[kernel] r11216 - in dists/trunk/linux-2.6/debian/patches: bugfix/all bugfix/arm features/all features/arm series
Maximilian Attems
maks at alioth.debian.org
Thu May 1 08:27:02 UTC 2008
Author: maks
Date: Thu May 1 08:26:37 2008
New Revision: 11216
Log:
update to 2.6.25-git17
* nuke bunch of merged patches
* mark at76 to fix
* comment newly conflicting m68k patches
Added:
dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-git17
- copied, changed from r11215, /dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-git9
Removed:
dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-git9
dists/trunk/linux-2.6/debian/patches/bugfix/all/rtc-x1205-new-style-conversion-checkpatch-fixes.patch
dists/trunk/linux-2.6/debian/patches/bugfix/all/rtc-x1205-new-style-conversion.patch
dists/trunk/linux-2.6/debian/patches/bugfix/arm/fix-ixp4xx_qmgr-used_sram_bitmap-corruption.patch
dists/trunk/linux-2.6/debian/patches/bugfix/arm/orion-enawrallo.patch
dists/trunk/linux-2.6/debian/patches/features/all/export-input-braille.patch
dists/trunk/linux-2.6/debian/patches/features/all/rtc-pcf8563-new-style-conversion.patch
dists/trunk/linux-2.6/debian/patches/features/arm/ixp4xx-net-drivers.patch
Modified:
dists/trunk/linux-2.6/debian/patches/series/1~experimental.1
dists/trunk/linux-2.6/debian/patches/series/1~experimental.1-extra
Copied: dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-git17 (from r11215, /dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-git9)
==============================================================================
--- /dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-git9 (original)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-git17 Thu May 1 08:26:37 2008
@@ -1,5 +1,5 @@
diff --git a/.gitignore b/.gitignore
-index fdcce40..3016ed3 100644
+index fdcce40..090b293 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,6 +27,7 @@ TAGS
@@ -10,6 +10,26 @@
Module.symvers
!.gitignore
+@@ -40,6 +41,7 @@ include/linux/autoconf.h
+ include/linux/compile.h
+ include/linux/version.h
+ include/linux/utsrelease.h
++include/linux/bounds.h
+
+ # stgit generated dirs
+ patches-*
+diff --git a/.mailmap b/.mailmap
+index ebf9bf8..7260842 100644
+--- a/.mailmap
++++ b/.mailmap
+@@ -88,6 +88,7 @@ Rudolf Marek <R.Marek at sh.cvut.cz>
+ Rui Saraiva <rmps at joel.ist.utl.pt>
+ Sachin P Sant <ssant at in.ibm.com>
+ Sam Ravnborg <sam at mars.ravnborg.org>
++S.ÃaÄlar Onur <caglar at pardus.org.tr>
+ Simon Kelley <simon at thekelleys.org.uk>
+ Stéphane Witzmann <stephane.witzmann at ubpmes.univ-bpclermont.fr>
+ Stephen Hemminger <shemminger at osdl.org>
diff --git a/CREDITS b/CREDITS
index da0a56e..8fec7b3 100644
--- a/CREDITS
@@ -361,6 +381,58 @@
+ 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-class-bdi b/Documentation/ABI/testing/sysfs-class-bdi
+new file mode 100644
+index 0000000..5ac1e01
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-class-bdi
+@@ -0,0 +1,46 @@
++What: /sys/class/bdi/<bdi>/
++Date: January 2008
++Contact: Peter Zijlstra <a.p.zijlstra at chello.nl>
++Description:
++
++Provide a place in sysfs for the backing_dev_info object. This allows
++setting and retrieving various BDI specific variables.
++
++The <bdi> identifier can be either of the following:
++
++MAJOR:MINOR
++
++ Device number for block devices, or value of st_dev on
++ non-block filesystems which provide their own BDI, such as NFS
++ and FUSE.
++
++default
++
++ The default backing dev, used for non-block device backed
++ filesystems which do not provide their own BDI.
++
++Files under /sys/class/bdi/<bdi>/
++---------------------------------
++
++read_ahead_kb (read-write)
++
++ Size of the read-ahead window in kilobytes
++
++min_ratio (read-write)
++
++ Under normal circumstances each device is given a part of the
++ total write-back cache that relates to its current average
++ writeout speed in relation to the other devices.
++
++ The 'min_ratio' parameter allows assigning a minimum
++ percentage of the write-back cache to a particular device.
++ For example, this is useful for providing a minimum QoS.
++
++max_ratio (read-write)
++
++ Allows limiting a particular device to use not more than the
++ given percentage of the write-back cache. This is useful in
++ situations where we want to avoid one device taking all or
++ most of the write-back cache. For example in case of an NFS
++ mount that is prone to get stuck, or a FUSE mount which cannot
++ be trusted to play fair.
diff --git a/Documentation/ABI/testing/sysfs-ibft b/Documentation/ABI/testing/sysfs-ibft
new file mode 100644
index 0000000..c2b7d11
@@ -485,8 +557,261 @@
+
+Users:
+ ocfs2-tools <ocfs2-tools-devel at oss.oracle.com>
+diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
+index b939ebb..80d1504 100644
+--- a/Documentation/DMA-API.txt
++++ b/Documentation/DMA-API.txt
+@@ -145,7 +145,7 @@ Part Ic - DMA addressing limitations
+ int
+ dma_supported(struct device *dev, u64 mask)
+ int
+-pci_dma_supported(struct device *dev, u64 mask)
++pci_dma_supported(struct pci_dev *hwdev, u64 mask)
+
+ Checks to see if the device can support DMA to the memory described by
+ mask.
+@@ -189,7 +189,7 @@ dma_addr_t
+ dma_map_single(struct device *dev, void *cpu_addr, size_t size,
+ enum dma_data_direction direction)
+ dma_addr_t
+-pci_map_single(struct device *dev, void *cpu_addr, size_t size,
++pci_map_single(struct pci_dev *hwdev, void *cpu_addr, size_t size,
+ int direction)
+
+ Maps a piece of processor virtual memory so it can be accessed by the
+@@ -395,6 +395,71 @@ Notes: You must do this:
+
+ See also dma_map_single().
+
++dma_addr_t
++dma_map_single_attrs(struct device *dev, void *cpu_addr, size_t size,
++ enum dma_data_direction dir,
++ struct dma_attrs *attrs)
++
++void
++dma_unmap_single_attrs(struct device *dev, dma_addr_t dma_addr,
++ size_t size, enum dma_data_direction dir,
++ struct dma_attrs *attrs)
++
++int
++dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
++ int nents, enum dma_data_direction dir,
++ struct dma_attrs *attrs)
++
++void
++dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl,
++ int nents, enum dma_data_direction dir,
++ struct dma_attrs *attrs)
++
++The four functions above are just like the counterpart functions
++without the _attrs suffixes, except that they pass an optional
++struct dma_attrs*.
++
++struct dma_attrs encapsulates a set of "dma attributes". For the
++definition of struct dma_attrs see linux/dma-attrs.h.
++
++The interpretation of dma attributes is architecture-specific, and
++each attribute should be documented in Documentation/DMA-attributes.txt.
++
++If struct dma_attrs* is NULL, the semantics of each of these
++functions is identical to those of the corresponding function
++without the _attrs suffix. As a result dma_map_single_attrs()
++can generally replace dma_map_single(), etc.
++
++As an example of the use of the *_attrs functions, here's how
++you could pass an attribute DMA_ATTR_FOO when mapping memory
++for DMA:
++
++#include <linux/dma-attrs.h>
++/* DMA_ATTR_FOO should be defined in linux/dma-attrs.h and
++ * documented in Documentation/DMA-attributes.txt */
++...
++
++ DEFINE_DMA_ATTRS(attrs);
++ dma_set_attr(DMA_ATTR_FOO, &attrs);
++ ....
++ n = dma_map_sg_attrs(dev, sg, nents, DMA_TO_DEVICE, &attr);
++ ....
++
++Architectures that care about DMA_ATTR_FOO would check for its
++presence in their implementations of the mapping and unmapping
++routines, e.g.:
++
++void whizco_dma_map_sg_attrs(struct device *dev, dma_addr_t dma_addr,
++ size_t size, enum dma_data_direction dir,
++ struct dma_attrs *attrs)
++{
++ ....
++ int foo = dma_get_attr(DMA_ATTR_FOO, attrs);
++ ....
++ if (foo)
++ /* twizzle the frobnozzle */
++ ....
++
+
+ Part II - Advanced dma_ usage
+ -----------------------------
+diff --git a/Documentation/DMA-attributes.txt b/Documentation/DMA-attributes.txt
+new file mode 100644
+index 0000000..6d772f8
+--- /dev/null
++++ b/Documentation/DMA-attributes.txt
+@@ -0,0 +1,24 @@
++ DMA attributes
++ ==============
++
++This document describes the semantics of the DMA attributes that are
++defined in linux/dma-attrs.h.
++
++DMA_ATTR_WRITE_BARRIER
++----------------------
++
++DMA_ATTR_WRITE_BARRIER is a (write) barrier attribute for DMA. DMA
++to a memory region with the DMA_ATTR_WRITE_BARRIER attribute forces
++all pending DMA writes to complete, and thus provides a mechanism to
++strictly order DMA from a device across all intervening busses and
++bridges. This barrier is not specific to a particular type of
++interconnect, it applies to the system as a whole, and so its
++implementation must account for the idiosyncracies of the system all
++the way from the DMA device to memory.
++
++As an example of a situation where DMA_ATTR_WRITE_BARRIER would be
++useful, suppose that a device does a DMA write to indicate that data is
++ready and available in memory. The DMA of the "completion indication"
++could race with data DMA. Mapping the memory used for completion
++indications with DMA_ATTR_WRITE_BARRIER would prevent the race.
++
+diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt
+index d84f89d..b463ecd 100644
+--- a/Documentation/DMA-mapping.txt
++++ b/Documentation/DMA-mapping.txt
+@@ -315,11 +315,11 @@ you should do:
+
+ dma_addr_t dma_handle;
+
+- cpu_addr = pci_alloc_consistent(dev, size, &dma_handle);
++ cpu_addr = pci_alloc_consistent(pdev, size, &dma_handle);
+
+-where dev is a struct pci_dev *. You should pass NULL for PCI like buses
+-where devices don't have struct pci_dev (like ISA, EISA). This may be
+-called in interrupt context.
++where pdev is a struct pci_dev *. This may be called in interrupt context.
++You should use dma_alloc_coherent (see DMA-API.txt) for buses
++where devices don't have struct pci_dev (like ISA, EISA).
+
+ This argument is needed because the DMA translations may be bus
+ specific (and often is private to the bus which the device is attached
+@@ -332,7 +332,7 @@ __get_free_pages (but takes size instead of a page order). If your
+ driver needs regions sized smaller than a page, you may prefer using
+ the pci_pool interface, described below.
+
+-The consistent DMA mapping interfaces, for non-NULL dev, will by
++The consistent DMA mapping interfaces, for non-NULL pdev, will by
+ default return a DMA address which is SAC (Single Address Cycle)
+ addressable. Even if the device indicates (via PCI dma mask) that it
+ may address the upper 32-bits and thus perform DAC cycles, consistent
+@@ -354,9 +354,9 @@ buffer you receive will not cross a 64K boundary.
+
+ To unmap and free such a DMA region, you call:
+
+- pci_free_consistent(dev, size, cpu_addr, dma_handle);
++ pci_free_consistent(pdev, size, cpu_addr, dma_handle);
+
+-where dev, size are the same as in the above call and cpu_addr and
++where pdev, size are the same as in the above call and cpu_addr and
+ dma_handle are the values pci_alloc_consistent returned to you.
+ This function may not be called in interrupt context.
+
+@@ -371,9 +371,9 @@ Create a pci_pool like this:
+
+ struct pci_pool *pool;
+
+- pool = pci_pool_create(name, dev, size, align, alloc);
++ pool = pci_pool_create(name, pdev, size, align, alloc);
+
+-The "name" is for diagnostics (like a kmem_cache name); dev and size
++The "name" is for diagnostics (like a kmem_cache name); pdev and size
+ are as above. The device's hardware alignment requirement for this
+ type of data is "align" (which is expressed in bytes, and must be a
+ power of two). If your device has no boundary crossing restrictions,
+@@ -472,11 +472,11 @@ To map a single region, you do:
+ void *addr = buffer->ptr;
+ size_t size = buffer->len;
+
+- dma_handle = pci_map_single(dev, addr, size, direction);
++ dma_handle = pci_map_single(pdev, addr, size, direction);
+
+ and to unmap it:
+
+- pci_unmap_single(dev, dma_handle, size, direction);
++ pci_unmap_single(pdev, dma_handle, size, direction);
+
+ You should call pci_unmap_single when the DMA activity is finished, e.g.
+ from the interrupt which told you that the DMA transfer is done.
+@@ -493,17 +493,17 @@ Specifically:
+ unsigned long offset = buffer->offset;
+ size_t size = buffer->len;
+
+- dma_handle = pci_map_page(dev, page, offset, size, direction);
++ dma_handle = pci_map_page(pdev, page, offset, size, direction);
+
+ ...
+
+- pci_unmap_page(dev, dma_handle, size, direction);
++ pci_unmap_page(pdev, dma_handle, size, direction);
+
+ Here, "offset" means byte offset within the given page.
+
+ With scatterlists, you map a region gathered from several regions by:
+
+- int i, count = pci_map_sg(dev, sglist, nents, direction);
++ int i, count = pci_map_sg(pdev, sglist, nents, direction);
+ struct scatterlist *sg;
+
+ for_each_sg(sglist, sg, count, i) {
+@@ -527,7 +527,7 @@ accessed sg->address and sg->length as shown above.
+
+ To unmap a scatterlist, just call:
+
+- pci_unmap_sg(dev, sglist, nents, direction);
++ pci_unmap_sg(pdev, sglist, nents, direction);
+
+ Again, make sure DMA activity has already finished.
+
+@@ -550,11 +550,11 @@ correct copy of the DMA buffer.
+ So, firstly, just map it with pci_map_{single,sg}, and after each DMA
+ transfer call either:
+
+- pci_dma_sync_single_for_cpu(dev, dma_handle, size, direction);
++ pci_dma_sync_single_for_cpu(pdev, dma_handle, size, direction);
+
+ or:
+
+- pci_dma_sync_sg_for_cpu(dev, sglist, nents, direction);
++ pci_dma_sync_sg_for_cpu(pdev, sglist, nents, direction);
+
+ as appropriate.
+
+@@ -562,7 +562,7 @@ Then, if you wish to let the device get at the DMA area again,
+ finish accessing the data with the cpu, and then before actually
+ giving the buffer to the hardware call either:
+
+- pci_dma_sync_single_for_device(dev, dma_handle, size, direction);
++ pci_dma_sync_single_for_device(pdev, dma_handle, size, direction);
+
+ or:
+
+@@ -739,7 +739,7 @@ failure can be determined by:
+
+ dma_addr_t dma_handle;
+
+- dma_handle = pci_map_single(dev, addr, size, direction);
++ dma_handle = pci_map_single(pdev, addr, size, direction);
+ if (pci_dma_mapping_error(dma_handle)) {
+ /*
+ * reduce current DMA mapping usage,
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
-index 300e170..83966e9 100644
+index 300e170..0eb0d02 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -9,9 +9,10 @@
@@ -498,7 +823,7 @@
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
++ mac80211.xml debugobjects.xml
###
# The build process is as follows (targets):
@@ -515,10 +840,416 @@
@( \
echo "<programlisting>"; \
expand --tabs=8 < $< | \
+diff --git a/Documentation/DocBook/debugobjects.tmpl b/Documentation/DocBook/debugobjects.tmpl
+new file mode 100644
+index 0000000..7f5f218
+--- /dev/null
++++ b/Documentation/DocBook/debugobjects.tmpl
+@@ -0,0 +1,391 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
++ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
++
++<book id="debug-objects-guide">
++ <bookinfo>
++ <title>Debug objects life time</title>
++
++ <authorgroup>
++ <author>
++ <firstname>Thomas</firstname>
++ <surname>Gleixner</surname>
++ <affiliation>
++ <address>
++ <email>tglx at linutronix.de</email>
++ </address>
++ </affiliation>
++ </author>
++ </authorgroup>
++
++ <copyright>
++ <year>2008</year>
++ <holder>Thomas Gleixner</holder>
++ </copyright>
++
++ <legalnotice>
++ <para>
++ This documentation is free software; you can redistribute
++ it and/or modify it under the terms of the GNU General Public
++ License version 2 as published by the Free Software Foundation.
++ </para>
++
++ <para>
++ This program is distributed in the hope that it will be
++ useful, but WITHOUT ANY WARRANTY; without even the implied
++ warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
++ See the GNU General Public License for more details.
++ </para>
++
++ <para>
++ You should have received a copy of the GNU General Public
++ License along with this program; if not, write to the Free
++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ MA 02111-1307 USA
++ </para>
++
++ <para>
++ For more details see the file COPYING in the source
++ distribution of Linux.
++ </para>
++ </legalnotice>
++ </bookinfo>
++
++<toc></toc>
++
++ <chapter id="intro">
++ <title>Introduction</title>
++ <para>
++ debugobjects is a generic infrastructure to track the life time
++ of kernel objects and validate the operations on those.
++ </para>
++ <para>
++ debugobjects is useful to check for the following error patterns:
++ <itemizedlist>
++ <listitem><para>Activation of uninitialized objects</para></listitem>
++ <listitem><para>Initialization of active objects</para></listitem>
++ <listitem><para>Usage of freed/destroyed objects</para></listitem>
++ </itemizedlist>
++ </para>
++ <para>
++ debugobjects is not changing the data structure of the real
++ object so it can be compiled in with a minimal runtime impact
++ and enabled on demand with a kernel command line option.
++ </para>
++ </chapter>
++
++ <chapter id="howto">
++ <title>Howto use debugobjects</title>
++ <para>
++ A kernel subsystem needs to provide a data structure which
++ describes the object type and add calls into the debug code at
++ appropriate places. The data structure to describe the object
++ type needs at minimum the name of the object type. Optional
++ functions can and should be provided to fixup detected problems
++ so the kernel can continue to work and the debug information can
++ be retrieved from a live system instead of hard core debugging
++ with serial consoles and stack trace transcripts from the
++ monitor.
++ </para>
++ <para>
++ The debug calls provided by debugobjects are:
++ <itemizedlist>
++ <listitem><para>debug_object_init</para></listitem>
++ <listitem><para>debug_object_init_on_stack</para></listitem>
++ <listitem><para>debug_object_activate</para></listitem>
++ <listitem><para>debug_object_deactivate</para></listitem>
++ <listitem><para>debug_object_destroy</para></listitem>
++ <listitem><para>debug_object_free</para></listitem>
++ </itemizedlist>
++ Each of these functions takes the address of the real object and
++ a pointer to the object type specific debug description
++ structure.
++ </para>
++ <para>
++ Each detected error is reported in the statistics and a limited
++ number of errors are printk'ed including a full stack trace.
++ </para>
++ <para>
++ The statistics are available via debugfs/debug_objects/stats.
++ They provide information about the number of warnings and the
++ number of successful fixups along with information about the
++ usage of the internal tracking objects and the state of the
++ internal tracking objects pool.
++ </para>
++ </chapter>
++ <chapter id="debugfunctions">
++ <title>Debug functions</title>
++ <sect1 id="prototypes">
++ <title>Debug object function reference</title>
++!Elib/debugobjects.c
++ </sect1>
++ <sect1 id="debug_object_init">
++ <title>debug_object_init</title>
++ <para>
++ This function is called whenever the initialization function
++ of a real object is called.
++ </para>
++ <para>
++ When the real object is already tracked by debugobjects it is
++ checked, whether the object can be initialized. Initializing
++ is not allowed for active and destroyed objects. When
++ debugobjects detects an error, then it calls the fixup_init
++ function of the object type description structure if provided
++ by the caller. The fixup function can correct the problem
++ before the real initialization of the object happens. E.g. it
++ can deactivate an active object in order to prevent damage to
++ the subsystem.
++ </para>
++ <para>
++ When the real object is not yet tracked by debugobjects,
++ debugobjects allocates a tracker object for the real object
++ and sets the tracker object state to ODEBUG_STATE_INIT. It
++ verifies that the object is not on the callers stack. If it is
++ on the callers stack then a limited number of warnings
++ including a full stack trace is printk'ed. The calling code
++ must use debug_object_init_on_stack() and remove the object
++ before leaving the function which allocated it. See next
++ section.
++ </para>
++ </sect1>
++
++ <sect1 id="debug_object_init_on_stack">
++ <title>debug_object_init_on_stack</title>
++ <para>
++ This function is called whenever the initialization function
++ of a real object which resides on the stack is called.
++ </para>
++ <para>
++ When the real object is already tracked by debugobjects it is
++ checked, whether the object can be initialized. Initializing
++ is not allowed for active and destroyed objects. When
++ debugobjects detects an error, then it calls the fixup_init
++ function of the object type description structure if provided
++ by the caller. The fixup function can correct the problem
++ before the real initialization of the object happens. E.g. it
++ can deactivate an active object in order to prevent damage to
++ the subsystem.
++ </para>
++ <para>
++ When the real object is not yet tracked by debugobjects
++ debugobjects allocates a tracker object for the real object
++ and sets the tracker object state to ODEBUG_STATE_INIT. It
++ verifies that the object is on the callers stack.
++ </para>
++ <para>
++ An object which is on the stack must be removed from the
++ tracker by calling debug_object_free() before the function
++ which allocates the object returns. Otherwise we keep track of
++ stale objects.
++ </para>
++ </sect1>
++
++ <sect1 id="debug_object_activate">
++ <title>debug_object_activate</title>
++ <para>
++ This function is called whenever the activation function of a
++ real object is called.
++ </para>
++ <para>
++ When the real object is already tracked by debugobjects it is
++ checked, whether the object can be activated. Activating is
++ not allowed for active and destroyed objects. When
++ debugobjects detects an error, then it calls the
++ fixup_activate function of the object type description
++ structure if provided by the caller. The fixup function can
++ correct the problem before the real activation of the object
++ happens. E.g. it can deactivate an active object in order to
++ prevent damage to the subsystem.
++ </para>
++ <para>
++ When the real object is not yet tracked by debugobjects then
++ the fixup_activate function is called if available. This is
++ necessary to allow the legitimate activation of statically
++ allocated and initialized objects. The fixup function checks
++ whether the object is valid and calls the debug_objects_init()
++ function to initialize the tracking of this object.
++ </para>
++ <para>
++ When the activation is legitimate, then the state of the
++ associated tracker object is set to ODEBUG_STATE_ACTIVE.
++ </para>
++ </sect1>
++
++ <sect1 id="debug_object_deactivate">
++ <title>debug_object_deactivate</title>
++ <para>
++ This function is called whenever the deactivation function of
++ a real object is called.
++ </para>
++ <para>
++ When the real object is tracked by debugobjects it is checked,
++ whether the object can be deactivated. Deactivating is not
++ allowed for untracked or destroyed objects.
++ </para>
++ <para>
++ When the deactivation is legitimate, then the state of the
++ associated tracker object is set to ODEBUG_STATE_INACTIVE.
++ </para>
++ </sect1>
++
++ <sect1 id="debug_object_destroy">
++ <title>debug_object_destroy</title>
++ <para>
++ This function is called to mark an object destroyed. This is
++ useful to prevent the usage of invalid objects, which are
++ still available in memory: either statically allocated objects
++ or objects which are freed later.
++ </para>
++ <para>
++ When the real object is tracked by debugobjects it is checked,
++ whether the object can be destroyed. Destruction is not
++ allowed for active and destroyed objects. When debugobjects
++ detects an error, then it calls the fixup_destroy function of
++ the object type description structure if provided by the
++ caller. The fixup function can correct the problem before the
++ real destruction of the object happens. E.g. it can deactivate
++ an active object in order to prevent damage to the subsystem.
++ </para>
++ <para>
++ When the destruction is legitimate, then the state of the
++ associated tracker object is set to ODEBUG_STATE_DESTROYED.
++ </para>
++ </sect1>
++
++ <sect1 id="debug_object_free">
++ <title>debug_object_free</title>
++ <para>
++ This function is called before an object is freed.
++ </para>
++ <para>
++ When the real object is tracked by debugobjects it is checked,
++ whether the object can be freed. Free is not allowed for
++ active objects. When debugobjects detects an error, then it
++ calls the fixup_free function of the object type description
++ structure if provided by the caller. The fixup function can
++ correct the problem before the real free of the object
++ happens. E.g. it can deactivate an active object in order to
++ prevent damage to the subsystem.
++ </para>
++ <para>
++ Note that debug_object_free removes the object from the
++ tracker. Later usage of the object is detected by the other
++ debug checks.
++ </para>
++ </sect1>
++ </chapter>
++ <chapter id="fixupfunctions">
++ <title>Fixup functions</title>
++ <sect1 id="debug_obj_descr">
++ <title>Debug object type description structure</title>
++!Iinclude/linux/debugobjects.h
++ </sect1>
++ <sect1 id="fixup_init">
++ <title>fixup_init</title>
++ <para>
++ This function is called from the debug code whenever a problem
++ in debug_object_init is detected. The function takes the
++ address of the object and the state which is currently
++ recorded in the tracker.
++ </para>
++ <para>
++ Called from debug_object_init when the object state is:
++ <itemizedlist>
++ <listitem><para>ODEBUG_STATE_ACTIVE</para></listitem>
++ </itemizedlist>
++ </para>
++ <para>
++ The function returns 1 when the fixup was successful,
++ otherwise 0. The return value is used to update the
++ statistics.
++ </para>
++ <para>
++ Note, that the function needs to call the debug_object_init()
++ function again, after the damage has been repaired in order to
++ keep the state consistent.
++ </para>
++ </sect1>
++
++ <sect1 id="fixup_activate">
++ <title>fixup_activate</title>
++ <para>
++ This function is called from the debug code whenever a problem
++ in debug_object_activate is detected.
++ </para>
++ <para>
++ Called from debug_object_activate when the object state is:
++ <itemizedlist>
++ <listitem><para>ODEBUG_STATE_NOTAVAILABLE</para></listitem>
++ <listitem><para>ODEBUG_STATE_ACTIVE</para></listitem>
++ </itemizedlist>
++ </para>
++ <para>
++ The function returns 1 when the fixup was successful,
++ otherwise 0. The return value is used to update the
++ statistics.
++ </para>
++ <para>
++ Note that the function needs to call the debug_object_activate()
++ function again after the damage has been repaired in order to
++ keep the state consistent.
++ </para>
++ <para>
++ The activation of statically initialized objects is a special
++ case. When debug_object_activate() has no tracked object for
++ this object address then fixup_activate() is called with
++ object state ODEBUG_STATE_NOTAVAILABLE. The fixup function
++ needs to check whether this is a legitimate case of a
++ statically initialized object or not. In case it is it calls
++ debug_object_init() and debug_object_activate() to make the
++ object known to the tracker and marked active. In this case
++ the function should return 0 because this is not a real fixup.
++ </para>
++ </sect1>
++
++ <sect1 id="fixup_destroy">
++ <title>fixup_destroy</title>
++ <para>
++ This function is called from the debug code whenever a problem
++ in debug_object_destroy is detected.
++ </para>
++ <para>
++ Called from debug_object_destroy when the object state is:
++ <itemizedlist>
++ <listitem><para>ODEBUG_STATE_ACTIVE</para></listitem>
++ </itemizedlist>
++ </para>
++ <para>
++ The function returns 1 when the fixup was successful,
++ otherwise 0. The return value is used to update the
++ statistics.
++ </para>
++ </sect1>
++ <sect1 id="fixup_free">
++ <title>fixup_free</title>
++ <para>
++ This function is called from the debug code whenever a problem
++ in debug_object_free is detected. Further it can be called
++ from the debug checks in kfree/vfree, when an active object is
++ detected from the debug_check_no_obj_freed() sanity checks.
++ </para>
++ <para>
++ Called from debug_object_free() or debug_check_no_obj_freed()
++ when the object state is:
++ <itemizedlist>
++ <listitem><para>ODEBUG_STATE_ACTIVE</para></listitem>
++ </itemizedlist>
++ </para>
++ <para>
++ The function returns 1 when the fixup was successful,
++ otherwise 0. The return value is used to update the
++ statistics.
++ </para>
++ </sect1>
++ </chapter>
++ <chapter id="bugs">
++ <title>Known Bugs And Assumptions</title>
++ <para>
++ None (knock on wood).
++ </para>
++ </chapter>
++</book>
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
-index dc0f30c..488dd4a 100644
+index dc0f30c..b7b1482 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
+@@ -119,7 +119,7 @@ X!Ilib/string.c
+ !Elib/string.c
+ </sect1>
+ <sect1><title>Bit Operations</title>
+-!Iinclude/asm-x86/bitops_32.h
++!Iinclude/asm-x86/bitops.h
+ </sect1>
+ </chapter>
+
@@ -297,11 +297,6 @@ X!Earch/x86/kernel/mca_32.c
!Ikernel/acct.c
</chapter>
@@ -531,6 +1262,65 @@
<chapter id="devdrivers">
<title>Device drivers infrastructure</title>
<sect1><title>Device Drivers Base</title>
+@@ -650,4 +645,58 @@ X!Idrivers/video/console/fonts.c
+ !Edrivers/i2c/i2c-core.c
+ </chapter>
+
++ <chapter id="clk">
++ <title>Clock Framework</title>
++
++ <para>
++ The clock framework defines programming interfaces to support
++ software management of the system clock tree.
++ This framework is widely used with System-On-Chip (SOC) platforms
++ to support power management and various devices which may need
++ custom clock rates.
++ Note that these "clocks" don't relate to timekeeping or real
++ time clocks (RTCs), each of which have separate frameworks.
++ These <structname>struct clk</structname> instances may be used
++ to manage for example a 96 MHz signal that is used to shift bits
++ into and out of peripherals or busses, or otherwise trigger
++ synchronous state machine transitions in system hardware.
++ </para>
++
++ <para>
++ Power management is supported by explicit software clock gating:
++ unused clocks are disabled, so the system doesn't waste power
++ changing the state of transistors that aren't in active use.
++ On some systems this may be backed by hardware clock gating,
++ where clocks are gated without being disabled in software.
++ Sections of chips that are powered but not clocked may be able
++ to retain their last state.
++ This low power state is often called a <emphasis>retention
++ mode</emphasis>.
++ This mode still incurs leakage currents, especially with finer
++ circuit geometries, but for CMOS circuits power is mostly used
++ by clocked state changes.
++ </para>
++
++ <para>
++ Power-aware drivers only enable their clocks when the device
++ they manage is in active use. Also, system sleep states often
++ differ according to which clock domains are active: while a
++ "standby" state may allow wakeup from several active domains, a
++ "mem" (suspend-to-RAM) state may require a more wholesale shutdown
++ of clocks derived from higher speed PLLs and oscillators, limiting
++ the number of possible wakeup event sources. A driver's suspend
++ method may need to be aware of system-specific clock constraints
++ on the target sleep state.
++ </para>
++
++ <para>
++ Some platforms support programmable clock generators. These
++ can be used by external chips of various kinds, such as other
++ CPUs, multimedia codecs, and devices with strict requirements
++ for interface clocking.
++ </para>
++
++!Iinclude/linux/clk.h
++ </chapter>
++
+ </book>
diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl
index 2e9d6b4..77c42f4 100644
--- a/Documentation/DocBook/kernel-locking.tmpl
@@ -1374,6 +2164,18 @@
+ </chapter>
+ </part>
+</book>
+diff --git a/Documentation/DocBook/rapidio.tmpl b/Documentation/DocBook/rapidio.tmpl
+index b9e143e..54eb26b 100644
+--- a/Documentation/DocBook/rapidio.tmpl
++++ b/Documentation/DocBook/rapidio.tmpl
+@@ -133,7 +133,6 @@
+ !Idrivers/rapidio/rio-sysfs.c
+ </sect1>
+ <sect1 id="PPC32_support"><title>PPC32 support</title>
+-!Iarch/powerpc/kernel/rio.c
+ !Earch/powerpc/sysdev/fsl_rio.c
+ !Iarch/powerpc/sysdev/fsl_rio.c
+ </sect1>
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
@@ -3359,6 +4161,46 @@
and passing the address to that lock to blk_init_queue().
+diff --git a/Documentation/braille-console.txt b/Documentation/braille-console.txt
+new file mode 100644
+index 0000000..000b0fb
+--- /dev/null
++++ b/Documentation/braille-console.txt
+@@ -0,0 +1,34 @@
++ Linux Braille Console
++
++To get early boot messages on a braille device (before userspace screen
++readers can start), you first need to compile the support for the usual serial
++console (see serial-console.txt), and for braille device (in Device Drivers -
++Accessibility).
++
++Then you need to specify a console=brl, option on the kernel command line, the
++format is:
++
++ console=brl,serial_options...
++
++where serial_options... are the same as described in serial-console.txt
++
++So for instance you can use console=brl,ttyS0 if the braille device is connected
++to the first serial port, and console=brl,ttyS0,115200 to override the baud rate
++to 115200, etc.
++
++By default, the braille device will just show the last kernel message (console
++mode). To review previous messages, press the Insert key to switch to the VT
++review mode. In review mode, the arrow keys permit to browse in the VT content,
++page up/down keys go at the top/bottom of the screen, and the home key goes back
++to the cursor, hence providing very basic screen reviewing facility.
++
++Sound feedback can be obtained by adding the braille_console.sound=1 kernel
++parameter.
++
++For simplicity, only one braille console can be enabled, other uses of
++console=brl,... will be discarded. Also note that it does not interfere with
++the console selection mecanism described in serial-console.txt
++
++For now, only the VisioBraille device is supported.
++
++Samuel Thibault <samuel.thibault at ens-lyon.org>
diff --git a/Documentation/cdrom/cdrom-standard.tex b/Documentation/cdrom/cdrom-standard.tex
index c713aeb..c06233f 100644
--- a/Documentation/cdrom/cdrom-standard.tex
@@ -3372,6 +4214,20 @@
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/cgroups.txt b/Documentation/cgroups.txt
+index 31d12e2..c298a66 100644
+--- a/Documentation/cgroups.txt
++++ b/Documentation/cgroups.txt
+@@ -500,8 +500,7 @@ post-attachment activity that requires memory allocations or blocking.
+
+ void fork(struct cgroup_subsy *ss, struct task_struct *task)
+
+-Called when a task is forked into a cgroup. Also called during
+-registration for all existing tasks.
++Called when a task is forked into a cgroup.
+
+ void exit(struct cgroup_subsys *ss, struct task_struct *task)
+
diff --git a/Documentation/cli-sti-removal.txt b/Documentation/cli-sti-removal.txt
index 0223c9d..60932b0 100644
--- a/Documentation/cli-sti-removal.txt
@@ -3385,8 +4241,281 @@
struct driver_data;
irq_handler (...)
+diff --git a/Documentation/controllers/devices.txt b/Documentation/controllers/devices.txt
+new file mode 100644
+index 0000000..4dcea42
+--- /dev/null
++++ b/Documentation/controllers/devices.txt
+@@ -0,0 +1,48 @@
++Device Whitelist Controller
++
++1. Description:
++
++Implement a cgroup to track and enforce open and mknod restrictions
++on device files. A device cgroup associates a device access
++whitelist with each cgroup. A whitelist entry has 4 fields.
++'type' is a (all), c (char), or b (block). 'all' means it applies
++to all types and all major and minor numbers. Major and minor are
++either an integer or * for all. Access is a composition of r
++(read), w (write), and m (mknod).
++
++The root device cgroup starts with rwm to 'all'. A child device
++cgroup gets a copy of the parent. Administrators can then remove
++devices from the whitelist or add new entries. A child cgroup can
++never receive a device access which is denied its parent. However
++when a device access is removed from a parent it will not also be
++removed from the child(ren).
++
++2. User Interface
++
++An entry is added using devices.allow, and removed using
++devices.deny. For instance
++
++ echo 'c 1:3 mr' > /cgroups/1/devices.allow
++
++allows cgroup 1 to read and mknod the device usually known as
++/dev/null. Doing
++
++ echo a > /cgroups/1/devices.deny
++
++will remove the default 'a *:* mrw' entry.
++
++3. Security
++
++Any task can move itself between cgroups. This clearly won't
++suffice, but we can decide the best way to adequately restrict
++movement as people get some experience with this. We may just want
++to require CAP_SYS_ADMIN, which at least is a separate bit from
++CAP_MKNOD. We may want to just refuse moving to a cgroup which
++isn't a descendent of the current one. Or we may want to use
++CAP_MAC_ADMIN, since we really are trying to lock down root.
++
++CAP_SYS_ADMIN is needed to modify the whitelist or move another
++task to a new cgroup. (Again we'll probably want to change that).
++
++A cgroup may not be granted more permissions than the cgroup's
++parent has.
+diff --git a/Documentation/controllers/resource_counter.txt b/Documentation/controllers/resource_counter.txt
+new file mode 100644
+index 0000000..f196ac1
+--- /dev/null
++++ b/Documentation/controllers/resource_counter.txt
+@@ -0,0 +1,181 @@
++
++ The Resource Counter
++
++The resource counter, declared at include/linux/res_counter.h,
++is supposed to facilitate the resource management by controllers
++by providing common stuff for accounting.
++
++This "stuff" includes the res_counter structure and routines
++to work with it.
++
++
++
++1. Crucial parts of the res_counter structure
++
++ a. unsigned long long usage
++
++ The usage value shows the amount of a resource that is consumed
++ by a group at a given time. The units of measurement should be
++ determined by the controller that uses this counter. E.g. it can
++ be bytes, items or any other unit the controller operates on.
++
++ b. unsigned long long max_usage
++
++ The maximal value of the usage over time.
++
++ This value is useful when gathering statistical information about
++ the particular group, as it shows the actual resource requirements
++ for a particular group, not just some usage snapshot.
++
++ c. unsigned long long limit
++
++ The maximal allowed amount of resource to consume by the group. In
++ case the group requests for more resources, so that the usage value
++ would exceed the limit, the resource allocation is rejected (see
++ the next section).
++
++ d. unsigned long long failcnt
++
++ The failcnt stands for "failures counter". This is the number of
++ resource allocation attempts that failed.
++
++ c. spinlock_t lock
++
++ Protects changes of the above values.
++
++
++
++2. Basic accounting routines
++
++ a. void res_counter_init(struct res_counter *rc)
++
++ Initializes the resource counter. As usual, should be the first
++ routine called for a new counter.
++
++ b. int res_counter_charge[_locked]
++ (struct res_counter *rc, unsigned long val)
++
++ When a resource is about to be allocated it has to be accounted
++ with the appropriate resource counter (controller should determine
++ which one to use on its own). This operation is called "charging".
++
++ This is not very important which operation - resource allocation
++ or charging - is performed first, but
++ * if the allocation is performed first, this may create a
++ temporary resource over-usage by the time resource counter is
++ charged;
++ * if the charging is performed first, then it should be uncharged
++ on error path (if the one is called).
++
++ c. void res_counter_uncharge[_locked]
++ (struct res_counter *rc, unsigned long val)
++
++ When a resource is released (freed) it should be de-accounted
++ from the resource counter it was accounted to. This is called
++ "uncharging".
++
++ The _locked routines imply that the res_counter->lock is taken.
++
++
++ 2.1 Other accounting routines
++
++ There are more routines that may help you with common needs, like
++ checking whether the limit is reached or resetting the max_usage
++ value. They are all declared in include/linux/res_counter.h.
++
++
++
++3. Analyzing the resource counter registrations
++
++ a. If the failcnt value constantly grows, this means that the counter's
++ limit is too tight. Either the group is misbehaving and consumes too
++ many resources, or the configuration is not suitable for the group
++ and the limit should be increased.
++
++ b. The max_usage value can be used to quickly tune the group. One may
++ set the limits to maximal values and either load the container with
++ a common pattern or leave one for a while. After this the max_usage
++ value shows the amount of memory the container would require during
++ its common activity.
++
++ Setting the limit a bit above this value gives a pretty good
++ configuration that works in most of the cases.
++
++ c. If the max_usage is much less than the limit, but the failcnt value
++ is growing, then the group tries to allocate a big chunk of resource
++ at once.
++
++ d. If the max_usage is much less than the limit, but the failcnt value
++ is 0, then this group is given too high limit, that it does not
++ require. It is better to lower the limit a bit leaving more resource
++ for other groups.
++
++
++
++4. Communication with the control groups subsystem (cgroups)
++
++All the resource controllers that are using cgroups and resource counters
++should provide files (in the cgroup filesystem) to work with the resource
++counter fields. They are recommended to adhere to the following rules:
++
++ a. File names
++
++ Field name File name
++ ---------------------------------------------------
++ usage usage_in_<unit_of_measurement>
++ max_usage max_usage_in_<unit_of_measurement>
++ limit limit_in_<unit_of_measurement>
++ failcnt failcnt
++ lock no file :)
++
++ b. Reading from file should show the corresponding field value in the
++ appropriate format.
++
++ c. Writing to file
++
++ Field Expected behavior
++ ----------------------------------
++ usage prohibited
++ max_usage reset to usage
++ limit set the limit
++ failcnt reset to zero
++
++
++
++5. Usage example
++
++ a. Declare a task group (take a look at cgroups subsystem for this) and
++ fold a res_counter into it
++
++ struct my_group {
++ struct res_counter res;
++
++ <other fields>
++ }
++
++ b. Put hooks in resource allocation/release paths
++
++ int alloc_something(...)
++ {
++ if (res_counter_charge(res_counter_ptr, amount) < 0)
++ return -ENOMEM;
++
++ <allocate the resource and return to the caller>
++ }
++
++ void release_something(...)
++ {
++ res_counter_uncharge(res_counter_ptr, amount);
++
++ <release the resource>
++ }
++
++ In order to keep the usage value self-consistent, both the
++ "res_counter_ptr" and the "amount" in release_something() should be
++ the same as they were in the alloc_something() when the releasing
++ resource was allocated.
++
++ c. Provide the way to read res_counter values and set them (the cgroups
++ still can help with it).
++
++ c. Compile and run :)
+diff --git a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt
+index af3b925..6c442d8 100644
+--- a/Documentation/cpu-freq/user-guide.txt
++++ b/Documentation/cpu-freq/user-guide.txt
+@@ -154,6 +154,11 @@ scaling_governor, and by "echoing" the name of another
+ that some governors won't load - they only
+ work on some specific architectures or
+ processors.
++
++cpuinfo_cur_freq : Current speed of the CPU, in KHz.
++
++scaling_available_frequencies : List of available frequencies, in KHz.
++
+ scaling_min_freq and
+ scaling_max_freq show the current "policy limits" (in
+ kHz). By echoing new values into these
+@@ -162,6 +167,15 @@ scaling_max_freq show the current "policy limits" (in
+ first set scaling_max_freq, then
+ scaling_min_freq.
+
++affected_cpus : List of CPUs that require software coordination
++ of frequency.
++
++related_cpus : List of CPUs that need some sort of frequency
++ coordination, whether software or hardware.
++
++scaling_driver : Hardware driver for cpufreq.
++
++scaling_cur_freq : Current frequency of the CPU, in KHz.
+
+ If you have selected the "userspace" governor which allows you to
+ set the CPU operating frequency to a specific value, you can read out
diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt
-index ad2bb3b..aa854b9 100644
+index ad2bb3b..fb7b361 100644
--- a/Documentation/cpusets.txt
+++ b/Documentation/cpusets.txt
@@ -8,6 +8,7 @@ Portions Copyright (c) 2004-2006 Silicon Graphics, Inc.
@@ -3407,7 +4536,45 @@
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
+@@ -169,6 +171,7 @@ files describing that cpuset:
+ - memory_migrate flag: if set, move pages to cpusets nodes
+ - cpu_exclusive flag: is cpu placement exclusive?
+ - mem_exclusive flag: is memory placement exclusive?
++ - mem_hardwall flag: is memory allocation hardwalled
+ - memory_pressure: measure of how much paging pressure in cpuset
+
+ In addition, the root cpuset only has the following file:
+@@ -220,17 +223,18 @@ If a cpuset is cpu or mem exclusive, no other cpuset, other than
+ a direct ancestor or descendent, may share any of the same CPUs or
+ Memory Nodes.
+
+-A cpuset that is mem_exclusive restricts kernel allocations for
+-page, buffer and other data commonly shared by the kernel across
+-multiple users. All cpusets, whether mem_exclusive or not, restrict
+-allocations of memory for user space. This enables configuring a
+-system so that several independent jobs can share common kernel data,
+-such as file system pages, while isolating each jobs user allocation in
+-its own cpuset. To do this, construct a large mem_exclusive cpuset to
+-hold all the jobs, and construct child, non-mem_exclusive cpusets for
+-each individual job. Only a small amount of typical kernel memory,
+-such as requests from interrupt handlers, is allowed to be taken
+-outside even a mem_exclusive cpuset.
++A cpuset that is mem_exclusive *or* mem_hardwall is "hardwalled",
++i.e. it restricts kernel allocations for page, buffer and other data
++commonly shared by the kernel across multiple users. All cpusets,
++whether hardwalled or not, restrict allocations of memory for user
++space. This enables configuring a system so that several independent
++jobs can share common kernel data, such as file system pages, while
++isolating each job's user allocation in its own cpuset. To do this,
++construct a large mem_exclusive cpuset to hold all the jobs, and
++construct child, non-mem_exclusive cpusets for each individual job.
++Only a small amount of typical kernel memory, such as requests from
++interrupt handlers, is allowed to be taken outside even a
++mem_exclusive cpuset.
+
+
+ 1.5 What is memory_pressure ?
+@@ -497,7 +501,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.
@@ -3482,6 +4649,15 @@
--------------------------
In order to minimize the impact of cpusets on critical kernel
+@@ -639,7 +709,7 @@ Now you want to do something with this cpuset.
+
+ In this directory you can find several files:
+ # ls
+-cpus cpu_exclusive mems mem_exclusive tasks
++cpus cpu_exclusive mems mem_exclusive mem_hardwall tasks
+
+ Reading them will give you information about the state of this cpuset:
+ the CPUs and Memory Nodes it can use, the processes that are using
diff --git a/Documentation/debugging-via-ohci1394.txt b/Documentation/debugging-via-ohci1394.txt
index c360d4e..59a91e5 100644
--- a/Documentation/debugging-via-ohci1394.txt
@@ -3571,7 +4747,7 @@
+cryptsetup luksOpen $1 crypt1
+]]
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
-index c09a96b..354aec0 100644
+index c09a96b..881e6dd 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -47,7 +47,6 @@
@@ -3582,6 +4758,22 @@
COPYING
CREDITS
CVS
+@@ -142,6 +141,7 @@ mkprep
+ mktables
+ mktree
+ modpost
++modules.order
+ modversions.h*
+ offset.h
+ offsets.h
+@@ -172,6 +172,7 @@ sm_tbl*
+ split-include
+ tags
+ tftpboot.img
++timeconst.h
+ times.h*
+ tkparse
+ trix_boot.h
diff --git a/Documentation/early-userspace/README b/Documentation/early-userspace/README
index 766d320..e35d830 100644
--- a/Documentation/early-userspace/README
@@ -3597,11 +4789,238 @@
The standalone klibc distribution currently provides three components,
in addition to the klibc library:
+diff --git a/Documentation/fb/gxfb.txt b/Documentation/fb/gxfb.txt
+new file mode 100644
+index 0000000..2f64090
+--- /dev/null
++++ b/Documentation/fb/gxfb.txt
+@@ -0,0 +1,52 @@
++[This file is cloned from VesaFB/aty128fb]
++
++What is gxfb?
++=================
++
++This is a graphics framebuffer driver for AMD Geode GX2 based processors.
++
++Advantages:
++
++ * No need to use AMD's VSA code (or other VESA emulation layer) in the
++ BIOS.
++ * It provides a nice large console (128 cols + 48 lines with 1024x768)
++ without using tiny, unreadable fonts.
++ * You can run XF68_FBDev on top of /dev/fb0
++ * Most important: boot logo :-)
++
++Disadvantages:
++
++ * graphic mode is slower than text mode...
++
++
++How to use it?
++==============
++
++Switching modes is done using gxfb.mode_option=<resolution>... boot
++parameter or using `fbset' program.
++
++See Documentation/fb/modedb.txt for more information on modedb
++resolutions.
++
++
++X11
++===
++
++XF68_FBDev should generally work fine, but it is non-accelerated.
++
++
++Configuration
++=============
++
++You can pass kernel command line options to gxfb with gxfb.<option>.
++For example, gxfb.mode_option=800x600 at 75.
++Accepted options:
++
++mode_option - specify the video mode. Of the form
++ <x>x<y>[-<bpp>][@<refresh>]
++vram - size of video ram (normally auto-detected)
++vt_switch - enable vt switching during suspend/resume. The vt
++ switch is slow, but harmless.
++
++--
++Andres Salomon <dilinger at debian.org>
+diff --git a/Documentation/fb/intelfb.txt b/Documentation/fb/intelfb.txt
+index da5ee74..27a3160 100644
+--- a/Documentation/fb/intelfb.txt
++++ b/Documentation/fb/intelfb.txt
+@@ -14,6 +14,8 @@ graphics devices. These would include:
+ Intel 915GM
+ Intel 945G
+ Intel 945GM
++ Intel 965G
++ Intel 965GM
+
+ B. List of available options
+
+diff --git a/Documentation/fb/lxfb.txt b/Documentation/fb/lxfb.txt
+new file mode 100644
+index 0000000..38b3ca6
+--- /dev/null
++++ b/Documentation/fb/lxfb.txt
+@@ -0,0 +1,52 @@
++[This file is cloned from VesaFB/aty128fb]
++
++What is lxfb?
++=================
++
++This is a graphics framebuffer driver for AMD Geode LX based processors.
++
++Advantages:
++
++ * No need to use AMD's VSA code (or other VESA emulation layer) in the
++ BIOS.
++ * It provides a nice large console (128 cols + 48 lines with 1024x768)
++ without using tiny, unreadable fonts.
++ * You can run XF68_FBDev on top of /dev/fb0
++ * Most important: boot logo :-)
++
++Disadvantages:
++
++ * graphic mode is slower than text mode...
++
++
++How to use it?
++==============
++
++Switching modes is done using lxfb.mode_option=<resolution>... boot
++parameter or using `fbset' program.
++
++See Documentation/fb/modedb.txt for more information on modedb
++resolutions.
++
++
++X11
++===
++
++XF68_FBDev should generally work fine, but it is non-accelerated.
++
++
++Configuration
++=============
++
++You can pass kernel command line options to lxfb with lxfb.<option>.
++For example, lxfb.mode_option=800x600 at 75.
++Accepted options:
++
++mode_option - specify the video mode. Of the form
++ <x>x<y>[-<bpp>][@<refresh>]
++vram - size of video ram (normally auto-detected)
++vt_switch - enable vt switching during suspend/resume. The vt
++ switch is slow, but harmless.
++
++--
++Andres Salomon <dilinger at debian.org>
+diff --git a/Documentation/fb/metronomefb.txt b/Documentation/fb/metronomefb.txt
+index b9a2e7b..237ca41 100644
+--- a/Documentation/fb/metronomefb.txt
++++ b/Documentation/fb/metronomefb.txt
+@@ -1,7 +1,7 @@
+ Metronomefb
+ -----------
+ Maintained by Jaya Kumar <jayakumar.lkml.gmail.com>
+-Last revised: Nov 20, 2007
++Last revised: Mar 10, 2008
+
+ Metronomefb is a driver for the Metronome display controller. The controller
+ is from E-Ink Corporation. It is intended to be used to drive the E-Ink
+@@ -11,20 +11,18 @@ display media here http://www.e-ink.com/products/matrix/metronome.html .
+ Metronome is interfaced to the host CPU through the AMLCD interface. The
+ host CPU generates the control information and the image in a framebuffer
+ which is then delivered to the AMLCD interface by a host specific method.
+-Currently, that's implemented for the PXA's LCDC controller. The display and
+-error status are each pulled through individual GPIOs.
++The display and error status are each pulled through individual GPIOs.
+
+-Metronomefb was written for the PXA255/gumstix/lyre combination and
+-therefore currently has board set specific code in it. If other boards based on
+-other architectures are available, then the host specific code can be separated
+-and abstracted out.
++Metronomefb is platform independent and depends on a board specific driver
++to do all physical IO work. Currently, an example is implemented for the
++PXA board used in the AM-200 EPD devkit. This example is am200epd.c
+
+ Metronomefb requires waveform information which is delivered via the AMLCD
+ interface to the metronome controller. The waveform information is expected to
+ be delivered from userspace via the firmware class interface. The waveform file
+ can be compressed as long as your udev or hotplug script is aware of the need
+-to uncompress it before delivering it. metronomefb will ask for waveform.wbf
+-which would typically go into /lib/firmware/waveform.wbf depending on your
++to uncompress it before delivering it. metronomefb will ask for metronome.wbf
++which would typically go into /lib/firmware/metronome.wbf depending on your
+ udev/hotplug setup. I have only tested with a single waveform file which was
+ originally labeled 23P01201_60_WT0107_MTC. I do not know what it stands for.
+ Caution should be exercised when manipulating the waveform as there may be
+diff --git a/Documentation/fb/modedb.txt b/Documentation/fb/modedb.txt
+index 4fcdb4c..ec4dee7 100644
+--- a/Documentation/fb/modedb.txt
++++ b/Documentation/fb/modedb.txt
+@@ -125,8 +125,12 @@ There may be more modes.
+ amifb - Amiga chipset frame buffer
+ aty128fb - ATI Rage128 / Pro frame buffer
+ atyfb - ATI Mach64 frame buffer
++ pm2fb - Permedia 2/2V frame buffer
++ pm3fb - Permedia 3 frame buffer
++ sstfb - Voodoo 1/2 (SST1) chipset frame buffer
+ tdfxfb - 3D Fx frame buffer
+ tridentfb - Trident (Cyber)blade chipset frame buffer
++ vt8623fb - VIA 8623 frame buffer
+
+ BTW, only a few drivers use this at the moment. Others are to follow
+ (feel free to send patches).
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
-index bf0e3df..448729f 100644
+index bf0e3df..3c35d45 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
-@@ -203,16 +203,8 @@ Who: linuxppc-dev at ozlabs.org
+@@ -128,15 +128,6 @@ Who: Arjan van de Ven <arjan at linux.intel.com>
+
+ ---------------------------
+
+-What: vm_ops.nopage
+-When: Soon, provided in-kernel callers have been converted
+-Why: This interface is replaced by vm_ops.fault, but it has been around
+- forever, is used by a lot of drivers, and doesn't cost much to
+- maintain.
+-Who: Nick Piggin <npiggin at suse.de>
+-
+----------------------------
+-
+ What: PHYSDEVPATH, PHYSDEVBUS, PHYSDEVDRIVER in the uevent environment
+ When: October 2008
+ Why: The stacking of class devices makes these values misleading and
+@@ -147,6 +138,24 @@ Who: Kay Sievers <kay.sievers at suse.de>
+
+ ---------------------------
+
++What: find_task_by_pid
++When: 2.6.26
++Why: With pid namespaces, calling this funciton will return the
++ wrong task when called from inside a namespace.
++
++ The best way to save a task pid and find a task by this
++ pid later, is to find this task's struct pid pointer (or get
++ it directly from the task) and call pid_task() later.
++
++ If someone really needs to get a task by its pid_t, then
++ he most likely needs the find_task_by_vpid() to get the
++ task from the same namespace as the current task is in, but
++ this may be not so in general.
++
++Who: Pavel Emelyanov <xemul at openvz.org>
++
++---------------------------
++
+ What: ACPI procfs interface
+ When: July 2008
+ Why: ACPI sysfs conversion should be finished by January 2008.
+@@ -203,16 +212,8 @@ Who: linuxppc-dev at ozlabs.org
---------------------------
@@ -3619,7 +5038,7 @@
Why: The i386/x86_64 merge provides a symlink to the old bzImage
location so not yet updated user space tools, e.g. package
-@@ -221,8 +213,6 @@ Who: Thomas Gleixner <tglx at linutronix.de>
+@@ -221,8 +222,6 @@ Who: Thomas Gleixner <tglx at linutronix.de>
---------------------------
@@ -3628,7 +5047,7 @@
What: i2c-i810, i2c-prosavage and i2c-savage4
When: May 2008
Why: These drivers are superseded by i810fb, intelfb and savagefb.
-@@ -230,33 +220,6 @@ Who: Jean Delvare <khali at linux-fr.org>
+@@ -230,33 +229,6 @@ Who: Jean Delvare <khali at linux-fr.org>
---------------------------
@@ -3662,7 +5081,7 @@
What (Why):
- include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files
(superseded by xt_TOS/xt_tos target & match)
-@@ -298,17 +261,6 @@ Who: Michael Buesch <mb at bu3sch.de>
+@@ -298,17 +270,6 @@ Who: Michael Buesch <mb at bu3sch.de>
---------------------------
@@ -3680,7 +5099,7 @@
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
+@@ -318,3 +279,28 @@ Why: Not used in-tree. The current out-of-tree users used it to
code / infrastructure should be in the kernel and not in some
out-of-tree driver.
Who: Thomas Gleixner <tglx at linutronix.de>
@@ -3709,6 +5128,31 @@
+Why: Implementation became generic; users should now include
+ linux/semaphore.h instead.
+Who: Matthew Wilcox <willy at linux.intel.com>
+diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
+index 42d4b30..c2992bc 100644
+--- a/Documentation/filesystems/Locking
++++ b/Documentation/filesystems/Locking
+@@ -511,7 +511,6 @@ prototypes:
+ void (*open)(struct vm_area_struct*);
+ void (*close)(struct vm_area_struct*);
+ int (*fault)(struct vm_area_struct*, struct vm_fault *);
+- struct page *(*nopage)(struct vm_area_struct*, unsigned long, int *);
+ int (*page_mkwrite)(struct vm_area_struct *, struct page *);
+
+ locking rules:
+@@ -519,7 +518,6 @@ locking rules:
+ open: no yes
+ close: no yes
+ fault: no yes
+-nopage: no yes
+ page_mkwrite: no yes no
+
+ ->page_mkwrite() is called when a previously read-only page is
+@@ -537,4 +535,3 @@ NULL.
+
+ ipc/shm.c::shm_delete() - may need BKL.
+ ->read() and ->write() in many drivers are (probably) missing BKL.
+-drivers/sgi/char/graphics.c::sgi_graphics_nopage() - may need BKL.
diff --git a/Documentation/filesystems/nfs-rdma.txt b/Documentation/filesystems/nfs-rdma.txt
new file mode 100644
index 0000000..d0ec45a
@@ -3972,7 +5416,7 @@
+
+ Congratulations! You're using NFS/RDMA!
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
-index 518ebe6..2a99116 100644
+index 518ebe6..dbc3c6a 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -43,6 +43,7 @@ Table of Contents
@@ -3983,7 +5427,54 @@
------------------------------------------------------------------------------
Preface
-@@ -2348,4 +2349,41 @@ For example:
+@@ -462,11 +463,17 @@ SwapTotal: 0 kB
+ SwapFree: 0 kB
+ Dirty: 968 kB
+ Writeback: 0 kB
++AnonPages: 861800 kB
+ Mapped: 280372 kB
+-Slab: 684068 kB
++Slab: 284364 kB
++SReclaimable: 159856 kB
++SUnreclaim: 124508 kB
++PageTables: 24448 kB
++NFS_Unstable: 0 kB
++Bounce: 0 kB
++WritebackTmp: 0 kB
+ CommitLimit: 7669796 kB
+ Committed_AS: 100056 kB
+-PageTables: 24448 kB
+ VmallocTotal: 112216 kB
+ VmallocUsed: 428 kB
+ VmallocChunk: 111088 kB
+@@ -502,8 +509,17 @@ VmallocChunk: 111088 kB
+ on the disk
+ Dirty: Memory which is waiting to get written back to the disk
+ Writeback: Memory which is actively being written back to the disk
++ AnonPages: Non-file backed pages mapped into userspace page tables
+ Mapped: files which have been mmaped, such as libraries
+ Slab: in-kernel data structures cache
++SReclaimable: Part of Slab, that might be reclaimed, such as caches
++ SUnreclaim: Part of Slab, that cannot be reclaimed on memory pressure
++ PageTables: amount of memory dedicated to the lowest level of page
++ tables.
++NFS_Unstable: NFS pages sent to the server, but not yet committed to stable
++ storage
++ Bounce: Memory used for block device "bounce buffers"
++WritebackTmp: Memory used by FUSE for temporary writeback buffers
+ CommitLimit: Based on the overcommit ratio ('vm.overcommit_ratio'),
+ this is the total amount of memory currently available to
+ be allocated on the system. This limit is only adhered to
+@@ -530,8 +546,6 @@ Committed_AS: The amount of memory presently allocated on the system.
+ above) will not be permitted. This is useful if one needs
+ to guarantee that processes will not fail due to lack of
+ memory once that memory has been successfully allocated.
+- PageTables: amount of memory dedicated to the lowest level of page
+- tables.
+ VmallocTotal: total size of vmalloc memory area
+ VmallocUsed: amount of vmalloc area which is used
+ VmallocChunk: largest contigious block of vmalloc area which is free
+@@ -2348,4 +2362,41 @@ For example:
$ echo 0x7 > /proc/self/coredump_filter
$ ./some_program
@@ -4100,6 +5591,55 @@
- The buffer will always be PAGE_SIZE bytes in length. On i386, this
is 4096.
+diff --git a/Documentation/filesystems/tmpfs.txt b/Documentation/filesystems/tmpfs.txt
+index 145e440..222437e 100644
+--- a/Documentation/filesystems/tmpfs.txt
++++ b/Documentation/filesystems/tmpfs.txt
+@@ -92,6 +92,18 @@ NodeList format is a comma-separated list of decimal numbers and ranges,
+ a range being two hyphen-separated decimal numbers, the smallest and
+ largest node numbers in the range. For example, mpol=bind:0-3,5,7,9-15
+
++NUMA memory allocation policies have optional flags that can be used in
++conjunction with their modes. These optional flags can be specified
++when tmpfs is mounted by appending them to the mode before the NodeList.
++See Documentation/vm/numa_memory_policy.txt for a list of all available
++memory allocation policy mode flags.
++
++ =static is equivalent to MPOL_F_STATIC_NODES
++ =relative is equivalent to MPOL_F_RELATIVE_NODES
++
++For example, mpol=bind=static:NodeList, is the equivalent of an
++allocation policy of MPOL_BIND | MPOL_F_STATIC_NODES.
++
+ Note that trying to mount a tmpfs with an mpol option will fail if the
+ running kernel does not support NUMA; and will fail if its nodelist
+ specifies a node which is not online. If your system relies on that
+diff --git a/Documentation/filesystems/vfat.txt b/Documentation/filesystems/vfat.txt
+index fcc123f..2d5e1e5 100644
+--- a/Documentation/filesystems/vfat.txt
++++ b/Documentation/filesystems/vfat.txt
+@@ -17,6 +17,21 @@ dmask=### -- The permission mask for the directory.
+ fmask=### -- The permission mask for files.
+ The default is the umask of current process.
+
++allow_utime=### -- This option controls the permission check of mtime/atime.
++
++ 20 - If current process is in group of file's group ID,
++ you can change timestamp.
++ 2 - Other users can change timestamp.
++
++ The default is set from `dmask' option. (If the directory is
++ writable, utime(2) is also allowed. I.e. ~dmask & 022)
++
++ Normally utime(2) checks current process is owner of
++ the file, or it has CAP_FOWNER capability. But FAT
++ filesystem doesn't have uid/gid on disk, so normal
++ check is too unflexible. With this option you can
++ relax it.
++
+ codepage=### -- Sets the codepage number for converting to shortname
+ characters on FAT filesystem.
+ By default, FAT_DEFAULT_CODEPAGE setting is used.
diff --git a/Documentation/filesystems/xfs.txt b/Documentation/filesystems/xfs.txt
index 74aeb14..0a1668b 100644
--- a/Documentation/filesystems/xfs.txt
@@ -4462,6 +6002,27 @@
-module_init(firmware_sample_init);
-module_exit(firmware_sample_exit);
-
+diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt
+index 5463009..c35ca9e 100644
+--- a/Documentation/gpio.txt
++++ b/Documentation/gpio.txt
+@@ -107,6 +107,16 @@ type of GPIO controller, and on one particular board 80-95 with an FPGA.
+ The numbers need not be contiguous; either of those platforms could also
+ use numbers 2000-2063 to identify GPIOs in a bank of I2C GPIO expanders.
+
++If you want to initialize a structure with an invalid GPIO number, use
++some negative number (perhaps "-EINVAL"); that will never be valid. To
++test if a number could reference a GPIO, you may use this predicate:
++
++ int gpio_is_valid(int number);
++
++A number that's not valid will be rejected by calls which may request
++or free GPIOs (see below). Other numbers may also be rejected; for
++example, a number might be valid but unused on a given board.
++
+ Whether a platform supports multiple GPIO controllers is currently a
+ platform-specific implementation issue.
+
diff --git a/Documentation/highuid.txt b/Documentation/highuid.txt
index 76034d9..6bad6f1 100644
--- a/Documentation/highuid.txt
@@ -4993,20 +6554,56 @@
-code got a healthy amount of testing and use in practice.
-
- Thomas Gleixner, Ingo Molnar
+diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
+index bfb0a55..ee75cba 100644
+--- a/Documentation/i2c/writing-clients
++++ b/Documentation/i2c/writing-clients
+@@ -164,7 +164,8 @@ I2C device drivers using this binding model work just like any other
+ kind of driver in Linux: they provide a probe() method to bind to
+ those devices, and a remove() method to unbind.
+
+- static int foo_probe(struct i2c_client *client);
++ static int foo_probe(struct i2c_client *client,
++ const struct i2c_device_id *id);
+ static int foo_remove(struct i2c_client *client);
+
+ Remember that the i2c_driver does not create those client handles. The
diff --git a/Documentation/i386/boot.txt b/Documentation/i386/boot.txt
-index fc49b79..2eb1610 100644
+index fc49b79..95ad15c 100644
--- a/Documentation/i386/boot.txt
+++ b/Documentation/i386/boot.txt
-@@ -170,6 +170,8 @@ Offset Proto Name Meaning
+@@ -40,8 +40,18 @@ Protocol 2.05: (Kernel 2.6.20) Make protected mode kernel relocatable.
+ Introduce relocatable_kernel and kernel_alignment fields.
+
+ Protocol 2.06: (Kernel 2.6.22) Added a field that contains the size of
+- the boot command line
++ the boot command line.
+
++Protocol 2.07: (Kernel 2.6.24) Added paravirtualised boot protocol.
++ Introduced hardware_subarch and hardware_subarch_data
++ and KEEP_SEGMENTS flag in load_flags.
++
++Protocol 2.08: (Kernel 2.6.26) Added crc32 checksum and ELF format
++ payload. Introduced payload_offset and payload length
++ fields to aid in locating the payload.
++
++Protocol 2.09: (Kernel 2.6.26) Added a field of 64-bit physical
++ pointer to single linked list of struct setup_data.
+
+ **** MEMORY LAYOUT
+
+@@ -170,6 +180,10 @@ 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
++0250/8 2.09+ setup_data 64-bit physical pointer to linked list
++ of struct setup_data
(1) For backwards compatibility, if the setup_sects field contains 0, the
real value is 4.
-@@ -512,6 +514,32 @@ Protocol: 2.07+
+@@ -512,6 +526,32 @@ Protocol: 2.07+
A pointer to data that is specific to hardware subarch
@@ -5039,8 +6636,341 @@
**** THE KERNEL COMMAND LINE
+@@ -544,6 +584,28 @@ command line is entered using the following protocol:
+ covered by setup_move_size, so you may need to adjust this
+ field.
+
++Field name: setup_data
++Type: write (obligatory)
++Offset/size: 0x250/8
++Protocol: 2.09+
++
++ The 64-bit physical pointer to NULL terminated single linked list of
++ struct setup_data. This is used to define a more extensible boot
++ parameters passing mechanism. The definition of struct setup_data is
++ as follow:
++
++ struct setup_data {
++ u64 next;
++ u32 type;
++ u32 len;
++ u8 data[0];
++ };
++
++ Where, the next is a 64-bit physical pointer to the next node of
++ linked list, the next field of the last node is 0; the type is used
++ to identify the contents of data; the len is the length of data
++ field; the data holds the real payload.
++
+
+ **** MEMORY LAYOUT OF THE REAL-MODE CODE
+
+diff --git a/Documentation/ia64/kvm.txt b/Documentation/ia64/kvm.txt
+new file mode 100644
+index 0000000..bec9d81
+--- /dev/null
++++ b/Documentation/ia64/kvm.txt
+@@ -0,0 +1,82 @@
++Currently, kvm module in EXPERIMENTAL stage on IA64. This means that
++interfaces are not stable enough to use. So, plase had better don't run
++critical applications in virtual machine. We will try our best to make it
++strong in future versions!
++ Guide: How to boot up guests on kvm/ia64
++
++This guide is to describe how to enable kvm support for IA-64 systems.
++
++1. Get the kvm source from git.kernel.org.
++ Userspace source:
++ git clone git://git.kernel.org/pub/scm/virt/kvm/kvm-userspace.git
++ Kernel Source:
++ git clone git://git.kernel.org/pub/scm/linux/kernel/git/xiantao/kvm-ia64.git
++
++2. Compile the source code.
++ 2.1 Compile userspace code:
++ (1)cd ./kvm-userspace
++ (2)./configure
++ (3)cd kernel
++ (4)make sync LINUX= $kernel_dir (kernel_dir is the directory of kernel source.)
++ (5)cd ..
++ (6)make qemu
++ (7)cd qemu; make install
++
++ 2.2 Compile kernel source code:
++ (1) cd ./$kernel_dir
++ (2) Make menuconfig
++ (3) Enter into virtualization option, and choose kvm.
++ (4) make
++ (5) Once (4) done, make modules_install
++ (6) Make initrd, and use new kernel to reboot up host machine.
++ (7) Once (6) done, cd $kernel_dir/arch/ia64/kvm
++ (8) insmod kvm.ko; insmod kvm-intel.ko
++
++Note: For step 2, please make sure that host page size == TARGET_PAGE_SIZE of qemu, otherwise, may fail.
++
++3. Get Guest Firmware named as Flash.fd, and put it under right place:
++ (1) If you have the guest firmware (binary) released by Intel Corp for Xen, use it directly.
++
++ (2) If you have no firmware at hand, Please download its source from
++ hg clone http://xenbits.xensource.com/ext/efi-vfirmware.hg
++ you can get the firmware's binary in the directory of efi-vfirmware.hg/binaries.
++
++ (3) Rename the firware you owned to Flash.fd, and copy it to /usr/local/share/qemu
++
++4. Boot up Linux or Windows guests:
++ 4.1 Create or install a image for guest boot. If you have xen experience, it should be easy.
++
++ 4.2 Boot up guests use the following command.
++ /usr/local/bin/qemu-system-ia64 -smp xx -m 512 -hda $your_image
++ (xx is the number of virtual processors for the guest, now the maximum value is 4)
++
++5. Known possibile issue on some platforms with old Firmware.
++
++If meet strange host crashe issues, try to solve it through either of the following ways:
++
++(1): Upgrade your Firmware to the latest one.
++
++(2): Applying the below patch to kernel source.
++diff --git a/arch/ia64/kernel/pal.S b/arch/ia64/kernel/pal.S
++index 0b53344..f02b0f7 100644
++--- a/arch/ia64/kernel/pal.S
+++++ b/arch/ia64/kernel/pal.S
++@@ -84,7 +84,8 @@ GLOBAL_ENTRY(ia64_pal_call_static)
++ mov ar.pfs = loc1
++ mov rp = loc0
++ ;;
++- srlz.d // seralize restoration of psr.l
+++ srlz.i // seralize restoration of psr.l
+++ ;;
++ br.ret.sptk.many b0
++ END(ia64_pal_call_static)
++
++6. Bug report:
++ If you found any issues when use kvm/ia64, Please post the bug info to kvm-ia64-devel mailing list.
++ https://lists.sourceforge.net/lists/listinfo/kvm-ia64-devel/
++
++Thanks for your interest! Let's work together, and make kvm/ia64 stronger and stronger!
++
++
++ Xiantao Zhang <xiantao.zhang at intel.com>
++ 2008.3.10
+diff --git a/Documentation/ide/ide-tape.txt b/Documentation/ide/ide-tape.txt
+index 658f271..3f348a0 100644
+--- a/Documentation/ide/ide-tape.txt
++++ b/Documentation/ide/ide-tape.txt
+@@ -1,146 +1,65 @@
+-/*
+- * IDE ATAPI streaming tape driver.
+- *
+- * This driver is a part of the Linux ide driver.
+- *
+- * The driver, in co-operation with ide.c, basically traverses the
+- * request-list for the block device interface. The character device
+- * interface, on the other hand, creates new requests, adds them
+- * to the request-list of the block device, and waits for their completion.
+- *
+- * Pipelined operation mode is now supported on both reads and writes.
+- *
+- * The block device major and minor numbers are determined from the
+- * tape's relative position in the ide interfaces, as explained in ide.c.
+- *
+- * The character device interface consists of the following devices:
+- *
+- * ht0 major 37, minor 0 first IDE tape, rewind on close.
+- * ht1 major 37, minor 1 second IDE tape, rewind on close.
+- * ...
+- * nht0 major 37, minor 128 first IDE tape, no rewind on close.
+- * nht1 major 37, minor 129 second IDE tape, no rewind on close.
+- * ...
+- *
+- * The general magnetic tape commands compatible interface, as defined by
+- * include/linux/mtio.h, is accessible through the character device.
+- *
+- * General ide driver configuration options, such as the interrupt-unmask
+- * flag, can be configured by issuing an ioctl to the block device interface,
+- * as any other ide device.
+- *
+- * Our own ide-tape ioctl's can be issued to either the block device or
+- * the character device interface.
+- *
+- * Maximal throughput with minimal bus load will usually be achieved in the
+- * following scenario:
+- *
+- * 1. ide-tape is operating in the pipelined operation mode.
+- * 2. No buffering is performed by the user backup program.
+- *
+- * Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive.
+- *
+- * Here are some words from the first releases of hd.c, which are quoted
+- * in ide.c and apply here as well:
+- *
+- * | Special care is recommended. Have Fun!
+- *
+- *
+- * An overview of the pipelined operation mode.
+- *
+- * In the pipelined write mode, we will usually just add requests to our
+- * pipeline and return immediately, before we even start to service them. The
+- * user program will then have enough time to prepare the next request while
+- * we are still busy servicing previous requests. In the pipelined read mode,
+- * the situation is similar - we add read-ahead requests into the pipeline,
+- * before the user even requested them.
+- *
+- * The pipeline can be viewed as a "safety net" which will be activated when
+- * the system load is high and prevents the user backup program from keeping up
+- * with the current tape speed. At this point, the pipeline will get
+- * shorter and shorter but the tape will still be streaming at the same speed.
+- * Assuming we have enough pipeline stages, the system load will hopefully
+- * decrease before the pipeline is completely empty, and the backup program
+- * will be able to "catch up" and refill the pipeline again.
+- *
+- * When using the pipelined mode, it would be best to disable any type of
+- * buffering done by the user program, as ide-tape already provides all the
+- * benefits in the kernel, where it can be done in a more efficient way.
+- * As we will usually not block the user program on a request, the most
+- * efficient user code will then be a simple read-write-read-... cycle.
+- * Any additional logic will usually just slow down the backup process.
+- *
+- * Using the pipelined mode, I get a constant over 400 KBps throughput,
+- * which seems to be the maximum throughput supported by my tape.
+- *
+- * However, there are some downfalls:
+- *
+- * 1. We use memory (for data buffers) in proportional to the number
+- * of pipeline stages (each stage is about 26 KB with my tape).
+- * 2. In the pipelined write mode, we cheat and postpone error codes
+- * to the user task. In read mode, the actual tape position
+- * will be a bit further than the last requested block.
+- *
+- * Concerning (1):
+- *
+- * 1. We allocate stages dynamically only when we need them. When
+- * we don't need them, we don't consume additional memory. In
+- * case we can't allocate stages, we just manage without them
+- * (at the expense of decreased throughput) so when Linux is
+- * tight in memory, we will not pose additional difficulties.
+- *
+- * 2. The maximum number of stages (which is, in fact, the maximum
+- * amount of memory) which we allocate is limited by the compile
+- * time parameter IDETAPE_MAX_PIPELINE_STAGES.
+- *
+- * 3. The maximum number of stages is a controlled parameter - We
+- * don't start from the user defined maximum number of stages
+- * but from the lower IDETAPE_MIN_PIPELINE_STAGES (again, we
+- * will not even allocate this amount of stages if the user
+- * program can't handle the speed). We then implement a feedback
+- * loop which checks if the pipeline is empty, and if it is, we
+- * increase the maximum number of stages as necessary until we
+- * reach the optimum value which just manages to keep the tape
+- * busy with minimum allocated memory or until we reach
+- * IDETAPE_MAX_PIPELINE_STAGES.
+- *
+- * Concerning (2):
+- *
+- * In pipelined write mode, ide-tape can not return accurate error codes
+- * to the user program since we usually just add the request to the
+- * pipeline without waiting for it to be serviced. In case an error
+- * occurs, I will report it on the next user request.
+- *
+- * In the pipelined read mode, subsequent read requests or forward
+- * filemark spacing will perform correctly, as we preserve all blocks
+- * and filemarks which we encountered during our excess read-ahead.
+- *
+- * For accurate tape positioning and error reporting, disabling
+- * pipelined mode might be the best option.
+- *
+- * You can enable/disable/tune the pipelined operation mode by adjusting
+- * the compile time parameters below.
+- *
+- *
+- * Possible improvements.
+- *
+- * 1. Support for the ATAPI overlap protocol.
+- *
+- * In order to maximize bus throughput, we currently use the DSC
+- * overlap method which enables ide.c to service requests from the
+- * other device while the tape is busy executing a command. The
+- * DSC overlap method involves polling the tape's status register
+- * for the DSC bit, and servicing the other device while the tape
+- * isn't ready.
+- *
+- * In the current QIC development standard (December 1995),
+- * it is recommended that new tape drives will *in addition*
+- * implement the ATAPI overlap protocol, which is used for the
+- * same purpose - efficient use of the IDE bus, but is interrupt
+- * driven and thus has much less CPU overhead.
+- *
+- * ATAPI overlap is likely to be supported in most new ATAPI
+- * devices, including new ATAPI cdroms, and thus provides us
+- * a method by which we can achieve higher throughput when
+- * sharing a (fast) ATA-2 disk with any (slow) new ATAPI device.
+- */
++IDE ATAPI streaming tape driver.
++
++This driver is a part of the Linux ide driver.
++
++The driver, in co-operation with ide.c, basically traverses the
++request-list for the block device interface. The character device
++interface, on the other hand, creates new requests, adds them
++to the request-list of the block device, and waits for their completion.
++
++The block device major and minor numbers are determined from the
++tape's relative position in the ide interfaces, as explained in ide.c.
++
++The character device interface consists of the following devices:
++
++ht0 major 37, minor 0 first IDE tape, rewind on close.
++ht1 major 37, minor 1 second IDE tape, rewind on close.
++...
++nht0 major 37, minor 128 first IDE tape, no rewind on close.
++nht1 major 37, minor 129 second IDE tape, no rewind on close.
++...
++
++The general magnetic tape commands compatible interface, as defined by
++include/linux/mtio.h, is accessible through the character device.
++
++General ide driver configuration options, such as the interrupt-unmask
++flag, can be configured by issuing an ioctl to the block device interface,
++as any other ide device.
++
++Our own ide-tape ioctl's can be issued to either the block device or
++the character device interface.
++
++Maximal throughput with minimal bus load will usually be achieved in the
++following scenario:
++
++ 1. ide-tape is operating in the pipelined operation mode.
++ 2. No buffering is performed by the user backup program.
++
++Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive.
++
++Here are some words from the first releases of hd.c, which are quoted
++in ide.c and apply here as well:
++
++| Special care is recommended. Have Fun!
++
++Possible improvements:
++
++1. Support for the ATAPI overlap protocol.
++
++In order to maximize bus throughput, we currently use the DSC
++overlap method which enables ide.c to service requests from the
++other device while the tape is busy executing a command. The
++DSC overlap method involves polling the tape's status register
++for the DSC bit, and servicing the other device while the tape
++isn't ready.
++
++In the current QIC development standard (December 1995),
++it is recommended that new tape drives will *in addition*
++implement the ATAPI overlap protocol, which is used for the
++same purpose - efficient use of the IDE bus, but is interrupt
++driven and thus has much less CPU overhead.
++
++ATAPI overlap is likely to be supported in most new ATAPI
++devices, including new ATAPI cdroms, and thus provides us
++a method by which we can achieve higher throughput when
++sharing a (fast) ATA-2 disk with any (slow) new ATAPI device.
diff --git a/Documentation/ide/ide.txt b/Documentation/ide/ide.txt
-index 818676a..486c699 100644
+index 818676a..0c78f4b 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
@@ -5073,7 +7003,57 @@
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).
+@@ -105,27 +82,26 @@ Drives are normally found by auto-probing and/or examining the CMOS/BIOS data.
+ For really weird situations, the apparent (fdisk) geometry can also be specified
+ on the kernel "command line" using LILO. The format of such lines is:
+
+- hdx=cyls,heads,sects
+-or hdx=cdrom
++ ide_core.chs=[interface_number.device_number]:cyls,heads,sects
++or ide_core.cdrom=[interface_number.device_number]
+
+-where hdx can be any of hda through hdh, Three values are required
+-(cyls,heads,sects). For example:
++For example:
+
+- hdc=1050,32,64 hdd=cdrom
++ ide_core.chs=1.0:1050,32,64 ide_core.cdrom=1.1
+
+-either {hda,hdb} or {hdc,hdd}. The results of successful auto-probing may
+-override the physical geometry/irq specified, though the "original" geometry
+-may be retained as the "logical" geometry for partitioning purposes (fdisk).
++The results of successful auto-probing may override the physical geometry/irq
++specified, though the "original" geometry may be retained as the "logical"
++geometry for partitioning purposes (fdisk).
+
+ If the auto-probing during boot time confuses a drive (ie. the drive works
+ with hd.c but not with ide.c), then an command line option may be specified
+ for each drive for which you'd like the drive to skip the hardware
+ probe/identification sequence. For example:
+
+- hdb=noprobe
++ ide_core.noprobe=0.1
+ or
+- hdc=768,16,32
+- hdc=noprobe
++ ide_core.chs=1.0:768,16,32
++ ide_core.noprobe=1.0
+
+ Note that when only one IDE device is attached to an interface, it should be
+ jumpered as "single" or "master", *not* "slave". Many folks have had
+@@ -141,9 +117,9 @@ If for some reason your cdrom drive is *not* found at boot time, you can force
+ the probe to look harder by supplying a kernel command line parameter
+ via LILO, such as:
+
+- hdc=cdrom /* hdc = "master" on second interface */
++ ide_core.cdrom=1.0 /* "master" on second interface (hdc) */
+ or
+- hdd=cdrom /* hdd = "slave" on second interface */
++ ide_core.cdrom=1.1 /* "slave" on second interface (hdd) */
+
+ For example, a GW2000 system might have a hard drive on the primary
+ interface (/dev/hda) and an IDE cdrom drive on the secondary interface
+@@ -184,13 +160,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.
@@ -5087,56 +7067,126 @@
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:
+@@ -204,9 +173,7 @@ to /etc/modprobe.conf.
+ 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.
+@@ -214,81 +181,48 @@ driver using the "options=" keyword to insmod, while replacing any ',' with
+ Summary of ide driver parameters for kernel command line
+ --------------------------------------------------------
+
+- "hdx=" is recognized for all "x" from "a" to "u", such as "hdc".
+-
+- "idex=" is recognized for all "x" from "0" to "9", such as "ide1".
+-
+- "hdx=noprobe" : drive may be present, but do not probe for it
+-
+- "hdx=none" : drive is NOT present, ignore cmos and do not probe
+-
+- "hdx=nowerr" : ignore the WRERR_STAT bit on this drive
+-
+- "hdx=cdrom" : drive is present, and is a cdrom drive
+-
+- "hdx=cyl,head,sect" : disk drive is present, with specified geometry
+-
+- "hdx=autotune" : driver will attempt to tune interface speed
+- to the fastest PIO mode supported,
+- if possible for this drive only.
+- Not fully supported by all chipset types,
+- and quite likely to cause trouble with
+- older/odd IDE drives.
+-
+- "hdx=nodma" : disallow DMA
+-
+- "idebus=xx" : inform IDE driver of VESA/PCI bus speed in MHz,
+- where "xx" is between 20 and 66 inclusive,
+- used when tuning chipset PIO modes.
+- For PCI bus, 25 is correct for a P75 system,
+- 30 is correct for P90,P120,P180 systems,
+- and 33 is used for P100,P133,P166 systems.
+- If in doubt, use idebus=33 for PCI.
+- As for VLB, it is safest to not specify it.
+- Bigger values are safer than smaller ones.
++For legacy IDE VLB host drivers (ali14xx/dtc2278/ht6560b/qd65xx/umc8672)
++you need to explicitly enable probing by using "probe" kernel parameter,
++i.e. to enable probing for ALI M14xx chipsets (ali14xx host driver) use:
- "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
--
++* "ali14xx.probe" boot option when ali14xx driver is built-in the kernel
+
- "idex=base,ctl" : specify both base and ctl
--
++* "probe" module parameter when ali14xx driver is compiled as module
++ ("modprobe ali14xx probe")
+
- "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.
++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).
+
+- "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.
++You also need to use "probe" kernel parameter for ide-4drives driver
++(support for IDE generic chipset with four drives on one port).
- "idex=four" : four drives on idex and ide(x^1) share same ports
--
- "idex=reset" : reset interface after probe
++To enable support for IDE doublers on Amiga use "doubler" kernel parameter
++for gayle host driver (i.e. "gayle.doubler" if the driver is built-in).
- "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.
+- "idex=reset" : reset interface after probe
++To force ignoring cable detection (this should be needed only if you're using
++short 40-wires cable which cannot be automatically detected - if this is not
++a case please report it as a bug instead) use "ignore_cable" kernel parameter:
+
+- "idex=ata66" : informs the interface that it has an 80c cable
+- for chipsets that are ATA-66 capable, but the
+- ability to bit test for detection is currently
+- unknown.
++* "ide_core.ignore_cable=[interface_number]" boot option if IDE is built-in
++ (i.e. "ide_core.ignore_cable=1" to force ignoring cable for "ide1")
- "ide=reverse" : formerly called to pci sub-system, but now local.
--
- "ide=doubler" : probe/support IDE doublers on Amiga
++* "ignore_cable=[interface_number]" module parameter (for ide_core module)
++ if IDE is compiled as module
- 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).
+- "ide=doubler" : probe/support IDE doublers on Amiga
++Other kernel parameters for ide_core are:
+
+-There may be more options than shown -- use the source, Luke!
++* "nodma=[interface_number.device_number]" to disallow DMA for a device
+
+-Everything else is rejected with a "BAD OPTION" message.
++* "noflush=[interface_number.device_number]" to disable flush requests
+
+-For legacy IDE VLB host drivers (ali14xx/dtc2278/ht6560b/qd65xx/umc8672)
+-you need to explicitly enable probing by using "probe" kernel parameter,
+-i.e. to enable probing for ALI M14xx chipsets (ali14xx host driver) use:
++* "noprobe=[interface_number.device_number]" to skip probing
+
+-* "ali14xx.probe" boot option when ali14xx driver is built-in the kernel
++* "nowerr=[interface_number.device_number]" to ignore the WRERR_STAT bit
+
+-* "probe" module parameter when ali14xx driver is compiled as module
+- ("modprobe ali14xx probe")
++* "cdrom=[interface_number.device_number]" to force device as a CD-ROM
+
+-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).
++* "chs=[interface_number.device_number]" to force device as a disk (using CHS)
-+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
@@ -5156,6 +7206,47 @@
+# echo -n "1" > /sys/class/ide_port/idex/scan
+
+done
+diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt
+index c18363b..240ce7a 100644
+--- a/Documentation/ioctl-number.txt
++++ b/Documentation/ioctl-number.txt
+@@ -183,6 +183,8 @@ Code Seq# Include File Comments
+ 0xAC 00-1F linux/raw.h
+ 0xAD 00 Netfilter device in development:
+ <mailto:rusty at rustcorp.com.au>
++0xAE all linux/kvm.h Kernel-based Virtual Machine
++ <mailto:kvm-devel at lists.sourceforge.net>
+ 0xB0 all RATIO devices in development:
+ <mailto:vgo at ratio.de>
+ 0xB1 00-1F PPPoX <mailto:mostrows at styx.uwaterloo.ca>
+diff --git a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt
+index 649cb87..00b950d 100644
+--- a/Documentation/kbuild/kconfig-language.txt
++++ b/Documentation/kbuild/kconfig-language.txt
+@@ -104,14 +104,15 @@ applicable everywhere (see syntax).
+ Reverse dependencies can only be used with boolean or tristate
+ symbols.
+ Note:
+- select is evil.... select will by brute force set a symbol
+- equal to 'y' without visiting the dependencies. So abusing
+- select you are able to select a symbol FOO even if FOO depends
+- on BAR that is not set. In general use select only for
+- non-visible symbols (no prompts anywhere) and for symbols with
+- no dependencies. That will limit the usefulness but on the
+- other hand avoid the illegal configurations all over. kconfig
+- should one day warn about such things.
++ select should be used with care. select will force
++ a symbol to a value without visiting the dependencies.
++ By abusing select you are able to select a symbol FOO even
++ if FOO depends on BAR that is not set.
++ In general use select only for non-visible symbols
++ (no prompts anywhere) and for symbols with no dependencies.
++ That will limit the usefulness but on the other hand avoid
++ the illegal configurations all over.
++ kconfig should one day warn about such things.
+
+ - numerical ranges: "range" <symbol> <symbol> ["if" <expr>]
+ This allows to limit the range of possible input values for int
diff --git a/Documentation/kbuild/modules.txt b/Documentation/kbuild/modules.txt
index 1d247d5..1821c07 100644
--- a/Documentation/kbuild/modules.txt
@@ -5184,7 +7275,7 @@
--- 8.1 Testing for CONFIG_FOO_BAR
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
-index dafd001..bf6303e 100644
+index dafd001..a3c3544 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
@@ -5200,21 +7291,51 @@
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
+@@ -490,6 +496,11 @@ and is between 256 and 4096 characters. It is defined in the file
+ switching to the matching ttyS device later. The
+ options are the same as for ttyS, above.
+
++ If the device connected to the port is not a TTY but a braille
++ device, prepend "brl," before the device type, for instance
++ console=brl,ttyS0
++ For now, only VisioBraille is supported.
++
+ earlycon= [KNL] Output early console device and options.
+ uart[8250],io,<addr>[,options]
+ uart[8250],mmio,<addr>[,options]
+@@ -550,6 +561,8 @@ and is between 256 and 4096 characters. It is defined in the file
+ 1 will print _a lot_ more information - normally
+ only useful to kernel developers.
+
++ debug_objects [KNL] Enable object debugging
++
+ decnet.addr= [HW,NET]
+ Format: <area>[,<node>]
+ See also Documentation/networking/decnet.txt.
+@@ -621,8 +634,7 @@ and is between 256 and 4096 characters. It is defined in the file
+ eata= [HW,SCSI]
+
+ edd= [EDD]
+- Format: {"of[f]" | "sk[ipmbr]"}
+- See comment in arch/i386/boot/edd.S
++ Format: {"off" | "on" | "skip[mbr]"}
+
+ eisa_irq_edge= [PARISC,HW]
+ See header of drivers/parisc/eisa.c.
+@@ -763,11 +775,7 @@ and is between 256 and 4096 characters. It is defined in the file
Format: <io>[,<membase>[,<icn_id>[,<icn_id2>]]]
ide= [HW] (E)IDE subsystem
- Format: ide=nodma or ide=doubler or ide=reverse
-+ Format: ide=nodma or ide=doubler
- See Documentation/ide/ide.txt.
-
- ide?= [HW] (E)IDE subsystem
+- See Documentation/ide/ide.txt.
+-
+- ide?= [HW] (E)IDE subsystem
- Format: ide?=noprobe or chipset specific parameters.
-+ Format: ide?=ata66 or chipset specific parameters.
++ Format: ide=nodma or ide=doubler
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
+@@ -812,6 +820,19 @@ and is between 256 and 4096 characters. It is defined in the file
inttest= [IA64]
@@ -5234,7 +7355,7 @@
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
+@@ -828,6 +849,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.
@@ -5245,7 +7366,7 @@
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
+@@ -928,8 +953,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.
@@ -5261,7 +7382,7 @@
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
+@@ -1134,6 +1166,11 @@ and is between 256 and 4096 characters. It is defined in the file
or
memmap=0x10000$0x18690000
@@ -5273,7 +7394,7 @@
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
+@@ -1251,8 +1288,16 @@ and is between 256 and 4096 characters. It is defined in the file
noexec [IA-64]
noexec [X86-32,X86-64]
@@ -5291,7 +7412,7 @@
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
+@@ -1339,6 +1384,10 @@ and is between 256 and 4096 characters. It is defined in the file
nowb [ARM]
@@ -5302,7 +7423,21 @@
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
+@@ -1346,6 +1395,13 @@ and is between 256 and 4096 characters. It is defined in the file
+
+ nr_uarts= [SERIAL] maximum number of UARTs to be registered.
+
++ olpc_ec_timeout= [OLPC] ms delay when issuing EC commands
++ Rather than timing out after 20 ms if an EC
++ command is not properly ACKed, override the length
++ of the timeout. We have interrupts disabled while
++ waiting for the ACK, so if this is set too high
++ interrupts *may* be lost!
++
+ opl3= [HW,OSS]
+ Format: <io>
+
+@@ -1428,10 +1484,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.
@@ -5313,6 +7448,232 @@
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/keys-request-key.txt b/Documentation/keys-request-key.txt
+index 266955d..09b55e4 100644
+--- a/Documentation/keys-request-key.txt
++++ b/Documentation/keys-request-key.txt
+@@ -11,26 +11,29 @@ request_key*():
+
+ struct key *request_key(const struct key_type *type,
+ const char *description,
+- const char *callout_string);
++ const char *callout_info);
+
+ or:
+
+ struct key *request_key_with_auxdata(const struct key_type *type,
+ const char *description,
+- const char *callout_string,
++ const char *callout_info,
++ size_t callout_len,
+ void *aux);
+
+ or:
+
+ struct key *request_key_async(const struct key_type *type,
+ const char *description,
+- const char *callout_string);
++ const char *callout_info,
++ size_t callout_len);
+
+ or:
+
+ struct key *request_key_async_with_auxdata(const struct key_type *type,
+ const char *description,
+- const char *callout_string,
++ const char *callout_info,
++ size_t callout_len,
+ void *aux);
+
+ Or by userspace invoking the request_key system call:
+diff --git a/Documentation/keys.txt b/Documentation/keys.txt
+index 51652d3..d5c7a57 100644
+--- a/Documentation/keys.txt
++++ b/Documentation/keys.txt
+@@ -170,7 +170,8 @@ The key service provides a number of features besides keys:
+ amount of description and payload space that can be consumed.
+
+ The user can view information on this and other statistics through procfs
+- files.
++ files. The root user may also alter the quota limits through sysctl files
++ (see the section "New procfs files").
+
+ Process-specific and thread-specific keyrings are not counted towards a
+ user's quota.
+@@ -329,6 +330,27 @@ about the status of the key service:
+ <bytes>/<max> Key size quota
+
+
++Four new sysctl files have been added also for the purpose of controlling the
++quota limits on keys:
++
++ (*) /proc/sys/kernel/keys/root_maxkeys
++ /proc/sys/kernel/keys/root_maxbytes
++
++ These files hold the maximum number of keys that root may have and the
++ maximum total number of bytes of data that root may have stored in those
++ keys.
++
++ (*) /proc/sys/kernel/keys/maxkeys
++ /proc/sys/kernel/keys/maxbytes
++
++ These files hold the maximum number of keys that each non-root user may
++ have and the maximum total number of bytes of data that each of those
++ users may have stored in their keys.
++
++Root may alter these by writing each new limit as a decimal number string to
++the appropriate file.
++
++
+ ===============================
+ USERSPACE SYSTEM CALL INTERFACE
+ ===============================
+@@ -711,6 +733,27 @@ The keyctl syscall functions are:
+ The assumed authoritative key is inherited across fork and exec.
+
+
++ (*) Get the LSM security context attached to a key.
++
++ long keyctl(KEYCTL_GET_SECURITY, key_serial_t key, char *buffer,
++ size_t buflen)
++
++ This function returns a string that represents the LSM security context
++ attached to a key in the buffer provided.
++
++ Unless there's an error, it always returns the amount of data it could
++ produce, even if that's too big for the buffer, but it won't copy more
++ than requested to userspace. If the buffer pointer is NULL then no copy
++ will take place.
++
++ A NUL character is included at the end of the string if the buffer is
++ sufficiently big. This is included in the returned count. If no LSM is
++ in force then an empty string will be returned.
++
++ A process must have view permission on the key for this function to be
++ successful.
++
++
+ ===============
+ KERNEL SERVICES
+ ===============
+@@ -771,7 +814,7 @@ payload contents" for more information.
+
+ struct key *request_key(const struct key_type *type,
+ const char *description,
+- const char *callout_string);
++ const char *callout_info);
+
+ This is used to request a key or keyring with a description that matches
+ the description specified according to the key type's match function. This
+@@ -793,24 +836,28 @@ payload contents" for more information.
+
+ struct key *request_key_with_auxdata(const struct key_type *type,
+ const char *description,
+- const char *callout_string,
++ const void *callout_info,
++ size_t callout_len,
+ void *aux);
+
+ This is identical to request_key(), except that the auxiliary data is
+- passed to the key_type->request_key() op if it exists.
++ passed to the key_type->request_key() op if it exists, and the callout_info
++ is a blob of length callout_len, if given (the length may be 0).
+
+
+ (*) A key can be requested asynchronously by calling one of:
+
+ struct key *request_key_async(const struct key_type *type,
+ const char *description,
+- const char *callout_string);
++ const void *callout_info,
++ size_t callout_len);
+
+ or:
+
+ struct key *request_key_async_with_auxdata(const struct key_type *type,
+ const char *description,
+- const char *callout_string,
++ const char *callout_info,
++ size_t callout_len,
+ void *aux);
+
+ which are asynchronous equivalents of request_key() and
+diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt
+index be89f39..6877e71 100644
+--- a/Documentation/kprobes.txt
++++ b/Documentation/kprobes.txt
+@@ -37,6 +37,11 @@ registration function such as register_kprobe() specifies where
+ the probe is to be inserted and what handler is to be called when
+ the probe is hit.
+
++There are also register_/unregister_*probes() functions for batch
++registration/unregistration of a group of *probes. These functions
++can speed up unregistration process when you have to unregister
++a lot of probes at once.
++
+ The next three subsections explain how the different types of
+ probes work. They explain certain things that you'll need to
+ know in order to make the best use of Kprobes -- e.g., the
+@@ -190,10 +195,11 @@ code mapping.
+ 4. API Reference
+
+ The Kprobes API includes a "register" function and an "unregister"
+-function for each type of probe. Here are terse, mini-man-page
+-specifications for these functions and the associated probe handlers
+-that you'll write. See the files in the samples/kprobes/ sub-directory
+-for examples.
++function for each type of probe. The API also includes "register_*probes"
++and "unregister_*probes" functions for (un)registering arrays of probes.
++Here are terse, mini-man-page specifications for these functions and
++the associated probe handlers that you'll write. See the files in the
++samples/kprobes/ sub-directory for examples.
+
+ 4.1 register_kprobe
+
+@@ -319,6 +325,43 @@ void unregister_kretprobe(struct kretprobe *rp);
+ Removes the specified probe. The unregister function can be called
+ at any time after the probe has been registered.
+
++NOTE:
++If the functions find an incorrect probe (ex. an unregistered probe),
++they clear the addr field of the probe.
++
++4.5 register_*probes
++
++#include <linux/kprobes.h>
++int register_kprobes(struct kprobe **kps, int num);
++int register_kretprobes(struct kretprobe **rps, int num);
++int register_jprobes(struct jprobe **jps, int num);
++
++Registers each of the num probes in the specified array. If any
++error occurs during registration, all probes in the array, up to
++the bad probe, are safely unregistered before the register_*probes
++function returns.
++- kps/rps/jps: an array of pointers to *probe data structures
++- num: the number of the array entries.
++
++NOTE:
++You have to allocate(or define) an array of pointers and set all
++of the array entries before using these functions.
++
++4.6 unregister_*probes
++
++#include <linux/kprobes.h>
++void unregister_kprobes(struct kprobe **kps, int num);
++void unregister_kretprobes(struct kretprobe **rps, int num);
++void unregister_jprobes(struct jprobe **jps, int num);
++
++Removes each of the num probes in the specified array at once.
++
++NOTE:
++If the functions find some incorrect probes (ex. unregistered
++probes) in the specified array, they clear the addr field of those
++incorrect probes. However, other probes in the array are
++unregistered correctly.
++
+ 5. Kprobes Features and Limitations
+
+ Kprobes allows multiple probes at the same address. Currently,
diff --git a/Documentation/laptops/acer-wmi.txt b/Documentation/laptops/acer-wmi.txt
index 23df051..79b7dbd 100644
--- a/Documentation/laptops/acer-wmi.txt
@@ -5326,6 +7687,207 @@
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/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
+index 76cb428..01c6c3d 100644
+--- a/Documentation/laptops/thinkpad-acpi.txt
++++ b/Documentation/laptops/thinkpad-acpi.txt
+@@ -1,7 +1,7 @@
+ ThinkPad ACPI Extras Driver
+
+- Version 0.19
+- January 06th, 2008
++ Version 0.20
++ April 09th, 2008
+
+ Borislav Deianov <borislav at users.sf.net>
+ Henrique de Moraes Holschuh <hmh at hmh.eng.br>
+@@ -18,6 +18,11 @@ This driver used to be named ibm-acpi until kernel 2.6.21 and release
+ moved to the drivers/misc tree and renamed to thinkpad-acpi for kernel
+ 2.6.22, and release 0.14.
+
++The driver is named "thinkpad-acpi". In some places, like module
++names, "thinkpad_acpi" is used because of userspace issues.
++
++"tpacpi" is used as a shorthand where "thinkpad-acpi" would be too
++long due to length limitations on some Linux kernel versions.
+
+ Status
+ ------
+@@ -571,6 +576,47 @@ netlink interface and the input layer interface, and don't bother at all
+ with hotkey_report_mode.
+
+
++Brightness hotkey notes:
++
++These are the current sane choices for brightness key mapping in
++thinkpad-acpi:
++
++For IBM and Lenovo models *without* ACPI backlight control (the ones on
++which thinkpad-acpi will autoload its backlight interface by default,
++and on which ACPI video does not export a backlight interface):
++
++1. Don't enable or map the brightness hotkeys in thinkpad-acpi, as
++ these older firmware versions unfortunately won't respect the hotkey
++ mask for brightness keys anyway, and always reacts to them. This
++ usually work fine, unless X.org drivers are doing something to block
++ the BIOS. In that case, use (3) below. This is the default mode of
++ operation.
++
++2. Enable the hotkeys, but map them to something else that is NOT
++ KEY_BRIGHTNESS_UP/DOWN or any other keycode that would cause
++ userspace to try to change the backlight level, and use that as an
++ on-screen-display hint.
++
++3. IF AND ONLY IF X.org drivers find a way to block the firmware from
++ automatically changing the brightness, enable the hotkeys and map
++ them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN, and feed that to
++ something that calls xbacklight. thinkpad-acpi will not be able to
++ change brightness in that case either, so you should disable its
++ backlight interface.
++
++For Lenovo models *with* ACPI backlight control:
++
++1. Load up ACPI video and use that. ACPI video will report ACPI
++ events for brightness change keys. Do not mess with thinkpad-acpi
++ defaults in this case. thinkpad-acpi should not have anything to do
++ with backlight events in a scenario where ACPI video is loaded:
++ brightness hotkeys must be disabled, and the backlight interface is
++ to be kept disabled as well. This is the default mode of operation.
++
++2. Do *NOT* load up ACPI video, enable the hotkeys in thinkpad-acpi,
++ and map them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN. Process
++ these keys on userspace somehow (e.g. by calling xbacklight).
++
+ Bluetooth
+ ---------
+
+@@ -647,16 +693,31 @@ while others are still having problems. For more information:
+
+ https://bugs.freedesktop.org/show_bug.cgi?id=2000
+
+-ThinkLight control -- /proc/acpi/ibm/light
+-------------------------------------------
++ThinkLight control
++------------------
++
++procfs: /proc/acpi/ibm/light
++sysfs attributes: as per LED class, for the "tpacpi::thinklight" LED
+
+-The current status of the ThinkLight can be found in this file. A few
+-models which do not make the status available will show it as
+-"unknown". The available commands are:
++procfs notes:
++
++The ThinkLight status can be read and set through the procfs interface. A
++few models which do not make the status available will show the ThinkLight
++status as "unknown". The available commands are:
+
+ echo on > /proc/acpi/ibm/light
+ echo off > /proc/acpi/ibm/light
+
++sysfs notes:
++
++The ThinkLight sysfs interface is documented by the LED class
++documentation, in Documentation/leds-class.txt. The ThinkLight LED name
++is "tpacpi::thinklight".
++
++Due to limitations in the sysfs LED class, if the status of the thinklight
++cannot be read or if it is unknown, thinkpad-acpi will report it as "off".
++It is impossible to know if the status returned through sysfs is valid.
++
+ Docking / undocking -- /proc/acpi/ibm/dock
+ ------------------------------------------
+
+@@ -815,28 +876,63 @@ The cmos command interface is prone to firmware split-brain problems, as
+ in newer ThinkPads it is just a compatibility layer. Do not use it, it is
+ exported just as a debug tool.
+
+-LED control -- /proc/acpi/ibm/led
+----------------------------------
++LED control
++-----------
++
++procfs: /proc/acpi/ibm/led
++sysfs attributes: as per LED class, see below for names
++
++Some of the LED indicators can be controlled through this feature. On
++some older ThinkPad models, it is possible to query the status of the
++LED indicators as well. Newer ThinkPads cannot query the real status
++of the LED indicators.
+
+-Some of the LED indicators can be controlled through this feature. The
+-available commands are:
++procfs notes:
++
++The available commands are:
+
+- echo '<led number> on' >/proc/acpi/ibm/led
+- echo '<led number> off' >/proc/acpi/ibm/led
+- echo '<led number> blink' >/proc/acpi/ibm/led
++ echo '<LED number> on' >/proc/acpi/ibm/led
++ echo '<LED number> off' >/proc/acpi/ibm/led
++ echo '<LED number> blink' >/proc/acpi/ibm/led
+
+-The <led number> range is 0 to 7. The set of LEDs that can be
+-controlled varies from model to model. Here is the mapping on the X40:
++The <LED number> range is 0 to 7. The set of LEDs that can be
++controlled varies from model to model. Here is the common ThinkPad
++mapping:
+
+ 0 - power
+ 1 - battery (orange)
+ 2 - battery (green)
+- 3 - UltraBase
++ 3 - UltraBase/dock
+ 4 - UltraBay
++ 5 - UltraBase battery slot
++ 6 - (unknown)
+ 7 - standby
+
+ All of the above can be turned on and off and can be made to blink.
+
++sysfs notes:
++
++The ThinkPad LED sysfs interface is described in detail by the LED class
++documentation, in Documentation/leds-class.txt.
++
++The leds are named (in LED ID order, from 0 to 7):
++"tpacpi::power", "tpacpi:orange:batt", "tpacpi:green:batt",
++"tpacpi::dock_active", "tpacpi::bay_active", "tpacpi::dock_batt",
++"tpacpi::unknown_led", "tpacpi::standby".
++
++Due to limitations in the sysfs LED class, if the status of the LED
++indicators cannot be read due to an error, thinkpad-acpi will report it as
++a brightness of zero (same as LED off).
++
++If the thinkpad firmware doesn't support reading the current status,
++trying to read the current LED brightness will just return whatever
++brightness was last written to that attribute.
++
++These LEDs can blink using hardware acceleration. To request that a
++ThinkPad indicator LED should blink in hardware accelerated mode, use the
++"timer" trigger, and leave the delay_on and delay_off parameters set to
++zero (to request hardware acceleration autodetection).
++
+ ACPI sounds -- /proc/acpi/ibm/beep
+ ----------------------------------
+
+@@ -1090,6 +1186,15 @@ it there will be the following attributes:
+ dim the display.
+
+
++WARNING:
++
++ Whatever you do, do NOT ever call thinkpad-acpi backlight-level change
++ interface and the ACPI-based backlight level change interface
++ (available on newer BIOSes, and driven by the Linux ACPI video driver)
++ at the same time. The two will interact in bad ways, do funny things,
++ and maybe reduce the life of the backlight lamps by needlessly kicking
++ its level up and down at every change.
++
+ Volume control -- /proc/acpi/ibm/volume
+ ---------------------------------------
+
diff --git a/Documentation/leds-class.txt b/Documentation/leds-class.txt
index 56757c7..18860ad 100644
--- a/Documentation/leds-class.txt
@@ -5368,6 +7930,20 @@
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/md.txt b/Documentation/md.txt
+index 396cdd9..a8b4306 100644
+--- a/Documentation/md.txt
++++ b/Documentation/md.txt
+@@ -450,3 +450,9 @@ These currently include
+ there are upper and lower limits (32768, 16). Default is 128.
+ strip_cache_active (currently raid5 only)
+ number of active entries in the stripe cache
++ preread_bypass_threshold (currently raid5 only)
++ number of times a stripe requiring preread will be bypassed by
++ a stripe that does not require preread. For fairness defaults
++ to 1. Setting this to 0 disables bypass accounting and
++ requires preread stripes to wait until all full-width stripe-
++ writes are complete. Valid values are 0 to stripe_cache_size.
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 1f506f7..e5a819a 100644
--- a/Documentation/memory-barriers.txt
@@ -5383,6 +7959,77 @@
Documentation/DMA-API.txt
+diff --git a/Documentation/mips/AU1xxx_IDE.README b/Documentation/mips/AU1xxx_IDE.README
+index 5c83341..25a6ed1 100644
+--- a/Documentation/mips/AU1xxx_IDE.README
++++ b/Documentation/mips/AU1xxx_IDE.README
+@@ -46,8 +46,6 @@ Two files are introduced:
+
+ a) 'include/asm-mips/mach-au1x00/au1xxx_ide.h'
+ containes : struct _auide_hwif
+- struct drive_list_entry dma_white_list
+- struct drive_list_entry dma_black_list
+ timing parameters for PIO mode 0/1/2/3/4
+ timing parameters for MWDMA 0/1/2
+
+@@ -63,12 +61,6 @@ Four configs variables are introduced:
+ CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ - maximum transfer size
+ per descriptor
+
+-If MWDMA is enabled and the connected hard disc is not on the white list, the
+-kernel switches to a "safe mwdma mode" at boot time. In this mode the IDE
+-performance is substantial slower then in full speed mwdma. In this case
+-please add your hard disc to the white list (follow instruction from 'ADD NEW
+-HARD DISC TO WHITE OR BLACK LIST' section).
+-
+
+ SUPPORTED IDE MODES
+ -------------------
+@@ -120,44 +112,6 @@ CONFIG_IDEDMA_AUTO=y
+ Also undefine 'IDE_AU1XXX_BURSTMODE' in 'drivers/ide/mips/au1xxx-ide.c' to
+ disable the burst support on DBDMA controller.
+
+-ADD NEW HARD DISC TO WHITE OR BLACK LIST
+-----------------------------------------
+-
+-Step 1 : detect the model name of your hard disc
+-
+- a) connect your hard disc to the AU1XXX
+-
+- b) boot your kernel and get the hard disc model.
+-
+- Example boot log:
+-
+- --snipped--
+- Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2
+- ide: Assuming 50MHz system bus speed for PIO modes; override with idebus=xx
+- Au1xxx IDE(builtin) configured for MWDMA2
+- Probing IDE interface ide0...
+- hda: Maxtor 6E040L0, ATA DISK drive
+- ide0 at 0xac800000-0xac800007,0xac8001c0 on irq 64
+- hda: max request size: 64KiB
+- hda: 80293248 sectors (41110 MB) w/2048KiB Cache, CHS=65535/16/63, (U)DMA
+- --snipped--
+-
+- In this example 'Maxtor 6E040L0'.
+-
+-Step 2 : edit 'include/asm-mips/mach-au1x00/au1xxx_ide.h'
+-
+- Add your hard disc to the dma_white_list or dma_black_list structur.
+-
+-Step 3 : Recompile the kernel
+-
+- Enable MWDMA support in the kernel configuration. Recompile the kernel and
+- reboot.
+-
+-Step 4 : Tests
+-
+- If you have add a hard disc to the white list, please run some stress tests
+- for verification.
+-
+
+ ACKNOWLEDGMENTS
+ ---------------
diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index c485ee0..1634c6d 100644
--- a/Documentation/networking/00-INDEX
@@ -6171,6 +8818,21 @@
->>>>>> END OF README <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
-
-
+diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
+index 7f60dfe..b152e81 100644
+--- a/Documentation/oops-tracing.txt
++++ b/Documentation/oops-tracing.txt
+@@ -253,6 +253,10 @@ characters, each representing a particular tainted value.
+
+ 8: 'D' if the kernel has died recently, i.e. there was an OOPS or BUG.
+
++ 9: 'A' if the ACPI table has been overridden.
++
++ 10: 'W' if a warning has previously been issued by the kernel.
++
+ The primary reason for the 'Tainted: ' string is to tell kernel
+ debuggers if this is a clean kernel or if anything unusual has
+ occurred. Tainting is permanent: even if an offending module is
diff --git a/Documentation/pci-error-recovery.txt b/Documentation/pci-error-recovery.txt
deleted file mode 100644
index 6650af4..0000000
@@ -7501,7 +10163,7 @@
Suspending Devices
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
-index 7b4e8a7..cf89e8c 100644
+index 7b4e8a7..1d2a772 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -59,12 +59,39 @@ Table of Contents
@@ -7634,11 +10296,44 @@
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.
+@@ -2816,10 +2836,562 @@ platforms are moved over to use the flattened-device-tree model.
+ big-endian;
};
-
-- More devices will be defined as this spec matures.
++ r) Freescale Display Interface Unit
++
++ The Freescale DIU is a LCD controller, with proper hardware, it can also
++ drive DVI monitors.
++
++ Required properties:
++ - compatible : should be "fsl-diu".
++ - reg : should contain at least address and length of the DIU register
++ set.
++ - Interrupts : one DIU interrupt should be describe here.
++
++ Example (MPC8610HPCD)
++ display at 2c000 {
++ compatible = "fsl,diu";
++ reg = <0x2c000 100>;
++ interrupts = <72 2>;
++ interrupt-parent = <&mpic>;
++ };
++
++ s) Freescale on board FPGA
++
++ This is the memory-mapped registers for on board FPGA.
++
++ Required properities:
++ - compatible : should be "fsl,fpga-pixis".
++ - reg : should contain the address and the lenght of the FPPGA register
++ set.
++
++ Example (MPC8610HPCD)
++ board-control at e8000000 {
++ compatible = "fsl,fpga-pixis";
++ reg = <0xe8000000 32>;
++ };
++
+VII - Marvell Discovery mv64[345]6x System Controller chips
+===========================================================
+
@@ -7802,7 +10497,8 @@
+ - 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
-+
+
+- More devices will be defined as this spec matures.
+ Example Discovery PHY node:
+ ethernet-phy at 1 {
+ device_type = "ethernet-phy";
@@ -7811,7 +10507,8 @@
+ interrupt-parent = <&PIC>;
+ reg = <1>;
+ };
-+
+
+-VII - Specifying interrupt information for devices
+
+ d) Marvell Discovery SDMA nodes
+
@@ -7890,8 +10587,7 @@
+
+
+ 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).
+
@@ -8165,7 +10861,7 @@
===================================================
The device tree represents the busses and devices of a hardware
-@@ -2905,6 +3444,54 @@ encodings listed below:
+@@ -2905,6 +3477,54 @@ encodings listed below:
2 = high to low edge sensitive type enabled
3 = low to high edge sensitive type enabled
@@ -8220,6 +10916,83 @@
Appendix A - Sample SOC node for MPC8540
========================================
+diff --git a/Documentation/powerpc/kvm_440.txt b/Documentation/powerpc/kvm_440.txt
+new file mode 100644
+index 0000000..c02a003
+--- /dev/null
++++ b/Documentation/powerpc/kvm_440.txt
+@@ -0,0 +1,41 @@
++Hollis Blanchard <hollisb at us.ibm.com>
++15 Apr 2008
++
++Various notes on the implementation of KVM for PowerPC 440:
++
++To enforce isolation, host userspace, guest kernel, and guest userspace all
++run at user privilege level. Only the host kernel runs in supervisor mode.
++Executing privileged instructions in the guest traps into KVM (in the host
++kernel), where we decode and emulate them. Through this technique, unmodified
++440 Linux kernels can be run (slowly) as guests. Future performance work will
++focus on reducing the overhead and frequency of these traps.
++
++The usual code flow is started from userspace invoking an "run" ioctl, which
++causes KVM to switch into guest context. We use IVPR to hijack the host
++interrupt vectors while running the guest, which allows us to direct all
++interrupts to kvmppc_handle_interrupt(). At this point, we could either
++- handle the interrupt completely (e.g. emulate "mtspr SPRG0"), or
++- let the host interrupt handler run (e.g. when the decrementer fires), or
++- return to host userspace (e.g. when the guest performs device MMIO)
++
++Address spaces: We take advantage of the fact that Linux doesn't use the AS=1
++address space (in host or guest), which gives us virtual address space to use
++for guest mappings. While the guest is running, the host kernel remains mapped
++in AS=0, but the guest can only use AS=1 mappings.
++
++TLB entries: The TLB entries covering the host linear mapping remain
++present while running the guest. This reduces the overhead of lightweight
++exits, which are handled by KVM running in the host kernel. We keep three
++copies of the TLB:
++ - guest TLB: contents of the TLB as the guest sees it
++ - shadow TLB: the TLB that is actually in hardware while guest is running
++ - host TLB: to restore TLB state when context switching guest -> host
++When a TLB miss occurs because a mapping was not present in the shadow TLB,
++but was present in the guest TLB, KVM handles the fault without invoking the
++guest. Large guest pages are backed by multiple 4KB shadow pages through this
++mechanism.
++
++IO: MMIO and DCR accesses are emulated by userspace. We use virtio for network
++and block IO, so those drivers must be enabled in the guest. It's possible
++that some qemu device emulation (e.g. e1000 or rtl8139) may also work with
++little effort.
+diff --git a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
+index 5e03610..cda7a7d 100644
+--- a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
++++ b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
+@@ -186,6 +186,12 @@ Recommended soc5200 child nodes; populate as needed for your board
+ name device_type compatible Description
+ ---- ----------- ---------- -----------
+ gpt@<addr> gpt fsl,mpc5200-gpt General purpose timers
++gpt@<addr> gpt fsl,mpc5200-gpt-gpio General purpose
++ timers in GPIO mode
++gpio@<addr> fsl,mpc5200-gpio MPC5200 simple gpio
++ controller
++gpio@<addr> fsl,mpc5200-gpio-wkup MPC5200 wakeup gpio
++ controller
+ rtc@<addr> rtc mpc5200-rtc Real time clock
+ mscan@<addr> mscan mpc5200-mscan CAN bus controller
+ pci@<addr> pci mpc5200-pci PCI bridge
+@@ -225,6 +231,12 @@ PSC in i2s mode: The mpc5200 and mpc5200b PSCs are not compatible when in
+ i2s mode. An 'mpc5200b-psc-i2s' node cannot include 'mpc5200-psc-i2s' in the
+ compatible field.
+
++7) GPIO controller nodes
++Each GPIO controller node should have the empty property gpio-controller and
++#gpio-cells set to 2. First cell is the GPIO number which is interpreted
++according to the bit numbers in the GPIO control registers. The second cell
++is for flags which is currently unsused.
++
+ IV - Extra Notes
+ ================
+
diff --git a/Documentation/powerpc/phyp-assisted-dump.txt b/Documentation/powerpc/phyp-assisted-dump.txt
new file mode 100644
index 0000000..c4682b9
@@ -8656,6 +11429,137 @@
+ exit(EXIT_SUCCESS);
+}
+
+diff --git a/Documentation/s390/kvm.txt b/Documentation/s390/kvm.txt
+new file mode 100644
+index 0000000..6f5ceb0
+--- /dev/null
++++ b/Documentation/s390/kvm.txt
+@@ -0,0 +1,125 @@
++*** BIG FAT WARNING ***
++The kvm module is currently in EXPERIMENTAL state for s390. This means that
++the interface to the module is not yet considered to remain stable. Thus, be
++prepared that we keep breaking your userspace application and guest
++compatibility over and over again until we feel happy with the result. Make sure
++your guest kernel, your host kernel, and your userspace launcher are in a
++consistent state.
++
++This Documentation describes the unique ioctl calls to /dev/kvm, the resulting
++kvm-vm file descriptors, and the kvm-vcpu file descriptors that differ from x86.
++
++1. ioctl calls to /dev/kvm
++KVM does support the following ioctls on s390 that are common with other
++architectures and do behave the same:
++KVM_GET_API_VERSION
++KVM_CREATE_VM (*) see note
++KVM_CHECK_EXTENSION
++KVM_GET_VCPU_MMAP_SIZE
++
++Notes:
++* KVM_CREATE_VM may fail on s390, if the calling process has multiple
++threads and has not called KVM_S390_ENABLE_SIE before.
++
++In addition, on s390 the following architecture specific ioctls are supported:
++ioctl: KVM_S390_ENABLE_SIE
++args: none
++see also: include/linux/kvm.h
++This call causes the kernel to switch on PGSTE in the user page table. This
++operation is needed in order to run a virtual machine, and it requires the
++calling process to be single-threaded. Note that the first call to KVM_CREATE_VM
++will implicitly try to switch on PGSTE if the user process has not called
++KVM_S390_ENABLE_SIE before. User processes that want to launch multiple threads
++before creating a virtual machine have to call KVM_S390_ENABLE_SIE, or will
++observe an error calling KVM_CREATE_VM. Switching on PGSTE is a one-time
++operation, is not reversible, and will persist over the entire lifetime of
++the calling process. It does not have any user-visible effect other than a small
++performance penalty.
++
++2. ioctl calls to the kvm-vm file descriptor
++KVM does support the following ioctls on s390 that are common with other
++architectures and do behave the same:
++KVM_CREATE_VCPU
++KVM_SET_USER_MEMORY_REGION (*) see note
++KVM_GET_DIRTY_LOG (**) see note
++
++Notes:
++* kvm does only allow exactly one memory slot on s390, which has to start
++ at guest absolute address zero and at a user address that is aligned on any
++ page boundary. This hardware "limitation" allows us to have a few unique
++ optimizations. The memory slot doesn't have to be filled
++ with memory actually, it may contain sparse holes. That said, with different
++ user memory layout this does still allow a large flexibility when
++ doing the guest memory setup.
++** KVM_GET_DIRTY_LOG doesn't work properly yet. The user will receive an empty
++log. This ioctl call is only needed for guest migration, and we intend to
++implement this one in the future.
++
++In addition, on s390 the following architecture specific ioctls for the kvm-vm
++file descriptor are supported:
++ioctl: KVM_S390_INTERRUPT
++args: struct kvm_s390_interrupt *
++see also: include/linux/kvm.h
++This ioctl is used to submit a floating interrupt for a virtual machine.
++Floating interrupts may be delivered to any virtual cpu in the configuration.
++Only some interrupt types defined in include/linux/kvm.h make sense when
++submitted as floating interrupts. The following interrupts are not considered
++to be useful as floating interrupts, and a call to inject them will result in
++-EINVAL error code: program interrupts and interprocessor signals. Valid
++floating interrupts are:
++KVM_S390_INT_VIRTIO
++KVM_S390_INT_SERVICE
++
++3. ioctl calls to the kvm-vcpu file descriptor
++KVM does support the following ioctls on s390 that are common with other
++architectures and do behave the same:
++KVM_RUN
++KVM_GET_REGS
++KVM_SET_REGS
++KVM_GET_SREGS
++KVM_SET_SREGS
++KVM_GET_FPU
++KVM_SET_FPU
++
++In addition, on s390 the following architecture specific ioctls for the
++kvm-vcpu file descriptor are supported:
++ioctl: KVM_S390_INTERRUPT
++args: struct kvm_s390_interrupt *
++see also: include/linux/kvm.h
++This ioctl is used to submit an interrupt for a specific virtual cpu.
++Only some interrupt types defined in include/linux/kvm.h make sense when
++submitted for a specific cpu. The following interrupts are not considered
++to be useful, and a call to inject them will result in -EINVAL error code:
++service processor calls and virtio interrupts. Valid interrupt types are:
++KVM_S390_PROGRAM_INT
++KVM_S390_SIGP_STOP
++KVM_S390_RESTART
++KVM_S390_SIGP_SET_PREFIX
++KVM_S390_INT_EMERGENCY
++
++ioctl: KVM_S390_STORE_STATUS
++args: unsigned long
++see also: include/linux/kvm.h
++This ioctl stores the state of the cpu at the guest real address given as
++argument, unless one of the following values defined in include/linux/kvm.h
++is given as arguement:
++KVM_S390_STORE_STATUS_NOADDR - the CPU stores its status to the save area in
++absolute lowcore as defined by the principles of operation
++KVM_S390_STORE_STATUS_PREFIXED - the CPU stores its status to the save area in
++its prefix page just like the dump tool that comes with zipl. This is useful
++to create a system dump for use with lkcdutils or crash.
++
++ioctl: KVM_S390_SET_INITIAL_PSW
++args: struct kvm_s390_psw *
++see also: include/linux/kvm.h
++This ioctl can be used to set the processor status word (psw) of a stopped cpu
++prior to running it with KVM_RUN. Note that this call is not required to modify
++the psw during sie intercepts that fall back to userspace because struct kvm_run
++does contain the psw, and this value is evaluated during reentry of KVM_RUN
++after the intercept exit was recognized.
++
++ioctl: KVM_S390_INITIAL_RESET
++args: none
++see also: include/linux/kvm.h
++This ioctl can be used to perform an initial cpu reset as defined by the
++principles of operation. The target cpu has to be in stopped state.
diff --git a/Documentation/s390/s390dbf.txt b/Documentation/s390/s390dbf.txt
index 0eb7c58..e054209 100644
--- a/Documentation/s390/s390dbf.txt
@@ -9047,7 +11951,7 @@
-
- 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
+index e985cf5..0bbee38 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.
@@ -9064,7 +11968,15 @@
Module snd-azt2320
------------------
-@@ -818,19 +825,25 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+@@ -788,6 +795,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ lg-lw LG LW20/LW25 laptop
+ tcl TCL S700
+ clevo Clevo laptops (m520G, m665n)
++ medion Medion Rim 2150
+ test for testing/debugging purpose, almost all controls can be
+ adjusted. Appearing only when compiled with
+ $CONFIG_SND_DEBUG=y
+@@ -818,19 +826,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
@@ -9091,7 +12003,7 @@
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.
+@@ -871,10 +885,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
@@ -9104,7 +12016,7 @@
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.
+@@ -911,6 +926,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
3stack 3-stack mode (default)
6stack 6-stack mode
@@ -9117,7 +12029,7 @@
AD1884
N/A
-@@ -936,7 +956,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+@@ -936,7 +957,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)
@@ -9126,7 +12038,7 @@
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.
+@@ -979,6 +1000,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
@@ -9134,7 +12046,7 @@
STAC9205/9254
ref Reference board
-@@ -1017,6 +1038,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+@@ -1017,6 +1039,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
@@ -9151,7 +12063,7 @@
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.
+@@ -1590,6 +1622,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Power management is _not_ supported.
@@ -9168,6 +12080,447 @@
Module snd-pcxhr
----------------
+diff --git a/Documentation/spi/spidev b/Documentation/spi/spidev
+index 5c8e1b9..ed2da5e 100644
+--- a/Documentation/spi/spidev
++++ b/Documentation/spi/spidev
+@@ -126,8 +126,8 @@ NOTES:
+ FULL DUPLEX CHARACTER DEVICE API
+ ================================
+
+-See the sample program below for one example showing the use of the full
+-duplex programming interface. (Although it doesn't perform a full duplex
++See the spidev_fdx.c sample program for one example showing the use of the
++full duplex programming interface. (Although it doesn't perform a full duplex
+ transfer.) The model is the same as that used in the kernel spi_sync()
+ request; the individual transfers offer the same capabilities as are
+ available to kernel drivers (except that it's not asynchronous).
+@@ -141,167 +141,3 @@ and bitrate for each transfer segment.)
+
+ To make a full duplex request, provide both rx_buf and tx_buf for the
+ same transfer. It's even OK if those are the same buffer.
+-
+-
+-SAMPLE PROGRAM
+-==============
+-
+--------------------------------- CUT HERE
+-#include <stdio.h>
+-#include <unistd.h>
+-#include <stdlib.h>
+-#include <fcntl.h>
+-#include <string.h>
+-
+-#include <sys/ioctl.h>
+-#include <sys/types.h>
+-#include <sys/stat.h>
+-
+-#include <linux/types.h>
+-#include <linux/spi/spidev.h>
+-
+-
+-static int verbose;
+-
+-static void do_read(int fd, int len)
+-{
+- unsigned char buf[32], *bp;
+- int status;
+-
+- /* read at least 2 bytes, no more than 32 */
+- if (len < 2)
+- len = 2;
+- else if (len > sizeof(buf))
+- len = sizeof(buf);
+- memset(buf, 0, sizeof buf);
+-
+- status = read(fd, buf, len);
+- if (status < 0) {
+- perror("read");
+- return;
+- }
+- if (status != len) {
+- fprintf(stderr, "short read\n");
+- return;
+- }
+-
+- printf("read(%2d, %2d): %02x %02x,", len, status,
+- buf[0], buf[1]);
+- status -= 2;
+- bp = buf + 2;
+- while (status-- > 0)
+- printf(" %02x", *bp++);
+- printf("\n");
+-}
+-
+-static void do_msg(int fd, int len)
+-{
+- struct spi_ioc_transfer xfer[2];
+- unsigned char buf[32], *bp;
+- int status;
+-
+- memset(xfer, 0, sizeof xfer);
+- memset(buf, 0, sizeof buf);
+-
+- if (len > sizeof buf)
+- len = sizeof buf;
+-
+- buf[0] = 0xaa;
+- xfer[0].tx_buf = (__u64) buf;
+- xfer[0].len = 1;
+-
+- xfer[1].rx_buf = (__u64) buf;
+- xfer[1].len = len;
+-
+- status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer);
+- if (status < 0) {
+- perror("SPI_IOC_MESSAGE");
+- return;
+- }
+-
+- printf("response(%2d, %2d): ", len, status);
+- for (bp = buf; len; len--)
+- printf(" %02x", *bp++);
+- printf("\n");
+-}
+-
+-static void dumpstat(const char *name, int fd)
+-{
+- __u8 mode, lsb, bits;
+- __u32 speed;
+-
+- if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0) {
+- perror("SPI rd_mode");
+- return;
+- }
+- if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) {
+- perror("SPI rd_lsb_fist");
+- return;
+- }
+- if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) {
+- perror("SPI bits_per_word");
+- return;
+- }
+- if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) {
+- perror("SPI max_speed_hz");
+- return;
+- }
+-
+- printf("%s: spi mode %d, %d bits %sper word, %d Hz max\n",
+- name, mode, bits, lsb ? "(lsb first) " : "", speed);
+-}
+-
+-int main(int argc, char **argv)
+-{
+- int c;
+- int readcount = 0;
+- int msglen = 0;
+- int fd;
+- const char *name;
+-
+- while ((c = getopt(argc, argv, "hm:r:v")) != EOF) {
+- switch (c) {
+- case 'm':
+- msglen = atoi(optarg);
+- if (msglen < 0)
+- goto usage;
+- continue;
+- case 'r':
+- readcount = atoi(optarg);
+- if (readcount < 0)
+- goto usage;
+- continue;
+- case 'v':
+- verbose++;
+- continue;
+- case 'h':
+- case '?':
+-usage:
+- fprintf(stderr,
+- "usage: %s [-h] [-m N] [-r N] /dev/spidevB.D\n",
+- argv[0]);
+- return 1;
+- }
+- }
+-
+- if ((optind + 1) != argc)
+- goto usage;
+- name = argv[optind];
+-
+- fd = open(name, O_RDWR);
+- if (fd < 0) {
+- perror("open");
+- return 1;
+- }
+-
+- dumpstat(name, fd);
+-
+- if (msglen)
+- do_msg(fd, msglen);
+-
+- if (readcount)
+- do_read(fd, readcount);
+-
+- close(fd);
+- return 0;
+-}
+diff --git a/Documentation/spi/spidev_fdx.c b/Documentation/spi/spidev_fdx.c
+new file mode 100644
+index 0000000..fc354f7
+--- /dev/null
++++ b/Documentation/spi/spidev_fdx.c
+@@ -0,0 +1,158 @@
++#include <stdio.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include <fcntl.h>
++#include <string.h>
++
++#include <sys/ioctl.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++
++#include <linux/types.h>
++#include <linux/spi/spidev.h>
++
++
++static int verbose;
++
++static void do_read(int fd, int len)
++{
++ unsigned char buf[32], *bp;
++ int status;
++
++ /* read at least 2 bytes, no more than 32 */
++ if (len < 2)
++ len = 2;
++ else if (len > sizeof(buf))
++ len = sizeof(buf);
++ memset(buf, 0, sizeof buf);
++
++ status = read(fd, buf, len);
++ if (status < 0) {
++ perror("read");
++ return;
++ }
++ if (status != len) {
++ fprintf(stderr, "short read\n");
++ return;
++ }
++
++ printf("read(%2d, %2d): %02x %02x,", len, status,
++ buf[0], buf[1]);
++ status -= 2;
++ bp = buf + 2;
++ while (status-- > 0)
++ printf(" %02x", *bp++);
++ printf("\n");
++}
++
++static void do_msg(int fd, int len)
++{
++ struct spi_ioc_transfer xfer[2];
++ unsigned char buf[32], *bp;
++ int status;
++
++ memset(xfer, 0, sizeof xfer);
++ memset(buf, 0, sizeof buf);
++
++ if (len > sizeof buf)
++ len = sizeof buf;
++
++ buf[0] = 0xaa;
++ xfer[0].tx_buf = (__u64) buf;
++ xfer[0].len = 1;
++
++ xfer[1].rx_buf = (__u64) buf;
++ xfer[1].len = len;
++
++ status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer);
++ if (status < 0) {
++ perror("SPI_IOC_MESSAGE");
++ return;
++ }
++
++ printf("response(%2d, %2d): ", len, status);
++ for (bp = buf; len; len--)
++ printf(" %02x", *bp++);
++ printf("\n");
++}
++
++static void dumpstat(const char *name, int fd)
++{
++ __u8 mode, lsb, bits;
++ __u32 speed;
++
++ if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0) {
++ perror("SPI rd_mode");
++ return;
++ }
++ if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) {
++ perror("SPI rd_lsb_fist");
++ return;
++ }
++ if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) {
++ perror("SPI bits_per_word");
++ return;
++ }
++ if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) {
++ perror("SPI max_speed_hz");
++ return;
++ }
++
++ printf("%s: spi mode %d, %d bits %sper word, %d Hz max\n",
++ name, mode, bits, lsb ? "(lsb first) " : "", speed);
++}
++
++int main(int argc, char **argv)
++{
++ int c;
++ int readcount = 0;
++ int msglen = 0;
++ int fd;
++ const char *name;
++
++ while ((c = getopt(argc, argv, "hm:r:v")) != EOF) {
++ switch (c) {
++ case 'm':
++ msglen = atoi(optarg);
++ if (msglen < 0)
++ goto usage;
++ continue;
++ case 'r':
++ readcount = atoi(optarg);
++ if (readcount < 0)
++ goto usage;
++ continue;
++ case 'v':
++ verbose++;
++ continue;
++ case 'h':
++ case '?':
++usage:
++ fprintf(stderr,
++ "usage: %s [-h] [-m N] [-r N] /dev/spidevB.D\n",
++ argv[0]);
++ return 1;
++ }
++ }
++
++ if ((optind + 1) != argc)
++ goto usage;
++ name = argv[optind];
++
++ fd = open(name, O_RDWR);
++ if (fd < 0) {
++ perror("open");
++ return 1;
++ }
++
++ dumpstat(name, fd);
++
++ if (msglen)
++ do_msg(fd, msglen);
++
++ if (readcount)
++ do_read(fd, readcount);
++
++ close(fd);
++ return 0;
++}
+diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
+index 10c8f69..5ce0952 100644
+--- a/Documentation/sysrq.txt
++++ b/Documentation/sysrq.txt
+@@ -85,6 +85,8 @@ On all - write a character to /proc/sysrq-trigger. e.g.:
+ 'k' - Secure Access Key (SAK) Kills all programs on the current virtual
+ console. NOTE: See important comments below in SAK section.
+
++'l' - Shows a stack backtrace for all active CPUs.
++
+ 'm' - Will dump current memory info to your console.
+
+ 'n' - Used to make RT tasks nice-able
+diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
+index d9f28be..70d68ce 100644
+--- a/Documentation/thermal/sysfs-api.txt
++++ b/Documentation/thermal/sysfs-api.txt
+@@ -108,10 +108,12 @@ and throttle appropriate devices.
+ RO read only value
+ RW read/write value
+
+-All thermal sysfs attributes will be represented under /sys/class/thermal
++Thermal sysfs attributes will be represented under /sys/class/thermal.
++Hwmon sysfs I/F extension is also available under /sys/class/hwmon
++if hwmon is compiled in or built as a module.
+
+ Thermal zone device sys I/F, created once it's registered:
+-|thermal_zone[0-*]:
++/sys/class/thermal/thermal_zone[0-*]:
+ |-----type: Type of the thermal zone
+ |-----temp: Current temperature
+ |-----mode: Working mode of the thermal zone
+@@ -119,7 +121,7 @@ Thermal zone device sys I/F, created once it's registered:
+ |-----trip_point_[0-*]_type: Trip point type
+
+ Thermal cooling device sys I/F, created once it's registered:
+-|cooling_device[0-*]:
++/sys/class/thermal/cooling_device[0-*]:
+ |-----type : Type of the cooling device(processor/fan/...)
+ |-----max_state: Maximum cooling state of the cooling device
+ |-----cur_state: Current cooling state of the cooling device
+@@ -130,10 +132,19 @@ They represent the relationship between a thermal zone and its associated coolin
+ They are created/removed for each
+ thermal_zone_bind_cooling_device/thermal_zone_unbind_cooling_device successful execution.
+
+-|thermal_zone[0-*]
++/sys/class/thermal/thermal_zone[0-*]
+ |-----cdev[0-*]: The [0-*]th cooling device in the current thermal zone
+ |-----cdev[0-*]_trip_point: Trip point that cdev[0-*] is associated with
+
++Besides the thermal zone device sysfs I/F and cooling device sysfs I/F,
++the generic thermal driver also creates a hwmon sysfs I/F for each _type_ of
++thermal zone device. E.g. the generic thermal driver registers one hwmon class device
++and build the associated hwmon sysfs I/F for all the registered ACPI thermal zones.
++/sys/class/hwmon/hwmon[0-*]:
++ |-----name: The type of the thermal zone devices.
++ |-----temp[1-*]_input: The current temperature of thermal zone [1-*].
++ |-----temp[1-*]_critical: The critical trip point of thermal zone [1-*].
++Please read Documentation/hwmon/sysfs-interface for additional information.
+
+ ***************************
+ * Thermal zone attributes *
+@@ -141,7 +152,10 @@ thermal_zone_bind_cooling_device/thermal_zone_unbind_cooling_device successful e
+
+ type Strings which represent the thermal zone type.
+ This is given by thermal zone driver as part of registration.
+- Eg: "ACPI thermal zone" indicates it's a ACPI thermal device
++ Eg: "acpitz" indicates it's an ACPI thermal device.
++ In order to keep it consistent with hwmon sys attribute,
++ this should be a short, lowercase string,
++ not containing spaces nor dashes.
+ RO
+ Required
+
+@@ -218,7 +232,7 @@ the sys I/F structure will be built like this:
+ /sys/class/thermal:
+
+ |thermal_zone1:
+- |-----type: ACPI thermal zone
++ |-----type: acpitz
+ |-----temp: 37000
+ |-----mode: kernel
+ |-----trip_point_0_temp: 100000
+@@ -243,3 +257,10 @@ the sys I/F structure will be built like this:
+ |-----type: Fan
+ |-----max_state: 2
+ |-----cur_state: 0
++
++/sys/class/hwmon:
++
++|hwmon0:
++ |-----name: acpitz
++ |-----temp1_input: 37000
++ |-----temp1_crit: 100000
diff --git a/Documentation/timers/highres.txt b/Documentation/timers/highres.txt
new file mode 100644
index 0000000..a73ecf5
@@ -10059,7 +13412,7 @@
+ 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
+index 0424901..67937df 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -25,8 +25,8 @@
@@ -10073,8 +13426,12 @@
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]
+@@ -128,6 +128,16 @@
+ 127 -> Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM [0000:5071,0000:507B,5ace:5070,5ace:5090]
+ 128 -> Beholder BeholdTV Columbus TVFM [0000:5201]
+ 129 -> Beholder BeholdTV 607 / BeholdTV 609 [5ace:6070,5ace:6071,5ace:6072,5ace:6073,5ace:6090,5ace:6091,5ace:6092,5ace:6093]
+-130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193]
++130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193,5ace:6191]
131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022]
132 -> Genius TVGO AM11MCE
+133 -> NXP Snake DVB-S reference design
@@ -10086,6 +13443,47 @@
+139 -> Compro VideoMate T750 [185b:c900]
+140 -> Avermedia DVB-S Pro A700 [1461:a7a1]
+141 -> Avermedia DVB-S Hybrid+FM A700 [1461:a7a2]
++142 -> Beholder BeholdTV H6 [5ace:6290]
+diff --git a/Documentation/video4linux/cx18.txt b/Documentation/video4linux/cx18.txt
+new file mode 100644
+index 0000000..077d56e
+--- /dev/null
++++ b/Documentation/video4linux/cx18.txt
+@@ -0,0 +1,34 @@
++Some notes regarding the cx18 driver for the Conexant CX23418 MPEG
++encoder chip:
++
++1) The only hardware currently supported is the Hauppauge HVR-1600.
++
++2) Some people have problems getting the i2c bus to work. Cause unknown.
++ The symptom is that the eeprom cannot be read and the card is
++ unusable.
++
++3) The audio from the analog tuner is mono only. Probably caused by
++ incorrect audio register information in the datasheet. We are
++ waiting for updated information from Conexant.
++
++4) VBI (raw or sliced) has not yet been implemented.
++
++5) MPEG indexing is not yet implemented.
++
++6) The driver is still a bit rough around the edges, this should
++ improve over time.
++
++
++Firmware:
++
++The firmware needs to be extracted from the Windows Hauppauge HVR-1600
++driver, available here:
++
++http://hauppauge.lightpath.net/software/install_cd/hauppauge_cd_3.4d1.zip
++
++Unzip, then copy the following files to the firmware directory
++and rename them as follows:
++
++Drivers/Driver18/hcw18apu.rom -> v4l-cx23418-apu.fw
++Drivers/Driver18/hcw18enc.rom -> v4l-cx23418-cpu.fw
++Drivers/Driver18/hcw18mlC.rom -> v4l-cx23418-dig.fw
diff --git a/Documentation/video4linux/extract_xc3028.pl b/Documentation/video4linux/extract_xc3028.pl
index cced8ac..2cb8160 100644
--- a/Documentation/video4linux/extract_xc3028.pl
@@ -10230,6 +13628,425 @@
write_le16(6500); # IF
write_le32(192); # Size
write_hunk(811128, 192);
+diff --git a/Documentation/vm/numa_memory_policy.txt b/Documentation/vm/numa_memory_policy.txt
+index dd49864..bad16d3 100644
+--- a/Documentation/vm/numa_memory_policy.txt
++++ b/Documentation/vm/numa_memory_policy.txt
+@@ -135,77 +135,58 @@ most general to most specific:
+
+ Components of Memory Policies
+
+- A Linux memory policy is a tuple consisting of a "mode" and an optional set
+- of nodes. The mode determine the behavior of the policy, while the
+- optional set of nodes can be viewed as the arguments to the behavior.
++ A Linux memory policy consists of a "mode", optional mode flags, and an
++ optional set of nodes. The mode determines the behavior of the policy,
++ the optional mode flags determine the behavior of the mode, and the
++ optional set of nodes can be viewed as the arguments to the policy
++ behavior.
+
+ Internally, memory policies are implemented by a reference counted
+ structure, struct mempolicy. Details of this structure will be discussed
+ in context, below, as required to explain the behavior.
+
+- Note: in some functions AND in the struct mempolicy itself, the mode
+- is called "policy". However, to avoid confusion with the policy tuple,
+- this document will continue to use the term "mode".
+-
+ Linux memory policy supports the following 4 behavioral modes:
+
+- Default Mode--MPOL_DEFAULT: The behavior specified by this mode is
+- context or scope dependent.
+-
+- As mentioned in the Policy Scope section above, during normal
+- system operation, the System Default Policy is hard coded to
+- contain the Default mode.
+-
+- In this context, default mode means "local" allocation--that is
+- attempt to allocate the page from the node associated with the cpu
+- where the fault occurs. If the "local" node has no memory, or the
+- node's memory can be exhausted [no free pages available], local
+- allocation will "fallback to"--attempt to allocate pages from--
+- "nearby" nodes, in order of increasing "distance".
++ Default Mode--MPOL_DEFAULT: This mode is only used in the memory
++ policy APIs. Internally, MPOL_DEFAULT is converted to the NULL
++ memory policy in all policy scopes. Any existing non-default policy
++ will simply be removed when MPOL_DEFAULT is specified. As a result,
++ MPOL_DEFAULT means "fall back to the next most specific policy scope."
+
+- Implementation detail -- subject to change: "Fallback" uses
+- a per node list of sibling nodes--called zonelists--built at
+- boot time, or when nodes or memory are added or removed from
+- the system [memory hotplug]. These per node zonelist are
+- constructed with nodes in order of increasing distance based
+- on information provided by the platform firmware.
++ For example, a NULL or default task policy will fall back to the
++ system default policy. A NULL or default vma policy will fall
++ back to the task policy.
+
+- When a task/process policy or a shared policy contains the Default
+- mode, this also means "local allocation", as described above.
++ When specified in one of the memory policy APIs, the Default mode
++ does not use the optional set of nodes.
+
+- In the context of a VMA, Default mode means "fall back to task
+- policy"--which may or may not specify Default mode. Thus, Default
+- mode can not be counted on to mean local allocation when used
+- on a non-shared region of the address space. However, see
+- MPOL_PREFERRED below.
+-
+- The Default mode does not use the optional set of nodes.
++ It is an error for the set of nodes specified for this policy to
++ be non-empty.
+
+ MPOL_BIND: This mode specifies that memory must come from the
+- set of nodes specified by the policy.
+-
+- The memory policy APIs do not specify an order in which the nodes
+- will be searched. However, unlike "local allocation", the Bind
+- policy does not consider the distance between the nodes. Rather,
+- allocations will fallback to the nodes specified by the policy in
+- order of numeric node id. Like everything in Linux, this is subject
+- to change.
++ set of nodes specified by the policy. Memory will be allocated from
++ the node in the set with sufficient free memory that is closest to
++ the node where the allocation takes place.
+
+ MPOL_PREFERRED: This mode specifies that the allocation should be
+ attempted from the single node specified in the policy. If that
+- allocation fails, the kernel will search other nodes, exactly as
+- it would for a local allocation that started at the preferred node
+- in increasing distance from the preferred node. "Local" allocation
+- policy can be viewed as a Preferred policy that starts at the node
++ allocation fails, the kernel will search other nodes, in order of
++ increasing distance from the preferred node based on information
++ provided by the platform firmware.
+ containing the cpu where the allocation takes place.
+
+ Internally, the Preferred policy uses a single node--the
+- preferred_node member of struct mempolicy. A "distinguished
+- value of this preferred_node, currently '-1', is interpreted
+- as "the node containing the cpu where the allocation takes
+- place"--local allocation. This is the way to specify
+- local allocation for a specific range of addresses--i.e. for
+- VMA policies.
++ preferred_node member of struct mempolicy. When the internal
++ mode flag MPOL_F_LOCAL is set, the preferred_node is ignored and
++ the policy is interpreted as local allocation. "Local" allocation
++ policy can be viewed as a Preferred policy that starts at the node
++ containing the cpu where the allocation takes place.
++
++ It is possible for the user to specify that local allocation is
++ always preferred by passing an empty nodemask with this mode.
++ If an empty nodemask is passed, the policy cannot use the
++ MPOL_F_STATIC_NODES or MPOL_F_RELATIVE_NODES flags described
++ below.
+
+ MPOL_INTERLEAVED: This mode specifies that page allocations be
+ interleaved, on a page granularity, across the nodes specified in
+@@ -231,6 +212,154 @@ Components of Memory Policies
+ the temporary interleaved system default policy works in this
+ mode.
+
++ Linux memory policy supports the following optional mode flags:
++
++ MPOL_F_STATIC_NODES: This flag specifies that the nodemask passed by
++ the user should not be remapped if the task or VMA's set of allowed
++ nodes changes after the memory policy has been defined.
++
++ Without this flag, anytime a mempolicy is rebound because of a
++ change in the set of allowed nodes, the node (Preferred) or
++ nodemask (Bind, Interleave) is remapped to the new set of
++ allowed nodes. This may result in nodes being used that were
++ previously undesired.
++
++ With this flag, if the user-specified nodes overlap with the
++ nodes allowed by the task's cpuset, then the memory policy is
++ applied to their intersection. If the two sets of nodes do not
++ overlap, the Default policy is used.
++
++ For example, consider a task that is attached to a cpuset with
++ mems 1-3 that sets an Interleave policy over the same set. If
++ the cpuset's mems change to 3-5, the Interleave will now occur
++ over nodes 3, 4, and 5. With this flag, however, since only node
++ 3 is allowed from the user's nodemask, the "interleave" only
++ occurs over that node. If no nodes from the user's nodemask are
++ now allowed, the Default behavior is used.
++
++ MPOL_F_STATIC_NODES cannot be combined with the
++ MPOL_F_RELATIVE_NODES flag. It also cannot be used for
++ MPOL_PREFERRED policies that were created with an empty nodemask
++ (local allocation).
++
++ MPOL_F_RELATIVE_NODES: This flag specifies that the nodemask passed
++ by the user will be mapped relative to the set of the task or VMA's
++ set of allowed nodes. The kernel stores the user-passed nodemask,
++ and if the allowed nodes changes, then that original nodemask will
++ be remapped relative to the new set of allowed nodes.
++
++ Without this flag (and without MPOL_F_STATIC_NODES), anytime a
++ mempolicy is rebound because of a change in the set of allowed
++ nodes, the node (Preferred) or nodemask (Bind, Interleave) is
++ remapped to the new set of allowed nodes. That remap may not
++ preserve the relative nature of the user's passed nodemask to its
++ set of allowed nodes upon successive rebinds: a nodemask of
++ 1,3,5 may be remapped to 7-9 and then to 1-3 if the set of
++ allowed nodes is restored to its original state.
++
++ With this flag, the remap is done so that the node numbers from
++ the user's passed nodemask are relative to the set of allowed
++ nodes. In other words, if nodes 0, 2, and 4 are set in the user's
++ nodemask, the policy will be effected over the first (and in the
++ Bind or Interleave case, the third and fifth) nodes in the set of
++ allowed nodes. The nodemask passed by the user represents nodes
++ relative to task or VMA's set of allowed nodes.
++
++ If the user's nodemask includes nodes that are outside the range
++ of the new set of allowed nodes (for example, node 5 is set in
++ the user's nodemask when the set of allowed nodes is only 0-3),
++ then the remap wraps around to the beginning of the nodemask and,
++ if not already set, sets the node in the mempolicy nodemask.
++
++ For example, consider a task that is attached to a cpuset with
++ mems 2-5 that sets an Interleave policy over the same set with
++ MPOL_F_RELATIVE_NODES. If the cpuset's mems change to 3-7, the
++ interleave now occurs over nodes 3,5-6. If the cpuset's mems
++ then change to 0,2-3,5, then the interleave occurs over nodes
++ 0,3,5.
++
++ Thanks to the consistent remapping, applications preparing
++ nodemasks to specify memory policies using this flag should
++ disregard their current, actual cpuset imposed memory placement
++ and prepare the nodemask as if they were always located on
++ memory nodes 0 to N-1, where N is the number of memory nodes the
++ policy is intended to manage. Let the kernel then remap to the
++ set of memory nodes allowed by the task's cpuset, as that may
++ change over time.
++
++ MPOL_F_RELATIVE_NODES cannot be combined with the
++ MPOL_F_STATIC_NODES flag. It also cannot be used for
++ MPOL_PREFERRED policies that were created with an empty nodemask
++ (local allocation).
++
++MEMORY POLICY REFERENCE COUNTING
++
++To resolve use/free races, struct mempolicy contains an atomic reference
++count field. Internal interfaces, mpol_get()/mpol_put() increment and
++decrement this reference count, respectively. mpol_put() will only free
++the structure back to the mempolicy kmem cache when the reference count
++goes to zero.
++
++When a new memory policy is allocated, it's reference count is initialized
++to '1', representing the reference held by the task that is installing the
++new policy. When a pointer to a memory policy structure is stored in another
++structure, another reference is added, as the task's reference will be dropped
++on completion of the policy installation.
++
++During run-time "usage" of the policy, we attempt to minimize atomic operations
++on the reference count, as this can lead to cache lines bouncing between cpus
++and NUMA nodes. "Usage" here means one of the following:
++
++1) querying of the policy, either by the task itself [using the get_mempolicy()
++ API discussed below] or by another task using the /proc/<pid>/numa_maps
++ interface.
++
++2) examination of the policy to determine the policy mode and associated node
++ or node lists, if any, for page allocation. This is considered a "hot
++ path". Note that for MPOL_BIND, the "usage" extends across the entire
++ allocation process, which may sleep during page reclaimation, because the
++ BIND policy nodemask is used, by reference, to filter ineligible nodes.
++
++We can avoid taking an extra reference during the usages listed above as
++follows:
++
++1) we never need to get/free the system default policy as this is never
++ changed nor freed, once the system is up and running.
++
++2) for querying the policy, we do not need to take an extra reference on the
++ target task's task policy nor vma policies because we always acquire the
++ task's mm's mmap_sem for read during the query. The set_mempolicy() and
++ mbind() APIs [see below] always acquire the mmap_sem for write when
++ installing or replacing task or vma policies. Thus, there is no possibility
++ of a task or thread freeing a policy while another task or thread is
++ querying it.
++
++3) Page allocation usage of task or vma policy occurs in the fault path where
++ we hold them mmap_sem for read. Again, because replacing the task or vma
++ policy requires that the mmap_sem be held for write, the policy can't be
++ freed out from under us while we're using it for page allocation.
++
++4) Shared policies require special consideration. One task can replace a
++ shared memory policy while another task, with a distinct mmap_sem, is
++ querying or allocating a page based on the policy. To resolve this
++ potential race, the shared policy infrastructure adds an extra reference
++ to the shared policy during lookup while holding a spin lock on the shared
++ policy management structure. This requires that we drop this extra
++ reference when we're finished "using" the policy. We must drop the
++ extra reference on shared policies in the same query/allocation paths
++ used for non-shared policies. For this reason, shared policies are marked
++ as such, and the extra reference is dropped "conditionally"--i.e., only
++ for shared policies.
++
++ Because of this extra reference counting, and because we must lookup
++ shared policies in a tree structure under spinlock, shared policies are
++ more expensive to use in the page allocation path. This is expecially
++ true for shared policies on shared memory regions shared by tasks running
++ on different NUMA nodes. This extra overhead can be avoided by always
++ falling back to task or system default policy for shared memory regions,
++ or by prefaulting the entire shared memory region into memory and locking
++ it down. However, this might not be appropriate for all applications.
++
+ MEMORY POLICY APIs
+
+ Linux supports 3 system calls for controlling memory policy. These APIS
+@@ -251,7 +380,9 @@ Set [Task] Memory Policy:
+ Set's the calling task's "task/process memory policy" to mode
+ specified by the 'mode' argument and the set of nodes defined
+ by 'nmask'. 'nmask' points to a bit mask of node ids containing
+- at least 'maxnode' ids.
++ at least 'maxnode' ids. Optional mode flags may be passed by
++ combining the 'mode' argument with the flag (for example:
++ MPOL_INTERLEAVE | MPOL_F_STATIC_NODES).
+
+ See the set_mempolicy(2) man page for more details
+
+@@ -303,29 +434,19 @@ MEMORY POLICIES AND CPUSETS
+ Memory policies work within cpusets as described above. For memory policies
+ that require a node or set of nodes, the nodes are restricted to the set of
+ nodes whose memories are allowed by the cpuset constraints. If the nodemask
+-specified for the policy contains nodes that are not allowed by the cpuset, or
+-the intersection of the set of nodes specified for the policy and the set of
+-nodes with memory is the empty set, the policy is considered invalid
+-and cannot be installed.
+-
+-The interaction of memory policies and cpusets can be problematic for a
+-couple of reasons:
+-
+-1) the memory policy APIs take physical node id's as arguments. As mentioned
+- above, it is illegal to specify nodes that are not allowed in the cpuset.
+- The application must query the allowed nodes using the get_mempolicy()
+- API with the MPOL_F_MEMS_ALLOWED flag to determine the allowed nodes and
+- restrict itself to those nodes. However, the resources available to a
+- cpuset can be changed by the system administrator, or a workload manager
+- application, at any time. So, a task may still get errors attempting to
+- specify policy nodes, and must query the allowed memories again.
+-
+-2) when tasks in two cpusets share access to a memory region, such as shared
+- memory segments created by shmget() of mmap() with the MAP_ANONYMOUS and
+- MAP_SHARED flags, and any of the tasks install shared policy on the region,
+- only nodes whose memories are allowed in both cpusets may be used in the
+- policies. Obtaining this information requires "stepping outside" the
+- memory policy APIs to use the cpuset information and requires that one
+- know in what cpusets other task might be attaching to the shared region.
+- Furthermore, if the cpusets' allowed memory sets are disjoint, "local"
+- allocation is the only valid policy.
++specified for the policy contains nodes that are not allowed by the cpuset and
++MPOL_F_RELATIVE_NODES is not used, the intersection of the set of nodes
++specified for the policy and the set of nodes with memory is used. If the
++result is the empty set, the policy is considered invalid and cannot be
++installed. If MPOL_F_RELATIVE_NODES is used, the policy's nodes are mapped
++onto and folded into the task's set of allowed nodes as previously described.
++
++The interaction of memory policies and cpusets can be problematic when tasks
++in two cpusets share access to a memory region, such as shared memory segments
++created by shmget() of mmap() with the MAP_ANONYMOUS and MAP_SHARED flags, and
++any of the tasks install shared policy on the region, only nodes whose
++memories are allowed in both cpusets may be used in the policies. Obtaining
++this information requires "stepping outside" the memory policy APIs to use the
++cpuset information and requires that one know in what cpusets other task might
++be attaching to the shared region. Furthermore, if the cpusets' allowed
++memory sets are disjoint, "local" allocation is the only valid policy.
+diff --git a/Documentation/vm/slabinfo.c b/Documentation/vm/slabinfo.c
+index 22d7e3e..d3ce295 100644
+--- a/Documentation/vm/slabinfo.c
++++ b/Documentation/vm/slabinfo.c
+@@ -31,7 +31,7 @@ struct slabinfo {
+ int hwcache_align, object_size, objs_per_slab;
+ int sanity_checks, slab_size, store_user, trace;
+ int order, poison, reclaim_account, red_zone;
+- unsigned long partial, objects, slabs;
++ unsigned long partial, objects, slabs, objects_partial, objects_total;
+ unsigned long alloc_fastpath, alloc_slowpath;
+ unsigned long free_fastpath, free_slowpath;
+ unsigned long free_frozen, free_add_partial, free_remove_partial;
+@@ -540,7 +540,8 @@ void slabcache(struct slabinfo *s)
+ return;
+
+ store_size(size_str, slab_size(s));
+- snprintf(dist_str, 40, "%lu/%lu/%d", s->slabs, s->partial, s->cpu_slabs);
++ snprintf(dist_str, 40, "%lu/%lu/%d", s->slabs - s->cpu_slabs,
++ s->partial, s->cpu_slabs);
+
+ if (!line++)
+ first_line();
+@@ -776,7 +777,6 @@ void totals(void)
+ unsigned long used;
+ unsigned long long wasted;
+ unsigned long long objwaste;
+- long long objects_in_partial_slabs;
+ unsigned long percentage_partial_slabs;
+ unsigned long percentage_partial_objs;
+
+@@ -790,18 +790,11 @@ void totals(void)
+ wasted = size - used;
+ objwaste = s->slab_size - s->object_size;
+
+- objects_in_partial_slabs = s->objects -
+- (s->slabs - s->partial - s ->cpu_slabs) *
+- s->objs_per_slab;
+-
+- if (objects_in_partial_slabs < 0)
+- objects_in_partial_slabs = 0;
+-
+ percentage_partial_slabs = s->partial * 100 / s->slabs;
+ if (percentage_partial_slabs > 100)
+ percentage_partial_slabs = 100;
+
+- percentage_partial_objs = objects_in_partial_slabs * 100
++ percentage_partial_objs = s->objects_partial * 100
+ / s->objects;
+
+ if (percentage_partial_objs > 100)
+@@ -823,8 +816,8 @@ void totals(void)
+ min_objects = s->objects;
+ if (used < min_used)
+ min_used = used;
+- if (objects_in_partial_slabs < min_partobj)
+- min_partobj = objects_in_partial_slabs;
++ if (s->objects_partial < min_partobj)
++ min_partobj = s->objects_partial;
+ if (percentage_partial_slabs < min_ppart)
+ min_ppart = percentage_partial_slabs;
+ if (percentage_partial_objs < min_ppartobj)
+@@ -848,8 +841,8 @@ void totals(void)
+ max_objects = s->objects;
+ if (used > max_used)
+ max_used = used;
+- if (objects_in_partial_slabs > max_partobj)
+- max_partobj = objects_in_partial_slabs;
++ if (s->objects_partial > max_partobj)
++ max_partobj = s->objects_partial;
+ if (percentage_partial_slabs > max_ppart)
+ max_ppart = percentage_partial_slabs;
+ if (percentage_partial_objs > max_ppartobj)
+@@ -864,7 +857,7 @@ void totals(void)
+
+ total_objects += s->objects;
+ total_used += used;
+- total_partobj += objects_in_partial_slabs;
++ total_partobj += s->objects_partial;
+ total_ppart += percentage_partial_slabs;
+ total_ppartobj += percentage_partial_objs;
+
+@@ -1160,6 +1153,8 @@ void read_slab_dir(void)
+ slab->hwcache_align = get_obj("hwcache_align");
+ slab->object_size = get_obj("object_size");
+ slab->objects = get_obj("objects");
++ slab->objects_partial = get_obj("objects_partial");
++ slab->objects_total = get_obj("objects_total");
+ slab->objs_per_slab = get_obj("objs_per_slab");
+ slab->order = get_obj("order");
+ slab->partial = get_obj("partial");
diff --git a/Documentation/x86/pat.txt b/Documentation/x86/pat.txt
new file mode 100644
index 0000000..17965f9
@@ -10349,8 +14166,110 @@
+ Do not use GB pages for kernel direct mappings.
+ gbpages
+ Use GB pages for kernel direct mappings.
+diff --git a/Kbuild b/Kbuild
+index 1570d24..32f19c5 100644
+--- a/Kbuild
++++ b/Kbuild
+@@ -1,26 +1,61 @@
+ #
+ # Kbuild for top-level directory of the kernel
+ # This file takes care of the following:
+-# 1) Generate asm-offsets.h
+-# 2) Check for missing system calls
++# 1) Generate bounds.h
++# 2) Generate asm-offsets.h (may need bounds.h)
++# 3) Check for missing system calls
+
+ #####
+-# 1) Generate asm-offsets.h
++# 1) Generate bounds.h
++
++bounds-file := include/linux/bounds.h
++
++always := $(bounds-file)
++targets := $(bounds-file) kernel/bounds.s
++
++quiet_cmd_bounds = GEN $@
++define cmd_bounds
++ (set -e; \
++ echo "#ifndef __LINUX_BOUNDS_H__"; \
++ echo "#define __LINUX_BOUNDS_H__"; \
++ echo "/*"; \
++ echo " * DO NOT MODIFY."; \
++ echo " *"; \
++ echo " * This file was generated by Kbuild"; \
++ echo " *"; \
++ echo " */"; \
++ echo ""; \
++ sed -ne $(sed-y) $<; \
++ echo ""; \
++ echo "#endif" ) > $@
++endef
++
++# We use internal kbuild rules to avoid the "is up to date" message from make
++kernel/bounds.s: kernel/bounds.c FORCE
++ $(Q)mkdir -p $(dir $@)
++ $(call if_changed_dep,cc_s_c)
++
++$(obj)/$(bounds-file): kernel/bounds.s Kbuild
++ $(Q)mkdir -p $(dir $@)
++ $(call cmd,bounds)
++
++#####
++# 2) Generate asm-offsets.h
+ #
+
+ offsets-file := include/asm-$(SRCARCH)/asm-offsets.h
+
+-always := $(offsets-file)
+-targets := $(offsets-file)
++always += $(offsets-file)
++targets += $(offsets-file)
+ targets += arch/$(SRCARCH)/kernel/asm-offsets.s
+-clean-files := $(addprefix $(objtree)/,$(targets))
++
+
+ # Default sed regexp - multiline due to syntax constraints
+ define sed-y
+- "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"
++ "/^->/{s:->#\(.*\):/* \1 */:; \
++ s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
++ s:->::; p;}"
+ endef
+-# Override default regexp for specific architectures
+-sed-$(CONFIG_MIPS) := "/^@@@/{s/^@@@//; s/ \#.*\$$//; p;}"
+
+ quiet_cmd_offsets = GEN $@
+ define cmd_offsets
+@@ -40,7 +75,8 @@ define cmd_offsets
+ endef
+
+ # We use internal kbuild rules to avoid the "is up to date" message from make
+-arch/$(SRCARCH)/kernel/asm-offsets.s: arch/$(SRCARCH)/kernel/asm-offsets.c FORCE
++arch/$(SRCARCH)/kernel/asm-offsets.s: arch/$(SRCARCH)/kernel/asm-offsets.c \
++ $(obj)/$(bounds-file) FORCE
+ $(Q)mkdir -p $(dir $@)
+ $(call if_changed_dep,cc_s_c)
+
+@@ -49,7 +85,7 @@ $(obj)/$(offsets-file): arch/$(SRCARCH)/kernel/asm-offsets.s Kbuild
+ $(call cmd,offsets)
+
+ #####
+-# 2) Check for missing system calls
++# 3) Check for missing system calls
+ #
+
+ quiet_cmd_syscalls = CALL $<
+@@ -58,3 +94,7 @@ quiet_cmd_syscalls = CALL $<
+ PHONY += missing-syscalls
+ missing-syscalls: scripts/checksyscalls.sh FORCE
+ $(call cmd,syscalls)
++
++# Delete all targets during make clean
++clean-files := $(addprefix $(objtree)/,$(targets))
++
diff --git a/MAINTAINERS b/MAINTAINERS
-index e467758..a942f38 100644
+index e467758..c3a533d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -486,6 +486,12 @@ M: kernel at wantstofly.org
@@ -10378,7 +14297,24 @@
ATL1 ETHERNET DRIVER
P: Jay Cliburn
M: jcliburn at gmail.com
-@@ -840,15 +851,6 @@ L: linux-wireless at vger.kernel.org
+@@ -741,11 +752,13 @@ W: http://atmelwlandriver.sourceforge.net/
+ S: Maintained
+
+ AUDIT SUBSYSTEM
+-P: David Woodhouse
+-M: dwmw2 at infradead.org
++P: Al Viro
++M: viro at zeniv.linux.org.uk
++P: Eric Paris
++M: eparis at redhat.com
+ L: linux-audit at redhat.com (subscribers-only)
+ W: http://people.redhat.com/sgrubb/audit/
+-T: git kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git
++T: git git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current.git
+ S: Maintained
+
+ AUXILIARY DISPLAY DRIVERS
+@@ -840,15 +853,6 @@ L: linux-wireless at vger.kernel.org
W: http://linuxwireless.org/en/users/Drivers/b43
S: Maintained
@@ -10394,7 +14330,16 @@
BEFS FILE SYSTEM
P: Sergey S. Kostyliov
M: rathamahata at php4.ru
-@@ -1104,6 +1106,12 @@ M: kernel at wantstofly.org
+@@ -1035,7 +1039,7 @@ P: Urs Thuermann
+ M: urs.thuermann at volkswagen.de
+ P: Oliver Hartkopp
+ M: oliver.hartkopp at volkswagen.de
+-L: socketcan-core at lists.berlios.de
++L: socketcan-core at lists.berlios.de (subscribers-only)
+ W: http://developer.berlios.de/projects/socketcan/
+ S: Maintained
+
+@@ -1104,6 +1108,12 @@ M: kernel at wantstofly.org
L: linux-usb at vger.kernel.org
S: Maintained
@@ -10407,7 +14352,21 @@
CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER
P: Cirrus Logic Corporation (kernel 2.2 driver)
M: Cirrus Logic Corporation, Thomas Woller <twoller at crystal.cirrus.com>
-@@ -1626,6 +1634,12 @@ L: linuxppc-dev at ozlabs.org
+@@ -1523,6 +1533,13 @@ L: bluesmoke-devel at lists.sourceforge.net
+ W: bluesmoke.sourceforge.net
+ S: Maintained
+
++EEEPC LAPTOP EXTRAS DRIVER
++P: Corentin Chary
++M: corentincj at iksaif.net
++L: acpi4asus-user at lists.sourceforge.net
++W: http://sourceforge.net/projects/acpi4asus
++S: Maintained
++
+ EEPRO100 NETWORK DRIVER
+ P: Andrey V. Savochkin
+ M: saw at saw.sw.com.sg
+@@ -1626,6 +1643,12 @@ L: linuxppc-dev at ozlabs.org
L: netdev at vger.kernel.org
S: Maintained
@@ -10420,7 +14379,7 @@
FREESCALE HIGHSPEED USB DEVICE DRIVER
P: Li Yang
M: leoli at freescale.com
-@@ -1640,6 +1654,19 @@ L: netdev at vger.kernel.org
+@@ -1640,6 +1663,19 @@ L: netdev at vger.kernel.org
L: linuxppc-dev at ozlabs.org
S: Maintained
@@ -10440,7 +14399,38 @@
FILE LOCKING (flock() and fcntl()/lockf())
P: Matthew Wilcox
M: matthew at wil.cx
-@@ -2319,6 +2346,12 @@ L: linux-kernel at vger.kernel.org
+@@ -2302,6 +2338,13 @@ L: kvm-devel at lists.sourceforge.net
+ W: kvm.sourceforge.net
+ S: Supported
+
++KERNEL VIRTUAL MACHINE (KVM) FOR POWERPC
++P: Hollis Blanchard
++M: hollisb at us.ibm.com
++L: kvm-ppc-devel at lists.sourceforge.net
++W: kvm.sourceforge.net
++S: Supported
++
+ KERNEL VIRTUAL MACHINE For Itanium(KVM/IA64)
+ P: Anthony Xu
+ M: anthony.xu at intel.com
+@@ -2311,6 +2354,16 @@ L: kvm-ia64-devel at lists.sourceforge.net
+ W: kvm.sourceforge.net
+ S: Supported
+
++KERNEL VIRTUAL MACHINE for s390 (KVM/s390)
++P: Carsten Otte
++M: cotte at de.ibm.com
++P: Christian Borntraeger
++M: borntraeger at de.ibm.com
++M: linux390 at de.ibm.com
++L: linux-s390 at vger.kernel.org
++W: http://www.ibm.com/developerworks/linux/linux390/
++S: Supported
++
+ KEXEC
+ P: Eric Biederman
+ M: ebiederm at xmission.com
+@@ -2319,6 +2372,12 @@ L: linux-kernel at vger.kernel.org
L: kexec at lists.infradead.org
S: Maintained
@@ -10453,7 +14443,7 @@
KPROBES
P: Ananth N Mavinakayanahalli
M: ananth at in.ibm.com
-@@ -2550,12 +2583,10 @@ W: http://www.tazenda.demon.co.uk/phil/linux-hp
+@@ -2550,12 +2609,10 @@ W: http://www.tazenda.demon.co.uk/phil/linux-hp
S: Maintained
MAC80211
@@ -10468,7 +14458,25 @@
L: linux-wireless at vger.kernel.org
W: http://linuxwireless.org/
T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
-@@ -2944,8 +2975,9 @@ P: Mark Fasheh
+@@ -2646,7 +2703,7 @@ P: David Howells
+ M: dhowells at redhat.com
+ P: Koichi Yasutake
+ M: yasutake.koichi at jp.panasonic.com
+-L: linux-am33-list at redhat.com
++L: linux-am33-list at redhat.com (moderated for non-subscribers)
+ W: ftp://ftp.redhat.com/pub/redhat/gnupro/AM33/
+ S: Maintained
+
+@@ -2709,7 +2766,7 @@ M: rubini at ipvvis.unipv.it
+ L: linux-kernel at vger.kernel.org
+ S: Maintained
+
+-MOXA SMARTIO/INDUSTIO SERIAL CARD (MXSER 2.0)
++MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
+ P: Jiri Slaby
+ M: jirislaby at gmail.com
+ L: linux-kernel at vger.kernel.org
+@@ -2944,8 +3001,9 @@ P: Mark Fasheh
M: mfasheh at suse.com
P: Joel Becker
M: joel.becker at oracle.com
@@ -10479,7 +14487,7 @@
S: Supported
OMNIKEY CARDMAN 4000 DRIVER
-@@ -3061,11 +3093,10 @@ L: linux-pci at atrey.karlin.mff.cuni.cz
+@@ -3061,11 +3119,11 @@ L: linux-pci at atrey.karlin.mff.cuni.cz
S: Supported
PCI SUBSYSTEM
@@ -10490,10 +14498,11 @@
L: linux-kernel at vger.kernel.org
L: linux-pci at atrey.karlin.mff.cuni.cz
-T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
++T: git kernel.org:/pub/scm/linux/kernel/git/jbarnes/pci-2.6.git
S: Supported
PCI HOTPLUG CORE
-@@ -3472,7 +3503,7 @@ P: Vlad Yasevich
+@@ -3472,7 +3530,7 @@ P: Vlad Yasevich
M: vladislav.yasevich at hp.com
P: Sridhar Samudrala
M: sri at us.ibm.com
@@ -10502,7 +14511,21 @@
W: http://lksctp.sourceforge.net
S: Supported
-@@ -3606,11 +3637,10 @@ M: mhoffman at lightlink.com
+@@ -3526,6 +3584,13 @@ M: pfg at sgi.com
+ L: linux-ia64 at vger.kernel.org
+ S: Supported
+
++SFC NETWORK DRIVER
++P: Steve Hodgson
++P: Ben Hutchings
++P: Robert Stonehouse
++M: linux-net-drivers at solarflare.com
++S: Supported
++
+ SGI VISUAL WORKSTATION 320 AND 540
+ P: Andrey Panin
+ M: pazke at donpac.ru
+@@ -3606,11 +3671,10 @@ M: mhoffman at lightlink.com
L: lm-sensors at lm-sensors.org
S: Maintained
@@ -10518,7 +14541,197 @@
SOFTWARE RAID (Multiple Disks) SUPPORT
P: Ingo Molnar
-@@ -4351,6 +4381,16 @@ L: linux-wireless at vger.kernel.org
+@@ -3693,42 +3757,6 @@ M: chrisw at sous-sol.org
+ L: stable at kernel.org
+ S: Maintained
+
+-TPM DEVICE DRIVER
+-P: Kylene Hall
+-M: tpmdd-devel at lists.sourceforge.net
+-W: http://tpmdd.sourceforge.net
+-P: Marcel Selhorst
+-M: tpm at selhorst.net
+-W: http://www.prosec.rub.de/tpm/
+-L: tpmdd-devel at lists.sourceforge.net
+-S: Maintained
+-
+-Telecom Clock Driver for MCPL0010
+-P: Mark Gross
+-M: mark.gross at intel.com
+-S: Supported
+-
+-TENSILICA XTENSA PORT (xtensa):
+-P: Chris Zankel
+-M: chris at zankel.net
+-S: Maintained
+-
+-THINKPAD ACPI EXTRAS DRIVER
+-P: Henrique de Moraes Holschuh
+-M: ibm-acpi at hmh.eng.br
+-L: ibm-acpi-devel at lists.sourceforge.net
+-W: http://ibm-acpi.sourceforge.net
+-W: http://thinkwiki.org/wiki/Ibm-acpi
+-T: git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
+-S: Maintained
+-
+-UltraSPARC (sparc64):
+-P: David S. Miller
+-M: davem at davemloft.net
+-L: sparclinux at vger.kernel.org
+-T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git
+-S: Maintained
+-
+ SHARP LH SUPPORT (LH7952X & LH7A40X)
+ P: Marc Singer
+ M: elf at buici.com
+@@ -3825,6 +3853,12 @@ P: Christoph Hellwig
+ M: hch at infradead.org
+ S: Maintained
+
++TASKSTATS STATISTICS INTERFACE
++P: Shailabh Nagar
++M: nagar at watson.ibm.com
++L: linux-kernel at vger.kernel.org
++S: Maintained
++
+ TC CLASSIFIER
+ P: Jamal Hadi Salim
+ M: hadi at cyberus.ca
+@@ -3847,6 +3881,25 @@ M: andy at greyhouse.net
+ L: netdev at vger.kernel.org
+ S: Supported
+
++Telecom Clock Driver for MCPL0010
++P: Mark Gross
++M: mark.gross at intel.com
++S: Supported
++
++TENSILICA XTENSA PORT (xtensa):
++P: Chris Zankel
++M: chris at zankel.net
++S: Maintained
++
++THINKPAD ACPI EXTRAS DRIVER
++P: Henrique de Moraes Holschuh
++M: ibm-acpi at hmh.eng.br
++L: ibm-acpi-devel at lists.sourceforge.net
++W: http://ibm-acpi.sourceforge.net
++W: http://thinkwiki.org/wiki/Ibm-acpi
++T: git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
++S: Maintained
++
+ TI FLASH MEDIA INTERFACE DRIVER
+ P: Alex Dubov
+ M: oakad at yahoo.com
+@@ -3864,12 +3917,6 @@ P: Deepak Saxena
+ M: dsaxena at plexity.net
+ S: Maintained
+
+-TASKSTATS STATISTICS INTERFACE
+-P: Shailabh Nagar
+-M: nagar at watson.ibm.com
+-L: linux-kernel at vger.kernel.org
+-S: Maintained
+-
+ TIPC NETWORK LAYER
+ P: Per Liden
+ M: per.liden at ericsson.com
+@@ -3903,6 +3950,16 @@ L: tlinux-users at tce.toshiba-dme.co.jp
+ W: http://www.buzzard.org.uk/toshiba/
+ S: Maintained
+
++TPM DEVICE DRIVER
++P: Kylene Hall
++M: tpmdd-devel at lists.sourceforge.net
++W: http://tpmdd.sourceforge.net
++P: Marcel Selhorst
++M: tpm at selhorst.net
++W: http://www.prosec.rub.de/tpm/
++L: tpmdd-devel at lists.sourceforge.net
++S: Maintained
++
+ TRIDENT 4DWAVE/SIS 7018 PCI AUDIO CORE
+ P: Muli Ben-Yehuda
+ M: mulix at mulix.org
+@@ -3915,6 +3972,12 @@ M: trivial at kernel.org
+ L: linux-kernel at vger.kernel.org
+ S: Maintained
+
++TTY LAYER
++P: Alan Cox
++M: alan at lxorguk.ukuu.org.uk
++L: linux-kernel at vger.kernel.org
++S: Maintained
++
+ TULIP NETWORK DRIVERS
+ P: Grant Grundler
+ M: grundler at parisc-linux.org
+@@ -4083,6 +4146,20 @@ L: linux-usb at vger.kernel.org
+ W: http://www.chello.nl/~j.vreeken/se401/
+ S: Maintained
+
++USB SERIAL BELKIN F5U103 DRIVER
++P: William Greathouse
++M: wgreathouse at smva.com
++L: linux-usb at vger.kernel.org
++S: Maintained
++
++USB SERIAL CYPRESS M8 DRIVER
++P: Lonnie Mendez
++M: dignome at gmail.com
++L: linux-usb at vger.kernel.org
++S: Maintained
++W: http://geocities.com/i0xox0i
++W: http://firstlight.net/cvs
++
+ USB SERIAL CYBERJACK DRIVER
+ P: Matthias Bruestle and Harald Welte
+ M: support at reiner-sct.com
+@@ -4102,20 +4179,6 @@ M: gregkh at suse.de
+ L: linux-usb at vger.kernel.org
+ S: Supported
+
+-USB SERIAL BELKIN F5U103 DRIVER
+-P: William Greathouse
+-M: wgreathouse at smva.com
+-L: linux-usb at vger.kernel.org
+-S: Maintained
+-
+-USB SERIAL CYPRESS M8 DRIVER
+-P: Lonnie Mendez
+-M: dignome at gmail.com
+-L: linux-usb at vger.kernel.org
+-S: Maintained
+-W: http://geocities.com/i0xox0i
+-W: http://firstlight.net/cvs
+-
+ USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER
+ P: Gary Brubaker
+ M: xavyer at ix.netcom.com
+@@ -4218,7 +4281,7 @@ M: gregkh at suse.de
+ L: linux-kernel at vger.kernel.org
+ S: Maintained
+
+-FAT/VFAT/MSDOS FILESYSTEM:
++VFAT/FAT/MSDOS FILESYSTEM:
+ P: OGAWA Hirofumi
+ M: hirofumi at mail.parknet.co.jp
+ L: linux-kernel at vger.kernel.org
+@@ -4263,6 +4326,13 @@ M: dushistov at mail.ru
+ L: linux-kernel at vger.kernel.org
+ S: Maintained
+
++UltraSPARC (sparc64):
++P: David S. Miller
++M: davem at davemloft.net
++L: sparclinux at vger.kernel.org
++T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git
++S: Maintained
++
+ USB DIAMOND RIO500 DRIVER
+ P: Cesar Miquel
+ M: miquel at df.uba.ar
+@@ -4351,6 +4421,16 @@ L: linux-wireless at vger.kernel.org
W: http://oops.ghostprotocols.net:81/blog
S: Maintained
@@ -10536,7 +14749,7 @@
P: Henner Eisen
M: eis at baty.hanse.de
diff --git a/Makefile b/Makefile
-index 39516bf..cbd79f3 100644
+index 39516bf..cb3bb89 100644
--- a/Makefile
+++ b/Makefile
@@ -507,6 +507,10 @@ else
@@ -10550,7 +14763,62 @@
# 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
+@@ -1170,8 +1174,10 @@ rpm: include/config/kernel.release FORCE
+ # Brief documentation of the typical targets used
+ # ---------------------------------------------------------------------------
+
+-boards := $(wildcard $(srctree)/arch/$(ARCH)/configs/*_defconfig)
++boards := $(wildcard $(srctree)/arch/$(SRCARCH)/configs/*_defconfig)
+ boards := $(notdir $(boards))
++board-dirs := $(dir $(wildcard $(srctree)/arch/$(SRCARCH)/configs/*/*_defconfig))
++board-dirs := $(sort $(notdir $(board-dirs:/=)))
+
+ help:
+ @echo 'Cleaning targets:'
+@@ -1217,14 +1223,19 @@ help:
+ @echo 'Documentation targets:'
+ @$(MAKE) -f $(srctree)/Documentation/DocBook/Makefile dochelp
+ @echo ''
+- @echo 'Architecture specific targets ($(ARCH)):'
++ @echo 'Architecture specific targets ($(SRCARCH)):'
+ @$(if $(archhelp),$(archhelp),\
+- echo ' No architecture specific help defined for $(ARCH)')
++ echo ' No architecture specific help defined for $(SRCARCH)')
+ @echo ''
+ @$(if $(boards), \
+ $(foreach b, $(boards), \
+ printf " %-24s - Build for %s\\n" $(b) $(subst _defconfig,,$(b));) \
+ echo '')
++ @$(if $(board-dirs), \
++ $(foreach b, $(board-dirs), \
++ printf " %-16s - Show %s-specific targets\\n" help-$(b) $(b);) \
++ printf " %-16s - Show all of the above\\n" help-boards; \
++ echo '')
+
+ @echo ' make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build'
+ @echo ' make V=2 [targets] 2 => give reason for rebuild of target'
+@@ -1236,6 +1247,20 @@ help:
+ @echo 'For further info see the ./README file'
+
+
++help-board-dirs := $(addprefix help-,$(board-dirs))
++
++help-boards: $(help-board-dirs)
++
++boards-per-dir = $(notdir $(wildcard $(srctree)/arch/$(SRCARCH)/configs/$*/*_defconfig))
++
++$(help-board-dirs): help-%:
++ @echo 'Architecture specific targets ($(SRCARCH) $*):'
++ @$(if $(boards-per-dir), \
++ $(foreach b, $(boards-per-dir), \
++ printf " %-24s - Build for %s\\n" $*/$(b) $(subst _defconfig,,$(b));) \
++ echo '')
++
++
+ # Documentation targets
+ # ---------------------------------------------------------------------------
+ %docs: scripts_basic FORCE
+@@ -1396,7 +1421,7 @@ define xtags
$(all-kconfigs) | xargs $1 -a \
--langdef=kconfig \
--language-force=kconfig \
@@ -10559,7 +14827,7 @@
$(all-defconfigs) | xargs -r $1 -a \
--langdef=dotconfig \
--language-force=dotconfig \
-@@ -1404,7 +1408,7 @@ define xtags
+@@ -1404,7 +1429,7 @@ define xtags
elif $1 --version 2>&1 | grep -iq emacs; then \
$(all-sources) | xargs $1 -a; \
$(all-kconfigs) | xargs $1 -a \
@@ -10568,7 +14836,7 @@
$(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)))
+@@ -1538,8 +1563,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)
@@ -10578,6 +14846,17 @@
quiet_cmd_depmod = DEPMOD $(KERNELRELEASE)
cmd_depmod = \
if [ -r System.map -a -x $(DEPMOD) ]; then \
+diff --git a/arch/Kconfig b/arch/Kconfig
+index 694c9af..3ea332b 100644
+--- a/arch/Kconfig
++++ b/arch/Kconfig
+@@ -36,3 +36,6 @@ config HAVE_KPROBES
+
+ config HAVE_KRETPROBES
+ def_bool n
++
++config HAVE_DMA_ATTRS
++ def_bool n
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index dccf052..ac706c1 100644
--- a/arch/alpha/kernel/Makefile
@@ -10611,6 +14890,233 @@
/*
* SMP-specific symbols.
*/
+diff --git a/arch/alpha/kernel/asm-offsets.c b/arch/alpha/kernel/asm-offsets.c
+index 6c56c75..4b18cd9 100644
+--- a/arch/alpha/kernel/asm-offsets.c
++++ b/arch/alpha/kernel/asm-offsets.c
+@@ -8,13 +8,9 @@
+ #include <linux/stddef.h>
+ #include <linux/sched.h>
+ #include <linux/ptrace.h>
++#include <linux/kbuild.h>
+ #include <asm/io.h>
+
+-#define DEFINE(sym, val) \
+- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+-
+-#define BLANK() asm volatile("\n->" : : )
+-
+ void foo(void)
+ {
+ DEFINE(TI_TASK, offsetof(struct thread_info, task));
+diff --git a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c
+index f10d2ed..b04f1fe 100644
+--- a/arch/alpha/kernel/core_marvel.c
++++ b/arch/alpha/kernel/core_marvel.c
+@@ -994,7 +994,7 @@ marvel_agp_configure(alpha_agp_info *agp)
+ * rate, but warn the user.
+ */
+ printk("%s: unknown PLL setting RNGB=%lx (PLL6_CTL=%016lx)\n",
+- __FUNCTION__, IO7_PLL_RNGB(agp_pll), agp_pll);
++ __func__, IO7_PLL_RNGB(agp_pll), agp_pll);
+ break;
+ }
+
+@@ -1044,13 +1044,13 @@ marvel_agp_translate(alpha_agp_info *agp, dma_addr_t addr)
+
+ if (addr < agp->aperture.bus_base ||
+ addr >= agp->aperture.bus_base + agp->aperture.size) {
+- printk("%s: addr out of range\n", __FUNCTION__);
++ printk("%s: addr out of range\n", __func__);
+ return -EINVAL;
+ }
+
+ pte = aper->arena->ptes[baddr >> PAGE_SHIFT];
+ if (!(pte & 1)) {
+- printk("%s: pte not valid\n", __FUNCTION__);
++ printk("%s: pte not valid\n", __func__);
+ return -EINVAL;
+ }
+ return (pte >> 1) << PAGE_SHIFT;
+diff --git a/arch/alpha/kernel/core_t2.c b/arch/alpha/kernel/core_t2.c
+index f5ca525..c075029 100644
+--- a/arch/alpha/kernel/core_t2.c
++++ b/arch/alpha/kernel/core_t2.c
+@@ -336,10 +336,7 @@ t2_direct_map_window1(unsigned long base, unsigned long length)
+
+ #if DEBUG_PRINT_FINAL_SETTINGS
+ printk("%s: setting WBASE1=0x%lx WMASK1=0x%lx TBASE1=0x%lx\n",
+- __FUNCTION__,
+- *(vulp)T2_WBASE1,
+- *(vulp)T2_WMASK1,
+- *(vulp)T2_TBASE1);
++ __func__, *(vulp)T2_WBASE1, *(vulp)T2_WMASK1, *(vulp)T2_TBASE1);
+ #endif
+ }
+
+@@ -366,10 +363,7 @@ t2_sg_map_window2(struct pci_controller *hose,
+
+ #if DEBUG_PRINT_FINAL_SETTINGS
+ printk("%s: setting WBASE2=0x%lx WMASK2=0x%lx TBASE2=0x%lx\n",
+- __FUNCTION__,
+- *(vulp)T2_WBASE2,
+- *(vulp)T2_WMASK2,
+- *(vulp)T2_TBASE2);
++ __func__, *(vulp)T2_WBASE2, *(vulp)T2_WMASK2, *(vulp)T2_TBASE2);
+ #endif
+ }
+
+@@ -377,15 +371,15 @@ static void __init
+ t2_save_configuration(void)
+ {
+ #if DEBUG_PRINT_INITIAL_SETTINGS
+- printk("%s: HAE_1 was 0x%lx\n", __FUNCTION__, srm_hae); /* HW is 0 */
+- printk("%s: HAE_2 was 0x%lx\n", __FUNCTION__, *(vulp)T2_HAE_2);
+- printk("%s: HAE_3 was 0x%lx\n", __FUNCTION__, *(vulp)T2_HAE_3);
+- printk("%s: HAE_4 was 0x%lx\n", __FUNCTION__, *(vulp)T2_HAE_4);
+- printk("%s: HBASE was 0x%lx\n", __FUNCTION__, *(vulp)T2_HBASE);
++ printk("%s: HAE_1 was 0x%lx\n", __func__, srm_hae); /* HW is 0 */
++ printk("%s: HAE_2 was 0x%lx\n", __func__, *(vulp)T2_HAE_2);
++ printk("%s: HAE_3 was 0x%lx\n", __func__, *(vulp)T2_HAE_3);
++ printk("%s: HAE_4 was 0x%lx\n", __func__, *(vulp)T2_HAE_4);
++ printk("%s: HBASE was 0x%lx\n", __func__, *(vulp)T2_HBASE);
+
+- printk("%s: WBASE1=0x%lx WMASK1=0x%lx TBASE1=0x%lx\n", __FUNCTION__,
++ printk("%s: WBASE1=0x%lx WMASK1=0x%lx TBASE1=0x%lx\n", __func__,
+ *(vulp)T2_WBASE1, *(vulp)T2_WMASK1, *(vulp)T2_TBASE1);
+- printk("%s: WBASE2=0x%lx WMASK2=0x%lx TBASE2=0x%lx\n", __FUNCTION__,
++ printk("%s: WBASE2=0x%lx WMASK2=0x%lx TBASE2=0x%lx\n", __func__,
+ *(vulp)T2_WBASE2, *(vulp)T2_WMASK2, *(vulp)T2_TBASE2);
+ #endif
+
+diff --git a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c
+index 8193266..319fcb7 100644
+--- a/arch/alpha/kernel/core_titan.c
++++ b/arch/alpha/kernel/core_titan.c
+@@ -365,21 +365,21 @@ void __init
+ titan_init_arch(void)
+ {
+ #if 0
+- printk("%s: titan_init_arch()\n", __FUNCTION__);
+- printk("%s: CChip registers:\n", __FUNCTION__);
+- printk("%s: CSR_CSC 0x%lx\n", __FUNCTION__, TITAN_cchip->csc.csr);
+- printk("%s: CSR_MTR 0x%lx\n", __FUNCTION__, TITAN_cchip->mtr.csr);
+- printk("%s: CSR_MISC 0x%lx\n", __FUNCTION__, TITAN_cchip->misc.csr);
+- printk("%s: CSR_DIM0 0x%lx\n", __FUNCTION__, TITAN_cchip->dim0.csr);
+- printk("%s: CSR_DIM1 0x%lx\n", __FUNCTION__, TITAN_cchip->dim1.csr);
+- printk("%s: CSR_DIR0 0x%lx\n", __FUNCTION__, TITAN_cchip->dir0.csr);
+- printk("%s: CSR_DIR1 0x%lx\n", __FUNCTION__, TITAN_cchip->dir1.csr);
+- printk("%s: CSR_DRIR 0x%lx\n", __FUNCTION__, TITAN_cchip->drir.csr);
+-
+- printk("%s: DChip registers:\n", __FUNCTION__);
+- printk("%s: CSR_DSC 0x%lx\n", __FUNCTION__, TITAN_dchip->dsc.csr);
+- printk("%s: CSR_STR 0x%lx\n", __FUNCTION__, TITAN_dchip->str.csr);
+- printk("%s: CSR_DREV 0x%lx\n", __FUNCTION__, TITAN_dchip->drev.csr);
++ printk("%s: titan_init_arch()\n", __func__);
++ printk("%s: CChip registers:\n", __func__);
++ printk("%s: CSR_CSC 0x%lx\n", __func__, TITAN_cchip->csc.csr);
++ printk("%s: CSR_MTR 0x%lx\n", __func__, TITAN_cchip->mtr.csr);
++ printk("%s: CSR_MISC 0x%lx\n", __func__, TITAN_cchip->misc.csr);
++ printk("%s: CSR_DIM0 0x%lx\n", __func__, TITAN_cchip->dim0.csr);
++ printk("%s: CSR_DIM1 0x%lx\n", __func__, TITAN_cchip->dim1.csr);
++ printk("%s: CSR_DIR0 0x%lx\n", __func__, TITAN_cchip->dir0.csr);
++ printk("%s: CSR_DIR1 0x%lx\n", __func__, TITAN_cchip->dir1.csr);
++ printk("%s: CSR_DRIR 0x%lx\n", __func__, TITAN_cchip->drir.csr);
++
++ printk("%s: DChip registers:\n", __func__);
++ printk("%s: CSR_DSC 0x%lx\n", __func__, TITAN_dchip->dsc.csr);
++ printk("%s: CSR_STR 0x%lx\n", __func__, TITAN_dchip->str.csr);
++ printk("%s: CSR_DREV 0x%lx\n", __func__, TITAN_dchip->drev.csr);
+ #endif
+
+ boot_cpuid = __hard_smp_processor_id();
+@@ -700,13 +700,13 @@ titan_agp_translate(alpha_agp_info *agp, dma_addr_t addr)
+
+ if (addr < agp->aperture.bus_base ||
+ addr >= agp->aperture.bus_base + agp->aperture.size) {
+- printk("%s: addr out of range\n", __FUNCTION__);
++ printk("%s: addr out of range\n", __func__);
+ return -EINVAL;
+ }
+
+ pte = aper->arena->ptes[baddr >> PAGE_SHIFT];
+ if (!(pte & 1)) {
+- printk("%s: pte not valid\n", __FUNCTION__);
++ printk("%s: pte not valid\n", __func__);
+ return -EINVAL;
+ }
+
+diff --git a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c
+index ef91e09..5e7c28f 100644
+--- a/arch/alpha/kernel/core_tsunami.c
++++ b/arch/alpha/kernel/core_tsunami.c
+@@ -241,8 +241,6 @@ tsunami_probe_write(volatile unsigned long *vaddr)
+ #define tsunami_probe_read(ADDR) 1
+ #endif /* NXM_MACHINE_CHECKS_ON_TSUNAMI */
+
+-#define FN __FUNCTION__
+-
+ static void __init
+ tsunami_init_one_pchip(tsunami_pchip *pchip, int index)
+ {
+@@ -383,27 +381,27 @@ tsunami_init_arch(void)
+ /* NXMs just don't matter to Tsunami--unless they make it
+ choke completely. */
+ tmp = (unsigned long)(TSUNAMI_cchip - 1);
+- printk("%s: probing bogus address: 0x%016lx\n", FN, bogus_addr);
++ printk("%s: probing bogus address: 0x%016lx\n", __func__, bogus_addr);
+ printk("\tprobe %s\n",
+ tsunami_probe_write((unsigned long *)bogus_addr)
+ ? "succeeded" : "failed");
+ #endif /* NXM_MACHINE_CHECKS_ON_TSUNAMI */
+
+ #if 0
+- printk("%s: CChip registers:\n", FN);
+- printk("%s: CSR_CSC 0x%lx\n", FN, TSUNAMI_cchip->csc.csr);
+- printk("%s: CSR_MTR 0x%lx\n", FN, TSUNAMI_cchip.mtr.csr);
+- printk("%s: CSR_MISC 0x%lx\n", FN, TSUNAMI_cchip->misc.csr);
+- printk("%s: CSR_DIM0 0x%lx\n", FN, TSUNAMI_cchip->dim0.csr);
+- printk("%s: CSR_DIM1 0x%lx\n", FN, TSUNAMI_cchip->dim1.csr);
+- printk("%s: CSR_DIR0 0x%lx\n", FN, TSUNAMI_cchip->dir0.csr);
+- printk("%s: CSR_DIR1 0x%lx\n", FN, TSUNAMI_cchip->dir1.csr);
+- printk("%s: CSR_DRIR 0x%lx\n", FN, TSUNAMI_cchip->drir.csr);
++ printk("%s: CChip registers:\n", __func__);
++ printk("%s: CSR_CSC 0x%lx\n", __func__, TSUNAMI_cchip->csc.csr);
++ printk("%s: CSR_MTR 0x%lx\n", __func__, TSUNAMI_cchip.mtr.csr);
++ printk("%s: CSR_MISC 0x%lx\n", __func__, TSUNAMI_cchip->misc.csr);
++ printk("%s: CSR_DIM0 0x%lx\n", __func__, TSUNAMI_cchip->dim0.csr);
++ printk("%s: CSR_DIM1 0x%lx\n", __func__, TSUNAMI_cchip->dim1.csr);
++ printk("%s: CSR_DIR0 0x%lx\n", __func__, TSUNAMI_cchip->dir0.csr);
++ printk("%s: CSR_DIR1 0x%lx\n", __func__, TSUNAMI_cchip->dir1.csr);
++ printk("%s: CSR_DRIR 0x%lx\n", __func__, TSUNAMI_cchip->drir.csr);
+
+ printk("%s: DChip registers:\n");
+- printk("%s: CSR_DSC 0x%lx\n", FN, TSUNAMI_dchip->dsc.csr);
+- printk("%s: CSR_STR 0x%lx\n", FN, TSUNAMI_dchip->str.csr);
+- printk("%s: CSR_DREV 0x%lx\n", FN, TSUNAMI_dchip->drev.csr);
++ printk("%s: CSR_DSC 0x%lx\n", __func__, TSUNAMI_dchip->dsc.csr);
++ printk("%s: CSR_STR 0x%lx\n", __func__, TSUNAMI_dchip->str.csr);
++ printk("%s: CSR_DREV 0x%lx\n", __func__, TSUNAMI_dchip->drev.csr);
+ #endif
+ /* With multiple PCI busses, we play with I/O as physical addrs. */
+ ioport_resource.end = ~0UL;
+diff --git a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c
+index 026ba9a..ebc3c89 100644
+--- a/arch/alpha/kernel/module.c
++++ b/arch/alpha/kernel/module.c
+@@ -120,6 +120,12 @@ module_frob_arch_sections(Elf64_Ehdr *hdr, Elf64_Shdr *sechdrs,
+
+ nsyms = symtab->sh_size / sizeof(Elf64_Sym);
+ chains = kcalloc(nsyms, sizeof(struct got_entry), GFP_KERNEL);
++ if (!chains) {
++ printk(KERN_ERR
++ "module %s: no memory for symbol chain buffer\n",
++ me->name);
++ return -ENOMEM;
++ }
+
+ got->sh_size = 0;
+ got->sh_addralign = 8;
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
@@ -10624,7 +15130,7 @@
#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
+index 9dc1cee..36ab22a 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
@@ -10654,6 +15160,15 @@
if (__direct_map_base + __direct_map_size >= 0xfff00000UL)
__direct_map_size = 0xfff00000UL - __direct_map_base;
else {
+@@ -220,7 +208,7 @@ pdev_save_srm_config(struct pci_dev *dev)
+
+ tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
+ if (!tmp) {
+- printk(KERN_ERR "%s: kmalloc() failed!\n", __FUNCTION__);
++ printk(KERN_ERR "%s: kmalloc() failed!\n", __func__);
+ return;
+ }
+ tmp->next = srm_saved_configs;
@@ -372,28 +360,7 @@ EXPORT_SYMBOL(pcibios_bus_to_resource);
int
pcibios_enable_device(struct pci_dev *dev, int mask)
@@ -10713,6 +15228,62 @@
pci_assign_unassigned_resources();
pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
+@@ -547,8 +514,8 @@ sys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn)
+
+ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+ {
+- unsigned long start = pci_resource_start(dev, bar);
+- unsigned long len = pci_resource_len(dev, bar);
++ resource_size_t start = pci_resource_start(dev, bar);
++ resource_size_t len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (!len || !start)
+diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
+index dd6e334..2179c60 100644
+--- a/arch/alpha/kernel/pci_iommu.c
++++ b/arch/alpha/kernel/pci_iommu.c
+@@ -79,25 +79,21 @@ iommu_arena_new_node(int nid, struct pci_controller *hose, dma_addr_t base,
+
+ #ifdef CONFIG_DISCONTIGMEM
+
+- if (!NODE_DATA(nid) ||
+- (NULL == (arena = alloc_bootmem_node(NODE_DATA(nid),
+- sizeof(*arena))))) {
+- printk("%s: couldn't allocate arena from node %d\n"
+- " falling back to system-wide allocation\n",
+- __FUNCTION__, nid);
+- arena = alloc_bootmem(sizeof(*arena));
+- }
+-
+- if (!NODE_DATA(nid) ||
+- (NULL == (arena->ptes = __alloc_bootmem_node(NODE_DATA(nid),
+- mem_size,
+- align,
+- 0)))) {
+- printk("%s: couldn't allocate arena ptes from node %d\n"
+- " falling back to system-wide allocation\n",
+- __FUNCTION__, nid);
+- arena->ptes = __alloc_bootmem(mem_size, align, 0);
+- }
++ arena = alloc_bootmem_node(NODE_DATA(nid), sizeof(*arena));
++ if (!NODE_DATA(nid) || !arena) {
++ printk("%s: couldn't allocate arena from node %d\n"
++ " falling back to system-wide allocation\n",
++ __func__, nid);
++ arena = alloc_bootmem(sizeof(*arena));
++ }
++
++ arena->ptes = __alloc_bootmem_node(NODE_DATA(nid), mem_size, align, 0);
++ if (!NODE_DATA(nid) || !arena->ptes) {
++ printk("%s: couldn't allocate arena ptes from node %d\n"
++ " falling back to system-wide allocation\n",
++ __func__, nid);
++ arena->ptes = __alloc_bootmem(mem_size, align, 0);
++ }
+
+ #else /* CONFIG_DISCONTIGMEM */
+
diff --git a/arch/alpha/kernel/semaphore.c b/arch/alpha/kernel/semaphore.c
deleted file mode 100644
index 8d2982a..0000000
@@ -10943,6 +15514,98 @@
-#endif
- __up(sem);
-}
+diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
+index 63c2073..2525692 100644
+--- a/arch/alpha/kernel/smp.c
++++ b/arch/alpha/kernel/smp.c
+@@ -755,7 +755,7 @@ smp_call_function_on_cpu (void (*func) (void *info), void *info, int retry,
+ if (atomic_read(&data.unstarted_count) > 0) {
+ long start_time = jiffies;
+ printk(KERN_ERR "%s: initial timeout -- trying long wait\n",
+- __FUNCTION__);
++ __func__);
+ timeout = jiffies + 30 * HZ;
+ while (atomic_read(&data.unstarted_count) > 0
+ && time_before(jiffies, timeout))
+@@ -764,7 +764,7 @@ smp_call_function_on_cpu (void (*func) (void *info), void *info, int retry,
+ long delta = jiffies - start_time;
+ printk(KERN_ERR
+ "%s: response %ld.%ld seconds into long wait\n",
+- __FUNCTION__, delta / HZ,
++ __func__, delta / HZ,
+ (100 * (delta - ((delta / HZ) * HZ))) / HZ);
+ }
+ }
+diff --git a/arch/alpha/kernel/srm_env.c b/arch/alpha/kernel/srm_env.c
+index f7dd081..78ad7cd 100644
+--- a/arch/alpha/kernel/srm_env.c
++++ b/arch/alpha/kernel/srm_env.c
+@@ -199,7 +199,7 @@ srm_env_init(void)
+ printk(KERN_INFO "%s: This Alpha system doesn't "
+ "know about SRM (or you've booted "
+ "SRM->MILO->Linux, which gets "
+- "misdetected)...\n", __FUNCTION__);
++ "misdetected)...\n", __func__);
+ return -ENODEV;
+ }
+
+diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c
+index d187d01..e53a1e1 100644
+--- a/arch/alpha/kernel/sys_alcor.c
++++ b/arch/alpha/kernel/sys_alcor.c
+@@ -259,7 +259,7 @@ alcor_init_pci(void)
+ if (dev && dev->devfn == PCI_DEVFN(6,0)) {
+ alpha_mv.sys.cia.gru_int_req_bits = XLT_GRU_INT_REQ_BITS;
+ printk(KERN_INFO "%s: Detected AS500 or XLT motherboard.\n",
+- __FUNCTION__);
++ __func__);
+ }
+ pci_dev_put(dev);
+ }
+diff --git a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c
+index 922143e..828449c 100644
+--- a/arch/alpha/kernel/sys_marvel.c
++++ b/arch/alpha/kernel/sys_marvel.c
+@@ -80,7 +80,7 @@ io7_get_irq_ctl(unsigned int irq, struct io7 **pio7)
+ if (!(io7 = marvel_find_io7(pid))) {
+ printk(KERN_ERR
+ "%s for nonexistent io7 -- vec %x, pid %d\n",
+- __FUNCTION__, irq, pid);
++ __func__, irq, pid);
+ return NULL;
+ }
+
+@@ -90,7 +90,7 @@ io7_get_irq_ctl(unsigned int irq, struct io7 **pio7)
+ if (irq >= 0x180) {
+ printk(KERN_ERR
+ "%s for invalid irq -- pid %d adjusted irq %x\n",
+- __FUNCTION__, pid, irq);
++ __func__, pid, irq);
+ return NULL;
+ }
+
+@@ -110,8 +110,8 @@ io7_enable_irq(unsigned int irq)
+
+ ctl = io7_get_irq_ctl(irq, &io7);
+ if (!ctl || !io7) {
+- printk(KERN_ERR "%s: get_ctl failed for irq %x\n",
+- __FUNCTION__, irq);
++ printk(KERN_ERR "%s: get_ctl failed for irq %x\n",
++ __func__, irq);
+ return;
+ }
+
+@@ -130,8 +130,8 @@ io7_disable_irq(unsigned int irq)
+
+ ctl = io7_get_irq_ctl(irq, &io7);
+ if (!ctl || !io7) {
+- printk(KERN_ERR "%s: get_ctl failed for irq %x\n",
+- __FUNCTION__, irq);
++ printk(KERN_ERR "%s: get_ctl failed for irq %x\n",
++ __func__, irq);
+ return;
+ }
+
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
@@ -10963,11 +15626,109 @@
irongate = pci_get_bus_and_slot(0, 0);
bus->self = irongate;
+diff --git a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c
+index 906019c..99a7f19 100644
+--- a/arch/alpha/kernel/sys_sable.c
++++ b/arch/alpha/kernel/sys_sable.c
+@@ -454,7 +454,7 @@ sable_lynx_enable_irq(unsigned int irq)
+ spin_unlock(&sable_lynx_irq_lock);
+ #if 0
+ printk("%s: mask 0x%lx bit 0x%x irq 0x%x\n",
+- __FUNCTION__, mask, bit, irq);
++ __func__, mask, bit, irq);
+ #endif
+ }
+
+@@ -470,7 +470,7 @@ sable_lynx_disable_irq(unsigned int irq)
+ spin_unlock(&sable_lynx_irq_lock);
+ #if 0
+ printk("%s: mask 0x%lx bit 0x%x irq 0x%x\n",
+- __FUNCTION__, mask, bit, irq);
++ __func__, mask, bit, irq);
+ #endif
+ }
+
+@@ -524,7 +524,7 @@ sable_lynx_srm_device_interrupt(unsigned long vector)
+ irq = sable_lynx_irq_swizzle->mask_to_irq[bit];
+ #if 0
+ printk("%s: vector 0x%lx bit 0x%x irq 0x%x\n",
+- __FUNCTION__, vector, bit, irq);
++ __func__, vector, bit, irq);
+ #endif
+ handle_irq(irq);
+ }
+diff --git a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c
+index ee7b900..d4327e4 100644
+--- a/arch/alpha/kernel/sys_sio.c
++++ b/arch/alpha/kernel/sys_sio.c
+@@ -89,7 +89,7 @@ sio_pci_route(void)
+ /* First, ALWAYS read and print the original setting. */
+ pci_bus_read_config_dword(pci_isa_hose->bus, PCI_DEVFN(7, 0), 0x60,
+ &orig_route_tab);
+- printk("%s: PIRQ original 0x%x new 0x%x\n", __FUNCTION__,
++ printk("%s: PIRQ original 0x%x new 0x%x\n", __func__,
+ orig_route_tab, alpha_mv.sys.sio.route_tab);
+
+ #if defined(ALPHA_RESTORE_SRM_SETUP)
+diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
+index 2dc7f9f..dc57790 100644
+--- a/arch/alpha/kernel/traps.c
++++ b/arch/alpha/kernel/traps.c
+@@ -8,6 +8,7 @@
+ * This file initializes the trap entry points
+ */
+
++#include <linux/jiffies.h>
+ #include <linux/mm.h>
+ #include <linux/sched.h>
+ #include <linux/tty.h>
+@@ -770,7 +771,7 @@ do_entUnaUser(void __user * va, unsigned long opcode,
+ unsigned long reg, struct pt_regs *regs)
+ {
+ static int cnt = 0;
+- static long last_time = 0;
++ static unsigned long last_time;
+
+ unsigned long tmp1, tmp2, tmp3, tmp4;
+ unsigned long fake_reg, *reg_addr = &fake_reg;
+@@ -781,7 +782,7 @@ do_entUnaUser(void __user * va, unsigned long opcode,
+ with the unaliged access. */
+
+ if (!test_thread_flag (TIF_UAC_NOPRINT)) {
+- if (cnt >= 5 && jiffies - last_time > 5*HZ) {
++ if (cnt >= 5 && time_after(jiffies, last_time + 5 * HZ)) {
+ cnt = 0;
+ }
+ if (++cnt < 5) {
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
-index 4039a13..d8d2532 100644
+index 4039a13..b786e68 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
-@@ -255,6 +255,7 @@ config ARCH_EP93XX
+@@ -8,6 +8,7 @@ mainmenu "Linux Kernel Configuration"
+ config ARM
+ bool
+ default y
++ select HAVE_IDE
+ select RTC_LIB
+ select SYS_SUPPORTS_APM_EMULATION
+ select HAVE_OPROFILE
+@@ -223,7 +224,6 @@ config ARCH_CLPS7500
+ select TIMER_ACORN
+ select ISA
+ select NO_IOPORT
+- select HAVE_IDE
+ help
+ Support for the Cirrus Logic PS7500FE system-on-a-chip.
+
+@@ -236,7 +236,6 @@ config ARCH_CO285
+ bool "Co-EBSA285"
+ select FOOTBRIDGE
+ select FOOTBRIDGE_ADDIN
+- select HAVE_IDE
+ help
+ Support for Intel's EBSA285 companion chip.
+
+@@ -255,13 +254,13 @@ config ARCH_EP93XX
select ARM_AMBA
select ARM_VIC
select GENERIC_GPIO
@@ -10975,7 +15736,52 @@
help
This enables support for the Cirrus EP93xx series of CPUs.
-@@ -377,15 +378,17 @@ config ARCH_MXC
+ config ARCH_FOOTBRIDGE
+ bool "FootBridge"
+ select FOOTBRIDGE
+- select HAVE_IDE
+ help
+ Support for systems based on the DC21285 companion chip
+ ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
+@@ -300,7 +299,6 @@ config ARCH_IOP32X
+ depends on MMU
+ select PLAT_IOP
+ select PCI
+- select HAVE_IDE
+ help
+ Support for Intel's 80219 and IOP32X (XScale) family of
+ processors.
+@@ -310,14 +308,12 @@ config ARCH_IOP33X
+ depends on MMU
+ select PLAT_IOP
+ select PCI
+- select HAVE_IDE
+ help
+ Support for Intel's IOP33X (XScale) family of processors.
+
+ config ARCH_IXP23XX
+ bool "IXP23XX-based"
+ depends on MMU
+- select HAVE_IDE
+ select PCI
+ help
+ Support for Intel's IXP23xx (XScale) family of processors.
+@@ -335,14 +331,12 @@ config ARCH_IXP4XX
+ select GENERIC_GPIO
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
+- select HAVE_IDE
+ help
+ Support for Intel's IXP4XX (XScale) family of processors.
+
+ config ARCH_L7200
+ bool "LinkUp-L7200"
+ select FIQ
+- select HAVE_IDE
+ help
+ Say Y here if you intend to run this kernel on a LinkUp Systems
+ L7200 Software Development Board which uses an ARM720T processor.
+@@ -377,15 +371,17 @@ config ARCH_MXC
help
Support for Freescale MXC/iMX-based family of processors
@@ -10995,7 +15801,23 @@
config ARCH_PNX4008
bool "Philips Nexperia PNX4008 Mobile"
-@@ -422,10 +425,15 @@ config ARCH_SA1100
+@@ -397,7 +393,6 @@ config ARCH_PXA
+ depends on MMU
+ select ARCH_MTD_XIP
+ select GENERIC_GPIO
+- select HAVE_IDE
+ select HAVE_GPIO_LIB
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
+@@ -413,7 +408,6 @@ config ARCH_RPC
+ select ARCH_MAY_HAVE_PC_FDC
+ select ISA_DMA_API
+ select NO_IOPORT
+- select HAVE_IDE
+ help
+ On the Acorn Risc-PC, Linux can support the internal IDE disk and
+ CD-ROM interface, serial and parallel port, and the floppy drive.
+@@ -422,17 +416,20 @@ config ARCH_SA1100
bool "SA1100-based"
select ISA
select ARCH_DISCONTIGMEM_ENABLE
@@ -11004,14 +15826,37 @@
select ARCH_MTD_XIP
select GENERIC_GPIO
select GENERIC_TIME
+- select HAVE_IDE
+ 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_S3C2410
+ bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"
+ select GENERIC_GPIO
+- select HAVE_IDE
+ help
+ Samsung S3C2410X CPU based systems, such as the Simtec Electronics
+ BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
+@@ -440,7 +437,6 @@ config ARCH_S3C2410
+
+ config ARCH_SHARK
+ bool "Shark"
+- select HAVE_IDE
+ select ISA
+ select ISA_DMA
+ select PCI
+@@ -450,7 +446,6 @@ config ARCH_SHARK
+
+ config ARCH_LH7A40X
+ bool "Sharp LH7A40X"
+- select HAVE_IDE
+ help
+ Say Y here for systems based on one of the Sharp LH7A40X
+ System on a Chip processors. These CPUs include an ARM922T
+@@ -468,6 +463,7 @@ config ARCH_DAVINCI
config ARCH_OMAP
bool "TI OMAP"
select GENERIC_GPIO
@@ -11019,7 +15864,7 @@
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
help
-@@ -516,7 +525,7 @@ source "arch/arm/mach-omap1/Kconfig"
+@@ -516,7 +512,7 @@ source "arch/arm/mach-omap1/Kconfig"
source "arch/arm/mach-omap2/Kconfig"
@@ -11028,7 +15873,7 @@
source "arch/arm/plat-s3c24xx/Kconfig"
source "arch/arm/plat-s3c/Kconfig"
-@@ -563,6 +572,9 @@ config ARCH_ACORN
+@@ -563,6 +559,9 @@ config ARCH_ACORN
config PLAT_IOP
bool
@@ -11038,7 +15883,7 @@
source arch/arm/mm/Kconfig
config IWMMXT
-@@ -650,7 +662,7 @@ source "kernel/time/Kconfig"
+@@ -650,7 +649,7 @@ source "kernel/time/Kconfig"
config SMP
bool "Symmetric Multi-Processing (EXPERIMENTAL)"
@@ -11047,7 +15892,7 @@
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
+@@ -683,7 +682,7 @@ config HOTPLUG_CPU
config LOCAL_TIMERS
bool "Use local timer interrupts"
@@ -11056,7 +15901,7 @@
default y
help
Enable support for local timers on SMP platforms, rather then the
-@@ -774,6 +786,12 @@ config ARCH_DISCONTIGMEM_ENABLE
+@@ -774,6 +773,12 @@ config ARCH_DISCONTIGMEM_ENABLE
or have huge holes in the physical address space for other reasons.
See <file:Documentation/vm/numa> for more.
@@ -11069,7 +15914,7 @@
config NODES_SHIFT
int
default "4" if ARCH_LH7A40X
-@@ -1174,6 +1192,8 @@ source "drivers/dma/Kconfig"
+@@ -1174,6 +1179,8 @@ source "drivers/dma/Kconfig"
source "drivers/dca/Kconfig"
@@ -11442,14 +16287,14 @@
}
diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
new file mode 100644
-index 0000000..dc030cf
+index 0000000..5e68420
--- /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
++# Linux kernel version: 2.6.25
++# Sun Apr 20 00:29:49 2008
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -11499,7 +16344,8 @@
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
-+# CONFIG_SYSFS_DEPRECATED 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
@@ -11533,6 +16379,7 @@
+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
@@ -11563,7 +16410,6 @@
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_CLASSIC_RCU=y
-+# CONFIG_PREEMPT_RCU is not set
+
+#
+# System Type
@@ -11768,8 +16614,6 @@
+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
@@ -11831,7 +16675,6 @@
+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
+
@@ -11951,7 +16794,7 @@
+CONFIG_BLK_DEV_IDE=m
+
+#
-+# 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=m
@@ -11966,10 +16809,9 @@
+#
+# 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_ONLY is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
@@ -12010,6 +16852,7 @@
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_NET_PCMCIA is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
@@ -12155,6 +16998,8 @@
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
++# CONFIG_HTC_EGPIO is not set
++# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
@@ -12193,6 +17038,7 @@
+CONFIG_FB_PXA=y
+CONFIG_FB_PXA_PARAMETERS=y
+CONFIG_FB_MBX=m
++# CONFIG_FB_METRONOME is not set
+CONFIG_FB_VIRTUAL=m
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
@@ -12339,7 +17185,6 @@
+# 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
@@ -30007,10 +34852,32 @@
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
+index 3278e71..4a88125 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
-@@ -58,6 +58,9 @@ int main(void)
+@@ -16,6 +16,7 @@
+ #include <asm/thread_info.h>
+ #include <asm/memory.h>
+ #include <asm/procinfo.h>
++#include <linux/kbuild.h>
+
+ /*
+ * Make sure that the compiler and target are compatible.
+@@ -35,13 +36,6 @@
+ #error Known good compilers: 3.3
+ #endif
+
+-/* Use marker if you need to separate the values later */
+-
+-#define DEFINE(sym, val) \
+- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+-
+-#define BLANK() asm volatile("\n->" : : )
+-
+ int main(void)
+ {
+ DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
+@@ -58,6 +52,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));
@@ -30020,7 +34887,7 @@
#ifdef CONFIG_IWMMXT
DEFINE(TI_IWMMXT_STATE, offsetof(struct thread_info, fpstate.iwmmxt));
#endif
-@@ -108,5 +111,12 @@ int main(void)
+@@ -108,5 +105,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));
@@ -30033,6 +34900,19 @@
+#endif
return 0;
}
+diff --git a/arch/arm/kernel/atags.c b/arch/arm/kernel/atags.c
+index e2e934c..64c4208 100644
+--- a/arch/arm/kernel/atags.c
++++ b/arch/arm/kernel/atags.c
+@@ -35,7 +35,7 @@ create_proc_entries(void)
+ {
+ struct proc_dir_entry* tags_entry;
+
+- tags_entry = create_proc_read_entry("atags", 0400, &proc_root, read_buffer, &tags_buffer);
++ tags_entry = create_proc_read_entry("atags", 0400, NULL, read_buffer, &tags_buffer);
+ if (!tags_entry)
+ return -ENOMEM;
+
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 7e97b73..30a67a5 100644
--- a/arch/arm/kernel/calls.S
@@ -30050,6 +34930,106 @@
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
#define syscalls_counted
+diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
+index f56d48c..a53c0ab 100644
+--- a/arch/arm/kernel/ecard.c
++++ b/arch/arm/kernel/ecard.c
+@@ -37,6 +37,7 @@
+ #include <linux/mm.h>
+ #include <linux/slab.h>
+ #include <linux/proc_fs.h>
++#include <linux/seq_file.h>
+ #include <linux/device.h>
+ #include <linux/init.h>
+ #include <linux/mutex.h>
+@@ -723,17 +724,14 @@ unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
+ return address;
+ }
+
+-static int ecard_prints(char *buffer, ecard_t *ec)
++static int ecard_prints(struct seq_file *m, ecard_t *ec)
+ {
+- char *start = buffer;
+-
+- buffer += sprintf(buffer, " %d: %s ", ec->slot_no,
+- ec->easi ? "EASI" : " ");
++ seq_printf(m, " %d: %s ", ec->slot_no, ec->easi ? "EASI" : " ");
+
+ if (ec->cid.id == 0) {
+ struct in_chunk_dir incd;
+
+- buffer += sprintf(buffer, "[%04X:%04X] ",
++ seq_printf(m, "[%04X:%04X] ",
+ ec->cid.manufacturer, ec->cid.product);
+
+ if (!ec->card_desc && ec->cid.cd &&
+@@ -744,43 +742,43 @@ static int ecard_prints(char *buffer, ecard_t *ec)
+ strcpy((char *)ec->card_desc, incd.d.string);
+ }
+
+- buffer += sprintf(buffer, "%s\n", ec->card_desc ? ec->card_desc : "*unknown*");
++ seq_printf(m, "%s\n", ec->card_desc ? ec->card_desc : "*unknown*");
+ } else
+- buffer += sprintf(buffer, "Simple card %d\n", ec->cid.id);
++ seq_printf(m, "Simple card %d\n", ec->cid.id);
+
+- return buffer - start;
++ return 0;
+ }
+
+-static int get_ecard_dev_info(char *buf, char **start, off_t pos, int count)
++static int ecard_devices_proc_show(struct seq_file *m, void *v)
+ {
+ ecard_t *ec = cards;
+- off_t at = 0;
+- int len, cnt;
+-
+- cnt = 0;
+- while (ec && count > cnt) {
+- len = ecard_prints(buf, ec);
+- at += len;
+- if (at >= pos) {
+- if (!*start) {
+- *start = buf + (pos - (at - len));
+- cnt = at - pos;
+- } else
+- cnt += len;
+- buf += len;
+- }
++
++ while (ec) {
++ ecard_prints(m, ec);
+ ec = ec->next;
+ }
+- return (count > cnt) ? cnt : count;
++ return 0;
+ }
+
++static int ecard_devices_proc_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, ecard_devices_proc_show, NULL);
++}
++
++static const struct file_operations bus_ecard_proc_fops = {
++ .owner = THIS_MODULE,
++ .open = ecard_devices_proc_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
+ static struct proc_dir_entry *proc_bus_ecard_dir = NULL;
+
+ static void ecard_proc_init(void)
+ {
+- proc_bus_ecard_dir = proc_mkdir("ecard", proc_bus);
+- create_proc_info_entry("devices", 0, proc_bus_ecard_dir,
+- get_ecard_dev_info);
++ proc_bus_ecard_dir = proc_mkdir("bus/ecard", NULL);
++ proc_create("devices", 0, proc_bus_ecard_dir, &bus_ecard_proc_fops);
+ }
+
+ #define ec_set_resource(ec,nr,st,sz) \
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
@@ -30327,6 +35307,32 @@
.align
#endif
+diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c
+index d51bc8b..b4565bb 100644
+--- a/arch/arm/kernel/kprobes-decode.c
++++ b/arch/arm/kernel/kprobes-decode.c
+@@ -1176,7 +1176,7 @@ space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+ * *S (bit 20) updates condition codes
+ * ADC/SBC/RSC reads the C flag
+ */
+- insn &= 0xfff00ff0; /* Rn = r0, Rd = r0 */
++ insn &= 0xfff00fff; /* Rn = r0, Rd = r0 */
+ asi->insn[0] = insn;
+ asi->insn_handler = (insn & (1 << 20)) ? /* S-bit */
+ emulate_alu_imm_rwflags : emulate_alu_imm_rflags;
+diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
+index 13e371a..5593dd2 100644
+--- a/arch/arm/kernel/kprobes.c
++++ b/arch/arm/kernel/kprobes.c
+@@ -66,7 +66,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
+ return -ENOMEM;
+ for (is = 0; is < MAX_INSN_SIZE; ++is)
+ p->ainsn.insn[is] = tmp_insn[is];
+- flush_insns(&p->ainsn.insn, MAX_INSN_SIZE);
++ flush_insns(p->ainsn.insn, MAX_INSN_SIZE);
+ break;
+
+ case INSN_GOOD_NO_SLOT: /* instruction doesn't need insn slot */
diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c
deleted file mode 100644
index 981fe5c..0000000
@@ -30789,7 +35795,7 @@
/* 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
+index c50fad9..be52674 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -16,15 +16,15 @@
@@ -30810,6 +35816,15 @@
#include "generic.h"
+@@ -246,7 +246,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+ }
+
+ mmc0_data = *data;
+- at91_clock_associate("mci0_clk", &at91cap9_mmc1_device.dev, "mci_clk");
++ at91_clock_associate("mci0_clk", &at91cap9_mmc0_device.dev, "mci_clk");
+ platform_device_register(&at91cap9_mmc0_device);
+ } else { /* MCI1 */
+ /* CLK */
@@ -283,10 +283,15 @@ static struct at91_nand_data nand_data;
#define NAND_BASE AT91_CHIPSELECT_3
@@ -31371,7 +36386,7 @@
| (1 << AT91SAM9261_ID_IRQ2);
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
-index 2456412..37cd547 100644
+index 2456412..728bb8f 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -24,7 +24,7 @@
@@ -31383,7 +36398,25 @@
#include "generic.h"
-@@ -548,6 +548,55 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
+@@ -539,6 +539,17 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
+ at91_set_B_periph(AT91_PIN_PB28, 0); /* LCDD23 */
+ #endif
+
++ if (ARRAY_SIZE(lcdc_resources) > 2) {
++ void __iomem *fb;
++ struct resource *fb_res = &lcdc_resources[2];
++ size_t fb_len = fb_res->end - fb_res->start + 1;
++
++ fb = ioremap_writecombine(fb_res->start, fb_len);
++ if (fb) {
++ memset(fb, 0, fb_len);
++ iounmap(fb, fb_len);
++ }
++ }
+ lcdc_data = *data;
+ platform_device_register(&at91_lcdc_device);
+ }
+@@ -548,6 +559,55 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
/* --------------------------------------------------------------------
@@ -31439,7 +36472,7 @@
* RTT
* -------------------------------------------------------------------- */
-@@ -561,7 +610,7 @@ static struct resource rtt_resources[] = {
+@@ -561,7 +621,7 @@ static struct resource rtt_resources[] = {
static struct platform_device at91sam9261_rtt_device = {
.name = "at91_rtt",
@@ -31448,7 +36481,7 @@
.resource = rtt_resources,
.num_resources = ARRAY_SIZE(rtt_resources),
};
-@@ -938,49 +987,9 @@ static inline void configure_usart2_pins(unsigned pins)
+@@ -938,49 +998,9 @@ static inline void configure_usart2_pins(unsigned pins)
at91_set_B_periph(AT91_PIN_PA16, 0); /* CTS2 */
}
@@ -31499,7 +36532,7 @@
void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
{
struct platform_device *pdev;
-@@ -1019,8 +1028,6 @@ void __init at91_set_serial_console(unsigned portnr)
+@@ -1019,8 +1039,6 @@ void __init at91_set_serial_console(unsigned portnr)
{
if (portnr < ATMEL_MAX_UART)
atmel_default_console_device = at91_uarts[portnr];
@@ -31508,7 +36541,7 @@
}
void __init at91_add_device_serial(void)
-@@ -1031,9 +1038,11 @@ void __init at91_add_device_serial(void)
+@@ -1031,9 +1049,11 @@ void __init at91_add_device_serial(void)
if (at91_uarts[i])
platform_device_register(at91_uarts[i]);
}
@@ -31521,7 +36554,7 @@
void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
void __init at91_set_serial_console(unsigned portnr) {}
void __init at91_add_device_serial(void) {}
-@@ -1050,6 +1059,7 @@ static int __init at91_add_standard_devices(void)
+@@ -1050,6 +1070,7 @@ static int __init at91_add_standard_devices(void)
{
at91_add_device_rtt();
at91_add_device_watchdog();
@@ -31569,7 +36602,7 @@
/* Init clock subsystem */
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
-index 0b12e1a..b6454c5 100644
+index 0b12e1a..719667e 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -22,8 +22,8 @@
@@ -31582,6 +36615,15 @@
#include "generic.h"
+@@ -308,7 +308,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+ }
+
+ mmc0_data = *data;
+- at91_clock_associate("mci0_clk", &at91sam9263_mmc1_device.dev, "mci_clk");
++ at91_clock_associate("mci0_clk", &at91sam9263_mmc0_device.dev, "mci_clk");
+ platform_device_register(&at91sam9263_mmc0_device);
+ } else { /* MCI1 */
+ /* CLK */
@@ -358,10 +358,15 @@ static struct at91_nand_data nand_data;
#define NAND_BASE AT91_CHIPSELECT_3
@@ -32014,7 +37056,7 @@
/* Init clock subsystem */
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
-index f43b5c3..dbb9a5f 100644
+index f43b5c3..0546898 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -20,7 +20,7 @@
@@ -32043,7 +37085,28 @@
}
};
-@@ -385,6 +390,55 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
+@@ -376,6 +381,20 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
+ at91_set_B_periph(AT91_PIN_PC24, 0); /* LCDD22 */
+ at91_set_B_periph(AT91_PIN_PC25, 0); /* LCDD23 */
+
++#ifdef CONFIG_FB_INTSRAM
++ {
++ void __iomem *fb;
++ struct resource *fb_res = &lcdc_resources[2];
++ size_t fb_len = fb_res->end - fb_res->start + 1;
++
++ fb = ioremap_writecombine(fb_res->start, fb_len);
++ if (fb) {
++ memset(fb, 0, fb_len);
++ iounmap(fb, fb_len);
++ }
++ }
++#endif
++
+ lcdc_data = *data;
+ platform_device_register(&at91_lcdc_device);
+ }
+@@ -385,6 +404,55 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
/* --------------------------------------------------------------------
@@ -32099,7 +37162,7 @@
* RTC
* -------------------------------------------------------------------- */
-@@ -418,7 +472,7 @@ static struct resource rtt_resources[] = {
+@@ -418,7 +486,7 @@ static struct resource rtt_resources[] = {
static struct platform_device at91sam9rl_rtt_device = {
.name = "at91_rtt",
@@ -32108,7 +37171,7 @@
.resource = rtt_resources,
.num_resources = ARRAY_SIZE(rtt_resources),
};
-@@ -539,9 +593,6 @@ static inline void configure_ssc1_pins(unsigned pins)
+@@ -539,9 +607,6 @@ static inline void configure_ssc1_pins(unsigned pins)
}
/*
@@ -32118,7 +37181,7 @@
* SSC controllers are accessed through library code, instead of any
* kind of all-singing/all-dancing driver. For example one could be
* used by a particular I2S audio codec's driver, while another one
-@@ -802,54 +853,9 @@ static inline void configure_usart3_pins(unsigned pins)
+@@ -802,54 +867,9 @@ static inline void configure_usart3_pins(unsigned pins)
at91_set_B_periph(AT91_PIN_PD3, 0); /* CTS3 */
}
@@ -32174,7 +37237,7 @@
void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
{
struct platform_device *pdev;
-@@ -893,8 +899,6 @@ void __init at91_set_serial_console(unsigned portnr)
+@@ -893,8 +913,6 @@ void __init at91_set_serial_console(unsigned portnr)
{
if (portnr < ATMEL_MAX_UART)
atmel_default_console_device = at91_uarts[portnr];
@@ -32183,7 +37246,7 @@
}
void __init at91_add_device_serial(void)
-@@ -905,9 +909,11 @@ void __init at91_add_device_serial(void)
+@@ -905,9 +923,11 @@ void __init at91_add_device_serial(void)
if (at91_uarts[i])
platform_device_register(at91_uarts[i]);
}
@@ -32196,7 +37259,7 @@
void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
void __init at91_set_serial_console(unsigned portnr) {}
void __init at91_add_device_serial(void) {}
-@@ -925,6 +931,7 @@ static int __init at91_add_standard_devices(void)
+@@ -925,6 +945,7 @@ static int __init at91_add_standard_devices(void)
at91_add_device_rtc();
at91_add_device_rtt();
at91_add_device_watchdog();
@@ -32404,7 +37467,7 @@
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
-index 0e2a11f..26fea4d 100644
+index 0e2a11f..81f1ebb 100644
--- a/arch/arm/mach-at91/board-csb337.c
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -43,17 +43,6 @@
@@ -32439,6 +37502,16 @@
}
static void __init csb337_init_irq(void)
+@@ -87,8 +79,7 @@ static struct at91_udc_data __initdata csb337_udc_data = {
+
+ static struct i2c_board_info __initdata csb337_i2c_devices[] = {
+ {
+- I2C_BOARD_INFO("rtc-ds1307", 0x68),
+- .type = "ds1307",
++ I2C_BOARD_INFO("ds1307", 0x68),
+ },
+ };
+
diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
index c5c721d..419fd19 100644
--- a/arch/arm/mach-at91/board-csb637.c
@@ -32495,6 +37568,34 @@
/* Serial */
at91_add_device_serial();
/* Ethernet */
+diff --git a/arch/arm/mach-at91/board-dk.c b/arch/arm/mach-at91/board-dk.c
+index 0a897ef..c1a813c 100644
+--- a/arch/arm/mach-at91/board-dk.c
++++ b/arch/arm/mach-at91/board-dk.c
+@@ -132,8 +132,7 @@ static struct i2c_board_info __initdata dk_i2c_devices[] = {
+ I2C_BOARD_INFO("x9429", 0x28),
+ },
+ {
+- I2C_BOARD_INFO("at24c", 0x50),
+- .type = "24c1024",
++ I2C_BOARD_INFO("24c1024", 0x50),
+ }
+ };
+
+diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
+index b7b79bb..af1a1d8 100644
+--- a/arch/arm/mach-at91/board-eb9200.c
++++ b/arch/arm/mach-at91/board-eb9200.c
+@@ -93,8 +93,7 @@ static struct at91_mmc_data __initdata eb9200_mmc_data = {
+
+ static struct i2c_board_info __initdata eb9200_i2c_devices[] = {
+ {
+- I2C_BOARD_INFO("at24c", 0x50),
+- .type = "24c512",
++ I2C_BOARD_INFO("24c512", 0x50),
+ },
+ };
+
diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
new file mode 100644
index 0000000..e77fad4
@@ -33973,10 +39074,10 @@
#include <asm/mach-types.h>
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
-index a67defd..39733b6 100644
+index a67defd..aa863c1 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
-@@ -26,12 +26,135 @@
+@@ -26,12 +26,139 @@
#include <asm/mach-types.h>
#include <asm/arch/at91_pmc.h>
@@ -34016,6 +39117,15 @@
+#else
+#include <asm/arch/at91sam9_sdramc.h>
+
++#ifdef CONFIG_ARCH_AT91SAM9263
++/*
++ * FIXME either or both the SDRAM controllers (EB0, EB1) might be in use;
++ * handle those cases both here and in the Suspend-To-RAM support.
++ */
++#define AT91_SDRAMC AT91_SDRAMC0
++#warning Assuming EB1 SDRAM controller is *NOT* used
++#endif
++
+static u32 saved_lpr;
+
+static inline void sdram_selfrefresh_enable(void)
@@ -34030,11 +39140,6 @@
+
+#define sdram_selfrefresh_disable() at91_sys_write(AT91_SDRAMC_LPR, saved_lpr)
+
-+/*
-+ * FIXME: The AT91SAM9263 has a second EBI controller which may have
-+ * additional SDRAM. pm_slowclock.S will require a similar fix.
-+ */
-+
+#endif
+
+
@@ -34113,7 +39218,7 @@
static int at91_pm_valid_state(suspend_state_t state)
{
-@@ -125,6 +248,11 @@ EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
+@@ -125,6 +252,11 @@ EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
static void (*slow_clock)(void);
@@ -34125,7 +39230,7 @@
static int at91_pm_enter(suspend_state_t state)
{
-@@ -158,11 +286,14 @@ static int at91_pm_enter(suspend_state_t state)
+@@ -158,11 +290,14 @@ static int at91_pm_enter(suspend_state_t state)
* turning off the main oscillator; reverse on wakeup.
*/
if (slow_clock) {
@@ -34142,7 +39247,7 @@
/* FALLTHROUGH leaving master clock alone */
}
-@@ -175,13 +306,15 @@ static int at91_pm_enter(suspend_state_t state)
+@@ -175,13 +310,15 @@ static int at91_pm_enter(suspend_state_t state)
case PM_SUSPEND_STANDBY:
/*
* NOTE: the Wait-for-Interrupt instruction needs to be
@@ -34162,7 +39267,7 @@
case PM_SUSPEND_ON:
asm("mcr p15, 0, r0, c7, c0, 4"); /* wait for interrupt */
-@@ -196,6 +329,7 @@ static int at91_pm_enter(suspend_state_t state)
+@@ -196,6 +333,7 @@ static int at91_pm_enter(suspend_state_t state)
at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR));
error:
@@ -34170,7 +39275,7 @@
target_state = PM_SUSPEND_ON;
at91_irq_resume();
at91_gpio_resume();
-@@ -220,21 +354,20 @@ static struct platform_suspend_ops at91_pm_ops ={
+@@ -220,21 +358,20 @@ static struct platform_suspend_ops at91_pm_ops ={
static int __init at91_pm_init(void)
{
@@ -34213,6 +39318,23 @@
help
Say Y here if you intend to run this kernel on a Cirrus Logic EDB-7211
evaluation board.
+diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
+index 4143828..c6b94f6 100644
+--- a/arch/arm/mach-davinci/clock.c
++++ b/arch/arm/mach-davinci/clock.c
+@@ -311,11 +311,7 @@ static const struct file_operations proc_davinci_ck_operations = {
+
+ static int __init davinci_ck_proc_init(void)
+ {
+- struct proc_dir_entry *entry;
+-
+- entry = create_proc_entry("davinci_clocks", 0, NULL);
+- if (entry)
+- entry->proc_fops = &proc_davinci_ck_operations;
++ proc_create("davinci_clocks", 0, NULL, &proc_davinci_ck_operations);
+ return 0;
+
+ }
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
index 0ecf997..c1252ca 100644
--- a/arch/arm/mach-ep93xx/Makefile
@@ -34620,6 +39742,38 @@
config MACH_EM7210
bool "Enable support for the Lanner EM7210"
help
+diff --git a/arch/arm/mach-iop32x/em7210.c b/arch/arm/mach-iop32x/em7210.c
+index c947152..4877597 100644
+--- a/arch/arm/mach-iop32x/em7210.c
++++ b/arch/arm/mach-iop32x/em7210.c
+@@ -50,8 +50,7 @@ static struct sys_timer em7210_timer = {
+ */
+ static struct i2c_board_info __initdata em7210_i2c_devices[] = {
+ {
+- I2C_BOARD_INFO("rtc-rs5c372", 0x32),
+- .type = "rs5c372a",
++ I2C_BOARD_INFO("rs5c372a", 0x32),
+ },
+ };
+
+diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c
+index d2a7b04..d4fca75 100644
+--- a/arch/arm/mach-iop32x/glantank.c
++++ b/arch/arm/mach-iop32x/glantank.c
+@@ -176,12 +176,10 @@ static struct f75375s_platform_data glantank_f75375s = {
+
+ static struct i2c_board_info __initdata glantank_i2c_devices[] = {
+ {
+- I2C_BOARD_INFO("rtc-rs5c372", 0x32),
+- .type = "rs5c372a",
++ I2C_BOARD_INFO("rs5c372a", 0x32),
+ },
+ {
+ I2C_BOARD_INFO("f75375", 0x2e),
+- .type = "f75375",
+ .platform_data = &glantank_f75375s,
+ },
+ };
diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
index 98cfa1c..4a89823 100644
--- a/arch/arm/mach-iop32x/iq31244.c
@@ -34662,6 +39816,24 @@
.scan = iop3xx_pci_scan_bus,
.map_irq = iq80321_pci_map_irq,
};
+diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
+index bc91d6e..2741063 100644
+--- a/arch/arm/mach-iop32x/n2100.c
++++ b/arch/arm/mach-iop32x/n2100.c
+@@ -208,12 +208,10 @@ static struct f75375s_platform_data n2100_f75375s = {
+
+ static struct i2c_board_info __initdata n2100_i2c_devices[] = {
+ {
+- I2C_BOARD_INFO("rtc-rs5c372", 0x32),
+- .type = "rs5c372b",
++ I2C_BOARD_INFO("rs5c372b", 0x32),
+ },
+ {
+ I2C_BOARD_INFO("f75375", 0x2e),
+- .type = "f75375",
+ .platform_data = &n2100_f75375s,
+ },
+ };
diff --git a/arch/arm/mach-iop33x/Kconfig b/arch/arm/mach-iop33x/Kconfig
index 45598e0..9aa016b 100644
--- a/arch/arm/mach-iop33x/Kconfig
@@ -34707,6 +39879,82 @@
.scan = iop3xx_pci_scan_bus,
.map_irq = iq80332_pci_map_irq,
};
+diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
+index 8cb0743..a51bfa6 100644
+--- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
++++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
+@@ -65,7 +65,7 @@ static struct platform_device dsmg600_i2c_gpio = {
+
+ static struct i2c_board_info __initdata dsmg600_i2c_board_info [] = {
+ {
+- I2C_BOARD_INFO("rtc-pcf8563", 0x51),
++ I2C_BOARD_INFO("pcf8563", 0x51),
+ },
+ };
+
+diff --git a/arch/arm/mach-ixp4xx/ixp4xx_npe.c b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
+index 83c137e..63a23fa 100644
+--- a/arch/arm/mach-ixp4xx/ixp4xx_npe.c
++++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
+@@ -448,7 +448,9 @@ int npe_send_message(struct npe *npe, const void *msg, const char *what)
+ return -ETIMEDOUT;
+ }
+
++#if DEBUG_MSG > 1
+ debug_msg(npe, "Sending a message took %i cycles\n", cycles);
++#endif
+ return 0;
+ }
+
+@@ -484,7 +486,9 @@ int npe_recv_message(struct npe *npe, void *msg, const char *what)
+ return -ETIMEDOUT;
+ }
+
++#if DEBUG_MSG > 1
+ debug_msg(npe, "Receiving a message took %i cycles\n", cycles);
++#endif
+ return 0;
+ }
+
+diff --git a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
+index e833013..fab94ea 100644
+--- a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
++++ b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
+@@ -184,6 +184,8 @@ void qmgr_release_queue(unsigned int queue)
+ case 3: mask[0] = 0xFF; break;
+ }
+
++ mask[1] = mask[2] = mask[3] = 0;
++
+ while (addr--)
+ shift_mask(mask);
+
+diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
+index 159e1c4..84b5e62 100644
+--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
++++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
+@@ -54,7 +54,7 @@ static struct platform_device nas100d_flash = {
+
+ static struct i2c_board_info __initdata nas100d_i2c_board_info [] = {
+ {
+- I2C_BOARD_INFO("rtc-pcf8563", 0x51),
++ I2C_BOARD_INFO("pcf8563", 0x51),
+ },
+ };
+
+diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
+index d9a1828..a48a665 100644
+--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
++++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
+@@ -57,7 +57,7 @@ static struct i2c_gpio_platform_data nslu2_i2c_gpio_data = {
+
+ static struct i2c_board_info __initdata nslu2_i2c_board_info [] = {
+ {
+- I2C_BOARD_INFO("rtc-x1205", 0x6f),
++ I2C_BOARD_INFO("x1205", 0x6f),
+ },
+ };
+
diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile
index 730a3af..ade42b7 100644
--- a/arch/arm/mach-ks8695/Makefile
@@ -36466,8 +41714,38 @@
# Power Management
obj-$(CONFIG_PM) += pm.o sleep.o
+diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
+index 5079877..4b444fd 100644
+--- a/arch/arm/mach-omap1/board-h2.c
++++ b/arch/arm/mach-omap1/board-h2.c
+@@ -351,11 +351,9 @@ static void __init h2_init_smc91x(void)
+ static struct i2c_board_info __initdata h2_i2c_board_info[] = {
+ {
+ I2C_BOARD_INFO("tps65010", 0x48),
+- .type = "tps65010",
+ .irq = OMAP_GPIO_IRQ(58),
+ }, {
+ I2C_BOARD_INFO("isp1301_omap", 0x2d),
+- .type = "isp1301_omap",
+ .irq = OMAP_GPIO_IRQ(2),
+ },
+ };
+diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
+index c3ef1ee..7fbaa8d 100644
+--- a/arch/arm/mach-omap1/board-h3.c
++++ b/arch/arm/mach-omap1/board-h3.c
+@@ -473,8 +473,7 @@ static struct omap_board_config_kernel h3_config[] __initdata = {
+
+ static struct i2c_board_info __initdata h3_i2c_board_info[] = {
+ {
+- I2C_BOARD_INFO("tps65010", 0x48),
+- .type = "tps65013",
++ I2C_BOARD_INFO("tps65013", 0x48),
+ /* .irq = OMAP_GPIO_IRQ(??), */
+ },
+ };
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
-index 5279e35..4f9baba 100644
+index 5279e35..a66505f 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -32,6 +32,7 @@
@@ -36478,7 +41756,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
-@@ -183,11 +184,80 @@ static struct platform_device *osk5912_devices[] __initdata = {
+@@ -183,11 +184,79 @@ static struct platform_device *osk5912_devices[] __initdata = {
&osk5912_mcbsp1_device,
};
@@ -36552,14 +41830,14 @@
static struct i2c_board_info __initdata osk_i2c_board_info[] = {
{
I2C_BOARD_INFO("tps65010", 0x48),
- .type = "tps65010",
+- .type = "tps65010",
.irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1)),
+ .platform_data = &tps_board,
+
},
/* TODO when driver support is ready:
* - aic23 audio chip at 0x1a
-@@ -198,7 +268,7 @@ static struct i2c_board_info __initdata osk_i2c_board_info[] = {
+@@ -198,7 +267,7 @@ static struct i2c_board_info __initdata osk_i2c_board_info[] = {
static void __init osk_init_smc91x(void)
{
@@ -36568,7 +41846,7 @@
printk("Error requesting gpio 0 for smc91x irq\n");
return;
}
-@@ -210,7 +280,7 @@ static void __init osk_init_smc91x(void)
+@@ -210,7 +279,7 @@ static void __init osk_init_smc91x(void)
static void __init osk_init_cf(void)
{
omap_cfg_reg(M7_1610_GPIO62);
@@ -36577,7 +41855,7 @@
printk("Error requesting gpio 62 for CF irq\n");
return;
}
-@@ -334,7 +404,7 @@ static struct platform_device *mistral_devices[] __initdata = {
+@@ -334,7 +403,7 @@ static struct platform_device *mistral_devices[] __initdata = {
static int mistral_get_pendown_state(void)
{
@@ -36586,7 +41864,7 @@
}
static const struct ads7846_platform_data mistral_ts_info = {
-@@ -396,25 +466,31 @@ static void __init osk_mistral_init(void)
+@@ -396,25 +465,31 @@ static void __init osk_mistral_init(void)
omap_cfg_reg(W14_1610_CCP_DATAP);
/* CAM_PWDN */
@@ -36623,7 +41901,7 @@
set_irq_type(OMAP_GPIO_IRQ(OMAP_MPUIO(2)), IRQT_RISING);
#ifdef CONFIG_PM
/* share the IRQ in case someone wants to use the
-@@ -425,7 +501,7 @@ static void __init osk_mistral_init(void)
+@@ -425,7 +500,7 @@ static void __init osk_mistral_init(void)
IRQF_SHARED, "mistral_wakeup",
&osk_mistral_wake_interrupt);
if (ret != 0) {
@@ -36632,7 +41910,7 @@
printk(KERN_ERR "OSK+Mistral: no wakeup irq, %d?\n",
ret);
} else
-@@ -438,10 +514,8 @@ static void __init osk_mistral_init(void)
+@@ -438,10 +513,8 @@ static void __init osk_mistral_init(void)
* board, like the touchscreen, EEPROM, and wakeup (!) switch.
*/
omap_cfg_reg(PWL);
@@ -36645,7 +41923,7 @@
platform_add_devices(mistral_devices, ARRAY_SIZE(mistral_devices));
}
-@@ -484,44 +558,6 @@ static void __init osk_map_io(void)
+@@ -484,44 +557,6 @@ static void __init osk_map_io(void)
omap1_map_common_io();
}
@@ -56550,7 +61828,7 @@
+initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-orion5x/addr-map.c b/arch/arm/mach-orion5x/addr-map.c
new file mode 100644
-index 0000000..6b17937
+index 0000000..9608503
--- /dev/null
+++ b/arch/arm/mach-orion5x/addr-map.c
@@ -0,0 +1,240 @@
@@ -56575,14 +61853,14 @@
+
+/*
+ * The Orion has fully programable address map. There's a separate address
-+ * map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIE, USB,
++ * map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIe, USB,
+ * Gigabit Ethernet, DMA/XOR engines, etc. Each interface has its own
+ * address decode windows that allow it to access any of the Orion resources.
+ *
+ * CPU address decoding --
+ * Linux assumes that it is the boot loader that already setup the access to
+ * DDR and internal registers.
-+ * Setup access to PCI and PCI-E IO/MEM space is issued by this file.
++ * Setup access to PCI and PCIe IO/MEM space is issued by this file.
+ * Setup access to various devices located on the device bus interface (e.g.
+ * flashes, RTC, etc) should be issued by machine-setup.c according to
+ * specific board population (by using orion5x_setup_*_win()).
@@ -56796,7 +62074,7 @@
+}
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
new file mode 100644
-index 0000000..439c778
+index 0000000..968deb5
--- /dev/null
+++ b/arch/arm/mach-orion5x/common.c
@@ -0,0 +1,391 @@
@@ -56934,7 +62212,7 @@
+static struct resource orion5x_ehci0_resources[] = {
+ {
+ .start = ORION5X_USB0_PHYS_BASE,
-+ .end = ORION5X_USB0_PHYS_BASE + SZ_4K,
++ .end = ORION5X_USB0_PHYS_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
@@ -56947,7 +62225,7 @@
+static struct resource orion5x_ehci1_resources[] = {
+ {
+ .start = ORION5X_USB1_PHYS_BASE,
-+ .end = ORION5X_USB1_PHYS_BASE + SZ_4K,
++ .end = ORION5X_USB1_PHYS_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
@@ -57119,7 +62397,7 @@
+ ****************************************************************************/
+
+/*
-+ * Identify device ID and rev from PCIE configuration header space '0'.
++ * Identify device ID and rev from PCIe configuration header space '0'.
+ */
+static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name)
+{
@@ -57193,10 +62471,10 @@
+}
diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h
new file mode 100644
-index 0000000..f4c4c9a
+index 0000000..14adf8d
--- /dev/null
+++ b/arch/arm/mach-orion5x/common.h
-@@ -0,0 +1,72 @@
+@@ -0,0 +1,71 @@
+#ifndef __ARCH_ORION5X_COMMON_H
+#define __ARCH_ORION5X_COMMON_H
+
@@ -57232,10 +62510,9 @@
+struct pci_bus;
+
+void orion5x_pcie_id(u32 *dev, u32 *rev);
-+int orion5x_pcie_local_bus_nr(void);
-+int orion5x_pci_local_bus_nr(void);
+int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys);
+struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
++int orion5x_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin);
+
+/*
+ * Valid GPIO pins according to MPP setup, used by machine-setup.
@@ -57271,10 +62548,10 @@
+#endif
diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c
new file mode 100644
-index 0000000..872aed3
+index 0000000..44c6434
--- /dev/null
+++ b/arch/arm/mach-orion5x/db88f5281-setup.c
-@@ -0,0 +1,361 @@
+@@ -0,0 +1,362 @@
+/*
+ * arch/arm/mach-orion5x/db88f5281-setup.c
+ *
@@ -57518,14 +62795,17 @@
+
+static int __init db88f5281_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
++ int irq;
++
+ /*
-+ * PCIE IRQ is connected internally (not GPIO)
++ * Check for devices with hard-wired IRQs.
+ */
-+ if (dev->bus->number == orion5x_pcie_local_bus_nr())
-+ return IRQ_ORION5X_PCIE0_INT;
++ irq = orion5x_pci_map_irq(dev, slot, pin);
++ if (irq != -1)
++ return irq;
+
+ /*
-+ * PCI IRQs are connected via GPIOs
++ * PCI IRQs are connected via GPIOs.
+ */
+ switch (slot - DB88F5281_PCI_SLOT0_OFFS) {
+ case 0:
@@ -57569,9 +62849,7 @@
+ * RTC DS1339 on I2C bus
+ ****************************************************************************/
+static struct i2c_board_info __initdata db88f5281_i2c_rtc = {
-+ .driver_name = "rtc-ds1307",
-+ .type = "ds1339",
-+ .addr = 0x68,
++ I2C_BOARD_INFO("ds1339", 0x68),
+};
+
+/*****************************************************************************
@@ -57638,10 +62916,10 @@
+MACHINE_END
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
new file mode 100644
-index 0000000..d67790e
+index 0000000..f9430f5
--- /dev/null
+++ b/arch/arm/mach-orion5x/dns323-setup.c
-@@ -0,0 +1,320 @@
+@@ -0,0 +1,322 @@
+/*
+ * arch/arm/mach-orion5x/dns323-setup.c
+ *
@@ -57687,11 +62965,16 @@
+
+static int __init dns323_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
-+ /* PCI-E */
-+ if (dev->bus->number == orion5x_pcie_local_bus_nr())
-+ return IRQ_ORION5X_PCIE0_INT;
++ int irq;
++
++ /*
++ * Check for devices with hard-wired IRQs.
++ */
++ irq = orion5x_pci_map_irq(dev, slot, pin);
++ if (irq != -1)
++ return irq;
+
-+ pr_err("%s: requested mapping for unknown bus\n", __func__);
++ pr_err("%s: requested mapping for unknown device\n", __func__);
+
+ return -1;
+}
@@ -57864,19 +63147,16 @@
+static struct i2c_board_info __initdata dns323_i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("g760a", 0x3e),
-+ .type = "g760a",
+ },
+#if 0
+ /* this entry requires the new-style driver model lm75 driver,
+ * for the meantime "insmod lm75.ko force_lm75=0,0x48" is needed */
+ {
-+ I2C_BOARD_INFO("lm75", 0x48),
-+ .type = "g751",
++ I2C_BOARD_INFO("g751", 0x48),
+ },
+#endif
+ {
-+ I2C_BOARD_INFO("rtc-m41t80", 0x68),
-+ .type = "m41t80",
++ I2C_BOARD_INFO("m41t80", 0x68),
+ }
+};
+
@@ -57897,9 +63177,9 @@
+ */
+ orion5x_setup_dev_boot_win(DNS323_NOR_BOOT_BASE, DNS323_NOR_BOOT_SIZE);
+
-+ /* DNS-323 has a Marvell 88X7042 SATA controller attached via PCIE
++ /* DNS-323 has a Marvell 88X7042 SATA controller attached via PCIe
+ *
-+ * Open a special address decode windows for the PCIE WA.
++ * Open a special address decode windows for the PCIe WA.
+ */
+ orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
+ ORION5X_PCIE_WA_SIZE);
@@ -58413,10 +63693,10 @@
+}
diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c
new file mode 100644
-index 0000000..9141345
+index 0000000..8841086
--- /dev/null
+++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
-@@ -0,0 +1,256 @@
+@@ -0,0 +1,260 @@
+/*
+ * arch/arm/mach-orion5x/kurobox_pro-setup.c
+ *
@@ -58539,13 +63819,19 @@
+
+static int __init kurobox_pro_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
++ int irq;
++
++ /*
++ * Check for devices with hard-wired IRQs.
++ */
++ irq = orion5x_pci_map_irq(dev, slot, pin);
++ if (irq != -1)
++ return irq;
++
+ /*
+ * PCI isn't used on the Kuro
+ */
-+ if (dev->bus->number == orion5x_pcie_local_bus_nr())
-+ return IRQ_ORION5X_PCIE0_INT;
-+ else
-+ printk(KERN_ERR "kurobox_pro_pci_map_irq failed, unknown bus\n");
++ printk(KERN_ERR "kurobox_pro_pci_map_irq failed, unknown bus\n");
+
+ return -1;
+}
@@ -58581,9 +63867,7 @@
+ * RTC 5C372a on I2C bus
+ ****************************************************************************/
+static struct i2c_board_info __initdata kurobox_pro_i2c_rtc = {
-+ .driver_name = "rtc-rs5c372",
-+ .type = "rs5c372a",
-+ .addr = 0x32,
++ I2C_BOARD_INFO("rs5c372a", 0x32),
+};
+
+/*****************************************************************************
@@ -58612,7 +63896,7 @@
+ orion5x_setup_dev0_win(KUROBOX_PRO_NAND_BASE, KUROBOX_PRO_NAND_SIZE);
+
+ /*
-+ * Open a special address decode windows for the PCIE WA.
++ * Open a special address decode windows for the PCIe WA.
+ */
+ orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
+ ORION5X_PCIE_WA_SIZE);
@@ -58675,10 +63959,10 @@
+#endif
diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c
new file mode 100644
-index 0000000..fdf99fc
+index 0000000..9d5d39f
--- /dev/null
+++ b/arch/arm/mach-orion5x/pci.c
-@@ -0,0 +1,559 @@
+@@ -0,0 +1,567 @@
+/*
+ * arch/arm/mach-orion5x/pci.c
+ *
@@ -58722,11 +64006,6 @@
+ *rev = orion_pcie_rev(PCIE_BASE);
+}
+
-+int __init orion5x_pcie_local_bus_nr(void)
-+{
-+ return orion_pcie_get_local_bus_nr(PCIE_BASE);
-+}
-+
+static int pcie_valid_config(int bus, int dev)
+{
+ /*
@@ -58950,7 +64229,7 @@
+ */
+static DEFINE_SPINLOCK(orion5x_pci_lock);
+
-+int orion5x_pci_local_bus_nr(void)
++static int orion5x_pci_local_bus_nr(void)
+{
+ u32 conf = orion5x_read(PCI_P2P_CONF);
+ return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS);
@@ -59238,12 +64517,25 @@
+
+ return bus;
+}
++
++int __init orion5x_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ int bus = dev->bus->number;
++
++ /*
++ * PCIe endpoint?
++ */
++ if (bus < orion5x_pci_local_bus_nr())
++ return IRQ_ORION5X_PCIE0_INT;
++
++ return -1;
++}
diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c
new file mode 100644
-index 0000000..37e8b2d
+index 0000000..81abc10
--- /dev/null
+++ b/arch/arm/mach-orion5x/rd88f5182-setup.c
-@@ -0,0 +1,312 @@
+@@ -0,0 +1,313 @@
+/*
+ * arch/arm/mach-orion5x/rd88f5182-setup.c
+ *
@@ -59418,11 +64710,14 @@
+
+static int __init rd88f5182_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
++ int irq;
++
+ /*
-+ * PCI-E isn't used on the RD2
++ * Check for devices with hard-wired IRQs.
+ */
-+ if (dev->bus->number == orion5x_pcie_local_bus_nr())
-+ return IRQ_ORION5X_PCIE0_INT;
++ irq = orion5x_pci_map_irq(dev, slot, pin);
++ if (irq != -1)
++ return irq;
+
+ /*
+ * PCI IRQs are connected via GPIOs
@@ -59470,9 +64765,7 @@
+ * RTC DS1338 on I2C bus
+ ****************************************************************************/
+static struct i2c_board_info __initdata rd88f5182_i2c_rtc = {
-+ .driver_name = "rtc-ds1307",
-+ .type = "ds1338",
-+ .addr = 0x68,
++ I2C_BOARD_INFO("ds1338", 0x68),
+};
+
+/*****************************************************************************
@@ -59505,7 +64798,7 @@
+ orion5x_setup_dev1_win(RD88F5182_NOR_BASE, RD88F5182_NOR_SIZE);
+
+ /*
-+ * Open a special address decode windows for the PCIE WA.
++ * Open a special address decode windows for the PCIe WA.
+ */
+ orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
+ ORION5X_PCIE_WA_SIZE);
@@ -59558,10 +64851,10 @@
+MACHINE_END
diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c
new file mode 100644
-index 0000000..fd43863
+index 0000000..9afb41e
--- /dev/null
+++ b/arch/arm/mach-orion5x/ts209-setup.c
-@@ -0,0 +1,442 @@
+@@ -0,0 +1,444 @@
+/*
+ * QNAP TS-109/TS-209 Board Setup
+ *
@@ -59705,14 +64998,17 @@
+
+static int __init qnap_ts209_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
++ int irq;
++
+ /*
-+ * PCIE IRQ is connected internally (not GPIO)
++ * Check for devices with hard-wired IRQs.
+ */
-+ if (dev->bus->number == orion5x_pcie_local_bus_nr())
-+ return IRQ_ORION5X_PCIE0_INT;
++ irq = orion5x_pci_map_irq(dev, slot, pin);
++ if (irq != -1)
++ return irq;
+
+ /*
-+ * PCI IRQs are connected via GPIOs
++ * PCI IRQs are connected via GPIOs.
+ */
+ switch (slot - QNAP_TS209_PCI_SLOT0_OFFS) {
+ case 0:
@@ -59840,8 +65136,7 @@
+#define TS209_RTC_GPIO 3
+
+static struct i2c_board_info __initdata qnap_ts209_i2c_rtc = {
-+ .driver_name = "rtc-s35390a",
-+ .addr = 0x30,
++ I2C_BOARD_INFO("s35390a", 0x30),
+ .irq = 0,
+};
+
@@ -59937,7 +65232,7 @@
+ QNAP_TS209_NOR_BOOT_SIZE);
+
+ /*
-+ * Open a special address decode windows for the PCIE WA.
++ * Open a special address decode windows for the PCIe WA.
+ */
+ orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
+ ORION5X_PCIE_WA_SIZE);
@@ -60067,7 +65362,7 @@
choice
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
-index 6e0c4f5..7cdcb45 100644
+index 6e0c4f5..6a83085 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -5,13 +5,14 @@
@@ -60077,9 +65372,9 @@
-obj-$(CONFIG_PXA25x) += pxa25x.o
-obj-$(CONFIG_PXA27x) += pxa27x.o
-obj-$(CONFIG_PXA3xx) += pxa3xx.o mfp.o smemc.o
-+obj-$(CONFIG_PXA25x) += pxa25x.o mfp-pxa2xx.o
-+obj-$(CONFIG_PXA27x) += pxa27x.o mfp-pxa2xx.o
-+obj-$(CONFIG_PXA3xx) += pxa3xx.o mfp-pxa3xx.o smemc.o
++obj-$(CONFIG_PXA25x) += mfp-pxa2xx.o pxa25x.o
++obj-$(CONFIG_PXA27x) += mfp-pxa2xx.o pxa27x.o
++obj-$(CONFIG_PXA3xx) += mfp-pxa3xx.o pxa3xx.o smemc.o
obj-$(CONFIG_CPU_PXA300) += pxa300.o
obj-$(CONFIG_CPU_PXA320) += pxa320.o
@@ -60280,7 +65575,7 @@
#include <asm/arch/ohci.h>
#include <asm/arch/mmc.h>
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
-index 80721c6..331f29b 100644
+index 80721c6..4461793 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -19,14 +19,8 @@
@@ -60298,7 +65593,19 @@
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/mach/map.h>
-@@ -134,59 +128,3 @@ void __init pxa_map_io(void)
+@@ -96,11 +90,6 @@ static struct map_desc standard_io_desc[] __initdata = {
+ .pfn = __phys_to_pfn(0x40000000),
+ .length = 0x02000000,
+ .type = MT_DEVICE
+- }, { /* LCD */
+- .virtual = 0xf4000000,
+- .pfn = __phys_to_pfn(0x44000000),
+- .length = 0x00100000,
+- .type = MT_DEVICE
+ }, { /* Mem Ctl */
+ .virtual = 0xf6000000,
+ .pfn = __phys_to_pfn(0x48000000),
+@@ -134,59 +123,3 @@ void __init pxa_map_io(void)
iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
get_clk_frequency_khz(1);
}
@@ -60754,10 +66061,10 @@
+core_initcall(pxa_gpio_init);
diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
new file mode 100644
-index 0000000..f01d185
+index 0000000..bdf2397
--- /dev/null
+++ b/arch/arm/mach-pxa/gumstix.c
-@@ -0,0 +1,147 @@
+@@ -0,0 +1,148 @@
+/*
+ * linux/arch/arm/mach-pxa/gumstix.c
+ *
@@ -60800,6 +66107,7 @@
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+
+#include "generic.h"
+
@@ -61329,7 +66637,7 @@
#include "leds.h"
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
-index 0a4b54c..0339606 100644
+index 0a4b54c..5306544 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -37,12 +37,11 @@
@@ -61368,7 +66676,17 @@
};
static struct resource smc91x_resources[] = {
-@@ -300,6 +314,54 @@ static void littleton_init_lcd(void)
+@@ -287,8 +301,7 @@ static struct pxafb_mode_info tpo_tdo24mtea1_modes[] = {
+ static struct pxafb_mach_info littleton_lcd_info = {
+ .modes = tpo_tdo24mtea1_modes,
+ .num_modes = 2,
+- .lccr0 = LCCR0_Act,
+- .lccr3 = LCCR3_HSP | LCCR3_VSP,
++ .lcd_conn = LCD_COLOR_TFT_16BPP,
+ .pxafb_lcd_power = littleton_lcd_power,
+ };
+
+@@ -300,6 +313,54 @@ static void littleton_init_lcd(void)
static inline void littleton_init_lcd(void) {};
#endif /* CONFIG_FB_PXA || CONFIG_FB_PXA_MODULES */
@@ -61423,7 +66741,7 @@
static void __init littleton_init(void)
{
/* initialize MFP configurations */
-@@ -312,6 +374,7 @@ static void __init littleton_init(void)
+@@ -312,6 +373,7 @@ static void __init littleton_init(void)
platform_device_register(&smc91x_device);
littleton_init_lcd();
@@ -61444,7 +66762,7 @@
#include <asm/arch/audio.h>
#include <asm/arch/pxafb.h>
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
-index e7ae4bb..ca209c4 100644
+index e7ae4bb..0993f4d 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -42,6 +42,7 @@
@@ -61550,6 +66868,17 @@
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = -1,
+@@ -360,8 +395,8 @@ static struct pxafb_mach_info sharp_lm8v31 = {
+ .num_modes = 1,
+ .cmap_inverse = 0,
+ .cmap_static = 0,
+- .lccr0 = LCCR0_SDS,
+- .lccr3 = LCCR3_PCP | LCCR3_Acb(255),
++ .lcd_conn = LCD_COLOR_DSTN_16BPP | LCD_PCLK_EDGE_FALL |
++ LCD_AC_BIAS_FREQ(255);
+ };
+
+ #define MMC_POLL_RATE msecs_to_jiffies(1000)
@@ -404,10 +439,6 @@ static int lubbock_mci_init(struct device *dev,
irq_handler_t detect_int,
void *data)
@@ -61618,10 +66947,10 @@
}
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
-index d98ef7a..d70be75 100644
+index d98ef7a..badba06 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
-@@ -16,24 +16,106 @@
+@@ -16,24 +16,114 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -61723,17 +67052,26 @@
+ GPIO82_CIF_DD_5,
+ GPIO84_CIF_FV,
+ GPIO85_CIF_LV,
++
++ /* Magician specific input GPIOs */
++ GPIO9_GPIO, /* unknown */
++ GPIO10_GPIO, /* GSM_IRQ */
++ GPIO13_GPIO, /* CPLD_IRQ */
++ GPIO107_GPIO, /* DS1WM_IRQ */
++ GPIO108_GPIO, /* GSM_READY */
++ GPIO115_GPIO, /* nPEN_IRQ */
+};
+
/*
* IRDA
*/
-@@ -83,8 +165,64 @@ static struct platform_device gpio_keys = {
+@@ -83,8 +173,64 @@ static struct platform_device gpio_keys = {
.id = -1,
};
+
-+/*
+ /*
+- * LCD - Toppoly TD028STEB1
+ * EGPIO (Xilinx CPLD)
+ *
+ * 7 32-bit aligned 8-bit registers: 3x output, 1x irq, 3x input
@@ -61788,13 +67126,12 @@
+ },
+};
+
- /*
-- * LCD - Toppoly TD028STEB1
++/*
+ * LCD - Toppoly TD028STEB1 or Samsung LTP280QV
*/
static struct pxafb_mode_info toppoly_modes[] = {
-@@ -103,12 +241,99 @@ static struct pxafb_mode_info toppoly_modes[] = {
+@@ -103,12 +249,99 @@ static struct pxafb_mode_info toppoly_modes[] = {
},
};
@@ -61899,7 +67236,7 @@
};
/*
-@@ -120,9 +345,18 @@ static void magician_set_bl_intensity(int intensity)
+@@ -120,9 +353,18 @@ static void magician_set_bl_intensity(int intensity)
if (intensity) {
PWM_CTRL0 = 1;
PWM_PERVAL0 = 0xc8;
@@ -61919,7 +67256,7 @@
pxa_set_cken(CKEN_PWM0, 0);
}
}
-@@ -130,18 +364,215 @@ static void magician_set_bl_intensity(int intensity)
+@@ -130,18 +372,236 @@ static void magician_set_bl_intensity(int intensity)
static struct generic_bl_info backlight_info = {
.default_intensity = 0x64,
.limit_mask = 0x0b,
@@ -61999,7 +67336,7 @@
+
+static struct platform_device pasic3;
+
-+static struct pasic3_leds_machinfo __devinit pasic3_leds_info = {
++static struct pasic3_leds_machinfo pasic3_leds_info = {
+ .num_leds = ARRAY_SIZE(pasic3_leds),
+ .power_gpio = EGPIO_MAGICIAN_LED_POWER,
+ .leds = pasic3_leds,
@@ -62104,9 +67441,28 @@
+static int magician_mci_init(struct device *dev,
+ irq_handler_t detect_irq, void *data)
+{
-+ return request_irq(IRQ_MAGICIAN_SD, detect_irq,
++ int err;
++
++ err = request_irq(IRQ_MAGICIAN_SD, detect_irq,
+ IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
+ "MMC card detect", data);
++ if (err)
++ goto err_request_irq;
++ err = gpio_request(EGPIO_MAGICIAN_SD_POWER, "SD_POWER");
++ if (err)
++ goto err_request_power;
++ err = gpio_request(EGPIO_MAGICIAN_nSD_READONLY, "nSD_READONLY");
++ if (err)
++ goto err_request_readonly;
++
++ return 0;
++
++err_request_readonly:
++ gpio_free(EGPIO_MAGICIAN_SD_POWER);
++err_request_power:
++ free_irq(IRQ_MAGICIAN_SD, data);
++err_request_irq:
++ return err;
+}
+
+static void magician_mci_setpower(struct device *dev, unsigned int vdd)
@@ -62123,6 +67479,8 @@
+
+static void magician_mci_exit(struct device *dev, void *data)
+{
++ gpio_free(EGPIO_MAGICIAN_nSD_READONLY);
++ gpio_free(EGPIO_MAGICIAN_SD_POWER);
+ free_irq(IRQ_MAGICIAN_SD, data);
+}
+
@@ -62137,7 +67495,7 @@
/*
* USB OHCI
-@@ -166,6 +597,11 @@ static struct pxaohci_platform_data magician_ohci_info = {
+@@ -166,6 +626,11 @@ static struct pxaohci_platform_data magician_ohci_info = {
* StrataFlash
*/
@@ -62149,7 +67507,7 @@
#define PXA_CS_SIZE 0x04000000
static struct resource strataflash_resource = {
-@@ -176,13 +612,14 @@ static struct resource strataflash_resource = {
+@@ -176,13 +641,14 @@ static struct resource strataflash_resource = {
static struct physmap_flash_data strataflash_data = {
.width = 4,
@@ -62165,7 +67523,7 @@
.dev = {
.platform_data = &strataflash_data,
},
-@@ -194,16 +631,43 @@ static struct platform_device strataflash = {
+@@ -194,16 +660,57 @@ static struct platform_device strataflash = {
static struct platform_device *devices[] __initdata = {
&gpio_keys,
@@ -62181,29 +67539,44 @@
{
+ void __iomem *cpld;
+ int lcd_select;
++ int err;
++
++ gpio_request(GPIO13_MAGICIAN_CPLD_IRQ, "CPLD_IRQ");
++ gpio_request(GPIO107_MAGICIAN_DS1WM_IRQ, "DS1WM_IRQ");
+
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(magician_pin_config));
+
platform_add_devices(devices, ARRAY_SIZE(devices));
++
++ err = gpio_request(GPIO83_MAGICIAN_nIR_EN, "nIR_EN");
++ if (!err) {
++ gpio_direction_output(GPIO83_MAGICIAN_nIR_EN, 1);
++ pxa_set_ficp_info(&magician_ficp_info);
++ }
+ pxa_set_i2c_info(NULL);
+ pxa_set_mci_info(&magician_mci_info);
pxa_set_ohci_info(&magician_ohci_info);
- pxa_set_ficp_info(&magician_ficp_info);
+- pxa_set_ficp_info(&magician_ficp_info);
- set_pxa_fb_info(&toppoly_info);
+
+ /* Check LCD type we have */
+ cpld = ioremap_nocache(PXA_CS3_PHYS, 0x1000);
+ if (cpld) {
+ u8 board_id = __raw_readb(cpld+0x14);
++ iounmap(cpld);
+ system_rev = board_id & 0x7;
+ lcd_select = board_id & 0x8;
-+ iounmap(cpld);
+ pr_info("LCD type: %s\n", lcd_select ? "Samsung" : "Toppoly");
-+ if (lcd_select && (system_rev < 3))
-+ pxa_gpio_mode(GPIO75_MAGICIAN_SAMSUNG_POWER_MD);
-+ pxa_gpio_mode(GPIO104_MAGICIAN_LCD_POWER_1_MD);
-+ pxa_gpio_mode(GPIO105_MAGICIAN_LCD_POWER_2_MD);
-+ pxa_gpio_mode(GPIO106_MAGICIAN_LCD_POWER_3_MD);
++ if (lcd_select && (system_rev < 3)) {
++ gpio_request(GPIO75_MAGICIAN_SAMSUNG_POWER, "SAMSUNG_POWER");
++ gpio_direction_output(GPIO75_MAGICIAN_SAMSUNG_POWER, 0);
++ }
++ gpio_request(GPIO104_MAGICIAN_LCD_POWER_1, "LCD_POWER_1");
++ gpio_request(GPIO105_MAGICIAN_LCD_POWER_2, "LCD_POWER_2");
++ gpio_request(GPIO106_MAGICIAN_LCD_POWER_3, "LCD_POWER_3");
++ gpio_direction_output(GPIO104_MAGICIAN_LCD_POWER_1, 0);
++ gpio_direction_output(GPIO105_MAGICIAN_LCD_POWER_2, 0);
++ gpio_direction_output(GPIO106_MAGICIAN_LCD_POWER_3, 0);
+ set_pxa_fb_info(lcd_select ? &samsung_info : &toppoly_info);
+ } else
+ pr_err("LCD detection: CPLD mapping failed\n");
@@ -62211,7 +67584,7 @@
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
-index 72a436f..18d47cf 100644
+index 72a436f..7399fb3 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -24,6 +24,8 @@
@@ -62335,7 +67708,16 @@
if (brightness == 0)
pxa_set_cken(CKEN_PWM0, 0);
return 0; /* pointless return value */
-@@ -362,16 +442,6 @@ static int mainstone_mci_init(struct device *dev, irq_handler_t mstone_detect_in
+@@ -354,24 +434,13 @@ static struct pxafb_mode_info toshiba_ltm035a776c_mode = {
+
+ static struct pxafb_mach_info mainstone_pxafb_info = {
+ .num_modes = 1,
+- .lccr0 = LCCR0_Act,
+- .lccr3 = LCCR3_PCP,
++ .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
+ };
+
+ static int mainstone_mci_init(struct device *dev, irq_handler_t mstone_detect_int, void *data)
{
int err;
@@ -62352,7 +67734,7 @@
/* make sure SD/Memory Stick multiplexer's signals
* are routed to MMC controller
*/
-@@ -434,19 +504,39 @@ static struct pxaficp_platform_data mainstone_ficp_platform_data = {
+@@ -434,19 +503,39 @@ static struct pxaficp_platform_data mainstone_ficp_platform_data = {
.transceiver_mode = mainstone_irda_transceiver_mode,
};
@@ -62396,7 +67778,7 @@
/* Set the Power Control Polarity Low and Power Sense
Polarity Low to active low. */
UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
-@@ -460,10 +550,63 @@ static struct pxaohci_platform_data mainstone_ohci_platform_data = {
+@@ -460,10 +549,63 @@ static struct pxaohci_platform_data mainstone_ohci_platform_data = {
.init = mainstone_ohci_init,
};
@@ -62460,7 +67842,7 @@
mst_flash_data[0].width = (BOOT_DEF & 1) ? 2 : 4;
mst_flash_data[1].width = 4;
-@@ -480,31 +623,6 @@ static void __init mainstone_init(void)
+@@ -480,31 +622,6 @@ static void __init mainstone_init(void)
*/
ARB_CNTRL = ARB_CORE_PARK | 0x234;
@@ -62492,7 +67874,7 @@
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
/* reading Mainstone's "Virtual Configuration Register"
-@@ -520,6 +638,9 @@ static void __init mainstone_init(void)
+@@ -520,6 +637,9 @@ static void __init mainstone_init(void)
pxa_set_mci_info(&mainstone_mci_platform_data);
pxa_set_ficp_info(&mainstone_ficp_platform_data);
pxa_set_ohci_info(&mainstone_ohci_platform_data);
@@ -62502,7 +67884,7 @@
}
-@@ -537,23 +658,9 @@ static void __init mainstone_map_io(void)
+@@ -537,23 +657,9 @@ static void __init mainstone_map_io(void)
pxa_map_io();
iotable_init(mainstone_io_desc, ARRAY_SIZE(mainstone_io_desc));
@@ -63312,7 +68694,7 @@
#include <asm/arch/pxa2xx_spi.h>
#include <asm/arch/pcm027.h>
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
-index 3dda16a..e6be9d0 100644
+index 3dda16a..49d951d 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -23,8 +23,16 @@
@@ -63332,7 +68714,7 @@
#include <asm/arch/mmc.h>
#include <asm/arch/ohci.h>
#include <asm/arch/pcm990_baseboard.h>
-@@ -258,6 +266,76 @@ static struct pxaohci_platform_data pcm990_ohci_platform_data = {
+@@ -258,6 +266,73 @@ static struct pxaohci_platform_data pcm990_ohci_platform_data = {
};
/*
@@ -63390,16 +68772,13 @@
+static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
+ {
+ /* Must initialize before the camera(s) */
-+ I2C_BOARD_INFO("pca953x", 0x41),
-+ .type = "pca9536",
++ I2C_BOARD_INFO("pca9536", 0x41),
+ .platform_data = &pca9536_data,
+ }, {
+ I2C_BOARD_INFO("mt9v022", 0x48),
-+ .type = "mt9v022",
+ .platform_data = &iclink[0], /* With extender */
+ }, {
+ I2C_BOARD_INFO("mt9m001", 0x5d),
-+ .type = "mt9m001",
+ .platform_data = &iclink[0], /* With extender */
+ },
+};
@@ -63409,7 +68788,7 @@
* AC97 support
* Note: The connected AC97 mixer also reports interrupts at PCM990_AC97_IRQ
*/
-@@ -326,5 +404,14 @@ void __init pcm990_baseboard_init(void)
+@@ -326,5 +401,14 @@ void __init pcm990_baseboard_init(void)
/* USB host */
pxa_set_ohci_info(&pcm990_ohci_platform_data);
@@ -63424,6 +68803,21 @@
+
printk(KERN_INFO"PCM-990 Evaluation baseboard initialized\n");
}
+diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
+index 039194c..ec1bbf3 100644
+--- a/arch/arm/mach-pxa/pm.c
++++ b/arch/arm/mach-pxa/pm.c
+@@ -46,8 +46,8 @@ int pxa_pm_enter(suspend_state_t state)
+ sleep_save_checksum += sleep_save[i];
+ }
+
+- /* Clear sleep reset status */
+- RCSR = RCSR_SMR;
++ /* Clear reset status */
++ RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+
+ /* *** go zzz *** */
+ pxa_cpu_pm_fns->enter(state);
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 209eabf..ca5ac19 100644
--- a/arch/arm/mach-pxa/poodle.c
@@ -63614,7 +69008,7 @@
-subsys_initcall(pxa27x_init);
+postcore_initcall(pxa27x_init);
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
-index 35f25fd..dde355e 100644
+index 35f25fd..b6a6f5f 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -110,6 +110,25 @@ unsigned int pxa3xx_get_memclk_frequency_10khz(void)
@@ -63710,7 +69104,16 @@
switch (state) {
case PM_SUSPEND_STANDBY:
-@@ -446,15 +497,9 @@ static int pxa3xx_set_wake(unsigned int irq, unsigned int on)
+@@ -435,6 +486,8 @@ static int pxa3xx_set_wake(unsigned int irq, unsigned int on)
+ case IRQ_MMC3:
+ mask = ADXER_MFP_GEN12;
+ break;
++ default:
++ return -EINVAL;
+ }
+
+ local_irq_save(flags);
+@@ -446,15 +499,9 @@ static int pxa3xx_set_wake(unsigned int irq, unsigned int on)
return 0;
}
@@ -63727,7 +69130,7 @@
#endif
void __init pxa3xx_init_irq(void)
-@@ -465,10 +510,8 @@ void __init pxa3xx_init_irq(void)
+@@ -465,10 +512,8 @@ void __init pxa3xx_init_irq(void)
value |= (1 << 6);
__asm__ __volatile__("mcr p15, 0, %0, c15, c1, 0\n": :"r"(value));
@@ -63740,7 +69143,7 @@
}
/*
-@@ -490,11 +533,9 @@ static struct platform_device *devices[] __initdata = {
+@@ -490,11 +535,9 @@ static struct platform_device *devices[] __initdata = {
static struct sys_device pxa3xx_sysdev[] = {
{
@@ -63753,7 +69156,7 @@
}, {
.cls = &pxa_gpio_sysclass,
},
-@@ -532,4 +573,4 @@ static int __init pxa3xx_init(void)
+@@ -532,4 +575,4 @@ static int __init pxa3xx_init(void)
return ret;
}
@@ -64247,7 +69650,7 @@
#include <asm/arch/audio.h>
#include <asm/arch/pxafb.h>
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
-index afd2cbf..dbb5462 100644
+index afd2cbf..4a00280 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -26,6 +26,7 @@
@@ -64267,7 +69670,27 @@
int lcd_id;
int lcd_orientation;
-@@ -249,6 +252,71 @@ static void __init zylonite_init_mmc(void)
+@@ -94,8 +97,7 @@ static struct pxafb_mode_info toshiba_ltm04c380k_mode = {
+
+ static struct pxafb_mach_info zylonite_toshiba_lcd_info = {
+ .num_modes = 1,
+- .lccr0 = LCCR0_Act,
+- .lccr3 = LCCR3_PCP,
++ .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
+ .pxafb_backlight_power = zylonite_backlight_power,
+ };
+
+@@ -131,8 +133,7 @@ static struct pxafb_mode_info sharp_ls037_modes[] = {
+ static struct pxafb_mach_info zylonite_sharp_lcd_info = {
+ .modes = sharp_ls037_modes,
+ .num_modes = 2,
+- .lccr0 = LCCR0_Act,
+- .lccr3 = LCCR3_PCP | LCCR3_HSP | LCCR3_VSP,
++ .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
+ .pxafb_backlight_power = zylonite_backlight_power,
+ };
+
+@@ -249,6 +250,71 @@ static void __init zylonite_init_mmc(void)
static inline void zylonite_init_mmc(void) {}
#endif
@@ -64339,7 +69762,7 @@
static void __init zylonite_init(void)
{
/* board-processor specific initialization */
-@@ -265,6 +333,7 @@ static void __init zylonite_init(void)
+@@ -265,6 +331,7 @@ static void __init zylonite_init(void)
zylonite_init_lcd();
zylonite_init_mmc();
@@ -66351,7 +71774,7 @@
#include "clock.h"
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
-index 76348f0..1b8229d 100644
+index 76348f0..33ed048 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -18,6 +18,7 @@ config CPU_ARM610
@@ -66514,7 +71937,7 @@
select CPU_CACHE_VIVT
select CPU_CP15_MMU
select CPU_TLB_V4WBI if MMU
-@@ -345,10 +365,11 @@ config CPU_XSC3
+@@ -345,13 +365,14 @@ config CPU_XSC3
# Feroceon
config CPU_FEROCEON
bool
@@ -66526,7 +71949,11 @@
+ select CPU_PABRT_NOIFAR
select CPU_CACHE_VIVT
select CPU_CP15_MMU
- select CPU_COPY_V4WB if MMU
+- select CPU_COPY_V4WB if MMU
++ select CPU_COPY_FEROCEON if MMU
+ select CPU_TLB_V4WBI if MMU
+
+ config CPU_FEROCEON_OLD_ID
@@ -366,11 +387,12 @@ config CPU_FEROCEON_OLD_ID
# ARMv6
config CPU_V6
@@ -66567,7 +71994,17 @@
# The cache model
config CPU_CACHE_V3
bool
-@@ -572,6 +601,13 @@ config ARM_THUMB
+@@ -494,6 +523,9 @@ config CPU_COPY_V4WT
+ config CPU_COPY_V4WB
+ bool
+
++config CPU_COPY_FEROCEON
++ bool
++
+ config CPU_COPY_V6
+ bool
+
+@@ -572,6 +604,13 @@ config ARM_THUMB
If you don't know what this all is, saying Y is a safe choice.
@@ -66581,7 +72018,16 @@
config CPU_BIG_ENDIAN
bool "Build big-endian kernel"
depends on ARCH_SUPPORTS_BIG_ENDIAN
-@@ -671,5 +707,9 @@ config OUTER_CACHE
+@@ -622,7 +661,7 @@ config CPU_DCACHE_SIZE
+
+ config CPU_DCACHE_WRITETHROUGH
+ bool "Force write through D-cache"
+- depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_FEROCEON) && !CPU_DCACHE_DISABLE
++ depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020) && !CPU_DCACHE_DISABLE
+ default y if CPU_ARM925T
+ help
+ Say Y here to use the data cache in writethrough mode. Unless you
+@@ -671,5 +710,9 @@ config OUTER_CACHE
default n
config CACHE_L2X0
@@ -66592,6 +72038,119 @@
select OUTER_CACHE
+ help
+ This option enables the L2x0 PrimeCell.
+diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
+index 44536a0..32b2d2d 100644
+--- a/arch/arm/mm/Makefile
++++ b/arch/arm/mm/Makefile
+@@ -36,6 +36,7 @@ obj-$(CONFIG_CPU_CACHE_V7) += cache-v7.o
+ obj-$(CONFIG_CPU_COPY_V3) += copypage-v3.o
+ obj-$(CONFIG_CPU_COPY_V4WT) += copypage-v4wt.o
+ obj-$(CONFIG_CPU_COPY_V4WB) += copypage-v4wb.o
++obj-$(CONFIG_CPU_COPY_FEROCEON) += copypage-feroceon.o
+ obj-$(CONFIG_CPU_COPY_V6) += copypage-v6.o context.o
+ obj-$(CONFIG_CPU_SA1100) += copypage-v4mc.o
+ obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o
+diff --git a/arch/arm/mm/copypage-feroceon.S b/arch/arm/mm/copypage-feroceon.S
+new file mode 100644
+index 0000000..7eb0d32
+--- /dev/null
++++ b/arch/arm/mm/copypage-feroceon.S
+@@ -0,0 +1,95 @@
++/*
++ * linux/arch/arm/lib/copypage-feroceon.S
++ *
++ * Copyright (C) 2008 Marvell Semiconductors
++ *
++ * 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 handles copy_user_page and clear_user_page on Feroceon
++ * more optimally than the generic implementations.
++ */
++#include <linux/linkage.h>
++#include <linux/init.h>
++#include <asm/asm-offsets.h>
++
++ .text
++ .align 5
++
++ENTRY(feroceon_copy_user_page)
++ stmfd sp!, {r4-r9, lr}
++ mov ip, #PAGE_SZ
++1: mov lr, r1
++ ldmia r1!, {r2 - r9}
++ pld [lr, #32]
++ pld [lr, #64]
++ pld [lr, #96]
++ pld [lr, #128]
++ pld [lr, #160]
++ pld [lr, #192]
++ pld [lr, #224]
++ stmia r0, {r2 - r9}
++ ldmia r1!, {r2 - r9}
++ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line
++ add r0, r0, #32
++ stmia r0, {r2 - r9}
++ ldmia r1!, {r2 - r9}
++ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line
++ add r0, r0, #32
++ stmia r0, {r2 - r9}
++ ldmia r1!, {r2 - r9}
++ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line
++ add r0, r0, #32
++ stmia r0, {r2 - r9}
++ ldmia r1!, {r2 - r9}
++ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line
++ add r0, r0, #32
++ stmia r0, {r2 - r9}
++ ldmia r1!, {r2 - r9}
++ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line
++ add r0, r0, #32
++ stmia r0, {r2 - r9}
++ ldmia r1!, {r2 - r9}
++ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line
++ add r0, r0, #32
++ stmia r0, {r2 - r9}
++ ldmia r1!, {r2 - r9}
++ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line
++ add r0, r0, #32
++ stmia r0, {r2 - r9}
++ subs ip, ip, #(32 * 8)
++ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line
++ add r0, r0, #32
++ bne 1b
++ mcr p15, 0, ip, c7, c10, 4 @ drain WB
++ ldmfd sp!, {r4-r9, pc}
++
++ .align 5
++
++ENTRY(feroceon_clear_user_page)
++ stmfd sp!, {r4-r7, lr}
++ mov r1, #PAGE_SZ/32
++ mov r2, #0
++ mov r3, #0
++ mov r4, #0
++ mov r5, #0
++ mov r6, #0
++ mov r7, #0
++ mov ip, #0
++ mov lr, #0
++1: stmia r0, {r2-r7, ip, lr}
++ subs r1, r1, #1
++ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line
++ add r0, r0, #32
++ bne 1b
++ mcr p15, 0, r1, c7, c10, 4 @ drain WB
++ ldmfd sp!, {r4-r7, pc}
++
++ __INITDATA
++
++ .type feroceon_user_fns, #object
++ENTRY(feroceon_user_fns)
++ .long feroceon_clear_user_page
++ .long feroceon_copy_user_page
++ .size feroceon_user_fns, . - feroceon_user_fns
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index ec00f26..b657f17 100644
--- a/arch/arm/mm/init.c
@@ -66605,6 +72164,33 @@
for_each_online_node(node) {
pg_data_t *n = NODE_DATA(node);
struct page *map = n->node_mem_map - n->node_start_pfn;
+diff --git a/arch/arm/mm/iomap.c b/arch/arm/mm/iomap.c
+index 62066f3..7429f8c 100644
+--- a/arch/arm/mm/iomap.c
++++ b/arch/arm/mm/iomap.c
+@@ -26,8 +26,8 @@ EXPORT_SYMBOL(ioport_unmap);
+ #ifdef CONFIG_PCI
+ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+ {
+- unsigned long start = pci_resource_start(dev, bar);
+- unsigned long len = pci_resource_len(dev, bar);
++ resource_size_t start = pci_resource_start(dev, bar);
++ resource_size_t len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (!len || !start)
+diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
+index d41a75e..2d6d682 100644
+--- a/arch/arm/mm/mmu.c
++++ b/arch/arm/mm/mmu.c
+@@ -35,6 +35,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+ * zero-initialized data and COW.
+ */
+ struct page *empty_zero_page;
++EXPORT_SYMBOL(empty_zero_page);
+
+ /*
+ * The pmd table for the upper-most set of pages.
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index 700c04d..5673f4d 100644
--- a/arch/arm/mm/proc-arm1020.S
@@ -66794,10 +72380,200 @@
.word cpu_arm9tdmi_proc_fin
.word cpu_arm9tdmi_reset
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
-index fa0dc7e..90e7594 100644
+index fa0dc7e..a02c171 100644
--- a/arch/arm/mm/proc-feroceon.S
+++ b/arch/arm/mm/proc-feroceon.S
-@@ -423,6 +423,7 @@ feroceon_crval:
+@@ -93,7 +93,7 @@ ENTRY(cpu_feroceon_reset)
+ *
+ * Called with IRQs disabled
+ */
+- .align 10
++ .align 5
+ ENTRY(cpu_feroceon_do_idle)
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
+@@ -106,6 +106,7 @@ ENTRY(cpu_feroceon_do_idle)
+ * Clean and invalidate all cache entries in a particular
+ * address space.
+ */
++ .align 5
+ ENTRY(feroceon_flush_user_cache_all)
+ /* FALLTHROUGH */
+
+@@ -118,12 +119,8 @@ ENTRY(feroceon_flush_kern_cache_all)
+ mov r2, #VM_EXEC
+ mov ip, #0
+ __flush_whole_cache:
+-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+- mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
+-#else
+ 1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate
+ bne 1b
+-#endif
+ tst r2, #VM_EXEC
+ mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
+ mcrne p15, 0, ip, c7, c10, 4 @ drain WB
+@@ -139,27 +136,19 @@ __flush_whole_cache:
+ * - end - end address (exclusive)
+ * - flags - vm_flags describing address space
+ */
++ .align 5
+ ENTRY(feroceon_flush_user_cache_range)
+ mov ip, #0
+ sub r3, r1, r0 @ calculate total size
+ cmp r3, #CACHE_DLIMIT
+ bgt __flush_whole_cache
+ 1: tst r2, #VM_EXEC
+-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+- mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
+- mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
+- add r0, r0, #CACHE_DLINESIZE
+- mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
+- mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
+- add r0, r0, #CACHE_DLINESIZE
+-#else
+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
+ mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
+ add r0, r0, #CACHE_DLINESIZE
+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
+ mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
+ add r0, r0, #CACHE_DLINESIZE
+-#endif
+ cmp r0, r1
+ blo 1b
+ tst r2, #VM_EXEC
+@@ -176,6 +165,7 @@ ENTRY(feroceon_flush_user_cache_range)
+ * - start - virtual start address
+ * - end - virtual end address
+ */
++ .align 5
+ ENTRY(feroceon_coherent_kern_range)
+ /* FALLTHROUGH */
+
+@@ -207,6 +197,7 @@ ENTRY(feroceon_coherent_user_range)
+ *
+ * - addr - page aligned address
+ */
++ .align 5
+ ENTRY(feroceon_flush_kern_dcache_page)
+ add r1, r0, #PAGE_SZ
+ 1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry
+@@ -231,13 +222,12 @@ ENTRY(feroceon_flush_kern_dcache_page)
+ *
+ * (same as v4wb)
+ */
++ .align 5
+ ENTRY(feroceon_dma_inv_range)
+-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+ tst r0, #CACHE_DLINESIZE - 1
+ mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
+ tst r1, #CACHE_DLINESIZE - 1
+ mcrne p15, 0, r1, c7, c10, 1 @ clean D entry
+-#endif
+ bic r0, r0, #CACHE_DLINESIZE - 1
+ 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
+ add r0, r0, #CACHE_DLINESIZE
+@@ -256,14 +246,13 @@ ENTRY(feroceon_dma_inv_range)
+ *
+ * (same as v4wb)
+ */
++ .align 5
+ ENTRY(feroceon_dma_clean_range)
+-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+ bic r0, r0, #CACHE_DLINESIZE - 1
+ 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ add r0, r0, #CACHE_DLINESIZE
+ cmp r0, r1
+ blo 1b
+-#endif
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+@@ -275,14 +264,10 @@ ENTRY(feroceon_dma_clean_range)
+ * - start - virtual start address
+ * - end - virtual end address
+ */
++ .align 5
+ ENTRY(feroceon_dma_flush_range)
+ bic r0, r0, #CACHE_DLINESIZE - 1
+-1:
+-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+- mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry
+-#else
+- mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+-#endif
++1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry
+ add r0, r0, #CACHE_DLINESIZE
+ cmp r0, r1
+ blo 1b
+@@ -300,13 +285,12 @@ ENTRY(feroceon_cache_fns)
+ .long feroceon_dma_clean_range
+ .long feroceon_dma_flush_range
+
++ .align 5
+ ENTRY(cpu_feroceon_dcache_clean_area)
+-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+ 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ add r0, r0, #CACHE_DLINESIZE
+ subs r1, r1, #CACHE_DLINESIZE
+ bhi 1b
+-#endif
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+@@ -323,13 +307,9 @@ ENTRY(cpu_feroceon_dcache_clean_area)
+ ENTRY(cpu_feroceon_switch_mm)
+ #ifdef CONFIG_MMU
+ mov ip, #0
+-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+- mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
+-#else
+ @ && 'Clean & Invalidate whole DCache'
+ 1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate
+ bne 1b
+-#endif
+ mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
+ mcr p15, 0, ip, c7, c10, 4 @ drain WB
+ mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
+@@ -362,16 +342,9 @@ ENTRY(cpu_feroceon_set_pte_ext)
+ tst r1, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young?
+ movne r2, #0
+
+-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+- eor r3, r2, #0x0a @ C & small page?
+- tst r3, #0x0b
+- biceq r2, r2, #4
+-#endif
+ str r2, [r0] @ hardware version
+ mov r0, r0
+-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+-#endif
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ #endif
+ mov pc, lr
+@@ -387,20 +360,11 @@ __feroceon_setup:
+ mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4
+ #endif
+
+-
+-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+- mov r0, #4 @ disable write-back on caches explicitly
+- mcr p15, 7, r0, c15, c0, 0
+-#endif
+-
+ adr r5, feroceon_crval
+ ldmia r5, {r5, r6}
+ mrc p15, 0, r0, c1, c0 @ get control register v4
+ bic r0, r0, r5
+ orr r0, r0, r6
+-#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
+- orr r0, r0, #0x4000 @ .1.. .... .... ....
+-#endif
+ mov pc, lr
+ .size __feroceon_setup, . - __feroceon_setup
+
+@@ -423,6 +387,7 @@ feroceon_crval:
.type feroceon_processor_functions, #object
feroceon_processor_functions:
.word v5t_early_abort
@@ -66805,6 +72581,23 @@
.word cpu_feroceon_proc_init
.word cpu_feroceon_proc_fin
.word cpu_feroceon_reset
+@@ -475,7 +440,7 @@ __feroceon_old_id_proc_info:
+ .long cpu_feroceon_name
+ .long feroceon_processor_functions
+ .long v4wbi_tlb_fns
+- .long v4wb_user_fns
++ .long feroceon_user_fns
+ .long feroceon_cache_fns
+ .size __feroceon_old_id_proc_info, . - __feroceon_old_id_proc_info
+ #endif
+@@ -501,6 +466,6 @@ __feroceon_proc_info:
+ .long cpu_feroceon_name
+ .long feroceon_processor_functions
+ .long v4wbi_tlb_fns
+- .long v4wb_user_fns
++ .long feroceon_user_fns
+ .long feroceon_cache_fns
+ .size __feroceon_proc_info, . - __feroceon_proc_info
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index 6e226e1..9818195 100644
--- a/arch/arm/mm/proc-sa110.S
@@ -66909,6 +72702,109 @@
.word cpu_xscale_proc_init
.word cpu_xscale_proc_fin
.word cpu_xscale_reset
+diff --git a/arch/arm/oprofile/op_model_mpcore.c b/arch/arm/oprofile/op_model_mpcore.c
+index 75bae06..74fae60 100644
+--- a/arch/arm/oprofile/op_model_mpcore.c
++++ b/arch/arm/oprofile/op_model_mpcore.c
+@@ -51,7 +51,7 @@
+ /*
+ * MPCore SCU event monitor support
+ */
+-#define SCU_EVENTMONITORS_VA_BASE __io_address(REALVIEW_MPCORE_SCU_BASE + 0x10)
++#define SCU_EVENTMONITORS_VA_BASE __io_address(REALVIEW_EB11MP_SCU_BASE + 0x10)
+
+ /*
+ * Bitmask of used SCU counters
+@@ -80,7 +80,7 @@ static irqreturn_t scu_em_interrupt(int irq, void *arg)
+ struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE;
+ unsigned int cnt;
+
+- cnt = irq - IRQ_PMU_SCU0;
++ cnt = irq - IRQ_EB11MP_PMU_SCU0;
+ oprofile_add_sample(get_irq_regs(), SCU_COUNTER(cnt));
+ scu_reset_counter(emc, cnt);
+
+@@ -119,10 +119,10 @@ static int scu_start(void)
+ */
+ for (i = 0; i < NUM_SCU_COUNTERS; i++) {
+ if (scu_em_used & (1 << i)) {
+- ret = request_irq(IRQ_PMU_SCU0 + i, scu_em_interrupt, IRQF_DISABLED, "SCU PMU", NULL);
++ ret = request_irq(IRQ_EB11MP_PMU_SCU0 + i, scu_em_interrupt, IRQF_DISABLED, "SCU PMU", NULL);
+ if (ret) {
+ printk(KERN_ERR "oprofile: unable to request IRQ%u for SCU Event Monitor\n",
+- IRQ_PMU_SCU0 + i);
++ IRQ_EB11MP_PMU_SCU0 + i);
+ goto err_free_scu;
+ }
+ }
+@@ -153,7 +153,7 @@ static int scu_start(void)
+
+ err_free_scu:
+ while (i--)
+- free_irq(IRQ_PMU_SCU0 + i, NULL);
++ free_irq(IRQ_EB11MP_PMU_SCU0 + i, NULL);
+ return ret;
+ }
+
+@@ -175,7 +175,7 @@ static void scu_stop(void)
+ for (i = 0; i < NUM_SCU_COUNTERS; i++) {
+ if (scu_em_used & (1 << i)) {
+ scu_reset_counter(emc, i);
+- free_irq(IRQ_PMU_SCU0 + i, NULL);
++ free_irq(IRQ_EB11MP_PMU_SCU0 + i, NULL);
+ }
+ }
+ }
+@@ -225,10 +225,10 @@ static int em_setup_ctrs(void)
+ }
+
+ static int arm11_irqs[] = {
+- [0] = IRQ_PMU_CPU0,
+- [1] = IRQ_PMU_CPU1,
+- [2] = IRQ_PMU_CPU2,
+- [3] = IRQ_PMU_CPU3
++ [0] = IRQ_EB11MP_PMU_CPU0,
++ [1] = IRQ_EB11MP_PMU_CPU1,
++ [2] = IRQ_EB11MP_PMU_CPU2,
++ [3] = IRQ_EB11MP_PMU_CPU3
+ };
+
+ static int em_start(void)
+@@ -273,22 +273,22 @@ static int em_setup(void)
+ /*
+ * Send SCU PMU interrupts to the "owner" CPU.
+ */
+- em_route_irq(IRQ_PMU_SCU0, 0);
+- em_route_irq(IRQ_PMU_SCU1, 0);
+- em_route_irq(IRQ_PMU_SCU2, 1);
+- em_route_irq(IRQ_PMU_SCU3, 1);
+- em_route_irq(IRQ_PMU_SCU4, 2);
+- em_route_irq(IRQ_PMU_SCU5, 2);
+- em_route_irq(IRQ_PMU_SCU6, 3);
+- em_route_irq(IRQ_PMU_SCU7, 3);
++ em_route_irq(IRQ_EB11MP_PMU_SCU0, 0);
++ em_route_irq(IRQ_EB11MP_PMU_SCU1, 0);
++ em_route_irq(IRQ_EB11MP_PMU_SCU2, 1);
++ em_route_irq(IRQ_EB11MP_PMU_SCU3, 1);
++ em_route_irq(IRQ_EB11MP_PMU_SCU4, 2);
++ em_route_irq(IRQ_EB11MP_PMU_SCU5, 2);
++ em_route_irq(IRQ_EB11MP_PMU_SCU6, 3);
++ em_route_irq(IRQ_EB11MP_PMU_SCU7, 3);
+
+ /*
+ * Send CP15 PMU interrupts to the owner CPU.
+ */
+- em_route_irq(IRQ_PMU_CPU0, 0);
+- em_route_irq(IRQ_PMU_CPU1, 1);
+- em_route_irq(IRQ_PMU_CPU2, 2);
+- em_route_irq(IRQ_PMU_CPU3, 3);
++ em_route_irq(IRQ_EB11MP_PMU_CPU0, 0);
++ em_route_irq(IRQ_EB11MP_PMU_CPU1, 1);
++ em_route_irq(IRQ_EB11MP_PMU_CPU2, 2);
++ em_route_irq(IRQ_EB11MP_PMU_CPU3, 3);
+
+ return 0;
+ }
diff --git a/arch/arm/plat-iop/pci.c b/arch/arm/plat-iop/pci.c
index 98d0151..d9bc15a 100644
--- a/arch/arm/plat-iop/pci.c
@@ -69135,6 +75031,26 @@
obj-y += signal.o sys_avr32.o process.o time.o
obj-y += init_task.o switch_to.o cpu.o
obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o
+diff --git a/arch/avr32/kernel/asm-offsets.c b/arch/avr32/kernel/asm-offsets.c
+index 078cd33..e4796c6 100644
+--- a/arch/avr32/kernel/asm-offsets.c
++++ b/arch/avr32/kernel/asm-offsets.c
+@@ -5,14 +5,7 @@
+ */
+
+ #include <linux/thread_info.h>
+-
+-#define DEFINE(sym, val) \
+- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+-
+-#define BLANK() asm volatile("\n->" : : )
+-
+-#define OFFSET(sym, str, mem) \
+- DEFINE(sym, offsetof(struct str, mem));
++#include <linux/kbuild.h>
+
+ void foo(void)
+ {
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 8cf16d7..5f31702 100644
--- a/arch/avr32/kernel/entry-avr32b.S
@@ -69347,6 +75263,19 @@
- return retval;
-}
-EXPORT_SYMBOL(__down_interruptible);
+diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c
+index 2687b73..ce48c14 100644
+--- a/arch/avr32/kernel/setup.c
++++ b/arch/avr32/kernel/setup.c
+@@ -274,6 +274,8 @@ static int __init early_parse_fbmem(char *p)
+ printk(KERN_WARNING
+ "Failed to allocate framebuffer memory\n");
+ fbmem_size = 0;
++ } else {
++ memset(__va(fbmem_start), 0, fbmem_size);
+ }
+ }
+
diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c
index 36a46c3..00a9862 100644
--- a/arch/avr32/kernel/time.c
@@ -70354,6 +76283,23 @@
void show_mem(void)
{
int total = 0, reserved = 0, cached = 0;
+diff --git a/arch/avr32/mm/tlb.c b/arch/avr32/mm/tlb.c
+index b835257..cd12edb 100644
+--- a/arch/avr32/mm/tlb.c
++++ b/arch/avr32/mm/tlb.c
+@@ -369,11 +369,7 @@ static const struct file_operations proc_tlb_operations = {
+
+ static int __init proctlb_init(void)
+ {
+- struct proc_dir_entry *entry;
+-
+- entry = create_proc_entry("tlb", 0, NULL);
+- if (entry)
+- entry->proc_fops = &proc_tlb_operations;
++ proc_create("tlb", 0, NULL, &proc_tlb_operations);
+ return 0;
+ }
+ late_initcall(proctlb_init);
diff --git a/arch/avr32/oprofile/op_model_avr32.c b/arch/avr32/oprofile/op_model_avr32.c
index e2f876b..df42325 100644
--- a/arch/avr32/oprofile/op_model_avr32.c
@@ -78499,6 +84445,20 @@
obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_BFIN_DMA_5XX) += bfin_dma_5xx.o
+diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c
+index b56b274..721f15f 100644
+--- a/arch/blackfin/kernel/asm-offsets.c
++++ b/arch/blackfin/kernel/asm-offsets.c
+@@ -34,8 +34,7 @@
+ #include <linux/hardirq.h>
+ #include <linux/irq.h>
+ #include <linux/thread_info.h>
+-
+-#define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val))
++#include <linux/kbuild.h>
+
+ int main(void)
+ {
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c
index 8fd5d22..fd5448d 100644
--- a/arch/blackfin/kernel/bfin_dma_5xx.c
@@ -79858,7 +85818,7 @@
seq_printf(m, "board memory\t: %ld kB (0x%p -> 0x%p)\n",
physical_mem_end >> 10, (void *)0, (void *)physical_mem_end);
diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c
-index 5564c95..d1fa244 100644
+index 5564c95..cb9d883 100644
--- a/arch/blackfin/kernel/signal.c
+++ b/arch/blackfin/kernel/signal.c
@@ -38,6 +38,7 @@
@@ -79904,7 +85864,7 @@
static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
size_t frame_size)
{
-@@ -209,19 +207,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
+@@ -209,29 +207,19 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
err |= rt_setup_sigcontext(&frame->uc.uc_mcontext, regs);
err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
@@ -79923,8 +85883,11 @@
-
/* Set up registers for signal handler */
wrusp((unsigned long)frame);
- if (get_personality & FDPIC_FUNCPTRS) {
-@@ -231,7 +219,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
+- if (get_personality & FDPIC_FUNCPTRS) {
++ if (current->personality & FDPIC_FUNCPTRS) {
+ struct fdpic_func_descriptor __user *funcptr =
+ (struct fdpic_func_descriptor *) ka->sa.sa_handler;
+ __get_user(regs->pc, &funcptr->text);
__get_user(regs->p3, &funcptr->GOT);
} else
regs->pc = (unsigned long)ka->sa.sa_handler;
@@ -81343,7 +87306,7 @@
+
+arch_initcall(ip0x_init);
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
-index b2ac481..fddce32 100644
+index b2ac481..024f418 100644
--- a/arch/blackfin/mach-bf533/boards/stamp.c
+++ b/arch/blackfin/mach-bf533/boards/stamp.c
@@ -40,6 +40,7 @@
@@ -81396,7 +87359,7 @@
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
static struct platform_device bfin_sport0_uart_device = {
.name = "bfin-sport-uart",
-@@ -472,6 +494,31 @@ static struct platform_device i2c_gpio_device = {
+@@ -472,6 +494,28 @@ static struct platform_device i2c_gpio_device = {
};
#endif
@@ -81405,20 +87368,17 @@
+#if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
+ {
+ I2C_BOARD_INFO("ad7142_joystick", 0x2C),
-+ .type = "ad7142_joystick",
+ .irq = 39,
+ },
+#endif
+#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+ {
+ I2C_BOARD_INFO("pcf8574_lcd", 0x22),
-+ .type = "pcf8574_lcd",
+ },
+#endif
+#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
+ {
+ I2C_BOARD_INFO("pcf8574_keypad", 0x27),
-+ .type = "pcf8574_keypad",
+ .irq = 39,
+ },
+#endif
@@ -81428,7 +87388,7 @@
static struct platform_device *stamp_devices[] __initdata = {
#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
&rtc_device,
-@@ -497,6 +544,10 @@ static struct platform_device *stamp_devices[] __initdata = {
+@@ -497,6 +541,10 @@ static struct platform_device *stamp_devices[] __initdata = {
&bfin_uart_device,
#endif
@@ -81439,7 +87399,7 @@
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
&bfin_sport0_uart_device,
&bfin_sport1_uart_device,
-@@ -515,14 +566,23 @@ static struct platform_device *stamp_devices[] __initdata = {
+@@ -515,14 +563,23 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
&bfin_gpios_device,
@@ -82007,7 +87967,7 @@
#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
spi_register_board_info(bfin_spi_board_info,
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
-index ea83148..0cec14b 100644
+index ea83148..d3727b7 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -41,6 +41,7 @@
@@ -82111,7 +88071,7 @@
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
static struct resource bfin_twi0_resource[] = {
[0] = {
-@@ -698,6 +746,31 @@ static struct platform_device i2c_bfin_twi_device = {
+@@ -698,6 +746,28 @@ static struct platform_device i2c_bfin_twi_device = {
};
#endif
@@ -82120,20 +88080,17 @@
+#if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
+ {
+ I2C_BOARD_INFO("ad7142_joystick", 0x2C),
-+ .type = "ad7142_joystick",
+ .irq = 55,
+ },
+#endif
+#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+ {
+ I2C_BOARD_INFO("pcf8574_lcd", 0x22),
-+ .type = "pcf8574_lcd",
+ },
+#endif
+#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
+ {
+ I2C_BOARD_INFO("pcf8574_keypad", 0x27),
-+ .type = "pcf8574_keypad",
+ .irq = 72,
+ },
+#endif
@@ -82143,7 +88100,7 @@
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
static struct platform_device bfin_sport0_uart_device = {
.name = "bfin-sport-uart",
-@@ -800,6 +873,10 @@ static struct platform_device *stamp_devices[] __initdata = {
+@@ -800,6 +870,10 @@ static struct platform_device *stamp_devices[] __initdata = {
&bfin_uart_device,
#endif
@@ -82154,7 +88111,7 @@
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
&i2c_bfin_twi_device,
#endif
-@@ -818,12 +895,21 @@ static struct platform_device *stamp_devices[] __initdata = {
+@@ -818,12 +892,21 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
&bfin_gpios_device,
@@ -82177,7 +88134,7 @@
platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
spi_register_board_info(bfin_spi_board_info,
-@@ -833,6 +919,7 @@ static int __init stamp_init(void)
+@@ -833,6 +916,7 @@ static int __init stamp_init(void)
#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
#endif
@@ -83164,7 +89121,7 @@
+
+arch_initcall(cm_bf548_init);
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
-index 40846aa..231dfbd 100644
+index 40846aa..b00f68a 100644
--- a/arch/blackfin/mach-bf548/boards/ezkit.c
+++ b/arch/blackfin/mach-bf548/boards/ezkit.c
@@ -36,6 +36,7 @@
@@ -83279,7 +89236,7 @@
#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
{
.modalias = "ad7877",
-@@ -571,6 +632,29 @@ static struct platform_device i2c_bfin_twi1_device = {
+@@ -571,6 +632,27 @@ static struct platform_device i2c_bfin_twi1_device = {
#endif
#endif
@@ -83292,13 +89249,11 @@
+#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+ {
+ I2C_BOARD_INFO("pcf8574_lcd", 0x22),
-+ .type = "pcf8574_lcd",
+ },
+#endif
+#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
+ {
+ I2C_BOARD_INFO("pcf8574_keypad", 0x27),
-+ .type = "pcf8574_keypad",
+ .irq = 212,
+ },
+#endif
@@ -83309,7 +89264,7 @@
#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
#include <linux/gpio_keys.h>
-@@ -616,6 +700,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
+@@ -616,6 +698,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
&bfin_uart_device,
#endif
@@ -83320,7 +89275,7 @@
#if defined(CONFIG_FB_BF54X_LQ043) || defined(CONFIG_FB_BF54X_LQ043_MODULE)
&bf54x_lq043_device,
#endif
-@@ -661,12 +749,25 @@ static struct platform_device *ezkit_devices[] __initdata = {
+@@ -661,12 +747,25 @@ static struct platform_device *ezkit_devices[] __initdata = {
#endif
&bfin_gpios_device,
@@ -84517,6 +90472,22 @@
/* Userspace access functions */
EXPORT_SYMBOL(__copy_user_zeroing);
EXPORT_SYMBOL(__copy_user);
+diff --git a/arch/cris/kernel/profile.c b/arch/cris/kernel/profile.c
+index aad0a9e..44f7b4f 100644
+--- a/arch/cris/kernel/profile.c
++++ b/arch/cris/kernel/profile.c
+@@ -75,9 +75,9 @@ __init init_cris_profile(void)
+
+ sample_buffer_pos = sample_buffer;
+
+- entry = create_proc_entry("system_profile", S_IWUSR | S_IRUGO, NULL);
++ entry = proc_create("system_profile", S_IWUSR | S_IRUGO, NULL,
++ &cris_proc_profile_operations);
+ if (entry) {
+- entry->proc_fops = &cris_proc_profile_operations;
+ entry->size = SAMPLE_BUFFER_SIZE;
+ }
+ prof_running = 1;
diff --git a/arch/cris/kernel/semaphore.c b/arch/cris/kernel/semaphore.c
deleted file mode 100644
index f137a43..0000000
@@ -84652,6 +90623,18 @@
-{
- return waking_non_zero_trylock(sem);
-}
+diff --git a/arch/cris/mm/init.c b/arch/cris/mm/init.c
+index 4207a2b..5b06ffa 100644
+--- a/arch/cris/mm/init.c
++++ b/arch/cris/mm/init.c
+@@ -27,7 +27,6 @@ show_mem(void)
+
+ printk("\nMem-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/frv/kernel/Makefile b/arch/frv/kernel/Makefile
index e8f73ed..c36f70b 100644
--- a/arch/frv/kernel/Makefile
@@ -84665,6 +90648,39 @@
debug-stub.o irq.o sleep.o uaccess.o
obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-io.o
+diff --git a/arch/frv/kernel/asm-offsets.c b/arch/frv/kernel/asm-offsets.c
+index fbb19fc..9de9684 100644
+--- a/arch/frv/kernel/asm-offsets.c
++++ b/arch/frv/kernel/asm-offsets.c
+@@ -7,15 +7,13 @@
+ #include <linux/sched.h>
+ #include <linux/signal.h>
+ #include <linux/personality.h>
++#include <linux/kbuild.h>
+ #include <asm/registers.h>
+ #include <asm/ucontext.h>
+ #include <asm/processor.h>
+ #include <asm/thread_info.h>
+ #include <asm/gdb-stub.h>
+
+-#define DEFINE(sym, val) \
+- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+-
+ #define DEF_PTREG(sym, reg) \
+ asm volatile("\n->" #sym " %0 offsetof(struct pt_regs, " #reg ")" \
+ : : "i" (offsetof(struct pt_regs, reg)))
+@@ -32,11 +30,6 @@
+ asm volatile("\n->" #sym " %0 offsetof(struct frv_frame0, " #reg ")" \
+ : : "i" (offsetof(struct frv_frame0, reg)))
+
+-#define BLANK() asm volatile("\n->" : : )
+-
+-#define OFFSET(sym, str, mem) \
+- DEFINE(sym, offsetof(struct str, mem));
+-
+ void foo(void)
+ {
+ /* offsets into the thread_info structure */
diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c
index f772704..0316b3c 100644
--- a/arch/frv/kernel/frv_ksyms.c
@@ -84677,6 +90693,44 @@
#include <asm/checksum.h>
#include <asm/hardirq.h>
#include <asm/cacheflush.h>
+diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c
+index c57ce3f..73f3aee 100644
+--- a/arch/frv/kernel/pm.c
++++ b/arch/frv/kernel/pm.c
+@@ -163,14 +163,11 @@ static int sysctl_pm_do_suspend(ctl_table *ctl, int write, struct file *filp,
+ if ((mode != 1) && (mode != 5))
+ return -EINVAL;
+
+- retval = pm_send_all(PM_SUSPEND, (void *)3);
+-
+ if (retval == 0) {
+ if (mode == 5)
+ retval = pm_do_bus_sleep();
+ else
+ retval = pm_do_suspend();
+- pm_send_all(PM_RESUME, (void *)0);
+ }
+
+ return retval;
+@@ -183,9 +180,6 @@ static int try_set_cmode(int new_cmode)
+ if (!(clock_cmodes_permitted & (1<<new_cmode)))
+ return -EINVAL;
+
+- /* tell all the drivers we're suspending */
+- pm_send_all(PM_SUSPEND, (void *)3);
+-
+ /* now change cmode */
+ local_irq_disable();
+ frv_dma_pause_all();
+@@ -201,8 +195,6 @@ static int try_set_cmode(int new_cmode)
+ frv_dma_resume_all();
+ local_irq_enable();
+
+- /* tell all the drivers we're resuming */
+- pm_send_all(PM_RESUME, (void *)0);
+ return 0;
+ }
+
diff --git a/arch/frv/kernel/semaphore.c b/arch/frv/kernel/semaphore.c
deleted file mode 100644
index 7ee3a14..0000000
@@ -84838,6 +90892,182 @@
-}
-
-EXPORT_SYMBOL(__up);
+diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
+index d64bcaf..3bdb368 100644
+--- a/arch/frv/kernel/signal.c
++++ b/arch/frv/kernel/signal.c
+@@ -297,7 +297,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
+ __frame->lr = (unsigned long) &frame->retcode;
+ __frame->gr8 = sig;
+
+- if (get_personality & FDPIC_FUNCPTRS) {
++ if (current->personality & FDPIC_FUNCPTRS) {
+ struct fdpic_func_descriptor __user *funcptr =
+ (struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
+ __get_user(__frame->pc, &funcptr->text);
+@@ -396,7 +396,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ __frame->gr8 = sig;
+ __frame->gr9 = (unsigned long) &frame->info;
+
+- if (get_personality & FDPIC_FUNCPTRS) {
++ if (current->personality & FDPIC_FUNCPTRS) {
+ struct fdpic_func_descriptor __user *funcptr =
+ (struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
+ __get_user(__frame->pc, &funcptr->text);
+diff --git a/arch/frv/kernel/traps.c b/arch/frv/kernel/traps.c
+index 7089c24..1d2dfe6 100644
+--- a/arch/frv/kernel/traps.c
++++ b/arch/frv/kernel/traps.c
+@@ -49,7 +49,7 @@ asmlinkage void insn_access_error(unsigned long esfr1, unsigned long epcr0, unsi
+ info.si_signo = SIGSEGV;
+ info.si_code = SEGV_ACCERR;
+ info.si_errno = 0;
+- info.si_addr = (void *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc);
++ info.si_addr = (void __user *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc);
+
+ force_sig_info(info.si_signo, &info, current);
+ } /* end insn_access_error() */
+@@ -73,7 +73,7 @@ asmlinkage void illegal_instruction(unsigned long esfr1, unsigned long epcr0, un
+ epcr0, esr0, esfr1);
+
+ info.si_errno = 0;
+- info.si_addr = (void *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc);
++ info.si_addr = (void __user *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc);
+
+ switch (__frame->tbr & TBR_TT) {
+ case TBR_TT_ILLEGAL_INSTR:
+@@ -111,7 +111,8 @@ asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0,
+ unsigned long esr0)
+ {
+ static DEFINE_SPINLOCK(atomic_op_lock);
+- unsigned long x, y, z, *p;
++ unsigned long x, y, z;
++ unsigned long __user *p;
+ mm_segment_t oldfs;
+ siginfo_t info;
+ int ret;
+@@ -128,7 +129,7 @@ asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0,
+ * u32 __atomic_user_cmpxchg32(u32 *ptr, u32 test, u32 new)
+ */
+ case TBR_TT_ATOMIC_CMPXCHG32:
+- p = (unsigned long *) __frame->gr8;
++ p = (unsigned long __user *) __frame->gr8;
+ x = __frame->gr9;
+ y = __frame->gr10;
+
+@@ -158,7 +159,7 @@ asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0,
+ * u32 __atomic_kernel_xchg32(void *v, u32 new)
+ */
+ case TBR_TT_ATOMIC_XCHG32:
+- p = (unsigned long *) __frame->gr8;
++ p = (unsigned long __user *) __frame->gr8;
+ y = __frame->gr9;
+
+ for (;;) {
+@@ -181,7 +182,7 @@ asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0,
+ * ulong __atomic_kernel_XOR_return(ulong i, ulong *v)
+ */
+ case TBR_TT_ATOMIC_XOR:
+- p = (unsigned long *) __frame->gr8;
++ p = (unsigned long __user *) __frame->gr8;
+ x = __frame->gr9;
+
+ for (;;) {
+@@ -205,7 +206,7 @@ asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0,
+ * ulong __atomic_kernel_OR_return(ulong i, ulong *v)
+ */
+ case TBR_TT_ATOMIC_OR:
+- p = (unsigned long *) __frame->gr8;
++ p = (unsigned long __user *) __frame->gr8;
+ x = __frame->gr9;
+
+ for (;;) {
+@@ -229,7 +230,7 @@ asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0,
+ * ulong __atomic_kernel_AND_return(ulong i, ulong *v)
+ */
+ case TBR_TT_ATOMIC_AND:
+- p = (unsigned long *) __frame->gr8;
++ p = (unsigned long __user *) __frame->gr8;
+ x = __frame->gr9;
+
+ for (;;) {
+@@ -253,7 +254,7 @@ asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0,
+ * int __atomic_user_sub_return(atomic_t *v, int i)
+ */
+ case TBR_TT_ATOMIC_SUB:
+- p = (unsigned long *) __frame->gr8;
++ p = (unsigned long __user *) __frame->gr8;
+ x = __frame->gr9;
+
+ for (;;) {
+@@ -277,7 +278,7 @@ asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0,
+ * int __atomic_user_add_return(atomic_t *v, int i)
+ */
+ case TBR_TT_ATOMIC_ADD:
+- p = (unsigned long *) __frame->gr8;
++ p = (unsigned long __user *) __frame->gr8;
+ x = __frame->gr9;
+
+ for (;;) {
+@@ -322,7 +323,7 @@ error:
+ info.si_signo = SIGSEGV;
+ info.si_code = SEGV_ACCERR;
+ info.si_errno = 0;
+- info.si_addr = (void *) __frame->pc;
++ info.si_addr = (void __user *) __frame->pc;
+
+ force_sig_info(info.si_signo, &info, current);
+ }
+@@ -343,7 +344,7 @@ asmlinkage void media_exception(unsigned long msr0, unsigned long msr1)
+ info.si_signo = SIGFPE;
+ info.si_code = FPE_MDAOVF;
+ info.si_errno = 0;
+- info.si_addr = (void *) __frame->pc;
++ info.si_addr = (void __user *) __frame->pc;
+
+ force_sig_info(info.si_signo, &info, current);
+ } /* end media_exception() */
+@@ -361,11 +362,8 @@ asmlinkage void memory_access_exception(unsigned long esr0,
+ #ifdef CONFIG_MMU
+ unsigned long fixup;
+
+- if ((esr0 & ESRx_EC) == ESRx_EC_DATA_ACCESS)
+- if (handle_misalignment(esr0, ear0, epcr0) == 0)
+- return;
+-
+- if ((fixup = search_exception_table(__frame->pc)) != 0) {
++ fixup = search_exception_table(__frame->pc);
++ if (fixup) {
+ __frame->pc = fixup;
+ return;
+ }
+@@ -383,7 +381,7 @@ asmlinkage void memory_access_exception(unsigned long esr0,
+ info.si_addr = NULL;
+
+ if ((esr0 & (ESRx_VALID | ESR0_EAV)) == (ESRx_VALID | ESR0_EAV))
+- info.si_addr = (void *) ear0;
++ info.si_addr = (void __user *) ear0;
+
+ force_sig_info(info.si_signo, &info, current);
+
+@@ -412,7 +410,7 @@ asmlinkage void data_access_error(unsigned long esfr1, unsigned long esr15, unsi
+ info.si_signo = SIGSEGV;
+ info.si_code = SEGV_ACCERR;
+ info.si_errno = 0;
+- info.si_addr = (void *)
++ info.si_addr = (void __user *)
+ (((esr15 & (ESRx_VALID|ESR15_EAV)) == (ESRx_VALID|ESR15_EAV)) ? ear15 : 0);
+
+ force_sig_info(info.si_signo, &info, current);
+@@ -446,7 +444,7 @@ asmlinkage void division_exception(unsigned long esfr1, unsigned long esr0, unsi
+ info.si_signo = SIGFPE;
+ info.si_code = FPE_INTDIV;
+ info.si_errno = 0;
+- info.si_addr = (void *) __frame->pc;
++ info.si_addr = (void __user *) __frame->pc;
+
+ force_sig_info(info.si_signo, &info, current);
+ } /* end division_exception() */
diff --git a/arch/frv/mb93090-mb00/pci-frv.h b/arch/frv/mb93090-mb00/pci-frv.h
index 7481797..0c7bf39 100644
--- a/arch/frv/mb93090-mb00/pci-frv.h
@@ -84851,6 +91081,21 @@
#define PCI_NO_CHECKS 0x0400
#define PCI_ASSIGN_ROMS 0x1000
#define PCI_BIOS_IRQ_SCAN 0x2000
+diff --git a/arch/frv/mb93090-mb00/pci-iomap.c b/arch/frv/mb93090-mb00/pci-iomap.c
+index 068fa04..35f6df2 100644
+--- a/arch/frv/mb93090-mb00/pci-iomap.c
++++ b/arch/frv/mb93090-mb00/pci-iomap.c
+@@ -13,8 +13,8 @@
+
+ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+ {
+- unsigned long start = pci_resource_start(dev, bar);
+- unsigned long len = pci_resource_len(dev, bar);
++ resource_size_t start = pci_resource_start(dev, bar);
++ resource_size_t len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (!len || !start)
diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c
index 6d51f13..f003cfa 100644
--- a/arch/frv/mb93090-mb00/pci-vdk.c
@@ -84933,6 +91178,229 @@
-
-
-EXPORT_SYMBOL(kmap_atomic_to_page);
+diff --git a/arch/frv/mm/unaligned.c b/arch/frv/mm/unaligned.c
+deleted file mode 100644
+index 8f0375f..0000000
+--- a/arch/frv/mm/unaligned.c
++++ /dev/null
+@@ -1,217 +0,0 @@
+-/* unaligned.c: unalignment fixup handler for CPUs on which it is supported (FR451 only)
+- *
+- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+- * Written by David Howells (dhowells at redhat.com)
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/signal.h>
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/types.h>
+-#include <linux/user.h>
+-#include <linux/string.h>
+-#include <linux/linkage.h>
+-#include <linux/init.h>
+-
+-#include <asm/setup.h>
+-#include <asm/system.h>
+-#include <asm/uaccess.h>
+-
+-#if 0
+-#define kdebug(fmt, ...) printk("FDPIC "fmt"\n" ,##__VA_ARGS__ )
+-#else
+-#define kdebug(fmt, ...) do {} while(0)
+-#endif
+-
+-#define _MA_SIGNED 0x01
+-#define _MA_HALF 0x02
+-#define _MA_WORD 0x04
+-#define _MA_DWORD 0x08
+-#define _MA_SZ_MASK 0x0e
+-#define _MA_LOAD 0x10
+-#define _MA_STORE 0x20
+-#define _MA_UPDATE 0x40
+-#define _MA_IMM 0x80
+-
+-#define _MA_LDxU _MA_LOAD | _MA_UPDATE
+-#define _MA_LDxI _MA_LOAD | _MA_IMM
+-#define _MA_STxU _MA_STORE | _MA_UPDATE
+-#define _MA_STxI _MA_STORE | _MA_IMM
+-
+-static const uint8_t tbl_LDGRk_reg[0x40] = {
+- [0x02] = _MA_LOAD | _MA_HALF | _MA_SIGNED, /* LDSH @(GRi,GRj),GRk */
+- [0x03] = _MA_LOAD | _MA_HALF, /* LDUH @(GRi,GRj),GRk */
+- [0x04] = _MA_LOAD | _MA_WORD, /* LD @(GRi,GRj),GRk */
+- [0x05] = _MA_LOAD | _MA_DWORD, /* LDD @(GRi,GRj),GRk */
+- [0x12] = _MA_LDxU | _MA_HALF | _MA_SIGNED, /* LDSHU @(GRi,GRj),GRk */
+- [0x13] = _MA_LDxU | _MA_HALF, /* LDUHU @(GRi,GRj),GRk */
+- [0x14] = _MA_LDxU | _MA_WORD, /* LDU @(GRi,GRj),GRk */
+- [0x15] = _MA_LDxU | _MA_DWORD, /* LDDU @(GRi,GRj),GRk */
+-};
+-
+-static const uint8_t tbl_STGRk_reg[0x40] = {
+- [0x01] = _MA_STORE | _MA_HALF, /* STH @(GRi,GRj),GRk */
+- [0x02] = _MA_STORE | _MA_WORD, /* ST @(GRi,GRj),GRk */
+- [0x03] = _MA_STORE | _MA_DWORD, /* STD @(GRi,GRj),GRk */
+- [0x11] = _MA_STxU | _MA_HALF, /* STHU @(GRi,GRj),GRk */
+- [0x12] = _MA_STxU | _MA_WORD, /* STU @(GRi,GRj),GRk */
+- [0x13] = _MA_STxU | _MA_DWORD, /* STDU @(GRi,GRj),GRk */
+-};
+-
+-static const uint8_t tbl_LDSTGRk_imm[0x80] = {
+- [0x31] = _MA_LDxI | _MA_HALF | _MA_SIGNED, /* LDSHI @(GRi,d12),GRk */
+- [0x32] = _MA_LDxI | _MA_WORD, /* LDI @(GRi,d12),GRk */
+- [0x33] = _MA_LDxI | _MA_DWORD, /* LDDI @(GRi,d12),GRk */
+- [0x36] = _MA_LDxI | _MA_HALF, /* LDUHI @(GRi,d12),GRk */
+- [0x51] = _MA_STxI | _MA_HALF, /* STHI @(GRi,d12),GRk */
+- [0x52] = _MA_STxI | _MA_WORD, /* STI @(GRi,d12),GRk */
+- [0x53] = _MA_STxI | _MA_DWORD, /* STDI @(GRi,d12),GRk */
+-};
+-
+-
+-/*****************************************************************************/
+-/*
+- * see if we can handle the exception by fixing up a misaligned memory access
+- */
+-int handle_misalignment(unsigned long esr0, unsigned long ear0, unsigned long epcr0)
+-{
+- unsigned long insn, addr, *greg;
+- int GRi, GRj, GRk, D12, op;
+-
+- union {
+- uint64_t _64;
+- uint32_t _32[2];
+- uint16_t _16;
+- uint8_t _8[8];
+- } x;
+-
+- if (!(esr0 & ESR0_EAV) || !(epcr0 & EPCR0_V) || !(ear0 & 7))
+- return -EAGAIN;
+-
+- epcr0 &= EPCR0_PC;
+-
+- if (__frame->pc != epcr0) {
+- kdebug("MISALIGN: Execution not halted on excepting instruction\n");
+- BUG();
+- }
+-
+- if (__get_user(insn, (unsigned long *) epcr0) < 0)
+- return -EFAULT;
+-
+- /* determine the instruction type first */
+- switch ((insn >> 18) & 0x7f) {
+- case 0x2:
+- /* LDx @(GRi,GRj),GRk */
+- op = tbl_LDGRk_reg[(insn >> 6) & 0x3f];
+- break;
+-
+- case 0x3:
+- /* STx GRk,@(GRi,GRj) */
+- op = tbl_STGRk_reg[(insn >> 6) & 0x3f];
+- break;
+-
+- default:
+- op = tbl_LDSTGRk_imm[(insn >> 18) & 0x7f];
+- break;
+- }
+-
+- if (!op)
+- return -EAGAIN;
+-
+- kdebug("MISALIGN: pc=%08lx insn=%08lx ad=%08lx op=%02x\n", epcr0, insn, ear0, op);
+-
+- memset(&x, 0xba, 8);
+-
+- /* validate the instruction parameters */
+- greg = (unsigned long *) &__frame->tbr;
+-
+- GRi = (insn >> 12) & 0x3f;
+- GRk = (insn >> 25) & 0x3f;
+-
+- if (GRi > 31 || GRk > 31)
+- return -ENOENT;
+-
+- if (op & _MA_DWORD && GRk & 1)
+- return -EINVAL;
+-
+- if (op & _MA_IMM) {
+- D12 = insn & 0xfff;
+- asm ("slli %0,#20,%0 ! srai %0,#20,%0" : "=r"(D12) : "0"(D12)); /* sign extend */
+- addr = (GRi ? greg[GRi] : 0) + D12;
+- }
+- else {
+- GRj = (insn >> 0) & 0x3f;
+- if (GRj > 31)
+- return -ENOENT;
+- addr = (GRi ? greg[GRi] : 0) + (GRj ? greg[GRj] : 0);
+- }
+-
+- if (addr != ear0) {
+- kdebug("MISALIGN: Calculated addr (%08lx) does not match EAR0 (%08lx)\n",
+- addr, ear0);
+- return -EFAULT;
+- }
+-
+- /* check the address is okay */
+- if (user_mode(__frame) && ___range_ok(ear0, 8) < 0)
+- return -EFAULT;
+-
+- /* perform the memory op */
+- if (op & _MA_STORE) {
+- /* perform a store */
+- x._32[0] = 0;
+- if (GRk != 0) {
+- if (op & _MA_HALF) {
+- x._16 = greg[GRk];
+- }
+- else {
+- x._32[0] = greg[GRk];
+- }
+- }
+- if (op & _MA_DWORD)
+- x._32[1] = greg[GRk + 1];
+-
+- kdebug("MISALIGN: Store GR%d { %08x:%08x } -> %08lx (%dB)\n",
+- GRk, x._32[1], x._32[0], addr, op & _MA_SZ_MASK);
+-
+- if (__memcpy_user((void *) addr, &x, op & _MA_SZ_MASK) != 0)
+- return -EFAULT;
+- }
+- else {
+- /* perform a load */
+- if (__memcpy_user(&x, (void *) addr, op & _MA_SZ_MASK) != 0)
+- return -EFAULT;
+-
+- if (op & _MA_HALF) {
+- if (op & _MA_SIGNED)
+- asm ("slli %0,#16,%0 ! srai %0,#16,%0"
+- : "=r"(x._32[0]) : "0"(x._16));
+- else
+- asm ("sethi #0,%0"
+- : "=r"(x._32[0]) : "0"(x._16));
+- }
+-
+- kdebug("MISALIGN: Load %08lx (%dB) -> GR%d, { %08x:%08x }\n",
+- addr, op & _MA_SZ_MASK, GRk, x._32[1], x._32[0]);
+-
+- if (GRk != 0)
+- greg[GRk] = x._32[0];
+- if (op & _MA_DWORD)
+- greg[GRk + 1] = x._32[1];
+- }
+-
+- /* update the base pointer if required */
+- if (op & _MA_UPDATE)
+- greg[GRi] = addr;
+-
+- /* well... we've done that insn */
+- __frame->pc = __frame->pc + 4;
+-
+- return 0;
+-} /* end handle_misalignment() */
diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile
index 874f6ae..6c248c3 100644
--- a/arch/h8300/kernel/Makefile
@@ -84946,6 +91414,27 @@
setup.o gpio.o init_task.o syscalls.o \
entry.o
+diff --git a/arch/h8300/kernel/asm-offsets.c b/arch/h8300/kernel/asm-offsets.c
+index fc30b4f..2042552 100644
+--- a/arch/h8300/kernel/asm-offsets.c
++++ b/arch/h8300/kernel/asm-offsets.c
+@@ -13,15 +13,11 @@
+ #include <linux/kernel_stat.h>
+ #include <linux/ptrace.h>
+ #include <linux/hardirq.h>
++#include <linux/kbuild.h>
+ #include <asm/bootinfo.h>
+ #include <asm/irq.h>
+ #include <asm/ptrace.h>
+
+-#define DEFINE(sym, val) \
+- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+-
+-#define BLANK() asm volatile("\n->" : : )
+-
+ int main(void)
+ {
+ /* offsets into the task struct */
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
index d1b1526..6866bd9 100644
--- a/arch/h8300/kernel/h8300_ksyms.c
@@ -85097,10 +91586,29 @@
- return waking_non_zero_trylock(sem);
-}
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
-index 8fa3faf..cd13e13 100644
+index 8fa3faf..0df5f6f 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
-@@ -266,23 +266,23 @@ config IOSAPIC
+@@ -19,6 +19,8 @@ config IA64
+ select HAVE_OPROFILE
+ select HAVE_KPROBES
+ select HAVE_KRETPROBES
++ select HAVE_DMA_ATTRS
++ select HAVE_KVM
+ default y
+ help
+ The Itanium Processor Family is Intel's 64-bit successor to
+@@ -46,6 +48,9 @@ config MMU
+ config SWIOTLB
+ bool
+
++config IOMMU_HELPER
++ bool
++
+ config GENERIC_LOCKBREAK
+ bool
+ default y
+@@ -266,23 +271,23 @@ config IOSAPIC
depends on !IA64_HP_SIM
default y
@@ -85135,18 +91643,159 @@
config SMP
bool "Symmetric multi-processing support"
help
-@@ -611,6 +611,9 @@ config IRQ_PER_CPU
+@@ -589,6 +594,8 @@ config MSPEC
+
+ source "fs/Kconfig"
+
++source "arch/ia64/kvm/Kconfig"
++
+ source "lib/Kconfig"
+
+ #
+@@ -611,6 +618,9 @@ config IRQ_PER_CPU
bool
default y
+config IOMMU_HELPER
-+ def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC)
++ def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC || SWIOTLB)
+
source "arch/ia64/hp/sim/Kconfig"
source "arch/ia64/Kconfig.debug"
+diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
+index f1645c4..ec4cca4 100644
+--- a/arch/ia64/Makefile
++++ b/arch/ia64/Makefile
+@@ -57,6 +57,7 @@ core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/
+ core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/
+ core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/
+ core-$(CONFIG_IA64_SGI_SN2) += arch/ia64/sn/
++core-$(CONFIG_KVM) += arch/ia64/kvm/
+
+ drivers-$(CONFIG_PCI) += arch/ia64/pci/
+ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/
+diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c
+index 8f6bcfe..1c44ec2 100644
+--- a/arch/ia64/hp/common/hwsw_iommu.c
++++ b/arch/ia64/hp/common/hwsw_iommu.c
+@@ -20,10 +20,10 @@
+ extern int swiotlb_late_init_with_default_size (size_t size);
+ extern ia64_mv_dma_alloc_coherent swiotlb_alloc_coherent;
+ extern ia64_mv_dma_free_coherent swiotlb_free_coherent;
+-extern ia64_mv_dma_map_single swiotlb_map_single;
+-extern ia64_mv_dma_unmap_single swiotlb_unmap_single;
+-extern ia64_mv_dma_map_sg swiotlb_map_sg;
+-extern ia64_mv_dma_unmap_sg swiotlb_unmap_sg;
++extern ia64_mv_dma_map_single_attrs swiotlb_map_single_attrs;
++extern ia64_mv_dma_unmap_single_attrs swiotlb_unmap_single_attrs;
++extern ia64_mv_dma_map_sg_attrs swiotlb_map_sg_attrs;
++extern ia64_mv_dma_unmap_sg_attrs swiotlb_unmap_sg_attrs;
+ extern ia64_mv_dma_supported swiotlb_dma_supported;
+ extern ia64_mv_dma_mapping_error swiotlb_dma_mapping_error;
+
+@@ -31,19 +31,19 @@ extern ia64_mv_dma_mapping_error swiotlb_dma_mapping_error;
+
+ extern ia64_mv_dma_alloc_coherent sba_alloc_coherent;
+ extern ia64_mv_dma_free_coherent sba_free_coherent;
+-extern ia64_mv_dma_map_single sba_map_single;
+-extern ia64_mv_dma_unmap_single sba_unmap_single;
+-extern ia64_mv_dma_map_sg sba_map_sg;
+-extern ia64_mv_dma_unmap_sg sba_unmap_sg;
++extern ia64_mv_dma_map_single_attrs sba_map_single_attrs;
++extern ia64_mv_dma_unmap_single_attrs sba_unmap_single_attrs;
++extern ia64_mv_dma_map_sg_attrs sba_map_sg_attrs;
++extern ia64_mv_dma_unmap_sg_attrs sba_unmap_sg_attrs;
+ extern ia64_mv_dma_supported sba_dma_supported;
+ extern ia64_mv_dma_mapping_error sba_dma_mapping_error;
+
+ #define hwiommu_alloc_coherent sba_alloc_coherent
+ #define hwiommu_free_coherent sba_free_coherent
+-#define hwiommu_map_single sba_map_single
+-#define hwiommu_unmap_single sba_unmap_single
+-#define hwiommu_map_sg sba_map_sg
+-#define hwiommu_unmap_sg sba_unmap_sg
++#define hwiommu_map_single_attrs sba_map_single_attrs
++#define hwiommu_unmap_single_attrs sba_unmap_single_attrs
++#define hwiommu_map_sg_attrs sba_map_sg_attrs
++#define hwiommu_unmap_sg_attrs sba_unmap_sg_attrs
+ #define hwiommu_dma_supported sba_dma_supported
+ #define hwiommu_dma_mapping_error sba_dma_mapping_error
+ #define hwiommu_sync_single_for_cpu machvec_dma_sync_single
+@@ -98,41 +98,48 @@ hwsw_free_coherent (struct device *dev, size_t size, void *vaddr, dma_addr_t dma
+ }
+
+ dma_addr_t
+-hwsw_map_single (struct device *dev, void *addr, size_t size, int dir)
++hwsw_map_single_attrs(struct device *dev, void *addr, size_t size, int dir,
++ struct dma_attrs *attrs)
+ {
+ if (use_swiotlb(dev))
+- return swiotlb_map_single(dev, addr, size, dir);
++ return swiotlb_map_single_attrs(dev, addr, size, dir, attrs);
+ else
+- return hwiommu_map_single(dev, addr, size, dir);
++ return hwiommu_map_single_attrs(dev, addr, size, dir, attrs);
+ }
++EXPORT_SYMBOL(hwsw_map_single_attrs);
+
+ void
+-hwsw_unmap_single (struct device *dev, dma_addr_t iova, size_t size, int dir)
++hwsw_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size,
++ int dir, struct dma_attrs *attrs)
+ {
+ if (use_swiotlb(dev))
+- return swiotlb_unmap_single(dev, iova, size, dir);
++ return swiotlb_unmap_single_attrs(dev, iova, size, dir, attrs);
+ else
+- return hwiommu_unmap_single(dev, iova, size, dir);
++ return hwiommu_unmap_single_attrs(dev, iova, size, dir, attrs);
+ }
+-
++EXPORT_SYMBOL(hwsw_unmap_single_attrs);
+
+ int
+-hwsw_map_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir)
++hwsw_map_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents,
++ int dir, struct dma_attrs *attrs)
+ {
+ if (use_swiotlb(dev))
+- return swiotlb_map_sg(dev, sglist, nents, dir);
++ return swiotlb_map_sg_attrs(dev, sglist, nents, dir, attrs);
+ else
+- return hwiommu_map_sg(dev, sglist, nents, dir);
++ return hwiommu_map_sg_attrs(dev, sglist, nents, dir, attrs);
+ }
++EXPORT_SYMBOL(hwsw_map_sg_attrs);
+
+ void
+-hwsw_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir)
++hwsw_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents,
++ int dir, struct dma_attrs *attrs)
+ {
+ if (use_swiotlb(dev))
+- return swiotlb_unmap_sg(dev, sglist, nents, dir);
++ return swiotlb_unmap_sg_attrs(dev, sglist, nents, dir, attrs);
+ else
+- return hwiommu_unmap_sg(dev, sglist, nents, dir);
++ return hwiommu_unmap_sg_attrs(dev, sglist, nents, dir, attrs);
+ }
++EXPORT_SYMBOL(hwsw_unmap_sg_attrs);
+
+ void
+ hwsw_sync_single_for_cpu (struct device *dev, dma_addr_t addr, size_t size, int dir)
+@@ -185,10 +192,6 @@ hwsw_dma_mapping_error (dma_addr_t dma_addr)
+ }
+
+ EXPORT_SYMBOL(hwsw_dma_mapping_error);
+-EXPORT_SYMBOL(hwsw_map_single);
+-EXPORT_SYMBOL(hwsw_unmap_single);
+-EXPORT_SYMBOL(hwsw_map_sg);
+-EXPORT_SYMBOL(hwsw_unmap_sg);
+ EXPORT_SYMBOL(hwsw_dma_supported);
+ EXPORT_SYMBOL(hwsw_alloc_coherent);
+ EXPORT_SYMBOL(hwsw_free_coherent);
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
-index 523eae6..9409de5 100644
+index 523eae6..34421ae 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -35,6 +35,7 @@
@@ -85280,7 +91929,44 @@
if (unlikely(pide >= (ioc->res_size << 3)))
panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n",
ioc->ioc_hpa);
-@@ -936,7 +958,7 @@ sba_map_single(struct device *dev, void *addr, size_t size, int dir)
+@@ -877,16 +899,18 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
+ }
+
+ /**
+- * sba_map_single - map one buffer and return IOVA for DMA
++ * sba_map_single_attrs - map one buffer and return IOVA for DMA
+ * @dev: instance of PCI owned by the driver that's asking.
+ * @addr: driver buffer to map.
+ * @size: number of bytes to map in driver buffer.
+ * @dir: R/W or both.
++ * @attrs: optional dma attributes
+ *
+ * See Documentation/DMA-mapping.txt
+ */
+ dma_addr_t
+-sba_map_single(struct device *dev, void *addr, size_t size, int dir)
++sba_map_single_attrs(struct device *dev, void *addr, size_t size, int dir,
++ struct dma_attrs *attrs)
+ {
+ struct ioc *ioc;
+ dma_addr_t iovp;
+@@ -910,7 +934,8 @@ sba_map_single(struct device *dev, void *addr, size_t size, int dir)
+ ** Device is bit capable of DMA'ing to the buffer...
+ ** just return the PCI address of ptr
+ */
+- DBG_BYPASS("sba_map_single() bypass mask/addr: 0x%lx/0x%lx\n",
++ DBG_BYPASS("sba_map_single_attrs() bypass mask/addr: "
++ "0x%lx/0x%lx\n",
+ to_pci_dev(dev)->dma_mask, pci_addr);
+ return pci_addr;
+ }
+@@ -931,12 +956,12 @@ sba_map_single(struct device *dev, void *addr, size_t size, int dir)
+
+ #ifdef ASSERT_PDIR_SANITY
+ spin_lock_irqsave(&ioc->res_lock, flags);
+- if (sba_check_pdir(ioc,"Check before sba_map_single()"))
++ if (sba_check_pdir(ioc,"Check before sba_map_single_attrs()"))
+ panic("Sanity check failed");
spin_unlock_irqrestore(&ioc->res_lock, flags);
#endif
@@ -85289,7 +91975,79 @@
iovp = (dma_addr_t) pide << iovp_shift;
-@@ -1373,7 +1395,7 @@ sba_coalesce_chunks(struct ioc *ioc, struct device *dev,
+@@ -960,11 +985,12 @@ sba_map_single(struct device *dev, void *addr, size_t size, int dir)
+ /* form complete address */
+ #ifdef ASSERT_PDIR_SANITY
+ spin_lock_irqsave(&ioc->res_lock, flags);
+- sba_check_pdir(ioc,"Check after sba_map_single()");
++ sba_check_pdir(ioc,"Check after sba_map_single_attrs()");
+ spin_unlock_irqrestore(&ioc->res_lock, flags);
+ #endif
+ return SBA_IOVA(ioc, iovp, offset);
+ }
++EXPORT_SYMBOL(sba_map_single_attrs);
+
+ #ifdef ENABLE_MARK_CLEAN
+ static SBA_INLINE void
+@@ -991,15 +1017,17 @@ sba_mark_clean(struct ioc *ioc, dma_addr_t iova, size_t size)
+ #endif
+
+ /**
+- * sba_unmap_single - unmap one IOVA and free resources
++ * sba_unmap_single_attrs - unmap one IOVA and free resources
+ * @dev: instance of PCI owned by the driver that's asking.
+ * @iova: IOVA of driver buffer previously mapped.
+ * @size: number of bytes mapped in driver buffer.
+ * @dir: R/W or both.
++ * @attrs: optional dma attributes
+ *
+ * See Documentation/DMA-mapping.txt
+ */
+-void sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, int dir)
++void sba_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size,
++ int dir, struct dma_attrs *attrs)
+ {
+ struct ioc *ioc;
+ #if DELAYED_RESOURCE_CNT > 0
+@@ -1016,7 +1044,8 @@ void sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, int dir)
+ /*
+ ** Address does not fall w/in IOVA, must be bypassing
+ */
+- DBG_BYPASS("sba_unmap_single() bypass addr: 0x%lx\n", iova);
++ DBG_BYPASS("sba_unmap_single_atttrs() bypass addr: 0x%lx\n",
++ iova);
+
+ #ifdef ENABLE_MARK_CLEAN
+ if (dir == DMA_FROM_DEVICE) {
+@@ -1065,7 +1094,7 @@ void sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, int dir)
+ spin_unlock_irqrestore(&ioc->res_lock, flags);
+ #endif /* DELAYED_RESOURCE_CNT == 0 */
+ }
+-
++EXPORT_SYMBOL(sba_unmap_single_attrs);
+
+ /**
+ * sba_alloc_coherent - allocate/map shared mem for DMA
+@@ -1122,7 +1151,8 @@ sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp
+ * If device can't bypass or bypass is disabled, pass the 32bit fake
+ * device to map single to get an iova mapping.
+ */
+- *dma_handle = sba_map_single(&ioc->sac_only_dev->dev, addr, size, 0);
++ *dma_handle = sba_map_single_attrs(&ioc->sac_only_dev->dev, addr,
++ size, 0, NULL);
+
+ return addr;
+ }
+@@ -1139,7 +1169,7 @@ sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp
+ */
+ void sba_free_coherent (struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle)
+ {
+- sba_unmap_single(dev, dma_handle, size, 0);
++ sba_unmap_single_attrs(dev, dma_handle, size, 0, NULL);
+ free_pages((unsigned long) vaddr, get_order(size));
+ }
+
+@@ -1373,7 +1403,7 @@ sba_coalesce_chunks(struct ioc *ioc, struct device *dev,
dma_len = (dma_len + dma_offset + ~iovp_mask) & iovp_mask;
ASSERT(dma_len <= DMA_CHUNK_SIZE);
dma_sg->dma_address = (dma_addr_t) (PIDE_FLAG
@@ -85298,6 +92056,137 @@
| dma_offset);
n_mappings++;
}
+@@ -1388,10 +1418,12 @@ sba_coalesce_chunks(struct ioc *ioc, struct device *dev,
+ * @sglist: array of buffer/length pairs
+ * @nents: number of entries in list
+ * @dir: R/W or both.
++ * @attrs: optional dma attributes
+ *
+ * See Documentation/DMA-mapping.txt
+ */
+-int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int dir)
++int sba_map_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents,
++ int dir, struct dma_attrs *attrs)
+ {
+ struct ioc *ioc;
+ int coalesced, filled = 0;
+@@ -1419,16 +1451,16 @@ int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int di
+ /* Fast path single entry scatterlists. */
+ if (nents == 1) {
+ sglist->dma_length = sglist->length;
+- sglist->dma_address = sba_map_single(dev, sba_sg_address(sglist), sglist->length, dir);
++ sglist->dma_address = sba_map_single_attrs(dev, sba_sg_address(sglist), sglist->length, dir, attrs);
+ return 1;
+ }
+
+ #ifdef ASSERT_PDIR_SANITY
+ spin_lock_irqsave(&ioc->res_lock, flags);
+- if (sba_check_pdir(ioc,"Check before sba_map_sg()"))
++ if (sba_check_pdir(ioc,"Check before sba_map_sg_attrs()"))
+ {
+ sba_dump_sg(ioc, sglist, nents);
+- panic("Check before sba_map_sg()");
++ panic("Check before sba_map_sg_attrs()");
+ }
+ spin_unlock_irqrestore(&ioc->res_lock, flags);
+ #endif
+@@ -1457,10 +1489,10 @@ int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int di
+
+ #ifdef ASSERT_PDIR_SANITY
+ spin_lock_irqsave(&ioc->res_lock, flags);
+- if (sba_check_pdir(ioc,"Check after sba_map_sg()"))
++ if (sba_check_pdir(ioc,"Check after sba_map_sg_attrs()"))
+ {
+ sba_dump_sg(ioc, sglist, nents);
+- panic("Check after sba_map_sg()\n");
++ panic("Check after sba_map_sg_attrs()\n");
+ }
+ spin_unlock_irqrestore(&ioc->res_lock, flags);
+ #endif
+@@ -1470,18 +1502,20 @@ int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int di
+
+ return filled;
+ }
+-
++EXPORT_SYMBOL(sba_map_sg_attrs);
+
+ /**
+- * sba_unmap_sg - unmap Scatter/Gather list
++ * sba_unmap_sg_attrs - unmap Scatter/Gather list
+ * @dev: instance of PCI owned by the driver that's asking.
+ * @sglist: array of buffer/length pairs
+ * @nents: number of entries in list
+ * @dir: R/W or both.
++ * @attrs: optional dma attributes
+ *
+ * See Documentation/DMA-mapping.txt
+ */
+-void sba_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir)
++void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
++ int nents, int dir, struct dma_attrs *attrs)
+ {
+ #ifdef ASSERT_PDIR_SANITY
+ struct ioc *ioc;
+@@ -1496,13 +1530,14 @@ void sba_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, in
+ ASSERT(ioc);
+
+ spin_lock_irqsave(&ioc->res_lock, flags);
+- sba_check_pdir(ioc,"Check before sba_unmap_sg()");
++ sba_check_pdir(ioc,"Check before sba_unmap_sg_attrs()");
+ spin_unlock_irqrestore(&ioc->res_lock, flags);
+ #endif
+
+ while (nents && sglist->dma_length) {
+
+- sba_unmap_single(dev, sglist->dma_address, sglist->dma_length, dir);
++ sba_unmap_single_attrs(dev, sglist->dma_address,
++ sglist->dma_length, dir, attrs);
+ sglist = sg_next(sglist);
+ nents--;
+ }
+@@ -1511,11 +1546,12 @@ void sba_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, in
+
+ #ifdef ASSERT_PDIR_SANITY
+ spin_lock_irqsave(&ioc->res_lock, flags);
+- sba_check_pdir(ioc,"Check after sba_unmap_sg()");
++ sba_check_pdir(ioc,"Check after sba_unmap_sg_attrs()");
+ spin_unlock_irqrestore(&ioc->res_lock, flags);
+ #endif
+
+ }
++EXPORT_SYMBOL(sba_unmap_sg_attrs);
+
+ /**************************************************************
+ *
+@@ -1896,15 +1932,13 @@ static const struct file_operations ioc_fops = {
+ static void __init
+ ioc_proc_init(void)
+ {
+- struct proc_dir_entry *dir, *entry;
++ struct proc_dir_entry *dir;
+
+ dir = proc_mkdir("bus/mckinley", NULL);
+ if (!dir)
+ return;
+
+- entry = create_proc_entry(ioc_list->name, 0, dir);
+- if (entry)
+- entry->proc_fops = &ioc_fops;
++ proc_create(ioc_list->name, 0, dir, &ioc_fops);
+ }
+ #endif
+
+@@ -2144,10 +2178,6 @@ sba_page_override(char *str)
+ __setup("sbapagesize=",sba_page_override);
+
+ EXPORT_SYMBOL(sba_dma_mapping_error);
+-EXPORT_SYMBOL(sba_map_single);
+-EXPORT_SYMBOL(sba_unmap_single);
+-EXPORT_SYMBOL(sba_map_sg);
+-EXPORT_SYMBOL(sba_unmap_sg);
+ EXPORT_SYMBOL(sba_dma_supported);
+ EXPORT_SYMBOL(sba_alloc_coherent);
+ EXPORT_SYMBOL(sba_free_coherent);
diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c
index 969fe9f..3d47839 100644
--- a/arch/ia64/hp/sim/simeth.c
@@ -85365,6 +92254,47 @@
sc->result = GOOD;
break;
+diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
+index eb0c32a..23cafc8 100644
+--- a/arch/ia64/hp/sim/simserial.c
++++ b/arch/ia64/hp/sim/simserial.c
+@@ -210,21 +210,23 @@ static void do_softint(struct work_struct *private_)
+ printk(KERN_ERR "simserial: do_softint called\n");
+ }
+
+-static void rs_put_char(struct tty_struct *tty, unsigned char ch)
++static int rs_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ struct async_struct *info = (struct async_struct *)tty->driver_data;
+ unsigned long flags;
+
+- if (!tty || !info->xmit.buf) return;
++ if (!tty || !info->xmit.buf)
++ return 0;
+
+ local_irq_save(flags);
+ if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) {
+ local_irq_restore(flags);
+- return;
++ return 0;
+ }
+ info->xmit.buf[info->xmit.head] = ch;
+ info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1);
+ local_irq_restore(flags);
++ return 1;
+ }
+
+ static void transmit_chars(struct async_struct *info, int *intr_done)
+@@ -621,7 +623,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
+ * the line discipline to only process XON/XOFF characters.
+ */
+ shutdown(info);
+- if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty);
++ if (tty->ops->flush_buffer)
++ tty->ops->flush_buffer(tty);
+ if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty);
+ info->event = 0;
+ info->tty = NULL;
diff --git a/arch/ia64/ia32/elfcore32.h b/arch/ia64/ia32/elfcore32.h
index 446c9aa..9a3abf5 100644
--- a/arch/ia64/ia32/elfcore32.h
@@ -86134,18 +93064,33 @@
printk(KERN_INFO "Number of logical nodes in system = %d\n",
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
-index 0aebc6f..230a6f9 100644
+index 0aebc6f..c64a55a 100644
--- a/arch/ia64/kernel/asm-offsets.c
+++ b/arch/ia64/kernel/asm-offsets.c
-@@ -7,6 +7,7 @@
+@@ -7,8 +7,9 @@
#define ASM_OFFSETS_C 1
#include <linux/sched.h>
+#include <linux/pid.h>
#include <linux/clocksource.h>
-
+-
++#include <linux/kbuild.h>
#include <asm-ia64/processor.h>
-@@ -34,17 +35,29 @@ void foo(void)
+ #include <asm-ia64/ptrace.h>
+ #include <asm-ia64/siginfo.h>
+@@ -18,11 +19,6 @@
+ #include "../kernel/sigframe.h"
+ #include "../kernel/fsyscall_gtod_data.h"
+
+-#define DEFINE(sym, val) \
+- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+-
+-#define BLANK() asm volatile("\n->" : : )
+-
+ void foo(void)
+ {
+ DEFINE(IA64_TASK_SIZE, sizeof (struct task_struct));
+@@ -34,17 +30,29 @@ void foo(void)
DEFINE(SIGFRAME_SIZE, sizeof (struct sigframe));
DEFINE(UNW_FRAME_INFO_SIZE, sizeof (struct unw_frame_info));
@@ -87441,7 +94386,7 @@
++offp;
}
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
-index a2aabfd..c8e4037 100644
+index a2aabfd..7fbb51e 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -4204,10 +4204,10 @@ pfm_check_task_exist(pfm_context_t *ctx)
@@ -87475,10 +94420,37 @@
total_cycles = ia64_get_itc();
+@@ -6695,16 +6695,12 @@ pfm_init(void)
+ /*
+ * create /proc/perfmon (mostly for debugging purposes)
+ */
+- perfmon_dir = create_proc_entry("perfmon", S_IRUGO, NULL);
++ perfmon_dir = proc_create("perfmon", S_IRUGO, NULL, &pfm_proc_fops);
+ if (perfmon_dir == NULL) {
+ printk(KERN_ERR "perfmon: cannot create /proc entry, perfmon disabled\n");
+ pmu_conf = NULL;
+ return -1;
+ }
+- /*
+- * install customized file operations for /proc/perfmon entry
+- */
+- perfmon_dir->proc_fops = &pfm_proc_fops;
+
+ /*
+ * create /proc/sys/kernel/perfmon (for debugging purposes)
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
-index 49937a3..a5ea817 100644
+index 49937a3..58dcfac 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
+@@ -183,7 +183,7 @@ do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall
+ #endif
+
+ /* deal with pending signal delivery */
+- if (test_thread_flag(TIF_SIGPENDING)||test_thread_flag(TIF_RESTORE_SIGMASK))
++ if (test_thread_flag(TIF_SIGPENDING))
+ ia64_do_signal(scr, in_syscall);
+
+ /* copy user rbs to kernel rbs */
@@ -625,21 +625,6 @@ do_dump_fpu (struct unw_frame_info *info, void *arg)
do_dump_task_fpu(current, info, arg);
}
@@ -88777,7 +95749,7 @@
+ return &user_ia64_view;
+}
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
-index 779c3cc..b11bb50 100644
+index 779c3cc..ecb9eb7 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -44,8 +44,8 @@
@@ -88790,6 +95762,29 @@
#include <asm/sal.h>
#include <asm/uaccess.h>
+@@ -648,18 +648,16 @@ salinfo_init(void)
+ if (!dir)
+ continue;
+
+- entry = create_proc_entry("event", S_IRUSR, dir);
++ entry = proc_create_data("event", S_IRUSR, dir,
++ &salinfo_event_fops, data);
+ if (!entry)
+ continue;
+- entry->data = data;
+- entry->proc_fops = &salinfo_event_fops;
+ *sdir++ = entry;
+
+- entry = create_proc_entry("data", S_IRUSR | S_IWUSR, dir);
++ entry = proc_create_data("data", S_IRUSR | S_IWUSR, dir,
++ &salinfo_data_fops, data);
+ if (!entry)
+ continue;
+- entry->data = data;
+- entry->proc_fops = &salinfo_data_fops;
+ *sdir++ = entry;
+
+ /* we missed any events before now */
diff --git a/arch/ia64/kernel/semaphore.c b/arch/ia64/kernel/semaphore.c
deleted file mode 100644
index 2724ef3..0000000
@@ -89126,7 +96121,7 @@
* this function sends a 'generic call function' IPI to all other CPUs
* in the system.
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
-index 32ee597..16483be 100644
+index 32ee597..d7ad42b 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -400,9 +400,9 @@ smp_callin (void)
@@ -89140,6 +96135,32 @@
smp_setup_percpu_timer();
+@@ -873,7 +873,8 @@ identify_siblings(struct cpuinfo_ia64 *c)
+ u16 pltid;
+ pal_logical_to_physical_t info;
+
+- if ((status = ia64_pal_logical_to_phys(-1, &info)) != PAL_STATUS_SUCCESS) {
++ status = ia64_pal_logical_to_phys(-1, &info);
++ if (status != PAL_STATUS_SUCCESS) {
+ if (status != PAL_STATUS_UNIMPLEMENTED) {
+ printk(KERN_ERR
+ "ia64_pal_logical_to_phys failed with %ld\n",
+@@ -885,8 +886,13 @@ identify_siblings(struct cpuinfo_ia64 *c)
+ info.overview_cpp = 1;
+ info.overview_tpc = 1;
+ }
+- if ((status = ia64_sal_physical_id_info(&pltid)) != PAL_STATUS_SUCCESS) {
+- printk(KERN_ERR "ia64_sal_pltid failed with %ld\n", status);
++
++ status = ia64_sal_physical_id_info(&pltid);
++ if (status != PAL_STATUS_SUCCESS) {
++ if (status != PAL_STATUS_UNIMPLEMENTED)
++ printk(KERN_ERR
++ "ia64_sal_pltid failed with %ld\n",
++ status);
+ return;
+ }
+
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 17fda52..48e15a5 100644
--- a/arch/ia64/kernel/time.c
@@ -89229,6 +96250,26 @@
static irqreturn_t
timer_interrupt (int irq, void *dev_id)
{
+diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
+index a2484fc..abb17a6 100644
+--- a/arch/ia64/kernel/topology.c
++++ b/arch/ia64/kernel/topology.c
+@@ -27,6 +27,15 @@
+
+ static struct ia64_cpu *sysfs_cpus;
+
++void arch_fix_phys_package_id(int num, u32 slot)
++{
++#ifdef CONFIG_SMP
++ if (cpu_data(num)->socket_id == -1)
++ cpu_data(num)->socket_id = slot;
++#endif
++}
++EXPORT_SYMBOL_GPL(arch_fix_phys_package_id);
++
+ int arch_register_cpu(int num)
+ {
+ #if defined (CONFIG_ACPI) && defined (CONFIG_HOTPLUG_CPU)
diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c
index 6903361..ff0e7c1 100644
--- a/arch/ia64/kernel/unaligned.c
@@ -89250,1078 +96291,12974 @@
count = 0;
if (count < 5) {
last_time = jiffies;
-diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
-index 344f64e..798bf98 100644
---- a/arch/ia64/mm/contig.c
-+++ b/arch/ia64/mm/contig.c
-@@ -45,8 +45,6 @@ void show_mem(void)
-
- printk(KERN_INFO "Mem-info:\n");
- show_free_areas();
-- printk(KERN_INFO "Free swap: %6ldkB\n",
-- nr_swap_pages<<(PAGE_SHIFT-10));
- printk(KERN_INFO "Node memory in pages:\n");
- for_each_online_pgdat(pgdat) {
- unsigned long present;
-@@ -255,7 +253,7 @@ paging_init (void)
- max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
-
- #ifdef CONFIG_VIRTUAL_MEM_MAP
-- efi_memmap_walk(register_active_ranges, NULL);
-+ efi_memmap_walk(filter_memory, register_active_ranges);
- efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
- if (max_gap < LARGE_GAP) {
- vmem_map = (struct page *) 0;
-diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
-index ee5e68b..544dc42 100644
---- a/arch/ia64/mm/discontig.c
-+++ b/arch/ia64/mm/discontig.c
-@@ -104,7 +104,7 @@ static int __meminit early_nr_cpus_node(int node)
- {
- int cpu, n = 0;
-
-- for (cpu = 0; cpu < NR_CPUS; cpu++)
-+ for_each_possible_early_cpu(cpu)
- if (node == node_cpuid[cpu].nid)
- n++;
-
-@@ -124,6 +124,7 @@ static unsigned long __meminit compute_pernodesize(int node)
- pernodesize += node * L1_CACHE_BYTES;
- pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t));
- pernodesize += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
-+ pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t));
- pernodesize = PAGE_ALIGN(pernodesize);
- return pernodesize;
- }
-@@ -142,7 +143,7 @@ static void *per_cpu_node_setup(void *cpu_data, int node)
- #ifdef CONFIG_SMP
- int cpu;
-
-- for (cpu = 0; cpu < NR_CPUS; cpu++) {
-+ for_each_possible_early_cpu(cpu) {
- if (node == node_cpuid[cpu].nid) {
- memcpy(__va(cpu_data), __phys_per_cpu_start,
- __per_cpu_end - __per_cpu_start);
-@@ -345,7 +346,7 @@ static void __init initialize_pernode_data(void)
-
- #ifdef CONFIG_SMP
- /* Set the node_data pointer for each per-cpu struct */
-- for (cpu = 0; cpu < NR_CPUS; cpu++) {
-+ for_each_possible_early_cpu(cpu) {
- node = node_cpuid[cpu].nid;
- per_cpu(cpu_info, cpu).node_data = mem_data[node].node_data;
- }
-@@ -444,7 +445,7 @@ void __init find_memory(void)
- mem_data[node].min_pfn = ~0UL;
- }
-
-- efi_memmap_walk(register_active_ranges, NULL);
-+ efi_memmap_walk(filter_memory, register_active_ranges);
-
- /*
- * Initialize the boot memory maps in reverse order since that's
-@@ -493,13 +494,9 @@ void __cpuinit *per_cpu_init(void)
- int cpu;
- static int first_time = 1;
-
--
-- if (smp_processor_id() != 0)
-- return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
--
- if (first_time) {
- first_time = 0;
-- for (cpu = 0; cpu < NR_CPUS; cpu++)
-+ for_each_possible_early_cpu(cpu)
- per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
- }
-
-@@ -522,8 +519,6 @@ void show_mem(void)
-
- printk(KERN_INFO "Mem-info:\n");
- show_free_areas();
-- printk(KERN_INFO "Free swap: %6ldkB\n",
-- nr_swap_pages<<(PAGE_SHIFT-10));
- printk(KERN_INFO "Node memory in pages:\n");
- for_each_online_pgdat(pgdat) {
- unsigned long present;
-diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
-index a4ca657..5c1de53 100644
---- a/arch/ia64/mm/init.c
-+++ b/arch/ia64/mm/init.c
-@@ -58,7 +58,6 @@ __ia64_sync_icache_dcache (pte_t pte)
- {
- unsigned long addr;
- struct page *page;
-- unsigned long order;
-
- page = pte_page(pte);
- addr = (unsigned long) page_address(page);
-@@ -66,12 +65,7 @@ __ia64_sync_icache_dcache (pte_t pte)
- if (test_bit(PG_arch_1, &page->flags))
- return; /* i-cache is already coherent with d-cache */
+diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
+index 2a90c32..e77995a 100644
+--- a/arch/ia64/kernel/uncached.c
++++ b/arch/ia64/kernel/uncached.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (C) 2001-2006 Silicon Graphics, Inc. All rights reserved.
++ * Copyright (C) 2001-2008 Silicon Graphics, Inc. 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
+@@ -177,12 +177,13 @@ failed:
+ * uncached_alloc_page
+ *
+ * @starting_nid: node id of node to start with, or -1
++ * @n_pages: number of contiguous pages to allocate
+ *
+- * Allocate 1 uncached page. Allocates on the requested node. If no
+- * uncached pages are available on the requested node, roundrobin starting
+- * with the next higher node.
++ * Allocate the specified number of contiguous uncached pages on the
++ * the requested node. If not enough contiguous uncached pages are available
++ * on the requested node, roundrobin starting with the next higher node.
+ */
+-unsigned long uncached_alloc_page(int starting_nid)
++unsigned long uncached_alloc_page(int starting_nid, int n_pages)
+ {
+ unsigned long uc_addr;
+ struct uncached_pool *uc_pool;
+@@ -202,7 +203,8 @@ unsigned long uncached_alloc_page(int starting_nid)
+ if (uc_pool->pool == NULL)
+ continue;
+ do {
+- uc_addr = gen_pool_alloc(uc_pool->pool, PAGE_SIZE);
++ uc_addr = gen_pool_alloc(uc_pool->pool,
++ n_pages * PAGE_SIZE);
+ if (uc_addr != 0)
+ return uc_addr;
+ } while (uncached_add_chunk(uc_pool, nid) == 0);
+@@ -217,11 +219,12 @@ EXPORT_SYMBOL(uncached_alloc_page);
+ /*
+ * uncached_free_page
+ *
+- * @uc_addr: uncached address of page to free
++ * @uc_addr: uncached address of first page to free
++ * @n_pages: number of contiguous pages to free
+ *
+- * Free a single uncached page.
++ * Free the specified number of uncached pages.
+ */
+-void uncached_free_page(unsigned long uc_addr)
++void uncached_free_page(unsigned long uc_addr, int n_pages)
+ {
+ int nid = paddr_to_nid(uc_addr - __IA64_UNCACHED_OFFSET);
+ struct gen_pool *pool = uncached_pools[nid].pool;
+@@ -232,7 +235,7 @@ void uncached_free_page(unsigned long uc_addr)
+ if ((uc_addr & (0XFUL << 60)) != __IA64_UNCACHED_OFFSET)
+ panic("uncached_free_page invalid address %lx\n", uc_addr);
-- if (PageCompound(page)) {
-- order = compound_order(page);
-- flush_icache_range(addr, addr + (1UL << order << PAGE_SHIFT));
-- }
-- else
-- flush_icache_range(addr, addr + PAGE_SIZE);
-+ flush_icache_range(addr, addr + (PAGE_SIZE << compound_order(page)));
- set_bit(PG_arch_1, &page->flags); /* mark page as clean */
+- gen_pool_free(pool, uc_addr, PAGE_SIZE);
++ gen_pool_free(pool, uc_addr, n_pages * PAGE_SIZE);
}
+ EXPORT_SYMBOL(uncached_free_page);
-@@ -553,12 +547,10 @@ find_largest_hole (u64 start, u64 end, void *arg)
- #endif /* CONFIG_VIRTUAL_MEM_MAP */
-
- int __init
--register_active_ranges(u64 start, u64 end, void *arg)
-+register_active_ranges(u64 start, u64 len, int nid)
- {
-- int nid = paddr_to_nid(__pa(start));
-+ u64 end = start + len;
-
-- if (nid < 0)
-- nid = 0;
- #ifdef CONFIG_KEXEC
- if (start > crashk_res.start && start < crashk_res.end)
- start = crashk_res.end;
-diff --git a/arch/ia64/mm/numa.c b/arch/ia64/mm/numa.c
-index 7807fc5..b73bf18 100644
---- a/arch/ia64/mm/numa.c
-+++ b/arch/ia64/mm/numa.c
-@@ -27,7 +27,9 @@
- */
- int num_node_memblks;
- struct node_memblk_s node_memblk[NR_NODE_MEMBLKS];
--struct node_cpuid_s node_cpuid[NR_CPUS];
-+struct node_cpuid_s node_cpuid[NR_CPUS] =
-+ { [0 ... NR_CPUS-1] = { .phys_id = 0, .nid = NUMA_NO_NODE } };
+diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig
+new file mode 100644
+index 0000000..7914e48
+--- /dev/null
++++ b/arch/ia64/kvm/Kconfig
+@@ -0,0 +1,49 @@
++#
++# KVM configuration
++#
++config HAVE_KVM
++ bool
+
- /*
- * This is a matrix with "distances" between nodes, they should be
- * proportional to the memory access latency ratios.
-diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
-index 655da24..d52ec4e 100644
---- a/arch/ia64/mm/tlb.c
-+++ b/arch/ia64/mm/tlb.c
-@@ -11,6 +11,9 @@
- * Rohit Seth <rohit.seth at intel.com>
- * Ken Chen <kenneth.w.chen at intel.com>
- * Christophe de Dinechin <ddd at hp.com>: Avoid ptc.e on memory allocation
-+ * Copyright (C) 2007 Intel Corp
-+ * Fenghua Yu <fenghua.yu at intel.com>
-+ * Add multiple ptc.g/ptc.ga instruction support in global tlb purge.
- */
- #include <linux/module.h>
- #include <linux/init.h>
-@@ -26,6 +29,9 @@
- #include <asm/pal.h>
- #include <asm/tlbflush.h>
- #include <asm/dma.h>
-+#include <asm/processor.h>
-+#include <asm/sal.h>
-+#include <asm/tlb.h>
-
- static struct {
- unsigned long mask; /* mask of supported purge page-sizes */
-@@ -39,6 +45,10 @@ struct ia64_ctx ia64_ctx = {
- };
-
- DEFINE_PER_CPU(u8, ia64_need_tlb_flush);
-+DEFINE_PER_CPU(u8, ia64_tr_num); /*Number of TR slots in current processor*/
-+DEFINE_PER_CPU(u8, ia64_tr_used); /*Max Slot number used by kernel*/
++menuconfig VIRTUALIZATION
++ bool "Virtualization"
++ depends on HAVE_KVM || IA64
++ default y
++ ---help---
++ Say Y here to get to see options for using your Linux host to run other
++ operating systems inside virtual machines (guests).
++ This option alone does not add any kernel code.
++
++ If you say N, all options in this submenu will be skipped and disabled.
++
++if VIRTUALIZATION
++
++config KVM
++ tristate "Kernel-based Virtual Machine (KVM) support"
++ depends on HAVE_KVM && EXPERIMENTAL
++ select PREEMPT_NOTIFIERS
++ select ANON_INODES
++ ---help---
++ Support hosting fully virtualized guest machines using hardware
++ virtualization extensions. You will need a fairly recent
++ processor equipped with virtualization extensions. You will also
++ need to select one or more of the processor modules below.
+
-+struct ia64_tr_entry __per_cpu_idtrs[NR_CPUS][2][IA64_TR_ALLOC_MAX];
-
- /*
- * Initializes the ia64_ctx.bitmap array based on max_ctx+1.
-@@ -84,14 +94,140 @@ wrap_mmu_context (struct mm_struct *mm)
- local_flush_tlb_all();
- }
-
-+/*
-+ * Implement "spinaphores" ... like counting semaphores, but they
-+ * spin instead of sleeping. If there are ever any other users for
-+ * this primitive it can be moved up to a spinaphore.h header.
-+ */
-+struct spinaphore {
-+ atomic_t cur;
-+};
++ This module provides access to the hardware capabilities through
++ a character device node named /dev/kvm.
+
-+static inline void spinaphore_init(struct spinaphore *ss, int val)
-+{
-+ atomic_set(&ss->cur, val);
-+}
++ To compile this as a module, choose M here: the module
++ will be called kvm.
+
-+static inline void down_spin(struct spinaphore *ss)
-+{
-+ while (unlikely(!atomic_add_unless(&ss->cur, -1, 0)))
-+ while (atomic_read(&ss->cur) == 0)
-+ cpu_relax();
-+}
++ If unsure, say N.
+
-+static inline void up_spin(struct spinaphore *ss)
-+{
-+ atomic_add(1, &ss->cur);
-+}
++config KVM_INTEL
++ tristate "KVM for Intel Itanium 2 processors support"
++ depends on KVM && m
++ ---help---
++ Provides support for KVM on Itanium 2 processors equipped with the VT
++ extensions.
+
-+static struct spinaphore ptcg_sem;
-+static u16 nptcg = 1;
-+static int need_ptcg_sem = 1;
-+static int toolatetochangeptcgsem = 0;
++config KVM_TRACE
++ bool
++
++endif # VIRTUALIZATION
+diff --git a/arch/ia64/kvm/Makefile b/arch/ia64/kvm/Makefile
+new file mode 100644
+index 0000000..5235339
+--- /dev/null
++++ b/arch/ia64/kvm/Makefile
+@@ -0,0 +1,58 @@
++#This Make file is to generate asm-offsets.h and build source.
++#
++
++#Generate asm-offsets.h for vmm module build
++offsets-file := asm-offsets.h
+
++always := $(offsets-file)
++targets := $(offsets-file)
++targets += arch/ia64/kvm/asm-offsets.s
++clean-files := $(addprefix $(objtree)/,$(targets) $(obj)/memcpy.S $(obj)/memset.S)
++
++# Default sed regexp - multiline due to syntax constraints
++define sed-y
++ "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"
++endef
++
++quiet_cmd_offsets = GEN $@
++define cmd_offsets
++ (set -e; \
++ echo "#ifndef __ASM_KVM_OFFSETS_H__"; \
++ echo "#define __ASM_KVM_OFFSETS_H__"; \
++ echo "/*"; \
++ echo " * DO NOT MODIFY."; \
++ echo " *"; \
++ echo " * This file was generated by Makefile"; \
++ echo " *"; \
++ echo " */"; \
++ echo ""; \
++ sed -ne $(sed-y) $<; \
++ echo ""; \
++ echo "#endif" ) > $@
++endef
++# We use internal rules to avoid the "is up to date" message from make
++arch/ia64/kvm/asm-offsets.s: arch/ia64/kvm/asm-offsets.c
++ $(call if_changed_dep,cc_s_c)
++
++$(obj)/$(offsets-file): arch/ia64/kvm/asm-offsets.s
++ $(call cmd,offsets)
++
++#
++# Makefile for Kernel-based Virtual Machine module
++#
++
++EXTRA_CFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/
++EXTRA_AFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/
++
++common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o)
++
++kvm-objs := $(common-objs) kvm-ia64.o kvm_fw.o
++obj-$(CONFIG_KVM) += kvm.o
++
++FORCE : $(obj)/$(offsets-file)
++EXTRA_CFLAGS_vcpu.o += -mfixed-range=f2-f5,f12-f127
++kvm-intel-objs = vmm.o vmm_ivt.o trampoline.o vcpu.o optvfault.o mmio.o \
++ vtlb.o process.o
++#Add link memcpy and memset to avoid possible structure assignment error
++kvm-intel-objs += ../lib/memset.o ../lib/memcpy.o
++obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
+diff --git a/arch/ia64/kvm/asm-offsets.c b/arch/ia64/kvm/asm-offsets.c
+new file mode 100644
+index 0000000..4e3dc13
+--- /dev/null
++++ b/arch/ia64/kvm/asm-offsets.c
+@@ -0,0 +1,251 @@
+/*
-+ * Kernel parameter "nptcg=" overrides max number of concurrent global TLB
-+ * purges which is reported from either PAL or SAL PALO.
++ * asm-offsets.c Generate definitions needed by assembly language modules.
++ * This code generates raw asm output which is post-processed
++ * to extract and format the required data.
++ *
++ * Anthony Xu <anthony.xu at intel.com>
++ * Xiantao Zhang <xiantao.zhang at intel.com>
++ * Copyright (c) 2007 Intel Corporation KVM support.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You 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.
+ *
-+ * We don't have sanity checking for nptcg value. It's the user's responsibility
-+ * for valid nptcg value on the platform. Otherwise, kernel may hang in some
-+ * cases.
+ */
-+static int __init
-+set_nptcg(char *str)
-+{
-+ int value = 0;
+
-+ get_option(&str, &value);
-+ setup_ptcg_sem(value, NPTCG_FROM_KERNEL_PARAMETER);
++#include <linux/autoconf.h>
++#include <linux/kvm_host.h>
+
-+ return 1;
++#include "vcpu.h"
++
++#define task_struct kvm_vcpu
++
++#define DEFINE(sym, val) \
++ asm volatile("\n->" #sym " (%0) " #val : : "i" (val))
++
++#define BLANK() asm volatile("\n->" : :)
++
++#define OFFSET(_sym, _str, _mem) \
++ DEFINE(_sym, offsetof(_str, _mem));
++
++void foo(void)
++{
++ DEFINE(VMM_TASK_SIZE, sizeof(struct kvm_vcpu));
++ DEFINE(VMM_PT_REGS_SIZE, sizeof(struct kvm_pt_regs));
++
++ BLANK();
++
++ DEFINE(VMM_VCPU_META_RR0_OFFSET,
++ offsetof(struct kvm_vcpu, arch.metaphysical_rr0));
++ DEFINE(VMM_VCPU_META_SAVED_RR0_OFFSET,
++ offsetof(struct kvm_vcpu,
++ arch.metaphysical_saved_rr0));
++ DEFINE(VMM_VCPU_VRR0_OFFSET,
++ offsetof(struct kvm_vcpu, arch.vrr[0]));
++ DEFINE(VMM_VPD_IRR0_OFFSET,
++ offsetof(struct vpd, irr[0]));
++ DEFINE(VMM_VCPU_ITC_CHECK_OFFSET,
++ offsetof(struct kvm_vcpu, arch.itc_check));
++ DEFINE(VMM_VCPU_IRQ_CHECK_OFFSET,
++ offsetof(struct kvm_vcpu, arch.irq_check));
++ DEFINE(VMM_VPD_VHPI_OFFSET,
++ offsetof(struct vpd, vhpi));
++ DEFINE(VMM_VCPU_VSA_BASE_OFFSET,
++ offsetof(struct kvm_vcpu, arch.vsa_base));
++ DEFINE(VMM_VCPU_VPD_OFFSET,
++ offsetof(struct kvm_vcpu, arch.vpd));
++ DEFINE(VMM_VCPU_IRQ_CHECK,
++ offsetof(struct kvm_vcpu, arch.irq_check));
++ DEFINE(VMM_VCPU_TIMER_PENDING,
++ offsetof(struct kvm_vcpu, arch.timer_pending));
++ DEFINE(VMM_VCPU_META_SAVED_RR0_OFFSET,
++ offsetof(struct kvm_vcpu, arch.metaphysical_saved_rr0));
++ DEFINE(VMM_VCPU_MODE_FLAGS_OFFSET,
++ offsetof(struct kvm_vcpu, arch.mode_flags));
++ DEFINE(VMM_VCPU_ITC_OFS_OFFSET,
++ offsetof(struct kvm_vcpu, arch.itc_offset));
++ DEFINE(VMM_VCPU_LAST_ITC_OFFSET,
++ offsetof(struct kvm_vcpu, arch.last_itc));
++ DEFINE(VMM_VCPU_SAVED_GP_OFFSET,
++ offsetof(struct kvm_vcpu, arch.saved_gp));
++
++ BLANK();
++
++ DEFINE(VMM_PT_REGS_B6_OFFSET,
++ offsetof(struct kvm_pt_regs, b6));
++ DEFINE(VMM_PT_REGS_B7_OFFSET,
++ offsetof(struct kvm_pt_regs, b7));
++ DEFINE(VMM_PT_REGS_AR_CSD_OFFSET,
++ offsetof(struct kvm_pt_regs, ar_csd));
++ DEFINE(VMM_PT_REGS_AR_SSD_OFFSET,
++ offsetof(struct kvm_pt_regs, ar_ssd));
++ DEFINE(VMM_PT_REGS_R8_OFFSET,
++ offsetof(struct kvm_pt_regs, r8));
++ DEFINE(VMM_PT_REGS_R9_OFFSET,
++ offsetof(struct kvm_pt_regs, r9));
++ DEFINE(VMM_PT_REGS_R10_OFFSET,
++ offsetof(struct kvm_pt_regs, r10));
++ DEFINE(VMM_PT_REGS_R11_OFFSET,
++ offsetof(struct kvm_pt_regs, r11));
++ DEFINE(VMM_PT_REGS_CR_IPSR_OFFSET,
++ offsetof(struct kvm_pt_regs, cr_ipsr));
++ DEFINE(VMM_PT_REGS_CR_IIP_OFFSET,
++ offsetof(struct kvm_pt_regs, cr_iip));
++ DEFINE(VMM_PT_REGS_CR_IFS_OFFSET,
++ offsetof(struct kvm_pt_regs, cr_ifs));
++ DEFINE(VMM_PT_REGS_AR_UNAT_OFFSET,
++ offsetof(struct kvm_pt_regs, ar_unat));
++ DEFINE(VMM_PT_REGS_AR_PFS_OFFSET,
++ offsetof(struct kvm_pt_regs, ar_pfs));
++ DEFINE(VMM_PT_REGS_AR_RSC_OFFSET,
++ offsetof(struct kvm_pt_regs, ar_rsc));
++ DEFINE(VMM_PT_REGS_AR_RNAT_OFFSET,
++ offsetof(struct kvm_pt_regs, ar_rnat));
++
++ DEFINE(VMM_PT_REGS_AR_BSPSTORE_OFFSET,
++ offsetof(struct kvm_pt_regs, ar_bspstore));
++ DEFINE(VMM_PT_REGS_PR_OFFSET,
++ offsetof(struct kvm_pt_regs, pr));
++ DEFINE(VMM_PT_REGS_B0_OFFSET,
++ offsetof(struct kvm_pt_regs, b0));
++ DEFINE(VMM_PT_REGS_LOADRS_OFFSET,
++ offsetof(struct kvm_pt_regs, loadrs));
++ DEFINE(VMM_PT_REGS_R1_OFFSET,
++ offsetof(struct kvm_pt_regs, r1));
++ DEFINE(VMM_PT_REGS_R12_OFFSET,
++ offsetof(struct kvm_pt_regs, r12));
++ DEFINE(VMM_PT_REGS_R13_OFFSET,
++ offsetof(struct kvm_pt_regs, r13));
++ DEFINE(VMM_PT_REGS_AR_FPSR_OFFSET,
++ offsetof(struct kvm_pt_regs, ar_fpsr));
++ DEFINE(VMM_PT_REGS_R15_OFFSET,
++ offsetof(struct kvm_pt_regs, r15));
++ DEFINE(VMM_PT_REGS_R14_OFFSET,
++ offsetof(struct kvm_pt_regs, r14));
++ DEFINE(VMM_PT_REGS_R2_OFFSET,
++ offsetof(struct kvm_pt_regs, r2));
++ DEFINE(VMM_PT_REGS_R3_OFFSET,
++ offsetof(struct kvm_pt_regs, r3));
++ DEFINE(VMM_PT_REGS_R16_OFFSET,
++ offsetof(struct kvm_pt_regs, r16));
++ DEFINE(VMM_PT_REGS_R17_OFFSET,
++ offsetof(struct kvm_pt_regs, r17));
++ DEFINE(VMM_PT_REGS_R18_OFFSET,
++ offsetof(struct kvm_pt_regs, r18));
++ DEFINE(VMM_PT_REGS_R19_OFFSET,
++ offsetof(struct kvm_pt_regs, r19));
++ DEFINE(VMM_PT_REGS_R20_OFFSET,
++ offsetof(struct kvm_pt_regs, r20));
++ DEFINE(VMM_PT_REGS_R21_OFFSET,
++ offsetof(struct kvm_pt_regs, r21));
++ DEFINE(VMM_PT_REGS_R22_OFFSET,
++ offsetof(struct kvm_pt_regs, r22));
++ DEFINE(VMM_PT_REGS_R23_OFFSET,
++ offsetof(struct kvm_pt_regs, r23));
++ DEFINE(VMM_PT_REGS_R24_OFFSET,
++ offsetof(struct kvm_pt_regs, r24));
++ DEFINE(VMM_PT_REGS_R25_OFFSET,
++ offsetof(struct kvm_pt_regs, r25));
++ DEFINE(VMM_PT_REGS_R26_OFFSET,
++ offsetof(struct kvm_pt_regs, r26));
++ DEFINE(VMM_PT_REGS_R27_OFFSET,
++ offsetof(struct kvm_pt_regs, r27));
++ DEFINE(VMM_PT_REGS_R28_OFFSET,
++ offsetof(struct kvm_pt_regs, r28));
++ DEFINE(VMM_PT_REGS_R29_OFFSET,
++ offsetof(struct kvm_pt_regs, r29));
++ DEFINE(VMM_PT_REGS_R30_OFFSET,
++ offsetof(struct kvm_pt_regs, r30));
++ DEFINE(VMM_PT_REGS_R31_OFFSET,
++ offsetof(struct kvm_pt_regs, r31));
++ DEFINE(VMM_PT_REGS_AR_CCV_OFFSET,
++ offsetof(struct kvm_pt_regs, ar_ccv));
++ DEFINE(VMM_PT_REGS_F6_OFFSET,
++ offsetof(struct kvm_pt_regs, f6));
++ DEFINE(VMM_PT_REGS_F7_OFFSET,
++ offsetof(struct kvm_pt_regs, f7));
++ DEFINE(VMM_PT_REGS_F8_OFFSET,
++ offsetof(struct kvm_pt_regs, f8));
++ DEFINE(VMM_PT_REGS_F9_OFFSET,
++ offsetof(struct kvm_pt_regs, f9));
++ DEFINE(VMM_PT_REGS_F10_OFFSET,
++ offsetof(struct kvm_pt_regs, f10));
++ DEFINE(VMM_PT_REGS_F11_OFFSET,
++ offsetof(struct kvm_pt_regs, f11));
++ DEFINE(VMM_PT_REGS_R4_OFFSET,
++ offsetof(struct kvm_pt_regs, r4));
++ DEFINE(VMM_PT_REGS_R5_OFFSET,
++ offsetof(struct kvm_pt_regs, r5));
++ DEFINE(VMM_PT_REGS_R6_OFFSET,
++ offsetof(struct kvm_pt_regs, r6));
++ DEFINE(VMM_PT_REGS_R7_OFFSET,
++ offsetof(struct kvm_pt_regs, r7));
++ DEFINE(VMM_PT_REGS_EML_UNAT_OFFSET,
++ offsetof(struct kvm_pt_regs, eml_unat));
++ DEFINE(VMM_VCPU_IIPA_OFFSET,
++ offsetof(struct kvm_vcpu, arch.cr_iipa));
++ DEFINE(VMM_VCPU_OPCODE_OFFSET,
++ offsetof(struct kvm_vcpu, arch.opcode));
++ DEFINE(VMM_VCPU_CAUSE_OFFSET, offsetof(struct kvm_vcpu, arch.cause));
++ DEFINE(VMM_VCPU_ISR_OFFSET,
++ offsetof(struct kvm_vcpu, arch.cr_isr));
++ DEFINE(VMM_PT_REGS_R16_SLOT,
++ (((offsetof(struct kvm_pt_regs, r16)
++ - sizeof(struct kvm_pt_regs)) >> 3) & 0x3f));
++ DEFINE(VMM_VCPU_MODE_FLAGS_OFFSET,
++ offsetof(struct kvm_vcpu, arch.mode_flags));
++ DEFINE(VMM_VCPU_GP_OFFSET, offsetof(struct kvm_vcpu, arch.__gp));
++ BLANK();
++
++ DEFINE(VMM_VPD_BASE_OFFSET, offsetof(struct kvm_vcpu, arch.vpd));
++ DEFINE(VMM_VPD_VIFS_OFFSET, offsetof(struct vpd, ifs));
++ DEFINE(VMM_VLSAPIC_INSVC_BASE_OFFSET,
++ offsetof(struct kvm_vcpu, arch.insvc[0]));
++ DEFINE(VMM_VPD_VPTA_OFFSET, offsetof(struct vpd, pta));
++ DEFINE(VMM_VPD_VPSR_OFFSET, offsetof(struct vpd, vpsr));
++
++ DEFINE(VMM_CTX_R4_OFFSET, offsetof(union context, gr[4]));
++ DEFINE(VMM_CTX_R5_OFFSET, offsetof(union context, gr[5]));
++ DEFINE(VMM_CTX_R12_OFFSET, offsetof(union context, gr[12]));
++ DEFINE(VMM_CTX_R13_OFFSET, offsetof(union context, gr[13]));
++ DEFINE(VMM_CTX_KR0_OFFSET, offsetof(union context, ar[0]));
++ DEFINE(VMM_CTX_KR1_OFFSET, offsetof(union context, ar[1]));
++ DEFINE(VMM_CTX_B0_OFFSET, offsetof(union context, br[0]));
++ DEFINE(VMM_CTX_B1_OFFSET, offsetof(union context, br[1]));
++ DEFINE(VMM_CTX_B2_OFFSET, offsetof(union context, br[2]));
++ DEFINE(VMM_CTX_RR0_OFFSET, offsetof(union context, rr[0]));
++ DEFINE(VMM_CTX_RSC_OFFSET, offsetof(union context, ar[16]));
++ DEFINE(VMM_CTX_BSPSTORE_OFFSET, offsetof(union context, ar[18]));
++ DEFINE(VMM_CTX_RNAT_OFFSET, offsetof(union context, ar[19]));
++ DEFINE(VMM_CTX_FCR_OFFSET, offsetof(union context, ar[21]));
++ DEFINE(VMM_CTX_EFLAG_OFFSET, offsetof(union context, ar[24]));
++ DEFINE(VMM_CTX_CFLG_OFFSET, offsetof(union context, ar[27]));
++ DEFINE(VMM_CTX_FSR_OFFSET, offsetof(union context, ar[28]));
++ DEFINE(VMM_CTX_FIR_OFFSET, offsetof(union context, ar[29]));
++ DEFINE(VMM_CTX_FDR_OFFSET, offsetof(union context, ar[30]));
++ DEFINE(VMM_CTX_UNAT_OFFSET, offsetof(union context, ar[36]));
++ DEFINE(VMM_CTX_FPSR_OFFSET, offsetof(union context, ar[40]));
++ DEFINE(VMM_CTX_PFS_OFFSET, offsetof(union context, ar[64]));
++ DEFINE(VMM_CTX_LC_OFFSET, offsetof(union context, ar[65]));
++ DEFINE(VMM_CTX_DCR_OFFSET, offsetof(union context, cr[0]));
++ DEFINE(VMM_CTX_IVA_OFFSET, offsetof(union context, cr[2]));
++ DEFINE(VMM_CTX_PTA_OFFSET, offsetof(union context, cr[8]));
++ DEFINE(VMM_CTX_IBR0_OFFSET, offsetof(union context, ibr[0]));
++ DEFINE(VMM_CTX_DBR0_OFFSET, offsetof(union context, dbr[0]));
++ DEFINE(VMM_CTX_F2_OFFSET, offsetof(union context, fr[2]));
++ DEFINE(VMM_CTX_F3_OFFSET, offsetof(union context, fr[3]));
++ DEFINE(VMM_CTX_F32_OFFSET, offsetof(union context, fr[32]));
++ DEFINE(VMM_CTX_F33_OFFSET, offsetof(union context, fr[33]));
++ DEFINE(VMM_CTX_PKR0_OFFSET, offsetof(union context, pkr[0]));
++ DEFINE(VMM_CTX_PSR_OFFSET, offsetof(union context, psr));
++ BLANK();
+}
-+
-+__setup("nptcg=", set_nptcg);
+diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
+new file mode 100644
+index 0000000..6df0732
+--- /dev/null
++++ b/arch/ia64/kvm/kvm-ia64.c
+@@ -0,0 +1,1806 @@
+
+/*
-+ * Maximum number of simultaneous ptc.g purges in the system can
-+ * be defined by PAL_VM_SUMMARY (in which case we should take
-+ * the smallest value for any cpu in the system) or by the PAL
-+ * override table (in which case we should ignore the value from
-+ * PAL_VM_SUMMARY).
++ * kvm_ia64.c: Basic KVM suppport On Itanium series processors
+ *
-+ * Kernel parameter "nptcg=" overrides maximum number of simultanesous ptc.g
-+ * purges defined in either PAL_VM_SUMMARY or PAL override table. In this case,
-+ * we should ignore the value from either PAL_VM_SUMMARY or PAL override table.
+ *
-+ * Complicating the logic here is the fact that num_possible_cpus()
-+ * isn't fully setup until we start bringing cpus online.
++ * Copyright (C) 2007, Intel Corporation.
++ * Xiantao Zhang (xiantao.zhang at intel.com)
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You 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.
++ *
+ */
-+void
-+setup_ptcg_sem(int max_purges, int nptcg_from)
++
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/percpu.h>
++#include <linux/gfp.h>
++#include <linux/fs.h>
++#include <linux/smp.h>
++#include <linux/kvm_host.h>
++#include <linux/kvm.h>
++#include <linux/bitops.h>
++#include <linux/hrtimer.h>
++#include <linux/uaccess.h>
++
++#include <asm/pgtable.h>
++#include <asm/gcc_intrin.h>
++#include <asm/pal.h>
++#include <asm/cacheflush.h>
++#include <asm/div64.h>
++#include <asm/tlb.h>
++
++#include "misc.h"
++#include "vti.h"
++#include "iodev.h"
++#include "ioapic.h"
++#include "lapic.h"
++
++static unsigned long kvm_vmm_base;
++static unsigned long kvm_vsa_base;
++static unsigned long kvm_vm_buffer;
++static unsigned long kvm_vm_buffer_size;
++unsigned long kvm_vmm_gp;
++
++static long vp_env_info;
++
++static struct kvm_vmm_info *kvm_vmm_info;
++
++static DEFINE_PER_CPU(struct kvm_vcpu *, last_vcpu);
++
++struct kvm_stats_debugfs_item debugfs_entries[] = {
++ { NULL }
++};
++
++
++struct fdesc{
++ unsigned long ip;
++ unsigned long gp;
++};
++
++static void kvm_flush_icache(unsigned long start, unsigned long len)
+{
-+ static int kp_override;
-+ static int palo_override;
-+ static int firstcpu = 1;
++ int l;
+
-+ if (toolatetochangeptcgsem) {
-+ BUG_ON(max_purges < nptcg);
-+ return;
-+ }
++ for (l = 0; l < (len + 32); l += 32)
++ ia64_fc(start + l);
+
-+ if (nptcg_from == NPTCG_FROM_KERNEL_PARAMETER) {
-+ kp_override = 1;
-+ nptcg = max_purges;
-+ goto resetsema;
-+ }
-+ if (kp_override) {
-+ need_ptcg_sem = num_possible_cpus() > nptcg;
-+ return;
-+ }
++ ia64_sync_i();
++ ia64_srlz_i();
++}
+
-+ if (nptcg_from == NPTCG_FROM_PALO) {
-+ palo_override = 1;
++static void kvm_flush_tlb_all(void)
++{
++ unsigned long i, j, count0, count1, stride0, stride1, addr;
++ long flags;
+
-+ /* In PALO max_purges == 0 really means it! */
-+ if (max_purges == 0)
-+ panic("Whoa! Platform does not support global TLB purges.\n");
-+ nptcg = max_purges;
-+ if (nptcg == PALO_MAX_TLB_PURGES) {
-+ need_ptcg_sem = 0;
-+ return;
++ addr = local_cpu_data->ptce_base;
++ count0 = local_cpu_data->ptce_count[0];
++ count1 = local_cpu_data->ptce_count[1];
++ stride0 = local_cpu_data->ptce_stride[0];
++ stride1 = local_cpu_data->ptce_stride[1];
++
++ local_irq_save(flags);
++ for (i = 0; i < count0; ++i) {
++ for (j = 0; j < count1; ++j) {
++ ia64_ptce(addr);
++ addr += stride1;
+ }
-+ goto resetsema;
++ addr += stride0;
+ }
-+ if (palo_override) {
-+ if (nptcg != PALO_MAX_TLB_PURGES)
-+ need_ptcg_sem = (num_possible_cpus() > nptcg);
++ local_irq_restore(flags);
++ ia64_srlz_i(); /* srlz.i implies srlz.d */
++}
++
++long ia64_pal_vp_create(u64 *vpd, u64 *host_iva, u64 *opt_handler)
++{
++ struct ia64_pal_retval iprv;
++
++ PAL_CALL_STK(iprv, PAL_VP_CREATE, (u64)vpd, (u64)host_iva,
++ (u64)opt_handler);
++
++ return iprv.status;
++}
++
++static DEFINE_SPINLOCK(vp_lock);
++
++void kvm_arch_hardware_enable(void *garbage)
++{
++ long status;
++ long tmp_base;
++ unsigned long pte;
++ unsigned long saved_psr;
++ int slot;
++
++ pte = pte_val(mk_pte_phys(__pa(kvm_vmm_base),
++ PAGE_KERNEL));
++ local_irq_save(saved_psr);
++ slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
++ if (slot < 0)
+ return;
-+ }
++ local_irq_restore(saved_psr);
+
-+ /* In PAL_VM_SUMMARY max_purges == 0 actually means 1 */
-+ if (max_purges == 0) max_purges = 1;
++ spin_lock(&vp_lock);
++ status = ia64_pal_vp_init_env(kvm_vsa_base ?
++ VP_INIT_ENV : VP_INIT_ENV_INITALIZE,
++ __pa(kvm_vm_buffer), KVM_VM_BUFFER_BASE, &tmp_base);
++ if (status != 0) {
++ printk(KERN_WARNING"kvm: Failed to Enable VT Support!!!!\n");
++ return ;
++ }
+
-+ if (firstcpu) {
-+ nptcg = max_purges;
-+ firstcpu = 0;
++ if (!kvm_vsa_base) {
++ kvm_vsa_base = tmp_base;
++ printk(KERN_INFO"kvm: kvm_vsa_base:0x%lx\n", kvm_vsa_base);
+ }
-+ if (max_purges < nptcg)
-+ nptcg = max_purges;
-+ if (nptcg == PAL_MAX_PURGES) {
-+ need_ptcg_sem = 0;
++ spin_unlock(&vp_lock);
++ ia64_ptr_entry(0x3, slot);
++}
++
++void kvm_arch_hardware_disable(void *garbage)
++{
++
++ long status;
++ int slot;
++ unsigned long pte;
++ unsigned long saved_psr;
++ unsigned long host_iva = ia64_getreg(_IA64_REG_CR_IVA);
++
++ pte = pte_val(mk_pte_phys(__pa(kvm_vmm_base),
++ PAGE_KERNEL));
++
++ local_irq_save(saved_psr);
++ slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
++ if (slot < 0)
+ return;
-+ } else
-+ need_ptcg_sem = (num_possible_cpus() > nptcg);
++ local_irq_restore(saved_psr);
+
-+resetsema:
-+ spinaphore_init(&ptcg_sem, max_purges);
++ status = ia64_pal_vp_exit_env(host_iva);
++ if (status)
++ printk(KERN_DEBUG"kvm: Failed to disable VT support! :%ld\n",
++ status);
++ ia64_ptr_entry(0x3, slot);
+}
+
- void
- ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start,
- unsigned long end, unsigned long nbits)
- {
-- static DEFINE_SPINLOCK(ptcg_lock);
--
- struct mm_struct *active_mm = current->active_mm;
-
-+ toolatetochangeptcgsem = 1;
++void kvm_arch_check_processor_compat(void *rtn)
++{
++ *(int *)rtn = 0;
++}
+
- if (mm != active_mm) {
- /* Restore region IDs for mm */
- if (mm && active_mm) {
-@@ -102,19 +238,20 @@ ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start,
- }
- }
-
-- /* HW requires global serialization of ptc.ga. */
-- spin_lock(&ptcg_lock);
-- {
-- do {
-- /*
-- * Flush ALAT entries also.
-- */
-- ia64_ptcga(start, (nbits<<2));
-- ia64_srlz_i();
-- start += (1UL << nbits);
-- } while (start < end);
-- }
-- spin_unlock(&ptcg_lock);
-+ if (need_ptcg_sem)
-+ down_spin(&ptcg_sem);
++int kvm_dev_ioctl_check_extension(long ext)
++{
+
-+ do {
-+ /*
-+ * Flush ALAT entries also.
-+ */
-+ ia64_ptcga(start, (nbits << 2));
-+ ia64_srlz_i();
-+ start += (1UL << nbits);
-+ } while (start < end);
++ int r;
+
-+ if (need_ptcg_sem)
-+ up_spin(&ptcg_sem);
-
- if (mm != active_mm) {
- activate_context(active_mm);
-@@ -190,6 +327,9 @@ ia64_tlb_init (void)
- ia64_ptce_info_t uninitialized_var(ptce_info); /* GCC be quiet */
- unsigned long tr_pgbits;
- long status;
-+ pal_vm_info_1_u_t vm_info_1;
-+ pal_vm_info_2_u_t vm_info_2;
-+ int cpu = smp_processor_id();
-
- if ((status = ia64_pal_vm_page_size(&tr_pgbits, &purge.mask)) != 0) {
- printk(KERN_ERR "PAL_VM_PAGE_SIZE failed with status=%ld; "
-@@ -206,4 +346,191 @@ ia64_tlb_init (void)
- local_cpu_data->ptce_stride[1] = ptce_info.stride[1];
-
- local_flush_tlb_all(); /* nuke left overs from bootstrapping... */
-+ status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2);
++ switch (ext) {
++ case KVM_CAP_IRQCHIP:
++ case KVM_CAP_USER_MEMORY:
+
-+ if (status) {
-+ printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status);
-+ per_cpu(ia64_tr_num, cpu) = 8;
-+ return;
++ r = 1;
++ break;
++ default:
++ r = 0;
+ }
-+ per_cpu(ia64_tr_num, cpu) = vm_info_1.pal_vm_info_1_s.max_itr_entry+1;
-+ if (per_cpu(ia64_tr_num, cpu) >
-+ (vm_info_1.pal_vm_info_1_s.max_dtr_entry+1))
-+ per_cpu(ia64_tr_num, cpu) =
-+ vm_info_1.pal_vm_info_1_s.max_dtr_entry+1;
-+ if (per_cpu(ia64_tr_num, cpu) > IA64_TR_ALLOC_MAX) {
-+ per_cpu(ia64_tr_num, cpu) = IA64_TR_ALLOC_MAX;
-+ printk(KERN_DEBUG "TR register number exceeds IA64_TR_ALLOC_MAX!"
-+ "IA64_TR_ALLOC_MAX should be extended\n");
++ return r;
++
++}
++
++static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu,
++ gpa_t addr)
++{
++ struct kvm_io_device *dev;
++
++ dev = kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr);
++
++ return dev;
++}
++
++static int handle_vm_error(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
++{
++ kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
++ kvm_run->hw.hardware_exit_reason = 1;
++ return 0;
++}
++
++static int handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
++{
++ struct kvm_mmio_req *p;
++ struct kvm_io_device *mmio_dev;
++
++ p = kvm_get_vcpu_ioreq(vcpu);
++
++ if ((p->addr & PAGE_MASK) == IOAPIC_DEFAULT_BASE_ADDRESS)
++ goto mmio;
++ vcpu->mmio_needed = 1;
++ vcpu->mmio_phys_addr = kvm_run->mmio.phys_addr = p->addr;
++ vcpu->mmio_size = kvm_run->mmio.len = p->size;
++ vcpu->mmio_is_write = kvm_run->mmio.is_write = !p->dir;
++
++ if (vcpu->mmio_is_write)
++ memcpy(vcpu->mmio_data, &p->data, p->size);
++ memcpy(kvm_run->mmio.data, &p->data, p->size);
++ kvm_run->exit_reason = KVM_EXIT_MMIO;
++ return 0;
++mmio:
++ mmio_dev = vcpu_find_mmio_dev(vcpu, p->addr);
++ if (mmio_dev) {
++ if (!p->dir)
++ kvm_iodevice_write(mmio_dev, p->addr, p->size,
++ &p->data);
++ else
++ kvm_iodevice_read(mmio_dev, p->addr, p->size,
++ &p->data);
++
++ } else
++ printk(KERN_ERR"kvm: No iodevice found! addr:%lx\n", p->addr);
++ p->state = STATE_IORESP_READY;
++
++ return 1;
++}
++
++static int handle_pal_call(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
++{
++ struct exit_ctl_data *p;
++
++ p = kvm_get_exit_data(vcpu);
++
++ if (p->exit_reason == EXIT_REASON_PAL_CALL)
++ return kvm_pal_emul(vcpu, kvm_run);
++ else {
++ kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
++ kvm_run->hw.hardware_exit_reason = 2;
++ return 0;
++ }
++}
++
++static int handle_sal_call(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
++{
++ struct exit_ctl_data *p;
++
++ p = kvm_get_exit_data(vcpu);
++
++ if (p->exit_reason == EXIT_REASON_SAL_CALL) {
++ kvm_sal_emul(vcpu);
++ return 1;
++ } else {
++ kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
++ kvm_run->hw.hardware_exit_reason = 3;
++ return 0;
+ }
++
+}
+
+/*
-+ * is_tr_overlap
-+ *
-+ * Check overlap with inserted TRs.
++ * offset: address offset to IPI space.
++ * value: deliver value.
+ */
-+static int is_tr_overlap(struct ia64_tr_entry *p, u64 va, u64 log_size)
++static void vcpu_deliver_ipi(struct kvm_vcpu *vcpu, uint64_t dm,
++ uint64_t vector)
+{
-+ u64 tr_log_size;
-+ u64 tr_end;
-+ u64 va_rr = ia64_get_rr(va);
-+ u64 va_rid = RR_TO_RID(va_rr);
-+ u64 va_end = va + (1<<log_size) - 1;
++ switch (dm) {
++ case SAPIC_FIXED:
++ kvm_apic_set_irq(vcpu, vector, 0);
++ break;
++ case SAPIC_NMI:
++ kvm_apic_set_irq(vcpu, 2, 0);
++ break;
++ case SAPIC_EXTINT:
++ kvm_apic_set_irq(vcpu, 0, 0);
++ break;
++ case SAPIC_INIT:
++ case SAPIC_PMI:
++ default:
++ printk(KERN_ERR"kvm: Unimplemented Deliver reserved IPI!\n");
++ break;
++ }
++}
+
-+ if (va_rid != RR_TO_RID(p->rr))
-+ return 0;
-+ tr_log_size = (p->itir & 0xff) >> 2;
-+ tr_end = p->ifa + (1<<tr_log_size) - 1;
++static struct kvm_vcpu *lid_to_vcpu(struct kvm *kvm, unsigned long id,
++ unsigned long eid)
++{
++ union ia64_lid lid;
++ int i;
+
-+ if (va > tr_end || p->ifa > va_end)
++ for (i = 0; i < KVM_MAX_VCPUS; i++) {
++ if (kvm->vcpus[i]) {
++ lid.val = VCPU_LID(kvm->vcpus[i]);
++ if (lid.id == id && lid.eid == eid)
++ return kvm->vcpus[i];
++ }
++ }
++
++ return NULL;
++}
++
++static int handle_ipi(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
++{
++ struct exit_ctl_data *p = kvm_get_exit_data(vcpu);
++ struct kvm_vcpu *target_vcpu;
++ struct kvm_pt_regs *regs;
++ union ia64_ipi_a addr = p->u.ipi_data.addr;
++ union ia64_ipi_d data = p->u.ipi_data.data;
++
++ target_vcpu = lid_to_vcpu(vcpu->kvm, addr.id, addr.eid);
++ if (!target_vcpu)
++ return handle_vm_error(vcpu, kvm_run);
++
++ if (!target_vcpu->arch.launched) {
++ regs = vcpu_regs(target_vcpu);
++
++ regs->cr_iip = vcpu->kvm->arch.rdv_sal_data.boot_ip;
++ regs->r1 = vcpu->kvm->arch.rdv_sal_data.boot_gp;
++
++ target_vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
++ if (waitqueue_active(&target_vcpu->wq))
++ wake_up_interruptible(&target_vcpu->wq);
++ } else {
++ vcpu_deliver_ipi(target_vcpu, data.dm, data.vector);
++ if (target_vcpu != vcpu)
++ kvm_vcpu_kick(target_vcpu);
++ }
++
++ return 1;
++}
++
++struct call_data {
++ struct kvm_ptc_g ptc_g_data;
++ struct kvm_vcpu *vcpu;
++};
++
++static void vcpu_global_purge(void *info)
++{
++ struct call_data *p = (struct call_data *)info;
++ struct kvm_vcpu *vcpu = p->vcpu;
++
++ if (test_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests))
++ return;
++
++ set_bit(KVM_REQ_PTC_G, &vcpu->requests);
++ if (vcpu->arch.ptc_g_count < MAX_PTC_G_NUM) {
++ vcpu->arch.ptc_g_data[vcpu->arch.ptc_g_count++] =
++ p->ptc_g_data;
++ } else {
++ clear_bit(KVM_REQ_PTC_G, &vcpu->requests);
++ vcpu->arch.ptc_g_count = 0;
++ set_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests);
++ }
++}
++
++static int handle_global_purge(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
++{
++ struct exit_ctl_data *p = kvm_get_exit_data(vcpu);
++ struct kvm *kvm = vcpu->kvm;
++ struct call_data call_data;
++ int i;
++ call_data.ptc_g_data = p->u.ptc_g_data;
++
++ for (i = 0; i < KVM_MAX_VCPUS; i++) {
++ if (!kvm->vcpus[i] || kvm->vcpus[i]->arch.mp_state ==
++ KVM_MP_STATE_UNINITIALIZED ||
++ vcpu == kvm->vcpus[i])
++ continue;
++
++ if (waitqueue_active(&kvm->vcpus[i]->wq))
++ wake_up_interruptible(&kvm->vcpus[i]->wq);
++
++ if (kvm->vcpus[i]->cpu != -1) {
++ call_data.vcpu = kvm->vcpus[i];
++ smp_call_function_single(kvm->vcpus[i]->cpu,
++ vcpu_global_purge, &call_data, 0, 1);
++ } else
++ printk(KERN_WARNING"kvm: Uninit vcpu received ipi!\n");
++
++ }
++ return 1;
++}
++
++static int handle_switch_rr6(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
++{
++ return 1;
++}
++
++int kvm_emulate_halt(struct kvm_vcpu *vcpu)
++{
++
++ ktime_t kt;
++ long itc_diff;
++ unsigned long vcpu_now_itc;
++
++ unsigned long expires;
++ struct hrtimer *p_ht = &vcpu->arch.hlt_timer;
++ unsigned long cyc_per_usec = local_cpu_data->cyc_per_usec;
++ struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
++
++ vcpu_now_itc = ia64_getreg(_IA64_REG_AR_ITC) + vcpu->arch.itc_offset;
++
++ if (time_after(vcpu_now_itc, vpd->itm)) {
++ vcpu->arch.timer_check = 1;
++ return 1;
++ }
++ itc_diff = vpd->itm - vcpu_now_itc;
++ if (itc_diff < 0)
++ itc_diff = -itc_diff;
++
++ expires = div64_64(itc_diff, cyc_per_usec);
++ kt = ktime_set(0, 1000 * expires);
++ vcpu->arch.ht_active = 1;
++ hrtimer_start(p_ht, kt, HRTIMER_MODE_ABS);
++
++ if (irqchip_in_kernel(vcpu->kvm)) {
++ vcpu->arch.mp_state = KVM_MP_STATE_HALTED;
++ kvm_vcpu_block(vcpu);
++ hrtimer_cancel(p_ht);
++ vcpu->arch.ht_active = 0;
++
++ if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
++ return -EINTR;
++ return 1;
++ } else {
++ printk(KERN_ERR"kvm: Unsupported userspace halt!");
+ return 0;
++ }
++}
++
++static int handle_vm_shutdown(struct kvm_vcpu *vcpu,
++ struct kvm_run *kvm_run)
++{
++ kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
++ return 0;
++}
++
++static int handle_external_interrupt(struct kvm_vcpu *vcpu,
++ struct kvm_run *kvm_run)
++{
+ return 1;
++}
++
++static int (*kvm_vti_exit_handlers[])(struct kvm_vcpu *vcpu,
++ struct kvm_run *kvm_run) = {
++ [EXIT_REASON_VM_PANIC] = handle_vm_error,
++ [EXIT_REASON_MMIO_INSTRUCTION] = handle_mmio,
++ [EXIT_REASON_PAL_CALL] = handle_pal_call,
++ [EXIT_REASON_SAL_CALL] = handle_sal_call,
++ [EXIT_REASON_SWITCH_RR6] = handle_switch_rr6,
++ [EXIT_REASON_VM_DESTROY] = handle_vm_shutdown,
++ [EXIT_REASON_EXTERNAL_INTERRUPT] = handle_external_interrupt,
++ [EXIT_REASON_IPI] = handle_ipi,
++ [EXIT_REASON_PTC_G] = handle_global_purge,
++
++};
++
++static const int kvm_vti_max_exit_handlers =
++ sizeof(kvm_vti_exit_handlers)/sizeof(*kvm_vti_exit_handlers);
++
++static void kvm_prepare_guest_switch(struct kvm_vcpu *vcpu)
++{
++}
++
++static uint32_t kvm_get_exit_reason(struct kvm_vcpu *vcpu)
++{
++ struct exit_ctl_data *p_exit_data;
+
++ p_exit_data = kvm_get_exit_data(vcpu);
++ return p_exit_data->exit_reason;
+}
+
+/*
-+ * ia64_insert_tr in virtual mode. Allocate a TR slot
++ * The guest has exited. See if we can fix it or if we need userspace
++ * assistance.
++ */
++static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
++{
++ u32 exit_reason = kvm_get_exit_reason(vcpu);
++ vcpu->arch.last_exit = exit_reason;
++
++ if (exit_reason < kvm_vti_max_exit_handlers
++ && kvm_vti_exit_handlers[exit_reason])
++ return kvm_vti_exit_handlers[exit_reason](vcpu, kvm_run);
++ else {
++ kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
++ kvm_run->hw.hardware_exit_reason = exit_reason;
++ }
++ return 0;
++}
++
++static inline void vti_set_rr6(unsigned long rr6)
++{
++ ia64_set_rr(RR6, rr6);
++ ia64_srlz_i();
++}
++
++static int kvm_insert_vmm_mapping(struct kvm_vcpu *vcpu)
++{
++ unsigned long pte;
++ struct kvm *kvm = vcpu->kvm;
++ int r;
++
++ /*Insert a pair of tr to map vmm*/
++ pte = pte_val(mk_pte_phys(__pa(kvm_vmm_base), PAGE_KERNEL));
++ r = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
++ if (r < 0)
++ goto out;
++ vcpu->arch.vmm_tr_slot = r;
++ /*Insert a pairt of tr to map data of vm*/
++ pte = pte_val(mk_pte_phys(__pa(kvm->arch.vm_base), PAGE_KERNEL));
++ r = ia64_itr_entry(0x3, KVM_VM_DATA_BASE,
++ pte, KVM_VM_DATA_SHIFT);
++ if (r < 0)
++ goto out;
++ vcpu->arch.vm_tr_slot = r;
++ r = 0;
++out:
++ return r;
++
++}
++
++static void kvm_purge_vmm_mapping(struct kvm_vcpu *vcpu)
++{
++
++ ia64_ptr_entry(0x3, vcpu->arch.vmm_tr_slot);
++ ia64_ptr_entry(0x3, vcpu->arch.vm_tr_slot);
++
++}
++
++static int kvm_vcpu_pre_transition(struct kvm_vcpu *vcpu)
++{
++ int cpu = smp_processor_id();
++
++ if (vcpu->arch.last_run_cpu != cpu ||
++ per_cpu(last_vcpu, cpu) != vcpu) {
++ per_cpu(last_vcpu, cpu) = vcpu;
++ vcpu->arch.last_run_cpu = cpu;
++ kvm_flush_tlb_all();
++ }
++
++ vcpu->arch.host_rr6 = ia64_get_rr(RR6);
++ vti_set_rr6(vcpu->arch.vmm_rr);
++ return kvm_insert_vmm_mapping(vcpu);
++}
++static void kvm_vcpu_post_transition(struct kvm_vcpu *vcpu)
++{
++ kvm_purge_vmm_mapping(vcpu);
++ vti_set_rr6(vcpu->arch.host_rr6);
++}
++
++static int vti_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
++{
++ union context *host_ctx, *guest_ctx;
++ int r;
++
++ /*Get host and guest context with guest address space.*/
++ host_ctx = kvm_get_host_context(vcpu);
++ guest_ctx = kvm_get_guest_context(vcpu);
++
++ r = kvm_vcpu_pre_transition(vcpu);
++ if (r < 0)
++ goto out;
++ kvm_vmm_info->tramp_entry(host_ctx, guest_ctx);
++ kvm_vcpu_post_transition(vcpu);
++ r = 0;
++out:
++ return r;
++}
++
++static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
++{
++ int r;
++
++again:
++ preempt_disable();
++
++ kvm_prepare_guest_switch(vcpu);
++ local_irq_disable();
++
++ if (signal_pending(current)) {
++ local_irq_enable();
++ preempt_enable();
++ r = -EINTR;
++ kvm_run->exit_reason = KVM_EXIT_INTR;
++ goto out;
++ }
++
++ vcpu->guest_mode = 1;
++ kvm_guest_enter();
++
++ r = vti_vcpu_run(vcpu, kvm_run);
++ if (r < 0) {
++ local_irq_enable();
++ preempt_enable();
++ kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
++ goto out;
++ }
++
++ vcpu->arch.launched = 1;
++ vcpu->guest_mode = 0;
++ local_irq_enable();
++
++ /*
++ * We must have an instruction between local_irq_enable() and
++ * kvm_guest_exit(), so the timer interrupt isn't delayed by
++ * the interrupt shadow. The stat.exits increment will do nicely.
++ * But we need to prevent reordering, hence this barrier():
++ */
++ barrier();
++
++ kvm_guest_exit();
++
++ preempt_enable();
++
++ r = kvm_handle_exit(kvm_run, vcpu);
++
++ if (r > 0) {
++ if (!need_resched())
++ goto again;
++ }
++
++out:
++ if (r > 0) {
++ kvm_resched(vcpu);
++ goto again;
++ }
++
++ return r;
++}
++
++static void kvm_set_mmio_data(struct kvm_vcpu *vcpu)
++{
++ struct kvm_mmio_req *p = kvm_get_vcpu_ioreq(vcpu);
++
++ if (!vcpu->mmio_is_write)
++ memcpy(&p->data, vcpu->mmio_data, 8);
++ p->state = STATE_IORESP_READY;
++}
++
++int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
++{
++ int r;
++ sigset_t sigsaved;
++
++ vcpu_load(vcpu);
++
++ if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)) {
++ kvm_vcpu_block(vcpu);
++ vcpu_put(vcpu);
++ return -EAGAIN;
++ }
++
++ if (vcpu->sigset_active)
++ sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
++
++ if (vcpu->mmio_needed) {
++ memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8);
++ kvm_set_mmio_data(vcpu);
++ vcpu->mmio_read_completed = 1;
++ vcpu->mmio_needed = 0;
++ }
++ r = __vcpu_run(vcpu, kvm_run);
++
++ if (vcpu->sigset_active)
++ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
++
++ vcpu_put(vcpu);
++ return r;
++}
++
++/*
++ * Allocate 16M memory for every vm to hold its specific data.
++ * Its memory map is defined in kvm_host.h.
++ */
++static struct kvm *kvm_alloc_kvm(void)
++{
++
++ struct kvm *kvm;
++ uint64_t vm_base;
++
++ vm_base = __get_free_pages(GFP_KERNEL, get_order(KVM_VM_DATA_SIZE));
++
++ if (!vm_base)
++ return ERR_PTR(-ENOMEM);
++ printk(KERN_DEBUG"kvm: VM data's base Address:0x%lx\n", vm_base);
++
++ /* Zero all pages before use! */
++ memset((void *)vm_base, 0, KVM_VM_DATA_SIZE);
++
++ kvm = (struct kvm *)(vm_base + KVM_VM_OFS);
++ kvm->arch.vm_base = vm_base;
++
++ return kvm;
++}
++
++struct kvm_io_range {
++ unsigned long start;
++ unsigned long size;
++ unsigned long type;
++};
++
++static const struct kvm_io_range io_ranges[] = {
++ {VGA_IO_START, VGA_IO_SIZE, GPFN_FRAME_BUFFER},
++ {MMIO_START, MMIO_SIZE, GPFN_LOW_MMIO},
++ {LEGACY_IO_START, LEGACY_IO_SIZE, GPFN_LEGACY_IO},
++ {IO_SAPIC_START, IO_SAPIC_SIZE, GPFN_IOSAPIC},
++ {PIB_START, PIB_SIZE, GPFN_PIB},
++};
++
++static void kvm_build_io_pmt(struct kvm *kvm)
++{
++ unsigned long i, j;
++
++ /* Mark I/O ranges */
++ for (i = 0; i < (sizeof(io_ranges) / sizeof(struct kvm_io_range));
++ i++) {
++ for (j = io_ranges[i].start;
++ j < io_ranges[i].start + io_ranges[i].size;
++ j += PAGE_SIZE)
++ kvm_set_pmt_entry(kvm, j >> PAGE_SHIFT,
++ io_ranges[i].type, 0);
++ }
++
++}
++
++/*Use unused rids to virtualize guest rid.*/
++#define GUEST_PHYSICAL_RR0 0x1739
++#define GUEST_PHYSICAL_RR4 0x2739
++#define VMM_INIT_RR 0x1660
++
++static void kvm_init_vm(struct kvm *kvm)
++{
++ long vm_base;
++
++ BUG_ON(!kvm);
++
++ kvm->arch.metaphysical_rr0 = GUEST_PHYSICAL_RR0;
++ kvm->arch.metaphysical_rr4 = GUEST_PHYSICAL_RR4;
++ kvm->arch.vmm_init_rr = VMM_INIT_RR;
++
++ vm_base = kvm->arch.vm_base;
++ if (vm_base) {
++ kvm->arch.vhpt_base = vm_base + KVM_VHPT_OFS;
++ kvm->arch.vtlb_base = vm_base + KVM_VTLB_OFS;
++ kvm->arch.vpd_base = vm_base + KVM_VPD_OFS;
++ }
++
++ /*
++ *Fill P2M entries for MMIO/IO ranges
++ */
++ kvm_build_io_pmt(kvm);
++
++}
++
++struct kvm *kvm_arch_create_vm(void)
++{
++ struct kvm *kvm = kvm_alloc_kvm();
++
++ if (IS_ERR(kvm))
++ return ERR_PTR(-ENOMEM);
++ kvm_init_vm(kvm);
++
++ return kvm;
++
++}
++
++static int kvm_vm_ioctl_get_irqchip(struct kvm *kvm,
++ struct kvm_irqchip *chip)
++{
++ int r;
++
++ r = 0;
++ switch (chip->chip_id) {
++ case KVM_IRQCHIP_IOAPIC:
++ memcpy(&chip->chip.ioapic, ioapic_irqchip(kvm),
++ sizeof(struct kvm_ioapic_state));
++ break;
++ default:
++ r = -EINVAL;
++ break;
++ }
++ return r;
++}
++
++static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, struct kvm_irqchip *chip)
++{
++ int r;
++
++ r = 0;
++ switch (chip->chip_id) {
++ case KVM_IRQCHIP_IOAPIC:
++ memcpy(ioapic_irqchip(kvm),
++ &chip->chip.ioapic,
++ sizeof(struct kvm_ioapic_state));
++ break;
++ default:
++ r = -EINVAL;
++ break;
++ }
++ return r;
++}
++
++#define RESTORE_REGS(_x) vcpu->arch._x = regs->_x
++
++int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
++{
++ int i;
++ struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
++ int r;
++
++ vcpu_load(vcpu);
++
++ for (i = 0; i < 16; i++) {
++ vpd->vgr[i] = regs->vpd.vgr[i];
++ vpd->vbgr[i] = regs->vpd.vbgr[i];
++ }
++ for (i = 0; i < 128; i++)
++ vpd->vcr[i] = regs->vpd.vcr[i];
++ vpd->vhpi = regs->vpd.vhpi;
++ vpd->vnat = regs->vpd.vnat;
++ vpd->vbnat = regs->vpd.vbnat;
++ vpd->vpsr = regs->vpd.vpsr;
++
++ vpd->vpr = regs->vpd.vpr;
++
++ r = -EFAULT;
++ r = copy_from_user(&vcpu->arch.guest, regs->saved_guest,
++ sizeof(union context));
++ if (r)
++ goto out;
++ r = copy_from_user(vcpu + 1, regs->saved_stack +
++ sizeof(struct kvm_vcpu),
++ IA64_STK_OFFSET - sizeof(struct kvm_vcpu));
++ if (r)
++ goto out;
++ vcpu->arch.exit_data =
++ ((struct kvm_vcpu *)(regs->saved_stack))->arch.exit_data;
++
++ RESTORE_REGS(mp_state);
++ RESTORE_REGS(vmm_rr);
++ memcpy(vcpu->arch.itrs, regs->itrs, sizeof(struct thash_data) * NITRS);
++ memcpy(vcpu->arch.dtrs, regs->dtrs, sizeof(struct thash_data) * NDTRS);
++ RESTORE_REGS(itr_regions);
++ RESTORE_REGS(dtr_regions);
++ RESTORE_REGS(tc_regions);
++ RESTORE_REGS(irq_check);
++ RESTORE_REGS(itc_check);
++ RESTORE_REGS(timer_check);
++ RESTORE_REGS(timer_pending);
++ RESTORE_REGS(last_itc);
++ for (i = 0; i < 8; i++) {
++ vcpu->arch.vrr[i] = regs->vrr[i];
++ vcpu->arch.ibr[i] = regs->ibr[i];
++ vcpu->arch.dbr[i] = regs->dbr[i];
++ }
++ for (i = 0; i < 4; i++)
++ vcpu->arch.insvc[i] = regs->insvc[i];
++ RESTORE_REGS(xtp);
++ RESTORE_REGS(metaphysical_rr0);
++ RESTORE_REGS(metaphysical_rr4);
++ RESTORE_REGS(metaphysical_saved_rr0);
++ RESTORE_REGS(metaphysical_saved_rr4);
++ RESTORE_REGS(fp_psr);
++ RESTORE_REGS(saved_gp);
++
++ vcpu->arch.irq_new_pending = 1;
++ vcpu->arch.itc_offset = regs->saved_itc - ia64_getreg(_IA64_REG_AR_ITC);
++ set_bit(KVM_REQ_RESUME, &vcpu->requests);
++
++ vcpu_put(vcpu);
++ r = 0;
++out:
++ return r;
++}
++
++long kvm_arch_vm_ioctl(struct file *filp,
++ unsigned int ioctl, unsigned long arg)
++{
++ struct kvm *kvm = filp->private_data;
++ void __user *argp = (void __user *)arg;
++ int r = -EINVAL;
++
++ switch (ioctl) {
++ case KVM_SET_MEMORY_REGION: {
++ struct kvm_memory_region kvm_mem;
++ struct kvm_userspace_memory_region kvm_userspace_mem;
++
++ r = -EFAULT;
++ if (copy_from_user(&kvm_mem, argp, sizeof kvm_mem))
++ goto out;
++ kvm_userspace_mem.slot = kvm_mem.slot;
++ kvm_userspace_mem.flags = kvm_mem.flags;
++ kvm_userspace_mem.guest_phys_addr =
++ kvm_mem.guest_phys_addr;
++ kvm_userspace_mem.memory_size = kvm_mem.memory_size;
++ r = kvm_vm_ioctl_set_memory_region(kvm,
++ &kvm_userspace_mem, 0);
++ if (r)
++ goto out;
++ break;
++ }
++ case KVM_CREATE_IRQCHIP:
++ r = -EFAULT;
++ r = kvm_ioapic_init(kvm);
++ if (r)
++ goto out;
++ break;
++ case KVM_IRQ_LINE: {
++ struct kvm_irq_level irq_event;
++
++ r = -EFAULT;
++ if (copy_from_user(&irq_event, argp, sizeof irq_event))
++ goto out;
++ if (irqchip_in_kernel(kvm)) {
++ mutex_lock(&kvm->lock);
++ kvm_ioapic_set_irq(kvm->arch.vioapic,
++ irq_event.irq,
++ irq_event.level);
++ mutex_unlock(&kvm->lock);
++ r = 0;
++ }
++ break;
++ }
++ case KVM_GET_IRQCHIP: {
++ /* 0: PIC master, 1: PIC slave, 2: IOAPIC */
++ struct kvm_irqchip chip;
++
++ r = -EFAULT;
++ if (copy_from_user(&chip, argp, sizeof chip))
++ goto out;
++ r = -ENXIO;
++ if (!irqchip_in_kernel(kvm))
++ goto out;
++ r = kvm_vm_ioctl_get_irqchip(kvm, &chip);
++ if (r)
++ goto out;
++ r = -EFAULT;
++ if (copy_to_user(argp, &chip, sizeof chip))
++ goto out;
++ r = 0;
++ break;
++ }
++ case KVM_SET_IRQCHIP: {
++ /* 0: PIC master, 1: PIC slave, 2: IOAPIC */
++ struct kvm_irqchip chip;
++
++ r = -EFAULT;
++ if (copy_from_user(&chip, argp, sizeof chip))
++ goto out;
++ r = -ENXIO;
++ if (!irqchip_in_kernel(kvm))
++ goto out;
++ r = kvm_vm_ioctl_set_irqchip(kvm, &chip);
++ if (r)
++ goto out;
++ r = 0;
++ break;
++ }
++ default:
++ ;
++ }
++out:
++ return r;
++}
++
++int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
++ struct kvm_sregs *sregs)
++{
++ return -EINVAL;
++}
++
++int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
++ struct kvm_sregs *sregs)
++{
++ return -EINVAL;
++
++}
++int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
++ struct kvm_translation *tr)
++{
++
++ return -EINVAL;
++}
++
++static int kvm_alloc_vmm_area(void)
++{
++ if (!kvm_vmm_base && (kvm_vm_buffer_size < KVM_VM_BUFFER_SIZE)) {
++ kvm_vmm_base = __get_free_pages(GFP_KERNEL,
++ get_order(KVM_VMM_SIZE));
++ if (!kvm_vmm_base)
++ return -ENOMEM;
++
++ memset((void *)kvm_vmm_base, 0, KVM_VMM_SIZE);
++ kvm_vm_buffer = kvm_vmm_base + VMM_SIZE;
++
++ printk(KERN_DEBUG"kvm:VMM's Base Addr:0x%lx, vm_buffer:0x%lx\n",
++ kvm_vmm_base, kvm_vm_buffer);
++ }
++
++ return 0;
++}
++
++static void kvm_free_vmm_area(void)
++{
++ if (kvm_vmm_base) {
++ /*Zero this area before free to avoid bits leak!!*/
++ memset((void *)kvm_vmm_base, 0, KVM_VMM_SIZE);
++ free_pages(kvm_vmm_base, get_order(KVM_VMM_SIZE));
++ kvm_vmm_base = 0;
++ kvm_vm_buffer = 0;
++ kvm_vsa_base = 0;
++ }
++}
++
++/*
++ * Make sure that a cpu that is being hot-unplugged does not have any vcpus
++ * cached on it. Leave it as blank for IA64.
++ */
++void decache_vcpus_on_cpu(int cpu)
++{
++}
++
++static void vti_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
++{
++}
++
++static int vti_init_vpd(struct kvm_vcpu *vcpu)
++{
++ int i;
++ union cpuid3_t cpuid3;
++ struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
++
++ if (IS_ERR(vpd))
++ return PTR_ERR(vpd);
++
++ /* CPUID init */
++ for (i = 0; i < 5; i++)
++ vpd->vcpuid[i] = ia64_get_cpuid(i);
++
++ /* Limit the CPUID number to 5 */
++ cpuid3.value = vpd->vcpuid[3];
++ cpuid3.number = 4; /* 5 - 1 */
++ vpd->vcpuid[3] = cpuid3.value;
++
++ /*Set vac and vdc fields*/
++ vpd->vac.a_from_int_cr = 1;
++ vpd->vac.a_to_int_cr = 1;
++ vpd->vac.a_from_psr = 1;
++ vpd->vac.a_from_cpuid = 1;
++ vpd->vac.a_cover = 1;
++ vpd->vac.a_bsw = 1;
++ vpd->vac.a_int = 1;
++ vpd->vdc.d_vmsw = 1;
++
++ /*Set virtual buffer*/
++ vpd->virt_env_vaddr = KVM_VM_BUFFER_BASE;
++
++ return 0;
++}
++
++static int vti_create_vp(struct kvm_vcpu *vcpu)
++{
++ long ret;
++ struct vpd *vpd = vcpu->arch.vpd;
++ unsigned long vmm_ivt;
++
++ vmm_ivt = kvm_vmm_info->vmm_ivt;
++
++ printk(KERN_DEBUG "kvm: vcpu:%p,ivt: 0x%lx\n", vcpu, vmm_ivt);
++
++ ret = ia64_pal_vp_create((u64 *)vpd, (u64 *)vmm_ivt, 0);
++
++ if (ret) {
++ printk(KERN_ERR"kvm: ia64_pal_vp_create failed!\n");
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static void init_ptce_info(struct kvm_vcpu *vcpu)
++{
++ ia64_ptce_info_t ptce = {0};
++
++ ia64_get_ptce(&ptce);
++ vcpu->arch.ptce_base = ptce.base;
++ vcpu->arch.ptce_count[0] = ptce.count[0];
++ vcpu->arch.ptce_count[1] = ptce.count[1];
++ vcpu->arch.ptce_stride[0] = ptce.stride[0];
++ vcpu->arch.ptce_stride[1] = ptce.stride[1];
++}
++
++static void kvm_migrate_hlt_timer(struct kvm_vcpu *vcpu)
++{
++ struct hrtimer *p_ht = &vcpu->arch.hlt_timer;
++
++ if (hrtimer_cancel(p_ht))
++ hrtimer_start(p_ht, p_ht->expires, HRTIMER_MODE_ABS);
++}
++
++static enum hrtimer_restart hlt_timer_fn(struct hrtimer *data)
++{
++ struct kvm_vcpu *vcpu;
++ wait_queue_head_t *q;
++
++ vcpu = container_of(data, struct kvm_vcpu, arch.hlt_timer);
++ if (vcpu->arch.mp_state != KVM_MP_STATE_HALTED)
++ goto out;
++
++ q = &vcpu->wq;
++ if (waitqueue_active(q)) {
++ vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
++ wake_up_interruptible(q);
++ }
++out:
++ vcpu->arch.timer_check = 1;
++ return HRTIMER_NORESTART;
++}
++
++#define PALE_RESET_ENTRY 0x80000000ffffffb0UL
++
++int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
++{
++ struct kvm_vcpu *v;
++ int r;
++ int i;
++ long itc_offset;
++ struct kvm *kvm = vcpu->kvm;
++ struct kvm_pt_regs *regs = vcpu_regs(vcpu);
++
++ union context *p_ctx = &vcpu->arch.guest;
++ struct kvm_vcpu *vmm_vcpu = to_guest(vcpu->kvm, vcpu);
++
++ /*Init vcpu context for first run.*/
++ if (IS_ERR(vmm_vcpu))
++ return PTR_ERR(vmm_vcpu);
++
++ if (vcpu->vcpu_id == 0) {
++ vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
++
++ /*Set entry address for first run.*/
++ regs->cr_iip = PALE_RESET_ENTRY;
++
++ /*Initilize itc offset for vcpus*/
++ itc_offset = 0UL - ia64_getreg(_IA64_REG_AR_ITC);
++ for (i = 0; i < MAX_VCPU_NUM; i++) {
++ v = (struct kvm_vcpu *)((char *)vcpu + VCPU_SIZE * i);
++ v->arch.itc_offset = itc_offset;
++ v->arch.last_itc = 0;
++ }
++ } else
++ vcpu->arch.mp_state = KVM_MP_STATE_UNINITIALIZED;
++
++ r = -ENOMEM;
++ vcpu->arch.apic = kzalloc(sizeof(struct kvm_lapic), GFP_KERNEL);
++ if (!vcpu->arch.apic)
++ goto out;
++ vcpu->arch.apic->vcpu = vcpu;
++
++ p_ctx->gr[1] = 0;
++ p_ctx->gr[12] = (unsigned long)((char *)vmm_vcpu + IA64_STK_OFFSET);
++ p_ctx->gr[13] = (unsigned long)vmm_vcpu;
++ p_ctx->psr = 0x1008522000UL;
++ p_ctx->ar[40] = FPSR_DEFAULT; /*fpsr*/
++ p_ctx->caller_unat = 0;
++ p_ctx->pr = 0x0;
++ p_ctx->ar[36] = 0x0; /*unat*/
++ p_ctx->ar[19] = 0x0; /*rnat*/
++ p_ctx->ar[18] = (unsigned long)vmm_vcpu +
++ ((sizeof(struct kvm_vcpu)+15) & ~15);
++ p_ctx->ar[64] = 0x0; /*pfs*/
++ p_ctx->cr[0] = 0x7e04UL;
++ p_ctx->cr[2] = (unsigned long)kvm_vmm_info->vmm_ivt;
++ p_ctx->cr[8] = 0x3c;
++
++ /*Initilize region register*/
++ p_ctx->rr[0] = 0x30;
++ p_ctx->rr[1] = 0x30;
++ p_ctx->rr[2] = 0x30;
++ p_ctx->rr[3] = 0x30;
++ p_ctx->rr[4] = 0x30;
++ p_ctx->rr[5] = 0x30;
++ p_ctx->rr[7] = 0x30;
++
++ /*Initilize branch register 0*/
++ p_ctx->br[0] = *(unsigned long *)kvm_vmm_info->vmm_entry;
++
++ vcpu->arch.vmm_rr = kvm->arch.vmm_init_rr;
++ vcpu->arch.metaphysical_rr0 = kvm->arch.metaphysical_rr0;
++ vcpu->arch.metaphysical_rr4 = kvm->arch.metaphysical_rr4;
++
++ hrtimer_init(&vcpu->arch.hlt_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
++ vcpu->arch.hlt_timer.function = hlt_timer_fn;
++
++ vcpu->arch.last_run_cpu = -1;
++ vcpu->arch.vpd = (struct vpd *)VPD_ADDR(vcpu->vcpu_id);
++ vcpu->arch.vsa_base = kvm_vsa_base;
++ vcpu->arch.__gp = kvm_vmm_gp;
++ vcpu->arch.dirty_log_lock_pa = __pa(&kvm->arch.dirty_log_lock);
++ vcpu->arch.vhpt.hash = (struct thash_data *)VHPT_ADDR(vcpu->vcpu_id);
++ vcpu->arch.vtlb.hash = (struct thash_data *)VTLB_ADDR(vcpu->vcpu_id);
++ init_ptce_info(vcpu);
++
++ r = 0;
++out:
++ return r;
++}
++
++static int vti_vcpu_setup(struct kvm_vcpu *vcpu, int id)
++{
++ unsigned long psr;
++ int r;
++
++ local_irq_save(psr);
++ r = kvm_insert_vmm_mapping(vcpu);
++ if (r)
++ goto fail;
++ r = kvm_vcpu_init(vcpu, vcpu->kvm, id);
++ if (r)
++ goto fail;
++
++ r = vti_init_vpd(vcpu);
++ if (r) {
++ printk(KERN_DEBUG"kvm: vpd init error!!\n");
++ goto uninit;
++ }
++
++ r = vti_create_vp(vcpu);
++ if (r)
++ goto uninit;
++
++ kvm_purge_vmm_mapping(vcpu);
++ local_irq_restore(psr);
++
++ return 0;
++uninit:
++ kvm_vcpu_uninit(vcpu);
++fail:
++ return r;
++}
++
++struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
++ unsigned int id)
++{
++ struct kvm_vcpu *vcpu;
++ unsigned long vm_base = kvm->arch.vm_base;
++ int r;
++ int cpu;
++
++ r = -ENOMEM;
++ if (!vm_base) {
++ printk(KERN_ERR"kvm: Create vcpu[%d] error!\n", id);
++ goto fail;
++ }
++ vcpu = (struct kvm_vcpu *)(vm_base + KVM_VCPU_OFS + VCPU_SIZE * id);
++ vcpu->kvm = kvm;
++
++ cpu = get_cpu();
++ vti_vcpu_load(vcpu, cpu);
++ r = vti_vcpu_setup(vcpu, id);
++ put_cpu();
++
++ if (r) {
++ printk(KERN_DEBUG"kvm: vcpu_setup error!!\n");
++ goto fail;
++ }
++
++ return vcpu;
++fail:
++ return ERR_PTR(r);
++}
++
++int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
++{
++ return 0;
++}
++
++int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
++{
++ return -EINVAL;
++}
++
++int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
++{
++ return -EINVAL;
++}
++
++int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
++ struct kvm_debug_guest *dbg)
++{
++ return -EINVAL;
++}
++
++static void free_kvm(struct kvm *kvm)
++{
++ unsigned long vm_base = kvm->arch.vm_base;
++
++ if (vm_base) {
++ memset((void *)vm_base, 0, KVM_VM_DATA_SIZE);
++ free_pages(vm_base, get_order(KVM_VM_DATA_SIZE));
++ }
++
++}
++
++static void kvm_release_vm_pages(struct kvm *kvm)
++{
++ struct kvm_memory_slot *memslot;
++ int i, j;
++ unsigned long base_gfn;
++
++ for (i = 0; i < kvm->nmemslots; i++) {
++ memslot = &kvm->memslots[i];
++ base_gfn = memslot->base_gfn;
++
++ for (j = 0; j < memslot->npages; j++) {
++ if (memslot->rmap[j])
++ put_page((struct page *)memslot->rmap[j]);
++ }
++ }
++}
++
++void kvm_arch_destroy_vm(struct kvm *kvm)
++{
++ kfree(kvm->arch.vioapic);
++ kvm_release_vm_pages(kvm);
++ kvm_free_physmem(kvm);
++ free_kvm(kvm);
++}
++
++void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
++{
++}
++
++void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
++{
++ if (cpu != vcpu->cpu) {
++ vcpu->cpu = cpu;
++ if (vcpu->arch.ht_active)
++ kvm_migrate_hlt_timer(vcpu);
++ }
++}
++
++#define SAVE_REGS(_x) regs->_x = vcpu->arch._x
++
++int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
++{
++ int i;
++ int r;
++ struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
++ vcpu_load(vcpu);
++
++ for (i = 0; i < 16; i++) {
++ regs->vpd.vgr[i] = vpd->vgr[i];
++ regs->vpd.vbgr[i] = vpd->vbgr[i];
++ }
++ for (i = 0; i < 128; i++)
++ regs->vpd.vcr[i] = vpd->vcr[i];
++ regs->vpd.vhpi = vpd->vhpi;
++ regs->vpd.vnat = vpd->vnat;
++ regs->vpd.vbnat = vpd->vbnat;
++ regs->vpd.vpsr = vpd->vpsr;
++ regs->vpd.vpr = vpd->vpr;
++
++ r = -EFAULT;
++ r = copy_to_user(regs->saved_guest, &vcpu->arch.guest,
++ sizeof(union context));
++ if (r)
++ goto out;
++ r = copy_to_user(regs->saved_stack, (void *)vcpu, IA64_STK_OFFSET);
++ if (r)
++ goto out;
++ SAVE_REGS(mp_state);
++ SAVE_REGS(vmm_rr);
++ memcpy(regs->itrs, vcpu->arch.itrs, sizeof(struct thash_data) * NITRS);
++ memcpy(regs->dtrs, vcpu->arch.dtrs, sizeof(struct thash_data) * NDTRS);
++ SAVE_REGS(itr_regions);
++ SAVE_REGS(dtr_regions);
++ SAVE_REGS(tc_regions);
++ SAVE_REGS(irq_check);
++ SAVE_REGS(itc_check);
++ SAVE_REGS(timer_check);
++ SAVE_REGS(timer_pending);
++ SAVE_REGS(last_itc);
++ for (i = 0; i < 8; i++) {
++ regs->vrr[i] = vcpu->arch.vrr[i];
++ regs->ibr[i] = vcpu->arch.ibr[i];
++ regs->dbr[i] = vcpu->arch.dbr[i];
++ }
++ for (i = 0; i < 4; i++)
++ regs->insvc[i] = vcpu->arch.insvc[i];
++ regs->saved_itc = vcpu->arch.itc_offset + ia64_getreg(_IA64_REG_AR_ITC);
++ SAVE_REGS(xtp);
++ SAVE_REGS(metaphysical_rr0);
++ SAVE_REGS(metaphysical_rr4);
++ SAVE_REGS(metaphysical_saved_rr0);
++ SAVE_REGS(metaphysical_saved_rr4);
++ SAVE_REGS(fp_psr);
++ SAVE_REGS(saved_gp);
++ vcpu_put(vcpu);
++ r = 0;
++out:
++ return r;
++}
++
++void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
++{
++
++ hrtimer_cancel(&vcpu->arch.hlt_timer);
++ kfree(vcpu->arch.apic);
++}
++
++
++long kvm_arch_vcpu_ioctl(struct file *filp,
++ unsigned int ioctl, unsigned long arg)
++{
++ return -EINVAL;
++}
++
++int kvm_arch_set_memory_region(struct kvm *kvm,
++ struct kvm_userspace_memory_region *mem,
++ struct kvm_memory_slot old,
++ int user_alloc)
++{
++ unsigned long i;
++ struct page *page;
++ int npages = mem->memory_size >> PAGE_SHIFT;
++ struct kvm_memory_slot *memslot = &kvm->memslots[mem->slot];
++ unsigned long base_gfn = memslot->base_gfn;
++
++ for (i = 0; i < npages; i++) {
++ page = gfn_to_page(kvm, base_gfn + i);
++ kvm_set_pmt_entry(kvm, base_gfn + i,
++ page_to_pfn(page) << PAGE_SHIFT,
++ _PAGE_AR_RWX|_PAGE_MA_WB);
++ memslot->rmap[i] = (unsigned long)page;
++ }
++
++ return 0;
++}
++
++
++long kvm_arch_dev_ioctl(struct file *filp,
++ unsigned int ioctl, unsigned long arg)
++{
++ return -EINVAL;
++}
++
++void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
++{
++ kvm_vcpu_uninit(vcpu);
++}
++
++static int vti_cpu_has_kvm_support(void)
++{
++ long avail = 1, status = 1, control = 1;
++ long ret;
++
++ ret = ia64_pal_proc_get_features(&avail, &status, &control, 0);
++ if (ret)
++ goto out;
++
++ if (!(avail & PAL_PROC_VM_BIT))
++ goto out;
++
++ printk(KERN_DEBUG"kvm: Hardware Supports VT\n");
++
++ ret = ia64_pal_vp_env_info(&kvm_vm_buffer_size, &vp_env_info);
++ if (ret)
++ goto out;
++ printk(KERN_DEBUG"kvm: VM Buffer Size:0x%lx\n", kvm_vm_buffer_size);
++
++ if (!(vp_env_info & VP_OPCODE)) {
++ printk(KERN_WARNING"kvm: No opcode ability on hardware, "
++ "vm_env_info:0x%lx\n", vp_env_info);
++ }
++
++ return 1;
++out:
++ return 0;
++}
++
++static int kvm_relocate_vmm(struct kvm_vmm_info *vmm_info,
++ struct module *module)
++{
++ unsigned long module_base;
++ unsigned long vmm_size;
++
++ unsigned long vmm_offset, func_offset, fdesc_offset;
++ struct fdesc *p_fdesc;
++
++ BUG_ON(!module);
++
++ if (!kvm_vmm_base) {
++ printk("kvm: kvm area hasn't been initilized yet!!\n");
++ return -EFAULT;
++ }
++
++ /*Calculate new position of relocated vmm module.*/
++ module_base = (unsigned long)module->module_core;
++ vmm_size = module->core_size;
++ if (unlikely(vmm_size > KVM_VMM_SIZE))
++ return -EFAULT;
++
++ memcpy((void *)kvm_vmm_base, (void *)module_base, vmm_size);
++ kvm_flush_icache(kvm_vmm_base, vmm_size);
++
++ /*Recalculate kvm_vmm_info based on new VMM*/
++ vmm_offset = vmm_info->vmm_ivt - module_base;
++ kvm_vmm_info->vmm_ivt = KVM_VMM_BASE + vmm_offset;
++ printk(KERN_DEBUG"kvm: Relocated VMM's IVT Base Addr:%lx\n",
++ kvm_vmm_info->vmm_ivt);
++
++ fdesc_offset = (unsigned long)vmm_info->vmm_entry - module_base;
++ kvm_vmm_info->vmm_entry = (kvm_vmm_entry *)(KVM_VMM_BASE +
++ fdesc_offset);
++ func_offset = *(unsigned long *)vmm_info->vmm_entry - module_base;
++ p_fdesc = (struct fdesc *)(kvm_vmm_base + fdesc_offset);
++ p_fdesc->ip = KVM_VMM_BASE + func_offset;
++ p_fdesc->gp = KVM_VMM_BASE+(p_fdesc->gp - module_base);
++
++ printk(KERN_DEBUG"kvm: Relocated VMM's Init Entry Addr:%lx\n",
++ KVM_VMM_BASE+func_offset);
++
++ fdesc_offset = (unsigned long)vmm_info->tramp_entry - module_base;
++ kvm_vmm_info->tramp_entry = (kvm_tramp_entry *)(KVM_VMM_BASE +
++ fdesc_offset);
++ func_offset = *(unsigned long *)vmm_info->tramp_entry - module_base;
++ p_fdesc = (struct fdesc *)(kvm_vmm_base + fdesc_offset);
++ p_fdesc->ip = KVM_VMM_BASE + func_offset;
++ p_fdesc->gp = KVM_VMM_BASE + (p_fdesc->gp - module_base);
++
++ kvm_vmm_gp = p_fdesc->gp;
++
++ printk(KERN_DEBUG"kvm: Relocated VMM's Entry IP:%p\n",
++ kvm_vmm_info->vmm_entry);
++ printk(KERN_DEBUG"kvm: Relocated VMM's Trampoline Entry IP:0x%lx\n",
++ KVM_VMM_BASE + func_offset);
++
++ return 0;
++}
++
++int kvm_arch_init(void *opaque)
++{
++ int r;
++ struct kvm_vmm_info *vmm_info = (struct kvm_vmm_info *)opaque;
++
++ if (!vti_cpu_has_kvm_support()) {
++ printk(KERN_ERR "kvm: No Hardware Virtualization Support!\n");
++ r = -EOPNOTSUPP;
++ goto out;
++ }
++
++ if (kvm_vmm_info) {
++ printk(KERN_ERR "kvm: Already loaded VMM module!\n");
++ r = -EEXIST;
++ goto out;
++ }
++
++ r = -ENOMEM;
++ kvm_vmm_info = kzalloc(sizeof(struct kvm_vmm_info), GFP_KERNEL);
++ if (!kvm_vmm_info)
++ goto out;
++
++ if (kvm_alloc_vmm_area())
++ goto out_free0;
++
++ r = kvm_relocate_vmm(vmm_info, vmm_info->module);
++ if (r)
++ goto out_free1;
++
++ return 0;
++
++out_free1:
++ kvm_free_vmm_area();
++out_free0:
++ kfree(kvm_vmm_info);
++out:
++ return r;
++}
++
++void kvm_arch_exit(void)
++{
++ kvm_free_vmm_area();
++ kfree(kvm_vmm_info);
++ kvm_vmm_info = NULL;
++}
++
++static int kvm_ia64_sync_dirty_log(struct kvm *kvm,
++ struct kvm_dirty_log *log)
++{
++ struct kvm_memory_slot *memslot;
++ int r, i;
++ long n, base;
++ unsigned long *dirty_bitmap = (unsigned long *)((void *)kvm - KVM_VM_OFS
++ + KVM_MEM_DIRTY_LOG_OFS);
++
++ r = -EINVAL;
++ if (log->slot >= KVM_MEMORY_SLOTS)
++ goto out;
++
++ memslot = &kvm->memslots[log->slot];
++ r = -ENOENT;
++ if (!memslot->dirty_bitmap)
++ goto out;
++
++ n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
++ base = memslot->base_gfn / BITS_PER_LONG;
++
++ for (i = 0; i < n/sizeof(long); ++i) {
++ memslot->dirty_bitmap[i] = dirty_bitmap[base + i];
++ dirty_bitmap[base + i] = 0;
++ }
++ r = 0;
++out:
++ return r;
++}
++
++int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
++ struct kvm_dirty_log *log)
++{
++ int r;
++ int n;
++ struct kvm_memory_slot *memslot;
++ int is_dirty = 0;
++
++ spin_lock(&kvm->arch.dirty_log_lock);
++
++ r = kvm_ia64_sync_dirty_log(kvm, log);
++ if (r)
++ goto out;
++
++ r = kvm_get_dirty_log(kvm, log, &is_dirty);
++ if (r)
++ goto out;
++
++ /* If nothing is dirty, don't bother messing with page tables. */
++ if (is_dirty) {
++ kvm_flush_remote_tlbs(kvm);
++ memslot = &kvm->memslots[log->slot];
++ n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
++ memset(memslot->dirty_bitmap, 0, n);
++ }
++ r = 0;
++out:
++ spin_unlock(&kvm->arch.dirty_log_lock);
++ return r;
++}
++
++int kvm_arch_hardware_setup(void)
++{
++ return 0;
++}
++
++void kvm_arch_hardware_unsetup(void)
++{
++}
++
++static void vcpu_kick_intr(void *info)
++{
++#ifdef DEBUG
++ struct kvm_vcpu *vcpu = (struct kvm_vcpu *)info;
++ printk(KERN_DEBUG"vcpu_kick_intr %p \n", vcpu);
++#endif
++}
++
++void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
++{
++ int ipi_pcpu = vcpu->cpu;
++
++ if (waitqueue_active(&vcpu->wq))
++ wake_up_interruptible(&vcpu->wq);
++
++ if (vcpu->guest_mode)
++ smp_call_function_single(ipi_pcpu, vcpu_kick_intr, vcpu, 0, 0);
++}
++
++int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig)
++{
++
++ struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
++
++ if (!test_and_set_bit(vec, &vpd->irr[0])) {
++ vcpu->arch.irq_new_pending = 1;
++ if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
++ kvm_vcpu_kick(vcpu);
++ else if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED) {
++ vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
++ if (waitqueue_active(&vcpu->wq))
++ wake_up_interruptible(&vcpu->wq);
++ }
++ return 1;
++ }
++ return 0;
++}
++
++int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest)
++{
++ return apic->vcpu->vcpu_id == dest;
++}
++
++int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda)
++{
++ return 0;
++}
++
++struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
++ unsigned long bitmap)
++{
++ struct kvm_vcpu *lvcpu = kvm->vcpus[0];
++ int i;
++
++ for (i = 1; i < KVM_MAX_VCPUS; i++) {
++ if (!kvm->vcpus[i])
++ continue;
++ if (lvcpu->arch.xtp > kvm->vcpus[i]->arch.xtp)
++ lvcpu = kvm->vcpus[i];
++ }
++
++ return lvcpu;
++}
++
++static int find_highest_bits(int *dat)
++{
++ u32 bits, bitnum;
++ int i;
++
++ /* loop for all 256 bits */
++ for (i = 7; i >= 0 ; i--) {
++ bits = dat[i];
++ if (bits) {
++ bitnum = fls(bits);
++ return i * 32 + bitnum - 1;
++ }
++ }
++
++ return -1;
++}
++
++int kvm_highest_pending_irq(struct kvm_vcpu *vcpu)
++{
++ struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
++
++ if (vpd->irr[0] & (1UL << NMI_VECTOR))
++ return NMI_VECTOR;
++ if (vpd->irr[0] & (1UL << ExtINT_VECTOR))
++ return ExtINT_VECTOR;
++
++ return find_highest_bits((int *)&vpd->irr[0]);
++}
++
++int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu)
++{
++ if (kvm_highest_pending_irq(vcpu) != -1)
++ return 1;
++ return 0;
++}
++
++int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
++{
++ return 0;
++}
++
++gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
++{
++ return gfn;
++}
++
++int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
++{
++ return vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE;
++}
++
++int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
++ struct kvm_mp_state *mp_state)
++{
++ return -EINVAL;
++}
++
++int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
++ struct kvm_mp_state *mp_state)
++{
++ return -EINVAL;
++}
+diff --git a/arch/ia64/kvm/kvm_fw.c b/arch/ia64/kvm/kvm_fw.c
+new file mode 100644
+index 0000000..091f936
+--- /dev/null
++++ b/arch/ia64/kvm/kvm_fw.c
+@@ -0,0 +1,500 @@
++/*
++ * PAL/SAL call delegation
+ *
-+ * target_mask : 0x1 : itr, 0x2 : dtr, 0x3 : idtr
++ * Copyright (c) 2004 Li Susie <susie.li at intel.com>
++ * Copyright (c) 2005 Yu Ke <ke.yu at intel.com>
++ * Copyright (c) 2007 Xiantao Zhang <xiantao.zhang at intel.com>
+ *
-+ * va : virtual address.
-+ * pte : pte entries inserted.
-+ * log_size: range to be covered.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * Return value: <0 : error No.
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
+ *
-+ * >=0 : slot number allocated for TR.
-+ * Must be called with preemption disabled.
++ * You 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.
+ */
-+int ia64_itr_entry(u64 target_mask, u64 va, u64 pte, u64 log_size)
++
++#include <linux/kvm_host.h>
++#include <linux/smp.h>
++
++#include "vti.h"
++#include "misc.h"
++
++#include <asm/pal.h>
++#include <asm/sal.h>
++#include <asm/tlb.h>
++
++/*
++ * Handy macros to make sure that the PAL return values start out
++ * as something meaningful.
++ */
++#define INIT_PAL_STATUS_UNIMPLEMENTED(x) \
++ { \
++ x.status = PAL_STATUS_UNIMPLEMENTED; \
++ x.v0 = 0; \
++ x.v1 = 0; \
++ x.v2 = 0; \
++ }
++
++#define INIT_PAL_STATUS_SUCCESS(x) \
++ { \
++ x.status = PAL_STATUS_SUCCESS; \
++ x.v0 = 0; \
++ x.v1 = 0; \
++ x.v2 = 0; \
++ }
++
++static void kvm_get_pal_call_data(struct kvm_vcpu *vcpu,
++ u64 *gr28, u64 *gr29, u64 *gr30, u64 *gr31) {
++ struct exit_ctl_data *p;
++
++ if (vcpu) {
++ p = &vcpu->arch.exit_data;
++ if (p->exit_reason == EXIT_REASON_PAL_CALL) {
++ *gr28 = p->u.pal_data.gr28;
++ *gr29 = p->u.pal_data.gr29;
++ *gr30 = p->u.pal_data.gr30;
++ *gr31 = p->u.pal_data.gr31;
++ return ;
++ }
++ }
++ printk(KERN_DEBUG"Failed to get vcpu pal data!!!\n");
++}
++
++static void set_pal_result(struct kvm_vcpu *vcpu,
++ struct ia64_pal_retval result) {
++
++ struct exit_ctl_data *p;
++
++ p = kvm_get_exit_data(vcpu);
++ if (p && p->exit_reason == EXIT_REASON_PAL_CALL) {
++ p->u.pal_data.ret = result;
++ return ;
++ }
++ INIT_PAL_STATUS_UNIMPLEMENTED(p->u.pal_data.ret);
++}
++
++static void set_sal_result(struct kvm_vcpu *vcpu,
++ struct sal_ret_values result) {
++ struct exit_ctl_data *p;
++
++ p = kvm_get_exit_data(vcpu);
++ if (p && p->exit_reason == EXIT_REASON_SAL_CALL) {
++ p->u.sal_data.ret = result;
++ return ;
++ }
++ printk(KERN_WARNING"Failed to set sal result!!\n");
++}
++
++struct cache_flush_args {
++ u64 cache_type;
++ u64 operation;
++ u64 progress;
++ long status;
++};
++
++cpumask_t cpu_cache_coherent_map;
++
++static void remote_pal_cache_flush(void *data)
+{
-+ int i, r;
-+ unsigned long psr;
-+ struct ia64_tr_entry *p;
-+ int cpu = smp_processor_id();
++ struct cache_flush_args *args = data;
++ long status;
++ u64 progress = args->progress;
+
-+ r = -EINVAL;
-+ /*Check overlap with existing TR entries*/
-+ if (target_mask & 0x1) {
-+ p = &__per_cpu_idtrs[cpu][0][0];
-+ for (i = IA64_TR_ALLOC_BASE; i <= per_cpu(ia64_tr_used, cpu);
-+ i++, p++) {
-+ if (p->pte & 0x1)
-+ if (is_tr_overlap(p, va, log_size)) {
-+ printk(KERN_DEBUG "Overlapped Entry"
-+ "Inserted for TR Reigster!!\n");
-+ goto out;
++ status = ia64_pal_cache_flush(args->cache_type, args->operation,
++ &progress, NULL);
++ if (status != 0)
++ args->status = status;
++}
++
++static struct ia64_pal_retval pal_cache_flush(struct kvm_vcpu *vcpu)
++{
++ u64 gr28, gr29, gr30, gr31;
++ struct ia64_pal_retval result = {0, 0, 0, 0};
++ struct cache_flush_args args = {0, 0, 0, 0};
++ long psr;
++
++ gr28 = gr29 = gr30 = gr31 = 0;
++ kvm_get_pal_call_data(vcpu, &gr28, &gr29, &gr30, &gr31);
++
++ if (gr31 != 0)
++ printk(KERN_ERR"vcpu:%p called cache_flush error!\n", vcpu);
++
++ /* Always call Host Pal in int=1 */
++ gr30 &= ~PAL_CACHE_FLUSH_CHK_INTRS;
++ args.cache_type = gr29;
++ args.operation = gr30;
++ smp_call_function(remote_pal_cache_flush,
++ (void *)&args, 1, 1);
++ if (args.status != 0)
++ printk(KERN_ERR"pal_cache_flush error!,"
++ "status:0x%lx\n", args.status);
++ /*
++ * Call Host PAL cache flush
++ * Clear psr.ic when call PAL_CACHE_FLUSH
++ */
++ local_irq_save(psr);
++ result.status = ia64_pal_cache_flush(gr29, gr30, &result.v1,
++ &result.v0);
++ local_irq_restore(psr);
++ if (result.status != 0)
++ printk(KERN_ERR"vcpu:%p crashed due to cache_flush err:%ld"
++ "in1:%lx,in2:%lx\n",
++ vcpu, result.status, gr29, gr30);
++
++#if 0
++ if (gr29 == PAL_CACHE_TYPE_COHERENT) {
++ cpus_setall(vcpu->arch.cache_coherent_map);
++ cpu_clear(vcpu->cpu, vcpu->arch.cache_coherent_map);
++ cpus_setall(cpu_cache_coherent_map);
++ cpu_clear(vcpu->cpu, cpu_cache_coherent_map);
++ }
++#endif
++ return result;
++}
++
++struct ia64_pal_retval pal_cache_summary(struct kvm_vcpu *vcpu)
++{
++
++ struct ia64_pal_retval result;
++
++ PAL_CALL(result, PAL_CACHE_SUMMARY, 0, 0, 0);
++ return result;
++}
++
++static struct ia64_pal_retval pal_freq_base(struct kvm_vcpu *vcpu)
++{
++
++ struct ia64_pal_retval result;
++
++ PAL_CALL(result, PAL_FREQ_BASE, 0, 0, 0);
++
++ /*
++ * PAL_FREQ_BASE may not be implemented in some platforms,
++ * call SAL instead.
++ */
++ if (result.v0 == 0) {
++ result.status = ia64_sal_freq_base(SAL_FREQ_BASE_PLATFORM,
++ &result.v0,
++ &result.v1);
++ result.v2 = 0;
++ }
++
++ return result;
++}
++
++static struct ia64_pal_retval pal_freq_ratios(struct kvm_vcpu *vcpu)
++{
++
++ struct ia64_pal_retval result;
++
++ PAL_CALL(result, PAL_FREQ_RATIOS, 0, 0, 0);
++ return result;
++}
++
++static struct ia64_pal_retval pal_logical_to_physica(struct kvm_vcpu *vcpu)
++{
++ struct ia64_pal_retval result;
++
++ INIT_PAL_STATUS_UNIMPLEMENTED(result);
++ return result;
++}
++
++static struct ia64_pal_retval pal_platform_addr(struct kvm_vcpu *vcpu)
++{
++
++ struct ia64_pal_retval result;
++
++ INIT_PAL_STATUS_SUCCESS(result);
++ return result;
++}
++
++static struct ia64_pal_retval pal_proc_get_features(struct kvm_vcpu *vcpu)
++{
++
++ struct ia64_pal_retval result = {0, 0, 0, 0};
++ long in0, in1, in2, in3;
++
++ kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
++ result.status = ia64_pal_proc_get_features(&result.v0, &result.v1,
++ &result.v2, in2);
++
++ return result;
++}
++
++static struct ia64_pal_retval pal_cache_info(struct kvm_vcpu *vcpu)
++{
++
++ pal_cache_config_info_t ci;
++ long status;
++ unsigned long in0, in1, in2, in3, r9, r10;
++
++ kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
++ status = ia64_pal_cache_config_info(in1, in2, &ci);
++ r9 = ci.pcci_info_1.pcci1_data;
++ r10 = ci.pcci_info_2.pcci2_data;
++ return ((struct ia64_pal_retval){status, r9, r10, 0});
++}
++
++#define GUEST_IMPL_VA_MSB 59
++#define GUEST_RID_BITS 18
++
++static struct ia64_pal_retval pal_vm_summary(struct kvm_vcpu *vcpu)
++{
++
++ pal_vm_info_1_u_t vminfo1;
++ pal_vm_info_2_u_t vminfo2;
++ struct ia64_pal_retval result;
++
++ PAL_CALL(result, PAL_VM_SUMMARY, 0, 0, 0);
++ if (!result.status) {
++ vminfo1.pvi1_val = result.v0;
++ vminfo1.pal_vm_info_1_s.max_itr_entry = 8;
++ vminfo1.pal_vm_info_1_s.max_dtr_entry = 8;
++ result.v0 = vminfo1.pvi1_val;
++ vminfo2.pal_vm_info_2_s.impl_va_msb = GUEST_IMPL_VA_MSB;
++ vminfo2.pal_vm_info_2_s.rid_size = GUEST_RID_BITS;
++ result.v1 = vminfo2.pvi2_val;
++ }
++
++ return result;
++}
++
++static struct ia64_pal_retval pal_vm_info(struct kvm_vcpu *vcpu)
++{
++ struct ia64_pal_retval result;
++
++ INIT_PAL_STATUS_UNIMPLEMENTED(result);
++
++ return result;
++}
++
++static u64 kvm_get_pal_call_index(struct kvm_vcpu *vcpu)
++{
++ u64 index = 0;
++ struct exit_ctl_data *p;
++
++ p = kvm_get_exit_data(vcpu);
++ if (p && (p->exit_reason == EXIT_REASON_PAL_CALL))
++ index = p->u.pal_data.gr28;
++
++ return index;
++}
++
++int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run)
++{
++
++ u64 gr28;
++ struct ia64_pal_retval result;
++ int ret = 1;
++
++ gr28 = kvm_get_pal_call_index(vcpu);
++ /*printk("pal_call index:%lx\n",gr28);*/
++ switch (gr28) {
++ case PAL_CACHE_FLUSH:
++ result = pal_cache_flush(vcpu);
++ break;
++ case PAL_CACHE_SUMMARY:
++ result = pal_cache_summary(vcpu);
++ break;
++ case PAL_HALT_LIGHT:
++ {
++ vcpu->arch.timer_pending = 1;
++ INIT_PAL_STATUS_SUCCESS(result);
++ if (kvm_highest_pending_irq(vcpu) == -1)
++ ret = kvm_emulate_halt(vcpu);
++
++ }
++ break;
++
++ case PAL_FREQ_RATIOS:
++ result = pal_freq_ratios(vcpu);
++ break;
++
++ case PAL_FREQ_BASE:
++ result = pal_freq_base(vcpu);
++ break;
++
++ case PAL_LOGICAL_TO_PHYSICAL :
++ result = pal_logical_to_physica(vcpu);
++ break;
++
++ case PAL_VM_SUMMARY :
++ result = pal_vm_summary(vcpu);
++ break;
++
++ case PAL_VM_INFO :
++ result = pal_vm_info(vcpu);
++ break;
++ case PAL_PLATFORM_ADDR :
++ result = pal_platform_addr(vcpu);
++ break;
++ case PAL_CACHE_INFO:
++ result = pal_cache_info(vcpu);
++ break;
++ case PAL_PTCE_INFO:
++ INIT_PAL_STATUS_SUCCESS(result);
++ result.v1 = (1L << 32) | 1L;
++ break;
++ case PAL_VM_PAGE_SIZE:
++ result.status = ia64_pal_vm_page_size(&result.v0,
++ &result.v1);
++ break;
++ case PAL_RSE_INFO:
++ result.status = ia64_pal_rse_info(&result.v0,
++ (pal_hints_u_t *)&result.v1);
++ break;
++ case PAL_PROC_GET_FEATURES:
++ result = pal_proc_get_features(vcpu);
++ break;
++ case PAL_DEBUG_INFO:
++ result.status = ia64_pal_debug_info(&result.v0,
++ &result.v1);
++ break;
++ case PAL_VERSION:
++ result.status = ia64_pal_version(
++ (pal_version_u_t *)&result.v0,
++ (pal_version_u_t *)&result.v1);
++
++ break;
++ case PAL_FIXED_ADDR:
++ result.status = PAL_STATUS_SUCCESS;
++ result.v0 = vcpu->vcpu_id;
++ break;
++ default:
++ INIT_PAL_STATUS_UNIMPLEMENTED(result);
++ printk(KERN_WARNING"kvm: Unsupported pal call,"
++ " index:0x%lx\n", gr28);
++ }
++ set_pal_result(vcpu, result);
++ return ret;
++}
++
++static struct sal_ret_values sal_emulator(struct kvm *kvm,
++ long index, unsigned long in1,
++ unsigned long in2, unsigned long in3,
++ unsigned long in4, unsigned long in5,
++ unsigned long in6, unsigned long in7)
++{
++ unsigned long r9 = 0;
++ unsigned long r10 = 0;
++ long r11 = 0;
++ long status;
++
++ status = 0;
++ switch (index) {
++ case SAL_FREQ_BASE:
++ status = ia64_sal_freq_base(in1, &r9, &r10);
++ break;
++ case SAL_PCI_CONFIG_READ:
++ printk(KERN_WARNING"kvm: Not allowed to call here!"
++ " SAL_PCI_CONFIG_READ\n");
++ break;
++ case SAL_PCI_CONFIG_WRITE:
++ printk(KERN_WARNING"kvm: Not allowed to call here!"
++ " SAL_PCI_CONFIG_WRITE\n");
++ break;
++ case SAL_SET_VECTORS:
++ if (in1 == SAL_VECTOR_OS_BOOT_RENDEZ) {
++ if (in4 != 0 || in5 != 0 || in6 != 0 || in7 != 0) {
++ status = -2;
++ } else {
++ kvm->arch.rdv_sal_data.boot_ip = in2;
++ kvm->arch.rdv_sal_data.boot_gp = in3;
+ }
++ printk("Rendvous called! iip:%lx\n\n", in2);
++ } else
++ printk(KERN_WARNING"kvm: CALLED SAL_SET_VECTORS %lu."
++ "ignored...\n", in1);
++ break;
++ case SAL_GET_STATE_INFO:
++ /* No more info. */
++ status = -5;
++ r9 = 0;
++ break;
++ case SAL_GET_STATE_INFO_SIZE:
++ /* Return a dummy size. */
++ status = 0;
++ r9 = 128;
++ break;
++ case SAL_CLEAR_STATE_INFO:
++ /* Noop. */
++ break;
++ case SAL_MC_RENDEZ:
++ printk(KERN_WARNING
++ "kvm: called SAL_MC_RENDEZ. ignored...\n");
++ break;
++ case SAL_MC_SET_PARAMS:
++ printk(KERN_WARNING
++ "kvm: called SAL_MC_SET_PARAMS.ignored!\n");
++ break;
++ case SAL_CACHE_FLUSH:
++ if (1) {
++ /*Flush using SAL.
++ This method is faster but has a side
++ effect on other vcpu running on
++ this cpu. */
++ status = ia64_sal_cache_flush(in1);
++ } else {
++ /*Maybe need to implement the method
++ without side effect!*/
++ status = 0;
+ }
++ break;
++ case SAL_CACHE_INIT:
++ printk(KERN_WARNING
++ "kvm: called SAL_CACHE_INIT. ignored...\n");
++ break;
++ case SAL_UPDATE_PAL:
++ printk(KERN_WARNING
++ "kvm: CALLED SAL_UPDATE_PAL. ignored...\n");
++ break;
++ default:
++ printk(KERN_WARNING"kvm: called SAL_CALL with unknown index."
++ " index:%ld\n", index);
++ status = -1;
++ break;
+ }
-+ if (target_mask & 0x2) {
-+ p = &__per_cpu_idtrs[cpu][1][0];
-+ for (i = IA64_TR_ALLOC_BASE; i <= per_cpu(ia64_tr_used, cpu);
-+ i++, p++) {
-+ if (p->pte & 0x1)
-+ if (is_tr_overlap(p, va, log_size)) {
-+ printk(KERN_DEBUG "Overlapped Entry"
-+ "Inserted for TR Reigster!!\n");
-+ goto out;
-+ }
++ return ((struct sal_ret_values) {status, r9, r10, r11});
++}
++
++static void kvm_get_sal_call_data(struct kvm_vcpu *vcpu, u64 *in0, u64 *in1,
++ u64 *in2, u64 *in3, u64 *in4, u64 *in5, u64 *in6, u64 *in7){
++
++ struct exit_ctl_data *p;
++
++ p = kvm_get_exit_data(vcpu);
++
++ if (p) {
++ if (p->exit_reason == EXIT_REASON_SAL_CALL) {
++ *in0 = p->u.sal_data.in0;
++ *in1 = p->u.sal_data.in1;
++ *in2 = p->u.sal_data.in2;
++ *in3 = p->u.sal_data.in3;
++ *in4 = p->u.sal_data.in4;
++ *in5 = p->u.sal_data.in5;
++ *in6 = p->u.sal_data.in6;
++ *in7 = p->u.sal_data.in7;
++ return ;
+ }
+ }
++ *in0 = 0;
++}
+
-+ for (i = IA64_TR_ALLOC_BASE; i < per_cpu(ia64_tr_num, cpu); i++) {
-+ switch (target_mask & 0x3) {
-+ case 1:
-+ if (!(__per_cpu_idtrs[cpu][0][i].pte & 0x1))
-+ goto found;
-+ continue;
-+ case 2:
-+ if (!(__per_cpu_idtrs[cpu][1][i].pte & 0x1))
-+ goto found;
-+ continue;
-+ case 3:
-+ if (!(__per_cpu_idtrs[cpu][0][i].pte & 0x1) &&
-+ !(__per_cpu_idtrs[cpu][1][i].pte & 0x1))
-+ goto found;
-+ continue;
-+ default:
-+ r = -EINVAL;
-+ goto out;
++void kvm_sal_emul(struct kvm_vcpu *vcpu)
++{
++
++ struct sal_ret_values result;
++ u64 index, in1, in2, in3, in4, in5, in6, in7;
++
++ kvm_get_sal_call_data(vcpu, &index, &in1, &in2,
++ &in3, &in4, &in5, &in6, &in7);
++ result = sal_emulator(vcpu->kvm, index, in1, in2, in3,
++ in4, in5, in6, in7);
++ set_sal_result(vcpu, result);
++}
+diff --git a/arch/ia64/kvm/kvm_minstate.h b/arch/ia64/kvm/kvm_minstate.h
+new file mode 100644
+index 0000000..13980d9
+--- /dev/null
++++ b/arch/ia64/kvm/kvm_minstate.h
+@@ -0,0 +1,273 @@
++/*
++ * kvm_minstate.h: min save macros
++ * Copyright (c) 2007, Intel Corporation.
++ *
++ * Xuefei Xu (Anthony Xu) (Anthony.xu at intel.com)
++ * Xiantao Zhang (xiantao.zhang at intel.com)
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You 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 <asm/asmmacro.h>
++#include <asm/types.h>
++#include <asm/kregs.h>
++#include "asm-offsets.h"
++
++#define KVM_MINSTATE_START_SAVE_MIN \
++ mov ar.rsc = 0;/* set enforced lazy mode, pl 0, little-endian, loadrs=0 */\
++ ;; \
++ mov.m r28 = ar.rnat; \
++ addl r22 = VMM_RBS_OFFSET,r1; /* compute base of RBS */ \
++ ;; \
++ lfetch.fault.excl.nt1 [r22]; \
++ addl r1 = IA64_STK_OFFSET-VMM_PT_REGS_SIZE,r1; /* compute base of memory stack */ \
++ mov r23 = ar.bspstore; /* save ar.bspstore */ \
++ ;; \
++ mov ar.bspstore = r22; /* switch to kernel RBS */\
++ ;; \
++ mov r18 = ar.bsp; \
++ mov ar.rsc = 0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */
++
++
++
++#define KVM_MINSTATE_END_SAVE_MIN \
++ bsw.1; /* switch back to bank 1 (must be last in insn group) */\
++ ;;
++
++
++#define PAL_VSA_SYNC_READ \
++ /* begin to call pal vps sync_read */ \
++ add r25 = VMM_VPD_BASE_OFFSET, r21; \
++ adds r20 = VMM_VCPU_VSA_BASE_OFFSET, r21; /* entry point */ \
++ ;; \
++ ld8 r25 = [r25]; /* read vpd base */ \
++ ld8 r20 = [r20]; \
++ ;; \
++ add r20 = PAL_VPS_SYNC_READ,r20; \
++ ;; \
++{ .mii; \
++ nop 0x0; \
++ mov r24 = ip; \
++ mov b0 = r20; \
++ ;; \
++}; \
++{ .mmb; \
++ add r24 = 0x20, r24; \
++ nop 0x0; \
++ br.cond.sptk b0; /* call the service */ \
++ ;; \
++};
++
++
++
++#define KVM_MINSTATE_GET_CURRENT(reg) mov reg=r21
++
++/*
++ * KVM_DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves
++ * the minimum state necessary that allows us to turn psr.ic back
++ * on.
++ *
++ * Assumed state upon entry:
++ * psr.ic: off
++ * r31: contains saved predicates (pr)
++ *
++ * Upon exit, the state is as follows:
++ * psr.ic: off
++ * r2 = points to &pt_regs.r16
++ * r8 = contents of ar.ccv
++ * r9 = contents of ar.csd
++ * r10 = contents of ar.ssd
++ * r11 = FPSR_DEFAULT
++ * r12 = kernel sp (kernel virtual address)
++ * r13 = points to current task_struct (kernel virtual address)
++ * p15 = TRUE if psr.i is set in cr.ipsr
++ * predicate registers (other than p2, p3, and p15), b6, r3, r14, r15:
++ * preserved
++ *
++ * Note that psr.ic is NOT turned on by this macro. This is so that
++ * we can pass interruption state as arguments to a handler.
++ */
++
++
++#define PT(f) (VMM_PT_REGS_##f##_OFFSET)
++
++#define KVM_DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA) \
++ KVM_MINSTATE_GET_CURRENT(r16); /* M (or M;;I) */ \
++ mov r27 = ar.rsc; /* M */ \
++ mov r20 = r1; /* A */ \
++ mov r25 = ar.unat; /* M */ \
++ mov r29 = cr.ipsr; /* M */ \
++ mov r26 = ar.pfs; /* I */ \
++ mov r18 = cr.isr; \
++ COVER; /* B;; (or nothing) */ \
++ ;; \
++ tbit.z p0,p15 = r29,IA64_PSR_I_BIT; \
++ mov r1 = r16; \
++/* mov r21=r16; */ \
++ /* switch from user to kernel RBS: */ \
++ ;; \
++ invala; /* M */ \
++ SAVE_IFS; \
++ ;; \
++ KVM_MINSTATE_START_SAVE_MIN \
++ adds r17 = 2*L1_CACHE_BYTES,r1;/* cache-line size */ \
++ adds r16 = PT(CR_IPSR),r1; \
++ ;; \
++ lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES; \
++ st8 [r16] = r29; /* save cr.ipsr */ \
++ ;; \
++ lfetch.fault.excl.nt1 [r17]; \
++ tbit.nz p15,p0 = r29,IA64_PSR_I_BIT; \
++ mov r29 = b0 \
++ ;; \
++ adds r16 = PT(R8),r1; /* initialize first base pointer */\
++ adds r17 = PT(R9),r1; /* initialize second base pointer */\
++ ;; \
++.mem.offset 0,0; st8.spill [r16] = r8,16; \
++.mem.offset 8,0; st8.spill [r17] = r9,16; \
++ ;; \
++.mem.offset 0,0; st8.spill [r16] = r10,24; \
++.mem.offset 8,0; st8.spill [r17] = r11,24; \
++ ;; \
++ mov r9 = cr.iip; /* M */ \
++ mov r10 = ar.fpsr; /* M */ \
++ ;; \
++ st8 [r16] = r9,16; /* save cr.iip */ \
++ st8 [r17] = r30,16; /* save cr.ifs */ \
++ sub r18 = r18,r22; /* r18=RSE.ndirty*8 */ \
++ ;; \
++ st8 [r16] = r25,16; /* save ar.unat */ \
++ st8 [r17] = r26,16; /* save ar.pfs */ \
++ shl r18 = r18,16; /* calu ar.rsc used for "loadrs" */\
++ ;; \
++ st8 [r16] = r27,16; /* save ar.rsc */ \
++ st8 [r17] = r28,16; /* save ar.rnat */ \
++ ;; /* avoid RAW on r16 & r17 */ \
++ st8 [r16] = r23,16; /* save ar.bspstore */ \
++ st8 [r17] = r31,16; /* save predicates */ \
++ ;; \
++ st8 [r16] = r29,16; /* save b0 */ \
++ st8 [r17] = r18,16; /* save ar.rsc value for "loadrs" */\
++ ;; \
++.mem.offset 0,0; st8.spill [r16] = r20,16;/* save original r1 */ \
++.mem.offset 8,0; st8.spill [r17] = r12,16; \
++ adds r12 = -16,r1; /* switch to kernel memory stack */ \
++ ;; \
++.mem.offset 0,0; st8.spill [r16] = r13,16; \
++.mem.offset 8,0; st8.spill [r17] = r10,16; /* save ar.fpsr */\
++ mov r13 = r21; /* establish `current' */ \
++ ;; \
++.mem.offset 0,0; st8.spill [r16] = r15,16; \
++.mem.offset 8,0; st8.spill [r17] = r14,16; \
++ ;; \
++.mem.offset 0,0; st8.spill [r16] = r2,16; \
++.mem.offset 8,0; st8.spill [r17] = r3,16; \
++ adds r2 = VMM_PT_REGS_R16_OFFSET,r1; \
++ ;; \
++ adds r16 = VMM_VCPU_IIPA_OFFSET,r13; \
++ adds r17 = VMM_VCPU_ISR_OFFSET,r13; \
++ mov r26 = cr.iipa; \
++ mov r27 = cr.isr; \
++ ;; \
++ st8 [r16] = r26; \
++ st8 [r17] = r27; \
++ ;; \
++ EXTRA; \
++ mov r8 = ar.ccv; \
++ mov r9 = ar.csd; \
++ mov r10 = ar.ssd; \
++ movl r11 = FPSR_DEFAULT; /* L-unit */ \
++ adds r17 = VMM_VCPU_GP_OFFSET,r13; \
++ ;; \
++ ld8 r1 = [r17];/* establish kernel global pointer */ \
++ ;; \
++ PAL_VSA_SYNC_READ \
++ KVM_MINSTATE_END_SAVE_MIN
++
++/*
++ * SAVE_REST saves the remainder of pt_regs (with psr.ic on).
++ *
++ * Assumed state upon entry:
++ * psr.ic: on
++ * r2: points to &pt_regs.f6
++ * r3: points to &pt_regs.f7
++ * r8: contents of ar.ccv
++ * r9: contents of ar.csd
++ * r10: contents of ar.ssd
++ * r11: FPSR_DEFAULT
++ *
++ * Registers r14 and r15 are guaranteed not to be touched by SAVE_REST.
++ */
++#define KVM_SAVE_REST \
++.mem.offset 0,0; st8.spill [r2] = r16,16; \
++.mem.offset 8,0; st8.spill [r3] = r17,16; \
++ ;; \
++.mem.offset 0,0; st8.spill [r2] = r18,16; \
++.mem.offset 8,0; st8.spill [r3] = r19,16; \
++ ;; \
++.mem.offset 0,0; st8.spill [r2] = r20,16; \
++.mem.offset 8,0; st8.spill [r3] = r21,16; \
++ mov r18=b6; \
++ ;; \
++.mem.offset 0,0; st8.spill [r2] = r22,16; \
++.mem.offset 8,0; st8.spill [r3] = r23,16; \
++ mov r19 = b7; \
++ ;; \
++.mem.offset 0,0; st8.spill [r2] = r24,16; \
++.mem.offset 8,0; st8.spill [r3] = r25,16; \
++ ;; \
++.mem.offset 0,0; st8.spill [r2] = r26,16; \
++.mem.offset 8,0; st8.spill [r3] = r27,16; \
++ ;; \
++.mem.offset 0,0; st8.spill [r2] = r28,16; \
++.mem.offset 8,0; st8.spill [r3] = r29,16; \
++ ;; \
++.mem.offset 0,0; st8.spill [r2] = r30,16; \
++.mem.offset 8,0; st8.spill [r3] = r31,32; \
++ ;; \
++ mov ar.fpsr = r11; \
++ st8 [r2] = r8,8; \
++ adds r24 = PT(B6)-PT(F7),r3; \
++ adds r25 = PT(B7)-PT(F7),r3; \
++ ;; \
++ st8 [r24] = r18,16; /* b6 */ \
++ st8 [r25] = r19,16; /* b7 */ \
++ adds r2 = PT(R4)-PT(F6),r2; \
++ adds r3 = PT(R5)-PT(F7),r3; \
++ ;; \
++ st8 [r24] = r9; /* ar.csd */ \
++ st8 [r25] = r10; /* ar.ssd */ \
++ ;; \
++ mov r18 = ar.unat; \
++ adds r19 = PT(EML_UNAT)-PT(R4),r2; \
++ ;; \
++ st8 [r19] = r18; /* eml_unat */ \
++
++
++#define KVM_SAVE_EXTRA \
++.mem.offset 0,0; st8.spill [r2] = r4,16; \
++.mem.offset 8,0; st8.spill [r3] = r5,16; \
++ ;; \
++.mem.offset 0,0; st8.spill [r2] = r6,16; \
++.mem.offset 8,0; st8.spill [r3] = r7; \
++ ;; \
++ mov r26 = ar.unat; \
++ ;; \
++ st8 [r2] = r26;/* eml_unat */ \
++
++#define KVM_SAVE_MIN_WITH_COVER KVM_DO_SAVE_MIN(cover, mov r30 = cr.ifs,)
++#define KVM_SAVE_MIN_WITH_COVER_R19 KVM_DO_SAVE_MIN(cover, mov r30 = cr.ifs, mov r15 = r19)
++#define KVM_SAVE_MIN KVM_DO_SAVE_MIN( , mov r30 = r0, )
+diff --git a/arch/ia64/kvm/lapic.h b/arch/ia64/kvm/lapic.h
+new file mode 100644
+index 0000000..6d6cbcb
+--- /dev/null
++++ b/arch/ia64/kvm/lapic.h
+@@ -0,0 +1,25 @@
++#ifndef __KVM_IA64_LAPIC_H
++#define __KVM_IA64_LAPIC_H
++
++#include <linux/kvm_host.h>
++
++/*
++ * vlsapic
++ */
++struct kvm_lapic{
++ struct kvm_vcpu *vcpu;
++ uint64_t insvc[4];
++ uint64_t vhpi;
++ uint8_t xtp;
++ uint8_t pal_init_pending;
++ uint8_t pad[2];
++};
++
++int kvm_create_lapic(struct kvm_vcpu *vcpu);
++void kvm_free_lapic(struct kvm_vcpu *vcpu);
++
++int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
++int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
++int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig);
++
++#endif
+diff --git a/arch/ia64/kvm/misc.h b/arch/ia64/kvm/misc.h
+new file mode 100644
+index 0000000..e585c46
+--- /dev/null
++++ b/arch/ia64/kvm/misc.h
+@@ -0,0 +1,93 @@
++#ifndef __KVM_IA64_MISC_H
++#define __KVM_IA64_MISC_H
++
++#include <linux/kvm_host.h>
++/*
++ * misc.h
++ * Copyright (C) 2007, Intel Corporation.
++ * Xiantao Zhang (xiantao.zhang at intel.com)
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You 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.
++ *
++ */
++
++/*
++ *Return p2m base address at host side!
++ */
++static inline uint64_t *kvm_host_get_pmt(struct kvm *kvm)
++{
++ return (uint64_t *)(kvm->arch.vm_base + KVM_P2M_OFS);
++}
++
++static inline void kvm_set_pmt_entry(struct kvm *kvm, gfn_t gfn,
++ u64 paddr, u64 mem_flags)
++{
++ uint64_t *pmt_base = kvm_host_get_pmt(kvm);
++ unsigned long pte;
++
++ pte = PAGE_ALIGN(paddr) | mem_flags;
++ pmt_base[gfn] = pte;
++}
++
++/*Function for translating host address to guest address*/
++
++static inline void *to_guest(struct kvm *kvm, void *addr)
++{
++ return (void *)((unsigned long)(addr) - kvm->arch.vm_base +
++ KVM_VM_DATA_BASE);
++}
++
++/*Function for translating guest address to host address*/
++
++static inline void *to_host(struct kvm *kvm, void *addr)
++{
++ return (void *)((unsigned long)addr - KVM_VM_DATA_BASE
++ + kvm->arch.vm_base);
++}
++
++/* Get host context of the vcpu */
++static inline union context *kvm_get_host_context(struct kvm_vcpu *vcpu)
++{
++ union context *ctx = &vcpu->arch.host;
++ return to_guest(vcpu->kvm, ctx);
++}
++
++/* Get guest context of the vcpu */
++static inline union context *kvm_get_guest_context(struct kvm_vcpu *vcpu)
++{
++ union context *ctx = &vcpu->arch.guest;
++ return to_guest(vcpu->kvm, ctx);
++}
++
++/* kvm get exit data from gvmm! */
++static inline struct exit_ctl_data *kvm_get_exit_data(struct kvm_vcpu *vcpu)
++{
++ return &vcpu->arch.exit_data;
++}
++
++/*kvm get vcpu ioreq for kvm module!*/
++static inline struct kvm_mmio_req *kvm_get_vcpu_ioreq(struct kvm_vcpu *vcpu)
++{
++ struct exit_ctl_data *p_ctl_data;
++
++ if (vcpu) {
++ p_ctl_data = kvm_get_exit_data(vcpu);
++ if (p_ctl_data->exit_reason == EXIT_REASON_MMIO_INSTRUCTION)
++ return &p_ctl_data->u.ioreq;
++ }
++
++ return NULL;
++}
++
++#endif
+diff --git a/arch/ia64/kvm/mmio.c b/arch/ia64/kvm/mmio.c
+new file mode 100644
+index 0000000..351bf70
+--- /dev/null
++++ b/arch/ia64/kvm/mmio.c
+@@ -0,0 +1,341 @@
++/*
++ * mmio.c: MMIO emulation components.
++ * Copyright (c) 2004, Intel Corporation.
++ * Yaozu Dong (Eddie Dong) (Eddie.dong at intel.com)
++ * Kun Tian (Kevin Tian) (Kevin.tian at intel.com)
++ *
++ * Copyright (c) 2007 Intel Corporation KVM support.
++ * Xuefei Xu (Anthony Xu) (anthony.xu at intel.com)
++ * Xiantao Zhang (xiantao.zhang at intel.com)
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
++ * Place - Suite 330, Boston, MA 02111-1307 USA.
++ *
++ */
++
++#include <linux/kvm_host.h>
++
++#include "vcpu.h"
++
++static void vlsapic_write_xtp(struct kvm_vcpu *v, uint8_t val)
++{
++ VLSAPIC_XTP(v) = val;
++}
++
++/*
++ * LSAPIC OFFSET
++ */
++#define PIB_LOW_HALF(ofst) !(ofst & (1 << 20))
++#define PIB_OFST_INTA 0x1E0000
++#define PIB_OFST_XTP 0x1E0008
++
++/*
++ * execute write IPI op.
++ */
++static void vlsapic_write_ipi(struct kvm_vcpu *vcpu,
++ uint64_t addr, uint64_t data)
++{
++ struct exit_ctl_data *p = ¤t_vcpu->arch.exit_data;
++ unsigned long psr;
++
++ local_irq_save(psr);
++
++ p->exit_reason = EXIT_REASON_IPI;
++ p->u.ipi_data.addr.val = addr;
++ p->u.ipi_data.data.val = data;
++ vmm_transition(current_vcpu);
++
++ local_irq_restore(psr);
++
++}
++
++void lsapic_write(struct kvm_vcpu *v, unsigned long addr,
++ unsigned long length, unsigned long val)
++{
++ addr &= (PIB_SIZE - 1);
++
++ switch (addr) {
++ case PIB_OFST_INTA:
++ /*panic_domain(NULL, "Undefined write on PIB INTA\n");*/
++ panic_vm(v);
++ break;
++ case PIB_OFST_XTP:
++ if (length == 1) {
++ vlsapic_write_xtp(v, val);
++ } else {
++ /*panic_domain(NULL,
++ "Undefined write on PIB XTP\n");*/
++ panic_vm(v);
++ }
++ break;
++ default:
++ if (PIB_LOW_HALF(addr)) {
++ /*lower half */
++ if (length != 8)
++ /*panic_domain(NULL,
++ "Can't LHF write with size %ld!\n",
++ length);*/
++ panic_vm(v);
++ else
++ vlsapic_write_ipi(v, addr, val);
++ } else { /* upper half
++ printk("IPI-UHF write %lx\n",addr);*/
++ panic_vm(v);
+ }
++ break;
+ }
-+found:
-+ if (i >= per_cpu(ia64_tr_num, cpu))
-+ return -EBUSY;
++}
+
-+ /*Record tr info for mca hander use!*/
-+ if (i > per_cpu(ia64_tr_used, cpu))
-+ per_cpu(ia64_tr_used, cpu) = i;
++unsigned long lsapic_read(struct kvm_vcpu *v, unsigned long addr,
++ unsigned long length)
++{
++ uint64_t result = 0;
+
-+ psr = ia64_clear_ic();
-+ if (target_mask & 0x1) {
-+ ia64_itr(0x1, i, va, pte, log_size);
-+ ia64_srlz_i();
-+ p = &__per_cpu_idtrs[cpu][0][i];
-+ p->ifa = va;
-+ p->pte = pte;
-+ p->itir = log_size << 2;
-+ p->rr = ia64_get_rr(va);
++ addr &= (PIB_SIZE - 1);
++
++ switch (addr) {
++ case PIB_OFST_INTA:
++ if (length == 1) /* 1 byte load */
++ ; /* There is no i8259, there is no INTA access*/
++ else
++ /*panic_domain(NULL,"Undefined read on PIB INTA\n"); */
++ panic_vm(v);
++
++ break;
++ case PIB_OFST_XTP:
++ if (length == 1) {
++ result = VLSAPIC_XTP(v);
++ /* printk("read xtp %lx\n", result); */
++ } else {
++ /*panic_domain(NULL,
++ "Undefined read on PIB XTP\n");*/
++ panic_vm(v);
++ }
++ break;
++ default:
++ panic_vm(v);
++ break;
+ }
-+ if (target_mask & 0x2) {
-+ ia64_itr(0x2, i, va, pte, log_size);
-+ ia64_srlz_i();
-+ p = &__per_cpu_idtrs[cpu][1][i];
-+ p->ifa = va;
-+ p->pte = pte;
-+ p->itir = log_size << 2;
-+ p->rr = ia64_get_rr(va);
++ return result;
++}
++
++static void mmio_access(struct kvm_vcpu *vcpu, u64 src_pa, u64 *dest,
++ u16 s, int ma, int dir)
++{
++ unsigned long iot;
++ struct exit_ctl_data *p = &vcpu->arch.exit_data;
++ unsigned long psr;
++
++ iot = __gpfn_is_io(src_pa >> PAGE_SHIFT);
++
++ local_irq_save(psr);
++
++ /*Intercept the acces for PIB range*/
++ if (iot == GPFN_PIB) {
++ if (!dir)
++ lsapic_write(vcpu, src_pa, s, *dest);
++ else
++ *dest = lsapic_read(vcpu, src_pa, s);
++ goto out;
+ }
-+ ia64_set_psr(psr);
-+ r = i;
++ p->exit_reason = EXIT_REASON_MMIO_INSTRUCTION;
++ p->u.ioreq.addr = src_pa;
++ p->u.ioreq.size = s;
++ p->u.ioreq.dir = dir;
++ if (dir == IOREQ_WRITE)
++ p->u.ioreq.data = *dest;
++ p->u.ioreq.state = STATE_IOREQ_READY;
++ vmm_transition(vcpu);
++
++ if (p->u.ioreq.state == STATE_IORESP_READY) {
++ if (dir == IOREQ_READ)
++ *dest = p->u.ioreq.data;
++ } else
++ panic_vm(vcpu);
+out:
-+ return r;
++ local_irq_restore(psr);
++ return ;
+}
-+EXPORT_SYMBOL_GPL(ia64_itr_entry);
+
+/*
-+ * ia64_purge_tr
++ dir 1: read 0:write
++ inst_type 0:integer 1:floating point
++ */
++#define SL_INTEGER 0 /* store/load interger*/
++#define SL_FLOATING 1 /* store/load floating*/
++
++void emulate_io_inst(struct kvm_vcpu *vcpu, u64 padr, u64 ma)
++{
++ struct kvm_pt_regs *regs;
++ IA64_BUNDLE bundle;
++ int slot, dir = 0;
++ int inst_type = -1;
++ u16 size = 0;
++ u64 data, slot1a, slot1b, temp, update_reg;
++ s32 imm;
++ INST64 inst;
++
++ regs = vcpu_regs(vcpu);
++
++ if (fetch_code(vcpu, regs->cr_iip, &bundle)) {
++ /* if fetch code fail, return and try again */
++ return;
++ }
++ slot = ((struct ia64_psr *)&(regs->cr_ipsr))->ri;
++ if (!slot)
++ inst.inst = bundle.slot0;
++ else if (slot == 1) {
++ slot1a = bundle.slot1a;
++ slot1b = bundle.slot1b;
++ inst.inst = slot1a + (slot1b << 18);
++ } else if (slot == 2)
++ inst.inst = bundle.slot2;
++
++ /* Integer Load/Store */
++ if (inst.M1.major == 4 && inst.M1.m == 0 && inst.M1.x == 0) {
++ inst_type = SL_INTEGER;
++ size = (inst.M1.x6 & 0x3);
++ if ((inst.M1.x6 >> 2) > 0xb) {
++ /*write*/
++ dir = IOREQ_WRITE;
++ data = vcpu_get_gr(vcpu, inst.M4.r2);
++ } else if ((inst.M1.x6 >> 2) < 0xb) {
++ /*read*/
++ dir = IOREQ_READ;
++ }
++ } else if (inst.M2.major == 4 && inst.M2.m == 1 && inst.M2.x == 0) {
++ /* Integer Load + Reg update */
++ inst_type = SL_INTEGER;
++ dir = IOREQ_READ;
++ size = (inst.M2.x6 & 0x3);
++ temp = vcpu_get_gr(vcpu, inst.M2.r3);
++ update_reg = vcpu_get_gr(vcpu, inst.M2.r2);
++ temp += update_reg;
++ vcpu_set_gr(vcpu, inst.M2.r3, temp, 0);
++ } else if (inst.M3.major == 5) {
++ /*Integer Load/Store + Imm update*/
++ inst_type = SL_INTEGER;
++ size = (inst.M3.x6&0x3);
++ if ((inst.M5.x6 >> 2) > 0xb) {
++ /*write*/
++ dir = IOREQ_WRITE;
++ data = vcpu_get_gr(vcpu, inst.M5.r2);
++ temp = vcpu_get_gr(vcpu, inst.M5.r3);
++ imm = (inst.M5.s << 31) | (inst.M5.i << 30) |
++ (inst.M5.imm7 << 23);
++ temp += imm >> 23;
++ vcpu_set_gr(vcpu, inst.M5.r3, temp, 0);
++
++ } else if ((inst.M3.x6 >> 2) < 0xb) {
++ /*read*/
++ dir = IOREQ_READ;
++ temp = vcpu_get_gr(vcpu, inst.M3.r3);
++ imm = (inst.M3.s << 31) | (inst.M3.i << 30) |
++ (inst.M3.imm7 << 23);
++ temp += imm >> 23;
++ vcpu_set_gr(vcpu, inst.M3.r3, temp, 0);
++
++ }
++ } else if (inst.M9.major == 6 && inst.M9.x6 == 0x3B
++ && inst.M9.m == 0 && inst.M9.x == 0) {
++ /* Floating-point spill*/
++ struct ia64_fpreg v;
++
++ inst_type = SL_FLOATING;
++ dir = IOREQ_WRITE;
++ vcpu_get_fpreg(vcpu, inst.M9.f2, &v);
++ /* Write high word. FIXME: this is a kludge! */
++ v.u.bits[1] &= 0x3ffff;
++ mmio_access(vcpu, padr + 8, &v.u.bits[1], 8, ma, IOREQ_WRITE);
++ data = v.u.bits[0];
++ size = 3;
++ } else if (inst.M10.major == 7 && inst.M10.x6 == 0x3B) {
++ /* Floating-point spill + Imm update */
++ struct ia64_fpreg v;
++
++ inst_type = SL_FLOATING;
++ dir = IOREQ_WRITE;
++ vcpu_get_fpreg(vcpu, inst.M10.f2, &v);
++ temp = vcpu_get_gr(vcpu, inst.M10.r3);
++ imm = (inst.M10.s << 31) | (inst.M10.i << 30) |
++ (inst.M10.imm7 << 23);
++ temp += imm >> 23;
++ vcpu_set_gr(vcpu, inst.M10.r3, temp, 0);
++
++ /* Write high word.FIXME: this is a kludge! */
++ v.u.bits[1] &= 0x3ffff;
++ mmio_access(vcpu, padr + 8, &v.u.bits[1], 8, ma, IOREQ_WRITE);
++ data = v.u.bits[0];
++ size = 3;
++ } else if (inst.M10.major == 7 && inst.M10.x6 == 0x31) {
++ /* Floating-point stf8 + Imm update */
++ struct ia64_fpreg v;
++ inst_type = SL_FLOATING;
++ dir = IOREQ_WRITE;
++ size = 3;
++ vcpu_get_fpreg(vcpu, inst.M10.f2, &v);
++ data = v.u.bits[0]; /* Significand. */
++ temp = vcpu_get_gr(vcpu, inst.M10.r3);
++ imm = (inst.M10.s << 31) | (inst.M10.i << 30) |
++ (inst.M10.imm7 << 23);
++ temp += imm >> 23;
++ vcpu_set_gr(vcpu, inst.M10.r3, temp, 0);
++ } else if (inst.M15.major == 7 && inst.M15.x6 >= 0x2c
++ && inst.M15.x6 <= 0x2f) {
++ temp = vcpu_get_gr(vcpu, inst.M15.r3);
++ imm = (inst.M15.s << 31) | (inst.M15.i << 30) |
++ (inst.M15.imm7 << 23);
++ temp += imm >> 23;
++ vcpu_set_gr(vcpu, inst.M15.r3, temp, 0);
++
++ vcpu_increment_iip(vcpu);
++ return;
++ } else if (inst.M12.major == 6 && inst.M12.m == 1
++ && inst.M12.x == 1 && inst.M12.x6 == 1) {
++ /* Floating-point Load Pair + Imm ldfp8 M12*/
++ struct ia64_fpreg v;
++
++ inst_type = SL_FLOATING;
++ dir = IOREQ_READ;
++ size = 8; /*ldfd*/
++ mmio_access(vcpu, padr, &data, size, ma, dir);
++ v.u.bits[0] = data;
++ v.u.bits[1] = 0x1003E;
++ vcpu_set_fpreg(vcpu, inst.M12.f1, &v);
++ padr += 8;
++ mmio_access(vcpu, padr, &data, size, ma, dir);
++ v.u.bits[0] = data;
++ v.u.bits[1] = 0x1003E;
++ vcpu_set_fpreg(vcpu, inst.M12.f2, &v);
++ padr += 8;
++ vcpu_set_gr(vcpu, inst.M12.r3, padr, 0);
++ vcpu_increment_iip(vcpu);
++ return;
++ } else {
++ inst_type = -1;
++ panic_vm(vcpu);
++ }
++
++ size = 1 << size;
++ if (dir == IOREQ_WRITE) {
++ mmio_access(vcpu, padr, &data, size, ma, dir);
++ } else {
++ mmio_access(vcpu, padr, &data, size, ma, dir);
++ if (inst_type == SL_INTEGER)
++ vcpu_set_gr(vcpu, inst.M1.r1, data, 0);
++ else
++ panic_vm(vcpu);
++
++ }
++ vcpu_increment_iip(vcpu);
++}
+diff --git a/arch/ia64/kvm/optvfault.S b/arch/ia64/kvm/optvfault.S
+new file mode 100644
+index 0000000..e4f15d6
+--- /dev/null
++++ b/arch/ia64/kvm/optvfault.S
+@@ -0,0 +1,918 @@
++/*
++ * arch/ia64/vmx/optvfault.S
++ * optimize virtualization fault handler
+ *
-+ * target_mask: 0x1: purge itr, 0x2 : purge dtr, 0x3 purge idtr.
-+ * slot: slot number to be freed.
++ * Copyright (C) 2006 Intel Co
++ * Xuefei Xu (Anthony Xu) <anthony.xu at intel.com>
++ */
++
++#include <asm/asmmacro.h>
++#include <asm/processor.h>
++
++#include "vti.h"
++#include "asm-offsets.h"
++
++#define ACCE_MOV_FROM_AR
++#define ACCE_MOV_FROM_RR
++#define ACCE_MOV_TO_RR
++#define ACCE_RSM
++#define ACCE_SSM
++#define ACCE_MOV_TO_PSR
++#define ACCE_THASH
++
++//mov r1=ar3
++GLOBAL_ENTRY(kvm_asm_mov_from_ar)
++#ifndef ACCE_MOV_FROM_AR
++ br.many kvm_virtualization_fault_back
++#endif
++ add r18=VMM_VCPU_ITC_OFS_OFFSET, r21
++ add r16=VMM_VCPU_LAST_ITC_OFFSET,r21
++ extr.u r17=r25,6,7
++ ;;
++ ld8 r18=[r18]
++ mov r19=ar.itc
++ mov r24=b0
++ ;;
++ add r19=r19,r18
++ addl r20=@gprel(asm_mov_to_reg),gp
++ ;;
++ st8 [r16] = r19
++ adds r30=kvm_resume_to_guest-asm_mov_to_reg,r20
++ shladd r17=r17,4,r20
++ ;;
++ mov b0=r17
++ br.sptk.few b0
++ ;;
++END(kvm_asm_mov_from_ar)
++
++
++// mov r1=rr[r3]
++GLOBAL_ENTRY(kvm_asm_mov_from_rr)
++#ifndef ACCE_MOV_FROM_RR
++ br.many kvm_virtualization_fault_back
++#endif
++ extr.u r16=r25,20,7
++ extr.u r17=r25,6,7
++ addl r20=@gprel(asm_mov_from_reg),gp
++ ;;
++ adds r30=kvm_asm_mov_from_rr_back_1-asm_mov_from_reg,r20
++ shladd r16=r16,4,r20
++ mov r24=b0
++ ;;
++ add r27=VMM_VCPU_VRR0_OFFSET,r21
++ mov b0=r16
++ br.many b0
++ ;;
++kvm_asm_mov_from_rr_back_1:
++ adds r30=kvm_resume_to_guest-asm_mov_from_reg,r20
++ adds r22=asm_mov_to_reg-asm_mov_from_reg,r20
++ shr.u r26=r19,61
++ ;;
++ shladd r17=r17,4,r22
++ shladd r27=r26,3,r27
++ ;;
++ ld8 r19=[r27]
++ mov b0=r17
++ br.many b0
++END(kvm_asm_mov_from_rr)
++
++
++// mov rr[r3]=r2
++GLOBAL_ENTRY(kvm_asm_mov_to_rr)
++#ifndef ACCE_MOV_TO_RR
++ br.many kvm_virtualization_fault_back
++#endif
++ extr.u r16=r25,20,7
++ extr.u r17=r25,13,7
++ addl r20=@gprel(asm_mov_from_reg),gp
++ ;;
++ adds r30=kvm_asm_mov_to_rr_back_1-asm_mov_from_reg,r20
++ shladd r16=r16,4,r20
++ mov r22=b0
++ ;;
++ add r27=VMM_VCPU_VRR0_OFFSET,r21
++ mov b0=r16
++ br.many b0
++ ;;
++kvm_asm_mov_to_rr_back_1:
++ adds r30=kvm_asm_mov_to_rr_back_2-asm_mov_from_reg,r20
++ shr.u r23=r19,61
++ shladd r17=r17,4,r20
++ ;;
++ //if rr6, go back
++ cmp.eq p6,p0=6,r23
++ mov b0=r22
++ (p6) br.cond.dpnt.many kvm_virtualization_fault_back
++ ;;
++ mov r28=r19
++ mov b0=r17
++ br.many b0
++kvm_asm_mov_to_rr_back_2:
++ adds r30=kvm_resume_to_guest-asm_mov_from_reg,r20
++ shladd r27=r23,3,r27
++ ;; // vrr.rid<<4 |0xe
++ st8 [r27]=r19
++ mov b0=r30
++ ;;
++ extr.u r16=r19,8,26
++ extr.u r18 =r19,2,6
++ mov r17 =0xe
++ ;;
++ shladd r16 = r16, 4, r17
++ extr.u r19 =r19,0,8
++ ;;
++ shl r16 = r16,8
++ ;;
++ add r19 = r19, r16
++ ;; //set ve 1
++ dep r19=-1,r19,0,1
++ cmp.lt p6,p0=14,r18
++ ;;
++ (p6) mov r18=14
++ ;;
++ (p6) dep r19=r18,r19,2,6
++ ;;
++ cmp.eq p6,p0=0,r23
++ ;;
++ cmp.eq.or p6,p0=4,r23
++ ;;
++ adds r16=VMM_VCPU_MODE_FLAGS_OFFSET,r21
++ (p6) adds r17=VMM_VCPU_META_SAVED_RR0_OFFSET,r21
++ ;;
++ ld4 r16=[r16]
++ cmp.eq p7,p0=r0,r0
++ (p6) shladd r17=r23,1,r17
++ ;;
++ (p6) st8 [r17]=r19
++ (p6) tbit.nz p6,p7=r16,0
++ ;;
++ (p7) mov rr[r28]=r19
++ mov r24=r22
++ br.many b0
++END(kvm_asm_mov_to_rr)
++
++
++//rsm
++GLOBAL_ENTRY(kvm_asm_rsm)
++#ifndef ACCE_RSM
++ br.many kvm_virtualization_fault_back
++#endif
++ add r16=VMM_VPD_BASE_OFFSET,r21
++ extr.u r26=r25,6,21
++ extr.u r27=r25,31,2
++ ;;
++ ld8 r16=[r16]
++ extr.u r28=r25,36,1
++ dep r26=r27,r26,21,2
++ ;;
++ add r17=VPD_VPSR_START_OFFSET,r16
++ add r22=VMM_VCPU_MODE_FLAGS_OFFSET,r21
++ //r26 is imm24
++ dep r26=r28,r26,23,1
++ ;;
++ ld8 r18=[r17]
++ movl r28=IA64_PSR_IC+IA64_PSR_I+IA64_PSR_DT+IA64_PSR_SI
++ ld4 r23=[r22]
++ sub r27=-1,r26
++ mov r24=b0
++ ;;
++ mov r20=cr.ipsr
++ or r28=r27,r28
++ and r19=r18,r27
++ ;;
++ st8 [r17]=r19
++ and r20=r20,r28
++ /* Comment it out due to short of fp lazy alorgithm support
++ adds r27=IA64_VCPU_FP_PSR_OFFSET,r21
++ ;;
++ ld8 r27=[r27]
++ ;;
++ tbit.nz p8,p0= r27,IA64_PSR_DFH_BIT
++ ;;
++ (p8) dep r20=-1,r20,IA64_PSR_DFH_BIT,1
++ */
++ ;;
++ mov cr.ipsr=r20
++ tbit.nz p6,p0=r23,0
++ ;;
++ tbit.z.or p6,p0=r26,IA64_PSR_DT_BIT
++ (p6) br.dptk kvm_resume_to_guest
++ ;;
++ add r26=VMM_VCPU_META_RR0_OFFSET,r21
++ add r27=VMM_VCPU_META_RR0_OFFSET+8,r21
++ dep r23=-1,r23,0,1
++ ;;
++ ld8 r26=[r26]
++ ld8 r27=[r27]
++ st4 [r22]=r23
++ dep.z r28=4,61,3
++ ;;
++ mov rr[r0]=r26
++ ;;
++ mov rr[r28]=r27
++ ;;
++ srlz.d
++ br.many kvm_resume_to_guest
++END(kvm_asm_rsm)
++
++
++//ssm
++GLOBAL_ENTRY(kvm_asm_ssm)
++#ifndef ACCE_SSM
++ br.many kvm_virtualization_fault_back
++#endif
++ add r16=VMM_VPD_BASE_OFFSET,r21
++ extr.u r26=r25,6,21
++ extr.u r27=r25,31,2
++ ;;
++ ld8 r16=[r16]
++ extr.u r28=r25,36,1
++ dep r26=r27,r26,21,2
++ ;; //r26 is imm24
++ add r27=VPD_VPSR_START_OFFSET,r16
++ dep r26=r28,r26,23,1
++ ;; //r19 vpsr
++ ld8 r29=[r27]
++ mov r24=b0
++ ;;
++ add r22=VMM_VCPU_MODE_FLAGS_OFFSET,r21
++ mov r20=cr.ipsr
++ or r19=r29,r26
++ ;;
++ ld4 r23=[r22]
++ st8 [r27]=r19
++ or r20=r20,r26
++ ;;
++ mov cr.ipsr=r20
++ movl r28=IA64_PSR_DT+IA64_PSR_RT+IA64_PSR_IT
++ ;;
++ and r19=r28,r19
++ tbit.z p6,p0=r23,0
++ ;;
++ cmp.ne.or p6,p0=r28,r19
++ (p6) br.dptk kvm_asm_ssm_1
++ ;;
++ add r26=VMM_VCPU_META_SAVED_RR0_OFFSET,r21
++ add r27=VMM_VCPU_META_SAVED_RR0_OFFSET+8,r21
++ dep r23=0,r23,0,1
++ ;;
++ ld8 r26=[r26]
++ ld8 r27=[r27]
++ st4 [r22]=r23
++ dep.z r28=4,61,3
++ ;;
++ mov rr[r0]=r26
++ ;;
++ mov rr[r28]=r27
++ ;;
++ srlz.d
++ ;;
++kvm_asm_ssm_1:
++ tbit.nz p6,p0=r29,IA64_PSR_I_BIT
++ ;;
++ tbit.z.or p6,p0=r19,IA64_PSR_I_BIT
++ (p6) br.dptk kvm_resume_to_guest
++ ;;
++ add r29=VPD_VTPR_START_OFFSET,r16
++ add r30=VPD_VHPI_START_OFFSET,r16
++ ;;
++ ld8 r29=[r29]
++ ld8 r30=[r30]
++ ;;
++ extr.u r17=r29,4,4
++ extr.u r18=r29,16,1
++ ;;
++ dep r17=r18,r17,4,1
++ ;;
++ cmp.gt p6,p0=r30,r17
++ (p6) br.dpnt.few kvm_asm_dispatch_vexirq
++ br.many kvm_resume_to_guest
++END(kvm_asm_ssm)
++
++
++//mov psr.l=r2
++GLOBAL_ENTRY(kvm_asm_mov_to_psr)
++#ifndef ACCE_MOV_TO_PSR
++ br.many kvm_virtualization_fault_back
++#endif
++ add r16=VMM_VPD_BASE_OFFSET,r21
++ extr.u r26=r25,13,7 //r2
++ ;;
++ ld8 r16=[r16]
++ addl r20=@gprel(asm_mov_from_reg),gp
++ ;;
++ adds r30=kvm_asm_mov_to_psr_back-asm_mov_from_reg,r20
++ shladd r26=r26,4,r20
++ mov r24=b0
++ ;;
++ add r27=VPD_VPSR_START_OFFSET,r16
++ mov b0=r26
++ br.many b0
++ ;;
++kvm_asm_mov_to_psr_back:
++ ld8 r17=[r27]
++ add r22=VMM_VCPU_MODE_FLAGS_OFFSET,r21
++ dep r19=0,r19,32,32
++ ;;
++ ld4 r23=[r22]
++ dep r18=0,r17,0,32
++ ;;
++ add r30=r18,r19
++ movl r28=IA64_PSR_DT+IA64_PSR_RT+IA64_PSR_IT
++ ;;
++ st8 [r27]=r30
++ and r27=r28,r30
++ and r29=r28,r17
++ ;;
++ cmp.eq p5,p0=r29,r27
++ cmp.eq p6,p7=r28,r27
++ (p5) br.many kvm_asm_mov_to_psr_1
++ ;;
++ //virtual to physical
++ (p7) add r26=VMM_VCPU_META_RR0_OFFSET,r21
++ (p7) add r27=VMM_VCPU_META_RR0_OFFSET+8,r21
++ (p7) dep r23=-1,r23,0,1
++ ;;
++ //physical to virtual
++ (p6) add r26=VMM_VCPU_META_SAVED_RR0_OFFSET,r21
++ (p6) add r27=VMM_VCPU_META_SAVED_RR0_OFFSET+8,r21
++ (p6) dep r23=0,r23,0,1
++ ;;
++ ld8 r26=[r26]
++ ld8 r27=[r27]
++ st4 [r22]=r23
++ dep.z r28=4,61,3
++ ;;
++ mov rr[r0]=r26
++ ;;
++ mov rr[r28]=r27
++ ;;
++ srlz.d
++ ;;
++kvm_asm_mov_to_psr_1:
++ mov r20=cr.ipsr
++ movl r28=IA64_PSR_IC+IA64_PSR_I+IA64_PSR_DT+IA64_PSR_SI+IA64_PSR_RT
++ ;;
++ or r19=r19,r28
++ dep r20=0,r20,0,32
++ ;;
++ add r20=r19,r20
++ mov b0=r24
++ ;;
++ /* Comment it out due to short of fp lazy algorithm support
++ adds r27=IA64_VCPU_FP_PSR_OFFSET,r21
++ ;;
++ ld8 r27=[r27]
++ ;;
++ tbit.nz p8,p0=r27,IA64_PSR_DFH_BIT
++ ;;
++ (p8) dep r20=-1,r20,IA64_PSR_DFH_BIT,1
++ ;;
++ */
++ mov cr.ipsr=r20
++ cmp.ne p6,p0=r0,r0
++ ;;
++ tbit.nz.or p6,p0=r17,IA64_PSR_I_BIT
++ tbit.z.or p6,p0=r30,IA64_PSR_I_BIT
++ (p6) br.dpnt.few kvm_resume_to_guest
++ ;;
++ add r29=VPD_VTPR_START_OFFSET,r16
++ add r30=VPD_VHPI_START_OFFSET,r16
++ ;;
++ ld8 r29=[r29]
++ ld8 r30=[r30]
++ ;;
++ extr.u r17=r29,4,4
++ extr.u r18=r29,16,1
++ ;;
++ dep r17=r18,r17,4,1
++ ;;
++ cmp.gt p6,p0=r30,r17
++ (p6) br.dpnt.few kvm_asm_dispatch_vexirq
++ br.many kvm_resume_to_guest
++END(kvm_asm_mov_to_psr)
++
++
++ENTRY(kvm_asm_dispatch_vexirq)
++//increment iip
++ mov r16=cr.ipsr
++ ;;
++ extr.u r17=r16,IA64_PSR_RI_BIT,2
++ tbit.nz p6,p7=r16,IA64_PSR_RI_BIT+1
++ ;;
++ (p6) mov r18=cr.iip
++ (p6) mov r17=r0
++ (p7) add r17=1,r17
++ ;;
++ (p6) add r18=0x10,r18
++ dep r16=r17,r16,IA64_PSR_RI_BIT,2
++ ;;
++ (p6) mov cr.iip=r18
++ mov cr.ipsr=r16
++ mov r30 =1
++ br.many kvm_dispatch_vexirq
++END(kvm_asm_dispatch_vexirq)
++
++// thash
++// TODO: add support when pta.vf = 1
++GLOBAL_ENTRY(kvm_asm_thash)
++#ifndef ACCE_THASH
++ br.many kvm_virtualization_fault_back
++#endif
++ extr.u r17=r25,20,7 // get r3 from opcode in r25
++ extr.u r18=r25,6,7 // get r1 from opcode in r25
++ addl r20=@gprel(asm_mov_from_reg),gp
++ ;;
++ adds r30=kvm_asm_thash_back1-asm_mov_from_reg,r20
++ shladd r17=r17,4,r20 // get addr of MOVE_FROM_REG(r17)
++ adds r16=VMM_VPD_BASE_OFFSET,r21 // get vcpu.arch.priveregs
++ ;;
++ mov r24=b0
++ ;;
++ ld8 r16=[r16] // get VPD addr
++ mov b0=r17
++ br.many b0 // r19 return value
++ ;;
++kvm_asm_thash_back1:
++ shr.u r23=r19,61 // get RR number
++ adds r25=VMM_VCPU_VRR0_OFFSET,r21 // get vcpu->arch.vrr[0]'s addr
++ adds r16=VMM_VPD_VPTA_OFFSET,r16 // get vpta
++ ;;
++ shladd r27=r23,3,r25 // get vcpu->arch.vrr[r23]'s addr
++ ld8 r17=[r16] // get PTA
++ mov r26=1
++ ;;
++ extr.u r29=r17,2,6 // get pta.size
++ ld8 r25=[r27] // get vcpu->arch.vrr[r23]'s value
++ ;;
++ extr.u r25=r25,2,6 // get rr.ps
++ shl r22=r26,r29 // 1UL << pta.size
++ ;;
++ shr.u r23=r19,r25 // vaddr >> rr.ps
++ adds r26=3,r29 // pta.size + 3
++ shl r27=r17,3 // pta << 3
++ ;;
++ shl r23=r23,3 // (vaddr >> rr.ps) << 3
++ shr.u r27=r27,r26 // (pta << 3) >> (pta.size+3)
++ movl r16=7<<61
++ ;;
++ adds r22=-1,r22 // (1UL << pta.size) - 1
++ shl r27=r27,r29 // ((pta<<3)>>(pta.size+3))<<pta.size
++ and r19=r19,r16 // vaddr & VRN_MASK
++ ;;
++ and r22=r22,r23 // vhpt_offset
++ or r19=r19,r27 // (vadr&VRN_MASK)|(((pta<<3)>>(pta.size + 3))<<pta.size)
++ adds r26=asm_mov_to_reg-asm_mov_from_reg,r20
++ ;;
++ or r19=r19,r22 // calc pval
++ shladd r17=r18,4,r26
++ adds r30=kvm_resume_to_guest-asm_mov_from_reg,r20
++ ;;
++ mov b0=r17
++ br.many b0
++END(kvm_asm_thash)
++
++#define MOV_TO_REG0 \
++{; \
++ nop.b 0x0; \
++ nop.b 0x0; \
++ nop.b 0x0; \
++ ;; \
++};
++
++
++#define MOV_TO_REG(n) \
++{; \
++ mov r##n##=r19; \
++ mov b0=r30; \
++ br.sptk.many b0; \
++ ;; \
++};
++
++
++#define MOV_FROM_REG(n) \
++{; \
++ mov r19=r##n##; \
++ mov b0=r30; \
++ br.sptk.many b0; \
++ ;; \
++};
++
++
++#define MOV_TO_BANK0_REG(n) \
++ENTRY_MIN_ALIGN(asm_mov_to_bank0_reg##n##); \
++{; \
++ mov r26=r2; \
++ mov r2=r19; \
++ bsw.1; \
++ ;; \
++}; \
++{; \
++ mov r##n##=r2; \
++ nop.b 0x0; \
++ bsw.0; \
++ ;; \
++}; \
++{; \
++ mov r2=r26; \
++ mov b0=r30; \
++ br.sptk.many b0; \
++ ;; \
++}; \
++END(asm_mov_to_bank0_reg##n##)
++
++
++#define MOV_FROM_BANK0_REG(n) \
++ENTRY_MIN_ALIGN(asm_mov_from_bank0_reg##n##); \
++{; \
++ mov r26=r2; \
++ nop.b 0x0; \
++ bsw.1; \
++ ;; \
++}; \
++{; \
++ mov r2=r##n##; \
++ nop.b 0x0; \
++ bsw.0; \
++ ;; \
++}; \
++{; \
++ mov r19=r2; \
++ mov r2=r26; \
++ mov b0=r30; \
++}; \
++{; \
++ nop.b 0x0; \
++ nop.b 0x0; \
++ br.sptk.many b0; \
++ ;; \
++}; \
++END(asm_mov_from_bank0_reg##n##)
++
++
++#define JMP_TO_MOV_TO_BANK0_REG(n) \
++{; \
++ nop.b 0x0; \
++ nop.b 0x0; \
++ br.sptk.many asm_mov_to_bank0_reg##n##; \
++ ;; \
++}
++
++
++#define JMP_TO_MOV_FROM_BANK0_REG(n) \
++{; \
++ nop.b 0x0; \
++ nop.b 0x0; \
++ br.sptk.many asm_mov_from_bank0_reg##n##; \
++ ;; \
++}
++
++
++MOV_FROM_BANK0_REG(16)
++MOV_FROM_BANK0_REG(17)
++MOV_FROM_BANK0_REG(18)
++MOV_FROM_BANK0_REG(19)
++MOV_FROM_BANK0_REG(20)
++MOV_FROM_BANK0_REG(21)
++MOV_FROM_BANK0_REG(22)
++MOV_FROM_BANK0_REG(23)
++MOV_FROM_BANK0_REG(24)
++MOV_FROM_BANK0_REG(25)
++MOV_FROM_BANK0_REG(26)
++MOV_FROM_BANK0_REG(27)
++MOV_FROM_BANK0_REG(28)
++MOV_FROM_BANK0_REG(29)
++MOV_FROM_BANK0_REG(30)
++MOV_FROM_BANK0_REG(31)
++
++
++// mov from reg table
++ENTRY(asm_mov_from_reg)
++ MOV_FROM_REG(0)
++ MOV_FROM_REG(1)
++ MOV_FROM_REG(2)
++ MOV_FROM_REG(3)
++ MOV_FROM_REG(4)
++ MOV_FROM_REG(5)
++ MOV_FROM_REG(6)
++ MOV_FROM_REG(7)
++ MOV_FROM_REG(8)
++ MOV_FROM_REG(9)
++ MOV_FROM_REG(10)
++ MOV_FROM_REG(11)
++ MOV_FROM_REG(12)
++ MOV_FROM_REG(13)
++ MOV_FROM_REG(14)
++ MOV_FROM_REG(15)
++ JMP_TO_MOV_FROM_BANK0_REG(16)
++ JMP_TO_MOV_FROM_BANK0_REG(17)
++ JMP_TO_MOV_FROM_BANK0_REG(18)
++ JMP_TO_MOV_FROM_BANK0_REG(19)
++ JMP_TO_MOV_FROM_BANK0_REG(20)
++ JMP_TO_MOV_FROM_BANK0_REG(21)
++ JMP_TO_MOV_FROM_BANK0_REG(22)
++ JMP_TO_MOV_FROM_BANK0_REG(23)
++ JMP_TO_MOV_FROM_BANK0_REG(24)
++ JMP_TO_MOV_FROM_BANK0_REG(25)
++ JMP_TO_MOV_FROM_BANK0_REG(26)
++ JMP_TO_MOV_FROM_BANK0_REG(27)
++ JMP_TO_MOV_FROM_BANK0_REG(28)
++ JMP_TO_MOV_FROM_BANK0_REG(29)
++ JMP_TO_MOV_FROM_BANK0_REG(30)
++ JMP_TO_MOV_FROM_BANK0_REG(31)
++ MOV_FROM_REG(32)
++ MOV_FROM_REG(33)
++ MOV_FROM_REG(34)
++ MOV_FROM_REG(35)
++ MOV_FROM_REG(36)
++ MOV_FROM_REG(37)
++ MOV_FROM_REG(38)
++ MOV_FROM_REG(39)
++ MOV_FROM_REG(40)
++ MOV_FROM_REG(41)
++ MOV_FROM_REG(42)
++ MOV_FROM_REG(43)
++ MOV_FROM_REG(44)
++ MOV_FROM_REG(45)
++ MOV_FROM_REG(46)
++ MOV_FROM_REG(47)
++ MOV_FROM_REG(48)
++ MOV_FROM_REG(49)
++ MOV_FROM_REG(50)
++ MOV_FROM_REG(51)
++ MOV_FROM_REG(52)
++ MOV_FROM_REG(53)
++ MOV_FROM_REG(54)
++ MOV_FROM_REG(55)
++ MOV_FROM_REG(56)
++ MOV_FROM_REG(57)
++ MOV_FROM_REG(58)
++ MOV_FROM_REG(59)
++ MOV_FROM_REG(60)
++ MOV_FROM_REG(61)
++ MOV_FROM_REG(62)
++ MOV_FROM_REG(63)
++ MOV_FROM_REG(64)
++ MOV_FROM_REG(65)
++ MOV_FROM_REG(66)
++ MOV_FROM_REG(67)
++ MOV_FROM_REG(68)
++ MOV_FROM_REG(69)
++ MOV_FROM_REG(70)
++ MOV_FROM_REG(71)
++ MOV_FROM_REG(72)
++ MOV_FROM_REG(73)
++ MOV_FROM_REG(74)
++ MOV_FROM_REG(75)
++ MOV_FROM_REG(76)
++ MOV_FROM_REG(77)
++ MOV_FROM_REG(78)
++ MOV_FROM_REG(79)
++ MOV_FROM_REG(80)
++ MOV_FROM_REG(81)
++ MOV_FROM_REG(82)
++ MOV_FROM_REG(83)
++ MOV_FROM_REG(84)
++ MOV_FROM_REG(85)
++ MOV_FROM_REG(86)
++ MOV_FROM_REG(87)
++ MOV_FROM_REG(88)
++ MOV_FROM_REG(89)
++ MOV_FROM_REG(90)
++ MOV_FROM_REG(91)
++ MOV_FROM_REG(92)
++ MOV_FROM_REG(93)
++ MOV_FROM_REG(94)
++ MOV_FROM_REG(95)
++ MOV_FROM_REG(96)
++ MOV_FROM_REG(97)
++ MOV_FROM_REG(98)
++ MOV_FROM_REG(99)
++ MOV_FROM_REG(100)
++ MOV_FROM_REG(101)
++ MOV_FROM_REG(102)
++ MOV_FROM_REG(103)
++ MOV_FROM_REG(104)
++ MOV_FROM_REG(105)
++ MOV_FROM_REG(106)
++ MOV_FROM_REG(107)
++ MOV_FROM_REG(108)
++ MOV_FROM_REG(109)
++ MOV_FROM_REG(110)
++ MOV_FROM_REG(111)
++ MOV_FROM_REG(112)
++ MOV_FROM_REG(113)
++ MOV_FROM_REG(114)
++ MOV_FROM_REG(115)
++ MOV_FROM_REG(116)
++ MOV_FROM_REG(117)
++ MOV_FROM_REG(118)
++ MOV_FROM_REG(119)
++ MOV_FROM_REG(120)
++ MOV_FROM_REG(121)
++ MOV_FROM_REG(122)
++ MOV_FROM_REG(123)
++ MOV_FROM_REG(124)
++ MOV_FROM_REG(125)
++ MOV_FROM_REG(126)
++ MOV_FROM_REG(127)
++END(asm_mov_from_reg)
++
++
++/* must be in bank 0
++ * parameter:
++ * r31: pr
++ * r24: b0
++ */
++ENTRY(kvm_resume_to_guest)
++ adds r16 = VMM_VCPU_SAVED_GP_OFFSET,r21
++ ;;
++ ld8 r1 =[r16]
++ adds r20 = VMM_VCPU_VSA_BASE_OFFSET,r21
++ ;;
++ mov r16=cr.ipsr
++ ;;
++ ld8 r20 = [r20]
++ adds r19=VMM_VPD_BASE_OFFSET,r21
++ ;;
++ ld8 r25=[r19]
++ extr.u r17=r16,IA64_PSR_RI_BIT,2
++ tbit.nz p6,p7=r16,IA64_PSR_RI_BIT+1
++ ;;
++ (p6) mov r18=cr.iip
++ (p6) mov r17=r0
++ ;;
++ (p6) add r18=0x10,r18
++ (p7) add r17=1,r17
++ ;;
++ (p6) mov cr.iip=r18
++ dep r16=r17,r16,IA64_PSR_RI_BIT,2
++ ;;
++ mov cr.ipsr=r16
++ adds r19= VPD_VPSR_START_OFFSET,r25
++ add r28=PAL_VPS_RESUME_NORMAL,r20
++ add r29=PAL_VPS_RESUME_HANDLER,r20
++ ;;
++ ld8 r19=[r19]
++ mov b0=r29
++ cmp.ne p6,p7 = r0,r0
++ ;;
++ tbit.z p6,p7 = r19,IA64_PSR_IC_BIT // p1=vpsr.ic
++ ;;
++ (p6) ld8 r26=[r25]
++ (p7) mov b0=r28
++ mov pr=r31,-2
++ br.sptk.many b0 // call pal service
++ ;;
++END(kvm_resume_to_guest)
++
++
++MOV_TO_BANK0_REG(16)
++MOV_TO_BANK0_REG(17)
++MOV_TO_BANK0_REG(18)
++MOV_TO_BANK0_REG(19)
++MOV_TO_BANK0_REG(20)
++MOV_TO_BANK0_REG(21)
++MOV_TO_BANK0_REG(22)
++MOV_TO_BANK0_REG(23)
++MOV_TO_BANK0_REG(24)
++MOV_TO_BANK0_REG(25)
++MOV_TO_BANK0_REG(26)
++MOV_TO_BANK0_REG(27)
++MOV_TO_BANK0_REG(28)
++MOV_TO_BANK0_REG(29)
++MOV_TO_BANK0_REG(30)
++MOV_TO_BANK0_REG(31)
++
++
++// mov to reg table
++ENTRY(asm_mov_to_reg)
++ MOV_TO_REG0
++ MOV_TO_REG(1)
++ MOV_TO_REG(2)
++ MOV_TO_REG(3)
++ MOV_TO_REG(4)
++ MOV_TO_REG(5)
++ MOV_TO_REG(6)
++ MOV_TO_REG(7)
++ MOV_TO_REG(8)
++ MOV_TO_REG(9)
++ MOV_TO_REG(10)
++ MOV_TO_REG(11)
++ MOV_TO_REG(12)
++ MOV_TO_REG(13)
++ MOV_TO_REG(14)
++ MOV_TO_REG(15)
++ JMP_TO_MOV_TO_BANK0_REG(16)
++ JMP_TO_MOV_TO_BANK0_REG(17)
++ JMP_TO_MOV_TO_BANK0_REG(18)
++ JMP_TO_MOV_TO_BANK0_REG(19)
++ JMP_TO_MOV_TO_BANK0_REG(20)
++ JMP_TO_MOV_TO_BANK0_REG(21)
++ JMP_TO_MOV_TO_BANK0_REG(22)
++ JMP_TO_MOV_TO_BANK0_REG(23)
++ JMP_TO_MOV_TO_BANK0_REG(24)
++ JMP_TO_MOV_TO_BANK0_REG(25)
++ JMP_TO_MOV_TO_BANK0_REG(26)
++ JMP_TO_MOV_TO_BANK0_REG(27)
++ JMP_TO_MOV_TO_BANK0_REG(28)
++ JMP_TO_MOV_TO_BANK0_REG(29)
++ JMP_TO_MOV_TO_BANK0_REG(30)
++ JMP_TO_MOV_TO_BANK0_REG(31)
++ MOV_TO_REG(32)
++ MOV_TO_REG(33)
++ MOV_TO_REG(34)
++ MOV_TO_REG(35)
++ MOV_TO_REG(36)
++ MOV_TO_REG(37)
++ MOV_TO_REG(38)
++ MOV_TO_REG(39)
++ MOV_TO_REG(40)
++ MOV_TO_REG(41)
++ MOV_TO_REG(42)
++ MOV_TO_REG(43)
++ MOV_TO_REG(44)
++ MOV_TO_REG(45)
++ MOV_TO_REG(46)
++ MOV_TO_REG(47)
++ MOV_TO_REG(48)
++ MOV_TO_REG(49)
++ MOV_TO_REG(50)
++ MOV_TO_REG(51)
++ MOV_TO_REG(52)
++ MOV_TO_REG(53)
++ MOV_TO_REG(54)
++ MOV_TO_REG(55)
++ MOV_TO_REG(56)
++ MOV_TO_REG(57)
++ MOV_TO_REG(58)
++ MOV_TO_REG(59)
++ MOV_TO_REG(60)
++ MOV_TO_REG(61)
++ MOV_TO_REG(62)
++ MOV_TO_REG(63)
++ MOV_TO_REG(64)
++ MOV_TO_REG(65)
++ MOV_TO_REG(66)
++ MOV_TO_REG(67)
++ MOV_TO_REG(68)
++ MOV_TO_REG(69)
++ MOV_TO_REG(70)
++ MOV_TO_REG(71)
++ MOV_TO_REG(72)
++ MOV_TO_REG(73)
++ MOV_TO_REG(74)
++ MOV_TO_REG(75)
++ MOV_TO_REG(76)
++ MOV_TO_REG(77)
++ MOV_TO_REG(78)
++ MOV_TO_REG(79)
++ MOV_TO_REG(80)
++ MOV_TO_REG(81)
++ MOV_TO_REG(82)
++ MOV_TO_REG(83)
++ MOV_TO_REG(84)
++ MOV_TO_REG(85)
++ MOV_TO_REG(86)
++ MOV_TO_REG(87)
++ MOV_TO_REG(88)
++ MOV_TO_REG(89)
++ MOV_TO_REG(90)
++ MOV_TO_REG(91)
++ MOV_TO_REG(92)
++ MOV_TO_REG(93)
++ MOV_TO_REG(94)
++ MOV_TO_REG(95)
++ MOV_TO_REG(96)
++ MOV_TO_REG(97)
++ MOV_TO_REG(98)
++ MOV_TO_REG(99)
++ MOV_TO_REG(100)
++ MOV_TO_REG(101)
++ MOV_TO_REG(102)
++ MOV_TO_REG(103)
++ MOV_TO_REG(104)
++ MOV_TO_REG(105)
++ MOV_TO_REG(106)
++ MOV_TO_REG(107)
++ MOV_TO_REG(108)
++ MOV_TO_REG(109)
++ MOV_TO_REG(110)
++ MOV_TO_REG(111)
++ MOV_TO_REG(112)
++ MOV_TO_REG(113)
++ MOV_TO_REG(114)
++ MOV_TO_REG(115)
++ MOV_TO_REG(116)
++ MOV_TO_REG(117)
++ MOV_TO_REG(118)
++ MOV_TO_REG(119)
++ MOV_TO_REG(120)
++ MOV_TO_REG(121)
++ MOV_TO_REG(122)
++ MOV_TO_REG(123)
++ MOV_TO_REG(124)
++ MOV_TO_REG(125)
++ MOV_TO_REG(126)
++ MOV_TO_REG(127)
++END(asm_mov_to_reg)
+diff --git a/arch/ia64/kvm/process.c b/arch/ia64/kvm/process.c
+new file mode 100644
+index 0000000..5a33f7e
+--- /dev/null
++++ b/arch/ia64/kvm/process.c
+@@ -0,0 +1,970 @@
++/*
++ * process.c: handle interruption inject for guests.
++ * Copyright (c) 2005, Intel Corporation.
+ *
-+ * Must be called with preemption disabled.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You 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.
++ *
++ * Shaofan Li (Susue Li) <susie.li at intel.com>
++ * Xiaoyan Feng (Fleming Feng) <fleming.feng at intel.com>
++ * Xuefei Xu (Anthony Xu) (Anthony.xu at intel.com)
++ * Xiantao Zhang (xiantao.zhang at intel.com)
+ */
-+void ia64_ptr_entry(u64 target_mask, int slot)
++#include "vcpu.h"
++
++#include <asm/pal.h>
++#include <asm/sal.h>
++#include <asm/fpswa.h>
++#include <asm/kregs.h>
++#include <asm/tlb.h>
++
++fpswa_interface_t *vmm_fpswa_interface;
++
++#define IA64_VHPT_TRANS_VECTOR 0x0000
++#define IA64_INST_TLB_VECTOR 0x0400
++#define IA64_DATA_TLB_VECTOR 0x0800
++#define IA64_ALT_INST_TLB_VECTOR 0x0c00
++#define IA64_ALT_DATA_TLB_VECTOR 0x1000
++#define IA64_DATA_NESTED_TLB_VECTOR 0x1400
++#define IA64_INST_KEY_MISS_VECTOR 0x1800
++#define IA64_DATA_KEY_MISS_VECTOR 0x1c00
++#define IA64_DIRTY_BIT_VECTOR 0x2000
++#define IA64_INST_ACCESS_BIT_VECTOR 0x2400
++#define IA64_DATA_ACCESS_BIT_VECTOR 0x2800
++#define IA64_BREAK_VECTOR 0x2c00
++#define IA64_EXTINT_VECTOR 0x3000
++#define IA64_PAGE_NOT_PRESENT_VECTOR 0x5000
++#define IA64_KEY_PERMISSION_VECTOR 0x5100
++#define IA64_INST_ACCESS_RIGHTS_VECTOR 0x5200
++#define IA64_DATA_ACCESS_RIGHTS_VECTOR 0x5300
++#define IA64_GENEX_VECTOR 0x5400
++#define IA64_DISABLED_FPREG_VECTOR 0x5500
++#define IA64_NAT_CONSUMPTION_VECTOR 0x5600
++#define IA64_SPECULATION_VECTOR 0x5700 /* UNUSED */
++#define IA64_DEBUG_VECTOR 0x5900
++#define IA64_UNALIGNED_REF_VECTOR 0x5a00
++#define IA64_UNSUPPORTED_DATA_REF_VECTOR 0x5b00
++#define IA64_FP_FAULT_VECTOR 0x5c00
++#define IA64_FP_TRAP_VECTOR 0x5d00
++#define IA64_LOWERPRIV_TRANSFER_TRAP_VECTOR 0x5e00
++#define IA64_TAKEN_BRANCH_TRAP_VECTOR 0x5f00
++#define IA64_SINGLE_STEP_TRAP_VECTOR 0x6000
++
++/* SDM vol2 5.5 - IVA based interruption handling */
++#define INITIAL_PSR_VALUE_AT_INTERRUPTION (IA64_PSR_UP | IA64_PSR_MFL |\
++ IA64_PSR_MFH | IA64_PSR_PK | IA64_PSR_DT | \
++ IA64_PSR_RT | IA64_PSR_MC|IA64_PSR_IT)
++
++#define DOMN_PAL_REQUEST 0x110000
++#define DOMN_SAL_REQUEST 0x110001
++
++static u64 vec2off[68] = {0x0, 0x400, 0x800, 0xc00, 0x1000, 0x1400, 0x1800,
++ 0x1c00, 0x2000, 0x2400, 0x2800, 0x2c00, 0x3000, 0x3400, 0x3800, 0x3c00,
++ 0x4000, 0x4400, 0x4800, 0x4c00, 0x5000, 0x5100, 0x5200, 0x5300, 0x5400,
++ 0x5500, 0x5600, 0x5700, 0x5800, 0x5900, 0x5a00, 0x5b00, 0x5c00, 0x5d00,
++ 0x5e00, 0x5f00, 0x6000, 0x6100, 0x6200, 0x6300, 0x6400, 0x6500, 0x6600,
++ 0x6700, 0x6800, 0x6900, 0x6a00, 0x6b00, 0x6c00, 0x6d00, 0x6e00, 0x6f00,
++ 0x7000, 0x7100, 0x7200, 0x7300, 0x7400, 0x7500, 0x7600, 0x7700, 0x7800,
++ 0x7900, 0x7a00, 0x7b00, 0x7c00, 0x7d00, 0x7e00, 0x7f00
++};
++
++static void collect_interruption(struct kvm_vcpu *vcpu)
++{
++ u64 ipsr;
++ u64 vdcr;
++ u64 vifs;
++ unsigned long vpsr;
++ struct kvm_pt_regs *regs = vcpu_regs(vcpu);
++
++ vpsr = vcpu_get_psr(vcpu);
++ vcpu_bsw0(vcpu);
++ if (vpsr & IA64_PSR_IC) {
++
++ /* Sync mpsr id/da/dd/ss/ed bits to vipsr
++ * since after guest do rfi, we still want these bits on in
++ * mpsr
++ */
++
++ ipsr = regs->cr_ipsr;
++ vpsr = vpsr | (ipsr & (IA64_PSR_ID | IA64_PSR_DA
++ | IA64_PSR_DD | IA64_PSR_SS
++ | IA64_PSR_ED));
++ vcpu_set_ipsr(vcpu, vpsr);
++
++ /* Currently, for trap, we do not advance IIP to next
++ * instruction. That's because we assume caller already
++ * set up IIP correctly
++ */
++
++ vcpu_set_iip(vcpu , regs->cr_iip);
++
++ /* set vifs.v to zero */
++ vifs = VCPU(vcpu, ifs);
++ vifs &= ~IA64_IFS_V;
++ vcpu_set_ifs(vcpu, vifs);
++
++ vcpu_set_iipa(vcpu, VMX(vcpu, cr_iipa));
++ }
++
++ vdcr = VCPU(vcpu, dcr);
++
++ /* Set guest psr
++ * up/mfl/mfh/pk/dt/rt/mc/it keeps unchanged
++ * be: set to the value of dcr.be
++ * pp: set to the value of dcr.pp
++ */
++ vpsr &= INITIAL_PSR_VALUE_AT_INTERRUPTION;
++ vpsr |= (vdcr & IA64_DCR_BE);
++
++ /* VDCR pp bit position is different from VPSR pp bit */
++ if (vdcr & IA64_DCR_PP) {
++ vpsr |= IA64_PSR_PP;
++ } else {
++ vpsr &= ~IA64_PSR_PP;;
++ }
++
++ vcpu_set_psr(vcpu, vpsr);
++
++}
++
++void inject_guest_interruption(struct kvm_vcpu *vcpu, u64 vec)
+{
-+ int cpu = smp_processor_id();
-+ int i;
-+ struct ia64_tr_entry *p;
++ u64 viva;
++ struct kvm_pt_regs *regs;
++ union ia64_isr pt_isr;
+
-+ if (slot < IA64_TR_ALLOC_BASE || slot >= per_cpu(ia64_tr_num, cpu))
++ regs = vcpu_regs(vcpu);
++
++ /* clear cr.isr.ir (incomplete register frame)*/
++ pt_isr.val = VMX(vcpu, cr_isr);
++ pt_isr.ir = 0;
++ VMX(vcpu, cr_isr) = pt_isr.val;
++
++ collect_interruption(vcpu);
++
++ viva = vcpu_get_iva(vcpu);
++ regs->cr_iip = viva + vec;
++}
++
++static u64 vcpu_get_itir_on_fault(struct kvm_vcpu *vcpu, u64 ifa)
++{
++ union ia64_rr rr, rr1;
++
++ rr.val = vcpu_get_rr(vcpu, ifa);
++ rr1.val = 0;
++ rr1.ps = rr.ps;
++ rr1.rid = rr.rid;
++ return (rr1.val);
++}
++
++
++/*
++ * Set vIFA & vITIR & vIHA, when vPSR.ic =1
++ * Parameter:
++ * set_ifa: if true, set vIFA
++ * set_itir: if true, set vITIR
++ * set_iha: if true, set vIHA
++ */
++void set_ifa_itir_iha(struct kvm_vcpu *vcpu, u64 vadr,
++ int set_ifa, int set_itir, int set_iha)
++{
++ long vpsr;
++ u64 value;
++
++ vpsr = VCPU(vcpu, vpsr);
++ /* Vol2, Table 8-1 */
++ if (vpsr & IA64_PSR_IC) {
++ if (set_ifa)
++ vcpu_set_ifa(vcpu, vadr);
++ if (set_itir) {
++ value = vcpu_get_itir_on_fault(vcpu, vadr);
++ vcpu_set_itir(vcpu, value);
++ }
++
++ if (set_iha) {
++ value = vcpu_thash(vcpu, vadr);
++ vcpu_set_iha(vcpu, value);
++ }
++ }
++}
++
++/*
++ * Data TLB Fault
++ * @ Data TLB vector
++ * Refer to SDM Vol2 Table 5-6 & 8-1
++ */
++void dtlb_fault(struct kvm_vcpu *vcpu, u64 vadr)
++{
++ /* If vPSR.ic, IFA, ITIR, IHA */
++ set_ifa_itir_iha(vcpu, vadr, 1, 1, 1);
++ inject_guest_interruption(vcpu, IA64_DATA_TLB_VECTOR);
++}
++
++/*
++ * Instruction TLB Fault
++ * @ Instruction TLB vector
++ * Refer to SDM Vol2 Table 5-6 & 8-1
++ */
++void itlb_fault(struct kvm_vcpu *vcpu, u64 vadr)
++{
++ /* If vPSR.ic, IFA, ITIR, IHA */
++ set_ifa_itir_iha(vcpu, vadr, 1, 1, 1);
++ inject_guest_interruption(vcpu, IA64_INST_TLB_VECTOR);
++}
++
++
++
++/*
++ * Data Nested TLB Fault
++ * @ Data Nested TLB Vector
++ * Refer to SDM Vol2 Table 5-6 & 8-1
++ */
++void nested_dtlb(struct kvm_vcpu *vcpu)
++{
++ inject_guest_interruption(vcpu, IA64_DATA_NESTED_TLB_VECTOR);
++}
++
++/*
++ * Alternate Data TLB Fault
++ * @ Alternate Data TLB vector
++ * Refer to SDM Vol2 Table 5-6 & 8-1
++ */
++void alt_dtlb(struct kvm_vcpu *vcpu, u64 vadr)
++{
++ set_ifa_itir_iha(vcpu, vadr, 1, 1, 0);
++ inject_guest_interruption(vcpu, IA64_ALT_DATA_TLB_VECTOR);
++}
++
++
++/*
++ * Data TLB Fault
++ * @ Data TLB vector
++ * Refer to SDM Vol2 Table 5-6 & 8-1
++ */
++void alt_itlb(struct kvm_vcpu *vcpu, u64 vadr)
++{
++ set_ifa_itir_iha(vcpu, vadr, 1, 1, 0);
++ inject_guest_interruption(vcpu, IA64_ALT_INST_TLB_VECTOR);
++}
++
++/* Deal with:
++ * VHPT Translation Vector
++ */
++static void _vhpt_fault(struct kvm_vcpu *vcpu, u64 vadr)
++{
++ /* If vPSR.ic, IFA, ITIR, IHA*/
++ set_ifa_itir_iha(vcpu, vadr, 1, 1, 1);
++ inject_guest_interruption(vcpu, IA64_VHPT_TRANS_VECTOR);
++
++
++}
++
++/*
++ * VHPT Instruction Fault
++ * @ VHPT Translation vector
++ * Refer to SDM Vol2 Table 5-6 & 8-1
++ */
++void ivhpt_fault(struct kvm_vcpu *vcpu, u64 vadr)
++{
++ _vhpt_fault(vcpu, vadr);
++}
++
++
++/*
++ * VHPT Data Fault
++ * @ VHPT Translation vector
++ * Refer to SDM Vol2 Table 5-6 & 8-1
++ */
++void dvhpt_fault(struct kvm_vcpu *vcpu, u64 vadr)
++{
++ _vhpt_fault(vcpu, vadr);
++}
++
++
++
++/*
++ * Deal with:
++ * General Exception vector
++ */
++void _general_exception(struct kvm_vcpu *vcpu)
++{
++ inject_guest_interruption(vcpu, IA64_GENEX_VECTOR);
++}
++
++
++/*
++ * Illegal Operation Fault
++ * @ General Exception Vector
++ * Refer to SDM Vol2 Table 5-6 & 8-1
++ */
++void illegal_op(struct kvm_vcpu *vcpu)
++{
++ _general_exception(vcpu);
++}
++
++/*
++ * Illegal Dependency Fault
++ * @ General Exception Vector
++ * Refer to SDM Vol2 Table 5-6 & 8-1
++ */
++void illegal_dep(struct kvm_vcpu *vcpu)
++{
++ _general_exception(vcpu);
++}
++
++/*
++ * Reserved Register/Field Fault
++ * @ General Exception Vector
++ * Refer to SDM Vol2 Table 5-6 & 8-1
++ */
++void rsv_reg_field(struct kvm_vcpu *vcpu)
++{
++ _general_exception(vcpu);
++}
++/*
++ * Privileged Operation Fault
++ * @ General Exception Vector
++ * Refer to SDM Vol2 Table 5-6 & 8-1
++ */
++
++void privilege_op(struct kvm_vcpu *vcpu)
++{
++ _general_exception(vcpu);
++}
++
++/*
++ * Unimplement Data Address Fault
++ * @ General Exception Vector
++ * Refer to SDM Vol2 Table 5-6 & 8-1
++ */
++void unimpl_daddr(struct kvm_vcpu *vcpu)
++{
++ _general_exception(vcpu);
++}
++
++/*
++ * Privileged Register Fault
++ * @ General Exception Vector
++ * Refer to SDM Vol2 Table 5-6 & 8-1
++ */
++void privilege_reg(struct kvm_vcpu *vcpu)
++{
++ _general_exception(vcpu);
++}
++
++/* Deal with
++ * Nat consumption vector
++ * Parameter:
++ * vaddr: Optional, if t == REGISTER
++ */
++static void _nat_consumption_fault(struct kvm_vcpu *vcpu, u64 vadr,
++ enum tlb_miss_type t)
++{
++ /* If vPSR.ic && t == DATA/INST, IFA */
++ if (t == DATA || t == INSTRUCTION) {
++ /* IFA */
++ set_ifa_itir_iha(vcpu, vadr, 1, 0, 0);
++ }
++
++ inject_guest_interruption(vcpu, IA64_NAT_CONSUMPTION_VECTOR);
++}
++
++/*
++ * Instruction Nat Page Consumption Fault
++ * @ Nat Consumption Vector
++ * Refer to SDM Vol2 Table 5-6 & 8-1
++ */
++void inat_page_consumption(struct kvm_vcpu *vcpu, u64 vadr)
++{
++ _nat_consumption_fault(vcpu, vadr, INSTRUCTION);
++}
++
++/*
++ * Register Nat Consumption Fault
++ * @ Nat Consumption Vector
++ * Refer to SDM Vol2 Table 5-6 & 8-1
++ */
++void rnat_consumption(struct kvm_vcpu *vcpu)
++{
++ _nat_consumption_fault(vcpu, 0, REGISTER);
++}
++
++/*
++ * Data Nat Page Consumption Fault
++ * @ Nat Consumption Vector
++ * Refer to SDM Vol2 Table 5-6 & 8-1
++ */
++void dnat_page_consumption(struct kvm_vcpu *vcpu, u64 vadr)
++{
++ _nat_consumption_fault(vcpu, vadr, DATA);
++}
++
++/* Deal with
++ * Page not present vector
++ */
++static void __page_not_present(struct kvm_vcpu *vcpu, u64 vadr)
++{
++ /* If vPSR.ic, IFA, ITIR */
++ set_ifa_itir_iha(vcpu, vadr, 1, 1, 0);
++ inject_guest_interruption(vcpu, IA64_PAGE_NOT_PRESENT_VECTOR);
++}
++
++
++void data_page_not_present(struct kvm_vcpu *vcpu, u64 vadr)
++{
++ __page_not_present(vcpu, vadr);
++}
++
++
++void inst_page_not_present(struct kvm_vcpu *vcpu, u64 vadr)
++{
++ __page_not_present(vcpu, vadr);
++}
++
++
++/* Deal with
++ * Data access rights vector
++ */
++void data_access_rights(struct kvm_vcpu *vcpu, u64 vadr)
++{
++ /* If vPSR.ic, IFA, ITIR */
++ set_ifa_itir_iha(vcpu, vadr, 1, 1, 0);
++ inject_guest_interruption(vcpu, IA64_DATA_ACCESS_RIGHTS_VECTOR);
++}
++
++fpswa_ret_t vmm_fp_emulate(int fp_fault, void *bundle, unsigned long *ipsr,
++ unsigned long *fpsr, unsigned long *isr, unsigned long *pr,
++ unsigned long *ifs, struct kvm_pt_regs *regs)
++{
++ fp_state_t fp_state;
++ fpswa_ret_t ret;
++ struct kvm_vcpu *vcpu = current_vcpu;
++
++ uint64_t old_rr7 = ia64_get_rr(7UL<<61);
++
++ if (!vmm_fpswa_interface)
++ return (fpswa_ret_t) {-1, 0, 0, 0};
++
++ /*
++ * Just let fpswa driver to use hardware fp registers.
++ * No fp register is valid in memory.
++ */
++ memset(&fp_state, 0, sizeof(fp_state_t));
++
++ /*
++ * unsigned long (*EFI_FPSWA) (
++ * unsigned long trap_type,
++ * void *Bundle,
++ * unsigned long *pipsr,
++ * unsigned long *pfsr,
++ * unsigned long *pisr,
++ * unsigned long *ppreds,
++ * unsigned long *pifs,
++ * void *fp_state);
++ */
++ /*Call host fpswa interface directly to virtualize
++ *guest fpswa request!
++ */
++ ia64_set_rr(7UL << 61, vcpu->arch.host.rr[7]);
++ ia64_srlz_d();
++
++ ret = (*vmm_fpswa_interface->fpswa) (fp_fault, bundle,
++ ipsr, fpsr, isr, pr, ifs, &fp_state);
++ ia64_set_rr(7UL << 61, old_rr7);
++ ia64_srlz_d();
++ return ret;
++}
++
++/*
++ * Handle floating-point assist faults and traps for domain.
++ */
++unsigned long vmm_handle_fpu_swa(int fp_fault, struct kvm_pt_regs *regs,
++ unsigned long isr)
++{
++ struct kvm_vcpu *v = current_vcpu;
++ IA64_BUNDLE bundle;
++ unsigned long fault_ip;
++ fpswa_ret_t ret;
++
++ fault_ip = regs->cr_iip;
++ /*
++ * When the FP trap occurs, the trapping instruction is completed.
++ * If ipsr.ri == 0, there is the trapping instruction in previous
++ * bundle.
++ */
++ if (!fp_fault && (ia64_psr(regs)->ri == 0))
++ fault_ip -= 16;
++
++ if (fetch_code(v, fault_ip, &bundle))
++ return -EAGAIN;
++
++ if (!bundle.i64[0] && !bundle.i64[1])
++ return -EACCES;
++
++ ret = vmm_fp_emulate(fp_fault, &bundle, ®s->cr_ipsr, ®s->ar_fpsr,
++ &isr, ®s->pr, ®s->cr_ifs, regs);
++ return ret.status;
++}
++
++void reflect_interruption(u64 ifa, u64 isr, u64 iim,
++ u64 vec, struct kvm_pt_regs *regs)
++{
++ u64 vector;
++ int status ;
++ struct kvm_vcpu *vcpu = current_vcpu;
++ u64 vpsr = VCPU(vcpu, vpsr);
++
++ vector = vec2off[vec];
++
++ if (!(vpsr & IA64_PSR_IC) && (vector != IA64_DATA_NESTED_TLB_VECTOR)) {
++ panic_vm(vcpu);
+ return;
++ }
+
-+ if (target_mask & 0x1) {
-+ p = &__per_cpu_idtrs[cpu][0][slot];
-+ if ((p->pte&0x1) && is_tr_overlap(p, p->ifa, p->itir>>2)) {
-+ p->pte = 0;
-+ ia64_ptr(0x1, p->ifa, p->itir>>2);
-+ ia64_srlz_i();
++ switch (vec) {
++ case 32: /*IA64_FP_FAULT_VECTOR*/
++ status = vmm_handle_fpu_swa(1, regs, isr);
++ if (!status) {
++ vcpu_increment_iip(vcpu);
++ return;
++ } else if (-EAGAIN == status)
++ return;
++ break;
++ case 33: /*IA64_FP_TRAP_VECTOR*/
++ status = vmm_handle_fpu_swa(0, regs, isr);
++ if (!status)
++ return ;
++ else if (-EAGAIN == status) {
++ vcpu_decrement_iip(vcpu);
++ return ;
+ }
++ break;
+ }
+
-+ if (target_mask & 0x2) {
-+ p = &__per_cpu_idtrs[cpu][1][slot];
-+ if ((p->pte & 0x1) && is_tr_overlap(p, p->ifa, p->itir>>2)) {
-+ p->pte = 0;
-+ ia64_ptr(0x2, p->ifa, p->itir>>2);
-+ ia64_srlz_i();
++ VCPU(vcpu, isr) = isr;
++ VCPU(vcpu, iipa) = regs->cr_iip;
++ if (vector == IA64_BREAK_VECTOR || vector == IA64_SPECULATION_VECTOR)
++ VCPU(vcpu, iim) = iim;
++ else
++ set_ifa_itir_iha(vcpu, ifa, 1, 1, 1);
++
++ inject_guest_interruption(vcpu, vector);
++}
++
++static void set_pal_call_data(struct kvm_vcpu *vcpu)
++{
++ struct exit_ctl_data *p = &vcpu->arch.exit_data;
++
++ /*FIXME:For static and stacked convention, firmware
++ * has put the parameters in gr28-gr31 before
++ * break to vmm !!*/
++
++ p->u.pal_data.gr28 = vcpu_get_gr(vcpu, 28);
++ p->u.pal_data.gr29 = vcpu_get_gr(vcpu, 29);
++ p->u.pal_data.gr30 = vcpu_get_gr(vcpu, 30);
++ p->u.pal_data.gr31 = vcpu_get_gr(vcpu, 31);
++ p->exit_reason = EXIT_REASON_PAL_CALL;
++}
++
++static void set_pal_call_result(struct kvm_vcpu *vcpu)
++{
++ struct exit_ctl_data *p = &vcpu->arch.exit_data;
++
++ if (p->exit_reason == EXIT_REASON_PAL_CALL) {
++ vcpu_set_gr(vcpu, 8, p->u.pal_data.ret.status, 0);
++ vcpu_set_gr(vcpu, 9, p->u.pal_data.ret.v0, 0);
++ vcpu_set_gr(vcpu, 10, p->u.pal_data.ret.v1, 0);
++ vcpu_set_gr(vcpu, 11, p->u.pal_data.ret.v2, 0);
++ } else
++ panic_vm(vcpu);
++}
++
++static void set_sal_call_data(struct kvm_vcpu *vcpu)
++{
++ struct exit_ctl_data *p = &vcpu->arch.exit_data;
++
++ p->u.sal_data.in0 = vcpu_get_gr(vcpu, 32);
++ p->u.sal_data.in1 = vcpu_get_gr(vcpu, 33);
++ p->u.sal_data.in2 = vcpu_get_gr(vcpu, 34);
++ p->u.sal_data.in3 = vcpu_get_gr(vcpu, 35);
++ p->u.sal_data.in4 = vcpu_get_gr(vcpu, 36);
++ p->u.sal_data.in5 = vcpu_get_gr(vcpu, 37);
++ p->u.sal_data.in6 = vcpu_get_gr(vcpu, 38);
++ p->u.sal_data.in7 = vcpu_get_gr(vcpu, 39);
++ p->exit_reason = EXIT_REASON_SAL_CALL;
++}
++
++static void set_sal_call_result(struct kvm_vcpu *vcpu)
++{
++ struct exit_ctl_data *p = &vcpu->arch.exit_data;
++
++ if (p->exit_reason == EXIT_REASON_SAL_CALL) {
++ vcpu_set_gr(vcpu, 8, p->u.sal_data.ret.r8, 0);
++ vcpu_set_gr(vcpu, 9, p->u.sal_data.ret.r9, 0);
++ vcpu_set_gr(vcpu, 10, p->u.sal_data.ret.r10, 0);
++ vcpu_set_gr(vcpu, 11, p->u.sal_data.ret.r11, 0);
++ } else
++ panic_vm(vcpu);
++}
++
++void kvm_ia64_handle_break(unsigned long ifa, struct kvm_pt_regs *regs,
++ unsigned long isr, unsigned long iim)
++{
++ struct kvm_vcpu *v = current_vcpu;
++
++ if (ia64_psr(regs)->cpl == 0) {
++ /* Allow hypercalls only when cpl = 0. */
++ if (iim == DOMN_PAL_REQUEST) {
++ set_pal_call_data(v);
++ vmm_transition(v);
++ set_pal_call_result(v);
++ vcpu_increment_iip(v);
++ return;
++ } else if (iim == DOMN_SAL_REQUEST) {
++ set_sal_call_data(v);
++ vmm_transition(v);
++ set_sal_call_result(v);
++ vcpu_increment_iip(v);
++ return;
+ }
+ }
++ reflect_interruption(ifa, isr, iim, 11, regs);
++}
+
-+ for (i = per_cpu(ia64_tr_used, cpu); i >= IA64_TR_ALLOC_BASE; i--) {
-+ if ((__per_cpu_idtrs[cpu][0][i].pte & 0x1) ||
-+ (__per_cpu_idtrs[cpu][1][i].pte & 0x1))
-+ break;
++void check_pending_irq(struct kvm_vcpu *vcpu)
++{
++ int mask, h_pending, h_inservice;
++ u64 isr;
++ unsigned long vpsr;
++ struct kvm_pt_regs *regs = vcpu_regs(vcpu);
++
++ h_pending = highest_pending_irq(vcpu);
++ if (h_pending == NULL_VECTOR) {
++ update_vhpi(vcpu, NULL_VECTOR);
++ return;
+ }
-+ per_cpu(ia64_tr_used, cpu) = i;
- }
-+EXPORT_SYMBOL_GPL(ia64_ptr_entry);
-diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
-index 53d0a8e..77b15f8 100644
---- a/arch/ia64/pci/pci.c
-+++ b/arch/ia64/pci/pci.c
-@@ -504,54 +504,12 @@ pcibios_update_irq (struct pci_dev *dev, int irq)
- /* ??? FIXME -- record old value for shutdown. */
- }
-
--static inline int
--pcibios_enable_resources (struct pci_dev *dev, int mask)
--{
-- u16 cmd, old_cmd;
-- int idx;
-- struct resource *r;
-- unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
--
-- if (!dev)
-- return -EINVAL;
--
-- pci_read_config_word(dev, PCI_COMMAND, &cmd);
-- old_cmd = cmd;
-- for (idx=0; idx<PCI_NUM_RESOURCES; idx++) {
-- /* Only set up the desired resources. */
-- if (!(mask & (1 << idx)))
-- continue;
--
-- r = &dev->resource[idx];
-- if (!(r->flags & type_mask))
-- continue;
-- if ((idx == PCI_ROM_RESOURCE) &&
-- (!(r->flags & IORESOURCE_ROM_ENABLE)))
-- continue;
-- if (!r->start && r->end) {
-- printk(KERN_ERR
-- "PCI: Device %s not available because of resource collisions\n",
-- pci_name(dev));
-- return -EINVAL;
-- }
-- if (r->flags & IORESOURCE_IO)
-- cmd |= PCI_COMMAND_IO;
-- if (r->flags & IORESOURCE_MEM)
-- cmd |= PCI_COMMAND_MEMORY;
-- }
-- if (cmd != old_cmd) {
-- printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
-- pci_write_config_word(dev, PCI_COMMAND, cmd);
-- }
-- return 0;
--}
--
- int
- pcibios_enable_device (struct pci_dev *dev, int mask)
- {
- int ret;
-
-- ret = pcibios_enable_resources(dev, mask);
-+ ret = pci_enable_resources(dev, mask);
- if (ret < 0)
- return ret;
-
-diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile
-index 688a3c2..0591038 100644
---- a/arch/ia64/sn/kernel/Makefile
-+++ b/arch/ia64/sn/kernel/Makefile
-@@ -4,7 +4,7 @@
- # License. See the file "COPYING" in the main directory of this archive
- # for more details.
- #
--# Copyright (C) 1999,2001-2006 Silicon Graphics, Inc. All Rights Reserved.
-+# Copyright (C) 1999,2001-2006,2008 Silicon Graphics, Inc. All Rights Reserved.
- #
-
- EXTRA_CFLAGS += -Iarch/ia64/sn/include
-@@ -15,9 +15,4 @@ obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \
- sn2/
- obj-$(CONFIG_IA64_GENERIC) += machvec.o
- obj-$(CONFIG_SGI_TIOCX) += tiocx.o
--obj-$(CONFIG_IA64_SGI_SN_XP) += xp.o
--xp-y := xp_main.o xp_nofault.o
--obj-$(CONFIG_IA64_SGI_SN_XP) += xpc.o
--xpc-y := xpc_main.o xpc_channel.o xpc_partition.o
--obj-$(CONFIG_IA64_SGI_SN_XP) += xpnet.o
- obj-$(CONFIG_PCI_MSI) += msi_sn.o
-diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c
-index 0101c79..08b0d9b 100644
---- a/arch/ia64/sn/kernel/huberror.c
-+++ b/arch/ia64/sn/kernel/huberror.c
-@@ -187,8 +187,8 @@ void hub_error_init(struct hubdev_info *hubdev_info)
- {
-
- if (request_irq(SGI_II_ERROR, hub_eint_handler, IRQF_SHARED,
-- "SN_hub_error", (void *)hubdev_info)) {
-- printk("hub_error_init: Failed to request_irq for 0x%p\n",
-+ "SN_hub_error", hubdev_info)) {
-+ printk(KERN_ERR "hub_error_init: Failed to request_irq for 0x%p\n",
- hubdev_info);
- return;
- }
-diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
-index 4b0d153..8cc0c47 100644
---- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
-+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
-@@ -37,7 +37,6 @@
-
- #include <asm/processor.h>
- #include <asm/topology.h>
--#include <asm/semaphore.h>
- #include <asm/uaccess.h>
- #include <asm/sal.h>
- #include <asm/sn/io.h>
-diff --git a/arch/ia64/sn/kernel/xp_main.c b/arch/ia64/sn/kernel/xp_main.c
-deleted file mode 100644
-index b7ea466..0000000
---- a/arch/ia64/sn/kernel/xp_main.c
-+++ /dev/null
-@@ -1,290 +0,0 @@
--/*
-- * This file is subject to the terms and conditions of the GNU General Public
-- * License. See the file "COPYING" in the main directory of this archive
-- * for more details.
-- *
-- * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
-- */
--
--
--/*
-- * Cross Partition (XP) base.
-- *
-- * XP provides a base from which its users can interact
-- * with XPC, yet not be dependent on XPC.
-- *
-- */
--
--
--#include <linux/kernel.h>
--#include <linux/interrupt.h>
--#include <linux/module.h>
--#include <linux/mutex.h>
--#include <asm/sn/intr.h>
--#include <asm/sn/sn_sal.h>
--#include <asm/sn/xp.h>
--
--
--/*
-- * Target of nofault PIO read.
-- */
--u64 xp_nofault_PIOR_target;
--
--
--/*
-- * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level
-- * users of XPC.
-- */
--struct xpc_registration xpc_registrations[XPC_NCHANNELS];
--
--
--/*
-- * Initialize the XPC interface to indicate that XPC isn't loaded.
-- */
--static enum xpc_retval xpc_notloaded(void) { return xpcNotLoaded; }
--
--struct xpc_interface xpc_interface = {
-- (void (*)(int)) xpc_notloaded,
-- (void (*)(int)) xpc_notloaded,
-- (enum xpc_retval (*)(partid_t, int, u32, void **)) xpc_notloaded,
-- (enum xpc_retval (*)(partid_t, int, void *)) xpc_notloaded,
-- (enum xpc_retval (*)(partid_t, int, void *, xpc_notify_func, void *))
-- xpc_notloaded,
-- (void (*)(partid_t, int, void *)) xpc_notloaded,
-- (enum xpc_retval (*)(partid_t, void *)) xpc_notloaded
--};
--
--
--/*
-- * XPC calls this when it (the XPC module) has been loaded.
-- */
--void
--xpc_set_interface(void (*connect)(int),
-- void (*disconnect)(int),
-- enum xpc_retval (*allocate)(partid_t, int, u32, void **),
-- enum xpc_retval (*send)(partid_t, int, void *),
-- enum xpc_retval (*send_notify)(partid_t, int, void *,
-- xpc_notify_func, void *),
-- void (*received)(partid_t, int, void *),
-- enum xpc_retval (*partid_to_nasids)(partid_t, void *))
--{
-- xpc_interface.connect = connect;
-- xpc_interface.disconnect = disconnect;
-- xpc_interface.allocate = allocate;
-- xpc_interface.send = send;
-- xpc_interface.send_notify = send_notify;
-- xpc_interface.received = received;
-- xpc_interface.partid_to_nasids = partid_to_nasids;
--}
--
--
--/*
-- * XPC calls this when it (the XPC module) is being unloaded.
-- */
--void
--xpc_clear_interface(void)
--{
-- xpc_interface.connect = (void (*)(int)) xpc_notloaded;
-- xpc_interface.disconnect = (void (*)(int)) xpc_notloaded;
-- xpc_interface.allocate = (enum xpc_retval (*)(partid_t, int, u32,
-- void **)) xpc_notloaded;
-- xpc_interface.send = (enum xpc_retval (*)(partid_t, int, void *))
-- xpc_notloaded;
-- xpc_interface.send_notify = (enum xpc_retval (*)(partid_t, int, void *,
-- xpc_notify_func, void *)) xpc_notloaded;
-- xpc_interface.received = (void (*)(partid_t, int, void *))
-- xpc_notloaded;
-- xpc_interface.partid_to_nasids = (enum xpc_retval (*)(partid_t, void *))
-- xpc_notloaded;
--}
--
--
--/*
-- * Register for automatic establishment of a channel connection whenever
-- * a partition comes up.
-- *
-- * Arguments:
-- *
-- * ch_number - channel # to register for connection.
-- * func - function to call for asynchronous notification of channel
-- * state changes (i.e., connection, disconnection, error) and
-- * the arrival of incoming messages.
-- * key - pointer to optional user-defined value that gets passed back
-- * to the user on any callouts made to func.
-- * payload_size - size in bytes of the XPC message's payload area which
-- * contains a user-defined message. The user should make
-- * this large enough to hold their largest message.
-- * nentries - max #of XPC message entries a message queue can contain.
-- * The actual number, which is determined when a connection
-- * is established and may be less then requested, will be
-- * passed to the user via the xpcConnected callout.
-- * assigned_limit - max number of kthreads allowed to be processing
-- * messages (per connection) at any given instant.
-- * idle_limit - max number of kthreads allowed to be idle at any given
-- * instant.
-- */
--enum xpc_retval
--xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
-- u16 nentries, u32 assigned_limit, u32 idle_limit)
--{
-- struct xpc_registration *registration;
--
--
-- DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
-- DBUG_ON(payload_size == 0 || nentries == 0);
-- DBUG_ON(func == NULL);
-- DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);
--
-- registration = &xpc_registrations[ch_number];
--
-- if (mutex_lock_interruptible(®istration->mutex) != 0) {
-- return xpcInterrupted;
-- }
--
-- /* if XPC_CHANNEL_REGISTERED(ch_number) */
-- if (registration->func != NULL) {
-- mutex_unlock(®istration->mutex);
-- return xpcAlreadyRegistered;
-- }
--
-- /* register the channel for connection */
-- registration->msg_size = XPC_MSG_SIZE(payload_size);
-- registration->nentries = nentries;
-- registration->assigned_limit = assigned_limit;
-- registration->idle_limit = idle_limit;
-- registration->key = key;
-- registration->func = func;
--
-- mutex_unlock(®istration->mutex);
--
-- xpc_interface.connect(ch_number);
--
-- return xpcSuccess;
--}
--
--
--/*
-- * Remove the registration for automatic connection of the specified channel
-- * when a partition comes up.
-- *
-- * Before returning this xpc_disconnect() will wait for all connections on the
-- * specified channel have been closed/torndown. So the caller can be assured
-- * that they will not be receiving any more callouts from XPC to their
-- * function registered via xpc_connect().
-- *
-- * Arguments:
-- *
-- * ch_number - channel # to unregister.
-- */
--void
--xpc_disconnect(int ch_number)
--{
-- struct xpc_registration *registration;
--
--
-- DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
--
-- registration = &xpc_registrations[ch_number];
--
-- /*
-- * We've decided not to make this a down_interruptible(), since we
-- * figured XPC's users will just turn around and call xpc_disconnect()
-- * again anyways, so we might as well wait, if need be.
-- */
-- mutex_lock(®istration->mutex);
--
-- /* if !XPC_CHANNEL_REGISTERED(ch_number) */
-- if (registration->func == NULL) {
-- mutex_unlock(®istration->mutex);
-- return;
-- }
--
-- /* remove the connection registration for the specified channel */
-- registration->func = NULL;
-- registration->key = NULL;
-- registration->nentries = 0;
-- registration->msg_size = 0;
-- registration->assigned_limit = 0;
-- registration->idle_limit = 0;
--
-- xpc_interface.disconnect(ch_number);
--
-- mutex_unlock(®istration->mutex);
--
-- return;
--}
--
--
--int __init
--xp_init(void)
--{
-- int ret, ch_number;
-- u64 func_addr = *(u64 *) xp_nofault_PIOR;
-- u64 err_func_addr = *(u64 *) xp_error_PIOR;
--
--
-- if (!ia64_platform_is("sn2")) {
-- return -ENODEV;
-- }
--
-- /*
-- * Register a nofault code region which performs a cross-partition
-- * PIO read. If the PIO read times out, the MCA handler will consume
-- * the error and return to a kernel-provided instruction to indicate
-- * an error. This PIO read exists because it is guaranteed to timeout
-- * if the destination is down (AMO operations do not timeout on at
-- * least some CPUs on Shubs <= v1.2, which unfortunately we have to
-- * work around).
-- */
-- if ((ret = sn_register_nofault_code(func_addr, err_func_addr,
-- err_func_addr, 1, 1)) != 0) {
-- printk(KERN_ERR "XP: can't register nofault code, error=%d\n",
-- ret);
-- }
-- /*
-- * Setup the nofault PIO read target. (There is no special reason why
-- * SH_IPI_ACCESS was selected.)
-- */
-- if (is_shub2()) {
-- xp_nofault_PIOR_target = SH2_IPI_ACCESS0;
-- } else {
-- xp_nofault_PIOR_target = SH1_IPI_ACCESS;
-- }
--
-- /* initialize the connection registration mutex */
-- for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) {
-- mutex_init(&xpc_registrations[ch_number].mutex);
-- }
--
-- return 0;
--}
--module_init(xp_init);
--
--
--void __exit
--xp_exit(void)
--{
-- u64 func_addr = *(u64 *) xp_nofault_PIOR;
-- u64 err_func_addr = *(u64 *) xp_error_PIOR;
--
--
-- /* unregister the PIO read nofault code region */
-- (void) sn_register_nofault_code(func_addr, err_func_addr,
-- err_func_addr, 1, 0);
--}
--module_exit(xp_exit);
--
--
--MODULE_AUTHOR("Silicon Graphics, Inc.");
--MODULE_DESCRIPTION("Cross Partition (XP) base");
--MODULE_LICENSE("GPL");
--
--EXPORT_SYMBOL(xp_nofault_PIOR);
--EXPORT_SYMBOL(xp_nofault_PIOR_target);
--EXPORT_SYMBOL(xpc_registrations);
--EXPORT_SYMBOL(xpc_interface);
--EXPORT_SYMBOL(xpc_clear_interface);
--EXPORT_SYMBOL(xpc_set_interface);
--EXPORT_SYMBOL(xpc_connect);
--EXPORT_SYMBOL(xpc_disconnect);
--
-diff --git a/arch/ia64/sn/kernel/xp_nofault.S b/arch/ia64/sn/kernel/xp_nofault.S
-deleted file mode 100644
-index 98e7c7d..0000000
---- a/arch/ia64/sn/kernel/xp_nofault.S
-+++ /dev/null
-@@ -1,36 +0,0 @@
--/*
-- * This file is subject to the terms and conditions of the GNU General Public
-- * License. See the file "COPYING" in the main directory of this archive
-- * for more details.
-- *
-- * Copyright (c) 2004-2007 Silicon Graphics, Inc. All Rights Reserved.
-- */
--
--
--/*
-- * The xp_nofault_PIOR function takes a pointer to a remote PIO register
-- * and attempts to load and consume a value from it. This function
-- * will be registered as a nofault code block. In the event that the
-- * PIO read fails, the MCA handler will force the error to look
-- * corrected and vector to the xp_error_PIOR which will return an error.
-- *
-- * The definition of "consumption" and the time it takes for an MCA
-- * to surface is processor implementation specific. This code
-- * is sufficient on Itanium through the Montvale processor family.
-- * It may need to be adjusted for future processor implementations.
-- *
-- * extern int xp_nofault_PIOR(void *remote_register);
-- */
--
-- .global xp_nofault_PIOR
--xp_nofault_PIOR:
-- mov r8=r0 // Stage a success return value
-- ld8.acq r9=[r32];; // PIO Read the specified register
-- adds r9=1,r9;; // Add to force consumption
-- srlz.i;; // Allow time for MCA to surface
-- br.ret.sptk.many b0;; // Return success
--
-- .global xp_error_PIOR
--xp_error_PIOR:
-- mov r8=1 // Return value of 1
-- br.ret.sptk.many b0;; // Return failure
-diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
-deleted file mode 100644
-index 44ccc0d..0000000
---- a/arch/ia64/sn/kernel/xpc_channel.c
-+++ /dev/null
-@@ -1,2379 +0,0 @@
--/*
-- * This file is subject to the terms and conditions of the GNU General Public
-- * License. See the file "COPYING" in the main directory of this archive
-- * for more details.
-- *
-- * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved.
-- */
--
--
--/*
-- * Cross Partition Communication (XPC) channel support.
-- *
-- * This is the part of XPC that manages the channels and
-- * sends/receives messages across them to/from other partitions.
-- *
-- */
--
--
--#include <linux/kernel.h>
--#include <linux/init.h>
--#include <linux/sched.h>
--#include <linux/cache.h>
--#include <linux/interrupt.h>
--#include <linux/mutex.h>
--#include <linux/completion.h>
--#include <asm/sn/bte.h>
--#include <asm/sn/sn_sal.h>
--#include <asm/sn/xpc.h>
--
++ h_inservice = highest_inservice_irq(vcpu);
++
++ vpsr = VCPU(vcpu, vpsr);
++ mask = irq_masked(vcpu, h_pending, h_inservice);
++ if ((vpsr & IA64_PSR_I) && IRQ_NO_MASKED == mask) {
++ isr = vpsr & IA64_PSR_RI;
++ update_vhpi(vcpu, h_pending);
++ reflect_interruption(0, isr, 0, 12, regs); /* EXT IRQ */
++ } else if (mask == IRQ_MASKED_BY_INSVC) {
++ if (VCPU(vcpu, vhpi))
++ update_vhpi(vcpu, NULL_VECTOR);
++ } else {
++ /* masked by vpsr.i or vtpr.*/
++ update_vhpi(vcpu, h_pending);
++ }
++}
++
++static void generate_exirq(struct kvm_vcpu *vcpu)
++{
++ unsigned vpsr;
++ uint64_t isr;
++
++ struct kvm_pt_regs *regs = vcpu_regs(vcpu);
++
++ vpsr = VCPU(vcpu, vpsr);
++ isr = vpsr & IA64_PSR_RI;
++ if (!(vpsr & IA64_PSR_IC))
++ panic_vm(vcpu);
++ reflect_interruption(0, isr, 0, 12, regs); /* EXT IRQ */
++}
++
++void vhpi_detection(struct kvm_vcpu *vcpu)
++{
++ uint64_t threshold, vhpi;
++ union ia64_tpr vtpr;
++ struct ia64_psr vpsr;
++
++ vpsr = *(struct ia64_psr *)&VCPU(vcpu, vpsr);
++ vtpr.val = VCPU(vcpu, tpr);
++
++ threshold = ((!vpsr.i) << 5) | (vtpr.mmi << 4) | vtpr.mic;
++ vhpi = VCPU(vcpu, vhpi);
++ if (vhpi > threshold) {
++ /* interrupt actived*/
++ generate_exirq(vcpu);
++ }
++}
++
++
++void leave_hypervisor_tail(void)
++{
++ struct kvm_vcpu *v = current_vcpu;
++
++ if (VMX(v, timer_check)) {
++ VMX(v, timer_check) = 0;
++ if (VMX(v, itc_check)) {
++ if (vcpu_get_itc(v) > VCPU(v, itm)) {
++ if (!(VCPU(v, itv) & (1 << 16))) {
++ vcpu_pend_interrupt(v, VCPU(v, itv)
++ & 0xff);
++ VMX(v, itc_check) = 0;
++ } else {
++ v->arch.timer_pending = 1;
++ }
++ VMX(v, last_itc) = VCPU(v, itm) + 1;
++ }
++ }
++ }
++
++ rmb();
++ if (v->arch.irq_new_pending) {
++ v->arch.irq_new_pending = 0;
++ VMX(v, irq_check) = 0;
++ check_pending_irq(v);
++ return;
++ }
++ if (VMX(v, irq_check)) {
++ VMX(v, irq_check) = 0;
++ vhpi_detection(v);
++ }
++}
++
++
++static inline void handle_lds(struct kvm_pt_regs *regs)
++{
++ regs->cr_ipsr |= IA64_PSR_ED;
++}
++
++void physical_tlb_miss(struct kvm_vcpu *vcpu, unsigned long vadr, int type)
++{
++ unsigned long pte;
++ union ia64_rr rr;
++
++ rr.val = ia64_get_rr(vadr);
++ pte = vadr & _PAGE_PPN_MASK;
++ pte = pte | PHY_PAGE_WB;
++ thash_vhpt_insert(vcpu, pte, (u64)(rr.ps << 2), vadr, type);
++ return;
++}
++
++void kvm_page_fault(u64 vadr , u64 vec, struct kvm_pt_regs *regs)
++{
++ unsigned long vpsr;
++ int type;
++
++ u64 vhpt_adr, gppa, pteval, rr, itir;
++ union ia64_isr misr;
++ union ia64_pta vpta;
++ struct thash_data *data;
++ struct kvm_vcpu *v = current_vcpu;
++
++ vpsr = VCPU(v, vpsr);
++ misr.val = VMX(v, cr_isr);
++
++ type = vec;
++
++ if (is_physical_mode(v) && (!(vadr << 1 >> 62))) {
++ if (vec == 2) {
++ if (__gpfn_is_io((vadr << 1) >> (PAGE_SHIFT + 1))) {
++ emulate_io_inst(v, ((vadr << 1) >> 1), 4);
++ return;
++ }
++ }
++ physical_tlb_miss(v, vadr, type);
++ return;
++ }
++ data = vtlb_lookup(v, vadr, type);
++ if (data != 0) {
++ if (type == D_TLB) {
++ gppa = (vadr & ((1UL << data->ps) - 1))
++ + (data->ppn >> (data->ps - 12) << data->ps);
++ if (__gpfn_is_io(gppa >> PAGE_SHIFT)) {
++ if (data->pl >= ((regs->cr_ipsr >>
++ IA64_PSR_CPL0_BIT) & 3))
++ emulate_io_inst(v, gppa, data->ma);
++ else {
++ vcpu_set_isr(v, misr.val);
++ data_access_rights(v, vadr);
++ }
++ return ;
++ }
++ }
++ thash_vhpt_insert(v, data->page_flags, data->itir, vadr, type);
++
++ } else if (type == D_TLB) {
++ if (misr.sp) {
++ handle_lds(regs);
++ return;
++ }
++
++ rr = vcpu_get_rr(v, vadr);
++ itir = rr & (RR_RID_MASK | RR_PS_MASK);
++
++ if (!vhpt_enabled(v, vadr, misr.rs ? RSE_REF : DATA_REF)) {
++ if (vpsr & IA64_PSR_IC) {
++ vcpu_set_isr(v, misr.val);
++ alt_dtlb(v, vadr);
++ } else {
++ nested_dtlb(v);
++ }
++ return ;
++ }
++
++ vpta.val = vcpu_get_pta(v);
++ /* avoid recursively walking (short format) VHPT */
++
++ vhpt_adr = vcpu_thash(v, vadr);
++ if (!guest_vhpt_lookup(vhpt_adr, &pteval)) {
++ /* VHPT successfully read. */
++ if (!(pteval & _PAGE_P)) {
++ if (vpsr & IA64_PSR_IC) {
++ vcpu_set_isr(v, misr.val);
++ dtlb_fault(v, vadr);
++ } else {
++ nested_dtlb(v);
++ }
++ } else if ((pteval & _PAGE_MA_MASK) != _PAGE_MA_ST) {
++ thash_purge_and_insert(v, pteval, itir,
++ vadr, D_TLB);
++ } else if (vpsr & IA64_PSR_IC) {
++ vcpu_set_isr(v, misr.val);
++ dtlb_fault(v, vadr);
++ } else {
++ nested_dtlb(v);
++ }
++ } else {
++ /* Can't read VHPT. */
++ if (vpsr & IA64_PSR_IC) {
++ vcpu_set_isr(v, misr.val);
++ dvhpt_fault(v, vadr);
++ } else {
++ nested_dtlb(v);
++ }
++ }
++ } else if (type == I_TLB) {
++ if (!(vpsr & IA64_PSR_IC))
++ misr.ni = 1;
++ if (!vhpt_enabled(v, vadr, INST_REF)) {
++ vcpu_set_isr(v, misr.val);
++ alt_itlb(v, vadr);
++ return;
++ }
++
++ vpta.val = vcpu_get_pta(v);
++
++ vhpt_adr = vcpu_thash(v, vadr);
++ if (!guest_vhpt_lookup(vhpt_adr, &pteval)) {
++ /* VHPT successfully read. */
++ if (pteval & _PAGE_P) {
++ if ((pteval & _PAGE_MA_MASK) == _PAGE_MA_ST) {
++ vcpu_set_isr(v, misr.val);
++ itlb_fault(v, vadr);
++ return ;
++ }
++ rr = vcpu_get_rr(v, vadr);
++ itir = rr & (RR_RID_MASK | RR_PS_MASK);
++ thash_purge_and_insert(v, pteval, itir,
++ vadr, I_TLB);
++ } else {
++ vcpu_set_isr(v, misr.val);
++ inst_page_not_present(v, vadr);
++ }
++ } else {
++ vcpu_set_isr(v, misr.val);
++ ivhpt_fault(v, vadr);
++ }
++ }
++}
++
++void kvm_vexirq(struct kvm_vcpu *vcpu)
++{
++ u64 vpsr, isr;
++ struct kvm_pt_regs *regs;
++
++ regs = vcpu_regs(vcpu);
++ vpsr = VCPU(vcpu, vpsr);
++ isr = vpsr & IA64_PSR_RI;
++ reflect_interruption(0, isr, 0, 12, regs); /*EXT IRQ*/
++}
++
++void kvm_ia64_handle_irq(struct kvm_vcpu *v)
++{
++ struct exit_ctl_data *p = &v->arch.exit_data;
++ long psr;
++
++ local_irq_save(psr);
++ p->exit_reason = EXIT_REASON_EXTERNAL_INTERRUPT;
++ vmm_transition(v);
++ local_irq_restore(psr);
++
++ VMX(v, timer_check) = 1;
++
++}
++
++static void ptc_ga_remote_func(struct kvm_vcpu *v, int pos)
++{
++ u64 oldrid, moldrid, oldpsbits, vaddr;
++ struct kvm_ptc_g *p = &v->arch.ptc_g_data[pos];
++ vaddr = p->vaddr;
++
++ oldrid = VMX(v, vrr[0]);
++ VMX(v, vrr[0]) = p->rr;
++ oldpsbits = VMX(v, psbits[0]);
++ VMX(v, psbits[0]) = VMX(v, psbits[REGION_NUMBER(vaddr)]);
++ moldrid = ia64_get_rr(0x0);
++ ia64_set_rr(0x0, vrrtomrr(p->rr));
++ ia64_srlz_d();
++
++ vaddr = PAGEALIGN(vaddr, p->ps);
++ thash_purge_entries_remote(v, vaddr, p->ps);
++
++ VMX(v, vrr[0]) = oldrid;
++ VMX(v, psbits[0]) = oldpsbits;
++ ia64_set_rr(0x0, moldrid);
++ ia64_dv_serialize_data();
++}
++
++static void vcpu_do_resume(struct kvm_vcpu *vcpu)
++{
++ /*Re-init VHPT and VTLB once from resume*/
++ vcpu->arch.vhpt.num = VHPT_NUM_ENTRIES;
++ thash_init(&vcpu->arch.vhpt, VHPT_SHIFT);
++ vcpu->arch.vtlb.num = VTLB_NUM_ENTRIES;
++ thash_init(&vcpu->arch.vtlb, VTLB_SHIFT);
++
++ ia64_set_pta(vcpu->arch.vhpt.pta.val);
++}
++
++static void kvm_do_resume_op(struct kvm_vcpu *vcpu)
++{
++ if (test_and_clear_bit(KVM_REQ_RESUME, &vcpu->requests)) {
++ vcpu_do_resume(vcpu);
++ return;
++ }
++
++ if (unlikely(test_and_clear_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests))) {
++ thash_purge_all(vcpu);
++ return;
++ }
++
++ if (test_and_clear_bit(KVM_REQ_PTC_G, &vcpu->requests)) {
++ while (vcpu->arch.ptc_g_count > 0)
++ ptc_ga_remote_func(vcpu, --vcpu->arch.ptc_g_count);
++ }
++}
++
++void vmm_transition(struct kvm_vcpu *vcpu)
++{
++ ia64_call_vsa(PAL_VPS_SAVE, (unsigned long)vcpu->arch.vpd,
++ 0, 0, 0, 0, 0, 0);
++ vmm_trampoline(&vcpu->arch.guest, &vcpu->arch.host);
++ ia64_call_vsa(PAL_VPS_RESTORE, (unsigned long)vcpu->arch.vpd,
++ 0, 0, 0, 0, 0, 0);
++ kvm_do_resume_op(vcpu);
++}
+diff --git a/arch/ia64/kvm/trampoline.S b/arch/ia64/kvm/trampoline.S
+new file mode 100644
+index 0000000..30897d4
+--- /dev/null
++++ b/arch/ia64/kvm/trampoline.S
+@@ -0,0 +1,1038 @@
++/* Save all processor states
++ *
++ * Copyright (c) 2007 Fleming Feng <fleming.feng at intel.com>
++ * Copyright (c) 2007 Anthony Xu <anthony.xu at intel.com>
++ */
++
++#include <asm/asmmacro.h>
++#include "asm-offsets.h"
++
++
++#define CTX(name) VMM_CTX_##name##_OFFSET
++
++ /*
++ * r32: context_t base address
++ */
++#define SAVE_BRANCH_REGS \
++ add r2 = CTX(B0),r32; \
++ add r3 = CTX(B1),r32; \
++ mov r16 = b0; \
++ mov r17 = b1; \
++ ;; \
++ st8 [r2]=r16,16; \
++ st8 [r3]=r17,16; \
++ ;; \
++ mov r16 = b2; \
++ mov r17 = b3; \
++ ;; \
++ st8 [r2]=r16,16; \
++ st8 [r3]=r17,16; \
++ ;; \
++ mov r16 = b4; \
++ mov r17 = b5; \
++ ;; \
++ st8 [r2]=r16; \
++ st8 [r3]=r17; \
++ ;;
++
++ /*
++ * r33: context_t base address
++ */
++#define RESTORE_BRANCH_REGS \
++ add r2 = CTX(B0),r33; \
++ add r3 = CTX(B1),r33; \
++ ;; \
++ ld8 r16=[r2],16; \
++ ld8 r17=[r3],16; \
++ ;; \
++ mov b0 = r16; \
++ mov b1 = r17; \
++ ;; \
++ ld8 r16=[r2],16; \
++ ld8 r17=[r3],16; \
++ ;; \
++ mov b2 = r16; \
++ mov b3 = r17; \
++ ;; \
++ ld8 r16=[r2]; \
++ ld8 r17=[r3]; \
++ ;; \
++ mov b4=r16; \
++ mov b5=r17; \
++ ;;
++
++
++ /*
++ * r32: context_t base address
++ * bsw == 1
++ * Save all bank1 general registers, r4 ~ r7
++ */
++#define SAVE_GENERAL_REGS \
++ add r2=CTX(R4),r32; \
++ add r3=CTX(R5),r32; \
++ ;; \
++.mem.offset 0,0; \
++ st8.spill [r2]=r4,16; \
++.mem.offset 8,0; \
++ st8.spill [r3]=r5,16; \
++ ;; \
++.mem.offset 0,0; \
++ st8.spill [r2]=r6,48; \
++.mem.offset 8,0; \
++ st8.spill [r3]=r7,48; \
++ ;; \
++.mem.offset 0,0; \
++ st8.spill [r2]=r12; \
++.mem.offset 8,0; \
++ st8.spill [r3]=r13; \
++ ;;
++
++ /*
++ * r33: context_t base address
++ * bsw == 1
++ */
++#define RESTORE_GENERAL_REGS \
++ add r2=CTX(R4),r33; \
++ add r3=CTX(R5),r33; \
++ ;; \
++ ld8.fill r4=[r2],16; \
++ ld8.fill r5=[r3],16; \
++ ;; \
++ ld8.fill r6=[r2],48; \
++ ld8.fill r7=[r3],48; \
++ ;; \
++ ld8.fill r12=[r2]; \
++ ld8.fill r13 =[r3]; \
++ ;;
++
++
++
++
++ /*
++ * r32: context_t base address
++ */
++#define SAVE_KERNEL_REGS \
++ add r2 = CTX(KR0),r32; \
++ add r3 = CTX(KR1),r32; \
++ mov r16 = ar.k0; \
++ mov r17 = ar.k1; \
++ ;; \
++ st8 [r2] = r16,16; \
++ st8 [r3] = r17,16; \
++ ;; \
++ mov r16 = ar.k2; \
++ mov r17 = ar.k3; \
++ ;; \
++ st8 [r2] = r16,16; \
++ st8 [r3] = r17,16; \
++ ;; \
++ mov r16 = ar.k4; \
++ mov r17 = ar.k5; \
++ ;; \
++ st8 [r2] = r16,16; \
++ st8 [r3] = r17,16; \
++ ;; \
++ mov r16 = ar.k6; \
++ mov r17 = ar.k7; \
++ ;; \
++ st8 [r2] = r16; \
++ st8 [r3] = r17; \
++ ;;
++
++
++
++ /*
++ * r33: context_t base address
++ */
++#define RESTORE_KERNEL_REGS \
++ add r2 = CTX(KR0),r33; \
++ add r3 = CTX(KR1),r33; \
++ ;; \
++ ld8 r16=[r2],16; \
++ ld8 r17=[r3],16; \
++ ;; \
++ mov ar.k0=r16; \
++ mov ar.k1=r17; \
++ ;; \
++ ld8 r16=[r2],16; \
++ ld8 r17=[r3],16; \
++ ;; \
++ mov ar.k2=r16; \
++ mov ar.k3=r17; \
++ ;; \
++ ld8 r16=[r2],16; \
++ ld8 r17=[r3],16; \
++ ;; \
++ mov ar.k4=r16; \
++ mov ar.k5=r17; \
++ ;; \
++ ld8 r16=[r2],16; \
++ ld8 r17=[r3],16; \
++ ;; \
++ mov ar.k6=r16; \
++ mov ar.k7=r17; \
++ ;;
++
++
++
++ /*
++ * r32: context_t base address
++ */
++#define SAVE_APP_REGS \
++ add r2 = CTX(BSPSTORE),r32; \
++ mov r16 = ar.bspstore; \
++ ;; \
++ st8 [r2] = r16,CTX(RNAT)-CTX(BSPSTORE);\
++ mov r16 = ar.rnat; \
++ ;; \
++ st8 [r2] = r16,CTX(FCR)-CTX(RNAT); \
++ mov r16 = ar.fcr; \
++ ;; \
++ st8 [r2] = r16,CTX(EFLAG)-CTX(FCR); \
++ mov r16 = ar.eflag; \
++ ;; \
++ st8 [r2] = r16,CTX(CFLG)-CTX(EFLAG); \
++ mov r16 = ar.cflg; \
++ ;; \
++ st8 [r2] = r16,CTX(FSR)-CTX(CFLG); \
++ mov r16 = ar.fsr; \
++ ;; \
++ st8 [r2] = r16,CTX(FIR)-CTX(FSR); \
++ mov r16 = ar.fir; \
++ ;; \
++ st8 [r2] = r16,CTX(FDR)-CTX(FIR); \
++ mov r16 = ar.fdr; \
++ ;; \
++ st8 [r2] = r16,CTX(UNAT)-CTX(FDR); \
++ mov r16 = ar.unat; \
++ ;; \
++ st8 [r2] = r16,CTX(FPSR)-CTX(UNAT); \
++ mov r16 = ar.fpsr; \
++ ;; \
++ st8 [r2] = r16,CTX(PFS)-CTX(FPSR); \
++ mov r16 = ar.pfs; \
++ ;; \
++ st8 [r2] = r16,CTX(LC)-CTX(PFS); \
++ mov r16 = ar.lc; \
++ ;; \
++ st8 [r2] = r16; \
++ ;;
++
++ /*
++ * r33: context_t base address
++ */
++#define RESTORE_APP_REGS \
++ add r2=CTX(BSPSTORE),r33; \
++ ;; \
++ ld8 r16=[r2],CTX(RNAT)-CTX(BSPSTORE); \
++ ;; \
++ mov ar.bspstore=r16; \
++ ld8 r16=[r2],CTX(FCR)-CTX(RNAT); \
++ ;; \
++ mov ar.rnat=r16; \
++ ld8 r16=[r2],CTX(EFLAG)-CTX(FCR); \
++ ;; \
++ mov ar.fcr=r16; \
++ ld8 r16=[r2],CTX(CFLG)-CTX(EFLAG); \
++ ;; \
++ mov ar.eflag=r16; \
++ ld8 r16=[r2],CTX(FSR)-CTX(CFLG); \
++ ;; \
++ mov ar.cflg=r16; \
++ ld8 r16=[r2],CTX(FIR)-CTX(FSR); \
++ ;; \
++ mov ar.fsr=r16; \
++ ld8 r16=[r2],CTX(FDR)-CTX(FIR); \
++ ;; \
++ mov ar.fir=r16; \
++ ld8 r16=[r2],CTX(UNAT)-CTX(FDR); \
++ ;; \
++ mov ar.fdr=r16; \
++ ld8 r16=[r2],CTX(FPSR)-CTX(UNAT); \
++ ;; \
++ mov ar.unat=r16; \
++ ld8 r16=[r2],CTX(PFS)-CTX(FPSR); \
++ ;; \
++ mov ar.fpsr=r16; \
++ ld8 r16=[r2],CTX(LC)-CTX(PFS); \
++ ;; \
++ mov ar.pfs=r16; \
++ ld8 r16=[r2]; \
++ ;; \
++ mov ar.lc=r16; \
++ ;;
++
++ /*
++ * r32: context_t base address
++ */
++#define SAVE_CTL_REGS \
++ add r2 = CTX(DCR),r32; \
++ mov r16 = cr.dcr; \
++ ;; \
++ st8 [r2] = r16,CTX(IVA)-CTX(DCR); \
++ ;; \
++ mov r16 = cr.iva; \
++ ;; \
++ st8 [r2] = r16,CTX(PTA)-CTX(IVA); \
++ ;; \
++ mov r16 = cr.pta; \
++ ;; \
++ st8 [r2] = r16 ; \
++ ;;
++
++ /*
++ * r33: context_t base address
++ */
++#define RESTORE_CTL_REGS \
++ add r2 = CTX(DCR),r33; \
++ ;; \
++ ld8 r16 = [r2],CTX(IVA)-CTX(DCR); \
++ ;; \
++ mov cr.dcr = r16; \
++ dv_serialize_data; \
++ ;; \
++ ld8 r16 = [r2],CTX(PTA)-CTX(IVA); \
++ ;; \
++ mov cr.iva = r16; \
++ dv_serialize_data; \
++ ;; \
++ ld8 r16 = [r2]; \
++ ;; \
++ mov cr.pta = r16; \
++ dv_serialize_data; \
++ ;;
++
++
++ /*
++ * r32: context_t base address
++ */
++#define SAVE_REGION_REGS \
++ add r2=CTX(RR0),r32; \
++ mov r16=rr[r0]; \
++ dep.z r18=1,61,3; \
++ ;; \
++ st8 [r2]=r16,8; \
++ mov r17=rr[r18]; \
++ dep.z r18=2,61,3; \
++ ;; \
++ st8 [r2]=r17,8; \
++ mov r16=rr[r18]; \
++ dep.z r18=3,61,3; \
++ ;; \
++ st8 [r2]=r16,8; \
++ mov r17=rr[r18]; \
++ dep.z r18=4,61,3; \
++ ;; \
++ st8 [r2]=r17,8; \
++ mov r16=rr[r18]; \
++ dep.z r18=5,61,3; \
++ ;; \
++ st8 [r2]=r16,8; \
++ mov r17=rr[r18]; \
++ dep.z r18=7,61,3; \
++ ;; \
++ st8 [r2]=r17,16; \
++ mov r16=rr[r18]; \
++ ;; \
++ st8 [r2]=r16,8; \
++ ;;
++
++ /*
++ * r33:context_t base address
++ */
++#define RESTORE_REGION_REGS \
++ add r2=CTX(RR0),r33;\
++ mov r18=r0; \
++ ;; \
++ ld8 r20=[r2],8; \
++ ;; /* rr0 */ \
++ ld8 r21=[r2],8; \
++ ;; /* rr1 */ \
++ ld8 r22=[r2],8; \
++ ;; /* rr2 */ \
++ ld8 r23=[r2],8; \
++ ;; /* rr3 */ \
++ ld8 r24=[r2],8; \
++ ;; /* rr4 */ \
++ ld8 r25=[r2],16; \
++ ;; /* rr5 */ \
++ ld8 r27=[r2]; \
++ ;; /* rr7 */ \
++ mov rr[r18]=r20; \
++ dep.z r18=1,61,3; \
++ ;; /* rr1 */ \
++ mov rr[r18]=r21; \
++ dep.z r18=2,61,3; \
++ ;; /* rr2 */ \
++ mov rr[r18]=r22; \
++ dep.z r18=3,61,3; \
++ ;; /* rr3 */ \
++ mov rr[r18]=r23; \
++ dep.z r18=4,61,3; \
++ ;; /* rr4 */ \
++ mov rr[r18]=r24; \
++ dep.z r18=5,61,3; \
++ ;; /* rr5 */ \
++ mov rr[r18]=r25; \
++ dep.z r18=7,61,3; \
++ ;; /* rr7 */ \
++ mov rr[r18]=r27; \
++ ;; \
++ srlz.i; \
++ ;;
++
++
++
++ /*
++ * r32: context_t base address
++ * r36~r39:scratch registers
++ */
++#define SAVE_DEBUG_REGS \
++ add r2=CTX(IBR0),r32; \
++ add r3=CTX(DBR0),r32; \
++ mov r16=ibr[r0]; \
++ mov r17=dbr[r0]; \
++ ;; \
++ st8 [r2]=r16,8; \
++ st8 [r3]=r17,8; \
++ add r18=1,r0; \
++ ;; \
++ mov r16=ibr[r18]; \
++ mov r17=dbr[r18]; \
++ ;; \
++ st8 [r2]=r16,8; \
++ st8 [r3]=r17,8; \
++ add r18=2,r0; \
++ ;; \
++ mov r16=ibr[r18]; \
++ mov r17=dbr[r18]; \
++ ;; \
++ st8 [r2]=r16,8; \
++ st8 [r3]=r17,8; \
++ add r18=2,r0; \
++ ;; \
++ mov r16=ibr[r18]; \
++ mov r17=dbr[r18]; \
++ ;; \
++ st8 [r2]=r16,8; \
++ st8 [r3]=r17,8; \
++ add r18=3,r0; \
++ ;; \
++ mov r16=ibr[r18]; \
++ mov r17=dbr[r18]; \
++ ;; \
++ st8 [r2]=r16,8; \
++ st8 [r3]=r17,8; \
++ add r18=4,r0; \
++ ;; \
++ mov r16=ibr[r18]; \
++ mov r17=dbr[r18]; \
++ ;; \
++ st8 [r2]=r16,8; \
++ st8 [r3]=r17,8; \
++ add r18=5,r0; \
++ ;; \
++ mov r16=ibr[r18]; \
++ mov r17=dbr[r18]; \
++ ;; \
++ st8 [r2]=r16,8; \
++ st8 [r3]=r17,8; \
++ add r18=6,r0; \
++ ;; \
++ mov r16=ibr[r18]; \
++ mov r17=dbr[r18]; \
++ ;; \
++ st8 [r2]=r16,8; \
++ st8 [r3]=r17,8; \
++ add r18=7,r0; \
++ ;; \
++ mov r16=ibr[r18]; \
++ mov r17=dbr[r18]; \
++ ;; \
++ st8 [r2]=r16,8; \
++ st8 [r3]=r17,8; \
++ ;;
++
++
++/*
++ * r33: point to context_t structure
++ * ar.lc are corrupted.
++ */
++#define RESTORE_DEBUG_REGS \
++ add r2=CTX(IBR0),r33; \
++ add r3=CTX(DBR0),r33; \
++ mov r16=7; \
++ mov r17=r0; \
++ ;; \
++ mov ar.lc = r16; \
++ ;; \
++1: \
++ ld8 r18=[r2],8; \
++ ld8 r19=[r3],8; \
++ ;; \
++ mov ibr[r17]=r18; \
++ mov dbr[r17]=r19; \
++ ;; \
++ srlz.i; \
++ ;; \
++ add r17=1,r17; \
++ br.cloop.sptk 1b; \
++ ;;
++
++
++ /*
++ * r32: context_t base address
++ */
++#define SAVE_FPU_LOW \
++ add r2=CTX(F2),r32; \
++ add r3=CTX(F3),r32; \
++ ;; \
++ stf.spill.nta [r2]=f2,32; \
++ stf.spill.nta [r3]=f3,32; \
++ ;; \
++ stf.spill.nta [r2]=f4,32; \
++ stf.spill.nta [r3]=f5,32; \
++ ;; \
++ stf.spill.nta [r2]=f6,32; \
++ stf.spill.nta [r3]=f7,32; \
++ ;; \
++ stf.spill.nta [r2]=f8,32; \
++ stf.spill.nta [r3]=f9,32; \
++ ;; \
++ stf.spill.nta [r2]=f10,32; \
++ stf.spill.nta [r3]=f11,32; \
++ ;; \
++ stf.spill.nta [r2]=f12,32; \
++ stf.spill.nta [r3]=f13,32; \
++ ;; \
++ stf.spill.nta [r2]=f14,32; \
++ stf.spill.nta [r3]=f15,32; \
++ ;; \
++ stf.spill.nta [r2]=f16,32; \
++ stf.spill.nta [r3]=f17,32; \
++ ;; \
++ stf.spill.nta [r2]=f18,32; \
++ stf.spill.nta [r3]=f19,32; \
++ ;; \
++ stf.spill.nta [r2]=f20,32; \
++ stf.spill.nta [r3]=f21,32; \
++ ;; \
++ stf.spill.nta [r2]=f22,32; \
++ stf.spill.nta [r3]=f23,32; \
++ ;; \
++ stf.spill.nta [r2]=f24,32; \
++ stf.spill.nta [r3]=f25,32; \
++ ;; \
++ stf.spill.nta [r2]=f26,32; \
++ stf.spill.nta [r3]=f27,32; \
++ ;; \
++ stf.spill.nta [r2]=f28,32; \
++ stf.spill.nta [r3]=f29,32; \
++ ;; \
++ stf.spill.nta [r2]=f30; \
++ stf.spill.nta [r3]=f31; \
++ ;;
++
++ /*
++ * r32: context_t base address
++ */
++#define SAVE_FPU_HIGH \
++ add r2=CTX(F32),r32; \
++ add r3=CTX(F33),r32; \
++ ;; \
++ stf.spill.nta [r2]=f32,32; \
++ stf.spill.nta [r3]=f33,32; \
++ ;; \
++ stf.spill.nta [r2]=f34,32; \
++ stf.spill.nta [r3]=f35,32; \
++ ;; \
++ stf.spill.nta [r2]=f36,32; \
++ stf.spill.nta [r3]=f37,32; \
++ ;; \
++ stf.spill.nta [r2]=f38,32; \
++ stf.spill.nta [r3]=f39,32; \
++ ;; \
++ stf.spill.nta [r2]=f40,32; \
++ stf.spill.nta [r3]=f41,32; \
++ ;; \
++ stf.spill.nta [r2]=f42,32; \
++ stf.spill.nta [r3]=f43,32; \
++ ;; \
++ stf.spill.nta [r2]=f44,32; \
++ stf.spill.nta [r3]=f45,32; \
++ ;; \
++ stf.spill.nta [r2]=f46,32; \
++ stf.spill.nta [r3]=f47,32; \
++ ;; \
++ stf.spill.nta [r2]=f48,32; \
++ stf.spill.nta [r3]=f49,32; \
++ ;; \
++ stf.spill.nta [r2]=f50,32; \
++ stf.spill.nta [r3]=f51,32; \
++ ;; \
++ stf.spill.nta [r2]=f52,32; \
++ stf.spill.nta [r3]=f53,32; \
++ ;; \
++ stf.spill.nta [r2]=f54,32; \
++ stf.spill.nta [r3]=f55,32; \
++ ;; \
++ stf.spill.nta [r2]=f56,32; \
++ stf.spill.nta [r3]=f57,32; \
++ ;; \
++ stf.spill.nta [r2]=f58,32; \
++ stf.spill.nta [r3]=f59,32; \
++ ;; \
++ stf.spill.nta [r2]=f60,32; \
++ stf.spill.nta [r3]=f61,32; \
++ ;; \
++ stf.spill.nta [r2]=f62,32; \
++ stf.spill.nta [r3]=f63,32; \
++ ;; \
++ stf.spill.nta [r2]=f64,32; \
++ stf.spill.nta [r3]=f65,32; \
++ ;; \
++ stf.spill.nta [r2]=f66,32; \
++ stf.spill.nta [r3]=f67,32; \
++ ;; \
++ stf.spill.nta [r2]=f68,32; \
++ stf.spill.nta [r3]=f69,32; \
++ ;; \
++ stf.spill.nta [r2]=f70,32; \
++ stf.spill.nta [r3]=f71,32; \
++ ;; \
++ stf.spill.nta [r2]=f72,32; \
++ stf.spill.nta [r3]=f73,32; \
++ ;; \
++ stf.spill.nta [r2]=f74,32; \
++ stf.spill.nta [r3]=f75,32; \
++ ;; \
++ stf.spill.nta [r2]=f76,32; \
++ stf.spill.nta [r3]=f77,32; \
++ ;; \
++ stf.spill.nta [r2]=f78,32; \
++ stf.spill.nta [r3]=f79,32; \
++ ;; \
++ stf.spill.nta [r2]=f80,32; \
++ stf.spill.nta [r3]=f81,32; \
++ ;; \
++ stf.spill.nta [r2]=f82,32; \
++ stf.spill.nta [r3]=f83,32; \
++ ;; \
++ stf.spill.nta [r2]=f84,32; \
++ stf.spill.nta [r3]=f85,32; \
++ ;; \
++ stf.spill.nta [r2]=f86,32; \
++ stf.spill.nta [r3]=f87,32; \
++ ;; \
++ stf.spill.nta [r2]=f88,32; \
++ stf.spill.nta [r3]=f89,32; \
++ ;; \
++ stf.spill.nta [r2]=f90,32; \
++ stf.spill.nta [r3]=f91,32; \
++ ;; \
++ stf.spill.nta [r2]=f92,32; \
++ stf.spill.nta [r3]=f93,32; \
++ ;; \
++ stf.spill.nta [r2]=f94,32; \
++ stf.spill.nta [r3]=f95,32; \
++ ;; \
++ stf.spill.nta [r2]=f96,32; \
++ stf.spill.nta [r3]=f97,32; \
++ ;; \
++ stf.spill.nta [r2]=f98,32; \
++ stf.spill.nta [r3]=f99,32; \
++ ;; \
++ stf.spill.nta [r2]=f100,32; \
++ stf.spill.nta [r3]=f101,32; \
++ ;; \
++ stf.spill.nta [r2]=f102,32; \
++ stf.spill.nta [r3]=f103,32; \
++ ;; \
++ stf.spill.nta [r2]=f104,32; \
++ stf.spill.nta [r3]=f105,32; \
++ ;; \
++ stf.spill.nta [r2]=f106,32; \
++ stf.spill.nta [r3]=f107,32; \
++ ;; \
++ stf.spill.nta [r2]=f108,32; \
++ stf.spill.nta [r3]=f109,32; \
++ ;; \
++ stf.spill.nta [r2]=f110,32; \
++ stf.spill.nta [r3]=f111,32; \
++ ;; \
++ stf.spill.nta [r2]=f112,32; \
++ stf.spill.nta [r3]=f113,32; \
++ ;; \
++ stf.spill.nta [r2]=f114,32; \
++ stf.spill.nta [r3]=f115,32; \
++ ;; \
++ stf.spill.nta [r2]=f116,32; \
++ stf.spill.nta [r3]=f117,32; \
++ ;; \
++ stf.spill.nta [r2]=f118,32; \
++ stf.spill.nta [r3]=f119,32; \
++ ;; \
++ stf.spill.nta [r2]=f120,32; \
++ stf.spill.nta [r3]=f121,32; \
++ ;; \
++ stf.spill.nta [r2]=f122,32; \
++ stf.spill.nta [r3]=f123,32; \
++ ;; \
++ stf.spill.nta [r2]=f124,32; \
++ stf.spill.nta [r3]=f125,32; \
++ ;; \
++ stf.spill.nta [r2]=f126; \
++ stf.spill.nta [r3]=f127; \
++ ;;
++
++ /*
++ * r33: point to context_t structure
++ */
++#define RESTORE_FPU_LOW \
++ add r2 = CTX(F2), r33; \
++ add r3 = CTX(F3), r33; \
++ ;; \
++ ldf.fill.nta f2 = [r2], 32; \
++ ldf.fill.nta f3 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f4 = [r2], 32; \
++ ldf.fill.nta f5 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f6 = [r2], 32; \
++ ldf.fill.nta f7 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f8 = [r2], 32; \
++ ldf.fill.nta f9 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f10 = [r2], 32; \
++ ldf.fill.nta f11 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f12 = [r2], 32; \
++ ldf.fill.nta f13 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f14 = [r2], 32; \
++ ldf.fill.nta f15 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f16 = [r2], 32; \
++ ldf.fill.nta f17 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f18 = [r2], 32; \
++ ldf.fill.nta f19 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f20 = [r2], 32; \
++ ldf.fill.nta f21 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f22 = [r2], 32; \
++ ldf.fill.nta f23 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f24 = [r2], 32; \
++ ldf.fill.nta f25 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f26 = [r2], 32; \
++ ldf.fill.nta f27 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f28 = [r2], 32; \
++ ldf.fill.nta f29 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f30 = [r2], 32; \
++ ldf.fill.nta f31 = [r3], 32; \
++ ;;
++
++
++
++ /*
++ * r33: point to context_t structure
++ */
++#define RESTORE_FPU_HIGH \
++ add r2 = CTX(F32), r33; \
++ add r3 = CTX(F33), r33; \
++ ;; \
++ ldf.fill.nta f32 = [r2], 32; \
++ ldf.fill.nta f33 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f34 = [r2], 32; \
++ ldf.fill.nta f35 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f36 = [r2], 32; \
++ ldf.fill.nta f37 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f38 = [r2], 32; \
++ ldf.fill.nta f39 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f40 = [r2], 32; \
++ ldf.fill.nta f41 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f42 = [r2], 32; \
++ ldf.fill.nta f43 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f44 = [r2], 32; \
++ ldf.fill.nta f45 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f46 = [r2], 32; \
++ ldf.fill.nta f47 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f48 = [r2], 32; \
++ ldf.fill.nta f49 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f50 = [r2], 32; \
++ ldf.fill.nta f51 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f52 = [r2], 32; \
++ ldf.fill.nta f53 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f54 = [r2], 32; \
++ ldf.fill.nta f55 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f56 = [r2], 32; \
++ ldf.fill.nta f57 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f58 = [r2], 32; \
++ ldf.fill.nta f59 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f60 = [r2], 32; \
++ ldf.fill.nta f61 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f62 = [r2], 32; \
++ ldf.fill.nta f63 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f64 = [r2], 32; \
++ ldf.fill.nta f65 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f66 = [r2], 32; \
++ ldf.fill.nta f67 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f68 = [r2], 32; \
++ ldf.fill.nta f69 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f70 = [r2], 32; \
++ ldf.fill.nta f71 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f72 = [r2], 32; \
++ ldf.fill.nta f73 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f74 = [r2], 32; \
++ ldf.fill.nta f75 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f76 = [r2], 32; \
++ ldf.fill.nta f77 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f78 = [r2], 32; \
++ ldf.fill.nta f79 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f80 = [r2], 32; \
++ ldf.fill.nta f81 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f82 = [r2], 32; \
++ ldf.fill.nta f83 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f84 = [r2], 32; \
++ ldf.fill.nta f85 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f86 = [r2], 32; \
++ ldf.fill.nta f87 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f88 = [r2], 32; \
++ ldf.fill.nta f89 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f90 = [r2], 32; \
++ ldf.fill.nta f91 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f92 = [r2], 32; \
++ ldf.fill.nta f93 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f94 = [r2], 32; \
++ ldf.fill.nta f95 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f96 = [r2], 32; \
++ ldf.fill.nta f97 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f98 = [r2], 32; \
++ ldf.fill.nta f99 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f100 = [r2], 32; \
++ ldf.fill.nta f101 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f102 = [r2], 32; \
++ ldf.fill.nta f103 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f104 = [r2], 32; \
++ ldf.fill.nta f105 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f106 = [r2], 32; \
++ ldf.fill.nta f107 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f108 = [r2], 32; \
++ ldf.fill.nta f109 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f110 = [r2], 32; \
++ ldf.fill.nta f111 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f112 = [r2], 32; \
++ ldf.fill.nta f113 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f114 = [r2], 32; \
++ ldf.fill.nta f115 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f116 = [r2], 32; \
++ ldf.fill.nta f117 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f118 = [r2], 32; \
++ ldf.fill.nta f119 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f120 = [r2], 32; \
++ ldf.fill.nta f121 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f122 = [r2], 32; \
++ ldf.fill.nta f123 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f124 = [r2], 32; \
++ ldf.fill.nta f125 = [r3], 32; \
++ ;; \
++ ldf.fill.nta f126 = [r2], 32; \
++ ldf.fill.nta f127 = [r3], 32; \
++ ;;
++
++ /*
++ * r32: context_t base address
++ */
++#define SAVE_PTK_REGS \
++ add r2=CTX(PKR0), r32; \
++ mov r16=7; \
++ ;; \
++ mov ar.lc=r16; \
++ mov r17=r0; \
++ ;; \
++1: \
++ mov r18=pkr[r17]; \
++ ;; \
++ srlz.i; \
++ ;; \
++ st8 [r2]=r18, 8; \
++ ;; \
++ add r17 =1,r17; \
++ ;; \
++ br.cloop.sptk 1b; \
++ ;;
++
++/*
++ * r33: point to context_t structure
++ * ar.lc are corrupted.
++ */
++#define RESTORE_PTK_REGS \
++ add r2=CTX(PKR0), r33; \
++ mov r16=7; \
++ ;; \
++ mov ar.lc=r16; \
++ mov r17=r0; \
++ ;; \
++1: \
++ ld8 r18=[r2], 8; \
++ ;; \
++ mov pkr[r17]=r18; \
++ ;; \
++ srlz.i; \
++ ;; \
++ add r17 =1,r17; \
++ ;; \
++ br.cloop.sptk 1b; \
++ ;;
++
++
++/*
++ * void vmm_trampoline( context_t * from,
++ * context_t * to)
++ *
++ * from: r32
++ * to: r33
++ * note: interrupt disabled before call this function.
++ */
++GLOBAL_ENTRY(vmm_trampoline)
++ mov r16 = psr
++ adds r2 = CTX(PSR), r32
++ ;;
++ st8 [r2] = r16, 8 // psr
++ mov r17 = pr
++ ;;
++ st8 [r2] = r17, 8 // pr
++ mov r18 = ar.unat
++ ;;
++ st8 [r2] = r18
++ mov r17 = ar.rsc
++ ;;
++ adds r2 = CTX(RSC),r32
++ ;;
++ st8 [r2]= r17
++ mov ar.rsc =0
++ flushrs
++ ;;
++ SAVE_GENERAL_REGS
++ ;;
++ SAVE_KERNEL_REGS
++ ;;
++ SAVE_APP_REGS
++ ;;
++ SAVE_BRANCH_REGS
++ ;;
++ SAVE_CTL_REGS
++ ;;
++ SAVE_REGION_REGS
++ ;;
++ //SAVE_DEBUG_REGS
++ ;;
++ rsm psr.dfl
++ ;;
++ srlz.d
++ ;;
++ SAVE_FPU_LOW
++ ;;
++ rsm psr.dfh
++ ;;
++ srlz.d
++ ;;
++ SAVE_FPU_HIGH
++ ;;
++ SAVE_PTK_REGS
++ ;;
++ RESTORE_PTK_REGS
++ ;;
++ RESTORE_FPU_HIGH
++ ;;
++ RESTORE_FPU_LOW
++ ;;
++ //RESTORE_DEBUG_REGS
++ ;;
++ RESTORE_REGION_REGS
++ ;;
++ RESTORE_CTL_REGS
++ ;;
++ RESTORE_BRANCH_REGS
++ ;;
++ RESTORE_APP_REGS
++ ;;
++ RESTORE_KERNEL_REGS
++ ;;
++ RESTORE_GENERAL_REGS
++ ;;
++ adds r2=CTX(PSR), r33
++ ;;
++ ld8 r16=[r2], 8 // psr
++ ;;
++ mov psr.l=r16
++ ;;
++ srlz.d
++ ;;
++ ld8 r16=[r2], 8 // pr
++ ;;
++ mov pr =r16,-1
++ ld8 r16=[r2] // unat
++ ;;
++ mov ar.unat=r16
++ ;;
++ adds r2=CTX(RSC),r33
++ ;;
++ ld8 r16 =[r2]
++ ;;
++ mov ar.rsc = r16
++ ;;
++ br.ret.sptk.few b0
++END(vmm_trampoline)
+diff --git a/arch/ia64/kvm/vcpu.c b/arch/ia64/kvm/vcpu.c
+new file mode 100644
+index 0000000..e44027c
+--- /dev/null
++++ b/arch/ia64/kvm/vcpu.c
+@@ -0,0 +1,2163 @@
++/*
++ * kvm_vcpu.c: handling all virtual cpu related thing.
++ * Copyright (c) 2005, 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,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You 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.
++ *
++ * Shaofan Li (Susue Li) <susie.li at intel.com>
++ * Yaozu Dong (Eddie Dong) (Eddie.dong at intel.com)
++ * Xuefei Xu (Anthony Xu) (Anthony.xu at intel.com)
++ * Xiantao Zhang <xiantao.zhang at intel.com>
++ */
++
++#include <linux/kvm_host.h>
++#include <linux/types.h>
++
++#include <asm/processor.h>
++#include <asm/ia64regs.h>
++#include <asm/gcc_intrin.h>
++#include <asm/kregs.h>
++#include <asm/pgtable.h>
++#include <asm/tlb.h>
++
++#include "asm-offsets.h"
++#include "vcpu.h"
++
++/*
++ * Special notes:
++ * - Index by it/dt/rt sequence
++ * - Only existing mode transitions are allowed in this table
++ * - RSE is placed at lazy mode when emulating guest partial mode
++ * - If gva happens to be rr0 and rr4, only allowed case is identity
++ * mapping (gva=gpa), or panic! (How?)
++ */
++int mm_switch_table[8][8] = {
++ /* 2004/09/12(Kevin): Allow switch to self */
++ /*
++ * (it,dt,rt): (0,0,0) -> (1,1,1)
++ * This kind of transition usually occurs in the very early
++ * stage of Linux boot up procedure. Another case is in efi
++ * and pal calls. (see "arch/ia64/kernel/head.S")
++ *
++ * (it,dt,rt): (0,0,0) -> (0,1,1)
++ * This kind of transition is found when OSYa exits efi boot
++ * service. Due to gva = gpa in this case (Same region),
++ * data access can be satisfied though itlb entry for physical
++ * emulation is hit.
++ */
++ {SW_SELF, 0, 0, SW_NOP, 0, 0, 0, SW_P2V},
++ {0, 0, 0, 0, 0, 0, 0, 0},
++ {0, 0, 0, 0, 0, 0, 0, 0},
++ /*
++ * (it,dt,rt): (0,1,1) -> (1,1,1)
++ * This kind of transition is found in OSYa.
++ *
++ * (it,dt,rt): (0,1,1) -> (0,0,0)
++ * This kind of transition is found in OSYa
++ */
++ {SW_NOP, 0, 0, SW_SELF, 0, 0, 0, SW_P2V},
++ /* (1,0,0)->(1,1,1) */
++ {0, 0, 0, 0, 0, 0, 0, SW_P2V},
++ /*
++ * (it,dt,rt): (1,0,1) -> (1,1,1)
++ * This kind of transition usually occurs when Linux returns
++ * from the low level TLB miss handlers.
++ * (see "arch/ia64/kernel/ivt.S")
++ */
++ {0, 0, 0, 0, 0, SW_SELF, 0, SW_P2V},
++ {0, 0, 0, 0, 0, 0, 0, 0},
++ /*
++ * (it,dt,rt): (1,1,1) -> (1,0,1)
++ * This kind of transition usually occurs in Linux low level
++ * TLB miss handler. (see "arch/ia64/kernel/ivt.S")
++ *
++ * (it,dt,rt): (1,1,1) -> (0,0,0)
++ * This kind of transition usually occurs in pal and efi calls,
++ * which requires running in physical mode.
++ * (see "arch/ia64/kernel/head.S")
++ * (1,1,1)->(1,0,0)
++ */
++
++ {SW_V2P, 0, 0, 0, SW_V2P, SW_V2P, 0, SW_SELF},
++};
++
++void physical_mode_init(struct kvm_vcpu *vcpu)
++{
++ vcpu->arch.mode_flags = GUEST_IN_PHY;
++}
++
++void switch_to_physical_rid(struct kvm_vcpu *vcpu)
++{
++ unsigned long psr;
++
++ /* Save original virtual mode rr[0] and rr[4] */
++ psr = ia64_clear_ic();
++ ia64_set_rr(VRN0<<VRN_SHIFT, vcpu->arch.metaphysical_rr0);
++ ia64_srlz_d();
++ ia64_set_rr(VRN4<<VRN_SHIFT, vcpu->arch.metaphysical_rr4);
++ ia64_srlz_d();
++
++ ia64_set_psr(psr);
++ return;
++}
++
++
++void switch_to_virtual_rid(struct kvm_vcpu *vcpu)
++{
++ unsigned long psr;
++
++ psr = ia64_clear_ic();
++ ia64_set_rr(VRN0 << VRN_SHIFT, vcpu->arch.metaphysical_saved_rr0);
++ ia64_srlz_d();
++ ia64_set_rr(VRN4 << VRN_SHIFT, vcpu->arch.metaphysical_saved_rr4);
++ ia64_srlz_d();
++ ia64_set_psr(psr);
++ return;
++}
++
++static int mm_switch_action(struct ia64_psr opsr, struct ia64_psr npsr)
++{
++ return mm_switch_table[MODE_IND(opsr)][MODE_IND(npsr)];
++}
++
++void switch_mm_mode(struct kvm_vcpu *vcpu, struct ia64_psr old_psr,
++ struct ia64_psr new_psr)
++{
++ int act;
++ act = mm_switch_action(old_psr, new_psr);
++ switch (act) {
++ case SW_V2P:
++ /*printk("V -> P mode transition: (0x%lx -> 0x%lx)\n",
++ old_psr.val, new_psr.val);*/
++ switch_to_physical_rid(vcpu);
++ /*
++ * Set rse to enforced lazy, to prevent active rse
++ *save/restor when guest physical mode.
++ */
++ vcpu->arch.mode_flags |= GUEST_IN_PHY;
++ break;
++ case SW_P2V:
++ switch_to_virtual_rid(vcpu);
++ /*
++ * recover old mode which is saved when entering
++ * guest physical mode
++ */
++ vcpu->arch.mode_flags &= ~GUEST_IN_PHY;
++ break;
++ case SW_SELF:
++ break;
++ case SW_NOP:
++ break;
++ default:
++ /* Sanity check */
++ break;
++ }
++ return;
++}
++
++
++
++/*
++ * In physical mode, insert tc/tr for region 0 and 4 uses
++ * RID[0] and RID[4] which is for physical mode emulation.
++ * However what those inserted tc/tr wants is rid for
++ * virtual mode. So original virtual rid needs to be restored
++ * before insert.
++ *
++ * Operations which required such switch include:
++ * - insertions (itc.*, itr.*)
++ * - purges (ptc.* and ptr.*)
++ * - tpa
++ * - tak
++ * - thash?, ttag?
++ * All above needs actual virtual rid for destination entry.
++ */
++
++void check_mm_mode_switch(struct kvm_vcpu *vcpu, struct ia64_psr old_psr,
++ struct ia64_psr new_psr)
++{
++
++ if ((old_psr.dt != new_psr.dt)
++ || (old_psr.it != new_psr.it)
++ || (old_psr.rt != new_psr.rt))
++ switch_mm_mode(vcpu, old_psr, new_psr);
++
++ return;
++}
++
++
++/*
++ * In physical mode, insert tc/tr for region 0 and 4 uses
++ * RID[0] and RID[4] which is for physical mode emulation.
++ * However what those inserted tc/tr wants is rid for
++ * virtual mode. So original virtual rid needs to be restored
++ * before insert.
++ *
++ * Operations which required such switch include:
++ * - insertions (itc.*, itr.*)
++ * - purges (ptc.* and ptr.*)
++ * - tpa
++ * - tak
++ * - thash?, ttag?
++ * All above needs actual virtual rid for destination entry.
++ */
++
++void prepare_if_physical_mode(struct kvm_vcpu *vcpu)
++{
++ if (is_physical_mode(vcpu)) {
++ vcpu->arch.mode_flags |= GUEST_PHY_EMUL;
++ switch_to_virtual_rid(vcpu);
++ }
++ return;
++}
++
++/* Recover always follows prepare */
++void recover_if_physical_mode(struct kvm_vcpu *vcpu)
++{
++ if (is_physical_mode(vcpu))
++ switch_to_physical_rid(vcpu);
++ vcpu->arch.mode_flags &= ~GUEST_PHY_EMUL;
++ return;
++}
++
++#define RPT(x) ((u16) &((struct kvm_pt_regs *)0)->x)
++
++static u16 gr_info[32] = {
++ 0, /* r0 is read-only : WE SHOULD NEVER GET THIS */
++ RPT(r1), RPT(r2), RPT(r3),
++ RPT(r4), RPT(r5), RPT(r6), RPT(r7),
++ RPT(r8), RPT(r9), RPT(r10), RPT(r11),
++ RPT(r12), RPT(r13), RPT(r14), RPT(r15),
++ RPT(r16), RPT(r17), RPT(r18), RPT(r19),
++ RPT(r20), RPT(r21), RPT(r22), RPT(r23),
++ RPT(r24), RPT(r25), RPT(r26), RPT(r27),
++ RPT(r28), RPT(r29), RPT(r30), RPT(r31)
++};
++
++#define IA64_FIRST_STACKED_GR 32
++#define IA64_FIRST_ROTATING_FR 32
++
++static inline unsigned long
++rotate_reg(unsigned long sor, unsigned long rrb, unsigned long reg)
++{
++ reg += rrb;
++ if (reg >= sor)
++ reg -= sor;
++ return reg;
++}
++
++/*
++ * Return the (rotated) index for floating point register
++ * be in the REGNUM (REGNUM must range from 32-127,
++ * result is in the range from 0-95.
++ */
++static inline unsigned long fph_index(struct kvm_pt_regs *regs,
++ long regnum)
++{
++ unsigned long rrb_fr = (regs->cr_ifs >> 25) & 0x7f;
++ return rotate_reg(96, rrb_fr, (regnum - IA64_FIRST_ROTATING_FR));
++}
++
++
++/*
++ * The inverse of the above: given bspstore and the number of
++ * registers, calculate ar.bsp.
++ */
++static inline unsigned long *kvm_rse_skip_regs(unsigned long *addr,
++ long num_regs)
++{
++ long delta = ia64_rse_slot_num(addr) + num_regs;
++ int i = 0;
++
++ if (num_regs < 0)
++ delta -= 0x3e;
++ if (delta < 0) {
++ while (delta <= -0x3f) {
++ i--;
++ delta += 0x3f;
++ }
++ } else {
++ while (delta >= 0x3f) {
++ i++;
++ delta -= 0x3f;
++ }
++ }
++
++ return addr + num_regs + i;
++}
++
++static void get_rse_reg(struct kvm_pt_regs *regs, unsigned long r1,
++ unsigned long *val, int *nat)
++{
++ unsigned long *bsp, *addr, *rnat_addr, *bspstore;
++ unsigned long *kbs = (void *) current_vcpu + VMM_RBS_OFFSET;
++ unsigned long nat_mask;
++ unsigned long old_rsc, new_rsc;
++ long sof = (regs->cr_ifs) & 0x7f;
++ long sor = (((regs->cr_ifs >> 14) & 0xf) << 3);
++ long rrb_gr = (regs->cr_ifs >> 18) & 0x7f;
++ long ridx = r1 - 32;
++
++ if (ridx < sor)
++ ridx = rotate_reg(sor, rrb_gr, ridx);
++
++ old_rsc = ia64_getreg(_IA64_REG_AR_RSC);
++ new_rsc = old_rsc&(~(0x3));
++ ia64_setreg(_IA64_REG_AR_RSC, new_rsc);
++
++ bspstore = (unsigned long *)ia64_getreg(_IA64_REG_AR_BSPSTORE);
++ bsp = kbs + (regs->loadrs >> 19);
++
++ addr = kvm_rse_skip_regs(bsp, -sof + ridx);
++ nat_mask = 1UL << ia64_rse_slot_num(addr);
++ rnat_addr = ia64_rse_rnat_addr(addr);
++
++ if (addr >= bspstore) {
++ ia64_flushrs();
++ ia64_mf();
++ bspstore = (unsigned long *)ia64_getreg(_IA64_REG_AR_BSPSTORE);
++ }
++ *val = *addr;
++ if (nat) {
++ if (bspstore < rnat_addr)
++ *nat = (int)!!(ia64_getreg(_IA64_REG_AR_RNAT)
++ & nat_mask);
++ else
++ *nat = (int)!!((*rnat_addr) & nat_mask);
++ ia64_setreg(_IA64_REG_AR_RSC, old_rsc);
++ }
++}
++
++void set_rse_reg(struct kvm_pt_regs *regs, unsigned long r1,
++ unsigned long val, unsigned long nat)
++{
++ unsigned long *bsp, *bspstore, *addr, *rnat_addr;
++ unsigned long *kbs = (void *) current_vcpu + VMM_RBS_OFFSET;
++ unsigned long nat_mask;
++ unsigned long old_rsc, new_rsc, psr;
++ unsigned long rnat;
++ long sof = (regs->cr_ifs) & 0x7f;
++ long sor = (((regs->cr_ifs >> 14) & 0xf) << 3);
++ long rrb_gr = (regs->cr_ifs >> 18) & 0x7f;
++ long ridx = r1 - 32;
++
++ if (ridx < sor)
++ ridx = rotate_reg(sor, rrb_gr, ridx);
++
++ old_rsc = ia64_getreg(_IA64_REG_AR_RSC);
++ /* put RSC to lazy mode, and set loadrs 0 */
++ new_rsc = old_rsc & (~0x3fff0003);
++ ia64_setreg(_IA64_REG_AR_RSC, new_rsc);
++ bsp = kbs + (regs->loadrs >> 19); /* 16 + 3 */
++
++ addr = kvm_rse_skip_regs(bsp, -sof + ridx);
++ nat_mask = 1UL << ia64_rse_slot_num(addr);
++ rnat_addr = ia64_rse_rnat_addr(addr);
++
++ local_irq_save(psr);
++ bspstore = (unsigned long *)ia64_getreg(_IA64_REG_AR_BSPSTORE);
++ if (addr >= bspstore) {
++
++ ia64_flushrs();
++ ia64_mf();
++ *addr = val;
++ bspstore = (unsigned long *)ia64_getreg(_IA64_REG_AR_BSPSTORE);
++ rnat = ia64_getreg(_IA64_REG_AR_RNAT);
++ if (bspstore < rnat_addr)
++ rnat = rnat & (~nat_mask);
++ else
++ *rnat_addr = (*rnat_addr)&(~nat_mask);
++
++ ia64_mf();
++ ia64_loadrs();
++ ia64_setreg(_IA64_REG_AR_RNAT, rnat);
++ } else {
++ rnat = ia64_getreg(_IA64_REG_AR_RNAT);
++ *addr = val;
++ if (bspstore < rnat_addr)
++ rnat = rnat&(~nat_mask);
++ else
++ *rnat_addr = (*rnat_addr) & (~nat_mask);
++
++ ia64_setreg(_IA64_REG_AR_BSPSTORE, bspstore);
++ ia64_setreg(_IA64_REG_AR_RNAT, rnat);
++ }
++ local_irq_restore(psr);
++ ia64_setreg(_IA64_REG_AR_RSC, old_rsc);
++}
++
++void getreg(unsigned long regnum, unsigned long *val,
++ int *nat, struct kvm_pt_regs *regs)
++{
++ unsigned long addr, *unat;
++ if (regnum >= IA64_FIRST_STACKED_GR) {
++ get_rse_reg(regs, regnum, val, nat);
++ return;
++ }
++
++ /*
++ * Now look at registers in [0-31] range and init correct UNAT
++ */
++ addr = (unsigned long)regs;
++ unat = ®s->eml_unat;;
++
++ addr += gr_info[regnum];
++
++ *val = *(unsigned long *)addr;
++ /*
++ * do it only when requested
++ */
++ if (nat)
++ *nat = (*unat >> ((addr >> 3) & 0x3f)) & 0x1UL;
++}
++
++void setreg(unsigned long regnum, unsigned long val,
++ int nat, struct kvm_pt_regs *regs)
++{
++ unsigned long addr;
++ unsigned long bitmask;
++ unsigned long *unat;
++
++ /*
++ * First takes care of stacked registers
++ */
++ if (regnum >= IA64_FIRST_STACKED_GR) {
++ set_rse_reg(regs, regnum, val, nat);
++ return;
++ }
++
++ /*
++ * Now look at registers in [0-31] range and init correct UNAT
++ */
++ addr = (unsigned long)regs;
++ unat = ®s->eml_unat;
++ /*
++ * add offset from base of struct
++ * and do it !
++ */
++ addr += gr_info[regnum];
++
++ *(unsigned long *)addr = val;
++
++ /*
++ * We need to clear the corresponding UNAT bit to fully emulate the load
++ * UNAT bit_pos = GR[r3]{8:3} form EAS-2.4
++ */
++ bitmask = 1UL << ((addr >> 3) & 0x3f);
++ if (nat)
++ *unat |= bitmask;
++ else
++ *unat &= ~bitmask;
++
++}
++
++u64 vcpu_get_gr(struct kvm_vcpu *vcpu, unsigned long reg)
++{
++ struct kvm_pt_regs *regs = vcpu_regs(vcpu);
++ u64 val;
++
++ if (!reg)
++ return 0;
++ getreg(reg, &val, 0, regs);
++ return val;
++}
++
++void vcpu_set_gr(struct kvm_vcpu *vcpu, u64 reg, u64 value, int nat)
++{
++ struct kvm_pt_regs *regs = vcpu_regs(vcpu);
++ long sof = (regs->cr_ifs) & 0x7f;
++
++ if (!reg)
++ return;
++ if (reg >= sof + 32)
++ return;
++ setreg(reg, value, nat, regs); /* FIXME: handle NATs later*/
++}
++
++void getfpreg(unsigned long regnum, struct ia64_fpreg *fpval,
++ struct kvm_pt_regs *regs)
++{
++ /* Take floating register rotation into consideration*/
++ if (regnum >= IA64_FIRST_ROTATING_FR)
++ regnum = IA64_FIRST_ROTATING_FR + fph_index(regs, regnum);
++#define CASE_FIXED_FP(reg) \
++ case (reg) : \
++ ia64_stf_spill(fpval, reg); \
++ break
++
++ switch (regnum) {
++ CASE_FIXED_FP(0);
++ CASE_FIXED_FP(1);
++ CASE_FIXED_FP(2);
++ CASE_FIXED_FP(3);
++ CASE_FIXED_FP(4);
++ CASE_FIXED_FP(5);
++
++ CASE_FIXED_FP(6);
++ CASE_FIXED_FP(7);
++ CASE_FIXED_FP(8);
++ CASE_FIXED_FP(9);
++ CASE_FIXED_FP(10);
++ CASE_FIXED_FP(11);
++
++ CASE_FIXED_FP(12);
++ CASE_FIXED_FP(13);
++ CASE_FIXED_FP(14);
++ CASE_FIXED_FP(15);
++ CASE_FIXED_FP(16);
++ CASE_FIXED_FP(17);
++ CASE_FIXED_FP(18);
++ CASE_FIXED_FP(19);
++ CASE_FIXED_FP(20);
++ CASE_FIXED_FP(21);
++ CASE_FIXED_FP(22);
++ CASE_FIXED_FP(23);
++ CASE_FIXED_FP(24);
++ CASE_FIXED_FP(25);
++ CASE_FIXED_FP(26);
++ CASE_FIXED_FP(27);
++ CASE_FIXED_FP(28);
++ CASE_FIXED_FP(29);
++ CASE_FIXED_FP(30);
++ CASE_FIXED_FP(31);
++ CASE_FIXED_FP(32);
++ CASE_FIXED_FP(33);
++ CASE_FIXED_FP(34);
++ CASE_FIXED_FP(35);
++ CASE_FIXED_FP(36);
++ CASE_FIXED_FP(37);
++ CASE_FIXED_FP(38);
++ CASE_FIXED_FP(39);
++ CASE_FIXED_FP(40);
++ CASE_FIXED_FP(41);
++ CASE_FIXED_FP(42);
++ CASE_FIXED_FP(43);
++ CASE_FIXED_FP(44);
++ CASE_FIXED_FP(45);
++ CASE_FIXED_FP(46);
++ CASE_FIXED_FP(47);
++ CASE_FIXED_FP(48);
++ CASE_FIXED_FP(49);
++ CASE_FIXED_FP(50);
++ CASE_FIXED_FP(51);
++ CASE_FIXED_FP(52);
++ CASE_FIXED_FP(53);
++ CASE_FIXED_FP(54);
++ CASE_FIXED_FP(55);
++ CASE_FIXED_FP(56);
++ CASE_FIXED_FP(57);
++ CASE_FIXED_FP(58);
++ CASE_FIXED_FP(59);
++ CASE_FIXED_FP(60);
++ CASE_FIXED_FP(61);
++ CASE_FIXED_FP(62);
++ CASE_FIXED_FP(63);
++ CASE_FIXED_FP(64);
++ CASE_FIXED_FP(65);
++ CASE_FIXED_FP(66);
++ CASE_FIXED_FP(67);
++ CASE_FIXED_FP(68);
++ CASE_FIXED_FP(69);
++ CASE_FIXED_FP(70);
++ CASE_FIXED_FP(71);
++ CASE_FIXED_FP(72);
++ CASE_FIXED_FP(73);
++ CASE_FIXED_FP(74);
++ CASE_FIXED_FP(75);
++ CASE_FIXED_FP(76);
++ CASE_FIXED_FP(77);
++ CASE_FIXED_FP(78);
++ CASE_FIXED_FP(79);
++ CASE_FIXED_FP(80);
++ CASE_FIXED_FP(81);
++ CASE_FIXED_FP(82);
++ CASE_FIXED_FP(83);
++ CASE_FIXED_FP(84);
++ CASE_FIXED_FP(85);
++ CASE_FIXED_FP(86);
++ CASE_FIXED_FP(87);
++ CASE_FIXED_FP(88);
++ CASE_FIXED_FP(89);
++ CASE_FIXED_FP(90);
++ CASE_FIXED_FP(91);
++ CASE_FIXED_FP(92);
++ CASE_FIXED_FP(93);
++ CASE_FIXED_FP(94);
++ CASE_FIXED_FP(95);
++ CASE_FIXED_FP(96);
++ CASE_FIXED_FP(97);
++ CASE_FIXED_FP(98);
++ CASE_FIXED_FP(99);
++ CASE_FIXED_FP(100);
++ CASE_FIXED_FP(101);
++ CASE_FIXED_FP(102);
++ CASE_FIXED_FP(103);
++ CASE_FIXED_FP(104);
++ CASE_FIXED_FP(105);
++ CASE_FIXED_FP(106);
++ CASE_FIXED_FP(107);
++ CASE_FIXED_FP(108);
++ CASE_FIXED_FP(109);
++ CASE_FIXED_FP(110);
++ CASE_FIXED_FP(111);
++ CASE_FIXED_FP(112);
++ CASE_FIXED_FP(113);
++ CASE_FIXED_FP(114);
++ CASE_FIXED_FP(115);
++ CASE_FIXED_FP(116);
++ CASE_FIXED_FP(117);
++ CASE_FIXED_FP(118);
++ CASE_FIXED_FP(119);
++ CASE_FIXED_FP(120);
++ CASE_FIXED_FP(121);
++ CASE_FIXED_FP(122);
++ CASE_FIXED_FP(123);
++ CASE_FIXED_FP(124);
++ CASE_FIXED_FP(125);
++ CASE_FIXED_FP(126);
++ CASE_FIXED_FP(127);
++ }
++#undef CASE_FIXED_FP
++}
++
++void setfpreg(unsigned long regnum, struct ia64_fpreg *fpval,
++ struct kvm_pt_regs *regs)
++{
++ /* Take floating register rotation into consideration*/
++ if (regnum >= IA64_FIRST_ROTATING_FR)
++ regnum = IA64_FIRST_ROTATING_FR + fph_index(regs, regnum);
++
++#define CASE_FIXED_FP(reg) \
++ case (reg) : \
++ ia64_ldf_fill(reg, fpval); \
++ break
++
++ switch (regnum) {
++ CASE_FIXED_FP(2);
++ CASE_FIXED_FP(3);
++ CASE_FIXED_FP(4);
++ CASE_FIXED_FP(5);
++
++ CASE_FIXED_FP(6);
++ CASE_FIXED_FP(7);
++ CASE_FIXED_FP(8);
++ CASE_FIXED_FP(9);
++ CASE_FIXED_FP(10);
++ CASE_FIXED_FP(11);
++
++ CASE_FIXED_FP(12);
++ CASE_FIXED_FP(13);
++ CASE_FIXED_FP(14);
++ CASE_FIXED_FP(15);
++ CASE_FIXED_FP(16);
++ CASE_FIXED_FP(17);
++ CASE_FIXED_FP(18);
++ CASE_FIXED_FP(19);
++ CASE_FIXED_FP(20);
++ CASE_FIXED_FP(21);
++ CASE_FIXED_FP(22);
++ CASE_FIXED_FP(23);
++ CASE_FIXED_FP(24);
++ CASE_FIXED_FP(25);
++ CASE_FIXED_FP(26);
++ CASE_FIXED_FP(27);
++ CASE_FIXED_FP(28);
++ CASE_FIXED_FP(29);
++ CASE_FIXED_FP(30);
++ CASE_FIXED_FP(31);
++ CASE_FIXED_FP(32);
++ CASE_FIXED_FP(33);
++ CASE_FIXED_FP(34);
++ CASE_FIXED_FP(35);
++ CASE_FIXED_FP(36);
++ CASE_FIXED_FP(37);
++ CASE_FIXED_FP(38);
++ CASE_FIXED_FP(39);
++ CASE_FIXED_FP(40);
++ CASE_FIXED_FP(41);
++ CASE_FIXED_FP(42);
++ CASE_FIXED_FP(43);
++ CASE_FIXED_FP(44);
++ CASE_FIXED_FP(45);
++ CASE_FIXED_FP(46);
++ CASE_FIXED_FP(47);
++ CASE_FIXED_FP(48);
++ CASE_FIXED_FP(49);
++ CASE_FIXED_FP(50);
++ CASE_FIXED_FP(51);
++ CASE_FIXED_FP(52);
++ CASE_FIXED_FP(53);
++ CASE_FIXED_FP(54);
++ CASE_FIXED_FP(55);
++ CASE_FIXED_FP(56);
++ CASE_FIXED_FP(57);
++ CASE_FIXED_FP(58);
++ CASE_FIXED_FP(59);
++ CASE_FIXED_FP(60);
++ CASE_FIXED_FP(61);
++ CASE_FIXED_FP(62);
++ CASE_FIXED_FP(63);
++ CASE_FIXED_FP(64);
++ CASE_FIXED_FP(65);
++ CASE_FIXED_FP(66);
++ CASE_FIXED_FP(67);
++ CASE_FIXED_FP(68);
++ CASE_FIXED_FP(69);
++ CASE_FIXED_FP(70);
++ CASE_FIXED_FP(71);
++ CASE_FIXED_FP(72);
++ CASE_FIXED_FP(73);
++ CASE_FIXED_FP(74);
++ CASE_FIXED_FP(75);
++ CASE_FIXED_FP(76);
++ CASE_FIXED_FP(77);
++ CASE_FIXED_FP(78);
++ CASE_FIXED_FP(79);
++ CASE_FIXED_FP(80);
++ CASE_FIXED_FP(81);
++ CASE_FIXED_FP(82);
++ CASE_FIXED_FP(83);
++ CASE_FIXED_FP(84);
++ CASE_FIXED_FP(85);
++ CASE_FIXED_FP(86);
++ CASE_FIXED_FP(87);
++ CASE_FIXED_FP(88);
++ CASE_FIXED_FP(89);
++ CASE_FIXED_FP(90);
++ CASE_FIXED_FP(91);
++ CASE_FIXED_FP(92);
++ CASE_FIXED_FP(93);
++ CASE_FIXED_FP(94);
++ CASE_FIXED_FP(95);
++ CASE_FIXED_FP(96);
++ CASE_FIXED_FP(97);
++ CASE_FIXED_FP(98);
++ CASE_FIXED_FP(99);
++ CASE_FIXED_FP(100);
++ CASE_FIXED_FP(101);
++ CASE_FIXED_FP(102);
++ CASE_FIXED_FP(103);
++ CASE_FIXED_FP(104);
++ CASE_FIXED_FP(105);
++ CASE_FIXED_FP(106);
++ CASE_FIXED_FP(107);
++ CASE_FIXED_FP(108);
++ CASE_FIXED_FP(109);
++ CASE_FIXED_FP(110);
++ CASE_FIXED_FP(111);
++ CASE_FIXED_FP(112);
++ CASE_FIXED_FP(113);
++ CASE_FIXED_FP(114);
++ CASE_FIXED_FP(115);
++ CASE_FIXED_FP(116);
++ CASE_FIXED_FP(117);
++ CASE_FIXED_FP(118);
++ CASE_FIXED_FP(119);
++ CASE_FIXED_FP(120);
++ CASE_FIXED_FP(121);
++ CASE_FIXED_FP(122);
++ CASE_FIXED_FP(123);
++ CASE_FIXED_FP(124);
++ CASE_FIXED_FP(125);
++ CASE_FIXED_FP(126);
++ CASE_FIXED_FP(127);
++ }
++}
++
++void vcpu_get_fpreg(struct kvm_vcpu *vcpu, unsigned long reg,
++ struct ia64_fpreg *val)
++{
++ struct kvm_pt_regs *regs = vcpu_regs(vcpu);
++
++ getfpreg(reg, val, regs); /* FIXME: handle NATs later*/
++}
++
++void vcpu_set_fpreg(struct kvm_vcpu *vcpu, unsigned long reg,
++ struct ia64_fpreg *val)
++{
++ struct kvm_pt_regs *regs = vcpu_regs(vcpu);
++
++ if (reg > 1)
++ setfpreg(reg, val, regs); /* FIXME: handle NATs later*/
++}
++
++/************************************************************************
++ * lsapic timer
++ ***********************************************************************/
++u64 vcpu_get_itc(struct kvm_vcpu *vcpu)
++{
++ unsigned long guest_itc;
++ guest_itc = VMX(vcpu, itc_offset) + ia64_getreg(_IA64_REG_AR_ITC);
++
++ if (guest_itc >= VMX(vcpu, last_itc)) {
++ VMX(vcpu, last_itc) = guest_itc;
++ return guest_itc;
++ } else
++ return VMX(vcpu, last_itc);
++}
++
++static inline void vcpu_set_itm(struct kvm_vcpu *vcpu, u64 val);
++static void vcpu_set_itc(struct kvm_vcpu *vcpu, u64 val)
++{
++ struct kvm_vcpu *v;
++ int i;
++ long itc_offset = val - ia64_getreg(_IA64_REG_AR_ITC);
++ unsigned long vitv = VCPU(vcpu, itv);
++
++ if (vcpu->vcpu_id == 0) {
++ for (i = 0; i < MAX_VCPU_NUM; i++) {
++ v = (struct kvm_vcpu *)((char *)vcpu + VCPU_SIZE * i);
++ VMX(v, itc_offset) = itc_offset;
++ VMX(v, last_itc) = 0;
++ }
++ }
++ VMX(vcpu, last_itc) = 0;
++ if (VCPU(vcpu, itm) <= val) {
++ VMX(vcpu, itc_check) = 0;
++ vcpu_unpend_interrupt(vcpu, vitv);
++ } else {
++ VMX(vcpu, itc_check) = 1;
++ vcpu_set_itm(vcpu, VCPU(vcpu, itm));
++ }
++
++}
++
++static inline u64 vcpu_get_itm(struct kvm_vcpu *vcpu)
++{
++ return ((u64)VCPU(vcpu, itm));
++}
++
++static inline void vcpu_set_itm(struct kvm_vcpu *vcpu, u64 val)
++{
++ unsigned long vitv = VCPU(vcpu, itv);
++ VCPU(vcpu, itm) = val;
++
++ if (val > vcpu_get_itc(vcpu)) {
++ VMX(vcpu, itc_check) = 1;
++ vcpu_unpend_interrupt(vcpu, vitv);
++ VMX(vcpu, timer_pending) = 0;
++ } else
++ VMX(vcpu, itc_check) = 0;
++}
++
++#define ITV_VECTOR(itv) (itv&0xff)
++#define ITV_IRQ_MASK(itv) (itv&(1<<16))
++
++static inline void vcpu_set_itv(struct kvm_vcpu *vcpu, u64 val)
++{
++ VCPU(vcpu, itv) = val;
++ if (!ITV_IRQ_MASK(val) && vcpu->arch.timer_pending) {
++ vcpu_pend_interrupt(vcpu, ITV_VECTOR(val));
++ vcpu->arch.timer_pending = 0;
++ }
++}
++
++static inline void vcpu_set_eoi(struct kvm_vcpu *vcpu, u64 val)
++{
++ int vec;
++
++ vec = highest_inservice_irq(vcpu);
++ if (vec == NULL_VECTOR)
++ return;
++ VMX(vcpu, insvc[vec >> 6]) &= ~(1UL << (vec & 63));
++ VCPU(vcpu, eoi) = 0;
++ vcpu->arch.irq_new_pending = 1;
++
++}
++
++/* See Table 5-8 in SDM vol2 for the definition */
++int irq_masked(struct kvm_vcpu *vcpu, int h_pending, int h_inservice)
++{
++ union ia64_tpr vtpr;
++
++ vtpr.val = VCPU(vcpu, tpr);
++
++ if (h_inservice == NMI_VECTOR)
++ return IRQ_MASKED_BY_INSVC;
++
++ if (h_pending == NMI_VECTOR) {
++ /* Non Maskable Interrupt */
++ return IRQ_NO_MASKED;
++ }
++
++ if (h_inservice == ExtINT_VECTOR)
++ return IRQ_MASKED_BY_INSVC;
++
++ if (h_pending == ExtINT_VECTOR) {
++ if (vtpr.mmi) {
++ /* mask all external IRQ */
++ return IRQ_MASKED_BY_VTPR;
++ } else
++ return IRQ_NO_MASKED;
++ }
++
++ if (is_higher_irq(h_pending, h_inservice)) {
++ if (is_higher_class(h_pending, vtpr.mic + (vtpr.mmi << 4)))
++ return IRQ_NO_MASKED;
++ else
++ return IRQ_MASKED_BY_VTPR;
++ } else {
++ return IRQ_MASKED_BY_INSVC;
++ }
++}
++
++void vcpu_pend_interrupt(struct kvm_vcpu *vcpu, u8 vec)
++{
++ long spsr;
++ int ret;
++
++ local_irq_save(spsr);
++ ret = test_and_set_bit(vec, &VCPU(vcpu, irr[0]));
++ local_irq_restore(spsr);
++
++ vcpu->arch.irq_new_pending = 1;
++}
++
++void vcpu_unpend_interrupt(struct kvm_vcpu *vcpu, u8 vec)
++{
++ long spsr;
++ int ret;
++
++ local_irq_save(spsr);
++ ret = test_and_clear_bit(vec, &VCPU(vcpu, irr[0]));
++ local_irq_restore(spsr);
++ if (ret) {
++ vcpu->arch.irq_new_pending = 1;
++ wmb();
++ }
++}
++
++void update_vhpi(struct kvm_vcpu *vcpu, int vec)
++{
++ u64 vhpi;
++
++ if (vec == NULL_VECTOR)
++ vhpi = 0;
++ else if (vec == NMI_VECTOR)
++ vhpi = 32;
++ else if (vec == ExtINT_VECTOR)
++ vhpi = 16;
++ else
++ vhpi = vec >> 4;
++
++ VCPU(vcpu, vhpi) = vhpi;
++ if (VCPU(vcpu, vac).a_int)
++ ia64_call_vsa(PAL_VPS_SET_PENDING_INTERRUPT,
++ (u64)vcpu->arch.vpd, 0, 0, 0, 0, 0, 0);
++}
++
++u64 vcpu_get_ivr(struct kvm_vcpu *vcpu)
++{
++ int vec, h_inservice, mask;
++
++ vec = highest_pending_irq(vcpu);
++ h_inservice = highest_inservice_irq(vcpu);
++ mask = irq_masked(vcpu, vec, h_inservice);
++ if (vec == NULL_VECTOR || mask == IRQ_MASKED_BY_INSVC) {
++ if (VCPU(vcpu, vhpi))
++ update_vhpi(vcpu, NULL_VECTOR);
++ return IA64_SPURIOUS_INT_VECTOR;
++ }
++ if (mask == IRQ_MASKED_BY_VTPR) {
++ update_vhpi(vcpu, vec);
++ return IA64_SPURIOUS_INT_VECTOR;
++ }
++ VMX(vcpu, insvc[vec >> 6]) |= (1UL << (vec & 63));
++ vcpu_unpend_interrupt(vcpu, vec);
++ return (u64)vec;
++}
++
++/**************************************************************************
++ Privileged operation emulation routines
++ **************************************************************************/
++u64 vcpu_thash(struct kvm_vcpu *vcpu, u64 vadr)
++{
++ union ia64_pta vpta;
++ union ia64_rr vrr;
++ u64 pval;
++ u64 vhpt_offset;
++
++ vpta.val = vcpu_get_pta(vcpu);
++ vrr.val = vcpu_get_rr(vcpu, vadr);
++ vhpt_offset = ((vadr >> vrr.ps) << 3) & ((1UL << (vpta.size)) - 1);
++ if (vpta.vf) {
++ pval = ia64_call_vsa(PAL_VPS_THASH, vadr, vrr.val,
++ vpta.val, 0, 0, 0, 0);
++ } else {
++ pval = (vadr & VRN_MASK) | vhpt_offset |
++ (vpta.val << 3 >> (vpta.size + 3) << (vpta.size));
++ }
++ return pval;
++}
++
++u64 vcpu_ttag(struct kvm_vcpu *vcpu, u64 vadr)
++{
++ union ia64_rr vrr;
++ union ia64_pta vpta;
++ u64 pval;
++
++ vpta.val = vcpu_get_pta(vcpu);
++ vrr.val = vcpu_get_rr(vcpu, vadr);
++ if (vpta.vf) {
++ pval = ia64_call_vsa(PAL_VPS_TTAG, vadr, vrr.val,
++ 0, 0, 0, 0, 0);
++ } else
++ pval = 1;
++
++ return pval;
++}
++
++u64 vcpu_tak(struct kvm_vcpu *vcpu, u64 vadr)
++{
++ struct thash_data *data;
++ union ia64_pta vpta;
++ u64 key;
++
++ vpta.val = vcpu_get_pta(vcpu);
++ if (vpta.vf == 0) {
++ key = 1;
++ return key;
++ }
++ data = vtlb_lookup(vcpu, vadr, D_TLB);
++ if (!data || !data->p)
++ key = 1;
++ else
++ key = data->key;
++
++ return key;
++}
++
++
++
++void kvm_thash(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long thash, vadr;
++
++ vadr = vcpu_get_gr(vcpu, inst.M46.r3);
++ thash = vcpu_thash(vcpu, vadr);
++ vcpu_set_gr(vcpu, inst.M46.r1, thash, 0);
++}
++
++
++void kvm_ttag(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long tag, vadr;
++
++ vadr = vcpu_get_gr(vcpu, inst.M46.r3);
++ tag = vcpu_ttag(vcpu, vadr);
++ vcpu_set_gr(vcpu, inst.M46.r1, tag, 0);
++}
++
++int vcpu_tpa(struct kvm_vcpu *vcpu, u64 vadr, u64 *padr)
++{
++ struct thash_data *data;
++ union ia64_isr visr, pt_isr;
++ struct kvm_pt_regs *regs;
++ struct ia64_psr vpsr;
++
++ regs = vcpu_regs(vcpu);
++ pt_isr.val = VMX(vcpu, cr_isr);
++ visr.val = 0;
++ visr.ei = pt_isr.ei;
++ visr.ir = pt_isr.ir;
++ vpsr = *(struct ia64_psr *)&VCPU(vcpu, vpsr);
++ visr.na = 1;
++
++ data = vhpt_lookup(vadr);
++ if (data) {
++ if (data->p == 0) {
++ vcpu_set_isr(vcpu, visr.val);
++ data_page_not_present(vcpu, vadr);
++ return IA64_FAULT;
++ } else if (data->ma == VA_MATTR_NATPAGE) {
++ vcpu_set_isr(vcpu, visr.val);
++ dnat_page_consumption(vcpu, vadr);
++ return IA64_FAULT;
++ } else {
++ *padr = (data->gpaddr >> data->ps << data->ps) |
++ (vadr & (PSIZE(data->ps) - 1));
++ return IA64_NO_FAULT;
++ }
++ }
++
++ data = vtlb_lookup(vcpu, vadr, D_TLB);
++ if (data) {
++ if (data->p == 0) {
++ vcpu_set_isr(vcpu, visr.val);
++ data_page_not_present(vcpu, vadr);
++ return IA64_FAULT;
++ } else if (data->ma == VA_MATTR_NATPAGE) {
++ vcpu_set_isr(vcpu, visr.val);
++ dnat_page_consumption(vcpu, vadr);
++ return IA64_FAULT;
++ } else{
++ *padr = ((data->ppn >> (data->ps - 12)) << data->ps)
++ | (vadr & (PSIZE(data->ps) - 1));
++ return IA64_NO_FAULT;
++ }
++ }
++ if (!vhpt_enabled(vcpu, vadr, NA_REF)) {
++ if (vpsr.ic) {
++ vcpu_set_isr(vcpu, visr.val);
++ alt_dtlb(vcpu, vadr);
++ return IA64_FAULT;
++ } else {
++ nested_dtlb(vcpu);
++ return IA64_FAULT;
++ }
++ } else {
++ if (vpsr.ic) {
++ vcpu_set_isr(vcpu, visr.val);
++ dvhpt_fault(vcpu, vadr);
++ return IA64_FAULT;
++ } else{
++ nested_dtlb(vcpu);
++ return IA64_FAULT;
++ }
++ }
++
++ return IA64_NO_FAULT;
++}
++
++
++int kvm_tpa(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long r1, r3;
++
++ r3 = vcpu_get_gr(vcpu, inst.M46.r3);
++
++ if (vcpu_tpa(vcpu, r3, &r1))
++ return IA64_FAULT;
++
++ vcpu_set_gr(vcpu, inst.M46.r1, r1, 0);
++ return(IA64_NO_FAULT);
++}
++
++void kvm_tak(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long r1, r3;
++
++ r3 = vcpu_get_gr(vcpu, inst.M46.r3);
++ r1 = vcpu_tak(vcpu, r3);
++ vcpu_set_gr(vcpu, inst.M46.r1, r1, 0);
++}
++
++
++/************************************
++ * Insert/Purge translation register/cache
++ ************************************/
++void vcpu_itc_i(struct kvm_vcpu *vcpu, u64 pte, u64 itir, u64 ifa)
++{
++ thash_purge_and_insert(vcpu, pte, itir, ifa, I_TLB);
++}
++
++void vcpu_itc_d(struct kvm_vcpu *vcpu, u64 pte, u64 itir, u64 ifa)
++{
++ thash_purge_and_insert(vcpu, pte, itir, ifa, D_TLB);
++}
++
++void vcpu_itr_i(struct kvm_vcpu *vcpu, u64 slot, u64 pte, u64 itir, u64 ifa)
++{
++ u64 ps, va, rid;
++ struct thash_data *p_itr;
++
++ ps = itir_ps(itir);
++ va = PAGEALIGN(ifa, ps);
++ pte &= ~PAGE_FLAGS_RV_MASK;
++ rid = vcpu_get_rr(vcpu, ifa);
++ rid = rid & RR_RID_MASK;
++ p_itr = (struct thash_data *)&vcpu->arch.itrs[slot];
++ vcpu_set_tr(p_itr, pte, itir, va, rid);
++ vcpu_quick_region_set(VMX(vcpu, itr_regions), va);
++}
++
++
++void vcpu_itr_d(struct kvm_vcpu *vcpu, u64 slot, u64 pte, u64 itir, u64 ifa)
++{
++ u64 gpfn;
++ u64 ps, va, rid;
++ struct thash_data *p_dtr;
++
++ ps = itir_ps(itir);
++ va = PAGEALIGN(ifa, ps);
++ pte &= ~PAGE_FLAGS_RV_MASK;
++
++ if (ps != _PAGE_SIZE_16M)
++ thash_purge_entries(vcpu, va, ps);
++ gpfn = (pte & _PAGE_PPN_MASK) >> PAGE_SHIFT;
++ if (__gpfn_is_io(gpfn))
++ pte |= VTLB_PTE_IO;
++ rid = vcpu_get_rr(vcpu, va);
++ rid = rid & RR_RID_MASK;
++ p_dtr = (struct thash_data *)&vcpu->arch.dtrs[slot];
++ vcpu_set_tr((struct thash_data *)&vcpu->arch.dtrs[slot],
++ pte, itir, va, rid);
++ vcpu_quick_region_set(VMX(vcpu, dtr_regions), va);
++}
++
++void vcpu_ptr_d(struct kvm_vcpu *vcpu, u64 ifa, u64 ps)
++{
++ int index;
++ u64 va;
++
++ va = PAGEALIGN(ifa, ps);
++ while ((index = vtr_find_overlap(vcpu, va, ps, D_TLB)) >= 0)
++ vcpu->arch.dtrs[index].page_flags = 0;
++
++ thash_purge_entries(vcpu, va, ps);
++}
++
++void vcpu_ptr_i(struct kvm_vcpu *vcpu, u64 ifa, u64 ps)
++{
++ int index;
++ u64 va;
++
++ va = PAGEALIGN(ifa, ps);
++ while ((index = vtr_find_overlap(vcpu, va, ps, I_TLB)) >= 0)
++ vcpu->arch.itrs[index].page_flags = 0;
++
++ thash_purge_entries(vcpu, va, ps);
++}
++
++void vcpu_ptc_l(struct kvm_vcpu *vcpu, u64 va, u64 ps)
++{
++ va = PAGEALIGN(va, ps);
++ thash_purge_entries(vcpu, va, ps);
++}
++
++void vcpu_ptc_e(struct kvm_vcpu *vcpu, u64 va)
++{
++ thash_purge_all(vcpu);
++}
++
++void vcpu_ptc_ga(struct kvm_vcpu *vcpu, u64 va, u64 ps)
++{
++ struct exit_ctl_data *p = &vcpu->arch.exit_data;
++ long psr;
++ local_irq_save(psr);
++ p->exit_reason = EXIT_REASON_PTC_G;
++
++ p->u.ptc_g_data.rr = vcpu_get_rr(vcpu, va);
++ p->u.ptc_g_data.vaddr = va;
++ p->u.ptc_g_data.ps = ps;
++ vmm_transition(vcpu);
++ /* Do Local Purge Here*/
++ vcpu_ptc_l(vcpu, va, ps);
++ local_irq_restore(psr);
++}
++
++
++void vcpu_ptc_g(struct kvm_vcpu *vcpu, u64 va, u64 ps)
++{
++ vcpu_ptc_ga(vcpu, va, ps);
++}
++
++void kvm_ptc_e(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long ifa;
++
++ ifa = vcpu_get_gr(vcpu, inst.M45.r3);
++ vcpu_ptc_e(vcpu, ifa);
++}
++
++void kvm_ptc_g(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long ifa, itir;
++
++ ifa = vcpu_get_gr(vcpu, inst.M45.r3);
++ itir = vcpu_get_gr(vcpu, inst.M45.r2);
++ vcpu_ptc_g(vcpu, ifa, itir_ps(itir));
++}
++
++void kvm_ptc_ga(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long ifa, itir;
++
++ ifa = vcpu_get_gr(vcpu, inst.M45.r3);
++ itir = vcpu_get_gr(vcpu, inst.M45.r2);
++ vcpu_ptc_ga(vcpu, ifa, itir_ps(itir));
++}
++
++void kvm_ptc_l(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long ifa, itir;
++
++ ifa = vcpu_get_gr(vcpu, inst.M45.r3);
++ itir = vcpu_get_gr(vcpu, inst.M45.r2);
++ vcpu_ptc_l(vcpu, ifa, itir_ps(itir));
++}
++
++void kvm_ptr_d(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long ifa, itir;
++
++ ifa = vcpu_get_gr(vcpu, inst.M45.r3);
++ itir = vcpu_get_gr(vcpu, inst.M45.r2);
++ vcpu_ptr_d(vcpu, ifa, itir_ps(itir));
++}
++
++void kvm_ptr_i(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long ifa, itir;
++
++ ifa = vcpu_get_gr(vcpu, inst.M45.r3);
++ itir = vcpu_get_gr(vcpu, inst.M45.r2);
++ vcpu_ptr_i(vcpu, ifa, itir_ps(itir));
++}
++
++void kvm_itr_d(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long itir, ifa, pte, slot;
++
++ slot = vcpu_get_gr(vcpu, inst.M45.r3);
++ pte = vcpu_get_gr(vcpu, inst.M45.r2);
++ itir = vcpu_get_itir(vcpu);
++ ifa = vcpu_get_ifa(vcpu);
++ vcpu_itr_d(vcpu, slot, pte, itir, ifa);
++}
++
++
++
++void kvm_itr_i(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long itir, ifa, pte, slot;
++
++ slot = vcpu_get_gr(vcpu, inst.M45.r3);
++ pte = vcpu_get_gr(vcpu, inst.M45.r2);
++ itir = vcpu_get_itir(vcpu);
++ ifa = vcpu_get_ifa(vcpu);
++ vcpu_itr_i(vcpu, slot, pte, itir, ifa);
++}
++
++void kvm_itc_d(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long itir, ifa, pte;
++
++ itir = vcpu_get_itir(vcpu);
++ ifa = vcpu_get_ifa(vcpu);
++ pte = vcpu_get_gr(vcpu, inst.M45.r2);
++ vcpu_itc_d(vcpu, pte, itir, ifa);
++}
++
++void kvm_itc_i(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long itir, ifa, pte;
++
++ itir = vcpu_get_itir(vcpu);
++ ifa = vcpu_get_ifa(vcpu);
++ pte = vcpu_get_gr(vcpu, inst.M45.r2);
++ vcpu_itc_i(vcpu, pte, itir, ifa);
++}
++
++/*************************************
++ * Moves to semi-privileged registers
++ *************************************/
++
++void kvm_mov_to_ar_imm(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long imm;
++
++ if (inst.M30.s)
++ imm = -inst.M30.imm;
++ else
++ imm = inst.M30.imm;
++
++ vcpu_set_itc(vcpu, imm);
++}
++
++void kvm_mov_to_ar_reg(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long r2;
++
++ r2 = vcpu_get_gr(vcpu, inst.M29.r2);
++ vcpu_set_itc(vcpu, r2);
++}
++
++
++void kvm_mov_from_ar_reg(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long r1;
++
++ r1 = vcpu_get_itc(vcpu);
++ vcpu_set_gr(vcpu, inst.M31.r1, r1, 0);
++}
++/**************************************************************************
++ struct kvm_vcpu*protection key register access routines
++ **************************************************************************/
++
++unsigned long vcpu_get_pkr(struct kvm_vcpu *vcpu, unsigned long reg)
++{
++ return ((unsigned long)ia64_get_pkr(reg));
++}
++
++void vcpu_set_pkr(struct kvm_vcpu *vcpu, unsigned long reg, unsigned long val)
++{
++ ia64_set_pkr(reg, val);
++}
++
++
++unsigned long vcpu_get_itir_on_fault(struct kvm_vcpu *vcpu, unsigned long ifa)
++{
++ union ia64_rr rr, rr1;
++
++ rr.val = vcpu_get_rr(vcpu, ifa);
++ rr1.val = 0;
++ rr1.ps = rr.ps;
++ rr1.rid = rr.rid;
++ return (rr1.val);
++}
++
++
++
++/********************************
++ * Moves to privileged registers
++ ********************************/
++unsigned long vcpu_set_rr(struct kvm_vcpu *vcpu, unsigned long reg,
++ unsigned long val)
++{
++ union ia64_rr oldrr, newrr;
++ unsigned long rrval;
++ struct exit_ctl_data *p = &vcpu->arch.exit_data;
++ unsigned long psr;
++
++ oldrr.val = vcpu_get_rr(vcpu, reg);
++ newrr.val = val;
++ vcpu->arch.vrr[reg >> VRN_SHIFT] = val;
++
++ switch ((unsigned long)(reg >> VRN_SHIFT)) {
++ case VRN6:
++ vcpu->arch.vmm_rr = vrrtomrr(val);
++ local_irq_save(psr);
++ p->exit_reason = EXIT_REASON_SWITCH_RR6;
++ vmm_transition(vcpu);
++ local_irq_restore(psr);
++ break;
++ case VRN4:
++ rrval = vrrtomrr(val);
++ vcpu->arch.metaphysical_saved_rr4 = rrval;
++ if (!is_physical_mode(vcpu))
++ ia64_set_rr(reg, rrval);
++ break;
++ case VRN0:
++ rrval = vrrtomrr(val);
++ vcpu->arch.metaphysical_saved_rr0 = rrval;
++ if (!is_physical_mode(vcpu))
++ ia64_set_rr(reg, rrval);
++ break;
++ default:
++ ia64_set_rr(reg, vrrtomrr(val));
++ break;
++ }
++
++ return (IA64_NO_FAULT);
++}
++
++
++
++void kvm_mov_to_rr(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long r3, r2;
++
++ r3 = vcpu_get_gr(vcpu, inst.M42.r3);
++ r2 = vcpu_get_gr(vcpu, inst.M42.r2);
++ vcpu_set_rr(vcpu, r3, r2);
++}
++
++void kvm_mov_to_dbr(struct kvm_vcpu *vcpu, INST64 inst)
++{
++}
++
++void kvm_mov_to_ibr(struct kvm_vcpu *vcpu, INST64 inst)
++{
++}
++
++void kvm_mov_to_pmc(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long r3, r2;
++
++ r3 = vcpu_get_gr(vcpu, inst.M42.r3);
++ r2 = vcpu_get_gr(vcpu, inst.M42.r2);
++ vcpu_set_pmc(vcpu, r3, r2);
++}
++
++void kvm_mov_to_pmd(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long r3, r2;
++
++ r3 = vcpu_get_gr(vcpu, inst.M42.r3);
++ r2 = vcpu_get_gr(vcpu, inst.M42.r2);
++ vcpu_set_pmd(vcpu, r3, r2);
++}
++
++void kvm_mov_to_pkr(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ u64 r3, r2;
++
++ r3 = vcpu_get_gr(vcpu, inst.M42.r3);
++ r2 = vcpu_get_gr(vcpu, inst.M42.r2);
++ vcpu_set_pkr(vcpu, r3, r2);
++}
++
++
++
++void kvm_mov_from_rr(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long r3, r1;
++
++ r3 = vcpu_get_gr(vcpu, inst.M43.r3);
++ r1 = vcpu_get_rr(vcpu, r3);
++ vcpu_set_gr(vcpu, inst.M43.r1, r1, 0);
++}
++
++void kvm_mov_from_pkr(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long r3, r1;
++
++ r3 = vcpu_get_gr(vcpu, inst.M43.r3);
++ r1 = vcpu_get_pkr(vcpu, r3);
++ vcpu_set_gr(vcpu, inst.M43.r1, r1, 0);
++}
++
++void kvm_mov_from_dbr(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long r3, r1;
++
++ r3 = vcpu_get_gr(vcpu, inst.M43.r3);
++ r1 = vcpu_get_dbr(vcpu, r3);
++ vcpu_set_gr(vcpu, inst.M43.r1, r1, 0);
++}
++
++void kvm_mov_from_ibr(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long r3, r1;
++
++ r3 = vcpu_get_gr(vcpu, inst.M43.r3);
++ r1 = vcpu_get_ibr(vcpu, r3);
++ vcpu_set_gr(vcpu, inst.M43.r1, r1, 0);
++}
++
++void kvm_mov_from_pmc(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long r3, r1;
++
++ r3 = vcpu_get_gr(vcpu, inst.M43.r3);
++ r1 = vcpu_get_pmc(vcpu, r3);
++ vcpu_set_gr(vcpu, inst.M43.r1, r1, 0);
++}
++
++
++unsigned long vcpu_get_cpuid(struct kvm_vcpu *vcpu, unsigned long reg)
++{
++ /* FIXME: This could get called as a result of a rsvd-reg fault */
++ if (reg > (ia64_get_cpuid(3) & 0xff))
++ return 0;
++ else
++ return ia64_get_cpuid(reg);
++}
++
++void kvm_mov_from_cpuid(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long r3, r1;
++
++ r3 = vcpu_get_gr(vcpu, inst.M43.r3);
++ r1 = vcpu_get_cpuid(vcpu, r3);
++ vcpu_set_gr(vcpu, inst.M43.r1, r1, 0);
++}
++
++void vcpu_set_tpr(struct kvm_vcpu *vcpu, unsigned long val)
++{
++ VCPU(vcpu, tpr) = val;
++ vcpu->arch.irq_check = 1;
++}
++
++unsigned long kvm_mov_to_cr(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long r2;
++
++ r2 = vcpu_get_gr(vcpu, inst.M32.r2);
++ VCPU(vcpu, vcr[inst.M32.cr3]) = r2;
++
++ switch (inst.M32.cr3) {
++ case 0:
++ vcpu_set_dcr(vcpu, r2);
++ break;
++ case 1:
++ vcpu_set_itm(vcpu, r2);
++ break;
++ case 66:
++ vcpu_set_tpr(vcpu, r2);
++ break;
++ case 67:
++ vcpu_set_eoi(vcpu, r2);
++ break;
++ default:
++ break;
++ }
++
++ return 0;
++}
++
++
++unsigned long kvm_mov_from_cr(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long tgt = inst.M33.r1;
++ unsigned long val;
++
++ switch (inst.M33.cr3) {
++ case 65:
++ val = vcpu_get_ivr(vcpu);
++ vcpu_set_gr(vcpu, tgt, val, 0);
++ break;
++
++ case 67:
++ vcpu_set_gr(vcpu, tgt, 0L, 0);
++ break;
++ default:
++ val = VCPU(vcpu, vcr[inst.M33.cr3]);
++ vcpu_set_gr(vcpu, tgt, val, 0);
++ break;
++ }
++
++ return 0;
++}
++
++
++
++void vcpu_set_psr(struct kvm_vcpu *vcpu, unsigned long val)
++{
++
++ unsigned long mask;
++ struct kvm_pt_regs *regs;
++ struct ia64_psr old_psr, new_psr;
++
++ old_psr = *(struct ia64_psr *)&VCPU(vcpu, vpsr);
++
++ regs = vcpu_regs(vcpu);
++ /* We only support guest as:
++ * vpsr.pk = 0
++ * vpsr.is = 0
++ * Otherwise panic
++ */
++ if (val & (IA64_PSR_PK | IA64_PSR_IS | IA64_PSR_VM))
++ panic_vm(vcpu);
++
++ /*
++ * For those IA64_PSR bits: id/da/dd/ss/ed/ia
++ * Since these bits will become 0, after success execution of each
++ * instruction, we will change set them to mIA64_PSR
++ */
++ VCPU(vcpu, vpsr) = val
++ & (~(IA64_PSR_ID | IA64_PSR_DA | IA64_PSR_DD |
++ IA64_PSR_SS | IA64_PSR_ED | IA64_PSR_IA));
++
++ if (!old_psr.i && (val & IA64_PSR_I)) {
++ /* vpsr.i 0->1 */
++ vcpu->arch.irq_check = 1;
++ }
++ new_psr = *(struct ia64_psr *)&VCPU(vcpu, vpsr);
++
++ /*
++ * All vIA64_PSR bits shall go to mPSR (v->tf->tf_special.psr)
++ * , except for the following bits:
++ * ic/i/dt/si/rt/mc/it/bn/vm
++ */
++ mask = IA64_PSR_IC + IA64_PSR_I + IA64_PSR_DT + IA64_PSR_SI +
++ IA64_PSR_RT + IA64_PSR_MC + IA64_PSR_IT + IA64_PSR_BN +
++ IA64_PSR_VM;
++
++ regs->cr_ipsr = (regs->cr_ipsr & mask) | (val & (~mask));
++
++ check_mm_mode_switch(vcpu, old_psr, new_psr);
++
++ return ;
++}
++
++unsigned long vcpu_cover(struct kvm_vcpu *vcpu)
++{
++ struct ia64_psr vpsr;
++
++ struct kvm_pt_regs *regs = vcpu_regs(vcpu);
++ vpsr = *(struct ia64_psr *)&VCPU(vcpu, vpsr);
++
++ if (!vpsr.ic)
++ VCPU(vcpu, ifs) = regs->cr_ifs;
++ regs->cr_ifs = IA64_IFS_V;
++ return (IA64_NO_FAULT);
++}
++
++
++
++/**************************************************************************
++ VCPU banked general register access routines
++ **************************************************************************/
++#define vcpu_bsw0_unat(i, b0unat, b1unat, runat, VMM_PT_REGS_R16_SLOT) \
++ do { \
++ __asm__ __volatile__ ( \
++ ";;extr.u %0 = %3,%6,16;;\n" \
++ "dep %1 = %0, %1, 0, 16;;\n" \
++ "st8 [%4] = %1\n" \
++ "extr.u %0 = %2, 16, 16;;\n" \
++ "dep %3 = %0, %3, %6, 16;;\n" \
++ "st8 [%5] = %3\n" \
++ ::"r"(i), "r"(*b1unat), "r"(*b0unat), \
++ "r"(*runat), "r"(b1unat), "r"(runat), \
++ "i"(VMM_PT_REGS_R16_SLOT) : "memory"); \
++ } while (0)
++
++void vcpu_bsw0(struct kvm_vcpu *vcpu)
++{
++ unsigned long i;
++
++ struct kvm_pt_regs *regs = vcpu_regs(vcpu);
++ unsigned long *r = ®s->r16;
++ unsigned long *b0 = &VCPU(vcpu, vbgr[0]);
++ unsigned long *b1 = &VCPU(vcpu, vgr[0]);
++ unsigned long *runat = ®s->eml_unat;
++ unsigned long *b0unat = &VCPU(vcpu, vbnat);
++ unsigned long *b1unat = &VCPU(vcpu, vnat);
++
++
++ if (VCPU(vcpu, vpsr) & IA64_PSR_BN) {
++ for (i = 0; i < 16; i++) {
++ *b1++ = *r;
++ *r++ = *b0++;
++ }
++ vcpu_bsw0_unat(i, b0unat, b1unat, runat,
++ VMM_PT_REGS_R16_SLOT);
++ VCPU(vcpu, vpsr) &= ~IA64_PSR_BN;
++ }
++}
++
++#define vcpu_bsw1_unat(i, b0unat, b1unat, runat, VMM_PT_REGS_R16_SLOT) \
++ do { \
++ __asm__ __volatile__ (";;extr.u %0 = %3, %6, 16;;\n" \
++ "dep %1 = %0, %1, 16, 16;;\n" \
++ "st8 [%4] = %1\n" \
++ "extr.u %0 = %2, 0, 16;;\n" \
++ "dep %3 = %0, %3, %6, 16;;\n" \
++ "st8 [%5] = %3\n" \
++ ::"r"(i), "r"(*b0unat), "r"(*b1unat), \
++ "r"(*runat), "r"(b0unat), "r"(runat), \
++ "i"(VMM_PT_REGS_R16_SLOT) : "memory"); \
++ } while (0)
++
++void vcpu_bsw1(struct kvm_vcpu *vcpu)
++{
++ unsigned long i;
++ struct kvm_pt_regs *regs = vcpu_regs(vcpu);
++ unsigned long *r = ®s->r16;
++ unsigned long *b0 = &VCPU(vcpu, vbgr[0]);
++ unsigned long *b1 = &VCPU(vcpu, vgr[0]);
++ unsigned long *runat = ®s->eml_unat;
++ unsigned long *b0unat = &VCPU(vcpu, vbnat);
++ unsigned long *b1unat = &VCPU(vcpu, vnat);
++
++ if (!(VCPU(vcpu, vpsr) & IA64_PSR_BN)) {
++ for (i = 0; i < 16; i++) {
++ *b0++ = *r;
++ *r++ = *b1++;
++ }
++ vcpu_bsw1_unat(i, b0unat, b1unat, runat,
++ VMM_PT_REGS_R16_SLOT);
++ VCPU(vcpu, vpsr) |= IA64_PSR_BN;
++ }
++}
++
++
++
++
++void vcpu_rfi(struct kvm_vcpu *vcpu)
++{
++ unsigned long ifs, psr;
++ struct kvm_pt_regs *regs = vcpu_regs(vcpu);
++
++ psr = VCPU(vcpu, ipsr);
++ if (psr & IA64_PSR_BN)
++ vcpu_bsw1(vcpu);
++ else
++ vcpu_bsw0(vcpu);
++ vcpu_set_psr(vcpu, psr);
++ ifs = VCPU(vcpu, ifs);
++ if (ifs >> 63)
++ regs->cr_ifs = ifs;
++ regs->cr_iip = VCPU(vcpu, iip);
++}
++
++
++/*
++ VPSR can't keep track of below bits of guest PSR
++ This function gets guest PSR
++ */
++
++unsigned long vcpu_get_psr(struct kvm_vcpu *vcpu)
++{
++ unsigned long mask;
++ struct kvm_pt_regs *regs = vcpu_regs(vcpu);
++
++ mask = IA64_PSR_BE | IA64_PSR_UP | IA64_PSR_AC | IA64_PSR_MFL |
++ IA64_PSR_MFH | IA64_PSR_CPL | IA64_PSR_RI;
++ return (VCPU(vcpu, vpsr) & ~mask) | (regs->cr_ipsr & mask);
++}
++
++void kvm_rsm(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long vpsr;
++ unsigned long imm24 = (inst.M44.i<<23) | (inst.M44.i2<<21)
++ | inst.M44.imm;
++
++ vpsr = vcpu_get_psr(vcpu);
++ vpsr &= (~imm24);
++ vcpu_set_psr(vcpu, vpsr);
++}
++
++void kvm_ssm(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long vpsr;
++ unsigned long imm24 = (inst.M44.i << 23) | (inst.M44.i2 << 21)
++ | inst.M44.imm;
++
++ vpsr = vcpu_get_psr(vcpu);
++ vpsr |= imm24;
++ vcpu_set_psr(vcpu, vpsr);
++}
++
++/* Generate Mask
++ * Parameter:
++ * bit -- starting bit
++ * len -- how many bits
++ */
++#define MASK(bit,len) \
++({ \
++ __u64 ret; \
++ \
++ __asm __volatile("dep %0=-1, r0, %1, %2"\
++ : "=r" (ret): \
++ "M" (bit), \
++ "M" (len)); \
++ ret; \
++})
++
++void vcpu_set_psr_l(struct kvm_vcpu *vcpu, unsigned long val)
++{
++ val = (val & MASK(0, 32)) | (vcpu_get_psr(vcpu) & MASK(32, 32));
++ vcpu_set_psr(vcpu, val);
++}
++
++void kvm_mov_to_psr(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long val;
++
++ val = vcpu_get_gr(vcpu, inst.M35.r2);
++ vcpu_set_psr_l(vcpu, val);
++}
++
++void kvm_mov_from_psr(struct kvm_vcpu *vcpu, INST64 inst)
++{
++ unsigned long val;
++
++ val = vcpu_get_psr(vcpu);
++ val = (val & MASK(0, 32)) | (val & MASK(35, 2));
++ vcpu_set_gr(vcpu, inst.M33.r1, val, 0);
++}
++
++void vcpu_increment_iip(struct kvm_vcpu *vcpu)
++{
++ struct kvm_pt_regs *regs = vcpu_regs(vcpu);
++ struct ia64_psr *ipsr = (struct ia64_psr *)®s->cr_ipsr;
++ if (ipsr->ri == 2) {
++ ipsr->ri = 0;
++ regs->cr_iip += 16;
++ } else
++ ipsr->ri++;
++}
++
++void vcpu_decrement_iip(struct kvm_vcpu *vcpu)
++{
++ struct kvm_pt_regs *regs = vcpu_regs(vcpu);
++ struct ia64_psr *ipsr = (struct ia64_psr *)®s->cr_ipsr;
++
++ if (ipsr->ri == 0) {
++ ipsr->ri = 2;
++ regs->cr_iip -= 16;
++ } else
++ ipsr->ri--;
++}
++
++/** Emulate a privileged operation.
++ *
++ *
++ * @param vcpu virtual cpu
++ * @cause the reason cause virtualization fault
++ * @opcode the instruction code which cause virtualization fault
++ */
++
++void kvm_emulate(struct kvm_vcpu *vcpu, struct kvm_pt_regs *regs)
++{
++ unsigned long status, cause, opcode ;
++ INST64 inst;
++
++ status = IA64_NO_FAULT;
++ cause = VMX(vcpu, cause);
++ opcode = VMX(vcpu, opcode);
++ inst.inst = opcode;
++ /*
++ * Switch to actual virtual rid in rr0 and rr4,
++ * which is required by some tlb related instructions.
++ */
++ prepare_if_physical_mode(vcpu);
++
++ switch (cause) {
++ case EVENT_RSM:
++ kvm_rsm(vcpu, inst);
++ break;
++ case EVENT_SSM:
++ kvm_ssm(vcpu, inst);
++ break;
++ case EVENT_MOV_TO_PSR:
++ kvm_mov_to_psr(vcpu, inst);
++ break;
++ case EVENT_MOV_FROM_PSR:
++ kvm_mov_from_psr(vcpu, inst);
++ break;
++ case EVENT_MOV_FROM_CR:
++ kvm_mov_from_cr(vcpu, inst);
++ break;
++ case EVENT_MOV_TO_CR:
++ kvm_mov_to_cr(vcpu, inst);
++ break;
++ case EVENT_BSW_0:
++ vcpu_bsw0(vcpu);
++ break;
++ case EVENT_BSW_1:
++ vcpu_bsw1(vcpu);
++ break;
++ case EVENT_COVER:
++ vcpu_cover(vcpu);
++ break;
++ case EVENT_RFI:
++ vcpu_rfi(vcpu);
++ break;
++ case EVENT_ITR_D:
++ kvm_itr_d(vcpu, inst);
++ break;
++ case EVENT_ITR_I:
++ kvm_itr_i(vcpu, inst);
++ break;
++ case EVENT_PTR_D:
++ kvm_ptr_d(vcpu, inst);
++ break;
++ case EVENT_PTR_I:
++ kvm_ptr_i(vcpu, inst);
++ break;
++ case EVENT_ITC_D:
++ kvm_itc_d(vcpu, inst);
++ break;
++ case EVENT_ITC_I:
++ kvm_itc_i(vcpu, inst);
++ break;
++ case EVENT_PTC_L:
++ kvm_ptc_l(vcpu, inst);
++ break;
++ case EVENT_PTC_G:
++ kvm_ptc_g(vcpu, inst);
++ break;
++ case EVENT_PTC_GA:
++ kvm_ptc_ga(vcpu, inst);
++ break;
++ case EVENT_PTC_E:
++ kvm_ptc_e(vcpu, inst);
++ break;
++ case EVENT_MOV_TO_RR:
++ kvm_mov_to_rr(vcpu, inst);
++ break;
++ case EVENT_MOV_FROM_RR:
++ kvm_mov_from_rr(vcpu, inst);
++ break;
++ case EVENT_THASH:
++ kvm_thash(vcpu, inst);
++ break;
++ case EVENT_TTAG:
++ kvm_ttag(vcpu, inst);
++ break;
++ case EVENT_TPA:
++ status = kvm_tpa(vcpu, inst);
++ break;
++ case EVENT_TAK:
++ kvm_tak(vcpu, inst);
++ break;
++ case EVENT_MOV_TO_AR_IMM:
++ kvm_mov_to_ar_imm(vcpu, inst);
++ break;
++ case EVENT_MOV_TO_AR:
++ kvm_mov_to_ar_reg(vcpu, inst);
++ break;
++ case EVENT_MOV_FROM_AR:
++ kvm_mov_from_ar_reg(vcpu, inst);
++ break;
++ case EVENT_MOV_TO_DBR:
++ kvm_mov_to_dbr(vcpu, inst);
++ break;
++ case EVENT_MOV_TO_IBR:
++ kvm_mov_to_ibr(vcpu, inst);
++ break;
++ case EVENT_MOV_TO_PMC:
++ kvm_mov_to_pmc(vcpu, inst);
++ break;
++ case EVENT_MOV_TO_PMD:
++ kvm_mov_to_pmd(vcpu, inst);
++ break;
++ case EVENT_MOV_TO_PKR:
++ kvm_mov_to_pkr(vcpu, inst);
++ break;
++ case EVENT_MOV_FROM_DBR:
++ kvm_mov_from_dbr(vcpu, inst);
++ break;
++ case EVENT_MOV_FROM_IBR:
++ kvm_mov_from_ibr(vcpu, inst);
++ break;
++ case EVENT_MOV_FROM_PMC:
++ kvm_mov_from_pmc(vcpu, inst);
++ break;
++ case EVENT_MOV_FROM_PKR:
++ kvm_mov_from_pkr(vcpu, inst);
++ break;
++ case EVENT_MOV_FROM_CPUID:
++ kvm_mov_from_cpuid(vcpu, inst);
++ break;
++ case EVENT_VMSW:
++ status = IA64_FAULT;
++ break;
++ default:
++ break;
++ };
++ /*Assume all status is NO_FAULT ?*/
++ if (status == IA64_NO_FAULT && cause != EVENT_RFI)
++ vcpu_increment_iip(vcpu);
++
++ recover_if_physical_mode(vcpu);
++}
++
++void init_vcpu(struct kvm_vcpu *vcpu)
++{
++ int i;
++
++ vcpu->arch.mode_flags = GUEST_IN_PHY;
++ VMX(vcpu, vrr[0]) = 0x38;
++ VMX(vcpu, vrr[1]) = 0x38;
++ VMX(vcpu, vrr[2]) = 0x38;
++ VMX(vcpu, vrr[3]) = 0x38;
++ VMX(vcpu, vrr[4]) = 0x38;
++ VMX(vcpu, vrr[5]) = 0x38;
++ VMX(vcpu, vrr[6]) = 0x38;
++ VMX(vcpu, vrr[7]) = 0x38;
++ VCPU(vcpu, vpsr) = IA64_PSR_BN;
++ VCPU(vcpu, dcr) = 0;
++ /* pta.size must not be 0. The minimum is 15 (32k) */
++ VCPU(vcpu, pta) = 15 << 2;
++ VCPU(vcpu, itv) = 0x10000;
++ VCPU(vcpu, itm) = 0;
++ VMX(vcpu, last_itc) = 0;
++
++ VCPU(vcpu, lid) = VCPU_LID(vcpu);
++ VCPU(vcpu, ivr) = 0;
++ VCPU(vcpu, tpr) = 0x10000;
++ VCPU(vcpu, eoi) = 0;
++ VCPU(vcpu, irr[0]) = 0;
++ VCPU(vcpu, irr[1]) = 0;
++ VCPU(vcpu, irr[2]) = 0;
++ VCPU(vcpu, irr[3]) = 0;
++ VCPU(vcpu, pmv) = 0x10000;
++ VCPU(vcpu, cmcv) = 0x10000;
++ VCPU(vcpu, lrr0) = 0x10000; /* default reset value? */
++ VCPU(vcpu, lrr1) = 0x10000; /* default reset value? */
++ update_vhpi(vcpu, NULL_VECTOR);
++ VLSAPIC_XTP(vcpu) = 0x80; /* disabled */
++
++ for (i = 0; i < 4; i++)
++ VLSAPIC_INSVC(vcpu, i) = 0;
++}
++
++void kvm_init_all_rr(struct kvm_vcpu *vcpu)
++{
++ unsigned long psr;
++
++ local_irq_save(psr);
++
++ /* WARNING: not allow co-exist of both virtual mode and physical
++ * mode in same region
++ */
++
++ vcpu->arch.metaphysical_saved_rr0 = vrrtomrr(VMX(vcpu, vrr[VRN0]));
++ vcpu->arch.metaphysical_saved_rr4 = vrrtomrr(VMX(vcpu, vrr[VRN4]));
++
++ if (is_physical_mode(vcpu)) {
++ if (vcpu->arch.mode_flags & GUEST_PHY_EMUL)
++ panic_vm(vcpu);
++
++ ia64_set_rr((VRN0 << VRN_SHIFT), vcpu->arch.metaphysical_rr0);
++ ia64_dv_serialize_data();
++ ia64_set_rr((VRN4 << VRN_SHIFT), vcpu->arch.metaphysical_rr4);
++ ia64_dv_serialize_data();
++ } else {
++ ia64_set_rr((VRN0 << VRN_SHIFT),
++ vcpu->arch.metaphysical_saved_rr0);
++ ia64_dv_serialize_data();
++ ia64_set_rr((VRN4 << VRN_SHIFT),
++ vcpu->arch.metaphysical_saved_rr4);
++ ia64_dv_serialize_data();
++ }
++ ia64_set_rr((VRN1 << VRN_SHIFT),
++ vrrtomrr(VMX(vcpu, vrr[VRN1])));
++ ia64_dv_serialize_data();
++ ia64_set_rr((VRN2 << VRN_SHIFT),
++ vrrtomrr(VMX(vcpu, vrr[VRN2])));
++ ia64_dv_serialize_data();
++ ia64_set_rr((VRN3 << VRN_SHIFT),
++ vrrtomrr(VMX(vcpu, vrr[VRN3])));
++ ia64_dv_serialize_data();
++ ia64_set_rr((VRN5 << VRN_SHIFT),
++ vrrtomrr(VMX(vcpu, vrr[VRN5])));
++ ia64_dv_serialize_data();
++ ia64_set_rr((VRN7 << VRN_SHIFT),
++ vrrtomrr(VMX(vcpu, vrr[VRN7])));
++ ia64_dv_serialize_data();
++ ia64_srlz_d();
++ ia64_set_psr(psr);
++}
++
++int vmm_entry(void)
++{
++ struct kvm_vcpu *v;
++ v = current_vcpu;
++
++ ia64_call_vsa(PAL_VPS_RESTORE, (unsigned long)v->arch.vpd,
++ 0, 0, 0, 0, 0, 0);
++ kvm_init_vtlb(v);
++ kvm_init_vhpt(v);
++ init_vcpu(v);
++ kvm_init_all_rr(v);
++ vmm_reset_entry();
++
++ return 0;
++}
++
++void panic_vm(struct kvm_vcpu *v)
++{
++ struct exit_ctl_data *p = &v->arch.exit_data;
++
++ p->exit_reason = EXIT_REASON_VM_PANIC;
++ vmm_transition(v);
++ /*Never to return*/
++ while (1);
++}
+diff --git a/arch/ia64/kvm/vcpu.h b/arch/ia64/kvm/vcpu.h
+new file mode 100644
+index 0000000..b0fcfb6
+--- /dev/null
++++ b/arch/ia64/kvm/vcpu.h
+@@ -0,0 +1,740 @@
++/*
++ * vcpu.h: vcpu routines
++ * Copyright (c) 2005, Intel Corporation.
++ * Xuefei Xu (Anthony Xu) (Anthony.xu at intel.com)
++ * Yaozu Dong (Eddie Dong) (Eddie.dong at intel.com)
++ *
++ * Copyright (c) 2007, Intel Corporation.
++ * Xuefei Xu (Anthony Xu) (Anthony.xu at intel.com)
++ * Xiantao Zhang (xiantao.zhang at intel.com)
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You 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 __KVM_VCPU_H__
++#define __KVM_VCPU_H__
++
++#include <asm/types.h>
++#include <asm/fpu.h>
++#include <asm/processor.h>
++
++#ifndef __ASSEMBLY__
++#include "vti.h"
++
++#include <linux/kvm_host.h>
++#include <linux/spinlock.h>
++
++typedef unsigned long IA64_INST;
++
++typedef union U_IA64_BUNDLE {
++ unsigned long i64[2];
++ struct { unsigned long template:5, slot0:41, slot1a:18,
++ slot1b:23, slot2:41; };
++ /* NOTE: following doesn't work because bitfields can't cross natural
++ size boundaries
++ struct { unsigned long template:5, slot0:41, slot1:41, slot2:41; }; */
++} IA64_BUNDLE;
++
++typedef union U_INST64_A5 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, r1:7, imm7b:7, r3:2, imm5c:5,
++ imm9d:9, s:1, major:4; };
++} INST64_A5;
++
++typedef union U_INST64_B4 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, btype:3, un3:3, p:1, b2:3, un11:11, x6:6,
++ wh:2, d:1, un1:1, major:4; };
++} INST64_B4;
++
++typedef union U_INST64_B8 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, un21:21, x6:6, un4:4, major:4; };
++} INST64_B8;
++
++typedef union U_INST64_B9 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, imm20:20, :1, x6:6, :3, i:1, major:4; };
++} INST64_B9;
++
++typedef union U_INST64_I19 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, imm20:20, :1, x6:6, x3:3, i:1, major:4; };
++} INST64_I19;
++
++typedef union U_INST64_I26 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, :7, r2:7, ar3:7, x6:6, x3:3, :1, major:4; };
++} INST64_I26;
++
++typedef union U_INST64_I27 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, :7, imm:7, ar3:7, x6:6, x3:3, s:1, major:4; };
++} INST64_I27;
++
++typedef union U_INST64_I28 { /* not privileged (mov from AR) */
++ IA64_INST inst;
++ struct { unsigned long qp:6, r1:7, :7, ar3:7, x6:6, x3:3, :1, major:4; };
++} INST64_I28;
++
++typedef union U_INST64_M28 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, :14, r3:7, x6:6, x3:3, :1, major:4; };
++} INST64_M28;
++
++typedef union U_INST64_M29 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, :7, r2:7, ar3:7, x6:6, x3:3, :1, major:4; };
++} INST64_M29;
++
++typedef union U_INST64_M30 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, :7, imm:7, ar3:7, x4:4, x2:2,
++ x3:3, s:1, major:4; };
++} INST64_M30;
++
++typedef union U_INST64_M31 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, r1:7, :7, ar3:7, x6:6, x3:3, :1, major:4; };
++} INST64_M31;
++
++typedef union U_INST64_M32 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, :7, r2:7, cr3:7, x6:6, x3:3, :1, major:4; };
++} INST64_M32;
++
++typedef union U_INST64_M33 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, r1:7, :7, cr3:7, x6:6, x3:3, :1, major:4; };
++} INST64_M33;
++
++typedef union U_INST64_M35 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, :7, r2:7, :7, x6:6, x3:3, :1, major:4; };
++
++} INST64_M35;
++
++typedef union U_INST64_M36 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, r1:7, :14, x6:6, x3:3, :1, major:4; };
++} INST64_M36;
++
++typedef union U_INST64_M37 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, imm20a:20, :1, x4:4, x2:2, x3:3,
++ i:1, major:4; };
++} INST64_M37;
++
++typedef union U_INST64_M41 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, :7, r2:7, :7, x6:6, x3:3, :1, major:4; };
++} INST64_M41;
++
++typedef union U_INST64_M42 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, :7, r2:7, r3:7, x6:6, x3:3, :1, major:4; };
++} INST64_M42;
++
++typedef union U_INST64_M43 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, r1:7, :7, r3:7, x6:6, x3:3, :1, major:4; };
++} INST64_M43;
++
++typedef union U_INST64_M44 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, imm:21, x4:4, i2:2, x3:3, i:1, major:4; };
++} INST64_M44;
++
++typedef union U_INST64_M45 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, :7, r2:7, r3:7, x6:6, x3:3, :1, major:4; };
++} INST64_M45;
++
++typedef union U_INST64_M46 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, r1:7, un7:7, r3:7, x6:6,
++ x3:3, un1:1, major:4; };
++} INST64_M46;
++
++typedef union U_INST64_M47 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, un14:14, r3:7, x6:6, x3:3, un1:1, major:4; };
++} INST64_M47;
++
++typedef union U_INST64_M1{
++ IA64_INST inst;
++ struct { unsigned long qp:6, r1:7, un7:7, r3:7, x:1, hint:2,
++ x6:6, m:1, major:4; };
++} INST64_M1;
++
++typedef union U_INST64_M2{
++ IA64_INST inst;
++ struct { unsigned long qp:6, r1:7, r2:7, r3:7, x:1, hint:2,
++ x6:6, m:1, major:4; };
++} INST64_M2;
++
++typedef union U_INST64_M3{
++ IA64_INST inst;
++ struct { unsigned long qp:6, r1:7, imm7:7, r3:7, i:1, hint:2,
++ x6:6, s:1, major:4; };
++} INST64_M3;
++
++typedef union U_INST64_M4 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, un7:7, r2:7, r3:7, x:1, hint:2,
++ x6:6, m:1, major:4; };
++} INST64_M4;
++
++typedef union U_INST64_M5 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, imm7:7, r2:7, r3:7, i:1, hint:2,
++ x6:6, s:1, major:4; };
++} INST64_M5;
++
++typedef union U_INST64_M6 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, f1:7, un7:7, r3:7, x:1, hint:2,
++ x6:6, m:1, major:4; };
++} INST64_M6;
++
++typedef union U_INST64_M9 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, :7, f2:7, r3:7, x:1, hint:2,
++ x6:6, m:1, major:4; };
++} INST64_M9;
++
++typedef union U_INST64_M10 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, imm7:7, f2:7, r3:7, i:1, hint:2,
++ x6:6, s:1, major:4; };
++} INST64_M10;
++
++typedef union U_INST64_M12 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, f1:7, f2:7, r3:7, x:1, hint:2,
++ x6:6, m:1, major:4; };
++} INST64_M12;
++
++typedef union U_INST64_M15 {
++ IA64_INST inst;
++ struct { unsigned long qp:6, :7, imm7:7, r3:7, i:1, hint:2,
++ x6:6, s:1, major:4; };
++} INST64_M15;
++
++typedef union U_INST64 {
++ IA64_INST inst;
++ struct { unsigned long :37, major:4; } generic;
++ INST64_A5 A5; /* used in build_hypercall_bundle only */
++ INST64_B4 B4; /* used in build_hypercall_bundle only */
++ INST64_B8 B8; /* rfi, bsw.[01] */
++ INST64_B9 B9; /* break.b */
++ INST64_I19 I19; /* used in build_hypercall_bundle only */
++ INST64_I26 I26; /* mov register to ar (I unit) */
++ INST64_I27 I27; /* mov immediate to ar (I unit) */
++ INST64_I28 I28; /* mov from ar (I unit) */
++ INST64_M1 M1; /* ld integer */
++ INST64_M2 M2;
++ INST64_M3 M3;
++ INST64_M4 M4; /* st integer */
++ INST64_M5 M5;
++ INST64_M6 M6; /* ldfd floating pointer */
++ INST64_M9 M9; /* stfd floating pointer */
++ INST64_M10 M10; /* stfd floating pointer */
++ INST64_M12 M12; /* ldfd pair floating pointer */
++ INST64_M15 M15; /* lfetch + imm update */
++ INST64_M28 M28; /* purge translation cache entry */
++ INST64_M29 M29; /* mov register to ar (M unit) */
++ INST64_M30 M30; /* mov immediate to ar (M unit) */
++ INST64_M31 M31; /* mov from ar (M unit) */
++ INST64_M32 M32; /* mov reg to cr */
++ INST64_M33 M33; /* mov from cr */
++ INST64_M35 M35; /* mov to psr */
++ INST64_M36 M36; /* mov from psr */
++ INST64_M37 M37; /* break.m */
++ INST64_M41 M41; /* translation cache insert */
++ INST64_M42 M42; /* mov to indirect reg/translation reg insert*/
++ INST64_M43 M43; /* mov from indirect reg */
++ INST64_M44 M44; /* set/reset system mask */
++ INST64_M45 M45; /* translation purge */
++ INST64_M46 M46; /* translation access (tpa,tak) */
++ INST64_M47 M47; /* purge translation entry */
++} INST64;
++
++#define MASK_41 ((unsigned long)0x1ffffffffff)
++
++/* Virtual address memory attributes encoding */
++#define VA_MATTR_WB 0x0
++#define VA_MATTR_UC 0x4
++#define VA_MATTR_UCE 0x5
++#define VA_MATTR_WC 0x6
++#define VA_MATTR_NATPAGE 0x7
++
++#define PMASK(size) (~((size) - 1))
++#define PSIZE(size) (1UL<<(size))
++#define CLEARLSB(ppn, nbits) (((ppn) >> (nbits)) << (nbits))
++#define PAGEALIGN(va, ps) CLEARLSB(va, ps)
++#define PAGE_FLAGS_RV_MASK (0x2|(0x3UL<<50)|(((1UL<<11)-1)<<53))
++#define _PAGE_MA_ST (0x1 << 2) /* is reserved for software use */
++
++#define ARCH_PAGE_SHIFT 12
++
++#define INVALID_TI_TAG (1UL << 63)
++
++#define VTLB_PTE_P_BIT 0
++#define VTLB_PTE_IO_BIT 60
++#define VTLB_PTE_IO (1UL<<VTLB_PTE_IO_BIT)
++#define VTLB_PTE_P (1UL<<VTLB_PTE_P_BIT)
++
++#define vcpu_quick_region_check(_tr_regions,_ifa) \
++ (_tr_regions & (1 << ((unsigned long)_ifa >> 61)))
++
++#define vcpu_quick_region_set(_tr_regions,_ifa) \
++ do {_tr_regions |= (1 << ((unsigned long)_ifa >> 61)); } while (0)
++
++static inline void vcpu_set_tr(struct thash_data *trp, u64 pte, u64 itir,
++ u64 va, u64 rid)
++{
++ trp->page_flags = pte;
++ trp->itir = itir;
++ trp->vadr = va;
++ trp->rid = rid;
++}
++
++extern u64 kvm_lookup_mpa(u64 gpfn);
++extern u64 kvm_gpa_to_mpa(u64 gpa);
++
++/* Return I/O type if trye */
++#define __gpfn_is_io(gpfn) \
++ ({ \
++ u64 pte, ret = 0; \
++ pte = kvm_lookup_mpa(gpfn); \
++ if (!(pte & GPFN_INV_MASK)) \
++ ret = pte & GPFN_IO_MASK; \
++ ret; \
++ })
++
++#endif
++
++#define IA64_NO_FAULT 0
++#define IA64_FAULT 1
++
++#define VMM_RBS_OFFSET ((VMM_TASK_SIZE + 15) & ~15)
++
++#define SW_BAD 0 /* Bad mode transitition */
++#define SW_V2P 1 /* Physical emulatino is activated */
++#define SW_P2V 2 /* Exit physical mode emulation */
++#define SW_SELF 3 /* No mode transition */
++#define SW_NOP 4 /* Mode transition, but without action required */
++
++#define GUEST_IN_PHY 0x1
++#define GUEST_PHY_EMUL 0x2
++
++#define current_vcpu ((struct kvm_vcpu *) ia64_getreg(_IA64_REG_TP))
++
++#define VRN_SHIFT 61
++#define VRN_MASK 0xe000000000000000
++#define VRN0 0x0UL
++#define VRN1 0x1UL
++#define VRN2 0x2UL
++#define VRN3 0x3UL
++#define VRN4 0x4UL
++#define VRN5 0x5UL
++#define VRN6 0x6UL
++#define VRN7 0x7UL
++
++#define IRQ_NO_MASKED 0
++#define IRQ_MASKED_BY_VTPR 1
++#define IRQ_MASKED_BY_INSVC 2 /* masked by inservice IRQ */
++
++#define PTA_BASE_SHIFT 15
++
++#define IA64_PSR_VM_BIT 46
++#define IA64_PSR_VM (__IA64_UL(1) << IA64_PSR_VM_BIT)
++
++/* Interruption Function State */
++#define IA64_IFS_V_BIT 63
++#define IA64_IFS_V (__IA64_UL(1) << IA64_IFS_V_BIT)
++
++#define PHY_PAGE_UC (_PAGE_A|_PAGE_D|_PAGE_P|_PAGE_MA_UC|_PAGE_AR_RWX)
++#define PHY_PAGE_WB (_PAGE_A|_PAGE_D|_PAGE_P|_PAGE_MA_WB|_PAGE_AR_RWX)
++
++#ifndef __ASSEMBLY__
++
++#include <asm/gcc_intrin.h>
++
++#define is_physical_mode(v) \
++ ((v->arch.mode_flags) & GUEST_IN_PHY)
++
++#define is_virtual_mode(v) \
++ (!is_physical_mode(v))
++
++#define MODE_IND(psr) \
++ (((psr).it << 2) + ((psr).dt << 1) + (psr).rt)
++
++#define _vmm_raw_spin_lock(x) \
++ do { \
++ __u32 *ia64_spinlock_ptr = (__u32 *) (x); \
++ __u64 ia64_spinlock_val; \
++ ia64_spinlock_val = ia64_cmpxchg4_acq(ia64_spinlock_ptr, 1, 0);\
++ if (unlikely(ia64_spinlock_val)) { \
++ do { \
++ while (*ia64_spinlock_ptr) \
++ ia64_barrier(); \
++ ia64_spinlock_val = \
++ ia64_cmpxchg4_acq(ia64_spinlock_ptr, 1, 0);\
++ } while (ia64_spinlock_val); \
++ } \
++ } while (0)
++
++#define _vmm_raw_spin_unlock(x) \
++ do { barrier(); \
++ ((spinlock_t *)x)->raw_lock.lock = 0; } \
++while (0)
++
++void vmm_spin_lock(spinlock_t *lock);
++void vmm_spin_unlock(spinlock_t *lock);
++enum {
++ I_TLB = 1,
++ D_TLB = 2
++};
++
++union kvm_va {
++ struct {
++ unsigned long off : 60; /* intra-region offset */
++ unsigned long reg : 4; /* region number */
++ } f;
++ unsigned long l;
++ void *p;
++};
++
++#define __kvm_pa(x) ({union kvm_va _v; _v.l = (long) (x); \
++ _v.f.reg = 0; _v.l; })
++#define __kvm_va(x) ({union kvm_va _v; _v.l = (long) (x); \
++ _v.f.reg = -1; _v.p; })
++
++#define _REGION_ID(x) ({union ia64_rr _v; _v.val = (long)(x); \
++ _v.rid; })
++#define _REGION_PAGE_SIZE(x) ({union ia64_rr _v; _v.val = (long)(x); \
++ _v.ps; })
++#define _REGION_HW_WALKER(x) ({union ia64_rr _v; _v.val = (long)(x); \
++ _v.ve; })
++
++enum vhpt_ref{ DATA_REF, NA_REF, INST_REF, RSE_REF };
++enum tlb_miss_type { INSTRUCTION, DATA, REGISTER };
++
++#define VCPU(_v, _x) ((_v)->arch.vpd->_x)
++#define VMX(_v, _x) ((_v)->arch._x)
++
++#define VLSAPIC_INSVC(vcpu, i) ((vcpu)->arch.insvc[i])
++#define VLSAPIC_XTP(_v) VMX(_v, xtp)
++
++static inline unsigned long itir_ps(unsigned long itir)
++{
++ return ((itir >> 2) & 0x3f);
++}
++
++
++/**************************************************************************
++ VCPU control register access routines
++ **************************************************************************/
++
++static inline u64 vcpu_get_itir(struct kvm_vcpu *vcpu)
++{
++ return ((u64)VCPU(vcpu, itir));
++}
++
++static inline void vcpu_set_itir(struct kvm_vcpu *vcpu, u64 val)
++{
++ VCPU(vcpu, itir) = val;
++}
++
++static inline u64 vcpu_get_ifa(struct kvm_vcpu *vcpu)
++{
++ return ((u64)VCPU(vcpu, ifa));
++}
++
++static inline void vcpu_set_ifa(struct kvm_vcpu *vcpu, u64 val)
++{
++ VCPU(vcpu, ifa) = val;
++}
++
++static inline u64 vcpu_get_iva(struct kvm_vcpu *vcpu)
++{
++ return ((u64)VCPU(vcpu, iva));
++}
++
++static inline u64 vcpu_get_pta(struct kvm_vcpu *vcpu)
++{
++ return ((u64)VCPU(vcpu, pta));
++}
++
++static inline u64 vcpu_get_lid(struct kvm_vcpu *vcpu)
++{
++ return ((u64)VCPU(vcpu, lid));
++}
++
++static inline u64 vcpu_get_tpr(struct kvm_vcpu *vcpu)
++{
++ return ((u64)VCPU(vcpu, tpr));
++}
++
++static inline u64 vcpu_get_eoi(struct kvm_vcpu *vcpu)
++{
++ return (0UL); /*reads of eoi always return 0 */
++}
++
++static inline u64 vcpu_get_irr0(struct kvm_vcpu *vcpu)
++{
++ return ((u64)VCPU(vcpu, irr[0]));
++}
++
++static inline u64 vcpu_get_irr1(struct kvm_vcpu *vcpu)
++{
++ return ((u64)VCPU(vcpu, irr[1]));
++}
++
++static inline u64 vcpu_get_irr2(struct kvm_vcpu *vcpu)
++{
++ return ((u64)VCPU(vcpu, irr[2]));
++}
++
++static inline u64 vcpu_get_irr3(struct kvm_vcpu *vcpu)
++{
++ return ((u64)VCPU(vcpu, irr[3]));
++}
++
++static inline void vcpu_set_dcr(struct kvm_vcpu *vcpu, u64 val)
++{
++ ia64_setreg(_IA64_REG_CR_DCR, val);
++}
++
++static inline void vcpu_set_isr(struct kvm_vcpu *vcpu, u64 val)
++{
++ VCPU(vcpu, isr) = val;
++}
++
++static inline void vcpu_set_lid(struct kvm_vcpu *vcpu, u64 val)
++{
++ VCPU(vcpu, lid) = val;
++}
++
++static inline void vcpu_set_ipsr(struct kvm_vcpu *vcpu, u64 val)
++{
++ VCPU(vcpu, ipsr) = val;
++}
++
++static inline void vcpu_set_iip(struct kvm_vcpu *vcpu, u64 val)
++{
++ VCPU(vcpu, iip) = val;
++}
++
++static inline void vcpu_set_ifs(struct kvm_vcpu *vcpu, u64 val)
++{
++ VCPU(vcpu, ifs) = val;
++}
++
++static inline void vcpu_set_iipa(struct kvm_vcpu *vcpu, u64 val)
++{
++ VCPU(vcpu, iipa) = val;
++}
++
++static inline void vcpu_set_iha(struct kvm_vcpu *vcpu, u64 val)
++{
++ VCPU(vcpu, iha) = val;
++}
++
++
++static inline u64 vcpu_get_rr(struct kvm_vcpu *vcpu, u64 reg)
++{
++ return vcpu->arch.vrr[reg>>61];
++}
++
++/**************************************************************************
++ VCPU debug breakpoint register access routines
++ **************************************************************************/
++
++static inline void vcpu_set_dbr(struct kvm_vcpu *vcpu, u64 reg, u64 val)
++{
++ __ia64_set_dbr(reg, val);
++}
++
++static inline void vcpu_set_ibr(struct kvm_vcpu *vcpu, u64 reg, u64 val)
++{
++ ia64_set_ibr(reg, val);
++}
++
++static inline u64 vcpu_get_dbr(struct kvm_vcpu *vcpu, u64 reg)
++{
++ return ((u64)__ia64_get_dbr(reg));
++}
++
++static inline u64 vcpu_get_ibr(struct kvm_vcpu *vcpu, u64 reg)
++{
++ return ((u64)ia64_get_ibr(reg));
++}
++
++/**************************************************************************
++ VCPU performance monitor register access routines
++ **************************************************************************/
++static inline void vcpu_set_pmc(struct kvm_vcpu *vcpu, u64 reg, u64 val)
++{
++ /* NOTE: Writes to unimplemented PMC registers are discarded */
++ ia64_set_pmc(reg, val);
++}
++
++static inline void vcpu_set_pmd(struct kvm_vcpu *vcpu, u64 reg, u64 val)
++{
++ /* NOTE: Writes to unimplemented PMD registers are discarded */
++ ia64_set_pmd(reg, val);
++}
++
++static inline u64 vcpu_get_pmc(struct kvm_vcpu *vcpu, u64 reg)
++{
++ /* NOTE: Reads from unimplemented PMC registers return zero */
++ return ((u64)ia64_get_pmc(reg));
++}
++
++static inline u64 vcpu_get_pmd(struct kvm_vcpu *vcpu, u64 reg)
++{
++ /* NOTE: Reads from unimplemented PMD registers return zero */
++ return ((u64)ia64_get_pmd(reg));
++}
++
++static inline unsigned long vrrtomrr(unsigned long val)
++{
++ union ia64_rr rr;
++ rr.val = val;
++ rr.rid = (rr.rid << 4) | 0xe;
++ if (rr.ps > PAGE_SHIFT)
++ rr.ps = PAGE_SHIFT;
++ rr.ve = 1;
++ return rr.val;
++}
++
++
++static inline int highest_bits(int *dat)
++{
++ u32 bits, bitnum;
++ int i;
++
++ /* loop for all 256 bits */
++ for (i = 7; i >= 0 ; i--) {
++ bits = dat[i];
++ if (bits) {
++ bitnum = fls(bits);
++ return i * 32 + bitnum - 1;
++ }
++ }
++ return NULL_VECTOR;
++}
++
++/*
++ * The pending irq is higher than the inservice one.
++ *
++ */
++static inline int is_higher_irq(int pending, int inservice)
++{
++ return ((pending > inservice)
++ || ((pending != NULL_VECTOR)
++ && (inservice == NULL_VECTOR)));
++}
++
++static inline int is_higher_class(int pending, int mic)
++{
++ return ((pending >> 4) > mic);
++}
++
++/*
++ * Return 0-255 for pending irq.
++ * NULL_VECTOR: when no pending.
++ */
++static inline int highest_pending_irq(struct kvm_vcpu *vcpu)
++{
++ if (VCPU(vcpu, irr[0]) & (1UL<<NMI_VECTOR))
++ return NMI_VECTOR;
++ if (VCPU(vcpu, irr[0]) & (1UL<<ExtINT_VECTOR))
++ return ExtINT_VECTOR;
++
++ return highest_bits((int *)&VCPU(vcpu, irr[0]));
++}
++
++static inline int highest_inservice_irq(struct kvm_vcpu *vcpu)
++{
++ if (VMX(vcpu, insvc[0]) & (1UL<<NMI_VECTOR))
++ return NMI_VECTOR;
++ if (VMX(vcpu, insvc[0]) & (1UL<<ExtINT_VECTOR))
++ return ExtINT_VECTOR;
++
++ return highest_bits((int *)&(VMX(vcpu, insvc[0])));
++}
++
++extern void vcpu_get_fpreg(struct kvm_vcpu *vcpu, u64 reg,
++ struct ia64_fpreg *val);
++extern void vcpu_set_fpreg(struct kvm_vcpu *vcpu, u64 reg,
++ struct ia64_fpreg *val);
++extern u64 vcpu_get_gr(struct kvm_vcpu *vcpu, u64 reg);
++extern void vcpu_set_gr(struct kvm_vcpu *vcpu, u64 reg, u64 val, int nat);
++extern u64 vcpu_get_psr(struct kvm_vcpu *vcpu);
++extern void vcpu_set_psr(struct kvm_vcpu *vcpu, u64 val);
++extern u64 vcpu_thash(struct kvm_vcpu *vcpu, u64 vadr);
++extern void vcpu_bsw0(struct kvm_vcpu *vcpu);
++extern void thash_vhpt_insert(struct kvm_vcpu *v, u64 pte,
++ u64 itir, u64 va, int type);
++extern struct thash_data *vhpt_lookup(u64 va);
++extern u64 guest_vhpt_lookup(u64 iha, u64 *pte);
++extern void thash_purge_entries(struct kvm_vcpu *v, u64 va, u64 ps);
++extern void thash_purge_entries_remote(struct kvm_vcpu *v, u64 va, u64 ps);
++extern u64 translate_phy_pte(u64 *pte, u64 itir, u64 va);
++extern int thash_purge_and_insert(struct kvm_vcpu *v, u64 pte,
++ u64 itir, u64 ifa, int type);
++extern void thash_purge_all(struct kvm_vcpu *v);
++extern struct thash_data *vtlb_lookup(struct kvm_vcpu *v,
++ u64 va, int is_data);
++extern int vtr_find_overlap(struct kvm_vcpu *vcpu, u64 va,
++ u64 ps, int is_data);
++
++extern void vcpu_increment_iip(struct kvm_vcpu *v);
++extern void vcpu_decrement_iip(struct kvm_vcpu *vcpu);
++extern void vcpu_pend_interrupt(struct kvm_vcpu *vcpu, u8 vec);
++extern void vcpu_unpend_interrupt(struct kvm_vcpu *vcpu, u8 vec);
++extern void data_page_not_present(struct kvm_vcpu *vcpu, u64 vadr);
++extern void dnat_page_consumption(struct kvm_vcpu *vcpu, u64 vadr);
++extern void alt_dtlb(struct kvm_vcpu *vcpu, u64 vadr);
++extern void nested_dtlb(struct kvm_vcpu *vcpu);
++extern void dvhpt_fault(struct kvm_vcpu *vcpu, u64 vadr);
++extern int vhpt_enabled(struct kvm_vcpu *vcpu, u64 vadr, enum vhpt_ref ref);
++
++extern void update_vhpi(struct kvm_vcpu *vcpu, int vec);
++extern int irq_masked(struct kvm_vcpu *vcpu, int h_pending, int h_inservice);
++
++extern int fetch_code(struct kvm_vcpu *vcpu, u64 gip, IA64_BUNDLE *pbundle);
++extern void emulate_io_inst(struct kvm_vcpu *vcpu, u64 padr, u64 ma);
++extern void vmm_transition(struct kvm_vcpu *vcpu);
++extern void vmm_trampoline(union context *from, union context *to);
++extern int vmm_entry(void);
++extern u64 vcpu_get_itc(struct kvm_vcpu *vcpu);
++
++extern void vmm_reset_entry(void);
++void kvm_init_vtlb(struct kvm_vcpu *v);
++void kvm_init_vhpt(struct kvm_vcpu *v);
++void thash_init(struct thash_cb *hcb, u64 sz);
++
++void panic_vm(struct kvm_vcpu *v);
++
++extern u64 ia64_call_vsa(u64 proc, u64 arg1, u64 arg2, u64 arg3,
++ u64 arg4, u64 arg5, u64 arg6, u64 arg7);
++#endif
++#endif /* __VCPU_H__ */
+diff --git a/arch/ia64/kvm/vmm.c b/arch/ia64/kvm/vmm.c
+new file mode 100644
+index 0000000..2275bf4
+--- /dev/null
++++ b/arch/ia64/kvm/vmm.c
+@@ -0,0 +1,66 @@
++/*
++ * vmm.c: vmm module interface with kvm module
++ *
++ * Copyright (c) 2007, Intel Corporation.
++ *
++ * Xiantao Zhang (xiantao.zhang at intel.com)
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
++ * Place - Suite 330, Boston, MA 02111-1307 USA.
++ */
++
++
++#include<linux/module.h>
++#include<asm/fpswa.h>
++
++#include "vcpu.h"
++
++MODULE_AUTHOR("Intel");
++MODULE_LICENSE("GPL");
++
++extern char kvm_ia64_ivt;
++extern fpswa_interface_t *vmm_fpswa_interface;
++
++struct kvm_vmm_info vmm_info = {
++ .module = THIS_MODULE,
++ .vmm_entry = vmm_entry,
++ .tramp_entry = vmm_trampoline,
++ .vmm_ivt = (unsigned long)&kvm_ia64_ivt,
++};
++
++static int __init kvm_vmm_init(void)
++{
++
++ vmm_fpswa_interface = fpswa_interface;
++
++ /*Register vmm data to kvm side*/
++ return kvm_init(&vmm_info, 1024, THIS_MODULE);
++}
++
++static void __exit kvm_vmm_exit(void)
++{
++ kvm_exit();
++ return ;
++}
++
++void vmm_spin_lock(spinlock_t *lock)
++{
++ _vmm_raw_spin_lock(lock);
++}
++
++void vmm_spin_unlock(spinlock_t *lock)
++{
++ _vmm_raw_spin_unlock(lock);
++}
++module_init(kvm_vmm_init)
++module_exit(kvm_vmm_exit)
+diff --git a/arch/ia64/kvm/vmm_ivt.S b/arch/ia64/kvm/vmm_ivt.S
+new file mode 100644
+index 0000000..3ee5f48
+--- /dev/null
++++ b/arch/ia64/kvm/vmm_ivt.S
+@@ -0,0 +1,1424 @@
++/*
++ * /ia64/kvm_ivt.S
++ *
++ * Copyright (C) 1998-2001, 2003 Hewlett-Packard Co
++ * Stephane Eranian <eranian at hpl.hp.com>
++ * David Mosberger <davidm at hpl.hp.com>
++ * Copyright (C) 2000, 2002-2003 Intel Co
++ * Asit Mallick <asit.k.mallick at intel.com>
++ * Suresh Siddha <suresh.b.siddha at intel.com>
++ * Kenneth Chen <kenneth.w.chen at intel.com>
++ * Fenghua Yu <fenghua.yu at intel.com>
++ *
++ *
++ * 00/08/23 Asit Mallick <asit.k.mallick at intel.com> TLB handling
++ * for SMP
++ * 00/12/20 David Mosberger-Tang <davidm at hpl.hp.com> DTLB/ITLB
++ * handler now uses virtual PT.
++ *
++ * 07/6/20 Xuefei Xu (Anthony Xu) (anthony.xu at intel.com)
++ * Supporting Intel virtualization architecture
++ *
++ */
++
++/*
++ * This file defines the interruption vector table used by the CPU.
++ * It does not include one entry per possible cause of interruption.
++ *
++ * The first 20 entries of the table contain 64 bundles each while the
++ * remaining 48 entries contain only 16 bundles each.
++ *
++ * The 64 bundles are used to allow inlining the whole handler for
++ * critical
++ * interruptions like TLB misses.
++ *
++ * For each entry, the comment is as follows:
++ *
++ * // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss
++ * (12,51)
++ * entry offset ----/ / / /
++ * /
++ * entry number ---------/ / /
++ * /
++ * size of the entry -------------/ /
++ * /
++ * vector name -------------------------------------/
++ * /
++ * interruptions triggering this vector
++ * ----------------------/
++ *
++ * The table is 32KB in size and must be aligned on 32KB
++ * boundary.
++ * (The CPU ignores the 15 lower bits of the address)
++ *
++ * Table is based upon EAS2.6 (Oct 1999)
++ */
++
++
++#include <asm/asmmacro.h>
++#include <asm/cache.h>
++#include <asm/pgtable.h>
++
++#include "asm-offsets.h"
++#include "vcpu.h"
++#include "kvm_minstate.h"
++#include "vti.h"
++
++#if 1
++# define PSR_DEFAULT_BITS psr.ac
++#else
++# define PSR_DEFAULT_BITS 0
++#endif
++
++
++#define KVM_FAULT(n) \
++ kvm_fault_##n:; \
++ mov r19=n;; \
++ br.sptk.many kvm_fault_##n; \
++ ;; \
++
++
++#define KVM_REFLECT(n) \
++ mov r31=pr; \
++ mov r19=n; /* prepare to save predicates */ \
++ mov r29=cr.ipsr; \
++ ;; \
++ tbit.z p6,p7=r29,IA64_PSR_VM_BIT; \
++(p7)br.sptk.many kvm_dispatch_reflection; \
++ br.sptk.many kvm_panic; \
++
++
++GLOBAL_ENTRY(kvm_panic)
++ br.sptk.many kvm_panic
++ ;;
++END(kvm_panic)
++
++
++
++
++
++ .section .text.ivt,"ax"
++
++ .align 32768 // align on 32KB boundary
++ .global kvm_ia64_ivt
++kvm_ia64_ivt:
++///////////////////////////////////////////////////////////////
++// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)
++ENTRY(kvm_vhpt_miss)
++ KVM_FAULT(0)
++END(kvm_vhpt_miss)
++
++
++ .org kvm_ia64_ivt+0x400
++////////////////////////////////////////////////////////////////
++// 0x0400 Entry 1 (size 64 bundles) ITLB (21)
++ENTRY(kvm_itlb_miss)
++ mov r31 = pr
++ mov r29=cr.ipsr;
++ ;;
++ tbit.z p6,p7=r29,IA64_PSR_VM_BIT;
++ (p6) br.sptk kvm_alt_itlb_miss
++ mov r19 = 1
++ br.sptk kvm_itlb_miss_dispatch
++ KVM_FAULT(1);
++END(kvm_itlb_miss)
++
++ .org kvm_ia64_ivt+0x0800
++//////////////////////////////////////////////////////////////////
++// 0x0800 Entry 2 (size 64 bundles) DTLB (9,48)
++ENTRY(kvm_dtlb_miss)
++ mov r31 = pr
++ mov r29=cr.ipsr;
++ ;;
++ tbit.z p6,p7=r29,IA64_PSR_VM_BIT;
++(p6)br.sptk kvm_alt_dtlb_miss
++ br.sptk kvm_dtlb_miss_dispatch
++END(kvm_dtlb_miss)
++
++ .org kvm_ia64_ivt+0x0c00
++////////////////////////////////////////////////////////////////////
++// 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19)
++ENTRY(kvm_alt_itlb_miss)
++ mov r16=cr.ifa // get address that caused the TLB miss
++ ;;
++ movl r17=PAGE_KERNEL
++ mov r24=cr.ipsr
++ movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
++ ;;
++ and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
++ ;;
++ or r19=r17,r19 // insert PTE control bits into r19
++ ;;
++ movl r20=IA64_GRANULE_SHIFT<<2
++ ;;
++ mov cr.itir=r20
++ ;;
++ itc.i r19 // insert the TLB entry
++ mov pr=r31,-1
++ rfi
++END(kvm_alt_itlb_miss)
++
++ .org kvm_ia64_ivt+0x1000
++/////////////////////////////////////////////////////////////////////
++// 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46)
++ENTRY(kvm_alt_dtlb_miss)
++ mov r16=cr.ifa // get address that caused the TLB miss
++ ;;
++ movl r17=PAGE_KERNEL
++ movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
++ mov r24=cr.ipsr
++ ;;
++ and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
++ ;;
++ or r19=r19,r17 // insert PTE control bits into r19
++ ;;
++ movl r20=IA64_GRANULE_SHIFT<<2
++ ;;
++ mov cr.itir=r20
++ ;;
++ itc.d r19 // insert the TLB entry
++ mov pr=r31,-1
++ rfi
++END(kvm_alt_dtlb_miss)
++
++ .org kvm_ia64_ivt+0x1400
++//////////////////////////////////////////////////////////////////////
++// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)
++ENTRY(kvm_nested_dtlb_miss)
++ KVM_FAULT(5)
++END(kvm_nested_dtlb_miss)
++
++ .org kvm_ia64_ivt+0x1800
++/////////////////////////////////////////////////////////////////////
++// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)
++ENTRY(kvm_ikey_miss)
++ KVM_REFLECT(6)
++END(kvm_ikey_miss)
++
++ .org kvm_ia64_ivt+0x1c00
++/////////////////////////////////////////////////////////////////////
++// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
++ENTRY(kvm_dkey_miss)
++ KVM_REFLECT(7)
++END(kvm_dkey_miss)
++
++ .org kvm_ia64_ivt+0x2000
++////////////////////////////////////////////////////////////////////
++// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)
++ENTRY(kvm_dirty_bit)
++ KVM_REFLECT(8)
++END(kvm_dirty_bit)
++
++ .org kvm_ia64_ivt+0x2400
++////////////////////////////////////////////////////////////////////
++// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)
++ENTRY(kvm_iaccess_bit)
++ KVM_REFLECT(9)
++END(kvm_iaccess_bit)
++
++ .org kvm_ia64_ivt+0x2800
++///////////////////////////////////////////////////////////////////
++// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)
++ENTRY(kvm_daccess_bit)
++ KVM_REFLECT(10)
++END(kvm_daccess_bit)
++
++ .org kvm_ia64_ivt+0x2c00
++/////////////////////////////////////////////////////////////////
++// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)
++ENTRY(kvm_break_fault)
++ mov r31=pr
++ mov r19=11
++ mov r29=cr.ipsr
++ ;;
++ KVM_SAVE_MIN_WITH_COVER_R19
++ ;;
++ alloc r14=ar.pfs,0,0,4,0 // now it's safe (must be first in insn group!)
++ mov out0=cr.ifa
++ mov out2=cr.isr // FIXME: pity to make this slow access twice
++ mov out3=cr.iim // FIXME: pity to make this slow access twice
++ adds r3=8,r2 // set up second base pointer
++ ;;
++ ssm psr.ic
++ ;;
++ srlz.i // guarantee that interruption collection is on
++ ;;
++ //(p15)ssm psr.i // restore psr.i
++ addl r14=@gprel(ia64_leave_hypervisor),gp
++ ;;
++ KVM_SAVE_REST
++ mov rp=r14
++ ;;
++ adds out1=16,sp
++ br.call.sptk.many b6=kvm_ia64_handle_break
++ ;;
++END(kvm_break_fault)
++
++ .org kvm_ia64_ivt+0x3000
++/////////////////////////////////////////////////////////////////
++// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)
++ENTRY(kvm_interrupt)
++ mov r31=pr // prepare to save predicates
++ mov r19=12
++ mov r29=cr.ipsr
++ ;;
++ tbit.z p6,p7=r29,IA64_PSR_VM_BIT
++ tbit.z p0,p15=r29,IA64_PSR_I_BIT
++ ;;
++(p7) br.sptk kvm_dispatch_interrupt
++ ;;
++ mov r27=ar.rsc /* M */
++ mov r20=r1 /* A */
++ mov r25=ar.unat /* M */
++ mov r26=ar.pfs /* I */
++ mov r28=cr.iip /* M */
++ cover /* B (or nothing) */
++ ;;
++ mov r1=sp
++ ;;
++ invala /* M */
++ mov r30=cr.ifs
++ ;;
++ addl r1=-VMM_PT_REGS_SIZE,r1
++ ;;
++ adds r17=2*L1_CACHE_BYTES,r1 /* really: biggest cache-line size */
++ adds r16=PT(CR_IPSR),r1
++ ;;
++ lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES
++ st8 [r16]=r29 /* save cr.ipsr */
++ ;;
++ lfetch.fault.excl.nt1 [r17]
++ mov r29=b0
++ ;;
++ adds r16=PT(R8),r1 /* initialize first base pointer */
++ adds r17=PT(R9),r1 /* initialize second base pointer */
++ mov r18=r0 /* make sure r18 isn't NaT */
++ ;;
++.mem.offset 0,0; st8.spill [r16]=r8,16
++.mem.offset 8,0; st8.spill [r17]=r9,16
++ ;;
++.mem.offset 0,0; st8.spill [r16]=r10,24
++.mem.offset 8,0; st8.spill [r17]=r11,24
++ ;;
++ st8 [r16]=r28,16 /* save cr.iip */
++ st8 [r17]=r30,16 /* save cr.ifs */
++ mov r8=ar.fpsr /* M */
++ mov r9=ar.csd
++ mov r10=ar.ssd
++ movl r11=FPSR_DEFAULT /* L-unit */
++ ;;
++ st8 [r16]=r25,16 /* save ar.unat */
++ st8 [r17]=r26,16 /* save ar.pfs */
++ shl r18=r18,16 /* compute ar.rsc to be used for "loadrs" */
++ ;;
++ st8 [r16]=r27,16 /* save ar.rsc */
++ adds r17=16,r17 /* skip over ar_rnat field */
++ ;;
++ st8 [r17]=r31,16 /* save predicates */
++ adds r16=16,r16 /* skip over ar_bspstore field */
++ ;;
++ st8 [r16]=r29,16 /* save b0 */
++ st8 [r17]=r18,16 /* save ar.rsc value for "loadrs" */
++ ;;
++.mem.offset 0,0; st8.spill [r16]=r20,16 /* save original r1 */
++.mem.offset 8,0; st8.spill [r17]=r12,16
++ adds r12=-16,r1
++ /* switch to kernel memory stack (with 16 bytes of scratch) */
++ ;;
++.mem.offset 0,0; st8.spill [r16]=r13,16
++.mem.offset 8,0; st8.spill [r17]=r8,16 /* save ar.fpsr */
++ ;;
++.mem.offset 0,0; st8.spill [r16]=r15,16
++.mem.offset 8,0; st8.spill [r17]=r14,16
++ dep r14=-1,r0,60,4
++ ;;
++.mem.offset 0,0; st8.spill [r16]=r2,16
++.mem.offset 8,0; st8.spill [r17]=r3,16
++ adds r2=VMM_PT_REGS_R16_OFFSET,r1
++ adds r14 = VMM_VCPU_GP_OFFSET,r13
++ ;;
++ mov r8=ar.ccv
++ ld8 r14 = [r14]
++ ;;
++ mov r1=r14 /* establish kernel global pointer */
++ ;; \
++ bsw.1
++ ;;
++ alloc r14=ar.pfs,0,0,1,0 // must be first in an insn group
++ mov out0=r13
++ ;;
++ ssm psr.ic
++ ;;
++ srlz.i
++ ;;
++ //(p15) ssm psr.i
++ adds r3=8,r2 // set up second base pointer for SAVE_REST
++ srlz.i // ensure everybody knows psr.ic is back on
++ ;;
++.mem.offset 0,0; st8.spill [r2]=r16,16
++.mem.offset 8,0; st8.spill [r3]=r17,16
++ ;;
++.mem.offset 0,0; st8.spill [r2]=r18,16
++.mem.offset 8,0; st8.spill [r3]=r19,16
++ ;;
++.mem.offset 0,0; st8.spill [r2]=r20,16
++.mem.offset 8,0; st8.spill [r3]=r21,16
++ mov r18=b6
++ ;;
++.mem.offset 0,0; st8.spill [r2]=r22,16
++.mem.offset 8,0; st8.spill [r3]=r23,16
++ mov r19=b7
++ ;;
++.mem.offset 0,0; st8.spill [r2]=r24,16
++.mem.offset 8,0; st8.spill [r3]=r25,16
++ ;;
++.mem.offset 0,0; st8.spill [r2]=r26,16
++.mem.offset 8,0; st8.spill [r3]=r27,16
++ ;;
++.mem.offset 0,0; st8.spill [r2]=r28,16
++.mem.offset 8,0; st8.spill [r3]=r29,16
++ ;;
++.mem.offset 0,0; st8.spill [r2]=r30,16
++.mem.offset 8,0; st8.spill [r3]=r31,32
++ ;;
++ mov ar.fpsr=r11 /* M-unit */
++ st8 [r2]=r8,8 /* ar.ccv */
++ adds r24=PT(B6)-PT(F7),r3
++ ;;
++ stf.spill [r2]=f6,32
++ stf.spill [r3]=f7,32
++ ;;
++ stf.spill [r2]=f8,32
++ stf.spill [r3]=f9,32
++ ;;
++ stf.spill [r2]=f10
++ stf.spill [r3]=f11
++ adds r25=PT(B7)-PT(F11),r3
++ ;;
++ st8 [r24]=r18,16 /* b6 */
++ st8 [r25]=r19,16 /* b7 */
++ ;;
++ st8 [r24]=r9 /* ar.csd */
++ st8 [r25]=r10 /* ar.ssd */
++ ;;
++ srlz.d // make sure we see the effect of cr.ivr
++ addl r14=@gprel(ia64_leave_nested),gp
++ ;;
++ mov rp=r14
++ br.call.sptk.many b6=kvm_ia64_handle_irq
++ ;;
++END(kvm_interrupt)
++
++ .global kvm_dispatch_vexirq
++ .org kvm_ia64_ivt+0x3400
++//////////////////////////////////////////////////////////////////////
++// 0x3400 Entry 13 (size 64 bundles) Reserved
++ENTRY(kvm_virtual_exirq)
++ mov r31=pr
++ mov r19=13
++ mov r30 =r0
++ ;;
++kvm_dispatch_vexirq:
++ cmp.eq p6,p0 = 1,r30
++ ;;
++(p6)add r29 = VMM_VCPU_SAVED_GP_OFFSET,r21
++ ;;
++(p6)ld8 r1 = [r29]
++ ;;
++ KVM_SAVE_MIN_WITH_COVER_R19
++ alloc r14=ar.pfs,0,0,1,0
++ mov out0=r13
++
++ ssm psr.ic
++ ;;
++ srlz.i // guarantee that interruption collection is on
++ ;;
++ //(p15) ssm psr.i // restore psr.i
++ adds r3=8,r2 // set up second base pointer
++ ;;
++ KVM_SAVE_REST
++ addl r14=@gprel(ia64_leave_hypervisor),gp
++ ;;
++ mov rp=r14
++ br.call.sptk.many b6=kvm_vexirq
++END(kvm_virtual_exirq)
++
++ .org kvm_ia64_ivt+0x3800
++/////////////////////////////////////////////////////////////////////
++// 0x3800 Entry 14 (size 64 bundles) Reserved
++ KVM_FAULT(14)
++ // this code segment is from 2.6.16.13
++
++
++ .org kvm_ia64_ivt+0x3c00
++///////////////////////////////////////////////////////////////////////
++// 0x3c00 Entry 15 (size 64 bundles) Reserved
++ KVM_FAULT(15)
++
++
++ .org kvm_ia64_ivt+0x4000
++///////////////////////////////////////////////////////////////////////
++// 0x4000 Entry 16 (size 64 bundles) Reserved
++ KVM_FAULT(16)
++
++ .org kvm_ia64_ivt+0x4400
++//////////////////////////////////////////////////////////////////////
++// 0x4400 Entry 17 (size 64 bundles) Reserved
++ KVM_FAULT(17)
++
++ .org kvm_ia64_ivt+0x4800
++//////////////////////////////////////////////////////////////////////
++// 0x4800 Entry 18 (size 64 bundles) Reserved
++ KVM_FAULT(18)
++
++ .org kvm_ia64_ivt+0x4c00
++//////////////////////////////////////////////////////////////////////
++// 0x4c00 Entry 19 (size 64 bundles) Reserved
++ KVM_FAULT(19)
++
++ .org kvm_ia64_ivt+0x5000
++//////////////////////////////////////////////////////////////////////
++// 0x5000 Entry 20 (size 16 bundles) Page Not Present
++ENTRY(kvm_page_not_present)
++ KVM_REFLECT(20)
++END(kvm_page_not_present)
++
++ .org kvm_ia64_ivt+0x5100
++///////////////////////////////////////////////////////////////////////
++// 0x5100 Entry 21 (size 16 bundles) Key Permission vector
++ENTRY(kvm_key_permission)
++ KVM_REFLECT(21)
++END(kvm_key_permission)
++
++ .org kvm_ia64_ivt+0x5200
++//////////////////////////////////////////////////////////////////////
++// 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26)
++ENTRY(kvm_iaccess_rights)
++ KVM_REFLECT(22)
++END(kvm_iaccess_rights)
++
++ .org kvm_ia64_ivt+0x5300
++//////////////////////////////////////////////////////////////////////
++// 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53)
++ENTRY(kvm_daccess_rights)
++ KVM_REFLECT(23)
++END(kvm_daccess_rights)
++
++ .org kvm_ia64_ivt+0x5400
++/////////////////////////////////////////////////////////////////////
++// 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39)
++ENTRY(kvm_general_exception)
++ KVM_REFLECT(24)
++ KVM_FAULT(24)
++END(kvm_general_exception)
++
++ .org kvm_ia64_ivt+0x5500
++//////////////////////////////////////////////////////////////////////
++// 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35)
++ENTRY(kvm_disabled_fp_reg)
++ KVM_REFLECT(25)
++END(kvm_disabled_fp_reg)
++
++ .org kvm_ia64_ivt+0x5600
++////////////////////////////////////////////////////////////////////
++// 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50)
++ENTRY(kvm_nat_consumption)
++ KVM_REFLECT(26)
++END(kvm_nat_consumption)
++
++ .org kvm_ia64_ivt+0x5700
++/////////////////////////////////////////////////////////////////////
++// 0x5700 Entry 27 (size 16 bundles) Speculation (40)
++ENTRY(kvm_speculation_vector)
++ KVM_REFLECT(27)
++END(kvm_speculation_vector)
++
++ .org kvm_ia64_ivt+0x5800
++/////////////////////////////////////////////////////////////////////
++// 0x5800 Entry 28 (size 16 bundles) Reserved
++ KVM_FAULT(28)
++
++ .org kvm_ia64_ivt+0x5900
++///////////////////////////////////////////////////////////////////
++// 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56)
++ENTRY(kvm_debug_vector)
++ KVM_FAULT(29)
++END(kvm_debug_vector)
++
++ .org kvm_ia64_ivt+0x5a00
++///////////////////////////////////////////////////////////////
++// 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57)
++ENTRY(kvm_unaligned_access)
++ KVM_REFLECT(30)
++END(kvm_unaligned_access)
++
++ .org kvm_ia64_ivt+0x5b00
++//////////////////////////////////////////////////////////////////////
++// 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57)
++ENTRY(kvm_unsupported_data_reference)
++ KVM_REFLECT(31)
++END(kvm_unsupported_data_reference)
++
++ .org kvm_ia64_ivt+0x5c00
++////////////////////////////////////////////////////////////////////
++// 0x5c00 Entry 32 (size 16 bundles) Floating Point FAULT (65)
++ENTRY(kvm_floating_point_fault)
++ KVM_REFLECT(32)
++END(kvm_floating_point_fault)
++
++ .org kvm_ia64_ivt+0x5d00
++/////////////////////////////////////////////////////////////////////
++// 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66)
++ENTRY(kvm_floating_point_trap)
++ KVM_REFLECT(33)
++END(kvm_floating_point_trap)
++
++ .org kvm_ia64_ivt+0x5e00
++//////////////////////////////////////////////////////////////////////
++// 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66)
++ENTRY(kvm_lower_privilege_trap)
++ KVM_REFLECT(34)
++END(kvm_lower_privilege_trap)
++
++ .org kvm_ia64_ivt+0x5f00
++//////////////////////////////////////////////////////////////////////
++// 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68)
++ENTRY(kvm_taken_branch_trap)
++ KVM_REFLECT(35)
++END(kvm_taken_branch_trap)
++
++ .org kvm_ia64_ivt+0x6000
++////////////////////////////////////////////////////////////////////
++// 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69)
++ENTRY(kvm_single_step_trap)
++ KVM_REFLECT(36)
++END(kvm_single_step_trap)
++ .global kvm_virtualization_fault_back
++ .org kvm_ia64_ivt+0x6100
++/////////////////////////////////////////////////////////////////////
++// 0x6100 Entry 37 (size 16 bundles) Virtualization Fault
++ENTRY(kvm_virtualization_fault)
++ mov r31=pr
++ adds r16 = VMM_VCPU_SAVED_GP_OFFSET,r21
++ ;;
++ st8 [r16] = r1
++ adds r17 = VMM_VCPU_GP_OFFSET, r21
++ ;;
++ ld8 r1 = [r17]
++ cmp.eq p6,p0=EVENT_MOV_FROM_AR,r24
++ cmp.eq p7,p0=EVENT_MOV_FROM_RR,r24
++ cmp.eq p8,p0=EVENT_MOV_TO_RR,r24
++ cmp.eq p9,p0=EVENT_RSM,r24
++ cmp.eq p10,p0=EVENT_SSM,r24
++ cmp.eq p11,p0=EVENT_MOV_TO_PSR,r24
++ cmp.eq p12,p0=EVENT_THASH,r24
++ (p6) br.dptk.many kvm_asm_mov_from_ar
++ (p7) br.dptk.many kvm_asm_mov_from_rr
++ (p8) br.dptk.many kvm_asm_mov_to_rr
++ (p9) br.dptk.many kvm_asm_rsm
++ (p10) br.dptk.many kvm_asm_ssm
++ (p11) br.dptk.many kvm_asm_mov_to_psr
++ (p12) br.dptk.many kvm_asm_thash
++ ;;
++kvm_virtualization_fault_back:
++ adds r16 = VMM_VCPU_SAVED_GP_OFFSET,r21
++ ;;
++ ld8 r1 = [r16]
++ ;;
++ mov r19=37
++ adds r16 = VMM_VCPU_CAUSE_OFFSET,r21
++ adds r17 = VMM_VCPU_OPCODE_OFFSET,r21
++ ;;
++ st8 [r16] = r24
++ st8 [r17] = r25
++ ;;
++ cmp.ne p6,p0=EVENT_RFI, r24
++ (p6) br.sptk kvm_dispatch_virtualization_fault
++ ;;
++ adds r18=VMM_VPD_BASE_OFFSET,r21
++ ;;
++ ld8 r18=[r18]
++ ;;
++ adds r18=VMM_VPD_VIFS_OFFSET,r18
++ ;;
++ ld8 r18=[r18]
++ ;;
++ tbit.z p6,p0=r18,63
++ (p6) br.sptk kvm_dispatch_virtualization_fault
++ ;;
++ //if vifs.v=1 desert current register frame
++ alloc r18=ar.pfs,0,0,0,0
++ br.sptk kvm_dispatch_virtualization_fault
++END(kvm_virtualization_fault)
++
++ .org kvm_ia64_ivt+0x6200
++//////////////////////////////////////////////////////////////
++// 0x6200 Entry 38 (size 16 bundles) Reserved
++ KVM_FAULT(38)
++
++ .org kvm_ia64_ivt+0x6300
++/////////////////////////////////////////////////////////////////
++// 0x6300 Entry 39 (size 16 bundles) Reserved
++ KVM_FAULT(39)
++
++ .org kvm_ia64_ivt+0x6400
++/////////////////////////////////////////////////////////////////
++// 0x6400 Entry 40 (size 16 bundles) Reserved
++ KVM_FAULT(40)
++
++ .org kvm_ia64_ivt+0x6500
++//////////////////////////////////////////////////////////////////
++// 0x6500 Entry 41 (size 16 bundles) Reserved
++ KVM_FAULT(41)
++
++ .org kvm_ia64_ivt+0x6600
++//////////////////////////////////////////////////////////////////
++// 0x6600 Entry 42 (size 16 bundles) Reserved
++ KVM_FAULT(42)
++
++ .org kvm_ia64_ivt+0x6700
++//////////////////////////////////////////////////////////////////
++// 0x6700 Entry 43 (size 16 bundles) Reserved
++ KVM_FAULT(43)
++
++ .org kvm_ia64_ivt+0x6800
++//////////////////////////////////////////////////////////////////
++// 0x6800 Entry 44 (size 16 bundles) Reserved
++ KVM_FAULT(44)
++
++ .org kvm_ia64_ivt+0x6900
++///////////////////////////////////////////////////////////////////
++// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception
++//(17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77)
++ENTRY(kvm_ia32_exception)
++ KVM_FAULT(45)
++END(kvm_ia32_exception)
++
++ .org kvm_ia64_ivt+0x6a00
++////////////////////////////////////////////////////////////////////
++// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71)
++ENTRY(kvm_ia32_intercept)
++ KVM_FAULT(47)
++END(kvm_ia32_intercept)
++
++ .org kvm_ia64_ivt+0x6c00
++/////////////////////////////////////////////////////////////////////
++// 0x6c00 Entry 48 (size 16 bundles) Reserved
++ KVM_FAULT(48)
++
++ .org kvm_ia64_ivt+0x6d00
++//////////////////////////////////////////////////////////////////////
++// 0x6d00 Entry 49 (size 16 bundles) Reserved
++ KVM_FAULT(49)
++
++ .org kvm_ia64_ivt+0x6e00
++//////////////////////////////////////////////////////////////////////
++// 0x6e00 Entry 50 (size 16 bundles) Reserved
++ KVM_FAULT(50)
++
++ .org kvm_ia64_ivt+0x6f00
++/////////////////////////////////////////////////////////////////////
++// 0x6f00 Entry 51 (size 16 bundles) Reserved
++ KVM_FAULT(52)
++
++ .org kvm_ia64_ivt+0x7100
++////////////////////////////////////////////////////////////////////
++// 0x7100 Entry 53 (size 16 bundles) Reserved
++ KVM_FAULT(53)
++
++ .org kvm_ia64_ivt+0x7200
++/////////////////////////////////////////////////////////////////////
++// 0x7200 Entry 54 (size 16 bundles) Reserved
++ KVM_FAULT(54)
++
++ .org kvm_ia64_ivt+0x7300
++////////////////////////////////////////////////////////////////////
++// 0x7300 Entry 55 (size 16 bundles) Reserved
++ KVM_FAULT(55)
++
++ .org kvm_ia64_ivt+0x7400
++////////////////////////////////////////////////////////////////////
++// 0x7400 Entry 56 (size 16 bundles) Reserved
++ KVM_FAULT(56)
++
++ .org kvm_ia64_ivt+0x7500
++/////////////////////////////////////////////////////////////////////
++// 0x7500 Entry 57 (size 16 bundles) Reserved
++ KVM_FAULT(57)
++
++ .org kvm_ia64_ivt+0x7600
++/////////////////////////////////////////////////////////////////////
++// 0x7600 Entry 58 (size 16 bundles) Reserved
++ KVM_FAULT(58)
++
++ .org kvm_ia64_ivt+0x7700
++////////////////////////////////////////////////////////////////////
++// 0x7700 Entry 59 (size 16 bundles) Reserved
++ KVM_FAULT(59)
++
++ .org kvm_ia64_ivt+0x7800
++////////////////////////////////////////////////////////////////////
++// 0x7800 Entry 60 (size 16 bundles) Reserved
++ KVM_FAULT(60)
++
++ .org kvm_ia64_ivt+0x7900
++/////////////////////////////////////////////////////////////////////
++// 0x7900 Entry 61 (size 16 bundles) Reserved
++ KVM_FAULT(61)
++
++ .org kvm_ia64_ivt+0x7a00
++/////////////////////////////////////////////////////////////////////
++// 0x7a00 Entry 62 (size 16 bundles) Reserved
++ KVM_FAULT(62)
++
++ .org kvm_ia64_ivt+0x7b00
++/////////////////////////////////////////////////////////////////////
++// 0x7b00 Entry 63 (size 16 bundles) Reserved
++ KVM_FAULT(63)
++
++ .org kvm_ia64_ivt+0x7c00
++////////////////////////////////////////////////////////////////////
++// 0x7c00 Entry 64 (size 16 bundles) Reserved
++ KVM_FAULT(64)
++
++ .org kvm_ia64_ivt+0x7d00
++/////////////////////////////////////////////////////////////////////
++// 0x7d00 Entry 65 (size 16 bundles) Reserved
++ KVM_FAULT(65)
++
++ .org kvm_ia64_ivt+0x7e00
++/////////////////////////////////////////////////////////////////////
++// 0x7e00 Entry 66 (size 16 bundles) Reserved
++ KVM_FAULT(66)
++
++ .org kvm_ia64_ivt+0x7f00
++////////////////////////////////////////////////////////////////////
++// 0x7f00 Entry 67 (size 16 bundles) Reserved
++ KVM_FAULT(67)
++
++ .org kvm_ia64_ivt+0x8000
++// There is no particular reason for this code to be here, other than that
++// there happens to be space here that would go unused otherwise. If this
++// fault ever gets "unreserved", simply moved the following code to a more
++// suitable spot...
++
++
++ENTRY(kvm_dtlb_miss_dispatch)
++ mov r19 = 2
++ KVM_SAVE_MIN_WITH_COVER_R19
++ alloc r14=ar.pfs,0,0,3,0
++ mov out0=cr.ifa
++ mov out1=r15
++ adds r3=8,r2 // set up second base pointer
++ ;;
++ ssm psr.ic
++ ;;
++ srlz.i // guarantee that interruption collection is on
++ ;;
++ //(p15) ssm psr.i // restore psr.i
++ addl r14=@gprel(ia64_leave_hypervisor_prepare),gp
++ ;;
++ KVM_SAVE_REST
++ KVM_SAVE_EXTRA
++ mov rp=r14
++ ;;
++ adds out2=16,r12
++ br.call.sptk.many b6=kvm_page_fault
++END(kvm_dtlb_miss_dispatch)
++
++ENTRY(kvm_itlb_miss_dispatch)
++
++ KVM_SAVE_MIN_WITH_COVER_R19
++ alloc r14=ar.pfs,0,0,3,0
++ mov out0=cr.ifa
++ mov out1=r15
++ adds r3=8,r2 // set up second base pointer
++ ;;
++ ssm psr.ic
++ ;;
++ srlz.i // guarantee that interruption collection is on
++ ;;
++ //(p15) ssm psr.i // restore psr.i
++ addl r14=@gprel(ia64_leave_hypervisor),gp
++ ;;
++ KVM_SAVE_REST
++ mov rp=r14
++ ;;
++ adds out2=16,r12
++ br.call.sptk.many b6=kvm_page_fault
++END(kvm_itlb_miss_dispatch)
++
++ENTRY(kvm_dispatch_reflection)
++ /*
++ * Input:
++ * psr.ic: off
++ * r19: intr type (offset into ivt, see ia64_int.h)
++ * r31: contains saved predicates (pr)
++ */
++ KVM_SAVE_MIN_WITH_COVER_R19
++ alloc r14=ar.pfs,0,0,5,0
++ mov out0=cr.ifa
++ mov out1=cr.isr
++ mov out2=cr.iim
++ mov out3=r15
++ adds r3=8,r2 // set up second base pointer
++ ;;
++ ssm psr.ic
++ ;;
++ srlz.i // guarantee that interruption collection is on
++ ;;
++ //(p15) ssm psr.i // restore psr.i
++ addl r14=@gprel(ia64_leave_hypervisor),gp
++ ;;
++ KVM_SAVE_REST
++ mov rp=r14
++ ;;
++ adds out4=16,r12
++ br.call.sptk.many b6=reflect_interruption
++END(kvm_dispatch_reflection)
++
++ENTRY(kvm_dispatch_virtualization_fault)
++ adds r16 = VMM_VCPU_CAUSE_OFFSET,r21
++ adds r17 = VMM_VCPU_OPCODE_OFFSET,r21
++ ;;
++ st8 [r16] = r24
++ st8 [r17] = r25
++ ;;
++ KVM_SAVE_MIN_WITH_COVER_R19
++ ;;
++ alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!)
++ mov out0=r13 //vcpu
++ adds r3=8,r2 // set up second base pointer
++ ;;
++ ssm psr.ic
++ ;;
++ srlz.i // guarantee that interruption collection is on
++ ;;
++ //(p15) ssm psr.i // restore psr.i
++ addl r14=@gprel(ia64_leave_hypervisor_prepare),gp
++ ;;
++ KVM_SAVE_REST
++ KVM_SAVE_EXTRA
++ mov rp=r14
++ ;;
++ adds out1=16,sp //regs
++ br.call.sptk.many b6=kvm_emulate
++END(kvm_dispatch_virtualization_fault)
++
++
++ENTRY(kvm_dispatch_interrupt)
++ KVM_SAVE_MIN_WITH_COVER_R19 // uses r31; defines r2 and r3
++ ;;
++ alloc r14=ar.pfs,0,0,1,0 // must be first in an insn group
++ //mov out0=cr.ivr // pass cr.ivr as first arg
++ adds r3=8,r2 // set up second base pointer for SAVE_REST
++ ;;
++ ssm psr.ic
++ ;;
++ srlz.i
++ ;;
++ //(p15) ssm psr.i
++ addl r14=@gprel(ia64_leave_hypervisor),gp
++ ;;
++ KVM_SAVE_REST
++ mov rp=r14
++ ;;
++ mov out0=r13 // pass pointer to pt_regs as second arg
++ br.call.sptk.many b6=kvm_ia64_handle_irq
++END(kvm_dispatch_interrupt)
++
++
++
++
++GLOBAL_ENTRY(ia64_leave_nested)
++ rsm psr.i
++ ;;
++ adds r21=PT(PR)+16,r12
++ ;;
++ lfetch [r21],PT(CR_IPSR)-PT(PR)
++ adds r2=PT(B6)+16,r12
++ adds r3=PT(R16)+16,r12
++ ;;
++ lfetch [r21]
++ ld8 r28=[r2],8 // load b6
++ adds r29=PT(R24)+16,r12
++
++ ld8.fill r16=[r3]
++ adds r3=PT(AR_CSD)-PT(R16),r3
++ adds r30=PT(AR_CCV)+16,r12
++ ;;
++ ld8.fill r24=[r29]
++ ld8 r15=[r30] // load ar.ccv
++ ;;
++ ld8 r29=[r2],16 // load b7
++ ld8 r30=[r3],16 // load ar.csd
++ ;;
++ ld8 r31=[r2],16 // load ar.ssd
++ ld8.fill r8=[r3],16
++ ;;
++ ld8.fill r9=[r2],16
++ ld8.fill r10=[r3],PT(R17)-PT(R10)
++ ;;
++ ld8.fill r11=[r2],PT(R18)-PT(R11)
++ ld8.fill r17=[r3],16
++ ;;
++ ld8.fill r18=[r2],16
++ ld8.fill r19=[r3],16
++ ;;
++ ld8.fill r20=[r2],16
++ ld8.fill r21=[r3],16
++ mov ar.csd=r30
++ mov ar.ssd=r31
++ ;;
++ rsm psr.i | psr.ic
++ // initiate turning off of interrupt and interruption collection
++ invala // invalidate ALAT
++ ;;
++ srlz.i
++ ;;
++ ld8.fill r22=[r2],24
++ ld8.fill r23=[r3],24
++ mov b6=r28
++ ;;
++ ld8.fill r25=[r2],16
++ ld8.fill r26=[r3],16
++ mov b7=r29
++ ;;
++ ld8.fill r27=[r2],16
++ ld8.fill r28=[r3],16
++ ;;
++ ld8.fill r29=[r2],16
++ ld8.fill r30=[r3],24
++ ;;
++ ld8.fill r31=[r2],PT(F9)-PT(R31)
++ adds r3=PT(F10)-PT(F6),r3
++ ;;
++ ldf.fill f9=[r2],PT(F6)-PT(F9)
++ ldf.fill f10=[r3],PT(F8)-PT(F10)
++ ;;
++ ldf.fill f6=[r2],PT(F7)-PT(F6)
++ ;;
++ ldf.fill f7=[r2],PT(F11)-PT(F7)
++ ldf.fill f8=[r3],32
++ ;;
++ srlz.i // ensure interruption collection is off
++ mov ar.ccv=r15
++ ;;
++ bsw.0 // switch back to bank 0 (no stop bit required beforehand...)
++ ;;
++ ldf.fill f11=[r2]
++// mov r18=r13
++// mov r21=r13
++ adds r16=PT(CR_IPSR)+16,r12
++ adds r17=PT(CR_IIP)+16,r12
++ ;;
++ ld8 r29=[r16],16 // load cr.ipsr
++ ld8 r28=[r17],16 // load cr.iip
++ ;;
++ ld8 r30=[r16],16 // load cr.ifs
++ ld8 r25=[r17],16 // load ar.unat
++ ;;
++ ld8 r26=[r16],16 // load ar.pfs
++ ld8 r27=[r17],16 // load ar.rsc
++ cmp.eq p9,p0=r0,r0
++ // set p9 to indicate that we should restore cr.ifs
++ ;;
++ ld8 r24=[r16],16 // load ar.rnat (may be garbage)
++ ld8 r23=[r17],16// load ar.bspstore (may be garbage)
++ ;;
++ ld8 r31=[r16],16 // load predicates
++ ld8 r22=[r17],16 // load b0
++ ;;
++ ld8 r19=[r16],16 // load ar.rsc value for "loadrs"
++ ld8.fill r1=[r17],16 // load r1
++ ;;
++ ld8.fill r12=[r16],16
++ ld8.fill r13=[r17],16
++ ;;
++ ld8 r20=[r16],16 // ar.fpsr
++ ld8.fill r15=[r17],16
++ ;;
++ ld8.fill r14=[r16],16
++ ld8.fill r2=[r17]
++ ;;
++ ld8.fill r3=[r16]
++ ;;
++ mov r16=ar.bsp // get existing backing store pointer
++ ;;
++ mov b0=r22
++ mov ar.pfs=r26
++ mov cr.ifs=r30
++ mov cr.ipsr=r29
++ mov ar.fpsr=r20
++ mov cr.iip=r28
++ ;;
++ mov ar.rsc=r27
++ mov ar.unat=r25
++ mov pr=r31,-1
++ rfi
++END(ia64_leave_nested)
++
++
++
++GLOBAL_ENTRY(ia64_leave_hypervisor_prepare)
++ /*
++ * work.need_resched etc. mustn't get changed
++ *by this CPU before it returns to
++ ;;
++ * user- or fsys-mode, hence we disable interrupts early on:
++ */
++ adds r2 = PT(R4)+16,r12
++ adds r3 = PT(R5)+16,r12
++ adds r8 = PT(EML_UNAT)+16,r12
++ ;;
++ ld8 r8 = [r8]
++ ;;
++ mov ar.unat=r8
++ ;;
++ ld8.fill r4=[r2],16 //load r4
++ ld8.fill r5=[r3],16 //load r5
++ ;;
++ ld8.fill r6=[r2] //load r6
++ ld8.fill r7=[r3] //load r7
++ ;;
++END(ia64_leave_hypervisor_prepare)
++//fall through
++GLOBAL_ENTRY(ia64_leave_hypervisor)
++ rsm psr.i
++ ;;
++ br.call.sptk.many b0=leave_hypervisor_tail
++ ;;
++ adds r20=PT(PR)+16,r12
++ adds r8=PT(EML_UNAT)+16,r12
++ ;;
++ ld8 r8=[r8]
++ ;;
++ mov ar.unat=r8
++ ;;
++ lfetch [r20],PT(CR_IPSR)-PT(PR)
++ adds r2 = PT(B6)+16,r12
++ adds r3 = PT(B7)+16,r12
++ ;;
++ lfetch [r20]
++ ;;
++ ld8 r24=[r2],16 /* B6 */
++ ld8 r25=[r3],16 /* B7 */
++ ;;
++ ld8 r26=[r2],16 /* ar_csd */
++ ld8 r27=[r3],16 /* ar_ssd */
++ mov b6 = r24
++ ;;
++ ld8.fill r8=[r2],16
++ ld8.fill r9=[r3],16
++ mov b7 = r25
++ ;;
++ mov ar.csd = r26
++ mov ar.ssd = r27
++ ;;
++ ld8.fill r10=[r2],PT(R15)-PT(R10)
++ ld8.fill r11=[r3],PT(R14)-PT(R11)
++ ;;
++ ld8.fill r15=[r2],PT(R16)-PT(R15)
++ ld8.fill r14=[r3],PT(R17)-PT(R14)
++ ;;
++ ld8.fill r16=[r2],16
++ ld8.fill r17=[r3],16
++ ;;
++ ld8.fill r18=[r2],16
++ ld8.fill r19=[r3],16
++ ;;
++ ld8.fill r20=[r2],16
++ ld8.fill r21=[r3],16
++ ;;
++ ld8.fill r22=[r2],16
++ ld8.fill r23=[r3],16
++ ;;
++ ld8.fill r24=[r2],16
++ ld8.fill r25=[r3],16
++ ;;
++ ld8.fill r26=[r2],16
++ ld8.fill r27=[r3],16
++ ;;
++ ld8.fill r28=[r2],16
++ ld8.fill r29=[r3],16
++ ;;
++ ld8.fill r30=[r2],PT(F6)-PT(R30)
++ ld8.fill r31=[r3],PT(F7)-PT(R31)
++ ;;
++ rsm psr.i | psr.ic
++ // initiate turning off of interrupt and interruption collection
++ invala // invalidate ALAT
++ ;;
++ srlz.i // ensure interruption collection is off
++ ;;
++ bsw.0
++ ;;
++ adds r16 = PT(CR_IPSR)+16,r12
++ adds r17 = PT(CR_IIP)+16,r12
++ mov r21=r13 // get current
++ ;;
++ ld8 r31=[r16],16 // load cr.ipsr
++ ld8 r30=[r17],16 // load cr.iip
++ ;;
++ ld8 r29=[r16],16 // load cr.ifs
++ ld8 r28=[r17],16 // load ar.unat
++ ;;
++ ld8 r27=[r16],16 // load ar.pfs
++ ld8 r26=[r17],16 // load ar.rsc
++ ;;
++ ld8 r25=[r16],16 // load ar.rnat
++ ld8 r24=[r17],16 // load ar.bspstore
++ ;;
++ ld8 r23=[r16],16 // load predicates
++ ld8 r22=[r17],16 // load b0
++ ;;
++ ld8 r20=[r16],16 // load ar.rsc value for "loadrs"
++ ld8.fill r1=[r17],16 //load r1
++ ;;
++ ld8.fill r12=[r16],16 //load r12
++ ld8.fill r13=[r17],PT(R2)-PT(R13) //load r13
++ ;;
++ ld8 r19=[r16],PT(R3)-PT(AR_FPSR) //load ar_fpsr
++ ld8.fill r2=[r17],PT(AR_CCV)-PT(R2) //load r2
++ ;;
++ ld8.fill r3=[r16] //load r3
++ ld8 r18=[r17] //load ar_ccv
++ ;;
++ mov ar.fpsr=r19
++ mov ar.ccv=r18
++ shr.u r18=r20,16
++ ;;
++kvm_rbs_switch:
++ mov r19=96
++
++kvm_dont_preserve_current_frame:
++/*
++ * To prevent leaking bits between the hypervisor and guest domain,
++ * we must clear the stacked registers in the "invalid" partition here.
++ * 5 registers/cycle on McKinley).
++ */
++# define pRecurse p6
++# define pReturn p7
++# define Nregs 14
++
++ alloc loc0=ar.pfs,2,Nregs-2,2,0
++ shr.u loc1=r18,9 // RNaTslots <= floor(dirtySize / (64*8))
++ sub r19=r19,r18 // r19 = (physStackedSize + 8) - dirtySize
++ ;;
++ mov ar.rsc=r20 // load ar.rsc to be used for "loadrs"
++ shladd in0=loc1,3,r19
++ mov in1=0
++ ;;
++ TEXT_ALIGN(32)
++kvm_rse_clear_invalid:
++ alloc loc0=ar.pfs,2,Nregs-2,2,0
++ cmp.lt pRecurse,p0=Nregs*8,in0
++ // if more than Nregs regs left to clear, (re)curse
++ add out0=-Nregs*8,in0
++ add out1=1,in1 // increment recursion count
++ mov loc1=0
++ mov loc2=0
++ ;;
++ mov loc3=0
++ mov loc4=0
++ mov loc5=0
++ mov loc6=0
++ mov loc7=0
++(pRecurse) br.call.dptk.few b0=kvm_rse_clear_invalid
++ ;;
++ mov loc8=0
++ mov loc9=0
++ cmp.ne pReturn,p0=r0,in1
++ // if recursion count != 0, we need to do a br.ret
++ mov loc10=0
++ mov loc11=0
++(pReturn) br.ret.dptk.many b0
++
++# undef pRecurse
++# undef pReturn
++
++// loadrs has already been shifted
++ alloc r16=ar.pfs,0,0,0,0 // drop current register frame
++ ;;
++ loadrs
++ ;;
++ mov ar.bspstore=r24
++ ;;
++ mov ar.unat=r28
++ mov ar.rnat=r25
++ mov ar.rsc=r26
++ ;;
++ mov cr.ipsr=r31
++ mov cr.iip=r30
++ mov cr.ifs=r29
++ mov ar.pfs=r27
++ adds r18=VMM_VPD_BASE_OFFSET,r21
++ ;;
++ ld8 r18=[r18] //vpd
++ adds r17=VMM_VCPU_ISR_OFFSET,r21
++ ;;
++ ld8 r17=[r17]
++ adds r19=VMM_VPD_VPSR_OFFSET,r18
++ ;;
++ ld8 r19=[r19] //vpsr
++ adds r20=VMM_VCPU_VSA_BASE_OFFSET,r21
++ ;;
++ ld8 r20=[r20]
++ ;;
++//vsa_sync_write_start
++ mov r25=r18
++ adds r16= VMM_VCPU_GP_OFFSET,r21
++ ;;
++ ld8 r16= [r16] // Put gp in r24
++ movl r24=@gprel(ia64_vmm_entry) // calculate return address
++ ;;
++ add r24=r24,r16
++ ;;
++ add r16=PAL_VPS_SYNC_WRITE,r20
++ ;;
++ mov b0=r16
++ br.cond.sptk b0 // call the service
++ ;;
++END(ia64_leave_hypervisor)
++// fall through
++GLOBAL_ENTRY(ia64_vmm_entry)
++/*
++ * must be at bank 0
++ * parameter:
++ * r17:cr.isr
++ * r18:vpd
++ * r19:vpsr
++ * r20:__vsa_base
++ * r22:b0
++ * r23:predicate
++ */
++ mov r24=r22
++ mov r25=r18
++ tbit.nz p1,p2 = r19,IA64_PSR_IC_BIT // p1=vpsr.ic
++ ;;
++ (p1) add r29=PAL_VPS_RESUME_NORMAL,r20
++ (p1) br.sptk.many ia64_vmm_entry_out
++ ;;
++ tbit.nz p1,p2 = r17,IA64_ISR_IR_BIT //p1=cr.isr.ir
++ ;;
++ (p1) add r29=PAL_VPS_RESUME_NORMAL,r20
++ (p2) add r29=PAL_VPS_RESUME_HANDLER,r20
++ (p2) ld8 r26=[r25]
++ ;;
++ia64_vmm_entry_out:
++ mov pr=r23,-2
++ mov b0=r29
++ ;;
++ br.cond.sptk b0 // call pal service
++END(ia64_vmm_entry)
++
++
++
++/*
++ * extern u64 ia64_call_vsa(u64 proc, u64 arg1, u64 arg2,
++ * u64 arg3, u64 arg4, u64 arg5,
++ * u64 arg6, u64 arg7);
++ *
++ * XXX: The currently defined services use only 4 args at the max. The
++ * rest are not consumed.
++ */
++GLOBAL_ENTRY(ia64_call_vsa)
++ .regstk 4,4,0,0
++
++rpsave = loc0
++pfssave = loc1
++psrsave = loc2
++entry = loc3
++hostret = r24
++
++ alloc pfssave=ar.pfs,4,4,0,0
++ mov rpsave=rp
++ adds entry=VMM_VCPU_VSA_BASE_OFFSET, r13
++ ;;
++ ld8 entry=[entry]
++1: mov hostret=ip
++ mov r25=in1 // copy arguments
++ mov r26=in2
++ mov r27=in3
++ mov psrsave=psr
++ ;;
++ tbit.nz p6,p0=psrsave,14 // IA64_PSR_I
++ tbit.nz p7,p0=psrsave,13 // IA64_PSR_IC
++ ;;
++ add hostret=2f-1b,hostret // calculate return address
++ add entry=entry,in0
++ ;;
++ rsm psr.i | psr.ic
++ ;;
++ srlz.i
++ mov b6=entry
++ br.cond.sptk b6 // call the service
++2:
++ // Architectural sequence for enabling interrupts if necessary
++(p7) ssm psr.ic
++ ;;
++(p7) srlz.i
++ ;;
++//(p6) ssm psr.i
++ ;;
++ mov rp=rpsave
++ mov ar.pfs=pfssave
++ mov r8=r31
++ ;;
++ srlz.d
++ br.ret.sptk rp
++
++END(ia64_call_vsa)
++
++#define INIT_BSPSTORE ((4<<30)-(12<<20)-0x100)
++
++GLOBAL_ENTRY(vmm_reset_entry)
++ //set up ipsr, iip, vpd.vpsr, dcr
++ // For IPSR: it/dt/rt=1, i/ic=1, si=1, vm/bn=1
++ // For DCR: all bits 0
++ adds r14=-VMM_PT_REGS_SIZE, r12
++ ;;
++ movl r6=0x501008826000 // IPSR dt/rt/it:1;i/ic:1, si:1, vm/bn:1
++ movl r10=0x8000000000000000
++ adds r16=PT(CR_IIP), r14
++ adds r20=PT(R1), r14
++ ;;
++ rsm psr.ic | psr.i
++ ;;
++ srlz.i
++ ;;
++ bsw.0
++ ;;
++ mov r21 =r13
++ ;;
++ bsw.1
++ ;;
++ mov ar.rsc = 0
++ ;;
++ flushrs
++ ;;
++ mov ar.bspstore = 0
++ // clear BSPSTORE
++ ;;
++ mov cr.ipsr=r6
++ mov cr.ifs=r10
++ ld8 r4 = [r16] // Set init iip for first run.
++ ld8 r1 = [r20]
++ ;;
++ mov cr.iip=r4
++ ;;
++ adds r16=VMM_VPD_BASE_OFFSET,r13
++ adds r20=VMM_VCPU_VSA_BASE_OFFSET,r13
++ ;;
++ ld8 r18=[r16]
++ ld8 r20=[r20]
++ ;;
++ adds r19=VMM_VPD_VPSR_OFFSET,r18
++ ;;
++ ld8 r19=[r19]
++ mov r17=r0
++ mov r22=r0
++ mov r23=r0
++ br.cond.sptk ia64_vmm_entry
++ br.ret.sptk b0
++END(vmm_reset_entry)
+diff --git a/arch/ia64/kvm/vti.h b/arch/ia64/kvm/vti.h
+new file mode 100644
+index 0000000..f6c5617
+--- /dev/null
++++ b/arch/ia64/kvm/vti.h
+@@ -0,0 +1,290 @@
++/*
++ * vti.h: prototype for generial vt related interface
++ * Copyright (c) 2004, Intel Corporation.
++ *
++ * Xuefei Xu (Anthony Xu) (anthony.xu at intel.com)
++ * Fred Yang (fred.yang at intel.com)
++ * Kun Tian (Kevin Tian) (kevin.tian at intel.com)
++ *
++ * Copyright (c) 2007, Intel Corporation.
++ * Zhang xiantao <xiantao.zhang at intel.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You 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 _KVM_VT_I_H
++#define _KVM_VT_I_H
++
++#ifndef __ASSEMBLY__
++#include <asm/page.h>
++
++#include <linux/kvm_host.h>
++
++/* define itr.i and itr.d in ia64_itr function */
++#define ITR 0x01
++#define DTR 0x02
++#define IaDTR 0x03
++
++#define IA64_TR_VMM 6 /*itr6, dtr6 : maps vmm code, vmbuffer*/
++#define IA64_TR_VM_DATA 7 /*dtr7 : maps current vm data*/
++
++#define RR6 (6UL<<61)
++#define RR7 (7UL<<61)
++
++
++/* config_options in pal_vp_init_env */
++#define VP_INITIALIZE 1UL
++#define VP_FR_PMC 1UL<<1
++#define VP_OPCODE 1UL<<8
++#define VP_CAUSE 1UL<<9
++#define VP_FW_ACC 1UL<<63
++
++/* init vp env with initializing vm_buffer */
++#define VP_INIT_ENV_INITALIZE (VP_INITIALIZE | VP_FR_PMC |\
++ VP_OPCODE | VP_CAUSE | VP_FW_ACC)
++/* init vp env without initializing vm_buffer */
++#define VP_INIT_ENV VP_FR_PMC | VP_OPCODE | VP_CAUSE | VP_FW_ACC
++
++#define PAL_VP_CREATE 265
++/* Stacked Virt. Initializes a new VPD for the operation of
++ * a new virtual processor in the virtual environment.
++ */
++#define PAL_VP_ENV_INFO 266
++/*Stacked Virt. Returns the parameters needed to enter a virtual environment.*/
++#define PAL_VP_EXIT_ENV 267
++/*Stacked Virt. Allows a logical processor to exit a virtual environment.*/
++#define PAL_VP_INIT_ENV 268
++/*Stacked Virt. Allows a logical processor to enter a virtual environment.*/
++#define PAL_VP_REGISTER 269
++/*Stacked Virt. Register a different host IVT for the virtual processor.*/
++#define PAL_VP_RESUME 270
++/* Renamed from PAL_VP_RESUME */
++#define PAL_VP_RESTORE 270
++/*Stacked Virt. Resumes virtual processor operation on the logical processor.*/
++#define PAL_VP_SUSPEND 271
++/* Renamed from PAL_VP_SUSPEND */
++#define PAL_VP_SAVE 271
++/* Stacked Virt. Suspends operation for the specified virtual processor on
++ * the logical processor.
++ */
++#define PAL_VP_TERMINATE 272
++/* Stacked Virt. Terminates operation for the specified virtual processor.*/
++
++union vac {
++ unsigned long value;
++ struct {
++ int a_int:1;
++ int a_from_int_cr:1;
++ int a_to_int_cr:1;
++ int a_from_psr:1;
++ int a_from_cpuid:1;
++ int a_cover:1;
++ int a_bsw:1;
++ long reserved:57;
++ };
++};
++
++union vdc {
++ unsigned long value;
++ struct {
++ int d_vmsw:1;
++ int d_extint:1;
++ int d_ibr_dbr:1;
++ int d_pmc:1;
++ int d_to_pmd:1;
++ int d_itm:1;
++ long reserved:58;
++ };
++};
++
++struct vpd {
++ union vac vac;
++ union vdc vdc;
++ unsigned long virt_env_vaddr;
++ unsigned long reserved1[29];
++ unsigned long vhpi;
++ unsigned long reserved2[95];
++ unsigned long vgr[16];
++ unsigned long vbgr[16];
++ unsigned long vnat;
++ unsigned long vbnat;
++ unsigned long vcpuid[5];
++ unsigned long reserved3[11];
++ unsigned long vpsr;
++ unsigned long vpr;
++ unsigned long reserved4[76];
++ union {
++ unsigned long vcr[128];
++ struct {
++ unsigned long dcr;
++ unsigned long itm;
++ unsigned long iva;
++ unsigned long rsv1[5];
++ unsigned long pta;
++ unsigned long rsv2[7];
++ unsigned long ipsr;
++ unsigned long isr;
++ unsigned long rsv3;
++ unsigned long iip;
++ unsigned long ifa;
++ unsigned long itir;
++ unsigned long iipa;
++ unsigned long ifs;
++ unsigned long iim;
++ unsigned long iha;
++ unsigned long rsv4[38];
++ unsigned long lid;
++ unsigned long ivr;
++ unsigned long tpr;
++ unsigned long eoi;
++ unsigned long irr[4];
++ unsigned long itv;
++ unsigned long pmv;
++ unsigned long cmcv;
++ unsigned long rsv5[5];
++ unsigned long lrr0;
++ unsigned long lrr1;
++ unsigned long rsv6[46];
++ };
++ };
++ unsigned long reserved5[128];
++ unsigned long reserved6[3456];
++ unsigned long vmm_avail[128];
++ unsigned long reserved7[4096];
++};
++
++#define PAL_PROC_VM_BIT (1UL << 40)
++#define PAL_PROC_VMSW_BIT (1UL << 54)
++
++static inline s64 ia64_pal_vp_env_info(u64 *buffer_size,
++ u64 *vp_env_info)
++{
++ struct ia64_pal_retval iprv;
++ PAL_CALL_STK(iprv, PAL_VP_ENV_INFO, 0, 0, 0);
++ *buffer_size = iprv.v0;
++ *vp_env_info = iprv.v1;
++ return iprv.status;
++}
++
++static inline s64 ia64_pal_vp_exit_env(u64 iva)
++{
++ struct ia64_pal_retval iprv;
++
++ PAL_CALL_STK(iprv, PAL_VP_EXIT_ENV, (u64)iva, 0, 0);
++ return iprv.status;
++}
++
++static inline s64 ia64_pal_vp_init_env(u64 config_options, u64 pbase_addr,
++ u64 vbase_addr, u64 *vsa_base)
++{
++ struct ia64_pal_retval iprv;
++
++ PAL_CALL_STK(iprv, PAL_VP_INIT_ENV, config_options, pbase_addr,
++ vbase_addr);
++ *vsa_base = iprv.v0;
++
++ return iprv.status;
++}
++
++static inline s64 ia64_pal_vp_restore(u64 *vpd, u64 pal_proc_vector)
++{
++ struct ia64_pal_retval iprv;
++
++ PAL_CALL_STK(iprv, PAL_VP_RESTORE, (u64)vpd, pal_proc_vector, 0);
++
++ return iprv.status;
++}
++
++static inline s64 ia64_pal_vp_save(u64 *vpd, u64 pal_proc_vector)
++{
++ struct ia64_pal_retval iprv;
++
++ PAL_CALL_STK(iprv, PAL_VP_SAVE, (u64)vpd, pal_proc_vector, 0);
++
++ return iprv.status;
++}
++
++#endif
++
++/*VPD field offset*/
++#define VPD_VAC_START_OFFSET 0
++#define VPD_VDC_START_OFFSET 8
++#define VPD_VHPI_START_OFFSET 256
++#define VPD_VGR_START_OFFSET 1024
++#define VPD_VBGR_START_OFFSET 1152
++#define VPD_VNAT_START_OFFSET 1280
++#define VPD_VBNAT_START_OFFSET 1288
++#define VPD_VCPUID_START_OFFSET 1296
++#define VPD_VPSR_START_OFFSET 1424
++#define VPD_VPR_START_OFFSET 1432
++#define VPD_VRSE_CFLE_START_OFFSET 1440
++#define VPD_VCR_START_OFFSET 2048
++#define VPD_VTPR_START_OFFSET 2576
++#define VPD_VRR_START_OFFSET 3072
++#define VPD_VMM_VAIL_START_OFFSET 31744
++
++/*Virtualization faults*/
++
++#define EVENT_MOV_TO_AR 1
++#define EVENT_MOV_TO_AR_IMM 2
++#define EVENT_MOV_FROM_AR 3
++#define EVENT_MOV_TO_CR 4
++#define EVENT_MOV_FROM_CR 5
++#define EVENT_MOV_TO_PSR 6
++#define EVENT_MOV_FROM_PSR 7
++#define EVENT_ITC_D 8
++#define EVENT_ITC_I 9
++#define EVENT_MOV_TO_RR 10
++#define EVENT_MOV_TO_DBR 11
++#define EVENT_MOV_TO_IBR 12
++#define EVENT_MOV_TO_PKR 13
++#define EVENT_MOV_TO_PMC 14
++#define EVENT_MOV_TO_PMD 15
++#define EVENT_ITR_D 16
++#define EVENT_ITR_I 17
++#define EVENT_MOV_FROM_RR 18
++#define EVENT_MOV_FROM_DBR 19
++#define EVENT_MOV_FROM_IBR 20
++#define EVENT_MOV_FROM_PKR 21
++#define EVENT_MOV_FROM_PMC 22
++#define EVENT_MOV_FROM_CPUID 23
++#define EVENT_SSM 24
++#define EVENT_RSM 25
++#define EVENT_PTC_L 26
++#define EVENT_PTC_G 27
++#define EVENT_PTC_GA 28
++#define EVENT_PTR_D 29
++#define EVENT_PTR_I 30
++#define EVENT_THASH 31
++#define EVENT_TTAG 32
++#define EVENT_TPA 33
++#define EVENT_TAK 34
++#define EVENT_PTC_E 35
++#define EVENT_COVER 36
++#define EVENT_RFI 37
++#define EVENT_BSW_0 38
++#define EVENT_BSW_1 39
++#define EVENT_VMSW 40
++
++/**PAL virtual services offsets */
++#define PAL_VPS_RESUME_NORMAL 0x0000
++#define PAL_VPS_RESUME_HANDLER 0x0400
++#define PAL_VPS_SYNC_READ 0x0800
++#define PAL_VPS_SYNC_WRITE 0x0c00
++#define PAL_VPS_SET_PENDING_INTERRUPT 0x1000
++#define PAL_VPS_THASH 0x1400
++#define PAL_VPS_TTAG 0x1800
++#define PAL_VPS_RESTORE 0x1c00
++#define PAL_VPS_SAVE 0x2000
++
++#endif/* _VT_I_H*/
+diff --git a/arch/ia64/kvm/vtlb.c b/arch/ia64/kvm/vtlb.c
+new file mode 100644
+index 0000000..def4576
+--- /dev/null
++++ b/arch/ia64/kvm/vtlb.c
+@@ -0,0 +1,636 @@
++/*
++ * vtlb.c: guest virtual tlb handling module.
++ * Copyright (c) 2004, Intel Corporation.
++ * Yaozu Dong (Eddie Dong) <Eddie.dong at intel.com>
++ * Xuefei Xu (Anthony Xu) <anthony.xu at intel.com>
++ *
++ * Copyright (c) 2007, Intel Corporation.
++ * Xuefei Xu (Anthony Xu) <anthony.xu at intel.com>
++ * Xiantao Zhang <xiantao.zhang at intel.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You 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 "vcpu.h"
++
++#include <linux/rwsem.h>
++
++#include <asm/tlb.h>
++
++/*
++ * Check to see if the address rid:va is translated by the TLB
++ */
++
++static int __is_tr_translated(struct thash_data *trp, u64 rid, u64 va)
++{
++ return ((trp->p) && (trp->rid == rid)
++ && ((va-trp->vadr) < PSIZE(trp->ps)));
++}
++
++/*
++ * Only for GUEST TR format.
++ */
++static int __is_tr_overlap(struct thash_data *trp, u64 rid, u64 sva, u64 eva)
++{
++ u64 sa1, ea1;
++
++ if (!trp->p || trp->rid != rid)
++ return 0;
++
++ sa1 = trp->vadr;
++ ea1 = sa1 + PSIZE(trp->ps) - 1;
++ eva -= 1;
++ if ((sva > ea1) || (sa1 > eva))
++ return 0;
++ else
++ return 1;
++
++}
++
++void machine_tlb_purge(u64 va, u64 ps)
++{
++ ia64_ptcl(va, ps << 2);
++}
++
++void local_flush_tlb_all(void)
++{
++ int i, j;
++ unsigned long flags, count0, count1;
++ unsigned long stride0, stride1, addr;
++
++ addr = current_vcpu->arch.ptce_base;
++ count0 = current_vcpu->arch.ptce_count[0];
++ count1 = current_vcpu->arch.ptce_count[1];
++ stride0 = current_vcpu->arch.ptce_stride[0];
++ stride1 = current_vcpu->arch.ptce_stride[1];
++
++ local_irq_save(flags);
++ for (i = 0; i < count0; ++i) {
++ for (j = 0; j < count1; ++j) {
++ ia64_ptce(addr);
++ addr += stride1;
++ }
++ addr += stride0;
++ }
++ local_irq_restore(flags);
++ ia64_srlz_i(); /* srlz.i implies srlz.d */
++}
++
++int vhpt_enabled(struct kvm_vcpu *vcpu, u64 vadr, enum vhpt_ref ref)
++{
++ union ia64_rr vrr;
++ union ia64_pta vpta;
++ struct ia64_psr vpsr;
++
++ vpsr = *(struct ia64_psr *)&VCPU(vcpu, vpsr);
++ vrr.val = vcpu_get_rr(vcpu, vadr);
++ vpta.val = vcpu_get_pta(vcpu);
++
++ if (vrr.ve & vpta.ve) {
++ switch (ref) {
++ case DATA_REF:
++ case NA_REF:
++ return vpsr.dt;
++ case INST_REF:
++ return vpsr.dt && vpsr.it && vpsr.ic;
++ case RSE_REF:
++ return vpsr.dt && vpsr.rt;
++
++ }
++ }
++ return 0;
++}
++
++struct thash_data *vsa_thash(union ia64_pta vpta, u64 va, u64 vrr, u64 *tag)
++{
++ u64 index, pfn, rid, pfn_bits;
++
++ pfn_bits = vpta.size - 5 - 8;
++ pfn = REGION_OFFSET(va) >> _REGION_PAGE_SIZE(vrr);
++ rid = _REGION_ID(vrr);
++ index = ((rid & 0xff) << pfn_bits)|(pfn & ((1UL << pfn_bits) - 1));
++ *tag = ((rid >> 8) & 0xffff) | ((pfn >> pfn_bits) << 16);
++
++ return (struct thash_data *)((vpta.base << PTA_BASE_SHIFT) +
++ (index << 5));
++}
++
++struct thash_data *__vtr_lookup(struct kvm_vcpu *vcpu, u64 va, int type)
++{
++
++ struct thash_data *trp;
++ int i;
++ u64 rid;
++
++ rid = vcpu_get_rr(vcpu, va);
++ rid = rid & RR_RID_MASK;;
++ if (type == D_TLB) {
++ if (vcpu_quick_region_check(vcpu->arch.dtr_regions, va)) {
++ for (trp = (struct thash_data *)&vcpu->arch.dtrs, i = 0;
++ i < NDTRS; i++, trp++) {
++ if (__is_tr_translated(trp, rid, va))
++ return trp;
++ }
++ }
++ } else {
++ if (vcpu_quick_region_check(vcpu->arch.itr_regions, va)) {
++ for (trp = (struct thash_data *)&vcpu->arch.itrs, i = 0;
++ i < NITRS; i++, trp++) {
++ if (__is_tr_translated(trp, rid, va))
++ return trp;
++ }
++ }
++ }
++
++ return NULL;
++}
++
++static void vhpt_insert(u64 pte, u64 itir, u64 ifa, u64 gpte)
++{
++ union ia64_rr rr;
++ struct thash_data *head;
++ unsigned long ps, gpaddr;
++
++ ps = itir_ps(itir);
++
++ gpaddr = ((gpte & _PAGE_PPN_MASK) >> ps << ps) |
++ (ifa & ((1UL << ps) - 1));
++
++ rr.val = ia64_get_rr(ifa);
++ head = (struct thash_data *)ia64_thash(ifa);
++ head->etag = INVALID_TI_TAG;
++ ia64_mf();
++ head->page_flags = pte & ~PAGE_FLAGS_RV_MASK;
++ head->itir = rr.ps << 2;
++ head->etag = ia64_ttag(ifa);
++ head->gpaddr = gpaddr;
++}
++
++void mark_pages_dirty(struct kvm_vcpu *v, u64 pte, u64 ps)
++{
++ u64 i, dirty_pages = 1;
++ u64 base_gfn = (pte&_PAGE_PPN_MASK) >> PAGE_SHIFT;
++ spinlock_t *lock = __kvm_va(v->arch.dirty_log_lock_pa);
++ void *dirty_bitmap = (void *)v - (KVM_VCPU_OFS + v->vcpu_id * VCPU_SIZE)
++ + KVM_MEM_DIRTY_LOG_OFS;
++ dirty_pages <<= ps <= PAGE_SHIFT ? 0 : ps - PAGE_SHIFT;
++
++ vmm_spin_lock(lock);
++ for (i = 0; i < dirty_pages; i++) {
++ /* avoid RMW */
++ if (!test_bit(base_gfn + i, dirty_bitmap))
++ set_bit(base_gfn + i , dirty_bitmap);
++ }
++ vmm_spin_unlock(lock);
++}
++
++void thash_vhpt_insert(struct kvm_vcpu *v, u64 pte, u64 itir, u64 va, int type)
++{
++ u64 phy_pte, psr;
++ union ia64_rr mrr;
++
++ mrr.val = ia64_get_rr(va);
++ phy_pte = translate_phy_pte(&pte, itir, va);
++
++ if (itir_ps(itir) >= mrr.ps) {
++ vhpt_insert(phy_pte, itir, va, pte);
++ } else {
++ phy_pte &= ~PAGE_FLAGS_RV_MASK;
++ psr = ia64_clear_ic();
++ ia64_itc(type, va, phy_pte, itir_ps(itir));
++ ia64_set_psr(psr);
++ }
++
++ if (!(pte&VTLB_PTE_IO))
++ mark_pages_dirty(v, pte, itir_ps(itir));
++}
++
++/*
++ * vhpt lookup
++ */
++struct thash_data *vhpt_lookup(u64 va)
++{
++ struct thash_data *head;
++ u64 tag;
++
++ head = (struct thash_data *)ia64_thash(va);
++ tag = ia64_ttag(va);
++ if (head->etag == tag)
++ return head;
++ return NULL;
++}
++
++u64 guest_vhpt_lookup(u64 iha, u64 *pte)
++{
++ u64 ret;
++ struct thash_data *data;
++
++ data = __vtr_lookup(current_vcpu, iha, D_TLB);
++ if (data != NULL)
++ thash_vhpt_insert(current_vcpu, data->page_flags,
++ data->itir, iha, D_TLB);
++
++ asm volatile ("rsm psr.ic|psr.i;;"
++ "srlz.d;;"
++ "ld8.s r9=[%1];;"
++ "tnat.nz p6,p7=r9;;"
++ "(p6) mov %0=1;"
++ "(p6) mov r9=r0;"
++ "(p7) extr.u r9=r9,0,53;;"
++ "(p7) mov %0=r0;"
++ "(p7) st8 [%2]=r9;;"
++ "ssm psr.ic;;"
++ "srlz.d;;"
++ /* "ssm psr.i;;" Once interrupts in vmm open, need fix*/
++ : "=r"(ret) : "r"(iha), "r"(pte):"memory");
++
++ return ret;
++}
++
++/*
++ * purge software guest tlb
++ */
++
++static void vtlb_purge(struct kvm_vcpu *v, u64 va, u64 ps)
++{
++ struct thash_data *cur;
++ u64 start, curadr, size, psbits, tag, rr_ps, num;
++ union ia64_rr vrr;
++ struct thash_cb *hcb = &v->arch.vtlb;
++
++ vrr.val = vcpu_get_rr(v, va);
++ psbits = VMX(v, psbits[(va >> 61)]);
++ start = va & ~((1UL << ps) - 1);
++ while (psbits) {
++ curadr = start;
++ rr_ps = __ffs(psbits);
++ psbits &= ~(1UL << rr_ps);
++ num = 1UL << ((ps < rr_ps) ? 0 : (ps - rr_ps));
++ size = PSIZE(rr_ps);
++ vrr.ps = rr_ps;
++ while (num) {
++ cur = vsa_thash(hcb->pta, curadr, vrr.val, &tag);
++ if (cur->etag == tag && cur->ps == rr_ps)
++ cur->etag = INVALID_TI_TAG;
++ curadr += size;
++ num--;
++ }
++ }
++}
++
++
++/*
++ * purge VHPT and machine TLB
++ */
++static void vhpt_purge(struct kvm_vcpu *v, u64 va, u64 ps)
++{
++ struct thash_data *cur;
++ u64 start, size, tag, num;
++ union ia64_rr rr;
++
++ start = va & ~((1UL << ps) - 1);
++ rr.val = ia64_get_rr(va);
++ size = PSIZE(rr.ps);
++ num = 1UL << ((ps < rr.ps) ? 0 : (ps - rr.ps));
++ while (num) {
++ cur = (struct thash_data *)ia64_thash(start);
++ tag = ia64_ttag(start);
++ if (cur->etag == tag)
++ cur->etag = INVALID_TI_TAG;
++ start += size;
++ num--;
++ }
++ machine_tlb_purge(va, ps);
++}
++
++/*
++ * Insert an entry into hash TLB or VHPT.
++ * NOTES:
++ * 1: When inserting VHPT to thash, "va" is a must covered
++ * address by the inserted machine VHPT entry.
++ * 2: The format of entry is always in TLB.
++ * 3: The caller need to make sure the new entry will not overlap
++ * with any existed entry.
++ */
++void vtlb_insert(struct kvm_vcpu *v, u64 pte, u64 itir, u64 va)
++{
++ struct thash_data *head;
++ union ia64_rr vrr;
++ u64 tag;
++ struct thash_cb *hcb = &v->arch.vtlb;
++
++ vrr.val = vcpu_get_rr(v, va);
++ vrr.ps = itir_ps(itir);
++ VMX(v, psbits[va >> 61]) |= (1UL << vrr.ps);
++ head = vsa_thash(hcb->pta, va, vrr.val, &tag);
++ head->page_flags = pte;
++ head->itir = itir;
++ head->etag = tag;
++}
++
++int vtr_find_overlap(struct kvm_vcpu *vcpu, u64 va, u64 ps, int type)
++{
++ struct thash_data *trp;
++ int i;
++ u64 end, rid;
++
++ rid = vcpu_get_rr(vcpu, va);
++ rid = rid & RR_RID_MASK;
++ end = va + PSIZE(ps);
++ if (type == D_TLB) {
++ if (vcpu_quick_region_check(vcpu->arch.dtr_regions, va)) {
++ for (trp = (struct thash_data *)&vcpu->arch.dtrs, i = 0;
++ i < NDTRS; i++, trp++) {
++ if (__is_tr_overlap(trp, rid, va, end))
++ return i;
++ }
++ }
++ } else {
++ if (vcpu_quick_region_check(vcpu->arch.itr_regions, va)) {
++ for (trp = (struct thash_data *)&vcpu->arch.itrs, i = 0;
++ i < NITRS; i++, trp++) {
++ if (__is_tr_overlap(trp, rid, va, end))
++ return i;
++ }
++ }
++ }
++ return -1;
++}
++
++/*
++ * Purge entries in VTLB and VHPT
++ */
++void thash_purge_entries(struct kvm_vcpu *v, u64 va, u64 ps)
++{
++ if (vcpu_quick_region_check(v->arch.tc_regions, va))
++ vtlb_purge(v, va, ps);
++ vhpt_purge(v, va, ps);
++}
++
++void thash_purge_entries_remote(struct kvm_vcpu *v, u64 va, u64 ps)
++{
++ u64 old_va = va;
++ va = REGION_OFFSET(va);
++ if (vcpu_quick_region_check(v->arch.tc_regions, old_va))
++ vtlb_purge(v, va, ps);
++ vhpt_purge(v, va, ps);
++}
++
++u64 translate_phy_pte(u64 *pte, u64 itir, u64 va)
++{
++ u64 ps, ps_mask, paddr, maddr;
++ union pte_flags phy_pte;
++
++ ps = itir_ps(itir);
++ ps_mask = ~((1UL << ps) - 1);
++ phy_pte.val = *pte;
++ paddr = *pte;
++ paddr = ((paddr & _PAGE_PPN_MASK) & ps_mask) | (va & ~ps_mask);
++ maddr = kvm_lookup_mpa(paddr >> PAGE_SHIFT);
++ if (maddr & GPFN_IO_MASK) {
++ *pte |= VTLB_PTE_IO;
++ return -1;
++ }
++ maddr = ((maddr & _PAGE_PPN_MASK) & PAGE_MASK) |
++ (paddr & ~PAGE_MASK);
++ phy_pte.ppn = maddr >> ARCH_PAGE_SHIFT;
++ return phy_pte.val;
++}
++
++/*
++ * Purge overlap TCs and then insert the new entry to emulate itc ops.
++ * Notes: Only TC entry can purge and insert.
++ * 1 indicates this is MMIO
++ */
++int thash_purge_and_insert(struct kvm_vcpu *v, u64 pte, u64 itir,
++ u64 ifa, int type)
++{
++ u64 ps;
++ u64 phy_pte;
++ union ia64_rr vrr, mrr;
++ int ret = 0;
++
++ ps = itir_ps(itir);
++ vrr.val = vcpu_get_rr(v, ifa);
++ mrr.val = ia64_get_rr(ifa);
++
++ phy_pte = translate_phy_pte(&pte, itir, ifa);
++
++ /* Ensure WB attribute if pte is related to a normal mem page,
++ * which is required by vga acceleration since qemu maps shared
++ * vram buffer with WB.
++ */
++ if (!(pte & VTLB_PTE_IO) && ((pte & _PAGE_MA_MASK) != _PAGE_MA_NAT)) {
++ pte &= ~_PAGE_MA_MASK;
++ phy_pte &= ~_PAGE_MA_MASK;
++ }
++
++ if (pte & VTLB_PTE_IO)
++ ret = 1;
++
++ vtlb_purge(v, ifa, ps);
++ vhpt_purge(v, ifa, ps);
++
++ if (ps == mrr.ps) {
++ if (!(pte&VTLB_PTE_IO)) {
++ vhpt_insert(phy_pte, itir, ifa, pte);
++ } else {
++ vtlb_insert(v, pte, itir, ifa);
++ vcpu_quick_region_set(VMX(v, tc_regions), ifa);
++ }
++ } else if (ps > mrr.ps) {
++ vtlb_insert(v, pte, itir, ifa);
++ vcpu_quick_region_set(VMX(v, tc_regions), ifa);
++ if (!(pte&VTLB_PTE_IO))
++ vhpt_insert(phy_pte, itir, ifa, pte);
++ } else {
++ u64 psr;
++ phy_pte &= ~PAGE_FLAGS_RV_MASK;
++ psr = ia64_clear_ic();
++ ia64_itc(type, ifa, phy_pte, ps);
++ ia64_set_psr(psr);
++ }
++ if (!(pte&VTLB_PTE_IO))
++ mark_pages_dirty(v, pte, ps);
++
++ return ret;
++}
++
++/*
++ * Purge all TCs or VHPT entries including those in Hash table.
++ *
++ */
++
++void thash_purge_all(struct kvm_vcpu *v)
++{
++ int i;
++ struct thash_data *head;
++ struct thash_cb *vtlb, *vhpt;
++ vtlb = &v->arch.vtlb;
++ vhpt = &v->arch.vhpt;
++
++ for (i = 0; i < 8; i++)
++ VMX(v, psbits[i]) = 0;
++
++ head = vtlb->hash;
++ for (i = 0; i < vtlb->num; i++) {
++ head->page_flags = 0;
++ head->etag = INVALID_TI_TAG;
++ head->itir = 0;
++ head->next = 0;
++ head++;
++ };
++
++ head = vhpt->hash;
++ for (i = 0; i < vhpt->num; i++) {
++ head->page_flags = 0;
++ head->etag = INVALID_TI_TAG;
++ head->itir = 0;
++ head->next = 0;
++ head++;
++ };
++
++ local_flush_tlb_all();
++}
++
++
++/*
++ * Lookup the hash table and its collision chain to find an entry
++ * covering this address rid:va or the entry.
++ *
++ * INPUT:
++ * in: TLB format for both VHPT & TLB.
++ */
++
++struct thash_data *vtlb_lookup(struct kvm_vcpu *v, u64 va, int is_data)
++{
++ struct thash_data *cch;
++ u64 psbits, ps, tag;
++ union ia64_rr vrr;
++
++ struct thash_cb *hcb = &v->arch.vtlb;
++
++ cch = __vtr_lookup(v, va, is_data);;
++ if (cch)
++ return cch;
++
++ if (vcpu_quick_region_check(v->arch.tc_regions, va) == 0)
++ return NULL;
++
++ psbits = VMX(v, psbits[(va >> 61)]);
++ vrr.val = vcpu_get_rr(v, va);
++ while (psbits) {
++ ps = __ffs(psbits);
++ psbits &= ~(1UL << ps);
++ vrr.ps = ps;
++ cch = vsa_thash(hcb->pta, va, vrr.val, &tag);
++ if (cch->etag == tag && cch->ps == ps)
++ return cch;
++ }
++
++ return NULL;
++}
++
++
++/*
++ * Initialize internal control data before service.
++ */
++void thash_init(struct thash_cb *hcb, u64 sz)
++{
++ int i;
++ struct thash_data *head;
++
++ hcb->pta.val = (unsigned long)hcb->hash;
++ hcb->pta.vf = 1;
++ hcb->pta.ve = 1;
++ hcb->pta.size = sz;
++ head = hcb->hash;
++ for (i = 0; i < hcb->num; i++) {
++ head->page_flags = 0;
++ head->itir = 0;
++ head->etag = INVALID_TI_TAG;
++ head->next = 0;
++ head++;
++ }
++}
++
++u64 kvm_lookup_mpa(u64 gpfn)
++{
++ u64 *base = (u64 *) KVM_P2M_BASE;
++ return *(base + gpfn);
++}
++
++u64 kvm_gpa_to_mpa(u64 gpa)
++{
++ u64 pte = kvm_lookup_mpa(gpa >> PAGE_SHIFT);
++ return (pte >> PAGE_SHIFT << PAGE_SHIFT) | (gpa & ~PAGE_MASK);
++}
++
++
++/*
++ * Fetch guest bundle code.
++ * INPUT:
++ * gip: guest ip
++ * pbundle: used to return fetched bundle.
++ */
++int fetch_code(struct kvm_vcpu *vcpu, u64 gip, IA64_BUNDLE *pbundle)
++{
++ u64 gpip = 0; /* guest physical IP*/
++ u64 *vpa;
++ struct thash_data *tlb;
++ u64 maddr;
++
++ if (!(VCPU(vcpu, vpsr) & IA64_PSR_IT)) {
++ /* I-side physical mode */
++ gpip = gip;
++ } else {
++ tlb = vtlb_lookup(vcpu, gip, I_TLB);
++ if (tlb)
++ gpip = (tlb->ppn >> (tlb->ps - 12) << tlb->ps) |
++ (gip & (PSIZE(tlb->ps) - 1));
++ }
++ if (gpip) {
++ maddr = kvm_gpa_to_mpa(gpip);
++ } else {
++ tlb = vhpt_lookup(gip);
++ if (tlb == NULL) {
++ ia64_ptcl(gip, ARCH_PAGE_SHIFT << 2);
++ return IA64_FAULT;
++ }
++ maddr = (tlb->ppn >> (tlb->ps - 12) << tlb->ps)
++ | (gip & (PSIZE(tlb->ps) - 1));
++ }
++ vpa = (u64 *)__kvm_va(maddr);
++
++ pbundle->i64[0] = *vpa++;
++ pbundle->i64[1] = *vpa;
++
++ return IA64_NO_FAULT;
++}
++
++
++void kvm_init_vhpt(struct kvm_vcpu *v)
++{
++ v->arch.vhpt.num = VHPT_NUM_ENTRIES;
++ thash_init(&v->arch.vhpt, VHPT_SHIFT);
++ ia64_set_pta(v->arch.vhpt.pta.val);
++ /*Enable VHPT here?*/
++}
++
++void kvm_init_vtlb(struct kvm_vcpu *v)
++{
++ v->arch.vtlb.num = VTLB_NUM_ENTRIES;
++ thash_init(&v->arch.vtlb, VTLB_SHIFT);
++}
+diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
+index 344f64e..798bf98 100644
+--- a/arch/ia64/mm/contig.c
++++ b/arch/ia64/mm/contig.c
+@@ -45,8 +45,6 @@ void show_mem(void)
+
+ printk(KERN_INFO "Mem-info:\n");
+ show_free_areas();
+- printk(KERN_INFO "Free swap: %6ldkB\n",
+- nr_swap_pages<<(PAGE_SHIFT-10));
+ printk(KERN_INFO "Node memory in pages:\n");
+ for_each_online_pgdat(pgdat) {
+ unsigned long present;
+@@ -255,7 +253,7 @@ paging_init (void)
+ max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
+
+ #ifdef CONFIG_VIRTUAL_MEM_MAP
+- efi_memmap_walk(register_active_ranges, NULL);
++ efi_memmap_walk(filter_memory, register_active_ranges);
+ efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
+ if (max_gap < LARGE_GAP) {
+ vmem_map = (struct page *) 0;
+diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
+index ee5e68b..544dc42 100644
+--- a/arch/ia64/mm/discontig.c
++++ b/arch/ia64/mm/discontig.c
+@@ -104,7 +104,7 @@ static int __meminit early_nr_cpus_node(int node)
+ {
+ int cpu, n = 0;
+
+- for (cpu = 0; cpu < NR_CPUS; cpu++)
++ for_each_possible_early_cpu(cpu)
+ if (node == node_cpuid[cpu].nid)
+ n++;
+
+@@ -124,6 +124,7 @@ static unsigned long __meminit compute_pernodesize(int node)
+ pernodesize += node * L1_CACHE_BYTES;
+ pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t));
+ pernodesize += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
++ pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t));
+ pernodesize = PAGE_ALIGN(pernodesize);
+ return pernodesize;
+ }
+@@ -142,7 +143,7 @@ static void *per_cpu_node_setup(void *cpu_data, int node)
+ #ifdef CONFIG_SMP
+ int cpu;
+
+- for (cpu = 0; cpu < NR_CPUS; cpu++) {
++ for_each_possible_early_cpu(cpu) {
+ if (node == node_cpuid[cpu].nid) {
+ memcpy(__va(cpu_data), __phys_per_cpu_start,
+ __per_cpu_end - __per_cpu_start);
+@@ -345,7 +346,7 @@ static void __init initialize_pernode_data(void)
+
+ #ifdef CONFIG_SMP
+ /* Set the node_data pointer for each per-cpu struct */
+- for (cpu = 0; cpu < NR_CPUS; cpu++) {
++ for_each_possible_early_cpu(cpu) {
+ node = node_cpuid[cpu].nid;
+ per_cpu(cpu_info, cpu).node_data = mem_data[node].node_data;
+ }
+@@ -444,7 +445,7 @@ void __init find_memory(void)
+ mem_data[node].min_pfn = ~0UL;
+ }
+
+- efi_memmap_walk(register_active_ranges, NULL);
++ efi_memmap_walk(filter_memory, register_active_ranges);
+
+ /*
+ * Initialize the boot memory maps in reverse order since that's
+@@ -493,13 +494,9 @@ void __cpuinit *per_cpu_init(void)
+ int cpu;
+ static int first_time = 1;
+
-
--/*
-- * 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);
+- if (smp_processor_id() != 0)
+- return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
-
-- /* nope, we'll have to do it ourselves */
-- *base = kzalloc(size + L1_CACHE_BYTES, flags);
-- if (*base == NULL) {
-- return NULL;
+ if (first_time) {
+ first_time = 0;
+- for (cpu = 0; cpu < NR_CPUS; cpu++)
++ for_each_possible_early_cpu(cpu)
+ per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
+ }
+
+@@ -522,8 +519,6 @@ void show_mem(void)
+
+ printk(KERN_INFO "Mem-info:\n");
+ show_free_areas();
+- printk(KERN_INFO "Free swap: %6ldkB\n",
+- nr_swap_pages<<(PAGE_SHIFT-10));
+ printk(KERN_INFO "Node memory in pages:\n");
+ for_each_online_pgdat(pgdat) {
+ unsigned long present;
+diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
+index a4ca657..fc6c663 100644
+--- a/arch/ia64/mm/init.c
++++ b/arch/ia64/mm/init.c
+@@ -58,7 +58,6 @@ __ia64_sync_icache_dcache (pte_t pte)
+ {
+ unsigned long addr;
+ struct page *page;
+- unsigned long order;
+
+ page = pte_page(pte);
+ addr = (unsigned long) page_address(page);
+@@ -66,12 +65,7 @@ __ia64_sync_icache_dcache (pte_t pte)
+ if (test_bit(PG_arch_1, &page->flags))
+ return; /* i-cache is already coherent with d-cache */
+
+- if (PageCompound(page)) {
+- order = compound_order(page);
+- flush_icache_range(addr, addr + (1UL << order << PAGE_SHIFT));
- }
-- return (void *) L1_CACHE_ALIGN((u64) *base);
--}
--
+- else
+- flush_icache_range(addr, addr + PAGE_SIZE);
++ flush_icache_range(addr, addr + (PAGE_SIZE << compound_order(page)));
+ set_bit(PG_arch_1, &page->flags); /* mark page as clean */
+ }
+
+@@ -553,12 +547,10 @@ find_largest_hole (u64 start, u64 end, void *arg)
+ #endif /* CONFIG_VIRTUAL_MEM_MAP */
+
+ int __init
+-register_active_ranges(u64 start, u64 end, void *arg)
++register_active_ranges(u64 start, u64 len, int nid)
+ {
+- int nid = paddr_to_nid(__pa(start));
++ u64 end = start + len;
+
+- if (nid < 0)
+- nid = 0;
+ #ifdef CONFIG_KEXEC
+ if (start > crashk_res.start && start < crashk_res.end)
+ start = crashk_res.end;
+@@ -690,15 +682,6 @@ mem_init (void)
+ }
+
+ #ifdef CONFIG_MEMORY_HOTPLUG
+-void online_page(struct page *page)
+-{
+- ClearPageReserved(page);
+- init_page_count(page);
+- __free_page(page);
+- totalram_pages++;
+- num_physpages++;
+-}
+-
+ int arch_add_memory(int nid, u64 start, u64 size)
+ {
+ pg_data_t *pgdat;
+diff --git a/arch/ia64/mm/numa.c b/arch/ia64/mm/numa.c
+index 7807fc5..b73bf18 100644
+--- a/arch/ia64/mm/numa.c
++++ b/arch/ia64/mm/numa.c
+@@ -27,7 +27,9 @@
+ */
+ int num_node_memblks;
+ struct node_memblk_s node_memblk[NR_NODE_MEMBLKS];
+-struct node_cpuid_s node_cpuid[NR_CPUS];
++struct node_cpuid_s node_cpuid[NR_CPUS] =
++ { [0 ... NR_CPUS-1] = { .phys_id = 0, .nid = NUMA_NO_NODE } };
++
+ /*
+ * This is a matrix with "distances" between nodes, they should be
+ * proportional to the memory access latency ratios.
+diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
+index 655da24..8caf424 100644
+--- a/arch/ia64/mm/tlb.c
++++ b/arch/ia64/mm/tlb.c
+@@ -11,6 +11,9 @@
+ * Rohit Seth <rohit.seth at intel.com>
+ * Ken Chen <kenneth.w.chen at intel.com>
+ * Christophe de Dinechin <ddd at hp.com>: Avoid ptc.e on memory allocation
++ * Copyright (C) 2007 Intel Corp
++ * Fenghua Yu <fenghua.yu at intel.com>
++ * Add multiple ptc.g/ptc.ga instruction support in global tlb purge.
+ */
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -26,6 +29,9 @@
+ #include <asm/pal.h>
+ #include <asm/tlbflush.h>
+ #include <asm/dma.h>
++#include <asm/processor.h>
++#include <asm/sal.h>
++#include <asm/tlb.h>
+
+ static struct {
+ unsigned long mask; /* mask of supported purge page-sizes */
+@@ -39,6 +45,10 @@ struct ia64_ctx ia64_ctx = {
+ };
+
+ DEFINE_PER_CPU(u8, ia64_need_tlb_flush);
++DEFINE_PER_CPU(u8, ia64_tr_num); /*Number of TR slots in current processor*/
++DEFINE_PER_CPU(u8, ia64_tr_used); /*Max Slot number used by kernel*/
++
++struct ia64_tr_entry __per_cpu_idtrs[NR_CPUS][2][IA64_TR_ALLOC_MAX];
+
+ /*
+ * Initializes the ia64_ctx.bitmap array based on max_ctx+1.
+@@ -84,14 +94,143 @@ wrap_mmu_context (struct mm_struct *mm)
+ local_flush_tlb_all();
+ }
+
++/*
++ * Implement "spinaphores" ... like counting semaphores, but they
++ * spin instead of sleeping. If there are ever any other users for
++ * this primitive it can be moved up to a spinaphore.h header.
++ */
++struct spinaphore {
++ atomic_t cur;
++};
++
++static inline void spinaphore_init(struct spinaphore *ss, int val)
++{
++ atomic_set(&ss->cur, val);
++}
++
++static inline void down_spin(struct spinaphore *ss)
++{
++ while (unlikely(!atomic_add_unless(&ss->cur, -1, 0)))
++ while (atomic_read(&ss->cur) == 0)
++ cpu_relax();
++}
++
++static inline void up_spin(struct spinaphore *ss)
++{
++ atomic_add(1, &ss->cur);
++}
++
++static struct spinaphore ptcg_sem;
++static u16 nptcg = 1;
++static int need_ptcg_sem = 1;
++static int toolatetochangeptcgsem = 0;
++
++/*
++ * Kernel parameter "nptcg=" overrides max number of concurrent global TLB
++ * purges which is reported from either PAL or SAL PALO.
++ *
++ * We don't have sanity checking for nptcg value. It's the user's responsibility
++ * for valid nptcg value on the platform. Otherwise, kernel may hang in some
++ * cases.
++ */
++static int __init
++set_nptcg(char *str)
++{
++ int value = 0;
++
++ get_option(&str, &value);
++ setup_ptcg_sem(value, NPTCG_FROM_KERNEL_PARAMETER);
++
++ return 1;
++}
++
++__setup("nptcg=", set_nptcg);
++
++/*
++ * Maximum number of simultaneous ptc.g purges in the system can
++ * be defined by PAL_VM_SUMMARY (in which case we should take
++ * the smallest value for any cpu in the system) or by the PAL
++ * override table (in which case we should ignore the value from
++ * PAL_VM_SUMMARY).
++ *
++ * Kernel parameter "nptcg=" overrides maximum number of simultanesous ptc.g
++ * purges defined in either PAL_VM_SUMMARY or PAL override table. In this case,
++ * we should ignore the value from either PAL_VM_SUMMARY or PAL override table.
++ *
++ * Complicating the logic here is the fact that num_possible_cpus()
++ * isn't fully setup until we start bringing cpus online.
++ */
++void
++setup_ptcg_sem(int max_purges, int nptcg_from)
++{
++ static int kp_override;
++ static int palo_override;
++ static int firstcpu = 1;
++
++ if (toolatetochangeptcgsem) {
++ if (nptcg_from == NPTCG_FROM_PAL && max_purges == 0)
++ BUG_ON(1 < nptcg);
++ else
++ BUG_ON(max_purges < nptcg);
++ return;
++ }
++
++ if (nptcg_from == NPTCG_FROM_KERNEL_PARAMETER) {
++ kp_override = 1;
++ nptcg = max_purges;
++ goto resetsema;
++ }
++ if (kp_override) {
++ need_ptcg_sem = num_possible_cpus() > nptcg;
++ return;
++ }
++
++ if (nptcg_from == NPTCG_FROM_PALO) {
++ palo_override = 1;
++
++ /* In PALO max_purges == 0 really means it! */
++ if (max_purges == 0)
++ panic("Whoa! Platform does not support global TLB purges.\n");
++ nptcg = max_purges;
++ if (nptcg == PALO_MAX_TLB_PURGES) {
++ need_ptcg_sem = 0;
++ return;
++ }
++ goto resetsema;
++ }
++ if (palo_override) {
++ if (nptcg != PALO_MAX_TLB_PURGES)
++ need_ptcg_sem = (num_possible_cpus() > nptcg);
++ return;
++ }
++
++ /* In PAL_VM_SUMMARY max_purges == 0 actually means 1 */
++ if (max_purges == 0) max_purges = 1;
++
++ if (firstcpu) {
++ nptcg = max_purges;
++ firstcpu = 0;
++ }
++ if (max_purges < nptcg)
++ nptcg = max_purges;
++ if (nptcg == PAL_MAX_PURGES) {
++ need_ptcg_sem = 0;
++ return;
++ } else
++ need_ptcg_sem = (num_possible_cpus() > nptcg);
++
++resetsema:
++ spinaphore_init(&ptcg_sem, max_purges);
++}
++
+ void
+ ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start,
+ unsigned long end, unsigned long nbits)
+ {
+- static DEFINE_SPINLOCK(ptcg_lock);
+-
+ struct mm_struct *active_mm = current->active_mm;
+
++ toolatetochangeptcgsem = 1;
++
+ if (mm != active_mm) {
+ /* Restore region IDs for mm */
+ if (mm && active_mm) {
+@@ -102,19 +241,20 @@ ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start,
+ }
+ }
+
+- /* HW requires global serialization of ptc.ga. */
+- spin_lock(&ptcg_lock);
+- {
+- do {
+- /*
+- * Flush ALAT entries also.
+- */
+- ia64_ptcga(start, (nbits<<2));
+- ia64_srlz_i();
+- start += (1UL << nbits);
+- } while (start < end);
+- }
+- spin_unlock(&ptcg_lock);
++ if (need_ptcg_sem)
++ down_spin(&ptcg_sem);
++
++ do {
++ /*
++ * Flush ALAT entries also.
++ */
++ ia64_ptcga(start, (nbits << 2));
++ ia64_srlz_i();
++ start += (1UL << nbits);
++ } while (start < end);
++
++ if (need_ptcg_sem)
++ up_spin(&ptcg_sem);
+
+ if (mm != active_mm) {
+ activate_context(active_mm);
+@@ -190,6 +330,9 @@ ia64_tlb_init (void)
+ ia64_ptce_info_t uninitialized_var(ptce_info); /* GCC be quiet */
+ unsigned long tr_pgbits;
+ long status;
++ pal_vm_info_1_u_t vm_info_1;
++ pal_vm_info_2_u_t vm_info_2;
++ int cpu = smp_processor_id();
+
+ if ((status = ia64_pal_vm_page_size(&tr_pgbits, &purge.mask)) != 0) {
+ printk(KERN_ERR "PAL_VM_PAGE_SIZE failed with status=%ld; "
+@@ -206,4 +349,191 @@ ia64_tlb_init (void)
+ local_cpu_data->ptce_stride[1] = ptce_info.stride[1];
+
+ local_flush_tlb_all(); /* nuke left overs from bootstrapping... */
++ status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2);
++
++ if (status) {
++ printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status);
++ per_cpu(ia64_tr_num, cpu) = 8;
++ return;
++ }
++ per_cpu(ia64_tr_num, cpu) = vm_info_1.pal_vm_info_1_s.max_itr_entry+1;
++ if (per_cpu(ia64_tr_num, cpu) >
++ (vm_info_1.pal_vm_info_1_s.max_dtr_entry+1))
++ per_cpu(ia64_tr_num, cpu) =
++ vm_info_1.pal_vm_info_1_s.max_dtr_entry+1;
++ if (per_cpu(ia64_tr_num, cpu) > IA64_TR_ALLOC_MAX) {
++ per_cpu(ia64_tr_num, cpu) = IA64_TR_ALLOC_MAX;
++ printk(KERN_DEBUG "TR register number exceeds IA64_TR_ALLOC_MAX!"
++ "IA64_TR_ALLOC_MAX should be extended\n");
++ }
++}
++
++/*
++ * is_tr_overlap
++ *
++ * Check overlap with inserted TRs.
++ */
++static int is_tr_overlap(struct ia64_tr_entry *p, u64 va, u64 log_size)
++{
++ u64 tr_log_size;
++ u64 tr_end;
++ u64 va_rr = ia64_get_rr(va);
++ u64 va_rid = RR_TO_RID(va_rr);
++ u64 va_end = va + (1<<log_size) - 1;
++
++ if (va_rid != RR_TO_RID(p->rr))
++ return 0;
++ tr_log_size = (p->itir & 0xff) >> 2;
++ tr_end = p->ifa + (1<<tr_log_size) - 1;
++
++ if (va > tr_end || p->ifa > va_end)
++ return 0;
++ return 1;
++
++}
++
++/*
++ * ia64_insert_tr in virtual mode. Allocate a TR slot
++ *
++ * target_mask : 0x1 : itr, 0x2 : dtr, 0x3 : idtr
++ *
++ * va : virtual address.
++ * pte : pte entries inserted.
++ * log_size: range to be covered.
++ *
++ * Return value: <0 : error No.
++ *
++ * >=0 : slot number allocated for TR.
++ * Must be called with preemption disabled.
++ */
++int ia64_itr_entry(u64 target_mask, u64 va, u64 pte, u64 log_size)
++{
++ int i, r;
++ unsigned long psr;
++ struct ia64_tr_entry *p;
++ int cpu = smp_processor_id();
++
++ r = -EINVAL;
++ /*Check overlap with existing TR entries*/
++ if (target_mask & 0x1) {
++ p = &__per_cpu_idtrs[cpu][0][0];
++ for (i = IA64_TR_ALLOC_BASE; i <= per_cpu(ia64_tr_used, cpu);
++ i++, p++) {
++ if (p->pte & 0x1)
++ if (is_tr_overlap(p, va, log_size)) {
++ printk(KERN_DEBUG "Overlapped Entry"
++ "Inserted for TR Reigster!!\n");
++ goto out;
++ }
++ }
++ }
++ if (target_mask & 0x2) {
++ p = &__per_cpu_idtrs[cpu][1][0];
++ for (i = IA64_TR_ALLOC_BASE; i <= per_cpu(ia64_tr_used, cpu);
++ i++, p++) {
++ if (p->pte & 0x1)
++ if (is_tr_overlap(p, va, log_size)) {
++ printk(KERN_DEBUG "Overlapped Entry"
++ "Inserted for TR Reigster!!\n");
++ goto out;
++ }
++ }
++ }
++
++ for (i = IA64_TR_ALLOC_BASE; i < per_cpu(ia64_tr_num, cpu); i++) {
++ switch (target_mask & 0x3) {
++ case 1:
++ if (!(__per_cpu_idtrs[cpu][0][i].pte & 0x1))
++ goto found;
++ continue;
++ case 2:
++ if (!(__per_cpu_idtrs[cpu][1][i].pte & 0x1))
++ goto found;
++ continue;
++ case 3:
++ if (!(__per_cpu_idtrs[cpu][0][i].pte & 0x1) &&
++ !(__per_cpu_idtrs[cpu][1][i].pte & 0x1))
++ goto found;
++ continue;
++ default:
++ r = -EINVAL;
++ goto out;
++ }
++ }
++found:
++ if (i >= per_cpu(ia64_tr_num, cpu))
++ return -EBUSY;
++
++ /*Record tr info for mca hander use!*/
++ if (i > per_cpu(ia64_tr_used, cpu))
++ per_cpu(ia64_tr_used, cpu) = i;
++
++ psr = ia64_clear_ic();
++ if (target_mask & 0x1) {
++ ia64_itr(0x1, i, va, pte, log_size);
++ ia64_srlz_i();
++ p = &__per_cpu_idtrs[cpu][0][i];
++ p->ifa = va;
++ p->pte = pte;
++ p->itir = log_size << 2;
++ p->rr = ia64_get_rr(va);
++ }
++ if (target_mask & 0x2) {
++ ia64_itr(0x2, i, va, pte, log_size);
++ ia64_srlz_i();
++ p = &__per_cpu_idtrs[cpu][1][i];
++ p->ifa = va;
++ p->pte = pte;
++ p->itir = log_size << 2;
++ p->rr = ia64_get_rr(va);
++ }
++ ia64_set_psr(psr);
++ r = i;
++out:
++ return r;
++}
++EXPORT_SYMBOL_GPL(ia64_itr_entry);
++
++/*
++ * ia64_purge_tr
++ *
++ * target_mask: 0x1: purge itr, 0x2 : purge dtr, 0x3 purge idtr.
++ * slot: slot number to be freed.
++ *
++ * Must be called with preemption disabled.
++ */
++void ia64_ptr_entry(u64 target_mask, int slot)
++{
++ int cpu = smp_processor_id();
++ int i;
++ struct ia64_tr_entry *p;
++
++ if (slot < IA64_TR_ALLOC_BASE || slot >= per_cpu(ia64_tr_num, cpu))
++ return;
++
++ if (target_mask & 0x1) {
++ p = &__per_cpu_idtrs[cpu][0][slot];
++ if ((p->pte&0x1) && is_tr_overlap(p, p->ifa, p->itir>>2)) {
++ p->pte = 0;
++ ia64_ptr(0x1, p->ifa, p->itir>>2);
++ ia64_srlz_i();
++ }
++ }
++
++ if (target_mask & 0x2) {
++ p = &__per_cpu_idtrs[cpu][1][slot];
++ if ((p->pte & 0x1) && is_tr_overlap(p, p->ifa, p->itir>>2)) {
++ p->pte = 0;
++ ia64_ptr(0x2, p->ifa, p->itir>>2);
++ ia64_srlz_i();
++ }
++ }
++
++ for (i = per_cpu(ia64_tr_used, cpu); i >= IA64_TR_ALLOC_BASE; i--) {
++ if ((__per_cpu_idtrs[cpu][0][i].pte & 0x1) ||
++ (__per_cpu_idtrs[cpu][1][i].pte & 0x1))
++ break;
++ }
++ per_cpu(ia64_tr_used, cpu) = i;
+ }
++EXPORT_SYMBOL_GPL(ia64_ptr_entry);
+diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
+index 53d0a8e..77b15f8 100644
+--- a/arch/ia64/pci/pci.c
++++ b/arch/ia64/pci/pci.c
+@@ -504,54 +504,12 @@ pcibios_update_irq (struct pci_dev *dev, int irq)
+ /* ??? FIXME -- record old value for shutdown. */
+ }
+
+-static inline int
+-pcibios_enable_resources (struct pci_dev *dev, int mask)
+-{
+- u16 cmd, old_cmd;
+- int idx;
+- struct resource *r;
+- unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
+-
+- if (!dev)
+- return -EINVAL;
+-
+- pci_read_config_word(dev, PCI_COMMAND, &cmd);
+- old_cmd = cmd;
+- for (idx=0; idx<PCI_NUM_RESOURCES; idx++) {
+- /* Only set up the desired resources. */
+- if (!(mask & (1 << idx)))
+- continue;
+-
+- r = &dev->resource[idx];
+- if (!(r->flags & type_mask))
+- continue;
+- if ((idx == PCI_ROM_RESOURCE) &&
+- (!(r->flags & IORESOURCE_ROM_ENABLE)))
+- continue;
+- if (!r->start && r->end) {
+- printk(KERN_ERR
+- "PCI: Device %s not available because of resource collisions\n",
+- pci_name(dev));
+- return -EINVAL;
+- }
+- if (r->flags & IORESOURCE_IO)
+- cmd |= PCI_COMMAND_IO;
+- if (r->flags & IORESOURCE_MEM)
+- cmd |= PCI_COMMAND_MEMORY;
+- }
+- if (cmd != old_cmd) {
+- printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
+- pci_write_config_word(dev, PCI_COMMAND, cmd);
+- }
+- return 0;
+-}
+-
+ int
+ pcibios_enable_device (struct pci_dev *dev, int mask)
+ {
+ int ret;
+
+- ret = pcibios_enable_resources(dev, mask);
++ ret = pci_enable_resources(dev, mask);
+ if (ret < 0)
+ return ret;
+
+diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile
+index 688a3c2..0591038 100644
+--- a/arch/ia64/sn/kernel/Makefile
++++ b/arch/ia64/sn/kernel/Makefile
+@@ -4,7 +4,7 @@
+ # License. See the file "COPYING" in the main directory of this archive
+ # for more details.
+ #
+-# Copyright (C) 1999,2001-2006 Silicon Graphics, Inc. All Rights Reserved.
++# Copyright (C) 1999,2001-2006,2008 Silicon Graphics, Inc. All Rights Reserved.
+ #
+
+ EXTRA_CFLAGS += -Iarch/ia64/sn/include
+@@ -15,9 +15,4 @@ obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \
+ sn2/
+ obj-$(CONFIG_IA64_GENERIC) += machvec.o
+ obj-$(CONFIG_SGI_TIOCX) += tiocx.o
+-obj-$(CONFIG_IA64_SGI_SN_XP) += xp.o
+-xp-y := xp_main.o xp_nofault.o
+-obj-$(CONFIG_IA64_SGI_SN_XP) += xpc.o
+-xpc-y := xpc_main.o xpc_channel.o xpc_partition.o
+-obj-$(CONFIG_IA64_SGI_SN_XP) += xpnet.o
+ obj-$(CONFIG_PCI_MSI) += msi_sn.o
+diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c
+index 0101c79..08b0d9b 100644
+--- a/arch/ia64/sn/kernel/huberror.c
++++ b/arch/ia64/sn/kernel/huberror.c
+@@ -187,8 +187,8 @@ void hub_error_init(struct hubdev_info *hubdev_info)
+ {
+
+ if (request_irq(SGI_II_ERROR, hub_eint_handler, IRQF_SHARED,
+- "SN_hub_error", (void *)hubdev_info)) {
+- printk("hub_error_init: Failed to request_irq for 0x%p\n",
++ "SN_hub_error", hubdev_info)) {
++ printk(KERN_ERR "hub_error_init: Failed to request_irq for 0x%p\n",
+ hubdev_info);
+ return;
+ }
+diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
+index dfc6bf1..49d3120 100644
+--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
++++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
+@@ -550,11 +550,12 @@ static int __init sn2_ptc_init(void)
+ if (!ia64_platform_is("sn2"))
+ return 0;
+
+- if (!(proc_sn2_ptc = create_proc_entry(PTC_BASENAME, 0444, NULL))) {
++ proc_sn2_ptc = proc_create(PTC_BASENAME, 0444,
++ NULL, &proc_sn2_ptc_operations);
++ if (!&proc_sn2_ptc_operations) {
+ printk(KERN_ERR "unable to create %s proc entry", PTC_BASENAME);
+ return -EINVAL;
+ }
+- proc_sn2_ptc->proc_fops = &proc_sn2_ptc_operations;
+ spin_lock_init(&sn2_global_ptc_lock);
+ return 0;
+ }
+diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+index 4b0d153..8cc0c47 100644
+--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
++++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+@@ -37,7 +37,6 @@
+
+ #include <asm/processor.h>
+ #include <asm/topology.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ #include <asm/sal.h>
+ #include <asm/sn/io.h>
+diff --git a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
+index 62b3e9a..2526e5c 100644
+--- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
++++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
+@@ -139,30 +139,21 @@ static const struct file_operations proc_sn_topo_fops = {
+ void register_sn_procfs(void)
+ {
+ static struct proc_dir_entry *sgi_proc_dir = NULL;
+- struct proc_dir_entry *pde;
+
+ BUG_ON(sgi_proc_dir != NULL);
+ if (!(sgi_proc_dir = proc_mkdir("sgi_sn", NULL)))
+ return;
+
+- pde = create_proc_entry("partition_id", 0444, sgi_proc_dir);
+- if (pde)
+- pde->proc_fops = &proc_partition_id_fops;
+- pde = create_proc_entry("system_serial_number", 0444, sgi_proc_dir);
+- if (pde)
+- pde->proc_fops = &proc_system_sn_fops;
+- pde = create_proc_entry("licenseID", 0444, sgi_proc_dir);
+- if (pde)
+- pde->proc_fops = &proc_license_id_fops;
+- pde = create_proc_entry("sn_force_interrupt", 0644, sgi_proc_dir);
+- if (pde)
+- pde->proc_fops = &proc_sn_force_intr_fops;
+- pde = create_proc_entry("coherence_id", 0444, sgi_proc_dir);
+- if (pde)
+- pde->proc_fops = &proc_coherence_id_fops;
+- pde = create_proc_entry("sn_topology", 0444, sgi_proc_dir);
+- if (pde)
+- pde->proc_fops = &proc_sn_topo_fops;
++ proc_create("partition_id", 0444, sgi_proc_dir,
++ &proc_partition_id_fops);
++ proc_create("system_serial_number", 0444, sgi_proc_dir,
++ &proc_system_sn_fops);
++ proc_create("licenseID", 0444, sgi_proc_dir, &proc_license_id_fops);
++ proc_create("sn_force_interrupt", 0644, sgi_proc_dir,
++ &proc_sn_force_intr_fops);
++ proc_create("coherence_id", 0444, sgi_proc_dir,
++ &proc_coherence_id_fops);
++ proc_create("sn_topology", 0444, sgi_proc_dir, &proc_sn_topo_fops);
+ }
+
+ #endif /* CONFIG_PROC_FS */
+diff --git a/arch/ia64/sn/kernel/xp_main.c b/arch/ia64/sn/kernel/xp_main.c
+deleted file mode 100644
+index b7ea466..0000000
+--- a/arch/ia64/sn/kernel/xp_main.c
++++ /dev/null
+@@ -1,290 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
+- */
+-
+-
+-/*
+- * Cross Partition (XP) base.
+- *
+- * XP provides a base from which its users can interact
+- * with XPC, yet not be dependent on XPC.
+- *
+- */
+-
+-
+-#include <linux/kernel.h>
+-#include <linux/interrupt.h>
+-#include <linux/module.h>
+-#include <linux/mutex.h>
+-#include <asm/sn/intr.h>
+-#include <asm/sn/sn_sal.h>
+-#include <asm/sn/xp.h>
+-
+-
+-/*
+- * Target of nofault PIO read.
+- */
+-u64 xp_nofault_PIOR_target;
+-
+-
+-/*
+- * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level
+- * users of XPC.
+- */
+-struct xpc_registration xpc_registrations[XPC_NCHANNELS];
+-
+-
+-/*
+- * Initialize the XPC interface to indicate that XPC isn't loaded.
+- */
+-static enum xpc_retval xpc_notloaded(void) { return xpcNotLoaded; }
+-
+-struct xpc_interface xpc_interface = {
+- (void (*)(int)) xpc_notloaded,
+- (void (*)(int)) xpc_notloaded,
+- (enum xpc_retval (*)(partid_t, int, u32, void **)) xpc_notloaded,
+- (enum xpc_retval (*)(partid_t, int, void *)) xpc_notloaded,
+- (enum xpc_retval (*)(partid_t, int, void *, xpc_notify_func, void *))
+- xpc_notloaded,
+- (void (*)(partid_t, int, void *)) xpc_notloaded,
+- (enum xpc_retval (*)(partid_t, void *)) xpc_notloaded
+-};
+-
+-
+-/*
+- * XPC calls this when it (the XPC module) has been loaded.
+- */
+-void
+-xpc_set_interface(void (*connect)(int),
+- void (*disconnect)(int),
+- enum xpc_retval (*allocate)(partid_t, int, u32, void **),
+- enum xpc_retval (*send)(partid_t, int, void *),
+- enum xpc_retval (*send_notify)(partid_t, int, void *,
+- xpc_notify_func, void *),
+- void (*received)(partid_t, int, void *),
+- enum xpc_retval (*partid_to_nasids)(partid_t, void *))
+-{
+- xpc_interface.connect = connect;
+- xpc_interface.disconnect = disconnect;
+- xpc_interface.allocate = allocate;
+- xpc_interface.send = send;
+- xpc_interface.send_notify = send_notify;
+- xpc_interface.received = received;
+- xpc_interface.partid_to_nasids = partid_to_nasids;
+-}
+-
+-
+-/*
+- * XPC calls this when it (the XPC module) is being unloaded.
+- */
+-void
+-xpc_clear_interface(void)
+-{
+- xpc_interface.connect = (void (*)(int)) xpc_notloaded;
+- xpc_interface.disconnect = (void (*)(int)) xpc_notloaded;
+- xpc_interface.allocate = (enum xpc_retval (*)(partid_t, int, u32,
+- void **)) xpc_notloaded;
+- xpc_interface.send = (enum xpc_retval (*)(partid_t, int, void *))
+- xpc_notloaded;
+- xpc_interface.send_notify = (enum xpc_retval (*)(partid_t, int, void *,
+- xpc_notify_func, void *)) xpc_notloaded;
+- xpc_interface.received = (void (*)(partid_t, int, void *))
+- xpc_notloaded;
+- xpc_interface.partid_to_nasids = (enum xpc_retval (*)(partid_t, void *))
+- xpc_notloaded;
+-}
+-
+-
+-/*
+- * Register for automatic establishment of a channel connection whenever
+- * a partition comes up.
+- *
+- * Arguments:
+- *
+- * ch_number - channel # to register for connection.
+- * func - function to call for asynchronous notification of channel
+- * state changes (i.e., connection, disconnection, error) and
+- * the arrival of incoming messages.
+- * key - pointer to optional user-defined value that gets passed back
+- * to the user on any callouts made to func.
+- * payload_size - size in bytes of the XPC message's payload area which
+- * contains a user-defined message. The user should make
+- * this large enough to hold their largest message.
+- * nentries - max #of XPC message entries a message queue can contain.
+- * The actual number, which is determined when a connection
+- * is established and may be less then requested, will be
+- * passed to the user via the xpcConnected callout.
+- * assigned_limit - max number of kthreads allowed to be processing
+- * messages (per connection) at any given instant.
+- * idle_limit - max number of kthreads allowed to be idle at any given
+- * instant.
+- */
+-enum xpc_retval
+-xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
+- u16 nentries, u32 assigned_limit, u32 idle_limit)
+-{
+- struct xpc_registration *registration;
+-
+-
+- DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+- DBUG_ON(payload_size == 0 || nentries == 0);
+- DBUG_ON(func == NULL);
+- DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);
+-
+- registration = &xpc_registrations[ch_number];
+-
+- if (mutex_lock_interruptible(®istration->mutex) != 0) {
+- return xpcInterrupted;
+- }
+-
+- /* if XPC_CHANNEL_REGISTERED(ch_number) */
+- if (registration->func != NULL) {
+- mutex_unlock(®istration->mutex);
+- return xpcAlreadyRegistered;
+- }
+-
+- /* register the channel for connection */
+- registration->msg_size = XPC_MSG_SIZE(payload_size);
+- registration->nentries = nentries;
+- registration->assigned_limit = assigned_limit;
+- registration->idle_limit = idle_limit;
+- registration->key = key;
+- registration->func = func;
+-
+- mutex_unlock(®istration->mutex);
+-
+- xpc_interface.connect(ch_number);
+-
+- return xpcSuccess;
+-}
+-
+-
+-/*
+- * Remove the registration for automatic connection of the specified channel
+- * when a partition comes up.
+- *
+- * Before returning this xpc_disconnect() will wait for all connections on the
+- * specified channel have been closed/torndown. So the caller can be assured
+- * that they will not be receiving any more callouts from XPC to their
+- * function registered via xpc_connect().
+- *
+- * Arguments:
+- *
+- * ch_number - channel # to unregister.
+- */
+-void
+-xpc_disconnect(int ch_number)
+-{
+- struct xpc_registration *registration;
+-
+-
+- DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+-
+- registration = &xpc_registrations[ch_number];
+-
+- /*
+- * We've decided not to make this a down_interruptible(), since we
+- * figured XPC's users will just turn around and call xpc_disconnect()
+- * again anyways, so we might as well wait, if need be.
+- */
+- mutex_lock(®istration->mutex);
+-
+- /* if !XPC_CHANNEL_REGISTERED(ch_number) */
+- if (registration->func == NULL) {
+- mutex_unlock(®istration->mutex);
+- return;
+- }
+-
+- /* remove the connection registration for the specified channel */
+- registration->func = NULL;
+- registration->key = NULL;
+- registration->nentries = 0;
+- registration->msg_size = 0;
+- registration->assigned_limit = 0;
+- registration->idle_limit = 0;
+-
+- xpc_interface.disconnect(ch_number);
+-
+- mutex_unlock(®istration->mutex);
+-
+- return;
+-}
+-
+-
+-int __init
+-xp_init(void)
+-{
+- int ret, ch_number;
+- u64 func_addr = *(u64 *) xp_nofault_PIOR;
+- u64 err_func_addr = *(u64 *) xp_error_PIOR;
+-
+-
+- if (!ia64_platform_is("sn2")) {
+- return -ENODEV;
+- }
+-
+- /*
+- * Register a nofault code region which performs a cross-partition
+- * PIO read. If the PIO read times out, the MCA handler will consume
+- * the error and return to a kernel-provided instruction to indicate
+- * an error. This PIO read exists because it is guaranteed to timeout
+- * if the destination is down (AMO operations do not timeout on at
+- * least some CPUs on Shubs <= v1.2, which unfortunately we have to
+- * work around).
+- */
+- if ((ret = sn_register_nofault_code(func_addr, err_func_addr,
+- err_func_addr, 1, 1)) != 0) {
+- printk(KERN_ERR "XP: can't register nofault code, error=%d\n",
+- ret);
+- }
+- /*
+- * Setup the nofault PIO read target. (There is no special reason why
+- * SH_IPI_ACCESS was selected.)
+- */
+- if (is_shub2()) {
+- xp_nofault_PIOR_target = SH2_IPI_ACCESS0;
+- } else {
+- xp_nofault_PIOR_target = SH1_IPI_ACCESS;
+- }
+-
+- /* initialize the connection registration mutex */
+- for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) {
+- mutex_init(&xpc_registrations[ch_number].mutex);
+- }
+-
+- return 0;
+-}
+-module_init(xp_init);
+-
+-
+-void __exit
+-xp_exit(void)
+-{
+- u64 func_addr = *(u64 *) xp_nofault_PIOR;
+- u64 err_func_addr = *(u64 *) xp_error_PIOR;
+-
+-
+- /* unregister the PIO read nofault code region */
+- (void) sn_register_nofault_code(func_addr, err_func_addr,
+- err_func_addr, 1, 0);
+-}
+-module_exit(xp_exit);
+-
+-
+-MODULE_AUTHOR("Silicon Graphics, Inc.");
+-MODULE_DESCRIPTION("Cross Partition (XP) base");
+-MODULE_LICENSE("GPL");
+-
+-EXPORT_SYMBOL(xp_nofault_PIOR);
+-EXPORT_SYMBOL(xp_nofault_PIOR_target);
+-EXPORT_SYMBOL(xpc_registrations);
+-EXPORT_SYMBOL(xpc_interface);
+-EXPORT_SYMBOL(xpc_clear_interface);
+-EXPORT_SYMBOL(xpc_set_interface);
+-EXPORT_SYMBOL(xpc_connect);
+-EXPORT_SYMBOL(xpc_disconnect);
+-
+diff --git a/arch/ia64/sn/kernel/xp_nofault.S b/arch/ia64/sn/kernel/xp_nofault.S
+deleted file mode 100644
+index 98e7c7d..0000000
+--- a/arch/ia64/sn/kernel/xp_nofault.S
++++ /dev/null
+@@ -1,36 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (c) 2004-2007 Silicon Graphics, Inc. All Rights Reserved.
+- */
+-
+-
+-/*
+- * The xp_nofault_PIOR function takes a pointer to a remote PIO register
+- * and attempts to load and consume a value from it. This function
+- * will be registered as a nofault code block. In the event that the
+- * PIO read fails, the MCA handler will force the error to look
+- * corrected and vector to the xp_error_PIOR which will return an error.
+- *
+- * The definition of "consumption" and the time it takes for an MCA
+- * to surface is processor implementation specific. This code
+- * is sufficient on Itanium through the Montvale processor family.
+- * It may need to be adjusted for future processor implementations.
+- *
+- * extern int xp_nofault_PIOR(void *remote_register);
+- */
+-
+- .global xp_nofault_PIOR
+-xp_nofault_PIOR:
+- mov r8=r0 // Stage a success return value
+- ld8.acq r9=[r32];; // PIO Read the specified register
+- adds r9=1,r9;; // Add to force consumption
+- srlz.i;; // Allow time for MCA to surface
+- br.ret.sptk.many b0;; // Return success
+-
+- .global xp_error_PIOR
+-xp_error_PIOR:
+- mov r8=1 // Return value of 1
+- br.ret.sptk.many b0;; // Return failure
+diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
+deleted file mode 100644
+index 44ccc0d..0000000
+--- a/arch/ia64/sn/kernel/xpc_channel.c
++++ /dev/null
+@@ -1,2379 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved.
+- */
+-
+-
+-/*
+- * Cross Partition Communication (XPC) channel support.
+- *
+- * This is the part of XPC that manages the channels and
+- * sends/receives messages across them to/from other partitions.
+- *
+- */
+-
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/cache.h>
+-#include <linux/interrupt.h>
+-#include <linux/mutex.h>
+-#include <linux/completion.h>
+-#include <asm/sn/bte.h>
+-#include <asm/sn/sn_sal.h>
+-#include <asm/sn/xpc.h>
+-
+-
+-/*
+- * Guarantee that the kzalloc'd memory is cacheline aligned.
+- */
+-static void *
+-xpc_kzalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
+-{
+- /* see if kzalloc will give us cachline aligned memory by default */
+- *base = kzalloc(size, flags);
+- if (*base == NULL) {
+- return NULL;
+- }
+- if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) {
+- return *base;
+- }
+- kfree(*base);
+-
+- /* nope, we'll have to do it ourselves */
+- *base = kzalloc(size + L1_CACHE_BYTES, flags);
+- if (*base == NULL) {
+- return NULL;
+- }
+- return (void *) L1_CACHE_ALIGN((u64) *base);
+-}
+-
-
-/*
- * Set up the initial values for the XPartition Communication channels.
@@ -96053,6 +114990,206 @@
-MODULE_DESCRIPTION("Cross Partition Network adapter (XPNET)");
-MODULE_LICENSE("GPL");
-
+diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
+index 18b94b7..52175af 100644
+--- a/arch/ia64/sn/pci/pci_dma.c
++++ b/arch/ia64/sn/pci/pci_dma.c
+@@ -10,6 +10,7 @@
+ */
+
+ #include <linux/module.h>
++#include <linux/dma-attrs.h>
+ #include <asm/dma.h>
+ #include <asm/sn/intr.h>
+ #include <asm/sn/pcibus_provider_defs.h>
+@@ -149,11 +150,12 @@ void sn_dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
+ EXPORT_SYMBOL(sn_dma_free_coherent);
+
+ /**
+- * sn_dma_map_single - map a single page for DMA
++ * sn_dma_map_single_attrs - map a single page for DMA
+ * @dev: device to map for
+ * @cpu_addr: kernel virtual address of the region to map
+ * @size: size of the region
+ * @direction: DMA direction
++ * @attrs: optional dma attributes
+ *
+ * Map the region pointed to by @cpu_addr for DMA and return the
+ * DMA address.
+@@ -163,42 +165,59 @@ EXPORT_SYMBOL(sn_dma_free_coherent);
+ * no way of saving the dmamap handle from the alloc to later free
+ * (which is pretty much unacceptable).
+ *
++ * mappings with the DMA_ATTR_WRITE_BARRIER get mapped with
++ * dma_map_consistent() so that writes force a flush of pending DMA.
++ * (See "SGI Altix Architecture Considerations for Linux Device Drivers",
++ * Document Number: 007-4763-001)
++ *
+ * TODO: simplify our interface;
+ * figure out how to save dmamap handle so can use two step.
+ */
+-dma_addr_t sn_dma_map_single(struct device *dev, void *cpu_addr, size_t size,
+- int direction)
++dma_addr_t sn_dma_map_single_attrs(struct device *dev, void *cpu_addr,
++ size_t size, int direction,
++ struct dma_attrs *attrs)
+ {
+ dma_addr_t dma_addr;
+ unsigned long phys_addr;
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
++ int dmabarr;
++
++ dmabarr = dma_get_attr(DMA_ATTR_WRITE_BARRIER, attrs);
+
+ BUG_ON(dev->bus != &pci_bus_type);
+
+ phys_addr = __pa(cpu_addr);
+- dma_addr = provider->dma_map(pdev, phys_addr, size, SN_DMA_ADDR_PHYS);
++ if (dmabarr)
++ dma_addr = provider->dma_map_consistent(pdev, phys_addr,
++ size, SN_DMA_ADDR_PHYS);
++ else
++ dma_addr = provider->dma_map(pdev, phys_addr, size,
++ SN_DMA_ADDR_PHYS);
++
+ if (!dma_addr) {
+ printk(KERN_ERR "%s: out of ATEs\n", __func__);
+ return 0;
+ }
+ return dma_addr;
+ }
+-EXPORT_SYMBOL(sn_dma_map_single);
++EXPORT_SYMBOL(sn_dma_map_single_attrs);
+
+ /**
+- * sn_dma_unmap_single - unamp a DMA mapped page
++ * sn_dma_unmap_single_attrs - unamp a DMA mapped page
+ * @dev: device to sync
+ * @dma_addr: DMA address to sync
+ * @size: size of region
+ * @direction: DMA direction
++ * @attrs: optional dma attributes
+ *
+ * This routine is supposed to sync the DMA region specified
+ * by @dma_handle into the coherence domain. On SN, we're always cache
+ * coherent, so we just need to free any ATEs associated with this mapping.
+ */
+-void sn_dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+- int direction)
++void sn_dma_unmap_single_attrs(struct device *dev, dma_addr_t dma_addr,
++ size_t size, int direction,
++ struct dma_attrs *attrs)
+ {
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
+@@ -207,19 +226,21 @@ void sn_dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+
+ provider->dma_unmap(pdev, dma_addr, direction);
+ }
+-EXPORT_SYMBOL(sn_dma_unmap_single);
++EXPORT_SYMBOL(sn_dma_unmap_single_attrs);
+
+ /**
+- * sn_dma_unmap_sg - unmap a DMA scatterlist
++ * sn_dma_unmap_sg_attrs - unmap a DMA scatterlist
+ * @dev: device to unmap
+ * @sg: scatterlist to unmap
+ * @nhwentries: number of scatterlist entries
+ * @direction: DMA direction
++ * @attrs: optional dma attributes
+ *
+ * Unmap a set of streaming mode DMA translations.
+ */
+-void sn_dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
+- int nhwentries, int direction)
++void sn_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl,
++ int nhwentries, int direction,
++ struct dma_attrs *attrs)
+ {
+ int i;
+ struct pci_dev *pdev = to_pci_dev(dev);
+@@ -234,25 +255,34 @@ void sn_dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
+ sg->dma_length = 0;
+ }
+ }
+-EXPORT_SYMBOL(sn_dma_unmap_sg);
++EXPORT_SYMBOL(sn_dma_unmap_sg_attrs);
+
+ /**
+- * sn_dma_map_sg - map a scatterlist for DMA
++ * sn_dma_map_sg_attrs - map a scatterlist for DMA
+ * @dev: device to map for
+ * @sg: scatterlist to map
+ * @nhwentries: number of entries
+ * @direction: direction of the DMA transaction
++ * @attrs: optional dma attributes
++ *
++ * mappings with the DMA_ATTR_WRITE_BARRIER get mapped with
++ * dma_map_consistent() so that writes force a flush of pending DMA.
++ * (See "SGI Altix Architecture Considerations for Linux Device Drivers",
++ * Document Number: 007-4763-001)
+ *
+ * Maps each entry of @sg for DMA.
+ */
+-int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries,
+- int direction)
++int sn_dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
++ int nhwentries, int direction, struct dma_attrs *attrs)
+ {
+ unsigned long phys_addr;
+ struct scatterlist *saved_sg = sgl, *sg;
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
+ int i;
++ int dmabarr;
++
++ dmabarr = dma_get_attr(DMA_ATTR_WRITE_BARRIER, attrs);
+
+ BUG_ON(dev->bus != &pci_bus_type);
+
+@@ -260,11 +290,19 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries,
+ * Setup a DMA address for each entry in the scatterlist.
+ */
+ for_each_sg(sgl, sg, nhwentries, i) {
++ dma_addr_t dma_addr;
+ phys_addr = SG_ENT_PHYS_ADDRESS(sg);
+- sg->dma_address = provider->dma_map(pdev,
+- phys_addr, sg->length,
+- SN_DMA_ADDR_PHYS);
++ if (dmabarr)
++ dma_addr = provider->dma_map_consistent(pdev,
++ phys_addr,
++ sg->length,
++ SN_DMA_ADDR_PHYS);
++ else
++ dma_addr = provider->dma_map(pdev, phys_addr,
++ sg->length,
++ SN_DMA_ADDR_PHYS);
+
++ sg->dma_address = dma_addr;
+ if (!sg->dma_address) {
+ printk(KERN_ERR "%s: out of ATEs\n", __func__);
+
+@@ -272,7 +310,8 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries,
+ * Free any successfully allocated entries.
+ */
+ if (i > 0)
+- sn_dma_unmap_sg(dev, saved_sg, i, direction);
++ sn_dma_unmap_sg_attrs(dev, saved_sg, i,
++ direction, attrs);
+ return 0;
+ }
+
+@@ -281,7 +320,7 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries,
+
+ return nhwentries;
+ }
+-EXPORT_SYMBOL(sn_dma_map_sg);
++EXPORT_SYMBOL(sn_dma_map_sg_attrs);
+
+ void sn_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
+ size_t size, int direction)
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index 9b3c113..94e5845 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
@@ -96329,6 +115466,75 @@
devres-y = ../../../kernel/irq/devres.o
+diff --git a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c
+index 246a882..b1f012f 100644
+--- a/arch/m68k/kernel/asm-offsets.c
++++ b/arch/m68k/kernel/asm-offsets.c
+@@ -11,14 +11,12 @@
+ #include <linux/stddef.h>
+ #include <linux/sched.h>
+ #include <linux/kernel_stat.h>
++#include <linux/kbuild.h>
+ #include <asm/bootinfo.h>
+ #include <asm/irq.h>
+ #include <asm/amigahw.h>
+ #include <linux/font.h>
+
+-#define DEFINE(sym, val) \
+- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+-
+ int main(void)
+ {
+ /* offsets into the task struct */
+diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
+index 2b41245..ded7dd2 100644
+--- a/arch/m68k/kernel/ints.c
++++ b/arch/m68k/kernel/ints.c
+@@ -186,7 +186,7 @@ int setup_irq(unsigned int irq, struct irq_node *node)
+
+ if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
+ printk("%s: Incorrect IRQ %d from %s\n",
+- __FUNCTION__, irq, node->devname);
++ __func__, irq, node->devname);
+ return -ENXIO;
+ }
+
+@@ -249,7 +249,7 @@ void free_irq(unsigned int irq, void *dev_id)
+ unsigned long flags;
+
+ if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
+- printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
++ printk("%s: Incorrect IRQ %d\n", __func__, irq);
+ return;
+ }
+
+@@ -267,7 +267,7 @@ void free_irq(unsigned int irq, void *dev_id)
+ node->handler = NULL;
+ } else
+ printk("%s: Removing probably wrong IRQ %d\n",
+- __FUNCTION__, irq);
++ __func__, irq);
+
+ if (!irq_list[irq]) {
+ if (contr->shutdown)
+@@ -288,7 +288,7 @@ void enable_irq(unsigned int irq)
+
+ if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
+ printk("%s: Incorrect IRQ %d\n",
+- __FUNCTION__, irq);
++ __func__, irq);
+ return;
+ }
+
+@@ -312,7 +312,7 @@ void disable_irq(unsigned int irq)
+
+ if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
+ printk("%s: Incorrect IRQ %d\n",
+- __FUNCTION__, irq);
++ __func__, irq);
+ return;
+ }
+
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index 6fc69c7..d900e77 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
@@ -96555,6 +115761,175 @@
- moveml (%sp)+,%a0/%d0/%d1
- rts
-
+diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c
+index 5b2799e..326fb99 100644
+--- a/arch/m68k/mac/iop.c
++++ b/arch/m68k/mac/iop.c
+@@ -109,7 +109,6 @@
+ #include <linux/mm.h>
+ #include <linux/delay.h>
+ #include <linux/init.h>
+-#include <linux/proc_fs.h>
+ #include <linux/interrupt.h>
+
+ #include <asm/bootinfo.h>
+@@ -124,10 +123,6 @@
+
+ int iop_scc_present,iop_ism_present;
+
+-#ifdef CONFIG_PROC_FS
+-static int iop_get_proc_info(char *, char **, off_t, int);
+-#endif /* CONFIG_PROC_FS */
+-
+ /* structure for tracking channel listeners */
+
+ struct listener {
+@@ -299,12 +294,6 @@ void __init iop_init(void)
+ iop_listeners[IOP_NUM_ISM][i].devname = NULL;
+ iop_listeners[IOP_NUM_ISM][i].handler = NULL;
+ }
+-
+-#if 0 /* Crashing in 2.4 now, not yet sure why. --jmt */
+-#ifdef CONFIG_PROC_FS
+- create_proc_info_entry("mac_iop", 0, &proc_root, iop_get_proc_info);
+-#endif
+-#endif
+ }
+
+ /*
+@@ -637,77 +626,3 @@ irqreturn_t iop_ism_irq(int irq, void *dev_id)
+ }
+ return IRQ_HANDLED;
+ }
+-
+-#ifdef CONFIG_PROC_FS
+-
+-char *iop_chan_state(int state)
+-{
+- switch(state) {
+- case IOP_MSG_IDLE : return "idle ";
+- case IOP_MSG_NEW : return "new ";
+- case IOP_MSG_RCVD : return "received ";
+- case IOP_MSG_COMPLETE : return "completed ";
+- default : return "unknown ";
+- }
+-}
+-
+-int iop_dump_one_iop(char *buf, int iop_num, char *iop_name)
+-{
+- int i,len = 0;
+- volatile struct mac_iop *iop = iop_base[iop_num];
+-
+- len += sprintf(buf+len, "%s IOP channel states:\n\n", iop_name);
+- len += sprintf(buf+len, "## send_state recv_state device\n");
+- len += sprintf(buf+len, "------------------------------------------------\n");
+- for (i = 0 ; i < NUM_IOP_CHAN ; i++) {
+- len += sprintf(buf+len, "%2d %10s %10s %s\n", i,
+- iop_chan_state(iop_readb(iop, IOP_ADDR_SEND_STATE+i)),
+- iop_chan_state(iop_readb(iop, IOP_ADDR_RECV_STATE+i)),
+- iop_listeners[iop_num][i].handler?
+- iop_listeners[iop_num][i].devname : "");
+-
+- }
+- len += sprintf(buf+len, "\n");
+- return len;
+-}
+-
+-static int iop_get_proc_info(char *buf, char **start, off_t pos, int count)
+-{
+- int len, cnt;
+-
+- cnt = 0;
+- len = sprintf(buf, "IOPs detected:\n\n");
+-
+- if (iop_scc_present) {
+- len += sprintf(buf+len, "SCC IOP (%p): status %02X\n",
+- iop_base[IOP_NUM_SCC],
+- (uint) iop_base[IOP_NUM_SCC]->status_ctrl);
+- }
+- if (iop_ism_present) {
+- len += sprintf(buf+len, "ISM IOP (%p): status %02X\n\n",
+- iop_base[IOP_NUM_ISM],
+- (uint) iop_base[IOP_NUM_ISM]->status_ctrl);
+- }
+-
+- if (iop_scc_present) {
+- len += iop_dump_one_iop(buf+len, IOP_NUM_SCC, "SCC");
+-
+- }
+-
+- if (iop_ism_present) {
+- len += iop_dump_one_iop(buf+len, IOP_NUM_ISM, "ISM");
+-
+- }
+-
+- if (len >= pos) {
+- if (!*start) {
+- *start = buf + pos;
+- cnt = len - pos;
+- } else {
+- cnt += len;
+- }
+- }
+- return (count > cnt) ? cnt : count;
+-}
+-
+-#endif /* CONFIG_PROC_FS */
+diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c
+index 50603d3..3c943d2 100644
+--- a/arch/m68k/mac/oss.c
++++ b/arch/m68k/mac/oss.c
+@@ -190,7 +190,7 @@ void oss_irq_enable(int irq) {
+ break;
+ #ifdef DEBUG_IRQUSE
+ default:
+- printk("%s unknown irq %d\n",__FUNCTION__, irq);
++ printk("%s unknown irq %d\n", __func__, irq);
+ break;
+ #endif
+ }
+@@ -230,7 +230,7 @@ void oss_irq_disable(int irq) {
+ break;
+ #ifdef DEBUG_IRQUSE
+ default:
+- printk("%s unknown irq %d\n", __FUNCTION__, irq);
++ printk("%s unknown irq %d\n", __func__, irq);
+ break;
+ #endif
+ }
+diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
+index f42caa7..d8fb9c5 100644
+--- a/arch/m68k/mm/init.c
++++ b/arch/m68k/mm/init.c
+@@ -69,6 +69,7 @@ void __init m68k_setup_node(int node)
+ */
+
+ void *empty_zero_page;
++EXPORT_SYMBOL(empty_zero_page);
+
+ void show_mem(void)
+ {
+@@ -79,7 +80,6 @@ void show_mem(void)
+
+ printk("\nMem-info:\n");
+ show_free_areas();
+- printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ for_each_online_pgdat(pgdat) {
+ for (i = 0; i < pgdat->node_spanned_pages; i++) {
+ struct page *page = pgdat->node_mem_map + i;
+diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
+index 46161ce..9f0e3d5 100644
+--- a/arch/m68k/q40/q40ints.c
++++ b/arch/m68k/q40/q40ints.c
+@@ -47,7 +47,7 @@ static int q40_irq_startup(unsigned int irq)
+ switch (irq) {
+ case 1: case 2: case 8: case 9:
+ case 11: case 12: case 13:
+- printk("%s: ISA IRQ %d not implemented by HW\n", __FUNCTION__, irq);
++ printk("%s: ISA IRQ %d not implemented by HW\n", __func__, irq);
+ return -ENXIO;
+ }
+ return 0;
diff --git a/arch/m68k/sun3/intersil.c b/arch/m68k/sun3/intersil.c
index db359d7..0116d20 100644
--- a/arch/m68k/sun3/intersil.c
@@ -96580,6 +115955,27 @@
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_COMEMPCI) += comempci.o
+diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c
+index d97b89b..fd0c685 100644
+--- a/arch/m68knommu/kernel/asm-offsets.c
++++ b/arch/m68knommu/kernel/asm-offsets.c
+@@ -13,15 +13,11 @@
+ #include <linux/kernel_stat.h>
+ #include <linux/ptrace.h>
+ #include <linux/hardirq.h>
++#include <linux/kbuild.h>
+ #include <asm/bootinfo.h>
+ #include <asm/irq.h>
+ #include <asm/thread_info.h>
+
+-#define DEFINE(sym, val) \
+- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+-
+-#define BLANK() asm volatile("\n->" : : )
+-
+ int main(void)
+ {
+ /* offsets into the task struct */
diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
index 53fad14..39fe0a7 100644
--- a/arch/m68knommu/kernel/m68k_ksyms.c
@@ -96825,6987 +116221,17340 @@
- movel (%sp)+,%a0
- rts
-
-diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
-index 9e78e1a..6fcdb6f 100644
---- a/arch/mips/kernel/Makefile
-+++ b/arch/mips/kernel/Makefile
-@@ -5,7 +5,7 @@
- extra-y := head.o init_task.o vmlinux.lds
+diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
+index 8724ed3..e5a7c5d 100644
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -81,7 +81,9 @@ config MIPS_COBALT
+ config MACH_DECSTATION
+ bool "DECstations"
+ select BOOT_ELF32
++ select CEVT_DS1287
+ select CEVT_R4K
++ select CSRC_IOASIC
+ select CSRC_R4K
+ select CPU_DADDI_WORKAROUNDS if 64BIT
+ select CPU_R4000_WORKAROUNDS if 64BIT
+@@ -221,6 +223,7 @@ config MIPS_MALTA
+ select DMA_NONCOHERENT
+ select GENERIC_ISA_DMA
+ select IRQ_CPU
++ select IRQ_GIC
+ select HW_HAS_PCI
+ select I8253
+ select I8259
+@@ -309,12 +312,12 @@ config MACH_VR41XX
+ select GENERIC_HARDIRQS_NO__DO_IRQ
+
+ config PNX8550_JBS
+- bool "Philips PNX8550 based JBS board"
++ bool "NXP PNX8550 based JBS board"
+ select PNX8550
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+ config PNX8550_STB810
+- bool "Philips PNX8550 based STB810 board"
++ bool "NXP PNX8550 based STB810 board"
+ select PNX8550
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+@@ -612,6 +615,7 @@ config TOSHIBA_JMR3927
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+ select SYS_SUPPORTS_BIG_ENDIAN
+ select GENERIC_HARDIRQS_NO__DO_IRQ
++ select GPIO_TXX9
+
+ config TOSHIBA_RBTX4927
+ bool "Toshiba RBTX49[23]7 board"
+@@ -653,7 +657,7 @@ config TOSHIBA_RBTX4938
+ select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_KGDB
+ select GENERIC_HARDIRQS_NO__DO_IRQ
+- select GENERIC_GPIO
++ select GPIO_TXX9
+ help
+ This Toshiba board is based on the TX4938 processor. Say Y here to
+ support this machine type
+@@ -767,6 +771,9 @@ config BOOT_RAW
+ config CEVT_BCM1480
+ bool
- obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
-- ptrace.o reset.o semaphore.o setup.o signal.o syscall.o \
-+ ptrace.o reset.o setup.o signal.o syscall.o \
- time.o topology.o traps.o unaligned.o
++config CEVT_DS1287
++ bool
++
+ config CEVT_GT641XX
+ bool
- obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o
-diff --git a/arch/mips/kernel/semaphore.c b/arch/mips/kernel/semaphore.c
-deleted file mode 100644
-index 1265358..0000000
---- a/arch/mips/kernel/semaphore.c
-+++ /dev/null
-@@ -1,168 +0,0 @@
--/*
-- * MIPS-specific semaphore code.
-- *
-- * Copyright (C) 1999 Cort Dougan <cort at cs.nmt.edu>
-- * Copyright (C) 2004 Ralf Baechle <ralf at linux-mips.org>
-- *
-- * This program is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU General Public License
-- * as published by the Free Software Foundation; either version
-- * 2 of the License, or (at your option) any later version.
-- *
-- * April 2001 - Reworked by Paul Mackerras <paulus at samba.org>
-- * to eliminate the SMP races in the old version between the updates
-- * of `count' and `waking'. Now we use negative `count' values to
-- * indicate that some process(es) are waiting for the semaphore.
-- */
+@@ -782,12 +789,20 @@ config CEVT_TXX9
+ config CSRC_BCM1480
+ bool
+
++config CSRC_IOASIC
++ bool
++
+ config CSRC_R4K
+ bool
+
+ config CSRC_SB1250
+ bool
+
++config GPIO_TXX9
++ select GENERIC_GPIO
++ select HAVE_GPIO_LIB
++ bool
++
+ config CFE
+ bool
+
+@@ -840,6 +855,9 @@ config MIPS_NILE4
+ config MIPS_DISABLE_OBSOLETE_IDE
+ bool
+
++config SYNC_R4K
++ bool
++
+ config NO_IOPORT
+ def_bool n
+
+@@ -909,6 +927,9 @@ config IRQ_TXX9
+ config IRQ_GT641XX
+ bool
+
++config IRQ_GIC
++ bool
++
+ config MIPS_BOARDS_GEN
+ bool
+
+@@ -1811,6 +1832,17 @@ config NR_CPUS
+ performance should round up your number of processors to the next
+ power of two.
+
++config MIPS_CMP
++ bool "MIPS CMP framework support"
++ depends on SMP
++ select SYNC_R4K
++ select SYS_SUPPORTS_SCHED_SMT
++ select WEAK_ORDERING
++ default n
++ help
++ This is a placeholder option for the GCMP work. It will need to
++ be handled differently...
++
+ source "kernel/time/Kconfig"
+
+ #
+diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
+index fd7124c..f18cf92 100644
+--- a/arch/mips/Kconfig.debug
++++ b/arch/mips/Kconfig.debug
+@@ -73,14 +73,4 @@ config RUNTIME_DEBUG
+ include/asm-mips/debug.h for debuging macros.
+ If unsure, say N.
+
+-config MIPS_UNCACHED
+- bool "Run uncached"
+- depends on DEBUG_KERNEL && !SMP && !SGI_IP27
+- help
+- If you say Y here there kernel will disable all CPU caches. This will
+- reduce the system's performance dramatically but can help finding
+- otherwise hard to track bugs. It can also useful if you're doing
+- hardware debugging with a logic analyzer and need to see all traffic
+- on the bus.
-
--#include <linux/module.h>
+ endmenu
+diff --git a/arch/mips/Makefile b/arch/mips/Makefile
+index 1c62381..69648d0 100644
+--- a/arch/mips/Makefile
++++ b/arch/mips/Makefile
+@@ -410,21 +410,21 @@ load-$(CONFIG_CASIO_E55) += 0xffffffff80004000
+ load-$(CONFIG_TANBAC_TB022X) += 0xffffffff80000000
+
+ #
+-# Common Philips PNX8550
++# Common NXP PNX8550
+ #
+-core-$(CONFIG_SOC_PNX8550) += arch/mips/philips/pnx8550/common/
++core-$(CONFIG_SOC_PNX8550) += arch/mips/nxp/pnx8550/common/
+ cflags-$(CONFIG_SOC_PNX8550) += -Iinclude/asm-mips/mach-pnx8550
+
+ #
+-# Philips PNX8550 JBS board
++# NXP PNX8550 JBS board
+ #
+-libs-$(CONFIG_PNX8550_JBS) += arch/mips/philips/pnx8550/jbs/
++libs-$(CONFIG_PNX8550_JBS) += arch/mips/nxp/pnx8550/jbs/
+ #cflags-$(CONFIG_PNX8550_JBS) += -Iinclude/asm-mips/mach-pnx8550
+ load-$(CONFIG_PNX8550_JBS) += 0xffffffff80060000
+
+-# Philips PNX8550 STB810 board
++# NXP PNX8550 STB810 board
+ #
+-libs-$(CONFIG_PNX8550_STB810) += arch/mips/philips/pnx8550/stb810/
++libs-$(CONFIG_PNX8550_STB810) += arch/mips/nxp/pnx8550/stb810/
+ load-$(CONFIG_PNX8550_STB810) += 0xffffffff80060000
+
+ # NEC EMMA2RH boards
+diff --git a/arch/mips/au1000/common/cputable.c b/arch/mips/au1000/common/cputable.c
+index 5c0d35d..8c93a05 100644
+--- a/arch/mips/au1000/common/cputable.c
++++ b/arch/mips/au1000/common/cputable.c
+@@ -11,10 +11,7 @@
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+-#include <linux/string.h>
-#include <linux/sched.h>
+-#include <linux/threads.h>
-#include <linux/init.h>
--#include <asm/atomic.h>
--#include <asm/cpu-features.h>
--#include <asm/errno.h>
--#include <asm/semaphore.h>
--#include <asm/war.h>
--/*
-- * Atomically update sem->count.
-- * This does the equivalent of the following:
-- *
-- * old_count = sem->count;
-- * tmp = MAX(old_count, 0) + incr;
-- * sem->count = tmp;
-- * return old_count;
-- *
-- * On machines without lld/scd we need a spinlock to make the manipulation of
-- * sem->count and sem->waking atomic. Scalability isn't an issue because
-- * this lock is used on UP only so it's just an empty variable.
-- */
--static inline int __sem_update_count(struct semaphore *sem, int incr)
--{
-- int old_count, tmp;
--
-- if (cpu_has_llsc && R10000_LLSC_WAR) {
-- __asm__ __volatile__(
-- " .set mips3 \n"
-- "1: ll %0, %2 # __sem_update_count \n"
-- " sra %1, %0, 31 \n"
-- " not %1 \n"
-- " and %1, %0, %1 \n"
-- " addu %1, %1, %3 \n"
-- " sc %1, %2 \n"
-- " beqzl %1, 1b \n"
-- " .set mips0 \n"
-- : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
-- : "r" (incr), "m" (sem->count));
-- } else if (cpu_has_llsc) {
-- __asm__ __volatile__(
-- " .set mips3 \n"
-- "1: ll %0, %2 # __sem_update_count \n"
-- " sra %1, %0, 31 \n"
-- " not %1 \n"
-- " and %1, %0, %1 \n"
-- " addu %1, %1, %3 \n"
-- " sc %1, %2 \n"
-- " beqz %1, 1b \n"
-- " .set mips0 \n"
-- : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
-- : "r" (incr), "m" (sem->count));
-- } else {
-- static DEFINE_SPINLOCK(semaphore_lock);
-- unsigned long flags;
--
-- spin_lock_irqsave(&semaphore_lock, flags);
-- old_count = atomic_read(&sem->count);
-- tmp = max_t(int, old_count, 0) + incr;
-- atomic_set(&sem->count, tmp);
-- spin_unlock_irqrestore(&semaphore_lock, flags);
-- }
--
-- return old_count;
--}
--
--void __up(struct semaphore *sem)
--{
-- /*
-- * Note that we incremented count in up() before we came here,
-- * but that was ineffective since the result was <= 0, and
-- * any negative value of count is equivalent to 0.
-- * This ends up setting count to 1, unless count is now > 0
-- * (i.e. because some other cpu has called up() in the meantime),
-- * in which case we just increment count.
-- */
-- __sem_update_count(sem, 1);
-- wake_up(&sem->wait);
--}
--
--EXPORT_SYMBOL(__up);
--
--/*
-- * Note that when we come in to __down or __down_interruptible,
-- * we have already decremented count, but that decrement was
-- * ineffective since the result was < 0, and any negative value
-- * of count is equivalent to 0.
-- * Thus it is only when we decrement count from some value > 0
-- * that we have actually got the semaphore.
-- */
--void __sched __down(struct semaphore *sem)
--{
-- struct task_struct *tsk = current;
-- DECLARE_WAITQUEUE(wait, tsk);
--
-- __set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-- add_wait_queue_exclusive(&sem->wait, &wait);
--
-- /*
-- * Try to get the semaphore. If the count is > 0, then we've
-- * got the semaphore; we decrement count and exit the loop.
-- * If the count is 0 or negative, we set it to -1, indicating
-- * that we are asleep, and then sleep.
-- */
-- while (__sem_update_count(sem, -1) <= 0) {
-- schedule();
-- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-- }
-- remove_wait_queue(&sem->wait, &wait);
-- __set_task_state(tsk, TASK_RUNNING);
--
-- /*
-- * If there are any more sleepers, wake one of them up so
-- * that it can either get the semaphore, or set count to -1
-- * indicating that there are still processes sleeping.
-- */
-- wake_up(&sem->wait);
--}
--
--EXPORT_SYMBOL(__down);
--
--int __sched __down_interruptible(struct semaphore * sem)
--{
-- int retval = 0;
-- struct task_struct *tsk = current;
-- DECLARE_WAITQUEUE(wait, tsk);
--
-- __set_task_state(tsk, TASK_INTERRUPTIBLE);
-- add_wait_queue_exclusive(&sem->wait, &wait);
--
-- while (__sem_update_count(sem, -1) <= 0) {
-- if (signal_pending(current)) {
-- /*
-- * A signal is pending - give up trying.
-- * Set sem->count to 0 if it is negative,
-- * since we are no longer sleeping.
-- */
-- __sem_update_count(sem, 0);
-- retval = -EINTR;
-- break;
-- }
-- schedule();
-- set_task_state(tsk, TASK_INTERRUPTIBLE);
-- }
-- remove_wait_queue(&sem->wait, &wait);
-- __set_task_state(tsk, TASK_RUNNING);
--
-- wake_up(&sem->wait);
-- return retval;
--}
++
+ #include <asm/mach-au1x00/au1000.h>
+
+ struct cpu_spec* cur_cpu_spec[NR_CPUS];
+diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/au1000/common/dbdma.c
+index 57f17b4..53377df 100644
+--- a/arch/mips/au1000/common/dbdma.c
++++ b/arch/mips/au1000/common/dbdma.c
+@@ -31,18 +31,12 @@
+ */
+
+ #include <linux/kernel.h>
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+ #include <linux/slab.h>
+ #include <linux/spinlock.h>
+-#include <linux/string.h>
+-#include <linux/delay.h>
+ #include <linux/interrupt.h>
+ #include <linux/module.h>
+ #include <asm/mach-au1x00/au1000.h>
+ #include <asm/mach-au1x00/au1xxx_dbdma.h>
+-#include <asm/system.h>
-
--EXPORT_SYMBOL(__down_interruptible);
-diff --git a/arch/mips/sgi-ip27/ip27-console.c b/arch/mips/sgi-ip27/ip27-console.c
-index 3ba8306..984e561 100644
---- a/arch/mips/sgi-ip27/ip27-console.c
-+++ b/arch/mips/sgi-ip27/ip27-console.c
-@@ -8,7 +8,6 @@
- #include <linux/init.h>
- #include <asm/page.h>
--#include <asm/semaphore.h>
- #include <asm/sn/addrs.h>
- #include <asm/sn/sn0/hub.h>
- #include <asm/sn/klconfig.h>
-diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile
-index ef07c95..23f2ab6 100644
---- a/arch/mn10300/kernel/Makefile
-+++ b/arch/mn10300/kernel/Makefile
-@@ -3,7 +3,7 @@
- #
- extra-y := head.o init_task.o vmlinux.lds
+ #if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
--obj-y := process.o semaphore.o signal.o entry.o fpu.o traps.o irq.o \
-+obj-y := process.o signal.o entry.o fpu.o traps.o irq.o \
- ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \
- switch_to.o mn10300_ksyms.o kernel_execve.o
+diff --git a/arch/mips/au1000/common/dbg_io.c b/arch/mips/au1000/common/dbg_io.c
+index 79e0b0a..eae1bb2 100644
+--- a/arch/mips/au1000/common/dbg_io.c
++++ b/arch/mips/au1000/common/dbg_io.c
+@@ -1,5 +1,4 @@
-diff --git a/arch/mn10300/kernel/semaphore.c b/arch/mn10300/kernel/semaphore.c
-deleted file mode 100644
-index 9153c40..0000000
---- a/arch/mn10300/kernel/semaphore.c
-+++ /dev/null
-@@ -1,149 +0,0 @@
--/* MN10300 Semaphore implementation
-- *
-- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
-- * Written by David Howells (dhowells at redhat.com)
-- *
-- * This program is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU General Public Licence
-- * as published by the Free Software Foundation; either version
-- * 2 of the Licence, or (at your option) any later version.
-- */
+-#include <asm/io.h>
+ #include <asm/mach-au1x00/au1000.h>
+
+ #ifdef CONFIG_KGDB
+@@ -55,8 +54,7 @@ typedef unsigned int uint32;
+ #define UART16550_READ(y) (au_readl(DEBUG_BASE + y) & 0xff)
+ #define UART16550_WRITE(y, z) (au_writel(z&0xff, DEBUG_BASE + y))
+
+-extern unsigned long get_au1x00_uart_baud_base(void);
+-extern unsigned long cal_r4koff(void);
++extern unsigned long calc_clock(void);
+
+ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+ {
+@@ -64,7 +62,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+ if (UART16550_READ(UART_MOD_CNTRL) != 0x3) {
+ UART16550_WRITE(UART_MOD_CNTRL, 3);
+ }
+- cal_r4koff();
++ calc_clock();
+
+ /* disable interrupts */
+ UART16550_WRITE(UART_IER, 0);
+diff --git a/arch/mips/au1000/common/dma.c b/arch/mips/au1000/common/dma.c
+index c78260d..95f69ea 100644
+--- a/arch/mips/au1000/common/dma.c
++++ b/arch/mips/au1000/common/dma.c
+@@ -33,12 +33,9 @@
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
-#include <linux/sched.h>
--#include <linux/module.h>
--#include <asm/semaphore.h>
--
--struct sem_waiter {
-- struct list_head list;
-- struct task_struct *task;
--};
--
--#if SEMAPHORE_DEBUG
--void semtrace(struct semaphore *sem, const char *str)
--{
-- if (sem->debug)
-- printk(KERN_DEBUG "[%d] %s({%d,%d})\n",
-- current->pid,
-- str,
-- atomic_read(&sem->count),
-- list_empty(&sem->wait_list) ? 0 : 1);
--}
--#else
--#define semtrace(SEM, STR) do { } while (0)
--#endif
--
--/*
-- * wait for a token to be granted from a semaphore
-- * - entered with lock held and interrupts disabled
-- */
--void __down(struct semaphore *sem, unsigned long flags)
--{
-- struct task_struct *tsk = current;
-- struct sem_waiter waiter;
--
-- semtrace(sem, "Entering __down");
--
-- /* set up my own style of waitqueue */
-- waiter.task = tsk;
-- get_task_struct(tsk);
--
-- list_add_tail(&waiter.list, &sem->wait_list);
--
-- /* we don't need to touch the semaphore struct anymore */
-- spin_unlock_irqrestore(&sem->wait_lock, flags);
--
-- /* wait to be given the semaphore */
-- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
--
-- for (;;) {
-- if (!waiter.task)
-- break;
-- schedule();
-- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-- }
--
-- tsk->state = TASK_RUNNING;
-- semtrace(sem, "Leaving __down");
--}
--EXPORT_SYMBOL(__down);
--
--/*
-- * interruptibly wait for a token to be granted from a semaphore
-- * - entered with lock held and interrupts disabled
-- */
--int __down_interruptible(struct semaphore *sem, unsigned long flags)
--{
-- struct task_struct *tsk = current;
-- struct sem_waiter waiter;
-- int ret;
--
-- semtrace(sem, "Entering __down_interruptible");
--
-- /* set up my own style of waitqueue */
-- waiter.task = tsk;
-- get_task_struct(tsk);
--
-- list_add_tail(&waiter.list, &sem->wait_list);
--
-- /* we don't need to touch the semaphore struct anymore */
-- set_task_state(tsk, TASK_INTERRUPTIBLE);
--
-- spin_unlock_irqrestore(&sem->wait_lock, flags);
+ #include <linux/spinlock.h>
+-#include <linux/string.h>
+-#include <linux/delay.h>
+ #include <linux/interrupt.h>
+-#include <asm/system.h>
++
+ #include <asm/mach-au1x00/au1000.h>
+ #include <asm/mach-au1x00/au1000_dma.h>
+
+diff --git a/arch/mips/au1000/common/gpio.c b/arch/mips/au1000/common/gpio.c
+index 0b658f1..5254525 100644
+--- a/arch/mips/au1000/common/gpio.c
++++ b/arch/mips/au1000/common/gpio.c
+@@ -27,13 +27,8 @@
+ * others have a second one : GPIO2
+ */
+
+-#include <linux/init.h>
+-#include <linux/io.h>
+-#include <linux/types.h>
+ #include <linux/module.h>
+
+-#include <asm/addrspace.h>
-
-- /* wait to be given the semaphore */
-- ret = 0;
-- for (;;) {
-- if (!waiter.task)
-- break;
-- if (unlikely(signal_pending(current)))
-- goto interrupted;
-- schedule();
-- set_task_state(tsk, TASK_INTERRUPTIBLE);
+ #include <asm/mach-au1x00/au1000.h>
+ #include <asm/gpio.h>
+
+diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c
+index 3c7714f..f062699 100644
+--- a/arch/mips/au1000/common/irq.c
++++ b/arch/mips/au1000/common/irq.c
+@@ -1,7 +1,6 @@
+ /*
+- * Copyright 2001 MontaVista Software Inc.
+- * Author: MontaVista Software, Inc.
+- * ppopov at mvista.com or source at mvista.com
++ * Copyright 2001, 2007-2008 MontaVista Software Inc.
++ * Author: MontaVista Software, Inc. <source at mvista.com>
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf at linux-mips.org)
+ *
+@@ -27,7 +26,6 @@
+ */
+ #include <linux/bitops.h>
+ #include <linux/init.h>
+-#include <linux/io.h>
+ #include <linux/interrupt.h>
+ #include <linux/irq.h>
+
+@@ -591,7 +589,7 @@ void __init arch_init_irq(void)
+ imp++;
+ }
+
+- set_c0_status(ALLINTS);
++ set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
+
+ /* Board specific IRQ initialization.
+ */
+diff --git a/arch/mips/au1000/common/pci.c b/arch/mips/au1000/common/pci.c
+index ce77148..7e966b3 100644
+--- a/arch/mips/au1000/common/pci.c
++++ b/arch/mips/au1000/common/pci.c
+@@ -30,7 +30,7 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+-#include <linux/types.h>
++
+ #include <linux/pci.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/au1000/common/platform.c
+index 39d6812..31d2a22 100644
+--- a/arch/mips/au1000/common/platform.c
++++ b/arch/mips/au1000/common/platform.c
+@@ -3,18 +3,65 @@
+ *
+ * Copyright 2004, Matt Porter <mporter at kernel.crashing.org>
+ *
++ * (C) Copyright Embedded Alley Solutions, Inc 2005
++ * Author: Pantelis Antoniou <pantelis at embeddedalley.com>
++ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+-#include <linux/device.h>
++
+ #include <linux/platform_device.h>
+-#include <linux/kernel.h>
++#include <linux/serial_8250.h>
+ #include <linux/init.h>
+-#include <linux/resource.h>
+
+ #include <asm/mach-au1x00/au1xxx.h>
+
++#define PORT(_base, _irq) \
++ { \
++ .iobase = _base, \
++ .membase = (void __iomem *)_base,\
++ .mapbase = CPHYSADDR(_base), \
++ .irq = _irq, \
++ .regshift = 2, \
++ .iotype = UPIO_AU, \
++ .flags = UPF_SKIP_TEST \
++ }
++
++static struct plat_serial8250_port au1x00_uart_data[] = {
++#if defined(CONFIG_SERIAL_8250_AU1X00)
++#if defined(CONFIG_SOC_AU1000)
++ PORT(UART0_ADDR, AU1000_UART0_INT),
++ PORT(UART1_ADDR, AU1000_UART1_INT),
++ PORT(UART2_ADDR, AU1000_UART2_INT),
++ PORT(UART3_ADDR, AU1000_UART3_INT),
++#elif defined(CONFIG_SOC_AU1500)
++ PORT(UART0_ADDR, AU1500_UART0_INT),
++ PORT(UART3_ADDR, AU1500_UART3_INT),
++#elif defined(CONFIG_SOC_AU1100)
++ PORT(UART0_ADDR, AU1100_UART0_INT),
++ PORT(UART1_ADDR, AU1100_UART1_INT),
++ PORT(UART3_ADDR, AU1100_UART3_INT),
++#elif defined(CONFIG_SOC_AU1550)
++ PORT(UART0_ADDR, AU1550_UART0_INT),
++ PORT(UART1_ADDR, AU1550_UART1_INT),
++ PORT(UART3_ADDR, AU1550_UART3_INT),
++#elif defined(CONFIG_SOC_AU1200)
++ PORT(UART0_ADDR, AU1200_UART0_INT),
++ PORT(UART1_ADDR, AU1200_UART1_INT),
++#endif
++#endif /* CONFIG_SERIAL_8250_AU1X00 */
++ { },
++};
++
++static struct platform_device au1xx0_uart_device = {
++ .name = "serial8250",
++ .id = PLAT8250_DEV_AU1X00,
++ .dev = {
++ .platform_data = au1x00_uart_data,
++ },
++};
++
+ /* OHCI (USB full speed host controller) */
+ static struct resource au1xxx_usb_ohci_resources[] = {
+ [0] = {
+@@ -186,19 +233,6 @@ static struct resource au1200_lcd_resources[] = {
+ }
+ };
+
+-static struct resource au1200_ide0_resources[] = {
+- [0] = {
+- .start = AU1XXX_ATA_PHYS_ADDR,
+- .end = AU1XXX_ATA_PHYS_ADDR + AU1XXX_ATA_PHYS_LEN - 1,
+- .flags = IORESOURCE_MEM,
+- },
+- [1] = {
+- .start = AU1XXX_ATA_INT,
+- .end = AU1XXX_ATA_INT,
+- .flags = IORESOURCE_IRQ,
- }
+-};
-
-- out:
-- tsk->state = TASK_RUNNING;
-- semtrace(sem, "Leaving __down_interruptible");
-- return ret;
+ static u64 au1200_lcd_dmamask = ~(u32)0;
+
+ static struct platform_device au1200_lcd_device = {
+@@ -212,20 +246,6 @@ static struct platform_device au1200_lcd_device = {
+ .resource = au1200_lcd_resources,
+ };
+
-
-- interrupted:
-- spin_lock_irqsave(&sem->wait_lock, flags);
-- list_del(&waiter.list);
-- spin_unlock_irqrestore(&sem->wait_lock, flags);
+-static u64 ide0_dmamask = ~(u32)0;
-
-- ret = 0;
-- if (!waiter.task) {
-- put_task_struct(current);
-- ret = -EINTR;
-- }
-- goto out;
--}
--EXPORT_SYMBOL(__down_interruptible);
+-static struct platform_device au1200_ide0_device = {
+- .name = "au1200-ide",
+- .id = 0,
+- .dev = {
+- .dma_mask = &ide0_dmamask,
+- .coherent_dma_mask = 0xffffffff,
+- },
+- .num_resources = ARRAY_SIZE(au1200_ide0_resources),
+- .resource = au1200_ide0_resources,
+-};
-
--/*
-- * release a single token back to a semaphore
-- * - entered with lock held and interrupts disabled
-- */
--void __up(struct semaphore *sem)
--{
-- struct task_struct *tsk;
-- struct sem_waiter *waiter;
+ static u64 au1xxx_mmc_dmamask = ~(u32)0;
+
+ static struct platform_device au1xxx_mmc_device = {
+@@ -245,31 +265,6 @@ static struct platform_device au1x00_pcmcia_device = {
+ .id = 0,
+ };
+
+-#ifdef CONFIG_MIPS_DB1200
-
-- semtrace(sem, "Entering __up");
+-static struct resource smc91x_resources[] = {
+- [0] = {
+- .name = "smc91x-regs",
+- .start = AU1XXX_SMC91111_PHYS_ADDR,
+- .end = AU1XXX_SMC91111_PHYS_ADDR + 0xfffff,
+- .flags = IORESOURCE_MEM,
+- },
+- [1] = {
+- .start = AU1XXX_SMC91111_IRQ,
+- .end = AU1XXX_SMC91111_IRQ,
+- .flags = IORESOURCE_IRQ,
+- },
+-};
-
-- /* grant the token to the process at the front of the queue */
-- waiter = list_entry(sem->wait_list.next, struct sem_waiter, list);
+-static struct platform_device smc91x_device = {
+- .name = "smc91x",
+- .id = -1,
+- .num_resources = ARRAY_SIZE(smc91x_resources),
+- .resource = smc91x_resources,
+-};
-
-- /* We must be careful not to touch 'waiter' after we set ->task = NULL.
-- * It is an allocated on the waiter's stack and may become invalid at
-- * any time after that point (due to a wakeup from another source).
-- */
-- list_del_init(&waiter->list);
-- tsk = waiter->task;
-- smp_mb();
-- waiter->task = NULL;
-- wake_up_process(tsk);
-- put_task_struct(tsk);
+-#endif
-
-- semtrace(sem, "Leaving __up");
--}
--EXPORT_SYMBOL(__up);
-diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.h b/arch/mn10300/unit-asb2305/pci-asb2305.h
-index 84634fa..9763d1c 100644
---- a/arch/mn10300/unit-asb2305/pci-asb2305.h
-+++ b/arch/mn10300/unit-asb2305/pci-asb2305.h
-@@ -23,8 +23,6 @@
- #define PCI_PROBE_BIOS 1
- #define PCI_PROBE_CONF1 2
- #define PCI_PROBE_CONF2 4
--#define PCI_NO_SORT 0x100
--#define PCI_BIOS_SORT 0x200
- #define PCI_NO_CHECKS 0x400
- #define PCI_ASSIGN_ROMS 0x1000
- #define PCI_BIOS_IRQ_SCAN 0x2000
-diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
-index 27827bc..1f6585a 100644
---- a/arch/parisc/kernel/Makefile
-+++ b/arch/parisc/kernel/Makefile
-@@ -9,7 +9,7 @@ AFLAGS_pacache.o := -traditional
+ /* All Alchemy demoboards with I2C have this #define in their headers */
+ #ifdef SMBUS_PSC_BASE
+ static struct resource pbdb_smbus_resources[] = {
+@@ -289,6 +284,7 @@ static struct platform_device pbdb_smbus_device = {
+ #endif
- obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \
- pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
-- ptrace.o hardware.o inventory.o drivers.o semaphore.o \
-+ ptrace.o hardware.o inventory.o drivers.o \
- signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \
- process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \
- topology.o
-diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
-index 7aca704..5b7fc4a 100644
---- a/arch/parisc/kernel/parisc_ksyms.c
-+++ b/arch/parisc/kernel/parisc_ksyms.c
-@@ -69,11 +69,6 @@ EXPORT_SYMBOL(memcpy_toio);
- EXPORT_SYMBOL(memcpy_fromio);
- EXPORT_SYMBOL(memset_io);
+ static struct platform_device *au1xxx_platform_devices[] __initdata = {
++ &au1xx0_uart_device,
+ &au1xxx_usb_ohci_device,
+ &au1x00_pcmcia_device,
+ #ifdef CONFIG_FB_AU1100
+@@ -299,12 +295,8 @@ static struct platform_device *au1xxx_platform_devices[] __initdata = {
+ &au1xxx_usb_gdt_device,
+ &au1xxx_usb_otg_device,
+ &au1200_lcd_device,
+- &au1200_ide0_device,
+ &au1xxx_mmc_device,
+ #endif
+-#ifdef CONFIG_MIPS_DB1200
+- &smc91x_device,
+-#endif
+ #ifdef SMBUS_PSC_BASE
+ &pbdb_smbus_device,
+ #endif
+@@ -312,6 +304,13 @@ static struct platform_device *au1xxx_platform_devices[] __initdata = {
--#include <asm/semaphore.h>
--EXPORT_SYMBOL(__up);
--EXPORT_SYMBOL(__down_interruptible);
--EXPORT_SYMBOL(__down);
--
- extern void $$divI(void);
- extern void $$divU(void);
- extern void $$remI(void);
-diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
-index 507d0ac..6936386 100644
---- a/arch/parisc/kernel/pci.c
-+++ b/arch/parisc/kernel/pci.c
-@@ -287,23 +287,15 @@ void pcibios_align_resource(void *data, struct resource *res,
- */
- int pcibios_enable_device(struct pci_dev *dev, int mask)
+ int __init au1xxx_platform_init(void)
{
-- u16 cmd;
-- int idx;
-+ int err;
-+ u16 cmd, old_cmd;
++ unsigned int uartclk = get_au1x00_uart_baud_base() * 16;
++ int i;
++
++ /* Fill up uartclk. */
++ for (i = 0; au1x00_uart_data[i].flags ; i++)
++ au1x00_uart_data[i].uartclk = uartclk;
++
+ return platform_add_devices(au1xxx_platform_devices, ARRAY_SIZE(au1xxx_platform_devices));
+ }
-- pci_read_config_word(dev, PCI_COMMAND, &cmd);
--
-- for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) {
-- struct resource *r = &dev->resource[idx];
-+ err = pci_enable_resources(dev, mask);
-+ if (err < 0)
-+ return err;
+diff --git a/arch/mips/au1000/common/power.c b/arch/mips/au1000/common/power.c
+index 54047d6..a8cd2c1 100644
+--- a/arch/mips/au1000/common/power.c
++++ b/arch/mips/au1000/common/power.c
+@@ -29,17 +29,14 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
++
+ #include <linux/init.h>
+ #include <linux/pm.h>
+ #include <linux/pm_legacy.h>
+-#include <linux/slab.h>
+ #include <linux/sysctl.h>
+ #include <linux/jiffies.h>
-- /* only setup requested resources */
-- if (!(mask & (1<<idx)))
-- continue;
--
-- if (r->flags & IORESOURCE_IO)
-- cmd |= PCI_COMMAND_IO;
-- if (r->flags & IORESOURCE_MEM)
-- cmd |= PCI_COMMAND_MEMORY;
-- }
-+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
-+ old_cmd = cmd;
+-#include <asm/string.h>
+ #include <asm/uaccess.h>
+-#include <asm/io.h>
+-#include <asm/system.h>
+ #include <asm/cacheflush.h>
+ #include <asm/mach-au1x00/au1000.h>
- cmd |= (PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
+@@ -47,17 +44,13 @@
-@@ -312,8 +304,12 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
- if (dev->bus->bridge_ctl & PCI_BRIDGE_CTL_FAST_BACK)
- cmd |= PCI_COMMAND_FAST_BACK;
+ #define DEBUG 1
+ #ifdef DEBUG
+-# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
++# define DPRINTK(fmt, args...) printk("%s: " fmt, __func__, ## args)
+ #else
+ # define DPRINTK(fmt, args...)
#endif
-- DBGC("PCIBIOS: Enabling device %s cmd 0x%04x\n", pci_name(dev), cmd);
-- pci_write_config_word(dev, PCI_COMMAND, cmd);
-+
-+ if (cmd != old_cmd) {
-+ dev_info(&dev->dev, "enabling SERR and PARITY (%04x -> %04x)\n",
-+ old_cmd, cmd);
-+ pci_write_config_word(dev, PCI_COMMAND, cmd);
-+ }
- return 0;
- }
-diff --git a/arch/parisc/kernel/semaphore.c b/arch/parisc/kernel/semaphore.c
-deleted file mode 100644
-index ee806bc..0000000
---- a/arch/parisc/kernel/semaphore.c
-+++ /dev/null
-@@ -1,102 +0,0 @@
--/*
-- * Semaphore implementation Copyright (c) 2001 Matthew Wilcox, Hewlett-Packard
-- */
--
--#include <linux/sched.h>
--#include <linux/spinlock.h>
--#include <linux/errno.h>
--#include <linux/init.h>
--
--/*
-- * Semaphores are complex as we wish to avoid using two variables.
-- * `count' has multiple roles, depending on its value. If it is positive
-- * or zero, there are no waiters. The functions here will never be
-- * called; see <asm/semaphore.h>
-- *
-- * When count is -1 it indicates there is at least one task waiting
-- * for the semaphore.
-- *
-- * When count is less than that, there are '- count - 1' wakeups
-- * pending. ie if it has value -3, there are 2 wakeups pending.
-- *
-- * Note that these functions are only called when there is contention
-- * on the lock, and as such all this is the "non-critical" part of the
-- * whole semaphore business. The critical part is the inline stuff in
-- * <asm/semaphore.h> where we want to avoid any extra jumps and calls.
-- */
--void __up(struct semaphore *sem)
--{
-- sem->count--;
-- wake_up(&sem->wait);
--}
--
--#define wakers(count) (-1 - count)
--
--#define DOWN_HEAD \
-- int ret = 0; \
-- DECLARE_WAITQUEUE(wait, current); \
-- \
-- /* Note that someone is waiting */ \
-- if (sem->count == 0) \
-- sem->count = -1; \
-- \
-- /* protected by the sentry still -- use unlocked version */ \
-- wait.flags = WQ_FLAG_EXCLUSIVE; \
-- __add_wait_queue_tail(&sem->wait, &wait); \
-- lost_race: \
-- spin_unlock_irq(&sem->sentry); \
--
--#define DOWN_TAIL \
-- spin_lock_irq(&sem->sentry); \
-- if (wakers(sem->count) == 0 && ret == 0) \
-- goto lost_race; /* Someone stole our wakeup */ \
-- __remove_wait_queue(&sem->wait, &wait); \
-- current->state = TASK_RUNNING; \
-- if (!waitqueue_active(&sem->wait) && (sem->count < 0)) \
-- sem->count = wakers(sem->count);
--
--#define UPDATE_COUNT \
-- sem->count += (sem->count < 0) ? 1 : - 1;
--
--
--void __sched __down(struct semaphore * sem)
--{
-- DOWN_HEAD
--
-- for(;;) {
-- set_task_state(current, TASK_UNINTERRUPTIBLE);
-- /* we can _read_ this without the sentry */
-- if (sem->count != -1)
-- break;
-- schedule();
-- }
+ static void au1000_calibrate_delay(void);
+
+-extern void set_au1x00_speed(unsigned int new_freq);
+-extern unsigned int get_au1x00_speed(void);
+-extern unsigned long get_au1x00_uart_baud_base(void);
+-extern void set_au1x00_uart_baud_base(unsigned long new_baud_base);
+ extern unsigned long save_local_and_disable(int controller);
+ extern void restore_local_and_enable(int controller, unsigned long mask);
+ extern void local_enable_irq(unsigned int irq_nr);
+@@ -258,7 +251,6 @@ int au_sleep(void)
+ static int pm_do_sleep(ctl_table * ctl, int write, struct file *file,
+ void __user *buffer, size_t * len, loff_t *ppos)
+ {
+- int retval = 0;
+ #ifdef SLEEP_TEST_TIMEOUT
+ #define TMPBUFLEN2 16
+ char buf[TMPBUFLEN2], *p;
+@@ -278,36 +270,12 @@ static int pm_do_sleep(ctl_table * ctl, int write, struct file *file,
+ p = buf;
+ sleep_ticks = simple_strtoul(p, &p, 0);
+ #endif
+- retval = pm_send_all(PM_SUSPEND, (void *) 2);
-
-- DOWN_TAIL
-- UPDATE_COUNT
+- if (retval)
+- return retval;
+
+ au_sleep();
+- retval = pm_send_all(PM_RESUME, (void *) 0);
+- }
+- return retval;
-}
-
--int __sched __down_interruptible(struct semaphore * sem)
+-static int pm_do_suspend(ctl_table * ctl, int write, struct file *file,
+- void __user *buffer, size_t * len, loff_t *ppos)
-{
-- DOWN_HEAD
--
-- for(;;) {
-- set_task_state(current, TASK_INTERRUPTIBLE);
-- /* we can _read_ this without the sentry */
-- if (sem->count != -1)
-- break;
--
-- if (signal_pending(current)) {
-- ret = -EINTR;
-- break;
-- }
-- schedule();
-- }
+- int retval = 0;
-
-- DOWN_TAIL
+- if (!write) {
+- *len = 0;
+- } else {
+- retval = pm_send_all(PM_SUSPEND, (void *) 2);
+- if (retval)
+- return retval;
+- suspend_mode = 1;
-
-- if (!ret) {
-- UPDATE_COUNT
-- }
+- retval = pm_send_all(PM_RESUME, (void *) 0);
+ }
+- return retval;
++ return 0;
+ }
+
-
-- return ret;
--}
-diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
-index 50bbf33..71efd6a 100644
---- a/arch/parisc/kernel/sys_parisc32.c
-+++ b/arch/parisc/kernel/sys_parisc32.c
-@@ -49,7 +49,6 @@
+ static int pm_do_freq(ctl_table * ctl, int write, struct file *file,
+ void __user *buffer, size_t * len, loff_t *ppos)
+ {
+@@ -421,14 +389,6 @@ static int pm_do_freq(ctl_table * ctl, int write, struct file *file,
- #include <asm/types.h>
- #include <asm/uaccess.h>
--#include <asm/semaphore.h>
- #include <asm/mmu_context.h>
+ static struct ctl_table pm_table[] = {
+ {
+- .ctl_name = CTL_UNNUMBERED,
+- .procname = "suspend",
+- .data = NULL,
+- .maxlen = 0,
+- .mode = 0600,
+- .proc_handler = &pm_do_suspend
+- },
+- {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sleep",
+ .data = NULL,
+diff --git a/arch/mips/au1000/common/prom.c b/arch/mips/au1000/common/prom.c
+index 90d7069..f10af82 100644
+--- a/arch/mips/au1000/common/prom.c
++++ b/arch/mips/au1000/common/prom.c
+@@ -33,8 +33,8 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
++
+ #include <linux/module.h>
+-#include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/string.h>
- #include "sys32.h"
-diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
-index 1189d8d..20f45a8 100644
---- a/arch/powerpc/Kconfig
-+++ b/arch/powerpc/Kconfig
-@@ -49,6 +49,19 @@ config IRQ_PER_CPU
- bool
- default y
+diff --git a/arch/mips/au1000/common/puts.c b/arch/mips/au1000/common/puts.c
+index 2705829..e34c67e 100644
+--- a/arch/mips/au1000/common/puts.c
++++ b/arch/mips/au1000/common/puts.c
+@@ -28,7 +28,6 @@
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
-+config STACKTRACE_SUPPORT
-+ bool
-+ default y
-+
-+config TRACE_IRQFLAGS_SUPPORT
-+ bool
-+ depends on PPC64
-+ default y
+-#include <linux/types.h>
+ #include <asm/mach-au1x00/au1000.h>
+
+ #define SERIAL_BASE UART_BASE
+diff --git a/arch/mips/au1000/common/reset.c b/arch/mips/au1000/common/reset.c
+index b8638d2..60cec53 100644
+--- a/arch/mips/au1000/common/reset.c
++++ b/arch/mips/au1000/common/reset.c
+@@ -27,13 +27,7 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+-#include <linux/sched.h>
+-#include <linux/mm.h>
+-#include <asm/io.h>
+-#include <asm/pgtable.h>
+-#include <asm/processor.h>
+-#include <asm/reboot.h>
+-#include <asm/system.h>
+
-+config LOCKDEP_SUPPORT
-+ bool
-+ default y
+ #include <asm/mach-au1x00/au1000.h>
+
+ extern int au_sleep(void);
+diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c
+index 9e4ab80..0e86f7a 100644
+--- a/arch/mips/au1000/common/setup.c
++++ b/arch/mips/au1000/common/setup.c
+@@ -25,21 +25,14 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
- config RWSEM_GENERIC_SPINLOCK
- bool
+ #include <linux/init.h>
+-#include <linux/sched.h>
+ #include <linux/ioport.h>
+-#include <linux/mm.h>
+-#include <linux/delay.h>
+-#include <linux/interrupt.h>
+ #include <linux/module.h>
+ #include <linux/pm.h>
-@@ -81,6 +94,11 @@ config GENERIC_FIND_NEXT_BIT
- bool
- default y
+-#include <asm/cpu.h>
+-#include <asm/bootinfo.h>
+-#include <asm/irq.h>
+ #include <asm/mipsregs.h>
+ #include <asm/reboot.h>
+-#include <asm/pgtable.h>
+ #include <asm/time.h>
-+config GENERIC_GPIO
-+ bool
-+ help
-+ Generic GPIO API support
+ #include <au1000.h>
+@@ -49,8 +42,6 @@ extern void __init board_setup(void);
+ extern void au1000_restart(char *);
+ extern void au1000_halt(void);
+ extern void au1000_power_off(void);
+-extern void au1x_time_init(void);
+-extern void au1x_timer_setup(struct irqaction *irq);
+ extern void set_cpuspec(void);
+
+ void __init plat_mem_setup(void)
+diff --git a/arch/mips/au1000/common/sleeper.S b/arch/mips/au1000/common/sleeper.S
+index 683d9da..4b3cf02 100644
+--- a/arch/mips/au1000/common/sleeper.S
++++ b/arch/mips/au1000/common/sleeper.S
+@@ -9,9 +9,9 @@
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
- config ARCH_NO_VIRT_TO_BUS
- def_bool PPC64
+ #include <asm/asm.h>
+ #include <asm/mipsregs.h>
+-#include <asm/addrspace.h>
+ #include <asm/regdef.h>
+ #include <asm/stackframe.h>
+
+diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c
+index e122bbc..bdb6d73 100644
+--- a/arch/mips/au1000/common/time.c
++++ b/arch/mips/au1000/common/time.c
+@@ -1,6 +1,6 @@
+ /*
+ *
+- * Copyright (C) 2001 MontaVista Software, ppopov at mvista.com
++ * Copyright (C) 2001, 2006, 2008 MontaVista Software, <source at mvista.com>
+ * Copied and modified Carsten Langgaard's time.c
+ *
+ * Carsten Langgaard, carstenl at mips.com
+@@ -34,23 +34,13 @@
-@@ -91,6 +109,7 @@ config PPC
- select HAVE_OPROFILE
- select HAVE_KPROBES
- select HAVE_KRETPROBES
-+ select HAVE_LMB
+ #include <linux/types.h>
+ #include <linux/init.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/sched.h>
+ #include <linux/spinlock.h>
+-#include <linux/hardirq.h>
- config EARLY_PRINTK
- bool
-@@ -210,15 +229,6 @@ source kernel/Kconfig.hz
- source kernel/Kconfig.preempt
- source "fs/Kconfig.binfmt"
+-#include <asm/compiler.h>
+ #include <asm/mipsregs.h>
+ #include <asm/time.h>
+-#include <asm/div64.h>
+ #include <asm/mach-au1x00/au1000.h>
--# We optimistically allocate largepages from the VM, so make the limit
--# large enough (16MB). This badly named config option is actually
--# max order + 1
--config FORCE_MAX_ZONEORDER
-- int
-- depends on PPC64
-- default "9" if PPC_64K_PAGES
-- default "13"
+-#include <linux/mc146818rtc.h>
+-#include <linux/timex.h>
-
- config HUGETLB_PAGE_SIZE_VARIABLE
- bool
- depends on HUGETLB_PAGE
-@@ -307,6 +317,16 @@ config CRASH_DUMP
+-static unsigned long r4k_offset; /* Amount to increment compare reg each time */
+-static unsigned long r4k_cur; /* What counter should be at next timer irq */
+-int no_au1xxx_32khz;
++static int no_au1xxx_32khz;
+ extern int allow_au1k_wait; /* default off for CP0 Counter */
- Don't change this unless you know what you are doing.
+ #ifdef CONFIG_PM
+@@ -184,7 +174,7 @@ wakeup_counter0_set(int ticks)
+ * "wait" is enabled, and we need to detect if the 32KHz isn't present
+ * but requested......got it? :-) -- Dan
+ */
+-unsigned long cal_r4koff(void)
++unsigned long calc_clock(void)
+ {
+ unsigned long cpu_speed;
+ unsigned long flags;
+@@ -229,19 +219,13 @@ unsigned long cal_r4koff(void)
+ // Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16)
+ set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16));
+ spin_unlock_irqrestore(&time_lock, flags);
+- return (cpu_speed / HZ);
++ return cpu_speed;
+ }
+
+ void __init plat_time_init(void)
+ {
+- unsigned int est_freq;
+-
+- printk("calculating r4koff... ");
+- r4k_offset = cal_r4koff();
+- printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);
++ unsigned int est_freq = calc_clock();
+
+- //est_freq = 2*r4k_offset*HZ;
+- est_freq = r4k_offset*HZ;
+ est_freq += 5000; /* round */
+ est_freq -= est_freq%10000;
+ printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
+@@ -249,9 +233,6 @@ void __init plat_time_init(void)
+ set_au1x00_speed(est_freq);
+ set_au1x00_lcd_clock(); // program the LCD clock
-+config PHYP_DUMP
-+ bool "Hypervisor-assisted dump (EXPERIMENTAL)"
-+ depends on PPC_PSERIES && EXPERIMENTAL
-+ help
-+ Hypervisor-assisted dump is meant to be a kdump replacement
-+ offering robustness and speed not possible without system
-+ hypervisor assistence.
+- r4k_cur = (read_c0_count() + r4k_offset);
+- write_c0_compare(r4k_cur);
+-
+ #ifdef CONFIG_PM
+ /*
+ * setup counter 0, since it keeps ticking after a
+@@ -265,12 +246,8 @@ void __init plat_time_init(void)
+ * Check to ensure we really have a 32KHz oscillator before
+ * we do this.
+ */
+- if (no_au1xxx_32khz) {
++ if (no_au1xxx_32khz)
+ printk("WARNING: no 32KHz clock found.\n");
+-
+- /* Ensure we get CPO_COUNTER interrupts. */
+- set_c0_status(IE_IRQ5);
+- }
+ else {
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
+ au_writel(0, SYS_TOYWRITE);
+diff --git a/arch/mips/au1000/db1x00/board_setup.c b/arch/mips/au1000/db1x00/board_setup.c
+index 99eafea..b7dcbad 100644
+--- a/arch/mips/au1000/db1x00/board_setup.c
++++ b/arch/mips/au1000/db1x00/board_setup.c
+@@ -27,20 +27,9 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
-+ If unsure, say "N"
+ #include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/ioport.h>
+-#include <linux/mm.h>
+-#include <linux/console.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/delay.h>
+-
+-#include <asm/cpu.h>
+-#include <asm/bootinfo.h>
+-#include <asm/irq.h>
+-#include <asm/mipsregs.h>
+-#include <asm/reboot.h>
+-#include <asm/pgtable.h>
+
- config PPCBUG_NVRAM
- bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC
- default y if PPC_PREP
-@@ -381,6 +401,26 @@ config PPC_64K_PAGES
- while on hardware with such support, it will be used to map
- normal application pages.
+ #include <asm/mach-au1x00/au1000.h>
+ #include <asm/mach-db1x00/db1x00.h>
-+config FORCE_MAX_ZONEORDER
-+ int "Maximum zone order"
-+ default "9" if PPC_64K_PAGES
-+ default "13" if PPC64 && !PPC_64K_PAGES
-+ default "11"
-+ help
-+ The kernel memory allocator divides physically contiguous memory
-+ blocks into "zones", where each zone is a power of two number of
-+ pages. This option selects the largest power of two that the kernel
-+ keeps in the memory allocator. If you need to allocate very large
-+ blocks of physically contiguous memory, then you may need to
-+ increase this value.
-+
-+ This config option is actually maximum order plus one. For example,
-+ a value of 11 means that the largest free memory block is 2^10 pages.
-+
-+ The page size is not necessarily 4KB. For example, on 64-bit
-+ systems, 64KB pages can be enabled via CONFIG_PPC_64K_PAGES. Keep
-+ this in mind when choosing a value for this option.
-+
- config PPC_SUBPAGE_PROT
- bool "Support setting protections for 4k subpages"
- depends on PPC_64K_PAGES
-@@ -490,6 +530,14 @@ config FSL_PCI
- bool
- select PPC_INDIRECT_PCI
+diff --git a/arch/mips/au1000/db1x00/init.c b/arch/mips/au1000/db1x00/init.c
+index e822c12..d3b967c 100644
+--- a/arch/mips/au1000/db1x00/init.c
++++ b/arch/mips/au1000/db1x00/init.c
+@@ -28,13 +28,8 @@
+ */
-+config 4xx_SOC
-+ bool
-+
-+config FSL_LBC
-+ bool
-+ help
-+ Freescale Localbus support
-+
- # Yes MCA RS/6000s exist but Linux-PPC does not currently support any
- config MCA
- bool
-@@ -578,20 +626,6 @@ config ADVANCED_OPTIONS
- comment "Default settings for advanced configuration options are used"
- depends on !ADVANCED_OPTIONS
+ #include <linux/init.h>
+-#include <linux/mm.h>
+-#include <linux/sched.h>
+-#include <linux/bootmem.h>
+-#include <linux/string.h>
+ #include <linux/kernel.h>
--config HIGHMEM_START_BOOL
-- bool "Set high memory pool address"
-- depends on ADVANCED_OPTIONS && HIGHMEM
-- help
-- This option allows you to set the base address of the kernel virtual
-- area used to map high memory pages. This can be useful in
-- optimizing the layout of kernel virtual memory.
--
-- Say N here unless you know what you are doing.
--
--config HIGHMEM_START
-- hex "Virtual start address of high memory pool" if HIGHMEM_START_BOOL
-- default "0xfe000000"
--
- config LOWMEM_SIZE_BOOL
- bool "Set maximum low memory"
- depends on ADVANCED_OPTIONS
-@@ -608,21 +642,76 @@ config LOWMEM_SIZE
- hex "Maximum low memory size (in bytes)" if LOWMEM_SIZE_BOOL
- default "0x30000000"
+-#include <asm/addrspace.h>
+ #include <asm/bootinfo.h>
-+config RELOCATABLE
-+ bool "Build a relocatable kernel (EXPERIMENTAL)"
-+ depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE
-+ help
-+ This builds a kernel image that is capable of running at the
-+ location the kernel is loaded at (some alignment restrictions may
-+ exist).
-+
-+ One use is for the kexec on panic case where the recovery kernel
-+ must live at a different physical address than the primary
-+ kernel.
-+
-+ Note: If CONFIG_RELOCATABLE=y, then the kernel runs from the address
-+ it has been loaded at and the compile time physical addresses
-+ CONFIG_PHYSICAL_START is ignored. However CONFIG_PHYSICAL_START
-+ setting can still be useful to bootwrappers that need to know the
-+ load location of the kernel (eg. u-boot/mkimage).
-+
-+config PAGE_OFFSET_BOOL
-+ bool "Set custom page offset address"
-+ depends on ADVANCED_OPTIONS
-+ help
-+ This option allows you to set the kernel virtual address at which
-+ the kernel will map low memory. This can be useful in optimizing
-+ the virtual memory layout of the system.
-+
-+ Say N here unless you know what you are doing.
-+
-+config PAGE_OFFSET
-+ hex "Virtual address of memory base" if PAGE_OFFSET_BOOL
-+ default "0xc0000000"
+ #include <prom.h>
+diff --git a/arch/mips/au1000/db1x00/irqmap.c b/arch/mips/au1000/db1x00/irqmap.c
+index 09cea03..eaa50c7 100644
+--- a/arch/mips/au1000/db1x00/irqmap.c
++++ b/arch/mips/au1000/db1x00/irqmap.c
+@@ -25,26 +25,9 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+-#include <linux/errno.h>
+
- config KERNEL_START_BOOL
- bool "Set custom kernel base address"
- depends on ADVANCED_OPTIONS
- help
- This option allows you to set the kernel virtual address at which
-- the kernel will map low memory (the kernel image will be linked at
-- this address). This can be useful in optimizing the virtual memory
-- layout of the system.
-+ the kernel will be loaded. Normally this should match PAGE_OFFSET
-+ however there are times (like kdump) that one might not want them
-+ to be the same.
-
- Say N here unless you know what you are doing.
+ #include <linux/init.h>
+-#include <linux/irq.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/module.h>
+-#include <linux/signal.h>
+-#include <linux/sched.h>
+-#include <linux/types.h>
+-#include <linux/interrupt.h>
+-#include <linux/ioport.h>
+-#include <linux/timex.h>
+-#include <linux/slab.h>
+-#include <linux/random.h>
+-#include <linux/delay.h>
+-#include <linux/bitops.h>
- config KERNEL_START
- hex "Virtual address of kernel base" if KERNEL_START_BOOL
-+ default PAGE_OFFSET if PAGE_OFFSET_BOOL
-+ default "0xc2000000" if CRASH_DUMP
- default "0xc0000000"
+-#include <asm/bootinfo.h>
+-#include <asm/io.h>
+-#include <asm/mipsregs.h>
+-#include <asm/system.h>
+ #include <asm/mach-au1x00/au1000.h>
-+config PHYSICAL_START_BOOL
-+ bool "Set physical address where the kernel is loaded"
-+ depends on ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE
-+ help
-+ This gives the physical address where the kernel is loaded.
-+
-+ Say N here unless you know what you are doing.
-+
-+config PHYSICAL_START
-+ hex "Physical address where the kernel is loaded" if PHYSICAL_START_BOOL
-+ default "0x02000000" if PPC_STD_MMU && CRASH_DUMP
-+ default "0x00000000"
-+
-+config PHYSICAL_ALIGN
-+ hex
-+ default "0x10000000" if FSL_BOOKE
-+ help
-+ This value puts the alignment restrictions on physical address
-+ where kernel is loaded and run from. Kernel is compiled for an
-+ address which meets above alignment restriction.
+ #ifdef CONFIG_MIPS_DB1500
+diff --git a/arch/mips/au1000/mtx-1/board_setup.c b/arch/mips/au1000/mtx-1/board_setup.c
+index 310d5df..5736354 100644
+--- a/arch/mips/au1000/mtx-1/board_setup.c
++++ b/arch/mips/au1000/mtx-1/board_setup.c
+@@ -28,19 +28,9 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
- config TASK_SIZE_BOOL
- bool "Set custom user task size"
- depends on ADVANCED_OPTIONS
-@@ -663,31 +752,23 @@ config CONSISTENT_SIZE
- hex "Size of consistent memory pool" if CONSISTENT_SIZE_BOOL
- default "0x00200000" if NOT_COHERENT_CACHE
+ #include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/ioport.h>
+-#include <linux/mm.h>
+-#include <linux/console.h>
+-#include <linux/delay.h>
--config BOOT_LOAD_BOOL
-- bool "Set the boot link/load address"
-- depends on ADVANCED_OPTIONS && !PPC_MULTIPLATFORM
-- help
-- This option allows you to set the initial load address of the zImage
-- or zImage.initrd file. This can be useful if you are on a board
-- which has a small amount of memory.
--
-- Say N here unless you know what you are doing.
--
--config BOOT_LOAD
-- hex "Link/load address for booting" if BOOT_LOAD_BOOL
-- default "0x00400000" if 40x || 8xx || 8260
-- default "0x01000000" if 44x
-- default "0x00800000"
--
- config PIN_TLB
- bool "Pinned Kernel TLBs (860 ONLY)"
- depends on ADVANCED_OPTIONS && 8xx
- endmenu
+-#include <asm/cpu.h>
+-#include <asm/bootinfo.h>
+-#include <asm/irq.h>
+-#include <asm/mipsregs.h>
+-#include <asm/reboot.h>
+-#include <asm/pgtable.h>
+ #include <asm/mach-au1x00/au1000.h>
- if PPC64
-+config PAGE_OFFSET
-+ hex
-+ default "0xc000000000000000"
- config KERNEL_START
- hex
-+ default "0xc000000002000000" if CRASH_DUMP
- default "0xc000000000000000"
-+config PHYSICAL_START
-+ hex
-+ default "0x02000000" if CRASH_DUMP
-+ default "0x00000000"
- endif
+ extern int (*board_pci_idsel)(unsigned int devsel, int assert);
+diff --git a/arch/mips/au1000/mtx-1/init.c b/arch/mips/au1000/mtx-1/init.c
+index e700fd3..c015cbc 100644
+--- a/arch/mips/au1000/mtx-1/init.c
++++ b/arch/mips/au1000/mtx-1/init.c
+@@ -28,14 +28,10 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+-#include <linux/string.h>
++
+ #include <linux/kernel.h>
+-#include <linux/sched.h>
+ #include <linux/init.h>
+-#include <linux/mm.h>
+-#include <linux/bootmem.h>
- source "net/Kconfig"
-diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
-index db7cc34..a86d8d8 100644
---- a/arch/powerpc/Kconfig.debug
-+++ b/arch/powerpc/Kconfig.debug
-@@ -269,7 +269,7 @@ config PPC_EARLY_DEBUG_CPM_ADDR
- hex "CPM UART early debug transmit descriptor address"
- depends on PPC_EARLY_DEBUG_CPM
- default "0xfa202008" if PPC_EP88XC
-- default "0xf0000008" if CPM2
-+ default "0xf0001ff8" if CPM2
- default "0xff002008" if CPM1
- help
- This specifies the address of the transmit descriptor
-diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
-index ab5cfe8..e2ec4a9 100644
---- a/arch/powerpc/Makefile
-+++ b/arch/powerpc/Makefile
-@@ -71,13 +71,11 @@ endif
+-#include <asm/addrspace.h>
+ #include <asm/bootinfo.h>
- LDFLAGS_vmlinux := -Bstatic
+ #include <prom.h>
+diff --git a/arch/mips/au1000/mtx-1/irqmap.c b/arch/mips/au1000/mtx-1/irqmap.c
+index 49c612a..78d70c4 100644
+--- a/arch/mips/au1000/mtx-1/irqmap.c
++++ b/arch/mips/au1000/mtx-1/irqmap.c
+@@ -25,26 +25,9 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+-#include <linux/errno.h>
++
+ #include <linux/init.h>
+-#include <linux/irq.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/module.h>
+-#include <linux/signal.h>
+-#include <linux/sched.h>
+-#include <linux/types.h>
+-#include <linux/interrupt.h>
+-#include <linux/ioport.h>
+-#include <linux/timex.h>
+-#include <linux/slab.h>
+-#include <linux/random.h>
+-#include <linux/delay.h>
+-#include <linux/bitops.h>
--CPPFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH)
--AFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH)
- CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=none -mcall-aixdesc
--CFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH) -ffixed-r2 -mmultiple
--KBUILD_CPPFLAGS += $(CPPFLAGS-y)
--KBUILD_AFLAGS += $(AFLAGS-y)
--KBUILD_CFLAGS += -msoft-float -pipe $(CFLAGS-y)
-+CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple
-+KBUILD_CPPFLAGS += -Iarch/$(ARCH)
-+KBUILD_AFLAGS += -Iarch/$(ARCH)
-+KBUILD_CFLAGS += -msoft-float -pipe -Iarch/$(ARCH) $(CFLAGS-y)
- CPP = $(CC) -E $(KBUILD_CFLAGS)
+-#include <asm/bootinfo.h>
+-#include <asm/io.h>
+-#include <asm/mipsregs.h>
+-#include <asm/system.h>
+ #include <asm/mach-au1x00/au1000.h>
- CHECKFLAGS += -m$(CONFIG_WORD_SIZE) -D__powerpc__ -D__powerpc$(CONFIG_WORD_SIZE)__
-@@ -164,7 +162,7 @@ boot := arch/$(ARCH)/boot
- $(BOOT_TARGETS): vmlinux
- $(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
+ char irq_tab_alchemy[][5] __initdata = {
+diff --git a/arch/mips/au1000/mtx-1/platform.c b/arch/mips/au1000/mtx-1/platform.c
+index ce8637b..a7edbf0 100644
+--- a/arch/mips/au1000/mtx-1/platform.c
++++ b/arch/mips/au1000/mtx-1/platform.c
+@@ -19,7 +19,6 @@
+ */
--bootwrapper_install:
-+bootwrapper_install %.dtb:
- $(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
+ #include <linux/init.h>
+-#include <linux/types.h>
+ #include <linux/platform_device.h>
+ #include <linux/leds.h>
+ #include <linux/gpio_keys.h>
+diff --git a/arch/mips/au1000/pb1000/board_setup.c b/arch/mips/au1000/pb1000/board_setup.c
+index 5198c4f..33f15ac 100644
+--- a/arch/mips/au1000/pb1000/board_setup.c
++++ b/arch/mips/au1000/pb1000/board_setup.c
+@@ -23,19 +23,10 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
++
+ #include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/ioport.h>
+-#include <linux/mm.h>
+-#include <linux/console.h>
+ #include <linux/delay.h>
- define archhelp
-diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore
-index 5ef2bdf..2347294 100644
---- a/arch/powerpc/boot/.gitignore
-+++ b/arch/powerpc/boot/.gitignore
-@@ -27,6 +27,7 @@ zImage.chrp
- zImage.coff
- zImage.coff.lds
- zImage.ep*
-+zImage.iseries
- zImage.*lds
- zImage.miboot
- zImage.pmac
-diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
-index 1aded8f..7822d25 100644
---- a/arch/powerpc/boot/Makefile
-+++ b/arch/powerpc/boot/Makefile
-@@ -40,6 +40,7 @@ $(obj)/ebony.o: BOOTCFLAGS += -mcpu=405
- $(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=405
- $(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405
- $(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405
-+$(obj)/virtex405-head.o: BOOTAFLAGS += -mcpu=405
+-#include <asm/cpu.h>
+-#include <asm/bootinfo.h>
+-#include <asm/irq.h>
+-#include <asm/mipsregs.h>
+-#include <asm/reboot.h>
+-#include <asm/pgtable.h>
+ #include <asm/mach-au1x00/au1000.h>
+ #include <asm/mach-pb1x00/pb1000.h>
+diff --git a/arch/mips/au1000/pb1000/init.c b/arch/mips/au1000/pb1000/init.c
+index 2515b9f..549447d 100644
+--- a/arch/mips/au1000/pb1000/init.c
++++ b/arch/mips/au1000/pb1000/init.c
+@@ -26,14 +26,10 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
++
+ #include <linux/init.h>
+-#include <linux/mm.h>
+-#include <linux/sched.h>
+-#include <linux/bootmem.h>
+-#include <linux/string.h>
+ #include <linux/kernel.h>
- zlib := inffast.c inflate.c inftrees.c
-@@ -64,7 +65,8 @@ src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c
- cuboot-bamboo.c cuboot-mpc7448hpc2.c cuboot-taishan.c \
- fixed-head.S ep88xc.c ep405.c \
- cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \
-- cuboot-warp.c cuboot-85xx-cpm2.c
-+ cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \
-+ virtex405-head.S
- src-boot := $(src-wlib) $(src-plat) empty.c
+-#include <asm/addrspace.h>
+ #include <asm/bootinfo.h>
- src-boot := $(addprefix $(obj)/, $(src-boot))
-@@ -192,7 +194,7 @@ image-$(CONFIG_PPC_CHRP) += zImage.chrp
- image-$(CONFIG_PPC_EFIKA) += zImage.chrp
- image-$(CONFIG_PPC_PMAC) += zImage.pmac
- image-$(CONFIG_PPC_HOLLY) += zImage.holly
--image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800
-+image-$(CONFIG_PPC_PRPMC2800) += dtbImage.prpmc2800
- image-$(CONFIG_PPC_ISERIES) += zImage.iseries
- image-$(CONFIG_DEFAULT_UIMAGE) += uImage
+ #include <prom.h>
+diff --git a/arch/mips/au1000/pb1000/irqmap.c b/arch/mips/au1000/pb1000/irqmap.c
+index 88e3545..b3d56b0 100644
+--- a/arch/mips/au1000/pb1000/irqmap.c
++++ b/arch/mips/au1000/pb1000/irqmap.c
+@@ -25,26 +25,10 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+-#include <linux/errno.h>
++
+ #include <linux/init.h>
+-#include <linux/irq.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/module.h>
+-#include <linux/signal.h>
+-#include <linux/sched.h>
+-#include <linux/types.h>
+ #include <linux/interrupt.h>
+-#include <linux/ioport.h>
+-#include <linux/timex.h>
+-#include <linux/slab.h>
+-#include <linux/random.h>
+-#include <linux/delay.h>
+-#include <linux/bitops.h>
-@@ -216,6 +218,7 @@ image-$(CONFIG_RAINIER) += cuImage.rainier
- image-$(CONFIG_TAISHAN) += cuImage.taishan
- image-$(CONFIG_KATMAI) += cuImage.katmai
- image-$(CONFIG_WARP) += cuImage.warp
-+image-$(CONFIG_YOSEMITE) += cuImage.yosemite
+-#include <asm/bootinfo.h>
+-#include <asm/io.h>
+-#include <asm/mipsregs.h>
+-#include <asm/system.h>
+ #include <asm/mach-au1x00/au1000.h>
- # Board ports in arch/powerpc/platform/8xx/Kconfig
- image-$(CONFIG_PPC_MPC86XADS) += cuImage.mpc866ads
-@@ -255,6 +258,7 @@ image-$(CONFIG_TQM8555) += cuImage.tqm8555
- image-$(CONFIG_TQM8560) += cuImage.tqm8560
- image-$(CONFIG_SBC8548) += cuImage.sbc8548
- image-$(CONFIG_SBC8560) += cuImage.sbc8560
-+image-$(CONFIG_KSI8560) += cuImage.ksi8560
+ struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
+diff --git a/arch/mips/au1000/pb1100/board_setup.c b/arch/mips/au1000/pb1100/board_setup.c
+index 42874a6..656164c 100644
+--- a/arch/mips/au1000/pb1100/board_setup.c
++++ b/arch/mips/au1000/pb1100/board_setup.c
+@@ -23,19 +23,10 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
++
+ #include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/ioport.h>
+-#include <linux/mm.h>
+-#include <linux/console.h>
+ #include <linux/delay.h>
- # Board ports in arch/powerpc/platform/embedded6xx/Kconfig
- image-$(CONFIG_STORCENTER) += cuImage.storcenter
-@@ -285,11 +289,11 @@ $(obj)/zImage.%: vmlinux $(wrapperbits)
- $(call if_changed,wrap,$*)
+-#include <asm/cpu.h>
+-#include <asm/bootinfo.h>
+-#include <asm/irq.h>
+-#include <asm/mipsregs.h>
+-#include <asm/reboot.h>
+-#include <asm/pgtable.h>
+ #include <asm/mach-au1x00/au1000.h>
+ #include <asm/mach-pb1x00/pb1100.h>
- # dtbImage% - a dtbImage is a zImage with an embedded device tree blob
--$(obj)/dtbImage.initrd.%: vmlinux $(wrapperbits) $(dtstree)/%.dts
-- $(call if_changed,wrap,$*,$(dtstree)/$*.dts,,$(obj)/ramdisk.image.gz)
-+$(obj)/dtbImage.initrd.%: vmlinux $(wrapperbits) $(obj)/%.dtb
-+ $(call if_changed,wrap,$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
+diff --git a/arch/mips/au1000/pb1100/init.c b/arch/mips/au1000/pb1100/init.c
+index 490c380..c913446 100644
+--- a/arch/mips/au1000/pb1100/init.c
++++ b/arch/mips/au1000/pb1100/init.c
+@@ -27,14 +27,10 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
++
+ #include <linux/init.h>
+-#include <linux/mm.h>
+-#include <linux/sched.h>
+-#include <linux/bootmem.h>
+-#include <linux/string.h>
+ #include <linux/kernel.h>
--$(obj)/dtbImage.%: vmlinux $(wrapperbits) $(dtstree)/%.dts
-- $(call if_changed,wrap,$*,$(dtstree)/$*.dts)
-+$(obj)/dtbImage.%: vmlinux $(wrapperbits) $(obj)/%.dtb
-+ $(call if_changed,wrap,$*,,$(obj)/$*.dtb)
+-#include <asm/addrspace.h>
+ #include <asm/bootinfo.h>
- # This cannot be in the root of $(src) as the zImage rule always adds a $(obj)
- # prefix
-@@ -302,14 +306,24 @@ $(obj)/zImage.iseries: vmlinux
- $(obj)/uImage: vmlinux $(wrapperbits)
- $(call if_changed,wrap,uboot)
+ #include <prom.h>
+diff --git a/arch/mips/au1000/pb1100/irqmap.c b/arch/mips/au1000/pb1100/irqmap.c
+index 880456b..b5021e3 100644
+--- a/arch/mips/au1000/pb1100/irqmap.c
++++ b/arch/mips/au1000/pb1100/irqmap.c
+@@ -25,26 +25,9 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+-#include <linux/errno.h>
++
+ #include <linux/init.h>
+-#include <linux/irq.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/module.h>
+-#include <linux/signal.h>
+-#include <linux/sched.h>
+-#include <linux/types.h>
+-#include <linux/interrupt.h>
+-#include <linux/ioport.h>
+-#include <linux/timex.h>
+-#include <linux/slab.h>
+-#include <linux/random.h>
+-#include <linux/delay.h>
+-#include <linux/bitops.h>
--$(obj)/cuImage.%: vmlinux $(dtstree)/%.dts $(wrapperbits)
-- $(call if_changed,wrap,cuboot-$*,$(dtstree)/$*.dts)
-+$(obj)/cuImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
-+ $(call if_changed,wrap,cuboot-$*,,$(obj)/$*.dtb)
+-#include <asm/bootinfo.h>
+-#include <asm/io.h>
+-#include <asm/mipsregs.h>
+-#include <asm/system.h>
+ #include <asm/mach-au1x00/au1000.h>
--$(obj)/treeImage.initrd.%: vmlinux $(dtstree)/%.dts $(wrapperbits)
-- $(call if_changed,wrap,treeboot-$*,$(dtstree)/$*.dts,,$(obj)/ramdisk.image.gz)
-+$(obj)/simpleImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
-+ $(call if_changed,wrap,simpleboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
+ struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
+diff --git a/arch/mips/au1000/pb1200/Makefile b/arch/mips/au1000/pb1200/Makefile
+index 970b1b1..4fe02ea 100644
+--- a/arch/mips/au1000/pb1200/Makefile
++++ b/arch/mips/au1000/pb1200/Makefile
+@@ -3,5 +3,6 @@
+ #
+
+ lib-y := init.o board_setup.o irqmap.o
++obj-y += platform.o
+
+ EXTRA_CFLAGS += -Werror
+diff --git a/arch/mips/au1000/pb1200/board_setup.c b/arch/mips/au1000/pb1200/board_setup.c
+index b98bebf..4493a79 100644
+--- a/arch/mips/au1000/pb1200/board_setup.c
++++ b/arch/mips/au1000/pb1200/board_setup.c
+@@ -23,27 +23,11 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
++
+ #include <linux/init.h>
+ #include <linux/sched.h>
+-#include <linux/ioport.h>
+-#include <linux/mm.h>
+-#include <linux/console.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/delay.h>
+-
+-#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
+-#include <linux/ide.h>
+-#endif
+-
+-#include <asm/cpu.h>
+-#include <asm/bootinfo.h>
+-#include <asm/irq.h>
+-#include <asm/mipsregs.h>
+-#include <asm/reboot.h>
+-#include <asm/pgtable.h>
--$(obj)/treeImage.%: vmlinux $(dtstree)/%.dts $(wrapperbits)
-- $(call if_changed,wrap,treeboot-$*,$(dtstree)/$*.dts)
-+$(obj)/simpleImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
-+ $(call if_changed,wrap,simpleboot-$*,,$(obj)/$*.dtb)
+ #include <au1000.h>
+-#include <au1xxx_dbdma.h>
+ #include <prom.h>
+
+ #ifdef CONFIG_MIPS_PB1200
+@@ -52,8 +36,6 @@
+
+ #ifdef CONFIG_MIPS_DB1200
+ #include <asm/mach-db1x00/db1200.h>
+-#define PB1200_ETH_INT DB1200_ETH_INT
+-#define PB1200_IDE_INT DB1200_IDE_INT
+ #endif
+
+ extern void _board_init_irq(void);
+diff --git a/arch/mips/au1000/pb1200/init.c b/arch/mips/au1000/pb1200/init.c
+index 069ed45..72af550 100644
+--- a/arch/mips/au1000/pb1200/init.c
++++ b/arch/mips/au1000/pb1200/init.c
+@@ -27,14 +27,10 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
-+$(obj)/treeImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
-+ $(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
+ #include <linux/init.h>
+-#include <linux/mm.h>
+-#include <linux/sched.h>
+-#include <linux/bootmem.h>
+-#include <linux/string.h>
+ #include <linux/kernel.h>
+
+-#include <asm/addrspace.h>
+ #include <asm/bootinfo.h>
+
+ #include <prom.h>
+diff --git a/arch/mips/au1000/pb1200/irqmap.c b/arch/mips/au1000/pb1200/irqmap.c
+index 8fcd0df..e61eb8e 100644
+--- a/arch/mips/au1000/pb1200/irqmap.c
++++ b/arch/mips/au1000/pb1200/irqmap.c
+@@ -22,26 +22,10 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+-#include <linux/errno.h>
+
-+$(obj)/treeImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
-+ $(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb)
+ #include <linux/init.h>
+-#include <linux/irq.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/module.h>
+-#include <linux/signal.h>
+-#include <linux/sched.h>
+-#include <linux/types.h>
+ #include <linux/interrupt.h>
+-#include <linux/ioport.h>
+-#include <linux/timex.h>
+-#include <linux/slab.h>
+-#include <linux/random.h>
+-#include <linux/delay.h>
+-#include <linux/bitops.h>
+-
+-#include <asm/bootinfo.h>
+-#include <asm/io.h>
+-#include <asm/mipsregs.h>
+-#include <asm/system.h>
+
-+# Rule to build device tree blobs
-+$(obj)/%.dtb: $(dtstree)/%.dts $(obj)/dtc
-+ $(obj)/dtc -O dtb -o $(obj)/$*.dtb -b 0 $(DTS_FLAGS) $(dtstree)/$*.dts
-
- # If there isn't a platform selected then just strip the vmlinux.
- ifeq (,$(image-y))
-@@ -326,7 +340,7 @@ install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
+ #include <asm/mach-au1x00/au1000.h>
- # anything not in $(targets)
- clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \
-- otheros.bld
-+ otheros.bld *.dtb
+ #ifdef CONFIG_MIPS_PB1200
+diff --git a/arch/mips/au1000/pb1200/platform.c b/arch/mips/au1000/pb1200/platform.c
+new file mode 100644
+index 0000000..5930110
+--- /dev/null
++++ b/arch/mips/au1000/pb1200/platform.c
+@@ -0,0 +1,84 @@
++/*
++ * Pb1200/DBAu1200 board platform device registration
++ *
++ * Copyright (C) 2008 MontaVista Software Inc. <source at mvista.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
++
++#include <linux/init.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-au1x00/au1xxx.h>
++
++static struct resource ide_resources[] = {
++ [0] = {
++ .start = IDE_PHYS_ADDR,
++ .end = IDE_PHYS_ADDR + IDE_PHYS_LEN - 1,
++ .flags = IORESOURCE_MEM
++ },
++ [1] = {
++ .start = IDE_INT,
++ .end = IDE_INT,
++ .flags = IORESOURCE_IRQ
++ }
++};
++
++static u64 ide_dmamask = ~(u32)0;
++
++static struct platform_device ide_device = {
++ .name = "au1200-ide",
++ .id = 0,
++ .dev = {
++ .dma_mask = &ide_dmamask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .num_resources = ARRAY_SIZE(ide_resources),
++ .resource = ide_resources
++};
++
++static struct resource smc91c111_resources[] = {
++ [0] = {
++ .name = "smc91x-regs",
++ .start = SMC91C111_PHYS_ADDR,
++ .end = SMC91C111_PHYS_ADDR + 0xf,
++ .flags = IORESOURCE_MEM
++ },
++ [1] = {
++ .start = SMC91C111_INT,
++ .end = SMC91C111_INT,
++ .flags = IORESOURCE_IRQ
++ },
++};
++
++static struct platform_device smc91c111_device = {
++ .name = "smc91x",
++ .id = -1,
++ .num_resources = ARRAY_SIZE(smc91c111_resources),
++ .resource = smc91c111_resources
++};
++
++static struct platform_device *board_platform_devices[] __initdata = {
++ &ide_device,
++ &smc91c111_device
++};
++
++static int __init board_register_devices(void)
++{
++ return platform_add_devices(board_platform_devices,
++ ARRAY_SIZE(board_platform_devices));
++}
++
++arch_initcall(board_register_devices);
+diff --git a/arch/mips/au1000/pb1500/board_setup.c b/arch/mips/au1000/pb1500/board_setup.c
+index 5446836..24c652e 100644
+--- a/arch/mips/au1000/pb1500/board_setup.c
++++ b/arch/mips/au1000/pb1500/board_setup.c
+@@ -23,19 +23,10 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
++
+ #include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/ioport.h>
+-#include <linux/mm.h>
+-#include <linux/console.h>
+ #include <linux/delay.h>
- # clean up files cached by wrapper
- clean-kernel := vmlinux.strip vmlinux.bin
-diff --git a/arch/powerpc/boot/bamboo.c b/arch/powerpc/boot/bamboo.c
-index 54b33f1..b82cacb 100644
---- a/arch/powerpc/boot/bamboo.c
-+++ b/arch/powerpc/boot/bamboo.c
-@@ -33,7 +33,8 @@ static void bamboo_fixups(void)
- ibm440ep_fixup_clocks(sysclk, 11059200, 25000000);
- ibm4xx_sdram_fixup_memsize();
- ibm4xx_quiesce_eth((u32 *)0xef600e00, (u32 *)0xef600f00);
-- dt_fixup_mac_addresses(bamboo_mac0, bamboo_mac1);
-+ dt_fixup_mac_address_by_alias("ethernet0", bamboo_mac0);
-+ dt_fixup_mac_address_by_alias("ethernet1", bamboo_mac1);
- }
+-#include <asm/cpu.h>
+-#include <asm/bootinfo.h>
+-#include <asm/irq.h>
+-#include <asm/mipsregs.h>
+-#include <asm/reboot.h>
+-#include <asm/pgtable.h>
+ #include <asm/mach-au1x00/au1000.h>
+ #include <asm/mach-pb1x00/pb1500.h>
- void bamboo_init(void *mac0, void *mac1)
-diff --git a/arch/powerpc/boot/cpm-serial.c b/arch/powerpc/boot/cpm-serial.c
-index 28296fa..19dc15a 100644
---- a/arch/powerpc/boot/cpm-serial.c
-+++ b/arch/powerpc/boot/cpm-serial.c
-@@ -11,6 +11,7 @@
- #include "types.h"
- #include "io.h"
- #include "ops.h"
-+#include "page.h"
+diff --git a/arch/mips/au1000/pb1500/init.c b/arch/mips/au1000/pb1500/init.c
+index db558c9..488507c 100644
+--- a/arch/mips/au1000/pb1500/init.c
++++ b/arch/mips/au1000/pb1500/init.c
+@@ -27,14 +27,10 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
++
+ #include <linux/init.h>
+-#include <linux/mm.h>
+-#include <linux/sched.h>
+-#include <linux/bootmem.h>
+-#include <linux/string.h>
+ #include <linux/kernel.h>
- struct cpm_scc {
- u32 gsmrl;
-@@ -42,6 +43,22 @@ struct cpm_param {
- u16 tbase;
- u8 rfcr;
- u8 tfcr;
-+ u16 mrblr;
-+ u32 rstate;
-+ u8 res1[4];
-+ u16 rbptr;
-+ u8 res2[6];
-+ u32 tstate;
-+ u8 res3[4];
-+ u16 tbptr;
-+ u8 res4[6];
-+ u16 maxidl;
-+ u16 idlc;
-+ u16 brkln;
-+ u16 brkec;
-+ u16 brkcr;
-+ u16 rmask;
-+ u8 res5[4];
- };
+-#include <asm/addrspace.h>
+ #include <asm/bootinfo.h>
- struct cpm_bd {
-@@ -54,10 +71,10 @@ static void *cpcr;
- static struct cpm_param *param;
- static struct cpm_smc *smc;
- static struct cpm_scc *scc;
--struct cpm_bd *tbdf, *rbdf;
-+static struct cpm_bd *tbdf, *rbdf;
- static u32 cpm_cmd;
--static u8 *muram_start;
--static u32 muram_offset;
-+static void *cbd_addr;
-+static u32 cbd_offset;
+ #include <prom.h>
+diff --git a/arch/mips/au1000/pb1500/irqmap.c b/arch/mips/au1000/pb1500/irqmap.c
+index 810f695..4817ab4 100644
+--- a/arch/mips/au1000/pb1500/irqmap.c
++++ b/arch/mips/au1000/pb1500/irqmap.c
+@@ -25,26 +25,9 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+-#include <linux/errno.h>
++
+ #include <linux/init.h>
+-#include <linux/irq.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/module.h>
+-#include <linux/signal.h>
+-#include <linux/sched.h>
+-#include <linux/types.h>
+-#include <linux/interrupt.h>
+-#include <linux/ioport.h>
+-#include <linux/timex.h>
+-#include <linux/slab.h>
+-#include <linux/random.h>
+-#include <linux/delay.h>
+-#include <linux/bitops.h>
- static void (*do_cmd)(int op);
- static void (*enable_port)(void);
-@@ -119,20 +136,25 @@ static int cpm_serial_open(void)
+-#include <asm/bootinfo.h>
+-#include <asm/io.h>
+-#include <asm/mipsregs.h>
+-#include <asm/system.h>
+ #include <asm/mach-au1x00/au1000.h>
- out_8(¶m->rfcr, 0x10);
- out_8(¶m->tfcr, 0x10);
--
-- rbdf = (struct cpm_bd *)muram_start;
-- rbdf->addr = (u8 *)(rbdf + 2);
-+ out_be16(¶m->mrblr, 1);
-+ out_be16(¶m->maxidl, 0);
-+ out_be16(¶m->brkec, 0);
-+ out_be16(¶m->brkln, 0);
-+ out_be16(¶m->brkcr, 0);
+ char irq_tab_alchemy[][5] __initdata = {
+diff --git a/arch/mips/au1000/pb1550/board_setup.c b/arch/mips/au1000/pb1550/board_setup.c
+index e3cfb0d..45d6087 100644
+--- a/arch/mips/au1000/pb1550/board_setup.c
++++ b/arch/mips/au1000/pb1550/board_setup.c
+@@ -27,20 +27,9 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
-+ rbdf = cbd_addr;
-+ rbdf->addr = (u8 *)rbdf - 1;
- rbdf->sc = 0xa000;
- rbdf->len = 1;
+ #include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/ioport.h>
+-#include <linux/mm.h>
+-#include <linux/console.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/delay.h>
- tbdf = rbdf + 1;
-- tbdf->addr = (u8 *)(rbdf + 2) + 1;
-+ tbdf->addr = (u8 *)rbdf - 2;
- tbdf->sc = 0x2000;
- tbdf->len = 1;
+-#include <asm/cpu.h>
+-#include <asm/bootinfo.h>
+-#include <asm/irq.h>
+-#include <asm/mipsregs.h>
+-#include <asm/reboot.h>
+-#include <asm/pgtable.h>
+ #include <asm/mach-au1x00/au1000.h>
+ #include <asm/mach-pb1x00/pb1550.h>
- sync();
-- out_be16(¶m->rbase, muram_offset);
-- out_be16(¶m->tbase, muram_offset + sizeof(struct cpm_bd));
-+ out_be16(¶m->rbase, cbd_offset);
-+ out_be16(¶m->tbase, cbd_offset + sizeof(struct cpm_bd));
+diff --git a/arch/mips/au1000/pb1550/init.c b/arch/mips/au1000/pb1550/init.c
+index b716363..f6b2fc5 100644
+--- a/arch/mips/au1000/pb1550/init.c
++++ b/arch/mips/au1000/pb1550/init.c
+@@ -27,14 +27,10 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
++
+ #include <linux/init.h>
+-#include <linux/mm.h>
+-#include <linux/sched.h>
+-#include <linux/bootmem.h>
+-#include <linux/string.h>
+ #include <linux/kernel.h>
- do_cmd(CPM_CMD_INIT_RX_TX);
+-#include <asm/addrspace.h>
+ #include <asm/bootinfo.h>
-@@ -175,10 +197,12 @@ static unsigned char cpm_serial_getc(void)
+ #include <prom.h>
+diff --git a/arch/mips/au1000/pb1550/irqmap.c b/arch/mips/au1000/pb1550/irqmap.c
+index 56becab..e1dac37 100644
+--- a/arch/mips/au1000/pb1550/irqmap.c
++++ b/arch/mips/au1000/pb1550/irqmap.c
+@@ -25,26 +25,9 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+-#include <linux/errno.h>
++
+ #include <linux/init.h>
+-#include <linux/irq.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/module.h>
+-#include <linux/signal.h>
+-#include <linux/sched.h>
+-#include <linux/types.h>
+-#include <linux/interrupt.h>
+-#include <linux/ioport.h>
+-#include <linux/timex.h>
+-#include <linux/slab.h>
+-#include <linux/random.h>
+-#include <linux/delay.h>
+-#include <linux/bitops.h>
- int cpm_console_init(void *devp, struct serial_console_data *scdp)
- {
-- void *reg_virt[2];
-- int is_smc = 0, is_cpm2 = 0, n;
-- unsigned long reg_phys;
-+ void *vreg[2];
-+ u32 reg[2];
-+ int is_smc = 0, is_cpm2 = 0;
- void *parent, *muram;
-+ void *muram_addr;
-+ unsigned long muram_offset, muram_size;
+-#include <asm/bootinfo.h>
+-#include <asm/io.h>
+-#include <asm/mipsregs.h>
+-#include <asm/system.h>
+ #include <asm/mach-au1x00/au1000.h>
- if (dt_is_compatible(devp, "fsl,cpm1-smc-uart")) {
- is_smc = 1;
-@@ -202,63 +226,64 @@ int cpm_console_init(void *devp, struct serial_console_data *scdp)
- else
- do_cmd = cpm1_cmd;
+ char irq_tab_alchemy[][5] __initdata = {
+diff --git a/arch/mips/au1000/xxs1500/board_setup.c b/arch/mips/au1000/xxs1500/board_setup.c
+index b2e413e..79d1798 100644
+--- a/arch/mips/au1000/xxs1500/board_setup.c
++++ b/arch/mips/au1000/xxs1500/board_setup.c
+@@ -23,19 +23,10 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
++
+ #include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/ioport.h>
+-#include <linux/mm.h>
+-#include <linux/console.h>
+ #include <linux/delay.h>
-- n = getprop(devp, "fsl,cpm-command", &cpm_cmd, 4);
-- if (n < 4)
-+ if (getprop(devp, "fsl,cpm-command", &cpm_cmd, 4) < 4)
- return -1;
+-#include <asm/cpu.h>
+-#include <asm/bootinfo.h>
+-#include <asm/irq.h>
+-#include <asm/mipsregs.h>
+-#include <asm/reboot.h>
+-#include <asm/pgtable.h>
+ #include <asm/mach-au1x00/au1000.h>
-- n = getprop(devp, "virtual-reg", reg_virt, sizeof(reg_virt));
-- if (n < (int)sizeof(reg_virt)) {
-- for (n = 0; n < 2; n++) {
-- if (!dt_xlate_reg(devp, n, ®_phys, NULL))
-- return -1;
--
-- reg_virt[n] = (void *)reg_phys;
-- }
-- }
-+ if (dt_get_virtual_reg(devp, vreg, 2) < 2)
-+ return -1;
+ void board_reset(void)
+diff --git a/arch/mips/au1000/xxs1500/init.c b/arch/mips/au1000/xxs1500/init.c
+index 7e6878c..24fc6e1 100644
+--- a/arch/mips/au1000/xxs1500/init.c
++++ b/arch/mips/au1000/xxs1500/init.c
+@@ -26,14 +26,10 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
++
+ #include <linux/init.h>
+-#include <linux/mm.h>
+-#include <linux/sched.h>
+-#include <linux/bootmem.h>
+-#include <linux/string.h>
+ #include <linux/kernel.h>
- if (is_smc)
-- smc = reg_virt[0];
-+ smc = vreg[0];
- else
-- scc = reg_virt[0];
-+ scc = vreg[0];
+-#include <asm/addrspace.h>
+ #include <asm/bootinfo.h>
-- param = reg_virt[1];
-+ param = vreg[1];
+ #include <prom.h>
+diff --git a/arch/mips/au1000/xxs1500/irqmap.c b/arch/mips/au1000/xxs1500/irqmap.c
+index a343da1..dd6e3d1 100644
+--- a/arch/mips/au1000/xxs1500/irqmap.c
++++ b/arch/mips/au1000/xxs1500/irqmap.c
+@@ -25,26 +25,9 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+-#include <linux/errno.h>
++
+ #include <linux/init.h>
+-#include <linux/irq.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/module.h>
+-#include <linux/signal.h>
+-#include <linux/sched.h>
+-#include <linux/types.h>
+-#include <linux/interrupt.h>
+-#include <linux/ioport.h>
+-#include <linux/timex.h>
+-#include <linux/slab.h>
+-#include <linux/random.h>
+-#include <linux/delay.h>
+-#include <linux/bitops.h>
- parent = get_parent(devp);
- if (!parent)
- return -1;
+-#include <asm/bootinfo.h>
+-#include <asm/io.h>
+-#include <asm/mipsregs.h>
+-#include <asm/system.h>
+ #include <asm/mach-au1x00/au1000.h>
-- n = getprop(parent, "virtual-reg", reg_virt, sizeof(reg_virt));
-- if (n < (int)sizeof(reg_virt)) {
-- if (!dt_xlate_reg(parent, 0, ®_phys, NULL))
-- return -1;
--
-- reg_virt[0] = (void *)reg_phys;
-- }
+ struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
+diff --git a/arch/mips/basler/excite/excite_procfs.c b/arch/mips/basler/excite/excite_procfs.c
+index 9ee67a9..08923e6 100644
+--- a/arch/mips/basler/excite/excite_procfs.c
++++ b/arch/mips/basler/excite/excite_procfs.c
+@@ -18,8 +18,9 @@
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
-
-- cpcr = reg_virt[0];
-+ if (dt_get_virtual_reg(parent, &cpcr, 1) < 1)
-+ return -1;
-
- muram = finddevice("/soc/cpm/muram/data");
- if (!muram)
- return -1;
-
- /* For bootwrapper-compatible device trees, we assume that the first
-- * entry has at least 18 bytes, and that #address-cells/#data-cells
-+ * entry has at least 128 bytes, and that #address-cells/#data-cells
- * is one for both parent and child.
- */
-
-- n = getprop(muram, "virtual-reg", reg_virt, sizeof(reg_virt));
-- if (n < (int)sizeof(reg_virt)) {
-- if (!dt_xlate_reg(muram, 0, ®_phys, NULL))
-- return -1;
-+ if (dt_get_virtual_reg(muram, &muram_addr, 1) < 1)
-+ return -1;
++#include <linux/module.h>
+ #include <linux/proc_fs.h>
++#include <linux/seq_file.h>
+ #include <linux/stat.h>
+ #include <asm/page.h>
+ #include <asm/io.h>
+@@ -28,14 +29,25 @@
-- reg_virt[0] = (void *)reg_phys;
-- }
-+ if (getprop(muram, "reg", reg, 8) < 8)
-+ return -1;
+ #include <excite.h>
-- muram_start = reg_virt[0];
-+ muram_offset = reg[0];
-+ muram_size = reg[1];
+-static int excite_get_unit_id(char *buf, char **addr, off_t offs, int size)
++static int excite_unit_id_proc_show(struct seq_file *m, void *v)
+ {
+- const int len = snprintf(buf, PAGE_SIZE, "%06x", unit_id);
+- const int w = len - offs;
+- *addr = buf + offs;
+- return w < size ? w : size;
++ seq_printf(m, "%06x", unit_id);
++ return 0;
+ }
-- n = getprop(muram, "reg", &muram_offset, 4);
-- if (n < 4)
-- return -1;
-+ /* Store the buffer descriptors at the end of the first muram chunk.
-+ * For SMC ports on CPM2-based platforms, relocate the parameter RAM
-+ * just before the buffer descriptors.
-+ */
-+
-+ cbd_offset = muram_offset + muram_size - 2 * sizeof(struct cpm_bd);
-+
-+ if (is_cpm2 && is_smc) {
-+ u16 *smc_base = (u16 *)param;
-+ u16 pram_offset;
-+
-+ pram_offset = cbd_offset - 64;
-+ pram_offset = _ALIGN_DOWN(pram_offset, 64);
++static int excite_unit_id_proc_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, excite_unit_id_proc_show, NULL);
++}
+
-+ disable_port();
-+ out_be16(smc_base, pram_offset);
-+ param = muram_addr - muram_offset + pram_offset;
-+ }
++static const struct file_operations excite_unit_id_proc_fops = {
++ .owner = THIS_MODULE,
++ .open = excite_unit_id_proc_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
+
-+ cbd_addr = muram_addr - muram_offset + cbd_offset;
+ static int
+ excite_bootrom_read(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+@@ -65,12 +77,12 @@ excite_bootrom_read(char *page, char **start, off_t off, int count,
+ void excite_procfs_init(void)
+ {
+ /* Create & populate /proc/excite */
+- struct proc_dir_entry * const pdir = proc_mkdir("excite", &proc_root);
++ struct proc_dir_entry * const pdir = proc_mkdir("excite", NULL);
+ if (pdir) {
+ struct proc_dir_entry * e;
+
+- e = create_proc_info_entry("unit_id", S_IRUGO, pdir,
+- excite_get_unit_id);
++ e = proc_create("unit_id", S_IRUGO, pdir,
++ &excite_unit_id_proc_fops);
+ if (e) e->size = 6;
+
+ e = create_proc_read_entry("bootrom", S_IRUGO, pdir,
+diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig
+index 6db0bda..4f6bce9 100644
+--- a/arch/mips/configs/mipssim_defconfig
++++ b/arch/mips/configs/mipssim_defconfig
+@@ -641,7 +641,6 @@ CONFIG_CROSSCOMPILE=y
+ CONFIG_CMDLINE="nfsroot=192.168.192.169:/u1/mipsel,timeo=20 ip=dhcp"
+ # CONFIG_DEBUG_STACK_USAGE is not set
+ # CONFIG_RUNTIME_DEBUG is not set
+-# CONFIG_MIPS_UNCACHED is not set
- scdp->open = cpm_serial_open;
- scdp->putc = cpm_serial_putc;
-diff --git a/arch/powerpc/boot/cuboot-pq2.c b/arch/powerpc/boot/cuboot-pq2.c
-index f56ac6c..9c7d134 100644
---- a/arch/powerpc/boot/cuboot-pq2.c
-+++ b/arch/powerpc/boot/cuboot-pq2.c
-@@ -128,7 +128,7 @@ static void fixup_pci(void)
- u8 *soc_regs;
- int i, len;
- void *node, *parent_node;
-- u32 naddr, nsize, mem_log2;
-+ u32 naddr, nsize, mem_pow2, mem_mask;
+ #
+ # Security options
+diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig
+index 518a608..780c7fc 100644
+--- a/arch/mips/configs/pnx8550-jbs_defconfig
++++ b/arch/mips/configs/pnx8550-jbs_defconfig
+@@ -1223,7 +1223,6 @@ CONFIG_CMDLINE="console=ttyS1,38400n8 kgdb=ttyS0 root=/dev/nfs ip=bootp"
+ # CONFIG_KGDB is not set
+ CONFIG_SYS_SUPPORTS_KGDB=y
+ # CONFIG_RUNTIME_DEBUG is not set
+-# CONFIG_MIPS_UNCACHED is not set
+
+ #
+ # Security options
+diff --git a/arch/mips/configs/pnx8550-stb810_defconfig b/arch/mips/configs/pnx8550-stb810_defconfig
+index 68351eb..267f21e 100644
+--- a/arch/mips/configs/pnx8550-stb810_defconfig
++++ b/arch/mips/configs/pnx8550-stb810_defconfig
+@@ -1213,7 +1213,6 @@ CONFIG_CMDLINE="console=ttyS1,38400n8 kgdb=ttyS0 root=/dev/nfs ip=bootp"
+ # CONFIG_KGDB is not set
+ CONFIG_SYS_SUPPORTS_KGDB=y
+ # CONFIG_RUNTIME_DEBUG is not set
+-# CONFIG_MIPS_UNCACHED is not set
+
+ #
+ # Security options
+diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c
+index 6034906..3965fda 100644
+--- a/arch/mips/dec/time.c
++++ b/arch/mips/dec/time.c
+@@ -9,30 +9,15 @@
+ *
+ */
+ #include <linux/bcd.h>
+-#include <linux/errno.h>
+ #include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <linux/kernel.h>
+ #include <linux/mc146818rtc.h>
+-#include <linux/mm.h>
+-#include <linux/module.h>
+ #include <linux/param.h>
+-#include <linux/sched.h>
+-#include <linux/string.h>
+-#include <linux/time.h>
+-#include <linux/types.h>
+-
+-#include <asm/bootinfo.h>
+-#include <asm/cpu.h>
+-#include <asm/io.h>
+-#include <asm/irq.h>
+-#include <asm/mipsregs.h>
+-#include <asm/sections.h>
+-#include <asm/time.h>
- node = finddevice("/pci");
- if (!node || !dt_is_compatible(node, "fsl,pq2-pci"))
-@@ -141,7 +141,7 @@ static void fixup_pci(void)
++#include <asm/cpu-features.h>
++#include <asm/ds1287.h>
++#include <asm/time.h>
+ #include <asm/dec/interrupts.h>
+ #include <asm/dec/ioasic.h>
+-#include <asm/dec/ioasic_addrs.h>
+ #include <asm/dec/machtype.h>
- soc_regs = (u8 *)fsl_get_immr();
- if (!soc_regs)
-- goto err;
-+ goto unhandled;
+ unsigned long read_persistent_clock(void)
+@@ -139,42 +124,32 @@ int rtc_mips_set_mmss(unsigned long nowtime)
+ return retval;
+ }
- dt_get_reg_format(node, &naddr, &nsize);
- if (naddr != 3 || nsize != 2)
-@@ -153,7 +153,7 @@ static void fixup_pci(void)
+-static int dec_timer_state(void)
++void __init plat_time_init(void)
+ {
+- return (CMOS_READ(RTC_REG_C) & RTC_PF) != 0;
+-}
++ u32 start, end;
++ int i = HZ / 10;
- dt_get_reg_format(parent_node, &naddr, &nsize);
- if (naddr != 1 || nsize != 1)
-- goto err;
-+ goto unhandled;
+-static void dec_timer_ack(void)
+-{
+- CMOS_READ(RTC_REG_C); /* Ack the RTC interrupt. */
+-}
+-
+-static cycle_t dec_ioasic_hpt_read(void)
+-{
+- /*
+- * The free-running counter is 32-bit which is good for about
+- * 2 minutes, 50 seconds at possible count rates of up to 25MHz.
+- */
+- return ioasic_read(IO_REG_FCTR);
+-}
++ /* Set up the rate of periodic DS1287 interrupts. */
++ ds1287_set_base_clock(HZ);
- len = getprop(node, "ranges", pci_ranges_buf,
- sizeof(pci_ranges_buf));
-@@ -170,14 +170,20 @@ static void fixup_pci(void)
- }
++ if (cpu_has_counter) {
++ while (!ds1287_timer_state())
++ ;
- if (!mem || !mmio || !io)
-- goto err;
-+ goto unhandled;
-+ if (mem->size[1] != mmio->size[1])
-+ goto unhandled;
-+ if (mem->size[1] & (mem->size[1] - 1))
-+ goto unhandled;
-+ if (io->size[1] & (io->size[1] - 1))
-+ goto unhandled;
+-void __init plat_time_init(void)
+-{
+- mips_timer_ack = dec_timer_ack;
++ start = read_c0_count();
- if (mem->phys_addr + mem->size[1] == mmio->phys_addr)
- mem_base = mem;
- else if (mmio->phys_addr + mmio->size[1] == mem->phys_addr)
- mem_base = mmio;
- else
-- goto err;
-+ goto unhandled;
+- if (!cpu_has_counter && IOASIC)
+- /* For pre-R4k systems we use the I/O ASIC's counter. */
+- clocksource_mips.read = dec_ioasic_hpt_read;
++ while (i--)
++ while (!ds1287_timer_state())
++ ;
- out_be32(&pci_regs[1][0], mem_base->phys_addr | 1);
- out_be32(&pci_regs[2][0], ~(mem->size[1] + mmio->size[1] - 1));
-@@ -201,8 +207,9 @@ static void fixup_pci(void)
- out_le32(&pci_regs[0][58], 0);
- out_le32(&pci_regs[0][60], 0);
+- /* Set up the rate of periodic DS1287 interrupts. */
+- CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - __ffs(HZ)), RTC_REG_A);
+-}
++ end = read_c0_count();
-- mem_log2 = 1 << (__ilog2_u32(bd.bi_memsize - 1) + 1);
-- out_le32(&pci_regs[0][62], 0xa0000000 | ~((1 << (mem_log2 - 12)) - 1));
-+ mem_pow2 = 1 << (__ilog2_u32(bd.bi_memsize - 1) + 1);
-+ mem_mask = ~(mem_pow2 - 1) >> 12;
-+ out_le32(&pci_regs[0][62], 0xa0000000 | mem_mask);
+-void __init plat_timer_setup(struct irqaction *irq)
+-{
+- setup_irq(dec_interrupt[DEC_IRQ_RTC], irq);
++ mips_hpt_frequency = (end - start) * 10;
++ printk(KERN_INFO "MIPS counter frequency %dHz\n",
++ mips_hpt_frequency);
++ } else if (IOASIC)
++ /* For pre-R4k systems we use the I/O ASIC's counter. */
++ dec_ioasic_clocksource_init();
+
+- /* Enable periodic DS1287 interrupts. */
+- CMOS_WRITE(CMOS_READ(RTC_REG_B) | RTC_PIE, RTC_REG_B);
++ ds1287_clockevent_init(dec_interrupt[DEC_IRQ_RTC]);
+ }
+diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c
+index c886d80..f39c444 100644
+--- a/arch/mips/jmr3927/rbhma3100/setup.c
++++ b/arch/mips/jmr3927/rbhma3100/setup.c
+@@ -36,11 +36,13 @@
+ #include <linux/pm.h>
+ #include <linux/platform_device.h>
+ #include <linux/clk.h>
++#include <linux/gpio.h>
+ #ifdef CONFIG_SERIAL_TXX9
+ #include <linux/serial_core.h>
+ #endif
- /* If PCI is disabled, drive RST high to enable. */
- if (!(in_le32(&pci_regs[0][32]) & 1)) {
-@@ -228,7 +235,11 @@ static void fixup_pci(void)
- return;
+ #include <asm/txx9tmr.h>
++#include <asm/txx9pio.h>
+ #include <asm/reboot.h>
+ #include <asm/jmr3927/jmr3927.h>
+ #include <asm/mipsregs.h>
+@@ -340,9 +342,12 @@ static void __init tx3927_setup(void)
+
+ /* PIO */
+ /* PIO[15:12] connected to LEDs */
+- tx3927_pioptr->dir = 0x0000f000;
+- tx3927_pioptr->maskcpu = 0;
+- tx3927_pioptr->maskext = 0;
++ __raw_writel(0x0000f000, &tx3927_pioptr->dir);
++ __raw_writel(0, &tx3927_pioptr->maskcpu);
++ __raw_writel(0, &tx3927_pioptr->maskext);
++ txx9_gpio_init(TX3927_PIO_REG, 0, 16);
++ gpio_request(11, "dipsw1");
++ gpio_request(10, "dipsw2");
+ {
+ unsigned int conf;
- err:
-- printf("Bad PCI node\r\n");
-+ printf("Bad PCI node -- using existing firmware setup.\r\n");
-+ return;
-+
-+unhandled:
-+ printf("Unsupported PCI node -- using existing firmware setup.\r\n");
- }
+diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
+index 9e78e1a..45545be 100644
+--- a/arch/mips/kernel/Makefile
++++ b/arch/mips/kernel/Makefile
+@@ -5,17 +5,20 @@
+ extra-y := head.o init_task.o vmlinux.lds
- static void pq2_platform_fixups(void)
-diff --git a/arch/powerpc/boot/cuboot-rainier.c b/arch/powerpc/boot/cuboot-rainier.c
-index cf452b6..0a3fdde 100644
---- a/arch/powerpc/boot/cuboot-rainier.c
-+++ b/arch/powerpc/boot/cuboot-rainier.c
-@@ -42,7 +42,8 @@ static void rainier_fixups(void)
- ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
- ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
- ibm4xx_denali_fixup_memsize();
-- dt_fixup_mac_addresses(&bd.bi_enetaddr, &bd.bi_enet1addr);
-+ dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
-+ dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
- }
+ obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
+- ptrace.o reset.o semaphore.o setup.o signal.o syscall.o \
++ ptrace.o reset.o setup.o signal.o syscall.o \
+ time.o topology.o traps.o unaligned.o
- void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-diff --git a/arch/powerpc/boot/cuboot-sequoia.c b/arch/powerpc/boot/cuboot-sequoia.c
-index f555575..caf8f2e 100644
---- a/arch/powerpc/boot/cuboot-sequoia.c
-+++ b/arch/powerpc/boot/cuboot-sequoia.c
-@@ -42,7 +42,8 @@ static void sequoia_fixups(void)
- ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
- ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
- ibm4xx_denali_fixup_memsize();
-- dt_fixup_mac_addresses(&bd.bi_enetaddr, &bd.bi_enet1addr);
-+ dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
-+ dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
- }
+ obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o
+ obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o
++obj-$(CONFIG_CEVT_DS1287) += cevt-ds1287.o
+ obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o
+ obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o
+ obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o
+ obj-$(CONFIG_CSRC_BCM1480) += csrc-bcm1480.o
++obj-$(CONFIG_CSRC_IOASIC) += csrc-ioasic.o
+ obj-$(CONFIG_CSRC_R4K) += csrc-r4k.o
+ obj-$(CONFIG_CSRC_SB1250) += csrc-sb1250.o
++obj-$(CONFIG_SYNC_R4K) += sync-r4k.o
+
+ binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \
+ irix5sys.o sysirix.o
+@@ -50,6 +53,8 @@ obj-$(CONFIG_MIPS_MT) += mips-mt.o
+ obj-$(CONFIG_MIPS_MT_FPAFF) += mips-mt-fpaff.o
+ obj-$(CONFIG_MIPS_MT_SMTC) += smtc.o smtc-asm.o smtc-proc.o
+ obj-$(CONFIG_MIPS_MT_SMP) += smp-mt.o
++obj-$(CONFIG_MIPS_CMP) += smp-cmp.o
++obj-$(CONFIG_CPU_MIPSR2) += spram.o
+
+ obj-$(CONFIG_MIPS_APSP_KSPD) += kspd.o
+ obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o
+@@ -62,6 +67,7 @@ obj-$(CONFIG_IRQ_CPU_RM9K) += irq-rm9000.o
+ obj-$(CONFIG_MIPS_BOARDS_GEN) += irq-msc01.o
+ obj-$(CONFIG_IRQ_TXX9) += irq_txx9.o
+ obj-$(CONFIG_IRQ_GT641XX) += irq-gt641xx.o
++obj-$(CONFIG_IRQ_GIC) += irq-gic.o
+
+ obj-$(CONFIG_32BIT) += scall32-o32.o
+ obj-$(CONFIG_64BIT) += scall64-64.o
+@@ -77,6 +83,8 @@ obj-$(CONFIG_64BIT) += cpu-bugs64.o
- void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-diff --git a/arch/powerpc/boot/cuboot-taishan.c b/arch/powerpc/boot/cuboot-taishan.c
-index b55b804..9bc906a 100644
---- a/arch/powerpc/boot/cuboot-taishan.c
-+++ b/arch/powerpc/boot/cuboot-taishan.c
-@@ -40,7 +40,8 @@ static void taishan_fixups(void)
+ obj-$(CONFIG_I8253) += i8253.o
- ibm4xx_sdram_fixup_memsize();
++obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o
++
+ obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
-- dt_fixup_mac_addresses(bd.bi_enetaddr, bd.bi_enet1addr);
-+ dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
-+ dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
+diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
+index ca13629..7294222 100644
+--- a/arch/mips/kernel/asm-offsets.c
++++ b/arch/mips/kernel/asm-offsets.c
+@@ -13,327 +13,285 @@
+ #include <linux/sched.h>
+ #include <linux/mm.h>
+ #include <linux/interrupt.h>
+-
++#include <linux/kbuild.h>
+ #include <asm/ptrace.h>
+ #include <asm/processor.h>
- ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
- }
-diff --git a/arch/powerpc/boot/cuboot-warp.c b/arch/powerpc/boot/cuboot-warp.c
-index 3db93e8..eb108a8 100644
---- a/arch/powerpc/boot/cuboot-warp.c
-+++ b/arch/powerpc/boot/cuboot-warp.c
-@@ -24,7 +24,7 @@ static void warp_fixups(void)
- ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
- ibm4xx_sdram_fixup_memsize();
- ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
-- dt_fixup_mac_addresses(&bd.bi_enetaddr);
-+ dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
+-#define text(t) __asm__("\n@@@" t)
+-#define _offset(type, member) (&(((type *)NULL)->member))
+-#define offset(string, ptr, member) \
+- __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member)))
+-#define constant(string, member) \
+- __asm__("\n@@@" string "%X0" : : "ri" (member))
+-#define size(string, size) \
+- __asm__("\n@@@" string "%0" : : "i" (sizeof(size)))
+-#define linefeed text("")
+-
+ void output_ptreg_defines(void)
+ {
+- text("/* MIPS pt_regs offsets. */");
+- offset("#define PT_R0 ", struct pt_regs, regs[0]);
+- offset("#define PT_R1 ", struct pt_regs, regs[1]);
+- offset("#define PT_R2 ", struct pt_regs, regs[2]);
+- offset("#define PT_R3 ", struct pt_regs, regs[3]);
+- offset("#define PT_R4 ", struct pt_regs, regs[4]);
+- offset("#define PT_R5 ", struct pt_regs, regs[5]);
+- offset("#define PT_R6 ", struct pt_regs, regs[6]);
+- offset("#define PT_R7 ", struct pt_regs, regs[7]);
+- offset("#define PT_R8 ", struct pt_regs, regs[8]);
+- offset("#define PT_R9 ", struct pt_regs, regs[9]);
+- offset("#define PT_R10 ", struct pt_regs, regs[10]);
+- offset("#define PT_R11 ", struct pt_regs, regs[11]);
+- offset("#define PT_R12 ", struct pt_regs, regs[12]);
+- offset("#define PT_R13 ", struct pt_regs, regs[13]);
+- offset("#define PT_R14 ", struct pt_regs, regs[14]);
+- offset("#define PT_R15 ", struct pt_regs, regs[15]);
+- offset("#define PT_R16 ", struct pt_regs, regs[16]);
+- offset("#define PT_R17 ", struct pt_regs, regs[17]);
+- offset("#define PT_R18 ", struct pt_regs, regs[18]);
+- offset("#define PT_R19 ", struct pt_regs, regs[19]);
+- offset("#define PT_R20 ", struct pt_regs, regs[20]);
+- offset("#define PT_R21 ", struct pt_regs, regs[21]);
+- offset("#define PT_R22 ", struct pt_regs, regs[22]);
+- offset("#define PT_R23 ", struct pt_regs, regs[23]);
+- offset("#define PT_R24 ", struct pt_regs, regs[24]);
+- offset("#define PT_R25 ", struct pt_regs, regs[25]);
+- offset("#define PT_R26 ", struct pt_regs, regs[26]);
+- offset("#define PT_R27 ", struct pt_regs, regs[27]);
+- offset("#define PT_R28 ", struct pt_regs, regs[28]);
+- offset("#define PT_R29 ", struct pt_regs, regs[29]);
+- offset("#define PT_R30 ", struct pt_regs, regs[30]);
+- offset("#define PT_R31 ", struct pt_regs, regs[31]);
+- offset("#define PT_LO ", struct pt_regs, lo);
+- offset("#define PT_HI ", struct pt_regs, hi);
++ COMMENT("MIPS pt_regs offsets.");
++ OFFSET(PT_R0, pt_regs, regs[0]);
++ OFFSET(PT_R1, pt_regs, regs[1]);
++ OFFSET(PT_R2, pt_regs, regs[2]);
++ OFFSET(PT_R3, pt_regs, regs[3]);
++ OFFSET(PT_R4, pt_regs, regs[4]);
++ OFFSET(PT_R5, pt_regs, regs[5]);
++ OFFSET(PT_R6, pt_regs, regs[6]);
++ OFFSET(PT_R7, pt_regs, regs[7]);
++ OFFSET(PT_R8, pt_regs, regs[8]);
++ OFFSET(PT_R9, pt_regs, regs[9]);
++ OFFSET(PT_R10, pt_regs, regs[10]);
++ OFFSET(PT_R11, pt_regs, regs[11]);
++ OFFSET(PT_R12, pt_regs, regs[12]);
++ OFFSET(PT_R13, pt_regs, regs[13]);
++ OFFSET(PT_R14, pt_regs, regs[14]);
++ OFFSET(PT_R15, pt_regs, regs[15]);
++ OFFSET(PT_R16, pt_regs, regs[16]);
++ OFFSET(PT_R17, pt_regs, regs[17]);
++ OFFSET(PT_R18, pt_regs, regs[18]);
++ OFFSET(PT_R19, pt_regs, regs[19]);
++ OFFSET(PT_R20, pt_regs, regs[20]);
++ OFFSET(PT_R21, pt_regs, regs[21]);
++ OFFSET(PT_R22, pt_regs, regs[22]);
++ OFFSET(PT_R23, pt_regs, regs[23]);
++ OFFSET(PT_R24, pt_regs, regs[24]);
++ OFFSET(PT_R25, pt_regs, regs[25]);
++ OFFSET(PT_R26, pt_regs, regs[26]);
++ OFFSET(PT_R27, pt_regs, regs[27]);
++ OFFSET(PT_R28, pt_regs, regs[28]);
++ OFFSET(PT_R29, pt_regs, regs[29]);
++ OFFSET(PT_R30, pt_regs, regs[30]);
++ OFFSET(PT_R31, pt_regs, regs[31]);
++ OFFSET(PT_LO, pt_regs, lo);
++ OFFSET(PT_HI, pt_regs, hi);
+ #ifdef CONFIG_CPU_HAS_SMARTMIPS
+- offset("#define PT_ACX ", struct pt_regs, acx);
++ OFFSET(PT_ACX, pt_regs, acx);
+ #endif
+- offset("#define PT_EPC ", struct pt_regs, cp0_epc);
+- offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr);
+- offset("#define PT_STATUS ", struct pt_regs, cp0_status);
+- offset("#define PT_CAUSE ", struct pt_regs, cp0_cause);
++ OFFSET(PT_EPC, pt_regs, cp0_epc);
++ OFFSET(PT_BVADDR, pt_regs, cp0_badvaddr);
++ OFFSET(PT_STATUS, pt_regs, cp0_status);
++ OFFSET(PT_CAUSE, pt_regs, cp0_cause);
+ #ifdef CONFIG_MIPS_MT_SMTC
+- offset("#define PT_TCSTATUS ", struct pt_regs, cp0_tcstatus);
++ OFFSET(PT_TCSTATUS, pt_regs, cp0_tcstatus);
+ #endif /* CONFIG_MIPS_MT_SMTC */
+- size("#define PT_SIZE ", struct pt_regs);
+- linefeed;
++ DEFINE(PT_SIZE, sizeof(struct pt_regs));
++ BLANK();
+ }
+
+ void output_task_defines(void)
+ {
+- text("/* MIPS task_struct offsets. */");
+- offset("#define TASK_STATE ", struct task_struct, state);
+- offset("#define TASK_THREAD_INFO ", struct task_struct, stack);
+- offset("#define TASK_FLAGS ", struct task_struct, flags);
+- offset("#define TASK_MM ", struct task_struct, mm);
+- offset("#define TASK_PID ", struct task_struct, pid);
+- size( "#define TASK_STRUCT_SIZE ", struct task_struct);
+- linefeed;
++ COMMENT("MIPS task_struct offsets.");
++ OFFSET(TASK_STATE, task_struct, state);
++ OFFSET(TASK_THREAD_INFO, task_struct, stack);
++ OFFSET(TASK_FLAGS, task_struct, flags);
++ OFFSET(TASK_MM, task_struct, mm);
++ OFFSET(TASK_PID, task_struct, pid);
++ DEFINE(TASK_STRUCT_SIZE, sizeof(struct task_struct));
++ BLANK();
+ }
+
+ void output_thread_info_defines(void)
+ {
+- text("/* MIPS thread_info offsets. */");
+- offset("#define TI_TASK ", struct thread_info, task);
+- offset("#define TI_EXEC_DOMAIN ", struct thread_info, exec_domain);
+- offset("#define TI_FLAGS ", struct thread_info, flags);
+- offset("#define TI_TP_VALUE ", struct thread_info, tp_value);
+- offset("#define TI_CPU ", struct thread_info, cpu);
+- offset("#define TI_PRE_COUNT ", struct thread_info, preempt_count);
+- offset("#define TI_ADDR_LIMIT ", struct thread_info, addr_limit);
+- offset("#define TI_RESTART_BLOCK ", struct thread_info, restart_block);
+- offset("#define TI_REGS ", struct thread_info, regs);
+- constant("#define _THREAD_SIZE ", THREAD_SIZE);
+- constant("#define _THREAD_MASK ", THREAD_MASK);
+- linefeed;
++ COMMENT("MIPS thread_info offsets.");
++ OFFSET(TI_TASK, thread_info, task);
++ OFFSET(TI_EXEC_DOMAIN, thread_info, exec_domain);
++ OFFSET(TI_FLAGS, thread_info, flags);
++ OFFSET(TI_TP_VALUE, thread_info, tp_value);
++ OFFSET(TI_CPU, thread_info, cpu);
++ OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
++ OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
++ OFFSET(TI_RESTART_BLOCK, thread_info, restart_block);
++ OFFSET(TI_REGS, thread_info, regs);
++ DEFINE(_THREAD_SIZE, THREAD_SIZE);
++ DEFINE(_THREAD_MASK, THREAD_MASK);
++ BLANK();
+ }
+
+ void output_thread_defines(void)
+ {
+- text("/* MIPS specific thread_struct offsets. */");
+- offset("#define THREAD_REG16 ", struct task_struct, thread.reg16);
+- offset("#define THREAD_REG17 ", struct task_struct, thread.reg17);
+- offset("#define THREAD_REG18 ", struct task_struct, thread.reg18);
+- offset("#define THREAD_REG19 ", struct task_struct, thread.reg19);
+- offset("#define THREAD_REG20 ", struct task_struct, thread.reg20);
+- offset("#define THREAD_REG21 ", struct task_struct, thread.reg21);
+- offset("#define THREAD_REG22 ", struct task_struct, thread.reg22);
+- offset("#define THREAD_REG23 ", struct task_struct, thread.reg23);
+- offset("#define THREAD_REG29 ", struct task_struct, thread.reg29);
+- offset("#define THREAD_REG30 ", struct task_struct, thread.reg30);
+- offset("#define THREAD_REG31 ", struct task_struct, thread.reg31);
+- offset("#define THREAD_STATUS ", struct task_struct,
++ COMMENT("MIPS specific thread_struct offsets.");
++ OFFSET(THREAD_REG16, task_struct, thread.reg16);
++ OFFSET(THREAD_REG17, task_struct, thread.reg17);
++ OFFSET(THREAD_REG18, task_struct, thread.reg18);
++ OFFSET(THREAD_REG19, task_struct, thread.reg19);
++ OFFSET(THREAD_REG20, task_struct, thread.reg20);
++ OFFSET(THREAD_REG21, task_struct, thread.reg21);
++ OFFSET(THREAD_REG22, task_struct, thread.reg22);
++ OFFSET(THREAD_REG23, task_struct, thread.reg23);
++ OFFSET(THREAD_REG29, task_struct, thread.reg29);
++ OFFSET(THREAD_REG30, task_struct, thread.reg30);
++ OFFSET(THREAD_REG31, task_struct, thread.reg31);
++ OFFSET(THREAD_STATUS, task_struct,
+ thread.cp0_status);
+- offset("#define THREAD_FPU ", struct task_struct, thread.fpu);
++ OFFSET(THREAD_FPU, task_struct, thread.fpu);
+
+- offset("#define THREAD_BVADDR ", struct task_struct, \
++ OFFSET(THREAD_BVADDR, task_struct, \
+ thread.cp0_badvaddr);
+- offset("#define THREAD_BUADDR ", struct task_struct, \
++ OFFSET(THREAD_BUADDR, task_struct, \
+ thread.cp0_baduaddr);
+- offset("#define THREAD_ECODE ", struct task_struct, \
++ OFFSET(THREAD_ECODE, task_struct, \
+ thread.error_code);
+- offset("#define THREAD_TRAPNO ", struct task_struct, thread.trap_no);
+- offset("#define THREAD_TRAMP ", struct task_struct, \
++ OFFSET(THREAD_TRAPNO, task_struct, thread.trap_no);
++ OFFSET(THREAD_TRAMP, task_struct, \
+ thread.irix_trampoline);
+- offset("#define THREAD_OLDCTX ", struct task_struct, \
++ OFFSET(THREAD_OLDCTX, task_struct, \
+ thread.irix_oldctx);
+- linefeed;
++ BLANK();
+ }
+
+ void output_thread_fpu_defines(void)
+ {
+- offset("#define THREAD_FPR0 ",
+- struct task_struct, thread.fpu.fpr[0]);
+- offset("#define THREAD_FPR1 ",
+- struct task_struct, thread.fpu.fpr[1]);
+- offset("#define THREAD_FPR2 ",
+- struct task_struct, thread.fpu.fpr[2]);
+- offset("#define THREAD_FPR3 ",
+- struct task_struct, thread.fpu.fpr[3]);
+- offset("#define THREAD_FPR4 ",
+- struct task_struct, thread.fpu.fpr[4]);
+- offset("#define THREAD_FPR5 ",
+- struct task_struct, thread.fpu.fpr[5]);
+- offset("#define THREAD_FPR6 ",
+- struct task_struct, thread.fpu.fpr[6]);
+- offset("#define THREAD_FPR7 ",
+- struct task_struct, thread.fpu.fpr[7]);
+- offset("#define THREAD_FPR8 ",
+- struct task_struct, thread.fpu.fpr[8]);
+- offset("#define THREAD_FPR9 ",
+- struct task_struct, thread.fpu.fpr[9]);
+- offset("#define THREAD_FPR10 ",
+- struct task_struct, thread.fpu.fpr[10]);
+- offset("#define THREAD_FPR11 ",
+- struct task_struct, thread.fpu.fpr[11]);
+- offset("#define THREAD_FPR12 ",
+- struct task_struct, thread.fpu.fpr[12]);
+- offset("#define THREAD_FPR13 ",
+- struct task_struct, thread.fpu.fpr[13]);
+- offset("#define THREAD_FPR14 ",
+- struct task_struct, thread.fpu.fpr[14]);
+- offset("#define THREAD_FPR15 ",
+- struct task_struct, thread.fpu.fpr[15]);
+- offset("#define THREAD_FPR16 ",
+- struct task_struct, thread.fpu.fpr[16]);
+- offset("#define THREAD_FPR17 ",
+- struct task_struct, thread.fpu.fpr[17]);
+- offset("#define THREAD_FPR18 ",
+- struct task_struct, thread.fpu.fpr[18]);
+- offset("#define THREAD_FPR19 ",
+- struct task_struct, thread.fpu.fpr[19]);
+- offset("#define THREAD_FPR20 ",
+- struct task_struct, thread.fpu.fpr[20]);
+- offset("#define THREAD_FPR21 ",
+- struct task_struct, thread.fpu.fpr[21]);
+- offset("#define THREAD_FPR22 ",
+- struct task_struct, thread.fpu.fpr[22]);
+- offset("#define THREAD_FPR23 ",
+- struct task_struct, thread.fpu.fpr[23]);
+- offset("#define THREAD_FPR24 ",
+- struct task_struct, thread.fpu.fpr[24]);
+- offset("#define THREAD_FPR25 ",
+- struct task_struct, thread.fpu.fpr[25]);
+- offset("#define THREAD_FPR26 ",
+- struct task_struct, thread.fpu.fpr[26]);
+- offset("#define THREAD_FPR27 ",
+- struct task_struct, thread.fpu.fpr[27]);
+- offset("#define THREAD_FPR28 ",
+- struct task_struct, thread.fpu.fpr[28]);
+- offset("#define THREAD_FPR29 ",
+- struct task_struct, thread.fpu.fpr[29]);
+- offset("#define THREAD_FPR30 ",
+- struct task_struct, thread.fpu.fpr[30]);
+- offset("#define THREAD_FPR31 ",
+- struct task_struct, thread.fpu.fpr[31]);
++ OFFSET(THREAD_FPR0, task_struct, thread.fpu.fpr[0]);
++ OFFSET(THREAD_FPR1, task_struct, thread.fpu.fpr[1]);
++ OFFSET(THREAD_FPR2, task_struct, thread.fpu.fpr[2]);
++ OFFSET(THREAD_FPR3, task_struct, thread.fpu.fpr[3]);
++ OFFSET(THREAD_FPR4, task_struct, thread.fpu.fpr[4]);
++ OFFSET(THREAD_FPR5, task_struct, thread.fpu.fpr[5]);
++ OFFSET(THREAD_FPR6, task_struct, thread.fpu.fpr[6]);
++ OFFSET(THREAD_FPR7, task_struct, thread.fpu.fpr[7]);
++ OFFSET(THREAD_FPR8, task_struct, thread.fpu.fpr[8]);
++ OFFSET(THREAD_FPR9, task_struct, thread.fpu.fpr[9]);
++ OFFSET(THREAD_FPR10, task_struct, thread.fpu.fpr[10]);
++ OFFSET(THREAD_FPR11, task_struct, thread.fpu.fpr[11]);
++ OFFSET(THREAD_FPR12, task_struct, thread.fpu.fpr[12]);
++ OFFSET(THREAD_FPR13, task_struct, thread.fpu.fpr[13]);
++ OFFSET(THREAD_FPR14, task_struct, thread.fpu.fpr[14]);
++ OFFSET(THREAD_FPR15, task_struct, thread.fpu.fpr[15]);
++ OFFSET(THREAD_FPR16, task_struct, thread.fpu.fpr[16]);
++ OFFSET(THREAD_FPR17, task_struct, thread.fpu.fpr[17]);
++ OFFSET(THREAD_FPR18, task_struct, thread.fpu.fpr[18]);
++ OFFSET(THREAD_FPR19, task_struct, thread.fpu.fpr[19]);
++ OFFSET(THREAD_FPR20, task_struct, thread.fpu.fpr[20]);
++ OFFSET(THREAD_FPR21, task_struct, thread.fpu.fpr[21]);
++ OFFSET(THREAD_FPR22, task_struct, thread.fpu.fpr[22]);
++ OFFSET(THREAD_FPR23, task_struct, thread.fpu.fpr[23]);
++ OFFSET(THREAD_FPR24, task_struct, thread.fpu.fpr[24]);
++ OFFSET(THREAD_FPR25, task_struct, thread.fpu.fpr[25]);
++ OFFSET(THREAD_FPR26, task_struct, thread.fpu.fpr[26]);
++ OFFSET(THREAD_FPR27, task_struct, thread.fpu.fpr[27]);
++ OFFSET(THREAD_FPR28, task_struct, thread.fpu.fpr[28]);
++ OFFSET(THREAD_FPR29, task_struct, thread.fpu.fpr[29]);
++ OFFSET(THREAD_FPR30, task_struct, thread.fpu.fpr[30]);
++ OFFSET(THREAD_FPR31, task_struct, thread.fpu.fpr[31]);
+
+- offset("#define THREAD_FCR31 ",
+- struct task_struct, thread.fpu.fcr31);
+- linefeed;
++ OFFSET(THREAD_FCR31, task_struct, thread.fpu.fcr31);
++ BLANK();
+ }
+
+ void output_mm_defines(void)
+ {
+- text("/* Size of struct page */");
+- size("#define STRUCT_PAGE_SIZE ", struct page);
+- linefeed;
+- text("/* Linux mm_struct offsets. */");
+- offset("#define MM_USERS ", struct mm_struct, mm_users);
+- offset("#define MM_PGD ", struct mm_struct, pgd);
+- offset("#define MM_CONTEXT ", struct mm_struct, context);
+- linefeed;
+- constant("#define _PAGE_SIZE ", PAGE_SIZE);
+- constant("#define _PAGE_SHIFT ", PAGE_SHIFT);
+- linefeed;
+- constant("#define _PGD_T_SIZE ", sizeof(pgd_t));
+- constant("#define _PMD_T_SIZE ", sizeof(pmd_t));
+- constant("#define _PTE_T_SIZE ", sizeof(pte_t));
+- linefeed;
+- constant("#define _PGD_T_LOG2 ", PGD_T_LOG2);
+- constant("#define _PMD_T_LOG2 ", PMD_T_LOG2);
+- constant("#define _PTE_T_LOG2 ", PTE_T_LOG2);
+- linefeed;
+- constant("#define _PGD_ORDER ", PGD_ORDER);
+- constant("#define _PMD_ORDER ", PMD_ORDER);
+- constant("#define _PTE_ORDER ", PTE_ORDER);
+- linefeed;
+- constant("#define _PMD_SHIFT ", PMD_SHIFT);
+- constant("#define _PGDIR_SHIFT ", PGDIR_SHIFT);
+- linefeed;
+- constant("#define _PTRS_PER_PGD ", PTRS_PER_PGD);
+- constant("#define _PTRS_PER_PMD ", PTRS_PER_PMD);
+- constant("#define _PTRS_PER_PTE ", PTRS_PER_PTE);
+- linefeed;
++ COMMENT("Size of struct page");
++ DEFINE(STRUCT_PAGE_SIZE, sizeof(struct page));
++ BLANK();
++ COMMENT("Linux mm_struct offsets.");
++ OFFSET(MM_USERS, mm_struct, mm_users);
++ OFFSET(MM_PGD, mm_struct, pgd);
++ OFFSET(MM_CONTEXT, mm_struct, context);
++ BLANK();
++ DEFINE(_PAGE_SIZE, PAGE_SIZE);
++ DEFINE(_PAGE_SHIFT, PAGE_SHIFT);
++ BLANK();
++ DEFINE(_PGD_T_SIZE, sizeof(pgd_t));
++ DEFINE(_PMD_T_SIZE, sizeof(pmd_t));
++ DEFINE(_PTE_T_SIZE, sizeof(pte_t));
++ BLANK();
++ DEFINE(_PGD_T_LOG2, PGD_T_LOG2);
++ DEFINE(_PMD_T_LOG2, PMD_T_LOG2);
++ DEFINE(_PTE_T_LOG2, PTE_T_LOG2);
++ BLANK();
++ DEFINE(_PGD_ORDER, PGD_ORDER);
++ DEFINE(_PMD_ORDER, PMD_ORDER);
++ DEFINE(_PTE_ORDER, PTE_ORDER);
++ BLANK();
++ DEFINE(_PMD_SHIFT, PMD_SHIFT);
++ DEFINE(_PGDIR_SHIFT, PGDIR_SHIFT);
++ BLANK();
++ DEFINE(_PTRS_PER_PGD, PTRS_PER_PGD);
++ DEFINE(_PTRS_PER_PMD, PTRS_PER_PMD);
++ DEFINE(_PTRS_PER_PTE, PTRS_PER_PTE);
++ BLANK();
+ }
+
+ #ifdef CONFIG_32BIT
+ void output_sc_defines(void)
+ {
+- text("/* Linux sigcontext offsets. */");
+- offset("#define SC_REGS ", struct sigcontext, sc_regs);
+- offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs);
+- offset("#define SC_ACX ", struct sigcontext, sc_acx);
+- offset("#define SC_MDHI ", struct sigcontext, sc_mdhi);
+- offset("#define SC_MDLO ", struct sigcontext, sc_mdlo);
+- offset("#define SC_PC ", struct sigcontext, sc_pc);
+- offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr);
+- offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir);
+- offset("#define SC_HI1 ", struct sigcontext, sc_hi1);
+- offset("#define SC_LO1 ", struct sigcontext, sc_lo1);
+- offset("#define SC_HI2 ", struct sigcontext, sc_hi2);
+- offset("#define SC_LO2 ", struct sigcontext, sc_lo2);
+- offset("#define SC_HI3 ", struct sigcontext, sc_hi3);
+- offset("#define SC_LO3 ", struct sigcontext, sc_lo3);
+- linefeed;
++ COMMENT("Linux sigcontext offsets.");
++ OFFSET(SC_REGS, sigcontext, sc_regs);
++ OFFSET(SC_FPREGS, sigcontext, sc_fpregs);
++ OFFSET(SC_ACX, sigcontext, sc_acx);
++ OFFSET(SC_MDHI, sigcontext, sc_mdhi);
++ OFFSET(SC_MDLO, sigcontext, sc_mdlo);
++ OFFSET(SC_PC, sigcontext, sc_pc);
++ OFFSET(SC_FPC_CSR, sigcontext, sc_fpc_csr);
++ OFFSET(SC_FPC_EIR, sigcontext, sc_fpc_eir);
++ OFFSET(SC_HI1, sigcontext, sc_hi1);
++ OFFSET(SC_LO1, sigcontext, sc_lo1);
++ OFFSET(SC_HI2, sigcontext, sc_hi2);
++ OFFSET(SC_LO2, sigcontext, sc_lo2);
++ OFFSET(SC_HI3, sigcontext, sc_hi3);
++ OFFSET(SC_LO3, sigcontext, sc_lo3);
++ BLANK();
}
+ #endif
-
-diff --git a/arch/powerpc/boot/cuboot-yosemite.c b/arch/powerpc/boot/cuboot-yosemite.c
+ #ifdef CONFIG_64BIT
+ void output_sc_defines(void)
+ {
+- text("/* Linux sigcontext offsets. */");
+- offset("#define SC_REGS ", struct sigcontext, sc_regs);
+- offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs);
+- offset("#define SC_MDHI ", struct sigcontext, sc_mdhi);
+- offset("#define SC_MDLO ", struct sigcontext, sc_mdlo);
+- offset("#define SC_PC ", struct sigcontext, sc_pc);
+- offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr);
+- linefeed;
++ COMMENT("Linux sigcontext offsets.");
++ OFFSET(SC_REGS, sigcontext, sc_regs);
++ OFFSET(SC_FPREGS, sigcontext, sc_fpregs);
++ OFFSET(SC_MDHI, sigcontext, sc_mdhi);
++ OFFSET(SC_MDLO, sigcontext, sc_mdlo);
++ OFFSET(SC_PC, sigcontext, sc_pc);
++ OFFSET(SC_FPC_CSR, sigcontext, sc_fpc_csr);
++ BLANK();
+ }
+ #endif
+
+ #ifdef CONFIG_MIPS32_COMPAT
+ void output_sc32_defines(void)
+ {
+- text("/* Linux 32-bit sigcontext offsets. */");
+- offset("#define SC32_FPREGS ", struct sigcontext32, sc_fpregs);
+- offset("#define SC32_FPC_CSR ", struct sigcontext32, sc_fpc_csr);
+- offset("#define SC32_FPC_EIR ", struct sigcontext32, sc_fpc_eir);
+- linefeed;
++ COMMENT("Linux 32-bit sigcontext offsets.");
++ OFFSET(SC32_FPREGS, sigcontext32, sc_fpregs);
++ OFFSET(SC32_FPC_CSR, sigcontext32, sc_fpc_csr);
++ OFFSET(SC32_FPC_EIR, sigcontext32, sc_fpc_eir);
++ BLANK();
+ }
+ #endif
+
+ void output_signal_defined(void)
+ {
+- text("/* Linux signal numbers. */");
+- constant("#define _SIGHUP ", SIGHUP);
+- constant("#define _SIGINT ", SIGINT);
+- constant("#define _SIGQUIT ", SIGQUIT);
+- constant("#define _SIGILL ", SIGILL);
+- constant("#define _SIGTRAP ", SIGTRAP);
+- constant("#define _SIGIOT ", SIGIOT);
+- constant("#define _SIGABRT ", SIGABRT);
+- constant("#define _SIGEMT ", SIGEMT);
+- constant("#define _SIGFPE ", SIGFPE);
+- constant("#define _SIGKILL ", SIGKILL);
+- constant("#define _SIGBUS ", SIGBUS);
+- constant("#define _SIGSEGV ", SIGSEGV);
+- constant("#define _SIGSYS ", SIGSYS);
+- constant("#define _SIGPIPE ", SIGPIPE);
+- constant("#define _SIGALRM ", SIGALRM);
+- constant("#define _SIGTERM ", SIGTERM);
+- constant("#define _SIGUSR1 ", SIGUSR1);
+- constant("#define _SIGUSR2 ", SIGUSR2);
+- constant("#define _SIGCHLD ", SIGCHLD);
+- constant("#define _SIGPWR ", SIGPWR);
+- constant("#define _SIGWINCH ", SIGWINCH);
+- constant("#define _SIGURG ", SIGURG);
+- constant("#define _SIGIO ", SIGIO);
+- constant("#define _SIGSTOP ", SIGSTOP);
+- constant("#define _SIGTSTP ", SIGTSTP);
+- constant("#define _SIGCONT ", SIGCONT);
+- constant("#define _SIGTTIN ", SIGTTIN);
+- constant("#define _SIGTTOU ", SIGTTOU);
+- constant("#define _SIGVTALRM ", SIGVTALRM);
+- constant("#define _SIGPROF ", SIGPROF);
+- constant("#define _SIGXCPU ", SIGXCPU);
+- constant("#define _SIGXFSZ ", SIGXFSZ);
+- linefeed;
++ COMMENT("Linux signal numbers.");
++ DEFINE(_SIGHUP, SIGHUP);
++ DEFINE(_SIGINT, SIGINT);
++ DEFINE(_SIGQUIT, SIGQUIT);
++ DEFINE(_SIGILL, SIGILL);
++ DEFINE(_SIGTRAP, SIGTRAP);
++ DEFINE(_SIGIOT, SIGIOT);
++ DEFINE(_SIGABRT, SIGABRT);
++ DEFINE(_SIGEMT, SIGEMT);
++ DEFINE(_SIGFPE, SIGFPE);
++ DEFINE(_SIGKILL, SIGKILL);
++ DEFINE(_SIGBUS, SIGBUS);
++ DEFINE(_SIGSEGV, SIGSEGV);
++ DEFINE(_SIGSYS, SIGSYS);
++ DEFINE(_SIGPIPE, SIGPIPE);
++ DEFINE(_SIGALRM, SIGALRM);
++ DEFINE(_SIGTERM, SIGTERM);
++ DEFINE(_SIGUSR1, SIGUSR1);
++ DEFINE(_SIGUSR2, SIGUSR2);
++ DEFINE(_SIGCHLD, SIGCHLD);
++ DEFINE(_SIGPWR, SIGPWR);
++ DEFINE(_SIGWINCH, SIGWINCH);
++ DEFINE(_SIGURG, SIGURG);
++ DEFINE(_SIGIO, SIGIO);
++ DEFINE(_SIGSTOP, SIGSTOP);
++ DEFINE(_SIGTSTP, SIGTSTP);
++ DEFINE(_SIGCONT, SIGCONT);
++ DEFINE(_SIGTTIN, SIGTTIN);
++ DEFINE(_SIGTTOU, SIGTTOU);
++ DEFINE(_SIGVTALRM, SIGVTALRM);
++ DEFINE(_SIGPROF, SIGPROF);
++ DEFINE(_SIGXCPU, SIGXCPU);
++ DEFINE(_SIGXFSZ, SIGXFSZ);
++ BLANK();
+ }
+
+ void output_irq_cpustat_t_defines(void)
+ {
+- text("/* Linux irq_cpustat_t offsets. */");
+- offset("#define IC_SOFTIRQ_PENDING ", irq_cpustat_t, __softirq_pending);
+- size("#define IC_IRQ_CPUSTAT_T ", irq_cpustat_t);
+- linefeed;
++ COMMENT("Linux irq_cpustat_t offsets.");
++ DEFINE(IC_SOFTIRQ_PENDING,
++ offsetof(irq_cpustat_t, __softirq_pending));
++ DEFINE(IC_IRQ_CPUSTAT_T, sizeof(irq_cpustat_t));
++ BLANK();
+ }
+diff --git a/arch/mips/kernel/cevt-ds1287.c b/arch/mips/kernel/cevt-ds1287.c
new file mode 100644
-index 0000000..cc6e338
+index 0000000..df4acb6
--- /dev/null
-+++ b/arch/powerpc/boot/cuboot-yosemite.c
-@@ -0,0 +1,44 @@
++++ b/arch/mips/kernel/cevt-ds1287.c
+@@ -0,0 +1,129 @@
+/*
-+ * Old U-boot compatibility for Yosemite
++ * DS1287 clockevent driver
+ *
-+ * Author: Josh Boyer <jwboyer at linux.vnet.ibm.com>
++ * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa at tripeaks.co.jp>
+ *
-+ * 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 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
+ */
++#include <linux/clockchips.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/mc146818rtc.h>
+
-+#include "ops.h"
-+#include "stdio.h"
-+#include "4xx.h"
-+#include "44x.h"
-+#include "cuboot.h"
-+
-+#define TARGET_4xx
-+#define TARGET_44x
-+#include "ppcboot.h"
++#include <asm/time.h>
+
-+static bd_t bd;
++int ds1287_timer_state(void)
++{
++ return (CMOS_READ(RTC_REG_C) & RTC_PF) != 0;
++}
+
-+static void yosemite_fixups(void)
++int ds1287_set_base_clock(unsigned int hz)
+{
-+ unsigned long sysclk = 66666666;
++ u8 rate;
+
-+ ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
-+ ibm4xx_sdram_fixup_memsize();
-+ ibm4xx_quiesce_eth((u32 *)0xef600e00, (u32 *)0xef600f00);
-+ dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
-+ dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
++ switch (hz) {
++ case 128:
++ rate = 0x9;
++ break;
++ case 256:
++ rate = 0x8;
++ break;
++ case 1024:
++ rate = 0x6;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ CMOS_WRITE(RTC_REF_CLCK_32KHZ | rate, RTC_REG_A);
++
++ return 0;
+}
+
-+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-+ unsigned long r6, unsigned long r7)
++static int ds1287_set_next_event(unsigned long delta,
++ struct clock_event_device *evt)
+{
-+ CUBOOT_INIT();
-+ platform_ops.fixups = yosemite_fixups;
-+ platform_ops.exit = ibm44x_dbcr_reset;
-+ fdt_init(_dtb_start);
-+ serial_console_init();
++ return -EINVAL;
+}
-diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c
-index 60f561e..5d12336 100644
---- a/arch/powerpc/boot/devtree.c
-+++ b/arch/powerpc/boot/devtree.c
-@@ -350,3 +350,23 @@ int dt_is_compatible(void *node, const char *compat)
-
- return 0;
- }
+
-+int dt_get_virtual_reg(void *node, void **addr, int nres)
++static void ds1287_set_mode(enum clock_event_mode mode,
++ struct clock_event_device *evt)
+{
-+ unsigned long xaddr;
-+ int n;
++ u8 val;
+
-+ n = getprop(node, "virtual-reg", addr, nres * 4);
-+ if (n > 0)
-+ return n / 4;
++ spin_lock(&rtc_lock);
+
-+ for (n = 0; n < nres; n++) {
-+ if (!dt_xlate_reg(node, n, &xaddr, NULL))
-+ break;
++ val = CMOS_READ(RTC_REG_B);
+
-+ addr[n] = (void *)xaddr;
++ switch (mode) {
++ case CLOCK_EVT_MODE_PERIODIC:
++ val |= RTC_PIE;
++ break;
++ default:
++ val &= ~RTC_PIE;
++ break;
+ }
+
-+ return n;
++ CMOS_WRITE(val, RTC_REG_B);
++
++ spin_unlock(&rtc_lock);
+}
+
-diff --git a/arch/powerpc/boot/dts/bamboo.dts b/arch/powerpc/boot/dts/bamboo.dts
-index 7dc37c9..ba2521b 100644
---- a/arch/powerpc/boot/dts/bamboo.dts
-+++ b/arch/powerpc/boot/dts/bamboo.dts
-@@ -204,7 +204,6 @@
- };
++static void ds1287_event_handler(struct clock_event_device *dev)
++{
++}
++
++static struct clock_event_device ds1287_clockevent = {
++ .name = "ds1287",
++ .features = CLOCK_EVT_FEAT_PERIODIC,
++ .cpumask = CPU_MASK_CPU0,
++ .set_next_event = ds1287_set_next_event,
++ .set_mode = ds1287_set_mode,
++ .event_handler = ds1287_event_handler,
++};
++
++static irqreturn_t ds1287_interrupt(int irq, void *dev_id)
++{
++ struct clock_event_device *cd = &ds1287_clockevent;
++
++ /* Ack the RTC interrupt. */
++ CMOS_READ(RTC_REG_C);
++
++ cd->event_handler(cd);
++
++ return IRQ_HANDLED;
++}
++
++static struct irqaction ds1287_irqaction = {
++ .handler = ds1287_interrupt,
++ .flags = IRQF_DISABLED | IRQF_PERCPU,
++ .name = "ds1287",
++};
++
++int __init ds1287_clockevent_init(int irq)
++{
++ struct clock_event_device *cd;
++
++ cd = &ds1287_clockevent;
++ cd->rating = 100;
++ cd->irq = irq;
++ clockevent_set_clock(cd, 32768);
++ cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
++ cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
++
++ clockevents_register_device(&ds1287_clockevent);
++
++ return setup_irq(irq, &ds1287_irqaction);
++}
+diff --git a/arch/mips/kernel/cevt-gt641xx.c b/arch/mips/kernel/cevt-gt641xx.c
+index c367726..6e2f585 100644
+--- a/arch/mips/kernel/cevt-gt641xx.c
++++ b/arch/mips/kernel/cevt-gt641xx.c
+@@ -25,8 +25,6 @@
+ #include <asm/gt64120.h>
+ #include <asm/time.h>
- EMAC0: ethernet at ef600e00 {
-- linux,network-index = <0>;
- device_type = "network";
- compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
- interrupt-parent = <&UIC1>;
-@@ -225,7 +224,6 @@
- };
+-#include <irq.h>
+-
+ static DEFINE_SPINLOCK(gt641xx_timer_lock);
+ static unsigned int gt641xx_base_clock;
- EMAC1: ethernet at ef600f00 {
-- linux,network-index = <1>;
- device_type = "network";
- compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
- interrupt-parent = <&UIC1>;
-diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts
+diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
+index 89c3304..335a6ae 100644
+--- a/arch/mips/kernel/cpu-probe.c
++++ b/arch/mips/kernel/cpu-probe.c
+@@ -169,6 +169,7 @@ static inline void check_wait(void)
+
+ case CPU_24K:
+ case CPU_34K:
++ case CPU_1004K:
+ cpu_wait = r4k_wait;
+ if (read_c0_config7() & MIPS_CONF7_WII)
+ cpu_wait = r4k_wait_irqoff;
+@@ -675,6 +676,12 @@ static void __cpuinit decode_configs(struct cpuinfo_mips *c)
+ return;
+ }
+
++#ifdef CONFIG_CPU_MIPSR2
++extern void spram_config(void);
++#else
++static inline void spram_config(void) {}
++#endif
++
+ static inline void cpu_probe_mips(struct cpuinfo_mips *c)
+ {
+ decode_configs(c);
+@@ -711,7 +718,12 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c)
+ case PRID_IMP_74K:
+ c->cputype = CPU_74K;
+ break;
++ case PRID_IMP_1004K:
++ c->cputype = CPU_1004K;
++ break;
+ }
++
++ spram_config();
+ }
+
+ static inline void cpu_probe_alchemy(struct cpuinfo_mips *c)
+@@ -778,7 +790,7 @@ static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c)
+ }
+ }
+
+-static inline void cpu_probe_philips(struct cpuinfo_mips *c)
++static inline void cpu_probe_nxp(struct cpuinfo_mips *c)
+ {
+ decode_configs(c);
+ switch (c->processor_id & 0xff00) {
+@@ -787,7 +799,7 @@ static inline void cpu_probe_philips(struct cpuinfo_mips *c)
+ c->isa_level = MIPS_CPU_ISA_M32R1;
+ break;
+ default:
+- panic("Unknown Philips Core!"); /* REVISIT: die? */
++ panic("Unknown NXP Core!"); /* REVISIT: die? */
+ break;
+ }
+ }
+@@ -876,6 +888,7 @@ static __cpuinit const char *cpu_to_name(struct cpuinfo_mips *c)
+ case CPU_24K: name = "MIPS 24K"; break;
+ case CPU_25KF: name = "MIPS 25Kf"; break;
+ case CPU_34K: name = "MIPS 34K"; break;
++ case CPU_1004K: name = "MIPS 1004K"; break;
+ case CPU_74K: name = "MIPS 74K"; break;
+ case CPU_VR4111: name = "NEC VR4111"; break;
+ case CPU_VR4121: name = "NEC VR4121"; break;
+@@ -925,8 +938,8 @@ __cpuinit void cpu_probe(void)
+ case PRID_COMP_SANDCRAFT:
+ cpu_probe_sandcraft(c);
+ break;
+- case PRID_COMP_PHILIPS:
+- cpu_probe_philips(c);
++ case PRID_COMP_NXP:
++ cpu_probe_nxp(c);
+ break;
+ default:
+ c->cputype = CPU_UNKNOWN;
+diff --git a/arch/mips/kernel/csrc-ioasic.c b/arch/mips/kernel/csrc-ioasic.c
new file mode 100644
-index 0000000..3963412
+index 0000000..1d5f63c
--- /dev/null
-+++ b/arch/powerpc/boot/dts/canyonlands.dts
-@@ -0,0 +1,439 @@
++++ b/arch/mips/kernel/csrc-ioasic.c
+@@ -0,0 +1,65 @@
+/*
-+ * Device Tree Source for AMCC Canyonlands (460EX)
++ * DEC I/O ASIC's counter clocksource
+ *
-+ * Copyright 2008 DENX Software Engineering, Stefan Roese <sr at denx.de>
++ * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa at tripeaks.co.jp>
+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
++#include <linux/clocksource.h>
++#include <linux/init.h>
+
-+/ {
-+ #address-cells = <2>;
-+ #size-cells = <1>;
-+ model = "amcc,canyonlands";
-+ compatible = "amcc,canyonlands";
-+ dcr-parent = <&/cpus/cpu at 0>;
-+
-+ aliases {
-+ ethernet0 = &EMAC0;
-+ ethernet1 = &EMAC1;
-+ serial0 = &UART0;
-+ serial1 = &UART1;
-+ };
++#include <asm/ds1287.h>
++#include <asm/time.h>
++#include <asm/dec/ioasic.h>
++#include <asm/dec/ioasic_addrs.h>
+
-+ cpus {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
++static cycle_t dec_ioasic_hpt_read(void)
++{
++ return ioasic_read(IO_REG_FCTR);
++}
+
-+ cpu at 0 {
-+ device_type = "cpu";
-+ model = "PowerPC,460EX";
-+ reg = <0>;
-+ clock-frequency = <0>; /* Filled in by U-Boot */
-+ timebase-frequency = <0>; /* Filled in by U-Boot */
-+ i-cache-line-size = <20>;
-+ d-cache-line-size = <20>;
-+ i-cache-size = <8000>;
-+ d-cache-size = <8000>;
-+ dcr-controller;
-+ dcr-access-method = "native";
-+ };
-+ };
++static struct clocksource clocksource_dec = {
++ .name = "dec-ioasic",
++ .read = dec_ioasic_hpt_read,
++ .mask = CLOCKSOURCE_MASK(32),
++ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
++};
+
-+ memory {
-+ device_type = "memory";
-+ reg = <0 0 0>; /* Filled in by U-Boot */
-+ };
++void __init dec_ioasic_clocksource_init(void)
++{
++ unsigned int freq;
++ u32 start, end;
++ int i = HZ / 10;
+
-+ UIC0: interrupt-controller0 {
-+ compatible = "ibm,uic-460ex","ibm,uic";
-+ interrupt-controller;
-+ cell-index = <0>;
-+ dcr-reg = <0c0 009>;
-+ #address-cells = <0>;
-+ #size-cells = <0>;
-+ #interrupt-cells = <2>;
-+ };
+
-+ UIC1: interrupt-controller1 {
-+ compatible = "ibm,uic-460ex","ibm,uic";
-+ interrupt-controller;
-+ cell-index = <1>;
-+ dcr-reg = <0d0 009>;
-+ #address-cells = <0>;
-+ #size-cells = <0>;
-+ #interrupt-cells = <2>;
-+ interrupts = <1e 4 1f 4>; /* cascade */
-+ interrupt-parent = <&UIC0>;
-+ };
++ while (!ds1287_timer_state())
++ ;
+
-+ UIC2: interrupt-controller2 {
-+ compatible = "ibm,uic-460ex","ibm,uic";
-+ interrupt-controller;
-+ cell-index = <2>;
-+ dcr-reg = <0e0 009>;
-+ #address-cells = <0>;
-+ #size-cells = <0>;
-+ #interrupt-cells = <2>;
-+ interrupts = <a 4 b 4>; /* cascade */
-+ interrupt-parent = <&UIC0>;
-+ };
++ start = dec_ioasic_hpt_read();
+
-+ 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>;
-+ };
++ while (i--)
++ while (!ds1287_timer_state())
++ ;
+
-+ SDR0: sdr {
-+ compatible = "ibm,sdr-460ex";
-+ dcr-reg = <00e 002>;
-+ };
++ end = dec_ioasic_hpt_read();
+
-+ CPR0: cpr {
-+ compatible = "ibm,cpr-460ex";
-+ dcr-reg = <00c 002>;
-+ };
++ freq = (end - start) * 10;
++ printk(KERN_INFO "I/O ASIC clock frequency %dHz\n", freq);
+
-+ plb {
-+ compatible = "ibm,plb-460ex", "ibm,plb4";
-+ #address-cells = <2>;
-+ #size-cells = <1>;
-+ ranges;
-+ clock-frequency = <0>; /* Filled in by U-Boot */
++ clocksource_dec.rating = 200 + freq / 10000000;
++ clocksource_set_clock(&clocksource_dec, freq);
+
-+ SDRAM0: sdram {
-+ compatible = "ibm,sdram-460ex", "ibm,sdram-405gp";
-+ dcr-reg = <010 2>;
-+ };
++ clocksource_register(&clocksource_dec);
++}
+diff --git a/arch/mips/kernel/gpio_txx9.c b/arch/mips/kernel/gpio_txx9.c
+new file mode 100644
+index 0000000..b1436a8
+--- /dev/null
++++ b/arch/mips/kernel/gpio_txx9.c
+@@ -0,0 +1,87 @@
++/*
++ * A gpio chip driver for TXx9 SoCs
++ *
++ * Copyright (C) 2008 Atsushi Nemoto <anemo at mba.ocn.ne.jp>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
+
-+ 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>;
-+ };
++#include <linux/init.h>
++#include <linux/spinlock.h>
++#include <linux/gpio.h>
++#include <linux/errno.h>
++#include <linux/io.h>
++#include <asm/txx9pio.h>
+
-+ POB0: opb {
-+ compatible = "ibm,opb-460ex", "ibm,opb";
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges = <b0000000 4 b0000000 50000000>;
-+ clock-frequency = <0>; /* Filled in by U-Boot */
++static DEFINE_SPINLOCK(txx9_gpio_lock);
+
-+ 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>;
++static struct txx9_pio_reg __iomem *txx9_pioptr;
+
-+ nor_flash at 0,0 {
-+ compatible = "amd,s29gl512n", "cfi-flash";
-+ bank-width = <2>;
-+ reg = <0 000000 4000000>;
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ partition at 0 {
-+ label = "kernel";
-+ reg = <0 1e0000>;
-+ };
-+ partition at 1e0000 {
-+ label = "dtb";
-+ reg = <1e0000 20000>;
-+ };
-+ partition at 200000 {
-+ label = "ramdisk";
-+ reg = <200000 1400000>;
-+ };
-+ partition at 1600000 {
-+ label = "jffs2";
-+ reg = <1600000 400000>;
-+ };
-+ partition at 1a00000 {
-+ label = "user";
-+ reg = <1a00000 2560000>;
-+ };
-+ partition at 3f60000 {
-+ label = "env";
-+ reg = <3f60000 40000>;
-+ };
-+ partition at 3fa0000 {
-+ label = "u-boot";
-+ reg = <3fa0000 60000>;
-+ };
-+ };
-+ };
++static int txx9_gpio_get(struct gpio_chip *chip, unsigned int offset)
++{
++ return __raw_readl(&txx9_pioptr->din) & (1 << offset);
++}
+
-+ UART0: serial at ef600300 {
-+ device_type = "serial";
-+ compatible = "ns16550";
-+ reg = <ef600300 8>;
-+ virtual-reg = <ef600300>;
-+ clock-frequency = <0>; /* Filled in by U-Boot */
-+ current-speed = <0>; /* Filled in by U-Boot */
-+ interrupt-parent = <&UIC1>;
-+ interrupts = <1 4>;
-+ };
++static void txx9_gpio_set_raw(unsigned int offset, int value)
++{
++ u32 val;
++ val = __raw_readl(&txx9_pioptr->dout);
++ if (value)
++ val |= 1 << offset;
++ else
++ val &= ~(1 << offset);
++ __raw_writel(val, &txx9_pioptr->dout);
++}
+
-+ UART1: serial at ef600400 {
-+ device_type = "serial";
-+ compatible = "ns16550";
-+ reg = <ef600400 8>;
-+ virtual-reg = <ef600400>;
-+ clock-frequency = <0>; /* Filled in by U-Boot */
-+ current-speed = <0>; /* Filled in by U-Boot */
-+ interrupt-parent = <&UIC0>;
-+ interrupts = <1 4>;
-+ };
++static void txx9_gpio_set(struct gpio_chip *chip, unsigned int offset,
++ int value)
++{
++ unsigned long flags;
++ spin_lock_irqsave(&txx9_gpio_lock, flags);
++ txx9_gpio_set_raw(offset, value);
++ mmiowb();
++ spin_unlock_irqrestore(&txx9_gpio_lock, flags);
++}
+
-+ UART2: serial at ef600500 {
-+ device_type = "serial";
-+ compatible = "ns16550";
-+ reg = <ef600500 8>;
-+ virtual-reg = <ef600500>;
-+ clock-frequency = <0>; /* Filled in by U-Boot */
-+ current-speed = <0>; /* Filled in by U-Boot */
-+ interrupt-parent = <&UIC1>;
-+ interrupts = <1d 4>;
-+ };
++static int txx9_gpio_dir_in(struct gpio_chip *chip, unsigned int offset)
++{
++ spin_lock_irq(&txx9_gpio_lock);
++ __raw_writel(__raw_readl(&txx9_pioptr->dir) & ~(1 << offset),
++ &txx9_pioptr->dir);
++ mmiowb();
++ spin_unlock_irq(&txx9_gpio_lock);
++ return 0;
++}
+
-+ UART3: serial at ef600600 {
-+ device_type = "serial";
-+ compatible = "ns16550";
-+ reg = <ef600600 8>;
-+ virtual-reg = <ef600600>;
-+ clock-frequency = <0>; /* Filled in by U-Boot */
-+ current-speed = <0>; /* Filled in by U-Boot */
-+ interrupt-parent = <&UIC1>;
-+ interrupts = <1e 4>;
-+ };
++static int txx9_gpio_dir_out(struct gpio_chip *chip, unsigned int offset,
++ int value)
++{
++ spin_lock_irq(&txx9_gpio_lock);
++ txx9_gpio_set_raw(offset, value);
++ __raw_writel(__raw_readl(&txx9_pioptr->dir) | (1 << offset),
++ &txx9_pioptr->dir);
++ mmiowb();
++ spin_unlock_irq(&txx9_gpio_lock);
++ return 0;
++}
+
-+ IIC0: i2c at ef600700 {
-+ compatible = "ibm,iic-460ex", "ibm,iic";
-+ reg = <ef600700 14>;
-+ interrupt-parent = <&UIC0>;
-+ interrupts = <2 4>;
-+ };
++static struct gpio_chip txx9_gpio_chip = {
++ .get = txx9_gpio_get,
++ .set = txx9_gpio_set,
++ .direction_input = txx9_gpio_dir_in,
++ .direction_output = txx9_gpio_dir_out,
++ .label = "TXx9",
++};
+
-+ IIC1: i2c at ef600800 {
-+ compatible = "ibm,iic-460ex", "ibm,iic";
-+ reg = <ef600800 14>;
-+ interrupt-parent = <&UIC0>;
-+ interrupts = <3 4>;
-+ };
++int __init txx9_gpio_init(unsigned long baseaddr,
++ unsigned int base, unsigned int num)
++{
++ txx9_pioptr = ioremap(baseaddr, sizeof(struct txx9_pio_reg));
++ if (!txx9_pioptr)
++ return -ENODEV;
++ txx9_gpio_chip.base = base;
++ txx9_gpio_chip.ngpio = num;
++ return gpiochip_add(&txx9_gpio_chip);
++}
+diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c
+new file mode 100644
+index 0000000..f0a4bb1
+--- /dev/null
++++ b/arch/mips/kernel/irq-gic.c
+@@ -0,0 +1,295 @@
++#undef DEBUG
+
-+ ZMII0: emac-zmii at ef600d00 {
-+ compatible = "ibm,zmii-460ex", "ibm,zmii";
-+ reg = <ef600d00 c>;
-+ };
++#include <linux/bitmap.h>
++#include <linux/init.h>
+
-+ RGMII0: emac-rgmii at ef601500 {
-+ compatible = "ibm,rgmii-460ex", "ibm,rgmii";
-+ reg = <ef601500 8>;
-+ has-mdio;
-+ };
++#include <asm/io.h>
++#include <asm/gic.h>
++#include <asm/gcmpregs.h>
++#include <asm/mips-boards/maltaint.h>
++#include <asm/irq.h>
++#include <linux/hardirq.h>
++#include <asm-generic/bitops/find.h>
+
-+ TAH0: emac-tah at ef601350 {
-+ compatible = "ibm,tah-460ex", "ibm,tah";
-+ reg = <ef601350 30>;
-+ };
+
-+ TAH1: emac-tah at ef601450 {
-+ compatible = "ibm,tah-460ex", "ibm,tah";
-+ reg = <ef601450 30>;
-+ };
++static unsigned long _gic_base;
++static unsigned int _irqbase, _mapsize, numvpes, numintrs;
++static struct gic_intr_map *_intrmap;
++
++static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
++static struct gic_pending_regs pending_regs[NR_CPUS];
++static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
+
-+ EMAC0: ethernet at ef600e00 {
-+ device_type = "network";
-+ compatible = "ibm,emac-460ex", "ibm,emac4";
-+ interrupt-parent = <&EMAC0>;
-+ interrupts = <0 1>;
-+ #interrupt-cells = <1>;
-+ #address-cells = <0>;
-+ #size-cells = <0>;
-+ interrupt-map = </*Status*/ 0 &UIC2 10 4
-+ /*Wake*/ 1 &UIC2 14 4>;
-+ reg = <ef600e00 70>;
-+ local-mac-address = [000000000000]; /* Filled in by U-Boot */
-+ mal-device = <&MAL0>;
-+ mal-tx-channel = <0>;
-+ mal-rx-channel = <0>;
-+ cell-index = <0>;
-+ max-frame-size = <2328>;
-+ rx-fifo-size = <1000>;
-+ tx-fifo-size = <800>;
-+ phy-mode = "rgmii";
-+ phy-map = <00000000>;
-+ rgmii-device = <&RGMII0>;
-+ rgmii-channel = <0>;
-+ tah-device = <&TAH0>;
-+ tah-channel = <0>;
-+ has-inverted-stacr-oc;
-+ has-new-stacr-staopc;
-+ };
++#define gic_wedgeb2bok 0 /*
++ * Can GIC handle b2b writes to wedge register?
++ */
++#if gic_wedgeb2bok == 0
++static DEFINE_SPINLOCK(gic_wedgeb2b_lock);
++#endif
+
-+ EMAC1: ethernet at ef600f00 {
-+ device_type = "network";
-+ compatible = "ibm,emac-460ex", "ibm,emac4";
-+ interrupt-parent = <&EMAC1>;
-+ interrupts = <0 1>;
-+ #interrupt-cells = <1>;
-+ #address-cells = <0>;
-+ #size-cells = <0>;
-+ interrupt-map = </*Status*/ 0 &UIC2 11 4
-+ /*Wake*/ 1 &UIC2 15 4>;
-+ reg = <ef600f00 70>;
-+ local-mac-address = [000000000000]; /* Filled in by U-Boot */
-+ mal-device = <&MAL0>;
-+ mal-tx-channel = <1>;
-+ mal-rx-channel = <8>;
-+ cell-index = <1>;
-+ max-frame-size = <2328>;
-+ rx-fifo-size = <1000>;
-+ tx-fifo-size = <800>;
-+ phy-mode = "rgmii";
-+ phy-map = <00000000>;
-+ rgmii-device = <&RGMII0>;
-+ rgmii-channel = <1>;
-+ tah-device = <&TAH1>;
-+ tah-channel = <1>;
-+ has-inverted-stacr-oc;
-+ has-new-stacr-staopc;
-+ mdio-device = <&EMAC0>;
-+ };
-+ };
++void gic_send_ipi(unsigned int intr)
++{
++#if gic_wedgeb2bok == 0
++ unsigned long flags;
++#endif
++ pr_debug("CPU%d: %s status %08x\n", smp_processor_id(), __func__,
++ read_c0_status());
++ if (!gic_wedgeb2bok)
++ spin_lock_irqsave(&gic_wedgeb2b_lock, flags);
++ GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr);
++ if (!gic_wedgeb2bok) {
++ (void) GIC_REG(SHARED, GIC_SH_CONFIG);
++ spin_unlock_irqrestore(&gic_wedgeb2b_lock, flags);
++ }
++}
+
-+ PCIX0: pci at c0ec00000 {
-+ device_type = "pci";
-+ #interrupt-cells = <1>;
-+ #size-cells = <2>;
-+ #address-cells = <3>;
-+ compatible = "ibm,plb-pcix-460ex", "ibm,plb-pcix";
-+ primary;
-+ large-inbound-windows;
-+ enable-msi-hole;
-+ reg = <c 0ec00000 8 /* Config space access */
-+ 0 0 0 /* no IACK cycles */
-+ c 0ed00000 4 /* Special cycles */
-+ c 0ec80000 100 /* Internal registers */
-+ c 0ec80100 fc>; /* Internal messaging registers */
++/* This is Malta specific and needs to be exported */
++static void vpe_local_setup(unsigned int numvpes)
++{
++ int i;
++ unsigned long timer_interrupt = 5, perf_interrupt = 5;
++ unsigned int vpe_ctl;
+
-+ /* 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>;
++ /*
++ * Setup the default performance counter timer interrupts
++ * for all VPEs
++ */
++ for (i = 0; i < numvpes; i++) {
++ GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
+
-+ /* Inbound 2GB range starting at 0 */
-+ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++ /* Are Interrupts locally routable? */
++ GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_CTL), vpe_ctl);
++ if (vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK)
++ GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP),
++ GIC_MAP_TO_PIN_MSK | timer_interrupt);
+
-+ /* This drives busses 0 to 0x3f */
-+ bus-range = <0 3f>;
++ if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK)
++ GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP),
++ GIC_MAP_TO_PIN_MSK | perf_interrupt);
++ }
++}
+
-+ /* 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 >;
-+ };
++unsigned int gic_get_int(void)
++{
++ unsigned int i;
++ unsigned long *pending, *intrmask, *pcpu_mask;
++ unsigned long *pending_abs, *intrmask_abs;
+
-+ PCIE0: pciex at d00000000 {
-+ device_type = "pci";
-+ #interrupt-cells = <1>;
-+ #size-cells = <2>;
-+ #address-cells = <3>;
-+ compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
-+ primary;
-+ port = <0>; /* port number */
-+ reg = <d 00000000 20000000 /* Config space access */
-+ c 08010000 00001000>; /* Registers */
-+ dcr-reg = <100 020>;
-+ sdr-base = <300>;
++ /* Get per-cpu bitmaps */
++ pending = pending_regs[smp_processor_id()].pending;
++ intrmask = intrmask_regs[smp_processor_id()].intrmask;
++ pcpu_mask = pcpu_masks[smp_processor_id()].pcpu_mask;
+
-+ /* 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>;
++ pending_abs = (unsigned long *) GIC_REG_ABS_ADDR(SHARED,
++ GIC_SH_PEND_31_0_OFS);
++ intrmask_abs = (unsigned long *) GIC_REG_ABS_ADDR(SHARED,
++ GIC_SH_MASK_31_0_OFS);
+
-+ /* Inbound 2GB range starting at 0 */
-+ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++ for (i = 0; i < BITS_TO_LONGS(GIC_NUM_INTRS); i++) {
++ GICREAD(*pending_abs, pending[i]);
++ GICREAD(*intrmask_abs, intrmask[i]);
++ pending_abs++;
++ intrmask_abs++;
++ }
+
-+ /* This drives busses 40 to 0x7f */
-+ bus-range = <40 7f>;
++ bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS);
++ bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS);
+
-+ /* 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 */>;
-+ };
++ i = find_first_bit(pending, GIC_NUM_INTRS);
+
-+ PCIE1: pciex at d20000000 {
-+ device_type = "pci";
-+ #interrupt-cells = <1>;
-+ #size-cells = <2>;
-+ #address-cells = <3>;
-+ compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
-+ primary;
-+ port = <1>; /* port number */
-+ reg = <d 20000000 20000000 /* Config space access */
-+ c 08011000 00001000>; /* Registers */
-+ dcr-reg = <120 020>;
-+ sdr-base = <340>;
++ pr_debug("CPU%d: %s pend=%d\n", smp_processor_id(), __func__, i);
+
-+ /* 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>;
++ return i;
++}
+
-+ /* Inbound 2GB range starting at 0 */
-+ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++static unsigned int gic_irq_startup(unsigned int irq)
++{
++ pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
++ irq -= _irqbase;
++ /* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */
++ GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_SMASK_31_0_OFS + (irq / 32))),
++ 1 << (irq % 32));
++ return 0;
++}
+
-+ /* This drives busses 80 to 0xbf */
-+ bus-range = <80 bf>;
++static void gic_irq_ack(unsigned int irq)
++{
++#if gic_wedgeb2bok == 0
++ unsigned long flags;
++#endif
++ pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
++ irq -= _irqbase;
++ GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_RMASK_31_0_OFS + (irq / 32))),
++ 1 << (irq % 32));
+
-+ /* Legacy interrupts (note the weird polarity, the bridge seems
-+ * to invert PCIe legacy interrupts).
-+ * We are de-swizzling here because the numbers are actually for
-+ * port of the root complex virtual P2P bridge. But I want
-+ * to avoid putting a node for it in the tree, so the numbers
-+ * below are basically de-swizzled numbers.
-+ * The real slot is on idsel 0, so the swizzling is 1:1
-+ */
-+ interrupt-map-mask = <0000 0 0 7>;
-+ interrupt-map = <
-+ 0000 0 0 1 &UIC3 10 4 /* swizzled int A */
-+ 0000 0 0 2 &UIC3 11 4 /* swizzled int B */
-+ 0000 0 0 3 &UIC3 12 4 /* swizzled int C */
-+ 0000 0 0 4 &UIC3 13 4 /* swizzled int D */>;
-+ };
-+ };
-+};
-diff --git a/arch/powerpc/boot/dts/ebony.dts b/arch/powerpc/boot/dts/ebony.dts
-index 0b000cb..5079dc8 100644
---- a/arch/powerpc/boot/dts/ebony.dts
-+++ b/arch/powerpc/boot/dts/ebony.dts
-@@ -241,7 +241,6 @@
- };
-
- EMAC0: ethernet at 40000800 {
-- linux,network-index = <0>;
- device_type = "network";
- compatible = "ibm,emac-440gp", "ibm,emac";
- interrupt-parent = <&UIC1>;
-@@ -261,7 +260,6 @@
- zmii-channel = <0>;
- };
- EMAC1: ethernet at 40000900 {
-- linux,network-index = <1>;
- device_type = "network";
- compatible = "ibm,emac-440gp", "ibm,emac";
- interrupt-parent = <&UIC1>;
-diff --git a/arch/powerpc/boot/dts/ep8248e.dts b/arch/powerpc/boot/dts/ep8248e.dts
-index 5d2fb76..756758f 100644
---- a/arch/powerpc/boot/dts/ep8248e.dts
-+++ b/arch/powerpc/boot/dts/ep8248e.dts
-@@ -121,8 +121,7 @@
-
- data at 0 {
- compatible = "fsl,cpm-muram-data";
-- reg = <0 0x1100 0x1140
-- 0xec0 0x9800 0x800>;
-+ reg = <0 0x2000 0x9800 0x800>;
- };
- };
-
-@@ -138,7 +137,7 @@
- device_type = "serial";
- compatible = "fsl,mpc8248-smc-uart",
- "fsl,cpm2-smc-uart";
-- reg = <0x11a80 0x20 0x1100 0x40>;
-+ reg = <0x11a80 0x20 0x87fc 2>;
- interrupts = <4 8>;
- interrupt-parent = <&PIC>;
- fsl,cpm-brg = <7>;
-diff --git a/arch/powerpc/boot/dts/ep88xc.dts b/arch/powerpc/boot/dts/ep88xc.dts
-index 02705f2..ae57d62 100644
---- a/arch/powerpc/boot/dts/ep88xc.dts
-+++ b/arch/powerpc/boot/dts/ep88xc.dts
-@@ -2,7 +2,7 @@
- * EP88xC Device Tree Source
- *
- * Copyright 2006 MontaVista Software, Inc.
-- * Copyright 2007 Freescale Semiconductor, Inc.
-+ * Copyright 2007,2008 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
-@@ -10,6 +10,7 @@
- * option) any later version.
- */
-
-+/dts-v1/;
-
- / {
- model = "EP88xC";
-@@ -23,44 +24,44 @@
-
- PowerPC,885 at 0 {
- device_type = "cpu";
-- reg = <0>;
-- d-cache-line-size = <d#16>;
-- i-cache-line-size = <d#16>;
-- d-cache-size = <d#8192>;
-- i-cache-size = <d#8192>;
-+ reg = <0x0>;
-+ d-cache-line-size = <16>;
-+ i-cache-line-size = <16>;
-+ d-cache-size = <8192>;
-+ i-cache-size = <8192>;
- timebase-frequency = <0>;
- bus-frequency = <0>;
- clock-frequency = <0>;
-- interrupts = <f 2>; // decrementer interrupt
-+ interrupts = <15 2>; // decrementer interrupt
- interrupt-parent = <&PIC>;
- };
- };
-
- memory {
- device_type = "memory";
-- reg = <0 0>;
-+ reg = <0x0 0x0>;
- };
-
- localbus at fa200100 {
- compatible = "fsl,mpc885-localbus", "fsl,pq1-localbus";
- #address-cells = <2>;
- #size-cells = <1>;
-- reg = <fa200100 40>;
-+ reg = <0xfa200100 0x40>;
-
- ranges = <
-- 0 0 fc000000 04000000
-- 3 0 fa000000 01000000
-+ 0x0 0x0 0xfc000000 0x4000000
-+ 0x3 0x0 0xfa000000 0x1000000
- >;
-
- flash at 0,2000000 {
- compatible = "cfi-flash";
-- reg = <0 2000000 2000000>;
-+ reg = <0x0 0x2000000 0x2000000>;
- bank-width = <4>;
- device-width = <2>;
- };
-
- board-control at 3,400000 {
-- reg = <3 400000 10>;
-+ reg = <0x3 0x400000 0x10>;
- compatible = "fsl,ep88xc-bcsr";
- };
- };
-@@ -70,25 +71,25 @@
- #address-cells = <1>;
- #size-cells = <1>;
- device_type = "soc";
-- ranges = <0 fa200000 00004000>;
-+ ranges = <0x0 0xfa200000 0x4000>;
- bus-frequency = <0>;
-
- // Temporary -- will go away once kernel uses ranges for get_immrbase().
-- reg = <fa200000 4000>;
-+ reg = <0xfa200000 0x4000>;
-
- mdio at e00 {
- compatible = "fsl,mpc885-fec-mdio", "fsl,pq1-fec-mdio";
-- reg = <e00 188>;
-+ reg = <0xe00 0x188>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- PHY0: ethernet-phy at 0 {
-- reg = <0>;
-+ reg = <0x0>;
- device_type = "ethernet-phy";
- };
-
- PHY1: ethernet-phy at 1 {
-- reg = <1>;
-+ reg = <0x1>;
- device_type = "ethernet-phy";
- };
- };
-@@ -97,7 +98,7 @@
- device_type = "network";
- compatible = "fsl,mpc885-fec-enet",
- "fsl,pq1-fec-enet";
-- reg = <e00 188>;
-+ reg = <0xe00 0x188>;
- local-mac-address = [ 00 00 00 00 00 00 ];
- interrupts = <3 1>;
- interrupt-parent = <&PIC>;
-@@ -109,7 +110,7 @@
- device_type = "network";
- compatible = "fsl,mpc885-fec-enet",
- "fsl,pq1-fec-enet";
-- reg = <1e00 188>;
-+ reg = <0x1e00 0x188>;
- local-mac-address = [ 00 00 00 00 00 00 ];
- interrupts = <7 1>;
- interrupt-parent = <&PIC>;
-@@ -120,7 +121,7 @@
- PIC: interrupt-controller at 0 {
- interrupt-controller;
- #interrupt-cells = <2>;
-- reg = <0 24>;
-+ reg = <0x0 0x24>;
- compatible = "fsl,mpc885-pic", "fsl,pq1-pic";
- };
-
-@@ -130,29 +131,29 @@
- #size-cells = <2>;
- compatible = "fsl,pq-pcmcia";
- device_type = "pcmcia";
-- reg = <80 80>;
-+ reg = <0x80 0x80>;
- interrupt-parent = <&PIC>;
-- interrupts = <d 1>;
-+ interrupts = <13 1>;
- };
-
- cpm at 9c0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "fsl,mpc885-cpm", "fsl,cpm1";
-- command-proc = <9c0>;
-+ command-proc = <0x9c0>;
- interrupts = <0>; // cpm error interrupt
- interrupt-parent = <&CPM_PIC>;
-- reg = <9c0 40>;
-+ reg = <0x9c0 0x40>;
- ranges;
-
- muram at 2000 {
- #address-cells = <1>;
- #size-cells = <1>;
-- ranges = <0 2000 2000>;
-+ ranges = <0x0 0x2000 0x2000>;
-
- data at 0 {
- compatible = "fsl,cpm-muram-data";
-- reg = <0 1c00>;
-+ reg = <0x0 0x1c00>;
- };
- };
-
-@@ -160,7 +161,7 @@
- compatible = "fsl,mpc885-brg",
- "fsl,cpm1-brg",
- "fsl,cpm-brg";
-- reg = <9f0 10>;
-+ reg = <0x9f0 0x10>;
- };
-
- CPM_PIC: interrupt-controller at 930 {
-@@ -168,7 +169,7 @@
- #interrupt-cells = <1>;
- interrupts = <5 2 0 2>;
- interrupt-parent = <&PIC>;
-- reg = <930 20>;
-+ reg = <0x930 0x20>;
- compatible = "fsl,mpc885-cpm-pic",
- "fsl,cpm1-pic";
- };
-@@ -178,11 +179,11 @@
- device_type = "serial";
- compatible = "fsl,mpc885-smc-uart",
- "fsl,cpm1-smc-uart";
-- reg = <a80 10 3e80 40>;
-+ reg = <0xa80 0x10 0x3e80 0x40>;
- interrupts = <4>;
- interrupt-parent = <&CPM_PIC>;
- fsl,cpm-brg = <1>;
-- fsl,cpm-command = <0090>;
-+ fsl,cpm-command = <0x90>;
- linux,planetcore-label = "SMC1";
- };
-
-@@ -191,11 +192,11 @@
- device_type = "serial";
- compatible = "fsl,mpc885-scc-uart",
- "fsl,cpm1-scc-uart";
-- reg = <a20 20 3d00 80>;
-- interrupts = <1d>;
-+ reg = <0xa20 0x20 0x3d00 0x80>;
-+ interrupts = <29>;
- interrupt-parent = <&CPM_PIC>;
- fsl,cpm-brg = <2>;
-- fsl,cpm-command = <0040>;
-+ fsl,cpm-command = <0x40>;
- linux,planetcore-label = "SCC2";
- };
-
-@@ -204,9 +205,9 @@
- #size-cells = <0>;
- compatible = "fsl,mpc885-usb",
- "fsl,cpm1-usb";
-- reg = <a00 18 1c00 80>;
-+ reg = <0xa00 0x18 0x1c00 0x80>;
- interrupt-parent = <&CPM_PIC>;
-- interrupts = <1e>;
-+ interrupts = <30>;
- fsl,cpm-command = <0000>;
- };
- };
-diff --git a/arch/powerpc/boot/dts/glacier.dts b/arch/powerpc/boot/dts/glacier.dts
-new file mode 100644
-index 0000000..0f2fc07
---- /dev/null
-+++ b/arch/powerpc/boot/dts/glacier.dts
-@@ -0,0 +1,504 @@
-+/*
-+ * Device Tree Source for AMCC Glacier (460GT)
-+ *
-+ * Copyright 2008 DENX Software Engineering, Stefan Roese <sr at denx.de>
-+ *
-+ * This file is licensed under the terms of the GNU General Public
-+ * License version 2. This program is licensed "as is" without
-+ * any warranty of any kind, whether express or implied.
-+ */
++ if (_intrmap[irq].trigtype == GIC_TRIG_EDGE) {
++ if (!gic_wedgeb2bok)
++ spin_lock_irqsave(&gic_wedgeb2b_lock, flags);
++ GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
++ if (!gic_wedgeb2bok) {
++ (void) GIC_REG(SHARED, GIC_SH_CONFIG);
++ spin_unlock_irqrestore(&gic_wedgeb2b_lock, flags);
++ }
++ }
++}
+
-+/ {
-+ #address-cells = <2>;
-+ #size-cells = <1>;
-+ model = "amcc,glacier";
-+ compatible = "amcc,glacier", "amcc,canyonlands";
-+ dcr-parent = <&/cpus/cpu at 0>;
++static void gic_mask_irq(unsigned int irq)
++{
++ pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
++ irq -= _irqbase;
++ /* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */
++ GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_RMASK_31_0_OFS + (irq / 32))),
++ 1 << (irq % 32));
++}
+
-+ aliases {
-+ ethernet0 = &EMAC0;
-+ ethernet1 = &EMAC1;
-+ ethernet2 = &EMAC2;
-+ ethernet3 = &EMAC3;
-+ serial0 = &UART0;
-+ serial1 = &UART1;
-+ };
++static void gic_unmask_irq(unsigned int irq)
++{
++ pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
++ irq -= _irqbase;
++ /* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */
++ GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_SMASK_31_0_OFS + (irq / 32))),
++ 1 << (irq % 32));
++}
+
-+ cpus {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
++#ifdef CONFIG_SMP
+
-+ cpu at 0 {
-+ device_type = "cpu";
-+ model = "PowerPC,460GT";
-+ reg = <0>;
-+ clock-frequency = <0>; /* Filled in by U-Boot */
-+ timebase-frequency = <0>; /* Filled in by U-Boot */
-+ i-cache-line-size = <20>;
-+ d-cache-line-size = <20>;
-+ i-cache-size = <8000>;
-+ d-cache-size = <8000>;
-+ dcr-controller;
-+ dcr-access-method = "native";
-+ };
-+ };
++static DEFINE_SPINLOCK(gic_lock);
+
-+ memory {
-+ device_type = "memory";
-+ reg = <0 0 0>; /* Filled in by U-Boot */
-+ };
++static void gic_set_affinity(unsigned int irq, cpumask_t cpumask)
++{
++ cpumask_t tmp = CPU_MASK_NONE;
++ unsigned long flags;
++ int i;
+
-+ 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>;
-+ };
++ pr_debug(KERN_DEBUG "%s called\n", __func__);
++ irq -= _irqbase;
+
-+ 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>;
-+ };
++ cpus_and(tmp, cpumask, cpu_online_map);
++ if (cpus_empty(tmp))
++ return;
+
-+ UIC2: interrupt-controller2 {
-+ compatible = "ibm,uic-460gt","ibm,uic";
-+ interrupt-controller;
-+ cell-index = <2>;
-+ dcr-reg = <0e0 009>;
-+ #address-cells = <0>;
-+ #size-cells = <0>;
-+ #interrupt-cells = <2>;
-+ interrupts = <a 4 b 4>; /* cascade */
-+ interrupt-parent = <&UIC0>;
-+ };
++ /* Assumption : cpumask refers to a single CPU */
++ spin_lock_irqsave(&gic_lock, flags);
++ for (;;) {
++ /* Re-route this IRQ */
++ GIC_SH_MAP_TO_VPE_SMASK(irq, first_cpu(tmp));
+
-+ 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>;
-+ };
++ /*
++ * FIXME: assumption that _intrmap is ordered and has no holes
++ */
+
-+ SDR0: sdr {
-+ compatible = "ibm,sdr-460gt";
-+ dcr-reg = <00e 002>;
-+ };
++ /* Update the intr_map */
++ _intrmap[irq].cpunum = first_cpu(tmp);
+
-+ CPR0: cpr {
-+ compatible = "ibm,cpr-460gt";
-+ dcr-reg = <00c 002>;
-+ };
++ /* Update the pcpu_masks */
++ for (i = 0; i < NR_CPUS; i++)
++ clear_bit(irq, pcpu_masks[i].pcpu_mask);
++ set_bit(irq, pcpu_masks[first_cpu(tmp)].pcpu_mask);
+
-+ plb {
-+ compatible = "ibm,plb-460gt", "ibm,plb4";
-+ #address-cells = <2>;
-+ #size-cells = <1>;
-+ ranges;
-+ clock-frequency = <0>; /* Filled in by U-Boot */
++ }
++ irq_desc[irq].affinity = cpumask;
++ spin_unlock_irqrestore(&gic_lock, flags);
+
-+ SDRAM0: sdram {
-+ compatible = "ibm,sdram-460gt", "ibm,sdram-405gp";
-+ dcr-reg = <010 2>;
-+ };
++}
++#endif
+
-+ 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>;
-+ };
++static struct irq_chip gic_irq_controller = {
++ .name = "MIPS GIC",
++ .startup = gic_irq_startup,
++ .ack = gic_irq_ack,
++ .mask = gic_mask_irq,
++ .mask_ack = gic_mask_irq,
++ .unmask = gic_unmask_irq,
++ .eoi = gic_unmask_irq,
++#ifdef CONFIG_SMP
++ .set_affinity = gic_set_affinity,
++#endif
++};
+
-+ POB0: opb {
-+ compatible = "ibm,opb-460gt", "ibm,opb";
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges = <b0000000 4 b0000000 50000000>;
-+ clock-frequency = <0>; /* Filled in by U-Boot */
++static void __init setup_intr(unsigned int intr, unsigned int cpu,
++ unsigned int pin, unsigned int polarity, unsigned int trigtype)
++{
++ /* Setup Intr to Pin mapping */
++ if (pin & GIC_MAP_TO_NMI_MSK) {
++ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin);
++ /* FIXME: hack to route NMI to all cpu's */
++ for (cpu = 0; cpu < NR_CPUS; cpu += 32) {
++ GICWRITE(GIC_REG_ADDR(SHARED,
++ GIC_SH_MAP_TO_VPE_REG_OFF(intr, cpu)),
++ 0xffffffff);
++ }
++ } else {
++ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)),
++ GIC_MAP_TO_PIN_MSK | pin);
++ /* Setup Intr to CPU mapping */
++ GIC_SH_MAP_TO_VPE_SMASK(intr, cpu);
++ }
+
-+ 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>;
++ /* Setup Intr Polarity */
++ GIC_SET_POLARITY(intr, polarity);
+
-+ nor_flash at 0,0 {
-+ compatible = "amd,s29gl512n", "cfi-flash";
-+ bank-width = <2>;
-+ reg = <0 000000 4000000>;
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ partition at 0 {
-+ label = "kernel";
-+ reg = <0 1e0000>;
-+ };
-+ partition at 1e0000 {
-+ label = "dtb";
-+ reg = <1e0000 20000>;
-+ };
-+ partition at 200000 {
-+ label = "ramdisk";
-+ reg = <200000 1400000>;
-+ };
-+ partition at 1600000 {
-+ label = "jffs2";
-+ reg = <1600000 400000>;
-+ };
-+ partition at 1a00000 {
-+ label = "user";
-+ reg = <1a00000 2560000>;
-+ };
-+ partition at 3f60000 {
-+ label = "env";
-+ reg = <3f60000 40000>;
-+ };
-+ partition at 3fa0000 {
-+ label = "u-boot";
-+ reg = <3fa0000 60000>;
-+ };
-+ };
-+ };
++ /* Setup Intr Trigger Type */
++ GIC_SET_TRIGGER(intr, trigtype);
+
-+ UART0: serial at ef600300 {
-+ device_type = "serial";
-+ compatible = "ns16550";
-+ reg = <ef600300 8>;
-+ virtual-reg = <ef600300>;
-+ clock-frequency = <0>; /* Filled in by U-Boot */
-+ current-speed = <0>; /* Filled in by U-Boot */
-+ interrupt-parent = <&UIC1>;
-+ interrupts = <1 4>;
-+ };
++ /* Init Intr Masks */
++ GIC_SET_INTR_MASK(intr, 0);
++}
+
-+ UART1: serial at ef600400 {
-+ device_type = "serial";
-+ compatible = "ns16550";
-+ reg = <ef600400 8>;
-+ virtual-reg = <ef600400>;
-+ clock-frequency = <0>; /* Filled in by U-Boot */
-+ current-speed = <0>; /* Filled in by U-Boot */
-+ interrupt-parent = <&UIC0>;
-+ interrupts = <1 4>;
-+ };
++static void __init gic_basic_init(void)
++{
++ unsigned int i, cpu;
+
-+ UART2: serial at ef600500 {
-+ device_type = "serial";
-+ compatible = "ns16550";
-+ reg = <ef600500 8>;
-+ virtual-reg = <ef600500>;
-+ clock-frequency = <0>; /* Filled in by U-Boot */
-+ current-speed = <0>; /* Filled in by U-Boot */
-+ interrupt-parent = <&UIC1>;
-+ interrupts = <1d 4>;
-+ };
++ /* Setup defaults */
++ for (i = 0; i < GIC_NUM_INTRS; i++) {
++ GIC_SET_POLARITY(i, GIC_POL_POS);
++ GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL);
++ GIC_SET_INTR_MASK(i, 0);
++ }
+
-+ UART3: serial at ef600600 {
-+ device_type = "serial";
-+ compatible = "ns16550";
-+ reg = <ef600600 8>;
-+ virtual-reg = <ef600600>;
-+ clock-frequency = <0>; /* Filled in by U-Boot */
-+ current-speed = <0>; /* Filled in by U-Boot */
-+ interrupt-parent = <&UIC1>;
-+ interrupts = <1e 4>;
-+ };
++ /* Setup specifics */
++ for (i = 0; i < _mapsize; i++) {
++ cpu = _intrmap[i].cpunum;
++ if (cpu == X)
++ continue;
+
-+ IIC0: i2c at ef600700 {
-+ compatible = "ibm,iic-460gt", "ibm,iic";
-+ reg = <ef600700 14>;
-+ interrupt-parent = <&UIC0>;
-+ interrupts = <2 4>;
-+ };
++ setup_intr(_intrmap[i].intrnum,
++ _intrmap[i].cpunum,
++ _intrmap[i].pin,
++ _intrmap[i].polarity,
++ _intrmap[i].trigtype);
++ /* Initialise per-cpu Interrupt software masks */
++ if (_intrmap[i].ipiflag)
++ set_bit(_intrmap[i].intrnum, pcpu_masks[cpu].pcpu_mask);
++ }
+
-+ IIC1: i2c at ef600800 {
-+ compatible = "ibm,iic-460gt", "ibm,iic";
-+ reg = <ef600800 14>;
-+ interrupt-parent = <&UIC0>;
-+ interrupts = <3 4>;
-+ };
++ vpe_local_setup(numvpes);
+
-+ ZMII0: emac-zmii at ef600d00 {
-+ compatible = "ibm,zmii-460gt", "ibm,zmii";
-+ reg = <ef600d00 c>;
-+ };
++ for (i = _irqbase; i < (_irqbase + numintrs); i++)
++ set_irq_chip(i, &gic_irq_controller);
++}
+
-+ RGMII0: emac-rgmii at ef601500 {
-+ compatible = "ibm,rgmii-460gt", "ibm,rgmii";
-+ reg = <ef601500 8>;
-+ has-mdio;
-+ };
++void __init gic_init(unsigned long gic_base_addr,
++ unsigned long gic_addrspace_size,
++ struct gic_intr_map *intr_map, unsigned int intr_map_size,
++ unsigned int irqbase)
++{
++ unsigned int gicconfig;
+
-+ RGMII1: emac-rgmii at ef601600 {
-+ compatible = "ibm,rgmii-460gt", "ibm,rgmii";
-+ reg = <ef601600 8>;
-+ has-mdio;
-+ };
++ _gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
++ gic_addrspace_size);
++ _irqbase = irqbase;
++ _intrmap = intr_map;
++ _mapsize = intr_map_size;
+
-+ TAH0: emac-tah at ef601350 {
-+ compatible = "ibm,tah-460gt", "ibm,tah";
-+ reg = <ef601350 30>;
-+ };
++ GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
++ numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
++ GIC_SH_CONFIG_NUMINTRS_SHF;
++ numintrs = ((numintrs + 1) * 8);
+
-+ TAH1: emac-tah at ef601450 {
-+ compatible = "ibm,tah-460gt", "ibm,tah";
-+ reg = <ef601450 30>;
-+ };
++ numvpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >>
++ GIC_SH_CONFIG_NUMVPES_SHF;
+
-+ EMAC0: ethernet at ef600e00 {
-+ device_type = "network";
-+ compatible = "ibm,emac-460gt", "ibm,emac4";
-+ interrupt-parent = <&EMAC0>;
-+ interrupts = <0 1>;
-+ #interrupt-cells = <1>;
-+ #address-cells = <0>;
-+ #size-cells = <0>;
-+ interrupt-map = </*Status*/ 0 &UIC2 10 4
-+ /*Wake*/ 1 &UIC2 14 4>;
-+ reg = <ef600e00 70>;
-+ local-mac-address = [000000000000]; /* Filled in by U-Boot */
-+ mal-device = <&MAL0>;
-+ mal-tx-channel = <0>;
-+ mal-rx-channel = <0>;
-+ cell-index = <0>;
-+ max-frame-size = <2328>;
-+ rx-fifo-size = <1000>;
-+ tx-fifo-size = <800>;
-+ phy-mode = "rgmii";
-+ phy-map = <00000000>;
-+ rgmii-device = <&RGMII0>;
-+ rgmii-channel = <0>;
-+ tah-device = <&TAH0>;
-+ tah-channel = <0>;
-+ has-inverted-stacr-oc;
-+ has-new-stacr-staopc;
-+ };
++ pr_debug("%s called\n", __func__);
+
-+ EMAC1: ethernet at ef600f00 {
-+ device_type = "network";
-+ compatible = "ibm,emac-460gt", "ibm,emac4";
-+ interrupt-parent = <&EMAC1>;
-+ interrupts = <0 1>;
-+ #interrupt-cells = <1>;
-+ #address-cells = <0>;
-+ #size-cells = <0>;
-+ interrupt-map = </*Status*/ 0 &UIC2 11 4
-+ /*Wake*/ 1 &UIC2 15 4>;
-+ reg = <ef600f00 70>;
-+ local-mac-address = [000000000000]; /* Filled in by U-Boot */
-+ mal-device = <&MAL0>;
-+ mal-tx-channel = <1>;
-+ mal-rx-channel = <8>;
-+ cell-index = <1>;
-+ max-frame-size = <2328>;
-+ rx-fifo-size = <1000>;
-+ tx-fifo-size = <800>;
-+ phy-mode = "rgmii";
-+ phy-map = <00000000>;
-+ rgmii-device = <&RGMII0>;
-+ rgmii-channel = <1>;
-+ tah-device = <&TAH1>;
-+ tah-channel = <1>;
-+ has-inverted-stacr-oc;
-+ has-new-stacr-staopc;
-+ mdio-device = <&EMAC0>;
-+ };
++ gic_basic_init();
++}
+diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c
+index 4edc7e4..963c16d 100644
+--- a/arch/mips/kernel/irq-msc01.c
++++ b/arch/mips/kernel/irq-msc01.c
+@@ -17,6 +17,7 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/msc01_ic.h>
++#include <asm/traps.h>
+
+ static unsigned long _icctrl_msc;
+ #define MSC01_IC_REG_BASE _icctrl_msc
+@@ -98,14 +99,13 @@ void ll_msc_irq(void)
+ }
+ }
+
+-void
+-msc_bind_eic_interrupt(unsigned int irq, unsigned int set)
++static void msc_bind_eic_interrupt(int irq, int set)
+ {
+ MSCIC_WRITE(MSC01_IC_RAMW,
+ (irq<<MSC01_IC_RAMW_ADDR_SHF) | (set<<MSC01_IC_RAMW_DATA_SHF));
+ }
+
+-struct irq_chip msc_levelirq_type = {
++static struct irq_chip msc_levelirq_type = {
+ .name = "SOC-it-Level",
+ .ack = level_mask_and_ack_msc_irq,
+ .mask = mask_msc_irq,
+@@ -115,7 +115,7 @@ struct irq_chip msc_levelirq_type = {
+ .end = end_msc_irq,
+ };
+
+-struct irq_chip msc_edgeirq_type = {
++static struct irq_chip msc_edgeirq_type = {
+ .name = "SOC-it-Edge",
+ .ack = edge_mask_and_ack_msc_irq,
+ .mask = mask_msc_irq,
+@@ -128,8 +128,6 @@ struct irq_chip msc_edgeirq_type = {
+
+ void __init init_msc_irqs(unsigned long icubase, unsigned int irqbase, msc_irqmap_t *imp, int nirq)
+ {
+- extern void (*board_bind_eic_interrupt)(unsigned int irq, unsigned int regset);
+-
+ _icctrl_msc = (unsigned long) ioremap(icubase, 0x40000);
+
+ /* Reset interrupt controller - initialises all registers to 0 */
+diff --git a/arch/mips/kernel/semaphore.c b/arch/mips/kernel/semaphore.c
+deleted file mode 100644
+index 1265358..0000000
+--- a/arch/mips/kernel/semaphore.c
++++ /dev/null
+@@ -1,168 +0,0 @@
+-/*
+- * MIPS-specific semaphore code.
+- *
+- * Copyright (C) 1999 Cort Dougan <cort at cs.nmt.edu>
+- * Copyright (C) 2004 Ralf Baechle <ralf at linux-mips.org>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- * April 2001 - Reworked by Paul Mackerras <paulus at samba.org>
+- * to eliminate the SMP races in the old version between the updates
+- * of `count' and `waking'. Now we use negative `count' values to
+- * indicate that some process(es) are waiting for the semaphore.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-#include <asm/atomic.h>
+-#include <asm/cpu-features.h>
+-#include <asm/errno.h>
+-#include <asm/semaphore.h>
+-#include <asm/war.h>
+-/*
+- * Atomically update sem->count.
+- * This does the equivalent of the following:
+- *
+- * old_count = sem->count;
+- * tmp = MAX(old_count, 0) + incr;
+- * sem->count = tmp;
+- * return old_count;
+- *
+- * On machines without lld/scd we need a spinlock to make the manipulation of
+- * sem->count and sem->waking atomic. Scalability isn't an issue because
+- * this lock is used on UP only so it's just an empty variable.
+- */
+-static inline int __sem_update_count(struct semaphore *sem, int incr)
+-{
+- int old_count, tmp;
+-
+- if (cpu_has_llsc && R10000_LLSC_WAR) {
+- __asm__ __volatile__(
+- " .set mips3 \n"
+- "1: ll %0, %2 # __sem_update_count \n"
+- " sra %1, %0, 31 \n"
+- " not %1 \n"
+- " and %1, %0, %1 \n"
+- " addu %1, %1, %3 \n"
+- " sc %1, %2 \n"
+- " beqzl %1, 1b \n"
+- " .set mips0 \n"
+- : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+- : "r" (incr), "m" (sem->count));
+- } else if (cpu_has_llsc) {
+- __asm__ __volatile__(
+- " .set mips3 \n"
+- "1: ll %0, %2 # __sem_update_count \n"
+- " sra %1, %0, 31 \n"
+- " not %1 \n"
+- " and %1, %0, %1 \n"
+- " addu %1, %1, %3 \n"
+- " sc %1, %2 \n"
+- " beqz %1, 1b \n"
+- " .set mips0 \n"
+- : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+- : "r" (incr), "m" (sem->count));
+- } else {
+- static DEFINE_SPINLOCK(semaphore_lock);
+- unsigned long flags;
+-
+- spin_lock_irqsave(&semaphore_lock, flags);
+- old_count = atomic_read(&sem->count);
+- tmp = max_t(int, old_count, 0) + incr;
+- atomic_set(&sem->count, tmp);
+- spin_unlock_irqrestore(&semaphore_lock, flags);
+- }
+-
+- return old_count;
+-}
+-
+-void __up(struct semaphore *sem)
+-{
+- /*
+- * Note that we incremented count in up() before we came here,
+- * but that was ineffective since the result was <= 0, and
+- * any negative value of count is equivalent to 0.
+- * This ends up setting count to 1, unless count is now > 0
+- * (i.e. because some other cpu has called up() in the meantime),
+- * in which case we just increment count.
+- */
+- __sem_update_count(sem, 1);
+- wake_up(&sem->wait);
+-}
+-
+-EXPORT_SYMBOL(__up);
+-
+-/*
+- * Note that when we come in to __down or __down_interruptible,
+- * we have already decremented count, but that decrement was
+- * ineffective since the result was < 0, and any negative value
+- * of count is equivalent to 0.
+- * Thus it is only when we decrement count from some value > 0
+- * that we have actually got the semaphore.
+- */
+-void __sched __down(struct semaphore *sem)
+-{
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+-
+- __set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+- add_wait_queue_exclusive(&sem->wait, &wait);
+-
+- /*
+- * Try to get the semaphore. If the count is > 0, then we've
+- * got the semaphore; we decrement count and exit the loop.
+- * If the count is 0 or negative, we set it to -1, indicating
+- * that we are asleep, and then sleep.
+- */
+- while (__sem_update_count(sem, -1) <= 0) {
+- schedule();
+- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+- }
+- remove_wait_queue(&sem->wait, &wait);
+- __set_task_state(tsk, TASK_RUNNING);
+-
+- /*
+- * If there are any more sleepers, wake one of them up so
+- * that it can either get the semaphore, or set count to -1
+- * indicating that there are still processes sleeping.
+- */
+- wake_up(&sem->wait);
+-}
+-
+-EXPORT_SYMBOL(__down);
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+- int retval = 0;
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+-
+- __set_task_state(tsk, TASK_INTERRUPTIBLE);
+- add_wait_queue_exclusive(&sem->wait, &wait);
+-
+- while (__sem_update_count(sem, -1) <= 0) {
+- if (signal_pending(current)) {
+- /*
+- * A signal is pending - give up trying.
+- * Set sem->count to 0 if it is negative,
+- * since we are no longer sleeping.
+- */
+- __sem_update_count(sem, 0);
+- retval = -EINTR;
+- break;
+- }
+- schedule();
+- set_task_state(tsk, TASK_INTERRUPTIBLE);
+- }
+- remove_wait_queue(&sem->wait, &wait);
+- __set_task_state(tsk, TASK_RUNNING);
+-
+- wake_up(&sem->wait);
+- return retval;
+-}
+-
+-EXPORT_SYMBOL(__down_interruptible);
+diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h
+index c0faabd..6c8e8c4 100644
+--- a/arch/mips/kernel/signal-common.h
++++ b/arch/mips/kernel/signal-common.h
+@@ -14,7 +14,7 @@
+ /* #define DEBUG_SIG */
+
+ #ifdef DEBUG_SIG
+-# define DEBUGP(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ##args)
++# define DEBUGP(fmt, args...) printk("%s: " fmt, __func__, ##args)
+ #else
+ # define DEBUGP(fmt, args...)
+ #endif
+diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c
+new file mode 100644
+index 0000000..ca476c4
+--- /dev/null
++++ b/arch/mips/kernel/smp-cmp.c
+@@ -0,0 +1,265 @@
++/*
++ * This program is free software; you can distribute 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 it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ *
++ * You 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) 2007 MIPS Technologies, Inc.
++ * Chris Dearman (chris at mips.com)
++ */
+
-+ EMAC2: ethernet at ef601100 {
-+ device_type = "network";
-+ compatible = "ibm,emac-460gt", "ibm,emac4";
-+ interrupt-parent = <&EMAC2>;
-+ interrupts = <0 1>;
-+ #interrupt-cells = <1>;
-+ #address-cells = <0>;
-+ #size-cells = <0>;
-+ interrupt-map = </*Status*/ 0 &UIC2 12 4
-+ /*Wake*/ 1 &UIC2 16 4>;
-+ reg = <ef601100 70>;
-+ local-mac-address = [000000000000]; /* Filled in by U-Boot */
-+ mal-device = <&MAL0>;
-+ mal-tx-channel = <2>;
-+ mal-rx-channel = <10>;
-+ cell-index = <2>;
-+ max-frame-size = <2328>;
-+ rx-fifo-size = <1000>;
-+ tx-fifo-size = <800>;
-+ phy-mode = "rgmii";
-+ phy-map = <00000000>;
-+ rgmii-device = <&RGMII1>;
-+ rgmii-channel = <0>;
-+ has-inverted-stacr-oc;
-+ has-new-stacr-staopc;
-+ mdio-device = <&EMAC0>;
-+ };
++#undef DEBUG
+
-+ EMAC3: ethernet at ef601200 {
-+ device_type = "network";
-+ compatible = "ibm,emac-460gt", "ibm,emac4";
-+ interrupt-parent = <&EMAC3>;
-+ interrupts = <0 1>;
-+ #interrupt-cells = <1>;
-+ #address-cells = <0>;
-+ #size-cells = <0>;
-+ interrupt-map = </*Status*/ 0 &UIC2 13 4
-+ /*Wake*/ 1 &UIC2 17 4>;
-+ reg = <ef601200 70>;
-+ local-mac-address = [000000000000]; /* Filled in by U-Boot */
-+ mal-device = <&MAL0>;
-+ mal-tx-channel = <3>;
-+ mal-rx-channel = <18>;
-+ cell-index = <3>;
-+ max-frame-size = <2328>;
-+ rx-fifo-size = <1000>;
-+ tx-fifo-size = <800>;
-+ phy-mode = "rgmii";
-+ phy-map = <00000000>;
-+ rgmii-device = <&RGMII1>;
-+ rgmii-channel = <1>;
-+ has-inverted-stacr-oc;
-+ has-new-stacr-staopc;
-+ mdio-device = <&EMAC0>;
-+ };
-+ };
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/cpumask.h>
++#include <linux/interrupt.h>
++#include <linux/compiler.h>
+
-+ PCIX0: pci at c0ec00000 {
-+ device_type = "pci";
-+ #interrupt-cells = <1>;
-+ #size-cells = <2>;
-+ #address-cells = <3>;
-+ compatible = "ibm,plb-pcix-460gt", "ibm,plb-pcix";
-+ primary;
-+ large-inbound-windows;
-+ enable-msi-hole;
-+ reg = <c 0ec00000 8 /* Config space access */
-+ 0 0 0 /* no IACK cycles */
-+ c 0ed00000 4 /* Special cycles */
-+ c 0ec80000 100 /* Internal registers */
-+ c 0ec80100 fc>; /* Internal messaging registers */
++#include <asm/atomic.h>
++#include <asm/cacheflush.h>
++#include <asm/cpu.h>
++#include <asm/processor.h>
++#include <asm/system.h>
++#include <asm/hardirq.h>
++#include <asm/mmu_context.h>
++#include <asm/smp.h>
++#include <asm/time.h>
++#include <asm/mipsregs.h>
++#include <asm/mipsmtregs.h>
++#include <asm/mips_mt.h>
+
-+ /* 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>;
++/*
++ * Crude manipulation of the CPU masks to control which
++ * which CPU's are brought online during initialisation
++ *
++ * Beware... this needs to be called after CPU discovery
++ * but before CPU bringup
++ */
++static int __init allowcpus(char *str)
++{
++ cpumask_t cpu_allow_map;
++ char buf[256];
++ int len;
+
-+ /* Inbound 2GB range starting at 0 */
-+ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++ cpus_clear(cpu_allow_map);
++ if (cpulist_parse(str, cpu_allow_map) == 0) {
++ cpu_set(0, cpu_allow_map);
++ cpus_and(cpu_possible_map, cpu_possible_map, cpu_allow_map);
++ len = cpulist_scnprintf(buf, sizeof(buf)-1, cpu_possible_map);
++ buf[len] = '\0';
++ pr_debug("Allowable CPUs: %s\n", buf);
++ return 1;
++ } else
++ return 0;
++}
++__setup("allowcpus=", allowcpus);
+
-+ /* This drives busses 0 to 0x3f */
-+ bus-range = <0 3f>;
++static void ipi_call_function(unsigned int cpu)
++{
++ unsigned int action = 0;
+
-+ /* 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 >;
-+ };
++ pr_debug("CPU%d: %s cpu %d status %08x\n",
++ smp_processor_id(), __func__, cpu, read_c0_status());
+
-+ PCIE0: pciex at d00000000 {
-+ device_type = "pci";
-+ #interrupt-cells = <1>;
-+ #size-cells = <2>;
-+ #address-cells = <3>;
-+ compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
-+ primary;
-+ port = <0>; /* port number */
-+ reg = <d 00000000 20000000 /* Config space access */
-+ c 08010000 00001000>; /* Registers */
-+ dcr-reg = <100 020>;
-+ sdr-base = <300>;
++ switch (cpu) {
++ case 0:
++ action = GIC_IPI_EXT_INTR_CALLFNC_VPE0;
++ break;
++ case 1:
++ action = GIC_IPI_EXT_INTR_CALLFNC_VPE1;
++ break;
++ case 2:
++ action = GIC_IPI_EXT_INTR_CALLFNC_VPE2;
++ break;
++ case 3:
++ action = GIC_IPI_EXT_INTR_CALLFNC_VPE3;
++ break;
++ }
++ gic_send_ipi(action);
++}
+
-+ /* 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>;
++static void ipi_resched(unsigned int cpu)
++{
++ unsigned int action = 0;
+
-+ /* This drives busses 40 to 0x7f */
-+ bus-range = <40 7f>;
++ pr_debug("CPU%d: %s cpu %d status %08x\n",
++ smp_processor_id(), __func__, cpu, read_c0_status());
+
-+ /* 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 */>;
-+ };
++ switch (cpu) {
++ case 0:
++ action = GIC_IPI_EXT_INTR_RESCHED_VPE0;
++ break;
++ case 1:
++ action = GIC_IPI_EXT_INTR_RESCHED_VPE1;
++ break;
++ case 2:
++ action = GIC_IPI_EXT_INTR_RESCHED_VPE2;
++ break;
++ case 3:
++ action = GIC_IPI_EXT_INTR_RESCHED_VPE3;
++ break;
++ }
++ gic_send_ipi(action);
++}
+
-+ PCIE1: pciex at d20000000 {
-+ device_type = "pci";
-+ #interrupt-cells = <1>;
-+ #size-cells = <2>;
-+ #address-cells = <3>;
-+ compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
-+ primary;
-+ port = <1>; /* port number */
-+ reg = <d 20000000 20000000 /* Config space access */
-+ c 08011000 00001000>; /* Registers */
-+ dcr-reg = <120 020>;
-+ sdr-base = <340>;
++/*
++ * FIXME: This isn't restricted to CMP
++ * The SMVP kernel could use GIC interrupts if available
++ */
++void cmp_send_ipi_single(int cpu, unsigned int action)
++{
++ unsigned long flags;
+
-+ /* 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>;
++ local_irq_save(flags);
+
-+ /* Inbound 2GB range starting at 0 */
-+ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++ switch (action) {
++ case SMP_CALL_FUNCTION:
++ ipi_call_function(cpu);
++ break;
+
-+ /* This drives busses 80 to 0xbf */
-+ bus-range = <80 bf>;
++ case SMP_RESCHEDULE_YOURSELF:
++ ipi_resched(cpu);
++ break;
++ }
+
-+ /* 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 */>;
-+ };
-+ };
++ local_irq_restore(flags);
++}
++
++static void cmp_send_ipi_mask(cpumask_t mask, unsigned int action)
++{
++ unsigned int i;
++
++ for_each_cpu_mask(i, mask)
++ cmp_send_ipi_single(i, action);
++}
++
++static void cmp_init_secondary(void)
++{
++ struct cpuinfo_mips *c = ¤t_cpu_data;
++
++ /* Assume GIC is present */
++ change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP6 |
++ STATUSF_IP7);
++
++ /* Enable per-cpu interrupts: platform specific */
++
++ c->core = (read_c0_ebase() >> 1) & 0xff;
++#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
++ c->vpe_id = (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE;
++#endif
++#ifdef CONFIG_MIPS_MT_SMTC
++ c->tc_id = (read_c0_tcbind() >> TCBIND_CURTC_SHIFT) & TCBIND_CURTC;
++#endif
++}
++
++static void cmp_smp_finish(void)
++{
++ pr_debug("SMPCMP: CPU%d: %s\n", smp_processor_id(), __func__);
++
++ /* CDFIXME: remove this? */
++ write_c0_compare(read_c0_count() + (8 * mips_hpt_frequency / HZ));
++
++#ifdef CONFIG_MIPS_MT_FPAFF
++ /* If we have an FPU, enroll ourselves in the FPU-full mask */
++ if (cpu_has_fpu)
++ cpu_set(smp_processor_id(), mt_fpu_cpumask);
++#endif /* CONFIG_MIPS_MT_FPAFF */
++
++ local_irq_enable();
++}
++
++static void cmp_cpus_done(void)
++{
++ pr_debug("SMPCMP: CPU%d: %s\n", smp_processor_id(), __func__);
++}
++
++/*
++ * Setup the PC, SP, and GP of a secondary processor and start it running
++ * smp_bootstrap is the place to resume from
++ * __KSTK_TOS(idle) is apparently the stack pointer
++ * (unsigned long)idle->thread_info the gp
++ */
++static void cmp_boot_secondary(int cpu, struct task_struct *idle)
++{
++ struct thread_info *gp = task_thread_info(idle);
++ unsigned long sp = __KSTK_TOS(idle);
++ unsigned long pc = (unsigned long)&smp_bootstrap;
++ unsigned long a0 = 0;
++
++ pr_debug("SMPCMP: CPU%d: %s cpu %d\n", smp_processor_id(),
++ __func__, cpu);
++
++#if 0
++ /* Needed? */
++ flush_icache_range((unsigned long)gp,
++ (unsigned long)(gp + sizeof(struct thread_info)));
++#endif
++
++ amon_cpu_start(cpu, pc, sp, gp, a0);
++}
++
++/*
++ * Common setup before any secondaries are started
++ */
++void __init cmp_smp_setup(void)
++{
++ int i;
++ int ncpu = 0;
++
++ pr_debug("SMPCMP: CPU%d: %s\n", smp_processor_id(), __func__);
++
++#ifdef CONFIG_MIPS_MT_FPAFF
++ /* If we have an FPU, enroll ourselves in the FPU-full mask */
++ if (cpu_has_fpu)
++ cpu_set(0, mt_fpu_cpumask);
++#endif /* CONFIG_MIPS_MT_FPAFF */
++
++ for (i = 1; i < NR_CPUS; i++) {
++ if (amon_cpu_avail(i)) {
++ cpu_set(i, phys_cpu_present_map);
++ __cpu_number_map[i] = ++ncpu;
++ __cpu_logical_map[ncpu] = i;
++ }
++ }
++
++ if (cpu_has_mipsmt) {
++ unsigned int nvpe, mvpconf0 = read_c0_mvpconf0();
++
++ nvpe = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
++ smp_num_siblings = nvpe;
++ }
++ pr_info("Detected %i available secondary CPU(s)\n", ncpu);
++}
++
++void __init cmp_prepare_cpus(unsigned int max_cpus)
++{
++ pr_debug("SMPCMP: CPU%d: %s max_cpus=%d\n",
++ smp_processor_id(), __func__, max_cpus);
++
++ /*
++ * FIXME: some of these options are per-system, some per-core and
++ * some per-cpu
++ */
++ mips_mt_set_cpuoptions();
++}
++
++struct plat_smp_ops cmp_smp_ops = {
++ .send_ipi_single = cmp_send_ipi_single,
++ .send_ipi_mask = cmp_send_ipi_mask,
++ .init_secondary = cmp_init_secondary,
++ .smp_finish = cmp_smp_finish,
++ .cpus_done = cmp_cpus_done,
++ .boot_secondary = cmp_boot_secondary,
++ .smp_setup = cmp_smp_setup,
++ .prepare_cpus = cmp_prepare_cpus,
+};
-diff --git a/arch/powerpc/boot/dts/haleakala.dts b/arch/powerpc/boot/dts/haleakala.dts
-index ae68fef..b5d95ac 100644
---- a/arch/powerpc/boot/dts/haleakala.dts
-+++ b/arch/powerpc/boot/dts/haleakala.dts
-@@ -12,7 +12,7 @@
- #address-cells = <1>;
- #size-cells = <1>;
- model = "amcc,haleakala";
-- compatible = "amcc,kilauea";
-+ compatible = "amcc,haleakala", "amcc,kilauea";
- dcr-parent = <&/cpus/cpu at 0>;
+diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
+index 89e6f6a..87a1816 100644
+--- a/arch/mips/kernel/smp-mt.c
++++ b/arch/mips/kernel/smp-mt.c
+@@ -36,110 +36,7 @@
+ #include <asm/mipsmtregs.h>
+ #include <asm/mips_mt.h>
- 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
+-#define MIPS_CPU_IPI_RESCHED_IRQ 0
+-#define MIPS_CPU_IPI_CALL_IRQ 1
+-
+-static int cpu_ipi_resched_irq, cpu_ipi_call_irq;
+-
+-#if 0
+-static void dump_mtregisters(int vpe, int tc)
+-{
+- printk("vpe %d tc %d\n", vpe, tc);
+-
+- settc(tc);
+-
+- printk(" c0 status 0x%lx\n", read_vpe_c0_status());
+- printk(" vpecontrol 0x%lx\n", read_vpe_c0_vpecontrol());
+- printk(" vpeconf0 0x%lx\n", read_vpe_c0_vpeconf0());
+- printk(" tcstatus 0x%lx\n", read_tc_c0_tcstatus());
+- printk(" tcrestart 0x%lx\n", read_tc_c0_tcrestart());
+- printk(" tcbind 0x%lx\n", read_tc_c0_tcbind());
+- printk(" tchalt 0x%lx\n", read_tc_c0_tchalt());
+-}
+-#endif
+-
+-void __init sanitize_tlb_entries(void)
+-{
+- int i, tlbsiz;
+- unsigned long mvpconf0, ncpu;
+-
+- if (!cpu_has_mipsmt)
+- return;
+-
+- /* Enable VPC */
+- set_c0_mvpcontrol(MVPCONTROL_VPC);
+-
+- back_to_back_c0_hazard();
+-
+- /* Disable TLB sharing */
+- clear_c0_mvpcontrol(MVPCONTROL_STLB);
+-
+- mvpconf0 = read_c0_mvpconf0();
+-
+- printk(KERN_INFO "MVPConf0 0x%lx TLBS %lx PTLBE %ld\n", mvpconf0,
+- (mvpconf0 & MVPCONF0_TLBS) >> MVPCONF0_TLBS_SHIFT,
+- (mvpconf0 & MVPCONF0_PTLBE) >> MVPCONF0_PTLBE_SHIFT);
+-
+- tlbsiz = (mvpconf0 & MVPCONF0_PTLBE) >> MVPCONF0_PTLBE_SHIFT;
+- ncpu = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
+-
+- printk(" tlbsiz %d ncpu %ld\n", tlbsiz, ncpu);
+-
+- if (tlbsiz > 0) {
+- /* share them out across the vpe's */
+- tlbsiz /= ncpu;
+-
+- printk(KERN_INFO "setting Config1.MMU_size to %d\n", tlbsiz);
+-
+- for (i = 0; i < ncpu; i++) {
+- settc(i);
+-
+- if (i == 0)
+- write_c0_config1((read_c0_config1() & ~(0x3f << 25)) | (tlbsiz << 25));
+- else
+- write_vpe_c0_config1((read_vpe_c0_config1() & ~(0x3f << 25)) |
+- (tlbsiz << 25));
+- }
+- }
+-
+- clear_c0_mvpcontrol(MVPCONTROL_VPC);
+-}
+-
+-static void ipi_resched_dispatch(void)
+-{
+- do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
+-}
+-
+-static void ipi_call_dispatch(void)
+-{
+- do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
+-}
+-
+-static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
+-{
+- return IRQ_HANDLED;
+-}
+-
+-static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
+-{
+- smp_call_function_interrupt();
+-
+- return IRQ_HANDLED;
+-}
+-
+-static struct irqaction irq_resched = {
+- .handler = ipi_resched_interrupt,
+- .flags = IRQF_DISABLED|IRQF_PERCPU,
+- .name = "IPI_resched"
+-};
+-
+-static struct irqaction irq_call = {
+- .handler = ipi_call_interrupt,
+- .flags = IRQF_DISABLED|IRQF_PERCPU,
+- .name = "IPI_call"
+-};
+-
+-static void __init smp_copy_vpe_config(void)
++static void __init smvp_copy_vpe_config(void)
+ {
+ write_vpe_c0_status(
+ (read_c0_status() & ~(ST0_IM | ST0_IE | ST0_KSU)) | ST0_CU0);
+@@ -156,7 +53,7 @@ static void __init smp_copy_vpe_config(void)
+ write_vpe_c0_count(read_c0_count());
+ }
+
+-static unsigned int __init smp_vpe_init(unsigned int tc, unsigned int mvpconf0,
++static unsigned int __init smvp_vpe_init(unsigned int tc, unsigned int mvpconf0,
+ unsigned int ncpu)
+ {
+ if (tc > ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT))
+@@ -182,12 +79,12 @@ static unsigned int __init smp_vpe_init(unsigned int tc, unsigned int mvpconf0,
+ write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE);
+
+ if (tc != 0)
+- smp_copy_vpe_config();
++ smvp_copy_vpe_config();
+
+ return ncpu;
+ }
+
+-static void __init smp_tc_init(unsigned int tc, unsigned int mvpconf0)
++static void __init smvp_tc_init(unsigned int tc, unsigned int mvpconf0)
+ {
+ unsigned long tmp;
+
+@@ -254,15 +151,20 @@ static void vsmp_send_ipi_mask(cpumask_t mask, unsigned int action)
+
+ static void __cpuinit vsmp_init_secondary(void)
+ {
+- /* Enable per-cpu interrupts */
++ extern int gic_present;
+
+ /* This is Malta specific: IPI,performance and timer inetrrupts */
+- write_c0_status((read_c0_status() & ~ST0_IM ) |
+- (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP6 | STATUSF_IP7));
++ if (gic_present)
++ change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 |
++ STATUSF_IP6 | STATUSF_IP7);
++ else
++ change_c0_status(ST0_IM, STATUSF_IP0 | STATUSF_IP1 |
++ STATUSF_IP6 | STATUSF_IP7);
+ }
+
+ static void __cpuinit vsmp_smp_finish(void)
+ {
++ /* CDFIXME: remove this? */
+ write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ));
+
+ #ifdef CONFIG_MIPS_MT_FPAFF
+@@ -323,7 +225,7 @@ static void __cpuinit vsmp_boot_secondary(int cpu, struct task_struct *idle)
+ /*
+ * Common setup before any secondaries are started
+ * Make sure all CPU's are in a sensible state before we boot any of the
+- * secondarys
++ * secondaries
+ */
+ static void __init vsmp_smp_setup(void)
+ {
+@@ -356,8 +258,8 @@ static void __init vsmp_smp_setup(void)
+ for (tc = 0; tc <= ntc; tc++) {
+ settc(tc);
+
+- smp_tc_init(tc, mvpconf0);
+- ncpu = smp_vpe_init(tc, mvpconf0, ncpu);
++ smvp_tc_init(tc, mvpconf0);
++ ncpu = smvp_vpe_init(tc, mvpconf0, ncpu);
+ }
+
+ /* Release config state */
+@@ -371,21 +273,6 @@ static void __init vsmp_smp_setup(void)
+ static void __init vsmp_prepare_cpus(unsigned int max_cpus)
+ {
+ mips_mt_set_cpuoptions();
+-
+- /* set up ipi interrupts */
+- if (cpu_has_vint) {
+- set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
+- set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
+- }
+-
+- cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
+- cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ;
+-
+- setup_irq(cpu_ipi_resched_irq, &irq_resched);
+- setup_irq(cpu_ipi_call_irq, &irq_call);
+-
+- set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq);
+- set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq);
+ }
+
+ struct plat_smp_ops vsmp_smp_ops = {
+diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
+index 9d41dab..33780cc 100644
+--- a/arch/mips/kernel/smp.c
++++ b/arch/mips/kernel/smp.c
+@@ -35,6 +35,7 @@
+ #include <asm/atomic.h>
+ #include <asm/cpu.h>
+ #include <asm/processor.h>
++#include <asm/r4k-timer.h>
+ #include <asm/system.h>
+ #include <asm/mmu_context.h>
+ #include <asm/time.h>
+@@ -125,6 +126,8 @@ asmlinkage __cpuinit void start_secondary(void)
+
+ cpu_set(cpu, cpu_callin_map);
+
++ synchronise_count_slave();
++
+ cpu_idle();
+ }
+
+@@ -287,6 +290,7 @@ void smp_send_stop(void)
+ void __init smp_cpus_done(unsigned int max_cpus)
+ {
+ mp_ops->cpus_done();
++ synchronise_count_master();
+ }
+
+ /* called from main before smp_init() */
+diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
+index b42e71c..3e86318 100644
+--- a/arch/mips/kernel/smtc.c
++++ b/arch/mips/kernel/smtc.c
+@@ -174,14 +174,6 @@ static int clock_hang_reported[NR_CPUS];
+
+ #endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
+
+-/* Initialize shared TLB - the should probably migrate to smtc_setup_cpus() */
+-
+-void __init sanitize_tlb_entries(void)
+-{
+- printk("Deprecated sanitize_tlb_entries() invoked\n");
+-}
+-
+-
+ /*
+ * Configure shared TLB - VPC configuration bit must be set by caller
+ */
+@@ -339,7 +331,8 @@ static void smtc_tc_setup(int vpe, int tc, int cpu)
+ /* In general, all TCs should have the same cpu_data indications */
+ memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips));
+ /* For 34Kf, start with TC/CPU 0 as sole owner of single FPU context */
+- if (cpu_data[0].cputype == CPU_34K)
++ if (cpu_data[0].cputype == CPU_34K ||
++ cpu_data[0].cputype == CPU_1004K)
+ cpu_data[cpu].options &= ~MIPS_CPU_FPU;
+ cpu_data[cpu].vpe_id = vpe;
+ cpu_data[cpu].tc_id = tc;
+diff --git a/arch/mips/kernel/spram.c b/arch/mips/kernel/spram.c
new file mode 100644
-index 0000000..f869ce3
+index 0000000..6ddb507
--- /dev/null
-+++ b/arch/powerpc/boot/dts/ksi8560.dts
-@@ -0,0 +1,267 @@
++++ b/arch/mips/kernel/spram.c
+@@ -0,0 +1,221 @@
+/*
-+ * Device Tree Source for Emerson KSI8560
-+ *
-+ * Author: Alexandr Smirnov <asmirnov at ru.mvista.com>
++ * MIPS SPRAM support
+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the 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) 2007, 2008 MIPS Technologies, Inc.
+ */
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/ptrace.h>
++#include <linux/stddef.h>
+
-+/dts-v1/;
++#include <asm/cpu.h>
++#include <asm/fpu.h>
++#include <asm/mipsregs.h>
++#include <asm/system.h>
++#include <asm/r4kcache.h>
++#include <asm/hazards.h>
+
-+/ {
-+ model = "KSI8560";
-+ compatible = "emerson,KSI8560";
-+ #address-cells = <1>;
-+ #size-cells = <1>;
++/*
++ * These definitions are correct for the 24K/34K/74K SPRAM sample
++ * implementation. The 4KS interpreted the tags differently...
++ */
++#define SPRAM_TAG0_ENABLE 0x00000080
++#define SPRAM_TAG0_PA_MASK 0xfffff000
++#define SPRAM_TAG1_SIZE_MASK 0xfffff000
+
-+ aliases {
-+ ethernet0 = &enet0;
-+ ethernet1 = &enet1;
-+ ethernet2 = &enet2;
-+ };
++#define SPRAM_TAG_STRIDE 8
+
-+ cpus {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
++#define ERRCTL_SPRAM (1 << 28)
+
-+ PowerPC,8560 at 0 {
-+ device_type = "cpu";
-+ reg = <0>;
-+ d-cache-line-size = <32>;
-+ i-cache-line-size = <32>;
-+ d-cache-size = <0x8000>; /* L1, 32K */
-+ i-cache-size = <0x8000>; /* L1, 32K */
-+ timebase-frequency = <0>; /* From U-boot */
-+ bus-frequency = <0>; /* From U-boot */
-+ clock-frequency = <0>; /* From U-boot */
-+ };
-+ };
++/* errctl access */
++#define read_c0_errctl(x) read_c0_ecc(x)
++#define write_c0_errctl(x) write_c0_ecc(x)
+
-+ memory {
-+ device_type = "memory";
-+ reg = <0x00000000 0x10000000>; /* Fixed by bootwrapper */
-+ };
++/*
++ * Different semantics to the set_c0_* function built by __BUILD_SET_C0
++ */
++static __cpuinit unsigned int bis_c0_errctl(unsigned int set)
++{
++ unsigned int res;
++ res = read_c0_errctl();
++ write_c0_errctl(res | set);
++ return res;
++}
+
-+ soc at fdf00000 {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ device_type = "soc";
-+ ranges = <0x00000000 0xfdf00000 0x00100000>;
-+ bus-frequency = <0>; /* Fixed by bootwrapper */
++static __cpuinit void ispram_store_tag(unsigned int offset, unsigned int data)
++{
++ unsigned int errctl;
+
-+ memory-controller at 2000 {
-+ compatible = "fsl,8540-memory-controller";
-+ reg = <0x2000 0x1000>;
-+ interrupt-parent = <&MPIC>;
-+ interrupts = <0x12 0x2>;
-+ };
++ /* enable SPRAM tag access */
++ errctl = bis_c0_errctl(ERRCTL_SPRAM);
++ ehb();
+
-+ l2-cache-controller at 20000 {
-+ compatible = "fsl,8540-l2-cache-controller";
-+ reg = <0x20000 0x1000>;
-+ cache-line-size = <0x20>; /* 32 bytes */
-+ cache-size = <0x40000>; /* L2, 256K */
-+ interrupt-parent = <&MPIC>;
-+ interrupts = <0x10 0x2>;
-+ };
++ write_c0_taglo(data);
++ ehb();
+
-+ i2c at 3000 {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ cell-index = <0>;
-+ compatible = "fsl-i2c";
-+ reg = <0x3000 0x100>;
-+ interrupts = <0x2b 0x2>;
-+ interrupt-parent = <&MPIC>;
-+ dfsrr;
-+ };
++ cache_op(Index_Store_Tag_I, CKSEG0|offset);
++ ehb();
+
-+ mdio at 24520 { /* For TSECs */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ compatible = "fsl,gianfar-mdio";
-+ reg = <0x24520 0x20>;
++ write_c0_errctl(errctl);
++ ehb();
++}
+
-+ PHY1: ethernet-phy at 1 {
-+ interrupt-parent = <&MPIC>;
-+ reg = <0x1>;
-+ device_type = "ethernet-phy";
-+ };
+
-+ PHY2: ethernet-phy at 2 {
-+ interrupt-parent = <&MPIC>;
-+ reg = <0x2>;
-+ device_type = "ethernet-phy";
-+ };
-+ };
++static __cpuinit unsigned int ispram_load_tag(unsigned int offset)
++{
++ unsigned int data;
++ unsigned int errctl;
+
-+ enet0: ethernet at 24000 {
-+ device_type = "network";
-+ model = "TSEC";
-+ compatible = "gianfar";
-+ reg = <0x24000 0x1000>;
-+ /* Mac address filled in by bootwrapper */
-+ local-mac-address = [ 00 00 00 00 00 00 ];
-+ interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
-+ interrupt-parent = <&MPIC>;
-+ phy-handle = <&PHY1>;
-+ };
++ /* enable SPRAM tag access */
++ errctl = bis_c0_errctl(ERRCTL_SPRAM);
++ ehb();
++ cache_op(Index_Load_Tag_I, CKSEG0 | offset);
++ ehb();
++ data = read_c0_taglo();
++ ehb();
++ write_c0_errctl(errctl);
++ ehb();
+
-+ enet1: ethernet at 25000 {
-+ device_type = "network";
-+ model = "TSEC";
-+ compatible = "gianfar";
-+ reg = <0x25000 0x1000>;
-+ /* Mac address filled in by bootwrapper */
-+ local-mac-address = [ 00 00 00 00 00 00 ];
-+ interrupts = <0x23 0x2 0x24 0x2 0x28 0x2>;
-+ interrupt-parent = <&MPIC>;
-+ phy-handle = <&PHY2>;
-+ };
++ return data;
++}
+
-+ MPIC: pic at 40000 {
-+ #address-cells = <0>;
-+ #interrupt-cells = <2>;
-+ interrupt-controller;
-+ reg = <0x40000 0x40000>;
-+ device_type = "open-pic";
-+ };
++static __cpuinit void dspram_store_tag(unsigned int offset, unsigned int data)
++{
++ unsigned int errctl;
+
-+ cpm at 919c0 {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ compatible = "fsl,mpc8560-cpm", "fsl,cpm2";
-+ reg = <0x919c0 0x30>;
-+ ranges;
++ /* enable SPRAM tag access */
++ errctl = bis_c0_errctl(ERRCTL_SPRAM);
++ ehb();
++ write_c0_dtaglo(data);
++ ehb();
++ cache_op(Index_Store_Tag_D, CKSEG0 | offset);
++ ehb();
++ write_c0_errctl(errctl);
++ ehb();
++}
+
-+ muram at 80000 {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges = <0x0 0x80000 0x10000>;
+
-+ data at 0 {
-+ compatible = "fsl,cpm-muram-data";
-+ reg = <0x0 0x4000 0x9000 0x2000>;
-+ };
-+ };
++static __cpuinit unsigned int dspram_load_tag(unsigned int offset)
++{
++ unsigned int data;
++ unsigned int errctl;
++
++ errctl = bis_c0_errctl(ERRCTL_SPRAM);
++ ehb();
++ cache_op(Index_Load_Tag_D, CKSEG0 | offset);
++ ehb();
++ data = read_c0_dtaglo();
++ ehb();
++ write_c0_errctl(errctl);
++ ehb();
+
-+ brg at 919f0 {
-+ compatible = "fsl,mpc8560-brg",
-+ "fsl,cpm2-brg",
-+ "fsl,cpm-brg";
-+ reg = <0x919f0 0x10 0x915f0 0x10>;
-+ clock-frequency = <165000000>; /* 166MHz */
-+ };
++ return data;
++}
+
-+ CPMPIC: pic at 90c00 {
-+ #address-cells = <0>;
-+ #interrupt-cells = <2>;
-+ interrupt-controller;
-+ interrupts = <0x2e 0x2>;
-+ interrupt-parent = <&MPIC>;
-+ reg = <0x90c00 0x80>;
-+ compatible = "fsl,mpc8560-cpm-pic", "fsl,cpm2-pic";
-+ };
++static __cpuinit void probe_spram(char *type,
++ unsigned int base,
++ unsigned int (*read)(unsigned int),
++ void (*write)(unsigned int, unsigned int))
++{
++ unsigned int firstsize = 0, lastsize = 0;
++ unsigned int firstpa = 0, lastpa = 0, pa = 0;
++ unsigned int offset = 0;
++ unsigned int size, tag0, tag1;
++ unsigned int enabled;
++ int i;
+
-+ serial at 91a00 {
-+ device_type = "serial";
-+ compatible = "fsl,mpc8560-scc-uart",
-+ "fsl,cpm2-scc-uart";
-+ reg = <0x91a00 0x20 0x88000 0x100>;
-+ fsl,cpm-brg = <1>;
-+ fsl,cpm-command = <0x800000>;
-+ current-speed = <0x1c200>;
-+ interrupts = <0x28 0x8>;
-+ interrupt-parent = <&CPMPIC>;
-+ };
++ /*
++ * The limit is arbitrary but avoids the loop running away if
++ * the SPRAM tags are implemented differently
++ */
+
-+ serial at 91a20 {
-+ device_type = "serial";
-+ compatible = "fsl,mpc8560-scc-uart",
-+ "fsl,cpm2-scc-uart";
-+ reg = <0x91a20 0x20 0x88100 0x100>;
-+ fsl,cpm-brg = <2>;
-+ fsl,cpm-command = <0x4a00000>;
-+ current-speed = <0x1c200>;
-+ interrupts = <0x29 0x8>;
-+ interrupt-parent = <&CPMPIC>;
-+ };
++ for (i = 0; i < 8; i++) {
++ tag0 = read(offset);
++ tag1 = read(offset+SPRAM_TAG_STRIDE);
++ pr_debug("DBG %s%d: tag0=%08x tag1=%08x\n",
++ type, i, tag0, tag1);
+
-+ mdio at 90d00 { /* For FCCs */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ compatible = "fsl,cpm2-mdio-bitbang";
-+ reg = <0x90d00 0x14>;
-+ fsl,mdio-pin = <24>;
-+ fsl,mdc-pin = <25>;
++ size = tag1 & SPRAM_TAG1_SIZE_MASK;
+
-+ PHY0: ethernet-phy at 0 {
-+ interrupt-parent = <&MPIC>;
-+ reg = <0x0>;
-+ device_type = "ethernet-phy";
-+ };
-+ };
++ if (size == 0)
++ break;
+
-+ enet2: ethernet at 91300 {
-+ device_type = "network";
-+ compatible = "fsl,mpc8560-fcc-enet",
-+ "fsl,cpm2-fcc-enet";
-+ reg = <0x91300 0x20 0x88400 0x100 0x91390 0x1>;
-+ /* Mac address filled in by bootwrapper */
-+ local-mac-address = [ 00 00 00 00 00 00 ];
-+ fsl,cpm-command = <0x12000300>;
-+ interrupts = <0x20 0x8>;
-+ interrupt-parent = <&CPMPIC>;
-+ phy-handle = <&PHY0>;
-+ };
-+ };
-+ };
++ if (i != 0) {
++ /* tags may repeat... */
++ if ((pa == firstpa && size == firstsize) ||
++ (pa == lastpa && size == lastsize))
++ break;
++ }
+
-+ localbus at fdf05000 {
-+ #address-cells = <2>;
-+ #size-cells = <1>;
-+ compatible = "fsl,mpc8560-localbus";
-+ reg = <0xfdf05000 0x68>;
++ /* Align base with size */
++ base = (base + size - 1) & ~(size-1);
+
-+ ranges = <0x0 0x0 0xe0000000 0x00800000
-+ 0x4 0x0 0xe8080000 0x00080000>;
++ /* reprogram the base address base address and enable */
++ tag0 = (base & SPRAM_TAG0_PA_MASK) | SPRAM_TAG0_ENABLE;
++ write(offset, tag0);
++
++ base += size;
++
++ /* reread the tag */
++ tag0 = read(offset);
++ pa = tag0 & SPRAM_TAG0_PA_MASK;
++ enabled = tag0 & SPRAM_TAG0_ENABLE;
+
-+ flash at 0,0 {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ compatible = "jedec-flash";
-+ reg = <0x0 0x0 0x800000>;
-+ bank-width = <0x2>;
++ if (i == 0) {
++ firstpa = pa;
++ firstsize = size;
++ }
+
-+ partition at 0 {
-+ label = "Primary Kernel";
-+ reg = <0x0 0x180000>;
-+ };
-+ partition at 180000 {
-+ label = "Primary Filesystem";
-+ reg = <0x180000 0x580000>;
-+ };
-+ partition at 700000 {
-+ label = "Monitor";
-+ reg = <0x300000 0x100000>;
-+ read-only;
-+ };
-+ };
++ lastpa = pa;
++ lastsize = size;
+
-+ cpld at 4,0 {
-+ compatible = "emerson,KSI8560-cpld";
-+ reg = <0x4 0x0 0x80000>;
-+ };
-+ };
++ if (strcmp(type, "DSPRAM") == 0) {
++ unsigned int *vp = (unsigned int *)(CKSEG1 | pa);
++ unsigned int v;
++#define TDAT 0x5a5aa5a5
++ vp[0] = TDAT;
++ vp[1] = ~TDAT;
+
++ mb();
+
-+ chosen {
-+ linux,stdout-path = "/soc/cpm/serial at 91a00";
-+ };
-+};
-diff --git a/arch/powerpc/boot/dts/kuroboxHD.dts b/arch/powerpc/boot/dts/kuroboxHD.dts
-index 4469588..2e5a1a1 100644
---- a/arch/powerpc/boot/dts/kuroboxHD.dts
-+++ b/arch/powerpc/boot/dts/kuroboxHD.dts
-@@ -7,6 +7,7 @@
- * Based on sandpoint.dts
- *
- * 2006 (c) G. Liakhovetski <g.liakhovetski at gmx.de>
-+ * Copyright 2008 Freescale Semiconductor, Inc.
- *
- * This file is licensed under
- * the terms of the GNU General Public License version 2. This program
-@@ -17,6 +18,8 @@ XXXX add flash parts, rtc, ??
++ v = vp[0];
++ if (v != TDAT)
++ printk(KERN_ERR "vp=%p wrote=%08x got=%08x\n",
++ vp, TDAT, v);
++ v = vp[1];
++ if (v != ~TDAT)
++ printk(KERN_ERR "vp=%p wrote=%08x got=%08x\n",
++ vp+1, ~TDAT, v);
++ }
++
++ pr_info("%s%d: PA=%08x,Size=%08x%s\n",
++ type, i, pa, size, enabled ? ",enabled" : "");
++ offset += 2 * SPRAM_TAG_STRIDE;
++ }
++}
++
++__cpuinit void spram_config(void)
++{
++ struct cpuinfo_mips *c = ¤t_cpu_data;
++ unsigned int config0;
++
++ switch (c->cputype) {
++ case CPU_24K:
++ case CPU_34K:
++ case CPU_74K:
++ config0 = read_c0_config();
++ /* FIXME: addresses are Malta specific */
++ if (config0 & (1<<24)) {
++ probe_spram("ISPRAM", 0x1c000000,
++ &ispram_load_tag, &ispram_store_tag);
++ }
++ if (config0 & (1<<23))
++ probe_spram("DSPRAM", 0x1c100000,
++ &dspram_load_tag, &dspram_store_tag);
++ }
++}
+diff --git a/arch/mips/kernel/sync-r4k.c b/arch/mips/kernel/sync-r4k.c
+new file mode 100644
+index 0000000..9021108
+--- /dev/null
++++ b/arch/mips/kernel/sync-r4k.c
+@@ -0,0 +1,159 @@
++/*
++ * Count register synchronisation.
++ *
++ * All CPUs will have their count registers synchronised to the CPU0 expirelo
++ * value. This can cause a small timewarp for CPU0. All other CPU's should
++ * not have done anything significant (but they may have had interrupts
++ * enabled briefly - prom_smp_finish() should not be responsible for enabling
++ * interrupts...)
++ *
++ * FIXME: broken for SMTC
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/irqflags.h>
++#include <linux/r4k-timer.h>
++
++#include <asm/atomic.h>
++#include <asm/barrier.h>
++#include <asm/cpumask.h>
++#include <asm/mipsregs.h>
++
++static atomic_t __initdata count_start_flag = ATOMIC_INIT(0);
++static atomic_t __initdata count_count_start = ATOMIC_INIT(0);
++static atomic_t __initdata count_count_stop = ATOMIC_INIT(0);
++
++#define COUNTON 100
++#define NR_LOOPS 5
++
++void __init synchronise_count_master(void)
++{
++ int i;
++ unsigned long flags;
++ unsigned int initcount;
++ int nslaves;
++
++#ifdef CONFIG_MIPS_MT_SMTC
++ /*
++ * SMTC needs to synchronise per VPE, not per CPU
++ * ignore for now
++ */
++ return;
++#endif
++
++ pr_info("Checking COUNT synchronization across %u CPUs: ",
++ num_online_cpus());
++
++ local_irq_save(flags);
++
++ /*
++ * Notify the slaves that it's time to start
++ */
++ atomic_set(&count_start_flag, 1);
++ smp_wmb();
++
++ /* Count will be initialised to expirelo for all CPU's */
++ initcount = expirelo;
++
++ /*
++ * We loop a few times to get a primed instruction cache,
++ * then the last pass is more or less synchronised and
++ * the master and slaves each set their cycle counters to a known
++ * value all at once. This reduces the chance of having random offsets
++ * between the processors, and guarantees that the maximum
++ * delay between the cycle counters is never bigger than
++ * the latency of information-passing (cachelines) between
++ * two CPUs.
++ */
++
++ nslaves = num_online_cpus()-1;
++ for (i = 0; i < NR_LOOPS; i++) {
++ /* slaves loop on '!= ncpus' */
++ while (atomic_read(&count_count_start) != nslaves)
++ mb();
++ atomic_set(&count_count_stop, 0);
++ smp_wmb();
++
++ /* this lets the slaves write their count register */
++ atomic_inc(&count_count_start);
++
++ /*
++ * Everyone initialises count in the last loop:
++ */
++ if (i == NR_LOOPS-1)
++ write_c0_count(initcount);
++
++ /*
++ * Wait for all slaves to leave the synchronization point:
++ */
++ while (atomic_read(&count_count_stop) != nslaves)
++ mb();
++ atomic_set(&count_count_start, 0);
++ smp_wmb();
++ atomic_inc(&count_count_stop);
++ }
++ /* Arrange for an interrupt in a short while */
++ write_c0_compare(read_c0_count() + COUNTON);
++
++ local_irq_restore(flags);
++
++ /*
++ * i386 code reported the skew here, but the
++ * count registers were almost certainly out of sync
++ * so no point in alarming people
++ */
++ printk("done.\n");
++}
++
++void __init synchronise_count_slave(void)
++{
++ int i;
++ unsigned long flags;
++ unsigned int initcount;
++ int ncpus;
++
++#ifdef CONFIG_MIPS_MT_SMTC
++ /*
++ * SMTC needs to synchronise per VPE, not per CPU
++ * ignore for now
++ */
++ return;
++#endif
++
++ local_irq_save(flags);
++
++ /*
++ * Not every cpu is online at the time this gets called,
++ * so we first wait for the master to say everyone is ready
++ */
++
++ while (!atomic_read(&count_start_flag))
++ mb();
++
++ /* Count will be initialised to expirelo for all CPU's */
++ initcount = expirelo;
++
++ ncpus = num_online_cpus();
++ for (i = 0; i < NR_LOOPS; i++) {
++ atomic_inc(&count_count_start);
++ while (atomic_read(&count_count_start) != ncpus)
++ mb();
++
++ /*
++ * Everyone initialises count in the last loop:
++ */
++ if (i == NR_LOOPS-1)
++ write_c0_count(initcount);
++
++ atomic_inc(&count_count_stop);
++ while (atomic_read(&count_count_stop) != ncpus)
++ mb();
++ }
++ /* Arrange for an interrupt in a short while */
++ write_c0_compare(read_c0_count() + COUNTON);
++
++ local_irq_restore(flags);
++}
++#undef NR_LOOPS
++#endif
+diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
+index b45a709..1f467d5 100644
+--- a/arch/mips/kernel/time.c
++++ b/arch/mips/kernel/time.c
+@@ -38,7 +38,6 @@ int __weak rtc_mips_set_time(unsigned long sec)
+ {
+ return 0;
+ }
+-EXPORT_SYMBOL(rtc_mips_set_time);
- */
+ int __weak rtc_mips_set_mmss(unsigned long nowtime)
+ {
+@@ -50,13 +49,11 @@ int update_persistent_clock(struct timespec now)
+ return rtc_mips_set_mmss(now.tv_sec);
+ }
-+/dts-v1/;
-+
- / {
- model = "KuroboxHD";
- compatible = "linkstation";
-@@ -35,19 +38,19 @@ XXXX add flash parts, rtc, ??
+-int null_perf_irq(void)
++static int null_perf_irq(void)
+ {
+ return 0;
+ }
- PowerPC,603e { /* Really 8241 */
- device_type = "cpu";
-- reg = <0>;
-- clock-frequency = <bebc200>; /* Fixed by bootloader */
-- timebase-frequency = <1743000>; /* Fixed by bootloader */
-+ reg = <0x0>;
-+ clock-frequency = <200000000>; /* Fixed by bootloader */
-+ timebase-frequency = <24391680>; /* Fixed by bootloader */
- bus-frequency = <0>; /* Fixed by bootloader */
- /* Following required by dtc but not used */
-- i-cache-size = <4000>;
-- d-cache-size = <4000>;
-+ i-cache-size = <0x4000>;
-+ d-cache-size = <0x4000>;
- };
- };
+-EXPORT_SYMBOL(null_perf_irq);
+-
+ int (*perf_irq)(void) = null_perf_irq;
- memory {
- device_type = "memory";
-- reg = <00000000 04000000>;
-+ reg = <0x0 0x4000000>;
- };
+ EXPORT_SYMBOL(perf_irq);
+diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
+index 984c0d0..cb8b0e2 100644
+--- a/arch/mips/kernel/traps.c
++++ b/arch/mips/kernel/traps.c
+@@ -22,6 +22,7 @@
+ #include <linux/kallsyms.h>
+ #include <linux/bootmem.h>
+ #include <linux/interrupt.h>
++#include <linux/ptrace.h>
- 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 */
+ #include <asm/bootinfo.h>
+ #include <asm/branch.h>
+@@ -80,19 +81,22 @@ void (*board_bind_eic_interrupt)(int irq, int regset);
- i2c at 80003000 {
- #address-cells = <1>;
- #size-cells = <0>;
- cell-index = <0>;
- compatible = "fsl-i2c";
-- reg = <80003000 1000>;
-+ reg = <0x80003000 0x1000>;
- interrupts = <5 2>;
- interrupt-parent = <&mpic>;
+ static void show_raw_backtrace(unsigned long reg29)
+ {
+- unsigned long *sp = (unsigned long *)reg29;
++ unsigned long *sp = (unsigned long *)(reg29 & ~3);
+ unsigned long addr;
- rtc at 32 {
- device_type = "rtc";
- compatible = "ricoh,rs5c372a";
-- reg = <32>;
-+ reg = <0x32>;
- };
- };
+ printk("Call Trace:");
+ #ifdef CONFIG_KALLSYMS
+ printk("\n");
+ #endif
+- while (!kstack_end(sp)) {
+- addr = *sp++;
+- if (__kernel_text_address(addr))
+- print_ip_sym(addr);
++#define IS_KVA01(a) ((((unsigned int)a) & 0xc0000000) == 0x80000000)
++ if (IS_KVA01(sp)) {
++ while (!kstack_end(sp)) {
++ addr = *sp++;
++ if (__kernel_text_address(addr))
++ print_ip_sym(addr);
++ }
++ printk("\n");
+ }
+- printk("\n");
+ }
-@@ -83,9 +86,9 @@ XXXX add flash parts, rtc, ??
- cell-index = <0>;
- device_type = "serial";
- compatible = "ns16550";
-- reg = <80004500 8>;
-- clock-frequency = <5d08d88>;
-- current-speed = <2580>;
-+ reg = <0x80004500 0x8>;
-+ clock-frequency = <97553800>;
-+ current-speed = <9600>;
- interrupts = <9 0>;
- interrupt-parent = <&mpic>;
- };
-@@ -94,10 +97,10 @@ XXXX add flash parts, rtc, ??
- cell-index = <1>;
- device_type = "serial";
- compatible = "ns16550";
-- reg = <80004600 8>;
-- clock-frequency = <5d08d88>;
-- current-speed = <e100>;
-- interrupts = <a 0>;
-+ reg = <0x80004600 0x8>;
-+ clock-frequency = <97553800>;
-+ current-speed = <57600>;
-+ interrupts = <10 0>;
- interrupt-parent = <&mpic>;
- };
+ #ifdef CONFIG_KALLSYMS
+@@ -192,16 +196,19 @@ EXPORT_SYMBOL(dump_stack);
+ static void show_code(unsigned int __user *pc)
+ {
+ long i;
++ unsigned short __user *pc16 = NULL;
-@@ -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>;
- };
+ printk("\nCode:");
- pci0: pci at fec00000 {
-@@ -116,29 +119,29 @@ XXXX add flash parts, rtc, ??
- #interrupt-cells = <1>;
- device_type = "pci";
- compatible = "mpc10x-pci";
-- reg = <fec00000 400000>;
-- ranges = <01000000 0 0 fe000000 0 00c00000
-- 02000000 0 80000000 80000000 0 70000000>;
-- bus-range = <0 ff>;
-- clock-frequency = <7f28155>;
-+ reg = <0xfec00000 0x400000>;
-+ ranges = <0x1000000 0x0 0x0 0xfe000000 0x0 0xc00000
-+ 0x2000000 0x0 0x80000000 0x80000000 0x0 0x70000000>;
-+ bus-range = <0 255>;
-+ clock-frequency = <133333333>;
- interrupt-parent = <&mpic>;
-- interrupt-map-mask = <f800 0 0 7>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
- /* IDSEL 11 - IRQ0 ETH */
-- 5800 0 0 1 &mpic 0 1
-- 5800 0 0 2 &mpic 1 1
-- 5800 0 0 3 &mpic 2 1
-- 5800 0 0 4 &mpic 3 1
-+ 0x5800 0x0 0x0 0x1 &mpic 0x0 0x1
-+ 0x5800 0x0 0x0 0x2 &mpic 0x1 0x1
-+ 0x5800 0x0 0x0 0x3 &mpic 0x2 0x1
-+ 0x5800 0x0 0x0 0x4 &mpic 0x3 0x1
- /* IDSEL 12 - IRQ1 IDE0 */
-- 6000 0 0 1 &mpic 1 1
-- 6000 0 0 2 &mpic 2 1
-- 6000 0 0 3 &mpic 3 1
-- 6000 0 0 4 &mpic 0 1
-+ 0x6000 0x0 0x0 0x1 &mpic 0x1 0x1
-+ 0x6000 0x0 0x0 0x2 &mpic 0x2 0x1
-+ 0x6000 0x0 0x0 0x3 &mpic 0x3 0x1
-+ 0x6000 0x0 0x0 0x4 &mpic 0x0 0x1
- /* IDSEL 14 - IRQ3 USB2.0 */
-- 7000 0 0 1 &mpic 3 1
-- 7000 0 0 2 &mpic 3 1
-- 7000 0 0 3 &mpic 3 1
-- 7000 0 0 4 &mpic 3 1
-+ 0x7000 0x0 0x0 0x1 &mpic 0x3 0x1
-+ 0x7000 0x0 0x0 0x2 &mpic 0x3 0x1
-+ 0x7000 0x0 0x0 0x3 &mpic 0x3 0x1
-+ 0x7000 0x0 0x0 0x4 &mpic 0x3 0x1
- >;
- };
- };
-diff --git a/arch/powerpc/boot/dts/kuroboxHG.dts b/arch/powerpc/boot/dts/kuroboxHG.dts
-index 8443c85..e4916e6 100644
---- a/arch/powerpc/boot/dts/kuroboxHG.dts
-+++ b/arch/powerpc/boot/dts/kuroboxHG.dts
-@@ -7,6 +7,7 @@
- * Based on sandpoint.dts
- *
- * 2006 (c) G. Liakhovetski <g.liakhovetski at gmx.de>
-+ * Copyright 2008 Freescale Semiconductor, Inc.
- *
- * This file is licensed under
- * the terms of the GNU General Public License version 2. This program
-@@ -17,6 +18,8 @@ XXXX add flash parts, rtc, ??
++ if ((unsigned long)pc & 1)
++ pc16 = (unsigned short __user *)((unsigned long)pc & ~1);
+ for(i = -3 ; i < 6 ; i++) {
+ unsigned int insn;
+- if (__get_user(insn, pc + i)) {
++ if (pc16 ? __get_user(insn, pc16 + i) : __get_user(insn, pc + i)) {
+ printk(" (Bad address in epc)\n");
+ break;
+ }
+- printk("%c%08x%c", (i?' ':'<'), insn, (i?' ':'>'));
++ printk("%c%0*x%c", (i?' ':'<'), pc16 ? 4 : 8, insn, (i?' ':'>'));
+ }
+ }
- */
+@@ -311,10 +318,21 @@ void show_regs(struct pt_regs *regs)
-+/dts-v1/;
+ void show_registers(const struct pt_regs *regs)
+ {
++ const int field = 2 * sizeof(unsigned long);
+
- / {
- model = "KuroboxHG";
- compatible = "linkstation";
-@@ -35,19 +38,19 @@ XXXX add flash parts, rtc, ??
-
- PowerPC,603e { /* Really 8241 */
- device_type = "cpu";
-- reg = <0>;
-- clock-frequency = <fdad680>; /* Fixed by bootloader */
-- timebase-frequency = <1F04000>; /* Fixed by bootloader */
-+ reg = <0x0>;
-+ clock-frequency = <266000000>; /* Fixed by bootloader */
-+ timebase-frequency = <32522240>; /* Fixed by bootloader */
- bus-frequency = <0>; /* Fixed by bootloader */
- /* Following required by dtc but not used */
-- i-cache-size = <4000>;
-- d-cache-size = <4000>;
-+ i-cache-size = <0x4000>;
-+ d-cache-size = <0x4000>;
- };
- };
+ __show_regs(regs);
+ print_modules();
+- printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n",
+- current->comm, task_pid_nr(current), current_thread_info(), current);
++ printk("Process %s (pid: %d, threadinfo=%p, task=%p, tls=%0*lx)\n",
++ current->comm, current->pid, current_thread_info(), current,
++ field, current_thread_info()->tp_value);
++ if (cpu_has_userlocal) {
++ unsigned long tls;
++
++ tls = read_c0_userlocal();
++ if (tls != current_thread_info()->tp_value)
++ printk("*HwTLS: %0*lx\n", field, tls);
++ }
++
+ show_stacktrace(current, regs);
+ show_code((unsigned int __user *) regs->cp0_epc);
+ printk("\n");
+@@ -657,35 +675,24 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
+ force_sig_info(SIGFPE, &info, current);
+ }
- memory {
- device_type = "memory";
-- reg = <00000000 08000000>;
-+ reg = <0x0 0x8000000>;
- };
+-asmlinkage void do_bp(struct pt_regs *regs)
++static void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
++ const char *str)
+ {
+- unsigned int opcode, bcode;
+ siginfo_t info;
+-
+- if (__get_user(opcode, (unsigned int __user *) exception_epc(regs)))
+- goto out_sigsegv;
+-
+- /*
+- * There is the ancient bug in the MIPS assemblers that the break
+- * code starts left to bit 16 instead to bit 6 in the opcode.
+- * Gas is bug-compatible, but not always, grrr...
+- * We handle both cases with a simple heuristics. --macro
+- */
+- bcode = ((opcode >> 6) & ((1 << 20) - 1));
+- if (bcode < (1 << 10))
+- bcode <<= 10;
++ char b[40];
+
+ /*
+- * (A short test says that IRIX 5.3 sends SIGTRAP for all break
+- * insns, even for break codes that indicate arithmetic failures.
+- * Weird ...)
++ * A short test says that IRIX 5.3 sends SIGTRAP for all trap
++ * insns, even for trap and break codes that indicate arithmetic
++ * failures. Weird ...
+ * But should we continue the brokenness??? --macro
+ */
+- switch (bcode) {
+- case BRK_OVERFLOW << 10:
+- case BRK_DIVZERO << 10:
+- die_if_kernel("Break instruction in kernel code", regs);
+- if (bcode == (BRK_DIVZERO << 10))
++ switch (code) {
++ case BRK_OVERFLOW:
++ case BRK_DIVZERO:
++ scnprintf(b, sizeof(b), "%s instruction in kernel code", str);
++ die_if_kernel(b, regs);
++ if (code == BRK_DIVZERO)
+ info.si_code = FPE_INTDIV;
+ else
+ info.si_code = FPE_INTOVF;
+@@ -695,12 +702,34 @@ asmlinkage void do_bp(struct pt_regs *regs)
+ force_sig_info(SIGFPE, &info, current);
+ break;
+ case BRK_BUG:
+- die("Kernel bug detected", regs);
++ die_if_kernel("Kernel bug detected", regs);
++ force_sig(SIGTRAP, current);
+ break;
+ default:
+- die_if_kernel("Break instruction in kernel code", regs);
++ scnprintf(b, sizeof(b), "%s instruction in kernel code", str);
++ die_if_kernel(b, regs);
+ force_sig(SIGTRAP, current);
+ }
++}
++
++asmlinkage void do_bp(struct pt_regs *regs)
++{
++ unsigned int opcode, bcode;
++
++ if (__get_user(opcode, (unsigned int __user *) exception_epc(regs)))
++ goto out_sigsegv;
++
++ /*
++ * There is the ancient bug in the MIPS assemblers that the break
++ * code starts left to bit 16 instead to bit 6 in the opcode.
++ * Gas is bug-compatible, but not always, grrr...
++ * We handle both cases with a simple heuristics. --macro
++ */
++ bcode = ((opcode >> 6) & ((1 << 20) - 1));
++ if (bcode >= (1 << 10))
++ bcode >>= 10;
++
++ do_trap_or_bp(regs, bcode, "Break");
+ return;
- 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 */
+ out_sigsegv:
+@@ -710,7 +739,6 @@ out_sigsegv:
+ asmlinkage void do_tr(struct pt_regs *regs)
+ {
+ unsigned int opcode, tcode = 0;
+- siginfo_t info;
- i2c at 80003000 {
- #address-cells = <1>;
- #size-cells = <0>;
- cell-index = <0>;
- compatible = "fsl-i2c";
-- reg = <80003000 1000>;
-+ reg = <0x80003000 0x1000>;
- interrupts = <5 2>;
- interrupt-parent = <&mpic>;
+ if (__get_user(opcode, (unsigned int __user *) exception_epc(regs)))
+ goto out_sigsegv;
+@@ -719,32 +747,7 @@ asmlinkage void do_tr(struct pt_regs *regs)
+ if (!(opcode & OPCODE))
+ tcode = ((opcode >> 6) & ((1 << 10) - 1));
+
+- /*
+- * (A short test says that IRIX 5.3 sends SIGTRAP for all trap
+- * insns, even for trap codes that indicate arithmetic failures.
+- * Weird ...)
+- * But should we continue the brokenness??? --macro
+- */
+- switch (tcode) {
+- case BRK_OVERFLOW:
+- case BRK_DIVZERO:
+- die_if_kernel("Trap instruction in kernel code", regs);
+- if (tcode == BRK_DIVZERO)
+- info.si_code = FPE_INTDIV;
+- else
+- info.si_code = FPE_INTOVF;
+- info.si_signo = SIGFPE;
+- info.si_errno = 0;
+- info.si_addr = (void __user *) regs->cp0_epc;
+- force_sig_info(SIGFPE, &info, current);
+- break;
+- case BRK_BUG:
+- die("Kernel bug detected", regs);
+- break;
+- default:
+- die_if_kernel("Trap instruction in kernel code", regs);
+- force_sig(SIGTRAP, current);
+- }
++ do_trap_or_bp(regs, tcode, "Trap");
+ return;
- rtc at 32 {
- device_type = "rtc";
- compatible = "ricoh,rs5c372a";
-- reg = <32>;
-+ reg = <0x32>;
- };
- };
+ out_sigsegv:
+@@ -985,6 +988,21 @@ asmlinkage void do_reserved(struct pt_regs *regs)
+ (regs->cp0_cause & 0x7f) >> 2);
+ }
-@@ -83,9 +86,9 @@ XXXX add flash parts, rtc, ??
- cell-index = <0>;
- device_type = "serial";
- compatible = "ns16550";
-- reg = <80004500 8>;
-- clock-frequency = <7c044a8>;
-- current-speed = <2580>;
-+ reg = <0x80004500 0x8>;
-+ clock-frequency = <130041000>;
-+ current-speed = <9600>;
- interrupts = <9 0>;
- interrupt-parent = <&mpic>;
- };
-@@ -94,10 +97,10 @@ XXXX add flash parts, rtc, ??
- cell-index = <1>;
- device_type = "serial";
- compatible = "ns16550";
-- reg = <80004600 8>;
-- clock-frequency = <7c044a8>;
-- current-speed = <e100>;
-- interrupts = <a 0>;
-+ reg = <0x80004600 0x8>;
-+ clock-frequency = <130041000>;
-+ current-speed = <57600>;
-+ interrupts = <10 0>;
- interrupt-parent = <&mpic>;
- };
++static int __initdata l1parity = 1;
++static int __init nol1parity(char *s)
++{
++ l1parity = 0;
++ return 1;
++}
++__setup("nol1par", nol1parity);
++static int __initdata l2parity = 1;
++static int __init nol2parity(char *s)
++{
++ l2parity = 0;
++ return 1;
++}
++__setup("nol2par", nol2parity);
++
+ /*
+ * Some MIPS CPUs can enable/disable for cache parity detection, but do
+ * it different ways.
+@@ -994,6 +1012,62 @@ static inline void parity_protection_init(void)
+ switch (current_cpu_type()) {
+ case CPU_24K:
+ case CPU_34K:
++ case CPU_74K:
++ case CPU_1004K:
++ {
++#define ERRCTL_PE 0x80000000
++#define ERRCTL_L2P 0x00800000
++ unsigned long errctl;
++ unsigned int l1parity_present, l2parity_present;
++
++ errctl = read_c0_ecc();
++ errctl &= ~(ERRCTL_PE|ERRCTL_L2P);
++
++ /* probe L1 parity support */
++ write_c0_ecc(errctl | ERRCTL_PE);
++ back_to_back_c0_hazard();
++ l1parity_present = (read_c0_ecc() & ERRCTL_PE);
++
++ /* probe L2 parity support */
++ write_c0_ecc(errctl|ERRCTL_L2P);
++ back_to_back_c0_hazard();
++ l2parity_present = (read_c0_ecc() & ERRCTL_L2P);
++
++ if (l1parity_present && l2parity_present) {
++ if (l1parity)
++ errctl |= ERRCTL_PE;
++ if (l1parity ^ l2parity)
++ errctl |= ERRCTL_L2P;
++ } else if (l1parity_present) {
++ if (l1parity)
++ errctl |= ERRCTL_PE;
++ } else if (l2parity_present) {
++ if (l2parity)
++ errctl |= ERRCTL_L2P;
++ } else {
++ /* No parity available */
++ }
++
++ printk(KERN_INFO "Writing ErrCtl register=%08lx\n", errctl);
++
++ write_c0_ecc(errctl);
++ back_to_back_c0_hazard();
++ errctl = read_c0_ecc();
++ printk(KERN_INFO "Readback ErrCtl register=%08lx\n", errctl);
++
++ if (l1parity_present)
++ printk(KERN_INFO "Cache parity protection %sabled\n",
++ (errctl & ERRCTL_PE) ? "en" : "dis");
++
++ if (l2parity_present) {
++ if (l1parity_present && l1parity)
++ errctl ^= ERRCTL_L2P;
++ printk(KERN_INFO "L2 cache parity protection %sabled\n",
++ (errctl & ERRCTL_L2P) ? "en" : "dis");
++ }
++ }
++ break;
++
+ case CPU_5KC:
+ write_c0_ecc(0x80000000);
+ back_to_back_c0_hazard();
+@@ -1306,6 +1380,17 @@ int cp0_compare_irq;
+ int cp0_perfcount_irq;
+ EXPORT_SYMBOL_GPL(cp0_perfcount_irq);
-@@ -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>;
- };
++static int __cpuinitdata noulri;
++
++static int __init ulri_disable(char *s)
++{
++ pr_info("Disabling ulri\n");
++ noulri = 1;
++
++ return 1;
++}
++__setup("noulri", ulri_disable);
++
+ void __cpuinit per_cpu_trap_init(void)
+ {
+ unsigned int cpu = smp_processor_id();
+@@ -1342,16 +1427,14 @@ void __cpuinit per_cpu_trap_init(void)
+ change_c0_status(ST0_CU|ST0_MX|ST0_RE|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
+ status_set);
+
+-#ifdef CONFIG_CPU_MIPSR2
+ if (cpu_has_mips_r2) {
+ unsigned int enable = 0x0000000f;
+
+- if (cpu_has_userlocal)
++ if (!noulri && cpu_has_userlocal)
+ enable |= (1 << 29);
+
+ write_c0_hwrena(enable);
+ }
+-#endif
- pci0: pci at fec00000 {
-@@ -116,29 +119,29 @@ XXXX add flash parts, rtc, ??
- #interrupt-cells = <1>;
- device_type = "pci";
- compatible = "mpc10x-pci";
-- reg = <fec00000 400000>;
-- ranges = <01000000 0 0 fe000000 0 00c00000
-- 02000000 0 80000000 80000000 0 70000000>;
-- bus-range = <0 ff>;
-- clock-frequency = <7f28155>;
-+ reg = <0xfec00000 0x400000>;
-+ ranges = <0x1000000 0x0 0x0 0xfe000000 0x0 0xc00000
-+ 0x2000000 0x0 0x80000000 0x80000000 0x0 0x70000000>;
-+ bus-range = <0 255>;
-+ clock-frequency = <133333333>;
- interrupt-parent = <&mpic>;
-- interrupt-map-mask = <f800 0 0 7>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
- /* IDSEL 11 - IRQ0 ETH */
-- 5800 0 0 1 &mpic 0 1
-- 5800 0 0 2 &mpic 1 1
-- 5800 0 0 3 &mpic 2 1
-- 5800 0 0 4 &mpic 3 1
-+ 0x5800 0x0 0x0 0x1 &mpic 0x0 0x1
-+ 0x5800 0x0 0x0 0x2 &mpic 0x1 0x1
-+ 0x5800 0x0 0x0 0x3 &mpic 0x2 0x1
-+ 0x5800 0x0 0x0 0x4 &mpic 0x3 0x1
- /* IDSEL 12 - IRQ1 IDE0 */
-- 6000 0 0 1 &mpic 1 1
-- 6000 0 0 2 &mpic 2 1
-- 6000 0 0 3 &mpic 3 1
-- 6000 0 0 4 &mpic 0 1
-+ 0x6000 0x0 0x0 0x1 &mpic 0x1 0x1
-+ 0x6000 0x0 0x0 0x2 &mpic 0x2 0x1
-+ 0x6000 0x0 0x0 0x3 &mpic 0x3 0x1
-+ 0x6000 0x0 0x0 0x4 &mpic 0x0 0x1
- /* IDSEL 14 - IRQ3 USB2.0 */
-- 7000 0 0 1 &mpic 3 1
-- 7000 0 0 2 &mpic 3 1
-- 7000 0 0 3 &mpic 3 1
-- 7000 0 0 4 &mpic 3 1
-+ 0x7000 0x0 0x0 0x1 &mpic 0x3 0x1
-+ 0x7000 0x0 0x0 0x2 &mpic 0x3 0x1
-+ 0x7000 0x0 0x0 0x3 &mpic 0x3 0x1
-+ 0x7000 0x0 0x0 0x4 &mpic 0x3 0x1
- >;
- };
- };
-diff --git a/arch/powerpc/boot/dts/makalu.dts b/arch/powerpc/boot/dts/makalu.dts
-index 710c011..84cc5e7 100644
---- a/arch/powerpc/boot/dts/makalu.dts
-+++ b/arch/powerpc/boot/dts/makalu.dts
-@@ -219,7 +219,7 @@
- mal-tx-channel = <0>;
- mal-rx-channel = <0>;
- cell-index = <0>;
-- max-frame-size = <5dc>;
-+ max-frame-size = <2328>;
- rx-fifo-size = <1000>;
- tx-fifo-size = <800>;
- phy-mode = "rgmii";
-@@ -247,7 +247,7 @@
- mal-tx-channel = <1>;
- mal-rx-channel = <1>;
- cell-index = <1>;
-- max-frame-size = <5dc>;
-+ max-frame-size = <2328>;
- rx-fifo-size = <1000>;
- tx-fifo-size = <800>;
- phy-mode = "rgmii";
-diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
-index 8fb5423..4936349 100644
---- a/arch/powerpc/boot/dts/mpc7448hpc2.dts
-+++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts
-@@ -1,7 +1,7 @@
- /*
- * MPC7448HPC2 (Taiga) board Device Tree Source
- *
-- * Copyright 2006 Freescale Semiconductor Inc.
-+ * Copyright 2006, 2008 Freescale Semiconductor Inc.
- * 2006 Roy Zang <Roy Zang at freescale.com>.
- *
- * This program is free software; you can redistribute it and/or modify it
-@@ -10,6 +10,7 @@
- * option) any later version.
- */
+ #ifdef CONFIG_MIPS_MT_SMTC
+ if (!secondaryTC) {
+diff --git a/arch/mips/lib/iomap-pci.c b/arch/mips/lib/iomap-pci.c
+index c11b249..2ab899c 100644
+--- a/arch/mips/lib/iomap-pci.c
++++ b/arch/mips/lib/iomap-pci.c
+@@ -45,8 +45,8 @@ static void __iomem *ioport_map_pci(struct pci_dev *dev,
+ */
+ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+ {
+- unsigned long start = pci_resource_start(dev, bar);
+- unsigned long len = pci_resource_len(dev, bar);
++ resource_size_t start = pci_resource_start(dev, bar);
++ resource_size_t len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (!len || !start)
+diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h
+index 8977eb5..7627865 100644
+--- a/arch/mips/math-emu/ieee754dp.h
++++ b/arch/mips/math-emu/ieee754dp.h
+@@ -46,7 +46,7 @@
+ #define DPDNORMX DPDNORMx(xm, xe)
+ #define DPDNORMY DPDNORMx(ym, ye)
-+/dts-v1/;
+-static __inline ieee754dp builddp(int s, int bx, u64 m)
++static inline ieee754dp builddp(int s, int bx, u64 m)
+ {
+ ieee754dp r;
- / {
- model = "mpc7448hpc2";
-@@ -23,11 +24,11 @@
-
- PowerPC,7448 at 0 {
- device_type = "cpu";
-- reg = <0>;
-- d-cache-line-size = <20>; // 32 bytes
-- i-cache-line-size = <20>; // 32 bytes
-- d-cache-size = <8000>; // L1, 32K bytes
-- i-cache-size = <8000>; // L1, 32K bytes
-+ reg = <0x0>;
-+ d-cache-line-size = <32>; // 32 bytes
-+ i-cache-line-size = <32>; // 32 bytes
-+ d-cache-size = <0x8000>; // L1, 32K bytes
-+ i-cache-size = <0x8000>; // L1, 32K bytes
- timebase-frequency = <0>; // 33 MHz, from uboot
- clock-frequency = <0>; // From U-Boot
- bus-frequency = <0>; // From U-Boot
-@@ -36,7 +37,7 @@
+diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h
+index 9917c1e..d9e3586 100644
+--- a/arch/mips/math-emu/ieee754sp.h
++++ b/arch/mips/math-emu/ieee754sp.h
+@@ -51,7 +51,7 @@
+ #define SPDNORMX SPDNORMx(xm, xe)
+ #define SPDNORMY SPDNORMx(ym, ye)
- memory {
- device_type = "memory";
-- reg = <00000000 20000000 // DDR2 512M at 0
-+ reg = <0x0 0x20000000 // DDR2 512M at 0
- >;
- };
+-static __inline ieee754sp buildsp(int s, int bx, unsigned m)
++static inline ieee754sp buildsp(int s, int bx, unsigned m)
+ {
+ ieee754sp r;
-@@ -44,14 +45,14 @@
- #address-cells = <1>;
- #size-cells = <1>;
- device_type = "tsi-bridge";
-- ranges = <00000000 c0000000 00010000>;
-- reg = <c0000000 00010000>;
-+ ranges = <0x0 0xc0000000 0x10000>;
-+ reg = <0xc0000000 0x10000>;
- bus-frequency = <0>;
+diff --git a/arch/mips/mips-boards/generic/Makefile b/arch/mips/mips-boards/generic/Makefile
+index b31d8df..f7f87fc 100644
+--- a/arch/mips/mips-boards/generic/Makefile
++++ b/arch/mips/mips-boards/generic/Makefile
+@@ -20,6 +20,7 @@
- i2c at 7000 {
- interrupt-parent = <&mpic>;
-- interrupts = <E 0>;
-- reg = <7000 400>;
-+ interrupts = <14 0>;
-+ reg = <0x7000 0x400>;
- device_type = "i2c";
- compatible = "tsi108-i2c";
- };
-@@ -59,20 +60,20 @@
- MDIO: mdio at 6000 {
- device_type = "mdio";
- compatible = "tsi108-mdio";
-- reg = <6000 50>;
-+ reg = <0x6000 0x50>;
- #address-cells = <1>;
- #size-cells = <0>;
+ obj-y := reset.o display.o init.o memory.o \
+ cmdline.o time.o
++obj-y += amon.o
- phy8: ethernet-phy at 8 {
- interrupt-parent = <&mpic>;
- interrupts = <2 1>;
-- reg = <8>;
-+ reg = <0x8>;
- };
+ obj-$(CONFIG_EARLY_PRINTK) += console.o
+ obj-$(CONFIG_PCI) += pci.o
+diff --git a/arch/mips/mips-boards/generic/amon.c b/arch/mips/mips-boards/generic/amon.c
+new file mode 100644
+index 0000000..b7633fd
+--- /dev/null
++++ b/arch/mips/mips-boards/generic/amon.c
+@@ -0,0 +1,80 @@
++/*
++ * Copyright (C) 2007 MIPS Technologies, Inc.
++ * All rights reserved.
++
++ * This program is free software; you can distribute 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 it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ *
++ * You 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.
++ *
++ * Arbitrary Monitor interface
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/smp.h>
++
++#include <asm-mips/addrspace.h>
++#include <asm-mips/mips-boards/launch.h>
++#include <asm-mips/mipsmtregs.h>
++
++int amon_cpu_avail(int cpu)
++{
++ struct cpulaunch *launch = (struct cpulaunch *)KSEG0ADDR(CPULAUNCH);
++
++ if (cpu < 0 || cpu >= NCPULAUNCH) {
++ pr_debug("avail: cpu%d is out of range\n", cpu);
++ return 0;
++ }
++
++ launch += cpu;
++ if (!(launch->flags & LAUNCH_FREADY)) {
++ pr_debug("avail: cpu%d is not ready\n", cpu);
++ return 0;
++ }
++ if (launch->flags & (LAUNCH_FGO|LAUNCH_FGONE)) {
++ pr_debug("avail: too late.. cpu%d is already gone\n", cpu);
++ return 0;
++ }
++
++ return 1;
++}
++
++void amon_cpu_start(int cpu,
++ unsigned long pc, unsigned long sp,
++ unsigned long gp, unsigned long a0)
++{
++ volatile struct cpulaunch *launch =
++ (struct cpulaunch *)KSEG0ADDR(CPULAUNCH);
++
++ if (!amon_cpu_avail(cpu))
++ return;
++ if (cpu == smp_processor_id()) {
++ pr_debug("launch: I am cpu%d!\n", cpu);
++ return;
++ }
++ launch += cpu;
++
++ pr_debug("launch: starting cpu%d\n", cpu);
++
++ launch->pc = pc;
++ launch->gp = gp;
++ launch->sp = sp;
++ launch->a0 = a0;
++
++ /* Make sure target sees parameters before the go bit */
++ smp_mb();
++
++ launch->flags |= LAUNCH_FGO;
++ while ((launch->flags & LAUNCH_FGONE) == 0)
++ ;
++ pr_debug("launch: cpu%d gone!\n", cpu);
++}
+diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c
+index 1695dca..83b9dc7 100644
+--- a/arch/mips/mips-boards/generic/init.c
++++ b/arch/mips/mips-boards/generic/init.c
+@@ -226,7 +226,7 @@ void __init kgdb_config(void)
+ }
+ #endif
- phy9: ethernet-phy at 9 {
- interrupt-parent = <&mpic>;
- interrupts = <2 1>;
-- reg = <9>;
-+ reg = <0x9>;
- };
+-void __init mips_nmi_setup(void)
++static void __init mips_nmi_setup(void)
+ {
+ void *base;
+ extern char except_vec_nmi;
+@@ -238,7 +238,7 @@ void __init mips_nmi_setup(void)
+ flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
+ }
- };
-@@ -82,9 +83,9 @@
- #size-cells = <0>;
- device_type = "network";
- compatible = "tsi108-ethernet";
-- reg = <6000 200>;
-+ reg = <0x6000 0x200>;
- address = [ 00 06 D2 00 00 01 ];
-- interrupts = <10 2>;
-+ interrupts = <16 2>;
- interrupt-parent = <&mpic>;
- mdio-handle = <&MDIO>;
- phy-handle = <&phy8>;
-@@ -96,9 +97,9 @@
- #size-cells = <0>;
- device_type = "network";
- compatible = "tsi108-ethernet";
-- reg = <6400 200>;
-+ reg = <0x6400 0x200>;
- address = [ 00 06 D2 00 00 02 ];
-- interrupts = <11 2>;
-+ interrupts = <17 2>;
- interrupt-parent = <&mpic>;
- mdio-handle = <&MDIO>;
- phy-handle = <&phy9>;
-@@ -107,18 +108,18 @@
- serial at 7808 {
- device_type = "serial";
- compatible = "ns16550";
-- reg = <7808 200>;
-- clock-frequency = <3f6b5a00>;
-- interrupts = <c 0>;
-+ reg = <0x7808 0x200>;
-+ clock-frequency = <1064000000>;
-+ interrupts = <12 0>;
- interrupt-parent = <&mpic>;
- };
+-void __init mips_ejtag_setup(void)
++static void __init mips_ejtag_setup(void)
+ {
+ void *base;
+ extern char except_vec_ejtag_debug;
+@@ -295,15 +295,21 @@ void __init prom_init(void)
+ break;
+ case MIPS_REVISION_CORID_CORE_MSC:
+ case MIPS_REVISION_CORID_CORE_FPGA2:
+- case MIPS_REVISION_CORID_CORE_FPGA3:
+- case MIPS_REVISION_CORID_CORE_FPGA4:
+ case MIPS_REVISION_CORID_CORE_24K:
+- case MIPS_REVISION_CORID_CORE_EMUL_MSC:
++ /*
++ * SOCit/ROCit support is essentially identical
++ * but make an attempt to distinguish them
++ */
+ mips_revision_sconid = MIPS_REVISION_SCON_SOCIT;
+ break;
++ case MIPS_REVISION_CORID_CORE_FPGA3:
++ case MIPS_REVISION_CORID_CORE_FPGA4:
++ case MIPS_REVISION_CORID_CORE_FPGA5:
++ case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+ default:
+- mips_display_message("CC Error");
+- while (1); /* We die here... */
++ /* See above */
++ mips_revision_sconid = MIPS_REVISION_SCON_ROCIT;
++ break;
+ }
+ }
- serial at 7c08 {
- device_type = "serial";
- compatible = "ns16550";
-- reg = <7c08 200>;
-- clock-frequency = <3f6b5a00>;
-- interrupts = <d 0>;
-+ reg = <0x7c08 0x200>;
-+ clock-frequency = <1064000000>;
-+ interrupts = <13 0>;
- interrupt-parent = <&mpic>;
- };
+@@ -418,6 +424,9 @@ void __init prom_init(void)
+ #ifdef CONFIG_SERIAL_8250_CONSOLE
+ console_config();
+ #endif
++#ifdef CONFIG_MIPS_CMP
++ register_smp_ops(&cmp_smp_ops);
++#endif
+ #ifdef CONFIG_MIPS_MT_SMP
+ register_smp_ops(&vsmp_smp_ops);
+ #endif
+diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c
+index dc272c1..5e443bb 100644
+--- a/arch/mips/mips-boards/generic/memory.c
++++ b/arch/mips/mips-boards/generic/memory.c
+@@ -37,7 +37,7 @@ enum yamon_memtypes {
+ yamon_prom,
+ yamon_free,
+ };
+-struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
++static struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
-@@ -127,7 +128,7 @@
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <2>;
-- reg = <7400 400>;
-+ reg = <0x7400 0x400>;
- compatible = "chrp,open-pic";
- device_type = "open-pic";
- big-endian;
-@@ -138,39 +139,39 @@
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- reg = <1000 1000>;
-+ reg = <0x1000 0x1000>;
- bus-range = <0 0>;
-- ranges = <02000000 0 e0000000 e0000000 0 1A000000
-- 01000000 0 00000000 fa000000 0 00010000>;
-- clock-frequency = <7f28154>;
-+ ranges = <0x2000000 0x0 0xe0000000 0xe0000000 0x0 0x1a000000
-+ 0x1000000 0x0 0x0 0xfa000000 0x0 0x10000>;
-+ clock-frequency = <133333332>;
- interrupt-parent = <&mpic>;
-- interrupts = <17 2>;
-- interrupt-map-mask = <f800 0 0 7>;
-+ interrupts = <23 2>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
+ #ifdef DEBUG
+ static char *mtypes[3] = {
+@@ -50,7 +50,7 @@ static char *mtypes[3] = {
+ /* determined physical memory size, not overridden by command line args */
+ unsigned long physical_memsize = 0L;
- /* 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
+-struct prom_pmemblock * __init prom_getmdesc(void)
++static struct prom_pmemblock * __init prom_getmdesc(void)
+ {
+ char *memsize_str;
+ unsigned int memsize;
+diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
+index b50e0fc..008fd82 100644
+--- a/arch/mips/mips-boards/generic/time.c
++++ b/arch/mips/mips-boards/generic/time.c
+@@ -55,16 +55,36 @@
+ unsigned long cpu_khz;
- /* 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
+ static int mips_cpu_timer_irq;
++static int mips_cpu_perf_irq;
+ extern int cp0_perfcount_irq;
- /* 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
++DEFINE_PER_CPU(unsigned int, tickcount);
++#define tickcount_this_cpu __get_cpu_var(tickcount)
++static unsigned long ledbitmask;
++
+ static void mips_timer_dispatch(void)
+ {
++#if defined(CONFIG_MIPS_MALTA) || defined(CONFIG_MIPS_ATLAS)
++ /*
++ * Yes, this is very tacky, won't work as expected with SMTC and
++ * dyntick will break it,
++ * but it gives me a nice warm feeling during debug
++ */
++#define LEDBAR 0xbf000408
++ if (tickcount_this_cpu++ >= HZ) {
++ tickcount_this_cpu = 0;
++ change_bit(smp_processor_id(), &ledbitmask);
++ smp_wmb(); /* Make sure every one else sees the change */
++ /* This will pick up any recent changes made by other CPU's */
++ *(unsigned int *)LEDBAR = ledbitmask;
++ }
++#endif
+ do_IRQ(mips_cpu_timer_irq);
+ }
- /* 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
- >;
+ static void mips_perf_dispatch(void)
+ {
+- do_IRQ(cp0_perfcount_irq);
++ do_IRQ(mips_cpu_perf_irq);
+ }
- RT0: router at 1180 {
-@@ -180,7 +181,7 @@
- #address-cells = <0>;
- #interrupt-cells = <2>;
- big-endian;
-- interrupts = <17 2>;
-+ interrupts = <23 2>;
- interrupt-parent = <&mpic>;
- };
- };
-diff --git a/arch/powerpc/boot/dts/mpc8272ads.dts b/arch/powerpc/boot/dts/mpc8272ads.dts
-index 7285ca1..46e2da3 100644
---- a/arch/powerpc/boot/dts/mpc8272ads.dts
-+++ b/arch/powerpc/boot/dts/mpc8272ads.dts
-@@ -1,7 +1,7 @@
/*
- * MPC8272 ADS Device Tree Source
- *
-- * Copyright 2005 Freescale Semiconductor Inc.
-+ * Copyright 2005,2008 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
-@@ -9,6 +9,8 @@
- * option) any later version.
- */
+@@ -127,21 +147,20 @@ unsigned long read_persistent_clock(void)
+ return mc146818_get_cmos_time();
+ }
-+/dts-v1/;
-+
- / {
- model = "MPC8272ADS";
- compatible = "fsl,mpc8272ads";
-@@ -21,11 +23,11 @@
+-void __init plat_perf_setup(void)
++static void __init plat_perf_setup(void)
+ {
+- cp0_perfcount_irq = -1;
+-
+ #ifdef MSC01E_INT_BASE
+ if (cpu_has_veic) {
+ set_vi_handler(MSC01E_INT_PERFCTR, mips_perf_dispatch);
+- cp0_perfcount_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR;
++ mips_cpu_perf_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR;
+ } else
+ #endif
+ if (cp0_perfcount_irq >= 0) {
+ if (cpu_has_vint)
+ set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch);
++ mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
+ #ifdef CONFIG_SMP
+- set_irq_handler(cp0_perfcount_irq, handle_percpu_irq);
++ set_irq_handler(mips_cpu_perf_irq, handle_percpu_irq);
+ #endif
+ }
+ }
+diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile
+index 931ca46..8dc6e2a 100644
+--- a/arch/mips/mips-boards/malta/Makefile
++++ b/arch/mips/mips-boards/malta/Makefile
+@@ -22,6 +22,7 @@
+ obj-y := malta_int.o malta_platform.o malta_setup.o
- PowerPC,8272 at 0 {
- device_type = "cpu";
-- reg = <0>;
-- d-cache-line-size = <d#32>;
-- i-cache-line-size = <d#32>;
-- d-cache-size = <d#16384>;
-- i-cache-size = <d#16384>;
-+ reg = <0x0>;
-+ d-cache-line-size = <32>;
-+ i-cache-line-size = <32>;
-+ d-cache-size = <16384>;
-+ i-cache-size = <16384>;
- timebase-frequency = <0>;
- bus-frequency = <0>;
- clock-frequency = <0>;
-@@ -34,7 +36,7 @@
+ obj-$(CONFIG_MTD) += malta_mtd.o
++# FIXME FIXME FIXME
+ obj-$(CONFIG_MIPS_MT_SMTC) += malta_smtc.o
+
+ EXTRA_CFLAGS += -Werror
+diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
+index dbe60eb..8c49510 100644
+--- a/arch/mips/mips-boards/malta/malta_int.c
++++ b/arch/mips/mips-boards/malta/malta_int.c
+@@ -31,6 +31,7 @@
+ #include <linux/kernel.h>
+ #include <linux/random.h>
- memory {
- device_type = "memory";
-- reg = <0 0>;
-+ reg = <0x0 0x0>;
- };
++#include <asm/traps.h>
+ #include <asm/i8259.h>
+ #include <asm/irq_cpu.h>
+ #include <asm/irq_regs.h>
+@@ -41,6 +42,14 @@
+ #include <asm/mips-boards/generic.h>
+ #include <asm/mips-boards/msc01_pci.h>
+ #include <asm/msc01_ic.h>
++#include <asm/gic.h>
++#include <asm/gcmpregs.h>
++
++int gcmp_present = -1;
++int gic_present;
++static unsigned long _msc01_biu_base;
++static unsigned long _gcmp_base;
++static unsigned int ipi_map[NR_CPUS];
- localbus at f0010100 {
-@@ -42,21 +44,21 @@
- "fsl,pq2-localbus";
- #address-cells = <2>;
- #size-cells = <1>;
-- reg = <f0010100 40>;
-+ reg = <0xf0010100 0x40>;
+ static DEFINE_SPINLOCK(mips_irq_lock);
-- 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>;
+@@ -121,6 +130,17 @@ static void malta_hw0_irqdispatch(void)
+ do_IRQ(MALTA_INT_BASE + irq);
+ }
- flash at 0,0 {
- compatible = "jedec-flash";
-- reg = <0 0 2000000>;
-+ reg = <0x0 0x0 0x2000000>;
- bank-width = <4>;
- device-width = <1>;
- };
++static void malta_ipi_irqdispatch(void)
++{
++ int irq;
++
++ irq = gic_get_int();
++ if (irq < 0)
++ return; /* interrupt has already been cleared */
++
++ do_IRQ(MIPS_GIC_IRQ_BASE + irq);
++}
++
+ static void corehi_irqdispatch(void)
+ {
+ unsigned int intedge, intsteer, pcicmd, pcibadaddr;
+@@ -257,12 +277,61 @@ asmlinkage void plat_irq_dispatch(void)
- board-control at 1,0 {
-- reg = <1 0 20>;
-+ reg = <0x1 0x0 0x20>;
- compatible = "fsl,mpc8272ads-bcsr";
- };
+ if (irq == MIPSCPU_INT_I8259A)
+ malta_hw0_irqdispatch();
++ else if (gic_present && ((1 << irq) & ipi_map[smp_processor_id()]))
++ malta_ipi_irqdispatch();
+ else if (irq >= 0)
+ do_IRQ(MIPS_CPU_IRQ_BASE + irq);
+ else
+ spurious_interrupt();
+ }
-@@ -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>;
- };
- };
++#ifdef CONFIG_MIPS_MT_SMP
++
++
++#define GIC_MIPS_CPU_IPI_RESCHED_IRQ 3
++#define GIC_MIPS_CPU_IPI_CALL_IRQ 4
++
++#define MIPS_CPU_IPI_RESCHED_IRQ 0 /* SW int 0 for resched */
++#define C_RESCHED C_SW0
++#define MIPS_CPU_IPI_CALL_IRQ 1 /* SW int 1 for resched */
++#define C_CALL C_SW1
++static int cpu_ipi_resched_irq, cpu_ipi_call_irq;
++
++static void ipi_resched_dispatch(void)
++{
++ do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
++}
++
++static void ipi_call_dispatch(void)
++{
++ do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
++}
++
++static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
++{
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
++{
++ smp_call_function_interrupt();
++
++ return IRQ_HANDLED;
++}
++
++static struct irqaction irq_resched = {
++ .handler = ipi_resched_interrupt,
++ .flags = IRQF_DISABLED|IRQF_PERCPU,
++ .name = "IPI_resched"
++};
++
++static struct irqaction irq_call = {
++ .handler = ipi_call_interrupt,
++ .flags = IRQF_DISABLED|IRQF_PERCPU,
++ .name = "IPI_call"
++};
++#endif /* CONFIG_MIPS_MT_SMP */
++
+ static struct irqaction i8259irq = {
+ .handler = no_action,
+ .name = "XT-PIC cascade"
+@@ -273,13 +342,13 @@ static struct irqaction corehi_irqaction = {
+ .name = "CoreHi"
+ };
+
+-msc_irqmap_t __initdata msc_irqmap[] = {
++static msc_irqmap_t __initdata msc_irqmap[] = {
+ {MSC01C_INT_TMR, MSC01_IRQ_EDGE, 0},
+ {MSC01C_INT_PCI, MSC01_IRQ_LEVEL, 0},
+ };
+-int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap);
++static int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap);
+
+-msc_irqmap_t __initdata msc_eicirqmap[] = {
++static msc_irqmap_t __initdata msc_eicirqmap[] = {
+ {MSC01E_INT_SW0, MSC01_IRQ_LEVEL, 0},
+ {MSC01E_INT_SW1, MSC01_IRQ_LEVEL, 0},
+ {MSC01E_INT_I8259A, MSC01_IRQ_LEVEL, 0},
+@@ -291,15 +360,90 @@ msc_irqmap_t __initdata msc_eicirqmap[] = {
+ {MSC01E_INT_PERFCTR, MSC01_IRQ_LEVEL, 0},
+ {MSC01E_INT_CPUCTR, MSC01_IRQ_LEVEL, 0}
+ };
+-int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
++
++static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
++
++/*
++ * This GIC specific tabular array defines the association between External
++ * Interrupts and CPUs/Core Interrupts. The nature of the External
++ * Interrupts is also defined here - polarity/trigger.
++ */
++static struct gic_intr_map gic_intr_map[] = {
++ { GIC_EXT_INTR(0), X, X, X, X, 0 },
++ { GIC_EXT_INTR(1), X, X, X, X, 0 },
++ { GIC_EXT_INTR(2), X, X, X, X, 0 },
++ { GIC_EXT_INTR(3), 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
++ { GIC_EXT_INTR(4), 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
++ { GIC_EXT_INTR(5), 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
++ { GIC_EXT_INTR(6), 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
++ { GIC_EXT_INTR(7), 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
++ { GIC_EXT_INTR(8), 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
++ { GIC_EXT_INTR(9), 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
++ { GIC_EXT_INTR(10), X, X, X, X, 0 },
++ { GIC_EXT_INTR(11), X, X, X, X, 0 },
++ { GIC_EXT_INTR(12), 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
++ { GIC_EXT_INTR(13), 0, GIC_MAP_TO_NMI_MSK, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
++ { GIC_EXT_INTR(14), 0, GIC_MAP_TO_NMI_MSK, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
++ { GIC_EXT_INTR(15), X, X, X, X, 0 },
++ { GIC_EXT_INTR(16), 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 },
++ { GIC_EXT_INTR(17), 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 },
++ { GIC_EXT_INTR(18), 1, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 },
++ { GIC_EXT_INTR(19), 1, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 },
++ { GIC_EXT_INTR(20), 2, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 },
++ { GIC_EXT_INTR(21), 2, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 },
++ { GIC_EXT_INTR(22), 3, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 },
++ { GIC_EXT_INTR(23), 3, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 },
++};
++
++/*
++ * GCMP needs to be detected before any SMP initialisation
++ */
++int __init gcmp_probe(unsigned long addr, unsigned long size)
++{
++ if (gcmp_present >= 0)
++ return gcmp_present;
++
++ _gcmp_base = (unsigned long) ioremap_nocache(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ);
++ _msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE, MSC01_BIU_ADDRSPACE_SZ);
++ gcmp_present = (GCMPGCB(GCMPB) & GCMP_GCB_GCMPB_GCMPBASE_MSK) == GCMP_BASE_ADDR;
++
++ if (gcmp_present)
++ printk(KERN_DEBUG "GCMP present\n");
++ return gcmp_present;
++}
++
++void __init fill_ipi_map(void)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(gic_intr_map); i++) {
++ if (gic_intr_map[i].ipiflag && (gic_intr_map[i].cpunum != X))
++ ipi_map[gic_intr_map[i].cpunum] |=
++ (1 << (gic_intr_map[i].pin + 2));
++ }
++}
+ void __init arch_init_irq(void)
+ {
++ int gic_present, gcmp_present;
++
+ init_i8259_irqs();
- pci at f0010800 {
- device_type = "pci";
-- reg = <f0010800 10c f00101ac 8 f00101c4 8>;
-+ reg = <0xf0010800 0x10c 0xf00101ac 0x8 0xf00101c4 0x8>;
- compatible = "fsl,mpc8272-pci", "fsl,pq2-pci";
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- clock-frequency = <d#66666666>;
-- interrupt-map-mask = <f800 0 0 7>;
-+ clock-frequency = <66666666>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
- /* IDSEL 0x16 */
-- b000 0 0 1 &PCI_PIC 0
-- b000 0 0 2 &PCI_PIC 1
-- b000 0 0 3 &PCI_PIC 2
-- b000 0 0 4 &PCI_PIC 3
-+ 0xb000 0x0 0x0 0x1 &PCI_PIC 0
-+ 0xb000 0x0 0x0 0x2 &PCI_PIC 1
-+ 0xb000 0x0 0x0 0x3 &PCI_PIC 2
-+ 0xb000 0x0 0x0 0x4 &PCI_PIC 3
-
- /* IDSEL 0x17 */
-- b800 0 0 1 &PCI_PIC 4
-- b800 0 0 2 &PCI_PIC 5
-- b800 0 0 3 &PCI_PIC 6
-- b800 0 0 4 &PCI_PIC 7
-+ 0xb800 0x0 0x0 0x1 &PCI_PIC 4
-+ 0xb800 0x0 0x0 0x2 &PCI_PIC 5
-+ 0xb800 0x0 0x0 0x3 &PCI_PIC 6
-+ 0xb800 0x0 0x0 0x4 &PCI_PIC 7
-
- /* IDSEL 0x18 */
-- c000 0 0 1 &PCI_PIC 8
-- c000 0 0 2 &PCI_PIC 9
-- c000 0 0 3 &PCI_PIC a
-- c000 0 0 4 &PCI_PIC b>;
-+ 0xc000 0x0 0x0 0x1 &PCI_PIC 8
-+ 0xc000 0x0 0x0 0x2 &PCI_PIC 9
-+ 0xc000 0x0 0x0 0x3 &PCI_PIC 10
-+ 0xc000 0x0 0x0 0x4 &PCI_PIC 11>;
+ if (!cpu_has_veic)
+ mips_cpu_irq_init();
- 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>;
- };
++ gcmp_present = gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ);
++ if (gcmp_present) {
++ GCMPGCB(GICBA) = GIC_BASE_ADDR | GCMP_GCB_GICBA_EN_MSK;
++ gic_present = 1;
++ } else {
++ _msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE, MSC01_BIU_ADDRSPACE_SZ);
++ gic_present = (REG(_msc01_biu_base, MSC01_SC_CFG) &
++ MSC01_SC_CFG_GICPRES_MSK) >> MSC01_SC_CFG_GICPRES_SHF;
++ }
++ if (gic_present)
++ printk(KERN_DEBUG "GIC present\n");
++
+ switch (mips_revision_sconid) {
+ case MIPS_REVISION_SCON_SOCIT:
+ case MIPS_REVISION_SCON_ROCIT:
+@@ -360,4 +504,206 @@ void __init arch_init_irq(void)
+ setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI,
+ &corehi_irqaction);
+ }
++
++#if defined(CONFIG_MIPS_MT_SMP)
++ if (gic_present) {
++ /* FIXME */
++ int i;
++ struct {
++ unsigned int resched;
++ unsigned int call;
++ } ipiirq[] = {
++ {
++ .resched = GIC_IPI_EXT_INTR_RESCHED_VPE0,
++ .call = GIC_IPI_EXT_INTR_CALLFNC_VPE0},
++ {
++ .resched = GIC_IPI_EXT_INTR_RESCHED_VPE1,
++ .call = GIC_IPI_EXT_INTR_CALLFNC_VPE1
++ }, {
++ .resched = GIC_IPI_EXT_INTR_RESCHED_VPE2,
++ .call = GIC_IPI_EXT_INTR_CALLFNC_VPE2
++ }, {
++ .resched = GIC_IPI_EXT_INTR_RESCHED_VPE3,
++ .call = GIC_IPI_EXT_INTR_CALLFNC_VPE3
++ }
++ };
++#define NIPI (sizeof(ipiirq)/sizeof(ipiirq[0]))
++ fill_ipi_map();
++ gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
++ if (!gcmp_present) {
++ /* Enable the GIC */
++ i = REG(_msc01_biu_base, MSC01_SC_CFG);
++ REG(_msc01_biu_base, MSC01_SC_CFG) =
++ (i | (0x1 << MSC01_SC_CFG_GICENA_SHF));
++ pr_debug("GIC Enabled\n");
++ }
++
++ /* set up ipi interrupts */
++ if (cpu_has_vint) {
++ set_vi_handler(MIPSCPU_INT_IPI0, malta_ipi_irqdispatch);
++ set_vi_handler(MIPSCPU_INT_IPI1, malta_ipi_irqdispatch);
++ }
++ /* Argh.. this really needs sorting out.. */
++ printk("CPU%d: status register was %08x\n", smp_processor_id(), read_c0_status());
++ write_c0_status(read_c0_status() | STATUSF_IP3 | STATUSF_IP4);
++ printk("CPU%d: status register now %08x\n", smp_processor_id(), read_c0_status());
++ write_c0_status(0x1100dc00);
++ printk("CPU%d: status register frc %08x\n", smp_processor_id(), read_c0_status());
++ for (i = 0; i < NIPI; i++) {
++ setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, &irq_resched);
++ setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].call, &irq_call);
++
++ set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, handle_percpu_irq);
++ set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].call, handle_percpu_irq);
++ }
++ } else {
++ /* set up ipi interrupts */
++ if (cpu_has_veic) {
++ set_vi_handler (MSC01E_INT_SW0, ipi_resched_dispatch);
++ set_vi_handler (MSC01E_INT_SW1, ipi_call_dispatch);
++ cpu_ipi_resched_irq = MSC01E_INT_SW0;
++ cpu_ipi_call_irq = MSC01E_INT_SW1;
++ } else {
++ if (cpu_has_vint) {
++ set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
++ set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
++ }
++ cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
++ cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ;
++ }
++
++ setup_irq(cpu_ipi_resched_irq, &irq_resched);
++ setup_irq(cpu_ipi_call_irq, &irq_call);
++
++ set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq);
++ set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq);
++ }
++#endif
++}
++
++void malta_be_init(void)
++{
++ if (gcmp_present) {
++ /* Could change CM error mask register */
++ }
++}
++
++
++static char *tr[8] = {
++ "mem", "gcr", "gic", "mmio",
++ "0x04", "0x05", "0x06", "0x07"
++};
++
++static char *mcmd[32] = {
++ [0x00] = "0x00",
++ [0x01] = "Legacy Write",
++ [0x02] = "Legacy Read",
++ [0x03] = "0x03",
++ [0x04] = "0x04",
++ [0x05] = "0x05",
++ [0x06] = "0x06",
++ [0x07] = "0x07",
++ [0x08] = "Coherent Read Own",
++ [0x09] = "Coherent Read Share",
++ [0x0a] = "Coherent Read Discard",
++ [0x0b] = "Coherent Ready Share Always",
++ [0x0c] = "Coherent Upgrade",
++ [0x0d] = "Coherent Writeback",
++ [0x0e] = "0x0e",
++ [0x0f] = "0x0f",
++ [0x10] = "Coherent Copyback",
++ [0x11] = "Coherent Copyback Invalidate",
++ [0x12] = "Coherent Invalidate",
++ [0x13] = "Coherent Write Invalidate",
++ [0x14] = "Coherent Completion Sync",
++ [0x15] = "0x15",
++ [0x16] = "0x16",
++ [0x17] = "0x17",
++ [0x18] = "0x18",
++ [0x19] = "0x19",
++ [0x1a] = "0x1a",
++ [0x1b] = "0x1b",
++ [0x1c] = "0x1c",
++ [0x1d] = "0x1d",
++ [0x1e] = "0x1e",
++ [0x1f] = "0x1f"
++};
++
++static char *core[8] = {
++ "Invalid/OK", "Invalid/Data",
++ "Shared/OK", "Shared/Data",
++ "Modified/OK", "Modified/Data",
++ "Exclusive/OK", "Exclusive/Data"
++};
++
++static char *causes[32] = {
++ "None", "GC_WR_ERR", "GC_RD_ERR", "COH_WR_ERR",
++ "COH_RD_ERR", "MMIO_WR_ERR", "MMIO_RD_ERR", "0x07",
++ "0x08", "0x09", "0x0a", "0x0b",
++ "0x0c", "0x0d", "0x0e", "0x0f",
++ "0x10", "0x11", "0x12", "0x13",
++ "0x14", "0x15", "0x16", "INTVN_WR_ERR",
++ "INTVN_RD_ERR", "0x19", "0x1a", "0x1b",
++ "0x1c", "0x1d", "0x1e", "0x1f"
++};
++
++int malta_be_handler(struct pt_regs *regs, int is_fixup)
++{
++ /* This duplicates the handling in do_be which seems wrong */
++ int retval = is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL;
++
++ if (gcmp_present) {
++ unsigned long cm_error = GCMPGCB(GCMEC);
++ unsigned long cm_addr = GCMPGCB(GCMEA);
++ unsigned long cm_other = GCMPGCB(GCMEO);
++ unsigned long cause, ocause;
++ char buf[256];
++
++ cause = (cm_error & GCMP_GCB_GMEC_ERROR_TYPE_MSK);
++ if (cause != 0) {
++ cause >>= GCMP_GCB_GMEC_ERROR_TYPE_SHF;
++ if (cause < 16) {
++ unsigned long cca_bits = (cm_error >> 15) & 7;
++ unsigned long tr_bits = (cm_error >> 12) & 7;
++ unsigned long mcmd_bits = (cm_error >> 7) & 0x1f;
++ unsigned long stag_bits = (cm_error >> 3) & 15;
++ unsigned long sport_bits = (cm_error >> 0) & 7;
++
++ snprintf(buf, sizeof(buf),
++ "CCA=%lu TR=%s MCmd=%s STag=%lu "
++ "SPort=%lu\n",
++ cca_bits, tr[tr_bits], mcmd[mcmd_bits],
++ stag_bits, sport_bits);
++ } else {
++ /* glob state & sresp together */
++ unsigned long c3_bits = (cm_error >> 18) & 7;
++ unsigned long c2_bits = (cm_error >> 15) & 7;
++ unsigned long c1_bits = (cm_error >> 12) & 7;
++ unsigned long c0_bits = (cm_error >> 9) & 7;
++ unsigned long sc_bit = (cm_error >> 8) & 1;
++ unsigned long mcmd_bits = (cm_error >> 3) & 0x1f;
++ unsigned long sport_bits = (cm_error >> 0) & 7;
++ snprintf(buf, sizeof(buf),
++ "C3=%s C2=%s C1=%s C0=%s SC=%s "
++ "MCmd=%s SPort=%lu\n",
++ core[c3_bits], core[c2_bits],
++ core[c1_bits], core[c0_bits],
++ sc_bit ? "True" : "False",
++ mcmd[mcmd_bits], sport_bits);
++ }
++
++ ocause = (cm_other & GCMP_GCB_GMEO_ERROR_2ND_MSK) >>
++ GCMP_GCB_GMEO_ERROR_2ND_SHF;
++
++ printk("CM_ERROR=%08lx %s <%s>\n", cm_error,
++ causes[cause], buf);
++ printk("CM_ADDR =%08lx\n", cm_addr);
++ printk("CM_OTHER=%08lx %s\n", cm_other, causes[ocause]);
++
++ /* reprime cause register */
++ GCMPGCB(GCMEC) = 0;
++ }
++ }
++
++ return retval;
+ }
+diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c
+index 2cd8f57..e7cad54 100644
+--- a/arch/mips/mips-boards/malta/malta_setup.c
++++ b/arch/mips/mips-boards/malta/malta_setup.c
+@@ -1,7 +1,7 @@
+ /*
+ * Carsten Langgaard, carstenl at mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+- * Copyright (C) Dmitri Vorobiev
++ * Copyright (C) 2008 Dmitri Vorobiev
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+@@ -36,7 +36,10 @@
+ #include <linux/console.h>
+ #endif
- soc at f0000000 {
-@@ -112,26 +114,26 @@
- #size-cells = <1>;
- device_type = "soc";
- compatible = "fsl,mpc8272", "fsl,pq2-soc";
-- ranges = <00000000 f0000000 00053000>;
-+ ranges = <0x0 0xf0000000 0x53000>;
+-struct resource standard_io_resources[] = {
++extern void malta_be_init(void);
++extern int malta_be_handler(struct pt_regs *regs, int is_fixup);
++
++static struct resource standard_io_resources[] = {
+ {
+ .name = "dma1",
+ .start = 0x00,
+@@ -220,4 +223,7 @@ void __init plat_mem_setup(void)
+ screen_info_setup();
+ #endif
+ mips_reboot_setup();
++
++ board_be_init = malta_be_init;
++ board_be_handler = malta_be_handler;
+ }
+diff --git a/arch/mips/mipssim/sim_setup.c b/arch/mips/mipssim/sim_setup.c
+index d49fe73..7c7148e 100644
+--- a/arch/mips/mipssim/sim_setup.c
++++ b/arch/mips/mipssim/sim_setup.c
+@@ -39,9 +39,6 @@
+ static void __init serial_init(void);
+ unsigned int _isbonito = 0;
+
+-extern void __init sanitize_tlb_entries(void);
+-
+-
+ const char *get_system_type(void)
+ {
+ return "MIPSsim";
+@@ -55,9 +52,6 @@ void __init plat_mem_setup(void)
+
+ pr_info("Linux started...\n");
+
+-#ifdef CONFIG_MIPS_MT_SMP
+- sanitize_tlb_entries();
+-#endif
+ }
+
+ extern struct plat_smp_ops ssmtc_smp_ops;
+diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
+index c6f832e..4873102 100644
+--- a/arch/mips/mm/Makefile
++++ b/arch/mips/mm/Makefile
+@@ -4,30 +4,29 @@
+
+ obj-y += cache.o dma-default.o extable.o fault.o \
+ init.o pgtable.o tlbex.o tlbex-fault.o \
+- uasm.o
++ uasm.o page.o
+
+ obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o
+ obj-$(CONFIG_64BIT) += pgtable-64.o
+ obj-$(CONFIG_HIGHMEM) += highmem.o
+
+-obj-$(CONFIG_CPU_LOONGSON2) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+-obj-$(CONFIG_CPU_MIPS32) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+-obj-$(CONFIG_CPU_MIPS64) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+-obj-$(CONFIG_CPU_NEVADA) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+-obj-$(CONFIG_CPU_R10000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+-obj-$(CONFIG_CPU_R3000) += c-r3k.o tlb-r3k.o pg-r4k.o
+-obj-$(CONFIG_CPU_R4300) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+-obj-$(CONFIG_CPU_R4X00) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+-obj-$(CONFIG_CPU_R5000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+-obj-$(CONFIG_CPU_R5432) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+-obj-$(CONFIG_CPU_R8000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r8k.o
+-obj-$(CONFIG_CPU_RM7000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+-obj-$(CONFIG_CPU_RM9000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+-obj-$(CONFIG_CPU_SB1) += c-r4k.o cerr-sb1.o cex-sb1.o pg-sb1.o \
+- tlb-r4k.o
+-obj-$(CONFIG_CPU_TX39XX) += c-tx39.o pg-r4k.o tlb-r3k.o
+-obj-$(CONFIG_CPU_TX49XX) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+-obj-$(CONFIG_CPU_VR41XX) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
++obj-$(CONFIG_CPU_LOONGSON2) += c-r4k.o cex-gen.o tlb-r4k.o
++obj-$(CONFIG_CPU_MIPS32) += c-r4k.o cex-gen.o tlb-r4k.o
++obj-$(CONFIG_CPU_MIPS64) += c-r4k.o cex-gen.o tlb-r4k.o
++obj-$(CONFIG_CPU_NEVADA) += c-r4k.o cex-gen.o tlb-r4k.o
++obj-$(CONFIG_CPU_R10000) += c-r4k.o cex-gen.o tlb-r4k.o
++obj-$(CONFIG_CPU_R3000) += c-r3k.o tlb-r3k.o
++obj-$(CONFIG_CPU_R4300) += c-r4k.o cex-gen.o tlb-r4k.o
++obj-$(CONFIG_CPU_R4X00) += c-r4k.o cex-gen.o tlb-r4k.o
++obj-$(CONFIG_CPU_R5000) += c-r4k.o cex-gen.o tlb-r4k.o
++obj-$(CONFIG_CPU_R5432) += c-r4k.o cex-gen.o tlb-r4k.o
++obj-$(CONFIG_CPU_R8000) += c-r4k.o cex-gen.o tlb-r8k.o
++obj-$(CONFIG_CPU_RM7000) += c-r4k.o cex-gen.o tlb-r4k.o
++obj-$(CONFIG_CPU_RM9000) += c-r4k.o cex-gen.o tlb-r4k.o
++obj-$(CONFIG_CPU_SB1) += c-r4k.o cerr-sb1.o cex-sb1.o tlb-r4k.o
++obj-$(CONFIG_CPU_TX39XX) += c-tx39.o tlb-r3k.o
++obj-$(CONFIG_CPU_TX49XX) += c-r4k.o cex-gen.o tlb-r4k.o
++obj-$(CONFIG_CPU_VR41XX) += c-r4k.o cex-gen.o tlb-r4k.o
+
+ obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o
+ obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o
+diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
+index 77aefb4..643c8bc 100644
+--- a/arch/mips/mm/c-r4k.c
++++ b/arch/mips/mm/c-r4k.c
+@@ -14,6 +14,7 @@
+ #include <linux/linkage.h>
+ #include <linux/sched.h>
+ #include <linux/mm.h>
++#include <linux/module.h>
+ #include <linux/bitops.h>
- // Temporary -- will go away once kernel uses ranges for get_immrbase().
-- reg = <f0000000 00053000>;
-+ reg = <0xf0000000 0x53000>;
+ #include <asm/bcache.h>
+@@ -53,6 +54,12 @@ static inline void r4k_on_each_cpu(void (*func) (void *info), void *info,
+ preempt_enable();
+ }
- cpm at 119c0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "fsl,mpc8272-cpm", "fsl,cpm2";
-- reg = <119c0 30>;
-+ reg = <0x119c0 0x30>;
- ranges;
++#if defined(CONFIG_MIPS_CMP)
++#define cpu_has_safe_index_cacheops 0
++#else
++#define cpu_has_safe_index_cacheops 1
++#endif
++
+ /*
+ * Must die.
+ */
+@@ -481,6 +488,8 @@ static inline void local_r4k_flush_cache_page(void *args)
- muram at 0 {
- #address-cells = <1>;
- #size-cells = <1>;
-- ranges = <0 0 10000>;
-+ ranges = <0x0 0x0 0x10000>;
+ if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
+ r4k_blast_dcache_page(addr);
++ if (exec && !cpu_icache_snoops_remote_store)
++ r4k_blast_scache_page(addr);
+ }
+ if (exec) {
+ if (vaddr && cpu_has_vtag_icache && mm == current->active_mm) {
+@@ -583,7 +592,7 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
+ * subset property so we have to flush the primary caches
+ * explicitly
+ */
+- if (size >= dcache_size) {
++ if (cpu_has_safe_index_cacheops && size >= dcache_size) {
+ r4k_blast_dcache();
+ } else {
+ R4600_HIT_CACHEOP_WAR_IMPL;
+@@ -606,7 +615,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
+ return;
+ }
- data at 0 {
- compatible = "fsl,cpm-muram-data";
-- reg = <0 2000 9800 800>;
-+ reg = <0x0 0x2000 0x9800 0x800>;
- };
- };
+- if (size >= dcache_size) {
++ if (cpu_has_safe_index_cacheops && size >= dcache_size) {
+ r4k_blast_dcache();
+ } else {
+ R4600_HIT_CACHEOP_WAR_IMPL;
+@@ -968,6 +977,7 @@ static void __cpuinit probe_pcache(void)
+ case CPU_24K:
+ case CPU_34K:
+ case CPU_74K:
++ case CPU_1004K:
+ if ((read_c0_config7() & (1 << 16))) {
+ /* effectively physically indexed dcache,
+ thus no virtual aliases. */
+@@ -1216,9 +1226,25 @@ void au1x00_fixup_config_od(void)
+ }
+ }
-@@ -139,29 +141,29 @@
- compatible = "fsl,mpc8272-brg",
- "fsl,cpm2-brg",
- "fsl,cpm-brg";
-- reg = <119f0 10 115f0 10>;
-+ reg = <0x119f0 0x10 0x115f0 0x10>;
- };
++static int __cpuinitdata cca = -1;
++
++static int __init cca_setup(char *str)
++{
++ get_option(&str, &cca);
++
++ return 1;
++}
++
++__setup("cca=", cca_setup);
++
+ static void __cpuinit coherency_setup(void)
+ {
+- change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
++ if (cca < 0 || cca > 7)
++ cca = read_c0_config() & CONF_CM_CMASK;
++ _page_cachable_default = cca << _CACHE_SHIFT;
++
++ pr_debug("Using cache attribute %d\n", cca);
++ change_c0_config(CONF_CM_CMASK, cca);
- serial at 11a00 {
- device_type = "serial";
- compatible = "fsl,mpc8272-scc-uart",
- "fsl,cpm2-scc-uart";
-- reg = <11a00 20 8000 100>;
-- interrupts = <28 8>;
-+ reg = <0x11a00 0x20 0x8000 0x100>;
-+ interrupts = <40 8>;
- interrupt-parent = <&PIC>;
- fsl,cpm-brg = <1>;
-- fsl,cpm-command = <00800000>;
-+ fsl,cpm-command = <0x800000>;
- };
+ /*
+ * c0_status.cu=0 specifies that updates by the sc instruction use
+@@ -1248,6 +1274,20 @@ static void __cpuinit coherency_setup(void)
+ }
+ }
- serial at 11a60 {
- device_type = "serial";
- compatible = "fsl,mpc8272-scc-uart",
- "fsl,cpm2-scc-uart";
-- reg = <11a60 20 8300 100>;
-- interrupts = <2b 8>;
-+ reg = <0x11a60 0x20 0x8300 0x100>;
-+ interrupts = <43 8>;
- interrupt-parent = <&PIC>;
- fsl,cpm-brg = <4>;
-- fsl,cpm-command = <0ce00000>;
-+ fsl,cpm-command = <0xce00000>;
- };
++#if defined(CONFIG_DMA_NONCOHERENT)
++
++static int __cpuinitdata coherentio;
++
++static int __init setcoherentio(char *str)
++{
++ coherentio = 1;
++
++ return 1;
++}
++
++__setup("coherentio", setcoherentio);
++#endif
++
+ void __cpuinit r4k_cache_init(void)
+ {
+ extern void build_clear_page(void);
+@@ -1307,14 +1347,22 @@ void __cpuinit r4k_cache_init(void)
+ flush_data_cache_page = r4k_flush_data_cache_page;
+ flush_icache_range = r4k_flush_icache_range;
+
+-#ifdef CONFIG_DMA_NONCOHERENT
+- _dma_cache_wback_inv = r4k_dma_cache_wback_inv;
+- _dma_cache_wback = r4k_dma_cache_wback_inv;
+- _dma_cache_inv = r4k_dma_cache_inv;
++#if defined(CONFIG_DMA_NONCOHERENT)
++ if (coherentio) {
++ _dma_cache_wback_inv = (void *)cache_noop;
++ _dma_cache_wback = (void *)cache_noop;
++ _dma_cache_inv = (void *)cache_noop;
++ } else {
++ _dma_cache_wback_inv = r4k_dma_cache_wback_inv;
++ _dma_cache_wback = r4k_dma_cache_wback_inv;
++ _dma_cache_inv = r4k_dma_cache_inv;
++ }
+ #endif
- mdio at 10d40 {
-@@ -169,23 +171,23 @@
- compatible = "fsl,mpc8272ads-mdio-bitbang",
- "fsl,mpc8272-mdio-bitbang",
- "fsl,cpm2-mdio-bitbang";
-- reg = <10d40 14>;
-+ reg = <0x10d40 0x14>;
- #address-cells = <1>;
- #size-cells = <0>;
-- fsl,mdio-pin = <12>;
-- fsl,mdc-pin = <13>;
-+ fsl,mdio-pin = <18>;
-+ fsl,mdc-pin = <19>;
+ build_clear_page();
+ build_copy_page();
++#if !defined(CONFIG_MIPS_CMP)
+ local_r4k___flush_cache_all(NULL);
++#endif
+ coherency_setup();
+ }
+diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
+index f590367..034e850 100644
+--- a/arch/mips/mm/cache.c
++++ b/arch/mips/mm/cache.c
+@@ -130,8 +130,28 @@ void __update_cache(struct vm_area_struct *vma, unsigned long address,
+ }
+ }
- PHY0: ethernet-phy at 0 {
- interrupt-parent = <&PIC>;
-- interrupts = <17 8>;
-- reg = <0>;
-+ interrupts = <23 8>;
-+ reg = <0x0>;
- device_type = "ethernet-phy";
- };
+-static char cache_panic[] __cpuinitdata =
+- "Yeee, unsupported cache architecture.";
++unsigned long _page_cachable_default;
++EXPORT_SYMBOL_GPL(_page_cachable_default);
++
++static inline void setup_protection_map(void)
++{
++ protection_map[0] = PAGE_NONE;
++ protection_map[1] = PAGE_READONLY;
++ protection_map[2] = PAGE_COPY;
++ protection_map[3] = PAGE_COPY;
++ protection_map[4] = PAGE_READONLY;
++ protection_map[5] = PAGE_READONLY;
++ protection_map[6] = PAGE_COPY;
++ protection_map[7] = PAGE_COPY;
++ protection_map[8] = PAGE_NONE;
++ protection_map[9] = PAGE_READONLY;
++ protection_map[10] = PAGE_SHARED;
++ protection_map[11] = PAGE_SHARED;
++ protection_map[12] = PAGE_READONLY;
++ protection_map[13] = PAGE_READONLY;
++ protection_map[14] = PAGE_SHARED;
++ protection_map[15] = PAGE_SHARED;
++}
- PHY1: ethernet-phy at 1 {
- interrupt-parent = <&PIC>;
-- interrupts = <17 8>;
-- reg = <3>;
-+ interrupts = <23 8>;
-+ reg = <0x3>;
- device_type = "ethernet-phy";
- };
- };
-@@ -194,33 +196,33 @@
- device_type = "network";
- compatible = "fsl,mpc8272-fcc-enet",
- "fsl,cpm2-fcc-enet";
-- reg = <11300 20 8400 100 11390 1>;
-+ reg = <0x11300 0x20 0x8400 0x100 0x11390 0x1>;
- local-mac-address = [ 00 00 00 00 00 00 ];
-- interrupts = <20 8>;
-+ interrupts = <32 8>;
- interrupt-parent = <&PIC>;
- phy-handle = <&PHY0>;
- linux,network-index = <0>;
-- fsl,cpm-command = <12000300>;
-+ fsl,cpm-command = <0x12000300>;
- };
+ void __devinit cpu_cache_init(void)
+ {
+@@ -139,34 +159,29 @@ void __devinit cpu_cache_init(void)
+ extern void __weak r3k_cache_init(void);
- ethernet at 11320 {
- device_type = "network";
- compatible = "fsl,mpc8272-fcc-enet",
- "fsl,cpm2-fcc-enet";
-- reg = <11320 20 8500 100 113b0 1>;
-+ reg = <0x11320 0x20 0x8500 0x100 0x113b0 0x1>;
- local-mac-address = [ 00 00 00 00 00 00 ];
-- interrupts = <21 8>;
-+ interrupts = <33 8>;
- interrupt-parent = <&PIC>;
- phy-handle = <&PHY1>;
- linux,network-index = <1>;
-- fsl,cpm-command = <16200300>;
-+ fsl,cpm-command = <0x16200300>;
- };
- };
+ r3k_cache_init();
+- return;
+ }
+ if (cpu_has_6k_cache) {
+ extern void __weak r6k_cache_init(void);
- PIC: interrupt-controller at 10c00 {
- #interrupt-cells = <2>;
- interrupt-controller;
-- reg = <10c00 80>;
-+ reg = <0x10c00 0x80>;
- compatible = "fsl,mpc8272-pic", "fsl,cpm2-pic";
- };
+ r6k_cache_init();
+- return;
+ }
+ if (cpu_has_4k_cache) {
+ extern void __weak r4k_cache_init(void);
-@@ -232,14 +234,14 @@
- "fsl,talitos-sec2",
- "fsl,talitos",
- "talitos";
-- reg = <30000 10000>;
-- interrupts = <b 8>;
-+ reg = <0x30000 0x10000>;
-+ interrupts = <11 8>;
- interrupt-parent = <&PIC>;
- num-channels = <4>;
-- channel-fifo-len = <18>;
-- exec-units-mask = <0000007e>;
-+ channel-fifo-len = <24>;
-+ exec-units-mask = <0x7e>;
- /* desc mask is for rev1.x, we need runtime fixup for >=2.x */
-- descriptor-types-mask = <01010ebf>;
-+ descriptor-types-mask = <0x1010ebf>;
- };
- };
+ r4k_cache_init();
+- return;
+ }
+ if (cpu_has_8k_cache) {
+ extern void __weak r8k_cache_init(void);
-diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
-index 9bb4083..539e02f 100644
---- a/arch/powerpc/boot/dts/mpc832x_mds.dts
-+++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
-@@ -255,9 +255,7 @@
- enet0: ucc at 2200 {
- device_type = "network";
- compatible = "ucc_geth";
-- model = "UCC";
- cell-index = <3>;
-- device-id = <3>;
- reg = <0x2200 0x200>;
- interrupts = <34>;
- interrupt-parent = <&qeic>;
-@@ -271,9 +269,7 @@
- enet1: ucc at 3200 {
- device_type = "network";
- compatible = "ucc_geth";
-- model = "UCC";
- cell-index = <4>;
-- device-id = <4>;
- reg = <0x3200 0x200>;
- interrupts = <35>;
- interrupt-parent = <&qeic>;
-@@ -287,8 +283,7 @@
- ucc at 2400 {
- device_type = "serial";
- compatible = "ucc_uart";
-- model = "UCC";
-- device-id = <5>; /* The UCC number, 1-7*/
-+ cell-index = <5>; /* The UCC number, 1-7*/
- port-number = <0>; /* Which ttyQEx device */
- soft-uart; /* We need Soft-UART */
- reg = <0x2400 0x200>;
-diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts
-index 94f93d2..179c81c 100644
---- a/arch/powerpc/boot/dts/mpc832x_rdb.dts
-+++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts
-@@ -208,9 +208,7 @@
- enet0: ucc at 3000 {
- device_type = "network";
- compatible = "ucc_geth";
-- model = "UCC";
- cell-index = <2>;
-- device-id = <2>;
- reg = <0x3000 0x200>;
- interrupts = <33>;
- interrupt-parent = <&qeic>;
-@@ -224,9 +222,7 @@
- enet1: ucc at 2200 {
- device_type = "network";
- compatible = "ucc_geth";
-- model = "UCC";
- cell-index = <3>;
-- device-id = <3>;
- reg = <0x2200 0x200>;
- interrupts = <34>;
- interrupt-parent = <&qeic>;
-diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
-index 55f03e8..8160ff2 100644
---- a/arch/powerpc/boot/dts/mpc836x_mds.dts
-+++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
-@@ -257,9 +257,7 @@
- enet0: ucc at 2000 {
- device_type = "network";
- compatible = "ucc_geth";
-- model = "UCC";
- cell-index = <1>;
-- device-id = <1>;
- reg = <0x2000 0x200>;
- interrupts = <32>;
- interrupt-parent = <&qeic>;
-@@ -274,9 +272,7 @@
- enet1: ucc at 3000 {
- device_type = "network";
- compatible = "ucc_geth";
-- model = "UCC";
- cell-index = <2>;
-- device-id = <2>;
- reg = <0x3000 0x200>;
- interrupts = <33>;
- interrupt-parent = <&qeic>;
-diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts
-index 9752484..18033ed 100644
---- a/arch/powerpc/boot/dts/mpc8540ads.dts
-+++ b/arch/powerpc/boot/dts/mpc8540ads.dts
-@@ -1,7 +1,7 @@
- /*
- * MPC8540 ADS Device Tree Source
- *
-- * Copyright 2006 Freescale Semiconductor Inc.
-+ * Copyright 2006, 2008 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
-@@ -9,6 +9,7 @@
- * option) any later version.
- */
+ r8k_cache_init();
+- return;
+ }
+ if (cpu_has_tx39_cache) {
+ extern void __weak tx39_cache_init(void);
-+/dts-v1/;
+ tx39_cache_init();
+- return;
+ }
- / {
- model = "MPC8540ADS";
-@@ -31,11 +32,11 @@
+- panic(cache_panic);
++ setup_protection_map();
+ }
- PowerPC,8540 at 0 {
- device_type = "cpu";
-- reg = <0>;
-- d-cache-line-size = <20>; // 32 bytes
-- i-cache-line-size = <20>; // 32 bytes
-- d-cache-size = <8000>; // L1, 32K
-- i-cache-size = <8000>; // L1, 32K
-+ reg = <0x0>;
-+ d-cache-line-size = <32>; // 32 bytes
-+ i-cache-line-size = <32>; // 32 bytes
-+ d-cache-size = <0x8000>; // L1, 32K
-+ i-cache-size = <0x8000>; // L1, 32K
- timebase-frequency = <0>; // 33 MHz, from uboot
- bus-frequency = <0>; // 166 MHz
- clock-frequency = <0>; // 825 MHz, from uboot
-@@ -44,31 +45,31 @@
+ int __weak __uncached_access(struct file *file, unsigned long addr)
+diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
+index c7aed13..ecd562d 100644
+--- a/arch/mips/mm/init.c
++++ b/arch/mips/mm/init.c
+@@ -142,7 +142,7 @@ void *kmap_coherent(struct page *page, unsigned long addr)
+ #endif
+ vaddr = __fix_to_virt(FIX_CMAP_END - idx);
+ pte = mk_pte(page, PAGE_KERNEL);
+-#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
++#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+ entrylo = pte.pte_high;
+ #else
+ entrylo = pte_val(pte) >> 6;
+@@ -221,7 +221,7 @@ void copy_user_highpage(struct page *to, struct page *from,
+ copy_page(vto, vfrom);
+ kunmap_atomic(vfrom, KM_USER0);
+ }
+- if (((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc) ||
++ if ((!cpu_has_ic_fills_f_dc) ||
+ pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
+ flush_data_cache_page((unsigned long)vto);
+ kunmap_atomic(vto, KM_USER1);
+@@ -229,8 +229,6 @@ void copy_user_highpage(struct page *to, struct page *from,
+ smp_wmb();
+ }
- memory {
- device_type = "memory";
-- reg = <00000000 08000000>; // 128M at 0x0
-+ reg = <0x0 0x8000000>; // 128M at 0x0
- };
+-EXPORT_SYMBOL(copy_user_highpage);
+-
+ void copy_to_user_page(struct vm_area_struct *vma,
+ struct page *page, unsigned long vaddr, void *dst, const void *src,
+ unsigned long len)
+@@ -249,8 +247,6 @@ void copy_to_user_page(struct vm_area_struct *vma,
+ flush_cache_page(vma, vaddr, page_to_pfn(page));
+ }
- soc8540 at e0000000 {
- #address-cells = <1>;
- #size-cells = <1>;
- device_type = "soc";
-- ranges = <0 e0000000 00100000>;
-- reg = <e0000000 00100000>; // CCSRBAR 1M
-+ ranges = <0x0 0xe0000000 0x100000>;
-+ reg = <0xe0000000 0x100000>; // CCSRBAR 1M
- bus-frequency = <0>;
+-EXPORT_SYMBOL(copy_to_user_page);
+-
+ void copy_from_user_page(struct vm_area_struct *vma,
+ struct page *page, unsigned long vaddr, void *dst, const void *src,
+ unsigned long len)
+@@ -267,9 +263,6 @@ void copy_from_user_page(struct vm_area_struct *vma,
+ }
+ }
- memory-controller at 2000 {
- compatible = "fsl,8540-memory-controller";
-- reg = <2000 1000>;
-+ reg = <0x2000 0x1000>;
- interrupt-parent = <&mpic>;
-- interrupts = <12 2>;
-+ interrupts = <18 2>;
- };
+-EXPORT_SYMBOL(copy_from_user_page);
+-
+-
+ #ifdef CONFIG_HIGHMEM
+ unsigned long highstart_pfn, highend_pfn;
- l2-cache-controller at 20000 {
- compatible = "fsl,8540-l2-cache-controller";
-- reg = <20000 1000>;
-- cache-line-size = <20>; // 32 bytes
-- cache-size = <40000>; // L2, 256K
-+ reg = <0x20000 0x1000>;
-+ cache-line-size = <32>; // 32 bytes
-+ cache-size = <0x40000>; // L2, 256K
- interrupt-parent = <&mpic>;
-- interrupts = <10 2>;
-+ interrupts = <16 2>;
- };
+diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c
+new file mode 100644
+index 0000000..d827d61
+--- /dev/null
++++ b/arch/mips/mm/page.c
+@@ -0,0 +1,684 @@
++/*
++ * 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) 2003, 04, 05 Ralf Baechle (ralf at linux-mips.org)
++ * Copyright (C) 2007 Maciej W. Rozycki
++ * Copyright (C) 2008 Thiemo Seufer
++ */
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/proc_fs.h>
++
++#include <asm/bugs.h>
++#include <asm/cacheops.h>
++#include <asm/inst.h>
++#include <asm/io.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/prefetch.h>
++#include <asm/system.h>
++#include <asm/bootinfo.h>
++#include <asm/mipsregs.h>
++#include <asm/mmu_context.h>
++#include <asm/cpu.h>
++#include <asm/war.h>
++
++#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
++#include <asm/sibyte/sb1250.h>
++#include <asm/sibyte/sb1250_regs.h>
++#include <asm/sibyte/sb1250_dma.h>
++#endif
++
++#include "uasm.h"
++
++/* Registers used in the assembled routines. */
++#define ZERO 0
++#define AT 2
++#define A0 4
++#define A1 5
++#define A2 6
++#define T0 8
++#define T1 9
++#define T2 10
++#define T3 11
++#define T9 25
++#define RA 31
++
++/* Handle labels (which must be positive integers). */
++enum label_id {
++ label_clear_nopref = 1,
++ label_clear_pref,
++ label_copy_nopref,
++ label_copy_pref_both,
++ label_copy_pref_store,
++};
++
++UASM_L_LA(_clear_nopref)
++UASM_L_LA(_clear_pref)
++UASM_L_LA(_copy_nopref)
++UASM_L_LA(_copy_pref_both)
++UASM_L_LA(_copy_pref_store)
++
++/* We need one branch and therefore one relocation per target label. */
++static struct uasm_label __cpuinitdata labels[5];
++static struct uasm_reloc __cpuinitdata relocs[5];
++
++#define cpu_is_r4600_v1_x() ((read_c0_prid() & 0xfffffff0) == 0x00002010)
++#define cpu_is_r4600_v2_x() ((read_c0_prid() & 0xfffffff0) == 0x00002020)
++
++/*
++ * Maximum sizes:
++ *
++ * R4000 128 bytes S-cache: 0x058 bytes
++ * R4600 v1.7: 0x05c bytes
++ * R4600 v2.0: 0x060 bytes
++ * With prefetching, 16 word strides 0x120 bytes
++ */
++
++static u32 clear_page_array[0x120 / 4];
++
++#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
++void clear_page_cpu(void *page) __attribute__((alias("clear_page_array")));
++#else
++void clear_page(void *page) __attribute__((alias("clear_page_array")));
++#endif
++
++EXPORT_SYMBOL(clear_page);
++
++/*
++ * Maximum sizes:
++ *
++ * R4000 128 bytes S-cache: 0x11c bytes
++ * R4600 v1.7: 0x080 bytes
++ * R4600 v2.0: 0x07c bytes
++ * With prefetching, 16 word strides 0x540 bytes
++ */
++static u32 copy_page_array[0x540 / 4];
++
++#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
++void
++copy_page_cpu(void *to, void *from) __attribute__((alias("copy_page_array")));
++#else
++void copy_page(void *to, void *from) __attribute__((alias("copy_page_array")));
++#endif
++
++EXPORT_SYMBOL(copy_page);
++
++
++static int pref_bias_clear_store __cpuinitdata;
++static int pref_bias_copy_load __cpuinitdata;
++static int pref_bias_copy_store __cpuinitdata;
++
++static u32 pref_src_mode __cpuinitdata;
++static u32 pref_dst_mode __cpuinitdata;
++
++static int clear_word_size __cpuinitdata;
++static int copy_word_size __cpuinitdata;
++
++static int half_clear_loop_size __cpuinitdata;
++static int half_copy_loop_size __cpuinitdata;
++
++static int cache_line_size __cpuinitdata;
++#define cache_line_mask() (cache_line_size - 1)
++
++static inline void __cpuinit
++pg_addiu(u32 **buf, unsigned int reg1, unsigned int reg2, unsigned int off)
++{
++ if (cpu_has_64bit_gp_regs && DADDI_WAR && r4k_daddiu_bug()) {
++ if (off > 0x7fff) {
++ uasm_i_lui(buf, T9, uasm_rel_hi(off));
++ uasm_i_addiu(buf, T9, T9, uasm_rel_lo(off));
++ } else
++ uasm_i_addiu(buf, T9, ZERO, off);
++ uasm_i_daddu(buf, reg1, reg2, T9);
++ } else {
++ if (off > 0x7fff) {
++ uasm_i_lui(buf, T9, uasm_rel_hi(off));
++ uasm_i_addiu(buf, T9, T9, uasm_rel_lo(off));
++ UASM_i_ADDU(buf, reg1, reg2, T9);
++ } else
++ UASM_i_ADDIU(buf, reg1, reg2, off);
++ }
++}
++
++static void __cpuinit set_prefetch_parameters(void)
++{
++ if (cpu_has_64bit_gp_regs || cpu_has_64bit_zero_reg)
++ clear_word_size = 8;
++ else
++ clear_word_size = 4;
++
++ if (cpu_has_64bit_gp_regs)
++ copy_word_size = 8;
++ else
++ copy_word_size = 4;
++
++ /*
++ * The pref's used here are using "streaming" hints, which cause the
++ * copied data to be kicked out of the cache sooner. A page copy often
++ * ends up copying a lot more data than is commonly used, so this seems
++ * to make sense in terms of reducing cache pollution, but I've no real
++ * performance data to back this up.
++ */
++ if (cpu_has_prefetch) {
++ /*
++ * XXX: Most prefetch bias values in here are based on
++ * guesswork.
++ */
++ cache_line_size = cpu_dcache_line_size();
++ switch (current_cpu_type()) {
++ case CPU_TX49XX:
++ /* TX49 supports only Pref_Load */
++ pref_bias_copy_load = 256;
++ break;
++
++ case CPU_RM9000:
++ /*
++ * As a workaround for erratum G105 which make the
++ * PrepareForStore hint unusable we fall back to
++ * StoreRetained on the RM9000. Once it is known which
++ * versions of the RM9000 we'll be able to condition-
++ * alize this.
++ */
++
++ case CPU_R10000:
++ case CPU_R12000:
++ case CPU_R14000:
++ /*
++ * Those values have been experimentally tuned for an
++ * Origin 200.
++ */
++ pref_bias_clear_store = 512;
++ pref_bias_copy_load = 256;
++ pref_bias_copy_store = 256;
++ pref_src_mode = Pref_LoadStreamed;
++ pref_dst_mode = Pref_StoreStreamed;
++ break;
++
++ case CPU_SB1:
++ case CPU_SB1A:
++ pref_bias_clear_store = 128;
++ pref_bias_copy_load = 128;
++ pref_bias_copy_store = 128;
++ /*
++ * SB1 pass1 Pref_LoadStreamed/Pref_StoreStreamed
++ * hints are broken.
++ */
++ if (current_cpu_type() == CPU_SB1 &&
++ (current_cpu_data.processor_id & 0xff) < 0x02) {
++ pref_src_mode = Pref_Load;
++ pref_dst_mode = Pref_Store;
++ } else {
++ pref_src_mode = Pref_LoadStreamed;
++ pref_dst_mode = Pref_StoreStreamed;
++ }
++ break;
++
++ default:
++ pref_bias_clear_store = 128;
++ pref_bias_copy_load = 256;
++ pref_bias_copy_store = 128;
++ pref_src_mode = Pref_LoadStreamed;
++ pref_dst_mode = Pref_PrepareForStore;
++ break;
++ }
++ } else {
++ if (cpu_has_cache_cdex_s)
++ cache_line_size = cpu_scache_line_size();
++ else if (cpu_has_cache_cdex_p)
++ cache_line_size = cpu_dcache_line_size();
++ }
++ /*
++ * Too much unrolling will overflow the available space in
++ * clear_space_array / copy_page_array. 8 words sounds generous,
++ * but a R4000 with 128 byte L2 line length can exceed even that.
++ */
++ half_clear_loop_size = min(8 * clear_word_size,
++ max(cache_line_size >> 1,
++ 4 * clear_word_size));
++ half_copy_loop_size = min(8 * copy_word_size,
++ max(cache_line_size >> 1,
++ 4 * copy_word_size));
++}
++
++static void __cpuinit build_clear_store(u32 **buf, int off)
++{
++ if (cpu_has_64bit_gp_regs || cpu_has_64bit_zero_reg) {
++ uasm_i_sd(buf, ZERO, off, A0);
++ } else {
++ uasm_i_sw(buf, ZERO, off, A0);
++ }
++}
++
++static inline void __cpuinit build_clear_pref(u32 **buf, int off)
++{
++ if (off & cache_line_mask())
++ return;
++
++ if (pref_bias_clear_store) {
++ uasm_i_pref(buf, pref_dst_mode, pref_bias_clear_store + off,
++ A0);
++ } else if (cpu_has_cache_cdex_s) {
++ uasm_i_cache(buf, Create_Dirty_Excl_SD, off, A0);
++ } else if (cpu_has_cache_cdex_p) {
++ if (R4600_V1_HIT_CACHEOP_WAR && cpu_is_r4600_v1_x()) {
++ uasm_i_nop(buf);
++ uasm_i_nop(buf);
++ uasm_i_nop(buf);
++ uasm_i_nop(buf);
++ }
++
++ if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
++ uasm_i_lw(buf, ZERO, ZERO, AT);
++
++ uasm_i_cache(buf, Create_Dirty_Excl_D, off, A0);
++ }
++}
++
++void __cpuinit build_clear_page(void)
++{
++ int off;
++ u32 *buf = (u32 *)&clear_page_array;
++ struct uasm_label *l = labels;
++ struct uasm_reloc *r = relocs;
++ int i;
++
++ memset(labels, 0, sizeof(labels));
++ memset(relocs, 0, sizeof(relocs));
++
++ set_prefetch_parameters();
++
++ /*
++ * This algorithm makes the following assumptions:
++ * - The prefetch bias is a multiple of 2 words.
++ * - The prefetch bias is less than one page.
++ */
++ BUG_ON(pref_bias_clear_store % (2 * clear_word_size));
++ BUG_ON(PAGE_SIZE < pref_bias_clear_store);
++
++ off = PAGE_SIZE - pref_bias_clear_store;
++ if (off > 0xffff || !pref_bias_clear_store)
++ pg_addiu(&buf, A2, A0, off);
++ else
++ uasm_i_ori(&buf, A2, A0, off);
++
++ if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
++ uasm_i_lui(&buf, AT, 0xa000);
++
++ off = min(8, pref_bias_clear_store / cache_line_size) *
++ cache_line_size;
++ while (off) {
++ build_clear_pref(&buf, -off);
++ off -= cache_line_size;
++ }
++ uasm_l_clear_pref(&l, buf);
++ do {
++ build_clear_pref(&buf, off);
++ build_clear_store(&buf, off);
++ off += clear_word_size;
++ } while (off < half_clear_loop_size);
++ pg_addiu(&buf, A0, A0, 2 * off);
++ off = -off;
++ do {
++ build_clear_pref(&buf, off);
++ if (off == -clear_word_size)
++ uasm_il_bne(&buf, &r, A0, A2, label_clear_pref);
++ build_clear_store(&buf, off);
++ off += clear_word_size;
++ } while (off < 0);
++
++ if (pref_bias_clear_store) {
++ pg_addiu(&buf, A2, A0, pref_bias_clear_store);
++ uasm_l_clear_nopref(&l, buf);
++ off = 0;
++ do {
++ build_clear_store(&buf, off);
++ off += clear_word_size;
++ } while (off < half_clear_loop_size);
++ pg_addiu(&buf, A0, A0, 2 * off);
++ off = -off;
++ do {
++ if (off == -clear_word_size)
++ uasm_il_bne(&buf, &r, A0, A2,
++ label_clear_nopref);
++ build_clear_store(&buf, off);
++ off += clear_word_size;
++ } while (off < 0);
++ }
++
++ uasm_i_jr(&buf, RA);
++ uasm_i_nop(&buf);
++
++ BUG_ON(buf > clear_page_array + ARRAY_SIZE(clear_page_array));
++
++ uasm_resolve_relocs(relocs, labels);
++
++ pr_debug("Synthesized clear page handler (%u instructions).\n",
++ (u32)(buf - clear_page_array));
++
++ pr_debug("\t.set push\n");
++ pr_debug("\t.set noreorder\n");
++ for (i = 0; i < (buf - clear_page_array); i++)
++ pr_debug("\t.word 0x%08x\n", clear_page_array[i]);
++ pr_debug("\t.set pop\n");
++}
++
++static void __cpuinit build_copy_load(u32 **buf, int reg, int off)
++{
++ if (cpu_has_64bit_gp_regs) {
++ uasm_i_ld(buf, reg, off, A1);
++ } else {
++ uasm_i_lw(buf, reg, off, A1);
++ }
++}
++
++static void __cpuinit build_copy_store(u32 **buf, int reg, int off)
++{
++ if (cpu_has_64bit_gp_regs) {
++ uasm_i_sd(buf, reg, off, A0);
++ } else {
++ uasm_i_sw(buf, reg, off, A0);
++ }
++}
++
++static inline void build_copy_load_pref(u32 **buf, int off)
++{
++ if (off & cache_line_mask())
++ return;
++
++ if (pref_bias_copy_load)
++ uasm_i_pref(buf, pref_src_mode, pref_bias_copy_load + off, A1);
++}
++
++static inline void build_copy_store_pref(u32 **buf, int off)
++{
++ if (off & cache_line_mask())
++ return;
++
++ if (pref_bias_copy_store) {
++ uasm_i_pref(buf, pref_dst_mode, pref_bias_copy_store + off,
++ A0);
++ } else if (cpu_has_cache_cdex_s) {
++ uasm_i_cache(buf, Create_Dirty_Excl_SD, off, A0);
++ } else if (cpu_has_cache_cdex_p) {
++ if (R4600_V1_HIT_CACHEOP_WAR && cpu_is_r4600_v1_x()) {
++ uasm_i_nop(buf);
++ uasm_i_nop(buf);
++ uasm_i_nop(buf);
++ uasm_i_nop(buf);
++ }
++
++ if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
++ uasm_i_lw(buf, ZERO, ZERO, AT);
++
++ uasm_i_cache(buf, Create_Dirty_Excl_D, off, A0);
++ }
++}
++
++void __cpuinit build_copy_page(void)
++{
++ int off;
++ u32 *buf = (u32 *)©_page_array;
++ struct uasm_label *l = labels;
++ struct uasm_reloc *r = relocs;
++ int i;
++
++ memset(labels, 0, sizeof(labels));
++ memset(relocs, 0, sizeof(relocs));
++
++ set_prefetch_parameters();
++
++ /*
++ * This algorithm makes the following assumptions:
++ * - All prefetch biases are multiples of 8 words.
++ * - The prefetch biases are less than one page.
++ * - The store prefetch bias isn't greater than the load
++ * prefetch bias.
++ */
++ BUG_ON(pref_bias_copy_load % (8 * copy_word_size));
++ BUG_ON(pref_bias_copy_store % (8 * copy_word_size));
++ BUG_ON(PAGE_SIZE < pref_bias_copy_load);
++ BUG_ON(pref_bias_copy_store > pref_bias_copy_load);
++
++ off = PAGE_SIZE - pref_bias_copy_load;
++ if (off > 0xffff || !pref_bias_copy_load)
++ pg_addiu(&buf, A2, A0, off);
++ else
++ uasm_i_ori(&buf, A2, A0, off);
++
++ if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
++ uasm_i_lui(&buf, AT, 0xa000);
++
++ off = min(8, pref_bias_copy_load / cache_line_size) * cache_line_size;
++ while (off) {
++ build_copy_load_pref(&buf, -off);
++ off -= cache_line_size;
++ }
++ off = min(8, pref_bias_copy_store / cache_line_size) * cache_line_size;
++ while (off) {
++ build_copy_store_pref(&buf, -off);
++ off -= cache_line_size;
++ }
++ uasm_l_copy_pref_both(&l, buf);
++ do {
++ build_copy_load_pref(&buf, off);
++ build_copy_load(&buf, T0, off);
++ build_copy_load_pref(&buf, off + copy_word_size);
++ build_copy_load(&buf, T1, off + copy_word_size);
++ build_copy_load_pref(&buf, off + 2 * copy_word_size);
++ build_copy_load(&buf, T2, off + 2 * copy_word_size);
++ build_copy_load_pref(&buf, off + 3 * copy_word_size);
++ build_copy_load(&buf, T3, off + 3 * copy_word_size);
++ build_copy_store_pref(&buf, off);
++ build_copy_store(&buf, T0, off);
++ build_copy_store_pref(&buf, off + copy_word_size);
++ build_copy_store(&buf, T1, off + copy_word_size);
++ build_copy_store_pref(&buf, off + 2 * copy_word_size);
++ build_copy_store(&buf, T2, off + 2 * copy_word_size);
++ build_copy_store_pref(&buf, off + 3 * copy_word_size);
++ build_copy_store(&buf, T3, off + 3 * copy_word_size);
++ off += 4 * copy_word_size;
++ } while (off < half_copy_loop_size);
++ pg_addiu(&buf, A1, A1, 2 * off);
++ pg_addiu(&buf, A0, A0, 2 * off);
++ off = -off;
++ do {
++ build_copy_load_pref(&buf, off);
++ build_copy_load(&buf, T0, off);
++ build_copy_load_pref(&buf, off + copy_word_size);
++ build_copy_load(&buf, T1, off + copy_word_size);
++ build_copy_load_pref(&buf, off + 2 * copy_word_size);
++ build_copy_load(&buf, T2, off + 2 * copy_word_size);
++ build_copy_load_pref(&buf, off + 3 * copy_word_size);
++ build_copy_load(&buf, T3, off + 3 * copy_word_size);
++ build_copy_store_pref(&buf, off);
++ build_copy_store(&buf, T0, off);
++ build_copy_store_pref(&buf, off + copy_word_size);
++ build_copy_store(&buf, T1, off + copy_word_size);
++ build_copy_store_pref(&buf, off + 2 * copy_word_size);
++ build_copy_store(&buf, T2, off + 2 * copy_word_size);
++ build_copy_store_pref(&buf, off + 3 * copy_word_size);
++ if (off == -(4 * copy_word_size))
++ uasm_il_bne(&buf, &r, A2, A0, label_copy_pref_both);
++ build_copy_store(&buf, T3, off + 3 * copy_word_size);
++ off += 4 * copy_word_size;
++ } while (off < 0);
++
++ if (pref_bias_copy_load - pref_bias_copy_store) {
++ pg_addiu(&buf, A2, A0,
++ pref_bias_copy_load - pref_bias_copy_store);
++ uasm_l_copy_pref_store(&l, buf);
++ off = 0;
++ do {
++ build_copy_load(&buf, T0, off);
++ build_copy_load(&buf, T1, off + copy_word_size);
++ build_copy_load(&buf, T2, off + 2 * copy_word_size);
++ build_copy_load(&buf, T3, off + 3 * copy_word_size);
++ build_copy_store_pref(&buf, off);
++ build_copy_store(&buf, T0, off);
++ build_copy_store_pref(&buf, off + copy_word_size);
++ build_copy_store(&buf, T1, off + copy_word_size);
++ build_copy_store_pref(&buf, off + 2 * copy_word_size);
++ build_copy_store(&buf, T2, off + 2 * copy_word_size);
++ build_copy_store_pref(&buf, off + 3 * copy_word_size);
++ build_copy_store(&buf, T3, off + 3 * copy_word_size);
++ off += 4 * copy_word_size;
++ } while (off < half_copy_loop_size);
++ pg_addiu(&buf, A1, A1, 2 * off);
++ pg_addiu(&buf, A0, A0, 2 * off);
++ off = -off;
++ do {
++ build_copy_load(&buf, T0, off);
++ build_copy_load(&buf, T1, off + copy_word_size);
++ build_copy_load(&buf, T2, off + 2 * copy_word_size);
++ build_copy_load(&buf, T3, off + 3 * copy_word_size);
++ build_copy_store_pref(&buf, off);
++ build_copy_store(&buf, T0, off);
++ build_copy_store_pref(&buf, off + copy_word_size);
++ build_copy_store(&buf, T1, off + copy_word_size);
++ build_copy_store_pref(&buf, off + 2 * copy_word_size);
++ build_copy_store(&buf, T2, off + 2 * copy_word_size);
++ build_copy_store_pref(&buf, off + 3 * copy_word_size);
++ if (off == -(4 * copy_word_size))
++ uasm_il_bne(&buf, &r, A2, A0,
++ label_copy_pref_store);
++ build_copy_store(&buf, T3, off + 3 * copy_word_size);
++ off += 4 * copy_word_size;
++ } while (off < 0);
++ }
++
++ if (pref_bias_copy_store) {
++ pg_addiu(&buf, A2, A0, pref_bias_copy_store);
++ uasm_l_copy_nopref(&l, buf);
++ off = 0;
++ do {
++ build_copy_load(&buf, T0, off);
++ build_copy_load(&buf, T1, off + copy_word_size);
++ build_copy_load(&buf, T2, off + 2 * copy_word_size);
++ build_copy_load(&buf, T3, off + 3 * copy_word_size);
++ build_copy_store(&buf, T0, off);
++ build_copy_store(&buf, T1, off + copy_word_size);
++ build_copy_store(&buf, T2, off + 2 * copy_word_size);
++ build_copy_store(&buf, T3, off + 3 * copy_word_size);
++ off += 4 * copy_word_size;
++ } while (off < half_copy_loop_size);
++ pg_addiu(&buf, A1, A1, 2 * off);
++ pg_addiu(&buf, A0, A0, 2 * off);
++ off = -off;
++ do {
++ build_copy_load(&buf, T0, off);
++ build_copy_load(&buf, T1, off + copy_word_size);
++ build_copy_load(&buf, T2, off + 2 * copy_word_size);
++ build_copy_load(&buf, T3, off + 3 * copy_word_size);
++ build_copy_store(&buf, T0, off);
++ build_copy_store(&buf, T1, off + copy_word_size);
++ build_copy_store(&buf, T2, off + 2 * copy_word_size);
++ if (off == -(4 * copy_word_size))
++ uasm_il_bne(&buf, &r, A2, A0,
++ label_copy_nopref);
++ build_copy_store(&buf, T3, off + 3 * copy_word_size);
++ off += 4 * copy_word_size;
++ } while (off < 0);
++ }
++
++ uasm_i_jr(&buf, RA);
++ uasm_i_nop(&buf);
++
++ BUG_ON(buf > copy_page_array + ARRAY_SIZE(copy_page_array));
++
++ uasm_resolve_relocs(relocs, labels);
++
++ pr_debug("Synthesized copy page handler (%u instructions).\n",
++ (u32)(buf - copy_page_array));
++
++ pr_debug("\t.set push\n");
++ pr_debug("\t.set noreorder\n");
++ for (i = 0; i < (buf - copy_page_array); i++)
++ pr_debug("\t.word 0x%08x\n", copy_page_array[i]);
++ pr_debug("\t.set pop\n");
++}
++
++#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
++
++/*
++ * Pad descriptors to cacheline, since each is exclusively owned by a
++ * particular CPU.
++ */
++struct dmadscr {
++ u64 dscr_a;
++ u64 dscr_b;
++ u64 pad_a;
++ u64 pad_b;
++} ____cacheline_aligned_in_smp page_descr[DM_NUM_CHANNELS];
++
++void sb1_dma_init(void)
++{
++ int i;
++
++ for (i = 0; i < DM_NUM_CHANNELS; i++) {
++ const u64 base_val = CPHYSADDR((unsigned long)&page_descr[i]) |
++ V_DM_DSCR_BASE_RINGSZ(1);
++ void *base_reg = IOADDR(A_DM_REGISTER(i, R_DM_DSCR_BASE));
++
++ __raw_writeq(base_val, base_reg);
++ __raw_writeq(base_val | M_DM_DSCR_BASE_RESET, base_reg);
++ __raw_writeq(base_val | M_DM_DSCR_BASE_ENABL, base_reg);
++ }
++}
++
++void clear_page(void *page)
++{
++ u64 to_phys = CPHYSADDR((unsigned long)page);
++ unsigned int cpu = smp_processor_id();
++
++ /* if the page is not in KSEG0, use old way */
++ if ((long)KSEGX((unsigned long)page) != (long)CKSEG0)
++ return clear_page_cpu(page);
++
++ page_descr[cpu].dscr_a = to_phys | M_DM_DSCRA_ZERO_MEM |
++ M_DM_DSCRA_L2C_DEST | M_DM_DSCRA_INTERRUPT;
++ page_descr[cpu].dscr_b = V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE);
++ __raw_writeq(1, IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)));
++
++ /*
++ * Don't really want to do it this way, but there's no
++ * reliable way to delay completion detection.
++ */
++ while (!(__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)))
++ & M_DM_DSCR_BASE_INTERRUPT))
++ ;
++ __raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
++}
++
++void copy_page(void *to, void *from)
++{
++ u64 from_phys = CPHYSADDR((unsigned long)from);
++ u64 to_phys = CPHYSADDR((unsigned long)to);
++ unsigned int cpu = smp_processor_id();
++
++ /* if any page is not in KSEG0, use old way */
++ if ((long)KSEGX((unsigned long)to) != (long)CKSEG0
++ || (long)KSEGX((unsigned long)from) != (long)CKSEG0)
++ return copy_page_cpu(to, from);
++
++ page_descr[cpu].dscr_a = to_phys | M_DM_DSCRA_L2C_DEST |
++ M_DM_DSCRA_INTERRUPT;
++ page_descr[cpu].dscr_b = from_phys | V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE);
++ __raw_writeq(1, IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)));
++
++ /*
++ * Don't really want to do it this way, but there's no
++ * reliable way to delay completion detection.
++ */
++ while (!(__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)))
++ & M_DM_DSCR_BASE_INTERRUPT))
++ ;
++ __raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
++}
++
++#endif /* CONFIG_SIBYTE_DMA_PAGEOPS */
+diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c
+deleted file mode 100644
+index 455dedb..0000000
+--- a/arch/mips/mm/pg-r4k.c
++++ /dev/null
+@@ -1,534 +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) 2003, 04, 05 Ralf Baechle (ralf at linux-mips.org)
+- * Copyright (C) 2007 Maciej W. Rozycki
+- */
+-#include <linux/init.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/mm.h>
+-#include <linux/module.h>
+-#include <linux/proc_fs.h>
+-
+-#include <asm/bugs.h>
+-#include <asm/cacheops.h>
+-#include <asm/inst.h>
+-#include <asm/io.h>
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/prefetch.h>
+-#include <asm/system.h>
+-#include <asm/bootinfo.h>
+-#include <asm/mipsregs.h>
+-#include <asm/mmu_context.h>
+-#include <asm/cpu.h>
+-#include <asm/war.h>
+-
+-#define half_scache_line_size() (cpu_scache_line_size() >> 1)
+-#define cpu_is_r4600_v1_x() ((read_c0_prid() & 0xfffffff0) == 0x00002010)
+-#define cpu_is_r4600_v2_x() ((read_c0_prid() & 0xfffffff0) == 0x00002020)
+-
+-
+-/*
+- * Maximum sizes:
+- *
+- * R4000 128 bytes S-cache: 0x58 bytes
+- * R4600 v1.7: 0x5c bytes
+- * R4600 v2.0: 0x60 bytes
+- * With prefetching, 16 byte strides 0xa0 bytes
+- */
+-
+-static unsigned int clear_page_array[0x130 / 4];
+-
+-void clear_page(void * page) __attribute__((alias("clear_page_array")));
+-
+-EXPORT_SYMBOL(clear_page);
+-
+-/*
+- * Maximum sizes:
+- *
+- * R4000 128 bytes S-cache: 0x11c bytes
+- * R4600 v1.7: 0x080 bytes
+- * R4600 v2.0: 0x07c bytes
+- * With prefetching, 16 byte strides 0x0b8 bytes
+- */
+-static unsigned int copy_page_array[0x148 / 4];
+-
+-void copy_page(void *to, void *from) __attribute__((alias("copy_page_array")));
+-
+-EXPORT_SYMBOL(copy_page);
+-
+-/*
+- * This is suboptimal for 32-bit kernels; we assume that R10000 is only used
+- * with 64-bit kernels. The prefetch offsets have been experimentally tuned
+- * an Origin 200.
+- */
+-static int pref_offset_clear __cpuinitdata = 512;
+-static int pref_offset_copy __cpuinitdata = 256;
+-
+-static unsigned int pref_src_mode __cpuinitdata;
+-static unsigned int pref_dst_mode __cpuinitdata;
+-
+-static int load_offset __cpuinitdata;
+-static int store_offset __cpuinitdata;
+-
+-static unsigned int __cpuinitdata *dest, *epc;
+-
+-static unsigned int instruction_pending;
+-static union mips_instruction delayed_mi;
+-
+-static void __cpuinit emit_instruction(union mips_instruction mi)
+-{
+- if (instruction_pending)
+- *epc++ = delayed_mi.word;
+-
+- instruction_pending = 1;
+- delayed_mi = mi;
+-}
+-
+-static inline void flush_delay_slot_or_nop(void)
+-{
+- if (instruction_pending) {
+- *epc++ = delayed_mi.word;
+- instruction_pending = 0;
+- return;
+- }
+-
+- *epc++ = 0;
+-}
+-
+-static inline unsigned int *label(void)
+-{
+- if (instruction_pending) {
+- *epc++ = delayed_mi.word;
+- instruction_pending = 0;
+- }
+-
+- return epc;
+-}
+-
+-static inline void build_insn_word(unsigned int word)
+-{
+- union mips_instruction mi;
+-
+- mi.word = word;
+-
+- emit_instruction(mi);
+-}
+-
+-static inline void build_nop(void)
+-{
+- build_insn_word(0); /* nop */
+-}
+-
+-static inline void build_src_pref(int advance)
+-{
+- if (!(load_offset & (cpu_dcache_line_size() - 1)) && advance) {
+- union mips_instruction mi;
+-
+- mi.i_format.opcode = pref_op;
+- mi.i_format.rs = 5; /* $a1 */
+- mi.i_format.rt = pref_src_mode;
+- mi.i_format.simmediate = load_offset + advance;
+-
+- emit_instruction(mi);
+- }
+-}
+-
+-static inline void __build_load_reg(int reg)
+-{
+- union mips_instruction mi;
+- unsigned int width;
+-
+- if (cpu_has_64bit_gp_regs) {
+- mi.i_format.opcode = ld_op;
+- width = 8;
+- } else {
+- mi.i_format.opcode = lw_op;
+- width = 4;
+- }
+- mi.i_format.rs = 5; /* $a1 */
+- mi.i_format.rt = reg; /* $reg */
+- mi.i_format.simmediate = load_offset;
+-
+- load_offset += width;
+- emit_instruction(mi);
+-}
+-
+-static inline void build_load_reg(int reg)
+-{
+- if (cpu_has_prefetch)
+- build_src_pref(pref_offset_copy);
+-
+- __build_load_reg(reg);
+-}
+-
+-static inline void build_dst_pref(int advance)
+-{
+- if (!(store_offset & (cpu_dcache_line_size() - 1)) && advance) {
+- union mips_instruction mi;
+-
+- mi.i_format.opcode = pref_op;
+- mi.i_format.rs = 4; /* $a0 */
+- mi.i_format.rt = pref_dst_mode;
+- mi.i_format.simmediate = store_offset + advance;
+-
+- emit_instruction(mi);
+- }
+-}
+-
+-static inline void build_cdex_s(void)
+-{
+- union mips_instruction mi;
+-
+- if ((store_offset & (cpu_scache_line_size() - 1)))
+- return;
+-
+- mi.c_format.opcode = cache_op;
+- mi.c_format.rs = 4; /* $a0 */
+- mi.c_format.c_op = 3; /* Create Dirty Exclusive */
+- mi.c_format.cache = 3; /* Secondary Data Cache */
+- mi.c_format.simmediate = store_offset;
+-
+- emit_instruction(mi);
+-}
+-
+-static inline void build_cdex_p(void)
+-{
+- union mips_instruction mi;
+-
+- if (store_offset & (cpu_dcache_line_size() - 1))
+- return;
+-
+- if (R4600_V1_HIT_CACHEOP_WAR && cpu_is_r4600_v1_x()) {
+- build_nop();
+- build_nop();
+- build_nop();
+- build_nop();
+- }
+-
+- if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
+- build_insn_word(0x8c200000); /* lw $zero, ($at) */
+-
+- mi.c_format.opcode = cache_op;
+- mi.c_format.rs = 4; /* $a0 */
+- mi.c_format.c_op = 3; /* Create Dirty Exclusive */
+- mi.c_format.cache = 1; /* Data Cache */
+- mi.c_format.simmediate = store_offset;
+-
+- emit_instruction(mi);
+-}
+-
+-static void __cpuinit __build_store_reg(int reg)
+-{
+- union mips_instruction mi;
+- unsigned int width;
+-
+- if (cpu_has_64bit_gp_regs ||
+- (cpu_has_64bit_zero_reg && reg == 0)) {
+- mi.i_format.opcode = sd_op;
+- width = 8;
+- } else {
+- mi.i_format.opcode = sw_op;
+- width = 4;
+- }
+- mi.i_format.rs = 4; /* $a0 */
+- mi.i_format.rt = reg; /* $reg */
+- mi.i_format.simmediate = store_offset;
+-
+- store_offset += width;
+- emit_instruction(mi);
+-}
+-
+-static inline void build_store_reg(int reg)
+-{
+- int pref_off = cpu_has_prefetch ?
+- (reg ? pref_offset_copy : pref_offset_clear) : 0;
+- if (pref_off)
+- build_dst_pref(pref_off);
+- else if (cpu_has_cache_cdex_s)
+- build_cdex_s();
+- else if (cpu_has_cache_cdex_p)
+- build_cdex_p();
+-
+- __build_store_reg(reg);
+-}
+-
+-static inline void build_addiu_rt_rs(unsigned int rt, unsigned int rs,
+- unsigned long offset)
+-{
+- union mips_instruction mi;
+-
+- BUG_ON(offset > 0x7fff);
+-
+- if (cpu_has_64bit_gp_regs && DADDI_WAR && r4k_daddiu_bug()) {
+- mi.i_format.opcode = addiu_op;
+- mi.i_format.rs = 0; /* $zero */
+- mi.i_format.rt = 25; /* $t9 */
+- mi.i_format.simmediate = offset;
+- emit_instruction(mi);
+-
+- mi.r_format.opcode = spec_op;
+- mi.r_format.rs = rs;
+- mi.r_format.rt = 25; /* $t9 */
+- mi.r_format.rd = rt;
+- mi.r_format.re = 0;
+- mi.r_format.func = daddu_op;
+- } else {
+- mi.i_format.opcode = cpu_has_64bit_gp_regs ?
+- daddiu_op : addiu_op;
+- mi.i_format.rs = rs;
+- mi.i_format.rt = rt;
+- mi.i_format.simmediate = offset;
+- }
+- emit_instruction(mi);
+-}
+-
+-static inline void build_addiu_a2_a0(unsigned long offset)
+-{
+- build_addiu_rt_rs(6, 4, offset); /* $a2, $a0, offset */
+-}
+-
+-static inline void build_addiu_a2(unsigned long offset)
+-{
+- build_addiu_rt_rs(6, 6, offset); /* $a2, $a2, offset */
+-}
+-
+-static inline void build_addiu_a1(unsigned long offset)
+-{
+- build_addiu_rt_rs(5, 5, offset); /* $a1, $a1, offset */
+-
+- load_offset -= offset;
+-}
+-
+-static inline void build_addiu_a0(unsigned long offset)
+-{
+- build_addiu_rt_rs(4, 4, offset); /* $a0, $a0, offset */
+-
+- store_offset -= offset;
+-}
+-
+-static inline void build_bne(unsigned int *dest)
+-{
+- union mips_instruction mi;
+-
+- mi.i_format.opcode = bne_op;
+- mi.i_format.rs = 6; /* $a2 */
+- mi.i_format.rt = 4; /* $a0 */
+- mi.i_format.simmediate = dest - epc - 1;
+-
+- *epc++ = mi.word;
+- flush_delay_slot_or_nop();
+-}
+-
+-static inline void build_jr_ra(void)
+-{
+- union mips_instruction mi;
+-
+- mi.r_format.opcode = spec_op;
+- mi.r_format.rs = 31;
+- mi.r_format.rt = 0;
+- mi.r_format.rd = 0;
+- mi.r_format.re = 0;
+- mi.r_format.func = jr_op;
+-
+- *epc++ = mi.word;
+- flush_delay_slot_or_nop();
+-}
+-
+-void __cpuinit build_clear_page(void)
+-{
+- unsigned int loop_start;
+- unsigned long off;
+- int i;
+-
+- epc = (unsigned int *) &clear_page_array;
+- instruction_pending = 0;
+- store_offset = 0;
+-
+- if (cpu_has_prefetch) {
+- switch (current_cpu_type()) {
+- case CPU_TX49XX:
+- /* TX49 supports only Pref_Load */
+- pref_offset_clear = 0;
+- pref_offset_copy = 0;
+- break;
+-
+- case CPU_RM9000:
+- /*
+- * As a workaround for erratum G105 which make the
+- * PrepareForStore hint unusable we fall back to
+- * StoreRetained on the RM9000. Once it is known which
+- * versions of the RM9000 we'll be able to condition-
+- * alize this.
+- */
+-
+- case CPU_R10000:
+- case CPU_R12000:
+- case CPU_R14000:
+- pref_src_mode = Pref_LoadStreamed;
+- pref_dst_mode = Pref_StoreStreamed;
+- break;
+-
+- default:
+- pref_src_mode = Pref_LoadStreamed;
+- pref_dst_mode = Pref_PrepareForStore;
+- break;
+- }
+- }
+-
+- off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0);
+- if (off > 0x7fff) {
+- build_addiu_a2_a0(off >> 1);
+- build_addiu_a2(off >> 1);
+- } else
+- build_addiu_a2_a0(off);
+-
+- if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
+- build_insn_word(0x3c01a000); /* lui $at, 0xa000 */
+-
+-dest = label();
+- do {
+- build_store_reg(0);
+- build_store_reg(0);
+- build_store_reg(0);
+- build_store_reg(0);
+- } while (store_offset < half_scache_line_size());
+- build_addiu_a0(2 * store_offset);
+- loop_start = store_offset;
+- do {
+- build_store_reg(0);
+- build_store_reg(0);
+- build_store_reg(0);
+- build_store_reg(0);
+- } while ((store_offset - loop_start) < half_scache_line_size());
+- build_bne(dest);
+-
+- if (cpu_has_prefetch && pref_offset_clear) {
+- build_addiu_a2_a0(pref_offset_clear);
+- dest = label();
+- loop_start = store_offset;
+- do {
+- __build_store_reg(0);
+- __build_store_reg(0);
+- __build_store_reg(0);
+- __build_store_reg(0);
+- } while ((store_offset - loop_start) < half_scache_line_size());
+- build_addiu_a0(2 * store_offset);
+- loop_start = store_offset;
+- do {
+- __build_store_reg(0);
+- __build_store_reg(0);
+- __build_store_reg(0);
+- __build_store_reg(0);
+- } while ((store_offset - loop_start) < half_scache_line_size());
+- build_bne(dest);
+- }
+-
+- build_jr_ra();
+-
+- BUG_ON(epc > clear_page_array + ARRAY_SIZE(clear_page_array));
+-
+- pr_info("Synthesized clear page handler (%u instructions).\n",
+- (unsigned int)(epc - clear_page_array));
+-
+- pr_debug("\t.set push\n");
+- pr_debug("\t.set noreorder\n");
+- for (i = 0; i < (epc - clear_page_array); i++)
+- pr_debug("\t.word 0x%08x\n", clear_page_array[i]);
+- pr_debug("\t.set pop\n");
+-}
+-
+-void __cpuinit build_copy_page(void)
+-{
+- unsigned int loop_start;
+- unsigned long off;
+- int i;
+-
+- epc = (unsigned int *) ©_page_array;
+- store_offset = load_offset = 0;
+- instruction_pending = 0;
+-
+- off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0);
+- if (off > 0x7fff) {
+- build_addiu_a2_a0(off >> 1);
+- build_addiu_a2(off >> 1);
+- } else
+- build_addiu_a2_a0(off);
+-
+- if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
+- build_insn_word(0x3c01a000); /* lui $at, 0xa000 */
+-
+-dest = label();
+- loop_start = store_offset;
+- do {
+- build_load_reg( 8);
+- build_load_reg( 9);
+- build_load_reg(10);
+- build_load_reg(11);
+- build_store_reg( 8);
+- build_store_reg( 9);
+- build_store_reg(10);
+- build_store_reg(11);
+- } while ((store_offset - loop_start) < half_scache_line_size());
+- build_addiu_a0(2 * store_offset);
+- build_addiu_a1(2 * load_offset);
+- loop_start = store_offset;
+- do {
+- build_load_reg( 8);
+- build_load_reg( 9);
+- build_load_reg(10);
+- build_load_reg(11);
+- build_store_reg( 8);
+- build_store_reg( 9);
+- build_store_reg(10);
+- build_store_reg(11);
+- } while ((store_offset - loop_start) < half_scache_line_size());
+- build_bne(dest);
+-
+- if (cpu_has_prefetch && pref_offset_copy) {
+- build_addiu_a2_a0(pref_offset_copy);
+- dest = label();
+- loop_start = store_offset;
+- do {
+- __build_load_reg( 8);
+- __build_load_reg( 9);
+- __build_load_reg(10);
+- __build_load_reg(11);
+- __build_store_reg( 8);
+- __build_store_reg( 9);
+- __build_store_reg(10);
+- __build_store_reg(11);
+- } while ((store_offset - loop_start) < half_scache_line_size());
+- build_addiu_a0(2 * store_offset);
+- build_addiu_a1(2 * load_offset);
+- loop_start = store_offset;
+- do {
+- __build_load_reg( 8);
+- __build_load_reg( 9);
+- __build_load_reg(10);
+- __build_load_reg(11);
+- __build_store_reg( 8);
+- __build_store_reg( 9);
+- __build_store_reg(10);
+- __build_store_reg(11);
+- } while ((store_offset - loop_start) < half_scache_line_size());
+- build_bne(dest);
+- }
+-
+- build_jr_ra();
+-
+- BUG_ON(epc > copy_page_array + ARRAY_SIZE(copy_page_array));
+-
+- pr_info("Synthesized copy page handler (%u instructions).\n",
+- (unsigned int)(epc - copy_page_array));
+-
+- pr_debug("\t.set push\n");
+- pr_debug("\t.set noreorder\n");
+- for (i = 0; i < (epc - copy_page_array); i++)
+- pr_debug("\t.word 0x%08x\n", copy_page_array[i]);
+- pr_debug("\t.set pop\n");
+-}
+diff --git a/arch/mips/mm/pg-sb1.c b/arch/mips/mm/pg-sb1.c
+deleted file mode 100644
+index 49e289d..0000000
+--- a/arch/mips/mm/pg-sb1.c
++++ /dev/null
+@@ -1,302 +0,0 @@
+-/*
+- * Copyright (C) 1996 David S. Miller (dm at engr.sgi.com)
+- * Copyright (C) 1997, 2001 Ralf Baechle (ralf at gnu.org)
+- * Copyright (C) 2000 SiByte, Inc.
+- * Copyright (C) 2005 Thiemo Seufer
+- *
+- * Written by Justin Carlson of SiByte, Inc.
+- * and Kip Walker of Broadcom 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.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+- */
+-#include <linux/module.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-
+-#include <asm/io.h>
+-#include <asm/sibyte/sb1250.h>
+-#include <asm/sibyte/sb1250_regs.h>
+-#include <asm/sibyte/sb1250_dma.h>
+-
+-#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
+-#define SB1_PREF_LOAD_STREAMED_HINT "0"
+-#define SB1_PREF_STORE_STREAMED_HINT "1"
+-#else
+-#define SB1_PREF_LOAD_STREAMED_HINT "4"
+-#define SB1_PREF_STORE_STREAMED_HINT "5"
+-#endif
+-
+-static inline void clear_page_cpu(void *page)
+-{
+- unsigned char *addr = (unsigned char *) page;
+- unsigned char *end = addr + PAGE_SIZE;
+-
+- /*
+- * JDCXXX - This should be bottlenecked by the write buffer, but these
+- * things tend to be mildly unpredictable...should check this on the
+- * performance model
+- *
+- * We prefetch 4 lines ahead. We're also "cheating" slightly here...
+- * since we know we're on an SB1, we force the assembler to take
+- * 64-bit operands to speed things up
+- */
+- __asm__ __volatile__(
+- " .set push \n"
+- " .set mips4 \n"
+- " .set noreorder \n"
+-#ifdef CONFIG_CPU_HAS_PREFETCH
+- " daddiu %0, %0, 128 \n"
+- " pref " SB1_PREF_STORE_STREAMED_HINT ", -128(%0) \n"
+- /* Prefetch the first 4 lines */
+- " pref " SB1_PREF_STORE_STREAMED_HINT ", -96(%0) \n"
+- " pref " SB1_PREF_STORE_STREAMED_HINT ", -64(%0) \n"
+- " pref " SB1_PREF_STORE_STREAMED_HINT ", -32(%0) \n"
+- "1: sd $0, -128(%0) \n" /* Throw out a cacheline of 0's */
+- " sd $0, -120(%0) \n"
+- " sd $0, -112(%0) \n"
+- " sd $0, -104(%0) \n"
+- " daddiu %0, %0, 32 \n"
+- " bnel %0, %1, 1b \n"
+- " pref " SB1_PREF_STORE_STREAMED_HINT ", -32(%0) \n"
+- " daddiu %0, %0, -128 \n"
+-#endif
+- " sd $0, 0(%0) \n" /* Throw out a cacheline of 0's */
+- "1: sd $0, 8(%0) \n"
+- " sd $0, 16(%0) \n"
+- " sd $0, 24(%0) \n"
+- " daddiu %0, %0, 32 \n"
+- " bnel %0, %1, 1b \n"
+- " sd $0, 0(%0) \n"
+- " .set pop \n"
+- : "+r" (addr)
+- : "r" (end)
+- : "memory");
+-}
+-
+-static inline void copy_page_cpu(void *to, void *from)
+-{
+- unsigned char *src = (unsigned char *)from;
+- unsigned char *dst = (unsigned char *)to;
+- unsigned char *end = src + PAGE_SIZE;
+-
+- /*
+- * The pref's used here are using "streaming" hints, which cause the
+- * copied data to be kicked out of the cache sooner. A page copy often
+- * ends up copying a lot more data than is commonly used, so this seems
+- * to make sense in terms of reducing cache pollution, but I've no real
+- * performance data to back this up
+- */
+- __asm__ __volatile__(
+- " .set push \n"
+- " .set mips4 \n"
+- " .set noreorder \n"
+-#ifdef CONFIG_CPU_HAS_PREFETCH
+- " daddiu %0, %0, 128 \n"
+- " daddiu %1, %1, 128 \n"
+- " pref " SB1_PREF_LOAD_STREAMED_HINT ", -128(%0)\n"
+- /* Prefetch the first 4 lines */
+- " pref " SB1_PREF_STORE_STREAMED_HINT ", -128(%1)\n"
+- " pref " SB1_PREF_LOAD_STREAMED_HINT ", -96(%0)\n"
+- " pref " SB1_PREF_STORE_STREAMED_HINT ", -96(%1)\n"
+- " pref " SB1_PREF_LOAD_STREAMED_HINT ", -64(%0)\n"
+- " pref " SB1_PREF_STORE_STREAMED_HINT ", -64(%1)\n"
+- " pref " SB1_PREF_LOAD_STREAMED_HINT ", -32(%0)\n"
+- "1: pref " SB1_PREF_STORE_STREAMED_HINT ", -32(%1)\n"
+-# ifdef CONFIG_64BIT
+- " ld $8, -128(%0) \n" /* Block copy a cacheline */
+- " ld $9, -120(%0) \n"
+- " ld $10, -112(%0) \n"
+- " ld $11, -104(%0) \n"
+- " sd $8, -128(%1) \n"
+- " sd $9, -120(%1) \n"
+- " sd $10, -112(%1) \n"
+- " sd $11, -104(%1) \n"
+-# else
+- " lw $2, -128(%0) \n" /* Block copy a cacheline */
+- " lw $3, -124(%0) \n"
+- " lw $6, -120(%0) \n"
+- " lw $7, -116(%0) \n"
+- " lw $8, -112(%0) \n"
+- " lw $9, -108(%0) \n"
+- " lw $10, -104(%0) \n"
+- " lw $11, -100(%0) \n"
+- " sw $2, -128(%1) \n"
+- " sw $3, -124(%1) \n"
+- " sw $6, -120(%1) \n"
+- " sw $7, -116(%1) \n"
+- " sw $8, -112(%1) \n"
+- " sw $9, -108(%1) \n"
+- " sw $10, -104(%1) \n"
+- " sw $11, -100(%1) \n"
+-# endif
+- " daddiu %0, %0, 32 \n"
+- " daddiu %1, %1, 32 \n"
+- " bnel %0, %2, 1b \n"
+- " pref " SB1_PREF_LOAD_STREAMED_HINT ", -32(%0)\n"
+- " daddiu %0, %0, -128 \n"
+- " daddiu %1, %1, -128 \n"
+-#endif
+-#ifdef CONFIG_64BIT
+- " ld $8, 0(%0) \n" /* Block copy a cacheline */
+- "1: ld $9, 8(%0) \n"
+- " ld $10, 16(%0) \n"
+- " ld $11, 24(%0) \n"
+- " sd $8, 0(%1) \n"
+- " sd $9, 8(%1) \n"
+- " sd $10, 16(%1) \n"
+- " sd $11, 24(%1) \n"
+-#else
+- " lw $2, 0(%0) \n" /* Block copy a cacheline */
+- "1: lw $3, 4(%0) \n"
+- " lw $6, 8(%0) \n"
+- " lw $7, 12(%0) \n"
+- " lw $8, 16(%0) \n"
+- " lw $9, 20(%0) \n"
+- " lw $10, 24(%0) \n"
+- " lw $11, 28(%0) \n"
+- " sw $2, 0(%1) \n"
+- " sw $3, 4(%1) \n"
+- " sw $6, 8(%1) \n"
+- " sw $7, 12(%1) \n"
+- " sw $8, 16(%1) \n"
+- " sw $9, 20(%1) \n"
+- " sw $10, 24(%1) \n"
+- " sw $11, 28(%1) \n"
+-#endif
+- " daddiu %0, %0, 32 \n"
+- " daddiu %1, %1, 32 \n"
+- " bnel %0, %2, 1b \n"
+-#ifdef CONFIG_64BIT
+- " ld $8, 0(%0) \n"
+-#else
+- " lw $2, 0(%0) \n"
+-#endif
+- " .set pop \n"
+- : "+r" (src), "+r" (dst)
+- : "r" (end)
+-#ifdef CONFIG_64BIT
+- : "$8", "$9", "$10", "$11", "memory");
+-#else
+- : "$2", "$3", "$6", "$7", "$8", "$9", "$10", "$11", "memory");
+-#endif
+-}
+-
+-
+-#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
+-
+-/*
+- * Pad descriptors to cacheline, since each is exclusively owned by a
+- * particular CPU.
+- */
+-typedef struct dmadscr_s {
+- u64 dscr_a;
+- u64 dscr_b;
+- u64 pad_a;
+- u64 pad_b;
+-} dmadscr_t;
+-
+-static dmadscr_t page_descr[DM_NUM_CHANNELS]
+- __attribute__((aligned(SMP_CACHE_BYTES)));
+-
+-void sb1_dma_init(void)
+-{
+- int i;
+-
+- for (i = 0; i < DM_NUM_CHANNELS; i++) {
+- const u64 base_val = CPHYSADDR((unsigned long)&page_descr[i]) |
+- V_DM_DSCR_BASE_RINGSZ(1);
+- void *base_reg = IOADDR(A_DM_REGISTER(i, R_DM_DSCR_BASE));
+-
+- __raw_writeq(base_val, base_reg);
+- __raw_writeq(base_val | M_DM_DSCR_BASE_RESET, base_reg);
+- __raw_writeq(base_val | M_DM_DSCR_BASE_ENABL, base_reg);
+- }
+-}
+-
+-void clear_page(void *page)
+-{
+- u64 to_phys = CPHYSADDR((unsigned long)page);
+- unsigned int cpu = smp_processor_id();
+-
+- /* if the page is not in KSEG0, use old way */
+- if ((long)KSEGX((unsigned long)page) != (long)CKSEG0)
+- return clear_page_cpu(page);
+-
+- page_descr[cpu].dscr_a = to_phys | M_DM_DSCRA_ZERO_MEM |
+- M_DM_DSCRA_L2C_DEST | M_DM_DSCRA_INTERRUPT;
+- page_descr[cpu].dscr_b = V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE);
+- __raw_writeq(1, IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)));
+-
+- /*
+- * Don't really want to do it this way, but there's no
+- * reliable way to delay completion detection.
+- */
+- while (!(__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)))
+- & M_DM_DSCR_BASE_INTERRUPT))
+- ;
+- __raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
+-}
+-
+-void copy_page(void *to, void *from)
+-{
+- u64 from_phys = CPHYSADDR((unsigned long)from);
+- u64 to_phys = CPHYSADDR((unsigned long)to);
+- unsigned int cpu = smp_processor_id();
+-
+- /* if any page is not in KSEG0, use old way */
+- if ((long)KSEGX((unsigned long)to) != (long)CKSEG0
+- || (long)KSEGX((unsigned long)from) != (long)CKSEG0)
+- return copy_page_cpu(to, from);
+-
+- page_descr[cpu].dscr_a = to_phys | M_DM_DSCRA_L2C_DEST |
+- M_DM_DSCRA_INTERRUPT;
+- page_descr[cpu].dscr_b = from_phys | V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE);
+- __raw_writeq(1, IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)));
+-
+- /*
+- * Don't really want to do it this way, but there's no
+- * reliable way to delay completion detection.
+- */
+- while (!(__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)))
+- & M_DM_DSCR_BASE_INTERRUPT))
+- ;
+- __raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
+-}
+-
+-#else /* !CONFIG_SIBYTE_DMA_PAGEOPS */
+-
+-void clear_page(void *page)
+-{
+- return clear_page_cpu(page);
+-}
+-
+-void copy_page(void *to, void *from)
+-{
+- return copy_page_cpu(to, from);
+-}
+-
+-#endif /* !CONFIG_SIBYTE_DMA_PAGEOPS */
+-
+-EXPORT_SYMBOL(clear_page);
+-EXPORT_SYMBOL(copy_page);
+-
+-void __cpuinit build_clear_page(void)
+-{
+-}
+-
+-void __cpuinit build_copy_page(void)
+-{
+-}
+diff --git a/arch/mips/mm/pgtable.c b/arch/mips/mm/pgtable.c
+index 57df1c3..7dfa579 100644
+--- a/arch/mips/mm/pgtable.c
++++ b/arch/mips/mm/pgtable.c
+@@ -12,7 +12,6 @@ void show_mem(void)
- i2c at 3000 {
-@@ -76,8 +77,8 @@
- #size-cells = <0>;
- cell-index = <0>;
- compatible = "fsl-i2c";
-- reg = <3000 100>;
-- interrupts = <2b 2>;
-+ reg = <0x3000 0x100>;
-+ interrupts = <43 2>;
- interrupt-parent = <&mpic>;
- dfsrr;
- };
-@@ -86,24 +87,24 @@
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "fsl,gianfar-mdio";
-- reg = <24520 20>;
-+ reg = <0x24520 0x20>;
+ printk("Mem-info:\n");
+ show_free_areas();
+- printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ pfn = max_mapnr;
+ while (pfn-- > 0) {
+ if (!pfn_valid(pfn))
+diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
+index 63065d6..5ce2fa7 100644
+--- a/arch/mips/mm/tlb-r4k.c
++++ b/arch/mips/mm/tlb-r4k.c
+@@ -299,7 +299,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
+ idx = read_c0_index();
+ ptep = pte_offset_map(pmdp, address);
+
+-#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
++#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+ write_c0_entrylo0(ptep->pte_high);
+ ptep++;
+ write_c0_entrylo1(ptep->pte_high);
+diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c
+index 1a6f770..1655aa6 100644
+--- a/arch/mips/mm/uasm.c
++++ b/arch/mips/mm/uasm.c
+@@ -58,13 +58,13 @@ enum opcode {
+ insn_invalid,
+ insn_addu, insn_addiu, insn_and, insn_andi, insn_beq,
+ insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl,
+- insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0,
+- insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32,
+- insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld,
+- insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0,
+- insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll,
+- insn_sra, insn_srl, insn_subu, insn_sw, insn_tlbp, insn_tlbwi,
+- insn_tlbwr, insn_xor, insn_xori
++ insn_bne, insn_cache, insn_daddu, insn_daddiu, insn_dmfc0,
++ insn_dmtc0, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl,
++ insn_dsrl32, insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr,
++ insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0,
++ insn_mtc0, insn_ori, insn_pref, insn_rfe, insn_sc, insn_scd,
++ insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw,
++ insn_tlbp, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori
+ };
+
+ struct insn {
+@@ -94,6 +94,7 @@ static struct insn insn_table[] __cpuinitdata = {
+ { insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM },
+ { insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM },
+ { insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
++ { insn_cache, M(cache_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+ { insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+ { insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
+ { insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET},
+@@ -116,6 +117,7 @@ static struct insn insn_table[] __cpuinitdata = {
+ { insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET},
+ { insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET},
+ { insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
++ { insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+ { insn_rfe, M(cop0_op, cop_op, 0, 0, 0, rfe_op), 0 },
+ { insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+ { insn_scd, M(scd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+@@ -337,6 +339,7 @@ I_u1s2(_bgezl)
+ I_u1s2(_bltz)
+ I_u1s2(_bltzl)
+ I_u1u2s3(_bne)
++I_u2s3u1(_cache)
+ I_u1u2u3(_dmfc0)
+ I_u1u2u3(_dmtc0)
+ I_u2u1s3(_daddiu)
+@@ -359,6 +362,7 @@ I_u2s3u1(_lw)
+ I_u1u2u3(_mfc0)
+ I_u1u2u3(_mtc0)
+ I_u2u1u3(_ori)
++I_u2s3u1(_pref)
+ I_0(_rfe)
+ I_u2s3u1(_sc)
+ I_u2s3u1(_scd)
+@@ -555,6 +559,14 @@ uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
+ }
+
+ void __cpuinit
++uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1,
++ unsigned int reg2, int lid)
++{
++ uasm_r_mips_pc16(r, *p, lid);
++ uasm_i_bne(p, reg1, reg2, 0);
++}
++
++void __cpuinit
+ uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
+ {
+ uasm_r_mips_pc16(r, *p, lid);
+diff --git a/arch/mips/mm/uasm.h b/arch/mips/mm/uasm.h
+index fe0574f..0d6a66f 100644
+--- a/arch/mips/mm/uasm.h
++++ b/arch/mips/mm/uasm.h
+@@ -55,6 +55,7 @@ Ip_u1s2(_bgezl);
+ Ip_u1s2(_bltz);
+ Ip_u1s2(_bltzl);
+ Ip_u1u2s3(_bne);
++Ip_u2s3u1(_cache);
+ Ip_u1u2u3(_dmfc0);
+ Ip_u1u2u3(_dmtc0);
+ Ip_u2u1s3(_daddiu);
+@@ -77,6 +78,7 @@ Ip_u2s3u1(_lw);
+ Ip_u1u2u3(_mfc0);
+ Ip_u1u2u3(_mtc0);
+ Ip_u2u1u3(_ori);
++Ip_u2s3u1(_pref);
+ Ip_0(_rfe);
+ Ip_u2s3u1(_sc);
+ Ip_u2s3u1(_scd);
+@@ -177,6 +179,8 @@ void uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
+ void uasm_il_b(u32 **p, struct uasm_reloc **r, int lid);
+ void uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
+ void uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
++void uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1,
++ unsigned int reg2, int lid);
+ void uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
+ void uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
+ void uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
+diff --git a/arch/mips/nxp/pnx8550/common/Makefile b/arch/mips/nxp/pnx8550/common/Makefile
+new file mode 100644
+index 0000000..31cc1a5
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/common/Makefile
+@@ -0,0 +1,29 @@
++#
++# Per Hallsmark, per.hallsmark at mvista.com
++#
++# ########################################################################
++#
++# This program is free software; you can distribute 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 it will be useful, but WITHOUT
++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++# for more details.
++#
++# You 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.
++#
++# #######################################################################
++#
++# Makefile for the PNX8550 specific kernel interface routines
++# under Linux.
++#
++
++obj-y := setup.o prom.o int.o reset.o time.o proc.o platform.o
++obj-$(CONFIG_PCI) += pci.o
++obj-$(CONFIG_KGDB) += gdb_hook.o
++
++EXTRA_CFLAGS += -Werror
+diff --git a/arch/mips/nxp/pnx8550/common/gdb_hook.c b/arch/mips/nxp/pnx8550/common/gdb_hook.c
+new file mode 100644
+index 0000000..ad4624f
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/common/gdb_hook.c
+@@ -0,0 +1,109 @@
++/*
++ * Carsten Langgaard, carstenl at mips.com
++ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
++ *
++ * ########################################################################
++ *
++ * This program is free software; you can distribute 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 it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ *
++ * You 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.
++ *
++ * ########################################################################
++ *
++ * This is the interface to the remote debugger stub.
++ *
++ */
++#include <linux/types.h>
++#include <linux/serial.h>
++#include <linux/serialP.h>
++#include <linux/serial_reg.h>
++#include <linux/serial_ip3106.h>
++
++#include <asm/serial.h>
++#include <asm/io.h>
++
++#include <uart.h>
++
++static struct serial_state rs_table[IP3106_NR_PORTS] = {
++};
++static struct async_struct kdb_port_info = {0};
++
++void rs_kgdb_hook(int tty_no)
++{
++ struct serial_state *ser = &rs_table[tty_no];
++
++ kdb_port_info.state = ser;
++ kdb_port_info.magic = SERIAL_MAGIC;
++ kdb_port_info.port = tty_no;
++ kdb_port_info.flags = ser->flags;
++
++ /*
++ * Clear all interrupts
++ */
++ /* Clear all the transmitter FIFO counters (pointer and status) */
++ ip3106_lcr(UART_BASE, tty_no) |= IP3106_UART_LCR_TX_RST;
++ /* Clear all the receiver FIFO counters (pointer and status) */
++ ip3106_lcr(UART_BASE, tty_no) |= IP3106_UART_LCR_RX_RST;
++ /* Clear all interrupts */
++ ip3106_iclr(UART_BASE, tty_no) = IP3106_UART_INT_ALLRX |
++ IP3106_UART_INT_ALLTX;
++
++ /*
++ * Now, initialize the UART
++ */
++ ip3106_lcr(UART_BASE, tty_no) = IP3106_UART_LCR_8BIT;
++ ip3106_baud(UART_BASE, tty_no) = 5; // 38400 Baud
++}
++
++int putDebugChar(char c)
++{
++ /* Wait until FIFO not full */
++ while (((ip3106_fifo(UART_BASE, kdb_port_info.port) & IP3106_UART_FIFO_TXFIFO) >> 16) >= 16)
++ ;
++ /* Send one char */
++ ip3106_fifo(UART_BASE, kdb_port_info.port) = c;
++
++ return 1;
++}
++
++char getDebugChar(void)
++{
++ char ch;
++
++ /* Wait until there is a char in the FIFO */
++ while (!((ip3106_fifo(UART_BASE, kdb_port_info.port) &
++ IP3106_UART_FIFO_RXFIFO) >> 8))
++ ;
++ /* Read one char */
++ ch = ip3106_fifo(UART_BASE, kdb_port_info.port) &
++ IP3106_UART_FIFO_RBRTHR;
++ /* Advance the RX FIFO read pointer */
++ ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_RX_NEXT;
++ return (ch);
++}
++
++void rs_disable_debug_interrupts(void)
++{
++ ip3106_ien(UART_BASE, kdb_port_info.port) = 0; /* Disable all interrupts */
++}
++
++void rs_enable_debug_interrupts(void)
++{
++ /* Clear all the transmitter FIFO counters (pointer and status) */
++ ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_TX_RST;
++ /* Clear all the receiver FIFO counters (pointer and status) */
++ ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_RX_RST;
++ /* Clear all interrupts */
++ ip3106_iclr(UART_BASE, kdb_port_info.port) = IP3106_UART_INT_ALLRX |
++ IP3106_UART_INT_ALLTX;
++ ip3106_ien(UART_BASE, kdb_port_info.port) = IP3106_UART_INT_ALLRX; /* Enable RX interrupts */
++}
+diff --git a/arch/mips/nxp/pnx8550/common/int.c b/arch/mips/nxp/pnx8550/common/int.c
+new file mode 100644
+index 0000000..aad0342
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/common/int.c
+@@ -0,0 +1,238 @@
++/*
++ *
++ * Copyright (C) 2005 Embedded Alley Solutions, Inc
++ * Ported to 2.6.
++ *
++ * Per Hallsmark, per.hallsmark at mvista.com
++ * Copyright (C) 2000, 2001 MIPS Technologies, Inc.
++ * Copyright (C) 2001 Ralf Baechle
++ *
++ * Cleaned up and bug fixing: Pete Popov, ppopov at embeddedalley.com
++ *
++ * This program is free software; you can distribute 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 it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
++ *
++ */
++#include <linux/compiler.h>
++#include <linux/init.h>
++#include <linux/irq.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/kernel_stat.h>
++#include <linux/random.h>
++#include <linux/module.h>
++
++#include <asm/io.h>
++#include <asm/gdb-stub.h>
++#include <int.h>
++#include <uart.h>
++
++/* default prio for interrupts */
++/* first one is a no-no so therefore always prio 0 (disabled) */
++static char gic_prio[PNX8550_INT_GIC_TOTINT] = {
++ 0, 1, 1, 1, 1, 15, 1, 1, 1, 1, // 0 - 9
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 10 - 19
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 20 - 29
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 30 - 39
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40 - 49
++ 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 50 - 59
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60 - 69
++ 1 // 70
++};
++
++static void hw0_irqdispatch(int irq)
++{
++ /* find out which interrupt */
++ irq = PNX8550_GIC_VECTOR_0 >> 3;
++
++ if (irq == 0) {
++ printk("hw0_irqdispatch: irq 0, spurious interrupt?\n");
++ return;
++ }
++ do_IRQ(PNX8550_INT_GIC_MIN + irq);
++}
++
++
++static void timer_irqdispatch(int irq)
++{
++ irq = (0x01c0 & read_c0_config7()) >> 6;
++
++ if (unlikely(irq == 0)) {
++ printk("timer_irqdispatch: irq 0, spurious interrupt?\n");
++ return;
++ }
++
++ if (irq & 0x1)
++ do_IRQ(PNX8550_INT_TIMER1);
++ if (irq & 0x2)
++ do_IRQ(PNX8550_INT_TIMER2);
++ if (irq & 0x4)
++ do_IRQ(PNX8550_INT_TIMER3);
++}
++
++asmlinkage void plat_irq_dispatch(void)
++{
++ unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
++
++ if (pending & STATUSF_IP2)
++ hw0_irqdispatch(2);
++ else if (pending & STATUSF_IP7) {
++ if (read_c0_config7() & 0x01c0)
++ timer_irqdispatch(7);
++ } else
++ spurious_interrupt();
++}
++
++static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
++{
++ unsigned long status = read_c0_status();
++
++ status &= ~((clr_mask & 0xFF) << 8);
++ status |= (set_mask & 0xFF) << 8;
++
++ write_c0_status(status);
++}
++
++static inline void mask_gic_int(unsigned int irq_nr)
++{
++ /* interrupt disabled, bit 26(WE_ENABLE)=1 and bit 16(enable)=0 */
++ PNX8550_GIC_REQ(irq_nr) = 1<<28; /* set priority to 0 */
++}
++
++static inline void unmask_gic_int(unsigned int irq_nr)
++{
++ /* set prio mask to lower four bits and enable interrupt */
++ PNX8550_GIC_REQ(irq_nr) = (1<<26 | 1<<16) | (1<<28) | gic_prio[irq_nr];
++}
++
++static inline void mask_irq(unsigned int irq_nr)
++{
++ if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) {
++ modify_cp0_intmask(1 << irq_nr, 0);
++ } else if ((PNX8550_INT_GIC_MIN <= irq_nr) &&
++ (irq_nr <= PNX8550_INT_GIC_MAX)) {
++ mask_gic_int(irq_nr - PNX8550_INT_GIC_MIN);
++ } else if ((PNX8550_INT_TIMER_MIN <= irq_nr) &&
++ (irq_nr <= PNX8550_INT_TIMER_MAX)) {
++ modify_cp0_intmask(1 << 7, 0);
++ } else {
++ printk("mask_irq: irq %d doesn't exist!\n", irq_nr);
++ }
++}
++
++static inline void unmask_irq(unsigned int irq_nr)
++{
++ if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) {
++ modify_cp0_intmask(0, 1 << irq_nr);
++ } else if ((PNX8550_INT_GIC_MIN <= irq_nr) &&
++ (irq_nr <= PNX8550_INT_GIC_MAX)) {
++ unmask_gic_int(irq_nr - PNX8550_INT_GIC_MIN);
++ } else if ((PNX8550_INT_TIMER_MIN <= irq_nr) &&
++ (irq_nr <= PNX8550_INT_TIMER_MAX)) {
++ modify_cp0_intmask(0, 1 << 7);
++ } else {
++ printk("mask_irq: irq %d doesn't exist!\n", irq_nr);
++ }
++}
++
++int pnx8550_set_gic_priority(int irq, int priority)
++{
++ int gic_irq = irq-PNX8550_INT_GIC_MIN;
++ int prev_priority = PNX8550_GIC_REQ(gic_irq) & 0xf;
++
++ gic_prio[gic_irq] = priority;
++ PNX8550_GIC_REQ(gic_irq) |= (0x10000000 | gic_prio[gic_irq]);
++
++ return prev_priority;
++}
++
++static struct irq_chip level_irq_type = {
++ .name = "PNX Level IRQ",
++ .ack = mask_irq,
++ .mask = mask_irq,
++ .mask_ack = mask_irq,
++ .unmask = unmask_irq,
++};
++
++static struct irqaction gic_action = {
++ .handler = no_action,
++ .flags = IRQF_DISABLED,
++ .name = "GIC",
++};
++
++static struct irqaction timer_action = {
++ .handler = no_action,
++ .flags = IRQF_DISABLED,
++ .name = "Timer",
++};
++
++void __init arch_init_irq(void)
++{
++ int i;
++ int configPR;
++
++ for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) {
++ set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq);
++ mask_irq(i); /* mask the irq just in case */
++ }
++
++ /* init of GIC/IPC interrupts */
++ /* should be done before cp0 since cp0 init enables the GIC int */
++ for (i = PNX8550_INT_GIC_MIN; i <= PNX8550_INT_GIC_MAX; i++) {
++ int gic_int_line = i - PNX8550_INT_GIC_MIN;
++ if (gic_int_line == 0 )
++ continue; // don't fiddle with int 0
++ /*
++ * enable change of TARGET, ENABLE and ACTIVE_LOW bits
++ * set TARGET 0 to route through hw0 interrupt
++ * set ACTIVE_LOW 0 active high (correct?)
++ *
++ * We really should setup an interrupt description table
++ * to do this nicely.
++ * Note, PCI INTA is active low on the bus, but inverted
++ * in the GIC, so to us it's active high.
++ */
++ PNX8550_GIC_REQ(i - PNX8550_INT_GIC_MIN) = 0x1E000000;
++
++ /* mask/priority is still 0 so we will not get any
++ * interrupts until it is unmasked */
++
++ set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq);
++ }
++
++ /* Priority level 0 */
++ PNX8550_GIC_PRIMASK_0 = PNX8550_GIC_PRIMASK_1 = 0;
++
++ /* Set int vector table address */
++ PNX8550_GIC_VECTOR_0 = PNX8550_GIC_VECTOR_1 = 0;
++
++ set_irq_chip_and_handler(MIPS_CPU_GIC_IRQ, &level_irq_type,
++ handle_level_irq);
++ setup_irq(MIPS_CPU_GIC_IRQ, &gic_action);
++
++ /* init of Timer interrupts */
++ for (i = PNX8550_INT_TIMER_MIN; i <= PNX8550_INT_TIMER_MAX; i++)
++ set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq);
++
++ /* Stop Timer 1-3 */
++ configPR = read_c0_config7();
++ configPR |= 0x00000038;
++ write_c0_config7(configPR);
++
++ set_irq_chip_and_handler(MIPS_CPU_TIMER_IRQ, &level_irq_type,
++ handle_level_irq);
++ setup_irq(MIPS_CPU_TIMER_IRQ, &timer_action);
++}
++
++EXPORT_SYMBOL(pnx8550_set_gic_priority);
+diff --git a/arch/mips/nxp/pnx8550/common/pci.c b/arch/mips/nxp/pnx8550/common/pci.c
+new file mode 100644
+index 0000000..eee4f3d
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/common/pci.c
+@@ -0,0 +1,133 @@
++/*
++ *
++ * BRIEF MODULE DESCRIPTION
++ *
++ * Author: source at mvista.com
++ *
++ * This program is free software; you can distribute 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 it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
++ */
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++
++#include <pci.h>
++#include <glb.h>
++#include <nand.h>
++
++static struct resource pci_io_resource = {
++ .start = PNX8550_PCIIO + 0x1000, /* reserve regacy I/O space */
++ .end = PNX8550_PCIIO + PNX8550_PCIIO_SIZE,
++ .name = "pci IO space",
++ .flags = IORESOURCE_IO
++};
++
++static struct resource pci_mem_resource = {
++ .start = PNX8550_PCIMEM,
++ .end = PNX8550_PCIMEM + PNX8550_PCIMEM_SIZE - 1,
++ .name = "pci memory space",
++ .flags = IORESOURCE_MEM
++};
++
++extern struct pci_ops pnx8550_pci_ops;
++
++static struct pci_controller pnx8550_controller = {
++ .pci_ops = &pnx8550_pci_ops,
++ .io_resource = &pci_io_resource,
++ .mem_resource = &pci_mem_resource,
++};
++
++/* Return the total size of DRAM-memory, (RANK0 + RANK1) */
++static inline unsigned long get_system_mem_size(void)
++{
++ /* Read IP2031_RANK0_ADDR_LO */
++ unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010);
++ /* Read IP2031_RANK1_ADDR_HI */
++ unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018);
++
++ return dram_r1_hi - dram_r0_lo + 1;
++}
++
++static int __init pnx8550_pci_setup(void)
++{
++ int pci_mem_code;
++ int mem_size = get_system_mem_size() >> 20;
++
++ /* Clear the Global 2 Register, PCI Inta Output Enable Registers
++ Bit 1:Enable DAC Powerdown
++ -> 0:DACs are enabled and are working normally
++ 1:DACs are powerdown
++ Bit 0:Enable of PCI inta output
++ -> 0 = Disable PCI inta output
++ 1 = Enable PCI inta output
++ */
++ PNX8550_GLB2_ENAB_INTA_O = 0;
++
++ /* Calc the PCI mem size code */
++ if (mem_size >= 128)
++ pci_mem_code = SIZE_128M;
++ else if (mem_size >= 64)
++ pci_mem_code = SIZE_64M;
++ else if (mem_size >= 32)
++ pci_mem_code = SIZE_32M;
++ else
++ pci_mem_code = SIZE_16M;
++
++ /* Set PCI_XIO registers */
++ outl(pci_mem_resource.start, PCI_BASE | PCI_BASE1_LO);
++ outl(pci_mem_resource.end + 1, PCI_BASE | PCI_BASE1_HI);
++ outl(pci_io_resource.start, PCI_BASE | PCI_BASE2_LO);
++ outl(pci_io_resource.end, PCI_BASE | PCI_BASE2_HI);
++
++ /* Send memory transaction via PCI_BASE2 */
++ outl(0x00000001, PCI_BASE | PCI_IO);
++
++ /* Unlock the setup register */
++ outl(0xca, PCI_BASE | PCI_UNLOCKREG);
++
++ /*
++ * BAR0 of PNX8550 (pci base 10) must be zero in order for ide
++ * to work, and in order for bus_to_baddr to work without any
++ * hacks.
++ */
++ outl(0x00000000, PCI_BASE | PCI_BASE10);
++
++ /*
++ *These two bars are set by default or the boot code.
++ * However, it's safer to set them here so we're not boot
++ * code dependent.
++ */
++ outl(0x1be00000, PCI_BASE | PCI_BASE14); /* PNX MMIO */
++ outl(PNX8550_NAND_BASE_ADDR, PCI_BASE | PCI_BASE18); /* XIO */
++
++ outl(PCI_EN_TA |
++ PCI_EN_PCI2MMI |
++ PCI_EN_XIO |
++ PCI_SETUP_BASE18_SIZE(SIZE_32M) |
++ PCI_SETUP_BASE18_EN |
++ PCI_SETUP_BASE14_EN |
++ PCI_SETUP_BASE10_PREF |
++ PCI_SETUP_BASE10_SIZE(pci_mem_code) |
++ PCI_SETUP_CFGMANAGE_EN |
++ PCI_SETUP_PCIARB_EN,
++ PCI_BASE |
++ PCI_SETUP); /* PCI_SETUP */
++ outl(0x00000000, PCI_BASE | PCI_CTRL); /* PCI_CONTROL */
++
++ register_pci_controller(&pnx8550_controller);
++
++ return 0;
++}
++
++arch_initcall(pnx8550_pci_setup);
+diff --git a/arch/mips/nxp/pnx8550/common/platform.c b/arch/mips/nxp/pnx8550/common/platform.c
+new file mode 100644
+index 0000000..c7c763d
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/common/platform.c
+@@ -0,0 +1,132 @@
++/*
++ * Platform device support for NXP PNX8550 SoCs
++ *
++ * Copyright 2005, Embedded Alley Solutions, Inc
++ *
++ * Based on arch/mips/au1000/common/platform.c
++ * Platform device support for Au1x00 SoCs.
++ *
++ * Copyright 2004, Matt Porter <mporter at kernel.crashing.org>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++#include <linux/device.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/resource.h>
++#include <linux/serial.h>
++#include <linux/serial_pnx8xxx.h>
++#include <linux/platform_device.h>
++
++#include <int.h>
++#include <usb.h>
++#include <uart.h>
++
++static struct resource pnx8550_usb_ohci_resources[] = {
++ [0] = {
++ .start = PNX8550_USB_OHCI_OP_BASE,
++ .end = PNX8550_USB_OHCI_OP_BASE +
++ PNX8550_USB_OHCI_OP_LEN,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = PNX8550_INT_USB,
++ .end = PNX8550_INT_USB,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct resource pnx8550_uart_resources[] = {
++ [0] = {
++ .start = PNX8550_UART_PORT0,
++ .end = PNX8550_UART_PORT0 + 0xfff,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = PNX8550_UART_INT(0),
++ .end = PNX8550_UART_INT(0),
++ .flags = IORESOURCE_IRQ,
++ },
++ [2] = {
++ .start = PNX8550_UART_PORT1,
++ .end = PNX8550_UART_PORT1 + 0xfff,
++ .flags = IORESOURCE_MEM,
++ },
++ [3] = {
++ .start = PNX8550_UART_INT(1),
++ .end = PNX8550_UART_INT(1),
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct pnx8xxx_port pnx8xxx_ports[] = {
++ [0] = {
++ .port = {
++ .type = PORT_PNX8XXX,
++ .iotype = UPIO_MEM,
++ .membase = (void __iomem *)PNX8550_UART_PORT0,
++ .mapbase = PNX8550_UART_PORT0,
++ .irq = PNX8550_UART_INT(0),
++ .uartclk = 3692300,
++ .fifosize = 16,
++ .flags = UPF_BOOT_AUTOCONF,
++ .line = 0,
++ },
++ },
++ [1] = {
++ .port = {
++ .type = PORT_PNX8XXX,
++ .iotype = UPIO_MEM,
++ .membase = (void __iomem *)PNX8550_UART_PORT1,
++ .mapbase = PNX8550_UART_PORT1,
++ .irq = PNX8550_UART_INT(1),
++ .uartclk = 3692300,
++ .fifosize = 16,
++ .flags = UPF_BOOT_AUTOCONF,
++ .line = 1,
++ },
++ },
++};
++
++/* The dmamask must be set for OHCI to work */
++static u64 ohci_dmamask = ~(u32)0;
++
++static u64 uart_dmamask = ~(u32)0;
++
++static struct platform_device pnx8550_usb_ohci_device = {
++ .name = "pnx8550-ohci",
++ .id = -1,
++ .dev = {
++ .dma_mask = &ohci_dmamask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .num_resources = ARRAY_SIZE(pnx8550_usb_ohci_resources),
++ .resource = pnx8550_usb_ohci_resources,
++};
++
++static struct platform_device pnx8550_uart_device = {
++ .name = "pnx8xxx-uart",
++ .id = -1,
++ .dev = {
++ .dma_mask = &uart_dmamask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = pnx8xxx_ports,
++ },
++ .num_resources = ARRAY_SIZE(pnx8550_uart_resources),
++ .resource = pnx8550_uart_resources,
++};
++
++static struct platform_device *pnx8550_platform_devices[] __initdata = {
++ &pnx8550_usb_ohci_device,
++ &pnx8550_uart_device,
++};
++
++static int __init pnx8550_platform_init(void)
++{
++ return platform_add_devices(pnx8550_platform_devices,
++ ARRAY_SIZE(pnx8550_platform_devices));
++}
++
++arch_initcall(pnx8550_platform_init);
+diff --git a/arch/mips/nxp/pnx8550/common/proc.c b/arch/mips/nxp/pnx8550/common/proc.c
+new file mode 100644
+index 0000000..18b125e
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/common/proc.c
+@@ -0,0 +1,112 @@
++/*
++ * This program is free software; you can distribute 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 it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
++ */
++#include <linux/init.h>
++#include <linux/proc_fs.h>
++#include <linux/irq.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/kernel_stat.h>
++#include <linux/random.h>
++
++#include <asm/io.h>
++#include <asm/gdb-stub.h>
++#include <int.h>
++#include <uart.h>
++
++
++static int pnx8550_timers_read(char* page, char** start, off_t offset, int count, int* eof, void* data)
++{
++ int len = 0;
++ int configPR = read_c0_config7();
++
++ if (offset==0) {
++ len += sprintf(&page[len], "Timer: count, compare, tc, status\n");
++ len += sprintf(&page[len], " 1: %11i, %8i, %1i, %s\n",
++ read_c0_count(), read_c0_compare(),
++ (configPR>>6)&0x1, ((configPR>>3)&0x1)? "off":"on");
++ len += sprintf(&page[len], " 2: %11i, %8i, %1i, %s\n",
++ read_c0_count2(), read_c0_compare2(),
++ (configPR>>7)&0x1, ((configPR>>4)&0x1)? "off":"on");
++ len += sprintf(&page[len], " 3: %11i, %8i, %1i, %s\n",
++ read_c0_count3(), read_c0_compare3(),
++ (configPR>>8)&0x1, ((configPR>>5)&0x1)? "off":"on");
++ }
++
++ return len;
++}
++
++static int pnx8550_registers_read(char* page, char** start, off_t offset, int count, int* eof, void* data)
++{
++ int len = 0;
++
++ if (offset==0) {
++ len += sprintf(&page[len], "config1: %#10.8x\n", read_c0_config1());
++ len += sprintf(&page[len], "config2: %#10.8x\n", read_c0_config2());
++ len += sprintf(&page[len], "config3: %#10.8x\n", read_c0_config3());
++ len += sprintf(&page[len], "configPR: %#10.8x\n", read_c0_config7());
++ len += sprintf(&page[len], "status: %#10.8x\n", read_c0_status());
++ len += sprintf(&page[len], "cause: %#10.8x\n", read_c0_cause());
++ len += sprintf(&page[len], "count: %#10.8x\n", read_c0_count());
++ len += sprintf(&page[len], "count_2: %#10.8x\n", read_c0_count2());
++ len += sprintf(&page[len], "count_3: %#10.8x\n", read_c0_count3());
++ len += sprintf(&page[len], "compare: %#10.8x\n", read_c0_compare());
++ len += sprintf(&page[len], "compare_2: %#10.8x\n", read_c0_compare2());
++ len += sprintf(&page[len], "compare_3: %#10.8x\n", read_c0_compare3());
++ }
++
++ return len;
++}
++
++static struct proc_dir_entry* pnx8550_dir = NULL;
++static struct proc_dir_entry* pnx8550_timers = NULL;
++static struct proc_dir_entry* pnx8550_registers = NULL;
++
++static int pnx8550_proc_init( void )
++{
++
++ // Create /proc/pnx8550
++ pnx8550_dir = proc_mkdir("pnx8550", NULL);
++ if (!pnx8550_dir) {
++ printk(KERN_ERR "Can't create pnx8550 proc dir\n");
++ return -1;
++ }
++
++ // Create /proc/pnx8550/timers
++ pnx8550_timers = create_proc_read_entry(
++ "timers",
++ 0,
++ pnx8550_dir,
++ pnx8550_timers_read,
++ NULL);
++
++ if (!pnx8550_timers)
++ printk(KERN_ERR "Can't create pnx8550 timers proc file\n");
++
++ // Create /proc/pnx8550/registers
++ pnx8550_registers = create_proc_read_entry(
++ "registers",
++ 0,
++ pnx8550_dir,
++ pnx8550_registers_read,
++ NULL);
++
++ if (!pnx8550_registers)
++ printk(KERN_ERR "Can't create pnx8550 registers proc file\n");
++
++ return 0;
++}
++
++__initcall(pnx8550_proc_init);
+diff --git a/arch/mips/nxp/pnx8550/common/prom.c b/arch/mips/nxp/pnx8550/common/prom.c
+new file mode 100644
+index 0000000..2f56745
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/common/prom.c
+@@ -0,0 +1,129 @@
++/*
++ *
++ * Per Hallsmark, per.hallsmark at mvista.com
++ *
++ * Based on jmr3927/common/prom.c
++ *
++ * 2004 (c) MontaVista Software, Inc. This file is licensed under the
++ * terms of the GNU General Public License version 2. This program is
++ * licensed "as is" without any warranty of any kind, whether express
++ * or implied.
++ */
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/string.h>
++#include <linux/serial_pnx8xxx.h>
++
++#include <asm/bootinfo.h>
++#include <uart.h>
++
++/* #define DEBUG_CMDLINE */
++
++extern int prom_argc;
++extern char **prom_argv, **prom_envp;
++
++typedef struct
++{
++ char *name;
++/* char *val; */
++}t_env_var;
++
++
++char * prom_getcmdline(void)
++{
++ return &(arcs_cmdline[0]);
++}
++
++void __init prom_init_cmdline(void)
++{
++ int i;
++
++ arcs_cmdline[0] = '\0';
++ for (i = 0; i < prom_argc; i++) {
++ strcat(arcs_cmdline, prom_argv[i]);
++ strcat(arcs_cmdline, " ");
++ }
++}
++
++char *prom_getenv(char *envname)
++{
++ /*
++ * Return a pointer to the given environment variable.
++ * Environment variables are stored in the form of "memsize=64".
++ */
++
++ t_env_var *env = (t_env_var *)prom_envp;
++ int i;
++
++ i = strlen(envname);
++
++ while(env->name) {
++ if(strncmp(envname, env->name, i) == 0) {
++ return(env->name + strlen(envname) + 1);
++ }
++ env++;
++ }
++ return(NULL);
++}
++
++inline unsigned char str2hexnum(unsigned char c)
++{
++ if(c >= '0' && c <= '9')
++ return c - '0';
++ if(c >= 'a' && c <= 'f')
++ return c - 'a' + 10;
++ if(c >= 'A' && c <= 'F')
++ return c - 'A' + 10;
++ return 0; /* foo */
++}
++
++inline void str2eaddr(unsigned char *ea, unsigned char *str)
++{
++ int i;
++
++ for(i = 0; i < 6; i++) {
++ unsigned char num;
++
++ if((*str == '.') || (*str == ':'))
++ str++;
++ num = str2hexnum(*str++) << 4;
++ num |= (str2hexnum(*str++));
++ ea[i] = num;
++ }
++}
++
++int get_ethernet_addr(char *ethernet_addr)
++{
++ char *ethaddr_str;
++
++ ethaddr_str = prom_getenv("ethaddr");
++ if (!ethaddr_str) {
++ printk("ethaddr not set in boot prom\n");
++ return -1;
++ }
++ str2eaddr(ethernet_addr, ethaddr_str);
++ return 0;
++}
++
++void __init prom_free_prom_memory(void)
++{
++}
++
++extern int pnx8550_console_port;
++
++/* used by early printk */
++void prom_putchar(char c)
++{
++ if (pnx8550_console_port != -1) {
++ /* Wait until FIFO not full */
++ while( ((ip3106_fifo(UART_BASE, pnx8550_console_port) & PNX8XXX_UART_FIFO_TXFIFO) >> 16) >= 16)
++ ;
++ /* Send one char */
++ ip3106_fifo(UART_BASE, pnx8550_console_port) = c;
++ }
++}
++
++EXPORT_SYMBOL(prom_getcmdline);
++EXPORT_SYMBOL(get_ethernet_addr);
++EXPORT_SYMBOL(str2eaddr);
+diff --git a/arch/mips/nxp/pnx8550/common/reset.c b/arch/mips/nxp/pnx8550/common/reset.c
+new file mode 100644
+index 0000000..7b2cbc5
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/common/reset.c
+@@ -0,0 +1,49 @@
++/*.
++ *
++ * ########################################################################
++ *
++ * This program is free software; you can distribute 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 it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ *
++ * You 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.
++ *
++ * ########################################################################
++ *
++ * Reset the PNX8550 board.
++ *
++ */
++#include <linux/slab.h>
++#include <asm/reboot.h>
++#include <glb.h>
++
++void pnx8550_machine_restart(char *command)
++{
++ char head[] = "************* Machine restart *************";
++ char foot[] = "*******************************************";
++
++ printk("\n\n");
++ printk("%s\n", head);
++ if (command != NULL)
++ printk("* %s\n", command);
++ printk("%s\n", foot);
++
++ PNX8550_RST_CTL = PNX8550_RST_DO_SW_RST;
++}
++
++void pnx8550_machine_halt(void)
++{
++ printk("*** Machine halt. (Not implemented) ***\n");
++}
++
++void pnx8550_machine_power_off(void)
++{
++ printk("*** Machine power off. (Not implemented) ***\n");
++}
+diff --git a/arch/mips/nxp/pnx8550/common/setup.c b/arch/mips/nxp/pnx8550/common/setup.c
+new file mode 100644
+index 0000000..92d764c
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/common/setup.c
+@@ -0,0 +1,157 @@
++/*
++ *
++ * 2.6 port, Embedded Alley Solutions, Inc
++ *
++ * Based on Per Hallsmark, per.hallsmark at mvista.com
++ *
++ * This program is free software; you can distribute 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 it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
++ */
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/ioport.h>
++#include <linux/irq.h>
++#include <linux/mm.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/serial_pnx8xxx.h>
++#include <linux/pm.h>
++
++#include <asm/cpu.h>
++#include <asm/bootinfo.h>
++#include <asm/irq.h>
++#include <asm/mipsregs.h>
++#include <asm/reboot.h>
++#include <asm/pgtable.h>
++#include <asm/time.h>
++
++#include <glb.h>
++#include <int.h>
++#include <pci.h>
++#include <uart.h>
++#include <nand.h>
++
++extern void __init board_setup(void);
++extern void pnx8550_machine_restart(char *);
++extern void pnx8550_machine_halt(void);
++extern void pnx8550_machine_power_off(void);
++extern struct resource ioport_resource;
++extern struct resource iomem_resource;
++extern void rs_kgdb_hook(int tty_no);
++extern char *prom_getcmdline(void);
++
++struct resource standard_io_resources[] = {
++ {
++ .start = 0x00,
++ .end = 0x1f,
++ .name = "dma1",
++ .flags = IORESOURCE_BUSY
++ }, {
++ .start = 0x40,
++ .end = 0x5f,
++ .name = "timer",
++ .flags = IORESOURCE_BUSY
++ }, {
++ .start = 0x80,
++ .end = 0x8f,
++ .name = "dma page reg",
++ .flags = IORESOURCE_BUSY
++ }, {
++ .start = 0xc0,
++ .end = 0xdf,
++ .name = "dma2",
++ .flags = IORESOURCE_BUSY
++ },
++};
++
++#define STANDARD_IO_RESOURCES ARRAY_SIZE(standard_io_resources)
++
++extern struct resource pci_io_resource;
++extern struct resource pci_mem_resource;
++
++/* Return the total size of DRAM-memory, (RANK0 + RANK1) */
++unsigned long get_system_mem_size(void)
++{
++ /* Read IP2031_RANK0_ADDR_LO */
++ unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010);
++ /* Read IP2031_RANK1_ADDR_HI */
++ unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018);
++
++ return dram_r1_hi - dram_r0_lo + 1;
++}
++
++int pnx8550_console_port = -1;
++
++void __init plat_mem_setup(void)
++{
++ int i;
++ char* argptr;
++
++ board_setup(); /* board specific setup */
++
++ _machine_restart = pnx8550_machine_restart;
++ _machine_halt = pnx8550_machine_halt;
++ pm_power_off = pnx8550_machine_power_off;
++
++ /* Clear the Global 2 Register, PCI Inta Output Enable Registers
++ Bit 1:Enable DAC Powerdown
++ -> 0:DACs are enabled and are working normally
++ 1:DACs are powerdown
++ Bit 0:Enable of PCI inta output
++ -> 0 = Disable PCI inta output
++ 1 = Enable PCI inta output
++ */
++ PNX8550_GLB2_ENAB_INTA_O = 0;
++
++ /* IO/MEM resources. */
++ set_io_port_base(KSEG1);
++ ioport_resource.start = 0;
++ ioport_resource.end = ~0;
++ iomem_resource.start = 0;
++ iomem_resource.end = ~0;
++
++ /* Request I/O space for devices on this board */
++ for (i = 0; i < STANDARD_IO_RESOURCES; i++)
++ request_resource(&ioport_resource, standard_io_resources + i);
++
++ /* Place the Mode Control bit for GPIO pin 16 in primary function */
++ /* Pin 16 is used by UART1, UA1_TX */
++ outl((PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_16_BIT) |
++ (PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_17_BIT),
++ PNX8550_GPIO_MC1);
++
++ argptr = prom_getcmdline();
++ if ((argptr = strstr(argptr, "console=ttyS")) != NULL) {
++ argptr += strlen("console=ttyS");
++ pnx8550_console_port = *argptr == '0' ? 0 : 1;
++
++ /* We must initialize the UART (console) before early printk */
++ /* Set LCR to 8-bit and BAUD to 38400 (no 5) */
++ ip3106_lcr(UART_BASE, pnx8550_console_port) =
++ PNX8XXX_UART_LCR_8BIT;
++ ip3106_baud(UART_BASE, pnx8550_console_port) = 5;
++ }
++
++#ifdef CONFIG_KGDB
++ argptr = prom_getcmdline();
++ if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
++ int line;
++ argptr += strlen("kgdb=ttyS");
++ line = *argptr == '0' ? 0 : 1;
++ rs_kgdb_hook(line);
++ pr_info("KGDB: Using ttyS%i for session, "
++ "please connect your debugger\n", line ? 1 : 0);
++ }
++#endif
++ return;
++}
+diff --git a/arch/mips/nxp/pnx8550/common/time.c b/arch/mips/nxp/pnx8550/common/time.c
+new file mode 100644
+index 0000000..62f495b
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/common/time.c
+@@ -0,0 +1,150 @@
++/*
++ * Copyright 2001, 2002, 2003 MontaVista Software Inc.
++ * Author: Jun Sun, jsun at mvista.com or jsun at junsun.net
++ * Copyright (C) 2007 Ralf Baechle (ralf at linux-mips.org)
++ *
++ * Common time service routines for MIPS machines. See
++ * Documents/MIPS/README.txt.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/param.h>
++#include <linux/time.h>
++#include <linux/timer.h>
++#include <linux/smp.h>
++#include <linux/kernel_stat.h>
++#include <linux/spinlock.h>
++#include <linux/interrupt.h>
++
++#include <asm/bootinfo.h>
++#include <asm/cpu.h>
++#include <asm/time.h>
++#include <asm/hardirq.h>
++#include <asm/div64.h>
++#include <asm/debug.h>
++
++#include <int.h>
++#include <cm.h>
++
++static unsigned long cpj;
++
++static cycle_t hpt_read(void)
++{
++ return read_c0_count2();
++}
++
++static struct clocksource pnx_clocksource = {
++ .name = "pnx8xxx",
++ .rating = 200,
++ .read = hpt_read,
++ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
++};
++
++static irqreturn_t pnx8xxx_timer_interrupt(int irq, void *dev_id)
++{
++ struct clock_event_device *c = dev_id;
++
++ /* clear MATCH, signal the event */
++ c->event_handler(c);
++
++ return IRQ_HANDLED;
++}
++
++static struct irqaction pnx8xxx_timer_irq = {
++ .handler = pnx8xxx_timer_interrupt,
++ .flags = IRQF_DISABLED | IRQF_PERCPU,
++ .name = "pnx8xxx_timer",
++};
++
++static irqreturn_t monotonic_interrupt(int irq, void *dev_id)
++{
++ /* Timer 2 clear interrupt */
++ write_c0_compare2(-1);
++ return IRQ_HANDLED;
++}
++
++static struct irqaction monotonic_irqaction = {
++ .handler = monotonic_interrupt,
++ .flags = IRQF_DISABLED,
++ .name = "Monotonic timer",
++};
++
++static int pnx8xxx_set_next_event(unsigned long delta,
++ struct clock_event_device *evt)
++{
++ write_c0_compare(delta);
++ return 0;
++}
++
++static struct clock_event_device pnx8xxx_clockevent = {
++ .name = "pnx8xxx_clockevent",
++ .features = CLOCK_EVT_FEAT_ONESHOT,
++ .set_next_event = pnx8xxx_set_next_event,
++};
++
++static inline void timer_ack(void)
++{
++ write_c0_compare(cpj);
++}
++
++__init void plat_time_init(void)
++{
++ unsigned int configPR;
++ unsigned int n;
++ unsigned int m;
++ unsigned int p;
++ unsigned int pow2p;
++
++ clockevents_register_device(&pnx8xxx_clockevent);
++ clocksource_register(&pnx_clocksource);
++
++ /* Timer 1 start */
++ configPR = read_c0_config7();
++ configPR &= ~0x00000008;
++ write_c0_config7(configPR);
++
++ /* Timer 2 start */
++ configPR = read_c0_config7();
++ configPR &= ~0x00000010;
++ write_c0_config7(configPR);
++
++ /* Timer 3 stop */
++ configPR = read_c0_config7();
++ configPR |= 0x00000020;
++ write_c0_config7(configPR);
++
++
++ /* PLL0 sets MIPS clock (PLL1 <=> TM1, PLL6 <=> TM2, PLL5 <=> mem) */
++ /* (but only if CLK_MIPS_CTL select value [bits 3:1] is 1: FIXME) */
++
++ n = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_N_MASK) >> 16;
++ m = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_M_MASK) >> 8;
++ p = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_P_MASK) >> 2;
++ pow2p = (1 << p);
++
++ db_assert(m != 0 && pow2p != 0);
++
++ /*
++ * Compute the frequency as in the PNX8550 User Manual 1.0, p.186
++ * (a.k.a. 8-10). Divide by HZ for a timer offset that results in
++ * HZ timer interrupts per second.
++ */
++ mips_hpt_frequency = 27UL * ((1000000UL * n)/(m * pow2p));
++ cpj = (mips_hpt_frequency + HZ / 2) / HZ;
++ write_c0_count(0);
++ timer_ack();
++
++ /* Setup Timer 2 */
++ write_c0_count2(0);
++ write_c0_compare2(0xffffffff);
++
++ setup_irq(PNX8550_INT_TIMER1, &pnx8xxx_timer_irq);
++ setup_irq(PNX8550_INT_TIMER2, &monotonic_irqaction);
++}
+diff --git a/arch/mips/nxp/pnx8550/jbs/Makefile b/arch/mips/nxp/pnx8550/jbs/Makefile
+new file mode 100644
+index 0000000..ad6a8ca
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/jbs/Makefile
+@@ -0,0 +1,4 @@
++
++# Makefile for the NXP JBS Board.
++
++lib-y := init.o board_setup.o irqmap.o
+diff --git a/arch/mips/nxp/pnx8550/jbs/board_setup.c b/arch/mips/nxp/pnx8550/jbs/board_setup.c
+new file mode 100644
+index 0000000..f92826e
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/jbs/board_setup.c
+@@ -0,0 +1,65 @@
++/*
++ * JBS Specific board startup routines.
++ *
++ * Copyright 2005, Embedded Alley Solutions, 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/ioport.h>
++#include <linux/mm.h>
++#include <linux/console.h>
++#include <linux/mc146818rtc.h>
++#include <linux/delay.h>
++
++#include <asm/cpu.h>
++#include <asm/bootinfo.h>
++#include <asm/irq.h>
++#include <asm/mipsregs.h>
++#include <asm/reboot.h>
++#include <asm/pgtable.h>
++
++#include <glb.h>
++
++/* CP0 hazard avoidance. */
++#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
++ "nop; nop; nop; nop; nop; nop;\n\t" \
++ ".set reorder\n\t")
++
++void __init board_setup(void)
++{
++ unsigned long config0, configpr;
++
++ config0 = read_c0_config();
++
++ /* clear all three cache coherency fields */
++ config0 &= ~(0x7 | (7<<25) | (7<<28));
++ config0 |= (CONF_CM_DEFAULT | (CONF_CM_DEFAULT<<25) |
++ (CONF_CM_DEFAULT<<28));
++ write_c0_config(config0);
++ BARRIER;
++
++ configpr = read_c0_config7();
++ configpr |= (1<<19); /* enable tlb */
++ write_c0_config7(configpr);
++ BARRIER;
++}
+diff --git a/arch/mips/nxp/pnx8550/jbs/init.c b/arch/mips/nxp/pnx8550/jbs/init.c
+new file mode 100644
+index 0000000..d59b4a4
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/jbs/init.c
+@@ -0,0 +1,53 @@
++/*
++ *
++ * Copyright 2005 Embedded Alley Solutions, Inc
++ * source at embeddedalley.com
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/bootmem.h>
++#include <asm/addrspace.h>
++#include <asm/bootinfo.h>
++#include <linux/string.h>
++#include <linux/kernel.h>
++
++int prom_argc;
++char **prom_argv, **prom_envp;
++extern void __init prom_init_cmdline(void);
++extern char *prom_getenv(char *envname);
++
++const char *get_system_type(void)
++{
++ return "NXP PNX8550/JBS";
++}
++
++void __init prom_init(void)
++{
++ unsigned long memsize;
++
++ //memsize = 0x02800000; /* Trimedia uses memory above */
++ memsize = 0x08000000; /* Trimedia uses memory above */
++ add_memory_region(0, memsize, BOOT_MEM_RAM);
++}
+diff --git a/arch/mips/nxp/pnx8550/jbs/irqmap.c b/arch/mips/nxp/pnx8550/jbs/irqmap.c
+new file mode 100644
+index 0000000..7fc8984
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/jbs/irqmap.c
+@@ -0,0 +1,35 @@
++/*
++ * NXP JBS board irqmap.
++ *
++ * Copyright 2005 Embedded Alley Solutions, Inc
++ * source at embeddealley.com
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/init.h>
++#include <int.h>
++
++char pnx8550_irq_tab[][5] __initdata = {
++ [8] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
++ [9] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
++ [17] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
++};
+diff --git a/arch/mips/nxp/pnx8550/stb810/Makefile b/arch/mips/nxp/pnx8550/stb810/Makefile
+new file mode 100644
+index 0000000..ab91d72
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/stb810/Makefile
+@@ -0,0 +1,4 @@
++
++# Makefile for the NXP STB810 Board.
++
++lib-y := prom_init.o board_setup.o irqmap.o
+diff --git a/arch/mips/nxp/pnx8550/stb810/board_setup.c b/arch/mips/nxp/pnx8550/stb810/board_setup.c
+new file mode 100644
+index 0000000..1282c27
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/stb810/board_setup.c
+@@ -0,0 +1,49 @@
++/*
++ * STB810 specific board startup routines.
++ *
++ * Based on the arch/mips/nxp/pnx8550/jbs/board_setup.c
++ *
++ * Author: MontaVista Software, Inc.
++ * source at mvista.com
++ *
++ * Copyright 2005 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 as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/ioport.h>
++#include <linux/mm.h>
++#include <linux/console.h>
++#include <linux/mc146818rtc.h>
++#include <linux/delay.h>
++
++#include <asm/cpu.h>
++#include <asm/bootinfo.h>
++#include <asm/irq.h>
++#include <asm/mipsregs.h>
++#include <asm/reboot.h>
++#include <asm/pgtable.h>
++
++#include <glb.h>
++
++void __init board_setup(void)
++{
++ unsigned long config0, configpr;
++
++ config0 = read_c0_config();
++
++ /* clear all three cache coherency fields */
++ config0 &= ~(0x7 | (7<<25) | (7<<28));
++ config0 |= (CONF_CM_DEFAULT | (CONF_CM_DEFAULT<<25) |
++ (CONF_CM_DEFAULT<<28));
++ write_c0_config(config0);
++
++ configpr = read_c0_config7();
++ configpr |= (1<<19); /* enable tlb */
++ write_c0_config7(configpr);
++}
+diff --git a/arch/mips/nxp/pnx8550/stb810/irqmap.c b/arch/mips/nxp/pnx8550/stb810/irqmap.c
+new file mode 100644
+index 0000000..8c03496
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/stb810/irqmap.c
+@@ -0,0 +1,22 @@
++/*
++ * NXP STB810 board irqmap.
++ *
++ * Author: MontaVista Software, Inc.
++ * source at mvista.com
++ *
++ * Copyright 2005 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 as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/init.h>
++#include <int.h>
++
++char pnx8550_irq_tab[][5] __initdata = {
++ [8] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
++ [9] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
++ [10] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
++};
+diff --git a/arch/mips/nxp/pnx8550/stb810/prom_init.c b/arch/mips/nxp/pnx8550/stb810/prom_init.c
+new file mode 100644
+index 0000000..ca7f4ad
+--- /dev/null
++++ b/arch/mips/nxp/pnx8550/stb810/prom_init.c
+@@ -0,0 +1,46 @@
++/*
++ * STB810 specific prom routines
++ *
++ * Author: MontaVista Software, Inc.
++ * source at mvista.com
++ *
++ * Copyright 2005 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 as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/bootmem.h>
++#include <asm/addrspace.h>
++#include <asm/bootinfo.h>
++#include <linux/string.h>
++#include <linux/kernel.h>
++
++int prom_argc;
++char **prom_argv, **prom_envp;
++extern void __init prom_init_cmdline(void);
++extern char *prom_getenv(char *envname);
++
++const char *get_system_type(void)
++{
++ return "NXP PNX8950/STB810";
++}
++
++void __init prom_init(void)
++{
++ unsigned long memsize;
++
++ prom_argc = (int) fw_arg0;
++ prom_argv = (char **) fw_arg1;
++ prom_envp = (char **) fw_arg2;
++
++ prom_init_cmdline();
++
++ memsize = 0x08000000; /* Trimedia uses memory above */
++ add_memory_region(0, memsize, BOOT_MEM_RAM);
++}
+diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
+index aa52aa1..b5f6f71 100644
+--- a/arch/mips/oprofile/common.c
++++ b/arch/mips/oprofile/common.c
+@@ -80,6 +80,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
+ case CPU_24K:
+ case CPU_25KF:
+ case CPU_34K:
++ case CPU_1004K:
+ case CPU_74K:
+ case CPU_SB1:
+ case CPU_SB1A:
+diff --git a/arch/mips/oprofile/op_impl.h b/arch/mips/oprofile/op_impl.h
+index fa6b4aa..2bfc17c 100644
+--- a/arch/mips/oprofile/op_impl.h
++++ b/arch/mips/oprofile/op_impl.h
+@@ -10,7 +10,6 @@
+ #ifndef OP_IMPL_H
+ #define OP_IMPL_H 1
- phy0: ethernet-phy at 0 {
- interrupt-parent = <&mpic>;
- interrupts = <5 1>;
-- reg = <0>;
-+ reg = <0x0>;
- device_type = "ethernet-phy";
- };
- phy1: ethernet-phy at 1 {
- interrupt-parent = <&mpic>;
- interrupts = <5 1>;
-- reg = <1>;
-+ reg = <0x1>;
- device_type = "ethernet-phy";
- };
- phy3: ethernet-phy at 3 {
- interrupt-parent = <&mpic>;
- interrupts = <7 1>;
-- reg = <3>;
-+ reg = <0x3>;
- device_type = "ethernet-phy";
- };
- };
-@@ -113,9 +114,9 @@
- device_type = "network";
- model = "TSEC";
- compatible = "gianfar";
-- reg = <24000 1000>;
-+ reg = <0x24000 0x1000>;
- local-mac-address = [ 00 00 00 00 00 00 ];
-- interrupts = <1d 2 1e 2 22 2>;
-+ interrupts = <29 2 30 2 34 2>;
- interrupt-parent = <&mpic>;
- phy-handle = <&phy0>;
- };
-@@ -125,9 +126,9 @@
- device_type = "network";
- model = "TSEC";
- compatible = "gianfar";
-- reg = <25000 1000>;
-+ reg = <0x25000 0x1000>;
- local-mac-address = [ 00 00 00 00 00 00 ];
-- interrupts = <23 2 24 2 28 2>;
-+ interrupts = <35 2 36 2 40 2>;
- interrupt-parent = <&mpic>;
- phy-handle = <&phy1>;
- };
-@@ -137,9 +138,9 @@
- device_type = "network";
- model = "FEC";
- compatible = "gianfar";
-- reg = <26000 1000>;
-+ reg = <0x26000 0x1000>;
- local-mac-address = [ 00 00 00 00 00 00 ];
-- interrupts = <29 2>;
-+ interrupts = <41 2>;
- interrupt-parent = <&mpic>;
- phy-handle = <&phy3>;
- };
-@@ -148,9 +149,9 @@
- cell-index = <0>;
- device_type = "serial";
- compatible = "ns16550";
-- reg = <4500 100>; // reg base, size
-+ reg = <0x4500 0x100>; // reg base, size
- clock-frequency = <0>; // should we fill in in uboot?
-- interrupts = <2a 2>;
-+ interrupts = <42 2>;
- interrupt-parent = <&mpic>;
- };
+-extern int null_perf_irq(void);
+ extern int (*perf_irq)(void);
-@@ -158,9 +159,9 @@
- cell-index = <1>;
- device_type = "serial";
- compatible = "ns16550";
-- reg = <4600 100>; // reg base, size
-+ reg = <0x4600 0x100>; // reg base, size
- clock-frequency = <0>; // should we fill in in uboot?
-- interrupts = <2a 2>;
-+ interrupts = <42 2>;
- interrupt-parent = <&mpic>;
- };
- mpic: pic at 40000 {
-@@ -168,7 +169,7 @@
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <2>;
-- reg = <40000 40000>;
-+ reg = <0x40000 0x40000>;
- compatible = "chrp,open-pic";
- device_type = "open-pic";
- big-endian;
-@@ -177,90 +178,90 @@
+ /* Per-counter configuration as set via oprofilefs. */
+diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
+index ccbea22..da8cbb6 100644
+--- a/arch/mips/oprofile/op_model_mipsxx.c
++++ b/arch/mips/oprofile/op_model_mipsxx.c
+@@ -31,9 +31,14 @@
- pci0: pci at e0008000 {
- cell-index = <0>;
-- interrupt-map-mask = <f800 0 0 7>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
+ #define M_COUNTER_OVERFLOW (1UL << 31)
- /* 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
++static int (*save_perf_irq)(void);
++
+ #ifdef CONFIG_MIPS_MT_SMP
+-#define WHAT (M_TC_EN_VPE | M_PERFCTL_VPEID(smp_processor_id()))
+-#define vpe_id() smp_processor_id()
++static int cpu_has_mipsmt_pertccounters;
++#define WHAT (M_TC_EN_VPE | \
++ M_PERFCTL_VPEID(cpu_data[smp_processor_id()].vpe_id))
++#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
++ 0 : cpu_data[smp_processor_id()].vpe_id)
- /* 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
+ /*
+ * The number of bits to shift to convert between counters per core and
+@@ -243,11 +248,11 @@ static inline int __n_counters(void)
+ {
+ if (!(read_c0_config1() & M_CONFIG1_PC))
+ return 0;
+- if (!(r_c0_perfctrl0() & M_PERFCTL_MORE))
++ if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
+ return 1;
+- if (!(r_c0_perfctrl1() & M_PERFCTL_MORE))
++ if (!(read_c0_perfctrl1() & M_PERFCTL_MORE))
+ return 2;
+- if (!(r_c0_perfctrl2() & M_PERFCTL_MORE))
++ if (!(read_c0_perfctrl2() & M_PERFCTL_MORE))
+ return 3;
- /* 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
+ return 4;
+@@ -274,8 +279,9 @@ static inline int n_counters(void)
+ return counters;
+ }
- /* 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
+-static inline void reset_counters(int counters)
++static void reset_counters(void *arg)
+ {
++ int counters = (int)arg;
+ switch (counters) {
+ case 4:
+ w_c0_perfctrl3(0);
+@@ -302,9 +308,12 @@ static int __init mipsxx_init(void)
+ return -ENODEV;
+ }
- /* 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
+- reset_counters(counters);
+-
+- counters = counters_total_to_per_cpu(counters);
++#ifdef CONFIG_MIPS_MT_SMP
++ cpu_has_mipsmt_pertccounters = read_c0_config7() & (1<<19);
++ if (!cpu_has_mipsmt_pertccounters)
++ counters = counters_total_to_per_cpu(counters);
++#endif
++ on_each_cpu(reset_counters, (void *)counters, 0, 1);
- /* 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
+ op_model_mipsxx_ops.num_counters = counters;
+ switch (current_cpu_type()) {
+@@ -320,6 +329,13 @@ static int __init mipsxx_init(void)
+ op_model_mipsxx_ops.cpu_type = "mips/25K";
+ break;
- /* 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
++ case CPU_1004K:
++#if 0
++ /* FIXME: report as 34K for now */
++ op_model_mipsxx_ops.cpu_type = "mips/1004K";
++ break;
++#endif
++
+ case CPU_34K:
+ op_model_mipsxx_ops.cpu_type = "mips/34K";
+ break;
+@@ -355,6 +371,7 @@ static int __init mipsxx_init(void)
+ return -ENODEV;
+ }
- /* 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
++ save_perf_irq = perf_irq;
+ perf_irq = mipsxx_perfcount_handler;
- /* 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
+ return 0;
+@@ -365,9 +382,9 @@ static void mipsxx_exit(void)
+ int counters = op_model_mipsxx_ops.num_counters;
- /* 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
+ counters = counters_per_cpu_to_total(counters);
+- reset_counters(counters);
++ on_each_cpu(reset_counters, (void *)counters, 0, 1);
- /* 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
+- perf_irq = null_perf_irq;
++ perf_irq = save_perf_irq;
+ }
- /* IDSEL 0x15 */
-- a800 0 0 1 &mpic 2 1
-- a800 0 0 2 &mpic 3 1
-- a800 0 0 3 &mpic 4 1
-- a800 0 0 4 &mpic 1 1>;
-+ 0xa800 0x0 0x0 0x1 &mpic 0x2 0x1
-+ 0xa800 0x0 0x0 0x2 &mpic 0x3 0x1
-+ 0xa800 0x0 0x0 0x3 &mpic 0x4 0x1
-+ 0xa800 0x0 0x0 0x4 &mpic 0x1 0x1>;
- interrupt-parent = <&mpic>;
-- interrupts = <18 2>;
-+ interrupts = <24 2>;
- bus-range = <0 0>;
-- ranges = <02000000 0 80000000 80000000 0 20000000
-- 01000000 0 00000000 e2000000 0 00100000>;
-- clock-frequency = <3f940aa>;
-+ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
-+ 0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>;
-+ clock-frequency = <66666666>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- reg = <e0008000 1000>;
-+ reg = <0xe0008000 0x1000>;
- compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci";
- device_type = "pci";
- };
-diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts
-index fa8d9aa..663c7c5 100644
---- a/arch/powerpc/boot/dts/mpc8541cds.dts
-+++ b/arch/powerpc/boot/dts/mpc8541cds.dts
-@@ -1,7 +1,7 @@
- /*
- * MPC8541 CDS Device Tree Source
- *
-- * Copyright 2006 Freescale Semiconductor Inc.
-+ * Copyright 2006, 2008 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
-@@ -9,6 +9,7 @@
- * option) any later version.
+ struct op_mips_model op_model_mipsxx_ops = {
+diff --git a/arch/mips/pci/fixup-au1000.c b/arch/mips/pci/fixup-au1000.c
+index ca0276c..00c36c9 100644
+--- a/arch/mips/pci/fixup-au1000.c
++++ b/arch/mips/pci/fixup-au1000.c
+@@ -26,13 +26,10 @@
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+-#include <linux/types.h>
++
+ #include <linux/pci.h>
+-#include <linux/kernel.h>
+ #include <linux/init.h>
-+/dts-v1/;
-
- / {
- model = "MPC8541CDS";
-@@ -31,11 +32,11 @@
-
- PowerPC,8541 at 0 {
- device_type = "cpu";
-- reg = <0>;
-- d-cache-line-size = <20>; // 32 bytes
-- i-cache-line-size = <20>; // 32 bytes
-- d-cache-size = <8000>; // L1, 32K
-- i-cache-size = <8000>; // L1, 32K
-+ reg = <0x0>;
-+ d-cache-line-size = <32>; // 32 bytes
-+ i-cache-line-size = <32>; // 32 bytes
-+ d-cache-size = <0x8000>; // L1, 32K
-+ i-cache-size = <0x8000>; // L1, 32K
- timebase-frequency = <0>; // 33 MHz, from uboot
- bus-frequency = <0>; // 166 MHz
- clock-frequency = <0>; // 825 MHz, from uboot
-@@ -44,31 +45,31 @@
-
- memory {
- device_type = "memory";
-- reg = <00000000 08000000>; // 128M at 0x0
-+ reg = <0x0 0x8000000>; // 128M at 0x0
- };
-
- soc8541 at e0000000 {
- #address-cells = <1>;
- #size-cells = <1>;
- device_type = "soc";
-- ranges = <0 e0000000 00100000>;
-- reg = <e0000000 00001000>; // CCSRBAR 1M
-+ ranges = <0x0 0xe0000000 0x100000>;
-+ reg = <0xe0000000 0x1000>; // CCSRBAR 1M
- bus-frequency = <0>;
+-#include <asm/mach-au1x00/au1000.h>
+-
+ extern char irq_tab_alchemy[][5];
- memory-controller at 2000 {
- compatible = "fsl,8541-memory-controller";
-- reg = <2000 1000>;
-+ reg = <0x2000 0x1000>;
- interrupt-parent = <&mpic>;
-- interrupts = <12 2>;
-+ interrupts = <18 2>;
- };
+ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+diff --git a/arch/mips/pci/ops-pnx8550.c b/arch/mips/pci/ops-pnx8550.c
+index d610646..0e160d9 100644
+--- a/arch/mips/pci/ops-pnx8550.c
++++ b/arch/mips/pci/ops-pnx8550.c
+@@ -90,14 +90,14 @@ config_access(unsigned int pci_cmd, struct pci_bus *bus, unsigned int devfn, int
- l2-cache-controller at 20000 {
- compatible = "fsl,8541-l2-cache-controller";
-- reg = <20000 1000>;
-- cache-line-size = <20>; // 32 bytes
-- cache-size = <40000>; // L2, 256K
-+ reg = <0x20000 0x1000>;
-+ cache-line-size = <32>; // 32 bytes
-+ cache-size = <0x40000>; // L2, 256K
- interrupt-parent = <&mpic>;
-- interrupts = <10 2>;
-+ interrupts = <16 2>;
- };
+ loops--;
+ if (loops == 0) {
+- printk("%s : Arbiter Locked.\n", __FUNCTION__);
++ printk("%s : Arbiter Locked.\n", __func__);
+ }
+ }
- i2c at 3000 {
-@@ -76,8 +77,8 @@
- #size-cells = <0>;
- cell-index = <0>;
- compatible = "fsl-i2c";
-- reg = <3000 100>;
-- interrupts = <2b 2>;
-+ reg = <0x3000 0x100>;
-+ interrupts = <43 2>;
- interrupt-parent = <&mpic>;
- dfsrr;
- };
-@@ -86,18 +87,18 @@
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "fsl,gianfar-mdio";
-- reg = <24520 20>;
-+ reg = <0x24520 0x20>;
+ clear_status();
+ if ((pci_cmd == PCI_CMD_IOR) || (pci_cmd == PCI_CMD_IOW)) {
+ printk("%s timeout (GPPM_CTRL=%X) ioaddr %lX pci_cmd %X\n",
+- __FUNCTION__, inl(PCI_BASE | PCI_GPPM_CTRL), ioaddr,
++ __func__, inl(PCI_BASE | PCI_GPPM_CTRL), ioaddr,
+ pci_cmd);
+ }
- phy0: ethernet-phy at 0 {
- interrupt-parent = <&mpic>;
- interrupts = <5 1>;
-- reg = <0>;
-+ reg = <0x0>;
- device_type = "ethernet-phy";
- };
- phy1: ethernet-phy at 1 {
- interrupt-parent = <&mpic>;
- interrupts = <5 1>;
-- reg = <1>;
-+ reg = <0x1>;
- device_type = "ethernet-phy";
- };
- };
-@@ -107,9 +108,9 @@
- device_type = "network";
- model = "TSEC";
- compatible = "gianfar";
-- reg = <24000 1000>;
-+ reg = <0x24000 0x1000>;
- local-mac-address = [ 00 00 00 00 00 00 ];
-- interrupts = <1d 2 1e 2 22 2>;
-+ interrupts = <29 2 30 2 34 2>;
- interrupt-parent = <&mpic>;
- phy-handle = <&phy0>;
- };
-@@ -119,9 +120,9 @@
- device_type = "network";
- model = "TSEC";
- compatible = "gianfar";
-- reg = <25000 1000>;
-+ reg = <0x25000 0x1000>;
- local-mac-address = [ 00 00 00 00 00 00 ];
-- interrupts = <23 2 24 2 28 2>;
-+ interrupts = <35 2 36 2 40 2>;
- interrupt-parent = <&mpic>;
- phy-handle = <&phy1>;
- };
-@@ -130,9 +131,9 @@
- cell-index = <0>;
- device_type = "serial";
- compatible = "ns16550";
-- reg = <4500 100>; // reg base, size
-+ reg = <0x4500 0x100>; // reg base, size
- clock-frequency = <0>; // should we fill in in uboot?
-- interrupts = <2a 2>;
-+ interrupts = <42 2>;
- interrupt-parent = <&mpic>;
- };
-
-@@ -140,9 +141,9 @@
- cell-index = <1>;
- device_type = "serial";
- compatible = "ns16550";
-- reg = <4600 100>; // reg base, size
-+ reg = <0x4600 0x100>; // reg base, size
- clock-frequency = <0>; // should we fill in in uboot?
-- interrupts = <2a 2>;
-+ interrupts = <42 2>;
- interrupt-parent = <&mpic>;
- };
+diff --git a/arch/mips/philips/pnx8550/common/Makefile b/arch/mips/philips/pnx8550/common/Makefile
+deleted file mode 100644
+index 31cc1a5..0000000
+--- a/arch/mips/philips/pnx8550/common/Makefile
++++ /dev/null
+@@ -1,29 +0,0 @@
+-#
+-# Per Hallsmark, per.hallsmark at mvista.com
+-#
+-# ########################################################################
+-#
+-# This program is free software; you can distribute 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 it will be useful, but WITHOUT
+-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+-# for more details.
+-#
+-# You 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.
+-#
+-# #######################################################################
+-#
+-# Makefile for the PNX8550 specific kernel interface routines
+-# under Linux.
+-#
+-
+-obj-y := setup.o prom.o int.o reset.o time.o proc.o platform.o
+-obj-$(CONFIG_PCI) += pci.o
+-obj-$(CONFIG_KGDB) += gdb_hook.o
+-
+-EXTRA_CFLAGS += -Werror
+diff --git a/arch/mips/philips/pnx8550/common/gdb_hook.c b/arch/mips/philips/pnx8550/common/gdb_hook.c
+deleted file mode 100644
+index ad4624f..0000000
+--- a/arch/mips/philips/pnx8550/common/gdb_hook.c
++++ /dev/null
+@@ -1,109 +0,0 @@
+-/*
+- * Carsten Langgaard, carstenl at mips.com
+- * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+- *
+- * ########################################################################
+- *
+- * This program is free software; you can distribute 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 it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+- * for more details.
+- *
+- * You 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.
+- *
+- * ########################################################################
+- *
+- * This is the interface to the remote debugger stub.
+- *
+- */
+-#include <linux/types.h>
+-#include <linux/serial.h>
+-#include <linux/serialP.h>
+-#include <linux/serial_reg.h>
+-#include <linux/serial_ip3106.h>
+-
+-#include <asm/serial.h>
+-#include <asm/io.h>
+-
+-#include <uart.h>
+-
+-static struct serial_state rs_table[IP3106_NR_PORTS] = {
+-};
+-static struct async_struct kdb_port_info = {0};
+-
+-void rs_kgdb_hook(int tty_no)
+-{
+- struct serial_state *ser = &rs_table[tty_no];
+-
+- kdb_port_info.state = ser;
+- kdb_port_info.magic = SERIAL_MAGIC;
+- kdb_port_info.port = tty_no;
+- kdb_port_info.flags = ser->flags;
+-
+- /*
+- * Clear all interrupts
+- */
+- /* Clear all the transmitter FIFO counters (pointer and status) */
+- ip3106_lcr(UART_BASE, tty_no) |= IP3106_UART_LCR_TX_RST;
+- /* Clear all the receiver FIFO counters (pointer and status) */
+- ip3106_lcr(UART_BASE, tty_no) |= IP3106_UART_LCR_RX_RST;
+- /* Clear all interrupts */
+- ip3106_iclr(UART_BASE, tty_no) = IP3106_UART_INT_ALLRX |
+- IP3106_UART_INT_ALLTX;
+-
+- /*
+- * Now, initialize the UART
+- */
+- ip3106_lcr(UART_BASE, tty_no) = IP3106_UART_LCR_8BIT;
+- ip3106_baud(UART_BASE, tty_no) = 5; // 38400 Baud
+-}
+-
+-int putDebugChar(char c)
+-{
+- /* Wait until FIFO not full */
+- while (((ip3106_fifo(UART_BASE, kdb_port_info.port) & IP3106_UART_FIFO_TXFIFO) >> 16) >= 16)
+- ;
+- /* Send one char */
+- ip3106_fifo(UART_BASE, kdb_port_info.port) = c;
+-
+- return 1;
+-}
+-
+-char getDebugChar(void)
+-{
+- char ch;
+-
+- /* Wait until there is a char in the FIFO */
+- while (!((ip3106_fifo(UART_BASE, kdb_port_info.port) &
+- IP3106_UART_FIFO_RXFIFO) >> 8))
+- ;
+- /* Read one char */
+- ch = ip3106_fifo(UART_BASE, kdb_port_info.port) &
+- IP3106_UART_FIFO_RBRTHR;
+- /* Advance the RX FIFO read pointer */
+- ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_RX_NEXT;
+- return (ch);
+-}
+-
+-void rs_disable_debug_interrupts(void)
+-{
+- ip3106_ien(UART_BASE, kdb_port_info.port) = 0; /* Disable all interrupts */
+-}
+-
+-void rs_enable_debug_interrupts(void)
+-{
+- /* Clear all the transmitter FIFO counters (pointer and status) */
+- ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_TX_RST;
+- /* Clear all the receiver FIFO counters (pointer and status) */
+- ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_RX_RST;
+- /* Clear all interrupts */
+- ip3106_iclr(UART_BASE, kdb_port_info.port) = IP3106_UART_INT_ALLRX |
+- IP3106_UART_INT_ALLTX;
+- ip3106_ien(UART_BASE, kdb_port_info.port) = IP3106_UART_INT_ALLRX; /* Enable RX interrupts */
+-}
+diff --git a/arch/mips/philips/pnx8550/common/int.c b/arch/mips/philips/pnx8550/common/int.c
+deleted file mode 100644
+index aad0342..0000000
+--- a/arch/mips/philips/pnx8550/common/int.c
++++ /dev/null
+@@ -1,238 +0,0 @@
+-/*
+- *
+- * Copyright (C) 2005 Embedded Alley Solutions, Inc
+- * Ported to 2.6.
+- *
+- * Per Hallsmark, per.hallsmark at mvista.com
+- * Copyright (C) 2000, 2001 MIPS Technologies, Inc.
+- * Copyright (C) 2001 Ralf Baechle
+- *
+- * Cleaned up and bug fixing: Pete Popov, ppopov at embeddedalley.com
+- *
+- * This program is free software; you can distribute 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 it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+- * for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+- *
+- */
+-#include <linux/compiler.h>
+-#include <linux/init.h>
+-#include <linux/irq.h>
+-#include <linux/sched.h>
+-#include <linux/slab.h>
+-#include <linux/interrupt.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/random.h>
+-#include <linux/module.h>
+-
+-#include <asm/io.h>
+-#include <asm/gdb-stub.h>
+-#include <int.h>
+-#include <uart.h>
+-
+-/* default prio for interrupts */
+-/* first one is a no-no so therefore always prio 0 (disabled) */
+-static char gic_prio[PNX8550_INT_GIC_TOTINT] = {
+- 0, 1, 1, 1, 1, 15, 1, 1, 1, 1, // 0 - 9
+- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 10 - 19
+- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 20 - 29
+- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 30 - 39
+- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40 - 49
+- 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 50 - 59
+- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60 - 69
+- 1 // 70
+-};
+-
+-static void hw0_irqdispatch(int irq)
+-{
+- /* find out which interrupt */
+- irq = PNX8550_GIC_VECTOR_0 >> 3;
+-
+- if (irq == 0) {
+- printk("hw0_irqdispatch: irq 0, spurious interrupt?\n");
+- return;
+- }
+- do_IRQ(PNX8550_INT_GIC_MIN + irq);
+-}
+-
+-
+-static void timer_irqdispatch(int irq)
+-{
+- irq = (0x01c0 & read_c0_config7()) >> 6;
+-
+- if (unlikely(irq == 0)) {
+- printk("timer_irqdispatch: irq 0, spurious interrupt?\n");
+- return;
+- }
+-
+- if (irq & 0x1)
+- do_IRQ(PNX8550_INT_TIMER1);
+- if (irq & 0x2)
+- do_IRQ(PNX8550_INT_TIMER2);
+- if (irq & 0x4)
+- do_IRQ(PNX8550_INT_TIMER3);
+-}
+-
+-asmlinkage void plat_irq_dispatch(void)
+-{
+- unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+-
+- if (pending & STATUSF_IP2)
+- hw0_irqdispatch(2);
+- else if (pending & STATUSF_IP7) {
+- if (read_c0_config7() & 0x01c0)
+- timer_irqdispatch(7);
+- } else
+- spurious_interrupt();
+-}
+-
+-static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
+-{
+- unsigned long status = read_c0_status();
+-
+- status &= ~((clr_mask & 0xFF) << 8);
+- status |= (set_mask & 0xFF) << 8;
+-
+- write_c0_status(status);
+-}
+-
+-static inline void mask_gic_int(unsigned int irq_nr)
+-{
+- /* interrupt disabled, bit 26(WE_ENABLE)=1 and bit 16(enable)=0 */
+- PNX8550_GIC_REQ(irq_nr) = 1<<28; /* set priority to 0 */
+-}
+-
+-static inline void unmask_gic_int(unsigned int irq_nr)
+-{
+- /* set prio mask to lower four bits and enable interrupt */
+- PNX8550_GIC_REQ(irq_nr) = (1<<26 | 1<<16) | (1<<28) | gic_prio[irq_nr];
+-}
+-
+-static inline void mask_irq(unsigned int irq_nr)
+-{
+- if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) {
+- modify_cp0_intmask(1 << irq_nr, 0);
+- } else if ((PNX8550_INT_GIC_MIN <= irq_nr) &&
+- (irq_nr <= PNX8550_INT_GIC_MAX)) {
+- mask_gic_int(irq_nr - PNX8550_INT_GIC_MIN);
+- } else if ((PNX8550_INT_TIMER_MIN <= irq_nr) &&
+- (irq_nr <= PNX8550_INT_TIMER_MAX)) {
+- modify_cp0_intmask(1 << 7, 0);
+- } else {
+- printk("mask_irq: irq %d doesn't exist!\n", irq_nr);
+- }
+-}
+-
+-static inline void unmask_irq(unsigned int irq_nr)
+-{
+- if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) {
+- modify_cp0_intmask(0, 1 << irq_nr);
+- } else if ((PNX8550_INT_GIC_MIN <= irq_nr) &&
+- (irq_nr <= PNX8550_INT_GIC_MAX)) {
+- unmask_gic_int(irq_nr - PNX8550_INT_GIC_MIN);
+- } else if ((PNX8550_INT_TIMER_MIN <= irq_nr) &&
+- (irq_nr <= PNX8550_INT_TIMER_MAX)) {
+- modify_cp0_intmask(0, 1 << 7);
+- } else {
+- printk("mask_irq: irq %d doesn't exist!\n", irq_nr);
+- }
+-}
+-
+-int pnx8550_set_gic_priority(int irq, int priority)
+-{
+- int gic_irq = irq-PNX8550_INT_GIC_MIN;
+- int prev_priority = PNX8550_GIC_REQ(gic_irq) & 0xf;
+-
+- gic_prio[gic_irq] = priority;
+- PNX8550_GIC_REQ(gic_irq) |= (0x10000000 | gic_prio[gic_irq]);
+-
+- return prev_priority;
+-}
+-
+-static struct irq_chip level_irq_type = {
+- .name = "PNX Level IRQ",
+- .ack = mask_irq,
+- .mask = mask_irq,
+- .mask_ack = mask_irq,
+- .unmask = unmask_irq,
+-};
+-
+-static struct irqaction gic_action = {
+- .handler = no_action,
+- .flags = IRQF_DISABLED,
+- .name = "GIC",
+-};
+-
+-static struct irqaction timer_action = {
+- .handler = no_action,
+- .flags = IRQF_DISABLED,
+- .name = "Timer",
+-};
+-
+-void __init arch_init_irq(void)
+-{
+- int i;
+- int configPR;
+-
+- for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) {
+- set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq);
+- mask_irq(i); /* mask the irq just in case */
+- }
+-
+- /* init of GIC/IPC interrupts */
+- /* should be done before cp0 since cp0 init enables the GIC int */
+- for (i = PNX8550_INT_GIC_MIN; i <= PNX8550_INT_GIC_MAX; i++) {
+- int gic_int_line = i - PNX8550_INT_GIC_MIN;
+- if (gic_int_line == 0 )
+- continue; // don't fiddle with int 0
+- /*
+- * enable change of TARGET, ENABLE and ACTIVE_LOW bits
+- * set TARGET 0 to route through hw0 interrupt
+- * set ACTIVE_LOW 0 active high (correct?)
+- *
+- * We really should setup an interrupt description table
+- * to do this nicely.
+- * Note, PCI INTA is active low on the bus, but inverted
+- * in the GIC, so to us it's active high.
+- */
+- PNX8550_GIC_REQ(i - PNX8550_INT_GIC_MIN) = 0x1E000000;
+-
+- /* mask/priority is still 0 so we will not get any
+- * interrupts until it is unmasked */
+-
+- set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq);
+- }
+-
+- /* Priority level 0 */
+- PNX8550_GIC_PRIMASK_0 = PNX8550_GIC_PRIMASK_1 = 0;
+-
+- /* Set int vector table address */
+- PNX8550_GIC_VECTOR_0 = PNX8550_GIC_VECTOR_1 = 0;
+-
+- set_irq_chip_and_handler(MIPS_CPU_GIC_IRQ, &level_irq_type,
+- handle_level_irq);
+- setup_irq(MIPS_CPU_GIC_IRQ, &gic_action);
+-
+- /* init of Timer interrupts */
+- for (i = PNX8550_INT_TIMER_MIN; i <= PNX8550_INT_TIMER_MAX; i++)
+- set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq);
+-
+- /* Stop Timer 1-3 */
+- configPR = read_c0_config7();
+- configPR |= 0x00000038;
+- write_c0_config7(configPR);
+-
+- set_irq_chip_and_handler(MIPS_CPU_TIMER_IRQ, &level_irq_type,
+- handle_level_irq);
+- setup_irq(MIPS_CPU_TIMER_IRQ, &timer_action);
+-}
+-
+-EXPORT_SYMBOL(pnx8550_set_gic_priority);
+diff --git a/arch/mips/philips/pnx8550/common/pci.c b/arch/mips/philips/pnx8550/common/pci.c
+deleted file mode 100644
+index eee4f3d..0000000
+--- a/arch/mips/philips/pnx8550/common/pci.c
++++ /dev/null
+@@ -1,133 +0,0 @@
+-/*
+- *
+- * BRIEF MODULE DESCRIPTION
+- *
+- * Author: source at mvista.com
+- *
+- * This program is free software; you can distribute 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 it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+- * for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+- */
+-#include <linux/types.h>
+-#include <linux/pci.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-
+-#include <pci.h>
+-#include <glb.h>
+-#include <nand.h>
+-
+-static struct resource pci_io_resource = {
+- .start = PNX8550_PCIIO + 0x1000, /* reserve regacy I/O space */
+- .end = PNX8550_PCIIO + PNX8550_PCIIO_SIZE,
+- .name = "pci IO space",
+- .flags = IORESOURCE_IO
+-};
+-
+-static struct resource pci_mem_resource = {
+- .start = PNX8550_PCIMEM,
+- .end = PNX8550_PCIMEM + PNX8550_PCIMEM_SIZE - 1,
+- .name = "pci memory space",
+- .flags = IORESOURCE_MEM
+-};
+-
+-extern struct pci_ops pnx8550_pci_ops;
+-
+-static struct pci_controller pnx8550_controller = {
+- .pci_ops = &pnx8550_pci_ops,
+- .io_resource = &pci_io_resource,
+- .mem_resource = &pci_mem_resource,
+-};
+-
+-/* Return the total size of DRAM-memory, (RANK0 + RANK1) */
+-static inline unsigned long get_system_mem_size(void)
+-{
+- /* Read IP2031_RANK0_ADDR_LO */
+- unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010);
+- /* Read IP2031_RANK1_ADDR_HI */
+- unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018);
+-
+- return dram_r1_hi - dram_r0_lo + 1;
+-}
+-
+-static int __init pnx8550_pci_setup(void)
+-{
+- int pci_mem_code;
+- int mem_size = get_system_mem_size() >> 20;
+-
+- /* Clear the Global 2 Register, PCI Inta Output Enable Registers
+- Bit 1:Enable DAC Powerdown
+- -> 0:DACs are enabled and are working normally
+- 1:DACs are powerdown
+- Bit 0:Enable of PCI inta output
+- -> 0 = Disable PCI inta output
+- 1 = Enable PCI inta output
+- */
+- PNX8550_GLB2_ENAB_INTA_O = 0;
+-
+- /* Calc the PCI mem size code */
+- if (mem_size >= 128)
+- pci_mem_code = SIZE_128M;
+- else if (mem_size >= 64)
+- pci_mem_code = SIZE_64M;
+- else if (mem_size >= 32)
+- pci_mem_code = SIZE_32M;
+- else
+- pci_mem_code = SIZE_16M;
+-
+- /* Set PCI_XIO registers */
+- outl(pci_mem_resource.start, PCI_BASE | PCI_BASE1_LO);
+- outl(pci_mem_resource.end + 1, PCI_BASE | PCI_BASE1_HI);
+- outl(pci_io_resource.start, PCI_BASE | PCI_BASE2_LO);
+- outl(pci_io_resource.end, PCI_BASE | PCI_BASE2_HI);
+-
+- /* Send memory transaction via PCI_BASE2 */
+- outl(0x00000001, PCI_BASE | PCI_IO);
+-
+- /* Unlock the setup register */
+- outl(0xca, PCI_BASE | PCI_UNLOCKREG);
+-
+- /*
+- * BAR0 of PNX8550 (pci base 10) must be zero in order for ide
+- * to work, and in order for bus_to_baddr to work without any
+- * hacks.
+- */
+- outl(0x00000000, PCI_BASE | PCI_BASE10);
+-
+- /*
+- *These two bars are set by default or the boot code.
+- * However, it's safer to set them here so we're not boot
+- * code dependent.
+- */
+- outl(0x1be00000, PCI_BASE | PCI_BASE14); /* PNX MMIO */
+- outl(PNX8550_NAND_BASE_ADDR, PCI_BASE | PCI_BASE18); /* XIO */
+-
+- outl(PCI_EN_TA |
+- PCI_EN_PCI2MMI |
+- PCI_EN_XIO |
+- PCI_SETUP_BASE18_SIZE(SIZE_32M) |
+- PCI_SETUP_BASE18_EN |
+- PCI_SETUP_BASE14_EN |
+- PCI_SETUP_BASE10_PREF |
+- PCI_SETUP_BASE10_SIZE(pci_mem_code) |
+- PCI_SETUP_CFGMANAGE_EN |
+- PCI_SETUP_PCIARB_EN,
+- PCI_BASE |
+- PCI_SETUP); /* PCI_SETUP */
+- outl(0x00000000, PCI_BASE | PCI_CTRL); /* PCI_CONTROL */
+-
+- register_pci_controller(&pnx8550_controller);
+-
+- return 0;
+-}
+-
+-arch_initcall(pnx8550_pci_setup);
+diff --git a/arch/mips/philips/pnx8550/common/platform.c b/arch/mips/philips/pnx8550/common/platform.c
+deleted file mode 100644
+index c839436..0000000
+--- a/arch/mips/philips/pnx8550/common/platform.c
++++ /dev/null
+@@ -1,132 +0,0 @@
+-/*
+- * Platform device support for Philips PNX8550 SoCs
+- *
+- * Copyright 2005, Embedded Alley Solutions, Inc
+- *
+- * Based on arch/mips/au1000/common/platform.c
+- * Platform device support for Au1x00 SoCs.
+- *
+- * Copyright 2004, Matt Porter <mporter at kernel.crashing.org>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-#include <linux/device.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/resource.h>
+-#include <linux/serial.h>
+-#include <linux/serial_pnx8xxx.h>
+-#include <linux/platform_device.h>
+-
+-#include <int.h>
+-#include <usb.h>
+-#include <uart.h>
+-
+-static struct resource pnx8550_usb_ohci_resources[] = {
+- [0] = {
+- .start = PNX8550_USB_OHCI_OP_BASE,
+- .end = PNX8550_USB_OHCI_OP_BASE +
+- PNX8550_USB_OHCI_OP_LEN,
+- .flags = IORESOURCE_MEM,
+- },
+- [1] = {
+- .start = PNX8550_INT_USB,
+- .end = PNX8550_INT_USB,
+- .flags = IORESOURCE_IRQ,
+- },
+-};
+-
+-static struct resource pnx8550_uart_resources[] = {
+- [0] = {
+- .start = PNX8550_UART_PORT0,
+- .end = PNX8550_UART_PORT0 + 0xfff,
+- .flags = IORESOURCE_MEM,
+- },
+- [1] = {
+- .start = PNX8550_UART_INT(0),
+- .end = PNX8550_UART_INT(0),
+- .flags = IORESOURCE_IRQ,
+- },
+- [2] = {
+- .start = PNX8550_UART_PORT1,
+- .end = PNX8550_UART_PORT1 + 0xfff,
+- .flags = IORESOURCE_MEM,
+- },
+- [3] = {
+- .start = PNX8550_UART_INT(1),
+- .end = PNX8550_UART_INT(1),
+- .flags = IORESOURCE_IRQ,
+- },
+-};
+-
+-struct pnx8xxx_port pnx8xxx_ports[] = {
+- [0] = {
+- .port = {
+- .type = PORT_PNX8XXX,
+- .iotype = UPIO_MEM,
+- .membase = (void __iomem *)PNX8550_UART_PORT0,
+- .mapbase = PNX8550_UART_PORT0,
+- .irq = PNX8550_UART_INT(0),
+- .uartclk = 3692300,
+- .fifosize = 16,
+- .flags = UPF_BOOT_AUTOCONF,
+- .line = 0,
+- },
+- },
+- [1] = {
+- .port = {
+- .type = PORT_PNX8XXX,
+- .iotype = UPIO_MEM,
+- .membase = (void __iomem *)PNX8550_UART_PORT1,
+- .mapbase = PNX8550_UART_PORT1,
+- .irq = PNX8550_UART_INT(1),
+- .uartclk = 3692300,
+- .fifosize = 16,
+- .flags = UPF_BOOT_AUTOCONF,
+- .line = 1,
+- },
+- },
+-};
+-
+-/* The dmamask must be set for OHCI to work */
+-static u64 ohci_dmamask = ~(u32)0;
+-
+-static u64 uart_dmamask = ~(u32)0;
+-
+-static struct platform_device pnx8550_usb_ohci_device = {
+- .name = "pnx8550-ohci",
+- .id = -1,
+- .dev = {
+- .dma_mask = &ohci_dmamask,
+- .coherent_dma_mask = 0xffffffff,
+- },
+- .num_resources = ARRAY_SIZE(pnx8550_usb_ohci_resources),
+- .resource = pnx8550_usb_ohci_resources,
+-};
+-
+-static struct platform_device pnx8550_uart_device = {
+- .name = "pnx8xxx-uart",
+- .id = -1,
+- .dev = {
+- .dma_mask = &uart_dmamask,
+- .coherent_dma_mask = 0xffffffff,
+- .platform_data = pnx8xxx_ports,
+- },
+- .num_resources = ARRAY_SIZE(pnx8550_uart_resources),
+- .resource = pnx8550_uart_resources,
+-};
+-
+-static struct platform_device *pnx8550_platform_devices[] __initdata = {
+- &pnx8550_usb_ohci_device,
+- &pnx8550_uart_device,
+-};
+-
+-static int __init pnx8550_platform_init(void)
+-{
+- return platform_add_devices(pnx8550_platform_devices,
+- ARRAY_SIZE(pnx8550_platform_devices));
+-}
+-
+-arch_initcall(pnx8550_platform_init);
+diff --git a/arch/mips/philips/pnx8550/common/proc.c b/arch/mips/philips/pnx8550/common/proc.c
+deleted file mode 100644
+index 18b125e..0000000
+--- a/arch/mips/philips/pnx8550/common/proc.c
++++ /dev/null
+@@ -1,112 +0,0 @@
+-/*
+- * This program is free software; you can distribute 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 it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+- * for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+- */
+-#include <linux/init.h>
+-#include <linux/proc_fs.h>
+-#include <linux/irq.h>
+-#include <linux/sched.h>
+-#include <linux/slab.h>
+-#include <linux/interrupt.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/random.h>
+-
+-#include <asm/io.h>
+-#include <asm/gdb-stub.h>
+-#include <int.h>
+-#include <uart.h>
+-
+-
+-static int pnx8550_timers_read(char* page, char** start, off_t offset, int count, int* eof, void* data)
+-{
+- int len = 0;
+- int configPR = read_c0_config7();
+-
+- if (offset==0) {
+- len += sprintf(&page[len], "Timer: count, compare, tc, status\n");
+- len += sprintf(&page[len], " 1: %11i, %8i, %1i, %s\n",
+- read_c0_count(), read_c0_compare(),
+- (configPR>>6)&0x1, ((configPR>>3)&0x1)? "off":"on");
+- len += sprintf(&page[len], " 2: %11i, %8i, %1i, %s\n",
+- read_c0_count2(), read_c0_compare2(),
+- (configPR>>7)&0x1, ((configPR>>4)&0x1)? "off":"on");
+- len += sprintf(&page[len], " 3: %11i, %8i, %1i, %s\n",
+- read_c0_count3(), read_c0_compare3(),
+- (configPR>>8)&0x1, ((configPR>>5)&0x1)? "off":"on");
+- }
+-
+- return len;
+-}
+-
+-static int pnx8550_registers_read(char* page, char** start, off_t offset, int count, int* eof, void* data)
+-{
+- int len = 0;
+-
+- if (offset==0) {
+- len += sprintf(&page[len], "config1: %#10.8x\n", read_c0_config1());
+- len += sprintf(&page[len], "config2: %#10.8x\n", read_c0_config2());
+- len += sprintf(&page[len], "config3: %#10.8x\n", read_c0_config3());
+- len += sprintf(&page[len], "configPR: %#10.8x\n", read_c0_config7());
+- len += sprintf(&page[len], "status: %#10.8x\n", read_c0_status());
+- len += sprintf(&page[len], "cause: %#10.8x\n", read_c0_cause());
+- len += sprintf(&page[len], "count: %#10.8x\n", read_c0_count());
+- len += sprintf(&page[len], "count_2: %#10.8x\n", read_c0_count2());
+- len += sprintf(&page[len], "count_3: %#10.8x\n", read_c0_count3());
+- len += sprintf(&page[len], "compare: %#10.8x\n", read_c0_compare());
+- len += sprintf(&page[len], "compare_2: %#10.8x\n", read_c0_compare2());
+- len += sprintf(&page[len], "compare_3: %#10.8x\n", read_c0_compare3());
+- }
+-
+- return len;
+-}
+-
+-static struct proc_dir_entry* pnx8550_dir = NULL;
+-static struct proc_dir_entry* pnx8550_timers = NULL;
+-static struct proc_dir_entry* pnx8550_registers = NULL;
+-
+-static int pnx8550_proc_init( void )
+-{
+-
+- // Create /proc/pnx8550
+- pnx8550_dir = proc_mkdir("pnx8550", NULL);
+- if (!pnx8550_dir) {
+- printk(KERN_ERR "Can't create pnx8550 proc dir\n");
+- return -1;
+- }
+-
+- // Create /proc/pnx8550/timers
+- pnx8550_timers = create_proc_read_entry(
+- "timers",
+- 0,
+- pnx8550_dir,
+- pnx8550_timers_read,
+- NULL);
+-
+- if (!pnx8550_timers)
+- printk(KERN_ERR "Can't create pnx8550 timers proc file\n");
+-
+- // Create /proc/pnx8550/registers
+- pnx8550_registers = create_proc_read_entry(
+- "registers",
+- 0,
+- pnx8550_dir,
+- pnx8550_registers_read,
+- NULL);
+-
+- if (!pnx8550_registers)
+- printk(KERN_ERR "Can't create pnx8550 registers proc file\n");
+-
+- return 0;
+-}
+-
+-__initcall(pnx8550_proc_init);
+diff --git a/arch/mips/philips/pnx8550/common/prom.c b/arch/mips/philips/pnx8550/common/prom.c
+deleted file mode 100644
+index 2f56745..0000000
+--- a/arch/mips/philips/pnx8550/common/prom.c
++++ /dev/null
+@@ -1,129 +0,0 @@
+-/*
+- *
+- * Per Hallsmark, per.hallsmark at mvista.com
+- *
+- * Based on jmr3927/common/prom.c
+- *
+- * 2004 (c) MontaVista Software, Inc. This file is licensed under the
+- * terms of the GNU General Public License version 2. This program is
+- * licensed "as is" without any warranty of any kind, whether express
+- * or implied.
+- */
+-#include <linux/module.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/string.h>
+-#include <linux/serial_pnx8xxx.h>
+-
+-#include <asm/bootinfo.h>
+-#include <uart.h>
+-
+-/* #define DEBUG_CMDLINE */
+-
+-extern int prom_argc;
+-extern char **prom_argv, **prom_envp;
+-
+-typedef struct
+-{
+- char *name;
+-/* char *val; */
+-}t_env_var;
+-
+-
+-char * prom_getcmdline(void)
+-{
+- return &(arcs_cmdline[0]);
+-}
+-
+-void __init prom_init_cmdline(void)
+-{
+- int i;
+-
+- arcs_cmdline[0] = '\0';
+- for (i = 0; i < prom_argc; i++) {
+- strcat(arcs_cmdline, prom_argv[i]);
+- strcat(arcs_cmdline, " ");
+- }
+-}
+-
+-char *prom_getenv(char *envname)
+-{
+- /*
+- * Return a pointer to the given environment variable.
+- * Environment variables are stored in the form of "memsize=64".
+- */
+-
+- t_env_var *env = (t_env_var *)prom_envp;
+- int i;
+-
+- i = strlen(envname);
+-
+- while(env->name) {
+- if(strncmp(envname, env->name, i) == 0) {
+- return(env->name + strlen(envname) + 1);
+- }
+- env++;
+- }
+- return(NULL);
+-}
+-
+-inline unsigned char str2hexnum(unsigned char c)
+-{
+- if(c >= '0' && c <= '9')
+- return c - '0';
+- if(c >= 'a' && c <= 'f')
+- return c - 'a' + 10;
+- if(c >= 'A' && c <= 'F')
+- return c - 'A' + 10;
+- return 0; /* foo */
+-}
+-
+-inline void str2eaddr(unsigned char *ea, unsigned char *str)
+-{
+- int i;
+-
+- for(i = 0; i < 6; i++) {
+- unsigned char num;
+-
+- if((*str == '.') || (*str == ':'))
+- str++;
+- num = str2hexnum(*str++) << 4;
+- num |= (str2hexnum(*str++));
+- ea[i] = num;
+- }
+-}
+-
+-int get_ethernet_addr(char *ethernet_addr)
+-{
+- char *ethaddr_str;
+-
+- ethaddr_str = prom_getenv("ethaddr");
+- if (!ethaddr_str) {
+- printk("ethaddr not set in boot prom\n");
+- return -1;
+- }
+- str2eaddr(ethernet_addr, ethaddr_str);
+- return 0;
+-}
+-
+-void __init prom_free_prom_memory(void)
+-{
+-}
+-
+-extern int pnx8550_console_port;
+-
+-/* used by early printk */
+-void prom_putchar(char c)
+-{
+- if (pnx8550_console_port != -1) {
+- /* Wait until FIFO not full */
+- while( ((ip3106_fifo(UART_BASE, pnx8550_console_port) & PNX8XXX_UART_FIFO_TXFIFO) >> 16) >= 16)
+- ;
+- /* Send one char */
+- ip3106_fifo(UART_BASE, pnx8550_console_port) = c;
+- }
+-}
+-
+-EXPORT_SYMBOL(prom_getcmdline);
+-EXPORT_SYMBOL(get_ethernet_addr);
+-EXPORT_SYMBOL(str2eaddr);
+diff --git a/arch/mips/philips/pnx8550/common/reset.c b/arch/mips/philips/pnx8550/common/reset.c
+deleted file mode 100644
+index 7b2cbc5..0000000
+--- a/arch/mips/philips/pnx8550/common/reset.c
++++ /dev/null
+@@ -1,49 +0,0 @@
+-/*.
+- *
+- * ########################################################################
+- *
+- * This program is free software; you can distribute 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 it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+- * for more details.
+- *
+- * You 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.
+- *
+- * ########################################################################
+- *
+- * Reset the PNX8550 board.
+- *
+- */
+-#include <linux/slab.h>
+-#include <asm/reboot.h>
+-#include <glb.h>
+-
+-void pnx8550_machine_restart(char *command)
+-{
+- char head[] = "************* Machine restart *************";
+- char foot[] = "*******************************************";
+-
+- printk("\n\n");
+- printk("%s\n", head);
+- if (command != NULL)
+- printk("* %s\n", command);
+- printk("%s\n", foot);
+-
+- PNX8550_RST_CTL = PNX8550_RST_DO_SW_RST;
+-}
+-
+-void pnx8550_machine_halt(void)
+-{
+- printk("*** Machine halt. (Not implemented) ***\n");
+-}
+-
+-void pnx8550_machine_power_off(void)
+-{
+- printk("*** Machine power off. (Not implemented) ***\n");
+-}
+diff --git a/arch/mips/philips/pnx8550/common/setup.c b/arch/mips/philips/pnx8550/common/setup.c
+deleted file mode 100644
+index 92d764c..0000000
+--- a/arch/mips/philips/pnx8550/common/setup.c
++++ /dev/null
+@@ -1,157 +0,0 @@
+-/*
+- *
+- * 2.6 port, Embedded Alley Solutions, Inc
+- *
+- * Based on Per Hallsmark, per.hallsmark at mvista.com
+- *
+- * This program is free software; you can distribute 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 it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+- * for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+- */
+-#include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/ioport.h>
+-#include <linux/irq.h>
+-#include <linux/mm.h>
+-#include <linux/delay.h>
+-#include <linux/interrupt.h>
+-#include <linux/serial_pnx8xxx.h>
+-#include <linux/pm.h>
+-
+-#include <asm/cpu.h>
+-#include <asm/bootinfo.h>
+-#include <asm/irq.h>
+-#include <asm/mipsregs.h>
+-#include <asm/reboot.h>
+-#include <asm/pgtable.h>
+-#include <asm/time.h>
+-
+-#include <glb.h>
+-#include <int.h>
+-#include <pci.h>
+-#include <uart.h>
+-#include <nand.h>
+-
+-extern void __init board_setup(void);
+-extern void pnx8550_machine_restart(char *);
+-extern void pnx8550_machine_halt(void);
+-extern void pnx8550_machine_power_off(void);
+-extern struct resource ioport_resource;
+-extern struct resource iomem_resource;
+-extern void rs_kgdb_hook(int tty_no);
+-extern char *prom_getcmdline(void);
+-
+-struct resource standard_io_resources[] = {
+- {
+- .start = 0x00,
+- .end = 0x1f,
+- .name = "dma1",
+- .flags = IORESOURCE_BUSY
+- }, {
+- .start = 0x40,
+- .end = 0x5f,
+- .name = "timer",
+- .flags = IORESOURCE_BUSY
+- }, {
+- .start = 0x80,
+- .end = 0x8f,
+- .name = "dma page reg",
+- .flags = IORESOURCE_BUSY
+- }, {
+- .start = 0xc0,
+- .end = 0xdf,
+- .name = "dma2",
+- .flags = IORESOURCE_BUSY
+- },
+-};
+-
+-#define STANDARD_IO_RESOURCES ARRAY_SIZE(standard_io_resources)
+-
+-extern struct resource pci_io_resource;
+-extern struct resource pci_mem_resource;
+-
+-/* Return the total size of DRAM-memory, (RANK0 + RANK1) */
+-unsigned long get_system_mem_size(void)
+-{
+- /* Read IP2031_RANK0_ADDR_LO */
+- unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010);
+- /* Read IP2031_RANK1_ADDR_HI */
+- unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018);
+-
+- return dram_r1_hi - dram_r0_lo + 1;
+-}
+-
+-int pnx8550_console_port = -1;
+-
+-void __init plat_mem_setup(void)
+-{
+- int i;
+- char* argptr;
+-
+- board_setup(); /* board specific setup */
+-
+- _machine_restart = pnx8550_machine_restart;
+- _machine_halt = pnx8550_machine_halt;
+- pm_power_off = pnx8550_machine_power_off;
+-
+- /* Clear the Global 2 Register, PCI Inta Output Enable Registers
+- Bit 1:Enable DAC Powerdown
+- -> 0:DACs are enabled and are working normally
+- 1:DACs are powerdown
+- Bit 0:Enable of PCI inta output
+- -> 0 = Disable PCI inta output
+- 1 = Enable PCI inta output
+- */
+- PNX8550_GLB2_ENAB_INTA_O = 0;
+-
+- /* IO/MEM resources. */
+- set_io_port_base(KSEG1);
+- ioport_resource.start = 0;
+- ioport_resource.end = ~0;
+- iomem_resource.start = 0;
+- iomem_resource.end = ~0;
+-
+- /* Request I/O space for devices on this board */
+- for (i = 0; i < STANDARD_IO_RESOURCES; i++)
+- request_resource(&ioport_resource, standard_io_resources + i);
+-
+- /* Place the Mode Control bit for GPIO pin 16 in primary function */
+- /* Pin 16 is used by UART1, UA1_TX */
+- outl((PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_16_BIT) |
+- (PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_17_BIT),
+- PNX8550_GPIO_MC1);
+-
+- argptr = prom_getcmdline();
+- if ((argptr = strstr(argptr, "console=ttyS")) != NULL) {
+- argptr += strlen("console=ttyS");
+- pnx8550_console_port = *argptr == '0' ? 0 : 1;
+-
+- /* We must initialize the UART (console) before early printk */
+- /* Set LCR to 8-bit and BAUD to 38400 (no 5) */
+- ip3106_lcr(UART_BASE, pnx8550_console_port) =
+- PNX8XXX_UART_LCR_8BIT;
+- ip3106_baud(UART_BASE, pnx8550_console_port) = 5;
+- }
+-
+-#ifdef CONFIG_KGDB
+- argptr = prom_getcmdline();
+- if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
+- int line;
+- argptr += strlen("kgdb=ttyS");
+- line = *argptr == '0' ? 0 : 1;
+- rs_kgdb_hook(line);
+- pr_info("KGDB: Using ttyS%i for session, "
+- "please connect your debugger\n", line ? 1 : 0);
+- }
+-#endif
+- return;
+-}
+diff --git a/arch/mips/philips/pnx8550/common/time.c b/arch/mips/philips/pnx8550/common/time.c
+deleted file mode 100644
+index 62f495b..0000000
+--- a/arch/mips/philips/pnx8550/common/time.c
++++ /dev/null
+@@ -1,150 +0,0 @@
+-/*
+- * Copyright 2001, 2002, 2003 MontaVista Software Inc.
+- * Author: Jun Sun, jsun at mvista.com or jsun at junsun.net
+- * Copyright (C) 2007 Ralf Baechle (ralf at linux-mips.org)
+- *
+- * Common time service routines for MIPS machines. See
+- * Documents/MIPS/README.txt.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2 of the License, or (at your
+- * option) any later version.
+- */
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/param.h>
+-#include <linux/time.h>
+-#include <linux/timer.h>
+-#include <linux/smp.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/spinlock.h>
+-#include <linux/interrupt.h>
+-
+-#include <asm/bootinfo.h>
+-#include <asm/cpu.h>
+-#include <asm/time.h>
+-#include <asm/hardirq.h>
+-#include <asm/div64.h>
+-#include <asm/debug.h>
+-
+-#include <int.h>
+-#include <cm.h>
+-
+-static unsigned long cpj;
+-
+-static cycle_t hpt_read(void)
+-{
+- return read_c0_count2();
+-}
+-
+-static struct clocksource pnx_clocksource = {
+- .name = "pnx8xxx",
+- .rating = 200,
+- .read = hpt_read,
+- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+-};
+-
+-static irqreturn_t pnx8xxx_timer_interrupt(int irq, void *dev_id)
+-{
+- struct clock_event_device *c = dev_id;
+-
+- /* clear MATCH, signal the event */
+- c->event_handler(c);
+-
+- return IRQ_HANDLED;
+-}
+-
+-static struct irqaction pnx8xxx_timer_irq = {
+- .handler = pnx8xxx_timer_interrupt,
+- .flags = IRQF_DISABLED | IRQF_PERCPU,
+- .name = "pnx8xxx_timer",
+-};
+-
+-static irqreturn_t monotonic_interrupt(int irq, void *dev_id)
+-{
+- /* Timer 2 clear interrupt */
+- write_c0_compare2(-1);
+- return IRQ_HANDLED;
+-}
+-
+-static struct irqaction monotonic_irqaction = {
+- .handler = monotonic_interrupt,
+- .flags = IRQF_DISABLED,
+- .name = "Monotonic timer",
+-};
+-
+-static int pnx8xxx_set_next_event(unsigned long delta,
+- struct clock_event_device *evt)
+-{
+- write_c0_compare(delta);
+- return 0;
+-}
+-
+-static struct clock_event_device pnx8xxx_clockevent = {
+- .name = "pnx8xxx_clockevent",
+- .features = CLOCK_EVT_FEAT_ONESHOT,
+- .set_next_event = pnx8xxx_set_next_event,
+-};
+-
+-static inline void timer_ack(void)
+-{
+- write_c0_compare(cpj);
+-}
+-
+-__init void plat_time_init(void)
+-{
+- unsigned int configPR;
+- unsigned int n;
+- unsigned int m;
+- unsigned int p;
+- unsigned int pow2p;
+-
+- clockevents_register_device(&pnx8xxx_clockevent);
+- clocksource_register(&pnx_clocksource);
+-
+- /* Timer 1 start */
+- configPR = read_c0_config7();
+- configPR &= ~0x00000008;
+- write_c0_config7(configPR);
+-
+- /* Timer 2 start */
+- configPR = read_c0_config7();
+- configPR &= ~0x00000010;
+- write_c0_config7(configPR);
+-
+- /* Timer 3 stop */
+- configPR = read_c0_config7();
+- configPR |= 0x00000020;
+- write_c0_config7(configPR);
+-
+-
+- /* PLL0 sets MIPS clock (PLL1 <=> TM1, PLL6 <=> TM2, PLL5 <=> mem) */
+- /* (but only if CLK_MIPS_CTL select value [bits 3:1] is 1: FIXME) */
+-
+- n = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_N_MASK) >> 16;
+- m = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_M_MASK) >> 8;
+- p = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_P_MASK) >> 2;
+- pow2p = (1 << p);
+-
+- db_assert(m != 0 && pow2p != 0);
+-
+- /*
+- * Compute the frequency as in the PNX8550 User Manual 1.0, p.186
+- * (a.k.a. 8-10). Divide by HZ for a timer offset that results in
+- * HZ timer interrupts per second.
+- */
+- mips_hpt_frequency = 27UL * ((1000000UL * n)/(m * pow2p));
+- cpj = (mips_hpt_frequency + HZ / 2) / HZ;
+- write_c0_count(0);
+- timer_ack();
+-
+- /* Setup Timer 2 */
+- write_c0_count2(0);
+- write_c0_compare2(0xffffffff);
+-
+- setup_irq(PNX8550_INT_TIMER1, &pnx8xxx_timer_irq);
+- setup_irq(PNX8550_INT_TIMER2, &monotonic_irqaction);
+-}
+diff --git a/arch/mips/philips/pnx8550/jbs/Makefile b/arch/mips/philips/pnx8550/jbs/Makefile
+deleted file mode 100644
+index e8228db..0000000
+--- a/arch/mips/philips/pnx8550/jbs/Makefile
++++ /dev/null
+@@ -1,4 +0,0 @@
+-
+-# Makefile for the Philips JBS Board.
+-
+-lib-y := init.o board_setup.o irqmap.o
+diff --git a/arch/mips/philips/pnx8550/jbs/board_setup.c b/arch/mips/philips/pnx8550/jbs/board_setup.c
+deleted file mode 100644
+index f92826e..0000000
+--- a/arch/mips/philips/pnx8550/jbs/board_setup.c
++++ /dev/null
+@@ -1,65 +0,0 @@
+-/*
+- * JBS Specific board startup routines.
+- *
+- * Copyright 2005, Embedded Alley Solutions, 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-#include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/ioport.h>
+-#include <linux/mm.h>
+-#include <linux/console.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/delay.h>
+-
+-#include <asm/cpu.h>
+-#include <asm/bootinfo.h>
+-#include <asm/irq.h>
+-#include <asm/mipsregs.h>
+-#include <asm/reboot.h>
+-#include <asm/pgtable.h>
+-
+-#include <glb.h>
+-
+-/* CP0 hazard avoidance. */
+-#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
+- "nop; nop; nop; nop; nop; nop;\n\t" \
+- ".set reorder\n\t")
+-
+-void __init board_setup(void)
+-{
+- unsigned long config0, configpr;
+-
+- config0 = read_c0_config();
+-
+- /* clear all three cache coherency fields */
+- config0 &= ~(0x7 | (7<<25) | (7<<28));
+- config0 |= (CONF_CM_DEFAULT | (CONF_CM_DEFAULT<<25) |
+- (CONF_CM_DEFAULT<<28));
+- write_c0_config(config0);
+- BARRIER;
+-
+- configpr = read_c0_config7();
+- configpr |= (1<<19); /* enable tlb */
+- write_c0_config7(configpr);
+- BARRIER;
+-}
+diff --git a/arch/mips/philips/pnx8550/jbs/init.c b/arch/mips/philips/pnx8550/jbs/init.c
+deleted file mode 100644
+index 90b4d35..0000000
+--- a/arch/mips/philips/pnx8550/jbs/init.c
++++ /dev/null
+@@ -1,53 +0,0 @@
+-/*
+- *
+- * Copyright 2005 Embedded Alley Solutions, Inc
+- * source at embeddedalley.com
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2 of the License, or (at your
+- * option) any later version.
+- *
+- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/mm.h>
+-#include <linux/sched.h>
+-#include <linux/bootmem.h>
+-#include <asm/addrspace.h>
+-#include <asm/bootinfo.h>
+-#include <linux/string.h>
+-#include <linux/kernel.h>
+-
+-int prom_argc;
+-char **prom_argv, **prom_envp;
+-extern void __init prom_init_cmdline(void);
+-extern char *prom_getenv(char *envname);
+-
+-const char *get_system_type(void)
+-{
+- return "Philips PNX8550/JBS";
+-}
+-
+-void __init prom_init(void)
+-{
+- unsigned long memsize;
+-
+- //memsize = 0x02800000; /* Trimedia uses memory above */
+- memsize = 0x08000000; /* Trimedia uses memory above */
+- add_memory_region(0, memsize, BOOT_MEM_RAM);
+-}
+diff --git a/arch/mips/philips/pnx8550/jbs/irqmap.c b/arch/mips/philips/pnx8550/jbs/irqmap.c
+deleted file mode 100644
+index 98c3429..0000000
+--- a/arch/mips/philips/pnx8550/jbs/irqmap.c
++++ /dev/null
+@@ -1,36 +0,0 @@
+-/*
+- * Philips JBS board irqmap.
+- *
+- * Copyright 2005 Embedded Alley Solutions, Inc
+- * source at embeddealley.com
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2 of the License, or (at your
+- * option) any later version.
+- *
+- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#include <linux/init.h>
+-#include <int.h>
+-
+-char pnx8550_irq_tab[][5] __initdata = {
+- [8] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+- [9] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+- [17] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+-};
+-
+diff --git a/arch/mips/philips/pnx8550/stb810/Makefile b/arch/mips/philips/pnx8550/stb810/Makefile
+deleted file mode 100644
+index f14b592..0000000
+--- a/arch/mips/philips/pnx8550/stb810/Makefile
++++ /dev/null
+@@ -1,4 +0,0 @@
+-
+-# Makefile for the Philips STB810 Board.
+-
+-lib-y := prom_init.o board_setup.o irqmap.o
+diff --git a/arch/mips/philips/pnx8550/stb810/board_setup.c b/arch/mips/philips/pnx8550/stb810/board_setup.c
+deleted file mode 100644
+index 345d71e..0000000
+--- a/arch/mips/philips/pnx8550/stb810/board_setup.c
++++ /dev/null
+@@ -1,49 +0,0 @@
+-/*
+- * STB810 specific board startup routines.
+- *
+- * Based on the arch/mips/philips/pnx8550/jbs/board_setup.c
+- *
+- * Author: MontaVista Software, Inc.
+- * source at mvista.com
+- *
+- * Copyright 2005 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 as published by the
+- * Free Software Foundation; either version 2 of the License, or (at your
+- * option) any later version.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/ioport.h>
+-#include <linux/mm.h>
+-#include <linux/console.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/delay.h>
+-
+-#include <asm/cpu.h>
+-#include <asm/bootinfo.h>
+-#include <asm/irq.h>
+-#include <asm/mipsregs.h>
+-#include <asm/reboot.h>
+-#include <asm/pgtable.h>
+-
+-#include <glb.h>
+-
+-void __init board_setup(void)
+-{
+- unsigned long config0, configpr;
+-
+- config0 = read_c0_config();
+-
+- /* clear all three cache coherency fields */
+- config0 &= ~(0x7 | (7<<25) | (7<<28));
+- config0 |= (CONF_CM_DEFAULT | (CONF_CM_DEFAULT<<25) |
+- (CONF_CM_DEFAULT<<28));
+- write_c0_config(config0);
+-
+- configpr = read_c0_config7();
+- configpr |= (1<<19); /* enable tlb */
+- write_c0_config7(configpr);
+-}
+diff --git a/arch/mips/philips/pnx8550/stb810/irqmap.c b/arch/mips/philips/pnx8550/stb810/irqmap.c
+deleted file mode 100644
+index 5ee11e1..0000000
+--- a/arch/mips/philips/pnx8550/stb810/irqmap.c
++++ /dev/null
+@@ -1,23 +0,0 @@
+-/*
+- * Philips STB810 board irqmap.
+- *
+- * Author: MontaVista Software, Inc.
+- * source at mvista.com
+- *
+- * Copyright 2005 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 as published by the
+- * Free Software Foundation; either version 2 of the License, or (at your
+- * option) any later version.
+- */
+-
+-#include <linux/init.h>
+-#include <int.h>
+-
+-char pnx8550_irq_tab[][5] __initdata = {
+- [8] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+- [9] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+- [10] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+-};
+-
+diff --git a/arch/mips/philips/pnx8550/stb810/prom_init.c b/arch/mips/philips/pnx8550/stb810/prom_init.c
+deleted file mode 100644
+index 832dd60..0000000
+--- a/arch/mips/philips/pnx8550/stb810/prom_init.c
++++ /dev/null
+@@ -1,46 +0,0 @@
+-/*
+- * STB810 specific prom routines
+- *
+- * Author: MontaVista Software, Inc.
+- * source at mvista.com
+- *
+- * Copyright 2005 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 as published by the
+- * Free Software Foundation; either version 2 of the License, or (at your
+- * option) any later version.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/mm.h>
+-#include <linux/sched.h>
+-#include <linux/bootmem.h>
+-#include <asm/addrspace.h>
+-#include <asm/bootinfo.h>
+-#include <linux/string.h>
+-#include <linux/kernel.h>
+-
+-int prom_argc;
+-char **prom_argv, **prom_envp;
+-extern void __init prom_init_cmdline(void);
+-extern char *prom_getenv(char *envname);
+-
+-const char *get_system_type(void)
+-{
+- return "Philips PNX8550/STB810";
+-}
+-
+-void __init prom_init(void)
+-{
+- unsigned long memsize;
+-
+- prom_argc = (int) fw_arg0;
+- prom_argv = (char **) fw_arg1;
+- prom_envp = (char **) fw_arg2;
+-
+- prom_init_cmdline();
+-
+- memsize = 0x08000000; /* Trimedia uses memory above */
+- add_memory_region(0, memsize, BOOT_MEM_RAM);
+-}
+diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c
+index 855977c..6537d90 100644
+--- a/arch/mips/pmc-sierra/yosemite/setup.c
++++ b/arch/mips/pmc-sierra/yosemite/setup.c
+@@ -143,9 +143,6 @@ void __init plat_time_init(void)
+ mips_hpt_frequency = 33000000 * 3 * 5;
+ }
-@@ -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;
+-/* No other usable initialization hook than this ... */
+-extern void (*late_time_init)(void);
+-
+ unsigned long ocd_base;
- muram at 80000 {
- #address-cells = <1>;
- #size-cells = <1>;
-- ranges = <0 80000 10000>;
-+ ranges = <0x0 0x80000 0x10000>;
+ EXPORT_SYMBOL(ocd_base);
+diff --git a/arch/mips/sgi-ip27/ip27-console.c b/arch/mips/sgi-ip27/ip27-console.c
+index 3ba8306..984e561 100644
+--- a/arch/mips/sgi-ip27/ip27-console.c
++++ b/arch/mips/sgi-ip27/ip27-console.c
+@@ -8,7 +8,6 @@
+ #include <linux/init.h>
- data at 0 {
- compatible = "fsl,cpm-muram-data";
-- reg = <0 2000 9000 1000>;
-+ reg = <0x0 0x2000 0x9000 0x1000>;
- };
- };
+ #include <asm/page.h>
+-#include <asm/semaphore.h>
+ #include <asm/sn/addrs.h>
+ #include <asm/sn/sn0/hub.h>
+ #include <asm/sn/klconfig.h>
+diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c
+index 624bbdb..b6cab08 100644
+--- a/arch/mips/sgi-ip32/ip32-reset.c
++++ b/arch/mips/sgi-ip32/ip32-reset.c
+@@ -142,7 +142,7 @@ static irqreturn_t ip32_rtc_int(int irq, void *dev_id)
+ reg_c = CMOS_READ(RTC_INTR_FLAGS);
+ if (!(reg_c & RTC_IRQF)) {
+ printk(KERN_WARNING
+- "%s: RTC IRQ without RTC_IRQF\n", __FUNCTION__);
++ "%s: RTC IRQ without RTC_IRQF\n", __func__);
+ }
+ /* Wait until interrupt goes away */
+ disable_irq(MACEISA_RTC_IRQ);
+diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
+index 3f808b6..6d31f2a 100644
+--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
++++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
+@@ -173,7 +173,7 @@ static const u32 toshiba_rbtx4927_irq_debug_flag =
+ { \
+ char tmp[100]; \
+ sprintf( tmp, str ); \
+- printk( "%s(%s:%u)::%s", __FUNCTION__, __FILE__, __LINE__, tmp ); \
++ printk( "%s(%s:%u)::%s", __func__, __FILE__, __LINE__, tmp ); \
+ }
+ #else
+ #define TOSHIBA_RBTX4927_IRQ_DPRINTK(flag, str...)
+diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
+index e466e5e..2203c77 100644
+--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
++++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
+@@ -93,7 +93,7 @@ static const u32 toshiba_rbtx4927_setup_debug_flag =
+ { \
+ char tmp[100]; \
+ sprintf( tmp, str ); \
+- printk( "%s(%s:%u)::%s", __FUNCTION__, __FILE__, __LINE__, tmp ); \
++ printk( "%s(%s:%u)::%s", __func__, __FILE__, __LINE__, tmp ); \
+ }
+ #else
+ #define TOSHIBA_RBTX4927_SETUP_DPRINTK(flag, str...)
+diff --git a/arch/mips/tx4938/common/dbgio.c b/arch/mips/tx4938/common/dbgio.c
+index bea59ff..33b9c67 100644
+--- a/arch/mips/tx4938/common/dbgio.c
++++ b/arch/mips/tx4938/common/dbgio.c
+@@ -31,9 +31,7 @@
+ * Support for TX4938 in 2.6 - Hiroshi DOYU <Hiroshi_DOYU at montavista.co.jp>
+ */
-@@ -179,16 +180,16 @@
- compatible = "fsl,mpc8541-brg",
- "fsl,cpm2-brg",
- "fsl,cpm-brg";
-- reg = <919f0 10 915f0 10>;
-+ reg = <0x919f0 0x10 0x915f0 0x10>;
- };
+-#include <asm/mipsregs.h>
+-#include <asm/system.h>
+-#include <asm/tx4938/tx4938_mips.h>
++#include <linux/types>
- cpmpic: pic at 90c00 {
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <2>;
-- interrupts = <2e 2>;
-+ interrupts = <46 2>;
- interrupt-parent = <&mpic>;
-- reg = <90c00 80>;
-+ reg = <0x90c00 0x80>;
- compatible = "fsl,mpc8541-cpm-pic", "fsl,cpm2-pic";
- };
- };
-@@ -196,68 +197,68 @@
+ extern u8 txx9_sio_kdbg_rd(void);
+ extern int txx9_sio_kdbg_wr( u8 ch );
+diff --git a/arch/mips/tx4938/common/prom.c b/arch/mips/tx4938/common/prom.c
+index 3189a65..20baeae 100644
+--- a/arch/mips/tx4938/common/prom.c
++++ b/arch/mips/tx4938/common/prom.c
+@@ -13,13 +13,8 @@
+ */
- pci0: pci at e0008000 {
- cell-index = <0>;
-- interrupt-map-mask = <1f800 0 0 7>;
-+ interrupt-map-mask = <0x1f800 0x0 0x0 0x7>;
- interrupt-map = <
+ #include <linux/init.h>
+-#include <linux/mm.h>
+-#include <linux/sched.h>
+-#include <linux/bootmem.h>
+-
+-#include <asm/addrspace.h>
+-#include <asm/bootinfo.h>
+-#include <asm/tx4938/tx4938.h>
++#include <linux/types.h>
++#include <linux/io.h>
- /* 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
+ static unsigned int __init
+ tx4938_process_sdccr(u64 * addr)
+@@ -35,7 +30,7 @@ tx4938_process_sdccr(u64 * addr)
+ unsigned int bc = 4;
+ unsigned int msize = 0;
+
+- val = (*((vu64 *) (addr)));
++ val = ____raw_readq((void __iomem *)addr);
+
+ /* MVMCP -- need #defs for these bits masks */
+ sdccr_ce = ((val & (1 << 10)) >> 10);
+diff --git a/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
+index f001850..4d6a8dc 100644
+--- a/arch/mips/tx4938/toshiba_rbtx4938/irq.c
++++ b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
+@@ -67,24 +67,7 @@ IRQ Device
+ 63 RBTX4938-IOC/07 SWINT
+ */
+ #include <linux/init.h>
+-#include <linux/kernel.h>
+-#include <linux/types.h>
+-#include <linux/mm.h>
+-#include <linux/swap.h>
+-#include <linux/ioport.h>
+-#include <linux/sched.h>
+ #include <linux/interrupt.h>
+-#include <linux/pci.h>
+-#include <linux/timex.h>
+-#include <asm/bootinfo.h>
+-#include <asm/page.h>
+-#include <asm/io.h>
+-#include <asm/irq.h>
+-#include <asm/processor.h>
+-#include <asm/reboot.h>
+-#include <asm/time.h>
+-#include <asm/wbflush.h>
+-#include <linux/bootmem.h>
+ #include <asm/tx4938/rbtx4938.h>
- /* 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
+ static void toshiba_rbtx4938_irq_ioc_enable(unsigned int irq);
+@@ -99,21 +82,16 @@ static struct irq_chip toshiba_rbtx4938_irq_ioc_type = {
+ .unmask = toshiba_rbtx4938_irq_ioc_enable,
+ };
- /* 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
+-#define TOSHIBA_RBTX4938_IOC_INTR_ENAB 0xb7f02000
+-#define TOSHIBA_RBTX4938_IOC_INTR_STAT 0xb7f0200a
+-
+ int
+ toshiba_rbtx4938_irq_nested(int sw_irq)
+ {
+ u8 level3;
- /* 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
+- level3 = reg_rd08(TOSHIBA_RBTX4938_IOC_INTR_STAT) & 0xff;
+- if (level3) {
++ level3 = readb(rbtx4938_imstat_addr);
++ if (level3)
+ /* must use fls so onboard ATA has priority */
+ sw_irq = TOSHIBA_RBTX4938_IRQ_IOC_BEG + fls(level3) - 1;
+- }
- /* 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
+- wbflush();
+ return sw_irq;
+ }
- /* 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
+@@ -144,25 +122,23 @@ toshiba_rbtx4938_irq_ioc_init(void)
+ static void
+ toshiba_rbtx4938_irq_ioc_enable(unsigned int irq)
+ {
+- volatile unsigned char v;
++ unsigned char v;
- /* Bus 1 (Tundra Bridge) */
- /* IDSEL 0x12 (ISA bridge) */
-- 19000 0 0 1 &mpic 0 1
-- 19000 0 0 2 &mpic 1 1
-- 19000 0 0 3 &mpic 2 1
-- 19000 0 0 4 &mpic 3 1>;
-+ 0x19000 0x0 0x0 0x1 &mpic 0x0 0x1
-+ 0x19000 0x0 0x0 0x2 &mpic 0x1 0x1
-+ 0x19000 0x0 0x0 0x3 &mpic 0x2 0x1
-+ 0x19000 0x0 0x0 0x4 &mpic 0x3 0x1>;
- interrupt-parent = <&mpic>;
-- interrupts = <18 2>;
-+ interrupts = <24 2>;
- bus-range = <0 0>;
-- ranges = <02000000 0 80000000 80000000 0 20000000
-- 01000000 0 00000000 e2000000 0 00100000>;
-- clock-frequency = <3f940aa>;
-+ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
-+ 0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>;
-+ clock-frequency = <66666666>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- reg = <e0008000 1000>;
-+ reg = <0xe0008000 0x1000>;
- compatible = "fsl,mpc8540-pci";
- device_type = "pci";
+- v = TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
++ v = readb(rbtx4938_imask_addr);
+ v |= (1 << (irq - TOSHIBA_RBTX4938_IRQ_IOC_BEG));
+- TX4938_WR08(TOSHIBA_RBTX4938_IOC_INTR_ENAB, v);
++ writeb(v, rbtx4938_imask_addr);
+ mmiowb();
+- TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
+ }
- i8259 at 19000 {
- interrupt-controller;
- device_type = "interrupt-controller";
-- reg = <19000 0 0 0 1>;
-+ reg = <0x19000 0x0 0x0 0x0 0x1>;
- #address-cells = <0>;
- #interrupt-cells = <2>;
- compatible = "chrp,iic";
-@@ -268,24 +269,24 @@
+ static void
+ toshiba_rbtx4938_irq_ioc_disable(unsigned int irq)
+ {
+- volatile unsigned char v;
++ unsigned char v;
- pci1: pci at e0009000 {
- cell-index = <1>;
-- interrupt-map-mask = <f800 0 0 7>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
+- v = TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
++ v = readb(rbtx4938_imask_addr);
+ v &= ~(1 << (irq - TOSHIBA_RBTX4938_IRQ_IOC_BEG));
+- TX4938_WR08(TOSHIBA_RBTX4938_IOC_INTR_ENAB, v);
++ writeb(v, rbtx4938_imask_addr);
+ mmiowb();
+- TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
+ }
- /* IDSEL 0x15 */
-- a800 0 0 1 &mpic b 1
-- a800 0 0 2 &mpic b 1
-- a800 0 0 3 &mpic b 1
-- a800 0 0 4 &mpic b 1>;
-+ 0xa800 0x0 0x0 0x1 &mpic 0xb 0x1
-+ 0xa800 0x0 0x0 0x2 &mpic 0xb 0x1
-+ 0xa800 0x0 0x0 0x3 &mpic 0xb 0x1
-+ 0xa800 0x0 0x0 0x4 &mpic 0xb 0x1>;
- interrupt-parent = <&mpic>;
-- interrupts = <19 2>;
-+ interrupts = <25 2>;
- bus-range = <0 0>;
-- ranges = <02000000 0 a0000000 a0000000 0 20000000
-- 01000000 0 00000000 e3000000 0 00100000>;
-- clock-frequency = <3f940aa>;
-+ ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
-+ 0x1000000 0x0 0x0 0xe3000000 0x0 0x100000>;
-+ clock-frequency = <66666666>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- reg = <e0009000 1000>;
-+ reg = <0xe0009000 0x1000>;
- compatible = "fsl,mpc8540-pci";
- device_type = "pci";
- };
-diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts
-index 688af9d..6a0d8db 100644
---- a/arch/powerpc/boot/dts/mpc8544ds.dts
-+++ b/arch/powerpc/boot/dts/mpc8544ds.dts
-@@ -1,7 +1,7 @@
- /*
- * MPC8544 DS Device Tree Source
- *
-- * Copyright 2007 Freescale Semiconductor Inc.
-+ * Copyright 2007, 2008 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
-@@ -9,6 +9,7 @@
- * option) any later version.
- */
+ void __init arch_init_irq(void)
+@@ -174,14 +150,12 @@ void __init arch_init_irq(void)
+ /* all IRC interrupt mode are Low Active. */
+
+ /* mask all IOC interrupts */
+- *rbtx4938_imask_ptr = 0;
++ writeb(0, rbtx4938_imask_addr);
+
+ /* clear SoftInt interrupts */
+- *rbtx4938_softint_ptr = 0;
++ writeb(0, rbtx4938_softint_addr);
+ tx4938_irq_init();
+ toshiba_rbtx4938_irq_ioc_init();
+ /* Onboard 10M Ether: High Active */
+ set_irq_type(RBTX4938_IRQ_ETHER, IRQF_TRIGGER_HIGH);
+-
+- wbflush();
+ }
+diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
+index 61249f0..3a3659e 100644
+--- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c
++++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
+@@ -21,8 +21,8 @@
+ #include <linux/pm.h>
+ #include <linux/platform_device.h>
+ #include <linux/clk.h>
++#include <linux/gpio.h>
-+/dts-v1/;
- / {
- model = "MPC8544DS";
- compatible = "MPC8544DS", "MPC85xxDS";
-@@ -27,17 +28,16 @@
- };
+-#include <asm/wbflush.h>
+ #include <asm/reboot.h>
+ #include <asm/time.h>
+ #include <asm/txx9tmr.h>
+@@ -34,7 +34,7 @@
+ #endif
+ #include <linux/spi/spi.h>
+ #include <asm/tx4938/spi.h>
+-#include <asm/gpio.h>
++#include <asm/txx9pio.h>
- cpus {
-- #cpus = <1>;
- #address-cells = <1>;
- #size-cells = <0>;
+ extern char * __init prom_getcmdline(void);
+ static inline void tx4938_report_pcic_status1(struct tx4938_pcic_reg *pcicptr);
+@@ -90,12 +90,11 @@ void rbtx4938_machine_restart(char *command)
+ local_irq_disable();
- PowerPC,8544 at 0 {
- device_type = "cpu";
-- reg = <0>;
-- d-cache-line-size = <20>; // 32 bytes
-- i-cache-line-size = <20>; // 32 bytes
-- d-cache-size = <8000>; // L1, 32K
-- i-cache-size = <8000>; // L1, 32K
-+ reg = <0x0>;
-+ d-cache-line-size = <32>; // 32 bytes
-+ i-cache-line-size = <32>; // 32 bytes
-+ d-cache-size = <0x8000>; // L1, 32K
-+ i-cache-size = <0x8000>; // L1, 32K
- timebase-frequency = <0>;
- bus-frequency = <0>;
- clock-frequency = <0>;
-@@ -46,7 +46,7 @@
+ printk("Rebooting...");
+- *rbtx4938_softresetlock_ptr = 1;
+- *rbtx4938_sfvol_ptr = 1;
+- *rbtx4938_softreset_ptr = 1;
+- wbflush();
+-
+- while(1);
++ writeb(1, rbtx4938_softresetlock_addr);
++ writeb(1, rbtx4938_sfvol_addr);
++ writeb(1, rbtx4938_softreset_addr);
++ while(1)
++ ;
+ }
- memory {
- device_type = "memory";
-- reg = <00000000 00000000>; // Filled by U-Boot
-+ reg = <0x0 0x0>; // Filled by U-Boot
- };
+ void __init
+@@ -487,7 +486,7 @@ static int __init tx4938_pcibios_init(void)
+ }
- soc8544 at e0000000 {
-@@ -54,24 +54,24 @@
- #size-cells = <1>;
- device_type = "soc";
+ /* Reset PCI Bus */
+- *rbtx4938_pcireset_ptr = 0;
++ writeb(0, rbtx4938_pcireset_addr);
+ /* Reset PCIC */
+ tx4938_ccfgptr->clkctr |= TX4938_CLKCTR_PCIRST;
+ if (txboard_pci66_mode > 0)
+@@ -495,8 +494,8 @@ static int __init tx4938_pcibios_init(void)
+ mdelay(10);
+ /* clear PCIC reset */
+ tx4938_ccfgptr->clkctr &= ~TX4938_CLKCTR_PCIRST;
+- *rbtx4938_pcireset_ptr = 1;
+- wbflush();
++ writeb(1, rbtx4938_pcireset_addr);
++ mmiowb();
+ tx4938_report_pcic_status1(tx4938_pcicptr);
-- ranges = <00000000 e0000000 00100000>;
-- reg = <e0000000 00001000>; // CCSRBAR 1M
-+ ranges = <0x0 0xe0000000 0x100000>;
-+ reg = <0xe0000000 0x1000>; // CCSRBAR 1M
- bus-frequency = <0>; // Filled out by uboot.
+ tx4938_report_pciclk();
+@@ -504,15 +503,15 @@ static int __init tx4938_pcibios_init(void)
+ if (txboard_pci66_mode == 0 &&
+ txboard_pci66_check(&tx4938_pci_controller[0], 0, 0)) {
+ /* Reset PCI Bus */
+- *rbtx4938_pcireset_ptr = 0;
++ writeb(0, rbtx4938_pcireset_addr);
+ /* Reset PCIC */
+ tx4938_ccfgptr->clkctr |= TX4938_CLKCTR_PCIRST;
+ tx4938_pciclk66_setup();
+ mdelay(10);
+ /* clear PCIC reset */
+ tx4938_ccfgptr->clkctr &= ~TX4938_CLKCTR_PCIRST;
+- *rbtx4938_pcireset_ptr = 1;
+- wbflush();
++ writeb(1, rbtx4938_pcireset_addr);
++ mmiowb();
+ /* Reinitialize PCIC */
+ tx4938_report_pciclk();
+ tx4938_pcic_setup(tx4938_pcicptr, &tx4938_pci_controller[0], io_base[0], extarb);
+@@ -615,9 +614,6 @@ static void __init rbtx4938_spi_setup(void)
+ {
+ /* set SPI_SEL */
+ tx4938_ccfgptr->pcfg |= TX4938_PCFG_SPI_SEL;
+- /* chip selects for SPI devices */
+- tx4938_pioptr->dout |= (1 << SEEPROM1_CS);
+- tx4938_pioptr->dir |= (1 << SEEPROM1_CS);
+ }
+
+ static struct resource rbtx4938_fpga_resource;
+@@ -776,12 +772,13 @@ void __init tx4938_board_setup(void)
+ txx9_tmr_init(TX4938_TMR_REG(i) & 0xfffffffffULL);
+
+ /* enable DMA */
+- TX4938_WR64(0xff1fb150, TX4938_DMA_MCR_MSTEN);
+- TX4938_WR64(0xff1fb950, TX4938_DMA_MCR_MSTEN);
++ for (i = 0; i < 2; i++)
++ ____raw_writeq(TX4938_DMA_MCR_MSTEN,
++ (void __iomem *)(TX4938_DMA_REG(i) + 0x50));
- memory-controller at 2000 {
- compatible = "fsl,8544-memory-controller";
-- reg = <2000 1000>;
-+ reg = <0x2000 0x1000>;
- interrupt-parent = <&mpic>;
-- interrupts = <12 2>;
-+ interrupts = <18 2>;
- };
+ /* PIO */
+- tx4938_pioptr->maskcpu = 0;
+- tx4938_pioptr->maskext = 0;
++ __raw_writel(0, &tx4938_pioptr->maskcpu);
++ __raw_writel(0, &tx4938_pioptr->maskext);
+
+ /* TX4938 internal registers */
+ if (request_resource(&iomem_resource, &tx4938_reg_resource))
+@@ -863,10 +860,6 @@ void __init plat_mem_setup(void)
+ if (txx9_master_clock == 0)
+ txx9_master_clock = 25000000; /* 25MHz */
+ tx4938_board_setup();
+- /* setup serial stuff */
+- TX4938_WR(0xff1ff314, 0x00000000); /* h/w flow control off */
+- TX4938_WR(0xff1ff414, 0x00000000); /* h/w flow control off */
+-
+ #ifndef CONFIG_PCI
+ set_io_port_base(RBTX4938_ETHER_BASE);
+ #endif
+@@ -932,16 +925,16 @@ void __init plat_mem_setup(void)
+ pcfg = tx4938_ccfgptr->pcfg; /* updated */
+ /* fixup piosel */
+ if ((pcfg & (TX4938_PCFG_ATA_SEL | TX4938_PCFG_NDF_SEL)) ==
+- TX4938_PCFG_ATA_SEL) {
+- *rbtx4938_piosel_ptr = (*rbtx4938_piosel_ptr & 0x03) | 0x04;
+- }
++ TX4938_PCFG_ATA_SEL)
++ writeb((readb(rbtx4938_piosel_addr) & 0x03) | 0x04,
++ rbtx4938_piosel_addr);
+ else if ((pcfg & (TX4938_PCFG_ATA_SEL | TX4938_PCFG_NDF_SEL)) ==
+- TX4938_PCFG_NDF_SEL) {
+- *rbtx4938_piosel_ptr = (*rbtx4938_piosel_ptr & 0x03) | 0x08;
+- }
+- else {
+- *rbtx4938_piosel_ptr &= ~(0x08 | 0x04);
+- }
++ TX4938_PCFG_NDF_SEL)
++ writeb((readb(rbtx4938_piosel_addr) & 0x03) | 0x08,
++ rbtx4938_piosel_addr);
++ else
++ writeb(readb(rbtx4938_piosel_addr) & ~(0x08 | 0x04),
++ rbtx4938_piosel_addr);
- l2-cache-controller at 20000 {
- compatible = "fsl,8544-l2-cache-controller";
-- reg = <20000 1000>;
-- cache-line-size = <20>; // 32 bytes
-- cache-size = <40000>; // L2, 256K
-+ reg = <0x20000 0x1000>;
-+ cache-line-size = <32>; // 32 bytes
-+ cache-size = <0x40000>; // L2, 256K
- interrupt-parent = <&mpic>;
-- interrupts = <10 2>;
-+ interrupts = <16 2>;
- };
+ rbtx4938_fpga_resource.name = "FPGA Registers";
+ rbtx4938_fpga_resource.start = CPHYSADDR(RBTX4938_FPGA_REG_ADDR);
+@@ -950,17 +943,14 @@ void __init plat_mem_setup(void)
+ if (request_resource(&iomem_resource, &rbtx4938_fpga_resource))
+ printk("request resource for fpga failed\n");
- i2c at 3000 {
-@@ -79,8 +79,8 @@
- #size-cells = <0>;
- cell-index = <0>;
- compatible = "fsl-i2c";
-- reg = <3000 100>;
-- interrupts = <2b 2>;
-+ reg = <0x3000 0x100>;
-+ interrupts = <43 2>;
- interrupt-parent = <&mpic>;
- dfsrr;
- };
-@@ -90,8 +90,8 @@
- #size-cells = <0>;
- cell-index = <1>;
- compatible = "fsl-i2c";
-- reg = <3100 100>;
-- interrupts = <2b 2>;
-+ reg = <0x3100 0x100>;
-+ interrupts = <43 2>;
- interrupt-parent = <&mpic>;
- dfsrr;
- };
-@@ -100,30 +100,71 @@
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "fsl,gianfar-mdio";
-- reg = <24520 20>;
-+ reg = <0x24520 0x20>;
+- /* disable all OnBoard I/O interrupts */
+- *rbtx4938_imask_ptr = 0;
+-
+ _machine_restart = rbtx4938_machine_restart;
+ _machine_halt = rbtx4938_machine_halt;
+ pm_power_off = rbtx4938_machine_power_off;
- phy0: ethernet-phy at 0 {
- interrupt-parent = <&mpic>;
-- interrupts = <a 1>;
-- reg = <0>;
-+ interrupts = <10 1>;
-+ reg = <0x0>;
- device_type = "ethernet-phy";
- };
- phy1: ethernet-phy at 1 {
- interrupt-parent = <&mpic>;
-- interrupts = <a 1>;
-- reg = <1>;
-+ interrupts = <10 1>;
-+ reg = <0x1>;
- device_type = "ethernet-phy";
- };
- };
+- *rbtx4938_led_ptr = 0xff;
+- printk("RBTX4938 --- FPGA(Rev %02x)", *rbtx4938_fpga_rev_ptr);
+- printk(" DIPSW:%02x,%02x\n",
+- *rbtx4938_dipsw_ptr, *rbtx4938_bdipsw_ptr);
++ writeb(0xff, rbtx4938_led_addr);
++ printk(KERN_INFO "RBTX4938 --- FPGA(Rev %02x) DIPSW:%02x,%02x\n",
++ readb(rbtx4938_fpga_rev_addr),
++ readb(rbtx4938_dipsw_addr), readb(rbtx4938_bdipsw_addr));
+ }
-+ dma at 21300 {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ compatible = "fsl,mpc8544-dma", "fsl,eloplus-dma";
-+ reg = <0x21300 0x4>;
-+ ranges = <0x0 0x21100 0x200>;
-+ cell-index = <0>;
-+ dma-channel at 0 {
-+ compatible = "fsl,mpc8544-dma-channel",
-+ "fsl,eloplus-dma-channel";
-+ reg = <0x0 0x80>;
-+ cell-index = <0>;
-+ interrupt-parent = <&mpic>;
-+ interrupts = <20 2>;
-+ };
-+ dma-channel at 80 {
-+ compatible = "fsl,mpc8544-dma-channel",
-+ "fsl,eloplus-dma-channel";
-+ reg = <0x80 0x80>;
-+ cell-index = <1>;
-+ interrupt-parent = <&mpic>;
-+ interrupts = <21 2>;
-+ };
-+ dma-channel at 100 {
-+ compatible = "fsl,mpc8544-dma-channel",
-+ "fsl,eloplus-dma-channel";
-+ reg = <0x100 0x80>;
-+ cell-index = <2>;
-+ interrupt-parent = <&mpic>;
-+ interrupts = <22 2>;
-+ };
-+ dma-channel at 180 {
-+ compatible = "fsl,mpc8544-dma-channel",
-+ "fsl,eloplus-dma-channel";
-+ reg = <0x180 0x80>;
-+ cell-index = <3>;
-+ interrupt-parent = <&mpic>;
-+ interrupts = <23 2>;
-+ };
-+ };
-+
- enet0: ethernet at 24000 {
- cell-index = <0>;
- device_type = "network";
- model = "TSEC";
- compatible = "gianfar";
-- reg = <24000 1000>;
-+ reg = <0x24000 0x1000>;
- local-mac-address = [ 00 00 00 00 00 00 ];
-- interrupts = <1d 2 1e 2 22 2>;
-+ interrupts = <29 2 30 2 34 2>;
- interrupt-parent = <&mpic>;
- phy-handle = <&phy0>;
- phy-connection-type = "rgmii-id";
-@@ -134,9 +175,9 @@
- device_type = "network";
- model = "TSEC";
- compatible = "gianfar";
-- reg = <26000 1000>;
-+ reg = <0x26000 0x1000>;
- local-mac-address = [ 00 00 00 00 00 00 ];
-- interrupts = <1f 2 20 2 21 2>;
-+ interrupts = <31 2 32 2 33 2>;
- interrupt-parent = <&mpic>;
- phy-handle = <&phy1>;
- phy-connection-type = "rgmii-id";
-@@ -146,9 +187,9 @@
- cell-index = <0>;
- device_type = "serial";
- compatible = "ns16550";
-- reg = <4500 100>;
-+ reg = <0x4500 0x100>;
- clock-frequency = <0>;
-- interrupts = <2a 2>;
-+ interrupts = <42 2>;
- interrupt-parent = <&mpic>;
- };
+ static int __init rbtx4938_ne_init(void)
+@@ -984,106 +974,48 @@ device_initcall(rbtx4938_ne_init);
-@@ -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>;
- };
+ /* GPIO support */
- global-utilities at e0000 { //global utilities block
- compatible = "fsl,mpc8548-guts";
-- reg = <e0000 1000>;
-+ reg = <0xe0000 0x1000>;
- fsl,has-rstcr;
- };
+-static DEFINE_SPINLOCK(rbtx4938_spi_gpio_lock);
+-
+-static void rbtx4938_spi_gpio_set(unsigned gpio, int value)
++int gpio_to_irq(unsigned gpio)
+ {
+- u8 val;
+- unsigned long flags;
+- gpio -= 16;
+- spin_lock_irqsave(&rbtx4938_spi_gpio_lock, flags);
+- val = *rbtx4938_spics_ptr;
+- if (value)
+- val |= 1 << gpio;
+- else
+- val &= ~(1 << gpio);
+- *rbtx4938_spics_ptr = val;
+- mmiowb();
+- spin_unlock_irqrestore(&rbtx4938_spi_gpio_lock, flags);
++ return -EINVAL;
+ }
-@@ -173,7 +214,7 @@
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <2>;
-- reg = <40000 40000>;
-+ reg = <0x40000 0x40000>;
- compatible = "chrp,open-pic";
- device_type = "open-pic";
- big-endian;
-@@ -184,32 +225,32 @@
- cell-index = <0>;
- compatible = "fsl,mpc8540-pci";
- device_type = "pci";
-- interrupt-map-mask = <f800 0 0 7>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
+-static int rbtx4938_spi_gpio_dir_out(unsigned gpio, int value)
++int irq_to_gpio(unsigned irq)
+ {
+- rbtx4938_spi_gpio_set(gpio, value);
+- return 0;
++ return -EINVAL;
+ }
- /* 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
+-static DEFINE_SPINLOCK(tx4938_gpio_lock);
+-
+-static int tx4938_gpio_get(unsigned gpio)
+-{
+- return tx4938_pioptr->din & (1 << gpio);
+-}
++static DEFINE_SPINLOCK(rbtx4938_spi_gpio_lock);
- /* IDSEL 0x12 J16 Slot 2 */
+-static void tx4938_gpio_set_raw(unsigned gpio, int value)
++static void rbtx4938_spi_gpio_set(struct gpio_chip *chip, unsigned int offset,
++ int value)
+ {
+- u32 val;
+- val = tx4938_pioptr->dout;
++ u8 val;
++ unsigned long flags;
++ spin_lock_irqsave(&rbtx4938_spi_gpio_lock, flags);
++ val = readb(rbtx4938_spics_addr);
+ if (value)
+- val |= 1 << gpio;
++ val |= 1 << offset;
+ else
+- val &= ~(1 << gpio);
+- tx4938_pioptr->dout = val;
+-}
+-
+-static void tx4938_gpio_set(unsigned gpio, int value)
+-{
+- unsigned long flags;
+- spin_lock_irqsave(&tx4938_gpio_lock, flags);
+- tx4938_gpio_set_raw(gpio, value);
+- mmiowb();
+- spin_unlock_irqrestore(&tx4938_gpio_lock, flags);
+-}
+-
+-static int tx4938_gpio_dir_in(unsigned gpio)
+-{
+- spin_lock_irq(&tx4938_gpio_lock);
+- tx4938_pioptr->dir &= ~(1 << gpio);
++ val &= ~(1 << offset);
++ writeb(val, rbtx4938_spics_addr);
+ mmiowb();
+- spin_unlock_irq(&tx4938_gpio_lock);
+- return 0;
+-}
+-
+-static int tx4938_gpio_dir_out(unsigned int gpio, int value)
+-{
+- spin_lock_irq(&tx4938_gpio_lock);
+- tx4938_gpio_set_raw(gpio, value);
+- tx4938_pioptr->dir |= 1 << gpio;
+- mmiowb();
+- spin_unlock_irq(&tx4938_gpio_lock);
+- return 0;
+-}
+-
+-int gpio_direction_input(unsigned gpio)
+-{
+- if (gpio < 16)
+- return tx4938_gpio_dir_in(gpio);
+- return -EINVAL;
+-}
+-
+-int gpio_direction_output(unsigned gpio, int value)
+-{
+- if (gpio < 16)
+- return tx4938_gpio_dir_out(gpio, value);
+- if (gpio < 16 + 3)
+- return rbtx4938_spi_gpio_dir_out(gpio, value);
+- return -EINVAL;
++ spin_unlock_irqrestore(&rbtx4938_spi_gpio_lock, flags);
+ }
-- 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>;
+-int gpio_get_value(unsigned gpio)
++static int rbtx4938_spi_gpio_dir_out(struct gpio_chip *chip,
++ unsigned int offset, int value)
+ {
+- if (gpio < 16)
+- return tx4938_gpio_get(gpio);
++ rbtx4938_spi_gpio_set(chip, offset, value);
+ return 0;
+ }
- interrupt-parent = <&mpic>;
-- interrupts = <18 2>;
-- bus-range = <0 ff>;
-- ranges = <02000000 0 c0000000 c0000000 0 20000000
-- 01000000 0 00000000 e1000000 0 00010000>;
-- clock-frequency = <3f940aa>;
-+ interrupts = <24 2>;
-+ bus-range = <0 255>;
-+ ranges = <0x2000000 0x0 0xc0000000 0xc0000000 0x0 0x20000000
-+ 0x1000000 0x0 0x0 0xe1000000 0x0 0x10000>;
-+ clock-frequency = <66666666>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- reg = <e0008000 1000>;
-+ reg = <0xe0008000 0x1000>;
+-void gpio_set_value(unsigned gpio, int value)
+-{
+- if (gpio < 16)
+- tx4938_gpio_set(gpio, value);
+- else
+- rbtx4938_spi_gpio_set(gpio, value);
+-}
++static struct gpio_chip rbtx4938_spi_gpio_chip = {
++ .set = rbtx4938_spi_gpio_set,
++ .direction_output = rbtx4938_spi_gpio_dir_out,
++ .label = "RBTX4938-SPICS",
++ .base = 16,
++ .ngpio = 3,
++};
+
+ /* SPI support */
+
+@@ -1094,7 +1026,6 @@ static void __init txx9_spi_init(unsigned long base, int irq)
+ .start = base,
+ .end = base + 0x20 - 1,
+ .flags = IORESOURCE_MEM,
+- .parent = &tx4938_reg_resource,
+ }, {
+ .start = irq,
+ .flags = IORESOURCE_IRQ,
+@@ -1118,10 +1049,25 @@ static int __init rbtx4938_spi_init(void)
+ spi_eeprom_register(SEEPROM1_CS);
+ spi_eeprom_register(16 + SEEPROM2_CS);
+ spi_eeprom_register(16 + SEEPROM3_CS);
++ gpio_request(16 + SRTC_CS, "rtc-rs5c348");
++ gpio_direction_output(16 + SRTC_CS, 0);
++ gpio_request(SEEPROM1_CS, "seeprom1");
++ gpio_direction_output(SEEPROM1_CS, 1);
++ gpio_request(16 + SEEPROM2_CS, "seeprom2");
++ gpio_direction_output(16 + SEEPROM2_CS, 1);
++ gpio_request(16 + SEEPROM3_CS, "seeprom3");
++ gpio_direction_output(16 + SEEPROM3_CS, 1);
+ txx9_spi_init(TX4938_SPI_REG & 0xfffffffffULL, RBTX4938_IRQ_IRC_SPI);
+ return 0;
+ }
+-arch_initcall(rbtx4938_spi_init);
++
++static int __init rbtx4938_arch_init(void)
++{
++ txx9_gpio_init(TX4938_PIO_REG & 0xfffffffffULL, 0, 16);
++ gpiochip_add(&rbtx4938_spi_gpio_chip);
++ return rbtx4938_spi_init();
++}
++arch_initcall(rbtx4938_arch_init);
+
+ /* Watchdog support */
+
+@@ -1131,7 +1077,6 @@ static int __init txx9_wdt_init(unsigned long base)
+ .start = base,
+ .end = base + 0x100 - 1,
+ .flags = IORESOURCE_MEM,
+- .parent = &tx4938_reg_resource,
};
+ struct platform_device *dev =
+ platform_device_register_simple("txx9wdt", -1, &res, 1);
+diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c
+index 76d4b5e..c649953 100644
+--- a/arch/mips/vr41xx/common/init.c
++++ b/arch/mips/vr41xx/common/init.c
+@@ -1,7 +1,7 @@
+ /*
+ * init.c, Common initialization routines for NEC VR4100 series.
+ *
+- * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa at tripeaks.co.jp>
++ * Copyright (C) 2003-2008 Yoichi Yuasa <yoichi_yuasa at tripeaks.co.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -53,6 +53,8 @@ void __init plat_time_init(void)
+ void __init plat_mem_setup(void)
+ {
+ iomem_resource_init();
++
++ vr41xx_siu_setup();
+ }
- pci1: pcie at e0009000 {
-@@ -219,33 +260,33 @@
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- reg = <e0009000 1000>;
-- bus-range = <0 ff>;
-- ranges = <02000000 0 80000000 80000000 0 20000000
-- 01000000 0 00000000 e1010000 0 00010000>;
-- clock-frequency = <1fca055>;
-+ reg = <0xe0009000 0x1000>;
-+ bus-range = <0 255>;
-+ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
-+ 0x1000000 0x0 0x0 0xe1010000 0x0 0x10000>;
-+ clock-frequency = <33333333>;
- interrupt-parent = <&mpic>;
-- interrupts = <1a 2>;
-- interrupt-map-mask = <f800 0 0 7>;
-+ interrupts = <26 2>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
- /* IDSEL 0x0 */
-- 0000 0 0 1 &mpic 4 1
-- 0000 0 0 2 &mpic 5 1
-- 0000 0 0 3 &mpic 6 1
-- 0000 0 0 4 &mpic 7 1
-+ 0000 0x0 0x0 0x1 &mpic 0x4 0x1
-+ 0000 0x0 0x0 0x2 &mpic 0x5 0x1
-+ 0000 0x0 0x0 0x3 &mpic 0x6 0x1
-+ 0000 0x0 0x0 0x4 &mpic 0x7 0x1
- >;
- pcie at 0 {
-- reg = <0 0 0 0 0>;
-+ reg = <0x0 0x0 0x0 0x0 0x0>;
- #size-cells = <2>;
- #address-cells = <3>;
- device_type = "pci";
-- ranges = <02000000 0 80000000
-- 02000000 0 80000000
-- 0 20000000
-+ ranges = <0x2000000 0x0 0x80000000
-+ 0x2000000 0x0 0x80000000
-+ 0x0 0x20000000
-
-- 01000000 0 00000000
-- 01000000 0 00000000
-- 0 00010000>;
-+ 0x1000000 0x0 0x0
-+ 0x1000000 0x0 0x0
-+ 0x0 0x10000>;
- };
- };
+ void __init prom_init(void)
+diff --git a/arch/mips/vr41xx/common/siu.c b/arch/mips/vr41xx/common/siu.c
+index b735f45..654dee6 100644
+--- a/arch/mips/vr41xx/common/siu.c
++++ b/arch/mips/vr41xx/common/siu.c
+@@ -1,7 +1,7 @@
+ /*
+ * NEC VR4100 series SIU platform device.
+ *
+- * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa at tripeaks.co.jp>
++ * Copyright (C) 2007-2008 Yoichi Yuasa <yoichi_yuasa at tripeaks.co.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -118,3 +118,37 @@ err_free_device:
+ return retval;
+ }
+ device_initcall(vr41xx_siu_add);
++
++void __init vr41xx_siu_setup(void)
++{
++ struct uart_port port;
++ struct resource *res;
++ unsigned int *type;
++ int i;
++
++ switch (current_cpu_type()) {
++ case CPU_VR4111:
++ case CPU_VR4121:
++ type = siu_type1_ports;
++ res = siu_type1_resource;
++ break;
++ case CPU_VR4122:
++ case CPU_VR4131:
++ case CPU_VR4133:
++ type = siu_type2_ports;
++ res = siu_type2_resource;
++ break;
++ default:
++ return;
++ }
++
++ for (i = 0; i < SIU_PORTS_MAX; i++) {
++ port.line = i;
++ port.type = type[i];
++ if (port.type == PORT_UNKNOWN)
++ break;
++ port.mapbase = res[i].start;
++ port.membase = (unsigned char __iomem *)KSEG1ADDR(res[i].start);
++ vr41xx_siu_early_setup(&port);
++ }
++}
+diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile
+index ef07c95..23f2ab6 100644
+--- a/arch/mn10300/kernel/Makefile
++++ b/arch/mn10300/kernel/Makefile
+@@ -3,7 +3,7 @@
+ #
+ extra-y := head.o init_task.o vmlinux.lds
-@@ -256,33 +297,33 @@
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- reg = <e000a000 1000>;
-- bus-range = <0 ff>;
-- ranges = <02000000 0 a0000000 a0000000 0 10000000
-- 01000000 0 00000000 e1020000 0 00010000>;
-- clock-frequency = <1fca055>;
-+ reg = <0xe000a000 0x1000>;
-+ bus-range = <0 255>;
-+ ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
-+ 0x1000000 0x0 0x0 0xe1020000 0x0 0x10000>;
-+ clock-frequency = <33333333>;
- interrupt-parent = <&mpic>;
-- interrupts = <19 2>;
-- interrupt-map-mask = <f800 0 0 7>;
-+ interrupts = <25 2>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
- /* IDSEL 0x0 */
-- 0000 0 0 1 &mpic 0 1
-- 0000 0 0 2 &mpic 1 1
-- 0000 0 0 3 &mpic 2 1
-- 0000 0 0 4 &mpic 3 1
-+ 0000 0x0 0x0 0x1 &mpic 0x0 0x1
-+ 0000 0x0 0x0 0x2 &mpic 0x1 0x1
-+ 0000 0x0 0x0 0x3 &mpic 0x2 0x1
-+ 0000 0x0 0x0 0x4 &mpic 0x3 0x1
- >;
- pcie at 0 {
-- reg = <0 0 0 0 0>;
-+ reg = <0x0 0x0 0x0 0x0 0x0>;
- #size-cells = <2>;
- #address-cells = <3>;
- device_type = "pci";
-- ranges = <02000000 0 a0000000
-- 02000000 0 a0000000
-- 0 10000000
-+ ranges = <0x2000000 0x0 0xa0000000
-+ 0x2000000 0x0 0xa0000000
-+ 0x0 0x10000000
+-obj-y := process.o semaphore.o signal.o entry.o fpu.o traps.o irq.o \
++obj-y := process.o signal.o entry.o fpu.o traps.o irq.o \
+ ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \
+ switch_to.o mn10300_ksyms.o kernel_execve.o
-- 01000000 0 00000000
-- 01000000 0 00000000
-- 0 00010000>;
-+ 0x1000000 0x0 0x0
-+ 0x1000000 0x0 0x0
-+ 0x0 0x10000>;
- };
- };
+diff --git a/arch/mn10300/kernel/asm-offsets.c b/arch/mn10300/kernel/asm-offsets.c
+index ee2d9f8..2646fcb 100644
+--- a/arch/mn10300/kernel/asm-offsets.c
++++ b/arch/mn10300/kernel/asm-offsets.c
+@@ -7,6 +7,7 @@
+ #include <linux/sched.h>
+ #include <linux/signal.h>
+ #include <linux/personality.h>
++#include <linux/kbuild.h>
+ #include <asm/ucontext.h>
+ #include <asm/processor.h>
+ #include <asm/thread_info.h>
+@@ -14,14 +15,6 @@
+ #include "sigframe.h"
+ #include "mn10300-serial.h"
-@@ -293,72 +334,72 @@
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- reg = <e000b000 1000>;
-- bus-range = <0 ff>;
-- ranges = <02000000 0 b0000000 b0000000 0 00100000
-- 01000000 0 00000000 b0100000 0 00100000>;
-- clock-frequency = <1fca055>;
-+ reg = <0xe000b000 0x1000>;
-+ bus-range = <0 255>;
-+ ranges = <0x2000000 0x0 0xb0000000 0xb0000000 0x0 0x100000
-+ 0x1000000 0x0 0x0 0xb0100000 0x0 0x100000>;
-+ clock-frequency = <33333333>;
- interrupt-parent = <&mpic>;
-- interrupts = <1b 2>;
-- interrupt-map-mask = <ff00 0 0 1>;
-+ interrupts = <27 2>;
-+ interrupt-map-mask = <0xff00 0x0 0x0 0x1>;
- interrupt-map = <
- // IDSEL 0x1c USB
-- e000 0 0 1 &i8259 c 2
-- e100 0 0 2 &i8259 9 2
-- e200 0 0 3 &i8259 a 2
-- e300 0 0 4 &i8259 b 2
-+ 0xe000 0x0 0x0 0x1 &i8259 0xc 0x2
-+ 0xe100 0x0 0x0 0x2 &i8259 0x9 0x2
-+ 0xe200 0x0 0x0 0x3 &i8259 0xa 0x2
-+ 0xe300 0x0 0x0 0x4 &i8259 0xb 0x2
+-#define DEFINE(sym, val) \
+- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+-
+-#define BLANK() asm volatile("\n->")
+-
+-#define OFFSET(sym, str, mem) \
+- DEFINE(sym, offsetof(struct str, mem));
+-
+ void foo(void)
+ {
+ OFFSET(SIGCONTEXT_d0, sigcontext, d0);
+diff --git a/arch/mn10300/kernel/semaphore.c b/arch/mn10300/kernel/semaphore.c
+deleted file mode 100644
+index 9153c40..0000000
+--- a/arch/mn10300/kernel/semaphore.c
++++ /dev/null
+@@ -1,149 +0,0 @@
+-/* MN10300 Semaphore implementation
+- *
+- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+- * Written by David Howells (dhowells at redhat.com)
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public Licence
+- * as published by the Free Software Foundation; either version
+- * 2 of the Licence, or (at your option) any later version.
+- */
+-#include <linux/sched.h>
+-#include <linux/module.h>
+-#include <asm/semaphore.h>
+-
+-struct sem_waiter {
+- struct list_head list;
+- struct task_struct *task;
+-};
+-
+-#if SEMAPHORE_DEBUG
+-void semtrace(struct semaphore *sem, const char *str)
+-{
+- if (sem->debug)
+- printk(KERN_DEBUG "[%d] %s({%d,%d})\n",
+- current->pid,
+- str,
+- atomic_read(&sem->count),
+- list_empty(&sem->wait_list) ? 0 : 1);
+-}
+-#else
+-#define semtrace(SEM, STR) do { } while (0)
+-#endif
+-
+-/*
+- * wait for a token to be granted from a semaphore
+- * - entered with lock held and interrupts disabled
+- */
+-void __down(struct semaphore *sem, unsigned long flags)
+-{
+- struct task_struct *tsk = current;
+- struct sem_waiter waiter;
+-
+- semtrace(sem, "Entering __down");
+-
+- /* set up my own style of waitqueue */
+- waiter.task = tsk;
+- get_task_struct(tsk);
+-
+- list_add_tail(&waiter.list, &sem->wait_list);
+-
+- /* we don't need to touch the semaphore struct anymore */
+- spin_unlock_irqrestore(&sem->wait_lock, flags);
+-
+- /* wait to be given the semaphore */
+- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+-
+- for (;;) {
+- if (!waiter.task)
+- break;
+- schedule();
+- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+- }
+-
+- tsk->state = TASK_RUNNING;
+- semtrace(sem, "Leaving __down");
+-}
+-EXPORT_SYMBOL(__down);
+-
+-/*
+- * interruptibly wait for a token to be granted from a semaphore
+- * - entered with lock held and interrupts disabled
+- */
+-int __down_interruptible(struct semaphore *sem, unsigned long flags)
+-{
+- struct task_struct *tsk = current;
+- struct sem_waiter waiter;
+- int ret;
+-
+- semtrace(sem, "Entering __down_interruptible");
+-
+- /* set up my own style of waitqueue */
+- waiter.task = tsk;
+- get_task_struct(tsk);
+-
+- list_add_tail(&waiter.list, &sem->wait_list);
+-
+- /* we don't need to touch the semaphore struct anymore */
+- set_task_state(tsk, TASK_INTERRUPTIBLE);
+-
+- spin_unlock_irqrestore(&sem->wait_lock, flags);
+-
+- /* wait to be given the semaphore */
+- ret = 0;
+- for (;;) {
+- if (!waiter.task)
+- break;
+- if (unlikely(signal_pending(current)))
+- goto interrupted;
+- schedule();
+- set_task_state(tsk, TASK_INTERRUPTIBLE);
+- }
+-
+- out:
+- tsk->state = TASK_RUNNING;
+- semtrace(sem, "Leaving __down_interruptible");
+- return ret;
+-
+- interrupted:
+- spin_lock_irqsave(&sem->wait_lock, flags);
+- list_del(&waiter.list);
+- spin_unlock_irqrestore(&sem->wait_lock, flags);
+-
+- ret = 0;
+- if (!waiter.task) {
+- put_task_struct(current);
+- ret = -EINTR;
+- }
+- goto out;
+-}
+-EXPORT_SYMBOL(__down_interruptible);
+-
+-/*
+- * release a single token back to a semaphore
+- * - entered with lock held and interrupts disabled
+- */
+-void __up(struct semaphore *sem)
+-{
+- struct task_struct *tsk;
+- struct sem_waiter *waiter;
+-
+- semtrace(sem, "Entering __up");
+-
+- /* grant the token to the process at the front of the queue */
+- waiter = list_entry(sem->wait_list.next, struct sem_waiter, list);
+-
+- /* We must be careful not to touch 'waiter' after we set ->task = NULL.
+- * It is an allocated on the waiter's stack and may become invalid at
+- * any time after that point (due to a wakeup from another source).
+- */
+- list_del_init(&waiter->list);
+- tsk = waiter->task;
+- smp_mb();
+- waiter->task = NULL;
+- wake_up_process(tsk);
+- put_task_struct(tsk);
+-
+- semtrace(sem, "Leaving __up");
+-}
+-EXPORT_SYMBOL(__up);
+diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.h b/arch/mn10300/unit-asb2305/pci-asb2305.h
+index 84634fa..9763d1c 100644
+--- a/arch/mn10300/unit-asb2305/pci-asb2305.h
++++ b/arch/mn10300/unit-asb2305/pci-asb2305.h
+@@ -23,8 +23,6 @@
+ #define PCI_PROBE_BIOS 1
+ #define PCI_PROBE_CONF1 2
+ #define PCI_PROBE_CONF2 4
+-#define PCI_NO_SORT 0x100
+-#define PCI_BIOS_SORT 0x200
+ #define PCI_NO_CHECKS 0x400
+ #define PCI_ASSIGN_ROMS 0x1000
+ #define PCI_BIOS_IRQ_SCAN 0x2000
+diff --git a/arch/mn10300/unit-asb2305/pci-iomap.c b/arch/mn10300/unit-asb2305/pci-iomap.c
+index dbceae4..c1a8d8f 100644
+--- a/arch/mn10300/unit-asb2305/pci-iomap.c
++++ b/arch/mn10300/unit-asb2305/pci-iomap.c
+@@ -16,8 +16,8 @@
+ */
+ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+ {
+- unsigned long start = pci_resource_start(dev, bar);
+- unsigned long len = pci_resource_len(dev, bar);
++ resource_size_t start = pci_resource_start(dev, bar);
++ resource_size_t len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
- // IDSEL 0x1d Audio
-- e800 0 0 1 &i8259 6 2
-+ 0xe800 0x0 0x0 0x1 &i8259 0x6 0x2
+ if (!len || !start)
+diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
+index 27827bc..1f6585a 100644
+--- a/arch/parisc/kernel/Makefile
++++ b/arch/parisc/kernel/Makefile
+@@ -9,7 +9,7 @@ AFLAGS_pacache.o := -traditional
- // 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
+ obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \
+ pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
+- ptrace.o hardware.o inventory.o drivers.o semaphore.o \
++ ptrace.o hardware.o inventory.o drivers.o \
+ signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \
+ process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \
+ topology.o
+diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c
+index eaa79bc..3efc0b7 100644
+--- a/arch/parisc/kernel/asm-offsets.c
++++ b/arch/parisc/kernel/asm-offsets.c
+@@ -32,6 +32,7 @@
+ #include <linux/thread_info.h>
+ #include <linux/ptrace.h>
+ #include <linux/hardirq.h>
++#include <linux/kbuild.h>
- // 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
- >;
+ #include <asm/pgtable.h>
+ #include <asm/ptrace.h>
+@@ -39,11 +40,6 @@
+ #include <asm/pdc.h>
+ #include <asm/uaccess.h>
- pcie at 0 {
-- reg = <0 0 0 0 0>;
-+ reg = <0x0 0x0 0x0 0x0 0x0>;
- #size-cells = <2>;
- #address-cells = <3>;
- device_type = "pci";
-- ranges = <02000000 0 b0000000
-- 02000000 0 b0000000
-- 0 00100000
-+ ranges = <0x2000000 0x0 0xb0000000
-+ 0x2000000 0x0 0xb0000000
-+ 0x0 0x100000
+-#define DEFINE(sym, val) \
+- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+-
+-#define BLANK() asm volatile("\n->" : : )
+-
+ #ifdef CONFIG_64BIT
+ #define FRAME_SIZE 128
+ #else
+diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
+index 7aca704..5b7fc4a 100644
+--- a/arch/parisc/kernel/parisc_ksyms.c
++++ b/arch/parisc/kernel/parisc_ksyms.c
+@@ -69,11 +69,6 @@ EXPORT_SYMBOL(memcpy_toio);
+ EXPORT_SYMBOL(memcpy_fromio);
+ EXPORT_SYMBOL(memset_io);
-- 01000000 0 00000000
-- 01000000 0 00000000
-- 0 00100000>;
-+ 0x1000000 0x0 0x0
-+ 0x1000000 0x0 0x0
-+ 0x0 0x100000>;
+-#include <asm/semaphore.h>
+-EXPORT_SYMBOL(__up);
+-EXPORT_SYMBOL(__down_interruptible);
+-EXPORT_SYMBOL(__down);
+-
+ extern void $$divI(void);
+ extern void $$divU(void);
+ extern void $$remI(void);
+diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
+index 9448d4e..ccd61b9 100644
+--- a/arch/parisc/kernel/pci-dma.c
++++ b/arch/parisc/kernel/pci-dma.c
+@@ -397,10 +397,9 @@ pcxl_dma_init(void)
+ "pcxl_dma_init: Unable to create gsc /proc dir entry\n");
+ else {
+ struct proc_dir_entry* ent;
+- ent = create_proc_entry("pcxl_dma", 0, proc_gsc_root);
+- if (ent)
+- ent->proc_fops = &proc_pcxl_dma_ops;
+- else
++ ent = proc_create("pcxl_dma", 0, proc_gsc_root,
++ &proc_pcxl_dma_ops);
++ if (!ent)
+ printk(KERN_WARNING
+ "pci-dma.c: Unable to create pcxl_dma /proc entry.\n");
+ }
+diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
+index 507d0ac..6936386 100644
+--- a/arch/parisc/kernel/pci.c
++++ b/arch/parisc/kernel/pci.c
+@@ -287,23 +287,15 @@ void pcibios_align_resource(void *data, struct resource *res,
+ */
+ int pcibios_enable_device(struct pci_dev *dev, int mask)
+ {
+- u16 cmd;
+- int idx;
++ int err;
++ u16 cmd, old_cmd;
- uli1575 at 0 {
-- reg = <0 0 0 0 0>;
-+ reg = <0x0 0x0 0x0 0x0 0x0>;
- #size-cells = <2>;
- #address-cells = <3>;
-- ranges = <02000000 0 b0000000
-- 02000000 0 b0000000
-- 0 00100000
-+ ranges = <0x2000000 0x0 0xb0000000
-+ 0x2000000 0x0 0xb0000000
-+ 0x0 0x100000
+- pci_read_config_word(dev, PCI_COMMAND, &cmd);
+-
+- for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) {
+- struct resource *r = &dev->resource[idx];
++ err = pci_enable_resources(dev, mask);
++ if (err < 0)
++ return err;
-- 01000000 0 00000000
-- 01000000 0 00000000
-- 0 00100000>;
-+ 0x1000000 0x0 0x0
-+ 0x1000000 0x0 0x0
-+ 0x0 0x100000>;
- isa at 1e {
- device_type = "isa";
- #interrupt-cells = <2>;
- #size-cells = <1>;
- #address-cells = <2>;
-- reg = <f000 0 0 0 0>;
-- ranges = <1 0
-- 01000000 0 0
-- 00001000>;
-+ reg = <0xf000 0x0 0x0 0x0 0x0>;
-+ ranges = <0x1 0x0
-+ 0x1000000 0x0 0x0
-+ 0x1000>;
- interrupt-parent = <&i8259>;
+- /* only setup requested resources */
+- if (!(mask & (1<<idx)))
+- continue;
+-
+- if (r->flags & IORESOURCE_IO)
+- cmd |= PCI_COMMAND_IO;
+- if (r->flags & IORESOURCE_MEM)
+- cmd |= PCI_COMMAND_MEMORY;
+- }
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ old_cmd = cmd;
- i8259: interrupt-controller at 20 {
-- reg = <1 20 2
-- 1 a0 2
-- 1 4d0 2>;
-+ reg = <0x1 0x20 0x2
-+ 0x1 0xa0 0x2
-+ 0x1 0x4d0 0x2>;
- interrupt-controller;
- device_type = "interrupt-controller";
- #address-cells = <0>;
-@@ -371,28 +412,28 @@
- i8042 at 60 {
- #size-cells = <0>;
- #address-cells = <1>;
-- reg = <1 60 1 1 64 1>;
-- interrupts = <1 3 c 3>;
-+ reg = <0x1 0x60 0x1 0x1 0x64 0x1>;
-+ interrupts = <1 3 12 3>;
- interrupt-parent = <&i8259>;
+ cmd |= (PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
- keyboard at 0 {
-- reg = <0>;
-+ reg = <0x0>;
- compatible = "pnpPNP,303";
- };
+@@ -312,8 +304,12 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
+ if (dev->bus->bridge_ctl & PCI_BRIDGE_CTL_FAST_BACK)
+ cmd |= PCI_COMMAND_FAST_BACK;
+ #endif
+- DBGC("PCIBIOS: Enabling device %s cmd 0x%04x\n", pci_name(dev), cmd);
+- pci_write_config_word(dev, PCI_COMMAND, cmd);
++
++ if (cmd != old_cmd) {
++ dev_info(&dev->dev, "enabling SERR and PARITY (%04x -> %04x)\n",
++ old_cmd, cmd);
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++ }
+ return 0;
+ }
- mouse at 1 {
-- reg = <1>;
-+ reg = <0x1>;
- compatible = "pnpPNP,f03";
- };
- };
+diff --git a/arch/parisc/kernel/semaphore.c b/arch/parisc/kernel/semaphore.c
+deleted file mode 100644
+index ee806bc..0000000
+--- a/arch/parisc/kernel/semaphore.c
++++ /dev/null
+@@ -1,102 +0,0 @@
+-/*
+- * Semaphore implementation Copyright (c) 2001 Matthew Wilcox, Hewlett-Packard
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/spinlock.h>
+-#include <linux/errno.h>
+-#include <linux/init.h>
+-
+-/*
+- * Semaphores are complex as we wish to avoid using two variables.
+- * `count' has multiple roles, depending on its value. If it is positive
+- * or zero, there are no waiters. The functions here will never be
+- * called; see <asm/semaphore.h>
+- *
+- * When count is -1 it indicates there is at least one task waiting
+- * for the semaphore.
+- *
+- * When count is less than that, there are '- count - 1' wakeups
+- * pending. ie if it has value -3, there are 2 wakeups pending.
+- *
+- * Note that these functions are only called when there is contention
+- * on the lock, and as such all this is the "non-critical" part of the
+- * whole semaphore business. The critical part is the inline stuff in
+- * <asm/semaphore.h> where we want to avoid any extra jumps and calls.
+- */
+-void __up(struct semaphore *sem)
+-{
+- sem->count--;
+- wake_up(&sem->wait);
+-}
+-
+-#define wakers(count) (-1 - count)
+-
+-#define DOWN_HEAD \
+- int ret = 0; \
+- DECLARE_WAITQUEUE(wait, current); \
+- \
+- /* Note that someone is waiting */ \
+- if (sem->count == 0) \
+- sem->count = -1; \
+- \
+- /* protected by the sentry still -- use unlocked version */ \
+- wait.flags = WQ_FLAG_EXCLUSIVE; \
+- __add_wait_queue_tail(&sem->wait, &wait); \
+- lost_race: \
+- spin_unlock_irq(&sem->sentry); \
+-
+-#define DOWN_TAIL \
+- spin_lock_irq(&sem->sentry); \
+- if (wakers(sem->count) == 0 && ret == 0) \
+- goto lost_race; /* Someone stole our wakeup */ \
+- __remove_wait_queue(&sem->wait, &wait); \
+- current->state = TASK_RUNNING; \
+- if (!waitqueue_active(&sem->wait) && (sem->count < 0)) \
+- sem->count = wakers(sem->count);
+-
+-#define UPDATE_COUNT \
+- sem->count += (sem->count < 0) ? 1 : - 1;
+-
+-
+-void __sched __down(struct semaphore * sem)
+-{
+- DOWN_HEAD
+-
+- for(;;) {
+- set_task_state(current, TASK_UNINTERRUPTIBLE);
+- /* we can _read_ this without the sentry */
+- if (sem->count != -1)
+- break;
+- schedule();
+- }
+-
+- DOWN_TAIL
+- UPDATE_COUNT
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+- DOWN_HEAD
+-
+- for(;;) {
+- set_task_state(current, TASK_INTERRUPTIBLE);
+- /* we can _read_ this without the sentry */
+- if (sem->count != -1)
+- break;
+-
+- if (signal_pending(current)) {
+- ret = -EINTR;
+- break;
+- }
+- schedule();
+- }
+-
+- DOWN_TAIL
+-
+- if (!ret) {
+- UPDATE_COUNT
+- }
+-
+- return ret;
+-}
+diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
+index 50bbf33..71efd6a 100644
+--- a/arch/parisc/kernel/sys_parisc32.c
++++ b/arch/parisc/kernel/sys_parisc32.c
+@@ -49,7 +49,6 @@
- rtc at 70 {
- compatible = "pnpPNP,b00";
-- reg = <1 70 2>;
-+ reg = <0x1 0x70 0x2>;
- };
+ #include <asm/types.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <asm/mmu_context.h>
- gpio at 400 {
-- reg = <1 400 80>;
-+ reg = <0x1 0x400 0x80>;
- };
- };
- };
-diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts
-index 1f470c6..fa298a8 100644
---- a/arch/powerpc/boot/dts/mpc8548cds.dts
-+++ b/arch/powerpc/boot/dts/mpc8548cds.dts
-@@ -1,7 +1,7 @@
- /*
- * MPC8548 CDS Device Tree Source
- *
-- * Copyright 2006 Freescale Semiconductor Inc.
-+ * Copyright 2006, 2008 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
-@@ -9,6 +9,7 @@
- * option) any later version.
- */
+ #include "sys32.h"
+diff --git a/arch/parisc/lib/iomap.c b/arch/parisc/lib/iomap.c
+index f4a8116..9abed07 100644
+--- a/arch/parisc/lib/iomap.c
++++ b/arch/parisc/lib/iomap.c
+@@ -438,8 +438,8 @@ void ioport_unmap(void __iomem *addr)
+ /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+ {
+- unsigned long start = pci_resource_start(dev, bar);
+- unsigned long len = pci_resource_len(dev, bar);
++ resource_size_t start = pci_resource_start(dev, bar);
++ resource_size_t len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (!len || !start)
+diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
+index eb80f5e..1f01284 100644
+--- a/arch/parisc/mm/init.c
++++ b/arch/parisc/mm/init.c
+@@ -603,15 +603,18 @@ void show_mem(void)
+ #ifdef CONFIG_DISCONTIGMEM
+ {
+ struct zonelist *zl;
+- int i, j, k;
++ int i, j;
+
+ for (i = 0; i < npmem_ranges; i++) {
++ zl = node_zonelist(i);
+ for (j = 0; j < MAX_NR_ZONES; j++) {
+- zl = NODE_DATA(i)->node_zonelists + j;
++ struct zoneref *z;
++ struct zone *zone;
+
+ printk("Zone list for zone %d on node %d: ", j, i);
+- for (k = 0; zl->zones[k] != NULL; k++)
+- printk("[%d/%s] ", zone_to_nid(zl->zones[k]), zl->zones[k]->name);
++ for_each_zone_zonelist(zone, z, zl, j)
++ printk("[%d/%s] ", zone_to_nid(zone),
++ zone->name);
+ printk("\n");
+ }
+ }
+diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
+index 1189d8d..3934e26 100644
+--- a/arch/powerpc/Kconfig
++++ b/arch/powerpc/Kconfig
+@@ -49,6 +49,19 @@ config IRQ_PER_CPU
+ bool
+ default y
-+/dts-v1/;
++config STACKTRACE_SUPPORT
++ bool
++ default y
++
++config TRACE_IRQFLAGS_SUPPORT
++ bool
++ depends on PPC64
++ default y
++
++config LOCKDEP_SUPPORT
++ bool
++ default y
++
+ config RWSEM_GENERIC_SPINLOCK
+ bool
- / {
- model = "MPC8548CDS";
-@@ -36,11 +37,11 @@
+@@ -81,6 +94,11 @@ config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
- PowerPC,8548 at 0 {
- device_type = "cpu";
-- reg = <0>;
-- d-cache-line-size = <20>; // 32 bytes
-- i-cache-line-size = <20>; // 32 bytes
-- d-cache-size = <8000>; // L1, 32K
-- i-cache-size = <8000>; // L1, 32K
-+ reg = <0x0>;
-+ d-cache-line-size = <32>; // 32 bytes
-+ i-cache-line-size = <32>; // 32 bytes
-+ d-cache-size = <0x8000>; // L1, 32K
-+ i-cache-size = <0x8000>; // L1, 32K
- timebase-frequency = <0>; // 33 MHz, from uboot
- bus-frequency = <0>; // 166 MHz
- clock-frequency = <0>; // 825 MHz, from uboot
-@@ -49,31 +50,31 @@
++config GENERIC_GPIO
++ bool
++ help
++ Generic GPIO API support
++
+ config ARCH_NO_VIRT_TO_BUS
+ def_bool PPC64
- memory {
- device_type = "memory";
-- reg = <00000000 08000000>; // 128M at 0x0
-+ reg = <0x0 0x8000000>; // 128M at 0x0
- };
+@@ -91,6 +109,7 @@ config PPC
+ select HAVE_OPROFILE
+ select HAVE_KPROBES
+ select HAVE_KRETPROBES
++ select HAVE_LMB
- soc8548 at e0000000 {
- #address-cells = <1>;
- #size-cells = <1>;
- device_type = "soc";
-- ranges = <00000000 e0000000 00100000>;
-- reg = <e0000000 00001000>; // CCSRBAR
-+ ranges = <0x0 0xe0000000 0x100000>;
-+ reg = <0xe0000000 0x1000>; // CCSRBAR
- bus-frequency = <0>;
+ config EARLY_PRINTK
+ bool
+@@ -210,15 +229,6 @@ source kernel/Kconfig.hz
+ source kernel/Kconfig.preempt
+ source "fs/Kconfig.binfmt"
- memory-controller at 2000 {
- compatible = "fsl,8548-memory-controller";
-- reg = <2000 1000>;
-+ reg = <0x2000 0x1000>;
- interrupt-parent = <&mpic>;
-- interrupts = <12 2>;
-+ interrupts = <18 2>;
- };
+-# We optimistically allocate largepages from the VM, so make the limit
+-# large enough (16MB). This badly named config option is actually
+-# max order + 1
+-config FORCE_MAX_ZONEORDER
+- int
+- depends on PPC64
+- default "9" if PPC_64K_PAGES
+- default "13"
+-
+ config HUGETLB_PAGE_SIZE_VARIABLE
+ bool
+ depends on HUGETLB_PAGE
+@@ -307,6 +317,16 @@ config CRASH_DUMP
- l2-cache-controller at 20000 {
- compatible = "fsl,8548-l2-cache-controller";
-- reg = <20000 1000>;
-- cache-line-size = <20>; // 32 bytes
-- cache-size = <80000>; // L2, 512K
-+ reg = <0x20000 0x1000>;
-+ cache-line-size = <32>; // 32 bytes
-+ cache-size = <0x80000>; // L2, 512K
- interrupt-parent = <&mpic>;
-- interrupts = <10 2>;
-+ interrupts = <16 2>;
- };
+ Don't change this unless you know what you are doing.
- i2c at 3000 {
-@@ -81,8 +82,8 @@
- #size-cells = <0>;
- cell-index = <0>;
- compatible = "fsl-i2c";
-- reg = <3000 100>;
-- interrupts = <2b 2>;
-+ reg = <0x3000 0x100>;
-+ interrupts = <43 2>;
- interrupt-parent = <&mpic>;
- dfsrr;
- };
-@@ -92,8 +93,8 @@
- #size-cells = <0>;
- cell-index = <1>;
- compatible = "fsl-i2c";
-- reg = <3100 100>;
-- interrupts = <2b 2>;
-+ reg = <0x3100 0x100>;
-+ interrupts = <43 2>;
- interrupt-parent = <&mpic>;
- dfsrr;
- };
-@@ -102,30 +103,30 @@
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "fsl,gianfar-mdio";
-- reg = <24520 20>;
-+ reg = <0x24520 0x20>;
++config PHYP_DUMP
++ bool "Hypervisor-assisted dump (EXPERIMENTAL)"
++ depends on PPC_PSERIES && EXPERIMENTAL
++ help
++ Hypervisor-assisted dump is meant to be a kdump replacement
++ offering robustness and speed not possible without system
++ hypervisor assistence.
++
++ If unsure, say "N"
++
+ config PPCBUG_NVRAM
+ bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC
+ default y if PPC_PREP
+@@ -381,6 +401,26 @@ config PPC_64K_PAGES
+ while on hardware with such support, it will be used to map
+ normal application pages.
- phy0: ethernet-phy at 0 {
- interrupt-parent = <&mpic>;
- interrupts = <5 1>;
-- reg = <0>;
-+ reg = <0x0>;
- device_type = "ethernet-phy";
- };
- phy1: ethernet-phy at 1 {
- interrupt-parent = <&mpic>;
- interrupts = <5 1>;
-- reg = <1>;
-+ reg = <0x1>;
- device_type = "ethernet-phy";
- };
- phy2: ethernet-phy at 2 {
- interrupt-parent = <&mpic>;
- interrupts = <5 1>;
-- reg = <2>;
-+ reg = <0x2>;
- device_type = "ethernet-phy";
- };
- phy3: ethernet-phy at 3 {
- interrupt-parent = <&mpic>;
- interrupts = <5 1>;
-- reg = <3>;
-+ reg = <0x3>;
- device_type = "ethernet-phy";
- };
- };
-@@ -135,9 +136,9 @@
- device_type = "network";
- model = "eTSEC";
- compatible = "gianfar";
-- reg = <24000 1000>;
-+ reg = <0x24000 0x1000>;
- local-mac-address = [ 00 00 00 00 00 00 ];
-- interrupts = <1d 2 1e 2 22 2>;
-+ interrupts = <29 2 30 2 34 2>;
- interrupt-parent = <&mpic>;
- phy-handle = <&phy0>;
- };
-@@ -147,9 +148,9 @@
- device_type = "network";
- model = "eTSEC";
- compatible = "gianfar";
-- reg = <25000 1000>;
-+ reg = <0x25000 0x1000>;
- local-mac-address = [ 00 00 00 00 00 00 ];
-- interrupts = <23 2 24 2 28 2>;
-+ interrupts = <35 2 36 2 40 2>;
- interrupt-parent = <&mpic>;
- phy-handle = <&phy1>;
- };
-@@ -160,9 +161,9 @@
- device_type = "network";
- model = "eTSEC";
- compatible = "gianfar";
-- reg = <26000 1000>;
-+ reg = <0x26000 0x1000>;
- local-mac-address = [ 00 00 00 00 00 00 ];
-- interrupts = <1f 2 20 2 21 2>;
-+ interrupts = <31 2 32 2 33 2>;
- interrupt-parent = <&mpic>;
- phy-handle = <&phy2>;
- };
-@@ -172,9 +173,9 @@
- device_type = "network";
- model = "eTSEC";
- compatible = "gianfar";
-- reg = <27000 1000>;
-+ reg = <0x27000 0x1000>;
- local-mac-address = [ 00 00 00 00 00 00 ];
-- interrupts = <25 2 26 2 27 2>;
-+ interrupts = <37 2 38 2 39 2>;
- interrupt-parent = <&mpic>;
- phy-handle = <&phy3>;
- };
-@@ -184,9 +185,9 @@
- cell-index = <0>;
- device_type = "serial";
- compatible = "ns16550";
-- reg = <4500 100>; // reg base, size
-+ reg = <0x4500 0x100>; // reg base, size
- clock-frequency = <0>; // should we fill in in uboot?
-- interrupts = <2a 2>;
-+ interrupts = <42 2>;
- interrupt-parent = <&mpic>;
- };
++config FORCE_MAX_ZONEORDER
++ int "Maximum zone order"
++ default "9" if PPC_64K_PAGES
++ default "13" if PPC64 && !PPC_64K_PAGES
++ default "11"
++ help
++ The kernel memory allocator divides physically contiguous memory
++ blocks into "zones", where each zone is a power of two number of
++ pages. This option selects the largest power of two that the kernel
++ keeps in the memory allocator. If you need to allocate very large
++ blocks of physically contiguous memory, then you may need to
++ increase this value.
++
++ This config option is actually maximum order plus one. For example,
++ a value of 11 means that the largest free memory block is 2^10 pages.
++
++ The page size is not necessarily 4KB. For example, on 64-bit
++ systems, 64KB pages can be enabled via CONFIG_PPC_64K_PAGES. Keep
++ this in mind when choosing a value for this option.
++
+ config PPC_SUBPAGE_PROT
+ bool "Support setting protections for 4k subpages"
+ depends on PPC_64K_PAGES
+@@ -490,6 +530,14 @@ config FSL_PCI
+ bool
+ select PPC_INDIRECT_PCI
-@@ -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>;
- };
++config 4xx_SOC
++ bool
++
++config FSL_LBC
++ bool
++ help
++ Freescale Localbus support
++
+ # Yes MCA RS/6000s exist but Linux-PPC does not currently support any
+ config MCA
+ bool
+@@ -560,6 +608,19 @@ source "drivers/pcmcia/Kconfig"
- global-utilities at e0000 { //global utilities reg
- compatible = "fsl,mpc8548-guts";
-- reg = <e0000 1000>;
-+ reg = <0xe0000 0x1000>;
- fsl,has-rstcr;
- };
+ source "drivers/pci/hotplug/Kconfig"
-@@ -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 @@
++config HAS_RAPIDIO
++ bool
++ default n
++
++config RAPIDIO
++ bool "RapidIO support"
++ depends on HAS_RAPIDIO
++ help
++ If you say Y here, the kernel will include drivers and
++ infrastructure code to support RapidIO interconnect devices.
++
++source "drivers/rapidio/Kconfig"
++
+ endmenu
- pci0: pci at e0008000 {
- cell-index = <0>;
-- interrupt-map-mask = <f800 0 0 7>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
- /* IDSEL 0x4 (PCIX Slot 2) */
-- 02000 0 0 1 &mpic 0 1
-- 02000 0 0 2 &mpic 1 1
-- 02000 0 0 3 &mpic 2 1
-- 02000 0 0 4 &mpic 3 1
-+ 0x2000 0x0 0x0 0x1 &mpic 0x0 0x1
-+ 0x2000 0x0 0x0 0x2 &mpic 0x1 0x1
-+ 0x2000 0x0 0x0 0x3 &mpic 0x2 0x1
-+ 0x2000 0x0 0x0 0x4 &mpic 0x3 0x1
+ menu "Advanced setup"
+@@ -578,20 +639,6 @@ config ADVANCED_OPTIONS
+ comment "Default settings for advanced configuration options are used"
+ depends on !ADVANCED_OPTIONS
- /* 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
+-config HIGHMEM_START_BOOL
+- bool "Set high memory pool address"
+- depends on ADVANCED_OPTIONS && HIGHMEM
+- help
+- This option allows you to set the base address of the kernel virtual
+- area used to map high memory pages. This can be useful in
+- optimizing the layout of kernel virtual memory.
+-
+- Say N here unless you know what you are doing.
+-
+-config HIGHMEM_START
+- hex "Virtual start address of high memory pool" if HIGHMEM_START_BOOL
+- default "0xfe000000"
+-
+ config LOWMEM_SIZE_BOOL
+ bool "Set maximum low memory"
+ depends on ADVANCED_OPTIONS
+@@ -608,21 +655,76 @@ config LOWMEM_SIZE
+ hex "Maximum low memory size (in bytes)" if LOWMEM_SIZE_BOOL
+ default "0x30000000"
- /* 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
++config RELOCATABLE
++ bool "Build a relocatable kernel (EXPERIMENTAL)"
++ depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE
++ help
++ This builds a kernel image that is capable of running at the
++ location the kernel is loaded at (some alignment restrictions may
++ exist).
++
++ One use is for the kexec on panic case where the recovery kernel
++ must live at a different physical address than the primary
++ kernel.
++
++ Note: If CONFIG_RELOCATABLE=y, then the kernel runs from the address
++ it has been loaded at and the compile time physical addresses
++ CONFIG_PHYSICAL_START is ignored. However CONFIG_PHYSICAL_START
++ setting can still be useful to bootwrappers that need to know the
++ load location of the kernel (eg. u-boot/mkimage).
++
++config PAGE_OFFSET_BOOL
++ bool "Set custom page offset address"
++ depends on ADVANCED_OPTIONS
++ help
++ This option allows you to set the kernel virtual address at which
++ the kernel will map low memory. This can be useful in optimizing
++ the virtual memory layout of the system.
++
++ Say N here unless you know what you are doing.
++
++config PAGE_OFFSET
++ hex "Virtual address of memory base" if PAGE_OFFSET_BOOL
++ default "0xc0000000"
++
+ config KERNEL_START_BOOL
+ bool "Set custom kernel base address"
+ depends on ADVANCED_OPTIONS
+ help
+ This option allows you to set the kernel virtual address at which
+- the kernel will map low memory (the kernel image will be linked at
+- this address). This can be useful in optimizing the virtual memory
+- layout of the system.
++ the kernel will be loaded. Normally this should match PAGE_OFFSET
++ however there are times (like kdump) that one might not want them
++ to be the same.
- /* 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
+ Say N here unless you know what you are doing.
- /* 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
+ config KERNEL_START
+ hex "Virtual address of kernel base" if KERNEL_START_BOOL
++ default PAGE_OFFSET if PAGE_OFFSET_BOOL
++ default "0xc2000000" if CRASH_DUMP
+ default "0xc0000000"
- /* 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
++config PHYSICAL_START_BOOL
++ bool "Set physical address where the kernel is loaded"
++ depends on ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE
++ help
++ This gives the physical address where the kernel is loaded.
++
++ Say N here unless you know what you are doing.
++
++config PHYSICAL_START
++ hex "Physical address where the kernel is loaded" if PHYSICAL_START_BOOL
++ default "0x02000000" if PPC_STD_MMU && CRASH_DUMP
++ default "0x00000000"
++
++config PHYSICAL_ALIGN
++ hex
++ default "0x10000000" if FSL_BOOKE
++ help
++ This value puts the alignment restrictions on physical address
++ where kernel is loaded and run from. Kernel is compiled for an
++ address which meets above alignment restriction.
++
+ config TASK_SIZE_BOOL
+ bool "Set custom user task size"
+ depends on ADVANCED_OPTIONS
+@@ -663,31 +765,23 @@ config CONSISTENT_SIZE
+ hex "Size of consistent memory pool" if CONSISTENT_SIZE_BOOL
+ default "0x00200000" if NOT_COHERENT_CACHE
- /* 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
+-config BOOT_LOAD_BOOL
+- bool "Set the boot link/load address"
+- depends on ADVANCED_OPTIONS && !PPC_MULTIPLATFORM
+- help
+- This option allows you to set the initial load address of the zImage
+- or zImage.initrd file. This can be useful if you are on a board
+- which has a small amount of memory.
+-
+- Say N here unless you know what you are doing.
+-
+-config BOOT_LOAD
+- hex "Link/load address for booting" if BOOT_LOAD_BOOL
+- default "0x00400000" if 40x || 8xx || 8260
+- default "0x01000000" if 44x
+- default "0x00800000"
+-
+ config PIN_TLB
+ bool "Pinned Kernel TLBs (860 ONLY)"
+ depends on ADVANCED_OPTIONS && 8xx
+ endmenu
- /* 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
+ if PPC64
++config PAGE_OFFSET
++ hex
++ default "0xc000000000000000"
+ config KERNEL_START
+ hex
++ default "0xc000000002000000" if CRASH_DUMP
+ default "0xc000000000000000"
++config PHYSICAL_START
++ hex
++ default "0x02000000" if CRASH_DUMP
++ default "0x00000000"
+ endif
- /* 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
+ source "net/Kconfig"
+@@ -722,3 +816,4 @@ config PPC_CLOCK
+ config PPC_LIB_RHEAP
+ bool
- /* 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>;
++source "arch/powerpc/kvm/Kconfig"
+diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
+index db7cc34..a7d24e6 100644
+--- a/arch/powerpc/Kconfig.debug
++++ b/arch/powerpc/Kconfig.debug
+@@ -118,7 +118,6 @@ config XMON_DISASSEMBLY
- interrupt-parent = <&mpic>;
-- interrupts = <18 2>;
-+ interrupts = <24 2>;
- bus-range = <0 0>;
-- ranges = <02000000 0 80000000 80000000 0 10000000
-- 01000000 0 00000000 e2000000 0 00800000>;
-- clock-frequency = <3f940aa>;
-+ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x10000000
-+ 0x1000000 0x0 0x0 0xe2000000 0x0 0x800000>;
-+ clock-frequency = <66666666>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- reg = <e0008000 1000>;
-+ reg = <0xe0008000 0x1000>;
- compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci";
- device_type = "pci";
+ config IRQSTACKS
+ bool "Use separate kernel stacks when processing interrupts"
+- depends on PPC64
+ help
+ If you say Y here the kernel will use separate kernel stacks
+ for handling hard and soft interrupts. This can help avoid
+@@ -151,6 +150,9 @@ config BOOTX_TEXT
+
+ config PPC_EARLY_DEBUG
+ bool "Early debugging (dangerous)"
++ # PPC_EARLY_DEBUG on 440 leaves AS=1 mappings above the TLB high water
++ # mark, which doesn't work with current 440 KVM.
++ depends on !KVM
+ help
+ Say Y to enable some early debugging facilities that may be available
+ for your processor/board combination. Those facilities are hacks
+@@ -269,7 +271,7 @@ config PPC_EARLY_DEBUG_CPM_ADDR
+ hex "CPM UART early debug transmit descriptor address"
+ depends on PPC_EARLY_DEBUG_CPM
+ default "0xfa202008" if PPC_EP88XC
+- default "0xf0000008" if CPM2
++ default "0xf0001ff8" if CPM2
+ default "0xff002008" if CPM1
+ help
+ This specifies the address of the transmit descriptor
+diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
+index ab5cfe8..9dcdc03 100644
+--- a/arch/powerpc/Makefile
++++ b/arch/powerpc/Makefile
+@@ -71,13 +71,11 @@ endif
- pci_bridge at 1c {
-- interrupt-map-mask = <f800 0 0 7>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
+ LDFLAGS_vmlinux := -Bstatic
- /* 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
+-CPPFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH)
+-AFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH)
+ CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=none -mcall-aixdesc
+-CFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH) -ffixed-r2 -mmultiple
+-KBUILD_CPPFLAGS += $(CPPFLAGS-y)
+-KBUILD_AFLAGS += $(AFLAGS-y)
+-KBUILD_CFLAGS += -msoft-float -pipe $(CFLAGS-y)
++CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple
++KBUILD_CPPFLAGS += -Iarch/$(ARCH)
++KBUILD_AFLAGS += -Iarch/$(ARCH)
++KBUILD_CFLAGS += -msoft-float -pipe -Iarch/$(ARCH) $(CFLAGS-y)
+ CPP = $(CC) -E $(KBUILD_CFLAGS)
- /* 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
+ CHECKFLAGS += -m$(CONFIG_WORD_SIZE) -D__powerpc__ -D__powerpc$(CONFIG_WORD_SIZE)__
+@@ -147,6 +145,7 @@ core-y += arch/powerpc/kernel/ \
+ arch/powerpc/platforms/
+ core-$(CONFIG_MATH_EMULATION) += arch/powerpc/math-emu/
+ core-$(CONFIG_XMON) += arch/powerpc/xmon/
++core-$(CONFIG_KVM) += arch/powerpc/kvm/
- /* IDSEL 0x05 (8139) */
-- 2800 0 0 1 &mpic 1 1
-+ 0x2800 0x0 0x0 0x1 &mpic 0x1 0x1
+ drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
- /* 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
+@@ -164,7 +163,7 @@ boot := arch/$(ARCH)/boot
+ $(BOOT_TARGETS): vmlinux
+ $(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
- /* 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>;
+-bootwrapper_install:
++bootwrapper_install %.dtb:
+ $(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
-- reg = <e000 0 0 0 0>;
-+ reg = <0xe000 0x0 0x0 0x0 0x0>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- ranges = <02000000 0 80000000
-- 02000000 0 80000000
-- 0 20000000
-- 01000000 0 00000000
-- 01000000 0 00000000
-- 0 00080000>;
-- clock-frequency = <1fca055>;
-+ ranges = <0x2000000 0x0 0x80000000
-+ 0x2000000 0x0 0x80000000
-+ 0x0 0x20000000
-+ 0x1000000 0x0 0x0
-+ 0x1000000 0x0 0x0
-+ 0x0 0x80000>;
-+ clock-frequency = <33333333>;
+ define archhelp
+diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore
+index 5ef2bdf..2347294 100644
+--- a/arch/powerpc/boot/.gitignore
++++ b/arch/powerpc/boot/.gitignore
+@@ -27,6 +27,7 @@ zImage.chrp
+ zImage.coff
+ zImage.coff.lds
+ zImage.ep*
++zImage.iseries
+ zImage.*lds
+ zImage.miboot
+ zImage.pmac
+diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
+index 1aded8f..7822d25 100644
+--- a/arch/powerpc/boot/Makefile
++++ b/arch/powerpc/boot/Makefile
+@@ -40,6 +40,7 @@ $(obj)/ebony.o: BOOTCFLAGS += -mcpu=405
+ $(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=405
+ $(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405
+ $(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405
++$(obj)/virtex405-head.o: BOOTAFLAGS += -mcpu=405
- isa at 4 {
- device_type = "isa";
- #interrupt-cells = <2>;
- #size-cells = <1>;
- #address-cells = <2>;
-- reg = <2000 0 0 0 0>;
-- ranges = <1 0 01000000 0 0 00001000>;
-+ reg = <0x2000 0x0 0x0 0x0 0x0>;
-+ ranges = <0x1 0x0 0x1000000 0x0 0x0 0x1000>;
- interrupt-parent = <&i8259>;
- i8259: interrupt-controller at 20 {
- interrupt-controller;
- device_type = "interrupt-controller";
-- reg = <1 20 2
-- 1 a0 2
-- 1 4d0 2>;
-+ reg = <0x1 0x20 0x2
-+ 0x1 0xa0 0x2
-+ 0x1 0x4d0 0x2>;
- #address-cells = <0>;
- #interrupt-cells = <2>;
- compatible = "chrp,iic";
-@@ -362,7 +363,7 @@
+ zlib := inffast.c inflate.c inftrees.c
+@@ -64,7 +65,8 @@ src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c
+ cuboot-bamboo.c cuboot-mpc7448hpc2.c cuboot-taishan.c \
+ fixed-head.S ep88xc.c ep405.c \
+ cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \
+- cuboot-warp.c cuboot-85xx-cpm2.c
++ cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \
++ virtex405-head.S
+ src-boot := $(src-wlib) $(src-plat) empty.c
- rtc at 70 {
- compatible = "pnpPNP,b00";
-- reg = <1 70 2>;
-+ reg = <0x1 0x70 0x2>;
- };
+ src-boot := $(addprefix $(obj)/, $(src-boot))
+@@ -192,7 +194,7 @@ image-$(CONFIG_PPC_CHRP) += zImage.chrp
+ image-$(CONFIG_PPC_EFIKA) += zImage.chrp
+ image-$(CONFIG_PPC_PMAC) += zImage.pmac
+ image-$(CONFIG_PPC_HOLLY) += zImage.holly
+-image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800
++image-$(CONFIG_PPC_PRPMC2800) += dtbImage.prpmc2800
+ image-$(CONFIG_PPC_ISERIES) += zImage.iseries
+ image-$(CONFIG_DEFAULT_UIMAGE) += uImage
+
+@@ -216,6 +218,7 @@ image-$(CONFIG_RAINIER) += cuImage.rainier
+ image-$(CONFIG_TAISHAN) += cuImage.taishan
+ image-$(CONFIG_KATMAI) += cuImage.katmai
+ image-$(CONFIG_WARP) += cuImage.warp
++image-$(CONFIG_YOSEMITE) += cuImage.yosemite
+
+ # Board ports in arch/powerpc/platform/8xx/Kconfig
+ image-$(CONFIG_PPC_MPC86XADS) += cuImage.mpc866ads
+@@ -255,6 +258,7 @@ image-$(CONFIG_TQM8555) += cuImage.tqm8555
+ image-$(CONFIG_TQM8560) += cuImage.tqm8560
+ image-$(CONFIG_SBC8548) += cuImage.sbc8548
+ image-$(CONFIG_SBC8560) += cuImage.sbc8560
++image-$(CONFIG_KSI8560) += cuImage.ksi8560
+
+ # Board ports in arch/powerpc/platform/embedded6xx/Kconfig
+ image-$(CONFIG_STORCENTER) += cuImage.storcenter
+@@ -285,11 +289,11 @@ $(obj)/zImage.%: vmlinux $(wrapperbits)
+ $(call if_changed,wrap,$*)
+
+ # dtbImage% - a dtbImage is a zImage with an embedded device tree blob
+-$(obj)/dtbImage.initrd.%: vmlinux $(wrapperbits) $(dtstree)/%.dts
+- $(call if_changed,wrap,$*,$(dtstree)/$*.dts,,$(obj)/ramdisk.image.gz)
++$(obj)/dtbImage.initrd.%: vmlinux $(wrapperbits) $(obj)/%.dtb
++ $(call if_changed,wrap,$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
+
+-$(obj)/dtbImage.%: vmlinux $(wrapperbits) $(dtstree)/%.dts
+- $(call if_changed,wrap,$*,$(dtstree)/$*.dts)
++$(obj)/dtbImage.%: vmlinux $(wrapperbits) $(obj)/%.dtb
++ $(call if_changed,wrap,$*,,$(obj)/$*.dtb)
+
+ # This cannot be in the root of $(src) as the zImage rule always adds a $(obj)
+ # prefix
+@@ -302,14 +306,24 @@ $(obj)/zImage.iseries: vmlinux
+ $(obj)/uImage: vmlinux $(wrapperbits)
+ $(call if_changed,wrap,uboot)
+
+-$(obj)/cuImage.%: vmlinux $(dtstree)/%.dts $(wrapperbits)
+- $(call if_changed,wrap,cuboot-$*,$(dtstree)/$*.dts)
++$(obj)/cuImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
++ $(call if_changed,wrap,cuboot-$*,,$(obj)/$*.dtb)
+
+-$(obj)/treeImage.initrd.%: vmlinux $(dtstree)/%.dts $(wrapperbits)
+- $(call if_changed,wrap,treeboot-$*,$(dtstree)/$*.dts,,$(obj)/ramdisk.image.gz)
++$(obj)/simpleImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
++ $(call if_changed,wrap,simpleboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
+
+-$(obj)/treeImage.%: vmlinux $(dtstree)/%.dts $(wrapperbits)
+- $(call if_changed,wrap,treeboot-$*,$(dtstree)/$*.dts)
++$(obj)/simpleImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
++ $(call if_changed,wrap,simpleboot-$*,,$(obj)/$*.dtb)
++
++$(obj)/treeImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
++ $(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
++
++$(obj)/treeImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
++ $(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb)
++
++# Rule to build device tree blobs
++$(obj)/%.dtb: $(dtstree)/%.dts $(obj)/dtc
++ $(obj)/dtc -O dtb -o $(obj)/$*.dtb -b 0 $(DTS_FLAGS) $(dtstree)/$*.dts
+
+ # If there isn't a platform selected then just strip the vmlinux.
+ ifeq (,$(image-y))
+@@ -326,7 +340,7 @@ install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
+
+ # anything not in $(targets)
+ clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \
+- otheros.bld
++ otheros.bld *.dtb
+
+ # clean up files cached by wrapper
+ clean-kernel := vmlinux.strip vmlinux.bin
+diff --git a/arch/powerpc/boot/bamboo.c b/arch/powerpc/boot/bamboo.c
+index 54b33f1..b82cacb 100644
+--- a/arch/powerpc/boot/bamboo.c
++++ b/arch/powerpc/boot/bamboo.c
+@@ -33,7 +33,8 @@ static void bamboo_fixups(void)
+ ibm440ep_fixup_clocks(sysclk, 11059200, 25000000);
+ ibm4xx_sdram_fixup_memsize();
+ ibm4xx_quiesce_eth((u32 *)0xef600e00, (u32 *)0xef600f00);
+- dt_fixup_mac_addresses(bamboo_mac0, bamboo_mac1);
++ dt_fixup_mac_address_by_alias("ethernet0", bamboo_mac0);
++ dt_fixup_mac_address_by_alias("ethernet1", bamboo_mac1);
+ }
+
+ void bamboo_init(void *mac0, void *mac1)
+diff --git a/arch/powerpc/boot/cpm-serial.c b/arch/powerpc/boot/cpm-serial.c
+index 28296fa..19dc15a 100644
+--- a/arch/powerpc/boot/cpm-serial.c
++++ b/arch/powerpc/boot/cpm-serial.c
+@@ -11,6 +11,7 @@
+ #include "types.h"
+ #include "io.h"
+ #include "ops.h"
++#include "page.h"
+
+ struct cpm_scc {
+ u32 gsmrl;
+@@ -42,6 +43,22 @@ struct cpm_param {
+ u16 tbase;
+ u8 rfcr;
+ u8 tfcr;
++ u16 mrblr;
++ u32 rstate;
++ u8 res1[4];
++ u16 rbptr;
++ u8 res2[6];
++ u32 tstate;
++ u8 res3[4];
++ u16 tbptr;
++ u8 res4[6];
++ u16 maxidl;
++ u16 idlc;
++ u16 brkln;
++ u16 brkec;
++ u16 brkcr;
++ u16 rmask;
++ u8 res5[4];
+ };
+
+ struct cpm_bd {
+@@ -54,10 +71,10 @@ static void *cpcr;
+ static struct cpm_param *param;
+ static struct cpm_smc *smc;
+ static struct cpm_scc *scc;
+-struct cpm_bd *tbdf, *rbdf;
++static struct cpm_bd *tbdf, *rbdf;
+ static u32 cpm_cmd;
+-static u8 *muram_start;
+-static u32 muram_offset;
++static void *cbd_addr;
++static u32 cbd_offset;
+
+ static void (*do_cmd)(int op);
+ static void (*enable_port)(void);
+@@ -119,20 +136,25 @@ static int cpm_serial_open(void)
+
+ out_8(¶m->rfcr, 0x10);
+ out_8(¶m->tfcr, 0x10);
+-
+- rbdf = (struct cpm_bd *)muram_start;
+- rbdf->addr = (u8 *)(rbdf + 2);
++ out_be16(¶m->mrblr, 1);
++ out_be16(¶m->maxidl, 0);
++ out_be16(¶m->brkec, 0);
++ out_be16(¶m->brkln, 0);
++ out_be16(¶m->brkcr, 0);
++
++ rbdf = cbd_addr;
++ rbdf->addr = (u8 *)rbdf - 1;
+ rbdf->sc = 0xa000;
+ rbdf->len = 1;
+
+ tbdf = rbdf + 1;
+- tbdf->addr = (u8 *)(rbdf + 2) + 1;
++ tbdf->addr = (u8 *)rbdf - 2;
+ tbdf->sc = 0x2000;
+ tbdf->len = 1;
+
+ sync();
+- out_be16(¶m->rbase, muram_offset);
+- out_be16(¶m->tbase, muram_offset + sizeof(struct cpm_bd));
++ out_be16(¶m->rbase, cbd_offset);
++ out_be16(¶m->tbase, cbd_offset + sizeof(struct cpm_bd));
+
+ do_cmd(CPM_CMD_INIT_RX_TX);
+
+@@ -175,10 +197,12 @@ static unsigned char cpm_serial_getc(void)
+
+ int cpm_console_init(void *devp, struct serial_console_data *scdp)
+ {
+- void *reg_virt[2];
+- int is_smc = 0, is_cpm2 = 0, n;
+- unsigned long reg_phys;
++ void *vreg[2];
++ u32 reg[2];
++ int is_smc = 0, is_cpm2 = 0;
+ void *parent, *muram;
++ void *muram_addr;
++ unsigned long muram_offset, muram_size;
+
+ if (dt_is_compatible(devp, "fsl,cpm1-smc-uart")) {
+ is_smc = 1;
+@@ -202,63 +226,64 @@ int cpm_console_init(void *devp, struct serial_console_data *scdp)
+ else
+ do_cmd = cpm1_cmd;
+
+- n = getprop(devp, "fsl,cpm-command", &cpm_cmd, 4);
+- if (n < 4)
++ if (getprop(devp, "fsl,cpm-command", &cpm_cmd, 4) < 4)
+ return -1;
+
+- n = getprop(devp, "virtual-reg", reg_virt, sizeof(reg_virt));
+- if (n < (int)sizeof(reg_virt)) {
+- for (n = 0; n < 2; n++) {
+- if (!dt_xlate_reg(devp, n, ®_phys, NULL))
+- return -1;
+-
+- reg_virt[n] = (void *)reg_phys;
+- }
+- }
++ if (dt_get_virtual_reg(devp, vreg, 2) < 2)
++ return -1;
+
+ if (is_smc)
+- smc = reg_virt[0];
++ smc = vreg[0];
+ else
+- scc = reg_virt[0];
++ scc = vreg[0];
+
+- param = reg_virt[1];
++ param = vreg[1];
+
+ parent = get_parent(devp);
+ if (!parent)
+ return -1;
+
+- n = getprop(parent, "virtual-reg", reg_virt, sizeof(reg_virt));
+- if (n < (int)sizeof(reg_virt)) {
+- if (!dt_xlate_reg(parent, 0, ®_phys, NULL))
+- return -1;
+-
+- reg_virt[0] = (void *)reg_phys;
+- }
+-
+- cpcr = reg_virt[0];
++ if (dt_get_virtual_reg(parent, &cpcr, 1) < 1)
++ return -1;
+
+ muram = finddevice("/soc/cpm/muram/data");
+ if (!muram)
+ return -1;
+
+ /* For bootwrapper-compatible device trees, we assume that the first
+- * entry has at least 18 bytes, and that #address-cells/#data-cells
++ * entry has at least 128 bytes, and that #address-cells/#data-cells
+ * is one for both parent and child.
+ */
+
+- n = getprop(muram, "virtual-reg", reg_virt, sizeof(reg_virt));
+- if (n < (int)sizeof(reg_virt)) {
+- if (!dt_xlate_reg(muram, 0, ®_phys, NULL))
+- return -1;
++ if (dt_get_virtual_reg(muram, &muram_addr, 1) < 1)
++ return -1;
+
+- reg_virt[0] = (void *)reg_phys;
+- }
++ if (getprop(muram, "reg", reg, 8) < 8)
++ return -1;
+
+- muram_start = reg_virt[0];
++ muram_offset = reg[0];
++ muram_size = reg[1];
+
+- n = getprop(muram, "reg", &muram_offset, 4);
+- if (n < 4)
+- return -1;
++ /* Store the buffer descriptors at the end of the first muram chunk.
++ * For SMC ports on CPM2-based platforms, relocate the parameter RAM
++ * just before the buffer descriptors.
++ */
++
++ cbd_offset = muram_offset + muram_size - 2 * sizeof(struct cpm_bd);
++
++ if (is_cpm2 && is_smc) {
++ u16 *smc_base = (u16 *)param;
++ u16 pram_offset;
++
++ pram_offset = cbd_offset - 64;
++ pram_offset = _ALIGN_DOWN(pram_offset, 64);
++
++ disable_port();
++ out_be16(smc_base, pram_offset);
++ param = muram_addr - muram_offset + pram_offset;
++ }
++
++ cbd_addr = muram_addr - muram_offset + cbd_offset;
+
+ scdp->open = cpm_serial_open;
+ scdp->putc = cpm_serial_putc;
+diff --git a/arch/powerpc/boot/cuboot-pq2.c b/arch/powerpc/boot/cuboot-pq2.c
+index f56ac6c..9c7d134 100644
+--- a/arch/powerpc/boot/cuboot-pq2.c
++++ b/arch/powerpc/boot/cuboot-pq2.c
+@@ -128,7 +128,7 @@ static void fixup_pci(void)
+ u8 *soc_regs;
+ int i, len;
+ void *node, *parent_node;
+- u32 naddr, nsize, mem_log2;
++ u32 naddr, nsize, mem_pow2, mem_mask;
+
+ node = finddevice("/pci");
+ if (!node || !dt_is_compatible(node, "fsl,pq2-pci"))
+@@ -141,7 +141,7 @@ static void fixup_pci(void)
+
+ soc_regs = (u8 *)fsl_get_immr();
+ if (!soc_regs)
+- goto err;
++ goto unhandled;
+
+ dt_get_reg_format(node, &naddr, &nsize);
+ if (naddr != 3 || nsize != 2)
+@@ -153,7 +153,7 @@ static void fixup_pci(void)
+
+ dt_get_reg_format(parent_node, &naddr, &nsize);
+ if (naddr != 1 || nsize != 1)
+- goto err;
++ goto unhandled;
+
+ len = getprop(node, "ranges", pci_ranges_buf,
+ sizeof(pci_ranges_buf));
+@@ -170,14 +170,20 @@ static void fixup_pci(void)
+ }
+
+ if (!mem || !mmio || !io)
+- goto err;
++ goto unhandled;
++ if (mem->size[1] != mmio->size[1])
++ goto unhandled;
++ if (mem->size[1] & (mem->size[1] - 1))
++ goto unhandled;
++ if (io->size[1] & (io->size[1] - 1))
++ goto unhandled;
+
+ if (mem->phys_addr + mem->size[1] == mmio->phys_addr)
+ mem_base = mem;
+ else if (mmio->phys_addr + mmio->size[1] == mem->phys_addr)
+ mem_base = mmio;
+ else
+- goto err;
++ goto unhandled;
+
+ out_be32(&pci_regs[1][0], mem_base->phys_addr | 1);
+ out_be32(&pci_regs[2][0], ~(mem->size[1] + mmio->size[1] - 1));
+@@ -201,8 +207,9 @@ static void fixup_pci(void)
+ out_le32(&pci_regs[0][58], 0);
+ out_le32(&pci_regs[0][60], 0);
+
+- mem_log2 = 1 << (__ilog2_u32(bd.bi_memsize - 1) + 1);
+- out_le32(&pci_regs[0][62], 0xa0000000 | ~((1 << (mem_log2 - 12)) - 1));
++ mem_pow2 = 1 << (__ilog2_u32(bd.bi_memsize - 1) + 1);
++ mem_mask = ~(mem_pow2 - 1) >> 12;
++ out_le32(&pci_regs[0][62], 0xa0000000 | mem_mask);
+
+ /* If PCI is disabled, drive RST high to enable. */
+ if (!(in_le32(&pci_regs[0][32]) & 1)) {
+@@ -228,7 +235,11 @@ static void fixup_pci(void)
+ return;
+
+ err:
+- printf("Bad PCI node\r\n");
++ printf("Bad PCI node -- using existing firmware setup.\r\n");
++ return;
++
++unhandled:
++ printf("Unsupported PCI node -- using existing firmware setup.\r\n");
+ }
+
+ static void pq2_platform_fixups(void)
+diff --git a/arch/powerpc/boot/cuboot-rainier.c b/arch/powerpc/boot/cuboot-rainier.c
+index cf452b6..0a3fdde 100644
+--- a/arch/powerpc/boot/cuboot-rainier.c
++++ b/arch/powerpc/boot/cuboot-rainier.c
+@@ -42,7 +42,8 @@ static void rainier_fixups(void)
+ ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
+ ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
+ ibm4xx_denali_fixup_memsize();
+- dt_fixup_mac_addresses(&bd.bi_enetaddr, &bd.bi_enet1addr);
++ dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
++ dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
+ }
+
+ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+diff --git a/arch/powerpc/boot/cuboot-sequoia.c b/arch/powerpc/boot/cuboot-sequoia.c
+index f555575..caf8f2e 100644
+--- a/arch/powerpc/boot/cuboot-sequoia.c
++++ b/arch/powerpc/boot/cuboot-sequoia.c
+@@ -42,7 +42,8 @@ static void sequoia_fixups(void)
+ ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
+ ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
+ ibm4xx_denali_fixup_memsize();
+- dt_fixup_mac_addresses(&bd.bi_enetaddr, &bd.bi_enet1addr);
++ dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
++ dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
+ }
+
+ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+diff --git a/arch/powerpc/boot/cuboot-taishan.c b/arch/powerpc/boot/cuboot-taishan.c
+index b55b804..9bc906a 100644
+--- a/arch/powerpc/boot/cuboot-taishan.c
++++ b/arch/powerpc/boot/cuboot-taishan.c
+@@ -40,7 +40,8 @@ static void taishan_fixups(void)
+
+ ibm4xx_sdram_fixup_memsize();
+
+- dt_fixup_mac_addresses(bd.bi_enetaddr, bd.bi_enet1addr);
++ dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
++ dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
+
+ ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
+ }
+diff --git a/arch/powerpc/boot/cuboot-warp.c b/arch/powerpc/boot/cuboot-warp.c
+index 3db93e8..eb108a8 100644
+--- a/arch/powerpc/boot/cuboot-warp.c
++++ b/arch/powerpc/boot/cuboot-warp.c
+@@ -24,7 +24,7 @@ static void warp_fixups(void)
+ ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
+ ibm4xx_sdram_fixup_memsize();
+ ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
+- dt_fixup_mac_addresses(&bd.bi_enetaddr);
++ dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
+ }
+
+
+diff --git a/arch/powerpc/boot/cuboot-yosemite.c b/arch/powerpc/boot/cuboot-yosemite.c
+new file mode 100644
+index 0000000..cc6e338
+--- /dev/null
++++ b/arch/powerpc/boot/cuboot-yosemite.c
+@@ -0,0 +1,44 @@
++/*
++ * Old U-boot compatibility for Yosemite
++ *
++ * Author: Josh Boyer <jwboyer at linux.vnet.ibm.com>
++ *
++ * Copyright 2008 IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++
++#include "ops.h"
++#include "stdio.h"
++#include "4xx.h"
++#include "44x.h"
++#include "cuboot.h"
++
++#define TARGET_4xx
++#define TARGET_44x
++#include "ppcboot.h"
++
++static bd_t bd;
++
++static void yosemite_fixups(void)
++{
++ unsigned long sysclk = 66666666;
++
++ ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
++ ibm4xx_sdram_fixup_memsize();
++ ibm4xx_quiesce_eth((u32 *)0xef600e00, (u32 *)0xef600f00);
++ dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
++ dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
++}
++
++void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
++ unsigned long r6, unsigned long r7)
++{
++ CUBOOT_INIT();
++ platform_ops.fixups = yosemite_fixups;
++ platform_ops.exit = ibm44x_dbcr_reset;
++ fdt_init(_dtb_start);
++ serial_console_init();
++}
+diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c
+index 60f561e..5d12336 100644
+--- a/arch/powerpc/boot/devtree.c
++++ b/arch/powerpc/boot/devtree.c
+@@ -350,3 +350,23 @@ int dt_is_compatible(void *node, const char *compat)
+
+ return 0;
+ }
++
++int dt_get_virtual_reg(void *node, void **addr, int nres)
++{
++ unsigned long xaddr;
++ int n;
++
++ n = getprop(node, "virtual-reg", addr, nres * 4);
++ if (n > 0)
++ return n / 4;
++
++ for (n = 0; n < nres; n++) {
++ if (!dt_xlate_reg(node, n, &xaddr, NULL))
++ break;
++
++ addr[n] = (void *)xaddr;
++ }
++
++ return n;
++}
++
+diff --git a/arch/powerpc/boot/dts/bamboo.dts b/arch/powerpc/boot/dts/bamboo.dts
+index 7dc37c9..ba2521b 100644
+--- a/arch/powerpc/boot/dts/bamboo.dts
++++ b/arch/powerpc/boot/dts/bamboo.dts
+@@ -204,7 +204,6 @@
};
- };
-@@ -370,64 +371,64 @@
- pci1: pci at e0009000 {
- cell-index = <1>;
-- interrupt-map-mask = <f800 0 0 7>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
+ EMAC0: ethernet at ef600e00 {
+- linux,network-index = <0>;
+ device_type = "network";
+ compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
+ interrupt-parent = <&UIC1>;
+@@ -225,7 +224,6 @@
+ };
- /* 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>;
+ EMAC1: ethernet at ef600f00 {
+- linux,network-index = <1>;
+ device_type = "network";
+ compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
+ interrupt-parent = <&UIC1>;
+diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts
+new file mode 100644
+index 0000000..3963412
+--- /dev/null
++++ b/arch/powerpc/boot/dts/canyonlands.dts
+@@ -0,0 +1,439 @@
++/*
++ * Device Tree Source for AMCC Canyonlands (460EX)
++ *
++ * Copyright 2008 DENX Software Engineering, Stefan Roese <sr at denx.de>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without
++ * any warranty of any kind, whether express or implied.
++ */
++
++/ {
++ #address-cells = <2>;
++ #size-cells = <1>;
++ model = "amcc,canyonlands";
++ compatible = "amcc,canyonlands";
++ dcr-parent = <&/cpus/cpu at 0>;
++
++ aliases {
++ ethernet0 = &EMAC0;
++ ethernet1 = &EMAC1;
++ serial0 = &UART0;
++ serial1 = &UART1;
++ };
++
++ cpus {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ cpu at 0 {
++ device_type = "cpu";
++ model = "PowerPC,460EX";
++ reg = <0>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ timebase-frequency = <0>; /* Filled in by U-Boot */
++ i-cache-line-size = <20>;
++ d-cache-line-size = <20>;
++ i-cache-size = <8000>;
++ d-cache-size = <8000>;
++ dcr-controller;
++ dcr-access-method = "native";
++ };
++ };
++
++ memory {
++ device_type = "memory";
++ reg = <0 0 0>; /* Filled in by U-Boot */
++ };
++
++ UIC0: interrupt-controller0 {
++ compatible = "ibm,uic-460ex","ibm,uic";
++ interrupt-controller;
++ cell-index = <0>;
++ dcr-reg = <0c0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ };
++
++ UIC1: interrupt-controller1 {
++ compatible = "ibm,uic-460ex","ibm,uic";
++ interrupt-controller;
++ cell-index = <1>;
++ dcr-reg = <0d0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ interrupts = <1e 4 1f 4>; /* cascade */
++ interrupt-parent = <&UIC0>;
++ };
++
++ UIC2: interrupt-controller2 {
++ compatible = "ibm,uic-460ex","ibm,uic";
++ interrupt-controller;
++ cell-index = <2>;
++ dcr-reg = <0e0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ interrupts = <a 4 b 4>; /* cascade */
++ interrupt-parent = <&UIC0>;
++ };
++
++ UIC3: interrupt-controller3 {
++ compatible = "ibm,uic-460ex","ibm,uic";
++ interrupt-controller;
++ cell-index = <3>;
++ dcr-reg = <0f0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ interrupts = <10 4 11 4>; /* cascade */
++ interrupt-parent = <&UIC0>;
++ };
++
++ SDR0: sdr {
++ compatible = "ibm,sdr-460ex";
++ dcr-reg = <00e 002>;
++ };
++
++ CPR0: cpr {
++ compatible = "ibm,cpr-460ex";
++ dcr-reg = <00c 002>;
++ };
++
++ plb {
++ compatible = "ibm,plb-460ex", "ibm,plb4";
++ #address-cells = <2>;
++ #size-cells = <1>;
++ ranges;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++
++ SDRAM0: sdram {
++ compatible = "ibm,sdram-460ex", "ibm,sdram-405gp";
++ dcr-reg = <010 2>;
++ };
++
++ MAL0: mcmal {
++ compatible = "ibm,mcmal-460ex", "ibm,mcmal2";
++ dcr-reg = <180 62>;
++ num-tx-chans = <2>;
++ num-rx-chans = <10>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ interrupt-parent = <&UIC2>;
++ interrupts = < /*TXEOB*/ 6 4
++ /*RXEOB*/ 7 4
++ /*SERR*/ 3 4
++ /*TXDE*/ 4 4
++ /*RXDE*/ 5 4>;
++ };
++
++ POB0: opb {
++ compatible = "ibm,opb-460ex", "ibm,opb";
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges = <b0000000 4 b0000000 50000000>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++
++ EBC0: ebc {
++ compatible = "ibm,ebc-460ex", "ibm,ebc";
++ dcr-reg = <012 2>;
++ #address-cells = <2>;
++ #size-cells = <1>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ /* ranges property is supplied by U-Boot */
++ interrupts = <6 4>;
++ interrupt-parent = <&UIC1>;
++
++ nor_flash at 0,0 {
++ compatible = "amd,s29gl512n", "cfi-flash";
++ bank-width = <2>;
++ reg = <0 000000 4000000>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++ partition at 0 {
++ label = "kernel";
++ reg = <0 1e0000>;
++ };
++ partition at 1e0000 {
++ label = "dtb";
++ reg = <1e0000 20000>;
++ };
++ partition at 200000 {
++ label = "ramdisk";
++ reg = <200000 1400000>;
++ };
++ partition at 1600000 {
++ label = "jffs2";
++ reg = <1600000 400000>;
++ };
++ partition at 1a00000 {
++ label = "user";
++ reg = <1a00000 2560000>;
++ };
++ partition at 3f60000 {
++ label = "env";
++ reg = <3f60000 40000>;
++ };
++ partition at 3fa0000 {
++ label = "u-boot";
++ reg = <3fa0000 60000>;
++ };
++ };
++ };
++
++ UART0: serial at ef600300 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600300 8>;
++ virtual-reg = <ef600300>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ current-speed = <0>; /* Filled in by U-Boot */
++ interrupt-parent = <&UIC1>;
++ interrupts = <1 4>;
++ };
++
++ UART1: serial at ef600400 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600400 8>;
++ virtual-reg = <ef600400>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ current-speed = <0>; /* Filled in by U-Boot */
++ interrupt-parent = <&UIC0>;
++ interrupts = <1 4>;
++ };
++
++ UART2: serial at ef600500 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600500 8>;
++ virtual-reg = <ef600500>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ current-speed = <0>; /* Filled in by U-Boot */
++ interrupt-parent = <&UIC1>;
++ interrupts = <1d 4>;
++ };
++
++ UART3: serial at ef600600 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600600 8>;
++ virtual-reg = <ef600600>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ current-speed = <0>; /* Filled in by U-Boot */
++ interrupt-parent = <&UIC1>;
++ interrupts = <1e 4>;
++ };
++
++ IIC0: i2c at ef600700 {
++ compatible = "ibm,iic-460ex", "ibm,iic";
++ reg = <ef600700 14>;
++ interrupt-parent = <&UIC0>;
++ interrupts = <2 4>;
++ };
++
++ IIC1: i2c at ef600800 {
++ compatible = "ibm,iic-460ex", "ibm,iic";
++ reg = <ef600800 14>;
++ interrupt-parent = <&UIC0>;
++ interrupts = <3 4>;
++ };
++
++ ZMII0: emac-zmii at ef600d00 {
++ compatible = "ibm,zmii-460ex", "ibm,zmii";
++ reg = <ef600d00 c>;
++ };
++
++ RGMII0: emac-rgmii at ef601500 {
++ compatible = "ibm,rgmii-460ex", "ibm,rgmii";
++ reg = <ef601500 8>;
++ has-mdio;
++ };
++
++ TAH0: emac-tah at ef601350 {
++ compatible = "ibm,tah-460ex", "ibm,tah";
++ reg = <ef601350 30>;
++ };
++
++ TAH1: emac-tah at ef601450 {
++ compatible = "ibm,tah-460ex", "ibm,tah";
++ reg = <ef601450 30>;
++ };
++
++ EMAC0: ethernet at ef600e00 {
++ device_type = "network";
++ compatible = "ibm,emac-460ex", "ibm,emac4";
++ interrupt-parent = <&EMAC0>;
++ interrupts = <0 1>;
++ #interrupt-cells = <1>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ interrupt-map = </*Status*/ 0 &UIC2 10 4
++ /*Wake*/ 1 &UIC2 14 4>;
++ reg = <ef600e00 70>;
++ local-mac-address = [000000000000]; /* Filled in by U-Boot */
++ mal-device = <&MAL0>;
++ mal-tx-channel = <0>;
++ mal-rx-channel = <0>;
++ cell-index = <0>;
++ max-frame-size = <2328>;
++ rx-fifo-size = <1000>;
++ tx-fifo-size = <800>;
++ phy-mode = "rgmii";
++ phy-map = <00000000>;
++ rgmii-device = <&RGMII0>;
++ rgmii-channel = <0>;
++ tah-device = <&TAH0>;
++ tah-channel = <0>;
++ has-inverted-stacr-oc;
++ has-new-stacr-staopc;
++ };
++
++ EMAC1: ethernet at ef600f00 {
++ device_type = "network";
++ compatible = "ibm,emac-460ex", "ibm,emac4";
++ interrupt-parent = <&EMAC1>;
++ interrupts = <0 1>;
++ #interrupt-cells = <1>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ interrupt-map = </*Status*/ 0 &UIC2 11 4
++ /*Wake*/ 1 &UIC2 15 4>;
++ reg = <ef600f00 70>;
++ local-mac-address = [000000000000]; /* Filled in by U-Boot */
++ mal-device = <&MAL0>;
++ mal-tx-channel = <1>;
++ mal-rx-channel = <8>;
++ cell-index = <1>;
++ max-frame-size = <2328>;
++ rx-fifo-size = <1000>;
++ tx-fifo-size = <800>;
++ phy-mode = "rgmii";
++ phy-map = <00000000>;
++ rgmii-device = <&RGMII0>;
++ rgmii-channel = <1>;
++ tah-device = <&TAH1>;
++ tah-channel = <1>;
++ has-inverted-stacr-oc;
++ has-new-stacr-staopc;
++ mdio-device = <&EMAC0>;
++ };
++ };
++
++ PCIX0: pci at c0ec00000 {
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ compatible = "ibm,plb-pcix-460ex", "ibm,plb-pcix";
++ primary;
++ large-inbound-windows;
++ enable-msi-hole;
++ reg = <c 0ec00000 8 /* Config space access */
++ 0 0 0 /* no IACK cycles */
++ c 0ed00000 4 /* Special cycles */
++ c 0ec80000 100 /* Internal registers */
++ c 0ec80100 fc>; /* Internal messaging registers */
++
++ /* Outbound ranges, one memory and one IO,
++ * later cannot be changed
++ */
++ ranges = <02000000 0 80000000 0000000d 80000000 0 80000000
++ 01000000 0 00000000 0000000c 08000000 0 00010000>;
++
++ /* Inbound 2GB range starting at 0 */
++ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++ /* This drives busses 0 to 0x3f */
++ bus-range = <0 3f>;
++
++ /* All PCI interrupts are routed to ext IRQ 2 -> UIC1-0 */
++ interrupt-map-mask = <0000 0 0 0>;
++ interrupt-map = < 0000 0 0 0 &UIC1 0 8 >;
++ };
++
++ PCIE0: pciex at d00000000 {
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
++ primary;
++ port = <0>; /* port number */
++ reg = <d 00000000 20000000 /* Config space access */
++ c 08010000 00001000>; /* Registers */
++ dcr-reg = <100 020>;
++ sdr-base = <300>;
++
++ /* Outbound ranges, one memory and one IO,
++ * later cannot be changed
++ */
++ ranges = <02000000 0 80000000 0000000e 00000000 0 80000000
++ 01000000 0 00000000 0000000f 80000000 0 00010000>;
++
++ /* Inbound 2GB range starting at 0 */
++ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++ /* This drives busses 40 to 0x7f */
++ bus-range = <40 7f>;
++
++ /* Legacy interrupts (note the weird polarity, the bridge seems
++ * to invert PCIe legacy interrupts).
++ * We are de-swizzling here because the numbers are actually for
++ * port of the root complex virtual P2P bridge. But I want
++ * to avoid putting a node for it in the tree, so the numbers
++ * below are basically de-swizzled numbers.
++ * The real slot is on idsel 0, so the swizzling is 1:1
++ */
++ interrupt-map-mask = <0000 0 0 7>;
++ interrupt-map = <
++ 0000 0 0 1 &UIC3 c 4 /* swizzled int A */
++ 0000 0 0 2 &UIC3 d 4 /* swizzled int B */
++ 0000 0 0 3 &UIC3 e 4 /* swizzled int C */
++ 0000 0 0 4 &UIC3 f 4 /* swizzled int D */>;
++ };
++
++ PCIE1: pciex at d20000000 {
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
++ primary;
++ port = <1>; /* port number */
++ reg = <d 20000000 20000000 /* Config space access */
++ c 08011000 00001000>; /* Registers */
++ dcr-reg = <120 020>;
++ sdr-base = <340>;
++
++ /* Outbound ranges, one memory and one IO,
++ * later cannot be changed
++ */
++ ranges = <02000000 0 80000000 0000000e 80000000 0 80000000
++ 01000000 0 00000000 0000000f 80010000 0 00010000>;
++
++ /* Inbound 2GB range starting at 0 */
++ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++ /* This drives busses 80 to 0xbf */
++ bus-range = <80 bf>;
++
++ /* Legacy interrupts (note the weird polarity, the bridge seems
++ * to invert PCIe legacy interrupts).
++ * We are de-swizzling here because the numbers are actually for
++ * port of the root complex virtual P2P bridge. But I want
++ * to avoid putting a node for it in the tree, so the numbers
++ * below are basically de-swizzled numbers.
++ * The real slot is on idsel 0, so the swizzling is 1:1
++ */
++ interrupt-map-mask = <0000 0 0 7>;
++ interrupt-map = <
++ 0000 0 0 1 &UIC3 10 4 /* swizzled int A */
++ 0000 0 0 2 &UIC3 11 4 /* swizzled int B */
++ 0000 0 0 3 &UIC3 12 4 /* swizzled int C */
++ 0000 0 0 4 &UIC3 13 4 /* swizzled int D */>;
++ };
++ };
++};
+diff --git a/arch/powerpc/boot/dts/cm5200.dts b/arch/powerpc/boot/dts/cm5200.dts
+index c6ca631..2f74cc4 100644
+--- a/arch/powerpc/boot/dts/cm5200.dts
++++ b/arch/powerpc/boot/dts/cm5200.dts
+@@ -10,11 +10,7 @@
+ * option) any later version.
+ */
- interrupt-parent = <&mpic>;
-- interrupts = <19 2>;
-+ interrupts = <25 2>;
- bus-range = <0 0>;
-- ranges = <02000000 0 90000000 90000000 0 10000000
-- 01000000 0 00000000 e2800000 0 00800000>;
-- clock-frequency = <3f940aa>;
-+ ranges = <0x2000000 0x0 0x90000000 0x90000000 0x0 0x10000000
-+ 0x1000000 0x0 0x0 0xe2800000 0x0 0x800000>;
-+ clock-frequency = <66666666>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- reg = <e0009000 1000>;
-+ reg = <0xe0009000 0x1000>;
- compatible = "fsl,mpc8540-pci";
- device_type = "pci";
+-/*
+- * WARNING: Do not depend on this tree layout remaining static just yet.
+- * The MPC5200 device tree conventions are still in flux
+- * Keep an eye on the linuxppc-dev mailing list for more details
+- */
++/dts-v1/;
+
+ / {
+ model = "schindler,cm5200";
+@@ -29,10 +25,10 @@
+ PowerPC,5200 at 0 {
+ device_type = "cpu";
+ reg = <0>;
+- d-cache-line-size = <20>;
+- i-cache-line-size = <20>;
+- d-cache-size = <4000>; // L1, 16K
+- i-cache-size = <4000>; // L1, 16K
++ d-cache-line-size = <32>;
++ i-cache-line-size = <32>;
++ d-cache-size = <0x4000>; // L1, 16K
++ i-cache-size = <0x4000>; // L1, 16K
+ timebase-frequency = <0>; // from bootloader
+ bus-frequency = <0>; // from bootloader
+ clock-frequency = <0>; // from bootloader
+@@ -41,34 +37,34 @@
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 04000000>; // 64MB
++ reg = <0x00000000 0x04000000>; // 64MB
};
- pci2: pcie at e000a000 {
- cell-index = <2>;
-- interrupt-map-mask = <f800 0 0 7>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
+ soc5200 at f0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc5200b-immr";
+- ranges = <0 f0000000 0000c000>;
+- reg = <f0000000 00000100>;
++ ranges = <0 0xf0000000 0x0000c000>;
++ reg = <0xf0000000 0x00000100>;
+ bus-frequency = <0>; // from bootloader
+ system-frequency = <0>; // from bootloader
+
+ cdm at 200 {
+ compatible = "fsl,mpc5200b-cdm","fsl,mpc5200-cdm";
+- reg = <200 38>;
++ reg = <0x200 0x38>;
+ };
- /* 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>;
+- mpc5200_pic: pic at 500 {
++ mpc5200_pic: interrupt-controller at 500 {
+ // 5200 interrupts are encoded into two levels;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ compatible = "fsl,mpc5200b-pic","fsl,mpc5200-pic";
+- reg = <500 80>;
++ reg = <0x500 0x80>;
+ };
- interrupt-parent = <&mpic>;
-- interrupts = <1a 2>;
-- bus-range = <0 ff>;
-- ranges = <02000000 0 a0000000 a0000000 0 20000000
-- 01000000 0 00000000 e3000000 0 08000000>;
-- clock-frequency = <1fca055>;
-+ interrupts = <26 2>;
-+ bus-range = <0 255>;
-+ ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
-+ 0x1000000 0x0 0x0 0xe3000000 0x0 0x8000000>;
-+ clock-frequency = <33333333>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- reg = <e000a000 1000>;
-+ reg = <0xe000a000 0x1000>;
- compatible = "fsl,mpc8548-pcie";
- device_type = "pci";
- pcie at 0 {
-- reg = <0 0 0 0 0>;
-+ reg = <0x0 0x0 0x0 0x0 0x0>;
- #size-cells = <2>;
- #address-cells = <3>;
- device_type = "pci";
-- ranges = <02000000 0 a0000000
-- 02000000 0 a0000000
-- 0 20000000
-+ ranges = <0x2000000 0x0 0xa0000000
-+ 0x2000000 0x0 0xa0000000
-+ 0x0 0x20000000
+ timer at 600 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+- reg = <600 10>;
++ reg = <0x600 0x10>;
+ interrupts = <1 9 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ fsl,has-wdt;
+@@ -76,108 +72,108 @@
+
+ timer at 610 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+- reg = <610 10>;
+- interrupts = <1 a 0>;
++ reg = <0x610 0x10>;
++ interrupts = <1 10 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
-- 01000000 0 00000000
-- 01000000 0 00000000
-- 0 08000000>;
-+ 0x1000000 0x0 0x0
-+ 0x1000000 0x0 0x0
-+ 0x0 0x8000000>;
+ timer at 620 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+- reg = <620 10>;
+- interrupts = <1 b 0>;
++ reg = <0x620 0x10>;
++ interrupts = <1 11 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ timer at 630 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+- reg = <630 10>;
+- interrupts = <1 c 0>;
++ reg = <0x630 0x10>;
++ interrupts = <1 12 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ timer at 640 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+- reg = <640 10>;
+- interrupts = <1 d 0>;
++ reg = <0x640 0x10>;
++ interrupts = <1 13 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ timer at 650 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+- reg = <650 10>;
+- interrupts = <1 e 0>;
++ reg = <0x650 0x10>;
++ interrupts = <1 14 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ timer at 660 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+- reg = <660 10>;
+- interrupts = <1 f 0>;
++ reg = <0x660 0x10>;
++ interrupts = <1 15 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ timer at 670 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+- reg = <670 10>;
+- interrupts = <1 10 0>;
++ reg = <0x670 0x10>;
++ interrupts = <1 16 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ rtc at 800 { // Real time clock
+ compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
+- reg = <800 100>;
++ reg = <0x800 0x100>;
+ interrupts = <1 5 0 1 6 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ gpio at b00 {
+ compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
+- reg = <b00 40>;
++ reg = <0xb00 0x40>;
+ interrupts = <1 7 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ gpio at c00 {
+ compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
+- reg = <c00 40>;
++ reg = <0xc00 0x40>;
+ interrupts = <1 8 0 0 3 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ spi at f00 {
+ compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
+- reg = <f00 20>;
+- interrupts = <2 d 0 2 e 0>;
++ reg = <0xf00 0x20>;
++ interrupts = <2 13 0 2 14 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ usb at 1000 {
+ compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
+- reg = <1000 ff>;
++ reg = <0x1000 0xff>;
+ interrupts = <2 6 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ dma-controller at 1200 {
+ compatible = "fsl,mpc5200b-bestcomm","fsl,mpc5200-bestcomm";
+- reg = <1200 80>;
++ reg = <0x1200 0x80>;
+ interrupts = <3 0 0 3 1 0 3 2 0 3 3 0
+ 3 4 0 3 5 0 3 6 0 3 7 0
+- 3 8 0 3 9 0 3 a 0 3 b 0
+- 3 c 0 3 d 0 3 e 0 3 f 0>;
++ 3 8 0 3 9 0 3 10 0 3 11 0
++ 3 12 0 3 13 0 3 14 0 3 15 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ xlb at 1f00 {
+ compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
+- reg = <1f00 100>;
++ reg = <0x1f00 0x100>;
+ };
+
+ serial at 2000 { // PSC1
+ device_type = "serial";
+ compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+ port-number = <0>; // Logical port assignment
+- reg = <2000 100>;
++ reg = <0x2000 0x100>;
+ interrupts = <2 1 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -186,7 +182,7 @@
+ device_type = "serial";
+ compatible = "fsl,mpc5200-psc-uart";
+ port-number = <1>; // Logical port assignment
+- reg = <2200 100>;
++ reg = <0x2200 0x100>;
+ interrupts = <2 2 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -195,7 +191,7 @@
+ device_type = "serial";
+ compatible = "fsl,mpc5200-psc-uart";
+ port-number = <2>; // Logical port assignment
+- reg = <2400 100>;
++ reg = <0x2400 0x100>;
+ interrupts = <2 3 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -204,7 +200,7 @@
+ device_type = "serial";
+ compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+ port-number = <5>; // Logical port assignment
+- reg = <2c00 100>;
++ reg = <0x2c00 0x100>;
+ interrupts = <2 4 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -212,7 +208,7 @@
+ ethernet at 3000 {
+ device_type = "network";
+ compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
+- reg = <3000 400>;
++ reg = <0x3000 0x400>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <2 5 0>;
+ interrupt-parent = <&mpc5200_pic>;
+@@ -223,7 +219,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200b-mdio","fsl,mpc5200-mdio";
+- reg = <3000 400>; // fec range, since we need to setup fec interrupts
++ reg = <0x3000 0x400>; // fec range, since we need to setup fec interrupts
+ interrupts = <2 5 0>; // these are for "mii command finished", not link changes & co.
+ interrupt-parent = <&mpc5200_pic>;
+
+@@ -237,15 +233,15 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
+- reg = <3d40 40>;
+- interrupts = <2 10 0>;
++ reg = <0x3d40 0x40>;
++ interrupts = <2 16 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ fsl5200-clocking;
+ };
+
+ sram at 8000 {
+ compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
+- reg = <8000 4000>;
++ reg = <0x8000 0x4000>;
};
};
- };
-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
+
+@@ -254,12 +250,12 @@
+ compatible = "fsl,lpb";
+ #address-cells = <2>;
+ #size-cells = <1>;
+- ranges = <0 0 fc000000 2000000>;
++ ranges = <0 0 0xfc000000 0x2000000>;
+
+ // 16-bit flash device at LocalPlus Bus CS0
+ flash at 0,0 {
+ compatible = "cfi-flash";
+- reg = <0 0 2000000>;
++ reg = <0 0 0x2000000>;
+ bank-width = <2>;
+ device-width = <2>;
+ #size-cells = <1>;
+diff --git a/arch/powerpc/boot/dts/ebony.dts b/arch/powerpc/boot/dts/ebony.dts
+index 0b000cb..5079dc8 100644
+--- a/arch/powerpc/boot/dts/ebony.dts
++++ b/arch/powerpc/boot/dts/ebony.dts
+@@ -241,7 +241,6 @@
+ };
+
+ EMAC0: ethernet at 40000800 {
+- linux,network-index = <0>;
+ device_type = "network";
+ compatible = "ibm,emac-440gp", "ibm,emac";
+ interrupt-parent = <&UIC1>;
+@@ -261,7 +260,6 @@
+ zmii-channel = <0>;
+ };
+ EMAC1: ethernet at 40000900 {
+- linux,network-index = <1>;
+ device_type = "network";
+ compatible = "ibm,emac-440gp", "ibm,emac";
+ interrupt-parent = <&UIC1>;
+diff --git a/arch/powerpc/boot/dts/ep8248e.dts b/arch/powerpc/boot/dts/ep8248e.dts
+index 5d2fb76..756758f 100644
+--- a/arch/powerpc/boot/dts/ep8248e.dts
++++ b/arch/powerpc/boot/dts/ep8248e.dts
+@@ -121,8 +121,7 @@
+
+ data at 0 {
+ compatible = "fsl,cpm-muram-data";
+- reg = <0 0x1100 0x1140
+- 0xec0 0x9800 0x800>;
++ reg = <0 0x2000 0x9800 0x800>;
+ };
+ };
+
+@@ -138,7 +137,7 @@
+ device_type = "serial";
+ compatible = "fsl,mpc8248-smc-uart",
+ "fsl,cpm2-smc-uart";
+- reg = <0x11a80 0x20 0x1100 0x40>;
++ reg = <0x11a80 0x20 0x87fc 2>;
+ interrupts = <4 8>;
+ interrupt-parent = <&PIC>;
+ fsl,cpm-brg = <7>;
+diff --git a/arch/powerpc/boot/dts/ep88xc.dts b/arch/powerpc/boot/dts/ep88xc.dts
+index 02705f2..ae57d62 100644
+--- a/arch/powerpc/boot/dts/ep88xc.dts
++++ b/arch/powerpc/boot/dts/ep88xc.dts
+@@ -2,7 +2,7 @@
+ * EP88xC Device Tree Source
*
-- * Copyright 2006 Freescale Semiconductor Inc.
-+ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+ * 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
-@@ -9,6 +9,7 @@
+@@ -10,6 +10,7 @@
* option) any later version.
*/
+/dts-v1/;
/ {
- model = "MPC8555CDS";
-@@ -31,11 +32,11 @@
+ model = "EP88xC";
+@@ -23,44 +24,44 @@
- PowerPC,8555 at 0 {
+ PowerPC,885 at 0 {
device_type = "cpu";
- reg = <0>;
-- d-cache-line-size = <20>; // 32 bytes
-- i-cache-line-size = <20>; // 32 bytes
-- d-cache-size = <8000>; // L1, 32K
-- i-cache-size = <8000>; // L1, 32K
+- d-cache-line-size = <d#16>;
+- i-cache-line-size = <d#16>;
+- d-cache-size = <d#8192>;
+- i-cache-size = <d#8192>;
+ reg = <0x0>;
-+ d-cache-line-size = <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 @@
++ d-cache-line-size = <16>;
++ i-cache-line-size = <16>;
++ d-cache-size = <8192>;
++ i-cache-size = <8192>;
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+- interrupts = <f 2>; // decrementer interrupt
++ interrupts = <15 2>; // decrementer interrupt
+ interrupt-parent = <&PIC>;
+ };
+ };
memory {
device_type = "memory";
-- reg = <00000000 08000000>; // 128M at 0x0
-+ reg = <0x0 0x8000000>; // 128M at 0x0
+- reg = <0 0>;
++ reg = <0x0 0x0>;
};
- soc8555 at e0000000 {
- #address-cells = <1>;
+ localbus at fa200100 {
+ compatible = "fsl,mpc885-localbus", "fsl,pq1-localbus";
+ #address-cells = <2>;
#size-cells = <1>;
- device_type = "soc";
-- ranges = <0 e0000000 00100000>;
-- reg = <e0000000 00001000>; // CCSRBAR 1M
-+ ranges = <0x0 0xe0000000 0x100000>;
-+ reg = <0xe0000000 0x1000>; // CCSRBAR 1M
- bus-frequency = <0>;
+- reg = <fa200100 40>;
++ reg = <0xfa200100 0x40>;
- memory-controller at 2000 {
- compatible = "fsl,8555-memory-controller";
-- reg = <2000 1000>;
-+ reg = <0x2000 0x1000>;
- interrupt-parent = <&mpic>;
-- interrupts = <12 2>;
-+ interrupts = <18 2>;
- };
+ ranges = <
+- 0 0 fc000000 04000000
+- 3 0 fa000000 01000000
++ 0x0 0x0 0xfc000000 0x4000000
++ 0x3 0x0 0xfa000000 0x1000000
+ >;
- l2-cache-controller at 20000 {
- compatible = "fsl,8555-l2-cache-controller";
-- reg = <20000 1000>;
-- cache-line-size = <20>; // 32 bytes
-- cache-size = <40000>; // L2, 256K
-+ reg = <0x20000 0x1000>;
-+ cache-line-size = <32>; // 32 bytes
-+ cache-size = <0x40000>; // L2, 256K
- interrupt-parent = <&mpic>;
-- interrupts = <10 2>;
-+ interrupts = <16 2>;
+ flash at 0,2000000 {
+ compatible = "cfi-flash";
+- reg = <0 2000000 2000000>;
++ reg = <0x0 0x2000000 0x2000000>;
+ bank-width = <4>;
+ device-width = <2>;
};
- i2c at 3000 {
-@@ -76,8 +77,8 @@
- #size-cells = <0>;
- cell-index = <0>;
- compatible = "fsl-i2c";
-- reg = <3000 100>;
-- interrupts = <2b 2>;
-+ reg = <0x3000 0x100>;
-+ interrupts = <43 2>;
- interrupt-parent = <&mpic>;
- dfsrr;
+ board-control at 3,400000 {
+- reg = <3 400000 10>;
++ reg = <0x3 0x400000 0x10>;
+ compatible = "fsl,ep88xc-bcsr";
};
-@@ -86,18 +87,18 @@
+ };
+@@ -70,25 +71,25 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+- ranges = <0 fa200000 00004000>;
++ ranges = <0x0 0xfa200000 0x4000>;
+ bus-frequency = <0>;
+
+ // Temporary -- will go away once kernel uses ranges for get_immrbase().
+- reg = <fa200000 4000>;
++ reg = <0xfa200000 0x4000>;
+
+ mdio at e00 {
+ compatible = "fsl,mpc885-fec-mdio", "fsl,pq1-fec-mdio";
+- reg = <e00 188>;
++ reg = <0xe00 0x188>;
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,gianfar-mdio";
-- reg = <24520 20>;
-+ reg = <0x24520 0x20>;
- phy0: ethernet-phy at 0 {
- interrupt-parent = <&mpic>;
- interrupts = <5 1>;
+ PHY0: ethernet-phy at 0 {
- reg = <0>;
+ reg = <0x0>;
device_type = "ethernet-phy";
};
- phy1: ethernet-phy at 1 {
- interrupt-parent = <&mpic>;
- interrupts = <5 1>;
+
+ PHY1: ethernet-phy at 1 {
- reg = <1>;
+ reg = <0x1>;
device_type = "ethernet-phy";
};
};
-@@ -107,9 +108,9 @@
+@@ -97,7 +98,7 @@
device_type = "network";
- model = "TSEC";
- compatible = "gianfar";
-- reg = <24000 1000>;
-+ reg = <0x24000 0x1000>;
+ compatible = "fsl,mpc885-fec-enet",
+ "fsl,pq1-fec-enet";
+- reg = <e00 188>;
++ reg = <0xe00 0x188>;
local-mac-address = [ 00 00 00 00 00 00 ];
-- interrupts = <1d 2 1e 2 22 2>;
-+ interrupts = <29 2 30 2 34 2>;
- interrupt-parent = <&mpic>;
- phy-handle = <&phy0>;
- };
-@@ -119,9 +120,9 @@
+ interrupts = <3 1>;
+ interrupt-parent = <&PIC>;
+@@ -109,7 +110,7 @@
device_type = "network";
- model = "TSEC";
- compatible = "gianfar";
-- reg = <25000 1000>;
-+ reg = <0x25000 0x1000>;
+ 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 = <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>;
+ interrupts = <7 1>;
+ interrupt-parent = <&PIC>;
+@@ -120,7 +121,7 @@
+ PIC: interrupt-controller at 0 {
+ interrupt-controller;
+ #interrupt-cells = <2>;
+- reg = <0 24>;
++ reg = <0x0 0x24>;
+ compatible = "fsl,mpc885-pic", "fsl,pq1-pic";
};
-@@ -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>;
+@@ -130,29 +131,29 @@
+ #size-cells = <2>;
+ compatible = "fsl,pq-pcmcia";
+ device_type = "pcmcia";
+- reg = <80 80>;
++ reg = <0x80 0x80>;
+ interrupt-parent = <&PIC>;
+- interrupts = <d 1>;
++ interrupts = <13 1>;
};
-@@ -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 @@
+ cpm at 9c0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "fsl,mpc8555-cpm", "fsl,cpm2";
-- reg = <919c0 30>;
-+ reg = <0x919c0 0x30>;
+ compatible = "fsl,mpc885-cpm", "fsl,cpm1";
+- command-proc = <9c0>;
++ command-proc = <0x9c0>;
+ interrupts = <0>; // cpm error interrupt
+ interrupt-parent = <&CPM_PIC>;
+- reg = <9c0 40>;
++ reg = <0x9c0 0x40>;
ranges;
- muram at 80000 {
+ muram at 2000 {
#address-cells = <1>;
#size-cells = <1>;
-- ranges = <0 80000 10000>;
-+ ranges = <0x0 0x80000 0x10000>;
+- ranges = <0 2000 2000>;
++ ranges = <0x0 0x2000 0x2000>;
data at 0 {
compatible = "fsl,cpm-muram-data";
-- reg = <0 2000 9000 1000>;
-+ reg = <0x0 0x2000 0x9000 0x1000>;
+- reg = <0 1c00>;
++ reg = <0x0 0x1c00>;
};
};
-@@ -179,16 +180,16 @@
- compatible = "fsl,mpc8555-brg",
- "fsl,cpm2-brg",
+@@ -160,7 +161,7 @@
+ compatible = "fsl,mpc885-brg",
+ "fsl,cpm1-brg",
"fsl,cpm-brg";
-- reg = <919f0 10 915f0 10>;
-+ reg = <0x919f0 0x10 0x915f0 0x10>;
+- reg = <9f0 10>;
++ reg = <0x9f0 0x10>;
};
- cpmpic: pic at 90c00 {
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <2>;
-- interrupts = <2e 2>;
-+ interrupts = <46 2>;
- interrupt-parent = <&mpic>;
-- reg = <90c00 80>;
-+ reg = <0x90c00 0x80>;
- compatible = "fsl,mpc8555-cpm-pic", "fsl,cpm2-pic";
+ CPM_PIC: interrupt-controller at 930 {
+@@ -168,7 +169,7 @@
+ #interrupt-cells = <1>;
+ interrupts = <5 2 0 2>;
+ interrupt-parent = <&PIC>;
+- reg = <930 20>;
++ reg = <0x930 0x20>;
+ compatible = "fsl,mpc885-cpm-pic",
+ "fsl,cpm1-pic";
+ };
+@@ -178,11 +179,11 @@
+ device_type = "serial";
+ compatible = "fsl,mpc885-smc-uart",
+ "fsl,cpm1-smc-uart";
+- reg = <a80 10 3e80 40>;
++ reg = <0xa80 0x10 0x3e80 0x40>;
+ interrupts = <4>;
+ interrupt-parent = <&CPM_PIC>;
+ fsl,cpm-brg = <1>;
+- fsl,cpm-command = <0090>;
++ fsl,cpm-command = <0x90>;
+ linux,planetcore-label = "SMC1";
};
- };
-@@ -196,68 +197,68 @@
-
- pci0: pci at e0008000 {
- cell-index = <0>;
-- interrupt-map-mask = <1f800 0 0 7>;
-+ interrupt-map-mask = <0x1f800 0x0 0x0 0x7>;
- interrupt-map = <
- /* IDSEL 0x10 */
-- 08000 0 0 1 &mpic 0 1
-- 08000 0 0 2 &mpic 1 1
-- 08000 0 0 3 &mpic 2 1
-- 08000 0 0 4 &mpic 3 1
-+ 0x8000 0x0 0x0 0x1 &mpic 0x0 0x1
-+ 0x8000 0x0 0x0 0x2 &mpic 0x1 0x1
-+ 0x8000 0x0 0x0 0x3 &mpic 0x2 0x1
-+ 0x8000 0x0 0x0 0x4 &mpic 0x3 0x1
+@@ -191,11 +192,11 @@
+ device_type = "serial";
+ compatible = "fsl,mpc885-scc-uart",
+ "fsl,cpm1-scc-uart";
+- reg = <a20 20 3d00 80>;
+- interrupts = <1d>;
++ reg = <0xa20 0x20 0x3d00 0x80>;
++ interrupts = <29>;
+ interrupt-parent = <&CPM_PIC>;
+ fsl,cpm-brg = <2>;
+- fsl,cpm-command = <0040>;
++ fsl,cpm-command = <0x40>;
+ linux,planetcore-label = "SCC2";
+ };
- /* 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
+@@ -204,9 +205,9 @@
+ #size-cells = <0>;
+ compatible = "fsl,mpc885-usb",
+ "fsl,cpm1-usb";
+- reg = <a00 18 1c00 80>;
++ reg = <0xa00 0x18 0x1c00 0x80>;
+ interrupt-parent = <&CPM_PIC>;
+- interrupts = <1e>;
++ interrupts = <30>;
+ fsl,cpm-command = <0000>;
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/glacier.dts b/arch/powerpc/boot/dts/glacier.dts
+new file mode 100644
+index 0000000..0f2fc07
+--- /dev/null
++++ b/arch/powerpc/boot/dts/glacier.dts
+@@ -0,0 +1,504 @@
++/*
++ * Device Tree Source for AMCC Glacier (460GT)
++ *
++ * Copyright 2008 DENX Software Engineering, Stefan Roese <sr at denx.de>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without
++ * any warranty of any kind, whether express or implied.
++ */
++
++/ {
++ #address-cells = <2>;
++ #size-cells = <1>;
++ model = "amcc,glacier";
++ compatible = "amcc,glacier", "amcc,canyonlands";
++ dcr-parent = <&/cpus/cpu at 0>;
++
++ aliases {
++ ethernet0 = &EMAC0;
++ ethernet1 = &EMAC1;
++ ethernet2 = &EMAC2;
++ ethernet3 = &EMAC3;
++ serial0 = &UART0;
++ serial1 = &UART1;
++ };
++
++ cpus {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ cpu at 0 {
++ device_type = "cpu";
++ model = "PowerPC,460GT";
++ reg = <0>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ timebase-frequency = <0>; /* Filled in by U-Boot */
++ i-cache-line-size = <20>;
++ d-cache-line-size = <20>;
++ i-cache-size = <8000>;
++ d-cache-size = <8000>;
++ dcr-controller;
++ dcr-access-method = "native";
++ };
++ };
++
++ memory {
++ device_type = "memory";
++ reg = <0 0 0>; /* Filled in by U-Boot */
++ };
++
++ UIC0: interrupt-controller0 {
++ compatible = "ibm,uic-460gt","ibm,uic";
++ interrupt-controller;
++ cell-index = <0>;
++ dcr-reg = <0c0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ };
++
++ UIC1: interrupt-controller1 {
++ compatible = "ibm,uic-460gt","ibm,uic";
++ interrupt-controller;
++ cell-index = <1>;
++ dcr-reg = <0d0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ interrupts = <1e 4 1f 4>; /* cascade */
++ interrupt-parent = <&UIC0>;
++ };
++
++ UIC2: interrupt-controller2 {
++ compatible = "ibm,uic-460gt","ibm,uic";
++ interrupt-controller;
++ cell-index = <2>;
++ dcr-reg = <0e0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ interrupts = <a 4 b 4>; /* cascade */
++ interrupt-parent = <&UIC0>;
++ };
++
++ UIC3: interrupt-controller3 {
++ compatible = "ibm,uic-460gt","ibm,uic";
++ interrupt-controller;
++ cell-index = <3>;
++ dcr-reg = <0f0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ interrupts = <10 4 11 4>; /* cascade */
++ interrupt-parent = <&UIC0>;
++ };
++
++ SDR0: sdr {
++ compatible = "ibm,sdr-460gt";
++ dcr-reg = <00e 002>;
++ };
++
++ CPR0: cpr {
++ compatible = "ibm,cpr-460gt";
++ dcr-reg = <00c 002>;
++ };
++
++ plb {
++ compatible = "ibm,plb-460gt", "ibm,plb4";
++ #address-cells = <2>;
++ #size-cells = <1>;
++ ranges;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++
++ SDRAM0: sdram {
++ compatible = "ibm,sdram-460gt", "ibm,sdram-405gp";
++ dcr-reg = <010 2>;
++ };
++
++ MAL0: mcmal {
++ compatible = "ibm,mcmal-460gt", "ibm,mcmal2";
++ dcr-reg = <180 62>;
++ num-tx-chans = <4>;
++ num-rx-chans = <20>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ interrupt-parent = <&UIC2>;
++ interrupts = < /*TXEOB*/ 6 4
++ /*RXEOB*/ 7 4
++ /*SERR*/ 3 4
++ /*TXDE*/ 4 4
++ /*RXDE*/ 5 4>;
++ desc-base-addr-high = <8>;
++ };
++
++ POB0: opb {
++ compatible = "ibm,opb-460gt", "ibm,opb";
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges = <b0000000 4 b0000000 50000000>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++
++ EBC0: ebc {
++ compatible = "ibm,ebc-460gt", "ibm,ebc";
++ dcr-reg = <012 2>;
++ #address-cells = <2>;
++ #size-cells = <1>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ /* ranges property is supplied by U-Boot */
++ interrupts = <6 4>;
++ interrupt-parent = <&UIC1>;
++
++ nor_flash at 0,0 {
++ compatible = "amd,s29gl512n", "cfi-flash";
++ bank-width = <2>;
++ reg = <0 000000 4000000>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++ partition at 0 {
++ label = "kernel";
++ reg = <0 1e0000>;
++ };
++ partition at 1e0000 {
++ label = "dtb";
++ reg = <1e0000 20000>;
++ };
++ partition at 200000 {
++ label = "ramdisk";
++ reg = <200000 1400000>;
++ };
++ partition at 1600000 {
++ label = "jffs2";
++ reg = <1600000 400000>;
++ };
++ partition at 1a00000 {
++ label = "user";
++ reg = <1a00000 2560000>;
++ };
++ partition at 3f60000 {
++ label = "env";
++ reg = <3f60000 40000>;
++ };
++ partition at 3fa0000 {
++ label = "u-boot";
++ reg = <3fa0000 60000>;
++ };
++ };
++ };
++
++ UART0: serial at ef600300 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600300 8>;
++ virtual-reg = <ef600300>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ current-speed = <0>; /* Filled in by U-Boot */
++ interrupt-parent = <&UIC1>;
++ interrupts = <1 4>;
++ };
++
++ UART1: serial at ef600400 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600400 8>;
++ virtual-reg = <ef600400>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ current-speed = <0>; /* Filled in by U-Boot */
++ interrupt-parent = <&UIC0>;
++ interrupts = <1 4>;
++ };
++
++ UART2: serial at ef600500 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600500 8>;
++ virtual-reg = <ef600500>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ current-speed = <0>; /* Filled in by U-Boot */
++ interrupt-parent = <&UIC1>;
++ interrupts = <1d 4>;
++ };
++
++ UART3: serial at ef600600 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600600 8>;
++ virtual-reg = <ef600600>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ current-speed = <0>; /* Filled in by U-Boot */
++ interrupt-parent = <&UIC1>;
++ interrupts = <1e 4>;
++ };
++
++ IIC0: i2c at ef600700 {
++ compatible = "ibm,iic-460gt", "ibm,iic";
++ reg = <ef600700 14>;
++ interrupt-parent = <&UIC0>;
++ interrupts = <2 4>;
++ };
++
++ IIC1: i2c at ef600800 {
++ compatible = "ibm,iic-460gt", "ibm,iic";
++ reg = <ef600800 14>;
++ interrupt-parent = <&UIC0>;
++ interrupts = <3 4>;
++ };
++
++ ZMII0: emac-zmii at ef600d00 {
++ compatible = "ibm,zmii-460gt", "ibm,zmii";
++ reg = <ef600d00 c>;
++ };
++
++ RGMII0: emac-rgmii at ef601500 {
++ compatible = "ibm,rgmii-460gt", "ibm,rgmii";
++ reg = <ef601500 8>;
++ has-mdio;
++ };
++
++ RGMII1: emac-rgmii at ef601600 {
++ compatible = "ibm,rgmii-460gt", "ibm,rgmii";
++ reg = <ef601600 8>;
++ has-mdio;
++ };
++
++ TAH0: emac-tah at ef601350 {
++ compatible = "ibm,tah-460gt", "ibm,tah";
++ reg = <ef601350 30>;
++ };
++
++ TAH1: emac-tah at ef601450 {
++ compatible = "ibm,tah-460gt", "ibm,tah";
++ reg = <ef601450 30>;
++ };
++
++ EMAC0: ethernet at ef600e00 {
++ device_type = "network";
++ compatible = "ibm,emac-460gt", "ibm,emac4";
++ interrupt-parent = <&EMAC0>;
++ interrupts = <0 1>;
++ #interrupt-cells = <1>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ interrupt-map = </*Status*/ 0 &UIC2 10 4
++ /*Wake*/ 1 &UIC2 14 4>;
++ reg = <ef600e00 70>;
++ local-mac-address = [000000000000]; /* Filled in by U-Boot */
++ mal-device = <&MAL0>;
++ mal-tx-channel = <0>;
++ mal-rx-channel = <0>;
++ cell-index = <0>;
++ max-frame-size = <2328>;
++ rx-fifo-size = <1000>;
++ tx-fifo-size = <800>;
++ phy-mode = "rgmii";
++ phy-map = <00000000>;
++ rgmii-device = <&RGMII0>;
++ rgmii-channel = <0>;
++ tah-device = <&TAH0>;
++ tah-channel = <0>;
++ has-inverted-stacr-oc;
++ has-new-stacr-staopc;
++ };
++
++ EMAC1: ethernet at ef600f00 {
++ device_type = "network";
++ compatible = "ibm,emac-460gt", "ibm,emac4";
++ interrupt-parent = <&EMAC1>;
++ interrupts = <0 1>;
++ #interrupt-cells = <1>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ interrupt-map = </*Status*/ 0 &UIC2 11 4
++ /*Wake*/ 1 &UIC2 15 4>;
++ reg = <ef600f00 70>;
++ local-mac-address = [000000000000]; /* Filled in by U-Boot */
++ mal-device = <&MAL0>;
++ mal-tx-channel = <1>;
++ mal-rx-channel = <8>;
++ cell-index = <1>;
++ max-frame-size = <2328>;
++ rx-fifo-size = <1000>;
++ tx-fifo-size = <800>;
++ phy-mode = "rgmii";
++ phy-map = <00000000>;
++ rgmii-device = <&RGMII0>;
++ rgmii-channel = <1>;
++ tah-device = <&TAH1>;
++ tah-channel = <1>;
++ has-inverted-stacr-oc;
++ has-new-stacr-staopc;
++ mdio-device = <&EMAC0>;
++ };
++
++ EMAC2: ethernet at ef601100 {
++ device_type = "network";
++ compatible = "ibm,emac-460gt", "ibm,emac4";
++ interrupt-parent = <&EMAC2>;
++ interrupts = <0 1>;
++ #interrupt-cells = <1>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ interrupt-map = </*Status*/ 0 &UIC2 12 4
++ /*Wake*/ 1 &UIC2 16 4>;
++ reg = <ef601100 70>;
++ local-mac-address = [000000000000]; /* Filled in by U-Boot */
++ mal-device = <&MAL0>;
++ mal-tx-channel = <2>;
++ mal-rx-channel = <10>;
++ cell-index = <2>;
++ max-frame-size = <2328>;
++ rx-fifo-size = <1000>;
++ tx-fifo-size = <800>;
++ phy-mode = "rgmii";
++ phy-map = <00000000>;
++ rgmii-device = <&RGMII1>;
++ rgmii-channel = <0>;
++ has-inverted-stacr-oc;
++ has-new-stacr-staopc;
++ mdio-device = <&EMAC0>;
++ };
++
++ EMAC3: ethernet at ef601200 {
++ device_type = "network";
++ compatible = "ibm,emac-460gt", "ibm,emac4";
++ interrupt-parent = <&EMAC3>;
++ interrupts = <0 1>;
++ #interrupt-cells = <1>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ interrupt-map = </*Status*/ 0 &UIC2 13 4
++ /*Wake*/ 1 &UIC2 17 4>;
++ reg = <ef601200 70>;
++ local-mac-address = [000000000000]; /* Filled in by U-Boot */
++ mal-device = <&MAL0>;
++ mal-tx-channel = <3>;
++ mal-rx-channel = <18>;
++ cell-index = <3>;
++ max-frame-size = <2328>;
++ rx-fifo-size = <1000>;
++ tx-fifo-size = <800>;
++ phy-mode = "rgmii";
++ phy-map = <00000000>;
++ rgmii-device = <&RGMII1>;
++ rgmii-channel = <1>;
++ has-inverted-stacr-oc;
++ has-new-stacr-staopc;
++ mdio-device = <&EMAC0>;
++ };
++ };
++
++ PCIX0: pci at c0ec00000 {
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ compatible = "ibm,plb-pcix-460gt", "ibm,plb-pcix";
++ primary;
++ large-inbound-windows;
++ enable-msi-hole;
++ reg = <c 0ec00000 8 /* Config space access */
++ 0 0 0 /* no IACK cycles */
++ c 0ed00000 4 /* Special cycles */
++ c 0ec80000 100 /* Internal registers */
++ c 0ec80100 fc>; /* Internal messaging registers */
++
++ /* Outbound ranges, one memory and one IO,
++ * later cannot be changed
++ */
++ ranges = <02000000 0 80000000 0000000d 80000000 0 80000000
++ 01000000 0 00000000 0000000c 08000000 0 00010000>;
++
++ /* Inbound 2GB range starting at 0 */
++ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++ /* This drives busses 0 to 0x3f */
++ bus-range = <0 3f>;
++
++ /* All PCI interrupts are routed to ext IRQ 2 -> UIC1-0 */
++ interrupt-map-mask = <0000 0 0 0>;
++ interrupt-map = < 0000 0 0 0 &UIC1 0 8 >;
++ };
++
++ PCIE0: pciex at d00000000 {
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
++ primary;
++ port = <0>; /* port number */
++ reg = <d 00000000 20000000 /* Config space access */
++ c 08010000 00001000>; /* Registers */
++ dcr-reg = <100 020>;
++ sdr-base = <300>;
++
++ /* Outbound ranges, one memory and one IO,
++ * later cannot be changed
++ */
++ ranges = <02000000 0 80000000 0000000e 00000000 0 80000000
++ 01000000 0 00000000 0000000f 80000000 0 00010000>;
++
++ /* Inbound 2GB range starting at 0 */
++ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++ /* This drives busses 40 to 0x7f */
++ bus-range = <40 7f>;
++
++ /* Legacy interrupts (note the weird polarity, the bridge seems
++ * to invert PCIe legacy interrupts).
++ * We are de-swizzling here because the numbers are actually for
++ * port of the root complex virtual P2P bridge. But I want
++ * to avoid putting a node for it in the tree, so the numbers
++ * below are basically de-swizzled numbers.
++ * The real slot is on idsel 0, so the swizzling is 1:1
++ */
++ interrupt-map-mask = <0000 0 0 7>;
++ interrupt-map = <
++ 0000 0 0 1 &UIC3 c 4 /* swizzled int A */
++ 0000 0 0 2 &UIC3 d 4 /* swizzled int B */
++ 0000 0 0 3 &UIC3 e 4 /* swizzled int C */
++ 0000 0 0 4 &UIC3 f 4 /* swizzled int D */>;
++ };
++
++ PCIE1: pciex at d20000000 {
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
++ primary;
++ port = <1>; /* port number */
++ reg = <d 20000000 20000000 /* Config space access */
++ c 08011000 00001000>; /* Registers */
++ dcr-reg = <120 020>;
++ sdr-base = <340>;
++
++ /* Outbound ranges, one memory and one IO,
++ * later cannot be changed
++ */
++ ranges = <02000000 0 80000000 0000000e 80000000 0 80000000
++ 01000000 0 00000000 0000000f 80010000 0 00010000>;
++
++ /* Inbound 2GB range starting at 0 */
++ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++ /* This drives busses 80 to 0xbf */
++ bus-range = <80 bf>;
++
++ /* Legacy interrupts (note the weird polarity, the bridge seems
++ * to invert PCIe legacy interrupts).
++ * We are de-swizzling here because the numbers are actually for
++ * port of the root complex virtual P2P bridge. But I want
++ * to avoid putting a node for it in the tree, so the numbers
++ * below are basically de-swizzled numbers.
++ * The real slot is on idsel 0, so the swizzling is 1:1
++ */
++ interrupt-map-mask = <0000 0 0 7>;
++ interrupt-map = <
++ 0000 0 0 1 &UIC3 10 4 /* swizzled int A */
++ 0000 0 0 2 &UIC3 11 4 /* swizzled int B */
++ 0000 0 0 3 &UIC3 12 4 /* swizzled int C */
++ 0000 0 0 4 &UIC3 13 4 /* swizzled int D */>;
++ };
++ };
++};
+diff --git a/arch/powerpc/boot/dts/haleakala.dts b/arch/powerpc/boot/dts/haleakala.dts
+index ae68fef..b5d95ac 100644
+--- a/arch/powerpc/boot/dts/haleakala.dts
++++ b/arch/powerpc/boot/dts/haleakala.dts
+@@ -12,7 +12,7 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "amcc,haleakala";
+- compatible = "amcc,kilauea";
++ compatible = "amcc,haleakala", "amcc,kilauea";
+ dcr-parent = <&/cpus/cpu at 0>;
- /* 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
+ aliases {
+@@ -218,7 +218,7 @@
+ mal-tx-channel = <0>;
+ mal-rx-channel = <0>;
+ cell-index = <0>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+diff --git a/arch/powerpc/boot/dts/katmai.dts b/arch/powerpc/boot/dts/katmai.dts
+index fc86e5a..cc2873a 100644
+--- a/arch/powerpc/boot/dts/katmai.dts
++++ b/arch/powerpc/boot/dts/katmai.dts
+@@ -212,7 +212,7 @@
+ mal-tx-channel = <0>;
+ mal-rx-channel = <0>;
+ cell-index = <0>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "gmii";
+diff --git a/arch/powerpc/boot/dts/kilauea.dts b/arch/powerpc/boot/dts/kilauea.dts
+index 8baef61..48c9a6e 100644
+--- a/arch/powerpc/boot/dts/kilauea.dts
++++ b/arch/powerpc/boot/dts/kilauea.dts
+@@ -219,7 +219,7 @@
+ mal-tx-channel = <0>;
+ mal-rx-channel = <0>;
+ cell-index = <0>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+@@ -247,7 +247,7 @@
+ mal-tx-channel = <1>;
+ mal-rx-channel = <1>;
+ cell-index = <1>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+diff --git a/arch/powerpc/boot/dts/ksi8560.dts b/arch/powerpc/boot/dts/ksi8560.dts
+new file mode 100644
+index 0000000..f869ce3
+--- /dev/null
++++ b/arch/powerpc/boot/dts/ksi8560.dts
+@@ -0,0 +1,267 @@
++/*
++ * Device Tree Source for Emerson KSI8560
++ *
++ * Author: Alexandr Smirnov <asmirnov at ru.mvista.com>
++ *
++ * Based on mpc8560ads.dts
++ *
++ * 2008 (c) MontaVista, Software, Inc. This file is licensed under
++ * the terms of the GNU General Public License version 2. This program
++ * is licensed "as is" without any warranty of any kind, whether express
++ * or implied.
++ *
++ */
++
++/dts-v1/;
++
++/ {
++ model = "KSI8560";
++ compatible = "emerson,KSI8560";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ aliases {
++ ethernet0 = &enet0;
++ ethernet1 = &enet1;
++ ethernet2 = &enet2;
++ };
++
++ cpus {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ PowerPC,8560 at 0 {
++ device_type = "cpu";
++ reg = <0>;
++ d-cache-line-size = <32>;
++ i-cache-line-size = <32>;
++ d-cache-size = <0x8000>; /* L1, 32K */
++ i-cache-size = <0x8000>; /* L1, 32K */
++ timebase-frequency = <0>; /* From U-boot */
++ bus-frequency = <0>; /* From U-boot */
++ clock-frequency = <0>; /* From U-boot */
++ };
++ };
++
++ memory {
++ device_type = "memory";
++ reg = <0x00000000 0x10000000>; /* Fixed by bootwrapper */
++ };
++
++ soc at fdf00000 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ device_type = "soc";
++ ranges = <0x00000000 0xfdf00000 0x00100000>;
++ bus-frequency = <0>; /* Fixed by bootwrapper */
++
++ memory-controller at 2000 {
++ compatible = "fsl,8540-memory-controller";
++ reg = <0x2000 0x1000>;
++ interrupt-parent = <&MPIC>;
++ interrupts = <0x12 0x2>;
++ };
++
++ l2-cache-controller at 20000 {
++ compatible = "fsl,8540-l2-cache-controller";
++ reg = <0x20000 0x1000>;
++ cache-line-size = <0x20>; /* 32 bytes */
++ cache-size = <0x40000>; /* L2, 256K */
++ interrupt-parent = <&MPIC>;
++ interrupts = <0x10 0x2>;
++ };
++
++ i2c at 3000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ cell-index = <0>;
++ compatible = "fsl-i2c";
++ reg = <0x3000 0x100>;
++ interrupts = <0x2b 0x2>;
++ interrupt-parent = <&MPIC>;
++ dfsrr;
++ };
++
++ mdio at 24520 { /* For TSECs */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "fsl,gianfar-mdio";
++ reg = <0x24520 0x20>;
++
++ PHY1: ethernet-phy at 1 {
++ interrupt-parent = <&MPIC>;
++ reg = <0x1>;
++ device_type = "ethernet-phy";
++ };
++
++ PHY2: ethernet-phy at 2 {
++ interrupt-parent = <&MPIC>;
++ reg = <0x2>;
++ device_type = "ethernet-phy";
++ };
++ };
++
++ enet0: ethernet at 24000 {
++ device_type = "network";
++ model = "TSEC";
++ compatible = "gianfar";
++ reg = <0x24000 0x1000>;
++ /* Mac address filled in by bootwrapper */
++ local-mac-address = [ 00 00 00 00 00 00 ];
++ interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
++ interrupt-parent = <&MPIC>;
++ phy-handle = <&PHY1>;
++ };
++
++ enet1: ethernet at 25000 {
++ device_type = "network";
++ model = "TSEC";
++ compatible = "gianfar";
++ reg = <0x25000 0x1000>;
++ /* Mac address filled in by bootwrapper */
++ local-mac-address = [ 00 00 00 00 00 00 ];
++ interrupts = <0x23 0x2 0x24 0x2 0x28 0x2>;
++ interrupt-parent = <&MPIC>;
++ phy-handle = <&PHY2>;
++ };
++
++ MPIC: pic at 40000 {
++ #address-cells = <0>;
++ #interrupt-cells = <2>;
++ interrupt-controller;
++ reg = <0x40000 0x40000>;
++ device_type = "open-pic";
++ };
++
++ cpm at 919c0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "fsl,mpc8560-cpm", "fsl,cpm2";
++ reg = <0x919c0 0x30>;
++ ranges;
++
++ muram at 80000 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges = <0x0 0x80000 0x10000>;
++
++ data at 0 {
++ compatible = "fsl,cpm-muram-data";
++ reg = <0x0 0x4000 0x9000 0x2000>;
++ };
++ };
++
++ brg at 919f0 {
++ compatible = "fsl,mpc8560-brg",
++ "fsl,cpm2-brg",
++ "fsl,cpm-brg";
++ reg = <0x919f0 0x10 0x915f0 0x10>;
++ clock-frequency = <165000000>; /* 166MHz */
++ };
++
++ CPMPIC: pic at 90c00 {
++ #address-cells = <0>;
++ #interrupt-cells = <2>;
++ interrupt-controller;
++ interrupts = <0x2e 0x2>;
++ interrupt-parent = <&MPIC>;
++ reg = <0x90c00 0x80>;
++ compatible = "fsl,mpc8560-cpm-pic", "fsl,cpm2-pic";
++ };
++
++ serial at 91a00 {
++ device_type = "serial";
++ compatible = "fsl,mpc8560-scc-uart",
++ "fsl,cpm2-scc-uart";
++ reg = <0x91a00 0x20 0x88000 0x100>;
++ fsl,cpm-brg = <1>;
++ fsl,cpm-command = <0x800000>;
++ current-speed = <0x1c200>;
++ interrupts = <0x28 0x8>;
++ interrupt-parent = <&CPMPIC>;
++ };
++
++ serial at 91a20 {
++ device_type = "serial";
++ compatible = "fsl,mpc8560-scc-uart",
++ "fsl,cpm2-scc-uart";
++ reg = <0x91a20 0x20 0x88100 0x100>;
++ fsl,cpm-brg = <2>;
++ fsl,cpm-command = <0x4a00000>;
++ current-speed = <0x1c200>;
++ interrupts = <0x29 0x8>;
++ interrupt-parent = <&CPMPIC>;
++ };
++
++ mdio at 90d00 { /* For FCCs */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "fsl,cpm2-mdio-bitbang";
++ reg = <0x90d00 0x14>;
++ fsl,mdio-pin = <24>;
++ fsl,mdc-pin = <25>;
++
++ PHY0: ethernet-phy at 0 {
++ interrupt-parent = <&MPIC>;
++ reg = <0x0>;
++ device_type = "ethernet-phy";
++ };
++ };
++
++ enet2: ethernet at 91300 {
++ device_type = "network";
++ compatible = "fsl,mpc8560-fcc-enet",
++ "fsl,cpm2-fcc-enet";
++ reg = <0x91300 0x20 0x88400 0x100 0x91390 0x1>;
++ /* Mac address filled in by bootwrapper */
++ local-mac-address = [ 00 00 00 00 00 00 ];
++ fsl,cpm-command = <0x12000300>;
++ interrupts = <0x20 0x8>;
++ interrupt-parent = <&CPMPIC>;
++ phy-handle = <&PHY0>;
++ };
++ };
++ };
++
++ localbus at fdf05000 {
++ #address-cells = <2>;
++ #size-cells = <1>;
++ compatible = "fsl,mpc8560-localbus";
++ reg = <0xfdf05000 0x68>;
++
++ ranges = <0x0 0x0 0xe0000000 0x00800000
++ 0x4 0x0 0xe8080000 0x00080000>;
++
++ flash at 0,0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "jedec-flash";
++ reg = <0x0 0x0 0x800000>;
++ bank-width = <0x2>;
++
++ partition at 0 {
++ label = "Primary Kernel";
++ reg = <0x0 0x180000>;
++ };
++ partition at 180000 {
++ label = "Primary Filesystem";
++ reg = <0x180000 0x580000>;
++ };
++ partition at 700000 {
++ label = "Monitor";
++ reg = <0x300000 0x100000>;
++ read-only;
++ };
++ };
++
++ cpld at 4,0 {
++ compatible = "emerson,KSI8560-cpld";
++ reg = <0x4 0x0 0x80000>;
++ };
++ };
++
++
++ chosen {
++ linux,stdout-path = "/soc/cpm/serial at 91a00";
++ };
++};
+diff --git a/arch/powerpc/boot/dts/kuroboxHD.dts b/arch/powerpc/boot/dts/kuroboxHD.dts
+index 4469588..2e5a1a1 100644
+--- a/arch/powerpc/boot/dts/kuroboxHD.dts
++++ b/arch/powerpc/boot/dts/kuroboxHD.dts
+@@ -7,6 +7,7 @@
+ * Based on sandpoint.dts
+ *
+ * 2006 (c) G. Liakhovetski <g.liakhovetski at gmx.de>
++ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+@@ -17,6 +18,8 @@ XXXX add flash parts, rtc, ??
- /* 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
++/dts-v1/;
++
+ / {
+ model = "KuroboxHD";
+ compatible = "linkstation";
+@@ -35,19 +38,19 @@ XXXX add flash parts, rtc, ??
- /* 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
+ PowerPC,603e { /* Really 8241 */
+ device_type = "cpu";
+- reg = <0>;
+- clock-frequency = <bebc200>; /* Fixed by bootloader */
+- timebase-frequency = <1743000>; /* Fixed by bootloader */
++ reg = <0x0>;
++ clock-frequency = <200000000>; /* Fixed by bootloader */
++ timebase-frequency = <24391680>; /* Fixed by bootloader */
+ bus-frequency = <0>; /* Fixed by bootloader */
+ /* Following required by dtc but not used */
+- i-cache-size = <4000>;
+- d-cache-size = <4000>;
++ i-cache-size = <0x4000>;
++ d-cache-size = <0x4000>;
+ };
+ };
- /* Bus 1 (Tundra Bridge) */
- /* IDSEL 0x12 (ISA bridge) */
-- 19000 0 0 1 &mpic 0 1
-- 19000 0 0 2 &mpic 1 1
-- 19000 0 0 3 &mpic 2 1
-- 19000 0 0 4 &mpic 3 1>;
-+ 0x19000 0x0 0x0 0x1 &mpic 0x0 0x1
-+ 0x19000 0x0 0x0 0x2 &mpic 0x1 0x1
-+ 0x19000 0x0 0x0 0x3 &mpic 0x2 0x1
-+ 0x19000 0x0 0x0 0x4 &mpic 0x3 0x1>;
- interrupt-parent = <&mpic>;
-- interrupts = <18 2>;
-+ interrupts = <24 2>;
- bus-range = <0 0>;
-- ranges = <02000000 0 80000000 80000000 0 20000000
-- 01000000 0 00000000 e2000000 0 00100000>;
-- clock-frequency = <3f940aa>;
-+ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
-+ 0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>;
-+ clock-frequency = <66666666>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- reg = <e0008000 1000>;
-+ reg = <0xe0008000 0x1000>;
- compatible = "fsl,mpc8540-pci";
- device_type = "pci";
+ memory {
+ device_type = "memory";
+- reg = <00000000 04000000>;
++ reg = <0x0 0x4000000>;
+ };
- i8259 at 19000 {
- interrupt-controller;
- device_type = "interrupt-controller";
-- reg = <19000 0 0 0 1>;
-+ reg = <0x19000 0x0 0x0 0x0 0x1>;
- #address-cells = <0>;
- #interrupt-cells = <2>;
- compatible = "chrp,iic";
-@@ -268,24 +269,24 @@
+ 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 */
- pci1: pci at e0009000 {
- cell-index = <1>;
-- interrupt-map-mask = <f800 0 0 7>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
+ i2c at 80003000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+- reg = <80003000 1000>;
++ reg = <0x80003000 0x1000>;
+ interrupts = <5 2>;
+ interrupt-parent = <&mpic>;
- /* IDSEL 0x15 */
-- a800 0 0 1 &mpic b 1
-- a800 0 0 2 &mpic b 1
-- a800 0 0 3 &mpic b 1
-- a800 0 0 4 &mpic b 1>;
-+ 0xa800 0x0 0x0 0x1 &mpic 0xb 0x1
-+ 0xa800 0x0 0x0 0x2 &mpic 0xb 0x1
-+ 0xa800 0x0 0x0 0x3 &mpic 0xb 0x1
-+ 0xa800 0x0 0x0 0x4 &mpic 0xb 0x1>;
- interrupt-parent = <&mpic>;
-- interrupts = <19 2>;
-+ interrupts = <25 2>;
- bus-range = <0 0>;
-- ranges = <02000000 0 a0000000 a0000000 0 20000000
-- 01000000 0 00000000 e3000000 0 00100000>;
-- clock-frequency = <3f940aa>;
-+ ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
-+ 0x1000000 0x0 0x0 0xe3000000 0x0 0x100000>;
-+ clock-frequency = <66666666>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- reg = <e0009000 1000>;
-+ reg = <0xe0009000 0x1000>;
- compatible = "fsl,mpc8540-pci";
- device_type = "pci";
+ rtc at 32 {
+ device_type = "rtc";
+ compatible = "ricoh,rs5c372a";
+- reg = <32>;
++ reg = <0x32>;
+ };
+ };
+
+@@ -83,9 +86,9 @@ XXXX add flash parts, rtc, ??
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <80004500 8>;
+- clock-frequency = <5d08d88>;
+- current-speed = <2580>;
++ reg = <0x80004500 0x8>;
++ clock-frequency = <97553800>;
++ current-speed = <9600>;
+ interrupts = <9 0>;
+ interrupt-parent = <&mpic>;
+ };
+@@ -94,10 +97,10 @@ XXXX add flash parts, rtc, ??
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <80004600 8>;
+- clock-frequency = <5d08d88>;
+- current-speed = <e100>;
+- interrupts = <a 0>;
++ reg = <0x80004600 0x8>;
++ clock-frequency = <97553800>;
++ current-speed = <57600>;
++ interrupts = <10 0>;
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -107,7 +110,7 @@ XXXX add flash parts, rtc, ??
+ device_type = "open-pic";
+ compatible = "chrp,open-pic";
+ interrupt-controller;
+- reg = <80040000 40000>;
++ reg = <0x80040000 0x40000>;
+ };
+
+ pci0: pci at fec00000 {
+@@ -116,29 +119,29 @@ XXXX add flash parts, rtc, ??
+ #interrupt-cells = <1>;
+ device_type = "pci";
+ compatible = "mpc10x-pci";
+- reg = <fec00000 400000>;
+- ranges = <01000000 0 0 fe000000 0 00c00000
+- 02000000 0 80000000 80000000 0 70000000>;
+- bus-range = <0 ff>;
+- clock-frequency = <7f28155>;
++ reg = <0xfec00000 0x400000>;
++ ranges = <0x1000000 0x0 0x0 0xfe000000 0x0 0xc00000
++ 0x2000000 0x0 0x80000000 0x80000000 0x0 0x70000000>;
++ bus-range = <0 255>;
++ clock-frequency = <133333333>;
+ interrupt-parent = <&mpic>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 11 - IRQ0 ETH */
+- 5800 0 0 1 &mpic 0 1
+- 5800 0 0 2 &mpic 1 1
+- 5800 0 0 3 &mpic 2 1
+- 5800 0 0 4 &mpic 3 1
++ 0x5800 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x5800 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x5800 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x5800 0x0 0x0 0x4 &mpic 0x3 0x1
+ /* IDSEL 12 - IRQ1 IDE0 */
+- 6000 0 0 1 &mpic 1 1
+- 6000 0 0 2 &mpic 2 1
+- 6000 0 0 3 &mpic 3 1
+- 6000 0 0 4 &mpic 0 1
++ 0x6000 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0x6000 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0x6000 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x6000 0x0 0x0 0x4 &mpic 0x0 0x1
+ /* IDSEL 14 - IRQ3 USB2.0 */
+- 7000 0 0 1 &mpic 3 1
+- 7000 0 0 2 &mpic 3 1
+- 7000 0 0 3 &mpic 3 1
+- 7000 0 0 4 &mpic 3 1
++ 0x7000 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x7000 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x7000 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x7000 0x0 0x0 0x4 &mpic 0x3 0x1
+ >;
+ };
};
-diff --git a/arch/powerpc/boot/dts/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
+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
*
-- * Copyright 2006 Freescale Semiconductor Inc.
-+ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+ * 2006 (c) G. Liakhovetski <g.liakhovetski at gmx.de>
++ * 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 +9,7 @@
- * option) any later version.
+ * 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 = "MPC8560ADS";
-@@ -32,74 +33,74 @@
+ model = "KuroboxHG";
+ compatible = "linkstation";
+@@ -35,19 +38,19 @@ XXXX add flash parts, rtc, ??
- PowerPC,8560 at 0 {
+ PowerPC,603e { /* Really 8241 */
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>;
+- clock-frequency = <fdad680>; /* Fixed by bootloader */
+- timebase-frequency = <1F04000>; /* Fixed by bootloader */
+ 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>;
++ 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 10000000>;
-+ reg = <0x0 0x10000000>;
+- reg = <00000000 08000000>;
++ reg = <0x0 0x8000000>;
};
- soc8560 at e0000000 {
- #address-cells = <1>;
- #size-cells = <1>;
+ 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";
-- ranges = <0 e0000000 00100000>;
-- reg = <e0000000 00000200>;
-- bus-frequency = <13ab6680>;
-+ ranges = <0x0 0xe0000000 0x100000>;
-+ reg = <0xe0000000 0x200>;
-+ bus-frequency = <330000000>;
-
- memory-controller at 2000 {
- compatible = "fsl,8540-memory-controller";
-- reg = <2000 1000>;
-+ reg = <0x2000 0x1000>;
- interrupt-parent = <&mpic>;
-- interrupts = <12 2>;
-+ interrupts = <18 2>;
- };
-
- l2-cache-controller at 20000 {
- compatible = "fsl,8540-l2-cache-controller";
-- reg = <20000 1000>;
-- cache-line-size = <20>; // 32 bytes
-- cache-size = <40000>; // L2, 256K
-+ reg = <0x20000 0x1000>;
-+ cache-line-size = <32>; // 32 bytes
-+ cache-size = <0x40000>; // L2, 256K
- interrupt-parent = <&mpic>;
-- interrupts = <10 2>;
-+ interrupts = <16 2>;
- };
+ 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 */
- mdio at 24520 {
+ i2c at 80003000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,gianfar-mdio";
-- reg = <24520 20>;
-+ reg = <0x24520 0x20>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+- reg = <80003000 1000>;
++ reg = <0x80003000 0x1000>;
+ interrupts = <5 2>;
+ interrupt-parent = <&mpic>;
- phy0: ethernet-phy at 0 {
- interrupt-parent = <&mpic>;
- interrupts = <5 1>;
-- reg = <0>;
-+ reg = <0x0>;
- device_type = "ethernet-phy";
- };
- phy1: ethernet-phy at 1 {
- interrupt-parent = <&mpic>;
- interrupts = <5 1>;
-- reg = <1>;
-+ reg = <0x1>;
- device_type = "ethernet-phy";
- };
- phy2: ethernet-phy at 2 {
- interrupt-parent = <&mpic>;
- interrupts = <7 1>;
-- reg = <2>;
-+ reg = <0x2>;
- device_type = "ethernet-phy";
- };
- phy3: ethernet-phy at 3 {
- interrupt-parent = <&mpic>;
- interrupts = <7 1>;
-- reg = <3>;
-+ reg = <0x3>;
- device_type = "ethernet-phy";
+ rtc at 32 {
+ device_type = "rtc";
+ compatible = "ricoh,rs5c372a";
+- reg = <32>;
++ reg = <0x32>;
};
};
-@@ -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>;
+
+@@ -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>;
- 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>;
+@@ -94,10 +97,10 @@ XXXX add flash parts, rtc, ??
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <80004600 8>;
+- clock-frequency = <7c044a8>;
+- current-speed = <e100>;
+- interrupts = <a 0>;
++ reg = <0x80004600 0x8>;
++ clock-frequency = <130041000>;
++ current-speed = <57600>;
++ interrupts = <10 0>;
interrupt-parent = <&mpic>;
- phy-handle = <&phy1>;
};
-@@ -132,7 +133,7 @@
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <2>;
-- reg = <40000 40000>;
-+ reg = <0x40000 0x40000>;
+
+@@ -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>;
};
-@@ -140,17 +141,17 @@
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "fsl,mpc8560-cpm", "fsl,cpm2";
-- reg = <919c0 30>;
-+ reg = <0x919c0 0x30>;
- ranges;
+ pci0: pci at fec00000 {
+@@ -116,29 +119,29 @@ XXXX add flash parts, rtc, ??
+ #interrupt-cells = <1>;
+ device_type = "pci";
+ compatible = "mpc10x-pci";
+- reg = <fec00000 400000>;
+- ranges = <01000000 0 0 fe000000 0 00c00000
+- 02000000 0 80000000 80000000 0 70000000>;
+- bus-range = <0 ff>;
+- clock-frequency = <7f28155>;
++ reg = <0xfec00000 0x400000>;
++ ranges = <0x1000000 0x0 0x0 0xfe000000 0x0 0xc00000
++ 0x2000000 0x0 0x80000000 0x80000000 0x0 0x70000000>;
++ bus-range = <0 255>;
++ clock-frequency = <133333333>;
+ interrupt-parent = <&mpic>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 11 - IRQ0 ETH */
+- 5800 0 0 1 &mpic 0 1
+- 5800 0 0 2 &mpic 1 1
+- 5800 0 0 3 &mpic 2 1
+- 5800 0 0 4 &mpic 3 1
++ 0x5800 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x5800 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x5800 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x5800 0x0 0x0 0x4 &mpic 0x3 0x1
+ /* IDSEL 12 - IRQ1 IDE0 */
+- 6000 0 0 1 &mpic 1 1
+- 6000 0 0 2 &mpic 2 1
+- 6000 0 0 3 &mpic 3 1
+- 6000 0 0 4 &mpic 0 1
++ 0x6000 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0x6000 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0x6000 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x6000 0x0 0x0 0x4 &mpic 0x0 0x1
+ /* IDSEL 14 - IRQ3 USB2.0 */
+- 7000 0 0 1 &mpic 3 1
+- 7000 0 0 2 &mpic 3 1
+- 7000 0 0 3 &mpic 3 1
+- 7000 0 0 4 &mpic 3 1
++ 0x7000 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x7000 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x7000 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x7000 0x0 0x0 0x4 &mpic 0x3 0x1
+ >;
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts
+index 09b4e16..2cf9a87 100644
+--- a/arch/powerpc/boot/dts/lite5200.dts
++++ b/arch/powerpc/boot/dts/lite5200.dts
+@@ -10,6 +10,8 @@
+ * option) any later version.
+ */
- muram at 80000 {
- #address-cells = <1>;
- #size-cells = <1>;
-- ranges = <0 80000 10000>;
-+ ranges = <0x0 0x80000 0x10000>;
++/dts-v1/;
++
+ / {
+ model = "fsl,lite5200";
+ compatible = "fsl,lite5200";
+@@ -23,10 +25,10 @@
+ PowerPC,5200 at 0 {
+ device_type = "cpu";
+ reg = <0>;
+- d-cache-line-size = <20>;
+- i-cache-line-size = <20>;
+- d-cache-size = <4000>; // L1, 16K
+- i-cache-size = <4000>; // L1, 16K
++ d-cache-line-size = <32>;
++ i-cache-line-size = <32>;
++ d-cache-size = <0x4000>; // L1, 16K
++ i-cache-size = <0x4000>; // L1, 16K
+ timebase-frequency = <0>; // from bootloader
+ bus-frequency = <0>; // from bootloader
+ clock-frequency = <0>; // from bootloader
+@@ -35,21 +37,21 @@
- data at 0 {
- compatible = "fsl,cpm-muram-data";
-- reg = <0 4000 9000 2000>;
-+ reg = <0x0 0x4000 0x9000 0x2000>;
- };
- };
+ memory {
+ device_type = "memory";
+- reg = <00000000 04000000>; // 64MB
++ reg = <0x00000000 0x04000000>; // 64MB
+ };
-@@ -158,17 +159,17 @@
- compatible = "fsl,mpc8560-brg",
- "fsl,cpm2-brg",
- "fsl,cpm-brg";
-- reg = <919f0 10 915f0 10>;
-- clock-frequency = <d#165000000>;
-+ reg = <0x919f0 0x10 0x915f0 0x10>;
-+ clock-frequency = <165000000>;
- };
+ soc5200 at f0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc5200-immr";
+- ranges = <0 f0000000 0000c000>;
+- reg = <f0000000 00000100>;
++ ranges = <0 0xf0000000 0x0000c000>;
++ reg = <0xf0000000 0x00000100>;
+ bus-frequency = <0>; // from bootloader
+ system-frequency = <0>; // from bootloader
+
+ cdm at 200 {
+ compatible = "fsl,mpc5200-cdm";
+- reg = <200 38>;
++ reg = <0x200 0x38>;
+ };
- cpmpic: pic at 90c00 {
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <2>;
-- interrupts = <2e 2>;
-+ interrupts = <46 2>;
- interrupt-parent = <&mpic>;
-- reg = <90c00 80>;
-+ reg = <0x90c00 0x80>;
- compatible = "fsl,mpc8560-cpm-pic", "fsl,cpm2-pic";
- };
+ mpc5200_pic: interrupt-controller at 500 {
+@@ -58,13 +60,13 @@
+ #interrupt-cells = <3>;
+ device_type = "interrupt-controller";
+ compatible = "fsl,mpc5200-pic";
+- reg = <500 80>;
++ reg = <0x500 0x80>;
+ };
-@@ -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>;
- };
+ timer at 600 { // General Purpose Timer
+ compatible = "fsl,mpc5200-gpt";
+ cell-index = <0>;
+- reg = <600 10>;
++ reg = <0x600 0x10>;
+ interrupts = <1 9 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ fsl,has-wdt;
+@@ -73,63 +75,63 @@
+ timer at 610 { // General Purpose Timer
+ compatible = "fsl,mpc5200-gpt";
+ cell-index = <1>;
+- reg = <610 10>;
+- interrupts = <1 a 0>;
++ reg = <0x610 0x10>;
++ interrupts = <1 10 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
-@@ -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>;
- };
+ timer at 620 { // General Purpose Timer
+ compatible = "fsl,mpc5200-gpt";
+ cell-index = <2>;
+- reg = <620 10>;
+- interrupts = <1 b 0>;
++ reg = <0x620 0x10>;
++ interrupts = <1 11 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
-@@ -200,10 +201,10 @@
- device_type = "network";
- compatible = "fsl,mpc8560-fcc-enet",
- "fsl,cpm2-fcc-enet";
-- reg = <91320 20 88500 100 913b0 1>;
-+ reg = <0x91320 0x20 0x88500 0x100 0x913b0 0x1>;
- local-mac-address = [ 00 00 00 00 00 00 ];
-- fsl,cpm-command = <16200300>;
-- interrupts = <21 8>;
-+ fsl,cpm-command = <0x16200300>;
-+ interrupts = <33 8>;
- interrupt-parent = <&cpmpic>;
- phy-handle = <&phy2>;
- };
-@@ -212,10 +213,10 @@
- device_type = "network";
- compatible = "fsl,mpc8560-fcc-enet",
- "fsl,cpm2-fcc-enet";
-- reg = <91340 20 88600 100 913d0 1>;
-+ reg = <0x91340 0x20 0x88600 0x100 0x913d0 0x1>;
- local-mac-address = [ 00 00 00 00 00 00 ];
-- fsl,cpm-command = <1a400300>;
-- interrupts = <22 8>;
-+ fsl,cpm-command = <0x1a400300>;
-+ interrupts = <34 8>;
- interrupt-parent = <&cpmpic>;
- phy-handle = <&phy3>;
- };
-@@ -229,87 +230,87 @@
- #address-cells = <3>;
- compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci";
- device_type = "pci";
-- reg = <e0008000 1000>;
-- clock-frequency = <3f940aa>;
-- interrupt-map-mask = <f800 0 0 7>;
-+ reg = <0xe0008000 0x1000>;
-+ clock-frequency = <66666666>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
+ timer at 630 { // General Purpose Timer
+ compatible = "fsl,mpc5200-gpt";
+ cell-index = <3>;
+- reg = <630 10>;
+- interrupts = <1 c 0>;
++ reg = <0x630 0x10>;
++ interrupts = <1 12 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
- /* 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
+ timer at 640 { // General Purpose Timer
+ compatible = "fsl,mpc5200-gpt";
+ cell-index = <4>;
+- reg = <640 10>;
+- interrupts = <1 d 0>;
++ reg = <0x640 0x10>;
++ interrupts = <1 13 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
- /* 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
+ timer at 650 { // General Purpose Timer
+ compatible = "fsl,mpc5200-gpt";
+ cell-index = <5>;
+- reg = <650 10>;
+- interrupts = <1 e 0>;
++ reg = <0x650 0x10>;
++ interrupts = <1 14 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
- /* 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
+ timer at 660 { // General Purpose Timer
+ compatible = "fsl,mpc5200-gpt";
+ cell-index = <6>;
+- reg = <660 10>;
+- interrupts = <1 f 0>;
++ reg = <0x660 0x10>;
++ interrupts = <1 15 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
- /* 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
+ timer at 670 { // General Purpose Timer
+ compatible = "fsl,mpc5200-gpt";
+ cell-index = <7>;
+- reg = <670 10>;
+- interrupts = <1 10 0>;
++ reg = <0x670 0x10>;
++ interrupts = <1 16 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
- /* 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
+ rtc at 800 { // Real time clock
+ compatible = "fsl,mpc5200-rtc";
+ device_type = "rtc";
+- reg = <800 100>;
++ reg = <0x800 0x100>;
+ interrupts = <1 5 0 1 6 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -137,43 +139,43 @@
+ can at 900 {
+ compatible = "fsl,mpc5200-mscan";
+ cell-index = <0>;
+- interrupts = <2 11 0>;
++ interrupts = <2 17 0>;
+ interrupt-parent = <&mpc5200_pic>;
+- reg = <900 80>;
++ reg = <0x900 0x80>;
+ };
- /* 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
+ can at 980 {
+ compatible = "fsl,mpc5200-mscan";
+ cell-index = <1>;
+- interrupts = <2 12 0>;
++ interrupts = <2 18 0>;
+ interrupt-parent = <&mpc5200_pic>;
+- reg = <980 80>;
++ reg = <0x980 0x80>;
+ };
- /* 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
+ gpio at b00 {
+ compatible = "fsl,mpc5200-gpio";
+- reg = <b00 40>;
++ reg = <0xb00 0x40>;
+ interrupts = <1 7 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
- /* 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
+ gpio at c00 {
+ compatible = "fsl,mpc5200-gpio-wkup";
+- reg = <c00 40>;
++ reg = <0xc00 0x40>;
+ interrupts = <1 8 0 0 3 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
- /* 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
+ spi at f00 {
+ compatible = "fsl,mpc5200-spi";
+- reg = <f00 20>;
+- interrupts = <2 d 0 2 e 0>;
++ reg = <0xf00 0x20>;
++ interrupts = <2 13 0 2 14 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
- /* 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
+ usb at 1000 {
+ compatible = "fsl,mpc5200-ohci","ohci-be";
+- reg = <1000 ff>;
++ reg = <0x1000 0xff>;
+ interrupts = <2 6 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -181,17 +183,17 @@
+ dma-controller at 1200 {
+ device_type = "dma-controller";
+ compatible = "fsl,mpc5200-bestcomm";
+- reg = <1200 80>;
++ reg = <0x1200 0x80>;
+ interrupts = <3 0 0 3 1 0 3 2 0 3 3 0
+ 3 4 0 3 5 0 3 6 0 3 7 0
+- 3 8 0 3 9 0 3 a 0 3 b 0
+- 3 c 0 3 d 0 3 e 0 3 f 0>;
++ 3 8 0 3 9 0 3 10 0 3 11 0
++ 3 12 0 3 13 0 3 14 0 3 15 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
- /* 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
+ xlb at 1f00 {
+ compatible = "fsl,mpc5200-xlb";
+- reg = <1f00 100>;
++ reg = <0x1f00 0x100>;
+ };
- /* 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>;
+ serial at 2000 { // PSC1
+@@ -199,7 +201,7 @@
+ compatible = "fsl,mpc5200-psc-uart";
+ port-number = <0>; // Logical port assignment
+ cell-index = <0>;
+- reg = <2000 100>;
++ reg = <0x2000 0x100>;
+ interrupts = <2 1 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -208,7 +210,7 @@
+ //ac97 at 2200 { // PSC2
+ // compatible = "fsl,mpc5200-psc-ac97";
+ // cell-index = <1>;
+- // reg = <2200 100>;
++ // reg = <0x2200 0x100>;
+ // interrupts = <2 2 0>;
+ // interrupt-parent = <&mpc5200_pic>;
+ //};
+@@ -217,7 +219,7 @@
+ //i2s at 2400 { // PSC3
+ // compatible = "fsl,mpc5200-psc-i2s";
+ // cell-index = <2>;
+- // reg = <2400 100>;
++ // reg = <0x2400 0x100>;
+ // interrupts = <2 3 0>;
+ // interrupt-parent = <&mpc5200_pic>;
+ //};
+@@ -227,8 +229,8 @@
+ // device_type = "serial";
+ // compatible = "fsl,mpc5200-psc-uart";
+ // cell-index = <3>;
+- // reg = <2600 100>;
+- // interrupts = <2 b 0>;
++ // reg = <0x2600 0x100>;
++ // interrupts = <2 11 0>;
+ // interrupt-parent = <&mpc5200_pic>;
+ //};
+
+@@ -237,8 +239,8 @@
+ // device_type = "serial";
+ // compatible = "fsl,mpc5200-psc-uart";
+ // cell-index = <4>;
+- // reg = <2800 100>;
+- // interrupts = <2 c 0>;
++ // reg = <0x2800 0x100>;
++ // interrupts = <2 12 0>;
+ // interrupt-parent = <&mpc5200_pic>;
+ //};
+
+@@ -246,7 +248,7 @@
+ //spi at 2c00 { // PSC6
+ // compatible = "fsl,mpc5200-psc-spi";
+ // cell-index = <5>;
+- // reg = <2c00 100>;
++ // reg = <0x2c00 0x100>;
+ // interrupts = <2 4 0>;
+ // interrupt-parent = <&mpc5200_pic>;
+ //};
+@@ -254,7 +256,7 @@
+ ethernet at 3000 {
+ device_type = "network";
+ compatible = "fsl,mpc5200-fec";
+- reg = <3000 800>;
++ reg = <0x3000 0x400>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <2 5 0>;
+ interrupt-parent = <&mpc5200_pic>;
+@@ -265,11 +267,11 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200-mdio";
+- reg = <3000 400>; // fec range, since we need to setup fec interrupts
++ reg = <0x3000 0x400>; // fec range, since we need to setup fec interrupts
+ interrupts = <2 5 0>; // these are for "mii command finished", not link changes & co.
+ interrupt-parent = <&mpc5200_pic>;
- interrupt-parent = <&mpic>;
-- interrupts = <18 2>;
-+ interrupts = <24 2>;
+- phy0:ethernet-phy at 1 {
++ phy0: ethernet-phy at 1 {
+ device_type = "ethernet-phy";
+ reg = <1>;
+ };
+@@ -278,7 +280,7 @@
+ ata at 3a00 {
+ device_type = "ata";
+ compatible = "fsl,mpc5200-ata";
+- reg = <3a00 100>;
++ reg = <0x3a00 0x100>;
+ interrupts = <2 7 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -288,8 +290,8 @@
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200-i2c","fsl-i2c";
+ cell-index = <0>;
+- reg = <3d00 40>;
+- interrupts = <2 f 0>;
++ reg = <0x3d00 0x40>;
++ interrupts = <2 15 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ fsl5200-clocking;
+ };
+@@ -299,14 +301,14 @@
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200-i2c","fsl-i2c";
+ cell-index = <1>;
+- reg = <3d40 40>;
+- interrupts = <2 10 0>;
++ reg = <0x3d40 0x40>;
++ interrupts = <2 16 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ fsl5200-clocking;
+ };
+ sram at 8000 {
+ compatible = "fsl,mpc5200-sram","sram";
+- reg = <8000 4000>;
++ reg = <0x8000 0x4000>;
+ };
+ };
+
+@@ -316,18 +318,18 @@
+ #address-cells = <3>;
+ device_type = "pci";
+ compatible = "fsl,mpc5200-pci";
+- reg = <f0000d00 100>;
+- interrupt-map-mask = <f800 0 0 7>;
+- interrupt-map = <c000 0 0 1 &mpc5200_pic 0 0 3
+- c000 0 0 2 &mpc5200_pic 0 0 3
+- c000 0 0 3 &mpc5200_pic 0 0 3
+- c000 0 0 4 &mpc5200_pic 0 0 3>;
++ reg = <0xf0000d00 0x100>;
++ interrupt-map-mask = <0xf800 0 0 7>;
++ interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3
++ 0xc000 0 0 2 &mpc5200_pic 0 0 3
++ 0xc000 0 0 3 &mpc5200_pic 0 0 3
++ 0xc000 0 0 4 &mpc5200_pic 0 0 3>;
+ clock-frequency = <0>; // From boot loader
+- interrupts = <2 8 0 2 9 0 2 a 0>;
++ interrupts = <2 8 0 2 9 0 2 10 0>;
+ interrupt-parent = <&mpc5200_pic>;
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>;
+- ranges = <42000000 0 80000000 80000000 0 20000000
+- 02000000 0 a0000000 a0000000 0 10000000
+- 01000000 0 00000000 b0000000 0 01000000>;
++ ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
++ 0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
++ 0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
};
};
-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 @@
+diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts
+index 2e9bc39..7bd5b9c 100644
+--- a/arch/powerpc/boot/dts/lite5200b.dts
++++ b/arch/powerpc/boot/dts/lite5200b.dts
+@@ -10,11 +10,7 @@
* option) any later version.
*/
--
-/*
--/memreserve/ 00000000 1000000;
--*/
+- * WARNING: Do not depend on this tree layout remaining static just yet.
+- * The MPC5200 device tree conventions are still in flux
+- * Keep an eye on the linuxppc-dev mailing list for more details
+- */
+/dts-v1/;
/ {
- model = "MPC8568EMDS";
-@@ -37,11 +34,11 @@
-
- PowerPC,8568 at 0 {
+ model = "fsl,lite5200b";
+@@ -29,10 +25,10 @@
+ PowerPC,5200 at 0 {
device_type = "cpu";
-- reg = <0>;
-- d-cache-line-size = <20>; // 32 bytes
-- i-cache-line-size = <20>; // 32 bytes
-- d-cache-size = <8000>; // L1, 32K
-- i-cache-size = <8000>; // L1, 32K
-+ reg = <0x0>;
-+ d-cache-line-size = <32>; // 32 bytes
-+ i-cache-line-size = <32>; // 32 bytes
-+ d-cache-size = <0x8000>; // L1, 32K
-+ i-cache-size = <0x8000>; // L1, 32K
- timebase-frequency = <0>;
- bus-frequency = <0>;
- clock-frequency = <0>;
-@@ -50,36 +47,36 @@
+ reg = <0>;
+- d-cache-line-size = <20>;
+- i-cache-line-size = <20>;
+- d-cache-size = <4000>; // L1, 16K
+- i-cache-size = <4000>; // L1, 16K
++ d-cache-line-size = <32>;
++ i-cache-line-size = <32>;
++ d-cache-size = <0x4000>; // L1, 16K
++ i-cache-size = <0x4000>; // L1, 16K
+ timebase-frequency = <0>; // from bootloader
+ bus-frequency = <0>; // from bootloader
+ clock-frequency = <0>; // from bootloader
+@@ -41,21 +37,21 @@
memory {
device_type = "memory";
-- reg = <00000000 10000000>;
-+ reg = <0x0 0x10000000>;
- };
-
- bcsr at f8000000 {
- device_type = "board-control";
-- reg = <f8000000 8000>;
-+ reg = <0xf8000000 0x8000>;
+- reg = <00000000 10000000>; // 256MB
++ reg = <0x00000000 0x10000000>; // 256MB
};
- soc8568 at e0000000 {
+ soc5200 at f0000000 {
#address-cells = <1>;
#size-cells = <1>;
- device_type = "soc";
-- ranges = <0 e0000000 00100000>;
-- reg = <e0000000 00001000>;
-+ ranges = <0x0 0xe0000000 0x100000>;
-+ reg = <0xe0000000 0x1000>;
- bus-frequency = <0>;
-
- memory-controller at 2000 {
- compatible = "fsl,8568-memory-controller";
-- reg = <2000 1000>;
-+ reg = <0x2000 0x1000>;
- interrupt-parent = <&mpic>;
-- interrupts = <12 2>;
-+ interrupts = <18 2>;
+ compatible = "fsl,mpc5200b-immr";
+- ranges = <0 f0000000 0000c000>;
+- reg = <f0000000 00000100>;
++ ranges = <0 0xf0000000 0x0000c000>;
++ reg = <0xf0000000 0x00000100>;
+ bus-frequency = <0>; // from bootloader
+ system-frequency = <0>; // from bootloader
+
+ cdm at 200 {
+ compatible = "fsl,mpc5200b-cdm","fsl,mpc5200-cdm";
+- reg = <200 38>;
++ reg = <0x200 0x38>;
};
- l2-cache-controller at 20000 {
- compatible = "fsl,8568-l2-cache-controller";
-- reg = <20000 1000>;
-- cache-line-size = <20>; // 32 bytes
-- cache-size = <80000>; // L2, 512K
-+ reg = <0x20000 0x1000>;
-+ cache-line-size = <32>; // 32 bytes
-+ cache-size = <0x80000>; // L2, 512K
- interrupt-parent = <&mpic>;
-- interrupts = <10 2>;
-+ interrupts = <16 2>;
+ mpc5200_pic: interrupt-controller at 500 {
+@@ -64,13 +60,13 @@
+ #interrupt-cells = <3>;
+ device_type = "interrupt-controller";
+ compatible = "fsl,mpc5200b-pic","fsl,mpc5200-pic";
+- reg = <500 80>;
++ reg = <0x500 0x80>;
};
- i2c at 3000 {
-@@ -87,14 +84,14 @@
- #size-cells = <0>;
+ timer at 600 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
cell-index = <0>;
- compatible = "fsl-i2c";
-- reg = <3000 100>;
-- interrupts = <2b 2>;
-+ reg = <0x3000 0x100>;
-+ interrupts = <43 2>;
- interrupt-parent = <&mpic>;
- dfsrr;
+- reg = <600 10>;
++ reg = <0x600 0x10>;
+ interrupts = <1 9 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ fsl,has-wdt;
+@@ -79,63 +75,63 @@
+ timer at 610 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+ cell-index = <1>;
+- reg = <610 10>;
+- interrupts = <1 a 0>;
++ reg = <0x610 0x10>;
++ interrupts = <1 10 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
- rtc at 68 {
- compatible = "dallas,ds1374";
-- reg = <68>;
-+ reg = <0x68>;
- };
+ timer at 620 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+ cell-index = <2>;
+- reg = <620 10>;
+- interrupts = <1 b 0>;
++ reg = <0x620 0x10>;
++ interrupts = <1 11 0>;
+ interrupt-parent = <&mpc5200_pic>;
};
-@@ -103,8 +100,8 @@
- #size-cells = <0>;
+ timer at 630 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+ cell-index = <3>;
+- reg = <630 10>;
+- interrupts = <1 c 0>;
++ reg = <0x630 0x10>;
++ interrupts = <1 12 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ timer at 640 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+ cell-index = <4>;
+- reg = <640 10>;
+- interrupts = <1 d 0>;
++ reg = <0x640 0x10>;
++ interrupts = <1 13 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ timer at 650 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+ cell-index = <5>;
+- reg = <650 10>;
+- interrupts = <1 e 0>;
++ reg = <0x650 0x10>;
++ interrupts = <1 14 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ timer at 660 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+ cell-index = <6>;
+- reg = <660 10>;
+- interrupts = <1 f 0>;
++ reg = <0x660 0x10>;
++ interrupts = <1 15 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ timer at 670 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+ cell-index = <7>;
+- reg = <670 10>;
+- interrupts = <1 10 0>;
++ reg = <0x670 0x10>;
++ interrupts = <1 16 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ rtc at 800 { // Real time clock
+ compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
+ device_type = "rtc";
+- reg = <800 100>;
++ reg = <0x800 0x100>;
+ interrupts = <1 5 0 1 6 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -143,43 +139,43 @@
+ can at 900 {
+ compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
+ cell-index = <0>;
+- interrupts = <2 11 0>;
++ interrupts = <2 17 0>;
+ interrupt-parent = <&mpc5200_pic>;
+- reg = <900 80>;
++ reg = <0x900 0x80>;
+ };
+
+ can at 980 {
+ compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
cell-index = <1>;
- compatible = "fsl-i2c";
-- reg = <3100 100>;
-- interrupts = <2b 2>;
-+ reg = <0x3100 0x100>;
-+ interrupts = <43 2>;
- interrupt-parent = <&mpic>;
- dfsrr;
+- interrupts = <2 12 0>;
++ interrupts = <2 18 0>;
+ interrupt-parent = <&mpc5200_pic>;
+- reg = <980 80>;
++ reg = <0x980 0x80>;
};
-@@ -113,30 +110,30 @@
+
+ gpio at b00 {
+ compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
+- reg = <b00 40>;
++ reg = <0xb00 0x40>;
+ interrupts = <1 7 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ gpio at c00 {
+ compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
+- reg = <c00 40>;
++ reg = <0xc00 0x40>;
+ interrupts = <1 8 0 0 3 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ spi at f00 {
+ compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
+- reg = <f00 20>;
+- interrupts = <2 d 0 2 e 0>;
++ reg = <0xf00 0x20>;
++ interrupts = <2 13 0 2 14 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ usb at 1000 {
+ compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
+- reg = <1000 ff>;
++ reg = <0x1000 0xff>;
+ interrupts = <2 6 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -187,17 +183,17 @@
+ dma-controller at 1200 {
+ device_type = "dma-controller";
+ compatible = "fsl,mpc5200b-bestcomm","fsl,mpc5200-bestcomm";
+- reg = <1200 80>;
++ reg = <0x1200 0x80>;
+ interrupts = <3 0 0 3 1 0 3 2 0 3 3 0
+ 3 4 0 3 5 0 3 6 0 3 7 0
+- 3 8 0 3 9 0 3 a 0 3 b 0
+- 3 c 0 3 d 0 3 e 0 3 f 0>;
++ 3 8 0 3 9 0 3 10 0 3 11 0
++ 3 12 0 3 13 0 3 14 0 3 15 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ xlb at 1f00 {
+ compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
+- reg = <1f00 100>;
++ reg = <0x1f00 0x100>;
+ };
+
+ serial at 2000 { // PSC1
+@@ -205,7 +201,7 @@
+ compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+ port-number = <0>; // Logical port assignment
+ cell-index = <0>;
+- reg = <2000 100>;
++ reg = <0x2000 0x100>;
+ interrupts = <2 1 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -214,7 +210,7 @@
+ //ac97 at 2200 { // PSC2
+ // compatible = "fsl,mpc5200b-psc-ac97","fsl,mpc5200-psc-ac97";
+ // cell-index = <1>;
+- // reg = <2200 100>;
++ // reg = <0x2200 0x100>;
+ // interrupts = <2 2 0>;
+ // interrupt-parent = <&mpc5200_pic>;
+ //};
+@@ -223,7 +219,7 @@
+ //i2s at 2400 { // PSC3
+ // compatible = "fsl,mpc5200b-psc-i2s"; //not 5200 compatible
+ // cell-index = <2>;
+- // reg = <2400 100>;
++ // reg = <0x2400 0x100>;
+ // interrupts = <2 3 0>;
+ // interrupt-parent = <&mpc5200_pic>;
+ //};
+@@ -233,8 +229,8 @@
+ // device_type = "serial";
+ // compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+ // cell-index = <3>;
+- // reg = <2600 100>;
+- // interrupts = <2 b 0>;
++ // reg = <0x2600 0x100>;
++ // interrupts = <2 11 0>;
+ // interrupt-parent = <&mpc5200_pic>;
+ //};
+
+@@ -243,8 +239,8 @@
+ // device_type = "serial";
+ // compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+ // cell-index = <4>;
+- // reg = <2800 100>;
+- // interrupts = <2 c 0>;
++ // reg = <0x2800 0x100>;
++ // interrupts = <2 12 0>;
+ // interrupt-parent = <&mpc5200_pic>;
+ //};
+
+@@ -252,7 +248,7 @@
+ //spi at 2c00 { // PSC6
+ // compatible = "fsl,mpc5200b-psc-spi","fsl,mpc5200-psc-spi";
+ // cell-index = <5>;
+- // reg = <2c00 100>;
++ // reg = <0x2c00 0x100>;
+ // interrupts = <2 4 0>;
+ // interrupt-parent = <&mpc5200_pic>;
+ //};
+@@ -260,7 +256,7 @@
+ ethernet at 3000 {
+ device_type = "network";
+ compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
+- reg = <3000 400>;
++ reg = <0x3000 0x400>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <2 5 0>;
+ interrupt-parent = <&mpc5200_pic>;
+@@ -271,11 +267,11 @@
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,gianfar-mdio";
-- reg = <24520 20>;
-+ reg = <0x24520 0x20>;
+ compatible = "fsl,mpc5200b-mdio", "fsl,mpc5200-mdio";
+- reg = <3000 400>; // fec range, since we need to setup fec interrupts
++ reg = <0x3000 0x400>; // fec range, since we need to setup fec interrupts
+ interrupts = <2 5 0>; // these are for "mii command finished", not link changes & co.
+ interrupt-parent = <&mpc5200_pic>;
- phy0: ethernet-phy at 7 {
- interrupt-parent = <&mpic>;
- interrupts = <1 1>;
-- reg = <7>;
-+ reg = <0x7>;
- device_type = "ethernet-phy";
- };
- phy1: ethernet-phy at 1 {
- interrupt-parent = <&mpic>;
- interrupts = <2 1>;
-- reg = <1>;
-+ reg = <0x1>;
- device_type = "ethernet-phy";
- };
- phy2: ethernet-phy at 2 {
- interrupt-parent = <&mpic>;
- interrupts = <1 1>;
-- reg = <2>;
-+ reg = <0x2>;
- device_type = "ethernet-phy";
- };
- phy3: ethernet-phy at 3 {
- interrupt-parent = <&mpic>;
- interrupts = <2 1>;
-- reg = <3>;
-+ reg = <0x3>;
+- phy0:ethernet-phy at 0 {
++ phy0: ethernet-phy at 0 {
device_type = "ethernet-phy";
+ reg = <0>;
};
+@@ -284,7 +280,7 @@
+ ata at 3a00 {
+ device_type = "ata";
+ compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
+- reg = <3a00 100>;
++ reg = <0x3a00 0x100>;
+ interrupts = <2 7 0>;
+ interrupt-parent = <&mpc5200_pic>;
};
-@@ -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>;
+@@ -294,8 +290,8 @@
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
+ cell-index = <0>;
+- reg = <3d00 40>;
+- interrupts = <2 f 0>;
++ reg = <0x3d00 0x40>;
++ interrupts = <2 15 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ fsl5200-clocking;
};
-@@ -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>;
+@@ -305,14 +301,14 @@
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
+ cell-index = <1>;
+- reg = <3d40 40>;
+- interrupts = <2 10 0>;
++ reg = <0x3d40 0x40>;
++ interrupts = <2 16 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ fsl5200-clocking;
};
-@@ -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>;
+ sram at 8000 {
+ compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram","sram";
+- reg = <8000 4000>;
++ reg = <0x8000 0x4000>;
};
+ };
- global-utilities at e0000 { //global utilities block
- compatible = "fsl,mpc8548-guts";
-- reg = <e0000 1000>;
-+ reg = <0xe0000 0x1000>;
- fsl,has-rstcr;
+@@ -322,23 +318,23 @@
+ #address-cells = <3>;
+ device_type = "pci";
+ compatible = "fsl,mpc5200b-pci","fsl,mpc5200-pci";
+- reg = <f0000d00 100>;
+- interrupt-map-mask = <f800 0 0 7>;
+- interrupt-map = <c000 0 0 1 &mpc5200_pic 0 0 3 // 1st slot
+- c000 0 0 2 &mpc5200_pic 1 1 3
+- c000 0 0 3 &mpc5200_pic 1 2 3
+- c000 0 0 4 &mpc5200_pic 1 3 3
+-
+- c800 0 0 1 &mpc5200_pic 1 1 3 // 2nd slot
+- c800 0 0 2 &mpc5200_pic 1 2 3
+- c800 0 0 3 &mpc5200_pic 1 3 3
+- c800 0 0 4 &mpc5200_pic 0 0 3>;
++ reg = <0xf0000d00 0x100>;
++ interrupt-map-mask = <0xf800 0 0 7>;
++ interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3 // 1st slot
++ 0xc000 0 0 2 &mpc5200_pic 1 1 3
++ 0xc000 0 0 3 &mpc5200_pic 1 2 3
++ 0xc000 0 0 4 &mpc5200_pic 1 3 3
++
++ 0xc800 0 0 1 &mpc5200_pic 1 1 3 // 2nd slot
++ 0xc800 0 0 2 &mpc5200_pic 1 2 3
++ 0xc800 0 0 3 &mpc5200_pic 1 3 3
++ 0xc800 0 0 4 &mpc5200_pic 0 0 3>;
+ clock-frequency = <0>; // From boot loader
+- interrupts = <2 8 0 2 9 0 2 a 0>;
++ interrupts = <2 8 0 2 9 0 2 10 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ bus-range = <0 0>;
+- ranges = <42000000 0 80000000 80000000 0 20000000
+- 02000000 0 a0000000 a0000000 0 10000000
+- 01000000 0 00000000 b0000000 0 01000000>;
++ ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
++ 0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
++ 0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
+ };
+ };
+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/motionpro.dts b/arch/powerpc/boot/dts/motionpro.dts
+index 2b0dde0..9e3c921 100644
+--- a/arch/powerpc/boot/dts/motionpro.dts
++++ b/arch/powerpc/boot/dts/motionpro.dts
+@@ -10,6 +10,8 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
++
+ / {
+ model = "promess,motionpro";
+ compatible = "promess,motionpro";
+@@ -23,10 +25,10 @@
+ PowerPC,5200 at 0 {
+ device_type = "cpu";
+ reg = <0>;
+- d-cache-line-size = <20>;
+- i-cache-line-size = <20>;
+- d-cache-size = <4000>; // L1, 16K
+- i-cache-size = <4000>; // L1, 16K
++ d-cache-line-size = <32>;
++ i-cache-line-size = <32>;
++ d-cache-size = <0x4000>; // L1, 16K
++ i-cache-size = <0x4000>; // L1, 16K
+ timebase-frequency = <0>; // from bootloader
+ bus-frequency = <0>; // from bootloader
+ clock-frequency = <0>; // from bootloader
+@@ -35,21 +37,21 @@
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 04000000>; // 64MB
++ reg = <0x00000000 0x04000000>; // 64MB
+ };
+
+ soc5200 at f0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc5200b-immr";
+- ranges = <0 f0000000 0000c000>;
+- reg = <f0000000 00000100>;
++ ranges = <0 0xf0000000 0x0000c000>;
++ reg = <0xf0000000 0x00000100>;
+ bus-frequency = <0>; // from bootloader
+ system-frequency = <0>; // from bootloader
+
+ cdm at 200 {
+ compatible = "fsl,mpc5200b-cdm","fsl,mpc5200-cdm";
+- reg = <200 38>;
++ reg = <0x200 0x38>;
};
-@@ -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>;
+ mpc5200_pic: interrupt-controller at 500 {
+@@ -57,12 +59,12 @@
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ compatible = "fsl,mpc5200b-pic","fsl,mpc5200-pic";
+- reg = <500 80>;
++ reg = <0x500 0x80>;
};
-@@ -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>;
+ timer at 600 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+- reg = <600 10>;
++ reg = <0x600 0x10>;
+ interrupts = <1 9 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ fsl,has-wdt;
+@@ -70,118 +72,118 @@
+
+ timer at 610 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+- reg = <610 10>;
+- interrupts = <1 a 0>;
++ reg = <0x610 0x10>;
++ interrupts = <1 10 0>;
+ interrupt-parent = <&mpc5200_pic>;
};
- mpic: pic at 40000 {
-@@ -209,73 +206,73 @@
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <2>;
-- reg = <40000 40000>;
-+ reg = <0x40000 0x40000>;
- compatible = "chrp,open-pic";
- device_type = "open-pic";
- big-endian;
+ timer at 620 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+- reg = <620 10>;
+- interrupts = <1 b 0>;
++ reg = <0x620 0x10>;
++ interrupts = <1 11 0>;
+ interrupt-parent = <&mpc5200_pic>;
};
- par_io at e0100 {
-- reg = <e0100 100>;
-+ reg = <0xe0100 0x100>;
- device_type = "par_io";
- num-ports = <7>;
+ timer at 630 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+- reg = <630 10>;
+- interrupts = <1 c 0>;
++ reg = <0x630 0x10>;
++ interrupts = <1 12 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
- pio1: ucc_pin at 01 {
- pio-map = <
- /* port pin dir open_drain assignment has_irq */
-- 4 0a 1 0 2 0 /* TxD0 */
-- 4 09 1 0 2 0 /* TxD1 */
-- 4 08 1 0 2 0 /* TxD2 */
-- 4 07 1 0 2 0 /* TxD3 */
-- 4 17 1 0 2 0 /* TxD4 */
-- 4 16 1 0 2 0 /* TxD5 */
-- 4 15 1 0 2 0 /* TxD6 */
-- 4 14 1 0 2 0 /* TxD7 */
-- 4 0f 2 0 2 0 /* RxD0 */
-- 4 0e 2 0 2 0 /* RxD1 */
-- 4 0d 2 0 2 0 /* RxD2 */
-- 4 0c 2 0 2 0 /* RxD3 */
-- 4 1d 2 0 2 0 /* RxD4 */
-- 4 1c 2 0 2 0 /* RxD5 */
-- 4 1b 2 0 2 0 /* RxD6 */
-- 4 1a 2 0 2 0 /* RxD7 */
-- 4 0b 1 0 2 0 /* TX_EN */
-- 4 18 1 0 2 0 /* TX_ER */
-- 4 10 2 0 2 0 /* RX_DV */
-- 4 1e 2 0 2 0 /* RX_ER */
-- 4 11 2 0 2 0 /* RX_CLK */
-- 4 13 1 0 2 0 /* GTX_CLK */
-- 1 1f 2 0 3 0>; /* GTX125 */
-+ 0x4 0xa 0x1 0x0 0x2 0x0 /* TxD0 */
-+ 0x4 0x9 0x1 0x0 0x2 0x0 /* TxD1 */
-+ 0x4 0x8 0x1 0x0 0x2 0x0 /* TxD2 */
-+ 0x4 0x7 0x1 0x0 0x2 0x0 /* TxD3 */
-+ 0x4 0x17 0x1 0x0 0x2 0x0 /* TxD4 */
-+ 0x4 0x16 0x1 0x0 0x2 0x0 /* TxD5 */
-+ 0x4 0x15 0x1 0x0 0x2 0x0 /* TxD6 */
-+ 0x4 0x14 0x1 0x0 0x2 0x0 /* TxD7 */
-+ 0x4 0xf 0x2 0x0 0x2 0x0 /* RxD0 */
-+ 0x4 0xe 0x2 0x0 0x2 0x0 /* RxD1 */
-+ 0x4 0xd 0x2 0x0 0x2 0x0 /* RxD2 */
-+ 0x4 0xc 0x2 0x0 0x2 0x0 /* RxD3 */
-+ 0x4 0x1d 0x2 0x0 0x2 0x0 /* RxD4 */
-+ 0x4 0x1c 0x2 0x0 0x2 0x0 /* RxD5 */
-+ 0x4 0x1b 0x2 0x0 0x2 0x0 /* RxD6 */
-+ 0x4 0x1a 0x2 0x0 0x2 0x0 /* RxD7 */
-+ 0x4 0xb 0x1 0x0 0x2 0x0 /* TX_EN */
-+ 0x4 0x18 0x1 0x0 0x2 0x0 /* TX_ER */
-+ 0x4 0x10 0x2 0x0 0x2 0x0 /* RX_DV */
-+ 0x4 0x1e 0x2 0x0 0x2 0x0 /* RX_ER */
-+ 0x4 0x11 0x2 0x0 0x2 0x0 /* RX_CLK */
-+ 0x4 0x13 0x1 0x0 0x2 0x0 /* GTX_CLK */
-+ 0x1 0x1f 0x2 0x0 0x3 0x0>; /* GTX125 */
+ timer at 640 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+- reg = <640 10>;
+- interrupts = <1 d 0>;
++ reg = <0x640 0x10>;
++ interrupts = <1 13 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ timer at 650 { // General Purpose Timer
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+- reg = <650 10>;
+- interrupts = <1 e 0>;
++ reg = <0x650 0x10>;
++ interrupts = <1 14 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ motionpro-led at 660 { // Motion-PRO status LED
+ compatible = "promess,motionpro-led";
+ label = "motionpro-statusled";
+- reg = <660 10>;
+- interrupts = <1 f 0>;
++ reg = <0x660 0x10>;
++ interrupts = <1 15 0>;
+ interrupt-parent = <&mpc5200_pic>;
+- blink-delay = <64>; // 100 msec
++ blink-delay = <100>; // 100 msec
+ };
+
+ motionpro-led at 670 { // Motion-PRO ready LED
+ compatible = "promess,motionpro-led";
+ label = "motionpro-readyled";
+- reg = <670 10>;
+- interrupts = <1 10 0>;
++ reg = <0x670 0x10>;
++ interrupts = <1 16 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ rtc at 800 { // Real time clock
+ compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
+- reg = <800 100>;
++ reg = <0x800 0x100>;
+ interrupts = <1 5 0 1 6 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+- mscan at 980 {
++ can at 980 {
+ compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
+- interrupts = <2 12 0>;
++ interrupts = <2 18 0>;
+ interrupt-parent = <&mpc5200_pic>;
+- reg = <980 80>;
++ reg = <0x980 0x80>;
+ };
+
+ gpio at b00 {
+ compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
+- reg = <b00 40>;
++ reg = <0xb00 0x40>;
+ interrupts = <1 7 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ gpio at c00 {
+ compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
+- reg = <c00 40>;
++ reg = <0xc00 0x40>;
+ interrupts = <1 8 0 0 3 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ spi at f00 {
+ compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
+- reg = <f00 20>;
+- interrupts = <2 d 0 2 e 0>;
++ reg = <0xf00 0x20>;
++ interrupts = <2 13 0 2 14 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ usb at 1000 {
+ compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
+- reg = <1000 ff>;
++ reg = <0x1000 0xff>;
+ interrupts = <2 6 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ dma-controller at 1200 {
+ compatible = "fsl,mpc5200b-bestcomm","fsl,mpc5200-bestcomm";
+- reg = <1200 80>;
++ reg = <0x1200 0x80>;
+ interrupts = <3 0 0 3 1 0 3 2 0 3 3 0
+ 3 4 0 3 5 0 3 6 0 3 7 0
+- 3 8 0 3 9 0 3 a 0 3 b 0
+- 3 c 0 3 d 0 3 e 0 3 f 0>;
++ 3 8 0 3 9 0 3 10 0 3 11 0
++ 3 12 0 3 13 0 3 14 0 3 15 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ xlb at 1f00 {
+ compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
+- reg = <1f00 100>;
++ reg = <0x1f00 0x100>;
+ };
+
+ serial at 2000 { // PSC1
+ device_type = "serial";
+ compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+ port-number = <0>; // Logical port assignment
+- reg = <2000 100>;
++ reg = <0x2000 0x100>;
+ interrupts = <2 1 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -190,7 +192,7 @@
+ spi at 2200 { // PSC2
+ compatible = "fsl,mpc5200b-psc-spi","fsl,mpc5200-psc-spi";
+ cell-index = <1>;
+- reg = <2200 100>;
++ reg = <0x2200 0x100>;
+ interrupts = <2 2 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -200,15 +202,15 @@
+ device_type = "serial";
+ compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+ port-number = <4>; // Logical port assignment
+- reg = <2800 100>;
+- interrupts = <2 c 0>;
++ reg = <0x2800 0x100>;
++ interrupts = <2 12 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ ethernet at 3000 {
+ device_type = "network";
+ compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
+- reg = <3000 400>;
++ reg = <0x3000 0x400>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <2 5 0>;
+ interrupt-parent = <&mpc5200_pic>;
+@@ -219,7 +221,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200b-mdio","fsl,mpc5200-mdio";
+- reg = <3000 400>; // fec range, since we need to setup fec interrupts
++ reg = <0x3000 0x400>; // fec range, since we need to setup fec interrupts
+ interrupts = <2 5 0>; // these are for "mii command finished", not link changes & co.
+ interrupt-parent = <&mpc5200_pic>;
+
+@@ -231,7 +233,7 @@
+
+ ata at 3a00 {
+ compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
+- reg = <3a00 100>;
++ reg = <0x3a00 0x100>;
+ interrupts = <2 7 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -240,21 +242,21 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
+- reg = <3d40 40>;
+- interrupts = <2 10 0>;
++ reg = <0x3d40 0x40>;
++ interrupts = <2 16 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ fsl5200-clocking;
+
+ rtc at 68 {
+ device_type = "rtc";
+ compatible = "dallas,ds1339";
+- reg = <68>;
++ reg = <0x68>;
};
+ };
- pio2: ucc_pin at 02 {
- pio-map = <
- /* port pin dir open_drain assignment has_irq */
-- 5 0a 1 0 2 0 /* TxD0 */
-- 5 09 1 0 2 0 /* TxD1 */
-- 5 08 1 0 2 0 /* TxD2 */
-- 5 07 1 0 2 0 /* TxD3 */
-- 5 17 1 0 2 0 /* TxD4 */
-- 5 16 1 0 2 0 /* TxD5 */
-- 5 15 1 0 2 0 /* TxD6 */
-- 5 14 1 0 2 0 /* TxD7 */
-- 5 0f 2 0 2 0 /* RxD0 */
-- 5 0e 2 0 2 0 /* RxD1 */
-- 5 0d 2 0 2 0 /* RxD2 */
-- 5 0c 2 0 2 0 /* RxD3 */
-- 5 1d 2 0 2 0 /* RxD4 */
-- 5 1c 2 0 2 0 /* RxD5 */
-- 5 1b 2 0 2 0 /* RxD6 */
-- 5 1a 2 0 2 0 /* RxD7 */
-- 5 0b 1 0 2 0 /* TX_EN */
-- 5 18 1 0 2 0 /* TX_ER */
-- 5 10 2 0 2 0 /* RX_DV */
-- 5 1e 2 0 2 0 /* RX_ER */
-- 5 11 2 0 2 0 /* RX_CLK */
-- 5 13 1 0 2 0 /* GTX_CLK */
-- 1 1f 2 0 3 0 /* GTX125 */
-- 4 06 3 0 2 0 /* MDIO */
-- 4 05 1 0 2 0>; /* MDC */
-+ 0x5 0xa 0x1 0x0 0x2 0x0 /* TxD0 */
-+ 0x5 0x9 0x1 0x0 0x2 0x0 /* TxD1 */
-+ 0x5 0x8 0x1 0x0 0x2 0x0 /* TxD2 */
-+ 0x5 0x7 0x1 0x0 0x2 0x0 /* TxD3 */
-+ 0x5 0x17 0x1 0x0 0x2 0x0 /* TxD4 */
-+ 0x5 0x16 0x1 0x0 0x2 0x0 /* TxD5 */
-+ 0x5 0x15 0x1 0x0 0x2 0x0 /* TxD6 */
-+ 0x5 0x14 0x1 0x0 0x2 0x0 /* TxD7 */
-+ 0x5 0xf 0x2 0x0 0x2 0x0 /* RxD0 */
-+ 0x5 0xe 0x2 0x0 0x2 0x0 /* RxD1 */
-+ 0x5 0xd 0x2 0x0 0x2 0x0 /* RxD2 */
-+ 0x5 0xc 0x2 0x0 0x2 0x0 /* RxD3 */
-+ 0x5 0x1d 0x2 0x0 0x2 0x0 /* RxD4 */
-+ 0x5 0x1c 0x2 0x0 0x2 0x0 /* RxD5 */
-+ 0x5 0x1b 0x2 0x0 0x2 0x0 /* RxD6 */
-+ 0x5 0x1a 0x2 0x0 0x2 0x0 /* RxD7 */
-+ 0x5 0xb 0x1 0x0 0x2 0x0 /* TX_EN */
-+ 0x5 0x18 0x1 0x0 0x2 0x0 /* TX_ER */
-+ 0x5 0x10 0x2 0x0 0x2 0x0 /* RX_DV */
-+ 0x5 0x1e 0x2 0x0 0x2 0x0 /* RX_ER */
-+ 0x5 0x11 0x2 0x0 0x2 0x0 /* RX_CLK */
-+ 0x5 0x13 0x1 0x0 0x2 0x0 /* GTX_CLK */
-+ 0x1 0x1f 0x2 0x0 0x3 0x0 /* GTX125 */
-+ 0x4 0x6 0x3 0x0 0x2 0x0 /* MDIO */
-+ 0x4 0x5 0x1 0x0 0x2 0x0>; /* MDC */
+ sram at 8000 {
+ compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
+- reg = <8000 4000>;
++ reg = <0x8000 0x4000>;
+ };
+ };
+
+@@ -262,15 +264,15 @@
+ compatible = "fsl,lpb";
+ #address-cells = <2>;
+ #size-cells = <1>;
+- ranges = <0 0 ff000000 01000000
+- 1 0 50000000 00010000
+- 2 0 50010000 00010000
+- 3 0 50020000 00010000>;
++ ranges = <0 0 0xff000000 0x01000000
++ 1 0 0x50000000 0x00010000
++ 2 0 0x50010000 0x00010000
++ 3 0 0x50020000 0x00010000>;
+
+ // 8-bit DualPort SRAM on LocalPlus Bus CS1
+ kollmorgen at 1,0 {
+ compatible = "promess,motionpro-kollmorgen";
+- reg = <1 0 10000>;
++ reg = <1 0 0x10000>;
+ interrupts = <1 1 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -278,13 +280,13 @@
+ // 8-bit board CPLD on LocalPlus Bus CS2
+ cpld at 2,0 {
+ compatible = "promess,motionpro-cpld";
+- reg = <2 0 10000>;
++ reg = <2 0 0x10000>;
+ };
+
+ // 8-bit custom Anybus Module on LocalPlus Bus CS3
+ anybus at 3,0 {
+ compatible = "promess,motionpro-anybus";
+- reg = <3 0 10000>;
++ reg = <3 0 0x10000>;
+ };
+ pro_module_general at 3,0 {
+ compatible = "promess,pro_module_general";
+@@ -292,13 +294,13 @@
+ };
+ pro_module_dio at 3,800 {
+ compatible = "promess,pro_module_dio";
+- reg = <3 800 2>;
++ reg = <3 0x800 2>;
+ };
+
+ // 16-bit flash device at LocalPlus Bus CS0
+ flash at 0,0 {
+ compatible = "cfi-flash";
+- reg = <0 0 01000000>;
++ reg = <0 0 0x01000000>;
+ bank-width = <2>;
+ device-width = <2>;
+ #size-cells = <1>;
+diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
+index 8fb5423..4936349 100644
+--- a/arch/powerpc/boot/dts/mpc7448hpc2.dts
++++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts
+@@ -1,7 +1,7 @@
+ /*
+ * MPC7448HPC2 (Taiga) board Device Tree Source
+ *
+- * Copyright 2006 Freescale Semiconductor Inc.
++ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+ * 2006 Roy Zang <Roy Zang at freescale.com>.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+@@ -10,6 +10,7 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
+
+ / {
+ model = "mpc7448hpc2";
+@@ -23,11 +24,11 @@
+
+ PowerPC,7448 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <20>; // 32 bytes
+- i-cache-line-size = <20>; // 32 bytes
+- d-cache-size = <8000>; // L1, 32K bytes
+- i-cache-size = <8000>; // L1, 32K bytes
++ reg = <0x0>;
++ d-cache-line-size = <32>; // 32 bytes
++ i-cache-line-size = <32>; // 32 bytes
++ d-cache-size = <0x8000>; // L1, 32K bytes
++ i-cache-size = <0x8000>; // L1, 32K bytes
+ timebase-frequency = <0>; // 33 MHz, from uboot
+ clock-frequency = <0>; // From U-Boot
+ bus-frequency = <0>; // From U-Boot
+@@ -36,7 +37,7 @@
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 20000000 // DDR2 512M at 0
++ reg = <0x0 0x20000000 // DDR2 512M at 0
+ >;
+ };
+
+@@ -44,14 +45,14 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "tsi-bridge";
+- ranges = <00000000 c0000000 00010000>;
+- reg = <c0000000 00010000>;
++ ranges = <0x0 0xc0000000 0x10000>;
++ reg = <0xc0000000 0x10000>;
+ bus-frequency = <0>;
+
+ i2c at 7000 {
+ interrupt-parent = <&mpic>;
+- interrupts = <E 0>;
+- reg = <7000 400>;
++ interrupts = <14 0>;
++ reg = <0x7000 0x400>;
+ device_type = "i2c";
+ compatible = "tsi108-i2c";
+ };
+@@ -59,20 +60,20 @@
+ MDIO: mdio at 6000 {
+ device_type = "mdio";
+ compatible = "tsi108-mdio";
+- reg = <6000 50>;
++ reg = <0x6000 0x50>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy8: ethernet-phy at 8 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1>;
+- reg = <8>;
++ reg = <0x8>;
+ };
+
+ phy9: ethernet-phy at 9 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1>;
+- reg = <9>;
++ reg = <0x9>;
+ };
+
+ };
+@@ -82,9 +83,9 @@
+ #size-cells = <0>;
+ device_type = "network";
+ compatible = "tsi108-ethernet";
+- reg = <6000 200>;
++ reg = <0x6000 0x200>;
+ address = [ 00 06 D2 00 00 01 ];
+- interrupts = <10 2>;
++ interrupts = <16 2>;
+ interrupt-parent = <&mpic>;
+ mdio-handle = <&MDIO>;
+ phy-handle = <&phy8>;
+@@ -96,9 +97,9 @@
+ #size-cells = <0>;
+ device_type = "network";
+ compatible = "tsi108-ethernet";
+- reg = <6400 200>;
++ reg = <0x6400 0x200>;
+ address = [ 00 06 D2 00 00 02 ];
+- interrupts = <11 2>;
++ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ mdio-handle = <&MDIO>;
+ phy-handle = <&phy9>;
+@@ -107,18 +108,18 @@
+ serial at 7808 {
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <7808 200>;
+- clock-frequency = <3f6b5a00>;
+- interrupts = <c 0>;
++ reg = <0x7808 0x200>;
++ clock-frequency = <1064000000>;
++ interrupts = <12 0>;
+ interrupt-parent = <&mpic>;
+ };
+
+ serial at 7c08 {
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <7c08 200>;
+- clock-frequency = <3f6b5a00>;
+- interrupts = <d 0>;
++ reg = <0x7c08 0x200>;
++ clock-frequency = <1064000000>;
++ interrupts = <13 0>;
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -127,7 +128,7 @@
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- reg = <7400 400>;
++ reg = <0x7400 0x400>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ big-endian;
+@@ -138,39 +139,39 @@
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <1000 1000>;
++ reg = <0x1000 0x1000>;
+ bus-range = <0 0>;
+- ranges = <02000000 0 e0000000 e0000000 0 1A000000
+- 01000000 0 00000000 fa000000 0 00010000>;
+- clock-frequency = <7f28154>;
++ ranges = <0x2000000 0x0 0xe0000000 0xe0000000 0x0 0x1a000000
++ 0x1000000 0x0 0x0 0xfa000000 0x0 0x10000>;
++ clock-frequency = <133333332>;
+ interrupt-parent = <&mpic>;
+- interrupts = <17 2>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupts = <23 2>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x11 */
+- 0800 0 0 1 &RT0 24 0
+- 0800 0 0 2 &RT0 25 0
+- 0800 0 0 3 &RT0 26 0
+- 0800 0 0 4 &RT0 27 0
++ 0x800 0x0 0x0 0x1 &RT0 0x24 0x0
++ 0x800 0x0 0x0 0x2 &RT0 0x25 0x0
++ 0x800 0x0 0x0 0x3 &RT0 0x26 0x0
++ 0x800 0x0 0x0 0x4 &RT0 0x27 0x0
+
+ /* IDSEL 0x12 */
+- 1000 0 0 1 &RT0 25 0
+- 1000 0 0 2 &RT0 26 0
+- 1000 0 0 3 &RT0 27 0
+- 1000 0 0 4 &RT0 24 0
++ 0x1000 0x0 0x0 0x1 &RT0 0x25 0x0
++ 0x1000 0x0 0x0 0x2 &RT0 0x26 0x0
++ 0x1000 0x0 0x0 0x3 &RT0 0x27 0x0
++ 0x1000 0x0 0x0 0x4 &RT0 0x24 0x0
+
+ /* IDSEL 0x13 */
+- 1800 0 0 1 &RT0 26 0
+- 1800 0 0 2 &RT0 27 0
+- 1800 0 0 3 &RT0 24 0
+- 1800 0 0 4 &RT0 25 0
++ 0x1800 0x0 0x0 0x1 &RT0 0x26 0x0
++ 0x1800 0x0 0x0 0x2 &RT0 0x27 0x0
++ 0x1800 0x0 0x0 0x3 &RT0 0x24 0x0
++ 0x1800 0x0 0x0 0x4 &RT0 0x25 0x0
+
+ /* IDSEL 0x14 */
+- 2000 0 0 1 &RT0 27 0
+- 2000 0 0 2 &RT0 24 0
+- 2000 0 0 3 &RT0 25 0
+- 2000 0 0 4 &RT0 26 0
++ 0x2000 0x0 0x0 0x1 &RT0 0x27 0x0
++ 0x2000 0x0 0x0 0x2 &RT0 0x24 0x0
++ 0x2000 0x0 0x0 0x3 &RT0 0x25 0x0
++ 0x2000 0x0 0x0 0x4 &RT0 0x26 0x0
+ >;
+
+ RT0: router at 1180 {
+@@ -180,7 +181,7 @@
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ big-endian;
+- interrupts = <17 2>;
++ interrupts = <23 2>;
+ interrupt-parent = <&mpic>;
};
};
+diff --git a/arch/powerpc/boot/dts/mpc8272ads.dts b/arch/powerpc/boot/dts/mpc8272ads.dts
+index 7285ca1..46e2da3 100644
+--- a/arch/powerpc/boot/dts/mpc8272ads.dts
++++ b/arch/powerpc/boot/dts/mpc8272ads.dts
+@@ -1,7 +1,7 @@
+ /*
+ * MPC8272 ADS Device Tree Source
+ *
+- * Copyright 2005 Freescale Semiconductor Inc.
++ * Copyright 2005,2008 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+@@ -9,6 +9,8 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
++
+ / {
+ model = "MPC8272ADS";
+ compatible = "fsl,mpc8272ads";
+@@ -21,11 +23,11 @@
+
+ PowerPC,8272 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <d#32>;
+- i-cache-line-size = <d#32>;
+- d-cache-size = <d#16384>;
+- i-cache-size = <d#16384>;
++ reg = <0x0>;
++ d-cache-line-size = <32>;
++ i-cache-line-size = <32>;
++ d-cache-size = <16384>;
++ i-cache-size = <16384>;
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+@@ -34,7 +36,7 @@
+
+ memory {
+ device_type = "memory";
+- reg = <0 0>;
++ reg = <0x0 0x0>;
};
-@@ -285,28 +282,28 @@
+
+ localbus at f0010100 {
+@@ -42,21 +44,21 @@
+ "fsl,pq2-localbus";
+ #address-cells = <2>;
#size-cells = <1>;
- device_type = "qe";
- compatible = "fsl,qe";
-- ranges = <0 e0080000 00040000>;
-- reg = <e0080000 480>;
-+ ranges = <0x0 0xe0080000 0x40000>;
-+ reg = <0xe0080000 0x480>;
- brg-frequency = <0>;
-- bus-frequency = <179A7B00>;
-+ bus-frequency = <396000000>;
+- reg = <f0010100 40>;
++ reg = <0xf0010100 0x40>;
- muram at 10000 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "fsl,qe-muram", "fsl,cpm-muram";
-- ranges = <0 00010000 0000c000>;
-+ ranges = <0x0 0x10000 0x10000>;
+- 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>;
- data-only at 0 {
- compatible = "fsl,qe-muram-data",
- "fsl,cpm-muram-data";
-- reg = <0 c000>;
-+ reg = <0x0 0x10000>;
+ flash at 0,0 {
+ compatible = "jedec-flash";
+- reg = <0 0 2000000>;
++ reg = <0x0 0x0 0x2000000>;
+ bank-width = <4>;
+ device-width = <1>;
+ };
+
+ board-control at 1,0 {
+- reg = <1 0 20>;
++ reg = <0x1 0x0 0x20>;
+ compatible = "fsl,mpc8272ads-bcsr";
+ };
+
+@@ -65,46 +67,46 @@
+ "fsl,pq2ads-pci-pic";
+ #interrupt-cells = <1>;
+ interrupt-controller;
+- reg = <3 0 8>;
++ reg = <0x3 0x0 0x8>;
+ interrupt-parent = <&PIC>;
+- interrupts = <14 8>;
++ interrupts = <20 8>;
+ };
+ };
+
+
+ pci at f0010800 {
+ device_type = "pci";
+- reg = <f0010800 10c f00101ac 8 f00101c4 8>;
++ reg = <0xf0010800 0x10c 0xf00101ac 0x8 0xf00101c4 0x8>;
+ compatible = "fsl,mpc8272-pci", "fsl,pq2-pci";
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- clock-frequency = <d#66666666>;
+- interrupt-map-mask = <f800 0 0 7>;
++ clock-frequency = <66666666>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x16 */
+- b000 0 0 1 &PCI_PIC 0
+- b000 0 0 2 &PCI_PIC 1
+- b000 0 0 3 &PCI_PIC 2
+- b000 0 0 4 &PCI_PIC 3
++ 0xb000 0x0 0x0 0x1 &PCI_PIC 0
++ 0xb000 0x0 0x0 0x2 &PCI_PIC 1
++ 0xb000 0x0 0x0 0x3 &PCI_PIC 2
++ 0xb000 0x0 0x0 0x4 &PCI_PIC 3
+
+ /* IDSEL 0x17 */
+- b800 0 0 1 &PCI_PIC 4
+- b800 0 0 2 &PCI_PIC 5
+- b800 0 0 3 &PCI_PIC 6
+- b800 0 0 4 &PCI_PIC 7
++ 0xb800 0x0 0x0 0x1 &PCI_PIC 4
++ 0xb800 0x0 0x0 0x2 &PCI_PIC 5
++ 0xb800 0x0 0x0 0x3 &PCI_PIC 6
++ 0xb800 0x0 0x0 0x4 &PCI_PIC 7
+
+ /* IDSEL 0x18 */
+- c000 0 0 1 &PCI_PIC 8
+- c000 0 0 2 &PCI_PIC 9
+- c000 0 0 3 &PCI_PIC a
+- c000 0 0 4 &PCI_PIC b>;
++ 0xc000 0x0 0x0 0x1 &PCI_PIC 8
++ 0xc000 0x0 0x0 0x2 &PCI_PIC 9
++ 0xc000 0x0 0x0 0x3 &PCI_PIC 10
++ 0xc000 0x0 0x0 0x4 &PCI_PIC 11>;
+
+ interrupt-parent = <&PIC>;
+- interrupts = <12 8>;
+- ranges = <42000000 0 80000000 80000000 0 20000000
+- 02000000 0 a0000000 a0000000 0 20000000
+- 01000000 0 00000000 f6000000 0 02000000>;
++ interrupts = <18 8>;
++ ranges = <0x42000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xf6000000 0x0 0x2000000>;
+ };
+
+ soc at f0000000 {
+@@ -112,26 +114,26 @@
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "fsl,mpc8272", "fsl,pq2-soc";
+- ranges = <00000000 f0000000 00053000>;
++ ranges = <0x0 0xf0000000 0x53000>;
+
+ // Temporary -- will go away once kernel uses ranges for get_immrbase().
+- reg = <f0000000 00053000>;
++ reg = <0xf0000000 0x53000>;
+
+ cpm at 119c0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8272-cpm", "fsl,cpm2";
+- reg = <119c0 30>;
++ reg = <0x119c0 0x30>;
+ ranges;
+
+ muram at 0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+- ranges = <0 0 10000>;
++ ranges = <0x0 0x0 0x10000>;
+
+ data at 0 {
+ compatible = "fsl,cpm-muram-data";
+- reg = <0 2000 9800 800>;
++ reg = <0x0 0x2000 0x9800 0x800>;
+ };
+ };
+
+@@ -139,29 +141,29 @@
+ compatible = "fsl,mpc8272-brg",
+ "fsl,cpm2-brg",
+ "fsl,cpm-brg";
+- reg = <119f0 10 115f0 10>;
++ reg = <0x119f0 0x10 0x115f0 0x10>;
+ };
+
+ serial at 11a00 {
+ device_type = "serial";
+ compatible = "fsl,mpc8272-scc-uart",
+ "fsl,cpm2-scc-uart";
+- reg = <11a00 20 8000 100>;
+- interrupts = <28 8>;
++ reg = <0x11a00 0x20 0x8000 0x100>;
++ interrupts = <40 8>;
+ interrupt-parent = <&PIC>;
+ fsl,cpm-brg = <1>;
+- fsl,cpm-command = <00800000>;
++ fsl,cpm-command = <0x800000>;
+ };
+
+ serial at 11a60 {
+ device_type = "serial";
+ compatible = "fsl,mpc8272-scc-uart",
+ "fsl,cpm2-scc-uart";
+- reg = <11a60 20 8300 100>;
+- interrupts = <2b 8>;
++ reg = <0x11a60 0x20 0x8300 0x100>;
++ interrupts = <43 8>;
+ interrupt-parent = <&PIC>;
+ fsl,cpm-brg = <4>;
+- fsl,cpm-command = <0ce00000>;
++ fsl,cpm-command = <0xce00000>;
+ };
+
+ mdio at 10d40 {
+@@ -169,23 +171,23 @@
+ compatible = "fsl,mpc8272ads-mdio-bitbang",
+ "fsl,mpc8272-mdio-bitbang",
+ "fsl,cpm2-mdio-bitbang";
+- reg = <10d40 14>;
++ reg = <0x10d40 0x14>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+- fsl,mdio-pin = <12>;
+- fsl,mdc-pin = <13>;
++ fsl,mdio-pin = <18>;
++ fsl,mdc-pin = <19>;
+
+ PHY0: ethernet-phy at 0 {
+ interrupt-parent = <&PIC>;
+- interrupts = <17 8>;
+- reg = <0>;
++ interrupts = <23 8>;
++ reg = <0x0>;
+ device_type = "ethernet-phy";
+ };
+
+ PHY1: ethernet-phy at 1 {
+ interrupt-parent = <&PIC>;
+- interrupts = <17 8>;
+- reg = <3>;
++ interrupts = <23 8>;
++ reg = <0x3>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -194,33 +196,33 @@
+ device_type = "network";
+ compatible = "fsl,mpc8272-fcc-enet",
+ "fsl,cpm2-fcc-enet";
+- reg = <11300 20 8400 100 11390 1>;
++ reg = <0x11300 0x20 0x8400 0x100 0x11390 0x1>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <20 8>;
++ interrupts = <32 8>;
+ interrupt-parent = <&PIC>;
+ phy-handle = <&PHY0>;
+ linux,network-index = <0>;
+- fsl,cpm-command = <12000300>;
++ fsl,cpm-command = <0x12000300>;
+ };
+
+ ethernet at 11320 {
+ device_type = "network";
+ compatible = "fsl,mpc8272-fcc-enet",
+ "fsl,cpm2-fcc-enet";
+- reg = <11320 20 8500 100 113b0 1>;
++ reg = <0x11320 0x20 0x8500 0x100 0x113b0 0x1>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <21 8>;
++ interrupts = <33 8>;
+ interrupt-parent = <&PIC>;
+ phy-handle = <&PHY1>;
+ linux,network-index = <1>;
+- fsl,cpm-command = <16200300>;
++ fsl,cpm-command = <0x16200300>;
};
};
- spi at 4c0 {
- cell-index = <0>;
- compatible = "fsl,spi";
-- reg = <4c0 40>;
-+ reg = <0x4c0 0x40>;
- interrupts = <2>;
+ PIC: interrupt-controller at 10c00 {
+ #interrupt-cells = <2>;
+ interrupt-controller;
+- reg = <10c00 80>;
++ reg = <0x10c00 0x80>;
+ compatible = "fsl,mpc8272-pic", "fsl,cpm2-pic";
+ };
+
+@@ -232,14 +234,14 @@
+ "fsl,talitos-sec2",
+ "fsl,talitos",
+ "talitos";
+- reg = <30000 10000>;
+- interrupts = <b 8>;
++ reg = <0x30000 0x10000>;
++ interrupts = <11 8>;
+ interrupt-parent = <&PIC>;
+ num-channels = <4>;
+- channel-fifo-len = <18>;
+- exec-units-mask = <0000007e>;
++ channel-fifo-len = <24>;
++ exec-units-mask = <0x7e>;
+ /* desc mask is for rev1.x, we need runtime fixup for >=2.x */
+- descriptor-types-mask = <01010ebf>;
++ descriptor-types-mask = <0x1010ebf>;
+ };
+ };
+
+diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
+index 9bb4083..539e02f 100644
+--- a/arch/powerpc/boot/dts/mpc832x_mds.dts
++++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
+@@ -255,9 +255,7 @@
+ enet0: ucc at 2200 {
+ device_type = "network";
+ compatible = "ucc_geth";
+- model = "UCC";
+ cell-index = <3>;
+- device-id = <3>;
+ reg = <0x2200 0x200>;
+ interrupts = <34>;
interrupt-parent = <&qeic>;
- mode = "cpu";
-@@ -315,7 +312,7 @@
- spi at 500 {
- cell-index = <1>;
- compatible = "fsl,spi";
-- reg = <500 40>;
-+ reg = <0x500 0x40>;
- interrupts = <1>;
+@@ -271,9 +269,7 @@
+ enet1: ucc at 3200 {
+ device_type = "network";
+ compatible = "ucc_geth";
+- model = "UCC";
+ cell-index = <4>;
+- device-id = <4>;
+ reg = <0x3200 0x200>;
+ interrupts = <35>;
interrupt-parent = <&qeic>;
- mode = "cpu";
-@@ -324,11 +321,9 @@
- enet2: ucc at 2000 {
+@@ -287,8 +283,7 @@
+ ucc at 2400 {
+ device_type = "serial";
+ compatible = "ucc_uart";
+- model = "UCC";
+- device-id = <5>; /* The UCC number, 1-7*/
++ cell-index = <5>; /* The UCC number, 1-7*/
+ port-number = <0>; /* Which ttyQEx device */
+ soft-uart; /* We need Soft-UART */
+ reg = <0x2400 0x200>;
+diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts
+index 94f93d2..179c81c 100644
+--- a/arch/powerpc/boot/dts/mpc832x_rdb.dts
++++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts
+@@ -208,9 +208,7 @@
+ enet0: ucc at 3000 {
+ device_type = "network";
+ compatible = "ucc_geth";
+- model = "UCC";
+ cell-index = <2>;
+- device-id = <2>;
+ reg = <0x3000 0x200>;
+ interrupts = <33>;
+ interrupt-parent = <&qeic>;
+@@ -224,9 +222,7 @@
+ enet1: ucc at 2200 {
+ device_type = "network";
+ compatible = "ucc_geth";
+- model = "UCC";
+ cell-index = <3>;
+- device-id = <3>;
+ reg = <0x2200 0x200>;
+ interrupts = <34>;
+ interrupt-parent = <&qeic>;
+diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
+index 55f03e8..8160ff2 100644
+--- a/arch/powerpc/boot/dts/mpc836x_mds.dts
++++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
+@@ -257,9 +257,7 @@
+ enet0: ucc at 2000 {
device_type = "network";
compatible = "ucc_geth";
- model = "UCC";
cell-index = <1>;
- device-id = <1>;
-- reg = <2000 200>;
-- interrupts = <20>;
-+ reg = <0x2000 0x200>;
-+ interrupts = <32>;
+ reg = <0x2000 0x200>;
+ interrupts = <32>;
interrupt-parent = <&qeic>;
- local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock-name = "none";
-@@ -341,11 +336,9 @@
- enet3: ucc at 3000 {
+@@ -274,9 +272,7 @@
+ enet1: ucc at 3000 {
device_type = "network";
compatible = "ucc_geth";
- model = "UCC";
cell-index = <2>;
- device-id = <2>;
-- reg = <3000 200>;
-- interrupts = <21>;
-+ reg = <0x3000 0x200>;
-+ interrupts = <33>;
+ reg = <0x3000 0x200>;
+ interrupts = <33>;
interrupt-parent = <&qeic>;
- local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock-name = "none";
-@@ -358,7 +351,7 @@
- mdio at 2120 {
+diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts
+index 9752484..18033ed 100644
+--- a/arch/powerpc/boot/dts/mpc8540ads.dts
++++ b/arch/powerpc/boot/dts/mpc8540ads.dts
+@@ -1,7 +1,7 @@
+ /*
+ * MPC8540 ADS Device Tree Source
+ *
+- * Copyright 2006 Freescale Semiconductor Inc.
++ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+@@ -9,6 +9,7 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
+
+ / {
+ model = "MPC8540ADS";
+@@ -31,11 +32,11 @@
+
+ PowerPC,8540 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <20>; // 32 bytes
+- i-cache-line-size = <20>; // 32 bytes
+- d-cache-size = <8000>; // L1, 32K
+- i-cache-size = <8000>; // L1, 32K
++ reg = <0x0>;
++ d-cache-line-size = <32>; // 32 bytes
++ i-cache-line-size = <32>; // 32 bytes
++ d-cache-size = <0x8000>; // L1, 32K
++ i-cache-size = <0x8000>; // L1, 32K
+ timebase-frequency = <0>; // 33 MHz, from uboot
+ bus-frequency = <0>; // 166 MHz
+ clock-frequency = <0>; // 825 MHz, from uboot
+@@ -44,31 +45,31 @@
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 08000000>; // 128M at 0x0
++ reg = <0x0 0x8000000>; // 128M at 0x0
+ };
+
+ soc8540 at e0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+- ranges = <0 e0000000 00100000>;
+- reg = <e0000000 00100000>; // CCSRBAR 1M
++ ranges = <0x0 0xe0000000 0x100000>;
++ reg = <0xe0000000 0x100000>; // CCSRBAR 1M
+ bus-frequency = <0>;
+
+ memory-controller at 2000 {
+ compatible = "fsl,8540-memory-controller";
+- reg = <2000 1000>;
++ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+- interrupts = <12 2>;
++ interrupts = <18 2>;
+ };
+
+ l2-cache-controller at 20000 {
+ compatible = "fsl,8540-l2-cache-controller";
+- reg = <20000 1000>;
+- cache-line-size = <20>; // 32 bytes
+- cache-size = <40000>; // L2, 256K
++ reg = <0x20000 0x1000>;
++ cache-line-size = <32>; // 32 bytes
++ cache-size = <0x40000>; // L2, 256K
+ interrupt-parent = <&mpic>;
+- interrupts = <10 2>;
++ interrupts = <16 2>;
+ };
+
+ i2c at 3000 {
+@@ -76,8 +77,8 @@
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+- reg = <3000 100>;
+- interrupts = <2b 2>;
++ reg = <0x3000 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+@@ -86,24 +87,24 @@
#address-cells = <1>;
#size-cells = <0>;
-- reg = <2120 18>;
-+ reg = <0x2120 0x18>;
- compatible = "fsl,ucc-mdio";
+ compatible = "fsl,gianfar-mdio";
+- reg = <24520 20>;
++ reg = <0x24520 0x20>;
- /* These are the same PHYs as on
-@@ -366,25 +359,25 @@
- qe_phy0: ethernet-phy at 07 {
+ phy0: ethernet-phy at 0 {
interrupt-parent = <&mpic>;
- interrupts = <1 1>;
-- reg = <7>;
-+ reg = <0x7>;
+ interrupts = <5 1>;
+- reg = <0>;
++ reg = <0x0>;
device_type = "ethernet-phy";
};
- qe_phy1: ethernet-phy at 01 {
+ phy1: ethernet-phy at 1 {
interrupt-parent = <&mpic>;
- interrupts = <2 1>;
+ interrupts = <5 1>;
- reg = <1>;
+ reg = <0x1>;
device_type = "ethernet-phy";
};
- qe_phy2: ethernet-phy at 02 {
- interrupt-parent = <&mpic>;
- interrupts = <1 1>;
-- reg = <2>;
-+ reg = <0x2>;
- device_type = "ethernet-phy";
- };
- qe_phy3: ethernet-phy at 03 {
+ phy3: ethernet-phy at 3 {
interrupt-parent = <&mpic>;
- interrupts = <2 1>;
+ interrupts = <7 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
+@@ -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>;
};
-@@ -404,30 +397,30 @@
+@@ -158,9 +159,9 @@
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4600 100>; // reg base, size
++ reg = <0x4600 0x100>; // reg base, size
+ clock-frequency = <0>; // should we fill in in uboot?
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+ mpic: pic at 40000 {
+@@ -168,7 +169,7 @@
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- reg = <40000 40000>;
++ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ big-endian;
+@@ -177,90 +178,90 @@
pci0: pci at e0008000 {
cell-index = <0>;
- interrupt-map-mask = <f800 0 0 7>;
+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
- /* IDSEL 0x12 AD18 */
-- 9000 0 0 1 &mpic 5 1
-- 9000 0 0 2 &mpic 6 1
-- 9000 0 0 3 &mpic 7 1
+
+ /* 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 0x5 0x1
-+ 0x9000 0x0 0x0 0x2 &mpic 0x6 0x1
-+ 0x9000 0x0 0x0 0x3 &mpic 0x7 0x1
++ 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 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>;
+ /* 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>;
-- bus-range = <0 ff>;
++ interrupts = <24 2>;
+ bus-range = <0 0>;
- ranges = <02000000 0 80000000 80000000 0 20000000
-- 01000000 0 00000000 e2000000 0 00800000>;
+- 01000000 0 00000000 e2000000 0 00100000>;
- clock-frequency = <3f940aa>;
++ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>;
++ clock-frequency = <66666666>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0008000 1000>;
++ reg = <0xe0008000 0x1000>;
+ compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci";
+ device_type = "pci";
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts
+index fa8d9aa..663c7c5 100644
+--- a/arch/powerpc/boot/dts/mpc8541cds.dts
++++ b/arch/powerpc/boot/dts/mpc8541cds.dts
+@@ -1,7 +1,7 @@
+ /*
+ * MPC8541 CDS Device Tree Source
+ *
+- * Copyright 2006 Freescale Semiconductor Inc.
++ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+@@ -9,6 +9,7 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
+
+ / {
+ model = "MPC8541CDS";
+@@ -31,11 +32,11 @@
+
+ PowerPC,8541 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <20>; // 32 bytes
+- i-cache-line-size = <20>; // 32 bytes
+- d-cache-size = <8000>; // L1, 32K
+- i-cache-size = <8000>; // L1, 32K
++ reg = <0x0>;
++ d-cache-line-size = <32>; // 32 bytes
++ i-cache-line-size = <32>; // 32 bytes
++ d-cache-size = <0x8000>; // L1, 32K
++ i-cache-size = <0x8000>; // L1, 32K
+ timebase-frequency = <0>; // 33 MHz, from uboot
+ bus-frequency = <0>; // 166 MHz
+ clock-frequency = <0>; // 825 MHz, from uboot
+@@ -44,31 +45,31 @@
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 08000000>; // 128M at 0x0
++ reg = <0x0 0x8000000>; // 128M at 0x0
+ };
+
+ soc8541 at e0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+- ranges = <0 e0000000 00100000>;
+- reg = <e0000000 00001000>; // CCSRBAR 1M
++ ranges = <0x0 0xe0000000 0x100000>;
++ reg = <0xe0000000 0x1000>; // CCSRBAR 1M
+ bus-frequency = <0>;
+
+ memory-controller at 2000 {
+ compatible = "fsl,8541-memory-controller";
+- reg = <2000 1000>;
++ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+- interrupts = <12 2>;
++ interrupts = <18 2>;
+ };
+
+ l2-cache-controller at 20000 {
+ compatible = "fsl,8541-l2-cache-controller";
+- reg = <20000 1000>;
+- cache-line-size = <20>; // 32 bytes
+- cache-size = <40000>; // L2, 256K
++ reg = <0x20000 0x1000>;
++ cache-line-size = <32>; // 32 bytes
++ cache-size = <0x40000>; // L2, 256K
+ interrupt-parent = <&mpic>;
+- interrupts = <10 2>;
++ interrupts = <16 2>;
+ };
+
+ i2c at 3000 {
+@@ -76,8 +77,8 @@
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+- reg = <3000 100>;
+- interrupts = <2b 2>;
++ reg = <0x3000 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+@@ -86,18 +87,18 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-mdio";
+- reg = <24520 20>;
++ reg = <0x24520 0x20>;
+
+ phy0: ethernet-phy at 0 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <0>;
++ reg = <0x0>;
+ device_type = "ethernet-phy";
+ };
+ phy1: ethernet-phy at 1 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <1>;
++ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -107,9 +108,9 @@
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+- reg = <24000 1000>;
++ reg = <0x24000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1d 2 1e 2 22 2>;
++ interrupts = <29 2 30 2 34 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy0>;
+ };
+@@ -119,9 +120,9 @@
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+- reg = <25000 1000>;
++ reg = <0x25000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <23 2 24 2 28 2>;
++ interrupts = <35 2 36 2 40 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy1>;
+ };
+@@ -130,9 +131,9 @@
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4500 100>; // reg base, size
++ reg = <0x4500 0x100>; // reg base, size
+ clock-frequency = <0>; // should we fill in in uboot?
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -140,9 +141,9 @@
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4600 100>; // reg base, size
++ reg = <0x4600 0x100>; // reg base, size
+ clock-frequency = <0>; // should we fill in in uboot?
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -151,7 +152,7 @@
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- reg = <40000 40000>;
++ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ big-endian;
+@@ -161,17 +162,17 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8541-cpm", "fsl,cpm2";
+- reg = <919c0 30>;
++ reg = <0x919c0 0x30>;
+ ranges;
+
+ muram at 80000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+- ranges = <0 80000 10000>;
++ ranges = <0x0 0x80000 0x10000>;
+
+ data at 0 {
+ compatible = "fsl,cpm-muram-data";
+- reg = <0 2000 9000 1000>;
++ reg = <0x0 0x2000 0x9000 0x1000>;
+ };
+ };
+
+@@ -179,16 +180,16 @@
+ compatible = "fsl,mpc8541-brg",
+ "fsl,cpm2-brg",
+ "fsl,cpm-brg";
+- reg = <919f0 10 915f0 10>;
++ reg = <0x919f0 0x10 0x915f0 0x10>;
+ };
+
+ cpmpic: pic at 90c00 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- interrupts = <2e 2>;
++ interrupts = <46 2>;
+ interrupt-parent = <&mpic>;
+- reg = <90c00 80>;
++ reg = <0x90c00 0x80>;
+ compatible = "fsl,mpc8541-cpm-pic", "fsl,cpm2-pic";
+ };
+ };
+@@ -196,68 +197,68 @@
+
+ pci0: pci at e0008000 {
+ cell-index = <0>;
+- interrupt-map-mask = <1f800 0 0 7>;
++ interrupt-map-mask = <0x1f800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x10 */
+- 08000 0 0 1 &mpic 0 1
+- 08000 0 0 2 &mpic 1 1
+- 08000 0 0 3 &mpic 2 1
+- 08000 0 0 4 &mpic 3 1
++ 0x8000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x8000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x8000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x8000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x11 */
+- 08800 0 0 1 &mpic 0 1
+- 08800 0 0 2 &mpic 1 1
+- 08800 0 0 3 &mpic 2 1
+- 08800 0 0 4 &mpic 3 1
++ 0x8800 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x8800 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x8800 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x8800 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x12 (Slot 1) */
+- 09000 0 0 1 &mpic 0 1
+- 09000 0 0 2 &mpic 1 1
+- 09000 0 0 3 &mpic 2 1
+- 09000 0 0 4 &mpic 3 1
++ 0x9000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x9000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x9000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x9000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x13 (Slot 2) */
+- 09800 0 0 1 &mpic 1 1
+- 09800 0 0 2 &mpic 2 1
+- 09800 0 0 3 &mpic 3 1
+- 09800 0 0 4 &mpic 0 1
++ 0x9800 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0x9800 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0x9800 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x9800 0x0 0x0 0x4 &mpic 0x0 0x1
+
+ /* IDSEL 0x14 (Slot 3) */
+- 0a000 0 0 1 &mpic 2 1
+- 0a000 0 0 2 &mpic 3 1
+- 0a000 0 0 3 &mpic 0 1
+- 0a000 0 0 4 &mpic 1 1
++ 0xa000 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0xa000 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0xa000 0x0 0x0 0x3 &mpic 0x0 0x1
++ 0xa000 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x15 (Slot 4) */
+- 0a800 0 0 1 &mpic 3 1
+- 0a800 0 0 2 &mpic 0 1
+- 0a800 0 0 3 &mpic 1 1
+- 0a800 0 0 4 &mpic 2 1
++ 0xa800 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0xa800 0x0 0x0 0x2 &mpic 0x0 0x1
++ 0xa800 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0xa800 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* Bus 1 (Tundra Bridge) */
+ /* IDSEL 0x12 (ISA bridge) */
+- 19000 0 0 1 &mpic 0 1
+- 19000 0 0 2 &mpic 1 1
+- 19000 0 0 3 &mpic 2 1
+- 19000 0 0 4 &mpic 3 1>;
++ 0x19000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x19000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x19000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x19000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+ interrupt-parent = <&mpic>;
+- interrupts = <18 2>;
+ interrupts = <24 2>;
-+ bus-range = <0 255>;
+ 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 0x800000>;
++ 0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>;
+ clock-frequency = <66666666>;
#interrupt-cells = <1>;
#size-cells = <2>;
@@ -103814,72 +133563,57 @@
+ reg = <0xe0008000 0x1000>;
compatible = "fsl,mpc8540-pci";
device_type = "pci";
- };
-@@ -435,39 +428,39 @@
- /* PCI Express */
- pci1: pcie at e000a000 {
- cell-index = <2>;
+
+ i8259 at 19000 {
+ interrupt-controller;
+ device_type = "interrupt-controller";
+- reg = <19000 0 0 0 1>;
++ reg = <0x19000 0x0 0x0 0x0 0x1>;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ compatible = "chrp,iic";
+@@ -268,24 +269,24 @@
+
+ pci1: pci at e0009000 {
+ cell-index = <1>;
- interrupt-map-mask = <f800 0 0 7>;
+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
- /* IDSEL 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>;
-
+ /* 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 = <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>;
+- 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 = <e000a000 1000>;
-+ reg = <0xe000a000 0x1000>;
- compatible = "fsl,mpc8548-pcie";
+- reg = <e0009000 1000>;
++ reg = <0xe0009000 0x1000>;
+ compatible = "fsl,mpc8540-pci";
device_type = "pci";
- pcie at 0 {
-- reg = <0 0 0 0 0>;
-+ reg = <0x0 0x0 0x0 0x0 0x0>;
- #size-cells = <2>;
- #address-cells = <3>;
- device_type = "pci";
-- ranges = <02000000 0 a0000000
-- 02000000 0 a0000000
-- 0 10000000
-+ ranges = <0x2000000 0x0 0xa0000000
-+ 0x2000000 0x0 0xa0000000
-+ 0x0 0x10000000
-
-- 01000000 0 00000000
-- 01000000 0 00000000
-- 0 00800000>;
-+ 0x1000000 0x0 0x0
-+ 0x1000000 0x0 0x0
-+ 0x0 0x800000>;
- };
};
- };
-diff --git a/arch/powerpc/boot/dts/mpc8572ds.dts b/arch/powerpc/boot/dts/mpc8572ds.dts
-index db37214..66f27ab 100644
---- a/arch/powerpc/boot/dts/mpc8572ds.dts
-+++ b/arch/powerpc/boot/dts/mpc8572ds.dts
+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 @@
/*
- * MPC8572 DS Device Tree Source
+ * MPC8544 DS Device Tree Source
*
- * Copyright 2007 Freescale Semiconductor Inc.
+ * Copyright 2007, 2008 Freescale Semiconductor Inc.
@@ -103892,11 +133626,17 @@
+/dts-v1/;
/ {
- model = "fsl,MPC8572DS";
- compatible = "fsl,MPC8572DS";
-@@ -33,11 +34,11 @@
+ model = "MPC8544DS";
+ compatible = "MPC8544DS", "MPC85xxDS";
+@@ -27,17 +28,16 @@
+ };
- PowerPC,8572 at 0 {
+ cpus {
+- #cpus = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,8544 at 0 {
device_type = "cpu";
- reg = <0>;
- d-cache-line-size = <20>; // 32 bytes
@@ -103911,24 +133651,7 @@
timebase-frequency = <0>;
bus-frequency = <0>;
clock-frequency = <0>;
-@@ -45,11 +46,11 @@
-
- PowerPC,8572 at 1 {
- device_type = "cpu";
-- reg = <1>;
-- d-cache-line-size = <20>; // 32 bytes
-- i-cache-line-size = <20>; // 32 bytes
-- d-cache-size = <8000>; // L1, 32K
-- i-cache-size = <8000>; // L1, 32K
-+ reg = <0x1>;
-+ d-cache-line-size = <32>; // 32 bytes
-+ i-cache-line-size = <32>; // 32 bytes
-+ d-cache-size = <0x8000>; // L1, 32K
-+ i-cache-size = <0x8000>; // L1, 32K
- timebase-frequency = <0>;
- bus-frequency = <0>;
- clock-frequency = <0>;
-@@ -58,38 +59,38 @@
+@@ -46,7 +46,7 @@
memory {
device_type = "memory";
@@ -103936,18 +133659,19 @@
+ reg = <0x0 0x0>; // Filled by U-Boot
};
- soc8572 at ffe00000 {
- #address-cells = <1>;
+ soc8544 at e0000000 {
+@@ -54,24 +54,24 @@
#size-cells = <1>;
device_type = "soc";
-- ranges = <00000000 ffe00000 00100000>;
-- reg = <ffe00000 00001000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed
-+ ranges = <0x0 0xffe00000 0x100000>;
-+ reg = <0xffe00000 0x1000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed
+
+- ranges = <00000000 e0000000 00100000>;
+- reg = <e0000000 00001000>; // CCSRBAR 1M
++ ranges = <0x0 0xe0000000 0x100000>;
++ reg = <0xe0000000 0x1000>; // CCSRBAR 1M
bus-frequency = <0>; // Filled out by uboot.
memory-controller at 2000 {
- compatible = "fsl,mpc8572-memory-controller";
+ compatible = "fsl,8544-memory-controller";
- reg = <2000 1000>;
+ reg = <0x2000 0x1000>;
interrupt-parent = <&mpic>;
@@ -103955,30 +133679,21 @@
+ interrupts = <18 2>;
};
- memory-controller at 6000 {
- compatible = "fsl,mpc8572-memory-controller";
-- reg = <6000 1000>;
-+ reg = <0x6000 0x1000>;
- interrupt-parent = <&mpic>;
-- interrupts = <12 2>;
-+ interrupts = <18 2>;
- };
-
l2-cache-controller at 20000 {
- compatible = "fsl,mpc8572-l2-cache-controller";
+ compatible = "fsl,8544-l2-cache-controller";
- reg = <20000 1000>;
- cache-line-size = <20>; // 32 bytes
-- cache-size = <80000>; // L2, 512K
+- cache-size = <40000>; // L2, 256K
+ reg = <0x20000 0x1000>;
+ cache-line-size = <32>; // 32 bytes
-+ cache-size = <0x80000>; // L2, 512K
++ cache-size = <0x40000>; // L2, 256K
interrupt-parent = <&mpic>;
- interrupts = <10 2>;
+ interrupts = <16 2>;
};
i2c at 3000 {
-@@ -97,8 +98,8 @@
+@@ -79,8 +79,8 @@
#size-cells = <0>;
cell-index = <0>;
compatible = "fsl-i2c";
@@ -103989,7 +133704,7 @@
interrupt-parent = <&mpic>;
dfsrr;
};
-@@ -108,8 +109,8 @@
+@@ -90,8 +90,8 @@
#size-cells = <0>;
cell-index = <1>;
compatible = "fsl-i2c";
@@ -104000,7 +133715,7 @@
interrupt-parent = <&mpic>;
dfsrr;
};
-@@ -118,27 +119,27 @@
+@@ -100,30 +100,71 @@
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,gianfar-mdio";
@@ -104013,6 +133728,7 @@
- reg = <0>;
+ interrupts = <10 1>;
+ reg = <0x0>;
+ device_type = "ethernet-phy";
};
phy1: ethernet-phy at 1 {
interrupt-parent = <&mpic>;
@@ -104020,26 +133736,55 @@
- reg = <1>;
+ interrupts = <10 1>;
+ reg = <0x1>;
- };
- phy2: ethernet-phy at 2 {
- interrupt-parent = <&mpic>;
-- interrupts = <a 1>;
-- reg = <2>;
-+ interrupts = <10 1>;
-+ reg = <0x2>;
- };
- phy3: ethernet-phy at 3 {
- interrupt-parent = <&mpic>;
-- interrupts = <a 1>;
-- reg = <3>;
-+ interrupts = <10 1>;
-+ reg = <0x3>;
+ device_type = "ethernet-phy";
};
};
-@@ -147,9 +148,9 @@
++ dma at 21300 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "fsl,mpc8544-dma", "fsl,eloplus-dma";
++ reg = <0x21300 0x4>;
++ ranges = <0x0 0x21100 0x200>;
++ cell-index = <0>;
++ dma-channel at 0 {
++ compatible = "fsl,mpc8544-dma-channel",
++ "fsl,eloplus-dma-channel";
++ reg = <0x0 0x80>;
++ cell-index = <0>;
++ interrupt-parent = <&mpic>;
++ interrupts = <20 2>;
++ };
++ dma-channel at 80 {
++ compatible = "fsl,mpc8544-dma-channel",
++ "fsl,eloplus-dma-channel";
++ reg = <0x80 0x80>;
++ cell-index = <1>;
++ interrupt-parent = <&mpic>;
++ interrupts = <21 2>;
++ };
++ dma-channel at 100 {
++ compatible = "fsl,mpc8544-dma-channel",
++ "fsl,eloplus-dma-channel";
++ reg = <0x100 0x80>;
++ cell-index = <2>;
++ interrupt-parent = <&mpic>;
++ interrupts = <22 2>;
++ };
++ dma-channel at 180 {
++ compatible = "fsl,mpc8544-dma-channel",
++ "fsl,eloplus-dma-channel";
++ reg = <0x180 0x80>;
++ cell-index = <3>;
++ interrupt-parent = <&mpic>;
++ interrupts = <23 2>;
++ };
++ };
++
+ enet0: ethernet at 24000 {
+ cell-index = <0>;
device_type = "network";
- model = "eTSEC";
+ model = "TSEC";
compatible = "gianfar";
- reg = <24000 1000>;
+ reg = <0x24000 0x1000>;
@@ -104049,21 +133794,9 @@
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 @@
+@@ -134,9 +175,9 @@
device_type = "network";
- model = "eTSEC";
+ model = "TSEC";
compatible = "gianfar";
- reg = <26000 1000>;
+ reg = <0x26000 0x1000>;
@@ -104071,21 +133804,9 @@
- 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-handle = <&phy1>;
phy-connection-type = "rgmii-id";
-@@ -198,9 +199,9 @@
+@@ -146,9 +187,9 @@
cell-index = <0>;
device_type = "serial";
compatible = "ns16550";
@@ -104097,7 +133818,7 @@
interrupt-parent = <&mpic>;
};
-@@ -208,15 +209,15 @@
+@@ -156,15 +197,15 @@
cell-index = <1>;
device_type = "serial";
compatible = "ns16550";
@@ -104110,13 +133831,13 @@
};
global-utilities at e0000 { //global utilities block
- compatible = "fsl,mpc8572-guts";
+ compatible = "fsl,mpc8548-guts";
- reg = <e0000 1000>;
+ reg = <0xe0000 0x1000>;
fsl,has-rstcr;
};
-@@ -225,7 +226,7 @@
+@@ -173,7 +214,7 @@
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
@@ -104125,27 +133846,15 @@
compatible = "chrp,open-pic";
device_type = "open-pic";
big-endian;
-@@ -239,167 +240,167 @@
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- reg = <ffe08000 1000>;
-- bus-range = <0 ff>;
-- ranges = <02000000 0 80000000 80000000 0 20000000
-- 01000000 0 00000000 ffc00000 0 00010000>;
-- clock-frequency = <1fca055>;
-+ reg = <0xffe08000 0x1000>;
-+ bus-range = <0 255>;
-+ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
-+ 0x1000000 0x0 0x0 0xffc00000 0x0 0x10000>;
-+ clock-frequency = <33333333>;
- interrupt-parent = <&mpic>;
-- interrupts = <18 2>;
-- interrupt-map-mask = <ff00 0 0 7>;
-+ interrupts = <24 2>;
-+ interrupt-map-mask = <0xff00 0x0 0x0 0x7>;
+@@ -184,32 +225,32 @@
+ cell-index = <0>;
+ compatible = "fsl,mpc8540-pci";
+ device_type = "pci";
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
- /* IDSEL 0x11 func 0 - PCI slot 1 */
+
+ /* 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
@@ -104155,156 +133864,160 @@
+ 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 J16 Slot 2 */
- /* 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
+- 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 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
++ 0x9000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x9000 0x0 0x0 0x4 &mpic 0x1 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
+ interrupt-parent = <&mpic>;
+- interrupts = <18 2>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 c0000000 c0000000 0 20000000
+- 01000000 0 00000000 e1000000 0 00010000>;
+- clock-frequency = <3f940aa>;
++ interrupts = <24 2>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0xc0000000 0xc0000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xe1000000 0x0 0x10000>;
++ clock-frequency = <66666666>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0008000 1000>;
++ reg = <0xe0008000 0x1000>;
+ };
- /* 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
+ pci1: pcie at e0009000 {
+@@ -219,33 +260,33 @@
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0009000 1000>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 80000000 80000000 0 20000000
+- 01000000 0 00000000 e1010000 0 00010000>;
+- clock-frequency = <1fca055>;
++ reg = <0xe0009000 0x1000>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xe1010000 0x0 0x10000>;
++ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+- interrupts = <1a 2>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupts = <26 2>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+- 0000 0 0 1 &mpic 4 1
+- 0000 0 0 2 &mpic 5 1
+- 0000 0 0 3 &mpic 6 1
+- 0000 0 0 4 &mpic 7 1
++ 0000 0x0 0x0 0x1 &mpic 0x4 0x1
++ 0000 0x0 0x0 0x2 &mpic 0x5 0x1
++ 0000 0x0 0x0 0x3 &mpic 0x6 0x1
++ 0000 0x0 0x0 0x4 &mpic 0x7 0x1
+ >;
+ pcie at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+- ranges = <02000000 0 80000000
+- 02000000 0 80000000
+- 0 20000000
++ ranges = <0x2000000 0x0 0x80000000
++ 0x2000000 0x0 0x80000000
++ 0x0 0x20000000
- /* 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
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00010000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x10000>;
+ };
+ };
- /* 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
+@@ -256,33 +297,33 @@
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e000a000 1000>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 a0000000 a0000000 0 10000000
+- 01000000 0 00000000 e1020000 0 00010000>;
+- clock-frequency = <1fca055>;
++ reg = <0xe000a000 0x1000>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
++ 0x1000000 0x0 0x0 0xe1020000 0x0 0x10000>;
++ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+- interrupts = <19 2>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupts = <25 2>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+- 0000 0 0 1 &mpic 0 1
+- 0000 0 0 2 &mpic 1 1
+- 0000 0 0 3 &mpic 2 1
+- 0000 0 0 4 &mpic 3 1
++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1
+ >;
+ pcie at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+- ranges = <02000000 0 a0000000
+- 02000000 0 a0000000
+- 0 10000000
++ ranges = <0x2000000 0x0 0xa0000000
++ 0x2000000 0x0 0xa0000000
++ 0x0 0x10000000
- /* 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
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00010000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x10000>;
+ };
+ };
+@@ -293,72 +334,72 @@
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e000b000 1000>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 b0000000 b0000000 0 00100000
+- 01000000 0 00000000 b0100000 0 00100000>;
+- clock-frequency = <1fca055>;
++ reg = <0xe000b000 0x1000>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0xb0000000 0xb0000000 0x0 0x100000
++ 0x1000000 0x0 0x0 0xb0100000 0x0 0x100000>;
++ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+- interrupts = <1b 2>;
+- interrupt-map-mask = <ff00 0 0 1>;
++ interrupts = <27 2>;
++ interrupt-map-mask = <0xff00 0x0 0x0 0x1>;
+ interrupt-map = <
// IDSEL 0x1c USB
- e000 0 0 1 &i8259 c 2
- e100 0 0 2 &i8259 9 2
@@ -104330,8 +134043,7 @@
- f900 0 0 1 &i8259 5 2
+ 0xf800 0x0 0x0 0x1 &i8259 0xe 0x2
+ 0xf900 0x0 0x0 0x1 &i8259 0x5 0x2
-
- >;
+ >;
pcie at 0 {
- reg = <0 0 0 0 0>;
@@ -104339,12 +134051,12 @@
#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
+- ranges = <02000000 0 b0000000
+- 02000000 0 b0000000
+- 0 00100000
++ ranges = <0x2000000 0x0 0xb0000000
++ 0x2000000 0x0 0xb0000000
++ 0x0 0x100000
- 01000000 0 00000000
- 01000000 0 00000000
@@ -104352,17 +134064,18 @@
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+
uli1575 at 0 {
- reg = <0 0 0 0 0>;
+ reg = <0x0 0x0 0x0 0x0 0x0>;
#size-cells = <2>;
#address-cells = <3>;
-- ranges = <02000000 0 80000000
-- 02000000 0 80000000
-- 0 20000000
-+ ranges = <0x2000000 0x0 0x80000000
-+ 0x2000000 0x0 0x80000000
-+ 0x0 0x20000000
+- ranges = <02000000 0 b0000000
+- 02000000 0 b0000000
+- 0 00100000
++ ranges = <0x2000000 0x0 0xb0000000
++ 0x2000000 0x0 0xb0000000
++ 0x0 0x100000
- 01000000 0 00000000
- 01000000 0 00000000
@@ -104376,10 +134089,12 @@
#size-cells = <1>;
#address-cells = <2>;
- reg = <f000 0 0 0 0>;
-- ranges = <1 0 01000000 0 0
+- ranges = <1 0
+- 01000000 0 0
- 00001000>;
+ reg = <0xf000 0x0 0x0 0x0 0x0>;
-+ ranges = <0x1 0x0 0x1000000 0x0 0x0
++ ranges = <0x1 0x0
++ 0x1000000 0x0 0x0
+ 0x1000>;
interrupt-parent = <&i8259>;
@@ -104393,7 +134108,7 @@
interrupt-controller;
device_type = "interrupt-controller";
#address-cells = <0>;
-@@ -412,29 +413,29 @@
+@@ -371,28 +412,28 @@
i8042 at 60 {
#size-cells = <0>;
#address-cells = <1>;
@@ -104401,8 +134116,7 @@
- interrupts = <1 3 c 3>;
+ reg = <0x1 0x60 0x1 0x1 0x64 0x1>;
+ interrupts = <1 3 12 3>;
- interrupt-parent =
- <&i8259>;
+ interrupt-parent = <&i8259>;
keyboard at 0 {
- reg = <0>;
@@ -104429,1361 +134143,3043 @@
};
};
};
-@@ -449,33 +450,33 @@
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- reg = <ffe09000 1000>;
-- bus-range = <0 ff>;
-- ranges = <02000000 0 a0000000 a0000000 0 20000000
-- 01000000 0 00000000 ffc10000 0 00010000>;
-- clock-frequency = <1fca055>;
-+ reg = <0xffe09000 0x1000>;
-+ bus-range = <0 255>;
-+ ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
-+ 0x1000000 0x0 0x0 0xffc10000 0x0 0x10000>;
-+ clock-frequency = <33333333>;
- interrupt-parent = <&mpic>;
-- interrupts = <1a 2>;
-- interrupt-map-mask = <f800 0 0 7>;
-+ interrupts = <26 2>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
- /* IDSEL 0x0 */
-- 0000 0 0 1 &mpic 4 1
-- 0000 0 0 2 &mpic 5 1
-- 0000 0 0 3 &mpic 6 1
-- 0000 0 0 4 &mpic 7 1
-+ 0000 0x0 0x0 0x1 &mpic 0x4 0x1
-+ 0000 0x0 0x0 0x2 &mpic 0x5 0x1
-+ 0000 0x0 0x0 0x3 &mpic 0x6 0x1
-+ 0000 0x0 0x0 0x4 &mpic 0x7 0x1
- >;
- pcie at 0 {
-- reg = <0 0 0 0 0>;
-+ reg = <0x0 0x0 0x0 0x0 0x0>;
- #size-cells = <2>;
- #address-cells = <3>;
- device_type = "pci";
-- ranges = <02000000 0 a0000000
-- 02000000 0 a0000000
-- 0 20000000
-+ ranges = <0x2000000 0x0 0xa0000000
-+ 0x2000000 0x0 0xa0000000
-+ 0x0 0x20000000
-
-- 01000000 0 00000000
-- 01000000 0 00000000
-- 0 00100000>;
-+ 0x1000000 0x0 0x0
-+ 0x1000000 0x0 0x0
-+ 0x0 0x100000>;
- };
- };
-
-@@ -486,33 +487,33 @@
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- reg = <ffe0a000 1000>;
-- bus-range = <0 ff>;
-- ranges = <02000000 0 c0000000 c0000000 0 20000000
-- 01000000 0 00000000 ffc20000 0 00010000>;
-- clock-frequency = <1fca055>;
-+ reg = <0xffe0a000 0x1000>;
-+ bus-range = <0 255>;
-+ ranges = <0x2000000 0x0 0xc0000000 0xc0000000 0x0 0x20000000
-+ 0x1000000 0x0 0x0 0xffc20000 0x0 0x10000>;
-+ clock-frequency = <33333333>;
- interrupt-parent = <&mpic>;
-- interrupts = <1b 2>;
-- interrupt-map-mask = <f800 0 0 7>;
-+ interrupts = <27 2>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
- /* IDSEL 0x0 */
-- 0000 0 0 1 &mpic 0 1
-- 0000 0 0 2 &mpic 1 1
-- 0000 0 0 3 &mpic 2 1
-- 0000 0 0 4 &mpic 3 1
-+ 0000 0x0 0x0 0x1 &mpic 0x0 0x1
-+ 0000 0x0 0x0 0x2 &mpic 0x1 0x1
-+ 0000 0x0 0x0 0x3 &mpic 0x2 0x1
-+ 0000 0x0 0x0 0x4 &mpic 0x3 0x1
- >;
- pcie at 0 {
-- reg = <0 0 0 0 0>;
-+ reg = <0x0 0x0 0x0 0x0 0x0>;
- #size-cells = <2>;
- #address-cells = <3>;
- device_type = "pci";
-- ranges = <02000000 0 c0000000
-- 02000000 0 c0000000
-- 0 20000000
-+ ranges = <0x2000000 0x0 0xc0000000
-+ 0x2000000 0x0 0xc0000000
-+ 0x0 0x20000000
-
-- 01000000 0 00000000
-- 01000000 0 00000000
-- 0 00100000>;
-+ 0x1000000 0x0 0x0
-+ 0x1000000 0x0 0x0
-+ 0x0 0x100000>;
- };
- };
- };
-diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
-index 79385bc..7f9b999 100644
---- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts
-+++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
-@@ -13,7 +13,7 @@
-
- / {
- model = "MPC8641HPCN";
-- compatible = "mpc86xx";
-+ compatible = "fsl,mpc8641hpcn";
- #address-cells = <1>;
- #size-cells = <1>;
-
-diff --git a/arch/powerpc/boot/dts/mpc866ads.dts b/arch/powerpc/boot/dts/mpc866ads.dts
-index daf9433..765e43c 100644
---- a/arch/powerpc/boot/dts/mpc866ads.dts
-+++ b/arch/powerpc/boot/dts/mpc866ads.dts
-@@ -2,6 +2,7 @@
- * MPC866 ADS Device Tree Source
+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 MontaVista Software, Inc.
-+ * Copyright 2008 Freescale Semiconductor, Inc.
+- * 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 +10,7 @@
+@@ -9,6 +9,7 @@
* option) any later version.
*/
+/dts-v1/;
/ {
- model = "MPC866ADS";
-@@ -22,37 +24,37 @@
+ model = "MPC8548CDS";
+@@ -36,11 +37,11 @@
- PowerPC,866 at 0 {
+ PowerPC,8548 at 0 {
device_type = "cpu";
- reg = <0>;
-- d-cache-line-size = <10>; // 16 bytes
-- i-cache-line-size = <10>; // 16 bytes
-- d-cache-size = <2000>; // L1, 8K
-- i-cache-size = <4000>; // L1, 16K
+- 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 = <16>; // 16 bytes
-+ i-cache-line-size = <16>; // 16 bytes
-+ d-cache-size = <0x2000>; // L1, 8K
-+ i-cache-size = <0x4000>; // L1, 16K
- timebase-frequency = <0>;
- bus-frequency = <0>;
- clock-frequency = <0>;
-- interrupts = <f 2>; // decrementer interrupt
-+ interrupts = <15 2>; // decrementer interrupt
- interrupt-parent = <&PIC>;
- };
- };
++ 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 800000>;
-+ reg = <0x0 0x800000>;
+- reg = <00000000 08000000>; // 128M at 0x0
++ reg = <0x0 0x8000000>; // 128M at 0x0
};
- localbus at ff000100 {
- compatible = "fsl,mpc866-localbus", "fsl,pq1-localbus";
- #address-cells = <2>;
- #size-cells = <1>;
-- reg = <ff000100 40>;
-+ reg = <0xff000100 0x40>;
-
- ranges = <
-- 1 0 ff080000 00008000
-- 5 0 ff0a0000 00008000
-+ 0x1 0x0 0xff080000 0x8000
-+ 0x5 0x0 0xff0a0000 0x8000
- >;
-
- board-control at 1,0 {
-- reg = <1 0 20 5 300 4>;
-+ reg = <0x1 0x0 0x20 0x5 0x300 0x4>;
- compatible = "fsl,mpc866ads-bcsr";
- };
- };
-@@ -61,17 +63,17 @@
+ soc8548 at e0000000 {
#address-cells = <1>;
#size-cells = <1>;
device_type = "soc";
-- ranges = <0 ff000000 00100000>;
-- reg = <ff000000 00000200>;
-+ ranges = <0x0 0xff000000 0x100000>;
-+ reg = <0xff000000 0x200>;
+- ranges = <00000000 e0000000 00100000>;
+- reg = <e0000000 00001000>; // CCSRBAR
++ ranges = <0x0 0xe0000000 0x100000>;
++ reg = <0xe0000000 0x1000>; // CCSRBAR
bus-frequency = <0>;
- mdio at e00 {
- compatible = "fsl,mpc866-fec-mdio", "fsl,pq1-fec-mdio";
-- reg = <e00 188>;
-+ reg = <0xe00 0x188>;
+ memory-controller at 2000 {
+ compatible = "fsl,8548-memory-controller";
+- reg = <2000 1000>;
++ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+- interrupts = <12 2>;
++ interrupts = <18 2>;
+ };
+
+ l2-cache-controller at 20000 {
+ compatible = "fsl,8548-l2-cache-controller";
+- reg = <20000 1000>;
+- cache-line-size = <20>; // 32 bytes
+- cache-size = <80000>; // L2, 512K
++ reg = <0x20000 0x1000>;
++ cache-line-size = <32>; // 32 bytes
++ cache-size = <0x80000>; // L2, 512K
+ interrupt-parent = <&mpic>;
+- interrupts = <10 2>;
++ interrupts = <16 2>;
+ };
+
+ i2c at 3000 {
+@@ -81,8 +82,8 @@
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+- reg = <3000 100>;
+- interrupts = <2b 2>;
++ reg = <0x3000 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+@@ -92,8 +93,8 @@
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+- reg = <3100 100>;
+- interrupts = <2b 2>;
++ reg = <0x3100 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+@@ -102,30 +103,30 @@
#address-cells = <1>;
#size-cells = <0>;
- PHY: ethernet-phy at f {
-- reg = <f>;
-+ reg = <0xf>;
+ compatible = "fsl,gianfar-mdio";
+- reg = <24520 20>;
++ reg = <0x24520 0x20>;
+
+ phy0: ethernet-phy at 0 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <0>;
++ reg = <0x0>;
+ device_type = "ethernet-phy";
+ };
+ phy1: ethernet-phy at 1 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <1>;
++ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+ phy2: ethernet-phy at 2 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <2>;
++ reg = <0x2>;
+ device_type = "ethernet-phy";
+ };
+ phy3: ethernet-phy at 3 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <3>;
++ reg = <0x3>;
device_type = "ethernet-phy";
};
};
-@@ -80,7 +82,7 @@
+@@ -135,9 +136,9 @@
device_type = "network";
- compatible = "fsl,mpc866-fec-enet",
- "fsl,pq1-fec-enet";
-- reg = <e00 188>;
-+ reg = <0xe00 0x188>;
+ model = "eTSEC";
+ compatible = "gianfar";
+- reg = <24000 1000>;
++ reg = <0x24000 0x1000>;
local-mac-address = [ 00 00 00 00 00 00 ];
- interrupts = <3 1>;
- interrupt-parent = <&PIC>;
-@@ -91,7 +93,7 @@
- PIC: pic at 0 {
+- interrupts = <1d 2 1e 2 22 2>;
++ interrupts = <29 2 30 2 34 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy0>;
+ };
+@@ -147,9 +148,9 @@
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+- reg = <25000 1000>;
++ reg = <0x25000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <23 2 24 2 28 2>;
++ interrupts = <35 2 36 2 40 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy1>;
+ };
+@@ -160,9 +161,9 @@
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+- reg = <26000 1000>;
++ reg = <0x26000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1f 2 20 2 21 2>;
++ interrupts = <31 2 32 2 33 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy2>;
+ };
+@@ -172,9 +173,9 @@
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+- reg = <27000 1000>;
++ reg = <0x27000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <25 2 26 2 27 2>;
++ interrupts = <37 2 38 2 39 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy3>;
+ };
+@@ -184,9 +185,9 @@
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4500 100>; // reg base, size
++ reg = <0x4500 0x100>; // reg base, size
+ clock-frequency = <0>; // should we fill in in uboot?
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -194,15 +195,15 @@
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4600 100>; // reg base, size
++ reg = <0x4600 0x100>; // reg base, size
+ clock-frequency = <0>; // should we fill in in uboot?
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ global-utilities at e0000 { //global utilities reg
+ compatible = "fsl,mpc8548-guts";
+- reg = <e0000 1000>;
++ reg = <0xe0000 0x1000>;
+ fsl,has-rstcr;
+ };
+
+@@ -211,7 +212,7 @@
interrupt-controller;
+ #address-cells = <0>;
#interrupt-cells = <2>;
-- reg = <0 24>;
-+ reg = <0x0 0x24>;
- compatible = "fsl,mpc866-pic", "fsl,pq1-pic";
- };
+- reg = <40000 40000>;
++ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ big-endian;
+@@ -220,139 +221,139 @@
-@@ -100,7 +102,7 @@
- #size-cells = <1>;
- compatible = "fsl,mpc866-cpm", "fsl,cpm1";
- ranges;
-- reg = <9c0 40>;
-+ reg = <0x9c0 0x40>;
- brg-frequency = <0>;
- interrupts = <0 2>; // cpm error interrupt
- interrupt-parent = <&CPM_PIC>;
-@@ -108,11 +110,11 @@
- muram at 2000 {
- #address-cells = <1>;
+ pci0: pci at e0008000 {
+ cell-index = <0>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x4 (PCIX Slot 2) */
+- 02000 0 0 1 &mpic 0 1
+- 02000 0 0 2 &mpic 1 1
+- 02000 0 0 3 &mpic 2 1
+- 02000 0 0 4 &mpic 3 1
++ 0x2000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x2000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x2000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x2000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x5 (PCIX Slot 3) */
+- 02800 0 0 1 &mpic 1 1
+- 02800 0 0 2 &mpic 2 1
+- 02800 0 0 3 &mpic 3 1
+- 02800 0 0 4 &mpic 0 1
++ 0x2800 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0x2800 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0x2800 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x2800 0x0 0x0 0x4 &mpic 0x0 0x1
+
+ /* IDSEL 0x6 (PCIX Slot 4) */
+- 03000 0 0 1 &mpic 2 1
+- 03000 0 0 2 &mpic 3 1
+- 03000 0 0 3 &mpic 0 1
+- 03000 0 0 4 &mpic 1 1
++ 0x3000 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x3000 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x3000 0x0 0x0 0x3 &mpic 0x0 0x1
++ 0x3000 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x8 (PCIX Slot 5) */
+- 04000 0 0 1 &mpic 0 1
+- 04000 0 0 2 &mpic 1 1
+- 04000 0 0 3 &mpic 2 1
+- 04000 0 0 4 &mpic 3 1
++ 0x4000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x4000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x4000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x4000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0xC (Tsi310 bridge) */
+- 06000 0 0 1 &mpic 0 1
+- 06000 0 0 2 &mpic 1 1
+- 06000 0 0 3 &mpic 2 1
+- 06000 0 0 4 &mpic 3 1
++ 0x6000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x6000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x6000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x6000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x14 (Slot 2) */
+- 0a000 0 0 1 &mpic 0 1
+- 0a000 0 0 2 &mpic 1 1
+- 0a000 0 0 3 &mpic 2 1
+- 0a000 0 0 4 &mpic 3 1
++ 0xa000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0xa000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0xa000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0xa000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x15 (Slot 3) */
+- 0a800 0 0 1 &mpic 1 1
+- 0a800 0 0 2 &mpic 2 1
+- 0a800 0 0 3 &mpic 3 1
+- 0a800 0 0 4 &mpic 0 1
++ 0xa800 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0xa800 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0xa800 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0xa800 0x0 0x0 0x4 &mpic 0x0 0x1
+
+ /* IDSEL 0x16 (Slot 4) */
+- 0b000 0 0 1 &mpic 2 1
+- 0b000 0 0 2 &mpic 3 1
+- 0b000 0 0 3 &mpic 0 1
+- 0b000 0 0 4 &mpic 1 1
++ 0xb000 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0xb000 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0xb000 0x0 0x0 0x3 &mpic 0x0 0x1
++ 0xb000 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x18 (Slot 5) */
+- 0c000 0 0 1 &mpic 0 1
+- 0c000 0 0 2 &mpic 1 1
+- 0c000 0 0 3 &mpic 2 1
+- 0c000 0 0 4 &mpic 3 1
++ 0xc000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0xc000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0xc000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0xc000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x1C (Tsi310 bridge PCI primary) */
+- 0E000 0 0 1 &mpic 0 1
+- 0E000 0 0 2 &mpic 1 1
+- 0E000 0 0 3 &mpic 2 1
+- 0E000 0 0 4 &mpic 3 1>;
++ 0xe000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0xe000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0xe000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0xe000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+
+ interrupt-parent = <&mpic>;
+- interrupts = <18 2>;
++ interrupts = <24 2>;
+ bus-range = <0 0>;
+- ranges = <02000000 0 80000000 80000000 0 10000000
+- 01000000 0 00000000 e2000000 0 00800000>;
+- clock-frequency = <3f940aa>;
++ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x10000000
++ 0x1000000 0x0 0x0 0xe2000000 0x0 0x800000>;
++ clock-frequency = <66666666>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0008000 1000>;
++ reg = <0xe0008000 0x1000>;
+ compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci";
+ device_type = "pci";
+
+ pci_bridge at 1c {
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x00 (PrPMC Site) */
+- 0000 0 0 1 &mpic 0 1
+- 0000 0 0 2 &mpic 1 1
+- 0000 0 0 3 &mpic 2 1
+- 0000 0 0 4 &mpic 3 1
++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x04 (VIA chip) */
+- 2000 0 0 1 &mpic 0 1
+- 2000 0 0 2 &mpic 1 1
+- 2000 0 0 3 &mpic 2 1
+- 2000 0 0 4 &mpic 3 1
++ 0x2000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x2000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x2000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x2000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x05 (8139) */
+- 2800 0 0 1 &mpic 1 1
++ 0x2800 0x0 0x0 0x1 &mpic 0x1 0x1
+
+ /* IDSEL 0x06 (Slot 6) */
+- 3000 0 0 1 &mpic 2 1
+- 3000 0 0 2 &mpic 3 1
+- 3000 0 0 3 &mpic 0 1
+- 3000 0 0 4 &mpic 1 1
++ 0x3000 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x3000 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x3000 0x0 0x0 0x3 &mpic 0x0 0x1
++ 0x3000 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDESL 0x07 (Slot 7) */
+- 3800 0 0 1 &mpic 3 1
+- 3800 0 0 2 &mpic 0 1
+- 3800 0 0 3 &mpic 1 1
+- 3800 0 0 4 &mpic 2 1>;
++ 0x3800 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x3800 0x0 0x0 0x2 &mpic 0x0 0x1
++ 0x3800 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x3800 0x0 0x0 0x4 &mpic 0x2 0x1>;
+
+- reg = <e000 0 0 0 0>;
++ reg = <0xe000 0x0 0x0 0x0 0x0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- ranges = <02000000 0 80000000
+- 02000000 0 80000000
+- 0 20000000
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00080000>;
+- clock-frequency = <1fca055>;
++ ranges = <0x2000000 0x0 0x80000000
++ 0x2000000 0x0 0x80000000
++ 0x0 0x20000000
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x80000>;
++ clock-frequency = <33333333>;
+
+ isa at 4 {
+ device_type = "isa";
+ #interrupt-cells = <2>;
#size-cells = <1>;
-- ranges = <0 2000 2000>;
-+ ranges = <0x0 0x2000 0x2000>;
+ #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>;
- data at 0 {
- compatible = "fsl,cpm-muram-data";
-- reg = <0 1c00>;
-+ reg = <0x0 0x1c00>;
+ i8259: interrupt-controller at 20 {
+ interrupt-controller;
+ device_type = "interrupt-controller";
+- reg = <1 20 2
+- 1 a0 2
+- 1 4d0 2>;
++ reg = <0x1 0x20 0x2
++ 0x1 0xa0 0x2
++ 0x1 0x4d0 0x2>;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ compatible = "chrp,iic";
+@@ -362,7 +363,7 @@
+
+ rtc at 70 {
+ compatible = "pnpPNP,b00";
+- reg = <1 70 2>;
++ reg = <0x1 0x70 0x2>;
};
};
+ };
+@@ -370,64 +371,64 @@
-@@ -120,7 +122,7 @@
- compatible = "fsl,mpc866-brg",
- "fsl,cpm1-brg",
- "fsl,cpm-brg";
-- reg = <9f0 10>;
-+ reg = <0x9f0 0x10>;
- clock-frequency = <0>;
- };
+ pci1: pci at e0009000 {
+ cell-index = <1>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
-@@ -130,7 +132,7 @@
- #interrupt-cells = <1>;
- interrupts = <5 2 0 2>;
- interrupt-parent = <&PIC>;
-- reg = <930 20>;
-+ reg = <0x930 0x20>;
- compatible = "fsl,mpc866-cpm-pic",
- "fsl,cpm1-pic";
- };
-@@ -140,31 +142,31 @@
- device_type = "serial";
- compatible = "fsl,mpc866-smc-uart",
- "fsl,cpm1-smc-uart";
-- reg = <a80 10 3e80 40>;
-+ reg = <0xa80 0x10 0x3e80 0x40>;
- interrupts = <4>;
- interrupt-parent = <&CPM_PIC>;
- fsl,cpm-brg = <1>;
-- fsl,cpm-command = <0090>;
-+ fsl,cpm-command = <0x90>;
- };
+ /* 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>;
- serial at a90 {
- device_type = "serial";
- compatible = "fsl,mpc866-smc-uart",
- "fsl,cpm1-smc-uart";
-- reg = <a90 10 3f80 40>;
-+ reg = <0xa90 0x10 0x3f80 0x40>;
- interrupts = <3>;
- interrupt-parent = <&CPM_PIC>;
- fsl,cpm-brg = <2>;
-- fsl,cpm-command = <00d0>;
-+ fsl,cpm-command = <0xd0>;
- };
+ interrupt-parent = <&mpic>;
+- interrupts = <19 2>;
++ interrupts = <25 2>;
+ bus-range = <0 0>;
+- ranges = <02000000 0 90000000 90000000 0 10000000
+- 01000000 0 00000000 e2800000 0 00800000>;
+- clock-frequency = <3f940aa>;
++ ranges = <0x2000000 0x0 0x90000000 0x90000000 0x0 0x10000000
++ 0x1000000 0x0 0x0 0xe2800000 0x0 0x800000>;
++ clock-frequency = <66666666>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0009000 1000>;
++ reg = <0xe0009000 0x1000>;
+ compatible = "fsl,mpc8540-pci";
+ device_type = "pci";
+ };
- ethernet at a00 {
- device_type = "network";
- compatible = "fsl,mpc866-scc-enet",
- "fsl,cpm1-scc-enet";
-- reg = <a00 18 3c00 100>;
-+ reg = <0xa00 0x18 0x3c00 0x100>;
- local-mac-address = [ 00 00 00 00 00 00 ];
-- interrupts = <1e>;
-+ interrupts = <30>;
- interrupt-parent = <&CPM_PIC>;
- fsl,cpm-command = <0000>;
- linux,network-index = <1>;
-diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts
-index d84a012..9895043 100644
---- a/arch/powerpc/boot/dts/mpc885ads.dts
-+++ b/arch/powerpc/boot/dts/mpc885ads.dts
-@@ -2,7 +2,7 @@
- * MPC885 ADS Device Tree Source
+ pci2: pcie at e000a000 {
+ cell-index = <2>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x0 (PEX) */
+- 00000 0 0 1 &mpic 0 1
+- 00000 0 0 2 &mpic 1 1
+- 00000 0 0 3 &mpic 2 1
+- 00000 0 0 4 &mpic 3 1>;
++ 00000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 00000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 00000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 00000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+
+ interrupt-parent = <&mpic>;
+- interrupts = <1a 2>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 a0000000 a0000000 0 20000000
+- 01000000 0 00000000 e3000000 0 08000000>;
+- clock-frequency = <1fca055>;
++ interrupts = <26 2>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xe3000000 0x0 0x8000000>;
++ clock-frequency = <33333333>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e000a000 1000>;
++ reg = <0xe000a000 0x1000>;
+ compatible = "fsl,mpc8548-pcie";
+ device_type = "pci";
+ pcie at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+- ranges = <02000000 0 a0000000
+- 02000000 0 a0000000
+- 0 20000000
++ ranges = <0x2000000 0x0 0xa0000000
++ 0x2000000 0x0 0xa0000000
++ 0x0 0x20000000
+
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 08000000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x8000000>;
+ };
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts
+index 4538f3c..b025c56 100644
+--- a/arch/powerpc/boot/dts/mpc8555cds.dts
++++ b/arch/powerpc/boot/dts/mpc8555cds.dts
+@@ -1,7 +1,7 @@
+ /*
+ * MPC8555 CDS Device Tree Source
*
- * Copyright 2006 MontaVista Software, Inc.
-- * Copyright 2007 Freescale Semiconductor, Inc.
-+ * Copyright 2007,2008 Freescale Semiconductor, Inc.
+- * 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
-@@ -10,6 +10,7 @@
+@@ -9,6 +9,7 @@
* option) any later version.
*/
+/dts-v1/;
/ {
- model = "MPC885ADS";
-@@ -23,45 +24,45 @@
+ model = "MPC8555CDS";
+@@ -31,11 +32,11 @@
- PowerPC,885 at 0 {
+ PowerPC,8555 at 0 {
device_type = "cpu";
- reg = <0>;
-- d-cache-line-size = <d#16>;
-- i-cache-line-size = <d#16>;
-- d-cache-size = <d#8192>;
-- i-cache-size = <d#8192>;
+- 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 = <16>;
-+ i-cache-line-size = <16>;
-+ d-cache-size = <8192>;
-+ i-cache-size = <8192>;
- timebase-frequency = <0>;
- bus-frequency = <0>;
- clock-frequency = <0>;
-- interrupts = <f 2>; // decrementer interrupt
-+ interrupts = <15 2>; // decrementer interrupt
- interrupt-parent = <&PIC>;
- };
- };
++ 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 = <0 0>;
-+ reg = <0x0 0x0>;
+- reg = <00000000 08000000>; // 128M at 0x0
++ reg = <0x0 0x8000000>; // 128M at 0x0
};
- localbus at ff000100 {
- compatible = "fsl,mpc885-localbus", "fsl,pq1-localbus";
- #address-cells = <2>;
- #size-cells = <1>;
-- reg = <ff000100 40>;
-+ reg = <0xff000100 0x40>;
-
- ranges = <
-- 0 0 fe000000 00800000
-- 1 0 ff080000 00008000
-- 5 0 ff0a0000 00008000
-+ 0x0 0x0 0xfe000000 0x800000
-+ 0x1 0x0 0xff080000 0x8000
-+ 0x5 0x0 0xff0a0000 0x8000
- >;
-
- flash at 0,0 {
- compatible = "jedec-flash";
-- reg = <0 0 800000>;
-+ reg = <0x0 0x0 0x800000>;
- bank-width = <4>;
- device-width = <1>;
- };
-
- board-control at 1,0 {
-- reg = <1 0 20 5 300 4>;
-+ reg = <0x1 0x0 0x20 0x5 0x300 0x4>;
- compatible = "fsl,mpc885ads-bcsr";
- };
- };
-@@ -71,30 +72,30 @@
+ soc8555 at e0000000 {
#address-cells = <1>;
#size-cells = <1>;
device_type = "soc";
-- ranges = <0 ff000000 00004000>;
-+ ranges = <0x0 0xff000000 0x4000>;
+- ranges = <0 e0000000 00100000>;
+- reg = <e0000000 00001000>; // CCSRBAR 1M
++ ranges = <0x0 0xe0000000 0x100000>;
++ reg = <0xe0000000 0x1000>; // CCSRBAR 1M
bus-frequency = <0>;
- // Temporary -- will go away once kernel uses ranges for get_immrbase().
-- reg = <ff000000 4000>;
-+ reg = <0xff000000 0x4000>;
+ memory-controller at 2000 {
+ compatible = "fsl,8555-memory-controller";
+- reg = <2000 1000>;
++ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+- interrupts = <12 2>;
++ interrupts = <18 2>;
+ };
- mdio at e00 {
- compatible = "fsl,mpc885-fec-mdio", "fsl,pq1-fec-mdio";
-- reg = <e00 188>;
-+ reg = <0xe00 0x188>;
+ l2-cache-controller at 20000 {
+ compatible = "fsl,8555-l2-cache-controller";
+- reg = <20000 1000>;
+- cache-line-size = <20>; // 32 bytes
+- cache-size = <40000>; // L2, 256K
++ reg = <0x20000 0x1000>;
++ cache-line-size = <32>; // 32 bytes
++ cache-size = <0x40000>; // L2, 256K
+ interrupt-parent = <&mpic>;
+- interrupts = <10 2>;
++ interrupts = <16 2>;
+ };
+
+ i2c at 3000 {
+@@ -76,8 +77,8 @@
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+- reg = <3000 100>;
+- interrupts = <2b 2>;
++ reg = <0x3000 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+@@ -86,18 +87,18 @@
#address-cells = <1>;
#size-cells = <0>;
+ compatible = "fsl,gianfar-mdio";
+- reg = <24520 20>;
++ reg = <0x24520 0x20>;
- PHY0: ethernet-phy at 0 {
+ phy0: ethernet-phy at 0 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
- reg = <0>;
+ reg = <0x0>;
device_type = "ethernet-phy";
};
-
- PHY1: ethernet-phy at 1 {
+ phy1: ethernet-phy at 1 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
- reg = <1>;
+ reg = <0x1>;
device_type = "ethernet-phy";
};
-
- PHY2: ethernet-phy at 2 {
-- reg = <2>;
-+ reg = <0x2>;
- device_type = "ethernet-phy";
- };
};
-@@ -103,7 +104,7 @@
+@@ -107,9 +108,9 @@
device_type = "network";
- compatible = "fsl,mpc885-fec-enet",
- "fsl,pq1-fec-enet";
-- reg = <e00 188>;
-+ reg = <0xe00 0x188>;
+ model = "TSEC";
+ compatible = "gianfar";
+- reg = <24000 1000>;
++ reg = <0x24000 0x1000>;
local-mac-address = [ 00 00 00 00 00 00 ];
- interrupts = <3 1>;
- interrupt-parent = <&PIC>;
-@@ -115,7 +116,7 @@
+- 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";
- compatible = "fsl,mpc885-fec-enet",
- "fsl,pq1-fec-enet";
-- reg = <1e00 188>;
-+ reg = <0x1e00 0x188>;
+ model = "TSEC";
+ compatible = "gianfar";
+- reg = <25000 1000>;
++ reg = <0x25000 0x1000>;
local-mac-address = [ 00 00 00 00 00 00 ];
- interrupts = <7 1>;
- interrupt-parent = <&PIC>;
-@@ -126,7 +127,7 @@
- PIC: interrupt-controller at 0 {
- interrupt-controller;
- #interrupt-cells = <2>;
-- reg = <0 24>;
-+ reg = <0x0 0x24>;
- compatible = "fsl,mpc885-pic", "fsl,pq1-pic";
+- 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>;
};
-@@ -136,29 +137,29 @@
- #size-cells = <2>;
- compatible = "fsl,pq-pcmcia";
- device_type = "pcmcia";
-- reg = <80 80>;
-+ reg = <0x80 0x80>;
- interrupt-parent = <&PIC>;
-- interrupts = <d 1>;
-+ interrupts = <13 1>;
+@@ -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>;
};
- cpm at 9c0 {
+@@ -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,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>;
+ compatible = "fsl,mpc8555-cpm", "fsl,cpm2";
+- reg = <919c0 30>;
++ reg = <0x919c0 0x30>;
ranges;
- muram at 2000 {
+ muram at 80000 {
#address-cells = <1>;
#size-cells = <1>;
-- ranges = <0 2000 2000>;
-+ ranges = <0x0 0x2000 0x2000>;
+- ranges = <0 80000 10000>;
++ ranges = <0x0 0x80000 0x10000>;
data at 0 {
compatible = "fsl,cpm-muram-data";
-- reg = <0 1c00>;
-+ reg = <0x0 0x1c00>;
+- reg = <0 2000 9000 1000>;
++ reg = <0x0 0x2000 0x9000 0x1000>;
};
};
-@@ -167,7 +168,7 @@
- "fsl,cpm1-brg",
+@@ -179,16 +180,16 @@
+ compatible = "fsl,mpc8555-brg",
+ "fsl,cpm2-brg",
"fsl,cpm-brg";
- clock-frequency = <0>;
-- reg = <9f0 10>;
-+ reg = <0x9f0 0x10>;
+- reg = <919f0 10 915f0 10>;
++ reg = <0x919f0 0x10 0x915f0 0x10>;
};
- CPM_PIC: interrupt-controller at 930 {
-@@ -175,7 +176,7 @@
- #interrupt-cells = <1>;
- interrupts = <5 2 0 2>;
- interrupt-parent = <&PIC>;
-- reg = <930 20>;
-+ reg = <0x930 0x20>;
- compatible = "fsl,mpc885-cpm-pic",
- "fsl,cpm1-pic";
- };
-@@ -184,34 +185,34 @@
- device_type = "serial";
- compatible = "fsl,mpc885-smc-uart",
- "fsl,cpm1-smc-uart";
-- reg = <a80 10 3e80 40>;
-+ reg = <0xa80 0x10 0x3e80 0x40>;
- interrupts = <4>;
- interrupt-parent = <&CPM_PIC>;
- fsl,cpm-brg = <1>;
-- fsl,cpm-command = <0090>;
-+ fsl,cpm-command = <0x90>;
+ cpmpic: pic at 90c00 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- interrupts = <2e 2>;
++ interrupts = <46 2>;
+ interrupt-parent = <&mpic>;
+- reg = <90c00 80>;
++ reg = <0x90c00 0x80>;
+ compatible = "fsl,mpc8555-cpm-pic", "fsl,cpm2-pic";
};
+ };
+@@ -196,68 +197,68 @@
- serial at a90 {
- device_type = "serial";
- compatible = "fsl,mpc885-smc-uart",
- "fsl,cpm1-smc-uart";
-- reg = <a90 10 3f80 40>;
-+ reg = <0xa90 0x10 0x3f80 0x40>;
- interrupts = <3>;
- interrupt-parent = <&CPM_PIC>;
- fsl,cpm-brg = <2>;
-- fsl,cpm-command = <00d0>;
-+ fsl,cpm-command = <0xd0>;
- };
+ pci0: pci at e0008000 {
+ cell-index = <0>;
+- interrupt-map-mask = <1f800 0 0 7>;
++ interrupt-map-mask = <0x1f800 0x0 0x0 0x7>;
+ interrupt-map = <
- ethernet at a40 {
- device_type = "network";
- compatible = "fsl,mpc885-scc-enet",
- "fsl,cpm1-scc-enet";
-- reg = <a40 18 3e00 100>;
-+ reg = <0xa40 0x18 0x3e00 0x100>;
- local-mac-address = [ 00 00 00 00 00 00 ];
-- interrupts = <1c>;
-+ interrupts = <28>;
- interrupt-parent = <&CPM_PIC>;
- phy-handle = <&PHY2>;
-- fsl,cpm-command = <0080>;
-+ fsl,cpm-command = <0x80>;
- linux,network-index = <2>;
- };
- };
-diff --git a/arch/powerpc/boot/dts/pq2fads.dts b/arch/powerpc/boot/dts/pq2fads.dts
-index 2d56492..b2d6109 100644
---- a/arch/powerpc/boot/dts/pq2fads.dts
-+++ b/arch/powerpc/boot/dts/pq2fads.dts
+ /* IDSEL 0x10 */
+- 08000 0 0 1 &mpic 0 1
+- 08000 0 0 2 &mpic 1 1
+- 08000 0 0 3 &mpic 2 1
+- 08000 0 0 4 &mpic 3 1
++ 0x8000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x8000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x8000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x8000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x11 */
+- 08800 0 0 1 &mpic 0 1
+- 08800 0 0 2 &mpic 1 1
+- 08800 0 0 3 &mpic 2 1
+- 08800 0 0 4 &mpic 3 1
++ 0x8800 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x8800 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x8800 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x8800 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x12 (Slot 1) */
+- 09000 0 0 1 &mpic 0 1
+- 09000 0 0 2 &mpic 1 1
+- 09000 0 0 3 &mpic 2 1
+- 09000 0 0 4 &mpic 3 1
++ 0x9000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x9000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x9000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x9000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x13 (Slot 2) */
+- 09800 0 0 1 &mpic 1 1
+- 09800 0 0 2 &mpic 2 1
+- 09800 0 0 3 &mpic 3 1
+- 09800 0 0 4 &mpic 0 1
++ 0x9800 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0x9800 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0x9800 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x9800 0x0 0x0 0x4 &mpic 0x0 0x1
+
+ /* IDSEL 0x14 (Slot 3) */
+- 0a000 0 0 1 &mpic 2 1
+- 0a000 0 0 2 &mpic 3 1
+- 0a000 0 0 3 &mpic 0 1
+- 0a000 0 0 4 &mpic 1 1
++ 0xa000 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0xa000 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0xa000 0x0 0x0 0x3 &mpic 0x0 0x1
++ 0xa000 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x15 (Slot 4) */
+- 0a800 0 0 1 &mpic 3 1
+- 0a800 0 0 2 &mpic 0 1
+- 0a800 0 0 3 &mpic 1 1
+- 0a800 0 0 4 &mpic 2 1
++ 0xa800 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0xa800 0x0 0x0 0x2 &mpic 0x0 0x1
++ 0xa800 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0xa800 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* Bus 1 (Tundra Bridge) */
+ /* IDSEL 0x12 (ISA bridge) */
+- 19000 0 0 1 &mpic 0 1
+- 19000 0 0 2 &mpic 1 1
+- 19000 0 0 3 &mpic 2 1
+- 19000 0 0 4 &mpic 3 1>;
++ 0x19000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x19000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x19000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x19000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+ interrupt-parent = <&mpic>;
+- interrupts = <18 2>;
++ interrupts = <24 2>;
+ bus-range = <0 0>;
+- ranges = <02000000 0 80000000 80000000 0 20000000
+- 01000000 0 00000000 e2000000 0 00100000>;
+- clock-frequency = <3f940aa>;
++ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>;
++ clock-frequency = <66666666>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0008000 1000>;
++ reg = <0xe0008000 0x1000>;
+ compatible = "fsl,mpc8540-pci";
+ device_type = "pci";
+
+ i8259 at 19000 {
+ interrupt-controller;
+ device_type = "interrupt-controller";
+- reg = <19000 0 0 0 1>;
++ reg = <0x19000 0x0 0x0 0x0 0x1>;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ compatible = "chrp,iic";
+@@ -268,24 +269,24 @@
+
+ pci1: pci at e0009000 {
+ cell-index = <1>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x15 */
+- a800 0 0 1 &mpic b 1
+- a800 0 0 2 &mpic b 1
+- a800 0 0 3 &mpic b 1
+- a800 0 0 4 &mpic b 1>;
++ 0xa800 0x0 0x0 0x1 &mpic 0xb 0x1
++ 0xa800 0x0 0x0 0x2 &mpic 0xb 0x1
++ 0xa800 0x0 0x0 0x3 &mpic 0xb 0x1
++ 0xa800 0x0 0x0 0x4 &mpic 0xb 0x1>;
+ interrupt-parent = <&mpic>;
+- interrupts = <19 2>;
++ interrupts = <25 2>;
+ bus-range = <0 0>;
+- ranges = <02000000 0 a0000000 a0000000 0 20000000
+- 01000000 0 00000000 e3000000 0 00100000>;
+- clock-frequency = <3f940aa>;
++ ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xe3000000 0x0 0x100000>;
++ clock-frequency = <66666666>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0009000 1000>;
++ reg = <0xe0009000 0x1000>;
+ compatible = "fsl,mpc8540-pci";
+ device_type = "pci";
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts
+index 639ce8a..0cc16ab 100644
+--- a/arch/powerpc/boot/dts/mpc8560ads.dts
++++ b/arch/powerpc/boot/dts/mpc8560ads.dts
@@ -1,7 +1,7 @@
/*
- * Device Tree for the PQ2FADS-ZU board with an MPC8280 chip.
+ * MPC8560 ADS Device Tree Source
*
-- * Copyright 2007 Freescale Semiconductor Inc.
-+ * Copyright 2007,2008 Freescale Semiconductor Inc.
+- * 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,8 @@
+@@ -9,6 +9,7 @@
* option) any later version.
*/
+/dts-v1/;
-+
+
/ {
- model = "pq2fads";
- compatible = "fsl,pq2fads";
-@@ -21,11 +23,11 @@
+ model = "MPC8560ADS";
+@@ -32,74 +33,74 @@
- cpu at 0 {
+ PowerPC,8560 at 0 {
device_type = "cpu";
- reg = <0>;
-- d-cache-line-size = <d#32>;
-- i-cache-line-size = <d#32>;
-- d-cache-size = <d#16384>;
-- i-cache-size = <d#16384>;
+- 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>;
-+ i-cache-line-size = <32>;
-+ d-cache-size = <16384>;
-+ i-cache-size = <16384>;
- timebase-frequency = <0>;
- clock-frequency = <0>;
++ 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>;
};
-@@ -33,7 +35,7 @@
+ };
memory {
device_type = "memory";
-- reg = <0 0>;
-+ reg = <0x0 0x0>;
+- reg = <00000000 10000000>;
++ reg = <0x0 0x10000000>;
};
- localbus at f0010100 {
-@@ -41,67 +43,67 @@
- "fsl,pq2-localbus";
- #address-cells = <2>;
+ soc8560 at e0000000 {
+ #address-cells = <1>;
#size-cells = <1>;
-- reg = <f0010100 60>;
-+ reg = <0xf0010100 0x60>;
-
-- ranges = <0 0 fe000000 00800000
-- 1 0 f4500000 00008000
-- 8 0 f8200000 00008000>;
-+ ranges = <0x0 0x0 0xfe000000 0x800000
-+ 0x1 0x0 0xf4500000 0x8000
-+ 0x8 0x0 0xf8200000 0x8000>;
+ device_type = "soc";
+- ranges = <0 e0000000 00100000>;
+- reg = <e0000000 00000200>;
+- bus-frequency = <13ab6680>;
++ ranges = <0x0 0xe0000000 0x100000>;
++ reg = <0xe0000000 0x200>;
++ bus-frequency = <330000000>;
- flash at 0,0 {
- compatible = "jedec-flash";
-- reg = <0 0 800000>;
-+ reg = <0x0 0x0 0x800000>;
- bank-width = <4>;
- device-width = <1>;
+ memory-controller at 2000 {
+ compatible = "fsl,8540-memory-controller";
+- reg = <2000 1000>;
++ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+- interrupts = <12 2>;
++ interrupts = <18 2>;
};
- bcsr at 1,0 {
-- reg = <1 0 20>;
-+ reg = <0x1 0x0 0x20>;
- compatible = "fsl,pq2fads-bcsr";
+ l2-cache-controller at 20000 {
+ compatible = "fsl,8540-l2-cache-controller";
+- reg = <20000 1000>;
+- cache-line-size = <20>; // 32 bytes
+- cache-size = <40000>; // L2, 256K
++ reg = <0x20000 0x1000>;
++ cache-line-size = <32>; // 32 bytes
++ cache-size = <0x40000>; // L2, 256K
+ interrupt-parent = <&mpic>;
+- interrupts = <10 2>;
++ interrupts = <16 2>;
};
- PCI_PIC: pic at 8,0 {
- #interrupt-cells = <1>;
+ mdio at 24520 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-mdio";
+- reg = <24520 20>;
++ reg = <0x24520 0x20>;
+
+ phy0: ethernet-phy at 0 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <0>;
++ reg = <0x0>;
+ device_type = "ethernet-phy";
+ };
+ phy1: ethernet-phy at 1 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <1>;
++ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+ phy2: ethernet-phy at 2 {
+ interrupt-parent = <&mpic>;
+ interrupts = <7 1>;
+- reg = <2>;
++ reg = <0x2>;
+ device_type = "ethernet-phy";
+ };
+ phy3: ethernet-phy at 3 {
+ interrupt-parent = <&mpic>;
+ interrupts = <7 1>;
+- reg = <3>;
++ reg = <0x3>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -109,9 +110,9 @@
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+- reg = <24000 1000>;
++ reg = <0x24000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1d 2 1e 2 22 2>;
++ interrupts = <29 2 30 2 34 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy0>;
+ };
+@@ -121,9 +122,9 @@
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+- reg = <25000 1000>;
++ reg = <0x25000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <23 2 24 2 28 2>;
++ interrupts = <35 2 36 2 40 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy1>;
+ };
+@@ -132,7 +133,7 @@
interrupt-controller;
-- reg = <8 0 8>;
-+ reg = <0x8 0x0 0x8>;
- compatible = "fsl,pq2ads-pci-pic";
- interrupt-parent = <&PIC>;
-- interrupts = <18 8>;
-+ interrupts = <24 8>;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- reg = <40000 40000>;
++ reg = <0x40000 0x40000>;
+ device_type = "open-pic";
};
- };
-
- pci at f0010800 {
- device_type = "pci";
-- reg = <f0010800 10c f00101ac 8 f00101c4 8>;
-+ reg = <0xf0010800 0x10c 0xf00101ac 0x8 0xf00101c4 0x8>;
- compatible = "fsl,mpc8280-pci", "fsl,pq2-pci";
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
-- clock-frequency = <d#66000000>;
-- interrupt-map-mask = <f800 0 0 7>;
-+ clock-frequency = <66000000>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
- /* IDSEL 0x16 */
-- b000 0 0 1 &PCI_PIC 0
-- b000 0 0 2 &PCI_PIC 1
-- b000 0 0 3 &PCI_PIC 2
-- b000 0 0 4 &PCI_PIC 3
-+ 0xb000 0x0 0x0 0x1 &PCI_PIC 0
-+ 0xb000 0x0 0x0 0x2 &PCI_PIC 1
-+ 0xb000 0x0 0x0 0x3 &PCI_PIC 2
-+ 0xb000 0x0 0x0 0x4 &PCI_PIC 3
-
- /* IDSEL 0x17 */
-- b800 0 0 1 &PCI_PIC 4
-- b800 0 0 2 &PCI_PIC 5
-- b800 0 0 3 &PCI_PIC 6
-- b800 0 0 4 &PCI_PIC 7
-+ 0xb800 0x0 0x0 0x1 &PCI_PIC 4
-+ 0xb800 0x0 0x0 0x2 &PCI_PIC 5
-+ 0xb800 0x0 0x0 0x3 &PCI_PIC 6
-+ 0xb800 0x0 0x0 0x4 &PCI_PIC 7
-
- /* IDSEL 0x18 */
-- c000 0 0 1 &PCI_PIC 8
-- c000 0 0 2 &PCI_PIC 9
-- c000 0 0 3 &PCI_PIC a
-- c000 0 0 4 &PCI_PIC b>;
-+ 0xc000 0x0 0x0 0x1 &PCI_PIC 8
-+ 0xc000 0x0 0x0 0x2 &PCI_PIC 9
-+ 0xc000 0x0 0x0 0x3 &PCI_PIC 10
-+ 0xc000 0x0 0x0 0x4 &PCI_PIC 11>;
-
- interrupt-parent = <&PIC>;
-- interrupts = <12 8>;
-- ranges = <42000000 0 80000000 80000000 0 20000000
-- 02000000 0 a0000000 a0000000 0 20000000
-- 01000000 0 00000000 f6000000 0 02000000>;
-+ interrupts = <18 8>;
-+ ranges = <0x42000000 0x0 0x80000000 0x80000000 0x0 0x20000000
-+ 0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
-+ 0x1000000 0x0 0x0 0xf6000000 0x0 0x2000000>;
- };
-
- soc at f0000000 {
-@@ -109,27 +111,27 @@
- #size-cells = <1>;
- device_type = "soc";
- compatible = "fsl,mpc8280", "fsl,pq2-soc";
-- ranges = <00000000 f0000000 00053000>;
-+ ranges = <0x0 0xf0000000 0x53000>;
-
- // Temporary -- will go away once kernel uses ranges for get_immrbase().
-- reg = <f0000000 00053000>;
-+ reg = <0xf0000000 0x53000>;
- cpm at 119c0 {
+@@ -140,17 +141,17 @@
#address-cells = <1>;
#size-cells = <1>;
- #interrupt-cells = <2>;
- compatible = "fsl,mpc8280-cpm", "fsl,cpm2";
-- reg = <119c0 30>;
-+ reg = <0x119c0 0x30>;
+ compatible = "fsl,mpc8560-cpm", "fsl,cpm2";
+- reg = <919c0 30>;
++ reg = <0x919c0 0x30>;
ranges;
- muram at 0 {
+ muram at 80000 {
#address-cells = <1>;
#size-cells = <1>;
-- ranges = <0 0 10000>;
-+ ranges = <0x0 0x0 0x10000>;
+- ranges = <0 80000 10000>;
++ ranges = <0x0 0x80000 0x10000>;
data at 0 {
compatible = "fsl,cpm-muram-data";
-- reg = <0 2000 9800 800>;
-+ reg = <0x0 0x2000 0x9800 0x800>;
+- reg = <0 4000 9000 2000>;
++ reg = <0x0 0x4000 0x9000 0x2000>;
};
};
-@@ -137,53 +139,53 @@
- compatible = "fsl,mpc8280-brg",
+@@ -158,17 +159,17 @@
+ compatible = "fsl,mpc8560-brg",
"fsl,cpm2-brg",
"fsl,cpm-brg";
-- reg = <119f0 10 115f0 10>;
-+ reg = <0x119f0 0x10 0x115f0 0x10>;
+- reg = <919f0 10 915f0 10>;
+- clock-frequency = <d#165000000>;
++ reg = <0x919f0 0x10 0x915f0 0x10>;
++ clock-frequency = <165000000>;
};
- serial at 11a00 {
+ cpmpic: pic at 90c00 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- interrupts = <2e 2>;
++ interrupts = <46 2>;
+ interrupt-parent = <&mpic>;
+- reg = <90c00 80>;
++ reg = <0x90c00 0x80>;
+ compatible = "fsl,mpc8560-cpm-pic", "fsl,cpm2-pic";
+ };
+
+@@ -176,11 +177,11 @@
device_type = "serial";
- compatible = "fsl,mpc8280-scc-uart",
+ compatible = "fsl,mpc8560-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>;
+- 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>;
};
- serial at 11a20 {
+@@ -188,11 +189,11 @@
device_type = "serial";
- compatible = "fsl,mpc8280-scc-uart",
+ compatible = "fsl,mpc8560-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>;
+- 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>;
};
- ethernet at 11320 {
+@@ -200,10 +201,10 @@
device_type = "network";
- compatible = "fsl,mpc8280-fcc-enet",
+ compatible = "fsl,mpc8560-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>;
+- 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>;
};
-
- ethernet at 11340 {
+@@ -212,10 +213,10 @@
device_type = "network";
- compatible = "fsl,mpc8280-fcc-enet",
+ compatible = "fsl,mpc8560-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>;
+- 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>;
- local-mac-address = [00 e0 0c 00 79 01];
++ interrupts = <34 8>;
+ interrupt-parent = <&cpmpic>;
+ phy-handle = <&phy3>;
};
+@@ -229,87 +230,87 @@
+ #address-cells = <3>;
+ compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci";
+ device_type = "pci";
+- reg = <e0008000 1000>;
+- clock-frequency = <3f940aa>;
+- interrupt-map-mask = <f800 0 0 7>;
++ reg = <0xe0008000 0x1000>;
++ clock-frequency = <66666666>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
-@@ -194,21 +196,21 @@
- "fsl,cpm2-mdio-bitbang";
- #address-cells = <1>;
- #size-cells = <0>;
-- reg = <10d40 14>;
-+ reg = <0x10d40 0x14>;
- fsl,mdio-pin = <9>;
-- fsl,mdc-pin = <a>;
-+ fsl,mdc-pin = <10>;
+ /* 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
- PHY0: ethernet-phy at 0 {
- interrupt-parent = <&PIC>;
-- interrupts = <19 2>;
-- reg = <0>;
-+ interrupts = <25 2>;
-+ reg = <0x0>;
- device_type = "ethernet-phy";
- };
+ /* 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
- PHY1: ethernet-phy at 1 {
- interrupt-parent = <&PIC>;
-- interrupts = <19 2>;
-- reg = <3>;
-+ interrupts = <25 2>;
-+ reg = <0x3>;
- device_type = "ethernet-phy";
- };
- };
-@@ -218,17 +220,17 @@
- #size-cells = <0>;
- compatible = "fsl,mpc8280-usb",
- "fsl,cpm2-usb";
-- reg = <11b60 18 8b00 100>;
-+ reg = <0x11b60 0x18 0x8b00 0x100>;
- interrupt-parent = <&PIC>;
-- interrupts = <b 8>;
-- fsl,cpm-command = <2e600000>;
-+ interrupts = <11 8>;
-+ fsl,cpm-command = <0x2e600000>;
- };
- };
+ /* 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
- PIC: interrupt-controller at 10c00 {
- #interrupt-cells = <2>;
- interrupt-controller;
-- reg = <10c00 80>;
-+ reg = <0x10c00 0x80>;
- compatible = "fsl,mpc8280-pic", "fsl,cpm2-pic";
- };
+ /* 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
-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.
+ /* 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/;
-+
+
/ {
- #address-cells = <1>;
- #size-cells = <1>;
-@@ -25,46 +27,46 @@
- PowerPC,7447 {
+ model = "MPC8568EMDS";
+@@ -37,11 +34,11 @@
+
+ PowerPC,8568 at 0 {
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>;
- };
- };
+- 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 20000000>; /* Default (512MB) */
-+ reg = <0x0 0x20000000>; /* Default (512MB) */
+- reg = <00000000 10000000>;
++ reg = <0x0 0x10000000>;
};
-- mv64x60 at f1000000 { /* Marvell Discovery */
-+ system-controller at f1000000 { /* Marvell Discovery mv64360 */
+ bcsr at f8000000 {
+ device_type = "board-control";
+- reg = <f8000000 8000>;
++ reg = <0xf8000000 0x8000>;
+ };
+
+ soc8568 at e0000000 {
#address-cells = <1>;
#size-cells = <1>;
- model = "mv64360"; /* Default */
-- compatible = "marvell,mv64x60";
-- clock-frequency = <7f28155>; /* 133.333333 MHz */
-- reg = <f1000000 00010000>;
-- virtual-reg = <f1000000>;
-- ranges = <88000000 88000000 01000000 /* PCI 0 I/O Space */
-- 80000000 80000000 08000000 /* PCI 0 MEM Space */
-- a0000000 a0000000 04000000 /* User FLASH */
-- 00000000 f1000000 00010000 /* Bridge's regs */
-- f2000000 f2000000 00040000>; /* Integrated SRAM */
-+ compatible = "marvell,mv64360";
-+ clock-frequency = <133333333>;
-+ reg = <0xf1000000 0x10000>;
-+ virtual-reg = <0xf1000000>;
-+ ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */
-+ 0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */
-+ 0xa0000000 0xa0000000 0x4000000 /* User FLASH */
-+ 0x00000000 0xf1000000 0x0010000 /* Bridge's regs */
-+ 0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */
+ device_type = "soc";
+- ranges = <0 e0000000 00100000>;
+- reg = <e0000000 00001000>;
++ ranges = <0x0 0xe0000000 0x100000>;
++ reg = <0xe0000000 0x1000>;
+ bus-frequency = <0>;
- flash at a0000000 {
- device_type = "rom";
- compatible = "direct-mapped";
-- reg = <a0000000 4000000>; /* Default (64MB) */
-+ reg = <0xa0000000 0x4000000>; /* Default (64MB) */
- probe-type = "CFI";
- bank-width = <4>;
-- partitions = <00000000 00100000 /* RO */
-- 00100000 00040001 /* RW */
-- 00140000 00400000 /* RO */
-- 00540000 039c0000 /* RO */
-- 03f00000 00100000>; /* RO */
-+ partitions = <0x00000000 0x00100000 /* RO */
-+ 0x00100000 0x00040001 /* RW */
-+ 0x00140000 0x00400000 /* RO */
-+ 0x00540000 0x039c0000 /* RO */
-+ 0x03f00000 0x00100000>; /* RO */
- partition-names = "FW Image A", "FW Config Data", "Kernel Image", "Filesystem", "FW Image B";
+ memory-controller at 2000 {
+ compatible = "fsl,8568-memory-controller";
+- reg = <2000 1000>;
++ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+- interrupts = <12 2>;
++ interrupts = <18 2>;
};
-@@ -72,171 +74,153 @@
+ l2-cache-controller at 20000 {
+ compatible = "fsl,8568-l2-cache-controller";
+- reg = <20000 1000>;
+- cache-line-size = <20>; // 32 bytes
+- cache-size = <80000>; // L2, 512K
++ reg = <0x20000 0x1000>;
++ cache-line-size = <32>; // 32 bytes
++ cache-size = <0x80000>; // L2, 512K
+ interrupt-parent = <&mpic>;
+- interrupts = <10 2>;
++ interrupts = <16 2>;
+ };
+
+ i2c at 3000 {
+@@ -87,14 +84,14 @@
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+- reg = <3000 100>;
+- interrupts = <2b 2>;
++ reg = <0x3000 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+
+ rtc at 68 {
+ compatible = "dallas,ds1374";
+- reg = <68>;
++ reg = <0x68>;
+ };
+ };
+
+@@ -103,8 +100,8 @@
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+- reg = <3100 100>;
+- interrupts = <2b 2>;
++ reg = <0x3100 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+@@ -113,30 +110,30 @@
#address-cells = <1>;
#size-cells = <0>;
- device_type = "mdio";
-- compatible = "marvell,mv64x60-mdio";
-- ethernet-phy at 1 {
-+ compatible = "marvell,mv64360-mdio";
-+ PHY0: ethernet-phy at 1 {
+ compatible = "fsl,gianfar-mdio";
+- reg = <24520 20>;
++ reg = <0x24520 0x20>;
+
+ phy0: ethernet-phy at 7 {
+ interrupt-parent = <&mpic>;
+ interrupts = <1 1>;
+- reg = <7>;
++ reg = <0x7>;
device_type = "ethernet-phy";
- compatible = "broadcom,bcm5421";
-- interrupts = <4c>; /* GPP 12 */
-- interrupt-parent = <&/mv64x60/pic>;
-+ interrupts = <76>; /* GPP 12 */
-+ interrupt-parent = <&PIC>;
- reg = <1>;
};
-- ethernet-phy at 3 {
-+ PHY1: ethernet-phy at 3 {
+ phy1: ethernet-phy at 1 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1>;
+- reg = <1>;
++ reg = <0x1>;
device_type = "ethernet-phy";
- compatible = "broadcom,bcm5421";
-- interrupts = <4c>; /* GPP 12 */
-- interrupt-parent = <&/mv64x60/pic>;
-+ interrupts = <76>; /* GPP 12 */
-+ interrupt-parent = <&PIC>;
- reg = <3>;
};
- };
-
-- ethernet at 2000 {
-- reg = <2000 2000>;
-- eth0 {
-+ ethernet-group at 2000 {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ compatible = "marvell,mv64360-eth-group";
-+ reg = <0x2000 0x2000>;
-+ ethernet at 0 {
- device_type = "network";
-- compatible = "marvell,mv64x60-eth";
-- block-index = <0>;
-- interrupts = <20>;
-- interrupt-parent = <&/mv64x60/pic>;
-- phy = <&/mv64x60/mdio/ethernet-phy at 1>;
-+ compatible = "marvell,mv64360-eth";
-+ reg = <0>;
-+ interrupts = <32>;
-+ interrupt-parent = <&PIC>;
-+ phy = <&PHY0>;
- local-mac-address = [ 00 00 00 00 00 00 ];
+ phy2: ethernet-phy at 2 {
+ interrupt-parent = <&mpic>;
+ interrupts = <1 1>;
+- reg = <2>;
++ reg = <0x2>;
+ device_type = "ethernet-phy";
};
-- eth1 {
-+ ethernet at 1 {
- device_type = "network";
-- compatible = "marvell,mv64x60-eth";
-- block-index = <1>;
-- interrupts = <21>;
-- interrupt-parent = <&/mv64x60/pic>;
-- phy = <&/mv64x60/mdio/ethernet-phy at 3>;
-+ compatible = "marvell,mv64360-eth";
-+ reg = <1>;
-+ interrupts = <33>;
-+ interrupt-parent = <&PIC>;
-+ phy = <&PHY1>;
- local-mac-address = [ 00 00 00 00 00 00 ];
+ phy3: ethernet-phy at 3 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1>;
+- reg = <3>;
++ reg = <0x3>;
+ device_type = "ethernet-phy";
};
};
+@@ -146,9 +143,9 @@
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+- reg = <24000 1000>;
++ reg = <0x24000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1d 2 1e 2 22 2>;
++ interrupts = <29 2 30 2 34 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy2>;
+ };
+@@ -158,9 +155,9 @@
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+- reg = <25000 1000>;
++ reg = <0x25000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <23 2 24 2 28 2>;
++ interrupts = <35 2 36 2 40 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy3>;
+ };
+@@ -169,15 +166,15 @@
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4500 100>;
++ reg = <0x4500 0x100>;
+ clock-frequency = <0>;
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
-- sdma at 4000 {
-- device_type = "dma";
-- compatible = "marvell,mv64x60-sdma";
-- reg = <4000 c18>;
-- virtual-reg = <f1004000>;
-- interrupt-base = <0>;
-- interrupts = <24>;
-- interrupt-parent = <&/mv64x60/pic>;
-+ SDMA0: sdma at 4000 {
-+ compatible = "marvell,mv64360-sdma";
-+ reg = <0x4000 0xc18>;
-+ virtual-reg = <0xf1004000>;
-+ interrupts = <36>;
-+ interrupt-parent = <&PIC>;
+ global-utilities at e0000 { //global utilities block
+ compatible = "fsl,mpc8548-guts";
+- reg = <e0000 1000>;
++ reg = <0xe0000 0x1000>;
+ fsl,has-rstcr;
};
-- sdma at 6000 {
-- device_type = "dma";
-- compatible = "marvell,mv64x60-sdma";
-- reg = <6000 c18>;
-- virtual-reg = <f1006000>;
-- interrupt-base = <0>;
-- interrupts = <26>;
-- interrupt-parent = <&/mv64x60/pic>;
-+ SDMA1: sdma at 6000 {
-+ compatible = "marvell,mv64360-sdma";
-+ reg = <0x6000 0xc18>;
-+ virtual-reg = <0xf1006000>;
-+ interrupts = <38>;
-+ interrupt-parent = <&PIC>;
+@@ -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>;
};
-- brg at b200 {
-- compatible = "marvell,mv64x60-brg";
-- reg = <b200 8>;
-+ BRG0: brg at b200 {
-+ compatible = "marvell,mv64360-brg";
-+ reg = <0xb200 0x8>;
- clock-src = <8>;
-- clock-frequency = <7ed6b40>;
-- current-speed = <2580>;
-- bcr = <0>;
-+ clock-frequency = <133333333>;
-+ current-speed = <9600>;
+@@ -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>;
};
-- brg at b208 {
-- compatible = "marvell,mv64x60-brg";
-- reg = <b208 8>;
-+ BRG1: brg at b208 {
-+ compatible = "marvell,mv64360-brg";
-+ reg = <0xb208 0x8>;
- clock-src = <8>;
-- clock-frequency = <7ed6b40>;
-- current-speed = <2580>;
-- bcr = <0>;
-+ clock-frequency = <133333333>;
-+ current-speed = <9600>;
+ mpic: pic at 40000 {
+@@ -209,73 +206,73 @@
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- reg = <40000 40000>;
++ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ big-endian;
};
-- cunit at f200 {
-- reg = <f200 200>;
-+ CUNIT: cunit at f200 {
-+ reg = <0xf200 0x200>;
+ par_io at e0100 {
+- reg = <e0100 100>;
++ reg = <0xe0100 0x100>;
+ device_type = "par_io";
+ num-ports = <7>;
+
+ pio1: ucc_pin at 01 {
+ pio-map = <
+ /* port pin dir open_drain assignment has_irq */
+- 4 0a 1 0 2 0 /* TxD0 */
+- 4 09 1 0 2 0 /* TxD1 */
+- 4 08 1 0 2 0 /* TxD2 */
+- 4 07 1 0 2 0 /* TxD3 */
+- 4 17 1 0 2 0 /* TxD4 */
+- 4 16 1 0 2 0 /* TxD5 */
+- 4 15 1 0 2 0 /* TxD6 */
+- 4 14 1 0 2 0 /* TxD7 */
+- 4 0f 2 0 2 0 /* RxD0 */
+- 4 0e 2 0 2 0 /* RxD1 */
+- 4 0d 2 0 2 0 /* RxD2 */
+- 4 0c 2 0 2 0 /* RxD3 */
+- 4 1d 2 0 2 0 /* RxD4 */
+- 4 1c 2 0 2 0 /* RxD5 */
+- 4 1b 2 0 2 0 /* RxD6 */
+- 4 1a 2 0 2 0 /* RxD7 */
+- 4 0b 1 0 2 0 /* TX_EN */
+- 4 18 1 0 2 0 /* TX_ER */
+- 4 10 2 0 2 0 /* RX_DV */
+- 4 1e 2 0 2 0 /* RX_ER */
+- 4 11 2 0 2 0 /* RX_CLK */
+- 4 13 1 0 2 0 /* GTX_CLK */
+- 1 1f 2 0 3 0>; /* GTX125 */
++ 0x4 0xa 0x1 0x0 0x2 0x0 /* TxD0 */
++ 0x4 0x9 0x1 0x0 0x2 0x0 /* TxD1 */
++ 0x4 0x8 0x1 0x0 0x2 0x0 /* TxD2 */
++ 0x4 0x7 0x1 0x0 0x2 0x0 /* TxD3 */
++ 0x4 0x17 0x1 0x0 0x2 0x0 /* TxD4 */
++ 0x4 0x16 0x1 0x0 0x2 0x0 /* TxD5 */
++ 0x4 0x15 0x1 0x0 0x2 0x0 /* TxD6 */
++ 0x4 0x14 0x1 0x0 0x2 0x0 /* TxD7 */
++ 0x4 0xf 0x2 0x0 0x2 0x0 /* RxD0 */
++ 0x4 0xe 0x2 0x0 0x2 0x0 /* RxD1 */
++ 0x4 0xd 0x2 0x0 0x2 0x0 /* RxD2 */
++ 0x4 0xc 0x2 0x0 0x2 0x0 /* RxD3 */
++ 0x4 0x1d 0x2 0x0 0x2 0x0 /* RxD4 */
++ 0x4 0x1c 0x2 0x0 0x2 0x0 /* RxD5 */
++ 0x4 0x1b 0x2 0x0 0x2 0x0 /* RxD6 */
++ 0x4 0x1a 0x2 0x0 0x2 0x0 /* RxD7 */
++ 0x4 0xb 0x1 0x0 0x2 0x0 /* TX_EN */
++ 0x4 0x18 0x1 0x0 0x2 0x0 /* TX_ER */
++ 0x4 0x10 0x2 0x0 0x2 0x0 /* RX_DV */
++ 0x4 0x1e 0x2 0x0 0x2 0x0 /* RX_ER */
++ 0x4 0x11 0x2 0x0 0x2 0x0 /* RX_CLK */
++ 0x4 0x13 0x1 0x0 0x2 0x0 /* GTX_CLK */
++ 0x1 0x1f 0x2 0x0 0x3 0x0>; /* GTX125 */
+ };
+
+ pio2: ucc_pin at 02 {
+ pio-map = <
+ /* port pin dir open_drain assignment has_irq */
+- 5 0a 1 0 2 0 /* TxD0 */
+- 5 09 1 0 2 0 /* TxD1 */
+- 5 08 1 0 2 0 /* TxD2 */
+- 5 07 1 0 2 0 /* TxD3 */
+- 5 17 1 0 2 0 /* TxD4 */
+- 5 16 1 0 2 0 /* TxD5 */
+- 5 15 1 0 2 0 /* TxD6 */
+- 5 14 1 0 2 0 /* TxD7 */
+- 5 0f 2 0 2 0 /* RxD0 */
+- 5 0e 2 0 2 0 /* RxD1 */
+- 5 0d 2 0 2 0 /* RxD2 */
+- 5 0c 2 0 2 0 /* RxD3 */
+- 5 1d 2 0 2 0 /* RxD4 */
+- 5 1c 2 0 2 0 /* RxD5 */
+- 5 1b 2 0 2 0 /* RxD6 */
+- 5 1a 2 0 2 0 /* RxD7 */
+- 5 0b 1 0 2 0 /* TX_EN */
+- 5 18 1 0 2 0 /* TX_ER */
+- 5 10 2 0 2 0 /* RX_DV */
+- 5 1e 2 0 2 0 /* RX_ER */
+- 5 11 2 0 2 0 /* RX_CLK */
+- 5 13 1 0 2 0 /* GTX_CLK */
+- 1 1f 2 0 3 0 /* GTX125 */
+- 4 06 3 0 2 0 /* MDIO */
+- 4 05 1 0 2 0>; /* MDC */
++ 0x5 0xa 0x1 0x0 0x2 0x0 /* TxD0 */
++ 0x5 0x9 0x1 0x0 0x2 0x0 /* TxD1 */
++ 0x5 0x8 0x1 0x0 0x2 0x0 /* TxD2 */
++ 0x5 0x7 0x1 0x0 0x2 0x0 /* TxD3 */
++ 0x5 0x17 0x1 0x0 0x2 0x0 /* TxD4 */
++ 0x5 0x16 0x1 0x0 0x2 0x0 /* TxD5 */
++ 0x5 0x15 0x1 0x0 0x2 0x0 /* TxD6 */
++ 0x5 0x14 0x1 0x0 0x2 0x0 /* TxD7 */
++ 0x5 0xf 0x2 0x0 0x2 0x0 /* RxD0 */
++ 0x5 0xe 0x2 0x0 0x2 0x0 /* RxD1 */
++ 0x5 0xd 0x2 0x0 0x2 0x0 /* RxD2 */
++ 0x5 0xc 0x2 0x0 0x2 0x0 /* RxD3 */
++ 0x5 0x1d 0x2 0x0 0x2 0x0 /* RxD4 */
++ 0x5 0x1c 0x2 0x0 0x2 0x0 /* RxD5 */
++ 0x5 0x1b 0x2 0x0 0x2 0x0 /* RxD6 */
++ 0x5 0x1a 0x2 0x0 0x2 0x0 /* RxD7 */
++ 0x5 0xb 0x1 0x0 0x2 0x0 /* TX_EN */
++ 0x5 0x18 0x1 0x0 0x2 0x0 /* TX_ER */
++ 0x5 0x10 0x2 0x0 0x2 0x0 /* RX_DV */
++ 0x5 0x1e 0x2 0x0 0x2 0x0 /* RX_ER */
++ 0x5 0x11 0x2 0x0 0x2 0x0 /* RX_CLK */
++ 0x5 0x13 0x1 0x0 0x2 0x0 /* GTX_CLK */
++ 0x1 0x1f 0x2 0x0 0x3 0x0 /* GTX125 */
++ 0x4 0x6 0x3 0x0 0x2 0x0 /* MDIO */
++ 0x4 0x5 0x1 0x0 0x2 0x0>; /* MDC */
+ };
};
+ };
+@@ -285,28 +282,28 @@
+ #size-cells = <1>;
+ device_type = "qe";
+ compatible = "fsl,qe";
+- ranges = <0 e0080000 00040000>;
+- reg = <e0080000 480>;
++ ranges = <0x0 0xe0080000 0x40000>;
++ reg = <0xe0080000 0x480>;
+ brg-frequency = <0>;
+- bus-frequency = <179A7B00>;
++ bus-frequency = <396000000>;
-- mpscrouting at b400 {
-- reg = <b400 c>;
-+ MPSCROUTING: mpscrouting at b400 {
-+ reg = <0xb400 0xc>;
+ muram at 10000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,qe-muram", "fsl,cpm-muram";
+- ranges = <0 00010000 0000c000>;
++ ranges = <0x0 0x10000 0x10000>;
+
+ data-only at 0 {
+ compatible = "fsl,qe-muram-data",
+ "fsl,cpm-muram-data";
+- reg = <0 c000>;
++ reg = <0x0 0x10000>;
+ };
};
-- mpscintr at b800 {
-- reg = <b800 100>;
-- virtual-reg = <f100b800>;
-+ MPSCINTR: mpscintr at b800 {
-+ reg = <0xb800 0x100>;
-+ virtual-reg = <0xf100b800>;
+ spi at 4c0 {
+ cell-index = <0>;
+ compatible = "fsl,spi";
+- reg = <4c0 40>;
++ reg = <0x4c0 0x40>;
+ interrupts = <2>;
+ interrupt-parent = <&qeic>;
+ mode = "cpu";
+@@ -315,7 +312,7 @@
+ spi at 500 {
+ cell-index = <1>;
+ compatible = "fsl,spi";
+- reg = <500 40>;
++ reg = <0x500 0x40>;
+ interrupts = <1>;
+ interrupt-parent = <&qeic>;
+ mode = "cpu";
+@@ -324,11 +321,9 @@
+ enet2: ucc at 2000 {
+ device_type = "network";
+ compatible = "ucc_geth";
+- model = "UCC";
+ cell-index = <1>;
+- device-id = <1>;
+- reg = <2000 200>;
+- interrupts = <20>;
++ reg = <0x2000 0x200>;
++ interrupts = <32>;
+ interrupt-parent = <&qeic>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ rx-clock-name = "none";
+@@ -341,11 +336,9 @@
+ enet3: ucc at 3000 {
+ device_type = "network";
+ compatible = "ucc_geth";
+- model = "UCC";
+ cell-index = <2>;
+- device-id = <2>;
+- reg = <3000 200>;
+- interrupts = <21>;
++ reg = <0x3000 0x200>;
++ interrupts = <33>;
+ interrupt-parent = <&qeic>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ rx-clock-name = "none";
+@@ -358,7 +351,7 @@
+ mdio at 2120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+- reg = <2120 18>;
++ reg = <0x2120 0x18>;
+ compatible = "fsl,ucc-mdio";
+
+ /* These are the same PHYs as on
+@@ -366,25 +359,25 @@
+ qe_phy0: ethernet-phy at 07 {
+ interrupt-parent = <&mpic>;
+ interrupts = <1 1>;
+- reg = <7>;
++ reg = <0x7>;
+ device_type = "ethernet-phy";
+ };
+ qe_phy1: ethernet-phy at 01 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1>;
+- reg = <1>;
++ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+ qe_phy2: ethernet-phy at 02 {
+ interrupt-parent = <&mpic>;
+ interrupts = <1 1>;
+- reg = <2>;
++ reg = <0x2>;
+ device_type = "ethernet-phy";
+ };
+ qe_phy3: ethernet-phy at 03 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1>;
+- reg = <3>;
++ reg = <0x3>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -394,9 +387,9 @@
+ compatible = "fsl,qe-ic";
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <80 80>;
++ reg = <0x80 0x80>;
+ big-endian;
+- interrupts = <2e 2 2e 2>; //high:30 low:30
++ interrupts = <46 2 46 2>; //high:30 low:30
+ interrupt-parent = <&mpic>;
};
-- mpsc at 8000 {
-+ MPSC0: mpsc at 8000 {
- device_type = "serial";
-- compatible = "marvell,mpsc";
-- reg = <8000 38>;
-- virtual-reg = <f1008000>;
-- sdma = <&/mv64x60/sdma at 4000>;
-- brg = <&/mv64x60/brg at b200>;
-- cunit = <&/mv64x60/cunit at f200>;
-- mpscrouting = <&/mv64x60/mpscrouting at b400>;
-- mpscintr = <&/mv64x60/mpscintr at b800>;
-- block-index = <0>;
-- max_idle = <28>;
-- chr_1 = <0>;
-- chr_2 = <0>;
-- chr_10 = <3>;
-- mpcr = <0>;
-- interrupts = <28>;
-- interrupt-parent = <&/mv64x60/pic>;
-+ compatible = "marvell,mv64360-mpsc";
-+ reg = <0x8000 0x38>;
-+ virtual-reg = <0xf1008000>;
-+ sdma = <&SDMA0>;
-+ brg = <&BRG0>;
-+ cunit = <&CUNIT>;
-+ mpscrouting = <&MPSCROUTING>;
-+ mpscintr = <&MPSCINTR>;
-+ cell-index = <0>;
-+ interrupts = <40>;
-+ interrupt-parent = <&PIC>;
+@@ -404,30 +397,30 @@
+
+ pci0: pci at e0008000 {
+ cell-index = <0>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x12 AD18 */
+- 9000 0 0 1 &mpic 5 1
+- 9000 0 0 2 &mpic 6 1
+- 9000 0 0 3 &mpic 7 1
+- 9000 0 0 4 &mpic 4 1
++ 0x9000 0x0 0x0 0x1 &mpic 0x5 0x1
++ 0x9000 0x0 0x0 0x2 &mpic 0x6 0x1
++ 0x9000 0x0 0x0 0x3 &mpic 0x7 0x1
++ 0x9000 0x0 0x0 0x4 &mpic 0x4 0x1
+
+ /* IDSEL 0x13 AD19 */
+- 9800 0 0 1 &mpic 6 1
+- 9800 0 0 2 &mpic 7 1
+- 9800 0 0 3 &mpic 4 1
+- 9800 0 0 4 &mpic 5 1>;
++ 0x9800 0x0 0x0 0x1 &mpic 0x6 0x1
++ 0x9800 0x0 0x0 0x2 &mpic 0x7 0x1
++ 0x9800 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x9800 0x0 0x0 0x4 &mpic 0x5 0x1>;
+
+ interrupt-parent = <&mpic>;
+- interrupts = <18 2>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 80000000 80000000 0 20000000
+- 01000000 0 00000000 e2000000 0 00800000>;
+- clock-frequency = <3f940aa>;
++ interrupts = <24 2>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xe2000000 0x0 0x800000>;
++ clock-frequency = <66666666>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0008000 1000>;
++ reg = <0xe0008000 0x1000>;
+ compatible = "fsl,mpc8540-pci";
+ device_type = "pci";
+ };
+@@ -435,39 +428,39 @@
+ /* PCI Express */
+ pci1: pcie at e000a000 {
+ cell-index = <2>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x0 (PEX) */
+- 00000 0 0 1 &mpic 0 1
+- 00000 0 0 2 &mpic 1 1
+- 00000 0 0 3 &mpic 2 1
+- 00000 0 0 4 &mpic 3 1>;
++ 00000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 00000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 00000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 00000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+
+ interrupt-parent = <&mpic>;
+- interrupts = <1a 2>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 a0000000 a0000000 0 10000000
+- 01000000 0 00000000 e2800000 0 00800000>;
+- clock-frequency = <1fca055>;
++ interrupts = <26 2>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
++ 0x1000000 0x0 0x0 0xe2800000 0x0 0x800000>;
++ clock-frequency = <33333333>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e000a000 1000>;
++ reg = <0xe000a000 0x1000>;
+ compatible = "fsl,mpc8548-pcie";
+ device_type = "pci";
+ pcie at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+- ranges = <02000000 0 a0000000
+- 02000000 0 a0000000
+- 0 10000000
++ ranges = <0x2000000 0x0 0xa0000000
++ 0x2000000 0x0 0xa0000000
++ 0x0 0x10000000
+
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00800000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x800000>;
};
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8572ds.dts b/arch/powerpc/boot/dts/mpc8572ds.dts
+index db37214..66f27ab 100644
+--- a/arch/powerpc/boot/dts/mpc8572ds.dts
++++ b/arch/powerpc/boot/dts/mpc8572ds.dts
+@@ -1,7 +1,7 @@
+ /*
+ * MPC8572 DS Device Tree Source
+ *
+- * Copyright 2007 Freescale Semiconductor Inc.
++ * Copyright 2007, 2008 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+@@ -9,6 +9,7 @@
+ * option) any later version.
+ */
-- mpsc at 9000 {
-+ MPSC1: mpsc at 9000 {
- device_type = "serial";
-- compatible = "marvell,mpsc";
-- reg = <9000 38>;
-- virtual-reg = <f1009000>;
-- sdma = <&/mv64x60/sdma at 6000>;
-- brg = <&/mv64x60/brg at b208>;
-- cunit = <&/mv64x60/cunit at f200>;
-- mpscrouting = <&/mv64x60/mpscrouting at b400>;
-- mpscintr = <&/mv64x60/mpscintr at b800>;
-- block-index = <1>;
-- max_idle = <28>;
-- chr_1 = <0>;
-- chr_2 = <0>;
-- chr_10 = <3>;
-- mpcr = <0>;
-- interrupts = <2a>;
-- interrupt-parent = <&/mv64x60/pic>;
-+ compatible = "marvell,mv64360-mpsc";
-+ reg = <0x9000 0x38>;
-+ virtual-reg = <0xf1009000>;
-+ sdma = <&SDMA1>;
-+ brg = <&BRG1>;
-+ cunit = <&CUNIT>;
-+ mpscrouting = <&MPSCROUTING>;
-+ mpscintr = <&MPSCINTR>;
-+ cell-index = <1>;
-+ interrupts = <42>;
-+ interrupt-parent = <&PIC>;
++/dts-v1/;
+ / {
+ model = "fsl,MPC8572DS";
+ compatible = "fsl,MPC8572DS";
+@@ -33,11 +34,11 @@
+
+ PowerPC,8572 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <20>; // 32 bytes
+- i-cache-line-size = <20>; // 32 bytes
+- d-cache-size = <8000>; // L1, 32K
+- i-cache-size = <8000>; // L1, 32K
++ reg = <0x0>;
++ d-cache-line-size = <32>; // 32 bytes
++ i-cache-line-size = <32>; // 32 bytes
++ d-cache-size = <0x8000>; // L1, 32K
++ i-cache-size = <0x8000>; // L1, 32K
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+@@ -45,11 +46,11 @@
+
+ PowerPC,8572 at 1 {
+ device_type = "cpu";
+- reg = <1>;
+- d-cache-line-size = <20>; // 32 bytes
+- i-cache-line-size = <20>; // 32 bytes
+- d-cache-size = <8000>; // L1, 32K
+- i-cache-size = <8000>; // L1, 32K
++ reg = <0x1>;
++ d-cache-line-size = <32>; // 32 bytes
++ i-cache-line-size = <32>; // 32 bytes
++ d-cache-size = <0x8000>; // L1, 32K
++ i-cache-size = <0x8000>; // L1, 32K
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+@@ -58,38 +59,38 @@
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 00000000>; // Filled by U-Boot
++ reg = <0x0 0x0>; // Filled by U-Boot
+ };
+
+ soc8572 at ffe00000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+- ranges = <00000000 ffe00000 00100000>;
+- reg = <ffe00000 00001000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed
++ ranges = <0x0 0xffe00000 0x100000>;
++ reg = <0xffe00000 0x1000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed
+ bus-frequency = <0>; // Filled out by uboot.
+
+ memory-controller at 2000 {
+ compatible = "fsl,mpc8572-memory-controller";
+- reg = <2000 1000>;
++ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+- interrupts = <12 2>;
++ interrupts = <18 2>;
};
- wdt at b410 { /* watchdog timer */
-- compatible = "marvell,mv64x60-wdt";
-- reg = <b410 8>;
-- timeout = <a>; /* wdt timeout in seconds */
-+ compatible = "marvell,mv64360-wdt";
-+ reg = <0xb410 0x8>;
+ memory-controller at 6000 {
+ compatible = "fsl,mpc8572-memory-controller";
+- reg = <6000 1000>;
++ reg = <0x6000 0x1000>;
+ interrupt-parent = <&mpic>;
+- interrupts = <12 2>;
++ interrupts = <18 2>;
};
- i2c at c000 {
- device_type = "i2c";
-- compatible = "marvell,mv64x60-i2c";
-- reg = <c000 20>;
-- virtual-reg = <f100c000>;
-- freq_m = <8>;
-- freq_n = <3>;
-- timeout = <3e8>; /* 1000 = 1 second */
-- retries = <1>;
-- interrupts = <25>;
-- interrupt-parent = <&/mv64x60/pic>;
-+ compatible = "marvell,mv64360-i2c";
-+ reg = <0xc000 0x20>;
-+ virtual-reg = <0xf100c000>;
-+ interrupts = <37>;
-+ interrupt-parent = <&PIC>;
+ l2-cache-controller at 20000 {
+ compatible = "fsl,mpc8572-l2-cache-controller";
+- reg = <20000 1000>;
+- cache-line-size = <20>; // 32 bytes
+- cache-size = <80000>; // L2, 512K
++ reg = <0x20000 0x1000>;
++ cache-line-size = <32>; // 32 bytes
++ cache-size = <0x80000>; // L2, 512K
+ interrupt-parent = <&mpic>;
+- interrupts = <10 2>;
++ interrupts = <16 2>;
};
-- 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;
+ i2c at 3000 {
+@@ -97,8 +98,8 @@
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+- reg = <3000 100>;
+- interrupts = <2b 2>;
++ reg = <0x3000 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+@@ -108,8 +109,8 @@
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+- reg = <3100 100>;
+- interrupts = <2b 2>;
++ reg = <0x3100 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
};
+@@ -118,27 +119,27 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-mdio";
+- reg = <24520 20>;
++ reg = <0x24520 0x20>;
- mpp at f000 {
-- compatible = "marvell,mv64x60-mpp";
-- reg = <f000 10>;
-+ compatible = "marvell,mv64360-mpp";
-+ reg = <0xf000 0x10>;
+ phy0: ethernet-phy at 0 {
+ interrupt-parent = <&mpic>;
+- interrupts = <a 1>;
+- reg = <0>;
++ interrupts = <10 1>;
++ reg = <0x0>;
+ };
+ phy1: ethernet-phy at 1 {
+ interrupt-parent = <&mpic>;
+- interrupts = <a 1>;
+- reg = <1>;
++ interrupts = <10 1>;
++ reg = <0x1>;
+ };
+ phy2: ethernet-phy at 2 {
+ interrupt-parent = <&mpic>;
+- interrupts = <a 1>;
+- reg = <2>;
++ interrupts = <10 1>;
++ reg = <0x2>;
+ };
+ phy3: ethernet-phy at 3 {
+ interrupt-parent = <&mpic>;
+- interrupts = <a 1>;
+- reg = <3>;
++ interrupts = <10 1>;
++ reg = <0x3>;
+ };
};
- gpp at f100 {
-- compatible = "marvell,mv64x60-gpp";
-- reg = <f100 20>;
-+ compatible = "marvell,mv64360-gpp";
-+ reg = <0xf100 0x20>;
+@@ -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>;
};
- pci at 80000000 {
-@@ -244,73 +228,75 @@
+@@ -208,15 +209,15 @@
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4600 100>;
++ reg = <0x4600 0x100>;
+ clock-frequency = <0>;
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ global-utilities at e0000 { //global utilities block
+ compatible = "fsl,mpc8572-guts";
+- reg = <e0000 1000>;
++ reg = <0xe0000 0x1000>;
+ fsl,has-rstcr;
+ };
+
+@@ -225,7 +226,7 @@
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- reg = <40000 40000>;
++ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ big-endian;
+@@ -239,167 +240,167 @@
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <ffe08000 1000>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 80000000 80000000 0 20000000
+- 01000000 0 00000000 ffc00000 0 00010000>;
+- clock-frequency = <1fca055>;
++ reg = <0xffe08000 0x1000>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xffc00000 0x0 0x10000>;
++ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+- interrupts = <18 2>;
+- interrupt-map-mask = <ff00 0 0 7>;
++ interrupts = <24 2>;
++ interrupt-map-mask = <0xff00 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x11 func 0 - PCI slot 1 */
+- 8800 0 0 1 &mpic 2 1
+- 8800 0 0 2 &mpic 3 1
+- 8800 0 0 3 &mpic 4 1
+- 8800 0 0 4 &mpic 1 1
++ 0x8800 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x8800 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x8800 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x8800 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x11 func 1 - PCI slot 1 */
+- 8900 0 0 1 &mpic 2 1
+- 8900 0 0 2 &mpic 3 1
+- 8900 0 0 3 &mpic 4 1
+- 8900 0 0 4 &mpic 1 1
++ 0x8900 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x8900 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x8900 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x8900 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x11 func 2 - PCI slot 1 */
+- 8a00 0 0 1 &mpic 2 1
+- 8a00 0 0 2 &mpic 3 1
+- 8a00 0 0 3 &mpic 4 1
+- 8a00 0 0 4 &mpic 1 1
++ 0x8a00 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x8a00 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x8a00 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x8a00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x11 func 3 - PCI slot 1 */
+- 8b00 0 0 1 &mpic 2 1
+- 8b00 0 0 2 &mpic 3 1
+- 8b00 0 0 3 &mpic 4 1
+- 8b00 0 0 4 &mpic 1 1
++ 0x8b00 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x8b00 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x8b00 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x8b00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x11 func 4 - PCI slot 1 */
+- 8c00 0 0 1 &mpic 2 1
+- 8c00 0 0 2 &mpic 3 1
+- 8c00 0 0 3 &mpic 4 1
+- 8c00 0 0 4 &mpic 1 1
++ 0x8c00 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x8c00 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x8c00 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x8c00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x11 func 5 - PCI slot 1 */
+- 8d00 0 0 1 &mpic 2 1
+- 8d00 0 0 2 &mpic 3 1
+- 8d00 0 0 3 &mpic 4 1
+- 8d00 0 0 4 &mpic 1 1
++ 0x8d00 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x8d00 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x8d00 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x8d00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x11 func 6 - PCI slot 1 */
+- 8e00 0 0 1 &mpic 2 1
+- 8e00 0 0 2 &mpic 3 1
+- 8e00 0 0 3 &mpic 4 1
+- 8e00 0 0 4 &mpic 1 1
++ 0x8e00 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x8e00 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x8e00 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x8e00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x11 func 7 - PCI slot 1 */
+- 8f00 0 0 1 &mpic 2 1
+- 8f00 0 0 2 &mpic 3 1
+- 8f00 0 0 3 &mpic 4 1
+- 8f00 0 0 4 &mpic 1 1
++ 0x8f00 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x8f00 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x8f00 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x8f00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x12 func 0 - PCI slot 2 */
+- 9000 0 0 1 &mpic 3 1
+- 9000 0 0 2 &mpic 4 1
+- 9000 0 0 3 &mpic 1 1
+- 9000 0 0 4 &mpic 2 1
++ 0x9000 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x9000 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x9000 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x9000 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x12 func 1 - PCI slot 2 */
+- 9100 0 0 1 &mpic 3 1
+- 9100 0 0 2 &mpic 4 1
+- 9100 0 0 3 &mpic 1 1
+- 9100 0 0 4 &mpic 2 1
++ 0x9100 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x9100 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x9100 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x9100 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x12 func 2 - PCI slot 2 */
+- 9200 0 0 1 &mpic 3 1
+- 9200 0 0 2 &mpic 4 1
+- 9200 0 0 3 &mpic 1 1
+- 9200 0 0 4 &mpic 2 1
++ 0x9200 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x9200 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x9200 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x9200 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x12 func 3 - PCI slot 2 */
+- 9300 0 0 1 &mpic 3 1
+- 9300 0 0 2 &mpic 4 1
+- 9300 0 0 3 &mpic 1 1
+- 9300 0 0 4 &mpic 2 1
++ 0x9300 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x9300 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x9300 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x9300 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x12 func 4 - PCI slot 2 */
+- 9400 0 0 1 &mpic 3 1
+- 9400 0 0 2 &mpic 4 1
+- 9400 0 0 3 &mpic 1 1
+- 9400 0 0 4 &mpic 2 1
++ 0x9400 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x9400 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x9400 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x9400 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x12 func 5 - PCI slot 2 */
+- 9500 0 0 1 &mpic 3 1
+- 9500 0 0 2 &mpic 4 1
+- 9500 0 0 3 &mpic 1 1
+- 9500 0 0 4 &mpic 2 1
++ 0x9500 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x9500 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x9500 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x9500 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x12 func 6 - PCI slot 2 */
+- 9600 0 0 1 &mpic 3 1
+- 9600 0 0 2 &mpic 4 1
+- 9600 0 0 3 &mpic 1 1
+- 9600 0 0 4 &mpic 2 1
++ 0x9600 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x9600 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x9600 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x9600 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x12 func 7 - PCI slot 2 */
+- 9700 0 0 1 &mpic 3 1
+- 9700 0 0 2 &mpic 4 1
+- 9700 0 0 3 &mpic 1 1
+- 9700 0 0 4 &mpic 2 1
++ 0x9700 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x9700 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x9700 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x9700 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ // IDSEL 0x1c USB
+- e000 0 0 1 &i8259 c 2
+- e100 0 0 2 &i8259 9 2
+- e200 0 0 3 &i8259 a 2
+- e300 0 0 4 &i8259 b 2
++ 0xe000 0x0 0x0 0x1 &i8259 0xc 0x2
++ 0xe100 0x0 0x0 0x2 &i8259 0x9 0x2
++ 0xe200 0x0 0x0 0x3 &i8259 0xa 0x2
++ 0xe300 0x0 0x0 0x4 &i8259 0xb 0x2
+
+ // IDSEL 0x1d Audio
+- e800 0 0 1 &i8259 6 2
++ 0xe800 0x0 0x0 0x1 &i8259 0x6 0x2
+
+ // IDSEL 0x1e Legacy
+- f000 0 0 1 &i8259 7 2
+- f100 0 0 1 &i8259 7 2
++ 0xf000 0x0 0x0 0x1 &i8259 0x7 0x2
++ 0xf100 0x0 0x0 0x1 &i8259 0x7 0x2
+
+ // IDSEL 0x1f IDE/SATA
+- f800 0 0 1 &i8259 e 2
+- f900 0 0 1 &i8259 5 2
++ 0xf800 0x0 0x0 0x1 &i8259 0xe 0x2
++ 0xf900 0x0 0x0 0x1 &i8259 0x5 0x2
+
+ >;
+
+ pcie at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
#size-cells = <2>;
- #interrupt-cells = <1>;
+ #address-cells = <3>;
device_type = "pci";
-- compatible = "marvell,mv64x60-pci";
-- reg = <0cf8 8>;
-- ranges = <01000000 0 0 88000000 0 01000000
-- 02000000 0 80000000 80000000 0 08000000>;
-- bus-range = <0 ff>;
-- clock-frequency = <3EF1480>;
-- interrupt-pci-iack = <0c34>;
-- interrupt-parent = <&/mv64x60/pic>;
-- interrupt-map-mask = <f800 0 0 7>;
-+ compatible = "marvell,mv64360-pci";
-+ reg = <0xcf8 0x8>;
-+ ranges = <0x01000000 0x0 0x0
-+ 0x88000000 0x0 0x01000000
-+ 0x02000000 0x0 0x80000000
-+ 0x80000000 0x0 0x08000000>;
-+ bus-range = <0 255>;
-+ clock-frequency = <66000000>;
-+ interrupt-pci-iack = <0xc34>;
-+ interrupt-parent = <&PIC>;
-+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
- /* IDSEL 0x0a */
-- 5000 0 0 1 &/mv64x60/pic 50
-- 5000 0 0 2 &/mv64x60/pic 51
-- 5000 0 0 3 &/mv64x60/pic 5b
-- 5000 0 0 4 &/mv64x60/pic 5d
-+ 0x5000 0 0 1 &PIC 80
-+ 0x5000 0 0 2 &PIC 81
-+ 0x5000 0 0 3 &PIC 91
-+ 0x5000 0 0 4 &PIC 93
+- ranges = <02000000 0 80000000
+- 02000000 0 80000000
+- 0 20000000
++ ranges = <0x2000000 0x0 0x80000000
++ 0x2000000 0x0 0x80000000
++ 0x0 0x20000000
- /* 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
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00100000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x100000>;
+ uli1575 at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- ranges = <02000000 0 80000000
+- 02000000 0 80000000
+- 0 20000000
++ ranges = <0x2000000 0x0 0x80000000
++ 0x2000000 0x0 0x80000000
++ 0x0 0x20000000
- /* 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
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00100000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x100000>;
+ isa at 1e {
+ device_type = "isa";
+ #interrupt-cells = <2>;
+ #size-cells = <1>;
+ #address-cells = <2>;
+- reg = <f000 0 0 0 0>;
+- ranges = <1 0 01000000 0 0
+- 00001000>;
++ reg = <0xf000 0x0 0x0 0x0 0x0>;
++ ranges = <0x1 0x0 0x1000000 0x0 0x0
++ 0x1000>;
+ interrupt-parent = <&i8259>;
- /* 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
+ i8259: interrupt-controller at 20 {
+- reg = <1 20 2
+- 1 a0 2
+- 1 4d0 2>;
++ reg = <0x1 0x20 0x2
++ 0x1 0xa0 0x2
++ 0x1 0x4d0 0x2>;
+ interrupt-controller;
+ device_type = "interrupt-controller";
+ #address-cells = <0>;
+@@ -412,29 +413,29 @@
+ i8042 at 60 {
+ #size-cells = <0>;
+ #address-cells = <1>;
+- reg = <1 60 1 1 64 1>;
+- interrupts = <1 3 c 3>;
++ reg = <0x1 0x60 0x1 0x1 0x64 0x1>;
++ interrupts = <1 3 12 3>;
+ interrupt-parent =
+ <&i8259>;
+
+ keyboard at 0 {
+- reg = <0>;
++ reg = <0x0>;
+ compatible = "pnpPNP,303";
+ };
+
+ mouse at 1 {
+- reg = <1>;
++ reg = <0x1>;
+ compatible = "pnpPNP,f03";
+ };
+ };
+
+ rtc at 70 {
+ compatible = "pnpPNP,b00";
+- reg = <1 70 2>;
++ reg = <0x1 0x70 0x2>;
+ };
+
+ gpio at 400 {
+- reg = <1 400 80>;
++ reg = <0x1 0x400 0x80>;
+ };
+ };
+ };
+@@ -449,33 +450,33 @@
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <ffe09000 1000>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 a0000000 a0000000 0 20000000
+- 01000000 0 00000000 ffc10000 0 00010000>;
+- clock-frequency = <1fca055>;
++ reg = <0xffe09000 0x1000>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xffc10000 0x0 0x10000>;
++ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+- interrupts = <1a 2>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupts = <26 2>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+- 0000 0 0 1 &mpic 4 1
+- 0000 0 0 2 &mpic 5 1
+- 0000 0 0 3 &mpic 6 1
+- 0000 0 0 4 &mpic 7 1
++ 0000 0x0 0x0 0x1 &mpic 0x4 0x1
++ 0000 0x0 0x0 0x2 &mpic 0x5 0x1
++ 0000 0x0 0x0 0x3 &mpic 0x6 0x1
++ 0000 0x0 0x0 0x4 &mpic 0x7 0x1
>;
+ pcie at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+- ranges = <02000000 0 a0000000
+- 02000000 0 a0000000
+- 0 20000000
++ ranges = <0x2000000 0x0 0xa0000000
++ 0x2000000 0x0 0xa0000000
++ 0x0 0x20000000
+
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00100000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x100000>;
};
+ };
- cpu-error at 0070 {
-- compatible = "marvell,mv64x60-cpu-error";
-- reg = <0070 10 0128 28>;
-- interrupts = <03>;
-- interrupt-parent = <&/mv64x60/pic>;
-+ compatible = "marvell,mv64360-cpu-error";
-+ reg = <0x70 0x10 0x128 0x28>;
-+ interrupts = <3>;
-+ interrupt-parent = <&PIC>;
+@@ -486,33 +487,33 @@
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <ffe0a000 1000>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 c0000000 c0000000 0 20000000
+- 01000000 0 00000000 ffc20000 0 00010000>;
+- clock-frequency = <1fca055>;
++ reg = <0xffe0a000 0x1000>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0xc0000000 0xc0000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xffc20000 0x0 0x10000>;
++ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+- interrupts = <1b 2>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupts = <27 2>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+- 0000 0 0 1 &mpic 0 1
+- 0000 0 0 2 &mpic 1 1
+- 0000 0 0 3 &mpic 2 1
+- 0000 0 0 4 &mpic 3 1
++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1
+ >;
+ pcie at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+- ranges = <02000000 0 c0000000
+- 02000000 0 c0000000
+- 0 20000000
++ ranges = <0x2000000 0x0 0xc0000000
++ 0x2000000 0x0 0xc0000000
++ 0x0 0x20000000
+
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00100000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x100000>;
};
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts
+index 16c947b..1f2f1e0 100644
+--- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts
++++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts
+@@ -45,6 +45,11 @@
+ reg = <0x00000000 0x20000000>; // 512M at 0x0
+ };
- sram-ctrl at 0380 {
-- compatible = "marvell,mv64x60-sram-ctrl";
-- reg = <0380 80>;
-- interrupts = <0d>;
-- interrupt-parent = <&/mv64x60/pic>;
-+ compatible = "marvell,mv64360-sram-ctrl";
-+ reg = <0x380 0x80>;
-+ interrupts = <13>;
-+ interrupt-parent = <&PIC>;
++ board-control at e8000000 {
++ compatible = "fsl,fpga-pixis";
++ reg = <0xe8000000 32>; // pixis at 0xe8000000
++ };
++
+ soc at e0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+@@ -104,6 +109,13 @@
+ interrupt-parent = <&mpic>;
};
- pci-error at 1d40 {
-- compatible = "marvell,mv64x60-pci-error";
-- reg = <1d40 40 0c28 4>;
-- interrupts = <0c>;
-- interrupt-parent = <&/mv64x60/pic>;
-+ compatible = "marvell,mv64360-pci-error";
-+ reg = <0x1d40 0x40 0xc28 0x4>;
-+ interrupts = <12>;
-+ interrupt-parent = <&PIC>;
++ display at 2c000 {
++ compatible = "fsl,diu";
++ reg = <0x2c000 100>;
++ interrupts = <72 2>;
++ interrupt-parent = <&mpic>;
++ };
++
+ mpic: interrupt-controller at 40000 {
+ clock-frequency = <0>;
+ interrupt-controller;
+diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
+index 79385bc..1e4bfe9 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>;
+
+@@ -26,6 +26,7 @@
+ serial1 = &serial1;
+ pci0 = &pci0;
+ pci1 = &pci1;
++ rapidio0 = &rapidio0;
+ };
+
+ cpus {
+@@ -500,4 +501,15 @@
+ 0x0 0x00100000>;
};
+ };
++ rapidio0: rapidio at f80c0000 {
++ #address-cells = <2>;
++ #size-cells = <2>;
++ compatible = "fsl,rapidio-delta";
++ reg = <0xf80c0000 0x20000>;
++ ranges = <0 0 0xc0000000 0 0x20000000>;
++ interrupt-parent = <&mpic>;
++ /* err_irq bell_outb_irq bell_inb_irq
++ msg1_tx_irq msg1_rx_irq msg2_tx_irq msg2_rx_irq */
++ interrupts = <48 2 49 2 50 2 53 2 54 2 55 2 56 2>;
++ };
+ };
+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.
+ */
- mem-ctrl at 1400 {
-- compatible = "marvell,mv64x60-mem-ctrl";
-- reg = <1400 60>;
-- interrupts = <11>;
-- interrupt-parent = <&/mv64x60/pic>;
-+ compatible = "marvell,mv64360-mem-ctrl";
-+ reg = <0x1400 0x60>;
-+ interrupts = <17>;
-+ interrupt-parent = <&PIC>;
++/dts-v1/;
+
+ / {
+ model = "MPC866ADS";
+@@ -22,37 +24,37 @@
+
+ PowerPC,866 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <10>; // 16 bytes
+- i-cache-line-size = <10>; // 16 bytes
+- d-cache-size = <2000>; // L1, 8K
+- i-cache-size = <4000>; // L1, 16K
++ reg = <0x0>;
++ d-cache-line-size = <16>; // 16 bytes
++ i-cache-line-size = <16>; // 16 bytes
++ d-cache-size = <0x2000>; // L1, 8K
++ i-cache-size = <0x4000>; // L1, 16K
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+- interrupts = <f 2>; // decrementer interrupt
++ interrupts = <15 2>; // decrementer interrupt
+ interrupt-parent = <&PIC>;
};
};
- chosen {
- bootargs = "ip=on";
-- linux,stdout-path = "/mv64x60 at f1000000/mpsc at 8000";
-+ linux,stdout-path = &MPSC0;
+ memory {
+ device_type = "memory";
+- reg = <00000000 800000>;
++ reg = <0x0 0x800000>;
};
- };
-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 @@
+
+ localbus at ff000100 {
+ compatible = "fsl,mpc866-localbus", "fsl,pq1-localbus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+- reg = <ff000100 40>;
++ reg = <0xff000100 0x40>;
+
+ ranges = <
+- 1 0 ff080000 00008000
+- 5 0 ff0a0000 00008000
++ 0x1 0x0 0xff080000 0x8000
++ 0x5 0x0 0xff0a0000 0x8000
+ >;
+
+ board-control at 1,0 {
+- reg = <1 0 20 5 300 4>;
++ reg = <0x1 0x0 0x20 0x5 0x300 0x4>;
+ compatible = "fsl,mpc866ads-bcsr";
+ };
+ };
+@@ -61,17 +63,17 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+- ranges = <0 ff000000 00100000>;
+- reg = <ff000000 00000200>;
++ ranges = <0x0 0xff000000 0x100000>;
++ reg = <0xff000000 0x200>;
+ bus-frequency = <0>;
+
+ mdio at e00 {
+ compatible = "fsl,mpc866-fec-mdio", "fsl,pq1-fec-mdio";
+- reg = <e00 188>;
++ reg = <0xe00 0x188>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ PHY: ethernet-phy at f {
+- reg = <f>;
++ reg = <0xf>;
+ device_type = "ethernet-phy";
};
+ };
+@@ -80,7 +82,7 @@
+ device_type = "network";
+ compatible = "fsl,mpc866-fec-enet",
+ "fsl,pq1-fec-enet";
+- reg = <e00 188>;
++ reg = <0xe00 0x188>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <3 1>;
+ interrupt-parent = <&PIC>;
+@@ -91,7 +93,7 @@
+ PIC: pic at 0 {
+ interrupt-controller;
+ #interrupt-cells = <2>;
+- reg = <0 24>;
++ reg = <0x0 0x24>;
+ compatible = "fsl,mpc866-pic", "fsl,pq1-pic";
+ };
- EMAC0: ethernet at ef600e00 {
-- linux,network-index = <0>;
+@@ -100,7 +102,7 @@
+ #size-cells = <1>;
+ compatible = "fsl,mpc866-cpm", "fsl,cpm1";
+ ranges;
+- reg = <9c0 40>;
++ reg = <0x9c0 0x40>;
+ brg-frequency = <0>;
+ interrupts = <0 2>; // cpm error interrupt
+ interrupt-parent = <&CPM_PIC>;
+@@ -108,11 +110,11 @@
+ muram at 2000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+- ranges = <0 2000 2000>;
++ ranges = <0x0 0x2000 0x2000>;
+
+ data at 0 {
+ compatible = "fsl,cpm-muram-data";
+- reg = <0 1c00>;
++ reg = <0x0 0x1c00>;
+ };
+ };
+
+@@ -120,7 +122,7 @@
+ compatible = "fsl,mpc866-brg",
+ "fsl,cpm1-brg",
+ "fsl,cpm-brg";
+- reg = <9f0 10>;
++ reg = <0x9f0 0x10>;
+ clock-frequency = <0>;
+ };
+
+@@ -130,7 +132,7 @@
+ #interrupt-cells = <1>;
+ interrupts = <5 2 0 2>;
+ interrupt-parent = <&PIC>;
+- reg = <930 20>;
++ reg = <0x930 0x20>;
+ compatible = "fsl,mpc866-cpm-pic",
+ "fsl,cpm1-pic";
+ };
+@@ -140,31 +142,31 @@
+ device_type = "serial";
+ compatible = "fsl,mpc866-smc-uart",
+ "fsl,cpm1-smc-uart";
+- reg = <a80 10 3e80 40>;
++ reg = <0xa80 0x10 0x3e80 0x40>;
+ interrupts = <4>;
+ interrupt-parent = <&CPM_PIC>;
+ fsl,cpm-brg = <1>;
+- fsl,cpm-command = <0090>;
++ fsl,cpm-command = <0x90>;
+ };
+
+ serial at a90 {
+ device_type = "serial";
+ compatible = "fsl,mpc866-smc-uart",
+ "fsl,cpm1-smc-uart";
+- reg = <a90 10 3f80 40>;
++ reg = <0xa90 0x10 0x3f80 0x40>;
+ interrupts = <3>;
+ interrupt-parent = <&CPM_PIC>;
+ fsl,cpm-brg = <2>;
+- fsl,cpm-command = <00d0>;
++ fsl,cpm-command = <0xd0>;
+ };
+
+ ethernet at a00 {
device_type = "network";
- compatible = "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 @@
+ compatible = "fsl,mpc866-scc-enet",
+ "fsl,cpm1-scc-enet";
+- reg = <a00 18 3c00 100>;
++ reg = <0xa00 0x18 0x3c00 0x100>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1e>;
++ interrupts = <30>;
+ interrupt-parent = <&CPM_PIC>;
+ fsl,cpm-command = <0000>;
+ linux,network-index = <1>;
+diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts
+index d84a012..9895043 100644
+--- a/arch/powerpc/boot/dts/mpc885ads.dts
++++ b/arch/powerpc/boot/dts/mpc885ads.dts
+@@ -2,7 +2,7 @@
+ * MPC885 ADS Device Tree Source
+ *
+ * Copyright 2006 MontaVista Software, Inc.
+- * Copyright 2007 Freescale Semiconductor, Inc.
++ * Copyright 2007,2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+@@ -10,6 +10,7 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
+
+ / {
+ model = "MPC885ADS";
+@@ -23,45 +24,45 @@
+
+ PowerPC,885 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <d#16>;
+- i-cache-line-size = <d#16>;
+- d-cache-size = <d#8192>;
+- i-cache-size = <d#8192>;
++ reg = <0x0>;
++ d-cache-line-size = <16>;
++ i-cache-line-size = <16>;
++ d-cache-size = <8192>;
++ i-cache-size = <8192>;
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+- interrupts = <f 2>; // decrementer interrupt
++ interrupts = <15 2>; // decrementer interrupt
+ interrupt-parent = <&PIC>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+- reg = <0 0>;
++ reg = <0x0 0x0>;
+ };
+
+ localbus at ff000100 {
+ compatible = "fsl,mpc885-localbus", "fsl,pq1-localbus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+- reg = <ff000100 40>;
++ reg = <0xff000100 0x40>;
+
+ ranges = <
+- 0 0 fe000000 00800000
+- 1 0 ff080000 00008000
+- 5 0 ff0a0000 00008000
++ 0x0 0x0 0xfe000000 0x800000
++ 0x1 0x0 0xff080000 0x8000
++ 0x5 0x0 0xff0a0000 0x8000
+ >;
+
+ flash at 0,0 {
+ compatible = "jedec-flash";
+- reg = <0 0 800000>;
++ reg = <0x0 0x0 0x800000>;
+ bank-width = <4>;
+ device-width = <1>;
+ };
+
+ board-control at 1,0 {
+- reg = <1 0 20 5 300 4>;
++ reg = <0x1 0x0 0x20 0x5 0x300 0x4>;
+ compatible = "fsl,mpc885ads-bcsr";
+ };
+ };
+@@ -71,30 +72,30 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+- ranges = <0 ff000000 00004000>;
++ ranges = <0x0 0xff000000 0x4000>;
+ bus-frequency = <0>;
+
+ // Temporary -- will go away once kernel uses ranges for get_immrbase().
+- reg = <ff000000 4000>;
++ reg = <0xff000000 0x4000>;
+
+ mdio at e00 {
+ compatible = "fsl,mpc885-fec-mdio", "fsl,pq1-fec-mdio";
+- reg = <e00 188>;
++ reg = <0xe00 0x188>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PHY0: ethernet-phy at 0 {
+- reg = <0>;
++ reg = <0x0>;
+ device_type = "ethernet-phy";
};
- EMAC1: ethernet at ef600f00 {
-- linux,network-index = <1>;
+ PHY1: ethernet-phy at 1 {
+- reg = <1>;
++ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+
+ PHY2: ethernet-phy at 2 {
+- reg = <2>;
++ reg = <0x2>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -103,7 +104,7 @@
+ device_type = "network";
+ compatible = "fsl,mpc885-fec-enet",
+ "fsl,pq1-fec-enet";
+- reg = <e00 188>;
++ reg = <0xe00 0x188>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <3 1>;
+ interrupt-parent = <&PIC>;
+@@ -115,7 +116,7 @@
+ device_type = "network";
+ compatible = "fsl,mpc885-fec-enet",
+ "fsl,pq1-fec-enet";
+- reg = <1e00 188>;
++ reg = <0x1e00 0x188>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <7 1>;
+ interrupt-parent = <&PIC>;
+@@ -126,7 +127,7 @@
+ PIC: interrupt-controller at 0 {
+ interrupt-controller;
+ #interrupt-cells = <2>;
+- reg = <0 24>;
++ reg = <0x0 0x24>;
+ compatible = "fsl,mpc885-pic", "fsl,pq1-pic";
+ };
+
+@@ -136,29 +137,29 @@
+ #size-cells = <2>;
+ compatible = "fsl,pq-pcmcia";
+ device_type = "pcmcia";
+- reg = <80 80>;
++ reg = <0x80 0x80>;
+ interrupt-parent = <&PIC>;
+- interrupts = <d 1>;
++ interrupts = <13 1>;
+ };
+
+ cpm at 9c0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc885-cpm", "fsl,cpm1";
+- command-proc = <9c0>;
++ command-proc = <0x9c0>;
+ interrupts = <0>; // cpm error interrupt
+ interrupt-parent = <&CPM_PIC>;
+- reg = <9c0 40>;
++ reg = <0x9c0 0x40>;
+ ranges;
+
+ muram at 2000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+- ranges = <0 2000 2000>;
++ ranges = <0x0 0x2000 0x2000>;
+
+ data at 0 {
+ compatible = "fsl,cpm-muram-data";
+- reg = <0 1c00>;
++ reg = <0x0 0x1c00>;
+ };
+ };
+
+@@ -167,7 +168,7 @@
+ "fsl,cpm1-brg",
+ "fsl,cpm-brg";
+ clock-frequency = <0>;
+- reg = <9f0 10>;
++ reg = <0x9f0 0x10>;
+ };
+
+ CPM_PIC: interrupt-controller at 930 {
+@@ -175,7 +176,7 @@
+ #interrupt-cells = <1>;
+ interrupts = <5 2 0 2>;
+ interrupt-parent = <&PIC>;
+- reg = <930 20>;
++ reg = <0x930 0x20>;
+ compatible = "fsl,mpc885-cpm-pic",
+ "fsl,cpm1-pic";
+ };
+@@ -184,34 +185,34 @@
+ device_type = "serial";
+ compatible = "fsl,mpc885-smc-uart",
+ "fsl,cpm1-smc-uart";
+- reg = <a80 10 3e80 40>;
++ reg = <0xa80 0x10 0x3e80 0x40>;
+ interrupts = <4>;
+ interrupt-parent = <&CPM_PIC>;
+ fsl,cpm-brg = <1>;
+- fsl,cpm-command = <0090>;
++ fsl,cpm-command = <0x90>;
+ };
+
+ serial at a90 {
+ device_type = "serial";
+ compatible = "fsl,mpc885-smc-uart",
+ "fsl,cpm1-smc-uart";
+- reg = <a90 10 3f80 40>;
++ reg = <0xa90 0x10 0x3f80 0x40>;
+ interrupts = <3>;
+ interrupt-parent = <&CPM_PIC>;
+ fsl,cpm-brg = <2>;
+- fsl,cpm-command = <00d0>;
++ fsl,cpm-command = <0xd0>;
+ };
+
+ ethernet at a40 {
device_type = "network";
- compatible = "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
+ compatible = "fsl,mpc885-scc-enet",
+ "fsl,cpm1-scc-enet";
+- reg = <a40 18 3e00 100>;
++ reg = <0xa40 0x18 0x3e00 0x100>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1c>;
++ interrupts = <28>;
+ interrupt-parent = <&CPM_PIC>;
+ phy-handle = <&PHY2>;
+- fsl,cpm-command = <0080>;
++ fsl,cpm-command = <0x80>;
+ linux,network-index = <2>;
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/pcm030.dts b/arch/powerpc/boot/dts/pcm030.dts
new file mode 100644
-index 0000000..3eebeec
+index 0000000..7c1bb95
--- /dev/null
-+++ b/arch/powerpc/boot/dts/sbc8641d.dts
-@@ -0,0 +1,352 @@
++++ b/arch/powerpc/boot/dts/pcm030.dts
+@@ -0,0 +1,363 @@
+/*
-+ * SBC8641D Device Tree Source
-+ *
-+ * Copyright 2008 Wind River Systems Inc.
-+ *
-+ * Paul Gortmaker (see MAINTAINERS for contact information)
++ * phyCORE-MPC5200B-tiny (pcm030) board Device Tree Source
+ *
-+ * Based largely on the mpc8641_hpcn.dts by Freescale Semiconductor Inc.
++ * Copyright 2006 Pengutronix
++ * Sascha Hauer <s.hauer at pengutronix.de>
++ * Copyright 2007 Pengutronix
++ * Juergen Beisert <j.beisert at pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
@@ -105794,315 +137190,1481 @@
+/dts-v1/;
+
+/ {
-+ model = "SBC8641D";
-+ compatible = "wind,sbc8641";
++ model = "phytec,pcm030";
++ compatible = "phytec,pcm030";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
-+ aliases {
-+ ethernet0 = &enet0;
-+ ethernet1 = &enet1;
-+ ethernet2 = &enet2;
-+ ethernet3 = &enet3;
-+ serial0 = &serial0;
-+ serial1 = &serial1;
-+ pci0 = &pci0;
-+ pci1 = &pci1;
-+ };
-+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
-+ PowerPC,8641 at 0 {
++ PowerPC,5200 at 0 {
+ device_type = "cpu";
+ reg = <0>;
+ d-cache-line-size = <32>;
+ i-cache-line-size = <32>;
-+ d-cache-size = <32768>; // L1
-+ i-cache-size = <32768>; // L1
-+ timebase-frequency = <0>; // From uboot
-+ bus-frequency = <0>; // From uboot
-+ clock-frequency = <0>; // From uboot
-+ };
-+ PowerPC,8641 at 1 {
-+ device_type = "cpu";
-+ reg = <1>;
-+ d-cache-line-size = <32>;
-+ i-cache-line-size = <32>;
-+ d-cache-size = <32768>;
-+ i-cache-size = <32768>;
-+ timebase-frequency = <0>; // From uboot
-+ bus-frequency = <0>; // From uboot
-+ clock-frequency = <0>; // From uboot
++ d-cache-size = <0x4000>; /* L1, 16K */
++ i-cache-size = <0x4000>; /* L1, 16K */
++ timebase-frequency = <0>; /* From Bootloader */
++ bus-frequency = <0>; /* From Bootloader */
++ clock-frequency = <0>; /* From Bootloader */
+ };
+ };
+
+ memory {
+ device_type = "memory";
-+ reg = <0x00000000 0x20000000>; // 512M at 0x0
++ reg = <0x00000000 0x04000000>; /* 64MB */
+ };
+
-+ localbus at f8005000 {
-+ #address-cells = <2>;
++ soc5200 at f0000000 {
++ #address-cells = <1>;
+ #size-cells = <1>;
-+ compatible = "fsl,mpc8641-localbus", "simple-bus";
-+ reg = <0xf8005000 0x1000>;
-+ interrupts = <19 2>;
-+ interrupt-parent = <&mpic>;
++ compatible = "fsl,mpc5200b-immr";
++ ranges = <0x0 0xf0000000 0x0000c000>;
++ bus-frequency = <0>; /* From bootloader */
++ system-frequency = <0>; /* From bootloader */
++
++ cdm at 200 {
++ compatible = "fsl,mpc5200b-cdm","fsl,mpc5200-cdm";
++ reg = <0x200 0x38>;
++ };
+
-+ 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
++ mpc5200_pic: interrupt-controller at 500 {
++ /* 5200 interrupts are encoded into two levels; */
++ interrupt-controller;
++ #interrupt-cells = <3>;
++ device_type = "interrupt-controller";
++ compatible = "fsl,mpc5200b-pic","fsl,mpc5200-pic";
++ reg = <0x500 0x80>;
++ };
+
-+ flash at 0,0 {
-+ compatible = "cfi-flash";
-+ reg = <0 0 0x01000000>;
-+ bank-width = <2>;
-+ device-width = <2>;
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ partition at 0 {
-+ label = "dtb";
-+ reg = <0x00000000 0x00100000>;
-+ read-only;
-+ };
-+ partition at 300000 {
-+ label = "kernel";
-+ reg = <0x00100000 0x00400000>;
-+ read-only;
-+ };
-+ partition at 400000 {
-+ label = "fs";
-+ reg = <0x00500000 0x00a00000>;
-+ };
-+ partition at 700000 {
-+ label = "firmware";
-+ reg = <0x00f00000 0x00100000>;
-+ read-only;
-+ };
++ timer at 600 { /* General Purpose Timer */
++ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
++ cell-index = <0>;
++ reg = <0x600 0x10>;
++ interrupts = <0x1 0x9 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ fsl,has-wdt;
+ };
+
-+ epld at 2,0 {
-+ compatible = "wrs,epld-localbus";
-+ #address-cells = <2>;
-+ #size-cells = <1>;
-+ reg = <2 0 0x100000>;
-+ ranges = <0 0 5 0 1 // User switches
-+ 1 0 5 1 1 // Board ID/Rev
-+ 3 0 5 3 1>; // LEDs
++ timer at 610 { /* General Purpose Timer */
++ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
++ cell-index = <1>;
++ reg = <0x610 0x10>;
++ interrupts = <0x1 0xa 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
+ };
-+ };
+
-+ soc at f8000000 {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ device_type = "soc";
-+ compatible = "simple-bus";
-+ ranges = <0x00000000 0xf8000000 0x00100000>;
-+ reg = <0xf8000000 0x00001000>; // CCSRBAR
-+ bus-frequency = <0>;
++ gpt2: timer at 620 { /* General Purpose Timer in GPIO mode */
++ compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
++ cell-index = <2>;
++ reg = <0x620 0x10>;
++ interrupts = <0x1 0xb 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ gpio-controller;
++ #gpio-cells = <2>;
++ };
+
-+ i2c at 3000 {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ cell-index = <0>;
-+ compatible = "fsl-i2c";
-+ reg = <0x3000 0x100>;
-+ interrupts = <43 2>;
-+ interrupt-parent = <&mpic>;
-+ dfsrr;
++ gpt3: timer at 630 { /* General Purpose Timer in GPIO mode */
++ compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
++ cell-index = <3>;
++ reg = <0x630 0x10>;
++ interrupts = <0x1 0xc 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ gpio-controller;
++ #gpio-cells = <2>;
+ };
+
-+ i2c at 3100 {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ cell-index = <1>;
-+ compatible = "fsl-i2c";
-+ reg = <0x3100 0x100>;
-+ interrupts = <43 2>;
-+ interrupt-parent = <&mpic>;
-+ dfsrr;
++ gpt4: timer at 640 { /* General Purpose Timer in GPIO mode */
++ compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
++ cell-index = <4>;
++ reg = <0x640 0x10>;
++ interrupts = <0x1 0xd 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ gpio-controller;
++ #gpio-cells = <2>;
+ };
+
-+ mdio at 24520 {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ compatible = "fsl,gianfar-mdio";
-+ reg = <0x24520 0x20>;
++ gpt5: timer at 650 { /* General Purpose Timer in GPIO mode */
++ compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
++ cell-index = <5>;
++ reg = <0x650 0x10>;
++ interrupts = <0x1 0xe 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ gpio-controller;
++ #gpio-cells = <2>;
++ };
+
-+ phy0: ethernet-phy at 1f {
-+ interrupt-parent = <&mpic>;
-+ interrupts = <10 1>;
-+ reg = <0x1f>;
-+ device_type = "ethernet-phy";
-+ };
-+ phy1: ethernet-phy at 0 {
-+ interrupt-parent = <&mpic>;
-+ interrupts = <10 1>;
-+ reg = <0>;
-+ device_type = "ethernet-phy";
-+ };
-+ phy2: ethernet-phy at 1 {
-+ interrupt-parent = <&mpic>;
-+ interrupts = <10 1>;
-+ reg = <1>;
-+ device_type = "ethernet-phy";
-+ };
-+ phy3: ethernet-phy at 2 {
-+ interrupt-parent = <&mpic>;
-+ interrupts = <10 1>;
-+ reg = <2>;
-+ device_type = "ethernet-phy";
-+ };
++ gpt6: timer at 660 { /* General Purpose Timer in GPIO mode */
++ compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
++ cell-index = <6>;
++ reg = <0x660 0x10>;
++ interrupts = <0x1 0xf 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ gpio-controller;
++ #gpio-cells = <2>;
+ };
+
-+ enet0: ethernet at 24000 {
++ gpt7: timer at 670 { /* General Purpose Timer in GPIO mode */
++ compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
++ cell-index = <7>;
++ reg = <0x670 0x10>;
++ interrupts = <0x1 0x10 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ gpio-controller;
++ #gpio-cells = <2>;
++ };
++
++ rtc at 800 { // Real time clock
++ compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
++ device_type = "rtc";
++ reg = <0x800 0x100>;
++ interrupts = <0x1 0x5 0x0 0x1 0x6 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ };
++
++ can at 900 {
++ compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
+ 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";
++ interrupts = <0x2 0x11 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ reg = <0x900 0x80>;
+ };
+
-+ enet1: ethernet at 25000 {
++ can at 980 {
++ compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
+ 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";
++ interrupts = <0x2 0x12 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ reg = <0x980 0x80>;
+ };
+
-+ enet2: ethernet at 26000 {
-+ cell-index = <2>;
-+ device_type = "network";
-+ model = "TSEC";
-+ compatible = "gianfar";
-+ reg = <0x26000 0x1000>;
-+ local-mac-address = [ 00 00 00 00 00 00 ];
-+ interrupts = <31 2 32 2 33 2>;
-+ interrupt-parent = <&mpic>;
-+ phy-handle = <&phy2>;
-+ phy-connection-type = "rgmii-id";
++ gpio_simple: gpio at b00 {
++ compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
++ reg = <0xb00 0x40>;
++ interrupts = <0x1 0x7 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ gpio-controller;
++ #gpio-cells = <2>;
+ };
+
-+ enet3: ethernet at 27000 {
-+ cell-index = <3>;
-+ device_type = "network";
-+ model = "TSEC";
-+ compatible = "gianfar";
-+ reg = <0x27000 0x1000>;
-+ local-mac-address = [ 00 00 00 00 00 00 ];
-+ interrupts = <37 2 38 2 39 2>;
-+ interrupt-parent = <&mpic>;
-+ phy-handle = <&phy3>;
-+ phy-connection-type = "rgmii-id";
++ gpio_wkup: gpio-wkup at c00 {
++ compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
++ reg = <0xc00 0x40>;
++ interrupts = <0x1 0x8 0x0 0x0 0x3 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ gpio-controller;
++ #gpio-cells = <2>;
+ };
+
-+ serial0: serial at 4500 {
++ spi at f00 {
++ compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
++ reg = <0xf00 0x20>;
++ interrupts = <0x2 0xd 0x0 0x2 0xe 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ };
++
++ usb at 1000 {
++ compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
++ reg = <0x1000 0xff>;
++ interrupts = <0x2 0x6 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ };
++
++ dma-controller at 1200 {
++ device_type = "dma-controller";
++ compatible = "fsl,mpc5200b-bestcomm","fsl,mpc5200-bestcomm";
++ reg = <0x1200 0x80>;
++ interrupts = <0x3 0x0 0x0 0x3 0x1 0x0 0x3 0x2 0x0 0x3 0x3 0x0
++ 0x3 0x4 0x0 0x3 0x5 0x0 0x3 0x6 0x0 0x3 0x7 0x0
++ 0x3 0x8 0x0 0x3 0x9 0x0 0x3 0xa 0x0 0x3 0xb 0x0
++ 0x3 0xc 0x0 0x3 0xd 0x0 0x3 0xe 0x0 0x3 0xf 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ };
++
++ xlb at 1f00 {
++ compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
++ reg = <0x1f00 0x100>;
++ };
++
++ ac97 at 2000 { /* PSC1 in ac97 mode */
++ device_type = "sound";
++ compatible = "mpc5200b-psc-ac97","fsl,mpc5200b-psc-ac97";
+ cell-index = <0>;
++ reg = <0x2000 0x100>;
++ interrupts = <0x2 0x2 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ };
++
++ /* PSC2 port is used by CAN1/2 */
++
++ serial at 2400 { /* PSC3 in UART mode */
+ device_type = "serial";
-+ compatible = "ns16550";
-+ reg = <0x4500 0x100>;
-+ clock-frequency = <0>;
-+ interrupts = <42 2>;
-+ interrupt-parent = <&mpic>;
++ compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
++ port-number = <0>;
++ cell-index = <2>;
++ reg = <0x2400 0x100>;
++ interrupts = <0x2 0x3 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
+ };
+
-+ serial1: serial at 4600 {
-+ cell-index = <1>;
++ /* PSC4 is ??? */
++
++ /* PSC5 is ??? */
++
++ serial at 2c00 { /* PSC6 in UART mode */
+ device_type = "serial";
-+ compatible = "ns16550";
-+ reg = <0x4600 0x100>;
-+ clock-frequency = <0>;
-+ interrupts = <28 2>;
-+ interrupt-parent = <&mpic>;
++ compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
++ port-number = <1>;
++ cell-index = <5>;
++ reg = <0x2c00 0x100>;
++ interrupts = <0x2 0x4 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
+ };
+
-+ mpic: pic at 40000 {
-+ clock-frequency = <0>;
-+ interrupt-controller;
-+ #address-cells = <0>;
-+ #interrupt-cells = <2>;
-+ reg = <0x40000 0x40000>;
-+ compatible = "chrp,open-pic";
-+ device_type = "open-pic";
-+ big-endian;
++ ethernet at 3000 {
++ device_type = "network";
++ compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
++ reg = <0x3000 0x400>;
++ local-mac-address = [00 00 00 00 00 00];
++ interrupts = <0x2 0x5 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ phy-handle = <&phy0>;
+ };
+
-+ global-utilities at e0000 {
-+ compatible = "fsl,mpc8641-guts";
-+ reg = <0xe0000 0x1000>;
-+ fsl,has-rstcr;
++ mdio at 3000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "fsl,mpc5200b-mdio", "fsl,mpc5200-mdio";
++ reg = <0x3000 0x400>; /* fec range, since we need to setup fec interrupts */
++ interrupts = <0x2 0x5 0x0>; /* these are for "mii command finished", not link changes & co. */
++ interrupt-parent = <&mpc5200_pic>;
++
++ phy0:ethernet-phy at 0 {
++ device_type = "ethernet-phy";
++ reg = <0x0>;
++ };
+ };
-+ };
+
-+ pci0: pcie at f8008000 {
-+ cell-index = <0>;
-+ compatible = "fsl,mpc8641-pcie";
-+ device_type = "pci";
-+ #interrupt-cells = <1>;
-+ #size-cells = <2>;
-+ #address-cells = <3>;
-+ reg = <0xf8008000 0x1000>;
-+ bus-range = <0x0 0xff>;
-+ ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000
-+ 0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
-+ clock-frequency = <33333333>;
-+ interrupt-parent = <&mpic>;
-+ interrupts = <24 2>;
-+ interrupt-map-mask = <0xff00 0 0 7>;
-+ interrupt-map = <
-+ /* IDSEL 0x0 */
-+ 0x0000 0 0 1 &mpic 0 1
-+ 0x0000 0 0 2 &mpic 1 1
-+ 0x0000 0 0 3 &mpic 2 1
-+ 0x0000 0 0 4 &mpic 3 1
-+ >;
++ ata at 3a00 {
++ device_type = "ata";
++ compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
++ reg = <0x3a00 0x100>;
++ interrupts = <0x2 0x7 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ };
+
-+ pcie at 0 {
-+ reg = <0 0 0 0 0>;
-+ #size-cells = <2>;
-+ #address-cells = <3>;
-+ device_type = "pci";
-+ ranges = <0x02000000 0x0 0x80000000
-+ 0x02000000 0x0 0x80000000
-+ 0x0 0x20000000
++ i2c at 3d00 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
++ cell-index = <0>;
++ reg = <0x3d00 0x40>;
++ interrupts = <0x2 0xf 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ fsl5200-clocking;
++ };
+
-+ 0x01000000 0x0 0x00000000
-+ 0x01000000 0x0 0x00000000
-+ 0x0 0x00100000>;
++ i2c at 3d40 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
++ cell-index = <1>;
++ reg = <0x3d40 0x40>;
++ interrupts = <0x2 0x10 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ fsl5200-clocking;
++ rtc at 51 {
++ device_type = "rtc";
++ compatible = "nxp,pcf8563";
++ reg = <0x51>;
++ };
++ /* FIXME: EEPROM */
++ };
++
++ sram at 8000 {
++ compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram","sram";
++ reg = <0x8000 0x4000>;
+ };
+
++ /* This is only an example device to show the usage of gpios. It maps all available
++ * gpios to the "gpio-provider" device.
++ */
++ gpio {
++ compatible = "gpio-provider";
++
++ /* mpc52xx exp.con patchfield */
++ gpios = <&gpio_wkup 0 0 /* GPIO_WKUP_7 11d jp13-3 */
++ &gpio_wkup 1 0 /* GPIO_WKUP_6 14c */
++ &gpio_wkup 6 0 /* PSC2_4 43c x5-11 */
++ &gpio_simple 2 0 /* IRDA_1 24c x7-6 set GPS_PORT_CONFIG[IRDA] = 0 */
++ &gpio_simple 3 0 /* IRDA_0 x8-5 set GPS_PORT_CONFIG[IRDA] = 0 */
++ &gpt2 0 0 /* timer2 12d x4-4 */
++ &gpt3 0 0 /* timer3 13d x6-4 */
++ &gpt4 0 0 /* timer4 61c x2-16 */
++ &gpt5 0 0 /* timer5 44c x7-11 */
++ &gpt6 0 0 /* timer6 60c x8-15 */
++ &gpt7 0 0 /* timer7 36a x17-9 */
++ >;
++ };
+ };
+
-+ pci1: pcie at f8009000 {
-+ cell-index = <1>;
-+ compatible = "fsl,mpc8641-pcie";
-+ device_type = "pci";
++ pci at f0000d00 {
+ #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>;
++ device_type = "pci";
++ compatible = "fsl,mpc5200b-pci","fsl,mpc5200-pci";
++ reg = <0xf0000d00 0x100>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
++ interrupt-map = <0xc000 0x0 0x0 0x1 &mpc5200_pic 0x0 0x0 0x3 /* 1st slot */
++ 0xc000 0x0 0x0 0x2 &mpc5200_pic 0x1 0x1 0x3
++ 0xc000 0x0 0x0 0x3 &mpc5200_pic 0x1 0x2 0x3
++ 0xc000 0x0 0x0 0x4 &mpc5200_pic 0x1 0x3 0x3
++
++ 0xc800 0x0 0x0 0x1 &mpc5200_pic 0x1 0x1 0x3 /* 2nd slot */
++ 0xc800 0x0 0x0 0x2 &mpc5200_pic 0x1 0x2 0x3
++ 0xc800 0x0 0x0 0x3 &mpc5200_pic 0x1 0x3 0x3
++ 0xc800 0x0 0x0 0x4 &mpc5200_pic 0x0 0x0 0x3>;
++ clock-frequency = <0>; // From boot loader
++ interrupts = <0x2 0x8 0x0 0x2 0x9 0x0 0x2 0xa 0x0>;
++ interrupt-parent = <&mpc5200_pic>;
++ bus-range = <0 0>;
++ ranges = <0x42000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
++ 0x01000000 0x0 0x00000000 0xb0000000 0x0 0x01000000>;
++ };
++};
+diff --git a/arch/powerpc/boot/dts/pq2fads.dts b/arch/powerpc/boot/dts/pq2fads.dts
+index 2d56492..b2d6109 100644
+--- a/arch/powerpc/boot/dts/pq2fads.dts
++++ b/arch/powerpc/boot/dts/pq2fads.dts
+@@ -1,7 +1,7 @@
+ /*
+ * Device Tree for the PQ2FADS-ZU board with an MPC8280 chip.
+ *
+- * Copyright 2007 Freescale Semiconductor Inc.
++ * Copyright 2007,2008 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+@@ -9,6 +9,8 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
++
+ / {
+ model = "pq2fads";
+ compatible = "fsl,pq2fads";
+@@ -21,11 +23,11 @@
+
+ cpu at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <d#32>;
+- i-cache-line-size = <d#32>;
+- d-cache-size = <d#16384>;
+- i-cache-size = <d#16384>;
++ reg = <0x0>;
++ d-cache-line-size = <32>;
++ i-cache-line-size = <32>;
++ d-cache-size = <16384>;
++ i-cache-size = <16384>;
+ timebase-frequency = <0>;
+ clock-frequency = <0>;
+ };
+@@ -33,7 +35,7 @@
+
+ memory {
+ device_type = "memory";
+- reg = <0 0>;
++ reg = <0x0 0x0>;
+ };
+
+ localbus at f0010100 {
+@@ -41,67 +43,67 @@
+ "fsl,pq2-localbus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+- reg = <f0010100 60>;
++ reg = <0xf0010100 0x60>;
+
+- ranges = <0 0 fe000000 00800000
+- 1 0 f4500000 00008000
+- 8 0 f8200000 00008000>;
++ ranges = <0x0 0x0 0xfe000000 0x800000
++ 0x1 0x0 0xf4500000 0x8000
++ 0x8 0x0 0xf8200000 0x8000>;
+
+ flash at 0,0 {
+ compatible = "jedec-flash";
+- reg = <0 0 800000>;
++ reg = <0x0 0x0 0x800000>;
+ bank-width = <4>;
+ device-width = <1>;
+ };
+
+ bcsr at 1,0 {
+- reg = <1 0 20>;
++ reg = <0x1 0x0 0x20>;
+ compatible = "fsl,pq2fads-bcsr";
+ };
+
+ PCI_PIC: pic at 8,0 {
+ #interrupt-cells = <1>;
+ interrupt-controller;
+- reg = <8 0 8>;
++ reg = <0x8 0x0 0x8>;
+ compatible = "fsl,pq2ads-pci-pic";
+ interrupt-parent = <&PIC>;
+- interrupts = <18 8>;
++ interrupts = <24 8>;
+ };
+ };
+
+ pci at f0010800 {
+ device_type = "pci";
+- reg = <f0010800 10c f00101ac 8 f00101c4 8>;
++ reg = <0xf0010800 0x10c 0xf00101ac 0x8 0xf00101c4 0x8>;
+ compatible = "fsl,mpc8280-pci", "fsl,pq2-pci";
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- clock-frequency = <d#66000000>;
+- interrupt-map-mask = <f800 0 0 7>;
++ clock-frequency = <66000000>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x16 */
+- b000 0 0 1 &PCI_PIC 0
+- b000 0 0 2 &PCI_PIC 1
+- b000 0 0 3 &PCI_PIC 2
+- b000 0 0 4 &PCI_PIC 3
++ 0xb000 0x0 0x0 0x1 &PCI_PIC 0
++ 0xb000 0x0 0x0 0x2 &PCI_PIC 1
++ 0xb000 0x0 0x0 0x3 &PCI_PIC 2
++ 0xb000 0x0 0x0 0x4 &PCI_PIC 3
+
+ /* IDSEL 0x17 */
+- b800 0 0 1 &PCI_PIC 4
+- b800 0 0 2 &PCI_PIC 5
+- b800 0 0 3 &PCI_PIC 6
+- b800 0 0 4 &PCI_PIC 7
++ 0xb800 0x0 0x0 0x1 &PCI_PIC 4
++ 0xb800 0x0 0x0 0x2 &PCI_PIC 5
++ 0xb800 0x0 0x0 0x3 &PCI_PIC 6
++ 0xb800 0x0 0x0 0x4 &PCI_PIC 7
+
+ /* IDSEL 0x18 */
+- c000 0 0 1 &PCI_PIC 8
+- c000 0 0 2 &PCI_PIC 9
+- c000 0 0 3 &PCI_PIC a
+- c000 0 0 4 &PCI_PIC b>;
++ 0xc000 0x0 0x0 0x1 &PCI_PIC 8
++ 0xc000 0x0 0x0 0x2 &PCI_PIC 9
++ 0xc000 0x0 0x0 0x3 &PCI_PIC 10
++ 0xc000 0x0 0x0 0x4 &PCI_PIC 11>;
+
+ interrupt-parent = <&PIC>;
+- interrupts = <12 8>;
+- ranges = <42000000 0 80000000 80000000 0 20000000
+- 02000000 0 a0000000 a0000000 0 20000000
+- 01000000 0 00000000 f6000000 0 02000000>;
++ interrupts = <18 8>;
++ ranges = <0x42000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xf6000000 0x0 0x2000000>;
+ };
+
+ soc at f0000000 {
+@@ -109,27 +111,27 @@
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "fsl,mpc8280", "fsl,pq2-soc";
+- ranges = <00000000 f0000000 00053000>;
++ ranges = <0x0 0xf0000000 0x53000>;
+
+ // Temporary -- will go away once kernel uses ranges for get_immrbase().
+- reg = <f0000000 00053000>;
++ reg = <0xf0000000 0x53000>;
+
+ cpm at 119c0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #interrupt-cells = <2>;
+ compatible = "fsl,mpc8280-cpm", "fsl,cpm2";
+- reg = <119c0 30>;
++ reg = <0x119c0 0x30>;
+ ranges;
+
+ muram at 0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+- ranges = <0 0 10000>;
++ ranges = <0x0 0x0 0x10000>;
+
+ data at 0 {
+ compatible = "fsl,cpm-muram-data";
+- reg = <0 2000 9800 800>;
++ reg = <0x0 0x2000 0x9800 0x800>;
+ };
+ };
+
+@@ -137,53 +139,53 @@
+ compatible = "fsl,mpc8280-brg",
+ "fsl,cpm2-brg",
+ "fsl,cpm-brg";
+- reg = <119f0 10 115f0 10>;
++ reg = <0x119f0 0x10 0x115f0 0x10>;
+ };
+
+ serial at 11a00 {
+ device_type = "serial";
+ compatible = "fsl,mpc8280-scc-uart",
+ "fsl,cpm2-scc-uart";
+- reg = <11a00 20 8000 100>;
+- interrupts = <28 8>;
++ reg = <0x11a00 0x20 0x8000 0x100>;
++ interrupts = <40 8>;
+ interrupt-parent = <&PIC>;
+ fsl,cpm-brg = <1>;
+- fsl,cpm-command = <00800000>;
++ fsl,cpm-command = <0x800000>;
+ };
+
+ serial at 11a20 {
+ device_type = "serial";
+ compatible = "fsl,mpc8280-scc-uart",
+ "fsl,cpm2-scc-uart";
+- reg = <11a20 20 8100 100>;
+- interrupts = <29 8>;
++ reg = <0x11a20 0x20 0x8100 0x100>;
++ interrupts = <41 8>;
+ interrupt-parent = <&PIC>;
+ fsl,cpm-brg = <2>;
+- fsl,cpm-command = <04a00000>;
++ fsl,cpm-command = <0x4a00000>;
+ };
+
+ ethernet at 11320 {
+ device_type = "network";
+ compatible = "fsl,mpc8280-fcc-enet",
+ "fsl,cpm2-fcc-enet";
+- reg = <11320 20 8500 100 113b0 1>;
+- interrupts = <21 8>;
++ reg = <0x11320 0x20 0x8500 0x100 0x113b0 0x1>;
++ interrupts = <33 8>;
+ interrupt-parent = <&PIC>;
+ phy-handle = <&PHY0>;
+ linux,network-index = <0>;
+- fsl,cpm-command = <16200300>;
++ fsl,cpm-command = <0x16200300>;
+ };
+
+ ethernet at 11340 {
+ device_type = "network";
+ compatible = "fsl,mpc8280-fcc-enet",
+ "fsl,cpm2-fcc-enet";
+- reg = <11340 20 8600 100 113d0 1>;
+- interrupts = <22 8>;
++ reg = <0x11340 0x20 0x8600 0x100 0x113d0 0x1>;
++ interrupts = <34 8>;
+ interrupt-parent = <&PIC>;
+ phy-handle = <&PHY1>;
+ linux,network-index = <1>;
+- fsl,cpm-command = <1a400300>;
++ fsl,cpm-command = <0x1a400300>;
+ local-mac-address = [00 e0 0c 00 79 01];
+ };
+
+@@ -194,21 +196,21 @@
+ "fsl,cpm2-mdio-bitbang";
+ #address-cells = <1>;
+ #size-cells = <0>;
+- reg = <10d40 14>;
++ reg = <0x10d40 0x14>;
+ fsl,mdio-pin = <9>;
+- fsl,mdc-pin = <a>;
++ fsl,mdc-pin = <10>;
+
+ PHY0: ethernet-phy at 0 {
+ interrupt-parent = <&PIC>;
+- interrupts = <19 2>;
+- reg = <0>;
++ interrupts = <25 2>;
++ reg = <0x0>;
+ device_type = "ethernet-phy";
+ };
+
+ PHY1: ethernet-phy at 1 {
+ interrupt-parent = <&PIC>;
+- interrupts = <19 2>;
+- reg = <3>;
++ interrupts = <25 2>;
++ reg = <0x3>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -218,17 +220,17 @@
+ #size-cells = <0>;
+ compatible = "fsl,mpc8280-usb",
+ "fsl,cpm2-usb";
+- reg = <11b60 18 8b00 100>;
++ reg = <0x11b60 0x18 0x8b00 0x100>;
+ interrupt-parent = <&PIC>;
+- interrupts = <b 8>;
+- fsl,cpm-command = <2e600000>;
++ interrupts = <11 8>;
++ fsl,cpm-command = <0x2e600000>;
+ };
+ };
+
+ PIC: interrupt-controller at 10c00 {
+ #interrupt-cells = <2>;
+ interrupt-controller;
+- reg = <10c00 80>;
++ reg = <0x10c00 0x80>;
+ compatible = "fsl,mpc8280-pic", "fsl,cpm2-pic";
+ };
+
+diff --git a/arch/powerpc/boot/dts/prpmc2800.dts b/arch/powerpc/boot/dts/prpmc2800.dts
+index 297dfa5..1ee6ff4 100644
+--- a/arch/powerpc/boot/dts/prpmc2800.dts
++++ b/arch/powerpc/boot/dts/prpmc2800.dts
+@@ -11,6 +11,8 @@
+ * if it can determine the exact PrPMC type.
+ */
+
++/dts-v1/;
++
+ / {
+ #address-cells = <1>;
+ #size-cells = <1>;
+@@ -25,46 +27,46 @@
+ PowerPC,7447 {
+ device_type = "cpu";
+ reg = <0>;
+- clock-frequency = <2bb0b140>; /* Default (733 MHz) */
+- bus-frequency = <7f28155>; /* 133.333333 MHz */
+- timebase-frequency = <1fca055>; /* 33.333333 MHz */
+- i-cache-line-size = <20>;
+- d-cache-line-size = <20>;
+- i-cache-size = <8000>;
+- d-cache-size = <8000>;
++ clock-frequency = <733333333>; /* Default */
++ bus-frequency = <133333333>;
++ timebase-frequency = <33333333>;
++ i-cache-line-size = <32>;
++ d-cache-line-size = <32>;
++ i-cache-size = <32768>;
++ d-cache-size = <32768>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 20000000>; /* Default (512MB) */
++ reg = <0x0 0x20000000>; /* Default (512MB) */
+ };
+
+- mv64x60 at f1000000 { /* Marvell Discovery */
++ system-controller at f1000000 { /* Marvell Discovery mv64360 */
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "mv64360"; /* Default */
+- compatible = "marvell,mv64x60";
+- clock-frequency = <7f28155>; /* 133.333333 MHz */
+- reg = <f1000000 00010000>;
+- virtual-reg = <f1000000>;
+- ranges = <88000000 88000000 01000000 /* PCI 0 I/O Space */
+- 80000000 80000000 08000000 /* PCI 0 MEM Space */
+- a0000000 a0000000 04000000 /* User FLASH */
+- 00000000 f1000000 00010000 /* Bridge's regs */
+- f2000000 f2000000 00040000>; /* Integrated SRAM */
++ compatible = "marvell,mv64360";
++ clock-frequency = <133333333>;
++ reg = <0xf1000000 0x10000>;
++ virtual-reg = <0xf1000000>;
++ ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */
++ 0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */
++ 0xa0000000 0xa0000000 0x4000000 /* User FLASH */
++ 0x00000000 0xf1000000 0x0010000 /* Bridge's regs */
++ 0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */
+
+ flash at a0000000 {
+ device_type = "rom";
+ compatible = "direct-mapped";
+- reg = <a0000000 4000000>; /* Default (64MB) */
++ reg = <0xa0000000 0x4000000>; /* Default (64MB) */
+ probe-type = "CFI";
+ bank-width = <4>;
+- partitions = <00000000 00100000 /* RO */
+- 00100000 00040001 /* RW */
+- 00140000 00400000 /* RO */
+- 00540000 039c0000 /* RO */
+- 03f00000 00100000>; /* RO */
++ partitions = <0x00000000 0x00100000 /* RO */
++ 0x00100000 0x00040001 /* RW */
++ 0x00140000 0x00400000 /* RO */
++ 0x00540000 0x039c0000 /* RO */
++ 0x03f00000 0x00100000>; /* RO */
+ partition-names = "FW Image A", "FW Config Data", "Kernel Image", "Filesystem", "FW Image B";
+ };
+
+@@ -72,171 +74,153 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ device_type = "mdio";
+- compatible = "marvell,mv64x60-mdio";
+- ethernet-phy at 1 {
++ compatible = "marvell,mv64360-mdio";
++ PHY0: ethernet-phy at 1 {
+ device_type = "ethernet-phy";
+ compatible = "broadcom,bcm5421";
+- interrupts = <4c>; /* GPP 12 */
+- interrupt-parent = <&/mv64x60/pic>;
++ interrupts = <76>; /* GPP 12 */
++ interrupt-parent = <&PIC>;
+ reg = <1>;
+ };
+- ethernet-phy at 3 {
++ PHY1: ethernet-phy at 3 {
+ device_type = "ethernet-phy";
+ compatible = "broadcom,bcm5421";
+- interrupts = <4c>; /* GPP 12 */
+- interrupt-parent = <&/mv64x60/pic>;
++ interrupts = <76>; /* GPP 12 */
++ interrupt-parent = <&PIC>;
+ reg = <3>;
+ };
+ };
+
+- ethernet at 2000 {
+- reg = <2000 2000>;
+- eth0 {
++ ethernet-group at 2000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "marvell,mv64360-eth-group";
++ reg = <0x2000 0x2000>;
++ ethernet at 0 {
+ device_type = "network";
+- compatible = "marvell,mv64x60-eth";
+- block-index = <0>;
+- interrupts = <20>;
+- interrupt-parent = <&/mv64x60/pic>;
+- phy = <&/mv64x60/mdio/ethernet-phy at 1>;
++ compatible = "marvell,mv64360-eth";
++ reg = <0>;
++ interrupts = <32>;
++ interrupt-parent = <&PIC>;
++ phy = <&PHY0>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+- eth1 {
++ ethernet at 1 {
+ device_type = "network";
+- compatible = "marvell,mv64x60-eth";
+- block-index = <1>;
+- interrupts = <21>;
+- interrupt-parent = <&/mv64x60/pic>;
+- phy = <&/mv64x60/mdio/ethernet-phy at 3>;
++ compatible = "marvell,mv64360-eth";
++ reg = <1>;
++ interrupts = <33>;
++ interrupt-parent = <&PIC>;
++ phy = <&PHY1>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ };
+
+- sdma at 4000 {
+- device_type = "dma";
+- compatible = "marvell,mv64x60-sdma";
+- reg = <4000 c18>;
+- virtual-reg = <f1004000>;
+- interrupt-base = <0>;
+- interrupts = <24>;
+- interrupt-parent = <&/mv64x60/pic>;
++ SDMA0: sdma at 4000 {
++ compatible = "marvell,mv64360-sdma";
++ reg = <0x4000 0xc18>;
++ virtual-reg = <0xf1004000>;
++ interrupts = <36>;
++ interrupt-parent = <&PIC>;
+ };
+
+- sdma at 6000 {
+- device_type = "dma";
+- compatible = "marvell,mv64x60-sdma";
+- reg = <6000 c18>;
+- virtual-reg = <f1006000>;
+- interrupt-base = <0>;
+- interrupts = <26>;
+- interrupt-parent = <&/mv64x60/pic>;
++ SDMA1: sdma at 6000 {
++ compatible = "marvell,mv64360-sdma";
++ reg = <0x6000 0xc18>;
++ virtual-reg = <0xf1006000>;
++ interrupts = <38>;
++ interrupt-parent = <&PIC>;
+ };
+
+- brg at b200 {
+- compatible = "marvell,mv64x60-brg";
+- reg = <b200 8>;
++ BRG0: brg at b200 {
++ compatible = "marvell,mv64360-brg";
++ reg = <0xb200 0x8>;
+ clock-src = <8>;
+- clock-frequency = <7ed6b40>;
+- current-speed = <2580>;
+- bcr = <0>;
++ clock-frequency = <133333333>;
++ current-speed = <9600>;
+ };
+
+- brg at b208 {
+- compatible = "marvell,mv64x60-brg";
+- reg = <b208 8>;
++ BRG1: brg at b208 {
++ compatible = "marvell,mv64360-brg";
++ reg = <0xb208 0x8>;
+ clock-src = <8>;
+- clock-frequency = <7ed6b40>;
+- current-speed = <2580>;
+- bcr = <0>;
++ clock-frequency = <133333333>;
++ current-speed = <9600>;
+ };
+
+- cunit at f200 {
+- reg = <f200 200>;
++ CUNIT: cunit at f200 {
++ reg = <0xf200 0x200>;
+ };
+
+- mpscrouting at b400 {
+- reg = <b400 c>;
++ MPSCROUTING: mpscrouting at b400 {
++ reg = <0xb400 0xc>;
+ };
+
+- mpscintr at b800 {
+- reg = <b800 100>;
+- virtual-reg = <f100b800>;
++ MPSCINTR: mpscintr at b800 {
++ reg = <0xb800 0x100>;
++ virtual-reg = <0xf100b800>;
+ };
+
+- mpsc at 8000 {
++ MPSC0: mpsc at 8000 {
+ device_type = "serial";
+- compatible = "marvell,mpsc";
+- reg = <8000 38>;
+- virtual-reg = <f1008000>;
+- sdma = <&/mv64x60/sdma at 4000>;
+- brg = <&/mv64x60/brg at b200>;
+- cunit = <&/mv64x60/cunit at f200>;
+- mpscrouting = <&/mv64x60/mpscrouting at b400>;
+- mpscintr = <&/mv64x60/mpscintr at b800>;
+- block-index = <0>;
+- max_idle = <28>;
+- chr_1 = <0>;
+- chr_2 = <0>;
+- chr_10 = <3>;
+- mpcr = <0>;
+- interrupts = <28>;
+- interrupt-parent = <&/mv64x60/pic>;
++ compatible = "marvell,mv64360-mpsc";
++ reg = <0x8000 0x38>;
++ virtual-reg = <0xf1008000>;
++ sdma = <&SDMA0>;
++ brg = <&BRG0>;
++ cunit = <&CUNIT>;
++ mpscrouting = <&MPSCROUTING>;
++ mpscintr = <&MPSCINTR>;
++ cell-index = <0>;
++ interrupts = <40>;
++ interrupt-parent = <&PIC>;
+ };
+
+- mpsc at 9000 {
++ MPSC1: mpsc at 9000 {
+ device_type = "serial";
+- compatible = "marvell,mpsc";
+- reg = <9000 38>;
+- virtual-reg = <f1009000>;
+- sdma = <&/mv64x60/sdma at 6000>;
+- brg = <&/mv64x60/brg at b208>;
+- cunit = <&/mv64x60/cunit at f200>;
+- mpscrouting = <&/mv64x60/mpscrouting at b400>;
+- mpscintr = <&/mv64x60/mpscintr at b800>;
+- block-index = <1>;
+- max_idle = <28>;
+- chr_1 = <0>;
+- chr_2 = <0>;
+- chr_10 = <3>;
+- mpcr = <0>;
+- interrupts = <2a>;
+- interrupt-parent = <&/mv64x60/pic>;
++ compatible = "marvell,mv64360-mpsc";
++ reg = <0x9000 0x38>;
++ virtual-reg = <0xf1009000>;
++ sdma = <&SDMA1>;
++ brg = <&BRG1>;
++ cunit = <&CUNIT>;
++ mpscrouting = <&MPSCROUTING>;
++ mpscintr = <&MPSCINTR>;
++ cell-index = <1>;
++ interrupts = <42>;
++ interrupt-parent = <&PIC>;
+ };
+
+ wdt at b410 { /* watchdog timer */
+- compatible = "marvell,mv64x60-wdt";
+- reg = <b410 8>;
+- timeout = <a>; /* wdt timeout in seconds */
++ compatible = "marvell,mv64360-wdt";
++ reg = <0xb410 0x8>;
+ };
+
+ i2c at c000 {
+ device_type = "i2c";
+- compatible = "marvell,mv64x60-i2c";
+- reg = <c000 20>;
+- virtual-reg = <f100c000>;
+- freq_m = <8>;
+- freq_n = <3>;
+- timeout = <3e8>; /* 1000 = 1 second */
+- retries = <1>;
+- interrupts = <25>;
+- interrupt-parent = <&/mv64x60/pic>;
++ compatible = "marvell,mv64360-i2c";
++ reg = <0xc000 0x20>;
++ virtual-reg = <0xf100c000>;
++ interrupts = <37>;
++ interrupt-parent = <&PIC>;
+ };
+
+- pic {
++ PIC: pic {
+ #interrupt-cells = <1>;
+ #address-cells = <0>;
+- compatible = "marvell,mv64x60-pic";
+- reg = <0000 88>;
++ compatible = "marvell,mv64360-pic";
++ reg = <0x0 0x88>;
+ interrupt-controller;
+ };
+
+ mpp at f000 {
+- compatible = "marvell,mv64x60-mpp";
+- reg = <f000 10>;
++ compatible = "marvell,mv64360-mpp";
++ reg = <0xf000 0x10>;
+ };
+
+ gpp at f100 {
+- compatible = "marvell,mv64x60-gpp";
+- reg = <f100 20>;
++ compatible = "marvell,mv64360-gpp";
++ reg = <0xf100 0x20>;
+ };
+
+ pci at 80000000 {
+@@ -244,73 +228,75 @@
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ device_type = "pci";
+- compatible = "marvell,mv64x60-pci";
+- reg = <0cf8 8>;
+- ranges = <01000000 0 0 88000000 0 01000000
+- 02000000 0 80000000 80000000 0 08000000>;
+- bus-range = <0 ff>;
+- clock-frequency = <3EF1480>;
+- interrupt-pci-iack = <0c34>;
+- interrupt-parent = <&/mv64x60/pic>;
+- interrupt-map-mask = <f800 0 0 7>;
++ compatible = "marvell,mv64360-pci";
++ reg = <0xcf8 0x8>;
++ ranges = <0x01000000 0x0 0x0
++ 0x88000000 0x0 0x01000000
++ 0x02000000 0x0 0x80000000
++ 0x80000000 0x0 0x08000000>;
++ bus-range = <0 255>;
++ clock-frequency = <66000000>;
++ interrupt-pci-iack = <0xc34>;
++ interrupt-parent = <&PIC>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x0a */
+- 5000 0 0 1 &/mv64x60/pic 50
+- 5000 0 0 2 &/mv64x60/pic 51
+- 5000 0 0 3 &/mv64x60/pic 5b
+- 5000 0 0 4 &/mv64x60/pic 5d
++ 0x5000 0 0 1 &PIC 80
++ 0x5000 0 0 2 &PIC 81
++ 0x5000 0 0 3 &PIC 91
++ 0x5000 0 0 4 &PIC 93
+
+ /* IDSEL 0x0b */
+- 5800 0 0 1 &/mv64x60/pic 5b
+- 5800 0 0 2 &/mv64x60/pic 5d
+- 5800 0 0 3 &/mv64x60/pic 50
+- 5800 0 0 4 &/mv64x60/pic 51
++ 0x5800 0 0 1 &PIC 91
++ 0x5800 0 0 2 &PIC 93
++ 0x5800 0 0 3 &PIC 80
++ 0x5800 0 0 4 &PIC 81
+
+ /* IDSEL 0x0c */
+- 6000 0 0 1 &/mv64x60/pic 5b
+- 6000 0 0 2 &/mv64x60/pic 5d
+- 6000 0 0 3 &/mv64x60/pic 50
+- 6000 0 0 4 &/mv64x60/pic 51
++ 0x6000 0 0 1 &PIC 91
++ 0x6000 0 0 2 &PIC 93
++ 0x6000 0 0 3 &PIC 80
++ 0x6000 0 0 4 &PIC 81
+
+ /* IDSEL 0x0d */
+- 6800 0 0 1 &/mv64x60/pic 5d
+- 6800 0 0 2 &/mv64x60/pic 50
+- 6800 0 0 3 &/mv64x60/pic 51
+- 6800 0 0 4 &/mv64x60/pic 5b
++ 0x6800 0 0 1 &PIC 93
++ 0x6800 0 0 2 &PIC 80
++ 0x6800 0 0 3 &PIC 81
++ 0x6800 0 0 4 &PIC 91
+ >;
+ };
+
+ cpu-error at 0070 {
+- compatible = "marvell,mv64x60-cpu-error";
+- reg = <0070 10 0128 28>;
+- interrupts = <03>;
+- interrupt-parent = <&/mv64x60/pic>;
++ compatible = "marvell,mv64360-cpu-error";
++ reg = <0x70 0x10 0x128 0x28>;
++ interrupts = <3>;
++ interrupt-parent = <&PIC>;
+ };
+
+ sram-ctrl at 0380 {
+- compatible = "marvell,mv64x60-sram-ctrl";
+- reg = <0380 80>;
+- interrupts = <0d>;
+- interrupt-parent = <&/mv64x60/pic>;
++ compatible = "marvell,mv64360-sram-ctrl";
++ reg = <0x380 0x80>;
++ interrupts = <13>;
++ interrupt-parent = <&PIC>;
+ };
+
+ pci-error at 1d40 {
+- compatible = "marvell,mv64x60-pci-error";
+- reg = <1d40 40 0c28 4>;
+- interrupts = <0c>;
+- interrupt-parent = <&/mv64x60/pic>;
++ compatible = "marvell,mv64360-pci-error";
++ reg = <0x1d40 0x40 0xc28 0x4>;
++ interrupts = <12>;
++ interrupt-parent = <&PIC>;
+ };
+
+ mem-ctrl at 1400 {
+- compatible = "marvell,mv64x60-mem-ctrl";
+- reg = <1400 60>;
+- interrupts = <11>;
+- interrupt-parent = <&/mv64x60/pic>;
++ compatible = "marvell,mv64360-mem-ctrl";
++ reg = <0x1400 0x60>;
++ interrupts = <17>;
++ interrupt-parent = <&PIC>;
+ };
+ };
+
+ chosen {
+ bootargs = "ip=on";
+- linux,stdout-path = "/mv64x60 at f1000000/mpsc at 8000";
++ linux,stdout-path = &MPSC0;
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/rainier.dts b/arch/powerpc/boot/dts/rainier.dts
+index f947c75..6a8fa70 100644
+--- a/arch/powerpc/boot/dts/rainier.dts
++++ b/arch/powerpc/boot/dts/rainier.dts
+@@ -254,7 +254,6 @@
+ };
+
+ EMAC0: ethernet at ef600e00 {
+- linux,network-index = <0>;
+ device_type = "network";
+ compatible = "ibm,emac-440grx", "ibm,emac-440epx", "ibm,emac4";
+ interrupt-parent = <&EMAC0>;
+@@ -270,7 +269,7 @@
+ mal-tx-channel = <0>;
+ mal-rx-channel = <0>;
+ cell-index = <0>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+@@ -284,7 +283,6 @@
+ };
+
+ EMAC1: ethernet at ef600f00 {
+- linux,network-index = <1>;
+ device_type = "network";
+ compatible = "ibm,emac-440grx", "ibm,emac-440epx", "ibm,emac4";
+ interrupt-parent = <&EMAC1>;
+@@ -300,7 +298,7 @@
+ mal-tx-channel = <1>;
+ mal-rx-channel = <1>;
+ cell-index = <1>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+diff --git a/arch/powerpc/boot/dts/sbc8641d.dts b/arch/powerpc/boot/dts/sbc8641d.dts
+new file mode 100644
+index 0000000..3eebeec
+--- /dev/null
++++ b/arch/powerpc/boot/dts/sbc8641d.dts
+@@ -0,0 +1,352 @@
++/*
++ * SBC8641D Device Tree Source
++ *
++ * Copyright 2008 Wind River Systems Inc.
++ *
++ * Paul Gortmaker (see MAINTAINERS for contact information)
++ *
++ * Based largely on the mpc8641_hpcn.dts by Freescale Semiconductor Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++/dts-v1/;
++
++/ {
++ model = "SBC8641D";
++ compatible = "wind,sbc8641";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ aliases {
++ ethernet0 = &enet0;
++ ethernet1 = &enet1;
++ ethernet2 = &enet2;
++ ethernet3 = &enet3;
++ serial0 = &serial0;
++ serial1 = &serial1;
++ pci0 = &pci0;
++ pci1 = &pci1;
++ };
++
++ cpus {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ PowerPC,8641 at 0 {
++ device_type = "cpu";
++ reg = <0>;
++ d-cache-line-size = <32>;
++ i-cache-line-size = <32>;
++ d-cache-size = <32768>; // L1
++ i-cache-size = <32768>; // L1
++ timebase-frequency = <0>; // From uboot
++ bus-frequency = <0>; // From uboot
++ clock-frequency = <0>; // From uboot
++ };
++ PowerPC,8641 at 1 {
++ device_type = "cpu";
++ reg = <1>;
++ d-cache-line-size = <32>;
++ i-cache-line-size = <32>;
++ d-cache-size = <32768>;
++ i-cache-size = <32768>;
++ timebase-frequency = <0>; // From uboot
++ bus-frequency = <0>; // From uboot
++ clock-frequency = <0>; // From uboot
++ };
++ };
++
++ memory {
++ device_type = "memory";
++ reg = <0x00000000 0x20000000>; // 512M at 0x0
++ };
++
++ localbus at f8005000 {
++ #address-cells = <2>;
++ #size-cells = <1>;
++ compatible = "fsl,mpc8641-localbus", "simple-bus";
++ reg = <0xf8005000 0x1000>;
++ interrupts = <19 2>;
++ interrupt-parent = <&mpic>;
++
++ ranges = <0 0 0xff000000 0x01000000 // 16MB Boot flash
++ 1 0 0xf0000000 0x00010000 // 64KB EEPROM
++ 2 0 0xf1000000 0x00100000 // EPLD (1MB)
++ 3 0 0xe0000000 0x04000000 // 64MB LB SDRAM (CS3)
++ 4 0 0xe4000000 0x04000000 // 64MB LB SDRAM (CS4)
++ 6 0 0xf4000000 0x00100000 // LCD display (1MB)
++ 7 0 0xe8000000 0x04000000>; // 64MB OneNAND
++
++ flash at 0,0 {
++ compatible = "cfi-flash";
++ reg = <0 0 0x01000000>;
++ bank-width = <2>;
++ device-width = <2>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++ partition at 0 {
++ label = "dtb";
++ reg = <0x00000000 0x00100000>;
++ read-only;
++ };
++ partition at 300000 {
++ label = "kernel";
++ reg = <0x00100000 0x00400000>;
++ read-only;
++ };
++ partition at 400000 {
++ label = "fs";
++ reg = <0x00500000 0x00a00000>;
++ };
++ partition at 700000 {
++ label = "firmware";
++ reg = <0x00f00000 0x00100000>;
++ read-only;
++ };
++ };
++
++ epld at 2,0 {
++ compatible = "wrs,epld-localbus";
++ #address-cells = <2>;
++ #size-cells = <1>;
++ reg = <2 0 0x100000>;
++ ranges = <0 0 5 0 1 // User switches
++ 1 0 5 1 1 // Board ID/Rev
++ 3 0 5 3 1>; // LEDs
++ };
++ };
++
++ soc at f8000000 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ device_type = "soc";
++ compatible = "simple-bus";
++ ranges = <0x00000000 0xf8000000 0x00100000>;
++ reg = <0xf8000000 0x00001000>; // CCSRBAR
++ bus-frequency = <0>;
++
++ i2c at 3000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ cell-index = <0>;
++ compatible = "fsl-i2c";
++ reg = <0x3000 0x100>;
++ interrupts = <43 2>;
++ interrupt-parent = <&mpic>;
++ dfsrr;
++ };
++
++ i2c at 3100 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ cell-index = <1>;
++ compatible = "fsl-i2c";
++ reg = <0x3100 0x100>;
++ interrupts = <43 2>;
++ interrupt-parent = <&mpic>;
++ dfsrr;
++ };
++
++ mdio at 24520 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "fsl,gianfar-mdio";
++ reg = <0x24520 0x20>;
++
++ phy0: ethernet-phy at 1f {
++ interrupt-parent = <&mpic>;
++ interrupts = <10 1>;
++ reg = <0x1f>;
++ device_type = "ethernet-phy";
++ };
++ phy1: ethernet-phy at 0 {
++ interrupt-parent = <&mpic>;
++ interrupts = <10 1>;
++ reg = <0>;
++ device_type = "ethernet-phy";
++ };
++ phy2: ethernet-phy at 1 {
++ interrupt-parent = <&mpic>;
++ interrupts = <10 1>;
++ reg = <1>;
++ device_type = "ethernet-phy";
++ };
++ phy3: ethernet-phy at 2 {
++ interrupt-parent = <&mpic>;
++ interrupts = <10 1>;
++ reg = <2>;
++ device_type = "ethernet-phy";
++ };
++ };
++
++ enet0: ethernet at 24000 {
++ cell-index = <0>;
++ device_type = "network";
++ model = "TSEC";
++ compatible = "gianfar";
++ reg = <0x24000 0x1000>;
++ local-mac-address = [ 00 00 00 00 00 00 ];
++ interrupts = <29 2 30 2 34 2>;
++ interrupt-parent = <&mpic>;
++ phy-handle = <&phy0>;
++ phy-connection-type = "rgmii-id";
++ };
++
++ enet1: ethernet at 25000 {
++ cell-index = <1>;
++ device_type = "network";
++ model = "TSEC";
++ compatible = "gianfar";
++ reg = <0x25000 0x1000>;
++ local-mac-address = [ 00 00 00 00 00 00 ];
++ interrupts = <35 2 36 2 40 2>;
++ interrupt-parent = <&mpic>;
++ phy-handle = <&phy1>;
++ phy-connection-type = "rgmii-id";
++ };
++
++ enet2: ethernet at 26000 {
++ cell-index = <2>;
++ device_type = "network";
++ model = "TSEC";
++ compatible = "gianfar";
++ reg = <0x26000 0x1000>;
++ local-mac-address = [ 00 00 00 00 00 00 ];
++ interrupts = <31 2 32 2 33 2>;
++ interrupt-parent = <&mpic>;
++ phy-handle = <&phy2>;
++ phy-connection-type = "rgmii-id";
++ };
++
++ enet3: ethernet at 27000 {
++ cell-index = <3>;
++ device_type = "network";
++ model = "TSEC";
++ compatible = "gianfar";
++ reg = <0x27000 0x1000>;
++ local-mac-address = [ 00 00 00 00 00 00 ];
++ interrupts = <37 2 38 2 39 2>;
++ interrupt-parent = <&mpic>;
++ phy-handle = <&phy3>;
++ phy-connection-type = "rgmii-id";
++ };
++
++ serial0: serial at 4500 {
++ cell-index = <0>;
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <0x4500 0x100>;
++ clock-frequency = <0>;
++ interrupts = <42 2>;
++ interrupt-parent = <&mpic>;
++ };
++
++ serial1: serial at 4600 {
++ cell-index = <1>;
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <0x4600 0x100>;
++ clock-frequency = <0>;
++ interrupts = <28 2>;
++ interrupt-parent = <&mpic>;
++ };
++
++ mpic: pic at 40000 {
++ clock-frequency = <0>;
++ interrupt-controller;
++ #address-cells = <0>;
++ #interrupt-cells = <2>;
++ reg = <0x40000 0x40000>;
++ compatible = "chrp,open-pic";
++ device_type = "open-pic";
++ big-endian;
++ };
++
++ global-utilities at e0000 {
++ compatible = "fsl,mpc8641-guts";
++ reg = <0xe0000 0x1000>;
++ fsl,has-rstcr;
++ };
++ };
++
++ pci0: pcie at f8008000 {
++ cell-index = <0>;
++ compatible = "fsl,mpc8641-pcie";
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ reg = <0xf8008000 0x1000>;
++ bus-range = <0x0 0xff>;
++ ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
++ clock-frequency = <33333333>;
++ interrupt-parent = <&mpic>;
++ interrupts = <24 2>;
++ interrupt-map-mask = <0xff00 0 0 7>;
++ interrupt-map = <
++ /* IDSEL 0x0 */
++ 0x0000 0 0 1 &mpic 0 1
++ 0x0000 0 0 2 &mpic 1 1
++ 0x0000 0 0 3 &mpic 2 1
++ 0x0000 0 0 4 &mpic 3 1
++ >;
++
++ pcie at 0 {
++ reg = <0 0 0 0 0>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ device_type = "pci";
++ ranges = <0x02000000 0x0 0x80000000
++ 0x02000000 0x0 0x80000000
++ 0x0 0x20000000
++
++ 0x01000000 0x0 0x00000000
++ 0x01000000 0x0 0x00000000
++ 0x0 0x00100000>;
++ };
++
++ };
++
++ pci1: pcie at f8009000 {
++ cell-index = <1>;
++ compatible = "fsl,mpc8641-pcie";
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ reg = <0xf8009000 0x1000>;
++ bus-range = <0 0xff>;
++ ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++ 0x01000000 0x0 0x00000000 0xe3000000 0x0 0x00100000>;
++ clock-frequency = <33333333>;
++ interrupt-parent = <&mpic>;
+ interrupts = <25 2>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
@@ -106263,6 +138825,237 @@
};
+diff --git a/arch/powerpc/boot/dts/tqm5200.dts b/arch/powerpc/boot/dts/tqm5200.dts
+index 65bcea6..773a68e 100644
+--- a/arch/powerpc/boot/dts/tqm5200.dts
++++ b/arch/powerpc/boot/dts/tqm5200.dts
+@@ -10,6 +10,8 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
++
+ / {
+ model = "tqc,tqm5200";
+ compatible = "tqc,tqm5200";
+@@ -23,10 +25,10 @@
+ PowerPC,5200 at 0 {
+ device_type = "cpu";
+ reg = <0>;
+- d-cache-line-size = <20>;
+- i-cache-line-size = <20>;
+- d-cache-size = <4000>; // L1, 16K
+- i-cache-size = <4000>; // L1, 16K
++ d-cache-line-size = <32>;
++ i-cache-line-size = <32>;
++ d-cache-size = <0x4000>; // L1, 16K
++ i-cache-size = <0x4000>; // L1, 16K
+ timebase-frequency = <0>; // from bootloader
+ bus-frequency = <0>; // from bootloader
+ clock-frequency = <0>; // from bootloader
+@@ -35,21 +37,21 @@
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 04000000>; // 64MB
++ reg = <0x00000000 0x04000000>; // 64MB
+ };
+
+ soc5200 at f0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc5200-immr";
+- ranges = <0 f0000000 0000c000>;
+- reg = <f0000000 00000100>;
++ ranges = <0 0xf0000000 0x0000c000>;
++ reg = <0xf0000000 0x00000100>;
+ bus-frequency = <0>; // from bootloader
+ system-frequency = <0>; // from bootloader
+
+ cdm at 200 {
+ compatible = "fsl,mpc5200-cdm";
+- reg = <200 38>;
++ reg = <0x200 0x38>;
+ };
+
+ mpc5200_pic: interrupt-controller at 500 {
+@@ -57,12 +59,12 @@
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ compatible = "fsl,mpc5200-pic";
+- reg = <500 80>;
++ reg = <0x500 0x80>;
+ };
+
+ timer at 600 { // General Purpose Timer
+ compatible = "fsl,mpc5200-gpt";
+- reg = <600 10>;
++ reg = <0x600 0x10>;
+ interrupts = <1 9 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ fsl,has-wdt;
+@@ -70,38 +72,38 @@
+
+ gpio at b00 {
+ compatible = "fsl,mpc5200-gpio";
+- reg = <b00 40>;
++ reg = <0xb00 0x40>;
+ interrupts = <1 7 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ usb at 1000 {
+ compatible = "fsl,mpc5200-ohci","ohci-be";
+- reg = <1000 ff>;
++ reg = <0x1000 0xff>;
+ interrupts = <2 6 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ dma-controller at 1200 {
+ compatible = "fsl,mpc5200-bestcomm";
+- reg = <1200 80>;
++ reg = <0x1200 0x80>;
+ interrupts = <3 0 0 3 1 0 3 2 0 3 3 0
+ 3 4 0 3 5 0 3 6 0 3 7 0
+- 3 8 0 3 9 0 3 a 0 3 b 0
+- 3 c 0 3 d 0 3 e 0 3 f 0>;
++ 3 8 0 3 9 0 3 10 0 3 11 0
++ 3 12 0 3 13 0 3 14 0 3 15 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+
+ xlb at 1f00 {
+ compatible = "fsl,mpc5200-xlb";
+- reg = <1f00 100>;
++ reg = <0x1f00 0x100>;
+ };
+
+ serial at 2000 { // PSC1
+ device_type = "serial";
+ compatible = "fsl,mpc5200-psc-uart";
+ port-number = <0>; // Logical port assignment
+- reg = <2000 100>;
++ reg = <0x2000 0x100>;
+ interrupts = <2 1 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -110,7 +112,7 @@
+ device_type = "serial";
+ compatible = "fsl,mpc5200-psc-uart";
+ port-number = <1>; // Logical port assignment
+- reg = <2200 100>;
++ reg = <0x2200 0x100>;
+ interrupts = <2 2 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -119,7 +121,7 @@
+ device_type = "serial";
+ compatible = "fsl,mpc5200-psc-uart";
+ port-number = <2>; // Logical port assignment
+- reg = <2400 100>;
++ reg = <0x2400 0x100>;
+ interrupts = <2 3 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -127,7 +129,7 @@
+ ethernet at 3000 {
+ device_type = "network";
+ compatible = "fsl,mpc5200-fec";
+- reg = <3000 400>;
++ reg = <0x3000 0x400>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <2 5 0>;
+ interrupt-parent = <&mpc5200_pic>;
+@@ -137,8 +139,8 @@
+ mdio at 3000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+- compatible = "fsl,mpc5200b-mdio","fsl,mpc5200-mdio";
+- reg = <3000 400>; // fec range, since we need to setup fec interrupts
++ compatible = "fsl,mpc5200-mdio";
++ reg = <0x3000 0x400>; // fec range, since we need to setup fec interrupts
+ interrupts = <2 5 0>; // these are for "mii command finished", not link changes & co.
+ interrupt-parent = <&mpc5200_pic>;
+
+@@ -150,7 +152,7 @@
+
+ ata at 3a00 {
+ compatible = "fsl,mpc5200-ata";
+- reg = <3a00 100>;
++ reg = <0x3a00 0x100>;
+ interrupts = <2 7 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ };
+@@ -159,21 +161,21 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200-i2c","fsl-i2c";
+- reg = <3d40 40>;
+- interrupts = <2 10 0>;
++ reg = <0x3d40 0x40>;
++ interrupts = <2 16 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ fsl5200-clocking;
+
+ rtc at 68 {
+ device_type = "rtc";
+ compatible = "dallas,ds1307";
+- reg = <68>;
++ reg = <0x68>;
+ };
+ };
+
+ sram at 8000 {
+ compatible = "fsl,mpc5200-sram";
+- reg = <8000 4000>;
++ reg = <0x8000 0x4000>;
+ };
+ };
+
+@@ -182,11 +184,11 @@
+ compatible = "fsl,lpb";
+ #address-cells = <2>;
+ #size-cells = <1>;
+- ranges = <0 0 fc000000 02000000>;
++ ranges = <0 0 0xfc000000 0x02000000>;
+
+ flash at 0,0 {
+ compatible = "cfi-flash";
+- reg = <0 0 02000000>;
++ reg = <0 0 0x02000000>;
+ bank-width = <4>;
+ device-width = <2>;
+ #size-cells = <1>;
+@@ -200,18 +202,18 @@
+ #address-cells = <3>;
+ device_type = "pci";
+ compatible = "fsl,mpc5200-pci";
+- reg = <f0000d00 100>;
+- interrupt-map-mask = <f800 0 0 7>;
+- interrupt-map = <c000 0 0 1 &mpc5200_pic 0 0 3
+- c000 0 0 2 &mpc5200_pic 0 0 3
+- c000 0 0 3 &mpc5200_pic 0 0 3
+- c000 0 0 4 &mpc5200_pic 0 0 3>;
++ reg = <0xf0000d00 0x100>;
++ interrupt-map-mask = <0xf800 0 0 7>;
++ interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3
++ 0xc000 0 0 2 &mpc5200_pic 0 0 3
++ 0xc000 0 0 3 &mpc5200_pic 0 0 3
++ 0xc000 0 0 4 &mpc5200_pic 0 0 3>;
+ clock-frequency = <0>; // From boot loader
+- interrupts = <2 8 0 2 9 0 2 a 0>;
++ interrupts = <2 8 0 2 9 0 2 10 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ bus-range = <0 0>;
+- ranges = <42000000 0 80000000 80000000 0 10000000
+- 02000000 0 90000000 90000000 0 10000000
+- 01000000 0 00000000 a0000000 0 01000000>;
++ ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000
++ 0x02000000 0 0x90000000 0x90000000 0 0x10000000
++ 0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
+ };
+ };
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
@@ -117723,16 +150516,16 @@
+# 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
+diff --git a/arch/powerpc/configs/52xx/cm5200_defconfig b/arch/powerpc/configs/52xx/cm5200_defconfig
new file mode 100644
-index 0000000..7d18440
+index 0000000..c10f739
--- /dev/null
-+++ b/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
-@@ -0,0 +1,1395 @@
++++ b/arch/powerpc/configs/52xx/cm5200_defconfig
+@@ -0,0 +1,1099 @@
+#
+# Automatically generated make config: don't edit
-+# Linux kernel version: 2.6.25-rc6
-+# Fri Apr 11 11:10:09 2008
++# Linux kernel version: 2.6.25
++# Tue Apr 29 07:11:37 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -117746,7 +150539,7 @@
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
-+# CONFIG_FSL_EMB_PERFMON is not set
++# CONFIG_ALTIVEC is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
@@ -117762,6 +150555,8 @@
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
@@ -117775,7 +150570,7 @@
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
-+CONFIG_PPC_UDBG_16550=y
++# CONFIG_PPC_UDBG_16550 is not set
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
@@ -117803,7 +150598,7 @@
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
-+# CONFIG_FAIR_GROUP_SCHED is not set
++CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
@@ -117816,7 +150611,7 @@
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
-+CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
@@ -117846,12 +150641,7 @@
+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_MODULES is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
@@ -117875,27 +150665,27 @@
+#
+# Platform support
+#
-+# CONFIG_PPC_MULTIPLATFORM is not set
++CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_PPC_82xx is not set
-+CONFIG_PPC_83xx=y
++# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
++CONFIG_CLASSIC32=y
++# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_MPC512x is not set
+# CONFIG_PPC_MPC5121 is not set
++# CONFIG_MPC5121_ADS is not set
++CONFIG_PPC_MPC52xx=y
++CONFIG_PPC_MPC5200_SIMPLE=y
++# CONFIG_PPC_EFIKA is not set
++# CONFIG_PPC_LITE5200 is not set
++# CONFIG_PPC_MPC5200_BUGFIX is not set
++# CONFIG_PPC_MPC5200_GPIO is not set
++# CONFIG_PPC_PMAC 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_EMBEDDED6xx is not set
++# CONFIG_IPIC is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
@@ -117906,15 +150696,20 @@
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
++# CONFIG_TAU is not set
+# CONFIG_FSL_ULI1575 is not set
++CONFIG_PPC_BESTCOMM=y
++# CONFIG_PPC_BESTCOMM_ATA is not set
++CONFIG_PPC_BESTCOMM_FEC=y
++# CONFIG_PPC_BESTCOMM_GEN_BD is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
-+CONFIG_TICK_ONESHOT=y
-+CONFIG_NO_HZ=y
-+CONFIG_HIGH_RES_TIMERS=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
@@ -117927,11 +150722,11 @@
+# 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_KEXEC is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
@@ -117942,14 +150737,18 @@
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_PAGEFLAGS_EXTENDED=y
+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_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
-+# CONFIG_PM is not set
++CONFIG_PM=y
++# CONFIG_PM_LEGACY is not set
++# CONFIG_PM_DEBUG is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
@@ -117958,18 +150757,13 @@
+#
+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_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
-+# CONFIG_HOTPLUG_PCI is not set
++# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
@@ -117979,11 +150773,11 @@
+#
+# Default settings for advanced configuration options are used
+#
-+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
++CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
-+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
@@ -117997,7 +150791,7 @@
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+# CONFIG_XFRM_USER is not set
++CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
@@ -118031,8 +150825,6 @@
+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
@@ -118091,8 +150883,9 @@
+# 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
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_OF_PARTS is not set
++# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
@@ -118138,15 +150931,11 @@
+# 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
@@ -118158,17 +150947,7 @@
+# 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_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
@@ -118176,18 +150955,14 @@
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_OF_DEVICE=y
++CONFIG_OF_I2C=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
@@ -118195,12 +150970,7 @@
+# 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_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
@@ -118217,7 +150987,7 @@
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
-+# CONFIG_BLK_DEV_SD is not set
++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
@@ -118231,72 +151001,18 @@
+# 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_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_SCSI_LOWLEVEL 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_MD is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
@@ -118306,7 +151022,6 @@
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
-+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
@@ -118315,8 +151030,8 @@
+# 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_LXT_PHY=y
++# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
@@ -118325,80 +151040,24 @@
+# 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_MII 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
++CONFIG_FEC_MPC52xx=y
++CONFIG_FEC_MPC52xx_MDIO=y
++# 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_IWLWIFI is not set
++# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# USB Network Adapters
@@ -118409,11 +151068,8 @@
+# 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
@@ -118423,27 +151079,7 @@
+#
+# 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
++# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
@@ -118456,17 +151092,11 @@
+#
+# 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 is not set
+
+#
+# Non-8250 serial port support
@@ -118474,58 +151104,33 @@
+# 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_MPC52xx=y
++CONFIG_SERIAL_MPC52xx_CONSOLE=y
++CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=57600
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
-+CONFIG_HW_RANDOM=y
++# 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_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_PCA_PLATFORM is not set
+
+#
+# Miscellaneous I2C Chip support
@@ -118535,90 +151140,16 @@
+# 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_SPI 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_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -118627,13 +151158,7 @@
+# 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
++# CONFIG_MPC5200_WDT is not set
+
+#
+# USB-based Watchdog Cards
@@ -118650,22 +151175,20 @@
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
++# CONFIG_HTC_PASIC3 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
++# 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_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
@@ -118678,25 +151201,10 @@
+# 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_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
@@ -118705,28 +151213,25 @@
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
-+CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
++# CONFIG_USB_OTG_WHITELIST is not set
++# CONFIG_USB_OTG_BLACKLIST_HUB 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_SOC=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_OHCI_LITTLE_ENDIAN is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
@@ -118755,6 +151260,7 @@
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
@@ -118762,7 +151268,7 @@
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
-+CONFIG_USB_MON=y
++# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
@@ -118787,99 +151293,17 @@
+# 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_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_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
-+
-+#
-+# Userspace I/O
-+#
+# CONFIG_UIO is not set
+
+#
@@ -118899,7 +151323,6 @@
+# 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
@@ -118918,8 +151341,11 @@
+#
+# DOS/FAT/NT Filesystems
+#
-+# CONFIG_MSDOS_FS is not set
-+# CONFIG_VFAT_FS is not set
++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
+
+#
@@ -118955,7 +151381,7 @@
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
-+# CONFIG_CRAMFS is not set
++CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
@@ -118968,7 +151394,6 @@
+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
@@ -119006,13 +151431,53 @@
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
-+# CONFIG_NLS 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
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
++# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
@@ -119030,9 +151495,10 @@
+#
+# Kernel hacking
+#
-+# CONFIG_PRINTK_TIME is not set
++CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
@@ -119055,10 +151521,10 @@
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# 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
-+# 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
@@ -119066,7 +151532,9 @@
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUGGER is not set
++# CONFIG_IRQSTACKS is not set
+# CONFIG_BDI_SWITCH is not set
++# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
@@ -119076,64 +151544,93 @@
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
-+# CONFIG_CRYPTO_SEQIV is not set
+CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++
++#
++# 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=y
++# CONFIG_CRYPTO_LRW is not set
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
-+# CONFIG_CRYPTO_NULL is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_MICHAEL_MIC 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=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_WP512 is not set
++
++#
++# Ciphers
++#
+# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA 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_DES=y
++# CONFIG_CRYPTO_FCRYPT 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_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
+# 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
++CONFIG_PPC_CLOCK=y
++CONFIG_PPC_LIB_RHEAP=y
++# CONFIG_VIRTUALIZATION is not set
+diff --git a/arch/powerpc/configs/52xx/lite5200b_defconfig b/arch/powerpc/configs/52xx/lite5200b_defconfig
new file mode 100644
-index 0000000..1f57456
+index 0000000..1a8a250
--- /dev/null
-+++ b/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
-@@ -0,0 +1,1451 @@
++++ b/arch/powerpc/configs/52xx/lite5200b_defconfig
+@@ -0,0 +1,1049 @@
+#
+# Automatically generated make config: don't edit
-+# Linux kernel version: 2.6.25-rc6
-+# Mon Mar 24 08:48:15 2008
++# Linux kernel version: 2.6.25
++# Tue Apr 29 07:12:56 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -119147,7 +151644,7 @@
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
-+# CONFIG_FSL_EMB_PERFMON is not set
++# CONFIG_ALTIVEC is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
@@ -119163,6 +151660,8 @@
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
@@ -119176,11 +151675,12 @@
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
-+CONFIG_PPC_UDBG_16550=y
++# CONFIG_PPC_UDBG_16550 is not set
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -119217,7 +151717,7 @@
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
-+CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
@@ -119276,27 +151776,27 @@
+#
+# Platform support
+#
-+# CONFIG_PPC_MULTIPLATFORM is not set
++CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_PPC_82xx is not set
-+CONFIG_PPC_83xx=y
++# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
++CONFIG_CLASSIC32=y
++# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_MPC512x is not set
+# CONFIG_PPC_MPC5121 is not set
++# CONFIG_MPC5121_ADS is not set
++CONFIG_PPC_MPC52xx=y
++CONFIG_PPC_MPC5200_SIMPLE=y
++# CONFIG_PPC_EFIKA is not set
++CONFIG_PPC_LITE5200=y
++# CONFIG_PPC_MPC5200_BUGFIX is not set
++# CONFIG_PPC_MPC5200_GPIO is not set
++# CONFIG_PPC_PMAC 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_EMBEDDED6xx is not set
++# CONFIG_IPIC is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
@@ -119307,7 +151807,12 @@
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
++# CONFIG_TAU is not set
+# CONFIG_FSL_ULI1575 is not set
++CONFIG_PPC_BESTCOMM=y
++CONFIG_PPC_BESTCOMM_ATA=y
++CONFIG_PPC_BESTCOMM_FEC=y
++CONFIG_PPC_BESTCOMM_GEN_BD=y
+
+#
+# Kernel options
@@ -119332,6 +151837,7 @@
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++# CONFIG_KEXEC is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
@@ -119342,14 +151848,21 @@
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_PAGEFLAGS_EXTENDED=y
+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_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
-+# CONFIG_PM is not set
++CONFIG_PM=y
++# CONFIG_PM_LEGACY is not set
++# CONFIG_PM_DEBUG is not set
++CONFIG_PM_SLEEP=y
++CONFIG_SUSPEND=y
++CONFIG_SUSPEND_FREEZER=y
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
@@ -119358,7 +151871,7 @@
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
-+CONFIG_PPC_INDIRECT_PCI=y
++# CONFIG_PPC_INDIRECT_PCI is not set
+CONFIG_FSL_SOC=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
@@ -119370,6 +151883,7 @@
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
++# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
@@ -119379,11 +151893,11 @@
+#
+# Default settings for advanced configuration options are used
+#
-+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
++CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
-+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
@@ -119397,7 +151911,7 @@
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+# CONFIG_XFRM_USER is not set
++CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
@@ -119431,8 +151945,6 @@
+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
@@ -119486,96 +151998,9 @@
+# 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_MTD is not set
+CONFIG_OF_DEVICE=y
++CONFIG_OF_I2C=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
@@ -119588,7 +152013,6 @@
+# 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
@@ -119612,7 +152036,7 @@
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
-+CONFIG_SCSI_PROC_FS=y
++# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
@@ -119621,7 +152045,7 @@
+# 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_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
@@ -119636,7 +152060,7 @@
+#
+# SCSI Transports
+#
-+CONFIG_SCSI_SPI_ATTRS=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_LIBSAS is not set
@@ -119681,7 +152105,11 @@
+# CONFIG_SCSI_SRP is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
++CONFIG_SATA_PMP=y
+# CONFIG_SATA_AHCI is not set
++# CONFIG_SATA_SIL24 is not set
++# CONFIG_SATA_FSL is not set
++CONFIG_ATA_SFF=y
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
@@ -119691,13 +152119,11 @@
+# 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
@@ -119718,6 +152144,7 @@
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
++CONFIG_PATA_MPC52xx=y
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
@@ -119737,16 +152164,7 @@
+# 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_MD is not set
+# CONFIG_FUSION is not set
+
+#
@@ -119773,7 +152191,7 @@
+# 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_LXT_PHY=y
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
@@ -119783,38 +152201,21 @@
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
-+CONFIG_MII=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_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_NET_PCI 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_FEC_MPC52xx=y
++CONFIG_FEC_MPC52xx_MDIO=y
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
@@ -119830,12 +152231,11 @@
+# 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_GIANFAR is not set
++# CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
@@ -119857,15 +152257,8 @@
+#
+# 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_IWLWIFI is not set
++# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
@@ -119881,27 +152274,7 @@
+#
+# 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
++# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
@@ -119919,12 +152292,7 @@
+#
+# 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 is not set
+
+#
+# Non-8250 serial port support
@@ -119932,15 +152300,18 @@
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_SERIAL_MPC52xx=y
++CONFIG_SERIAL_MPC52xx_CONSOLE=y
++CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
+# 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_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
-+# CONFIG_GEN_RTC 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
@@ -119951,13 +152322,6 @@
+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
@@ -119980,10 +152344,10 @@
+# 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_PCA_PLATFORM is not set
+
+#
+# Miscellaneous I2C Chip support
@@ -119993,110 +152357,18 @@
+# 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_SPI 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_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
++# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
@@ -120108,14 +152380,14 @@
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
++# CONFIG_HTC_PASIC3 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
++# CONFIG_DAB is not set
+
+#
+# Graphics support
@@ -120136,208 +152408,25 @@
+# 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
++# CONFIG_USB is not set
++# CONFIG_USB_OTG_WHITELIST is not set
++# CONFIG_USB_OTG_BLACKLIST_HUB 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_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_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
-+
-+#
-+# Userspace I/O
-+#
+# CONFIG_UIO is not set
+
+#
@@ -120357,7 +152446,6 @@
+# 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
@@ -120402,17 +152490,6 @@
+# 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
@@ -120426,7 +152503,6 @@
+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
@@ -120446,24 +152522,8 @@
+#
+# 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_PARTITION_ADVANCED 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
+
@@ -120471,25 +152531,26 @@
+# Library routines
+#
+CONFIG_BITREVERSE=y
++# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# 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_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
@@ -120510,8 +152571,9 @@
+# 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_INFO=y
+# 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
@@ -120523,7 +152585,9 @@
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUGGER is not set
++# CONFIG_IRQSTACKS is not set
+# CONFIG_BDI_SWITCH is not set
++# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
@@ -120533,64 +152597,95 @@
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
-+# CONFIG_CRYPTO_SEQIV is not set
+CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# 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 is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
-+# CONFIG_CRYPTO_NULL is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_MICHAEL_MIC 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=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_WP512 is not set
++
++#
++# Ciphers
++#
+# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA 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_DES=y
++# CONFIG_CRYPTO_FCRYPT 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_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
+# 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
++CONFIG_PPC_CLOCK=y
++CONFIG_PPC_LIB_RHEAP=y
++# CONFIG_VIRTUALIZATION is not set
+diff --git a/arch/powerpc/configs/52xx/motionpro_defconfig b/arch/powerpc/configs/52xx/motionpro_defconfig
new file mode 100644
-index 0000000..50cceda
+index 0000000..8c7ba7c
--- /dev/null
-+++ b/arch/powerpc/configs/83xx/mpc832x_mds_defconfig
-@@ -0,0 +1,1081 @@
++++ b/arch/powerpc/configs/52xx/motionpro_defconfig
+@@ -0,0 +1,1107 @@
+#
+# Automatically generated make config: don't edit
-+# Linux kernel version: 2.6.25-rc7
-+# Mon Mar 31 11:36:51 2008
++# Linux kernel version: 2.6.25
++# Tue Apr 29 07:12:22 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -120604,7 +152699,7 @@
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
-+# CONFIG_FSL_EMB_PERFMON is not set
++# CONFIG_ALTIVEC is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
@@ -120620,6 +152715,8 @@
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
@@ -120633,7 +152730,7 @@
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
-+CONFIG_PPC_UDBG_16550=y
++# CONFIG_PPC_UDBG_16550 is not set
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
@@ -120661,7 +152758,7 @@
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
-+# CONFIG_FAIR_GROUP_SCHED is not set
++CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
@@ -120674,7 +152771,7 @@
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
-+CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
@@ -120704,12 +152801,7 @@
+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_MODULES is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
@@ -120733,27 +152825,27 @@
+#
+# Platform support
+#
-+# CONFIG_PPC_MULTIPLATFORM is not set
++CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_PPC_82xx is not set
-+CONFIG_PPC_83xx=y
++# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
++CONFIG_CLASSIC32=y
++# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_MPC512x is not set
+# CONFIG_PPC_MPC5121 is not set
++# CONFIG_MPC5121_ADS is not set
++CONFIG_PPC_MPC52xx=y
++CONFIG_PPC_MPC5200_SIMPLE=y
++# CONFIG_PPC_EFIKA is not set
++# CONFIG_PPC_LITE5200 is not set
++# CONFIG_PPC_MPC5200_BUGFIX is not set
++# CONFIG_PPC_MPC5200_GPIO is not set
++# CONFIG_PPC_PMAC 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_EMBEDDED6xx is not set
++# CONFIG_IPIC is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
@@ -120764,16 +152856,20 @@
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
-+CONFIG_QUICC_ENGINE=y
++# CONFIG_TAU is not set
+# CONFIG_FSL_ULI1575 is not set
++CONFIG_PPC_BESTCOMM=y
++# CONFIG_PPC_BESTCOMM_ATA is not set
++CONFIG_PPC_BESTCOMM_FEC=y
++# CONFIG_PPC_BESTCOMM_GEN_BD is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
-+CONFIG_TICK_ONESHOT=y
-+CONFIG_NO_HZ=y
-+CONFIG_HIGH_RES_TIMERS=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
@@ -120786,11 +152882,11 @@
+# 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_KEXEC is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
@@ -120801,14 +152897,18 @@
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_PAGEFLAGS_EXTENDED=y
+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_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
-+# CONFIG_PM is not set
++CONFIG_PM=y
++# CONFIG_PM_LEGACY is not set
++# CONFIG_PM_DEBUG is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
@@ -120817,17 +152917,13 @@
+#
+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 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
-+# CONFIG_HOTPLUG_PCI is not set
++# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
@@ -120837,11 +152933,11 @@
+#
+# Default settings for advanced configuration options are used
+#
-+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
++CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
-+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
@@ -120855,7 +152951,7 @@
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+# CONFIG_XFRM_USER is not set
++CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
@@ -120889,8 +152985,6 @@
+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
@@ -120940,22 +153034,95 @@
+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_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
++# CONFIG_MTD_AR7_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=y
++# 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_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_OF_I2C=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
@@ -120963,10 +153130,7 @@
+# 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
@@ -120977,18 +153141,18 @@
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
-+# CONFIG_SCSI_TGT is not set
++CONFIG_SCSI_TGT=y
+# 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_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_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
@@ -120998,7 +153162,6 @@
+# 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
@@ -121010,51 +153173,16 @@
+# 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_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++CONFIG_SATA_PMP=y
++# CONFIG_SATA_FSL is not set
++CONFIG_ATA_SFF=y
++# CONFIG_SATA_MV is not set
++CONFIG_PATA_MPC52xx=y
++# 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
@@ -121064,90 +153192,45 @@
+# 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_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_QSEMI_PHY=y
++CONFIG_LXT_PHY=y
++CONFIG_CICADA_PHY=y
++CONFIG_VITESSE_PHY=y
++CONFIG_SMSC_PHY=y
++CONFIG_BROADCOM_PHY=y
++CONFIG_ICPLUS_PHY=y
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
-+# CONFIG_MDIO_BITBANG is not set
++CONFIG_MDIO_BITBANG=y
+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
++CONFIG_FEC_MPC52xx=y
++CONFIG_FEC_MPC52xx_MDIO=y
++# 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_IWLWIFI 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_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
@@ -121157,27 +153240,7 @@
+#
+# 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
++# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
@@ -121190,17 +153253,11 @@
+#
+# 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 is not set
+
+#
+# Non-8250 serial port support
@@ -121208,80 +153265,47 @@
+# 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_SERIAL_MPC52xx=y
++CONFIG_SERIAL_MPC52xx_CONSOLE=y
++CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
-+CONFIG_HW_RANDOM=y
++# 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
++# CONFIG_I2C_PCA_PLATFORM is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
-+# CONFIG_SENSORS_EEPROM 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
@@ -121297,7 +153321,6 @@
+# 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
@@ -121319,16 +153342,13 @@
+# 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
@@ -121346,13 +153366,7 @@
+# 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
++# CONFIG_MPC5200_WDT is not set
+
+#
+# Sonics Silicon Backplane
@@ -121364,6 +153378,7 @@
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
++# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
@@ -121375,10 +153390,8 @@
+#
+# Graphics support
+#
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
-+CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
@@ -121391,24 +153404,23 @@
+# 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
++# CONFIG_USB_SUPPORT is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
+
+#
-+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++# LED drivers
+#
-+# 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
++
++#
++# LED Triggers
++#
++CONFIG_LEDS_TRIGGERS=y
++CONFIG_LEDS_TRIGGER_TIMER=y
++# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
++# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
@@ -121428,8 +153440,8 @@
+#
+# I2C RTC drivers
+#
-+# CONFIG_RTC_DRV_DS1307 is not set
-+CONFIG_RTC_DRV_DS1374=y
++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
@@ -121460,10 +153472,6 @@
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
-+
-+#
-+# Userspace I/O
-+#
+# CONFIG_UIO is not set
+
+#
@@ -121483,7 +153491,6 @@
+# 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
@@ -121502,8 +153509,11 @@
+#
+# DOS/FAT/NT Filesystems
+#
-+# CONFIG_MSDOS_FS is not set
-+# CONFIG_VFAT_FS is not set
++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
+
+#
@@ -121528,7 +153538,18 @@
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
-+# CONFIG_CRAMFS 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
@@ -121541,7 +153562,6 @@
+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
@@ -121567,7 +153587,11 @@
+# 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_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
@@ -121575,41 +153599,110 @@
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
-+# CONFIG_NLS 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
-+CONFIG_UCC_FAST=y
-+CONFIG_UCC=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
++# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# 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_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
+# 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_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=y
++# 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
++# 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_IRQSTACKS is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
@@ -121619,65 +153712,93 @@
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
-+# CONFIG_CRYPTO_SEQIV is not set
+CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++
++#
++# 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=y
++# CONFIG_CRYPTO_LRW is not set
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
-+# CONFIG_CRYPTO_NULL is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_MICHAEL_MIC 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=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_WP512 is not set
++
++#
++# Ciphers
++#
+# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA 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_DES=y
++# CONFIG_CRYPTO_FCRYPT 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_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
+# 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_CLOCK=y
+CONFIG_PPC_LIB_RHEAP=y
-diff --git a/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig b/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
++# CONFIG_VIRTUALIZATION is not set
+diff --git a/arch/powerpc/configs/52xx/pcm030_defconfig b/arch/powerpc/configs/52xx/pcm030_defconfig
new file mode 100644
-index 0000000..ac91302
+index 0000000..9c0caa4
--- /dev/null
-+++ b/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
-@@ -0,0 +1,1233 @@
++++ b/arch/powerpc/configs/52xx/pcm030_defconfig
+@@ -0,0 +1,1115 @@
+#
+# Automatically generated make config: don't edit
-+# Linux kernel version: 2.6.25-rc6
-+# Mon Mar 24 08:48:16 2008
++# Linux kernel version: 2.6.25
++# Tue Apr 29 07:13:19 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -121691,7 +153812,7 @@
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
-+# CONFIG_FSL_EMB_PERFMON is not set
++# CONFIG_ALTIVEC is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
@@ -121707,6 +153828,8 @@
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
@@ -121720,7 +153843,7 @@
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
-+CONFIG_PPC_UDBG_16550=y
++# CONFIG_PPC_UDBG_16550 is not set
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
@@ -121734,21 +153857,23 @@
+#
+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_LOCALVERSION="trunk"
++# 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_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_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_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
@@ -121756,13 +153881,13 @@
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
-+CONFIG_BLK_DEV_INITRD=y
-+CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
-+CONFIG_SYSCTL_SYSCALL=y
-+# CONFIG_KALLSYMS is not set
++# CONFIG_SYSCTL_SYSCALL is not set
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
@@ -121771,19 +153896,19 @@
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
-+# CONFIG_EPOLL is not set
++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_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_HAVE_KRETPROBES=y
+CONFIG_PROC_PAGE_MONITOR=y
@@ -121807,40 +153932,40 @@
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
-+CONFIG_IOSCHED_AS=y
-+CONFIG_IOSCHED_DEADLINE=y
-+CONFIG_IOSCHED_CFQ=y
-+CONFIG_DEFAULT_AS=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 is not set
-+CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Platform support
+#
-+# CONFIG_PPC_MULTIPLATFORM is not set
++CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_PPC_82xx is not set
-+CONFIG_PPC_83xx=y
++# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
++CONFIG_CLASSIC32=y
++# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_MPC512x is not set
+# CONFIG_PPC_MPC5121 is not set
++# CONFIG_MPC5121_ADS is not set
++CONFIG_PPC_MPC52xx=y
++CONFIG_PPC_MPC5200_SIMPLE=y
++# CONFIG_PPC_EFIKA is not set
++# CONFIG_PPC_LITE5200 is not set
++# CONFIG_PPC_MPC5200_BUGFIX is not set
++# CONFIG_PPC_MPC5200_GPIO is not set
++# CONFIG_PPC_PMAC 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_EMBEDDED6xx is not set
++# CONFIG_IPIC is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
@@ -121851,8 +153976,12 @@
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
-+CONFIG_QUICC_ENGINE=y
++# CONFIG_TAU is not set
+# CONFIG_FSL_ULI1575 is not set
++CONFIG_PPC_BESTCOMM=y
++CONFIG_PPC_BESTCOMM_ATA=y
++CONFIG_PPC_BESTCOMM_FEC=y
++CONFIG_PPC_BESTCOMM_GEN_BD=y
+
+#
+# Kernel options
@@ -121862,22 +153991,23 @@
+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_100=y
++# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
-+CONFIG_HZ=250
++CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
-+CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
-+# CONFIG_PREEMPT is not set
++CONFIG_PREEMPT=y
++# CONFIG_PREEMPT_RCU 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_KEXEC is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
@@ -121888,15 +154018,17 @@
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_PAGEFLAGS_EXTENDED=y
+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_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
-+CONFIG_SECCOMP=y
++# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
@@ -121904,7 +154036,7 @@
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
-+CONFIG_PPC_INDIRECT_PCI=y
++# CONFIG_PPC_INDIRECT_PCI is not set
+CONFIG_FSL_SOC=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
@@ -121915,6 +154047,7 @@
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
++# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
@@ -121924,11 +154057,11 @@
+#
+# Default settings for advanced configuration options are used
+#
-+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
++CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
-+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
@@ -121941,11 +154074,6 @@
+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
@@ -121959,25 +154087,22 @@
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
-+CONFIG_SYN_COOKIES=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 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_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
@@ -122029,33 +154154,92 @@
+# 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=y
++# CONFIG_MTD_OF_PARTS is not set
++# CONFIG_MTD_AR7_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=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=0x0
++CONFIG_MTD_PHYSMAP_LEN=0x0
++CONFIG_MTD_PHYSMAP_BANKWIDTH=1
++# 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_OF_I2C=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_BLK_DEV is not set
++# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
@@ -122063,16 +154247,16 @@
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
-+CONFIG_SCSI=y
++CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
-+CONFIG_SCSI_PROC_FS=y
++# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
-+CONFIG_BLK_DEV_SD=y
++CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
@@ -122096,44 +154280,68 @@
+# 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_SCSI_LOWLEVEL is not set
++CONFIG_ATA=m
++# CONFIG_ATA_NONSTANDARD is not set
++CONFIG_SATA_PMP=y
++# CONFIG_SATA_AHCI is not set
++# CONFIG_SATA_SIL24 is not set
++# CONFIG_SATA_FSL is not set
++CONFIG_ATA_SFF=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_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_MPC52xx=m
++# 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
+
@@ -122166,7 +154374,7 @@
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
-+CONFIG_ICPLUS_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
@@ -122176,7 +154384,6 @@
+# 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
@@ -122185,47 +154392,10 @@
+# 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_FEC_MPC52xx=y
++CONFIG_FEC_MPC52xx_MDIO=y
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
@@ -122233,6 +154403,8 @@
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI is not set
++# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# USB Network Adapters
@@ -122257,27 +154429,7 @@
+#
+# 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
++# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
@@ -122295,12 +154447,7 @@
+#
+# 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 is not set
+
+#
+# Non-8250 serial port support
@@ -122308,17 +154455,15 @@
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_SERIAL_MPC52xx=y
++CONFIG_SERIAL_MPC52xx_CONSOLE=y
++CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=9600
+# 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_LEGACY_PTYS is not set
+# 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
@@ -122329,13 +154474,6 @@
+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
@@ -122362,118 +154500,28 @@
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
++# CONFIG_I2C_PCA_PLATFORM is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
-+# CONFIG_SENSORS_EEPROM is not set
++CONFIG_SENSORS_EEPROM=m
+# 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_SPI 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_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
++# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
@@ -122485,14 +154533,14 @@
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
++# CONFIG_HTC_PASIC3 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
++# CONFIG_DAB is not set
+
+#
+# Graphics support
@@ -122500,7 +154548,7 @@
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
-+CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
@@ -122513,21 +154561,6 @@
+# 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
@@ -122540,27 +154573,26 @@
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
-+CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
++# CONFIG_USB_OTG_WHITELIST is not set
++# CONFIG_USB_OTG_BLACKLIST_HUB 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_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
-+CONFIG_USB_OHCI_HCD=y
++CONFIG_USB_OHCI_HCD=m
++# CONFIG_USB_OHCI_HCD_PPC_SOC is not set
+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_HCD_PCI 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_OHCI_LITTLE_ENDIAN is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
@@ -122578,7 +154610,7 @@
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
-+CONFIG_USB_STORAGE=y
++CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
@@ -122590,6 +154622,7 @@
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
@@ -122597,7 +154630,7 @@
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
-+CONFIG_USB_MON=y
++# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
@@ -122622,64 +154655,85 @@
+# 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
++# 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=m
++CONFIG_RTC_CLASS=m
+
+#
-+# MMC/SD Card Drivers
++# RTC interfaces
+#
-+CONFIG_MMC_BLOCK=y
-+CONFIG_MMC_BLOCK_BOUNCE=y
-+# CONFIG_SDIO_UART 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
+
+#
-+# MMC/SD Host Controller Drivers
++# I2C RTC 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
++# 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=m
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
+
+#
-+# Userspace I/O
++# 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
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
-+CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
-+CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS=m
+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_JBD=m
++CONFIG_FS_MBCACHE=m
+# 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_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
@@ -122694,10 +154748,10 @@
+#
+# DOS/FAT/NT Filesystems
+#
-+CONFIG_FAT_FS=y
-+CONFIG_MSDOS_FS=y
-+CONFIG_VFAT_FS=y
-+CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_FS=m
++# CONFIG_MSDOS_FS is not set
++CONFIG_VFAT_FS=m
++CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
@@ -122705,7 +154759,7 @@
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
-+CONFIG_PROC_KCORE=y
++# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
@@ -122723,6 +154777,17 @@
+# 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
@@ -122735,17 +154800,15 @@
+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_NFS_V4 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_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
@@ -122756,31 +154819,14 @@
+#
+# 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_PARTITION_ADVANCED 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_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_850=y
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
@@ -122794,10 +154840,10 @@
+# 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_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
-+CONFIG_NLS_ISO8859_8=y
++# 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
@@ -122816,23 +154862,25 @@
+# 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_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
-+CONFIG_CRC_ITU_T=y
++# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
-+CONFIG_CRC7=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
@@ -122840,15 +154888,16 @@
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
+# 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_IRQSTACKS is not set
++# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
@@ -122857,66 +154906,20 @@
+# 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_CRYPTO is not set
++CONFIG_PPC_CLOCK=y
+CONFIG_PPC_LIB_RHEAP=y
-diff --git a/arch/powerpc/configs/83xx/mpc834x_itx_defconfig b/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
++# CONFIG_VIRTUALIZATION is not set
+diff --git a/arch/powerpc/configs/52xx/tqm5200_defconfig b/arch/powerpc/configs/52xx/tqm5200_defconfig
new file mode 100644
-index 0000000..e1de399
+index 0000000..7672bfb
--- /dev/null
-+++ b/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
-@@ -0,0 +1,1295 @@
++++ b/arch/powerpc/configs/52xx/tqm5200_defconfig
+@@ -0,0 +1,1214 @@
+#
+# Automatically generated make config: don't edit
-+# Linux kernel version: 2.6.25-rc6
-+# Mon Mar 24 08:48:17 2008
++# Linux kernel version: 2.6.25
++# Tue Apr 29 07:12:39 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -122930,7 +154933,7 @@
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
-+# CONFIG_FSL_EMB_PERFMON is not set
++# CONFIG_ALTIVEC is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
@@ -122946,6 +154949,8 @@
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
@@ -122959,7 +154964,7 @@
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
-+CONFIG_PPC_UDBG_16550=y
++# CONFIG_PPC_UDBG_16550 is not set
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
@@ -122987,7 +154992,7 @@
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
-+# CONFIG_FAIR_GROUP_SCHED is not set
++CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
@@ -123000,7 +155005,7 @@
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
-+CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
@@ -123033,9 +155038,9 @@
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
-+# CONFIG_MODVERSIONS is not set
++CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
-+# CONFIG_KMOD is not set
++CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
@@ -123059,27 +155064,27 @@
+#
+# Platform support
+#
-+# CONFIG_PPC_MULTIPLATFORM is not set
++CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_PPC_82xx is not set
-+CONFIG_PPC_83xx=y
++# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
++CONFIG_CLASSIC32=y
++# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_MPC512x is not set
+# CONFIG_PPC_MPC5121 is not set
++# CONFIG_MPC5121_ADS is not set
++CONFIG_PPC_MPC52xx=y
++CONFIG_PPC_MPC5200_SIMPLE=y
++# CONFIG_PPC_EFIKA is not set
++# CONFIG_PPC_LITE5200 is not set
++CONFIG_PPC_MPC5200_BUGFIX=y
++# CONFIG_PPC_MPC5200_GPIO is not set
++# CONFIG_PPC_PMAC 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_EMBEDDED6xx is not set
++# CONFIG_IPIC is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
@@ -123090,15 +155095,20 @@
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
++# CONFIG_TAU is not set
+# CONFIG_FSL_ULI1575 is not set
++CONFIG_PPC_BESTCOMM=y
++# CONFIG_PPC_BESTCOMM_ATA is not set
++CONFIG_PPC_BESTCOMM_FEC=y
++# CONFIG_PPC_BESTCOMM_GEN_BD is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
-+CONFIG_TICK_ONESHOT=y
-+CONFIG_NO_HZ=y
-+CONFIG_HIGH_RES_TIMERS=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
@@ -123115,6 +155125,7 @@
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++# CONFIG_KEXEC is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
@@ -123125,14 +155136,18 @@
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_PAGEFLAGS_EXTENDED=y
+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_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
-+# CONFIG_PM is not set
++CONFIG_PM=y
++# CONFIG_PM_LEGACY is not set
++# CONFIG_PM_DEBUG is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
@@ -123141,17 +155156,13 @@
+#
+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 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
-+# CONFIG_HOTPLUG_PCI is not set
++# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
@@ -123161,11 +155172,11 @@
+#
+# Default settings for advanced configuration options are used
+#
-+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
++CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
-+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
@@ -123179,7 +155190,7 @@
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+# CONFIG_XFRM_USER is not set
++CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
@@ -123213,8 +155224,6 @@
+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
@@ -123264,20 +155273,25 @@
+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 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
++# CONFIG_MTD_AR7_PARTS 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_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
@@ -123307,27 +155321,20 @@
+# 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_ROM=y
+# 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_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
+# 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
@@ -123347,18 +155354,14 @@
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_OF_DEVICE=y
++CONFIG_OF_I2C=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
@@ -123366,18 +155369,9 @@
+# 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_MISC_DEVICES 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
++# CONFIG_IDE is not set
+
+#
+# SCSI device support
@@ -123411,126 +155405,24 @@
+#
+# SCSI Transports
+#
-+CONFIG_SCSI_SPI_ATTRS=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_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_PMP=y
+# 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_ATA_SFF=y
++# CONFIG_SATA_MV is not set
++CONFIG_PATA_MPC52xx=y
+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_PATA_OF_PLATFORM is not set
++# CONFIG_MD is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
@@ -123540,7 +155432,6 @@
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
-+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
@@ -123549,8 +155440,8 @@
+# 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_LXT_PHY=y
++# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
@@ -123558,49 +155449,25 @@
+# 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
-+
-+#
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII 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_FEC_MPC52xx=y
++CONFIG_FEC_MPC52xx_MDIO=y
++# 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_IWLWIFI is not set
++# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# USB Network Adapters
@@ -123611,11 +155478,8 @@
+# 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
@@ -123638,17 +155502,11 @@
+#
+# 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
++# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
@@ -123656,96 +155514,101 @@
+# 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_MPC52xx=y
++CONFIG_SERIAL_MPC52xx_CONSOLE=y
++CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
-+CONFIG_HW_RANDOM=y
++# 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_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_PCA_PLATFORM is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
-+CONFIG_SENSORS_PCF8574=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=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_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
-+# CONFIG_HWMON 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
@@ -123754,13 +155617,7 @@
+# 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
++# CONFIG_MPC5200_WDT is not set
+
+#
+# USB-based Watchdog Cards
@@ -123777,22 +155634,20 @@
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
++# CONFIG_HTC_PASIC3 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
++# 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_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
@@ -123808,7 +155663,7 @@
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
-+CONFIG_USB_ARCH_HAS_EHCI=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
@@ -123817,21 +155672,25 @@
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
-+CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
++# CONFIG_USB_OTG_WHITELIST is not set
++# CONFIG_USB_OTG_BLACKLIST_HUB 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_OHCI_HCD=y
++CONFIG_USB_OHCI_HCD_PPC_SOC=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 is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
@@ -123860,6 +155719,7 @@
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
@@ -123892,7 +155752,6 @@
+# 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
@@ -123901,7 +155760,6 @@
+# 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
@@ -123915,7 +155773,7 @@
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
-+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
@@ -123936,9 +155794,6 @@
+#
+# 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
@@ -123956,10 +155811,6 @@
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
-+
-+#
-+# Userspace I/O
-+#
+# CONFIG_UIO is not set
+
+#
@@ -123979,7 +155830,6 @@
+# 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
@@ -124027,8 +155877,18 @@
+# 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_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
@@ -124041,7 +155901,6 @@
+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
@@ -124066,7 +155925,7 @@
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
-+CONFIG_MAC_PARTITION=y
++# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
@@ -124081,7 +155940,7 @@
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
-+# CONFIG_NLS_CODEPAGE_437 is not set
++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
@@ -124105,7 +155964,7 @@
+# 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_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
@@ -124125,32 +155984,65 @@
+# Library routines
+#
+CONFIG_BITREVERSE=y
++# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# 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_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
+# 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_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=y
++# 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
++# 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_IRQSTACKS is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
@@ -124160,64 +156052,94 @@
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
-+# CONFIG_CRYPTO_SEQIV is not set
+CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# 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=y
++# CONFIG_CRYPTO_LRW is not set
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
-+# CONFIG_CRYPTO_NULL is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_MICHAEL_MIC 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=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_WP512 is not set
++
++#
++# Ciphers
++#
+# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA 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_DES=y
++# CONFIG_CRYPTO_FCRYPT 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_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
+# 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
++CONFIG_PPC_CLOCK=y
++CONFIG_PPC_LIB_RHEAP=y
++# CONFIG_VIRTUALIZATION 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..b4e39cf
+index 0000000..7d18440
--- /dev/null
-+++ b/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig
-@@ -0,0 +1,1222 @@
++++ 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
-+# Mon Mar 24 08:48:18 2008
++# Fri Apr 11 11:10:09 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -124370,16 +156292,16 @@
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+CONFIG_MPC83xx=y
-+# CONFIG_MPC831x_RDB is not set
++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=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_PPC_MPC831x=y
+CONFIG_IPIC=y
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
@@ -124412,6 +156334,7 @@
+# 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
@@ -124451,6 +156374,7 @@
+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
+
@@ -124565,20 +156489,24 @@
+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 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 is not set
-+# CONFIG_MTD_BLOCK is not set
-+# CONFIG_MTD_BLOCK_RO 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
@@ -124615,11 +156543,8 @@
+# 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_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
@@ -124640,7 +156565,17 @@
+# 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_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
+
+#
@@ -124689,7 +156624,7 @@
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
-+CONFIG_BLK_DEV_SD=y
++# 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
@@ -124751,7 +156686,16 @@
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_ATA is not set
-+# CONFIG_MD 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
+
+#
@@ -124787,7 +156731,39 @@
+# 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_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
@@ -124854,7 +156830,27 @@
+#
+# Input device support
+#
-+# CONFIG_INPUT is not set
++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
@@ -124874,7 +156870,7 @@
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
-+# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -124943,7 +156939,7 @@
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
-+CONFIG_SENSORS_PCF8574=y
++# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
@@ -124958,6 +156954,7 @@
+# SPI support
+#
+CONFIG_SPI=y
++# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
@@ -124974,7 +156971,61 @@
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
-+# CONFIG_HWMON 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
@@ -125034,6 +157085,21 @@
+# 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
@@ -125045,7 +157111,7 @@
+#
+# Miscellaneous USB options
+#
-+# CONFIG_USB_DEVICEFS is not set
++CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
@@ -125059,7 +157125,14 @@
+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_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
@@ -125125,7 +157198,33 @@
+# 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_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
@@ -125226,11 +157325,8 @@
+#
+# 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_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
@@ -125255,7 +157351,17 @@
+# 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_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
@@ -125294,7 +157400,7 @@
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
-+CONFIG_MAC_PARTITION=y
++# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
@@ -125307,46 +157413,7 @@
+# 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_NLS is not set
+# CONFIG_DLM is not set
+
+#
@@ -125359,10 +157426,13 @@
+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
@@ -125374,11 +157444,36 @@
+# 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_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
+
+#
@@ -125436,16 +157531,16 @@
+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
+diff --git a/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig b/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
new file mode 100644
-index 0000000..b4e82c0
+index 0000000..1f57456
--- /dev/null
-+++ b/arch/powerpc/configs/83xx/mpc834x_mds_defconfig
-@@ -0,0 +1,1021 @@
++++ 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-rc7
-+# Mon Mar 31 11:36:56 2008
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:15 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -125598,16 +157693,16 @@
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+CONFIG_MPC83xx=y
-+# CONFIG_MPC831x_RDB is not set
++CONFIG_MPC831x_RDB=y
+# CONFIG_MPC832x_MDS is not set
+# CONFIG_MPC832x_RDB is not set
-+CONFIG_MPC834x_MDS=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_MPC834x=y
++CONFIG_PPC_MPC831x=y
+CONFIG_IPIC=y
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
@@ -125679,6 +157774,7 @@
+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
+
@@ -125708,7 +157804,7 @@
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+CONFIG_XFRM_USER=m
++# 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
@@ -125793,9 +157889,99 @@
+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_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
@@ -125809,6 +157995,7 @@
+# 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
@@ -125828,11 +158015,145 @@
+# 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_MD 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
+
+#
@@ -125856,7 +158177,7 @@
+#
+# MII PHY device drivers
+#
-+CONFIG_MARVELL_PHY=y
++# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
@@ -125874,6 +158195,7 @@
+# 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
@@ -125920,7 +158242,7 @@
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
-+# CONFIG_GFAR_NAPI is not set
++CONFIG_GFAR_NAPI=y
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
@@ -125942,11 +158264,21 @@
+#
+# 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
@@ -126013,7 +158345,7 @@
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
-+# CONFIG_HW_RANDOM is not set
++CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
@@ -126055,6 +158387,7 @@
+# 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
@@ -126078,8 +158411,22 @@
+#
+# 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
++
++#
++# 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
@@ -126103,6 +158450,7 @@
+# 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
@@ -126153,6 +158501,11 @@
+# CONFIG_WDTPCI is not set
+
+#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++
++#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
@@ -126169,6 +158522,7 @@
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
@@ -126193,16 +158547,142 @@
+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 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=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'
+#
-+# CONFIG_USB_GADGET is not set
++
++#
++# 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
@@ -126220,14 +158700,14 @@
+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_INTF_DEV_UIE_EMUL=y
+# 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_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
@@ -126241,6 +158721,9 @@
+#
+# 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
@@ -126326,6 +158809,17 @@
+# 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
@@ -126365,7 +158859,11 @@
+# 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_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
@@ -126386,6 +158884,8 @@
+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
@@ -126401,11 +158901,36 @@
+# 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_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
+
+#
@@ -126430,7 +158955,7 @@
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
-+CONFIG_CRYPTO_ECB=m
++# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
@@ -126463,16 +158988,16 @@
+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
+diff --git a/arch/powerpc/configs/83xx/mpc832x_mds_defconfig b/arch/powerpc/configs/83xx/mpc832x_mds_defconfig
new file mode 100644
-index 0000000..d50a96e
+index 0000000..50cceda
--- /dev/null
-+++ b/arch/powerpc/configs/83xx/mpc836x_mds_defconfig
-@@ -0,0 +1,1079 @@
++++ 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:57 2008
++# Mon Mar 31 11:36:51 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -126626,14 +159151,15 @@
+# CONFIG_PQ2ADS is not set
+CONFIG_MPC83xx=y
+# CONFIG_MPC831x_RDB is not set
-+# CONFIG_MPC832x_MDS 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=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_MPC832x=y
+CONFIG_IPIC=y
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
@@ -126667,6 +159193,7 @@
+# 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
@@ -126950,8 +159477,8 @@
+#
+# MII PHY device drivers
+#
-+CONFIG_MARVELL_PHY=y
-+# CONFIG_DAVICOM_PHY is not set
++# 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
@@ -127548,16 +160075,16 @@
+# 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
+diff --git a/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig b/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
new file mode 100644
-index 0000000..f377cde
+index 0000000..ac91302
--- /dev/null
-+++ b/arch/powerpc/configs/83xx/mpc837x_mds_defconfig
-@@ -0,0 +1,899 @@
++++ 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:23 2008
++# Mon Mar 24 08:48:16 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -127628,7 +160155,7 @@
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
-+CONFIG_FAIR_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
@@ -127642,8 +160169,7 @@
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
-+CONFIG_KALLSYMS=y
-+# CONFIG_KALLSYMS_EXTRA_PASS is not set
++# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
@@ -127658,13 +160184,13 @@
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
-+CONFIG_SLAB=y
-+# CONFIG_SLUB is not set
++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
@@ -127713,14 +160239,14 @@
+CONFIG_MPC83xx=y
+# CONFIG_MPC831x_RDB is not set
+# CONFIG_MPC832x_MDS is not set
-+# CONFIG_MPC832x_RDB 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=y
++# CONFIG_MPC837x_MDS is not set
+# CONFIG_MPC837x_RDB is not set
+# CONFIG_SBC834x is not set
-+CONFIG_PPC_MPC837x=y
++CONFIG_PPC_MPC832x=y
+CONFIG_IPIC=y
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
@@ -127732,15 +160258,16 @@
+# 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 is not set
-+# CONFIG_NO_HZ is not set
-+# CONFIG_HIGH_RES_TIMERS 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
@@ -127753,6 +160280,7 @@
+# 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
@@ -127785,11 +160313,15 @@
+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_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
@@ -127817,7 +160349,7 @@
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+CONFIG_XFRM_USER=m
++# 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
@@ -127909,10 +160441,16 @@
+# 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
@@ -127920,7 +160458,10 @@
+# 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
@@ -127942,7 +160483,7 @@
+# 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_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
@@ -127964,13 +160505,51 @@
+# 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_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_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
@@ -127980,12 +160559,13 @@
+# 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_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
@@ -127993,31 +160573,88 @@
+# 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_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_GIANFAR=y
-+# CONFIG_GFAR_NAPI 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
@@ -128060,12 +160697,14 @@
+#
+# 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
@@ -128076,18 +160715,22 @@
+# 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 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
@@ -128102,12 +160745,30 @@
+#
+# 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
@@ -128128,8 +160789,21 @@
+#
+# SPI support
+#
-+# CONFIG_SPI is not set
-+# CONFIG_SPI_MASTER is not set
++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
@@ -128145,6 +160819,7 @@
+# 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
@@ -128152,6 +160827,7 @@
+# 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
@@ -128166,13 +160842,16 @@
+# 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
@@ -128193,6 +160872,17 @@
+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
@@ -128209,10 +160899,13 @@
+# 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
@@ -128231,19 +160924,138 @@
+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 is not set
++CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
-+# CONFIG_USB 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=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 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
@@ -128289,8 +161101,11 @@
+#
+# DOS/FAT/NT Filesystems
+#
-+# CONFIG_MSDOS_FS is not set
-+# CONFIG_VFAT_FS is not set
++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
+
+#
@@ -128359,15 +161174,57 @@
+# 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_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 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
@@ -128375,9 +161232,9 @@
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
-+# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
-+# CONFIG_CRC7 is not set
++CONFIG_CRC7=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
@@ -128395,6 +161252,8 @@
+# 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
@@ -128452,17 +161311,19 @@
+# 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/mpc837x_rdb_defconfig b/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig
++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..a633176
+index 0000000..e1de399
--- /dev/null
-+++ b/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig
-@@ -0,0 +1,930 @@
++++ 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:24 2008
++# Mon Mar 24 08:48:17 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -128533,7 +161394,7 @@
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
-+CONFIG_FAIR_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
@@ -128547,8 +161408,7 @@
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
-+CONFIG_KALLSYMS=y
-+# CONFIG_KALLSYMS_EXTRA_PASS is not set
++# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
@@ -128563,13 +161423,13 @@
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
-+CONFIG_SLAB=y
-+# CONFIG_SLUB is not set
++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
@@ -128620,12 +161480,12 @@
+# 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_MPC834x_ITX=y
+# CONFIG_MPC836x_MDS is not set
+# CONFIG_MPC837x_MDS is not set
-+CONFIG_MPC837x_RDB=y
++# CONFIG_MPC837x_RDB is not set
+# CONFIG_SBC834x is not set
-+CONFIG_PPC_MPC837x=y
++CONFIG_PPC_MPC834x=y
+CONFIG_IPIC=y
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
@@ -128643,9 +161503,9 @@
+# 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_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
@@ -128690,11 +161550,15 @@
+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_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
@@ -128721,6 +161585,11 @@
+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
@@ -128740,9 +161609,9 @@
+# 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_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
@@ -128804,15 +161673,100 @@
+# 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 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
@@ -128820,10 +161774,17 @@
+# 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
++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
@@ -128857,30 +161818,126 @@
+#
+# SCSI Transports
+#
-+# CONFIG_SCSI_SPI_ATTRS is not set
++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_FSL=y
-+# CONFIG_PATA_PLATFORM 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 is not set
-+# CONFIG_MD_RAID0 is not set
++CONFIG_MD_LINEAR=y
++CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
-+CONFIG_MD_RAID456=y
-+CONFIG_MD_RAID5_RESHAPE=y
++# 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
@@ -128890,16 +161947,17 @@
+# 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_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_CICADA_PHY=y
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
@@ -128907,27 +161965,64 @@
+# 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_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_NETDEV_10000 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
@@ -128937,27 +162032,7 @@
+#
+# 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
++# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
@@ -128970,12 +162045,14 @@
+#
+# 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
@@ -128986,18 +162063,20 @@
+# 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_HW_RANDOM=y
+# CONFIG_NVRAM is not set
-+CONFIG_GEN_RTC=y
-+# CONFIG_GEN_RTC_X 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
@@ -129012,19 +162091,37 @@
+#
+# 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_SENSORS_PCF8574=y
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
@@ -129038,60 +162135,24 @@
+#
+# SPI support
+#
-+# CONFIG_SPI is not set
-+# CONFIG_SPI_MASTER is not set
++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_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_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -129103,6 +162164,17 @@
+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
@@ -129119,10 +162191,13 @@
+# 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
@@ -129137,13 +162212,9 @@
+# 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_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
@@ -129152,7 +162223,7 @@
+#
+# Miscellaneous USB options
+#
-+# CONFIG_USB_DEVICEFS is not set
++CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
@@ -129166,27 +162237,140 @@
+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
+
+#
-+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++# USB Device Class drivers
+#
-+# 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
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
+
+#
-+# Userspace I/O
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
-+# CONFIG_UIO is not set
+
+#
-+# File systems
++# 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
@@ -129221,8 +162405,11 @@
+#
+# DOS/FAT/NT Filesystems
+#
-+# CONFIG_MSDOS_FS is not set
-+# CONFIG_VFAT_FS is not set
++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
+
+#
@@ -129247,6 +162434,7 @@
+# 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
@@ -129285,7 +162473,7 @@
+# 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_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
@@ -129298,7 +162486,46 @@
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
-+# CONFIG_NLS 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
+
+#
@@ -129321,12 +162548,14 @@
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
-+# CONFIG_ENABLE_MUST_CHECK 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_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
@@ -129337,10 +162566,6 @@
+# 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
@@ -129357,7 +162582,7 @@
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
-+CONFIG_CRYPTO_ECB=m
++# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
@@ -129388,17 +162613,18 @@
+# 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/sbc834x_defconfig b/arch/powerpc/configs/83xx/sbc834x_defconfig
+diff --git a/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig b/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig
new file mode 100644
-index 0000000..1f15182
+index 0000000..b4e39cf
--- /dev/null
-+++ b/arch/powerpc/configs/83xx/sbc834x_defconfig
-@@ -0,0 +1,828 @@
++++ 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:38 2008
++# Mon Mar 24 08:48:18 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -129469,7 +162695,7 @@
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
-+CONFIG_FAIR_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
@@ -129498,8 +162724,9 @@
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
-+CONFIG_SLAB=y
-+# CONFIG_SLUB is not set
++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
@@ -129554,11 +162781,11 @@
+# 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_MPC834x_ITX=y
+# CONFIG_MPC836x_MDS is not set
+# CONFIG_MPC837x_MDS is not set
+# CONFIG_MPC837x_RDB is not set
-+CONFIG_SBC834x=y
++# CONFIG_SBC834x is not set
+CONFIG_PPC_MPC834x=y
+CONFIG_IPIC=y
+# CONFIG_MPIC is not set
@@ -129577,9 +162804,9 @@
+# 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_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
@@ -129624,11 +162851,15 @@
+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_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
@@ -129656,7 +162887,7 @@
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+CONFIG_XFRM_USER=m
++# 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
@@ -129743,15 +162974,100 @@
+# 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 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
@@ -129759,7 +163075,10 @@
+# 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
@@ -129768,11 +163087,86 @@
+# 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_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
@@ -129782,6 +163176,7 @@
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
@@ -129791,35 +163186,72 @@
+# 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_CICADA_PHY=y
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
-+CONFIG_BROADCOM_PHY=y
++# 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_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 is not set
-+# CONFIG_NETDEV_10000 is not set
++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
@@ -129829,27 +163261,7 @@
+#
+# 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
++# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
@@ -129862,12 +163274,14 @@
+#
+# 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
@@ -129878,18 +163292,20 @@
+# 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_HW_RANDOM=y
+# CONFIG_NVRAM is not set
-+CONFIG_GEN_RTC=y
-+# CONFIG_GEN_RTC_X 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
@@ -129904,19 +163320,37 @@
+#
+# 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_SENSORS_PCF8574=y
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
@@ -129930,60 +163364,24 @@
+#
+# SPI support
+#
-+# CONFIG_SPI is not set
-+# CONFIG_SPI_MASTER is not set
++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_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_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -129995,6 +163393,17 @@
+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
@@ -130010,13 +163419,16 @@
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
-+# CONFIG_DAB 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 is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
@@ -130029,16 +163441,155 @@
+# 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_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_CLASS 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
+
+#
@@ -130049,9 +163600,16 @@
+#
+# File systems
+#
-+# CONFIG_EXT2_FS is not set
-+# CONFIG_EXT3_FS is not set
++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
@@ -130075,8 +163633,11 @@
+#
+# DOS/FAT/NT Filesystems
+#
-+# CONFIG_MSDOS_FS is not set
-+# CONFIG_VFAT_FS is not set
++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
+
+#
@@ -130101,6 +163662,7 @@
+# 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
@@ -130134,9 +163696,64 @@
+#
+# Partition Types
+#
-+# CONFIG_PARTITION_ADVANCED is not set
++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_NLS is not set
++# 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
+
+#
@@ -130165,6 +163782,8 @@
+# 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
@@ -130191,7 +163810,7 @@
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
-+CONFIG_CRYPTO_ECB=m
++# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
@@ -130221,37 +163840,37 @@
+# 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_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X 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
+diff --git a/arch/powerpc/configs/83xx/mpc834x_mds_defconfig b/arch/powerpc/configs/83xx/mpc834x_mds_defconfig
new file mode 100644
-index 0000000..2d0debc
+index 0000000..b4e82c0
--- /dev/null
-+++ b/arch/powerpc/configs/85xx/ksi8560_defconfig
-@@ -0,0 +1,899 @@
++++ b/arch/powerpc/configs/83xx/mpc834x_mds_defconfig
+@@ -0,0 +1,1021 @@
+#
+# Automatically generated make config: don't edit
-+# Linux kernel version: 2.6.24
-+# Mon Feb 11 16:25:19 2008
++# Linux kernel version: 2.6.25-rc7
++# Mon Mar 31 11:36:56 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
-+# CONFIG_6xx is not set
-+CONFIG_PPC_85xx=y
++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_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_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
@@ -130299,34 +163918,35 @@
+# 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_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_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=y
++# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
@@ -130340,12 +163960,18 @@
+# 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_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
@@ -130365,32 +163991,32 @@
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
-+# CONFIG_PREEMPT_RCU is not set
+
+#
+# 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_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_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
@@ -130400,18 +164026,15 @@
+# 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_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
@@ -130422,12 +164045,12 @@
+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_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
@@ -130443,23 +164066,28 @@
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
-+# CONFIG_PROC_DEVICETREE is not set
++CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
-+# CONFIG_SECCOMP is not set
-+CONFIG_WANT_DEVICE_TREE=y
++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_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
@@ -130487,7 +164115,7 @@
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+# CONFIG_XFRM_USER is not set
++CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
@@ -130572,124 +164200,36 @@
+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_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_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
++# CONFIG_PHANTOM is not set
+# 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
++# 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
@@ -130700,6 +164240,14 @@
+# 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
@@ -130709,6 +164257,7 @@
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
@@ -130725,23 +164274,75 @@
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
-+CONFIG_MDIO_BITBANG=y
++# 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_FS_ENET=y
-+# CONFIG_FS_ENET_HAS_SCC is not set
-+CONFIG_FS_ENET_HAS_FCC=y
-+CONFIG_FS_ENET_MDIO_FCC=y
++# 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_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
@@ -130749,6 +164350,8 @@
+# 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
@@ -130793,11 +164396,17 @@
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
-+# CONFIG_SERIAL_8250 is not set
++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
@@ -130805,26 +164414,73 @@
+# 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_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
-+CONFIG_GEN_RTC=y
-+# CONFIG_GEN_RTC_X 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_I2C 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
@@ -130835,18 +164491,73 @@
+# 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_WATCHDOG 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
@@ -130869,8 +164580,10 @@
+#
+# Graphics support
+#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
-+CONFIG_VIDEO_OUTPUT_CONTROL=y
++CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
@@ -130888,18 +164601,70 @@
+# 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
++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_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
@@ -130918,7 +164683,6 @@
+# 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
@@ -130926,12 +164690,10 @@
+# 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_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
@@ -130971,25 +164733,29 @@
+# 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 is not set
-+# CONFIG_NFS_V4 is not set
++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 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
@@ -131040,40 +164806,13 @@
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
-+CONFIG_DEBUG_FS=y
++# 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_KERNEL 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_SLUB_STATS 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
+
+#
@@ -131083,29 +164822,31 @@
+# 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 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 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 is not set
-+# CONFIG_CRYPTO_PCBC 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 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
@@ -131123,40 +164864,40 @@
+# 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/mpc8540_ads_defconfig b/arch/powerpc/configs/85xx/mpc8540_ads_defconfig
+diff --git a/arch/powerpc/configs/83xx/mpc836x_mds_defconfig b/arch/powerpc/configs/83xx/mpc836x_mds_defconfig
new file mode 100644
-index 0000000..b998539
+index 0000000..d50a96e
--- /dev/null
-+++ b/arch/powerpc/configs/85xx/mpc8540_ads_defconfig
-@@ -0,0 +1,796 @@
++++ 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-rc6
-+# Mon Mar 24 08:48:25 2008
++# Linux kernel version: 2.6.25-rc7
++# Mon Mar 31 11:36:57 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
-+# CONFIG_6xx is not set
-+CONFIG_PPC_85xx=y
++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_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_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
@@ -131223,9 +164964,7 @@
+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_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
@@ -131234,7 +164973,7 @@
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
-+CONFIG_EPOLL=y
++# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
@@ -131254,7 +164993,12 @@
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
-+# CONFIG_MODULES is not set
++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
@@ -131278,26 +165022,27 @@
+#
+# 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_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_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
@@ -131307,7 +165052,7 @@
+# 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_QUICC_ENGINE=y
+# CONFIG_FSL_ULI1575 is not set
+
+#
@@ -131328,8 +165073,7 @@
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
-+CONFIG_BINFMT_MISC=y
-+CONFIG_MATH_EMULATION=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
@@ -131352,19 +165096,25 @@
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
-+# CONFIG_SECCOMP 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_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
@@ -131392,7 +165142,7 @@
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+CONFIG_XFRM_USER=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
@@ -131477,8 +165227,6 @@
+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
@@ -131486,10 +165234,15 @@
+# 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
@@ -131497,7 +165250,10 @@
+# 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
@@ -131506,11 +165262,86 @@
+# 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_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
@@ -131520,12 +165351,13 @@
+# 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_MARVELL_PHY=y
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
@@ -131539,16 +165371,58 @@
+# 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_GIANFAR=y
-+CONFIG_GFAR_NAPI=y
++# 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
@@ -131556,8 +165430,11 @@
+# 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
@@ -131600,16 +165477,17 @@
+#
+# 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
@@ -131617,19 +165495,74 @@
+# 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 is not set
++CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
-+CONFIG_GEN_RTC=y
-+# CONFIG_GEN_RTC_X 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_I2C 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
@@ -131640,19 +165573,73 @@
+# 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
++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
@@ -131675,8 +165662,10 @@
+#
+# Graphics support
+#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
-+CONFIG_VIDEO_OUTPUT_CONTROL=y
++CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
@@ -131694,9 +165683,10 @@
+# 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
++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'
@@ -131705,8 +165695,57 @@
+# 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_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
+
+#
@@ -131786,16 +165825,19 @@
+# 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_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 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
@@ -131822,6 +165864,8 @@
+# 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
@@ -131848,35 +165892,11 @@
+# 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_KERNEL 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
+
+#
@@ -131886,29 +165906,31 @@
+# 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 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 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 is not set
-+# CONFIG_CRYPTO_PCBC 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 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
@@ -131926,39 +165948,41 @@
+# 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/mpc8544_ds_defconfig b/arch/powerpc/configs/85xx/mpc8544_ds_defconfig
++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..a9f113b
+index 0000000..f377cde
--- /dev/null
-+++ b/arch/powerpc/configs/85xx/mpc8544_ds_defconfig
-@@ -0,0 +1,1564 @@
++++ 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-rc7
-+# Mon Mar 31 11:37:03 2008
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:23 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
-+# CONFIG_6xx is not set
-+CONFIG_PPC_85xx=y
++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_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_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
@@ -132003,18 +166027,15 @@
+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_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
-+CONFIG_AUDIT=y
-+# CONFIG_AUDITSYSCALL is not set
-+CONFIG_IKCONFIG=y
-+CONFIG_IKCONFIG_PROC=y
++# 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_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
@@ -132029,8 +166050,7 @@
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
-+CONFIG_KALLSYMS_ALL=y
-+CONFIG_KALLSYMS_EXTRA_PASS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
@@ -132039,15 +166059,14 @@
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
-+CONFIG_EPOLL=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_SLAB=y
++# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
@@ -132062,12 +166081,12 @@
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
-+CONFIG_MODULE_FORCE_UNLOAD=y
-+CONFIG_MODVERSIONS=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
-+CONFIG_KMOD=y
++# CONFIG_KMOD is not set
+CONFIG_BLOCK=y
-+CONFIG_LBD=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
@@ -132079,39 +166098,40 @@
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
-+# CONFIG_DEFAULT_AS is not set
++CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
-+CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
-+CONFIG_DEFAULT_IOSCHED="cfq"
++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_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_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=y
++# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
@@ -132119,16 +166139,15 @@
+# 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
++# CONFIG_FSL_ULI1575 is not set
+
+#
+# Kernel options
+#
-+CONFIG_HIGHMEM=y
-+CONFIG_TICK_ONESHOT=y
-+CONFIG_NO_HZ=y
-+CONFIG_HIGH_RES_TIMERS=y
++# 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
@@ -132140,9 +166159,7 @@
+# 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_BINFMT_MISC is not set
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
@@ -132175,17 +166192,11 @@
+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_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
-+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
@@ -132213,41 +166224,32 @@
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+CONFIG_XFRM_USER=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_NET_KEY 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_ADVANCED_ROUTER 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_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=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_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
@@ -132255,32 +166257,13 @@
+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_IPV6 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_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
@@ -132304,7 +166287,6 @@
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
-+CONFIG_FIB_RULES=y
+
+#
+# Wireless
@@ -132326,9 +166308,7 @@
+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_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
@@ -132336,27 +166316,18 @@
+# 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_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
-+CONFIG_BLK_DEV_RAM_SIZE=131072
++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
@@ -132375,19 +166346,18 @@
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
-+CONFIG_CHR_DEV_ST=y
++# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
-+CONFIG_BLK_DEV_SR=y
-+# CONFIG_BLK_DEV_SR_VENDOR is not set
++# CONFIG_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_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
-+CONFIG_SCSI_LOGGING=y
++# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
@@ -132401,130 +166371,33 @@
+# 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_SATA_FSL=y
+# 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_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_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=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
@@ -132533,75 +166406,25 @@
+# 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_GFAR_NAPI 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
@@ -132636,37 +166459,23 @@
+#
+# 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_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_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=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
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
@@ -132674,23 +166483,21 @@
+# 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_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 is not set
++CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
@@ -132702,36 +166509,18 @@
+#
+# 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_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCF8591 is not set
@@ -132750,9 +166539,65 @@
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
-+# CONFIG_HWMON 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 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
@@ -132769,124 +166614,14 @@
+# 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_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=y
++CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
@@ -132896,318 +166631,29 @@
+# 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_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_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=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
++# CONFIG_USB 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
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
+
+#
+# Userspace I/O
@@ -133244,23 +166690,15 @@
+#
+# CD-ROM/DVD Filesystems
+#
-+CONFIG_ISO9660_FS=m
-+CONFIG_JOLIET=y
-+CONFIG_ZISOFS=y
-+CONFIG_UDF_FS=m
-+CONFIG_UDF_NLS=y
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
+
+#
+# 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
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
@@ -133277,38 +166715,31 @@
+#
+# 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_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=m
-+CONFIG_QNX4FS_FS=m
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
+# 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_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=y
-+# CONFIG_NFSD_V3 is not set
-+CONFIG_NFSD_TCP=y
++# CONFIG_NFSD is not set
+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
@@ -133329,7 +166760,7 @@
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
-+CONFIG_MAC_PARTITION=y
++# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
@@ -133342,46 +166773,7 @@
+# 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_NLS is not set
+# CONFIG_DLM is not set
+
+#
@@ -133393,13 +166785,11 @@
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
-+CONFIG_LIBCRC32C=m
-+CONFIG_ZLIB_INFLATE=y
++# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
-+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
@@ -133411,37 +166801,9 @@
+# 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_KERNEL 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
+
+#
@@ -133454,20 +166816,19 @@
+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_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=m
++# 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_ECB=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
@@ -133498,37 +166859,35 @@
+# 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
+diff --git a/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig b/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig
new file mode 100644
-index 0000000..851ac91
+index 0000000..a633176
--- /dev/null
-+++ b/arch/powerpc/configs/85xx/mpc8560_ads_defconfig
-@@ -0,0 +1,885 @@
++++ 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:27 2008
++# Mon Mar 24 08:48:24 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
-+# CONFIG_6xx is not set
-+CONFIG_PPC_85xx=y
++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_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_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
@@ -133581,7 +166940,7 @@
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
-+# CONFIG_FAIR_GROUP_SCHED is not set
++CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
@@ -133596,7 +166955,6 @@
+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
@@ -133606,19 +166964,19 @@
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
-+CONFIG_EPOLL=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_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
@@ -133626,7 +166984,12 @@
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
-+# CONFIG_MODULES is not set
++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
@@ -133650,26 +167013,28 @@
+#
+# 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_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_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
@@ -133679,10 +167044,7 @@
+# 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
@@ -133702,8 +167064,7 @@
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
-+CONFIG_BINFMT_MISC=y
-+CONFIG_MATH_EMULATION=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
@@ -133723,29 +167084,24 @@
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
-+# CONFIG_PROC_DEVICETREE is not set
++CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
-+# CONFIG_SECCOMP 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=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
-+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
@@ -133772,11 +167128,6 @@
+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
@@ -133796,9 +167147,9 @@
+# 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
@@ -133858,8 +167209,6 @@
+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
@@ -133867,15 +167216,10 @@
+# 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
@@ -133883,10 +167227,7 @@
+# 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
@@ -133895,19 +167236,58 @@
+# 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_MD is not set
-+# CONFIG_FUSION is not set
++CONFIG_SCSI_PROC_FS=y
+
+#
-+# IEEE 1394 (FireWire) support
++# SCSI support type (disk, tape, CD-ROM)
+#
-+# CONFIG_FIREWIRE is not set
-+# CONFIG_IEEE1394 is not set
-+# CONFIG_I2O is not set
++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
@@ -133917,14 +167297,13 @@
+# 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_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
@@ -133937,60 +167316,16 @@
+# 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
++# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
@@ -133998,8 +167333,6 @@
+# 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
@@ -134044,12 +167377,15 @@
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
-+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
-+# CONFIG_SERIAL_8250 is not set
++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
@@ -134057,29 +167393,54 @@
+# 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_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_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
++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
@@ -134090,23 +167451,63 @@
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
-+# CONFIG_SENSORS_I5K_AMB 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_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_VIA686A is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 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
++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
@@ -134129,10 +167530,8 @@
+#
+# Graphics support
+#
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
-+CONFIG_VIDEO_OUTPUT_CONTROL=y
++CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
@@ -134151,9 +167550,31 @@
+# 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_OHCI is not set
+CONFIG_USB_ARCH_HAS_EHCI=y
-+# CONFIG_USB 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_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'
@@ -134162,7 +167583,6 @@
+# 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
@@ -134244,16 +167664,19 @@
+# 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_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 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
@@ -134270,7 +167693,11 @@
+# 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_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
@@ -134301,41 +167728,14 @@
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
-+CONFIG_ENABLE_MUST_CHECK=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=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_KERNEL 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
+
+#
@@ -134344,30 +167744,36 @@
+# 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 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 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 is not set
-+# CONFIG_CRYPTO_PCBC 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 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
@@ -134385,41 +167791,39 @@
+# 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/mpc8568mds_defconfig b/arch/powerpc/configs/85xx/mpc8568mds_defconfig
+diff --git a/arch/powerpc/configs/83xx/sbc834x_defconfig b/arch/powerpc/configs/83xx/sbc834x_defconfig
new file mode 100644
-index 0000000..2b866b3
+index 0000000..1f15182
--- /dev/null
-+++ b/arch/powerpc/configs/85xx/mpc8568mds_defconfig
-@@ -0,0 +1,1117 @@
++++ b/arch/powerpc/configs/83xx/sbc834x_defconfig
+@@ -0,0 +1,828 @@
+#
+# Automatically generated make config: don't edit
-+# Linux kernel version: 2.6.25-rc7
-+# Mon Mar 31 11:37:05 2008
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:38 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
-+# CONFIG_6xx is not set
-+CONFIG_PPC_85xx=y
++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_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_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
@@ -134472,7 +167876,7 @@
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
-+# CONFIG_FAIR_GROUP_SCHED is not set
++CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
@@ -134501,9 +167905,8 @@
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
-+CONFIG_SLUB_DEBUG=y
-+# CONFIG_SLAB is not set
-+CONFIG_SLUB=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
@@ -134544,26 +167947,28 @@
+#
+# 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_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_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
@@ -134573,17 +167978,15 @@
+# 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_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
@@ -134596,7 +167999,6 @@
+# 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
@@ -134626,19 +168028,14 @@
+# 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_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
-+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
@@ -134666,7 +168063,7 @@
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+# CONFIG_XFRM_USER is not set
++CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
@@ -134751,8 +168148,6 @@
+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
@@ -134760,15 +168155,10 @@
+# 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
@@ -134776,10 +168166,7 @@
+# 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
@@ -134788,86 +168175,11 @@
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
-+CONFIG_SCSI=y
-+CONFIG_SCSI_DMA=y
-+# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA 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
@@ -134877,75 +168189,35 @@
+# 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_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_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_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
++# CONFIG_GFAR_NAPI is not set
++# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
@@ -134953,11 +168225,8 @@
+# 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
@@ -135000,18 +168269,15 @@
+#
+# 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
@@ -135019,21 +168285,18 @@
+# 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_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
-+# CONFIG_GEN_RTC 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
@@ -135048,29 +168311,12 @@
+#
+# 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
@@ -135108,7 +168354,6 @@
+# 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
@@ -135130,16 +168375,13 @@
+# 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
@@ -135157,13 +168399,7 @@
+# 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
++CONFIG_83xx_WDT=y
+
+#
+# Sonics Silicon Backplane
@@ -135181,15 +168417,13 @@
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
-+CONFIG_DAB=y
++# 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_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
@@ -135206,70 +168440,12 @@
+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_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_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_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+
+#
@@ -135280,16 +168456,9 @@
+#
+# 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_EXT2_FS is not set
++# CONFIG_EXT3_FS 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
@@ -135372,20 +168541,8 @@
+#
+# 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_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
@@ -135414,49 +168571,10 @@
+# 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_KERNEL 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
++# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
@@ -135510,20 +168628,18 @@
+# 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_CRYPTO_HW 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
+diff --git a/arch/powerpc/configs/85xx/ksi8560_defconfig b/arch/powerpc/configs/85xx/ksi8560_defconfig
new file mode 100644
-index 0000000..53aa6f3
+index 0000000..2d0debc
--- /dev/null
-+++ b/arch/powerpc/configs/85xx/mpc8572_ds_defconfig
-@@ -0,0 +1,1549 @@
++++ b/arch/powerpc/configs/85xx/ksi8560_defconfig
+@@ -0,0 +1,899 @@
+#
+# Automatically generated make config: don't edit
-+# Linux kernel version: 2.6.25-rc7
-+# Mon Mar 31 11:37:06 2008
++# Linux kernel version: 2.6.24
++# Mon Feb 11 16:25:19 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -135587,25 +168703,20 @@
+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_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
-+CONFIG_AUDIT=y
-+# CONFIG_AUDITSYSCALL is not set
-+CONFIG_IKCONFIG=y
-+CONFIG_IKCONFIG_PROC=y
++# 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_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_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_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
@@ -135613,13 +168724,12 @@
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
-+CONFIG_KALLSYMS_ALL=y
-+CONFIG_KALLSYMS_EXTRA_PASS=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
@@ -135636,22 +168746,15 @@
+# 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_MODULES is not set
+CONFIG_BLOCK=y
-+CONFIG_LBD=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
@@ -135663,12 +168766,13 @@
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
-+# CONFIG_DEFAULT_AS is not set
++CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
-+CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
-+CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
+
+#
+# Platform support
@@ -135683,7 +168787,8 @@
+# CONFIG_MPC8560_ADS is not set
+# CONFIG_MPC85xx_CDS is not set
+# CONFIG_MPC85xx_MDS is not set
-+CONFIG_MPC85xx_DS=y
++# 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
@@ -135694,7 +168799,7 @@
+# CONFIG_IPIC is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
-+CONFIG_PPC_I8259=y
++# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
@@ -135702,16 +168807,18 @@
+# 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
++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=y
-+CONFIG_NO_HZ=y
-+CONFIG_HIGH_RES_TIMERS=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
@@ -135722,13 +168829,12 @@
+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=m
++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
@@ -135744,30 +168850,23 @@
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
-+CONFIG_PROC_DEVICETREE=y
++# CONFIG_PROC_DEVICETREE is not set
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
-+CONFIG_SECCOMP=y
++# CONFIG_SECCOMP is not set
++CONFIG_WANT_DEVICE_TREE=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_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
-+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
@@ -135795,41 +168894,32 @@
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+CONFIG_XFRM_USER=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=m
-+# CONFIG_NET_KEY_MIGRATE is not set
++# CONFIG_NET_KEY 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_ADVANCED_ROUTER 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_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=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_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
@@ -135837,32 +168927,13 @@
+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_IPV6 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_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
@@ -135886,7 +168957,6 @@
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
-+CONFIG_FIB_RULES=y
+
+#
+# Wireless
@@ -135908,94 +168978,1849 @@
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
-+CONFIG_FW_LOADER=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_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_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_NBD 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_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_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
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++CONFIG_BLK_DEV_IDE=y
+
+#
-+# SCSI device support
++# Please see Documentation/ide.txt for help/info on IDE drives
+#
-+# 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
++# 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
+
+#
-+# SCSI support type (disk, tape, CD-ROM)
++# IDE chipset support/bugfixes
+#
-+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
++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
+
+#
-+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++# SCSI device support
+#
-+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
++# 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
+
+#
-+# SCSI Transports
++# MII PHY device drivers
+#
-+# 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_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
@@ -136777,7 +171602,19 @@
+#
+# on-CPU RTC drivers
+#
-+# CONFIG_DMADEVICES is not set
++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
@@ -136969,6 +171806,7 @@
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
@@ -137069,16 +171907,16 @@
+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
+diff --git a/arch/powerpc/configs/85xx/mpc8560_ads_defconfig b/arch/powerpc/configs/85xx/mpc8560_ads_defconfig
new file mode 100644
-index 0000000..a469fe9
+index 0000000..851ac91
--- /dev/null
-+++ b/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig
-@@ -0,0 +1,935 @@
++++ 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:30 2008
++# Mon Mar 24 08:48:27 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -137226,8 +172064,8 @@
+# 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_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
@@ -137240,7 +172078,7 @@
+# CONFIG_IPIC is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
-+CONFIG_PPC_I8259=y
++# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
@@ -137248,16 +172086,18 @@
+# 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_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=y
-+CONFIG_NO_HZ=y
-+CONFIG_HIGH_RES_TIMERS=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
@@ -137290,7 +172130,7 @@
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
-+CONFIG_PROC_DEVICETREE=y
++# CONFIG_PROC_DEVICETREE is not set
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+# CONFIG_SECCOMP is not set
@@ -137310,7 +172150,7 @@
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY=y
-+# CONFIG_PCI_DEBUG is not set
++CONFIG_PCI_DEBUG=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+
@@ -137340,7 +172180,7 @@
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+CONFIG_XFRM_USER=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
@@ -137456,66 +172296,7 @@
+# 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
++# CONFIG_IDE is not set
+
+#
+# SCSI device support
@@ -137549,8 +172330,8 @@
+#
+# MII PHY device drivers
+#
-+# CONFIG_MARVELL_PHY is not set
-+# CONFIG_DAVICOM_PHY is not set
++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
@@ -137575,6 +172356,10 @@
+# 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
@@ -137671,13 +172456,7 @@
+#
+# 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
++# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
@@ -137685,13 +172464,20 @@
+# 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_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_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
@@ -137955,6 +172741,7 @@
+# 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
+
@@ -138010,16 +172797,17 @@
+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
++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..67f6797
+index 0000000..2b866b3
--- /dev/null
-+++ b/arch/powerpc/configs/85xx/sbc8548_defconfig
-@@ -0,0 +1,812 @@
++++ b/arch/powerpc/configs/85xx/mpc8568mds_defconfig
+@@ -0,0 +1,1117 @@
+#
+# Automatically generated make config: don't edit
-+# Linux kernel version: 2.6.25-rc6
-+# Mon Mar 24 08:48:39 2008
++# Linux kernel version: 2.6.25-rc7
++# Mon Mar 31 11:37:05 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -138091,7 +172879,7 @@
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
-+CONFIG_FAIR_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
@@ -138105,8 +172893,7 @@
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
-+CONFIG_KALLSYMS=y
-+# CONFIG_KALLSYMS_EXTRA_PASS is not set
++# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
@@ -138115,14 +172902,15 @@
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
-+CONFIG_EPOLL=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_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
@@ -138134,7 +172922,12 @@
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
-+# CONFIG_MODULES is not set
++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
@@ -138167,14 +172960,14 @@
+# 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_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=y
++# CONFIG_SBC8548 is not set
+# CONFIG_SBC8560 is not set
+# CONFIG_IPIC is not set
+CONFIG_MPIC=y
@@ -138187,6 +172980,7 @@
+# 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
+
@@ -138194,9 +172988,9 @@
+# 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_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
@@ -138208,7 +173002,7 @@
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
-+CONFIG_BINFMT_MISC=y
++# CONFIG_BINFMT_MISC is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
@@ -138232,7 +173026,7 @@
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
-+# CONFIG_SECCOMP is not set
++CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
@@ -138249,6 +173043,7 @@
+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
+
@@ -138278,7 +173073,7 @@
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+CONFIG_XFRM_USER=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
@@ -138363,6 +173158,8 @@
+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
@@ -138381,7 +173178,7 @@
+# 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_RAM_SIZE=32768
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
@@ -138398,9 +173195,76 @@
+# 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_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
@@ -138426,14 +173290,14 @@
+#
+# MII PHY device drivers
+#
-+# CONFIG_MARVELL_PHY is not set
++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=y
++# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
@@ -138473,6 +173337,7 @@
+# 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
@@ -138499,6 +173364,7 @@
+# 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
@@ -138562,20 +173428,72 @@
+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 is not set
++CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
-+CONFIG_GEN_RTC=y
-+# CONFIG_GEN_RTC_X 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
++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
@@ -138586,23 +173504,73 @@
+# 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_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_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
++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
@@ -138628,7 +173596,7 @@
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
-+CONFIG_VIDEO_OUTPUT_CONTROL=y
++CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
@@ -138641,14 +173609,74 @@
+# Sound
+#
+# CONFIG_SOUND is not set
-+# CONFIG_HID_SUPPORT is not set
-+# CONFIG_USB_SUPPORT 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_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
+
+#
@@ -138659,9 +173687,16 @@
+#
+# File systems
+#
-+# CONFIG_EXT2_FS is not set
-+# CONFIG_EXT3_FS is not set
++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
@@ -138721,16 +173756,19 @@
+# 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_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 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
@@ -138741,8 +173779,20 @@
+#
+# Partition Types
+#
-+# CONFIG_PARTITION_ADVANCED is not set
-+CONFIG_MSDOS_PARTITION=y
++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
+
@@ -138771,10 +173821,49 @@
+# 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_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_PPC_EARLY_DEBUG 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
@@ -138783,29 +173872,31 @@
+# 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 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 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 is not set
-+# CONFIG_CRYPTO_PCBC 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 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
@@ -138823,21 +173914,23 @@
+# 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/sbc8560_defconfig b/arch/powerpc/configs/85xx/sbc8560_defconfig
++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..fef6055
+index 0000000..53aa6f3
--- /dev/null
-+++ b/arch/powerpc/configs/85xx/sbc8560_defconfig
-@@ -0,0 +1,830 @@
++++ 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-rc6
-+# Mon Mar 24 08:48:39 2008
++# Linux kernel version: 2.6.25-rc7
++# Mon Mar 31 11:37:06 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -138901,15 +173994,18 @@
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
-+# CONFIG_POSIX_MQUEUE is not set
-+# CONFIG_BSD_PROCESS_ACCT is not set
++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_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=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
@@ -138924,8 +174020,8 @@
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
-+# CONFIG_KALLSYMS_ALL is not set
-+# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
@@ -138940,12 +174036,14 @@
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
-+CONFIG_SLAB=y
-+# CONFIG_SLUB is not set
++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
@@ -138953,9 +174051,14 @@
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
-+# CONFIG_MODULES is not set
++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 is not set
++CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
@@ -138967,11 +174070,11 @@
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
-+CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
-+# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
-+CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+
+#
@@ -138987,18 +174090,18 @@
+# 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_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=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_I8259=y
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
@@ -139007,15 +174110,15 @@
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
-+# CONFIG_FSL_ULI1575 is not set
++CONFIG_FSL_ULI1575=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_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
@@ -139027,8 +174130,8 @@
+# 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_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
@@ -139051,19 +174154,27 @@
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
-+# CONFIG_SECCOMP 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_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
@@ -139095,28 +174206,37 @@
+# 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_NET_KEY=m
++# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
-+# CONFIG_IP_ADVANCED_ROUTER is not set
++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 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_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 is not set
-+CONFIG_INET_XFRM_MODE_TRANSPORT=y
-+CONFIG_INET_XFRM_MODE_TUNNEL=y
-+CONFIG_INET_XFRM_MODE_BEET=y
++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
@@ -139124,13 +174244,32 @@
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
-+# CONFIG_IPV6 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 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
@@ -139154,6 +174293,7 @@
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
++CONFIG_FIB_RULES=y
+
+#
+# Wireless
@@ -139175,7 +174315,7 @@
+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
@@ -139185,18 +174325,27 @@
+# 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_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=32768
++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
@@ -139205,20 +174354,155 @@
+# 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=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 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
+
+#
@@ -139229,34 +174513,84 @@
+# 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_VITESSE_PHY=y
+# CONFIG_SMSC_PHY is not set
-+CONFIG_BROADCOM_PHY=y
++# 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
@@ -139291,24 +174625,37 @@
+#
+# Hardware I/O ports
+#
-+# CONFIG_SERIO is not set
++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 is not set
++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 is not set
++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
@@ -139316,18 +174663,74 @@
+# 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_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_I2C 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
@@ -139336,19 +174739,7 @@
+# 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_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
@@ -139367,12 +174758,122 @@
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
-+# CONFIG_DVB_CORE 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
@@ -139384,25 +174885,255 @@
+# 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_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 is not set
-+# CONFIG_USB_ARCH_HAS_OHCI is not set
-+# CONFIG_USB_ARCH_HAS_EHCI is not set
++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
@@ -139420,19 +175151,34 @@
+# 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 is not set
++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=y
++# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
@@ -139448,9 +175194,16 @@
+#
+# File systems
+#
-+# CONFIG_EXT2_FS is not set
-+# CONFIG_EXT3_FS is not set
++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
@@ -139468,15 +175221,23 @@
+#
+# CD-ROM/DVD Filesystems
+#
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_UDF_FS is not set
++CONFIG_ISO9660_FS=m
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_UDF_FS=m
++CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
-+# CONFIG_MSDOS_FS is not set
-+# CONFIG_VFAT_FS is not set
-+# CONFIG_NTFS_FS is not set
++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
@@ -139493,33 +175254,43 @@
+#
+# 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_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 is not set
-+# CONFIG_QNX4FS_FS is not set
++CONFIG_HPFS_FS=m
++CONFIG_QNX4FS_FS=m
+# CONFIG_ROMFS_FS is not set
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UFS_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 is not set
-+# CONFIG_NFS_V4 is not set
++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_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 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
@@ -139535,8 +175306,12 @@
+# 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_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
@@ -139544,7 +175319,46 @@
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
-+# CONFIG_NLS 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
+
+#
@@ -139556,7 +175370,8 @@
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
-+# CONFIG_LIBCRC32C is not set
++CONFIG_LIBCRC32C=m
++CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
@@ -139568,7 +175383,7 @@
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
-+CONFIG_MAGIC_SYSRQ=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
@@ -139578,20 +175393,23 @@
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
-+# CONFIG_DEBUG_SLAB 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_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_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
@@ -139600,18 +175418,7 @@
+# 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
++# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
@@ -139620,29 +175427,32 @@
+# 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 is not set
-+# CONFIG_CRYPTO_HMAC 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 is not set
-+# CONFIG_CRYPTO_SHA1 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 is not set
-+# CONFIG_CRYPTO_PCBC 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 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
@@ -139660,20 +175470,22 @@
+# 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/stx_gp3_defconfig b/arch/powerpc/configs/85xx/stx_gp3_defconfig
+diff --git a/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig b/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig
new file mode 100644
-index 0000000..1d303c4
+index 0000000..a469fe9
--- /dev/null
-+++ b/arch/powerpc/configs/85xx/stx_gp3_defconfig
-@@ -0,0 +1,1253 @@
++++ 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:42 2008
++# Mon Mar 24 08:48:30 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -139745,7 +175557,7 @@
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
-+CONFIG_FAIR_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
@@ -139783,7 +175595,6 @@
+# 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
@@ -139791,11 +175602,7 @@
+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_MODULES is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
@@ -139809,11 +175616,11 @@
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
-+# CONFIG_DEFAULT_AS is not set
++CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
-+CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
-+CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+
+#
@@ -139827,10 +175634,10 @@
+CONFIG_MPC85xx=y
+# CONFIG_MPC8540_ADS is not set
+# CONFIG_MPC8560_ADS is not set
-+# CONFIG_MPC85xx_CDS is not set
++CONFIG_MPC85xx_CDS=y
+# CONFIG_MPC85xx_MDS is not set
+# CONFIG_MPC85xx_DS is not set
-+CONFIG_STX_GP3=y
++# CONFIG_STX_GP3 is not set
+# CONFIG_TQM8540 is not set
+# CONFIG_TQM8541 is not set
+# CONFIG_TQM8555 is not set
@@ -139840,7 +175647,7 @@
+# CONFIG_IPIC is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
-+# CONFIG_PPC_I8259 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
@@ -139848,18 +175655,16 @@
+# 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_CPM2 is not set
+# 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_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
@@ -139871,7 +175676,7 @@
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
-+CONFIG_BINFMT_MISC=m
++CONFIG_BINFMT_MISC=y
+CONFIG_MATH_EMULATION=y
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
@@ -139895,7 +175700,7 @@
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
-+CONFIG_SECCOMP=y
++# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
@@ -139942,23 +175747,24 @@
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+# CONFIG_XFRM_USER is not set
++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 is not set
++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_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_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
@@ -139974,69 +175780,11 @@
+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_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
@@ -140056,7 +175804,7 @@
+#
+# Network testing
+#
-+CONFIG_NET_PKTGEN=y
++# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
@@ -140090,24 +175838,17 @@
+# 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_PARPORT 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_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-+CONFIG_BLK_DEV_NBD=m
++# 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
@@ -140130,13 +175871,11 @@
+# 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_BLK_DEV_IDEDISK is not set
+# CONFIG_IDEDISK_MULTI_MODE is not set
-+CONFIG_BLK_DEV_IDECD=m
-+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
++# CONFIG_BLK_DEV_IDECD is not set
+# 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
+
@@ -140145,12 +175884,17 @@
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_PLATFORM is not set
++CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+#
+# PCI IDE chipsets support
+#
-+# CONFIG_BLK_DEV_GENERIC is not set
++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
@@ -140174,9 +175918,9 @@
+# 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_VIA82CXXX=y
+# CONFIG_BLK_DEV_TC86C001 is not set
-+# CONFIG_BLK_DEV_IDEDMA is not set
++CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+# CONFIG_BLK_DEV_HD is not set
+
@@ -140184,79 +175928,9 @@
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
-+CONFIG_SCSI=m
-+CONFIG_SCSI_DMA=y
-+# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA 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
@@ -140282,7 +175956,7 @@
+#
+# MII PHY device drivers
+#
-+CONFIG_MARVELL_PHY=y
++# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
@@ -140295,7 +175969,7 @@
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
-+# CONFIG_MII is not set
++CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
@@ -140308,12 +175982,12 @@
+# 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_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
@@ -140355,10 +176029,8 @@
+# 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
@@ -140375,35 +176047,16 @@
+#
+# 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_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=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_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
@@ -140412,13 +176065,7 @@
+#
+# 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_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
@@ -140431,7 +176078,13 @@
+#
+# Serial drivers
+#
-+# CONFIG_SERIAL_8250 is not set
++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
@@ -140439,84 +176092,22 @@
+# 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_SERIAL_OF_PLATFORM 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_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
-+# CONFIG_GEN_RTC 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=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
++# CONFIG_I2C is not set
+
+#
+# SPI support
@@ -140527,55 +176118,18 @@
+# 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
@@ -140603,17 +176157,10 @@
+#
+# 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_AGP is not set
++# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
-+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
@@ -140625,17 +176172,7 @@
+#
+# Sound
+#
-+CONFIG_SOUND=m
-+
-+#
-+# Advanced Linux Sound Architecture
-+#
-+# CONFIG_SND is not set
-+
-+#
-+# Open Sound System
-+#
-+# CONFIG_SOUND_PRIME is not set
++# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
@@ -140657,7 +176194,6 @@
+# CONFIG_EDAC is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
-+# CONFIG_AUXDISPLAY is not set
+
+#
+# Userspace I/O
@@ -140687,34 +176223,28 @@
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
-+CONFIG_AUTOFS_FS=m
-+CONFIG_AUTOFS4_FS=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
-+CONFIG_ISO9660_FS=m
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+CONFIG_UDF_FS=m
-+CONFIG_UDF_NLS=y
++# 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_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_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
@@ -140732,7 +176262,7 @@
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
-+CONFIG_CRAMFS=m
++# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
@@ -140742,21 +176272,18 @@
+# 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_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_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_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
@@ -140765,61 +176292,33 @@
+#
+# 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_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=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=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
@@ -140846,18 +176345,16 @@
+# 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_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_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
@@ -140865,8 +176362,7 @@
+# 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_BDI_SWITCH is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
@@ -140916,23 +176412,21 @@
+# 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
+diff --git a/arch/powerpc/configs/85xx/sbc8548_defconfig b/arch/powerpc/configs/85xx/sbc8548_defconfig
new file mode 100644
-index 0000000..d39ee3b
+index 0000000..67f6797
--- /dev/null
-+++ b/arch/powerpc/configs/85xx/tqm8540_defconfig
-@@ -0,0 +1,1097 @@
++++ 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:43 2008
++# Mon Mar 24 08:48:39 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -141018,8 +176512,9 @@
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
-+# CONFIG_KALLSYMS is not set
-+# CONFIG_HOTPLUG is not set
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
@@ -141027,15 +176522,14 @@
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
-+# CONFIG_EPOLL is not set
++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_SLAB=y
++# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
@@ -141083,13 +176577,12 @@
+# CONFIG_MPC85xx_MDS is not set
+# CONFIG_MPC85xx_DS is not set
+# CONFIG_STX_GP3 is not set
-+CONFIG_TQM8540=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_SBC8548=y
+# CONFIG_SBC8560 is not set
-+CONFIG_TQM85xx=y
+# CONFIG_IPIC is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
@@ -141102,7 +176595,6 @@
+# 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
+
+#
@@ -141123,7 +176615,7 @@
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_MISC is not set
++CONFIG_BINFMT_MISC=y
+CONFIG_MATH_EMULATION=y
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
@@ -141144,10 +176636,10 @@
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
-+# CONFIG_PROC_DEVICETREE is not set
++CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
-+CONFIG_SECCOMP=y
++# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
@@ -141164,6 +176656,8 @@
+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
@@ -141191,7 +176685,7 @@
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+# CONFIG_XFRM_USER is not set
++CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
@@ -141272,87 +176766,13 @@
+#
+# 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=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_MTD is not set
+CONFIG_OF_DEVICE=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
@@ -141368,7 +176788,7 @@
+# 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_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
@@ -141379,66 +176799,7 @@
+# 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
++# CONFIG_IDE is not set
+
+#
+# SCSI device support
@@ -141479,7 +176840,7 @@
+# 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_BROADCOM_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
@@ -141496,26 +176857,8 @@
+# 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_NET_PCI 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
@@ -141630,7 +176973,7 @@
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
-+CONFIG_HW_RANDOM=y
++# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
@@ -141639,58 +176982,7 @@
+# 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
++# CONFIG_I2C is not set
+
+#
+# SPI support
@@ -141701,58 +176993,21 @@
+# 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_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
@@ -141780,7 +177035,7 @@
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
-+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
@@ -141793,20 +177048,8 @@
+# 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_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
@@ -141823,16 +177066,9 @@
+#
+# 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_EXT2_FS is not set
++# CONFIG_EXT3_FS 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
@@ -141882,18 +177118,7 @@
+# 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_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
@@ -141923,20 +177148,8 @@
+#
+# 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_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
@@ -141950,8 +177163,6 @@
+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
@@ -141968,8 +177179,6 @@
+# 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
@@ -142026,16 +177235,16 @@
+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
+diff --git a/arch/powerpc/configs/85xx/sbc8560_defconfig b/arch/powerpc/configs/85xx/sbc8560_defconfig
new file mode 100644
-index 0000000..cbf6ad2
+index 0000000..fef6055
--- /dev/null
-+++ b/arch/powerpc/configs/85xx/tqm8541_defconfig
-@@ -0,0 +1,1109 @@
++++ 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:44 2008
++# Mon Mar 24 08:48:39 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -142121,8 +177330,10 @@
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
-+# CONFIG_KALLSYMS is not set
-+# CONFIG_HOTPLUG 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
@@ -142130,15 +177341,14 @@
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
-+# CONFIG_EPOLL is not set
++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_SLAB=y
++# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
@@ -142187,12 +177397,11 @@
+# CONFIG_MPC85xx_DS is not set
+# CONFIG_STX_GP3 is not set
+# CONFIG_TQM8540 is not set
-+CONFIG_TQM8541=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_SBC8560=y
+# CONFIG_IPIC is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
@@ -142204,10 +177413,8 @@
+# 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_CPM2 is not set
+# CONFIG_FSL_ULI1575 is not set
-+CONFIG_CPM=y
+
+#
+# Kernel options
@@ -142227,8 +177434,8 @@
+# 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_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
@@ -142248,26 +177455,22 @@
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
-+# CONFIG_PROC_DEVICETREE is not set
++CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
-+CONFIG_SECCOMP=y
++# 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 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
@@ -142295,7 +177498,7 @@
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+# CONFIG_XFRM_USER is not set
++CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
@@ -142376,99 +177579,942 @@
+#
+# 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_OF_PARTS 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
+
+#
-+# User Modules And Translation Layers
++# SCSI device support
+#
-+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
++# 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
+
+#
-+# RAM/ROM/Flash chip drivers
++# MII PHY device 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
++# 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
+
+#
-+# Mapping drivers for chip access
++# Wireless LAN
+#
-+# 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
++# 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
+
+#
-+# Self-contained MTD device drivers
++# Input device support
+#
-+# 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
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
+
+#
-+# Disk-On-Chip Device Drivers
++# Userland interfaces
+#
-+# 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
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
+
+#
-+# UBI - Unsorted block images
++# Input Device Drivers
+#
-+# CONFIG_MTD_UBI is not set
++# 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 is not set
++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=y
++CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-+# CONFIG_BLK_DEV_NBD 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
@@ -142493,9 +178539,11 @@
+# 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_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
+
@@ -142504,17 +178552,12 @@
+#
+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_GENERIC is not set
+# 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
@@ -142538,9 +178581,9 @@
+# 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_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
-+CONFIG_BLK_DEV_IDEDMA=y
++# CONFIG_BLK_DEV_IDEDMA is not set
+CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+# CONFIG_BLK_DEV_HD is not set
+
@@ -142548,9 +178591,79 @@
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
-+# CONFIG_SCSI is not set
-+# CONFIG_SCSI_DMA 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
@@ -142576,7 +178689,7 @@
+#
+# MII PHY device drivers
+#
-+# CONFIG_MARVELL_PHY is not set
++CONFIG_MARVELL_PHY=y
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
@@ -142589,7 +178702,7 @@
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
-+CONFIG_MII=y
++# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
@@ -142600,26 +178713,9 @@
+# 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_NET_PCI 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_NET_POCKET is not set
+# CONFIG_FS_ENET is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
@@ -142666,8 +178762,10 @@
+# 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
@@ -142684,16 +178782,35 @@
+#
+# Userland interfaces
+#
-+# CONFIG_INPUT_MOUSEDEV is not set
-+# CONFIG_INPUT_JOYDEV is not set
-+# CONFIG_INPUT_EVDEV is not set
++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 is not set
-+# CONFIG_INPUT_MOUSE is not set
++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
@@ -142702,7 +178819,13 @@
+#
+# Hardware I/O ports
+#
-+# CONFIG_SERIO is not set
++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
+
+#
@@ -142715,13 +178838,7 @@
+#
+# 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
++# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
@@ -142731,35 +178848,36 @@
+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_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_SERIAL_OF_PLATFORM 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=y
++CONFIG_HW_RANDOM=m
+# CONFIG_NVRAM is not set
-+CONFIG_GEN_RTC=y
-+# CONFIG_GEN_RTC_X 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=m
+CONFIG_I2C_BOARDINFO=y
-+CONFIG_I2C_CHARDEV=y
++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
+
@@ -142774,9 +178892,10 @@
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
-+CONFIG_I2C_MPC=y
++# 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
@@ -142785,6 +178904,7 @@
+# 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
@@ -142833,7 +178953,7 @@
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
-+CONFIG_SENSORS_LM75=y
++# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
@@ -142865,7 +178985,7 @@
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
-+CONFIG_HWMON_DEBUG_CHIP=y
++# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
@@ -142890,8 +179010,15 @@
+#
+# Graphics support
+#
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
++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
@@ -142905,7 +179032,17 @@
+#
+# Sound
+#
-+# CONFIG_SOUND is not set
++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
@@ -142927,6 +179064,7 @@
+# CONFIG_EDAC is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
++# CONFIG_AUXDISPLAY is not set
+
+#
+# Userspace I/O
@@ -142956,28 +179094,34 @@
+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_AUTOFS_FS=m
++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
++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_MSDOS_FS is not set
-+# CONFIG_VFAT_FS is not set
++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=y
++# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
@@ -142995,18 +179139,7 @@
+# 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_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
@@ -143016,18 +179149,21 @@
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
-+# CONFIG_NFS_V3 is not set
++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_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
@@ -143036,35 +179172,61 @@
+#
+# 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_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 is not set
++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_ZLIB_INFLATE=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
@@ -143080,12 +179242,38 @@
+# 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_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
+
+#
@@ -143135,22 +179323,23 @@
+# 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/tqm8555_defconfig b/arch/powerpc/configs/85xx/tqm8555_defconfig
+diff --git a/arch/powerpc/configs/85xx/tqm8540_defconfig b/arch/powerpc/configs/85xx/tqm8540_defconfig
new file mode 100644
-index 0000000..bbff962
+index 0000000..d39ee3b
--- /dev/null
-+++ b/arch/powerpc/configs/85xx/tqm8555_defconfig
-@@ -0,0 +1,1109 @@
++++ 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:44 2008
++# Mon Mar 24 08:48:43 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -143301,9 +179490,9 @@
+# CONFIG_MPC85xx_MDS is not set
+# CONFIG_MPC85xx_DS is not set
+# CONFIG_STX_GP3 is not set
-+# CONFIG_TQM8540 is not set
++CONFIG_TQM8540=y
+# CONFIG_TQM8541 is not set
-+CONFIG_TQM8555=y
++# CONFIG_TQM8555 is not set
+# CONFIG_TQM8560 is not set
+# CONFIG_SBC8548 is not set
+# CONFIG_SBC8560 is not set
@@ -143319,10 +179508,9 @@
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
-+CONFIG_CPM2=y
++# CONFIG_CPM2 is not set
+CONFIG_PPC_CPM_NEW_BINDING=y
+# CONFIG_FSL_ULI1575 is not set
-+CONFIG_CPM=y
+
+#
+# Kernel options
@@ -143735,7 +179923,6 @@
+# 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
@@ -143844,14 +180031,6 @@
+# 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
@@ -144200,7 +180379,6 @@
+# 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
+
+#
@@ -144255,17 +180433,16 @@
+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
+diff --git a/arch/powerpc/configs/85xx/tqm8541_defconfig b/arch/powerpc/configs/85xx/tqm8541_defconfig
new file mode 100644
-index 0000000..63c5ec8
+index 0000000..cbf6ad2
--- /dev/null
-+++ b/arch/powerpc/configs/85xx/tqm8560_defconfig
++++ 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:45 2008
++# Mon Mar 24 08:48:44 2008
+#
+# CONFIG_PPC64 is not set
+
@@ -144417,9 +180594,9 @@
+# CONFIG_MPC85xx_DS is not set
+# CONFIG_STX_GP3 is not set
+# CONFIG_TQM8540 is not set
-+# CONFIG_TQM8541 is not set
++CONFIG_TQM8541=y
+# CONFIG_TQM8555 is not set
-+CONFIG_TQM8560=y
++# CONFIG_TQM8560 is not set
+# CONFIG_SBC8548 is not set
+# CONFIG_SBC8560 is not set
+CONFIG_TQM85xx=y
@@ -145371,630 +181548,2860 @@
+# 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
+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
@@ -148110,7 +186517,7 @@
-# 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
+index 0f82f66..88338a9 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -1,7 +1,7 @@
@@ -148140,7 +186547,15 @@
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
-@@ -1596,6 +1594,7 @@ CONFIG_PLIST=y
+@@ -698,6 +696,7 @@ CONFIG_WINDFARM=y
+ CONFIG_WINDFARM_PM81=y
+ CONFIG_WINDFARM_PM91=y
+ CONFIG_WINDFARM_PM112=y
++CONFIG_WINDFARM_PM121=y
+ # CONFIG_PMAC_RACKMETER is not set
+ CONFIG_NETDEVICES=y
+ # CONFIG_NETDEVICES_MULTIQUEUE is not set
+@@ -1596,6 +1595,7 @@ CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
@@ -184956,7 +223371,7 @@
-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
+index c1baf9d..d14cebf 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -12,7 +12,7 @@ CFLAGS_prom_init.o += -fPIC
@@ -184968,7 +223383,7 @@
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
+@@ -67,12 +67,12 @@ 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
@@ -184976,7 +223391,13 @@
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
+ pci-common.o
+ obj-$(CONFIG_PCI_MSI) += msi.o
+-obj-$(CONFIG_RAPIDIO) += rio.o
+ obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o \
+ machine_kexec_$(CONFIG_WORD_SIZE).o
+ obj-$(CONFIG_AUDIT) += audit.o
+@@ -105,4 +105,13 @@ PHONY += systbl_chk
systbl_chk: $(src)/systbl_chk.sh $(obj)/systbl_chk.i
$(call cmd,systbl_chk)
@@ -184991,29 +223412,42 @@
+
clean-files := vmlinux.lds
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
-index 4b749c4..adf1d09 100644
+index 4b749c4..ec9228d 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
-@@ -26,8 +26,6 @@
+@@ -23,12 +23,14 @@
+ #include <linux/mm.h>
+ #include <linux/suspend.h>
+ #include <linux/hrtimer.h>
++#ifdef CONFIG_KVM
++#include <linux/kvm_host.h>
++#endif
#ifdef CONFIG_PPC64
#include <linux/time.h>
#include <linux/hardirq.h>
-#else
-#include <linux/ptrace.h>
#endif
++#include <linux/kbuild.h>
#include <asm/io.h>
-@@ -46,6 +44,9 @@
+ #include <asm/page.h>
+@@ -46,11 +48,9 @@
#include <asm/mmu.h>
#include <asm/hvcall.h>
#endif
+-
+-#define DEFINE(sym, val) \
+- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+-
+-#define BLANK() asm volatile("\n->" : : )
+#ifdef CONFIG_PPC_ISERIES
+#include <asm/iseries/alpaca.h>
+#endif
- #define DEFINE(sym, val) \
- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-@@ -60,7 +61,6 @@ int main(void)
+ int main(void)
+ {
+@@ -60,10 +60,10 @@ int main(void)
DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context));
#else
DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
@@ -185021,6 +223455,10 @@
#endif /* CONFIG_PPC64 */
DEFINE(KSP, offsetof(struct thread_struct, ksp));
++ DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit));
+ DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
+ DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
+ DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
@@ -80,7 +80,6 @@ int main(void)
DEFINE(PGDIR, offsetof(struct thread_struct, pgdir));
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
@@ -185056,7 +223494,7 @@
/* 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)
+@@ -325,9 +317,37 @@ 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));
@@ -185066,6 +223504,34 @@
#endif
DEFINE(PGD_TABLE_SIZE, PGD_TABLE_SIZE);
+
++#ifdef CONFIG_KVM
++ DEFINE(TLBE_BYTES, sizeof(struct tlbe));
++
++ DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack));
++ DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid));
++ DEFINE(VCPU_HOST_TLB, offsetof(struct kvm_vcpu, arch.host_tlb));
++ DEFINE(VCPU_SHADOW_TLB, offsetof(struct kvm_vcpu, arch.shadow_tlb));
++ DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
++ DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
++ DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
++ DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
++ DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
++ DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc));
++ DEFINE(VCPU_MSR, offsetof(struct kvm_vcpu, arch.msr));
++ DEFINE(VCPU_SPRG4, offsetof(struct kvm_vcpu, arch.sprg4));
++ DEFINE(VCPU_SPRG5, offsetof(struct kvm_vcpu, arch.sprg5));
++ DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6));
++ DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7));
++ DEFINE(VCPU_PID, offsetof(struct kvm_vcpu, arch.pid));
++
++ DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
++ DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear));
++ DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr));
++#endif
++
+ return 0;
+ }
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c
index 80e2eef..9f93777 100644
--- a/arch/powerpc/kernel/btext.c
@@ -185214,7 +223680,7 @@
#include <asm/uaccess.h>
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
-index 69a91bd..84c8686 100644
+index 69a91bd..0c8614d 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -110,9 +110,9 @@ transfer_to_handler:
@@ -185242,7 +223708,22 @@
lwz r12,0(r11)
mtspr SPRN_DBCR0,r12
lwz r12,4(r11)
-@@ -238,10 +244,10 @@ ret_from_syscall:
+@@ -131,11 +137,12 @@ transfer_to_handler:
+ 2: /* if from kernel, check interrupted DOZE/NAP mode and
+ * check for stack overflow
+ */
+- lwz r9,THREAD_INFO-THREAD(r12)
+- cmplw r1,r9 /* if r1 <= current->thread_info */
++ lwz r9,KSP_LIMIT(r12)
++ cmplw r1,r9 /* if r1 <= ksp_limit */
+ ble- stack_ovf /* then the kernel stack overflowed */
+ 5:
+ #ifdef CONFIG_6xx
++ rlwinm r9,r1,0,0,31-THREAD_SHIFT
+ tophys(r9,r9) /* check local flags */
+ lwz r12,TI_LOCAL_FLAGS(r9)
+ mtcrf 0x01,r12
+@@ -238,10 +245,10 @@ ret_from_syscall:
stw r11,_CCR(r1)
syscall_exit_cont:
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
@@ -185256,7 +223737,7 @@
bnel- load_dbcr0
#endif
#ifdef CONFIG_44x
-@@ -666,10 +672,10 @@ user_exc_return: /* r10 contains MSR_KERNEL here */
+@@ -666,10 +673,10 @@ user_exc_return: /* r10 contains MSR_KERNEL here */
restore_user:
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
@@ -185270,7 +223751,7 @@
bnel- load_dbcr0
#endif
-@@ -879,6 +885,12 @@ load_dbcr0:
+@@ -879,6 +886,12 @@ load_dbcr0:
mfspr r10,SPRN_DBCR0
lis r11,global_dbcr0 at ha
addi r11,r11,global_dbcr0 at l
@@ -185283,7 +223764,7 @@
stw r10,0(r11)
mtspr SPRN_DBCR0,r0
lwz r10,4(r11)
-@@ -891,7 +903,7 @@ load_dbcr0:
+@@ -891,7 +904,7 @@ load_dbcr0:
.section .bss
.align 4
global_dbcr0:
@@ -185445,7 +223926,7 @@
/*
* Local functions
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
-index d3aee08..215973a 100644
+index d3aee08..024805e 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -36,8 +36,7 @@
@@ -185458,7 +223939,32 @@
/*
* We layout physical memory as follows:
-@@ -450,8 +449,8 @@ bad_stack:
+@@ -240,6 +239,10 @@ instruction_access_slb_pSeries:
+ .globl system_call_pSeries
+ system_call_pSeries:
+ HMT_MEDIUM
++BEGIN_FTR_SECTION
++ cmpdi r0,0x1ebe
++ beq- 1f
++END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
+ mr r9,r13
+ mfmsr r10
+ mfspr r13,SPRN_SPRG3
+@@ -254,6 +257,13 @@ system_call_pSeries:
+ rfid
+ b . /* prevent speculative execution */
+
++/* Fast LE/BE switch system call */
++1: mfspr r12,SPRN_SRR1
++ xori r12,r12,MSR_LE
++ mtspr SPRN_SRR1,r12
++ rfid /* return to userspace */
++ b .
++
+ STD_EXCEPTION_PSERIES(0xd00, single_step)
+ STD_EXCEPTION_PSERIES(0xe00, trap_0e)
+
+@@ -450,8 +460,8 @@ bad_stack:
*/
fast_exc_return_irq: /* restores irq state too */
ld r3,SOFTE(r1)
@@ -185468,7 +223974,7 @@
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)
+@@ -621,7 +631,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
mtlr r10
andi. r10,r12,MSR_RI /* check for unrecoverable exception */
@@ -185477,7 +223983,7 @@
.machine push
.machine "power4"
-@@ -643,6 +642,22 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+@@ -643,6 +653,22 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
rfid
b . /* prevent speculative execution */
@@ -185500,7 +224006,7 @@
unrecov_slb:
EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
DISABLE_INTS
-@@ -808,7 +823,7 @@ _STATIC(load_up_altivec)
+@@ -808,7 +834,7 @@ _STATIC(load_up_altivec)
* Hash table stuff
*/
.align 7
@@ -185509,7 +224015,7 @@
std r3,_DAR(r1)
std r4,_DSISR(r1)
-@@ -820,6 +835,27 @@ BEGIN_FTR_SECTION
+@@ -820,6 +846,27 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
/*
@@ -185537,7 +224043,7 @@
* 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)
+@@ -832,13 +879,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
rlwimi r4,r5,22+2,31-2,31-2 /* Set _PAGE_EXEC if trap is 0x400 */
/*
@@ -185551,7 +224057,7 @@
* 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)
+@@ -848,7 +888,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
bl .hash_page /* build HPTE if possible */
cmpdi r3,0 /* see if hash_page succeeded */
@@ -185559,7 +224065,7 @@
BEGIN_FW_FTR_SECTION
/*
* If we had interrupts soft-enabled at the point where the
-@@ -860,7 +888,7 @@ BEGIN_FW_FTR_SECTION
+@@ -860,7 +899,7 @@ BEGIN_FW_FTR_SECTION
*/
beq 13f
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
@@ -185568,7 +224074,7 @@
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)
+@@ -874,11 +913,12 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
/*
* hash_page couldn't handle it, set soft interrupt enable back
@@ -185583,7 +224089,7 @@
b 11f
/* Here we have a page fault that hash_page can't handle. */
-@@ -1477,6 +1506,10 @@ _INIT_STATIC(start_here_multiplatform)
+@@ -1477,6 +1517,10 @@ _INIT_STATIC(start_here_multiplatform)
addi r2,r2,0x4000
add r2,r2,r26
@@ -185594,7 +224100,7 @@
/* 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)
+@@ -1505,10 +1549,6 @@ _INIT_GLOBAL(start_here_common)
li r0,0
stdu r0,-STACK_FRAME_OVERHEAD(r1)
@@ -185883,7 +224389,7 @@
}
}
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
-index 292163f..425616f 100644
+index 292163f..2f73f70 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)
@@ -185903,7 +224409,12 @@
#endif /* CONFIG_PPC64 */
int show_interrupts(struct seq_file *p, void *v)
-@@ -310,8 +311,21 @@ void do_IRQ(struct pt_regs *regs)
+@@ -306,12 +307,29 @@ void do_IRQ(struct pt_regs *regs)
+ if (curtp != irqtp) {
+ struct irq_desc *desc = irq_desc + irq;
+ void *handler = desc->handle_irq;
++ unsigned long saved_sp_limit = current->thread.ksp_limit;
+ if (handler == NULL)
handler = &__do_IRQ;
irqtp->task = curtp->task;
irqtp->flags = 0;
@@ -185915,7 +224426,10 @@
+ (irqtp->preempt_count & ~SOFTIRQ_MASK) |
+ (curtp->preempt_count & SOFTIRQ_MASK);
+
++ current->thread.ksp_limit = (unsigned long)irqtp +
++ _ALIGN_UP(sizeof(struct thread_info), 16);
call_handle_irq(irq, desc, irqtp, handler);
++ current->thread.ksp_limit = saved_sp_limit;
irqtp->task = NULL;
+
+
@@ -185925,7 +224439,17 @@
if (irqtp->flags)
set_bits(irqtp->flags, &curtp->flags);
} else
-@@ -357,7 +371,7 @@ void irq_ctx_init(void)
+@@ -338,9 +356,7 @@ void __init init_IRQ(void)
+ {
+ if (ppc_md.init_IRQ)
+ ppc_md.init_IRQ();
+-#ifdef CONFIG_PPC64
+ irq_ctx_init();
+-#endif
+ }
+
+
+@@ -357,7 +373,7 @@ void irq_ctx_init(void)
memset((void *)softirq_ctx[i], 0, THREAD_SIZE);
tp = softirq_ctx[i];
tp->cpu = i;
@@ -185934,6 +224458,22 @@
memset((void *)hardirq_ctx[i], 0, THREAD_SIZE);
tp = hardirq_ctx[i];
+@@ -369,11 +385,15 @@ void irq_ctx_init(void)
+ static inline void do_softirq_onstack(void)
+ {
+ struct thread_info *curtp, *irqtp;
++ unsigned long saved_sp_limit = current->thread.ksp_limit;
+
+ curtp = current_thread_info();
+ irqtp = softirq_ctx[smp_processor_id()];
+ irqtp->task = curtp->task;
++ current->thread.ksp_limit = (unsigned long)irqtp +
++ _ALIGN_UP(sizeof(struct thread_info), 16);
+ call_do_softirq(irqtp);
++ current->thread.ksp_limit = saved_sp_limit;
+ irqtp->task = NULL;
+ }
+
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
@@ -185964,7 +224504,7 @@
}
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
-index dcb89a8..1ffacc6 100644
+index dcb89a8..1e656b4 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)
@@ -186015,8 +224555,21 @@
retval = -EIO;
}
+@@ -591,10 +591,8 @@ int __init lparcfg_init(void)
+ !firmware_has_feature(FW_FEATURE_ISERIES))
+ mode |= S_IWUSR;
+
+- ent = create_proc_entry("ppc64/lparcfg", mode, NULL);
+- if (ent) {
+- ent->proc_fops = &lparcfg_fops;
+- } else {
++ ent = proc_create("ppc64/lparcfg", mode, NULL, &lparcfg_fops);
++ if (!ent) {
+ printk(KERN_ERR "Failed to create ppc64/lparcfg\n");
+ return -EIO;
+ }
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
-index c0c8e8c..2d202f2 100644
+index c0c8e8c..29a0e03 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -12,8 +12,9 @@
@@ -186030,11 +224583,70 @@
void machine_crash_shutdown(struct pt_regs *regs)
{
+@@ -73,20 +74,20 @@ void __init reserve_crashkernel(void)
+ ret = parse_crashkernel(boot_command_line, lmb_phys_mem_size(),
+ &crash_size, &crash_base);
+ if (ret == 0 && crash_size > 0) {
+- if (crash_base == 0)
+- crash_base = KDUMP_KERNELBASE;
+ crashk_res.start = crash_base;
+- } else {
+- /* handle the device tree */
+- crash_size = crashk_res.end - crashk_res.start + 1;
++ crashk_res.end = crash_base + crash_size - 1;
+ }
+
+- if (crash_size == 0)
++ if (crashk_res.end == crashk_res.start) {
++ crashk_res.start = crashk_res.end = 0;
+ return;
++ }
+
+ /* We might have got these values via the command line or the
+ * device tree, either way sanitise them now. */
+
++ crash_size = crashk_res.end - crashk_res.start + 1;
++
+ if (crashk_res.start != KDUMP_KERNELBASE)
+ printk("Crash kernel location must be 0x%x\n",
+ KDUMP_KERNELBASE);
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
-index 9d2c566..92ccc6f 100644
+index 9d2c566..89aaaa6 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
-@@ -152,7 +152,7 @@ _GLOBAL(low_choose_750fx_pll)
+@@ -32,6 +32,31 @@
+
+ .text
+
++#ifdef CONFIG_IRQSTACKS
++_GLOBAL(call_do_softirq)
++ mflr r0
++ stw r0,4(r1)
++ stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
++ mr r1,r3
++ bl __do_softirq
++ lwz r1,0(r1)
++ lwz r0,4(r1)
++ mtlr r0
++ blr
++
++_GLOBAL(call_handle_irq)
++ mflr r0
++ stw r0,4(r1)
++ mtctr r6
++ stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r5)
++ mr r1,r5
++ bctrl
++ lwz r1,0(r1)
++ lwz r0,4(r1)
++ mtlr r0
++ blr
++#endif /* CONFIG_IRQSTACKS */
++
+ /*
+ * This returns the high 64 bits of the product of two 64-bit numbers.
+ */
+@@ -152,7 +177,7 @@ _GLOBAL(low_choose_750fx_pll)
mtspr SPRN_HID1,r4
/* Store new HID1 image */
@@ -186043,7 +224655,7 @@
lwz r6,TI_CPU(r6)
slwi r6,r6,2
addis r6,r6,nap_save_hid1 at ha
-@@ -281,7 +281,7 @@ _GLOBAL(_tlbia)
+@@ -281,7 +306,7 @@ _GLOBAL(_tlbia)
#endif /* CONFIG_SMP */
#else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
#if defined(CONFIG_SMP)
@@ -186052,7 +224664,7 @@
lwz r8,TI_CPU(r8)
oris r8,r8,10
mfmsr r10
-@@ -377,7 +377,7 @@ _GLOBAL(_tlbie)
+@@ -377,7 +402,7 @@ _GLOBAL(_tlbie)
#endif /* CONFIG_SMP */
#else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
#if defined(CONFIG_SMP)
@@ -186316,7 +224928,7 @@
}
-
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
-index 9c98424..09fcb50 100644
+index 9c98424..cf6b5a7 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -15,7 +15,6 @@
@@ -186354,16 +224966,54 @@
EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL(csum_partial_copy_generic);
-@@ -192,3 +187,4 @@ EXPORT_SYMBOL(intercept_table);
+@@ -138,9 +133,6 @@ EXPORT_SYMBOL(adb_try_handler_change);
+ EXPORT_SYMBOL(cuda_request);
+ EXPORT_SYMBOL(cuda_poll);
+ #endif /* CONFIG_ADB_CUDA */
+-#ifdef CONFIG_VT
+-EXPORT_SYMBOL(kd_mksound);
+-#endif
+ EXPORT_SYMBOL(to_tm);
+
+ #ifdef CONFIG_PPC32
+@@ -192,3 +184,4 @@ EXPORT_SYMBOL(intercept_table);
EXPORT_SYMBOL(__mtdcr);
EXPORT_SYMBOL(__mfdcr);
#endif
+EXPORT_SYMBOL(empty_zero_page);
+diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c
+index f78dfce..c647dde 100644
+--- a/arch/powerpc/kernel/proc_ppc64.c
++++ b/arch/powerpc/kernel/proc_ppc64.c
+@@ -68,12 +68,11 @@ static int __init proc_ppc64_init(void)
+ {
+ struct proc_dir_entry *pde;
+
+- pde = create_proc_entry("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL);
++ pde = proc_create_data("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL,
++ &page_map_fops, vdso_data);
+ if (!pde)
+ return 1;
+- pde->data = vdso_data;
+ pde->size = PAGE_SIZE;
+- pde->proc_fops = &page_map_fops;
+
+ return 0;
+ }
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
-index 4ec6055..6caad17 100644
+index 4ec6055..7de41c3 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,
+@@ -589,6 +589,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ kregs = (struct pt_regs *) sp;
+ sp -= STACK_FRAME_OVERHEAD;
+ p->thread.ksp = sp;
++ p->thread.ksp_limit = (unsigned long)task_stack_page(p) +
++ _ALIGN_UP(sizeof(struct thread_info), 16);
+
+ #ifdef CONFIG_PPC64
+ if (cpu_has_feature(CPU_FTR_SLB)) {
+@@ -868,11 +870,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);
@@ -186375,7 +225025,7 @@
putname(filename);
out:
return error;
-@@ -919,20 +914,6 @@ int validate_sp(unsigned long sp, struct task_struct *p,
+@@ -919,20 +916,6 @@ int validate_sp(unsigned long sp, struct task_struct *p,
return valid_irq_stack(sp, p, nbytes);
}
@@ -186396,7 +225046,7 @@
EXPORT_SYMBOL(validate_sp);
unsigned long get_wchan(struct task_struct *p)
-@@ -944,15 +925,15 @@ unsigned long get_wchan(struct task_struct *p)
+@@ -944,15 +927,15 @@ unsigned long get_wchan(struct task_struct *p)
return 0;
sp = p->thread.ksp;
@@ -186415,7 +225065,7 @@
if (!in_sched_functions(ip))
return ip;
}
-@@ -981,12 +962,12 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
+@@ -981,12 +964,12 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
lr = 0;
printk("Call Trace:\n");
do {
@@ -186430,7 +225080,7 @@
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)
+@@ -1000,8 +983,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.
*/
@@ -186441,7 +225091,7 @@
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)
+@@ -1052,3 +1035,34 @@ void ppc64_runlatch_off(void)
}
}
#endif
@@ -186817,6 +225467,127 @@
+done
+
+exit $ERROR
+diff --git a/arch/powerpc/kernel/rio.c b/arch/powerpc/kernel/rio.c
+deleted file mode 100644
+index 29487fe..0000000
+--- a/arch/powerpc/kernel/rio.c
++++ /dev/null
+@@ -1,52 +0,0 @@
+-/*
+- * RapidIO PPC32 support
+- *
+- * Copyright 2005 MontaVista Software, Inc.
+- * Matt Porter <mporter at kernel.crashing.org>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2 of the License, or (at your
+- * option) any later version.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/kernel.h>
+-#include <linux/rio.h>
+-
+-#include <asm/rio.h>
+-
+-/**
+- * platform_rio_init - Do platform specific RIO init
+- *
+- * Any platform specific initialization of RapdIO
+- * hardware is done here as well as registration
+- * of any active master ports in the system.
+- */
+-void __attribute__ ((weak))
+- platform_rio_init(void)
+-{
+- printk(KERN_WARNING "RIO: No platform_rio_init() present\n");
+-}
+-
+-/**
+- * ppc_rio_init - Do PPC32 RIO init
+- *
+- * Calls platform-specific RIO init code and then calls
+- * rio_init_mports() to initialize any master ports that
+- * have been registered with the RIO subsystem.
+- */
+-static int __init ppc_rio_init(void)
+-{
+- printk(KERN_INFO "RIO: RapidIO init\n");
+-
+- /* Platform specific initialization */
+- platform_rio_init();
+-
+- /* Enumerate all registered ports */
+- rio_init_mports();
+-
+- return 0;
+-}
+-
+-subsys_initcall(ppc_rio_init);
+diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c
+index f2e3bc7..f9c6abc 100644
+--- a/arch/powerpc/kernel/rtas-proc.c
++++ b/arch/powerpc/kernel/rtas-proc.c
+@@ -255,8 +255,6 @@ static void check_location(struct seq_file *m, const char *c);
+
+ static int __init proc_rtas_init(void)
+ {
+- struct proc_dir_entry *entry;
+-
+ if (!machine_is(pseries))
+ return -ENODEV;
+
+@@ -264,35 +262,20 @@ static int __init proc_rtas_init(void)
+ if (rtas_node == NULL)
+ return -ENODEV;
+
+- entry = create_proc_entry("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL);
+- if (entry)
+- entry->proc_fops = &ppc_rtas_progress_operations;
+-
+- entry = create_proc_entry("ppc64/rtas/clock", S_IRUGO|S_IWUSR, NULL);
+- if (entry)
+- entry->proc_fops = &ppc_rtas_clock_operations;
+-
+- entry = create_proc_entry("ppc64/rtas/poweron", S_IWUSR|S_IRUGO, NULL);
+- if (entry)
+- entry->proc_fops = &ppc_rtas_poweron_operations;
+-
+- entry = create_proc_entry("ppc64/rtas/sensors", S_IRUGO, NULL);
+- if (entry)
+- entry->proc_fops = &ppc_rtas_sensors_operations;
+-
+- entry = create_proc_entry("ppc64/rtas/frequency", S_IWUSR|S_IRUGO,
+- NULL);
+- if (entry)
+- entry->proc_fops = &ppc_rtas_tone_freq_operations;
+-
+- entry = create_proc_entry("ppc64/rtas/volume", S_IWUSR|S_IRUGO, NULL);
+- if (entry)
+- entry->proc_fops = &ppc_rtas_tone_volume_operations;
+-
+- entry = create_proc_entry("ppc64/rtas/rmo_buffer", S_IRUSR, NULL);
+- if (entry)
+- entry->proc_fops = &ppc_rtas_rmo_buf_ops;
+-
++ proc_create("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL,
++ &ppc_rtas_progress_operations);
++ proc_create("ppc64/rtas/clock", S_IRUGO|S_IWUSR, NULL,
++ &ppc_rtas_clock_operations);
++ proc_create("ppc64/rtas/poweron", S_IWUSR|S_IRUGO, NULL,
++ &ppc_rtas_poweron_operations);
++ proc_create("ppc64/rtas/sensors", S_IRUGO, NULL,
++ &ppc_rtas_sensors_operations);
++ proc_create("ppc64/rtas/frequency", S_IWUSR|S_IRUGO, NULL,
++ &ppc_rtas_tone_freq_operations);
++ proc_create("ppc64/rtas/volume", S_IWUSR|S_IRUGO, NULL,
++ &ppc_rtas_tone_volume_operations);
++ proc_create("ppc64/rtas/rmo_buffer", S_IRUSR, NULL,
++ &ppc_rtas_rmo_buf_ops);
+ return 0;
+ }
+
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 52e95c2..34843c3 100644
--- a/arch/powerpc/kernel/rtas.c
@@ -186852,10 +225623,47 @@
break;
}
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
-index 538baf4..627f126 100644
+index 538baf4..0a5e22b 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)
+@@ -704,18 +704,11 @@ static int initialize_flash_pde_data(const char *rtas_call_name,
+ static struct proc_dir_entry *create_flash_pde(const char *filename,
+ const struct file_operations *fops)
+ {
+- struct proc_dir_entry *ent = NULL;
+-
+- ent = create_proc_entry(filename, S_IRUSR | S_IWUSR, NULL);
+- if (ent != NULL) {
+- ent->proc_fops = fops;
+- ent->owner = THIS_MODULE;
+- }
+-
+- return ent;
++ return proc_create(filename, S_IRUSR | S_IWUSR, NULL, fops);
+ }
+
+ static const struct file_operations rtas_flash_operations = {
++ .owner = THIS_MODULE,
+ .read = rtas_flash_read,
+ .write = rtas_flash_write,
+ .open = rtas_excl_open,
+@@ -723,6 +716,7 @@ static const struct file_operations rtas_flash_operations = {
+ };
+
+ static const struct file_operations manage_flash_operations = {
++ .owner = THIS_MODULE,
+ .read = manage_flash_read,
+ .write = manage_flash_write,
+ .open = rtas_excl_open,
+@@ -730,6 +724,7 @@ static const struct file_operations manage_flash_operations = {
+ };
+
+ static const struct file_operations validate_flash_operations = {
++ .owner = THIS_MODULE,
+ .read = validate_flash_read,
+ .write = validate_flash_write,
+ .open = rtas_excl_open,
+@@ -807,7 +802,7 @@ int __init rtas_flash_init(void)
rtas_block_ctor);
if (!flash_block_cache) {
printk(KERN_ERR "%s: failed to create block cache\n",
@@ -187134,10 +225942,10 @@
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
+index cd870a8..5112a4a 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
-@@ -10,9 +10,6 @@
+@@ -10,15 +10,13 @@
#include <linux/reboot.h>
#include <linux/delay.h>
#include <linux/initrd.h>
@@ -187147,7 +225955,14 @@
#include <linux/tty.h>
#include <linux/bootmem.h>
#include <linux/seq_file.h>
-@@ -51,11 +48,6 @@
+ #include <linux/root_dev.h>
+ #include <linux/cpu.h>
+ #include <linux/console.h>
++#include <linux/lmb.h>
+
+ #include <asm/io.h>
+ #include <asm/prom.h>
+@@ -51,11 +49,6 @@
extern void bootx_init(unsigned long r4, unsigned long phys);
@@ -187159,7 +225974,7 @@
int boot_cpuid;
EXPORT_SYMBOL_GPL(boot_cpuid);
int boot_cpuid_phys;
-@@ -172,6 +164,18 @@ int __init ppc_setup_l2cr(char *str)
+@@ -172,6 +165,18 @@ int __init ppc_setup_l2cr(char *str)
}
__setup("l2cr=", ppc_setup_l2cr);
@@ -187178,7 +225993,32 @@
#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)
+@@ -225,6 +230,24 @@ int __init ppc_init(void)
+
+ arch_initcall(ppc_init);
+
++#ifdef CONFIG_IRQSTACKS
++static void __init irqstack_early_init(void)
++{
++ unsigned int i;
++
++ /* interrupt stacks must be in lowmem, we get that for free on ppc32
++ * as the lmb is limited to lowmem by LMB_REAL_LIMIT */
++ for_each_possible_cpu(i) {
++ softirq_ctx[i] = (struct thread_info *)
++ __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
++ hardirq_ctx[i] = (struct thread_info *)
++ __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
++ }
++}
++#else
++#define irqstack_early_init()
++#endif
++
+ /* Warning, IO base is not yet inited */
+ void __init setup_arch(char **cmdline_p)
+ {
+@@ -277,11 +300,13 @@ void __init setup_arch(char **cmdline_p)
if (ppc_md.panic)
setup_panic();
@@ -187187,8 +226027,14 @@
init_mm.end_code = (unsigned long) _etext;
init_mm.end_data = (unsigned long) _edata;
init_mm.brk = klimit;
+
++ irqstack_early_init();
++
+ /* set up the bootmem stuff with available memory */
+ do_init_bootmem();
+ if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
-index 3b1529c..dff6308 100644
+index 3b1529c..25e3fd8 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -33,6 +33,8 @@
@@ -187237,7 +226083,23 @@
#endif
printk("-----------------------------------------------------\n");
-@@ -510,7 +517,7 @@ void __init setup_arch(char **cmdline_p)
+@@ -480,9 +487,12 @@ static void __init emergency_stack_init(void)
+ */
+ limit = min(0x10000000UL, lmb.rmo_size);
+
+- for_each_possible_cpu(i)
+- paca[i].emergency_sp =
+- __va(lmb_alloc_base(HW_PAGE_SIZE, 128, limit)) + HW_PAGE_SIZE;
++ for_each_possible_cpu(i) {
++ unsigned long sp;
++ sp = lmb_alloc_base(THREAD_SIZE, THREAD_SIZE, limit);
++ sp += THREAD_SIZE;
++ paca[i].emergency_sp = __va(sp);
++ }
+ }
+
+ /*
+@@ -510,7 +520,7 @@ void __init setup_arch(char **cmdline_p)
if (ppc_md.panic)
setup_panic();
@@ -187650,6 +226512,2762 @@
__bss_start = .;
*(.sbss) *(.scommon)
*(.dynbss)
+diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c
+new file mode 100644
+index 0000000..f5d7a5e
+--- /dev/null
++++ b/arch/powerpc/kvm/44x_tlb.c
+@@ -0,0 +1,224 @@
++/*
++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * Copyright IBM Corp. 2007
++ *
++ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ */
++
++#include <linux/types.h>
++#include <linux/string.h>
++#include <linux/kvm_host.h>
++#include <linux/highmem.h>
++#include <asm/mmu-44x.h>
++#include <asm/kvm_ppc.h>
++
++#include "44x_tlb.h"
++
++#define PPC44x_TLB_USER_PERM_MASK (PPC44x_TLB_UX|PPC44x_TLB_UR|PPC44x_TLB_UW)
++#define PPC44x_TLB_SUPER_PERM_MASK (PPC44x_TLB_SX|PPC44x_TLB_SR|PPC44x_TLB_SW)
++
++static unsigned int kvmppc_tlb_44x_pos;
++
++static u32 kvmppc_44x_tlb_shadow_attrib(u32 attrib, int usermode)
++{
++ /* Mask off reserved bits. */
++ attrib &= PPC44x_TLB_PERM_MASK|PPC44x_TLB_ATTR_MASK;
++
++ if (!usermode) {
++ /* Guest is in supervisor mode, so we need to translate guest
++ * supervisor permissions into user permissions. */
++ attrib &= ~PPC44x_TLB_USER_PERM_MASK;
++ attrib |= (attrib & PPC44x_TLB_SUPER_PERM_MASK) << 3;
++ }
++
++ /* Make sure host can always access this memory. */
++ attrib |= PPC44x_TLB_SX|PPC44x_TLB_SR|PPC44x_TLB_SW;
++
++ return attrib;
++}
++
++/* Search the guest TLB for a matching entry. */
++int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr, unsigned int pid,
++ unsigned int as)
++{
++ int i;
++
++ /* XXX Replace loop with fancy data structures. */
++ for (i = 0; i < PPC44x_TLB_SIZE; i++) {
++ struct tlbe *tlbe = &vcpu->arch.guest_tlb[i];
++ unsigned int tid;
++
++ if (eaddr < get_tlb_eaddr(tlbe))
++ continue;
++
++ if (eaddr > get_tlb_end(tlbe))
++ continue;
++
++ tid = get_tlb_tid(tlbe);
++ if (tid && (tid != pid))
++ continue;
++
++ if (!get_tlb_v(tlbe))
++ continue;
++
++ if (get_tlb_ts(tlbe) != as)
++ continue;
++
++ return i;
++ }
++
++ return -1;
++}
++
++struct tlbe *kvmppc_44x_itlb_search(struct kvm_vcpu *vcpu, gva_t eaddr)
++{
++ unsigned int as = !!(vcpu->arch.msr & MSR_IS);
++ unsigned int index;
++
++ index = kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
++ if (index == -1)
++ return NULL;
++ return &vcpu->arch.guest_tlb[index];
++}
++
++struct tlbe *kvmppc_44x_dtlb_search(struct kvm_vcpu *vcpu, gva_t eaddr)
++{
++ unsigned int as = !!(vcpu->arch.msr & MSR_DS);
++ unsigned int index;
++
++ index = kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
++ if (index == -1)
++ return NULL;
++ return &vcpu->arch.guest_tlb[index];
++}
++
++static int kvmppc_44x_tlbe_is_writable(struct tlbe *tlbe)
++{
++ return tlbe->word2 & (PPC44x_TLB_SW|PPC44x_TLB_UW);
++}
++
++/* Must be called with mmap_sem locked for writing. */
++static void kvmppc_44x_shadow_release(struct kvm_vcpu *vcpu,
++ unsigned int index)
++{
++ struct tlbe *stlbe = &vcpu->arch.shadow_tlb[index];
++ struct page *page = vcpu->arch.shadow_pages[index];
++
++ kunmap(vcpu->arch.shadow_pages[index]);
++
++ if (get_tlb_v(stlbe)) {
++ if (kvmppc_44x_tlbe_is_writable(stlbe))
++ kvm_release_page_dirty(page);
++ else
++ kvm_release_page_clean(page);
++ }
++}
++
++/* Caller must ensure that the specified guest TLB entry is safe to insert into
++ * the shadow TLB. */
++void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid,
++ u32 flags)
++{
++ struct page *new_page;
++ struct tlbe *stlbe;
++ hpa_t hpaddr;
++ unsigned int victim;
++
++ /* Future optimization: don't overwrite the TLB entry containing the
++ * current PC (or stack?). */
++ victim = kvmppc_tlb_44x_pos++;
++ if (kvmppc_tlb_44x_pos > tlb_44x_hwater)
++ kvmppc_tlb_44x_pos = 0;
++ stlbe = &vcpu->arch.shadow_tlb[victim];
++
++ /* Get reference to new page. */
++ down_write(¤t->mm->mmap_sem);
++ new_page = gfn_to_page(vcpu->kvm, gfn);
++ if (is_error_page(new_page)) {
++ printk(KERN_ERR "Couldn't get guest page!\n");
++ kvm_release_page_clean(new_page);
++ return;
++ }
++ hpaddr = page_to_phys(new_page);
++
++ /* Drop reference to old page. */
++ kvmppc_44x_shadow_release(vcpu, victim);
++ up_write(¤t->mm->mmap_sem);
++
++ vcpu->arch.shadow_pages[victim] = new_page;
++
++ /* XXX Make sure (va, size) doesn't overlap any other
++ * entries. 440x6 user manual says the result would be
++ * "undefined." */
++
++ /* XXX what about AS? */
++
++ stlbe->tid = asid & 0xff;
++
++ /* Force TS=1 for all guest mappings. */
++ /* For now we hardcode 4KB mappings, but it will be important to
++ * use host large pages in the future. */
++ stlbe->word0 = (gvaddr & PAGE_MASK) | PPC44x_TLB_VALID | PPC44x_TLB_TS
++ | PPC44x_TLB_4K;
++
++ stlbe->word1 = (hpaddr & 0xfffffc00) | ((hpaddr >> 32) & 0xf);
++ stlbe->word2 = kvmppc_44x_tlb_shadow_attrib(flags,
++ vcpu->arch.msr & MSR_PR);
++}
++
++void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, u64 eaddr, u64 asid)
++{
++ unsigned int pid = asid & 0xff;
++ int i;
++
++ /* XXX Replace loop with fancy data structures. */
++ down_write(¤t->mm->mmap_sem);
++ for (i = 0; i <= tlb_44x_hwater; i++) {
++ struct tlbe *stlbe = &vcpu->arch.shadow_tlb[i];
++ unsigned int tid;
++
++ if (!get_tlb_v(stlbe))
++ continue;
++
++ if (eaddr < get_tlb_eaddr(stlbe))
++ continue;
++
++ if (eaddr > get_tlb_end(stlbe))
++ continue;
++
++ tid = get_tlb_tid(stlbe);
++ if (tid && (tid != pid))
++ continue;
++
++ kvmppc_44x_shadow_release(vcpu, i);
++ stlbe->word0 = 0;
++ }
++ up_write(¤t->mm->mmap_sem);
++}
++
++/* Invalidate all mappings, so that when they fault back in they will get the
++ * proper permission bits. */
++void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode)
++{
++ int i;
++
++ /* XXX Replace loop with fancy data structures. */
++ down_write(¤t->mm->mmap_sem);
++ for (i = 0; i <= tlb_44x_hwater; i++) {
++ kvmppc_44x_shadow_release(vcpu, i);
++ vcpu->arch.shadow_tlb[i].word0 = 0;
++ }
++ up_write(¤t->mm->mmap_sem);
++}
+diff --git a/arch/powerpc/kvm/44x_tlb.h b/arch/powerpc/kvm/44x_tlb.h
+new file mode 100644
+index 0000000..2ccd46b
+--- /dev/null
++++ b/arch/powerpc/kvm/44x_tlb.h
+@@ -0,0 +1,91 @@
++/*
++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * Copyright IBM Corp. 2007
++ *
++ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ */
++
++#ifndef __KVM_POWERPC_TLB_H__
++#define __KVM_POWERPC_TLB_H__
++
++#include <linux/kvm_host.h>
++#include <asm/mmu-44x.h>
++
++extern int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr,
++ unsigned int pid, unsigned int as);
++extern struct tlbe *kvmppc_44x_dtlb_search(struct kvm_vcpu *vcpu, gva_t eaddr);
++extern struct tlbe *kvmppc_44x_itlb_search(struct kvm_vcpu *vcpu, gva_t eaddr);
++
++/* TLB helper functions */
++static inline unsigned int get_tlb_size(const struct tlbe *tlbe)
++{
++ return (tlbe->word0 >> 4) & 0xf;
++}
++
++static inline gva_t get_tlb_eaddr(const struct tlbe *tlbe)
++{
++ return tlbe->word0 & 0xfffffc00;
++}
++
++static inline gva_t get_tlb_bytes(const struct tlbe *tlbe)
++{
++ unsigned int pgsize = get_tlb_size(tlbe);
++ return 1 << 10 << (pgsize << 1);
++}
++
++static inline gva_t get_tlb_end(const struct tlbe *tlbe)
++{
++ return get_tlb_eaddr(tlbe) + get_tlb_bytes(tlbe) - 1;
++}
++
++static inline u64 get_tlb_raddr(const struct tlbe *tlbe)
++{
++ u64 word1 = tlbe->word1;
++ return ((word1 & 0xf) << 32) | (word1 & 0xfffffc00);
++}
++
++static inline unsigned int get_tlb_tid(const struct tlbe *tlbe)
++{
++ return tlbe->tid & 0xff;
++}
++
++static inline unsigned int get_tlb_ts(const struct tlbe *tlbe)
++{
++ return (tlbe->word0 >> 8) & 0x1;
++}
++
++static inline unsigned int get_tlb_v(const struct tlbe *tlbe)
++{
++ return (tlbe->word0 >> 9) & 0x1;
++}
++
++static inline unsigned int get_mmucr_stid(const struct kvm_vcpu *vcpu)
++{
++ return vcpu->arch.mmucr & 0xff;
++}
++
++static inline unsigned int get_mmucr_sts(const struct kvm_vcpu *vcpu)
++{
++ return (vcpu->arch.mmucr >> 16) & 0x1;
++}
++
++static inline gpa_t tlb_xlate(struct tlbe *tlbe, gva_t eaddr)
++{
++ unsigned int pgmask = get_tlb_bytes(tlbe) - 1;
++
++ return get_tlb_raddr(tlbe) | (eaddr & pgmask);
++}
++
++#endif /* __KVM_POWERPC_TLB_H__ */
+diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
+new file mode 100644
+index 0000000..6b07601
+--- /dev/null
++++ b/arch/powerpc/kvm/Kconfig
+@@ -0,0 +1,42 @@
++#
++# KVM configuration
++#
++
++menuconfig VIRTUALIZATION
++ bool "Virtualization"
++ ---help---
++ Say Y here to get to see options for using your Linux host to run
++ other operating systems inside virtual machines (guests).
++ This option alone does not add any kernel code.
++
++ If you say N, all options in this submenu will be skipped and
++ disabled.
++
++if VIRTUALIZATION
++
++config KVM
++ bool "Kernel-based Virtual Machine (KVM) support"
++ depends on 44x && EXPERIMENTAL
++ select PREEMPT_NOTIFIERS
++ select ANON_INODES
++ # We can only run on Book E hosts so far
++ select KVM_BOOKE_HOST
++ ---help---
++ Support hosting virtualized guest machines. You will also
++ need to select one or more of the processor modules below.
++
++ This module provides access to the hardware capabilities through
++ a character device node named /dev/kvm.
++
++ If unsure, say N.
++
++config KVM_BOOKE_HOST
++ bool "KVM host support for Book E PowerPC processors"
++ depends on KVM && 44x
++ ---help---
++ Provides host support for KVM on Book E PowerPC processors. Currently
++ this works on 440 processors only.
++
++source drivers/virtio/Kconfig
++
++endif # VIRTUALIZATION
+diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
+new file mode 100644
+index 0000000..d0d358d
+--- /dev/null
++++ b/arch/powerpc/kvm/Makefile
+@@ -0,0 +1,15 @@
++#
++# Makefile for Kernel-based Virtual Machine module
++#
++
++EXTRA_CFLAGS += -Ivirt/kvm -Iarch/powerpc/kvm
++
++common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o)
++
++kvm-objs := $(common-objs) powerpc.o emulate.o booke_guest.o
++obj-$(CONFIG_KVM) += kvm.o
++
++AFLAGS_booke_interrupts.o := -I$(obj)
++
++kvm-booke-host-objs := booke_host.o booke_interrupts.o 44x_tlb.o
++obj-$(CONFIG_KVM_BOOKE_HOST) += kvm-booke-host.o
+diff --git a/arch/powerpc/kvm/booke_guest.c b/arch/powerpc/kvm/booke_guest.c
+new file mode 100644
+index 0000000..6d9884a
+--- /dev/null
++++ b/arch/powerpc/kvm/booke_guest.c
+@@ -0,0 +1,615 @@
++/*
++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * Copyright IBM Corp. 2007
++ *
++ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ * Christian Ehrhardt <ehrhardt at linux.vnet.ibm.com>
++ */
++
++#include <linux/errno.h>
++#include <linux/err.h>
++#include <linux/kvm_host.h>
++#include <linux/module.h>
++#include <linux/vmalloc.h>
++#include <linux/fs.h>
++#include <asm/cputable.h>
++#include <asm/uaccess.h>
++#include <asm/kvm_ppc.h>
++
++#include "44x_tlb.h"
++
++#define VM_STAT(x) offsetof(struct kvm, stat.x), KVM_STAT_VM
++#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
++
++struct kvm_stats_debugfs_item debugfs_entries[] = {
++ { "exits", VCPU_STAT(sum_exits) },
++ { "mmio", VCPU_STAT(mmio_exits) },
++ { "dcr", VCPU_STAT(dcr_exits) },
++ { "sig", VCPU_STAT(signal_exits) },
++ { "light", VCPU_STAT(light_exits) },
++ { "itlb_r", VCPU_STAT(itlb_real_miss_exits) },
++ { "itlb_v", VCPU_STAT(itlb_virt_miss_exits) },
++ { "dtlb_r", VCPU_STAT(dtlb_real_miss_exits) },
++ { "dtlb_v", VCPU_STAT(dtlb_virt_miss_exits) },
++ { "sysc", VCPU_STAT(syscall_exits) },
++ { "isi", VCPU_STAT(isi_exits) },
++ { "dsi", VCPU_STAT(dsi_exits) },
++ { "inst_emu", VCPU_STAT(emulated_inst_exits) },
++ { "dec", VCPU_STAT(dec_exits) },
++ { "ext_intr", VCPU_STAT(ext_intr_exits) },
++ { NULL }
++};
++
++static const u32 interrupt_msr_mask[16] = {
++ [BOOKE_INTERRUPT_CRITICAL] = MSR_ME,
++ [BOOKE_INTERRUPT_MACHINE_CHECK] = 0,
++ [BOOKE_INTERRUPT_DATA_STORAGE] = MSR_CE|MSR_ME|MSR_DE,
++ [BOOKE_INTERRUPT_INST_STORAGE] = MSR_CE|MSR_ME|MSR_DE,
++ [BOOKE_INTERRUPT_EXTERNAL] = MSR_CE|MSR_ME|MSR_DE,
++ [BOOKE_INTERRUPT_ALIGNMENT] = MSR_CE|MSR_ME|MSR_DE,
++ [BOOKE_INTERRUPT_PROGRAM] = MSR_CE|MSR_ME|MSR_DE,
++ [BOOKE_INTERRUPT_FP_UNAVAIL] = MSR_CE|MSR_ME|MSR_DE,
++ [BOOKE_INTERRUPT_SYSCALL] = MSR_CE|MSR_ME|MSR_DE,
++ [BOOKE_INTERRUPT_AP_UNAVAIL] = MSR_CE|MSR_ME|MSR_DE,
++ [BOOKE_INTERRUPT_DECREMENTER] = MSR_CE|MSR_ME|MSR_DE,
++ [BOOKE_INTERRUPT_FIT] = MSR_CE|MSR_ME|MSR_DE,
++ [BOOKE_INTERRUPT_WATCHDOG] = MSR_ME,
++ [BOOKE_INTERRUPT_DTLB_MISS] = MSR_CE|MSR_ME|MSR_DE,
++ [BOOKE_INTERRUPT_ITLB_MISS] = MSR_CE|MSR_ME|MSR_DE,
++ [BOOKE_INTERRUPT_DEBUG] = MSR_ME,
++};
++
++const unsigned char exception_priority[] = {
++ [BOOKE_INTERRUPT_DATA_STORAGE] = 0,
++ [BOOKE_INTERRUPT_INST_STORAGE] = 1,
++ [BOOKE_INTERRUPT_ALIGNMENT] = 2,
++ [BOOKE_INTERRUPT_PROGRAM] = 3,
++ [BOOKE_INTERRUPT_FP_UNAVAIL] = 4,
++ [BOOKE_INTERRUPT_SYSCALL] = 5,
++ [BOOKE_INTERRUPT_AP_UNAVAIL] = 6,
++ [BOOKE_INTERRUPT_DTLB_MISS] = 7,
++ [BOOKE_INTERRUPT_ITLB_MISS] = 8,
++ [BOOKE_INTERRUPT_MACHINE_CHECK] = 9,
++ [BOOKE_INTERRUPT_DEBUG] = 10,
++ [BOOKE_INTERRUPT_CRITICAL] = 11,
++ [BOOKE_INTERRUPT_WATCHDOG] = 12,
++ [BOOKE_INTERRUPT_EXTERNAL] = 13,
++ [BOOKE_INTERRUPT_FIT] = 14,
++ [BOOKE_INTERRUPT_DECREMENTER] = 15,
++};
++
++const unsigned char priority_exception[] = {
++ BOOKE_INTERRUPT_DATA_STORAGE,
++ BOOKE_INTERRUPT_INST_STORAGE,
++ BOOKE_INTERRUPT_ALIGNMENT,
++ BOOKE_INTERRUPT_PROGRAM,
++ BOOKE_INTERRUPT_FP_UNAVAIL,
++ BOOKE_INTERRUPT_SYSCALL,
++ BOOKE_INTERRUPT_AP_UNAVAIL,
++ BOOKE_INTERRUPT_DTLB_MISS,
++ BOOKE_INTERRUPT_ITLB_MISS,
++ BOOKE_INTERRUPT_MACHINE_CHECK,
++ BOOKE_INTERRUPT_DEBUG,
++ BOOKE_INTERRUPT_CRITICAL,
++ BOOKE_INTERRUPT_WATCHDOG,
++ BOOKE_INTERRUPT_EXTERNAL,
++ BOOKE_INTERRUPT_FIT,
++ BOOKE_INTERRUPT_DECREMENTER,
++};
++
++
++void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu)
++{
++ struct tlbe *tlbe;
++ int i;
++
++ printk("vcpu %d TLB dump:\n", vcpu->vcpu_id);
++ printk("| %2s | %3s | %8s | %8s | %8s |\n",
++ "nr", "tid", "word0", "word1", "word2");
++
++ for (i = 0; i < PPC44x_TLB_SIZE; i++) {
++ tlbe = &vcpu->arch.guest_tlb[i];
++ if (tlbe->word0 & PPC44x_TLB_VALID)
++ printk(" G%2d | %02X | %08X | %08X | %08X |\n",
++ i, tlbe->tid, tlbe->word0, tlbe->word1,
++ tlbe->word2);
++ }
++
++ for (i = 0; i < PPC44x_TLB_SIZE; i++) {
++ tlbe = &vcpu->arch.shadow_tlb[i];
++ if (tlbe->word0 & PPC44x_TLB_VALID)
++ printk(" S%2d | %02X | %08X | %08X | %08X |\n",
++ i, tlbe->tid, tlbe->word0, tlbe->word1,
++ tlbe->word2);
++ }
++}
++
++/* TODO: use vcpu_printf() */
++void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu)
++{
++ int i;
++
++ printk("pc: %08x msr: %08x\n", vcpu->arch.pc, vcpu->arch.msr);
++ printk("lr: %08x ctr: %08x\n", vcpu->arch.lr, vcpu->arch.ctr);
++ printk("srr0: %08x srr1: %08x\n", vcpu->arch.srr0, vcpu->arch.srr1);
++
++ printk("exceptions: %08lx\n", vcpu->arch.pending_exceptions);
++
++ for (i = 0; i < 32; i += 4) {
++ printk("gpr%02d: %08x %08x %08x %08x\n", i,
++ vcpu->arch.gpr[i],
++ vcpu->arch.gpr[i+1],
++ vcpu->arch.gpr[i+2],
++ vcpu->arch.gpr[i+3]);
++ }
++}
++
++/* Check if we are ready to deliver the interrupt */
++static int kvmppc_can_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt)
++{
++ int r;
++
++ switch (interrupt) {
++ case BOOKE_INTERRUPT_CRITICAL:
++ r = vcpu->arch.msr & MSR_CE;
++ break;
++ case BOOKE_INTERRUPT_MACHINE_CHECK:
++ r = vcpu->arch.msr & MSR_ME;
++ break;
++ case BOOKE_INTERRUPT_EXTERNAL:
++ r = vcpu->arch.msr & MSR_EE;
++ break;
++ case BOOKE_INTERRUPT_DECREMENTER:
++ r = vcpu->arch.msr & MSR_EE;
++ break;
++ case BOOKE_INTERRUPT_FIT:
++ r = vcpu->arch.msr & MSR_EE;
++ break;
++ case BOOKE_INTERRUPT_WATCHDOG:
++ r = vcpu->arch.msr & MSR_CE;
++ break;
++ case BOOKE_INTERRUPT_DEBUG:
++ r = vcpu->arch.msr & MSR_DE;
++ break;
++ default:
++ r = 1;
++ }
++
++ return r;
++}
++
++static void kvmppc_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt)
++{
++ switch (interrupt) {
++ case BOOKE_INTERRUPT_DECREMENTER:
++ vcpu->arch.tsr |= TSR_DIS;
++ break;
++ }
++
++ vcpu->arch.srr0 = vcpu->arch.pc;
++ vcpu->arch.srr1 = vcpu->arch.msr;
++ vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[interrupt];
++ kvmppc_set_msr(vcpu, vcpu->arch.msr & interrupt_msr_mask[interrupt]);
++}
++
++/* Check pending exceptions and deliver one, if possible. */
++void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu)
++{
++ unsigned long *pending = &vcpu->arch.pending_exceptions;
++ unsigned int exception;
++ unsigned int priority;
++
++ priority = find_first_bit(pending, BITS_PER_BYTE * sizeof(*pending));
++ while (priority <= BOOKE_MAX_INTERRUPT) {
++ exception = priority_exception[priority];
++ if (kvmppc_can_deliver_interrupt(vcpu, exception)) {
++ kvmppc_clear_exception(vcpu, exception);
++ kvmppc_deliver_interrupt(vcpu, exception);
++ break;
++ }
++
++ priority = find_next_bit(pending,
++ BITS_PER_BYTE * sizeof(*pending),
++ priority + 1);
++ }
++}
++
++static int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu)
++{
++ enum emulation_result er;
++ int r;
++
++ er = kvmppc_emulate_instruction(run, vcpu);
++ switch (er) {
++ case EMULATE_DONE:
++ /* Future optimization: only reload non-volatiles if they were
++ * actually modified. */
++ r = RESUME_GUEST_NV;
++ break;
++ case EMULATE_DO_MMIO:
++ run->exit_reason = KVM_EXIT_MMIO;
++ /* We must reload nonvolatiles because "update" load/store
++ * instructions modify register state. */
++ /* Future optimization: only reload non-volatiles if they were
++ * actually modified. */
++ r = RESUME_HOST_NV;
++ break;
++ case EMULATE_FAIL:
++ /* XXX Deliver Program interrupt to guest. */
++ printk(KERN_EMERG "%s: emulation failed (%08x)\n", __func__,
++ vcpu->arch.last_inst);
++ r = RESUME_HOST;
++ break;
++ default:
++ BUG();
++ }
++
++ return r;
++}
++
++/**
++ * kvmppc_handle_exit
++ *
++ * Return value is in the form (errcode<<2 | RESUME_FLAG_HOST | RESUME_FLAG_NV)
++ */
++int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
++ unsigned int exit_nr)
++{
++ enum emulation_result er;
++ int r = RESUME_HOST;
++
++ local_irq_enable();
++
++ run->exit_reason = KVM_EXIT_UNKNOWN;
++ run->ready_for_interrupt_injection = 1;
++
++ switch (exit_nr) {
++ case BOOKE_INTERRUPT_MACHINE_CHECK:
++ printk("MACHINE CHECK: %lx\n", mfspr(SPRN_MCSR));
++ kvmppc_dump_vcpu(vcpu);
++ r = RESUME_HOST;
++ break;
++
++ case BOOKE_INTERRUPT_EXTERNAL:
++ case BOOKE_INTERRUPT_DECREMENTER:
++ /* Since we switched IVPR back to the host's value, the host
++ * handled this interrupt the moment we enabled interrupts.
++ * Now we just offer it a chance to reschedule the guest. */
++
++ /* XXX At this point the TLB still holds our shadow TLB, so if
++ * we do reschedule the host will fault over it. Perhaps we
++ * should politely restore the host's entries to minimize
++ * misses before ceding control. */
++ if (need_resched())
++ cond_resched();
++ if (exit_nr == BOOKE_INTERRUPT_DECREMENTER)
++ vcpu->stat.dec_exits++;
++ else
++ vcpu->stat.ext_intr_exits++;
++ r = RESUME_GUEST;
++ break;
++
++ case BOOKE_INTERRUPT_PROGRAM:
++ if (vcpu->arch.msr & MSR_PR) {
++ /* Program traps generated by user-level software must be handled
++ * by the guest kernel. */
++ vcpu->arch.esr = vcpu->arch.fault_esr;
++ kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM);
++ r = RESUME_GUEST;
++ break;
++ }
++
++ er = kvmppc_emulate_instruction(run, vcpu);
++ switch (er) {
++ case EMULATE_DONE:
++ /* Future optimization: only reload non-volatiles if
++ * they were actually modified by emulation. */
++ vcpu->stat.emulated_inst_exits++;
++ r = RESUME_GUEST_NV;
++ break;
++ case EMULATE_DO_DCR:
++ run->exit_reason = KVM_EXIT_DCR;
++ r = RESUME_HOST;
++ break;
++ case EMULATE_FAIL:
++ /* XXX Deliver Program interrupt to guest. */
++ printk(KERN_CRIT "%s: emulation at %x failed (%08x)\n",
++ __func__, vcpu->arch.pc, vcpu->arch.last_inst);
++ /* For debugging, encode the failing instruction and
++ * report it to userspace. */
++ run->hw.hardware_exit_reason = ~0ULL << 32;
++ run->hw.hardware_exit_reason |= vcpu->arch.last_inst;
++ r = RESUME_HOST;
++ break;
++ default:
++ BUG();
++ }
++ break;
++
++ case BOOKE_INTERRUPT_DATA_STORAGE:
++ vcpu->arch.dear = vcpu->arch.fault_dear;
++ vcpu->arch.esr = vcpu->arch.fault_esr;
++ kvmppc_queue_exception(vcpu, exit_nr);
++ vcpu->stat.dsi_exits++;
++ r = RESUME_GUEST;
++ break;
++
++ case BOOKE_INTERRUPT_INST_STORAGE:
++ vcpu->arch.esr = vcpu->arch.fault_esr;
++ kvmppc_queue_exception(vcpu, exit_nr);
++ vcpu->stat.isi_exits++;
++ r = RESUME_GUEST;
++ break;
++
++ case BOOKE_INTERRUPT_SYSCALL:
++ kvmppc_queue_exception(vcpu, exit_nr);
++ vcpu->stat.syscall_exits++;
++ r = RESUME_GUEST;
++ break;
++
++ case BOOKE_INTERRUPT_DTLB_MISS: {
++ struct tlbe *gtlbe;
++ unsigned long eaddr = vcpu->arch.fault_dear;
++ gfn_t gfn;
++
++ /* Check the guest TLB. */
++ gtlbe = kvmppc_44x_dtlb_search(vcpu, eaddr);
++ if (!gtlbe) {
++ /* The guest didn't have a mapping for it. */
++ kvmppc_queue_exception(vcpu, exit_nr);
++ vcpu->arch.dear = vcpu->arch.fault_dear;
++ vcpu->arch.esr = vcpu->arch.fault_esr;
++ vcpu->stat.dtlb_real_miss_exits++;
++ r = RESUME_GUEST;
++ break;
++ }
++
++ vcpu->arch.paddr_accessed = tlb_xlate(gtlbe, eaddr);
++ gfn = vcpu->arch.paddr_accessed >> PAGE_SHIFT;
++
++ if (kvm_is_visible_gfn(vcpu->kvm, gfn)) {
++ /* The guest TLB had a mapping, but the shadow TLB
++ * didn't, and it is RAM. This could be because:
++ * a) the entry is mapping the host kernel, or
++ * b) the guest used a large mapping which we're faking
++ * Either way, we need to satisfy the fault without
++ * invoking the guest. */
++ kvmppc_mmu_map(vcpu, eaddr, gfn, gtlbe->tid,
++ gtlbe->word2);
++ vcpu->stat.dtlb_virt_miss_exits++;
++ r = RESUME_GUEST;
++ } else {
++ /* Guest has mapped and accessed a page which is not
++ * actually RAM. */
++ r = kvmppc_emulate_mmio(run, vcpu);
++ }
++
++ break;
++ }
++
++ case BOOKE_INTERRUPT_ITLB_MISS: {
++ struct tlbe *gtlbe;
++ unsigned long eaddr = vcpu->arch.pc;
++ gfn_t gfn;
++
++ r = RESUME_GUEST;
++
++ /* Check the guest TLB. */
++ gtlbe = kvmppc_44x_itlb_search(vcpu, eaddr);
++ if (!gtlbe) {
++ /* The guest didn't have a mapping for it. */
++ kvmppc_queue_exception(vcpu, exit_nr);
++ vcpu->stat.itlb_real_miss_exits++;
++ break;
++ }
++
++ vcpu->stat.itlb_virt_miss_exits++;
++
++ gfn = tlb_xlate(gtlbe, eaddr) >> PAGE_SHIFT;
++
++ if (kvm_is_visible_gfn(vcpu->kvm, gfn)) {
++ /* The guest TLB had a mapping, but the shadow TLB
++ * didn't. This could be because:
++ * a) the entry is mapping the host kernel, or
++ * b) the guest used a large mapping which we're faking
++ * Either way, we need to satisfy the fault without
++ * invoking the guest. */
++ kvmppc_mmu_map(vcpu, eaddr, gfn, gtlbe->tid,
++ gtlbe->word2);
++ } else {
++ /* Guest mapped and leaped at non-RAM! */
++ kvmppc_queue_exception(vcpu,
++ BOOKE_INTERRUPT_MACHINE_CHECK);
++ }
++
++ break;
++ }
++
++ default:
++ printk(KERN_EMERG "exit_nr %d\n", exit_nr);
++ BUG();
++ }
++
++ local_irq_disable();
++
++ kvmppc_check_and_deliver_interrupts(vcpu);
++
++ /* Do some exit accounting. */
++ vcpu->stat.sum_exits++;
++ if (!(r & RESUME_HOST)) {
++ /* To avoid clobbering exit_reason, only check for signals if
++ * we aren't already exiting to userspace for some other
++ * reason. */
++ if (signal_pending(current)) {
++ run->exit_reason = KVM_EXIT_INTR;
++ r = (-EINTR << 2) | RESUME_HOST | (r & RESUME_FLAG_NV);
++
++ vcpu->stat.signal_exits++;
++ } else {
++ vcpu->stat.light_exits++;
++ }
++ } else {
++ switch (run->exit_reason) {
++ case KVM_EXIT_MMIO:
++ vcpu->stat.mmio_exits++;
++ break;
++ case KVM_EXIT_DCR:
++ vcpu->stat.dcr_exits++;
++ break;
++ case KVM_EXIT_INTR:
++ vcpu->stat.signal_exits++;
++ break;
++ }
++ }
++
++ return r;
++}
++
++/* Initial guest state: 16MB mapping 0 -> 0, PC = 0, MSR = 0, R1 = 16MB */
++int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
++{
++ struct tlbe *tlbe = &vcpu->arch.guest_tlb[0];
++
++ tlbe->tid = 0;
++ tlbe->word0 = PPC44x_TLB_16M | PPC44x_TLB_VALID;
++ tlbe->word1 = 0;
++ tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR;
++
++ tlbe++;
++ tlbe->tid = 0;
++ tlbe->word0 = 0xef600000 | PPC44x_TLB_4K | PPC44x_TLB_VALID;
++ tlbe->word1 = 0xef600000;
++ tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR
++ | PPC44x_TLB_I | PPC44x_TLB_G;
++
++ vcpu->arch.pc = 0;
++ vcpu->arch.msr = 0;
++ vcpu->arch.gpr[1] = (16<<20) - 8; /* -8 for the callee-save LR slot */
++
++ /* Eye-catching number so we know if the guest takes an interrupt
++ * before it's programmed its own IVPR. */
++ vcpu->arch.ivpr = 0x55550000;
++
++ /* Since the guest can directly access the timebase, it must know the
++ * real timebase frequency. Accordingly, it must see the state of
++ * CCR1[TCS]. */
++ vcpu->arch.ccr1 = mfspr(SPRN_CCR1);
++
++ return 0;
++}
++
++int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
++{
++ int i;
++
++ regs->pc = vcpu->arch.pc;
++ regs->cr = vcpu->arch.cr;
++ regs->ctr = vcpu->arch.ctr;
++ regs->lr = vcpu->arch.lr;
++ regs->xer = vcpu->arch.xer;
++ regs->msr = vcpu->arch.msr;
++ regs->srr0 = vcpu->arch.srr0;
++ regs->srr1 = vcpu->arch.srr1;
++ regs->pid = vcpu->arch.pid;
++ regs->sprg0 = vcpu->arch.sprg0;
++ regs->sprg1 = vcpu->arch.sprg1;
++ regs->sprg2 = vcpu->arch.sprg2;
++ regs->sprg3 = vcpu->arch.sprg3;
++ regs->sprg5 = vcpu->arch.sprg4;
++ regs->sprg6 = vcpu->arch.sprg5;
++ regs->sprg7 = vcpu->arch.sprg6;
++
++ for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
++ regs->gpr[i] = vcpu->arch.gpr[i];
++
++ return 0;
++}
++
++int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
++{
++ int i;
++
++ vcpu->arch.pc = regs->pc;
++ vcpu->arch.cr = regs->cr;
++ vcpu->arch.ctr = regs->ctr;
++ vcpu->arch.lr = regs->lr;
++ vcpu->arch.xer = regs->xer;
++ vcpu->arch.msr = regs->msr;
++ vcpu->arch.srr0 = regs->srr0;
++ vcpu->arch.srr1 = regs->srr1;
++ vcpu->arch.sprg0 = regs->sprg0;
++ vcpu->arch.sprg1 = regs->sprg1;
++ vcpu->arch.sprg2 = regs->sprg2;
++ vcpu->arch.sprg3 = regs->sprg3;
++ vcpu->arch.sprg5 = regs->sprg4;
++ vcpu->arch.sprg6 = regs->sprg5;
++ vcpu->arch.sprg7 = regs->sprg6;
++
++ for (i = 0; i < ARRAY_SIZE(vcpu->arch.gpr); i++)
++ vcpu->arch.gpr[i] = regs->gpr[i];
++
++ return 0;
++}
++
++int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
++ struct kvm_sregs *sregs)
++{
++ return -ENOTSUPP;
++}
++
++int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
++ struct kvm_sregs *sregs)
++{
++ return -ENOTSUPP;
++}
++
++int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
++{
++ return -ENOTSUPP;
++}
++
++int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
++{
++ return -ENOTSUPP;
++}
++
++/* 'linear_address' is actually an encoding of AS|PID|EADDR . */
++int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
++ struct kvm_translation *tr)
++{
++ struct tlbe *gtlbe;
++ int index;
++ gva_t eaddr;
++ u8 pid;
++ u8 as;
++
++ eaddr = tr->linear_address;
++ pid = (tr->linear_address >> 32) & 0xff;
++ as = (tr->linear_address >> 40) & 0x1;
++
++ index = kvmppc_44x_tlb_index(vcpu, eaddr, pid, as);
++ if (index == -1) {
++ tr->valid = 0;
++ return 0;
++ }
++
++ gtlbe = &vcpu->arch.guest_tlb[index];
++
++ tr->physical_address = tlb_xlate(gtlbe, eaddr);
++ /* XXX what does "writeable" and "usermode" even mean? */
++ tr->valid = 1;
++
++ return 0;
++}
+diff --git a/arch/powerpc/kvm/booke_host.c b/arch/powerpc/kvm/booke_host.c
+new file mode 100644
+index 0000000..b480341
+--- /dev/null
++++ b/arch/powerpc/kvm/booke_host.c
+@@ -0,0 +1,83 @@
++/*
++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * Copyright IBM Corp. 2008
++ *
++ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ */
++
++#include <linux/errno.h>
++#include <linux/kvm_host.h>
++#include <linux/module.h>
++#include <asm/cacheflush.h>
++#include <asm/kvm_ppc.h>
++
++unsigned long kvmppc_booke_handlers;
++
++static int kvmppc_booke_init(void)
++{
++ unsigned long ivor[16];
++ unsigned long max_ivor = 0;
++ int i;
++
++ /* We install our own exception handlers by hijacking IVPR. IVPR must
++ * be 16-bit aligned, so we need a 64KB allocation. */
++ kvmppc_booke_handlers = __get_free_pages(GFP_KERNEL | __GFP_ZERO,
++ VCPU_SIZE_ORDER);
++ if (!kvmppc_booke_handlers)
++ return -ENOMEM;
++
++ /* XXX make sure our handlers are smaller than Linux's */
++
++ /* Copy our interrupt handlers to match host IVORs. That way we don't
++ * have to swap the IVORs on every guest/host transition. */
++ ivor[0] = mfspr(SPRN_IVOR0);
++ ivor[1] = mfspr(SPRN_IVOR1);
++ ivor[2] = mfspr(SPRN_IVOR2);
++ ivor[3] = mfspr(SPRN_IVOR3);
++ ivor[4] = mfspr(SPRN_IVOR4);
++ ivor[5] = mfspr(SPRN_IVOR5);
++ ivor[6] = mfspr(SPRN_IVOR6);
++ ivor[7] = mfspr(SPRN_IVOR7);
++ ivor[8] = mfspr(SPRN_IVOR8);
++ ivor[9] = mfspr(SPRN_IVOR9);
++ ivor[10] = mfspr(SPRN_IVOR10);
++ ivor[11] = mfspr(SPRN_IVOR11);
++ ivor[12] = mfspr(SPRN_IVOR12);
++ ivor[13] = mfspr(SPRN_IVOR13);
++ ivor[14] = mfspr(SPRN_IVOR14);
++ ivor[15] = mfspr(SPRN_IVOR15);
++
++ for (i = 0; i < 16; i++) {
++ if (ivor[i] > max_ivor)
++ max_ivor = ivor[i];
++
++ memcpy((void *)kvmppc_booke_handlers + ivor[i],
++ kvmppc_handlers_start + i * kvmppc_handler_len,
++ kvmppc_handler_len);
++ }
++ flush_icache_range(kvmppc_booke_handlers,
++ kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
++
++ return kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE);
++}
++
++static void __exit kvmppc_booke_exit(void)
++{
++ free_pages(kvmppc_booke_handlers, VCPU_SIZE_ORDER);
++ kvm_exit();
++}
++
++module_init(kvmppc_booke_init)
++module_exit(kvmppc_booke_exit)
+diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S
+new file mode 100644
+index 0000000..3b653b5
+--- /dev/null
++++ b/arch/powerpc/kvm/booke_interrupts.S
+@@ -0,0 +1,436 @@
++/*
++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * Copyright IBM Corp. 2007
++ *
++ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ */
++
++#include <asm/ppc_asm.h>
++#include <asm/kvm_asm.h>
++#include <asm/reg.h>
++#include <asm/mmu-44x.h>
++#include <asm/page.h>
++#include <asm/asm-offsets.h>
++
++#define KVMPPC_MSR_MASK (MSR_CE|MSR_EE|MSR_PR|MSR_DE|MSR_ME|MSR_IS|MSR_DS)
++
++#define VCPU_GPR(n) (VCPU_GPRS + (n * 4))
++
++/* The host stack layout: */
++#define HOST_R1 0 /* Implied by stwu. */
++#define HOST_CALLEE_LR 4
++#define HOST_RUN 8
++/* r2 is special: it holds 'current', and it made nonvolatile in the
++ * kernel with the -ffixed-r2 gcc option. */
++#define HOST_R2 12
++#define HOST_NV_GPRS 16
++#define HOST_NV_GPR(n) (HOST_NV_GPRS + ((n - 14) * 4))
++#define HOST_MIN_STACK_SIZE (HOST_NV_GPR(31) + 4)
++#define HOST_STACK_SIZE (((HOST_MIN_STACK_SIZE + 15) / 16) * 16) /* Align. */
++#define HOST_STACK_LR (HOST_STACK_SIZE + 4) /* In caller stack frame. */
++
++#define NEED_INST_MASK ((1<<BOOKE_INTERRUPT_PROGRAM) | \
++ (1<<BOOKE_INTERRUPT_DTLB_MISS))
++
++#define NEED_DEAR_MASK ((1<<BOOKE_INTERRUPT_DATA_STORAGE) | \
++ (1<<BOOKE_INTERRUPT_DTLB_MISS))
++
++#define NEED_ESR_MASK ((1<<BOOKE_INTERRUPT_DATA_STORAGE) | \
++ (1<<BOOKE_INTERRUPT_INST_STORAGE) | \
++ (1<<BOOKE_INTERRUPT_PROGRAM) | \
++ (1<<BOOKE_INTERRUPT_DTLB_MISS))
++
++.macro KVM_HANDLER ivor_nr
++_GLOBAL(kvmppc_handler_\ivor_nr)
++ /* Get pointer to vcpu and record exit number. */
++ mtspr SPRN_SPRG0, r4
++ mfspr r4, SPRN_SPRG1
++ stw r5, VCPU_GPR(r5)(r4)
++ stw r6, VCPU_GPR(r6)(r4)
++ mfctr r5
++ lis r6, kvmppc_resume_host at h
++ stw r5, VCPU_CTR(r4)
++ li r5, \ivor_nr
++ ori r6, r6, kvmppc_resume_host at l
++ mtctr r6
++ bctr
++.endm
++
++_GLOBAL(kvmppc_handlers_start)
++KVM_HANDLER BOOKE_INTERRUPT_CRITICAL
++KVM_HANDLER BOOKE_INTERRUPT_MACHINE_CHECK
++KVM_HANDLER BOOKE_INTERRUPT_DATA_STORAGE
++KVM_HANDLER BOOKE_INTERRUPT_INST_STORAGE
++KVM_HANDLER BOOKE_INTERRUPT_EXTERNAL
++KVM_HANDLER BOOKE_INTERRUPT_ALIGNMENT
++KVM_HANDLER BOOKE_INTERRUPT_PROGRAM
++KVM_HANDLER BOOKE_INTERRUPT_FP_UNAVAIL
++KVM_HANDLER BOOKE_INTERRUPT_SYSCALL
++KVM_HANDLER BOOKE_INTERRUPT_AP_UNAVAIL
++KVM_HANDLER BOOKE_INTERRUPT_DECREMENTER
++KVM_HANDLER BOOKE_INTERRUPT_FIT
++KVM_HANDLER BOOKE_INTERRUPT_WATCHDOG
++KVM_HANDLER BOOKE_INTERRUPT_DTLB_MISS
++KVM_HANDLER BOOKE_INTERRUPT_ITLB_MISS
++KVM_HANDLER BOOKE_INTERRUPT_DEBUG
++
++_GLOBAL(kvmppc_handler_len)
++ .long kvmppc_handler_1 - kvmppc_handler_0
++
++
++/* Registers:
++ * SPRG0: guest r4
++ * r4: vcpu pointer
++ * r5: KVM exit number
++ */
++_GLOBAL(kvmppc_resume_host)
++ stw r3, VCPU_GPR(r3)(r4)
++ mfcr r3
++ stw r3, VCPU_CR(r4)
++ stw r7, VCPU_GPR(r7)(r4)
++ stw r8, VCPU_GPR(r8)(r4)
++ stw r9, VCPU_GPR(r9)(r4)
++
++ li r6, 1
++ slw r6, r6, r5
++
++ /* Save the faulting instruction and all GPRs for emulation. */
++ andi. r7, r6, NEED_INST_MASK
++ beq ..skip_inst_copy
++ mfspr r9, SPRN_SRR0
++ mfmsr r8
++ ori r7, r8, MSR_DS
++ mtmsr r7
++ isync
++ lwz r9, 0(r9)
++ mtmsr r8
++ isync
++ stw r9, VCPU_LAST_INST(r4)
++
++ stw r15, VCPU_GPR(r15)(r4)
++ stw r16, VCPU_GPR(r16)(r4)
++ stw r17, VCPU_GPR(r17)(r4)
++ stw r18, VCPU_GPR(r18)(r4)
++ stw r19, VCPU_GPR(r19)(r4)
++ stw r20, VCPU_GPR(r20)(r4)
++ stw r21, VCPU_GPR(r21)(r4)
++ stw r22, VCPU_GPR(r22)(r4)
++ stw r23, VCPU_GPR(r23)(r4)
++ stw r24, VCPU_GPR(r24)(r4)
++ stw r25, VCPU_GPR(r25)(r4)
++ stw r26, VCPU_GPR(r26)(r4)
++ stw r27, VCPU_GPR(r27)(r4)
++ stw r28, VCPU_GPR(r28)(r4)
++ stw r29, VCPU_GPR(r29)(r4)
++ stw r30, VCPU_GPR(r30)(r4)
++ stw r31, VCPU_GPR(r31)(r4)
++..skip_inst_copy:
++
++ /* Also grab DEAR and ESR before the host can clobber them. */
++
++ andi. r7, r6, NEED_DEAR_MASK
++ beq ..skip_dear
++ mfspr r9, SPRN_DEAR
++ stw r9, VCPU_FAULT_DEAR(r4)
++..skip_dear:
++
++ andi. r7, r6, NEED_ESR_MASK
++ beq ..skip_esr
++ mfspr r9, SPRN_ESR
++ stw r9, VCPU_FAULT_ESR(r4)
++..skip_esr:
++
++ /* Save remaining volatile guest register state to vcpu. */
++ stw r0, VCPU_GPR(r0)(r4)
++ stw r1, VCPU_GPR(r1)(r4)
++ stw r2, VCPU_GPR(r2)(r4)
++ stw r10, VCPU_GPR(r10)(r4)
++ stw r11, VCPU_GPR(r11)(r4)
++ stw r12, VCPU_GPR(r12)(r4)
++ stw r13, VCPU_GPR(r13)(r4)
++ stw r14, VCPU_GPR(r14)(r4) /* We need a NV GPR below. */
++ mflr r3
++ stw r3, VCPU_LR(r4)
++ mfxer r3
++ stw r3, VCPU_XER(r4)
++ mfspr r3, SPRN_SPRG0
++ stw r3, VCPU_GPR(r4)(r4)
++ mfspr r3, SPRN_SRR0
++ stw r3, VCPU_PC(r4)
++
++ /* Restore host stack pointer and PID before IVPR, since the host
++ * exception handlers use them. */
++ lwz r1, VCPU_HOST_STACK(r4)
++ lwz r3, VCPU_HOST_PID(r4)
++ mtspr SPRN_PID, r3
++
++ /* Restore host IVPR before re-enabling interrupts. We cheat and know
++ * that Linux IVPR is always 0xc0000000. */
++ lis r3, 0xc000
++ mtspr SPRN_IVPR, r3
++
++ /* Switch to kernel stack and jump to handler. */
++ LOAD_REG_ADDR(r3, kvmppc_handle_exit)
++ mtctr r3
++ lwz r3, HOST_RUN(r1)
++ lwz r2, HOST_R2(r1)
++ mr r14, r4 /* Save vcpu pointer. */
++
++ bctrl /* kvmppc_handle_exit() */
++
++ /* Restore vcpu pointer and the nonvolatiles we used. */
++ mr r4, r14
++ lwz r14, VCPU_GPR(r14)(r4)
++
++ /* Sometimes instruction emulation must restore complete GPR state. */
++ andi. r5, r3, RESUME_FLAG_NV
++ beq ..skip_nv_load
++ lwz r15, VCPU_GPR(r15)(r4)
++ lwz r16, VCPU_GPR(r16)(r4)
++ lwz r17, VCPU_GPR(r17)(r4)
++ lwz r18, VCPU_GPR(r18)(r4)
++ lwz r19, VCPU_GPR(r19)(r4)
++ lwz r20, VCPU_GPR(r20)(r4)
++ lwz r21, VCPU_GPR(r21)(r4)
++ lwz r22, VCPU_GPR(r22)(r4)
++ lwz r23, VCPU_GPR(r23)(r4)
++ lwz r24, VCPU_GPR(r24)(r4)
++ lwz r25, VCPU_GPR(r25)(r4)
++ lwz r26, VCPU_GPR(r26)(r4)
++ lwz r27, VCPU_GPR(r27)(r4)
++ lwz r28, VCPU_GPR(r28)(r4)
++ lwz r29, VCPU_GPR(r29)(r4)
++ lwz r30, VCPU_GPR(r30)(r4)
++ lwz r31, VCPU_GPR(r31)(r4)
++..skip_nv_load:
++
++ /* Should we return to the guest? */
++ andi. r5, r3, RESUME_FLAG_HOST
++ beq lightweight_exit
++
++ srawi r3, r3, 2 /* Shift -ERR back down. */
++
++heavyweight_exit:
++ /* Not returning to guest. */
++
++ /* We already saved guest volatile register state; now save the
++ * non-volatiles. */
++ stw r15, VCPU_GPR(r15)(r4)
++ stw r16, VCPU_GPR(r16)(r4)
++ stw r17, VCPU_GPR(r17)(r4)
++ stw r18, VCPU_GPR(r18)(r4)
++ stw r19, VCPU_GPR(r19)(r4)
++ stw r20, VCPU_GPR(r20)(r4)
++ stw r21, VCPU_GPR(r21)(r4)
++ stw r22, VCPU_GPR(r22)(r4)
++ stw r23, VCPU_GPR(r23)(r4)
++ stw r24, VCPU_GPR(r24)(r4)
++ stw r25, VCPU_GPR(r25)(r4)
++ stw r26, VCPU_GPR(r26)(r4)
++ stw r27, VCPU_GPR(r27)(r4)
++ stw r28, VCPU_GPR(r28)(r4)
++ stw r29, VCPU_GPR(r29)(r4)
++ stw r30, VCPU_GPR(r30)(r4)
++ stw r31, VCPU_GPR(r31)(r4)
++
++ /* Load host non-volatile register state from host stack. */
++ lwz r14, HOST_NV_GPR(r14)(r1)
++ lwz r15, HOST_NV_GPR(r15)(r1)
++ lwz r16, HOST_NV_GPR(r16)(r1)
++ lwz r17, HOST_NV_GPR(r17)(r1)
++ lwz r18, HOST_NV_GPR(r18)(r1)
++ lwz r19, HOST_NV_GPR(r19)(r1)
++ lwz r20, HOST_NV_GPR(r20)(r1)
++ lwz r21, HOST_NV_GPR(r21)(r1)
++ lwz r22, HOST_NV_GPR(r22)(r1)
++ lwz r23, HOST_NV_GPR(r23)(r1)
++ lwz r24, HOST_NV_GPR(r24)(r1)
++ lwz r25, HOST_NV_GPR(r25)(r1)
++ lwz r26, HOST_NV_GPR(r26)(r1)
++ lwz r27, HOST_NV_GPR(r27)(r1)
++ lwz r28, HOST_NV_GPR(r28)(r1)
++ lwz r29, HOST_NV_GPR(r29)(r1)
++ lwz r30, HOST_NV_GPR(r30)(r1)
++ lwz r31, HOST_NV_GPR(r31)(r1)
++
++ /* Return to kvm_vcpu_run(). */
++ lwz r4, HOST_STACK_LR(r1)
++ addi r1, r1, HOST_STACK_SIZE
++ mtlr r4
++ /* r3 still contains the return code from kvmppc_handle_exit(). */
++ blr
++
++
++/* Registers:
++ * r3: kvm_run pointer
++ * r4: vcpu pointer
++ */
++_GLOBAL(__kvmppc_vcpu_run)
++ stwu r1, -HOST_STACK_SIZE(r1)
++ stw r1, VCPU_HOST_STACK(r4) /* Save stack pointer to vcpu. */
++
++ /* Save host state to stack. */
++ stw r3, HOST_RUN(r1)
++ mflr r3
++ stw r3, HOST_STACK_LR(r1)
++
++ /* Save host non-volatile register state to stack. */
++ stw r14, HOST_NV_GPR(r14)(r1)
++ stw r15, HOST_NV_GPR(r15)(r1)
++ stw r16, HOST_NV_GPR(r16)(r1)
++ stw r17, HOST_NV_GPR(r17)(r1)
++ stw r18, HOST_NV_GPR(r18)(r1)
++ stw r19, HOST_NV_GPR(r19)(r1)
++ stw r20, HOST_NV_GPR(r20)(r1)
++ stw r21, HOST_NV_GPR(r21)(r1)
++ stw r22, HOST_NV_GPR(r22)(r1)
++ stw r23, HOST_NV_GPR(r23)(r1)
++ stw r24, HOST_NV_GPR(r24)(r1)
++ stw r25, HOST_NV_GPR(r25)(r1)
++ stw r26, HOST_NV_GPR(r26)(r1)
++ stw r27, HOST_NV_GPR(r27)(r1)
++ stw r28, HOST_NV_GPR(r28)(r1)
++ stw r29, HOST_NV_GPR(r29)(r1)
++ stw r30, HOST_NV_GPR(r30)(r1)
++ stw r31, HOST_NV_GPR(r31)(r1)
++
++ /* Load guest non-volatiles. */
++ lwz r14, VCPU_GPR(r14)(r4)
++ lwz r15, VCPU_GPR(r15)(r4)
++ lwz r16, VCPU_GPR(r16)(r4)
++ lwz r17, VCPU_GPR(r17)(r4)
++ lwz r18, VCPU_GPR(r18)(r4)
++ lwz r19, VCPU_GPR(r19)(r4)
++ lwz r20, VCPU_GPR(r20)(r4)
++ lwz r21, VCPU_GPR(r21)(r4)
++ lwz r22, VCPU_GPR(r22)(r4)
++ lwz r23, VCPU_GPR(r23)(r4)
++ lwz r24, VCPU_GPR(r24)(r4)
++ lwz r25, VCPU_GPR(r25)(r4)
++ lwz r26, VCPU_GPR(r26)(r4)
++ lwz r27, VCPU_GPR(r27)(r4)
++ lwz r28, VCPU_GPR(r28)(r4)
++ lwz r29, VCPU_GPR(r29)(r4)
++ lwz r30, VCPU_GPR(r30)(r4)
++ lwz r31, VCPU_GPR(r31)(r4)
++
++lightweight_exit:
++ stw r2, HOST_R2(r1)
++
++ mfspr r3, SPRN_PID
++ stw r3, VCPU_HOST_PID(r4)
++ lwz r3, VCPU_PID(r4)
++ mtspr SPRN_PID, r3
++
++ /* Prevent all TLB updates. */
++ mfmsr r5
++ lis r6, (MSR_EE|MSR_CE|MSR_ME|MSR_DE)@h
++ ori r6, r6, (MSR_EE|MSR_CE|MSR_ME|MSR_DE)@l
++ andc r6, r5, r6
++ mtmsr r6
++
++ /* Save the host's non-pinned TLB mappings, and load the guest mappings
++ * over them. Leave the host's "pinned" kernel mappings in place. */
++ /* XXX optimization: use generation count to avoid swapping unmodified
++ * entries. */
++ mfspr r10, SPRN_MMUCR /* Save host MMUCR. */
++ lis r8, tlb_44x_hwater at ha
++ lwz r8, tlb_44x_hwater at l(r8)
++ addi r3, r4, VCPU_HOST_TLB - 4
++ addi r9, r4, VCPU_SHADOW_TLB - 4
++ li r6, 0
++1:
++ /* Save host entry. */
++ tlbre r7, r6, PPC44x_TLB_PAGEID
++ mfspr r5, SPRN_MMUCR
++ stwu r5, 4(r3)
++ stwu r7, 4(r3)
++ tlbre r7, r6, PPC44x_TLB_XLAT
++ stwu r7, 4(r3)
++ tlbre r7, r6, PPC44x_TLB_ATTRIB
++ stwu r7, 4(r3)
++ /* Load guest entry. */
++ lwzu r7, 4(r9)
++ mtspr SPRN_MMUCR, r7
++ lwzu r7, 4(r9)
++ tlbwe r7, r6, PPC44x_TLB_PAGEID
++ lwzu r7, 4(r9)
++ tlbwe r7, r6, PPC44x_TLB_XLAT
++ lwzu r7, 4(r9)
++ tlbwe r7, r6, PPC44x_TLB_ATTRIB
++ /* Increment index. */
++ addi r6, r6, 1
++ cmpw r6, r8
++ blt 1b
++ mtspr SPRN_MMUCR, r10 /* Restore host MMUCR. */
++
++ iccci 0, 0 /* XXX hack */
++
++ /* Load some guest volatiles. */
++ lwz r0, VCPU_GPR(r0)(r4)
++ lwz r2, VCPU_GPR(r2)(r4)
++ lwz r9, VCPU_GPR(r9)(r4)
++ lwz r10, VCPU_GPR(r10)(r4)
++ lwz r11, VCPU_GPR(r11)(r4)
++ lwz r12, VCPU_GPR(r12)(r4)
++ lwz r13, VCPU_GPR(r13)(r4)
++ lwz r3, VCPU_LR(r4)
++ mtlr r3
++ lwz r3, VCPU_XER(r4)
++ mtxer r3
++
++ /* Switch the IVPR. XXX If we take a TLB miss after this we're screwed,
++ * so how do we make sure vcpu won't fault? */
++ lis r8, kvmppc_booke_handlers at ha
++ lwz r8, kvmppc_booke_handlers at l(r8)
++ mtspr SPRN_IVPR, r8
++
++ /* Save vcpu pointer for the exception handlers. */
++ mtspr SPRN_SPRG1, r4
++
++ /* Can't switch the stack pointer until after IVPR is switched,
++ * because host interrupt handlers would get confused. */
++ lwz r1, VCPU_GPR(r1)(r4)
++
++ /* XXX handle USPRG0 */
++ /* Host interrupt handlers may have clobbered these guest-readable
++ * SPRGs, so we need to reload them here with the guest's values. */
++ lwz r3, VCPU_SPRG4(r4)
++ mtspr SPRN_SPRG4, r3
++ lwz r3, VCPU_SPRG5(r4)
++ mtspr SPRN_SPRG5, r3
++ lwz r3, VCPU_SPRG6(r4)
++ mtspr SPRN_SPRG6, r3
++ lwz r3, VCPU_SPRG7(r4)
++ mtspr SPRN_SPRG7, r3
++
++ /* Finish loading guest volatiles and jump to guest. */
++ lwz r3, VCPU_CTR(r4)
++ mtctr r3
++ lwz r3, VCPU_CR(r4)
++ mtcr r3
++ lwz r5, VCPU_GPR(r5)(r4)
++ lwz r6, VCPU_GPR(r6)(r4)
++ lwz r7, VCPU_GPR(r7)(r4)
++ lwz r8, VCPU_GPR(r8)(r4)
++ lwz r3, VCPU_PC(r4)
++ mtsrr0 r3
++ lwz r3, VCPU_MSR(r4)
++ oris r3, r3, KVMPPC_MSR_MASK at h
++ ori r3, r3, KVMPPC_MSR_MASK at l
++ mtsrr1 r3
++ lwz r3, VCPU_GPR(r3)(r4)
++ lwz r4, VCPU_GPR(r4)(r4)
++ rfi
+diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
+new file mode 100644
+index 0000000..a03fe0c
+--- /dev/null
++++ b/arch/powerpc/kvm/emulate.c
+@@ -0,0 +1,760 @@
++/*
++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * Copyright IBM Corp. 2007
++ *
++ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ */
++
++#include <linux/jiffies.h>
++#include <linux/timer.h>
++#include <linux/types.h>
++#include <linux/string.h>
++#include <linux/kvm_host.h>
++
++#include <asm/dcr.h>
++#include <asm/dcr-regs.h>
++#include <asm/time.h>
++#include <asm/byteorder.h>
++#include <asm/kvm_ppc.h>
++
++#include "44x_tlb.h"
++
++/* Instruction decoding */
++static inline unsigned int get_op(u32 inst)
++{
++ return inst >> 26;
++}
++
++static inline unsigned int get_xop(u32 inst)
++{
++ return (inst >> 1) & 0x3ff;
++}
++
++static inline unsigned int get_sprn(u32 inst)
++{
++ return ((inst >> 16) & 0x1f) | ((inst >> 6) & 0x3e0);
++}
++
++static inline unsigned int get_dcrn(u32 inst)
++{
++ return ((inst >> 16) & 0x1f) | ((inst >> 6) & 0x3e0);
++}
++
++static inline unsigned int get_rt(u32 inst)
++{
++ return (inst >> 21) & 0x1f;
++}
++
++static inline unsigned int get_rs(u32 inst)
++{
++ return (inst >> 21) & 0x1f;
++}
++
++static inline unsigned int get_ra(u32 inst)
++{
++ return (inst >> 16) & 0x1f;
++}
++
++static inline unsigned int get_rb(u32 inst)
++{
++ return (inst >> 11) & 0x1f;
++}
++
++static inline unsigned int get_rc(u32 inst)
++{
++ return inst & 0x1;
++}
++
++static inline unsigned int get_ws(u32 inst)
++{
++ return (inst >> 11) & 0x1f;
++}
++
++static inline unsigned int get_d(u32 inst)
++{
++ return inst & 0xffff;
++}
++
++static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,
++ const struct tlbe *tlbe)
++{
++ gpa_t gpa;
++
++ if (!get_tlb_v(tlbe))
++ return 0;
++
++ /* Does it match current guest AS? */
++ /* XXX what about IS != DS? */
++ if (get_tlb_ts(tlbe) != !!(vcpu->arch.msr & MSR_IS))
++ return 0;
++
++ gpa = get_tlb_raddr(tlbe);
++ if (!gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT))
++ /* Mapping is not for RAM. */
++ return 0;
++
++ return 1;
++}
++
++static int kvmppc_emul_tlbwe(struct kvm_vcpu *vcpu, u32 inst)
++{
++ u64 eaddr;
++ u64 raddr;
++ u64 asid;
++ u32 flags;
++ struct tlbe *tlbe;
++ unsigned int ra;
++ unsigned int rs;
++ unsigned int ws;
++ unsigned int index;
++
++ ra = get_ra(inst);
++ rs = get_rs(inst);
++ ws = get_ws(inst);
++
++ index = vcpu->arch.gpr[ra];
++ if (index > PPC44x_TLB_SIZE) {
++ printk("%s: index %d\n", __func__, index);
++ kvmppc_dump_vcpu(vcpu);
++ return EMULATE_FAIL;
++ }
++
++ tlbe = &vcpu->arch.guest_tlb[index];
++
++ /* Invalidate shadow mappings for the about-to-be-clobbered TLBE. */
++ if (tlbe->word0 & PPC44x_TLB_VALID) {
++ eaddr = get_tlb_eaddr(tlbe);
++ asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid;
++ kvmppc_mmu_invalidate(vcpu, eaddr, asid);
++ }
++
++ switch (ws) {
++ case PPC44x_TLB_PAGEID:
++ tlbe->tid = vcpu->arch.mmucr & 0xff;
++ tlbe->word0 = vcpu->arch.gpr[rs];
++ break;
++
++ case PPC44x_TLB_XLAT:
++ tlbe->word1 = vcpu->arch.gpr[rs];
++ break;
++
++ case PPC44x_TLB_ATTRIB:
++ tlbe->word2 = vcpu->arch.gpr[rs];
++ break;
++
++ default:
++ return EMULATE_FAIL;
++ }
++
++ if (tlbe_is_host_safe(vcpu, tlbe)) {
++ eaddr = get_tlb_eaddr(tlbe);
++ raddr = get_tlb_raddr(tlbe);
++ asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid;
++ flags = tlbe->word2 & 0xffff;
++
++ /* Create a 4KB mapping on the host. If the guest wanted a
++ * large page, only the first 4KB is mapped here and the rest
++ * are mapped on the fly. */
++ kvmppc_mmu_map(vcpu, eaddr, raddr >> PAGE_SHIFT, asid, flags);
++ }
++
++ return EMULATE_DONE;
++}
++
++static void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
++{
++ if (vcpu->arch.tcr & TCR_DIE) {
++ /* The decrementer ticks at the same rate as the timebase, so
++ * that's how we convert the guest DEC value to the number of
++ * host ticks. */
++ unsigned long nr_jiffies;
++
++ nr_jiffies = vcpu->arch.dec / tb_ticks_per_jiffy;
++ mod_timer(&vcpu->arch.dec_timer,
++ get_jiffies_64() + nr_jiffies);
++ } else {
++ del_timer(&vcpu->arch.dec_timer);
++ }
++}
++
++static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu)
++{
++ vcpu->arch.pc = vcpu->arch.srr0;
++ kvmppc_set_msr(vcpu, vcpu->arch.srr1);
++}
++
++/* XXX to do:
++ * lhax
++ * lhaux
++ * lswx
++ * lswi
++ * stswx
++ * stswi
++ * lha
++ * lhau
++ * lmw
++ * stmw
++ *
++ * XXX is_bigendian should depend on MMU mapping or MSR[LE]
++ */
++int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
++{
++ u32 inst = vcpu->arch.last_inst;
++ u32 ea;
++ int ra;
++ int rb;
++ int rc;
++ int rs;
++ int rt;
++ int sprn;
++ int dcrn;
++ enum emulation_result emulated = EMULATE_DONE;
++ int advance = 1;
++
++ switch (get_op(inst)) {
++ case 3: /* trap */
++ printk("trap!\n");
++ kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM);
++ advance = 0;
++ break;
++
++ case 19:
++ switch (get_xop(inst)) {
++ case 50: /* rfi */
++ kvmppc_emul_rfi(vcpu);
++ advance = 0;
++ break;
++
++ default:
++ emulated = EMULATE_FAIL;
++ break;
++ }
++ break;
++
++ case 31:
++ switch (get_xop(inst)) {
++
++ case 83: /* mfmsr */
++ rt = get_rt(inst);
++ vcpu->arch.gpr[rt] = vcpu->arch.msr;
++ break;
++
++ case 87: /* lbzx */
++ rt = get_rt(inst);
++ emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
++ break;
++
++ case 131: /* wrtee */
++ rs = get_rs(inst);
++ vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
++ | (vcpu->arch.gpr[rs] & MSR_EE);
++ break;
++
++ case 146: /* mtmsr */
++ rs = get_rs(inst);
++ kvmppc_set_msr(vcpu, vcpu->arch.gpr[rs]);
++ break;
++
++ case 163: /* wrteei */
++ vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
++ | (inst & MSR_EE);
++ break;
++
++ case 215: /* stbx */
++ rs = get_rs(inst);
++ emulated = kvmppc_handle_store(run, vcpu,
++ vcpu->arch.gpr[rs],
++ 1, 1);
++ break;
++
++ case 247: /* stbux */
++ rs = get_rs(inst);
++ ra = get_ra(inst);
++ rb = get_rb(inst);
++
++ ea = vcpu->arch.gpr[rb];
++ if (ra)
++ ea += vcpu->arch.gpr[ra];
++
++ emulated = kvmppc_handle_store(run, vcpu,
++ vcpu->arch.gpr[rs],
++ 1, 1);
++ vcpu->arch.gpr[rs] = ea;
++ break;
++
++ case 279: /* lhzx */
++ rt = get_rt(inst);
++ emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
++ break;
++
++ case 311: /* lhzux */
++ rt = get_rt(inst);
++ ra = get_ra(inst);
++ rb = get_rb(inst);
++
++ ea = vcpu->arch.gpr[rb];
++ if (ra)
++ ea += vcpu->arch.gpr[ra];
++
++ emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
++ vcpu->arch.gpr[ra] = ea;
++ break;
++
++ case 323: /* mfdcr */
++ dcrn = get_dcrn(inst);
++ rt = get_rt(inst);
++
++ /* The guest may access CPR0 registers to determine the timebase
++ * frequency, and it must know the real host frequency because it
++ * can directly access the timebase registers.
++ *
++ * It would be possible to emulate those accesses in userspace,
++ * but userspace can really only figure out the end frequency.
++ * We could decompose that into the factors that compute it, but
++ * that's tricky math, and it's easier to just report the real
++ * CPR0 values.
++ */
++ switch (dcrn) {
++ case DCRN_CPR0_CONFIG_ADDR:
++ vcpu->arch.gpr[rt] = vcpu->arch.cpr0_cfgaddr;
++ break;
++ case DCRN_CPR0_CONFIG_DATA:
++ local_irq_disable();
++ mtdcr(DCRN_CPR0_CONFIG_ADDR,
++ vcpu->arch.cpr0_cfgaddr);
++ vcpu->arch.gpr[rt] = mfdcr(DCRN_CPR0_CONFIG_DATA);
++ local_irq_enable();
++ break;
++ default:
++ run->dcr.dcrn = dcrn;
++ run->dcr.data = 0;
++ run->dcr.is_write = 0;
++ vcpu->arch.io_gpr = rt;
++ vcpu->arch.dcr_needed = 1;
++ emulated = EMULATE_DO_DCR;
++ }
++
++ break;
++
++ case 339: /* mfspr */
++ sprn = get_sprn(inst);
++ rt = get_rt(inst);
++
++ switch (sprn) {
++ case SPRN_SRR0:
++ vcpu->arch.gpr[rt] = vcpu->arch.srr0; break;
++ case SPRN_SRR1:
++ vcpu->arch.gpr[rt] = vcpu->arch.srr1; break;
++ case SPRN_MMUCR:
++ vcpu->arch.gpr[rt] = vcpu->arch.mmucr; break;
++ case SPRN_PID:
++ vcpu->arch.gpr[rt] = vcpu->arch.pid; break;
++ case SPRN_IVPR:
++ vcpu->arch.gpr[rt] = vcpu->arch.ivpr; break;
++ case SPRN_CCR0:
++ vcpu->arch.gpr[rt] = vcpu->arch.ccr0; break;
++ case SPRN_CCR1:
++ vcpu->arch.gpr[rt] = vcpu->arch.ccr1; break;
++ case SPRN_PVR:
++ vcpu->arch.gpr[rt] = vcpu->arch.pvr; break;
++ case SPRN_DEAR:
++ vcpu->arch.gpr[rt] = vcpu->arch.dear; break;
++ case SPRN_ESR:
++ vcpu->arch.gpr[rt] = vcpu->arch.esr; break;
++ case SPRN_DBCR0:
++ vcpu->arch.gpr[rt] = vcpu->arch.dbcr0; break;
++ case SPRN_DBCR1:
++ vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break;
++
++ /* Note: mftb and TBRL/TBWL are user-accessible, so
++ * the guest can always access the real TB anyways.
++ * In fact, we probably will never see these traps. */
++ case SPRN_TBWL:
++ vcpu->arch.gpr[rt] = mftbl(); break;
++ case SPRN_TBWU:
++ vcpu->arch.gpr[rt] = mftbu(); break;
++
++ case SPRN_SPRG0:
++ vcpu->arch.gpr[rt] = vcpu->arch.sprg0; break;
++ case SPRN_SPRG1:
++ vcpu->arch.gpr[rt] = vcpu->arch.sprg1; break;
++ case SPRN_SPRG2:
++ vcpu->arch.gpr[rt] = vcpu->arch.sprg2; break;
++ case SPRN_SPRG3:
++ vcpu->arch.gpr[rt] = vcpu->arch.sprg3; break;
++ /* Note: SPRG4-7 are user-readable, so we don't get
++ * a trap. */
++
++ case SPRN_IVOR0:
++ vcpu->arch.gpr[rt] = vcpu->arch.ivor[0]; break;
++ case SPRN_IVOR1:
++ vcpu->arch.gpr[rt] = vcpu->arch.ivor[1]; break;
++ case SPRN_IVOR2:
++ vcpu->arch.gpr[rt] = vcpu->arch.ivor[2]; break;
++ case SPRN_IVOR3:
++ vcpu->arch.gpr[rt] = vcpu->arch.ivor[3]; break;
++ case SPRN_IVOR4:
++ vcpu->arch.gpr[rt] = vcpu->arch.ivor[4]; break;
++ case SPRN_IVOR5:
++ vcpu->arch.gpr[rt] = vcpu->arch.ivor[5]; break;
++ case SPRN_IVOR6:
++ vcpu->arch.gpr[rt] = vcpu->arch.ivor[6]; break;
++ case SPRN_IVOR7:
++ vcpu->arch.gpr[rt] = vcpu->arch.ivor[7]; break;
++ case SPRN_IVOR8:
++ vcpu->arch.gpr[rt] = vcpu->arch.ivor[8]; break;
++ case SPRN_IVOR9:
++ vcpu->arch.gpr[rt] = vcpu->arch.ivor[9]; break;
++ case SPRN_IVOR10:
++ vcpu->arch.gpr[rt] = vcpu->arch.ivor[10]; break;
++ case SPRN_IVOR11:
++ vcpu->arch.gpr[rt] = vcpu->arch.ivor[11]; break;
++ case SPRN_IVOR12:
++ vcpu->arch.gpr[rt] = vcpu->arch.ivor[12]; break;
++ case SPRN_IVOR13:
++ vcpu->arch.gpr[rt] = vcpu->arch.ivor[13]; break;
++ case SPRN_IVOR14:
++ vcpu->arch.gpr[rt] = vcpu->arch.ivor[14]; break;
++ case SPRN_IVOR15:
++ vcpu->arch.gpr[rt] = vcpu->arch.ivor[15]; break;
++
++ default:
++ printk("mfspr: unknown spr %x\n", sprn);
++ vcpu->arch.gpr[rt] = 0;
++ break;
++ }
++ break;
++
++ case 407: /* sthx */
++ rs = get_rs(inst);
++ ra = get_ra(inst);
++ rb = get_rb(inst);
++
++ emulated = kvmppc_handle_store(run, vcpu,
++ vcpu->arch.gpr[rs],
++ 2, 1);
++ break;
++
++ case 439: /* sthux */
++ rs = get_rs(inst);
++ ra = get_ra(inst);
++ rb = get_rb(inst);
++
++ ea = vcpu->arch.gpr[rb];
++ if (ra)
++ ea += vcpu->arch.gpr[ra];
++
++ emulated = kvmppc_handle_store(run, vcpu,
++ vcpu->arch.gpr[rs],
++ 2, 1);
++ vcpu->arch.gpr[ra] = ea;
++ break;
++
++ case 451: /* mtdcr */
++ dcrn = get_dcrn(inst);
++ rs = get_rs(inst);
++
++ /* emulate some access in kernel */
++ switch (dcrn) {
++ case DCRN_CPR0_CONFIG_ADDR:
++ vcpu->arch.cpr0_cfgaddr = vcpu->arch.gpr[rs];
++ break;
++ default:
++ run->dcr.dcrn = dcrn;
++ run->dcr.data = vcpu->arch.gpr[rs];
++ run->dcr.is_write = 1;
++ vcpu->arch.dcr_needed = 1;
++ emulated = EMULATE_DO_DCR;
++ }
++
++ break;
++
++ case 467: /* mtspr */
++ sprn = get_sprn(inst);
++ rs = get_rs(inst);
++ switch (sprn) {
++ case SPRN_SRR0:
++ vcpu->arch.srr0 = vcpu->arch.gpr[rs]; break;
++ case SPRN_SRR1:
++ vcpu->arch.srr1 = vcpu->arch.gpr[rs]; break;
++ case SPRN_MMUCR:
++ vcpu->arch.mmucr = vcpu->arch.gpr[rs]; break;
++ case SPRN_PID:
++ vcpu->arch.pid = vcpu->arch.gpr[rs]; break;
++ case SPRN_CCR0:
++ vcpu->arch.ccr0 = vcpu->arch.gpr[rs]; break;
++ case SPRN_CCR1:
++ vcpu->arch.ccr1 = vcpu->arch.gpr[rs]; break;
++ case SPRN_DEAR:
++ vcpu->arch.dear = vcpu->arch.gpr[rs]; break;
++ case SPRN_ESR:
++ vcpu->arch.esr = vcpu->arch.gpr[rs]; break;
++ case SPRN_DBCR0:
++ vcpu->arch.dbcr0 = vcpu->arch.gpr[rs]; break;
++ case SPRN_DBCR1:
++ vcpu->arch.dbcr1 = vcpu->arch.gpr[rs]; break;
++
++ /* XXX We need to context-switch the timebase for
++ * watchdog and FIT. */
++ case SPRN_TBWL: break;
++ case SPRN_TBWU: break;
++
++ case SPRN_DEC:
++ vcpu->arch.dec = vcpu->arch.gpr[rs];
++ kvmppc_emulate_dec(vcpu);
++ break;
++
++ case SPRN_TSR:
++ vcpu->arch.tsr &= ~vcpu->arch.gpr[rs]; break;
++
++ case SPRN_TCR:
++ vcpu->arch.tcr = vcpu->arch.gpr[rs];
++ kvmppc_emulate_dec(vcpu);
++ break;
++
++ case SPRN_SPRG0:
++ vcpu->arch.sprg0 = vcpu->arch.gpr[rs]; break;
++ case SPRN_SPRG1:
++ vcpu->arch.sprg1 = vcpu->arch.gpr[rs]; break;
++ case SPRN_SPRG2:
++ vcpu->arch.sprg2 = vcpu->arch.gpr[rs]; break;
++ case SPRN_SPRG3:
++ vcpu->arch.sprg3 = vcpu->arch.gpr[rs]; break;
++
++ /* Note: SPRG4-7 are user-readable. These values are
++ * loaded into the real SPRGs when resuming the
++ * guest. */
++ case SPRN_SPRG4:
++ vcpu->arch.sprg4 = vcpu->arch.gpr[rs]; break;
++ case SPRN_SPRG5:
++ vcpu->arch.sprg5 = vcpu->arch.gpr[rs]; break;
++ case SPRN_SPRG6:
++ vcpu->arch.sprg6 = vcpu->arch.gpr[rs]; break;
++ case SPRN_SPRG7:
++ vcpu->arch.sprg7 = vcpu->arch.gpr[rs]; break;
++
++ case SPRN_IVPR:
++ vcpu->arch.ivpr = vcpu->arch.gpr[rs]; break;
++ case SPRN_IVOR0:
++ vcpu->arch.ivor[0] = vcpu->arch.gpr[rs]; break;
++ case SPRN_IVOR1:
++ vcpu->arch.ivor[1] = vcpu->arch.gpr[rs]; break;
++ case SPRN_IVOR2:
++ vcpu->arch.ivor[2] = vcpu->arch.gpr[rs]; break;
++ case SPRN_IVOR3:
++ vcpu->arch.ivor[3] = vcpu->arch.gpr[rs]; break;
++ case SPRN_IVOR4:
++ vcpu->arch.ivor[4] = vcpu->arch.gpr[rs]; break;
++ case SPRN_IVOR5:
++ vcpu->arch.ivor[5] = vcpu->arch.gpr[rs]; break;
++ case SPRN_IVOR6:
++ vcpu->arch.ivor[6] = vcpu->arch.gpr[rs]; break;
++ case SPRN_IVOR7:
++ vcpu->arch.ivor[7] = vcpu->arch.gpr[rs]; break;
++ case SPRN_IVOR8:
++ vcpu->arch.ivor[8] = vcpu->arch.gpr[rs]; break;
++ case SPRN_IVOR9:
++ vcpu->arch.ivor[9] = vcpu->arch.gpr[rs]; break;
++ case SPRN_IVOR10:
++ vcpu->arch.ivor[10] = vcpu->arch.gpr[rs]; break;
++ case SPRN_IVOR11:
++ vcpu->arch.ivor[11] = vcpu->arch.gpr[rs]; break;
++ case SPRN_IVOR12:
++ vcpu->arch.ivor[12] = vcpu->arch.gpr[rs]; break;
++ case SPRN_IVOR13:
++ vcpu->arch.ivor[13] = vcpu->arch.gpr[rs]; break;
++ case SPRN_IVOR14:
++ vcpu->arch.ivor[14] = vcpu->arch.gpr[rs]; break;
++ case SPRN_IVOR15:
++ vcpu->arch.ivor[15] = vcpu->arch.gpr[rs]; break;
++
++ default:
++ printk("mtspr: unknown spr %x\n", sprn);
++ emulated = EMULATE_FAIL;
++ break;
++ }
++ break;
++
++ case 470: /* dcbi */
++ /* Do nothing. The guest is performing dcbi because
++ * hardware DMA is not snooped by the dcache, but
++ * emulated DMA either goes through the dcache as
++ * normal writes, or the host kernel has handled dcache
++ * coherence. */
++ break;
++
++ case 534: /* lwbrx */
++ rt = get_rt(inst);
++ emulated = kvmppc_handle_load(run, vcpu, rt, 4, 0);
++ break;
++
++ case 566: /* tlbsync */
++ break;
++
++ case 662: /* stwbrx */
++ rs = get_rs(inst);
++ ra = get_ra(inst);
++ rb = get_rb(inst);
++
++ emulated = kvmppc_handle_store(run, vcpu,
++ vcpu->arch.gpr[rs],
++ 4, 0);
++ break;
++
++ case 978: /* tlbwe */
++ emulated = kvmppc_emul_tlbwe(vcpu, inst);
++ break;
++
++ case 914: { /* tlbsx */
++ int index;
++ unsigned int as = get_mmucr_sts(vcpu);
++ unsigned int pid = get_mmucr_stid(vcpu);
++
++ rt = get_rt(inst);
++ ra = get_ra(inst);
++ rb = get_rb(inst);
++ rc = get_rc(inst);
++
++ ea = vcpu->arch.gpr[rb];
++ if (ra)
++ ea += vcpu->arch.gpr[ra];
++
++ index = kvmppc_44x_tlb_index(vcpu, ea, pid, as);
++ if (rc) {
++ if (index < 0)
++ vcpu->arch.cr &= ~0x20000000;
++ else
++ vcpu->arch.cr |= 0x20000000;
++ }
++ vcpu->arch.gpr[rt] = index;
++
++ }
++ break;
++
++ case 790: /* lhbrx */
++ rt = get_rt(inst);
++ emulated = kvmppc_handle_load(run, vcpu, rt, 2, 0);
++ break;
++
++ case 918: /* sthbrx */
++ rs = get_rs(inst);
++ ra = get_ra(inst);
++ rb = get_rb(inst);
++
++ emulated = kvmppc_handle_store(run, vcpu,
++ vcpu->arch.gpr[rs],
++ 2, 0);
++ break;
++
++ case 966: /* iccci */
++ break;
++
++ default:
++ printk("unknown: op %d xop %d\n", get_op(inst),
++ get_xop(inst));
++ emulated = EMULATE_FAIL;
++ break;
++ }
++ break;
++
++ case 32: /* lwz */
++ rt = get_rt(inst);
++ emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
++ break;
++
++ case 33: /* lwzu */
++ ra = get_ra(inst);
++ rt = get_rt(inst);
++ emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
++ vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
++ break;
++
++ case 34: /* lbz */
++ rt = get_rt(inst);
++ emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
++ break;
++
++ case 35: /* lbzu */
++ ra = get_ra(inst);
++ rt = get_rt(inst);
++ emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
++ vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
++ break;
++
++ case 36: /* stw */
++ rs = get_rs(inst);
++ emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
++ 4, 1);
++ break;
++
++ case 37: /* stwu */
++ ra = get_ra(inst);
++ rs = get_rs(inst);
++ emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
++ 4, 1);
++ vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
++ break;
++
++ case 38: /* stb */
++ rs = get_rs(inst);
++ emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
++ 1, 1);
++ break;
++
++ case 39: /* stbu */
++ ra = get_ra(inst);
++ rs = get_rs(inst);
++ emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
++ 1, 1);
++ vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
++ break;
++
++ case 40: /* lhz */
++ rt = get_rt(inst);
++ emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
++ break;
++
++ case 41: /* lhzu */
++ ra = get_ra(inst);
++ rt = get_rt(inst);
++ emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
++ vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
++ break;
++
++ case 44: /* sth */
++ rs = get_rs(inst);
++ emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
++ 2, 1);
++ break;
++
++ case 45: /* sthu */
++ ra = get_ra(inst);
++ rs = get_rs(inst);
++ emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
++ 2, 1);
++ vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
++ break;
++
++ default:
++ printk("unknown op %d\n", get_op(inst));
++ emulated = EMULATE_FAIL;
++ break;
++ }
++
++ if (advance)
++ vcpu->arch.pc += 4; /* Advance past emulated instruction. */
++
++ return emulated;
++}
+diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
+new file mode 100644
+index 0000000..bad40bd
+--- /dev/null
++++ b/arch/powerpc/kvm/powerpc.c
+@@ -0,0 +1,436 @@
++/*
++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * Copyright IBM Corp. 2007
++ *
++ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ * Christian Ehrhardt <ehrhardt at linux.vnet.ibm.com>
++ */
++
++#include <linux/errno.h>
++#include <linux/err.h>
++#include <linux/kvm_host.h>
++#include <linux/module.h>
++#include <linux/vmalloc.h>
++#include <linux/fs.h>
++#include <asm/cputable.h>
++#include <asm/uaccess.h>
++#include <asm/kvm_ppc.h>
++
++
++gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
++{
++ return gfn;
++}
++
++int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
++{
++ /* XXX implement me */
++ return 0;
++}
++
++int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
++{
++ return 1;
++}
++
++
++int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu)
++{
++ enum emulation_result er;
++ int r;
++
++ er = kvmppc_emulate_instruction(run, vcpu);
++ switch (er) {
++ case EMULATE_DONE:
++ /* Future optimization: only reload non-volatiles if they were
++ * actually modified. */
++ r = RESUME_GUEST_NV;
++ break;
++ case EMULATE_DO_MMIO:
++ run->exit_reason = KVM_EXIT_MMIO;
++ /* We must reload nonvolatiles because "update" load/store
++ * instructions modify register state. */
++ /* Future optimization: only reload non-volatiles if they were
++ * actually modified. */
++ r = RESUME_HOST_NV;
++ break;
++ case EMULATE_FAIL:
++ /* XXX Deliver Program interrupt to guest. */
++ printk(KERN_EMERG "%s: emulation failed (%08x)\n", __func__,
++ vcpu->arch.last_inst);
++ r = RESUME_HOST;
++ break;
++ default:
++ BUG();
++ }
++
++ return r;
++}
++
++void kvm_arch_hardware_enable(void *garbage)
++{
++}
++
++void kvm_arch_hardware_disable(void *garbage)
++{
++}
++
++int kvm_arch_hardware_setup(void)
++{
++ return 0;
++}
++
++void kvm_arch_hardware_unsetup(void)
++{
++}
++
++void kvm_arch_check_processor_compat(void *rtn)
++{
++ int r;
++
++ if (strcmp(cur_cpu_spec->platform, "ppc440") == 0)
++ r = 0;
++ else
++ r = -ENOTSUPP;
++
++ *(int *)rtn = r;
++}
++
++struct kvm *kvm_arch_create_vm(void)
++{
++ struct kvm *kvm;
++
++ kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL);
++ if (!kvm)
++ return ERR_PTR(-ENOMEM);
++
++ return kvm;
++}
++
++static void kvmppc_free_vcpus(struct kvm *kvm)
++{
++ unsigned int i;
++
++ for (i = 0; i < KVM_MAX_VCPUS; ++i) {
++ if (kvm->vcpus[i]) {
++ kvm_arch_vcpu_free(kvm->vcpus[i]);
++ kvm->vcpus[i] = NULL;
++ }
++ }
++}
++
++void kvm_arch_destroy_vm(struct kvm *kvm)
++{
++ kvmppc_free_vcpus(kvm);
++ kvm_free_physmem(kvm);
++ kfree(kvm);
++}
++
++int kvm_dev_ioctl_check_extension(long ext)
++{
++ int r;
++
++ switch (ext) {
++ case KVM_CAP_USER_MEMORY:
++ r = 1;
++ break;
++ default:
++ r = 0;
++ break;
++ }
++ return r;
++
++}
++
++long kvm_arch_dev_ioctl(struct file *filp,
++ unsigned int ioctl, unsigned long arg)
++{
++ return -EINVAL;
++}
++
++int kvm_arch_set_memory_region(struct kvm *kvm,
++ struct kvm_userspace_memory_region *mem,
++ struct kvm_memory_slot old,
++ int user_alloc)
++{
++ return 0;
++}
++
++struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
++{
++ struct kvm_vcpu *vcpu;
++ int err;
++
++ vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
++ if (!vcpu) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ err = kvm_vcpu_init(vcpu, kvm, id);
++ if (err)
++ goto free_vcpu;
++
++ return vcpu;
++
++free_vcpu:
++ kmem_cache_free(kvm_vcpu_cache, vcpu);
++out:
++ return ERR_PTR(err);
++}
++
++void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
++{
++ kvm_vcpu_uninit(vcpu);
++ kmem_cache_free(kvm_vcpu_cache, vcpu);
++}
++
++void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
++{
++ kvm_arch_vcpu_free(vcpu);
++}
++
++int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
++{
++ unsigned int priority = exception_priority[BOOKE_INTERRUPT_DECREMENTER];
++
++ return test_bit(priority, &vcpu->arch.pending_exceptions);
++}
++
++static void kvmppc_decrementer_func(unsigned long data)
++{
++ struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
++
++ kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_DECREMENTER);
++}
++
++int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
++{
++ setup_timer(&vcpu->arch.dec_timer, kvmppc_decrementer_func,
++ (unsigned long)vcpu);
++
++ return 0;
++}
++
++void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
++{
++}
++
++void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
++{
++}
++
++void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
++{
++}
++
++void decache_vcpus_on_cpu(int cpu)
++{
++}
++
++int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
++ struct kvm_debug_guest *dbg)
++{
++ return -ENOTSUPP;
++}
++
++static void kvmppc_complete_dcr_load(struct kvm_vcpu *vcpu,
++ struct kvm_run *run)
++{
++ u32 *gpr = &vcpu->arch.gpr[vcpu->arch.io_gpr];
++ *gpr = run->dcr.data;
++}
++
++static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,
++ struct kvm_run *run)
++{
++ u32 *gpr = &vcpu->arch.gpr[vcpu->arch.io_gpr];
++
++ if (run->mmio.len > sizeof(*gpr)) {
++ printk(KERN_ERR "bad MMIO length: %d\n", run->mmio.len);
++ return;
++ }
++
++ if (vcpu->arch.mmio_is_bigendian) {
++ switch (run->mmio.len) {
++ case 4: *gpr = *(u32 *)run->mmio.data; break;
++ case 2: *gpr = *(u16 *)run->mmio.data; break;
++ case 1: *gpr = *(u8 *)run->mmio.data; break;
++ }
++ } else {
++ /* Convert BE data from userland back to LE. */
++ switch (run->mmio.len) {
++ case 4: *gpr = ld_le32((u32 *)run->mmio.data); break;
++ case 2: *gpr = ld_le16((u16 *)run->mmio.data); break;
++ case 1: *gpr = *(u8 *)run->mmio.data; break;
++ }
++ }
++}
++
++int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
++ unsigned int rt, unsigned int bytes, int is_bigendian)
++{
++ if (bytes > sizeof(run->mmio.data)) {
++ printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__,
++ run->mmio.len);
++ }
++
++ run->mmio.phys_addr = vcpu->arch.paddr_accessed;
++ run->mmio.len = bytes;
++ run->mmio.is_write = 0;
++
++ vcpu->arch.io_gpr = rt;
++ vcpu->arch.mmio_is_bigendian = is_bigendian;
++ vcpu->mmio_needed = 1;
++ vcpu->mmio_is_write = 0;
++
++ return EMULATE_DO_MMIO;
++}
++
++int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
++ u32 val, unsigned int bytes, int is_bigendian)
++{
++ void *data = run->mmio.data;
++
++ if (bytes > sizeof(run->mmio.data)) {
++ printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__,
++ run->mmio.len);
++ }
++
++ run->mmio.phys_addr = vcpu->arch.paddr_accessed;
++ run->mmio.len = bytes;
++ run->mmio.is_write = 1;
++ vcpu->mmio_needed = 1;
++ vcpu->mmio_is_write = 1;
++
++ /* Store the value at the lowest bytes in 'data'. */
++ if (is_bigendian) {
++ switch (bytes) {
++ case 4: *(u32 *)data = val; break;
++ case 2: *(u16 *)data = val; break;
++ case 1: *(u8 *)data = val; break;
++ }
++ } else {
++ /* Store LE value into 'data'. */
++ switch (bytes) {
++ case 4: st_le32(data, val); break;
++ case 2: st_le16(data, val); break;
++ case 1: *(u8 *)data = val; break;
++ }
++ }
++
++ return EMULATE_DO_MMIO;
++}
++
++int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
++{
++ int r;
++ sigset_t sigsaved;
++
++ if (vcpu->sigset_active)
++ sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
++
++ if (vcpu->mmio_needed) {
++ if (!vcpu->mmio_is_write)
++ kvmppc_complete_mmio_load(vcpu, run);
++ vcpu->mmio_needed = 0;
++ } else if (vcpu->arch.dcr_needed) {
++ if (!vcpu->arch.dcr_is_write)
++ kvmppc_complete_dcr_load(vcpu, run);
++ vcpu->arch.dcr_needed = 0;
++ }
++
++ kvmppc_check_and_deliver_interrupts(vcpu);
++
++ local_irq_disable();
++ kvm_guest_enter();
++ r = __kvmppc_vcpu_run(run, vcpu);
++ kvm_guest_exit();
++ local_irq_enable();
++
++ if (vcpu->sigset_active)
++ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
++
++ return r;
++}
++
++int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
++{
++ kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_EXTERNAL);
++ return 0;
++}
++
++int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
++ struct kvm_mp_state *mp_state)
++{
++ return -EINVAL;
++}
++
++int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
++ struct kvm_mp_state *mp_state)
++{
++ return -EINVAL;
++}
++
++long kvm_arch_vcpu_ioctl(struct file *filp,
++ unsigned int ioctl, unsigned long arg)
++{
++ struct kvm_vcpu *vcpu = filp->private_data;
++ void __user *argp = (void __user *)arg;
++ long r;
++
++ switch (ioctl) {
++ case KVM_INTERRUPT: {
++ struct kvm_interrupt irq;
++ r = -EFAULT;
++ if (copy_from_user(&irq, argp, sizeof(irq)))
++ goto out;
++ r = kvm_vcpu_ioctl_interrupt(vcpu, &irq);
++ break;
++ }
++ default:
++ r = -EINVAL;
++ }
++
++out:
++ return r;
++}
++
++int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
++{
++ return -ENOTSUPP;
++}
++
++long kvm_arch_vm_ioctl(struct file *filp,
++ unsigned int ioctl, unsigned long arg)
++{
++ long r;
++
++ switch (ioctl) {
++ default:
++ r = -EINVAL;
++ }
++
++ return r;
++}
++
++int kvm_arch_init(void *opaque)
++{
++ return 0;
++}
++
++void kvm_arch_exit(void)
++{
++}
diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c
index 22c3b4f..29b2941 100644
--- a/arch/powerpc/lib/rheap.c
@@ -189025,7 +230643,7 @@
- return 0;
-}
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
-index be5c506..5ccb579 100644
+index be5c506..f67e118 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -31,6 +31,7 @@
@@ -189068,7 +230686,23 @@
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)
+@@ -95,15 +110,6 @@ EXPORT_SYMBOL(phys_mem_access_prot);
+
+ #ifdef CONFIG_MEMORY_HOTPLUG
+
+-void online_page(struct page *page)
+-{
+- ClearPageReserved(page);
+- init_page_count(page);
+- __free_page(page);
+- totalram_pages++;
+- num_physpages++;
+-}
+-
+ #ifdef CONFIG_NUMA
+ int memory_add_physaddr_to_nid(u64 start)
+ {
+@@ -111,7 +117,7 @@ int memory_add_physaddr_to_nid(u64 start)
}
#endif
@@ -189077,7 +230711,50 @@
{
struct pglist_data *pgdata;
struct zone *zone;
-@@ -175,7 +190,6 @@ void show_mem(void)
+@@ -148,19 +154,35 @@ out:
+
+ /*
+ * walk_memory_resource() needs to make sure there is no holes in a given
+- * memory range. On PPC64, since this range comes from /sysfs, the range
+- * is guaranteed to be valid, non-overlapping and can not contain any
+- * holes. By the time we get here (memory add or remove), /proc/device-tree
+- * is updated and correct. Only reason we need to check against device-tree
+- * would be if we allow user-land to specify a memory range through a
+- * system call/ioctl etc. instead of doing offline/online through /sysfs.
++ * memory range. PPC64 does not maintain the memory layout in /proc/iomem.
++ * Instead it maintains it in lmb.memory structures. Walk through the
++ * memory regions, find holes and callback for contiguous regions.
+ */
+ int
+ walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg,
+ int (*func)(unsigned long, unsigned long, void *))
+ {
+- return (*func)(start_pfn, nr_pages, arg);
++ struct lmb_property res;
++ unsigned long pfn, len;
++ u64 end;
++ int ret = -1;
++
++ res.base = (u64) start_pfn << PAGE_SHIFT;
++ res.size = (u64) nr_pages << PAGE_SHIFT;
++
++ end = res.base + res.size - 1;
++ while ((res.base < end) && (lmb_find(&res) >= 0)) {
++ pfn = (unsigned long)(res.base >> PAGE_SHIFT);
++ len = (unsigned long)(res.size >> PAGE_SHIFT);
++ ret = (*func)(pfn, len, arg);
++ if (ret)
++ break;
++ res.base += (res.size + 1);
++ res.size = (end - res.base + 1);
++ }
++ return ret;
+ }
++EXPORT_SYMBOL_GPL(walk_memory_resource);
+
+ #endif /* CONFIG_MEMORY_HOTPLUG */
+
+@@ -175,7 +197,6 @@ void show_mem(void)
printk("Mem-info:\n");
show_free_areas();
@@ -189085,7 +230762,7 @@
for_each_online_pgdat(pgdat) {
unsigned long flags;
pgdat_resize_lock(pgdat, &flags);
-@@ -217,9 +231,11 @@ void __init do_init_bootmem(void)
+@@ -217,9 +238,11 @@ void __init do_init_bootmem(void)
unsigned long total_pages;
int boot_mapsize;
@@ -189098,7 +230775,7 @@
#endif
/*
-@@ -231,7 +247,8 @@ void __init do_init_bootmem(void)
+@@ -231,7 +254,8 @@ void __init do_init_bootmem(void)
start = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE);
@@ -189108,7 +230785,7 @@
/* Add active regions with valid PFNs */
for (i = 0; i < lmb.memory.cnt; i++) {
-@@ -245,18 +262,18 @@ void __init do_init_bootmem(void)
+@@ -245,18 +269,18 @@ void __init do_init_bootmem(void)
* present.
*/
#ifdef CONFIG_HIGHMEM
@@ -189131,7 +230808,7 @@
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)
+@@ -309,14 +333,19 @@ void __init paging_init(void)
unsigned long top_of_ram = lmb_end_of_DRAM();
unsigned long max_zone_pfns[MAX_NR_ZONES];
@@ -189157,7 +230834,7 @@
kmap_prot = PAGE_KERNEL;
#endif /* CONFIG_HIGHMEM */
-@@ -326,7 +348,7 @@ void __init paging_init(void)
+@@ -326,7 +355,7 @@ void __init paging_init(void)
(top_of_ram - total_ram) >> 20);
memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
#ifdef CONFIG_HIGHMEM
@@ -189166,7 +230843,7 @@
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)
+@@ -381,7 +410,7 @@ void __init mem_init(void)
{
unsigned long pfn, highmem_mapnr;
@@ -190039,6 +231716,31 @@
.calibrate_decr = generic_calibrate_decr,
};
+diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig
+index cf945d5..acd2fc8 100644
+--- a/arch/powerpc/platforms/52xx/Kconfig
++++ b/arch/powerpc/platforms/52xx/Kconfig
+@@ -44,3 +44,9 @@ config PPC_MPC5200_BUGFIX
+
+ It is safe to say 'Y' here
+
++config PPC_MPC5200_GPIO
++ bool "MPC5200 GPIO support"
++ depends on PPC_MPC52xx
++ select HAVE_GPIO_LIB
++ help
++ Enable gpiolib support for mpc5200 based boards
+diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile
+index fe1b81b..daf0e15 100644
+--- a/arch/powerpc/platforms/52xx/Makefile
++++ b/arch/powerpc/platforms/52xx/Makefile
+@@ -14,3 +14,5 @@ obj-$(CONFIG_PM) += mpc52xx_sleep.o mpc52xx_pm.o
+ ifeq ($(CONFIG_PPC_LITE5200),y)
+ obj-$(CONFIG_PM) += lite5200_sleep.o lite5200_pm.o
+ endif
++
++obj-$(CONFIG_PPC_MPC5200_GPIO) += mpc52xx_gpio.o
+\ No newline at end of file
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
@@ -190061,6 +231763,550 @@
return;
}
+diff --git a/arch/powerpc/platforms/52xx/mpc5200_simple.c b/arch/powerpc/platforms/52xx/mpc5200_simple.c
+index c48b82b..a3bda0b 100644
+--- a/arch/powerpc/platforms/52xx/mpc5200_simple.c
++++ b/arch/powerpc/platforms/52xx/mpc5200_simple.c
+@@ -51,6 +51,7 @@ static void __init mpc5200_simple_setup_arch(void)
+ /* list of the supported boards */
+ static char *board[] __initdata = {
+ "promess,motionpro",
++ "phytec,pcm030",
+ "schindler,cm5200",
+ "tqc,tqm5200",
+ NULL
+diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
+new file mode 100644
+index 0000000..48da5df
+--- /dev/null
++++ b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
+@@ -0,0 +1,465 @@
++/*
++ * MPC52xx gpio driver
++ *
++ * Copyright (c) 2008 Sascha Hauer <s.hauer at pengutronix.de>, 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.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/of.h>
++#include <linux/kernel.h>
++#include <linux/of_gpio.h>
++#include <linux/io.h>
++#include <linux/of_platform.h>
++
++#include <asm/gpio.h>
++#include <asm/mpc52xx.h>
++#include <sysdev/fsl_soc.h>
++
++static DEFINE_SPINLOCK(gpio_lock);
++
++struct mpc52xx_gpiochip {
++ struct of_mm_gpio_chip mmchip;
++ unsigned int shadow_dvo;
++ unsigned int shadow_gpioe;
++ unsigned int shadow_ddr;
++};
++
++/*
++ * GPIO LIB API implementation for wakeup GPIOs.
++ *
++ * There's a maximum of 8 wakeup GPIOs. Which of these are available
++ * for use depends on your board setup.
++ *
++ * 0 -> GPIO_WKUP_7
++ * 1 -> GPIO_WKUP_6
++ * 2 -> PSC6_1
++ * 3 -> PSC6_0
++ * 4 -> ETH_17
++ * 5 -> PSC3_9
++ * 6 -> PSC2_4
++ * 7 -> PSC1_4
++ *
++ */
++static int mpc52xx_wkup_gpio_get(struct gpio_chip *gc, unsigned int gpio)
++{
++ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
++ struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
++ unsigned int ret;
++
++ ret = (in_8(®s->wkup_ival) >> (7 - gpio)) & 1;
++
++ pr_debug("%s: gpio: %d ret: %d\n", __func__, gpio, ret);
++
++ return ret;
++}
++
++static inline void
++__mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
++{
++ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
++ struct mpc52xx_gpiochip *chip = container_of(mm_gc,
++ struct mpc52xx_gpiochip, mmchip);
++ struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
++
++ if (val)
++ chip->shadow_dvo |= 1 << (7 - gpio);
++ else
++ chip->shadow_dvo &= ~(1 << (7 - gpio));
++
++ out_8(®s->wkup_dvo, chip->shadow_dvo);
++}
++
++static void
++mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&gpio_lock, flags);
++
++ __mpc52xx_wkup_gpio_set(gc, gpio, val);
++
++ spin_unlock_irqrestore(&gpio_lock, flags);
++
++ pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
++}
++
++static int mpc52xx_wkup_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
++{
++ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
++ struct mpc52xx_gpiochip *chip = container_of(mm_gc,
++ struct mpc52xx_gpiochip, mmchip);
++ struct mpc52xx_gpio_wkup *regs = mm_gc->regs;
++ unsigned long flags;
++
++ spin_lock_irqsave(&gpio_lock, flags);
++
++ /* set the direction */
++ chip->shadow_ddr &= ~(1 << (7 - gpio));
++ out_8(®s->wkup_ddr, chip->shadow_ddr);
++
++ /* and enable the pin */
++ chip->shadow_gpioe |= 1 << (7 - gpio);
++ out_8(®s->wkup_gpioe, chip->shadow_gpioe);
++
++ spin_unlock_irqrestore(&gpio_lock, flags);
++
++ return 0;
++}
++
++static int
++mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
++{
++ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
++ struct mpc52xx_gpio_wkup *regs = mm_gc->regs;
++ struct mpc52xx_gpiochip *chip = container_of(mm_gc,
++ struct mpc52xx_gpiochip, mmchip);
++ unsigned long flags;
++
++ spin_lock_irqsave(&gpio_lock, flags);
++
++ __mpc52xx_wkup_gpio_set(gc, gpio, val);
++
++ /* Then set direction */
++ chip->shadow_ddr |= 1 << (7 - gpio);
++ out_8(®s->wkup_ddr, chip->shadow_ddr);
++
++ /* Finally enable the pin */
++ chip->shadow_gpioe |= 1 << (7 - gpio);
++ out_8(®s->wkup_gpioe, chip->shadow_gpioe);
++
++ spin_unlock_irqrestore(&gpio_lock, flags);
++
++ pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
++
++ return 0;
++}
++
++static int __devinit mpc52xx_wkup_gpiochip_probe(struct of_device *ofdev,
++ const struct of_device_id *match)
++{
++ struct mpc52xx_gpiochip *chip;
++ struct mpc52xx_gpio_wkup *regs;
++ struct of_gpio_chip *ofchip;
++ int ret;
++
++ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
++ if (!chip)
++ return -ENOMEM;
++
++ ofchip = &chip->mmchip.of_gc;
++
++ ofchip->gpio_cells = 2;
++ ofchip->gc.ngpio = 8;
++ ofchip->gc.direction_input = mpc52xx_wkup_gpio_dir_in;
++ ofchip->gc.direction_output = mpc52xx_wkup_gpio_dir_out;
++ ofchip->gc.get = mpc52xx_wkup_gpio_get;
++ ofchip->gc.set = mpc52xx_wkup_gpio_set;
++
++ ret = of_mm_gpiochip_add(ofdev->node, &chip->mmchip);
++ if (ret)
++ return ret;
++
++ regs = chip->mmchip.regs;
++ chip->shadow_gpioe = in_8(®s->wkup_gpioe);
++ chip->shadow_ddr = in_8(®s->wkup_ddr);
++ chip->shadow_dvo = in_8(®s->wkup_dvo);
++
++ return 0;
++}
++
++static int mpc52xx_gpiochip_remove(struct of_device *ofdev)
++{
++ return -EBUSY;
++}
++
++static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = {
++ {
++ .compatible = "fsl,mpc5200-gpio-wkup",
++ },
++ {}
++};
++
++static struct of_platform_driver mpc52xx_wkup_gpiochip_driver = {
++ .name = "gpio_wkup",
++ .match_table = mpc52xx_wkup_gpiochip_match,
++ .probe = mpc52xx_wkup_gpiochip_probe,
++ .remove = mpc52xx_gpiochip_remove,
++};
++
++/*
++ * GPIO LIB API implementation for simple GPIOs
++ *
++ * There's a maximum of 32 simple GPIOs. Which of these are available
++ * for use depends on your board setup.
++ * The numbering reflects the bit numbering in the port registers:
++ *
++ * 0..1 > reserved
++ * 2..3 > IRDA
++ * 4..7 > ETHR
++ * 8..11 > reserved
++ * 12..15 > USB
++ * 16..17 > reserved
++ * 18..23 > PSC3
++ * 24..27 > PSC2
++ * 28..31 > PSC1
++ */
++static int mpc52xx_simple_gpio_get(struct gpio_chip *gc, unsigned int gpio)
++{
++ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
++ struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
++ unsigned int ret;
++
++ ret = (in_be32(®s->simple_ival) >> (31 - gpio)) & 1;
++
++ return ret;
++}
++
++static inline void
++__mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
++{
++ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
++ struct mpc52xx_gpiochip *chip = container_of(mm_gc,
++ struct mpc52xx_gpiochip, mmchip);
++ struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
++
++ if (val)
++ chip->shadow_dvo |= 1 << (31 - gpio);
++ else
++ chip->shadow_dvo &= ~(1 << (31 - gpio));
++ out_be32(®s->simple_dvo, chip->shadow_dvo);
++}
++
++static void
++mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&gpio_lock, flags);
++
++ __mpc52xx_simple_gpio_set(gc, gpio, val);
++
++ spin_unlock_irqrestore(&gpio_lock, flags);
++
++ pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
++}
++
++static int mpc52xx_simple_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
++{
++ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
++ struct mpc52xx_gpiochip *chip = container_of(mm_gc,
++ struct mpc52xx_gpiochip, mmchip);
++ struct mpc52xx_gpio *regs = mm_gc->regs;
++ unsigned long flags;
++
++ spin_lock_irqsave(&gpio_lock, flags);
++
++ /* set the direction */
++ chip->shadow_ddr &= ~(1 << (31 - gpio));
++ out_be32(®s->simple_ddr, chip->shadow_ddr);
++
++ /* and enable the pin */
++ chip->shadow_gpioe |= 1 << (31 - gpio);
++ out_be32(®s->simple_gpioe, chip->shadow_gpioe);
++
++ spin_unlock_irqrestore(&gpio_lock, flags);
++
++ return 0;
++}
++
++static int
++mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
++{
++ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
++ struct mpc52xx_gpiochip *chip = container_of(mm_gc,
++ struct mpc52xx_gpiochip, mmchip);
++ struct mpc52xx_gpio *regs = mm_gc->regs;
++ unsigned long flags;
++
++ spin_lock_irqsave(&gpio_lock, flags);
++
++ /* First set initial value */
++ __mpc52xx_simple_gpio_set(gc, gpio, val);
++
++ /* Then set direction */
++ chip->shadow_ddr |= 1 << (31 - gpio);
++ out_be32(®s->simple_ddr, chip->shadow_ddr);
++
++ /* Finally enable the pin */
++ chip->shadow_gpioe |= 1 << (31 - gpio);
++ out_be32(®s->simple_gpioe, chip->shadow_gpioe);
++
++ spin_unlock_irqrestore(&gpio_lock, flags);
++
++ pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
++
++ return 0;
++}
++
++static int __devinit mpc52xx_simple_gpiochip_probe(struct of_device *ofdev,
++ const struct of_device_id *match)
++{
++ struct mpc52xx_gpiochip *chip;
++ struct of_gpio_chip *ofchip;
++ struct mpc52xx_gpio *regs;
++ int ret;
++
++ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
++ if (!chip)
++ return -ENOMEM;
++
++ ofchip = &chip->mmchip.of_gc;
++
++ ofchip->gpio_cells = 2;
++ ofchip->gc.ngpio = 32;
++ ofchip->gc.direction_input = mpc52xx_simple_gpio_dir_in;
++ ofchip->gc.direction_output = mpc52xx_simple_gpio_dir_out;
++ ofchip->gc.get = mpc52xx_simple_gpio_get;
++ ofchip->gc.set = mpc52xx_simple_gpio_set;
++
++ ret = of_mm_gpiochip_add(ofdev->node, &chip->mmchip);
++ if (ret)
++ return ret;
++
++ regs = chip->mmchip.regs;
++ chip->shadow_gpioe = in_be32(®s->simple_gpioe);
++ chip->shadow_ddr = in_be32(®s->simple_ddr);
++ chip->shadow_dvo = in_be32(®s->simple_dvo);
++
++ return 0;
++}
++
++static const struct of_device_id mpc52xx_simple_gpiochip_match[] = {
++ {
++ .compatible = "fsl,mpc5200-gpio",
++ },
++ {}
++};
++
++static struct of_platform_driver mpc52xx_simple_gpiochip_driver = {
++ .name = "gpio",
++ .match_table = mpc52xx_simple_gpiochip_match,
++ .probe = mpc52xx_simple_gpiochip_probe,
++ .remove = mpc52xx_gpiochip_remove,
++};
++
++/*
++ * GPIO LIB API implementation for gpt GPIOs.
++ *
++ * Each gpt only has a single GPIO.
++ */
++static int mpc52xx_gpt_gpio_get(struct gpio_chip *gc, unsigned int gpio)
++{
++ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
++ struct mpc52xx_gpt __iomem *regs = mm_gc->regs;
++ unsigned int ret;
++
++ return (in_be32(®s->status) & (1 << (31 - 23))) ? 1 : 0;
++
++ return ret;
++}
++
++static void
++mpc52xx_gpt_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
++{
++ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
++ struct mpc52xx_gpt __iomem *regs = mm_gc->regs;
++
++ if (val)
++ out_be32(®s->mode, 0x34);
++ else
++ out_be32(®s->mode, 0x24);
++
++ pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
++}
++
++static int mpc52xx_gpt_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
++{
++ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
++ struct mpc52xx_gpt *regs = mm_gc->regs;
++
++ out_be32(®s->mode, 0x04);
++
++ return 0;
++}
++
++static int
++mpc52xx_gpt_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
++{
++ mpc52xx_gpt_gpio_set(gc, gpio, val);
++ pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
++
++ return 0;
++}
++
++static int __devinit mpc52xx_gpt_gpiochip_probe(struct of_device *ofdev,
++ const struct of_device_id *match)
++{
++ struct of_mm_gpio_chip *mmchip;
++ struct of_gpio_chip *chip;
++
++ mmchip = kzalloc(sizeof(*mmchip), GFP_KERNEL);
++ if (!mmchip)
++ return -ENOMEM;
++
++ chip = &mmchip->of_gc;
++
++ chip->gpio_cells = 2;
++ chip->gc.ngpio = 1;
++ chip->gc.direction_input = mpc52xx_gpt_gpio_dir_in;
++ chip->gc.direction_output = mpc52xx_gpt_gpio_dir_out;
++ chip->gc.get = mpc52xx_gpt_gpio_get;
++ chip->gc.set = mpc52xx_gpt_gpio_set;
++
++ return of_mm_gpiochip_add(ofdev->node, mmchip);
++}
++
++static const struct of_device_id mpc52xx_gpt_gpiochip_match[] = {
++ {
++ .compatible = "fsl,mpc5200-gpt-gpio",
++ },
++ {}
++};
++
++static struct of_platform_driver mpc52xx_gpt_gpiochip_driver = {
++ .name = "gpio_gpt",
++ .match_table = mpc52xx_gpt_gpiochip_match,
++ .probe = mpc52xx_gpt_gpiochip_probe,
++ .remove = mpc52xx_gpiochip_remove,
++};
++
++static int __init mpc52xx_gpio_init(void)
++{
++ if (of_register_platform_driver(&mpc52xx_wkup_gpiochip_driver))
++ printk(KERN_ERR "Unable to register wakeup GPIO driver\n");
++
++ if (of_register_platform_driver(&mpc52xx_simple_gpiochip_driver))
++ printk(KERN_ERR "Unable to register simple GPIO driver\n");
++
++ if (of_register_platform_driver(&mpc52xx_gpt_gpiochip_driver))
++ printk(KERN_ERR "Unable to register gpt GPIO driver\n");
++
++ return 0;
++}
++
++
++/* Make sure we get initialised before anyone else tries to use us */
++subsys_initcall(mpc52xx_gpio_init);
++
++/* No exit call at the moment as we cannot unregister of gpio chips */
++
++MODULE_DESCRIPTION("Freescale MPC52xx gpio driver");
++MODULE_AUTHOR("Sascha Hauer <s.hauer at pengutronix.de");
++MODULE_LICENSE("GPL v2");
++
+diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+index d0dead8..8479394 100644
+--- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
++++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+@@ -18,6 +18,7 @@
+
+ #undef DEBUG
+
++#include <linux/interrupt.h>
+ #include <linux/irq.h>
+ #include <linux/of.h>
+ #include <asm/io.h>
+@@ -109,11 +110,48 @@ static void mpc52xx_extirq_ack(unsigned int virq)
+ io_be_setbit(&intr->ctrl, 27-l2irq);
+ }
+
++static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type)
++{
++ u32 ctrl_reg, type;
++ int irq;
++ int l2irq;
++
++ irq = irq_map[virq].hwirq;
++ l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
++
++ pr_debug("%s: irq=%x. l2=%d flow_type=%d\n", __func__, irq, l2irq, flow_type);
++
++ switch (flow_type) {
++ case IRQF_TRIGGER_HIGH:
++ type = 0;
++ break;
++ case IRQF_TRIGGER_RISING:
++ type = 1;
++ break;
++ case IRQF_TRIGGER_FALLING:
++ type = 2;
++ break;
++ case IRQF_TRIGGER_LOW:
++ type = 3;
++ break;
++ default:
++ type = 0;
++ }
++
++ ctrl_reg = in_be32(&intr->ctrl);
++ ctrl_reg &= ~(0x3 << (22 - (l2irq * 2)));
++ ctrl_reg |= (type << (22 - (l2irq * 2)));
++ out_be32(&intr->ctrl, ctrl_reg);
++
++ return 0;
++}
++
+ static struct irq_chip mpc52xx_extirq_irqchip = {
+ .typename = " MPC52xx IRQ[0-3] ",
+ .mask = mpc52xx_extirq_mask,
+ .unmask = mpc52xx_extirq_unmask,
+ .ack = mpc52xx_extirq_ack,
++ .set_type = mpc52xx_extirq_set_type,
+ };
+
+ /*
diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig
index 4fad6c7..917ac88 100644
--- a/arch/powerpc/platforms/82xx/Kconfig
@@ -190563,10 +232809,14 @@
* 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
+index 21d1135..053f49a 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
-@@ -11,6 +11,12 @@ config MPC8641_HPCN
+@@ -8,9 +8,16 @@ config MPC8641_HPCN
+ select PPC_I8259
+ select DEFAULT_UIMAGE
+ select FSL_ULI1575
++ select HAS_RAPIDIO
help
This option enables support for the MPC8641 HPCN board.
@@ -190579,7 +232829,7 @@
config MPC8610_HPCD
bool "Freescale MPC8610 HPCD"
select DEFAULT_UIMAGE
-@@ -24,7 +30,7 @@ config MPC8641
+@@ -24,7 +31,7 @@ config MPC8641
select FSL_PCI if PCI
select PPC_UDBG_16550
select MPIC
@@ -190599,29 +232849,249 @@
+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
+index 0b07485..5e1e8cf 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)
+@@ -3,11 +3,12 @@
+ *
+ * Initial author: Xianghua Xiao <x.xiao at freescale.com>
+ * Recode: Jason Jin <jason.jin at freescale.com>
++ * York Sun <yorksun at freescale.com>
+ *
+ * Rewrite the interrupt routing. remove the 8259PIC support,
+ * All the integrated device in ULI use sideband interrupt.
+ *
+- * Copyright 2007 Freescale Semiconductor 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
+@@ -38,6 +39,8 @@
+ #include <sysdev/fsl_pci.h>
+ #include <sysdev/fsl_soc.h>
+
++static unsigned char *pixis_bdcfg0, *pixis_arch;
++
+ static struct of_device_id __initdata mpc8610_ids[] = {
+ { .compatible = "fsl,mpc8610-immr", },
+ {}
+@@ -52,8 +55,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)
+-mpc86xx_hpcd_init_irq(void)
++static void __init mpc86xx_hpcd_init_irq(void)
{
struct mpic *mpic1;
-@@ -200,7 +200,7 @@ static int __init mpc86xx_hpcd_probe(void)
+ struct device_node *np;
+@@ -161,12 +163,159 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x5288, final_uli5288);
+ #endif /* CONFIG_PCI */
+
+-static void __init
+-mpc86xx_hpcd_setup_arch(void)
++#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
++
++static u32 get_busfreq(void)
+ {
+-#ifdef CONFIG_PCI
+- struct device_node *np;
++ struct device_node *node;
++
++ u32 fs_busfreq = 0;
++ node = of_find_node_by_type(NULL, "cpu");
++ if (node) {
++ unsigned int size;
++ const unsigned int *prop =
++ of_get_property(node, "bus-frequency", &size);
++ if (prop)
++ fs_busfreq = *prop;
++ of_node_put(node);
++ };
++ return fs_busfreq;
++}
++
++unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel,
++ int monitor_port)
++{
++ static const unsigned long pixelformat[][3] = {
++ {0x88882317, 0x88083218, 0x65052119},
++ {0x88883316, 0x88082219, 0x65053118},
++ };
++ unsigned int pix_fmt, arch_monitor;
++
++ arch_monitor = ((*pixis_arch == 0x01) && (monitor_port == 0))? 0 : 1;
++ /* DVI port for board version 0x01 */
++
++ if (bits_per_pixel == 32)
++ pix_fmt = pixelformat[arch_monitor][0];
++ else if (bits_per_pixel == 24)
++ pix_fmt = pixelformat[arch_monitor][1];
++ else if (bits_per_pixel == 16)
++ pix_fmt = pixelformat[arch_monitor][2];
++ else
++ pix_fmt = pixelformat[1][0];
++
++ return pix_fmt;
++}
++
++void mpc8610hpcd_set_gamma_table(int monitor_port, char *gamma_table_base)
++{
++ int i;
++ if (monitor_port == 2) { /* dual link LVDS */
++ for (i = 0; i < 256*3; i++)
++ gamma_table_base[i] = (gamma_table_base[i] << 2) |
++ ((gamma_table_base[i] >> 6) & 0x03);
++ }
++}
++
++void mpc8610hpcd_set_monitor_port(int monitor_port)
++{
++ static const u8 bdcfg[] = {0xBD, 0xB5, 0xA5};
++ if (monitor_port < 3)
++ *pixis_bdcfg0 = bdcfg[monitor_port];
++}
++
++void mpc8610hpcd_set_pixel_clock(unsigned int pixclock)
++{
++ u32 __iomem *clkdvdr;
++ u32 temp;
++ /* variables for pixel clock calcs */
++ ulong bestval, bestfreq, speed_ccb, minpixclock, maxpixclock;
++ ulong pixval;
++ long err;
++ int i;
++
++ clkdvdr = ioremap(get_immrbase() + 0xe0800, sizeof(u32));
++ if (!clkdvdr) {
++ printk(KERN_ERR "Err: can't map clock divider register!\n");
++ return;
++ }
++
++ /* Pixel Clock configuration */
++ pr_debug("DIU: Bus Frequency = %d\n", get_busfreq());
++ speed_ccb = get_busfreq();
++
++ /* Calculate the pixel clock with the smallest error */
++ /* calculate the following in steps to avoid overflow */
++ pr_debug("DIU pixclock in ps - %d\n", pixclock);
++ temp = 1000000000/pixclock;
++ temp *= 1000;
++ pixclock = temp;
++ pr_debug("DIU pixclock freq - %u\n", pixclock);
++
++ temp = pixclock * 5 / 100;
++ pr_debug("deviation = %d\n", temp);
++ minpixclock = pixclock - temp;
++ maxpixclock = pixclock + temp;
++ pr_debug("DIU minpixclock - %lu\n", minpixclock);
++ pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
++ pixval = speed_ccb/pixclock;
++ pr_debug("DIU pixval = %lu\n", pixval);
++
++ err = 100000000;
++ bestval = pixval;
++ pr_debug("DIU bestval = %lu\n", bestval);
++
++ bestfreq = 0;
++ for (i = -1; i <= 1; i++) {
++ temp = speed_ccb / ((pixval+i) + 1);
++ pr_debug("DIU test pixval i= %d, pixval=%lu, temp freq. = %u\n",
++ i, pixval, temp);
++ if ((temp < minpixclock) || (temp > maxpixclock))
++ pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
++ minpixclock, maxpixclock);
++ else if (abs(temp - pixclock) < err) {
++ pr_debug("Entered the else if block %d\n", i);
++ err = abs(temp - pixclock);
++ bestval = pixval+i;
++ bestfreq = temp;
++ }
++ }
++
++ pr_debug("DIU chose = %lx\n", bestval);
++ pr_debug("DIU error = %ld\n NomPixClk ", err);
++ pr_debug("DIU: Best Freq = %lx\n", bestfreq);
++ /* Modify PXCLK in GUTS CLKDVDR */
++ pr_debug("DIU: Current value of CLKDVDR = 0x%08x\n", (*clkdvdr));
++ temp = (*clkdvdr) & 0x2000FFFF;
++ *clkdvdr = temp; /* turn off clock */
++ *clkdvdr = temp | 0x80000000 | (((bestval) & 0x1F) << 16);
++ pr_debug("DIU: Modified value of CLKDVDR = 0x%08x\n", (*clkdvdr));
++ iounmap(clkdvdr);
++}
++
++ssize_t mpc8610hpcd_show_monitor_port(int monitor_port, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE,
++ "%c0 - DVI\n"
++ "%c1 - Single link LVDS\n"
++ "%c2 - Dual link LVDS\n",
++ monitor_port == 0 ? '*' : ' ',
++ monitor_port == 1 ? '*' : ' ',
++ monitor_port == 2 ? '*' : ' ');
++}
++
++int mpc8610hpcd_set_sysfs_monitor_port(int val)
++{
++ return val < 3 ? val : 0;
++}
++
+ #endif
++
++static void __init mpc86xx_hpcd_setup_arch(void)
++{
++ struct resource r;
++ struct device_node *np;
++ unsigned char *pixis;
++
+ if (ppc_md.progress)
+ ppc_md.progress("mpc86xx_hpcd_setup_arch()", 0);
+
+@@ -183,6 +332,30 @@ mpc86xx_hpcd_setup_arch(void)
+ }
+ }
+ #endif
++#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
++ preallocate_diu_videomemory();
++ diu_ops.get_pixel_format = mpc8610hpcd_get_pixel_format;
++ diu_ops.set_gamma_table = mpc8610hpcd_set_gamma_table;
++ diu_ops.set_monitor_port = mpc8610hpcd_set_monitor_port;
++ diu_ops.set_pixel_clock = mpc8610hpcd_set_pixel_clock;
++ diu_ops.show_monitor_port = mpc8610hpcd_show_monitor_port;
++ diu_ops.set_sysfs_monitor_port = mpc8610hpcd_set_sysfs_monitor_port;
++#endif
++
++ np = of_find_compatible_node(NULL, NULL, "fsl,fpga-pixis");
++ if (np) {
++ of_address_to_resource(np, 0, &r);
++ of_node_put(np);
++ pixis = ioremap(r.start, 32);
++ if (!pixis) {
++ printk(KERN_ERR "Err: can't map FPGA cfg register!\n");
++ return;
++ }
++ pixis_bdcfg0 = pixis + 8;
++ pixis_arch = pixis + 1;
++ } else
++ printk(KERN_ERR "Err: "
++ "can't find device node 'fsl,fpga-pixis'\n");
+
+ printk("MPC86xx HPCD board from Freescale Semiconductor\n");
+ }
+@@ -200,8 +373,7 @@ static int __init mpc86xx_hpcd_probe(void)
return 0;
}
-long __init
-+static long __init
- mpc86xx_time_init(void)
+-mpc86xx_time_init(void)
++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
+index cfbe8c5..f13704a 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)
@@ -190664,6 +233134,14 @@
mpc86xx_time_init(void)
{
unsigned int temp;
+@@ -215,6 +221,7 @@ mpc86xx_time_init(void)
+
+ static __initdata struct of_device_id of_bus_ids[] = {
+ { .compatible = "simple-bus", },
++ { .compatible = "fsl,rapidio-delta", },
+ {},
+ };
+
diff --git a/arch/powerpc/platforms/86xx/sbc8641d.c b/arch/powerpc/platforms/86xx/sbc8641d.c
new file mode 100644
index 0000000..510a06e
@@ -194720,7 +237198,7 @@
+};
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
+index 0000000..31da84c
--- /dev/null
+++ b/arch/powerpc/platforms/cell/celleb_scc_pciex.c
@@ -0,0 +1,547 @@
@@ -194762,8 +237240,8 @@
+#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))
++#define PEX_IN(base, off) in_be32((void __iomem *)(base) + (off))
++#define PEX_OUT(base, off, data) out_be32((void __iomem *)(base) + (off), (data))
+
+static void scc_pciex_io_flush(struct iowa_bus *bus)
+{
@@ -195030,7 +237508,7 @@
+ ((((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,
++static uint32_t config_read_pciex_dev(unsigned int __iomem *base,
+ uint64_t bus_no, uint64_t dev_no, uint64_t func_no,
+ uint64_t off, uint64_t size)
+{
@@ -195046,7 +237524,7 @@
+ return ret;
+}
+
-+static void config_write_pciex_dev(unsigned int *base, uint64_t bus_no,
++static void config_write_pciex_dev(unsigned int __iomem *base, uint64_t bus_no,
+ uint64_t dev_no, uint64_t func_no, uint64_t off, uint64_t size,
+ uint32_t data)
+{
@@ -195064,7 +237542,7 @@
+ ((((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,
++static uint32_t config_read_pciex_rc(unsigned int __iomem *base,
+ uint32_t where, uint32_t size)
+{
+ PEX_OUT(base, PEXCADRS, MK_PEXCADRS(PEXCADRS_CMD_READ, where, size));
@@ -195072,7 +237550,7 @@
+ >> ((where & (4 - size)) * 8)) & ((0x1 << (size * 8)) - 1);
+}
+
-+static void config_write_pciex_rc(unsigned int *base, uint32_t where,
++static void config_write_pciex_rc(unsigned int __iomem *base, uint32_t where,
+ uint32_t size, uint32_t val)
+{
+ uint32_t data;
@@ -195136,7 +237614,7 @@
+ scc_pciex_write_config,
+};
+
-+static void pciex_clear_intr_all(unsigned int *base)
++static void pciex_clear_intr_all(unsigned int __iomem *base)
+{
+ PEX_OUT(base, PEXAERRSTS, 0xffffffff);
+ PEX_OUT(base, PEXPRERRSTS, 0xffffffff);
@@ -195153,7 +237631,7 @@
+}
+#endif
+
-+static void pciex_enable_intr_all(unsigned int *base)
++static void pciex_enable_intr_all(unsigned int __iomem *base)
+{
+ PEX_OUT(base, PEXINTMASK, 0x0000e7f1);
+ PEX_OUT(base, PEXAERRMASK, 0x03ff01ff);
@@ -195161,7 +237639,7 @@
+ PEX_OUT(base, PEXVDMASK, 0x00000001);
+}
+
-+static void pciex_check_status(unsigned int *base)
++static void pciex_check_status(unsigned int __iomem *base)
+{
+ uint32_t err = 0;
+ uint32_t intsts, aerr, prerr, rcvcp, lenerr;
@@ -196730,6 +239208,43 @@
}
ret = spu_map_interrupts_old(spu, spe);
if (ret) {
+diff --git a/arch/powerpc/platforms/cell/spufs/.gitignore b/arch/powerpc/platforms/cell/spufs/.gitignore
+new file mode 100644
+index 0000000..a09ee8d
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/spufs/.gitignore
+@@ -0,0 +1,2 @@
++spu_save_dump.h
++spu_restore_dump.h
+diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
+index 0ad83ae..177735f 100644
+--- a/arch/powerpc/platforms/cell/spufs/context.c
++++ b/arch/powerpc/platforms/cell/spufs/context.c
+@@ -78,6 +78,7 @@ void destroy_spu_context(struct kref *kref)
+ {
+ struct spu_context *ctx;
+ ctx = container_of(kref, struct spu_context, kref);
++ spu_context_nospu_trace(destroy_spu_context__enter, ctx);
+ mutex_lock(&ctx->state_mutex);
+ spu_deactivate(ctx);
+ mutex_unlock(&ctx->state_mutex);
+@@ -88,6 +89,7 @@ void destroy_spu_context(struct kref *kref)
+ kref_put(ctx->prof_priv_kref, ctx->prof_priv_release);
+ BUG_ON(!list_empty(&ctx->rq));
+ atomic_dec(&nr_spu_contexts);
++ kfree(ctx->switch_log);
+ kfree(ctx);
+ }
+
+@@ -150,6 +152,8 @@ int spu_acquire_saved(struct spu_context *ctx)
+ {
+ int ret;
+
++ spu_context_nospu_trace(spu_acquire_saved__enter, ctx);
++
+ ret = spu_acquire(ctx);
+ if (ret)
+ return 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
@@ -196764,7 +239279,7 @@
return 0;
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
-index f7a7e86..08f44d1 100644
+index f7a7e86..80911a3 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -32,7 +32,6 @@
@@ -196811,6 +239326,186 @@
free_elements, tagstatus, ctx->tagwait);
return mask;
+@@ -2387,6 +2386,171 @@ static const struct file_operations spufs_stat_fops = {
+ .release = single_release,
+ };
+
++static inline int spufs_switch_log_used(struct spu_context *ctx)
++{
++ return (ctx->switch_log->head - ctx->switch_log->tail) %
++ SWITCH_LOG_BUFSIZE;
++}
++
++static inline int spufs_switch_log_avail(struct spu_context *ctx)
++{
++ return SWITCH_LOG_BUFSIZE - spufs_switch_log_used(ctx);
++}
++
++static int spufs_switch_log_open(struct inode *inode, struct file *file)
++{
++ struct spu_context *ctx = SPUFS_I(inode)->i_ctx;
++
++ /*
++ * We (ab-)use the mapping_lock here because it serves the similar
++ * purpose for synchronizing open/close elsewhere. Maybe it should
++ * be renamed eventually.
++ */
++ mutex_lock(&ctx->mapping_lock);
++ if (ctx->switch_log) {
++ spin_lock(&ctx->switch_log->lock);
++ ctx->switch_log->head = 0;
++ ctx->switch_log->tail = 0;
++ spin_unlock(&ctx->switch_log->lock);
++ } else {
++ /*
++ * We allocate the switch log data structures on first open.
++ * They will never be free because we assume a context will
++ * be traced until it goes away.
++ */
++ ctx->switch_log = kzalloc(sizeof(struct switch_log) +
++ SWITCH_LOG_BUFSIZE * sizeof(struct switch_log_entry),
++ GFP_KERNEL);
++ if (!ctx->switch_log)
++ goto out;
++ spin_lock_init(&ctx->switch_log->lock);
++ init_waitqueue_head(&ctx->switch_log->wait);
++ }
++ mutex_unlock(&ctx->mapping_lock);
++
++ return 0;
++ out:
++ mutex_unlock(&ctx->mapping_lock);
++ return -ENOMEM;
++}
++
++static int switch_log_sprint(struct spu_context *ctx, char *tbuf, int n)
++{
++ struct switch_log_entry *p;
++
++ p = ctx->switch_log->log + ctx->switch_log->tail % SWITCH_LOG_BUFSIZE;
++
++ return snprintf(tbuf, n, "%u.%09u %d %u %u %llu\n",
++ (unsigned int) p->tstamp.tv_sec,
++ (unsigned int) p->tstamp.tv_nsec,
++ p->spu_id,
++ (unsigned int) p->type,
++ (unsigned int) p->val,
++ (unsigned long long) p->timebase);
++}
++
++static ssize_t spufs_switch_log_read(struct file *file, char __user *buf,
++ size_t len, loff_t *ppos)
++{
++ struct inode *inode = file->f_path.dentry->d_inode;
++ struct spu_context *ctx = SPUFS_I(inode)->i_ctx;
++ int error = 0, cnt = 0;
++
++ if (!buf || len < 0)
++ return -EINVAL;
++
++ while (cnt < len) {
++ char tbuf[128];
++ int width;
++
++ if (file->f_flags & O_NONBLOCK) {
++ if (spufs_switch_log_used(ctx) <= 0)
++ return cnt ? cnt : -EAGAIN;
++ } else {
++ /* Wait for data in buffer */
++ error = wait_event_interruptible(ctx->switch_log->wait,
++ spufs_switch_log_used(ctx) > 0);
++ if (error)
++ break;
++ }
++
++ spin_lock(&ctx->switch_log->lock);
++ if (ctx->switch_log->head == ctx->switch_log->tail) {
++ /* multiple readers race? */
++ spin_unlock(&ctx->switch_log->lock);
++ continue;
++ }
++
++ width = switch_log_sprint(ctx, tbuf, sizeof(tbuf));
++ if (width < len) {
++ ctx->switch_log->tail =
++ (ctx->switch_log->tail + 1) %
++ SWITCH_LOG_BUFSIZE;
++ }
++
++ spin_unlock(&ctx->switch_log->lock);
++
++ /*
++ * If the record is greater than space available return
++ * partial buffer (so far)
++ */
++ if (width >= len)
++ break;
++
++ error = copy_to_user(buf + cnt, tbuf, width);
++ if (error)
++ break;
++ cnt += width;
++ }
++
++ return cnt == 0 ? error : cnt;
++}
++
++static unsigned int spufs_switch_log_poll(struct file *file, poll_table *wait)
++{
++ struct inode *inode = file->f_path.dentry->d_inode;
++ struct spu_context *ctx = SPUFS_I(inode)->i_ctx;
++ unsigned int mask = 0;
++
++ poll_wait(file, &ctx->switch_log->wait, wait);
++
++ if (spufs_switch_log_used(ctx) > 0)
++ mask |= POLLIN;
++
++ return mask;
++}
++
++static const struct file_operations spufs_switch_log_fops = {
++ .owner = THIS_MODULE,
++ .open = spufs_switch_log_open,
++ .read = spufs_switch_log_read,
++ .poll = spufs_switch_log_poll,
++};
++
++void spu_switch_log_notify(struct spu *spu, struct spu_context *ctx,
++ u32 type, u32 val)
++{
++ if (!ctx->switch_log)
++ return;
++
++ spin_lock(&ctx->switch_log->lock);
++ if (spufs_switch_log_avail(ctx) > 1) {
++ struct switch_log_entry *p;
++
++ p = ctx->switch_log->log + ctx->switch_log->head;
++ ktime_get_ts(&p->tstamp);
++ p->timebase = get_tb();
++ p->spu_id = spu ? spu->number : -1;
++ p->type = type;
++ p->val = val;
++
++ ctx->switch_log->head =
++ (ctx->switch_log->head + 1) % SWITCH_LOG_BUFSIZE;
++ }
++ spin_unlock(&ctx->switch_log->lock);
++
++ wake_up(&ctx->switch_log->wait);
++}
+
+ struct tree_descr spufs_dir_contents[] = {
+ { "capabilities", &spufs_caps_fops, 0444, },
+@@ -2423,6 +2587,7 @@ struct tree_descr spufs_dir_contents[] = {
+ { "proxydma_info", &spufs_proxydma_info_fops, 0444, },
+ { "tid", &spufs_tid_fops, 0444, },
+ { "stat", &spufs_stat_fops, 0444, },
++ { "switch_log", &spufs_switch_log_fops, 0444 },
+ {},
+ };
+
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
@@ -196824,7 +239519,7 @@
#include <asm/spu_priv1.h>
#include <asm/uaccess.h>
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
-index cac69e1..96bf7c2 100644
+index cac69e1..a9c35b7 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)
@@ -196883,6 +239578,180 @@
/* write result, jump over indirect pointer */
memcpy_toio(ls + ls_pointer, &spu_ret, sizeof(spu_ret));
ctx->ops->npc_write(ctx, npc);
+@@ -401,6 +405,8 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
+ ret = spu_run_fini(ctx, npc, &status);
+ spu_yield(ctx);
+
++ spu_switch_log_notify(NULL, ctx, SWITCH_LOG_EXIT, status);
++
+ if ((status & SPU_STATUS_STOPPED_BY_STOP) &&
+ (((status >> SPU_STOP_STATUS_SHIFT) & 0x3f00) == 0x2100))
+ ctx->stats.libassist++;
+diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
+index 00528ef..7298e7d 100644
+--- a/arch/powerpc/platforms/cell/spufs/sched.c
++++ b/arch/powerpc/platforms/cell/spufs/sched.c
+@@ -240,6 +240,7 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
+ spu->mfc_callback = spufs_mfc_callback;
+ mb();
+ spu_unmap_mappings(ctx);
++ spu_switch_log_notify(spu, ctx, SWITCH_LOG_START, 0);
+ spu_restore(&ctx->csa, spu);
+ spu->timestamp = jiffies;
+ spu_cpu_affinity_set(spu, raw_smp_processor_id());
+@@ -419,6 +420,7 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
+ spu_switch_notify(spu, NULL);
+ spu_unmap_mappings(ctx);
+ spu_save(&ctx->csa, spu);
++ spu_switch_log_notify(spu, ctx, SWITCH_LOG_STOP, 0);
+ spu->timestamp = jiffies;
+ ctx->state = SPU_STATE_SAVED;
+ spu->ibox_callback = NULL;
+@@ -591,7 +593,7 @@ static struct spu *find_victim(struct spu_context *ctx)
+ struct spu *spu;
+ int node, n;
+
+- spu_context_nospu_trace(spu_find_vitim__enter, ctx);
++ spu_context_nospu_trace(spu_find_victim__enter, ctx);
+
+ /*
+ * Look for a possible preemption candidate on the local node first.
+@@ -1063,10 +1065,9 @@ int __init spu_sched_init(void)
+
+ mod_timer(&spuloadavg_timer, 0);
+
+- entry = create_proc_entry("spu_loadavg", 0, NULL);
++ entry = proc_create("spu_loadavg", 0, NULL, &spu_loadavg_fops);
+ if (!entry)
+ goto out_stop_kthread;
+- entry->proc_fops = &spu_loadavg_fops;
+
+ pr_debug("spusched: tick: %d, min ticks: %d, default ticks: %d\n",
+ SPUSCHED_TICK, MIN_SPU_TIMESLICE, DEF_SPU_TIMESLICE);
+diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
+index cdc5151..7312745 100644
+--- a/arch/powerpc/platforms/cell/spufs/spufs.h
++++ b/arch/powerpc/platforms/cell/spufs/spufs.h
+@@ -47,6 +47,30 @@ enum {
+ SPU_SCHED_SPU_RUN, /* context is within spu_run */
+ };
+
++enum {
++ SWITCH_LOG_BUFSIZE = 4096,
++};
++
++enum {
++ SWITCH_LOG_START,
++ SWITCH_LOG_STOP,
++ SWITCH_LOG_EXIT,
++};
++
++struct switch_log {
++ spinlock_t lock;
++ wait_queue_head_t wait;
++ unsigned long head;
++ unsigned long tail;
++ struct switch_log_entry {
++ struct timespec tstamp;
++ s32 spu_id;
++ u32 type;
++ u32 val;
++ u64 timebase;
++ } log[];
++};
++
+ struct spu_context {
+ struct spu *spu; /* pointer to a physical SPU */
+ struct spu_state csa; /* SPU context save area. */
+@@ -116,6 +140,9 @@ struct spu_context {
+ unsigned long long libassist;
+ } stats;
+
++ /* context switch log */
++ struct switch_log *switch_log;
++
+ struct list_head aff_list;
+ int aff_head;
+ int aff_offset;
+@@ -256,6 +283,8 @@ int spu_activate(struct spu_context *ctx, unsigned long flags);
+ void spu_deactivate(struct spu_context *ctx);
+ void spu_yield(struct spu_context *ctx);
+ void spu_switch_notify(struct spu *spu, struct spu_context *ctx);
++void spu_switch_log_notify(struct spu *spu, struct spu_context *ctx,
++ u32 type, u32 val);
+ void spu_set_timeslice(struct spu_context *ctx);
+ void spu_update_sched_info(struct spu_context *ctx);
+ void __spu_update_sched_info(struct spu_context *ctx);
+@@ -330,8 +359,8 @@ extern void spuctx_switch_state(struct spu_context *ctx,
+ enum spu_utilization_state new_state);
+
+ #define spu_context_trace(name, ctx, spu) \
+- trace_mark(name, "%p %p", ctx, spu);
++ trace_mark(name, "ctx %p spu %p", ctx, spu);
+ #define spu_context_nospu_trace(name, ctx) \
+- trace_mark(name, "%p", ctx);
++ trace_mark(name, "ctx %p", ctx);
+
+ #endif
+diff --git a/arch/powerpc/platforms/cell/spufs/sputrace.c b/arch/powerpc/platforms/cell/spufs/sputrace.c
+index 79aa773..5320242 100644
+--- a/arch/powerpc/platforms/cell/spufs/sputrace.c
++++ b/arch/powerpc/platforms/cell/spufs/sputrace.c
+@@ -171,24 +171,24 @@ static void spu_context_nospu_event(void *probe_private, void *call_data,
+ }
+
+ struct spu_probe spu_probes[] = {
+- { "spu_bind_context__enter", "%p %p", spu_context_event },
+- { "spu_unbind_context__enter", "%p %p", spu_context_event },
+- { "spu_get_idle__enter", "%p", spu_context_nospu_event },
+- { "spu_get_idle__found", "%p %p", spu_context_event },
+- { "spu_get_idle__not_found", "%p", spu_context_nospu_event },
+- { "spu_find_victim__enter", "%p", spu_context_nospu_event },
+- { "spusched_tick__preempt", "%p %p", spu_context_event },
+- { "spusched_tick__newslice", "%p", spu_context_nospu_event },
+- { "spu_yield__enter", "%p", spu_context_nospu_event },
+- { "spu_deactivate__enter", "%p", spu_context_nospu_event },
+- { "__spu_deactivate__unload", "%p %p", spu_context_event },
+- { "spufs_ps_nopfn__enter", "%p", spu_context_nospu_event },
+- { "spufs_ps_nopfn__sleep", "%p", spu_context_nospu_event },
+- { "spufs_ps_nopfn__wake", "%p %p", spu_context_event },
+- { "spufs_ps_nopfn__insert", "%p %p", spu_context_event },
+- { "spu_acquire_saved__enter", "%p", spu_context_nospu_event },
+- { "destroy_spu_context__enter", "%p", spu_context_nospu_event },
+- { "spufs_stop_callback__enter", "%p %p", spu_context_event },
++ { "spu_bind_context__enter", "ctx %p spu %p", spu_context_event },
++ { "spu_unbind_context__enter", "ctx %p spu %p", spu_context_event },
++ { "spu_get_idle__enter", "ctx %p", spu_context_nospu_event },
++ { "spu_get_idle__found", "ctx %p spu %p", spu_context_event },
++ { "spu_get_idle__not_found", "ctx %p", spu_context_nospu_event },
++ { "spu_find_victim__enter", "ctx %p", spu_context_nospu_event },
++ { "spusched_tick__preempt", "ctx %p spu %p", spu_context_event },
++ { "spusched_tick__newslice", "ctx %p", spu_context_nospu_event },
++ { "spu_yield__enter", "ctx %p", spu_context_nospu_event },
++ { "spu_deactivate__enter", "ctx %p", spu_context_nospu_event },
++ { "__spu_deactivate__unload", "ctx %p spu %p", spu_context_event },
++ { "spufs_ps_nopfn__enter", "ctx %p", spu_context_nospu_event },
++ { "spufs_ps_nopfn__sleep", "ctx %p", spu_context_nospu_event },
++ { "spufs_ps_nopfn__wake", "ctx %p spu %p", spu_context_event },
++ { "spufs_ps_nopfn__insert", "ctx %p spu %p", spu_context_event },
++ { "spu_acquire_saved__enter", "ctx %p", spu_context_nospu_event },
++ { "destroy_spu_context__enter", "ctx %p", spu_context_nospu_event },
++ { "spufs_stop_callback__enter", "ctx %p spu %p", spu_context_event },
+ };
+
+ static int __init sputrace_init(void)
+@@ -201,10 +201,9 @@ static int __init sputrace_init(void)
+ if (!sputrace_log)
+ goto out;
+
+- entry = create_proc_entry("sputrace", S_IRUSR, NULL);
++ entry = proc_create("sputrace", S_IRUSR, NULL, &sputrace_fops);
+ if (!entry)
+ goto out_free_log;
+- entry->proc_fops = &sputrace_fops;
+
+ for (i = 0; i < ARRAY_SIZE(spu_probes); i++) {
+ struct spu_probe *p = &spu_probes[i];
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
@@ -201640,6 +244509,47 @@
- .xSize = sizeof(struct ItLpRegSave),
- },
-};
+diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c
+index e5b40e3..b0f8a85 100644
+--- a/arch/powerpc/platforms/iseries/lpevents.c
++++ b/arch/powerpc/platforms/iseries/lpevents.c
+@@ -330,15 +330,11 @@ static const struct file_operations proc_lpevents_operations = {
+
+ static int __init proc_lpevents_init(void)
+ {
+- struct proc_dir_entry *e;
+-
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return 0;
+
+- e = create_proc_entry("iSeries/lpevents", S_IFREG|S_IRUGO, NULL);
+- if (e)
+- e->proc_fops = &proc_lpevents_operations;
+-
++ proc_create("iSeries/lpevents", S_IFREG|S_IRUGO, NULL,
++ &proc_lpevents_operations);
+ return 0;
+ }
+ __initcall(proc_lpevents_init);
+diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
+index c0f2433..1dc7295 100644
+--- a/arch/powerpc/platforms/iseries/mf.c
++++ b/arch/powerpc/platforms/iseries/mf.c
+@@ -1255,11 +1255,11 @@ static int __init mf_proc_init(void)
+ if (i == 3) /* no vmlinux entry for 'D' */
+ continue;
+
+- ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf);
++ ent = proc_create_data("vmlinux", S_IFREG|S_IWUSR, mf,
++ &proc_vmlinux_operations,
++ (void *)(long)i);
+ if (!ent)
+ return 1;
+- ent->data = (void *)(long)i;
+- ent->proc_fops = &proc_vmlinux_operations;
+ }
+
+ ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
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
@@ -201674,6 +244584,28 @@
last_jiffies = jiffies;
num_printed = 0;
}
+diff --git a/arch/powerpc/platforms/iseries/proc.c b/arch/powerpc/platforms/iseries/proc.c
+index f2cde41..91f4c6c 100644
+--- a/arch/powerpc/platforms/iseries/proc.c
++++ b/arch/powerpc/platforms/iseries/proc.c
+@@ -110,15 +110,11 @@ static const struct file_operations proc_titantod_operations = {
+
+ static int __init iseries_proc_init(void)
+ {
+- struct proc_dir_entry *e;
+-
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return 0;
+
+- e = create_proc_entry("iSeries/titanTod", S_IFREG|S_IRUGO, NULL);
+- if (e)
+- e->proc_fops = &proc_titantod_operations;
+-
++ proc_create("iSeries/titanTod", S_IFREG|S_IRUGO, NULL,
++ &proc_titantod_operations);
+ return 0;
+ }
+ __initcall(iseries_proc_init);
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
@@ -201697,6 +244629,27 @@
-extern struct SpCommArea xSpCommArea;
-
#endif /* _ISERIES_SPCOMM_AREA_H */
+diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c
+index df23331..49ff4dc 100644
+--- a/arch/powerpc/platforms/iseries/viopath.c
++++ b/arch/powerpc/platforms/iseries/viopath.c
+@@ -180,15 +180,10 @@ static const struct file_operations proc_viopath_operations = {
+
+ static int __init vio_proc_init(void)
+ {
+- struct proc_dir_entry *e;
+-
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return 0;
+
+- e = create_proc_entry("iSeries/config", 0, NULL);
+- if (e)
+- e->proc_fops = &proc_viopath_operations;
+-
++ proc_create("iSeries/config", 0, NULL, &proc_viopath_operations);
+ return 0;
+ }
+ __initcall(vio_proc_init);
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
@@ -202071,6 +245024,22 @@
}
/* set 2GB translation window, based at 0 */
+diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile
+index 78093d7..4d72c8f 100644
+--- a/arch/powerpc/platforms/powermac/Makefile
++++ b/arch/powerpc/platforms/powermac/Makefile
+@@ -6,7 +6,10 @@ obj-y += pic.o setup.o time.o feature.o pci.o \
+ obj-$(CONFIG_PMAC_BACKLIGHT) += backlight.o
+ obj-$(CONFIG_CPU_FREQ_PMAC) += cpufreq_32.o
+ obj-$(CONFIG_CPU_FREQ_PMAC64) += cpufreq_64.o
+-obj-$(CONFIG_NVRAM) += nvram.o
++# CONFIG_NVRAM is an arch. independant tristate symbol, for pmac32 we really
++# need this to be a bool. Cheat here and pretend CONFIG_NVRAM=m is really
++# CONFIG_NVRAM=y
++obj-$(CONFIG_NVRAM:m=y) += nvram.o
+ # ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff
+ obj-$(CONFIG_PPC64) += nvram.o
+ obj-$(CONFIG_PPC32) += bootx_init.o
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
@@ -202140,7 +245109,7 @@
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
+index 36ff1b6..00bd016 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -53,6 +53,7 @@
@@ -202159,7 +245128,17 @@
#include <asm/udbg.h>
#include "pmac.h"
-@@ -574,14 +574,6 @@ static int __init pmac_probe(void)
+@@ -337,7 +337,8 @@ static void __init pmac_setup_arch(void)
+ find_via_pmu();
+ smu_init();
+
+-#if defined(CONFIG_NVRAM) || defined(CONFIG_PPC64)
++#if defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE) || \
++ defined(CONFIG_PPC64)
+ pmac_nvram_init();
+ #endif
+
+@@ -574,14 +575,6 @@ static int __init pmac_probe(void)
ISA_DMA_THRESHOLD = ~0L;
DMA_MODE_READ = 1;
DMA_MODE_WRITE = 2;
@@ -202436,7 +245415,7 @@
+ 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
+index 992ba67..554c6e4 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -2,6 +2,10 @@ ifeq ($(CONFIG_PPC64),y)
@@ -202450,13 +245429,18 @@
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
+@@ -14,7 +18,9 @@ obj-$(CONFIG_PCI) += pci.o pci_dlpar.o
+ obj-$(CONFIG_PCI_MSI) += msi.o
+
+ obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o
++obj-$(CONFIG_MEMORY_HOTPLUG) += hotplug-memory.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
+index 9eb539e..6f544ba 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -39,7 +39,6 @@
@@ -202486,6 +245470,23 @@
/* Ignore bad nodes. */
if (!class_code || !vendor_id || !device_id)
+@@ -1261,14 +1259,8 @@ static const struct file_operations proc_eeh_operations = {
+
+ static int __init eeh_init_proc(void)
+ {
+- struct proc_dir_entry *e;
+-
+- if (machine_is(pseries)) {
+- e = create_proc_entry("ppc64/eeh", 0, NULL);
+- if (e)
+- e->proc_fops = &proc_eeh_operations;
+- }
+-
++ if (machine_is(pseries))
++ proc_create("ppc64/eeh", 0, NULL, &proc_eeh_operations);
+ return 0;
+ }
+ __initcall(eeh_init_proc);
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
@@ -202536,6 +245537,153 @@
- DBG(" <- fw_feature_init()\n");
+ pr_debug(" <- fw_feature_init()\n");
}
+diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
+new file mode 100644
+index 0000000..3c5727d
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
+@@ -0,0 +1,141 @@
++/*
++ * pseries Memory Hotplug infrastructure.
++ *
++ * Copyright (C) 2008 Badari Pulavarty, IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/of.h>
++#include <linux/lmb.h>
++#include <asm/firmware.h>
++#include <asm/machdep.h>
++#include <asm/pSeries_reconfig.h>
++
++static int pseries_remove_memory(struct device_node *np)
++{
++ const char *type;
++ const unsigned int *my_index;
++ const unsigned int *regs;
++ u64 start_pfn, start;
++ struct zone *zone;
++ int ret = -EINVAL;
++
++ /*
++ * Check to see if we are actually removing memory
++ */
++ type = of_get_property(np, "device_type", NULL);
++ if (type == NULL || strcmp(type, "memory") != 0)
++ return 0;
++
++ /*
++ * Find the memory index and size of the removing section
++ */
++ my_index = of_get_property(np, "ibm,my-drc-index", NULL);
++ if (!my_index)
++ return ret;
++
++ regs = of_get_property(np, "reg", NULL);
++ if (!regs)
++ return ret;
++
++ start_pfn = section_nr_to_pfn(*my_index & 0xffff);
++ zone = page_zone(pfn_to_page(start_pfn));
++
++ /*
++ * Remove section mappings and sysfs entries for the
++ * section of the memory we are removing.
++ *
++ * NOTE: Ideally, this should be done in generic code like
++ * remove_memory(). But remove_memory() gets called by writing
++ * to sysfs "state" file and we can't remove sysfs entries
++ * while writing to it. So we have to defer it to here.
++ */
++ ret = __remove_pages(zone, start_pfn, regs[3] >> PAGE_SHIFT);
++ if (ret)
++ return ret;
++
++ /*
++ * Update memory regions for memory remove
++ */
++ lmb_remove(start_pfn << PAGE_SHIFT, regs[3]);
++
++ /*
++ * Remove htab bolted mappings for this section of memory
++ */
++ start = (unsigned long)__va(start_pfn << PAGE_SHIFT);
++ ret = remove_section_mapping(start, start + regs[3]);
++ return ret;
++}
++
++static int pseries_add_memory(struct device_node *np)
++{
++ const char *type;
++ const unsigned int *my_index;
++ const unsigned int *regs;
++ u64 start_pfn;
++ int ret = -EINVAL;
++
++ /*
++ * Check to see if we are actually adding memory
++ */
++ type = of_get_property(np, "device_type", NULL);
++ if (type == NULL || strcmp(type, "memory") != 0)
++ return 0;
++
++ /*
++ * Find the memory index and size of the added section
++ */
++ my_index = of_get_property(np, "ibm,my-drc-index", NULL);
++ if (!my_index)
++ return ret;
++
++ regs = of_get_property(np, "reg", NULL);
++ if (!regs)
++ return ret;
++
++ start_pfn = section_nr_to_pfn(*my_index & 0xffff);
++
++ /*
++ * Update memory region to represent the memory add
++ */
++ lmb_add(start_pfn << PAGE_SHIFT, regs[3]);
++ return 0;
++}
++
++static int pseries_memory_notifier(struct notifier_block *nb,
++ unsigned long action, void *node)
++{
++ int err = NOTIFY_OK;
++
++ switch (action) {
++ case PSERIES_RECONFIG_ADD:
++ if (pseries_add_memory(node))
++ err = NOTIFY_BAD;
++ break;
++ case PSERIES_RECONFIG_REMOVE:
++ if (pseries_remove_memory(node))
++ err = NOTIFY_BAD;
++ break;
++ default:
++ err = NOTIFY_DONE;
++ break;
++ }
++ return err;
++}
++
++static struct notifier_block pseries_mem_nb = {
++ .notifier_call = pseries_memory_notifier,
++};
++
++static int __init pseries_memory_hotplug_init(void)
++{
++ if (firmware_has_feature(FW_FEATURE_LPAR))
++ pSeries_reconfig_notifier_register(&pseries_mem_nb);
++
++ return 0;
++}
++machine_device_initcall(pseries, pseries_memory_hotplug_init);
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
@@ -203439,7 +246587,7 @@
* 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
+index 2800fce..75769aa 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
@@ -203489,8 +246637,23 @@
return NULL;
}
tmp++;
+@@ -512,12 +512,9 @@ static int proc_ppc64_create_ofdt(void)
+ if (!machine_is(pseries))
+ return 0;
+
+- ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL);
+- if (ent) {
+- ent->data = NULL;
++ ent = proc_create("ppc64/ofdt", S_IWUSR, NULL, &ofdt_fops);
++ if (ent)
+ ent->size = 0;
+- ent->proc_fops = &ofdt_fops;
+- }
+
+ return 0;
+ }
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c
-index e3078ce..befadd4 100644
+index e3078ce..7d3e2b0 100644
--- a/arch/powerpc/platforms/pseries/rtasd.c
+++ b/arch/powerpc/platforms/pseries/rtasd.c
@@ -29,11 +29,6 @@
@@ -203536,6 +246699,20 @@
}
/* Delay should be at least one second since some
+@@ -472,10 +468,9 @@ static int __init rtas_init(void)
+ return -ENOMEM;
+ }
+
+- entry = create_proc_entry("ppc64/rtas/error_log", S_IRUSR, NULL);
+- if (entry)
+- entry->proc_fops = &proc_rtas_log_operations;
+- else
++ entry = proc_create("ppc64/rtas/error_log", S_IRUSR, NULL,
++ &proc_rtas_log_operations);
++ if (!entry)
+ printk(KERN_ERR "Failed to create error_log proc entry\n");
+
+ if (kernel_thread(rtasd, NULL, CLONE_FS) < 0)
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
@@ -204082,6 +247259,29 @@
obj-$(CONFIG_XILINX_VIRTEX) += xilinx_intc.o
obj-$(CONFIG_OF_RTC) += of_rtc.o
ifeq ($(CONFIG_PCI),y)
+diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c
+index d359d6e..7f59188 100644
+--- a/arch/powerpc/sysdev/axonram.c
++++ b/arch/powerpc/sysdev/axonram.c
+@@ -143,7 +143,7 @@ axon_ram_make_request(struct request_queue *queue, struct bio *bio)
+ */
+ static int
+ axon_ram_direct_access(struct block_device *device, sector_t sector,
+- unsigned long *data)
++ void **kaddr, unsigned long *pfn)
+ {
+ struct axon_ram_bank *bank = device->bd_disk->private_data;
+ loff_t offset;
+@@ -154,7 +154,8 @@ axon_ram_direct_access(struct block_device *device, sector_t sector,
+ return -ERANGE;
+ }
+
+- *data = bank->ph_addr + offset;
++ *kaddr = (void *)(bank->ph_addr + offset);
++ *pfn = virt_to_phys(kaddr) >> PAGE_SHIFT;
+
+ return 0;
+ }
diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c
index df8bd2b..58292a0 100644
--- a/arch/powerpc/sysdev/cpm1.c
@@ -204544,8 +247744,1259 @@
+ return 0;
+}
+EXPORT_SYMBOL(fsl_upm_find);
+diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
+index af2425e..3d92037 100644
+--- a/arch/powerpc/sysdev/fsl_rio.c
++++ b/arch/powerpc/sysdev/fsl_rio.c
+@@ -1,5 +1,8 @@
+ /*
+- * MPC85xx RapidIO support
++ * Freescale MPC85xx/MPC86xx RapidIO support
++ *
++ * Copyright (C) 2007, 2008 Freescale Semiconductor, Inc.
++ * Zhang Wei <wei.zhang at freescale.com>
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter at kernel.crashing.org>
+@@ -17,12 +20,23 @@
+ #include <linux/interrupt.h>
+ #include <linux/rio.h>
+ #include <linux/rio_drv.h>
++#include <linux/of_platform.h>
++#include <linux/delay.h>
+
+ #include <asm/io.h>
+
+-#define RIO_REGS_BASE (CCSRBAR + 0xc0000)
++/* RapidIO definition irq, which read from OF-tree */
++#define IRQ_RIO_BELL(m) (((struct rio_priv *)(m->priv))->bellirq)
++#define IRQ_RIO_TX(m) (((struct rio_priv *)(m->priv))->txirq)
++#define IRQ_RIO_RX(m) (((struct rio_priv *)(m->priv))->rxirq)
++
+ #define RIO_ATMU_REGS_OFFSET 0x10c00
+-#define RIO_MSG_REGS_OFFSET 0x11000
++#define RIO_P_MSG_REGS_OFFSET 0x11000
++#define RIO_S_MSG_REGS_OFFSET 0x13000
++#define RIO_ESCSR 0x158
++#define RIO_CCSR 0x15c
++#define RIO_ISR_AACR 0x10120
++#define RIO_ISR_AACR_AA 0x1 /* Accept All ID */
+ #define RIO_MAINT_WIN_SIZE 0x400000
+ #define RIO_DBELL_WIN_SIZE 0x1000
+
+@@ -50,18 +64,18 @@
+ #define DOORBELL_DSR_TE 0x00000080
+ #define DOORBELL_DSR_QFI 0x00000010
+ #define DOORBELL_DSR_DIQI 0x00000001
+-#define DOORBELL_TID_OFFSET 0x03
+-#define DOORBELL_SID_OFFSET 0x05
++#define DOORBELL_TID_OFFSET 0x02
++#define DOORBELL_SID_OFFSET 0x04
+ #define DOORBELL_INFO_OFFSET 0x06
+
+ #define DOORBELL_MESSAGE_SIZE 0x08
+-#define DBELL_SID(x) (*(u8 *)(x + DOORBELL_SID_OFFSET))
+-#define DBELL_TID(x) (*(u8 *)(x + DOORBELL_TID_OFFSET))
++#define DBELL_SID(x) (*(u16 *)(x + DOORBELL_SID_OFFSET))
++#define DBELL_TID(x) (*(u16 *)(x + DOORBELL_TID_OFFSET))
+ #define DBELL_INF(x) (*(u16 *)(x + DOORBELL_INFO_OFFSET))
+
+ struct rio_atmu_regs {
+ u32 rowtar;
+- u32 pad1;
++ u32 rowtear;
+ u32 rowbar;
+ u32 pad2;
+ u32 rowar;
+@@ -87,7 +101,15 @@ struct rio_msg_regs {
+ u32 ifqdpar;
+ u32 pad6;
+ u32 ifqepar;
+- u32 pad7[250];
++ u32 pad7[226];
++ u32 odmr;
++ u32 odsr;
++ u32 res0[4];
++ u32 oddpr;
++ u32 oddatr;
++ u32 res1[3];
++ u32 odretcr;
++ u32 res2[12];
+ u32 dmr;
+ u32 dsr;
+ u32 pad8;
+@@ -112,20 +134,12 @@ struct rio_tx_desc {
+ u32 res4;
+ };
+
+-static u32 regs_win;
+-static struct rio_atmu_regs *atmu_regs;
+-static struct rio_atmu_regs *maint_atmu_regs;
+-static struct rio_atmu_regs *dbell_atmu_regs;
+-static u32 dbell_win;
+-static u32 maint_win;
+-static struct rio_msg_regs *msg_regs;
+-
+-static struct rio_dbell_ring {
++struct rio_dbell_ring {
+ void *virt;
+ dma_addr_t phys;
+-} dbell_ring;
++};
+
+-static struct rio_msg_tx_ring {
++struct rio_msg_tx_ring {
+ void *virt;
+ dma_addr_t phys;
+ void *virt_buffer[RIO_MAX_TX_RING_SIZE];
+@@ -133,19 +147,35 @@ static struct rio_msg_tx_ring {
+ int tx_slot;
+ int size;
+ void *dev_id;
+-} msg_tx_ring;
++};
+
+-static struct rio_msg_rx_ring {
++struct rio_msg_rx_ring {
+ void *virt;
+ dma_addr_t phys;
+ void *virt_buffer[RIO_MAX_RX_RING_SIZE];
+ int rx_slot;
+ int size;
+ void *dev_id;
+-} msg_rx_ring;
++};
++
++struct rio_priv {
++ void __iomem *regs_win;
++ struct rio_atmu_regs __iomem *atmu_regs;
++ struct rio_atmu_regs __iomem *maint_atmu_regs;
++ struct rio_atmu_regs __iomem *dbell_atmu_regs;
++ void __iomem *dbell_win;
++ void __iomem *maint_win;
++ struct rio_msg_regs __iomem *msg_regs;
++ struct rio_dbell_ring dbell_ring;
++ struct rio_msg_tx_ring msg_tx_ring;
++ struct rio_msg_rx_ring msg_rx_ring;
++ int bellirq;
++ int txirq;
++ int rxirq;
++};
+
+ /**
+- * mpc85xx_rio_doorbell_send - Send a MPC85xx doorbell message
++ * fsl_rio_doorbell_send - Send a MPC85xx doorbell message
+ * @index: ID of RapidIO interface
+ * @destid: Destination ID of target device
+ * @data: 16-bit info field of RapidIO doorbell message
+@@ -153,18 +183,34 @@ static struct rio_msg_rx_ring {
+ * Sends a MPC85xx doorbell message. Returns %0 on success or
+ * %-EINVAL on failure.
+ */
+-static int mpc85xx_rio_doorbell_send(int index, u16 destid, u16 data)
++static int fsl_rio_doorbell_send(struct rio_mport *mport,
++ int index, u16 destid, u16 data)
+ {
+- pr_debug("mpc85xx_doorbell_send: index %d destid %4.4x data %4.4x\n",
++ struct rio_priv *priv = mport->priv;
++ pr_debug("fsl_doorbell_send: index %d destid %4.4x data %4.4x\n",
+ index, destid, data);
+- out_be32((void *)&dbell_atmu_regs->rowtar, destid << 22);
+- out_be16((void *)(dbell_win), data);
++ switch (mport->phy_type) {
++ case RIO_PHY_PARALLEL:
++ out_be32(&priv->dbell_atmu_regs->rowtar, destid << 22);
++ out_be16(priv->dbell_win, data);
++ break;
++ case RIO_PHY_SERIAL:
++ /* In the serial version silicons, such as MPC8548, MPC8641,
++ * below operations is must be.
++ */
++ out_be32(&priv->msg_regs->odmr, 0x00000000);
++ out_be32(&priv->msg_regs->odretcr, 0x00000004);
++ out_be32(&priv->msg_regs->oddpr, destid << 16);
++ out_be32(&priv->msg_regs->oddatr, data);
++ out_be32(&priv->msg_regs->odmr, 0x00000001);
++ break;
++ }
+
+ return 0;
+ }
+
+ /**
+- * mpc85xx_local_config_read - Generate a MPC85xx local config space read
++ * fsl_local_config_read - Generate a MPC85xx local config space read
+ * @index: ID of RapdiIO interface
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+@@ -173,17 +219,19 @@ static int mpc85xx_rio_doorbell_send(int index, u16 destid, u16 data)
+ * Generates a MPC85xx local configuration space read. Returns %0 on
+ * success or %-EINVAL on failure.
+ */
+-static int mpc85xx_local_config_read(int index, u32 offset, int len, u32 * data)
++static int fsl_local_config_read(struct rio_mport *mport,
++ int index, u32 offset, int len, u32 *data)
+ {
+- pr_debug("mpc85xx_local_config_read: index %d offset %8.8x\n", index,
++ struct rio_priv *priv = mport->priv;
++ pr_debug("fsl_local_config_read: index %d offset %8.8x\n", index,
+ offset);
+- *data = in_be32((void *)(regs_win + offset));
++ *data = in_be32(priv->regs_win + offset);
+
+ return 0;
+ }
+
+ /**
+- * mpc85xx_local_config_write - Generate a MPC85xx local config space write
++ * fsl_local_config_write - Generate a MPC85xx local config space write
+ * @index: ID of RapdiIO interface
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+@@ -192,18 +240,20 @@ static int mpc85xx_local_config_read(int index, u32 offset, int len, u32 * data)
+ * Generates a MPC85xx local configuration space write. Returns %0 on
+ * success or %-EINVAL on failure.
+ */
+-static int mpc85xx_local_config_write(int index, u32 offset, int len, u32 data)
++static int fsl_local_config_write(struct rio_mport *mport,
++ int index, u32 offset, int len, u32 data)
+ {
++ struct rio_priv *priv = mport->priv;
+ pr_debug
+- ("mpc85xx_local_config_write: index %d offset %8.8x data %8.8x\n",
++ ("fsl_local_config_write: index %d offset %8.8x data %8.8x\n",
+ index, offset, data);
+- out_be32((void *)(regs_win + offset), data);
++ out_be32(priv->regs_win + offset, data);
+
+ return 0;
+ }
+
+ /**
+- * mpc85xx_rio_config_read - Generate a MPC85xx read maintenance transaction
++ * fsl_rio_config_read - Generate a MPC85xx read maintenance transaction
+ * @index: ID of RapdiIO interface
+ * @destid: Destination ID of transaction
+ * @hopcount: Number of hops to target device
+@@ -215,18 +265,19 @@ static int mpc85xx_local_config_write(int index, u32 offset, int len, u32 data)
+ * success or %-EINVAL on failure.
+ */
+ static int
+-mpc85xx_rio_config_read(int index, u16 destid, u8 hopcount, u32 offset, int len,
+- u32 * val)
++fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
++ u8 hopcount, u32 offset, int len, u32 *val)
+ {
++ struct rio_priv *priv = mport->priv;
+ u8 *data;
+
+ pr_debug
+- ("mpc85xx_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n",
++ ("fsl_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n",
+ index, destid, hopcount, offset, len);
+- out_be32((void *)&maint_atmu_regs->rowtar,
++ out_be32(&priv->maint_atmu_regs->rowtar,
+ (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9));
+
+- data = (u8 *) maint_win + offset;
++ data = (u8 *) priv->maint_win + offset;
+ switch (len) {
+ case 1:
+ *val = in_8((u8 *) data);
+@@ -243,7 +294,7 @@ mpc85xx_rio_config_read(int index, u16 destid, u8 hopcount, u32 offset, int len,
+ }
+
+ /**
+- * mpc85xx_rio_config_write - Generate a MPC85xx write maintenance transaction
++ * fsl_rio_config_write - Generate a MPC85xx write maintenance transaction
+ * @index: ID of RapdiIO interface
+ * @destid: Destination ID of transaction
+ * @hopcount: Number of hops to target device
+@@ -255,17 +306,18 @@ mpc85xx_rio_config_read(int index, u16 destid, u8 hopcount, u32 offset, int len,
+ * success or %-EINVAL on failure.
+ */
+ static int
+-mpc85xx_rio_config_write(int index, u16 destid, u8 hopcount, u32 offset,
+- int len, u32 val)
++fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
++ u8 hopcount, u32 offset, int len, u32 val)
+ {
++ struct rio_priv *priv = mport->priv;
+ u8 *data;
+ pr_debug
+- ("mpc85xx_rio_config_write: index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n",
++ ("fsl_rio_config_write: index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n",
+ index, destid, hopcount, offset, len, val);
+- out_be32((void *)&maint_atmu_regs->rowtar,
++ out_be32(&priv->maint_atmu_regs->rowtar,
+ (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9));
+
+- data = (u8 *) maint_win + offset;
++ data = (u8 *) priv->maint_win + offset;
+ switch (len) {
+ case 1:
+ out_8((u8 *) data, val);
+@@ -296,9 +348,10 @@ int
+ rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox,
+ void *buffer, size_t len)
+ {
++ struct rio_priv *priv = mport->priv;
+ u32 omr;
+- struct rio_tx_desc *desc =
+- (struct rio_tx_desc *)msg_tx_ring.virt + msg_tx_ring.tx_slot;
++ struct rio_tx_desc *desc = (struct rio_tx_desc *)priv->msg_tx_ring.virt
++ + priv->msg_tx_ring.tx_slot;
+ int ret = 0;
+
+ pr_debug
+@@ -311,31 +364,43 @@ rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox,
+ }
+
+ /* Copy and clear rest of buffer */
+- memcpy(msg_tx_ring.virt_buffer[msg_tx_ring.tx_slot], buffer, len);
++ memcpy(priv->msg_tx_ring.virt_buffer[priv->msg_tx_ring.tx_slot], buffer,
++ len);
+ if (len < (RIO_MAX_MSG_SIZE - 4))
+- memset((void *)((u32) msg_tx_ring.
+- virt_buffer[msg_tx_ring.tx_slot] + len), 0,
+- RIO_MAX_MSG_SIZE - len);
++ memset(priv->msg_tx_ring.virt_buffer[priv->msg_tx_ring.tx_slot]
++ + len, 0, RIO_MAX_MSG_SIZE - len);
+
+- /* Set mbox field for message */
+- desc->dport = mbox & 0x3;
++ switch (mport->phy_type) {
++ case RIO_PHY_PARALLEL:
++ /* Set mbox field for message */
++ desc->dport = mbox & 0x3;
+
+- /* Enable EOMI interrupt, set priority, and set destid */
+- desc->dattr = 0x28000000 | (rdev->destid << 2);
++ /* Enable EOMI interrupt, set priority, and set destid */
++ desc->dattr = 0x28000000 | (rdev->destid << 2);
++ break;
++ case RIO_PHY_SERIAL:
++ /* Set mbox field for message, and set destid */
++ desc->dport = (rdev->destid << 16) | (mbox & 0x3);
++
++ /* Enable EOMI interrupt and priority */
++ desc->dattr = 0x28000000;
++ break;
++ }
+
+ /* Set transfer size aligned to next power of 2 (in double words) */
+ desc->dwcnt = is_power_of_2(len) ? len : 1 << get_bitmask_order(len);
+
+ /* Set snooping and source buffer address */
+- desc->saddr = 0x00000004 | msg_tx_ring.phys_buffer[msg_tx_ring.tx_slot];
++ desc->saddr = 0x00000004
++ | priv->msg_tx_ring.phys_buffer[priv->msg_tx_ring.tx_slot];
+
+ /* Increment enqueue pointer */
+- omr = in_be32((void *)&msg_regs->omr);
+- out_be32((void *)&msg_regs->omr, omr | RIO_MSG_OMR_MUI);
++ omr = in_be32(&priv->msg_regs->omr);
++ out_be32(&priv->msg_regs->omr, omr | RIO_MSG_OMR_MUI);
+
+ /* Go to next descriptor */
+- if (++msg_tx_ring.tx_slot == msg_tx_ring.size)
+- msg_tx_ring.tx_slot = 0;
++ if (++priv->msg_tx_ring.tx_slot == priv->msg_tx_ring.size)
++ priv->msg_tx_ring.tx_slot = 0;
+
+ out:
+ return ret;
+@@ -344,7 +409,7 @@ rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox,
+ EXPORT_SYMBOL_GPL(rio_hw_add_outb_message);
+
+ /**
+- * mpc85xx_rio_tx_handler - MPC85xx outbound message interrupt handler
++ * fsl_rio_tx_handler - MPC85xx outbound message interrupt handler
+ * @irq: Linux interrupt number
+ * @dev_instance: Pointer to interrupt-specific data
+ *
+@@ -352,32 +417,34 @@ EXPORT_SYMBOL_GPL(rio_hw_add_outb_message);
+ * mailbox event handler and acks the interrupt occurrence.
+ */
+ static irqreturn_t
+-mpc85xx_rio_tx_handler(int irq, void *dev_instance)
++fsl_rio_tx_handler(int irq, void *dev_instance)
+ {
+ int osr;
+ struct rio_mport *port = (struct rio_mport *)dev_instance;
++ struct rio_priv *priv = port->priv;
+
+- osr = in_be32((void *)&msg_regs->osr);
++ osr = in_be32(&priv->msg_regs->osr);
+
+ if (osr & RIO_MSG_OSR_TE) {
+ pr_info("RIO: outbound message transmission error\n");
+- out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_TE);
++ out_be32(&priv->msg_regs->osr, RIO_MSG_OSR_TE);
+ goto out;
+ }
+
+ if (osr & RIO_MSG_OSR_QOI) {
+ pr_info("RIO: outbound message queue overflow\n");
+- out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_QOI);
++ out_be32(&priv->msg_regs->osr, RIO_MSG_OSR_QOI);
+ goto out;
+ }
+
+ if (osr & RIO_MSG_OSR_EOMI) {
+- u32 dqp = in_be32((void *)&msg_regs->odqdpar);
+- int slot = (dqp - msg_tx_ring.phys) >> 5;
+- port->outb_msg[0].mcback(port, msg_tx_ring.dev_id, -1, slot);
++ u32 dqp = in_be32(&priv->msg_regs->odqdpar);
++ int slot = (dqp - priv->msg_tx_ring.phys) >> 5;
++ port->outb_msg[0].mcback(port, priv->msg_tx_ring.dev_id, -1,
++ slot);
+
+ /* Ack the end-of-message interrupt */
+- out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_EOMI);
++ out_be32(&priv->msg_regs->osr, RIO_MSG_OSR_EOMI);
+ }
+
+ out:
+@@ -398,6 +465,7 @@ mpc85xx_rio_tx_handler(int irq, void *dev_instance)
+ int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
+ {
+ int i, j, rc = 0;
++ struct rio_priv *priv = mport->priv;
+
+ if ((entries < RIO_MIN_TX_RING_SIZE) ||
+ (entries > RIO_MAX_TX_RING_SIZE) || (!is_power_of_2(entries))) {
+@@ -406,54 +474,53 @@ int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entr
+ }
+
+ /* Initialize shadow copy ring */
+- msg_tx_ring.dev_id = dev_id;
+- msg_tx_ring.size = entries;
+-
+- for (i = 0; i < msg_tx_ring.size; i++) {
+- if (!
+- (msg_tx_ring.virt_buffer[i] =
+- dma_alloc_coherent(NULL, RIO_MSG_BUFFER_SIZE,
+- &msg_tx_ring.phys_buffer[i],
+- GFP_KERNEL))) {
++ priv->msg_tx_ring.dev_id = dev_id;
++ priv->msg_tx_ring.size = entries;
++
++ for (i = 0; i < priv->msg_tx_ring.size; i++) {
++ priv->msg_tx_ring.virt_buffer[i] =
++ dma_alloc_coherent(NULL, RIO_MSG_BUFFER_SIZE,
++ &priv->msg_tx_ring.phys_buffer[i], GFP_KERNEL);
++ if (!priv->msg_tx_ring.virt_buffer[i]) {
+ rc = -ENOMEM;
+- for (j = 0; j < msg_tx_ring.size; j++)
+- if (msg_tx_ring.virt_buffer[j])
++ for (j = 0; j < priv->msg_tx_ring.size; j++)
++ if (priv->msg_tx_ring.virt_buffer[j])
+ dma_free_coherent(NULL,
+- RIO_MSG_BUFFER_SIZE,
+- msg_tx_ring.
+- virt_buffer[j],
+- msg_tx_ring.
+- phys_buffer[j]);
++ RIO_MSG_BUFFER_SIZE,
++ priv->msg_tx_ring.
++ virt_buffer[j],
++ priv->msg_tx_ring.
++ phys_buffer[j]);
+ goto out;
+ }
+ }
+
+ /* Initialize outbound message descriptor ring */
+- if (!(msg_tx_ring.virt = dma_alloc_coherent(NULL,
+- msg_tx_ring.size *
+- RIO_MSG_DESC_SIZE,
+- &msg_tx_ring.phys,
+- GFP_KERNEL))) {
++ priv->msg_tx_ring.virt = dma_alloc_coherent(NULL,
++ priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
++ &priv->msg_tx_ring.phys, GFP_KERNEL);
++ if (!priv->msg_tx_ring.virt) {
+ rc = -ENOMEM;
+ goto out_dma;
+ }
+- memset(msg_tx_ring.virt, 0, msg_tx_ring.size * RIO_MSG_DESC_SIZE);
+- msg_tx_ring.tx_slot = 0;
++ memset(priv->msg_tx_ring.virt, 0,
++ priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE);
++ priv->msg_tx_ring.tx_slot = 0;
+
+ /* Point dequeue/enqueue pointers at first entry in ring */
+- out_be32((void *)&msg_regs->odqdpar, msg_tx_ring.phys);
+- out_be32((void *)&msg_regs->odqepar, msg_tx_ring.phys);
++ out_be32(&priv->msg_regs->odqdpar, priv->msg_tx_ring.phys);
++ out_be32(&priv->msg_regs->odqepar, priv->msg_tx_ring.phys);
+
+ /* Configure for snooping */
+- out_be32((void *)&msg_regs->osar, 0x00000004);
++ out_be32(&priv->msg_regs->osar, 0x00000004);
+
+ /* Clear interrupt status */
+- out_be32((void *)&msg_regs->osr, 0x000000b3);
++ out_be32(&priv->msg_regs->osr, 0x000000b3);
+
+ /* Hook up outbound message handler */
+- if ((rc =
+- request_irq(MPC85xx_IRQ_RIO_TX, mpc85xx_rio_tx_handler, 0,
+- "msg_tx", (void *)mport)) < 0)
++ rc = request_irq(IRQ_RIO_TX(mport), fsl_rio_tx_handler, 0,
++ "msg_tx", (void *)mport);
++ if (rc < 0)
+ goto out_irq;
+
+ /*
+@@ -463,28 +530,28 @@ int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entr
+ * Chaining mode
+ * Disable
+ */
+- out_be32((void *)&msg_regs->omr, 0x00100220);
++ out_be32(&priv->msg_regs->omr, 0x00100220);
+
+ /* Set number of entries */
+- out_be32((void *)&msg_regs->omr,
+- in_be32((void *)&msg_regs->omr) |
++ out_be32(&priv->msg_regs->omr,
++ in_be32(&priv->msg_regs->omr) |
+ ((get_bitmask_order(entries) - 2) << 12));
+
+ /* Now enable the unit */
+- out_be32((void *)&msg_regs->omr, in_be32((void *)&msg_regs->omr) | 0x1);
++ out_be32(&priv->msg_regs->omr, in_be32(&priv->msg_regs->omr) | 0x1);
+
+ out:
+ return rc;
+
+ out_irq:
+- dma_free_coherent(NULL, msg_tx_ring.size * RIO_MSG_DESC_SIZE,
+- msg_tx_ring.virt, msg_tx_ring.phys);
++ dma_free_coherent(NULL, priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
++ priv->msg_tx_ring.virt, priv->msg_tx_ring.phys);
+
+ out_dma:
+- for (i = 0; i < msg_tx_ring.size; i++)
++ for (i = 0; i < priv->msg_tx_ring.size; i++)
+ dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE,
+- msg_tx_ring.virt_buffer[i],
+- msg_tx_ring.phys_buffer[i]);
++ priv->msg_tx_ring.virt_buffer[i],
++ priv->msg_tx_ring.phys_buffer[i]);
+
+ return rc;
+ }
+@@ -499,19 +566,20 @@ int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entr
+ */
+ void rio_close_outb_mbox(struct rio_mport *mport, int mbox)
+ {
++ struct rio_priv *priv = mport->priv;
+ /* Disable inbound message unit */
+- out_be32((void *)&msg_regs->omr, 0);
++ out_be32(&priv->msg_regs->omr, 0);
+
+ /* Free ring */
+- dma_free_coherent(NULL, msg_tx_ring.size * RIO_MSG_DESC_SIZE,
+- msg_tx_ring.virt, msg_tx_ring.phys);
++ dma_free_coherent(NULL, priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
++ priv->msg_tx_ring.virt, priv->msg_tx_ring.phys);
+
+ /* Free interrupt */
+- free_irq(MPC85xx_IRQ_RIO_TX, (void *)mport);
++ free_irq(IRQ_RIO_TX(mport), (void *)mport);
+ }
+
+ /**
+- * mpc85xx_rio_rx_handler - MPC85xx inbound message interrupt handler
++ * fsl_rio_rx_handler - MPC85xx inbound message interrupt handler
+ * @irq: Linux interrupt number
+ * @dev_instance: Pointer to interrupt-specific data
+ *
+@@ -519,16 +587,17 @@ void rio_close_outb_mbox(struct rio_mport *mport, int mbox)
+ * mailbox event handler and acks the interrupt occurrence.
+ */
+ static irqreturn_t
+-mpc85xx_rio_rx_handler(int irq, void *dev_instance)
++fsl_rio_rx_handler(int irq, void *dev_instance)
+ {
+ int isr;
+ struct rio_mport *port = (struct rio_mport *)dev_instance;
++ struct rio_priv *priv = port->priv;
+
+- isr = in_be32((void *)&msg_regs->isr);
++ isr = in_be32(&priv->msg_regs->isr);
+
+ if (isr & RIO_MSG_ISR_TE) {
+ pr_info("RIO: inbound message reception error\n");
+- out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_TE);
++ out_be32((void *)&priv->msg_regs->isr, RIO_MSG_ISR_TE);
+ goto out;
+ }
+
+@@ -540,10 +609,10 @@ mpc85xx_rio_rx_handler(int irq, void *dev_instance)
+ * make the callback with an unknown/invalid mailbox number
+ * argument.
+ */
+- port->inb_msg[0].mcback(port, msg_rx_ring.dev_id, -1, -1);
++ port->inb_msg[0].mcback(port, priv->msg_rx_ring.dev_id, -1, -1);
+
+ /* Ack the queueing interrupt */
+- out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_DIQI);
++ out_be32(&priv->msg_regs->isr, RIO_MSG_ISR_DIQI);
+ }
+
+ out:
+@@ -564,6 +633,7 @@ mpc85xx_rio_rx_handler(int irq, void *dev_instance)
+ int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
+ {
+ int i, rc = 0;
++ struct rio_priv *priv = mport->priv;
+
+ if ((entries < RIO_MIN_RX_RING_SIZE) ||
+ (entries > RIO_MAX_RX_RING_SIZE) || (!is_power_of_2(entries))) {
+@@ -572,36 +642,35 @@ int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entri
+ }
+
+ /* Initialize client buffer ring */
+- msg_rx_ring.dev_id = dev_id;
+- msg_rx_ring.size = entries;
+- msg_rx_ring.rx_slot = 0;
+- for (i = 0; i < msg_rx_ring.size; i++)
+- msg_rx_ring.virt_buffer[i] = NULL;
++ priv->msg_rx_ring.dev_id = dev_id;
++ priv->msg_rx_ring.size = entries;
++ priv->msg_rx_ring.rx_slot = 0;
++ for (i = 0; i < priv->msg_rx_ring.size; i++)
++ priv->msg_rx_ring.virt_buffer[i] = NULL;
+
+ /* Initialize inbound message ring */
+- if (!(msg_rx_ring.virt = dma_alloc_coherent(NULL,
+- msg_rx_ring.size *
+- RIO_MAX_MSG_SIZE,
+- &msg_rx_ring.phys,
+- GFP_KERNEL))) {
++ priv->msg_rx_ring.virt = dma_alloc_coherent(NULL,
++ priv->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
++ &priv->msg_rx_ring.phys, GFP_KERNEL);
++ if (!priv->msg_rx_ring.virt) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ /* Point dequeue/enqueue pointers at first entry in ring */
+- out_be32((void *)&msg_regs->ifqdpar, (u32) msg_rx_ring.phys);
+- out_be32((void *)&msg_regs->ifqepar, (u32) msg_rx_ring.phys);
++ out_be32(&priv->msg_regs->ifqdpar, (u32) priv->msg_rx_ring.phys);
++ out_be32(&priv->msg_regs->ifqepar, (u32) priv->msg_rx_ring.phys);
+
+ /* Clear interrupt status */
+- out_be32((void *)&msg_regs->isr, 0x00000091);
++ out_be32(&priv->msg_regs->isr, 0x00000091);
+
+ /* Hook up inbound message handler */
+- if ((rc =
+- request_irq(MPC85xx_IRQ_RIO_RX, mpc85xx_rio_rx_handler, 0,
+- "msg_rx", (void *)mport)) < 0) {
++ rc = request_irq(IRQ_RIO_RX(mport), fsl_rio_rx_handler, 0,
++ "msg_rx", (void *)mport);
++ if (rc < 0) {
+ dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE,
+- msg_tx_ring.virt_buffer[i],
+- msg_tx_ring.phys_buffer[i]);
++ priv->msg_tx_ring.virt_buffer[i],
++ priv->msg_tx_ring.phys_buffer[i]);
+ goto out;
+ }
+
+@@ -612,15 +681,13 @@ int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entri
+ * Unmask all interrupt sources
+ * Disable
+ */
+- out_be32((void *)&msg_regs->imr, 0x001b0060);
++ out_be32(&priv->msg_regs->imr, 0x001b0060);
+
+ /* Set number of queue entries */
+- out_be32((void *)&msg_regs->imr,
+- in_be32((void *)&msg_regs->imr) |
+- ((get_bitmask_order(entries) - 2) << 12));
++ setbits32(&priv->msg_regs->imr, (get_bitmask_order(entries) - 2) << 12);
+
+ /* Now enable the unit */
+- out_be32((void *)&msg_regs->imr, in_be32((void *)&msg_regs->imr) | 0x1);
++ setbits32(&priv->msg_regs->imr, 0x1);
+
+ out:
+ return rc;
+@@ -636,15 +703,16 @@ int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entri
+ */
+ void rio_close_inb_mbox(struct rio_mport *mport, int mbox)
+ {
++ struct rio_priv *priv = mport->priv;
+ /* Disable inbound message unit */
+- out_be32((void *)&msg_regs->imr, 0);
++ out_be32(&priv->msg_regs->imr, 0);
+
+ /* Free ring */
+- dma_free_coherent(NULL, msg_rx_ring.size * RIO_MAX_MSG_SIZE,
+- msg_rx_ring.virt, msg_rx_ring.phys);
++ dma_free_coherent(NULL, priv->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
++ priv->msg_rx_ring.virt, priv->msg_rx_ring.phys);
+
+ /* Free interrupt */
+- free_irq(MPC85xx_IRQ_RIO_RX, (void *)mport);
++ free_irq(IRQ_RIO_RX(mport), (void *)mport);
+ }
+
+ /**
+@@ -659,21 +727,22 @@ void rio_close_inb_mbox(struct rio_mport *mport, int mbox)
+ int rio_hw_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf)
+ {
+ int rc = 0;
++ struct rio_priv *priv = mport->priv;
+
+ pr_debug("RIO: rio_hw_add_inb_buffer(), msg_rx_ring.rx_slot %d\n",
+- msg_rx_ring.rx_slot);
++ priv->msg_rx_ring.rx_slot);
+
+- if (msg_rx_ring.virt_buffer[msg_rx_ring.rx_slot]) {
++ if (priv->msg_rx_ring.virt_buffer[priv->msg_rx_ring.rx_slot]) {
+ printk(KERN_ERR
+ "RIO: error adding inbound buffer %d, buffer exists\n",
+- msg_rx_ring.rx_slot);
++ priv->msg_rx_ring.rx_slot);
+ rc = -EINVAL;
+ goto out;
+ }
+
+- msg_rx_ring.virt_buffer[msg_rx_ring.rx_slot] = buf;
+- if (++msg_rx_ring.rx_slot == msg_rx_ring.size)
+- msg_rx_ring.rx_slot = 0;
++ priv->msg_rx_ring.virt_buffer[priv->msg_rx_ring.rx_slot] = buf;
++ if (++priv->msg_rx_ring.rx_slot == priv->msg_rx_ring.size)
++ priv->msg_rx_ring.rx_slot = 0;
+
+ out:
+ return rc;
+@@ -691,20 +760,21 @@ EXPORT_SYMBOL_GPL(rio_hw_add_inb_buffer);
+ */
+ void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox)
+ {
+- u32 imr;
++ struct rio_priv *priv = mport->priv;
+ u32 phys_buf, virt_buf;
+ void *buf = NULL;
+ int buf_idx;
+
+- phys_buf = in_be32((void *)&msg_regs->ifqdpar);
++ phys_buf = in_be32(&priv->msg_regs->ifqdpar);
+
+ /* If no more messages, then bail out */
+- if (phys_buf == in_be32((void *)&msg_regs->ifqepar))
++ if (phys_buf == in_be32(&priv->msg_regs->ifqepar))
+ goto out2;
+
+- virt_buf = (u32) msg_rx_ring.virt + (phys_buf - msg_rx_ring.phys);
+- buf_idx = (phys_buf - msg_rx_ring.phys) / RIO_MAX_MSG_SIZE;
+- buf = msg_rx_ring.virt_buffer[buf_idx];
++ virt_buf = (u32) priv->msg_rx_ring.virt + (phys_buf
++ - priv->msg_rx_ring.phys);
++ buf_idx = (phys_buf - priv->msg_rx_ring.phys) / RIO_MAX_MSG_SIZE;
++ buf = priv->msg_rx_ring.virt_buffer[buf_idx];
+
+ if (!buf) {
+ printk(KERN_ERR
+@@ -716,11 +786,10 @@ void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox)
+ memcpy(buf, (void *)virt_buf, RIO_MAX_MSG_SIZE);
+
+ /* Clear the available buffer */
+- msg_rx_ring.virt_buffer[buf_idx] = NULL;
++ priv->msg_rx_ring.virt_buffer[buf_idx] = NULL;
+
+ out1:
+- imr = in_be32((void *)&msg_regs->imr);
+- out_be32((void *)&msg_regs->imr, imr | RIO_MSG_IMR_MI);
++ setbits32(&priv->msg_regs->imr, RIO_MSG_IMR_MI);
+
+ out2:
+ return buf;
+@@ -729,7 +798,7 @@ void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox)
+ EXPORT_SYMBOL_GPL(rio_hw_get_inb_message);
+
+ /**
+- * mpc85xx_rio_dbell_handler - MPC85xx doorbell interrupt handler
++ * fsl_rio_dbell_handler - MPC85xx doorbell interrupt handler
+ * @irq: Linux interrupt number
+ * @dev_instance: Pointer to interrupt-specific data
+ *
+@@ -737,31 +806,31 @@ EXPORT_SYMBOL_GPL(rio_hw_get_inb_message);
+ * doorbell event handlers and executes a matching event handler.
+ */
+ static irqreturn_t
+-mpc85xx_rio_dbell_handler(int irq, void *dev_instance)
++fsl_rio_dbell_handler(int irq, void *dev_instance)
+ {
+ int dsr;
+ struct rio_mport *port = (struct rio_mport *)dev_instance;
++ struct rio_priv *priv = port->priv;
+
+- dsr = in_be32((void *)&msg_regs->dsr);
++ dsr = in_be32(&priv->msg_regs->dsr);
+
+ if (dsr & DOORBELL_DSR_TE) {
+ pr_info("RIO: doorbell reception error\n");
+- out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_TE);
++ out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_TE);
+ goto out;
+ }
+
+ if (dsr & DOORBELL_DSR_QFI) {
+ pr_info("RIO: doorbell queue full\n");
+- out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_QFI);
++ out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_QFI);
+ goto out;
+ }
+
+ /* XXX Need to check/dispatch until queue empty */
+ if (dsr & DOORBELL_DSR_DIQI) {
+ u32 dmsg =
+- (u32) dbell_ring.virt +
+- (in_be32((void *)&msg_regs->dqdpar) & 0xfff);
+- u32 dmr;
++ (u32) priv->dbell_ring.virt +
++ (in_be32(&priv->msg_regs->dqdpar) & 0xfff);
+ struct rio_dbell *dbell;
+ int found = 0;
+
+@@ -784,9 +853,8 @@ mpc85xx_rio_dbell_handler(int irq, void *dev_instance)
+ ("RIO: spurious doorbell, sid %2.2x tid %2.2x info %4.4x\n",
+ DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg));
+ }
+- dmr = in_be32((void *)&msg_regs->dmr);
+- out_be32((void *)&msg_regs->dmr, dmr | DOORBELL_DMR_DI);
+- out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_DIQI);
++ setbits32(&priv->msg_regs->dmr, DOORBELL_DMR_DI);
++ out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_DIQI);
+ }
+
+ out:
+@@ -794,21 +862,22 @@ mpc85xx_rio_dbell_handler(int irq, void *dev_instance)
+ }
+
+ /**
+- * mpc85xx_rio_doorbell_init - MPC85xx doorbell interface init
++ * fsl_rio_doorbell_init - MPC85xx doorbell interface init
+ * @mport: Master port implementing the inbound doorbell unit
+ *
+ * Initializes doorbell unit hardware and inbound DMA buffer
+- * ring. Called from mpc85xx_rio_setup(). Returns %0 on success
++ * ring. Called from fsl_rio_setup(). Returns %0 on success
+ * or %-ENOMEM on failure.
+ */
+-static int mpc85xx_rio_doorbell_init(struct rio_mport *mport)
++static int fsl_rio_doorbell_init(struct rio_mport *mport)
+ {
++ struct rio_priv *priv = mport->priv;
+ int rc = 0;
+
+ /* Map outbound doorbell window immediately after maintenance window */
+- if (!(dbell_win =
+- (u32) ioremap(mport->iores.start + RIO_MAINT_WIN_SIZE,
+- RIO_DBELL_WIN_SIZE))) {
++ priv->dbell_win = ioremap(mport->iores.start + RIO_MAINT_WIN_SIZE,
++ RIO_DBELL_WIN_SIZE);
++ if (!priv->dbell_win) {
+ printk(KERN_ERR
+ "RIO: unable to map outbound doorbell window\n");
+ rc = -ENOMEM;
+@@ -816,37 +885,36 @@ static int mpc85xx_rio_doorbell_init(struct rio_mport *mport)
+ }
+
+ /* Initialize inbound doorbells */
+- if (!(dbell_ring.virt = dma_alloc_coherent(NULL,
+- 512 * DOORBELL_MESSAGE_SIZE,
+- &dbell_ring.phys,
+- GFP_KERNEL))) {
++ priv->dbell_ring.virt = dma_alloc_coherent(NULL, 512 *
++ DOORBELL_MESSAGE_SIZE, &priv->dbell_ring.phys, GFP_KERNEL);
++ if (!priv->dbell_ring.virt) {
+ printk(KERN_ERR "RIO: unable allocate inbound doorbell ring\n");
+ rc = -ENOMEM;
+- iounmap((void *)dbell_win);
++ iounmap(priv->dbell_win);
+ goto out;
+ }
+
+ /* Point dequeue/enqueue pointers at first entry in ring */
+- out_be32((void *)&msg_regs->dqdpar, (u32) dbell_ring.phys);
+- out_be32((void *)&msg_regs->dqepar, (u32) dbell_ring.phys);
++ out_be32(&priv->msg_regs->dqdpar, (u32) priv->dbell_ring.phys);
++ out_be32(&priv->msg_regs->dqepar, (u32) priv->dbell_ring.phys);
+
+ /* Clear interrupt status */
+- out_be32((void *)&msg_regs->dsr, 0x00000091);
++ out_be32(&priv->msg_regs->dsr, 0x00000091);
+
+ /* Hook up doorbell handler */
+- if ((rc =
+- request_irq(MPC85xx_IRQ_RIO_BELL, mpc85xx_rio_dbell_handler, 0,
+- "dbell_rx", (void *)mport) < 0)) {
+- iounmap((void *)dbell_win);
++ rc = request_irq(IRQ_RIO_BELL(mport), fsl_rio_dbell_handler, 0,
++ "dbell_rx", (void *)mport);
++ if (rc < 0) {
++ iounmap(priv->dbell_win);
+ dma_free_coherent(NULL, 512 * DOORBELL_MESSAGE_SIZE,
+- dbell_ring.virt, dbell_ring.phys);
++ priv->dbell_ring.virt, priv->dbell_ring.phys);
+ printk(KERN_ERR
+ "MPC85xx RIO: unable to request inbound doorbell irq");
+ goto out;
+ }
+
+ /* Configure doorbells for snooping, 512 entries, and enable */
+- out_be32((void *)&msg_regs->dmr, 0x00108161);
++ out_be32(&priv->msg_regs->dmr, 0x00108161);
+
+ out:
+ return rc;
+@@ -854,7 +922,7 @@ static int mpc85xx_rio_doorbell_init(struct rio_mport *mport)
+
+ static char *cmdline = NULL;
+
+-static int mpc85xx_rio_get_hdid(int index)
++static int fsl_rio_get_hdid(int index)
+ {
+ /* XXX Need to parse multiple entries in some format */
+ if (!cmdline)
+@@ -863,7 +931,7 @@ static int mpc85xx_rio_get_hdid(int index)
+ return simple_strtol(cmdline, NULL, 0);
+ }
+
+-static int mpc85xx_rio_get_cmdline(char *s)
++static int fsl_rio_get_cmdline(char *s)
+ {
+ if (!s)
+ return 0;
+@@ -872,61 +940,266 @@ static int mpc85xx_rio_get_cmdline(char *s)
+ return 1;
+ }
+
+-__setup("riohdid=", mpc85xx_rio_get_cmdline);
++__setup("riohdid=", fsl_rio_get_cmdline);
++
++static inline void fsl_rio_info(struct device *dev, u32 ccsr)
++{
++ const char *str;
++ if (ccsr & 1) {
++ /* Serial phy */
++ switch (ccsr >> 30) {
++ case 0:
++ str = "1";
++ break;
++ case 1:
++ str = "4";
++ break;
++ default:
++ str = "Unknown";
++ break;;
++ }
++ dev_info(dev, "Hardware port width: %s\n", str);
++
++ switch ((ccsr >> 27) & 7) {
++ case 0:
++ str = "Single-lane 0";
++ break;
++ case 1:
++ str = "Single-lane 2";
++ break;
++ case 2:
++ str = "Four-lane";
++ break;
++ default:
++ str = "Unknown";
++ break;
++ }
++ dev_info(dev, "Training connection status: %s\n", str);
++ } else {
++ /* Parallel phy */
++ if (!(ccsr & 0x80000000))
++ dev_info(dev, "Output port operating in 8-bit mode\n");
++ if (!(ccsr & 0x08000000))
++ dev_info(dev, "Input port operating in 8-bit mode\n");
++ }
++}
+
+ /**
+- * mpc85xx_rio_setup - Setup MPC85xx RapidIO interface
+- * @law_start: Starting physical address of RapidIO LAW
+- * @law_size: Size of RapidIO LAW
++ * fsl_rio_setup - Setup MPC85xx RapidIO interface
++ * @fsl_rio_setup - Setup Freescale PowerPC RapidIO interface
+ *
+ * Initializes MPC85xx RapidIO hardware interface, configures
+ * master port with system-specific info, and registers the
+ * master port with the RapidIO subsystem.
+ */
+-void mpc85xx_rio_setup(int law_start, int law_size)
++int fsl_rio_setup(struct of_device *dev)
+ {
+ struct rio_ops *ops;
+ struct rio_mport *port;
++ struct rio_priv *priv;
++ int rc = 0;
++ const u32 *dt_range, *cell;
++ struct resource regs;
++ int rlen;
++ u32 ccsr;
++ u64 law_start, law_size;
++ int paw, aw, sw;
++
++ if (!dev->node) {
++ dev_err(&dev->dev, "Device OF-Node is NULL");
++ return -EFAULT;
++ }
++
++ rc = of_address_to_resource(dev->node, 0, ®s);
++ if (rc) {
++ dev_err(&dev->dev, "Can't get %s property 'reg'\n",
++ dev->node->full_name);
++ return -EFAULT;
++ }
++ dev_info(&dev->dev, "Of-device full name %s\n", dev->node->full_name);
++ dev_info(&dev->dev, "Regs start 0x%08x size 0x%08x\n", regs.start,
++ regs.end - regs.start + 1);
++
++ dt_range = of_get_property(dev->node, "ranges", &rlen);
++ if (!dt_range) {
++ dev_err(&dev->dev, "Can't get %s property 'ranges'\n",
++ dev->node->full_name);
++ return -EFAULT;
++ }
++
++ /* Get node address wide */
++ cell = of_get_property(dev->node, "#address-cells", NULL);
++ if (cell)
++ aw = *cell;
++ else
++ aw = of_n_addr_cells(dev->node);
++ /* Get node size wide */
++ cell = of_get_property(dev->node, "#size-cells", NULL);
++ if (cell)
++ sw = *cell;
++ else
++ sw = of_n_size_cells(dev->node);
++ /* Get parent address wide wide */
++ paw = of_n_addr_cells(dev->node);
++
++ law_start = of_read_number(dt_range + aw, paw);
++ law_size = of_read_number(dt_range + aw + paw, sw);
++
++ dev_info(&dev->dev, "LAW start 0x%016llx, size 0x%016llx.\n",
++ law_start, law_size);
+
+ ops = kmalloc(sizeof(struct rio_ops), GFP_KERNEL);
+- ops->lcread = mpc85xx_local_config_read;
+- ops->lcwrite = mpc85xx_local_config_write;
+- ops->cread = mpc85xx_rio_config_read;
+- ops->cwrite = mpc85xx_rio_config_write;
+- ops->dsend = mpc85xx_rio_doorbell_send;
++ ops->lcread = fsl_local_config_read;
++ ops->lcwrite = fsl_local_config_write;
++ ops->cread = fsl_rio_config_read;
++ ops->cwrite = fsl_rio_config_write;
++ ops->dsend = fsl_rio_doorbell_send;
+
+- port = kmalloc(sizeof(struct rio_mport), GFP_KERNEL);
++ port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL);
+ port->id = 0;
+ port->index = 0;
++
++ priv = kzalloc(sizeof(struct rio_priv), GFP_KERNEL);
++ if (!priv) {
++ printk(KERN_ERR "Can't alloc memory for 'priv'\n");
++ rc = -ENOMEM;
++ goto err;
++ }
++
+ INIT_LIST_HEAD(&port->dbells);
+ port->iores.start = law_start;
+ port->iores.end = law_start + law_size;
+ port->iores.flags = IORESOURCE_MEM;
+
++ priv->bellirq = irq_of_parse_and_map(dev->node, 2);
++ priv->txirq = irq_of_parse_and_map(dev->node, 3);
++ priv->rxirq = irq_of_parse_and_map(dev->node, 4);
++ dev_info(&dev->dev, "bellirq: %d, txirq: %d, rxirq %d\n", priv->bellirq,
++ priv->txirq, priv->rxirq);
++
+ rio_init_dbell_res(&port->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff);
+ rio_init_mbox_res(&port->riores[RIO_INB_MBOX_RESOURCE], 0, 0);
+ rio_init_mbox_res(&port->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0);
+ strcpy(port->name, "RIO0 mport");
+
+ port->ops = ops;
+- port->host_deviceid = mpc85xx_rio_get_hdid(port->id);
++ port->host_deviceid = fsl_rio_get_hdid(port->id);
+
++ port->priv = priv;
+ rio_register_mport(port);
+
+- regs_win = (u32) ioremap(RIO_REGS_BASE, 0x20000);
+- atmu_regs = (struct rio_atmu_regs *)(regs_win + RIO_ATMU_REGS_OFFSET);
+- maint_atmu_regs = atmu_regs + 1;
+- dbell_atmu_regs = atmu_regs + 2;
+- msg_regs = (struct rio_msg_regs *)(regs_win + RIO_MSG_REGS_OFFSET);
++ priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1);
++
++ /* Probe the master port phy type */
++ ccsr = in_be32(priv->regs_win + RIO_CCSR);
++ port->phy_type = (ccsr & 1) ? RIO_PHY_SERIAL : RIO_PHY_PARALLEL;
++ dev_info(&dev->dev, "RapidIO PHY type: %s\n",
++ (port->phy_type == RIO_PHY_PARALLEL) ? "parallel" :
++ ((port->phy_type == RIO_PHY_SERIAL) ? "serial" :
++ "unknown"));
++ /* Checking the port training status */
++ if (in_be32((priv->regs_win + RIO_ESCSR)) & 1) {
++ dev_err(&dev->dev, "Port is not ready. "
++ "Try to restart connection...\n");
++ switch (port->phy_type) {
++ case RIO_PHY_SERIAL:
++ /* Disable ports */
++ out_be32(priv->regs_win + RIO_CCSR, 0);
++ /* Set 1x lane */
++ setbits32(priv->regs_win + RIO_CCSR, 0x02000000);
++ /* Enable ports */
++ setbits32(priv->regs_win + RIO_CCSR, 0x00600000);
++ break;
++ case RIO_PHY_PARALLEL:
++ /* Disable ports */
++ out_be32(priv->regs_win + RIO_CCSR, 0x22000000);
++ /* Enable ports */
++ out_be32(priv->regs_win + RIO_CCSR, 0x44000000);
++ break;
++ }
++ msleep(100);
++ if (in_be32((priv->regs_win + RIO_ESCSR)) & 1) {
++ dev_err(&dev->dev, "Port restart failed.\n");
++ rc = -ENOLINK;
++ goto err;
++ }
++ dev_info(&dev->dev, "Port restart success!\n");
++ }
++ fsl_rio_info(&dev->dev, ccsr);
++
++ port->sys_size = (in_be32((priv->regs_win + RIO_PEF_CAR))
++ & RIO_PEF_CTLS) >> 4;
++ dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n",
++ port->sys_size ? 65536 : 256);
++
++ priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win
++ + RIO_ATMU_REGS_OFFSET);
++ priv->maint_atmu_regs = priv->atmu_regs + 1;
++ priv->dbell_atmu_regs = priv->atmu_regs + 2;
++ priv->msg_regs = (struct rio_msg_regs *)(priv->regs_win +
++ ((port->phy_type == RIO_PHY_SERIAL) ?
++ RIO_S_MSG_REGS_OFFSET : RIO_P_MSG_REGS_OFFSET));
++
++ /* Set to receive any dist ID for serial RapidIO controller. */
++ if (port->phy_type == RIO_PHY_SERIAL)
++ out_be32((priv->regs_win + RIO_ISR_AACR), RIO_ISR_AACR_AA);
+
+ /* Configure maintenance transaction window */
+- out_be32((void *)&maint_atmu_regs->rowbar, 0x000c0000);
+- out_be32((void *)&maint_atmu_regs->rowar, 0x80077015);
++ out_be32(&priv->maint_atmu_regs->rowbar, 0x000c0000);
++ out_be32(&priv->maint_atmu_regs->rowar, 0x80077015);
+
+- maint_win = (u32) ioremap(law_start, RIO_MAINT_WIN_SIZE);
++ priv->maint_win = ioremap(law_start, RIO_MAINT_WIN_SIZE);
+
+ /* Configure outbound doorbell window */
+- out_be32((void *)&dbell_atmu_regs->rowbar, 0x000c0400);
+- out_be32((void *)&dbell_atmu_regs->rowar, 0x8004200b);
+- mpc85xx_rio_doorbell_init(port);
++ out_be32(&priv->dbell_atmu_regs->rowbar, 0x000c0400);
++ out_be32(&priv->dbell_atmu_regs->rowar, 0x8004200b);
++ fsl_rio_doorbell_init(port);
++
++ return 0;
++err:
++ if (priv)
++ iounmap(priv->regs_win);
++ kfree(ops);
++ kfree(priv);
++ kfree(port);
++ return rc;
++}
++
++/* The probe function for RapidIO peer-to-peer network.
++ */
++static int __devinit fsl_of_rio_rpn_probe(struct of_device *dev,
++ const struct of_device_id *match)
++{
++ int rc;
++ printk(KERN_INFO "Setting up RapidIO peer-to-peer network %s\n",
++ dev->node->full_name);
++
++ rc = fsl_rio_setup(dev);
++ if (rc)
++ goto out;
++
++ /* Enumerate all registered ports */
++ rc = rio_init_mports();
++out:
++ return rc;
++};
++
++static const struct of_device_id fsl_of_rio_rpn_ids[] = {
++ {
++ .compatible = "fsl,rapidio-delta",
++ },
++ {},
++};
++
++static struct of_platform_driver fsl_of_rio_rpn_driver = {
++ .name = "fsl-of-rio",
++ .match_table = fsl_of_rio_rpn_ids,
++ .probe = fsl_of_rio_rpn_probe,
++};
++
++static __init int fsl_of_rio_rpn_init(void)
++{
++ return of_register_platform_driver(&fsl_of_rio_rpn_driver);
+ }
++
++subsys_initcall(fsl_of_rio_rpn_init);
+diff --git a/arch/powerpc/sysdev/fsl_rio.h b/arch/powerpc/sysdev/fsl_rio.h
+deleted file mode 100644
+index 6d3ff30..0000000
+--- a/arch/powerpc/sysdev/fsl_rio.h
++++ /dev/null
+@@ -1,20 +0,0 @@
+-/*
+- * MPC85xx RapidIO definitions
+- *
+- * Copyright 2005 MontaVista Software, Inc.
+- * Matt Porter <mporter at kernel.crashing.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.
+- */
+-
+-#ifndef __PPC_SYSLIB_PPC85XX_RIO_H
+-#define __PPC_SYSLIB_PPC85XX_RIO_H
+-
+-#include <linux/init.h>
+-
+-extern void mpc85xx_rio_setup(int law_start, int law_size);
+-
+-#endif /* __PPC_SYSLIB_PPC85XX_RIO_H */
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
-index 2c5388c..5c1b246 100644
+index 2c5388c..324c01b 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)
@@ -204601,7 +249052,52 @@
of_node_put(phy);
of_node_put(mdio);
-@@ -516,9 +544,9 @@ arch_initcall(fsl_i2c_of_init);
+@@ -390,22 +418,21 @@ arch_initcall(gfar_of_init);
+ #include <linux/i2c.h>
+ struct i2c_driver_device {
+ char *of_device;
+- char *i2c_driver;
+ char *i2c_type;
+ };
+
+ static struct i2c_driver_device i2c_devices[] __initdata = {
+- {"ricoh,rs5c372a", "rtc-rs5c372", "rs5c372a",},
+- {"ricoh,rs5c372b", "rtc-rs5c372", "rs5c372b",},
+- {"ricoh,rv5c386", "rtc-rs5c372", "rv5c386",},
+- {"ricoh,rv5c387a", "rtc-rs5c372", "rv5c387a",},
+- {"dallas,ds1307", "rtc-ds1307", "ds1307",},
+- {"dallas,ds1337", "rtc-ds1307", "ds1337",},
+- {"dallas,ds1338", "rtc-ds1307", "ds1338",},
+- {"dallas,ds1339", "rtc-ds1307", "ds1339",},
+- {"dallas,ds1340", "rtc-ds1307", "ds1340",},
+- {"stm,m41t00", "rtc-ds1307", "m41t00"},
+- {"dallas,ds1374", "rtc-ds1374", "rtc-ds1374",},
++ {"ricoh,rs5c372a", "rs5c372a"},
++ {"ricoh,rs5c372b", "rs5c372b"},
++ {"ricoh,rv5c386", "rv5c386"},
++ {"ricoh,rv5c387a", "rv5c387a"},
++ {"dallas,ds1307", "ds1307"},
++ {"dallas,ds1337", "ds1337"},
++ {"dallas,ds1338", "ds1338"},
++ {"dallas,ds1339", "ds1339"},
++ {"dallas,ds1340", "ds1340"},
++ {"stm,m41t00", "m41t00"},
++ {"dallas,ds1374", "rtc-ds1374"},
+ };
+
+ static int __init of_find_i2c_driver(struct device_node *node,
+@@ -416,9 +443,7 @@ static int __init of_find_i2c_driver(struct device_node *node,
+ for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) {
+ if (!of_device_is_compatible(node, i2c_devices[i].of_device))
+ continue;
+- if (strlcpy(info->driver_name, i2c_devices[i].i2c_driver,
+- KOBJ_NAME_LEN) >= KOBJ_NAME_LEN ||
+- strlcpy(info->type, i2c_devices[i].i2c_type,
++ if (strlcpy(info->type, i2c_devices[i].i2c_type,
+ I2C_NAME_SIZE) >= I2C_NAME_SIZE)
+ return -ENOMEM;
+ return 0;
+@@ -516,9 +541,9 @@ arch_initcall(fsl_i2c_of_init);
static int __init mpc83xx_wdt_init(void)
{
struct resource r;
@@ -204613,7 +249109,7 @@
int ret;
np = of_find_compatible_node(NULL, "watchdog", "mpc83xx_wdt");
-@@ -528,19 +556,6 @@ static int __init mpc83xx_wdt_init(void)
+@@ -528,19 +553,6 @@ static int __init mpc83xx_wdt_init(void)
goto nodev;
}
@@ -204633,7 +249129,7 @@
memset(&r, 0, sizeof(r));
ret = of_address_to_resource(np, 0, &r);
-@@ -553,20 +568,16 @@ static int __init mpc83xx_wdt_init(void)
+@@ -553,20 +565,16 @@ static int __init mpc83xx_wdt_init(void)
goto err;
}
@@ -204655,7 +249151,7 @@
of_node_put(np);
nodev:
return ret;
-@@ -735,547 +746,6 @@ err:
+@@ -735,547 +743,6 @@ err:
arch_initcall(fsl_usb_of_init);
@@ -205203,7 +249699,7 @@
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,
+@@ -1371,25 +838,9 @@ int __init fsl_spi_init(struct spi_board_info *board_infos,
sysclk = get_brgfreq();
#endif
if (sysclk == -1) {
@@ -205231,8 +249727,53 @@
}
ret = of_fsl_spi_probe(NULL, "fsl,spi", sysclk, board_infos,
+@@ -1438,3 +889,44 @@ void fsl_rstcr_restart(char *cmd)
+ while (1) ;
+ }
+ #endif
++
++#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
++struct platform_diu_data_ops diu_ops = {
++ .diu_size = 1280 * 1024 * 4, /* default one 1280x1024 buffer */
++};
++EXPORT_SYMBOL(diu_ops);
++
++int __init preallocate_diu_videomemory(void)
++{
++ pr_debug("diu_size=%lu\n", diu_ops.diu_size);
++
++ diu_ops.diu_mem = __alloc_bootmem(diu_ops.diu_size, 8, 0);
++ if (!diu_ops.diu_mem) {
++ printk(KERN_ERR "fsl-diu: cannot allocate %lu bytes\n",
++ diu_ops.diu_size);
++ return -ENOMEM;
++ }
++
++ pr_debug("diu_mem=%p\n", diu_ops.diu_mem);
++
++ rh_init(&diu_ops.diu_rh_info, 4096, ARRAY_SIZE(diu_ops.diu_rh_block),
++ diu_ops.diu_rh_block);
++ return rh_attach_region(&diu_ops.diu_rh_info,
++ (unsigned long) diu_ops.diu_mem,
++ diu_ops.diu_size);
++}
++
++static int __init early_parse_diufb(char *p)
++{
++ if (!p)
++ return 1;
++
++ diu_ops.diu_size = _ALIGN_UP(memparse(p, &p), 8);
++
++ pr_debug("diu_size=%lu\n", diu_ops.diu_size);
++
++ return 0;
++}
++early_param("diufb", early_parse_diufb);
++
++#endif
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
-index 63e7db3..74c4a96 100644
+index 63e7db3..52c831f 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -7,6 +7,7 @@
@@ -205243,6 +249784,35 @@
struct spi_board_info;
+@@ -16,5 +17,28 @@ extern int fsl_spi_init(struct spi_board_info *board_infos,
+ void (*deactivate_cs)(u8 cs, u8 polarity));
+
+ extern void fsl_rstcr_restart(char *cmd);
++
++#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
++#include <linux/bootmem.h>
++#include <asm/rheap.h>
++struct platform_diu_data_ops {
++ rh_block_t diu_rh_block[16];
++ rh_info_t diu_rh_info;
++ unsigned long diu_size;
++ void *diu_mem;
++
++ unsigned int (*get_pixel_format) (unsigned int bits_per_pixel,
++ int monitor_port);
++ void (*set_gamma_table) (int monitor_port, char *gamma_table_base);
++ void (*set_monitor_port) (int monitor_port);
++ void (*set_pixel_clock) (unsigned int pixclock);
++ ssize_t (*show_monitor_port) (int monitor_port, char *buf);
++ int (*set_sysfs_monitor_port) (int val);
++};
++
++extern struct platform_diu_data_ops diu_ops;
++int __init preallocate_diu_videomemory(void);
++#endif
++
+ #endif
+ #endif
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 6ffdda2..8619f2a 100644
--- a/arch/powerpc/sysdev/mpic.c
@@ -209047,6 +253617,31 @@
# 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/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c
+index a51a177..8dcbdd6 100644
+--- a/arch/ppc/kernel/asm-offsets.c
++++ b/arch/ppc/kernel/asm-offsets.c
+@@ -18,6 +18,8 @@
+ #include <linux/suspend.h>
+ #include <linux/mman.h>
+ #include <linux/mm.h>
++#include <linux/kbuild.h>
++
+ #include <asm/io.h>
+ #include <asm/page.h>
+ #include <asm/pgtable.h>
+@@ -26,11 +28,6 @@
+ #include <asm/thread_info.h>
+ #include <asm/vdso_datapage.h>
+
+-#define DEFINE(sym, val) \
+- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+-
+-#define BLANK() asm volatile("\n->" : : )
+-
+ int
+ main(void)
+ {
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index 1b0ec72..e7e642b 100644
--- a/arch/ppc/kernel/head.S
@@ -209076,7 +253671,7 @@
* 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
+index c2ec13b..df3ef6d 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -578,39 +578,6 @@ pcibios_assign_resources(void)
@@ -209155,8 +253750,19 @@
}
struct pci_controller*
+@@ -1176,8 +1121,8 @@ void __init pci_init_resource(struct resource *res, resource_size_t start,
+
+ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
+ {
+- unsigned long start = pci_resource_start(dev, bar);
+- unsigned long len = pci_resource_len(dev, bar);
++ resource_size_t start = pci_resource_start(dev, bar);
++ resource_size_t len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (!len)
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
-index c353502..d9036ef 100644
+index c353502..16ac11c 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -12,7 +12,6 @@
@@ -209186,6 +253792,16 @@
#ifdef CONFIG_PCI
EXPORT_SYMBOL(isa_io_base);
EXPORT_SYMBOL(isa_mem_base);
+@@ -187,9 +183,6 @@ EXPORT_SYMBOL(cuda_poll);
+ #if defined(CONFIG_BOOTX_TEXT)
+ EXPORT_SYMBOL(btext_update_display);
+ #endif
+-#ifdef CONFIG_VT
+-EXPORT_SYMBOL(kd_mksound);
+-#endif
+ EXPORT_SYMBOL(to_tm);
+
+ EXPORT_SYMBOL(pm_power_off);
diff --git a/arch/ppc/kernel/semaphore.c b/arch/ppc/kernel/semaphore.c
deleted file mode 100644
index 2fe429b..0000000
@@ -211251,10 +255867,19 @@
/*
diff --git a/arch/ppc/platforms/sbc82xx.c b/arch/ppc/platforms/sbc82xx.c
-index cc0935c..0df6aac 100644
+index cc0935c..24f6e06 100644
--- a/arch/ppc/platforms/sbc82xx.c
+++ b/arch/ppc/platforms/sbc82xx.c
-@@ -121,8 +121,10 @@ struct hw_interrupt_type sbc82xx_i8259_ic = {
+@@ -30,8 +30,6 @@ static void (*callback_init_IRQ)(void);
+
+ extern unsigned char __res[sizeof(bd_t)];
+
+-extern void (*late_time_init)(void);
+-
+ #ifdef CONFIG_GEN_RTC
+ TODC_ALLOC();
+
+@@ -121,8 +119,10 @@ struct hw_interrupt_type sbc82xx_i8259_ic = {
.end = sbc82xx_i8259_end_irq,
};
@@ -211478,7 +256103,7 @@
/* Called from machine_check_exception */
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
-index 1831833..f6a68e1 100644
+index 1831833..29a7940 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -3,6 +3,10 @@
@@ -211502,7 +256127,26 @@
config GENERIC_BUG
bool
depends on BUG
-@@ -69,6 +76,8 @@ menu "Base setup"
+@@ -55,6 +62,10 @@ config GENERIC_LOCKBREAK
+ default y
+ depends on SMP && PREEMPT
+
++config PGSTE
++ bool
++ default y if KVM
++
+ mainmenu "Linux Kernel Configuration"
+
+ config S390
+@@ -62,6 +73,7 @@ config S390
+ select HAVE_OPROFILE
+ select HAVE_KPROBES
+ select HAVE_KRETPROBES
++ select HAVE_KVM if 64BIT
+
+ source "init/Kconfig"
+
+@@ -69,6 +81,8 @@ menu "Base setup"
comment "Processor type and features"
@@ -211511,7 +256155,22 @@
config 64BIT
bool "64 bit kernel"
help
-@@ -301,10 +310,7 @@ config QDIO
+@@ -286,6 +300,14 @@ comment "Kernel preemption"
+
+ source "kernel/Kconfig.preempt"
+
++config ARCH_SPARSEMEM_ENABLE
++ def_bool y
++ select SPARSEMEM_VMEMMAP_ENABLE
++ select SPARSEMEM_VMEMMAP
++
++config ARCH_SPARSEMEM_DEFAULT
++ def_bool y
++
+ source "mm/Kconfig"
+
+ comment "I/O subsystem configuration"
+@@ -301,10 +323,7 @@ config QDIO
tristate "QDIO support"
---help---
This driver provides the Queued Direct I/O base support for
@@ -211523,7 +256182,7 @@
To compile this driver as a module, choose M here: the
module will be called qdio.
-@@ -486,25 +492,6 @@ config APPLDATA_NET_SUM
+@@ -486,25 +505,6 @@ config APPLDATA_NET_SUM
source kernel/Kconfig.hz
@@ -211549,6 +256208,39 @@
config S390_HYPFS_FS
bool "s390 hypervisor file system support"
select SYS_HYPERVISOR
+@@ -528,6 +528,13 @@ config ZFCPDUMP
+ Select this option if you want to build an zfcpdump enabled kernel.
+ Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this.
+
++config S390_GUEST
++bool "s390 guest support (EXPERIMENTAL)"
++ depends on 64BIT && EXPERIMENTAL
++ select VIRTIO
++ select VIRTIO_RING
++ help
++ Select this option if you want to run the kernel under s390 linux
+ endmenu
+
+ source "net/Kconfig"
+@@ -549,3 +556,5 @@ source "security/Kconfig"
+ source "crypto/Kconfig"
+
+ source "lib/Kconfig"
++
++source "arch/s390/kvm/Kconfig"
+diff --git a/arch/s390/Makefile b/arch/s390/Makefile
+index f708be3..792a4e7 100644
+--- a/arch/s390/Makefile
++++ b/arch/s390/Makefile
+@@ -87,7 +87,7 @@ LDFLAGS_vmlinux := -e start
+ head-y := arch/s390/kernel/head.o arch/s390/kernel/init_task.o
+
+ core-y += arch/s390/mm/ arch/s390/kernel/ arch/s390/crypto/ \
+- arch/s390/appldata/ arch/s390/hypfs/
++ arch/s390/appldata/ arch/s390/hypfs/ arch/s390/kvm/
+ libs-y += arch/s390/lib/
+ drivers-y += drivers/s390/
+ drivers-$(CONFIG_MATHEMU) += arch/s390/math-emu/
diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile
index 14e552c..6a1157f 100644
--- a/arch/s390/crypto/Makefile
@@ -212205,18 +256897,153 @@
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("s390 SHA cipher common functions");
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
-index 62f6b5a..a72f208 100644
+index 62f6b5a..aa341d0 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
+@@ -1,8 +1,9 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc4
+-# Wed Mar 5 11:22:59 2008
++# Linux kernel version: 2.6.25
++# Wed Apr 30 11:07:45 2008
#
+CONFIG_SCHED_MC=y
CONFIG_MMU=y
CONFIG_ZONE_DMA=y
CONFIG_LOCKDEP_SUPPORT=y
-@@ -537,11 +538,9 @@ CONFIG_CTC=m
+@@ -13,10 +14,12 @@ CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+ # CONFIG_ARCH_HAS_ILOG2_U64 is not set
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
+ CONFIG_GENERIC_BUG=y
+ CONFIG_NO_IOMEM=y
+ CONFIG_NO_DMA=y
+ CONFIG_GENERIC_LOCKBREAK=y
++CONFIG_PGSTE=y
+ CONFIG_S390=y
+ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+@@ -42,6 +45,7 @@ CONFIG_LOG_BUF_SHIFT=17
+ CONFIG_CGROUPS=y
+ # CONFIG_CGROUP_DEBUG is not set
+ CONFIG_CGROUP_NS=y
++# CONFIG_CGROUP_DEVICE is not set
+ # CONFIG_CPUSETS is not set
+ CONFIG_GROUP_SCHED=y
+ CONFIG_FAIR_GROUP_SCHED=y
+@@ -64,6 +68,7 @@ CONFIG_INITRAMFS_SOURCE=""
+ CONFIG_SYSCTL=y
+ # CONFIG_EMBEDDED is not set
+ CONFIG_SYSCTL_SYSCALL=y
++CONFIG_SYSCTL_SYSCALL_CHECK=y
+ CONFIG_KALLSYMS=y
+ # CONFIG_KALLSYMS_ALL is not set
+ # CONFIG_KALLSYMS_EXTRA_PASS is not set
+@@ -91,6 +96,7 @@ CONFIG_KPROBES=y
+ CONFIG_KRETPROBES=y
+ CONFIG_HAVE_KPROBES=y
+ CONFIG_HAVE_KRETPROBES=y
++# CONFIG_HAVE_DMA_ATTRS is not set
+ CONFIG_PROC_PAGE_MONITOR=y
+ CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+@@ -120,8 +126,8 @@ CONFIG_DEFAULT_DEADLINE=y
+ # CONFIG_DEFAULT_CFQ is not set
+ # CONFIG_DEFAULT_NOOP is not set
+ CONFIG_DEFAULT_IOSCHED="deadline"
++CONFIG_PREEMPT_NOTIFIERS=y
+ CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+
+ #
+ # Base setup
+@@ -130,6 +136,10 @@ CONFIG_CLASSIC_RCU=y
+ #
+ # Processor type and features
+ #
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+ CONFIG_64BIT=y
+ CONFIG_SMP=y
+ CONFIG_NR_CPUS=32
+@@ -160,15 +170,20 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y
+ # CONFIG_PREEMPT_NONE is not set
+ # CONFIG_PREEMPT_VOLUNTARY is not set
+ CONFIG_PREEMPT=y
+-# CONFIG_RCU_TRACE is not set
++# CONFIG_PREEMPT_RCU is not set
++CONFIG_ARCH_SPARSEMEM_ENABLE=y
++CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+ CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
++# CONFIG_FLATMEM_MANUAL is not set
+ # CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_SPARSEMEM_MANUAL=y
++CONFIG_SPARSEMEM=y
++CONFIG_HAVE_MEMORY_PRESENT=y
+ # CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPARSEMEM_EXTREME=y
++CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
++CONFIG_SPARSEMEM_VMEMMAP=y
++CONFIG_PAGEFLAGS_EXTENDED=y
+ CONFIG_SPLIT_PTLOCK_CPUS=4
+ CONFIG_RESOURCES_64BIT=y
+ CONFIG_ZONE_DMA_FLAG=1
+@@ -204,11 +219,10 @@ CONFIG_HZ_100=y
+ # CONFIG_HZ_1000 is not set
+ CONFIG_HZ=100
+ # CONFIG_SCHED_HRTICK is not set
+-CONFIG_NO_IDLE_HZ=y
+-CONFIG_NO_IDLE_HZ_INIT=y
+ CONFIG_S390_HYPFS_FS=y
+ CONFIG_KEXEC=y
+ # CONFIG_ZFCPDUMP is not set
++CONFIG_S390_GUEST=y
+
+ #
+ # Networking
+@@ -271,8 +285,10 @@ 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_NDISC_NODETYPE=y
+ # CONFIG_IPV6_TUNNEL is not set
+ # CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_IPV6_MROUTE is not set
+ # CONFIG_NETWORK_SECMARK is not set
+ CONFIG_NETFILTER=y
+ # CONFIG_NETFILTER_DEBUG is not set
+@@ -288,6 +304,7 @@ CONFIG_NF_CONNTRACK=m
+ # CONFIG_NF_CT_ACCT is not set
+ # CONFIG_NF_CONNTRACK_MARK is not set
+ # CONFIG_NF_CONNTRACK_EVENTS is not set
++# CONFIG_NF_CT_PROTO_DCCP is not set
+ # CONFIG_NF_CT_PROTO_SCTP is not set
+ # CONFIG_NF_CT_PROTO_UDPLITE is not set
+ # CONFIG_NF_CONNTRACK_AMANDA is not set
+@@ -438,6 +455,7 @@ CONFIG_DASD_ECKD=y
+ CONFIG_DASD_FBA=y
+ CONFIG_DASD_DIAG=y
+ CONFIG_DASD_EER=y
++CONFIG_VIRTIO_BLK=m
+ CONFIG_MISC_DEVICES=y
+ # CONFIG_EEPROM_93CX6 is not set
+ # CONFIG_ENCLOSURE_SERVICES is not set
+@@ -532,26 +550,26 @@ CONFIG_NETDEV_10000=y
+ # S/390 network device drivers
+ #
+ CONFIG_LCS=m
+-CONFIG_CTC=m
++CONFIG_CTCM=m
+ # CONFIG_NETIUCV is not set
# CONFIG_SMSGIUCV is not set
# CONFIG_CLAW is not set
CONFIG_QETH=y
@@ -212231,11 +257058,212 @@
CONFIG_CCWGROUP=y
# 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_VIRTIO_NET=m
+
+ #
+ # Character devices
+ #
++CONFIG_DEVKMEM=y
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+ CONFIG_LEGACY_PTY_COUNT=256
+@@ -601,6 +619,7 @@ CONFIG_S390_VMUR=m
+ # Sonics Silicon Backplane
+ #
+ # CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
+
+ #
+ # File systems
+@@ -653,6 +672,7 @@ CONFIG_PROC_SYSCTL=y
+ CONFIG_SYSFS=y
+ CONFIG_TMPFS=y
+ CONFIG_TMPFS_POSIX_ACL=y
++# CONFIG_HUGETLBFS is not set
+ # CONFIG_HUGETLB_PAGE is not set
+ CONFIG_CONFIGFS_FS=m
+
+@@ -679,12 +699,10 @@ 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=y
+ CONFIG_NFSD_V3=y
+ # CONFIG_NFSD_V3_ACL is not set
+ # CONFIG_NFSD_V4 is not set
+-CONFIG_NFSD_TCP=y
+ CONFIG_LOCKD=y
+ CONFIG_LOCKD_V4=y
+ CONFIG_EXPORTFS=y
+@@ -732,6 +750,7 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+ # CONFIG_PRINTK_TIME is not set
+ CONFIG_ENABLE_WARN_DEPRECATED=y
+ CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=2048
+ CONFIG_MAGIC_SYSRQ=y
+ # CONFIG_UNUSED_SYMBOLS is not set
+ CONFIG_DEBUG_FS=y
+@@ -755,6 +774,7 @@ CONFIG_DEBUG_SPINLOCK_SLEEP=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_FRAME_POINTER is not set
+@@ -776,58 +796,88 @@ CONFIG_SAMPLES=y
+ # CONFIG_SECURITY is not set
+ # CONFIG_SECURITY_FILE_CAPABILITIES is not set
+ CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
+ CONFIG_CRYPTO_ALGAPI=y
+ CONFIG_CRYPTO_AEAD=m
+ CONFIG_CRYPTO_BLKCIPHER=y
+-CONFIG_CRYPTO_SEQIV=m
+ CONFIG_CRYPTO_HASH=m
+ CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_GF128MUL=m
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_AUTHENC=m
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++CONFIG_CRYPTO_CCM=m
++CONFIG_CRYPTO_GCM=m
++CONFIG_CRYPTO_SEQIV=m
++
++#
++# Block modes
++#
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_CTR=m
++CONFIG_CRYPTO_CTS=m
++CONFIG_CRYPTO_ECB=m
++# CONFIG_CRYPTO_LRW is not set
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
+ CONFIG_CRYPTO_HMAC=m
+ # CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
+ # CONFIG_CRYPTO_MD4 is not set
+ CONFIG_CRYPTO_MD5=m
++# CONFIG_CRYPTO_MICHAEL_MIC 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=m
+-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=m
+-CONFIG_CRYPTO_GCM=m
+-CONFIG_CRYPTO_CCM=m
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-CONFIG_CRYPTO_FCRYPT=m
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_WP512 is not set
++
++#
++# Ciphers
++#
+ # CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++CONFIG_CRYPTO_CAMELLIA=m
+ # 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_DES is not set
++CONFIG_CRYPTO_FCRYPT=m
+ # CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-CONFIG_CRYPTO_SEED=m
+ CONFIG_CRYPTO_SALSA20=m
++CONFIG_CRYPTO_SEED=m
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
+ # CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-CONFIG_CRYPTO_CAMELLIA=m
+-# CONFIG_CRYPTO_TEST is not set
+-CONFIG_CRYPTO_AUTHENC=m
+ CONFIG_CRYPTO_LZO=m
+ CONFIG_CRYPTO_HW=y
+ CONFIG_ZCRYPT=m
+ # CONFIG_ZCRYPT_MONOLITHIC is not set
+ # CONFIG_CRYPTO_SHA1_S390 is not set
+ # CONFIG_CRYPTO_SHA256_S390 is not set
++CONFIG_CRYPTO_SHA512_S390=m
+ # CONFIG_CRYPTO_DES_S390 is not set
+ # CONFIG_CRYPTO_AES_S390 is not set
+ CONFIG_S390_PRNG=m
+@@ -836,6 +886,8 @@ CONFIG_S390_PRNG=m
+ # Library routines
+ #
+ CONFIG_BITREVERSE=m
++# CONFIG_GENERIC_FIND_FIRST_BIT is not set
++# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+ # CONFIG_CRC_CCITT is not set
+ # CONFIG_CRC16 is not set
+ # CONFIG_CRC_ITU_T is not set
+@@ -845,3 +897,9 @@ CONFIG_LIBCRC32C=m
+ CONFIG_LZO_COMPRESS=m
+ CONFIG_LZO_DECOMPRESS=m
+ CONFIG_PLIST=y
++CONFIG_HAVE_KVM=y
++CONFIG_VIRTUALIZATION=y
++CONFIG_KVM=m
++CONFIG_VIRTIO=y
++CONFIG_VIRTIO_RING=y
++CONFIG_VIRTIO_BALLOON=m
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
-index 4d3e383..77051cd 100644
+index 4d3e383..6302f50 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
-@@ -11,7 +11,7 @@ CFLAGS_smp.o := -Wno-nonnull
+@@ -2,8 +2,6 @@
+ # Makefile for the linux kernel.
+ #
+
+-EXTRA_AFLAGS := -traditional
+-
+ #
+ # Passing null pointers is ok for smp code, since we access the lowcore here.
+ #
+@@ -11,7 +9,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 \
@@ -212244,7 +257272,7 @@
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)
+@@ -19,7 +17,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
@@ -212253,6 +257281,79 @@
obj-$(CONFIG_AUDIT) += audit.o
compat-obj-$(CONFIG_AUDIT) += compat_audit.o
+diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
+index 1375f8a..fa28eca 100644
+--- a/arch/s390/kernel/asm-offsets.c
++++ b/arch/s390/kernel/asm-offsets.c
+@@ -5,44 +5,38 @@
+ */
+
+ #include <linux/sched.h>
+-
+-/* Use marker if you need to separate the values later */
+-
+-#define DEFINE(sym, val, marker) \
+- asm volatile("\n->" #sym " %0 " #val " " #marker : : "i" (val))
+-
+-#define BLANK() asm volatile("\n->" : : )
++#include <linux/kbuild.h>
+
+ int main(void)
+ {
+- DEFINE(__THREAD_info, offsetof(struct task_struct, stack),);
+- DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp),);
+- DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info),);
++ DEFINE(__THREAD_info, offsetof(struct task_struct, stack));
++ DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp));
++ DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info));
+ DEFINE(__THREAD_mm_segment,
+- offsetof(struct task_struct, thread.mm_segment),);
++ offsetof(struct task_struct, thread.mm_segment));
+ BLANK();
+- DEFINE(__TASK_pid, offsetof(struct task_struct, pid),);
++ DEFINE(__TASK_pid, offsetof(struct task_struct, pid));
+ BLANK();
+- DEFINE(__PER_atmid, offsetof(per_struct, lowcore.words.perc_atmid),);
+- DEFINE(__PER_address, offsetof(per_struct, lowcore.words.address),);
+- DEFINE(__PER_access_id, offsetof(per_struct, lowcore.words.access_id),);
++ DEFINE(__PER_atmid, offsetof(per_struct, lowcore.words.perc_atmid));
++ DEFINE(__PER_address, offsetof(per_struct, lowcore.words.address));
++ DEFINE(__PER_access_id, offsetof(per_struct, lowcore.words.access_id));
+ BLANK();
+- DEFINE(__TI_task, offsetof(struct thread_info, task),);
+- DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain),);
+- DEFINE(__TI_flags, offsetof(struct thread_info, flags),);
+- DEFINE(__TI_cpu, offsetof(struct thread_info, cpu),);
+- DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count),);
++ DEFINE(__TI_task, offsetof(struct thread_info, task));
++ DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain));
++ DEFINE(__TI_flags, offsetof(struct thread_info, flags));
++ DEFINE(__TI_cpu, offsetof(struct thread_info, cpu));
++ DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count));
+ BLANK();
+- DEFINE(__PT_ARGS, offsetof(struct pt_regs, args),);
+- DEFINE(__PT_PSW, offsetof(struct pt_regs, psw),);
+- DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs),);
+- DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2),);
+- DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc),);
+- DEFINE(__PT_TRAP, offsetof(struct pt_regs, trap),);
+- DEFINE(__PT_SIZE, sizeof(struct pt_regs),);
++ DEFINE(__PT_ARGS, offsetof(struct pt_regs, args));
++ DEFINE(__PT_PSW, offsetof(struct pt_regs, psw));
++ DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs));
++ DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2));
++ DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc));
++ DEFINE(__PT_TRAP, offsetof(struct pt_regs, trap));
++ DEFINE(__PT_SIZE, sizeof(struct pt_regs));
+ BLANK();
+- DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain),);
+- DEFINE(__SF_GPRS, offsetof(struct stack_frame, gprs),);
+- DEFINE(__SF_EMPTY, offsetof(struct stack_frame, empty1),);
++ DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain));
++ DEFINE(__SF_GPRS, offsetof(struct stack_frame, gprs));
++ DEFINE(__SF_EMPTY, offsetof(struct stack_frame, empty1));
+ return 0;
+ }
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
@@ -212520,7 +257621,7 @@
id , &debug_file_ops);
if (!pde){
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
-index 01832c4..540a67f 100644
+index 01832c4..d0e0968 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -21,6 +21,7 @@
@@ -212531,6 +257632,218 @@
/*
* Create a Kernel NSS if the SAVESYS= parameter is defined
+@@ -138,11 +139,15 @@ static noinline __init void detect_machine_type(void)
+
+ /* Running under z/VM ? */
+ if (cpuinfo->cpu_id.version == 0xff)
+- machine_flags |= 1;
++ machine_flags |= MACHINE_FLAG_VM;
+
+ /* Running on a P/390 ? */
+ if (cpuinfo->cpu_id.machine == 0x7490)
+- machine_flags |= 4;
++ machine_flags |= MACHINE_FLAG_P390;
++
++ /* Running under KVM ? */
++ if (cpuinfo->cpu_id.version == 0xfe)
++ machine_flags |= MACHINE_FLAG_KVM;
+ }
+
+ #ifdef CONFIG_64BIT
+@@ -263,6 +268,118 @@ static noinline __init void setup_lowcore_early(void)
+ s390_base_pgm_handler_fn = early_pgm_check_handler;
+ }
+
++static noinline __init void setup_hpage(void)
++{
++#ifndef CONFIG_DEBUG_PAGEALLOC
++ unsigned int facilities;
++
++ facilities = stfl();
++ if (!(facilities & (1UL << 23)) || !(facilities & (1UL << 29)))
++ return;
++ machine_flags |= MACHINE_FLAG_HPAGE;
++ __ctl_set_bit(0, 23);
++#endif
++}
++
++static __init void detect_mvpg(void)
++{
++#ifndef CONFIG_64BIT
++ int rc;
++
++ asm volatile(
++ " la 0,0\n"
++ " mvpg %2,%2\n"
++ "0: la %0,0\n"
++ "1:\n"
++ EX_TABLE(0b,1b)
++ : "=d" (rc) : "0" (-EOPNOTSUPP), "a" (0) : "memory", "cc", "0");
++ if (!rc)
++ machine_flags |= MACHINE_FLAG_MVPG;
++#endif
++}
++
++static __init void detect_ieee(void)
++{
++#ifndef CONFIG_64BIT
++ int rc, tmp;
++
++ asm volatile(
++ " efpc %1,0\n"
++ "0: la %0,0\n"
++ "1:\n"
++ EX_TABLE(0b,1b)
++ : "=d" (rc), "=d" (tmp): "0" (-EOPNOTSUPP) : "cc");
++ if (!rc)
++ machine_flags |= MACHINE_FLAG_IEEE;
++#endif
++}
++
++static __init void detect_csp(void)
++{
++#ifndef CONFIG_64BIT
++ int rc;
++
++ asm volatile(
++ " la 0,0\n"
++ " la 1,0\n"
++ " la 2,4\n"
++ " csp 0,2\n"
++ "0: la %0,0\n"
++ "1:\n"
++ EX_TABLE(0b,1b)
++ : "=d" (rc) : "0" (-EOPNOTSUPP) : "cc", "0", "1", "2");
++ if (!rc)
++ machine_flags |= MACHINE_FLAG_CSP;
++#endif
++}
++
++static __init void detect_diag9c(void)
++{
++ unsigned int cpu_address;
++ int rc;
++
++ cpu_address = stap();
++ asm volatile(
++ " diag %2,0,0x9c\n"
++ "0: la %0,0\n"
++ "1:\n"
++ EX_TABLE(0b,1b)
++ : "=d" (rc) : "0" (-EOPNOTSUPP), "d" (cpu_address) : "cc");
++ if (!rc)
++ machine_flags |= MACHINE_FLAG_DIAG9C;
++}
++
++static __init void detect_diag44(void)
++{
++#ifdef CONFIG_64BIT
++ int rc;
++
++ asm volatile(
++ " diag 0,0,0x44\n"
++ "0: la %0,0\n"
++ "1:\n"
++ EX_TABLE(0b,1b)
++ : "=d" (rc) : "0" (-EOPNOTSUPP) : "cc");
++ if (!rc)
++ machine_flags |= MACHINE_FLAG_DIAG44;
++#endif
++}
++
++static __init void detect_machine_facilities(void)
++{
++#ifdef CONFIG_64BIT
++ unsigned int facilities;
++
++ facilities = stfl();
++ if (facilities & (1 << 28))
++ machine_flags |= MACHINE_FLAG_IDTE;
++ if (facilities & (1 << 23))
++ machine_flags |= MACHINE_FLAG_PFMF;
++ if (facilities & (1 << 4))
++ machine_flags |= MACHINE_FLAG_MVCOS;
++#endif
++}
++
+ /*
+ * Save ipl parameters, clear bss memory, initialize storage keys
+ * and create a kernel NSS at startup if the SAVESYS= parm is defined
+@@ -280,6 +397,13 @@ void __init startup_init(void)
+ create_kernel_nss();
+ sort_main_extable();
+ setup_lowcore_early();
++ detect_mvpg();
++ detect_ieee();
++ detect_csp();
++ detect_diag9c();
++ detect_diag44();
++ detect_machine_facilities();
++ setup_hpage();
+ sclp_read_info_early();
+ sclp_facilities_detect();
+ memsize = sclp_memory_detect();
+diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
+index 6766e37..bdbb3bc 100644
+--- a/arch/s390/kernel/entry.S
++++ b/arch/s390/kernel/entry.S
+@@ -49,9 +49,9 @@ SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC
+ SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP
+ SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
+
+-_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
++_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
+ _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
+-_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
++_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
+ _TIF_MCCK_PENDING)
+
+ STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
+@@ -316,7 +316,7 @@ sysc_work:
+ bo BASED(sysc_mcck_pending)
+ tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
+ bo BASED(sysc_reschedule)
+- tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
++ tm __TI_flags+3(%r9),_TIF_SIGPENDING
+ bnz BASED(sysc_sigpending)
+ tm __TI_flags+3(%r9),_TIF_RESTART_SVC
+ bo BASED(sysc_restart)
+@@ -342,7 +342,7 @@ sysc_mcck_pending:
+ br %r1 # TIF bit will be cleared by handler
+
+ #
+-# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
++# _TIF_SIGPENDING is set, call do_signal
+ #
+ sysc_sigpending:
+ ni __TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
+@@ -657,7 +657,7 @@ io_work:
+ lr %r15,%r1
+ #
+ # One of the work bits is on. Find out which one.
+-# Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGMASK, _TIF_NEED_RESCHED
++# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED
+ # and _TIF_MCCK_PENDING
+ #
+ io_work_loop:
+@@ -665,7 +665,7 @@ io_work_loop:
+ bo BASED(io_mcck_pending)
+ tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
+ bo BASED(io_reschedule)
+- tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
++ tm __TI_flags+3(%r9),_TIF_SIGPENDING
+ bnz BASED(io_sigpending)
+ b BASED(io_restore)
+ io_work_done:
+@@ -693,7 +693,7 @@ io_reschedule:
+ b BASED(io_work_loop)
+
+ #
+-# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
++# _TIF_SIGPENDING is set, call do_signal
+ #
+ io_sigpending:
+ TRACE_IRQS_ON
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
new file mode 100644
index 0000000..6b18963
@@ -212598,9 +257911,39 @@
+
+#endif /* _ENTRY_H */
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
-index efde6e1..cd959c0 100644
+index efde6e1..5a4a7bc 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
+@@ -52,9 +52,9 @@ SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
+ STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
+ STACK_SIZE = 1 << STACK_SHIFT
+
+-_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
++_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
+ _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
+-_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
++_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
+ _TIF_MCCK_PENDING)
+
+ #define BASED(name) name-system_call(%r13)
+@@ -308,7 +308,7 @@ sysc_work:
+ jo sysc_mcck_pending
+ tm __TI_flags+7(%r9),_TIF_NEED_RESCHED
+ jo sysc_reschedule
+- tm __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
++ tm __TI_flags+7(%r9),_TIF_SIGPENDING
+ jnz sysc_sigpending
+ tm __TI_flags+7(%r9),_TIF_RESTART_SVC
+ jo sysc_restart
+@@ -332,7 +332,7 @@ sysc_mcck_pending:
+ jg s390_handle_mcck # TIF bit will be cleared by handler
+
+ #
+-# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
++# _TIF_SIGPENDING is set, call do_signal
+ #
+ sysc_sigpending:
+ ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
@@ -475,6 +475,7 @@ pgm_check_handler:
pgm_no_vtime:
#endif
@@ -212609,6 +257952,24 @@
TRACE_IRQS_OFF
lgf %r3,__LC_PGM_ILC # load program interruption code
lghi %r8,0x7f
+@@ -647,7 +648,7 @@ io_work_loop:
+ jo io_mcck_pending
+ tm __TI_flags+7(%r9),_TIF_NEED_RESCHED
+ jo io_reschedule
+- tm __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
++ tm __TI_flags+7(%r9),_TIF_SIGPENDING
+ jnz io_sigpending
+ j io_restore
+ io_work_done:
+@@ -673,7 +674,7 @@ io_reschedule:
+ j io_work_loop
+
+ #
+-# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
++# _TIF_SIGPENDING or is set, call do_signal
+ #
+ io_sigpending:
+ TRACE_IRQS_ON
@@ -847,6 +848,7 @@ stack_overflow:
je 0f
la %r1,__LC_SAVE_AREA+32
@@ -212617,6 +257978,165 @@
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/head31.S b/arch/s390/kernel/head31.S
+index dc364c1..a816e2d 100644
+--- a/arch/s390/kernel/head31.S
++++ b/arch/s390/kernel/head31.S
+@@ -57,61 +57,6 @@ startup_continue:
+ #
+ l %r14,.Lstartup_init-.LPG1(%r13)
+ basr %r14,%r14
+-
+- l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags
+-#
+-# find out if we have an IEEE fpu
+-#
+- mvc __LC_PGM_NEW_PSW(8),.Lpcfpu-.LPG1(%r13)
+- efpc %r0,0 # test IEEE extract fpc instruction
+- oi 3(%r12),2 # set IEEE fpu flag
+-.Lchkfpu:
+-
+-#
+-# find out if we have the CSP instruction
+-#
+- mvc __LC_PGM_NEW_PSW(8),.Lpccsp-.LPG1(%r13)
+- la %r0,0
+- lr %r1,%r0
+- la %r2,4
+- csp %r0,%r2 # Test CSP instruction
+- oi 3(%r12),8 # set CSP flag
+-.Lchkcsp:
+-
+-#
+-# find out if we have the MVPG instruction
+-#
+- mvc __LC_PGM_NEW_PSW(8),.Lpcmvpg-.LPG1(%r13)
+- sr %r0,%r0
+- la %r1,0
+- la %r2,0
+- mvpg %r1,%r2 # Test CSP instruction
+- oi 3(%r12),16 # set MVPG flag
+-.Lchkmvpg:
+-
+-#
+-# find out if we have the IDTE instruction
+-#
+- mvc __LC_PGM_NEW_PSW(8),.Lpcidte-.LPG1(%r13)
+- .long 0xb2b10000 # store facility list
+- tm 0xc8,0x08 # check bit for clearing-by-ASCE
+- bno .Lchkidte-.LPG1(%r13)
+- lhi %r1,2094
+- lhi %r2,0
+- .long 0xb98e2001
+- oi 3(%r12),0x80 # set IDTE flag
+-.Lchkidte:
+-
+-#
+-# find out if the diag 0x9c is available
+-#
+- mvc __LC_PGM_NEW_PSW(8),.Lpcdiag9c-.LPG1(%r13)
+- stap __LC_CPUID+4 # store cpu address
+- lh %r1,__LC_CPUID+4
+- diag %r1,0,0x9c # test diag 0x9c
+- oi 2(%r12),1 # set diag9c flag
+-.Lchkdiag9c:
+-
+ lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space,
+ # virtual and never return ...
+ .align 8
+@@ -132,13 +77,7 @@ startup_continue:
+ .long 0 # cr13: home space segment table
+ .long 0xc0000000 # cr14: machine check handling off
+ .long 0 # cr15: linkage stack operations
+-.Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu
+-.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp
+-.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg
+-.Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte
+-.Lpcdiag9c:.long 0x00080000,0x80000000 + .Lchkdiag9c
+ .Lmchunk:.long memory_chunk
+-.Lmflags:.long machine_flags
+ .Lbss_bgn: .long __bss_start
+ .Lbss_end: .long _end
+ .Lparmaddr: .long PARMAREA
+diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
+index 79dccd2..1d06961 100644
+--- a/arch/s390/kernel/head64.S
++++ b/arch/s390/kernel/head64.S
+@@ -125,73 +125,11 @@ startup_continue:
+ # and create a kernel NSS if the SAVESYS= parm is defined
+ #
+ brasl %r14,startup_init
+- # set program check new psw mask
+- mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
+- larl %r12,machine_flags
+-#
+-# find out if we have the MVPG instruction
+-#
+- la %r1,0f-.LPG1(%r13) # set program check address
+- stg %r1,__LC_PGM_NEW_PSW+8
+- sgr %r0,%r0
+- lghi %r1,0
+- lghi %r2,0
+- mvpg %r1,%r2 # test MVPG instruction
+- oi 7(%r12),16 # set MVPG flag
+-0:
+-
+-#
+-# find out if the diag 0x44 works in 64 bit mode
+-#
+- la %r1,0f-.LPG1(%r13) # set program check address
+- stg %r1,__LC_PGM_NEW_PSW+8
+- diag 0,0,0x44 # test diag 0x44
+- oi 7(%r12),32 # set diag44 flag
+-0:
+-
+-#
+-# find out if we have the IDTE instruction
+-#
+- la %r1,0f-.LPG1(%r13) # set program check address
+- stg %r1,__LC_PGM_NEW_PSW+8
+- .long 0xb2b10000 # store facility list
+- tm 0xc8,0x08 # check bit for clearing-by-ASCE
+- bno 0f-.LPG1(%r13)
+- lhi %r1,2048
+- lhi %r2,0
+- .long 0xb98e2001
+- oi 7(%r12),0x80 # set IDTE flag
+-0:
+-
+-#
+-# find out if the diag 0x9c is available
+-#
+- la %r1,0f-.LPG1(%r13) # set program check address
+- stg %r1,__LC_PGM_NEW_PSW+8
+- stap __LC_CPUID+4 # store cpu address
+- lh %r1,__LC_CPUID+4
+- diag %r1,0,0x9c # test diag 0x9c
+- oi 6(%r12),1 # set diag9c flag
+-0:
+-
+-#
+-# find out if we have the MVCOS instruction
+-#
+- la %r1,0f-.LPG1(%r13) # set program check address
+- stg %r1,__LC_PGM_NEW_PSW+8
+- .short 0xc800 # mvcos 0(%r0),0(%r0),%r0
+- .short 0x0000
+- .short 0x0000
+-0: tm 0x8f,0x13 # special-operation exception?
+- bno 1f-.LPG1(%r13) # if yes, MVCOS is present
+- oi 6(%r12),2 # set MVCOS flag
+-1:
+-
+ lpswe .Lentry-.LPG1(13) # jump to _stext in primary-space,
+ # virtual and never return ...
+ .align 16
+ .Lentry:.quad 0x0000000180000000,_stext
+-.Lctl: .quad 0x04b50002 # cr0: various things
++.Lctl: .quad 0x04350002 # cr0: various things
+ .quad 0 # cr1: primary space segment table
+ .quad .Lduct # cr2: dispatchable unit control table
+ .quad 0 # cr3: instruction authorization
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 375232c..5325424 100644
--- a/arch/s390/kernel/ipl.c
@@ -212630,6 +258150,19 @@
{
struct ccw_dev_id devid;
static char buf[100];
+diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
+index c36d812..c59a86d 100644
+--- a/arch/s390/kernel/irq.c
++++ b/arch/s390/kernel/irq.c
+@@ -60,8 +60,6 @@ init_IRQ(void)
+ /*
+ * Switch to the asynchronous interrupt stack for softirq execution.
+ */
+-extern void __do_softirq(void);
+-
+ asmlinkage void do_softirq(void)
+ {
+ unsigned long flags, old, new;
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index c5549a2..ed04d13 100644
--- a/arch/s390/kernel/kprobes.c
@@ -212644,7 +258177,7 @@
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
+index ce20315..7920861 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -36,6 +36,8 @@
@@ -212784,7 +258317,7 @@
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)
+@@ -177,32 +170,16 @@ static void default_idle(void)
void cpu_idle(void)
{
for (;;) {
@@ -212796,16 +258329,31 @@
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);
+ }
}
+-void show_regs(struct pt_regs *regs)
+-{
+- print_modules();
+- printk("CPU: %d %s %s %.*s\n",
+- task_thread_info(current)->cpu, print_tainted(),
+- init_utsname()->release,
+- (int)strcspn(init_utsname()->version, " "),
+- init_utsname()->version);
+- printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
+- current->comm, current->pid, current,
+- (void *) current->thread.ksp);
+- show_registers(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]);
+-}
+-
extern void kernel_thread_starter(void);
+
+ asm(
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
-index 6e036ba..58a0642 100644
+index 6e036ba..7f42701 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -41,6 +41,7 @@
@@ -212816,6 +258364,78 @@
#ifdef CONFIG_COMPAT
#include "compat_ptrace.h"
+@@ -606,38 +607,8 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data)
+ }
+ #endif
+
+-#define PT32_IEEE_IP 0x13c
+-
+-static int
+-do_ptrace(struct task_struct *child, long request, long addr, long data)
++long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+ {
+- int ret;
+-
+- if (request == PTRACE_ATTACH)
+- return ptrace_attach(child);
+-
+- /*
+- * Special cases to get/store the ieee instructions pointer.
+- */
+- if (child == current) {
+- if (request == PTRACE_PEEKUSR && addr == PT_IEEE_IP)
+- return peek_user(child, addr, data);
+- if (request == PTRACE_POKEUSR && addr == PT_IEEE_IP)
+- return poke_user(child, addr, data);
+-#ifdef CONFIG_COMPAT
+- if (request == PTRACE_PEEKUSR &&
+- addr == PT32_IEEE_IP && test_thread_flag(TIF_31BIT))
+- return peek_user_emu31(child, addr, data);
+- if (request == PTRACE_POKEUSR &&
+- addr == PT32_IEEE_IP && test_thread_flag(TIF_31BIT))
+- return poke_user_emu31(child, addr, data);
+-#endif
+- }
+-
+- ret = ptrace_check_attach(child, request == PTRACE_KILL);
+- if (ret < 0)
+- return ret;
+-
+ switch (request) {
+ case PTRACE_SYSCALL:
+ /* continue and stop at next (return from) syscall */
+@@ -692,31 +663,6 @@ do_ptrace(struct task_struct *child, long request, long addr, long data)
+ return -EIO;
+ }
+
+-asmlinkage long
+-sys_ptrace(long request, long pid, long addr, long data)
+-{
+- struct task_struct *child;
+- int ret;
+-
+- lock_kernel();
+- if (request == PTRACE_TRACEME) {
+- ret = ptrace_traceme();
+- goto out;
+- }
+-
+- child = ptrace_get_task_struct(pid);
+- if (IS_ERR(child)) {
+- ret = PTR_ERR(child);
+- goto out;
+- }
+-
+- ret = do_ptrace(child, request, addr, data);
+- put_task_struct(child);
+-out:
+- unlock_kernel();
+- return ret;
+-}
+-
+ asmlinkage void
+ syscall_trace(struct pt_regs *regs, int entryexit)
+ {
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
@@ -212985,7 +258605,7 @@
-}
-
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
-index 290e504..7141147 100644
+index 290e504..2bc70b6 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -39,6 +39,7 @@
@@ -212996,7 +258616,28 @@
#include <asm/ipl.h>
#include <asm/uaccess.h>
-@@ -427,7 +428,7 @@ setup_lowcore(void)
+@@ -72,7 +73,7 @@ EXPORT_SYMBOL(uaccess);
+ unsigned int console_mode = 0;
+ unsigned int console_devno = -1;
+ unsigned int console_irq = -1;
+-unsigned long machine_flags = 0;
++unsigned long machine_flags;
+ unsigned long elf_hwcap = 0;
+ char elf_platform[ELF_PLATFORM_SIZE];
+
+@@ -315,7 +316,11 @@ static int __init early_parse_ipldelay(char *p)
+ early_param("ipldelay", early_parse_ipldelay);
+
+ #ifdef CONFIG_S390_SWITCH_AMODE
++#ifdef CONFIG_PGSTE
++unsigned int switch_amode = 1;
++#else
+ unsigned int switch_amode = 0;
++#endif
+ EXPORT_SYMBOL_GPL(switch_amode);
+
+ static void set_amode_and_uaccess(unsigned long user_amode,
+@@ -427,7 +432,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;
@@ -213005,16 +258646,25 @@
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;
+@@ -678,16 +683,7 @@ setup_memory(void)
+ #endif
}
+-static __init unsigned int stfl(void)
+-{
+- asm volatile(
+- " .insn s,0xb2b10000,0(0)\n" /* stfl */
+- "0:\n"
+- EX_TABLE(0b,0b));
+- 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)
+@@ -697,6 +693,13 @@ static __init int stfle(unsigned long long *list, int doublewords)
return __nr + 1;
}
@@ -213028,7 +258678,7 @@
/*
* Setup hardware capabilities.
*/
-@@ -741,7 +749,7 @@ static void __init setup_hwcaps(void)
+@@ -741,11 +744,14 @@ static void __init setup_hwcaps(void)
* HWCAP_S390_DFP bit 6.
*/
if ((elf_hwcap & (1UL << 2)) &&
@@ -213037,7 +258687,31 @@
if (facility_list_extended & (1ULL << (64 - 43)))
elf_hwcap |= 1UL << 6;
}
-@@ -823,6 +831,7 @@ setup_arch(char **cmdline_p)
+
++ if (MACHINE_HAS_HPAGE)
++ elf_hwcap |= 1UL << 7;
++
+ switch (cpuinfo->cpu_id.machine) {
+ case 0x9672:
+ #if !defined(CONFIG_64BIT)
+@@ -789,9 +795,13 @@ setup_arch(char **cmdline_p)
+ "This machine has an IEEE fpu\n" :
+ "This machine has no IEEE fpu\n");
+ #else /* CONFIG_64BIT */
+- printk((MACHINE_IS_VM) ?
+- "We are running under VM (64 bit mode)\n" :
+- "We are running native (64 bit mode)\n");
++ if (MACHINE_IS_VM)
++ printk("We are running under VM (64 bit mode)\n");
++ else if (MACHINE_IS_KVM) {
++ printk("We are running under KVM (64 bit mode)\n");
++ add_preferred_console("ttyS", 1, NULL);
++ } else
++ printk("We are running native (64 bit mode)\n");
+ #endif /* CONFIG_64BIT */
+
+ /* Save unparsed command line copy for /proc/cmdline */
+@@ -823,6 +833,7 @@ setup_arch(char **cmdline_p)
cpu_init();
__cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr;
@@ -213045,6 +258719,27 @@
/*
* Setup capabilities (ELF_HWCAP & ELF_PLATFORM).
+@@ -864,8 +875,9 @@ void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo)
+
+ static int show_cpuinfo(struct seq_file *m, void *v)
+ {
+- static const char *hwcap_str[7] = {
+- "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp"
++ static const char *hwcap_str[8] = {
++ "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
++ "edat"
+ };
+ struct cpuinfo_S390 *cpuinfo;
+ unsigned long n = (unsigned long) v - 1;
+@@ -880,7 +892,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
+ num_online_cpus(), loops_per_jiffy/(500000/HZ),
+ (loops_per_jiffy/(5000/HZ))%100);
+ seq_puts(m, "features\t: ");
+- for (i = 0; i < 7; i++)
++ for (i = 0; i < 8; i++)
+ if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
+ seq_printf(m, "%s ", hwcap_str[i]);
+ seq_puts(m, "\n");
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 4449bf3..b976820 100644
--- a/arch/s390/kernel/signal.c
@@ -213101,7 +258796,7 @@
}
else
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
-index 8f894d3..0dfa988 100644
+index 8f894d3..0aeb290 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -44,6 +44,7 @@
@@ -213154,6 +258849,24 @@
cpu_set(logical_cpu, cpu_present_map);
if (cpu >= info->configured)
smp_cpu_state[logical_cpu] = CPU_STATE_STANDBY;
+@@ -503,7 +505,7 @@ out:
+ return rc;
+ }
+
+-static int smp_rescan_cpus(void)
++static int __smp_rescan_cpus(void)
+ {
+ cpumask_t avail;
+
+@@ -568,7 +570,7 @@ out:
+ kfree(info);
+ printk(KERN_INFO "CPUs: %d configured, %d standby\n", c_cpus, s_cpus);
+ get_online_cpus();
+- smp_rescan_cpus();
++ __smp_rescan_cpus();
+ put_online_cpus();
+ }
+
@@ -846,6 +848,7 @@ void __init smp_prepare_boot_cpu(void)
S390_lowcore.percpu_offset = __per_cpu_offset[0];
current_set[0] = current;
@@ -213162,7 +258875,17 @@
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,
+@@ -887,8 +890,8 @@ static ssize_t cpu_configure_store(struct sys_device *dev, const char *buf,
+ if (val != 0 && val != 1)
+ return -EINVAL;
+
+- mutex_lock(&smp_cpu_state_mutex);
+ get_online_cpus();
++ mutex_lock(&smp_cpu_state_mutex);
+ rc = -EBUSY;
+ if (cpu_online(cpu))
+ goto out;
+@@ -897,28 +900,60 @@ 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]);
@@ -213184,7 +258907,14 @@
}
break;
default:
-@@ -919,6 +926,34 @@ out:
+ break;
+ }
+ out:
+- put_online_cpus();
+ mutex_unlock(&smp_cpu_state_mutex);
++ put_online_cpus();
+ return rc ? rc : count;
+ }
static SYSDEV_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store);
#endif /* CONFIG_HOTPLUG_CPU */
@@ -213227,12 +258957,46 @@
NULL,
};
-@@ -1075,11 +1111,48 @@ static ssize_t __ref rescan_store(struct sys_device *dev,
+@@ -1052,17 +1088,17 @@ out:
+ }
+
+ #ifdef CONFIG_HOTPLUG_CPU
+-static ssize_t __ref rescan_store(struct sys_device *dev,
+- const char *buf, size_t count)
++
++int smp_rescan_cpus(void)
+ {
+ cpumask_t newcpus;
+ int cpu;
+ int rc;
+
+- mutex_lock(&smp_cpu_state_mutex);
+ get_online_cpus();
++ mutex_lock(&smp_cpu_state_mutex);
+ newcpus = cpu_present_map;
+- rc = smp_rescan_cpus();
++ rc = __smp_rescan_cpus();
+ if (rc)
+ goto out;
+ cpus_andnot(newcpus, cpu_present_map, newcpus);
+@@ -1073,13 +1109,59 @@ static ssize_t __ref rescan_store(struct sys_device *dev,
+ }
+ rc = 0;
out:
- put_online_cpus();
+- put_online_cpus();
mutex_unlock(&smp_cpu_state_mutex);
++ put_online_cpus();
+ if (!cpus_empty(newcpus))
+ topology_schedule_update();
++ return rc;
++}
++
++static ssize_t __ref rescan_store(struct sys_device *dev, const char *buf,
++ size_t count)
++{
++ int rc;
++
++ rc = smp_rescan_cpus();
return rc ? rc : count;
}
static SYSDEV_ATTR(rescan, 0200, NULL, rescan_store);
@@ -213259,16 +259023,16 @@
+ if (val != 0 && val != 1)
+ return -EINVAL;
+ rc = 0;
-+ mutex_lock(&smp_cpu_state_mutex);
+ get_online_cpus();
++ mutex_lock(&smp_cpu_state_mutex);
+ 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);
++ put_online_cpus();
+ return rc ? rc : count;
+}
+static SYSDEV_ATTR(dispatching, 0644, dispatching_show, dispatching_store);
@@ -213276,7 +259040,7 @@
static int __init topology_init(void)
{
int cpu;
-@@ -1093,6 +1166,10 @@ static int __init topology_init(void)
+@@ -1093,6 +1175,10 @@ static int __init topology_init(void)
if (rc)
return rc;
#endif
@@ -213742,10 +259506,10 @@
local_irq_enable();
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
new file mode 100644
-index 0000000..12b39b3
+index 0000000..661a072
--- /dev/null
+++ b/arch/s390/kernel/topology.c
-@@ -0,0 +1,314 @@
+@@ -0,0 +1,341 @@
+/*
+ * Copyright IBM Corp. 2007
+ * Author(s): Heiko Carstens <heiko.carstens at de.ibm.com>
@@ -213757,6 +259521,7 @@
+#include <linux/device.h>
+#include <linux/bootmem.h>
+#include <linux/sched.h>
++#include <linux/kthread.h>
+#include <linux/workqueue.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
@@ -213814,6 +259579,8 @@
+static void set_topology_timer(void);
+static DECLARE_WORK(topology_work, topology_work_fn);
+
++cpumask_t cpu_core_map[NR_CPUS];
++
+cpumask_t cpu_coregroup_map(unsigned int cpu)
+{
+ struct core_info *core = &core_info;
@@ -213947,175 +259714,2931 @@
+ return rc;
+}
+
-+void arch_update_cpu_topology(void)
++static void update_cpu_core_map(void)
++{
++ int cpu;
++
++ for_each_present_cpu(cpu)
++ cpu_core_map[cpu] = cpu_coregroup_map(cpu);
++}
++
++void arch_update_cpu_topology(void)
++{
++ struct tl_info *info = tl_info;
++ struct sys_device *sysdev;
++ int cpu;
++
++ if (!machine_has_topology) {
++ update_cpu_core_map();
++ topology_update_polarization_simple();
++ return;
++ }
++ stsi(info, 15, 1, 2);
++ tl_to_cores(info);
++ update_cpu_core_map();
++ for_each_online_cpu(cpu) {
++ sysdev = get_cpu_sysdev(cpu);
++ kobject_uevent(&sysdev->kobj, KOBJ_CHANGE);
++ }
++}
++
++static int topology_kthread(void *data)
++{
++ arch_reinit_sched_domains();
++ return 0;
++}
++
++static void topology_work_fn(struct work_struct *work)
++{
++ /* We can't call arch_reinit_sched_domains() from a multi-threaded
++ * workqueue context since it may deadlock in case of cpu hotplug.
++ * So we have to create a kernel thread in order to call
++ * arch_reinit_sched_domains().
++ */
++ kthread_run(topology_kthread, NULL, "topology_update");
++}
++
++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;
++
++ rc = 0;
++ if (!machine_has_topology) {
++ topology_update_polarization_simple();
++ goto out;
++ }
++ init_timer_deferrable(&topology_timer);
++ if (machine_has_topology_irq) {
++ rc = register_external_interrupt(0x2005, topology_interrupt);
++ if (rc)
++ goto out;
++ ctl_set_bit(0, 8);
++ }
++ else
++ set_topology_timer();
++out:
++ update_cpu_core_map();
++ return rc;
++}
++__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..4584d81 100644
+--- a/arch/s390/kernel/traps.c
++++ b/arch/s390/kernel/traps.c
+@@ -42,11 +42,8 @@
+ #include <asm/s390_ext.h>
+ #include <asm/lowcore.h>
+ #include <asm/debug.h>
++#include "entry.h"
+
+-/* Called from entry.S only */
+-extern void handle_per_exception(struct pt_regs *regs);
+-
+-typedef void pgm_check_handler_t(struct pt_regs *, long);
+ pgm_check_handler_t *pgm_check_table[128];
+
+ #ifdef CONFIG_SYSCTL
+@@ -59,7 +56,6 @@ int sysctl_userprocess_debug = 0;
+
+ extern pgm_check_handler_t do_protection_exception;
+ extern pgm_check_handler_t do_dat_exception;
+-extern pgm_check_handler_t do_monitor_call;
+ extern pgm_check_handler_t do_asce_exception;
+
+ #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
+@@ -117,7 +113,7 @@ __show_trace(unsigned long sp, unsigned long low, unsigned long high)
+ }
+ }
+
+-void show_trace(struct task_struct *task, unsigned long *stack)
++static void show_trace(struct task_struct *task, unsigned long *stack)
+ {
+ register unsigned long __r15 asm ("15");
+ unsigned long 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);
+ }
+
++static void show_last_breaking_event(struct pt_regs *regs)
++{
++#ifdef CONFIG_64BIT
++ 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
+ */
+@@ -219,6 +223,24 @@ void show_registers(struct pt_regs *regs)
+ show_code(regs);
+ }
+
++void show_regs(struct pt_regs *regs)
++{
++ print_modules();
++ printk("CPU: %d %s %s %.*s\n",
++ task_thread_info(current)->cpu, print_tainted(),
++ init_utsname()->release,
++ (int)strcspn(init_utsname()->version, " "),
++ init_utsname()->version);
++ printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
++ current->comm, current->pid, current,
++ (void *) current->thread.ksp);
++ show_registers(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);
++}
++
+ /* This is called from fs/proc/array.c */
+ void task_show_regs(struct seq_file *m, struct task_struct *task)
+ {
+@@ -739,6 +761,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/kernel/vtime.c b/arch/s390/kernel/vtime.c
+index c5f05b3..ca90ee3 100644
+--- a/arch/s390/kernel/vtime.c
++++ b/arch/s390/kernel/vtime.c
+@@ -110,6 +110,7 @@ void account_system_vtime(struct task_struct *tsk)
+ S390_lowcore.steal_clock -= cputime << 12;
+ account_system_time(tsk, 0, cputime);
+ }
++EXPORT_SYMBOL_GPL(account_system_vtime);
+
+ static inline void set_vtimer(__u64 expires)
+ {
+diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
+new file mode 100644
+index 0000000..1761b74
+--- /dev/null
++++ b/arch/s390/kvm/Kconfig
+@@ -0,0 +1,46 @@
++#
++# KVM configuration
++#
++config HAVE_KVM
++ bool
++
++menuconfig VIRTUALIZATION
++ bool "Virtualization"
++ default y
++ ---help---
++ Say Y here to get to see options for using your Linux host to run other
++ operating systems inside virtual machines (guests).
++ This option alone does not add any kernel code.
++
++ If you say N, all options in this submenu will be skipped and disabled.
++
++if VIRTUALIZATION
++
++config KVM
++ tristate "Kernel-based Virtual Machine (KVM) support"
++ depends on HAVE_KVM && EXPERIMENTAL
++ select PREEMPT_NOTIFIERS
++ select ANON_INODES
++ select S390_SWITCH_AMODE
++ select PREEMPT
++ ---help---
++ Support hosting paravirtualized guest machines using the SIE
++ virtualization capability on the mainframe. This should work
++ on any 64bit machine.
++
++ This module provides access to the hardware capabilities through
++ a character device node named /dev/kvm.
++
++ To compile this as a module, choose M here: the module
++ will be called kvm.
++
++ If unsure, say N.
++
++config KVM_TRACE
++ bool
++
++# OK, it's a little counter-intuitive to do this, but it puts it neatly under
++# the virtualization menu.
++source drivers/virtio/Kconfig
++
++endif # VIRTUALIZATION
+diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile
+new file mode 100644
+index 0000000..e5221ec
+--- /dev/null
++++ b/arch/s390/kvm/Makefile
+@@ -0,0 +1,14 @@
++# Makefile for kernel virtual machines on s390
++#
++# Copyright IBM Corp. 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.
++
++common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o)
++
++EXTRA_CFLAGS += -Ivirt/kvm -Iarch/s390/kvm
++
++kvm-objs := $(common-objs) kvm-s390.o sie64a.o intercept.o interrupt.o priv.o sigp.o diag.o
++obj-$(CONFIG_KVM) += kvm.o
+diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c
+new file mode 100644
+index 0000000..f639a15
+--- /dev/null
++++ b/arch/s390/kvm/diag.c
+@@ -0,0 +1,67 @@
++/*
++ * diag.c - handling diagnose instructions
++ *
++ * Copyright IBM Corp. 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): Carsten Otte <cotte at de.ibm.com>
++ * Christian Borntraeger <borntraeger at de.ibm.com>
++ */
++
++#include <linux/kvm.h>
++#include <linux/kvm_host.h>
++#include "kvm-s390.h"
++
++static int __diag_time_slice_end(struct kvm_vcpu *vcpu)
++{
++ VCPU_EVENT(vcpu, 5, "%s", "diag time slice end");
++ vcpu->stat.diagnose_44++;
++ vcpu_put(vcpu);
++ schedule();
++ vcpu_load(vcpu);
++ return 0;
++}
++
++static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
++{
++ unsigned int reg = vcpu->arch.sie_block->ipa & 0xf;
++ unsigned long subcode = vcpu->arch.guest_gprs[reg] & 0xffff;
++
++ VCPU_EVENT(vcpu, 5, "diag ipl functions, subcode %lx", subcode);
++ switch (subcode) {
++ case 3:
++ vcpu->run->s390_reset_flags = KVM_S390_RESET_CLEAR;
++ break;
++ case 4:
++ vcpu->run->s390_reset_flags = 0;
++ break;
++ default:
++ return -ENOTSUPP;
++ }
++
++ atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
++ vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM;
++ vcpu->run->s390_reset_flags |= KVM_S390_RESET_IPL;
++ vcpu->run->s390_reset_flags |= KVM_S390_RESET_CPU_INIT;
++ vcpu->run->exit_reason = KVM_EXIT_S390_RESET;
++ VCPU_EVENT(vcpu, 3, "requesting userspace resets %lx",
++ vcpu->run->s390_reset_flags);
++ return -EREMOTE;
++}
++
++int kvm_s390_handle_diag(struct kvm_vcpu *vcpu)
++{
++ int code = (vcpu->arch.sie_block->ipb & 0xfff0000) >> 16;
++
++ switch (code) {
++ case 0x44:
++ return __diag_time_slice_end(vcpu);
++ case 0x308:
++ return __diag_ipl_functions(vcpu);
++ default:
++ return -ENOTSUPP;
++ }
++}
+diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h
+new file mode 100644
+index 0000000..4e0633c
+--- /dev/null
++++ b/arch/s390/kvm/gaccess.h
+@@ -0,0 +1,274 @@
++/*
++ * gaccess.h - access guest memory
++ *
++ * Copyright IBM Corp. 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): Carsten Otte <cotte at de.ibm.com>
++ */
++
++#ifndef __KVM_S390_GACCESS_H
++#define __KVM_S390_GACCESS_H
++
++#include <linux/compiler.h>
++#include <linux/kvm_host.h>
++#include <asm/uaccess.h>
++
++static inline void __user *__guestaddr_to_user(struct kvm_vcpu *vcpu,
++ u64 guestaddr)
++{
++ u64 prefix = vcpu->arch.sie_block->prefix;
++ u64 origin = vcpu->kvm->arch.guest_origin;
++ u64 memsize = vcpu->kvm->arch.guest_memsize;
++
++ if (guestaddr < 2 * PAGE_SIZE)
++ guestaddr += prefix;
++ else if ((guestaddr >= prefix) && (guestaddr < prefix + 2 * PAGE_SIZE))
++ guestaddr -= prefix;
++
++ if (guestaddr > memsize)
++ return (void __user __force *) ERR_PTR(-EFAULT);
++
++ guestaddr += origin;
++
++ return (void __user *) guestaddr;
++}
++
++static inline int get_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
++ u64 *result)
++{
++ void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
++
++ BUG_ON(guestaddr & 7);
++
++ if (IS_ERR((void __force *) uptr))
++ return PTR_ERR((void __force *) uptr);
++
++ return get_user(*result, (u64 __user *) uptr);
++}
++
++static inline int get_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
++ u32 *result)
++{
++ void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
++
++ BUG_ON(guestaddr & 3);
++
++ if (IS_ERR((void __force *) uptr))
++ return PTR_ERR((void __force *) uptr);
++
++ return get_user(*result, (u32 __user *) uptr);
++}
++
++static inline int get_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
++ u16 *result)
++{
++ void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
++
++ BUG_ON(guestaddr & 1);
++
++ if (IS_ERR(uptr))
++ return PTR_ERR(uptr);
++
++ return get_user(*result, (u16 __user *) uptr);
++}
++
++static inline int get_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
++ u8 *result)
++{
++ void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
++
++ if (IS_ERR((void __force *) uptr))
++ return PTR_ERR((void __force *) uptr);
++
++ return get_user(*result, (u8 __user *) uptr);
++}
++
++static inline int put_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
++ u64 value)
++{
++ void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
++
++ BUG_ON(guestaddr & 7);
++
++ if (IS_ERR((void __force *) uptr))
++ return PTR_ERR((void __force *) uptr);
++
++ return put_user(value, (u64 __user *) uptr);
++}
++
++static inline int put_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
++ u32 value)
++{
++ void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
++
++ BUG_ON(guestaddr & 3);
++
++ if (IS_ERR((void __force *) uptr))
++ return PTR_ERR((void __force *) uptr);
++
++ return put_user(value, (u32 __user *) uptr);
++}
++
++static inline int put_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
++ u16 value)
++{
++ void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
++
++ BUG_ON(guestaddr & 1);
++
++ if (IS_ERR((void __force *) uptr))
++ return PTR_ERR((void __force *) uptr);
++
++ return put_user(value, (u16 __user *) uptr);
++}
++
++static inline int put_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
++ u8 value)
++{
++ void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
++
++ if (IS_ERR((void __force *) uptr))
++ return PTR_ERR((void __force *) uptr);
++
++ return put_user(value, (u8 __user *) uptr);
++}
++
++
++static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu, u64 guestdest,
++ const void *from, unsigned long n)
++{
++ int rc;
++ unsigned long i;
++ const u8 *data = from;
++
++ for (i = 0; i < n; i++) {
++ rc = put_guest_u8(vcpu, guestdest++, *(data++));
++ if (rc < 0)
++ return rc;
++ }
++ return 0;
++}
++
++static inline int copy_to_guest(struct kvm_vcpu *vcpu, u64 guestdest,
++ const void *from, unsigned long n)
++{
++ u64 prefix = vcpu->arch.sie_block->prefix;
++ u64 origin = vcpu->kvm->arch.guest_origin;
++ u64 memsize = vcpu->kvm->arch.guest_memsize;
++
++ if ((guestdest < 2 * PAGE_SIZE) && (guestdest + n > 2 * PAGE_SIZE))
++ goto slowpath;
++
++ if ((guestdest < prefix) && (guestdest + n > prefix))
++ goto slowpath;
++
++ if ((guestdest < prefix + 2 * PAGE_SIZE)
++ && (guestdest + n > prefix + 2 * PAGE_SIZE))
++ goto slowpath;
++
++ if (guestdest < 2 * PAGE_SIZE)
++ guestdest += prefix;
++ else if ((guestdest >= prefix) && (guestdest < prefix + 2 * PAGE_SIZE))
++ guestdest -= prefix;
++
++ if (guestdest + n > memsize)
++ return -EFAULT;
++
++ if (guestdest + n < guestdest)
++ return -EFAULT;
++
++ guestdest += origin;
++
++ return copy_to_user((void __user *) guestdest, from, n);
++slowpath:
++ return __copy_to_guest_slow(vcpu, guestdest, from, n);
++}
++
++static inline int __copy_from_guest_slow(struct kvm_vcpu *vcpu, void *to,
++ u64 guestsrc, unsigned long n)
++{
++ int rc;
++ unsigned long i;
++ u8 *data = to;
++
++ for (i = 0; i < n; i++) {
++ rc = get_guest_u8(vcpu, guestsrc++, data++);
++ if (rc < 0)
++ return rc;
++ }
++ return 0;
++}
++
++static inline int copy_from_guest(struct kvm_vcpu *vcpu, void *to,
++ u64 guestsrc, unsigned long n)
++{
++ u64 prefix = vcpu->arch.sie_block->prefix;
++ u64 origin = vcpu->kvm->arch.guest_origin;
++ u64 memsize = vcpu->kvm->arch.guest_memsize;
++
++ if ((guestsrc < 2 * PAGE_SIZE) && (guestsrc + n > 2 * PAGE_SIZE))
++ goto slowpath;
++
++ if ((guestsrc < prefix) && (guestsrc + n > prefix))
++ goto slowpath;
++
++ if ((guestsrc < prefix + 2 * PAGE_SIZE)
++ && (guestsrc + n > prefix + 2 * PAGE_SIZE))
++ goto slowpath;
++
++ if (guestsrc < 2 * PAGE_SIZE)
++ guestsrc += prefix;
++ else if ((guestsrc >= prefix) && (guestsrc < prefix + 2 * PAGE_SIZE))
++ guestsrc -= prefix;
++
++ if (guestsrc + n > memsize)
++ return -EFAULT;
++
++ if (guestsrc + n < guestsrc)
++ return -EFAULT;
++
++ guestsrc += origin;
++
++ return copy_from_user(to, (void __user *) guestsrc, n);
++slowpath:
++ return __copy_from_guest_slow(vcpu, to, guestsrc, n);
++}
++
++static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu, u64 guestdest,
++ const void *from, unsigned long n)
++{
++ u64 origin = vcpu->kvm->arch.guest_origin;
++ u64 memsize = vcpu->kvm->arch.guest_memsize;
++
++ if (guestdest + n > memsize)
++ return -EFAULT;
++
++ if (guestdest + n < guestdest)
++ return -EFAULT;
++
++ guestdest += origin;
++
++ return copy_to_user((void __user *) guestdest, from, n);
++}
++
++static inline int copy_from_guest_absolute(struct kvm_vcpu *vcpu, void *to,
++ u64 guestsrc, unsigned long n)
++{
++ u64 origin = vcpu->kvm->arch.guest_origin;
++ u64 memsize = vcpu->kvm->arch.guest_memsize;
++
++ if (guestsrc + n > memsize)
++ return -EFAULT;
++
++ if (guestsrc + n < guestsrc)
++ return -EFAULT;
++
++ guestsrc += origin;
++
++ return copy_from_user(to, (void __user *) guestsrc, n);
++}
++#endif
+diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
+new file mode 100644
+index 0000000..349581a
+--- /dev/null
++++ b/arch/s390/kvm/intercept.c
+@@ -0,0 +1,216 @@
++/*
++ * intercept.c - in-kernel handling for sie intercepts
++ *
++ * Copyright IBM Corp. 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): Carsten Otte <cotte at de.ibm.com>
++ * Christian Borntraeger <borntraeger at de.ibm.com>
++ */
++
++#include <linux/kvm_host.h>
++#include <linux/errno.h>
++#include <linux/pagemap.h>
++
++#include <asm/kvm_host.h>
++
++#include "kvm-s390.h"
++#include "gaccess.h"
++
++static int handle_lctg(struct kvm_vcpu *vcpu)
++{
++ int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
++ int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
++ int base2 = vcpu->arch.sie_block->ipb >> 28;
++ int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16) +
++ ((vcpu->arch.sie_block->ipb & 0xff00) << 4);
++ u64 useraddr;
++ int reg, rc;
++
++ vcpu->stat.instruction_lctg++;
++ if ((vcpu->arch.sie_block->ipb & 0xff) != 0x2f)
++ return -ENOTSUPP;
++
++ useraddr = disp2;
++ if (base2)
++ useraddr += vcpu->arch.guest_gprs[base2];
++
++ reg = reg1;
++
++ VCPU_EVENT(vcpu, 5, "lctg r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
++ disp2);
++
++ do {
++ rc = get_guest_u64(vcpu, useraddr,
++ &vcpu->arch.sie_block->gcr[reg]);
++ if (rc == -EFAULT) {
++ kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
++ break;
++ }
++ useraddr += 8;
++ if (reg == reg3)
++ break;
++ reg = (reg + 1) % 16;
++ } while (1);
++ return 0;
++}
++
++static int handle_lctl(struct kvm_vcpu *vcpu)
++{
++ int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
++ int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
++ int base2 = vcpu->arch.sie_block->ipb >> 28;
++ int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
++ u64 useraddr;
++ u32 val = 0;
++ int reg, rc;
++
++ vcpu->stat.instruction_lctl++;
++
++ useraddr = disp2;
++ if (base2)
++ useraddr += vcpu->arch.guest_gprs[base2];
++
++ VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
++ disp2);
++
++ reg = reg1;
++ do {
++ rc = get_guest_u32(vcpu, useraddr, &val);
++ if (rc == -EFAULT) {
++ kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
++ break;
++ }
++ vcpu->arch.sie_block->gcr[reg] &= 0xffffffff00000000ul;
++ vcpu->arch.sie_block->gcr[reg] |= val;
++ useraddr += 4;
++ if (reg == reg3)
++ break;
++ reg = (reg + 1) % 16;
++ } while (1);
++ return 0;
++}
++
++static intercept_handler_t instruction_handlers[256] = {
++ [0x83] = kvm_s390_handle_diag,
++ [0xae] = kvm_s390_handle_sigp,
++ [0xb2] = kvm_s390_handle_priv,
++ [0xb7] = handle_lctl,
++ [0xeb] = handle_lctg,
++};
++
++static int handle_noop(struct kvm_vcpu *vcpu)
++{
++ switch (vcpu->arch.sie_block->icptcode) {
++ case 0x10:
++ vcpu->stat.exit_external_request++;
++ break;
++ case 0x14:
++ vcpu->stat.exit_external_interrupt++;
++ break;
++ default:
++ break; /* nothing */
++ }
++ return 0;
++}
++
++static int handle_stop(struct kvm_vcpu *vcpu)
++{
++ int rc;
++
++ vcpu->stat.exit_stop_request++;
++ atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
++ spin_lock_bh(&vcpu->arch.local_int.lock);
++ if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) {
++ vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP;
++ rc = __kvm_s390_vcpu_store_status(vcpu,
++ KVM_S390_STORE_STATUS_NOADDR);
++ if (rc >= 0)
++ rc = -ENOTSUPP;
++ }
++
++ if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) {
++ vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP;
++ VCPU_EVENT(vcpu, 3, "%s", "cpu stopped");
++ rc = -ENOTSUPP;
++ } else
++ rc = 0;
++ spin_unlock_bh(&vcpu->arch.local_int.lock);
++ return rc;
++}
++
++static int handle_validity(struct kvm_vcpu *vcpu)
++{
++ int viwhy = vcpu->arch.sie_block->ipb >> 16;
++ vcpu->stat.exit_validity++;
++ if (viwhy == 0x37) {
++ fault_in_pages_writeable((char __user *)
++ vcpu->kvm->arch.guest_origin +
++ vcpu->arch.sie_block->prefix,
++ PAGE_SIZE);
++ return 0;
++ }
++ VCPU_EVENT(vcpu, 2, "unhandled validity intercept code %d",
++ viwhy);
++ return -ENOTSUPP;
++}
++
++static int handle_instruction(struct kvm_vcpu *vcpu)
++{
++ intercept_handler_t handler;
++
++ vcpu->stat.exit_instruction++;
++ handler = instruction_handlers[vcpu->arch.sie_block->ipa >> 8];
++ if (handler)
++ return handler(vcpu);
++ return -ENOTSUPP;
++}
++
++static int handle_prog(struct kvm_vcpu *vcpu)
++{
++ vcpu->stat.exit_program_interruption++;
++ return kvm_s390_inject_program_int(vcpu, vcpu->arch.sie_block->iprcc);
++}
++
++static int handle_instruction_and_prog(struct kvm_vcpu *vcpu)
++{
++ int rc, rc2;
++
++ vcpu->stat.exit_instr_and_program++;
++ rc = handle_instruction(vcpu);
++ rc2 = handle_prog(vcpu);
++
++ if (rc == -ENOTSUPP)
++ vcpu->arch.sie_block->icptcode = 0x04;
++ if (rc)
++ return rc;
++ return rc2;
++}
++
++static const intercept_handler_t intercept_funcs[0x48 >> 2] = {
++ [0x00 >> 2] = handle_noop,
++ [0x04 >> 2] = handle_instruction,
++ [0x08 >> 2] = handle_prog,
++ [0x0C >> 2] = handle_instruction_and_prog,
++ [0x10 >> 2] = handle_noop,
++ [0x14 >> 2] = handle_noop,
++ [0x1C >> 2] = kvm_s390_handle_wait,
++ [0x20 >> 2] = handle_validity,
++ [0x28 >> 2] = handle_stop,
++};
++
++int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)
++{
++ intercept_handler_t func;
++ u8 code = vcpu->arch.sie_block->icptcode;
++
++ if (code & 3 || code > 0x48)
++ return -ENOTSUPP;
++ func = intercept_funcs[code >> 2];
++ if (func)
++ return func(vcpu);
++ return -ENOTSUPP;
++}
+diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
+new file mode 100644
+index 0000000..fcd1ed8
+--- /dev/null
++++ b/arch/s390/kvm/interrupt.c
+@@ -0,0 +1,592 @@
++/*
++ * interrupt.c - handling kvm guest interrupts
++ *
++ * Copyright IBM Corp. 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): Carsten Otte <cotte at de.ibm.com>
++ */
++
++#include <asm/lowcore.h>
++#include <asm/uaccess.h>
++#include <linux/kvm_host.h>
++#include "kvm-s390.h"
++#include "gaccess.h"
++
++static int psw_extint_disabled(struct kvm_vcpu *vcpu)
++{
++ return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_EXT);
++}
++
++static int psw_interrupts_disabled(struct kvm_vcpu *vcpu)
++{
++ if ((vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PER) ||
++ (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_IO) ||
++ (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_EXT))
++ return 0;
++ return 1;
++}
++
++static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu,
++ struct interrupt_info *inti)
++{
++ switch (inti->type) {
++ case KVM_S390_INT_EMERGENCY:
++ if (psw_extint_disabled(vcpu))
++ return 0;
++ if (vcpu->arch.sie_block->gcr[0] & 0x4000ul)
++ return 1;
++ return 0;
++ case KVM_S390_INT_SERVICE:
++ if (psw_extint_disabled(vcpu))
++ return 0;
++ if (vcpu->arch.sie_block->gcr[0] & 0x200ul)
++ return 1;
++ return 0;
++ case KVM_S390_INT_VIRTIO:
++ if (psw_extint_disabled(vcpu))
++ return 0;
++ if (vcpu->arch.sie_block->gcr[0] & 0x200ul)
++ return 1;
++ return 0;
++ case KVM_S390_PROGRAM_INT:
++ case KVM_S390_SIGP_STOP:
++ case KVM_S390_SIGP_SET_PREFIX:
++ case KVM_S390_RESTART:
++ return 1;
++ default:
++ BUG();
++ }
++ return 0;
++}
++
++static void __set_cpu_idle(struct kvm_vcpu *vcpu)
++{
++ BUG_ON(vcpu->vcpu_id > KVM_MAX_VCPUS - 1);
++ atomic_set_mask(CPUSTAT_WAIT, &vcpu->arch.sie_block->cpuflags);
++ set_bit(vcpu->vcpu_id, vcpu->arch.local_int.float_int->idle_mask);
++}
++
++static void __unset_cpu_idle(struct kvm_vcpu *vcpu)
++{
++ BUG_ON(vcpu->vcpu_id > KVM_MAX_VCPUS - 1);
++ atomic_clear_mask(CPUSTAT_WAIT, &vcpu->arch.sie_block->cpuflags);
++ clear_bit(vcpu->vcpu_id, vcpu->arch.local_int.float_int->idle_mask);
++}
++
++static void __reset_intercept_indicators(struct kvm_vcpu *vcpu)
++{
++ atomic_clear_mask(CPUSTAT_ECALL_PEND |
++ CPUSTAT_IO_INT | CPUSTAT_EXT_INT | CPUSTAT_STOP_INT,
++ &vcpu->arch.sie_block->cpuflags);
++ vcpu->arch.sie_block->lctl = 0x0000;
++}
++
++static void __set_cpuflag(struct kvm_vcpu *vcpu, u32 flag)
++{
++ atomic_set_mask(flag, &vcpu->arch.sie_block->cpuflags);
++}
++
++static void __set_intercept_indicator(struct kvm_vcpu *vcpu,
++ struct interrupt_info *inti)
++{
++ switch (inti->type) {
++ case KVM_S390_INT_EMERGENCY:
++ case KVM_S390_INT_SERVICE:
++ case KVM_S390_INT_VIRTIO:
++ if (psw_extint_disabled(vcpu))
++ __set_cpuflag(vcpu, CPUSTAT_EXT_INT);
++ else
++ vcpu->arch.sie_block->lctl |= LCTL_CR0;
++ break;
++ case KVM_S390_SIGP_STOP:
++ __set_cpuflag(vcpu, CPUSTAT_STOP_INT);
++ break;
++ default:
++ BUG();
++ }
++}
++
++static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
++ struct interrupt_info *inti)
++{
++ const unsigned short table[] = { 2, 4, 4, 6 };
++ int rc, exception = 0;
++
++ switch (inti->type) {
++ case KVM_S390_INT_EMERGENCY:
++ VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp emerg");
++ vcpu->stat.deliver_emergency_signal++;
++ rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x1201);
++ if (rc == -EFAULT)
++ exception = 1;
++
++ rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ if (rc == -EFAULT)
++ exception = 1;
++
++ rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
++ __LC_EXT_NEW_PSW, sizeof(psw_t));
++ if (rc == -EFAULT)
++ exception = 1;
++ break;
++
++ case KVM_S390_INT_SERVICE:
++ VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x",
++ inti->ext.ext_params);
++ vcpu->stat.deliver_service_signal++;
++ rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x2401);
++ if (rc == -EFAULT)
++ exception = 1;
++
++ rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ if (rc == -EFAULT)
++ exception = 1;
++
++ rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
++ __LC_EXT_NEW_PSW, sizeof(psw_t));
++ if (rc == -EFAULT)
++ exception = 1;
++
++ rc = put_guest_u32(vcpu, __LC_EXT_PARAMS, inti->ext.ext_params);
++ if (rc == -EFAULT)
++ exception = 1;
++ break;
++
++ case KVM_S390_INT_VIRTIO:
++ VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%lx",
++ inti->ext.ext_params, inti->ext.ext_params2);
++ vcpu->stat.deliver_virtio_interrupt++;
++ rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x2603);
++ if (rc == -EFAULT)
++ exception = 1;
++
++ rc = put_guest_u16(vcpu, __LC_CPU_ADDRESS, 0x0d00);
++ if (rc == -EFAULT)
++ exception = 1;
++
++ rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ if (rc == -EFAULT)
++ exception = 1;
++
++ rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
++ __LC_EXT_NEW_PSW, sizeof(psw_t));
++ if (rc == -EFAULT)
++ exception = 1;
++
++ rc = put_guest_u32(vcpu, __LC_EXT_PARAMS, inti->ext.ext_params);
++ if (rc == -EFAULT)
++ exception = 1;
++
++ rc = put_guest_u64(vcpu, __LC_PFAULT_INTPARM,
++ inti->ext.ext_params2);
++ if (rc == -EFAULT)
++ exception = 1;
++ break;
++
++ case KVM_S390_SIGP_STOP:
++ VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu stop");
++ vcpu->stat.deliver_stop_signal++;
++ __set_intercept_indicator(vcpu, inti);
++ break;
++
++ case KVM_S390_SIGP_SET_PREFIX:
++ VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x",
++ inti->prefix.address);
++ vcpu->stat.deliver_prefix_signal++;
++ vcpu->arch.sie_block->prefix = inti->prefix.address;
++ vcpu->arch.sie_block->ihcpu = 0xffff;
++ break;
++
++ case KVM_S390_RESTART:
++ VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu restart");
++ vcpu->stat.deliver_restart_signal++;
++ rc = copy_to_guest(vcpu, offsetof(struct _lowcore,
++ restart_old_psw), &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ if (rc == -EFAULT)
++ exception = 1;
++
++ rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
++ offsetof(struct _lowcore, restart_psw), sizeof(psw_t));
++ if (rc == -EFAULT)
++ exception = 1;
++ break;
++
++ case KVM_S390_PROGRAM_INT:
++ VCPU_EVENT(vcpu, 4, "interrupt: pgm check code:%x, ilc:%x",
++ inti->pgm.code,
++ table[vcpu->arch.sie_block->ipa >> 14]);
++ vcpu->stat.deliver_program_int++;
++ rc = put_guest_u16(vcpu, __LC_PGM_INT_CODE, inti->pgm.code);
++ if (rc == -EFAULT)
++ exception = 1;
++
++ rc = put_guest_u16(vcpu, __LC_PGM_ILC,
++ table[vcpu->arch.sie_block->ipa >> 14]);
++ if (rc == -EFAULT)
++ exception = 1;
++
++ rc = copy_to_guest(vcpu, __LC_PGM_OLD_PSW,
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ if (rc == -EFAULT)
++ exception = 1;
++
++ rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
++ __LC_PGM_NEW_PSW, sizeof(psw_t));
++ if (rc == -EFAULT)
++ exception = 1;
++ break;
++
++ default:
++ BUG();
++ }
++
++ if (exception) {
++ VCPU_EVENT(vcpu, 1, "%s", "program exception while delivering"
++ " interrupt");
++ kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
++ if (inti->type == KVM_S390_PROGRAM_INT) {
++ printk(KERN_WARNING "kvm: recursive program check\n");
++ BUG();
++ }
++ }
++}
++
++static int __try_deliver_ckc_interrupt(struct kvm_vcpu *vcpu)
++{
++ int rc, exception = 0;
++
++ if (psw_extint_disabled(vcpu))
++ return 0;
++ if (!(vcpu->arch.sie_block->gcr[0] & 0x800ul))
++ return 0;
++ rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x1004);
++ if (rc == -EFAULT)
++ exception = 1;
++ rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ if (rc == -EFAULT)
++ exception = 1;
++ rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
++ __LC_EXT_NEW_PSW, sizeof(psw_t));
++ if (rc == -EFAULT)
++ exception = 1;
++
++ if (exception) {
++ VCPU_EVENT(vcpu, 1, "%s", "program exception while delivering" \
++ " ckc interrupt");
++ kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
++ return 0;
++ }
++
++ return 1;
++}
++
++int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu)
++{
++ struct local_interrupt *li = &vcpu->arch.local_int;
++ struct float_interrupt *fi = vcpu->arch.local_int.float_int;
++ struct interrupt_info *inti;
++ int rc = 0;
++
++ if (atomic_read(&li->active)) {
++ spin_lock_bh(&li->lock);
++ list_for_each_entry(inti, &li->list, list)
++ if (__interrupt_is_deliverable(vcpu, inti)) {
++ rc = 1;
++ break;
++ }
++ spin_unlock_bh(&li->lock);
++ }
++
++ if ((!rc) && atomic_read(&fi->active)) {
++ spin_lock_bh(&fi->lock);
++ list_for_each_entry(inti, &fi->list, list)
++ if (__interrupt_is_deliverable(vcpu, inti)) {
++ rc = 1;
++ break;
++ }
++ spin_unlock_bh(&fi->lock);
++ }
++
++ if ((!rc) && (vcpu->arch.sie_block->ckc <
++ get_clock() + vcpu->arch.sie_block->epoch)) {
++ if ((!psw_extint_disabled(vcpu)) &&
++ (vcpu->arch.sie_block->gcr[0] & 0x800ul))
++ rc = 1;
++ }
++
++ return rc;
++}
++
++int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
++{
++ return 0;
++}
++
++int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
++{
++ u64 now, sltime;
++ DECLARE_WAITQUEUE(wait, current);
++
++ vcpu->stat.exit_wait_state++;
++ if (kvm_cpu_has_interrupt(vcpu))
++ return 0;
++
++ if (psw_interrupts_disabled(vcpu)) {
++ VCPU_EVENT(vcpu, 3, "%s", "disabled wait");
++ __unset_cpu_idle(vcpu);
++ return -ENOTSUPP; /* disabled wait */
++ }
++
++ if (psw_extint_disabled(vcpu) ||
++ (!(vcpu->arch.sie_block->gcr[0] & 0x800ul))) {
++ VCPU_EVENT(vcpu, 3, "%s", "enabled wait w/o timer");
++ goto no_timer;
++ }
++
++ now = get_clock() + vcpu->arch.sie_block->epoch;
++ if (vcpu->arch.sie_block->ckc < now) {
++ __unset_cpu_idle(vcpu);
++ return 0;
++ }
++
++ sltime = (vcpu->arch.sie_block->ckc - now) / (0xf4240000ul / HZ) + 1;
++
++ vcpu->arch.ckc_timer.expires = jiffies + sltime;
++
++ add_timer(&vcpu->arch.ckc_timer);
++ VCPU_EVENT(vcpu, 5, "enabled wait timer:%lx jiffies", sltime);
++no_timer:
++ spin_lock_bh(&vcpu->arch.local_int.float_int->lock);
++ spin_lock_bh(&vcpu->arch.local_int.lock);
++ __set_cpu_idle(vcpu);
++ vcpu->arch.local_int.timer_due = 0;
++ add_wait_queue(&vcpu->arch.local_int.wq, &wait);
++ while (list_empty(&vcpu->arch.local_int.list) &&
++ list_empty(&vcpu->arch.local_int.float_int->list) &&
++ (!vcpu->arch.local_int.timer_due) &&
++ !signal_pending(current)) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ spin_unlock_bh(&vcpu->arch.local_int.lock);
++ spin_unlock_bh(&vcpu->arch.local_int.float_int->lock);
++ vcpu_put(vcpu);
++ schedule();
++ vcpu_load(vcpu);
++ spin_lock_bh(&vcpu->arch.local_int.float_int->lock);
++ spin_lock_bh(&vcpu->arch.local_int.lock);
++ }
++ __unset_cpu_idle(vcpu);
++ __set_current_state(TASK_RUNNING);
++ remove_wait_queue(&vcpu->wq, &wait);
++ spin_unlock_bh(&vcpu->arch.local_int.lock);
++ spin_unlock_bh(&vcpu->arch.local_int.float_int->lock);
++ del_timer(&vcpu->arch.ckc_timer);
++ return 0;
++}
++
++void kvm_s390_idle_wakeup(unsigned long data)
++{
++ struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
++
++ spin_lock_bh(&vcpu->arch.local_int.lock);
++ vcpu->arch.local_int.timer_due = 1;
++ if (waitqueue_active(&vcpu->arch.local_int.wq))
++ wake_up_interruptible(&vcpu->arch.local_int.wq);
++ spin_unlock_bh(&vcpu->arch.local_int.lock);
++}
++
++
++void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
++{
++ struct local_interrupt *li = &vcpu->arch.local_int;
++ struct float_interrupt *fi = vcpu->arch.local_int.float_int;
++ struct interrupt_info *n, *inti = NULL;
++ int deliver;
++
++ __reset_intercept_indicators(vcpu);
++ if (atomic_read(&li->active)) {
++ do {
++ deliver = 0;
++ spin_lock_bh(&li->lock);
++ list_for_each_entry_safe(inti, n, &li->list, list) {
++ if (__interrupt_is_deliverable(vcpu, inti)) {
++ list_del(&inti->list);
++ deliver = 1;
++ break;
++ }
++ __set_intercept_indicator(vcpu, inti);
++ }
++ if (list_empty(&li->list))
++ atomic_set(&li->active, 0);
++ spin_unlock_bh(&li->lock);
++ if (deliver) {
++ __do_deliver_interrupt(vcpu, inti);
++ kfree(inti);
++ }
++ } while (deliver);
++ }
++
++ if ((vcpu->arch.sie_block->ckc <
++ get_clock() + vcpu->arch.sie_block->epoch))
++ __try_deliver_ckc_interrupt(vcpu);
++
++ if (atomic_read(&fi->active)) {
++ do {
++ deliver = 0;
++ spin_lock_bh(&fi->lock);
++ list_for_each_entry_safe(inti, n, &fi->list, list) {
++ if (__interrupt_is_deliverable(vcpu, inti)) {
++ list_del(&inti->list);
++ deliver = 1;
++ break;
++ }
++ __set_intercept_indicator(vcpu, inti);
++ }
++ if (list_empty(&fi->list))
++ atomic_set(&fi->active, 0);
++ spin_unlock_bh(&fi->lock);
++ if (deliver) {
++ __do_deliver_interrupt(vcpu, inti);
++ kfree(inti);
++ }
++ } while (deliver);
++ }
++}
++
++int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
++{
++ struct local_interrupt *li = &vcpu->arch.local_int;
++ struct interrupt_info *inti;
++
++ inti = kzalloc(sizeof(*inti), GFP_KERNEL);
++ if (!inti)
++ return -ENOMEM;
++
++ inti->type = KVM_S390_PROGRAM_INT;;
++ inti->pgm.code = code;
++
++ VCPU_EVENT(vcpu, 3, "inject: program check %d (from kernel)", code);
++ spin_lock_bh(&li->lock);
++ list_add(&inti->list, &li->list);
++ atomic_set(&li->active, 1);
++ BUG_ON(waitqueue_active(&li->wq));
++ spin_unlock_bh(&li->lock);
++ return 0;
++}
++
++int kvm_s390_inject_vm(struct kvm *kvm,
++ struct kvm_s390_interrupt *s390int)
++{
++ struct local_interrupt *li;
++ struct float_interrupt *fi;
++ struct interrupt_info *inti;
++ int sigcpu;
++
++ inti = kzalloc(sizeof(*inti), GFP_KERNEL);
++ if (!inti)
++ return -ENOMEM;
++
++ switch (s390int->type) {
++ case KVM_S390_INT_VIRTIO:
++ VM_EVENT(kvm, 5, "inject: virtio parm:%x,parm64:%lx",
++ s390int->parm, s390int->parm64);
++ inti->type = s390int->type;
++ inti->ext.ext_params = s390int->parm;
++ inti->ext.ext_params2 = s390int->parm64;
++ break;
++ case KVM_S390_INT_SERVICE:
++ VM_EVENT(kvm, 5, "inject: sclp parm:%x", s390int->parm);
++ inti->type = s390int->type;
++ inti->ext.ext_params = s390int->parm;
++ break;
++ case KVM_S390_PROGRAM_INT:
++ case KVM_S390_SIGP_STOP:
++ case KVM_S390_INT_EMERGENCY:
++ default:
++ kfree(inti);
++ return -EINVAL;
++ }
++
++ mutex_lock(&kvm->lock);
++ fi = &kvm->arch.float_int;
++ spin_lock_bh(&fi->lock);
++ list_add_tail(&inti->list, &fi->list);
++ atomic_set(&fi->active, 1);
++ sigcpu = find_first_bit(fi->idle_mask, KVM_MAX_VCPUS);
++ if (sigcpu == KVM_MAX_VCPUS) {
++ do {
++ sigcpu = fi->next_rr_cpu++;
++ if (sigcpu == KVM_MAX_VCPUS)
++ sigcpu = fi->next_rr_cpu = 0;
++ } while (fi->local_int[sigcpu] == NULL);
++ }
++ li = fi->local_int[sigcpu];
++ spin_lock_bh(&li->lock);
++ atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
++ if (waitqueue_active(&li->wq))
++ wake_up_interruptible(&li->wq);
++ spin_unlock_bh(&li->lock);
++ spin_unlock_bh(&fi->lock);
++ mutex_unlock(&kvm->lock);
++ return 0;
++}
++
++int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
++ struct kvm_s390_interrupt *s390int)
++{
++ struct local_interrupt *li;
++ struct interrupt_info *inti;
++
++ inti = kzalloc(sizeof(*inti), GFP_KERNEL);
++ if (!inti)
++ return -ENOMEM;
++
++ switch (s390int->type) {
++ case KVM_S390_PROGRAM_INT:
++ if (s390int->parm & 0xffff0000) {
++ kfree(inti);
++ return -EINVAL;
++ }
++ inti->type = s390int->type;
++ inti->pgm.code = s390int->parm;
++ VCPU_EVENT(vcpu, 3, "inject: program check %d (from user)",
++ s390int->parm);
++ break;
++ case KVM_S390_SIGP_STOP:
++ case KVM_S390_RESTART:
++ case KVM_S390_SIGP_SET_PREFIX:
++ case KVM_S390_INT_EMERGENCY:
++ VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
++ inti->type = s390int->type;
++ break;
++ case KVM_S390_INT_VIRTIO:
++ case KVM_S390_INT_SERVICE:
++ default:
++ kfree(inti);
++ return -EINVAL;
++ }
++
++ mutex_lock(&vcpu->kvm->lock);
++ li = &vcpu->arch.local_int;
++ spin_lock_bh(&li->lock);
++ if (inti->type == KVM_S390_PROGRAM_INT)
++ list_add(&inti->list, &li->list);
++ else
++ list_add_tail(&inti->list, &li->list);
++ atomic_set(&li->active, 1);
++ if (inti->type == KVM_S390_SIGP_STOP)
++ li->action_bits |= ACTION_STOP_ON_STOP;
++ atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
++ if (waitqueue_active(&li->wq))
++ wake_up_interruptible(&vcpu->arch.local_int.wq);
++ spin_unlock_bh(&li->lock);
++ mutex_unlock(&vcpu->kvm->lock);
++ return 0;
++}
+diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
+new file mode 100644
+index 0000000..98d1e73
+--- /dev/null
++++ b/arch/s390/kvm/kvm-s390.c
+@@ -0,0 +1,685 @@
++/*
++ * s390host.c -- hosting zSeries kernel virtual machines
++ *
++ * Copyright IBM Corp. 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): Carsten Otte <cotte at de.ibm.com>
++ * Christian Borntraeger <borntraeger at de.ibm.com>
++ * Heiko Carstens <heiko.carstens at de.ibm.com>
++ */
++
++#include <linux/compiler.h>
++#include <linux/err.h>
++#include <linux/fs.h>
++#include <linux/init.h>
++#include <linux/kvm.h>
++#include <linux/kvm_host.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/timer.h>
++#include <asm/lowcore.h>
++#include <asm/pgtable.h>
++
++#include "kvm-s390.h"
++#include "gaccess.h"
++
++#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
++
++struct kvm_stats_debugfs_item debugfs_entries[] = {
++ { "userspace_handled", VCPU_STAT(exit_userspace) },
++ { "exit_validity", VCPU_STAT(exit_validity) },
++ { "exit_stop_request", VCPU_STAT(exit_stop_request) },
++ { "exit_external_request", VCPU_STAT(exit_external_request) },
++ { "exit_external_interrupt", VCPU_STAT(exit_external_interrupt) },
++ { "exit_instruction", VCPU_STAT(exit_instruction) },
++ { "exit_program_interruption", VCPU_STAT(exit_program_interruption) },
++ { "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) },
++ { "instruction_lctg", VCPU_STAT(instruction_lctg) },
++ { "instruction_lctl", VCPU_STAT(instruction_lctl) },
++ { "deliver_emergency_signal", VCPU_STAT(deliver_emergency_signal) },
++ { "deliver_service_signal", VCPU_STAT(deliver_service_signal) },
++ { "deliver_virtio_interrupt", VCPU_STAT(deliver_virtio_interrupt) },
++ { "deliver_stop_signal", VCPU_STAT(deliver_stop_signal) },
++ { "deliver_prefix_signal", VCPU_STAT(deliver_prefix_signal) },
++ { "deliver_restart_signal", VCPU_STAT(deliver_restart_signal) },
++ { "deliver_program_interruption", VCPU_STAT(deliver_program_int) },
++ { "exit_wait_state", VCPU_STAT(exit_wait_state) },
++ { "instruction_stidp", VCPU_STAT(instruction_stidp) },
++ { "instruction_spx", VCPU_STAT(instruction_spx) },
++ { "instruction_stpx", VCPU_STAT(instruction_stpx) },
++ { "instruction_stap", VCPU_STAT(instruction_stap) },
++ { "instruction_storage_key", VCPU_STAT(instruction_storage_key) },
++ { "instruction_stsch", VCPU_STAT(instruction_stsch) },
++ { "instruction_chsc", VCPU_STAT(instruction_chsc) },
++ { "instruction_stsi", VCPU_STAT(instruction_stsi) },
++ { "instruction_stfl", VCPU_STAT(instruction_stfl) },
++ { "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) },
++ { "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) },
++ { "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) },
++ { "instruction_sigp_set_arch", VCPU_STAT(instruction_sigp_arch) },
++ { "instruction_sigp_set_prefix", VCPU_STAT(instruction_sigp_prefix) },
++ { "instruction_sigp_restart", VCPU_STAT(instruction_sigp_restart) },
++ { "diagnose_44", VCPU_STAT(diagnose_44) },
++ { NULL }
++};
++
++
++/* Section: not file related */
++void kvm_arch_hardware_enable(void *garbage)
++{
++ /* every s390 is virtualization enabled ;-) */
++}
++
++void kvm_arch_hardware_disable(void *garbage)
++{
++}
++
++void decache_vcpus_on_cpu(int cpu)
++{
++}
++
++int kvm_arch_hardware_setup(void)
++{
++ return 0;
++}
++
++void kvm_arch_hardware_unsetup(void)
++{
++}
++
++void kvm_arch_check_processor_compat(void *rtn)
++{
++}
++
++int kvm_arch_init(void *opaque)
++{
++ return 0;
++}
++
++void kvm_arch_exit(void)
++{
++}
++
++/* Section: device related */
++long kvm_arch_dev_ioctl(struct file *filp,
++ unsigned int ioctl, unsigned long arg)
++{
++ if (ioctl == KVM_S390_ENABLE_SIE)
++ return s390_enable_sie();
++ return -EINVAL;
++}
++
++int kvm_dev_ioctl_check_extension(long ext)
++{
++ return 0;
++}
++
++/* Section: vm related */
++/*
++ * Get (and clear) the dirty memory log for a memory slot.
++ */
++int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
++ struct kvm_dirty_log *log)
++{
++ return 0;
++}
++
++long kvm_arch_vm_ioctl(struct file *filp,
++ unsigned int ioctl, unsigned long arg)
++{
++ struct kvm *kvm = filp->private_data;
++ void __user *argp = (void __user *)arg;
++ int r;
++
++ switch (ioctl) {
++ case KVM_S390_INTERRUPT: {
++ struct kvm_s390_interrupt s390int;
++
++ r = -EFAULT;
++ if (copy_from_user(&s390int, argp, sizeof(s390int)))
++ break;
++ r = kvm_s390_inject_vm(kvm, &s390int);
++ break;
++ }
++ default:
++ r = -EINVAL;
++ }
++
++ return r;
++}
++
++struct kvm *kvm_arch_create_vm(void)
++{
++ struct kvm *kvm;
++ int rc;
++ char debug_name[16];
++
++ rc = s390_enable_sie();
++ if (rc)
++ goto out_nokvm;
++
++ rc = -ENOMEM;
++ kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL);
++ if (!kvm)
++ goto out_nokvm;
++
++ kvm->arch.sca = (struct sca_block *) get_zeroed_page(GFP_KERNEL);
++ if (!kvm->arch.sca)
++ goto out_nosca;
++
++ sprintf(debug_name, "kvm-%u", current->pid);
++
++ kvm->arch.dbf = debug_register(debug_name, 8, 2, 8 * sizeof(long));
++ if (!kvm->arch.dbf)
++ goto out_nodbf;
++
++ spin_lock_init(&kvm->arch.float_int.lock);
++ INIT_LIST_HEAD(&kvm->arch.float_int.list);
++
++ debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
++ VM_EVENT(kvm, 3, "%s", "vm created");
++
++ try_module_get(THIS_MODULE);
++
++ return kvm;
++out_nodbf:
++ free_page((unsigned long)(kvm->arch.sca));
++out_nosca:
++ kfree(kvm);
++out_nokvm:
++ return ERR_PTR(rc);
++}
++
++void kvm_arch_destroy_vm(struct kvm *kvm)
++{
++ debug_unregister(kvm->arch.dbf);
++ free_page((unsigned long)(kvm->arch.sca));
++ kfree(kvm);
++ module_put(THIS_MODULE);
++}
++
++/* Section: vcpu related */
++int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
++{
++ return 0;
++}
++
++void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
++{
++ /* kvm common code refers to this, but does'nt call it */
++ BUG();
++}
++
++void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
++{
++ save_fp_regs(&vcpu->arch.host_fpregs);
++ save_access_regs(vcpu->arch.host_acrs);
++ vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK;
++ restore_fp_regs(&vcpu->arch.guest_fpregs);
++ restore_access_regs(vcpu->arch.guest_acrs);
++
++ if (signal_pending(current))
++ atomic_set_mask(CPUSTAT_STOP_INT,
++ &vcpu->arch.sie_block->cpuflags);
++}
++
++void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
++{
++ save_fp_regs(&vcpu->arch.guest_fpregs);
++ save_access_regs(vcpu->arch.guest_acrs);
++ restore_fp_regs(&vcpu->arch.host_fpregs);
++ restore_access_regs(vcpu->arch.host_acrs);
++}
++
++static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
++{
++ /* this equals initial cpu reset in pop, but we don't switch to ESA */
++ vcpu->arch.sie_block->gpsw.mask = 0UL;
++ vcpu->arch.sie_block->gpsw.addr = 0UL;
++ vcpu->arch.sie_block->prefix = 0UL;
++ vcpu->arch.sie_block->ihcpu = 0xffff;
++ vcpu->arch.sie_block->cputm = 0UL;
++ vcpu->arch.sie_block->ckc = 0UL;
++ vcpu->arch.sie_block->todpr = 0;
++ memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64));
++ vcpu->arch.sie_block->gcr[0] = 0xE0UL;
++ vcpu->arch.sie_block->gcr[14] = 0xC2000000UL;
++ vcpu->arch.guest_fpregs.fpc = 0;
++ asm volatile("lfpc %0" : : "Q" (vcpu->arch.guest_fpregs.fpc));
++ vcpu->arch.sie_block->gbea = 1;
++}
++
++int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
++{
++ atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH);
++ vcpu->arch.sie_block->gmslm = 0xffffffffffUL;
++ vcpu->arch.sie_block->gmsor = 0x000000000000;
++ vcpu->arch.sie_block->ecb = 2;
++ vcpu->arch.sie_block->eca = 0xC1002001U;
++ setup_timer(&vcpu->arch.ckc_timer, kvm_s390_idle_wakeup,
++ (unsigned long) vcpu);
++ get_cpu_id(&vcpu->arch.cpu_id);
++ vcpu->arch.cpu_id.version = 0xfe;
++ return 0;
++}
++
++struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
++ unsigned int id)
++{
++ struct kvm_vcpu *vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
++ int rc = -ENOMEM;
++
++ if (!vcpu)
++ goto out_nomem;
++
++ vcpu->arch.sie_block = (struct sie_block *) get_zeroed_page(GFP_KERNEL);
++
++ if (!vcpu->arch.sie_block)
++ goto out_free_cpu;
++
++ vcpu->arch.sie_block->icpua = id;
++ BUG_ON(!kvm->arch.sca);
++ BUG_ON(kvm->arch.sca->cpu[id].sda);
++ kvm->arch.sca->cpu[id].sda = (__u64) vcpu->arch.sie_block;
++ vcpu->arch.sie_block->scaoh = (__u32)(((__u64)kvm->arch.sca) >> 32);
++ vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca;
++
++ spin_lock_init(&vcpu->arch.local_int.lock);
++ INIT_LIST_HEAD(&vcpu->arch.local_int.list);
++ vcpu->arch.local_int.float_int = &kvm->arch.float_int;
++ spin_lock_bh(&kvm->arch.float_int.lock);
++ kvm->arch.float_int.local_int[id] = &vcpu->arch.local_int;
++ init_waitqueue_head(&vcpu->arch.local_int.wq);
++ vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
++ spin_unlock_bh(&kvm->arch.float_int.lock);
++
++ rc = kvm_vcpu_init(vcpu, kvm, id);
++ if (rc)
++ goto out_free_cpu;
++ VM_EVENT(kvm, 3, "create cpu %d at %p, sie block at %p", id, vcpu,
++ vcpu->arch.sie_block);
++
++ try_module_get(THIS_MODULE);
++
++ return vcpu;
++out_free_cpu:
++ kfree(vcpu);
++out_nomem:
++ return ERR_PTR(rc);
++}
++
++void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
++{
++ VCPU_EVENT(vcpu, 3, "%s", "destroy cpu");
++ free_page((unsigned long)(vcpu->arch.sie_block));
++ kfree(vcpu);
++ module_put(THIS_MODULE);
++}
++
++int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
++{
++ /* kvm common code refers to this, but never calls it */
++ BUG();
++ return 0;
++}
++
++static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
++{
++ vcpu_load(vcpu);
++ kvm_s390_vcpu_initial_reset(vcpu);
++ vcpu_put(vcpu);
++ return 0;
++}
++
++int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
++{
++ vcpu_load(vcpu);
++ memcpy(&vcpu->arch.guest_gprs, ®s->gprs, sizeof(regs->gprs));
++ vcpu_put(vcpu);
++ return 0;
++}
++
++int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
++{
++ vcpu_load(vcpu);
++ memcpy(®s->gprs, &vcpu->arch.guest_gprs, sizeof(regs->gprs));
++ vcpu_put(vcpu);
++ return 0;
++}
++
++int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
++ struct kvm_sregs *sregs)
++{
++ vcpu_load(vcpu);
++ memcpy(&vcpu->arch.guest_acrs, &sregs->acrs, sizeof(sregs->acrs));
++ memcpy(&vcpu->arch.sie_block->gcr, &sregs->crs, sizeof(sregs->crs));
++ vcpu_put(vcpu);
++ return 0;
++}
++
++int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
++ struct kvm_sregs *sregs)
++{
++ vcpu_load(vcpu);
++ memcpy(&sregs->acrs, &vcpu->arch.guest_acrs, sizeof(sregs->acrs));
++ memcpy(&sregs->crs, &vcpu->arch.sie_block->gcr, sizeof(sregs->crs));
++ vcpu_put(vcpu);
++ return 0;
++}
++
++int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
++{
++ vcpu_load(vcpu);
++ memcpy(&vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
++ vcpu->arch.guest_fpregs.fpc = fpu->fpc;
++ vcpu_put(vcpu);
++ return 0;
++}
++
++int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
++{
++ vcpu_load(vcpu);
++ memcpy(&fpu->fprs, &vcpu->arch.guest_fpregs.fprs, sizeof(fpu->fprs));
++ fpu->fpc = vcpu->arch.guest_fpregs.fpc;
++ vcpu_put(vcpu);
++ return 0;
++}
++
++static int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw)
++{
++ int rc = 0;
++
++ vcpu_load(vcpu);
++ if (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_RUNNING)
++ rc = -EBUSY;
++ else
++ vcpu->arch.sie_block->gpsw = psw;
++ vcpu_put(vcpu);
++ return rc;
++}
++
++int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
++ struct kvm_translation *tr)
++{
++ return -EINVAL; /* not implemented yet */
++}
++
++int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
++ struct kvm_debug_guest *dbg)
++{
++ return -EINVAL; /* not implemented yet */
++}
++
++int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
++ struct kvm_mp_state *mp_state)
++{
++ return -EINVAL; /* not implemented yet */
++}
++
++int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
++ struct kvm_mp_state *mp_state)
++{
++ return -EINVAL; /* not implemented yet */
++}
++
++static void __vcpu_run(struct kvm_vcpu *vcpu)
++{
++ memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16);
++
++ if (need_resched())
++ schedule();
++
++ vcpu->arch.sie_block->icptcode = 0;
++ local_irq_disable();
++ kvm_guest_enter();
++ local_irq_enable();
++ VCPU_EVENT(vcpu, 6, "entering sie flags %x",
++ atomic_read(&vcpu->arch.sie_block->cpuflags));
++ sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs);
++ VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
++ vcpu->arch.sie_block->icptcode);
++ local_irq_disable();
++ kvm_guest_exit();
++ local_irq_enable();
++
++ memcpy(&vcpu->arch.guest_gprs[14], &vcpu->arch.sie_block->gg14, 16);
++}
++
++int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
++{
++ int rc;
++ sigset_t sigsaved;
++
++ vcpu_load(vcpu);
++
++ if (vcpu->sigset_active)
++ sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
++
++ atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
++
++ BUG_ON(vcpu->kvm->arch.float_int.local_int[vcpu->vcpu_id] == NULL);
++
++ switch (kvm_run->exit_reason) {
++ case KVM_EXIT_S390_SIEIC:
++ vcpu->arch.sie_block->gpsw.mask = kvm_run->s390_sieic.mask;
++ vcpu->arch.sie_block->gpsw.addr = kvm_run->s390_sieic.addr;
++ break;
++ case KVM_EXIT_UNKNOWN:
++ case KVM_EXIT_S390_RESET:
++ break;
++ default:
++ BUG();
++ }
++
++ might_sleep();
++
++ do {
++ kvm_s390_deliver_pending_interrupts(vcpu);
++ __vcpu_run(vcpu);
++ rc = kvm_handle_sie_intercept(vcpu);
++ } while (!signal_pending(current) && !rc);
++
++ if (signal_pending(current) && !rc)
++ rc = -EINTR;
++
++ if (rc == -ENOTSUPP) {
++ /* intercept cannot be handled in-kernel, prepare kvm-run */
++ kvm_run->exit_reason = KVM_EXIT_S390_SIEIC;
++ kvm_run->s390_sieic.icptcode = vcpu->arch.sie_block->icptcode;
++ kvm_run->s390_sieic.mask = vcpu->arch.sie_block->gpsw.mask;
++ kvm_run->s390_sieic.addr = vcpu->arch.sie_block->gpsw.addr;
++ kvm_run->s390_sieic.ipa = vcpu->arch.sie_block->ipa;
++ kvm_run->s390_sieic.ipb = vcpu->arch.sie_block->ipb;
++ rc = 0;
++ }
++
++ if (rc == -EREMOTE) {
++ /* intercept was handled, but userspace support is needed
++ * kvm_run has been prepared by the handler */
++ rc = 0;
++ }
++
++ if (vcpu->sigset_active)
++ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
++
++ vcpu_put(vcpu);
++
++ vcpu->stat.exit_userspace++;
++ return rc;
++}
++
++static int __guestcopy(struct kvm_vcpu *vcpu, u64 guestdest, const void *from,
++ unsigned long n, int prefix)
++{
++ if (prefix)
++ return copy_to_guest(vcpu, guestdest, from, n);
++ else
++ return copy_to_guest_absolute(vcpu, guestdest, from, n);
++}
++
++/*
++ * store status at address
++ * we use have two special cases:
++ * KVM_S390_STORE_STATUS_NOADDR: -> 0x1200 on 64 bit
++ * KVM_S390_STORE_STATUS_PREFIXED: -> prefix
++ */
++int __kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
++{
++ const unsigned char archmode = 1;
++ int prefix;
++
++ if (addr == KVM_S390_STORE_STATUS_NOADDR) {
++ if (copy_to_guest_absolute(vcpu, 163ul, &archmode, 1))
++ return -EFAULT;
++ addr = SAVE_AREA_BASE;
++ prefix = 0;
++ } else if (addr == KVM_S390_STORE_STATUS_PREFIXED) {
++ if (copy_to_guest(vcpu, 163ul, &archmode, 1))
++ return -EFAULT;
++ addr = SAVE_AREA_BASE;
++ prefix = 1;
++ } else
++ prefix = 0;
++
++ if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, fp_regs),
++ vcpu->arch.guest_fpregs.fprs, 128, prefix))
++ return -EFAULT;
++
++ if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, gp_regs),
++ vcpu->arch.guest_gprs, 128, prefix))
++ return -EFAULT;
++
++ if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, psw),
++ &vcpu->arch.sie_block->gpsw, 16, prefix))
++ return -EFAULT;
++
++ if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, pref_reg),
++ &vcpu->arch.sie_block->prefix, 4, prefix))
++ return -EFAULT;
++
++ if (__guestcopy(vcpu,
++ addr + offsetof(struct save_area_s390x, fp_ctrl_reg),
++ &vcpu->arch.guest_fpregs.fpc, 4, prefix))
++ return -EFAULT;
++
++ if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, tod_reg),
++ &vcpu->arch.sie_block->todpr, 4, prefix))
++ return -EFAULT;
++
++ if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, timer),
++ &vcpu->arch.sie_block->cputm, 8, prefix))
++ return -EFAULT;
++
++ if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, clk_cmp),
++ &vcpu->arch.sie_block->ckc, 8, prefix))
++ return -EFAULT;
++
++ if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, acc_regs),
++ &vcpu->arch.guest_acrs, 64, prefix))
++ return -EFAULT;
++
++ if (__guestcopy(vcpu,
++ addr + offsetof(struct save_area_s390x, ctrl_regs),
++ &vcpu->arch.sie_block->gcr, 128, prefix))
++ return -EFAULT;
++ return 0;
++}
++
++static int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
++{
++ int rc;
++
++ vcpu_load(vcpu);
++ rc = __kvm_s390_vcpu_store_status(vcpu, addr);
++ vcpu_put(vcpu);
++ return rc;
++}
++
++long kvm_arch_vcpu_ioctl(struct file *filp,
++ unsigned int ioctl, unsigned long arg)
++{
++ struct kvm_vcpu *vcpu = filp->private_data;
++ void __user *argp = (void __user *)arg;
++
++ switch (ioctl) {
++ case KVM_S390_INTERRUPT: {
++ struct kvm_s390_interrupt s390int;
++
++ if (copy_from_user(&s390int, argp, sizeof(s390int)))
++ return -EFAULT;
++ return kvm_s390_inject_vcpu(vcpu, &s390int);
++ }
++ case KVM_S390_STORE_STATUS:
++ return kvm_s390_vcpu_store_status(vcpu, arg);
++ case KVM_S390_SET_INITIAL_PSW: {
++ psw_t psw;
++
++ if (copy_from_user(&psw, argp, sizeof(psw)))
++ return -EFAULT;
++ return kvm_arch_vcpu_ioctl_set_initial_psw(vcpu, psw);
++ }
++ case KVM_S390_INITIAL_RESET:
++ return kvm_arch_vcpu_ioctl_initial_reset(vcpu);
++ default:
++ ;
++ }
++ return -EINVAL;
++}
++
++/* Section: memory related */
++int kvm_arch_set_memory_region(struct kvm *kvm,
++ struct kvm_userspace_memory_region *mem,
++ struct kvm_memory_slot old,
++ int user_alloc)
++{
++ /* A few sanity checks. We can have exactly one memory slot which has
++ to start at guest virtual zero and which has to be located at a
++ page boundary in userland and which has to end at a page boundary.
++ The memory in userland is ok to be fragmented into various different
++ vmas. It is okay to mmap() and munmap() stuff in this slot after
++ doing this call at any time */
++
++ if (mem->slot)
++ return -EINVAL;
++
++ if (mem->guest_phys_addr)
++ return -EINVAL;
++
++ if (mem->userspace_addr & (PAGE_SIZE - 1))
++ return -EINVAL;
++
++ if (mem->memory_size & (PAGE_SIZE - 1))
++ return -EINVAL;
++
++ kvm->arch.guest_origin = mem->userspace_addr;
++ kvm->arch.guest_memsize = mem->memory_size;
++
++ /* FIXME: we do want to interrupt running CPUs and update their memory
++ configuration now to avoid race conditions. But hey, changing the
++ memory layout while virtual CPUs are running is usually bad
++ programming practice. */
++
++ return 0;
++}
++
++gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
++{
++ return gfn;
++}
++
++static int __init kvm_s390_init(void)
++{
++ return kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE);
++}
++
++static void __exit kvm_s390_exit(void)
++{
++ kvm_exit();
++}
++
++module_init(kvm_s390_init);
++module_exit(kvm_s390_exit);
+diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
+new file mode 100644
+index 0000000..3893cf1
+--- /dev/null
++++ b/arch/s390/kvm/kvm-s390.h
+@@ -0,0 +1,64 @@
++/*
++ * kvm_s390.h - definition for kvm on s390
++ *
++ * Copyright IBM Corp. 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): Carsten Otte <cotte at de.ibm.com>
++ * Christian Borntraeger <borntraeger at de.ibm.com>
++ */
++
++#ifndef ARCH_S390_KVM_S390_H
++#define ARCH_S390_KVM_S390_H
++
++#include <linux/kvm.h>
++#include <linux/kvm_host.h>
++
++typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu);
++
++int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu);
++
++#define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\
++do { \
++ debug_sprintf_event(d_kvm->arch.dbf, d_loglevel, d_string "\n", \
++ d_args); \
++} while (0)
++
++#define VCPU_EVENT(d_vcpu, d_loglevel, d_string, d_args...)\
++do { \
++ debug_sprintf_event(d_vcpu->kvm->arch.dbf, d_loglevel, \
++ "%02d[%016lx-%016lx]: " d_string "\n", d_vcpu->vcpu_id, \
++ d_vcpu->arch.sie_block->gpsw.mask, d_vcpu->arch.sie_block->gpsw.addr,\
++ d_args); \
++} while (0)
++
++static inline int __cpu_is_stopped(struct kvm_vcpu *vcpu)
++{
++ return atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOP_INT;
++}
++
++int kvm_s390_handle_wait(struct kvm_vcpu *vcpu);
++void kvm_s390_idle_wakeup(unsigned long data);
++void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu);
++int kvm_s390_inject_vm(struct kvm *kvm,
++ struct kvm_s390_interrupt *s390int);
++int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
++ struct kvm_s390_interrupt *s390int);
++int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code);
++
++/* implemented in priv.c */
++int kvm_s390_handle_priv(struct kvm_vcpu *vcpu);
++
++/* implemented in sigp.c */
++int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu);
++
++/* implemented in kvm-s390.c */
++int __kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu,
++ unsigned long addr);
++/* implemented in diag.c */
++int kvm_s390_handle_diag(struct kvm_vcpu *vcpu);
++
++#endif
+diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
+new file mode 100644
+index 0000000..c02286c
+--- /dev/null
++++ b/arch/s390/kvm/priv.c
+@@ -0,0 +1,314 @@
++/*
++ * priv.c - handling privileged instructions
++ *
++ * Copyright IBM Corp. 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): Carsten Otte <cotte at de.ibm.com>
++ * Christian Borntraeger <borntraeger at de.ibm.com>
++ */
++
++#include <linux/kvm.h>
++#include <linux/errno.h>
++#include <asm/current.h>
++#include <asm/debug.h>
++#include <asm/ebcdic.h>
++#include <asm/sysinfo.h>
++#include "gaccess.h"
++#include "kvm-s390.h"
++
++static int handle_set_prefix(struct kvm_vcpu *vcpu)
++{
++ int base2 = vcpu->arch.sie_block->ipb >> 28;
++ int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
++ u64 operand2;
++ u32 address = 0;
++ u8 tmp;
++
++ vcpu->stat.instruction_spx++;
++
++ operand2 = disp2;
++ if (base2)
++ operand2 += vcpu->arch.guest_gprs[base2];
++
++ /* must be word boundary */
++ if (operand2 & 3) {
++ kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
++ goto out;
++ }
++
++ /* get the value */
++ if (get_guest_u32(vcpu, operand2, &address)) {
++ kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
++ goto out;
++ }
++
++ address = address & 0x7fffe000u;
++
++ /* make sure that the new value is valid memory */
++ if (copy_from_guest_absolute(vcpu, &tmp, address, 1) ||
++ (copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1))) {
++ kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
++ goto out;
++ }
++
++ vcpu->arch.sie_block->prefix = address;
++ vcpu->arch.sie_block->ihcpu = 0xffff;
++
++ VCPU_EVENT(vcpu, 5, "setting prefix to %x", address);
++out:
++ return 0;
++}
++
++static int handle_store_prefix(struct kvm_vcpu *vcpu)
++{
++ int base2 = vcpu->arch.sie_block->ipb >> 28;
++ int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
++ u64 operand2;
++ u32 address;
++
++ vcpu->stat.instruction_stpx++;
++ operand2 = disp2;
++ if (base2)
++ operand2 += vcpu->arch.guest_gprs[base2];
++
++ /* must be word boundary */
++ if (operand2 & 3) {
++ kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
++ goto out;
++ }
++
++ address = vcpu->arch.sie_block->prefix;
++ address = address & 0x7fffe000u;
++
++ /* get the value */
++ if (put_guest_u32(vcpu, operand2, address)) {
++ kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
++ goto out;
++ }
++
++ VCPU_EVENT(vcpu, 5, "storing prefix to %x", address);
++out:
++ return 0;
++}
++
++static int handle_store_cpu_address(struct kvm_vcpu *vcpu)
++{
++ int base2 = vcpu->arch.sie_block->ipb >> 28;
++ int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
++ u64 useraddr;
++ int rc;
++
++ vcpu->stat.instruction_stap++;
++ useraddr = disp2;
++ if (base2)
++ useraddr += vcpu->arch.guest_gprs[base2];
++
++ if (useraddr & 1) {
++ kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
++ goto out;
++ }
++
++ rc = put_guest_u16(vcpu, useraddr, vcpu->vcpu_id);
++ if (rc == -EFAULT) {
++ kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
++ goto out;
++ }
++
++ VCPU_EVENT(vcpu, 5, "storing cpu address to %lx", useraddr);
++out:
++ return 0;
++}
++
++static int handle_skey(struct kvm_vcpu *vcpu)
++{
++ vcpu->stat.instruction_storage_key++;
++ vcpu->arch.sie_block->gpsw.addr -= 4;
++ VCPU_EVENT(vcpu, 4, "%s", "retrying storage key operation");
++ return 0;
++}
++
++static int handle_stsch(struct kvm_vcpu *vcpu)
++{
++ vcpu->stat.instruction_stsch++;
++ VCPU_EVENT(vcpu, 4, "%s", "store subchannel - CC3");
++ /* condition code 3 */
++ vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
++ vcpu->arch.sie_block->gpsw.mask |= (3 & 3ul) << 44;
++ return 0;
++}
++
++static int handle_chsc(struct kvm_vcpu *vcpu)
++{
++ vcpu->stat.instruction_chsc++;
++ VCPU_EVENT(vcpu, 4, "%s", "channel subsystem call - CC3");
++ /* condition code 3 */
++ vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
++ vcpu->arch.sie_block->gpsw.mask |= (3 & 3ul) << 44;
++ return 0;
++}
++
++static int handle_stfl(struct kvm_vcpu *vcpu)
++{
++ unsigned int facility_list = stfl();
++ int rc;
++
++ vcpu->stat.instruction_stfl++;
++ facility_list &= ~(1UL<<24); /* no stfle */
++
++ rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list),
++ &facility_list, sizeof(facility_list));
++ if (rc == -EFAULT)
++ kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
++ else
++ VCPU_EVENT(vcpu, 5, "store facility list value %x",
++ facility_list);
++ return 0;
++}
++
++static int handle_stidp(struct kvm_vcpu *vcpu)
++{
++ int base2 = vcpu->arch.sie_block->ipb >> 28;
++ int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
++ u64 operand2;
++ int rc;
++
++ vcpu->stat.instruction_stidp++;
++ operand2 = disp2;
++ if (base2)
++ operand2 += vcpu->arch.guest_gprs[base2];
++
++ if (operand2 & 7) {
++ kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
++ goto out;
++ }
++
++ rc = put_guest_u64(vcpu, operand2, vcpu->arch.stidp_data);
++ if (rc == -EFAULT) {
++ kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
++ goto out;
++ }
++
++ VCPU_EVENT(vcpu, 5, "%s", "store cpu id");
++out:
++ return 0;
++}
++
++static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem)
++{
++ struct float_interrupt *fi = &vcpu->kvm->arch.float_int;
++ int cpus = 0;
++ int n;
++
++ spin_lock_bh(&fi->lock);
++ for (n = 0; n < KVM_MAX_VCPUS; n++)
++ if (fi->local_int[n])
++ cpus++;
++ spin_unlock_bh(&fi->lock);
++
++ /* deal with other level 3 hypervisors */
++ if (stsi(mem, 3, 2, 2) == -ENOSYS)
++ mem->count = 0;
++ if (mem->count < 8)
++ mem->count++;
++ for (n = mem->count - 1; n > 0 ; n--)
++ memcpy(&mem->vm[n], &mem->vm[n - 1], sizeof(mem->vm[0]));
++
++ mem->vm[0].cpus_total = cpus;
++ mem->vm[0].cpus_configured = cpus;
++ mem->vm[0].cpus_standby = 0;
++ mem->vm[0].cpus_reserved = 0;
++ mem->vm[0].caf = 1000;
++ memcpy(mem->vm[0].name, "KVMguest", 8);
++ ASCEBC(mem->vm[0].name, 8);
++ memcpy(mem->vm[0].cpi, "KVM/Linux ", 16);
++ ASCEBC(mem->vm[0].cpi, 16);
++}
++
++static int handle_stsi(struct kvm_vcpu *vcpu)
++{
++ int fc = (vcpu->arch.guest_gprs[0] & 0xf0000000) >> 28;
++ int sel1 = vcpu->arch.guest_gprs[0] & 0xff;
++ int sel2 = vcpu->arch.guest_gprs[1] & 0xffff;
++ int base2 = vcpu->arch.sie_block->ipb >> 28;
++ int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
++ u64 operand2;
++ unsigned long mem;
++
++ vcpu->stat.instruction_stsi++;
++ VCPU_EVENT(vcpu, 4, "stsi: fc: %x sel1: %x sel2: %x", fc, sel1, sel2);
++
++ operand2 = disp2;
++ if (base2)
++ operand2 += vcpu->arch.guest_gprs[base2];
++
++ if (operand2 & 0xfff && fc > 0)
++ return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
++
++ switch (fc) {
++ case 0:
++ vcpu->arch.guest_gprs[0] = 3 << 28;
++ vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
++ return 0;
++ case 1: /* same handling for 1 and 2 */
++ case 2:
++ mem = get_zeroed_page(GFP_KERNEL);
++ if (!mem)
++ goto out_fail;
++ if (stsi((void *) mem, fc, sel1, sel2) == -ENOSYS)
++ goto out_mem;
++ break;
++ case 3:
++ if (sel1 != 2 || sel2 != 2)
++ goto out_fail;
++ mem = get_zeroed_page(GFP_KERNEL);
++ if (!mem)
++ goto out_fail;
++ handle_stsi_3_2_2(vcpu, (void *) mem);
++ break;
++ default:
++ goto out_fail;
++ }
++
++ if (copy_to_guest_absolute(vcpu, operand2, (void *) mem, PAGE_SIZE)) {
++ kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
++ goto out_mem;
++ }
++ free_page(mem);
++ vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
++ vcpu->arch.guest_gprs[0] = 0;
++ return 0;
++out_mem:
++ free_page(mem);
++out_fail:
++ /* condition code 3 */
++ vcpu->arch.sie_block->gpsw.mask |= 3ul << 44;
++ return 0;
++}
++
++static intercept_handler_t priv_handlers[256] = {
++ [0x02] = handle_stidp,
++ [0x10] = handle_set_prefix,
++ [0x11] = handle_store_prefix,
++ [0x12] = handle_store_cpu_address,
++ [0x29] = handle_skey,
++ [0x2a] = handle_skey,
++ [0x2b] = handle_skey,
++ [0x34] = handle_stsch,
++ [0x5f] = handle_chsc,
++ [0x7d] = handle_stsi,
++ [0xb1] = handle_stfl,
++};
++
++int kvm_s390_handle_priv(struct kvm_vcpu *vcpu)
++{
++ intercept_handler_t handler;
++
++ handler = priv_handlers[vcpu->arch.sie_block->ipa & 0x00ff];
++ if (handler)
++ return handler(vcpu);
++ return -ENOTSUPP;
++}
+diff --git a/arch/s390/kvm/sie64a.S b/arch/s390/kvm/sie64a.S
+new file mode 100644
+index 0000000..934fd6a
+--- /dev/null
++++ b/arch/s390/kvm/sie64a.S
+@@ -0,0 +1,47 @@
++/*
++ * sie64a.S - low level sie call
++ *
++ * Copyright IBM Corp. 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): Heiko Carstens <heiko.carstens at de.ibm.com>
++ */
++
++#include <linux/errno.h>
++#include <asm/asm-offsets.h>
++
++SP_R5 = 5 * 8 # offset into stackframe
++SP_R6 = 6 * 8
++
++/*
++ * sie64a calling convention:
++ * %r2 pointer to sie control block
++ * %r3 guest register save area
++ */
++ .globl sie64a
++sie64a:
++ lgr %r5,%r3
++ stmg %r5,%r14,SP_R5(%r15) # save register on entry
++ lgr %r14,%r2 # pointer to sie control block
++ lmg %r0,%r13,0(%r3) # load guest gprs 0-13
++sie_inst:
++ sie 0(%r14)
++ lg %r14,SP_R5(%r15)
++ stmg %r0,%r13,0(%r14) # save guest gprs 0-13
++ lghi %r2,0
++ lmg %r6,%r14,SP_R6(%r15)
++ br %r14
++
++sie_err:
++ lg %r14,SP_R5(%r15)
++ stmg %r0,%r13,0(%r14) # save guest gprs 0-13
++ lghi %r2,-EFAULT
++ lmg %r6,%r14,SP_R6(%r15)
++ br %r14
++
++ .section __ex_table,"a"
++ .quad sie_inst,sie_err
++ .previous
+diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
+new file mode 100644
+index 0000000..0a236ac
+--- /dev/null
++++ b/arch/s390/kvm/sigp.c
+@@ -0,0 +1,288 @@
++/*
++ * sigp.c - handlinge interprocessor communication
++ *
++ * Copyright IBM Corp. 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): Carsten Otte <cotte at de.ibm.com>
++ * Christian Borntraeger <borntraeger at de.ibm.com>
++ */
++
++#include <linux/kvm.h>
++#include <linux/kvm_host.h>
++#include "gaccess.h"
++#include "kvm-s390.h"
++
++/* sigp order codes */
++#define SIGP_SENSE 0x01
++#define SIGP_EXTERNAL_CALL 0x02
++#define SIGP_EMERGENCY 0x03
++#define SIGP_START 0x04
++#define SIGP_STOP 0x05
++#define SIGP_RESTART 0x06
++#define SIGP_STOP_STORE_STATUS 0x09
++#define SIGP_INITIAL_CPU_RESET 0x0b
++#define SIGP_CPU_RESET 0x0c
++#define SIGP_SET_PREFIX 0x0d
++#define SIGP_STORE_STATUS_ADDR 0x0e
++#define SIGP_SET_ARCH 0x12
++
++/* cpu status bits */
++#define SIGP_STAT_EQUIPMENT_CHECK 0x80000000UL
++#define SIGP_STAT_INCORRECT_STATE 0x00000200UL
++#define SIGP_STAT_INVALID_PARAMETER 0x00000100UL
++#define SIGP_STAT_EXT_CALL_PENDING 0x00000080UL
++#define SIGP_STAT_STOPPED 0x00000040UL
++#define SIGP_STAT_OPERATOR_INTERV 0x00000020UL
++#define SIGP_STAT_CHECK_STOP 0x00000010UL
++#define SIGP_STAT_INOPERATIVE 0x00000004UL
++#define SIGP_STAT_INVALID_ORDER 0x00000002UL
++#define SIGP_STAT_RECEIVER_CHECK 0x00000001UL
++
++
++static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr, u64 *reg)
++{
++ struct float_interrupt *fi = &vcpu->kvm->arch.float_int;
++ int rc;
++
++ if (cpu_addr >= KVM_MAX_VCPUS)
++ return 3; /* not operational */
++
++ spin_lock_bh(&fi->lock);
++ if (fi->local_int[cpu_addr] == NULL)
++ rc = 3; /* not operational */
++ else if (atomic_read(fi->local_int[cpu_addr]->cpuflags)
++ & CPUSTAT_RUNNING) {
++ *reg &= 0xffffffff00000000UL;
++ rc = 1; /* status stored */
++ } else {
++ *reg &= 0xffffffff00000000UL;
++ *reg |= SIGP_STAT_STOPPED;
++ rc = 1; /* status stored */
++ }
++ spin_unlock_bh(&fi->lock);
++
++ VCPU_EVENT(vcpu, 4, "sensed status of cpu %x rc %x", cpu_addr, rc);
++ return rc;
++}
++
++static int __sigp_emergency(struct kvm_vcpu *vcpu, u16 cpu_addr)
+{
-+ struct tl_info *info = tl_info;
-+ struct sys_device *sysdev;
-+ int cpu;
++ struct float_interrupt *fi = &vcpu->kvm->arch.float_int;
++ struct local_interrupt *li;
++ struct interrupt_info *inti;
++ int rc;
+
-+ 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);
++ if (cpu_addr >= KVM_MAX_VCPUS)
++ return 3; /* not operational */
++
++ inti = kzalloc(sizeof(*inti), GFP_KERNEL);
++ if (!inti)
++ return -ENOMEM;
++
++ inti->type = KVM_S390_INT_EMERGENCY;
++
++ spin_lock_bh(&fi->lock);
++ li = fi->local_int[cpu_addr];
++ if (li == NULL) {
++ rc = 3; /* not operational */
++ kfree(inti);
++ goto unlock;
+ }
++ spin_lock_bh(&li->lock);
++ list_add_tail(&inti->list, &li->list);
++ atomic_set(&li->active, 1);
++ atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
++ if (waitqueue_active(&li->wq))
++ wake_up_interruptible(&li->wq);
++ spin_unlock_bh(&li->lock);
++ rc = 0; /* order accepted */
++unlock:
++ spin_unlock_bh(&fi->lock);
++ VCPU_EVENT(vcpu, 4, "sent sigp emerg to cpu %x", cpu_addr);
++ return rc;
+}
+
-+static void topology_work_fn(struct work_struct *work)
++static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int store)
+{
-+ arch_reinit_sched_domains();
-+}
++ struct float_interrupt *fi = &vcpu->kvm->arch.float_int;
++ struct local_interrupt *li;
++ struct interrupt_info *inti;
++ int rc;
+
-+void topology_schedule_update(void)
-+{
-+ schedule_work(&topology_work);
-+}
++ if (cpu_addr >= KVM_MAX_VCPUS)
++ return 3; /* not operational */
+
-+static void topology_timer_fn(unsigned long ignored)
-+{
-+ if (ptf(PTF_CHECK))
-+ topology_schedule_update();
-+ set_topology_timer();
-+}
++ inti = kzalloc(sizeof(*inti), GFP_KERNEL);
++ if (!inti)
++ return -ENOMEM;
+
-+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);
-+}
++ inti->type = KVM_S390_SIGP_STOP;
+
-+static void topology_interrupt(__u16 code)
-+{
-+ schedule_work(&topology_work);
++ spin_lock_bh(&fi->lock);
++ li = fi->local_int[cpu_addr];
++ if (li == NULL) {
++ rc = 3; /* not operational */
++ kfree(inti);
++ goto unlock;
++ }
++ spin_lock_bh(&li->lock);
++ list_add_tail(&inti->list, &li->list);
++ atomic_set(&li->active, 1);
++ atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags);
++ if (store)
++ li->action_bits |= ACTION_STORE_ON_STOP;
++ li->action_bits |= ACTION_STOP_ON_STOP;
++ if (waitqueue_active(&li->wq))
++ wake_up_interruptible(&li->wq);
++ spin_unlock_bh(&li->lock);
++ rc = 0; /* order accepted */
++unlock:
++ spin_unlock_bh(&fi->lock);
++ VCPU_EVENT(vcpu, 4, "sent sigp stop to cpu %x", cpu_addr);
++ return rc;
+}
+
-+static int __init init_topology_update(void)
++static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter)
+{
+ 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);
++ switch (parameter & 0xff) {
++ case 0:
++ printk(KERN_WARNING "kvm: request to switch to ESA/390 mode"
++ " not supported");
++ rc = 3; /* not operational */
++ break;
++ case 1:
++ case 2:
++ rc = 0; /* order accepted */
++ break;
++ default:
++ rc = -ENOTSUPP;
+ }
-+ else
-+ set_topology_timer();
-+ return 0;
++ return rc;
+}
-+__initcall(init_topology_update);
+
-+void __init s390_init_cpu_topology(void)
++static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
++ u64 *reg)
+{
-+ 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;
++ struct float_interrupt *fi = &vcpu->kvm->arch.float_int;
++ struct local_interrupt *li;
++ struct interrupt_info *inti;
++ int rc;
++ u8 tmp;
+
-+ if (facility_bits & (1ULL << 51))
-+ machine_has_topology_irq = 1;
++ /* make sure that the new value is valid memory */
++ address = address & 0x7fffe000u;
++ if ((copy_from_guest(vcpu, &tmp,
++ (u64) (address + vcpu->kvm->arch.guest_origin) , 1)) ||
++ (copy_from_guest(vcpu, &tmp, (u64) (address +
++ vcpu->kvm->arch.guest_origin + PAGE_SIZE), 1))) {
++ *reg |= SIGP_STAT_INVALID_PARAMETER;
++ return 1; /* invalid parameter */
++ }
++
++ inti = kzalloc(sizeof(*inti), GFP_KERNEL);
++ if (!inti)
++ return 2; /* busy */
++
++ spin_lock_bh(&fi->lock);
++ li = fi->local_int[cpu_addr];
++
++ if ((cpu_addr >= KVM_MAX_VCPUS) || (li == NULL)) {
++ rc = 1; /* incorrect state */
++ *reg &= SIGP_STAT_INCORRECT_STATE;
++ kfree(inti);
++ goto out_fi;
++ }
++
++ spin_lock_bh(&li->lock);
++ /* cpu must be in stopped state */
++ if (atomic_read(li->cpuflags) & CPUSTAT_RUNNING) {
++ rc = 1; /* incorrect state */
++ *reg &= SIGP_STAT_INCORRECT_STATE;
++ kfree(inti);
++ goto out_li;
++ }
++
++ inti->type = KVM_S390_SIGP_SET_PREFIX;
++ inti->prefix.address = address;
++
++ list_add_tail(&inti->list, &li->list);
++ atomic_set(&li->active, 1);
++ if (waitqueue_active(&li->wq))
++ wake_up_interruptible(&li->wq);
++ rc = 0; /* order accepted */
++
++ VCPU_EVENT(vcpu, 4, "set prefix of cpu %02x to %x", cpu_addr, address);
++out_li:
++ spin_unlock_bh(&li->lock);
++out_fi:
++ spin_unlock_bh(&fi->lock);
++ return rc;
++}
+
-+ tl_info = alloc_bootmem_pages(PAGE_SIZE);
-+ if (!tl_info)
-+ goto error;
-+ info = tl_info;
-+ stsi(info, 15, 1, 2);
++int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
++{
++ int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
++ int r3 = vcpu->arch.sie_block->ipa & 0x000f;
++ int base2 = vcpu->arch.sie_block->ipb >> 28;
++ int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
++ u32 parameter;
++ u16 cpu_addr = vcpu->arch.guest_gprs[r3];
++ u8 order_code;
++ int rc;
+
-+ nr_cores = info->mag[NR_MAG - 2];
-+ for (i = 0; i < info->mnest - 2; i++)
-+ nr_cores *= info->mag[NR_MAG - 3 - i];
++ order_code = disp2;
++ if (base2)
++ order_code += vcpu->arch.guest_gprs[base2];
+
-+ printk(KERN_INFO "CPU topology:");
-+ for (i = 0; i < NR_MAG; i++)
-+ printk(" %d", info->mag[i]);
-+ printk(" / %d\n", info->mnest);
++ if (r1 % 2)
++ parameter = vcpu->arch.guest_gprs[r1];
++ else
++ parameter = vcpu->arch.guest_gprs[r1 + 1];
+
-+ 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;
++ switch (order_code) {
++ case SIGP_SENSE:
++ vcpu->stat.instruction_sigp_sense++;
++ rc = __sigp_sense(vcpu, cpu_addr,
++ &vcpu->arch.guest_gprs[r1]);
++ break;
++ case SIGP_EMERGENCY:
++ vcpu->stat.instruction_sigp_emergency++;
++ rc = __sigp_emergency(vcpu, cpu_addr);
++ break;
++ case SIGP_STOP:
++ vcpu->stat.instruction_sigp_stop++;
++ rc = __sigp_stop(vcpu, cpu_addr, 0);
++ break;
++ case SIGP_STOP_STORE_STATUS:
++ vcpu->stat.instruction_sigp_stop++;
++ rc = __sigp_stop(vcpu, cpu_addr, 1);
++ break;
++ case SIGP_SET_ARCH:
++ vcpu->stat.instruction_sigp_arch++;
++ rc = __sigp_set_arch(vcpu, parameter);
++ break;
++ case SIGP_SET_PREFIX:
++ vcpu->stat.instruction_sigp_prefix++;
++ rc = __sigp_set_prefix(vcpu, cpu_addr, parameter,
++ &vcpu->arch.guest_gprs[r1]);
++ break;
++ case SIGP_RESTART:
++ vcpu->stat.instruction_sigp_restart++;
++ /* user space must know about restart */
++ default:
++ return -ENOTSUPP;
+ }
-+ return;
-+error:
-+ machine_has_topology = 0;
-+ machine_has_topology_irq = 0;
++
++ if (rc < 0)
++ return rc;
++
++ vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
++ vcpu->arch.sie_block->gpsw.mask |= (rc & 3ul) << 44;
++ return 0;
+}
-diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
-index 60f728a..57b607b 100644
---- a/arch/s390/kernel/traps.c
-+++ b/arch/s390/kernel/traps.c
-@@ -42,11 +42,8 @@
- #include <asm/s390_ext.h>
- #include <asm/lowcore.h>
- #include <asm/debug.h>
-+#include "entry.h"
+diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
+index 5208443..ab6735d 100644
+--- a/arch/s390/lib/Makefile
++++ b/arch/s390/lib/Makefile
+@@ -2,8 +2,6 @@
+ # Makefile for s390-specific library files..
+ #
--/* Called from entry.S only */
--extern void handle_per_exception(struct pt_regs *regs);
+-EXTRA_AFLAGS := -traditional
-
--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();
- }
+ lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
+ obj-$(CONFIG_32BIT) += div64.o qrnnd.o
+ lib-$(CONFIG_64BIT) += uaccess_mvcos.o
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index 70f2a86..eae21a8 100644
--- a/arch/s390/lib/delay.c
@@ -214164,6 +262687,26 @@
+ set_clock_comparator(S390_lowcore.clock_comparator);
local_irq_restore(flags);
}
+diff --git a/arch/s390/lib/uaccess_mvcos.c b/arch/s390/lib/uaccess_mvcos.c
+index 6d87723..3f15aaf 100644
+--- a/arch/s390/lib/uaccess_mvcos.c
++++ b/arch/s390/lib/uaccess_mvcos.c
+@@ -162,6 +162,7 @@ static size_t clear_user_mvcos(size_t size, void __user *to)
+ return size;
+ }
+
++#ifdef CONFIG_S390_SWITCH_AMODE
+ static size_t strnlen_user_mvcos(size_t count, const char __user *src)
+ {
+ char buf[256];
+@@ -199,6 +200,7 @@ static size_t strncpy_from_user_mvcos(size_t count, const char __user *src,
+ } while ((len_str == len) && (done < count));
+ return done;
+ }
++#endif /* CONFIG_S390_SWITCH_AMODE */
+
+ struct uaccess_ops uaccess_mvcos = {
+ .copy_from_user = copy_from_user_mvcos_check,
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
@@ -214267,13 +262810,35 @@
put_page(virt_to_page(uaddr));
return ret;
}
+diff --git a/arch/s390/math-emu/Makefile b/arch/s390/math-emu/Makefile
+index 73b3e72..c848903 100644
+--- a/arch/s390/math-emu/Makefile
++++ b/arch/s390/math-emu/Makefile
+@@ -5,4 +5,3 @@
+ obj-$(CONFIG_MATHEMU) := math.o
+
+ EXTRA_CFLAGS := -I$(src) -Iinclude/math-emu -w
+-EXTRA_AFLAGS := -traditional
+diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile
+index 6640193..fb988a4 100644
+--- a/arch/s390/mm/Makefile
++++ b/arch/s390/mm/Makefile
+@@ -4,4 +4,4 @@
+
+ obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o
+ obj-$(CONFIG_CMM) += cmm.o
+-
++obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
-index 880b0eb..ed2af0a 100644
+index 880b0eb..f231f5e 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
+@@ -287,24 +287,10 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
+ if (rc < 0)
+ goto out_free;
- rc = add_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
+- rc = add_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
++ rc = vmem_add_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
- switch (rc) {
- case 0:
@@ -214295,6 +262860,33 @@
seg->res = kzalloc(sizeof(struct resource), GFP_KERNEL);
if (seg->res == NULL) {
+@@ -365,7 +351,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
+ release_resource(seg->res);
+ kfree(seg->res);
+ out_shared:
+- remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
++ vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
+ out_free:
+ kfree(seg);
+ out:
+@@ -488,7 +474,7 @@ segment_modify_shared (char *name, int do_nonshared)
+ rc = 0;
+ goto out_unlock;
+ out_del:
+- remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
++ vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
+ list_del(&seg->list);
+ dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
+ kfree(seg);
+@@ -522,7 +508,7 @@ segment_unload(char *name)
+ goto out_unlock;
+ release_resource(seg->res);
+ kfree(seg->res);
+- remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
++ vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
+ list_del(&seg->list);
+ dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
+ kfree(seg);
@@ -582,8 +568,59 @@ out:
mutex_unlock(&dcss_lock);
}
@@ -214356,14 +262948,15 @@
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
+index ed13d42..4d53720 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
-@@ -28,11 +28,11 @@
+@@ -28,11 +28,12 @@
#include <linux/hardirq.h>
#include <linux/kprobes.h>
#include <linux/uaccess.h>
-
++#include <linux/hugetlb.h>
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/s390_ext.h>
@@ -214372,7 +262965,7 @@
#ifndef CONFIG_64BIT
#define __FAIL_ADDR_MASK 0x7ffff000
-@@ -50,8 +50,6 @@
+@@ -50,8 +51,6 @@
extern int sysctl_userprocess_debug;
#endif
@@ -214381,7 +262974,7 @@
#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,
+@@ -245,11 +244,6 @@ static void do_sigbus(struct pt_regs *regs, unsigned long error_code,
}
#ifdef CONFIG_S390_EXEC_PROTECT
@@ -214393,7 +262986,7 @@
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,
+@@ -270,15 +264,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)
@@ -214413,7 +263006,16 @@
else {
current->thread.prot_addr = address;
current->thread.trap_no = error_code;
-@@ -424,7 +417,7 @@ no_context:
+@@ -374,6 +368,8 @@ good_area:
+ }
+
+ survive:
++ if (is_vm_hugetlb_page(vma))
++ address &= HPAGE_MASK;
+ /*
+ * If for any reason at all we couldn't handle the fault,
+ * make sure we exit gracefully rather than endlessly redo
+@@ -424,7 +420,7 @@ no_context:
}
void __kprobes do_protection_exception(struct pt_regs *regs,
@@ -214422,7 +263024,7 @@
{
/* 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,
+@@ -440,7 +436,7 @@ void __kprobes do_protection_exception(struct pt_regs *regs,
do_exception(regs, 4, 1);
}
@@ -214431,8 +263033,148 @@
{
do_exception(regs, error_code & 0xff, 0);
}
+diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
+new file mode 100644
+index 0000000..f4b6124
+--- /dev/null
++++ b/arch/s390/mm/hugetlbpage.c
+@@ -0,0 +1,134 @@
++/*
++ * IBM System z Huge TLB Page Support for Kernel.
++ *
++ * Copyright 2007 IBM Corp.
++ * Author(s): Gerald Schaefer <gerald.schaefer at de.ibm.com>
++ */
++
++#include <linux/mm.h>
++#include <linux/hugetlb.h>
++
++
++void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
++ pte_t *pteptr, pte_t pteval)
++{
++ pmd_t *pmdp = (pmd_t *) pteptr;
++ pte_t shadow_pteval = pteval;
++ unsigned long mask;
++
++ if (!MACHINE_HAS_HPAGE) {
++ pteptr = (pte_t *) pte_page(pteval)[1].index;
++ mask = pte_val(pteval) &
++ (_SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO);
++ pte_val(pteval) = (_SEGMENT_ENTRY + __pa(pteptr)) | mask;
++ if (mm->context.noexec) {
++ pteptr += PTRS_PER_PTE;
++ pte_val(shadow_pteval) =
++ (_SEGMENT_ENTRY + __pa(pteptr)) | mask;
++ }
++ }
++
++ pmd_val(*pmdp) = pte_val(pteval);
++ if (mm->context.noexec) {
++ pmdp = get_shadow_table(pmdp);
++ pmd_val(*pmdp) = pte_val(shadow_pteval);
++ }
++}
++
++int arch_prepare_hugepage(struct page *page)
++{
++ unsigned long addr = page_to_phys(page);
++ pte_t pte;
++ pte_t *ptep;
++ int i;
++
++ if (MACHINE_HAS_HPAGE)
++ return 0;
++
++ ptep = (pte_t *) pte_alloc_one(&init_mm, address);
++ if (!ptep)
++ return -ENOMEM;
++
++ pte = mk_pte(page, PAGE_RW);
++ for (i = 0; i < PTRS_PER_PTE; i++) {
++ set_pte_at(&init_mm, addr + i * PAGE_SIZE, ptep + i, pte);
++ pte_val(pte) += PAGE_SIZE;
++ }
++ page[1].index = (unsigned long) ptep;
++ return 0;
++}
++
++void arch_release_hugepage(struct page *page)
++{
++ pte_t *ptep;
++
++ if (MACHINE_HAS_HPAGE)
++ return;
++
++ ptep = (pte_t *) page[1].index;
++ if (!ptep)
++ return;
++ pte_free(&init_mm, ptep);
++ page[1].index = 0;
++}
++
++pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
++{
++ pgd_t *pgdp;
++ pud_t *pudp;
++ pmd_t *pmdp = NULL;
++
++ pgdp = pgd_offset(mm, addr);
++ pudp = pud_alloc(mm, pgdp, addr);
++ if (pudp)
++ pmdp = pmd_alloc(mm, pudp, addr);
++ return (pte_t *) pmdp;
++}
++
++pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
++{
++ pgd_t *pgdp;
++ pud_t *pudp;
++ pmd_t *pmdp = NULL;
++
++ pgdp = pgd_offset(mm, addr);
++ if (pgd_present(*pgdp)) {
++ pudp = pud_offset(pgdp, addr);
++ if (pud_present(*pudp))
++ pmdp = pmd_offset(pudp, addr);
++ }
++ return (pte_t *) pmdp;
++}
++
++int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
++{
++ return 0;
++}
++
++struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
++ int write)
++{
++ return ERR_PTR(-EINVAL);
++}
++
++int pmd_huge(pmd_t pmd)
++{
++ if (!MACHINE_HAS_HPAGE)
++ return 0;
++
++ return !!(pmd_val(pmd) & _SEGMENT_ENTRY_LARGE);
++}
++
++struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
++ pmd_t *pmdp, int write)
++{
++ struct page *page;
++
++ if (!MACHINE_HAS_HPAGE)
++ return NULL;
++
++ page = pmd_page(*pmdp);
++ if (page)
++ page += ((address & ~HPAGE_MASK) >> PAGE_SHIFT);
++ return page;
++}
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
-index 8053245..202c952 100644
+index 8053245..fa31de6 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -50,7 +50,6 @@ void show_mem(void)
@@ -214443,6 +263185,418 @@
i = max_mapnr;
while (i-- > 0) {
if (!pfn_valid(i))
+@@ -78,28 +77,6 @@ void show_mem(void)
+ printk("%lu pages pagetables\n", global_page_state(NR_PAGETABLE));
+ }
+
+-static void __init setup_ro_region(void)
+-{
+- pgd_t *pgd;
+- pud_t *pud;
+- pmd_t *pmd;
+- pte_t *pte;
+- pte_t new_pte;
+- unsigned long address, end;
+-
+- address = ((unsigned long)&_stext) & PAGE_MASK;
+- end = PFN_ALIGN((unsigned long)&_eshared);
+-
+- for (; address < end; address += PAGE_SIZE) {
+- pgd = pgd_offset_k(address);
+- pud = pud_offset(pgd, address);
+- pmd = pmd_offset(pud, address);
+- pte = pte_offset_kernel(pmd, address);
+- new_pte = mk_pte_phys(address, __pgprot(_PAGE_RO));
+- *pte = new_pte;
+- }
+-}
+-
+ /*
+ * paging_init() sets up the page tables
+ */
+@@ -122,7 +99,6 @@ void __init paging_init(void)
+ clear_table((unsigned long *) init_mm.pgd, pgd_type,
+ sizeof(unsigned long)*2048);
+ vmem_map_init();
+- setup_ro_region();
+
+ /* enable virtual mapping in kernel mode */
+ __ctl_load(S390_lowcore.kernel_asce, 1, 1);
+@@ -130,6 +106,8 @@ void __init paging_init(void)
+ __ctl_load(S390_lowcore.kernel_asce, 13, 13);
+ __raw_local_irq_ssm(ssm_mask);
+
++ sparse_memory_present_with_active_regions(MAX_NUMNODES);
++ sparse_init();
+ memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+ #ifdef CONFIG_ZONE_DMA
+ max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS);
+diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
+index fd07201..5c1aea9 100644
+--- a/arch/s390/mm/pgtable.c
++++ b/arch/s390/mm/pgtable.c
+@@ -30,11 +30,27 @@
+ #define TABLES_PER_PAGE 4
+ #define FRAG_MASK 15UL
+ #define SECOND_HALVES 10UL
++
++void clear_table_pgstes(unsigned long *table)
++{
++ clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE/4);
++ memset(table + 256, 0, PAGE_SIZE/4);
++ clear_table(table + 512, _PAGE_TYPE_EMPTY, PAGE_SIZE/4);
++ memset(table + 768, 0, PAGE_SIZE/4);
++}
++
+ #else
+ #define ALLOC_ORDER 2
+ #define TABLES_PER_PAGE 2
+ #define FRAG_MASK 3UL
+ #define SECOND_HALVES 2UL
++
++void clear_table_pgstes(unsigned long *table)
++{
++ clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE/2);
++ memset(table + 256, 0, PAGE_SIZE/2);
++}
++
+ #endif
+
+ unsigned long *crst_table_alloc(struct mm_struct *mm, int noexec)
+@@ -153,7 +169,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
+ unsigned long *table;
+ unsigned long bits;
+
+- bits = mm->context.noexec ? 3UL : 1UL;
++ bits = (mm->context.noexec || mm->context.pgstes) ? 3UL : 1UL;
+ spin_lock(&mm->page_table_lock);
+ page = NULL;
+ if (!list_empty(&mm->context.pgtable_list)) {
+@@ -170,7 +186,10 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
+ pgtable_page_ctor(page);
+ page->flags &= ~FRAG_MASK;
+ table = (unsigned long *) page_to_phys(page);
+- clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
++ if (mm->context.pgstes)
++ clear_table_pgstes(table);
++ else
++ clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
+ spin_lock(&mm->page_table_lock);
+ list_add(&page->lru, &mm->context.pgtable_list);
+ }
+@@ -191,7 +210,7 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
+ struct page *page;
+ unsigned long bits;
+
+- bits = mm->context.noexec ? 3UL : 1UL;
++ bits = (mm->context.noexec || mm->context.pgstes) ? 3UL : 1UL;
+ bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long);
+ page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+ spin_lock(&mm->page_table_lock);
+@@ -228,3 +247,43 @@ void disable_noexec(struct mm_struct *mm, struct task_struct *tsk)
+ mm->context.noexec = 0;
+ update_mm(mm, tsk);
+ }
++
++/*
++ * switch on pgstes for its userspace process (for kvm)
++ */
++int s390_enable_sie(void)
++{
++ struct task_struct *tsk = current;
++ struct mm_struct *mm;
++ int rc;
++
++ task_lock(tsk);
++
++ rc = 0;
++ if (tsk->mm->context.pgstes)
++ goto unlock;
++
++ rc = -EINVAL;
++ if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 ||
++ tsk->mm != tsk->active_mm || tsk->mm->ioctx_list)
++ goto unlock;
++
++ tsk->mm->context.pgstes = 1; /* dirty little tricks .. */
++ mm = dup_mm(tsk);
++ tsk->mm->context.pgstes = 0;
++
++ rc = -ENOMEM;
++ if (!mm)
++ goto unlock;
++ mmput(tsk->mm);
++ tsk->mm = tsk->active_mm = mm;
++ preempt_disable();
++ update_mm(mm, tsk);
++ cpu_set(smp_processor_id(), mm->cpu_vm_mask);
++ preempt_enable();
++ rc = 0;
++unlock:
++ task_unlock(tsk);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(s390_enable_sie);
+diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
+index 35d90a4..beccacf 100644
+--- a/arch/s390/mm/vmem.c
++++ b/arch/s390/mm/vmem.c
+@@ -10,10 +10,12 @@
+ #include <linux/mm.h>
+ #include <linux/module.h>
+ #include <linux/list.h>
++#include <linux/hugetlb.h>
+ #include <asm/pgalloc.h>
+ #include <asm/pgtable.h>
+ #include <asm/setup.h>
+ #include <asm/tlbflush.h>
++#include <asm/sections.h>
+
+ static DEFINE_MUTEX(vmem_mutex);
+
+@@ -25,43 +27,6 @@ struct memory_segment {
+
+ static LIST_HEAD(mem_segs);
+
+-void __meminit memmap_init(unsigned long size, int nid, unsigned long zone,
+- unsigned long start_pfn)
+-{
+- struct page *start, *end;
+- struct page *map_start, *map_end;
+- int i;
+-
+- start = pfn_to_page(start_pfn);
+- end = start + size;
+-
+- for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
+- unsigned long cstart, cend;
+-
+- cstart = PFN_DOWN(memory_chunk[i].addr);
+- cend = cstart + PFN_DOWN(memory_chunk[i].size);
+-
+- map_start = mem_map + cstart;
+- map_end = mem_map + cend;
+-
+- if (map_start < start)
+- map_start = start;
+- if (map_end > end)
+- map_end = end;
+-
+- map_start -= ((unsigned long) map_start & (PAGE_SIZE - 1))
+- / sizeof(struct page);
+- map_end += ((PFN_ALIGN((unsigned long) map_end)
+- - (unsigned long) map_end)
+- / sizeof(struct page));
+-
+- if (map_start < map_end)
+- memmap_init_zone((unsigned long)(map_end - map_start),
+- nid, zone, page_to_pfn(map_start),
+- MEMMAP_EARLY);
+- }
+-}
+-
+ static void __ref *vmem_alloc_pages(unsigned int order)
+ {
+ if (slab_is_available())
+@@ -77,8 +42,7 @@ static inline pud_t *vmem_pud_alloc(void)
+ pud = vmem_alloc_pages(2);
+ if (!pud)
+ return NULL;
+- pud_val(*pud) = _REGION3_ENTRY_EMPTY;
+- memcpy(pud + 1, pud, (PTRS_PER_PUD - 1)*sizeof(pud_t));
++ clear_table((unsigned long *) pud, _REGION3_ENTRY_EMPTY, PAGE_SIZE * 4);
+ #endif
+ return pud;
+ }
+@@ -91,7 +55,7 @@ static inline pmd_t *vmem_pmd_alloc(void)
+ pmd = vmem_alloc_pages(2);
+ if (!pmd)
+ return NULL;
+- clear_table((unsigned long *) pmd, _SEGMENT_ENTRY_EMPTY, PAGE_SIZE*4);
++ clear_table((unsigned long *) pmd, _SEGMENT_ENTRY_EMPTY, PAGE_SIZE * 4);
+ #endif
+ return pmd;
+ }
+@@ -114,7 +78,7 @@ static pte_t __init_refok *vmem_pte_alloc(void)
+ /*
+ * Add a physical memory range to the 1:1 mapping.
+ */
+-static int vmem_add_range(unsigned long start, unsigned long size)
++static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
+ {
+ unsigned long address;
+ pgd_t *pg_dir;
+@@ -141,7 +105,19 @@ static int vmem_add_range(unsigned long start, unsigned long size)
+ pud_populate_kernel(&init_mm, pu_dir, pm_dir);
+ }
+
++ pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0));
+ pm_dir = pmd_offset(pu_dir, address);
++
++#ifdef __s390x__
++ if (MACHINE_HAS_HPAGE && !(address & ~HPAGE_MASK) &&
++ (address + HPAGE_SIZE <= start + size) &&
++ (address >= HPAGE_SIZE)) {
++ pte_val(pte) |= _SEGMENT_ENTRY_LARGE;
++ pmd_val(*pm_dir) = pte_val(pte);
++ address += HPAGE_SIZE - PAGE_SIZE;
++ continue;
++ }
++#endif
+ if (pmd_none(*pm_dir)) {
+ pt_dir = vmem_pte_alloc();
+ if (!pt_dir)
+@@ -150,7 +126,6 @@ static int vmem_add_range(unsigned long start, unsigned long size)
+ }
+
+ pt_dir = pte_offset_kernel(pm_dir, address);
+- pte = pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL);
+ *pt_dir = pte;
+ }
+ ret = 0;
+@@ -181,6 +156,13 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
+ pm_dir = pmd_offset(pu_dir, address);
+ if (pmd_none(*pm_dir))
+ continue;
++
++ if (pmd_huge(*pm_dir)) {
++ pmd_clear_kernel(pm_dir);
++ address += HPAGE_SIZE - PAGE_SIZE;
++ continue;
++ }
++
+ pt_dir = pte_offset_kernel(pm_dir, address);
+ *pt_dir = pte;
+ }
+@@ -190,10 +172,9 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
+ /*
+ * Add a backed mem_map array to the virtual mem_map array.
+ */
+-static int vmem_add_mem_map(unsigned long start, unsigned long size)
++int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
+ {
+ unsigned long address, start_addr, end_addr;
+- struct page *map_start, *map_end;
+ pgd_t *pg_dir;
+ pud_t *pu_dir;
+ pmd_t *pm_dir;
+@@ -201,11 +182,8 @@ static int vmem_add_mem_map(unsigned long start, unsigned long size)
+ pte_t pte;
+ int ret = -ENOMEM;
+
+- map_start = VMEM_MAP + PFN_DOWN(start);
+- map_end = VMEM_MAP + PFN_DOWN(start + size);
+-
+- start_addr = (unsigned long) map_start & PAGE_MASK;
+- end_addr = PFN_ALIGN((unsigned long) map_end);
++ start_addr = (unsigned long) start;
++ end_addr = (unsigned long) (start + nr);
+
+ for (address = start_addr; address < end_addr; address += PAGE_SIZE) {
+ pg_dir = pgd_offset_k(address);
+@@ -249,16 +227,6 @@ out:
+ return ret;
+ }
+
+-static int vmem_add_mem(unsigned long start, unsigned long size)
+-{
+- int ret;
+-
+- ret = vmem_add_mem_map(start, size);
+- if (ret)
+- return ret;
+- return vmem_add_range(start, size);
+-}
+-
+ /*
+ * Add memory segment to the segment list if it doesn't overlap with
+ * an already present segment.
+@@ -296,7 +264,7 @@ static void __remove_shared_memory(struct memory_segment *seg)
+ vmem_remove_range(seg->start, seg->size);
+ }
+
+-int remove_shared_memory(unsigned long start, unsigned long size)
++int vmem_remove_mapping(unsigned long start, unsigned long size)
+ {
+ struct memory_segment *seg;
+ int ret;
+@@ -320,11 +288,9 @@ out:
+ return ret;
+ }
+
+-int add_shared_memory(unsigned long start, unsigned long size)
++int vmem_add_mapping(unsigned long start, unsigned long size)
+ {
+ struct memory_segment *seg;
+- struct page *page;
+- unsigned long pfn, num_pfn, end_pfn;
+ int ret;
+
+ mutex_lock(&vmem_mutex);
+@@ -339,24 +305,9 @@ int add_shared_memory(unsigned long start, unsigned long size)
+ if (ret)
+ goto out_free;
+
+- ret = vmem_add_mem(start, size);
++ ret = vmem_add_mem(start, size, 0);
+ if (ret)
+ goto out_remove;
+-
+- pfn = PFN_DOWN(start);
+- num_pfn = PFN_DOWN(size);
+- end_pfn = pfn + num_pfn;
+-
+- page = pfn_to_page(pfn);
+- memset(page, 0, num_pfn * sizeof(struct page));
+-
+- for (; pfn < end_pfn; pfn++) {
+- page = pfn_to_page(pfn);
+- init_page_count(page);
+- reset_page_mapcount(page);
+- SetPageReserved(page);
+- INIT_LIST_HEAD(&page->lru);
+- }
+ goto out;
+
+ out_remove:
+@@ -375,14 +326,34 @@ out:
+ */
+ void __init vmem_map_init(void)
+ {
++ unsigned long ro_start, ro_end;
++ unsigned long start, end;
+ int i;
+
+ INIT_LIST_HEAD(&init_mm.context.crst_list);
+ INIT_LIST_HEAD(&init_mm.context.pgtable_list);
+ init_mm.context.noexec = 0;
+- NODE_DATA(0)->node_mem_map = VMEM_MAP;
+- for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++)
+- vmem_add_mem(memory_chunk[i].addr, memory_chunk[i].size);
++ ro_start = ((unsigned long)&_stext) & PAGE_MASK;
++ ro_end = PFN_ALIGN((unsigned long)&_eshared);
++ for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
++ start = memory_chunk[i].addr;
++ end = memory_chunk[i].addr + memory_chunk[i].size;
++ if (start >= ro_end || end <= ro_start)
++ vmem_add_mem(start, end - start, 0);
++ else if (start >= ro_start && end <= ro_end)
++ vmem_add_mem(start, end - start, 1);
++ else if (start >= ro_start) {
++ vmem_add_mem(start, ro_end - start, 1);
++ vmem_add_mem(ro_end, end - ro_end, 0);
++ } else if (end < ro_end) {
++ vmem_add_mem(start, ro_start - start, 0);
++ vmem_add_mem(ro_start, end - ro_start, 1);
++ } else {
++ vmem_add_mem(start, ro_start - start, 0);
++ vmem_add_mem(ro_start, ro_end - ro_start, 1);
++ vmem_add_mem(ro_end, end - ro_end, 0);
++ }
++ }
+ }
+
+ /*
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 8d2cd1d..6a679c3 100644
--- a/arch/sh/Kconfig
@@ -214562,7 +263716,7 @@
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
+index 21ab8c8..e7c150d 100644
--- a/arch/sh/boards/renesas/migor/setup.c
+++ b/arch/sh/boards/renesas/migor/setup.c
@@ -10,8 +10,14 @@
@@ -214593,7 +263747,7 @@
.flags = IORESOURCE_MEM,
},
[1] = {
-@@ -40,19 +46,202 @@ static struct platform_device smc91x_eth_device = {
+@@ -40,19 +46,201 @@ static struct platform_device smc91x_eth_device = {
.resource = smc91x_eth_resources,
};
@@ -214750,8 +263904,7 @@
+
+static struct i2c_board_info __initdata migor_i2c_devices[] = {
+ {
-+ I2C_BOARD_INFO("rtc-rs5c372", 0x32),
-+ .type = "rs5c372b",
++ I2C_BOARD_INFO("rs5c372b", 0x32),
+ },
+ {
+ I2C_BOARD_INFO("migor_ts", 0x51),
@@ -214860,7 +264013,7 @@
};
diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c
-index 2f68bea..a5c5e92 100644
+index 2f68bea..ac0a965 100644
--- a/arch/sh/boards/renesas/r7780rp/setup.c
+++ b/arch/sh/boards/renesas/r7780rp/setup.c
@@ -4,7 +4,7 @@
@@ -214880,7 +264033,7 @@
#include <net/ax88796.h>
#include <asm/machvec.h>
#include <asm/r7780rp.h>
-@@ -176,11 +177,38 @@ static struct platform_device ax88796_device = {
+@@ -176,11 +177,37 @@ static struct platform_device ax88796_device = {
.resource = ax88796_resources,
};
@@ -214906,8 +264059,7 @@
+
+static struct i2c_board_info __initdata highlander_i2c_devices[] = {
+ {
-+ I2C_BOARD_INFO("rtc-rs5c372", 0x32),
-+ .type = "r2025sd",
++ I2C_BOARD_INFO("r2025sd", 0x32),
+ },
+};
@@ -214919,7 +264071,7 @@
#ifndef CONFIG_SH_R7780RP
&ax88796_device,
#endif
-@@ -199,12 +227,20 @@ static struct trapped_io cf_trapped_io = {
+@@ -199,12 +226,20 @@ static struct trapped_io cf_trapped_io = {
static int __init r7780rp_devices_setup(void)
{
@@ -216283,6 +265435,21 @@
#define PCI_NO_CHECKS 0x400
#define PCI_ASSIGN_ROMS 0x1000
#define PCI_BIOS_IRQ_SCAN 0x2000
+diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
+index 49b435c..08d2e73 100644
+--- a/arch/sh/drivers/pci/pci.c
++++ b/arch/sh/drivers/pci/pci.c
+@@ -191,8 +191,8 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
+
+ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+ {
+- unsigned long start = pci_resource_start(dev, bar);
+- unsigned long len = pci_resource_len(dev, bar);
++ resource_size_t start = pci_resource_start(dev, bar);
++ resource_size_t len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (unlikely(!len || !start))
diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32
index 62bf373..4bbdce3 100644
--- a/arch/sh/kernel/Makefile_32
@@ -216309,6 +265476,25 @@
syscalls_64.o time_64.o topology.o traps.o traps_64.o
obj-y += cpu/ timers/
+diff --git a/arch/sh/kernel/asm-offsets.c b/arch/sh/kernel/asm-offsets.c
+index dc6725c..57cf0e0 100644
+--- a/arch/sh/kernel/asm-offsets.c
++++ b/arch/sh/kernel/asm-offsets.c
+@@ -11,12 +11,9 @@
+ #include <linux/stddef.h>
+ #include <linux/types.h>
+ #include <linux/mm.h>
+-#include <asm/thread_info.h>
+-
+-#define DEFINE(sym, val) \
+- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
++#include <linux/kbuild.h>
+
+-#define BLANK() asm volatile("\n->" : : )
++#include <asm/thread_info.h>
+
+ int main(void)
+ {
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
@@ -217101,6 +266287,19 @@
.flags = 0,
}
};
+diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
+index 9bf19b0..a2a99e4 100644
+--- a/arch/sh/kernel/irq.c
++++ b/arch/sh/kernel/irq.c
+@@ -200,8 +200,6 @@ void irq_ctx_exit(int cpu)
+ hardirq_ctx[cpu] = NULL;
+ }
+
+-extern asmlinkage void __do_softirq(void);
+-
+ asmlinkage void do_softirq(void)
+ {
+ unsigned long flags;
diff --git a/arch/sh/kernel/semaphore.c b/arch/sh/kernel/semaphore.c
deleted file mode 100644
index 184119e..0000000
@@ -217388,6 +266587,26 @@
(unsigned int *)CACHE_TYPE_ICACHE,
&cache_debugfs_fops);
if (IS_ERR(icache_dentry)) {
+diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
+index 53dde06..d7df26b 100644
+--- a/arch/sh/mm/init.c
++++ b/arch/sh/mm/init.c
+@@ -307,15 +307,6 @@ void free_initrd_mem(unsigned long start, unsigned long end)
+ #endif
+
+ #ifdef CONFIG_MEMORY_HOTPLUG
+-void online_page(struct page *page)
+-{
+- ClearPageReserved(page);
+- init_page_count(page);
+- __free_page(page);
+- totalram_pages++;
+- num_physpages++;
+-}
+-
+ int arch_add_memory(int nid, u64 start, u64 size)
+ {
+ pg_data_t *pgdat;
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
index ab81c60..0b0ec6e 100644
--- a/arch/sh/mm/pmb.c
@@ -217418,7 +266637,7 @@
7751SYSTEMH SH_7751_SYSTEMH
HP6XX SH_HP6XX
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
-index c40343c..49590f8 100644
+index c40343c..d211fdb 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -27,9 +27,6 @@ config ARCH_NO_VIRT_TO_BUS
@@ -217431,7 +266650,15 @@
config HZ
int
default 100
-@@ -257,15 +254,6 @@ config SPARC_LED
+@@ -71,6 +68,7 @@ config SPARC
+ default y
+ select HAVE_IDE
+ select HAVE_OPROFILE
++ select HAVE_ARCH_KGDB if !SMP
+
+ # Identify this as a Sparc32 build
+ config SPARC32
+@@ -257,15 +255,6 @@ config SPARC_LED
source "fs/Kconfig.binfmt"
@@ -217448,7 +266675,7 @@
endmenu
diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig
-index f7a5091..6a2c57a 100644
+index f7a5091..2e3a149 100644
--- a/arch/sparc/defconfig
+++ b/arch/sparc/defconfig
@@ -1,7 +1,7 @@
@@ -217457,7 +266684,7 @@
-# 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
++# Tue Apr 29 01:28:58 2008
#
CONFIG_MMU=y
CONFIG_HIGHMEM=y
@@ -217577,7 +266804,7 @@
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
+@@ -191,17 +210,14 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=m
CONFIG_INET6_XFRM_MODE_BEET=m
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
CONFIG_IPV6_SIT=m
@@ -217588,7 +266815,17 @@
# 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_IP_SCTP=m
+-# CONFIG_SCTP_DBG_MSG is not set
+-CONFIG_SCTP_DBG_OBJCNT=y
+-# CONFIG_SCTP_HMAC_NONE is not set
+-# CONFIG_SCTP_HMAC_SHA1 is not set
+-CONFIG_SCTP_HMAC_MD5=y
++# CONFIG_IP_SCTP is not set
+ # CONFIG_TIPC is not set
+ # CONFIG_ATM is not set
+ # CONFIG_BRIDGE is not set
+@@ -214,10 +230,6 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -217599,15 +266836,21 @@
# CONFIG_NET_SCHED is not set
#
-@@ -225,6 +242,7 @@ CONFIG_SCTP_HMAC_MD5=y
+@@ -225,11 +237,10 @@ 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
+-CONFIG_AF_RXRPC=m
+-# CONFIG_AF_RXRPC_DEBUG is not set
+-# CONFIG_RXKAD is not set
++# CONFIG_AF_RXRPC is not set
+
+ #
+ # Wireless
+@@ -248,6 +259,7 @@ CONFIG_AF_RXRPC=m
#
# Generic Driver Options
#
@@ -217615,7 +266858,7 @@
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
-@@ -271,7 +290,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
+@@ -271,7 +283,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
@@ -217624,7 +266867,7 @@
# 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
+@@ -279,6 +291,8 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
@@ -217633,7 +266876,7 @@
# CONFIG_IDE is not set
#
-@@ -318,6 +339,7 @@ CONFIG_SCSI_SPI_ATTRS=y
+@@ -318,6 +332,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
@@ -217641,7 +266884,7 @@
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
+@@ -338,6 +353,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
@@ -217649,7 +266892,7 @@
# 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
+@@ -353,14 +369,7 @@ CONFIG_SCSI_SUNESP=y
# CONFIG_SCSI_SRP is not set
# CONFIG_ATA is not set
# CONFIG_MD is not set
@@ -217664,15 +266907,17 @@
#
# IEEE 1394 (FireWire) support
-@@ -375,6 +391,7 @@ CONFIG_DUMMY=m
+@@ -374,7 +383,8 @@ CONFIG_DUMMY=m
+ # CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
- CONFIG_TUN=m
+-CONFIG_TUN=m
++# CONFIG_TUN is not set
+# 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
+@@ -388,11 +398,20 @@ CONFIG_SUNQE=m
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
@@ -217693,7 +266938,7 @@
# CONFIG_MYRI_SBUS is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
-@@ -409,11 +435,15 @@ CONFIG_NETDEV_1000=y
+@@ -409,11 +428,15 @@ CONFIG_NETDEV_1000=y
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
@@ -217709,7 +266954,7 @@
# CONFIG_TR is not set
#
-@@ -421,13 +451,13 @@ CONFIG_NETDEV_10000=y
+@@ -421,13 +444,13 @@ CONFIG_NETDEV_10000=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
@@ -217724,7 +266969,7 @@
# 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
+@@ -449,7 +472,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
CONFIG_INPUT_JOYDEV=m
@@ -217732,7 +266977,7 @@
CONFIG_INPUT_EVDEV=m
CONFIG_INPUT_EVBUG=m
-@@ -498,6 +527,7 @@ CONFIG_VT_CONSOLE=y
+@@ -498,6 +520,7 @@ CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
# CONFIG_SERIAL_NONSTANDARD is not set
@@ -217740,7 +266985,13 @@
#
# Serial drivers
-@@ -519,7 +549,6 @@ CONFIG_UNIX98_PTYS=y
+@@ -514,12 +537,12 @@ CONFIG_SERIAL_SUNSU_CONSOLE=y
+ # CONFIG_SERIAL_SUNSAB is not set
+ CONFIG_SERIAL_CORE=y
+ CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_CONSOLE_POLL=y
+ # 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
@@ -217748,7 +266999,7 @@
CONFIG_HW_RANDOM=m
CONFIG_JS_RTC=m
# CONFIG_R3964 is not set
-@@ -538,9 +567,9 @@ CONFIG_DEVPORT=y
+@@ -538,9 +561,9 @@ CONFIG_DEVPORT=y
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
@@ -217760,7 +267011,7 @@
# 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
+@@ -553,11 +576,20 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
@@ -217775,7 +267026,13 @@
#
# Multifunction device drivers
-@@ -569,15 +606,15 @@ CONFIG_HWMON=y
+ #
+ # CONFIG_MFD_SM501 is not set
++# CONFIG_HTC_PASIC3 is not set
+
+ #
+ # Multimedia devices
+@@ -569,15 +601,15 @@ CONFIG_HWMON=y
#
# Graphics support
#
@@ -217794,7 +267051,7 @@
#
# Console display driver support
-@@ -592,6 +629,7 @@ CONFIG_DUMMY_CONSOLE=y
+@@ -592,6 +624,7 @@ CONFIG_DUMMY_CONSOLE=y
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
@@ -217802,7 +267059,7 @@
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
+@@ -601,36 +634,12 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
@@ -217820,8 +267077,8 @@
-# Real Time Clock
-#
# CONFIG_RTC_CLASS is not set
-
- #
+-
+-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
@@ -217835,17 +267092,22 @@
-#
-
-#
- # Userspace I/O
- #
+-# Userspace I/O
+-#
# CONFIG_UIO is not set
-@@ -664,18 +682,14 @@ CONFIG_FS_MBCACHE=y
+
+ #
+@@ -662,20 +671,12 @@ CONFIG_FS_MBCACHE=y
+ # CONFIG_REISERFS_FS is not set
+ # CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
- CONFIG_XFS_FS=m
- CONFIG_XFS_QUOTA=y
+-CONFIG_XFS_FS=m
+-CONFIG_XFS_QUOTA=y
-CONFIG_XFS_SECURITY=y
- CONFIG_XFS_POSIX_ACL=y
- CONFIG_XFS_RT=y
+-CONFIG_XFS_POSIX_ACL=y
+-CONFIG_XFS_RT=y
-# CONFIG_GFS2_FS is not set
++# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_ROMFS_FS=m
@@ -217853,12 +267115,12 @@
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
- CONFIG_QUOTACTL=y
+-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
+@@ -704,7 +705,6 @@ CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
@@ -217866,7 +267128,17 @@
# CONFIG_CONFIGFS_FS is not set
#
-@@ -721,14 +734,13 @@ CONFIG_BEFS_FS=m
+@@ -712,27 +712,23 @@ CONFIG_RAMFS=y
+ #
+ # CONFIG_ADFS_FS is not set
+ # CONFIG_AFFS_FS is not set
+-# CONFIG_ECRYPT_FS is not set
+ # CONFIG_HFS_FS is not set
+ # CONFIG_HFSPLUS_FS is not set
+-CONFIG_BEFS_FS=m
+-# CONFIG_BEFS_DEBUG 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
@@ -217884,7 +267156,30 @@
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_NFS_DIRECTIO is not set
+ # CONFIG_NFSD is not set
+ CONFIG_ROOT_NFS=y
+ CONFIG_LOCKD=y
+@@ -743,16 +739,10 @@ CONFIG_SUNRPC_GSS=m
+ CONFIG_RPCSEC_GSS_KRB5=m
+ # CONFIG_RPCSEC_GSS_SPKM3 is not set
+ # CONFIG_SMB_FS is not set
+-CONFIG_CIFS=m
+-# CONFIG_CIFS_STATS is not set
+-# CONFIG_CIFS_WEAK_PW_HASH is not set
+-# CONFIG_CIFS_XATTR is not set
+-# CONFIG_CIFS_DEBUG2 is not set
+-# CONFIG_CIFS_EXPERIMENTAL is not set
++# CONFIG_CIFS is not set
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+-CONFIG_AFS_FS=m
+-# CONFIG_AFS_DEBUG is not set
++# CONFIG_AFS_FS is not set
+
+ #
+ # Partition Types
+@@ -760,10 +750,6 @@ CONFIG_AFS_FS=m
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
CONFIG_SUN_PARTITION=y
@@ -217895,7 +267190,7 @@
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
-@@ -804,21 +812,14 @@ CONFIG_NLS_DEFAULT="iso8859-1"
+@@ -804,22 +790,16 @@ 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
@@ -217917,64 +267212,150 @@
# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
-@@ -842,9 +843,12 @@ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_FS is not set
+@@ -841,63 +821,113 @@ CONFIG_DETECT_SOFTLOCKUP=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_FORCED_INLINING=y
+# 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_KGDB=y
++CONFIG_HAVE_ARCH_KGDB=y
++CONFIG_KGDB_SERIAL_CONSOLE=y
++CONFIG_KGDB_TESTS=y
++# CONFIG_KGDB_TESTS_ON_BOOT 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
+ # Security options
+ #
+-CONFIG_KEYS=y
+-# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
++# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
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_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_GF128MUL is not set
++CONFIG_CRYPTO_NULL=m
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_AUTHENC=y
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
+# 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_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 is not set
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
+ CONFIG_CRYPTO_HMAC=y
+ # CONFIG_CRYPTO_XCBC is not set
+-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 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_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_WP512 is not set
++
++#
++# Ciphers
++#
+ CONFIG_CRYPTO_AES=m
++# CONFIG_CRYPTO_ANUBIS is not set
++CONFIG_CRYPTO_ARC4=m
++CONFIG_CRYPTO_BLOWFISH=m
++# CONFIG_CRYPTO_CAMELLIA is not set
+ CONFIG_CRYPTO_CAST5=m
+ CONFIG_CRYPTO_CAST6=m
+-# CONFIG_CRYPTO_TEA is not set
+-CONFIG_CRYPTO_ARC4=m
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_KHAZAD is not set
- # CONFIG_CRYPTO_ANUBIS is not set
-+# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++CONFIG_CRYPTO_SERPENT=m
++# CONFIG_CRYPTO_TEA is not set
++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 is not set
- # CONFIG_CRYPTO_TEST is not set
-+CONFIG_CRYPTO_AUTHENC=y
+-CONFIG_CRYPTO_MICHAEL_MIC=m
+-CONFIG_CRYPTO_CRC32C=m
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_LZO is not set
# CONFIG_CRYPTO_HW is not set
#
+ # Library routines
+ #
+ CONFIG_BITREVERSE=y
++# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+ # CONFIG_CRC_CCITT is not set
+ # CONFIG_CRC16 is not set
+ # CONFIG_CRC_ITU_T is not set
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
-index bf1b15d..59700aa 100644
+index bf1b15d..6e03a2a 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -9,10 +9,10 @@ EXTRA_AFLAGS := -ansi
@@ -217992,7 +267373,7 @@
prom.o of_device.o devres.o
devres-y = ../../../kernel/irq/devres.o
-@@ -25,7 +25,3 @@ obj-$(CONFIG_PCI) += ebus.o
+@@ -25,7 +25,4 @@ 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
@@ -218000,11 +267381,138 @@
-ifdef CONFIG_SUNOS_EMUL
-obj-y += sys_sunos.o sunos_ioctl.o
-endif
++obj-$(CONFIG_KGDB) += kgdb.o
+diff --git a/arch/sparc/kernel/asm-offsets.c b/arch/sparc/kernel/asm-offsets.c
+index 6773ed7..cd3f769 100644
+--- a/arch/sparc/kernel/asm-offsets.c
++++ b/arch/sparc/kernel/asm-offsets.c
+@@ -12,11 +12,7 @@
+
+ #include <linux/sched.h>
+ // #include <linux/mm.h>
+-
+-#define DEFINE(sym, val) \
+- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+-
+-#define BLANK() asm volatile("\n->" : : )
++#include <linux/kbuild.h>
+
+ int foo(void)
+ {
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
-index c2eed8f..484c83d 100644
+index c2eed8f..57d1bbd 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
-@@ -1186,36 +1186,6 @@ srmmu_fault:
+@@ -12,7 +12,6 @@
+ #include <asm/head.h>
+ #include <asm/asi.h>
+ #include <asm/smp.h>
+-#include <asm/kgdb.h>
+ #include <asm/contregs.h>
+ #include <asm/ptrace.h>
+ #include <asm/asm-offsets.h>
+@@ -45,91 +44,20 @@
+ _SV; _SV; _SV; _SV; _SV; _SV; _SV; \
+ _RS; _RS; _RS; _RS; _RS; _RS; _RS;
+
+-/* First, KGDB low level things. This is a rewrite
+- * of the routines found in the sparc-stub.c asm() statement
+- * from the gdb distribution. This is also dual-purpose
+- * as a software trap for userlevel programs.
+- */
+- .data
+- .align 4
+-
+-in_trap_handler:
+- .word 0
+-
+ .text
+- .align 4
+-
+-#if 0 /* kgdb is dropped from 2.5.33 */
+-! This function is called when any SPARC trap (except window overflow or
+-! underflow) occurs. It makes sure that the invalid register window is still
+-! available before jumping into C code. It will also restore the world if you
+-! return from handle_exception.
+-
+- .globl trap_low
+-trap_low:
+- rd %wim, %l3
+- SAVE_ALL
+-
+- sethi %hi(in_trap_handler), %l4
+- ld [%lo(in_trap_handler) + %l4], %l5
+- inc %l5
+- st %l5, [%lo(in_trap_handler) + %l4]
+-
+- /* Make sure kgdb sees the same state we just saved. */
+- LOAD_PT_GLOBALS(sp)
+- LOAD_PT_INS(sp)
+- ld [%sp + STACKFRAME_SZ + PT_Y], %l4
+- ld [%sp + STACKFRAME_SZ + PT_WIM], %l3
+- ld [%sp + STACKFRAME_SZ + PT_PSR], %l0
+- ld [%sp + STACKFRAME_SZ + PT_PC], %l1
+- ld [%sp + STACKFRAME_SZ + PT_NPC], %l2
+- rd %tbr, %l5 /* Never changes... */
+-
+- /* Make kgdb exception frame. */
+- sub %sp,(16+1+6+1+72)*4,%sp ! Make room for input & locals
+- ! + hidden arg + arg spill
+- ! + doubleword alignment
+- ! + registers[72] local var
+- SAVE_KGDB_GLOBALS(sp)
+- SAVE_KGDB_INS(sp)
+- SAVE_KGDB_SREGS(sp, l4, l0, l3, l5, l1, l2)
+-
+- /* We are increasing PIL, so two writes. */
+- or %l0, PSR_PIL, %l0
+- wr %l0, 0, %psr
+- WRITE_PAUSE
+- wr %l0, PSR_ET, %psr
+- WRITE_PAUSE
+-
+- call handle_exception
+- add %sp, STACKFRAME_SZ, %o0 ! Pass address of registers
+-
+- /* Load new kgdb register set. */
+- LOAD_KGDB_GLOBALS(sp)
+- LOAD_KGDB_INS(sp)
+- LOAD_KGDB_SREGS(sp, l4, l0, l3, l5, l1, l2)
+- wr %l4, 0x0, %y
+-
+- sethi %hi(in_trap_handler), %l4
+- ld [%lo(in_trap_handler) + %l4], %l5
+- dec %l5
+- st %l5, [%lo(in_trap_handler) + %l4]
+-
+- add %sp,(16+1+6+1+72)*4,%sp ! Undo the kgdb trap frame.
+-
+- /* Now take what kgdb did and place it into the pt_regs
+- * frame which SparcLinux RESTORE_ALL understands.,
+- */
+- STORE_PT_INS(sp)
+- STORE_PT_GLOBALS(sp)
+- STORE_PT_YREG(sp, g2)
+- STORE_PT_PRIV(sp, l0, l1, l2)
+
+- RESTORE_ALL
++#ifdef CONFIG_KGDB
++ .align 4
++ .globl arch_kgdb_breakpoint
++ .type arch_kgdb_breakpoint,#function
++arch_kgdb_breakpoint:
++ ta 0x7d
++ retl
++ nop
++ .size arch_kgdb_breakpoint,.-arch_kgdb_breakpoint
+ #endif
+
+ #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
+- .text
+ .align 4
+ .globl floppy_hardint
+ floppy_hardint:
+@@ -1186,36 +1114,6 @@ srmmu_fault:
RESTORE_ALL
@@ -218041,7 +267549,7 @@
.align 4
.globl sys_nis_syscall
sys_nis_syscall:
-@@ -1232,6 +1202,16 @@ sys_execve:
+@@ -1232,6 +1130,16 @@ sys_execve:
call sparc_execve
mov %l5, %o7
@@ -218058,7 +267566,7 @@
.align 4
.globl sys_pipe
sys_pipe:
-@@ -1394,7 +1374,7 @@ ret_from_fork:
+@@ -1394,7 +1302,7 @@ ret_from_fork:
b ret_sys_call
ld [%sp + STACKFRAME_SZ + PT_I0], %o0
@@ -218067,7 +267575,7 @@
.align 4
.globl linux_sparc_syscall
linux_sparc_syscall:
-@@ -1429,7 +1409,6 @@ syscall_is_too_hard:
+@@ -1429,7 +1337,6 @@ syscall_is_too_hard:
st %o0, [%sp + STACKFRAME_SZ + PT_I0]
@@ -218075,7 +267583,7 @@
ret_sys_call:
ld [%curptr + TI_FLAGS], %l6
cmp %o0, -ERESTART_RESTARTBLOCK
-@@ -1472,170 +1451,6 @@ linux_syscall_trace2:
+@@ -1472,170 +1379,6 @@ linux_syscall_trace2:
st %l2, [%sp + STACKFRAME_SZ + PT_NPC]
@@ -218246,6 +267754,53 @@
/* Saving and restoring the FPU state is best done from lowlevel code.
*
* void fpsave(unsigned long *fpregs, unsigned long *fsr,
+@@ -1781,6 +1524,23 @@ breakpoint_trap:
+
+ RESTORE_ALL
+
++#ifdef CONFIG_KGDB
++ .align 4
++ .globl kgdb_trap_low
++ .type kgdb_trap_low,#function
++kgdb_trap_low:
++ rd %wim,%l3
++ SAVE_ALL
++ wr %l0, PSR_ET, %psr
++ WRITE_PAUSE
++
++ call kgdb_trap
++ add %sp, STACKFRAME_SZ, %o0
++
++ RESTORE_ALL
++ .size kgdb_trap_low,.-kgdb_trap_low
++#endif
++
+ .align 4
+ .globl __handle_exception, flush_patch_exception
+ __handle_exception:
+@@ -1883,4 +1643,22 @@ pcic_nmi_trap_patch:
+
+ #endif /* CONFIG_PCI */
+
++ .globl flushw_all
++flushw_all:
++ save %sp, -0x40, %sp
++ save %sp, -0x40, %sp
++ save %sp, -0x40, %sp
++ save %sp, -0x40, %sp
++ save %sp, -0x40, %sp
++ save %sp, -0x40, %sp
++ save %sp, -0x40, %sp
++ restore
++ restore
++ restore
++ restore
++ restore
++ restore
++ ret
++ restore
++
+ /* End of entry.S */
diff --git a/arch/sparc/kernel/errtbls.c b/arch/sparc/kernel/errtbls.c
deleted file mode 100644
index ed14df7..0000000
@@ -218397,7 +267952,7 @@
- SOL_ELIBSCN,
-};
diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S
-index 9a219e8..b7f1e81 100644
+index 9a219e8..8bec05f 100644
--- a/arch/sparc/kernel/head.S
+++ b/arch/sparc/kernel/head.S
@@ -78,11 +78,6 @@ sun4e_notsup:
@@ -218441,7 +267996,17 @@
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:
+@@ -196,7 +191,8 @@ t_bade8:BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xe
+ t_baded:BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
+ t_badf2:BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
+ t_badf7:BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
+-t_badfc:BAD_TRAP(0xfc) BAD_TRAP(0xfd)
++t_badfc:BAD_TRAP(0xfc)
++t_kgdb: KGDB_TRAP(0xfd)
+ dbtrap: BAD_TRAP(0xfe) /* Debugger/PROM breakpoint #1 */
+ dbtrap2:BAD_TRAP(0xff) /* Debugger/PROM breakpoint #2 */
+
+@@ -243,19 +239,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)
@@ -218465,7 +268030,16 @@
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:
+@@ -272,7 +268,7 @@ trapbase_cpu1:
+ BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
+ BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
+ BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
+- BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
++ BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
+
+ trapbase_cpu2:
+ BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
+@@ -311,19 +307,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)
@@ -218489,7 +268063,16 @@
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:
+@@ -340,7 +336,7 @@ trapbase_cpu2:
+ BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
+ BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
+ BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
+- BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
++ BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
+
+ trapbase_cpu3:
+ BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
+@@ -379,19 +375,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)
@@ -218513,6 +268096,198 @@
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)
+@@ -408,7 +404,7 @@ trapbase_cpu3:
+ BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
+ BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
+ BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
+- BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
++ BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
+
+ #endif
+ .align PAGE_SIZE
+diff --git a/arch/sparc/kernel/kgdb.c b/arch/sparc/kernel/kgdb.c
+new file mode 100644
+index 0000000..757805c
+--- /dev/null
++++ b/arch/sparc/kernel/kgdb.c
+@@ -0,0 +1,164 @@
++/* kgdb.c: KGDB support for 32-bit sparc.
++ *
++ * Copyright (C) 2008 David S. Miller <davem at davemloft.net>
++ */
++
++#include <linux/kgdb.h>
++#include <linux/kdebug.h>
++
++#include <asm/kdebug.h>
++#include <asm/ptrace.h>
++#include <asm/irq.h>
++
++extern unsigned long trapbase;
++
++void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++ struct reg_window *win;
++ int i;
++
++ gdb_regs[GDB_G0] = 0;
++ for (i = 0; i < 15; i++)
++ gdb_regs[GDB_G1 + i] = regs->u_regs[UREG_G1 + i];
++
++ win = (struct reg_window *) regs->u_regs[UREG_FP];
++ for (i = 0; i < 8; i++)
++ gdb_regs[GDB_L0 + i] = win->locals[i];
++ for (i = 0; i < 8; i++)
++ gdb_regs[GDB_I0 + i] = win->ins[i];
++
++ for (i = GDB_F0; i <= GDB_F31; i++)
++ gdb_regs[i] = 0;
++
++ gdb_regs[GDB_Y] = regs->y;
++ gdb_regs[GDB_PSR] = regs->psr;
++ gdb_regs[GDB_WIM] = 0;
++ gdb_regs[GDB_TBR] = (unsigned long) &trapbase;
++ gdb_regs[GDB_PC] = regs->pc;
++ gdb_regs[GDB_NPC] = regs->npc;
++ gdb_regs[GDB_FSR] = 0;
++ gdb_regs[GDB_CSR] = 0;
++}
++
++void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
++{
++ struct thread_info *t = task_thread_info(p);
++ struct reg_window *win;
++ int i;
++
++ for (i = GDB_G0; i < GDB_G6; i++)
++ gdb_regs[i] = 0;
++ gdb_regs[GDB_G6] = (unsigned long) t;
++ gdb_regs[GDB_G7] = 0;
++ for (i = GDB_O0; i < GDB_SP; i++)
++ gdb_regs[i] = 0;
++ gdb_regs[GDB_SP] = t->ksp;
++ gdb_regs[GDB_O7] = 0;
++
++ win = (struct reg_window *) t->ksp;
++ for (i = 0; i < 8; i++)
++ gdb_regs[GDB_L0 + i] = win->locals[i];
++ for (i = 0; i < 8; i++)
++ gdb_regs[GDB_I0 + i] = win->ins[i];
++
++ for (i = GDB_F0; i <= GDB_F31; i++)
++ gdb_regs[i] = 0;
++
++ gdb_regs[GDB_Y] = 0;
++
++ gdb_regs[GDB_PSR] = t->kpsr;
++ gdb_regs[GDB_WIM] = t->kwim;
++ gdb_regs[GDB_TBR] = (unsigned long) &trapbase;
++ gdb_regs[GDB_PC] = t->kpc;
++ gdb_regs[GDB_NPC] = t->kpc + 4;
++ gdb_regs[GDB_FSR] = 0;
++ gdb_regs[GDB_CSR] = 0;
++}
++
++void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++ struct reg_window *win;
++ int i;
++
++ for (i = 0; i < 15; i++)
++ regs->u_regs[UREG_G1 + i] = gdb_regs[GDB_G1 + i];
++
++ /* If the PSR register is changing, we have to preserve
++ * the CWP field, otherwise window save/restore explodes.
++ */
++ if (regs->psr != gdb_regs[GDB_PSR]) {
++ unsigned long cwp = regs->psr & PSR_CWP;
++
++ regs->psr = (gdb_regs[GDB_PSR] & ~PSR_CWP) | cwp;
++ }
++
++ regs->pc = gdb_regs[GDB_PC];
++ regs->npc = gdb_regs[GDB_NPC];
++ regs->y = gdb_regs[GDB_Y];
++
++ win = (struct reg_window *) regs->u_regs[UREG_FP];
++ for (i = 0; i < 8; i++)
++ win->locals[i] = gdb_regs[GDB_L0 + i];
++ for (i = 0; i < 8; i++)
++ win->ins[i] = gdb_regs[GDB_I0 + i];
++}
++
++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;
++ char *ptr;
++
++ switch (remcomInBuffer[0]) {
++ case 'c':
++ /* try to read optional parameter, pc unchanged if no parm */
++ ptr = &remcomInBuffer[1];
++ if (kgdb_hex2long(&ptr, &addr)) {
++ linux_regs->pc = addr;
++ linux_regs->npc = addr + 4;
++ }
++ /* fallthru */
++
++ case 'D':
++ case 'k':
++ if (linux_regs->pc == (unsigned long) arch_kgdb_breakpoint) {
++ linux_regs->pc = linux_regs->npc;
++ linux_regs->npc += 4;
++ }
++ return 0;
++ }
++ return -1;
++}
++
++extern void do_hw_interrupt(struct pt_regs *regs, unsigned long type);
++
++asmlinkage void kgdb_trap(struct pt_regs *regs)
++{
++ unsigned long flags;
++
++ if (user_mode(regs)) {
++ do_hw_interrupt(regs, 0xfd);
++ return;
++ }
++
++ flushw_all();
++
++ local_irq_save(flags);
++ kgdb_handle_exception(0x172, SIGTRAP, 0, regs);
++ local_irq_restore(flags);
++}
++
++int kgdb_arch_init(void)
++{
++ return 0;
++}
++
++void kgdb_arch_exit(void)
++{
++}
++
++struct kgdb_arch arch_kgdb_ops = {
++ /* Breakpoint instruction: ta 0x7d */
++ .gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x7d },
++};
+diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
+index 70c0dd2..e7f3519 100644
+--- a/arch/sparc/kernel/process.c
++++ b/arch/sparc/kernel/process.c
+@@ -357,8 +357,6 @@ void flush_thread(void)
+ {
+ current_thread_info()->w_saved = 0;
+
+- /* No new signal delivery by default */
+- current->thread.new_signal = 0;
+ #ifndef CONFIG_SMP
+ if(last_task_used_math == current) {
+ #else
diff --git a/arch/sparc/kernel/sclow.S b/arch/sparc/kernel/sclow.S
deleted file mode 100644
index 136e37c..0000000
@@ -218767,10 +268542,17 @@
- return 1;
-}
diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
-index 9994cac..3e849e8 100644
+index 9994cac..3c31229 100644
--- a/arch/sparc/kernel/signal.c
+++ b/arch/sparc/kernel/signal.c
-@@ -22,7 +22,6 @@
+@@ -1,5 +1,4 @@
+-/* $Id: signal.c,v 1.110 2002/02/08 03:57:14 davem Exp $
+- * linux/arch/sparc/kernel/signal.c
++/* linux/arch/sparc/kernel/signal.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
+@@ -22,7 +21,6 @@
#include <asm/uaccess.h>
#include <asm/ptrace.h>
@@ -218778,7 +268560,56 @@
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/cacheflush.h> /* flush_sig_insns */
-@@ -106,11 +105,6 @@ static int _sigpause_common(old_sigset_t set)
+@@ -33,37 +31,7 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
+ void *fpqueue, unsigned long *fpqdepth);
+ extern void fpload(unsigned long *fpregs, unsigned long *fsr);
+
+-/* Signal frames: the original one (compatible with SunOS):
+- *
+- * Set up a signal frame... Make the stack look the way SunOS
+- * expects it to look which is basically:
+- *
+- * ---------------------------------- <-- %sp at signal time
+- * Struct sigcontext
+- * Signal address
+- * Ptr to sigcontext area above
+- * Signal code
+- * The signal number itself
+- * One register window
+- * ---------------------------------- <-- New %sp
+- */
+-struct signal_sframe {
+- struct reg_window sig_window;
+- int sig_num;
+- int sig_code;
+- struct sigcontext __user *sig_scptr;
+- int sig_address;
+- struct sigcontext sig_context;
+- unsigned int extramask[_NSIG_WORDS - 1];
+-};
+-
+-/*
+- * And the new one, intended to be used for Linux applications only
+- * (we have enough in there to work with clone).
+- * All the interesting bits are in the info field.
+- */
+-
+-struct new_signal_frame {
++struct signal_frame {
+ struct sparc_stackf ss;
+ __siginfo_t info;
+ __siginfo_fpu_t __user *fpu_save;
+@@ -86,8 +54,7 @@ struct rt_signal_frame {
+ };
+
+ /* Align macros */
+-#define SF_ALIGNEDSZ (((sizeof(struct signal_sframe) + 7) & (~7)))
+-#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame) + 7) & (~7)))
++#define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7)))
+ #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7)))
+
+ static int _sigpause_common(old_sigset_t set)
+@@ -106,11 +73,6 @@ static int _sigpause_common(old_sigset_t set)
return -ERESTARTNOHAND;
}
@@ -218790,15 +268621,274 @@
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)) {
+@@ -147,15 +109,20 @@ restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
+ return err;
+ }
+
+-static inline void do_new_sigreturn (struct pt_regs *regs)
++asmlinkage void do_sigreturn(struct pt_regs *regs)
+ {
+- struct new_signal_frame __user *sf;
++ struct signal_frame __user *sf;
+ unsigned long up_psr, pc, npc;
+ sigset_t set;
+ __siginfo_fpu_t __user *fpu_save;
+ int err;
+
+- sf = (struct new_signal_frame __user *) regs->u_regs[UREG_FP];
++ /* Always make any pending restarted system calls return -EINTR */
++ current_thread_info()->restart_block.fn = do_no_restart_syscall;
++
++ synchronize_user_stack();
++
++ sf = (struct signal_frame __user *) regs->u_regs[UREG_FP];
+
+ /* 1. Make sure we are not getting garbage from the user */
+ if (!access_ok(VERIFY_READ, sf, sizeof(*sf)))
+@@ -204,73 +171,6 @@ segv_and_exit:
+ force_sig(SIGSEGV, current);
+ }
+
+-asmlinkage void do_sigreturn(struct pt_regs *regs)
+-{
+- struct sigcontext __user *scptr;
+- unsigned long pc, npc, psr;
+- sigset_t set;
+- int err;
+-
+- /* Always make any pending restarted system calls return -EINTR */
+- current_thread_info()->restart_block.fn = do_no_restart_syscall;
+-
+- synchronize_user_stack();
+-
+- if (current->thread.new_signal) {
+- do_new_sigreturn(regs);
+- return;
+- }
+-
+- scptr = (struct sigcontext __user *) regs->u_regs[UREG_I0];
+-
+- /* Check sanity of the user arg. */
+- if (!access_ok(VERIFY_READ, scptr, sizeof(struct sigcontext)) ||
+- (((unsigned long) scptr) & 3))
+- goto segv_and_exit;
+-
+- err = __get_user(pc, &scptr->sigc_pc);
+- err |= __get_user(npc, &scptr->sigc_npc);
+-
+- if ((pc | npc) & 3)
+- goto segv_and_exit;
+-
+- /* This is pretty much atomic, no amount locking would prevent
+- * the races which exist anyways.
+- */
+- err |= __get_user(set.sig[0], &scptr->sigc_mask);
+- /* Note that scptr + 1 points to extramask */
+- err |= __copy_from_user(&set.sig[1], scptr + 1,
+- (_NSIG_WORDS - 1) * sizeof(unsigned int));
+-
+- if (err)
+- goto segv_and_exit;
+-
+- 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;
+-
+- err = __get_user(regs->u_regs[UREG_FP], &scptr->sigc_sp);
+- err |= __get_user(regs->u_regs[UREG_I0], &scptr->sigc_o0);
+- err |= __get_user(regs->u_regs[UREG_G1], &scptr->sigc_g1);
+-
+- /* User can only change condition codes in %psr. */
+- err |= __get_user(psr, &scptr->sigc_psr);
+- if (err)
+- goto segv_and_exit;
+-
+- regs->psr &= ~(PSR_ICC);
+- regs->psr |= (psr & PSR_ICC);
+- return;
+-
+-segv_and_exit:
+- force_sig(SIGSEGV, current);
+-}
+-
+ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
+ {
+ struct rt_signal_frame __user *sf;
+@@ -357,129 +257,6 @@ static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *re
+ return (void __user *)(sp - framesize);
+ }
+
+-static inline void
+-setup_frame(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *oldset, siginfo_t *info)
+-{
+- struct signal_sframe __user *sframep;
+- struct sigcontext __user *sc;
+- int window = 0, err;
+- unsigned long pc = regs->pc;
+- unsigned long npc = regs->npc;
+- struct thread_info *tp = current_thread_info();
+- void __user *sig_address;
+- int sig_code;
+-
+- synchronize_user_stack();
+- sframep = (struct signal_sframe __user *)
+- get_sigframe(sa, regs, SF_ALIGNEDSZ);
+- if (invalid_frame_pointer(sframep, sizeof(*sframep))){
+- /* Don't change signal code and address, so that
+- * post mortem debuggers can have a look.
+- */
+- goto sigill_and_return;
+- }
+-
+- sc = &sframep->sig_context;
+-
+- /* We've already made sure frame pointer isn't in kernel space... */
+- err = __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK),
+- &sc->sigc_onstack);
+- err |= __put_user(oldset->sig[0], &sc->sigc_mask);
+- err |= __copy_to_user(sframep->extramask, &oldset->sig[1],
+- (_NSIG_WORDS - 1) * sizeof(unsigned int));
+- err |= __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp);
+- err |= __put_user(pc, &sc->sigc_pc);
+- err |= __put_user(npc, &sc->sigc_npc);
+- err |= __put_user(regs->psr, &sc->sigc_psr);
+- err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1);
+- err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0);
+- err |= __put_user(tp->w_saved, &sc->sigc_oswins);
+- if (tp->w_saved)
+- for (window = 0; window < tp->w_saved; window++) {
+- put_user((char *)tp->rwbuf_stkptrs[window],
+- &sc->sigc_spbuf[window]);
+- err |= __copy_to_user(&sc->sigc_wbuf[window],
+- &tp->reg_window[window],
+- sizeof(struct reg_window));
+- }
+- else
+- err |= __copy_to_user(sframep, (char *) regs->u_regs[UREG_FP],
+- sizeof(struct reg_window));
+-
+- tp->w_saved = 0; /* So process is allowed to execute. */
+-
+- err |= __put_user(signr, &sframep->sig_num);
+- sig_address = NULL;
+- sig_code = 0;
+- if (SI_FROMKERNEL (info) && (info->si_code & __SI_MASK) == __SI_FAULT) {
+- sig_address = info->si_addr;
+- switch (signr) {
+- case SIGSEGV:
+- switch (info->si_code) {
+- case SEGV_MAPERR: sig_code = SUBSIG_NOMAPPING; break;
+- default: sig_code = SUBSIG_PROTECTION; break;
+- }
+- break;
+- case SIGILL:
+- switch (info->si_code) {
+- case ILL_ILLOPC: sig_code = SUBSIG_ILLINST; break;
+- case ILL_PRVOPC: sig_code = SUBSIG_PRIVINST; break;
+- case ILL_ILLTRP: sig_code = SUBSIG_BADTRAP(info->si_trapno); break;
+- default: sig_code = SUBSIG_STACK; break;
+- }
+- break;
+- case SIGFPE:
+- switch (info->si_code) {
+- case FPE_INTDIV: sig_code = SUBSIG_IDIVZERO; break;
+- case FPE_INTOVF: sig_code = SUBSIG_FPINTOVFL; break;
+- case FPE_FLTDIV: sig_code = SUBSIG_FPDIVZERO; break;
+- case FPE_FLTOVF: sig_code = SUBSIG_FPOVFLOW; break;
+- case FPE_FLTUND: sig_code = SUBSIG_FPUNFLOW; break;
+- case FPE_FLTRES: sig_code = SUBSIG_FPINEXACT; break;
+- case FPE_FLTINV: sig_code = SUBSIG_FPOPERROR; break;
+- default: sig_code = SUBSIG_FPERROR; break;
+- }
+- break;
+- case SIGBUS:
+- switch (info->si_code) {
+- case BUS_ADRALN: sig_code = SUBSIG_ALIGNMENT; break;
+- case BUS_ADRERR: sig_code = SUBSIG_MISCERROR; break;
+- default: sig_code = SUBSIG_BUSTIMEOUT; break;
+- }
+- break;
+- case SIGEMT:
+- switch (info->si_code) {
+- case EMT_TAGOVF: sig_code = SUBSIG_TAG; break;
+- }
+- 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:
+- sig_code = info->si_trapno;
+- break;
+- }
+- default:
+- sig_address = NULL;
+- }
+- }
+- err |= __put_user((unsigned long)sig_address, &sframep->sig_address);
+- err |= __put_user(sig_code, &sframep->sig_code);
+- err |= __put_user(sc, &sframep->sig_scptr);
+- if (err)
+- goto sigsegv;
+-
+- regs->u_regs[UREG_FP] = (unsigned long) sframep;
+- regs->pc = (unsigned long) sa->sa_handler;
+- regs->npc = (regs->pc + 4);
+- return;
+-
+-sigill_and_return:
+- do_exit(SIGILL);
+-sigsegv:
+- force_sigsegv(signr, current);
+-}
+-
+-
+ static inline int
+ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
+ {
+@@ -515,21 +292,20 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
+ return err;
+ }
+
+-static inline void
+-new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
+- int signo, sigset_t *oldset)
++static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
++ int signo, sigset_t *oldset)
+ {
+- struct new_signal_frame __user *sf;
++ struct signal_frame __user *sf;
+ int sigframe_size, err;
+
+ /* 1. Make sure everything is clean */
+ synchronize_user_stack();
+
+- sigframe_size = NF_ALIGNEDSZ;
++ sigframe_size = SF_ALIGNEDSZ;
+ if (!used_math())
+ sigframe_size -= sizeof(__siginfo_fpu_t);
+
+- sf = (struct new_signal_frame __user *)
++ sf = (struct signal_frame __user *)
+ get_sigframe(&ka->sa, regs, sigframe_size);
+
+ if (invalid_frame_pointer(sf, sigframe_size))
+@@ -593,9 +369,8 @@ sigsegv:
+ force_sigsegv(signo, current);
+ }
+
+-static inline void
+-new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
+- int signo, sigset_t *oldset, siginfo_t *info)
++static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
++ int signo, sigset_t *oldset, siginfo_t *info)
+ {
+ struct rt_signal_frame __user *sf;
+ int sigframe_size;
+@@ -676,291 +451,15 @@ sigsegv:
force_sigsegv(signo, current);
}
@@ -219089,16 +269179,14 @@
- 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);
++ setup_rt_frame(ka, regs, signr, oldset, info);
+ else
-+ setup_frame(&ka->sa, regs, signr, oldset, info);
++ setup_frame(ka, regs, signr, oldset);
+
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
+@@ -1002,17 +501,6 @@ asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int rest
int signr;
sigset_t *oldset;
@@ -219116,7 +269204,7 @@
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
+@@ -1025,8 +513,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);
@@ -219127,8 +269215,738 @@
/* 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-stub.c b/arch/sparc/kernel/sparc-stub.c
+deleted file mode 100644
+index e84f815..0000000
+--- a/arch/sparc/kernel/sparc-stub.c
++++ /dev/null
+@@ -1,724 +0,0 @@
+-/* $Id: sparc-stub.c,v 1.28 2001/10/30 04:54:21 davem Exp $
+- * sparc-stub.c: KGDB support for the Linux kernel.
+- *
+- * Modifications to run under Linux
+- * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
+- *
+- * This file originally came from the gdb sources, and the
+- * copyright notices have been retained below.
+- */
+-
+-/****************************************************************************
+-
+- THIS SOFTWARE IS NOT COPYRIGHTED
+-
+- HP offers the following for use in the public domain. HP makes no
+- warranty with regard to the software or its performance and the
+- user accepts the software "AS IS" with all faults.
+-
+- HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+- TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+-
+-****************************************************************************/
+-
+-/****************************************************************************
+- * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
+- *
+- * Module name: remcom.c $
+- * Revision: 1.34 $
+- * Date: 91/03/09 12:29:49 $
+- * Contributor: Lake Stevens Instrument Division$
+- *
+- * Description: low level support for gdb debugger. $
+- *
+- * Considerations: only works on target hardware $
+- *
+- * Written by: Glenn Engel $
+- * ModuleState: Experimental $
+- *
+- * NOTES: See Below $
+- *
+- * Modified for SPARC by Stu Grossman, Cygnus Support.
+- *
+- * This code has been extensively tested on the Fujitsu SPARClite demo board.
+- *
+- * To enable debugger support, two things need to happen. One, a
+- * call to set_debug_traps() is necessary in order to allow any breakpoints
+- * or error conditions to be properly intercepted and reported to gdb.
+- * Two, a breakpoint needs to be generated to begin communication. This
+- * is most easily accomplished by a call to breakpoint(). Breakpoint()
+- * simulates a breakpoint by executing a trap #1.
+- *
+- *************
+- *
+- * The following gdb commands are supported:
+- *
+- * command function Return value
+- *
+- * g return the value of the CPU registers hex data or ENN
+- * G set the value of the CPU registers OK or ENN
+- *
+- * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+- * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+- *
+- * c Resume at current address SNN ( signal NN)
+- * cAA..AA Continue at address AA..AA SNN
+- *
+- * s Step one instruction SNN
+- * sAA..AA Step one instruction from AA..AA SNN
+- *
+- * k kill
+- *
+- * ? What was the last sigval ? SNN (signal NN)
+- *
+- * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
+- * baud rate
+- *
+- * All commands and responses are sent with a packet which includes a
+- * checksum. A packet consists of
+- *
+- * $<packet info>#<checksum>.
+- *
+- * where
+- * <packet info> :: <characters representing the command or response>
+- * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+- *
+- * When a packet is received, it is first acknowledged with either '+' or '-'.
+- * '+' indicates a successful transfer. '-' indicates a failed transfer.
+- *
+- * Example:
+- *
+- * Host: Reply:
+- * $m0,10#2a +$00010203040506070809101112131415#42
+- *
+- ****************************************************************************/
+-
+-#include <linux/kernel.h>
+-#include <linux/string.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-
+-#include <asm/system.h>
+-#include <asm/signal.h>
+-#include <asm/oplib.h>
+-#include <asm/head.h>
+-#include <asm/traps.h>
+-#include <asm/vac-ops.h>
+-#include <asm/kgdb.h>
+-#include <asm/pgalloc.h>
+-#include <asm/pgtable.h>
+-#include <asm/cacheflush.h>
+-
+-/*
+- *
+- * external low-level support routines
+- */
+-
+-extern void putDebugChar(char); /* write a single character */
+-extern char getDebugChar(void); /* read and return a single char */
+-
+-/*
+- * BUFMAX defines the maximum number of characters in inbound/outbound buffers
+- * at least NUMREGBYTES*2 are needed for register packets
+- */
+-#define BUFMAX 2048
+-
+-static int initialized; /* !0 means we've been initialized */
+-
+-static const char hexchars[]="0123456789abcdef";
+-
+-#define NUMREGS 72
+-
+-/* Number of bytes of registers. */
+-#define NUMREGBYTES (NUMREGS * 4)
+-enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
+- O0, O1, O2, O3, O4, O5, SP, O7,
+- L0, L1, L2, L3, L4, L5, L6, L7,
+- I0, I1, I2, I3, I4, I5, FP, I7,
+-
+- F0, F1, F2, F3, F4, F5, F6, F7,
+- F8, F9, F10, F11, F12, F13, F14, F15,
+- F16, F17, F18, F19, F20, F21, F22, F23,
+- F24, F25, F26, F27, F28, F29, F30, F31,
+- Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR };
+-
+-
+-extern void trap_low(void); /* In arch/sparc/kernel/entry.S */
+-
+-unsigned long get_sun4cpte(unsigned long addr)
+-{
+- unsigned long entry;
+-
+- __asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" :
+- "=r" (entry) :
+- "r" (addr), "i" (ASI_PTE));
+- return entry;
+-}
+-
+-unsigned long get_sun4csegmap(unsigned long addr)
+-{
+- unsigned long entry;
+-
+- __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" :
+- "=r" (entry) :
+- "r" (addr), "i" (ASI_SEGMAP));
+- return entry;
+-}
+-
+-#if 0
+-/* Have to sort this out. This cannot be done after initialization. */
+-static void flush_cache_all_nop(void) {}
+-#endif
+-
+-/* Place where we save old trap entries for restoration */
+-struct tt_entry kgdb_savettable[256];
+-typedef void (*trapfunc_t)(void);
+-
+-/* Helper routine for manipulation of kgdb_savettable */
+-static inline void copy_ttentry(struct tt_entry *src, struct tt_entry *dest)
+-{
+- dest->inst_one = src->inst_one;
+- dest->inst_two = src->inst_two;
+- dest->inst_three = src->inst_three;
+- dest->inst_four = src->inst_four;
+-}
+-
+-/* Initialize the kgdb_savettable so that debugging can commence */
+-static void eh_init(void)
+-{
+- int i;
+-
+- for(i=0; i < 256; i++)
+- copy_ttentry(&sparc_ttable[i], &kgdb_savettable[i]);
+-}
+-
+-/* Install an exception handler for kgdb */
+-static void exceptionHandler(int tnum, trapfunc_t trap_entry)
+-{
+- unsigned long te_addr = (unsigned long) trap_entry;
+-
+- /* Make new vector */
+- sparc_ttable[tnum].inst_one =
+- SPARC_BRANCH((unsigned long) te_addr,
+- (unsigned long) &sparc_ttable[tnum].inst_one);
+- sparc_ttable[tnum].inst_two = SPARC_RD_PSR_L0;
+- sparc_ttable[tnum].inst_three = SPARC_NOP;
+- sparc_ttable[tnum].inst_four = SPARC_NOP;
+-}
+-
+-/* Convert ch from a hex digit to an int */
+-static int
+-hex(unsigned char ch)
+-{
+- if (ch >= 'a' && ch <= 'f')
+- return ch-'a'+10;
+- if (ch >= '0' && ch <= '9')
+- return ch-'0';
+- if (ch >= 'A' && ch <= 'F')
+- return ch-'A'+10;
+- return -1;
+-}
+-
+-/* scan for the sequence $<data>#<checksum> */
+-static void
+-getpacket(char *buffer)
+-{
+- unsigned char checksum;
+- unsigned char xmitcsum;
+- int i;
+- int count;
+- unsigned char ch;
+-
+- do {
+- /* wait around for the start character, ignore all other characters */
+- while ((ch = (getDebugChar() & 0x7f)) != '$') ;
+-
+- checksum = 0;
+- xmitcsum = -1;
+-
+- count = 0;
+-
+- /* now, read until a # or end of buffer is found */
+- while (count < BUFMAX) {
+- ch = getDebugChar() & 0x7f;
+- if (ch == '#')
+- break;
+- checksum = checksum + ch;
+- buffer[count] = ch;
+- count = count + 1;
+- }
+-
+- if (count >= BUFMAX)
+- continue;
+-
+- buffer[count] = 0;
+-
+- if (ch == '#') {
+- xmitcsum = hex(getDebugChar() & 0x7f) << 4;
+- xmitcsum |= hex(getDebugChar() & 0x7f);
+- if (checksum != xmitcsum)
+- putDebugChar('-'); /* failed checksum */
+- else {
+- putDebugChar('+'); /* successful transfer */
+- /* if a sequence char is present, reply the ID */
+- if (buffer[2] == ':') {
+- putDebugChar(buffer[0]);
+- putDebugChar(buffer[1]);
+- /* remove sequence chars from buffer */
+- count = strlen(buffer);
+- for (i=3; i <= count; i++)
+- buffer[i-3] = buffer[i];
+- }
+- }
+- }
+- } while (checksum != xmitcsum);
+-}
+-
+-/* send the packet in buffer. */
+-
+-static void
+-putpacket(unsigned char *buffer)
+-{
+- unsigned char checksum;
+- int count;
+- unsigned char ch, recv;
+-
+- /* $<packet info>#<checksum>. */
+- do {
+- putDebugChar('$');
+- checksum = 0;
+- count = 0;
+-
+- while ((ch = buffer[count])) {
+- putDebugChar(ch);
+- checksum += ch;
+- count += 1;
+- }
+-
+- putDebugChar('#');
+- putDebugChar(hexchars[checksum >> 4]);
+- putDebugChar(hexchars[checksum & 0xf]);
+- recv = getDebugChar();
+- } while ((recv & 0x7f) != '+');
+-}
+-
+-static char remcomInBuffer[BUFMAX];
+-static char remcomOutBuffer[BUFMAX];
+-
+-/* Convert the memory pointed to by mem into hex, placing result in buf.
+- * Return a pointer to the last char put in buf (null), in case of mem fault,
+- * return 0.
+- */
+-
+-static unsigned char *
+-mem2hex(char *mem, char *buf, int count)
+-{
+- unsigned char ch;
+-
+- while (count-- > 0) {
+- /* This assembler code is basically: ch = *mem++;
+- * except that we use the SPARC/Linux exception table
+- * mechanism (see how "fixup" works in kernel_mna_trap_fault)
+- * to arrange for a "return 0" upon a memory fault
+- */
+- __asm__(
+- "\n1:\n\t"
+- "ldub [%0], %1\n\t"
+- "inc %0\n\t"
+- ".section .fixup,#alloc,#execinstr\n\t"
+- ".align 4\n"
+- "2:\n\t"
+- "retl\n\t"
+- " mov 0, %%o0\n\t"
+- ".section __ex_table, #alloc\n\t"
+- ".align 4\n\t"
+- ".word 1b, 2b\n\t"
+- ".text\n"
+- : "=r" (mem), "=r" (ch) : "0" (mem));
+- *buf++ = hexchars[ch >> 4];
+- *buf++ = hexchars[ch & 0xf];
+- }
+-
+- *buf = 0;
+- return buf;
+-}
+-
+-/* 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.
+-*/
+-static char *
+-hex2mem(char *buf, char *mem, int count)
+-{
+- int i;
+- unsigned char ch;
+-
+- for (i=0; i<count; i++) {
+-
+- ch = hex(*buf++) << 4;
+- ch |= hex(*buf++);
+- /* Assembler code is *mem++ = ch; with return 0 on fault */
+- __asm__(
+- "\n1:\n\t"
+- "stb %1, [%0]\n\t"
+- "inc %0\n\t"
+- ".section .fixup,#alloc,#execinstr\n\t"
+- ".align 4\n"
+- "2:\n\t"
+- "retl\n\t"
+- " mov 0, %%o0\n\t"
+- ".section __ex_table, #alloc\n\t"
+- ".align 4\n\t"
+- ".word 1b, 2b\n\t"
+- ".text\n"
+- : "=r" (mem) : "r" (ch) , "0" (mem));
+- }
+- return mem;
+-}
+-
+-/* This table contains the mapping between SPARC hardware trap types, and
+- signals, which are primarily what GDB understands. It also indicates
+- which hardware traps we need to commandeer when initializing the stub. */
+-
+-static struct hard_trap_info
+-{
+- unsigned char tt; /* Trap type code for SPARC */
+- unsigned char signo; /* Signal that we map this trap into */
+-} hard_trap_info[] = {
+- {SP_TRAP_SBPT, SIGTRAP}, /* ta 1 - Linux/KGDB software breakpoint */
+- {0, 0} /* Must be last */
+-};
+-
+-/* Set up exception handlers for tracing and breakpoints */
+-
+-void
+-set_debug_traps(void)
+-{
+- struct hard_trap_info *ht;
+- unsigned long flags;
+-
+- local_irq_save(flags);
+-#if 0
+-/* Have to sort this out. This cannot be done after initialization. */
+- BTFIXUPSET_CALL(flush_cache_all, flush_cache_all_nop, BTFIXUPCALL_NOP);
+-#endif
+-
+- /* Initialize our copy of the Linux Sparc trap table */
+- eh_init();
+-
+- for (ht = hard_trap_info; ht->tt && ht->signo; ht++) {
+- /* Only if it doesn't destroy our fault handlers */
+- if((ht->tt != SP_TRAP_TFLT) &&
+- (ht->tt != SP_TRAP_DFLT))
+- exceptionHandler(ht->tt, trap_low);
+- }
+-
+- /* In case GDB is started before us, ack any packets (presumably
+- * "$?#xx") sitting there.
+- *
+- * I've found this code causes more problems than it solves,
+- * so that's why it's commented out. GDB seems to work fine
+- * now starting either before or after the kernel -bwb
+- */
+-#if 0
+- while((c = getDebugChar()) != '$');
+- while((c = getDebugChar()) != '#');
+- c = getDebugChar(); /* eat first csum byte */
+- c = getDebugChar(); /* eat second csum byte */
+- putDebugChar('+'); /* ack it */
+-#endif
+-
+- initialized = 1; /* connect! */
+- local_irq_restore(flags);
+-}
+-
+-/* Convert the SPARC hardware trap type code to a unix signal number. */
+-
+-static int
+-computeSignal(int tt)
+-{
+- struct hard_trap_info *ht;
+-
+- for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+- if (ht->tt == tt)
+- return ht->signo;
+-
+- return SIGHUP; /* default for things we don't know about */
+-}
+-
+-/*
+- * While we find nice hex chars, build an int.
+- * Return number of chars processed.
+- */
+-
+-static int
+-hexToInt(char **ptr, int *intValue)
+-{
+- int numChars = 0;
+- int hexValue;
+-
+- *intValue = 0;
+-
+- while (**ptr) {
+- hexValue = hex(**ptr);
+- if (hexValue < 0)
+- break;
+-
+- *intValue = (*intValue << 4) | hexValue;
+- numChars ++;
+-
+- (*ptr)++;
+- }
+-
+- return (numChars);
+-}
+-
+-/*
+- * This function does all command processing for interfacing to gdb. It
+- * returns 1 if you should skip the instruction at the trap address, 0
+- * otherwise.
+- */
+-
+-extern void breakinst(void);
+-
+-void
+-handle_exception (unsigned long *registers)
+-{
+- int tt; /* Trap type */
+- int sigval;
+- int addr;
+- int length;
+- char *ptr;
+- unsigned long *sp;
+-
+- /* First, we must force all of the windows to be spilled out */
+-
+- asm("save %sp, -64, %sp\n\t"
+- "save %sp, -64, %sp\n\t"
+- "save %sp, -64, %sp\n\t"
+- "save %sp, -64, %sp\n\t"
+- "save %sp, -64, %sp\n\t"
+- "save %sp, -64, %sp\n\t"
+- "save %sp, -64, %sp\n\t"
+- "save %sp, -64, %sp\n\t"
+- "restore\n\t"
+- "restore\n\t"
+- "restore\n\t"
+- "restore\n\t"
+- "restore\n\t"
+- "restore\n\t"
+- "restore\n\t"
+- "restore\n\t");
+-
+- lock_kernel();
+- if (registers[PC] == (unsigned long)breakinst) {
+- /* Skip over breakpoint trap insn */
+- registers[PC] = registers[NPC];
+- registers[NPC] += 4;
+- }
+-
+- sp = (unsigned long *)registers[SP];
+-
+- tt = (registers[TBR] >> 4) & 0xff;
+-
+- /* reply to host that an exception has occurred */
+- sigval = computeSignal(tt);
+- ptr = remcomOutBuffer;
+-
+- *ptr++ = 'T';
+- *ptr++ = hexchars[sigval >> 4];
+- *ptr++ = hexchars[sigval & 0xf];
+-
+- *ptr++ = hexchars[PC >> 4];
+- *ptr++ = hexchars[PC & 0xf];
+- *ptr++ = ':';
+- ptr = mem2hex((char *)®isters[PC], ptr, 4);
+- *ptr++ = ';';
+-
+- *ptr++ = hexchars[FP >> 4];
+- *ptr++ = hexchars[FP & 0xf];
+- *ptr++ = ':';
+- ptr = mem2hex((char *) (sp + 8 + 6), ptr, 4); /* FP */
+- *ptr++ = ';';
+-
+- *ptr++ = hexchars[SP >> 4];
+- *ptr++ = hexchars[SP & 0xf];
+- *ptr++ = ':';
+- ptr = mem2hex((char *)&sp, ptr, 4);
+- *ptr++ = ';';
+-
+- *ptr++ = hexchars[NPC >> 4];
+- *ptr++ = hexchars[NPC & 0xf];
+- *ptr++ = ':';
+- ptr = mem2hex((char *)®isters[NPC], ptr, 4);
+- *ptr++ = ';';
+-
+- *ptr++ = hexchars[O7 >> 4];
+- *ptr++ = hexchars[O7 & 0xf];
+- *ptr++ = ':';
+- ptr = mem2hex((char *)®isters[O7], ptr, 4);
+- *ptr++ = ';';
+-
+- *ptr++ = 0;
+-
+- putpacket(remcomOutBuffer);
+-
+- /* XXX We may want to add some features dealing with poking the
+- * XXX page tables, the real ones on the srmmu, and what is currently
+- * XXX loaded in the sun4/sun4c tlb at this point in time. But this
+- * XXX also required hacking to the gdb sources directly...
+- */
+-
+- while (1) {
+- remcomOutBuffer[0] = 0;
+-
+- getpacket(remcomInBuffer);
+- switch (remcomInBuffer[0]) {
+- case '?':
+- remcomOutBuffer[0] = 'S';
+- remcomOutBuffer[1] = hexchars[sigval >> 4];
+- remcomOutBuffer[2] = hexchars[sigval & 0xf];
+- remcomOutBuffer[3] = 0;
+- break;
+-
+- case 'd':
+- /* toggle debug flag */
+- break;
+-
+- case 'g': /* return the value of the CPU registers */
+- {
+- ptr = remcomOutBuffer;
+- /* G & O regs */
+- ptr = mem2hex((char *)registers, ptr, 16 * 4);
+- /* L & I regs */
+- ptr = mem2hex((char *) (sp + 0), ptr, 16 * 4);
+- /* Floating point */
+- memset(ptr, '0', 32 * 8);
+- /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
+- mem2hex((char *)®isters[Y], (ptr + 32 * 4 * 2), (8 * 4));
+- }
+- break;
+-
+- case 'G': /* set the value of the CPU registers - return OK */
+- {
+- unsigned long *newsp, psr;
+-
+- psr = registers[PSR];
+-
+- ptr = &remcomInBuffer[1];
+- /* G & O regs */
+- hex2mem(ptr, (char *)registers, 16 * 4);
+- /* L & I regs */
+- hex2mem(ptr + 16 * 4 * 2, (char *) (sp + 0), 16 * 4);
+- /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
+- hex2mem(ptr + 64 * 4 * 2, (char *)®isters[Y], 8 * 4);
+-
+- /* See if the stack pointer has moved. If so,
+- * then copy the saved locals and ins to the
+- * new location. This keeps the window
+- * overflow and underflow routines happy.
+- */
+-
+- newsp = (unsigned long *)registers[SP];
+- if (sp != newsp)
+- sp = memcpy(newsp, sp, 16 * 4);
+-
+- /* Don't allow CWP to be modified. */
+-
+- if (psr != registers[PSR])
+- registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
+-
+- strcpy(remcomOutBuffer,"OK");
+- }
+- break;
+-
+- case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
+- /* Try to read %x,%x. */
+-
+- ptr = &remcomInBuffer[1];
+-
+- if (hexToInt(&ptr, &addr)
+- && *ptr++ == ','
+- && hexToInt(&ptr, &length)) {
+- if (mem2hex((char *)addr, remcomOutBuffer, length))
+- break;
+-
+- strcpy (remcomOutBuffer, "E03");
+- } else {
+- strcpy(remcomOutBuffer,"E01");
+- }
+- break;
+-
+- case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+- /* Try to read '%x,%x:'. */
+-
+- ptr = &remcomInBuffer[1];
+-
+- if (hexToInt(&ptr, &addr)
+- && *ptr++ == ','
+- && hexToInt(&ptr, &length)
+- && *ptr++ == ':') {
+- if (hex2mem(ptr, (char *)addr, length)) {
+- strcpy(remcomOutBuffer, "OK");
+- } else {
+- strcpy(remcomOutBuffer, "E03");
+- }
+- } else {
+- strcpy(remcomOutBuffer, "E02");
+- }
+- break;
+-
+- case 'c': /* cAA..AA Continue at address AA..AA(optional) */
+- /* try to read optional parameter, pc unchanged if no parm */
+-
+- ptr = &remcomInBuffer[1];
+- if (hexToInt(&ptr, &addr)) {
+- registers[PC] = addr;
+- registers[NPC] = addr + 4;
+- }
+-
+-/* Need to flush the instruction cache here, as we may have deposited a
+- * breakpoint, and the icache probably has no way of knowing that a data ref to
+- * some location may have changed something that is in the instruction cache.
+- */
+- flush_cache_all();
+- unlock_kernel();
+- return;
+-
+- /* kill the program */
+- case 'k' : /* do nothing */
+- break;
+- case 'r': /* Reset */
+- asm ("call 0\n\t"
+- "nop\n\t");
+- break;
+- } /* switch */
+-
+- /* reply to the request */
+- putpacket(remcomOutBuffer);
+- } /* while(1) */
+-}
+-
+-/* 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
+-breakpoint(void)
+-{
+- if (!initialized)
+- return;
+-
+- /* Again, watch those c-prefixes for ELF kernels */
+-#if defined(__svr4__) || defined(__ELF__)
+- asm(".globl breakinst\n"
+- "breakinst:\n\t"
+- "ta 1\n");
+-#else
+- asm(".globl _breakinst\n"
+- "_breakinst:\n\t"
+- "ta 1\n");
+-#endif
+-}
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
-index c1025e5..0bcf98a 100644
+index c1025e5..aa8ee06 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -36,12 +36,10 @@
@@ -219176,6 +269994,131 @@
/* prom symbols */
EXPORT_SYMBOL(idprom);
EXPORT_SYMBOL(prom_root_node);
+@@ -295,3 +282,5 @@ EXPORT_SYMBOL(do_BUG);
+
+ /* Sun Power Management Idle Handler */
+ EXPORT_SYMBOL(pm_idle);
++
++EXPORT_SYMBOL(empty_zero_page);
+diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
+index 0def481..dfde77f 100644
+--- a/arch/sparc/kernel/sun4d_smp.c
++++ b/arch/sparc/kernel/sun4d_smp.c
+@@ -335,37 +335,6 @@ void smp4d_cross_call_irq(void)
+ ccall_info.processors_out[i] = 1;
+ }
+
+-static int smp4d_stop_cpu_sender;
+-
+-static void smp4d_stop_cpu(void)
+-{
+- int me = hard_smp4d_processor_id();
+-
+- if (me != smp4d_stop_cpu_sender)
+- while(1) barrier();
+-}
+-
+-/* Cross calls, in order to work efficiently and atomically do all
+- * the message passing work themselves, only stopcpu and reschedule
+- * messages come through here.
+- */
+-void smp4d_message_pass(int target, int msg, unsigned long data, int wait)
+-{
+- int me = hard_smp4d_processor_id();
+-
+- SMP_PRINTK(("smp4d_message_pass %d %d %08lx %d\n", target, msg, data, wait));
+- if (msg == MSG_STOP_CPU && target == MSG_ALL_BUT_SELF) {
+- unsigned long flags;
+- static DEFINE_SPINLOCK(stop_cpu_lock);
+- spin_lock_irqsave(&stop_cpu_lock, flags);
+- smp4d_stop_cpu_sender = me;
+- smp4d_cross_call((smpfunc_t)smp4d_stop_cpu, 0, 0, 0, 0, 0);
+- spin_unlock_irqrestore(&stop_cpu_lock, flags);
+- }
+- printk("Yeeee, trying to send SMP msg(%d) to %d on cpu %d\n", msg, target, me);
+- panic("Bogon SMP message pass.");
+-}
+-
+ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
+ {
+ struct pt_regs *old_regs;
+@@ -439,7 +408,6 @@ void __init sun4d_init_smp(void)
+ BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id);
+ BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current);
+ BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM);
+- BTFIXUPSET_CALL(smp_message_pass, smp4d_message_pass, BTFIXUPCALL_NORM);
+ BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM);
+
+ for (i = 0; i < NR_CPUS; i++) {
+diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
+index 0b94072..ffb875a 100644
+--- a/arch/sparc/kernel/sun4m_smp.c
++++ b/arch/sparc/kernel/sun4m_smp.c
+@@ -34,8 +34,6 @@
+
+ #include "irq.h"
+
+-#define IRQ_RESCHEDULE 13
+-#define IRQ_STOP_CPU 14
+ #define IRQ_CROSS_CALL 15
+
+ extern ctxd_t *srmmu_ctx_table_phys;
+@@ -232,48 +230,6 @@ void smp4m_irq_rotate(int cpu)
+ set_irq_udt(next);
+ }
+
+-/* Cross calls, in order to work efficiently and atomically do all
+- * the message passing work themselves, only stopcpu and reschedule
+- * messages come through here.
+- */
+-void smp4m_message_pass(int target, int msg, unsigned long data, int wait)
+-{
+- static unsigned long smp_cpu_in_msg[NR_CPUS];
+- cpumask_t mask;
+- int me = smp_processor_id();
+- int irq, i;
+-
+- if(msg == MSG_RESCHEDULE) {
+- irq = IRQ_RESCHEDULE;
+-
+- if(smp_cpu_in_msg[me])
+- return;
+- } else if(msg == MSG_STOP_CPU) {
+- irq = IRQ_STOP_CPU;
+- } else {
+- goto barf;
+- }
+-
+- smp_cpu_in_msg[me]++;
+- if(target == MSG_ALL_BUT_SELF || target == MSG_ALL) {
+- mask = cpu_online_map;
+- if(target == MSG_ALL_BUT_SELF)
+- cpu_clear(me, mask);
+- for(i = 0; i < 4; i++) {
+- if (cpu_isset(i, mask))
+- set_cpu_int(i, irq);
+- }
+- } else {
+- set_cpu_int(target, irq);
+- }
+- smp_cpu_in_msg[me]--;
+-
+- return;
+-barf:
+- printk("Yeeee, trying to send SMP msg(%d) on cpu %d\n", msg, me);
+- panic("Bogon SMP message pass.");
+-}
+-
+ static struct smp_funcall {
+ smpfunc_t func;
+ unsigned long arg1;
+@@ -413,6 +369,5 @@ void __init sun4m_init_smp(void)
+ BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4m_blackbox_id);
+ BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current);
+ BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM);
+- BTFIXUPSET_CALL(smp_message_pass, smp4m_message_pass, BTFIXUPCALL_NORM);
+ BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM);
+ }
diff --git a/arch/sparc/kernel/sunos_asm.S b/arch/sparc/kernel/sunos_asm.S
deleted file mode 100644
index 07fe860..0000000
@@ -219526,6 +270469,42 @@
- return 0;
-}
-#endif
+diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
+index 42bf09d..f188b5d 100644
+--- a/arch/sparc/kernel/sys_sparc.c
++++ b/arch/sparc/kernel/sys_sparc.c
+@@ -1,5 +1,4 @@
+-/* $Id: sys_sparc.c,v 1.70 2001/04/14 01:12:02 davem Exp $
+- * linux/arch/sparc/kernel/sys_sparc.c
++/* linux/arch/sparc/kernel/sys_sparc.c
+ *
+ * This file contains various random system calls that
+ * have a non-standard calling sequence on the Linux/sparc
+@@ -395,10 +394,8 @@ sparc_sigaction (int sig, const struct old_sigaction __user *act,
+ struct k_sigaction new_ka, old_ka;
+ int ret;
+
+- if (sig < 0) {
+- current->thread.new_signal = 1;
+- sig = -sig;
+- }
++ WARN_ON_ONCE(sig >= 0);
++ sig = -sig;
+
+ if (act) {
+ unsigned long mask;
+@@ -446,11 +443,6 @@ sys_rt_sigaction(int sig,
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+
+- /* All tasks which use RT signals (effectively) use
+- * new style signals.
+- */
+- current->thread.new_signal = 1;
+-
+ if (act) {
+ new_ka.ka_restorer = restorer;
+ if (copy_from_user(&new_ka.sa, act, sizeof(*act)))
diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
deleted file mode 100644
index f5b608b..0000000
@@ -220884,19 +271863,53 @@
{
/* last time the cmos clock got updated */
static long last_rtc_update;
+diff --git a/arch/sparc/lib/iomap.c b/arch/sparc/lib/iomap.c
+index 54501c1..9ef37e1 100644
+--- a/arch/sparc/lib/iomap.c
++++ b/arch/sparc/lib/iomap.c
+@@ -21,8 +21,8 @@ EXPORT_SYMBOL(ioport_unmap);
+ /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+ {
+- unsigned long start = pci_resource_start(dev, bar);
+- unsigned long len = pci_resource_len(dev, bar);
++ resource_size_t start = pci_resource_start(dev, bar);
++ resource_size_t len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (!len || !start)
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
-index 463d1be..8acc5cc 100644
+index 463d1be..eb36f3b 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
-@@ -16,6 +16,7 @@ config SPARC64
+@@ -1,9 +1,5 @@
+-# $Id: config.in,v 1.158 2002/01/24 22:14:44 davem Exp $
+-# For a description of the syntax of this configuration file,
+-# see the Configure script.
+-#
+-
+-mainmenu "Linux/UltraSPARC Kernel Configuration"
++# sparc64 configuration
++mainmenu "Linux Kernel Configuration for 64-bit SPARC"
+
+ config SPARC
+ bool
+@@ -16,12 +12,8 @@ config SPARC64
bool
default y
select HAVE_IDE
+- help
+- SPARC is a family of RISC microprocessors designed and marketed by
+- Sun Microsystems, incorporated. This port covers the newer 64-bit
+- UltraSPARC. The UltraLinux project maintains both the SPARC32 and
+- SPARC64 ports; its web page is available at
+- <http://www.ultralinux.org/>.
+ 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
++ select HAVE_ARCH_KGDB
+
+ config GENERIC_TIME
+ bool
+@@ -87,9 +79,6 @@ config GENERIC_HARDIRQS_NO__DO_IRQ
bool
def_bool y
@@ -220906,7 +271919,24 @@
choice
prompt "Kernel page size"
default SPARC64_PAGE_SIZE_8KB
-@@ -147,11 +145,6 @@ config HOTPLUG_CPU
+@@ -99,7 +88,7 @@ config SPARC64_PAGE_SIZE_8KB
+ help
+ This lets you select the page size of the kernel.
+
+- 8KB and 64KB work quite well, since Sparc ELF sections
++ 8KB and 64KB work quite well, since SPARC ELF sections
+ provide for up to 64KB alignment.
+
+ Therefore, 512KB and 4MB are for expert hackers only.
+@@ -140,18 +129,13 @@ config HOTPLUG_CPU
+ bool "Support for hot-pluggable CPUs"
+ depends on SMP
+ select HOTPLUG
+- ---help---
++ help
+ Say Y here to experiment with turning CPUs off and on. CPUs
+ can be controlled through /sys/devices/system/cpu/cpu#.
+ Say N if you want to disable CPU hotplug.
source "init/Kconfig"
@@ -220918,7 +271948,35 @@
config GENERIC_HARDIRQS
bool
default y
-@@ -257,6 +250,26 @@ endchoice
+@@ -162,23 +146,16 @@ source "kernel/time/Kconfig"
+
+ config SMP
+ bool "Symmetric multi-processing support"
+- ---help---
++ help
+ This enables support for systems with more than one CPU. If you have
+ a system with only one CPU, say N. If you have a system with more than
+ one CPU, say Y.
+
+ If you say N here, the kernel will run on single and multiprocessor
+ machines, but will use only one CPU of a multiprocessor machine. If
+- you say Y here, the kernel will run on many, but not all,
+- singleprocessor machines. On a singleprocessor machine, the kernel
+- will run faster if you say N here.
+-
+- People using multiprocessor machines who say Y here should also say
+- Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
+- Management" code will be disabled if you say Y here.
+-
+- See also <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO
+- available at <http://www.tldp.org/docs.html#howto>.
++ you say Y here, the kernel will run on single-processor machines.
++ On a single-processor machine, the kernel will run faster if you say
++ N here.
+
+ If you don't know what to do here, say N.
+
+@@ -257,6 +234,26 @@ endchoice
endmenu
@@ -220945,18 +272003,89 @@
config ARCH_SELECT_MEMORY_MODEL
def_bool y
-@@ -379,6 +392,10 @@ config SUN_OPENPROMFS
+@@ -271,50 +268,19 @@ source "mm/Kconfig"
+
+ config ISA
+ bool
+- help
+- Find out whether you have ISA slots on your motherboard. ISA is the
+- name of a bus system, i.e. the way the CPU talks to the other stuff
+- inside your box. Other bus systems are PCI, EISA, MicroChannel
+- (MCA) or VESA. ISA is an older system, now being displaced by PCI;
+- newer boards don't support it. If you have ISA, say Y, otherwise N.
+
+ config ISAPNP
+ bool
+- help
+- Say Y here if you would like support for ISA Plug and Play devices.
+- Some information is in <file:Documentation/isapnp.txt>.
+-
+- To compile this driver as a module, choose M here: the
+- module will be called isapnp.
+-
+- If unsure, say Y.
+
+ config EISA
+ bool
+- ---help---
+- The Extended Industry Standard Architecture (EISA) bus was
+- developed as an open alternative to the IBM MicroChannel bus.
+-
+- The EISA bus provided some of the features of the IBM MicroChannel
+- bus while maintaining backward compatibility with cards made for
+- the older ISA bus. The EISA bus saw limited use between 1988 and
+- 1995 when it was made obsolete by the PCI bus.
+-
+- Say Y here if you are building a kernel for an EISA-based machine.
+-
+- Otherwise, say N.
+
+ config MCA
+ bool
+- help
+- MicroChannel Architecture is found in some IBM PS/2 machines and
+- laptops. It is a bus system similar to PCI or ISA. See
+- <file:Documentation/mca.txt> (and especially the web page given
+- there) before attempting to build an MCA bus kernel.
+
+ config PCMCIA
+ tristate
+- ---help---
++ help
+ Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
+ computer. These are credit-card size devices such as network cards,
+ modems or hard drives often used with laptops computers. There are
+@@ -356,10 +322,10 @@ config PCI
+ bool "PCI support"
+ select ARCH_SUPPORTS_MSI
+ help
+- Find out whether you have a PCI motherboard. PCI is the name of a
+- bus system, i.e. the way the CPU talks to the other stuff inside
+- your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
+- VESA. If you have PCI, say Y, otherwise N.
++ Find out whether your system includes a PCI bus. PCI is the name of
++ a bus system, i.e. the way the CPU talks to the other stuff inside
++ your box. If you say Y here, the kernel will include drivers and
++ infrastructure code to support PCI bus devices.
+
+ config PCI_DOMAINS
+ def_bool PCI
+@@ -379,49 +345,19 @@ 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.
+-config SPARC32_COMPAT
+- bool "Kernel support for Linux/Sparc 32bit binary compatibility"
+- help
+- This allows you to run 32-bit binaries on your Ultra.
+- Everybody wants this; say Y.
+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
+
+ config COMPAT
+ bool
+- depends on SPARC32_COMPAT
default y
select COMPAT_BINFMT_ELF
@@ -220998,6 +272127,17 @@
endmenu
+@@ -431,8 +367,8 @@ config SCHED_SMT
+ default y
+ help
+ SMT scheduler support improves the CPU scheduler's decision making
+- when dealing with UltraSPARC cpus at a cost of slightly increased
+- overhead in some places. If unsure say N here.
++ when dealing with SPARC cpus at a cost of slightly increased overhead
++ in some places. If unsure say N here.
+
+ config SCHED_MC
+ bool "Multi-core scheduler support"
diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile
index f0c22f8..9cb75c8 100644
--- a/arch/sparc64/Makefile
@@ -221011,7 +272151,7 @@
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
+index 9d4bd22..aff93c9 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
@@ -221019,8 +272159,8 @@
# 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
++# Linux kernel version: 2.6.25
++# Sat Apr 26 03:11:06 2008
#
CONFIG_SPARC=y
CONFIG_SPARC64=y
@@ -221059,16 +272199,33 @@
CONFIG_GENERIC_HARDIRQS=y
#
-@@ -152,6 +152,8 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
+@@ -152,6 +152,10 @@ 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_NUMA=y
++CONFIG_NODES_SHIFT=4
++CONFIG_NODES_SPAN_OTHER_NODES=y
+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
+@@ -160,12 +164,14 @@ CONFIG_SELECT_MEMORY_MODEL=y
+ # CONFIG_DISCONTIGMEM_MANUAL is not set
+ CONFIG_SPARSEMEM_MANUAL=y
+ CONFIG_SPARSEMEM=y
++CONFIG_NEED_MULTIPLE_NODES=y
+ CONFIG_HAVE_MEMORY_PRESENT=y
+ # CONFIG_SPARSEMEM_STATIC is not set
+ CONFIG_SPARSEMEM_EXTREME=y
+ CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+ CONFIG_SPARSEMEM_VMEMMAP=y
+ CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_MIGRATION=y
+ CONFIG_RESOURCES_64BIT=y
+ CONFIG_ZONE_DMA_FLAG=0
+ CONFIG_NR_QUICK=1
+@@ -182,9 +188,6 @@ CONFIG_PCI_MSI=y
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
CONFIG_SUN_OPENPROMFS=m
@@ -221078,12 +272235,11 @@
#
# Executable file formats
-@@ -192,13 +191,14 @@ CONFIG_COMPAT=y
+@@ -192,13 +195,13 @@ 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
@@ -221095,7 +272251,7 @@
# CONFIG_CMDLINE_BOOL is not set
#
-@@ -263,8 +263,10 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=m
+@@ -263,8 +266,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
@@ -221106,7 +272262,7 @@
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
CONFIG_IP_DCCP=m
-@@ -368,7 +370,7 @@ CONFIG_IDE=y
+@@ -368,7 +373,7 @@ CONFIG_IDE=y
CONFIG_BLK_DEV_IDE=y
#
@@ -221115,7 +272271,7 @@
#
# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_BLK_DEV_IDEDISK=y
-@@ -384,7 +386,6 @@ CONFIG_IDE_PROC_FS=y
+@@ -384,7 +389,6 @@ CONFIG_IDE_PROC_FS=y
#
# IDE chipset support/bugfixes
#
@@ -221123,7 +272279,7 @@
# CONFIG_BLK_DEV_PLATFORM is not set
CONFIG_BLK_DEV_IDEDMA_SFF=y
-@@ -422,7 +423,7 @@ CONFIG_BLK_DEV_ALI15X3=y
+@@ -422,7 +426,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
@@ -221132,7 +272288,7 @@
# CONFIG_BLK_DEV_HD is not set
#
-@@ -588,7 +589,6 @@ CONFIG_E1000_NAPI=y
+@@ -588,7 +592,6 @@ CONFIG_E1000_NAPI=y
# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
@@ -221140,7 +272296,7 @@
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=m
CONFIG_BNX2=m
-@@ -613,6 +613,7 @@ CONFIG_NIU=m
+@@ -613,6 +616,7 @@ CONFIG_NIU=m
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
@@ -221148,7 +272304,29 @@
#
# USB Network Adapters
-@@ -788,7 +789,6 @@ CONFIG_I2C_ALGOBIT=y
+@@ -745,13 +749,7 @@ CONFIG_DEVPORT=y
+ CONFIG_I2C=y
+ CONFIG_I2C_BOARDINFO=y
+ # CONFIG_I2C_CHARDEV is not set
+-
+-#
+-# I2C Algorithms
+-#
+ CONFIG_I2C_ALGOBIT=y
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+
+ #
+ # I2C Hardware Bus support
+@@ -779,6 +777,7 @@ CONFIG_I2C_ALGOBIT=y
+ # CONFIG_I2C_VIA is not set
+ # CONFIG_I2C_VIAPRO is not set
+ # CONFIG_I2C_VOODOO3 is not set
++# CONFIG_I2C_PCA_PLATFORM is not set
+
+ #
+ # Miscellaneous I2C Chip support
+@@ -788,7 +787,6 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -221156,7 +272334,7 @@
# 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
+@@ -870,6 +868,7 @@ CONFIG_SSB_POSSIBLE=y
# Multifunction device drivers
#
# CONFIG_MFD_SM501 is not set
@@ -221164,7 +272342,26 @@
#
# Multimedia devices
-@@ -1220,10 +1221,6 @@ CONFIG_USB_STORAGE=m
+@@ -1025,6 +1024,7 @@ CONFIG_SND_ALI5451=m
+ # CONFIG_SND_AU8810 is not set
+ # CONFIG_SND_AU8820 is not set
+ # CONFIG_SND_AU8830 is not set
++# CONFIG_SND_AW2 is not set
+ # CONFIG_SND_AZT3328 is not set
+ # CONFIG_SND_BT87X is not set
+ # CONFIG_SND_CA0106 is not set
+@@ -1096,10 +1096,6 @@ CONFIG_SND_SUN_CS4231=m
+ # CONFIG_SND_SOC is not set
+
+ #
+-# SoC Audio support for SuperH
+-#
+-
+-#
+ # ALSA SoC audio for Freescale SOCs
+ #
+
+@@ -1220,10 +1216,6 @@ CONFIG_USB_STORAGE=m
# CONFIG_NEW_LEDS is not set
# CONFIG_INFINIBAND is not set
# CONFIG_RTC_CLASS is not set
@@ -221175,7 +272372,7 @@
# CONFIG_UIO is not set
#
-@@ -1400,6 +1397,7 @@ CONFIG_SCHEDSTATS=y
+@@ -1400,6 +1392,7 @@ CONFIG_SCHEDSTATS=y
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
@@ -221183,7 +272380,7 @@
# 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
+@@ -1426,53 +1419,82 @@ CONFIG_ASYNC_CORE=m
CONFIG_ASYNC_MEMCPY=m
CONFIG_ASYNC_XOR=m
CONFIG_CRYPTO=y
@@ -221294,16 +272491,16 @@
# 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
+@@ -1493,3 +1515,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
+index 1bf5b18..ec4f5eb 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
-@@ -10,7 +10,7 @@ extra-y := head.o init_task.o vmlinux.lds
+@@ -10,31 +10,23 @@ 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 \
@@ -221312,17 +272509,24 @@
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_STACKTRACE) += stacktrace.o
+-obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o \
++obj-$(CONFIG_PCI) += ebus.o pci_common.o \
+ pci_psycho.o pci_sabre.o pci_schizo.o \
+ pci_sun4v.o pci_sun4v_asm.o pci_fire.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_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o
-obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o
++obj-$(CONFIG_COMPAT) += sys32.o sys_sparc32.o signal32.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_KPROBES) += kprobes.o
+ 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-$(CONFIG_AUDIT)$(CONFIG_SPARC32_COMPAT) += compat_audit.o
++obj-$(CONFIG_AUDIT)$(CONFIG_COMPAT) += compat_audit.o
obj-y += $(obj-yy)
-
-ifdef CONFIG_SUNOS_EMUL
@@ -221332,6 +272536,38 @@
- obj-y += sys_sunos32.o sunos_ioctl32.o
- endif
-endif
++obj-$(CONFIG_KGDB) += kgdb.o
+diff --git a/arch/sparc64/kernel/audit.c b/arch/sparc64/kernel/audit.c
+index 24d7f4b..8fff0ac 100644
+--- a/arch/sparc64/kernel/audit.c
++++ b/arch/sparc64/kernel/audit.c
+@@ -30,7 +30,7 @@ static unsigned signal_class[] = {
+
+ int audit_classify_arch(int arch)
+ {
+-#ifdef CONFIG_SPARC32_COMPAT
++#ifdef CONFIG_COMPAT
+ if (arch == AUDIT_ARCH_SPARC)
+ return 1;
+ #endif
+@@ -39,7 +39,7 @@ int audit_classify_arch(int arch)
+
+ int audit_classify_syscall(int abi, unsigned syscall)
+ {
+-#ifdef CONFIG_SPARC32_COMPAT
++#ifdef CONFIG_COMPAT
+ extern int sparc32_classify_syscall(unsigned);
+ if (abi == AUDIT_ARCH_SPARC)
+ return sparc32_classify_syscall(syscall);
+@@ -60,7 +60,7 @@ int audit_classify_syscall(int abi, unsigned syscall)
+
+ static int __init audit_classes_init(void)
+ {
+-#ifdef CONFIG_SPARC32_COMPAT
++#ifdef CONFIG_COMPAT
+ extern __u32 sparc32_dir_class[];
+ extern __u32 sparc32_write_class[];
+ extern __u32 sparc32_read_class[];
diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
deleted file mode 100644
index 9877f2d..0000000
@@ -221757,6 +272993,591 @@
-
-module_init(init_aout32_binfmt);
-module_exit(exit_aout32_binfmt);
+diff --git a/arch/sparc64/kernel/cherrs.S b/arch/sparc64/kernel/cherrs.S
+new file mode 100644
+index 0000000..89afebd
+--- /dev/null
++++ b/arch/sparc64/kernel/cherrs.S
+@@ -0,0 +1,579 @@
++ /* These get patched into the trap table at boot time
++ * once we know we have a cheetah processor.
++ */
++ .globl cheetah_fecc_trap_vector
++ .type cheetah_fecc_trap_vector,#function
++cheetah_fecc_trap_vector:
++ membar #Sync
++ ldxa [%g0] ASI_DCU_CONTROL_REG, %g1
++ andn %g1, DCU_DC | DCU_IC, %g1
++ stxa %g1, [%g0] ASI_DCU_CONTROL_REG
++ membar #Sync
++ sethi %hi(cheetah_fast_ecc), %g2
++ jmpl %g2 + %lo(cheetah_fast_ecc), %g0
++ mov 0, %g1
++ .size cheetah_fecc_trap_vector,.-cheetah_fecc_trap_vector
++
++ .globl cheetah_fecc_trap_vector_tl1
++ .type cheetah_fecc_trap_vector_tl1,#function
++cheetah_fecc_trap_vector_tl1:
++ membar #Sync
++ ldxa [%g0] ASI_DCU_CONTROL_REG, %g1
++ andn %g1, DCU_DC | DCU_IC, %g1
++ stxa %g1, [%g0] ASI_DCU_CONTROL_REG
++ membar #Sync
++ sethi %hi(cheetah_fast_ecc), %g2
++ jmpl %g2 + %lo(cheetah_fast_ecc), %g0
++ mov 1, %g1
++ .size cheetah_fecc_trap_vector_tl1,.-cheetah_fecc_trap_vector_tl1
++
++ .globl cheetah_cee_trap_vector
++ .type cheetah_cee_trap_vector,#function
++cheetah_cee_trap_vector:
++ membar #Sync
++ ldxa [%g0] ASI_DCU_CONTROL_REG, %g1
++ andn %g1, DCU_IC, %g1
++ stxa %g1, [%g0] ASI_DCU_CONTROL_REG
++ membar #Sync
++ sethi %hi(cheetah_cee), %g2
++ jmpl %g2 + %lo(cheetah_cee), %g0
++ mov 0, %g1
++ .size cheetah_cee_trap_vector,.-cheetah_cee_trap_vector
++
++ .globl cheetah_cee_trap_vector_tl1
++ .type cheetah_cee_trap_vector_tl1,#function
++cheetah_cee_trap_vector_tl1:
++ membar #Sync
++ ldxa [%g0] ASI_DCU_CONTROL_REG, %g1
++ andn %g1, DCU_IC, %g1
++ stxa %g1, [%g0] ASI_DCU_CONTROL_REG
++ membar #Sync
++ sethi %hi(cheetah_cee), %g2
++ jmpl %g2 + %lo(cheetah_cee), %g0
++ mov 1, %g1
++ .size cheetah_cee_trap_vector_tl1,.-cheetah_cee_trap_vector_tl1
++
++ .globl cheetah_deferred_trap_vector
++ .type cheetah_deferred_trap_vector,#function
++cheetah_deferred_trap_vector:
++ membar #Sync
++ ldxa [%g0] ASI_DCU_CONTROL_REG, %g1;
++ andn %g1, DCU_DC | DCU_IC, %g1;
++ stxa %g1, [%g0] ASI_DCU_CONTROL_REG;
++ membar #Sync;
++ sethi %hi(cheetah_deferred_trap), %g2
++ jmpl %g2 + %lo(cheetah_deferred_trap), %g0
++ mov 0, %g1
++ .size cheetah_deferred_trap_vector,.-cheetah_deferred_trap_vector
++
++ .globl cheetah_deferred_trap_vector_tl1
++ .type cheetah_deferred_trap_vector_tl1,#function
++cheetah_deferred_trap_vector_tl1:
++ membar #Sync;
++ ldxa [%g0] ASI_DCU_CONTROL_REG, %g1;
++ andn %g1, DCU_DC | DCU_IC, %g1;
++ stxa %g1, [%g0] ASI_DCU_CONTROL_REG;
++ membar #Sync;
++ sethi %hi(cheetah_deferred_trap), %g2
++ jmpl %g2 + %lo(cheetah_deferred_trap), %g0
++ mov 1, %g1
++ .size cheetah_deferred_trap_vector_tl1,.-cheetah_deferred_trap_vector_tl1
++
++ /* Cheetah+ specific traps. These are for the new I/D cache parity
++ * error traps. The first argument to cheetah_plus_parity_handler
++ * is encoded as follows:
++ *
++ * Bit0: 0=dcache,1=icache
++ * Bit1: 0=recoverable,1=unrecoverable
++ */
++ .globl cheetah_plus_dcpe_trap_vector
++ .type cheetah_plus_dcpe_trap_vector,#function
++cheetah_plus_dcpe_trap_vector:
++ membar #Sync
++ sethi %hi(do_cheetah_plus_data_parity), %g7
++ jmpl %g7 + %lo(do_cheetah_plus_data_parity), %g0
++ nop
++ nop
++ nop
++ nop
++ nop
++ .size cheetah_plus_dcpe_trap_vector,.-cheetah_plus_dcpe_trap_vector
++
++ .type do_cheetah_plus_data_parity,#function
++do_cheetah_plus_data_parity:
++ rdpr %pil, %g2
++ wrpr %g0, 15, %pil
++ ba,pt %xcc, etrap_irq
++ rd %pc, %g7
++#ifdef CONFIG_TRACE_IRQFLAGS
++ call trace_hardirqs_off
++ nop
++#endif
++ mov 0x0, %o0
++ call cheetah_plus_parity_error
++ add %sp, PTREGS_OFF, %o1
++ ba,a,pt %xcc, rtrap_irq
++ .size do_cheetah_plus_data_parity,.-do_cheetah_plus_data_parity
++
++ .globl cheetah_plus_dcpe_trap_vector_tl1
++ .type cheetah_plus_dcpe_trap_vector_tl1,#function
++cheetah_plus_dcpe_trap_vector_tl1:
++ membar #Sync
++ wrpr PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate
++ sethi %hi(do_dcpe_tl1), %g3
++ jmpl %g3 + %lo(do_dcpe_tl1), %g0
++ nop
++ nop
++ nop
++ nop
++ .size cheetah_plus_dcpe_trap_vector_tl1,.-cheetah_plus_dcpe_trap_vector_tl1
++
++ .globl cheetah_plus_icpe_trap_vector
++ .type cheetah_plus_icpe_trap_vector,#function
++cheetah_plus_icpe_trap_vector:
++ membar #Sync
++ sethi %hi(do_cheetah_plus_insn_parity), %g7
++ jmpl %g7 + %lo(do_cheetah_plus_insn_parity), %g0
++ nop
++ nop
++ nop
++ nop
++ nop
++ .size cheetah_plus_icpe_trap_vector,.-cheetah_plus_icpe_trap_vector
++
++ .type do_cheetah_plus_insn_parity,#function
++do_cheetah_plus_insn_parity:
++ rdpr %pil, %g2
++ wrpr %g0, 15, %pil
++ ba,pt %xcc, etrap_irq
++ rd %pc, %g7
++#ifdef CONFIG_TRACE_IRQFLAGS
++ call trace_hardirqs_off
++ nop
++#endif
++ mov 0x1, %o0
++ call cheetah_plus_parity_error
++ add %sp, PTREGS_OFF, %o1
++ ba,a,pt %xcc, rtrap_irq
++ .size do_cheetah_plus_insn_parity,.-do_cheetah_plus_insn_parity
++
++ .globl cheetah_plus_icpe_trap_vector_tl1
++ .type cheetah_plus_icpe_trap_vector_tl1,#function
++cheetah_plus_icpe_trap_vector_tl1:
++ membar #Sync
++ wrpr PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate
++ sethi %hi(do_icpe_tl1), %g3
++ jmpl %g3 + %lo(do_icpe_tl1), %g0
++ nop
++ nop
++ nop
++ nop
++ .size cheetah_plus_icpe_trap_vector_tl1,.-cheetah_plus_icpe_trap_vector_tl1
++
++ /* If we take one of these traps when tl >= 1, then we
++ * jump to interrupt globals. If some trap level above us
++ * was also using interrupt globals, we cannot recover.
++ * We may use all interrupt global registers except %g6.
++ */
++ .globl do_dcpe_tl1
++ .type do_dcpe_tl1,#function
++do_dcpe_tl1:
++ rdpr %tl, %g1 ! Save original trap level
++ mov 1, %g2 ! Setup TSTATE checking loop
++ sethi %hi(TSTATE_IG), %g3 ! TSTATE mask bit
++1: wrpr %g2, %tl ! Set trap level to check
++ rdpr %tstate, %g4 ! Read TSTATE for this level
++ andcc %g4, %g3, %g0 ! Interrupt globals in use?
++ bne,a,pn %xcc, do_dcpe_tl1_fatal ! Yep, irrecoverable
++ wrpr %g1, %tl ! Restore original trap level
++ add %g2, 1, %g2 ! Next trap level
++ cmp %g2, %g1 ! Hit them all yet?
++ ble,pt %icc, 1b ! Not yet
++ nop
++ wrpr %g1, %tl ! Restore original trap level
++do_dcpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */
++ sethi %hi(dcache_parity_tl1_occurred), %g2
++ lduw [%g2 + %lo(dcache_parity_tl1_occurred)], %g1
++ add %g1, 1, %g1
++ stw %g1, [%g2 + %lo(dcache_parity_tl1_occurred)]
++ /* Reset D-cache parity */
++ sethi %hi(1 << 16), %g1 ! D-cache size
++ mov (1 << 5), %g2 ! D-cache line size
++ sub %g1, %g2, %g1 ! Move down 1 cacheline
++1: srl %g1, 14, %g3 ! Compute UTAG
++ membar #Sync
++ stxa %g3, [%g1] ASI_DCACHE_UTAG
++ membar #Sync
++ sub %g2, 8, %g3 ! 64-bit data word within line
++2: membar #Sync
++ stxa %g0, [%g1 + %g3] ASI_DCACHE_DATA
++ membar #Sync
++ subcc %g3, 8, %g3 ! Next 64-bit data word
++ bge,pt %icc, 2b
++ nop
++ subcc %g1, %g2, %g1 ! Next cacheline
++ bge,pt %icc, 1b
++ nop
++ ba,pt %xcc, dcpe_icpe_tl1_common
++ nop
++
++do_dcpe_tl1_fatal:
++ sethi %hi(1f), %g7
++ ba,pt %xcc, etraptl1
++1: or %g7, %lo(1b), %g7
++ mov 0x2, %o0
++ call cheetah_plus_parity_error
++ add %sp, PTREGS_OFF, %o1
++ ba,pt %xcc, rtrap
++ nop
++ .size do_dcpe_tl1,.-do_dcpe_tl1
++
++ .globl do_icpe_tl1
++ .type do_icpe_tl1,#function
++do_icpe_tl1:
++ rdpr %tl, %g1 ! Save original trap level
++ mov 1, %g2 ! Setup TSTATE checking loop
++ sethi %hi(TSTATE_IG), %g3 ! TSTATE mask bit
++1: wrpr %g2, %tl ! Set trap level to check
++ rdpr %tstate, %g4 ! Read TSTATE for this level
++ andcc %g4, %g3, %g0 ! Interrupt globals in use?
++ bne,a,pn %xcc, do_icpe_tl1_fatal ! Yep, irrecoverable
++ wrpr %g1, %tl ! Restore original trap level
++ add %g2, 1, %g2 ! Next trap level
++ cmp %g2, %g1 ! Hit them all yet?
++ ble,pt %icc, 1b ! Not yet
++ nop
++ wrpr %g1, %tl ! Restore original trap level
++do_icpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */
++ sethi %hi(icache_parity_tl1_occurred), %g2
++ lduw [%g2 + %lo(icache_parity_tl1_occurred)], %g1
++ add %g1, 1, %g1
++ stw %g1, [%g2 + %lo(icache_parity_tl1_occurred)]
++ /* Flush I-cache */
++ sethi %hi(1 << 15), %g1 ! I-cache size
++ mov (1 << 5), %g2 ! I-cache line size
++ sub %g1, %g2, %g1
++1: or %g1, (2 << 3), %g3
++ stxa %g0, [%g3] ASI_IC_TAG
++ membar #Sync
++ subcc %g1, %g2, %g1
++ bge,pt %icc, 1b
++ nop
++ ba,pt %xcc, dcpe_icpe_tl1_common
++ nop
++
++do_icpe_tl1_fatal:
++ sethi %hi(1f), %g7
++ ba,pt %xcc, etraptl1
++1: or %g7, %lo(1b), %g7
++ mov 0x3, %o0
++ call cheetah_plus_parity_error
++ add %sp, PTREGS_OFF, %o1
++ ba,pt %xcc, rtrap
++ nop
++ .size do_icpe_tl1,.-do_icpe_tl1
++
++ .type dcpe_icpe_tl1_common,#function
++dcpe_icpe_tl1_common:
++ /* Flush D-cache, re-enable D/I caches in DCU and finally
++ * retry the trapping instruction.
++ */
++ sethi %hi(1 << 16), %g1 ! D-cache size
++ mov (1 << 5), %g2 ! D-cache line size
++ sub %g1, %g2, %g1
++1: stxa %g0, [%g1] ASI_DCACHE_TAG
++ membar #Sync
++ subcc %g1, %g2, %g1
++ bge,pt %icc, 1b
++ nop
++ ldxa [%g0] ASI_DCU_CONTROL_REG, %g1
++ or %g1, (DCU_DC | DCU_IC), %g1
++ stxa %g1, [%g0] ASI_DCU_CONTROL_REG
++ membar #Sync
++ retry
++ .size dcpe_icpe_tl1_common,.-dcpe_icpe_tl1_common
++
++ /* Capture I/D/E-cache state into per-cpu error scoreboard.
++ *
++ * %g1: (TL>=0) ? 1 : 0
++ * %g2: scratch
++ * %g3: scratch
++ * %g4: AFSR
++ * %g5: AFAR
++ * %g6: unused, will have current thread ptr after etrap
++ * %g7: scratch
++ */
++ .type __cheetah_log_error,#function
++__cheetah_log_error:
++ /* Put "TL1" software bit into AFSR. */
++ and %g1, 0x1, %g1
++ sllx %g1, 63, %g2
++ or %g4, %g2, %g4
++
++ /* Get log entry pointer for this cpu at this trap level. */
++ BRANCH_IF_JALAPENO(g2,g3,50f)
++ ldxa [%g0] ASI_SAFARI_CONFIG, %g2
++ srlx %g2, 17, %g2
++ ba,pt %xcc, 60f
++ and %g2, 0x3ff, %g2
++
++50: ldxa [%g0] ASI_JBUS_CONFIG, %g2
++ srlx %g2, 17, %g2
++ and %g2, 0x1f, %g2
++
++60: sllx %g2, 9, %g2
++ sethi %hi(cheetah_error_log), %g3
++ ldx [%g3 + %lo(cheetah_error_log)], %g3
++ brz,pn %g3, 80f
++ nop
++
++ add %g3, %g2, %g3
++ sllx %g1, 8, %g1
++ add %g3, %g1, %g1
++
++ /* %g1 holds pointer to the top of the logging scoreboard */
++ ldx [%g1 + 0x0], %g7
++ cmp %g7, -1
++ bne,pn %xcc, 80f
++ nop
++
++ stx %g4, [%g1 + 0x0]
++ stx %g5, [%g1 + 0x8]
++ add %g1, 0x10, %g1
++
++ /* %g1 now points to D-cache logging area */
++ set 0x3ff8, %g2 /* DC_addr mask */
++ and %g5, %g2, %g2 /* DC_addr bits of AFAR */
++ srlx %g5, 12, %g3
++ or %g3, 1, %g3 /* PHYS tag + valid */
++
++10: ldxa [%g2] ASI_DCACHE_TAG, %g7
++ cmp %g3, %g7 /* TAG match? */
++ bne,pt %xcc, 13f
++ nop
++
++ /* Yep, what we want, capture state. */
++ stx %g2, [%g1 + 0x20]
++ stx %g7, [%g1 + 0x28]
++
++ /* A membar Sync is required before and after utag access. */
++ membar #Sync
++ ldxa [%g2] ASI_DCACHE_UTAG, %g7
++ membar #Sync
++ stx %g7, [%g1 + 0x30]
++ ldxa [%g2] ASI_DCACHE_SNOOP_TAG, %g7
++ stx %g7, [%g1 + 0x38]
++ clr %g3
++
++12: ldxa [%g2 + %g3] ASI_DCACHE_DATA, %g7
++ stx %g7, [%g1]
++ add %g3, (1 << 5), %g3
++ cmp %g3, (4 << 5)
++ bl,pt %xcc, 12b
++ add %g1, 0x8, %g1
++
++ ba,pt %xcc, 20f
++ add %g1, 0x20, %g1
++
++13: sethi %hi(1 << 14), %g7
++ add %g2, %g7, %g2
++ srlx %g2, 14, %g7
++ cmp %g7, 4
++ bl,pt %xcc, 10b
++ nop
++
++ add %g1, 0x40, %g1
++
++ /* %g1 now points to I-cache logging area */
++20: set 0x1fe0, %g2 /* IC_addr mask */
++ and %g5, %g2, %g2 /* IC_addr bits of AFAR */
++ sllx %g2, 1, %g2 /* IC_addr[13:6]==VA[12:5] */
++ srlx %g5, (13 - 8), %g3 /* Make PTAG */
++ andn %g3, 0xff, %g3 /* Mask off undefined bits */
++
++21: ldxa [%g2] ASI_IC_TAG, %g7
++ andn %g7, 0xff, %g7
++ cmp %g3, %g7
++ bne,pt %xcc, 23f
++ nop
++
++ /* Yep, what we want, capture state. */
++ stx %g2, [%g1 + 0x40]
++ stx %g7, [%g1 + 0x48]
++ add %g2, (1 << 3), %g2
++ ldxa [%g2] ASI_IC_TAG, %g7
++ add %g2, (1 << 3), %g2
++ stx %g7, [%g1 + 0x50]
++ ldxa [%g2] ASI_IC_TAG, %g7
++ add %g2, (1 << 3), %g2
++ stx %g7, [%g1 + 0x60]
++ ldxa [%g2] ASI_IC_TAG, %g7
++ stx %g7, [%g1 + 0x68]
++ sub %g2, (3 << 3), %g2
++ ldxa [%g2] ASI_IC_STAG, %g7
++ stx %g7, [%g1 + 0x58]
++ clr %g3
++ srlx %g2, 2, %g2
++
++22: ldxa [%g2 + %g3] ASI_IC_INSTR, %g7
++ stx %g7, [%g1]
++ add %g3, (1 << 3), %g3
++ cmp %g3, (8 << 3)
++ bl,pt %xcc, 22b
++ add %g1, 0x8, %g1
++
++ ba,pt %xcc, 30f
++ add %g1, 0x30, %g1
++
++23: sethi %hi(1 << 14), %g7
++ add %g2, %g7, %g2
++ srlx %g2, 14, %g7
++ cmp %g7, 4
++ bl,pt %xcc, 21b
++ nop
++
++ add %g1, 0x70, %g1
++
++ /* %g1 now points to E-cache logging area */
++30: andn %g5, (32 - 1), %g2
++ stx %g2, [%g1 + 0x20]
++ ldxa [%g2] ASI_EC_TAG_DATA, %g7
++ stx %g7, [%g1 + 0x28]
++ ldxa [%g2] ASI_EC_R, %g0
++ clr %g3
++
++31: ldxa [%g3] ASI_EC_DATA, %g7
++ stx %g7, [%g1 + %g3]
++ add %g3, 0x8, %g3
++ cmp %g3, 0x20
++
++ bl,pt %xcc, 31b
++ nop
++80:
++ rdpr %tt, %g2
++ cmp %g2, 0x70
++ be c_fast_ecc
++ cmp %g2, 0x63
++ be c_cee
++ nop
++ ba,pt %xcc, c_deferred
++ .size __cheetah_log_error,.-__cheetah_log_error
++
++ /* Cheetah FECC trap handling, we get here from tl{0,1}_fecc
++ * in the trap table. That code has done a memory barrier
++ * and has disabled both the I-cache and D-cache in the DCU
++ * control register. The I-cache is disabled so that we may
++ * capture the corrupted cache line, and the D-cache is disabled
++ * because corrupt data may have been placed there and we don't
++ * want to reference it.
++ *
++ * %g1 is one if this trap occurred at %tl >= 1.
++ *
++ * Next, we turn off error reporting so that we don't recurse.
++ */
++ .globl cheetah_fast_ecc
++ .type cheetah_fast_ecc,#function
++cheetah_fast_ecc:
++ ldxa [%g0] ASI_ESTATE_ERROR_EN, %g2
++ andn %g2, ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN, %g2
++ stxa %g2, [%g0] ASI_ESTATE_ERROR_EN
++ membar #Sync
++
++ /* Fetch and clear AFSR/AFAR */
++ ldxa [%g0] ASI_AFSR, %g4
++ ldxa [%g0] ASI_AFAR, %g5
++ stxa %g4, [%g0] ASI_AFSR
++ membar #Sync
++
++ ba,pt %xcc, __cheetah_log_error
++ nop
++ .size cheetah_fast_ecc,.-cheetah_fast_ecc
++
++ .type c_fast_ecc,#function
++c_fast_ecc:
++ rdpr %pil, %g2
++ wrpr %g0, 15, %pil
++ ba,pt %xcc, etrap_irq
++ rd %pc, %g7
++#ifdef CONFIG_TRACE_IRQFLAGS
++ call trace_hardirqs_off
++ nop
++#endif
++ mov %l4, %o1
++ mov %l5, %o2
++ call cheetah_fecc_handler
++ add %sp, PTREGS_OFF, %o0
++ ba,a,pt %xcc, rtrap_irq
++ .size c_fast_ecc,.-c_fast_ecc
++
++ /* Our caller has disabled I-cache and performed membar Sync. */
++ .globl cheetah_cee
++ .type cheetah_cee,#function
++cheetah_cee:
++ ldxa [%g0] ASI_ESTATE_ERROR_EN, %g2
++ andn %g2, ESTATE_ERROR_CEEN, %g2
++ stxa %g2, [%g0] ASI_ESTATE_ERROR_EN
++ membar #Sync
++
++ /* Fetch and clear AFSR/AFAR */
++ ldxa [%g0] ASI_AFSR, %g4
++ ldxa [%g0] ASI_AFAR, %g5
++ stxa %g4, [%g0] ASI_AFSR
++ membar #Sync
++
++ ba,pt %xcc, __cheetah_log_error
++ nop
++ .size cheetah_cee,.-cheetah_cee
++
++ .type c_cee,#function
++c_cee:
++ rdpr %pil, %g2
++ wrpr %g0, 15, %pil
++ ba,pt %xcc, etrap_irq
++ rd %pc, %g7
++#ifdef CONFIG_TRACE_IRQFLAGS
++ call trace_hardirqs_off
++ nop
++#endif
++ mov %l4, %o1
++ mov %l5, %o2
++ call cheetah_cee_handler
++ add %sp, PTREGS_OFF, %o0
++ ba,a,pt %xcc, rtrap_irq
++ .size c_cee,.-c_cee
++
++ /* Our caller has disabled I-cache+D-cache and performed membar Sync. */
++ .globl cheetah_deferred_trap
++ .type cheetah_deferred_trap,#function
++cheetah_deferred_trap:
++ ldxa [%g0] ASI_ESTATE_ERROR_EN, %g2
++ andn %g2, ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN, %g2
++ stxa %g2, [%g0] ASI_ESTATE_ERROR_EN
++ membar #Sync
++
++ /* Fetch and clear AFSR/AFAR */
++ ldxa [%g0] ASI_AFSR, %g4
++ ldxa [%g0] ASI_AFAR, %g5
++ stxa %g4, [%g0] ASI_AFSR
++ membar #Sync
++
++ ba,pt %xcc, __cheetah_log_error
++ nop
++ .size cheetah_deferred_trap,.-cheetah_deferred_trap
++
++ .type c_deferred,#function
++c_deferred:
++ rdpr %pil, %g2
++ wrpr %g0, 15, %pil
++ ba,pt %xcc, etrap_irq
++ rd %pc, %g7
++#ifdef CONFIG_TRACE_IRQFLAGS
++ call trace_hardirqs_off
++ nop
++#endif
++ mov %l4, %o1
++ mov %l5, %o2
++ call cheetah_deferred_handler
++ add %sp, PTREGS_OFF, %o0
++ ba,a,pt %xcc, rtrap_irq
++ .size c_deferred,.-c_deferred
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c
index 04ab81c..bc26322 100644
--- a/arch/sparc64/kernel/ebus.c
@@ -221770,139 +273591,1366 @@
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
+deleted file mode 100644
+index 49eca4b..0000000
--- 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
++++ /dev/null
+@@ -1,2633 +0,0 @@
+-/* $Id: entry.S,v 1.144 2002/02/09 19:49:30 davem Exp $
+- * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points.
+- *
+- * Copyright (C) 1995,1997 David S. Miller (davem at caip.rutgers.edu)
+- * Copyright (C) 1996 Eddie C. Dost (ecd at skynet.be)
+- * Copyright (C) 1996 Miguel de Icaza (miguel at nuclecu.unam.mx)
+- * Copyright (C) 1996,98,99 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- */
+-
+-#include <linux/errno.h>
+-
+-#include <asm/head.h>
+-#include <asm/asi.h>
+-#include <asm/smp.h>
+-#include <asm/ptrace.h>
+-#include <asm/page.h>
+-#include <asm/signal.h>
+-#include <asm/pgtable.h>
+-#include <asm/processor.h>
+-#include <asm/visasm.h>
+-#include <asm/estate.h>
+-#include <asm/auxio.h>
+-#include <asm/sfafsr.h>
+-#include <asm/pil.h>
+-#include <asm/unistd.h>
+-
+-#define curptr g6
+-
+- .text
+- .align 32
+-
+- /* This is trivial with the new code... */
+- .globl do_fpdis
+-do_fpdis:
+- sethi %hi(TSTATE_PEF), %g4
+- rdpr %tstate, %g5
+- andcc %g5, %g4, %g0
+- be,pt %xcc, 1f
+- nop
+- rd %fprs, %g5
+- andcc %g5, FPRS_FEF, %g0
+- be,pt %xcc, 1f
+- nop
+-
+- /* Legal state when DCR_IFPOE is set in Cheetah %dcr. */
+- sethi %hi(109f), %g7
+- 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
+-
+-1: TRAP_LOAD_THREAD_REG(%g6, %g1)
+- ldub [%g6 + TI_FPSAVED], %g5
+- wr %g0, FPRS_FEF, %fprs
+- andcc %g5, FPRS_FEF, %g0
+- be,a,pt %icc, 1f
+- clr %g7
+- ldx [%g6 + TI_GSR], %g7
+-1: andcc %g5, FPRS_DL, %g0
+- bne,pn %icc, 2f
+- fzero %f0
+- andcc %g5, FPRS_DU, %g0
+- bne,pn %icc, 1f
+- fzero %f2
+- faddd %f0, %f2, %f4
+- fmuld %f0, %f2, %f6
+- faddd %f0, %f2, %f8
+- fmuld %f0, %f2, %f10
+- faddd %f0, %f2, %f12
+- fmuld %f0, %f2, %f14
+- faddd %f0, %f2, %f16
+- fmuld %f0, %f2, %f18
+- faddd %f0, %f2, %f20
+- fmuld %f0, %f2, %f22
+- faddd %f0, %f2, %f24
+- fmuld %f0, %f2, %f26
+- faddd %f0, %f2, %f28
+- fmuld %f0, %f2, %f30
+- faddd %f0, %f2, %f32
+- fmuld %f0, %f2, %f34
+- faddd %f0, %f2, %f36
+- fmuld %f0, %f2, %f38
+- faddd %f0, %f2, %f40
+- fmuld %f0, %f2, %f42
+- faddd %f0, %f2, %f44
+- fmuld %f0, %f2, %f46
+- faddd %f0, %f2, %f48
+- fmuld %f0, %f2, %f50
+- faddd %f0, %f2, %f52
+- fmuld %f0, %f2, %f54
+- faddd %f0, %f2, %f56
+- fmuld %f0, %f2, %f58
+- b,pt %xcc, fpdis_exit2
+- faddd %f0, %f2, %f60
+-1: mov SECONDARY_CONTEXT, %g3
+- add %g6, TI_FPREGS + 0x80, %g1
+- faddd %f0, %f2, %f4
+- fmuld %f0, %f2, %f6
+-
+-661: ldxa [%g3] ASI_DMMU, %g5
+- .section .sun4v_1insn_patch, "ax"
+- .word 661b
+- ldxa [%g3] ASI_MMU, %g5
+- .previous
+-
+- sethi %hi(sparc64_kern_sec_context), %g2
+- ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
+-
+-661: stxa %g2, [%g3] ASI_DMMU
+- .section .sun4v_1insn_patch, "ax"
+- .word 661b
+- stxa %g2, [%g3] ASI_MMU
+- .previous
+-
+- membar #Sync
+- add %g6, TI_FPREGS + 0xc0, %g2
+- faddd %f0, %f2, %f8
+- fmuld %f0, %f2, %f10
+- membar #Sync
+- ldda [%g1] ASI_BLK_S, %f32
+- ldda [%g2] ASI_BLK_S, %f48
+- membar #Sync
+- faddd %f0, %f2, %f12
+- fmuld %f0, %f2, %f14
+- faddd %f0, %f2, %f16
+- fmuld %f0, %f2, %f18
+- faddd %f0, %f2, %f20
+- fmuld %f0, %f2, %f22
+- faddd %f0, %f2, %f24
+- fmuld %f0, %f2, %f26
+- faddd %f0, %f2, %f28
+- fmuld %f0, %f2, %f30
+- b,pt %xcc, fpdis_exit
+- nop
+-2: andcc %g5, FPRS_DU, %g0
+- bne,pt %icc, 3f
+- fzero %f32
+- mov SECONDARY_CONTEXT, %g3
+- fzero %f34
+-
+-661: ldxa [%g3] ASI_DMMU, %g5
+- .section .sun4v_1insn_patch, "ax"
+- .word 661b
+- ldxa [%g3] ASI_MMU, %g5
+- .previous
+-
+- add %g6, TI_FPREGS, %g1
+- sethi %hi(sparc64_kern_sec_context), %g2
+- ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
+-
+-661: stxa %g2, [%g3] ASI_DMMU
+- .section .sun4v_1insn_patch, "ax"
+- .word 661b
+- stxa %g2, [%g3] ASI_MMU
+- .previous
+-
+- membar #Sync
+- add %g6, TI_FPREGS + 0x40, %g2
+- faddd %f32, %f34, %f36
+- fmuld %f32, %f34, %f38
+- membar #Sync
+- ldda [%g1] ASI_BLK_S, %f0
+- ldda [%g2] ASI_BLK_S, %f16
+- membar #Sync
+- faddd %f32, %f34, %f40
+- fmuld %f32, %f34, %f42
+- faddd %f32, %f34, %f44
+- fmuld %f32, %f34, %f46
+- faddd %f32, %f34, %f48
+- fmuld %f32, %f34, %f50
+- faddd %f32, %f34, %f52
+- fmuld %f32, %f34, %f54
+- faddd %f32, %f34, %f56
+- fmuld %f32, %f34, %f58
+- faddd %f32, %f34, %f60
+- fmuld %f32, %f34, %f62
+- ba,pt %xcc, fpdis_exit
+- nop
+-3: mov SECONDARY_CONTEXT, %g3
+- add %g6, TI_FPREGS, %g1
+-
+-661: ldxa [%g3] ASI_DMMU, %g5
+- .section .sun4v_1insn_patch, "ax"
+- .word 661b
+- ldxa [%g3] ASI_MMU, %g5
+- .previous
+-
+- sethi %hi(sparc64_kern_sec_context), %g2
+- ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
+-
+-661: stxa %g2, [%g3] ASI_DMMU
+- .section .sun4v_1insn_patch, "ax"
+- .word 661b
+- stxa %g2, [%g3] ASI_MMU
+- .previous
+-
+- membar #Sync
+- mov 0x40, %g2
+- membar #Sync
+- ldda [%g1] ASI_BLK_S, %f0
+- ldda [%g1 + %g2] ASI_BLK_S, %f16
+- add %g1, 0x80, %g1
+- ldda [%g1] ASI_BLK_S, %f32
+- ldda [%g1 + %g2] ASI_BLK_S, %f48
+- membar #Sync
+-fpdis_exit:
+-
+-661: stxa %g5, [%g3] ASI_DMMU
+- .section .sun4v_1insn_patch, "ax"
+- .word 661b
+- stxa %g5, [%g3] ASI_MMU
+- .previous
+-
+- membar #Sync
+-fpdis_exit2:
+- wr %g7, 0, %gsr
+- ldx [%g6 + TI_XFSR], %fsr
+- rdpr %tstate, %g3
+- or %g3, %g4, %g3 ! anal...
+- wrpr %g3, %tstate
+- wr %g0, FPRS_FEF, %fprs ! clean DU/DL bits
+- retry
+-
+- .align 32
+-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
+-
+- .globl do_fpother_check_fitos
+- .align 32
+-do_fpother_check_fitos:
+- TRAP_LOAD_THREAD_REG(%g6, %g1)
+- sethi %hi(fp_other_bounce - 4), %g7
+- or %g7, %lo(fp_other_bounce - 4), %g7
+-
+- /* NOTE: Need to preserve %g7 until we fully commit
+- * to the fitos fixup.
+- */
+- stx %fsr, [%g6 + TI_XFSR]
+- rdpr %tstate, %g3
+- andcc %g3, TSTATE_PRIV, %g0
+- bne,pn %xcc, do_fptrap_after_fsr
+- nop
+- ldx [%g6 + TI_XFSR], %g3
+- srlx %g3, 14, %g1
+- and %g1, 7, %g1
+- cmp %g1, 2 ! Unfinished FP-OP
+- bne,pn %xcc, do_fptrap_after_fsr
+- sethi %hi(1 << 23), %g1 ! Inexact
+- andcc %g3, %g1, %g0
+- bne,pn %xcc, do_fptrap_after_fsr
+- rdpr %tpc, %g1
+- lduwa [%g1] ASI_AIUP, %g3 ! This cannot ever fail
+-#define FITOS_MASK 0xc1f83fe0
+-#define FITOS_COMPARE 0x81a01880
+- sethi %hi(FITOS_MASK), %g1
+- or %g1, %lo(FITOS_MASK), %g1
+- and %g3, %g1, %g1
+- sethi %hi(FITOS_COMPARE), %g2
+- or %g2, %lo(FITOS_COMPARE), %g2
+- cmp %g1, %g2
+- bne,pn %xcc, do_fptrap_after_fsr
+- nop
+- std %f62, [%g6 + TI_FPREGS + (62 * 4)]
+- sethi %hi(fitos_table_1), %g1
+- and %g3, 0x1f, %g2
+- or %g1, %lo(fitos_table_1), %g1
+- sllx %g2, 2, %g2
+- jmpl %g1 + %g2, %g0
+- ba,pt %xcc, fitos_emul_continue
+-
+-fitos_table_1:
+- fitod %f0, %f62
+- fitod %f1, %f62
+- fitod %f2, %f62
+- fitod %f3, %f62
+- fitod %f4, %f62
+- fitod %f5, %f62
+- fitod %f6, %f62
+- fitod %f7, %f62
+- fitod %f8, %f62
+- fitod %f9, %f62
+- fitod %f10, %f62
+- fitod %f11, %f62
+- fitod %f12, %f62
+- fitod %f13, %f62
+- fitod %f14, %f62
+- fitod %f15, %f62
+- fitod %f16, %f62
+- fitod %f17, %f62
+- fitod %f18, %f62
+- fitod %f19, %f62
+- fitod %f20, %f62
+- fitod %f21, %f62
+- fitod %f22, %f62
+- fitod %f23, %f62
+- fitod %f24, %f62
+- fitod %f25, %f62
+- fitod %f26, %f62
+- fitod %f27, %f62
+- fitod %f28, %f62
+- fitod %f29, %f62
+- fitod %f30, %f62
+- fitod %f31, %f62
+-
+-fitos_emul_continue:
+- sethi %hi(fitos_table_2), %g1
+- srl %g3, 25, %g2
+- or %g1, %lo(fitos_table_2), %g1
+- and %g2, 0x1f, %g2
+- sllx %g2, 2, %g2
+- jmpl %g1 + %g2, %g0
+- ba,pt %xcc, fitos_emul_fini
+-
+-fitos_table_2:
+- fdtos %f62, %f0
+- fdtos %f62, %f1
+- fdtos %f62, %f2
+- fdtos %f62, %f3
+- fdtos %f62, %f4
+- fdtos %f62, %f5
+- fdtos %f62, %f6
+- fdtos %f62, %f7
+- fdtos %f62, %f8
+- fdtos %f62, %f9
+- fdtos %f62, %f10
+- fdtos %f62, %f11
+- fdtos %f62, %f12
+- fdtos %f62, %f13
+- fdtos %f62, %f14
+- fdtos %f62, %f15
+- fdtos %f62, %f16
+- fdtos %f62, %f17
+- fdtos %f62, %f18
+- fdtos %f62, %f19
+- fdtos %f62, %f20
+- fdtos %f62, %f21
+- fdtos %f62, %f22
+- fdtos %f62, %f23
+- fdtos %f62, %f24
+- fdtos %f62, %f25
+- fdtos %f62, %f26
+- fdtos %f62, %f27
+- fdtos %f62, %f28
+- fdtos %f62, %f29
+- fdtos %f62, %f30
+- fdtos %f62, %f31
+-
+-fitos_emul_fini:
+- ldd [%g6 + TI_FPREGS + (62 * 4)], %f62
+- done
+-
+- .globl do_fptrap
+- .align 32
+-do_fptrap:
+- TRAP_LOAD_THREAD_REG(%g6, %g1)
+- stx %fsr, [%g6 + TI_XFSR]
+-do_fptrap_after_fsr:
+- ldub [%g6 + TI_FPSAVED], %g3
+- rd %fprs, %g1
+- or %g3, %g1, %g3
+- stb %g3, [%g6 + TI_FPSAVED]
+- rd %gsr, %g3
+- stx %g3, [%g6 + TI_GSR]
+- mov SECONDARY_CONTEXT, %g3
+-
+-661: ldxa [%g3] ASI_DMMU, %g5
+- .section .sun4v_1insn_patch, "ax"
+- .word 661b
+- ldxa [%g3] ASI_MMU, %g5
+- .previous
+-
+- sethi %hi(sparc64_kern_sec_context), %g2
+- ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
+-
+-661: stxa %g2, [%g3] ASI_DMMU
+- .section .sun4v_1insn_patch, "ax"
+- .word 661b
+- stxa %g2, [%g3] ASI_MMU
+- .previous
+-
+- membar #Sync
+- add %g6, TI_FPREGS, %g2
+- andcc %g1, FPRS_DL, %g0
+- be,pn %icc, 4f
+- mov 0x40, %g3
+- stda %f0, [%g2] ASI_BLK_S
+- stda %f16, [%g2 + %g3] ASI_BLK_S
+- andcc %g1, FPRS_DU, %g0
+- be,pn %icc, 5f
+-4: add %g2, 128, %g2
+- stda %f32, [%g2] ASI_BLK_S
+- stda %f48, [%g2 + %g3] ASI_BLK_S
+-5: mov SECONDARY_CONTEXT, %g1
+- membar #Sync
+-
+-661: stxa %g5, [%g1] ASI_DMMU
+- .section .sun4v_1insn_patch, "ax"
+- .word 661b
+- stxa %g5, [%g1] ASI_MMU
+- .previous
+-
+- membar #Sync
+- ba,pt %xcc, etrap
+- wr %g0, 0, %fprs
+-
+- /* The registers for cross calls will be:
+- *
+- * DATA 0: [low 32-bits] Address of function to call, jmp to this
+- * [high 32-bits] MMU Context Argument 0, place in %g5
+- * DATA 1: Address Argument 1, place in %g1
+- * DATA 2: Address Argument 2, place in %g7
+- *
+- * With this method we can do most of the cross-call tlb/cache
+- * flushing very quickly.
+- */
+- .text
+- .align 32
+- .globl do_ivec
+-do_ivec:
+- mov 0x40, %g3
+- ldxa [%g3 + %g0] ASI_INTR_R, %g3
+- sethi %hi(KERNBASE), %g4
+- cmp %g3, %g4
+- bgeu,pn %xcc, do_ivec_xcall
+- srlx %g3, 32, %g5
+- stxa %g0, [%g0] ASI_INTR_RECEIVE
+- membar #Sync
+-
+- sethi %hi(ivector_table_pa), %g2
+- ldx [%g2 + %lo(ivector_table_pa)], %g2
+- sllx %g3, 4, %g3
+- add %g2, %g3, %g3
+-
+- TRAP_LOAD_IRQ_WORK_PA(%g6, %g1)
+-
+- ldx [%g6], %g5
+- stxa %g5, [%g3] ASI_PHYS_USE_EC
+- stx %g3, [%g6]
+- wr %g0, 1 << PIL_DEVICE_IRQ, %set_softint
+- retry
+-do_ivec_xcall:
+- mov 0x50, %g1
+- ldxa [%g1 + %g0] ASI_INTR_R, %g1
+- srl %g3, 0, %g3
+-
+- mov 0x60, %g7
+- ldxa [%g7 + %g0] ASI_INTR_R, %g7
+- stxa %g0, [%g0] ASI_INTR_RECEIVE
+- membar #Sync
+- ba,pt %xcc, 1f
+- nop
+-
+- .align 32
+-1: jmpl %g3, %g0
+- nop
+-
+- .globl getcc, setcc
+-getcc:
+- ldx [%o0 + PT_V9_TSTATE], %o1
+- srlx %o1, 32, %o1
+- and %o1, 0xf, %o1
+- retl
+- stx %o1, [%o0 + PT_V9_G1]
+-setcc:
+- ldx [%o0 + PT_V9_TSTATE], %o1
+- ldx [%o0 + PT_V9_G1], %o2
+- or %g0, %ulo(TSTATE_ICC), %o3
+- sllx %o3, 32, %o3
+- andn %o1, %o3, %o1
+- sllx %o2, 32, %o2
+- and %o2, %o3, %o2
+- or %o1, %o2, %o1
+- retl
+- stx %o1, [%o0 + PT_V9_TSTATE]
+-
+- .globl utrap_trap
+-utrap_trap: /* %g3=handler,%g4=level */
+- TRAP_LOAD_THREAD_REG(%g6, %g1)
+- ldx [%g6 + TI_UTRAPS], %g1
+- brnz,pt %g1, invoke_utrap
+- nop
+-
+- ba,pt %xcc, etrap
+- rd %pc, %g7
+- mov %l4, %o1
+- 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
+-
+-invoke_utrap:
+- sllx %g3, 3, %g3
+- ldx [%g1 + %g3], %g1
+- save %sp, -128, %sp
+- rdpr %tstate, %l6
+- rdpr %cwp, %l7
+- andn %l6, TSTATE_CWP, %l6
+- wrpr %l6, %l7, %tstate
+- rdpr %tpc, %l6
+- rdpr %tnpc, %l7
+- wrpr %g1, 0, %tnpc
+- done
+-
+- /* We need to carefully read the error status, ACK
+- * the errors, prevent recursive traps, and pass the
+- * information on to C code for logging.
+- *
+- * We pass the AFAR in as-is, and we encode the status
+- * information as described in asm-sparc64/sfafsr.h
+- */
+- .globl __spitfire_access_error
+-__spitfire_access_error:
+- /* Disable ESTATE error reporting so that we do not
+- * take recursive traps and RED state the processor.
+- */
+- stxa %g0, [%g0] ASI_ESTATE_ERROR_EN
+- membar #Sync
+-
+- mov UDBE_UE, %g1
+- ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
+-
+- /* __spitfire_cee_trap branches here with AFSR in %g4 and
+- * UDBE_CE in %g1. It only clears ESTATE_ERR_CE in the
+- * ESTATE Error Enable register.
+- */
+-__spitfire_cee_trap_continue:
+- ldxa [%g0] ASI_AFAR, %g5 ! Get AFAR
+-
+- rdpr %tt, %g3
+- and %g3, 0x1ff, %g3 ! Paranoia
+- sllx %g3, SFSTAT_TRAP_TYPE_SHIFT, %g3
+- or %g4, %g3, %g4
+- rdpr %tl, %g3
+- cmp %g3, 1
+- mov 1, %g3
+- bleu %xcc, 1f
+- sllx %g3, SFSTAT_TL_GT_ONE_SHIFT, %g3
+-
+- or %g4, %g3, %g4
+-
+- /* Read in the UDB error register state, clearing the
+- * sticky error bits as-needed. We only clear them if
+- * the UE bit is set. Likewise, __spitfire_cee_trap
+- * below will only do so if the CE bit is set.
+- *
+- * NOTE: UltraSparc-I/II have high and low UDB error
+- * registers, corresponding to the two UDB units
+- * present on those chips. UltraSparc-IIi only
+- * has a single UDB, called "SDB" in the manual.
+- * For IIi the upper UDB register always reads
+- * as zero so for our purposes things will just
+- * work with the checks below.
+- */
+-1: ldxa [%g0] ASI_UDBH_ERROR_R, %g3
+- and %g3, 0x3ff, %g7 ! Paranoia
+- sllx %g7, SFSTAT_UDBH_SHIFT, %g7
+- or %g4, %g7, %g4
+- andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
+- be,pn %xcc, 1f
+- nop
+- stxa %g3, [%g0] ASI_UDB_ERROR_W
+- membar #Sync
+-
+-1: mov 0x18, %g3
+- ldxa [%g3] ASI_UDBL_ERROR_R, %g3
+- and %g3, 0x3ff, %g7 ! Paranoia
+- sllx %g7, SFSTAT_UDBL_SHIFT, %g7
+- or %g4, %g7, %g4
+- andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
+- be,pn %xcc, 1f
+- nop
+- mov 0x18, %g7
+- stxa %g3, [%g7] ASI_UDB_ERROR_W
+- membar #Sync
+-
+-1: /* Ok, now that we've latched the error state,
+- * clear the sticky bits in the AFSR.
+- */
+- stxa %g4, [%g0] ASI_AFSR
+- membar #Sync
+-
+- rdpr %tl, %g2
+- cmp %g2, 1
+- rdpr %pil, %g2
+- bleu,pt %xcc, 1f
+- wrpr %g0, 15, %pil
+-
+- ba,pt %xcc, etraptl1
+- rd %pc, %g7
+-
+- ba,pt %xcc, 2f
+- nop
+-
+-1: ba,pt %xcc, etrap_irq
+- rd %pc, %g7
+-
+-2:
+-#ifdef CONFIG_TRACE_IRQFLAGS
+- call trace_hardirqs_off
+- nop
+-#endif
+- mov %l4, %o1
+- mov %l5, %o2
+- 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
+-
+- /* This is the trap handler entry point for ECC correctable
+- * errors. They are corrected, but we listen for the trap
+- * so that the event can be logged.
+- *
+- * Disrupting errors are either:
+- * 1) single-bit ECC errors during UDB reads to system
+- * memory
+- * 2) data parity errors during write-back events
+- *
+- * As far as I can make out from the manual, the CEE trap
+- * is only for correctable errors during memory read
+- * accesses by the front-end of the processor.
+- *
+- * The code below is only for trap level 1 CEE events,
+- * as it is the only situation where we can safely record
+- * and log. For trap level >1 we just clear the CE bit
+- * in the AFSR and return.
+- *
+- * This is just like __spiftire_access_error above, but it
+- * specifically handles correctable errors. If an
+- * uncorrectable error is indicated in the AFSR we
+- * will branch directly above to __spitfire_access_error
+- * to handle it instead. Uncorrectable therefore takes
+- * priority over correctable, and the error logging
+- * C code will notice this case by inspecting the
+- * trap type.
+- */
+- .globl __spitfire_cee_trap
+-__spitfire_cee_trap:
+- ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
+- mov 1, %g3
+- sllx %g3, SFAFSR_UE_SHIFT, %g3
+- andcc %g4, %g3, %g0 ! Check for UE
+- bne,pn %xcc, __spitfire_access_error
+- nop
+-
+- /* Ok, in this case we only have a correctable error.
+- * Indicate we only wish to capture that state in register
+- * %g1, and we only disable CE error reporting unlike UE
+- * handling which disables all errors.
+- */
+- ldxa [%g0] ASI_ESTATE_ERROR_EN, %g3
+- andn %g3, ESTATE_ERR_CE, %g3
+- stxa %g3, [%g0] ASI_ESTATE_ERROR_EN
+- membar #Sync
+-
+- /* Preserve AFSR in %g4, indicate UDB state to capture in %g1 */
+- ba,pt %xcc, __spitfire_cee_trap_continue
+- mov UDBE_CE, %g1
+-
+- .globl __spitfire_data_access_exception
+- .globl __spitfire_data_access_exception_tl1
+-__spitfire_data_access_exception_tl1:
+- rdpr %pstate, %g4
+- wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
+- mov TLB_SFSR, %g3
+- mov DMMU_SFAR, %g5
+- ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
+- ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
+- stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit
+- membar #Sync
+- rdpr %tt, %g3
+- cmp %g3, 0x80 ! first win spill/fill trap
+- blu,pn %xcc, 1f
+- cmp %g3, 0xff ! last win spill/fill trap
+- bgu,pn %xcc, 1f
+- nop
+- ba,pt %xcc, winfix_dax
+- rdpr %tpc, %g3
+-1: sethi %hi(109f), %g7
+- ba,pt %xcc, etraptl1
+-109: or %g7, %lo(109b), %g7
+- mov %l4, %o1
+- mov %l5, %o2
+- 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
+-
+-__spitfire_data_access_exception:
+- rdpr %pstate, %g4
+- wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
+- mov TLB_SFSR, %g3
+- mov DMMU_SFAR, %g5
+- ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
+- ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
+- stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit
+- membar #Sync
+- sethi %hi(109f), %g7
+- ba,pt %xcc, etrap
+-109: or %g7, %lo(109b), %g7
+- mov %l4, %o1
+- mov %l5, %o2
+- 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
+-
+- .globl __spitfire_insn_access_exception
+- .globl __spitfire_insn_access_exception_tl1
+-__spitfire_insn_access_exception_tl1:
+- rdpr %pstate, %g4
+- wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
+- mov TLB_SFSR, %g3
+- ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR
+- rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC
+- stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
+- membar #Sync
+- sethi %hi(109f), %g7
+- ba,pt %xcc, etraptl1
+-109: or %g7, %lo(109b), %g7
+- mov %l4, %o1
+- mov %l5, %o2
+- 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
+-
+-__spitfire_insn_access_exception:
+- rdpr %pstate, %g4
+- wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
+- mov TLB_SFSR, %g3
+- ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR
+- rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC
+- stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
+- membar #Sync
+- sethi %hi(109f), %g7
+- ba,pt %xcc, etrap
+-109: or %g7, %lo(109b), %g7
+- mov %l4, %o1
+- mov %l5, %o2
+- 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
+-
+- /* These get patched into the trap table at boot time
+- * once we know we have a cheetah processor.
+- */
+- .globl cheetah_fecc_trap_vector, cheetah_fecc_trap_vector_tl1
+-cheetah_fecc_trap_vector:
+- membar #Sync
+- ldxa [%g0] ASI_DCU_CONTROL_REG, %g1
+- andn %g1, DCU_DC | DCU_IC, %g1
+- stxa %g1, [%g0] ASI_DCU_CONTROL_REG
+- membar #Sync
+- sethi %hi(cheetah_fast_ecc), %g2
+- jmpl %g2 + %lo(cheetah_fast_ecc), %g0
+- mov 0, %g1
+-cheetah_fecc_trap_vector_tl1:
+- membar #Sync
+- ldxa [%g0] ASI_DCU_CONTROL_REG, %g1
+- andn %g1, DCU_DC | DCU_IC, %g1
+- stxa %g1, [%g0] ASI_DCU_CONTROL_REG
+- membar #Sync
+- sethi %hi(cheetah_fast_ecc), %g2
+- jmpl %g2 + %lo(cheetah_fast_ecc), %g0
+- mov 1, %g1
+- .globl cheetah_cee_trap_vector, cheetah_cee_trap_vector_tl1
+-cheetah_cee_trap_vector:
+- membar #Sync
+- ldxa [%g0] ASI_DCU_CONTROL_REG, %g1
+- andn %g1, DCU_IC, %g1
+- stxa %g1, [%g0] ASI_DCU_CONTROL_REG
+- membar #Sync
+- sethi %hi(cheetah_cee), %g2
+- jmpl %g2 + %lo(cheetah_cee), %g0
+- mov 0, %g1
+-cheetah_cee_trap_vector_tl1:
+- membar #Sync
+- ldxa [%g0] ASI_DCU_CONTROL_REG, %g1
+- andn %g1, DCU_IC, %g1
+- stxa %g1, [%g0] ASI_DCU_CONTROL_REG
+- membar #Sync
+- sethi %hi(cheetah_cee), %g2
+- jmpl %g2 + %lo(cheetah_cee), %g0
+- mov 1, %g1
+- .globl cheetah_deferred_trap_vector, cheetah_deferred_trap_vector_tl1
+-cheetah_deferred_trap_vector:
+- membar #Sync
+- ldxa [%g0] ASI_DCU_CONTROL_REG, %g1;
+- andn %g1, DCU_DC | DCU_IC, %g1;
+- stxa %g1, [%g0] ASI_DCU_CONTROL_REG;
+- membar #Sync;
+- sethi %hi(cheetah_deferred_trap), %g2
+- jmpl %g2 + %lo(cheetah_deferred_trap), %g0
+- mov 0, %g1
+-cheetah_deferred_trap_vector_tl1:
+- membar #Sync;
+- ldxa [%g0] ASI_DCU_CONTROL_REG, %g1;
+- andn %g1, DCU_DC | DCU_IC, %g1;
+- stxa %g1, [%g0] ASI_DCU_CONTROL_REG;
+- membar #Sync;
+- sethi %hi(cheetah_deferred_trap), %g2
+- jmpl %g2 + %lo(cheetah_deferred_trap), %g0
+- mov 1, %g1
+-
+- /* Cheetah+ specific traps. These are for the new I/D cache parity
+- * error traps. The first argument to cheetah_plus_parity_handler
+- * is encoded as follows:
+- *
+- * Bit0: 0=dcache,1=icache
+- * Bit1: 0=recoverable,1=unrecoverable
+- */
+- .globl cheetah_plus_dcpe_trap_vector, cheetah_plus_dcpe_trap_vector_tl1
+-cheetah_plus_dcpe_trap_vector:
+- membar #Sync
+- sethi %hi(do_cheetah_plus_data_parity), %g7
+- jmpl %g7 + %lo(do_cheetah_plus_data_parity), %g0
+- nop
+- nop
+- nop
+- nop
+- nop
+-
+-do_cheetah_plus_data_parity:
+- rdpr %pil, %g2
+- wrpr %g0, 15, %pil
+- ba,pt %xcc, etrap_irq
+- rd %pc, %g7
+-#ifdef CONFIG_TRACE_IRQFLAGS
+- call trace_hardirqs_off
+- nop
+-#endif
+- mov 0x0, %o0
+- call cheetah_plus_parity_error
+- add %sp, PTREGS_OFF, %o1
+- ba,a,pt %xcc, rtrap_irq
+-
+-cheetah_plus_dcpe_trap_vector_tl1:
+- membar #Sync
+- wrpr PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate
+- sethi %hi(do_dcpe_tl1), %g3
+- jmpl %g3 + %lo(do_dcpe_tl1), %g0
+- nop
+- nop
+- nop
+- nop
+-
+- .globl cheetah_plus_icpe_trap_vector, cheetah_plus_icpe_trap_vector_tl1
+-cheetah_plus_icpe_trap_vector:
+- membar #Sync
+- sethi %hi(do_cheetah_plus_insn_parity), %g7
+- jmpl %g7 + %lo(do_cheetah_plus_insn_parity), %g0
+- nop
+- nop
+- nop
+- nop
+- nop
+-
+-do_cheetah_plus_insn_parity:
+- rdpr %pil, %g2
+- wrpr %g0, 15, %pil
+- ba,pt %xcc, etrap_irq
+- rd %pc, %g7
+-#ifdef CONFIG_TRACE_IRQFLAGS
+- call trace_hardirqs_off
+- nop
+-#endif
+- mov 0x1, %o0
+- call cheetah_plus_parity_error
+- add %sp, PTREGS_OFF, %o1
+- ba,a,pt %xcc, rtrap_irq
+-
+-cheetah_plus_icpe_trap_vector_tl1:
+- membar #Sync
+- wrpr PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate
+- sethi %hi(do_icpe_tl1), %g3
+- jmpl %g3 + %lo(do_icpe_tl1), %g0
+- nop
+- nop
+- nop
+- nop
+-
+- /* If we take one of these traps when tl >= 1, then we
+- * jump to interrupt globals. If some trap level above us
+- * was also using interrupt globals, we cannot recover.
+- * We may use all interrupt global registers except %g6.
+- */
+- .globl do_dcpe_tl1, do_icpe_tl1
+-do_dcpe_tl1:
+- rdpr %tl, %g1 ! Save original trap level
+- mov 1, %g2 ! Setup TSTATE checking loop
+- sethi %hi(TSTATE_IG), %g3 ! TSTATE mask bit
+-1: wrpr %g2, %tl ! Set trap level to check
+- rdpr %tstate, %g4 ! Read TSTATE for this level
+- andcc %g4, %g3, %g0 ! Interrupt globals in use?
+- bne,a,pn %xcc, do_dcpe_tl1_fatal ! Yep, irrecoverable
+- wrpr %g1, %tl ! Restore original trap level
+- add %g2, 1, %g2 ! Next trap level
+- cmp %g2, %g1 ! Hit them all yet?
+- ble,pt %icc, 1b ! Not yet
+- nop
+- wrpr %g1, %tl ! Restore original trap level
+-do_dcpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */
+- sethi %hi(dcache_parity_tl1_occurred), %g2
+- lduw [%g2 + %lo(dcache_parity_tl1_occurred)], %g1
+- add %g1, 1, %g1
+- stw %g1, [%g2 + %lo(dcache_parity_tl1_occurred)]
+- /* Reset D-cache parity */
+- sethi %hi(1 << 16), %g1 ! D-cache size
+- mov (1 << 5), %g2 ! D-cache line size
+- sub %g1, %g2, %g1 ! Move down 1 cacheline
+-1: srl %g1, 14, %g3 ! Compute UTAG
+- membar #Sync
+- stxa %g3, [%g1] ASI_DCACHE_UTAG
+- membar #Sync
+- sub %g2, 8, %g3 ! 64-bit data word within line
+-2: membar #Sync
+- stxa %g0, [%g1 + %g3] ASI_DCACHE_DATA
+- membar #Sync
+- subcc %g3, 8, %g3 ! Next 64-bit data word
+- bge,pt %icc, 2b
+- nop
+- subcc %g1, %g2, %g1 ! Next cacheline
+- bge,pt %icc, 1b
+- nop
+- ba,pt %xcc, dcpe_icpe_tl1_common
+- nop
+-
+-do_dcpe_tl1_fatal:
+- sethi %hi(1f), %g7
+- ba,pt %xcc, etraptl1
+-1: or %g7, %lo(1b), %g7
+- mov 0x2, %o0
+- 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
+-
+-do_icpe_tl1:
+- rdpr %tl, %g1 ! Save original trap level
+- mov 1, %g2 ! Setup TSTATE checking loop
+- sethi %hi(TSTATE_IG), %g3 ! TSTATE mask bit
+-1: wrpr %g2, %tl ! Set trap level to check
+- rdpr %tstate, %g4 ! Read TSTATE for this level
+- andcc %g4, %g3, %g0 ! Interrupt globals in use?
+- bne,a,pn %xcc, do_icpe_tl1_fatal ! Yep, irrecoverable
+- wrpr %g1, %tl ! Restore original trap level
+- add %g2, 1, %g2 ! Next trap level
+- cmp %g2, %g1 ! Hit them all yet?
+- ble,pt %icc, 1b ! Not yet
+- nop
+- wrpr %g1, %tl ! Restore original trap level
+-do_icpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */
+- sethi %hi(icache_parity_tl1_occurred), %g2
+- lduw [%g2 + %lo(icache_parity_tl1_occurred)], %g1
+- add %g1, 1, %g1
+- stw %g1, [%g2 + %lo(icache_parity_tl1_occurred)]
+- /* Flush I-cache */
+- sethi %hi(1 << 15), %g1 ! I-cache size
+- mov (1 << 5), %g2 ! I-cache line size
+- sub %g1, %g2, %g1
+-1: or %g1, (2 << 3), %g3
+- stxa %g0, [%g3] ASI_IC_TAG
+- membar #Sync
+- subcc %g1, %g2, %g1
+- bge,pt %icc, 1b
+- nop
+- ba,pt %xcc, dcpe_icpe_tl1_common
+- nop
+-
+-do_icpe_tl1_fatal:
+- sethi %hi(1f), %g7
+- ba,pt %xcc, etraptl1
+-1: or %g7, %lo(1b), %g7
+- mov 0x3, %o0
+- 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
+-
+-dcpe_icpe_tl1_common:
+- /* Flush D-cache, re-enable D/I caches in DCU and finally
+- * retry the trapping instruction.
+- */
+- sethi %hi(1 << 16), %g1 ! D-cache size
+- mov (1 << 5), %g2 ! D-cache line size
+- sub %g1, %g2, %g1
+-1: stxa %g0, [%g1] ASI_DCACHE_TAG
+- membar #Sync
+- subcc %g1, %g2, %g1
+- bge,pt %icc, 1b
+- nop
+- ldxa [%g0] ASI_DCU_CONTROL_REG, %g1
+- or %g1, (DCU_DC | DCU_IC), %g1
+- stxa %g1, [%g0] ASI_DCU_CONTROL_REG
+- membar #Sync
+- retry
+-
+- /* Capture I/D/E-cache state into per-cpu error scoreboard.
+- *
+- * %g1: (TL>=0) ? 1 : 0
+- * %g2: scratch
+- * %g3: scratch
+- * %g4: AFSR
+- * %g5: AFAR
+- * %g6: unused, will have current thread ptr after etrap
+- * %g7: scratch
+- */
+-__cheetah_log_error:
+- /* Put "TL1" software bit into AFSR. */
+- and %g1, 0x1, %g1
+- sllx %g1, 63, %g2
+- or %g4, %g2, %g4
+-
+- /* Get log entry pointer for this cpu at this trap level. */
+- BRANCH_IF_JALAPENO(g2,g3,50f)
+- ldxa [%g0] ASI_SAFARI_CONFIG, %g2
+- srlx %g2, 17, %g2
+- ba,pt %xcc, 60f
+- and %g2, 0x3ff, %g2
+-
+-50: ldxa [%g0] ASI_JBUS_CONFIG, %g2
+- srlx %g2, 17, %g2
+- and %g2, 0x1f, %g2
+-
+-60: sllx %g2, 9, %g2
+- sethi %hi(cheetah_error_log), %g3
+- ldx [%g3 + %lo(cheetah_error_log)], %g3
+- brz,pn %g3, 80f
+- nop
+-
+- add %g3, %g2, %g3
+- sllx %g1, 8, %g1
+- add %g3, %g1, %g1
+-
+- /* %g1 holds pointer to the top of the logging scoreboard */
+- ldx [%g1 + 0x0], %g7
+- cmp %g7, -1
+- bne,pn %xcc, 80f
+- nop
+-
+- stx %g4, [%g1 + 0x0]
+- stx %g5, [%g1 + 0x8]
+- add %g1, 0x10, %g1
+-
+- /* %g1 now points to D-cache logging area */
+- set 0x3ff8, %g2 /* DC_addr mask */
+- and %g5, %g2, %g2 /* DC_addr bits of AFAR */
+- srlx %g5, 12, %g3
+- or %g3, 1, %g3 /* PHYS tag + valid */
+-
+-10: ldxa [%g2] ASI_DCACHE_TAG, %g7
+- cmp %g3, %g7 /* TAG match? */
+- bne,pt %xcc, 13f
+- nop
+-
+- /* Yep, what we want, capture state. */
+- stx %g2, [%g1 + 0x20]
+- stx %g7, [%g1 + 0x28]
+-
+- /* A membar Sync is required before and after utag access. */
+- membar #Sync
+- ldxa [%g2] ASI_DCACHE_UTAG, %g7
+- membar #Sync
+- stx %g7, [%g1 + 0x30]
+- ldxa [%g2] ASI_DCACHE_SNOOP_TAG, %g7
+- stx %g7, [%g1 + 0x38]
+- clr %g3
+-
+-12: ldxa [%g2 + %g3] ASI_DCACHE_DATA, %g7
+- stx %g7, [%g1]
+- add %g3, (1 << 5), %g3
+- cmp %g3, (4 << 5)
+- bl,pt %xcc, 12b
+- add %g1, 0x8, %g1
+-
+- ba,pt %xcc, 20f
+- add %g1, 0x20, %g1
+-
+-13: sethi %hi(1 << 14), %g7
+- add %g2, %g7, %g2
+- srlx %g2, 14, %g7
+- cmp %g7, 4
+- bl,pt %xcc, 10b
+- nop
+-
+- add %g1, 0x40, %g1
+-
+- /* %g1 now points to I-cache logging area */
+-20: set 0x1fe0, %g2 /* IC_addr mask */
+- and %g5, %g2, %g2 /* IC_addr bits of AFAR */
+- sllx %g2, 1, %g2 /* IC_addr[13:6]==VA[12:5] */
+- srlx %g5, (13 - 8), %g3 /* Make PTAG */
+- andn %g3, 0xff, %g3 /* Mask off undefined bits */
+-
+-21: ldxa [%g2] ASI_IC_TAG, %g7
+- andn %g7, 0xff, %g7
+- cmp %g3, %g7
+- bne,pt %xcc, 23f
+- nop
+-
+- /* Yep, what we want, capture state. */
+- stx %g2, [%g1 + 0x40]
+- stx %g7, [%g1 + 0x48]
+- add %g2, (1 << 3), %g2
+- ldxa [%g2] ASI_IC_TAG, %g7
+- add %g2, (1 << 3), %g2
+- stx %g7, [%g1 + 0x50]
+- ldxa [%g2] ASI_IC_TAG, %g7
+- add %g2, (1 << 3), %g2
+- stx %g7, [%g1 + 0x60]
+- ldxa [%g2] ASI_IC_TAG, %g7
+- stx %g7, [%g1 + 0x68]
+- sub %g2, (3 << 3), %g2
+- ldxa [%g2] ASI_IC_STAG, %g7
+- stx %g7, [%g1 + 0x58]
+- clr %g3
+- srlx %g2, 2, %g2
+-
+-22: ldxa [%g2 + %g3] ASI_IC_INSTR, %g7
+- stx %g7, [%g1]
+- add %g3, (1 << 3), %g3
+- cmp %g3, (8 << 3)
+- bl,pt %xcc, 22b
+- add %g1, 0x8, %g1
+-
+- ba,pt %xcc, 30f
+- add %g1, 0x30, %g1
+-
+-23: sethi %hi(1 << 14), %g7
+- add %g2, %g7, %g2
+- srlx %g2, 14, %g7
+- cmp %g7, 4
+- bl,pt %xcc, 21b
+- nop
+-
+- add %g1, 0x70, %g1
+-
+- /* %g1 now points to E-cache logging area */
+-30: andn %g5, (32 - 1), %g2
+- stx %g2, [%g1 + 0x20]
+- ldxa [%g2] ASI_EC_TAG_DATA, %g7
+- stx %g7, [%g1 + 0x28]
+- ldxa [%g2] ASI_EC_R, %g0
+- clr %g3
+-
+-31: ldxa [%g3] ASI_EC_DATA, %g7
+- stx %g7, [%g1 + %g3]
+- add %g3, 0x8, %g3
+- cmp %g3, 0x20
+-
+- bl,pt %xcc, 31b
+- nop
+-80:
+- rdpr %tt, %g2
+- cmp %g2, 0x70
+- be c_fast_ecc
+- cmp %g2, 0x63
+- be c_cee
+- nop
+- ba,pt %xcc, c_deferred
+-
+- /* Cheetah FECC trap handling, we get here from tl{0,1}_fecc
+- * in the trap table. That code has done a memory barrier
+- * and has disabled both the I-cache and D-cache in the DCU
+- * control register. The I-cache is disabled so that we may
+- * capture the corrupted cache line, and the D-cache is disabled
+- * because corrupt data may have been placed there and we don't
+- * want to reference it.
+- *
+- * %g1 is one if this trap occurred at %tl >= 1.
+- *
+- * Next, we turn off error reporting so that we don't recurse.
+- */
+- .globl cheetah_fast_ecc
+-cheetah_fast_ecc:
+- ldxa [%g0] ASI_ESTATE_ERROR_EN, %g2
+- andn %g2, ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN, %g2
+- stxa %g2, [%g0] ASI_ESTATE_ERROR_EN
+- membar #Sync
+-
+- /* Fetch and clear AFSR/AFAR */
+- ldxa [%g0] ASI_AFSR, %g4
+- ldxa [%g0] ASI_AFAR, %g5
+- stxa %g4, [%g0] ASI_AFSR
+- membar #Sync
+-
+- ba,pt %xcc, __cheetah_log_error
+- nop
+-
+-c_fast_ecc:
+- rdpr %pil, %g2
+- wrpr %g0, 15, %pil
+- ba,pt %xcc, etrap_irq
+- rd %pc, %g7
+-#ifdef CONFIG_TRACE_IRQFLAGS
+- call trace_hardirqs_off
+- nop
+-#endif
+- mov %l4, %o1
+- mov %l5, %o2
+- call cheetah_fecc_handler
+- add %sp, PTREGS_OFF, %o0
+- ba,a,pt %xcc, rtrap_irq
+-
+- /* Our caller has disabled I-cache and performed membar Sync. */
+- .globl cheetah_cee
+-cheetah_cee:
+- ldxa [%g0] ASI_ESTATE_ERROR_EN, %g2
+- andn %g2, ESTATE_ERROR_CEEN, %g2
+- stxa %g2, [%g0] ASI_ESTATE_ERROR_EN
+- membar #Sync
+-
+- /* Fetch and clear AFSR/AFAR */
+- ldxa [%g0] ASI_AFSR, %g4
+- ldxa [%g0] ASI_AFAR, %g5
+- stxa %g4, [%g0] ASI_AFSR
+- membar #Sync
+-
+- ba,pt %xcc, __cheetah_log_error
+- nop
+-
+-c_cee:
+- rdpr %pil, %g2
+- wrpr %g0, 15, %pil
+- ba,pt %xcc, etrap_irq
+- rd %pc, %g7
+-#ifdef CONFIG_TRACE_IRQFLAGS
+- call trace_hardirqs_off
+- nop
+-#endif
+- mov %l4, %o1
+- mov %l5, %o2
+- call cheetah_cee_handler
+- add %sp, PTREGS_OFF, %o0
+- ba,a,pt %xcc, rtrap_irq
+-
+- /* Our caller has disabled I-cache+D-cache and performed membar Sync. */
+- .globl cheetah_deferred_trap
+-cheetah_deferred_trap:
+- ldxa [%g0] ASI_ESTATE_ERROR_EN, %g2
+- andn %g2, ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN, %g2
+- stxa %g2, [%g0] ASI_ESTATE_ERROR_EN
+- membar #Sync
+-
+- /* Fetch and clear AFSR/AFAR */
+- ldxa [%g0] ASI_AFSR, %g4
+- ldxa [%g0] ASI_AFAR, %g5
+- stxa %g4, [%g0] ASI_AFSR
+- membar #Sync
+-
+- ba,pt %xcc, __cheetah_log_error
+- nop
+-
+-c_deferred:
+- rdpr %pil, %g2
+- wrpr %g0, 15, %pil
+- ba,pt %xcc, etrap_irq
+- rd %pc, %g7
+-#ifdef CONFIG_TRACE_IRQFLAGS
+- call trace_hardirqs_off
+- nop
+-#endif
+- mov %l4, %o1
+- mov %l5, %o2
+- call cheetah_deferred_handler
+- add %sp, PTREGS_OFF, %o0
+- ba,a,pt %xcc, rtrap_irq
+-
+- .globl __do_privact
+-__do_privact:
+- mov TLB_SFSR, %g3
+- stxa %g0, [%g3] ASI_DMMU ! Clear FaultValid bit
+- membar #Sync
+- sethi %hi(109f), %g7
+- ba,pt %xcc, etrap
+-109: or %g7, %lo(109b), %g7
+- 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
+-
+- .globl do_mna
+-do_mna:
+- rdpr %tl, %g3
+- cmp %g3, 1
+-
+- /* Setup %g4/%g5 now as they are used in the
+- * winfixup code.
+- */
+- mov TLB_SFSR, %g3
+- mov DMMU_SFAR, %g4
+- ldxa [%g4] ASI_DMMU, %g4
+- ldxa [%g3] ASI_DMMU, %g5
+- stxa %g0, [%g3] ASI_DMMU ! Clear FaultValid bit
+- membar #Sync
+- bgu,pn %icc, winfix_mna
+- rdpr %tpc, %g3
+-
+-1: sethi %hi(109f), %g7
+- ba,pt %xcc, etrap
+-109: or %g7, %lo(109b), %g7
+- mov %l4, %o1
+- mov %l5, %o2
+- 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
+-
+- .globl do_lddfmna
+-do_lddfmna:
+- sethi %hi(109f), %g7
+- mov TLB_SFSR, %g4
+- ldxa [%g4] ASI_DMMU, %g5
+- stxa %g0, [%g4] ASI_DMMU ! Clear FaultValid bit
+- membar #Sync
+- mov DMMU_SFAR, %g4
+- ldxa [%g4] ASI_DMMU, %g4
+- ba,pt %xcc, etrap
+-109: or %g7, %lo(109b), %g7
+- mov %l4, %o1
+- mov %l5, %o2
+- 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
+-
+- .globl do_stdfmna
+-do_stdfmna:
+- sethi %hi(109f), %g7
+- mov TLB_SFSR, %g4
+- ldxa [%g4] ASI_DMMU, %g5
+- stxa %g0, [%g4] ASI_DMMU ! Clear FaultValid bit
+- membar #Sync
+- mov DMMU_SFAR, %g4
+- ldxa [%g4] ASI_DMMU, %g4
+- ba,pt %xcc, etrap
+-109: or %g7, %lo(109b), %g7
+- mov %l4, %o1
+- mov %l5, %o2
+- 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
-
+-
+- .globl breakpoint_trap
+-breakpoint_trap:
+- call sparc_breakpoint
+- add %sp, PTREGS_OFF, %o0
+- 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
@@ -221960,63 +275008,1227 @@
- 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
+- /* SunOS's execv() call only specifies the argv argument, the
+- * environment settings are the same as the calling processes.
+- */
+- .globl sunos_execv
+-sys_execve:
+- sethi %hi(sparc_execve), %g1
+- ba,pt %xcc, execve_merge
+- or %g1, %lo(sparc_execve), %g1
+-#ifdef CONFIG_COMPAT
+- .globl sys_execve
+-sunos_execv:
+- stx %g0, [%sp + PTREGS_OFF + PT_V9_I2]
+- .globl sys32_execve
+-sys32_execve:
+- sethi %hi(sparc32_execve), %g1
+- or %g1, %lo(sparc32_execve), %g1
+-#endif
+-execve_merge:
+- flushw
+- jmpl %g1, %g0
+- add %sp, PTREGS_OFF, %o0
+-
+- .globl sys_pipe, sys_sigpause, sys_nis_syscall
+- .globl sys_rt_sigreturn
+- .globl sys_ptrace
+- .globl sys_sigaltstack
+- .align 32
+-sys_pipe: ba,pt %xcc, sparc_pipe
+- add %sp, PTREGS_OFF, %o0
+-sys_nis_syscall:ba,pt %xcc, c_sys_nis_syscall
+- add %sp, PTREGS_OFF, %o0
+-sys_memory_ordering:
+- ba,pt %xcc, sparc_memory_ordering
+- add %sp, PTREGS_OFF, %o1
+-sys_sigaltstack:ba,pt %xcc, do_sigaltstack
+- add %i6, STACK_BIAS, %o2
+-#ifdef CONFIG_COMPAT
+- .globl sys32_sigstack
+-sys32_sigstack: ba,pt %xcc, do_sys32_sigstack
+- mov %i6, %o2
+- .globl sys32_sigaltstack
+-sys32_sigaltstack:
+- ba,pt %xcc, do_sys32_sigaltstack
+- mov %i6, %o2
+-#endif
+- .align 32
+-#ifdef CONFIG_COMPAT
+- .globl sys32_sigreturn
+-sys32_sigreturn:
+- add %sp, PTREGS_OFF, %o0
+- call do_sigreturn32
+- add %o7, 1f-.-4, %o7
+- nop
+-#endif
+-sys_rt_sigreturn:
+- add %sp, PTREGS_OFF, %o0
+- call do_rt_sigreturn
+- add %o7, 1f-.-4, %o7
+- nop
+-#ifdef CONFIG_COMPAT
+- .globl sys32_rt_sigreturn
+-sys32_rt_sigreturn:
+- add %sp, PTREGS_OFF, %o0
+- call do_rt_sigreturn32
+- add %o7, 1f-.-4, %o7
+- nop
+-#endif
+- .align 32
+-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
+- 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
-
-
+-
+- /* This is how fork() was meant to be done, 8 instruction entry.
+- *
+- * I questioned the following code briefly, let me clear things
+- * up so you must not reason on it like I did.
+- *
+- * Know the fork_kpsr etc. we use in the sparc32 port? We don't
+- * need it here because the only piece of window state we copy to
+- * the child is the CWP register. Even if the parent sleeps,
+- * we are safe because we stuck it into pt_regs of the parent
+- * so it will not change.
+- *
+- * XXX This raises the question, whether we can do the same on
+- * XXX sparc32 to get rid of fork_kpsr _and_ fork_kwim. The
+- * XXX answer is yes. We stick fork_kpsr in UREG_G0 and
+- * XXX fork_kwim in UREG_G1 (global registers are considered
+- * XXX volatile across a system call in the sparc ABI I think
+- * XXX if it isn't we can use regs->y instead, anyone who depends
+- * XXX upon the Y register being preserved across a fork deserves
+- * XXX to lose).
+- *
+- * In fact we should take advantage of that fact for other things
+- * during system calls...
+- */
+- .globl sys_fork, sys_vfork, sys_clone, sparc_exit
+- .globl ret_from_syscall
+- .align 32
+-sys_vfork: /* Under Linux, vfork and fork are just special cases of clone. */
+- sethi %hi(0x4000 | 0x0100 | SIGCHLD), %o0
+- or %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
+- ba,pt %xcc, sys_clone
+-sys_fork: clr %o1
+- mov SIGCHLD, %o0
+-sys_clone: flushw
+- movrz %o1, %fp, %o1
+- mov 0, %o3
+- ba,pt %xcc, sparc_do_fork
+- add %sp, PTREGS_OFF, %o2
+-ret_from_syscall:
+- /* Clear current_thread_info()->new_child, and
+- * check performance counter stuff too.
+- */
+- stb %g0, [%g6 + TI_NEW_CHILD]
+- ldx [%g6 + TI_FLAGS], %l0
+- call schedule_tail
+- mov %g7, %o0
+- andcc %l0, _TIF_PERFCTR, %g0
+- be,pt %icc, 1f
+- nop
+- ldx [%g6 + TI_PCR], %o7
+- wr %g0, %o7, %pcr
+-
+- /* Blackbird errata workaround. See commentary in
+- * smp.c:smp_percpu_timer_interrupt() for more
+- * information.
+- */
+- ba,pt %xcc, 99f
+- nop
+- .align 64
+-99: wr %g0, %g0, %pic
+- rd %pic, %g0
+-
+-1: b,pt %xcc, ret_sys_call
+- ldx [%sp + PTREGS_OFF + PT_V9_I0], %o0
+-sparc_exit: rdpr %pstate, %g2
+- wrpr %g2, PSTATE_IE, %pstate
+- rdpr %otherwin, %g1
+- rdpr %cansave, %g3
+- add %g3, %g1, %g3
+- wrpr %g3, 0x0, %cansave
+- wrpr %g0, 0x0, %otherwin
+- wrpr %g2, 0x0, %pstate
+- ba,pt %xcc, sys_exit
+- stb %g0, [%g6 + TI_WSAVED]
+-
+-linux_sparc_ni_syscall:
+- sethi %hi(sys_ni_syscall), %l7
+- b,pt %xcc, 4f
+- or %l7, %lo(sys_ni_syscall), %l7
+-
+-linux_syscall_trace32:
+- add %sp, PTREGS_OFF, %o0
+- call syscall_trace
+- clr %o1
+- srl %i0, 0, %o0
+- srl %i4, 0, %o4
+- srl %i1, 0, %o1
+- srl %i2, 0, %o2
+- b,pt %xcc, 2f
+- srl %i3, 0, %o3
+-
+-linux_syscall_trace:
+- add %sp, PTREGS_OFF, %o0
+- call syscall_trace
+- clr %o1
+- mov %i0, %o0
+- mov %i1, %o1
+- mov %i2, %o2
+- mov %i3, %o3
+- b,pt %xcc, 2f
+- 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
-
+- .align 32
+- .globl linux_sparc_syscall32
+-linux_sparc_syscall32:
+- /* Direct access to user regs, much faster. */
+- cmp %g1, NR_SYSCALLS ! IEU1 Group
+- bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI
+- srl %i0, 0, %o0 ! IEU0
+- sll %g1, 2, %l4 ! IEU0 Group
+- srl %i4, 0, %o4 ! IEU1
+- lduw [%l7 + %l4], %l7 ! Load
+- srl %i1, 0, %o1 ! IEU0 Group
+- ldx [%curptr + TI_FLAGS], %l0 ! Load
+-
+- srl %i5, 0, %o5 ! IEU1
+- srl %i2, 0, %o2 ! IEU0 Group
+- andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
+- bne,pn %icc, linux_syscall_trace32 ! CTI
+- mov %i0, %l5 ! IEU1
+- call %l7 ! CTI Group brk forced
+- 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
+- .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]
+-linux_sparc_syscall:
+- /* Direct access to user regs, much faster. */
+- cmp %g1, NR_SYSCALLS ! IEU1 Group
+- bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI
+- mov %i0, %o0 ! IEU0
+- sll %g1, 2, %l4 ! IEU0 Group
+- mov %i1, %o1 ! IEU1
+- lduw [%l7 + %l4], %l7 ! Load
+-4: mov %i2, %o2 ! IEU0 Group
+- ldx [%curptr + TI_FLAGS], %l0 ! Load
+-
+- mov %i3, %o3 ! IEU1
+- mov %i4, %o4 ! IEU0 Group
+- andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
+- bne,pn %icc, linux_syscall_trace ! CTI Group
+- mov %i0, %l5 ! IEU0
+-2: call %l7 ! CTI Group brk forced
+- mov %i5, %o5 ! IEU0
+- nop
+-
+-3: stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
+-ret_sys_call:
+- ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
+- ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
+- sra %o0, 0, %o0
+- mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
+- sllx %g2, 32, %g2
+-
+- /* Check if force_successful_syscall_return()
+- * was invoked.
+- */
+- ldub [%curptr + TI_SYS_NOERROR], %l2
+- brnz,a,pn %l2, 80f
+- stb %g0, [%curptr + TI_SYS_NOERROR]
+-
+- cmp %o0, -ERESTART_RESTARTBLOCK
+- bgeu,pn %xcc, 1f
+- andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6
+-80:
+- /* System call success, clear Carry condition code. */
+- andn %g3, %g2, %g3
+- stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
+- 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]
+- stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
+-
+-1:
+- /* System call failure, set Carry condition code.
+- * Also, get abs(errno) to return to the process.
+- */
+- andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6
+- 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
+- stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
+- bne,pn %icc, linux_syscall_trace2
+- add %l1, 0x4, %l2 ! npc = npc+4
+- stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
+-
+- b,pt %xcc, rtrap
+- stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
+-linux_syscall_trace2:
+- add %sp, PTREGS_OFF, %o0
+- call syscall_trace
+- mov 1, %o1
+- stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
+- ba,pt %xcc, rtrap
+- stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
+-
+- .align 32
+- .globl __flushw_user
+-__flushw_user:
+- rdpr %otherwin, %g1
+- brz,pn %g1, 2f
+- clr %g2
+-1: save %sp, -128, %sp
+- rdpr %otherwin, %g1
+- brnz,pt %g1, 1b
+- add %g2, 1, %g2
+-1: sub %g2, 1, %g2
+- brnz,pt %g2, 1b
+- restore %g0, %g0, %g0
+-2: retl
+- nop
+-
+- /* Flush %fp and %i7 to the stack for all register
+- * windows active inside of the cpu. This allows
+- * show_stack_trace() to avoid using an expensive
+- * 'flushw'.
+- */
+- .globl stack_trace_flush
+- .type stack_trace_flush,#function
+-stack_trace_flush:
+- rdpr %pstate, %o0
+- wrpr %o0, PSTATE_IE, %pstate
+-
+- rdpr %cwp, %g1
+- rdpr %canrestore, %g2
+- sub %g1, 1, %g3
+-
+-1: brz,pn %g2, 2f
+- sub %g2, 1, %g2
+- wrpr %g3, %cwp
+- stx %fp, [%sp + STACK_BIAS + RW_V9_I6]
+- stx %i7, [%sp + STACK_BIAS + RW_V9_I7]
+- ba,pt %xcc, 1b
+- sub %g3, 1, %g3
+-
+-2: wrpr %g1, %cwp
+- wrpr %o0, %pstate
+-
+- retl
+- nop
+- .size stack_trace_flush,.-stack_trace_flush
+-
+-#ifdef CONFIG_SMP
+- .globl hard_smp_processor_id
+-hard_smp_processor_id:
+-#endif
+- .globl real_hard_smp_processor_id
+-real_hard_smp_processor_id:
+- __GET_CPUID(%o0)
+- retl
+- nop
+-
+- /* %o0: devhandle
+- * %o1: devino
+- *
+- * returns %o0: sysino
+- */
+- .globl sun4v_devino_to_sysino
+- .type sun4v_devino_to_sysino,#function
+-sun4v_devino_to_sysino:
+- mov HV_FAST_INTR_DEVINO2SYSINO, %o5
+- ta HV_FAST_TRAP
+- retl
+- mov %o1, %o0
+- .size sun4v_devino_to_sysino, .-sun4v_devino_to_sysino
+-
+- /* %o0: sysino
+- *
+- * returns %o0: intr_enabled (HV_INTR_{DISABLED,ENABLED})
+- */
+- .globl sun4v_intr_getenabled
+- .type sun4v_intr_getenabled,#function
+-sun4v_intr_getenabled:
+- mov HV_FAST_INTR_GETENABLED, %o5
+- ta HV_FAST_TRAP
+- retl
+- mov %o1, %o0
+- .size sun4v_intr_getenabled, .-sun4v_intr_getenabled
+-
+- /* %o0: sysino
+- * %o1: intr_enabled (HV_INTR_{DISABLED,ENABLED})
+- */
+- .globl sun4v_intr_setenabled
+- .type sun4v_intr_setenabled,#function
+-sun4v_intr_setenabled:
+- mov HV_FAST_INTR_SETENABLED, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_intr_setenabled, .-sun4v_intr_setenabled
+-
+- /* %o0: sysino
+- *
+- * returns %o0: intr_state (HV_INTR_STATE_*)
+- */
+- .globl sun4v_intr_getstate
+- .type sun4v_intr_getstate,#function
+-sun4v_intr_getstate:
+- mov HV_FAST_INTR_GETSTATE, %o5
+- ta HV_FAST_TRAP
+- retl
+- mov %o1, %o0
+- .size sun4v_intr_getstate, .-sun4v_intr_getstate
+-
+- /* %o0: sysino
+- * %o1: intr_state (HV_INTR_STATE_*)
+- */
+- .globl sun4v_intr_setstate
+- .type sun4v_intr_setstate,#function
+-sun4v_intr_setstate:
+- mov HV_FAST_INTR_SETSTATE, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_intr_setstate, .-sun4v_intr_setstate
+-
+- /* %o0: sysino
+- *
+- * returns %o0: cpuid
+- */
+- .globl sun4v_intr_gettarget
+- .type sun4v_intr_gettarget,#function
+-sun4v_intr_gettarget:
+- mov HV_FAST_INTR_GETTARGET, %o5
+- ta HV_FAST_TRAP
+- retl
+- mov %o1, %o0
+- .size sun4v_intr_gettarget, .-sun4v_intr_gettarget
+-
+- /* %o0: sysino
+- * %o1: cpuid
+- */
+- .globl sun4v_intr_settarget
+- .type sun4v_intr_settarget,#function
+-sun4v_intr_settarget:
+- mov HV_FAST_INTR_SETTARGET, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_intr_settarget, .-sun4v_intr_settarget
+-
+- /* %o0: cpuid
+- * %o1: pc
+- * %o2: rtba
+- * %o3: arg0
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_cpu_start
+- .type sun4v_cpu_start,#function
+-sun4v_cpu_start:
+- mov HV_FAST_CPU_START, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_cpu_start, .-sun4v_cpu_start
+-
+- /* %o0: cpuid
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_cpu_stop
+- .type sun4v_cpu_stop,#function
+-sun4v_cpu_stop:
+- mov HV_FAST_CPU_STOP, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_cpu_stop, .-sun4v_cpu_stop
+-
+- /* returns %o0: status */
+- .globl sun4v_cpu_yield
+- .type sun4v_cpu_yield, #function
+-sun4v_cpu_yield:
+- mov HV_FAST_CPU_YIELD, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_cpu_yield, .-sun4v_cpu_yield
+-
+- /* %o0: type
+- * %o1: queue paddr
+- * %o2: num queue entries
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_cpu_qconf
+- .type sun4v_cpu_qconf,#function
+-sun4v_cpu_qconf:
+- mov HV_FAST_CPU_QCONF, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_cpu_qconf, .-sun4v_cpu_qconf
+-
+- /* %o0: num cpus in cpu list
+- * %o1: cpu list paddr
+- * %o2: mondo block paddr
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_cpu_mondo_send
+- .type sun4v_cpu_mondo_send,#function
+-sun4v_cpu_mondo_send:
+- mov HV_FAST_CPU_MONDO_SEND, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_cpu_mondo_send, .-sun4v_cpu_mondo_send
+-
+- /* %o0: CPU ID
+- *
+- * returns %o0: -status if status non-zero, else
+- * %o0: cpu state as HV_CPU_STATE_*
+- */
+- .globl sun4v_cpu_state
+- .type sun4v_cpu_state,#function
+-sun4v_cpu_state:
+- mov HV_FAST_CPU_STATE, %o5
+- ta HV_FAST_TRAP
+- brnz,pn %o0, 1f
+- sub %g0, %o0, %o0
+- mov %o1, %o0
+-1: retl
+- nop
+- .size sun4v_cpu_state, .-sun4v_cpu_state
+-
+- /* %o0: virtual address
+- * %o1: must be zero
+- * %o2: TTE
+- * %o3: HV_MMU_* flags
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_mmu_map_perm_addr
+- .type sun4v_mmu_map_perm_addr,#function
+-sun4v_mmu_map_perm_addr:
+- mov HV_FAST_MMU_MAP_PERM_ADDR, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_mmu_map_perm_addr, .-sun4v_mmu_map_perm_addr
+-
+- /* %o0: number of TSB descriptions
+- * %o1: TSB descriptions real address
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_mmu_tsb_ctx0
+- .type sun4v_mmu_tsb_ctx0,#function
+-sun4v_mmu_tsb_ctx0:
+- mov HV_FAST_MMU_TSB_CTX0, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_mmu_tsb_ctx0, .-sun4v_mmu_tsb_ctx0
+-
+- /* %o0: API group number
+- * %o1: pointer to unsigned long major number storage
+- * %o2: pointer to unsigned long minor number storage
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_get_version
+- .type sun4v_get_version,#function
+-sun4v_get_version:
+- mov HV_CORE_GET_VER, %o5
+- mov %o1, %o3
+- mov %o2, %o4
+- ta HV_CORE_TRAP
+- stx %o1, [%o3]
+- retl
+- stx %o2, [%o4]
+- .size sun4v_get_version, .-sun4v_get_version
+-
+- /* %o0: API group number
+- * %o1: desired major number
+- * %o2: desired minor number
+- * %o3: pointer to unsigned long actual minor number storage
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_set_version
+- .type sun4v_set_version,#function
+-sun4v_set_version:
+- mov HV_CORE_SET_VER, %o5
+- mov %o3, %o4
+- ta HV_CORE_TRAP
+- retl
+- stx %o1, [%o4]
+- .size sun4v_set_version, .-sun4v_set_version
+-
+- /* %o0: pointer to unsigned long time
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_tod_get
+- .type sun4v_tod_get,#function
+-sun4v_tod_get:
+- mov %o0, %o4
+- mov HV_FAST_TOD_GET, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%o4]
+- retl
+- nop
+- .size sun4v_tod_get, .-sun4v_tod_get
+-
+- /* %o0: time
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_tod_set
+- .type sun4v_tod_set,#function
+-sun4v_tod_set:
+- mov HV_FAST_TOD_SET, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_tod_set, .-sun4v_tod_set
+-
+- /* %o0: pointer to unsigned long status
+- *
+- * returns %o0: signed character
+- */
+- .globl sun4v_con_getchar
+- .type sun4v_con_getchar,#function
+-sun4v_con_getchar:
+- mov %o0, %o4
+- mov HV_FAST_CONS_GETCHAR, %o5
+- clr %o0
+- clr %o1
+- ta HV_FAST_TRAP
+- stx %o0, [%o4]
+- retl
+- sra %o1, 0, %o0
+- .size sun4v_con_getchar, .-sun4v_con_getchar
+-
+- /* %o0: signed long character
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_con_putchar
+- .type sun4v_con_putchar,#function
+-sun4v_con_putchar:
+- mov HV_FAST_CONS_PUTCHAR, %o5
+- ta HV_FAST_TRAP
+- retl
+- sra %o0, 0, %o0
+- .size sun4v_con_putchar, .-sun4v_con_putchar
+-
+- /* %o0: buffer real address
+- * %o1: buffer size
+- * %o2: pointer to unsigned long bytes_read
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_con_read
+- .type sun4v_con_read,#function
+-sun4v_con_read:
+- mov %o2, %o4
+- mov HV_FAST_CONS_READ, %o5
+- ta HV_FAST_TRAP
+- brnz %o0, 1f
+- cmp %o1, -1 /* break */
+- be,a,pn %icc, 1f
+- mov %o1, %o0
+- cmp %o1, -2 /* hup */
+- be,a,pn %icc, 1f
+- mov %o1, %o0
+- stx %o1, [%o4]
+-1: retl
+- nop
+- .size sun4v_con_read, .-sun4v_con_read
+-
+- /* %o0: buffer real address
+- * %o1: buffer size
+- * %o2: pointer to unsigned long bytes_written
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_con_write
+- .type sun4v_con_write,#function
+-sun4v_con_write:
+- mov %o2, %o4
+- mov HV_FAST_CONS_WRITE, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%o4]
+- retl
+- nop
+- .size sun4v_con_write, .-sun4v_con_write
+-
+- /* %o0: soft state
+- * %o1: address of description string
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_mach_set_soft_state
+- .type sun4v_mach_set_soft_state,#function
+-sun4v_mach_set_soft_state:
+- mov HV_FAST_MACH_SET_SOFT_STATE, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_mach_set_soft_state, .-sun4v_mach_set_soft_state
+-
+- /* %o0: exit code
+- *
+- * Does not return.
+- */
+- .globl sun4v_mach_exit
+- .type sun4v_mach_exit,#function
+-sun4v_mach_exit:
+- mov HV_FAST_MACH_EXIT, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_mach_exit, .-sun4v_mach_exit
+-
+- /* %o0: buffer real address
+- * %o1: buffer length
+- * %o2: pointer to unsigned long real_buf_len
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_mach_desc
+- .type sun4v_mach_desc,#function
+-sun4v_mach_desc:
+- mov %o2, %o4
+- mov HV_FAST_MACH_DESC, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%o4]
+- retl
+- nop
+- .size sun4v_mach_desc, .-sun4v_mach_desc
+-
+- /* %o0: new timeout in milliseconds
+- * %o1: pointer to unsigned long orig_timeout
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_mach_set_watchdog
+- .type sun4v_mach_set_watchdog,#function
+-sun4v_mach_set_watchdog:
+- mov %o1, %o4
+- mov HV_FAST_MACH_SET_WATCHDOG, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%o4]
+- retl
+- nop
+- .size sun4v_mach_set_watchdog, .-sun4v_mach_set_watchdog
+-
+- /* No inputs and does not return. */
+- .globl sun4v_mach_sir
+- .type sun4v_mach_sir,#function
+-sun4v_mach_sir:
+- mov %o1, %o4
+- mov HV_FAST_MACH_SIR, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%o4]
+- retl
+- nop
+- .size sun4v_mach_sir, .-sun4v_mach_sir
+-
+- /* %o0: channel
+- * %o1: ra
+- * %o2: num_entries
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_ldc_tx_qconf
+- .type sun4v_ldc_tx_qconf,#function
+-sun4v_ldc_tx_qconf:
+- mov HV_FAST_LDC_TX_QCONF, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_ldc_tx_qconf, .-sun4v_ldc_tx_qconf
+-
+- /* %o0: channel
+- * %o1: pointer to unsigned long ra
+- * %o2: pointer to unsigned long num_entries
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_ldc_tx_qinfo
+- .type sun4v_ldc_tx_qinfo,#function
+-sun4v_ldc_tx_qinfo:
+- mov %o1, %g1
+- mov %o2, %g2
+- mov HV_FAST_LDC_TX_QINFO, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%g1]
+- stx %o2, [%g2]
+- retl
+- nop
+- .size sun4v_ldc_tx_qinfo, .-sun4v_ldc_tx_qinfo
+-
+- /* %o0: channel
+- * %o1: pointer to unsigned long head_off
+- * %o2: pointer to unsigned long tail_off
+- * %o2: pointer to unsigned long chan_state
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_ldc_tx_get_state
+- .type sun4v_ldc_tx_get_state,#function
+-sun4v_ldc_tx_get_state:
+- mov %o1, %g1
+- mov %o2, %g2
+- mov %o3, %g3
+- mov HV_FAST_LDC_TX_GET_STATE, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%g1]
+- stx %o2, [%g2]
+- stx %o3, [%g3]
+- retl
+- nop
+- .size sun4v_ldc_tx_get_state, .-sun4v_ldc_tx_get_state
+-
+- /* %o0: channel
+- * %o1: tail_off
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_ldc_tx_set_qtail
+- .type sun4v_ldc_tx_set_qtail,#function
+-sun4v_ldc_tx_set_qtail:
+- mov HV_FAST_LDC_TX_SET_QTAIL, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_ldc_tx_set_qtail, .-sun4v_ldc_tx_set_qtail
+-
+- /* %o0: channel
+- * %o1: ra
+- * %o2: num_entries
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_ldc_rx_qconf
+- .type sun4v_ldc_rx_qconf,#function
+-sun4v_ldc_rx_qconf:
+- mov HV_FAST_LDC_RX_QCONF, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_ldc_rx_qconf, .-sun4v_ldc_rx_qconf
+-
+- /* %o0: channel
+- * %o1: pointer to unsigned long ra
+- * %o2: pointer to unsigned long num_entries
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_ldc_rx_qinfo
+- .type sun4v_ldc_rx_qinfo,#function
+-sun4v_ldc_rx_qinfo:
+- mov %o1, %g1
+- mov %o2, %g2
+- mov HV_FAST_LDC_RX_QINFO, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%g1]
+- stx %o2, [%g2]
+- retl
+- nop
+- .size sun4v_ldc_rx_qinfo, .-sun4v_ldc_rx_qinfo
+-
+- /* %o0: channel
+- * %o1: pointer to unsigned long head_off
+- * %o2: pointer to unsigned long tail_off
+- * %o2: pointer to unsigned long chan_state
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_ldc_rx_get_state
+- .type sun4v_ldc_rx_get_state,#function
+-sun4v_ldc_rx_get_state:
+- mov %o1, %g1
+- mov %o2, %g2
+- mov %o3, %g3
+- mov HV_FAST_LDC_RX_GET_STATE, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%g1]
+- stx %o2, [%g2]
+- stx %o3, [%g3]
+- retl
+- nop
+- .size sun4v_ldc_rx_get_state, .-sun4v_ldc_rx_get_state
+-
+- /* %o0: channel
+- * %o1: head_off
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_ldc_rx_set_qhead
+- .type sun4v_ldc_rx_set_qhead,#function
+-sun4v_ldc_rx_set_qhead:
+- mov HV_FAST_LDC_RX_SET_QHEAD, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_ldc_rx_set_qhead, .-sun4v_ldc_rx_set_qhead
+-
+- /* %o0: channel
+- * %o1: ra
+- * %o2: num_entries
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_ldc_set_map_table
+- .type sun4v_ldc_set_map_table,#function
+-sun4v_ldc_set_map_table:
+- mov HV_FAST_LDC_SET_MAP_TABLE, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_ldc_set_map_table, .-sun4v_ldc_set_map_table
+-
+- /* %o0: channel
+- * %o1: pointer to unsigned long ra
+- * %o2: pointer to unsigned long num_entries
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_ldc_get_map_table
+- .type sun4v_ldc_get_map_table,#function
+-sun4v_ldc_get_map_table:
+- mov %o1, %g1
+- mov %o2, %g2
+- mov HV_FAST_LDC_GET_MAP_TABLE, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%g1]
+- stx %o2, [%g2]
+- retl
+- nop
+- .size sun4v_ldc_get_map_table, .-sun4v_ldc_get_map_table
+-
+- /* %o0: channel
+- * %o1: dir_code
+- * %o2: tgt_raddr
+- * %o3: lcl_raddr
+- * %o4: len
+- * %o5: pointer to unsigned long actual_len
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_ldc_copy
+- .type sun4v_ldc_copy,#function
+-sun4v_ldc_copy:
+- mov %o5, %g1
+- mov HV_FAST_LDC_COPY, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%g1]
+- retl
+- nop
+- .size sun4v_ldc_copy, .-sun4v_ldc_copy
+-
+- /* %o0: channel
+- * %o1: cookie
+- * %o2: pointer to unsigned long ra
+- * %o3: pointer to unsigned long perm
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_ldc_mapin
+- .type sun4v_ldc_mapin,#function
+-sun4v_ldc_mapin:
+- mov %o2, %g1
+- mov %o3, %g2
+- mov HV_FAST_LDC_MAPIN, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%g1]
+- stx %o2, [%g2]
+- retl
+- nop
+- .size sun4v_ldc_mapin, .-sun4v_ldc_mapin
+-
+- /* %o0: ra
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_ldc_unmap
+- .type sun4v_ldc_unmap,#function
+-sun4v_ldc_unmap:
+- mov HV_FAST_LDC_UNMAP, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_ldc_unmap, .-sun4v_ldc_unmap
+-
+- /* %o0: channel
+- * %o1: cookie
+- * %o2: mte_cookie
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_ldc_revoke
+- .type sun4v_ldc_revoke,#function
+-sun4v_ldc_revoke:
+- mov HV_FAST_LDC_REVOKE, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_ldc_revoke, .-sun4v_ldc_revoke
+-
+- /* %o0: device handle
+- * %o1: device INO
+- * %o2: pointer to unsigned long cookie
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_vintr_get_cookie
+- .type sun4v_vintr_get_cookie,#function
+-sun4v_vintr_get_cookie:
+- mov %o2, %g1
+- mov HV_FAST_VINTR_GET_COOKIE, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%g1]
+- retl
+- nop
+- .size sun4v_vintr_get_cookie, .-sun4v_vintr_get_cookie
+-
+- /* %o0: device handle
+- * %o1: device INO
+- * %o2: cookie
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_vintr_set_cookie
+- .type sun4v_vintr_set_cookie,#function
+-sun4v_vintr_set_cookie:
+- mov HV_FAST_VINTR_SET_COOKIE, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_vintr_set_cookie, .-sun4v_vintr_set_cookie
+-
+- /* %o0: device handle
+- * %o1: device INO
+- * %o2: pointer to unsigned long valid_state
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_vintr_get_valid
+- .type sun4v_vintr_get_valid,#function
+-sun4v_vintr_get_valid:
+- mov %o2, %g1
+- mov HV_FAST_VINTR_GET_VALID, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%g1]
+- retl
+- nop
+- .size sun4v_vintr_get_valid, .-sun4v_vintr_get_valid
+-
+- /* %o0: device handle
+- * %o1: device INO
+- * %o2: valid_state
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_vintr_set_valid
+- .type sun4v_vintr_set_valid,#function
+-sun4v_vintr_set_valid:
+- mov HV_FAST_VINTR_SET_VALID, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_vintr_set_valid, .-sun4v_vintr_set_valid
+-
+- /* %o0: device handle
+- * %o1: device INO
+- * %o2: pointer to unsigned long state
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_vintr_get_state
+- .type sun4v_vintr_get_state,#function
+-sun4v_vintr_get_state:
+- mov %o2, %g1
+- mov HV_FAST_VINTR_GET_STATE, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%g1]
+- retl
+- nop
+- .size sun4v_vintr_get_state, .-sun4v_vintr_get_state
+-
+- /* %o0: device handle
+- * %o1: device INO
+- * %o2: state
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_vintr_set_state
+- .type sun4v_vintr_set_state,#function
+-sun4v_vintr_set_state:
+- mov HV_FAST_VINTR_SET_STATE, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_vintr_set_state, .-sun4v_vintr_set_state
+-
+- /* %o0: device handle
+- * %o1: device INO
+- * %o2: pointer to unsigned long cpuid
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_vintr_get_target
+- .type sun4v_vintr_get_target,#function
+-sun4v_vintr_get_target:
+- mov %o2, %g1
+- mov HV_FAST_VINTR_GET_TARGET, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%g1]
+- retl
+- nop
+- .size sun4v_vintr_get_target, .-sun4v_vintr_get_target
+-
+- /* %o0: device handle
+- * %o1: device INO
+- * %o2: cpuid
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_vintr_set_target
+- .type sun4v_vintr_set_target,#function
+-sun4v_vintr_set_target:
+- mov HV_FAST_VINTR_SET_TARGET, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_vintr_set_target, .-sun4v_vintr_set_target
+-
+- /* %o0: NCS sub-function
+- * %o1: sub-function arg real-address
+- * %o2: sub-function arg size
+- *
+- * returns %o0: status
+- */
+- .globl sun4v_ncs_request
+- .type sun4v_ncs_request,#function
+-sun4v_ncs_request:
+- mov HV_FAST_NCS_REQUEST, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_ncs_request, .-sun4v_ncs_request
+-
+- .globl sun4v_svc_send
+- .type sun4v_svc_send,#function
+-sun4v_svc_send:
+- save %sp, -192, %sp
+- mov %i0, %o0
+- mov %i1, %o1
+- mov %i2, %o2
+- mov HV_FAST_SVC_SEND, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%i3]
+- ret
+- restore
+- .size sun4v_svc_send, .-sun4v_svc_send
+-
+- .globl sun4v_svc_recv
+- .type sun4v_svc_recv,#function
+-sun4v_svc_recv:
+- save %sp, -192, %sp
+- mov %i0, %o0
+- mov %i1, %o1
+- mov %i2, %o2
+- mov HV_FAST_SVC_RECV, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%i3]
+- ret
+- restore
+- .size sun4v_svc_recv, .-sun4v_svc_recv
+-
+- .globl sun4v_svc_getstatus
+- .type sun4v_svc_getstatus,#function
+-sun4v_svc_getstatus:
+- mov HV_FAST_SVC_GETSTATUS, %o5
+- mov %o1, %o4
+- ta HV_FAST_TRAP
+- stx %o1, [%o4]
+- retl
+- nop
+- .size sun4v_svc_getstatus, .-sun4v_svc_getstatus
+-
+- .globl sun4v_svc_setstatus
+- .type sun4v_svc_setstatus,#function
+-sun4v_svc_setstatus:
+- mov HV_FAST_SVC_SETSTATUS, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_svc_setstatus, .-sun4v_svc_setstatus
+-
+- .globl sun4v_svc_clrstatus
+- .type sun4v_svc_clrstatus,#function
+-sun4v_svc_clrstatus:
+- mov HV_FAST_SVC_CLRSTATUS, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_svc_clrstatus, .-sun4v_svc_clrstatus
+-
+- .globl sun4v_mmustat_conf
+- .type sun4v_mmustat_conf,#function
+-sun4v_mmustat_conf:
+- mov %o1, %o4
+- mov HV_FAST_MMUSTAT_CONF, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%o4]
+- retl
+- nop
+- .size sun4v_mmustat_conf, .-sun4v_mmustat_conf
+-
+- .globl sun4v_mmustat_info
+- .type sun4v_mmustat_info,#function
+-sun4v_mmustat_info:
+- mov %o0, %o4
+- mov HV_FAST_MMUSTAT_INFO, %o5
+- ta HV_FAST_TRAP
+- stx %o1, [%o4]
+- retl
+- nop
+- .size sun4v_mmustat_info, .-sun4v_mmustat_info
+-
+- .globl sun4v_mmu_demap_all
+- .type sun4v_mmu_demap_all,#function
+-sun4v_mmu_demap_all:
+- clr %o0
+- clr %o1
+- mov HV_MMU_ALL, %o2
+- mov HV_FAST_MMU_DEMAP_ALL, %o5
+- ta HV_FAST_TRAP
+- retl
+- nop
+- .size sun4v_mmu_demap_all, .-sun4v_mmu_demap_all
diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc64/kernel/entry.h
index 4a91e9c..32fbab6 100644
--- a/arch/sparc64/kernel/entry.h
@@ -222045,6 +276257,1420 @@
rdpr %cansave, %g1
brnz,pt %g1, etrap_save
+diff --git a/arch/sparc64/kernel/fpu_traps.S b/arch/sparc64/kernel/fpu_traps.S
+new file mode 100644
+index 0000000..a686482
+--- /dev/null
++++ b/arch/sparc64/kernel/fpu_traps.S
+@@ -0,0 +1,384 @@
++ /* This is trivial with the new code... */
++ .globl do_fpdis
++ .type do_fpdis,#function
++do_fpdis:
++ sethi %hi(TSTATE_PEF), %g4
++ rdpr %tstate, %g5
++ andcc %g5, %g4, %g0
++ be,pt %xcc, 1f
++ nop
++ rd %fprs, %g5
++ andcc %g5, FPRS_FEF, %g0
++ be,pt %xcc, 1f
++ nop
++
++ /* Legal state when DCR_IFPOE is set in Cheetah %dcr. */
++ sethi %hi(109f), %g7
++ ba,pt %xcc, etrap
++109: or %g7, %lo(109b), %g7
++ add %g0, %g0, %g0
++ ba,a,pt %xcc, rtrap
++
++1: TRAP_LOAD_THREAD_REG(%g6, %g1)
++ ldub [%g6 + TI_FPSAVED], %g5
++ wr %g0, FPRS_FEF, %fprs
++ andcc %g5, FPRS_FEF, %g0
++ be,a,pt %icc, 1f
++ clr %g7
++ ldx [%g6 + TI_GSR], %g7
++1: andcc %g5, FPRS_DL, %g0
++ bne,pn %icc, 2f
++ fzero %f0
++ andcc %g5, FPRS_DU, %g0
++ bne,pn %icc, 1f
++ fzero %f2
++ faddd %f0, %f2, %f4
++ fmuld %f0, %f2, %f6
++ faddd %f0, %f2, %f8
++ fmuld %f0, %f2, %f10
++ faddd %f0, %f2, %f12
++ fmuld %f0, %f2, %f14
++ faddd %f0, %f2, %f16
++ fmuld %f0, %f2, %f18
++ faddd %f0, %f2, %f20
++ fmuld %f0, %f2, %f22
++ faddd %f0, %f2, %f24
++ fmuld %f0, %f2, %f26
++ faddd %f0, %f2, %f28
++ fmuld %f0, %f2, %f30
++ faddd %f0, %f2, %f32
++ fmuld %f0, %f2, %f34
++ faddd %f0, %f2, %f36
++ fmuld %f0, %f2, %f38
++ faddd %f0, %f2, %f40
++ fmuld %f0, %f2, %f42
++ faddd %f0, %f2, %f44
++ fmuld %f0, %f2, %f46
++ faddd %f0, %f2, %f48
++ fmuld %f0, %f2, %f50
++ faddd %f0, %f2, %f52
++ fmuld %f0, %f2, %f54
++ faddd %f0, %f2, %f56
++ fmuld %f0, %f2, %f58
++ b,pt %xcc, fpdis_exit2
++ faddd %f0, %f2, %f60
++1: mov SECONDARY_CONTEXT, %g3
++ add %g6, TI_FPREGS + 0x80, %g1
++ faddd %f0, %f2, %f4
++ fmuld %f0, %f2, %f6
++
++661: ldxa [%g3] ASI_DMMU, %g5
++ .section .sun4v_1insn_patch, "ax"
++ .word 661b
++ ldxa [%g3] ASI_MMU, %g5
++ .previous
++
++ sethi %hi(sparc64_kern_sec_context), %g2
++ ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
++
++661: stxa %g2, [%g3] ASI_DMMU
++ .section .sun4v_1insn_patch, "ax"
++ .word 661b
++ stxa %g2, [%g3] ASI_MMU
++ .previous
++
++ membar #Sync
++ add %g6, TI_FPREGS + 0xc0, %g2
++ faddd %f0, %f2, %f8
++ fmuld %f0, %f2, %f10
++ membar #Sync
++ ldda [%g1] ASI_BLK_S, %f32
++ ldda [%g2] ASI_BLK_S, %f48
++ membar #Sync
++ faddd %f0, %f2, %f12
++ fmuld %f0, %f2, %f14
++ faddd %f0, %f2, %f16
++ fmuld %f0, %f2, %f18
++ faddd %f0, %f2, %f20
++ fmuld %f0, %f2, %f22
++ faddd %f0, %f2, %f24
++ fmuld %f0, %f2, %f26
++ faddd %f0, %f2, %f28
++ fmuld %f0, %f2, %f30
++ b,pt %xcc, fpdis_exit
++ nop
++2: andcc %g5, FPRS_DU, %g0
++ bne,pt %icc, 3f
++ fzero %f32
++ mov SECONDARY_CONTEXT, %g3
++ fzero %f34
++
++661: ldxa [%g3] ASI_DMMU, %g5
++ .section .sun4v_1insn_patch, "ax"
++ .word 661b
++ ldxa [%g3] ASI_MMU, %g5
++ .previous
++
++ add %g6, TI_FPREGS, %g1
++ sethi %hi(sparc64_kern_sec_context), %g2
++ ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
++
++661: stxa %g2, [%g3] ASI_DMMU
++ .section .sun4v_1insn_patch, "ax"
++ .word 661b
++ stxa %g2, [%g3] ASI_MMU
++ .previous
++
++ membar #Sync
++ add %g6, TI_FPREGS + 0x40, %g2
++ faddd %f32, %f34, %f36
++ fmuld %f32, %f34, %f38
++ membar #Sync
++ ldda [%g1] ASI_BLK_S, %f0
++ ldda [%g2] ASI_BLK_S, %f16
++ membar #Sync
++ faddd %f32, %f34, %f40
++ fmuld %f32, %f34, %f42
++ faddd %f32, %f34, %f44
++ fmuld %f32, %f34, %f46
++ faddd %f32, %f34, %f48
++ fmuld %f32, %f34, %f50
++ faddd %f32, %f34, %f52
++ fmuld %f32, %f34, %f54
++ faddd %f32, %f34, %f56
++ fmuld %f32, %f34, %f58
++ faddd %f32, %f34, %f60
++ fmuld %f32, %f34, %f62
++ ba,pt %xcc, fpdis_exit
++ nop
++3: mov SECONDARY_CONTEXT, %g3
++ add %g6, TI_FPREGS, %g1
++
++661: ldxa [%g3] ASI_DMMU, %g5
++ .section .sun4v_1insn_patch, "ax"
++ .word 661b
++ ldxa [%g3] ASI_MMU, %g5
++ .previous
++
++ sethi %hi(sparc64_kern_sec_context), %g2
++ ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
++
++661: stxa %g2, [%g3] ASI_DMMU
++ .section .sun4v_1insn_patch, "ax"
++ .word 661b
++ stxa %g2, [%g3] ASI_MMU
++ .previous
++
++ membar #Sync
++ mov 0x40, %g2
++ membar #Sync
++ ldda [%g1] ASI_BLK_S, %f0
++ ldda [%g1 + %g2] ASI_BLK_S, %f16
++ add %g1, 0x80, %g1
++ ldda [%g1] ASI_BLK_S, %f32
++ ldda [%g1 + %g2] ASI_BLK_S, %f48
++ membar #Sync
++fpdis_exit:
++
++661: stxa %g5, [%g3] ASI_DMMU
++ .section .sun4v_1insn_patch, "ax"
++ .word 661b
++ stxa %g5, [%g3] ASI_MMU
++ .previous
++
++ membar #Sync
++fpdis_exit2:
++ wr %g7, 0, %gsr
++ ldx [%g6 + TI_XFSR], %fsr
++ rdpr %tstate, %g3
++ or %g3, %g4, %g3 ! anal...
++ wrpr %g3, %tstate
++ wr %g0, FPRS_FEF, %fprs ! clean DU/DL bits
++ retry
++ .size do_fpdis,.-do_fpdis
++
++ .align 32
++ .type fp_other_bounce,#function
++fp_other_bounce:
++ call do_fpother
++ add %sp, PTREGS_OFF, %o0
++ ba,pt %xcc, rtrap
++ nop
++ .size fp_other_bounce,.-fp_other_bounce
++
++ .align 32
++ .globl do_fpother_check_fitos
++ .type do_fpother_check_fitos,#function
++do_fpother_check_fitos:
++ TRAP_LOAD_THREAD_REG(%g6, %g1)
++ sethi %hi(fp_other_bounce - 4), %g7
++ or %g7, %lo(fp_other_bounce - 4), %g7
++
++ /* NOTE: Need to preserve %g7 until we fully commit
++ * to the fitos fixup.
++ */
++ stx %fsr, [%g6 + TI_XFSR]
++ rdpr %tstate, %g3
++ andcc %g3, TSTATE_PRIV, %g0
++ bne,pn %xcc, do_fptrap_after_fsr
++ nop
++ ldx [%g6 + TI_XFSR], %g3
++ srlx %g3, 14, %g1
++ and %g1, 7, %g1
++ cmp %g1, 2 ! Unfinished FP-OP
++ bne,pn %xcc, do_fptrap_after_fsr
++ sethi %hi(1 << 23), %g1 ! Inexact
++ andcc %g3, %g1, %g0
++ bne,pn %xcc, do_fptrap_after_fsr
++ rdpr %tpc, %g1
++ lduwa [%g1] ASI_AIUP, %g3 ! This cannot ever fail
++#define FITOS_MASK 0xc1f83fe0
++#define FITOS_COMPARE 0x81a01880
++ sethi %hi(FITOS_MASK), %g1
++ or %g1, %lo(FITOS_MASK), %g1
++ and %g3, %g1, %g1
++ sethi %hi(FITOS_COMPARE), %g2
++ or %g2, %lo(FITOS_COMPARE), %g2
++ cmp %g1, %g2
++ bne,pn %xcc, do_fptrap_after_fsr
++ nop
++ std %f62, [%g6 + TI_FPREGS + (62 * 4)]
++ sethi %hi(fitos_table_1), %g1
++ and %g3, 0x1f, %g2
++ or %g1, %lo(fitos_table_1), %g1
++ sllx %g2, 2, %g2
++ jmpl %g1 + %g2, %g0
++ ba,pt %xcc, fitos_emul_continue
++
++fitos_table_1:
++ fitod %f0, %f62
++ fitod %f1, %f62
++ fitod %f2, %f62
++ fitod %f3, %f62
++ fitod %f4, %f62
++ fitod %f5, %f62
++ fitod %f6, %f62
++ fitod %f7, %f62
++ fitod %f8, %f62
++ fitod %f9, %f62
++ fitod %f10, %f62
++ fitod %f11, %f62
++ fitod %f12, %f62
++ fitod %f13, %f62
++ fitod %f14, %f62
++ fitod %f15, %f62
++ fitod %f16, %f62
++ fitod %f17, %f62
++ fitod %f18, %f62
++ fitod %f19, %f62
++ fitod %f20, %f62
++ fitod %f21, %f62
++ fitod %f22, %f62
++ fitod %f23, %f62
++ fitod %f24, %f62
++ fitod %f25, %f62
++ fitod %f26, %f62
++ fitod %f27, %f62
++ fitod %f28, %f62
++ fitod %f29, %f62
++ fitod %f30, %f62
++ fitod %f31, %f62
++
++fitos_emul_continue:
++ sethi %hi(fitos_table_2), %g1
++ srl %g3, 25, %g2
++ or %g1, %lo(fitos_table_2), %g1
++ and %g2, 0x1f, %g2
++ sllx %g2, 2, %g2
++ jmpl %g1 + %g2, %g0
++ ba,pt %xcc, fitos_emul_fini
++
++fitos_table_2:
++ fdtos %f62, %f0
++ fdtos %f62, %f1
++ fdtos %f62, %f2
++ fdtos %f62, %f3
++ fdtos %f62, %f4
++ fdtos %f62, %f5
++ fdtos %f62, %f6
++ fdtos %f62, %f7
++ fdtos %f62, %f8
++ fdtos %f62, %f9
++ fdtos %f62, %f10
++ fdtos %f62, %f11
++ fdtos %f62, %f12
++ fdtos %f62, %f13
++ fdtos %f62, %f14
++ fdtos %f62, %f15
++ fdtos %f62, %f16
++ fdtos %f62, %f17
++ fdtos %f62, %f18
++ fdtos %f62, %f19
++ fdtos %f62, %f20
++ fdtos %f62, %f21
++ fdtos %f62, %f22
++ fdtos %f62, %f23
++ fdtos %f62, %f24
++ fdtos %f62, %f25
++ fdtos %f62, %f26
++ fdtos %f62, %f27
++ fdtos %f62, %f28
++ fdtos %f62, %f29
++ fdtos %f62, %f30
++ fdtos %f62, %f31
++
++fitos_emul_fini:
++ ldd [%g6 + TI_FPREGS + (62 * 4)], %f62
++ done
++ .size do_fpother_check_fitos,.-do_fpother_check_fitos
++
++ .align 32
++ .globl do_fptrap
++ .type do_fptrap,#function
++do_fptrap:
++ TRAP_LOAD_THREAD_REG(%g6, %g1)
++ stx %fsr, [%g6 + TI_XFSR]
++do_fptrap_after_fsr:
++ ldub [%g6 + TI_FPSAVED], %g3
++ rd %fprs, %g1
++ or %g3, %g1, %g3
++ stb %g3, [%g6 + TI_FPSAVED]
++ rd %gsr, %g3
++ stx %g3, [%g6 + TI_GSR]
++ mov SECONDARY_CONTEXT, %g3
++
++661: ldxa [%g3] ASI_DMMU, %g5
++ .section .sun4v_1insn_patch, "ax"
++ .word 661b
++ ldxa [%g3] ASI_MMU, %g5
++ .previous
++
++ sethi %hi(sparc64_kern_sec_context), %g2
++ ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
++
++661: stxa %g2, [%g3] ASI_DMMU
++ .section .sun4v_1insn_patch, "ax"
++ .word 661b
++ stxa %g2, [%g3] ASI_MMU
++ .previous
++
++ membar #Sync
++ add %g6, TI_FPREGS, %g2
++ andcc %g1, FPRS_DL, %g0
++ be,pn %icc, 4f
++ mov 0x40, %g3
++ stda %f0, [%g2] ASI_BLK_S
++ stda %f16, [%g2 + %g3] ASI_BLK_S
++ andcc %g1, FPRS_DU, %g0
++ be,pn %icc, 5f
++4: add %g2, 128, %g2
++ stda %f32, [%g2] ASI_BLK_S
++ stda %f48, [%g2 + %g3] ASI_BLK_S
++5: mov SECONDARY_CONTEXT, %g1
++ membar #Sync
++
++661: stxa %g5, [%g1] ASI_DMMU
++ .section .sun4v_1insn_patch, "ax"
++ .word 661b
++ stxa %g5, [%g1] ASI_MMU
++ .previous
++
++ membar #Sync
++ ba,pt %xcc, etrap
++ wr %g0, 0, %fprs
++ .size do_fptrap,.-do_fptrap
+diff --git a/arch/sparc64/kernel/getsetcc.S b/arch/sparc64/kernel/getsetcc.S
+new file mode 100644
+index 0000000..a14d272
+--- /dev/null
++++ b/arch/sparc64/kernel/getsetcc.S
+@@ -0,0 +1,24 @@
++ .globl getcc
++ .type getcc,#function
++getcc:
++ ldx [%o0 + PT_V9_TSTATE], %o1
++ srlx %o1, 32, %o1
++ and %o1, 0xf, %o1
++ retl
++ stx %o1, [%o0 + PT_V9_G1]
++ .size getcc,.-getcc
++
++ .globl setcc
++ .type setcc,#function
++setcc:
++ ldx [%o0 + PT_V9_TSTATE], %o1
++ ldx [%o0 + PT_V9_G1], %o2
++ or %g0, %ulo(TSTATE_ICC), %o3
++ sllx %o3, 32, %o3
++ andn %o1, %o3, %o1
++ sllx %o2, 32, %o2
++ and %o2, %o3, %o2
++ or %o1, %o2, %o1
++ retl
++ stx %o1, [%o0 + PT_V9_TSTATE]
++ .size setcc,.-setcc
+diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
+index 34f8ff5..c9afef0 100644
+--- a/arch/sparc64/kernel/head.S
++++ b/arch/sparc64/kernel/head.S
+@@ -27,6 +27,10 @@
+ #include <asm/ttable.h>
+ #include <asm/mmu.h>
+ #include <asm/cpudata.h>
++#include <asm/pil.h>
++#include <asm/estate.h>
++#include <asm/sfafsr.h>
++#include <asm/unistd.h>
+
+ /* This section from from _start to sparc64_boot_end should fit into
+ * 0x0000000000404000 to 0x0000000000408000.
+@@ -823,7 +827,16 @@ sparc64_boot_end:
+ #include "etrap.S"
+ #include "rtrap.S"
+ #include "winfixup.S"
+-#include "entry.S"
++#include "fpu_traps.S"
++#include "ivec.S"
++#include "getsetcc.S"
++#include "utrap.S"
++#include "spiterrs.S"
++#include "cherrs.S"
++#include "misctrap.S"
++#include "syscalls.S"
++#include "helpers.S"
++#include "hvcalls.S"
+ #include "sun4v_tlb_miss.S"
+ #include "sun4v_ivec.S"
+ #include "ktlb.S"
+diff --git a/arch/sparc64/kernel/helpers.S b/arch/sparc64/kernel/helpers.S
+new file mode 100644
+index 0000000..314dd0c
+--- /dev/null
++++ b/arch/sparc64/kernel/helpers.S
+@@ -0,0 +1,63 @@
++ .align 32
++ .globl __flushw_user
++ .type __flushw_user,#function
++__flushw_user:
++ rdpr %otherwin, %g1
++ brz,pn %g1, 2f
++ clr %g2
++1: save %sp, -128, %sp
++ rdpr %otherwin, %g1
++ brnz,pt %g1, 1b
++ add %g2, 1, %g2
++1: sub %g2, 1, %g2
++ brnz,pt %g2, 1b
++ restore %g0, %g0, %g0
++2: retl
++ nop
++ .size __flushw_user,.-__flushw_user
++
++ /* Flush %fp and %i7 to the stack for all register
++ * windows active inside of the cpu. This allows
++ * show_stack_trace() to avoid using an expensive
++ * 'flushw'.
++ */
++ .globl stack_trace_flush
++ .type stack_trace_flush,#function
++stack_trace_flush:
++ rdpr %pstate, %o0
++ wrpr %o0, PSTATE_IE, %pstate
++
++ rdpr %cwp, %g1
++ rdpr %canrestore, %g2
++ sub %g1, 1, %g3
++
++1: brz,pn %g2, 2f
++ sub %g2, 1, %g2
++ wrpr %g3, %cwp
++ stx %fp, [%sp + STACK_BIAS + RW_V9_I6]
++ stx %i7, [%sp + STACK_BIAS + RW_V9_I7]
++ ba,pt %xcc, 1b
++ sub %g3, 1, %g3
++
++2: wrpr %g1, %cwp
++ wrpr %o0, %pstate
++
++ retl
++ nop
++ .size stack_trace_flush,.-stack_trace_flush
++
++#ifdef CONFIG_SMP
++ .globl hard_smp_processor_id
++ .type hard_smp_processor_id,#function
++hard_smp_processor_id:
++#endif
++ .globl real_hard_smp_processor_id
++ .type real_hard_smp_processor_id,#function
++real_hard_smp_processor_id:
++ __GET_CPUID(%o0)
++ retl
++ nop
++#ifdef CONFIG_SMP
++ .size hard_smp_processor_id,.-hard_smp_processor_id
++#endif
++ .size real_hard_smp_processor_id,.-real_hard_smp_processor_id
+diff --git a/arch/sparc64/kernel/hvcalls.S b/arch/sparc64/kernel/hvcalls.S
+new file mode 100644
+index 0000000..a2810f3
+--- /dev/null
++++ b/arch/sparc64/kernel/hvcalls.S
+@@ -0,0 +1,886 @@
++ /* %o0: devhandle
++ * %o1: devino
++ *
++ * returns %o0: sysino
++ */
++ .globl sun4v_devino_to_sysino
++ .type sun4v_devino_to_sysino,#function
++sun4v_devino_to_sysino:
++ mov HV_FAST_INTR_DEVINO2SYSINO, %o5
++ ta HV_FAST_TRAP
++ retl
++ mov %o1, %o0
++ .size sun4v_devino_to_sysino, .-sun4v_devino_to_sysino
++
++ /* %o0: sysino
++ *
++ * returns %o0: intr_enabled (HV_INTR_{DISABLED,ENABLED})
++ */
++ .globl sun4v_intr_getenabled
++ .type sun4v_intr_getenabled,#function
++sun4v_intr_getenabled:
++ mov HV_FAST_INTR_GETENABLED, %o5
++ ta HV_FAST_TRAP
++ retl
++ mov %o1, %o0
++ .size sun4v_intr_getenabled, .-sun4v_intr_getenabled
++
++ /* %o0: sysino
++ * %o1: intr_enabled (HV_INTR_{DISABLED,ENABLED})
++ */
++ .globl sun4v_intr_setenabled
++ .type sun4v_intr_setenabled,#function
++sun4v_intr_setenabled:
++ mov HV_FAST_INTR_SETENABLED, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_intr_setenabled, .-sun4v_intr_setenabled
++
++ /* %o0: sysino
++ *
++ * returns %o0: intr_state (HV_INTR_STATE_*)
++ */
++ .globl sun4v_intr_getstate
++ .type sun4v_intr_getstate,#function
++sun4v_intr_getstate:
++ mov HV_FAST_INTR_GETSTATE, %o5
++ ta HV_FAST_TRAP
++ retl
++ mov %o1, %o0
++ .size sun4v_intr_getstate, .-sun4v_intr_getstate
++
++ /* %o0: sysino
++ * %o1: intr_state (HV_INTR_STATE_*)
++ */
++ .globl sun4v_intr_setstate
++ .type sun4v_intr_setstate,#function
++sun4v_intr_setstate:
++ mov HV_FAST_INTR_SETSTATE, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_intr_setstate, .-sun4v_intr_setstate
++
++ /* %o0: sysino
++ *
++ * returns %o0: cpuid
++ */
++ .globl sun4v_intr_gettarget
++ .type sun4v_intr_gettarget,#function
++sun4v_intr_gettarget:
++ mov HV_FAST_INTR_GETTARGET, %o5
++ ta HV_FAST_TRAP
++ retl
++ mov %o1, %o0
++ .size sun4v_intr_gettarget, .-sun4v_intr_gettarget
++
++ /* %o0: sysino
++ * %o1: cpuid
++ */
++ .globl sun4v_intr_settarget
++ .type sun4v_intr_settarget,#function
++sun4v_intr_settarget:
++ mov HV_FAST_INTR_SETTARGET, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_intr_settarget, .-sun4v_intr_settarget
++
++ /* %o0: cpuid
++ * %o1: pc
++ * %o2: rtba
++ * %o3: arg0
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_cpu_start
++ .type sun4v_cpu_start,#function
++sun4v_cpu_start:
++ mov HV_FAST_CPU_START, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_cpu_start, .-sun4v_cpu_start
++
++ /* %o0: cpuid
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_cpu_stop
++ .type sun4v_cpu_stop,#function
++sun4v_cpu_stop:
++ mov HV_FAST_CPU_STOP, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_cpu_stop, .-sun4v_cpu_stop
++
++ /* returns %o0: status */
++ .globl sun4v_cpu_yield
++ .type sun4v_cpu_yield, #function
++sun4v_cpu_yield:
++ mov HV_FAST_CPU_YIELD, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_cpu_yield, .-sun4v_cpu_yield
++
++ /* %o0: type
++ * %o1: queue paddr
++ * %o2: num queue entries
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_cpu_qconf
++ .type sun4v_cpu_qconf,#function
++sun4v_cpu_qconf:
++ mov HV_FAST_CPU_QCONF, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_cpu_qconf, .-sun4v_cpu_qconf
++
++ /* %o0: num cpus in cpu list
++ * %o1: cpu list paddr
++ * %o2: mondo block paddr
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_cpu_mondo_send
++ .type sun4v_cpu_mondo_send,#function
++sun4v_cpu_mondo_send:
++ mov HV_FAST_CPU_MONDO_SEND, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_cpu_mondo_send, .-sun4v_cpu_mondo_send
++
++ /* %o0: CPU ID
++ *
++ * returns %o0: -status if status non-zero, else
++ * %o0: cpu state as HV_CPU_STATE_*
++ */
++ .globl sun4v_cpu_state
++ .type sun4v_cpu_state,#function
++sun4v_cpu_state:
++ mov HV_FAST_CPU_STATE, %o5
++ ta HV_FAST_TRAP
++ brnz,pn %o0, 1f
++ sub %g0, %o0, %o0
++ mov %o1, %o0
++1: retl
++ nop
++ .size sun4v_cpu_state, .-sun4v_cpu_state
++
++ /* %o0: virtual address
++ * %o1: must be zero
++ * %o2: TTE
++ * %o3: HV_MMU_* flags
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_mmu_map_perm_addr
++ .type sun4v_mmu_map_perm_addr,#function
++sun4v_mmu_map_perm_addr:
++ mov HV_FAST_MMU_MAP_PERM_ADDR, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_mmu_map_perm_addr, .-sun4v_mmu_map_perm_addr
++
++ /* %o0: number of TSB descriptions
++ * %o1: TSB descriptions real address
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_mmu_tsb_ctx0
++ .type sun4v_mmu_tsb_ctx0,#function
++sun4v_mmu_tsb_ctx0:
++ mov HV_FAST_MMU_TSB_CTX0, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_mmu_tsb_ctx0, .-sun4v_mmu_tsb_ctx0
++
++ /* %o0: API group number
++ * %o1: pointer to unsigned long major number storage
++ * %o2: pointer to unsigned long minor number storage
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_get_version
++ .type sun4v_get_version,#function
++sun4v_get_version:
++ mov HV_CORE_GET_VER, %o5
++ mov %o1, %o3
++ mov %o2, %o4
++ ta HV_CORE_TRAP
++ stx %o1, [%o3]
++ retl
++ stx %o2, [%o4]
++ .size sun4v_get_version, .-sun4v_get_version
++
++ /* %o0: API group number
++ * %o1: desired major number
++ * %o2: desired minor number
++ * %o3: pointer to unsigned long actual minor number storage
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_set_version
++ .type sun4v_set_version,#function
++sun4v_set_version:
++ mov HV_CORE_SET_VER, %o5
++ mov %o3, %o4
++ ta HV_CORE_TRAP
++ retl
++ stx %o1, [%o4]
++ .size sun4v_set_version, .-sun4v_set_version
++
++ /* %o0: pointer to unsigned long time
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_tod_get
++ .type sun4v_tod_get,#function
++sun4v_tod_get:
++ mov %o0, %o4
++ mov HV_FAST_TOD_GET, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%o4]
++ retl
++ nop
++ .size sun4v_tod_get, .-sun4v_tod_get
++
++ /* %o0: time
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_tod_set
++ .type sun4v_tod_set,#function
++sun4v_tod_set:
++ mov HV_FAST_TOD_SET, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_tod_set, .-sun4v_tod_set
++
++ /* %o0: pointer to unsigned long status
++ *
++ * returns %o0: signed character
++ */
++ .globl sun4v_con_getchar
++ .type sun4v_con_getchar,#function
++sun4v_con_getchar:
++ mov %o0, %o4
++ mov HV_FAST_CONS_GETCHAR, %o5
++ clr %o0
++ clr %o1
++ ta HV_FAST_TRAP
++ stx %o0, [%o4]
++ retl
++ sra %o1, 0, %o0
++ .size sun4v_con_getchar, .-sun4v_con_getchar
++
++ /* %o0: signed long character
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_con_putchar
++ .type sun4v_con_putchar,#function
++sun4v_con_putchar:
++ mov HV_FAST_CONS_PUTCHAR, %o5
++ ta HV_FAST_TRAP
++ retl
++ sra %o0, 0, %o0
++ .size sun4v_con_putchar, .-sun4v_con_putchar
++
++ /* %o0: buffer real address
++ * %o1: buffer size
++ * %o2: pointer to unsigned long bytes_read
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_con_read
++ .type sun4v_con_read,#function
++sun4v_con_read:
++ mov %o2, %o4
++ mov HV_FAST_CONS_READ, %o5
++ ta HV_FAST_TRAP
++ brnz %o0, 1f
++ cmp %o1, -1 /* break */
++ be,a,pn %icc, 1f
++ mov %o1, %o0
++ cmp %o1, -2 /* hup */
++ be,a,pn %icc, 1f
++ mov %o1, %o0
++ stx %o1, [%o4]
++1: retl
++ nop
++ .size sun4v_con_read, .-sun4v_con_read
++
++ /* %o0: buffer real address
++ * %o1: buffer size
++ * %o2: pointer to unsigned long bytes_written
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_con_write
++ .type sun4v_con_write,#function
++sun4v_con_write:
++ mov %o2, %o4
++ mov HV_FAST_CONS_WRITE, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%o4]
++ retl
++ nop
++ .size sun4v_con_write, .-sun4v_con_write
++
++ /* %o0: soft state
++ * %o1: address of description string
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_mach_set_soft_state
++ .type sun4v_mach_set_soft_state,#function
++sun4v_mach_set_soft_state:
++ mov HV_FAST_MACH_SET_SOFT_STATE, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_mach_set_soft_state, .-sun4v_mach_set_soft_state
++
++ /* %o0: exit code
++ *
++ * Does not return.
++ */
++ .globl sun4v_mach_exit
++ .type sun4v_mach_exit,#function
++sun4v_mach_exit:
++ mov HV_FAST_MACH_EXIT, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_mach_exit, .-sun4v_mach_exit
++
++ /* %o0: buffer real address
++ * %o1: buffer length
++ * %o2: pointer to unsigned long real_buf_len
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_mach_desc
++ .type sun4v_mach_desc,#function
++sun4v_mach_desc:
++ mov %o2, %o4
++ mov HV_FAST_MACH_DESC, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%o4]
++ retl
++ nop
++ .size sun4v_mach_desc, .-sun4v_mach_desc
++
++ /* %o0: new timeout in milliseconds
++ * %o1: pointer to unsigned long orig_timeout
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_mach_set_watchdog
++ .type sun4v_mach_set_watchdog,#function
++sun4v_mach_set_watchdog:
++ mov %o1, %o4
++ mov HV_FAST_MACH_SET_WATCHDOG, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%o4]
++ retl
++ nop
++ .size sun4v_mach_set_watchdog, .-sun4v_mach_set_watchdog
++
++ /* No inputs and does not return. */
++ .globl sun4v_mach_sir
++ .type sun4v_mach_sir,#function
++sun4v_mach_sir:
++ mov %o1, %o4
++ mov HV_FAST_MACH_SIR, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%o4]
++ retl
++ nop
++ .size sun4v_mach_sir, .-sun4v_mach_sir
++
++ /* %o0: channel
++ * %o1: ra
++ * %o2: num_entries
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_ldc_tx_qconf
++ .type sun4v_ldc_tx_qconf,#function
++sun4v_ldc_tx_qconf:
++ mov HV_FAST_LDC_TX_QCONF, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_ldc_tx_qconf, .-sun4v_ldc_tx_qconf
++
++ /* %o0: channel
++ * %o1: pointer to unsigned long ra
++ * %o2: pointer to unsigned long num_entries
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_ldc_tx_qinfo
++ .type sun4v_ldc_tx_qinfo,#function
++sun4v_ldc_tx_qinfo:
++ mov %o1, %g1
++ mov %o2, %g2
++ mov HV_FAST_LDC_TX_QINFO, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%g1]
++ stx %o2, [%g2]
++ retl
++ nop
++ .size sun4v_ldc_tx_qinfo, .-sun4v_ldc_tx_qinfo
++
++ /* %o0: channel
++ * %o1: pointer to unsigned long head_off
++ * %o2: pointer to unsigned long tail_off
++ * %o2: pointer to unsigned long chan_state
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_ldc_tx_get_state
++ .type sun4v_ldc_tx_get_state,#function
++sun4v_ldc_tx_get_state:
++ mov %o1, %g1
++ mov %o2, %g2
++ mov %o3, %g3
++ mov HV_FAST_LDC_TX_GET_STATE, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%g1]
++ stx %o2, [%g2]
++ stx %o3, [%g3]
++ retl
++ nop
++ .size sun4v_ldc_tx_get_state, .-sun4v_ldc_tx_get_state
++
++ /* %o0: channel
++ * %o1: tail_off
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_ldc_tx_set_qtail
++ .type sun4v_ldc_tx_set_qtail,#function
++sun4v_ldc_tx_set_qtail:
++ mov HV_FAST_LDC_TX_SET_QTAIL, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_ldc_tx_set_qtail, .-sun4v_ldc_tx_set_qtail
++
++ /* %o0: channel
++ * %o1: ra
++ * %o2: num_entries
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_ldc_rx_qconf
++ .type sun4v_ldc_rx_qconf,#function
++sun4v_ldc_rx_qconf:
++ mov HV_FAST_LDC_RX_QCONF, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_ldc_rx_qconf, .-sun4v_ldc_rx_qconf
++
++ /* %o0: channel
++ * %o1: pointer to unsigned long ra
++ * %o2: pointer to unsigned long num_entries
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_ldc_rx_qinfo
++ .type sun4v_ldc_rx_qinfo,#function
++sun4v_ldc_rx_qinfo:
++ mov %o1, %g1
++ mov %o2, %g2
++ mov HV_FAST_LDC_RX_QINFO, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%g1]
++ stx %o2, [%g2]
++ retl
++ nop
++ .size sun4v_ldc_rx_qinfo, .-sun4v_ldc_rx_qinfo
++
++ /* %o0: channel
++ * %o1: pointer to unsigned long head_off
++ * %o2: pointer to unsigned long tail_off
++ * %o2: pointer to unsigned long chan_state
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_ldc_rx_get_state
++ .type sun4v_ldc_rx_get_state,#function
++sun4v_ldc_rx_get_state:
++ mov %o1, %g1
++ mov %o2, %g2
++ mov %o3, %g3
++ mov HV_FAST_LDC_RX_GET_STATE, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%g1]
++ stx %o2, [%g2]
++ stx %o3, [%g3]
++ retl
++ nop
++ .size sun4v_ldc_rx_get_state, .-sun4v_ldc_rx_get_state
++
++ /* %o0: channel
++ * %o1: head_off
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_ldc_rx_set_qhead
++ .type sun4v_ldc_rx_set_qhead,#function
++sun4v_ldc_rx_set_qhead:
++ mov HV_FAST_LDC_RX_SET_QHEAD, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_ldc_rx_set_qhead, .-sun4v_ldc_rx_set_qhead
++
++ /* %o0: channel
++ * %o1: ra
++ * %o2: num_entries
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_ldc_set_map_table
++ .type sun4v_ldc_set_map_table,#function
++sun4v_ldc_set_map_table:
++ mov HV_FAST_LDC_SET_MAP_TABLE, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_ldc_set_map_table, .-sun4v_ldc_set_map_table
++
++ /* %o0: channel
++ * %o1: pointer to unsigned long ra
++ * %o2: pointer to unsigned long num_entries
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_ldc_get_map_table
++ .type sun4v_ldc_get_map_table,#function
++sun4v_ldc_get_map_table:
++ mov %o1, %g1
++ mov %o2, %g2
++ mov HV_FAST_LDC_GET_MAP_TABLE, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%g1]
++ stx %o2, [%g2]
++ retl
++ nop
++ .size sun4v_ldc_get_map_table, .-sun4v_ldc_get_map_table
++
++ /* %o0: channel
++ * %o1: dir_code
++ * %o2: tgt_raddr
++ * %o3: lcl_raddr
++ * %o4: len
++ * %o5: pointer to unsigned long actual_len
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_ldc_copy
++ .type sun4v_ldc_copy,#function
++sun4v_ldc_copy:
++ mov %o5, %g1
++ mov HV_FAST_LDC_COPY, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%g1]
++ retl
++ nop
++ .size sun4v_ldc_copy, .-sun4v_ldc_copy
++
++ /* %o0: channel
++ * %o1: cookie
++ * %o2: pointer to unsigned long ra
++ * %o3: pointer to unsigned long perm
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_ldc_mapin
++ .type sun4v_ldc_mapin,#function
++sun4v_ldc_mapin:
++ mov %o2, %g1
++ mov %o3, %g2
++ mov HV_FAST_LDC_MAPIN, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%g1]
++ stx %o2, [%g2]
++ retl
++ nop
++ .size sun4v_ldc_mapin, .-sun4v_ldc_mapin
++
++ /* %o0: ra
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_ldc_unmap
++ .type sun4v_ldc_unmap,#function
++sun4v_ldc_unmap:
++ mov HV_FAST_LDC_UNMAP, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_ldc_unmap, .-sun4v_ldc_unmap
++
++ /* %o0: channel
++ * %o1: cookie
++ * %o2: mte_cookie
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_ldc_revoke
++ .type sun4v_ldc_revoke,#function
++sun4v_ldc_revoke:
++ mov HV_FAST_LDC_REVOKE, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_ldc_revoke, .-sun4v_ldc_revoke
++
++ /* %o0: device handle
++ * %o1: device INO
++ * %o2: pointer to unsigned long cookie
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_vintr_get_cookie
++ .type sun4v_vintr_get_cookie,#function
++sun4v_vintr_get_cookie:
++ mov %o2, %g1
++ mov HV_FAST_VINTR_GET_COOKIE, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%g1]
++ retl
++ nop
++ .size sun4v_vintr_get_cookie, .-sun4v_vintr_get_cookie
++
++ /* %o0: device handle
++ * %o1: device INO
++ * %o2: cookie
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_vintr_set_cookie
++ .type sun4v_vintr_set_cookie,#function
++sun4v_vintr_set_cookie:
++ mov HV_FAST_VINTR_SET_COOKIE, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_vintr_set_cookie, .-sun4v_vintr_set_cookie
++
++ /* %o0: device handle
++ * %o1: device INO
++ * %o2: pointer to unsigned long valid_state
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_vintr_get_valid
++ .type sun4v_vintr_get_valid,#function
++sun4v_vintr_get_valid:
++ mov %o2, %g1
++ mov HV_FAST_VINTR_GET_VALID, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%g1]
++ retl
++ nop
++ .size sun4v_vintr_get_valid, .-sun4v_vintr_get_valid
++
++ /* %o0: device handle
++ * %o1: device INO
++ * %o2: valid_state
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_vintr_set_valid
++ .type sun4v_vintr_set_valid,#function
++sun4v_vintr_set_valid:
++ mov HV_FAST_VINTR_SET_VALID, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_vintr_set_valid, .-sun4v_vintr_set_valid
++
++ /* %o0: device handle
++ * %o1: device INO
++ * %o2: pointer to unsigned long state
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_vintr_get_state
++ .type sun4v_vintr_get_state,#function
++sun4v_vintr_get_state:
++ mov %o2, %g1
++ mov HV_FAST_VINTR_GET_STATE, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%g1]
++ retl
++ nop
++ .size sun4v_vintr_get_state, .-sun4v_vintr_get_state
++
++ /* %o0: device handle
++ * %o1: device INO
++ * %o2: state
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_vintr_set_state
++ .type sun4v_vintr_set_state,#function
++sun4v_vintr_set_state:
++ mov HV_FAST_VINTR_SET_STATE, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_vintr_set_state, .-sun4v_vintr_set_state
++
++ /* %o0: device handle
++ * %o1: device INO
++ * %o2: pointer to unsigned long cpuid
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_vintr_get_target
++ .type sun4v_vintr_get_target,#function
++sun4v_vintr_get_target:
++ mov %o2, %g1
++ mov HV_FAST_VINTR_GET_TARGET, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%g1]
++ retl
++ nop
++ .size sun4v_vintr_get_target, .-sun4v_vintr_get_target
++
++ /* %o0: device handle
++ * %o1: device INO
++ * %o2: cpuid
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_vintr_set_target
++ .type sun4v_vintr_set_target,#function
++sun4v_vintr_set_target:
++ mov HV_FAST_VINTR_SET_TARGET, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_vintr_set_target, .-sun4v_vintr_set_target
++
++ /* %o0: NCS sub-function
++ * %o1: sub-function arg real-address
++ * %o2: sub-function arg size
++ *
++ * returns %o0: status
++ */
++ .globl sun4v_ncs_request
++ .type sun4v_ncs_request,#function
++sun4v_ncs_request:
++ mov HV_FAST_NCS_REQUEST, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_ncs_request, .-sun4v_ncs_request
++
++ .globl sun4v_svc_send
++ .type sun4v_svc_send,#function
++sun4v_svc_send:
++ save %sp, -192, %sp
++ mov %i0, %o0
++ mov %i1, %o1
++ mov %i2, %o2
++ mov HV_FAST_SVC_SEND, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%i3]
++ ret
++ restore
++ .size sun4v_svc_send, .-sun4v_svc_send
++
++ .globl sun4v_svc_recv
++ .type sun4v_svc_recv,#function
++sun4v_svc_recv:
++ save %sp, -192, %sp
++ mov %i0, %o0
++ mov %i1, %o1
++ mov %i2, %o2
++ mov HV_FAST_SVC_RECV, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%i3]
++ ret
++ restore
++ .size sun4v_svc_recv, .-sun4v_svc_recv
++
++ .globl sun4v_svc_getstatus
++ .type sun4v_svc_getstatus,#function
++sun4v_svc_getstatus:
++ mov HV_FAST_SVC_GETSTATUS, %o5
++ mov %o1, %o4
++ ta HV_FAST_TRAP
++ stx %o1, [%o4]
++ retl
++ nop
++ .size sun4v_svc_getstatus, .-sun4v_svc_getstatus
++
++ .globl sun4v_svc_setstatus
++ .type sun4v_svc_setstatus,#function
++sun4v_svc_setstatus:
++ mov HV_FAST_SVC_SETSTATUS, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_svc_setstatus, .-sun4v_svc_setstatus
++
++ .globl sun4v_svc_clrstatus
++ .type sun4v_svc_clrstatus,#function
++sun4v_svc_clrstatus:
++ mov HV_FAST_SVC_CLRSTATUS, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_svc_clrstatus, .-sun4v_svc_clrstatus
++
++ .globl sun4v_mmustat_conf
++ .type sun4v_mmustat_conf,#function
++sun4v_mmustat_conf:
++ mov %o1, %o4
++ mov HV_FAST_MMUSTAT_CONF, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%o4]
++ retl
++ nop
++ .size sun4v_mmustat_conf, .-sun4v_mmustat_conf
++
++ .globl sun4v_mmustat_info
++ .type sun4v_mmustat_info,#function
++sun4v_mmustat_info:
++ mov %o0, %o4
++ mov HV_FAST_MMUSTAT_INFO, %o5
++ ta HV_FAST_TRAP
++ stx %o1, [%o4]
++ retl
++ nop
++ .size sun4v_mmustat_info, .-sun4v_mmustat_info
++
++ .globl sun4v_mmu_demap_all
++ .type sun4v_mmu_demap_all,#function
++sun4v_mmu_demap_all:
++ clr %o0
++ clr %o1
++ mov HV_MMU_ALL, %o2
++ mov HV_FAST_MMU_DEMAP_ALL, %o5
++ ta HV_FAST_TRAP
++ retl
++ nop
++ .size sun4v_mmu_demap_all, .-sun4v_mmu_demap_all
diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
index 756fa24..2a37a6c 100644
--- a/arch/sparc64/kernel/iommu.c
@@ -222135,18 +277761,471 @@
memset((char *)first_page, 0, PAGE_SIZE << order);
iommu = dev->archdata.iommu;
+diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
+index eb88bd6..b441a26 100644
+--- a/arch/sparc64/kernel/irq.c
++++ b/arch/sparc64/kernel/irq.c
+@@ -1,6 +1,6 @@
+ /* irq.c: UltraSparc IRQ handling/init/registry.
+ *
+- * Copyright (C) 1997, 2007 David S. Miller (davem at davemloft.net)
++ * Copyright (C) 1997, 2007, 2008 David S. Miller (davem at davemloft.net)
+ * Copyright (C) 1998 Eddie C. Dost (ecd at skynet.be)
+ * Copyright (C) 1998 Jakub Jelinek (jj at ultra.linux.cz)
+ */
+@@ -308,6 +308,7 @@ static void sun4u_irq_enable(unsigned int virt_irq)
+ IMAP_AID_SAFARI | IMAP_NID_SAFARI);
+ val |= tid | IMAP_VALID;
+ upa_writeq(val, imap);
++ upa_writeq(ICLR_IDLE, data->iclr);
+ }
+ }
+
diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c
-index b5f7b35..a2af5ed 100644
+deleted file mode 100644
+index b5f7b35..0000000
--- 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;
++++ /dev/null
+@@ -1,190 +0,0 @@
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/pci.h>
+-#include <linux/slab.h>
+-#include <asm/oplib.h>
+-#include <asm/prom.h>
+-#include <asm/of_device.h>
+-#include <asm/isa.h>
+-
+-struct sparc_isa_bridge *isa_chain;
+-
+-static void __init fatal_err(const char *reason)
+-{
+- prom_printf("ISA: fatal error, %s.\n", reason);
+-}
+-
+-static void __init report_dev(struct sparc_isa_device *isa_dev, int child)
+-{
+- if (child)
+- printk(" (%s)", isa_dev->prom_node->name);
+- else
+- printk(" [%s", isa_dev->prom_node->name);
+-}
+-
+-static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev)
+-{
+- struct of_device *op = of_find_device_by_node(isa_dev->prom_node);
+-
+- memcpy(&isa_dev->resource, &op->resource[0], sizeof(struct resource));
+-}
+-
+-static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev)
+-{
+- struct of_device *op = of_find_device_by_node(isa_dev->prom_node);
+-
+- if (!op || !op->num_irqs) {
+- isa_dev->irq = PCI_IRQ_NONE;
+- } else {
+- isa_dev->irq = op->irqs[0];
+- }
+-}
+-
+-static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev)
+-{
+- struct device_node *dp = parent_isa_dev->prom_node->child;
+-
+- if (!dp)
+- return;
+-
+- printk(" ->");
+- while (dp) {
+- struct sparc_isa_device *isa_dev;
+-
+- isa_dev = kzalloc(sizeof(*isa_dev), GFP_KERNEL);
+- if (!isa_dev) {
+- fatal_err("cannot allocate child isa_dev");
+- prom_halt();
+- }
+-
+- /* Link it in to parent. */
+- isa_dev->next = parent_isa_dev->child;
+- parent_isa_dev->child = isa_dev;
+-
+- isa_dev->bus = parent_isa_dev->bus;
+- isa_dev->prom_node = dp;
+-
+- isa_dev_get_resource(isa_dev);
+- isa_dev_get_irq(isa_dev);
+-
+- report_dev(isa_dev, 1);
+-
+- dp = dp->sibling;
+- }
+-}
+-
+-static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
+-{
+- struct device_node *dp = isa_br->prom_node->child;
+-
+- while (dp) {
+- struct sparc_isa_device *isa_dev;
+- struct dev_archdata *sd;
+-
+- isa_dev = kzalloc(sizeof(*isa_dev), GFP_KERNEL);
+- if (!isa_dev) {
+- printk(KERN_DEBUG "ISA: cannot allocate isa_dev");
+- return;
+- }
+-
+- sd = &isa_dev->ofdev.dev.archdata;
+- sd->prom_node = dp;
+- sd->op = &isa_dev->ofdev;
+- sd->iommu = isa_br->ofdev.dev.parent->archdata.iommu;
+- sd->stc = isa_br->ofdev.dev.parent->archdata.stc;
+-
+- isa_dev->ofdev.node = dp;
+- isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev;
+- isa_dev->ofdev.dev.bus = &isa_bus_type;
+- sprintf(isa_dev->ofdev.dev.bus_id, "isa[%08x]", dp->node);
+-
+- /* Register with core */
+- if (of_device_register(&isa_dev->ofdev) != 0) {
+- printk(KERN_DEBUG "isa: device registration error for %s!\n",
+- dp->path_component_name);
+- kfree(isa_dev);
+- goto next_sibling;
+- }
+-
+- /* Link it in. */
+- isa_dev->next = NULL;
+- if (isa_br->devices == NULL) {
+- isa_br->devices = isa_dev;
+- } else {
+- struct sparc_isa_device *tmp = isa_br->devices;
+-
+- while (tmp->next)
+- tmp = tmp->next;
+-
+- tmp->next = isa_dev;
+- }
+-
+- isa_dev->bus = isa_br;
+- isa_dev->prom_node = dp;
+-
+- isa_dev_get_resource(isa_dev);
+- isa_dev_get_irq(isa_dev);
+-
+- report_dev(isa_dev, 0);
+-
+- isa_fill_children(isa_dev);
+-
+- printk("]");
+-
+- next_sibling:
+- dp = dp->sibling;
+- }
+-}
+-
+-void __init isa_init(void)
+-{
+- struct pci_dev *pdev;
+- unsigned short vendor, device;
+- int index = 0;
+-
+- vendor = PCI_VENDOR_ID_AL;
+- device = PCI_DEVICE_ID_AL_M1533;
+-
+- pdev = NULL;
+- while ((pdev = pci_get_device(vendor, device, pdev)) != NULL) {
+- struct sparc_isa_bridge *isa_br;
+- struct device_node *dp;
+-
+- dp = pci_device_to_OF_node(pdev);
+-
+- isa_br = kzalloc(sizeof(*isa_br), GFP_KERNEL);
+- if (!isa_br) {
+- printk(KERN_DEBUG "isa: cannot allocate sparc_isa_bridge");
+- pci_dev_put(pdev);
+- return;
+- }
+-
+- isa_br->ofdev.node = dp;
+- isa_br->ofdev.dev.parent = &pdev->dev;
+- isa_br->ofdev.dev.bus = &isa_bus_type;
+- sprintf(isa_br->ofdev.dev.bus_id, "isa%d", index);
+-
+- /* Register with core */
+- if (of_device_register(&isa_br->ofdev) != 0) {
+- printk(KERN_DEBUG "isa: device registration error for %s!\n",
+- dp->path_component_name);
+- kfree(isa_br);
+- pci_dev_put(pdev);
+- return;
+- }
+-
+- /* Link it in. */
+- isa_br->next = isa_chain;
+- isa_chain = isa_br;
+-
+- isa_br->self = pdev;
+- isa_br->index = index++;
+- isa_br->prom_node = dp;
+-
+- printk("isa%d:", isa_br->index);
+-
+- isa_fill_devices(isa_br);
+-
+- printk("\n");
+- }
+-}
+diff --git a/arch/sparc64/kernel/ivec.S b/arch/sparc64/kernel/ivec.S
+new file mode 100644
+index 0000000..d29f92e
+--- /dev/null
++++ b/arch/sparc64/kernel/ivec.S
+@@ -0,0 +1,51 @@
++ /* The registers for cross calls will be:
++ *
++ * DATA 0: [low 32-bits] Address of function to call, jmp to this
++ * [high 32-bits] MMU Context Argument 0, place in %g5
++ * DATA 1: Address Argument 1, place in %g1
++ * DATA 2: Address Argument 2, place in %g7
++ *
++ * With this method we can do most of the cross-call tlb/cache
++ * flushing very quickly.
++ */
++ .align 32
++ .globl do_ivec
++ .type do_ivec,#function
++do_ivec:
++ mov 0x40, %g3
++ ldxa [%g3 + %g0] ASI_INTR_R, %g3
++ sethi %hi(KERNBASE), %g4
++ cmp %g3, %g4
++ bgeu,pn %xcc, do_ivec_xcall
++ srlx %g3, 32, %g5
++ stxa %g0, [%g0] ASI_INTR_RECEIVE
++ membar #Sync
++
++ sethi %hi(ivector_table_pa), %g2
++ ldx [%g2 + %lo(ivector_table_pa)], %g2
++ sllx %g3, 4, %g3
++ add %g2, %g3, %g3
++
++ TRAP_LOAD_IRQ_WORK_PA(%g6, %g1)
++
++ ldx [%g6], %g5
++ stxa %g5, [%g3] ASI_PHYS_USE_EC
++ stx %g3, [%g6]
++ wr %g0, 1 << PIL_DEVICE_IRQ, %set_softint
++ retry
++do_ivec_xcall:
++ mov 0x50, %g1
++ ldxa [%g1 + %g0] ASI_INTR_R, %g1
++ srl %g3, 0, %g3
++
++ mov 0x60, %g7
++ ldxa [%g7 + %g0] ASI_INTR_R, %g7
++ stxa %g0, [%g0] ASI_INTR_RECEIVE
++ membar #Sync
++ ba,pt %xcc, 1f
++ nop
++
++ .align 32
++1: jmpl %g3, %g0
++ nop
++ .size do_ivec,.-do_ivec
+diff --git a/arch/sparc64/kernel/kgdb.c b/arch/sparc64/kernel/kgdb.c
+new file mode 100644
+index 0000000..fefbe6d
+--- /dev/null
++++ b/arch/sparc64/kernel/kgdb.c
+@@ -0,0 +1,186 @@
++/* kgdb.c: KGDB support for 64-bit sparc.
++ *
++ * Copyright (C) 2008 David S. Miller <davem at davemloft.net>
++ */
++
++#include <linux/kgdb.h>
++#include <linux/kdebug.h>
++
++#include <asm/kdebug.h>
++#include <asm/ptrace.h>
++#include <asm/irq.h>
++
++void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++ struct reg_window *win;
++ int i;
++
++ gdb_regs[GDB_G0] = 0;
++ for (i = 0; i < 15; i++)
++ gdb_regs[GDB_G1 + i] = regs->u_regs[UREG_G1 + i];
++
++ win = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS);
++ for (i = 0; i < 8; i++)
++ gdb_regs[GDB_L0 + i] = win->locals[i];
++ for (i = 0; i < 8; i++)
++ gdb_regs[GDB_I0 + i] = win->ins[i];
++
++ for (i = GDB_F0; i <= GDB_F62; i++)
++ gdb_regs[i] = 0;
++
++ gdb_regs[GDB_PC] = regs->tpc;
++ gdb_regs[GDB_NPC] = regs->tnpc;
++ gdb_regs[GDB_STATE] = regs->tstate;
++ gdb_regs[GDB_FSR] = 0;
++ gdb_regs[GDB_FPRS] = 0;
++ gdb_regs[GDB_Y] = regs->y;
++}
++
++void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
++{
++ struct thread_info *t = task_thread_info(p);
++ extern unsigned int switch_to_pc;
++ extern unsigned int ret_from_syscall;
++ struct reg_window *win;
++ unsigned long pc, cwp;
++ int i;
++
++ for (i = GDB_G0; i < GDB_G6; i++)
++ gdb_regs[i] = 0;
++ gdb_regs[GDB_G6] = (unsigned long) t;
++ gdb_regs[GDB_G7] = (unsigned long) p;
++ for (i = GDB_O0; i < GDB_SP; i++)
++ gdb_regs[i] = 0;
++ gdb_regs[GDB_SP] = t->ksp;
++ gdb_regs[GDB_O7] = 0;
++
++ win = (struct reg_window *) (t->ksp + STACK_BIAS);
++ for (i = 0; i < 8; i++)
++ gdb_regs[GDB_L0 + i] = win->locals[i];
++ for (i = 0; i < 8; i++)
++ gdb_regs[GDB_I0 + i] = win->ins[i];
++
++ for (i = GDB_F0; i <= GDB_F62; i++)
++ gdb_regs[i] = 0;
++
++ if (t->new_child)
++ pc = (unsigned long) &ret_from_syscall;
++ else
++ pc = (unsigned long) &switch_to_pc;
++
++ gdb_regs[GDB_PC] = pc;
++ gdb_regs[GDB_NPC] = pc + 4;
++
++ cwp = __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP];
++
++ gdb_regs[GDB_STATE] = (TSTATE_PRIV | TSTATE_IE | cwp);
++ gdb_regs[GDB_FSR] = 0;
++ gdb_regs[GDB_FPRS] = 0;
++ gdb_regs[GDB_Y] = 0;
++}
++
++void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++ struct reg_window *win;
++ int i;
++
++ for (i = 0; i < 15; i++)
++ regs->u_regs[UREG_G1 + i] = gdb_regs[GDB_G1 + i];
++
++ /* If the TSTATE register is changing, we have to preserve
++ * the CWP field, otherwise window save/restore explodes.
++ */
++ if (regs->tstate != gdb_regs[GDB_STATE]) {
++ unsigned long cwp = regs->tstate & TSTATE_CWP;
++
++ regs->tstate = (gdb_regs[GDB_STATE] & ~TSTATE_CWP) | cwp;
++ }
++
++ regs->tpc = gdb_regs[GDB_PC];
++ regs->tnpc = gdb_regs[GDB_NPC];
++ regs->y = gdb_regs[GDB_Y];
++
++ win = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS);
++ for (i = 0; i < 8; i++)
++ win->locals[i] = gdb_regs[GDB_L0 + i];
++ for (i = 0; i < 8; i++)
++ win->ins[i] = gdb_regs[GDB_I0 + i];
++}
++
++#ifdef CONFIG_SMP
++void smp_kgdb_capture_client(struct pt_regs *regs)
++{
++ unsigned long flags;
++
++ __asm__ __volatile__("rdpr %%pstate, %0\n\t"
++ "wrpr %0, %1, %%pstate"
++ : "=r" (flags)
++ : "i" (PSTATE_IE));
++
++ flushw_all();
++
++ if (atomic_read(&kgdb_active) != -1)
++ kgdb_nmicallback(raw_smp_processor_id(), regs);
++
++ __asm__ __volatile__("wrpr %0, 0, %%pstate"
++ : : "r" (flags));
++}
++#endif
++
++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;
++ char *ptr;
++
++ switch (remcomInBuffer[0]) {
++ case 'c':
++ /* try to read optional parameter, pc unchanged if no parm */
++ ptr = &remcomInBuffer[1];
++ if (kgdb_hex2long(&ptr, &addr)) {
++ linux_regs->tpc = addr;
++ linux_regs->tnpc = addr + 4;
++ }
++ /* fallthru */
++
++ case 'D':
++ case 'k':
++ if (linux_regs->tpc == (unsigned long) arch_kgdb_breakpoint) {
++ linux_regs->tpc = linux_regs->tnpc;
++ linux_regs->tnpc += 4;
++ }
++ return 0;
++ }
++ return -1;
++}
++
++asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs)
++{
++ unsigned long flags;
++
++ if (user_mode(regs)) {
++ bad_trap(regs, trap_level);
++ return;
++ }
++
++ flushw_all();
++
++ local_irq_save(flags);
++ kgdb_handle_exception(0x172, SIGTRAP, 0, regs);
++ local_irq_restore(flags);
++}
++
++int kgdb_arch_init(void)
++{
++ return 0;
++}
++
++void kgdb_arch_exit(void)
++{
++}
++
++struct kgdb_arch arch_kgdb_ops = {
++ /* Breakpoint instruction: ta 0x72 */
++ .gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x72 },
++};
diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c
index 9100835..dde52bc 100644
--- a/arch/sparc64/kernel/mdesc.c
@@ -222221,8 +278300,111 @@
if (hp == NULL) {
prom_printf("MDESC: alloc of %lu bytes failed.\n", len);
prom_halt();
+diff --git a/arch/sparc64/kernel/misctrap.S b/arch/sparc64/kernel/misctrap.S
+new file mode 100644
+index 0000000..753b4f0
+--- /dev/null
++++ b/arch/sparc64/kernel/misctrap.S
+@@ -0,0 +1,97 @@
++#ifdef CONFIG_KGDB
++ .globl arch_kgdb_breakpoint
++ .type arch_kgdb_breakpoint,#function
++arch_kgdb_breakpoint:
++ ta 0x72
++ retl
++ nop
++ .size arch_kgdb_breakpoint,.-arch_kgdb_breakpoint
++#endif
++
++ .type __do_privact,#function
++__do_privact:
++ mov TLB_SFSR, %g3
++ stxa %g0, [%g3] ASI_DMMU ! Clear FaultValid bit
++ membar #Sync
++ sethi %hi(109f), %g7
++ ba,pt %xcc, etrap
++109: or %g7, %lo(109b), %g7
++ call do_privact
++ add %sp, PTREGS_OFF, %o0
++ ba,pt %xcc, rtrap
++ nop
++ .size __do_privact,.-__do_privact
++
++ .type do_mna,#function
++do_mna:
++ rdpr %tl, %g3
++ cmp %g3, 1
++
++ /* Setup %g4/%g5 now as they are used in the
++ * winfixup code.
++ */
++ mov TLB_SFSR, %g3
++ mov DMMU_SFAR, %g4
++ ldxa [%g4] ASI_DMMU, %g4
++ ldxa [%g3] ASI_DMMU, %g5
++ stxa %g0, [%g3] ASI_DMMU ! Clear FaultValid bit
++ membar #Sync
++ bgu,pn %icc, winfix_mna
++ rdpr %tpc, %g3
++
++1: sethi %hi(109f), %g7
++ ba,pt %xcc, etrap
++109: or %g7, %lo(109b), %g7
++ mov %l4, %o1
++ mov %l5, %o2
++ call mem_address_unaligned
++ add %sp, PTREGS_OFF, %o0
++ ba,pt %xcc, rtrap
++ nop
++ .size do_mna,.-do_mna
++
++ .type do_lddfmna,#function
++do_lddfmna:
++ sethi %hi(109f), %g7
++ mov TLB_SFSR, %g4
++ ldxa [%g4] ASI_DMMU, %g5
++ stxa %g0, [%g4] ASI_DMMU ! Clear FaultValid bit
++ membar #Sync
++ mov DMMU_SFAR, %g4
++ ldxa [%g4] ASI_DMMU, %g4
++ ba,pt %xcc, etrap
++109: or %g7, %lo(109b), %g7
++ mov %l4, %o1
++ mov %l5, %o2
++ call handle_lddfmna
++ add %sp, PTREGS_OFF, %o0
++ ba,pt %xcc, rtrap
++ nop
++ .size do_lddfmna,.-do_lddfmna
++
++ .type do_stdfmna,#function
++do_stdfmna:
++ sethi %hi(109f), %g7
++ mov TLB_SFSR, %g4
++ ldxa [%g4] ASI_DMMU, %g5
++ stxa %g0, [%g4] ASI_DMMU ! Clear FaultValid bit
++ membar #Sync
++ mov DMMU_SFAR, %g4
++ ldxa [%g4] ASI_DMMU, %g4
++ ba,pt %xcc, etrap
++109: or %g7, %lo(109b), %g7
++ mov %l4, %o1
++ mov %l5, %o2
++ call handle_stdfmna
++ add %sp, PTREGS_OFF, %o0
++ ba,pt %xcc, rtrap
++ nop
++ .size do_stdfmna,.-do_stdfmna
++
++ .type breakpoint_trap,#function
++breakpoint_trap:
++ call sparc_breakpoint
++ add %sp, PTREGS_OFF, %o0
++ ba,pt %xcc, rtrap
++ nop
++ .size breakpoint_trap,.-breakpoint_trap
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
-index 0fd9db9..9e58e8c 100644
+index 0fd9db9..d569f60 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -6,6 +6,7 @@
@@ -222233,7 +278415,20 @@
#include <linux/of_device.h>
#include <linux/of_platform.h>
-@@ -660,6 +661,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
+@@ -411,12 +412,6 @@ static int __init build_one_resource(struct device_node *parent,
+
+ static int __init use_1to1_mapping(struct device_node *pp)
+ {
+- /* If this is on the PMU bus, don't try to translate it even
+- * if a ranges property exists.
+- */
+- if (!strcmp(pp->name, "pmu"))
+- return 1;
+-
+ /* If we have a ranges property in the parent, use it. */
+ if (of_find_property(pp, "ranges", NULL) != NULL)
+ return 0;
+@@ -660,6 +655,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;
@@ -222241,7 +278436,7 @@
if (irq == 0xffffffff)
return irq;
-@@ -672,7 +674,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
+@@ -672,7 +668,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);
@@ -222250,7 +278445,7 @@
}
/* 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,
+@@ -744,6 +740,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);
@@ -222266,10 +278461,18 @@
}
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
-index 545356b..49f9127 100644
+index 545356b..dbf2fc2 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,
+@@ -23,7 +23,6 @@
+ #include <asm/pgtable.h>
+ #include <asm/irq.h>
+ #include <asm/ebus.h>
+-#include <asm/isa.h>
+ #include <asm/prom.h>
+ #include <asm/apb.h>
+
+@@ -369,10 +368,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);
@@ -222282,7 +278485,15 @@
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,
+@@ -883,7 +884,6 @@ static int __init pcibios_init(void)
+
+ pci_scan_each_controller_bus();
+
+- isa_init();
+ ebus_init();
+ power_init();
+
+@@ -1159,6 +1159,16 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
return 0;
}
@@ -222485,6 +278696,40 @@
pci_determine_mem_io_space(pbm);
+diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
+index acf8c52..0560137 100644
+--- a/arch/sparc64/kernel/process.c
++++ b/arch/sparc64/kernel/process.c
+@@ -1,5 +1,4 @@
+-/* $Id: process.c,v 1.131 2002/02/09 19:49:30 davem Exp $
+- * arch/sparc64/kernel/process.c
++/* arch/sparc64/kernel/process.c
+ *
+ * Copyright (C) 1995, 1996 David S. Miller (davem at caip.rutgers.edu)
+ * Copyright (C) 1996 Eddie C. Dost (ecd at skynet.be)
+@@ -368,9 +367,6 @@ void flush_thread(void)
+
+ if (get_thread_current_ds() != ASI_AIUS)
+ set_fs(USER_DS);
+-
+- /* Init new signal delivery disposition. */
+- clear_thread_flag(TIF_NEWSIGNALS);
+ }
+
+ /* It's a bit more tricky when 64-bit tasks are involved... */
+@@ -595,6 +591,12 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
+ if (clone_flags & CLONE_SETTLS)
+ t->kregs->u_regs[UREG_G7] = regs->u_regs[UREG_I3];
+
++ /* We do not want to accidently trigger system call restart
++ * handling in the new thread. Therefore, clear out the trap
++ * type, which will make pt_regs_regs_is_syscall() return false.
++ */
++ pt_regs_clear_trap_type(t->kregs);
++
+ return 0;
+ }
+
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
index 68964dd..ed03a18 100644
--- a/arch/sparc64/kernel/prom.c
@@ -222902,9 +279147,18 @@
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
+index 9d51956..f2d88d8 100644
--- a/arch/sparc64/kernel/signal.c
+++ b/arch/sparc64/kernel/signal.c
+@@ -8,7 +8,7 @@
+ * Copyright (C) 1997,1998 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+ */
+
+-#ifdef CONFIG_SPARC32_COMPAT
++#ifdef CONFIG_COMPAT
+ #include <linux/compat.h> /* for compat_old_sigset_t */
+ #endif
+ #include <linux/sched.h>
@@ -25,7 +25,6 @@
#include <asm/uaccess.h>
@@ -222913,7 +279167,26 @@
#include <asm/pgtable.h>
#include <asm/fpumacro.h>
#include <asm/uctx.h>
-@@ -511,15 +510,20 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
+@@ -237,9 +236,6 @@ struct rt_signal_frame {
+ __siginfo_fpu_t fpu_state;
+ };
+
+-/* Align macros */
+-#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7)))
+-
+ static long _sigpause_common(old_sigset_t set)
+ {
+ set &= _BLOCKABLE;
+@@ -401,7 +397,7 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
+ synchronize_user_stack();
+ save_and_clear_fpu();
+
+- sigframe_size = RT_ALIGNEDSZ;
++ sigframe_size = sizeof(struct rt_signal_frame);
+ if (!(current_thread_info()->fpsaved[0] & FPRS_FEF))
+ sigframe_size -= sizeof(__siginfo_fpu_t);
+
+@@ -511,15 +507,19 @@ 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.
*/
@@ -222926,20 +279199,23 @@
- int signr;
sigset_t *oldset;
+ siginfo_t info;
-+ int signr, tt;
++ int signr;
- cookie.restart_syscall = restart_syscall;
-+ tt = regs->magic & 0x1ff;
-+ if (tt == 0x110 || tt == 0x111 || tt == 0x16d) {
-+ regs->magic &= ~0x1ff;
++ if (pt_regs_is_syscall(regs)) {
++ pt_regs_clear_trap_type(regs);
+ 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
+@@ -527,12 +527,11 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_s
+ else
+ oldset = ¤t->blocked;
+
+-#ifdef CONFIG_SPARC32_COMPAT
++#ifdef CONFIG_COMPAT
if (test_thread_flag(TIF_32BIT)) {
extern void do_signal32(sigset_t *, struct pt_regs *,
- unsigned long, int);
@@ -222950,7 +279226,7 @@
return;
}
#endif
-@@ -540,7 +543,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_s
+@@ -540,7 +539,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)
@@ -222959,7 +279235,7 @@
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
+@@ -577,11 +576,10 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_s
}
}
@@ -222974,10 +279250,17 @@
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
+index 8c1c121..91f8d08 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
-@@ -23,7 +23,6 @@
+@@ -1,5 +1,4 @@
+-/* $Id: signal32.c,v 1.74 2002/02/09 19:49:30 davem Exp $
+- * arch/sparc64/kernel/signal32.c
++/* arch/sparc64/kernel/signal32.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
+@@ -23,7 +22,6 @@
#include <asm/uaccess.h>
#include <asm/ptrace.h>
@@ -222985,7 +279268,339 @@
#include <asm/pgtable.h>
#include <asm/psrcompat.h>
#include <asm/fpumacro.h>
-@@ -798,281 +797,6 @@ sigsegv:
+@@ -32,30 +30,6 @@
+
+ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+-/* Signal frames: the original one (compatible with SunOS):
+- *
+- * Set up a signal frame... Make the stack look the way SunOS
+- * expects it to look which is basically:
+- *
+- * ---------------------------------- <-- %sp at signal time
+- * Struct sigcontext
+- * Signal address
+- * Ptr to sigcontext area above
+- * Signal code
+- * The signal number itself
+- * One register window
+- * ---------------------------------- <-- New %sp
+- */
+-struct signal_sframe32 {
+- struct reg_window32 sig_window;
+- int sig_num;
+- int sig_code;
+- /* struct sigcontext32 * */ u32 sig_scptr;
+- int sig_address;
+- struct sigcontext32 sig_context;
+- unsigned int extramask[_COMPAT_NSIG_WORDS - 1];
+-};
+-
+ /* This magic should be in g_upper[0] for all upper parts
+ * to be valid.
+ */
+@@ -66,12 +40,7 @@ typedef struct {
+ unsigned int asi;
+ } siginfo_extra_v8plus_t;
+
+-/*
+- * And the new one, intended to be used for Linux applications only
+- * (we have enough in there to work with clone).
+- * All the interesting bits are in the info field.
+- */
+-struct new_signal_frame32 {
++struct signal_frame32 {
+ struct sparc_stackf32 ss;
+ __siginfo32_t info;
+ /* __siginfo_fpu32_t * */ u32 fpu_save;
+@@ -150,8 +119,7 @@ struct rt_signal_frame32 {
+ };
+
+ /* Align macros */
+-#define SF_ALIGNEDSZ (((sizeof(struct signal_sframe32) + 7) & (~7)))
+-#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame32) + 7) & (~7)))
++#define SF_ALIGNEDSZ (((sizeof(struct signal_frame32) + 7) & (~7)))
+ #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 7) & (~7)))
+
+ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
+@@ -242,17 +210,22 @@ static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu
+ return err;
+ }
+
+-void do_new_sigreturn32(struct pt_regs *regs)
++void do_sigreturn32(struct pt_regs *regs)
+ {
+- struct new_signal_frame32 __user *sf;
++ struct signal_frame32 __user *sf;
+ unsigned int psr;
+ unsigned pc, npc, fpu_save;
+ sigset_t set;
+ unsigned seta[_COMPAT_NSIG_WORDS];
+ int err, i;
+
++ /* Always make any pending restarted system calls return -EINTR */
++ current_thread_info()->restart_block.fn = do_no_restart_syscall;
++
++ synchronize_user_stack();
++
+ regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
+- sf = (struct new_signal_frame32 __user *) regs->u_regs[UREG_FP];
++ sf = (struct signal_frame32 __user *) regs->u_regs[UREG_FP];
+
+ /* 1. Make sure we are not getting garbage from the user */
+ if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
+@@ -320,76 +293,6 @@ segv:
+ force_sig(SIGSEGV, current);
+ }
+
+-asmlinkage void do_sigreturn32(struct pt_regs *regs)
+-{
+- struct sigcontext32 __user *scptr;
+- unsigned int pc, npc, psr;
+- sigset_t set;
+- unsigned int seta[_COMPAT_NSIG_WORDS];
+- int err;
+-
+- /* Always make any pending restarted system calls return -EINTR */
+- current_thread_info()->restart_block.fn = do_no_restart_syscall;
+-
+- synchronize_user_stack();
+- if (test_thread_flag(TIF_NEWSIGNALS)) {
+- do_new_sigreturn32(regs);
+- return;
+- }
+-
+- scptr = (struct sigcontext32 __user *)
+- (regs->u_regs[UREG_I0] & 0x00000000ffffffffUL);
+- /* Check sanity of the user arg. */
+- if (!access_ok(VERIFY_READ, scptr, sizeof(struct sigcontext32)) ||
+- (((unsigned long) scptr) & 3))
+- goto segv;
+-
+- err = __get_user(pc, &scptr->sigc_pc);
+- err |= __get_user(npc, &scptr->sigc_npc);
+-
+- if ((pc | npc) & 3)
+- goto segv; /* Nice try. */
+-
+- err |= __get_user(seta[0], &scptr->sigc_mask);
+- /* Note that scptr + 1 points to extramask */
+- err |= copy_from_user(seta+1, scptr + 1,
+- (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int));
+- if (err)
+- goto segv;
+- switch (_NSIG_WORDS) {
+- case 4: set.sig[3] = seta[6] + (((long)seta[7]) << 32);
+- case 3: set.sig[2] = seta[4] + (((long)seta[5]) << 32);
+- case 2: set.sig[1] = seta[2] + (((long)seta[3]) << 32);
+- case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32);
+- }
+- sigdelsetmask(&set, ~_BLOCKABLE);
+- spin_lock_irq(¤t->sighand->siglock);
+- current->blocked = set;
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+-
+- if (test_thread_flag(TIF_32BIT)) {
+- pc &= 0xffffffff;
+- npc &= 0xffffffff;
+- }
+- regs->tpc = pc;
+- regs->tnpc = npc;
+- err = __get_user(regs->u_regs[UREG_FP], &scptr->sigc_sp);
+- err |= __get_user(regs->u_regs[UREG_I0], &scptr->sigc_o0);
+- err |= __get_user(regs->u_regs[UREG_G1], &scptr->sigc_g1);
+-
+- /* User can only change condition codes in %tstate. */
+- err |= __get_user(psr, &scptr->sigc_psr);
+- if (err)
+- goto segv;
+- regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);
+- regs->tstate |= psr_to_tstate_icc(psr);
+- return;
+-
+-segv:
+- force_sig(SIGSEGV, current);
+-}
+-
+ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
+ {
+ struct rt_signal_frame32 __user *sf;
+@@ -505,145 +408,6 @@ static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns
+ return (void __user *)(sp - framesize);
+ }
+
+-static void
+-setup_frame32(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *oldset, siginfo_t *info)
+-{
+- struct signal_sframe32 __user *sframep;
+- struct sigcontext32 __user *sc;
+- unsigned int seta[_COMPAT_NSIG_WORDS];
+- int err = 0;
+- void __user *sig_address;
+- int sig_code;
+- unsigned long pc = regs->tpc;
+- unsigned long npc = regs->tnpc;
+- unsigned int psr;
+-
+- if (test_thread_flag(TIF_32BIT)) {
+- pc &= 0xffffffff;
+- npc &= 0xffffffff;
+- }
+-
+- synchronize_user_stack();
+- save_and_clear_fpu();
+-
+- sframep = (struct signal_sframe32 __user *)
+- get_sigframe(sa, regs, SF_ALIGNEDSZ);
+- if (invalid_frame_pointer(sframep, sizeof(*sframep))){
+- /* Don't change signal code and address, so that
+- * post mortem debuggers can have a look.
+- */
+- do_exit(SIGILL);
+- }
+-
+- sc = &sframep->sig_context;
+-
+- /* We've already made sure frame pointer isn't in kernel space... */
+- err = __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK),
+- &sc->sigc_onstack);
+-
+- switch (_NSIG_WORDS) {
+- case 4: seta[7] = (oldset->sig[3] >> 32);
+- seta[6] = oldset->sig[3];
+- case 3: seta[5] = (oldset->sig[2] >> 32);
+- seta[4] = oldset->sig[2];
+- case 2: seta[3] = (oldset->sig[1] >> 32);
+- seta[2] = oldset->sig[1];
+- case 1: seta[1] = (oldset->sig[0] >> 32);
+- seta[0] = oldset->sig[0];
+- }
+- err |= __put_user(seta[0], &sc->sigc_mask);
+- err |= __copy_to_user(sframep->extramask, seta + 1,
+- (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int));
+- err |= __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp);
+- err |= __put_user(pc, &sc->sigc_pc);
+- err |= __put_user(npc, &sc->sigc_npc);
+- psr = tstate_to_psr(regs->tstate);
+- if (current_thread_info()->fpsaved[0] & FPRS_FEF)
+- psr |= PSR_EF;
+- err |= __put_user(psr, &sc->sigc_psr);
+- err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1);
+- err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0);
+- err |= __put_user(get_thread_wsaved(), &sc->sigc_oswins);
+-
+- err |= copy_in_user((u32 __user *)sframep,
+- (u32 __user *)(regs->u_regs[UREG_FP]),
+- sizeof(struct reg_window32));
+-
+- set_thread_wsaved(0); /* So process is allowed to execute. */
+- err |= __put_user(signr, &sframep->sig_num);
+- sig_address = NULL;
+- sig_code = 0;
+- if (SI_FROMKERNEL (info) && (info->si_code & __SI_MASK) == __SI_FAULT) {
+- sig_address = info->si_addr;
+- switch (signr) {
+- case SIGSEGV:
+- switch (info->si_code) {
+- case SEGV_MAPERR: sig_code = SUBSIG_NOMAPPING; break;
+- default: sig_code = SUBSIG_PROTECTION; break;
+- }
+- break;
+- case SIGILL:
+- switch (info->si_code) {
+- case ILL_ILLOPC: sig_code = SUBSIG_ILLINST; break;
+- case ILL_PRVOPC: sig_code = SUBSIG_PRIVINST; break;
+- case ILL_ILLTRP: sig_code = SUBSIG_BADTRAP(info->si_trapno); break;
+- default: sig_code = SUBSIG_STACK; break;
+- }
+- break;
+- case SIGFPE:
+- switch (info->si_code) {
+- case FPE_INTDIV: sig_code = SUBSIG_IDIVZERO; break;
+- case FPE_INTOVF: sig_code = SUBSIG_FPINTOVFL; break;
+- case FPE_FLTDIV: sig_code = SUBSIG_FPDIVZERO; break;
+- case FPE_FLTOVF: sig_code = SUBSIG_FPOVFLOW; break;
+- case FPE_FLTUND: sig_code = SUBSIG_FPUNFLOW; break;
+- case FPE_FLTRES: sig_code = SUBSIG_FPINEXACT; break;
+- case FPE_FLTINV: sig_code = SUBSIG_FPOPERROR; break;
+- default: sig_code = SUBSIG_FPERROR; break;
+- }
+- break;
+- case SIGBUS:
+- switch (info->si_code) {
+- case BUS_ADRALN: sig_code = SUBSIG_ALIGNMENT; break;
+- case BUS_ADRERR: sig_code = SUBSIG_MISCERROR; break;
+- default: sig_code = SUBSIG_BUSTIMEOUT; break;
+- }
+- break;
+- case SIGEMT:
+- switch (info->si_code) {
+- case EMT_TAGOVF: sig_code = SUBSIG_TAG; break;
+- }
+- break;
+- case SIGSYS:
+- if (info->si_code == (__SI_FAULT|0x100)) {
+- /* See sys_sunos32.c */
+- sig_code = info->si_trapno;
+- break;
+- }
+- default:
+- sig_address = NULL;
+- }
+- }
+- err |= __put_user(ptr_to_compat(sig_address), &sframep->sig_address);
+- err |= __put_user(sig_code, &sframep->sig_code);
+- err |= __put_user(ptr_to_compat(sc), &sframep->sig_scptr);
+- if (err)
+- goto sigsegv;
+-
+- regs->u_regs[UREG_FP] = (unsigned long) sframep;
+- regs->tpc = (unsigned long) sa->sa_handler;
+- regs->tnpc = (regs->tpc + 4);
+- if (test_thread_flag(TIF_32BIT)) {
+- regs->tpc &= 0xffffffff;
+- regs->tnpc &= 0xffffffff;
+- }
+- return;
+-
+-sigsegv:
+- force_sigsegv(signr, current);
+-}
+-
+-
+ static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
+ {
+ unsigned long *fpregs = current_thread_info()->fpregs;
+@@ -664,10 +428,10 @@ static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
+ return err;
+ }
+
+-static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
+- int signo, sigset_t *oldset)
++static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
++ int signo, sigset_t *oldset)
+ {
+- struct new_signal_frame32 __user *sf;
++ struct signal_frame32 __user *sf;
+ int sigframe_size;
+ u32 psr;
+ int i, err;
+@@ -677,11 +441,11 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
+ synchronize_user_stack();
+ save_and_clear_fpu();
+
+- sigframe_size = NF_ALIGNEDSZ;
++ sigframe_size = SF_ALIGNEDSZ;
+ if (!(current_thread_info()->fpsaved[0] & FPRS_FEF))
+ sigframe_size -= sizeof(__siginfo_fpu_t);
+
+- sf = (struct new_signal_frame32 __user *)
++ sf = (struct signal_frame32 __user *)
+ get_sigframe(&ka->sa, regs, sigframe_size);
+
+ if (invalid_frame_pointer(sf, sigframe_size))
+@@ -798,281 +562,6 @@ sigsegv:
force_sigsegv(signo, current);
}
@@ -223267,7 +279882,7 @@
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:
+@@ -1216,20 +705,13 @@ sigsegv:
static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
siginfo_t *info,
@@ -223288,14 +279903,13 @@
- }
+ 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);
++ setup_frame32(ka, regs, signr, oldset);
++
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
+@@ -1264,23 +746,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,
@@ -223325,7 +279939,7 @@
/* 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,
+@@ -1291,16 +767,16 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs,
clear_thread_flag(TIF_RESTORE_SIGMASK);
return;
}
@@ -223346,7 +279960,7 @@
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
+index 59f020d..3aba476 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -20,7 +20,7 @@
@@ -223358,7 +279972,15 @@
#include <asm/head.h>
#include <asm/ptrace.h>
-@@ -866,14 +866,21 @@ void smp_call_function_client(int irq, struct pt_regs *regs)
+@@ -38,7 +38,6 @@
+ #include <asm/pgtable.h>
+ #include <asm/oplib.h>
+ #include <asm/uaccess.h>
+-#include <asm/timer.h>
+ #include <asm/starfire.h>
+ #include <asm/tlb.h>
+ #include <asm/sections.h>
+@@ -866,14 +865,21 @@ void smp_call_function_client(int irq, struct pt_regs *regs)
void *info = call_data->info;
clear_softint(1 << irq);
@@ -223377,15 +279999,25 @@
if (call_data->wait) {
/* let initiator proceed only after completion */
- func(info);
- atomic_inc(&call_data->finished);
+- atomic_inc(&call_data->finished);
- } else {
- /* let initiator proceed after getting data */
-- atomic_inc(&call_data->finished);
+ atomic_inc(&call_data->finished);
- func(info);
}
}
-@@ -1032,7 +1039,9 @@ void smp_receive_signal(int cpu)
+@@ -903,6 +909,9 @@ extern unsigned long xcall_flush_tlb_kernel_range;
+ extern unsigned long xcall_report_regs;
+ extern unsigned long xcall_receive_signal;
+ extern unsigned long xcall_new_mmu_context_version;
++#ifdef CONFIG_KGDB
++extern unsigned long xcall_kgdb_capture;
++#endif
+
+ #ifdef DCACHE_ALIASING_POSSIBLE
+ extern unsigned long xcall_flush_dcache_page_cheetah;
+@@ -1032,7 +1041,9 @@ void smp_receive_signal(int cpu)
void smp_receive_signal_client(int irq, struct pt_regs *regs)
{
@@ -223395,7 +280027,7 @@
}
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)
+@@ -1040,6 +1051,8 @@ void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
struct mm_struct *mm;
unsigned long flags;
@@ -223404,7 +280036,7 @@
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)
+@@ -1059,6 +1072,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);
@@ -223413,7 +280045,21 @@
}
void smp_new_mmu_context_version(void)
-@@ -1217,6 +1230,8 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
+@@ -1066,6 +1081,13 @@ void smp_new_mmu_context_version(void)
+ smp_cross_call(&xcall_new_mmu_context_version, 0, 0, 0);
+ }
+
++#ifdef CONFIG_KGDB
++void kgdb_roundup_cpus(unsigned long flags)
++{
++ smp_cross_call(&xcall_kgdb_capture, 0, 0, 0);
++}
++#endif
++
+ void smp_report_regs(void)
+ {
+ smp_cross_call(&xcall_report_regs, 0, 0, 0);
+@@ -1217,6 +1239,8 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
{
clear_softint(1 << irq);
@@ -223422,7 +280068,7 @@
preempt_disable();
__asm__ __volatile__("flushw");
-@@ -1229,6 +1244,8 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
+@@ -1229,6 +1253,8 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
prom_world(0);
preempt_enable();
@@ -223431,7 +280077,7 @@
}
/* /proc/profile writes can call this, don't __init it please. */
-@@ -1431,7 +1448,7 @@ EXPORT_SYMBOL(__per_cpu_shift);
+@@ -1431,7 +1457,7 @@ EXPORT_SYMBOL(__per_cpu_shift);
void __init real_setup_per_cpu_areas(void)
{
@@ -223440,7 +280086,7 @@
char *ptr;
/* Copy section for each CPU (we discard the original) */
-@@ -1441,8 +1458,13 @@ void __init real_setup_per_cpu_areas(void)
+@@ -1441,8 +1467,13 @@ void __init real_setup_per_cpu_areas(void)
for (size = PAGE_SIZE; size < goal; size <<= 1UL)
__per_cpu_shift++;
@@ -223456,7 +280102,7 @@
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
+index 51fa773..8ac0b99 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -33,13 +33,11 @@
@@ -223473,7 +280119,15 @@
#include <asm/uaccess.h>
#include <asm/checksum.h>
#include <asm/fpumacro.h>
-@@ -70,16 +68,9 @@ extern void *__memscan_zero(void *, size_t);
+@@ -51,7 +49,6 @@
+ #endif
+ #ifdef CONFIG_PCI
+ #include <asm/ebus.h>
+-#include <asm/isa.h>
+ #endif
+ #include <asm/ns87303.h>
+ #include <asm/timer.h>
+@@ -70,16 +67,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 *);
@@ -223490,7 +280144,7 @@
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);
+@@ -90,8 +80,6 @@ extern int __ashrdi3(int, int);
extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs);
@@ -223499,7 +280153,7 @@
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);
+@@ -130,12 +118,6 @@ EXPORT_SYMBOL(_mcount);
EXPORT_SYMBOL(sparc64_get_clock_tick);
@@ -223512,7 +280166,15 @@
/* RW semaphores */
EXPORT_SYMBOL(__down_read);
EXPORT_SYMBOL(__down_read_trylock);
-@@ -219,11 +202,6 @@ EXPORT_SYMBOL(pci_dma_supported);
+@@ -204,7 +186,6 @@ EXPORT_SYMBOL(insw);
+ EXPORT_SYMBOL(insl);
+ #ifdef CONFIG_PCI
+ EXPORT_SYMBOL(ebus_chain);
+-EXPORT_SYMBOL(isa_chain);
+ EXPORT_SYMBOL(pci_alloc_consistent);
+ EXPORT_SYMBOL(pci_free_consistent);
+ EXPORT_SYMBOL(pci_map_single);
+@@ -219,11 +200,6 @@ EXPORT_SYMBOL(pci_dma_supported);
/* I/O device mmaping on Sparc64. */
EXPORT_SYMBOL(io_remap_pfn_range);
@@ -223524,7 +280186,7 @@
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(put_fs_struct);
-@@ -260,30 +238,6 @@ EXPORT_SYMBOL(strlen);
+@@ -260,30 +236,6 @@ EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(__strlen_user);
EXPORT_SYMBOL(__strnlen_user);
@@ -223555,7 +280217,7 @@
/* Special internal versions of library functions. */
EXPORT_SYMBOL(_clear_page);
EXPORT_SYMBOL(clear_user_page);
-@@ -340,9 +294,6 @@ EXPORT_SYMBOL(do_BUG);
+@@ -340,9 +292,6 @@ EXPORT_SYMBOL(do_BUG);
/* for ns8703 */
EXPORT_SYMBOL(ns87303_lock);
@@ -223565,6 +280227,257 @@
EXPORT_SYMBOL(tick_ops);
EXPORT_SYMBOL(xor_vis_2);
+diff --git a/arch/sparc64/kernel/spiterrs.S b/arch/sparc64/kernel/spiterrs.S
+new file mode 100644
+index 0000000..ef902c6
+--- /dev/null
++++ b/arch/sparc64/kernel/spiterrs.S
+@@ -0,0 +1,245 @@
++ /* We need to carefully read the error status, ACK the errors,
++ * prevent recursive traps, and pass the information on to C
++ * code for logging.
++ *
++ * We pass the AFAR in as-is, and we encode the status
++ * information as described in asm-sparc64/sfafsr.h
++ */
++ .type __spitfire_access_error,#function
++__spitfire_access_error:
++ /* Disable ESTATE error reporting so that we do not take
++ * recursive traps and RED state the processor.
++ */
++ stxa %g0, [%g0] ASI_ESTATE_ERROR_EN
++ membar #Sync
++
++ mov UDBE_UE, %g1
++ ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
++
++ /* __spitfire_cee_trap branches here with AFSR in %g4 and
++ * UDBE_CE in %g1. It only clears ESTATE_ERR_CE in the ESTATE
++ * Error Enable register.
++ */
++__spitfire_cee_trap_continue:
++ ldxa [%g0] ASI_AFAR, %g5 ! Get AFAR
++
++ rdpr %tt, %g3
++ and %g3, 0x1ff, %g3 ! Paranoia
++ sllx %g3, SFSTAT_TRAP_TYPE_SHIFT, %g3
++ or %g4, %g3, %g4
++ rdpr %tl, %g3
++ cmp %g3, 1
++ mov 1, %g3
++ bleu %xcc, 1f
++ sllx %g3, SFSTAT_TL_GT_ONE_SHIFT, %g3
++
++ or %g4, %g3, %g4
++
++ /* Read in the UDB error register state, clearing the sticky
++ * error bits as-needed. We only clear them if the UE bit is
++ * set. Likewise, __spitfire_cee_trap below will only do so
++ * if the CE bit is set.
++ *
++ * NOTE: UltraSparc-I/II have high and low UDB error
++ * registers, corresponding to the two UDB units
++ * present on those chips. UltraSparc-IIi only
++ * has a single UDB, called "SDB" in the manual.
++ * For IIi the upper UDB register always reads
++ * as zero so for our purposes things will just
++ * work with the checks below.
++ */
++1: ldxa [%g0] ASI_UDBH_ERROR_R, %g3
++ and %g3, 0x3ff, %g7 ! Paranoia
++ sllx %g7, SFSTAT_UDBH_SHIFT, %g7
++ or %g4, %g7, %g4
++ andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
++ be,pn %xcc, 1f
++ nop
++ stxa %g3, [%g0] ASI_UDB_ERROR_W
++ membar #Sync
++
++1: mov 0x18, %g3
++ ldxa [%g3] ASI_UDBL_ERROR_R, %g3
++ and %g3, 0x3ff, %g7 ! Paranoia
++ sllx %g7, SFSTAT_UDBL_SHIFT, %g7
++ or %g4, %g7, %g4
++ andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
++ be,pn %xcc, 1f
++ nop
++ mov 0x18, %g7
++ stxa %g3, [%g7] ASI_UDB_ERROR_W
++ membar #Sync
++
++1: /* Ok, now that we've latched the error state, clear the
++ * sticky bits in the AFSR.
++ */
++ stxa %g4, [%g0] ASI_AFSR
++ membar #Sync
++
++ rdpr %tl, %g2
++ cmp %g2, 1
++ rdpr %pil, %g2
++ bleu,pt %xcc, 1f
++ wrpr %g0, 15, %pil
++
++ ba,pt %xcc, etraptl1
++ rd %pc, %g7
++
++ ba,pt %xcc, 2f
++ nop
++
++1: ba,pt %xcc, etrap_irq
++ rd %pc, %g7
++
++2:
++#ifdef CONFIG_TRACE_IRQFLAGS
++ call trace_hardirqs_off
++ nop
++#endif
++ mov %l4, %o1
++ mov %l5, %o2
++ call spitfire_access_error
++ add %sp, PTREGS_OFF, %o0
++ ba,pt %xcc, rtrap
++ nop
++ .size __spitfire_access_error,.-__spitfire_access_error
++
++ /* This is the trap handler entry point for ECC correctable
++ * errors. They are corrected, but we listen for the trap so
++ * that the event can be logged.
++ *
++ * Disrupting errors are either:
++ * 1) single-bit ECC errors during UDB reads to system
++ * memory
++ * 2) data parity errors during write-back events
++ *
++ * As far as I can make out from the manual, the CEE trap is
++ * only for correctable errors during memory read accesses by
++ * the front-end of the processor.
++ *
++ * The code below is only for trap level 1 CEE events, as it
++ * is the only situation where we can safely record and log.
++ * For trap level >1 we just clear the CE bit in the AFSR and
++ * return.
++ *
++ * This is just like __spiftire_access_error above, but it
++ * specifically handles correctable errors. If an
++ * uncorrectable error is indicated in the AFSR we will branch
++ * directly above to __spitfire_access_error to handle it
++ * instead. Uncorrectable therefore takes priority over
++ * correctable, and the error logging C code will notice this
++ * case by inspecting the trap type.
++ */
++ .type __spitfire_cee_trap,#function
++__spitfire_cee_trap:
++ ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
++ mov 1, %g3
++ sllx %g3, SFAFSR_UE_SHIFT, %g3
++ andcc %g4, %g3, %g0 ! Check for UE
++ bne,pn %xcc, __spitfire_access_error
++ nop
++
++ /* Ok, in this case we only have a correctable error.
++ * Indicate we only wish to capture that state in register
++ * %g1, and we only disable CE error reporting unlike UE
++ * handling which disables all errors.
++ */
++ ldxa [%g0] ASI_ESTATE_ERROR_EN, %g3
++ andn %g3, ESTATE_ERR_CE, %g3
++ stxa %g3, [%g0] ASI_ESTATE_ERROR_EN
++ membar #Sync
++
++ /* Preserve AFSR in %g4, indicate UDB state to capture in %g1 */
++ ba,pt %xcc, __spitfire_cee_trap_continue
++ mov UDBE_CE, %g1
++ .size __spitfire_cee_trap,.-__spitfire_cee_trap
++
++ .type __spitfire_data_access_exception_tl1,#function
++__spitfire_data_access_exception_tl1:
++ rdpr %pstate, %g4
++ wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
++ mov TLB_SFSR, %g3
++ mov DMMU_SFAR, %g5
++ ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
++ ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
++ stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit
++ membar #Sync
++ rdpr %tt, %g3
++ cmp %g3, 0x80 ! first win spill/fill trap
++ blu,pn %xcc, 1f
++ cmp %g3, 0xff ! last win spill/fill trap
++ bgu,pn %xcc, 1f
++ nop
++ ba,pt %xcc, winfix_dax
++ rdpr %tpc, %g3
++1: sethi %hi(109f), %g7
++ ba,pt %xcc, etraptl1
++109: or %g7, %lo(109b), %g7
++ mov %l4, %o1
++ mov %l5, %o2
++ call spitfire_data_access_exception_tl1
++ add %sp, PTREGS_OFF, %o0
++ ba,pt %xcc, rtrap
++ nop
++ .size __spitfire_data_access_exception_tl1,.-__spitfire_data_access_exception_tl1
++
++ .type __spitfire_data_access_exception,#function
++__spitfire_data_access_exception:
++ rdpr %pstate, %g4
++ wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
++ mov TLB_SFSR, %g3
++ mov DMMU_SFAR, %g5
++ ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
++ ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
++ stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit
++ membar #Sync
++ sethi %hi(109f), %g7
++ ba,pt %xcc, etrap
++109: or %g7, %lo(109b), %g7
++ mov %l4, %o1
++ mov %l5, %o2
++ call spitfire_data_access_exception
++ add %sp, PTREGS_OFF, %o0
++ ba,pt %xcc, rtrap
++ nop
++ .size __spitfire_data_access_exception,.-__spitfire_data_access_exception
++
++ .type __spitfire_insn_access_exception_tl1,#function
++__spitfire_insn_access_exception_tl1:
++ rdpr %pstate, %g4
++ wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
++ mov TLB_SFSR, %g3
++ ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR
++ rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC
++ stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
++ membar #Sync
++ sethi %hi(109f), %g7
++ ba,pt %xcc, etraptl1
++109: or %g7, %lo(109b), %g7
++ mov %l4, %o1
++ mov %l5, %o2
++ call spitfire_insn_access_exception_tl1
++ add %sp, PTREGS_OFF, %o0
++ ba,pt %xcc, rtrap
++ nop
++ .size __spitfire_insn_access_exception_tl1,.-__spitfire_insn_access_exception_tl1
++
++ .type __spitfire_insn_access_exception,#function
++__spitfire_insn_access_exception:
++ rdpr %pstate, %g4
++ wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
++ mov TLB_SFSR, %g3
++ ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR
++ rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC
++ stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
++ membar #Sync
++ sethi %hi(109f), %g7
++ ba,pt %xcc, etrap
++109: or %g7, %lo(109b), %g7
++ mov %l4, %o1
++ mov %l5, %o2
++ call spitfire_insn_access_exception
++ add %sp, PTREGS_OFF, %o0
++ ba,pt %xcc, rtrap
++ nop
++ .size __spitfire_insn_access_exception,.-__spitfire_insn_access_exception
diff --git a/arch/sparc64/kernel/stacktrace.c b/arch/sparc64/kernel/stacktrace.c
index 84d39e8..01b52f5 100644
--- a/arch/sparc64/kernel/stacktrace.c
@@ -224019,7 +280932,7 @@
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
+index 2455fa4..161ce47 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -55,7 +55,6 @@
@@ -224030,6 +280943,31 @@
#include <asm/mmu_context.h>
#include <asm/compat_signal.h>
+@@ -555,10 +554,8 @@ asmlinkage long compat_sys_sigaction(int sig, struct old_sigaction32 __user *act
+ struct k_sigaction new_ka, old_ka;
+ int ret;
+
+- if (sig < 0) {
+- set_thread_flag(TIF_NEWSIGNALS);
+- sig = -sig;
+- }
++ WARN_ON_ONCE(sig >= 0);
++ sig = -sig;
+
+ if (act) {
+ compat_old_sigset_t mask;
+@@ -602,11 +599,6 @@ asmlinkage long compat_sys_rt_sigaction(int sig,
+ if (sigsetsize != sizeof(compat_sigset_t))
+ return -EINVAL;
+
+- /* All tasks which use RT signals (effectively) use
+- * new style signals.
+- */
+- set_thread_flag(TIF_NEWSIGNALS);
+-
+ if (act) {
+ u32 u_handler, u_restorer;
+
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
deleted file mode 100644
index e91194f..0000000
@@ -225395,6 +282333,291 @@
- optval, optlen);
- return ret;
-}
+diff --git a/arch/sparc64/kernel/syscalls.S b/arch/sparc64/kernel/syscalls.S
+new file mode 100644
+index 0000000..db19ed6
+--- /dev/null
++++ b/arch/sparc64/kernel/syscalls.S
+@@ -0,0 +1,279 @@
++ /* SunOS's execv() call only specifies the argv argument, the
++ * environment settings are the same as the calling processes.
++ */
++sys_execve:
++ sethi %hi(sparc_execve), %g1
++ ba,pt %xcc, execve_merge
++ or %g1, %lo(sparc_execve), %g1
++
++#ifdef CONFIG_COMPAT
++sunos_execv:
++ stx %g0, [%sp + PTREGS_OFF + PT_V9_I2]
++sys32_execve:
++ sethi %hi(sparc32_execve), %g1
++ or %g1, %lo(sparc32_execve), %g1
++#endif
++
++execve_merge:
++ flushw
++ jmpl %g1, %g0
++ add %sp, PTREGS_OFF, %o0
++
++ .align 32
++sys_pipe:
++ ba,pt %xcc, sparc_pipe
++ add %sp, PTREGS_OFF, %o0
++sys_nis_syscall:
++ ba,pt %xcc, c_sys_nis_syscall
++ add %sp, PTREGS_OFF, %o0
++sys_memory_ordering:
++ ba,pt %xcc, sparc_memory_ordering
++ add %sp, PTREGS_OFF, %o1
++sys_sigaltstack:
++ ba,pt %xcc, do_sigaltstack
++ add %i6, STACK_BIAS, %o2
++#ifdef CONFIG_COMPAT
++sys32_sigstack:
++ ba,pt %xcc, do_sys32_sigstack
++ mov %i6, %o2
++sys32_sigaltstack:
++ ba,pt %xcc, do_sys32_sigaltstack
++ mov %i6, %o2
++#endif
++ .align 32
++#ifdef CONFIG_COMPAT
++sys32_sigreturn:
++ add %sp, PTREGS_OFF, %o0
++ call do_sigreturn32
++ add %o7, 1f-.-4, %o7
++ nop
++#endif
++sys_rt_sigreturn:
++ add %sp, PTREGS_OFF, %o0
++ call do_rt_sigreturn
++ add %o7, 1f-.-4, %o7
++ nop
++#ifdef CONFIG_COMPAT
++sys32_rt_sigreturn:
++ add %sp, PTREGS_OFF, %o0
++ call do_rt_sigreturn32
++ add %o7, 1f-.-4, %o7
++ nop
++#endif
++ .align 32
++1: ldx [%g6 + TI_FLAGS], %l5
++ andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
++ be,pt %icc, rtrap
++ nop
++ add %sp, PTREGS_OFF, %o0
++ call syscall_trace
++ mov 1, %o1
++ ba,pt %xcc, rtrap
++ nop
++
++ /* This is how fork() was meant to be done, 8 instruction entry.
++ *
++ * I questioned the following code briefly, let me clear things
++ * up so you must not reason on it like I did.
++ *
++ * Know the fork_kpsr etc. we use in the sparc32 port? We don't
++ * need it here because the only piece of window state we copy to
++ * the child is the CWP register. Even if the parent sleeps,
++ * we are safe because we stuck it into pt_regs of the parent
++ * so it will not change.
++ *
++ * XXX This raises the question, whether we can do the same on
++ * XXX sparc32 to get rid of fork_kpsr _and_ fork_kwim. The
++ * XXX answer is yes. We stick fork_kpsr in UREG_G0 and
++ * XXX fork_kwim in UREG_G1 (global registers are considered
++ * XXX volatile across a system call in the sparc ABI I think
++ * XXX if it isn't we can use regs->y instead, anyone who depends
++ * XXX upon the Y register being preserved across a fork deserves
++ * XXX to lose).
++ *
++ * In fact we should take advantage of that fact for other things
++ * during system calls...
++ */
++ .align 32
++sys_vfork: /* Under Linux, vfork and fork are just special cases of clone. */
++ sethi %hi(0x4000 | 0x0100 | SIGCHLD), %o0
++ or %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
++ ba,pt %xcc, sys_clone
++sys_fork:
++ clr %o1
++ mov SIGCHLD, %o0
++sys_clone:
++ flushw
++ movrz %o1, %fp, %o1
++ mov 0, %o3
++ ba,pt %xcc, sparc_do_fork
++ add %sp, PTREGS_OFF, %o2
++
++ .globl ret_from_syscall
++ret_from_syscall:
++ /* Clear current_thread_info()->new_child, and
++ * check performance counter stuff too.
++ */
++ stb %g0, [%g6 + TI_NEW_CHILD]
++ ldx [%g6 + TI_FLAGS], %l0
++ call schedule_tail
++ mov %g7, %o0
++ andcc %l0, _TIF_PERFCTR, %g0
++ be,pt %icc, 1f
++ nop
++ ldx [%g6 + TI_PCR], %o7
++ wr %g0, %o7, %pcr
++
++ /* Blackbird errata workaround. See commentary in
++ * smp.c:smp_percpu_timer_interrupt() for more
++ * information.
++ */
++ ba,pt %xcc, 99f
++ nop
++
++ .align 64
++99: wr %g0, %g0, %pic
++ rd %pic, %g0
++
++1: ba,pt %xcc, ret_sys_call
++ ldx [%sp + PTREGS_OFF + PT_V9_I0], %o0
++
++ .globl sparc_exit
++ .type sparc_exit,#function
++sparc_exit:
++ rdpr %pstate, %g2
++ wrpr %g2, PSTATE_IE, %pstate
++ rdpr %otherwin, %g1
++ rdpr %cansave, %g3
++ add %g3, %g1, %g3
++ wrpr %g3, 0x0, %cansave
++ wrpr %g0, 0x0, %otherwin
++ wrpr %g2, 0x0, %pstate
++ ba,pt %xcc, sys_exit
++ stb %g0, [%g6 + TI_WSAVED]
++ .size sparc_exit,.-sparc_exit
++
++linux_sparc_ni_syscall:
++ sethi %hi(sys_ni_syscall), %l7
++ ba,pt %xcc, 4f
++ or %l7, %lo(sys_ni_syscall), %l7
++
++linux_syscall_trace32:
++ add %sp, PTREGS_OFF, %o0
++ call syscall_trace
++ clr %o1
++ srl %i0, 0, %o0
++ srl %i4, 0, %o4
++ srl %i1, 0, %o1
++ srl %i2, 0, %o2
++ ba,pt %xcc, 2f
++ srl %i3, 0, %o3
++
++linux_syscall_trace:
++ add %sp, PTREGS_OFF, %o0
++ call syscall_trace
++ clr %o1
++ mov %i0, %o0
++ mov %i1, %o1
++ mov %i2, %o2
++ mov %i3, %o3
++ b,pt %xcc, 2f
++ mov %i4, %o4
++
++
++ /* Linux 32-bit system calls enter here... */
++ .align 32
++ .globl linux_sparc_syscall32
++linux_sparc_syscall32:
++ /* Direct access to user regs, much faster. */
++ cmp %g1, NR_SYSCALLS ! IEU1 Group
++ bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI
++ srl %i0, 0, %o0 ! IEU0
++ sll %g1, 2, %l4 ! IEU0 Group
++ srl %i4, 0, %o4 ! IEU1
++ lduw [%l7 + %l4], %l7 ! Load
++ srl %i1, 0, %o1 ! IEU0 Group
++ ldx [%g6 + TI_FLAGS], %l0 ! Load
++
++ srl %i5, 0, %o5 ! IEU1
++ srl %i2, 0, %o2 ! IEU0 Group
++ andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
++ bne,pn %icc, linux_syscall_trace32 ! CTI
++ mov %i0, %l5 ! IEU1
++ call %l7 ! CTI Group brk forced
++ srl %i3, 0, %o3 ! IEU0
++ ba,a,pt %xcc, 3f
++
++ /* Linux native system calls enter here... */
++ .align 32
++ .globl linux_sparc_syscall
++linux_sparc_syscall:
++ /* Direct access to user regs, much faster. */
++ cmp %g1, NR_SYSCALLS ! IEU1 Group
++ bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI
++ mov %i0, %o0 ! IEU0
++ sll %g1, 2, %l4 ! IEU0 Group
++ mov %i1, %o1 ! IEU1
++ lduw [%l7 + %l4], %l7 ! Load
++4: mov %i2, %o2 ! IEU0 Group
++ ldx [%g6 + TI_FLAGS], %l0 ! Load
++
++ mov %i3, %o3 ! IEU1
++ mov %i4, %o4 ! IEU0 Group
++ andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
++ bne,pn %icc, linux_syscall_trace ! CTI Group
++ mov %i0, %l5 ! IEU0
++2: call %l7 ! CTI Group brk forced
++ mov %i5, %o5 ! IEU0
++ nop
++
++3: stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
++ret_sys_call:
++ ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
++ ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
++ sra %o0, 0, %o0
++ mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
++ sllx %g2, 32, %g2
++
++ /* Check if force_successful_syscall_return()
++ * was invoked.
++ */
++ ldub [%g6 + TI_SYS_NOERROR], %l2
++ brnz,a,pn %l2, 80f
++ stb %g0, [%g6 + TI_SYS_NOERROR]
++
++ cmp %o0, -ERESTART_RESTARTBLOCK
++ bgeu,pn %xcc, 1f
++ andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6
++80:
++ /* System call success, clear Carry condition code. */
++ andn %g3, %g2, %g3
++ stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
++ 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
++ stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
++
++1:
++ /* System call failure, set Carry condition code.
++ * Also, get abs(errno) to return to the process.
++ */
++ andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6
++ sub %g0, %o0, %o0
++ or %g3, %g2, %g3
++ stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
++ stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
++ bne,pn %icc, linux_syscall_trace2
++ add %l1, 0x4, %l2 ! npc = npc+4
++ stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
++
++ b,pt %xcc, rtrap
++ stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
++linux_syscall_trace2:
++ add %sp, PTREGS_OFF, %o0
++ call syscall_trace
++ mov 1, %o1
++ stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
++ ba,pt %xcc, rtrap
++ stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
diff --git a/arch/sparc64/kernel/sysfs.c b/arch/sparc64/kernel/sysfs.c
index 52816c7..e885034 100644
--- a/arch/sparc64/kernel/sysfs.c
@@ -225624,7 +282847,7 @@
winfix_trampoline:
diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
-index 7575aa3..b0de4c0 100644
+index 7575aa3..450053a 100644
--- a/arch/sparc64/kernel/ttable.S
+++ b/arch/sparc64/kernel/ttable.S
@@ -117,16 +117,13 @@ tl0_f4o: FILL_4_OTHER
@@ -225658,6 +282881,50 @@
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)
+@@ -157,7 +153,7 @@ tl0_resv164: BTRAP(0x164) BTRAP(0x165) BTRAP(0x166) BTRAP(0x167) BTRAP(0x168)
+ tl0_resv169: BTRAP(0x169) BTRAP(0x16a) BTRAP(0x16b) BTRAP(0x16c)
+ tl0_linux64: LINUX_64BIT_SYSCALL_TRAP
+ tl0_gsctx: TRAP(sparc64_get_context) TRAP(sparc64_set_context)
+-tl0_resv170: KPROBES_TRAP(0x170) KPROBES_TRAP(0x171) BTRAP(0x172)
++tl0_resv170: KPROBES_TRAP(0x170) KPROBES_TRAP(0x171) KGDB_TRAP(0x172)
+ tl0_resv173: BTRAP(0x173) BTRAP(0x174) BTRAP(0x175) BTRAP(0x176) BTRAP(0x177)
+ tl0_resv178: BTRAP(0x178) BTRAP(0x179) BTRAP(0x17a) BTRAP(0x17b) BTRAP(0x17c)
+ tl0_resv17d: BTRAP(0x17d) BTRAP(0x17e) BTRAP(0x17f)
+diff --git a/arch/sparc64/kernel/utrap.S b/arch/sparc64/kernel/utrap.S
+new file mode 100644
+index 0000000..b7f0f3f
+--- /dev/null
++++ b/arch/sparc64/kernel/utrap.S
+@@ -0,0 +1,29 @@
++ .globl utrap_trap
++ .type utrap_trap,#function
++utrap_trap: /* %g3=handler,%g4=level */
++ TRAP_LOAD_THREAD_REG(%g6, %g1)
++ ldx [%g6 + TI_UTRAPS], %g1
++ brnz,pt %g1, invoke_utrap
++ nop
++
++ ba,pt %xcc, etrap
++ rd %pc, %g7
++ mov %l4, %o1
++ call bad_trap
++ add %sp, PTREGS_OFF, %o0
++ ba,pt %xcc, rtrap
++ nop
++
++invoke_utrap:
++ sllx %g3, 3, %g3
++ ldx [%g1 + %g3], %g1
++ save %sp, -128, %sp
++ rdpr %tstate, %l6
++ rdpr %cwp, %l7
++ andn %l6, TSTATE_CWP, %l6
++ wrpr %l6, %l7, %tstate
++ rdpr %tpc, %l6
++ rdpr %tnpc, %l7
++ wrpr %g1, 0, %tnpc
++ done
++ .size utrap_trap,.-utrap_trap
diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S
index c4aa110..a6b0863 100644
--- a/arch/sparc64/kernel/winfixup.S
@@ -225705,8 +282972,23 @@
nop
- ba,a,pt %xcc, rtrap_clr_l6
+ ba,a,pt %xcc, rtrap
+diff --git a/arch/sparc64/lib/iomap.c b/arch/sparc64/lib/iomap.c
+index ac556db..7120ebb 100644
+--- a/arch/sparc64/lib/iomap.c
++++ b/arch/sparc64/lib/iomap.c
+@@ -21,8 +21,8 @@ EXPORT_SYMBOL(ioport_unmap);
+ /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+ {
+- unsigned long start = pci_resource_start(dev, bar);
+- unsigned long len = pci_resource_len(dev, bar);
++ resource_size_t start = pci_resource_start(dev, bar);
++ resource_size_t len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (!len || !start)
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
-index f37078d..177d8aa 100644
+index f37078d..4cad0b3 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -24,6 +24,8 @@
@@ -225728,7 +283010,15 @@
static int cmp_p64(const void *a, const void *b)
{
-@@ -715,285 +715,684 @@ out:
+@@ -160,6 +160,7 @@ extern unsigned int sparc_ramdisk_image;
+ extern unsigned int sparc_ramdisk_size;
+
+ struct page *mem_map_zero __read_mostly;
++EXPORT_SYMBOL(mem_map_zero);
+
+ unsigned int sparc64_highest_unlocked_tlb_ent __read_mostly;
+
+@@ -715,286 +716,685 @@ out:
smp_new_mmu_context_version();
}
@@ -225749,22 +283039,22 @@
+
+ if (strstr(p, "off"))
+ numa_enabled = 0;
-+
+
+- bootmap_size = bootmem_bootmap_pages(end_pfn - start_pfn);
+- bootmap_size <<= PAGE_SHIFT;
+ if (strstr(p, "debug"))
+ numa_debug = 1;
-+
+
+- avoid_start = avoid_end = 0;
+ 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
@@ -226010,7 +283300,8 @@
+
+ for (i = 0; i < NR_CPUS; i++)
+ numa_cpu_lookup_table[i] = 0;
-+
+
+- if (trim_high <= trim_low)
+ numa_cpumask_lookup_table[0] = CPU_MASK_ALL;
+}
+
@@ -226034,8 +283325,7 @@
+ 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;
@@ -226110,7 +283400,8 @@
+
+ return scan_pio_for_cfg_handle(md, candidate, cfg_handle);
+}
-+
+
+- if (!to_trim)
+int of_node_to_nid(struct device_node *dp)
+{
+ const struct linux_prom64_registers *regs;
@@ -226118,8 +283409,7 @@
+ u32 cfg_handle;
+ int count, nid;
+ u64 grp;
-
-- if (!to_trim)
++
+ if (!mlgroups)
+ return -1;
+
@@ -226384,27 +283674,30 @@
- min_low_pfn = (phys_base >> PAGE_SHIFT);
+ return 0;
+}
-+
+
+- bootmap_pfn = choose_bootmap_pfn(min_low_pfn, end_pfn);
+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;
++ numa_parse_mdesc_group_cpus(md, grp, &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);
++ for_each_cpu_mask(cpu, mask)
++ numa_cpu_lookup_table[cpu] = index;
++ numa_cpumask_lookup_table[index] = mask;
+
+-#ifdef CONFIG_BLK_DEV_INITRD
+- if (initrd_start) {
+- size = initrd_end - initrd_start;
+ if (numa_debug) {
+ printk(KERN_INFO "NUMA GROUP[%d]: cpus [ ", index);
+ for_each_cpu_mask(cpu, mask)
@@ -226412,12 +283705,13 @@
+ printk("]\n");
+ }
--#ifdef CONFIG_BLK_DEV_INITRD
-- if (initrd_start) {
-- size = initrd_end - initrd_start;
+- /* Reserve the initrd image area. */
+- reserve_bootmem(initrd_start, size, BOOTMEM_DEFAULT);
+ return numa_attach_mlgroup(md, grp, index);
+}
-+
+
+- initrd_start += PAGE_OFFSET;
+- initrd_end += PAGE_OFFSET;
+static int __init numa_parse_mdesc(void)
+{
+ struct mdesc_handle *md = mdesc_grab();
@@ -226444,7 +283738,7 @@
+ if (err < 0)
+ break;
+ count++;
-+ }
+ }
+
+ add_node_ranges();
+
@@ -226463,15 +283757,11 @@
+{
+ 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) {
@@ -226479,7 +283769,7 @@
+ err = numa_parse_mdesc();
+ else
+ err = numa_parse_sun4u();
- }
++ }
+ return err;
+}
+
@@ -226536,8 +283826,8 @@
+ 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);
@@ -226610,7 +283900,7 @@
+ 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)
@@ -226629,10 +283919,11 @@
+
+ for_each_online_node(nid)
+ bootmem_init_one_node(nid);
-
++
sparse_init();
-@@ -1289,7 +1688,7 @@ void __init setup_per_cpu_areas(void)
+ return end_pfn;
+@@ -1289,7 +1689,7 @@ void __init setup_per_cpu_areas(void)
void __init paging_init(void)
{
@@ -226641,7 +283932,31 @@
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)
+@@ -1300,9 +1700,21 @@ void __init paging_init(void)
+ * functions like clear_dcache_dirty_cpu use the cpu mask
+ * in 13-bit signed-immediate instruction fields.
+ */
+- BUILD_BUG_ON(FLAGS_RESERVED != 32);
++
++ /*
++ * Page flags must not reach into upper 32 bits that are used
++ * for the cpu number
++ */
++ BUILD_BUG_ON(NR_PAGEFLAGS > 32);
++
++ /*
++ * The bit fields placed in the high range must not reach below
++ * the 32 bit boundary. Otherwise we cannot place the cpu field
++ * at the 32 bit boundary.
++ */
+ BUILD_BUG_ON(SECTIONS_WIDTH + NODES_WIDTH + ZONES_WIDTH +
+- ilog2(roundup_pow_of_two(NR_CPUS)) > FLAGS_RESERVED);
++ ilog2(roundup_pow_of_two(NR_CPUS)) > 32);
++
+ BUILD_BUG_ON(NR_CPUS > 4096);
+
+ kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL;
+@@ -1330,12 +1742,26 @@ void __init paging_init(void)
sun4v_ktsb_init();
}
@@ -226669,7 +283984,7 @@
set_bit(0, mmu_context_bmap);
-@@ -1371,14 +1784,10 @@ void __init paging_init(void)
+@@ -1371,14 +1797,10 @@ void __init paging_init(void)
if (tlb_type == hypervisor)
sun4v_ktsb_register();
@@ -226688,7 +284003,7 @@
real_setup_per_cpu_areas();
prom_build_devicetree();
-@@ -1386,20 +1795,22 @@ void __init paging_init(void)
+@@ -1386,20 +1808,22 @@ void __init paging_init(void)
if (tlb_type == hypervisor)
sun4v_mdesc_init();
@@ -226721,7 +284036,7 @@
}
printk("Booting Linux...\n");
-@@ -1408,21 +1819,52 @@ void __init paging_init(void)
+@@ -1408,21 +1832,52 @@ void __init paging_init(void)
cpu_probe();
}
@@ -226780,7 +284095,7 @@
while (old_start < old_end) {
int n;
-@@ -1440,7 +1882,16 @@ static void __init taint_real_pages(void)
+@@ -1440,7 +1895,16 @@ static void __init taint_real_pages(void)
goto do_next_page;
}
}
@@ -226798,7 +284113,7 @@
do_next_page:
old_start += PAGE_SIZE;
-@@ -1448,32 +1899,6 @@ static void __init taint_real_pages(void)
+@@ -1448,32 +1912,6 @@ static void __init taint_real_pages(void)
}
}
@@ -226831,7 +284146,7 @@
void __init mem_init(void)
{
unsigned long codepages, datapages, initpages;
-@@ -1496,14 +1921,26 @@ void __init mem_init(void)
+@@ -1496,14 +1934,26 @@ void __init mem_init(void)
addr += PAGE_SIZE;
}
@@ -226875,7 +284190,7 @@
/* 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
+index 2865c10..796e005 100644
--- a/arch/sparc64/mm/ultra.S
+++ b/arch/sparc64/mm/ultra.S
@@ -476,7 +476,6 @@ xcall_sync_tick:
@@ -226903,6 +284218,40 @@
.globl __hypervisor_xcall_flush_tlb_mm
__hypervisor_xcall_flush_tlb_mm: /* 21 insns */
+@@ -678,6 +676,33 @@ xcall_new_mmu_context_version:
+ wr %g0, (1 << PIL_SMP_CTX_NEW_VERSION), %set_softint
+ retry
+
++#ifdef CONFIG_KGDB
++ .globl xcall_kgdb_capture
++xcall_kgdb_capture:
++661: rdpr %pstate, %g2
++ wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate
++ .section .sun4v_2insn_patch, "ax"
++ .word 661b
++ nop
++ nop
++ .previous
++
++ rdpr %pil, %g2
++ wrpr %g0, 15, %pil
++ sethi %hi(109f), %g7
++ ba,pt %xcc, etrap_irq
++109: or %g7, %lo(109b), %g7
++#ifdef CONFIG_TRACE_IRQFLAGS
++ call trace_hardirqs_off
++ nop
++#endif
++ call smp_kgdb_capture_client
++ add %sp, PTREGS_OFF, %o0
++ /* Has to be a non-v9 branch due to the large distance. */
++ ba rtrap_xcall
++ ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
++#endif
++
+ #endif /* CONFIG_SMP */
+
+
diff --git a/arch/sparc64/solaris/Makefile b/arch/sparc64/solaris/Makefile
deleted file mode 100644
index 8c86630..0000000
@@ -232426,10 +289775,21 @@
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
+index 6533b34..5696e7b 100644
--- a/arch/um/Kconfig.x86_64
+++ b/arch/um/Kconfig.x86_64
-@@ -11,10 +11,6 @@ config RWSEM_GENERIC_SPINLOCK
+@@ -1,3 +1,10 @@
++
++menu "Host processor type and features"
++
++source "arch/x86/Kconfig.cpu"
++
++endmenu
++
+ config UML_X86
+ bool
+ default y
+@@ -11,10 +18,6 @@ config RWSEM_GENERIC_SPINLOCK
bool
default y
@@ -232440,6 +289800,814 @@
config 3_LEVEL_PGTABLES
bool
default y
+diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
+index db3082b..6e51424 100644
+--- a/arch/um/drivers/chan_kern.c
++++ b/arch/um/drivers/chan_kern.c
+@@ -125,7 +125,7 @@ static int open_one_chan(struct chan *chan)
+ return 0;
+ }
+
+-int open_chan(struct list_head *chans)
++static int open_chan(struct list_head *chans)
+ {
+ struct list_head *ele;
+ struct chan *chan;
+@@ -583,19 +583,6 @@ int parse_chan_pair(char *str, struct line *line, int device,
+ return 0;
+ }
+
+-int chan_out_fd(struct list_head *chans)
+-{
+- struct list_head *ele;
+- struct chan *chan;
+-
+- list_for_each(ele, chans) {
+- chan = list_entry(ele, struct chan, list);
+- if (chan->primary && chan->output)
+- return chan->fd;
+- }
+- return -1;
+-}
+-
+ void chan_interrupt(struct list_head *chans, struct delayed_work *task,
+ struct tty_struct *tty, int irq)
+ {
+diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
+index 2c898c4..10b86e1 100644
+--- a/arch/um/drivers/line.c
++++ b/arch/um/drivers/line.c
+@@ -304,7 +304,7 @@ int line_ioctl(struct tty_struct *tty, struct file * file,
+ break;
+ if (i == ARRAY_SIZE(tty_ioctls)) {
+ printk(KERN_ERR "%s: %s: unknown ioctl: 0x%x\n",
+- __FUNCTION__, tty->name, cmd);
++ __func__, tty->name, cmd);
+ }
+ ret = -ENOIOCTLCMD;
+ break;
+diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c
+index 822092f..8c4378a 100644
+--- a/arch/um/drivers/mcast_kern.c
++++ b/arch/um/drivers/mcast_kern.c
+@@ -58,7 +58,7 @@ static const struct net_kern_info mcast_kern_info = {
+ .write = mcast_write,
+ };
+
+-int mcast_setup(char *str, char **mac_out, void *data)
++static int mcast_setup(char *str, char **mac_out, void *data)
+ {
+ struct mcast_init *init = data;
+ char *port_str = NULL, *ttl_str = NULL, *remain;
+diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
+index 13af2f0..f8cf4c8 100644
+--- a/arch/um/drivers/mconsole_user.c
++++ b/arch/um/drivers/mconsole_user.c
+@@ -39,7 +39,7 @@ static struct mconsole_command commands[] = {
+ /* Initialized in mconsole_init, which is an initcall */
+ char mconsole_socket_name[256];
+
+-int mconsole_reply_v0(struct mc_request *req, char *reply)
++static int mconsole_reply_v0(struct mc_request *req, char *reply)
+ {
+ struct iovec iov;
+ struct msghdr msg;
+diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
+index 1d43bdf..5b4ca8d 100644
+--- a/arch/um/drivers/net_kern.c
++++ b/arch/um/drivers/net_kern.c
+@@ -116,7 +116,7 @@ static void uml_dev_close(struct work_struct *work)
+ dev_close(lp->dev);
+ }
+
+-irqreturn_t uml_net_interrupt(int irq, void *dev_id)
++static irqreturn_t uml_net_interrupt(int irq, void *dev_id)
+ {
+ struct net_device *dev = dev_id;
+ struct uml_net_private *lp = dev->priv;
+@@ -296,7 +296,7 @@ static struct ethtool_ops uml_net_ethtool_ops = {
+ .get_link = ethtool_op_get_link,
+ };
+
+-void uml_net_user_timer_expire(unsigned long _conn)
++static void uml_net_user_timer_expire(unsigned long _conn)
+ {
+ #ifdef undef
+ struct connection *conn = (struct connection *)_conn;
+@@ -786,7 +786,7 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event,
+ }
+
+ /* uml_net_init shouldn't be called twice on two CPUs at the same time */
+-struct notifier_block uml_inetaddr_notifier = {
++static struct notifier_block uml_inetaddr_notifier = {
+ .notifier_call = uml_inetaddr_event,
+ };
+
+diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
+index addd759..d269ca3 100644
+--- a/arch/um/drivers/port_user.c
++++ b/arch/um/drivers/port_user.c
+@@ -153,7 +153,7 @@ struct port_pre_exec_data {
+ int pipe_fd;
+ };
+
+-void port_pre_exec(void *arg)
++static void port_pre_exec(void *arg)
+ {
+ struct port_pre_exec_data *data = arg;
+
+diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c
+index 6b4a0f9..d19faec 100644
+--- a/arch/um/drivers/slip_kern.c
++++ b/arch/um/drivers/slip_kern.c
+@@ -13,7 +13,7 @@ struct slip_init {
+ char *gate_addr;
+ };
+
+-void slip_init(struct net_device *dev, void *data)
++static void slip_init(struct net_device *dev, void *data)
+ {
+ struct uml_net_private *private;
+ struct slip_data *spri;
+@@ -57,7 +57,7 @@ static int slip_write(int fd, struct sk_buff *skb, struct uml_net_private *lp)
+ (struct slip_data *) &lp->user);
+ }
+
+-const struct net_kern_info slip_kern_info = {
++static const struct net_kern_info slip_kern_info = {
+ .init = slip_init,
+ .protocol = slip_protocol,
+ .read = slip_read,
+diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
+index cec0c33..49266f6 100644
+--- a/arch/um/drivers/stdio_console.c
++++ b/arch/um/drivers/stdio_console.c
+@@ -34,7 +34,7 @@
+
+ static struct tty_driver *console_driver;
+
+-void stdio_announce(char *dev_name, int dev)
++static void stdio_announce(char *dev_name, int dev)
+ {
+ printk(KERN_INFO "Virtual console %d assigned device '%s'\n", dev,
+ dev_name);
+@@ -158,7 +158,7 @@ static struct console stdiocons = {
+ .index = -1,
+ };
+
+-int stdio_init(void)
++static int stdio_init(void)
+ {
+ char *new_title;
+
+diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
+index be3a279..5e45e39 100644
+--- a/arch/um/drivers/ubd_kern.c
++++ b/arch/um/drivers/ubd_kern.c
+@@ -72,18 +72,6 @@ struct io_thread_req {
+ int error;
+ };
+
+-extern int open_ubd_file(char *file, struct openflags *openflags, int shared,
+- char **backing_file_out, int *bitmap_offset_out,
+- unsigned long *bitmap_len_out, int *data_offset_out,
+- int *create_cow_out);
+-extern int create_cow_file(char *cow_file, char *backing_file,
+- struct openflags flags, int sectorsize,
+- int alignment, int *bitmap_offset_out,
+- unsigned long *bitmap_len_out,
+- int *data_offset_out);
+-extern int read_cow_bitmap(int fd, void *buf, int offset, int len);
+-extern void do_io(struct io_thread_req *req);
+-
+ static inline int ubd_test_bit(__u64 bit, unsigned char *data)
+ {
+ __u64 n;
+@@ -200,7 +188,7 @@ struct ubd {
+ }
+
+ /* Protected by ubd_lock */
+-struct ubd ubd_devs[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
++static struct ubd ubd_devs[MAX_DEV] = { [0 ... MAX_DEV - 1] = DEFAULT_UBD };
+
+ /* Only changed by fake_ide_setup which is a setup */
+ static int fake_ide = 0;
+@@ -463,7 +451,7 @@ __uml_help(udb_setup,
+ static void do_ubd_request(struct request_queue * q);
+
+ /* Only changed by ubd_init, which is an initcall. */
+-int thread_fd = -1;
++static int thread_fd = -1;
+
+ static void ubd_end_request(struct request *req, int bytes, int error)
+ {
+@@ -531,7 +519,7 @@ static irqreturn_t ubd_intr(int irq, void *dev)
+ /* Only changed by ubd_init, which is an initcall. */
+ static int io_pid = -1;
+
+-void kill_io_thread(void)
++static void kill_io_thread(void)
+ {
+ if(io_pid != -1)
+ os_kill_process(io_pid, 1);
+@@ -547,6 +535,192 @@ static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out)
+ return os_file_size(file, size_out);
+ }
+
++static int read_cow_bitmap(int fd, void *buf, int offset, int len)
++{
++ int err;
++
++ err = os_seek_file(fd, offset);
++ if (err < 0)
++ return err;
++
++ err = os_read_file(fd, buf, len);
++ if (err < 0)
++ return err;
++
++ return 0;
++}
++
++static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
++{
++ unsigned long modtime;
++ unsigned long long actual;
++ int err;
++
++ err = os_file_modtime(file, &modtime);
++ if (err < 0) {
++ printk(KERN_ERR "Failed to get modification time of backing "
++ "file \"%s\", err = %d\n", file, -err);
++ return err;
++ }
++
++ err = os_file_size(file, &actual);
++ if (err < 0) {
++ printk(KERN_ERR "Failed to get size of backing file \"%s\", "
++ "err = %d\n", file, -err);
++ return err;
++ }
++
++ if (actual != size) {
++ /*__u64 can be a long on AMD64 and with %lu GCC complains; so
++ * the typecast.*/
++ printk(KERN_ERR "Size mismatch (%llu vs %llu) of COW header "
++ "vs backing file\n", (unsigned long long) size, actual);
++ return -EINVAL;
++ }
++ if (modtime != mtime) {
++ printk(KERN_ERR "mtime mismatch (%ld vs %ld) of COW header vs "
++ "backing file\n", mtime, modtime);
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow)
++{
++ struct uml_stat buf1, buf2;
++ int err;
++
++ if (from_cmdline == NULL)
++ return 0;
++ if (!strcmp(from_cmdline, from_cow))
++ return 0;
++
++ err = os_stat_file(from_cmdline, &buf1);
++ if (err < 0) {
++ printk(KERN_ERR "Couldn't stat '%s', err = %d\n", from_cmdline,
++ -err);
++ return 0;
++ }
++ err = os_stat_file(from_cow, &buf2);
++ if (err < 0) {
++ printk(KERN_ERR "Couldn't stat '%s', err = %d\n", from_cow,
++ -err);
++ return 1;
++ }
++ if ((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
++ return 0;
++
++ printk(KERN_ERR "Backing file mismatch - \"%s\" requested, "
++ "\"%s\" specified in COW header of \"%s\"\n",
++ from_cmdline, from_cow, cow);
++ return 1;
++}
++
++static int open_ubd_file(char *file, struct openflags *openflags, int shared,
++ char **backing_file_out, int *bitmap_offset_out,
++ unsigned long *bitmap_len_out, int *data_offset_out,
++ int *create_cow_out)
++{
++ time_t mtime;
++ unsigned long long size;
++ __u32 version, align;
++ char *backing_file;
++ int fd, err, sectorsize, asked_switch, mode = 0644;
++
++ fd = os_open_file(file, *openflags, mode);
++ if (fd < 0) {
++ if ((fd == -ENOENT) && (create_cow_out != NULL))
++ *create_cow_out = 1;
++ if (!openflags->w ||
++ ((fd != -EROFS) && (fd != -EACCES)))
++ return fd;
++ openflags->w = 0;
++ fd = os_open_file(file, *openflags, mode);
++ if (fd < 0)
++ return fd;
++ }
++
++ if (shared)
++ printk(KERN_INFO "Not locking \"%s\" on the host\n", file);
++ else {
++ err = os_lock_file(fd, openflags->w);
++ if (err < 0) {
++ printk(KERN_ERR "Failed to lock '%s', err = %d\n",
++ file, -err);
++ goto out_close;
++ }
++ }
++
++ /* Successful return case! */
++ if (backing_file_out == NULL)
++ return fd;
++
++ err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
++ &size, §orsize, &align, bitmap_offset_out);
++ if (err && (*backing_file_out != NULL)) {
++ printk(KERN_ERR "Failed to read COW header from COW file "
++ "\"%s\", errno = %d\n", file, -err);
++ goto out_close;
++ }
++ if (err)
++ return fd;
++
++ asked_switch = path_requires_switch(*backing_file_out, backing_file,
++ file);
++
++ /* Allow switching only if no mismatch. */
++ if (asked_switch && !backing_file_mismatch(*backing_file_out, size,
++ mtime)) {
++ printk(KERN_ERR "Switching backing file to '%s'\n",
++ *backing_file_out);
++ err = write_cow_header(file, fd, *backing_file_out,
++ sectorsize, align, &size);
++ if (err) {
++ printk(KERN_ERR "Switch failed, errno = %d\n", -err);
++ goto out_close;
++ }
++ } else {
++ *backing_file_out = backing_file;
++ err = backing_file_mismatch(*backing_file_out, size, mtime);
++ if (err)
++ goto out_close;
++ }
++
++ cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
++ bitmap_len_out, data_offset_out);
++
++ return fd;
++ out_close:
++ os_close_file(fd);
++ return err;
++}
++
++static int create_cow_file(char *cow_file, char *backing_file,
++ struct openflags flags,
++ int sectorsize, int alignment, int *bitmap_offset_out,
++ unsigned long *bitmap_len_out, int *data_offset_out)
++{
++ int err, fd;
++
++ flags.c = 1;
++ fd = open_ubd_file(cow_file, &flags, 0, NULL, NULL, NULL, NULL, NULL);
++ if (fd < 0) {
++ err = fd;
++ printk(KERN_ERR "Open of COW file '%s' failed, errno = %d\n",
++ cow_file, -err);
++ goto out;
++ }
++
++ err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment,
++ bitmap_offset_out, bitmap_len_out,
++ data_offset_out);
++ if (!err)
++ return fd;
++ os_close_file(fd);
++ out:
++ return err;
++}
++
+ static void ubd_close_dev(struct ubd *ubd_dev)
+ {
+ os_close_file(ubd_dev->fd);
+@@ -1166,185 +1340,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
+ return -EINVAL;
+ }
+
+-static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow)
+-{
+- struct uml_stat buf1, buf2;
+- int err;
+-
+- if(from_cmdline == NULL)
+- return 0;
+- if(!strcmp(from_cmdline, from_cow))
+- return 0;
+-
+- err = os_stat_file(from_cmdline, &buf1);
+- if(err < 0){
+- printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err);
+- return 0;
+- }
+- err = os_stat_file(from_cow, &buf2);
+- if(err < 0){
+- printk("Couldn't stat '%s', err = %d\n", from_cow, -err);
+- return 1;
+- }
+- if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
+- return 0;
+-
+- printk("Backing file mismatch - \"%s\" requested,\n"
+- "\"%s\" specified in COW header of \"%s\"\n",
+- from_cmdline, from_cow, cow);
+- return 1;
+-}
+-
+-static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
+-{
+- unsigned long modtime;
+- unsigned long long actual;
+- int err;
+-
+- err = os_file_modtime(file, &modtime);
+- if(err < 0){
+- printk("Failed to get modification time of backing file "
+- "\"%s\", err = %d\n", file, -err);
+- return err;
+- }
+-
+- err = os_file_size(file, &actual);
+- if(err < 0){
+- printk("Failed to get size of backing file \"%s\", "
+- "err = %d\n", file, -err);
+- return err;
+- }
+-
+- if(actual != size){
+- /*__u64 can be a long on AMD64 and with %lu GCC complains; so
+- * the typecast.*/
+- printk("Size mismatch (%llu vs %llu) of COW header vs backing "
+- "file\n", (unsigned long long) size, actual);
+- return -EINVAL;
+- }
+- if(modtime != mtime){
+- printk("mtime mismatch (%ld vs %ld) of COW header vs backing "
+- "file\n", mtime, modtime);
+- return -EINVAL;
+- }
+- return 0;
+-}
+-
+-int read_cow_bitmap(int fd, void *buf, int offset, int len)
+-{
+- int err;
+-
+- err = os_seek_file(fd, offset);
+- if(err < 0)
+- return err;
+-
+- err = os_read_file(fd, buf, len);
+- if(err < 0)
+- return err;
+-
+- return 0;
+-}
+-
+-int open_ubd_file(char *file, struct openflags *openflags, int shared,
+- char **backing_file_out, int *bitmap_offset_out,
+- unsigned long *bitmap_len_out, int *data_offset_out,
+- int *create_cow_out)
+-{
+- time_t mtime;
+- unsigned long long size;
+- __u32 version, align;
+- char *backing_file;
+- int fd, err, sectorsize, asked_switch, mode = 0644;
+-
+- fd = os_open_file(file, *openflags, mode);
+- if (fd < 0) {
+- if ((fd == -ENOENT) && (create_cow_out != NULL))
+- *create_cow_out = 1;
+- if (!openflags->w ||
+- ((fd != -EROFS) && (fd != -EACCES)))
+- return fd;
+- openflags->w = 0;
+- fd = os_open_file(file, *openflags, mode);
+- if (fd < 0)
+- return fd;
+- }
+-
+- if(shared)
+- printk("Not locking \"%s\" on the host\n", file);
+- else {
+- err = os_lock_file(fd, openflags->w);
+- if(err < 0){
+- printk("Failed to lock '%s', err = %d\n", file, -err);
+- goto out_close;
+- }
+- }
+-
+- /* Successful return case! */
+- if(backing_file_out == NULL)
+- return fd;
+-
+- err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
+- &size, §orsize, &align, bitmap_offset_out);
+- if(err && (*backing_file_out != NULL)){
+- printk("Failed to read COW header from COW file \"%s\", "
+- "errno = %d\n", file, -err);
+- goto out_close;
+- }
+- if(err)
+- return fd;
+-
+- asked_switch = path_requires_switch(*backing_file_out, backing_file, file);
+-
+- /* Allow switching only if no mismatch. */
+- if (asked_switch && !backing_file_mismatch(*backing_file_out, size, mtime)) {
+- printk("Switching backing file to '%s'\n", *backing_file_out);
+- err = write_cow_header(file, fd, *backing_file_out,
+- sectorsize, align, &size);
+- if (err) {
+- printk("Switch failed, errno = %d\n", -err);
+- goto out_close;
+- }
+- } else {
+- *backing_file_out = backing_file;
+- err = backing_file_mismatch(*backing_file_out, size, mtime);
+- if (err)
+- goto out_close;
+- }
+-
+- cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
+- bitmap_len_out, data_offset_out);
+-
+- return fd;
+- out_close:
+- os_close_file(fd);
+- return err;
+-}
+-
+-int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
+- int sectorsize, int alignment, int *bitmap_offset_out,
+- unsigned long *bitmap_len_out, int *data_offset_out)
+-{
+- int err, fd;
+-
+- flags.c = 1;
+- fd = open_ubd_file(cow_file, &flags, 0, NULL, NULL, NULL, NULL, NULL);
+- if(fd < 0){
+- err = fd;
+- printk("Open of COW file '%s' failed, errno = %d\n", cow_file,
+- -err);
+- goto out;
+- }
+-
+- err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment,
+- bitmap_offset_out, bitmap_len_out,
+- data_offset_out);
+- if(!err)
+- return fd;
+- os_close_file(fd);
+- out:
+- return err;
+-}
+-
+ static int update_bitmap(struct io_thread_req *req)
+ {
+ int n;
+@@ -1369,7 +1364,7 @@ static int update_bitmap(struct io_thread_req *req)
+ return 0;
+ }
+
+-void do_io(struct io_thread_req *req)
++static void do_io(struct io_thread_req *req)
+ {
+ char *buf;
+ unsigned long len;
+diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h
+index 624b510..1e65145 100644
+--- a/arch/um/include/chan_kern.h
++++ b/arch/um/include/chan_kern.h
+@@ -31,7 +31,6 @@ extern void chan_interrupt(struct list_head *chans, struct delayed_work *task,
+ struct tty_struct *tty, int irq);
+ extern int parse_chan_pair(char *str, struct line *line, int device,
+ const struct chan_opts *opts, char **error_out);
+-extern int open_chan(struct list_head *chans);
+ extern int write_chan(struct list_head *chans, const char *buf, int len,
+ int write_irq);
+ extern int console_write_chan(struct list_head *chans, const char *buf,
+@@ -45,7 +44,6 @@ extern void close_chan(struct list_head *chans, int delay_free_irq);
+ extern int chan_window_size(struct list_head *chans,
+ unsigned short *rows_out,
+ unsigned short *cols_out);
+-extern int chan_out_fd(struct list_head *chans);
+ extern int chan_config_string(struct list_head *chans, char *str, int size,
+ char **error_out);
+
+diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c
+index 984f80e..6540d2c 100644
+--- a/arch/um/kernel/exitcode.c
++++ b/arch/um/kernel/exitcode.c
+@@ -59,7 +59,7 @@ static int make_proc_exitcode(void)
+ {
+ struct proc_dir_entry *ent;
+
+- ent = create_proc_entry("exitcode", 0600, &proc_root);
++ ent = create_proc_entry("exitcode", 0600, NULL);
+ if (ent == NULL) {
+ printk(KERN_WARNING "make_proc_exitcode : Failed to register "
+ "/proc/exitcode\n");
+diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
+index e8cb9ff..83603cf 100644
+--- a/arch/um/kernel/process.c
++++ b/arch/um/kernel/process.c
+@@ -364,7 +364,7 @@ int __init make_proc_sysemu(void)
+ if (!sysemu_supported)
+ return 0;
+
+- ent = create_proc_entry("sysemu", 0600, &proc_root);
++ ent = create_proc_entry("sysemu", 0600, NULL);
+
+ if (ent == NULL)
+ {
+diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
+index e066e84..0d0cea2 100644
+--- a/arch/um/kernel/time.c
++++ b/arch/um/kernel/time.c
+@@ -4,6 +4,7 @@
+ */
+
+ #include <linux/clockchips.h>
++#include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/jiffies.h>
+ #include <linux/threads.h>
+@@ -109,8 +110,6 @@ static void __init setup_itimer(void)
+ clockevents_register_device(&itimer_clockevent);
+ }
+
+-extern void (*late_time_init)(void);
+-
+ void __init time_init(void)
+ {
+ long long nsecs;
+diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
+index a6c1dd1..56deed6 100644
+--- a/arch/um/kernel/um_arch.c
++++ b/arch/um/kernel/um_arch.c
+@@ -115,7 +115,7 @@ static int have_root __initdata = 0;
+ /* Set in uml_mem_setup and modified in linux_main */
+ long long physmem_size = 32 * 1024 * 1024;
+
+-static char *usage_string =
++static const char *usage_string =
+ "User Mode Linux v%s\n"
+ " available at http://user-mode-linux.sourceforge.net/\n\n";
+
+@@ -202,7 +202,7 @@ static void __init uml_checksetup(char *line, int *add)
+
+ p = &__uml_setup_start;
+ while (p < &__uml_setup_end) {
+- int n;
++ size_t n;
+
+ n = strlen(p->str);
+ if (!strncmp(line, p->str, n) && p->setup_func(line + n, add))
+@@ -258,7 +258,8 @@ int __init linux_main(int argc, char **argv)
+ {
+ unsigned long avail, diff;
+ unsigned long virtmem_size, max_physmem;
+- unsigned int i, add;
++ unsigned int i;
++ int add;
+ char * mode;
+
+ for (i = 1; i < argc; i++) {
+diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
+index f4bd349..f25c29a 100644
+--- a/arch/um/os-Linux/helper.c
++++ b/arch/um/os-Linux/helper.c
+@@ -14,6 +14,7 @@
+ #include "os.h"
+ #include "um_malloc.h"
+ #include "user.h"
++#include <linux/limits.h>
+
+ struct helper_data {
+ void (*pre_exec)(void*);
+diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
+index b616e15..997d019 100644
+--- a/arch/um/os-Linux/start_up.c
++++ b/arch/um/os-Linux/start_up.c
+@@ -25,15 +25,15 @@
+ #include "registers.h"
+ #include "skas_ptrace.h"
+
+-static int ptrace_child(void)
++static void ptrace_child(void)
+ {
+ int ret;
+ /* Calling os_getpid because some libcs cached getpid incorrectly */
+ int pid = os_getpid(), ppid = getppid();
+ int sc_result;
+
+- change_sig(SIGWINCH, 0);
+- if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
++ if (change_sig(SIGWINCH, 0) < 0 ||
++ ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
+ perror("ptrace");
+ kill(pid, SIGKILL);
+ }
+@@ -75,9 +75,8 @@ static void fatal(char *fmt, ...)
+ va_list list;
+
+ va_start(list, fmt);
+- vprintf(fmt, list);
++ vfprintf(stderr, fmt, list);
+ va_end(list);
+- fflush(stdout);
+
+ exit(1);
+ }
+@@ -87,9 +86,8 @@ static void non_fatal(char *fmt, ...)
+ va_list list;
+
+ va_start(list, fmt);
+- vprintf(fmt, list);
++ vfprintf(stderr, fmt, list);
+ va_end(list);
+- fflush(stdout);
+ }
+
+ static int start_ptraced_child(void)
+@@ -495,7 +493,7 @@ int __init parse_iomem(char *str, int *add)
+ driver = str;
+ file = strchr(str,',');
+ if (file == NULL) {
+- printf("parse_iomem : failed to parse iomem\n");
++ fprintf(stderr, "parse_iomem : failed to parse iomem\n");
+ goto out;
+ }
+ *file = '\0';
+diff --git a/arch/um/os-Linux/sys-i386/task_size.c b/arch/um/os-Linux/sys-i386/task_size.c
+index 48d211b..ccb49b0 100644
+--- a/arch/um/os-Linux/sys-i386/task_size.c
++++ b/arch/um/os-Linux/sys-i386/task_size.c
+@@ -88,7 +88,10 @@ unsigned long os_get_task_size(void)
+ sa.sa_handler = segfault;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_NODEFER;
+- sigaction(SIGSEGV, &sa, &old);
++ if (sigaction(SIGSEGV, &sa, &old)) {
++ perror("os_get_task_size");
++ exit(1);
++ }
+
+ if (!page_ok(bottom)) {
+ fprintf(stderr, "Address 0x%x no good?\n",
+@@ -110,11 +113,12 @@ unsigned long os_get_task_size(void)
+
+ out:
+ /* Restore the old SIGSEGV handling */
+- sigaction(SIGSEGV, &old, NULL);
+-
++ if (sigaction(SIGSEGV, &old, NULL)) {
++ perror("os_get_task_size");
++ exit(1);
++ }
+ top <<= UM_KERN_PAGE_SHIFT;
+ printf("0x%x\n", top);
+- fflush(stdout);
+
+ return top;
+ }
+diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
+index 964dc1a..598b5c1 100644
+--- a/arch/um/sys-i386/Makefile
++++ b/arch/um/sys-i386/Makefile
+@@ -6,7 +6,7 @@ obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
+ ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
+ sys_call_table.o tls.o
+
+-subarch-obj-y = lib/bitops_32.o lib/semaphore_32.o lib/string_32.o
++subarch-obj-y = lib/semaphore_32.o lib/string_32.o
+ subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o
+ subarch-obj-$(CONFIG_MODULES) += kernel/module_32.o
+
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
@@ -232492,6 +290660,19 @@
-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/Makefile b/arch/um/sys-x86_64/Makefile
+index 3c22de5..c8b4cce 100644
+--- a/arch/um/sys-x86_64/Makefile
++++ b/arch/um/sys-x86_64/Makefile
+@@ -10,7 +10,7 @@ obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
+
+ obj-$(CONFIG_MODULES) += um_module.o
+
+-subarch-obj-y = lib/bitops_64.o lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o
++subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o
+ subarch-obj-$(CONFIG_MODULES) += kernel/module_64.o
+
+ ldt-y = ../sys-i386/ldt.o
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
@@ -232527,6 +290708,42 @@
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/asm-offsets.c b/arch/v850/kernel/asm-offsets.c
+index cee5c31..581e698 100644
+--- a/arch/v850/kernel/asm-offsets.c
++++ b/arch/v850/kernel/asm-offsets.c
+@@ -13,14 +13,11 @@
+ #include <linux/kernel_stat.h>
+ #include <linux/ptrace.h>
+ #include <linux/hardirq.h>
++#include <linux/kbuild.h>
++
+ #include <asm/irq.h>
+ #include <asm/errno.h>
+
+-#define DEFINE(sym, val) \
+- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+-
+-#define BLANK() asm volatile("\n->" : : )
+-
+ int main (void)
+ {
+ /* offsets into the task struct */
+diff --git a/arch/v850/kernel/rte_mb_a_pci.c b/arch/v850/kernel/rte_mb_a_pci.c
+index 7165478..687e367 100644
+--- a/arch/v850/kernel/rte_mb_a_pci.c
++++ b/arch/v850/kernel/rte_mb_a_pci.c
+@@ -790,8 +790,8 @@ pci_free_consistent (struct pci_dev *pdev, size_t size, void *cpu_addr,
+
+ void __iomem *pci_iomap (struct pci_dev *dev, int bar, unsigned long max)
+ {
+- unsigned long start = pci_resource_start (dev, bar);
+- unsigned long len = pci_resource_len (dev, bar);
++ resource_size_t start = pci_resource_start (dev, bar);
++ resource_size_t len = pci_resource_len (dev, bar);
+
+ if (!start || len == 0)
+ return 0;
diff --git a/arch/v850/kernel/semaphore.c b/arch/v850/kernel/semaphore.c
deleted file mode 100644
index fc89fd6..0000000
@@ -232737,18 +290954,30 @@
* 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
+index 6c70fed..c3f8809 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
-@@ -23,6 +23,7 @@ config X86
+@@ -23,6 +23,19 @@ 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 DEFCONFIG_LIST
++ string
++ depends on X86_32
++ option defconfig_list
++ default "arch/x86/configs/i386_defconfig"
++
++config DEFCONFIG_LIST
++ string
++ depends on X86_64
++ option defconfig_list
++ default "arch/x86/configs/x86_64_defconfig"
config GENERIC_LOCKBREAK
-@@ -53,9 +54,6 @@ config STACKTRACE_SUPPORT
+@@ -53,9 +66,6 @@ config STACKTRACE_SUPPORT
config HAVE_LATENCYTOP_SUPPORT
def_bool y
@@ -232758,9 +290987,23 @@
config FAST_CMPXCHG_LOCAL
bool
default y
-@@ -117,7 +115,10 @@ config ARCH_HAS_CPU_RELAX
+@@ -88,9 +98,6 @@ config GENERIC_GPIO
+ config ARCH_MAY_HAVE_PC_FDC
+ def_bool y
+
+-config DMI
+- def_bool y
+-
+ config RWSEM_GENERIC_SPINLOCK
+ def_bool !X86_XADD
+
+@@ -116,8 +123,14 @@ config GENERIC_TIME_VSYSCALL
+ config ARCH_HAS_CPU_RELAX
def_bool y
++config ARCH_HAS_CACHE_LINE_SIZE
++ def_bool y
++
config HAVE_SETUP_PER_CPU_AREA
- def_bool X86_64
+ def_bool X86_64 || (X86_SMP && !X86_VOYAGER)
@@ -232770,7 +291013,7 @@
config ARCH_HIBERNATION_POSSIBLE
def_bool y
-@@ -141,6 +142,9 @@ config AUDIT_ARCH
+@@ -141,6 +154,9 @@ config AUDIT_ARCH
config ARCH_SUPPORTS_AOUT
def_bool y
@@ -232780,7 +291023,7 @@
# Use the generic interrupt handling code in kernel/irq/:
config GENERIC_HARDIRQS
bool
-@@ -171,7 +175,7 @@ config X86_64_SMP
+@@ -171,17 +187,17 @@ config X86_64_SMP
config X86_HT
bool
depends on SMP
@@ -232789,7 +291032,10 @@
default y
config X86_BIOS_REBOOT
-@@ -181,7 +185,7 @@ config X86_BIOS_REBOOT
+ bool
+- depends on X86_32 && !(X86_VISWS || X86_VOYAGER)
++ depends on !X86_VISWS && !X86_VOYAGER
+ default y
config X86_TRAMPOLINE
bool
@@ -232798,7 +291044,7 @@
default y
config KTIME_SCALAR
-@@ -241,8 +245,7 @@ config X86_ELAN
+@@ -241,8 +257,7 @@ config X86_ELAN
config X86_VOYAGER
bool "Voyager (NCR)"
@@ -232808,7 +291054,7 @@
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
+@@ -254,9 +269,8 @@ config X86_VOYAGER
config X86_NUMAQ
bool "NUMAQ (IBM/Sequent)"
@@ -232819,7 +291065,7 @@
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
+@@ -327,8 +341,9 @@ config X86_RDC321X
config X86_VSMP
bool "Support for ScaleMP vSMP"
@@ -232831,7 +291077,33 @@
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
+@@ -370,6 +385,25 @@ config VMI
+ at the moment), by linking the kernel to a GPL-ed ROM module
+ provided by the hypervisor.
+
++config KVM_CLOCK
++ bool "KVM paravirtualized clock"
++ select PARAVIRT
++ depends on !(X86_VISWS || X86_VOYAGER)
++ help
++ Turning on this option will allow you to run a paravirtualized clock
++ when running over the KVM hypervisor. Instead of relying on a PIT
++ (or probably other) emulation by the underlying device model, the host
++ provides the guest with timing infrastructure such as time of day, and
++ system time
++
++config KVM_GUEST
++ bool "KVM Guest support"
++ select PARAVIRT
++ depends on !(X86_VISWS || X86_VOYAGER)
++ help
++ This option enables various optimizations for running under the KVM
++ hypervisor.
++
+ source "arch/x86/lguest/Kconfig"
+
+ config PARAVIRT
+@@ -383,6 +417,35 @@ config PARAVIRT
endif
@@ -232867,7 +291139,42 @@
config ACPI_SRAT
def_bool y
depends on X86_32 && ACPI && NUMA && (X86_SUMMIT || X86_GENERICARCH)
-@@ -507,7 +539,7 @@ config NR_CPUS
+@@ -431,6 +494,15 @@ config HPET_EMULATE_RTC
+
+ # Mark as embedded because too many people got it wrong.
+ # The code disables itself when not needed.
++config DMI
++ default y
++ bool "Enable DMI scanning" if EMBEDDED
++ help
++ Enabled scanning of DMI to identify machine quirks. Say Y
++ here unless you have verified that your setup is not
++ affected by entries in the DMI blacklist. Required by PNP
++ BIOS code.
++
+ config GART_IOMMU
+ bool "GART IOMMU support" if EMBEDDED
+ default y
+@@ -477,9 +549,6 @@ config CALGARY_IOMMU_ENABLED_BY_DEFAULT
+ Calgary anyway, pass 'iommu=calgary' on the kernel command line.
+ If unsure, say Y.
+
+-config IOMMU_HELPER
+- def_bool (CALGARY_IOMMU || GART_IOMMU)
+-
+ # need this always selected by IOMMU for the VIA workaround
+ config SWIOTLB
+ bool
+@@ -490,6 +559,8 @@ config SWIOTLB
+ access 32-bits of memory can be used on systems with more than
+ 3 GB of memory. If unsure, say Y.
+
++config IOMMU_HELPER
++ def_bool (CALGARY_IOMMU || GART_IOMMU || SWIOTLB)
+
+ config NR_CPUS
+ int "Maximum number of CPUs (2-255)"
+@@ -507,7 +578,7 @@ config NR_CPUS
config SCHED_SMT
bool "SMT (Hyperthreading) scheduler support"
@@ -232876,7 +291183,7 @@
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
+@@ -517,7 +588,7 @@ config SCHED_SMT
config SCHED_MC
def_bool y
prompt "Multi-core scheduler support"
@@ -232885,7 +291192,7 @@
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
+@@ -877,6 +948,15 @@ config X86_64_ACPI_NUMA
help
Enable ACPI SRAT based node topology detection.
@@ -232901,7 +291208,7 @@
config NUMA_EMU
bool "NUMA emulation"
depends on X86_64 && NUMA
-@@ -886,7 +927,7 @@ config NUMA_EMU
+@@ -886,7 +966,7 @@ config NUMA_EMU
number of nodes. This is only useful for debugging.
config NODES_SHIFT
@@ -232910,7 +291217,7 @@
range 1 15 if X86_64
default "6" if X86_64
default "4" if X86_NUMAQ
-@@ -1010,6 +1051,21 @@ config MTRR
+@@ -1010,6 +1090,21 @@ config MTRR
See <file:Documentation/mtrr.txt> for more information.
@@ -232932,15 +291239,15 @@
config EFI
def_bool n
prompt "EFI runtime service support"
-@@ -1078,6 +1134,7 @@ source kernel/Kconfig.hz
+@@ -1078,6 +1173,7 @@ source kernel/Kconfig.hz
config KEXEC
bool "kexec system call"
-+ depends on X86_64 || X86_BIOS_REBOOT
++ depends on 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
+@@ -1379,7 +1475,7 @@ endmenu
menu "Bus options (PCI etc.)"
config PCI
@@ -232949,8 +291256,52 @@
depends on !X86_VOYAGER
default y
select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC)
+@@ -1420,6 +1516,10 @@ config PCI_GODIRECT
+ config PCI_GOANY
+ bool "Any"
+
++config PCI_GOOLPC
++ bool "OLPC"
++ depends on OLPC
++
+ endchoice
+
+ config PCI_BIOS
+@@ -1429,12 +1529,17 @@ config PCI_BIOS
+ # x86-64 doesn't support PCI BIOS access from long mode so always go direct.
+ config PCI_DIRECT
+ def_bool y
+- depends on PCI && (X86_64 || (PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
++ depends on PCI && (X86_64 || (PCI_GODIRECT || PCI_GOANY || PCI_GOOLPC) || X86_VISWS)
+
+ config PCI_MMCONFIG
+ def_bool y
+ depends on X86_32 && PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
+
++config PCI_OLPC
++ bool
++ depends on PCI && PCI_GOOLPC
++ default y
++
+ config PCI_DOMAINS
+ def_bool y
+ depends on PCI
+@@ -1554,6 +1659,13 @@ config GEODE_MFGPT_TIMER
+ MFGPTs have a better resolution and max interval than the
+ generic PIT, and are suitable for use as high-res timers.
+
++config OLPC
++ bool "One Laptop Per Child support"
++ default n
++ help
++ Add support for detecting the unique features of the OLPC
++ XO hardware.
++
+ endif # X86_32
+
+ config K8_NB
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
-index 9304bfb..4da3cdb 100644
+index 9304bfb..2ad6301 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -21,8 +21,8 @@ config M386
@@ -232964,7 +291315,19 @@
- "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
+@@ -292,6 +292,11 @@ config X86_GENERIC
+
+ endif
+
++config X86_CPU
++ def_bool y
++ select GENERIC_FIND_FIRST_BIT
++ select GENERIC_FIND_NEXT_BIT
++
+ #
+ # Define implied options from the CPU selection here
+ config X86_L1_CACHE_BYTES
+@@ -388,7 +393,7 @@ config X86_OOSTORE
#
config X86_P6_NOP
def_bool y
@@ -232973,8 +291336,17 @@
config X86_TSC
def_bool y
+@@ -398,7 +403,7 @@ config X86_TSC
+ # generates cmov.
+ config X86_CMOV
+ def_bool y
+- depends on (MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7)
++ depends on (MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || X86_64)
+
+ config X86_MINIMUM_CPU_FAMILY
+ int
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
-index 702eb39..5b1979a 100644
+index 702eb39..ac1e31b 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -5,6 +5,17 @@ config TRACE_IRQFLAGS_SUPPORT
@@ -233033,24 +291405,21 @@
config DEBUG_RODATA_TEST
bool "Testcase for the DEBUG_RODATA feature"
depends on DEBUG_RODATA
-@@ -82,8 +117,8 @@ config DEBUG_NX_TEST
+@@ -82,7 +117,6 @@ 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
+@@ -221,4 +255,18 @@ config CPA_DEBUG
+ help
Do change_page_attr() self-tests every 30 seconds.
- endmenu
-+
+config OPTIMIZE_INLINING
+ bool "Allow gcc to uninline functions marked 'inline'"
-+ default y
++ depends on BROKEN
+ 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
@@ -233060,6 +291429,9 @@
+ 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.
++
+ endmenu
++
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index f1e739a..3cff3c8 100644
--- a/arch/x86/Makefile
@@ -233809,7 +292181,7 @@
static int has_fpu(void)
diff --git a/arch/x86/boot/edd.c b/arch/x86/boot/edd.c
-index 8721dc4..d84a48e 100644
+index 8721dc4..03399d6 100644
--- a/arch/x86/boot/edd.c
+++ b/arch/x86/boot/edd.c
@@ -9,8 +9,6 @@
@@ -233821,8 +292193,35 @@
* Get EDD BIOS disk information
*/
+@@ -128,17 +126,25 @@ void query_edd(void)
+ {
+ char eddarg[8];
+ int do_mbr = 1;
++#ifdef CONFIG_EDD_OFF
++ int do_edd = 0;
++#else
+ int do_edd = 1;
++#endif
+ int be_quiet;
+ int devno;
+ struct edd_info ei, *edp;
+ u32 *mbrptr;
+
+ if (cmdline_find_option("edd", eddarg, sizeof eddarg) > 0) {
+- if (!strcmp(eddarg, "skipmbr") || !strcmp(eddarg, "skip"))
++ if (!strcmp(eddarg, "skipmbr") || !strcmp(eddarg, "skip")) {
++ do_edd = 1;
+ do_mbr = 0;
++ }
+ else if (!strcmp(eddarg, "off"))
+ do_edd = 0;
++ else if (!strcmp(eddarg, "on"))
++ do_edd = 1;
+ }
+
+ be_quiet = cmdline_find_option_bool("quiet");
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
-index 64ad901..6d2df8d 100644
+index 64ad901..af86e43 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -22,6 +22,7 @@
@@ -233838,17 +292237,21 @@
.ascii "HdrS" # header signature
- .word 0x0207 # header version number (>= 0x0105)
-+ .word 0x0208 # header version number (>= 0x0105)
++ .word 0x0209 # 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
+@@ -223,6 +224,13 @@ 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
+
++setup_data: .quad 0 # 64-bit physical pointer to
++ # single linked list of
++ # struct setup_data
++
# End of setup header #####################################################
.section ".inittext", "ax"
@@ -234690,9 +293093,18 @@
ret
-
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
-index 5e7771a..bbed3a2 100644
+index 5e7771a..cb3856a 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
+@@ -128,7 +128,7 @@ asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
+
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+- set_thread_flag(TIF_RESTORE_SIGMASK);
++ set_restore_sigmask();
+ return -ERESTARTNOHAND;
+ }
+
@@ -468,7 +468,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
restorer = ka->sa.sa_restorer;
} else {
@@ -234860,7 +293272,7 @@
return error;
}
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
-index 4eb5ce8..90e092d 100644
+index 4eb5ce8..bbdacb3 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -2,8 +2,7 @@
@@ -234897,7 +293309,15 @@
obj-y += i387.o
obj-y += ptrace.o
obj-y += ds.o
-@@ -47,11 +48,12 @@ obj-$(CONFIG_MICROCODE) += microcode.o
+@@ -39,7 +40,6 @@ obj-$(CONFIG_STACKTRACE) += stacktrace.o
+ obj-y += cpu/
+ obj-y += acpi/
+ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o
+-obj-$(CONFIG_X86_64) += reboot.o
+ obj-$(CONFIG_MCA) += mca_32.o
+ obj-$(CONFIG_X86_MSR) += msr.o
+ obj-$(CONFIG_X86_CPUID) += cpuid.o
+@@ -47,11 +47,12 @@ obj-$(CONFIG_MICROCODE) += microcode.o
obj-$(CONFIG_PCI) += early-quirks.o
apm-y := apm_32.o
obj-$(CONFIG_APM) += apm.o
@@ -234914,7 +293334,7 @@
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
+@@ -60,12 +61,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
@@ -234929,7 +293349,21 @@
obj-$(CONFIG_VM86) += vm86_32.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
-@@ -89,7 +92,7 @@ scx200-y += scx200_32.o
+@@ -77,6 +79,8 @@ obj-$(CONFIG_DEBUG_RODATA_TEST) += test_rodata.o
+ obj-$(CONFIG_DEBUG_NX_TEST) += test_nx.o
+
+ obj-$(CONFIG_VMI) += vmi_32.o vmiclock_32.o
++obj-$(CONFIG_KVM_GUEST) += kvm.o
++obj-$(CONFIG_KVM_CLOCK) += kvmclock.o
+ obj-$(CONFIG_PARAVIRT) += paravirt.o paravirt_patch_$(BITS).o
+
+ ifdef CONFIG_INPUT_PCSPKR
+@@ -86,14 +90,18 @@ endif
+ obj-$(CONFIG_SCx200) += scx200.o
+ scx200-y += scx200_32.o
+
++obj-$(CONFIG_OLPC) += olpc.o
++
###
# 64 bit specific files
ifeq ($(CONFIG_X86_64),y)
@@ -234938,6 +293372,12 @@
obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o
obj-$(CONFIG_AUDIT) += audit_64.o
+ obj-$(CONFIG_GART_IOMMU) += pci-gart_64.o aperture_64.o
+ obj-$(CONFIG_CALGARY_IOMMU) += pci-calgary_64.o tce_64.o
+ obj-$(CONFIG_SWIOTLB) += pci-swiotlb_64.o
++
++ obj-$(CONFIG_PCI_MMCONFIG) += mmconf-fam10h_64.o
+ endif
diff --git a/arch/x86/kernel/acpi/Makefile b/arch/x86/kernel/acpi/Makefile
index 19d3d6e..7335959 100644
--- a/arch/x86/kernel/acpi/Makefile
@@ -234959,7 +293399,7 @@
+ $(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
+index 2cdc9de..c49ebcc 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -39,6 +39,11 @@
@@ -235069,7 +293509,7 @@
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)
+@@ -732,6 +761,42 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
* Parse LAPIC entries in MADT
* returns 0 on success, < 0 on error
*/
@@ -235083,10 +293523,36 @@
+ boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
+}
+
++static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
++{
++ int count;
++
++ if (!cpu_has_apic)
++ return -ENODEV;
++
++ /*
++ * Note that the LAPIC address is obtained from the MADT (32-bit value)
++ * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
++ */
++
++ count =
++ acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
++ acpi_parse_lapic_addr_ovr, 0);
++ if (count < 0) {
++ printk(KERN_ERR PREFIX
++ "Error parsing LAPIC address override entry\n");
++ return count;
++ }
++
++ acpi_register_lapic_address(acpi_lapic_addr);
++
++ return count;
++}
++
static int __init acpi_parse_madt_lapic_entries(void)
{
int count;
-@@ -753,10 +792,14 @@ static int __init acpi_parse_madt_lapic_entries(void)
+@@ -753,10 +818,14 @@ static int __init acpi_parse_madt_lapic_entries(void)
return count;
}
@@ -235104,6 +293570,64 @@
if (!count) {
printk(KERN_ERR PREFIX "No LAPIC entries present\n");
/* TBD: Cleanup to allow fallback to MPS */
+@@ -858,6 +927,33 @@ static inline int acpi_parse_madt_ioapic_entries(void)
+ }
+ #endif /* !CONFIG_X86_IO_APIC */
+
++static void __init early_acpi_process_madt(void)
++{
++#ifdef CONFIG_X86_LOCAL_APIC
++ int error;
++
++ if (!acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) {
++
++ /*
++ * Parse MADT LAPIC entries
++ */
++ error = early_acpi_parse_madt_lapic_addr_ovr();
++ if (!error) {
++ acpi_lapic = 1;
++ smp_found_config = 1;
++ }
++ if (error == -EINVAL) {
++ /*
++ * Dell Precision Workstation 410, 610 come here.
++ */
++ printk(KERN_ERR PREFIX
++ "Invalid BIOS MADT, disabling ACPI\n");
++ disable_acpi();
++ }
++ }
++#endif
++}
++
+ static void __init acpi_process_madt(void)
+ {
+ #ifdef CONFIG_X86_LOCAL_APIC
+@@ -1190,6 +1286,23 @@ int __init acpi_boot_table_init(void)
+ return 0;
+ }
+
++int __init early_acpi_boot_init(void)
++{
++ /*
++ * If acpi_disabled, bail out
++ * One exception: acpi=ht continues far enough to enumerate LAPICs
++ */
++ if (acpi_disabled && !acpi_ht)
++ return 1;
++
++ /*
++ * Process the Multiple APIC Description Table (MADT), if present
++ */
++ early_acpi_process_madt();
++
++ return 0;
++}
++
+ int __init acpi_boot_init(void)
+ {
+ /*
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
@@ -237253,10 +295777,65 @@
+ */
+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
+index d4438ef..bf9290e 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[] = {
+@@ -904,6 +904,7 @@ recalc:
+ original_pm_idle();
+ else
+ default_idle();
++ local_irq_disable();
+ jiffies_since_last_check = jiffies - last_jiffies;
+ if (jiffies_since_last_check > idle_period)
+ goto recalc;
+@@ -911,6 +912,8 @@ recalc:
+
+ if (apm_idle_done)
+ apm_do_busy();
++
++ local_irq_enable();
+ }
+
+ /**
+@@ -1189,19 +1192,6 @@ static int suspend(int vetoable)
+ int err;
+ struct apm_user *as;
+
+- if (pm_send_all(PM_SUSPEND, (void *)3)) {
+- /* Vetoed */
+- if (vetoable) {
+- if (apm_info.connection_version > 0x100)
+- set_system_power_state(APM_STATE_REJECT);
+- err = -EBUSY;
+- ignore_sys_suspend = 0;
+- printk(KERN_WARNING "apm: suspend was vetoed.\n");
+- goto out;
+- }
+- printk(KERN_CRIT "apm: suspend was vetoed, but suspending anyway.\n");
+- }
+-
+ device_suspend(PMSG_SUSPEND);
+ local_irq_disable();
+ device_power_down(PMSG_SUSPEND);
+@@ -1224,9 +1214,7 @@ static int suspend(int vetoable)
+ device_power_up();
+ local_irq_enable();
+ device_resume();
+- pm_send_all(PM_RESUME, (void *)0);
+ queue_event(APM_NORMAL_RESUME, NULL);
+- out:
+ spin_lock(&user_list_lock);
+ for (as = user_list; as != NULL; as = as->next) {
+ as->suspend_wait = 0;
+@@ -1337,7 +1325,6 @@ static void check_events(void)
+ if ((event != APM_NORMAL_RESUME)
+ || (ignore_normal_resume == 0)) {
+ device_resume();
+- pm_send_all(PM_RESUME, (void *)0);
+ queue_event(event, NULL);
+ }
+ ignore_normal_resume = 0;
+@@ -2217,7 +2204,6 @@ static struct dmi_system_id __initdata apm_dmi_table[] = {
*/
static int __init apm_init(void)
{
@@ -237264,7 +295843,7 @@
struct desc_struct *gdt;
int err;
-@@ -2322,9 +2321,7 @@ static int __init apm_init(void)
+@@ -2322,9 +2308,7 @@ static int __init apm_init(void)
set_base(gdt[APM_DS >> 3],
__va((unsigned long)apm_info.bios.dseg << 4));
@@ -237276,18 +295855,62 @@
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
+index 8ea0401..9258808 100644
--- a/arch/x86/kernel/asm-offsets_32.c
+++ b/arch/x86/kernel/asm-offsets_32.c
-@@ -10,7 +10,7 @@
+@@ -9,8 +9,9 @@
+ #include <linux/signal.h>
#include <linux/personality.h>
#include <linux/suspend.h>
++#include <linux/kbuild.h>
#include <asm/ucontext.h>
-#include "sigframe_32.h"
+#include "sigframe.h"
#include <asm/pgtable.h>
#include <asm/fixmap.h>
#include <asm/processor.h>
+@@ -23,14 +24,6 @@
+ #include <linux/lguest.h>
+ #include "../../../drivers/lguest/lg.h"
+
+-#define DEFINE(sym, val) \
+- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+-
+-#define BLANK() asm volatile("\n->" : : )
+-
+-#define OFFSET(sym, str, mem) \
+- DEFINE(sym, offsetof(struct str, mem));
+-
+ /* workaround for a warning with -Wmissing-prototypes */
+ void foo(void);
+
+diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c
+index 494e1e0..f126c05 100644
+--- a/arch/x86/kernel/asm-offsets_64.c
++++ b/arch/x86/kernel/asm-offsets_64.c
+@@ -10,6 +10,7 @@
+ #include <linux/errno.h>
+ #include <linux/hardirq.h>
+ #include <linux/suspend.h>
++#include <linux/kbuild.h>
+ #include <asm/pda.h>
+ #include <asm/processor.h>
+ #include <asm/segment.h>
+@@ -17,14 +18,6 @@
+ #include <asm/ia32.h>
+ #include <asm/bootparam.h>
+
+-#define DEFINE(sym, val) \
+- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+-
+-#define BLANK() asm volatile("\n->" : : )
+-
+-#define OFFSET(sym, str, mem) \
+- DEFINE(sym, offsetof(struct str, mem))
+-
+ #define __NO_STUBS 1
+ #undef __SYSCALL
+ #undef _ASM_X86_64_UNISTD_H_
diff --git a/arch/x86/kernel/bugs_64.c b/arch/x86/kernel/bugs_64.c
index 8f520f9..9a3ed06 100644
--- a/arch/x86/kernel/bugs_64.c
@@ -238792,7 +297415,7 @@
-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
+index a962dcb..b0c8208 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)
@@ -238871,12 +297494,29 @@
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)
+@@ -339,6 +339,7 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
+ {
+ struct acpi_cpufreq_data *data = per_cpu(drv_data, cpu);
+ unsigned int freq;
++ unsigned int cached_freq;
+
+ dprintk("get_cur_freq_on_cpu (%d)\n", cpu);
+
+@@ -347,13 +348,22 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
return 0;
}
- freq = extract_freq(get_cur_val(cpumask_of_cpu(cpu)), data);
++ cached_freq = data->freq_table[data->acpi_data->state].frequency;
+ freq = extract_freq(get_cur_val(&cpumask_of_cpu(cpu)), data);
++ if (freq != cached_freq) {
++ /*
++ * The dreaded BIOS frequency change behind our back.
++ * Force set the frequency on next target call.
++ */
++ data->resume = 1;
++ }
++
dprintk("cur freq = %u\n", freq);
return freq;
@@ -238887,7 +297527,7 @@
struct acpi_cpufreq_data *data)
{
unsigned int cur_freq;
-@@ -449,7 +449,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
+@@ -449,7 +459,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
drv_write(&cmd);
if (acpi_pstate_strict) {
@@ -238896,6 +297536,14 @@
dprintk("acpi_cpufreq_target failed (%d)\n",
policy->cpu);
return -EAGAIN;
+@@ -591,6 +601,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
+ policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
+ policy->cpus = perf->shared_cpu_map;
+ }
++ policy->related_cpus = perf->shared_cpu_map;
+
+ #ifdef CONFIG_SMP
+ dmi_check_system(sw_any_bug_dmi_table);
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
@@ -240483,7 +299131,7 @@
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
+index 3e18db4..5d241ce 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -11,6 +11,7 @@
@@ -240552,7 +299200,7 @@
+ * Look of multiple ranges matching this address and pick type
+ * as per MTRR precedence
+ */
-+ if (!mtrr_state.enabled & 2) {
++ if (!(mtrr_state.enabled & 2)) {
+ return mtrr_state.def_type;
+ }
+
@@ -240682,7 +299330,7 @@
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
+index 91e150a..84c480b 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)
@@ -240691,7 +299339,7 @@
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);
++ proc_create("mtrr", S_IWUSR | S_IRUGO, NULL, &mtrr_fops);
+
+ if (proc_root_mtrr)
proc_root_mtrr->owner = THIS_MODULE;
@@ -241224,12 +299872,14 @@
return err ? NOTIFY_BAD : NOTIFY_OK;
}
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
-index 9a5fa0a..2251d0a 100644
+index 9a5fa0a..2685538 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
-@@ -26,11 +26,7 @@
+@@ -25,12 +25,9 @@
+ #include <asm/hpet.h>
#include <linux/kdebug.h>
#include <asm/smp.h>
++#include <asm/reboot.h>
-#ifdef CONFIG_X86_32
#include <mach_ipi.h>
@@ -241239,6 +299889,15 @@
/* This keeps a track of which one is crashing cpu. */
static int crashing_cpu;
+@@ -121,7 +118,7 @@ static void nmi_shootdown_cpus(void)
+ }
+ #endif
+
+-void machine_crash_shutdown(struct pt_regs *regs)
++void native_machine_crash_shutdown(struct pt_regs *regs)
+ {
+ /* This function is only called after the system
+ * has panicked or is otherwise in a critical state.
diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c
index dcd918c..11c11b8 100644
--- a/arch/x86/kernel/ds.c
@@ -241327,7 +299986,7 @@
#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
+index 9be6971..124480c 100644
--- a/arch/x86/kernel/e820_64.c
+++ b/arch/x86/kernel/e820_64.c
@@ -27,6 +27,7 @@
@@ -241364,7 +300023,50 @@
#endif
{}
};
-@@ -95,7 +96,8 @@ void __init early_res_to_bootmem(void)
+@@ -83,19 +84,47 @@ void __init reserve_early(unsigned long start, unsigned long end, char *name)
+ strncpy(r->name, name, sizeof(r->name) - 1);
+ }
+
+-void __init early_res_to_bootmem(void)
++void __init free_early(unsigned long start, unsigned long end)
++{
++ struct early_res *r;
++ int i, j;
++
++ for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
++ r = &early_res[i];
++ if (start == r->start && end == r->end)
++ break;
++ }
++ if (i >= MAX_EARLY_RES || !early_res[i].end)
++ panic("free_early on not reserved area: %lx-%lx!", start, end);
++
++ for (j = i + 1; j < MAX_EARLY_RES && early_res[j].end; j++)
++ ;
++
++ memmove(&early_res[i], &early_res[i + 1],
++ (j - 1 - i) * sizeof(struct early_res));
++
++ early_res[j - 1].end = 0;
++}
++
++void __init early_res_to_bootmem(unsigned long start, unsigned long end)
+ {
+ int i;
++ unsigned long final_start, final_end;
+ for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
+ struct early_res *r = &early_res[i];
+- printk(KERN_INFO "early res: %d [%lx-%lx] %s\n", i,
+- r->start, r->end - 1, r->name);
+- reserve_bootmem_generic(r->start, r->end - r->start);
++ final_start = max(start, r->start);
++ final_end = min(end, r->end);
++ if (final_start >= final_end)
++ continue;
++ printk(KERN_INFO " early res: %d [%lx-%lx] %s\n", i,
++ final_start, final_end - 1, r->name);
++ reserve_bootmem_generic(final_start, final_end - final_start);
+ }
}
/* Check for already reserved areas */
@@ -241374,7 +300076,7 @@
{
int i;
unsigned long addr = *addrp, last;
-@@ -105,7 +107,7 @@ again:
+@@ -105,7 +134,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) {
@@ -241383,7 +300085,7 @@
changed = 1;
goto again;
}
-@@ -113,6 +115,40 @@ again:
+@@ -113,6 +142,40 @@ again:
return changed;
}
@@ -241424,7 +300126,7 @@
/*
* This function checks if any part of the range <start,end> is mapped
* with type.
-@@ -174,26 +210,27 @@ int __init e820_all_mapped(unsigned long start, unsigned long end,
+@@ -174,26 +237,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,
@@ -241460,7 +300162,7 @@
continue;
if (last > end)
continue;
-@@ -203,6 +240,40 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end,
+@@ -203,6 +267,40 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end,
}
/*
@@ -241501,7 +300203,7 @@
* 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)
+@@ -211,29 +309,29 @@ unsigned long __init e820_end_of_ram(void)
end_pfn = find_max_pfn_with_active_regions();
@@ -241542,7 +300244,7 @@
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,
+@@ -243,21 +341,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;
@@ -241566,7 +300268,7 @@
}
}
-@@ -309,9 +367,9 @@ static int __init e820_find_active_region(const struct e820entry *ei,
+@@ -309,9 +394,9 @@ static int __init e820_find_active_region(const struct e820entry *ei,
if (*ei_startpfn >= *ei_endpfn)
return 0;
@@ -241579,7 +300281,7 @@
/* 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)
+@@ -634,10 +719,10 @@ static int __init copy_e820_map(struct e820entry *biosmap, int nr_map)
return -1;
do {
@@ -241594,7 +300296,7 @@
/* Overflow in 64 bits? Ignore the memory map. */
if (start > end)
-@@ -702,7 +760,7 @@ static int __init parse_memmap_opt(char *p)
+@@ -702,7 +787,7 @@ static int __init parse_memmap_opt(char *p)
saved_max_pfn = e820_end_of_ram();
remove_all_active_ranges();
#endif
@@ -241970,7 +300672,7 @@
/*
diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c
-index 4ae7b64..021624c 100644
+index 4ae7b64..cbaaf69 100644
--- a/arch/x86/kernel/genapic_64.c
+++ b/arch/x86/kernel/genapic_64.c
@@ -15,6 +15,7 @@
@@ -242039,7 +300741,7 @@
+{
+ unsigned int id;
+
-+ WARN_ON(preemptible());
++ WARN_ON(preemptible() && num_online_cpus() > 1);
+ id = apic_read(APIC_ID);
+ if (uv_system_type >= UV_X2APIC)
+ id |= __get_cpu_var(x2apic_extra_bits);
@@ -242359,10 +301061,18 @@
+ start_kernel();
+}
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
-index ad24408..d31d6b7 100644
+index ad24408..e25c57b 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
-@@ -22,6 +22,7 @@
+@@ -11,6 +11,7 @@
+ #include <linux/string.h>
+ #include <linux/percpu.h>
+ #include <linux/start_kernel.h>
++#include <linux/io.h>
+
+ #include <asm/processor.h>
+ #include <asm/proto.h>
+@@ -22,6 +23,7 @@
#include <asm/sections.h>
#include <asm/kdebug.h>
#include <asm/e820.h>
@@ -242370,7 +301080,7 @@
static void __init zap_identity_mappings(void)
{
-@@ -49,39 +50,73 @@ static void __init copy_bootdata(char *real_mode_data)
+@@ -49,39 +51,91 @@ static void __init copy_bootdata(char *real_mode_data)
}
}
@@ -242416,13 +301126,18 @@
- 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;
+- ebda_size = *(unsigned short *)__va(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;
+
- /* Round EBDA up to pages */
- if (ebda_size == 0)
- ebda_size = 1;
@@ -242430,18 +301145,31 @@
- 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_early(ebda_addr, ebda_addr + ebda_size, "EBDA");
+ /* reserve all memory between lowmem and the 1MB mark */
+ reserve_early(lowmem, 0x100000, "BIOS reserved");
++}
++
++static void __init reserve_setup_data(void)
++{
++ struct setup_data *data;
++ unsigned long pa_data;
++ char buf[32];
++
++ if (boot_params.hdr.version < 0x0209)
++ return;
++ pa_data = boot_params.hdr.setup_data;
++ while (pa_data) {
++ data = early_ioremap(pa_data, sizeof(*data));
++ sprintf(buf, "setup data %x", data->type);
++ reserve_early(pa_data, pa_data+sizeof(*data)+data->len, buf);
++ pa_data = data->next;
++ early_iounmap(data, sizeof(*data));
++ }
}
void __init x86_64_start_kernel(char * real_mode_data)
@@ -242464,7 +301192,7 @@
/* 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)
+@@ -91,7 +145,7 @@ void __init x86_64_start_kernel(char * real_mode_data)
/* Cleanup the over mapped high alias */
cleanup_highmap();
@@ -242473,7 +301201,7 @@
#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)
+@@ -110,6 +164,7 @@ void __init x86_64_start_kernel(char * real_mode_data)
reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS");
@@ -242481,7 +301209,7 @@
/* 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)
+@@ -117,8 +172,10 @@ 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");
}
@@ -242489,11 +301217,12 @@
- reserve_ebda();
+ reserve_ebda_region();
++ reserve_setup_data();
/*
* 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
+index 74d87ea..b2cc737 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -1,5 +1,4 @@
@@ -242511,6 +301240,32 @@
/*
* We depend on ET to be correct. This checks for 287/387.
+@@ -657,15 +656,16 @@ int_msg:
+ .asciz "Unknown interrupt or fault at EIP %p %p %p\n"
+
+ fault_msg:
+- .asciz \
+-/* fault info: */ "BUG: Int %d: CR2 %p\n" \
+-/* pusha regs: */ " EDI %p ESI %p EBP %p ESP %p\n" \
+- " EBX %p EDX %p ECX %p EAX %p\n" \
+-/* fault frame: */ " err %p EIP %p CS %p flg %p\n" \
+- \
+- "Stack: %p %p %p %p %p %p %p %p\n" \
+- " %p %p %p %p %p %p %p %p\n" \
+- " %p %p %p %p %p %p %p %p\n"
++/* fault info: */
++ .ascii "BUG: Int %d: CR2 %p\n"
++/* pusha regs: */
++ .ascii " EDI %p ESI %p EBP %p ESP %p\n"
++ .ascii " EBX %p EDX %p ECX %p EAX %p\n"
++/* fault frame: */
++ .ascii " err %p EIP %p CS %p flg %p\n"
++ .ascii "Stack: %p %p %p %p %p %p %p %p\n"
++ .ascii " %p %p %p %p %p %p %p %p\n"
++ .asciz " %p %p %p %p %p %p %p %p\n"
+
+ #include "../../x86/xen/xen-head.S"
+
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
@@ -242579,10 +301334,23 @@
* too.)
*/
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
-index 36652ea..9007f9e 100644
+index 36652ea..9b5cfcd 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
-@@ -218,7 +218,7 @@ static void hpet_legacy_clockevent_register(void)
+@@ -137,9 +137,10 @@ static void hpet_reserve_platform_timers(unsigned long id)
+ hd.hd_irq[0] = HPET_LEGACY_8254;
+ hd.hd_irq[1] = HPET_LEGACY_RTC;
+
+- for (i = 2; i < nrtimers; timer++, i++)
+- hd.hd_irq[i] = (timer->hpet_config & Tn_INT_ROUTE_CNF_MASK) >>
++ for (i = 2; i < nrtimers; timer++, i++) {
++ hd.hd_irq[i] = (readl(&timer->hpet_config) & Tn_INT_ROUTE_CNF_MASK) >>
+ Tn_INT_ROUTE_CNF_SHIFT;
++ }
+
+ hpet_alloc(&hd);
+
+@@ -218,7 +219,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,
@@ -243074,7 +301842,7 @@
}
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
+index 4ca5486..a40d54f 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;
@@ -243411,7 +302179,15 @@
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)
+@@ -2477,6 +2444,7 @@ void destroy_irq(unsigned int irq)
+ dynamic_irq_cleanup(irq);
+
+ spin_lock_irqsave(&vector_lock, flags);
++ clear_bit(irq_vector[irq], used_vectors);
+ irq_vector[irq] = 0;
+ spin_unlock_irqrestore(&vector_lock, flags);
+ }
+@@ -2789,7 +2757,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;
@@ -243419,7 +302195,7 @@
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
+@@ -2830,9 +2797,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);
@@ -243816,7 +302592,7 @@
+}
+#endif
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
-index cef054b..00bda7b 100644
+index cef054b..147352d 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)
@@ -243837,6 +302613,215 @@
);
} else
#endif
+@@ -190,8 +190,6 @@ void irq_ctx_exit(int cpu)
+ hardirq_ctx[cpu] = NULL;
+ }
+
+-extern asmlinkage void __do_softirq(void);
+-
+ asmlinkage void do_softirq(void)
+ {
+ unsigned long flags;
+diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
+index 7335430..c032059 100644
+--- a/arch/x86/kernel/kdebugfs.c
++++ b/arch/x86/kernel/kdebugfs.c
+@@ -6,23 +6,171 @@
+ *
+ * This file is released under the GPLv2.
+ */
+-
+ #include <linux/debugfs.h>
++#include <linux/uaccess.h>
+ #include <linux/stat.h>
+ #include <linux/init.h>
++#include <linux/io.h>
++#include <linux/mm.h>
+
+ #include <asm/setup.h>
+
+ #ifdef CONFIG_DEBUG_BOOT_PARAMS
++struct setup_data_node {
++ u64 paddr;
++ u32 type;
++ u32 len;
++};
++
++static ssize_t
++setup_data_read(struct file *file, char __user *user_buf, size_t count,
++ loff_t *ppos)
++{
++ struct setup_data_node *node = file->private_data;
++ unsigned long remain;
++ loff_t pos = *ppos;
++ struct page *pg;
++ void *p;
++ u64 pa;
++
++ if (pos < 0)
++ return -EINVAL;
++ if (pos >= node->len)
++ return 0;
++
++ if (count > node->len - pos)
++ count = node->len - pos;
++ pa = node->paddr + sizeof(struct setup_data) + pos;
++ pg = pfn_to_page((pa + count - 1) >> PAGE_SHIFT);
++ if (PageHighMem(pg)) {
++ p = ioremap_cache(pa, count);
++ if (!p)
++ return -ENXIO;
++ } else {
++ p = __va(pa);
++ }
++
++ remain = copy_to_user(user_buf, p, count);
++
++ if (PageHighMem(pg))
++ iounmap(p);
++
++ if (remain)
++ return -EFAULT;
++
++ *ppos = pos + count;
++
++ return count;
++}
++
++static int setup_data_open(struct inode *inode, struct file *file)
++{
++ file->private_data = inode->i_private;
++ return 0;
++}
++
++static const struct file_operations fops_setup_data = {
++ .read = setup_data_read,
++ .open = setup_data_open,
++};
++
++static int __init
++create_setup_data_node(struct dentry *parent, int no,
++ struct setup_data_node *node)
++{
++ struct dentry *d, *type, *data;
++ char buf[16];
++ int error;
++
++ sprintf(buf, "%d", no);
++ d = debugfs_create_dir(buf, parent);
++ if (!d) {
++ error = -ENOMEM;
++ goto err_return;
++ }
++ type = debugfs_create_x32("type", S_IRUGO, d, &node->type);
++ if (!type) {
++ error = -ENOMEM;
++ goto err_dir;
++ }
++ data = debugfs_create_file("data", S_IRUGO, d, node, &fops_setup_data);
++ if (!data) {
++ error = -ENOMEM;
++ goto err_type;
++ }
++ return 0;
++
++err_type:
++ debugfs_remove(type);
++err_dir:
++ debugfs_remove(d);
++err_return:
++ return error;
++}
++
++static int __init create_setup_data_nodes(struct dentry *parent)
++{
++ struct setup_data_node *node;
++ struct setup_data *data;
++ int error, no = 0;
++ struct dentry *d;
++ struct page *pg;
++ u64 pa_data;
++
++ d = debugfs_create_dir("setup_data", parent);
++ if (!d) {
++ error = -ENOMEM;
++ goto err_return;
++ }
++
++ pa_data = boot_params.hdr.setup_data;
++
++ while (pa_data) {
++ node = kmalloc(sizeof(*node), GFP_KERNEL);
++ if (!node) {
++ error = -ENOMEM;
++ goto err_dir;
++ }
++ pg = pfn_to_page((pa_data+sizeof(*data)-1) >> PAGE_SHIFT);
++ if (PageHighMem(pg)) {
++ data = ioremap_cache(pa_data, sizeof(*data));
++ if (!data) {
++ error = -ENXIO;
++ goto err_dir;
++ }
++ } else {
++ data = __va(pa_data);
++ }
++
++ node->paddr = pa_data;
++ node->type = data->type;
++ node->len = data->len;
++ error = create_setup_data_node(d, no, node);
++ pa_data = data->next;
++
++ if (PageHighMem(pg))
++ iounmap(data);
++ if (error)
++ goto err_dir;
++ no++;
++ }
++ return 0;
++
++err_dir:
++ debugfs_remove(d);
++err_return:
++ return error;
++}
++
+ static struct debugfs_blob_wrapper boot_params_blob = {
+- .data = &boot_params,
+- .size = sizeof(boot_params),
++ .data = &boot_params,
++ .size = sizeof(boot_params),
+ };
+
+ static int __init boot_params_kdebugfs_init(void)
+ {
+- int error;
+ struct dentry *dbp, *version, *data;
++ int error;
+
+ dbp = debugfs_create_dir("boot_params", NULL);
+ if (!dbp) {
+@@ -41,7 +189,13 @@ static int __init boot_params_kdebugfs_init(void)
+ error = -ENOMEM;
+ goto err_version;
+ }
++ error = create_setup_data_nodes(dbp);
++ if (error)
++ goto err_data;
+ return 0;
++
++err_data:
++ debugfs_remove(data);
+ err_version:
+ debugfs_remove(version);
+ err_dir:
+@@ -61,5 +215,4 @@ static int __init arch_kdebugfs_init(void)
+
+ return error;
+ }
+-
+ arch_initcall(arch_kdebugfs_init);
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
new file mode 100644
index 0000000..f47f0eb
@@ -244459,6 +303444,453 @@
/* 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/kvm.c b/arch/x86/kernel/kvm.c
+new file mode 100644
+index 0000000..8b7a3cf
+--- /dev/null
++++ b/arch/x86/kernel/kvm.c
+@@ -0,0 +1,248 @@
++/*
++ * KVM paravirt_ops implementation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * Copyright (C) 2007, Red Hat, Inc., Ingo Molnar <mingo at redhat.com>
++ * Copyright IBM Corporation, 2007
++ * Authors: Anthony Liguori <aliguori at us.ibm.com>
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/kvm_para.h>
++#include <linux/cpu.h>
++#include <linux/mm.h>
++#include <linux/highmem.h>
++#include <linux/hardirq.h>
++
++#define MMU_QUEUE_SIZE 1024
++
++struct kvm_para_state {
++ u8 mmu_queue[MMU_QUEUE_SIZE];
++ int mmu_queue_len;
++ enum paravirt_lazy_mode mode;
++};
++
++static DEFINE_PER_CPU(struct kvm_para_state, para_state);
++
++static struct kvm_para_state *kvm_para_state(void)
++{
++ return &per_cpu(para_state, raw_smp_processor_id());
++}
++
++/*
++ * No need for any "IO delay" on KVM
++ */
++static void kvm_io_delay(void)
++{
++}
++
++static void kvm_mmu_op(void *buffer, unsigned len)
++{
++ int r;
++ unsigned long a1, a2;
++
++ do {
++ a1 = __pa(buffer);
++ a2 = 0; /* on i386 __pa() always returns <4G */
++ r = kvm_hypercall3(KVM_HC_MMU_OP, len, a1, a2);
++ buffer += r;
++ len -= r;
++ } while (len);
++}
++
++static void mmu_queue_flush(struct kvm_para_state *state)
++{
++ if (state->mmu_queue_len) {
++ kvm_mmu_op(state->mmu_queue, state->mmu_queue_len);
++ state->mmu_queue_len = 0;
++ }
++}
++
++static void kvm_deferred_mmu_op(void *buffer, int len)
++{
++ struct kvm_para_state *state = kvm_para_state();
++
++ if (state->mode != PARAVIRT_LAZY_MMU) {
++ kvm_mmu_op(buffer, len);
++ return;
++ }
++ if (state->mmu_queue_len + len > sizeof state->mmu_queue)
++ mmu_queue_flush(state);
++ memcpy(state->mmu_queue + state->mmu_queue_len, buffer, len);
++ state->mmu_queue_len += len;
++}
++
++static void kvm_mmu_write(void *dest, u64 val)
++{
++ __u64 pte_phys;
++ struct kvm_mmu_op_write_pte wpte;
++
++#ifdef CONFIG_HIGHPTE
++ struct page *page;
++ unsigned long dst = (unsigned long) dest;
++
++ page = kmap_atomic_to_page(dest);
++ pte_phys = page_to_pfn(page);
++ pte_phys <<= PAGE_SHIFT;
++ pte_phys += (dst & ~(PAGE_MASK));
++#else
++ pte_phys = (unsigned long)__pa(dest);
++#endif
++ wpte.header.op = KVM_MMU_OP_WRITE_PTE;
++ wpte.pte_val = val;
++ wpte.pte_phys = pte_phys;
++
++ kvm_deferred_mmu_op(&wpte, sizeof wpte);
++}
++
++/*
++ * We only need to hook operations that are MMU writes. We hook these so that
++ * we can use lazy MMU mode to batch these operations. We could probably
++ * improve the performance of the host code if we used some of the information
++ * here to simplify processing of batched writes.
++ */
++static void kvm_set_pte(pte_t *ptep, pte_t pte)
++{
++ kvm_mmu_write(ptep, pte_val(pte));
++}
++
++static void kvm_set_pte_at(struct mm_struct *mm, unsigned long addr,
++ pte_t *ptep, pte_t pte)
++{
++ kvm_mmu_write(ptep, pte_val(pte));
++}
++
++static void kvm_set_pmd(pmd_t *pmdp, pmd_t pmd)
++{
++ kvm_mmu_write(pmdp, pmd_val(pmd));
++}
++
++#if PAGETABLE_LEVELS >= 3
++#ifdef CONFIG_X86_PAE
++static void kvm_set_pte_atomic(pte_t *ptep, pte_t pte)
++{
++ kvm_mmu_write(ptep, pte_val(pte));
++}
++
++static void kvm_set_pte_present(struct mm_struct *mm, unsigned long addr,
++ pte_t *ptep, pte_t pte)
++{
++ kvm_mmu_write(ptep, pte_val(pte));
++}
++
++static void kvm_pte_clear(struct mm_struct *mm,
++ unsigned long addr, pte_t *ptep)
++{
++ kvm_mmu_write(ptep, 0);
++}
++
++static void kvm_pmd_clear(pmd_t *pmdp)
++{
++ kvm_mmu_write(pmdp, 0);
++}
++#endif
++
++static void kvm_set_pud(pud_t *pudp, pud_t pud)
++{
++ kvm_mmu_write(pudp, pud_val(pud));
++}
++
++#if PAGETABLE_LEVELS == 4
++static void kvm_set_pgd(pgd_t *pgdp, pgd_t pgd)
++{
++ kvm_mmu_write(pgdp, pgd_val(pgd));
++}
++#endif
++#endif /* PAGETABLE_LEVELS >= 3 */
++
++static void kvm_flush_tlb(void)
++{
++ struct kvm_mmu_op_flush_tlb ftlb = {
++ .header.op = KVM_MMU_OP_FLUSH_TLB,
++ };
++
++ kvm_deferred_mmu_op(&ftlb, sizeof ftlb);
++}
++
++static void kvm_release_pt(u32 pfn)
++{
++ struct kvm_mmu_op_release_pt rpt = {
++ .header.op = KVM_MMU_OP_RELEASE_PT,
++ .pt_phys = (u64)pfn << PAGE_SHIFT,
++ };
++
++ kvm_mmu_op(&rpt, sizeof rpt);
++}
++
++static void kvm_enter_lazy_mmu(void)
++{
++ struct kvm_para_state *state = kvm_para_state();
++
++ paravirt_enter_lazy_mmu();
++ state->mode = paravirt_get_lazy_mode();
++}
++
++static void kvm_leave_lazy_mmu(void)
++{
++ struct kvm_para_state *state = kvm_para_state();
++
++ mmu_queue_flush(state);
++ paravirt_leave_lazy(paravirt_get_lazy_mode());
++ state->mode = paravirt_get_lazy_mode();
++}
++
++static void paravirt_ops_setup(void)
++{
++ pv_info.name = "KVM";
++ pv_info.paravirt_enabled = 1;
++
++ if (kvm_para_has_feature(KVM_FEATURE_NOP_IO_DELAY))
++ pv_cpu_ops.io_delay = kvm_io_delay;
++
++ if (kvm_para_has_feature(KVM_FEATURE_MMU_OP)) {
++ pv_mmu_ops.set_pte = kvm_set_pte;
++ pv_mmu_ops.set_pte_at = kvm_set_pte_at;
++ pv_mmu_ops.set_pmd = kvm_set_pmd;
++#if PAGETABLE_LEVELS >= 3
++#ifdef CONFIG_X86_PAE
++ pv_mmu_ops.set_pte_atomic = kvm_set_pte_atomic;
++ pv_mmu_ops.set_pte_present = kvm_set_pte_present;
++ pv_mmu_ops.pte_clear = kvm_pte_clear;
++ pv_mmu_ops.pmd_clear = kvm_pmd_clear;
++#endif
++ pv_mmu_ops.set_pud = kvm_set_pud;
++#if PAGETABLE_LEVELS == 4
++ pv_mmu_ops.set_pgd = kvm_set_pgd;
++#endif
++#endif
++ pv_mmu_ops.flush_tlb_user = kvm_flush_tlb;
++ pv_mmu_ops.release_pte = kvm_release_pt;
++ pv_mmu_ops.release_pmd = kvm_release_pt;
++ pv_mmu_ops.release_pud = kvm_release_pt;
++
++ pv_mmu_ops.lazy_mode.enter = kvm_enter_lazy_mmu;
++ pv_mmu_ops.lazy_mode.leave = kvm_leave_lazy_mmu;
++ }
++}
++
++void __init kvm_guest_init(void)
++{
++ if (!kvm_para_available())
++ return;
++
++ paravirt_ops_setup();
++}
+diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
+new file mode 100644
+index 0000000..ddee040
+--- /dev/null
++++ b/arch/x86/kernel/kvmclock.c
+@@ -0,0 +1,187 @@
++/* KVM paravirtual clock driver. A clocksource implementation
++ Copyright (C) 2008 Glauber de Oliveira Costa, 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.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You 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
++*/
++
++#include <linux/clocksource.h>
++#include <linux/kvm_para.h>
++#include <asm/arch_hooks.h>
++#include <asm/msr.h>
++#include <asm/apic.h>
++#include <linux/percpu.h>
++#include <asm/reboot.h>
++
++#define KVM_SCALE 22
++
++static int kvmclock = 1;
++
++static int parse_no_kvmclock(char *arg)
++{
++ kvmclock = 0;
++ return 0;
++}
++early_param("no-kvmclock", parse_no_kvmclock);
++
++/* The hypervisor will put information about time periodically here */
++static DEFINE_PER_CPU_SHARED_ALIGNED(struct kvm_vcpu_time_info, hv_clock);
++#define get_clock(cpu, field) per_cpu(hv_clock, cpu).field
++
++static inline u64 kvm_get_delta(u64 last_tsc)
++{
++ int cpu = smp_processor_id();
++ u64 delta = native_read_tsc() - last_tsc;
++ return (delta * get_clock(cpu, tsc_to_system_mul)) >> KVM_SCALE;
++}
++
++static struct kvm_wall_clock wall_clock;
++static cycle_t kvm_clock_read(void);
++/*
++ * The wallclock is the time of day when we booted. Since then, some time may
++ * have elapsed since the hypervisor wrote the data. So we try to account for
++ * that with system time
++ */
++unsigned long kvm_get_wallclock(void)
++{
++ u32 wc_sec, wc_nsec;
++ u64 delta;
++ struct timespec ts;
++ int version, nsec;
++ int low, high;
++
++ low = (int)__pa(&wall_clock);
++ high = ((u64)__pa(&wall_clock) >> 32);
++
++ delta = kvm_clock_read();
++
++ native_write_msr(MSR_KVM_WALL_CLOCK, low, high);
++ do {
++ version = wall_clock.wc_version;
++ rmb();
++ wc_sec = wall_clock.wc_sec;
++ wc_nsec = wall_clock.wc_nsec;
++ rmb();
++ } while ((wall_clock.wc_version != version) || (version & 1));
++
++ delta = kvm_clock_read() - delta;
++ delta += wc_nsec;
++ nsec = do_div(delta, NSEC_PER_SEC);
++ set_normalized_timespec(&ts, wc_sec + delta, nsec);
++ /*
++ * Of all mechanisms of time adjustment I've tested, this one
++ * was the champion!
++ */
++ return ts.tv_sec + 1;
++}
++
++int kvm_set_wallclock(unsigned long now)
++{
++ return 0;
++}
++
++/*
++ * This is our read_clock function. The host puts an tsc timestamp each time
++ * it updates a new time. Without the tsc adjustment, we can have a situation
++ * in which a vcpu starts to run earlier (smaller system_time), but probes
++ * time later (compared to another vcpu), leading to backwards time
++ */
++static cycle_t kvm_clock_read(void)
++{
++ u64 last_tsc, now;
++ int cpu;
++
++ preempt_disable();
++ cpu = smp_processor_id();
++
++ last_tsc = get_clock(cpu, tsc_timestamp);
++ now = get_clock(cpu, system_time);
++
++ now += kvm_get_delta(last_tsc);
++ preempt_enable();
++
++ return now;
++}
++static struct clocksource kvm_clock = {
++ .name = "kvm-clock",
++ .read = kvm_clock_read,
++ .rating = 400,
++ .mask = CLOCKSOURCE_MASK(64),
++ .mult = 1 << KVM_SCALE,
++ .shift = KVM_SCALE,
++ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
++};
++
++static int kvm_register_clock(void)
++{
++ int cpu = smp_processor_id();
++ int low, high;
++ low = (int)__pa(&per_cpu(hv_clock, cpu)) | 1;
++ high = ((u64)__pa(&per_cpu(hv_clock, cpu)) >> 32);
++
++ return native_write_msr_safe(MSR_KVM_SYSTEM_TIME, low, high);
++}
++
++static void kvm_setup_secondary_clock(void)
++{
++ /*
++ * Now that the first cpu already had this clocksource initialized,
++ * we shouldn't fail.
++ */
++ WARN_ON(kvm_register_clock());
++ /* ok, done with our trickery, call native */
++ setup_secondary_APIC_clock();
++}
++
++/*
++ * After the clock is registered, the host will keep writing to the
++ * registered memory location. If the guest happens to shutdown, this memory
++ * won't be valid. In cases like kexec, in which you install a new kernel, this
++ * means a random memory location will be kept being written. So before any
++ * kind of shutdown from our side, we unregister the clock by writting anything
++ * that does not have the 'enable' bit set in the msr
++ */
++#ifdef CONFIG_KEXEC
++static void kvm_crash_shutdown(struct pt_regs *regs)
++{
++ native_write_msr_safe(MSR_KVM_SYSTEM_TIME, 0, 0);
++ native_machine_crash_shutdown(regs);
++}
++#endif
++
++static void kvm_shutdown(void)
++{
++ native_write_msr_safe(MSR_KVM_SYSTEM_TIME, 0, 0);
++ native_machine_shutdown();
++}
++
++void __init kvmclock_init(void)
++{
++ if (!kvm_para_available())
++ return;
++
++ if (kvmclock && kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE)) {
++ if (kvm_register_clock())
++ return;
++ pv_time_ops.get_wallclock = kvm_get_wallclock;
++ pv_time_ops.set_wallclock = kvm_set_wallclock;
++ pv_time_ops.sched_clock = kvm_clock_read;
++ pv_apic_ops.setup_secondary_clock = kvm_setup_secondary_clock;
++ machine_ops.shutdown = kvm_shutdown;
++#ifdef CONFIG_KEXEC
++ machine_ops.crash_shutdown = kvm_crash_shutdown;
++#endif
++ clocksource_register(&kvm_clock);
++ }
++}
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
@@ -244743,9 +304175,39 @@
*/
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
+index b402c0f..3cad17f 100644
--- a/arch/x86/kernel/mfgpt_32.c
+++ b/arch/x86/kernel/mfgpt_32.c
+@@ -63,7 +63,7 @@ static int __init mfgpt_fix(char *s)
+
+ /* The following udocumented bit resets the MFGPT timers */
+ val = 0xFF; dummy = 0;
+- wrmsr(0x5140002B, val, dummy);
++ wrmsr(MSR_MFGPT_SETUP, val, dummy);
+ return 1;
+ }
+ __setup("mfgptfix", mfgpt_fix);
+@@ -127,17 +127,17 @@ int geode_mfgpt_toggle_event(int timer, int cmp, int event, int enable)
+ * 6; that is, resets for 7 and 8 will be ignored. Is this
+ * a problem? -dilinger
+ */
+- msr = MFGPT_NR_MSR;
++ msr = MSR_MFGPT_NR;
+ mask = 1 << (timer + 24);
+ break;
+
+ case MFGPT_EVENT_NMI:
+- msr = MFGPT_NR_MSR;
++ msr = MSR_MFGPT_NR;
+ mask = 1 << (timer + shift);
+ break;
+
+ case MFGPT_EVENT_IRQ:
+- msr = MFGPT_IRQ_MSR;
++ msr = MSR_MFGPT_IRQ;
+ mask = 1 << (timer + shift);
+ break;
+
@@ -364,7 +364,8 @@ int __init mfgpt_timer_setup(void)
geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, val);
@@ -244897,6 +304359,255 @@
"group for CPU%d\n", cpu);
break;
case CPU_DOWN_PREPARE:
+diff --git a/arch/x86/kernel/mmconf-fam10h_64.c b/arch/x86/kernel/mmconf-fam10h_64.c
+new file mode 100644
+index 0000000..edc5fbf
+--- /dev/null
++++ b/arch/x86/kernel/mmconf-fam10h_64.c
+@@ -0,0 +1,243 @@
++/*
++ * AMD Family 10h mmconfig enablement
++ */
++
++#include <linux/types.h>
++#include <linux/mm.h>
++#include <linux/string.h>
++#include <linux/pci.h>
++#include <linux/dmi.h>
++#include <asm/pci-direct.h>
++#include <linux/sort.h>
++#include <asm/io.h>
++#include <asm/msr.h>
++#include <asm/acpi.h>
++
++#include "../pci/pci.h"
++
++struct pci_hostbridge_probe {
++ u32 bus;
++ u32 slot;
++ u32 vendor;
++ u32 device;
++};
++
++static u64 __cpuinitdata fam10h_pci_mmconf_base;
++static int __cpuinitdata fam10h_pci_mmconf_base_status;
++
++static struct pci_hostbridge_probe pci_probes[] __cpuinitdata = {
++ { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1200 },
++ { 0xff, 0, PCI_VENDOR_ID_AMD, 0x1200 },
++};
++
++struct range {
++ u64 start;
++ u64 end;
++};
++
++static int __cpuinit cmp_range(const void *x1, const void *x2)
++{
++ const struct range *r1 = x1;
++ const struct range *r2 = x2;
++ int start1, start2;
++
++ start1 = r1->start >> 32;
++ start2 = r2->start >> 32;
++
++ return start1 - start2;
++}
++
++/*[47:0] */
++/* need to avoid (0xfd<<32) and (0xfe<<32), ht used space */
++#define FAM10H_PCI_MMCONF_BASE (0xfcULL<<32)
++#define BASE_VALID(b) ((b != (0xfdULL << 32)) && (b != (0xfeULL << 32)))
++static void __cpuinit get_fam10h_pci_mmconf_base(void)
++{
++ int i;
++ unsigned bus;
++ unsigned slot;
++ int found;
++
++ u64 val;
++ u32 address;
++ u64 tom2;
++ u64 base = FAM10H_PCI_MMCONF_BASE;
++
++ int hi_mmio_num;
++ struct range range[8];
++
++ /* only try to get setting from BSP */
++ /* -1 or 1 */
++ if (fam10h_pci_mmconf_base_status)
++ return;
++
++ if (!early_pci_allowed())
++ goto fail;
++
++ found = 0;
++ for (i = 0; i < ARRAY_SIZE(pci_probes); i++) {
++ u32 id;
++ u16 device;
++ u16 vendor;
++
++ bus = pci_probes[i].bus;
++ slot = pci_probes[i].slot;
++ id = read_pci_config(bus, slot, 0, PCI_VENDOR_ID);
++
++ vendor = id & 0xffff;
++ device = (id>>16) & 0xffff;
++ if (pci_probes[i].vendor == vendor &&
++ pci_probes[i].device == device) {
++ found = 1;
++ break;
++ }
++ }
++
++ if (!found)
++ goto fail;
++
++ /* SYS_CFG */
++ address = MSR_K8_SYSCFG;
++ rdmsrl(address, val);
++
++ /* TOP_MEM2 is not enabled? */
++ if (!(val & (1<<21))) {
++ tom2 = 0;
++ } else {
++ /* TOP_MEM2 */
++ address = MSR_K8_TOP_MEM2;
++ rdmsrl(address, val);
++ tom2 = val & (0xffffULL<<32);
++ }
++
++ if (base <= tom2)
++ base = tom2 + (1ULL<<32);
++
++ /*
++ * need to check if the range is in the high mmio range that is
++ * above 4G
++ */
++ hi_mmio_num = 0;
++ for (i = 0; i < 8; i++) {
++ u32 reg;
++ u64 start;
++ u64 end;
++ reg = read_pci_config(bus, slot, 1, 0x80 + (i << 3));
++ if (!(reg & 3))
++ continue;
++
++ start = (((u64)reg) << 8) & (0xffULL << 32); /* 39:16 on 31:8*/
++ reg = read_pci_config(bus, slot, 1, 0x84 + (i << 3));
++ end = (((u64)reg) << 8) & (0xffULL << 32); /* 39:16 on 31:8*/
++
++ if (!end)
++ continue;
++
++ range[hi_mmio_num].start = start;
++ range[hi_mmio_num].end = end;
++ hi_mmio_num++;
++ }
++
++ if (!hi_mmio_num)
++ goto out;
++
++ /* sort the range */
++ sort(range, hi_mmio_num, sizeof(struct range), cmp_range, NULL);
++
++ if (range[hi_mmio_num - 1].end < base)
++ goto out;
++ if (range[0].start > base)
++ goto out;
++
++ /* need to find one window */
++ base = range[0].start - (1ULL << 32);
++ if ((base > tom2) && BASE_VALID(base))
++ goto out;
++ base = range[hi_mmio_num - 1].end + (1ULL << 32);
++ if ((base > tom2) && BASE_VALID(base))
++ goto out;
++ /* need to find window between ranges */
++ if (hi_mmio_num > 1)
++ for (i = 0; i < hi_mmio_num - 1; i++) {
++ if (range[i + 1].start > (range[i].end + (1ULL << 32))) {
++ base = range[i].end + (1ULL << 32);
++ if ((base > tom2) && BASE_VALID(base))
++ goto out;
++ }
++ }
++
++fail:
++ fam10h_pci_mmconf_base_status = -1;
++ return;
++out:
++ fam10h_pci_mmconf_base = base;
++ fam10h_pci_mmconf_base_status = 1;
++}
++
++void __cpuinit fam10h_check_enable_mmcfg(void)
++{
++ u64 val;
++ u32 address;
++
++ if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF))
++ return;
++
++ address = MSR_FAM10H_MMIO_CONF_BASE;
++ rdmsrl(address, val);
++
++ /* try to make sure that AP's setting is identical to BSP setting */
++ if (val & FAM10H_MMIO_CONF_ENABLE) {
++ unsigned busnbits;
++ busnbits = (val >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
++ FAM10H_MMIO_CONF_BUSRANGE_MASK;
++
++ /* only trust the one handle 256 buses, if acpi=off */
++ if (!acpi_pci_disabled || busnbits >= 8) {
++ u64 base;
++ base = val & (0xffffULL << 32);
++ if (fam10h_pci_mmconf_base_status <= 0) {
++ fam10h_pci_mmconf_base = base;
++ fam10h_pci_mmconf_base_status = 1;
++ return;
++ } else if (fam10h_pci_mmconf_base == base)
++ return;
++ }
++ }
++
++ /*
++ * if it is not enabled, try to enable it and assume only one segment
++ * with 256 buses
++ */
++ get_fam10h_pci_mmconf_base();
++ if (fam10h_pci_mmconf_base_status <= 0)
++ return;
++
++ printk(KERN_INFO "Enable MMCONFIG on AMD Family 10h\n");
++ val &= ~((FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT) |
++ (FAM10H_MMIO_CONF_BUSRANGE_MASK<<FAM10H_MMIO_CONF_BUSRANGE_SHIFT));
++ val |= fam10h_pci_mmconf_base | (8 << FAM10H_MMIO_CONF_BUSRANGE_SHIFT) |
++ FAM10H_MMIO_CONF_ENABLE;
++ wrmsrl(address, val);
++}
++
++static int __devinit set_check_enable_amd_mmconf(const struct dmi_system_id *d)
++{
++ pci_probe |= PCI_CHECK_ENABLE_AMD_MMCONF;
++ return 0;
++}
++
++static struct dmi_system_id __devinitdata mmconf_dmi_table[] = {
++ {
++ .callback = set_check_enable_amd_mmconf,
++ .ident = "Sun Microsystems Machine",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Sun Microsystems"),
++ },
++ },
++ {}
++};
++
++void __init check_enable_amd_mmconf_dmi(void)
++{
++ dmi_check_system(mmconf_dmi_table);
++}
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
new file mode 100644
index 0000000..3e2c54d
@@ -248134,6 +307845,272 @@
{
nmi_enter();
add_pda(__nmi_count,1);
+diff --git a/arch/x86/kernel/olpc.c b/arch/x86/kernel/olpc.c
+new file mode 100644
+index 0000000..3e66722
+--- /dev/null
++++ b/arch/x86/kernel/olpc.c
+@@ -0,0 +1,260 @@
++/*
++ * Support for the OLPC DCON and OLPC EC access
++ *
++ * Copyright © 2006 Advanced Micro Devices, Inc.
++ * Copyright © 2007-2008 Andres Salomon <dilinger at debian.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/io.h>
++#include <linux/string.h>
++#include <asm/geode.h>
++#include <asm/olpc.h>
++
++#ifdef CONFIG_OPEN_FIRMWARE
++#include <asm/ofw.h>
++#endif
++
++struct olpc_platform_t olpc_platform_info;
++EXPORT_SYMBOL_GPL(olpc_platform_info);
++
++static DEFINE_SPINLOCK(ec_lock);
++
++/* what the timeout *should* be (in ms) */
++#define EC_BASE_TIMEOUT 20
++
++/* the timeout that bugs in the EC might force us to actually use */
++static int ec_timeout = EC_BASE_TIMEOUT;
++
++static int __init olpc_ec_timeout_set(char *str)
++{
++ if (get_option(&str, &ec_timeout) != 1) {
++ ec_timeout = EC_BASE_TIMEOUT;
++ printk(KERN_ERR "olpc-ec: invalid argument to "
++ "'olpc_ec_timeout=', ignoring!\n");
++ }
++ printk(KERN_DEBUG "olpc-ec: using %d ms delay for EC commands.\n",
++ ec_timeout);
++ return 1;
++}
++__setup("olpc_ec_timeout=", olpc_ec_timeout_set);
++
++/*
++ * These {i,o}bf_status functions return whether the buffers are full or not.
++ */
++
++static inline unsigned int ibf_status(unsigned int port)
++{
++ return !!(inb(port) & 0x02);
++}
++
++static inline unsigned int obf_status(unsigned int port)
++{
++ return inb(port) & 0x01;
++}
++
++#define wait_on_ibf(p, d) __wait_on_ibf(__LINE__, (p), (d))
++static int __wait_on_ibf(unsigned int line, unsigned int port, int desired)
++{
++ unsigned int timeo;
++ int state = ibf_status(port);
++
++ for (timeo = ec_timeout; state != desired && timeo; timeo--) {
++ mdelay(1);
++ state = ibf_status(port);
++ }
++
++ if ((state == desired) && (ec_timeout > EC_BASE_TIMEOUT) &&
++ timeo < (ec_timeout - EC_BASE_TIMEOUT)) {
++ printk(KERN_WARNING "olpc-ec: %d: waited %u ms for IBF!\n",
++ line, ec_timeout - timeo);
++ }
++
++ return !(state == desired);
++}
++
++#define wait_on_obf(p, d) __wait_on_obf(__LINE__, (p), (d))
++static int __wait_on_obf(unsigned int line, unsigned int port, int desired)
++{
++ unsigned int timeo;
++ int state = obf_status(port);
++
++ for (timeo = ec_timeout; state != desired && timeo; timeo--) {
++ mdelay(1);
++ state = obf_status(port);
++ }
++
++ if ((state == desired) && (ec_timeout > EC_BASE_TIMEOUT) &&
++ timeo < (ec_timeout - EC_BASE_TIMEOUT)) {
++ printk(KERN_WARNING "olpc-ec: %d: waited %u ms for OBF!\n",
++ line, ec_timeout - timeo);
++ }
++
++ return !(state == desired);
++}
++
++/*
++ * This allows the kernel to run Embedded Controller commands. The EC is
++ * documented at <http://wiki.laptop.org/go/Embedded_controller>, and the
++ * available EC commands are here:
++ * <http://wiki.laptop.org/go/Ec_specification>. Unfortunately, while
++ * OpenFirmware's source is available, the EC's is not.
++ */
++int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
++ unsigned char *outbuf, size_t outlen)
++{
++ unsigned long flags;
++ int ret = -EIO;
++ int i;
++
++ spin_lock_irqsave(&ec_lock, flags);
++
++ /* Clear OBF */
++ for (i = 0; i < 10 && (obf_status(0x6c) == 1); i++)
++ inb(0x68);
++ if (i == 10) {
++ printk(KERN_ERR "olpc-ec: timeout while attempting to "
++ "clear OBF flag!\n");
++ goto err;
++ }
++
++ if (wait_on_ibf(0x6c, 0)) {
++ printk(KERN_ERR "olpc-ec: timeout waiting for EC to "
++ "quiesce!\n");
++ goto err;
++ }
++
++restart:
++ /*
++ * Note that if we time out during any IBF checks, that's a failure;
++ * we have to return. There's no way for the kernel to clear that.
++ *
++ * If we time out during an OBF check, we can restart the command;
++ * reissuing it will clear the OBF flag, and we should be alright.
++ * The OBF flag will sometimes misbehave due to what we believe
++ * is a hardware quirk..
++ */
++ printk(KERN_DEBUG "olpc-ec: running cmd 0x%x\n", cmd);
++ outb(cmd, 0x6c);
++
++ if (wait_on_ibf(0x6c, 0)) {
++ printk(KERN_ERR "olpc-ec: timeout waiting for EC to read "
++ "command!\n");
++ goto err;
++ }
++
++ if (inbuf && inlen) {
++ /* write data to EC */
++ for (i = 0; i < inlen; i++) {
++ if (wait_on_ibf(0x6c, 0)) {
++ printk(KERN_ERR "olpc-ec: timeout waiting for"
++ " EC accept data!\n");
++ goto err;
++ }
++ printk(KERN_DEBUG "olpc-ec: sending cmd arg 0x%x\n",
++ inbuf[i]);
++ outb(inbuf[i], 0x68);
++ }
++ }
++ if (outbuf && outlen) {
++ /* read data from EC */
++ for (i = 0; i < outlen; i++) {
++ if (wait_on_obf(0x6c, 1)) {
++ printk(KERN_ERR "olpc-ec: timeout waiting for"
++ " EC to provide data!\n");
++ goto restart;
++ }
++ outbuf[i] = inb(0x68);
++ printk(KERN_DEBUG "olpc-ec: received 0x%x\n",
++ outbuf[i]);
++ }
++ }
++
++ ret = 0;
++err:
++ spin_unlock_irqrestore(&ec_lock, flags);
++ return ret;
++}
++EXPORT_SYMBOL_GPL(olpc_ec_cmd);
++
++#ifdef CONFIG_OPEN_FIRMWARE
++static void __init platform_detect(void)
++{
++ size_t propsize;
++ u32 rev;
++
++ if (ofw("getprop", 4, 1, NULL, "board-revision-int", &rev, 4,
++ &propsize) || propsize != 4) {
++ printk(KERN_ERR "ofw: getprop call failed!\n");
++ rev = 0;
++ }
++ olpc_platform_info.boardrev = be32_to_cpu(rev);
++}
++#else
++static void __init platform_detect(void)
++{
++ /* stopgap until OFW support is added to the kernel */
++ olpc_platform_info.boardrev = be32_to_cpu(0xc2);
++}
++#endif
++
++static int __init olpc_init(void)
++{
++ unsigned char *romsig;
++
++ /* The ioremap check is dangerous; limit what we run it on */
++ if (!is_geode() || geode_has_vsa2())
++ return 0;
++
++ spin_lock_init(&ec_lock);
++
++ romsig = ioremap(0xffffffc0, 16);
++ if (!romsig)
++ return 0;
++
++ if (strncmp(romsig, "CL1 Q", 7))
++ goto unmap;
++ if (strncmp(romsig+6, romsig+13, 3)) {
++ printk(KERN_INFO "OLPC BIOS signature looks invalid. "
++ "Assuming not OLPC\n");
++ goto unmap;
++ }
++
++ printk(KERN_INFO "OLPC board with OpenFirmware %.16s\n", romsig);
++ olpc_platform_info.flags |= OLPC_F_PRESENT;
++
++ /* get the platform revision */
++ platform_detect();
++
++ /* assume B1 and above models always have a DCON */
++ if (olpc_board_at_least(olpc_board(0xb1)))
++ olpc_platform_info.flags |= OLPC_F_DCON;
++
++ /* get the EC revision */
++ olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0,
++ (unsigned char *) &olpc_platform_info.ecver, 1);
++
++ /* check to see if the VSA exists */
++ if (geode_has_vsa2())
++ olpc_platform_info.flags |= OLPC_F_VSA;
++
++ printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n",
++ ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "",
++ olpc_platform_info.boardrev >> 4,
++ olpc_platform_info.ecver);
++
++unmap:
++ iounmap(romsig);
++ return 0;
++}
++
++postcore_initcall(olpc_init);
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 075962c..74f0c5e 100644
--- a/arch/x86/kernel/paravirt.c
@@ -248226,7 +308203,7 @@
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
+index 0000000..0c37f16
--- /dev/null
+++ b/arch/x86/kernel/pci-dma.c
@@ -0,0 +1,524 @@
@@ -248246,7 +308223,7 @@
+const struct dma_mapping_ops *dma_ops;
+EXPORT_SYMBOL(dma_ops);
+
-+int iommu_sac_force __read_mostly = 0;
++static int iommu_sac_force __read_mostly;
+
+#ifdef CONFIG_IOMMU_DEBUG
+int panic_on_overflow __read_mostly = 1;
@@ -249563,16 +309540,18 @@
.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
+index 0000000..67e9b4a
--- /dev/null
+++ b/arch/x86/kernel/process.c
-@@ -0,0 +1,44 @@
+@@ -0,0 +1,161 @@
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
++#include <linux/module.h>
++#include <linux/pm.h>
+
+struct kmem_cache *task_xstate_cachep;
+
@@ -249611,8 +309590,123 @@
+ __alignof__(union thread_xstate),
+ SLAB_PANIC, NULL);
+}
++
++static void do_nothing(void *unused)
++{
++}
++
++/*
++ * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
++ * pm_idle and update to new pm_idle value. Required while changing pm_idle
++ * handler on SMP systems.
++ *
++ * Caller must have changed pm_idle to the new value before the call. Old
++ * pm_idle value will not be used by any CPU after the return of this function.
++ */
++void cpu_idle_wait(void)
++{
++ smp_mb();
++ /* kick all the CPUs so that they exit out of pm_idle */
++ smp_call_function(do_nothing, NULL, 0, 1);
++}
++EXPORT_SYMBOL_GPL(cpu_idle_wait);
++
++/*
++ * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
++ * which can obviate IPI to trigger checking of need_resched.
++ * We execute MONITOR against need_resched and enter optimized wait state
++ * through MWAIT. Whenever someone changes need_resched, we would be woken
++ * up from MWAIT (without an IPI).
++ *
++ * New with Core Duo processors, MWAIT can take some hints based on CPU
++ * capability.
++ */
++void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
++{
++ if (!need_resched()) {
++ __monitor((void *)¤t_thread_info()->flags, 0, 0);
++ smp_mb();
++ if (!need_resched())
++ __mwait(ax, cx);
++ }
++}
++
++/* Default MONITOR/MWAIT with no hints, used for default C1 state */
++static void mwait_idle(void)
++{
++ if (!need_resched()) {
++ __monitor((void *)¤t_thread_info()->flags, 0, 0);
++ smp_mb();
++ if (!need_resched())
++ __sti_mwait(0, 0);
++ else
++ local_irq_enable();
++ } else
++ local_irq_enable();
++}
++
++
++static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c)
++{
++ if (force_mwait)
++ return 1;
++ /* Any C1 states supported? */
++ return c->cpuid_level >= 5 && ((cpuid_edx(5) >> 4) & 0xf) > 0;
++}
++
++/*
++ * On SMP it's slightly faster (but much more power-consuming!)
++ * to poll the ->work.need_resched flag instead of waiting for the
++ * cross-CPU IPI to arrive. Use this option with caution.
++ */
++static void poll_idle(void)
++{
++ local_irq_enable();
++ cpu_relax();
++}
++
++void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
++{
++ static int selected;
++
++ if (selected)
++ return;
++#ifdef CONFIG_X86_SMP
++ if (pm_idle == poll_idle && smp_num_siblings > 1) {
++ printk(KERN_WARNING "WARNING: polling idle and HT enabled,"
++ " performance may degrade.\n");
++ }
++#endif
++ if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) {
++ /*
++ * Skip, if setup has overridden idle.
++ * One CPU supports mwait => All CPUs supports mwait
++ */
++ if (!pm_idle) {
++ printk(KERN_INFO "using mwait in idle threads.\n");
++ pm_idle = mwait_idle;
++ }
++ }
++ selected = 1;
++}
++
++static int __init idle_setup(char *str)
++{
++ if (!strcmp(str, "poll")) {
++ printk("using polling idle threads.\n");
++ pm_idle = poll_idle;
++ } else if (!strcmp(str, "mwait"))
++ force_mwait = 1;
++ else
++ return -1;
++
++ boot_option_idle_override = 1;
++ return 0;
++}
++early_param("idle", idle_setup);
++
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
-index 43930e7..77de848 100644
+index 43930e7..f8476df 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -36,6 +36,7 @@
@@ -249631,51 +309725,161 @@
#ifdef CONFIG_MATH_EMULATION
#include <asm/math_emu.h>
#endif
-@@ -113,20 +113,13 @@ void default_idle(void)
+@@ -111,22 +111,13 @@ void default_idle(void)
+ */
+ smp_mb();
- local_irq_disable();
- if (!need_resched()) {
+- local_irq_disable();
+- if (!need_resched()) {
- ktime_t t0, t1;
- u64 t0n, t1n;
-
- t0 = ktime_get();
- t0n = ktime_to_ns(t0);
++ if (!need_resched())
safe_halt(); /* enables interrupts racelessly */
- local_irq_disable();
+- local_irq_disable();
- t1 = ktime_get();
- t1n = ktime_to_ns(t1);
- sched_clock_idle_wakeup_event(t1n - t0n);
- }
- local_irq_enable();
+- }
+- local_irq_enable();
++ else
++ 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();
+@@ -135,16 +126,6 @@ void default_idle(void)
+ EXPORT_SYMBOL(default_idle);
+ #endif
+
+-/*
+- * On SMP it's slightly faster (but much more power-consuming!)
+- * to poll the ->work.need_resched flag instead of waiting for the
+- * cross-CPU IPI to arrive. Use this option with caution.
+- */
+-static void poll_idle(void)
+-{
+- cpu_relax();
+-}
+-
+ #ifdef CONFIG_HOTPLUG_CPU
+ #include <asm/nmi.h>
+ /* We don't actually take CPU down, just spin without interrupts. */
+@@ -202,6 +183,7 @@ void cpu_idle(void)
+ if (cpu_is_offline(cpu))
+ play_dead();
+
++ local_irq_disable();
+ __get_cpu_var(irq_stat).idle_timestamp = jiffies;
+ idle();
+ }
+@@ -212,101 +194,6 @@ void cpu_idle(void)
+ }
}
-@@ -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())
+-static void do_nothing(void *unused)
+-{
+-}
+-
+-/*
+- * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
+- * pm_idle and update to new pm_idle value. Required while changing pm_idle
+- * handler on SMP systems.
+- *
+- * Caller must have changed pm_idle to the new value before the call. Old
+- * pm_idle value will not be used by any CPU after the return of this function.
+- */
+-void cpu_idle_wait(void)
+-{
+- smp_mb();
+- /* kick all the CPUs so that they exit out of pm_idle */
+- smp_call_function(do_nothing, NULL, 0, 1);
+-}
+-EXPORT_SYMBOL_GPL(cpu_idle_wait);
+-
+-/*
+- * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
+- * which can obviate IPI to trigger checking of need_resched.
+- * We execute MONITOR against need_resched and enter optimized wait state
+- * through MWAIT. Whenever someone changes need_resched, we would be woken
+- * up from MWAIT (without an IPI).
+- *
+- * New with Core Duo processors, MWAIT can take some hints based on CPU
+- * capability.
+- */
+-void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
+-{
+- if (!need_resched()) {
+- __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)
+-}
+-
+-/* Default MONITOR/MWAIT with no hints, used for default C1 state */
+-static void mwait_idle(void)
+-{
+- local_irq_enable();
+- mwait_idle_with_hints(0, 0);
+-}
+-
+-static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c)
+-{
+- if (force_mwait)
+- return 1;
+- /* Any C1 states supported? */
+- return c->cpuid_level >= 5 && ((cpuid_edx(5) >> 4) & 0xf) > 0;
+-}
+-
+-void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
+-{
+- static int selected;
+-
+- if (selected)
+- return;
+-#ifdef CONFIG_X86_SMP
+- if (pm_idle == poll_idle && smp_num_siblings > 1) {
+- printk(KERN_WARNING "WARNING: polling idle and HT enabled,"
+- " performance may degrade.\n");
+- }
+-#endif
+- if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) {
+- /*
+- * Skip, if setup has overridden idle.
+- * One CPU supports mwait => All CPUs supports mwait
+- */
+- if (!pm_idle) {
+- printk(KERN_INFO "using mwait in idle threads.\n");
+- pm_idle = mwait_idle;
+- }
+- }
+- selected = 1;
+-}
+-
+-static int __init idle_setup(char *str)
+-{
+- if (!strcmp(str, "poll")) {
+- printk("using polling idle threads.\n");
+- pm_idle = poll_idle;
+- } else if (!strcmp(str, "mwait"))
+- force_mwait = 1;
+- else
+- return -1;
+-
+- boot_option_idle_override = 1;
+- return 0;
+-}
+-early_param("idle", idle_setup);
+-
+ void __show_registers(struct pt_regs *regs, int all)
+ {
+ unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
+@@ -332,7 +219,7 @@ void __show_registers(struct pt_regs *regs, int all)
init_utsname()->version);
printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
@@ -249684,7 +309888,7 @@
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)
+@@ -341,8 +228,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",
@@ -249694,7 +309898,7 @@
if (!all)
return;
-@@ -513,11 +509,30 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
+@@ -513,11 +399,30 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
return err;
}
@@ -249726,7 +309930,7 @@
void disable_TSC(void)
{
preempt_disable();
-@@ -529,11 +544,47 @@ void disable_TSC(void)
+@@ -529,11 +434,47 @@ void disable_TSC(void)
hard_disable_TSC();
preempt_enable();
}
@@ -249775,7 +309979,7 @@
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,
+@@ -550,12 +491,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;
@@ -249790,7 +309994,7 @@
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,
+@@ -567,7 +508,6 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
set_debugreg(next->debugreg7, 7);
}
@@ -249798,7 +310002,7 @@
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,
+@@ -576,7 +516,6 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
else
hard_enable_TSC();
}
@@ -249806,7 +310010,7 @@
#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
+@@ -658,7 +597,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)
@@ -249816,7 +310020,7 @@
/*
* Reload esp0.
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
-index 46c4c54..131c2ee 100644
+index 46c4c54..e2319f3 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -36,6 +36,7 @@
@@ -249827,24 +310031,156 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
-@@ -107,16 +108,8 @@ void default_idle(void)
+@@ -105,34 +106,13 @@ void default_idle(void)
+ * test NEED_RESCHED:
+ */
smp_mb();
- local_irq_disable();
- if (!need_resched()) {
+- local_irq_disable();
+- if (!need_resched()) {
- ktime_t t0, t1;
- u64 t0n, t1n;
-
- t0 = ktime_get();
- t0n = ktime_to_ns(t0);
++ if (!need_resched())
safe_halt(); /* enables interrupts racelessly */
- local_irq_disable();
+- local_irq_disable();
- t1 = ktime_get();
- t1n = ktime_to_ns(t1);
- sched_clock_idle_wakeup_event(t1n - t0n);
- }
- local_irq_enable();
+- }
+- local_irq_enable();
++ else
++ local_irq_enable();
current_thread_info()->status |= TS_POLLING;
-@@ -528,6 +521,83 @@ out:
+ }
+
+-/*
+- * On SMP it's slightly faster (but much more power-consuming!)
+- * to poll the ->need_resched flag instead of waiting for the
+- * cross-CPU IPI to arrive. Use this option with caution.
+- */
+-static void poll_idle(void)
+-{
+- local_irq_enable();
+- cpu_relax();
+-}
+-
+ #ifdef CONFIG_HOTPLUG_CPU
+ DECLARE_PER_CPU(int, cpu_state);
+
+@@ -199,110 +179,6 @@ void cpu_idle(void)
+ }
+ }
+
+-static void do_nothing(void *unused)
+-{
+-}
+-
+-/*
+- * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
+- * pm_idle and update to new pm_idle value. Required while changing pm_idle
+- * handler on SMP systems.
+- *
+- * Caller must have changed pm_idle to the new value before the call. Old
+- * pm_idle value will not be used by any CPU after the return of this function.
+- */
+-void cpu_idle_wait(void)
+-{
+- smp_mb();
+- /* kick all the CPUs so that they exit out of pm_idle */
+- smp_call_function(do_nothing, NULL, 0, 1);
+-}
+-EXPORT_SYMBOL_GPL(cpu_idle_wait);
+-
+-/*
+- * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
+- * which can obviate IPI to trigger checking of need_resched.
+- * We execute MONITOR against need_resched and enter optimized wait state
+- * through MWAIT. Whenever someone changes need_resched, we would be woken
+- * up from MWAIT (without an IPI).
+- *
+- * New with Core Duo processors, MWAIT can take some hints based on CPU
+- * capability.
+- */
+-void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
+-{
+- if (!need_resched()) {
+- __monitor((void *)¤t_thread_info()->flags, 0, 0);
+- smp_mb();
+- if (!need_resched())
+- __mwait(ax, cx);
+- }
+-}
+-
+-/* Default MONITOR/MWAIT with no hints, used for default C1 state */
+-static void mwait_idle(void)
+-{
+- if (!need_resched()) {
+- __monitor((void *)¤t_thread_info()->flags, 0, 0);
+- smp_mb();
+- if (!need_resched())
+- __sti_mwait(0, 0);
+- else
+- local_irq_enable();
+- } else {
+- local_irq_enable();
+- }
+-}
+-
+-
+-static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c)
+-{
+- if (force_mwait)
+- return 1;
+- /* Any C1 states supported? */
+- return c->cpuid_level >= 5 && ((cpuid_edx(5) >> 4) & 0xf) > 0;
+-}
+-
+-void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
+-{
+- static int selected;
+-
+- if (selected)
+- return;
+-#ifdef CONFIG_X86_SMP
+- if (pm_idle == poll_idle && smp_num_siblings > 1) {
+- printk(KERN_WARNING "WARNING: polling idle and HT enabled,"
+- " performance may degrade.\n");
+- }
+-#endif
+- if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) {
+- /*
+- * Skip, if setup has overridden idle.
+- * One CPU supports mwait => All CPUs supports mwait
+- */
+- if (!pm_idle) {
+- printk(KERN_INFO "using mwait in idle threads.\n");
+- pm_idle = mwait_idle;
+- }
+- }
+- selected = 1;
+-}
+-
+-static int __init idle_setup(char *str)
+-{
+- if (!strcmp(str, "poll")) {
+- printk("using polling idle threads.\n");
+- pm_idle = poll_idle;
+- } else if (!strcmp(str, "mwait"))
+- force_mwait = 1;
+- else
+- return -1;
+-
+- boot_option_idle_override = 1;
+- return 0;
+-}
+-early_param("idle", idle_setup);
+-
+ /* Prints also some state that isn't saved in the pt_regs */
+ void __show_regs(struct pt_regs * regs)
+ {
+@@ -528,6 +404,83 @@ out:
return err;
}
@@ -249928,7 +310264,7 @@
/*
* 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,
+@@ -548,12 +501,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;
@@ -249943,7 +310279,7 @@
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,
+@@ -565,6 +518,15 @@ static inline void __switch_to_xtra(struct task_struct *prev_p,
loaddebug(next, 7);
}
@@ -249959,7 +310295,7 @@
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)
+@@ -607,7 +569,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)
@@ -250100,7 +310436,7 @@
{
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
+index 484c4a8..07c6d42 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -1,5 +1,4 @@
@@ -250109,15 +310445,16 @@
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/pm.h>
-@@ -9,6 +8,7 @@
+@@ -9,6 +8,8 @@
#include <asm/apic.h>
#include <asm/desc.h>
#include <asm/hpet.h>
+#include <asm/pgtable.h>
++#include <asm/proto.h>
#include <asm/reboot_fixups.h>
#include <asm/reboot.h>
-@@ -16,7 +16,6 @@
+@@ -16,7 +17,6 @@
# include <linux/dmi.h>
# include <linux/ctype.h>
# include <linux/mc146818rtc.h>
@@ -250125,7 +310462,7 @@
#else
# include <asm/iommu.h>
#endif
-@@ -276,7 +275,7 @@ void machine_real_restart(unsigned char *code, int length)
+@@ -276,7 +276,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. */
@@ -250134,7 +310471,16 @@
sizeof(swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
/*
-@@ -412,16 +411,16 @@ static void native_machine_shutdown(void)
+@@ -400,7 +400,7 @@ static void native_machine_emergency_restart(void)
+ }
+ }
+
+-static void native_machine_shutdown(void)
++void native_machine_shutdown(void)
+ {
+ /* Stop the cpus and apics */
+ #ifdef CONFIG_SMP
+@@ -412,16 +412,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) &&
@@ -250154,6 +310500,28 @@
/* O.K Now that I'm on the appropriate processor,
* stop all of the others.
+@@ -471,7 +471,10 @@ struct machine_ops machine_ops = {
+ .shutdown = native_machine_shutdown,
+ .emergency_restart = native_machine_emergency_restart,
+ .restart = native_machine_restart,
+- .halt = native_machine_halt
++ .halt = native_machine_halt,
++#ifdef CONFIG_KEXEC
++ .crash_shutdown = native_machine_crash_shutdown,
++#endif
+ };
+
+ void machine_power_off(void)
+@@ -499,3 +502,9 @@ void machine_halt(void)
+ machine_ops.halt();
+ }
+
++#ifdef CONFIG_KEXEC
++void machine_crash_shutdown(struct pt_regs *regs)
++{
++ machine_ops.crash_shutdown(regs);
++}
++#endif
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
@@ -250692,7 +311060,7 @@
+ uv_cpu_init();
}
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
-index 2b3e5d4..44cc9b9 100644
+index 2b3e5d4..2283422 100644
--- a/arch/x86/kernel/setup_32.c
+++ b/arch/x86/kernel/setup_32.c
@@ -39,6 +39,7 @@
@@ -250703,7 +311071,15 @@
#include <linux/nodemask.h>
#include <linux/kexec.h>
#include <linux/crash_dump.h>
-@@ -62,8 +63,9 @@
+@@ -46,6 +47,7 @@
+ #include <linux/pfn.h>
+ #include <linux/pci.h>
+ #include <linux/init_ohci1394_dma.h>
++#include <linux/kvm_para.h>
+
+ #include <video/edid.h>
+
+@@ -62,8 +64,9 @@
#include <asm/io.h>
#include <asm/vmi.h>
#include <setup_arch.h>
@@ -250714,7 +311090,7 @@
/* 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 };
+@@ -154,6 +157,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);
@@ -250723,7 +311099,7 @@
#ifndef CONFIG_X86_PAE
unsigned long mmu_cr4_features;
#else
-@@ -189,7 +193,7 @@ EXPORT_SYMBOL(ist_info);
+@@ -189,7 +194,7 @@ EXPORT_SYMBOL(ist_info);
extern void early_cpu_init(void);
extern int root_mountflags;
@@ -250732,7 +311108,7 @@
#define RAMDISK_IMAGE_START_MASK 0x07FF
#define RAMDISK_PROMPT_FLAG 0x8000
-@@ -227,7 +231,7 @@ static inline void copy_edd(void)
+@@ -227,7 +232,7 @@ static inline void copy_edd(void)
}
#endif
@@ -250741,7 +311117,7 @@
/*
* "mem=nopentium" disables the 4MB page tables.
-@@ -385,19 +389,58 @@ unsigned long __init find_max_low_pfn(void)
+@@ -385,19 +390,58 @@ unsigned long __init find_max_low_pfn(void)
return max_low_pfn;
}
@@ -250806,7 +311182,7 @@
static unsigned long __init setup_memory(void)
{
/*
-@@ -432,7 +475,7 @@ static unsigned long __init setup_memory(void)
+@@ -432,7 +476,7 @@ static unsigned long __init setup_memory(void)
return max_low_pfn;
}
@@ -250815,7 +311191,7 @@
{
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)
+@@ -617,16 +661,9 @@ void __init setup_bootmem_allocator(void)
*/
reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT);
@@ -250833,7 +311209,7 @@
#ifdef CONFIG_SMP
/*
* But first pinch a few for the stack/trampoline stuff
-@@ -652,6 +688,8 @@ void __init setup_bootmem_allocator(void)
+@@ -652,6 +689,8 @@ void __init setup_bootmem_allocator(void)
#endif
numa_kva_reserve();
reserve_crashkernel();
@@ -250842,7 +311218,7 @@
}
/*
-@@ -687,6 +725,18 @@ char * __init __attribute__((weak)) memory_setup(void)
+@@ -687,6 +726,18 @@ char * __init __attribute__((weak)) memory_setup(void)
return machine_specific_memory_setup();
}
@@ -250861,7 +311237,7 @@
/*
* 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)
+@@ -714,7 +765,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;
@@ -250870,7 +311246,7 @@
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)
+@@ -763,13 +814,17 @@ void __init setup_arch(char **cmdline_p)
efi_init();
/* update e820 for memory not covered by WB MTRRs */
@@ -250883,7 +311259,22 @@
max_low_pfn = setup_memory();
-@@ -820,6 +870,18 @@ void __init setup_arch(char **cmdline_p)
++#ifdef CONFIG_KVM_CLOCK
++ kvmclock_init();
++#endif
++
+ #ifdef CONFIG_VMI
+ /*
+ * Must be after max_low_pfn is determined, and before kernel
+@@ -777,6 +832,7 @@ void __init setup_arch(char **cmdline_p)
+ */
+ vmi_init();
+ #endif
++ kvm_guest_init();
+
+ /*
+ * NOTE: before this point _nobody_ is allowed to allocate
+@@ -820,6 +876,18 @@ void __init setup_arch(char **cmdline_p)
io_delay_init();
@@ -250903,10 +311294,15 @@
generic_apic_probe();
#endif
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
-index f4f7ecf..17bdf23 100644
+index f4f7ecf..22c14e2 100644
--- a/arch/x86/kernel/setup_64.c
+++ b/arch/x86/kernel/setup_64.c
-@@ -33,6 +33,7 @@
+@@ -29,18 +29,22 @@
+ #include <linux/crash_dump.h>
+ #include <linux/root_dev.h>
+ #include <linux/pci.h>
++#include <asm/pci-direct.h>
+ #include <linux/efi.h>
#include <linux/acpi.h>
#include <linux/kallsyms.h>
#include <linux/edd.h>
@@ -250914,7 +311310,17 @@
#include <linux/mmzone.h>
#include <linux/kexec.h>
#include <linux/cpufreq.h>
-@@ -58,7 +59,6 @@
+ #include <linux/dmi.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/ctype.h>
++#include <linux/sort.h>
+ #include <linux/uaccess.h>
+ #include <linux/init_ohci1394_dma.h>
++#include <linux/kvm_para.h>
+
+ #include <asm/mtrr.h>
+ #include <asm/uaccess.h>
+@@ -58,7 +62,6 @@
#include <asm/mmu_context.h>
#include <asm/proto.h>
#include <asm/setup.h>
@@ -250922,7 +311328,7 @@
#include <asm/numa.h>
#include <asm/sections.h>
#include <asm/dmi.h>
-@@ -66,7 +66,9 @@
+@@ -66,7 +69,9 @@
#include <asm/mce.h>
#include <asm/ds.h>
#include <asm/topology.h>
@@ -250932,24 +311338,82 @@
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#else
-@@ -114,7 +116,7 @@ extern int root_mountflags;
+@@ -114,7 +119,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,
+@@ -188,6 +193,7 @@ contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
+ bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
+ e820_register_active_regions(0, start_pfn, end_pfn);
+ free_bootmem_with_active_regions(0, end_pfn);
++ early_res_to_bootmem(0, end_pfn<<PAGE_SHIFT);
+ reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT);
+ }
+ #endif
+@@ -248,6 +254,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
+@@ -261,6 +268,40 @@ void __attribute__((weak)) __init memory_setup(void)
+ machine_specific_memory_setup();
+ }
+
++static void __init parse_setup_data(void)
++{
++ struct setup_data *data;
++ unsigned long pa_data;
++
++ if (boot_params.hdr.version < 0x0209)
++ return;
++ pa_data = boot_params.hdr.setup_data;
++ while (pa_data) {
++ data = early_ioremap(pa_data, PAGE_SIZE);
++ switch (data->type) {
++ default:
++ break;
++ }
++#ifndef CONFIG_DEBUG_BOOT_PARAMS
++ free_early(pa_data, pa_data+sizeof(*data)+data->len);
++#endif
++ pa_data = data->next;
++ early_iounmap(data, PAGE_SIZE);
++ }
++}
++
++#ifdef CONFIG_PCI_MMCONFIG
++extern void __cpuinit fam10h_check_enable_mmcfg(void);
++extern void __init check_enable_amd_mmconf_dmi(void);
++#else
++void __cpuinit fam10h_check_enable_mmcfg(void)
++{
++}
++void __init check_enable_amd_mmconf_dmi(void)
++{
++}
++#endif
++
+ /*
+ * setup_arch - architecture-specific boot-time initializations
+ *
+@@ -313,6 +354,8 @@ void __init setup_arch(char **cmdline_p)
+ strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
+ *cmdline_p = command_line;
- char __initdata command_line[COMMAND_LINE_SIZE];
++ parse_setup_data();
++
+ parse_early_param();
--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)
+ #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+@@ -322,6 +365,11 @@ void __init setup_arch(char **cmdline_p)
finish_e820_parsing();
@@ -250961,7 +311425,7 @@
early_gart_iommu_check();
e820_register_active_regions(0, 0, -1UL);
-@@ -341,10 +349,12 @@ void __init setup_arch(char **cmdline_p)
+@@ -341,14 +389,20 @@ void __init setup_arch(char **cmdline_p)
check_efer();
@@ -250975,16 +311439,24 @@
dmi_scan_machine();
io_delay_init();
-@@ -389,6 +399,8 @@ void __init setup_arch(char **cmdline_p)
- early_res_to_bootmem();
++#ifdef CONFIG_KVM_CLOCK
++ kvmclock_init();
++#endif
++
+ #ifdef CONFIG_SMP
+ /* setup to use the early static init tables during kernel startup */
+ x86_cpu_to_apicid_early_ptr = (void *)x86_cpu_to_apicid_init;
+@@ -387,7 +441,7 @@ void __init setup_arch(char **cmdline_p)
+ contig_initmem_init(0, end_pfn);
+ #endif
+- 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)
+@@ -411,11 +465,14 @@ void __init setup_arch(char **cmdline_p)
unsigned long end_of_mem = end_pfn << PAGE_SHIFT;
if (ramdisk_end <= end_of_mem) {
@@ -251001,7 +311473,7 @@
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)
+@@ -425,6 +482,9 @@ void __init setup_arch(char **cmdline_p)
}
#endif
reserve_crashkernel();
@@ -251011,7 +311483,12 @@
paging_init();
map_vsyscall();
-@@ -450,7 +468,7 @@ void __init setup_arch(char **cmdline_p)
+@@ -447,10 +507,12 @@ void __init setup_arch(char **cmdline_p)
+ init_apic_mappings();
+ ioapic_init_mappings();
+
++ kvm_guest_init();
++
/*
* We trust e820 completely. No explicit ROM probing in memory.
*/
@@ -251020,7 +311497,17 @@
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)
+@@ -467,6 +529,9 @@ void __init setup_arch(char **cmdline_p)
+ conswitchp = &dummy_con;
+ #endif
+ #endif
++
++ /* do this before identify_cpu for boot cpu */
++ check_enable_amd_mmconf_dmi();
+ }
+
+ static int __cpuinit get_model_name(struct cpuinfo_x86 *c)
+@@ -552,9 +617,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) */
@@ -251033,7 +311520,7 @@
#ifdef CONFIG_NUMA
node = c->phys_proc_id;
-@@ -571,7 +589,7 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c)
+@@ -571,7 +636,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. */
@@ -251042,7 +311529,7 @@
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)
+@@ -677,7 +742,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 */
@@ -251051,8 +311538,13 @@
/* 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)
+@@ -719,8 +784,24 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ /* MFENCE stops RDTSC speculation */
+ set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
++ if (c->x86 == 0x10)
++ fam10h_check_enable_mmcfg();
++
if (amd_apic_timer_broken())
disable_apic_timer = 1;
+
@@ -251071,7 +311563,7 @@
}
void __cpuinit detect_ht(struct cpuinfo_x86 *c)
-@@ -813,7 +844,7 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
+@@ -813,7 +894,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))
@@ -251080,7 +311572,7 @@
}
static void __cpuinit init_intel(struct cpuinfo_x86 *c)
-@@ -856,9 +887,6 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+@@ -856,9 +937,6 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
if (c->x86 == 15)
c->x86_cache_alignment = c->x86_clflush_size * 2;
@@ -251090,7 +311582,7 @@
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)
+@@ -867,6 +945,32 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
srat_detect_node();
}
@@ -251123,7 +311615,7 @@
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)
+@@ -875,6 +979,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;
@@ -251132,7 +311624,7 @@
else
c->x86_vendor = X86_VENDOR_UNKNOWN;
}
-@@ -922,15 +978,16 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
+@@ -922,15 +1028,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;
@@ -251151,7 +311643,7 @@
#endif
/* AMD-defined flags: level 0x80000001 */
xlvl = cpuid_eax(0x80000000);
-@@ -956,12 +1013,22 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
+@@ -956,12 +1063,22 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
if (c->extended_cpuid_level >= 0x80000007)
c->x86_power = cpuid_edx(0x80000007);
@@ -251174,7 +311666,7 @@
break;
}
-@@ -999,6 +1066,10 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+@@ -999,6 +1116,10 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
init_intel(c);
break;
@@ -251185,7 +311677,7 @@
case X86_VENDOR_UNKNOWN:
default:
display_cacheinfo(c);
-@@ -1028,14 +1099,24 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+@@ -1028,14 +1149,24 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
#endif
select_idle_routine(c);
@@ -251212,7 +311704,7 @@
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)
+@@ -1064,123 +1195,3 @@ static __init int setup_disablecpuid(char *arg)
return 1;
}
__setup("clearcpuid=", setup_disablecpuid);
@@ -251397,7 +311889,7 @@
- char retcode[8];
-};
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c
-index 0157a6f..8e05e7f 100644
+index 0157a6f..d923736 100644
--- a/arch/x86/kernel/signal_32.c
+++ b/arch/x86/kernel/signal_32.c
@@ -4,32 +4,44 @@
@@ -251456,10 +311948,12 @@
/*
* 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)
+@@ -45,11 +57,12 @@ sys_sigsuspend(int history0, int history1, old_sigset_t mask)
+
current->state = TASK_INTERRUPTIBLE;
schedule();
- set_thread_flag(TIF_RESTORE_SIGMASK);
+- set_thread_flag(TIF_RESTORE_SIGMASK);
++ set_restore_sigmask();
+
return -ERESTARTNOHAND;
}
@@ -251967,7 +312461,7 @@
}
/*
-@@ -580,18 +578,17 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+@@ -580,52 +578,52 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
*/
static void do_signal(struct pt_regs *regs)
{
@@ -251992,7 +312486,12 @@
*/
if (!user_mode(regs))
return;
-@@ -603,29 +600,31 @@ static void do_signal(struct pt_regs *regs)
+
+- if (test_thread_flag(TIF_RESTORE_SIGMASK))
++ if (current_thread_info()->status & TS_RESTORE_SIGMASK)
+ oldset = ¤t->saved_sigmask;
+ else
+ oldset = ¤t->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
@@ -252012,14 +312511,15 @@
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
- /* a signal was successfully delivered; the saved
+ /*
-+ * 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);
++ * clear the TS_RESTORE_SIGMASK flag.
+ */
- if (test_thread_flag(TIF_RESTORE_SIGMASK))
- clear_thread_flag(TIF_RESTORE_SIGMASK);
++ current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
}
-
return;
@@ -252031,20 +312531,24 @@
/* Restart the system call - no handlers present */
switch (regs->ax) {
case -ERESTARTNOHAND:
-@@ -642,8 +641,10 @@ static void do_signal(struct pt_regs *regs)
+@@ -642,10 +640,12 @@ static void do_signal(struct pt_regs *regs)
}
}
- /* 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);
+ /*
+ * 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);
++ if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
++ current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
-@@ -654,13 +655,12 @@ static void do_signal(struct pt_regs *regs)
+ }
+ }
+@@ -654,22 +654,21 @@ static void do_signal(struct pt_regs *regs)
* notification of userspace execution resumption
* - triggered by the TIF_WORK_MASK flags
*/
@@ -252061,7 +312565,10 @@
clear_thread_flag(TIF_SINGLESTEP);
}
-@@ -670,6 +670,6 @@ void do_notify_resume(struct pt_regs *regs, void *_unused,
+ /* deal with pending signal delivery */
+- if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
++ if (thread_info_flags & _TIF_SIGPENDING)
+ do_signal(regs);
if (thread_info_flags & _TIF_HRTICK_RESCHED)
hrtick_resched();
@@ -252070,7 +312577,7 @@
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
+index 1c83e51..e53b267 100644
--- a/arch/x86/kernel/signal_64.c
+++ b/arch/x86/kernel/signal_64.c
@@ -19,17 +19,28 @@
@@ -252278,7 +312785,7 @@
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)
+@@ -420,15 +418,16 @@ static void do_signal(struct pt_regs *regs)
sigset_t *oldset;
/*
@@ -252293,18 +312800,43 @@
*/
if (!user_mode(regs))
return;
-@@ -473,22 +472,19 @@ static void do_signal(struct pt_regs *regs)
+
+- if (test_thread_flag(TIF_RESTORE_SIGMASK))
++ if (current_thread_info()->status & TS_RESTORE_SIGMASK)
+ oldset = ¤t->saved_sigmask;
+ else
+ oldset = ¤t->blocked;
+@@ -445,11 +444,13 @@ static void do_signal(struct pt_regs *regs)
+
+ /* 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_thread_flag(TIF_RESTORE_SIGMASK);
++ * clear the TS_RESTORE_SIGMASK flag.
++ */
++ current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+ }
+ return;
+ }
+@@ -473,22 +474,19 @@ static void do_signal(struct pt_regs *regs)
}
}
- /* 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);
+ /*
+ * 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);
++ if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
++ current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
}
}
@@ -252322,12 +312854,12 @@
/* 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)
+@@ -502,7 +500,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))
++ if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs);
if (thread_info_flags & _TIF_HRTICK_RESCHED)
@@ -253936,10 +314468,10 @@
-
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
new file mode 100644
-index 0000000..04c662b
+index 0000000..84241a2
--- /dev/null
+++ b/arch/x86/kernel/smpboot.c
-@@ -0,0 +1,1450 @@
+@@ -0,0 +1,1446 @@
+/*
+ * x86 SMP booting functions
+ *
@@ -255091,14 +315623,10 @@
+ "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();
-+ }
++ connect_bsp_APIC();
+#endif
++ setup_local_APIC();
++ end_local_APIC_setup();
+ return -1;
+ }
+
@@ -256844,4292 +317372,10379 @@
-#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))
+-struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
+-#define get_idle_for_cpu(x) (idle_thread_array[(x)])
+-#define set_idle_for_cpu(x,p) (idle_thread_array[(x)] = (p))
+-#endif
+-
+-
+-/*
+- * Currently trivial. Write the real->protected mode
+- * bootstrap into the page concerned. The caller
+- * has made sure it's suitably aligned.
+- */
+-
+-static unsigned long __cpuinit setup_trampoline(void)
+-{
+- void *tramp = __va(SMP_TRAMPOLINE_BASE);
+- memcpy(tramp, trampoline_data, trampoline_end - trampoline_data);
+- return virt_to_phys(tramp);
+-}
+-
+-/*
+- * The bootstrap kernel entry code has set these up. Save them for
+- * a given CPU
+- */
+-
+-static void __cpuinit smp_store_cpu_info(int id)
+-{
+- struct cpuinfo_x86 *c = &cpu_data(id);
+-
+- *c = boot_cpu_data;
+- c->cpu_index = id;
+- identify_cpu(c);
+- print_cpu_info(c);
+-}
+-
+-static atomic_t init_deasserted __cpuinitdata;
+-
+-/*
+- * Report back to the Boot Processor.
+- * Running on AP.
+- */
+-void __cpuinit smp_callin(void)
+-{
+- int cpuid, phys_id;
+- unsigned long timeout;
+-
+- /*
+- * If waken up by an INIT in an 82489DX configuration
+- * we may get here before an INIT-deassert IPI reaches
+- * our local APIC. We have to wait for the IPI or we'll
+- * lock up on an APIC access.
+- */
+- while (!atomic_read(&init_deasserted))
+- cpu_relax();
+-
+- /*
+- * (This works even if the APIC is not enabled.)
+- */
+- phys_id = GET_APIC_ID(apic_read(APIC_ID));
+- cpuid = smp_processor_id();
+- if (cpu_isset(cpuid, cpu_callin_map)) {
+- panic("smp_callin: phys CPU#%d, CPU#%d already present??\n",
+- phys_id, cpuid);
+- }
+- Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
+-
+- /*
+- * STARTUP IPIs are fragile beasts as they might sometimes
+- * trigger some glue motherboard logic. Complete APIC bus
+- * silence for 1 second, this overestimates the time the
+- * boot CPU is spending to send the up to 2 STARTUP IPIs
+- * by a factor of two. This should be enough.
+- */
+-
+- /*
+- * Waiting 2s total for startup (udelay is not yet working)
+- */
+- timeout = jiffies + 2*HZ;
+- while (time_before(jiffies, timeout)) {
+- /*
+- * Has the boot CPU finished it's STARTUP sequence?
+- */
+- if (cpu_isset(cpuid, cpu_callout_map))
+- break;
+- cpu_relax();
+- }
+-
+- if (!time_before(jiffies, timeout)) {
+- panic("smp_callin: CPU%d started up but did not get a callout!\n",
+- cpuid);
+- }
+-
+- /*
+- * the boot CPU has finished the init stage and is spinning
+- * on callin_map until we finish. We are free to set up this
+- * CPU, first the APIC. (this is probably redundant on most
+- * boards)
+- */
+-
+- Dprintk("CALLIN, before setup_local_APIC().\n");
+- setup_local_APIC();
+- end_local_APIC_setup();
+-
+- /*
+- * Get our bogomips.
+- *
+- * Need to enable IRQs because it can take longer and then
+- * the NMI watchdog might kill us.
+- */
+- local_irq_enable();
+- calibrate_delay();
+- local_irq_disable();
+- Dprintk("Stack at about %p\n",&cpuid);
+-
+- /*
+- * Save our processor parameters
+- */
+- smp_store_cpu_info(cpuid);
+-
+- /*
+- * Allow the master to continue.
+- */
+- cpu_set(cpuid, cpu_callin_map);
+-}
+-
+-/* maps the cpu to the sched domain representing multi-core */
+-cpumask_t cpu_coregroup_map(int cpu)
+-{
+- struct cpuinfo_x86 *c = &cpu_data(cpu);
+- /*
+- * For perf, we return last level cache shared map.
+- * And for power savings, we return cpu_core_map
+- */
+- if (sched_mc_power_savings || sched_smt_power_savings)
+- return per_cpu(cpu_core_map, cpu);
+- else
+- return c->llc_shared_map;
+-}
+-
+-/* representing cpus for which sibling maps can be computed */
+-static cpumask_t cpu_sibling_setup_map;
+-
+-static inline void set_cpu_sibling_map(int cpu)
+-{
+- int i;
+- struct cpuinfo_x86 *c = &cpu_data(cpu);
+-
+- cpu_set(cpu, cpu_sibling_setup_map);
+-
+- if (smp_num_siblings > 1) {
+- for_each_cpu_mask(i, cpu_sibling_setup_map) {
+- if (c->phys_proc_id == cpu_data(i).phys_proc_id &&
+- c->cpu_core_id == cpu_data(i).cpu_core_id) {
+- cpu_set(i, per_cpu(cpu_sibling_map, cpu));
+- cpu_set(cpu, per_cpu(cpu_sibling_map, i));
+- cpu_set(i, per_cpu(cpu_core_map, cpu));
+- cpu_set(cpu, per_cpu(cpu_core_map, i));
+- cpu_set(i, c->llc_shared_map);
+- cpu_set(cpu, cpu_data(i).llc_shared_map);
+- }
+- }
+- } else {
+- cpu_set(cpu, per_cpu(cpu_sibling_map, cpu));
+- }
+-
+- cpu_set(cpu, c->llc_shared_map);
+-
+- if (current_cpu_data.x86_max_cores == 1) {
+- per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu);
+- c->booted_cores = 1;
+- return;
+- }
+-
+- for_each_cpu_mask(i, cpu_sibling_setup_map) {
+- if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
+- per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
+- cpu_set(i, c->llc_shared_map);
+- cpu_set(cpu, cpu_data(i).llc_shared_map);
+- }
+- if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
+- cpu_set(i, per_cpu(cpu_core_map, cpu));
+- cpu_set(cpu, per_cpu(cpu_core_map, i));
+- /*
+- * Does this new cpu bringup a new core?
+- */
+- if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) {
+- /*
+- * for each core in package, increment
+- * the booted_cores for this new cpu
+- */
+- if (first_cpu(per_cpu(cpu_sibling_map, i)) == i)
+- c->booted_cores++;
+- /*
+- * increment the core count for all
+- * the other cpus in this package
+- */
+- if (i != cpu)
+- cpu_data(i).booted_cores++;
+- } else if (i != cpu && !c->booted_cores)
+- c->booted_cores = cpu_data(i).booted_cores;
+- }
+- }
+-}
+-
+-/*
+- * Setup code on secondary processor (after comming out of the trampoline)
+- */
+-void __cpuinit start_secondary(void)
+-{
+- /*
+- * Dont put anything before smp_callin(), SMP
+- * booting is too fragile that we want to limit the
+- * things done here to the most necessary things.
+- */
+- cpu_init();
+- preempt_disable();
+- smp_callin();
+-
+- /* otherwise gcc will move up the smp_processor_id before the cpu_init */
+- barrier();
+-
+- /*
+- * Check TSC sync first:
+- */
+- check_tsc_sync_target();
+-
+- if (nmi_watchdog == NMI_IO_APIC) {
+- disable_8259A_irq(0);
+- enable_NMI_through_LVT0();
+- enable_8259A_irq(0);
+- }
+-
+- /*
+- * The sibling maps must be set before turing the online map on for
+- * this cpu
+- */
+- set_cpu_sibling_map(smp_processor_id());
+-
+- /*
+- * We need to hold call_lock, so there is no inconsistency
+- * between the time smp_call_function() determines number of
+- * IPI recipients, and the time when the determination is made
+- * for which cpus receive the IPI in genapic_flat.c. Holding this
+- * lock helps us to not include this cpu in a currently in progress
+- * smp_call_function().
+- */
+- lock_ipi_call_lock();
+- spin_lock(&vector_lock);
+-
+- /* Setup the per cpu irq handling data structures */
+- __setup_vector_irq(smp_processor_id());
+- /*
+- * Allow the master to continue.
+- */
+- cpu_set(smp_processor_id(), cpu_online_map);
+- per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
+- spin_unlock(&vector_lock);
+-
+- unlock_ipi_call_lock();
+-
+- setup_secondary_clock();
+-
+- cpu_idle();
+-}
+-
+-extern volatile unsigned long init_rsp;
+-extern void (*initial_code)(void);
+-
+-#ifdef APIC_DEBUG
+-static void inquire_remote_apic(int apicid)
+-{
+- unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
+- char *names[] = { "ID", "VERSION", "SPIV" };
+- int timeout;
+- u32 status;
+-
+- printk(KERN_INFO "Inquiring remote APIC #%d...\n", apicid);
+-
+- for (i = 0; i < ARRAY_SIZE(regs); i++) {
+- printk(KERN_INFO "... APIC #%d %s: ", apicid, names[i]);
+-
+- /*
+- * Wait for idle.
+- */
+- status = safe_apic_wait_icr_idle();
+- if (status)
+- printk(KERN_CONT
+- "a previous APIC delivery may have failed\n");
+-
+- apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
+- apic_write(APIC_ICR, APIC_DM_REMRD | regs[i]);
+-
+- timeout = 0;
+- do {
+- udelay(100);
+- status = apic_read(APIC_ICR) & APIC_ICR_RR_MASK;
+- } while (status == APIC_ICR_RR_INPROG && timeout++ < 1000);
+-
+- switch (status) {
+- case APIC_ICR_RR_VALID:
+- status = apic_read(APIC_RRR);
+- printk(KERN_CONT "%08x\n", status);
+- break;
+- default:
+- printk(KERN_CONT "failed\n");
+- }
+- }
+-}
+-#endif
+-
+-/*
+- * Kick the secondary to wake up.
+- */
+-static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int start_rip)
+-{
+- unsigned long send_status, accept_status = 0;
+- int maxlvt, num_starts, j;
+-
+- Dprintk("Asserting INIT.\n");
+-
+- /*
+- * Turn INIT on target chip
+- */
+- apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+-
+- /*
+- * Send IPI
+- */
+- apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
+- | APIC_DM_INIT);
+-
+- Dprintk("Waiting for send to finish...\n");
+- send_status = safe_apic_wait_icr_idle();
+-
+- mdelay(10);
+-
+- Dprintk("Deasserting INIT.\n");
+-
+- /* Target chip */
+- apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+-
+- /* Send IPI */
+- apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
+-
+- Dprintk("Waiting for send to finish...\n");
+- send_status = safe_apic_wait_icr_idle();
+-
+- mb();
+- atomic_set(&init_deasserted, 1);
+-
+- num_starts = 2;
+-
+- /*
+- * Run STARTUP IPI loop.
+- */
+- Dprintk("#startup loops: %d.\n", num_starts);
+-
+- maxlvt = lapic_get_maxlvt();
+-
+- for (j = 1; j <= num_starts; j++) {
+- Dprintk("Sending STARTUP #%d.\n",j);
+- apic_write(APIC_ESR, 0);
+- apic_read(APIC_ESR);
+- Dprintk("After apic_write.\n");
+-
+- /*
+- * STARTUP IPI
+- */
+-
+- /* Target chip */
+- apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+-
+- /* Boot on the stack */
+- /* Kick the second */
+- apic_write(APIC_ICR, APIC_DM_STARTUP | (start_rip >> 12));
+-
+- /*
+- * Give the other CPU some time to accept the IPI.
+- */
+- udelay(300);
+-
+- Dprintk("Startup point 1.\n");
+-
+- Dprintk("Waiting for send to finish...\n");
+- send_status = safe_apic_wait_icr_idle();
+-
+- /*
+- * Give the other CPU some time to accept the IPI.
+- */
+- udelay(200);
+- /*
+- * Due to the Pentium erratum 3AP.
+- */
+- if (maxlvt > 3) {
+- apic_write(APIC_ESR, 0);
+- }
+- accept_status = (apic_read(APIC_ESR) & 0xEF);
+- if (send_status || accept_status)
+- break;
+- }
+- Dprintk("After Startup.\n");
+-
+- if (send_status)
+- printk(KERN_ERR "APIC never delivered???\n");
+- if (accept_status)
+- printk(KERN_ERR "APIC delivery error (%lx).\n", accept_status);
+-
+- return (send_status | accept_status);
+-}
+-
+-struct create_idle {
+- struct work_struct work;
+- struct task_struct *idle;
+- struct completion done;
+- int cpu;
+-};
+-
+-static void __cpuinit do_fork_idle(struct work_struct *work)
+-{
+- struct create_idle *c_idle =
+- container_of(work, struct create_idle, work);
+-
+- c_idle->idle = fork_idle(c_idle->cpu);
+- complete(&c_idle->done);
+-}
+-
+-/*
+- * Boot one CPU.
+- */
+-static int __cpuinit do_boot_cpu(int cpu, int apicid)
+-{
+- unsigned long boot_error;
+- int timeout;
+- unsigned long start_rip;
+- struct create_idle c_idle = {
+- .cpu = cpu,
+- .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
+- };
+- INIT_WORK(&c_idle.work, do_fork_idle);
+-
+- /* allocate memory for gdts of secondary cpus. Hotplug is considered */
+- if (!cpu_gdt_descr[cpu].address &&
+- !(cpu_gdt_descr[cpu].address = get_zeroed_page(GFP_KERNEL))) {
+- printk(KERN_ERR "Failed to allocate GDT for CPU %d\n", cpu);
+- return -1;
+- }
+-
+- /* Allocate node local memory for AP pdas */
+- if (cpu_pda(cpu) == &boot_cpu_pda[cpu]) {
+- struct x8664_pda *newpda, *pda;
+- int node = cpu_to_node(cpu);
+- pda = cpu_pda(cpu);
+- newpda = kmalloc_node(sizeof (struct x8664_pda), GFP_ATOMIC,
+- node);
+- if (newpda) {
+- memcpy(newpda, pda, sizeof (struct x8664_pda));
+- cpu_pda(cpu) = newpda;
+- } else
+- printk(KERN_ERR
+- "Could not allocate node local PDA for CPU %d on node %d\n",
+- cpu, node);
+- }
+-
+- alternatives_smp_switch(1);
+-
+- c_idle.idle = get_idle_for_cpu(cpu);
+-
+- if (c_idle.idle) {
+- c_idle.idle->thread.sp = (unsigned long) (((struct pt_regs *)
+- (THREAD_SIZE + task_stack_page(c_idle.idle))) - 1);
+- init_idle(c_idle.idle, cpu);
+- goto do_rest;
+- }
+-
+- /*
+- * During cold boot process, keventd thread is not spun up yet.
+- * When we do cpu hot-add, we create idle threads on the fly, we should
+- * not acquire any attributes from the calling context. Hence the clean
+- * way to create kernel_threads() is to do that from keventd().
+- * We do the current_is_keventd() due to the fact that ACPI notifier
+- * was also queuing to keventd() and when the caller is already running
+- * in context of keventd(), we would end up with locking up the keventd
+- * thread.
+- */
+- if (!keventd_up() || current_is_keventd())
+- c_idle.work.func(&c_idle.work);
+- else {
+- schedule_work(&c_idle.work);
+- wait_for_completion(&c_idle.done);
+- }
+-
+- if (IS_ERR(c_idle.idle)) {
+- printk("failed fork for CPU %d\n", cpu);
+- return PTR_ERR(c_idle.idle);
+- }
+-
+- set_idle_for_cpu(cpu, c_idle.idle);
+-
+-do_rest:
+-
+- cpu_pda(cpu)->pcurrent = c_idle.idle;
+-
+- start_rip = setup_trampoline();
+-
+- init_rsp = c_idle.idle->thread.sp;
+- load_sp0(&per_cpu(init_tss, cpu), &c_idle.idle->thread);
+- initial_code = start_secondary;
+- clear_tsk_thread_flag(c_idle.idle, TIF_FORK);
+-
+- printk(KERN_INFO "Booting processor %d/%d APIC 0x%x\n", cpu,
+- cpus_weight(cpu_present_map),
+- apicid);
+-
+- /*
+- * This grunge runs the startup process for
+- * the targeted processor.
+- */
+-
+- atomic_set(&init_deasserted, 0);
+-
+- Dprintk("Setting warm reset code and vector.\n");
+-
+- CMOS_WRITE(0xa, 0xf);
+- local_flush_tlb();
+- Dprintk("1.\n");
+- *((volatile unsigned short *) phys_to_virt(0x469)) = start_rip >> 4;
+- Dprintk("2.\n");
+- *((volatile unsigned short *) phys_to_virt(0x467)) = start_rip & 0xf;
+- Dprintk("3.\n");
+-
+- /*
+- * Be paranoid about clearing APIC errors.
+- */
+- apic_write(APIC_ESR, 0);
+- apic_read(APIC_ESR);
+-
+- /*
+- * Status is now clean
+- */
+- boot_error = 0;
+-
+- /*
+- * Starting actual IPI sequence...
+- */
+- boot_error = wakeup_secondary_via_INIT(apicid, start_rip);
+-
+- if (!boot_error) {
+- /*
+- * allow APs to start initializing.
+- */
+- Dprintk("Before Callout %d.\n", cpu);
+- cpu_set(cpu, cpu_callout_map);
+- Dprintk("After Callout %d.\n", cpu);
+-
+- /*
+- * Wait 5s total for a response
+- */
+- for (timeout = 0; timeout < 50000; timeout++) {
+- if (cpu_isset(cpu, cpu_callin_map))
+- break; /* It has booted */
+- udelay(100);
+- }
+-
+- if (cpu_isset(cpu, cpu_callin_map)) {
+- /* number CPUs logically, starting from 1 (BSP is 0) */
+- Dprintk("CPU has booted.\n");
+- } else {
+- boot_error = 1;
+- if (*((volatile unsigned char *)phys_to_virt(SMP_TRAMPOLINE_BASE))
+- == 0xA5)
+- /* trampoline started but...? */
+- printk("Stuck ??\n");
+- else
+- /* trampoline code not run */
+- printk("Not responding.\n");
+-#ifdef APIC_DEBUG
+- inquire_remote_apic(apicid);
+-#endif
+- }
+- }
+- if (boot_error) {
+- cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
+- clear_bit(cpu, (unsigned long *)&cpu_initialized); /* was set by cpu_init() */
+- clear_node_cpumask(cpu); /* was set by numa_add_cpu */
+- cpu_clear(cpu, cpu_present_map);
+- cpu_clear(cpu, cpu_possible_map);
+- per_cpu(x86_cpu_to_apicid, cpu) = BAD_APICID;
+- return -EIO;
+- }
+-
+- return 0;
+-}
+-
+-cycles_t cacheflush_time;
+-unsigned long cache_decay_ticks;
+-
+-/*
+- * Cleanup possible dangling ends...
+- */
+-static __cpuinit void smp_cleanup_boot(void)
+-{
+- /*
+- * Paranoid: Set warm reset code and vector here back
+- * to default values.
+- */
+- CMOS_WRITE(0, 0xf);
+-
+- /*
+- * Reset trampoline flag
+- */
+- *((volatile int *) phys_to_virt(0x467)) = 0;
+-}
+-
+-/*
+- * Fall back to non SMP mode after errors.
+- *
+- * RED-PEN audit/test this more. I bet there is more state messed up here.
+- */
+-static __init void disable_smp(void)
+-{
+- cpu_present_map = cpumask_of_cpu(0);
+- cpu_possible_map = cpumask_of_cpu(0);
+- if (smp_found_config)
+- phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id);
+- else
+- phys_cpu_present_map = physid_mask_of_physid(0);
+- cpu_set(0, per_cpu(cpu_sibling_map, 0));
+- cpu_set(0, per_cpu(cpu_core_map, 0));
+-}
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-
+-int additional_cpus __initdata = -1;
+-
+-/*
+- * cpu_possible_map should be static, it cannot change as cpu's
+- * are onlined, or offlined. The reason is per-cpu data-structures
+- * are allocated by some modules at init time, and dont expect to
+- * do this dynamically on cpu arrival/departure.
+- * cpu_present_map on the other hand can change dynamically.
+- * In case when cpu_hotplug is not compiled, then we resort to current
+- * behaviour, which is cpu_possible == cpu_present.
+- * - Ashok Raj
+- *
+- * Three ways to find out the number of additional hotplug CPUs:
+- * - If the BIOS specified disabled CPUs in ACPI/mptables use that.
+- * - The user can overwrite it with additional_cpus=NUM
+- * - Otherwise don't reserve additional CPUs.
+- * We do this because additional CPUs waste a lot of memory.
+- * -AK
+- */
+-__init void prefill_possible_map(void)
+-{
+- int i;
+- int possible;
+-
+- if (additional_cpus == -1) {
+- if (disabled_cpus > 0)
+- additional_cpus = disabled_cpus;
+- else
+- additional_cpus = 0;
+- }
+- possible = num_processors + additional_cpus;
+- if (possible > NR_CPUS)
+- possible = NR_CPUS;
+-
+- printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n",
+- possible,
+- max_t(int, possible - num_processors, 0));
+-
+- for (i = 0; i < possible; i++)
+- cpu_set(i, cpu_possible_map);
+-}
+-#endif
+-
+-/*
+- * Various sanity checks.
+- */
+-static int __init smp_sanity_check(unsigned max_cpus)
+-{
+- if (!physid_isset(hard_smp_processor_id(), phys_cpu_present_map)) {
+- printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
+- hard_smp_processor_id());
+- physid_set(hard_smp_processor_id(), phys_cpu_present_map);
+- }
+-
+- /*
+- * If we couldn't find an SMP configuration at boot time,
+- * get out of here now!
+- */
+- if (!smp_found_config) {
+- printk(KERN_NOTICE "SMP motherboard not detected.\n");
+- disable_smp();
+- if (APIC_init_uniprocessor())
+- printk(KERN_NOTICE "Local APIC not detected."
+- " Using dummy APIC emulation.\n");
+- return -1;
+- }
+-
+- /*
+- * Should not be necessary because the MP table should list the boot
+- * CPU too, but we do it for the sake of robustness anyway.
+- */
+- if (!physid_isset(boot_cpu_id, phys_cpu_present_map)) {
+- printk(KERN_NOTICE "weird, boot CPU (#%d) not listed by the BIOS.\n",
+- boot_cpu_id);
+- physid_set(hard_smp_processor_id(), phys_cpu_present_map);
+- }
+-
+- /*
+- * If we couldn't find a local APIC, then get out of here now!
+- */
+- if (!cpu_has_apic) {
+- printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
+- boot_cpu_id);
+- printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
+- nr_ioapics = 0;
+- return -1;
+- }
+-
+- /*
+- * If SMP should be disabled, then really disable it!
+- */
+- if (!max_cpus) {
+- printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
+- nr_ioapics = 0;
+- return -1;
+- }
+-
+- return 0;
+-}
+-
+-static void __init smp_cpu_index_default(void)
+-{
+- int i;
+- struct cpuinfo_x86 *c;
+-
+- for_each_cpu_mask(i, cpu_possible_map) {
+- c = &cpu_data(i);
+- /* mark all to hotplug */
+- c->cpu_index = NR_CPUS;
+- }
+-}
+-
+-/*
+- * Prepare for SMP bootup. The MP table or ACPI has been read
+- * earlier. Just do some sanity checking here and enable APIC mode.
+- */
+-void __init smp_prepare_cpus(unsigned int max_cpus)
+-{
+- nmi_watchdog_default();
+- smp_cpu_index_default();
+- current_cpu_data = boot_cpu_data;
+- current_thread_info()->cpu = 0; /* needed? */
+- set_cpu_sibling_map(0);
+-
+- if (smp_sanity_check(max_cpus) < 0) {
+- printk(KERN_INFO "SMP disabled\n");
+- disable_smp();
+- return;
+- }
+-
+-
+- /*
+- * Switch from PIC to APIC mode.
+- */
+- setup_local_APIC();
+-
+- /*
+- * Enable IO APIC before setting up error vector
+- */
+- if (!skip_ioapic_setup && nr_ioapics)
+- enable_IO_APIC();
+- end_local_APIC_setup();
+-
+- if (GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_id) {
+- panic("Boot APIC ID in local APIC unexpected (%d vs %d)",
+- GET_APIC_ID(apic_read(APIC_ID)), boot_cpu_id);
+- /* Or can we switch back to PIC here? */
+- }
+-
+- /*
+- * Now start the IO-APICs
+- */
+- if (!skip_ioapic_setup && nr_ioapics)
+- setup_IO_APIC();
+- else
+- nr_ioapics = 0;
+-
+- /*
+- * Set up local APIC timer on boot CPU.
+- */
+-
+- setup_boot_clock();
+-}
+-
+-/*
+- * Early setup to make printk work.
+- */
+-void __init smp_prepare_boot_cpu(void)
+-{
+- int me = smp_processor_id();
+- /* already set me in cpu_online_map in boot_cpu_init() */
+- cpu_set(me, cpu_callout_map);
+- per_cpu(cpu_state, me) = CPU_ONLINE;
+-}
+-
+-/*
+- * Entry point to boot a CPU.
+- */
+-int __cpuinit __cpu_up(unsigned int cpu)
+-{
+- int apicid = cpu_present_to_apicid(cpu);
+- unsigned long flags;
+- int err;
+-
+- WARN_ON(irqs_disabled());
+-
+- Dprintk("++++++++++++++++++++=_---CPU UP %u\n", cpu);
+-
+- if (apicid == BAD_APICID || apicid == boot_cpu_id ||
+- !physid_isset(apicid, phys_cpu_present_map)) {
+- printk("__cpu_up: bad cpu %d\n", cpu);
+- return -EINVAL;
+- }
+-
+- /*
+- * Already booted CPU?
+- */
+- if (cpu_isset(cpu, cpu_callin_map)) {
+- Dprintk("do_boot_cpu %d Already started\n", cpu);
+- return -ENOSYS;
+- }
+-
+- /*
+- * Save current MTRR state in case it was changed since early boot
+- * (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync:
+- */
+- mtrr_save_state();
+-
+- per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
+- /* Boot it! */
+- err = do_boot_cpu(cpu, apicid);
+- if (err < 0) {
+- Dprintk("do_boot_cpu failed %d\n", err);
+- return err;
+- }
+-
+- /* Unleash the CPU! */
+- Dprintk("waiting for cpu %d\n", cpu);
+-
+- /*
+- * Make sure and check TSC sync:
+- */
+- local_irq_save(flags);
+- check_tsc_sync_source(cpu);
+- local_irq_restore(flags);
+-
+- while (!cpu_isset(cpu, cpu_online_map))
+- cpu_relax();
+- err = 0;
+-
+- return err;
+-}
+-
+-/*
+- * Finish the SMP boot.
+- */
+-void __init smp_cpus_done(unsigned int max_cpus)
+-{
+- smp_cleanup_boot();
+- setup_ioapic_dest();
+- check_nmi_watchdog();
+-}
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-
+-static void remove_siblinginfo(int cpu)
+-{
+- int sibling;
+- struct cpuinfo_x86 *c = &cpu_data(cpu);
+-
+- for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) {
+- cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
+- /*
+- * last thread sibling in this cpu core going down
+- */
+- if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1)
+- cpu_data(sibling).booted_cores--;
+- }
+-
+- for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu))
+- cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
+- cpus_clear(per_cpu(cpu_sibling_map, cpu));
+- cpus_clear(per_cpu(cpu_core_map, cpu));
+- c->phys_proc_id = 0;
+- c->cpu_core_id = 0;
+- cpu_clear(cpu, cpu_sibling_setup_map);
+-}
+-
+-static void __ref remove_cpu_from_maps(void)
+-{
+- int cpu = smp_processor_id();
+-
+- cpu_clear(cpu, cpu_callout_map);
+- cpu_clear(cpu, cpu_callin_map);
+- clear_bit(cpu, (unsigned long *)&cpu_initialized); /* was set by cpu_init() */
+- clear_node_cpumask(cpu);
+-}
+-
+-int __cpu_disable(void)
+-{
+- int cpu = smp_processor_id();
+-
+- /*
+- * Perhaps use cpufreq to drop frequency, but that could go
+- * into generic code.
+- *
+- * We won't take down the boot processor on i386 due to some
+- * interrupts only being able to be serviced by the BSP.
+- * Especially so if we're not using an IOAPIC -zwane
+- */
+- if (cpu == 0)
+- return -EBUSY;
+-
+- if (nmi_watchdog == NMI_LOCAL_APIC)
+- stop_apic_nmi_watchdog(NULL);
+- clear_local_APIC();
+-
+- /*
+- * HACK:
+- * Allow any queued timer interrupts to get serviced
+- * This is only a temporary solution until we cleanup
+- * fixup_irqs as we do for IA64.
+- */
+- local_irq_enable();
+- mdelay(1);
+-
+- local_irq_disable();
+- remove_siblinginfo(cpu);
+-
+- spin_lock(&vector_lock);
+- /* It's now safe to remove this processor from the online map */
+- cpu_clear(cpu, cpu_online_map);
+- spin_unlock(&vector_lock);
+- remove_cpu_from_maps();
+- fixup_irqs(cpu_online_map);
+- return 0;
+-}
+-
+-void __cpu_die(unsigned int cpu)
+-{
+- /* We don't do anything here: idle task is faking death itself. */
+- unsigned int i;
+-
+- for (i = 0; i < 10; i++) {
+- /* They ack this in play_dead by setting CPU_DEAD */
+- if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
+- printk ("CPU %d is now offline\n", cpu);
+- if (1 == num_online_cpus())
+- alternatives_smp_switch(0);
+- return;
+- }
+- msleep(100);
+- }
+- printk(KERN_ERR "CPU %u didn't die...\n", cpu);
+-}
+-
+-static __init int setup_additional_cpus(char *s)
+-{
+- return s && get_option(&s, &additional_cpus) ? 0 : -EINVAL;
+-}
+-early_param("additional_cpus", setup_additional_cpus);
+-
+-#else /* ... !CONFIG_HOTPLUG_CPU */
+-
+-int __cpu_disable(void)
+-{
+- return -ENOSYS;
+-}
+-
+-void __cpu_die(unsigned int cpu)
+-{
+- /* We said "no" in __cpu_disable */
+- BUG();
+-}
+-#endif /* CONFIG_HOTPLUG_CPU */
+diff --git a/arch/x86/kernel/smpcommon.c b/arch/x86/kernel/smpcommon.c
+new file mode 100644
+index 0000000..3449064
+--- /dev/null
++++ b/arch/x86/kernel/smpcommon.c
+@@ -0,0 +1,83 @@
++/*
++ * SMP stuff which is common to all sub-architectures.
++ */
++#include <linux/module.h>
++#include <asm/smp.h>
++
++#ifdef CONFIG_X86_32
++DEFINE_PER_CPU(unsigned long, this_cpu_off);
++EXPORT_PER_CPU_SYMBOL(this_cpu_off);
++
++/* Initialize the CPU's GDT. This is either the boot CPU doing itself
++ (still using the master per-cpu area), or a CPU doing it for a
++ secondary which will soon come up. */
++__cpuinit void init_gdt(int cpu)
++{
++ struct desc_struct *gdt = get_cpu_gdt_table(cpu);
++
++ pack_descriptor(&gdt[GDT_ENTRY_PERCPU],
++ __per_cpu_offset[cpu], 0xFFFFF,
++ 0x2 | DESCTYPE_S, 0x8);
++
++ gdt[GDT_ENTRY_PERCPU].s = 1;
++
++ per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu];
++ per_cpu(cpu_number, cpu) = cpu;
++}
++#endif
++
++/**
++ * smp_call_function(): Run a function on all other CPUs.
++ * @func: The function to run. This must be fast and non-blocking.
++ * @info: An arbitrary pointer to pass to the function.
++ * @nonatomic: Unused.
++ * @wait: If true, wait (atomically) until function has completed on other CPUs.
++ *
++ * Returns 0 on success, else a negative status code.
++ *
++ * If @wait is true, then returns once @func has returned; otherwise
++ * it returns just before the target cpu calls @func.
++ *
++ * You must not call this function with disabled interrupts or from a
++ * hardware interrupt handler or from a bottom half handler.
++ */
++int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
++ int wait)
++{
++ return smp_call_function_mask(cpu_online_map, func, info, wait);
++}
++EXPORT_SYMBOL(smp_call_function);
++
++/**
++ * smp_call_function_single - Run a function on a specific CPU
++ * @cpu: The target CPU. Cannot be the calling CPU.
++ * @func: The function to run. This must be fast and non-blocking.
++ * @info: An arbitrary pointer to pass to the function.
++ * @nonatomic: Unused.
++ * @wait: If true, wait until function has completed on other CPUs.
++ *
++ * Returns 0 on success, else a negative status code.
++ *
++ * If @wait is true, then returns once @func has returned; otherwise
++ * it returns just before the target cpu calls @func.
++ */
++int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
++ int nonatomic, int wait)
++{
++ /* prevent preemption and reschedule on another processor */
++ int ret;
++ int me = get_cpu();
++ if (cpu == me) {
++ local_irq_disable();
++ func(info);
++ local_irq_enable();
++ put_cpu();
++ return 0;
++ }
++
++ ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
++
++ put_cpu();
++ return ret;
++}
++EXPORT_SYMBOL(smp_call_function_single);
+diff --git a/arch/x86/kernel/smpcommon_32.c b/arch/x86/kernel/smpcommon_32.c
+index 8bc38af..8b13789 100644
+--- a/arch/x86/kernel/smpcommon_32.c
++++ b/arch/x86/kernel/smpcommon_32.c
+@@ -1,82 +1 @@
+-/*
+- * SMP stuff which is common to all sub-architectures.
+- */
+-#include <linux/module.h>
+-#include <asm/smp.h>
+
+-DEFINE_PER_CPU(unsigned long, this_cpu_off);
+-EXPORT_PER_CPU_SYMBOL(this_cpu_off);
+-
+-/* Initialize the CPU's GDT. This is either the boot CPU doing itself
+- (still using the master per-cpu area), or a CPU doing it for a
+- secondary which will soon come up. */
+-__cpuinit void init_gdt(int cpu)
+-{
+- struct desc_struct *gdt = get_cpu_gdt_table(cpu);
+-
+- pack_descriptor(&gdt[GDT_ENTRY_PERCPU],
+- __per_cpu_offset[cpu], 0xFFFFF,
+- 0x2 | DESCTYPE_S, 0x8);
+-
+- gdt[GDT_ENTRY_PERCPU].s = 1;
+-
+- per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu];
+- per_cpu(cpu_number, cpu) = cpu;
+-}
+-
+-
+-/**
+- * smp_call_function(): Run a function on all other CPUs.
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @nonatomic: Unused.
+- * @wait: If true, wait (atomically) until function has completed on other CPUs.
+- *
+- * Returns 0 on success, else a negative status code.
+- *
+- * If @wait is true, then returns once @func has returned; otherwise
+- * it returns just before the target cpu calls @func.
+- *
+- * You must not call this function with disabled interrupts or from a
+- * hardware interrupt handler or from a bottom half handler.
+- */
+-int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
+- int wait)
+-{
+- return smp_call_function_mask(cpu_online_map, func, info, wait);
+-}
+-EXPORT_SYMBOL(smp_call_function);
+-
+-/**
+- * smp_call_function_single - Run a function on a specific CPU
+- * @cpu: The target CPU. Cannot be the calling CPU.
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @nonatomic: Unused.
+- * @wait: If true, wait until function has completed on other CPUs.
+- *
+- * Returns 0 on success, else a negative status code.
+- *
+- * If @wait is true, then returns once @func has returned; otherwise
+- * it returns just before the target cpu calls @func.
+- */
+-int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
+- int nonatomic, int wait)
+-{
+- /* prevent preemption and reschedule on another processor */
+- int ret;
+- int me = get_cpu();
+- if (cpu == me) {
+- local_irq_disable();
+- func(info);
+- local_irq_enable();
+- put_cpu();
+- return 0;
+- }
+-
+- ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
+-
+- put_cpu();
+- return ret;
+-}
+-EXPORT_SYMBOL(smp_call_function_single);
+diff --git a/arch/x86/kernel/srat_32.c b/arch/x86/kernel/srat_32.c
+index b72e613..70e4a37 100644
+--- a/arch/x86/kernel/srat_32.c
++++ b/arch/x86/kernel/srat_32.c
+@@ -277,14 +277,14 @@ int __init get_memcfg_from_srat(void)
+ rsdp_address = acpi_os_get_root_pointer();
+ if (!rsdp_address) {
+ printk("%s: System description tables not found\n",
+- __FUNCTION__);
++ __func__);
+ goto out_err;
+ }
+
+- printk("%s: assigning address to rsdp\n", __FUNCTION__);
++ printk("%s: assigning address to rsdp\n", __func__);
+ rsdp = (struct acpi_table_rsdp *)(u32)rsdp_address;
+ if (!rsdp) {
+- printk("%s: Didn't find ACPI root!\n", __FUNCTION__);
++ printk("%s: Didn't find ACPI root!\n", __func__);
+ goto out_err;
+ }
+
+@@ -292,7 +292,7 @@ int __init get_memcfg_from_srat(void)
+ rsdp->oem_id);
+
+ if (strncmp(rsdp->signature, ACPI_SIG_RSDP,strlen(ACPI_SIG_RSDP))) {
+- printk(KERN_WARNING "%s: RSDP table signature incorrect\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: RSDP table signature incorrect\n", __func__);
+ goto out_err;
+ }
+
+@@ -302,7 +302,7 @@ int __init get_memcfg_from_srat(void)
+ if (!rsdt) {
+ printk(KERN_WARNING
+ "%s: ACPI: Invalid root system description tables (RSDT)\n",
+- __FUNCTION__);
++ __func__);
+ goto out_err;
+ }
+
+diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c
+index 071ff47..92c20fe 100644
+--- a/arch/x86/kernel/step.c
++++ b/arch/x86/kernel/step.c
+@@ -148,7 +148,7 @@ static void write_debugctlmsr(struct task_struct *child, unsigned long val)
+ if (child != current)
+ return;
+
+- wrmsrl(MSR_IA32_DEBUGCTLMSR, val);
++ update_debugctlmsr(val);
+ }
+
+ /*
+diff --git a/arch/x86/kernel/summit_32.c b/arch/x86/kernel/summit_32.c
+index 72f4634..ae75109 100644
+--- a/arch/x86/kernel/summit_32.c
++++ b/arch/x86/kernel/summit_32.c
+@@ -29,49 +29,54 @@
+ #include <linux/mm.h>
+ #include <linux/init.h>
+ #include <asm/io.h>
++#include <asm/bios_ebda.h>
+ #include <asm/mach-summit/mach_mpparse.h>
+
+ static struct rio_table_hdr *rio_table_hdr __initdata;
+ static struct scal_detail *scal_devs[MAX_NUMNODES] __initdata;
+ static struct rio_detail *rio_devs[MAX_NUMNODES*4] __initdata;
+
++static int mp_bus_id_to_node[MAX_MP_BUSSES] __initdata;
++
+ static int __init setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus)
+ {
+ int twister = 0, node = 0;
+ int i, bus, num_buses;
+
+- for(i = 0; i < rio_table_hdr->num_rio_dev; i++){
+- if (rio_devs[i]->node_id == rio_devs[wpeg_num]->owner_id){
++ for (i = 0; i < rio_table_hdr->num_rio_dev; i++) {
++ if (rio_devs[i]->node_id == rio_devs[wpeg_num]->owner_id) {
+ twister = rio_devs[i]->owner_id;
+ break;
+ }
+ }
+- if (i == rio_table_hdr->num_rio_dev){
+- printk(KERN_ERR "%s: Couldn't find owner Cyclone for Winnipeg!\n", __FUNCTION__);
++ if (i == rio_table_hdr->num_rio_dev) {
++ printk(KERN_ERR "%s: Couldn't find owner Cyclone for Winnipeg!\n", __func__);
+ return last_bus;
+ }
+
+- for(i = 0; i < rio_table_hdr->num_scal_dev; i++){
+- if (scal_devs[i]->node_id == twister){
++ for (i = 0; i < rio_table_hdr->num_scal_dev; i++) {
++ if (scal_devs[i]->node_id == twister) {
+ node = scal_devs[i]->node_id;
+ break;
+ }
+ }
+- if (i == rio_table_hdr->num_scal_dev){
+- printk(KERN_ERR "%s: Couldn't find owner Twister for Cyclone!\n", __FUNCTION__);
++ if (i == rio_table_hdr->num_scal_dev) {
++ printk(KERN_ERR "%s: Couldn't find owner Twister for Cyclone!\n", __func__);
+ return last_bus;
+ }
+
+- switch (rio_devs[wpeg_num]->type){
++ switch (rio_devs[wpeg_num]->type) {
+ case CompatWPEG:
+- /* The Compatibility Winnipeg controls the 2 legacy buses,
++ /*
++ * The Compatibility Winnipeg controls the 2 legacy buses,
+ * the 66MHz PCI bus [2 slots] and the 2 "extra" buses in case
+ * a PCI-PCI bridge card is used in either slot: total 5 buses.
+ */
+ num_buses = 5;
+ break;
+ case AltWPEG:
+- /* The Alternate Winnipeg controls the 2 133MHz buses [1 slot
++ /*
++ * The Alternate Winnipeg controls the 2 133MHz buses [1 slot
+ * each], their 2 "extra" buses, the 100MHz bus [2 slots] and
+ * the "extra" buses for each of those slots: total 7 buses.
+ */
+@@ -79,17 +84,18 @@ static int __init setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus)
+ break;
+ case LookOutAWPEG:
+ case LookOutBWPEG:
+- /* A Lookout Winnipeg controls 3 100MHz buses [2 slots each]
++ /*
++ * A Lookout Winnipeg controls 3 100MHz buses [2 slots each]
+ * & the "extra" buses for each of those slots: total 9 buses.
+ */
+ num_buses = 9;
+ break;
+ default:
+- printk(KERN_INFO "%s: Unsupported Winnipeg type!\n", __FUNCTION__);
++ printk(KERN_INFO "%s: Unsupported Winnipeg type!\n", __func__);
+ return last_bus;
+ }
+
+- for(bus = last_bus; bus < last_bus + num_buses; bus++)
++ for (bus = last_bus; bus < last_bus + num_buses; bus++)
+ mp_bus_id_to_node[bus] = node;
+ return bus;
+ }
+@@ -99,14 +105,14 @@ static int __init build_detail_arrays(void)
+ unsigned long ptr;
+ int i, scal_detail_size, rio_detail_size;
+
+- if (rio_table_hdr->num_scal_dev > MAX_NUMNODES){
+- printk(KERN_WARNING "%s: MAX_NUMNODES too low! Defined as %d, but system has %d nodes.\n", __FUNCTION__, MAX_NUMNODES, rio_table_hdr->num_scal_dev);
++ if (rio_table_hdr->num_scal_dev > MAX_NUMNODES) {
++ printk(KERN_WARNING "%s: MAX_NUMNODES too low! Defined as %d, but system has %d nodes.\n", __func__, MAX_NUMNODES, rio_table_hdr->num_scal_dev);
+ return 0;
+ }
+
+- switch (rio_table_hdr->version){
++ switch (rio_table_hdr->version) {
+ default:
+- printk(KERN_WARNING "%s: Invalid Rio Grande Table Version: %d\n", __FUNCTION__, rio_table_hdr->version);
++ printk(KERN_WARNING "%s: Invalid Rio Grande Table Version: %d\n", __func__, rio_table_hdr->version);
+ return 0;
+ case 2:
+ scal_detail_size = 11;
+@@ -119,10 +125,10 @@ static int __init build_detail_arrays(void)
+ }
+
+ ptr = (unsigned long)rio_table_hdr + 3;
+- for(i = 0; i < rio_table_hdr->num_scal_dev; i++, ptr += scal_detail_size)
++ for (i = 0; i < rio_table_hdr->num_scal_dev; i++, ptr += scal_detail_size)
+ scal_devs[i] = (struct scal_detail *)ptr;
+
+- for(i = 0; i < rio_table_hdr->num_rio_dev; i++, ptr += rio_detail_size)
++ for (i = 0; i < rio_table_hdr->num_rio_dev; i++, ptr += rio_detail_size)
+ rio_devs[i] = (struct rio_detail *)ptr;
+
+ return 1;
+@@ -135,14 +141,14 @@ void __init setup_summit(void)
+ int i, next_wpeg, next_bus = 0;
+
+ /* The pointer to the EBDA is stored in the word @ phys 0x40E(40:0E) */
+- ptr = *(unsigned short *)phys_to_virt(0x40Eul);
+- ptr = (unsigned long)phys_to_virt(ptr << 4);
++ ptr = get_bios_ebda();
++ ptr = (unsigned long)phys_to_virt(ptr);
+
+ rio_table_hdr = NULL;
+ offset = 0x180;
+- while (offset){
++ while (offset) {
+ /* The block id is stored in the 2nd word */
+- if (*((unsigned short *)(ptr + offset + 2)) == 0x4752){
++ if (*((unsigned short *)(ptr + offset + 2)) == 0x4752) {
+ /* set the pointer past the offset & block id */
+ rio_table_hdr = (struct rio_table_hdr *)(ptr + offset + 4);
+ break;
+@@ -150,8 +156,8 @@ void __init setup_summit(void)
+ /* The next offset is stored in the 1st word. 0 means no more */
+ offset = *((unsigned short *)(ptr + offset));
+ }
+- if (!rio_table_hdr){
+- printk(KERN_ERR "%s: Unable to locate Rio Grande Table in EBDA - bailing!\n", __FUNCTION__);
++ if (!rio_table_hdr) {
++ printk(KERN_ERR "%s: Unable to locate Rio Grande Table in EBDA - bailing!\n", __func__);
+ return;
+ }
+
+@@ -161,8 +167,8 @@ void __init setup_summit(void)
+ /* The first Winnipeg we're looking for has an index of 0 */
+ next_wpeg = 0;
+ do {
+- for(i = 0; i < rio_table_hdr->num_rio_dev; i++){
+- if (is_WPEG(rio_devs[i]) && rio_devs[i]->WP_index == next_wpeg){
++ for (i = 0; i < rio_table_hdr->num_rio_dev; i++) {
++ if (is_WPEG(rio_devs[i]) && rio_devs[i]->WP_index == next_wpeg) {
+ /* It's the Winnipeg we're looking for! */
+ next_bus = setup_pci_node_map_for_wpeg(i, next_bus);
+ next_wpeg++;
+diff --git a/arch/x86/kernel/syscall_64.c b/arch/x86/kernel/syscall_64.c
+index 9d498c2..170d43c 100644
+--- a/arch/x86/kernel/syscall_64.c
++++ b/arch/x86/kernel/syscall_64.c
+@@ -1,4 +1,4 @@
+-/* System call table for x86-64. */
++/* System call table for x86-64. */
+
+ #include <linux/linkage.h>
+ #include <linux/sys.h>
+@@ -7,20 +7,23 @@
+
+ #define __NO_STUBS
+
+-#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
++#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
+ #undef _ASM_X86_64_UNISTD_H_
+ #include <asm/unistd_64.h>
+
+ #undef __SYSCALL
+-#define __SYSCALL(nr, sym) [ nr ] = sym,
++#define __SYSCALL(nr, sym) [nr] = sym,
+ #undef _ASM_X86_64_UNISTD_H_
+
+-typedef void (*sys_call_ptr_t)(void);
++typedef void (*sys_call_ptr_t)(void);
+
+ extern void sys_ni_syscall(void);
+
+ const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
+- /* Smells like a like a compiler bug -- it doesn't work when the & below is removed. */
++ /*
++ *Smells like a like a compiler bug -- it doesn't work
++ *when the & below is removed.
++ */
+ [0 ... __NR_syscall_max] = &sys_ni_syscall,
+ #include <asm/unistd_64.h>
+ };
+diff --git a/arch/x86/kernel/test_nx.c b/arch/x86/kernel/test_nx.c
+index 10b8a6f..787a5e4 100644
+--- a/arch/x86/kernel/test_nx.c
++++ b/arch/x86/kernel/test_nx.c
+@@ -11,6 +11,8 @@
+ */
+ #include <linux/module.h>
+ #include <linux/sort.h>
++#include <linux/slab.h>
++
+ #include <asm/uaccess.h>
+ #include <asm/asm.h>
+
+diff --git a/arch/x86/kernel/time_32.c b/arch/x86/kernel/time_32.c
+index 1a89e93..2ff21f3 100644
+--- a/arch/x86/kernel/time_32.c
++++ b/arch/x86/kernel/time_32.c
+@@ -115,7 +115,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
+ return IRQ_HANDLED;
+ }
+
+-extern void (*late_time_init)(void);
+ /* Duplicate of time_init() below, with hpet_enable part added */
+ void __init hpet_time_init(void)
+ {
+diff --git a/arch/x86/kernel/tlb_32.c b/arch/x86/kernel/tlb_32.c
+new file mode 100644
+index 0000000..9bb2363
+--- /dev/null
++++ b/arch/x86/kernel/tlb_32.c
+@@ -0,0 +1,243 @@
++#include <linux/spinlock.h>
++#include <linux/cpu.h>
++#include <linux/interrupt.h>
++
++#include <asm/tlbflush.h>
++
++DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate)
++ ____cacheline_aligned = { &init_mm, 0, };
++
++/* must come after the send_IPI functions above for inlining */
++#include <mach_ipi.h>
++
++/*
++ * Smarter SMP flushing macros.
++ * c/o Linus Torvalds.
++ *
++ * These mean you can really definitely utterly forget about
++ * writing to user space from interrupts. (Its not allowed anyway).
++ *
++ * Optimizations Manfred Spraul <manfred at colorfullife.com>
++ */
++
++static cpumask_t flush_cpumask;
++static struct mm_struct *flush_mm;
++static unsigned long flush_va;
++static DEFINE_SPINLOCK(tlbstate_lock);
++
++/*
++ * We cannot call mmdrop() because we are in interrupt context,
++ * instead update mm->cpu_vm_mask.
++ *
++ * We need to reload %cr3 since the page tables may be going
++ * away from under us..
++ */
++void leave_mm(int cpu)
++{
++ if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
++ BUG();
++ cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask);
++ load_cr3(swapper_pg_dir);
++}
++EXPORT_SYMBOL_GPL(leave_mm);
++
++/*
++ *
++ * The flush IPI assumes that a thread switch happens in this order:
++ * [cpu0: the cpu that switches]
++ * 1) switch_mm() either 1a) or 1b)
++ * 1a) thread switch to a different mm
++ * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
++ * Stop ipi delivery for the old mm. This is not synchronized with
++ * the other cpus, but smp_invalidate_interrupt ignore flush ipis
++ * for the wrong mm, and in the worst case we perform a superfluous
++ * tlb flush.
++ * 1a2) set cpu_tlbstate to TLBSTATE_OK
++ * Now the smp_invalidate_interrupt won't call leave_mm if cpu0
++ * was in lazy tlb mode.
++ * 1a3) update cpu_tlbstate[].active_mm
++ * Now cpu0 accepts tlb flushes for the new mm.
++ * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
++ * Now the other cpus will send tlb flush ipis.
++ * 1a4) change cr3.
++ * 1b) thread switch without mm change
++ * cpu_tlbstate[].active_mm is correct, cpu0 already handles
++ * flush ipis.
++ * 1b1) set cpu_tlbstate to TLBSTATE_OK
++ * 1b2) test_and_set the cpu bit in cpu_vm_mask.
++ * Atomically set the bit [other cpus will start sending flush ipis],
++ * and test the bit.
++ * 1b3) if the bit was 0: leave_mm was called, flush the tlb.
++ * 2) switch %%esp, ie current
++ *
++ * The interrupt must handle 2 special cases:
++ * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm.
++ * - the cpu performs speculative tlb reads, i.e. even if the cpu only
++ * runs in kernel space, the cpu could load tlb entries for user space
++ * pages.
++ *
++ * The good news is that cpu_tlbstate is local to each cpu, no
++ * write/read ordering problems.
++ */
++
++/*
++ * TLB flush IPI:
++ *
++ * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
++ * 2) Leave the mm if we are in the lazy tlb mode.
++ */
++
++void smp_invalidate_interrupt(struct pt_regs *regs)
++{
++ unsigned long cpu;
++
++ cpu = get_cpu();
++
++ if (!cpu_isset(cpu, flush_cpumask))
++ goto out;
++ /*
++ * This was a BUG() but until someone can quote me the
++ * line from the intel manual that guarantees an IPI to
++ * multiple CPUs is retried _only_ on the erroring CPUs
++ * its staying as a return
++ *
++ * BUG();
++ */
++
++ if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) {
++ if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) {
++ if (flush_va == TLB_FLUSH_ALL)
++ local_flush_tlb();
++ else
++ __flush_tlb_one(flush_va);
++ } else
++ leave_mm(cpu);
++ }
++ ack_APIC_irq();
++ smp_mb__before_clear_bit();
++ cpu_clear(cpu, flush_cpumask);
++ smp_mb__after_clear_bit();
++out:
++ put_cpu_no_resched();
++ __get_cpu_var(irq_stat).irq_tlb_count++;
++}
++
++void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
++ unsigned long va)
++{
++ cpumask_t cpumask = *cpumaskp;
++
++ /*
++ * A couple of (to be removed) sanity checks:
++ *
++ * - current CPU must not be in mask
++ * - mask must exist :)
++ */
++ BUG_ON(cpus_empty(cpumask));
++ BUG_ON(cpu_isset(smp_processor_id(), cpumask));
++ BUG_ON(!mm);
++
++#ifdef CONFIG_HOTPLUG_CPU
++ /* If a CPU which we ran on has gone down, OK. */
++ cpus_and(cpumask, cpumask, cpu_online_map);
++ if (unlikely(cpus_empty(cpumask)))
++ return;
++#endif
++
++ /*
++ * i'm not happy about this global shared spinlock in the
++ * MM hot path, but we'll see how contended it is.
++ * AK: x86-64 has a faster method that could be ported.
++ */
++ spin_lock(&tlbstate_lock);
++
++ flush_mm = mm;
++ flush_va = va;
++ cpus_or(flush_cpumask, cpumask, flush_cpumask);
++ /*
++ * We have to send the IPI only to
++ * CPUs affected.
++ */
++ send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);
++
++ while (!cpus_empty(flush_cpumask))
++ /* nothing. lockup detection does not belong here */
++ cpu_relax();
++
++ flush_mm = NULL;
++ flush_va = 0;
++ spin_unlock(&tlbstate_lock);
++}
++
++void flush_tlb_current_task(void)
++{
++ struct mm_struct *mm = current->mm;
++ cpumask_t cpu_mask;
++
++ preempt_disable();
++ cpu_mask = mm->cpu_vm_mask;
++ cpu_clear(smp_processor_id(), cpu_mask);
++
++ local_flush_tlb();
++ if (!cpus_empty(cpu_mask))
++ flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
++ preempt_enable();
++}
++
++void flush_tlb_mm(struct mm_struct *mm)
++{
++ cpumask_t cpu_mask;
++
++ preempt_disable();
++ cpu_mask = mm->cpu_vm_mask;
++ cpu_clear(smp_processor_id(), cpu_mask);
++
++ if (current->active_mm == mm) {
++ if (current->mm)
++ local_flush_tlb();
++ else
++ leave_mm(smp_processor_id());
++ }
++ if (!cpus_empty(cpu_mask))
++ flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
++
++ preempt_enable();
++}
++
++void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
++{
++ struct mm_struct *mm = vma->vm_mm;
++ cpumask_t cpu_mask;
++
++ preempt_disable();
++ cpu_mask = mm->cpu_vm_mask;
++ cpu_clear(smp_processor_id(), cpu_mask);
++
++ if (current->active_mm == mm) {
++ if (current->mm)
++ __flush_tlb_one(va);
++ else
++ leave_mm(smp_processor_id());
++ }
++
++ if (!cpus_empty(cpu_mask))
++ flush_tlb_others(cpu_mask, mm, va);
++
++ preempt_enable();
++}
++EXPORT_SYMBOL(flush_tlb_page);
++
++static void do_flush_tlb_all(void *info)
++{
++ unsigned long cpu = smp_processor_id();
++
++ __flush_tlb_all();
++ if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY)
++ leave_mm(cpu);
++}
++
++void flush_tlb_all(void)
++{
++ on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
++}
++
+diff --git a/arch/x86/kernel/tlb_64.c b/arch/x86/kernel/tlb_64.c
+new file mode 100644
+index 0000000..a1f07d7
+--- /dev/null
++++ b/arch/x86/kernel/tlb_64.c
+@@ -0,0 +1,274 @@
++#include <linux/init.h>
++
++#include <linux/mm.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/smp.h>
++#include <linux/kernel_stat.h>
++#include <linux/mc146818rtc.h>
++#include <linux/interrupt.h>
++
++#include <asm/mtrr.h>
++#include <asm/pgalloc.h>
++#include <asm/tlbflush.h>
++#include <asm/mmu_context.h>
++#include <asm/proto.h>
++#include <asm/apicdef.h>
++#include <asm/idle.h>
++
++#include <mach_ipi.h>
++/*
++ * Smarter SMP flushing macros.
++ * c/o Linus Torvalds.
++ *
++ * These mean you can really definitely utterly forget about
++ * writing to user space from interrupts. (Its not allowed anyway).
++ *
++ * Optimizations Manfred Spraul <manfred at colorfullife.com>
++ *
++ * More scalable flush, from Andi Kleen
++ *
++ * To avoid global state use 8 different call vectors.
++ * Each CPU uses a specific vector to trigger flushes on other
++ * CPUs. Depending on the received vector the target CPUs look into
++ * the right per cpu variable for the flush data.
++ *
++ * With more than 8 CPUs they are hashed to the 8 available
++ * vectors. The limited global vector space forces us to this right now.
++ * In future when interrupts are split into per CPU domains this could be
++ * fixed, at the cost of triggering multiple IPIs in some cases.
++ */
++
++union smp_flush_state {
++ struct {
++ cpumask_t flush_cpumask;
++ struct mm_struct *flush_mm;
++ unsigned long flush_va;
++ spinlock_t tlbstate_lock;
++ };
++ char pad[SMP_CACHE_BYTES];
++} ____cacheline_aligned;
++
++/* State is put into the per CPU data section, but padded
++ to a full cache line because other CPUs can access it and we don't
++ want false sharing in the per cpu data segment. */
++static DEFINE_PER_CPU(union smp_flush_state, flush_state);
++
++/*
++ * We cannot call mmdrop() because we are in interrupt context,
++ * instead update mm->cpu_vm_mask.
++ */
++void leave_mm(int cpu)
++{
++ if (read_pda(mmu_state) == TLBSTATE_OK)
++ BUG();
++ cpu_clear(cpu, read_pda(active_mm)->cpu_vm_mask);
++ load_cr3(swapper_pg_dir);
++}
++EXPORT_SYMBOL_GPL(leave_mm);
++
++/*
++ *
++ * The flush IPI assumes that a thread switch happens in this order:
++ * [cpu0: the cpu that switches]
++ * 1) switch_mm() either 1a) or 1b)
++ * 1a) thread switch to a different mm
++ * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
++ * Stop ipi delivery for the old mm. This is not synchronized with
++ * the other cpus, but smp_invalidate_interrupt ignore flush ipis
++ * for the wrong mm, and in the worst case we perform a superfluous
++ * tlb flush.
++ * 1a2) set cpu mmu_state to TLBSTATE_OK
++ * Now the smp_invalidate_interrupt won't call leave_mm if cpu0
++ * was in lazy tlb mode.
++ * 1a3) update cpu active_mm
++ * Now cpu0 accepts tlb flushes for the new mm.
++ * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
++ * Now the other cpus will send tlb flush ipis.
++ * 1a4) change cr3.
++ * 1b) thread switch without mm change
++ * cpu active_mm is correct, cpu0 already handles
++ * flush ipis.
++ * 1b1) set cpu mmu_state to TLBSTATE_OK
++ * 1b2) test_and_set the cpu bit in cpu_vm_mask.
++ * Atomically set the bit [other cpus will start sending flush ipis],
++ * and test the bit.
++ * 1b3) if the bit was 0: leave_mm was called, flush the tlb.
++ * 2) switch %%esp, ie current
++ *
++ * The interrupt must handle 2 special cases:
++ * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm.
++ * - the cpu performs speculative tlb reads, i.e. even if the cpu only
++ * runs in kernel space, the cpu could load tlb entries for user space
++ * pages.
++ *
++ * The good news is that cpu mmu_state is local to each cpu, no
++ * write/read ordering problems.
++ */
++
++/*
++ * TLB flush IPI:
++ *
++ * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
++ * 2) Leave the mm if we are in the lazy tlb mode.
++ *
++ * Interrupts are disabled.
++ */
++
++asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs)
++{
++ int cpu;
++ int sender;
++ union smp_flush_state *f;
++
++ cpu = smp_processor_id();
++ /*
++ * orig_rax contains the negated interrupt vector.
++ * Use that to determine where the sender put the data.
++ */
++ sender = ~regs->orig_ax - INVALIDATE_TLB_VECTOR_START;
++ f = &per_cpu(flush_state, sender);
++
++ if (!cpu_isset(cpu, f->flush_cpumask))
++ goto out;
++ /*
++ * This was a BUG() but until someone can quote me the
++ * line from the intel manual that guarantees an IPI to
++ * multiple CPUs is retried _only_ on the erroring CPUs
++ * its staying as a return
++ *
++ * BUG();
++ */
++
++ if (f->flush_mm == read_pda(active_mm)) {
++ if (read_pda(mmu_state) == TLBSTATE_OK) {
++ if (f->flush_va == TLB_FLUSH_ALL)
++ local_flush_tlb();
++ else
++ __flush_tlb_one(f->flush_va);
++ } else
++ leave_mm(cpu);
++ }
++out:
++ ack_APIC_irq();
++ cpu_clear(cpu, f->flush_cpumask);
++ add_pda(irq_tlb_count, 1);
++}
++
++void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
++ unsigned long va)
++{
++ int sender;
++ union smp_flush_state *f;
++ cpumask_t cpumask = *cpumaskp;
++
++ /* Caller has disabled preemption */
++ sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS;
++ f = &per_cpu(flush_state, sender);
++
++ /*
++ * Could avoid this lock when
++ * num_online_cpus() <= NUM_INVALIDATE_TLB_VECTORS, but it is
++ * probably not worth checking this for a cache-hot lock.
++ */
++ spin_lock(&f->tlbstate_lock);
++
++ f->flush_mm = mm;
++ f->flush_va = va;
++ cpus_or(f->flush_cpumask, cpumask, f->flush_cpumask);
++
++ /*
++ * We have to send the IPI only to
++ * CPUs affected.
++ */
++ send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR_START + sender);
++
++ while (!cpus_empty(f->flush_cpumask))
++ cpu_relax();
++
++ f->flush_mm = NULL;
++ f->flush_va = 0;
++ spin_unlock(&f->tlbstate_lock);
++}
++
++static int __cpuinit init_smp_flush(void)
++{
++ int i;
++
++ for_each_possible_cpu(i)
++ spin_lock_init(&per_cpu(flush_state, i).tlbstate_lock);
++
++ return 0;
++}
++core_initcall(init_smp_flush);
++
++void flush_tlb_current_task(void)
++{
++ struct mm_struct *mm = current->mm;
++ cpumask_t cpu_mask;
++
++ preempt_disable();
++ cpu_mask = mm->cpu_vm_mask;
++ cpu_clear(smp_processor_id(), cpu_mask);
++
++ local_flush_tlb();
++ if (!cpus_empty(cpu_mask))
++ flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
++ preempt_enable();
++}
++
++void flush_tlb_mm(struct mm_struct *mm)
++{
++ cpumask_t cpu_mask;
++
++ preempt_disable();
++ cpu_mask = mm->cpu_vm_mask;
++ cpu_clear(smp_processor_id(), cpu_mask);
++
++ if (current->active_mm == mm) {
++ if (current->mm)
++ local_flush_tlb();
++ else
++ leave_mm(smp_processor_id());
++ }
++ if (!cpus_empty(cpu_mask))
++ flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
++
++ preempt_enable();
++}
++
++void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
++{
++ struct mm_struct *mm = vma->vm_mm;
++ cpumask_t cpu_mask;
++
++ preempt_disable();
++ cpu_mask = mm->cpu_vm_mask;
++ cpu_clear(smp_processor_id(), cpu_mask);
++
++ if (current->active_mm == mm) {
++ if (current->mm)
++ __flush_tlb_one(va);
++ else
++ leave_mm(smp_processor_id());
++ }
++
++ if (!cpus_empty(cpu_mask))
++ flush_tlb_others(cpu_mask, mm, va);
++
++ preempt_enable();
++}
++
++static void do_flush_tlb_all(void *info)
++{
++ unsigned long cpu = smp_processor_id();
++
++ __flush_tlb_all();
++ if (read_pda(mmu_state) == TLBSTATE_LAZY)
++ leave_mm(cpu);
++}
++
++void flush_tlb_all(void)
++{
++ on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
++}
+diff --git a/arch/x86/kernel/trampoline.c b/arch/x86/kernel/trampoline.c
+new file mode 100644
+index 0000000..abbf199
+--- /dev/null
++++ b/arch/x86/kernel/trampoline.c
+@@ -0,0 +1,18 @@
++#include <linux/io.h>
++
++#include <asm/trampoline.h>
++
++/* ready for x86_64, no harm for x86, since it will overwrite after alloc */
++unsigned char *trampoline_base = __va(TRAMPOLINE_BASE);
++
++/*
++ * Currently trivial. Write the real->protected mode
++ * bootstrap into the page concerned. The caller
++ * has made sure it's suitably aligned.
++ */
++unsigned long setup_trampoline(void)
++{
++ memcpy(trampoline_base, trampoline_data,
++ trampoline_end - trampoline_data);
++ return virt_to_phys(trampoline_base);
++}
+diff --git a/arch/x86/kernel/trampoline_32.S b/arch/x86/kernel/trampoline_32.S
+index 6458067..d8ccc3c 100644
+--- a/arch/x86/kernel/trampoline_32.S
++++ b/arch/x86/kernel/trampoline_32.S
+@@ -33,7 +33,7 @@
+
+ /* We can free up trampoline after bootup if cpu hotplug is not supported. */
+ #ifndef CONFIG_HOTPLUG_CPU
+-.section ".init.data","aw", at progbits
++.section ".cpuinit.data","aw", at progbits
+ #else
+ .section .rodata,"a", at progbits
+ #endif
+diff --git a/arch/x86/kernel/trampoline_64.S b/arch/x86/kernel/trampoline_64.S
+index 4aedd0b..894293c 100644
+--- a/arch/x86/kernel/trampoline_64.S
++++ b/arch/x86/kernel/trampoline_64.S
+@@ -30,12 +30,7 @@
+ #include <asm/msr.h>
+ #include <asm/segment.h>
+
+-/* We can free up trampoline after bootup if cpu hotplug is not supported. */
+-#ifndef CONFIG_HOTPLUG_CPU
+-.section .init.data, "aw", @progbits
+-#else
+ .section .rodata, "a", @progbits
-#endif
+
+ .code16
+
+diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
+index b22c01e..bde6f63 100644
+--- a/arch/x86/kernel/traps_32.c
++++ b/arch/x86/kernel/traps_32.c
+@@ -9,26 +9,28 @@
+ * 'Traps.c' handles hardware traps and faults after we have saved some
+ * state in 'asm.s'.
+ */
+-#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/kallsyms.h>
++#include <linux/spinlock.h>
++#include <linux/highmem.h>
++#include <linux/kprobes.h>
++#include <linux/uaccess.h>
++#include <linux/utsname.h>
++#include <linux/kdebug.h>
+ #include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/ptrace.h>
+ #include <linux/string.h>
++#include <linux/unwind.h>
++#include <linux/delay.h>
+ #include <linux/errno.h>
++#include <linux/kexec.h>
++#include <linux/sched.h>
+ #include <linux/timer.h>
+-#include <linux/mm.h>
+ #include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/spinlock.h>
+-#include <linux/interrupt.h>
+-#include <linux/highmem.h>
+-#include <linux/kallsyms.h>
+-#include <linux/ptrace.h>
+-#include <linux/utsname.h>
+-#include <linux/kprobes.h>
+-#include <linux/kexec.h>
+-#include <linux/unwind.h>
+-#include <linux/uaccess.h>
+-#include <linux/nmi.h>
+ #include <linux/bug.h>
++#include <linux/nmi.h>
++#include <linux/mm.h>
+
+ #ifdef CONFIG_EISA
+ #include <linux/ioport.h>
+@@ -43,21 +45,18 @@
+ #include <linux/edac.h>
+ #endif
+
++#include <asm/arch_hooks.h>
++#include <asm/stacktrace.h>
+ #include <asm/processor.h>
+-#include <asm/system.h>
+-#include <asm/io.h>
+-#include <asm/atomic.h>
+ #include <asm/debugreg.h>
++#include <asm/atomic.h>
++#include <asm/system.h>
++#include <asm/unwind.h>
+ #include <asm/desc.h>
+ #include <asm/i387.h>
+ #include <asm/nmi.h>
+-#include <asm/unwind.h>
+ #include <asm/smp.h>
+-#include <asm/arch_hooks.h>
+-#include <linux/kdebug.h>
+-#include <asm/stacktrace.h>
-
--
--/*
-- * 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)) {
+-#include <linux/module.h>
++#include <asm/io.h>
+
+ #include "mach_traps.h"
+
+@@ -69,7 +68,7 @@ EXPORT_SYMBOL_GPL(used_vectors);
+ asmlinkage int system_call(void);
+
+ /* Do we ignore FPU interrupts ? */
+-char ignore_fpu_irq = 0;
++char ignore_fpu_irq;
+
+ /*
+ * The IDT has to be page-aligned to simplify the Pentium
+@@ -105,12 +104,13 @@ static unsigned int code_bytes = 64;
+ void printk_address(unsigned long address, int reliable)
+ {
+ #ifdef CONFIG_KALLSYMS
+- unsigned long offset = 0, symsize;
++ char namebuf[KSYM_NAME_LEN];
++ unsigned long offset = 0;
++ unsigned long symsize;
+ const char *symname;
+- char *modname;
+- char *delim = ":";
+- char namebuf[128];
+ char reliab[4] = "";
++ char *delim = ":";
++ char *modname;
+
+ symname = kallsyms_lookup(address, &symsize, &offset,
+ &modname, namebuf);
+@@ -138,13 +138,14 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p, unsigned s
+
+ /* The form of the top of the frame on the stack */
+ struct stack_frame {
+- struct stack_frame *next_frame;
+- unsigned long return_address;
++ struct stack_frame *next_frame;
++ unsigned long return_address;
+ };
+
+-static inline unsigned long print_context_stack(struct thread_info *tinfo,
+- unsigned long *stack, unsigned long bp,
+- const struct stacktrace_ops *ops, void *data)
++static inline unsigned long
++print_context_stack(struct thread_info *tinfo,
++ unsigned long *stack, unsigned long bp,
++ const struct stacktrace_ops *ops, void *data)
+ {
+ struct stack_frame *frame = (struct stack_frame *)bp;
+
+@@ -166,7 +167,7 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo,
+ return bp;
+ }
+
+-#define MSG(msg) ops->warning(data, msg)
++#define MSG(msg) ops->warning(data, msg)
+
+ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+ unsigned long *stack, unsigned long bp,
+@@ -177,6 +178,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+
+ if (!stack) {
+ unsigned long dummy;
++
+ stack = &dummy;
+ if (task != current)
+ stack = (unsigned long *)task->thread.sp;
+@@ -186,7 +188,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+ if (!bp) {
+ if (task == current) {
+ /* Grab bp right from our regs */
+- asm ("movl %%ebp, %0" : "=r" (bp) : );
++ asm("movl %%ebp, %0" : "=r" (bp) :);
+ } else {
+ /* bp is the last reg pushed by switch_to */
+ bp = *(unsigned long *) task->thread.sp;
+@@ -196,15 +198,18 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+
+ while (1) {
+ struct thread_info *context;
++
+ context = (struct thread_info *)
+ ((unsigned long)stack & (~(THREAD_SIZE - 1)));
+ bp = print_context_stack(context, stack, bp, ops, data);
+- /* Should be after the line below, but somewhere
+- in early boot context comes out corrupted and we
+- can't reference it -AK */
++ /*
++ * Should be after the line below, but somewhere
++ * in early boot context comes out corrupted and we
++ * can't reference it:
++ */
+ if (ops->stack(data, "IRQ") < 0)
+ break;
+- stack = (unsigned long*)context->previous_esp;
++ stack = (unsigned long *)context->previous_esp;
+ if (!stack)
+ break;
+ touch_nmi_watchdog();
+@@ -243,15 +248,15 @@ static void print_trace_address(void *data, unsigned long addr, int reliable)
+ }
+
+ static const struct stacktrace_ops print_trace_ops = {
+- .warning = print_trace_warning,
+- .warning_symbol = print_trace_warning_symbol,
+- .stack = print_trace_stack,
+- .address = print_trace_address,
++ .warning = print_trace_warning,
++ .warning_symbol = print_trace_warning_symbol,
++ .stack = print_trace_stack,
++ .address = print_trace_address,
+ };
+
+ static void
+ show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
+- unsigned long *stack, unsigned long bp, char *log_lvl)
++ unsigned long *stack, unsigned long bp, char *log_lvl)
+ {
+ dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
+ printk("%s =======================\n", log_lvl);
+@@ -263,21 +268,22 @@ void show_trace(struct task_struct *task, struct pt_regs *regs,
+ show_trace_log_lvl(task, regs, stack, bp, "");
+ }
+
+-static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+- unsigned long *sp, unsigned long bp, char *log_lvl)
++static void
++show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
++ unsigned long *sp, unsigned long bp, char *log_lvl)
+ {
+ unsigned long *stack;
+ int i;
+
+ if (sp == NULL) {
+ if (task)
+- sp = (unsigned long*)task->thread.sp;
++ sp = (unsigned long *)task->thread.sp;
+ else
+ sp = (unsigned long *)&sp;
+ }
+
+ stack = sp;
+- for(i = 0; i < kstack_depth_to_print; i++) {
++ for (i = 0; i < kstack_depth_to_print; i++) {
+ if (kstack_end(stack))
+ break;
+ if (i && ((i % 8) == 0))
+@@ -285,6 +291,7 @@ static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+ printk("%08lx ", *stack++);
+ }
+ printk("\n%sCall Trace:\n", log_lvl);
++
+ show_trace_log_lvl(task, regs, sp, bp, log_lvl);
+ }
+
+@@ -299,8 +306,8 @@ void show_stack(struct task_struct *task, unsigned long *sp)
+ */
+ void dump_stack(void)
+ {
+- unsigned long stack;
+ unsigned long bp = 0;
++ unsigned long stack;
+
+ #ifdef CONFIG_FRAME_POINTER
+ if (!bp)
+@@ -312,6 +319,7 @@ void dump_stack(void)
+ init_utsname()->release,
+ (int)strcspn(init_utsname()->version, " "),
+ init_utsname()->version);
++
+ show_trace(current, NULL, &stack, bp);
+ }
+
+@@ -323,6 +331,7 @@ void show_registers(struct pt_regs *regs)
+
+ print_modules();
+ __show_registers(regs, 0);
++
+ printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
+ TASK_COMM_LEN, current->comm, task_pid_nr(current),
+ current_thread_info(), current, task_thread_info(current));
+@@ -331,10 +340,10 @@ void show_registers(struct pt_regs *regs)
+ * time of the fault..
+ */
+ if (!user_mode_vm(regs)) {
+- u8 *ip;
+ unsigned int code_prologue = code_bytes * 43 / 64;
+ unsigned int code_len = code_bytes;
+ unsigned char c;
++ u8 *ip;
+
+ printk("\n" KERN_EMERG "Stack: ");
+ show_stack_log_lvl(NULL, regs, ®s->sp, 0, KERN_EMERG);
+@@ -361,7 +370,7 @@ void show_registers(struct pt_regs *regs)
+ }
+ }
+ printk("\n");
+-}
++}
+
+ int is_valid_bugaddr(unsigned long ip)
+ {
+@@ -377,10 +386,10 @@ int is_valid_bugaddr(unsigned long ip)
+
+ static int die_counter;
+
+-int __kprobes __die(const char * str, struct pt_regs * regs, long err)
++int __kprobes __die(const char *str, struct pt_regs *regs, long err)
+ {
+- unsigned long sp;
+ unsigned short ss;
++ unsigned long sp;
+
+ printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
+ #ifdef CONFIG_PREEMPT
+@@ -395,8 +404,8 @@ int __kprobes __die(const char * str, struct pt_regs * regs, long err)
+ printk("\n");
+
+ if (notify_die(DIE_OOPS, str, regs, err,
+- current->thread.trap_no, SIGSEGV) !=
+- NOTIFY_STOP) {
++ current->thread.trap_no, SIGSEGV) != NOTIFY_STOP) {
++
+ show_registers(regs);
+ /* Executive summary in case the oops scrolled away */
+ sp = (unsigned long) (®s->sp);
+@@ -408,17 +417,18 @@ int __kprobes __die(const char * str, struct pt_regs * regs, long err)
+ printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip);
+ print_symbol("%s", regs->ip);
+ printk(" SS:ESP %04x:%08lx\n", ss, sp);
++
+ return 0;
+- } else {
+- return 1;
+ }
++
++ return 1;
+ }
+
+ /*
+- * This is gone through when something in the kernel has done something bad and
+- * is about to be terminated.
++ * This is gone through when something in the kernel has done something bad
++ * and is about to be terminated:
+ */
+-void die(const char * str, struct pt_regs * regs, long err)
++void die(const char *str, struct pt_regs *regs, long err)
+ {
+ static struct {
+ raw_spinlock_t lock;
+@@ -440,8 +450,9 @@ void die(const char * str, struct pt_regs * regs, long err)
+ die.lock_owner = smp_processor_id();
+ die.lock_owner_depth = 0;
+ bust_spinlocks(1);
+- } else
++ } else {
+ raw_local_irq_save(flags);
++ }
+
+ if (++die.lock_owner_depth < 3) {
+ report_bug(regs->ip, regs);
+@@ -474,19 +485,20 @@ void die(const char * str, struct pt_regs * regs, long err)
+ do_exit(SIGSEGV);
+ }
+
+-static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
++static inline void
++die_if_kernel(const char *str, struct pt_regs *regs, long err)
+ {
+ if (!user_mode_vm(regs))
+ die(str, regs, err);
+ }
+
+-static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
+- struct pt_regs * regs, long error_code,
+- siginfo_t *info)
++static void __kprobes
++do_trap(int trapnr, int signr, char *str, int vm86, struct pt_regs *regs,
++ long error_code, siginfo_t *info)
+ {
+ struct task_struct *tsk = current;
+
+- if (regs->flags & VM_MASK) {
++ if (regs->flags & X86_VM_MASK) {
+ if (vm86)
+ goto vm86_trap;
+ goto trap_signal;
+@@ -495,111 +507,112 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
+ if (!user_mode(regs))
+ goto kernel_trap;
+
+- trap_signal: {
- /*
-- * Has the boot CPU finished it's STARTUP sequence?
+- * 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.
- */
-- 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);
+- 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;
- }
--
-- /*
-- * 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);
-- }
++ 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);
- }
-- } 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;
++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;
- }
--
-- 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));
++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 */
- /*
-- * Does this new cpu bringup a new core?
+- * swd & 0x240 == 0x040: Stack Underflow
+- * swd & 0x240 == 0x240: Stack Overflow
+- * User must clear the SF bit (0x40) if set
- */
-- 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);
+- 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:
-- 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);
--
+- 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 {
- /*
-- * Wait 5s total for a response
+- * Handle strange cache flush from user space exception
+- * in all other cases. This is undocumented behaviour.
- */
-- 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 (regs->flags & VM_MASK) {
+- handle_vm86_fault((struct kernel_vm86_regs *)regs,
+- error_code);
+- return;
- }
-- }
-- 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);
+- 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 */
+
-
-- 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--;
+ 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;
- }
--
-- 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();
+ 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);
+
- /*
-- * 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.
+- * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
+- * Generate a build-time error if the alignment is wrong.
- */
-- local_irq_enable();
-- mdelay(1);
--
-- local_irq_disable();
-- remove_siblinginfo(cpu);
--
-- spin_lock(&vector_lock);
-- /* It's now safe to remove this processor from the online map */
-- cpu_clear(cpu, cpu_online_map);
-- spin_unlock(&vector_lock);
-- remove_cpu_from_maps();
-- fixup_irqs(cpu_online_map);
-- return 0;
--}
--
--void __cpu_die(unsigned int cpu)
--{
-- /* We don't do anything here: idle task is faking death itself. */
-- unsigned int i;
--
-- for (i = 0; i < 10; i++) {
-- /* They ack this in play_dead by setting CPU_DEAD */
-- if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
-- printk ("CPU %d is now offline\n", cpu);
-- if (1 == num_online_cpus())
-- alternatives_smp_switch(0);
-- return;
-- }
-- msleep(100);
-- }
-- printk(KERN_ERR "CPU %u didn't die...\n", cpu);
--}
--
--static __init int setup_additional_cpus(char *s)
--{
-- return s && get_option(&s, &additional_cpus) ? 0 : -EINVAL;
--}
--early_param("additional_cpus", setup_additional_cpus);
--
--#else /* ... !CONFIG_HOTPLUG_CPU */
--
--int __cpu_disable(void)
--{
-- return -ENOSYS;
--}
--
--void __cpu_die(unsigned int cpu)
--{
-- /* We said "no" in __cpu_disable */
-- BUG();
--}
--#endif /* CONFIG_HOTPLUG_CPU */
-diff --git a/arch/x86/kernel/smpcommon.c b/arch/x86/kernel/smpcommon.c
-new file mode 100644
-index 0000000..3449064
---- /dev/null
-+++ b/arch/x86/kernel/smpcommon.c
-@@ -0,0 +1,83 @@
-+/*
-+ * SMP stuff which is common to all sub-architectures.
-+ */
-+#include <linux/module.h>
-+#include <asm/smp.h>
-+
-+#ifdef CONFIG_X86_32
-+DEFINE_PER_CPU(unsigned long, this_cpu_off);
-+EXPORT_PER_CPU_SYMBOL(this_cpu_off);
-+
-+/* Initialize the CPU's GDT. This is either the boot CPU doing itself
-+ (still using the master per-cpu area), or a CPU doing it for a
-+ secondary which will soon come up. */
-+__cpuinit void init_gdt(int cpu)
-+{
-+ struct desc_struct *gdt = get_cpu_gdt_table(cpu);
-+
-+ pack_descriptor(&gdt[GDT_ENTRY_PERCPU],
-+ __per_cpu_offset[cpu], 0xFFFFF,
-+ 0x2 | DESCTYPE_S, 0x8);
+- 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);
+
-+ gdt[GDT_ENTRY_PERCPU].s = 1;
+ 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);
+
-+ per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu];
-+ per_cpu(cpu_number, cpu) = cpu;
-+}
-+#endif
+ return 1;
+ }
+ __setup("kstack=", kstack_setup);
+diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c
+index 0454666..adff76e 100644
+--- a/arch/x86/kernel/traps_64.c
++++ b/arch/x86/kernel/traps_64.c
+@@ -33,6 +33,8 @@
+ #include <linux/kdebug.h>
+ #include <linux/utsname.h>
+
++#include <mach_traps.h>
+
-+/**
-+ * 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);
+ #if defined(CONFIG_EDAC)
+ #include <linux/edac.h>
+ #endif
+@@ -598,10 +600,16 @@ void die(const char * str, struct pt_regs * regs, long err)
+ oops_end(flags, regs, SIGSEGV);
+ }
+
+-void __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic)
++notrace __kprobes void
++die_nmi(char *str, struct pt_regs *regs, int do_panic)
+ {
+- unsigned long flags = oops_begin();
++ unsigned long flags;
+
-+/**
-+ * 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);
++ 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();
-+ put_cpu();
-+ return 0;
++ /*
++ * does a slab alloc which can sleep
++ */
++ if (init_fpu(me)) {
++ /*
++ * ran out of memory!
++ */
++ do_group_exit(SIGKILL);
++ return;
++ }
++ local_irq_disable();
+ }
+
-+ ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
-+
-+ put_cpu();
-+ return ret;
-+}
-+EXPORT_SYMBOL(smp_call_function_single);
-diff --git a/arch/x86/kernel/smpcommon_32.c b/arch/x86/kernel/smpcommon_32.c
-index 8bc38af..8b13789 100644
---- a/arch/x86/kernel/smpcommon_32.c
-+++ b/arch/x86/kernel/smpcommon_32.c
-@@ -1,82 +1 @@
--/*
-- * SMP stuff which is common to all sub-architectures.
-- */
--#include <linux/module.h>
--#include <asm/smp.h>
++ 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);
--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;
-- }
+ 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);
-
-- ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
+- return;
-
-- 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;
- }
+-out_no_tsc:
+- setup_clear_cpu_cap(X86_FEATURE_TSC);
+ }
+diff --git a/arch/x86/kernel/tsc_64.c b/arch/x86/kernel/tsc_64.c
+index d3bebaa..fcc16e5 100644
+--- a/arch/x86/kernel/tsc_64.c
++++ b/arch/x86/kernel/tsc_64.c
+@@ -11,6 +11,7 @@
+ #include <asm/hpet.h>
+ #include <asm/timex.h>
+ #include <asm/timer.h>
++#include <asm/vgtod.h>
-- 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;
- }
+ static int notsc __initdata = 0;
-@@ -292,7 +292,7 @@ int __init get_memcfg_from_srat(void)
- rsdp->oem_id);
+@@ -44,8 +45,8 @@ DEFINE_PER_CPU(unsigned long, cyc2ns);
- 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;
- }
+ 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;
-@@ -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;
- }
+ 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);
-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;
+- prev_scale = *scale;
+ if (cpu_khz)
+ *scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz;
-- wrmsrl(MSR_IA32_DEBUGCTLMSR, val);
-+ update_debugctlmsr(val);
+@@ -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
+
+
/*
-diff --git a/arch/x86/kernel/summit_32.c b/arch/x86/kernel/summit_32.c
-index 72f4634..ae75109 100644
---- a/arch/x86/kernel/summit_32.c
-+++ b/arch/x86/kernel/summit_32.c
-@@ -29,49 +29,54 @@
- #include <linux/mm.h>
- #include <linux/init.h>
- #include <asm/io.h>
-+#include <asm/bios_ebda.h>
- #include <asm/mach-summit/mach_mpparse.h>
+@@ -81,7 +81,7 @@
+ #define VFLAGS (*(unsigned short *)&(current->thread.v86flags))
+ #define VEFLAGS (current->thread.v86flags)
- 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;
+-#define set_flags(X,new,mask) \
++#define set_flags(X, new, mask) \
+ ((X) = ((X) & ~(mask)) | ((new) & (mask)))
-+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)
+ #define SAFE_MASK (0xDD5)
+@@ -93,8 +93,10 @@ static int copy_vm86_regs_to_user(struct vm86_regs __user *user,
{
- int twister = 0, node = 0;
- int i, bus, num_buses;
+ int ret = 0;
-- 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;
- }
+- /* 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;
+ }
-- 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;
+-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)
-- 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]
+ 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:
+ /*
-+ * 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;
++ * 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;
}
-- 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;
+ /* 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 */
}
-@@ -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);
+-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;
+ }
-- 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)
+-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;
}
- 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;
+- spin_unlock_irqrestore(&irqbits_lock, flags);
++ spin_unlock_irqrestore(&irqbits_lock, flags);
+ return ret;
+ }
-- 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;
+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
- return 1;
-@@ -135,14 +141,14 @@ void __init setup_summit(void)
- int i, next_wpeg, next_bus = 0;
+-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);
+ }
- /* 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);
+-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);
+ }
- 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));
+-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;
}
-- 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;
+
+ 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;
}
-@@ -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. */
+ /* 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..fad3674 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
- #include <linux/linkage.h>
- #include <linux/sys.h>
-@@ -7,20 +7,23 @@
+ . = ALIGN(8);
+@@ -204,12 +209,6 @@ SECTIONS
+ EXIT_DATA
+ }
- #define __NO_STUBS
+-/* vdso blob that is mapped into user space */
+- vdso_start = . ;
+- .vdso : AT(ADDR(.vdso) - LOAD_OFFSET) { *(.vdso) }
+- . = ALIGN(PAGE_SIZE);
+- vdso_end = .;
+-
+ #ifdef CONFIG_BLK_DEV_INITRD
+ . = ALIGN(PAGE_SIZE);
+ __initramfs_start = .;
+@@ -247,3 +246,9 @@ SECTIONS
--#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
-+#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
- #undef _ASM_X86_64_UNISTD_H_
- #include <asm/unistd_64.h>
+ 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..ba8c0b7 100644
+--- a/arch/x86/kernel/vsmp_64.c
++++ b/arch/x86/kernel/vsmp_64.c
+@@ -8,6 +8,8 @@
+ *
+ * Ravikiran Thirumalai <kiran at scalemp.com>,
+ * Shai Fultheim <shai at scalemp.com>
++ * Paravirt ops integration: Glauber de Oliveira Costa <gcosta at redhat.com>,
++ * Ravikiran Thirumalai <kiran at scalemp.com>
+ */
- #undef __SYSCALL
--#define __SYSCALL(nr, sym) [ nr ] = sym,
-+#define __SYSCALL(nr, sym) [nr] = sym,
- #undef _ASM_X86_64_UNISTD_H_
+ #include <linux/init.h>
+@@ -15,38 +17,137 @@
+ #include <linux/pci_regs.h>
+ #include <asm/pci-direct.h>
+ #include <asm/io.h>
++#include <asm/paravirt.h>
--typedef void (*sys_call_ptr_t)(void);
-+typedef void (*sys_call_ptr_t)(void);
+-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();
- extern void sys_ni_syscall(void);
+- if (!early_pci_allowed())
+- return 0;
++ if (!(flags & X86_EFLAGS_IF) || (flags & X86_EFLAGS_AC))
++ flags &= ~X86_EFLAGS_IF;
++ return flags;
++}
- const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
-- /* Smells like a like a compiler bug -- it doesn't work when the & below is removed. */
-+ /*
-+ *Smells like a like a compiler bug -- it doesn't work
-+ *when the & below is removed.
-+ */
- [0 ... __NR_syscall_max] = &sys_ni_syscall,
- #include <asm/unistd_64.h>
- };
-diff --git a/arch/x86/kernel/test_nx.c b/arch/x86/kernel/test_nx.c
-index 10b8a6f..787a5e4 100644
---- a/arch/x86/kernel/test_nx.c
-+++ b/arch/x86/kernel/test_nx.c
-@@ -11,6 +11,8 @@
- */
- #include <linux/module.h>
- #include <linux/sort.h>
-+#include <linux/slab.h>
+- /* 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);
++}
+
- #include <asm/uaccess.h>
- #include <asm/asm.h>
++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;
-diff --git a/arch/x86/kernel/tlb_32.c b/arch/x86/kernel/tlb_32.c
-new file mode 100644
-index 0000000..9bb2363
---- /dev/null
-+++ b/arch/x86/kernel/tlb_32.c
-@@ -0,0 +1,243 @@
-+#include <linux/spinlock.h>
-+#include <linux/cpu.h>
-+#include <linux/interrupt.h>
+ /* 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;
+
-+#include <asm/tlbflush.h>
+ 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
+
-+DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate)
-+ ____cacheline_aligned = { &init_mm, 0, };
++#ifdef CONFIG_PCI
++static int is_vsmp = -1;
+
-+/* must come after the send_IPI functions above for inlining */
-+#include <mach_ipi.h>
++static void __init detect_vsmp_box(void)
++{
++ is_vsmp = 0;
+
-+/*
-+ * Smarter SMP flushing macros.
-+ * c/o Linus Torvalds.
-+ *
-+ * These mean you can really definitely utterly forget about
-+ * writing to user space from interrupts. (Its not allowed anyway).
-+ *
-+ * Optimizations Manfred Spraul <manfred at colorfullife.com>
-+ */
++ if (!early_pci_allowed())
++ return;
+
-+static cpumask_t flush_cpumask;
-+static struct mm_struct *flush_mm;
-+static unsigned long flush_va;
-+static DEFINE_SPINLOCK(tlbstate_lock);
++ /* 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;
++}
+
-+/*
-+ * 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)
++int is_vsmp_box(void)
+{
-+ 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);
++ if (is_vsmp != -1)
++ return is_vsmp;
++ else {
++ WARN_ON_ONCE(1);
++ return 0;
++ }
+}
-+EXPORT_SYMBOL_GPL(leave_mm);
++#else
++static void __init detect_vsmp_box(void)
++{
++}
++int is_vsmp_box(void)
++{
+ return 0;
+ }
++#endif
+
+-core_initcall(vsmp_init);
++void __init vsmp_init(void)
++{
++ detect_vsmp_box();
++ if (!is_vsmp_box())
++ return;
+
++ set_vsmp_pv_ops();
++ return;
++}
+diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
+index edff4c9..61efa2f 100644
+--- a/arch/x86/kernel/vsyscall_64.c
++++ b/arch/x86/kernel/vsyscall_64.c
+@@ -216,7 +216,7 @@ vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
+ return 0;
+ }
+
+-long __vsyscall(3) venosys_1(void)
++static long __vsyscall(3) venosys_1(void)
+ {
+ return -ENOSYS;
+ }
+diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
+index a66e9c1..58882f9 100644
+--- a/arch/x86/kernel/x8664_ksyms_64.c
++++ b/arch/x86/kernel/x8664_ksyms_64.c
+@@ -4,7 +4,6 @@
+ #include <linux/module.h>
+ #include <linux/smp.h>
+
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -12,11 +11,6 @@
+
+ EXPORT_SYMBOL(kernel_thread);
+
+-EXPORT_SYMBOL(__down_failed);
+-EXPORT_SYMBOL(__down_failed_interruptible);
+-EXPORT_SYMBOL(__down_failed_trylock);
+-EXPORT_SYMBOL(__up_wakeup);
+-
+ EXPORT_SYMBOL(__get_user_1);
+ EXPORT_SYMBOL(__get_user_2);
+ EXPORT_SYMBOL(__get_user_4);
+@@ -35,15 +29,17 @@ EXPORT_SYMBOL(__copy_from_user_inatomic);
+ EXPORT_SYMBOL(copy_page);
+ EXPORT_SYMBOL(clear_page);
+
+-/* Export string functions. We normally rely on gcc builtin for most of these,
+- but gcc sometimes decides not to inline them. */
++/*
++ * Export string functions. We normally rely on gcc builtin for most of these,
++ * but gcc sometimes decides not to inline them.
++ */
+ #undef memcpy
+ #undef memset
+ #undef memmove
+
+-extern void * memset(void *,int,__kernel_size_t);
+-extern void * memcpy(void *,const void *,__kernel_size_t);
+-extern void * __memcpy(void *,const void *,__kernel_size_t);
++extern void *memset(void *, int, __kernel_size_t);
++extern void *memcpy(void *, const void *, __kernel_size_t);
++extern void *__memcpy(void *, const void *, __kernel_size_t);
+
+ EXPORT_SYMBOL(memset);
+ EXPORT_SYMBOL(memcpy);
+diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
+index 41962e7..8d45fab 100644
+--- a/arch/x86/kvm/Kconfig
++++ b/arch/x86/kvm/Kconfig
+@@ -19,7 +19,7 @@ if VIRTUALIZATION
+
+ config KVM
+ tristate "Kernel-based Virtual Machine (KVM) support"
+- depends on HAVE_KVM && EXPERIMENTAL
++ depends on HAVE_KVM
+ select PREEMPT_NOTIFIERS
+ select ANON_INODES
+ ---help---
+@@ -50,6 +50,17 @@ config KVM_AMD
+ Provides support for KVM on AMD processors equipped with the AMD-V
+ (SVM) extensions.
+
++config KVM_TRACE
++ bool "KVM trace support"
++ depends on KVM && MARKERS && SYSFS
++ select RELAY
++ select DEBUG_FS
++ default n
++ ---help---
++ This option allows reading a trace of kvm-related events through
++ relayfs. Note the ABI is not considered stable and will be
++ modified in future updates.
++
+ # OK, it's a little counter-intuitive to do this, but it puts it neatly under
+ # the virtualization menu.
+ source drivers/lguest/Kconfig
+diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
+index ffdd0b3..c97d35c 100644
+--- a/arch/x86/kvm/Makefile
++++ b/arch/x86/kvm/Makefile
+@@ -3,10 +3,14 @@
+ #
+
+ common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o)
++ifeq ($(CONFIG_KVM_TRACE),y)
++common-objs += $(addprefix ../../../virt/kvm/, kvm_trace.o)
++endif
+
+ EXTRA_CFLAGS += -Ivirt/kvm -Iarch/x86/kvm
+
+-kvm-objs := $(common-objs) x86.o mmu.o x86_emulate.o i8259.o irq.o lapic.o
++kvm-objs := $(common-objs) x86.o mmu.o x86_emulate.o i8259.o irq.o lapic.o \
++ i8254.o
+ obj-$(CONFIG_KVM) += kvm.o
+ kvm-intel-objs = vmx.o
+ obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
+diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
+new file mode 100644
+index 0000000..361e316
+--- /dev/null
++++ b/arch/x86/kvm/i8254.c
+@@ -0,0 +1,611 @@
+/*
++ * 8253/8254 interval timer emulation
+ *
-+ * 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
++ * Copyright (c) 2003-2004 Fabrice Bellard
++ * Copyright (c) 2006 Intel Corporation
++ * Copyright (c) 2007 Keir Fraser, XenSource Inc
++ * Copyright (c) 2008 Intel Corporation
+ *
-+ * 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.
++ * 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 good news is that cpu_tlbstate is local to each cpu, no
-+ * write/read ordering problems.
-+ */
-+
-+/*
-+ * TLB flush IPI:
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
+ *
-+ * 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.
++ * 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.
++ *
++ * Authors:
++ * Sheng Yang <sheng.yang at intel.com>
++ * Based on QEMU and Xen.
+ */
+
-+void smp_invalidate_interrupt(struct pt_regs *regs)
-+{
-+ unsigned long cpu;
++#include <linux/kvm_host.h>
+
-+ cpu = get_cpu();
++#include "irq.h"
++#include "i8254.h"
+
-+ 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();
-+ */
++#ifndef CONFIG_X86_64
++#define mod_64(x, y) ((x) - (y) * div64_64(x, y))
++#else
++#define mod_64(x, y) ((x) % (y))
++#endif
+
-+ 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++;
-+}
++#define RW_STATE_LSB 1
++#define RW_STATE_MSB 2
++#define RW_STATE_WORD0 3
++#define RW_STATE_WORD1 4
+
-+void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
-+ unsigned long va)
++/* Compute with 96 bit intermediate result: (a*b)/c */
++static u64 muldiv64(u64 a, u32 b, u32 c)
+{
-+ cpumask_t cpumask = *cpumaskp;
++ union {
++ u64 ll;
++ struct {
++ u32 low, high;
++ } l;
++ } u, res;
++ u64 rl, rh;
+
-+ /*
-+ * 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);
++ u.ll = a;
++ rl = (u64)u.l.low * (u64)b;
++ rh = (u64)u.l.high * (u64)b;
++ rh += (rl >> 32);
++ res.l.high = div64_64(rh, c);
++ res.l.low = div64_64(((mod_64(rh, c) << 32) + (rl & 0xffffffff)), c);
++ return res.ll;
++}
+
-+#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
++static void pit_set_gate(struct kvm *kvm, int channel, u32 val)
++{
++ struct kvm_kpit_channel_state *c =
++ &kvm->arch.vpit->pit_state.channels[channel];
+
-+ /*
-+ * 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);
++ WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.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);
++ switch (c->mode) {
++ default:
++ case 0:
++ case 4:
++ /* XXX: just disable/enable counting */
++ break;
++ case 1:
++ case 2:
++ case 3:
++ case 5:
++ /* Restart counting on rising edge. */
++ if (c->gate < val)
++ c->count_load_time = ktime_get();
++ break;
++ }
+
-+ while (!cpus_empty(flush_cpumask))
-+ /* nothing. lockup detection does not belong here */
-+ cpu_relax();
++ c->gate = val;
++}
+
-+ flush_mm = NULL;
-+ flush_va = 0;
-+ spin_unlock(&tlbstate_lock);
++int pit_get_gate(struct kvm *kvm, int channel)
++{
++ WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
++
++ return kvm->arch.vpit->pit_state.channels[channel].gate;
+}
+
-+void flush_tlb_current_task(void)
++static int pit_get_count(struct kvm *kvm, int channel)
+{
-+ struct mm_struct *mm = current->mm;
-+ cpumask_t cpu_mask;
++ struct kvm_kpit_channel_state *c =
++ &kvm->arch.vpit->pit_state.channels[channel];
++ s64 d, t;
++ int counter;
+
-+ preempt_disable();
-+ cpu_mask = mm->cpu_vm_mask;
-+ cpu_clear(smp_processor_id(), cpu_mask);
++ WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
+
-+ local_flush_tlb();
-+ if (!cpus_empty(cpu_mask))
-+ flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
-+ preempt_enable();
++ t = ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time));
++ d = muldiv64(t, KVM_PIT_FREQ, NSEC_PER_SEC);
++
++ switch (c->mode) {
++ case 0:
++ case 1:
++ case 4:
++ case 5:
++ counter = (c->count - d) & 0xffff;
++ break;
++ case 3:
++ /* XXX: may be incorrect for odd counts */
++ counter = c->count - (mod_64((2 * d), c->count));
++ break;
++ default:
++ counter = c->count - mod_64(d, c->count);
++ break;
++ }
++ return counter;
+}
+
-+void flush_tlb_mm(struct mm_struct *mm)
++static int pit_get_out(struct kvm *kvm, int channel)
+{
-+ cpumask_t cpu_mask;
++ struct kvm_kpit_channel_state *c =
++ &kvm->arch.vpit->pit_state.channels[channel];
++ s64 d, t;
++ int out;
+
-+ preempt_disable();
-+ cpu_mask = mm->cpu_vm_mask;
-+ cpu_clear(smp_processor_id(), cpu_mask);
++ WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
+
-+ if (current->active_mm == mm) {
-+ if (current->mm)
-+ local_flush_tlb();
-+ else
-+ leave_mm(smp_processor_id());
++ t = ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time));
++ d = muldiv64(t, KVM_PIT_FREQ, NSEC_PER_SEC);
++
++ switch (c->mode) {
++ default:
++ case 0:
++ out = (d >= c->count);
++ break;
++ case 1:
++ out = (d < c->count);
++ break;
++ case 2:
++ out = ((mod_64(d, c->count) == 0) && (d != 0));
++ break;
++ case 3:
++ out = (mod_64(d, c->count) < ((c->count + 1) >> 1));
++ break;
++ case 4:
++ case 5:
++ out = (d == c->count);
++ break;
+ }
-+ if (!cpus_empty(cpu_mask))
-+ flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
+
-+ preempt_enable();
++ return out;
+}
+
-+void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
++static void pit_latch_count(struct kvm *kvm, int channel)
+{
-+ struct mm_struct *mm = vma->vm_mm;
-+ cpumask_t cpu_mask;
++ struct kvm_kpit_channel_state *c =
++ &kvm->arch.vpit->pit_state.channels[channel];
+
-+ preempt_disable();
-+ cpu_mask = mm->cpu_vm_mask;
-+ cpu_clear(smp_processor_id(), cpu_mask);
++ WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
+
-+ if (current->active_mm == mm) {
-+ if (current->mm)
-+ __flush_tlb_one(va);
-+ else
-+ leave_mm(smp_processor_id());
++ if (!c->count_latched) {
++ c->latched_count = pit_get_count(kvm, channel);
++ c->count_latched = c->rw_mode;
+ }
++}
+
-+ if (!cpus_empty(cpu_mask))
-+ flush_tlb_others(cpu_mask, mm, va);
++static void pit_latch_status(struct kvm *kvm, int channel)
++{
++ struct kvm_kpit_channel_state *c =
++ &kvm->arch.vpit->pit_state.channels[channel];
+
-+ preempt_enable();
++ WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
++
++ if (!c->status_latched) {
++ /* TODO: Return NULL COUNT (bit 6). */
++ c->status = ((pit_get_out(kvm, channel) << 7) |
++ (c->rw_mode << 4) |
++ (c->mode << 1) |
++ c->bcd);
++ c->status_latched = 1;
++ }
+}
-+EXPORT_SYMBOL(flush_tlb_page);
+
-+static void do_flush_tlb_all(void *info)
++int __pit_timer_fn(struct kvm_kpit_state *ps)
+{
-+ unsigned long cpu = smp_processor_id();
++ struct kvm_vcpu *vcpu0 = ps->pit->kvm->vcpus[0];
++ struct kvm_kpit_timer *pt = &ps->pit_timer;
+
-+ __flush_tlb_all();
-+ if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY)
-+ leave_mm(cpu);
++ atomic_inc(&pt->pending);
++ smp_mb__after_atomic_inc();
++ /* FIXME: handle case where the guest is in guest mode */
++ if (vcpu0 && waitqueue_active(&vcpu0->wq)) {
++ vcpu0->arch.mp_state = KVM_MP_STATE_RUNNABLE;
++ wake_up_interruptible(&vcpu0->wq);
++ }
++
++ pt->timer.expires = ktime_add_ns(pt->timer.expires, pt->period);
++ pt->scheduled = ktime_to_ns(pt->timer.expires);
++
++ return (pt->period == 0 ? 0 : 1);
+}
+
-+void flush_tlb_all(void)
++int pit_has_pending_timer(struct kvm_vcpu *vcpu)
+{
-+ on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
-+}
++ struct kvm_pit *pit = vcpu->kvm->arch.vpit;
+
-diff --git a/arch/x86/kernel/tlb_64.c b/arch/x86/kernel/tlb_64.c
-new file mode 100644
-index 0000000..a1f07d7
---- /dev/null
-+++ b/arch/x86/kernel/tlb_64.c
-@@ -0,0 +1,274 @@
-+#include <linux/init.h>
++ if (pit && vcpu->vcpu_id == 0)
++ return atomic_read(&pit->pit_state.pit_timer.pending);
+
-+#include <linux/mm.h>
-+#include <linux/delay.h>
-+#include <linux/spinlock.h>
-+#include <linux/smp.h>
-+#include <linux/kernel_stat.h>
-+#include <linux/mc146818rtc.h>
-+#include <linux/interrupt.h>
++ return 0;
++}
+
-+#include <asm/mtrr.h>
-+#include <asm/pgalloc.h>
-+#include <asm/tlbflush.h>
-+#include <asm/mmu_context.h>
-+#include <asm/proto.h>
-+#include <asm/apicdef.h>
-+#include <asm/idle.h>
++static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
++{
++ struct kvm_kpit_state *ps;
++ int restart_timer = 0;
+
-+#include <mach_ipi.h>
-+/*
-+ * Smarter SMP flushing macros.
-+ * c/o Linus Torvalds.
-+ *
-+ * These mean you can really definitely utterly forget about
-+ * writing to user space from interrupts. (Its not allowed anyway).
-+ *
-+ * Optimizations Manfred Spraul <manfred at colorfullife.com>
-+ *
-+ * More scalable flush, from Andi Kleen
-+ *
-+ * To avoid global state use 8 different call vectors.
-+ * Each CPU uses a specific vector to trigger flushes on other
-+ * CPUs. Depending on the received vector the target CPUs look into
-+ * the right per cpu variable for the flush data.
-+ *
-+ * With more than 8 CPUs they are hashed to the 8 available
-+ * vectors. The limited global vector space forces us to this right now.
-+ * In future when interrupts are split into per CPU domains this could be
-+ * fixed, at the cost of triggering multiple IPIs in some cases.
-+ */
++ ps = container_of(data, struct kvm_kpit_state, pit_timer.timer);
+
-+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;
++ restart_timer = __pit_timer_fn(ps);
+
-+/* 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);
++ if (restart_timer)
++ return HRTIMER_RESTART;
++ else
++ return HRTIMER_NORESTART;
++}
+
-+/*
-+ * We cannot call mmdrop() because we are in interrupt context,
-+ * instead update mm->cpu_vm_mask.
-+ */
-+void leave_mm(int cpu)
++static void destroy_pit_timer(struct kvm_kpit_timer *pt)
+{
-+ if (read_pda(mmu_state) == TLBSTATE_OK)
-+ BUG();
-+ cpu_clear(cpu, read_pda(active_mm)->cpu_vm_mask);
-+ load_cr3(swapper_pg_dir);
++ pr_debug("pit: execute del timer!\n");
++ hrtimer_cancel(&pt->timer);
+}
-+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.
-+ */
++static void create_pit_timer(struct kvm_kpit_timer *pt, u32 val, int is_period)
++{
++ s64 interval;
+
-+/*
-+ * 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.
-+ */
++ interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ);
+
-+asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs)
++ pr_debug("pit: create pit timer, interval is %llu nsec\n", interval);
++
++ /* TODO The new value only affected after the retriggered */
++ hrtimer_cancel(&pt->timer);
++ pt->period = (is_period == 0) ? 0 : interval;
++ pt->timer.function = pit_timer_fn;
++ atomic_set(&pt->pending, 0);
++
++ hrtimer_start(&pt->timer, ktime_add_ns(ktime_get(), interval),
++ HRTIMER_MODE_ABS);
++}
++
++static void pit_load_count(struct kvm *kvm, int channel, u32 val)
+{
-+ int cpu;
-+ int sender;
-+ union smp_flush_state *f;
++ struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
++
++ WARN_ON(!mutex_is_locked(&ps->lock));
++
++ pr_debug("pit: load_count val is %d, channel is %d\n", val, channel);
+
-+ cpu = smp_processor_id();
+ /*
-+ * orig_rax contains the negated interrupt vector.
-+ * Use that to determine where the sender put the data.
++ * Though spec said the state of 8254 is undefined after power-up,
++ * seems some tricky OS like Windows XP depends on IRQ0 interrupt
++ * when booting up.
++ * So here setting initialize rate for it, and not a specific number
+ */
-+ sender = ~regs->orig_ax - INVALIDATE_TLB_VECTOR_START;
-+ f = &per_cpu(flush_state, sender);
++ if (val == 0)
++ val = 0x10000;
+
-+ 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();
-+ */
++ ps->channels[channel].count_load_time = ktime_get();
++ ps->channels[channel].count = val;
+
-+ 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);
++ if (channel != 0)
++ return;
++
++ /* Two types of timer
++ * mode 1 is one shot, mode 2 is period, otherwise del timer */
++ switch (ps->channels[0].mode) {
++ case 1:
++ create_pit_timer(&ps->pit_timer, val, 0);
++ break;
++ case 2:
++ create_pit_timer(&ps->pit_timer, val, 1);
++ break;
++ default:
++ destroy_pit_timer(&ps->pit_timer);
+ }
-+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)
++void kvm_pit_load_count(struct kvm *kvm, int channel, u32 val)
+{
-+ int sender;
-+ union smp_flush_state *f;
-+ cpumask_t cpumask = *cpumaskp;
++ mutex_lock(&kvm->arch.vpit->pit_state.lock);
++ pit_load_count(kvm, channel, val);
++ mutex_unlock(&kvm->arch.vpit->pit_state.lock);
++}
+
-+ /* Caller has disabled preemption */
-+ sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS;
-+ f = &per_cpu(flush_state, sender);
++static void pit_ioport_write(struct kvm_io_device *this,
++ gpa_t addr, int len, const void *data)
++{
++ struct kvm_pit *pit = (struct kvm_pit *)this->private;
++ struct kvm_kpit_state *pit_state = &pit->pit_state;
++ struct kvm *kvm = pit->kvm;
++ int channel, access;
++ struct kvm_kpit_channel_state *s;
++ u32 val = *(u32 *) data;
+
-+ /*
-+ * 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);
++ val &= 0xff;
++ addr &= KVM_PIT_CHANNEL_MASK;
+
-+ f->flush_mm = mm;
-+ f->flush_va = va;
-+ cpus_or(f->flush_cpumask, cpumask, f->flush_cpumask);
++ mutex_lock(&pit_state->lock);
+
-+ /*
-+ * We have to send the IPI only to
-+ * CPUs affected.
-+ */
-+ send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR_START + sender);
++ if (val != 0)
++ pr_debug("pit: write addr is 0x%x, len is %d, val is 0x%x\n",
++ (unsigned int)addr, len, val);
+
-+ while (!cpus_empty(f->flush_cpumask))
-+ cpu_relax();
++ if (addr == 3) {
++ channel = val >> 6;
++ if (channel == 3) {
++ /* Read-Back Command. */
++ for (channel = 0; channel < 3; channel++) {
++ s = &pit_state->channels[channel];
++ if (val & (2 << channel)) {
++ if (!(val & 0x20))
++ pit_latch_count(kvm, channel);
++ if (!(val & 0x10))
++ pit_latch_status(kvm, channel);
++ }
++ }
++ } else {
++ /* Select Counter <channel>. */
++ s = &pit_state->channels[channel];
++ access = (val >> 4) & KVM_PIT_CHANNEL_MASK;
++ if (access == 0) {
++ pit_latch_count(kvm, channel);
++ } else {
++ s->rw_mode = access;
++ s->read_state = access;
++ s->write_state = access;
++ s->mode = (val >> 1) & 7;
++ if (s->mode > 5)
++ s->mode -= 4;
++ s->bcd = val & 1;
++ }
++ }
++ } else {
++ /* Write Count. */
++ s = &pit_state->channels[addr];
++ switch (s->write_state) {
++ default:
++ case RW_STATE_LSB:
++ pit_load_count(kvm, addr, val);
++ break;
++ case RW_STATE_MSB:
++ pit_load_count(kvm, addr, val << 8);
++ break;
++ case RW_STATE_WORD0:
++ s->write_latch = val;
++ s->write_state = RW_STATE_WORD1;
++ break;
++ case RW_STATE_WORD1:
++ pit_load_count(kvm, addr, s->write_latch | (val << 8));
++ s->write_state = RW_STATE_WORD0;
++ break;
++ }
++ }
+
-+ f->flush_mm = NULL;
-+ f->flush_va = 0;
-+ spin_unlock(&f->tlbstate_lock);
++ mutex_unlock(&pit_state->lock);
+}
+
-+static int __cpuinit init_smp_flush(void)
++static void pit_ioport_read(struct kvm_io_device *this,
++ gpa_t addr, int len, void *data)
+{
-+ int i;
++ struct kvm_pit *pit = (struct kvm_pit *)this->private;
++ struct kvm_kpit_state *pit_state = &pit->pit_state;
++ struct kvm *kvm = pit->kvm;
++ int ret, count;
++ struct kvm_kpit_channel_state *s;
+
-+ for_each_possible_cpu(i)
-+ spin_lock_init(&per_cpu(flush_state, i).tlbstate_lock);
++ addr &= KVM_PIT_CHANNEL_MASK;
++ s = &pit_state->channels[addr];
+
-+ return 0;
++ mutex_lock(&pit_state->lock);
++
++ if (s->status_latched) {
++ s->status_latched = 0;
++ ret = s->status;
++ } else if (s->count_latched) {
++ switch (s->count_latched) {
++ default:
++ case RW_STATE_LSB:
++ ret = s->latched_count & 0xff;
++ s->count_latched = 0;
++ break;
++ case RW_STATE_MSB:
++ ret = s->latched_count >> 8;
++ s->count_latched = 0;
++ break;
++ case RW_STATE_WORD0:
++ ret = s->latched_count & 0xff;
++ s->count_latched = RW_STATE_MSB;
++ break;
++ }
++ } else {
++ switch (s->read_state) {
++ default:
++ case RW_STATE_LSB:
++ count = pit_get_count(kvm, addr);
++ ret = count & 0xff;
++ break;
++ case RW_STATE_MSB:
++ count = pit_get_count(kvm, addr);
++ ret = (count >> 8) & 0xff;
++ break;
++ case RW_STATE_WORD0:
++ count = pit_get_count(kvm, addr);
++ ret = count & 0xff;
++ s->read_state = RW_STATE_WORD1;
++ break;
++ case RW_STATE_WORD1:
++ count = pit_get_count(kvm, addr);
++ ret = (count >> 8) & 0xff;
++ s->read_state = RW_STATE_WORD0;
++ break;
++ }
++ }
++
++ if (len > sizeof(ret))
++ len = sizeof(ret);
++ memcpy(data, (char *)&ret, len);
++
++ mutex_unlock(&pit_state->lock);
+}
-+core_initcall(init_smp_flush);
+
-+void flush_tlb_current_task(void)
++static int pit_in_range(struct kvm_io_device *this, gpa_t addr)
+{
-+ struct mm_struct *mm = current->mm;
-+ cpumask_t cpu_mask;
++ return ((addr >= KVM_PIT_BASE_ADDRESS) &&
++ (addr < KVM_PIT_BASE_ADDRESS + KVM_PIT_MEM_LENGTH));
++}
+
-+ preempt_disable();
-+ cpu_mask = mm->cpu_vm_mask;
-+ cpu_clear(smp_processor_id(), cpu_mask);
++static void speaker_ioport_write(struct kvm_io_device *this,
++ gpa_t addr, int len, const void *data)
++{
++ struct kvm_pit *pit = (struct kvm_pit *)this->private;
++ struct kvm_kpit_state *pit_state = &pit->pit_state;
++ struct kvm *kvm = pit->kvm;
++ u32 val = *(u32 *) data;
++
++ mutex_lock(&pit_state->lock);
++ pit_state->speaker_data_on = (val >> 1) & 1;
++ pit_set_gate(kvm, 2, val & 1);
++ mutex_unlock(&pit_state->lock);
++}
++
++static void speaker_ioport_read(struct kvm_io_device *this,
++ gpa_t addr, int len, void *data)
++{
++ struct kvm_pit *pit = (struct kvm_pit *)this->private;
++ struct kvm_kpit_state *pit_state = &pit->pit_state;
++ struct kvm *kvm = pit->kvm;
++ unsigned int refresh_clock;
++ int ret;
++
++ /* Refresh clock toggles at about 15us. We approximate as 2^14ns. */
++ refresh_clock = ((unsigned int)ktime_to_ns(ktime_get()) >> 14) & 1;
++
++ mutex_lock(&pit_state->lock);
++ ret = ((pit_state->speaker_data_on << 1) | pit_get_gate(kvm, 2) |
++ (pit_get_out(kvm, 2) << 5) | (refresh_clock << 4));
++ if (len > sizeof(ret))
++ len = sizeof(ret);
++ memcpy(data, (char *)&ret, len);
++ mutex_unlock(&pit_state->lock);
++}
++
++static int speaker_in_range(struct kvm_io_device *this, gpa_t addr)
++{
++ return (addr == KVM_SPEAKER_BASE_ADDRESS);
++}
++
++void kvm_pit_reset(struct kvm_pit *pit)
++{
++ int i;
++ struct kvm_kpit_channel_state *c;
++
++ mutex_lock(&pit->pit_state.lock);
++ for (i = 0; i < 3; i++) {
++ c = &pit->pit_state.channels[i];
++ c->mode = 0xff;
++ c->gate = (i != 2);
++ pit_load_count(pit->kvm, i, 0);
++ }
++ mutex_unlock(&pit->pit_state.lock);
+
-+ local_flush_tlb();
-+ if (!cpus_empty(cpu_mask))
-+ flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
-+ preempt_enable();
++ atomic_set(&pit->pit_state.pit_timer.pending, 0);
++ pit->pit_state.inject_pending = 1;
+}
+
-+void flush_tlb_mm(struct mm_struct *mm)
++struct kvm_pit *kvm_create_pit(struct kvm *kvm)
+{
-+ cpumask_t cpu_mask;
++ struct kvm_pit *pit;
++ struct kvm_kpit_state *pit_state;
+
-+ preempt_disable();
-+ cpu_mask = mm->cpu_vm_mask;
-+ cpu_clear(smp_processor_id(), cpu_mask);
++ pit = kzalloc(sizeof(struct kvm_pit), GFP_KERNEL);
++ if (!pit)
++ return NULL;
+
-+ 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);
++ mutex_init(&pit->pit_state.lock);
++ mutex_lock(&pit->pit_state.lock);
+
-+ preempt_enable();
++ /* Initialize PIO device */
++ pit->dev.read = pit_ioport_read;
++ pit->dev.write = pit_ioport_write;
++ pit->dev.in_range = pit_in_range;
++ pit->dev.private = pit;
++ kvm_io_bus_register_dev(&kvm->pio_bus, &pit->dev);
++
++ pit->speaker_dev.read = speaker_ioport_read;
++ pit->speaker_dev.write = speaker_ioport_write;
++ pit->speaker_dev.in_range = speaker_in_range;
++ pit->speaker_dev.private = pit;
++ kvm_io_bus_register_dev(&kvm->pio_bus, &pit->speaker_dev);
++
++ kvm->arch.vpit = pit;
++ pit->kvm = kvm;
++
++ pit_state = &pit->pit_state;
++ pit_state->pit = pit;
++ hrtimer_init(&pit_state->pit_timer.timer,
++ CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
++ mutex_unlock(&pit->pit_state.lock);
++
++ kvm_pit_reset(pit);
++
++ return pit;
+}
+
-+void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
++void kvm_free_pit(struct kvm *kvm)
+{
-+ 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);
++ struct hrtimer *timer;
+
-+ if (current->active_mm == mm) {
-+ if (current->mm)
-+ __flush_tlb_one(va);
-+ else
-+ leave_mm(smp_processor_id());
++ if (kvm->arch.vpit) {
++ mutex_lock(&kvm->arch.vpit->pit_state.lock);
++ timer = &kvm->arch.vpit->pit_state.pit_timer.timer;
++ hrtimer_cancel(timer);
++ mutex_unlock(&kvm->arch.vpit->pit_state.lock);
++ kfree(kvm->arch.vpit);
+ }
++}
+
-+ if (!cpus_empty(cpu_mask))
-+ flush_tlb_others(cpu_mask, mm, va);
-+
-+ preempt_enable();
++void __inject_pit_timer_intr(struct kvm *kvm)
++{
++ mutex_lock(&kvm->lock);
++ kvm_ioapic_set_irq(kvm->arch.vioapic, 0, 1);
++ kvm_ioapic_set_irq(kvm->arch.vioapic, 0, 0);
++ kvm_pic_set_irq(pic_irqchip(kvm), 0, 1);
++ kvm_pic_set_irq(pic_irqchip(kvm), 0, 0);
++ mutex_unlock(&kvm->lock);
+}
+
-+static void do_flush_tlb_all(void *info)
++void kvm_inject_pit_timer_irqs(struct kvm_vcpu *vcpu)
+{
-+ unsigned long cpu = smp_processor_id();
++ struct kvm_pit *pit = vcpu->kvm->arch.vpit;
++ struct kvm *kvm = vcpu->kvm;
++ struct kvm_kpit_state *ps;
+
-+ __flush_tlb_all();
-+ if (read_pda(mmu_state) == TLBSTATE_LAZY)
-+ leave_mm(cpu);
++ if (vcpu && pit) {
++ ps = &pit->pit_state;
++
++ /* Try to inject pending interrupts when:
++ * 1. Pending exists
++ * 2. Last interrupt was accepted or waited for too long time*/
++ if (atomic_read(&ps->pit_timer.pending) &&
++ (ps->inject_pending ||
++ (jiffies - ps->last_injected_time
++ >= KVM_MAX_PIT_INTR_INTERVAL))) {
++ ps->inject_pending = 0;
++ __inject_pit_timer_intr(kvm);
++ ps->last_injected_time = jiffies;
++ }
++ }
+}
+
-+void flush_tlb_all(void)
++void kvm_pit_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
+{
-+ on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
++ struct kvm_arch *arch = &vcpu->kvm->arch;
++ struct kvm_kpit_state *ps;
++
++ if (vcpu && arch->vpit) {
++ ps = &arch->vpit->pit_state;
++ if (atomic_read(&ps->pit_timer.pending) &&
++ (((arch->vpic->pics[0].imr & 1) == 0 &&
++ arch->vpic->pics[0].irq_base == vec) ||
++ (arch->vioapic->redirtbl[0].fields.vector == vec &&
++ arch->vioapic->redirtbl[0].fields.mask != 1))) {
++ ps->inject_pending = 1;
++ atomic_dec(&ps->pit_timer.pending);
++ ps->channels[0].count_load_time = ktime_get();
++ }
++ }
+}
-diff --git a/arch/x86/kernel/trampoline.c b/arch/x86/kernel/trampoline.c
+diff --git a/arch/x86/kvm/i8254.h b/arch/x86/kvm/i8254.h
new file mode 100644
-index 0000000..abbf199
+index 0000000..db25c2a
--- /dev/null
-+++ b/arch/x86/kernel/trampoline.c
-@@ -0,0 +1,18 @@
-+#include <linux/io.h>
++++ b/arch/x86/kvm/i8254.h
+@@ -0,0 +1,63 @@
++#ifndef __I8254_H
++#define __I8254_H
+
-+#include <asm/trampoline.h>
++#include "iodev.h"
+
-+/* ready for x86_64, no harm for x86, since it will overwrite after alloc */
-+unsigned char *trampoline_base = __va(TRAMPOLINE_BASE);
++struct kvm_kpit_timer {
++ struct hrtimer timer;
++ int irq;
++ s64 period; /* unit: ns */
++ s64 scheduled;
++ ktime_t last_update;
++ atomic_t pending;
++};
++
++struct kvm_kpit_channel_state {
++ u32 count; /* can be 65536 */
++ u16 latched_count;
++ u8 count_latched;
++ u8 status_latched;
++ u8 status;
++ u8 read_state;
++ u8 write_state;
++ u8 write_latch;
++ u8 rw_mode;
++ u8 mode;
++ u8 bcd; /* not supported */
++ u8 gate; /* timer start */
++ ktime_t count_load_time;
++};
++
++struct kvm_kpit_state {
++ struct kvm_kpit_channel_state channels[3];
++ struct kvm_kpit_timer pit_timer;
++ u32 speaker_data_on;
++ struct mutex lock;
++ struct kvm_pit *pit;
++ bool inject_pending; /* if inject pending interrupts */
++ unsigned long last_injected_time;
++};
++
++struct kvm_pit {
++ unsigned long base_addresss;
++ struct kvm_io_device dev;
++ struct kvm_io_device speaker_dev;
++ struct kvm *kvm;
++ struct kvm_kpit_state pit_state;
++};
++
++#define KVM_PIT_BASE_ADDRESS 0x40
++#define KVM_SPEAKER_BASE_ADDRESS 0x61
++#define KVM_PIT_MEM_LENGTH 4
++#define KVM_PIT_FREQ 1193181
++#define KVM_MAX_PIT_INTR_INTERVAL HZ / 100
++#define KVM_PIT_CHANNEL_MASK 0x3
++
++void kvm_inject_pit_timer_irqs(struct kvm_vcpu *vcpu);
++void kvm_pit_timer_intr_post(struct kvm_vcpu *vcpu, int vec);
++void kvm_pit_load_count(struct kvm *kvm, int channel, u32 val);
++struct kvm_pit *kvm_create_pit(struct kvm *kvm);
++void kvm_free_pit(struct kvm *kvm);
++void kvm_pit_reset(struct kvm_pit *pit);
++
++#endif
+diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c
+index e571475..ce1f583 100644
+--- a/arch/x86/kvm/irq.c
++++ b/arch/x86/kvm/irq.c
+@@ -23,6 +23,22 @@
+ #include <linux/kvm_host.h>
+
+ #include "irq.h"
++#include "i8254.h"
+
+/*
-+ * Currently trivial. Write the real->protected mode
-+ * bootstrap into the page concerned. The caller
-+ * has made sure it's suitably aligned.
++ * check if there are pending timer events
++ * to be processed.
+ */
-+unsigned long setup_trampoline(void)
++int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
+{
-+ memcpy(trampoline_base, trampoline_data,
-+ trampoline_end - trampoline_data);
-+ return virt_to_phys(trampoline_base);
++ int ret;
++
++ ret = pit_has_pending_timer(vcpu);
++ ret |= apic_has_pending_timer(vcpu);
++
++ return ret;
+}
-diff --git a/arch/x86/kernel/trampoline_32.S b/arch/x86/kernel/trampoline_32.S
-index 6458067..d8ccc3c 100644
---- a/arch/x86/kernel/trampoline_32.S
-+++ b/arch/x86/kernel/trampoline_32.S
-@@ -33,7 +33,7 @@
-
- /* We can free up trampoline after bootup if cpu hotplug is not supported. */
- #ifndef CONFIG_HOTPLUG_CPU
--.section ".init.data","aw", at progbits
-+.section ".cpuinit.data","aw", at progbits
- #else
- .section .rodata,"a", at progbits
- #endif
-diff --git a/arch/x86/kernel/trampoline_64.S b/arch/x86/kernel/trampoline_64.S
-index 4aedd0b..894293c 100644
---- a/arch/x86/kernel/trampoline_64.S
-+++ b/arch/x86/kernel/trampoline_64.S
-@@ -30,12 +30,7 @@
- #include <asm/msr.h>
- #include <asm/segment.h>
++EXPORT_SYMBOL(kvm_cpu_has_pending_timer);
--/* 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
+ /*
+ * check if there is pending interrupt without
+@@ -66,6 +82,7 @@ EXPORT_SYMBOL_GPL(kvm_cpu_get_interrupt);
+ void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu)
+ {
+ kvm_inject_apic_timer_irqs(vcpu);
++ kvm_inject_pit_timer_irqs(vcpu);
+ /* TODO: PIT, RTC etc. */
+ }
+ EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs);
+@@ -73,6 +90,7 @@ EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs);
+ void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
+ {
+ kvm_apic_timer_intr_post(vcpu, vec);
++ kvm_pit_timer_intr_post(vcpu, vec);
+ /* TODO: PIT, RTC etc. */
+ }
+ EXPORT_SYMBOL_GPL(kvm_timer_intr_post);
+diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
+index fa5ed5d..1802134 100644
+--- a/arch/x86/kvm/irq.h
++++ b/arch/x86/kvm/irq.h
+@@ -85,4 +85,7 @@ void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu);
+ void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu);
+ void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu);
-diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
-index b22c01e..bde6f63 100644
---- a/arch/x86/kernel/traps_32.c
-+++ b/arch/x86/kernel/traps_32.c
-@@ -9,26 +9,28 @@
- * 'Traps.c' handles hardware traps and faults after we have saved some
- * state in 'asm.s'.
- */
--#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/kallsyms.h>
-+#include <linux/spinlock.h>
-+#include <linux/highmem.h>
-+#include <linux/kprobes.h>
-+#include <linux/uaccess.h>
-+#include <linux/utsname.h>
-+#include <linux/kdebug.h>
- #include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/ptrace.h>
- #include <linux/string.h>
-+#include <linux/unwind.h>
-+#include <linux/delay.h>
- #include <linux/errno.h>
-+#include <linux/kexec.h>
-+#include <linux/sched.h>
- #include <linux/timer.h>
--#include <linux/mm.h>
- #include <linux/init.h>
--#include <linux/delay.h>
--#include <linux/spinlock.h>
--#include <linux/interrupt.h>
--#include <linux/highmem.h>
--#include <linux/kallsyms.h>
--#include <linux/ptrace.h>
--#include <linux/utsname.h>
--#include <linux/kprobes.h>
--#include <linux/kexec.h>
--#include <linux/unwind.h>
--#include <linux/uaccess.h>
--#include <linux/nmi.h>
- #include <linux/bug.h>
-+#include <linux/nmi.h>
-+#include <linux/mm.h>
++int pit_has_pending_timer(struct kvm_vcpu *vcpu);
++int apic_has_pending_timer(struct kvm_vcpu *vcpu);
++
+ #endif
+diff --git a/arch/x86/kvm/kvm_svm.h b/arch/x86/kvm/kvm_svm.h
+index ecdfe97..65ef0fc 100644
+--- a/arch/x86/kvm/kvm_svm.h
++++ b/arch/x86/kvm/kvm_svm.h
+@@ -39,6 +39,8 @@ struct vcpu_svm {
+ unsigned long host_db_regs[NUM_DB_REGS];
+ unsigned long host_dr6;
+ unsigned long host_dr7;
++
++ u32 *msrpm;
+ };
- #ifdef CONFIG_EISA
- #include <linux/ioport.h>
-@@ -43,21 +45,18 @@
- #include <linux/edac.h>
#endif
+diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
+index 68a6b15..57ac4e4 100644
+--- a/arch/x86/kvm/lapic.c
++++ b/arch/x86/kvm/lapic.c
+@@ -338,10 +338,10 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
+ } else
+ apic_clear_vector(vector, apic->regs + APIC_TMR);
-+#include <asm/arch_hooks.h>
-+#include <asm/stacktrace.h>
- #include <asm/processor.h>
--#include <asm/system.h>
--#include <asm/io.h>
--#include <asm/atomic.h>
- #include <asm/debugreg.h>
-+#include <asm/atomic.h>
-+#include <asm/system.h>
-+#include <asm/unwind.h>
- #include <asm/desc.h>
- #include <asm/i387.h>
- #include <asm/nmi.h>
--#include <asm/unwind.h>
- #include <asm/smp.h>
--#include <asm/arch_hooks.h>
--#include <linux/kdebug.h>
--#include <asm/stacktrace.h>
--
--#include <linux/module.h>
-+#include <asm/io.h>
+- if (vcpu->arch.mp_state == VCPU_MP_STATE_RUNNABLE)
++ if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
+ kvm_vcpu_kick(vcpu);
+- else if (vcpu->arch.mp_state == VCPU_MP_STATE_HALTED) {
+- vcpu->arch.mp_state = VCPU_MP_STATE_RUNNABLE;
++ else if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED) {
++ vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+ if (waitqueue_active(&vcpu->wq))
+ wake_up_interruptible(&vcpu->wq);
+ }
+@@ -362,11 +362,11 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
+
+ case APIC_DM_INIT:
+ if (level) {
+- if (vcpu->arch.mp_state == VCPU_MP_STATE_RUNNABLE)
++ if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
+ printk(KERN_DEBUG
+ "INIT on a runnable vcpu %d\n",
+ vcpu->vcpu_id);
+- vcpu->arch.mp_state = VCPU_MP_STATE_INIT_RECEIVED;
++ vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
+ kvm_vcpu_kick(vcpu);
+ } else {
+ printk(KERN_DEBUG
+@@ -379,9 +379,9 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
+ case APIC_DM_STARTUP:
+ printk(KERN_DEBUG "SIPI to vcpu %d vector 0x%02x\n",
+ vcpu->vcpu_id, vector);
+- if (vcpu->arch.mp_state == VCPU_MP_STATE_INIT_RECEIVED) {
++ if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
+ vcpu->arch.sipi_vector = vector;
+- vcpu->arch.mp_state = VCPU_MP_STATE_SIPI_RECEIVED;
++ vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED;
+ if (waitqueue_active(&vcpu->wq))
+ wake_up_interruptible(&vcpu->wq);
+ }
+@@ -658,7 +658,7 @@ static void start_apic_timer(struct kvm_lapic *apic)
+ apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
+ PRIx64 ", "
+ "timer initial count 0x%x, period %lldns, "
+- "expire @ 0x%016" PRIx64 ".\n", __FUNCTION__,
++ "expire @ 0x%016" PRIx64 ".\n", __func__,
+ APIC_BUS_CYCLE_NS, ktime_to_ns(now),
+ apic_get_reg(apic, APIC_TMICT),
+ apic->timer.period,
+@@ -691,7 +691,7 @@ static void apic_mmio_write(struct kvm_io_device *this,
+ /* too common printing */
+ if (offset != APIC_EOI)
+ apic_debug("%s: offset 0x%x with length 0x%x, and value is "
+- "0x%x\n", __FUNCTION__, offset, len, val);
++ "0x%x\n", __func__, offset, len, val);
+
+ offset &= 0xff0;
+
+@@ -822,6 +822,7 @@ void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
+ apic_set_tpr(apic, ((cr8 & 0x0f) << 4)
+ | (apic_get_reg(apic, APIC_TASKPRI) & 4));
+ }
++EXPORT_SYMBOL_GPL(kvm_lapic_set_tpr);
- #include "mach_traps.h"
+ u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu)
+ {
+@@ -869,7 +870,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
+ struct kvm_lapic *apic;
+ int i;
-@@ -69,7 +68,7 @@ EXPORT_SYMBOL_GPL(used_vectors);
- asmlinkage int system_call(void);
+- apic_debug("%s\n", __FUNCTION__);
++ apic_debug("%s\n", __func__);
- /* Do we ignore FPU interrupts ? */
--char ignore_fpu_irq = 0;
-+char ignore_fpu_irq;
+ ASSERT(vcpu);
+ apic = vcpu->arch.apic;
+@@ -907,7 +908,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
+ apic_update_ppr(apic);
+
+ apic_debug(KERN_INFO "%s: vcpu=%p, id=%d, base_msr="
+- "0x%016" PRIx64 ", base_address=0x%0lx.\n", __FUNCTION__,
++ "0x%016" PRIx64 ", base_address=0x%0lx.\n", __func__,
+ vcpu, kvm_apic_id(apic),
+ vcpu->arch.apic_base, apic->base_address);
+ }
+@@ -940,7 +941,7 @@ static int __apic_timer_fn(struct kvm_lapic *apic)
+
+ atomic_inc(&apic->timer.pending);
+ if (waitqueue_active(q)) {
+- apic->vcpu->arch.mp_state = VCPU_MP_STATE_RUNNABLE;
++ apic->vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+ wake_up_interruptible(q);
+ }
+ if (apic_lvtt_period(apic)) {
+@@ -952,6 +953,16 @@ static int __apic_timer_fn(struct kvm_lapic *apic)
+ return result;
+ }
- /*
- * 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)
++int apic_has_pending_timer(struct kvm_vcpu *vcpu)
++{
++ struct kvm_lapic *lapic = vcpu->arch.apic;
++
++ if (lapic)
++ return atomic_read(&lapic->timer.pending);
++
++ return 0;
++}
++
+ static int __inject_apic_timer_irq(struct kvm_lapic *apic)
{
- #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
+ int vector;
+diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
+index e55af12..2ad6f54 100644
+--- a/arch/x86/kvm/mmu.c
++++ b/arch/x86/kvm/mmu.c
+@@ -27,11 +27,22 @@
+ #include <linux/highmem.h>
+ #include <linux/module.h>
+ #include <linux/swap.h>
++#include <linux/hugetlb.h>
++#include <linux/compiler.h>
- /* 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;
- };
+ #include <asm/page.h>
+ #include <asm/cmpxchg.h>
+ #include <asm/io.h>
--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;
++/*
++ * When setting this variable to true it enables Two-Dimensional-Paging
++ * where the hardware walks 2 page tables:
++ * 1. the guest-virtual to guest-physical
++ * 2. while doing 1. it walks guest-physical to host-physical
++ * If the hardware supports that we don't need to do shadow paging.
++ */
++bool tdp_enabled = false;
++
+ #undef MMU_DEBUG
-@@ -166,7 +167,7 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo,
- return bp;
- }
+ #undef AUDIT
+@@ -101,8 +112,6 @@ static int dbg = 1;
+ #define PT_FIRST_AVAIL_BITS_SHIFT 9
+ #define PT64_SECOND_AVAIL_BITS_SHIFT 52
--#define MSG(msg) ops->warning(data, msg)
-+#define MSG(msg) ops->warning(data, msg)
+-#define PT_SHADOW_IO_MARK (1ULL << PT_FIRST_AVAIL_BITS_SHIFT)
+-
+ #define VALID_PAGE(x) ((x) != INVALID_PAGE)
- 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,
+ #define PT64_LEVEL_BITS 9
+@@ -159,6 +168,13 @@ static int dbg = 1;
+ #define ACC_USER_MASK PT_USER_MASK
+ #define ACC_ALL (ACC_EXEC_MASK | ACC_WRITE_MASK | ACC_USER_MASK)
- if (!stack) {
- unsigned long dummy;
++struct kvm_pv_mmu_op_buffer {
++ void *ptr;
++ unsigned len;
++ unsigned processed;
++ char buf[512] __aligned(sizeof(long));
++};
+
- 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,
+ struct kvm_rmap_desc {
+ u64 *shadow_ptes[RMAP_EXT];
+ struct kvm_rmap_desc *more;
+@@ -200,11 +216,15 @@ static int is_present_pte(unsigned long pte)
- 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 int is_shadow_present_pte(u64 pte)
+ {
+- pte &= ~PT_SHADOW_IO_MARK;
+ return pte != shadow_trap_nonpresent_pte
+ && pte != shadow_notrap_nonpresent_pte;
}
- 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)
++static int is_large_pte(u64 pte)
++{
++ return pte & PT_PAGE_SIZE_MASK;
++}
++
+ static int is_writeble_pte(unsigned long pte)
{
- 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, "");
+ return pte & PT_WRITABLE_MASK;
+@@ -215,14 +235,14 @@ static int is_dirty_pte(unsigned long pte)
+ return pte & PT_DIRTY_MASK;
}
--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)
+-static int is_io_pte(unsigned long pte)
++static int is_rmap_pte(u64 pte)
{
- unsigned long *stack;
- int i;
+- return pte & PT_SHADOW_IO_MARK;
++ return is_shadow_present_pte(pte);
+ }
- if (sp == NULL) {
- if (task)
-- sp = (unsigned long*)task->thread.sp;
-+ sp = (unsigned long *)task->thread.sp;
- else
- sp = (unsigned long *)&sp;
- }
+-static int is_rmap_pte(u64 pte)
++static pfn_t spte_to_pfn(u64 pte)
+ {
+- return is_shadow_present_pte(pte);
++ return (pte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
+ }
- 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);
+ static gfn_t pse36_gfn_delta(u32 gpte)
+@@ -349,16 +369,100 @@ static void mmu_free_rmap_desc(struct kvm_rmap_desc *rd)
}
-@@ -299,8 +306,8 @@ void show_stack(struct task_struct *task, unsigned long *sp)
+ /*
++ * Return the pointer to the largepage write count for a given
++ * gfn, handling slots that are not large page aligned.
++ */
++static int *slot_largepage_idx(gfn_t gfn, struct kvm_memory_slot *slot)
++{
++ unsigned long idx;
++
++ idx = (gfn / KVM_PAGES_PER_HPAGE) -
++ (slot->base_gfn / KVM_PAGES_PER_HPAGE);
++ return &slot->lpage_info[idx].write_count;
++}
++
++static void account_shadowed(struct kvm *kvm, gfn_t gfn)
++{
++ int *write_count;
++
++ write_count = slot_largepage_idx(gfn, gfn_to_memslot(kvm, gfn));
++ *write_count += 1;
++ WARN_ON(*write_count > KVM_PAGES_PER_HPAGE);
++}
++
++static void unaccount_shadowed(struct kvm *kvm, gfn_t gfn)
++{
++ int *write_count;
++
++ write_count = slot_largepage_idx(gfn, gfn_to_memslot(kvm, gfn));
++ *write_count -= 1;
++ WARN_ON(*write_count < 0);
++}
++
++static int has_wrprotected_page(struct kvm *kvm, gfn_t gfn)
++{
++ struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn);
++ int *largepage_idx;
++
++ if (slot) {
++ largepage_idx = slot_largepage_idx(gfn, slot);
++ return *largepage_idx;
++ }
++
++ return 1;
++}
++
++static int host_largepage_backed(struct kvm *kvm, gfn_t gfn)
++{
++ struct vm_area_struct *vma;
++ unsigned long addr;
++
++ addr = gfn_to_hva(kvm, gfn);
++ if (kvm_is_error_hva(addr))
++ return 0;
++
++ vma = find_vma(current->mm, addr);
++ if (vma && is_vm_hugetlb_page(vma))
++ return 1;
++
++ return 0;
++}
++
++static int is_largepage_backed(struct kvm_vcpu *vcpu, gfn_t large_gfn)
++{
++ struct kvm_memory_slot *slot;
++
++ if (has_wrprotected_page(vcpu->kvm, large_gfn))
++ return 0;
++
++ if (!host_largepage_backed(vcpu->kvm, large_gfn))
++ return 0;
++
++ slot = gfn_to_memslot(vcpu->kvm, large_gfn);
++ if (slot && slot->dirty_bitmap)
++ return 0;
++
++ return 1;
++}
++
++/*
+ * Take gfn and return the reverse mapping to it.
+ * Note: gfn must be unaliased before this function get called
*/
- void dump_stack(void)
+
+-static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn)
++static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn, int lpage)
{
-- unsigned long stack;
- unsigned long bp = 0;
-+ unsigned long stack;
+ struct kvm_memory_slot *slot;
++ unsigned long idx;
- #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);
+ slot = gfn_to_memslot(kvm, gfn);
+- return &slot->rmap[gfn - slot->base_gfn];
++ if (!lpage)
++ return &slot->rmap[gfn - slot->base_gfn];
++
++ idx = (gfn / KVM_PAGES_PER_HPAGE) -
++ (slot->base_gfn / KVM_PAGES_PER_HPAGE);
++
++ return &slot->lpage_info[idx].rmap_pde;
}
-@@ -323,6 +331,7 @@ void show_registers(struct pt_regs *regs)
+ /*
+@@ -370,7 +474,7 @@ static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn)
+ * If rmapp bit zero is one, (then rmap & ~1) points to a struct kvm_rmap_desc
+ * containing more mappings.
+ */
+-static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
++static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
+ {
+ struct kvm_mmu_page *sp;
+ struct kvm_rmap_desc *desc;
+@@ -382,7 +486,7 @@ static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
+ gfn = unalias_gfn(vcpu->kvm, gfn);
+ sp = page_header(__pa(spte));
+ sp->gfns[spte - sp->spt] = gfn;
+- rmapp = gfn_to_rmap(vcpu->kvm, gfn);
++ rmapp = gfn_to_rmap(vcpu->kvm, gfn, lpage);
+ if (!*rmapp) {
+ rmap_printk("rmap_add: %p %llx 0->1\n", spte, *spte);
+ *rmapp = (unsigned long)spte;
+@@ -435,20 +539,21 @@ static void rmap_remove(struct kvm *kvm, u64 *spte)
+ struct kvm_rmap_desc *desc;
+ struct kvm_rmap_desc *prev_desc;
+ struct kvm_mmu_page *sp;
+- struct page *page;
++ pfn_t pfn;
+ unsigned long *rmapp;
+ int i;
- 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;
+ if (!is_rmap_pte(*spte))
+ return;
+ sp = page_header(__pa(spte));
+- page = pfn_to_page((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT);
+- mark_page_accessed(page);
++ pfn = spte_to_pfn(*spte);
++ if (*spte & PT_ACCESSED_MASK)
++ kvm_set_pfn_accessed(pfn);
+ if (is_writeble_pte(*spte))
+- kvm_release_page_dirty(page);
++ kvm_release_pfn_dirty(pfn);
+ else
+- kvm_release_page_clean(page);
+- rmapp = gfn_to_rmap(kvm, sp->gfns[spte - sp->spt]);
++ kvm_release_pfn_clean(pfn);
++ rmapp = gfn_to_rmap(kvm, sp->gfns[spte - sp->spt], is_large_pte(*spte));
+ if (!*rmapp) {
+ printk(KERN_ERR "rmap_remove: %p %llx 0->BUG\n", spte, *spte);
+ BUG();
+@@ -514,7 +619,7 @@ static void rmap_write_protect(struct kvm *kvm, u64 gfn)
+ int write_protected = 0;
- 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)
+ gfn = unalias_gfn(kvm, gfn);
+- rmapp = gfn_to_rmap(kvm, gfn);
++ rmapp = gfn_to_rmap(kvm, gfn, 0);
+
+ spte = rmap_next(kvm, rmapp, NULL);
+ while (spte) {
+@@ -527,8 +632,35 @@ static void rmap_write_protect(struct kvm *kvm, u64 gfn)
}
+ spte = rmap_next(kvm, rmapp, spte);
}
- printk("\n");
--}
-+}
++ if (write_protected) {
++ pfn_t pfn;
++
++ spte = rmap_next(kvm, rmapp, NULL);
++ pfn = spte_to_pfn(*spte);
++ kvm_set_pfn_dirty(pfn);
++ }
++
++ /* check for huge page mappings */
++ rmapp = gfn_to_rmap(kvm, gfn, 1);
++ spte = rmap_next(kvm, rmapp, NULL);
++ while (spte) {
++ BUG_ON(!spte);
++ BUG_ON(!(*spte & PT_PRESENT_MASK));
++ BUG_ON((*spte & (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK)) != (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK));
++ pgprintk("rmap_write_protect(large): spte %p %llx %lld\n", spte, *spte, gfn);
++ if (is_writeble_pte(*spte)) {
++ rmap_remove(kvm, spte);
++ --kvm->stat.lpages;
++ set_shadow_pte(spte, shadow_trap_nonpresent_pte);
++ write_protected = 1;
++ }
++ spte = rmap_next(kvm, rmapp, spte);
++ }
++
+ if (write_protected)
+ kvm_flush_remote_tlbs(kvm);
++
++ account_shadowed(kvm, gfn);
+ }
- int is_valid_bugaddr(unsigned long ip)
- {
-@@ -377,10 +386,10 @@ int is_valid_bugaddr(unsigned long ip)
+ #ifdef MMU_DEBUG
+@@ -538,8 +670,8 @@ static int is_empty_shadow_page(u64 *spt)
+ u64 *end;
- static int die_counter;
+ for (pos = spt, end = pos + PAGE_SIZE / sizeof(u64); pos != end; pos++)
+- if ((*pos & ~PT_SHADOW_IO_MARK) != shadow_trap_nonpresent_pte) {
+- printk(KERN_ERR "%s: %p %llx\n", __FUNCTION__,
++ if (*pos != shadow_trap_nonpresent_pte) {
++ printk(KERN_ERR "%s: %p %llx\n", __func__,
+ pos, *pos);
+ return 0;
+ }
+@@ -559,7 +691,7 @@ static void kvm_mmu_free_page(struct kvm *kvm, struct kvm_mmu_page *sp)
--int __kprobes __die(const char * str, struct pt_regs * regs, long err)
-+int __kprobes __die(const char *str, struct pt_regs *regs, long err)
+ static unsigned kvm_page_table_hashfn(gfn_t gfn)
{
-- unsigned long sp;
- unsigned short ss;
-+ unsigned long sp;
+- return gfn;
++ return gfn & ((1 << KVM_MMU_HASH_SHIFT) - 1);
+ }
- 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");
+ static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu,
+@@ -662,13 +794,14 @@ static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm, gfn_t gfn)
+ struct kvm_mmu_page *sp;
+ struct hlist_node *node;
- 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;
+- pgprintk("%s: looking for gfn %lx\n", __FUNCTION__, gfn);
+- index = kvm_page_table_hashfn(gfn) % KVM_NUM_MMU_PAGES;
++ pgprintk("%s: looking for gfn %lx\n", __func__, gfn);
++ index = kvm_page_table_hashfn(gfn);
+ bucket = &kvm->arch.mmu_page_hash[index];
+ hlist_for_each_entry(sp, node, bucket, hash_link)
+- if (sp->gfn == gfn && !sp->role.metaphysical) {
++ if (sp->gfn == gfn && !sp->role.metaphysical
++ && !sp->role.invalid) {
+ pgprintk("%s: found role %x\n",
+- __FUNCTION__, sp->role.word);
++ __func__, sp->role.word);
+ return sp;
+ }
+ return NULL;
+@@ -699,27 +832,27 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
+ quadrant &= (1 << ((PT32_PT_BITS - PT64_PT_BITS) * level)) - 1;
+ role.quadrant = quadrant;
+ }
+- pgprintk("%s: looking gfn %lx role %x\n", __FUNCTION__,
++ pgprintk("%s: looking gfn %lx role %x\n", __func__,
+ gfn, role.word);
+- index = kvm_page_table_hashfn(gfn) % KVM_NUM_MMU_PAGES;
++ index = kvm_page_table_hashfn(gfn);
+ bucket = &vcpu->kvm->arch.mmu_page_hash[index];
+ hlist_for_each_entry(sp, node, bucket, hash_link)
+ if (sp->gfn == gfn && sp->role.word == role.word) {
+ mmu_page_add_parent_pte(vcpu, sp, parent_pte);
+- pgprintk("%s: found\n", __FUNCTION__);
++ pgprintk("%s: found\n", __func__);
+ return sp;
+ }
+ ++vcpu->kvm->stat.mmu_cache_miss;
+ sp = kvm_mmu_alloc_page(vcpu, parent_pte);
+ if (!sp)
+ return sp;
+- pgprintk("%s: adding gfn %lx role %x\n", __FUNCTION__, gfn, role.word);
++ pgprintk("%s: adding gfn %lx role %x\n", __func__, gfn, role.word);
+ sp->gfn = gfn;
+ sp->role = role;
+ hlist_add_head(&sp->hash_link, bucket);
+- vcpu->arch.mmu.prefetch_page(vcpu, sp);
+ if (!metaphysical)
+ rmap_write_protect(vcpu->kvm, gfn);
++ vcpu->arch.mmu.prefetch_page(vcpu, sp);
+ return sp;
}
- /*
-- * 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);
+@@ -745,11 +878,17 @@ static void kvm_mmu_page_unlink_children(struct kvm *kvm,
+ for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
+ ent = pt[i];
+
++ if (is_shadow_present_pte(ent)) {
++ if (!is_large_pte(ent)) {
++ ent &= PT64_BASE_ADDR_MASK;
++ mmu_page_remove_parent_pte(page_header(ent),
++ &pt[i]);
++ } else {
++ --kvm->stat.lpages;
++ rmap_remove(kvm, &pt[i]);
++ }
++ }
+ pt[i] = shadow_trap_nonpresent_pte;
+- if (!is_shadow_present_pte(ent))
+- continue;
+- ent &= PT64_BASE_ADDR_MASK;
+- mmu_page_remove_parent_pte(page_header(ent), &pt[i]);
+ }
+ kvm_flush_remote_tlbs(kvm);
+ }
+@@ -789,10 +928,15 @@ static void kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp)
+ }
+ kvm_mmu_page_unlink_children(kvm, sp);
+ if (!sp->root_count) {
++ if (!sp->role.metaphysical)
++ unaccount_shadowed(kvm, sp->gfn);
+ hlist_del(&sp->hash_link);
+ kvm_mmu_free_page(kvm, sp);
- } else
+ } else {
- raw_local_irq_save(flags);
+ list_move(&sp->link, &kvm->arch.active_mmu_pages);
++ sp->role.invalid = 1;
++ kvm_reload_remote_mmus(kvm);
+ }
-
- 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);
+ kvm_mmu_reset_last_pte_updated(kvm);
}
--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;
+@@ -838,13 +982,13 @@ static int kvm_mmu_unprotect_page(struct kvm *kvm, gfn_t gfn)
+ struct hlist_node *node, *n;
+ int r;
-- 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;
+- pgprintk("%s: looking for gfn %lx\n", __FUNCTION__, gfn);
++ pgprintk("%s: looking for gfn %lx\n", __func__, gfn);
+ r = 0;
+- index = kvm_page_table_hashfn(gfn) % KVM_NUM_MMU_PAGES;
++ index = kvm_page_table_hashfn(gfn);
+ bucket = &kvm->arch.mmu_page_hash[index];
+ hlist_for_each_entry_safe(sp, node, n, bucket, hash_link)
+ if (sp->gfn == gfn && !sp->role.metaphysical) {
+- pgprintk("%s: gfn %lx role %x\n", __FUNCTION__, gfn,
++ pgprintk("%s: gfn %lx role %x\n", __func__, gfn,
+ sp->role.word);
+ kvm_mmu_zap_page(kvm, sp);
+ r = 1;
+@@ -857,7 +1001,7 @@ static void mmu_unshadow(struct kvm *kvm, gfn_t gfn)
+ struct kvm_mmu_page *sp;
+
+ while ((sp = kvm_mmu_lookup_page(kvm, gfn)) != NULL) {
+- pgprintk("%s: zap %lx %x\n", __FUNCTION__, gfn, sp->role.word);
++ pgprintk("%s: zap %lx %x\n", __func__, gfn, sp->role.word);
+ kvm_mmu_zap_page(kvm, sp);
+ }
+ }
+@@ -889,26 +1033,39 @@ struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva)
+ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
+ unsigned pt_access, unsigned pte_access,
+ int user_fault, int write_fault, int dirty,
+- int *ptwrite, gfn_t gfn, struct page *page)
++ int *ptwrite, int largepage, gfn_t gfn,
++ pfn_t pfn, bool speculative)
+ {
+ u64 spte;
+ int was_rmapped = 0;
+ int was_writeble = is_writeble_pte(*shadow_pte);
+- hfn_t host_pfn = (*shadow_pte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
+
+ pgprintk("%s: spte %llx access %x write_fault %d"
+ " user_fault %d gfn %lx\n",
+- __FUNCTION__, *shadow_pte, pt_access,
++ __func__, *shadow_pte, pt_access,
+ write_fault, user_fault, gfn);
-- if (info)
-- force_sig_info(signr, info, tsk);
+ if (is_rmap_pte(*shadow_pte)) {
+- if (host_pfn != page_to_pfn(page)) {
++ /*
++ * If we overwrite a PTE page pointer with a 2MB PMD, unlink
++ * the parent of the now unreachable PTE.
++ */
++ if (largepage && !is_large_pte(*shadow_pte)) {
++ struct kvm_mmu_page *child;
++ u64 pte = *shadow_pte;
++
++ child = page_header(pte & PT64_BASE_ADDR_MASK);
++ mmu_page_remove_parent_pte(child, shadow_pte);
++ } else if (pfn != spte_to_pfn(*shadow_pte)) {
+ pgprintk("hfn old %lx new %lx\n",
+- host_pfn, page_to_pfn(page));
++ spte_to_pfn(*shadow_pte), pfn);
+ rmap_remove(vcpu->kvm, shadow_pte);
++ } else {
++ if (largepage)
++ was_rmapped = is_large_pte(*shadow_pte);
++ else
++ was_rmapped = 1;
+ }
- 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);
+- was_rmapped = 1;
}
-+ return;
-- vm86_trap: {
-- int ret = handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr);
-- if (ret) goto trap_signal;
+ /*
+@@ -917,6 +1074,8 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
+ * demand paging).
+ */
+ spte = PT_PRESENT_MASK | PT_DIRTY_MASK;
++ if (!speculative)
++ pte_access |= PT_ACCESSED_MASK;
+ if (!dirty)
+ pte_access &= ~ACC_WRITE_MASK;
+ if (!(pte_access & ACC_EXEC_MASK))
+@@ -925,15 +1084,10 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
+ spte |= PT_PRESENT_MASK;
+ if (pte_access & ACC_USER_MASK)
+ spte |= PT_USER_MASK;
++ if (largepage)
++ spte |= PT_PAGE_SIZE_MASK;
+
+- if (is_error_page(page)) {
+- set_shadow_pte(shadow_pte,
+- shadow_trap_nonpresent_pte | PT_SHADOW_IO_MARK);
+- kvm_release_page_clean(page);
- return;
- }
-+vm86_trap:
-+ if (handle_vm86_trap((struct kernel_vm86_regs *) regs,
-+ error_code, trapnr))
-+ goto trap_signal;
-+ return;
- }
+-
+- spte |= page_to_phys(page);
++ spte |= (u64)pfn << PAGE_SHIFT;
--#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); \
+ if ((pte_access & ACC_WRITE_MASK)
+ || (write_fault && !is_write_protection(vcpu) && !user_fault)) {
+@@ -946,9 +1100,10 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
+ }
+
+ shadow = kvm_mmu_lookup_page(vcpu->kvm, gfn);
+- if (shadow) {
++ if (shadow ||
++ (largepage && has_wrprotected_page(vcpu->kvm, gfn))) {
+ pgprintk("%s: found shadow page for %lx, marking ro\n",
+- __FUNCTION__, gfn);
++ __func__, gfn);
+ pte_access &= ~ACC_WRITE_MASK;
+ if (is_writeble_pte(spte)) {
+ spte &= ~PT_WRITABLE_MASK;
+@@ -964,18 +1119,25 @@ unshadowed:
+ if (pte_access & ACC_WRITE_MASK)
+ mark_page_dirty(vcpu->kvm, gfn);
+
+- pgprintk("%s: setting spte %llx\n", __FUNCTION__, spte);
++ pgprintk("%s: setting spte %llx\n", __func__, spte);
++ pgprintk("instantiating %s PTE (%s) at %d (%llx) addr %llx\n",
++ (spte&PT_PAGE_SIZE_MASK)? "2MB" : "4kB",
++ (spte&PT_WRITABLE_MASK)?"RW":"R", gfn, spte, shadow_pte);
+ set_shadow_pte(shadow_pte, spte);
++ if (!was_rmapped && (spte & PT_PAGE_SIZE_MASK)
++ && (spte & PT_PRESENT_MASK))
++ ++vcpu->kvm->stat.lpages;
++
+ page_header_update_slot(vcpu->kvm, shadow_pte, gfn);
+ if (!was_rmapped) {
+- rmap_add(vcpu, shadow_pte, gfn);
++ rmap_add(vcpu, shadow_pte, gfn, largepage);
+ if (!is_rmap_pte(*shadow_pte))
+- kvm_release_page_clean(page);
++ kvm_release_pfn_clean(pfn);
+ } else {
+ if (was_writeble)
+- kvm_release_page_dirty(page);
++ kvm_release_pfn_dirty(pfn);
+ else
+- kvm_release_page_clean(page);
++ kvm_release_pfn_clean(pfn);
+ }
+ if (!ptwrite || !*ptwrite)
+ vcpu->arch.last_pte_updated = shadow_pte;
+@@ -985,10 +1147,10 @@ static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
+ {
}
--#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); \
- }
+-static int __nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write,
+- gfn_t gfn, struct page *page)
++static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
++ int largepage, gfn_t gfn, pfn_t pfn,
++ int level)
+ {
+- int level = PT32E_ROOT_LEVEL;
+ hpa_t table_addr = vcpu->arch.mmu.root_hpa;
+ int pt_write = 0;
--#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); \
- }
+@@ -1001,8 +1163,14 @@ static int __nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write,
--#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); \
- }
+ if (level == 1) {
+ mmu_set_spte(vcpu, &table[index], ACC_ALL, ACC_ALL,
+- 0, write, 1, &pt_write, gfn, page);
+- return pt_write || is_io_pte(table[index]);
++ 0, write, 1, &pt_write, 0, gfn, pfn, false);
++ return pt_write;
++ }
++
++ if (largepage && level == 2) {
++ mmu_set_spte(vcpu, &table[index], ACC_ALL, ACC_ALL,
++ 0, write, 1, &pt_write, 1, gfn, pfn, false);
++ return pt_write;
+ }
--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)
+ if (table[index] == shadow_trap_nonpresent_pte) {
+@@ -1016,7 +1184,7 @@ static int __nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write,
+ 1, ACC_ALL, &table[index]);
+ if (!new_table) {
+ pgprintk("nonpaging_map: ENOMEM\n");
+- kvm_release_page_clean(page);
++ kvm_release_pfn_clean(pfn);
+ return -ENOMEM;
+ }
--void __kprobes do_general_protection(struct pt_regs * regs,
-- long error_code)
-+void __kprobes do_general_protection(struct pt_regs *regs, long error_code)
+@@ -1030,21 +1198,30 @@ static int __nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write,
+ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn)
{
-- 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;
+ int r;
+-
+- struct page *page;
+-
+- down_read(&vcpu->kvm->slots_lock);
++ int largepage = 0;
++ pfn_t pfn;
+
+ down_read(¤t->mm->mmap_sem);
+- page = gfn_to_page(vcpu->kvm, gfn);
++ if (is_largepage_backed(vcpu, gfn & ~(KVM_PAGES_PER_HPAGE-1))) {
++ gfn &= ~(KVM_PAGES_PER_HPAGE-1);
++ largepage = 1;
++ }
++
++ pfn = gfn_to_pfn(vcpu->kvm, gfn);
+ up_read(¤t->mm->mmap_sem);
+
++ /* mmio */
++ if (is_error_pfn(pfn)) {
++ kvm_release_pfn_clean(pfn);
++ return 1;
++ }
+
-+ cpu = get_cpu();
-+ tss = &per_cpu(init_tss, cpu);
-+ thread = ¤t->thread;
+ spin_lock(&vcpu->kvm->mmu_lock);
+ kvm_mmu_free_some_pages(vcpu);
+- r = __nonpaging_map(vcpu, v, write, gfn, page);
++ r = __direct_map(vcpu, v, write, largepage, gfn, pfn,
++ PT32E_ROOT_LEVEL);
+ spin_unlock(&vcpu->kvm->mmu_lock);
- /*
- * 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();
-+
+- up_read(&vcpu->kvm->slots_lock);
+
+ return r;
+ }
+@@ -1073,6 +1250,8 @@ static void mmu_free_roots(struct kvm_vcpu *vcpu)
+
+ sp = page_header(root);
+ --sp->root_count;
++ if (!sp->root_count && sp->role.invalid)
++ kvm_mmu_zap_page(vcpu->kvm, sp);
+ vcpu->arch.mmu.root_hpa = INVALID_PAGE;
+ spin_unlock(&vcpu->kvm->mmu_lock);
return;
+@@ -1085,6 +1264,8 @@ static void mmu_free_roots(struct kvm_vcpu *vcpu)
+ root &= PT64_BASE_ADDR_MASK;
+ sp = page_header(root);
+ --sp->root_count;
++ if (!sp->root_count && sp->role.invalid)
++ kvm_mmu_zap_page(vcpu->kvm, sp);
+ }
+ vcpu->arch.mmu.pae_root[i] = INVALID_PAGE;
}
- put_cpu();
+@@ -1097,6 +1278,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
+ int i;
+ gfn_t root_gfn;
+ struct kvm_mmu_page *sp;
++ int metaphysical = 0;
+
+ root_gfn = vcpu->arch.cr3 >> PAGE_SHIFT;
+
+@@ -1105,14 +1287,20 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
+ hpa_t root = vcpu->arch.mmu.root_hpa;
+
+ ASSERT(!VALID_PAGE(root));
++ if (tdp_enabled)
++ metaphysical = 1;
+ sp = kvm_mmu_get_page(vcpu, root_gfn, 0,
+- PT64_ROOT_LEVEL, 0, ACC_ALL, NULL);
++ PT64_ROOT_LEVEL, metaphysical,
++ ACC_ALL, NULL);
+ root = __pa(sp->spt);
+ ++sp->root_count;
+ vcpu->arch.mmu.root_hpa = root;
+ return;
+ }
+ #endif
++ metaphysical = !is_paging(vcpu);
++ if (tdp_enabled)
++ metaphysical = 1;
+ for (i = 0; i < 4; ++i) {
+ hpa_t root = vcpu->arch.mmu.pae_root[i];
-- if (regs->flags & VM_MASK)
-+ if (regs->flags & X86_VM_MASK)
- goto gp_in_vm86;
+@@ -1126,7 +1314,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
+ } else if (vcpu->arch.mmu.root_level == 0)
+ root_gfn = 0;
+ sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30,
+- PT32_ROOT_LEVEL, !is_paging(vcpu),
++ PT32_ROOT_LEVEL, metaphysical,
+ ACC_ALL, NULL);
+ root = __pa(sp->spt);
+ ++sp->root_count;
+@@ -1146,7 +1334,7 @@ static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
+ gfn_t gfn;
+ int r;
- if (!user_mode(regs))
-@@ -636,6 +651,7 @@ void __kprobes do_general_protection(struct pt_regs * regs,
+- pgprintk("%s: gva %lx error %x\n", __FUNCTION__, gva, error_code);
++ pgprintk("%s: gva %lx error %x\n", __func__, gva, error_code);
+ r = mmu_topup_memory_caches(vcpu);
+ if (r)
+ return r;
+@@ -1160,6 +1348,41 @@ static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
+ error_code & PFERR_WRITE_MASK, gfn);
+ }
- current->thread.error_code = error_code;
- current->thread.trap_no = 13;
++static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa,
++ u32 error_code)
++{
++ pfn_t pfn;
++ int r;
++ int largepage = 0;
++ gfn_t gfn = gpa >> PAGE_SHIFT;
+
- if (show_unhandled_signals && unhandled_signal(current, SIGSEGV) &&
- printk_ratelimit()) {
- printk(KERN_INFO
-@@ -665,22 +681,25 @@ gp_in_kernel:
- }
++ ASSERT(vcpu);
++ ASSERT(VALID_PAGE(vcpu->arch.mmu.root_hpa));
++
++ r = mmu_topup_memory_caches(vcpu);
++ if (r)
++ return r;
++
++ down_read(¤t->mm->mmap_sem);
++ if (is_largepage_backed(vcpu, gfn & ~(KVM_PAGES_PER_HPAGE-1))) {
++ gfn &= ~(KVM_PAGES_PER_HPAGE-1);
++ largepage = 1;
++ }
++ pfn = gfn_to_pfn(vcpu->kvm, gfn);
++ up_read(¤t->mm->mmap_sem);
++ if (is_error_pfn(pfn)) {
++ kvm_release_pfn_clean(pfn);
++ return 1;
++ }
++ spin_lock(&vcpu->kvm->mmu_lock);
++ kvm_mmu_free_some_pages(vcpu);
++ r = __direct_map(vcpu, gpa, error_code & PFERR_WRITE_MASK,
++ largepage, gfn, pfn, TDP_ROOT_LEVEL);
++ spin_unlock(&vcpu->kvm->mmu_lock);
++
++ return r;
++}
++
+ static void nonpaging_free(struct kvm_vcpu *vcpu)
+ {
+ mmu_free_roots(vcpu);
+@@ -1188,7 +1411,7 @@ void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu)
+
+ static void paging_new_cr3(struct kvm_vcpu *vcpu)
+ {
+- pgprintk("%s: cr3 %lx\n", __FUNCTION__, vcpu->arch.cr3);
++ pgprintk("%s: cr3 %lx\n", __func__, vcpu->arch.cr3);
+ mmu_free_roots(vcpu);
}
--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)
+@@ -1253,7 +1476,35 @@ static int paging32E_init_context(struct kvm_vcpu *vcpu)
+ return paging64_init_context_common(vcpu, PT32E_ROOT_LEVEL);
+ }
+
+-static int init_kvm_mmu(struct kvm_vcpu *vcpu)
++static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
++{
++ struct kvm_mmu *context = &vcpu->arch.mmu;
++
++ context->new_cr3 = nonpaging_new_cr3;
++ context->page_fault = tdp_page_fault;
++ context->free = nonpaging_free;
++ context->prefetch_page = nonpaging_prefetch_page;
++ context->shadow_root_level = TDP_ROOT_LEVEL;
++ context->root_hpa = INVALID_PAGE;
++
++ if (!is_paging(vcpu)) {
++ context->gva_to_gpa = nonpaging_gva_to_gpa;
++ context->root_level = 0;
++ } else if (is_long_mode(vcpu)) {
++ context->gva_to_gpa = paging64_gva_to_gpa;
++ context->root_level = PT64_ROOT_LEVEL;
++ } else if (is_pae(vcpu)) {
++ context->gva_to_gpa = paging64_gva_to_gpa;
++ context->root_level = PT32E_ROOT_LEVEL;
++ } else {
++ context->gva_to_gpa = paging32_gva_to_gpa;
++ context->root_level = PT32_ROOT_LEVEL;
++ }
++
++ return 0;
++}
++
++static int init_kvm_softmmu(struct kvm_vcpu *vcpu)
{
-- 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());
+ ASSERT(vcpu);
+ ASSERT(!VALID_PAGE(vcpu->arch.mmu.root_hpa));
+@@ -1268,6 +1519,16 @@ static int init_kvm_mmu(struct kvm_vcpu *vcpu)
+ return paging32_init_context(vcpu);
+ }
+
++static int init_kvm_mmu(struct kvm_vcpu *vcpu)
++{
++ vcpu->arch.update_pte.pfn = bad_pfn;
+
-+ printk(KERN_EMERG
-+ "You have some hardware problem, likely on the PCI bus.\n");
++ if (tdp_enabled)
++ return init_kvm_tdp_mmu(vcpu);
++ else
++ return init_kvm_softmmu(vcpu);
++}
++
+ static void destroy_kvm_mmu(struct kvm_vcpu *vcpu)
+ {
+ ASSERT(vcpu);
+@@ -1316,7 +1577,8 @@ static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,
- #if defined(CONFIG_EDAC)
-- if(edac_handler_set()) {
-+ if (edac_handler_set()) {
- edac_atomic_assert_error();
+ pte = *spte;
+ if (is_shadow_present_pte(pte)) {
+- if (sp->role.level == PT_PAGE_TABLE_LEVEL)
++ if (sp->role.level == PT_PAGE_TABLE_LEVEL ||
++ is_large_pte(pte))
+ rmap_remove(vcpu->kvm, spte);
+ else {
+ child = page_header(pte & PT64_BASE_ADDR_MASK);
+@@ -1324,24 +1586,26 @@ static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,
+ }
+ }
+ set_shadow_pte(spte, shadow_trap_nonpresent_pte);
++ if (is_large_pte(pte))
++ --vcpu->kvm->stat.lpages;
+ }
+
+ static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu,
+ struct kvm_mmu_page *sp,
+ u64 *spte,
+- const void *new, int bytes,
+- int offset_in_pte)
++ const void *new)
+ {
+- if (sp->role.level != PT_PAGE_TABLE_LEVEL) {
++ if ((sp->role.level != PT_PAGE_TABLE_LEVEL)
++ && !vcpu->arch.update_pte.largepage) {
+ ++vcpu->kvm->stat.mmu_pde_zapped;
return;
}
- #endif
- if (panic_on_unrecovered_nmi)
-- panic("NMI: Not continuing");
-+ panic("NMI: Not continuing");
+ ++vcpu->kvm->stat.mmu_pte_updated;
+ if (sp->role.glevels == PT32_ROOT_LEVEL)
+- paging32_update_pte(vcpu, sp, spte, new, bytes, offset_in_pte);
++ paging32_update_pte(vcpu, sp, spte, new);
+ else
+- paging64_update_pte(vcpu, sp, spte, new, bytes, offset_in_pte);
++ paging64_update_pte(vcpu, sp, spte, new);
+ }
- printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+ static bool need_remote_flush(u64 old, u64 new)
+@@ -1378,7 +1642,9 @@ static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
+ gfn_t gfn;
+ int r;
+ u64 gpte = 0;
+- struct page *page;
++ pfn_t pfn;
++
++ vcpu->arch.update_pte.largepage = 0;
-@@ -688,8 +707,8 @@ mem_parity_error(unsigned char reason, struct pt_regs * regs)
- clear_mem_error(reason);
+ if (bytes != 4 && bytes != 8)
+ return;
+@@ -1408,11 +1674,19 @@ static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
+ gfn = (gpte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
+
+ down_read(¤t->mm->mmap_sem);
+- page = gfn_to_page(vcpu->kvm, gfn);
++ if (is_large_pte(gpte) && is_largepage_backed(vcpu, gfn)) {
++ gfn &= ~(KVM_PAGES_PER_HPAGE-1);
++ vcpu->arch.update_pte.largepage = 1;
++ }
++ pfn = gfn_to_pfn(vcpu->kvm, gfn);
+ up_read(¤t->mm->mmap_sem);
+
++ if (is_error_pfn(pfn)) {
++ kvm_release_pfn_clean(pfn);
++ return;
++ }
+ vcpu->arch.update_pte.gfn = gfn;
+- vcpu->arch.update_pte.page = page;
++ vcpu->arch.update_pte.pfn = pfn;
}
--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)
+ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
+@@ -1423,7 +1697,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
+ struct hlist_node *node, *n;
+ struct hlist_head *bucket;
+ unsigned index;
+- u64 entry;
++ u64 entry, gentry;
+ u64 *spte;
+ unsigned offset = offset_in_page(gpa);
+ unsigned pte_size;
+@@ -1433,8 +1707,9 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
+ int level;
+ int flooded = 0;
+ int npte;
++ int r;
+
+- pgprintk("%s: gpa %llx bytes %d\n", __FUNCTION__, gpa, bytes);
++ pgprintk("%s: gpa %llx bytes %d\n", __func__, gpa, bytes);
+ mmu_guess_page_from_pte_write(vcpu, gpa, new, bytes);
+ spin_lock(&vcpu->kvm->mmu_lock);
+ kvm_mmu_free_some_pages(vcpu);
+@@ -1450,7 +1725,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
+ vcpu->arch.last_pt_write_count = 1;
+ vcpu->arch.last_pte_updated = NULL;
+ }
+- index = kvm_page_table_hashfn(gfn) % KVM_NUM_MMU_PAGES;
++ index = kvm_page_table_hashfn(gfn);
+ bucket = &vcpu->kvm->arch.mmu_page_hash[index];
+ hlist_for_each_entry_safe(sp, node, n, bucket, hash_link) {
+ if (sp->gfn != gfn || sp->role.metaphysical)
+@@ -1496,20 +1771,29 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
+ continue;
+ }
+ spte = &sp->spt[page_offset / sizeof(*spte)];
++ if ((gpa & (pte_size - 1)) || (bytes < pte_size)) {
++ gentry = 0;
++ r = kvm_read_guest_atomic(vcpu->kvm,
++ gpa & ~(u64)(pte_size - 1),
++ &gentry, pte_size);
++ new = (const void *)&gentry;
++ if (r < 0)
++ new = NULL;
++ }
+ while (npte--) {
+ entry = *spte;
+ mmu_pte_write_zap_pte(vcpu, sp, spte);
+- mmu_pte_write_new_pte(vcpu, sp, spte, new, bytes,
+- page_offset & (pte_size - 1));
++ if (new)
++ mmu_pte_write_new_pte(vcpu, sp, spte, new);
+ mmu_pte_write_flush_tlb(vcpu, entry, *spte);
+ ++spte;
+ }
+ }
+ kvm_mmu_audit(vcpu, "post pte write");
+ spin_unlock(&vcpu->kvm->mmu_lock);
+- if (vcpu->arch.update_pte.page) {
+- kvm_release_page_clean(vcpu->arch.update_pte.page);
+- vcpu->arch.update_pte.page = NULL;
++ if (!is_error_pfn(vcpu->arch.update_pte.pfn)) {
++ kvm_release_pfn_clean(vcpu->arch.update_pte.pfn);
++ vcpu->arch.update_pte.pfn = bad_pfn;
+ }
+ }
+
+@@ -1518,9 +1802,7 @@ int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva)
+ gpa_t gpa;
+ int r;
+
+- down_read(&vcpu->kvm->slots_lock);
+ gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, gva);
+- up_read(&vcpu->kvm->slots_lock);
+
+ spin_lock(&vcpu->kvm->mmu_lock);
+ r = kvm_mmu_unprotect_page(vcpu->kvm, gpa >> PAGE_SHIFT);
+@@ -1577,6 +1859,12 @@ out:
+ }
+ EXPORT_SYMBOL_GPL(kvm_mmu_page_fault);
+
++void kvm_enable_tdp(void)
++{
++ tdp_enabled = true;
++}
++EXPORT_SYMBOL_GPL(kvm_enable_tdp);
++
+ static void free_mmu_pages(struct kvm_vcpu *vcpu)
{
- unsigned long i;
+ struct kvm_mmu_page *sp;
+@@ -1677,7 +1965,53 @@ void kvm_mmu_zap_all(struct kvm *kvm)
+ kvm_flush_remote_tlbs(kvm);
+ }
-@@ -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);
+-void kvm_mmu_module_exit(void)
++void kvm_mmu_remove_one_alloc_mmu_page(struct kvm *kvm)
++{
++ struct kvm_mmu_page *page;
+
- i = 2000;
-- while (--i) udelay(1000);
-+ while (--i)
-+ udelay(1000);
++ page = container_of(kvm->arch.active_mmu_pages.prev,
++ struct kvm_mmu_page, link);
++ kvm_mmu_zap_page(kvm, page);
++}
+
- reason &= ~8;
- outb(reason, 0x61);
++static int mmu_shrink(int nr_to_scan, gfp_t gfp_mask)
++{
++ struct kvm *kvm;
++ struct kvm *kvm_freed = NULL;
++ int cache_count = 0;
++
++ spin_lock(&kvm_lock);
++
++ list_for_each_entry(kvm, &vm_list, vm_list) {
++ int npages;
++
++ spin_lock(&kvm->mmu_lock);
++ npages = kvm->arch.n_alloc_mmu_pages -
++ kvm->arch.n_free_mmu_pages;
++ cache_count += npages;
++ if (!kvm_freed && nr_to_scan > 0 && npages > 0) {
++ kvm_mmu_remove_one_alloc_mmu_page(kvm);
++ cache_count--;
++ kvm_freed = kvm;
++ }
++ nr_to_scan--;
++
++ spin_unlock(&kvm->mmu_lock);
++ }
++ if (kvm_freed)
++ list_move_tail(&kvm_freed->vm_list, &vm_list);
++
++ spin_unlock(&kvm_lock);
++
++ return cache_count;
++}
++
++static struct shrinker mmu_shrinker = {
++ .shrink = mmu_shrink,
++ .seeks = DEFAULT_SEEKS * 10,
++};
++
++void mmu_destroy_caches(void)
+ {
+ if (pte_chain_cache)
+ kmem_cache_destroy(pte_chain_cache);
+@@ -1687,6 +2021,12 @@ void kvm_mmu_module_exit(void)
+ kmem_cache_destroy(mmu_page_header_cache);
}
--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)
++void kvm_mmu_module_exit(void)
++{
++ mmu_destroy_caches();
++ unregister_shrinker(&mmu_shrinker);
++}
++
+ int kvm_mmu_module_init(void)
{
-+ 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());
+ pte_chain_cache = kmem_cache_create("kvm_pte_chain",
+@@ -1706,10 +2046,12 @@ int kvm_mmu_module_init(void)
+ if (!mmu_page_header_cache)
+ goto nomem;
+
++ register_shrinker(&mmu_shrinker);
+
- 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");
+ return 0;
- printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+ nomem:
+- kvm_mmu_module_exit();
++ mmu_destroy_caches();
+ return -ENOMEM;
}
- static DEFINE_SPINLOCK(nmi_print_lock);
+@@ -1732,6 +2074,127 @@ unsigned int kvm_mmu_calculate_mmu_pages(struct kvm *kvm)
+ return nr_mmu_pages;
+ }
--void __kprobes die_nmi(struct pt_regs *regs, const char *msg)
-+void notrace __kprobes die_nmi(struct pt_regs *regs, const char *msg)
++static void *pv_mmu_peek_buffer(struct kvm_pv_mmu_op_buffer *buffer,
++ unsigned len)
++{
++ if (len > buffer->len)
++ return NULL;
++ return buffer->ptr;
++}
++
++static void *pv_mmu_read_buffer(struct kvm_pv_mmu_op_buffer *buffer,
++ unsigned len)
++{
++ void *ret;
++
++ ret = pv_mmu_peek_buffer(buffer, len);
++ if (!ret)
++ return ret;
++ buffer->ptr += len;
++ buffer->len -= len;
++ buffer->processed += len;
++ return ret;
++}
++
++static int kvm_pv_mmu_write(struct kvm_vcpu *vcpu,
++ gpa_t addr, gpa_t value)
++{
++ int bytes = 8;
++ int r;
++
++ if (!is_long_mode(vcpu) && !is_pae(vcpu))
++ bytes = 4;
++
++ r = mmu_topup_memory_caches(vcpu);
++ if (r)
++ return r;
++
++ if (!emulator_write_phys(vcpu, addr, &value, bytes))
++ return -EFAULT;
++
++ return 1;
++}
++
++static int kvm_pv_mmu_flush_tlb(struct kvm_vcpu *vcpu)
++{
++ kvm_x86_ops->tlb_flush(vcpu);
++ return 1;
++}
++
++static int kvm_pv_mmu_release_pt(struct kvm_vcpu *vcpu, gpa_t addr)
++{
++ spin_lock(&vcpu->kvm->mmu_lock);
++ mmu_unshadow(vcpu->kvm, addr >> PAGE_SHIFT);
++ spin_unlock(&vcpu->kvm->mmu_lock);
++ return 1;
++}
++
++static int kvm_pv_mmu_op_one(struct kvm_vcpu *vcpu,
++ struct kvm_pv_mmu_op_buffer *buffer)
++{
++ struct kvm_mmu_op_header *header;
++
++ header = pv_mmu_peek_buffer(buffer, sizeof *header);
++ if (!header)
++ return 0;
++ switch (header->op) {
++ case KVM_MMU_OP_WRITE_PTE: {
++ struct kvm_mmu_op_write_pte *wpte;
++
++ wpte = pv_mmu_read_buffer(buffer, sizeof *wpte);
++ if (!wpte)
++ return 0;
++ return kvm_pv_mmu_write(vcpu, wpte->pte_phys,
++ wpte->pte_val);
++ }
++ case KVM_MMU_OP_FLUSH_TLB: {
++ struct kvm_mmu_op_flush_tlb *ftlb;
++
++ ftlb = pv_mmu_read_buffer(buffer, sizeof *ftlb);
++ if (!ftlb)
++ return 0;
++ return kvm_pv_mmu_flush_tlb(vcpu);
++ }
++ case KVM_MMU_OP_RELEASE_PT: {
++ struct kvm_mmu_op_release_pt *rpt;
++
++ rpt = pv_mmu_read_buffer(buffer, sizeof *rpt);
++ if (!rpt)
++ return 0;
++ return kvm_pv_mmu_release_pt(vcpu, rpt->pt_phys);
++ }
++ default: return 0;
++ }
++}
++
++int kvm_pv_mmu_op(struct kvm_vcpu *vcpu, unsigned long bytes,
++ gpa_t addr, unsigned long *ret)
++{
++ int r;
++ struct kvm_pv_mmu_op_buffer buffer;
++
++ buffer.ptr = buffer.buf;
++ buffer.len = min_t(unsigned long, bytes, sizeof buffer.buf);
++ buffer.processed = 0;
++
++ r = kvm_read_guest(vcpu->kvm, addr, buffer.buf, buffer.len);
++ if (r)
++ goto out;
++
++ while (buffer.len) {
++ r = kvm_pv_mmu_op_one(vcpu, &buffer);
++ if (r < 0)
++ goto out;
++ if (r == 0)
++ break;
++ }
++
++ r = 1;
++out:
++ *ret = buffer.processed;
++ return r;
++}
++
+ #ifdef AUDIT
+
+ static const char *audit_msg;
+@@ -1768,8 +2231,7 @@ static void audit_mappings_page(struct kvm_vcpu *vcpu, u64 page_pte,
+ audit_mappings_page(vcpu, ent, va, level - 1);
+ } else {
+ gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, va);
+- struct page *page = gpa_to_page(vcpu, gpa);
+- hpa_t hpa = page_to_phys(page);
++ hpa_t hpa = (hpa_t)gpa_to_pfn(vcpu, gpa) << PAGE_SHIFT;
+
+ if (is_shadow_present_pte(ent)
+ && (ent & PT64_BASE_ADDR_MASK) != hpa)
+@@ -1782,7 +2244,7 @@ static void audit_mappings_page(struct kvm_vcpu *vcpu, u64 page_pte,
+ && !is_error_hpa(hpa))
+ printk(KERN_ERR "audit: (%s) notrap shadow,"
+ " valid guest gva %lx\n", audit_msg, va);
+- kvm_release_page_clean(page);
++ kvm_release_pfn_clean(pfn);
+
+ }
+ }
+@@ -1867,7 +2329,7 @@ static void audit_rmap(struct kvm_vcpu *vcpu)
+
+ if (n_rmap != n_actual)
+ printk(KERN_ERR "%s: (%s) rmap %d actual %d\n",
+- __FUNCTION__, audit_msg, n_rmap, n_actual);
++ __func__, audit_msg, n_rmap, n_actual);
+ }
+
+ static void audit_write_protection(struct kvm_vcpu *vcpu)
+@@ -1887,7 +2349,7 @@ static void audit_write_protection(struct kvm_vcpu *vcpu)
+ if (*rmapp)
+ printk(KERN_ERR "%s: (%s) shadow page has writable"
+ " mappings: gfn %lx role %x\n",
+- __FUNCTION__, audit_msg, sp->gfn,
++ __func__, audit_msg, sp->gfn,
+ sp->role.word);
+ }
+ }
+diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
+index 1fce19e..e64e9f5 100644
+--- a/arch/x86/kvm/mmu.h
++++ b/arch/x86/kvm/mmu.h
+@@ -3,6 +3,12 @@
+
+ #include <linux/kvm_host.h>
+
++#ifdef CONFIG_X86_64
++#define TDP_ROOT_LEVEL PT64_ROOT_LEVEL
++#else
++#define TDP_ROOT_LEVEL PT32E_ROOT_LEVEL
++#endif
++
+ static inline void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
{
-- 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;
+ if (unlikely(vcpu->kvm->arch.n_free_mmu_pages < KVM_MIN_FREE_MMU_PAGES))
+diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
+index ecc0856..156fe10 100644
+--- a/arch/x86/kvm/paging_tmpl.h
++++ b/arch/x86/kvm/paging_tmpl.h
+@@ -130,7 +130,7 @@ static int FNAME(walk_addr)(struct guest_walker *walker,
+ unsigned index, pt_access, pte_access;
+ gpa_t pte_gpa;
+
+- pgprintk("%s: addr %lx\n", __FUNCTION__, addr);
++ pgprintk("%s: addr %lx\n", __func__, addr);
+ walk:
+ walker->level = vcpu->arch.mmu.root_level;
+ pte = vcpu->arch.cr3;
+@@ -155,7 +155,7 @@ walk:
+ pte_gpa += index * sizeof(pt_element_t);
+ walker->table_gfn[walker->level - 1] = table_gfn;
+ walker->pte_gpa[walker->level - 1] = pte_gpa;
+- pgprintk("%s: table_gfn[%d] %lx\n", __FUNCTION__,
++ pgprintk("%s: table_gfn[%d] %lx\n", __func__,
+ walker->level - 1, table_gfn);
+
+ kvm_read_guest(vcpu->kvm, pte_gpa, &pte, sizeof(pte));
+@@ -222,7 +222,7 @@ walk:
+ walker->pt_access = pt_access;
+ walker->pte_access = pte_access;
+ pgprintk("%s: pte %llx pte_access %x pt_access %x\n",
+- __FUNCTION__, (u64)pte, pt_access, pte_access);
++ __func__, (u64)pte, pt_access, pte_access);
+ return 1;
- 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);
+ not_present:
+@@ -243,31 +243,30 @@ err:
+ }
-- /* 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 void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
+- u64 *spte, const void *pte, int bytes,
+- int offset_in_pte)
++ u64 *spte, const void *pte)
+ {
+ pt_element_t gpte;
+ unsigned pte_access;
+- struct page *npage;
++ pfn_t pfn;
++ int largepage = vcpu->arch.update_pte.largepage;
+
+ gpte = *(const pt_element_t *)pte;
+ if (~gpte & (PT_PRESENT_MASK | PT_ACCESSED_MASK)) {
+- if (!offset_in_pte && !is_present_pte(gpte))
++ if (!is_present_pte(gpte))
+ set_shadow_pte(spte, shadow_notrap_nonpresent_pte);
+ return;
+ }
+- if (bytes < sizeof(pt_element_t))
+- return;
+- pgprintk("%s: gpte %llx spte %p\n", __FUNCTION__, (u64)gpte, spte);
++ pgprintk("%s: gpte %llx spte %p\n", __func__, (u64)gpte, spte);
+ pte_access = page->role.access & FNAME(gpte_access)(vcpu, gpte);
+ if (gpte_to_gfn(gpte) != vcpu->arch.update_pte.gfn)
+ return;
+- npage = vcpu->arch.update_pte.page;
+- if (!npage)
++ pfn = vcpu->arch.update_pte.pfn;
++ if (is_error_pfn(pfn))
+ return;
+- get_page(npage);
++ kvm_get_pfn(pfn);
+ mmu_set_spte(vcpu, spte, page->role.access, pte_access, 0, 0,
+- gpte & PT_DIRTY_MASK, NULL, gpte_to_gfn(gpte), npage);
++ gpte & PT_DIRTY_MASK, NULL, largepage, gpte_to_gfn(gpte),
++ pfn, true);
}
--static __kprobes void default_do_nmi(struct pt_regs * regs)
-+static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
+ /*
+@@ -275,8 +274,8 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
+ */
+ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
+ struct guest_walker *walker,
+- int user_fault, int write_fault, int *ptwrite,
+- struct page *page)
++ int user_fault, int write_fault, int largepage,
++ int *ptwrite, pfn_t pfn)
{
- unsigned char reason = 0;
+ hpa_t shadow_addr;
+ int level;
+@@ -304,11 +303,19 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
+ shadow_ent = ((u64 *)__va(shadow_addr)) + index;
+ if (level == PT_PAGE_TABLE_LEVEL)
+ break;
+- if (is_shadow_present_pte(*shadow_ent)) {
++
++ if (largepage && level == PT_DIRECTORY_LEVEL)
++ break;
++
++ if (is_shadow_present_pte(*shadow_ent)
++ && !is_large_pte(*shadow_ent)) {
+ shadow_addr = *shadow_ent & PT64_BASE_ADDR_MASK;
+ continue;
+ }
-- /* 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 (is_large_pte(*shadow_ent))
++ rmap_remove(vcpu->kvm, shadow_ent);
+
- 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()))
+ if (level - 1 == PT_PAGE_TABLE_LEVEL
+ && walker->level == PT_DIRECTORY_LEVEL) {
+ metaphysical = 1;
+@@ -329,7 +336,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
+ walker->pte_gpa[level - 2],
+ &curr_pte, sizeof(curr_pte));
+ if (r || curr_pte != walker->ptes[level - 2]) {
+- kvm_release_page_clean(page);
++ kvm_release_pfn_clean(pfn);
+ return NULL;
+ }
+ }
+@@ -342,7 +349,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
+ mmu_set_spte(vcpu, shadow_ent, access, walker->pte_access & access,
+ user_fault, write_fault,
+ walker->ptes[walker->level-1] & PT_DIRTY_MASK,
+- ptwrite, walker->gfn, page);
++ ptwrite, largepage, walker->gfn, pfn, false);
+
+ return shadow_ent;
+ }
+@@ -371,16 +378,16 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
+ u64 *shadow_pte;
+ int write_pt = 0;
+ int r;
+- struct page *page;
++ pfn_t pfn;
++ int largepage = 0;
+
+- pgprintk("%s: addr %lx err %x\n", __FUNCTION__, addr, error_code);
++ pgprintk("%s: addr %lx err %x\n", __func__, addr, error_code);
+ kvm_mmu_audit(vcpu, "pre page fault");
+
+ r = mmu_topup_memory_caches(vcpu);
+ if (r)
+ return r;
+
+- down_read(&vcpu->kvm->slots_lock);
+ /*
+ * Look up the shadow pte for the faulting address.
+ */
+@@ -391,40 +398,45 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
+ * The page is not mapped by the guest. Let the guest handle it.
+ */
+ if (!r) {
+- pgprintk("%s: guest page fault\n", __FUNCTION__);
++ pgprintk("%s: guest page fault\n", __func__);
+ inject_page_fault(vcpu, addr, walker.error_code);
+ vcpu->arch.last_pt_write_count = 0; /* reset fork detector */
+- up_read(&vcpu->kvm->slots_lock);
+ return 0;
+ }
+
+ down_read(¤t->mm->mmap_sem);
+- page = gfn_to_page(vcpu->kvm, walker.gfn);
++ if (walker.level == PT_DIRECTORY_LEVEL) {
++ gfn_t large_gfn;
++ large_gfn = walker.gfn & ~(KVM_PAGES_PER_HPAGE-1);
++ if (is_largepage_backed(vcpu, large_gfn)) {
++ walker.gfn = large_gfn;
++ largepage = 1;
++ }
++ }
++ pfn = gfn_to_pfn(vcpu->kvm, walker.gfn);
+ up_read(¤t->mm->mmap_sem);
+
++ /* mmio */
++ if (is_error_pfn(pfn)) {
++ pgprintk("gfn %x is mmio\n", walker.gfn);
++ kvm_release_pfn_clean(pfn);
++ return 1;
++ }
++
+ spin_lock(&vcpu->kvm->mmu_lock);
+ kvm_mmu_free_some_pages(vcpu);
+ shadow_pte = FNAME(fetch)(vcpu, addr, &walker, user_fault, write_fault,
+- &write_pt, page);
+- pgprintk("%s: shadow pte %p %llx ptwrite %d\n", __FUNCTION__,
++ largepage, &write_pt, pfn);
++
++ pgprintk("%s: shadow pte %p %llx ptwrite %d\n", __func__,
+ shadow_pte, *shadow_pte, write_pt);
+
+ if (!write_pt)
+ vcpu->arch.last_pt_write_count = 0; /* reset fork detector */
+
+- /*
+- * mmio: emulate if accessible, otherwise its a guest fault.
+- */
+- if (shadow_pte && is_io_pte(*shadow_pte)) {
+- spin_unlock(&vcpu->kvm->mmu_lock);
+- up_read(&vcpu->kvm->slots_lock);
+- return 1;
+- }
+-
+ ++vcpu->stat.pf_fixed;
+ kvm_mmu_audit(vcpu, "post page fault (fixed)");
+ spin_unlock(&vcpu->kvm->mmu_lock);
+- up_read(&vcpu->kvm->slots_lock);
+
+ return write_pt;
+ }
+diff --git a/arch/x86/kvm/segment_descriptor.h b/arch/x86/kvm/segment_descriptor.h
+deleted file mode 100644
+index 56fc4c8..0000000
+--- a/arch/x86/kvm/segment_descriptor.h
++++ /dev/null
+@@ -1,29 +0,0 @@
+-#ifndef __SEGMENT_DESCRIPTOR_H
+-#define __SEGMENT_DESCRIPTOR_H
+-
+-struct segment_descriptor {
+- u16 limit_low;
+- u16 base_low;
+- u8 base_mid;
+- u8 type : 4;
+- u8 system : 1;
+- u8 dpl : 2;
+- u8 present : 1;
+- u8 limit_high : 4;
+- u8 avl : 1;
+- u8 long_mode : 1;
+- u8 default_op : 1;
+- u8 granularity : 1;
+- u8 base_high;
+-} __attribute__((packed));
+-
+-#ifdef CONFIG_X86_64
+-/* LDT or TSS descriptor in the GDT. 16 bytes. */
+-struct segment_descriptor_64 {
+- struct segment_descriptor s;
+- u32 base_higher;
+- u32 pad_zero;
+-};
+-
-#endif
- unknown_nmi_error(reason, regs);
+-#endif
+diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
+index 1a582f1..89e0be2 100644
+--- a/arch/x86/kvm/svm.c
++++ b/arch/x86/kvm/svm.c
+@@ -47,6 +47,18 @@ MODULE_LICENSE("GPL");
+ #define SVM_FEATURE_LBRV (1 << 1)
+ #define SVM_DEATURE_SVML (1 << 2)
+
++#define DEBUGCTL_RESERVED_BITS (~(0x3fULL))
++
++/* enable NPT for AMD64 and X86 with PAE */
++#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
++static bool npt_enabled = true;
+#else
-+ unknown_nmi_error(reason, regs);
++static bool npt_enabled = false;
+#endif
++static int npt = 1;
++
++module_param(npt, int, S_IRUGO);
++
+ static void kvm_reput_irq(struct vcpu_svm *svm);
- 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 inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu)
+@@ -54,8 +66,7 @@ static inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu)
+ return container_of(vcpu, struct vcpu_svm, vcpu);
}
- static int ignore_nmis;
+-unsigned long iopm_base;
+-unsigned long msrpm_base;
++static unsigned long iopm_base;
--__kprobes void do_nmi(struct pt_regs * regs, long error_code)
-+notrace __kprobes void do_nmi(struct pt_regs *regs, long error_code)
+ struct kvm_ldttss_desc {
+ u16 limit0;
+@@ -182,7 +193,7 @@ static inline void flush_guest_tlb(struct kvm_vcpu *vcpu)
+
+ static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer)
{
- int cpu;
+- if (!(efer & EFER_LMA))
++ if (!npt_enabled && !(efer & EFER_LMA))
+ efer &= ~EFER_LME;
-@@ -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)
+ to_svm(vcpu)->vmcb->save.efer = efer | MSR_EFER_SVME_MASK;
+@@ -219,12 +230,12 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
+ struct vcpu_svm *svm = to_svm(vcpu);
+
+ if (!svm->next_rip) {
+- printk(KERN_DEBUG "%s: NOP\n", __FUNCTION__);
++ printk(KERN_DEBUG "%s: NOP\n", __func__);
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);
+ }
+ if (svm->next_rip - svm->vmcb->save.rip > MAX_INST_SIZE)
+ printk(KERN_ERR "%s: ip 0x%llx next 0x%llx\n",
+- __FUNCTION__,
++ __func__,
+ svm->vmcb->save.rip,
+ svm->next_rip);
+
+@@ -279,11 +290,7 @@ static void svm_hardware_enable(void *garbage)
+
+ struct svm_cpu_data *svm_data;
+ uint64_t efer;
+-#ifdef CONFIG_X86_64
+- struct desc_ptr gdt_descr;
+-#else
+ struct desc_ptr gdt_descr;
+-#endif
+ struct desc_struct *gdt;
+ int me = raw_smp_processor_id();
+
+@@ -302,7 +309,6 @@ static void svm_hardware_enable(void *garbage)
+ svm_data->asid_generation = 1;
+ svm_data->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1;
+ svm_data->next_asid = svm_data->max_asid + 1;
+- svm_features = cpuid_edx(SVM_CPUID_FUNC);
+
+ asm volatile ("sgdt %0" : "=m"(gdt_descr));
+ gdt = (struct desc_struct *)gdt_descr.address;
+@@ -361,12 +367,51 @@ static void set_msr_interception(u32 *msrpm, unsigned msr,
+ BUG();
}
- #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)
+
++static void svm_vcpu_init_msrpm(u32 *msrpm)
++{
++ memset(msrpm, 0xff, PAGE_SIZE * (1 << MSRPM_ALLOC_ORDER));
++
++#ifdef CONFIG_X86_64
++ set_msr_interception(msrpm, MSR_GS_BASE, 1, 1);
++ set_msr_interception(msrpm, MSR_FS_BASE, 1, 1);
++ set_msr_interception(msrpm, MSR_KERNEL_GS_BASE, 1, 1);
++ set_msr_interception(msrpm, MSR_LSTAR, 1, 1);
++ set_msr_interception(msrpm, MSR_CSTAR, 1, 1);
++ set_msr_interception(msrpm, MSR_SYSCALL_MASK, 1, 1);
++#endif
++ set_msr_interception(msrpm, MSR_K6_STAR, 1, 1);
++ set_msr_interception(msrpm, MSR_IA32_SYSENTER_CS, 1, 1);
++ set_msr_interception(msrpm, MSR_IA32_SYSENTER_ESP, 1, 1);
++ set_msr_interception(msrpm, MSR_IA32_SYSENTER_EIP, 1, 1);
++}
++
++static void svm_enable_lbrv(struct vcpu_svm *svm)
++{
++ u32 *msrpm = svm->msrpm;
++
++ svm->vmcb->control.lbr_ctl = 1;
++ set_msr_interception(msrpm, MSR_IA32_LASTBRANCHFROMIP, 1, 1);
++ set_msr_interception(msrpm, MSR_IA32_LASTBRANCHTOIP, 1, 1);
++ set_msr_interception(msrpm, MSR_IA32_LASTINTFROMIP, 1, 1);
++ set_msr_interception(msrpm, MSR_IA32_LASTINTTOIP, 1, 1);
++}
++
++static void svm_disable_lbrv(struct vcpu_svm *svm)
++{
++ u32 *msrpm = svm->msrpm;
++
++ svm->vmcb->control.lbr_ctl = 0;
++ set_msr_interception(msrpm, MSR_IA32_LASTBRANCHFROMIP, 0, 0);
++ set_msr_interception(msrpm, MSR_IA32_LASTBRANCHTOIP, 0, 0);
++ set_msr_interception(msrpm, MSR_IA32_LASTINTFROMIP, 0, 0);
++ set_msr_interception(msrpm, MSR_IA32_LASTINTTOIP, 0, 0);
++}
++
+ static __init int svm_hardware_setup(void)
{
-- unsigned int condition;
- struct task_struct *tsk = current;
-+ unsigned int condition;
+ int cpu;
+ struct page *iopm_pages;
+- struct page *msrpm_pages;
+- void *iopm_va, *msrpm_va;
++ void *iopm_va;
+ int r;
- trace_hardirqs_fixup();
+ iopm_pages = alloc_pages(GFP_KERNEL, IOPM_ALLOC_ORDER);
+@@ -379,41 +424,33 @@ static __init int svm_hardware_setup(void)
+ clear_bit(0x80, iopm_va); /* allow direct access to PC debug port */
+ iopm_base = page_to_pfn(iopm_pages) << PAGE_SHIFT;
-@@ -891,7 +924,7 @@ void __kprobes do_debug(struct pt_regs * regs, long error_code)
- goto clear_dr7;
- }
++ if (boot_cpu_has(X86_FEATURE_NX))
++ kvm_enable_efer_bits(EFER_NX);
-- if (regs->flags & VM_MASK)
-+ if (regs->flags & X86_VM_MASK)
- goto debug_vm86;
+- msrpm_pages = alloc_pages(GFP_KERNEL, MSRPM_ALLOC_ORDER);
++ for_each_online_cpu(cpu) {
++ r = svm_cpu_init(cpu);
++ if (r)
++ goto err;
++ }
- /* 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);
+- r = -ENOMEM;
+- if (!msrpm_pages)
+- goto err_1;
++ svm_features = cpuid_edx(SVM_CPUID_FUNC);
+
+- msrpm_va = page_address(msrpm_pages);
+- memset(msrpm_va, 0xff, PAGE_SIZE * (1 << MSRPM_ALLOC_ORDER));
+- msrpm_base = page_to_pfn(msrpm_pages) << PAGE_SHIFT;
++ if (!svm_has(SVM_FEATURE_NPT))
++ npt_enabled = false;
-- /* 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:
+-#ifdef CONFIG_X86_64
+- set_msr_interception(msrpm_va, MSR_GS_BASE, 1, 1);
+- set_msr_interception(msrpm_va, MSR_FS_BASE, 1, 1);
+- set_msr_interception(msrpm_va, MSR_KERNEL_GS_BASE, 1, 1);
+- set_msr_interception(msrpm_va, MSR_LSTAR, 1, 1);
+- set_msr_interception(msrpm_va, MSR_CSTAR, 1, 1);
+- set_msr_interception(msrpm_va, MSR_SYSCALL_MASK, 1, 1);
+-#endif
+- set_msr_interception(msrpm_va, MSR_K6_STAR, 1, 1);
+- set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_CS, 1, 1);
+- set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_ESP, 1, 1);
+- set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_EIP, 1, 1);
++ if (npt_enabled && !npt) {
++ printk(KERN_INFO "kvm: Nested Paging disabled\n");
++ npt_enabled = false;
++ }
+
+- for_each_online_cpu(cpu) {
+- r = svm_cpu_init(cpu);
+- if (r)
+- goto err_2;
++ if (npt_enabled) {
++ printk(KERN_INFO "kvm: Nested Paging enabled\n");
++ kvm_enable_tdp();
+ }
++
+ return 0;
- clear_TF_reenable:
- set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
-- regs->flags &= ~TF_MASK;
-+ regs->flags &= ~X86_EFLAGS_TF;
- return;
- }
+-err_2:
+- __free_pages(msrpm_pages, MSRPM_ALLOC_ORDER);
+- msrpm_base = 0;
+-err_1:
++err:
+ __free_pages(iopm_pages, IOPM_ALLOC_ORDER);
+ iopm_base = 0;
+ return r;
+@@ -421,9 +458,8 @@ err_1:
-@@ -938,9 +972,10 @@ clear_TF_reenable:
- */
- void math_error(void __user *ip)
+ static __exit void svm_hardware_unsetup(void)
{
-- struct task_struct * task;
-+ struct task_struct *task;
-+ unsigned short cwd;
-+ unsigned short swd;
- siginfo_t info;
-- unsigned short cwd, swd;
+- __free_pages(pfn_to_page(msrpm_base >> PAGE_SHIFT), MSRPM_ALLOC_ORDER);
+ __free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT), IOPM_ALLOC_ORDER);
+- iopm_base = msrpm_base = 0;
++ iopm_base = 0;
+ }
- /*
- * 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);
+ static void init_seg(struct vmcb_seg *seg)
+@@ -443,15 +479,14 @@ static void init_sys_seg(struct vmcb_seg *seg, uint32_t type)
+ seg->base = 0;
}
--void do_coprocessor_error(struct pt_regs * regs, long error_code)
-+void do_coprocessor_error(struct pt_regs *regs, long error_code)
+-static void init_vmcb(struct vmcb *vmcb)
++static void init_vmcb(struct vcpu_svm *svm)
{
- 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)
+- struct vmcb_control_area *control = &vmcb->control;
+- struct vmcb_save_area *save = &vmcb->save;
++ struct vmcb_control_area *control = &svm->vmcb->control;
++ struct vmcb_save_area *save = &svm->vmcb->save;
- static void simd_math_error(void __user *ip)
+ control->intercept_cr_read = INTERCEPT_CR0_MASK |
+ INTERCEPT_CR3_MASK |
+- INTERCEPT_CR4_MASK |
+- INTERCEPT_CR8_MASK;
++ INTERCEPT_CR4_MASK;
+
+ control->intercept_cr_write = INTERCEPT_CR0_MASK |
+ INTERCEPT_CR3_MASK |
+@@ -471,23 +506,13 @@ static void init_vmcb(struct vmcb *vmcb)
+ INTERCEPT_DR7_MASK;
+
+ control->intercept_exceptions = (1 << PF_VECTOR) |
+- (1 << UD_VECTOR);
++ (1 << UD_VECTOR) |
++ (1 << MC_VECTOR);
+
+
+ control->intercept = (1ULL << INTERCEPT_INTR) |
+ (1ULL << INTERCEPT_NMI) |
+ (1ULL << INTERCEPT_SMI) |
+- /*
+- * selective cr0 intercept bug?
+- * 0: 0f 22 d8 mov %eax,%cr3
+- * 3: 0f 20 c0 mov %cr0,%eax
+- * 6: 0d 00 00 00 80 or $0x80000000,%eax
+- * b: 0f 22 c0 mov %eax,%cr0
+- * set cr3 ->interception
+- * get cr0 ->interception
+- * set cr0 -> no interception
+- */
+- /* (1ULL << INTERCEPT_SELECTIVE_CR0) | */
+ (1ULL << INTERCEPT_CPUID) |
+ (1ULL << INTERCEPT_INVD) |
+ (1ULL << INTERCEPT_HLT) |
+@@ -508,7 +533,7 @@ static void init_vmcb(struct vmcb *vmcb)
+ (1ULL << INTERCEPT_MWAIT);
+
+ control->iopm_base_pa = iopm_base;
+- control->msrpm_base_pa = msrpm_base;
++ control->msrpm_base_pa = __pa(svm->msrpm);
+ control->tsc_offset = 0;
+ control->int_ctl = V_INTR_MASKING_MASK;
+
+@@ -550,13 +575,30 @@ static void init_vmcb(struct vmcb *vmcb)
+ save->cr0 = 0x00000010 | X86_CR0_PG | X86_CR0_WP;
+ save->cr4 = X86_CR4_PAE;
+ /* rdx = ?? */
++
++ if (npt_enabled) {
++ /* Setup VMCB for Nested Paging */
++ control->nested_ctl = 1;
++ control->intercept &= ~(1ULL << INTERCEPT_TASK_SWITCH);
++ control->intercept_exceptions &= ~(1 << PF_VECTOR);
++ control->intercept_cr_read &= ~(INTERCEPT_CR0_MASK|
++ INTERCEPT_CR3_MASK);
++ control->intercept_cr_write &= ~(INTERCEPT_CR0_MASK|
++ INTERCEPT_CR3_MASK);
++ save->g_pat = 0x0007040600070406ULL;
++ /* enable caching because the QEMU Bios doesn't enable it */
++ save->cr0 = X86_CR0_ET;
++ save->cr3 = 0;
++ save->cr4 = 0;
++ }
++ force_new_asid(&svm->vcpu);
+ }
+
+ static int svm_vcpu_reset(struct kvm_vcpu *vcpu)
+ {
+ struct vcpu_svm *svm = to_svm(vcpu);
+
+- init_vmcb(svm->vmcb);
++ init_vmcb(svm);
+
+ if (vcpu->vcpu_id != 0) {
+ svm->vmcb->save.rip = 0;
+@@ -571,6 +613,7 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
{
-- struct task_struct * task;
-- siginfo_t info;
-+ struct task_struct *task;
- unsigned short mxcsr;
-+ siginfo_t info;
+ struct vcpu_svm *svm;
+ struct page *page;
++ struct page *msrpm_pages;
+ int err;
- /*
- * 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;
+ svm = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
+@@ -589,12 +632,19 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
+ goto uninit;
}
- force_sig_info(SIGFPE, &info, task);
+
++ err = -ENOMEM;
++ msrpm_pages = alloc_pages(GFP_KERNEL, MSRPM_ALLOC_ORDER);
++ if (!msrpm_pages)
++ goto uninit;
++ svm->msrpm = page_address(msrpm_pages);
++ svm_vcpu_init_msrpm(svm->msrpm);
++
+ svm->vmcb = page_address(page);
+ clear_page(svm->vmcb);
+ svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT;
+ svm->asid_generation = 0;
+ memset(svm->db_regs, 0, sizeof(svm->db_regs));
+- init_vmcb(svm->vmcb);
++ init_vmcb(svm);
+
+ fx_init(&svm->vcpu);
+ svm->vcpu.fpu_active = 1;
+@@ -617,6 +667,7 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu)
+ struct vcpu_svm *svm = to_svm(vcpu);
+
+ __free_page(pfn_to_page(svm->vmcb_pa >> PAGE_SHIFT));
++ __free_pages(virt_to_page(svm->msrpm), MSRPM_ALLOC_ORDER);
+ kvm_vcpu_uninit(vcpu);
+ kmem_cache_free(kvm_vcpu_cache, svm);
+ }
+@@ -731,6 +782,13 @@ static void svm_get_segment(struct kvm_vcpu *vcpu,
+ var->unusable = !var->present;
}
--void do_simd_coprocessor_error(struct pt_regs * regs,
-- long error_code)
-+void do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
++static int svm_get_cpl(struct kvm_vcpu *vcpu)
++{
++ struct vmcb_save_area *save = &to_svm(vcpu)->vmcb->save;
++
++ return save->cpl;
++}
++
+ static void svm_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
{
- 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;
+ struct vcpu_svm *svm = to_svm(vcpu);
+@@ -784,6 +842,9 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+ }
+ }
+ #endif
++ if (npt_enabled)
++ goto set;
++
+ if ((vcpu->arch.cr0 & X86_CR0_TS) && !(cr0 & X86_CR0_TS)) {
+ svm->vmcb->control.intercept_exceptions &= ~(1 << NM_VECTOR);
+ vcpu->fpu_active = 1;
+@@ -791,18 +852,29 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+
+ vcpu->arch.cr0 = cr0;
+ cr0 |= X86_CR0_PG | X86_CR0_WP;
+- cr0 &= ~(X86_CR0_CD | X86_CR0_NW);
+ if (!vcpu->fpu_active) {
+ svm->vmcb->control.intercept_exceptions |= (1 << NM_VECTOR);
+ cr0 |= X86_CR0_TS;
}
++set:
+ /*
-+ * Handle strange cache flush from user space exception
-+ * in all other cases. This is undocumented behaviour.
++ * re-enable caching here because the QEMU bios
++ * does not do it - this results in some delay at
++ * reboot
+ */
-+ 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);
++ cr0 &= ~(X86_CR0_CD | X86_CR0_NW);
+ svm->vmcb->save.cr0 = cr0;
}
--void do_spurious_interrupt_bug(struct pt_regs * regs,
-- long error_code)
-+void do_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
+ static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
{
- #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
+- vcpu->arch.cr4 = cr4;
+- to_svm(vcpu)->vmcb->save.cr4 = cr4 | X86_CR4_PAE;
++ unsigned long host_cr4_mce = read_cr4() & X86_CR4_MCE;
++
++ vcpu->arch.cr4 = cr4;
++ if (!npt_enabled)
++ cr4 |= X86_CR4_PAE;
++ cr4 |= host_cr4_mce;
++ to_svm(vcpu)->vmcb->save.cr4 = cr4;
}
--unsigned long patch_espfix_desc(unsigned long uesp,
-- unsigned long kesp)
-+unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp)
+ static void svm_set_segment(struct kvm_vcpu *vcpu,
+@@ -833,13 +905,6 @@ static void svm_set_segment(struct kvm_vcpu *vcpu,
+
+ }
+
+-/* FIXME:
+-
+- svm(vcpu)->vmcb->control.int_ctl &= ~V_TPR_MASK;
+- svm(vcpu)->vmcb->control.int_ctl |= (sregs->cr8 & V_TPR_MASK);
+-
+-*/
+-
+ static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg)
{
- 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];
+ return -EOPNOTSUPP;
+@@ -920,7 +985,7 @@ static void svm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long value,
+ }
+ default:
+ printk(KERN_DEBUG "%s: unexpected dr %u\n",
+- __FUNCTION__, dr);
++ __func__, dr);
+ *exception = UD_VECTOR;
+ return;
+ }
+@@ -962,6 +1027,19 @@ static int nm_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
+ return 1;
+ }
+
++static int mc_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
++{
++ /*
++ * On an #MC intercept the MCE handler is not called automatically in
++ * the host. So do it by hand here.
++ */
++ asm volatile (
++ "int $0x12\n");
++ /* not sure if we ever come back to this point */
+
- /* 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 1;
++}
+
- return new_kesp;
+ static int shutdown_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
+ {
+ /*
+@@ -969,7 +1047,7 @@ static int shutdown_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
+ * so reinitialize it.
+ */
+ clear_page(svm->vmcb);
+- init_vmcb(svm->vmcb);
++ init_vmcb(svm);
+
+ kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
+ return 0;
+@@ -1033,9 +1111,18 @@ static int invalid_op_interception(struct vcpu_svm *svm,
+ static int task_switch_interception(struct vcpu_svm *svm,
+ struct kvm_run *kvm_run)
+ {
+- pr_unimpl(&svm->vcpu, "%s: task switch is unsupported\n", __FUNCTION__);
+- kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
+- return 0;
++ u16 tss_selector;
++
++ tss_selector = (u16)svm->vmcb->control.exit_info_1;
++ if (svm->vmcb->control.exit_info_2 &
++ (1ULL << SVM_EXITINFOSHIFT_TS_REASON_IRET))
++ return kvm_task_switch(&svm->vcpu, tss_selector,
++ TASK_SWITCH_IRET);
++ if (svm->vmcb->control.exit_info_2 &
++ (1ULL << SVM_EXITINFOSHIFT_TS_REASON_JMP))
++ return kvm_task_switch(&svm->vcpu, tss_selector,
++ TASK_SWITCH_JMP);
++ return kvm_task_switch(&svm->vcpu, tss_selector, TASK_SWITCH_CALL);
}
- /*
-- * '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;
+ static int cpuid_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
+@@ -1049,7 +1136,7 @@ static int emulate_on_interception(struct vcpu_svm *svm,
+ struct kvm_run *kvm_run)
+ {
+ if (emulate_instruction(&svm->vcpu, NULL, 0, 0, 0) != EMULATE_DONE)
+- pr_unimpl(&svm->vcpu, "%s: failed\n", __FUNCTION__);
++ pr_unimpl(&svm->vcpu, "%s: failed\n", __func__);
+ return 1;
+ }
-- 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;
+@@ -1179,8 +1266,19 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)
+ svm->vmcb->save.sysenter_esp = data;
+ break;
+ case MSR_IA32_DEBUGCTLMSR:
+- pr_unimpl(vcpu, "%s: MSR_IA32_DEBUGCTLMSR 0x%llx, nop\n",
+- __FUNCTION__, data);
++ if (!svm_has(SVM_FEATURE_LBRV)) {
++ pr_unimpl(vcpu, "%s: MSR_IA32_DEBUGCTL 0x%llx, nop\n",
++ __func__, data);
++ break;
++ }
++ if (data & DEBUGCTL_RESERVED_BITS)
++ return 1;
++
++ svm->vmcb->save.dbgctl = data;
++ if (data & (1ULL<<0))
++ svm_enable_lbrv(svm);
++ else
++ svm_disable_lbrv(svm);
+ break;
+ case MSR_K7_EVNTSEL0:
+ case MSR_K7_EVNTSEL1:
+@@ -1265,6 +1363,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm,
+ [SVM_EXIT_EXCP_BASE + UD_VECTOR] = ud_interception,
+ [SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception,
+ [SVM_EXIT_EXCP_BASE + NM_VECTOR] = nm_interception,
++ [SVM_EXIT_EXCP_BASE + MC_VECTOR] = mc_interception,
+ [SVM_EXIT_INTR] = nop_on_interception,
+ [SVM_EXIT_NMI] = nop_on_interception,
+ [SVM_EXIT_SMI] = nop_on_interception,
+@@ -1290,14 +1389,34 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm,
+ [SVM_EXIT_WBINVD] = emulate_on_interception,
+ [SVM_EXIT_MONITOR] = invalid_op_interception,
+ [SVM_EXIT_MWAIT] = invalid_op_interception,
++ [SVM_EXIT_NPF] = pf_interception,
+ };
+
+-
+ static int handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+ {
+ struct vcpu_svm *svm = to_svm(vcpu);
+ u32 exit_code = svm->vmcb->control.exit_code;
+
++ if (npt_enabled) {
++ int mmu_reload = 0;
++ if ((vcpu->arch.cr0 ^ svm->vmcb->save.cr0) & X86_CR0_PG) {
++ svm_set_cr0(vcpu, svm->vmcb->save.cr0);
++ mmu_reload = 1;
++ }
++ vcpu->arch.cr0 = svm->vmcb->save.cr0;
++ vcpu->arch.cr3 = svm->vmcb->save.cr3;
++ if (is_paging(vcpu) && is_pae(vcpu) && !is_long_mode(vcpu)) {
++ if (!load_pdptrs(vcpu, vcpu->arch.cr3)) {
++ kvm_inject_gp(vcpu, 0);
++ return 1;
++ }
++ }
++ if (mmu_reload) {
++ kvm_mmu_reset_context(vcpu);
++ kvm_mmu_load(vcpu);
+ }
-+ 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);
+ kvm_reput_irq(svm);
- asmlinkage void math_emulate(long arg)
+ if (svm->vmcb->control.exit_code == SVM_EXIT_ERR) {
+@@ -1308,10 +1427,11 @@ static int handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+ }
+
+ if (is_external_interrupt(svm->vmcb->control.exit_int_info) &&
+- exit_code != SVM_EXIT_EXCP_BASE + PF_VECTOR)
++ exit_code != SVM_EXIT_EXCP_BASE + PF_VECTOR &&
++ exit_code != SVM_EXIT_NPF)
+ printk(KERN_ERR "%s: unexpected exit_ini_info 0x%x "
+ "exit_code 0x%x\n",
+- __FUNCTION__, svm->vmcb->control.exit_int_info,
++ __func__, svm->vmcb->control.exit_int_info,
+ exit_code);
+
+ if (exit_code >= ARRAY_SIZE(svm_exit_handlers)
+@@ -1364,6 +1484,27 @@ static void svm_set_irq(struct kvm_vcpu *vcpu, int irq)
+ svm_inject_irq(svm, irq);
+ }
+
++static void update_cr8_intercept(struct kvm_vcpu *vcpu)
++{
++ struct vcpu_svm *svm = to_svm(vcpu);
++ struct vmcb *vmcb = svm->vmcb;
++ int max_irr, tpr;
++
++ if (!irqchip_in_kernel(vcpu->kvm) || vcpu->arch.apic->vapic_addr)
++ return;
++
++ vmcb->control.intercept_cr_write &= ~INTERCEPT_CR8_MASK;
++
++ max_irr = kvm_lapic_find_highest_irr(vcpu);
++ if (max_irr == -1)
++ return;
++
++ tpr = kvm_lapic_get_cr8(vcpu) << 4;
++
++ if (tpr >= (max_irr & 0xf0))
++ vmcb->control.intercept_cr_write |= INTERCEPT_CR8_MASK;
++}
++
+ static void svm_intr_assist(struct kvm_vcpu *vcpu)
{
-- 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();
+ struct vcpu_svm *svm = to_svm(vcpu);
+@@ -1376,14 +1517,14 @@ static void svm_intr_assist(struct kvm_vcpu *vcpu)
+ SVM_EVTINJ_VEC_MASK;
+ vmcb->control.exit_int_info = 0;
+ svm_inject_irq(svm, intr_vector);
+- return;
++ goto out;
+ }
+
+ if (vmcb->control.int_ctl & V_IRQ_MASK)
+- return;
++ goto out;
+
+ if (!kvm_cpu_has_interrupt(vcpu))
+- return;
++ goto out;
+
+ if (!(vmcb->save.rflags & X86_EFLAGS_IF) ||
+ (vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) ||
+@@ -1391,12 +1532,14 @@ static void svm_intr_assist(struct kvm_vcpu *vcpu)
+ /* unable to deliver irq, set pending irq */
+ vmcb->control.intercept |= (1ULL << INTERCEPT_VINTR);
+ svm_inject_irq(svm, 0x0);
+- return;
++ goto out;
+ }
+ /* Okay, we can deliver the interrupt: grab it and update PIC state. */
+ intr_vector = kvm_cpu_get_interrupt(vcpu);
+ svm_inject_irq(svm, intr_vector);
+ kvm_timer_intr_post(vcpu, intr_vector);
++out:
++ update_cr8_intercept(vcpu);
}
- #endif /* CONFIG_MATH_EMULATION */
+ static void kvm_reput_irq(struct vcpu_svm *svm)
+@@ -1482,6 +1625,29 @@ static void svm_prepare_guest_switch(struct kvm_vcpu *vcpu)
+ {
+ }
--
- void __init trap_init(void)
++static inline void sync_cr8_to_lapic(struct kvm_vcpu *vcpu)
++{
++ struct vcpu_svm *svm = to_svm(vcpu);
++
++ if (!(svm->vmcb->control.intercept_cr_write & INTERCEPT_CR8_MASK)) {
++ int cr8 = svm->vmcb->control.int_ctl & V_TPR_MASK;
++ kvm_lapic_set_tpr(vcpu, cr8);
++ }
++}
++
++static inline void sync_lapic_to_cr8(struct kvm_vcpu *vcpu)
++{
++ struct vcpu_svm *svm = to_svm(vcpu);
++ u64 cr8;
++
++ if (!irqchip_in_kernel(vcpu->kvm))
++ return;
++
++ cr8 = kvm_get_cr8(vcpu);
++ svm->vmcb->control.int_ctl &= ~V_TPR_MASK;
++ svm->vmcb->control.int_ctl |= cr8 & V_TPR_MASK;
++}
++
+ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
- int i;
+ struct vcpu_svm *svm = to_svm(vcpu);
+@@ -1491,6 +1657,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
- #ifdef CONFIG_EISA
- void __iomem *p = early_ioremap(0x0FFFD9, 4);
-- if (readl(p) == 'E'+('I'<<8)+('S'<<16)+('A'<<24)) {
+ pre_svm_run(svm);
+
++ sync_lapic_to_cr8(vcpu);
+
-+ if (readl(p) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24))
- EISA_bus = 1;
-- }
- early_iounmap(p, 4);
- #endif
+ save_host_msrs(vcpu);
+ fs_selector = read_fs();
+ gs_selector = read_gs();
+@@ -1499,6 +1667,9 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+ svm->host_dr6 = read_dr6();
+ svm->host_dr7 = read_dr7();
+ svm->vmcb->save.cr2 = vcpu->arch.cr2;
++ /* required for live migration with NPT */
++ if (npt_enabled)
++ svm->vmcb->save.cr3 = vcpu->arch.cr3;
- #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);
+ if (svm->vmcb->save.dr7 & 0xff) {
+ write_dr7(0);
+@@ -1635,6 +1806,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
-- /*
-- * 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");
- }
+ stgi();
-- set_system_gate(SYSCALL_VECTOR,&system_call);
-+ set_system_gate(SYSCALL_VECTOR, &system_call);
++ sync_cr8_to_lapic(vcpu);
++
+ svm->next_rip = 0;
+ }
-- /* 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);
+@@ -1642,6 +1815,12 @@ static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root)
+ {
+ struct vcpu_svm *svm = to_svm(vcpu);
+
++ if (npt_enabled) {
++ svm->vmcb->control.nested_cr3 = root;
++ force_new_asid(vcpu);
++ return;
++ }
+
- set_bit(SYSCALL_VECTOR, used_vectors);
+ svm->vmcb->save.cr3 = root;
+ force_new_asid(vcpu);
-+ init_thread_xstate();
- /*
-- * Should be a barrier for any external CPU state.
-+ * Should be a barrier for any external CPU state:
- */
- cpu_init();
+@@ -1709,6 +1888,7 @@ static struct kvm_x86_ops svm_x86_ops = {
+ .get_segment_base = svm_get_segment_base,
+ .get_segment = svm_get_segment,
+ .set_segment = svm_set_segment,
++ .get_cpl = svm_get_cpl,
+ .get_cs_db_l_bits = kvm_get_cs_db_l_bits,
+ .decache_cr4_guest_bits = svm_decache_cr4_guest_bits,
+ .set_cr0 = svm_set_cr0,
+diff --git a/arch/x86/kvm/svm.h b/arch/x86/kvm/svm.h
+index 5fd5049..1b8afa7 100644
+--- a/arch/x86/kvm/svm.h
++++ b/arch/x86/kvm/svm.h
+@@ -238,6 +238,9 @@ struct __attribute__ ((__packed__)) vmcb {
+ #define SVM_EXITINTINFO_VALID SVM_EVTINJ_VALID
+ #define SVM_EXITINTINFO_VALID_ERR SVM_EVTINJ_VALID_ERR
+
++#define SVM_EXITINFOSHIFT_TS_REASON_IRET 36
++#define SVM_EXITINFOSHIFT_TS_REASON_JMP 38
++
+ #define SVM_EXIT_READ_CR0 0x000
+ #define SVM_EXIT_READ_CR3 0x003
+ #define SVM_EXIT_READ_CR4 0x004
+diff --git a/arch/x86/kvm/tss.h b/arch/x86/kvm/tss.h
+new file mode 100644
+index 0000000..622aa10
+--- /dev/null
++++ b/arch/x86/kvm/tss.h
+@@ -0,0 +1,59 @@
++#ifndef __TSS_SEGMENT_H
++#define __TSS_SEGMENT_H
++
++struct tss_segment_32 {
++ u32 prev_task_link;
++ u32 esp0;
++ u32 ss0;
++ u32 esp1;
++ u32 ss1;
++ u32 esp2;
++ u32 ss2;
++ u32 cr3;
++ u32 eip;
++ u32 eflags;
++ u32 eax;
++ u32 ecx;
++ u32 edx;
++ u32 ebx;
++ u32 esp;
++ u32 ebp;
++ u32 esi;
++ u32 edi;
++ u32 es;
++ u32 cs;
++ u32 ss;
++ u32 ds;
++ u32 fs;
++ u32 gs;
++ u32 ldt_selector;
++ u16 t;
++ u16 io_map;
++};
++
++struct tss_segment_16 {
++ u16 prev_task_link;
++ u16 sp0;
++ u16 ss0;
++ u16 sp1;
++ u16 ss1;
++ u16 sp2;
++ u16 ss2;
++ u16 ip;
++ u16 flag;
++ u16 ax;
++ u16 cx;
++ u16 dx;
++ u16 bx;
++ u16 sp;
++ u16 bp;
++ u16 si;
++ u16 di;
++ u16 es;
++ u16 cs;
++ u16 ss;
++ u16 ds;
++ u16 ldt;
++};
++
++#endif
+diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
+index 8e14628..8e5d664 100644
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -17,7 +17,6 @@
-@@ -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);
+ #include "irq.h"
+ #include "vmx.h"
+-#include "segment_descriptor.h"
+ #include "mmu.h"
+
+ #include <linux/kvm_host.h>
+@@ -37,6 +36,12 @@ MODULE_LICENSE("GPL");
+ static int bypass_guest_pf = 1;
+ module_param(bypass_guest_pf, bool, 0);
+
++static int enable_vpid = 1;
++module_param(enable_vpid, bool, 0);
++
++static int flexpriority_enabled = 1;
++module_param(flexpriority_enabled, bool, 0);
++
+ struct vmcs {
+ u32 revision_id;
+ u32 abort;
+@@ -71,6 +76,7 @@ struct vcpu_vmx {
+ unsigned rip;
+ } irq;
+ } rmode;
++ int vpid;
+ };
+
+ static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
+@@ -85,6 +91,10 @@ static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
+
+ static struct page *vmx_io_bitmap_a;
+ static struct page *vmx_io_bitmap_b;
++static struct page *vmx_msr_bitmap;
+
- return 1;
++static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS);
++static DEFINE_SPINLOCK(vmx_vpid_lock);
+
+ static struct vmcs_config {
+ int size;
+@@ -176,6 +186,11 @@ static inline int is_external_interrupt(u32 intr_info)
+ == (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
}
- __setup("kstack=", kstack_setup);
-diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c
-index 0454666..adff76e 100644
---- a/arch/x86/kernel/traps_64.c
-+++ b/arch/x86/kernel/traps_64.c
-@@ -33,6 +33,8 @@
- #include <linux/kdebug.h>
- #include <linux/utsname.h>
-+#include <mach_traps.h>
++static inline int cpu_has_vmx_msr_bitmap(void)
++{
++ return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS);
++}
+
- #if defined(CONFIG_EDAC)
- #include <linux/edac.h>
- #endif
-@@ -598,10 +600,16 @@ void die(const char * str, struct pt_regs * regs, long err)
- oops_end(flags, regs, SIGSEGV);
+ static inline int cpu_has_vmx_tpr_shadow(void)
+ {
+ return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW);
+@@ -194,8 +209,9 @@ static inline int cpu_has_secondary_exec_ctrls(void)
+
+ static inline bool cpu_has_vmx_virtualize_apic_accesses(void)
+ {
+- return (vmcs_config.cpu_based_2nd_exec_ctrl &
+- SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
++ return flexpriority_enabled
++ && (vmcs_config.cpu_based_2nd_exec_ctrl &
++ SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
}
--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)
+ static inline int vm_need_virtualize_apic_accesses(struct kvm *kvm)
+@@ -204,6 +220,12 @@ static inline int vm_need_virtualize_apic_accesses(struct kvm *kvm)
+ (irqchip_in_kernel(kvm)));
+ }
+
++static inline int cpu_has_vmx_vpid(void)
++{
++ return (vmcs_config.cpu_based_2nd_exec_ctrl &
++ SECONDARY_EXEC_ENABLE_VPID);
++}
++
+ static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
{
-- unsigned long flags = oops_begin();
-+ unsigned long flags;
+ int i;
+@@ -214,6 +236,20 @@ static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
+ return -1;
+ }
+
++static inline void __invvpid(int ext, u16 vpid, gva_t gva)
++{
++ struct {
++ u64 vpid : 16;
++ u64 rsvd : 48;
++ u64 gva;
++ } operand = { vpid, 0, gva };
+
-+ if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) ==
-+ NOTIFY_STOP)
++ asm volatile (ASM_VMX_INVVPID
++ /* CF==1 or ZF==1 --> rc = -1 */
++ "; ja 1f ; ud2 ; 1:"
++ : : "a"(&operand), "c"(ext) : "cc", "memory");
++}
++
+ static struct kvm_msr_entry *find_msr_entry(struct vcpu_vmx *vmx, u32 msr)
+ {
+ int i;
+@@ -257,6 +293,14 @@ static void vcpu_clear(struct vcpu_vmx *vmx)
+ vmx->launched = 0;
+ }
+
++static inline void vpid_sync_vcpu_all(struct vcpu_vmx *vmx)
++{
++ if (vmx->vpid == 0)
+ return;
++
++ __invvpid(VMX_VPID_EXTENT_SINGLE_CONTEXT, vmx->vpid, 0);
++}
++
+ static unsigned long vmcs_readl(unsigned long field)
+ {
+ unsigned long value;
+@@ -353,7 +397,7 @@ static void reload_tss(void)
+ * VT restores TR but not its size. Useless.
+ */
+ struct descriptor_table gdt;
+- struct segment_descriptor *descs;
++ struct desc_struct *descs;
-+ 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);
+ get_gdt(&gdt);
+ descs = (void *)gdt.base;
+@@ -485,11 +529,12 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+ {
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ u64 phys_addr = __pa(vmx->vmcs);
+- u64 tsc_this, delta;
++ u64 tsc_this, delta, new_offset;
+
+ if (vcpu->cpu != cpu) {
+ vcpu_clear(vmx);
+ kvm_migrate_apic_timer(vcpu);
++ vpid_sync_vcpu_all(vmx);
+ }
+
+ if (per_cpu(current_vmcs, cpu) != vmx->vmcs) {
+@@ -524,8 +569,11 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+ * Make sure the time stamp counter is monotonous.
+ */
+ rdtscll(tsc_this);
+- delta = vcpu->arch.host_tsc - tsc_this;
+- vmcs_write64(TSC_OFFSET, vmcs_read64(TSC_OFFSET) + delta);
++ if (tsc_this < vcpu->arch.host_tsc) {
++ delta = vcpu->arch.host_tsc - tsc_this;
++ new_offset = vmcs_read64(TSC_OFFSET) + delta;
++ vmcs_write64(TSC_OFFSET, new_offset);
++ }
+ }
}
--static __kprobes void
-+static notrace __kprobes void
- mem_parity_error(unsigned char reason, struct pt_regs * regs)
+@@ -596,7 +644,7 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
+ {
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+ nr | INTR_TYPE_EXCEPTION
+- | (has_error_code ? INTR_INFO_DELIEVER_CODE_MASK : 0)
++ | (has_error_code ? INTR_INFO_DELIVER_CODE_MASK : 0)
+ | INTR_INFO_VALID_MASK);
+ if (has_error_code)
+ vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
+@@ -959,6 +1007,7 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
+ CPU_BASED_MOV_DR_EXITING |
+ CPU_BASED_USE_TSC_OFFSETING;
+ opt = CPU_BASED_TPR_SHADOW |
++ CPU_BASED_USE_MSR_BITMAPS |
+ CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
+ if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS,
+ &_cpu_based_exec_control) < 0)
+@@ -971,7 +1020,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
+ if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) {
+ min = 0;
+ opt = SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
+- SECONDARY_EXEC_WBINVD_EXITING;
++ SECONDARY_EXEC_WBINVD_EXITING |
++ SECONDARY_EXEC_ENABLE_VPID;
+ if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS2,
+ &_cpu_based_2nd_exec_control) < 0)
+ return -EIO;
+@@ -1080,6 +1130,10 @@ static __init int hardware_setup(void)
{
- 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);
+ if (setup_vmcs_config(&vmcs_config) < 0)
+ return -EIO;
++
++ if (boot_cpu_has(X86_FEATURE_NX))
++ kvm_enable_efer_bits(EFER_NX);
++
+ return alloc_kvm_area();
}
--static __kprobes void
-+static notrace __kprobes void
- io_check_error(unsigned char reason, struct pt_regs * regs)
+@@ -1214,7 +1268,7 @@ static void enter_lmode(struct kvm_vcpu *vcpu)
+ guest_tr_ar = vmcs_read32(GUEST_TR_AR_BYTES);
+ if ((guest_tr_ar & AR_TYPE_MASK) != AR_TYPE_BUSY_64_TSS) {
+ printk(KERN_DEBUG "%s: tss fixup for long mode. \n",
+- __FUNCTION__);
++ __func__);
+ vmcs_write32(GUEST_TR_AR_BYTES,
+ (guest_tr_ar & ~AR_TYPE_MASK)
+ | AR_TYPE_BUSY_64_TSS);
+@@ -1239,6 +1293,11 @@ static void exit_lmode(struct kvm_vcpu *vcpu)
+
+ #endif
+
++static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
++{
++ vpid_sync_vcpu_all(to_vmx(vcpu));
++}
++
+ static void vmx_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
{
- printk("NMI: IOCK error (debug interrupt?)\n");
-@@ -803,9 +811,11 @@ io_check_error(unsigned char reason, struct pt_regs * regs)
- outb(reason, 0x61);
+ vcpu->arch.cr4 &= KVM_GUEST_CR4_MASK;
+@@ -1275,6 +1334,7 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+
+ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
+ {
++ vmx_flush_tlb(vcpu);
+ vmcs_writel(GUEST_CR3, cr3);
+ if (vcpu->arch.cr0 & X86_CR0_PE)
+ vmx_fpu_deactivate(vcpu);
+@@ -1288,14 +1348,14 @@ static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+ vcpu->arch.cr4 = cr4;
}
--static __kprobes void
-+static notrace __kprobes void
- unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
+-#ifdef CONFIG_X86_64
+-
+ static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
{
-+ if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct kvm_msr_entry *msr = find_msr_entry(vmx, MSR_EFER);
+
+ vcpu->arch.shadow_efer = efer;
++ if (!msr)
+ 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)
+ if (efer & EFER_LMA) {
+ vmcs_write32(VM_ENTRY_CONTROLS,
+ vmcs_read32(VM_ENTRY_CONTROLS) |
+@@ -1312,8 +1372,6 @@ static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
+ setup_msrs(vmx);
+ }
- /* 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)
+-#endif
+-
+ static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)
{
- 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 kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+@@ -1344,6 +1402,20 @@ static void vmx_get_segment(struct kvm_vcpu *vcpu,
+ var->unusable = (ar >> 16) & 1;
+ }
+
++static int vmx_get_cpl(struct kvm_vcpu *vcpu)
++{
++ struct kvm_segment kvm_seg;
++
++ if (!(vcpu->arch.cr0 & X86_CR0_PE)) /* if real mode */
++ return 0;
++
++ if (vmx_get_rflags(vcpu) & X86_EFLAGS_VM) /* if virtual 8086 */
++ return 3;
++
++ vmx_get_segment(vcpu, &kvm_seg, VCPU_SREG_CS);
++ return kvm_seg.selector & 3;
++}
++
+ static u32 vmx_segment_access_rights(struct kvm_segment *var)
{
- struct task_struct *me = current;
-- clts(); /* Allow maths ops (or we recurse) */
+ u32 ar;
+@@ -1433,7 +1505,6 @@ static int init_rmode_tss(struct kvm *kvm)
+ int ret = 0;
+ int r;
-- 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();
+- down_read(&kvm->slots_lock);
+ r = kvm_clear_guest_page(kvm, fn, 0, PAGE_SIZE);
+ if (r < 0)
+ goto out;
+@@ -1456,7 +1527,6 @@ static int init_rmode_tss(struct kvm *kvm)
+
+ ret = 1;
+ out:
+- up_read(&kvm->slots_lock);
+ return ret;
+ }
+
+@@ -1494,6 +1564,46 @@ out:
+ return r;
+ }
+
++static void allocate_vpid(struct vcpu_vmx *vmx)
++{
++ int vpid;
++
++ vmx->vpid = 0;
++ if (!enable_vpid || !cpu_has_vmx_vpid())
++ return;
++ spin_lock(&vmx_vpid_lock);
++ vpid = find_first_zero_bit(vmx_vpid_bitmap, VMX_NR_VPIDS);
++ if (vpid < VMX_NR_VPIDS) {
++ vmx->vpid = vpid;
++ __set_bit(vpid, vmx_vpid_bitmap);
+ }
++ spin_unlock(&vmx_vpid_lock);
++}
++
++void vmx_disable_intercept_for_msr(struct page *msr_bitmap, u32 msr)
++{
++ void *va;
++
++ if (!cpu_has_vmx_msr_bitmap())
++ return;
+
-+ 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);
++ * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals
++ * have the write-low and read-high bitmap offsets the wrong way round.
++ * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff.
++ */
++ va = kmap(msr_bitmap);
++ if (msr <= 0x1fff) {
++ __clear_bit(msr, va + 0x000); /* read-low */
++ __clear_bit(msr, va + 0x800); /* write-low */
++ } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
++ msr &= 0x1fff;
++ __clear_bit(msr, va + 0x400); /* read-high */
++ __clear_bit(msr, va + 0xc00); /* write-high */
++ }
++ kunmap(msr_bitmap);
++}
++
+ /*
+ * Sets up the vmcs for emulated real mode.
+ */
+@@ -1511,6 +1621,9 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
+ vmcs_write64(IO_BITMAP_A, page_to_phys(vmx_io_bitmap_a));
+ vmcs_write64(IO_BITMAP_B, page_to_phys(vmx_io_bitmap_b));
- 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;
++ if (cpu_has_vmx_msr_bitmap())
++ vmcs_write64(MSR_BITMAP, page_to_phys(vmx_msr_bitmap));
++
+ vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
- 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);
+ /* Control */
+@@ -1532,6 +1645,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
+ if (!vm_need_virtualize_apic_accesses(vmx->vcpu.kvm))
+ exec_control &=
+ ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
++ if (vmx->vpid == 0)
++ exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
+ vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
+ }
-- prev_scale = *scale;
- if (cpu_khz)
- *scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz;
+@@ -1613,6 +1728,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
+ u64 msr;
+ int ret;
-@@ -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;
++ down_read(&vcpu->kvm->slots_lock);
+ if (!init_rmode_tss(vmx->vcpu.kvm)) {
+ ret = -ENOMEM;
+ goto out;
+@@ -1621,7 +1737,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
+ vmx->vcpu.arch.rmode.active = 0;
- static int
- time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
-@@ -284,15 +283,28 @@ core_initcall(cpufreq_tsc);
+ vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val();
+- set_cr8(&vmx->vcpu, 0);
++ kvm_set_cr8(&vmx->vcpu, 0);
+ msr = 0xfee00000 | MSR_IA32_APICBASE_ENABLE;
+ if (vmx->vcpu.vcpu_id == 0)
+ msr |= MSR_IA32_APICBASE_BSP;
+@@ -1704,18 +1820,22 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
+ vmcs_write64(APIC_ACCESS_ADDR,
+ page_to_phys(vmx->vcpu.kvm->arch.apic_access_page));
+
++ if (vmx->vpid != 0)
++ vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
++
+ vmx->vcpu.arch.cr0 = 0x60000010;
+ vmx_set_cr0(&vmx->vcpu, vmx->vcpu.arch.cr0); /* enter rmode */
+ vmx_set_cr4(&vmx->vcpu, 0);
+-#ifdef CONFIG_X86_64
+ vmx_set_efer(&vmx->vcpu, 0);
+-#endif
+ vmx_fpu_activate(&vmx->vcpu);
+ update_exception_bitmap(&vmx->vcpu);
- /* clock source code */
+- return 0;
++ vpid_sync_vcpu_all(vmx);
++
++ ret = 0;
--static unsigned long current_tsc_khz = 0;
-+static unsigned long current_tsc_khz;
-+static struct clocksource clocksource_tsc;
+ out:
++ up_read(&vcpu->kvm->slots_lock);
+ return ret;
+ }
-+/*
-+ * 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)
+@@ -1723,6 +1843,8 @@ static void vmx_inject_irq(struct kvm_vcpu *vcpu, int irq)
{
- cycle_t ret;
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
- rdtscll(ret);
++ KVMTRACE_1D(INJ_VIRQ, vcpu, (u32)irq, handler);
++
+ if (vcpu->arch.rmode.active) {
+ vmx->rmode.irq.pending = true;
+ vmx->rmode.irq.vector = irq;
+@@ -1844,7 +1966,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+ if ((vect_info & VECTORING_INFO_VALID_MASK) &&
+ !is_page_fault(intr_info))
+ printk(KERN_ERR "%s: unexpected, vectoring info 0x%x "
+- "intr info 0x%x\n", __FUNCTION__, vect_info, intr_info);
++ "intr info 0x%x\n", __func__, vect_info, intr_info);
+
+ if (!irqchip_in_kernel(vcpu->kvm) && is_external_interrupt(vect_info)) {
+ int irq = vect_info & VECTORING_INFO_VECTOR_MASK;
+@@ -1869,10 +1991,12 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+
+ error_code = 0;
+ rip = vmcs_readl(GUEST_RIP);
+- if (intr_info & INTR_INFO_DELIEVER_CODE_MASK)
++ if (intr_info & INTR_INFO_DELIVER_CODE_MASK)
+ error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
+ if (is_page_fault(intr_info)) {
+ cr2 = vmcs_readl(EXIT_QUALIFICATION);
++ KVMTRACE_3D(PAGE_FAULT, vcpu, error_code, (u32)cr2,
++ (u32)((u64)cr2 >> 32), handler);
+ return kvm_mmu_page_fault(vcpu, cr2, error_code);
+ }
-- return ret;
-+ return ret >= clocksource_tsc.cycle_last ?
-+ ret : clocksource_tsc.cycle_last;
+@@ -1901,6 +2025,7 @@ static int handle_external_interrupt(struct kvm_vcpu *vcpu,
+ struct kvm_run *kvm_run)
+ {
+ ++vcpu->stat.irq_exits;
++ KVMTRACE_1D(INTR, vcpu, vmcs_read32(VM_EXIT_INTR_INFO), handler);
+ return 1;
}
- static struct clocksource clocksource_tsc = {
-@@ -392,13 +404,15 @@ void __init tsc_init(void)
- int cpu;
+@@ -1958,25 +2083,27 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+ reg = (exit_qualification >> 8) & 15;
+ switch ((exit_qualification >> 4) & 3) {
+ case 0: /* mov to cr */
++ KVMTRACE_3D(CR_WRITE, vcpu, (u32)cr, (u32)vcpu->arch.regs[reg],
++ (u32)((u64)vcpu->arch.regs[reg] >> 32), handler);
+ switch (cr) {
+ case 0:
+ vcpu_load_rsp_rip(vcpu);
+- set_cr0(vcpu, vcpu->arch.regs[reg]);
++ kvm_set_cr0(vcpu, vcpu->arch.regs[reg]);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ case 3:
+ vcpu_load_rsp_rip(vcpu);
+- set_cr3(vcpu, vcpu->arch.regs[reg]);
++ kvm_set_cr3(vcpu, vcpu->arch.regs[reg]);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ case 4:
+ vcpu_load_rsp_rip(vcpu);
+- set_cr4(vcpu, vcpu->arch.regs[reg]);
++ kvm_set_cr4(vcpu, vcpu->arch.regs[reg]);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ case 8:
+ vcpu_load_rsp_rip(vcpu);
+- set_cr8(vcpu, vcpu->arch.regs[reg]);
++ kvm_set_cr8(vcpu, vcpu->arch.regs[reg]);
+ skip_emulated_instruction(vcpu);
+ if (irqchip_in_kernel(vcpu->kvm))
+ return 1;
+@@ -1990,6 +2117,7 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+ vcpu->arch.cr0 &= ~X86_CR0_TS;
+ vmcs_writel(CR0_READ_SHADOW, vcpu->arch.cr0);
+ vmx_fpu_activate(vcpu);
++ KVMTRACE_0D(CLTS, vcpu, handler);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ case 1: /*mov from cr*/
+@@ -1998,18 +2126,24 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+ vcpu_load_rsp_rip(vcpu);
+ vcpu->arch.regs[reg] = vcpu->arch.cr3;
+ vcpu_put_rsp_rip(vcpu);
++ KVMTRACE_3D(CR_READ, vcpu, (u32)cr,
++ (u32)vcpu->arch.regs[reg],
++ (u32)((u64)vcpu->arch.regs[reg] >> 32),
++ handler);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ case 8:
+ vcpu_load_rsp_rip(vcpu);
+- vcpu->arch.regs[reg] = get_cr8(vcpu);
++ vcpu->arch.regs[reg] = kvm_get_cr8(vcpu);
+ vcpu_put_rsp_rip(vcpu);
++ KVMTRACE_2D(CR_READ, vcpu, (u32)cr,
++ (u32)vcpu->arch.regs[reg], handler);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ }
+ break;
+ case 3: /* lmsw */
+- lmsw(vcpu, (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f);
++ kvm_lmsw(vcpu, (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f);
- if (!cpu_has_tsc)
-- goto out_no_tsc;
-+ return;
+ skip_emulated_instruction(vcpu);
+ return 1;
+@@ -2049,6 +2183,7 @@ static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+ val = 0;
+ }
+ vcpu->arch.regs[reg] = val;
++ KVMTRACE_2D(DR_READ, vcpu, (u32)dr, (u32)val, handler);
+ } else {
+ /* mov to dr */
+ }
+@@ -2073,6 +2208,9 @@ static int handle_rdmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+ return 1;
+ }
- cpu_khz = calculate_cpu_khz();
- tsc_khz = cpu_khz;
++ KVMTRACE_3D(MSR_READ, vcpu, ecx, (u32)data, (u32)(data >> 32),
++ handler);
++
+ /* FIXME: handling of bits 32:63 of rax, rdx */
+ vcpu->arch.regs[VCPU_REGS_RAX] = data & -1u;
+ vcpu->arch.regs[VCPU_REGS_RDX] = (data >> 32) & -1u;
+@@ -2086,6 +2224,9 @@ static int handle_wrmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+ u64 data = (vcpu->arch.regs[VCPU_REGS_RAX] & -1u)
+ | ((u64)(vcpu->arch.regs[VCPU_REGS_RDX] & -1u) << 32);
-- if (!cpu_khz)
-- goto out_no_tsc;
-+ if (!cpu_khz) {
-+ mark_tsc_unstable("could not calculate TSC khz");
-+ return;
-+ }
++ KVMTRACE_3D(MSR_WRITE, vcpu, ecx, (u32)data, (u32)(data >> 32),
++ handler);
++
+ if (vmx_set_msr(vcpu, ecx, data) != 0) {
+ kvm_inject_gp(vcpu, 0);
+ return 1;
+@@ -2110,6 +2251,9 @@ static int handle_interrupt_window(struct kvm_vcpu *vcpu,
+ cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
+ cpu_based_vm_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
+ vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
++
++ KVMTRACE_0D(PEND_INTR, vcpu, handler);
++
+ /*
+ * If the user space waits to inject interrupts, exit as soon as
+ * possible
+@@ -2152,6 +2296,8 @@ static int handle_apic_access(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+ exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+ offset = exit_qualification & 0xffful;
- printk("Detected %lu.%03lu MHz processor.\n",
- (unsigned long)cpu_khz / 1000,
-@@ -431,9 +445,4 @@ void __init tsc_init(void)
- tsc_enabled = 1;
++ KVMTRACE_1D(APIC_ACCESS, vcpu, (u32)offset, handler);
++
+ er = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
- clocksource_register(&clocksource_tsc);
--
-- return;
+ if (er != EMULATE_DONE) {
+@@ -2163,6 +2309,20 @@ static int handle_apic_access(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+ return 1;
+ }
+
++static int handle_task_switch(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
++{
++ unsigned long exit_qualification;
++ u16 tss_selector;
++ int reason;
++
++ exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
++
++ reason = (u32)exit_qualification >> 30;
++ tss_selector = exit_qualification;
++
++ return kvm_task_switch(vcpu, tss_selector, reason);
++}
++
+ /*
+ * The exit handlers return 1 if the exit was handled fully and guest execution
+ * may resume. Otherwise they set the kvm_run parameter to indicate what needs
+@@ -2185,6 +2345,7 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu,
+ [EXIT_REASON_TPR_BELOW_THRESHOLD] = handle_tpr_below_threshold,
+ [EXIT_REASON_APIC_ACCESS] = handle_apic_access,
+ [EXIT_REASON_WBINVD] = handle_wbinvd,
++ [EXIT_REASON_TASK_SWITCH] = handle_task_switch,
+ };
+
+ static const int kvm_vmx_max_exit_handlers =
+@@ -2200,6 +2361,9 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ u32 vectoring_info = vmx->idt_vectoring_info;
+
++ KVMTRACE_3D(VMEXIT, vcpu, exit_reason, (u32)vmcs_readl(GUEST_RIP),
++ (u32)((u64)vmcs_readl(GUEST_RIP) >> 32), entryexit);
++
+ if (unlikely(vmx->fail)) {
+ kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+ kvm_run->fail_entry.hardware_entry_failure_reason
+@@ -2210,7 +2374,7 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+ if ((vectoring_info & VECTORING_INFO_VALID_MASK) &&
+ exit_reason != EXIT_REASON_EXCEPTION_NMI)
+ printk(KERN_WARNING "%s: unexpected, valid vectoring info and "
+- "exit reason is 0x%x\n", __FUNCTION__, exit_reason);
++ "exit reason is 0x%x\n", __func__, exit_reason);
+ if (exit_reason < kvm_vmx_max_exit_handlers
+ && kvm_vmx_exit_handlers[exit_reason])
+ return kvm_vmx_exit_handlers[exit_reason](vcpu, kvm_run);
+@@ -2221,10 +2385,6 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+ return 0;
+ }
+
+-static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
+-{
+-}
-
--out_no_tsc:
-- setup_clear_cpu_cap(X86_FEATURE_TSC);
+ static void update_tpr_threshold(struct kvm_vcpu *vcpu)
+ {
+ int max_irr, tpr;
+@@ -2285,11 +2445,13 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu)
+ return;
+ }
+
++ KVMTRACE_1D(REDELIVER_EVT, vcpu, idtv_info_field, handler);
++
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field);
+ vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
+ vmcs_read32(VM_EXIT_INSTRUCTION_LEN));
+
+- if (unlikely(idtv_info_field & INTR_INFO_DELIEVER_CODE_MASK))
++ if (unlikely(idtv_info_field & INTR_INFO_DELIVER_CODE_MASK))
+ vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE,
+ vmcs_read32(IDT_VECTORING_ERROR_CODE));
+ if (unlikely(has_ext_irq))
+@@ -2470,8 +2632,10 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+ intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+
+ /* We need to handle NMIs before interrupts are enabled */
+- if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) /* nmi */
++ if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { /* nmi */
++ KVMTRACE_0D(NMI, vcpu, handler);
+ asm("int $2");
++ }
}
-diff --git a/arch/x86/kernel/tsc_64.c b/arch/x86/kernel/tsc_64.c
-index d3bebaa..fcc16e5 100644
---- a/arch/x86/kernel/tsc_64.c
-+++ b/arch/x86/kernel/tsc_64.c
-@@ -11,6 +11,7 @@
- #include <asm/hpet.h>
- #include <asm/timex.h>
- #include <asm/timer.h>
-+#include <asm/vgtod.h>
- static int notsc __initdata = 0;
+ static void vmx_free_vmcs(struct kvm_vcpu *vcpu)
+@@ -2489,6 +2653,10 @@ static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
+ {
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
++ spin_lock(&vmx_vpid_lock);
++ if (vmx->vpid != 0)
++ __clear_bit(vmx->vpid, vmx_vpid_bitmap);
++ spin_unlock(&vmx_vpid_lock);
+ vmx_free_vmcs(vcpu);
+ kfree(vmx->host_msrs);
+ kfree(vmx->guest_msrs);
+@@ -2505,6 +2673,8 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
+ if (!vmx)
+ return ERR_PTR(-ENOMEM);
-@@ -44,8 +45,8 @@ DEFINE_PER_CPU(unsigned long, cyc2ns);
++ allocate_vpid(vmx);
++
+ err = kvm_vcpu_init(&vmx->vcpu, kvm, id);
+ if (err)
+ goto free_vcpu;
+@@ -2591,14 +2761,13 @@ static struct kvm_x86_ops vmx_x86_ops = {
+ .get_segment_base = vmx_get_segment_base,
+ .get_segment = vmx_get_segment,
+ .set_segment = vmx_set_segment,
++ .get_cpl = vmx_get_cpl,
+ .get_cs_db_l_bits = vmx_get_cs_db_l_bits,
+ .decache_cr4_guest_bits = vmx_decache_cr4_guest_bits,
+ .set_cr0 = vmx_set_cr0,
+ .set_cr3 = vmx_set_cr3,
+ .set_cr4 = vmx_set_cr4,
+-#ifdef CONFIG_X86_64
+ .set_efer = vmx_set_efer,
+-#endif
+ .get_idt = vmx_get_idt,
+ .set_idt = vmx_set_idt,
+ .get_gdt = vmx_get_gdt,
+@@ -2626,7 +2795,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
- static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
+ static int __init vmx_init(void)
{
-- unsigned long flags, prev_scale, *scale;
- unsigned long long tsc_now, ns_now;
-+ unsigned long flags, *scale;
+- void *iova;
++ void *va;
+ int r;
- 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);
+ vmx_io_bitmap_a = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
+@@ -2639,28 +2808,48 @@ static int __init vmx_init(void)
+ goto out;
+ }
-- prev_scale = *scale;
- if (cpu_khz)
- *scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz;
++ vmx_msr_bitmap = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
++ if (!vmx_msr_bitmap) {
++ r = -ENOMEM;
++ goto out1;
++ }
++
+ /*
+ * Allow direct access to the PC debug port (it is often used for I/O
+ * delays, but the vmexits simply slow things down).
+ */
+- iova = kmap(vmx_io_bitmap_a);
+- memset(iova, 0xff, PAGE_SIZE);
+- clear_bit(0x80, iova);
++ va = kmap(vmx_io_bitmap_a);
++ memset(va, 0xff, PAGE_SIZE);
++ clear_bit(0x80, va);
+ kunmap(vmx_io_bitmap_a);
+
+- iova = kmap(vmx_io_bitmap_b);
+- memset(iova, 0xff, PAGE_SIZE);
++ va = kmap(vmx_io_bitmap_b);
++ memset(va, 0xff, PAGE_SIZE);
+ kunmap(vmx_io_bitmap_b);
+
++ va = kmap(vmx_msr_bitmap);
++ memset(va, 0xff, PAGE_SIZE);
++ kunmap(vmx_msr_bitmap);
++
++ set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
++
+ r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), THIS_MODULE);
+ if (r)
+- goto out1;
++ goto out2;
++
++ vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_FS_BASE);
++ vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_GS_BASE);
++ vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_CS);
++ vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_ESP);
++ vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_EIP);
+
+ if (bypass_guest_pf)
+ kvm_mmu_set_nonpresent_ptes(~0xffeull, 0ull);
+
+ return 0;
+
++out2:
++ __free_page(vmx_msr_bitmap);
+ out1:
+ __free_page(vmx_io_bitmap_b);
+ out:
+@@ -2670,6 +2859,7 @@ out:
+
+ static void __exit vmx_exit(void)
+ {
++ __free_page(vmx_msr_bitmap);
+ __free_page(vmx_io_bitmap_b);
+ __free_page(vmx_io_bitmap_a);
-@@ -288,18 +288,34 @@ int __init notsc_setup(char *s)
+diff --git a/arch/x86/kvm/vmx.h b/arch/x86/kvm/vmx.h
+index d52ae8d..5dff460 100644
+--- a/arch/x86/kvm/vmx.h
++++ b/arch/x86/kvm/vmx.h
+@@ -49,6 +49,7 @@
+ * Definitions of Secondary Processor-Based VM-Execution Controls.
+ */
+ #define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
++#define SECONDARY_EXEC_ENABLE_VPID 0x00000020
+ #define SECONDARY_EXEC_WBINVD_EXITING 0x00000040
- __setup("notsc", notsc_setup);
-+static struct clocksource clocksource_tsc;
+@@ -65,6 +66,7 @@
--/* 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;
- }
+ /* VMCS Encodings */
+ enum vmcs_field {
++ VIRTUAL_PROCESSOR_ID = 0x00000000,
+ GUEST_ES_SELECTOR = 0x00000800,
+ GUEST_CS_SELECTOR = 0x00000802,
+ GUEST_SS_SELECTOR = 0x00000804,
+@@ -231,12 +233,12 @@ enum vmcs_field {
+ */
+ #define INTR_INFO_VECTOR_MASK 0xff /* 7:0 */
+ #define INTR_INFO_INTR_TYPE_MASK 0x700 /* 10:8 */
+-#define INTR_INFO_DELIEVER_CODE_MASK 0x800 /* 11 */
++#define INTR_INFO_DELIVER_CODE_MASK 0x800 /* 11 */
+ #define INTR_INFO_VALID_MASK 0x80000000 /* 31 */
- 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;
- }
+ #define VECTORING_INFO_VECTOR_MASK INTR_INFO_VECTOR_MASK
+ #define VECTORING_INFO_TYPE_MASK INTR_INFO_INTR_TYPE_MASK
+-#define VECTORING_INFO_DELIEVER_CODE_MASK INTR_INFO_DELIEVER_CODE_MASK
++#define VECTORING_INFO_DELIVER_CODE_MASK INTR_INFO_DELIVER_CODE_MASK
+ #define VECTORING_INFO_VALID_MASK INTR_INFO_VALID_MASK
- 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 INTR_TYPE_EXT_INTR (0 << 8) /* external interrupt */
+@@ -321,4 +323,8 @@ enum vmcs_field {
+ #define APIC_ACCESS_PAGE_PRIVATE_MEMSLOT 9
- #define KVM86 ((struct kernel_vm86_struct *)regs)
--#define VMPI KVM86->vm86plus
-+#define VMPI KVM86->vm86plus
++#define VMX_NR_VPIDS (1 << 16)
++#define VMX_VPID_EXTENT_SINGLE_CONTEXT 1
++#define VMX_VPID_EXTENT_ALL_CONTEXT 2
++
+ #endif
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 6b01552..0ce5563 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -15,10 +15,12 @@
+ */
+ #include <linux/kvm_host.h>
+-#include "segment_descriptor.h"
+ #include "irq.h"
+ #include "mmu.h"
++#include "i8254.h"
++#include "tss.h"
- /*
-@@ -81,7 +81,7 @@
- #define VFLAGS (*(unsigned short *)&(current->thread.v86flags))
- #define VEFLAGS (current->thread.v86flags)
++#include <linux/clocksource.h>
+ #include <linux/kvm.h>
+ #include <linux/fs.h>
+ #include <linux/vmalloc.h>
+@@ -28,6 +30,7 @@
--#define set_flags(X,new,mask) \
-+#define set_flags(X, new, mask) \
- ((X) = ((X) & ~(mask)) | ((new) & (mask)))
+ #include <asm/uaccess.h>
+ #include <asm/msr.h>
++#include <asm/desc.h>
- #define SAFE_MASK (0xDD5)
-@@ -93,8 +93,10 @@ static int copy_vm86_regs_to_user(struct vm86_regs __user *user,
- {
- int ret = 0;
+ #define MAX_IO_MSRS 256
+ #define CR0_RESERVED_BITS \
+@@ -41,7 +44,15 @@
+ | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE))
+
+ #define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR)
+-#define EFER_RESERVED_BITS 0xfffffffffffff2fe
++/* EFER defaults:
++ * - enable syscall per default because its emulated by KVM
++ * - enable LME and LMA per default on 64 bit KVM
++ */
++#ifdef CONFIG_X86_64
++static u64 __read_mostly efer_reserved_bits = 0xfffffffffffffafeULL;
++#else
++static u64 __read_mostly efer_reserved_bits = 0xfffffffffffffffeULL;
++#endif
-- /* 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;
+ #define VM_STAT(x) offsetof(struct kvm, stat.x), KVM_STAT_VM
+ #define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
+@@ -63,6 +74,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
+ { "irq_window", VCPU_STAT(irq_window_exits) },
+ { "halt_exits", VCPU_STAT(halt_exits) },
+ { "halt_wakeup", VCPU_STAT(halt_wakeup) },
++ { "hypercalls", VCPU_STAT(hypercalls) },
+ { "request_irq", VCPU_STAT(request_irq_exits) },
+ { "irq_exits", VCPU_STAT(irq_exits) },
+ { "host_state_reload", VCPU_STAT(host_state_reload) },
+@@ -78,6 +90,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
+ { "mmu_recycled", VM_STAT(mmu_recycled) },
+ { "mmu_cache_miss", VM_STAT(mmu_cache_miss) },
+ { "remote_tlb_flush", VM_STAT(remote_tlb_flush) },
++ { "largepages", VM_STAT(lpages) },
+ { NULL }
+ };
+
+@@ -85,7 +98,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
+ unsigned long segment_base(u16 selector)
+ {
+ struct descriptor_table gdt;
+- struct segment_descriptor *d;
++ struct desc_struct *d;
+ unsigned long table_base;
+ unsigned long v;
+
+@@ -101,13 +114,12 @@ unsigned long segment_base(u16 selector)
+ asm("sldt %0" : "=g"(ldt_selector));
+ table_base = segment_base(ldt_selector);
+ }
+- d = (struct segment_descriptor *)(table_base + (selector & ~7));
+- v = d->base_low | ((unsigned long)d->base_mid << 16) |
+- ((unsigned long)d->base_high << 24);
++ d = (struct desc_struct *)(table_base + (selector & ~7));
++ v = d->base0 | ((unsigned long)d->base1 << 16) |
++ ((unsigned long)d->base2 << 24);
+ #ifdef CONFIG_X86_64
+- if (d->system == 0 && (d->type == 2 || d->type == 9 || d->type == 11))
+- v |= ((unsigned long) \
+- ((struct segment_descriptor_64 *)d)->base_higher) << 32;
++ if (d->s == 0 && (d->type == 2 || d->type == 9 || d->type == 11))
++ v |= ((unsigned long)((struct ldttss_desc64 *)d)->base3) << 32;
+ #endif
+ return v;
}
-
--struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
-+struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs)
+@@ -145,11 +157,16 @@ void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long addr,
+ u32 error_code)
{
- 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;
+ ++vcpu->stat.pf_guest;
+- if (vcpu->arch.exception.pending && vcpu->arch.exception.nr == PF_VECTOR) {
+- printk(KERN_DEBUG "kvm: inject_page_fault:"
+- " double fault 0x%lx\n", addr);
+- vcpu->arch.exception.nr = DF_VECTOR;
+- vcpu->arch.exception.error_code = 0;
++ if (vcpu->arch.exception.pending) {
++ if (vcpu->arch.exception.nr == PF_VECTOR) {
++ printk(KERN_DEBUG "kvm: inject_page_fault:"
++ " double fault 0x%lx\n", addr);
++ vcpu->arch.exception.nr = DF_VECTOR;
++ vcpu->arch.exception.error_code = 0;
++ } else if (vcpu->arch.exception.nr == DF_VECTOR) {
++ /* triple fault -> shutdown */
++ set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests);
++ }
+ return;
}
+ vcpu->arch.cr2 = addr;
+@@ -184,7 +201,6 @@ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3)
+ int ret;
+ u64 pdpte[ARRAY_SIZE(vcpu->arch.pdptrs)];
- /* 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;
+- down_read(&vcpu->kvm->slots_lock);
+ ret = kvm_read_guest_page(vcpu->kvm, pdpt_gfn, pdpte,
+ offset * sizeof(u64), sizeof(pdpte));
+ if (ret < 0) {
+@@ -201,10 +217,10 @@ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3)
- 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;
- }
+ memcpy(vcpu->arch.pdptrs, pdpte, sizeof(vcpu->arch.pdptrs));
+ out:
+- up_read(&vcpu->kvm->slots_lock);
- /*
-@@ -346,9 +349,9 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
- /* we never return here */
+ return ret;
}
++EXPORT_SYMBOL_GPL(load_pdptrs);
--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)
+ static bool pdptrs_changed(struct kvm_vcpu *vcpu)
{
-- struct pt_regs * regs32;
-+ struct pt_regs *regs32;
+@@ -215,18 +231,16 @@ static bool pdptrs_changed(struct kvm_vcpu *vcpu)
+ if (is_long_mode(vcpu) || !is_pae(vcpu))
+ return false;
- 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()));
- }
+- down_read(&vcpu->kvm->slots_lock);
+ r = kvm_read_guest(vcpu->kvm, vcpu->arch.cr3 & ~31u, pdpte, sizeof(pdpte));
+ if (r < 0)
+ goto out;
+ changed = memcmp(pdpte, vcpu->arch.pdptrs, sizeof(pdpte)) != 0;
+ out:
+- up_read(&vcpu->kvm->slots_lock);
--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);
+ return changed;
}
--static inline void clear_IF(struct kernel_vm86_regs * regs)
-+static inline void clear_IF(struct kernel_vm86_regs *regs)
+-void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
++void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
{
-- VEFLAGS &= ~VIF_MASK;
-+ VEFLAGS &= ~X86_EFLAGS_VIF;
+ if (cr0 & CR0_RESERVED_BITS) {
+ printk(KERN_DEBUG "set_cr0: 0x%lx #GP, reserved bits 0x%lx\n",
+@@ -284,15 +298,18 @@ void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+ kvm_mmu_reset_context(vcpu);
+ return;
}
+-EXPORT_SYMBOL_GPL(set_cr0);
++EXPORT_SYMBOL_GPL(kvm_set_cr0);
--static inline void clear_TF(struct kernel_vm86_regs * regs)
-+static inline void clear_TF(struct kernel_vm86_regs *regs)
+-void lmsw(struct kvm_vcpu *vcpu, unsigned long msw)
++void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw)
{
-- regs->pt.flags &= ~TF_MASK;
-+ regs->pt.flags &= ~X86_EFLAGS_TF;
- }
+- set_cr0(vcpu, (vcpu->arch.cr0 & ~0x0ful) | (msw & 0x0f));
++ kvm_set_cr0(vcpu, (vcpu->arch.cr0 & ~0x0ful) | (msw & 0x0f));
++ KVMTRACE_1D(LMSW, vcpu,
++ (u32)((vcpu->arch.cr0 & ~0x0ful) | (msw & 0x0f)),
++ handler);
+ }
+-EXPORT_SYMBOL_GPL(lmsw);
++EXPORT_SYMBOL_GPL(kvm_lmsw);
+
+-void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
++void kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+ {
+ if (cr4 & CR4_RESERVED_BITS) {
+ printk(KERN_DEBUG "set_cr4: #GP, reserved bits\n");
+@@ -323,9 +340,9 @@ void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+ vcpu->arch.cr4 = cr4;
+ kvm_mmu_reset_context(vcpu);
+ }
+-EXPORT_SYMBOL_GPL(set_cr4);
++EXPORT_SYMBOL_GPL(kvm_set_cr4);
+
+-void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
++void kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
+ {
+ if (cr3 == vcpu->arch.cr3 && !pdptrs_changed(vcpu)) {
+ kvm_mmu_flush_tlb(vcpu);
+@@ -359,7 +376,6 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
+ */
+ }
--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;
+- down_read(&vcpu->kvm->slots_lock);
+ /*
+ * Does the new cr3 value map to physical memory? (Note, we
+ * catch an invalid cr3 even in real-mode, because it would
+@@ -375,11 +391,10 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
+ vcpu->arch.cr3 = cr3;
+ vcpu->arch.mmu.new_cr3(vcpu);
+ }
+- up_read(&vcpu->kvm->slots_lock);
}
+-EXPORT_SYMBOL_GPL(set_cr3);
++EXPORT_SYMBOL_GPL(kvm_set_cr3);
--/* 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)
+-void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
++void kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
{
- 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);
+ if (cr8 & CR8_RESERVED_BITS) {
+ printk(KERN_DEBUG "set_cr8: #GP, reserved bits 0x%lx\n", cr8);
+@@ -391,16 +406,16 @@ void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
else
- clear_IF(regs);
+ vcpu->arch.cr8 = cr8;
}
+-EXPORT_SYMBOL_GPL(set_cr8);
++EXPORT_SYMBOL_GPL(kvm_set_cr8);
--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)
+-unsigned long get_cr8(struct kvm_vcpu *vcpu)
++unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu)
{
- 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);
+ if (irqchip_in_kernel(vcpu->kvm))
+ return kvm_lapic_get_cr8(vcpu);
else
- clear_IF(regs);
+ return vcpu->arch.cr8;
}
+-EXPORT_SYMBOL_GPL(get_cr8);
++EXPORT_SYMBOL_GPL(kvm_get_cr8);
--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;
+ /*
+ * List of msr numbers which we expose to userspace through KVM_GET_MSRS
+@@ -415,7 +430,8 @@ static u32 msrs_to_save[] = {
+ #ifdef CONFIG_X86_64
+ MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR,
+ #endif
+- MSR_IA32_TIME_STAMP_COUNTER,
++ MSR_IA32_TIME_STAMP_COUNTER, MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK,
++ MSR_IA32_PERF_STATUS,
+ };
-- 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 unsigned num_msrs_to_save;
+@@ -424,11 +440,9 @@ static u32 emulated_msrs[] = {
+ MSR_IA32_MISC_ENABLE,
+ };
--static inline int is_revectored(int nr, struct revectored_struct * bitmap)
-+static inline int is_revectored(int nr, struct revectored_struct *bitmap)
+-#ifdef CONFIG_X86_64
+-
+ static void set_efer(struct kvm_vcpu *vcpu, u64 efer)
{
- __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
- :"=r" (nr)
-- :"m" (*bitmap),"r" (nr));
-+ :"m" (*bitmap), "r" (nr));
- return nr;
+- if (efer & EFER_RESERVED_BITS) {
++ if (efer & efer_reserved_bits) {
+ printk(KERN_DEBUG "set_efer: 0x%llx #GP, reserved bits\n",
+ efer);
+ kvm_inject_gp(vcpu, 0);
+@@ -450,7 +464,12 @@ static void set_efer(struct kvm_vcpu *vcpu, u64 efer)
+ vcpu->arch.shadow_efer = efer;
}
-@@ -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)
+-#endif
++void kvm_enable_efer_bits(u64 mask)
++{
++ efer_reserved_bits &= ~mask;
++}
++EXPORT_SYMBOL_GPL(kvm_enable_efer_bits);
++
- #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)
+ /*
+ * Writes msr value into into the appropriate "register".
+@@ -470,26 +489,86 @@ static int do_set_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
+ return kvm_set_msr(vcpu, index, *data);
+ }
- #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)
++static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock)
++{
++ static int version;
++ struct kvm_wall_clock wc;
++ struct timespec wc_ts;
++
++ if (!wall_clock)
++ return;
++
++ version++;
++
++ kvm_write_guest(kvm, wall_clock, &version, sizeof(version));
++
++ wc_ts = current_kernel_time();
++ wc.wc_sec = wc_ts.tv_sec;
++ wc.wc_nsec = wc_ts.tv_nsec;
++ wc.wc_version = version;
++
++ kvm_write_guest(kvm, wall_clock, &wc, sizeof(wc));
++
++ version++;
++ kvm_write_guest(kvm, wall_clock, &version, sizeof(version));
++}
++
++static void kvm_write_guest_time(struct kvm_vcpu *v)
++{
++ struct timespec ts;
++ unsigned long flags;
++ struct kvm_vcpu_arch *vcpu = &v->arch;
++ void *shared_kaddr;
++
++ if ((!vcpu->time_page))
++ return;
++
++ /* Keep irq disabled to prevent changes to the clock */
++ local_irq_save(flags);
++ kvm_get_msr(v, MSR_IA32_TIME_STAMP_COUNTER,
++ &vcpu->hv_clock.tsc_timestamp);
++ ktime_get_ts(&ts);
++ local_irq_restore(flags);
++
++ /* With all the info we got, fill in the values */
++
++ vcpu->hv_clock.system_time = ts.tv_nsec +
++ (NSEC_PER_SEC * (u64)ts.tv_sec);
++ /*
++ * The interface expects us to write an even number signaling that the
++ * update is finished. Since the guest won't see the intermediate
++ * state, we just write "2" at the end
++ */
++ vcpu->hv_clock.version = 2;
++
++ shared_kaddr = kmap_atomic(vcpu->time_page, KM_USER0);
++
++ memcpy(shared_kaddr + vcpu->time_offset, &vcpu->hv_clock,
++ sizeof(vcpu->hv_clock));
++
++ kunmap_atomic(shared_kaddr, KM_USER0);
++
++ mark_page_dirty(v->kvm, vcpu->time >> PAGE_SHIFT);
++}
++
- #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)
+ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
{
- 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));
- }
+ switch (msr) {
+-#ifdef CONFIG_X86_64
+ case MSR_EFER:
+ set_efer(vcpu, data);
+ break;
+-#endif
+ case MSR_IA32_MC0_STATUS:
+ pr_unimpl(vcpu, "%s: MSR_IA32_MC0_STATUS 0x%llx, nop\n",
+- __FUNCTION__, data);
++ __func__, data);
+ break;
+ case MSR_IA32_MCG_STATUS:
+ pr_unimpl(vcpu, "%s: MSR_IA32_MCG_STATUS 0x%llx, nop\n",
+- __FUNCTION__, data);
++ __func__, data);
+ break;
+ case MSR_IA32_MCG_CTL:
+ pr_unimpl(vcpu, "%s: MSR_IA32_MCG_CTL 0x%llx, nop\n",
+- __FUNCTION__, data);
++ __func__, data);
+ break;
+ case MSR_IA32_UCODE_REV:
+ case MSR_IA32_UCODE_WRITE:
+@@ -501,6 +580,42 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
+ case MSR_IA32_MISC_ENABLE:
+ vcpu->arch.ia32_misc_enable_msr = data;
+ break;
++ case MSR_KVM_WALL_CLOCK:
++ vcpu->kvm->arch.wall_clock = data;
++ kvm_write_wall_clock(vcpu->kvm, data);
++ break;
++ case MSR_KVM_SYSTEM_TIME: {
++ if (vcpu->arch.time_page) {
++ kvm_release_page_dirty(vcpu->arch.time_page);
++ vcpu->arch.time_page = NULL;
++ }
++
++ vcpu->arch.time = data;
++
++ /* we verify if the enable bit is set... */
++ if (!(data & 1))
++ break;
++
++ /* ...but clean it before doing the actual write */
++ vcpu->arch.time_offset = data & ~(PAGE_MASK | 1);
++
++ vcpu->arch.hv_clock.tsc_to_system_mul =
++ clocksource_khz2mult(tsc_khz, 22);
++ vcpu->arch.hv_clock.tsc_shift = 22;
++
++ down_read(¤t->mm->mmap_sem);
++ vcpu->arch.time_page =
++ gfn_to_page(vcpu->kvm, data >> PAGE_SHIFT);
++ up_read(¤t->mm->mmap_sem);
++
++ if (is_error_page(vcpu->arch.time_page)) {
++ kvm_release_page_clean(vcpu->arch.time_page);
++ vcpu->arch.time_page = NULL;
++ }
++
++ kvm_write_guest_time(vcpu);
++ break;
++ }
+ default:
+ pr_unimpl(vcpu, "unhandled wrmsr: 0x%x data %llx\n", msr, data);
+ return 1;
+@@ -540,7 +655,6 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
+ case MSR_IA32_MC0_MISC+12:
+ case MSR_IA32_MC0_MISC+16:
+ case MSR_IA32_UCODE_REV:
+- case MSR_IA32_PERF_STATUS:
+ case MSR_IA32_EBL_CR_POWERON:
+ /* MTRR registers */
+ case 0xfe:
+@@ -556,11 +670,21 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
+ case MSR_IA32_MISC_ENABLE:
+ data = vcpu->arch.ia32_misc_enable_msr;
+ break;
+-#ifdef CONFIG_X86_64
++ case MSR_IA32_PERF_STATUS:
++ /* TSC increment by tick */
++ data = 1000ULL;
++ /* CPU multiplier */
++ data |= (((uint64_t)4ULL) << 40);
++ break;
+ case MSR_EFER:
+ data = vcpu->arch.shadow_efer;
+ break;
+-#endif
++ case MSR_KVM_WALL_CLOCK:
++ data = vcpu->kvm->arch.wall_clock;
++ break;
++ case MSR_KVM_SYSTEM_TIME:
++ data = vcpu->arch.time;
++ break;
+ default:
+ pr_unimpl(vcpu, "unhandled rdmsr: 0x%x\n", msr);
+ return 1;
+@@ -584,9 +708,11 @@ static int __msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs *msrs,
--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;
- }
+ vcpu_load(vcpu);
--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)
++ down_read(&vcpu->kvm->slots_lock);
+ for (i = 0; i < msrs->nmsrs; ++i)
+ if (do_msr(vcpu, entries[i].index, &entries[i].data))
+ break;
++ up_read(&vcpu->kvm->slots_lock);
- #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)
+ vcpu_put(vcpu);
-@@ -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);
+@@ -688,11 +814,24 @@ int kvm_dev_ioctl_check_extension(long ext)
+ case KVM_CAP_USER_MEMORY:
+ case KVM_CAP_SET_TSS_ADDR:
+ case KVM_CAP_EXT_CPUID:
++ case KVM_CAP_CLOCKSOURCE:
++ case KVM_CAP_PIT:
++ case KVM_CAP_NOP_IO_DELAY:
++ case KVM_CAP_MP_STATE:
+ r = 1;
+ break;
+ case KVM_CAP_VAPIC:
+ r = !kvm_x86_ops->cpu_has_accelerated_tpr();
+ break;
++ case KVM_CAP_NR_VCPUS:
++ r = KVM_MAX_VCPUS;
++ break;
++ case KVM_CAP_NR_MEMSLOTS:
++ r = KVM_MEMORY_SLOTS;
++ break;
++ case KVM_CAP_PV_MMU:
++ r = !tdp_enabled;
++ break;
+ default:
+ r = 0;
+ break;
+@@ -763,6 +902,7 @@ out:
+ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+ {
+ kvm_x86_ops->vcpu_load(vcpu, cpu);
++ kvm_write_guest_time(vcpu);
+ }
-@@ -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;
+ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
+@@ -958,32 +1098,32 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
+ }
+ /* function 4 and 0xb have additional index. */
+ case 4: {
+- int index, cache_type;
++ int i, cache_type;
+
+ entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
+ /* read more entries until cache_type is zero */
+- for (index = 1; *nent < maxnent; ++index) {
+- cache_type = entry[index - 1].eax & 0x1f;
++ for (i = 1; *nent < maxnent; ++i) {
++ cache_type = entry[i - 1].eax & 0x1f;
+ if (!cache_type)
+ break;
+- do_cpuid_1_ent(&entry[index], function, index);
+- entry[index].flags |=
++ do_cpuid_1_ent(&entry[i], function, i);
++ entry[i].flags |=
+ KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
+ ++*nent;
}
-
- /* 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));
+ break;
+ }
+ case 0xb: {
+- int index, level_type;
++ int i, level_type;
+
+ entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
+ /* read more entries until level_type is zero */
+- for (index = 1; *nent < maxnent; ++index) {
+- level_type = entry[index - 1].ecx & 0xff;
++ for (i = 1; *nent < maxnent; ++i) {
++ level_type = entry[i - 1].ecx & 0xff;
+ if (!level_type)
+ break;
+- do_cpuid_1_ent(&entry[index], function, index);
+- entry[index].flags |=
++ do_cpuid_1_ent(&entry[i], function, i);
++ entry[i].flags |=
+ KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
+ ++*nent;
}
- 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;
+@@ -1365,6 +1505,23 @@ static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, struct kvm_irqchip *chip)
+ return r;
+ }
--#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 int kvm_vm_ioctl_get_pit(struct kvm *kvm, struct kvm_pit_state *ps)
++{
++ int r = 0;
+
- 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;
-
++ memcpy(ps, &kvm->arch.vpit->pit_state, sizeof(struct kvm_pit_state));
++ return r;
++}
++
++static int kvm_vm_ioctl_set_pit(struct kvm *kvm, struct kvm_pit_state *ps)
++{
++ int r = 0;
++
++ memcpy(&kvm->arch.vpit->pit_state, ps, sizeof(struct kvm_pit_state));
++ kvm_pit_load_count(kvm, 0, ps->channels[0].count);
++ return r;
++}
++
+ /*
+ * Get (and clear) the dirty memory log for a memory slot.
+ */
+@@ -1457,6 +1614,12 @@ long kvm_arch_vm_ioctl(struct file *filp,
+ } else
+ goto out;
+ break;
++ case KVM_CREATE_PIT:
++ r = -ENOMEM;
++ kvm->arch.vpit = kvm_create_pit(kvm);
++ if (kvm->arch.vpit)
++ r = 0;
++ break;
+ case KVM_IRQ_LINE: {
+ struct kvm_irq_level irq_event;
+
+@@ -1512,6 +1675,37 @@ long kvm_arch_vm_ioctl(struct file *filp,
+ r = 0;
+ break;
+ }
++ case KVM_GET_PIT: {
++ struct kvm_pit_state ps;
++ r = -EFAULT;
++ if (copy_from_user(&ps, argp, sizeof ps))
++ goto out;
++ r = -ENXIO;
++ if (!kvm->arch.vpit)
++ goto out;
++ r = kvm_vm_ioctl_get_pit(kvm, &ps);
++ if (r)
++ goto out;
++ r = -EFAULT;
++ if (copy_to_user(argp, &ps, sizeof ps))
++ goto out;
++ r = 0;
++ break;
++ }
++ case KVM_SET_PIT: {
++ struct kvm_pit_state ps;
++ r = -EFAULT;
++ if (copy_from_user(&ps, argp, sizeof ps))
++ goto out;
++ r = -ENXIO;
++ if (!kvm->arch.vpit)
++ goto out;
++ r = kvm_vm_ioctl_set_pit(kvm, &ps);
++ if (r)
++ goto out;
++ r = 0;
++ break;
++ }
+ default:
+ ;
+ }
+@@ -1570,7 +1764,6 @@ int emulator_read_std(unsigned long addr,
+ void *data = val;
+ int r = X86EMUL_CONTINUE;
+
+- down_read(&vcpu->kvm->slots_lock);
+ while (bytes) {
+ gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
+ unsigned offset = addr & (PAGE_SIZE-1);
+@@ -1592,7 +1785,6 @@ int emulator_read_std(unsigned long addr,
+ addr += tocopy;
+ }
out:
-- spin_unlock_irqrestore(&irqbits_lock, flags);
-+ spin_unlock_irqrestore(&irqbits_lock, flags);
- return IRQ_NONE;
+- up_read(&vcpu->kvm->slots_lock);
+ return r;
}
+ EXPORT_SYMBOL_GPL(emulator_read_std);
+@@ -1611,9 +1803,7 @@ static int emulator_read_emulated(unsigned long addr,
+ return X86EMUL_CONTINUE;
+ }
-@@ -770,9 +767,9 @@ static inline void free_vm86_irq(int irqnumber)
- free_irq(irqnumber, NULL);
- vm86_irqs[irqnumber].tsk = NULL;
+- down_read(&vcpu->kvm->slots_lock);
+ gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
+- up_read(&vcpu->kvm->slots_lock);
-- 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);
+ /* For APIC access vmexit */
+ if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
+@@ -1646,19 +1836,15 @@ mmio:
+ return X86EMUL_UNHANDLEABLE;
}
- 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;
- }
+-static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
+- const void *val, int bytes)
++int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
++ const void *val, int bytes)
+ {
+ int ret;
-- spin_unlock_irqrestore(&irqbits_lock, flags);
-+ spin_unlock_irqrestore(&irqbits_lock, flags);
- return ret;
+- down_read(&vcpu->kvm->slots_lock);
+ ret = kvm_write_guest(vcpu->kvm, gpa, val, bytes);
+- if (ret < 0) {
+- up_read(&vcpu->kvm->slots_lock);
++ if (ret < 0)
+ return 0;
+- }
+ kvm_mmu_pte_write(vcpu, gpa, val, bytes);
+- up_read(&vcpu->kvm->slots_lock);
+ return 1;
}
-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)
+@@ -1670,9 +1856,7 @@ static int emulator_write_emulated_onepage(unsigned long addr,
+ struct kvm_io_device *mmio_dev;
+ gpa_t gpa;
+
+- down_read(&vcpu->kvm->slots_lock);
+ gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
+- up_read(&vcpu->kvm->slots_lock);
+
+ if (gpa == UNMAPPED_GVA) {
+ kvm_inject_page_fault(vcpu, addr, 2);
+@@ -1749,7 +1933,6 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
+ char *kaddr;
+ u64 val;
+
+- down_read(&vcpu->kvm->slots_lock);
+ gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
+
+ if (gpa == UNMAPPED_GVA ||
+@@ -1769,9 +1952,8 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
+ set_64bit((u64 *)(kaddr + offset_in_page(gpa)), val);
+ kunmap_atomic(kaddr, KM_USER0);
+ kvm_release_page_dirty(page);
+- emul_write:
+- up_read(&vcpu->kvm->slots_lock);
+ }
++emul_write:
+ #endif
+
+ return emulator_write_emulated(addr, new, bytes, vcpu);
+@@ -1802,7 +1984,7 @@ int emulator_get_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long *dest)
+ *dest = kvm_x86_ops->get_dr(vcpu, dr);
+ return X86EMUL_CONTINUE;
+ default:
+- pr_unimpl(vcpu, "%s: unexpected dr %u\n", __FUNCTION__, dr);
++ pr_unimpl(vcpu, "%s: unexpected dr %u\n", __func__, dr);
+ return X86EMUL_UNHANDLEABLE;
+ }
+ }
+@@ -1840,7 +2022,7 @@ void kvm_report_emulation_failure(struct kvm_vcpu *vcpu, const char *context)
+ }
+ EXPORT_SYMBOL_GPL(kvm_report_emulation_failure);
+
+-struct x86_emulate_ops emulate_ops = {
++static struct x86_emulate_ops emulate_ops = {
+ .read_std = emulator_read_std,
+ .read_emulated = emulator_read_emulated,
+ .write_emulated = emulator_write_emulated,
+@@ -2091,6 +2273,13 @@ int kvm_emulate_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
+ vcpu->arch.pio.guest_page_offset = 0;
+ vcpu->arch.pio.rep = 0;
+
++ if (vcpu->run->io.direction == KVM_EXIT_IO_IN)
++ KVMTRACE_2D(IO_READ, vcpu, vcpu->run->io.port, (u32)size,
++ handler);
++ else
++ KVMTRACE_2D(IO_WRITE, vcpu, vcpu->run->io.port, (u32)size,
++ handler);
++
+ kvm_x86_ops->cache_regs(vcpu);
+ memcpy(vcpu->arch.pio_data, &vcpu->arch.regs[VCPU_REGS_RAX], 4);
+ kvm_x86_ops->decache_regs(vcpu);
+@@ -2129,6 +2318,13 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
+ vcpu->arch.pio.guest_page_offset = offset_in_page(address);
+ vcpu->arch.pio.rep = rep;
+
++ if (vcpu->run->io.direction == KVM_EXIT_IO_IN)
++ KVMTRACE_2D(IO_READ, vcpu, vcpu->run->io.port, (u32)size,
++ handler);
++ else
++ KVMTRACE_2D(IO_WRITE, vcpu, vcpu->run->io.port, (u32)size,
++ handler);
++
+ if (!count) {
+ kvm_x86_ops->skip_emulated_instruction(vcpu);
+ return 1;
+@@ -2163,10 +2359,8 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
+ kvm_x86_ops->skip_emulated_instruction(vcpu);
+
+ for (i = 0; i < nr_pages; ++i) {
+- down_read(&vcpu->kvm->slots_lock);
+ page = gva_to_page(vcpu, address + i * PAGE_SIZE);
+ vcpu->arch.pio.guest_pages[i] = page;
+- up_read(&vcpu->kvm->slots_lock);
+ if (!page) {
+ kvm_inject_gp(vcpu, 0);
+ free_pio_guest_pages(vcpu);
+@@ -2238,10 +2432,13 @@ void kvm_arch_exit(void)
+ int kvm_emulate_halt(struct kvm_vcpu *vcpu)
+ {
+ ++vcpu->stat.halt_exits;
++ KVMTRACE_0D(HLT, vcpu, handler);
+ if (irqchip_in_kernel(vcpu->kvm)) {
+- vcpu->arch.mp_state = VCPU_MP_STATE_HALTED;
++ vcpu->arch.mp_state = KVM_MP_STATE_HALTED;
++ up_read(&vcpu->kvm->slots_lock);
+ kvm_vcpu_block(vcpu);
+- if (vcpu->arch.mp_state != VCPU_MP_STATE_RUNNABLE)
++ down_read(&vcpu->kvm->slots_lock);
++ if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
+ return -EINTR;
+ return 1;
+ } else {
+@@ -2251,9 +2448,19 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu)
}
- #endif
+ EXPORT_SYMBOL_GPL(kvm_emulate_halt);
--static void vmi_allocate_pt(struct mm_struct *mm, u32 pfn)
-+static void vmi_allocate_pte(struct mm_struct *mm, u32 pfn)
++static inline gpa_t hc_gpa(struct kvm_vcpu *vcpu, unsigned long a0,
++ unsigned long a1)
++{
++ if (is_long_mode(vcpu))
++ return a0;
++ else
++ return a0 | ((gpa_t)a1 << 32);
++}
++
+ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
{
- vmi_set_page_type(pfn, VMI_PAGE_L1);
- vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0);
+ unsigned long nr, a0, a1, a2, a3, ret;
++ int r = 1;
+
+ kvm_x86_ops->cache_regs(vcpu);
+
+@@ -2263,6 +2470,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
+ a2 = vcpu->arch.regs[VCPU_REGS_RDX];
+ a3 = vcpu->arch.regs[VCPU_REGS_RSI];
+
++ KVMTRACE_1D(VMMCALL, vcpu, (u32)nr, handler);
++
+ if (!is_long_mode(vcpu)) {
+ nr &= 0xFFFFFFFF;
+ a0 &= 0xFFFFFFFF;
+@@ -2275,13 +2484,17 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
+ case KVM_HC_VAPIC_POLL_IRQ:
+ ret = 0;
+ break;
++ case KVM_HC_MMU_OP:
++ r = kvm_pv_mmu_op(vcpu, a0, hc_gpa(vcpu, a1, a2), &ret);
++ break;
+ default:
+ ret = -KVM_ENOSYS;
+ break;
+ }
+ vcpu->arch.regs[VCPU_REGS_RAX] = ret;
+ kvm_x86_ops->decache_regs(vcpu);
+- return 0;
++ ++vcpu->stat.hypercalls;
++ return r;
}
+ EXPORT_SYMBOL_GPL(kvm_emulate_hypercall);
--static void vmi_allocate_pd(struct mm_struct *mm, u32 pfn)
-+static void vmi_allocate_pmd(struct mm_struct *mm, u32 pfn)
+@@ -2329,7 +2542,7 @@ void realmode_lidt(struct kvm_vcpu *vcpu, u16 limit, unsigned long base)
+ void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw,
+ unsigned long *rflags)
{
- /*
- * 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);
+- lmsw(vcpu, msw);
++ kvm_lmsw(vcpu, msw);
+ *rflags = kvm_x86_ops->get_rflags(vcpu);
}
--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)
+@@ -2346,9 +2559,9 @@ unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr)
+ case 4:
+ return vcpu->arch.cr4;
+ case 8:
+- return get_cr8(vcpu);
++ return kvm_get_cr8(vcpu);
+ default:
+- vcpu_printf(vcpu, "%s: unexpected cr %u\n", __FUNCTION__, cr);
++ vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr);
+ return 0;
+ }
+ }
+@@ -2358,23 +2571,23 @@ void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long val,
{
- 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);
+ switch (cr) {
+ case 0:
+- set_cr0(vcpu, mk_cr_64(vcpu->arch.cr0, val));
++ kvm_set_cr0(vcpu, mk_cr_64(vcpu->arch.cr0, val));
+ *rflags = kvm_x86_ops->get_rflags(vcpu);
+ break;
+ case 2:
+ vcpu->arch.cr2 = val;
+ break;
+ case 3:
+- set_cr3(vcpu, val);
++ kvm_set_cr3(vcpu, val);
+ break;
+ case 4:
+- set_cr4(vcpu, mk_cr_64(vcpu->arch.cr4, val));
++ kvm_set_cr4(vcpu, mk_cr_64(vcpu->arch.cr4, val));
+ break;
+ case 8:
+- set_cr8(vcpu, val & 0xfUL);
++ kvm_set_cr8(vcpu, val & 0xfUL);
+ break;
+ default:
+- vcpu_printf(vcpu, "%s: unexpected cr %u\n", __FUNCTION__, cr);
++ vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr);
+ }
}
--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);
+@@ -2447,6 +2660,11 @@ void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
+ }
+ kvm_x86_ops->decache_regs(vcpu);
+ kvm_x86_ops->skip_emulated_instruction(vcpu);
++ KVMTRACE_5D(CPUID, vcpu, function,
++ (u32)vcpu->arch.regs[VCPU_REGS_RAX],
++ (u32)vcpu->arch.regs[VCPU_REGS_RBX],
++ (u32)vcpu->arch.regs[VCPU_REGS_RCX],
++ (u32)vcpu->arch.regs[VCPU_REGS_RDX], handler);
}
+ EXPORT_SYMBOL_GPL(kvm_emulate_cpuid);
--static void vmi_release_pd(u32 pfn)
-+static void vmi_release_pmd(u32 pfn)
+@@ -2469,7 +2687,7 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu,
+ struct kvm_run *kvm_run)
{
- 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)
+ kvm_run->if_flag = (kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_IF) != 0;
+- kvm_run->cr8 = get_cr8(vcpu);
++ kvm_run->cr8 = kvm_get_cr8(vcpu);
+ kvm_run->apic_base = kvm_get_apic_base(vcpu);
+ if (irqchip_in_kernel(vcpu->kvm))
+ kvm_run->ready_for_interrupt_injection = 1;
+@@ -2509,16 +2727,17 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+ {
+ int r;
- 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;
+- if (unlikely(vcpu->arch.mp_state == VCPU_MP_STATE_SIPI_RECEIVED)) {
++ if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED)) {
+ pr_debug("vcpu %d received sipi with vector # %x\n",
+ vcpu->vcpu_id, vcpu->arch.sipi_vector);
+ kvm_lapic_reset(vcpu);
+ r = kvm_x86_ops->vcpu_reset(vcpu);
+ if (r)
+ return r;
+- vcpu->arch.mp_state = VCPU_MP_STATE_RUNNABLE;
++ vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+ }
+
++ down_read(&vcpu->kvm->slots_lock);
+ vapic_enter(vcpu);
+
+ preempted:
+@@ -2526,6 +2745,10 @@ preempted:
+ kvm_x86_ops->guest_debug_pre(vcpu);
+
+ again:
++ if (vcpu->requests)
++ if (test_and_clear_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
++ kvm_mmu_unload(vcpu);
++
+ r = kvm_mmu_reload(vcpu);
+ if (unlikely(r))
+ goto out;
+@@ -2539,6 +2762,11 @@ again:
+ r = 0;
+ goto out;
+ }
++ if (test_and_clear_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests)) {
++ kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
++ r = 0;
++ goto out;
++ }
}
- 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;
+ kvm_inject_pending_timer_irqs(vcpu);
+@@ -2557,6 +2785,14 @@ again:
+ goto out;
}
- /* 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
++ if (vcpu->requests)
++ if (test_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests)) {
++ local_irq_enable();
++ preempt_enable();
++ r = 1;
++ goto out;
++ }
++
+ if (signal_pending(current)) {
+ local_irq_enable();
+ preempt_enable();
+@@ -2566,6 +2802,13 @@ again:
+ goto out;
+ }
- . = ALIGN(8);
-@@ -247,3 +252,9 @@ SECTIONS
++ vcpu->guest_mode = 1;
++ /*
++ * Make sure that guest_mode assignment won't happen after
++ * testing the pending IRQ vector bitmap.
++ */
++ smp_wmb();
++
+ if (vcpu->arch.exception.pending)
+ __queue_exception(vcpu);
+ else if (irqchip_in_kernel(vcpu->kvm))
+@@ -2575,13 +2818,15 @@ again:
- DWARF_DEBUG
- }
+ kvm_lapic_sync_to_vapic(vcpu);
+
+- vcpu->guest_mode = 1;
++ up_read(&vcpu->kvm->slots_lock);
+
-+/*
-+ * Build-time check on the image size:
-+ */
-+ASSERT((_end - _text <= KERNEL_IMAGE_SIZE),
-+ "kernel image bigger than KERNEL_IMAGE_SIZE")
-diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c
-index d971210..caf2a26 100644
---- a/arch/x86/kernel/vsmp_64.c
-+++ b/arch/x86/kernel/vsmp_64.c
-@@ -8,6 +8,8 @@
- *
- * Ravikiran Thirumalai <kiran at scalemp.com>,
- * Shai Fultheim <shai at scalemp.com>
-+ * Paravirt ops integration: Glauber de Oliveira Costa <gcosta at redhat.com>,
-+ * Ravikiran Thirumalai <kiran at scalemp.com>
- */
+ kvm_guest_enter();
- #include <linux/init.h>
-@@ -15,38 +17,137 @@
- #include <linux/pci_regs.h>
- #include <asm/pci-direct.h>
- #include <asm/io.h>
-+#include <asm/paravirt.h>
+ if (vcpu->requests)
+ if (test_and_clear_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests))
+ kvm_x86_ops->tlb_flush(vcpu);
--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.
-+ */
++ KVMTRACE_0D(VMENTRY, vcpu, entryexit);
+ kvm_x86_ops->run(vcpu, kvm_run);
+
+ vcpu->guest_mode = 0;
+@@ -2601,6 +2846,8 @@ again:
+
+ preempt_enable();
+
++ down_read(&vcpu->kvm->slots_lock);
+
-+static unsigned long vsmp_save_fl(void)
+ /*
+ * Profile KVM exit RIPs:
+ */
+@@ -2628,14 +2875,18 @@ again:
+ }
+
+ out:
++ up_read(&vcpu->kvm->slots_lock);
+ if (r > 0) {
+ kvm_resched(vcpu);
++ down_read(&vcpu->kvm->slots_lock);
+ goto preempted;
+ }
+
+ post_kvm_run_save(vcpu, kvm_run);
+
++ down_read(&vcpu->kvm->slots_lock);
+ vapic_exit(vcpu);
++ up_read(&vcpu->kvm->slots_lock);
+
+ return r;
+ }
+@@ -2647,7 +2898,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+
+ vcpu_load(vcpu);
+
+- if (unlikely(vcpu->arch.mp_state == VCPU_MP_STATE_UNINITIALIZED)) {
++ if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)) {
+ kvm_vcpu_block(vcpu);
+ vcpu_put(vcpu);
+ return -EAGAIN;
+@@ -2658,7 +2909,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+
+ /* re-sync apic's tpr */
+ if (!irqchip_in_kernel(vcpu->kvm))
+- set_cr8(vcpu, kvm_run->cr8);
++ kvm_set_cr8(vcpu, kvm_run->cr8);
+
+ if (vcpu->arch.pio.cur_count) {
+ r = complete_pio(vcpu);
+@@ -2670,9 +2921,12 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+ memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8);
+ vcpu->mmio_read_completed = 1;
+ vcpu->mmio_needed = 0;
++
++ down_read(&vcpu->kvm->slots_lock);
+ r = emulate_instruction(vcpu, kvm_run,
+ vcpu->arch.mmio_fault_cr2, 0,
+ EMULTYPE_NO_DECODE);
++ up_read(&vcpu->kvm->slots_lock);
+ if (r == EMULATE_DO_MMIO) {
+ /*
+ * Read-modify-write. Back to userspace.
+@@ -2773,7 +3027,7 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+ static void get_segment(struct kvm_vcpu *vcpu,
+ struct kvm_segment *var, int seg)
{
-- void *address;
-- unsigned int cap, ctl;
-+ unsigned long flags = native_save_fl();
+- return kvm_x86_ops->get_segment(vcpu, var, seg);
++ kvm_x86_ops->get_segment(vcpu, var, seg);
+ }
-- if (!early_pci_allowed())
-- return 0;
-+ if (!(flags & X86_EFLAGS_IF) || (flags & X86_EFLAGS_AC))
-+ flags &= ~X86_EFLAGS_IF;
-+ return flags;
-+}
+ void kvm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l)
+@@ -2816,7 +3070,7 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
+ sregs->cr2 = vcpu->arch.cr2;
+ sregs->cr3 = vcpu->arch.cr3;
+ sregs->cr4 = vcpu->arch.cr4;
+- sregs->cr8 = get_cr8(vcpu);
++ sregs->cr8 = kvm_get_cr8(vcpu);
+ sregs->efer = vcpu->arch.shadow_efer;
+ sregs->apic_base = kvm_get_apic_base(vcpu);
-- /* 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)
+@@ -2836,12 +3090,438 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
+ return 0;
+ }
+
++int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
++ struct kvm_mp_state *mp_state)
+{
-+ if (flags & X86_EFLAGS_IF)
-+ flags &= ~X86_EFLAGS_AC;
-+ else
-+ flags |= X86_EFLAGS_AC;
-+ native_restore_fl(flags);
++ vcpu_load(vcpu);
++ mp_state->mp_state = vcpu->arch.mp_state;
++ vcpu_put(vcpu);
++ return 0;
+}
+
-+static void vsmp_irq_disable(void)
++int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
++ struct kvm_mp_state *mp_state)
+{
-+ unsigned long flags = native_save_fl();
++ vcpu_load(vcpu);
++ vcpu->arch.mp_state = mp_state->mp_state;
++ vcpu_put(vcpu);
++ return 0;
++}
+
-+ native_restore_fl((flags & ~X86_EFLAGS_IF) | X86_EFLAGS_AC);
+ static void set_segment(struct kvm_vcpu *vcpu,
+ struct kvm_segment *var, int seg)
+ {
+- return kvm_x86_ops->set_segment(vcpu, var, seg);
++ kvm_x86_ops->set_segment(vcpu, var, seg);
+}
+
-+static void vsmp_irq_enable(void)
++static void seg_desct_to_kvm_desct(struct desc_struct *seg_desc, u16 selector,
++ struct kvm_segment *kvm_desct)
+{
-+ unsigned long flags = native_save_fl();
++ kvm_desct->base = seg_desc->base0;
++ kvm_desct->base |= seg_desc->base1 << 16;
++ kvm_desct->base |= seg_desc->base2 << 24;
++ kvm_desct->limit = seg_desc->limit0;
++ kvm_desct->limit |= seg_desc->limit << 16;
++ kvm_desct->selector = selector;
++ kvm_desct->type = seg_desc->type;
++ kvm_desct->present = seg_desc->p;
++ kvm_desct->dpl = seg_desc->dpl;
++ kvm_desct->db = seg_desc->d;
++ kvm_desct->s = seg_desc->s;
++ kvm_desct->l = seg_desc->l;
++ kvm_desct->g = seg_desc->g;
++ kvm_desct->avl = seg_desc->avl;
++ if (!selector)
++ kvm_desct->unusable = 1;
++ else
++ kvm_desct->unusable = 0;
++ kvm_desct->padding = 0;
++}
+
-+ native_restore_fl((flags | X86_EFLAGS_IF) & (~X86_EFLAGS_AC));
++static void get_segment_descritptor_dtable(struct kvm_vcpu *vcpu,
++ u16 selector,
++ struct descriptor_table *dtable)
++{
++ if (selector & 1 << 2) {
++ struct kvm_segment kvm_seg;
++
++ get_segment(vcpu, &kvm_seg, VCPU_SREG_LDTR);
++
++ if (kvm_seg.unusable)
++ dtable->limit = 0;
++ else
++ dtable->limit = kvm_seg.limit;
++ dtable->base = kvm_seg.base;
++ }
++ else
++ kvm_x86_ops->get_gdt(vcpu, dtable);
+}
+
-+static unsigned __init vsmp_patch(u8 type, u16 clobbers, void *ibuf,
-+ unsigned long addr, unsigned len)
++/* allowed just for 8 bytes segments */
++static int load_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
++ struct desc_struct *seg_desc)
+{
-+ 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);
++ struct descriptor_table dtable;
++ u16 index = selector >> 3;
++
++ get_segment_descritptor_dtable(vcpu, selector, &dtable);
++
++ if (dtable.limit < index * 8 + 7) {
++ kvm_queue_exception_e(vcpu, GP_VECTOR, selector & 0xfffc);
++ return 1;
+ }
++ return kvm_read_guest(vcpu->kvm, dtable.base + index * 8, seg_desc, 8);
++}
++
++/* allowed just for 8 bytes segments */
++static int save_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
++ struct desc_struct *seg_desc)
++{
++ struct descriptor_table dtable;
++ u16 index = selector >> 3;
++
++ get_segment_descritptor_dtable(vcpu, selector, &dtable);
+
++ if (dtable.limit < index * 8 + 7)
++ return 1;
++ return kvm_write_guest(vcpu->kvm, dtable.base + index * 8, seg_desc, 8);
+}
+
-+static void __init set_vsmp_pv_ops(void)
++static u32 get_tss_base_addr(struct kvm_vcpu *vcpu,
++ struct desc_struct *seg_desc)
+{
-+ 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;
++ u32 base_addr;
+
- 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);
++ base_addr = seg_desc->base0;
++ base_addr |= (seg_desc->base1 << 16);
++ base_addr |= (seg_desc->base2 << 24);
++
++ return base_addr;
+}
-+#else
-+static void __init set_vsmp_pv_ops(void)
++
++static int load_tss_segment32(struct kvm_vcpu *vcpu,
++ struct desc_struct *seg_desc,
++ struct tss_segment_32 *tss)
+{
++ u32 base_addr;
++
++ base_addr = get_tss_base_addr(vcpu, seg_desc);
++
++ return kvm_read_guest(vcpu->kvm, base_addr, tss,
++ sizeof(struct tss_segment_32));
+}
-+#endif
+
-+#ifdef CONFIG_PCI
-+static int is_vsmp = -1;
++static int save_tss_segment32(struct kvm_vcpu *vcpu,
++ struct desc_struct *seg_desc,
++ struct tss_segment_32 *tss)
++{
++ u32 base_addr;
+
-+static void __init detect_vsmp_box(void)
++ base_addr = get_tss_base_addr(vcpu, seg_desc);
++
++ return kvm_write_guest(vcpu->kvm, base_addr, tss,
++ sizeof(struct tss_segment_32));
++}
++
++static int load_tss_segment16(struct kvm_vcpu *vcpu,
++ struct desc_struct *seg_desc,
++ struct tss_segment_16 *tss)
+{
-+ is_vsmp = 0;
++ u32 base_addr;
+
-+ if (!early_pci_allowed())
-+ return;
++ base_addr = get_tss_base_addr(vcpu, seg_desc);
+
-+ /* 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;
++ return kvm_read_guest(vcpu->kvm, base_addr, tss,
++ sizeof(struct tss_segment_16));
+}
+
-+int is_vsmp_box(void)
++static int save_tss_segment16(struct kvm_vcpu *vcpu,
++ struct desc_struct *seg_desc,
++ struct tss_segment_16 *tss)
+{
-+ if (is_vsmp != -1)
-+ return is_vsmp;
-+ else {
-+ WARN_ON_ONCE(1);
-+ return 0;
-+ }
++ u32 base_addr;
++
++ base_addr = get_tss_base_addr(vcpu, seg_desc);
++
++ return kvm_write_guest(vcpu->kvm, base_addr, tss,
++ sizeof(struct tss_segment_16));
+}
-+#else
-+static int __init detect_vsmp_box(void)
++
++static u16 get_segment_selector(struct kvm_vcpu *vcpu, int seg)
+{
++ struct kvm_segment kvm_seg;
++
++ get_segment(vcpu, &kvm_seg, seg);
++ return kvm_seg.selector;
+}
-+int is_vsmp_box(void)
++
++static int load_segment_descriptor_to_kvm_desct(struct kvm_vcpu *vcpu,
++ u16 selector,
++ struct kvm_segment *kvm_seg)
+{
- return 0;
++ struct desc_struct seg_desc;
++
++ if (load_guest_segment_descriptor(vcpu, selector, &seg_desc))
++ return 1;
++ seg_desct_to_kvm_desct(&seg_desc, selector, kvm_seg);
++ return 0;
++}
++
++static int load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
++ int type_bits, int seg)
++{
++ struct kvm_segment kvm_seg;
++
++ if (load_segment_descriptor_to_kvm_desct(vcpu, selector, &kvm_seg))
++ return 1;
++ kvm_seg.type |= type_bits;
++
++ if (seg != VCPU_SREG_SS && seg != VCPU_SREG_CS &&
++ seg != VCPU_SREG_LDTR)
++ if (!kvm_seg.s)
++ kvm_seg.unusable = 1;
++
++ set_segment(vcpu, &kvm_seg, seg);
++ return 0;
++}
++
++static void save_state_to_tss32(struct kvm_vcpu *vcpu,
++ struct tss_segment_32 *tss)
++{
++ tss->cr3 = vcpu->arch.cr3;
++ tss->eip = vcpu->arch.rip;
++ tss->eflags = kvm_x86_ops->get_rflags(vcpu);
++ tss->eax = vcpu->arch.regs[VCPU_REGS_RAX];
++ tss->ecx = vcpu->arch.regs[VCPU_REGS_RCX];
++ tss->edx = vcpu->arch.regs[VCPU_REGS_RDX];
++ tss->ebx = vcpu->arch.regs[VCPU_REGS_RBX];
++ tss->esp = vcpu->arch.regs[VCPU_REGS_RSP];
++ tss->ebp = vcpu->arch.regs[VCPU_REGS_RBP];
++ tss->esi = vcpu->arch.regs[VCPU_REGS_RSI];
++ tss->edi = vcpu->arch.regs[VCPU_REGS_RDI];
++
++ tss->es = get_segment_selector(vcpu, VCPU_SREG_ES);
++ tss->cs = get_segment_selector(vcpu, VCPU_SREG_CS);
++ tss->ss = get_segment_selector(vcpu, VCPU_SREG_SS);
++ tss->ds = get_segment_selector(vcpu, VCPU_SREG_DS);
++ tss->fs = get_segment_selector(vcpu, VCPU_SREG_FS);
++ tss->gs = get_segment_selector(vcpu, VCPU_SREG_GS);
++ tss->ldt_selector = get_segment_selector(vcpu, VCPU_SREG_LDTR);
++ tss->prev_task_link = get_segment_selector(vcpu, VCPU_SREG_TR);
++}
++
++static int load_state_from_tss32(struct kvm_vcpu *vcpu,
++ struct tss_segment_32 *tss)
++{
++ kvm_set_cr3(vcpu, tss->cr3);
++
++ vcpu->arch.rip = tss->eip;
++ kvm_x86_ops->set_rflags(vcpu, tss->eflags | 2);
++
++ vcpu->arch.regs[VCPU_REGS_RAX] = tss->eax;
++ vcpu->arch.regs[VCPU_REGS_RCX] = tss->ecx;
++ vcpu->arch.regs[VCPU_REGS_RDX] = tss->edx;
++ vcpu->arch.regs[VCPU_REGS_RBX] = tss->ebx;
++ vcpu->arch.regs[VCPU_REGS_RSP] = tss->esp;
++ vcpu->arch.regs[VCPU_REGS_RBP] = tss->ebp;
++ vcpu->arch.regs[VCPU_REGS_RSI] = tss->esi;
++ vcpu->arch.regs[VCPU_REGS_RDI] = tss->edi;
++
++ if (load_segment_descriptor(vcpu, tss->ldt_selector, 0, VCPU_SREG_LDTR))
++ return 1;
++
++ if (load_segment_descriptor(vcpu, tss->es, 1, VCPU_SREG_ES))
++ return 1;
++
++ if (load_segment_descriptor(vcpu, tss->cs, 9, VCPU_SREG_CS))
++ return 1;
++
++ if (load_segment_descriptor(vcpu, tss->ss, 1, VCPU_SREG_SS))
++ return 1;
++
++ if (load_segment_descriptor(vcpu, tss->ds, 1, VCPU_SREG_DS))
++ return 1;
++
++ if (load_segment_descriptor(vcpu, tss->fs, 1, VCPU_SREG_FS))
++ return 1;
++
++ if (load_segment_descriptor(vcpu, tss->gs, 1, VCPU_SREG_GS))
++ return 1;
++ return 0;
++}
++
++static void save_state_to_tss16(struct kvm_vcpu *vcpu,
++ struct tss_segment_16 *tss)
++{
++ tss->ip = vcpu->arch.rip;
++ tss->flag = kvm_x86_ops->get_rflags(vcpu);
++ tss->ax = vcpu->arch.regs[VCPU_REGS_RAX];
++ tss->cx = vcpu->arch.regs[VCPU_REGS_RCX];
++ tss->dx = vcpu->arch.regs[VCPU_REGS_RDX];
++ tss->bx = vcpu->arch.regs[VCPU_REGS_RBX];
++ tss->sp = vcpu->arch.regs[VCPU_REGS_RSP];
++ tss->bp = vcpu->arch.regs[VCPU_REGS_RBP];
++ tss->si = vcpu->arch.regs[VCPU_REGS_RSI];
++ tss->di = vcpu->arch.regs[VCPU_REGS_RDI];
++
++ tss->es = get_segment_selector(vcpu, VCPU_SREG_ES);
++ tss->cs = get_segment_selector(vcpu, VCPU_SREG_CS);
++ tss->ss = get_segment_selector(vcpu, VCPU_SREG_SS);
++ tss->ds = get_segment_selector(vcpu, VCPU_SREG_DS);
++ tss->ldt = get_segment_selector(vcpu, VCPU_SREG_LDTR);
++ tss->prev_task_link = get_segment_selector(vcpu, VCPU_SREG_TR);
++}
++
++static int load_state_from_tss16(struct kvm_vcpu *vcpu,
++ struct tss_segment_16 *tss)
++{
++ vcpu->arch.rip = tss->ip;
++ kvm_x86_ops->set_rflags(vcpu, tss->flag | 2);
++ vcpu->arch.regs[VCPU_REGS_RAX] = tss->ax;
++ vcpu->arch.regs[VCPU_REGS_RCX] = tss->cx;
++ vcpu->arch.regs[VCPU_REGS_RDX] = tss->dx;
++ vcpu->arch.regs[VCPU_REGS_RBX] = tss->bx;
++ vcpu->arch.regs[VCPU_REGS_RSP] = tss->sp;
++ vcpu->arch.regs[VCPU_REGS_RBP] = tss->bp;
++ vcpu->arch.regs[VCPU_REGS_RSI] = tss->si;
++ vcpu->arch.regs[VCPU_REGS_RDI] = tss->di;
++
++ if (load_segment_descriptor(vcpu, tss->ldt, 0, VCPU_SREG_LDTR))
++ return 1;
++
++ if (load_segment_descriptor(vcpu, tss->es, 1, VCPU_SREG_ES))
++ return 1;
++
++ if (load_segment_descriptor(vcpu, tss->cs, 9, VCPU_SREG_CS))
++ return 1;
++
++ if (load_segment_descriptor(vcpu, tss->ss, 1, VCPU_SREG_SS))
++ return 1;
++
++ if (load_segment_descriptor(vcpu, tss->ds, 1, VCPU_SREG_DS))
++ return 1;
++ return 0;
++}
++
++int kvm_task_switch_16(struct kvm_vcpu *vcpu, u16 tss_selector,
++ struct desc_struct *cseg_desc,
++ struct desc_struct *nseg_desc)
++{
++ struct tss_segment_16 tss_segment_16;
++ int ret = 0;
++
++ if (load_tss_segment16(vcpu, cseg_desc, &tss_segment_16))
++ goto out;
++
++ save_state_to_tss16(vcpu, &tss_segment_16);
++ save_tss_segment16(vcpu, cseg_desc, &tss_segment_16);
++
++ if (load_tss_segment16(vcpu, nseg_desc, &tss_segment_16))
++ goto out;
++ if (load_state_from_tss16(vcpu, &tss_segment_16))
++ goto out;
++
++ ret = 1;
++out:
++ return ret;
++}
++
++int kvm_task_switch_32(struct kvm_vcpu *vcpu, u16 tss_selector,
++ struct desc_struct *cseg_desc,
++ struct desc_struct *nseg_desc)
++{
++ struct tss_segment_32 tss_segment_32;
++ int ret = 0;
++
++ if (load_tss_segment32(vcpu, cseg_desc, &tss_segment_32))
++ goto out;
++
++ save_state_to_tss32(vcpu, &tss_segment_32);
++ save_tss_segment32(vcpu, cseg_desc, &tss_segment_32);
++
++ if (load_tss_segment32(vcpu, nseg_desc, &tss_segment_32))
++ goto out;
++ if (load_state_from_tss32(vcpu, &tss_segment_32))
++ goto out;
++
++ ret = 1;
++out:
++ return ret;
}
-+#endif
--core_initcall(vsmp_init);
-+void __init vsmp_init(void)
++int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason)
+{
-+ detect_vsmp_box();
-+ if (!is_vsmp_box())
-+ return;
++ struct kvm_segment tr_seg;
++ struct desc_struct cseg_desc;
++ struct desc_struct nseg_desc;
++ int ret = 0;
+
-+ set_vsmp_pv_ops();
-+ return;
++ get_segment(vcpu, &tr_seg, VCPU_SREG_TR);
++
++ if (load_guest_segment_descriptor(vcpu, tss_selector, &nseg_desc))
++ goto out;
++
++ if (load_guest_segment_descriptor(vcpu, tr_seg.selector, &cseg_desc))
++ goto out;
++
++
++ if (reason != TASK_SWITCH_IRET) {
++ int cpl;
++
++ cpl = kvm_x86_ops->get_cpl(vcpu);
++ if ((tss_selector & 3) > nseg_desc.dpl || cpl > nseg_desc.dpl) {
++ kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
++ return 1;
++ }
++ }
++
++ if (!nseg_desc.p || (nseg_desc.limit0 | nseg_desc.limit << 16) < 0x67) {
++ kvm_queue_exception_e(vcpu, TS_VECTOR, tss_selector & 0xfffc);
++ return 1;
++ }
++
++ if (reason == TASK_SWITCH_IRET || reason == TASK_SWITCH_JMP) {
++ cseg_desc.type &= ~(1 << 8); //clear the B flag
++ save_guest_segment_descriptor(vcpu, tr_seg.selector,
++ &cseg_desc);
++ }
++
++ if (reason == TASK_SWITCH_IRET) {
++ u32 eflags = kvm_x86_ops->get_rflags(vcpu);
++ kvm_x86_ops->set_rflags(vcpu, eflags & ~X86_EFLAGS_NT);
++ }
++
++ kvm_x86_ops->skip_emulated_instruction(vcpu);
++ kvm_x86_ops->cache_regs(vcpu);
++
++ if (nseg_desc.type & 8)
++ ret = kvm_task_switch_32(vcpu, tss_selector, &cseg_desc,
++ &nseg_desc);
++ else
++ ret = kvm_task_switch_16(vcpu, tss_selector, &cseg_desc,
++ &nseg_desc);
++
++ if (reason == TASK_SWITCH_CALL || reason == TASK_SWITCH_GATE) {
++ u32 eflags = kvm_x86_ops->get_rflags(vcpu);
++ kvm_x86_ops->set_rflags(vcpu, eflags | X86_EFLAGS_NT);
++ }
++
++ if (reason != TASK_SWITCH_IRET) {
++ nseg_desc.type |= (1 << 8);
++ save_guest_segment_descriptor(vcpu, tss_selector,
++ &nseg_desc);
++ }
++
++ kvm_x86_ops->set_cr0(vcpu, vcpu->arch.cr0 | X86_CR0_TS);
++ seg_desct_to_kvm_desct(&nseg_desc, tss_selector, &tr_seg);
++ tr_seg.type = 11;
++ set_segment(vcpu, &tr_seg, VCPU_SREG_TR);
++out:
++ kvm_x86_ops->decache_regs(vcpu);
++ return ret;
+}
-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;
++EXPORT_SYMBOL_GPL(kvm_task_switch);
++
+ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
+ struct kvm_sregs *sregs)
+ {
+@@ -2862,12 +3542,10 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
+ mmu_reset_needed |= vcpu->arch.cr3 != sregs->cr3;
+ vcpu->arch.cr3 = sregs->cr3;
+
+- set_cr8(vcpu, sregs->cr8);
++ kvm_set_cr8(vcpu, sregs->cr8);
+
+ mmu_reset_needed |= vcpu->arch.shadow_efer != sregs->efer;
+-#ifdef CONFIG_X86_64
+ kvm_x86_ops->set_efer(vcpu, sregs->efer);
+-#endif
+ kvm_set_apic_base(vcpu, sregs->apic_base);
+
+ kvm_x86_ops->decache_cr4_guest_bits(vcpu);
+@@ -3141,9 +3819,9 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
+
+ vcpu->arch.mmu.root_hpa = INVALID_PAGE;
+ if (!irqchip_in_kernel(kvm) || vcpu->vcpu_id == 0)
+- vcpu->arch.mp_state = VCPU_MP_STATE_RUNNABLE;
++ vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+ else
+- vcpu->arch.mp_state = VCPU_MP_STATE_UNINITIALIZED;
++ vcpu->arch.mp_state = KVM_MP_STATE_UNINITIALIZED;
+
+ page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ if (!page) {
+@@ -3175,7 +3853,9 @@ fail:
+ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
+ {
+ kvm_free_lapic(vcpu);
++ down_read(&vcpu->kvm->slots_lock);
+ kvm_mmu_destroy(vcpu);
++ up_read(&vcpu->kvm->slots_lock);
+ free_page((unsigned long)vcpu->arch.pio_data);
}
--long __vsyscall(3) venosys_1(void)
-+static long __vsyscall(3) venosys_1(void)
+@@ -3219,10 +3899,13 @@ static void kvm_free_vcpus(struct kvm *kvm)
+
+ void kvm_arch_destroy_vm(struct kvm *kvm)
{
- return -ENOSYS;
++ kvm_free_pit(kvm);
+ kfree(kvm->arch.vpic);
+ kfree(kvm->arch.vioapic);
+ kvm_free_vcpus(kvm);
+ kvm_free_physmem(kvm);
++ if (kvm->arch.apic_access_page)
++ put_page(kvm->arch.apic_access_page);
+ kfree(kvm);
}
-diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
-index a66e9c1..58882f9 100644
---- a/arch/x86/kernel/x8664_ksyms_64.c
-+++ b/arch/x86/kernel/x8664_ksyms_64.c
-@@ -4,7 +4,6 @@
- #include <linux/module.h>
- #include <linux/smp.h>
--#include <asm/semaphore.h>
- #include <asm/processor.h>
- #include <asm/uaccess.h>
- #include <asm/pgtable.h>
-@@ -12,11 +11,6 @@
+@@ -3278,8 +3961,8 @@ int kvm_arch_set_memory_region(struct kvm *kvm,
- EXPORT_SYMBOL(kernel_thread);
+ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
+ {
+- return vcpu->arch.mp_state == VCPU_MP_STATE_RUNNABLE
+- || vcpu->arch.mp_state == VCPU_MP_STATE_SIPI_RECEIVED;
++ return vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE
++ || vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED;
+ }
--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);
+ static void vcpu_kick_intr(void *info)
+@@ -3293,11 +3976,17 @@ static void vcpu_kick_intr(void *info)
+ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
+ {
+ int ipi_pcpu = vcpu->cpu;
++ int cpu = get_cpu();
--/* 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
+ if (waitqueue_active(&vcpu->wq)) {
+ wake_up_interruptible(&vcpu->wq);
+ ++vcpu->stat.halt_wakeup;
+ }
+- if (vcpu->guest_mode)
++ /*
++ * We may be called synchronously with irqs disabled in guest mode,
++ * So need not to call smp_call_function_single() in that case.
++ */
++ if (vcpu->guest_mode && vcpu->cpu != cpu)
+ smp_call_function_single(ipi_pcpu, vcpu_kick_intr, vcpu, 0, 0);
++ put_cpu();
+ }
+diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c
+index 7958600..2ca0838 100644
+--- a/arch/x86/kvm/x86_emulate.c
++++ b/arch/x86/kvm/x86_emulate.c
+@@ -65,6 +65,14 @@
+ #define MemAbs (1<<9) /* Memory operand is absolute displacement */
+ #define String (1<<10) /* String instruction (rep capable) */
+ #define Stack (1<<11) /* Stack instruction (push/pop) */
++#define Group (1<<14) /* Bits 3:5 of modrm byte extend opcode */
++#define GroupDual (1<<15) /* Alternate decoding of mod == 3 */
++#define GroupMask 0xff /* Group number stored in bits 0:7 */
++
++enum {
++ Group1_80, Group1_81, Group1_82, Group1_83,
++ Group1A, Group3_Byte, Group3, Group4, Group5, Group7,
++};
--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);
+ static u16 opcode_table[256] = {
+ /* 0x00 - 0x07 */
+@@ -123,14 +131,14 @@ static u16 opcode_table[256] = {
+ ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
+ ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
+ /* 0x80 - 0x87 */
+- ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM,
+- ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM,
++ Group | Group1_80, Group | Group1_81,
++ Group | Group1_82, Group | Group1_83,
+ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+ /* 0x88 - 0x8F */
+ ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov,
+ ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+- 0, ModRM | DstReg, 0, DstMem | SrcNone | ModRM | Mov | Stack,
++ 0, ModRM | DstReg, 0, Group | Group1A,
+ /* 0x90 - 0x9F */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, ImplicitOps | Stack, ImplicitOps | Stack, 0, 0,
+@@ -164,16 +172,15 @@ static u16 opcode_table[256] = {
+ 0, 0, 0, 0,
+ /* 0xF0 - 0xF7 */
+ 0, 0, 0, 0,
+- ImplicitOps, ImplicitOps,
+- ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM,
++ ImplicitOps, ImplicitOps, Group | Group3_Byte, Group | Group3,
+ /* 0xF8 - 0xFF */
+ ImplicitOps, 0, ImplicitOps, ImplicitOps,
+- 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM
++ 0, 0, Group | Group4, Group | Group5,
+ };
+
+ static u16 twobyte_table[256] = {
+ /* 0x00 - 0x0F */
+- 0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0,
++ 0, Group | GroupDual | Group7, 0, 0, 0, 0, ImplicitOps, 0,
+ ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
+ /* 0x10 - 0x1F */
+ 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0,
+@@ -229,6 +236,56 @@ static u16 twobyte_table[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
++static u16 group_table[] = {
++ [Group1_80*8] =
++ ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
++ ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
++ ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
++ ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
++ [Group1_81*8] =
++ DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM,
++ DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM,
++ DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM,
++ DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM,
++ [Group1_82*8] =
++ ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
++ ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
++ ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
++ ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
++ [Group1_83*8] =
++ DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM,
++ DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM,
++ DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM,
++ DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM,
++ [Group1A*8] =
++ DstMem | SrcNone | ModRM | Mov | Stack, 0, 0, 0, 0, 0, 0, 0,
++ [Group3_Byte*8] =
++ ByteOp | SrcImm | DstMem | ModRM, 0,
++ ByteOp | DstMem | SrcNone | ModRM, ByteOp | DstMem | SrcNone | ModRM,
++ 0, 0, 0, 0,
++ [Group3*8] =
++ DstMem | SrcImm | ModRM | SrcImm, 0,
++ DstMem | SrcNone | ModRM, ByteOp | DstMem | SrcNone | ModRM,
++ 0, 0, 0, 0,
++ [Group4*8] =
++ ByteOp | DstMem | SrcNone | ModRM, ByteOp | DstMem | SrcNone | ModRM,
++ 0, 0, 0, 0, 0, 0,
++ [Group5*8] =
++ DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM, 0, 0,
++ SrcMem | ModRM, 0, SrcMem | ModRM | Stack, 0,
++ [Group7*8] =
++ 0, 0, ModRM | SrcMem, ModRM | SrcMem,
++ SrcNone | ModRM | DstMem | Mov, 0,
++ SrcMem16 | ModRM | Mov, SrcMem | ModRM | ByteOp,
++};
++
++static u16 group2_table[] = {
++ [Group7*8] =
++ SrcNone | ModRM, 0, 0, 0,
++ SrcNone | ModRM | DstMem | Mov, 0,
++ SrcMem16 | ModRM | Mov, 0,
++};
++
+ /* EFLAGS bit definitions. */
+ #define EFLG_OF (1<<11)
+ #define EFLG_DF (1<<10)
+@@ -317,7 +374,7 @@ static u16 twobyte_table[256] = {
+
+ #define __emulate_2op(_op,_src,_dst,_eflags,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \
+ do { \
+- unsigned long _tmp; \
++ unsigned long __tmp; \
+ switch ((_dst).bytes) { \
+ case 1: \
+ __asm__ __volatile__ ( \
+@@ -325,7 +382,7 @@ static u16 twobyte_table[256] = {
+ _op"b %"_bx"3,%1; " \
+ _POST_EFLAGS("0", "4", "2") \
+ : "=m" (_eflags), "=m" ((_dst).val), \
+- "=&r" (_tmp) \
++ "=&r" (__tmp) \
+ : _by ((_src).val), "i" (EFLAGS_MASK)); \
+ break; \
+ default: \
+@@ -426,29 +483,40 @@ static u16 twobyte_table[256] = {
+ (_type)_x; \
+ })
- EXPORT_SYMBOL(memset);
- EXPORT_SYMBOL(memcpy);
++static inline unsigned long ad_mask(struct decode_cache *c)
++{
++ return (1UL << (c->ad_bytes << 3)) - 1;
++}
++
+ /* Access/update address held in a register, based on addressing mode. */
+-#define address_mask(reg) \
+- ((c->ad_bytes == sizeof(unsigned long)) ? \
+- (reg) : ((reg) & ((1UL << (c->ad_bytes << 3)) - 1)))
+-#define register_address(base, reg) \
+- ((base) + address_mask(reg))
+-#define register_address_increment(reg, inc) \
+- do { \
+- /* signed type ensures sign extension to long */ \
+- int _inc = (inc); \
+- if (c->ad_bytes == sizeof(unsigned long)) \
+- (reg) += _inc; \
+- else \
+- (reg) = ((reg) & \
+- ~((1UL << (c->ad_bytes << 3)) - 1)) | \
+- (((reg) + _inc) & \
+- ((1UL << (c->ad_bytes << 3)) - 1)); \
+- } while (0)
++static inline unsigned long
++address_mask(struct decode_cache *c, unsigned long reg)
++{
++ if (c->ad_bytes == sizeof(unsigned long))
++ return reg;
++ else
++ return reg & ad_mask(c);
++}
+
+-#define JMP_REL(rel) \
+- do { \
+- register_address_increment(c->eip, rel); \
+- } while (0)
++static inline unsigned long
++register_address(struct decode_cache *c, unsigned long base, unsigned long reg)
++{
++ return base + address_mask(c, reg);
++}
++
++static inline void
++register_address_increment(struct decode_cache *c, unsigned long *reg, int inc)
++{
++ if (c->ad_bytes == sizeof(unsigned long))
++ *reg += inc;
++ else
++ *reg = (*reg & ~ad_mask(c)) | ((*reg + inc) & ad_mask(c));
++}
++
++static inline void jmp_rel(struct decode_cache *c, int rel)
++{
++ register_address_increment(c, &c->eip, rel);
++}
+
+ static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt,
+ struct x86_emulate_ops *ops,
+@@ -763,7 +831,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
+ struct decode_cache *c = &ctxt->decode;
+ int rc = 0;
+ int mode = ctxt->mode;
+- int def_op_bytes, def_ad_bytes;
++ int def_op_bytes, def_ad_bytes, group;
+
+ /* Shadow copy of register state. Committed on successful emulation. */
+
+@@ -864,12 +932,24 @@ done_prefixes:
+ c->b = insn_fetch(u8, 1, c->eip);
+ c->d = twobyte_table[c->b];
+ }
++ }
+
+- /* Unrecognised? */
+- if (c->d == 0) {
+- DPRINTF("Cannot emulate %02x\n", c->b);
+- return -1;
+- }
++ if (c->d & Group) {
++ group = c->d & GroupMask;
++ c->modrm = insn_fetch(u8, 1, c->eip);
++ --c->eip;
++
++ group = (group << 3) + ((c->modrm >> 3) & 7);
++ if ((c->d & GroupDual) && (c->modrm >> 6) == 3)
++ c->d = group2_table[group];
++ else
++ c->d = group_table[group];
++ }
++
++ /* Unrecognised? */
++ if (c->d == 0) {
++ DPRINTF("Cannot emulate %02x\n", c->b);
++ return -1;
+ }
+
+ if (mode == X86EMUL_MODE_PROT64 && (c->d & Stack))
+@@ -924,6 +1004,7 @@ done_prefixes:
+ */
+ if ((c->d & ModRM) && c->modrm_mod == 3) {
+ c->src.type = OP_REG;
++ c->src.val = c->modrm_val;
+ break;
+ }
+ c->src.type = OP_MEM;
+@@ -967,6 +1048,7 @@ done_prefixes:
+ case DstMem:
+ if ((c->d & ModRM) && c->modrm_mod == 3) {
+ c->dst.type = OP_REG;
++ c->dst.val = c->dst.orig_val = c->modrm_val;
+ break;
+ }
+ c->dst.type = OP_MEM;
+@@ -984,8 +1066,8 @@ static inline void emulate_push(struct x86_emulate_ctxt *ctxt)
+ c->dst.type = OP_MEM;
+ c->dst.bytes = c->op_bytes;
+ c->dst.val = c->src.val;
+- register_address_increment(c->regs[VCPU_REGS_RSP], -c->op_bytes);
+- c->dst.ptr = (void *) register_address(ctxt->ss_base,
++ register_address_increment(c, &c->regs[VCPU_REGS_RSP], -c->op_bytes);
++ c->dst.ptr = (void *) register_address(c, ctxt->ss_base,
+ c->regs[VCPU_REGS_RSP]);
+ }
+
+@@ -995,13 +1077,13 @@ static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt,
+ struct decode_cache *c = &ctxt->decode;
+ int rc;
+
+- rc = ops->read_std(register_address(ctxt->ss_base,
++ rc = ops->read_std(register_address(c, ctxt->ss_base,
+ c->regs[VCPU_REGS_RSP]),
+ &c->dst.val, c->dst.bytes, ctxt->vcpu);
+ if (rc != 0)
+ return rc;
+
+- register_address_increment(c->regs[VCPU_REGS_RSP], c->dst.bytes);
++ register_address_increment(c, &c->regs[VCPU_REGS_RSP], c->dst.bytes);
+
+ return 0;
+ }
+@@ -1043,26 +1125,6 @@ static inline int emulate_grp3(struct x86_emulate_ctxt *ctxt,
+
+ switch (c->modrm_reg) {
+ case 0 ... 1: /* test */
+- /*
+- * Special case in Grp3: test has an immediate
+- * source operand.
+- */
+- c->src.type = OP_IMM;
+- c->src.ptr = (unsigned long *)c->eip;
+- c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
+- if (c->src.bytes == 8)
+- c->src.bytes = 4;
+- switch (c->src.bytes) {
+- case 1:
+- c->src.val = insn_fetch(s8, 1, c->eip);
+- break;
+- case 2:
+- c->src.val = insn_fetch(s16, 2, c->eip);
+- break;
+- case 4:
+- c->src.val = insn_fetch(s32, 4, c->eip);
+- break;
+- }
+ emulate_2op_SrcV("test", c->src, c->dst, ctxt->eflags);
+ break;
+ case 2: /* not */
+@@ -1076,7 +1138,6 @@ static inline int emulate_grp3(struct x86_emulate_ctxt *ctxt,
+ rc = X86EMUL_UNHANDLEABLE;
+ break;
+ }
+-done:
+ return rc;
+ }
+
+@@ -1084,7 +1145,6 @@ static inline int emulate_grp45(struct x86_emulate_ctxt *ctxt,
+ struct x86_emulate_ops *ops)
+ {
+ struct decode_cache *c = &ctxt->decode;
+- int rc;
+
+ switch (c->modrm_reg) {
+ case 0: /* inc */
+@@ -1094,36 +1154,11 @@ static inline int emulate_grp45(struct x86_emulate_ctxt *ctxt,
+ emulate_1op("dec", c->dst, ctxt->eflags);
+ break;
+ case 4: /* jmp abs */
+- if (c->b == 0xff)
+- c->eip = c->dst.val;
+- else {
+- DPRINTF("Cannot emulate %02x\n", c->b);
+- return X86EMUL_UNHANDLEABLE;
+- }
++ c->eip = c->src.val;
+ break;
+ case 6: /* push */
+-
+- /* 64-bit mode: PUSH always pushes a 64-bit operand. */
+-
+- if (ctxt->mode == X86EMUL_MODE_PROT64) {
+- c->dst.bytes = 8;
+- rc = ops->read_std((unsigned long)c->dst.ptr,
+- &c->dst.val, 8, ctxt->vcpu);
+- if (rc != 0)
+- return rc;
+- }
+- register_address_increment(c->regs[VCPU_REGS_RSP],
+- -c->dst.bytes);
+- rc = ops->write_emulated(register_address(ctxt->ss_base,
+- c->regs[VCPU_REGS_RSP]), &c->dst.val,
+- c->dst.bytes, ctxt->vcpu);
+- if (rc != 0)
+- return rc;
+- c->dst.type = OP_NONE;
++ emulate_push(ctxt);
+ break;
+- default:
+- DPRINTF("Cannot emulate %02x\n", c->b);
+- return X86EMUL_UNHANDLEABLE;
+ }
+ return 0;
+ }
+@@ -1361,19 +1396,19 @@ special_insn:
+ c->dst.type = OP_MEM;
+ c->dst.bytes = c->op_bytes;
+ c->dst.val = c->src.val;
+- register_address_increment(c->regs[VCPU_REGS_RSP],
++ register_address_increment(c, &c->regs[VCPU_REGS_RSP],
+ -c->op_bytes);
+ c->dst.ptr = (void *) register_address(
+- ctxt->ss_base, c->regs[VCPU_REGS_RSP]);
++ c, ctxt->ss_base, c->regs[VCPU_REGS_RSP]);
+ break;
+ case 0x58 ... 0x5f: /* pop reg */
+ pop_instruction:
+- if ((rc = ops->read_std(register_address(ctxt->ss_base,
++ if ((rc = ops->read_std(register_address(c, ctxt->ss_base,
+ c->regs[VCPU_REGS_RSP]), c->dst.ptr,
+ c->op_bytes, ctxt->vcpu)) != 0)
+ goto done;
+
+- register_address_increment(c->regs[VCPU_REGS_RSP],
++ register_address_increment(c, &c->regs[VCPU_REGS_RSP],
+ c->op_bytes);
+ c->dst.type = OP_NONE; /* Disable writeback. */
+ break;
+@@ -1393,9 +1428,9 @@ special_insn:
+ 1,
+ (c->d & ByteOp) ? 1 : c->op_bytes,
+ c->rep_prefix ?
+- address_mask(c->regs[VCPU_REGS_RCX]) : 1,
++ address_mask(c, c->regs[VCPU_REGS_RCX]) : 1,
+ (ctxt->eflags & EFLG_DF),
+- register_address(ctxt->es_base,
++ register_address(c, ctxt->es_base,
+ c->regs[VCPU_REGS_RDI]),
+ c->rep_prefix,
+ c->regs[VCPU_REGS_RDX]) == 0) {
+@@ -1409,9 +1444,9 @@ special_insn:
+ 0,
+ (c->d & ByteOp) ? 1 : c->op_bytes,
+ c->rep_prefix ?
+- address_mask(c->regs[VCPU_REGS_RCX]) : 1,
++ address_mask(c, c->regs[VCPU_REGS_RCX]) : 1,
+ (ctxt->eflags & EFLG_DF),
+- register_address(c->override_base ?
++ register_address(c, c->override_base ?
+ *c->override_base :
+ ctxt->ds_base,
+ c->regs[VCPU_REGS_RSI]),
+@@ -1425,7 +1460,7 @@ special_insn:
+ int rel = insn_fetch(s8, 1, c->eip);
+
+ if (test_cc(c->b, ctxt->eflags))
+- JMP_REL(rel);
++ jmp_rel(c, rel);
+ break;
+ }
+ case 0x80 ... 0x83: /* Grp1 */
+@@ -1477,7 +1512,7 @@ special_insn:
+ case 0x88 ... 0x8b: /* mov */
+ goto mov;
+ case 0x8d: /* lea r16/r32, m */
+- c->dst.val = c->modrm_val;
++ c->dst.val = c->modrm_ea;
+ break;
+ case 0x8f: /* pop (sole member of Grp1a) */
+ rc = emulate_grp1a(ctxt, ops);
+@@ -1501,27 +1536,27 @@ special_insn:
+ case 0xa4 ... 0xa5: /* movs */
+ c->dst.type = OP_MEM;
+ c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
+- c->dst.ptr = (unsigned long *)register_address(
++ c->dst.ptr = (unsigned long *)register_address(c,
+ ctxt->es_base,
+ c->regs[VCPU_REGS_RDI]);
+- if ((rc = ops->read_emulated(register_address(
++ if ((rc = ops->read_emulated(register_address(c,
+ c->override_base ? *c->override_base :
+ ctxt->ds_base,
+ c->regs[VCPU_REGS_RSI]),
+ &c->dst.val,
+ c->dst.bytes, ctxt->vcpu)) != 0)
+ goto done;
+- register_address_increment(c->regs[VCPU_REGS_RSI],
++ register_address_increment(c, &c->regs[VCPU_REGS_RSI],
+ (ctxt->eflags & EFLG_DF) ? -c->dst.bytes
+ : c->dst.bytes);
+- register_address_increment(c->regs[VCPU_REGS_RDI],
++ register_address_increment(c, &c->regs[VCPU_REGS_RDI],
+ (ctxt->eflags & EFLG_DF) ? -c->dst.bytes
+ : c->dst.bytes);
+ break;
+ case 0xa6 ... 0xa7: /* cmps */
+ c->src.type = OP_NONE; /* Disable writeback. */
+ c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
+- c->src.ptr = (unsigned long *)register_address(
++ c->src.ptr = (unsigned long *)register_address(c,
+ c->override_base ? *c->override_base :
+ ctxt->ds_base,
+ c->regs[VCPU_REGS_RSI]);
+@@ -1533,7 +1568,7 @@ special_insn:
+
+ c->dst.type = OP_NONE; /* Disable writeback. */
+ c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
+- c->dst.ptr = (unsigned long *)register_address(
++ c->dst.ptr = (unsigned long *)register_address(c,
+ ctxt->es_base,
+ c->regs[VCPU_REGS_RDI]);
+ if ((rc = ops->read_emulated((unsigned long)c->dst.ptr,
+@@ -1546,10 +1581,10 @@ special_insn:
+
+ emulate_2op_SrcV("cmp", c->src, c->dst, ctxt->eflags);
+
+- register_address_increment(c->regs[VCPU_REGS_RSI],
++ register_address_increment(c, &c->regs[VCPU_REGS_RSI],
+ (ctxt->eflags & EFLG_DF) ? -c->src.bytes
+ : c->src.bytes);
+- register_address_increment(c->regs[VCPU_REGS_RDI],
++ register_address_increment(c, &c->regs[VCPU_REGS_RDI],
+ (ctxt->eflags & EFLG_DF) ? -c->dst.bytes
+ : c->dst.bytes);
+
+@@ -1557,11 +1592,11 @@ special_insn:
+ case 0xaa ... 0xab: /* stos */
+ c->dst.type = OP_MEM;
+ c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
+- c->dst.ptr = (unsigned long *)register_address(
++ c->dst.ptr = (unsigned long *)register_address(c,
+ ctxt->es_base,
+ c->regs[VCPU_REGS_RDI]);
+ c->dst.val = c->regs[VCPU_REGS_RAX];
+- register_address_increment(c->regs[VCPU_REGS_RDI],
++ register_address_increment(c, &c->regs[VCPU_REGS_RDI],
+ (ctxt->eflags & EFLG_DF) ? -c->dst.bytes
+ : c->dst.bytes);
+ break;
+@@ -1569,7 +1604,7 @@ special_insn:
+ c->dst.type = OP_REG;
+ c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
+ c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX];
+- if ((rc = ops->read_emulated(register_address(
++ if ((rc = ops->read_emulated(register_address(c,
+ c->override_base ? *c->override_base :
+ ctxt->ds_base,
+ c->regs[VCPU_REGS_RSI]),
+@@ -1577,7 +1612,7 @@ special_insn:
+ c->dst.bytes,
+ ctxt->vcpu)) != 0)
+ goto done;
+- register_address_increment(c->regs[VCPU_REGS_RSI],
++ register_address_increment(c, &c->regs[VCPU_REGS_RSI],
+ (ctxt->eflags & EFLG_DF) ? -c->dst.bytes
+ : c->dst.bytes);
+ break;
+@@ -1616,14 +1651,14 @@ special_insn:
+ goto cannot_emulate;
+ }
+ c->src.val = (unsigned long) c->eip;
+- JMP_REL(rel);
++ jmp_rel(c, rel);
+ c->op_bytes = c->ad_bytes;
+ emulate_push(ctxt);
+ break;
+ }
+ case 0xe9: /* jmp rel */
+ case 0xeb: /* jmp rel short */
+- JMP_REL(c->src.val);
++ jmp_rel(c, c->src.val);
+ c->dst.type = OP_NONE; /* Disable writeback. */
+ break;
+ case 0xf4: /* hlt */
+@@ -1690,6 +1725,8 @@ twobyte_insn:
+ goto done;
+
+ kvm_emulate_hypercall(ctxt->vcpu);
++ /* Disable writeback. */
++ c->dst.type = OP_NONE;
+ break;
+ case 2: /* lgdt */
+ rc = read_descriptor(ctxt, ops, c->src.ptr,
+@@ -1697,6 +1734,8 @@ twobyte_insn:
+ if (rc)
+ goto done;
+ realmode_lgdt(ctxt->vcpu, size, address);
++ /* Disable writeback. */
++ c->dst.type = OP_NONE;
+ break;
+ case 3: /* lidt/vmmcall */
+ if (c->modrm_mod == 3 && c->modrm_rm == 1) {
+@@ -1712,27 +1751,25 @@ twobyte_insn:
+ goto done;
+ realmode_lidt(ctxt->vcpu, size, address);
+ }
++ /* Disable writeback. */
++ c->dst.type = OP_NONE;
+ break;
+ case 4: /* smsw */
+- if (c->modrm_mod != 3)
+- goto cannot_emulate;
+- *(u16 *)&c->regs[c->modrm_rm]
+- = realmode_get_cr(ctxt->vcpu, 0);
++ c->dst.bytes = 2;
++ c->dst.val = realmode_get_cr(ctxt->vcpu, 0);
+ break;
+ case 6: /* lmsw */
+- if (c->modrm_mod != 3)
+- goto cannot_emulate;
+- realmode_lmsw(ctxt->vcpu, (u16)c->modrm_val,
+- &ctxt->eflags);
++ realmode_lmsw(ctxt->vcpu, (u16)c->src.val,
++ &ctxt->eflags);
+ break;
+ case 7: /* invlpg*/
+ emulate_invlpg(ctxt->vcpu, memop);
++ /* Disable writeback. */
++ c->dst.type = OP_NONE;
+ break;
+ default:
+ goto cannot_emulate;
+ }
+- /* Disable writeback. */
+- c->dst.type = OP_NONE;
+ break;
+ case 0x06:
+ emulate_clts(ctxt->vcpu);
+@@ -1823,7 +1860,7 @@ twobyte_insn:
+ goto cannot_emulate;
+ }
+ if (test_cc(c->b, ctxt->eflags))
+- JMP_REL(rel);
++ jmp_rel(c, rel);
+ c->dst.type = OP_NONE;
+ break;
+ }
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index 3335b45..af65b2d 100644
--- a/arch/x86/lguest/boot.c
@@ -261143,6 +327758,284 @@
return -ETIME;
}
+diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
+index 25df1c1..76f60f5 100644
+--- a/arch/x86/lib/Makefile
++++ b/arch/x86/lib/Makefile
+@@ -11,7 +11,7 @@ lib-y += memcpy_$(BITS).o
+ ifeq ($(CONFIG_X86_32),y)
+ lib-y += checksum_32.o
+ lib-y += strstr_32.o
+- lib-y += bitops_32.o semaphore_32.o string_32.o
++ lib-y += semaphore_32.o string_32.o
+
+ lib-$(CONFIG_X86_USE_3DNOW) += mmx_32.o
+ else
+@@ -21,7 +21,6 @@ else
+
+ lib-y += csum-partial_64.o csum-copy_64.o csum-wrappers_64.o
+ lib-y += thunk_64.o clear_page_64.o copy_page_64.o
+- lib-y += bitops_64.o
+ lib-y += memmove_64.o memset_64.o
+ lib-y += copy_user_64.o rwlock_64.o copy_user_nocache_64.o
+ endif
+diff --git a/arch/x86/lib/bitops_32.c b/arch/x86/lib/bitops_32.c
+deleted file mode 100644
+index b654404..0000000
+--- a/arch/x86/lib/bitops_32.c
++++ /dev/null
+@@ -1,70 +0,0 @@
+-#include <linux/bitops.h>
+-#include <linux/module.h>
+-
+-/**
+- * find_next_bit - find the next set bit in a memory region
+- * @addr: The address to base the search on
+- * @offset: The bitnumber to start searching at
+- * @size: The maximum size to search
+- */
+-int find_next_bit(const unsigned long *addr, int size, int offset)
+-{
+- const unsigned long *p = addr + (offset >> 5);
+- int set = 0, bit = offset & 31, res;
+-
+- if (bit) {
+- /*
+- * Look for nonzero in the first 32 bits:
+- */
+- __asm__("bsfl %1,%0\n\t"
+- "jne 1f\n\t"
+- "movl $32, %0\n"
+- "1:"
+- : "=r" (set)
+- : "r" (*p >> bit));
+- if (set < (32 - bit))
+- return set + offset;
+- set = 32 - bit;
+- p++;
+- }
+- /*
+- * No set bit yet, search remaining full words for a bit
+- */
+- res = find_first_bit (p, size - 32 * (p - addr));
+- return (offset + set + res);
+-}
+-EXPORT_SYMBOL(find_next_bit);
+-
+-/**
+- * find_next_zero_bit - find the first zero bit in a memory region
+- * @addr: The address to base the search on
+- * @offset: The bitnumber to start searching at
+- * @size: The maximum size to search
+- */
+-int find_next_zero_bit(const unsigned long *addr, int size, int offset)
+-{
+- const unsigned long *p = addr + (offset >> 5);
+- int set = 0, bit = offset & 31, res;
+-
+- if (bit) {
+- /*
+- * Look for zero in the first 32 bits.
+- */
+- __asm__("bsfl %1,%0\n\t"
+- "jne 1f\n\t"
+- "movl $32, %0\n"
+- "1:"
+- : "=r" (set)
+- : "r" (~(*p >> bit)));
+- if (set < (32 - bit))
+- return set + offset;
+- set = 32 - bit;
+- p++;
+- }
+- /*
+- * No zero yet, search remaining full bytes for a zero
+- */
+- res = find_first_zero_bit(p, size - 32 * (p - addr));
+- return (offset + set + res);
+-}
+-EXPORT_SYMBOL(find_next_zero_bit);
+diff --git a/arch/x86/lib/bitops_64.c b/arch/x86/lib/bitops_64.c
+deleted file mode 100644
+index 0e8f491..0000000
+--- a/arch/x86/lib/bitops_64.c
++++ /dev/null
+@@ -1,175 +0,0 @@
+-#include <linux/bitops.h>
+-
+-#undef find_first_zero_bit
+-#undef find_next_zero_bit
+-#undef find_first_bit
+-#undef find_next_bit
+-
+-static inline long
+-__find_first_zero_bit(const unsigned long * addr, unsigned long size)
+-{
+- long d0, d1, d2;
+- long res;
+-
+- /*
+- * We must test the size in words, not in bits, because
+- * otherwise incoming sizes in the range -63..-1 will not run
+- * any scasq instructions, and then the flags used by the je
+- * instruction will have whatever random value was in place
+- * before. Nobody should call us like that, but
+- * find_next_zero_bit() does when offset and size are at the
+- * same word and it fails to find a zero itself.
+- */
+- size += 63;
+- size >>= 6;
+- if (!size)
+- return 0;
+- asm volatile(
+- " repe; scasq\n"
+- " je 1f\n"
+- " xorq -8(%%rdi),%%rax\n"
+- " subq $8,%%rdi\n"
+- " bsfq %%rax,%%rdx\n"
+- "1: subq %[addr],%%rdi\n"
+- " shlq $3,%%rdi\n"
+- " addq %%rdi,%%rdx"
+- :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
+- :"0" (0ULL), "1" (size), "2" (addr), "3" (-1ULL),
+- [addr] "S" (addr) : "memory");
+- /*
+- * Any register would do for [addr] above, but GCC tends to
+- * prefer rbx over rsi, even though rsi is readily available
+- * and doesn't have to be saved.
+- */
+- return res;
+-}
+-
+-/**
+- * find_first_zero_bit - find the first zero 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 zero bit, not the number of the byte
+- * containing a bit.
+- */
+-long find_first_zero_bit(const unsigned long * addr, unsigned long size)
+-{
+- return __find_first_zero_bit (addr, size);
+-}
+-
+-/**
+- * find_next_zero_bit - find the next zero bit in a memory region
+- * @addr: The address to base the search on
+- * @offset: The bitnumber to start searching at
+- * @size: The maximum size to search
+- */
+-long find_next_zero_bit (const unsigned long * addr, long size, long offset)
+-{
+- const unsigned long * p = addr + (offset >> 6);
+- unsigned long set = 0;
+- unsigned long res, bit = offset&63;
+-
+- if (bit) {
+- /*
+- * Look for zero in first word
+- */
+- asm("bsfq %1,%0\n\t"
+- "cmoveq %2,%0"
+- : "=r" (set)
+- : "r" (~(*p >> bit)), "r"(64L));
+- if (set < (64 - bit))
+- return set + offset;
+- set = 64 - bit;
+- p++;
+- }
+- /*
+- * No zero yet, search remaining full words for a zero
+- */
+- res = __find_first_zero_bit (p, size - 64 * (p - addr));
+-
+- return (offset + set + res);
+-}
+-
+-static inline long
+-__find_first_bit(const unsigned long * addr, unsigned long size)
+-{
+- long d0, d1;
+- long res;
+-
+- /*
+- * We must test the size in words, not in bits, because
+- * otherwise incoming sizes in the range -63..-1 will not run
+- * any scasq instructions, and then the flags used by the jz
+- * instruction will have whatever random value was in place
+- * before. Nobody should call us like that, but
+- * find_next_bit() does when offset and size are at the same
+- * word and it fails to find a one itself.
+- */
+- size += 63;
+- size >>= 6;
+- if (!size)
+- return 0;
+- asm volatile(
+- " repe; scasq\n"
+- " jz 1f\n"
+- " subq $8,%%rdi\n"
+- " bsfq (%%rdi),%%rax\n"
+- "1: subq %[addr],%%rdi\n"
+- " shlq $3,%%rdi\n"
+- " addq %%rdi,%%rax"
+- :"=a" (res), "=&c" (d0), "=&D" (d1)
+- :"0" (0ULL), "1" (size), "2" (addr),
+- [addr] "r" (addr) : "memory");
+- return res;
+-}
+-
+-/**
+- * 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.
+- */
+-long find_first_bit(const unsigned long * addr, unsigned long size)
+-{
+- return __find_first_bit(addr,size);
+-}
+-
+-/**
+- * find_next_bit - find the first set bit in a memory region
+- * @addr: The address to base the search on
+- * @offset: The bitnumber to start searching at
+- * @size: The maximum size to search
+- */
+-long find_next_bit(const unsigned long * addr, long size, long offset)
+-{
+- const unsigned long * p = addr + (offset >> 6);
+- unsigned long set = 0, bit = offset & 63, res;
+-
+- if (bit) {
+- /*
+- * Look for nonzero in the first 64 bits:
+- */
+- asm("bsfq %1,%0\n\t"
+- "cmoveq %2,%0\n\t"
+- : "=r" (set)
+- : "r" (*p >> bit), "r" (64L));
+- if (set < (64 - bit))
+- return set + offset;
+- set = 64 - bit;
+- p++;
+- }
+- /*
+- * No set bit yet, search remaining full words for a bit
+- */
+- res = __find_first_bit (p, size - 64 * (p - addr));
+- return (offset + set + res);
+-}
+-
+-#include <linux/module.h>
+-
+-EXPORT_SYMBOL(find_next_bit);
+-EXPORT_SYMBOL(find_first_bit);
+-EXPORT_SYMBOL(find_first_zero_bit);
+-EXPORT_SYMBOL(find_next_zero_bit);
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
@@ -262705,7 +329598,7 @@
* 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
+index 17a7904..2ad598c 100644
--- a/arch/x86/mach-voyager/voyager_cat.c
+++ b/arch/x86/mach-voyager/voyager_cat.c
@@ -4,8 +4,6 @@
@@ -262717,6 +329610,15 @@
* This file contains all the logic for manipulating the CAT bus
* in a level 5 machine.
*
+@@ -879,7 +877,7 @@ void __init voyager_cat_init(void)
+ request_resource(&iomem_resource, res);
+ }
+
+- qic_addr = (unsigned long)ioremap(qic_addr, 0x400);
++ qic_addr = (unsigned long)ioremap_cache(qic_addr, 0x400);
+
+ for (j = 0; j < 4; j++) {
+ __u8 cpu;
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
@@ -263475,8 +330377,17 @@
- (__START_KERNEL & PGDIR_MASK)));
#endif
}
+diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c
+index 9cf33d3..165c871 100644
+--- a/arch/x86/mm/highmem_32.c
++++ b/arch/x86/mm/highmem_32.c
+@@ -155,4 +155,3 @@ EXPORT_SYMBOL(kmap);
+ EXPORT_SYMBOL(kunmap);
+ EXPORT_SYMBOL(kmap_atomic);
+ EXPORT_SYMBOL(kunmap_atomic);
+-EXPORT_SYMBOL(kmap_atomic_to_page);
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
-index ee1091a..4a47618 100644
+index ee1091a..de236e4 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -1,5 +1,4 @@
@@ -263569,7 +330480,58 @@
#ifdef CONFIG_HIGHMEM
pte_t *kmap_pte;
pgprot_t kmap_prot;
-@@ -357,7 +384,7 @@ void __init native_pagetable_setup_start(pgd_t *base)
+@@ -260,47 +287,17 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base)
+ pkmap_page_table = pte;
+ }
+
+-static void __meminit free_new_highpage(struct page *page)
+-{
+- init_page_count(page);
+- __free_page(page);
+- totalhigh_pages++;
+-}
+-
+ void __init add_one_highpage_init(struct page *page, int pfn, int bad_ppro)
+ {
+ if (page_is_ram(pfn) && !(bad_ppro && page_kills_ppro(pfn))) {
+ ClearPageReserved(page);
+- free_new_highpage(page);
++ init_page_count(page);
++ __free_page(page);
++ totalhigh_pages++;
+ } else
+ SetPageReserved(page);
+ }
+
+-static int __meminit
+-add_one_highpage_hotplug(struct page *page, unsigned long pfn)
+-{
+- free_new_highpage(page);
+- totalram_pages++;
+-#ifdef CONFIG_FLATMEM
+- max_mapnr = max(pfn, max_mapnr);
+-#endif
+- num_physpages++;
+-
+- return 0;
+-}
+-
+-/*
+- * Not currently handling the NUMA case.
+- * Assuming single node and all memory that
+- * has been added dynamically that would be
+- * onlined here is in HIGHMEM.
+- */
+-void __meminit online_page(struct page *page)
+-{
+- ClearPageReserved(page);
+- add_one_highpage_hotplug(page, page_to_pfn(page));
+-}
+-
+ #ifndef CONFIG_NUMA
+ static void __init set_highmem_pages_init(int bad_ppro)
+ {
+@@ -357,7 +354,7 @@ void __init native_pagetable_setup_start(pgd_t *base)
pte_clear(NULL, va, pte);
}
@@ -263578,7 +330540,7 @@
}
void __init native_pagetable_setup_done(pgd_t *base)
-@@ -449,7 +476,7 @@ void zap_low_mappings(void)
+@@ -449,7 +446,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.
*/
@@ -263587,7 +330549,7 @@
#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)
+@@ -539,9 +536,9 @@ void __init paging_init(void)
/*
* Test if the WP bit works in supervisor mode. It isn't supported on 386's
@@ -263600,7 +330562,7 @@
*/
static void __init test_wp_bit(void)
{
-@@ -723,25 +750,17 @@ void mark_rodata_ro(void)
+@@ -723,25 +720,17 @@ void mark_rodata_ro(void)
unsigned long start = PFN_ALIGN(_text);
unsigned long size = PFN_ALIGN(_etext) - start;
@@ -263635,7 +330597,7 @@
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
+index a02a14f..32ba13b 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -47,13 +47,30 @@
@@ -263969,7 +330931,23 @@
}
#ifndef CONFIG_NUMA
-@@ -482,11 +638,13 @@ int arch_add_memory(int nid, u64 start, u64 size)
+@@ -464,15 +620,6 @@ void __init paging_init(void)
+ /*
+ * Memory hotplug specific functions
+ */
+-void online_page(struct page *page)
+-{
+- ClearPageReserved(page);
+- init_page_count(page);
+- __free_page(page);
+- totalram_pages++;
+- num_physpages++;
+-}
+-
+ #ifdef CONFIG_MEMORY_HOTPLUG
+ /*
+ * Memory is added always to NORMAL zone. This means you will never get
+@@ -482,11 +629,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;
@@ -263985,7 +330963,7 @@
ret = __add_pages(zone, start_pfn, nr_pages);
WARN_ON(1);
-@@ -505,6 +663,26 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
+@@ -505,6 +654,26 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
#endif /* CONFIG_MEMORY_HOTPLUG */
@@ -264012,7 +330990,7 @@
static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel,
kcore_modules, kcore_vsyscall;
-@@ -596,24 +774,7 @@ EXPORT_SYMBOL_GPL(rodata_test_data);
+@@ -596,24 +765,7 @@ EXPORT_SYMBOL_GPL(rodata_test_data);
void mark_rodata_ro(void)
{
@@ -264038,7 +331016,7 @@
printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
(end - start) >> 10);
-@@ -636,6 +797,7 @@ void mark_rodata_ro(void)
+@@ -636,6 +788,7 @@ void mark_rodata_ro(void)
set_memory_ro(start, (end-start) >> PAGE_SHIFT);
#endif
}
@@ -264046,7 +331024,16 @@
#endif
#ifdef CONFIG_BLK_DEV_INITRD
-@@ -657,7 +819,7 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
+@@ -648,7 +801,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
+ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
+ {
+ #ifdef CONFIG_NUMA
+- int nid = phys_to_nid(phys);
++ int nid, next_nid;
+ #endif
+ unsigned long pfn = phys >> PAGE_SHIFT;
+
+@@ -657,7 +810,7 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
* This can happen with kdump kernels when accessing
* firmware tables:
*/
@@ -264055,8 +331042,72 @@
return;
printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %u\n",
+@@ -667,10 +820,16 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
+
+ /* Should check here against the e820 map to avoid double free */
+ #ifdef CONFIG_NUMA
+- reserve_bootmem_node(NODE_DATA(nid), phys, len, BOOTMEM_DEFAULT);
++ nid = phys_to_nid(phys);
++ next_nid = phys_to_nid(phys + len - 1);
++ if (nid == next_nid)
++ reserve_bootmem_node(NODE_DATA(nid), phys, len, BOOTMEM_DEFAULT);
++ else
++ reserve_bootmem(phys, len, BOOTMEM_DEFAULT);
+ #else
+ reserve_bootmem(phys, len, BOOTMEM_DEFAULT);
+ #endif
++
+ if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
+ dma_reserve += len / PAGE_SIZE;
+ set_dma_reserve(dma_reserve);
+@@ -764,6 +923,10 @@ const char *arch_vma_name(struct vm_area_struct *vma)
+ /*
+ * Initialise the sparsemem vmemmap using huge-pages at the PMD level.
+ */
++static long __meminitdata addr_start, addr_end;
++static void __meminitdata *p_start, *p_end;
++static int __meminitdata node_start;
++
+ int __meminit
+ vmemmap_populate(struct page *start_page, unsigned long size, int node)
+ {
+@@ -798,12 +961,32 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node)
+ PAGE_KERNEL_LARGE);
+ set_pmd(pmd, __pmd(pte_val(entry)));
+
+- printk(KERN_DEBUG " [%lx-%lx] PMD ->%p on node %d\n",
+- addr, addr + PMD_SIZE - 1, p, node);
++ /* check to see if we have contiguous blocks */
++ if (p_end != p || node_start != node) {
++ if (p_start)
++ printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n",
++ addr_start, addr_end-1, p_start, p_end-1, node_start);
++ addr_start = addr;
++ node_start = node;
++ p_start = p;
++ }
++ addr_end = addr + PMD_SIZE;
++ p_end = p + PMD_SIZE;
+ } else {
+ vmemmap_verify((pte_t *)pmd, node, addr, next);
+ }
+ }
+ return 0;
+ }
++
++void __meminit vmemmap_populate_print_last(void)
++{
++ if (p_start) {
++ printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n",
++ addr_start, addr_end-1, p_start, p_end-1, node_start);
++ p_start = NULL;
++ p_end = NULL;
++ node_start = 0;
++ }
++}
+ #endif
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
-index 794895c..d176b23 100644
+index 794895c..71bb315 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -19,11 +19,7 @@
@@ -264116,23 +331167,25 @@
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_WC:
++ err = _set_memory_wc(vaddr, nrpages);
++ break;
+ 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,
+@@ -106,18 +117,28 @@ static int ioremap_change_attr(unsigned long vaddr, unsigned long size,
+ * have to convert them into an offset in a page-aligned mapping, but the
* caller shouldn't need to know that small detail.
*/
- static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
+-static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
- enum ioremap_mode mode)
-+ unsigned long prot_val)
++static void __iomem *__ioremap_caller(resource_size_t phys_addr,
++ unsigned long size, unsigned long prot_val, void *caller)
{
- unsigned long pfn, offset, last_addr, vaddr;
+ unsigned long pfn, offset, vaddr;
@@ -264157,7 +331210,7 @@
/*
* 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,
+@@ -127,48 +148,87 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
/*
* Don't allow anybody to remap normal RAM that we're using..
*/
@@ -264165,35 +331218,27 @@
- (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;
++ (pfn << PAGE_SHIFT) < (last_addr & PAGE_MASK);
++ pfn++) {
++
+ int is_ram = page_is_ram(pfn);
+
+ if (is_ram && pfn_valid(pfn) && !PageReserved(pfn_to_page(pfn)))
-+ return NULL;
+ 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;
-
+- switch (mode) {
+- case IOR_MODE_UNCACHED:
+- default:
++ /*
++ * Mappings have to be page-aligned
++ */
++ offset = phys_addr & ~PAGE_MASK;
++ 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) {
@@ -264202,14 +331247,16 @@
+ }
+
+ if (prot_val != new_prot_val) {
-+ /*
+ /*
+- * FIXME: we will use UC MINUS for now, as video fb drivers
+- * depend on it. Upcoming ioremap_wc() will fix this behavior.
+ * 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 uc-, return cannot be write-back
++ * - request is uc-, return cannot be write-combine
+ * - request is write-combine, return cannot be write-back
-+ */
-+ if ((prot_val == _PAGE_CACHE_UC &&
+ */
++ if ((prot_val == _PAGE_CACHE_UC_MINUS &&
+ (new_prot_val == _PAGE_CACHE_WB ||
+ new_prot_val == _PAGE_CACHE_WC)) ||
+ (prot_val == _PAGE_CACHE_WC &&
@@ -264230,18 +331277,32 @@
+ default:
+ prot = PAGE_KERNEL_NOCACHE;
+ break;
++ case _PAGE_CACHE_UC_MINUS:
+ prot = PAGE_KERNEL_UC_MINUS;
+ break;
+- case IOR_MODE_CACHED:
+ case _PAGE_CACHE_WC:
+ prot = PAGE_KERNEL_WC;
+ break;
+ case _PAGE_CACHE_WB:
-+ prot = PAGE_KERNEL;
-+ break;
-+ }
-+
+ prot = PAGE_KERNEL;
+ break;
+ }
+
/*
+- * Mappings have to be page-aligned
+- */
+- offset = phys_addr & ~PAGE_MASK;
+- phys_addr &= PAGE_MASK;
+- size = PAGE_ALIGN(last_addr+1) - phys_addr;
+-
+- /*
* Ok, go for it..
*/
-@@ -164,11 +218,13 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
+- area = get_vm_area(size, VM_IOREMAP);
++ area = get_vm_area_caller(size, VM_IOREMAP, caller);
+ if (!area)
+ return NULL;
area->phys_addr = phys_addr;
vaddr = (unsigned long) area->addr;
if (ioremap_page_range(vaddr, vaddr + size, phys_addr, prot)) {
@@ -264256,12 +331317,22 @@
vunmap(area->addr);
return NULL;
}
-@@ -199,13 +255,32 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
+@@ -199,13 +259,44 @@ 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);
++ /*
++ * Ideally, this should be:
++ * pat_wc_enabled ? _PAGE_CACHE_UC : _PAGE_CACHE_UC_MINUS;
++ *
++ * Till we fix all X drivers to use ioremap_wc(), we will use
++ * UC MINUS.
++ */
++ unsigned long val = _PAGE_CACHE_UC_MINUS;
++
++ return __ioremap_caller(phys_addr, size, val,
++ __builtin_return_address(0));
}
EXPORT_SYMBOL(ioremap_nocache);
@@ -264278,7 +331349,8 @@
+void __iomem *ioremap_wc(unsigned long phys_addr, unsigned long size)
+{
+ if (pat_wc_enabled)
-+ return __ioremap(phys_addr, size, _PAGE_CACHE_WC);
++ return __ioremap_caller(phys_addr, size, _PAGE_CACHE_WC,
++ __builtin_return_address(0));
+ else
+ return ioremap_nocache(phys_addr, size);
+}
@@ -264287,11 +331359,12 @@
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);
++ return __ioremap_caller(phys_addr, size, _PAGE_CACHE_WB,
++ __builtin_return_address(0));
}
EXPORT_SYMBOL(ioremap_cache);
-@@ -252,6 +327,8 @@ void iounmap(volatile void __iomem *addr)
+@@ -252,6 +343,8 @@ void iounmap(volatile void __iomem *addr)
return;
}
@@ -264300,7 +331373,7 @@
/* 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)
+@@ -259,6 +352,35 @@ void iounmap(volatile void __iomem *addr)
}
EXPORT_SYMBOL(iounmap);
@@ -264336,7 +331409,7 @@
#ifdef CONFIG_X86_32
int __initdata early_ioremap_debug;
-@@ -272,8 +378,8 @@ static int __init early_ioremap_debug_setup(char *str)
+@@ -272,8 +394,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;
@@ -264347,7 +331420,7 @@
static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
{
-@@ -330,7 +436,7 @@ void __init early_ioremap_clear(void)
+@@ -330,7 +452,7 @@ void __init early_ioremap_clear(void)
pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
pmd_clear(pmd);
@@ -264357,10 +331430,65 @@
}
diff --git a/arch/x86/mm/k8topology_64.c b/arch/x86/mm/k8topology_64.c
-index 7a2ebce..86808e6 100644
+index 7a2ebce..1f476e4 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)
+@@ -13,12 +13,15 @@
+ #include <linux/nodemask.h>
+ #include <asm/io.h>
+ #include <linux/pci_ids.h>
++#include <linux/acpi.h>
+ #include <asm/types.h>
+ #include <asm/mmzone.h>
+ #include <asm/proto.h>
+ #include <asm/e820.h>
+ #include <asm/pci-direct.h>
+ #include <asm/numa.h>
++#include <asm/mpspec.h>
++#include <asm/apic.h>
+
+ static __init int find_northbridge(void)
+ {
+@@ -44,6 +47,30 @@ static __init int find_northbridge(void)
+ return -1;
+ }
+
++static __init void early_get_boot_cpu_id(void)
++{
++ /*
++ * need to get boot_cpu_id so can use that to create apicid_to_node
++ * in k8_scan_nodes()
++ */
++ /*
++ * Find possible boot-time SMP configuration:
++ */
++ early_find_smp_config();
++#ifdef CONFIG_ACPI
++ /*
++ * Read APIC information from ACPI tables.
++ */
++ early_acpi_boot_init();
++#endif
++ /*
++ * get boot-time SMP configuration:
++ */
++ if (smp_found_config)
++ early_get_smp_config();
++ early_init_lapic_mapping();
++}
++
+ int __init k8_scan_nodes(unsigned long start, unsigned long end)
+ {
+ unsigned long prevbase;
+@@ -56,6 +83,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
+ unsigned cores;
+ unsigned bits;
+ int j;
++ unsigned apicid_base;
+
+ if (!early_pci_allowed())
+ return -1;
+@@ -164,7 +192,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
if (!found)
return -1;
@@ -264369,8 +331497,29 @@
if (memnode_shift < 0) {
printk(KERN_ERR "No NUMA node hash function found. Contact maintainer\n");
return -1;
+@@ -174,11 +202,19 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
+ /* use the coreid bits from early_identify_cpu */
+ bits = boot_cpu_data.x86_coreid_bits;
+ cores = (1<<bits);
++ apicid_base = 0;
++ /* need to get boot_cpu_id early for system with apicid lifting */
++ early_get_boot_cpu_id();
++ if (boot_cpu_physical_apicid > 0) {
++ printk(KERN_INFO "BSP APIC ID: %02x\n",
++ boot_cpu_physical_apicid);
++ apicid_base = boot_cpu_physical_apicid;
++ }
+
+ for (i = 0; i < 8; i++) {
+ if (nodes[i].start != nodes[i].end) {
+ nodeid = nodeids[i];
+- for (j = 0; j < cores; j++)
++ for (j = apicid_base; j < cores + apicid_base; j++)
+ apicid_to_node[(nodeid << bits) + j] = i;
+ setup_node_bootmem(i, nodes[i].start, nodes[i].end);
+ }
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
-index 16b82ad..9a68922 100644
+index 16b82ad..c5066d5 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];
@@ -264432,7 +331581,71 @@
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,
+@@ -188,6 +196,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start,
+ unsigned long bootmap_start, nodedata_phys;
+ void *bootmap;
+ const int pgdat_size = round_up(sizeof(pg_data_t), PAGE_SIZE);
++ int nid;
+
+ start = round_up(start, ZONE_ALIGN);
+
+@@ -210,9 +219,19 @@ void __init setup_node_bootmem(int nodeid, unsigned long start,
+ NODE_DATA(nodeid)->node_start_pfn = start_pfn;
+ NODE_DATA(nodeid)->node_spanned_pages = end_pfn - start_pfn;
+
+- /* Find a place for the bootmem map */
++ /*
++ * Find a place for the bootmem map
++ * nodedata_phys could be on other nodes by alloc_bootmem,
++ * so need to sure bootmap_start not to be small, otherwise
++ * early_node_mem will get that with find_e820_area instead
++ * of alloc_bootmem, that could clash with reserved range
++ */
+ bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
+- bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE);
++ nid = phys_to_nid(nodedata_phys);
++ if (nid == nodeid)
++ bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE);
++ else
++ bootmap_start = round_up(start, PAGE_SIZE);
+ /*
+ * SMP_CAHCE_BYTES could be enough, but init_bootmem_node like
+ * to use that to align to PAGE_SIZE
+@@ -237,10 +256,29 @@ void __init setup_node_bootmem(int nodeid, unsigned long start,
+
+ free_bootmem_with_active_regions(nodeid, end);
+
+- reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size,
+- BOOTMEM_DEFAULT);
+- reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start,
+- bootmap_pages<<PAGE_SHIFT, BOOTMEM_DEFAULT);
++ /*
++ * convert early reserve to bootmem reserve earlier
++ * otherwise early_node_mem could use early reserved mem
++ * on previous node
++ */
++ early_res_to_bootmem(start, end);
++
++ /*
++ * in some case early_node_mem could use alloc_bootmem
++ * to get range on other node, don't reserve that again
++ */
++ if (nid != nodeid)
++ printk(KERN_INFO " NODE_DATA(%d) on node %d\n", nodeid, nid);
++ else
++ reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys,
++ pgdat_size, BOOTMEM_DEFAULT);
++ nid = phys_to_nid(bootmap_start);
++ if (nid != nodeid)
++ printk(KERN_INFO " bootmap(%d) on node %d\n", nodeid, nid);
++ else
++ reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start,
++ bootmap_pages<<PAGE_SHIFT, BOOTMEM_DEFAULT);
++
+ #ifdef CONFIG_ACPI_NUMA
+ srat_reserve_add_area(nodeid);
+ #endif
+@@ -378,9 +416,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.
*/
@@ -264444,7 +331657,7 @@
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:
+@@ -460,7 +499,7 @@ done:
}
}
out:
@@ -264453,7 +331666,7 @@
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)
+@@ -548,8 +587,6 @@ void __cpuinit numa_set_node(int cpu, int node)
{
int *cpu_to_node_map = x86_cpu_to_node_map_early_ptr;
@@ -264463,7 +331676,7 @@
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
+index 7b79f6b..60bcb5b 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -9,6 +9,8 @@
@@ -264548,7 +331761,7 @@
/* No alias checking for _NX bit modifications */
checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX;
-@@ -759,26 +766,61 @@ out:
+@@ -759,26 +766,67 @@ out:
static inline int change_page_attr_set(unsigned long addr, int numpages,
pgprot_t mask)
{
@@ -264566,15 +331779,21 @@
-int set_memory_uc(unsigned long addr, int numpages)
+int _set_memory_uc(unsigned long addr, int numpages)
{
++ /*
++ * for now UC MINUS. see comments in ioremap_nocache()
++ */
return change_page_attr_set(addr, numpages,
- __pgprot(_PAGE_PCD));
-+ __pgprot(_PAGE_CACHE_UC));
++ __pgprot(_PAGE_CACHE_UC_MINUS));
+}
+
+int set_memory_uc(unsigned long addr, int numpages)
+{
++ /*
++ * for now UC MINUS. see comments in ioremap_nocache()
++ */
+ if (reserve_memtype(addr, addr + numpages * PAGE_SIZE,
-+ _PAGE_CACHE_UC, NULL))
++ _PAGE_CACHE_UC_MINUS, NULL))
+ return -EINVAL;
+
+ return _set_memory_uc(addr, numpages);
@@ -264616,7 +331835,7 @@
}
EXPORT_SYMBOL(set_memory_wb);
-@@ -809,6 +851,12 @@ int set_memory_np(unsigned long addr, int numpages)
+@@ -809,6 +857,12 @@ int set_memory_np(unsigned long addr, int numpages)
return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_PRESENT));
}
@@ -264629,7 +331848,7 @@
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)
+@@ -918,6 +972,45 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
cpa_fill_pool(NULL);
}
@@ -264677,10 +331896,10 @@
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
+index 0000000..277446c
--- /dev/null
+++ b/arch/x86/mm/pat.c
-@@ -0,0 +1,568 @@
+@@ -0,0 +1,596 @@
+/*
+ * Handle caching attributes in page tables (PAT)
+ *
@@ -264699,6 +331918,7 @@
+#include <asm/msr.h>
+#include <asm/tlbflush.h>
+#include <asm/processor.h>
++#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/pat.h>
+#include <asm/e820.h>
@@ -265069,8 +332289,8 @@
+ break;
+ }
+
-+ printk(KERN_INFO "Overlap at 0x%Lx-0x%Lx\n",
-+ saved_ptr->start, saved_ptr->end);
++ pr_debug(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;
@@ -265160,14 +332380,43 @@
+ return vma_prot;
+}
+
++#ifdef CONFIG_NONPROMISC_DEVMEM
++/* This check is done in drivers/char/mem.c in case of NONPROMISC_DEVMEM*/
++static inline int range_is_allowed(unsigned long pfn, unsigned long size)
++{
++ return 1;
++}
++#else
++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;
++}
++#endif /* CONFIG_NONPROMISC_DEVMEM */
++
+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 (!range_is_allowed(pfn, size))
++ return 0;
++
+ if (file->f_flags & O_SYNC) {
+ flags = _PAGE_CACHE_UC;
+ }
@@ -265201,14 +332450,12 @@
+ if (flags != _PAGE_CACHE_UC_MINUS) {
+ retval = reserve_memtype(offset, offset + size, flags, NULL);
+ } else {
-+ retval = reserve_memtype(offset, offset + size, -1, &ret_flags);
++ retval = reserve_memtype(offset, offset + size, -1, &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);
@@ -266386,8 +333633,40 @@
release_evntsel_nmi(MSR_P6_EVNTSEL0 + i);
}
}
+diff --git a/arch/x86/pci/Makefile_32 b/arch/x86/pci/Makefile_32
+index cdd6828..7fa5198 100644
+--- a/arch/x86/pci/Makefile_32
++++ b/arch/x86/pci/Makefile_32
+@@ -3,12 +3,14 @@ obj-y := i386.o init.o
+ obj-$(CONFIG_PCI_BIOS) += pcbios.o
+ obj-$(CONFIG_PCI_MMCONFIG) += mmconfig_32.o direct.o mmconfig-shared.o
+ obj-$(CONFIG_PCI_DIRECT) += direct.o
++obj-$(CONFIG_PCI_OLPC) += olpc.o
+
+ pci-y := fixup.o
+ pci-$(CONFIG_ACPI) += acpi.o
+ pci-y += legacy.o irq.o
+
+-pci-$(CONFIG_X86_VISWS) := visws.o fixup.o
+-pci-$(CONFIG_X86_NUMAQ) := numa.o irq.o
++pci-$(CONFIG_X86_VISWS) += visws.o fixup.o
++pci-$(CONFIG_X86_NUMAQ) += numa.o irq.o
++pci-$(CONFIG_NUMA) += mp_bus_to_node.o
+
+ obj-y += $(pci-y) common.o early.o
+diff --git a/arch/x86/pci/Makefile_64 b/arch/x86/pci/Makefile_64
+index 7d8c467..8fbd198 100644
+--- a/arch/x86/pci/Makefile_64
++++ b/arch/x86/pci/Makefile_64
+@@ -13,5 +13,5 @@ obj-y += legacy.o irq.o common.o early.o
+ # mmconfig has a 64bit special
+ obj-$(CONFIG_PCI_MMCONFIG) += mmconfig_64.o direct.o mmconfig-shared.o
+
+-obj-$(CONFIG_NUMA) += k8-bus_64.o
++obj-y += k8-bus_64.o
+
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
-index 378136f..2664cb3 100644
+index 378136f..1a9c0c6 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)
@@ -266412,16 +333691,72 @@
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
+@@ -191,7 +191,10 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
+ {
+ struct pci_bus *bus;
+ struct pci_sysdata *sd;
++ int node;
++#ifdef CONFIG_ACPI_NUMA
+ int pxm;
++#endif
+
+ dmi_check_system(acpi_pciprobe_dmi_table);
+
+@@ -201,6 +204,17 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
+ return NULL;
+ }
+
++ node = -1;
++#ifdef CONFIG_ACPI_NUMA
++ pxm = acpi_get_pxm(device->handle);
++ if (pxm >= 0)
++ node = pxm_to_node(pxm);
++ if (node != -1)
++ set_mp_bus_to_node(busnum, node);
++ else
++ node = get_mp_bus_to_node(busnum);
++#endif
++
+ /* Allocate per-root-bus (not per bus) arch-specific data.
+ * TODO: leak; this memory is never freed.
+ * It's arguable whether it's worth the trouble to care.
+@@ -212,13 +226,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
+ }
+
+ sd->domain = domain;
+- sd->node = -1;
+-
+- pxm = acpi_get_pxm(device->handle);
+-#ifdef CONFIG_ACPI_NUMA
+- if (pxm >= 0)
+- sd->node = pxm_to_node(pxm);
+-#endif
++ sd->node = node;
+ /*
+ * Maybe the desired pci bus has been already scanned. In such case
+ * it is unnecessary to scan the pci bus with the given domain,busnum.
+@@ -238,17 +246,16 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
+ kfree(sd);
+
+ #ifdef CONFIG_ACPI_NUMA
+- if (bus != NULL) {
++ if (bus) {
+ if (pxm >= 0) {
+- printk("bus %d -> pxm %d -> node %d\n",
++ printk(KERN_DEBUG "bus %02x -> pxm %d -> node %d\n",
+ busnum, pxm, pxm_to_node(pxm));
+ }
+ }
#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)
+
+@@ -278,8 +285,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);
@@ -266432,7 +333767,7 @@
#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
+index 7b6e3bb..2a4d751 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -77,59 +77,6 @@ int pcibios_scanned;
@@ -266503,7 +333838,23 @@
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)
+@@ -396,9 +342,14 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum)
+ return NULL;
+ }
+
++ sd->node = get_mp_bus_to_node(busnum);
++
+ printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
++ bus = pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd);
++ if (!bus)
++ kfree(sd);
+
+- return pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd);
++ return bus;
+ }
+
+ extern u8 pci_cache_line_size;
+@@ -427,10 +378,6 @@ static int __init pcibios_init(void)
if (pci_bf_sort >= pci_force_bf)
pci_sort_breadthfirst();
@@ -266514,7 +333865,7 @@
return 0;
}
-@@ -455,9 +397,6 @@ char * __devinit pcibios_setup(char *str)
+@@ -455,9 +402,6 @@ char * __devinit pcibios_setup(char *str)
} else if (!strcmp(str, "nobios")) {
pci_probe &= ~PCI_PROBE_BIOS;
return NULL;
@@ -266524,227 +333875,1428 @@
} 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)
+@@ -481,6 +425,10 @@ char * __devinit pcibios_setup(char *str)
+ pci_probe &= ~PCI_PROBE_MMCONF;
+ return NULL;
+ }
++ else if (!strcmp(str, "check_enable_amd_mmconf")) {
++ pci_probe |= PCI_CHECK_ENABLE_AMD_MMCONF;
++ return NULL;
++ }
+ #endif
+ else if (!strcmp(str, "noacpi")) {
+ acpi_noirq_set();
+@@ -527,7 +475,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)
+@@ -541,7 +489,7 @@ void pcibios_disable_device (struct pci_dev *dev)
+ pcibios_disable_irq(dev);
+ }
+
+-struct pci_bus *__devinit pci_scan_bus_with_sysdata(int busno)
++struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node)
+ {
+ struct pci_bus *bus = NULL;
+ struct pci_sysdata *sd;
+@@ -556,10 +504,15 @@ struct pci_bus *__devinit pci_scan_bus_with_sysdata(int busno)
+ printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busno);
+ return NULL;
+ }
+- sd->node = -1;
+- bus = pci_scan_bus(busno, &pci_root_ops, sd);
++ sd->node = node;
++ bus = pci_scan_bus(busno, ops, sd);
+ if (!bus)
+ kfree(sd);
+
+ return bus;
+ }
++
++struct pci_bus *pci_scan_bus_with_sysdata(int busno)
++{
++ return pci_scan_bus_on_node(busno, &pci_root_ops, -1);
++}
+diff --git a/arch/x86/pci/direct.c b/arch/x86/pci/direct.c
+index 42f3e4c..21d1e0e 100644
+--- a/arch/x86/pci/direct.c
++++ b/arch/x86/pci/direct.c
+@@ -258,7 +258,8 @@ void __init pci_direct_init(int type)
+ {
+ if (type == 0)
+ return;
+- printk(KERN_INFO "PCI: Using configuration type %d\n", type);
++ printk(KERN_INFO "PCI: Using configuration type %d for base access\n",
++ type);
+ if (type == 1)
+ raw_pci_ops = &pci_direct_conf1;
+ else
+@@ -275,8 +276,10 @@ int __init pci_direct_probe(void)
+ if (!region)
+ goto type2;
+
+- if (pci_check_type1())
++ if (pci_check_type1()) {
++ raw_pci_ops = &pci_direct_conf1;
+ return 1;
++ }
+ release_resource(region);
+
+ type2:
+@@ -290,7 +293,6 @@ int __init pci_direct_probe(void)
+ goto fail2;
+
+ if (pci_check_type2()) {
+- printk(KERN_INFO "PCI: Using configuration type 2\n");
+ raw_pci_ops = &pci_direct_conf2;
+ return 2;
+ }
+diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
+index a5ef5f5..b60b2ab 100644
+--- a/arch/x86/pci/fixup.c
++++ b/arch/x86/pci/fixup.c
+@@ -493,3 +493,20 @@ static void __devinit pci_siemens_interrupt_controller(struct pci_dev *dev)
+ }
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SIEMENS, 0x0015,
+ pci_siemens_interrupt_controller);
++
++/*
++ * Regular PCI devices have 256 bytes, but AMD Family 10h Opteron ext config
++ * have 4096 bytes. Even if the device is capable, that doesn't mean we can
++ * access it. Maybe we don't have a way to generate extended config space
++ * accesses. So check it
++ */
++static void fam10h_pci_cfg_space_size(struct pci_dev *dev)
++{
++ dev->cfg_size = pci_cfg_space_size_ext(dev, 0);
++}
++
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1200, fam10h_pci_cfg_space_size);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1201, fam10h_pci_cfg_space_size);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1202, fam10h_pci_cfg_space_size);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1203, fam10h_pci_cfg_space_size);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1204, fam10h_pci_cfg_space_size);
+diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
+index 103b9df..8af0f0b 100644
+--- a/arch/x86/pci/i386.c
++++ b/arch/x86/pci/i386.c
+@@ -30,6 +30,9 @@
+ #include <linux/init.h>
+ #include <linux/ioport.h>
+ #include <linux/errno.h>
++#include <linux/bootmem.h>
++
++#include <asm/pat.h>
+
+ #include "pci.h"
+
+@@ -238,44 +241,6 @@ void __init pcibios_resource_survey(void)
+ */
+ fs_initcall(pcibios_assign_resources);
+
+-int pcibios_enable_resources(struct pci_dev *dev, int mask)
+-{
+- u16 cmd, old_cmd;
+- int idx;
+- struct resource *r;
+-
+- pci_read_config_word(dev, PCI_COMMAND, &cmd);
+- old_cmd = cmd;
+- for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+- /* Only set up the requested stuff */
+- if (!(mask & (1 << idx)))
+- continue;
+-
+- r = &dev->resource[idx];
+- if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+- continue;
+- if ((idx == PCI_ROM_RESOURCE) &&
+- (!(r->flags & IORESOURCE_ROM_ENABLE)))
+- continue;
+- if (!r->start && r->end) {
+- printk(KERN_ERR "PCI: Device %s not available "
+- "because of resource %d collisions\n",
+- pci_name(dev), idx);
+- return -EINVAL;
+- }
+- if (r->flags & IORESOURCE_IO)
+- cmd |= PCI_COMMAND_IO;
+- if (r->flags & IORESOURCE_MEM)
+- cmd |= PCI_COMMAND_MEMORY;
+- }
+- if (cmd != old_cmd) {
+- printk("PCI: Enabling device %s (%04x -> %04x)\n",
+- pci_name(dev), old_cmd, cmd);
+- pci_write_config_word(dev, PCI_COMMAND, cmd);
+- }
+- return 0;
+-}
+-
+ /*
+ * If we set up a device for bus mastering, we need to check the latency
+ * timer as certain crappy BIOSes forget to set it properly.
+@@ -297,10 +262,35 @@ void pcibios_set_master(struct pci_dev *dev)
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
+ }
+
++static void pci_unmap_page_range(struct vm_area_struct *vma)
++{
++ u64 addr = (u64)vma->vm_pgoff << PAGE_SHIFT;
++ free_memtype(addr, addr + vma->vm_end - vma->vm_start);
++}
++
++static void pci_track_mmap_page_range(struct vm_area_struct *vma)
++{
++ u64 addr = (u64)vma->vm_pgoff << PAGE_SHIFT;
++ unsigned long flags = pgprot_val(vma->vm_page_prot)
++ & _PAGE_CACHE_MASK;
++
++ reserve_memtype(addr, addr + vma->vm_end - vma->vm_start, flags, NULL);
++}
++
++static struct vm_operations_struct pci_mmap_ops = {
++ .open = pci_track_mmap_page_range,
++ .close = pci_unmap_page_range,
++};
++
+ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine)
+ {
+ unsigned long prot;
++ u64 addr = vma->vm_pgoff << PAGE_SHIFT;
++ unsigned long len = vma->vm_end - vma->vm_start;
++ unsigned long flags;
++ unsigned long new_flags;
++ int retval;
+
+ /* I/O space cannot be accessed via normal processor loads and
+ * stores on this platform.
+@@ -308,21 +298,56 @@ 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 (pat_wc_enabled)
++ /*
++ * ioremap() and ioremap_nocache() defaults to UC MINUS for now.
++ * To avoid attribute conflicts, request UC MINUS here
++ * aswell.
++ */
++ prot |= _PAGE_CACHE_UC_MINUS;
++ 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_MINUS &&
++ (new_flags == _PAGE_CACHE_WB)) ||
++ (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/init.c b/arch/x86/pci/init.c
+index 3de9f9b..dd30c60 100644
+--- a/arch/x86/pci/init.c
++++ b/arch/x86/pci/init.c
+@@ -6,16 +6,17 @@
+ in the right sequence from here. */
+ static __init int pci_access_init(void)
+ {
+- int type __maybe_unused = 0;
+-
+ #ifdef CONFIG_PCI_DIRECT
++ int type = 0;
++
+ type = pci_direct_probe();
+ #endif
+-#ifdef CONFIG_PCI_MMCONFIG
+- pci_mmcfg_init(type);
++
++ pci_mmcfg_early_init();
++
++#ifdef CONFIG_PCI_OLPC
++ pci_olpc_init();
+ #endif
+- if (raw_pci_ops)
+- return 0;
+ #ifdef CONFIG_PCI_BIOS
+ pci_pcbios_init();
+ #endif
+@@ -28,7 +29,7 @@ static __init int pci_access_init(void)
+ #ifdef CONFIG_PCI_DIRECT
+ pci_direct_init(type);
+ #endif
+- if (!raw_pci_ops)
++ if (!raw_pci_ops && !raw_pci_ext_ops)
+ printk(KERN_ERR
+ "PCI: Fatal: No config space access function found\n");
+
+diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
+index a871586..0908fca 100644
+--- a/arch/x86/pci/irq.c
++++ b/arch/x86/pci/irq.c
+@@ -136,9 +136,11 @@ static void __init pirq_peer_trick(void)
+ busmap[e->bus] = 1;
+ }
+ for(i = 1; i < 256; i++) {
++ int node;
+ if (!busmap[i] || pci_find_bus(0, i))
+ continue;
+- if (pci_scan_bus_with_sysdata(i))
++ node = get_mp_bus_to_node(i);
++ if (pci_scan_bus_on_node(i, &pci_root_ops, node))
+ printk(KERN_INFO "PCI: Discovered primary peer "
+ "bus %02x [IRQ]\n", i);
+ }
+@@ -200,7 +202,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 +211,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 +262,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 +270,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 +284,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 +292,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/k8-bus_64.c b/arch/x86/pci/k8-bus_64.c
+index 9cc813e..ab6d4b1 100644
+--- a/arch/x86/pci/k8-bus_64.c
++++ b/arch/x86/pci/k8-bus_64.c
+@@ -1,83 +1,536 @@
+ #include <linux/init.h>
+ #include <linux/pci.h>
++#include <asm/pci-direct.h>
+ #include <asm/mpspec.h>
+ #include <linux/cpumask.h>
++#include <linux/topology.h>
+
+ /*
+ * This discovers the pcibus <-> node mapping on AMD K8.
+- *
+- * RED-PEN need to call this again on PCI hotplug
+- * RED-PEN empty cpus get reported wrong
++ * also get peer root bus resource for io,mmio
+ */
+
+-#define NODE_ID_REGISTER 0x60
+-#define NODE_ID(dword) (dword & 0x07)
+-#define LDT_BUS_NUMBER_REGISTER_0 0x94
+-#define LDT_BUS_NUMBER_REGISTER_1 0xB4
+-#define LDT_BUS_NUMBER_REGISTER_2 0xD4
+-#define NR_LDT_BUS_NUMBER_REGISTERS 3
+-#define SECONDARY_LDT_BUS_NUMBER(dword) ((dword >> 8) & 0xFF)
+-#define SUBORDINATE_LDT_BUS_NUMBER(dword) ((dword >> 16) & 0xFF)
+-#define PCI_DEVICE_ID_K8HTCONFIG 0x1100
++
++/*
++ * sub bus (transparent) will use entres from 3 to store extra from root,
++ * so need to make sure have enought slot there, increase PCI_BUS_NUM_RESOURCES?
++ */
++#define RES_NUM 16
++struct pci_root_info {
++ char name[12];
++ unsigned int res_num;
++ struct resource res[RES_NUM];
++ int bus_min;
++ int bus_max;
++ int node;
++ int link;
++};
++
++/* 4 at this time, it may become to 32 */
++#define PCI_ROOT_NR 4
++static int pci_root_num;
++static struct pci_root_info pci_root_info[PCI_ROOT_NR];
++
++#ifdef CONFIG_NUMA
++
++#define BUS_NR 256
++
++static int mp_bus_to_node[BUS_NR];
++
++void set_mp_bus_to_node(int busnum, int node)
++{
++ if (busnum >= 0 && busnum < BUS_NR)
++ mp_bus_to_node[busnum] = node;
++}
++
++int get_mp_bus_to_node(int busnum)
++{
++ int node = -1;
++
++ if (busnum < 0 || busnum > (BUS_NR - 1))
++ return node;
++
++ node = mp_bus_to_node[busnum];
++
++ /*
++ * let numa_node_id to decide it later in dma_alloc_pages
++ * if there is no ram on that node
++ */
++ if (node != -1 && !node_online(node))
++ node = -1;
++
++ return node;
++}
++#endif
++
++void set_pci_bus_resources_arch_default(struct pci_bus *b)
++{
++ int i;
++ int j;
++ struct pci_root_info *info;
++
++ /* if only one root bus, don't need to anything */
++ if (pci_root_num < 2)
++ return;
++
++ for (i = 0; i < pci_root_num; i++) {
++ if (pci_root_info[i].bus_min == b->number)
++ break;
++ }
++
++ if (i == pci_root_num)
++ return;
++
++ info = &pci_root_info[i];
++ for (j = 0; j < info->res_num; j++) {
++ struct resource *res;
++ struct resource *root;
++
++ res = &info->res[j];
++ b->resource[j] = res;
++ if (res->flags & IORESOURCE_IO)
++ root = &ioport_resource;
++ else
++ root = &iomem_resource;
++ insert_resource(root, res);
++ }
++}
++
++#define RANGE_NUM 16
++
++struct res_range {
++ size_t start;
++ size_t end;
++};
++
++static void __init update_range(struct res_range *range, size_t start,
++ size_t end)
++{
++ int i;
++ int j;
++
++ for (j = 0; j < RANGE_NUM; j++) {
++ if (!range[j].end)
++ continue;
++
++ if (start <= range[j].start && end >= range[j].end) {
++ range[j].start = 0;
++ range[j].end = 0;
++ continue;
++ }
++
++ if (start <= range[j].start && end < range[j].end && range[j].start < end + 1) {
++ range[j].start = end + 1;
++ continue;
++ }
++
++
++ if (start > range[j].start && end >= range[j].end && range[j].end > start - 1) {
++ range[j].end = start - 1;
++ continue;
++ }
++
++ if (start > range[j].start && end < range[j].end) {
++ /* find the new spare */
++ for (i = 0; i < RANGE_NUM; i++) {
++ if (range[i].end == 0)
++ break;
++ }
++ if (i < RANGE_NUM) {
++ range[i].end = range[j].end;
++ range[i].start = end + 1;
++ } else {
++ printk(KERN_ERR "run of slot in ranges\n");
++ }
++ range[j].end = start - 1;
++ continue;
++ }
++ }
++}
++
++static void __init update_res(struct pci_root_info *info, size_t start,
++ size_t end, unsigned long flags, int merge)
++{
++ int i;
++ struct resource *res;
++
++ if (!merge)
++ goto addit;
++
++ /* try to merge it with old one */
++ for (i = 0; i < info->res_num; i++) {
++ size_t final_start, final_end;
++ size_t common_start, common_end;
++
++ res = &info->res[i];
++ if (res->flags != flags)
++ continue;
++
++ common_start = max((size_t)res->start, start);
++ common_end = min((size_t)res->end, end);
++ if (common_start > common_end + 1)
++ continue;
++
++ final_start = min((size_t)res->start, start);
++ final_end = max((size_t)res->end, end);
++
++ res->start = final_start;
++ res->end = final_end;
++ return;
++ }
++
++addit:
++
++ /* need to add that */
++ if (info->res_num >= RES_NUM)
++ return;
++
++ res = &info->res[info->res_num];
++ res->name = info->name;
++ res->flags = flags;
++ res->start = start;
++ res->end = end;
++ res->child = NULL;
++ info->res_num++;
++}
++
++struct pci_hostbridge_probe {
++ u32 bus;
++ u32 slot;
++ u32 vendor;
++ u32 device;
++};
++
++static struct pci_hostbridge_probe pci_probes[] __initdata = {
++ { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1100 },
++ { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1200 },
++ { 0xff, 0, PCI_VENDOR_ID_AMD, 0x1200 },
++ { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1300 },
++};
++
++static u64 __initdata fam10h_mmconf_start;
++static u64 __initdata fam10h_mmconf_end;
++static void __init get_pci_mmcfg_amd_fam10h_range(void)
++{
++ u32 address;
++ u64 base, msr;
++ unsigned segn_busn_bits;
++
++ /* assume all cpus from fam10h have mmconf */
++ if (boot_cpu_data.x86 < 0x10)
++ return;
++
++ address = MSR_FAM10H_MMIO_CONF_BASE;
++ rdmsrl(address, msr);
++
++ /* mmconfig is not enable */
++ if (!(msr & FAM10H_MMIO_CONF_ENABLE))
++ return;
++
++ base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT);
++
++ segn_busn_bits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
++ FAM10H_MMIO_CONF_BUSRANGE_MASK;
++
++ fam10h_mmconf_start = base;
++ fam10h_mmconf_end = base + (1ULL<<(segn_busn_bits + 20)) - 1;
++}
+
+ /**
+- * fill_mp_bus_to_cpumask()
++ * early_fill_mp_bus_to_node()
++ * called before pcibios_scan_root and pci_scan_bus
+ * fills the mp_bus_to_cpumask array based according to the LDT Bus Number
+ * Registers found in the K8 northbridge
+ */
+-__init static int
+-fill_mp_bus_to_cpumask(void)
++static int __init early_fill_mp_bus_info(void)
+ {
+- struct pci_dev *nb_dev = NULL;
+- int i, j;
+- u32 ldtbus, nid;
+- static int lbnr[3] = {
+- LDT_BUS_NUMBER_REGISTER_0,
+- LDT_BUS_NUMBER_REGISTER_1,
+- LDT_BUS_NUMBER_REGISTER_2
+- };
+-
+- while ((nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+- PCI_DEVICE_ID_K8HTCONFIG, nb_dev))) {
+- pci_read_config_dword(nb_dev, NODE_ID_REGISTER, &nid);
+-
+- for (i = 0; i < NR_LDT_BUS_NUMBER_REGISTERS; i++) {
+- pci_read_config_dword(nb_dev, lbnr[i], &ldtbus);
+- /*
+- * if there are no busses hanging off of the current
+- * ldt link then both the secondary and subordinate
+- * bus number fields are set to 0.
+- *
+- * RED-PEN
+- * This is slightly broken because it assumes
+- * HT node IDs == Linux node ids, which is not always
+- * true. However it is probably mostly true.
+- */
+- if (!(SECONDARY_LDT_BUS_NUMBER(ldtbus) == 0
+- && SUBORDINATE_LDT_BUS_NUMBER(ldtbus) == 0)) {
+- for (j = SECONDARY_LDT_BUS_NUMBER(ldtbus);
+- j <= SUBORDINATE_LDT_BUS_NUMBER(ldtbus);
+- j++) {
+- struct pci_bus *bus;
+- struct pci_sysdata *sd;
+-
+- long node = NODE_ID(nid);
+- /* Algorithm a bit dumb, but
+- it shouldn't matter here */
+- bus = pci_find_bus(0, j);
+- if (!bus)
+- continue;
+- if (!node_online(node))
+- node = 0;
+-
+- sd = bus->sysdata;
+- sd->node = node;
+- }
++ int i;
++ int j;
++ unsigned bus;
++ unsigned slot;
++ int found;
++ int node;
++ int link;
++ int def_node;
++ int def_link;
++ struct pci_root_info *info;
++ u32 reg;
++ struct resource *res;
++ size_t start;
++ size_t end;
++ struct res_range range[RANGE_NUM];
++ u64 val;
++ u32 address;
++
++#ifdef CONFIG_NUMA
++ for (i = 0; i < BUS_NR; i++)
++ mp_bus_to_node[i] = -1;
++#endif
++
++ if (!early_pci_allowed())
++ return -1;
++
++ found = 0;
++ for (i = 0; i < ARRAY_SIZE(pci_probes); i++) {
++ u32 id;
++ u16 device;
++ u16 vendor;
++
++ bus = pci_probes[i].bus;
++ slot = pci_probes[i].slot;
++ id = read_pci_config(bus, slot, 0, PCI_VENDOR_ID);
++
++ vendor = id & 0xffff;
++ device = (id>>16) & 0xffff;
++ if (pci_probes[i].vendor == vendor &&
++ pci_probes[i].device == device) {
++ found = 1;
++ break;
++ }
++ }
++
++ if (!found)
++ return 0;
++
++ pci_root_num = 0;
++ for (i = 0; i < 4; i++) {
++ int min_bus;
++ int max_bus;
++ reg = read_pci_config(bus, slot, 1, 0xe0 + (i << 2));
++
++ /* Check if that register is enabled for bus range */
++ if ((reg & 7) != 3)
++ continue;
++
++ min_bus = (reg >> 16) & 0xff;
++ max_bus = (reg >> 24) & 0xff;
++ node = (reg >> 4) & 0x07;
++#ifdef CONFIG_NUMA
++ for (j = min_bus; j <= max_bus; j++)
++ mp_bus_to_node[j] = (unsigned char) node;
++#endif
++ link = (reg >> 8) & 0x03;
++
++ info = &pci_root_info[pci_root_num];
++ info->bus_min = min_bus;
++ info->bus_max = max_bus;
++ info->node = node;
++ info->link = link;
++ sprintf(info->name, "PCI Bus #%02x", min_bus);
++ pci_root_num++;
++ }
++
++ /* get the default node and link for left over res */
++ reg = read_pci_config(bus, slot, 0, 0x60);
++ def_node = (reg >> 8) & 0x07;
++ reg = read_pci_config(bus, slot, 0, 0x64);
++ def_link = (reg >> 8) & 0x03;
++
++ memset(range, 0, sizeof(range));
++ range[0].end = 0xffff;
++ /* io port resource */
++ for (i = 0; i < 4; i++) {
++ reg = read_pci_config(bus, slot, 1, 0xc0 + (i << 3));
++ if (!(reg & 3))
++ continue;
++
++ start = reg & 0xfff000;
++ reg = read_pci_config(bus, slot, 1, 0xc4 + (i << 3));
++ node = reg & 0x07;
++ link = (reg >> 4) & 0x03;
++ end = (reg & 0xfff000) | 0xfff;
++
++ /* find the position */
++ for (j = 0; j < pci_root_num; j++) {
++ info = &pci_root_info[j];
++ if (info->node == node && info->link == link)
++ break;
++ }
++ if (j == pci_root_num)
++ continue; /* not found */
++
++ info = &pci_root_info[j];
++ printk(KERN_DEBUG "node %d link %d: io port [%llx, %llx]\n",
++ node, link, (u64)start, (u64)end);
++
++ /* kernel only handle 16 bit only */
++ if (end > 0xffff)
++ end = 0xffff;
++ update_res(info, start, end, IORESOURCE_IO, 1);
++ update_range(range, start, end);
++ }
++ /* add left over io port range to def node/link, [0, 0xffff] */
++ /* find the position */
++ for (j = 0; j < pci_root_num; j++) {
++ info = &pci_root_info[j];
++ if (info->node == def_node && info->link == def_link)
++ break;
++ }
++ if (j < pci_root_num) {
++ info = &pci_root_info[j];
++ for (i = 0; i < RANGE_NUM; i++) {
++ if (!range[i].end)
++ continue;
++
++ update_res(info, range[i].start, range[i].end,
++ IORESOURCE_IO, 1);
++ }
++ }
++
++ memset(range, 0, sizeof(range));
++ /* 0xfd00000000-0xffffffffff for HT */
++ range[0].end = (0xfdULL<<32) - 1;
++
++ /* need to take out [0, TOM) for RAM*/
++ address = MSR_K8_TOP_MEM1;
++ rdmsrl(address, val);
++ end = (val & 0xffffff8000000ULL);
++ printk(KERN_INFO "TOM: %016lx aka %ldM\n", end, end>>20);
++ if (end < (1ULL<<32))
++ update_range(range, 0, end - 1);
++
++ /* get mmconfig */
++ get_pci_mmcfg_amd_fam10h_range();
++ /* need to take out mmconf range */
++ if (fam10h_mmconf_end) {
++ printk(KERN_DEBUG "Fam 10h mmconf [%llx, %llx]\n", fam10h_mmconf_start, fam10h_mmconf_end);
++ update_range(range, fam10h_mmconf_start, fam10h_mmconf_end);
++ }
++
++ /* mmio resource */
++ for (i = 0; i < 8; i++) {
++ reg = read_pci_config(bus, slot, 1, 0x80 + (i << 3));
++ if (!(reg & 3))
++ continue;
++
++ start = reg & 0xffffff00; /* 39:16 on 31:8*/
++ start <<= 8;
++ reg = read_pci_config(bus, slot, 1, 0x84 + (i << 3));
++ node = reg & 0x07;
++ link = (reg >> 4) & 0x03;
++ end = (reg & 0xffffff00);
++ end <<= 8;
++ end |= 0xffff;
++
++ /* find the position */
++ for (j = 0; j < pci_root_num; j++) {
++ info = &pci_root_info[j];
++ if (info->node == node && info->link == link)
++ break;
++ }
++ if (j == pci_root_num)
++ continue; /* not found */
++
++ info = &pci_root_info[j];
++
++ printk(KERN_DEBUG "node %d link %d: mmio [%llx, %llx]",
++ node, link, (u64)start, (u64)end);
++ /*
++ * some sick allocation would have range overlap with fam10h
++ * mmconf range, so need to update start and end.
++ */
++ if (fam10h_mmconf_end) {
++ int changed = 0;
++ u64 endx = 0;
++ if (start >= fam10h_mmconf_start &&
++ start <= fam10h_mmconf_end) {
++ start = fam10h_mmconf_end + 1;
++ changed = 1;
++ }
++
++ if (end >= fam10h_mmconf_start &&
++ end <= fam10h_mmconf_end) {
++ end = fam10h_mmconf_start - 1;
++ changed = 1;
++ }
++
++ if (start < fam10h_mmconf_start &&
++ end > fam10h_mmconf_end) {
++ /* we got a hole */
++ endx = fam10h_mmconf_start - 1;
++ update_res(info, start, endx, IORESOURCE_MEM, 0);
++ update_range(range, start, endx);
++ printk(KERN_CONT " ==> [%llx, %llx]", (u64)start, endx);
++ start = fam10h_mmconf_end + 1;
++ changed = 1;
++ }
++ if (changed) {
++ if (start <= end) {
++ printk(KERN_CONT " %s [%llx, %llx]", endx?"and":"==>", (u64)start, (u64)end);
++ } else {
++ printk(KERN_CONT "%s\n", endx?"":" ==> none");
++ continue;
++ }
+ }
+ }
++
++ update_res(info, start, end, IORESOURCE_MEM, 1);
++ update_range(range, start, end);
++ printk(KERN_CONT "\n");
++ }
++
++ /* need to take out [4G, TOM2) for RAM*/
++ /* SYS_CFG */
++ address = MSR_K8_SYSCFG;
++ rdmsrl(address, val);
++ /* TOP_MEM2 is enabled? */
++ if (val & (1<<21)) {
++ /* TOP_MEM2 */
++ address = MSR_K8_TOP_MEM2;
++ rdmsrl(address, val);
++ end = (val & 0xffffff8000000ULL);
++ printk(KERN_INFO "TOM2: %016lx aka %ldM\n", end, end>>20);
++ update_range(range, 1ULL<<32, end - 1);
++ }
++
++ /*
++ * add left over mmio range to def node/link ?
++ * that is tricky, just record range in from start_min to 4G
++ */
++ for (j = 0; j < pci_root_num; j++) {
++ info = &pci_root_info[j];
++ if (info->node == def_node && info->link == def_link)
++ break;
++ }
++ if (j < pci_root_num) {
++ info = &pci_root_info[j];
++
++ for (i = 0; i < RANGE_NUM; i++) {
++ if (!range[i].end)
++ continue;
++
++ update_res(info, range[i].start, range[i].end,
++ IORESOURCE_MEM, 1);
++ }
++ }
++
++#ifdef CONFIG_NUMA
++ for (i = 0; i < BUS_NR; i++) {
++ node = mp_bus_to_node[i];
++ if (node >= 0)
++ printk(KERN_DEBUG "bus: %02x to node: %02x\n", i, node);
++ }
++#endif
++
++ for (i = 0; i < pci_root_num; i++) {
++ int res_num;
++ int busnum;
++
++ info = &pci_root_info[i];
++ res_num = info->res_num;
++ busnum = info->bus_min;
++ printk(KERN_DEBUG "bus: [%02x,%02x] on node %x link %x\n",
++ info->bus_min, info->bus_max, info->node, info->link);
++ for (j = 0; j < res_num; j++) {
++ res = &info->res[j];
++ printk(KERN_DEBUG "bus: %02x index %x %s: [%llx, %llx]\n",
++ busnum, j,
++ (res->flags & IORESOURCE_IO)?"io port":"mmio",
++ res->start, res->end);
++ }
+ }
+
+ return 0;
+ }
+
+-fs_initcall(fill_mp_bus_to_cpumask);
++postcore_initcall(early_fill_mp_bus_info);
+diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c
+index e041ced..a67921c 100644
+--- a/arch/x86/pci/legacy.c
++++ b/arch/x86/pci/legacy.c
+@@ -12,6 +12,7 @@
+ static void __devinit pcibios_fixup_peer_bridges(void)
{
- int err;
+ int n, devfn;
++ long node;
-- if ((err = pcibios_enable_resources(dev, mask)) < 0)
-+ if ((err = pci_enable_resources(dev, mask)) < 0)
- return err;
+ if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff)
+ return;
+@@ -21,12 +22,13 @@ static void __devinit pcibios_fixup_peer_bridges(void)
+ u32 l;
+ if (pci_find_bus(0, n))
+ continue;
++ node = get_mp_bus_to_node(n);
+ for (devfn = 0; devfn < 256; devfn += 8) {
+ if (!raw_pci_read(0, n, devfn, PCI_VENDOR_ID, 2, &l) &&
+ l != 0x0000 && l != 0xffff) {
+ DBG("Found device at %02x:%02x [%04x]\n", n, devfn, l);
+ printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
+- pci_scan_bus_with_sysdata(n);
++ pci_scan_bus_on_node(n, &pci_root_ops, node);
+ break;
+ }
+ }
+diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
+index 8d54df4..0cfebec 100644
+--- a/arch/x86/pci/mmconfig-shared.c
++++ b/arch/x86/pci/mmconfig-shared.c
+@@ -28,7 +28,7 @@ static int __initdata pci_mmcfg_resources_inserted;
+ static const char __init *pci_mmcfg_e7520(void)
+ {
+ u32 win;
+- pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
++ raw_pci_ops->read(0, 0, PCI_DEVFN(0, 0), 0xce, 2, &win);
- if (!dev->msi_enabled)
-diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
-index 103b9df..94f6c73 100644
---- a/arch/x86/pci/i386.c
-+++ b/arch/x86/pci/i386.c
-@@ -30,6 +30,9 @@
- #include <linux/init.h>
- #include <linux/ioport.h>
- #include <linux/errno.h>
-+#include <linux/bootmem.h>
-+
-+#include <asm/pat.h>
+ win = win & 0xf000;
+ if(win == 0x0000 || win == 0xf000)
+@@ -53,7 +53,7 @@ static const char __init *pci_mmcfg_intel_945(void)
- #include "pci.h"
+ pci_mmcfg_config_num = 1;
-@@ -238,44 +241,6 @@ void __init pcibios_resource_survey(void)
- */
- fs_initcall(pcibios_assign_resources);
+- pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar);
++ raw_pci_ops->read(0, 0, PCI_DEVFN(0, 0), 0x48, 4, &pciexbar);
--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);
+ /* Enable bit */
+ if (!(pciexbar & 1))
+@@ -100,33 +100,102 @@ static const char __init *pci_mmcfg_intel_945(void)
+ return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
}
-+static void pci_unmap_page_range(struct vm_area_struct *vma)
++static const char __init *pci_mmcfg_amd_fam10h(void)
+{
-+ u64 addr = (u64)vma->vm_pgoff << PAGE_SHIFT;
-+ free_memtype(addr, addr + vma->vm_end - vma->vm_start);
-+}
++ u32 low, high, address;
++ u64 base, msr;
++ int i;
++ unsigned segnbits = 0, busnbits;
+
-+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;
++ if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF))
++ return NULL;
+
-+ reserve_memtype(addr, addr + vma->vm_end - vma->vm_start, flags, NULL);
-+}
++ address = MSR_FAM10H_MMIO_CONF_BASE;
++ if (rdmsr_safe(address, &low, &high))
++ return NULL;
+
-+static struct vm_operations_struct pci_mmap_ops = {
-+ .open = pci_track_mmap_page_range,
-+ .close = pci_unmap_page_range,
-+};
++ msr = high;
++ msr <<= 32;
++ msr |= low;
+
- int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state, int write_combine)
++ /* mmconfig is not enable */
++ if (!(msr & FAM10H_MMIO_CONF_ENABLE))
++ return NULL;
++
++ base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT);
++
++ busnbits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
++ FAM10H_MMIO_CONF_BUSRANGE_MASK;
++
++ /*
++ * only handle bus 0 ?
++ * need to skip it
++ */
++ if (!busnbits)
++ return NULL;
++
++ if (busnbits > 8) {
++ segnbits = busnbits - 8;
++ busnbits = 8;
++ }
++
++ pci_mmcfg_config_num = (1 << segnbits);
++ pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]) *
++ pci_mmcfg_config_num, GFP_KERNEL);
++ if (!pci_mmcfg_config)
++ return NULL;
++
++ for (i = 0; i < (1 << segnbits); i++) {
++ pci_mmcfg_config[i].address = base + (1<<28) * i;
++ pci_mmcfg_config[i].pci_segment = i;
++ pci_mmcfg_config[i].start_bus_number = 0;
++ pci_mmcfg_config[i].end_bus_number = (1 << busnbits) - 1;
++ }
++
++ return "AMD Family 10h NB";
++}
++
+ struct pci_mmcfg_hostbridge_probe {
++ u32 bus;
++ u32 devfn;
+ u32 vendor;
+ u32 device;
+ const char *(*probe)(void);
+ };
+
+ static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
+- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
+- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
++ { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL,
++ PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
++ { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL,
++ PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
++ { 0, PCI_DEVFN(0x18, 0), PCI_VENDOR_ID_AMD,
++ 0x1200, pci_mmcfg_amd_fam10h },
++ { 0xff, PCI_DEVFN(0, 0), PCI_VENDOR_ID_AMD,
++ 0x1200, pci_mmcfg_amd_fam10h },
+ };
+
+ static int __init pci_mmcfg_check_hostbridge(void)
{
- 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;
+ u32 l;
++ u32 bus, devfn;
+ u16 vendor, device;
+ int i;
+ const char *name;
- /* 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;
+- pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
+- vendor = l & 0xffff;
+- device = (l >> 16) & 0xffff;
++ if (!raw_pci_ops)
++ return 0;
-- /* 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;
+ pci_mmcfg_config_num = 0;
+ pci_mmcfg_config = NULL;
+ name = NULL;
+
+ for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
++ bus = pci_mmcfg_probes[i].bus;
++ devfn = pci_mmcfg_probes[i].devfn;
++ raw_pci_ops->read(0, bus, devfn, 0, 4, &l);
++ vendor = l & 0xffff;
++ device = (l >> 16) & 0xffff;
+
- vma->vm_page_prot = __pgprot(prot);
+ if (pci_mmcfg_probes[i].vendor == vendor &&
+ pci_mmcfg_probes[i].device == device)
+ name = pci_mmcfg_probes[i].probe();
+@@ -173,9 +242,78 @@ static void __init pci_mmcfg_insert_resources(unsigned long resource_flags)
+ pci_mmcfg_resources_inserted = 1;
+ }
-- /* 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;
+-static void __init pci_mmcfg_reject_broken(int type)
++static acpi_status __init check_mcfg_resource(struct acpi_resource *res,
++ void *data)
++{
++ struct resource *mcfg_res = data;
++ struct acpi_resource_address64 address;
++ acpi_status status;
+
-+ 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;
++ if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
++ struct acpi_resource_fixed_memory32 *fixmem32 =
++ &res->data.fixed_memory32;
++ if (!fixmem32)
++ return AE_OK;
++ if ((mcfg_res->start >= fixmem32->address) &&
++ (mcfg_res->end < (fixmem32->address +
++ fixmem32->address_length))) {
++ mcfg_res->flags = 1;
++ return AE_CTRL_TERMINATE;
+ }
-+ flags = new_flags;
+ }
++ if ((res->type != ACPI_RESOURCE_TYPE_ADDRESS32) &&
++ (res->type != ACPI_RESOURCE_TYPE_ADDRESS64))
++ return AE_OK;
+
-+ if (vma->vm_pgoff <= max_pfn_mapped &&
-+ ioremap_change_attr((unsigned long)__va(addr), len, flags)) {
-+ free_memtype(addr, addr + len);
-+ return -EINVAL;
++ status = acpi_resource_to_address64(res, &address);
++ if (ACPI_FAILURE(status) ||
++ (address.address_length <= 0) ||
++ (address.resource_type != ACPI_MEMORY_RANGE))
++ return AE_OK;
++
++ if ((mcfg_res->start >= address.minimum) &&
++ (mcfg_res->end < (address.minimum + address.address_length))) {
++ mcfg_res->flags = 1;
++ return AE_CTRL_TERMINATE;
+ }
++ return AE_OK;
++}
+
- 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;
++static acpi_status __init find_mboard_resource(acpi_handle handle, u32 lvl,
++ void *context, void **rv)
++{
++ struct resource *mcfg_res = context;
+
- 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)
++ acpi_walk_resources(handle, METHOD_NAME__CRS,
++ check_mcfg_resource, context);
++
++ if (mcfg_res->flags)
++ return AE_CTRL_TERMINATE;
++
++ return AE_OK;
++}
++
++static int __init is_acpi_reserved(unsigned long start, unsigned long end)
++{
++ struct resource mcfg_res;
++
++ mcfg_res.start = start;
++ mcfg_res.end = end;
++ mcfg_res.flags = 0;
++
++ acpi_get_devices("PNP0C01", find_mboard_resource, &mcfg_res, NULL);
++
++ if (!mcfg_res.flags)
++ acpi_get_devices("PNP0C02", find_mboard_resource, &mcfg_res,
++ NULL);
++
++ return mcfg_res.flags;
++}
++
++static void __init pci_mmcfg_reject_broken(int early)
{
- static const unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
+ typeof(pci_mmcfg_config[0]) *cfg;
++ int i;
-- WARN_ON_ONCE(pirq >= 16);
-+ WARN_ON_ONCE(pirq > 16);
- return irqmap[read_config_nybble(router, 0x48, pirq-1)];
+ if ((pci_mmcfg_config_num == 0) ||
+ (pci_mmcfg_config == NULL) ||
+@@ -184,51 +322,80 @@ static void __init pci_mmcfg_reject_broken(int type)
+
+ cfg = &pci_mmcfg_config[0];
+
+- /*
+- * Handle more broken MCFG tables on Asus etc.
+- * They only contain a single entry for bus 0-0.
+- */
+- if (pci_mmcfg_config_num == 1 &&
+- cfg->pci_segment == 0 &&
+- (cfg->start_bus_number | cfg->end_bus_number) == 0) {
+- printk(KERN_ERR "PCI: start and end of bus number is 0. "
+- "Rejected as broken MCFG.\n");
+- goto reject;
++ for (i = 0; i < pci_mmcfg_config_num; i++) {
++ int valid = 0;
++ u32 size = (cfg->end_bus_number + 1) << 20;
++ cfg = &pci_mmcfg_config[i];
++ printk(KERN_NOTICE "PCI: MCFG configuration %d: base %lx "
++ "segment %hu buses %u - %u\n",
++ i, (unsigned long)cfg->address, cfg->pci_segment,
++ (unsigned int)cfg->start_bus_number,
++ (unsigned int)cfg->end_bus_number);
++
++ if (!early &&
++ is_acpi_reserved(cfg->address, cfg->address + size - 1)) {
++ printk(KERN_NOTICE "PCI: MCFG area at %Lx reserved "
++ "in ACPI motherboard resources\n",
++ cfg->address);
++ valid = 1;
++ }
++
++ if (valid)
++ continue;
++
++ if (!early)
++ printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not"
++ " reserved in ACPI motherboard resources\n",
++ cfg->address);
++ /* Don't try to do this check unless configuration
++ type 1 is available. how about type 2 ?*/
++ if (raw_pci_ops && e820_all_mapped(cfg->address,
++ cfg->address + size - 1,
++ E820_RESERVED)) {
++ printk(KERN_NOTICE
++ "PCI: MCFG area at %Lx reserved in E820\n",
++ cfg->address);
++ valid = 1;
++ }
++
++ if (!valid)
++ goto reject;
+ }
+
+- /*
+- * Only do this check when type 1 works. If it doesn't work
+- * assume we run on a Mac and always use MCFG
+- */
+- if (type == 1 && !e820_all_mapped(cfg->address,
+- cfg->address + MMCONFIG_APER_MIN,
+- E820_RESERVED)) {
+- printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not"
+- " E820-reserved\n", cfg->address);
+- goto reject;
+- }
+ return;
+
+ reject:
+ printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
++ pci_mmcfg_arch_free();
+ kfree(pci_mmcfg_config);
+ pci_mmcfg_config = NULL;
+ pci_mmcfg_config_num = 0;
}
-@@ -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];
+-void __init pci_mmcfg_init(int type)
+-{
+- int known_bridge = 0;
++static int __initdata known_bridge;
-- 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 };
++void __init __pci_mmcfg_init(int early)
++{
++ /* MMCONFIG disabled */
+ if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+ return;
-- WARN_ON_ONCE(pirq >= 5);
-+ WARN_ON_ONCE(pirq > 5);
- return read_config_nybble(router, 0x55, pirqmap[pirq-1]);
- }
+- if (type == 1 && pci_mmcfg_check_hostbridge())
+- known_bridge = 1;
++ /* MMCONFIG already enabled */
++ if (!early && !(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
++ return;
++
++ /* for late to exit */
++ if (known_bridge)
++ return;
++
++ if (early) {
++ if (pci_mmcfg_check_hostbridge())
++ known_bridge = 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 };
+ if (!known_bridge) {
+ acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
+- pci_mmcfg_reject_broken(type);
++ pci_mmcfg_reject_broken(early);
+ }
-- WARN_ON_ONCE(pirq >= 5);
-+ WARN_ON_ONCE(pirq > 5);
- write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
- return 1;
+ if ((pci_mmcfg_config_num == 0) ||
+@@ -249,6 +416,16 @@ void __init pci_mmcfg_init(int type)
+ }
}
-@@ -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]);
++void __init pci_mmcfg_early_init(void)
++{
++ __pci_mmcfg_init(1);
++}
++
++void __init pci_mmcfg_late_init(void)
++{
++ __pci_mmcfg_init(0);
++}
++
+ static int __init pci_mmcfg_late_insert_resources(void)
+ {
+ /*
+diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c
+index 081816a..f3c761d 100644
+--- a/arch/x86/pci/mmconfig_32.c
++++ b/arch/x86/pci/mmconfig_32.c
+@@ -136,3 +136,7 @@ int __init pci_mmcfg_arch_init(void)
+ raw_pci_ext_ops = &pci_mmcfg;
+ return 1;
}
-
-@@ -290,7 +290,7 @@ static int pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, i
++
++void __init pci_mmcfg_arch_free(void)
++{
++}
+diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c
+index 9207fd4..a199416 100644
+--- a/arch/x86/pci/mmconfig_64.c
++++ b/arch/x86/pci/mmconfig_64.c
+@@ -127,7 +127,7 @@ static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg)
+ int __init pci_mmcfg_arch_init(void)
{
- 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);
+ int i;
+- pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) *
++ pci_mmcfg_virt = kzalloc(sizeof(*pci_mmcfg_virt) *
+ pci_mmcfg_config_num, GFP_KERNEL);
+ if (pci_mmcfg_virt == NULL) {
+ printk(KERN_ERR "PCI: Can not allocate memory for mmconfig structures\n");
+@@ -141,9 +141,29 @@ int __init pci_mmcfg_arch_init(void)
+ printk(KERN_ERR "PCI: Cannot map mmconfig aperture for "
+ "segment %d\n",
+ pci_mmcfg_config[i].pci_segment);
++ pci_mmcfg_arch_free();
+ return 0;
+ }
+ }
+ raw_pci_ext_ops = &pci_mmcfg;
return 1;
}
++
++void __init pci_mmcfg_arch_free(void)
++{
++ int i;
++
++ if (pci_mmcfg_virt == NULL)
++ return;
++
++ for (i = 0; i < pci_mmcfg_config_num; ++i) {
++ if (pci_mmcfg_virt[i].virt) {
++ iounmap(pci_mmcfg_virt[i].virt);
++ pci_mmcfg_virt[i].virt = NULL;
++ pci_mmcfg_virt[i].cfg = NULL;
++ }
++ }
++
++ kfree(pci_mmcfg_virt);
++ pci_mmcfg_virt = NULL;
++}
+diff --git a/arch/x86/pci/mp_bus_to_node.c b/arch/x86/pci/mp_bus_to_node.c
+new file mode 100644
+index 0000000..0229439
+--- /dev/null
++++ b/arch/x86/pci/mp_bus_to_node.c
+@@ -0,0 +1,23 @@
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/topology.h>
++
++#define BUS_NR 256
++
++static unsigned char mp_bus_to_node[BUS_NR];
++
++void set_mp_bus_to_node(int busnum, int node)
++{
++ if (busnum >= 0 && busnum < BUS_NR)
++ mp_bus_to_node[busnum] = (unsigned char) node;
++}
++
++int get_mp_bus_to_node(int busnum)
++{
++ int node;
++
++ if (busnum < 0 || busnum > (BUS_NR - 1))
++ return 0;
++ node = mp_bus_to_node[busnum];
++ return node;
++}
diff --git a/arch/x86/pci/numa.c b/arch/x86/pci/numa.c
index 55270c2..d9afbae 100644
--- a/arch/x86/pci/numa.c
@@ -266792,6 +335344,325 @@
#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/olpc.c b/arch/x86/pci/olpc.c
+new file mode 100644
+index 0000000..5e76365
+--- /dev/null
++++ b/arch/x86/pci/olpc.c
+@@ -0,0 +1,313 @@
++/*
++ * Low-level PCI config space access for OLPC systems who lack the VSA
++ * PCI virtualization software.
++ *
++ * Copyright © 2006 Advanced Micro 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.
++ *
++ * The AMD Geode chipset (ie: GX2 processor, cs5536 I/O companion device)
++ * has some I/O functions (display, southbridge, sound, USB HCIs, etc)
++ * that more or less behave like PCI devices, but the hardware doesn't
++ * directly implement the PCI configuration space headers. AMD provides
++ * "VSA" (Virtual System Architecture) software that emulates PCI config
++ * space for these devices, by trapping I/O accesses to PCI config register
++ * (CF8/CFC) and running some code in System Management Mode interrupt state.
++ * On the OLPC platform, we don't want to use that VSA code because
++ * (a) it slows down suspend/resume, and (b) recompiling it requires special
++ * compilers that are hard to get. So instead of letting the complex VSA
++ * code simulate the PCI config registers for the on-chip devices, we
++ * just simulate them the easy way, by inserting the code into the
++ * pci_write_config and pci_read_config path. Most of the config registers
++ * are read-only anyway, so the bulk of the simulation is just table lookup.
++ */
++
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <asm/olpc.h>
++#include <asm/geode.h>
++#include "pci.h"
++
++/*
++ * In the tables below, the first two line (8 longwords) are the
++ * size masks that are used when the higher level PCI code determines
++ * the size of the region by writing ~0 to a base address register
++ * and reading back the result.
++ *
++ * The following lines are the values that are read during normal
++ * PCI config access cycles, i.e. not after just having written
++ * ~0 to a base address register.
++ */
++
++static const uint32_t lxnb_hdr[] = { /* dev 1 function 0 - devfn = 8 */
++ 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++
++ 0x281022, 0x2200005, 0x6000021, 0x80f808, /* AMD Vendor ID */
++ 0x0, 0x0, 0x0, 0x0, /* No virtual registers, hence no BAR */
++ 0x0, 0x0, 0x0, 0x28100b,
++ 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++};
++
++static const uint32_t gxnb_hdr[] = { /* dev 1 function 0 - devfn = 8 */
++ 0xfffffffd, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++
++ 0x28100b, 0x2200005, 0x6000021, 0x80f808, /* NSC Vendor ID */
++ 0xac1d, 0x0, 0x0, 0x0, /* I/O BAR - base of virtual registers */
++ 0x0, 0x0, 0x0, 0x28100b,
++ 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++};
++
++static const uint32_t lxfb_hdr[] = { /* dev 1 function 1 - devfn = 9 */
++ 0xff000008, 0xffffc000, 0xffffc000, 0xffffc000,
++ 0xffffc000, 0x0, 0x0, 0x0,
++
++ 0x20811022, 0x2200003, 0x3000000, 0x0, /* AMD Vendor ID */
++ 0xfd000000, 0xfe000000, 0xfe004000, 0xfe008000, /* FB, GP, VG, DF */
++ 0xfe00c000, 0x0, 0x0, 0x30100b, /* VIP */
++ 0x0, 0x0, 0x0, 0x10e, /* INTA, IRQ14 for graphics accel */
++ 0x0, 0x0, 0x0, 0x0,
++ 0x3d0, 0x3c0, 0xa0000, 0x0, /* VG IO, VG IO, EGA FB, MONO FB */
++ 0x0, 0x0, 0x0, 0x0,
++};
++
++static const uint32_t gxfb_hdr[] = { /* dev 1 function 1 - devfn = 9 */
++ 0xff800008, 0xffffc000, 0xffffc000, 0xffffc000,
++ 0x0, 0x0, 0x0, 0x0,
++
++ 0x30100b, 0x2200003, 0x3000000, 0x0, /* NSC Vendor ID */
++ 0xfd000000, 0xfe000000, 0xfe004000, 0xfe008000, /* FB, GP, VG, DF */
++ 0x0, 0x0, 0x0, 0x30100b,
++ 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++ 0x3d0, 0x3c0, 0xa0000, 0x0, /* VG IO, VG IO, EGA FB, MONO FB */
++ 0x0, 0x0, 0x0, 0x0,
++};
++
++static const uint32_t aes_hdr[] = { /* dev 1 function 2 - devfn = 0xa */
++ 0xffffc000, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++
++ 0x20821022, 0x2a00006, 0x10100000, 0x8, /* NSC Vendor ID */
++ 0xfe010000, 0x0, 0x0, 0x0, /* AES registers */
++ 0x0, 0x0, 0x0, 0x20821022,
++ 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++};
++
++
++static const uint32_t isa_hdr[] = { /* dev f function 0 - devfn = 78 */
++ 0xfffffff9, 0xffffff01, 0xffffffc1, 0xffffffe1,
++ 0xffffff81, 0xffffffc1, 0x0, 0x0,
++
++ 0x20901022, 0x2a00049, 0x6010003, 0x802000,
++ 0x18b1, 0x1001, 0x1801, 0x1881, /* SMB-8 GPIO-256 MFGPT-64 IRQ-32 */
++ 0x1401, 0x1841, 0x0, 0x20901022, /* PMS-128 ACPI-64 */
++ 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0xaa5b, /* IRQ steering */
++ 0x0, 0x0, 0x0, 0x0,
++};
++
++static const uint32_t ac97_hdr[] = { /* dev f function 3 - devfn = 7b */
++ 0xffffff81, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++
++ 0x20931022, 0x2a00041, 0x4010001, 0x0,
++ 0x1481, 0x0, 0x0, 0x0, /* I/O BAR-128 */
++ 0x0, 0x0, 0x0, 0x20931022,
++ 0x0, 0x0, 0x0, 0x205, /* IntB, IRQ5 */
++ 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++};
++
++static const uint32_t ohci_hdr[] = { /* dev f function 4 - devfn = 7c */
++ 0xfffff000, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++
++ 0x20941022, 0x2300006, 0xc031002, 0x0,
++ 0xfe01a000, 0x0, 0x0, 0x0, /* MEMBAR-1000 */
++ 0x0, 0x0, 0x0, 0x20941022,
++ 0x0, 0x40, 0x0, 0x40a, /* CapPtr INT-D, IRQA */
++ 0xc8020001, 0x0, 0x0, 0x0, /* Capabilities - 40 is R/O,
++ 44 is mask 8103 (power control) */
++ 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++};
++
++static const uint32_t ehci_hdr[] = { /* dev f function 4 - devfn = 7d */
++ 0xfffff000, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0,
++
++ 0x20951022, 0x2300006, 0xc032002, 0x0,
++ 0xfe01b000, 0x0, 0x0, 0x0, /* MEMBAR-1000 */
++ 0x0, 0x0, 0x0, 0x20951022,
++ 0x0, 0x40, 0x0, 0x40a, /* CapPtr INT-D, IRQA */
++ 0xc8020001, 0x0, 0x0, 0x0, /* Capabilities - 40 is R/O, 44 is
++ mask 8103 (power control) */
++#if 0
++ 0x1, 0x40080000, 0x0, 0x0, /* EECP - see EHCI spec section 2.1.7 */
++#endif
++ 0x01000001, 0x0, 0x0, 0x0, /* EECP - see EHCI spec section 2.1.7 */
++ 0x2020, 0x0, 0x0, 0x0, /* (EHCI page 8) 60 SBRN (R/O),
++ 61 FLADJ (R/W), PORTWAKECAP */
++};
++
++static uint32_t ff_loc = ~0;
++static uint32_t zero_loc;
++static int bar_probing; /* Set after a write of ~0 to a BAR */
++static int is_lx;
++
++#define NB_SLOT 0x1 /* Northbridge - GX chip - Device 1 */
++#define SB_SLOT 0xf /* Southbridge - CS5536 chip - Device F */
++
++static int is_simulated(unsigned int bus, unsigned int devfn)
++{
++ return (!bus && ((PCI_SLOT(devfn) == NB_SLOT) ||
++ (PCI_SLOT(devfn) == SB_SLOT)));
++}
++
++static uint32_t *hdr_addr(const uint32_t *hdr, int reg)
++{
++ uint32_t addr;
++
++ /*
++ * This is a little bit tricky. The header maps consist of
++ * 0x20 bytes of size masks, followed by 0x70 bytes of header data.
++ * In the normal case, when not probing a BAR's size, we want
++ * to access the header data, so we add 0x20 to the reg offset,
++ * thus skipping the size mask area.
++ * In the BAR probing case, we want to access the size mask for
++ * the BAR, so we subtract 0x10 (the config header offset for
++ * BAR0), and don't skip the size mask area.
++ */
++
++ addr = (uint32_t)hdr + reg + (bar_probing ? -0x10 : 0x20);
++
++ bar_probing = 0;
++ return (uint32_t *)addr;
++}
++
++static int pci_olpc_read(unsigned int seg, unsigned int bus,
++ unsigned int devfn, int reg, int len, uint32_t *value)
++{
++ uint32_t *addr;
++
++ /* Use the hardware mechanism for non-simulated devices */
++ if (!is_simulated(bus, devfn))
++ return pci_direct_conf1.read(seg, bus, devfn, reg, len, value);
++
++ /*
++ * No device has config registers past 0x70, so we save table space
++ * by not storing entries for the nonexistent registers
++ */
++ if (reg >= 0x70)
++ addr = &zero_loc;
++ else {
++ switch (devfn) {
++ case 0x8:
++ addr = hdr_addr(is_lx ? lxnb_hdr : gxnb_hdr, reg);
++ break;
++ case 0x9:
++ addr = hdr_addr(is_lx ? lxfb_hdr : gxfb_hdr, reg);
++ break;
++ case 0xa:
++ addr = is_lx ? hdr_addr(aes_hdr, reg) : &ff_loc;
++ break;
++ case 0x78:
++ addr = hdr_addr(isa_hdr, reg);
++ break;
++ case 0x7b:
++ addr = hdr_addr(ac97_hdr, reg);
++ break;
++ case 0x7c:
++ addr = hdr_addr(ohci_hdr, reg);
++ break;
++ case 0x7d:
++ addr = hdr_addr(ehci_hdr, reg);
++ break;
++ default:
++ addr = &ff_loc;
++ break;
++ }
++ }
++ switch (len) {
++ case 1:
++ *value = *(uint8_t *)addr;
++ break;
++ case 2:
++ *value = *(uint16_t *)addr;
++ break;
++ case 4:
++ *value = *addr;
++ break;
++ default:
++ BUG();
++ }
++
++ return 0;
++}
++
++static int pci_olpc_write(unsigned int seg, unsigned int bus,
++ unsigned int devfn, int reg, int len, uint32_t value)
++{
++ /* Use the hardware mechanism for non-simulated devices */
++ if (!is_simulated(bus, devfn))
++ return pci_direct_conf1.write(seg, bus, devfn, reg, len, value);
++
++ /* XXX we may want to extend this to simulate EHCI power management */
++
++ /*
++ * Mostly we just discard writes, but if the write is a size probe
++ * (i.e. writing ~0 to a BAR), we remember it and arrange to return
++ * the appropriate size mask on the next read. This is cheating
++ * to some extent, because it depends on the fact that the next
++ * access after such a write will always be a read to the same BAR.
++ */
++
++ if ((reg >= 0x10) && (reg < 0x2c)) {
++ /* write is to a BAR */
++ if (value == ~0)
++ bar_probing = 1;
++ } else {
++ /*
++ * No warning on writes to ROM BAR, CMD, LATENCY_TIMER,
++ * CACHE_LINE_SIZE, or PM registers.
++ */
++ if ((reg != PCI_ROM_ADDRESS) && (reg != PCI_COMMAND_MASTER) &&
++ (reg != PCI_LATENCY_TIMER) &&
++ (reg != PCI_CACHE_LINE_SIZE) && (reg != 0x44))
++ printk(KERN_WARNING "OLPC PCI: Config write to devfn"
++ " %x reg %x value %x\n", devfn, reg, value);
++ }
++
++ return 0;
++}
++
++static struct pci_raw_ops pci_olpc_conf = {
++ .read = pci_olpc_read,
++ .write = pci_olpc_write,
++};
++
++void __init pci_olpc_init(void)
++{
++ if (!machine_is_olpc() || olpc_has_vsa())
++ return;
++
++ printk(KERN_INFO "PCI: Using configuration type OLPC\n");
++ raw_pci_ops = &pci_olpc_conf;
++ is_lx = is_geode_lx();
++}
diff --git a/arch/x86/pci/pcbios.c b/arch/x86/pci/pcbios.c
index 2f7109a..37472fc 100644
--- a/arch/x86/pci/pcbios.c
@@ -266890,7 +335761,7 @@
}
}
diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h
-index 3431518..c4bddae 100644
+index 3431518..c58805a 100644
--- a/arch/x86/pci/pci.h
+++ b/arch/x86/pci/pci.h
@@ -19,8 +19,6 @@
@@ -266902,7 +335773,15 @@
#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 {
+@@ -28,6 +26,7 @@
+ #define PCI_ASSIGN_ALL_BUSSES 0x4000
+ #define PCI_CAN_SKIP_ISA_ALIGN 0x8000
+ #define PCI_USE__CRS 0x10000
++#define PCI_CHECK_ENABLE_AMD_MMCONF 0x20000
+
+ extern unsigned int pci_probe;
+ extern unsigned long pirq_table_addr;
+@@ -44,7 +43,6 @@ enum pci_bf_sort_state {
extern unsigned int pcibios_max_latency;
void pcibios_resource_survey(void);
@@ -266910,14 +335789,21 @@
/* pci-pc.c */
-@@ -101,7 +98,6 @@ extern int pci_direct_probe(void);
+@@ -100,12 +98,12 @@ extern struct pci_raw_ops pci_direct_conf1;
+ 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 pci_mmcfg_init(int type);
-extern void pcibios_sort(void);
++extern void pci_olpc_init(void);
/* pci-mmconfig.c */
+ extern int __init pci_mmcfg_arch_init(void);
++extern void __init pci_mmcfg_arch_free(void);
+
+ /*
+ * AMD Fam10h CPUs are buggy, and cannot access MMIO config space
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
@@ -267030,8 +335916,24 @@
targets += vdso-syms.lds
obj-$(VDSO64-y) += vdso-syms.lds
+diff --git a/arch/x86/vdso/vdso.S b/arch/x86/vdso/vdso.S
+index 4b1620a..1d3aa6b 100644
+--- a/arch/x86/vdso/vdso.S
++++ b/arch/x86/vdso/vdso.S
+@@ -1,2 +1,10 @@
+- .section ".vdso","a"
++#include <linux/init.h>
++
++__INITDATA
++
++ .globl vdso_start, vdso_end
++vdso_start:
+ .incbin "arch/x86/vdso/vdso.so"
++vdso_end:
++
++__FINIT
diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c
-index 348f134..e2af8ee 100644
+index 348f134..4dceeb1 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;
@@ -267049,7 +335951,16 @@
/* 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)
+@@ -299,8 +303,6 @@ int __init sysenter_setup(void)
+
+ #ifdef CONFIG_X86_32
+ gate_vma_init();
+-
+- printk("Compat vDSO mapped to %08lx.\n", __fix_to_virt(FIX_VDSO));
+ #endif
+
+ if (!vdso32_sysenter()) {
+@@ -325,6 +327,9 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack)
int ret = 0;
bool compat;
@@ -267997,7 +336908,7 @@
+ 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
+index 2a054ef..126766d 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)
@@ -268179,6 +337090,24 @@
#endif /* CONFIG_X86_PAE */
/*
+@@ -418,7 +387,7 @@ static void xen_do_pin(unsigned level, unsigned long pfn)
+
+ static int pin_page(struct page *page, enum pt_level level)
+ {
+- unsigned pgfl = test_and_set_bit(PG_pinned, &page->flags);
++ unsigned pgfl = TestSetPagePinned(page);
+ int flush;
+
+ if (pgfl)
+@@ -499,7 +468,7 @@ void __init xen_mark_init_mm_pinned(void)
+
+ static int unpin_page(struct page *page, enum pt_level level)
+ {
+- unsigned pgfl = test_and_clear_bit(PG_pinned, &page->flags);
++ unsigned pgfl = TestClearPagePinned(page);
+
+ if (pgfl && !PageHighMem(page)) {
+ void *pt = lowmem_page_address(page);
diff --git a/arch/x86/xen/multicalls.c b/arch/x86/xen/multicalls.c
index 5e6f36f..5791eb2 100644
--- a/arch/x86/xen/multicalls.c
@@ -268520,6 +337449,24 @@
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/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c
+index ef63ada..070ff8a 100644
+--- a/arch/xtensa/kernel/asm-offsets.c
++++ b/arch/xtensa/kernel/asm-offsets.c
+@@ -19,12 +19,11 @@
+ #include <linux/thread_info.h>
+ #include <linux/ptrace.h>
+ #include <linux/mm.h>
++#include <linux/kbuild.h>
+
+ #include <asm/ptrace.h>
+ #include <asm/uaccess.h>
+
+-#define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+-
+ int main(void)
+ {
+ /* struct pt_regs */
diff --git a/arch/xtensa/kernel/semaphore.c b/arch/xtensa/kernel/semaphore.c
deleted file mode 100644
index 995c641..0000000
@@ -268885,8 +337832,231 @@
endif # BLOCK
+diff --git a/block/blk-barrier.c b/block/blk-barrier.c
+index 55c5f1f..66e5528 100644
+--- a/block/blk-barrier.c
++++ b/block/blk-barrier.c
+@@ -53,7 +53,7 @@ EXPORT_SYMBOL(blk_queue_ordered);
+ /*
+ * Cache flushing for ordered writes handling
+ */
+-inline unsigned blk_ordered_cur_seq(struct request_queue *q)
++unsigned blk_ordered_cur_seq(struct request_queue *q)
+ {
+ if (!q->ordseq)
+ return 0;
+@@ -143,10 +143,8 @@ static void queue_flush(struct request_queue *q, unsigned which)
+ end_io = post_flush_end_io;
+ }
+
++ blk_rq_init(q, rq);
+ rq->cmd_flags = REQ_HARDBARRIER;
+- rq_init(q, rq);
+- rq->elevator_private = NULL;
+- rq->elevator_private2 = NULL;
+ rq->rq_disk = q->bar_rq.rq_disk;
+ rq->end_io = end_io;
+ q->prepare_flush_fn(q, rq);
+@@ -167,14 +165,11 @@ static inline struct request *start_ordered(struct request_queue *q,
+ blkdev_dequeue_request(rq);
+ q->orig_bar_rq = rq;
+ rq = &q->bar_rq;
+- rq->cmd_flags = 0;
+- rq_init(q, rq);
++ blk_rq_init(q, rq);
+ if (bio_data_dir(q->orig_bar_rq->bio) == WRITE)
+ rq->cmd_flags |= REQ_RW;
+ if (q->ordered & QUEUE_ORDERED_FUA)
+ rq->cmd_flags |= REQ_FUA;
+- rq->elevator_private = NULL;
+- rq->elevator_private2 = NULL;
+ init_request_from_bio(rq, q->orig_bar_rq->bio);
+ rq->end_io = bar_end_io;
+
+diff --git a/block/blk-core.c b/block/blk-core.c
+index 2a438a9..5d09f8c 100644
+--- a/block/blk-core.c
++++ b/block/blk-core.c
+@@ -107,41 +107,21 @@ struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev)
+ }
+ EXPORT_SYMBOL(blk_get_backing_dev_info);
+
+-/*
+- * We can't just memset() the structure, since the allocation path
+- * already stored some information in the request.
+- */
+-void rq_init(struct request_queue *q, struct request *rq)
++void blk_rq_init(struct request_queue *q, struct request *rq)
+ {
++ memset(rq, 0, sizeof(*rq));
++
+ INIT_LIST_HEAD(&rq->queuelist);
+ INIT_LIST_HEAD(&rq->donelist);
+ rq->q = q;
+ rq->sector = rq->hard_sector = (sector_t) -1;
+- rq->nr_sectors = rq->hard_nr_sectors = 0;
+- rq->current_nr_sectors = rq->hard_cur_sectors = 0;
+- rq->bio = rq->biotail = NULL;
+ INIT_HLIST_NODE(&rq->hash);
+ RB_CLEAR_NODE(&rq->rb_node);
+- rq->rq_disk = NULL;
+- rq->nr_phys_segments = 0;
+- rq->nr_hw_segments = 0;
+- rq->ioprio = 0;
+- rq->special = NULL;
+- rq->buffer = NULL;
++ rq->cmd = rq->__cmd;
+ rq->tag = -1;
+- rq->errors = 0;
+ rq->ref_count = 1;
+- rq->cmd_len = 0;
+- memset(rq->cmd, 0, sizeof(rq->cmd));
+- rq->data_len = 0;
+- rq->extra_len = 0;
+- rq->sense_len = 0;
+- rq->data = NULL;
+- rq->sense = NULL;
+- rq->end_io = NULL;
+- rq->end_io_data = NULL;
+- rq->next_rq = NULL;
+ }
++EXPORT_SYMBOL(blk_rq_init);
+
+ static void req_bio_endio(struct request *rq, struct bio *bio,
+ unsigned int nbytes, int error)
+@@ -194,7 +174,7 @@ void blk_dump_rq_flags(struct request *rq, char *msg)
+
+ if (blk_pc_request(rq)) {
+ printk(KERN_INFO " cdb: ");
+- for (bit = 0; bit < sizeof(rq->cmd); bit++)
++ for (bit = 0; bit < BLK_MAX_CDB; bit++)
+ printk("%02x ", rq->cmd[bit]);
+ printk("\n");
+ }
+@@ -220,7 +200,8 @@ void blk_plug_device(struct request_queue *q)
+ if (blk_queue_stopped(q))
+ return;
+
+- if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) {
++ if (!test_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) {
++ __set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags);
+ mod_timer(&q->unplug_timer, jiffies + q->unplug_delay);
+ blk_add_trace_generic(q, NULL, 0, BLK_TA_PLUG);
+ }
+@@ -235,9 +216,10 @@ int blk_remove_plug(struct request_queue *q)
+ {
+ WARN_ON(!irqs_disabled());
+
+- if (!test_and_clear_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags))
++ if (!test_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags))
+ return 0;
+
++ queue_flag_clear(QUEUE_FLAG_PLUGGED, q);
+ del_timer(&q->unplug_timer);
+ return 1;
+ }
+@@ -333,15 +315,16 @@ void blk_start_queue(struct request_queue *q)
+ {
+ WARN_ON(!irqs_disabled());
+
+- clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags);
++ queue_flag_clear(QUEUE_FLAG_STOPPED, q);
+
+ /*
+ * one level of recursion is ok and is much faster than kicking
+ * the unplug handling
+ */
+- if (!test_and_set_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) {
++ if (!test_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) {
++ queue_flag_set(QUEUE_FLAG_REENTER, q);
+ q->request_fn(q);
+- clear_bit(QUEUE_FLAG_REENTER, &q->queue_flags);
++ queue_flag_clear(QUEUE_FLAG_REENTER, q);
+ } else {
+ blk_plug_device(q);
+ kblockd_schedule_work(&q->unplug_work);
+@@ -366,7 +349,7 @@ EXPORT_SYMBOL(blk_start_queue);
+ void blk_stop_queue(struct request_queue *q)
+ {
+ blk_remove_plug(q);
+- set_bit(QUEUE_FLAG_STOPPED, &q->queue_flags);
++ queue_flag_set(QUEUE_FLAG_STOPPED, q);
+ }
+ EXPORT_SYMBOL(blk_stop_queue);
+
+@@ -395,11 +378,8 @@ EXPORT_SYMBOL(blk_sync_queue);
+ * blk_run_queue - run a single device queue
+ * @q: The queue to run
+ */
+-void blk_run_queue(struct request_queue *q)
++void __blk_run_queue(struct request_queue *q)
+ {
+- unsigned long flags;
+-
+- spin_lock_irqsave(q->queue_lock, flags);
+ blk_remove_plug(q);
+
+ /*
+@@ -407,15 +387,28 @@ void blk_run_queue(struct request_queue *q)
+ * handling reinvoke the handler shortly if we already got there.
+ */
+ if (!elv_queue_empty(q)) {
+- if (!test_and_set_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) {
++ if (!test_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) {
++ queue_flag_set(QUEUE_FLAG_REENTER, q);
+ q->request_fn(q);
+- clear_bit(QUEUE_FLAG_REENTER, &q->queue_flags);
++ queue_flag_clear(QUEUE_FLAG_REENTER, q);
+ } else {
+ blk_plug_device(q);
+ kblockd_schedule_work(&q->unplug_work);
+ }
+ }
++}
++EXPORT_SYMBOL(__blk_run_queue);
++
++/**
++ * blk_run_queue - run a single device queue
++ * @q: The queue to run
++ */
++void blk_run_queue(struct request_queue *q)
++{
++ unsigned long flags;
+
++ spin_lock_irqsave(q->queue_lock, flags);
++ __blk_run_queue(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+ }
+ EXPORT_SYMBOL(blk_run_queue);
+@@ -428,7 +421,7 @@ void blk_put_queue(struct request_queue *q)
+ void blk_cleanup_queue(struct request_queue *q)
+ {
+ mutex_lock(&q->sysfs_lock);
+- set_bit(QUEUE_FLAG_DEAD, &q->queue_flags);
++ queue_flag_set_unlocked(QUEUE_FLAG_DEAD, q);
+ mutex_unlock(&q->sysfs_lock);
+
+ if (q->elevator)
+@@ -607,6 +600,8 @@ blk_alloc_request(struct request_queue *q, int rw, int priv, gfp_t gfp_mask)
+ if (!rq)
+ return NULL;
+
++ blk_rq_init(q, rq);
++
+ /*
+ * first three bits are identical in rq->cmd_flags and bio->bi_rw,
+ * see bio.h and blkdev.h
+@@ -789,8 +784,6 @@ rq_starved:
+ if (ioc_batching(q, ioc))
+ ioc->nr_batch_requests--;
+
+- rq_init(q, rq);
+-
+ blk_add_trace_generic(q, bio, rw, BLK_TA_GETRQ);
+ out:
+ return rq;
diff --git a/block/blk-map.c b/block/blk-map.c
-index c07d9c8..3c942bd 100644
+index c07d9c8..0b1af5a 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -5,6 +5,7 @@
@@ -268967,10 +338137,82 @@
bio_get(bio);
blk_rq_bio_prep(q, rq, bio);
rq->buffer = rq->data = NULL;
+@@ -257,10 +255,18 @@ EXPORT_SYMBOL(blk_rq_unmap_user);
+ * @kbuf: the kernel buffer
+ * @len: length of user data
+ * @gfp_mask: memory allocation flags
++ *
++ * Description:
++ * Data will be mapped directly if possible. Otherwise a bounce
++ * buffer is used.
+ */
+ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
+ unsigned int len, gfp_t gfp_mask)
+ {
++ unsigned long kaddr;
++ unsigned int alignment;
++ int reading = rq_data_dir(rq) == READ;
++ int do_copy = 0;
+ struct bio *bio;
+
+ if (len > (q->max_hw_sectors << 9))
+@@ -268,13 +274,24 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
+ if (!len || !kbuf)
+ return -EINVAL;
+
+- bio = bio_map_kern(q, kbuf, len, gfp_mask);
++ kaddr = (unsigned long)kbuf;
++ alignment = queue_dma_alignment(q) | q->dma_pad_mask;
++ do_copy = ((kaddr & alignment) || (len & alignment));
++
++ if (do_copy)
++ bio = bio_copy_kern(q, kbuf, len, gfp_mask, reading);
++ else
++ bio = bio_map_kern(q, kbuf, len, gfp_mask);
++
+ if (IS_ERR(bio))
+ return PTR_ERR(bio);
+
+ if (rq_data_dir(rq) == WRITE)
+ bio->bi_rw |= (1 << BIO_RW);
+
++ if (do_copy)
++ rq->cmd_flags |= REQ_COPY_USER;
++
+ blk_rq_bio_prep(q, rq, bio);
+ blk_queue_bounce(q, &rq->bio);
+ rq->buffer = rq->data = NULL;
diff --git a/block/blk-merge.c b/block/blk-merge.c
-index 0f58616..b5c5c4a 100644
+index 0f58616..73b2356 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
+@@ -55,7 +55,7 @@ void blk_recalc_rq_segments(struct request *rq)
+ if (!rq->bio)
+ return;
+
+- cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER);
++ cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
+ hw_seg_size = seg_size = 0;
+ phys_size = hw_size = nr_phys_segs = nr_hw_segs = 0;
+ rq_for_each_segment(bv, rq, iter) {
+@@ -128,7 +128,7 @@ EXPORT_SYMBOL(blk_recount_segments);
+ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
+ struct bio *nxt)
+ {
+- if (!(q->queue_flags & (1 << QUEUE_FLAG_CLUSTER)))
++ if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags))
+ return 0;
+
+ if (!BIOVEC_PHYS_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)))
+@@ -175,7 +175,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
+ int nsegs, cluster;
+
+ nsegs = 0;
+- cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER);
++ cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
+
+ /*
+ * for each bio in rq
@@ -220,6 +220,15 @@ new_segment:
bvprv = bvec;
} /* segments in rq */
@@ -268987,11 +338229,79 @@
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-settings.c b/block/blk-settings.c
+index 5713f7e..6089384 100644
+--- a/block/blk-settings.c
++++ b/block/blk-settings.c
+@@ -14,7 +14,6 @@ unsigned long blk_max_low_pfn;
+ EXPORT_SYMBOL(blk_max_low_pfn);
+
+ unsigned long blk_max_pfn;
+-EXPORT_SYMBOL(blk_max_pfn);
+
+ /**
+ * blk_queue_prep_rq - set a prepare_request function for queue
+@@ -288,7 +287,7 @@ void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)
+ t->max_segment_size = min(t->max_segment_size, b->max_segment_size);
+ t->hardsect_size = max(t->hardsect_size, b->hardsect_size);
+ if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags))
+- clear_bit(QUEUE_FLAG_CLUSTER, &t->queue_flags);
++ queue_flag_clear(QUEUE_FLAG_CLUSTER, t);
+ }
+ EXPORT_SYMBOL(blk_queue_stack_limits);
+
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
-index 54d0db1..fc41d83 100644
+index 54d0db1..e85c401 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
-@@ -276,9 +276,12 @@ int blk_register_queue(struct gendisk *disk)
+@@ -135,6 +135,25 @@ static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page)
+ return queue_var_show(max_hw_sectors_kb, (page));
+ }
+
++static ssize_t queue_nomerges_show(struct request_queue *q, char *page)
++{
++ return queue_var_show(blk_queue_nomerges(q), page);
++}
++
++static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
++ size_t count)
++{
++ unsigned long nm;
++ ssize_t ret = queue_var_store(&nm, page, count);
++
++ if (nm)
++ set_bit(QUEUE_FLAG_NOMERGES, &q->queue_flags);
++ else
++ clear_bit(QUEUE_FLAG_NOMERGES, &q->queue_flags);
++
++ return ret;
++}
++
+
+ static struct queue_sysfs_entry queue_requests_entry = {
+ .attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
+@@ -170,6 +189,12 @@ static struct queue_sysfs_entry queue_hw_sector_size_entry = {
+ .show = queue_hw_sector_size_show,
+ };
+
++static struct queue_sysfs_entry queue_nomerges_entry = {
++ .attr = {.name = "nomerges", .mode = S_IRUGO | S_IWUSR },
++ .show = queue_nomerges_show,
++ .store = queue_nomerges_store,
++};
++
+ static struct attribute *default_attrs[] = {
+ &queue_requests_entry.attr,
+ &queue_ra_entry.attr,
+@@ -177,6 +202,7 @@ static struct attribute *default_attrs[] = {
+ &queue_max_sectors_entry.attr,
+ &queue_iosched_entry.attr,
+ &queue_hw_sector_size_entry.attr,
++ &queue_nomerges_entry.attr,
+ NULL,
+ };
+
+@@ -276,9 +302,12 @@ int blk_register_queue(struct gendisk *disk)
struct request_queue *q = disk->queue;
@@ -269005,7 +338315,7 @@
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)
+@@ -300,7 +329,10 @@ void blk_unregister_queue(struct gendisk *disk)
{
struct request_queue *q = disk->queue;
@@ -269017,8 +338327,60 @@
elv_unregister_queue(q);
kobject_uevent(&q->kobj, KOBJ_REMOVE);
+diff --git a/block/blk-tag.c b/block/blk-tag.c
+index 4780a46..e176ddb 100644
+--- a/block/blk-tag.c
++++ b/block/blk-tag.c
+@@ -70,7 +70,7 @@ void __blk_queue_free_tags(struct request_queue *q)
+ __blk_free_tags(bqt);
+
+ q->queue_tags = NULL;
+- q->queue_flags &= ~(1 << QUEUE_FLAG_QUEUED);
++ queue_flag_clear(QUEUE_FLAG_QUEUED, q);
+ }
+
+ /**
+@@ -98,7 +98,7 @@ EXPORT_SYMBOL(blk_free_tags);
+ **/
+ void blk_queue_free_tags(struct request_queue *q)
+ {
+- clear_bit(QUEUE_FLAG_QUEUED, &q->queue_flags);
++ queue_flag_clear(QUEUE_FLAG_QUEUED, q);
+ }
+ EXPORT_SYMBOL(blk_queue_free_tags);
+
+@@ -188,7 +188,7 @@ int blk_queue_init_tags(struct request_queue *q, int depth,
+ rc = blk_queue_resize_tags(q, depth);
+ if (rc)
+ return rc;
+- set_bit(QUEUE_FLAG_QUEUED, &q->queue_flags);
++ queue_flag_set(QUEUE_FLAG_QUEUED, q);
+ return 0;
+ } else
+ atomic_inc(&tags->refcnt);
+@@ -197,7 +197,7 @@ int blk_queue_init_tags(struct request_queue *q, int depth,
+ * assign it, all done
+ */
+ q->queue_tags = tags;
+- q->queue_flags |= (1 << QUEUE_FLAG_QUEUED);
++ queue_flag_set(QUEUE_FLAG_QUEUED, q);
+ INIT_LIST_HEAD(&q->tag_busy_list);
+ return 0;
+ fail:
+diff --git a/block/blk.h b/block/blk.h
+index ec9120f..59776ab 100644
+--- a/block/blk.h
++++ b/block/blk.h
+@@ -10,7 +10,6 @@
+ extern struct kmem_cache *blk_requestq_cachep;
+ extern struct kobj_type blk_queue_ktype;
+
+-void rq_init(struct request_queue *q, struct request *rq);
+ void init_request_from_bio(struct request *req, struct bio *bio);
+ void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
+ struct bio *bio);
diff --git a/block/bsg.c b/block/bsg.c
-index 8917c51..f51172e 100644
+index 8917c51..23ea4fd 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -37,7 +37,6 @@ struct bsg_device {
@@ -269047,23 +338409,51 @@
/*
* wait for all commands to complete
*/
-@@ -705,6 +702,7 @@ static struct bsg_device *bsg_alloc_device(void)
+@@ -702,13 +699,26 @@ static struct bsg_device *bsg_alloc_device(void)
+ return bd;
+ }
+
++static void bsg_kref_release_function(struct kref *kref)
++{
++ struct bsg_class_device *bcd =
++ container_of(kref, struct bsg_class_device, ref);
++
++ if (bcd->release)
++ bcd->release(bcd->parent);
++
++ put_device(bcd->parent);
++}
++
static int bsg_put_device(struct bsg_device *bd)
{
- int ret = 0;
-+ struct device *dev = bd->queue->bsg_dev.dev;
+- int ret = 0;
++ int ret = 0, do_free;
++ struct request_queue *q = bd->queue;
mutex_lock(&bsg_mutex);
-@@ -730,6 +728,7 @@ static int bsg_put_device(struct bsg_device *bd)
+- if (!atomic_dec_and_test(&bd->ref_count))
++ do_free = atomic_dec_and_test(&bd->ref_count);
++ if (!do_free)
+ goto out;
+
+ dprintk("%s: tearing down\n", bd->name);
+@@ -725,11 +735,13 @@ static int bsg_put_device(struct bsg_device *bd)
+ */
+ ret = bsg_complete_all_commands(bd);
+
+- blk_put_queue(bd->queue);
+ hlist_del(&bd->dev_list);
kfree(bd);
out:
mutex_unlock(&bsg_mutex);
-+ put_device(dev);
++ kref_put(&q->bsg_dev.ref, bsg_kref_release_function);
++ if (do_free)
++ blk_put_queue(q);
return ret;
}
-@@ -738,24 +737,28 @@ static struct bsg_device *bsg_add_device(struct inode *inode,
+@@ -738,24 +750,28 @@ static struct bsg_device *bsg_add_device(struct inode *inode,
struct file *file)
{
struct bsg_device *bd;
@@ -269097,7 +338487,7 @@
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,
+@@ -763,23 +779,21 @@ static struct bsg_device *bsg_add_device(struct inode *inode,
return bd;
}
@@ -269128,7 +338518,7 @@
mutex_unlock(&bsg_mutex);
return bd;
}
-@@ -789,21 +790,27 @@ static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
+@@ -789,21 +803,27 @@ static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
struct bsg_device *bd;
struct bsg_class_device *bcd;
@@ -269142,7 +338532,7 @@
mutex_lock(&bsg_mutex);
bcd = idr_find(&bsg_minor_idr, iminor(inode));
+ if (bcd)
-+ get_device(bcd->dev);
++ kref_get(&bcd->ref);
mutex_unlock(&bsg_mutex);
if (!bcd)
@@ -269155,25 +338545,31 @@
+
+ bd = bsg_add_device(inode, bcd->queue, file);
+ if (IS_ERR(bd))
-+ put_device(bcd->dev);
++ kref_put(&bcd->ref, bsg_kref_release_function);
+
+ return bd;
}
static int bsg_open(struct inode *inode, struct file *file)
-@@ -939,10 +946,9 @@ void bsg_unregister_queue(struct request_queue *q)
+@@ -939,27 +959,26 @@ 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);
+- put_device(bcd->dev);
+ device_unregister(bcd->class_dev);
- put_device(bcd->dev);
bcd->class_dev = NULL;
- bcd->dev = NULL;
++ kref_put(&bcd->ref, bsg_kref_release_function);
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,
+
+-int bsg_register_queue(struct request_queue *q, struct device *gdev,
+- const char *name)
++int bsg_register_queue(struct request_queue *q, struct device *parent,
++ const char *name, void (*release)(struct device *))
+ {
struct bsg_class_device *bcd;
dev_t dev;
int ret, minor;
@@ -269182,25 +338578,40 @@
const char *devname;
if (name)
-@@ -992,8 +998,7 @@ int bsg_register_queue(struct request_queue *q, struct device *gdev,
+ devname = name;
+ else
+- devname = gdev->bus_id;
++ devname = parent->bus_id;
+
+ /*
+ * we need a proper transport to send commands, not a stacked device
+@@ -990,10 +1009,11 @@ int bsg_register_queue(struct request_queue *q, struct device *gdev,
+
+ bcd->minor = minor;
bcd->queue = q;
- bcd->dev = get_device(gdev);
+- bcd->dev = get_device(gdev);
++ bcd->parent = get_device(parent);
++ bcd->release = release;
++ kref_init(&bcd->ref);
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);
++ class_dev = device_create(bsg_class, parent, 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,
+@@ -1010,9 +1030,9 @@ 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);
+- put_device(gdev);
++ put_device(parent);
remove_idr:
+ idr_remove(&bsg_minor_idr, minor);
+ unlock:
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index b733732..c70d0b6 100644
--- a/block/compat_ioctl.c
@@ -269213,6 +338624,115 @@
/* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
case 0x330:
/* 0x02 -- Floppy ioctls */
+diff --git a/block/elevator.c b/block/elevator.c
+index 88318c3..ac5310e 100644
+--- a/block/elevator.c
++++ b/block/elevator.c
+@@ -69,7 +69,7 @@ static int elv_iosched_allow_merge(struct request *rq, struct bio *bio)
+ /*
+ * can we safely merge with this request?
+ */
+-inline int elv_rq_merge_ok(struct request *rq, struct bio *bio)
++int elv_rq_merge_ok(struct request *rq, struct bio *bio)
+ {
+ if (!rq_mergeable(rq))
+ return 0;
+@@ -488,6 +488,9 @@ int elv_merge(struct request_queue *q, struct request **req, struct bio *bio)
+ }
+ }
+
++ if (blk_queue_nomerges(q))
++ return ELEVATOR_NO_MERGE;
++
+ /*
+ * See if our hash lookup can find a potential backmerge.
+ */
+@@ -1070,7 +1073,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
+ */
+ spin_lock_irq(q->queue_lock);
+
+- set_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
++ queue_flag_set(QUEUE_FLAG_ELVSWITCH, q);
+
+ elv_drain_elevator(q);
+
+@@ -1104,7 +1107,10 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
+ * finally exit old elevator and turn off BYPASS.
+ */
+ elevator_exit(old_elevator);
+- clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
++ spin_lock_irq(q->queue_lock);
++ queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
++ spin_unlock_irq(q->queue_lock);
++
+ return 1;
+
+ fail_register:
+@@ -1115,7 +1121,11 @@ fail_register:
+ elevator_exit(e);
+ q->elevator = old_elevator;
+ elv_register_queue(q);
+- clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
++
++ spin_lock_irq(q->queue_lock);
++ queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
++ spin_unlock_irq(q->queue_lock);
++
+ return 0;
+ }
+
+diff --git a/block/genhd.c b/block/genhd.c
+index 00da521..fda9c7a 100644
+--- a/block/genhd.c
++++ b/block/genhd.c
+@@ -182,11 +182,17 @@ static int exact_lock(dev_t devt, void *data)
+ */
+ void add_disk(struct gendisk *disk)
+ {
++ struct backing_dev_info *bdi;
++
+ disk->flags |= GENHD_FL_UP;
+ blk_register_region(MKDEV(disk->major, disk->first_minor),
+ disk->minors, NULL, exact_match, exact_lock, disk);
+ register_disk(disk);
+ blk_register_queue(disk);
++
++ bdi = &disk->queue->backing_dev_info;
++ bdi_register_dev(bdi, MKDEV(disk->major, disk->first_minor));
++ sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi");
+ }
+
+ EXPORT_SYMBOL(add_disk);
+@@ -194,6 +200,8 @@ EXPORT_SYMBOL(del_gendisk); /* in partitions/check.c */
+
+ void unlink_gendisk(struct gendisk *disk)
+ {
++ sysfs_remove_link(&disk->dev.kobj, "bdi");
++ bdi_unregister(&disk->queue->backing_dev_info);
+ blk_unregister_queue(disk);
+ blk_unregister_region(MKDEV(disk->major, disk->first_minor),
+ disk->minors);
+diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
+index a2c3a93..ffa3720 100644
+--- a/block/scsi_ioctl.c
++++ b/block/scsi_ioctl.c
+@@ -217,8 +217,6 @@ EXPORT_SYMBOL_GPL(blk_verify_command);
+ static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
+ struct sg_io_hdr *hdr, int has_write_perm)
+ {
+- memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
+-
+ if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len))
+ return -EFAULT;
+ if (blk_verify_command(rq->cmd, has_write_perm))
+@@ -531,7 +529,6 @@ static int __blk_send_generic(struct request_queue *q, struct gendisk *bd_disk,
+ rq->data_len = 0;
+ rq->extra_len = 0;
+ rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
+- memset(rq->cmd, 0, sizeof(rq->cmd));
+ rq->cmd[0] = cmd;
+ rq->cmd[4] = data;
+ rq->cmd_len = 6;
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 69f1be6..864456c 100644
--- a/crypto/Kconfig
@@ -285358,93928 +354878,189526 @@
- 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,
++ .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..59f33fa 100644
+--- a/drivers/Kconfig
++++ b/drivers/Kconfig
+@@ -84,6 +84,8 @@ source "drivers/memstick/Kconfig"
+
+ source "drivers/leds/Kconfig"
+
++source "drivers/accessibility/Kconfig"
++
+ source "drivers/infiniband/Kconfig"
+
+ source "drivers/edac/Kconfig"
+@@ -97,4 +99,6 @@ source "drivers/dca/Kconfig"
+ source "drivers/auxdisplay/Kconfig"
+
+ source "drivers/uio/Kconfig"
++
++source "drivers/xen/Kconfig"
+ endmenu
+diff --git a/drivers/Makefile b/drivers/Makefile
+index e5e394a..f65deda 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -70,6 +70,7 @@ obj-$(CONFIG_WATCHDOG) += watchdog/
+ obj-$(CONFIG_PHONE) += telephony/
+ obj-$(CONFIG_MD) += md/
+ obj-$(CONFIG_BT) += bluetooth/
++obj-$(CONFIG_ACCESSIBILITY) += accessibility/
+ obj-$(CONFIG_ISDN) += isdn/
+ obj-$(CONFIG_EDAC) += edac/
+ obj-$(CONFIG_MCA) += mca/
+diff --git a/drivers/accessibility/Kconfig b/drivers/accessibility/Kconfig
+new file mode 100644
+index 0000000..1264c4b
+--- /dev/null
++++ b/drivers/accessibility/Kconfig
+@@ -0,0 +1,23 @@
++menuconfig ACCESSIBILITY
++ bool "Accessibility support"
++ ---help---
++ Enable a submenu where accessibility items may be enabled.
++
++ If unsure, say N.
++
++if ACCESSIBILITY
++config A11Y_BRAILLE_CONSOLE
++ bool "Console on braille device"
++ depends on VT
++ depends on SERIAL_CORE_CONSOLE
++ ---help---
++ Enables console output on a braille device connected to a 8250
++ serial port. For now only the VisioBraille device is supported.
++
++ To actually enable it, you need to pass option
++ console=brl,ttyS0
++ to the kernel. Options are the same as for serial console.
++
++ If unsure, say N.
++
++endif # ACCESSIBILITY
+diff --git a/drivers/accessibility/Makefile b/drivers/accessibility/Makefile
+new file mode 100644
+index 0000000..72b01a4
+--- /dev/null
++++ b/drivers/accessibility/Makefile
+@@ -0,0 +1 @@
++obj-y += braille/
+diff --git a/drivers/accessibility/braille/Makefile b/drivers/accessibility/braille/Makefile
+new file mode 100644
+index 0000000..2e9f16c
+--- /dev/null
++++ b/drivers/accessibility/braille/Makefile
+@@ -0,0 +1 @@
++obj-$(CONFIG_A11Y_BRAILLE_CONSOLE) += braille_console.o
+diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c
+new file mode 100644
+index 0000000..0a5f6b2
+--- /dev/null
++++ b/drivers/accessibility/braille/braille_console.c
+@@ -0,0 +1,397 @@
++/*
++ * Minimalistic braille device kernel support.
++ *
++ * By default, shows console messages on the braille device.
++ * Pressing Insert switches to VC browsing.
++ *
++ * Copyright (C) Samuel Thibault <samuel.thibault at ens-lyon.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 the program ; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/autoconf.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/console.h>
++#include <linux/notifier.h>
++
++#include <linux/selection.h>
++#include <linux/vt_kern.h>
++#include <linux/consolemap.h>
++
++#include <linux/keyboard.h>
++#include <linux/kbd_kern.h>
++#include <linux/input.h>
++
++MODULE_AUTHOR("samuel.thibault at ens-lyon.org");
++MODULE_DESCRIPTION("braille device");
++MODULE_LICENSE("GPL");
++
++/*
++ * Braille device support part.
++ */
++
++/* Emit various sounds */
++static int sound;
++module_param(sound, bool, 0);
++MODULE_PARM_DESC(sound, "emit sounds");
++
++static void beep(unsigned int freq)
++{
++ if (sound)
++ kd_mksound(freq, HZ/10);
++}
++
++/* mini console */
++#define WIDTH 40
++#define BRAILLE_KEY KEY_INSERT
++static u16 console_buf[WIDTH];
++static int console_cursor;
++
++/* mini view of VC */
++static int vc_x, vc_y, lastvc_x, lastvc_y;
++
++/* show console ? (or show VC) */
++static int console_show = 1;
++/* pending newline ? */
++static int console_newline = 1;
++static int lastVC = -1;
++
++static struct console *braille_co;
++
++/* Very VisioBraille-specific */
++static void braille_write(u16 *buf)
++{
++ static u16 lastwrite[WIDTH];
++ unsigned char data[1 + 1 + 2*WIDTH + 2 + 1], csum = 0, *c;
++ u16 out;
++ int i;
++
++ if (!braille_co)
++ return;
++
++ if (!memcmp(lastwrite, buf, WIDTH * sizeof(*buf)))
++ return;
++ memcpy(lastwrite, buf, WIDTH * sizeof(*buf));
++
++#define SOH 1
++#define STX 2
++#define ETX 2
++#define EOT 4
++#define ENQ 5
++ data[0] = STX;
++ data[1] = '>';
++ csum ^= '>';
++ c = &data[2];
++ for (i = 0; i < WIDTH; i++) {
++ out = buf[i];
++ if (out >= 0x100)
++ out = '?';
++ else if (out == 0x00)
++ out = ' ';
++ csum ^= out;
++ if (out <= 0x05) {
++ *c++ = SOH;
++ out |= 0x40;
++ }
++ *c++ = out;
++ }
++
++ if (csum <= 0x05) {
++ *c++ = SOH;
++ csum |= 0x40;
++ }
++ *c++ = csum;
++ *c++ = ETX;
++
++ braille_co->write(braille_co, data, c - data);
++}
++
++/* Follow the VC cursor*/
++static void vc_follow_cursor(struct vc_data *vc)
++{
++ vc_x = vc->vc_x - (vc->vc_x % WIDTH);
++ vc_y = vc->vc_y;
++ lastvc_x = vc->vc_x;
++ lastvc_y = vc->vc_y;
++}
++
++/* Maybe the VC cursor moved, if so follow it */
++static void vc_maybe_cursor_moved(struct vc_data *vc)
++{
++ if (vc->vc_x != lastvc_x || vc->vc_y != lastvc_y)
++ vc_follow_cursor(vc);
++}
++
++/* Show portion of VC at vc_x, vc_y */
++static void vc_refresh(struct vc_data *vc)
++{
++ u16 buf[WIDTH];
++ int i;
++
++ for (i = 0; i < WIDTH; i++) {
++ u16 glyph = screen_glyph(vc,
++ 2 * (vc_x + i) + vc_y * vc->vc_size_row);
++ buf[i] = inverse_translate(vc, glyph, 1);
++ }
++ braille_write(buf);
++}
++
++/*
++ * Link to keyboard
++ */
++
++static int keyboard_notifier_call(struct notifier_block *blk,
++ unsigned long code, void *_param)
++{
++ struct keyboard_notifier_param *param = _param;
++ struct vc_data *vc = param->vc;
++ int ret = NOTIFY_OK;
++
++ if (!param->down)
++ return ret;
++
++ switch (code) {
++ case KBD_KEYCODE:
++ if (console_show) {
++ if (param->value == BRAILLE_KEY) {
++ console_show = 0;
++ beep(880);
++ vc_maybe_cursor_moved(vc);
++ vc_refresh(vc);
++ ret = NOTIFY_STOP;
++ }
++ } else {
++ ret = NOTIFY_STOP;
++ switch (param->value) {
++ case KEY_INSERT:
++ beep(440);
++ console_show = 1;
++ lastVC = -1;
++ braille_write(console_buf);
++ break;
++ case KEY_LEFT:
++ if (vc_x > 0) {
++ vc_x -= WIDTH;
++ if (vc_x < 0)
++ vc_x = 0;
++ } else if (vc_y >= 1) {
++ beep(880);
++ vc_y--;
++ vc_x = vc->vc_cols-WIDTH;
++ } else
++ beep(220);
++ break;
++ case KEY_RIGHT:
++ if (vc_x + WIDTH < vc->vc_cols) {
++ vc_x += WIDTH;
++ } else if (vc_y + 1 < vc->vc_rows) {
++ beep(880);
++ vc_y++;
++ vc_x = 0;
++ } else
++ beep(220);
++ break;
++ case KEY_DOWN:
++ if (vc_y + 1 < vc->vc_rows)
++ vc_y++;
++ else
++ beep(220);
++ break;
++ case KEY_UP:
++ if (vc_y >= 1)
++ vc_y--;
++ else
++ beep(220);
++ break;
++ case KEY_HOME:
++ vc_follow_cursor(vc);
++ break;
++ case KEY_PAGEUP:
++ vc_x = 0;
++ vc_y = 0;
++ break;
++ case KEY_PAGEDOWN:
++ vc_x = 0;
++ vc_y = vc->vc_rows-1;
++ break;
++ default:
++ ret = NOTIFY_OK;
++ break;
++ }
++ if (ret == NOTIFY_STOP)
++ vc_refresh(vc);
++ }
++ break;
++ case KBD_POST_KEYSYM:
++ {
++ unsigned char type = KTYP(param->value) - 0xf0;
++ if (type == KT_SPEC) {
++ unsigned char val = KVAL(param->value);
++ int on_off = -1;
++
++ switch (val) {
++ case KVAL(K_CAPS):
++ on_off = vc_kbd_led(kbd_table + fg_console,
++ VC_CAPSLOCK);
++ break;
++ case KVAL(K_NUM):
++ on_off = vc_kbd_led(kbd_table + fg_console,
++ VC_NUMLOCK);
++ break;
++ case KVAL(K_HOLD):
++ on_off = vc_kbd_led(kbd_table + fg_console,
++ VC_SCROLLOCK);
++ break;
++ }
++ if (on_off == 1)
++ beep(880);
++ else if (on_off == 0)
++ beep(440);
++ }
++ }
++ case KBD_UNBOUND_KEYCODE:
++ case KBD_UNICODE:
++ case KBD_KEYSYM:
++ /* Unused */
++ break;
++ }
++ return ret;
++}
++
++static struct notifier_block keyboard_notifier_block = {
++ .notifier_call = keyboard_notifier_call,
++};
++
++static int vt_notifier_call(struct notifier_block *blk,
++ unsigned long code, void *_param)
++{
++ struct vt_notifier_param *param = _param;
++ struct vc_data *vc = param->vc;
++ switch (code) {
++ case VT_ALLOCATE:
++ break;
++ case VT_DEALLOCATE:
++ break;
++ case VT_WRITE:
++ {
++ unsigned char c = param->c;
++ if (vc->vc_num != fg_console)
++ break;
++ switch (c) {
++ case '\b':
++ case 127:
++ if (console_cursor > 0) {
++ console_cursor--;
++ console_buf[console_cursor] = ' ';
++ }
++ break;
++ case '\n':
++ case '\v':
++ case '\f':
++ case '\r':
++ console_newline = 1;
++ break;
++ case '\t':
++ c = ' ';
++ /* Fallthrough */
++ default:
++ if (c < 32)
++ /* Ignore other control sequences */
++ break;
++ if (console_newline) {
++ memset(console_buf, 0, sizeof(console_buf));
++ console_cursor = 0;
++ console_newline = 0;
++ }
++ if (console_cursor == WIDTH)
++ memmove(console_buf, &console_buf[1],
++ (WIDTH-1) * sizeof(*console_buf));
++ else
++ console_cursor++;
++ console_buf[console_cursor-1] = c;
++ break;
++ }
++ if (console_show)
++ braille_write(console_buf);
++ else {
++ vc_maybe_cursor_moved(vc);
++ vc_refresh(vc);
++ }
++ break;
++ }
++ case VT_UPDATE:
++ /* Maybe a VT switch, flush */
++ if (console_show) {
++ if (vc->vc_num != lastVC) {
++ lastVC = vc->vc_num;
++ memset(console_buf, 0, sizeof(console_buf));
++ console_cursor = 0;
++ braille_write(console_buf);
++ }
++ } else {
++ vc_maybe_cursor_moved(vc);
++ vc_refresh(vc);
++ }
++ break;
++ }
++ return NOTIFY_OK;
++}
++
++static struct notifier_block vt_notifier_block = {
++ .notifier_call = vt_notifier_call,
++};
++
++/*
++ * Called from printk.c when console=brl is given
++ */
++
++int braille_register_console(struct console *console, int index,
++ char *console_options, char *braille_options)
++{
++ int ret;
++ if (!console_options)
++ /* Only support VisioBraille for now */
++ console_options = "57600o8";
++ if (braille_co)
++ return -ENODEV;
++ if (console->setup) {
++ ret = console->setup(console, console_options);
++ if (ret != 0)
++ return ret;
++ }
++ console->flags |= CON_ENABLED;
++ console->index = index;
++ braille_co = console;
++ return 0;
++}
++
++int braille_unregister_console(struct console *console)
++{
++ if (braille_co != console)
++ return -EINVAL;
++ braille_co = NULL;
++ return 0;
++}
++
++static int __init braille_init(void)
++{
++ register_keyboard_notifier(&keyboard_notifier_block);
++ register_vt_notifier(&vt_notifier_block);
++ return 0;
++}
++
++console_initcall(braille_init);
+diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
+index b4f5e85..c52fca8 100644
+--- a/drivers/acpi/Kconfig
++++ b/drivers/acpi/Kconfig
+@@ -140,6 +140,7 @@ config ACPI_VIDEO
+ tristate "Video"
+ depends on X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL
+ depends on INPUT
++ select THERMAL
+ help
+ This driver implement the ACPI Extensions For Display Adapters
+ for integrated graphics devices on motherboard, as specified in
+@@ -151,6 +152,7 @@ config ACPI_VIDEO
+
+ config ACPI_FAN
+ tristate "Fan"
++ select THERMAL
+ default y
+ help
+ This driver adds support for ACPI fan devices, allowing user-mode
+@@ -172,6 +174,7 @@ config ACPI_BAY
+
+ config ACPI_PROCESSOR
+ tristate "Processor"
++ select THERMAL
+ default y
+ help
+ This driver installs ACPI as the idle handler for Linux, and uses
+diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
+index 76b9bea..5b73f6a 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},
+ };
+@@ -92,6 +92,7 @@ struct acpi_ac {
+
+ #ifdef CONFIG_ACPI_PROCFS_POWER
+ static const struct file_operations acpi_ac_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_ac_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -195,16 +196,11 @@ static int acpi_ac_add_fs(struct acpi_device *device)
+ }
+
+ /* 'state' [R] */
+- entry = create_proc_entry(ACPI_AC_FILE_STATE,
+- S_IRUGO, acpi_device_dir(device));
++ entry = proc_create_data(ACPI_AC_FILE_STATE,
++ S_IRUGO, acpi_device_dir(device),
++ &acpi_ac_fops, acpi_driver_data(device));
+ if (!entry)
+ return -ENODEV;
+- else {
+- entry->proc_fops = &acpi_ac_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
+-
+ return 0;
+ }
+
+diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
+index d5729d5..b1c723f 100644
+--- a/drivers/acpi/battery.c
++++ b/drivers/acpi/battery.c
+@@ -741,15 +741,13 @@ static int acpi_battery_add_fs(struct acpi_device *device)
+ }
+
+ for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
+- entry = create_proc_entry(acpi_battery_file[i].name,
+- acpi_battery_file[i].mode, acpi_device_dir(device));
++ entry = proc_create_data(acpi_battery_file[i].name,
++ acpi_battery_file[i].mode,
++ acpi_device_dir(device),
++ &acpi_battery_file[i].ops,
++ acpi_driver_data(device));
+ if (!entry)
+ return -ENODEV;
+- else {
+- entry->proc_fops = &acpi_battery_file[i].ops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
+ }
+ return 0;
+ }
+diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c
+index 1fa8681..d2fc941 100644
+--- a/drivers/acpi/bay.c
++++ b/drivers/acpi/bay.c
+@@ -201,6 +201,7 @@ static int is_ejectable_bay(acpi_handle handle)
+ return 0;
+ }
+
++#if 0
+ /**
+ * eject_removable_drive - try to eject this drive
+ * @dev : the device structure of the drive
+@@ -225,6 +226,7 @@ int eject_removable_drive(struct device *dev)
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(eject_removable_drive);
++#endif /* 0 */
+
+ static int acpi_bay_add_fs(struct bay *bay)
+ {
+diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
+index 2d1955c..a6dbcf4 100644
+--- a/drivers/acpi/bus.c
++++ b/drivers/acpi/bus.c
+@@ -35,6 +35,7 @@
+ #ifdef CONFIG_X86
+ #include <asm/mpspec.h>
+ #endif
++#include <linux/pci.h>
+ #include <acpi/acpi_bus.h>
+ #include <acpi/acpi_drivers.h>
+
+@@ -784,6 +785,7 @@ static int __init acpi_init(void)
+ result = acpi_bus_init();
+
+ if (!result) {
++ pci_mmcfg_late_init();
+ if (!(pm_flags & PM_APM))
+ pm_flags |= PM_ACPI;
+ else {
+diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
+index 6c5da83..1dfec41 100644
+--- a/drivers/acpi/button.c
++++ b/drivers/acpi/button.c
+@@ -102,6 +102,7 @@ struct acpi_button {
+ };
+
+ static const struct file_operations acpi_button_info_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_button_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -109,6 +110,7 @@ static const struct file_operations acpi_button_info_fops = {
+ };
+
+ static const struct file_operations acpi_button_state_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_button_state_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -207,27 +209,21 @@ static int acpi_button_add_fs(struct acpi_device *device)
+ acpi_device_dir(device)->owner = THIS_MODULE;
+
+ /* 'info' [R] */
+- entry = create_proc_entry(ACPI_BUTTON_FILE_INFO,
+- S_IRUGO, acpi_device_dir(device));
++ entry = proc_create_data(ACPI_BUTTON_FILE_INFO,
++ S_IRUGO, acpi_device_dir(device),
++ &acpi_button_info_fops,
++ acpi_driver_data(device));
+ if (!entry)
+ return -ENODEV;
+- else {
+- entry->proc_fops = &acpi_button_info_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
+
+ /* show lid state [R] */
+ if (button->type == ACPI_BUTTON_TYPE_LID) {
+- entry = create_proc_entry(ACPI_BUTTON_FILE_STATE,
+- S_IRUGO, acpi_device_dir(device));
++ entry = proc_create_data(ACPI_BUTTON_FILE_STATE,
++ S_IRUGO, acpi_device_dir(device),
++ &acpi_button_state_fops,
++ acpi_driver_data(device));
+ if (!entry)
+ return -ENODEV;
+- else {
+- entry->proc_fops = &acpi_button_state_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
+ }
+
+ return 0;
+diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c
+index f049639..c780783 100644
+--- a/drivers/acpi/dispatcher/dsfield.c
++++ b/drivers/acpi/dispatcher/dsfield.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -89,12 +89,16 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
+
+ ACPI_FUNCTION_TRACE(ds_create_buffer_field);
+
+- /* Get the name_string argument */
+-
++ /*
++ * Get the name_string argument (name of the new buffer_field)
++ */
+ if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
++
++ /* For create_field, name is the 4th argument */
++
+ arg = acpi_ps_get_arg(op, 3);
+ } else {
+- /* Create Bit/Byte/Word/Dword field */
++ /* For all other create_xXXField operators, name is the 3rd argument */
+
+ arg = acpi_ps_get_arg(op, 2);
+ }
+@@ -107,26 +111,30 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
+ node = walk_state->deferred_node;
+ status = AE_OK;
+ } else {
+- /*
+- * During the load phase, we want to enter the name of the field into
+- * the namespace. During the execute phase (when we evaluate the size
+- * operand), we want to lookup the name
+- */
+- if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) {
+- flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE;
+- } else {
+- flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
+- ACPI_NS_ERROR_IF_FOUND;
++ /* Execute flag should always be set when this function is entered */
++
++ if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
++ return_ACPI_STATUS(AE_AML_INTERNAL);
+ }
+
+- /*
+- * Enter the name_string into the namespace
+- */
++ /* Creating new namespace node, should not already exist */
++
++ flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
++ ACPI_NS_ERROR_IF_FOUND;
++
++ /* Mark node temporary if we are executing a method */
++
++ if (walk_state->method_node) {
++ flags |= ACPI_NS_TEMPORARY;
++ }
++
++ /* Enter the name_string into the namespace */
++
+ status =
+ acpi_ns_lookup(walk_state->scope_info,
+ arg->common.value.string, ACPI_TYPE_ANY,
+ ACPI_IMODE_LOAD_PASS1, flags, walk_state,
+- &(node));
++ &node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
+ return_ACPI_STATUS(status);
+@@ -136,13 +144,13 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
+ /*
+ * We could put the returned object (Node) on the object stack for later,
+ * but for now, we will put it in the "op" object that the parser uses,
+- * so we can get it again at the end of this scope
++ * so we can get it again at the end of this scope.
+ */
+ op->common.node = node;
+
+ /*
+ * If there is no object attached to the node, this node was just created
+- * and we need to create the field object. Otherwise, this was a lookup
++ * and we need to create the field object. Otherwise, this was a lookup
+ * of an existing node and we don't want to create the field object again.
+ */
+ obj_desc = acpi_ns_get_attached_object(node);
+@@ -164,9 +172,8 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
+ }
+
+ /*
+- * Remember location in AML stream of the field unit
+- * opcode and operands -- since the buffer and index
+- * operands must be evaluated.
++ * Remember location in AML stream of the field unit opcode and operands --
++ * since the buffer and index operands must be evaluated.
+ */
+ second_desc = obj_desc->common.next_object;
+ second_desc->extra.aml_start = op->named.data;
+@@ -261,7 +268,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
+
+ case AML_INT_NAMEDFIELD_OP:
+
+- /* Lookup the name */
++ /* Lookup the name, it should already exist */
+
+ status = acpi_ns_lookup(walk_state->scope_info,
+ (char *)&arg->named.name,
+@@ -272,20 +279,23 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
+ if (ACPI_FAILURE(status)) {
+ ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
+ status);
+- if (status != AE_ALREADY_EXISTS) {
+- return_ACPI_STATUS(status);
+- }
+-
+- /* Already exists, ignore error */
++ return_ACPI_STATUS(status);
+ } else {
+ arg->common.node = info->field_node;
+ info->field_bit_length = arg->common.value.size;
+
+- /* Create and initialize an object for the new Field Node */
+-
+- status = acpi_ex_prep_field_value(info);
+- if (ACPI_FAILURE(status)) {
+- return_ACPI_STATUS(status);
++ /*
++ * If there is no object attached to the node, this node was
++ * just created and we need to create the field object.
++ * Otherwise, this was a lookup of an existing node and we
++ * don't want to create the field object again.
++ */
++ if (!acpi_ns_get_attached_object
++ (info->field_node)) {
++ status = acpi_ex_prep_field_value(info);
++ if (ACPI_FAILURE(status)) {
++ return_ACPI_STATUS(status);
++ }
+ }
+ }
+
+@@ -399,9 +409,27 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
+ union acpi_parse_object *arg = NULL;
+ struct acpi_namespace_node *node;
+ u8 type = 0;
++ u32 flags;
+
+ ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op);
+
++ /* Execute flag should always be set when this function is entered */
++
++ if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
++ if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) {
++
++ /* bank_field Op is deferred, just return OK */
++
++ return_ACPI_STATUS(AE_OK);
++ }
++
++ return_ACPI_STATUS(AE_AML_INTERNAL);
++ }
++
++ /*
++ * Get the field_list argument for this opcode. This is the start of the
++ * list of field elements.
++ */
+ switch (walk_state->opcode) {
+ case AML_FIELD_OP:
+ arg = acpi_ps_get_arg(op, 2);
+@@ -422,20 +450,33 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
++ if (!arg) {
++ return_ACPI_STATUS(AE_AML_NO_OPERAND);
++ }
++
++ /* Creating new namespace node(s), should not already exist */
++
++ flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
++ ACPI_NS_ERROR_IF_FOUND;
++
++ /* Mark node(s) temporary if we are executing a method */
++
++ if (walk_state->method_node) {
++ flags |= ACPI_NS_TEMPORARY;
++ }
++
+ /*
+ * Walk the list of entries in the field_list
+ */
+ while (arg) {
+-
+- /* Ignore OFFSET and ACCESSAS terms here */
+-
++ /*
++ * Ignore OFFSET and ACCESSAS terms here; we are only interested in the
++ * field names in order to enter them into the namespace.
++ */
+ if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
+ status = acpi_ns_lookup(walk_state->scope_info,
+- (char *)&arg->named.name,
+- type, ACPI_IMODE_LOAD_PASS1,
+- ACPI_NS_NO_UPSEARCH |
+- ACPI_NS_DONT_OPEN_SCOPE |
+- ACPI_NS_ERROR_IF_FOUND,
++ (char *)&arg->named.name, type,
++ ACPI_IMODE_LOAD_PASS1, flags,
+ walk_state, &node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
+@@ -452,7 +493,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
+ arg->common.node = node;
+ }
+
+- /* Move to next field in the list */
++ /* Get the next field element in the list */
+
+ arg = arg->common.next;
+ }
+@@ -466,7 +507,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
+ *
+ * PARAMETERS: Op - Op containing the Field definition and args
+ * region_node - Object for the containing Operation Region
+- * ` walk_state - Current method state
++ * walk_state - Current method state
+ *
+ * RETURN: Status
+ *
+@@ -513,36 +554,13 @@ acpi_ds_create_bank_field(union acpi_parse_object *op,
+ return_ACPI_STATUS(status);
+ }
+
+- /* Third arg is the bank_value */
+-
+- /* TBD: This arg is a term_arg, not a constant, and must be evaluated */
+-
++ /*
++ * Third arg is the bank_value
++ * This arg is a term_arg, not a constant
++ * It will be evaluated later, by acpi_ds_eval_bank_field_operands
++ */
+ arg = arg->common.next;
+
+- /* Currently, only the following constants are supported */
+-
+- switch (arg->common.aml_opcode) {
+- case AML_ZERO_OP:
+- info.bank_value = 0;
+- break;
+-
+- case AML_ONE_OP:
+- info.bank_value = 1;
+- break;
+-
+- case AML_BYTE_OP:
+- case AML_WORD_OP:
+- case AML_DWORD_OP:
+- case AML_QWORD_OP:
+- info.bank_value = (u32) arg->common.value.integer;
+- break;
+-
+- default:
+- info.bank_value = 0;
+- ACPI_ERROR((AE_INFO,
+- "Non-constant BankValue for BankField is not implemented"));
+- }
+-
+ /* Fourth arg is the field flags */
+
+ arg = arg->common.next;
+@@ -553,8 +571,17 @@ acpi_ds_create_bank_field(union acpi_parse_object *op,
+ info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD;
+ info.region_node = region_node;
+
+- status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
++ /*
++ * Use Info.data_register_node to store bank_field Op
++ * It's safe because data_register_node will never be used when create bank field
++ * We store aml_start and aml_length in the bank_field Op for late evaluation
++ * Used in acpi_ex_prep_field_value(Info)
++ *
++ * TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"?
++ */
++ info.data_register_node = (struct acpi_namespace_node *)op;
+
++ status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
+ return_ACPI_STATUS(status);
+ }
+
+diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c
+index af923c3..610b1ee 100644
+--- a/drivers/acpi/dispatcher/dsinit.c
++++ b/drivers/acpi/dispatcher/dsinit.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
+index 1cbe619..e48a3ea 100644
+--- a/drivers/acpi/dispatcher/dsmethod.c
++++ b/drivers/acpi/dispatcher/dsmethod.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -42,7 +42,6 @@
+ */
+
+ #include <acpi/acpi.h>
+-#include <acpi/acparser.h>
+ #include <acpi/amlcode.h>
+ #include <acpi/acdispat.h>
+ #include <acpi/acinterp.h>
+@@ -102,7 +101,7 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state)
+ walk_state->opcode,
+ walk_state->aml_offset,
+ NULL);
+- (void)acpi_ex_enter_interpreter();
++ acpi_ex_enter_interpreter();
+ }
+ #ifdef ACPI_DISASSEMBLER
+ if (ACPI_FAILURE(status)) {
+@@ -232,9 +231,9 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
+ * recursive call.
+ */
+ if (!walk_state ||
+- !obj_desc->method.mutex->mutex.owner_thread ||
+- (walk_state->thread !=
+- obj_desc->method.mutex->mutex.owner_thread)) {
++ !obj_desc->method.mutex->mutex.thread_id ||
++ (walk_state->thread->thread_id !=
++ obj_desc->method.mutex->mutex.thread_id)) {
+ /*
+ * Acquire the method mutex. This releases the interpreter if we
+ * block (and reacquires it before it returns)
+@@ -254,8 +253,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
+ original_sync_level =
+ walk_state->thread->current_sync_level;
+
+- obj_desc->method.mutex->mutex.owner_thread =
+- walk_state->thread;
++ obj_desc->method.mutex->mutex.thread_id =
++ walk_state->thread->thread_id;
+ walk_state->thread->current_sync_level =
+ obj_desc->method.sync_level;
+ } else {
+@@ -535,8 +534,6 @@ void
+ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
+ struct acpi_walk_state *walk_state)
+ {
+- struct acpi_namespace_node *method_node;
+- acpi_status status;
+
+ ACPI_FUNCTION_TRACE_PTR(ds_terminate_control_method, walk_state);
+
+@@ -551,34 +548,26 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
+ /* Delete all arguments and locals */
+
+ acpi_ds_method_data_delete_all(walk_state);
+- }
+
+- /*
+- * If method is serialized, release the mutex and restore the
+- * current sync level for this thread
+- */
+- if (method_desc->method.mutex) {
++ /*
++ * If method is serialized, release the mutex and restore the
++ * current sync level for this thread
++ */
++ if (method_desc->method.mutex) {
+
+- /* Acquisition Depth handles recursive calls */
++ /* Acquisition Depth handles recursive calls */
+
+- method_desc->method.mutex->mutex.acquisition_depth--;
+- if (!method_desc->method.mutex->mutex.acquisition_depth) {
+- walk_state->thread->current_sync_level =
+- method_desc->method.mutex->mutex.
+- original_sync_level;
++ method_desc->method.mutex->mutex.acquisition_depth--;
++ if (!method_desc->method.mutex->mutex.acquisition_depth) {
++ walk_state->thread->current_sync_level =
++ method_desc->method.mutex->mutex.
++ original_sync_level;
+
+- acpi_os_release_mutex(method_desc->method.mutex->mutex.
+- os_mutex);
+- method_desc->method.mutex->mutex.owner_thread = NULL;
++ acpi_os_release_mutex(method_desc->method.
++ mutex->mutex.os_mutex);
++ method_desc->method.mutex->mutex.thread_id = 0;
++ }
+ }
+- }
+-
+- if (walk_state) {
+- /*
+- * Delete any objects created by this method during execution.
+- * The method Node is stored in the walk state
+- */
+- method_node = walk_state->method_node;
+
+ /*
+ * Delete any namespace objects created anywhere within
+@@ -620,7 +609,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
+ */
+ if ((method_desc->method.method_flags & AML_METHOD_SERIALIZED)
+ && (!method_desc->method.mutex)) {
+- status = acpi_ds_create_method_mutex(method_desc);
++ (void)acpi_ds_create_method_mutex(method_desc);
+ }
+
+ /* No more threads, we can free the owner_id */
+diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c
+index ba4626e..13c43ea 100644
+--- a/drivers/acpi/dispatcher/dsmthdat.c
++++ b/drivers/acpi/dispatcher/dsmthdat.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c
+index 954ac8c..1022e38 100644
+--- a/drivers/acpi/dispatcher/dsobject.c
++++ b/drivers/acpi/dispatcher/dsobject.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -157,7 +157,9 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
+ * will remain as named references. This behavior is not described
+ * in the ACPI spec, but it appears to be an oversight.
+ */
+- obj_desc = (union acpi_operand_object *)op->common.node;
++ obj_desc =
++ ACPI_CAST_PTR(union acpi_operand_object,
++ op->common.node);
+
+ status =
+ acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
+@@ -172,7 +174,19 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
+ switch (op->common.node->type) {
+ /*
+ * For these types, we need the actual node, not the subobject.
+- * However, the subobject got an extra reference count above.
++ * However, the subobject did not get an extra reference count above.
++ *
++ * TBD: should ex_resolve_node_to_value be changed to fix this?
++ */
++ case ACPI_TYPE_DEVICE:
++ case ACPI_TYPE_THERMAL:
++
++ acpi_ut_add_reference(op->common.node->object);
++
++ /*lint -fallthrough */
++ /*
++ * For these types, we need the actual node, not the subobject.
++ * The subobject got an extra reference count in ex_resolve_node_to_value.
+ */
+ case ACPI_TYPE_MUTEX:
+ case ACPI_TYPE_METHOD:
+@@ -180,25 +194,15 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
+ case ACPI_TYPE_PROCESSOR:
+ case ACPI_TYPE_EVENT:
+ case ACPI_TYPE_REGION:
+- case ACPI_TYPE_DEVICE:
+- case ACPI_TYPE_THERMAL:
+
+- obj_desc =
+- (union acpi_operand_object *)op->common.
+- node;
++ /* We will create a reference object for these types below */
+ break;
+
+ default:
+- break;
+- }
+-
+- /*
+- * If above resolved to an operand object, we are done. Otherwise,
+- * we have a NS node, we must create the package entry as a named
+- * reference.
+- */
+- if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) !=
+- ACPI_DESC_TYPE_NAMED) {
++ /*
++ * All other types - the node was resolved to an actual
++ * object, we are done.
++ */
+ goto exit;
+ }
+ }
+@@ -223,7 +227,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
+
+ exit:
+ *obj_desc_ptr = obj_desc;
+- return_ACPI_STATUS(AE_OK);
++ return_ACPI_STATUS(status);
+ }
+
+ /*******************************************************************************
+@@ -369,7 +373,9 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *parent;
+ union acpi_operand_object *obj_desc = NULL;
+ acpi_status status = AE_OK;
+- acpi_native_uint i;
++ unsigned i;
++ u16 index;
++ u16 reference_count;
+
+ ACPI_FUNCTION_TRACE(ds_build_internal_package_obj);
+
+@@ -447,13 +453,60 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
+ package.
+ elements[i]);
+ }
++
++ if (*obj_desc_ptr) {
++
++ /* Existing package, get existing reference count */
++
++ reference_count =
++ (*obj_desc_ptr)->common.reference_count;
++ if (reference_count > 1) {
++
++ /* Make new element ref count match original ref count */
++
++ for (index = 0; index < (reference_count - 1);
++ index++) {
++ acpi_ut_add_reference((obj_desc->
++ package.
++ elements[i]));
++ }
++ }
++ }
++
+ arg = arg->common.next;
+ }
+
+- if (!arg) {
++ /* Check for match between num_elements and actual length of package_list */
++
++ if (arg) {
++ /*
++ * num_elements was exhausted, but there are remaining elements in the
++ * package_list.
++ *
++ * Note: technically, this is an error, from ACPI spec: "It is an error
++ * for NumElements to be less than the number of elements in the
++ * PackageList". However, for now, we just print an error message and
++ * no exception is returned.
++ */
++ while (arg) {
++
++ /* Find out how many elements there really are */
++
++ i++;
++ arg = arg->common.next;
++ }
++
++ ACPI_ERROR((AE_INFO,
++ "Package List length (%X) larger than NumElements count (%X), truncated\n",
++ i, element_count));
++ } else if (i < element_count) {
++ /*
++ * Arg list (elements) was exhausted, but we did not reach num_elements count.
++ * Note: this is not an error, the package is padded out with NULLs.
++ */
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+- "Package List length larger than NumElements count (%X), truncated\n",
+- element_count));
++ "Package List length (%X) smaller than NumElements count (%X), padded with null elements\n",
++ i, element_count));
+ }
+
+ obj_desc->package.flags |= AOPOBJ_DATA_VALID;
+@@ -721,6 +774,8 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
+ /* Node was saved in Op */
+
+ obj_desc->reference.node = op->common.node;
++ obj_desc->reference.object =
++ op->common.node->object;
+ }
+
+ obj_desc->reference.opcode = opcode;
+diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
+index f501e08..a818e0d 100644
+--- a/drivers/acpi/dispatcher/dsopcode.c
++++ b/drivers/acpi/dispatcher/dsopcode.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -49,6 +49,7 @@
+ #include <acpi/acinterp.h>
+ #include <acpi/acnamesp.h>
+ #include <acpi/acevents.h>
++#include <acpi/actables.h>
+
+ #define _COMPONENT ACPI_DISPATCHER
+ ACPI_MODULE_NAME("dsopcode")
+@@ -219,6 +220,50 @@ acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)
+
+ /*******************************************************************************
+ *
++ * FUNCTION: acpi_ds_get_bank_field_arguments
++ *
++ * PARAMETERS: obj_desc - A valid bank_field object
++ *
++ * RETURN: Status.
++ *
++ * DESCRIPTION: Get bank_field bank_value. This implements the late
++ * evaluation of these field attributes.
++ *
++ ******************************************************************************/
++
++acpi_status
++acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc)
++{
++ union acpi_operand_object *extra_desc;
++ struct acpi_namespace_node *node;
++ acpi_status status;
++
++ ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc);
++
++ if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
++ return_ACPI_STATUS(AE_OK);
++ }
++
++ /* Get the AML pointer (method object) and bank_field node */
++
++ extra_desc = acpi_ns_get_secondary_object(obj_desc);
++ node = obj_desc->bank_field.node;
++
++ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
++ (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL));
++ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n",
++ acpi_ut_get_node_name(node)));
++
++ /* Execute the AML code for the term_arg arguments */
++
++ status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
++ extra_desc->extra.aml_length,
++ extra_desc->extra.aml_start);
++ return_ACPI_STATUS(status);
++}
++
++/*******************************************************************************
++ *
+ * FUNCTION: acpi_ds_get_buffer_arguments
+ *
+ * PARAMETERS: obj_desc - A valid Buffer object
+@@ -770,7 +815,109 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
+
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
+ obj_desc,
+- ACPI_FORMAT_UINT64(obj_desc->region.address),
++ ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address),
++ obj_desc->region.length));
++
++ /* Now the address and length are valid for this opregion */
++
++ obj_desc->region.flags |= AOPOBJ_DATA_VALID;
++
++ return_ACPI_STATUS(status);
++}
++
++/*******************************************************************************
++ *
++ * FUNCTION: acpi_ds_eval_table_region_operands
++ *
++ * PARAMETERS: walk_state - Current walk
++ * Op - A valid region Op object
++ *
++ * RETURN: Status
++ *
++ * DESCRIPTION: Get region address and length
++ * Called from acpi_ds_exec_end_op during data_table_region parse tree walk
++ *
++ ******************************************************************************/
++
++acpi_status
++acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
++ union acpi_parse_object *op)
++{
++ acpi_status status;
++ union acpi_operand_object *obj_desc;
++ union acpi_operand_object **operand;
++ struct acpi_namespace_node *node;
++ union acpi_parse_object *next_op;
++ acpi_native_uint table_index;
++ struct acpi_table_header *table;
++
++ ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);
++
++ /*
++ * This is where we evaluate the signature_string and oem_iDString
++ * and oem_table_iDString of the data_table_region declaration
++ */
++ node = op->common.node;
++
++ /* next_op points to signature_string op */
++
++ next_op = op->common.value.arg;
++
++ /*
++ * Evaluate/create the signature_string and oem_iDString
++ * and oem_table_iDString operands
++ */
++ status = acpi_ds_create_operands(walk_state, next_op);
++ if (ACPI_FAILURE(status)) {
++ return_ACPI_STATUS(status);
++ }
++
++ /*
++ * Resolve the signature_string and oem_iDString
++ * and oem_table_iDString operands
++ */
++ status = acpi_ex_resolve_operands(op->common.aml_opcode,
++ ACPI_WALK_OPERANDS, walk_state);
++ if (ACPI_FAILURE(status)) {
++ return_ACPI_STATUS(status);
++ }
++
++ ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
++ acpi_ps_get_opcode_name(op->common.aml_opcode),
++ 1, "after AcpiExResolveOperands");
++
++ operand = &walk_state->operands[0];
++
++ /* Find the ACPI table */
++
++ status = acpi_tb_find_table(operand[0]->string.pointer,
++ operand[1]->string.pointer,
++ operand[2]->string.pointer, &table_index);
++ if (ACPI_FAILURE(status)) {
++ return_ACPI_STATUS(status);
++ }
++
++ acpi_ut_remove_reference(operand[0]);
++ acpi_ut_remove_reference(operand[1]);
++ acpi_ut_remove_reference(operand[2]);
++
++ status = acpi_get_table_by_index(table_index, &table);
++ if (ACPI_FAILURE(status)) {
++ return_ACPI_STATUS(status);
++ }
++
++ obj_desc = acpi_ns_get_attached_object(node);
++ if (!obj_desc) {
++ return_ACPI_STATUS(AE_NOT_EXIST);
++ }
++
++ obj_desc->region.address =
++ (acpi_physical_address) ACPI_TO_INTEGER(table);
++ obj_desc->region.length = table->length;
++
++ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
++ obj_desc,
++ ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address),
+ obj_desc->region.length));
+
+ /* Now the address and length are valid for this opregion */
+@@ -808,6 +955,12 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
+
+ /* The first operand (for all of these data objects) is the length */
+
++ /*
++ * Set proper index into operand stack for acpi_ds_obj_stack_push
++ * invoked inside acpi_ds_create_operand.
++ */
++ walk_state->operand_index = walk_state->num_operands;
++
+ status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+@@ -878,6 +1031,106 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
+
+ /*******************************************************************************
+ *
++ * FUNCTION: acpi_ds_eval_bank_field_operands
++ *
++ * PARAMETERS: walk_state - Current walk
++ * Op - A valid bank_field Op object
++ *
++ * RETURN: Status
++ *
++ * DESCRIPTION: Get bank_field bank_value
++ * Called from acpi_ds_exec_end_op during bank_field parse tree walk
++ *
++ ******************************************************************************/
++
++acpi_status
++acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,
++ union acpi_parse_object *op)
++{
++ acpi_status status;
++ union acpi_operand_object *obj_desc;
++ union acpi_operand_object *operand_desc;
++ struct acpi_namespace_node *node;
++ union acpi_parse_object *next_op;
++ union acpi_parse_object *arg;
++
++ ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op);
++
++ /*
++ * This is where we evaluate the bank_value field of the
++ * bank_field declaration
++ */
++
++ /* next_op points to the op that holds the Region */
++
++ next_op = op->common.value.arg;
++
++ /* next_op points to the op that holds the Bank Register */
++
++ next_op = next_op->common.next;
++
++ /* next_op points to the op that holds the Bank Value */
++
++ next_op = next_op->common.next;
++
++ /*
++ * Set proper index into operand stack for acpi_ds_obj_stack_push
++ * invoked inside acpi_ds_create_operand.
++ *
++ * We use walk_state->Operands[0] to store the evaluated bank_value
++ */
++ walk_state->operand_index = 0;
++
++ status = acpi_ds_create_operand(walk_state, next_op, 0);
++ if (ACPI_FAILURE(status)) {
++ return_ACPI_STATUS(status);
++ }
++
++ status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state);
++ if (ACPI_FAILURE(status)) {
++ return_ACPI_STATUS(status);
++ }
++
++ ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
++ acpi_ps_get_opcode_name(op->common.aml_opcode),
++ 1, "after AcpiExResolveOperands");
++
++ /*
++ * Get the bank_value operand and save it
++ * (at Top of stack)
++ */
++ operand_desc = walk_state->operands[0];
++
++ /* Arg points to the start Bank Field */
++
++ arg = acpi_ps_get_arg(op, 4);
++ while (arg) {
++
++ /* Ignore OFFSET and ACCESSAS terms here */
++
++ if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
++ node = arg->common.node;
++
++ obj_desc = acpi_ns_get_attached_object(node);
++ if (!obj_desc) {
++ return_ACPI_STATUS(AE_NOT_EXIST);
++ }
++
++ obj_desc->bank_field.value =
++ (u32) operand_desc->integer.value;
++ }
++
++ /* Move to next field in the list */
++
++ arg = arg->common.next;
++ }
++
++ acpi_ut_remove_reference(operand_desc);
++ return_ACPI_STATUS(status);
++}
++
++/*******************************************************************************
++ *
+ * FUNCTION: acpi_ds_exec_begin_control_op
+ *
+ * PARAMETERS: walk_list - The list that owns the walk stack
+@@ -1070,8 +1323,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
+ * is set to anything other than zero!
+ */
+ walk_state->return_desc = walk_state->operands[0];
+- } else if ((walk_state->results) &&
+- (walk_state->results->results.num_results > 0)) {
++ } else if (walk_state->result_count) {
+
+ /* Since we have a real Return(), delete any implicit return */
+
+diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c
+index 71503c0..b398982 100644
+--- a/drivers/acpi/dispatcher/dsutils.c
++++ b/drivers/acpi/dispatcher/dsutils.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -278,7 +278,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
+ AML_VAR_PACKAGE_OP)
+ || (op->common.parent->common.aml_opcode == AML_BUFFER_OP)
+ || (op->common.parent->common.aml_opcode ==
+- AML_INT_EVAL_SUBTREE_OP)) {
++ AML_INT_EVAL_SUBTREE_OP)
++ || (op->common.parent->common.aml_opcode ==
++ AML_BANK_FIELD_OP)) {
+ /*
+ * These opcodes allow term_arg(s) as operands and therefore
+ * the operands can be method calls. The result is used.
+@@ -472,7 +474,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
+ /* A valid name must be looked up in the namespace */
+
+ if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
+- (arg->common.value.string)) {
++ (arg->common.value.string) &&
++ !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n",
+ arg));
+
+@@ -595,7 +598,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
+ } else {
+ /* Check for null name case */
+
+- if (arg->common.aml_opcode == AML_INT_NAMEPATH_OP) {
++ if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
++ !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
+ /*
+ * If the name is null, this means that this is an
+ * optional result parameter that was not specified
+@@ -617,7 +621,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
+ return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
+ }
+
+- if (op_info->flags & AML_HAS_RETVAL) {
++ if ((op_info->flags & AML_HAS_RETVAL)
++ || (arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Argument previously created, already stacked\n"));
+
+@@ -630,9 +635,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
+ * Use value that was already previously returned
+ * by the evaluation of this argument
+ */
+- status =
+- acpi_ds_result_pop_from_bottom(&obj_desc,
+- walk_state);
++ status = acpi_ds_result_pop(&obj_desc, walk_state);
+ if (ACPI_FAILURE(status)) {
+ /*
+ * Only error is underflow, and this indicates
+@@ -698,27 +701,52 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state,
+ {
+ acpi_status status = AE_OK;
+ union acpi_parse_object *arg;
++ union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS];
+ u32 arg_count = 0;
++ u32 index = walk_state->num_operands;
++ u32 i;
+
+ ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg);
+
+- /* For all arguments in the list... */
++ /* Get all arguments in the list */
+
+ arg = first_arg;
+ while (arg) {
+- status = acpi_ds_create_operand(walk_state, arg, arg_count);
+- if (ACPI_FAILURE(status)) {
+- goto cleanup;
++ if (index >= ACPI_OBJ_NUM_OPERANDS) {
++ return_ACPI_STATUS(AE_BAD_DATA);
+ }
+
+- ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+- "Arg #%d (%p) done, Arg1=%p\n", arg_count,
+- arg, first_arg));
++ arguments[index] = arg;
++ walk_state->operands[index] = NULL;
+
+ /* Move on to next argument, if any */
+
+ arg = arg->common.next;
+ arg_count++;
++ index++;
++ }
++
++ index--;
++
++ /* It is the appropriate order to get objects from the Result stack */
++
++ for (i = 0; i < arg_count; i++) {
++ arg = arguments[index];
++
++ /* Force the filling of the operand stack in inverse order */
++
++ walk_state->operand_index = (u8) index;
++
++ status = acpi_ds_create_operand(walk_state, arg, index);
++ if (ACPI_FAILURE(status)) {
++ goto cleanup;
++ }
++
++ index--;
++
++ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
++ "Arg #%d (%p) done, Arg1=%p\n", index, arg,
++ first_arg));
+ }
+
+ return_ACPI_STATUS(status);
+@@ -729,9 +757,112 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state,
+ * pop everything off of the operand stack and delete those
+ * objects
+ */
+- (void)acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);
++ acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);
++
++ ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", index));
++ return_ACPI_STATUS(status);
++}
++
++/*****************************************************************************
++ *
++ * FUNCTION: acpi_ds_evaluate_name_path
++ *
++ * PARAMETERS: walk_state - Current state of the parse tree walk,
++ * the opcode of current operation should be
++ * AML_INT_NAMEPATH_OP
++ *
++ * RETURN: Status
++ *
++ * DESCRIPTION: Translate the -name_path- parse tree object to the equivalent
++ * interpreter object, convert it to value, if needed, duplicate
++ * it, if needed, and push it onto the current result stack.
++ *
++ ****************************************************************************/
++
++acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state)
++{
++ acpi_status status = AE_OK;
++ union acpi_parse_object *op = walk_state->op;
++ union acpi_operand_object **operand = &walk_state->operands[0];
++ union acpi_operand_object *new_obj_desc;
++ u8 type;
++
++ ACPI_FUNCTION_TRACE_PTR(ds_evaluate_name_path, walk_state);
++
++ if (!op->common.parent) {
++
++ /* This happens after certain exception processing */
++
++ goto exit;
++ }
++
++ if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
++ (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) ||
++ (op->common.parent->common.aml_opcode == AML_REF_OF_OP)) {
++
++ /* TBD: Should we specify this feature as a bit of op_info->Flags of these opcodes? */
++
++ goto exit;
++ }
++
++ status = acpi_ds_create_operand(walk_state, op, 0);
++ if (ACPI_FAILURE(status)) {
++ goto exit;
++ }
++
++ if (op->common.flags & ACPI_PARSEOP_TARGET) {
++ new_obj_desc = *operand;
++ goto push_result;
++ }
++
++ type = ACPI_GET_OBJECT_TYPE(*operand);
++
++ status = acpi_ex_resolve_to_value(operand, walk_state);
++ if (ACPI_FAILURE(status)) {
++ goto exit;
++ }
++
++ if (type == ACPI_TYPE_INTEGER) {
++
++ /* It was incremented by acpi_ex_resolve_to_value */
++
++ acpi_ut_remove_reference(*operand);
++
++ status =
++ acpi_ut_copy_iobject_to_iobject(*operand, &new_obj_desc,
++ walk_state);
++ if (ACPI_FAILURE(status)) {
++ goto exit;
++ }
++ } else {
++ /*
++ * The object either was anew created or is
++ * a Namespace node - don't decrement it.
++ */
++ new_obj_desc = *operand;
++ }
++
++ /* Cleanup for name-path operand */
++
++ status = acpi_ds_obj_stack_pop(1, walk_state);
++ if (ACPI_FAILURE(status)) {
++ walk_state->result_obj = new_obj_desc;
++ goto exit;
++ }
++
++ push_result:
++
++ walk_state->result_obj = new_obj_desc;
++
++ status = acpi_ds_result_push(walk_state->result_obj, walk_state);
++ if (ACPI_SUCCESS(status)) {
++
++ /* Force to take it from stack */
++
++ op->common.flags |= ACPI_PARSEOP_IN_STACK;
++ }
++
++ exit:
+
+- ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d",
+- (arg_count + 1)));
+ return_ACPI_STATUS(status);
+ }
+diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
+index 69693fa..b246b96 100644
+--- a/drivers/acpi/dispatcher/dswexec.c
++++ b/drivers/acpi/dispatcher/dswexec.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -285,11 +285,6 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
+ switch (opcode_class) {
+ case AML_CLASS_CONTROL:
+
+- status = acpi_ds_result_stack_push(walk_state);
+- if (ACPI_FAILURE(status)) {
+- goto error_exit;
+- }
+-
+ status = acpi_ds_exec_begin_control_op(walk_state, op);
+ break;
+
+@@ -305,20 +300,11 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
+ status = acpi_ds_load2_begin_op(walk_state, NULL);
+ }
+
+- if (op->common.aml_opcode == AML_REGION_OP) {
+- status = acpi_ds_result_stack_push(walk_state);
+- }
+ break;
+
+ case AML_CLASS_EXECUTE:
+ case AML_CLASS_CREATE:
+- /*
+- * Most operators with arguments (except create_xxx_field operators)
+- * Start a new result/operand state
+- */
+- if (walk_state->op_info->object_type != ACPI_TYPE_BUFFER_FIELD) {
+- status = acpi_ds_result_stack_push(walk_state);
+- }
++
+ break;
+
+ default:
+@@ -374,6 +360,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
+ /* Init the walk state */
+
+ walk_state->num_operands = 0;
++ walk_state->operand_index = 0;
+ walk_state->return_desc = NULL;
+ walk_state->result_obj = NULL;
+
+@@ -388,10 +375,17 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
+ /* Decode the Opcode Class */
+
+ switch (op_class) {
+- case AML_CLASS_ARGUMENT: /* constants, literals, etc. - do nothing */
++ case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */
++
++ if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
++ status = acpi_ds_evaluate_name_path(walk_state);
++ if (ACPI_FAILURE(status)) {
++ goto cleanup;
++ }
++ }
+ break;
+
+- case AML_CLASS_EXECUTE: /* most operators with arguments */
++ case AML_CLASS_EXECUTE: /* Most operators with arguments */
+
+ /* Build resolved operand stack */
+
+@@ -400,13 +394,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
+ goto cleanup;
+ }
+
+- /* Done with this result state (Now that operand stack is built) */
+-
+- status = acpi_ds_result_stack_pop(walk_state);
+- if (ACPI_FAILURE(status)) {
+- goto cleanup;
+- }
+-
+ /*
+ * All opcodes require operand resolution, with the only exceptions
+ * being the object_type and size_of operators.
+@@ -487,16 +474,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
+
+ status = acpi_ds_exec_end_control_op(walk_state, op);
+
+- /* Make sure to properly pop the result stack */
+-
+- if (ACPI_SUCCESS(status)) {
+- status = acpi_ds_result_stack_pop(walk_state);
+- } else if (status == AE_CTRL_PENDING) {
+- status = acpi_ds_result_stack_pop(walk_state);
+- if (ACPI_SUCCESS(status)) {
+- status = AE_CTRL_PENDING;
+- }
+- }
+ break;
+
+ case AML_TYPE_METHOD_CALL:
+@@ -516,7 +493,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
+
+ op->common.node =
+ (struct acpi_namespace_node *)op->asl.value.
+- arg->asl.node->object;
++ arg->asl.node;
+ acpi_ut_add_reference(op->asl.value.arg->asl.
+ node->object);
+ return_ACPI_STATUS(AE_OK);
+@@ -632,13 +609,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
+ break;
+ }
+
+- /* Done with result state (Now that operand stack is built) */
+-
+- status = acpi_ds_result_stack_pop(walk_state);
+- if (ACPI_FAILURE(status)) {
+- goto cleanup;
+- }
+-
+ /*
+ * If a result object was returned from above, push it on the
+ * current result stack
+@@ -671,8 +641,28 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
+ if (ACPI_FAILURE(status)) {
+ break;
+ }
++ } else if (op->common.aml_opcode == AML_DATA_REGION_OP) {
++ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
++ "Executing DataTableRegion Strings Op=%p\n",
++ op));
++
++ status =
++ acpi_ds_eval_table_region_operands
++ (walk_state, op);
++ if (ACPI_FAILURE(status)) {
++ break;
++ }
++ } else if (op->common.aml_opcode == AML_BANK_FIELD_OP) {
++ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
++ "Executing BankField Op=%p\n",
++ op));
+
+- status = acpi_ds_result_stack_pop(walk_state);
++ status =
++ acpi_ds_eval_bank_field_operands(walk_state,
++ op);
++ if (ACPI_FAILURE(status)) {
++ break;
++ }
+ }
+ break;
+
+diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
+index 8ab9d1b..dff7a3e 100644
+--- a/drivers/acpi/dispatcher/dswload.c
++++ b/drivers/acpi/dispatcher/dswload.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -443,6 +443,15 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
++ } else if (op->common.aml_opcode == AML_DATA_REGION_OP) {
++ status =
++ acpi_ex_create_region(op->named.data,
++ op->named.length,
++ REGION_DATA_TABLE,
++ walk_state);
++ if (ACPI_FAILURE(status)) {
++ return_ACPI_STATUS(status);
++ }
+ }
+ }
+ #endif
+@@ -767,6 +776,12 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
+ acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
+ object_type, ACPI_IMODE_LOAD_PASS2, flags,
+ walk_state, &node);
++
++ if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) {
++ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
++ "***New Node [%4.4s] %p is temporary\n",
++ acpi_ut_get_node_name(node), node));
++ }
+ break;
+ }
+
+@@ -823,6 +838,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
+ struct acpi_namespace_node *new_node;
+ #ifndef ACPI_NO_METHOD_EXECUTION
+ u32 i;
++ u8 region_space;
+ #endif
+
+ ACPI_FUNCTION_TRACE(ds_load2_end_op);
+@@ -1003,11 +1019,6 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
+ status = acpi_ex_create_event(walk_state);
+ break;
+
+- case AML_DATA_REGION_OP:
+-
+- status = acpi_ex_create_table_region(walk_state);
+- break;
+-
+ case AML_ALIAS_OP:
+
+ status = acpi_ex_create_alias(walk_state);
+@@ -1035,6 +1046,15 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
+ switch (op->common.aml_opcode) {
+ #ifndef ACPI_NO_METHOD_EXECUTION
+ case AML_REGION_OP:
++ case AML_DATA_REGION_OP:
++
++ if (op->common.aml_opcode == AML_REGION_OP) {
++ region_space = (acpi_adr_space_type)
++ ((op->common.value.arg)->common.value.
++ integer);
++ } else {
++ region_space = REGION_DATA_TABLE;
++ }
+
+ /*
+ * If we are executing a method, initialize the region
+@@ -1043,10 +1063,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
+ status =
+ acpi_ex_create_region(op->named.data,
+ op->named.length,
+- (acpi_adr_space_type)
+- ((op->common.value.
+- arg)->common.value.
+- integer),
++ region_space,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c
+index 3927c49..9e60732 100644
+--- a/drivers/acpi/dispatcher/dswscope.c
++++ b/drivers/acpi/dispatcher/dswscope.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c
+index 5afcdd9..1386ced 100644
+--- a/drivers/acpi/dispatcher/dswstate.c
++++ b/drivers/acpi/dispatcher/dswstate.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -49,85 +49,9 @@
+ #define _COMPONENT ACPI_DISPATCHER
+ ACPI_MODULE_NAME("dswstate")
+
+-/* Local prototypes */
+-#ifdef ACPI_OBSOLETE_FUNCTIONS
+-acpi_status
+-acpi_ds_result_insert(void *object,
+- u32 index, struct acpi_walk_state *walk_state);
+-
+-acpi_status acpi_ds_obj_stack_delete_all(struct acpi_walk_state *walk_state);
+-
+-acpi_status
+-acpi_ds_obj_stack_pop_object(union acpi_operand_object **object,
+- struct acpi_walk_state *walk_state);
+-
+-void *acpi_ds_obj_stack_get_value(u32 index,
+- struct acpi_walk_state *walk_state);
+-#endif
+-
+-#ifdef ACPI_FUTURE_USAGE
+-/*******************************************************************************
+- *
+- * FUNCTION: acpi_ds_result_remove
+- *
+- * PARAMETERS: Object - Where to return the popped object
+- * Index - Where to extract the object
+- * walk_state - Current Walk state
+- *
+- * RETURN: Status
+- *
+- * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In
+- * other words, this is a FIFO.
+- *
+- ******************************************************************************/
+-
+-acpi_status
+-acpi_ds_result_remove(union acpi_operand_object **object,
+- u32 index, struct acpi_walk_state *walk_state)
+-{
+- union acpi_generic_state *state;
+-
+- ACPI_FUNCTION_NAME(ds_result_remove);
+-
+- state = walk_state->results;
+- if (!state) {
+- ACPI_ERROR((AE_INFO, "No result object pushed! State=%p",
+- walk_state));
+- return (AE_NOT_EXIST);
+- }
+-
+- if (index >= ACPI_OBJ_MAX_OPERAND) {
+- ACPI_ERROR((AE_INFO,
+- "Index out of range: %X State=%p Num=%X",
+- index, walk_state, state->results.num_results));
+- }
+-
+- /* Check for a valid result object */
+-
+- if (!state->results.obj_desc[index]) {
+- ACPI_ERROR((AE_INFO,
+- "Null operand! State=%p #Ops=%X, Index=%X",
+- walk_state, state->results.num_results, index));
+- return (AE_AML_NO_RETURN_VALUE);
+- }
+-
+- /* Remove the object */
+-
+- state->results.num_results--;
+-
+- *object = state->results.obj_desc[index];
+- state->results.obj_desc[index] = NULL;
+-
+- ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+- "Obj=%p [%s] Index=%X State=%p Num=%X\n",
+- *object,
+- (*object) ? acpi_ut_get_object_type_name(*object) :
+- "NULL", index, walk_state,
+- state->results.num_results));
+-
+- return (AE_OK);
+-}
+-#endif /* ACPI_FUTURE_USAGE */
++ /* Local prototypes */
++static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *ws);
++static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *ws);
+
+ /*******************************************************************************
+ *
+@@ -138,122 +62,67 @@ acpi_ds_result_remove(union acpi_operand_object **object,
+ *
+ * RETURN: Status
+ *
+- * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In
+- * other words, this is a FIFO.
++ * DESCRIPTION: Pop an object off the top of this walk's result stack
+ *
+ ******************************************************************************/
+
+ acpi_status
+-acpi_ds_result_pop(union acpi_operand_object ** object,
+- struct acpi_walk_state * walk_state)
++acpi_ds_result_pop(union acpi_operand_object **object,
++ struct acpi_walk_state *walk_state)
+ {
+ acpi_native_uint index;
+ union acpi_generic_state *state;
++ acpi_status status;
+
+ ACPI_FUNCTION_NAME(ds_result_pop);
+
+ state = walk_state->results;
+- if (!state) {
+- return (AE_OK);
+- }
+-
+- if (!state->results.num_results) {
+- ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p",
+- walk_state));
+- return (AE_AML_NO_RETURN_VALUE);
+- }
+
+- /* Remove top element */
++ /* Incorrect state of result stack */
+
+- state->results.num_results--;
+-
+- for (index = ACPI_OBJ_NUM_OPERANDS; index; index--) {
+-
+- /* Check for a valid result object */
+-
+- if (state->results.obj_desc[index - 1]) {
+- *object = state->results.obj_desc[index - 1];
+- state->results.obj_desc[index - 1] = NULL;
+-
+- ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+- "Obj=%p [%s] Index=%X State=%p Num=%X\n",
+- *object,
+- (*object) ?
+- acpi_ut_get_object_type_name(*object)
+- : "NULL", (u32) index - 1, walk_state,
+- state->results.num_results));
+-
+- return (AE_OK);
+- }
++ if (state && !walk_state->result_count) {
++ ACPI_ERROR((AE_INFO, "No results on result stack"));
++ return (AE_AML_INTERNAL);
+ }
+
+- ACPI_ERROR((AE_INFO, "No result objects! State=%p", walk_state));
+- return (AE_AML_NO_RETURN_VALUE);
+-}
+-
+-/*******************************************************************************
+- *
+- * FUNCTION: acpi_ds_result_pop_from_bottom
+- *
+- * PARAMETERS: Object - Where to return the popped object
+- * walk_state - Current Walk state
+- *
+- * RETURN: Status
+- *
+- * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In
+- * other words, this is a FIFO.
+- *
+- ******************************************************************************/
+-
+-acpi_status
+-acpi_ds_result_pop_from_bottom(union acpi_operand_object ** object,
+- struct acpi_walk_state * walk_state)
+-{
+- acpi_native_uint index;
+- union acpi_generic_state *state;
++ if (!state && walk_state->result_count) {
++ ACPI_ERROR((AE_INFO, "No result state for result stack"));
++ return (AE_AML_INTERNAL);
++ }
+
+- ACPI_FUNCTION_NAME(ds_result_pop_from_bottom);
++ /* Empty result stack */
+
+- state = walk_state->results;
+ if (!state) {
+- ACPI_ERROR((AE_INFO,
+- "No result object pushed! State=%p", walk_state));
+- return (AE_NOT_EXIST);
+- }
+-
+- if (!state->results.num_results) {
+- ACPI_ERROR((AE_INFO, "No result objects! State=%p",
++ ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p",
+ walk_state));
+ return (AE_AML_NO_RETURN_VALUE);
+ }
+
+- /* Remove Bottom element */
+-
+- *object = state->results.obj_desc[0];
+-
+- /* Push entire stack down one element */
+-
+- for (index = 0; index < state->results.num_results; index++) {
+- state->results.obj_desc[index] =
+- state->results.obj_desc[index + 1];
+- }
++ /* Return object of the top element and clean that top element result stack */
+
+- state->results.num_results--;
+-
+- /* Check for a valid result object */
++ walk_state->result_count--;
++ index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM;
+
++ *object = state->results.obj_desc[index];
+ if (!*object) {
+ ACPI_ERROR((AE_INFO,
+- "Null operand! State=%p #Ops=%X Index=%X",
+- walk_state, state->results.num_results,
+- (u32) index));
++ "No result objects on result stack, State=%p",
++ walk_state));
+ return (AE_AML_NO_RETURN_VALUE);
+ }
+
+- ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] Results=%p State=%p\n",
+- *object,
+- (*object) ? acpi_ut_get_object_type_name(*object) :
+- "NULL", state, walk_state));
++ state->results.obj_desc[index] = NULL;
++ if (index == 0) {
++ status = acpi_ds_result_stack_pop(walk_state);
++ if (ACPI_FAILURE(status)) {
++ return (status);
++ }
++ }
++
++ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
++ "Obj=%p [%s] Index=%X State=%p Num=%X\n", *object,
++ acpi_ut_get_object_type_name(*object),
++ (u32) index, walk_state, walk_state->result_count));
+
+ return (AE_OK);
+ }
+@@ -276,39 +145,56 @@ acpi_ds_result_push(union acpi_operand_object * object,
+ struct acpi_walk_state * walk_state)
+ {
+ union acpi_generic_state *state;
++ acpi_status status;
++ acpi_native_uint index;
+
+ ACPI_FUNCTION_NAME(ds_result_push);
+
++ if (walk_state->result_count > walk_state->result_size) {
++ ACPI_ERROR((AE_INFO, "Result stack is full"));
++ return (AE_AML_INTERNAL);
++ } else if (walk_state->result_count == walk_state->result_size) {
++
++ /* Extend the result stack */
++
++ status = acpi_ds_result_stack_push(walk_state);
++ if (ACPI_FAILURE(status)) {
++ ACPI_ERROR((AE_INFO,
++ "Failed to extend the result stack"));
++ return (status);
++ }
++ }
++
++ if (!(walk_state->result_count < walk_state->result_size)) {
++ ACPI_ERROR((AE_INFO, "No free elements in result stack"));
++ return (AE_AML_INTERNAL);
++ }
++
+ state = walk_state->results;
+ if (!state) {
+ ACPI_ERROR((AE_INFO, "No result stack frame during push"));
+ return (AE_AML_INTERNAL);
+ }
+
+- if (state->results.num_results == ACPI_OBJ_NUM_OPERANDS) {
+- ACPI_ERROR((AE_INFO,
+- "Result stack overflow: Obj=%p State=%p Num=%X",
+- object, walk_state, state->results.num_results));
+- return (AE_STACK_OVERFLOW);
+- }
+-
+ if (!object) {
+ ACPI_ERROR((AE_INFO,
+ "Null Object! Obj=%p State=%p Num=%X",
+- object, walk_state, state->results.num_results));
++ object, walk_state, walk_state->result_count));
+ return (AE_BAD_PARAMETER);
+ }
+
+- state->results.obj_desc[state->results.num_results] = object;
+- state->results.num_results++;
++ /* Assign the address of object to the top free element of result stack */
++
++ index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM;
++ state->results.obj_desc[index] = object;
++ walk_state->result_count++;
+
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
+ object,
+- object ?
+ acpi_ut_get_object_type_name((union
+ acpi_operand_object *)
+- object) : "NULL",
+- walk_state, state->results.num_results,
++ object), walk_state,
++ walk_state->result_count,
+ walk_state->current_result));
+
+ return (AE_OK);
+@@ -322,16 +208,25 @@ acpi_ds_result_push(union acpi_operand_object * object,
+ *
+ * RETURN: Status
+ *
+- * DESCRIPTION: Push an object onto the walk_state result stack.
++ * DESCRIPTION: Push an object onto the walk_state result stack
+ *
+ ******************************************************************************/
+
+-acpi_status acpi_ds_result_stack_push(struct acpi_walk_state * walk_state)
++static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *walk_state)
+ {
+ union acpi_generic_state *state;
+
+ ACPI_FUNCTION_NAME(ds_result_stack_push);
+
++ /* Check for stack overflow */
++
++ if (((u32) walk_state->result_size + ACPI_RESULTS_FRAME_OBJ_NUM) >
++ ACPI_RESULTS_OBJ_NUM_MAX) {
++ ACPI_ERROR((AE_INFO, "Result stack overflow: State=%p Num=%X",
++ walk_state, walk_state->result_size));
++ return (AE_STACK_OVERFLOW);
++ }
++
+ state = acpi_ut_create_generic_state();
+ if (!state) {
+ return (AE_NO_MEMORY);
+@@ -340,6 +235,10 @@ acpi_status acpi_ds_result_stack_push(struct acpi_walk_state * walk_state)
+ state->common.descriptor_type = ACPI_DESC_TYPE_STATE_RESULT;
+ acpi_ut_push_generic_state(&walk_state->results, state);
+
++ /* Increase the length of the result stack by the length of frame */
++
++ walk_state->result_size += ACPI_RESULTS_FRAME_OBJ_NUM;
++
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n",
+ state, walk_state));
+
+@@ -354,11 +253,11 @@ acpi_status acpi_ds_result_stack_push(struct acpi_walk_state * walk_state)
+ *
+ * RETURN: Status
+ *
+- * DESCRIPTION: Pop an object off of the walk_state result stack.
++ * DESCRIPTION: Pop an object off of the walk_state result stack
+ *
+ ******************************************************************************/
+
+-acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state * walk_state)
++static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state)
+ {
+ union acpi_generic_state *state;
+
+@@ -367,18 +266,27 @@ acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state * walk_state)
+ /* Check for stack underflow */
+
+ if (walk_state->results == NULL) {
+- ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Underflow - State=%p\n",
++ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
++ "Result stack underflow - State=%p\n",
+ walk_state));
+ return (AE_AML_NO_OPERAND);
+ }
+
++ if (walk_state->result_size < ACPI_RESULTS_FRAME_OBJ_NUM) {
++ ACPI_ERROR((AE_INFO, "Insufficient result stack size"));
++ return (AE_AML_INTERNAL);
++ }
++
+ state = acpi_ut_pop_generic_state(&walk_state->results);
++ acpi_ut_delete_generic_state(state);
++
++ /* Decrease the length of result stack by the length of frame */
++
++ walk_state->result_size -= ACPI_RESULTS_FRAME_OBJ_NUM;
+
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Result=%p RemainingResults=%X State=%p\n",
+- state, state->results.num_results, walk_state));
+-
+- acpi_ut_delete_generic_state(state);
++ state, walk_state->result_count, walk_state));
+
+ return (AE_OK);
+ }
+@@ -412,9 +320,13 @@ acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state)
+
+ /* Put the object onto the stack */
+
+- walk_state->operands[walk_state->num_operands] = object;
++ walk_state->operands[walk_state->operand_index] = object;
+ walk_state->num_operands++;
+
++ /* For the usual order of filling the operand stack */
++
++ walk_state->operand_index++;
++
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
+ object,
+ acpi_ut_get_object_type_name((union
+@@ -484,43 +396,36 @@ acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state * walk_state)
+ *
+ ******************************************************************************/
+
+-acpi_status
++void
+ acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
+- struct acpi_walk_state * walk_state)
++ struct acpi_walk_state *walk_state)
+ {
+- u32 i;
++ acpi_native_int i;
+ union acpi_operand_object *obj_desc;
+
+ ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete);
+
+- for (i = 0; i < pop_count; i++) {
+-
+- /* Check for stack underflow */
++ if (pop_count == 0) {
++ return;
++ }
+
++ for (i = (acpi_native_int) (pop_count - 1); i >= 0; i--) {
+ if (walk_state->num_operands == 0) {
+- ACPI_ERROR((AE_INFO,
+- "Object stack underflow! Count=%X State=%p #Ops=%X",
+- pop_count, walk_state,
+- walk_state->num_operands));
+- return (AE_STACK_UNDERFLOW);
++ return;
+ }
+
+ /* Pop the stack and delete an object if present in this stack entry */
+
+ walk_state->num_operands--;
+- obj_desc = walk_state->operands[walk_state->num_operands];
++ obj_desc = walk_state->operands[i];
+ if (obj_desc) {
+- acpi_ut_remove_reference(walk_state->
+- operands[walk_state->
+- num_operands]);
+- walk_state->operands[walk_state->num_operands] = NULL;
++ acpi_ut_remove_reference(walk_state->operands[i]);
++ walk_state->operands[i] = NULL;
+ }
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
+ pop_count, walk_state, walk_state->num_operands));
+-
+- return (AE_OK);
+ }
+
+ /*******************************************************************************
+@@ -560,7 +465,7 @@ struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state
+ *
+ * RETURN: None
+ *
+- * DESCRIPTION: Place the Thread state at the head of the state list.
++ * DESCRIPTION: Place the Thread state at the head of the state list
+ *
+ ******************************************************************************/
+
+@@ -636,7 +541,6 @@ struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union
+ *thread)
+ {
+ struct acpi_walk_state *walk_state;
+- acpi_status status;
+
+ ACPI_FUNCTION_TRACE(ds_create_walk_state);
+
+@@ -659,14 +563,6 @@ struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union
+ acpi_ds_method_data_init(walk_state);
+ #endif
+
+- /* Create an initial result stack entry */
+-
+- status = acpi_ds_result_stack_push(walk_state);
+- if (ACPI_FAILURE(status)) {
+- ACPI_FREE(walk_state);
+- return_PTR(NULL);
+- }
+-
+ /* Put the new state at the head of the walk list */
+
+ if (thread) {
+@@ -860,190 +756,3 @@ void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state)
+ ACPI_FREE(walk_state);
+ return_VOID;
+ }
+-
+-#ifdef ACPI_OBSOLETE_FUNCTIONS
+-/*******************************************************************************
+- *
+- * FUNCTION: acpi_ds_result_insert
+- *
+- * PARAMETERS: Object - Object to push
+- * Index - Where to insert the object
+- * walk_state - Current Walk state
+- *
+- * RETURN: Status
+- *
+- * DESCRIPTION: Insert an object onto this walk's result stack
+- *
+- ******************************************************************************/
+-
+-acpi_status
+-acpi_ds_result_insert(void *object,
+- u32 index, struct acpi_walk_state *walk_state)
+-{
+- union acpi_generic_state *state;
+-
+- ACPI_FUNCTION_NAME(ds_result_insert);
+-
+- state = walk_state->results;
+- if (!state) {
+- ACPI_ERROR((AE_INFO, "No result object pushed! State=%p",
+- walk_state));
+- return (AE_NOT_EXIST);
+- }
+-
+- if (index >= ACPI_OBJ_NUM_OPERANDS) {
+- ACPI_ERROR((AE_INFO,
+- "Index out of range: %X Obj=%p State=%p Num=%X",
+- index, object, walk_state,
+- state->results.num_results));
+- return (AE_BAD_PARAMETER);
+- }
+-
+- if (!object) {
+- ACPI_ERROR((AE_INFO,
+- "Null Object! Index=%X Obj=%p State=%p Num=%X",
+- index, object, walk_state,
+- state->results.num_results));
+- return (AE_BAD_PARAMETER);
+- }
+-
+- state->results.obj_desc[index] = object;
+- state->results.num_results++;
+-
+- ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+- "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
+- object,
+- object ?
+- acpi_ut_get_object_type_name((union
+- acpi_operand_object *)
+- object) : "NULL",
+- walk_state, state->results.num_results,
+- walk_state->current_result));
+-
+- return (AE_OK);
+-}
+-
+-/*******************************************************************************
+- *
+- * FUNCTION: acpi_ds_obj_stack_delete_all
+- *
+- * PARAMETERS: walk_state - Current Walk state
+- *
+- * RETURN: Status
+- *
+- * DESCRIPTION: Clear the object stack by deleting all objects that are on it.
+- * Should be used with great care, if at all!
+- *
+- ******************************************************************************/
+-
+-acpi_status acpi_ds_obj_stack_delete_all(struct acpi_walk_state * walk_state)
+-{
+- u32 i;
+-
+- ACPI_FUNCTION_TRACE_PTR(ds_obj_stack_delete_all, walk_state);
+-
+- /* The stack size is configurable, but fixed */
+-
+- for (i = 0; i < ACPI_OBJ_NUM_OPERANDS; i++) {
+- if (walk_state->operands[i]) {
+- acpi_ut_remove_reference(walk_state->operands[i]);
+- walk_state->operands[i] = NULL;
+- }
+- }
+-
+- return_ACPI_STATUS(AE_OK);
+-}
+-
+-/*******************************************************************************
+- *
+- * FUNCTION: acpi_ds_obj_stack_pop_object
+- *
+- * PARAMETERS: Object - Where to return the popped object
+- * walk_state - Current Walk state
+- *
+- * RETURN: Status
+- *
+- * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
+- * deleted by this routine.
+- *
+- ******************************************************************************/
+-
+-acpi_status
+-acpi_ds_obj_stack_pop_object(union acpi_operand_object **object,
+- struct acpi_walk_state *walk_state)
+-{
+- ACPI_FUNCTION_NAME(ds_obj_stack_pop_object);
+-
+- /* Check for stack underflow */
+-
+- if (walk_state->num_operands == 0) {
+- ACPI_ERROR((AE_INFO,
+- "Missing operand/stack empty! State=%p #Ops=%X",
+- walk_state, walk_state->num_operands));
+- *object = NULL;
+- return (AE_AML_NO_OPERAND);
+- }
+-
+- /* Pop the stack */
+-
+- walk_state->num_operands--;
+-
+- /* Check for a valid operand */
+-
+- if (!walk_state->operands[walk_state->num_operands]) {
+- ACPI_ERROR((AE_INFO,
+- "Null operand! State=%p #Ops=%X",
+- walk_state, walk_state->num_operands));
+- *object = NULL;
+- return (AE_AML_NO_OPERAND);
+- }
+-
+- /* Get operand and set stack entry to null */
+-
+- *object = walk_state->operands[walk_state->num_operands];
+- walk_state->operands[walk_state->num_operands] = NULL;
+-
+- ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
+- *object, acpi_ut_get_object_type_name(*object),
+- walk_state, walk_state->num_operands));
+-
+- return (AE_OK);
+-}
+-
+-/*******************************************************************************
+- *
+- * FUNCTION: acpi_ds_obj_stack_get_value
+- *
+- * PARAMETERS: Index - Stack index whose value is desired. Based
+- * on the top of the stack (index=0 == top)
+- * walk_state - Current Walk state
+- *
+- * RETURN: Pointer to the requested operand
+- *
+- * DESCRIPTION: Retrieve an object from this walk's operand stack. Index must
+- * be within the range of the current stack pointer.
+- *
+- ******************************************************************************/
+-
+-void *acpi_ds_obj_stack_get_value(u32 index, struct acpi_walk_state *walk_state)
+-{
+-
+- ACPI_FUNCTION_TRACE_PTR(ds_obj_stack_get_value, walk_state);
+-
+- /* Can't do it if the stack is empty */
+-
+- if (walk_state->num_operands == 0) {
+- return_PTR(NULL);
+- }
+-
+- /* or if the index is past the top of the stack */
+-
+- if (index > (walk_state->num_operands - (u32) 1)) {
+- return_PTR(NULL);
+- }
+-
+- return_PTR(walk_state->
+- operands[(acpi_native_uint) (walk_state->num_operands - 1) -
+- index]);
+-}
+-#endif
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index 7222a18..0924992 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -73,38 +73,14 @@ enum ec_event {
+
+ #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */
+ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
++#define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */
+
+ enum {
+ EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */
+ EC_FLAGS_QUERY_PENDING, /* Query is pending */
+ EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */
+- EC_FLAGS_NO_ADDRESS_GPE, /* Expect GPE only for non-address event */
+- EC_FLAGS_ADDRESS, /* Address is being written */
+- EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */
+- EC_FLAGS_WDATA, /* Data is being written */
+- EC_FLAGS_NO_OBF1_GPE, /* Don't expect GPE before read */
+-};
+-
+-static int acpi_ec_remove(struct acpi_device *device, int type);
+-static int acpi_ec_start(struct acpi_device *device);
+-static int acpi_ec_stop(struct acpi_device *device, int type);
+-static int acpi_ec_add(struct acpi_device *device);
+-
+-static const struct acpi_device_id ec_device_ids[] = {
+- {"PNP0C09", 0},
+- {"", 0},
+-};
+-
+-static struct acpi_driver acpi_ec_driver = {
+- .name = "ec",
+- .class = ACPI_EC_CLASS,
+- .ids = ec_device_ids,
+- .ops = {
+- .add = acpi_ec_add,
+- .remove = acpi_ec_remove,
+- .start = acpi_ec_start,
+- .stop = acpi_ec_stop,
+- },
++ EC_FLAGS_NO_GPE, /* Don't use GPE mode */
++ EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */
+ };
+
+ /* If we find an EC via the ECDT, we need to keep a ptr to its context */
+@@ -129,6 +105,8 @@ static struct acpi_ec {
+ struct mutex lock;
+ wait_queue_head_t wait;
+ struct list_head list;
++ struct delayed_work work;
++ atomic_t irq_count;
+ u8 handlers_installed;
+ } *boot_ec, *first_ec;
+
+@@ -177,65 +155,52 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
+ return 0;
+ }
+
+-static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
++static void ec_schedule_ec_poll(struct acpi_ec *ec)
+ {
+- int ret = 0;
++ if (test_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags))
++ schedule_delayed_work(&ec->work,
++ msecs_to_jiffies(ACPI_EC_DELAY));
++}
++
++static void ec_switch_to_poll_mode(struct acpi_ec *ec)
++{
++ set_bit(EC_FLAGS_NO_GPE, &ec->flags);
++ clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
++ acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
++ set_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags);
++}
+
+- if (unlikely(event == ACPI_EC_EVENT_OBF_1 &&
+- test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags)))
+- force_poll = 1;
+- if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) &&
+- test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags)))
+- force_poll = 1;
+- if (unlikely(test_bit(EC_FLAGS_WDATA, &ec->flags) &&
+- test_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags)))
+- force_poll = 1;
++static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
++{
++ atomic_set(&ec->irq_count, 0);
+ if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) &&
+ likely(!force_poll)) {
+ if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event),
+ msecs_to_jiffies(ACPI_EC_DELAY)))
+- goto end;
++ return 0;
+ clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
+ if (acpi_ec_check_status(ec, event)) {
+- if (event == ACPI_EC_EVENT_OBF_1) {
+- /* miss OBF_1 GPE, don't expect it */
+- pr_info(PREFIX "missing OBF confirmation, "
+- "don't expect it any longer.\n");
+- set_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags);
+- } else if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) {
+- /* miss address GPE, don't expect it anymore */
+- pr_info(PREFIX "missing address confirmation, "
+- "don't expect it any longer.\n");
+- set_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags);
+- } else if (test_bit(EC_FLAGS_WDATA, &ec->flags)) {
+- /* miss write data GPE, don't expect it */
+- pr_info(PREFIX "missing write data confirmation, "
+- "don't expect it any longer.\n");
+- set_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags);
+- } else {
+- /* missing GPEs, switch back to poll mode */
+- if (printk_ratelimit())
+- pr_info(PREFIX "missing confirmations, "
++ /* missing GPEs, switch back to poll mode */
++ if (printk_ratelimit())
++ pr_info(PREFIX "missing confirmations, "
+ "switch off interrupt mode.\n");
+- clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
+- }
+- goto end;
++ ec_switch_to_poll_mode(ec);
++ ec_schedule_ec_poll(ec);
++ return 0;
+ }
+ } else {
+ unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
+ clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
+ while (time_before(jiffies, delay)) {
+ if (acpi_ec_check_status(ec, event))
+- goto end;
++ return 0;
++ udelay(ACPI_EC_UDELAY);
+ }
+ }
+- pr_err(PREFIX "acpi_ec_wait timeout,"
+- " status = %d, expect_event = %d\n",
+- acpi_ec_read_status(ec), event);
+- ret = -ETIME;
+- end:
+- clear_bit(EC_FLAGS_ADDRESS, &ec->flags);
+- return ret;
++ pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n",
++ acpi_ec_read_status(ec),
++ (event == ACPI_EC_EVENT_OBF_1) ? "\"b0=1\"" : "\"b1=0\"");
++ return -ETIME;
+ }
+
+ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
+@@ -245,8 +210,8 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
+ {
+ int result = 0;
+ set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
+- acpi_ec_write_cmd(ec, command);
+ pr_debug(PREFIX "transaction start\n");
++ acpi_ec_write_cmd(ec, command);
+ for (; wdata_len > 0; --wdata_len) {
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
+ if (result) {
+@@ -254,15 +219,11 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
+ "write_cmd timeout, command = %d\n", command);
+ goto end;
+ }
+- /* mark the address byte written to EC */
+- if (rdata_len + wdata_len > 1)
+- set_bit(EC_FLAGS_ADDRESS, &ec->flags);
+ set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
+ acpi_ec_write_data(ec, *(wdata++));
+ }
+
+ if (!rdata_len) {
+- set_bit(EC_FLAGS_WDATA, &ec->flags);
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
+ if (result) {
+ pr_err(PREFIX
+@@ -527,47 +488,51 @@ static u32 acpi_ec_gpe_handler(void *data)
+ {
+ acpi_status status = AE_OK;
+ struct acpi_ec *ec = data;
++ u8 state = acpi_ec_read_status(ec);
+
+ pr_debug(PREFIX "~~~> interrupt\n");
++ atomic_inc(&ec->irq_count);
++ if (atomic_read(&ec->irq_count) > 5) {
++ pr_err(PREFIX "GPE storm detected, disabling EC GPE\n");
++ ec_switch_to_poll_mode(ec);
++ goto end;
++ }
+ clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
+ if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))
+ wake_up(&ec->wait);
+
+- if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI) {
++ if (state & ACPI_EC_FLAG_SCI) {
+ if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
+ status = acpi_os_execute(OSL_EC_BURST_HANDLER,
+ acpi_ec_gpe_query, ec);
+- } else if (unlikely(!test_bit(EC_FLAGS_GPE_MODE, &ec->flags))) {
++ } else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
++ !test_bit(EC_FLAGS_NO_GPE, &ec->flags) &&
++ in_interrupt()) {
+ /* this is non-query, must be confirmation */
+ if (printk_ratelimit())
+ pr_info(PREFIX "non-query interrupt received,"
+ " switching to interrupt mode\n");
+ set_bit(EC_FLAGS_GPE_MODE, &ec->flags);
++ clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags);
+ }
+-
++end:
++ ec_schedule_ec_poll(ec);
+ return ACPI_SUCCESS(status) ?
+ ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
+ }
+
++static void do_ec_poll(struct work_struct *work)
++{
++ struct acpi_ec *ec = container_of(work, struct acpi_ec, work.work);
++ atomic_set(&ec->irq_count, 0);
++ (void)acpi_ec_gpe_handler(ec);
++}
++
+ /* --------------------------------------------------------------------------
+ Address Space Management
+ -------------------------------------------------------------------------- */
+
+ static acpi_status
+-acpi_ec_space_setup(acpi_handle region_handle,
+- u32 function, void *handler_context, void **return_context)
+-{
+- /*
+- * The EC object is in the handler context and is needed
+- * when calling the acpi_ec_space_handler.
+- */
+- *return_context = (function != ACPI_REGION_DEACTIVATE) ?
+- handler_context : NULL;
+-
+- return AE_OK;
+-}
+-
+-static acpi_status
+ acpi_ec_space_handler(u32 function, acpi_physical_address address,
+ u32 bits, acpi_integer *value,
+ void *handler_context, void *region_context)
+@@ -669,16 +634,11 @@ static int acpi_ec_add_fs(struct acpi_device *device)
+ return -ENODEV;
+ }
+
+- entry = create_proc_entry(ACPI_EC_FILE_INFO, S_IRUGO,
+- acpi_device_dir(device));
++ entry = proc_create_data(ACPI_EC_FILE_INFO, S_IRUGO,
++ acpi_device_dir(device),
++ &acpi_ec_info_ops, acpi_driver_data(device));
+ if (!entry)
+ return -ENODEV;
+- else {
+- entry->proc_fops = &acpi_ec_info_ops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
+-
+ return 0;
+ }
+
+@@ -709,6 +669,8 @@ static struct acpi_ec *make_acpi_ec(void)
+ mutex_init(&ec->lock);
+ init_waitqueue_head(&ec->wait);
+ INIT_LIST_HEAD(&ec->list);
++ INIT_DELAYED_WORK_DEFERRABLE(&ec->work, do_ec_poll);
++ atomic_set(&ec->irq_count, 0);
+ return ec;
+ }
+
+@@ -741,17 +703,21 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
+ status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe);
+ if (ACPI_FAILURE(status))
+ return status;
+- /* Find and register all query methods */
+- acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1,
+- acpi_ec_register_query_methods, ec, NULL);
+ /* Use the global lock for all EC transactions? */
+ acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
+ ec->handle = handle;
+ return AE_CTRL_TERMINATE;
+ }
+
++static void ec_poll_stop(struct acpi_ec *ec)
++{
++ clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags);
++ cancel_delayed_work(&ec->work);
++}
++
+ static void ec_remove_handlers(struct acpi_ec *ec)
+ {
++ ec_poll_stop(ec);
+ if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
+ ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
+ pr_err(PREFIX "failed to remove space handler\n");
+@@ -771,31 +737,28 @@ static int acpi_ec_add(struct acpi_device *device)
+ strcpy(acpi_device_class(device), ACPI_EC_CLASS);
+
+ /* Check for boot EC */
+- if (boot_ec) {
+- if (boot_ec->handle == device->handle) {
+- /* Pre-loaded EC from DSDT, just move pointer */
+- ec = boot_ec;
+- boot_ec = NULL;
+- goto end;
+- } else if (boot_ec->handle == ACPI_ROOT_OBJECT) {
+- /* ECDT-based EC, time to shut it down */
+- ec_remove_handlers(boot_ec);
+- kfree(boot_ec);
+- first_ec = boot_ec = NULL;
++ if (boot_ec &&
++ (boot_ec->handle == device->handle ||
++ boot_ec->handle == ACPI_ROOT_OBJECT)) {
++ ec = boot_ec;
++ boot_ec = NULL;
++ } else {
++ ec = make_acpi_ec();
++ if (!ec)
++ return -ENOMEM;
++ if (ec_parse_device(device->handle, 0, ec, NULL) !=
++ AE_CTRL_TERMINATE) {
++ kfree(ec);
++ return -EINVAL;
+ }
+ }
+
+- ec = make_acpi_ec();
+- if (!ec)
+- return -ENOMEM;
+-
+- if (ec_parse_device(device->handle, 0, ec, NULL) !=
+- AE_CTRL_TERMINATE) {
+- kfree(ec);
+- return -EINVAL;
+- }
+ ec->handle = device->handle;
+- end:
++
++ /* Find and register all query methods */
++ acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1,
++ acpi_ec_register_query_methods, ec, NULL);
++
+ if (!first_ec)
+ first_ec = ec;
+ acpi_driver_data(device) = ec;
+@@ -870,7 +833,7 @@ static int ec_install_handlers(struct acpi_ec *ec)
+ status = acpi_install_address_space_handler(ec->handle,
+ ACPI_ADR_SPACE_EC,
+ &acpi_ec_space_handler,
+- &acpi_ec_space_setup, ec);
++ NULL, ec);
+ if (ACPI_FAILURE(status)) {
+ acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler);
+ return -ENODEV;
+@@ -897,6 +860,7 @@ static int acpi_ec_start(struct acpi_device *device)
+
+ /* EC is fully operational, allow queries */
+ clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
++ ec_schedule_ec_poll(ec);
+ return ret;
+ }
+
+@@ -924,6 +888,11 @@ int __init acpi_boot_ec_enable(void)
+ return -EFAULT;
+ }
+
++static const struct acpi_device_id ec_device_ids[] = {
++ {"PNP0C09", 0},
++ {"", 0},
++};
++
+ int __init acpi_ec_ecdt_probe(void)
+ {
+ int ret;
+@@ -944,6 +913,7 @@ int __init acpi_ec_ecdt_probe(void)
+ boot_ec->data_addr = ecdt_ptr->data.address;
+ boot_ec->gpe = ecdt_ptr->gpe;
+ boot_ec->handle = ACPI_ROOT_OBJECT;
++ acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle);
+ } else {
+ /* This workaround is needed only on some broken machines,
+ * which require early EC, but fail to provide ECDT */
+@@ -973,6 +943,39 @@ int __init acpi_ec_ecdt_probe(void)
+ return -ENODEV;
+ }
+
++static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state)
++{
++ struct acpi_ec *ec = acpi_driver_data(device);
++ /* Stop using GPE */
++ set_bit(EC_FLAGS_NO_GPE, &ec->flags);
++ clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
++ acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
++ return 0;
++}
++
++static int acpi_ec_resume(struct acpi_device *device)
++{
++ struct acpi_ec *ec = acpi_driver_data(device);
++ /* Enable use of GPE back */
++ clear_bit(EC_FLAGS_NO_GPE, &ec->flags);
++ acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
++ return 0;
++}
++
++static struct acpi_driver acpi_ec_driver = {
++ .name = "ec",
++ .class = ACPI_EC_CLASS,
++ .ids = ec_device_ids,
++ .ops = {
++ .add = acpi_ec_add,
++ .remove = acpi_ec_remove,
++ .start = acpi_ec_start,
++ .stop = acpi_ec_stop,
++ .suspend = acpi_ec_suspend,
++ .resume = acpi_ec_resume,
++ },
++};
++
+ static int __init acpi_ec_init(void)
+ {
+ int result = 0;
+diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
+index abec1ca..0c24bd4 100644
+--- a/drivers/acpi/event.c
++++ b/drivers/acpi/event.c
+@@ -102,6 +102,7 @@ static unsigned int acpi_system_poll_event(struct file *file, poll_table * wait)
+ }
+
+ static const struct file_operations acpi_system_event_ops = {
++ .owner = THIS_MODULE,
+ .open = acpi_system_open_event,
+ .read = acpi_system_read_event,
+ .release = acpi_system_close_event,
+@@ -294,10 +295,9 @@ static int __init acpi_event_init(void)
+
+ #ifdef CONFIG_ACPI_PROC_EVENT
+ /* 'event' [R] */
+- entry = create_proc_entry("event", S_IRUSR, acpi_root_dir);
+- if (entry)
+- entry->proc_fops = &acpi_system_event_ops;
+- else
++ entry = proc_create("event", S_IRUSR, acpi_root_dir,
++ &acpi_system_event_ops);
++ if (!entry)
+ return -ENODEV;
+ #endif
+
+diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
+index 3048801..5d30e5b 100644
+--- a/drivers/acpi/events/evevent.c
++++ b/drivers/acpi/events/evevent.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
+index 0dadd2a..5354be4 100644
+--- a/drivers/acpi/events/evgpe.c
++++ b/drivers/acpi/events/evgpe.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -248,10 +248,6 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
+
+ ACPI_FUNCTION_TRACE(ev_disable_gpe);
+
+- if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) {
+- return_ACPI_STATUS(AE_OK);
+- }
+-
+ /* Make sure HW enable masks are updated */
+
+ status =
+diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c
+index 361ebe6..e6c4d4c 100644
+--- a/drivers/acpi/events/evgpeblk.c
++++ b/drivers/acpi/events/evgpeblk.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
+index 21cb749..2113e58 100644
+--- a/drivers/acpi/events/evmisc.c
++++ b/drivers/acpi/events/evmisc.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -49,22 +49,7 @@
+ #define _COMPONENT ACPI_EVENTS
+ ACPI_MODULE_NAME("evmisc")
+
+-/* Names for Notify() values, used for debug output */
+-#ifdef ACPI_DEBUG_OUTPUT
+-static const char *acpi_notify_value_names[] = {
+- "Bus Check",
+- "Device Check",
+- "Device Wake",
+- "Eject Request",
+- "Device Check Light",
+- "Frequency Mismatch",
+- "Bus Mode Mismatch",
+- "Power Fault"
+-};
+-#endif
+-
+ /* Pointer to FACS needed for the Global Lock */
+-
+ static struct acpi_table_facs *facs = NULL;
+
+ /* Local prototypes */
+@@ -94,7 +79,6 @@ u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node)
+ switch (node->type) {
+ case ACPI_TYPE_DEVICE:
+ case ACPI_TYPE_PROCESSOR:
+- case ACPI_TYPE_POWER:
+ case ACPI_TYPE_THERMAL:
+ /*
+ * These are the ONLY objects that can receive ACPI notifications
+@@ -139,17 +123,9 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
+ * initiate soft-off or sleep operation?
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+- "Dispatching Notify(%X) on node %p\n", notify_value,
+- node));
+-
+- if (notify_value <= 7) {
+- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notify value: %s\n",
+- acpi_notify_value_names[notify_value]));
+- } else {
+- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+- "Notify value: 0x%2.2X **Device Specific**\n",
+- notify_value));
+- }
++ "Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n",
++ acpi_ut_get_node_name(node), node, notify_value,
++ acpi_ut_get_notify_name(notify_value)));
+
+ /* Get the notify object attached to the NS Node */
+
+@@ -159,10 +135,12 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
+ /* We have the notify object, Get the right handler */
+
+ switch (node->type) {
++
++ /* Notify allowed only on these types */
++
+ case ACPI_TYPE_DEVICE:
+ case ACPI_TYPE_THERMAL:
+ case ACPI_TYPE_PROCESSOR:
+- case ACPI_TYPE_POWER:
+
+ if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
+ handler_obj =
+@@ -179,8 +157,13 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
+ }
+ }
+
+- /* If there is any handler to run, schedule the dispatcher */
+-
++ /*
++ * If there is any handler to run, schedule the dispatcher.
++ * Check for:
++ * 1) Global system notify handler
++ * 2) Global device notify handler
++ * 3) Per-device notify handler
++ */
+ if ((acpi_gbl_system_notify.handler
+ && (notify_value <= ACPI_MAX_SYS_NOTIFY))
+ || (acpi_gbl_device_notify.handler
+@@ -190,6 +173,13 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
+ return (AE_NO_MEMORY);
+ }
+
++ if (!handler_obj) {
++ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
++ "Executing system notify handler for Notify (%4.4s, %X) node %p\n",
++ acpi_ut_get_node_name(node),
++ notify_value, node));
++ }
++
+ notify_info->common.descriptor_type =
+ ACPI_DESC_TYPE_STATE_NOTIFY;
+ notify_info->notify.node = node;
+@@ -202,15 +192,12 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_delete_generic_state(notify_info);
+ }
+- }
+-
+- if (!handler_obj) {
++ } else {
+ /*
+- * There is no per-device notify handler for this device.
+- * This may or may not be a problem.
++ * There is no notify handler (per-device or system) for this device.
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+- "No notify handler for Notify(%4.4s, %X) node %p\n",
++ "No notify handler for Notify (%4.4s, %X) node %p\n",
+ acpi_ut_get_node_name(node), notify_value,
+ node));
+ }
+@@ -349,9 +336,10 @@ acpi_status acpi_ev_init_global_lock_handler(void)
+
+ ACPI_FUNCTION_TRACE(ev_init_global_lock_handler);
+
+- status =
+- acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
+- (struct acpi_table_header **)&facs);
++ status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
++ ACPI_CAST_INDIRECT_PTR(struct
++ acpi_table_header,
++ &facs));
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+@@ -439,7 +427,8 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
+ * Only one thread can acquire the GL at a time, the global_lock_mutex
+ * enforces this. This interface releases the interpreter if we must wait.
+ */
+- status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, 0);
++ status = acpi_ex_system_wait_mutex(
++ acpi_gbl_global_lock_mutex->mutex.os_mutex, 0);
+ if (status == AE_TIME) {
+ if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) {
+ acpi_ev_global_lock_acquired++;
+@@ -448,9 +437,9 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
+ }
+
+ if (ACPI_FAILURE(status)) {
+- status =
+- acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex,
+- timeout);
++ status = acpi_ex_system_wait_mutex(
++ acpi_gbl_global_lock_mutex->mutex.os_mutex,
++ timeout);
+ }
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+@@ -460,6 +449,19 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
+ acpi_ev_global_lock_acquired++;
+
+ /*
++ * Update the global lock handle and check for wraparound. The handle is
++ * only used for the external global lock interfaces, but it is updated
++ * here to properly handle the case where a single thread may acquire the
++ * lock via both the AML and the acpi_acquire_global_lock interfaces. The
++ * handle is therefore updated on the first acquire from a given thread
++ * regardless of where the acquisition request originated.
++ */
++ acpi_gbl_global_lock_handle++;
++ if (acpi_gbl_global_lock_handle == 0) {
++ acpi_gbl_global_lock_handle = 1;
++ }
++
++ /*
+ * Make sure that a global lock actually exists. If not, just treat
+ * the lock as a standard mutex.
+ */
+@@ -555,7 +557,7 @@ acpi_status acpi_ev_release_global_lock(void)
+ /* Release the local GL mutex */
+ acpi_ev_global_lock_thread_id = NULL;
+ acpi_ev_global_lock_acquired = 0;
+- acpi_os_release_mutex(acpi_gbl_global_lock_mutex);
++ acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex);
+ return_ACPI_STATUS(status);
+ }
+
+diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c
+index 58ad097..1628f59 100644
+--- a/drivers/acpi/events/evregion.c
++++ b/drivers/acpi/events/evregion.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -394,7 +394,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
+ ®ion_obj->region.handler->address_space, handler,
+- ACPI_FORMAT_UINT64(address),
++ ACPI_FORMAT_NATIVE_UINT(address),
+ acpi_ut_get_region_name(region_obj->region.
+ space_id)));
+
+diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c
+index b1aaa0e..2e3d2c5 100644
+--- a/drivers/acpi/events/evrgnini.c
++++ b/drivers/acpi/events/evrgnini.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/events/evsci.c b/drivers/acpi/events/evsci.c
+index 7e5d15c..2a8b778 100644
+--- a/drivers/acpi/events/evsci.c
++++ b/drivers/acpi/events/evsci.c
+@@ -6,7 +6,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
+index 6d866a0..94a6efe 100644
+--- a/drivers/acpi/events/evxface.c
++++ b/drivers/acpi/events/evxface.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -758,6 +758,12 @@ ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler)
+ *
+ * DESCRIPTION: Acquire the ACPI Global Lock
+ *
++ * Note: Allows callers with the same thread ID to acquire the global lock
++ * multiple times. In other words, externally, the behavior of the global lock
++ * is identical to an AML mutex. On the first acquire, a new handle is
++ * returned. On any subsequent calls to acquire by the same thread, the same
++ * handle is returned.
++ *
+ ******************************************************************************/
+ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
+ {
+@@ -770,14 +776,19 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
+ /* Must lock interpreter to prevent race conditions */
+
+ acpi_ex_enter_interpreter();
+- status = acpi_ev_acquire_global_lock(timeout);
+- acpi_ex_exit_interpreter();
++
++ status = acpi_ex_acquire_mutex_object(timeout,
++ acpi_gbl_global_lock_mutex,
++ acpi_os_get_thread_id());
+
+ if (ACPI_SUCCESS(status)) {
+- acpi_gbl_global_lock_handle++;
++
++ /* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */
++
+ *handle = acpi_gbl_global_lock_handle;
+ }
+
++ acpi_ex_exit_interpreter();
+ return (status);
+ }
+
+@@ -798,11 +809,11 @@ acpi_status acpi_release_global_lock(u32 handle)
+ {
+ acpi_status status;
+
+- if (handle != acpi_gbl_global_lock_handle) {
++ if (!handle || (handle != acpi_gbl_global_lock_handle)) {
+ return (AE_NOT_ACQUIRED);
+ }
+
+- status = acpi_ev_release_global_lock();
++ status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex);
+ return (status);
+ }
+
+diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c
+index 9cbd341..99a7502 100644
+--- a/drivers/acpi/events/evxfevnt.c
++++ b/drivers/acpi/events/evxfevnt.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c
+index 7bf09c5..e875080 100644
+--- a/drivers/acpi/events/evxfregn.c
++++ b/drivers/acpi/events/evxfregn.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
+index 25802f3..24da921 100644
+--- a/drivers/acpi/executer/exconfig.c
++++ b/drivers/acpi/executer/exconfig.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -45,7 +45,6 @@
+ #include <acpi/acinterp.h>
+ #include <acpi/amlcode.h>
+ #include <acpi/acnamesp.h>
+-#include <acpi/acevents.h>
+ #include <acpi/actables.h>
+ #include <acpi/acdispat.h>
+
+@@ -138,6 +137,14 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
+
+ ACPI_FUNCTION_TRACE(ex_load_table_op);
+
++ /* Validate lengths for the signature_string, OEMIDString, OEMtable_iD */
++
++ if ((operand[0]->string.length > ACPI_NAME_SIZE) ||
++ (operand[1]->string.length > ACPI_OEM_ID_SIZE) ||
++ (operand[2]->string.length > ACPI_OEM_TABLE_ID_SIZE)) {
++ return_ACPI_STATUS(AE_BAD_PARAMETER);
++ }
++
+ /* Find the ACPI table in the RSDT/XSDT */
+
+ status = acpi_tb_find_table(operand[0]->string.pointer,
+@@ -229,11 +236,18 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
+ status = acpi_get_table_by_index(table_index, &table);
+ if (ACPI_SUCCESS(status)) {
+ ACPI_INFO((AE_INFO,
+- "Dynamic OEM Table Load - [%4.4s] OemId [%6.6s] OemTableId [%8.8s]",
++ "Dynamic OEM Table Load - [%.4s] OemId [%.6s] OemTableId [%.8s]",
+ table->signature, table->oem_id,
+ table->oem_table_id));
+ }
+
++ /* Invoke table handler if present */
++
++ if (acpi_gbl_table_handler) {
++ (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table,
++ acpi_gbl_table_handler_context);
++ }
++
+ *return_desc = ddb_handle;
+ return_ACPI_STATUS(status);
+ }
+@@ -268,6 +282,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
+ struct acpi_table_desc table_desc;
+ acpi_native_uint table_index;
+ acpi_status status;
++ u32 length;
+
+ ACPI_FUNCTION_TRACE(ex_load_op);
+
+@@ -278,16 +293,16 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
+ case ACPI_TYPE_REGION:
+
++ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n",
++ obj_desc,
++ acpi_ut_get_object_type_name(obj_desc)));
++
+ /* Region must be system_memory (from ACPI spec) */
+
+ if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) {
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
+ }
+
+- ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n",
+- obj_desc,
+- acpi_ut_get_object_type_name(obj_desc)));
+-
+ /*
+ * If the Region Address and Length have not been previously evaluated,
+ * evaluate them now and save the results.
+@@ -299,6 +314,11 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
+ }
+ }
+
++ /*
++ * We will simply map the memory region for the table. However, the
++ * memory region is technically not guaranteed to remain stable and
++ * we may eventually have to copy the table to a local buffer.
++ */
+ table_desc.address = obj_desc->region.address;
+ table_desc.length = obj_desc->region.length;
+ table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED;
+@@ -306,18 +326,41 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
+
+ case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */
+
+- /* Simply extract the buffer from the buffer object */
+-
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Load from Buffer or Field %p %s\n", obj_desc,
+ acpi_ut_get_object_type_name(obj_desc)));
+
+- table_desc.pointer = ACPI_CAST_PTR(struct acpi_table_header,
+- obj_desc->buffer.pointer);
+- table_desc.length = table_desc.pointer->length;
+- table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED;
++ length = obj_desc->buffer.length;
++
++ /* Must have at least an ACPI table header */
++
++ if (length < sizeof(struct acpi_table_header)) {
++ return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
++ }
++
++ /* Validate checksum here. It won't get validated in tb_add_table */
+
+- obj_desc->buffer.pointer = NULL;
++ status =
++ acpi_tb_verify_checksum(ACPI_CAST_PTR
++ (struct acpi_table_header,
++ obj_desc->buffer.pointer), length);
++ if (ACPI_FAILURE(status)) {
++ return_ACPI_STATUS(status);
++ }
++
++ /*
++ * We need to copy the buffer since the original buffer could be
++ * changed or deleted in the future
++ */
++ table_desc.pointer = ACPI_ALLOCATE(length);
++ if (!table_desc.pointer) {
++ return_ACPI_STATUS(AE_NO_MEMORY);
++ }
++
++ ACPI_MEMCPY(table_desc.pointer, obj_desc->buffer.pointer,
++ length);
++ table_desc.length = length;
++ table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED;
+ break;
+
+ default:
+@@ -333,7 +376,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
+ }
+
+ status =
+- acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle);
++ acpi_ex_add_table(table_index, walk_state->scope_info->scope.node,
++ &ddb_handle);
+ if (ACPI_FAILURE(status)) {
+
+ /* On error, table_ptr was deallocated above */
+@@ -349,11 +393,23 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
+
+ /* table_ptr was deallocated above */
+
++ acpi_ut_remove_reference(ddb_handle);
+ return_ACPI_STATUS(status);
+ }
+
++ /* Invoke table handler if present */
++
++ if (acpi_gbl_table_handler) {
++ (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD,
++ table_desc.pointer,
++ acpi_gbl_table_handler_context);
++ }
++
+ cleanup:
+ if (ACPI_FAILURE(status)) {
++
++ /* Delete allocated buffer or mapping */
++
+ acpi_tb_delete_table(&table_desc);
+ }
+ return_ACPI_STATUS(status);
+@@ -376,6 +432,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
+ acpi_status status = AE_OK;
+ union acpi_operand_object *table_desc = ddb_handle;
+ acpi_native_uint table_index;
++ struct acpi_table_header *table;
+
+ ACPI_FUNCTION_TRACE(ex_unload_table);
+
+@@ -395,17 +452,25 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
+
+ table_index = (acpi_native_uint) table_desc->reference.object;
+
++ /* Invoke table handler if present */
++
++ if (acpi_gbl_table_handler) {
++ status = acpi_get_table_by_index(table_index, &table);
++ if (ACPI_SUCCESS(status)) {
++ (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD,
++ table,
++ acpi_gbl_table_handler_context);
++ }
++ }
++
+ /*
+ * Delete the entire namespace under this table Node
+ * (Offset contains the table_id)
+ */
+ acpi_tb_delete_namespace_by_owner(table_index);
+- acpi_tb_release_owner_id(table_index);
++ (void)acpi_tb_release_owner_id(table_index);
+
+ acpi_tb_set_table_loaded_flag(table_index, FALSE);
+
+- /* Delete the table descriptor (ddb_handle) */
+-
+- acpi_ut_remove_reference(table_desc);
+- return_ACPI_STATUS(status);
++ return_ACPI_STATUS(AE_OK);
+ }
+diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c
+index 79f2c0d..fd954b4 100644
+--- a/drivers/acpi/executer/exconvrt.c
++++ b/drivers/acpi/executer/exconvrt.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c
+index 6e9a23e..60e62c4 100644
+--- a/drivers/acpi/executer/excreate.c
++++ b/drivers/acpi/executer/excreate.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -96,6 +96,9 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
+ * to the original Node.
+ */
+ switch (target_node->type) {
++
++ /* For these types, the sub-object can change dynamically via a Store */
++
+ case ACPI_TYPE_INTEGER:
+ case ACPI_TYPE_STRING:
+ case ACPI_TYPE_BUFFER:
+@@ -103,9 +106,18 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
+ case ACPI_TYPE_BUFFER_FIELD:
+
+ /*
++ * These types open a new scope, so we need the NS node in order to access
++ * any children.
++ */
++ case ACPI_TYPE_DEVICE:
++ case ACPI_TYPE_POWER:
++ case ACPI_TYPE_PROCESSOR:
++ case ACPI_TYPE_THERMAL:
++ case ACPI_TYPE_LOCAL_SCOPE:
++
++ /*
+ * The new alias has the type ALIAS and points to the original
+- * NS node, not the object itself. This is because for these
+- * types, the object can change dynamically via a Store.
++ * NS node, not the object itself.
+ */
+ alias_node->type = ACPI_TYPE_LOCAL_ALIAS;
+ alias_node->object =
+@@ -115,9 +127,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
+ case ACPI_TYPE_METHOD:
+
+ /*
+- * The new alias has the type ALIAS and points to the original
+- * NS node, not the object itself. This is because for these
+- * types, the object can change dynamically via a Store.
++ * Control method aliases need to be differentiated
+ */
+ alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
+ alias_node->object =
+@@ -342,101 +352,6 @@ acpi_ex_create_region(u8 * aml_start,
+
+ /*******************************************************************************
+ *
+- * FUNCTION: acpi_ex_create_table_region
+- *
+- * PARAMETERS: walk_state - Current state
+- *
+- * RETURN: Status
+- *
+- * DESCRIPTION: Create a new data_table_region object
+- *
+- ******************************************************************************/
+-
+-acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state)
+-{
+- acpi_status status;
+- union acpi_operand_object **operand = &walk_state->operands[0];
+- union acpi_operand_object *obj_desc;
+- struct acpi_namespace_node *node;
+- union acpi_operand_object *region_obj2;
+- acpi_native_uint table_index;
+- struct acpi_table_header *table;
+-
+- ACPI_FUNCTION_TRACE(ex_create_table_region);
+-
+- /* Get the Node from the object stack */
+-
+- node = walk_state->op->common.node;
+-
+- /*
+- * If the region object is already attached to this node,
+- * just return
+- */
+- if (acpi_ns_get_attached_object(node)) {
+- return_ACPI_STATUS(AE_OK);
+- }
+-
+- /* Find the ACPI table */
+-
+- status = acpi_tb_find_table(operand[1]->string.pointer,
+- operand[2]->string.pointer,
+- operand[3]->string.pointer, &table_index);
+- if (ACPI_FAILURE(status)) {
+- return_ACPI_STATUS(status);
+- }
+-
+- /* Create the region descriptor */
+-
+- obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
+- if (!obj_desc) {
+- return_ACPI_STATUS(AE_NO_MEMORY);
+- }
+-
+- region_obj2 = obj_desc->common.next_object;
+- region_obj2->extra.region_context = NULL;
+-
+- status = acpi_get_table_by_index(table_index, &table);
+- if (ACPI_FAILURE(status)) {
+- return_ACPI_STATUS(status);
+- }
+-
+- /* Init the region from the operands */
+-
+- obj_desc->region.space_id = REGION_DATA_TABLE;
+- obj_desc->region.address =
+- (acpi_physical_address) ACPI_TO_INTEGER(table);
+- obj_desc->region.length = table->length;
+- obj_desc->region.node = node;
+- obj_desc->region.flags = AOPOBJ_DATA_VALID;
+-
+- /* Install the new region object in the parent Node */
+-
+- status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION);
+- if (ACPI_FAILURE(status)) {
+- goto cleanup;
+- }
+-
+- status = acpi_ev_initialize_region(obj_desc, FALSE);
+- if (ACPI_FAILURE(status)) {
+- if (status == AE_NOT_EXIST) {
+- status = AE_OK;
+- } else {
+- goto cleanup;
+- }
+- }
+-
+- obj_desc->region.flags |= AOPOBJ_SETUP_COMPLETE;
+-
+- cleanup:
+-
+- /* Remove local reference to the object */
+-
+- acpi_ut_remove_reference(obj_desc);
+- return_ACPI_STATUS(status);
+-}
+-
+-/*******************************************************************************
+- *
+ * FUNCTION: acpi_ex_create_processor
+ *
+ * PARAMETERS: walk_state - Current state
+diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
+index 51c9c29..74f1b22 100644
+--- a/drivers/acpi/executer/exdump.c
++++ b/drivers/acpi/executer/exdump.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -500,25 +500,28 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
+ acpi_os_printf("Reference: Debug\n");
+ break;
+
+- case AML_NAME_OP:
++ case AML_INDEX_OP:
+
+- ACPI_DUMP_PATHNAME(obj_desc->reference.object,
+- "Reference: Name: ", ACPI_LV_INFO,
+- _COMPONENT);
+- ACPI_DUMP_ENTRY(obj_desc->reference.object,
+- ACPI_LV_INFO);
++ acpi_os_printf("Reference: Index %p\n",
++ obj_desc->reference.object);
+ break;
+
+- case AML_INDEX_OP:
++ case AML_LOAD_OP:
+
+- acpi_os_printf("Reference: Index %p\n",
++ acpi_os_printf("Reference: [DdbHandle] TableIndex %p\n",
+ obj_desc->reference.object);
+ break;
+
+ case AML_REF_OF_OP:
+
+- acpi_os_printf("Reference: (RefOf) %p\n",
+- obj_desc->reference.object);
++ acpi_os_printf("Reference: (RefOf) %p [%s]\n",
++ obj_desc->reference.object,
++ acpi_ut_get_type_name(((union
++ acpi_operand_object
++ *)obj_desc->
++ reference.
++ object)->common.
++ type));
+ break;
+
+ case AML_ARG_OP:
+@@ -559,8 +562,9 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
+
+ case AML_INT_NAMEPATH_OP:
+
+- acpi_os_printf("Reference.Node->Name %X\n",
+- obj_desc->reference.node->name.integer);
++ acpi_os_printf("Reference: Namepath %X [%4.4s]\n",
++ obj_desc->reference.node->name.integer,
++ obj_desc->reference.node->name.ascii);
+ break;
+
+ default:
+@@ -640,8 +644,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
+ acpi_os_printf("\n");
+ } else {
+ acpi_os_printf(" base %8.8X%8.8X Length %X\n",
+- ACPI_FORMAT_UINT64(obj_desc->region.
+- address),
++ ACPI_FORMAT_NATIVE_UINT(obj_desc->region.
++ address),
+ obj_desc->region.length);
+ }
+ break;
+@@ -877,20 +881,43 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc)
+ ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+
+ if (obj_desc->reference.opcode == AML_INT_NAMEPATH_OP) {
+- acpi_os_printf("Named Object %p ", obj_desc->reference.node);
++ acpi_os_printf(" Named Object %p ", obj_desc->reference.node);
+
+ status =
+ acpi_ns_handle_to_pathname(obj_desc->reference.node,
+ &ret_buf);
+ if (ACPI_FAILURE(status)) {
+- acpi_os_printf("Could not convert name to pathname\n");
++ acpi_os_printf(" Could not convert name to pathname\n");
+ } else {
+ acpi_os_printf("%s\n", (char *)ret_buf.pointer);
+ ACPI_FREE(ret_buf.pointer);
+ }
+ } else if (obj_desc->reference.object) {
+- acpi_os_printf("\nReferenced Object: %p\n",
+- obj_desc->reference.object);
++ if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) ==
++ ACPI_DESC_TYPE_OPERAND) {
++ acpi_os_printf(" Target: %p",
++ obj_desc->reference.object);
++ if (obj_desc->reference.opcode == AML_LOAD_OP) {
++ /*
++ * For DDBHandle reference,
++ * obj_desc->Reference.Object is the table index
++ */
++ acpi_os_printf(" [DDBHandle]\n");
++ } else {
++ acpi_os_printf(" [%s]\n",
++ acpi_ut_get_type_name(((union
++ acpi_operand_object
++ *)
++ obj_desc->
++ reference.
++ object)->
++ common.
++ type));
++ }
++ } else {
++ acpi_os_printf(" Target: %p\n",
++ obj_desc->reference.object);
++ }
+ }
+ }
+
+@@ -976,7 +1003,9 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc,
+
+ case ACPI_TYPE_LOCAL_REFERENCE:
+
+- acpi_os_printf("[Object Reference] ");
++ acpi_os_printf("[Object Reference] %s",
++ (acpi_ps_get_opcode_info
++ (obj_desc->reference.opcode))->name);
+ acpi_ex_dump_reference_obj(obj_desc);
+ break;
+
+diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c
+index 2d88a3d..3e440d8 100644
+--- a/drivers/acpi/executer/exfield.c
++++ b/drivers/acpi/executer/exfield.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -71,7 +71,6 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
+ union acpi_operand_object *buffer_desc;
+ acpi_size length;
+ void *buffer;
+- u8 locked;
+
+ ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
+
+@@ -111,9 +110,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
+
+ /* Lock entire transaction if requested */
+
+- locked =
+- acpi_ex_acquire_global_lock(obj_desc->common_field.
+- field_flags);
++ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
+
+ /*
+ * Perform the read.
+@@ -125,7 +122,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
+ buffer.pointer),
+ ACPI_READ | (obj_desc->field.
+ attribute << 16));
+- acpi_ex_release_global_lock(locked);
++ acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
+ goto exit;
+ }
+
+@@ -175,13 +172,12 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
+
+ /* Lock entire transaction if requested */
+
+- locked =
+- acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
++ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
+
+ /* Read from the field */
+
+ status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length);
+- acpi_ex_release_global_lock(locked);
++ acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
+
+ exit:
+ if (ACPI_FAILURE(status)) {
+@@ -214,10 +210,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
+ {
+ acpi_status status;
+ u32 length;
+- u32 required_length;
+ void *buffer;
+- void *new_buffer;
+- u8 locked;
+ union acpi_operand_object *buffer_desc;
+
+ ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
+@@ -278,9 +271,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
+
+ /* Lock entire transaction if requested */
+
+- locked =
+- acpi_ex_acquire_global_lock(obj_desc->common_field.
+- field_flags);
++ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
+
+ /*
+ * Perform the write (returns status and perhaps data in the
+@@ -291,7 +282,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
+ (acpi_integer *) buffer,
+ ACPI_WRITE | (obj_desc->field.
+ attribute << 16));
+- acpi_ex_release_global_lock(locked);
++ acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
+
+ *result_desc = buffer_desc;
+ return_ACPI_STATUS(status);
+@@ -319,35 +310,6 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
+ }
+
+- /*
+- * We must have a buffer that is at least as long as the field
+- * we are writing to. This is because individual fields are
+- * indivisible and partial writes are not supported -- as per
+- * the ACPI specification.
+- */
+- new_buffer = NULL;
+- required_length =
+- ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
+-
+- if (length < required_length) {
+-
+- /* We need to create a new buffer */
+-
+- new_buffer = ACPI_ALLOCATE_ZEROED(required_length);
+- if (!new_buffer) {
+- return_ACPI_STATUS(AE_NO_MEMORY);
+- }
+-
+- /*
+- * Copy the original data to the new buffer, starting
+- * at Byte zero. All unused (upper) bytes of the
+- * buffer will be 0.
+- */
+- ACPI_MEMCPY((char *)new_buffer, (char *)buffer, length);
+- buffer = new_buffer;
+- length = required_length;
+- }
+-
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n",
+ source_desc,
+@@ -366,19 +328,12 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
+
+ /* Lock entire transaction if requested */
+
+- locked =
+- acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
++ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
+
+ /* Write to the field */
+
+ status = acpi_ex_insert_into_field(obj_desc, buffer, length);
+- acpi_ex_release_global_lock(locked);
+-
+- /* Free temporary buffer if we used one */
+-
+- if (new_buffer) {
+- ACPI_FREE(new_buffer);
+- }
++ acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
+
+ return_ACPI_STATUS(status);
+ }
+diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c
+index 65a48b6..e336b5d 100644
+--- a/drivers/acpi/executer/exfldio.c
++++ b/drivers/acpi/executer/exfldio.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -263,7 +263,8 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
+ rgn_desc->region.space_id,
+ obj_desc->common_field.access_byte_width,
+ obj_desc->common_field.base_byte_offset,
+- field_datum_byte_offset, (void *)address));
++ field_datum_byte_offset, ACPI_CAST_PTR(void,
++ address)));
+
+ /* Invoke the appropriate address_space/op_region handler */
+
+@@ -805,18 +806,39 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
+ u32 datum_count;
+ u32 field_datum_count;
+ u32 i;
++ u32 required_length;
++ void *new_buffer;
+
+ ACPI_FUNCTION_TRACE(ex_insert_into_field);
+
+ /* Validate input buffer */
+
+- if (buffer_length <
+- ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
+- ACPI_ERROR((AE_INFO,
+- "Field size %X (bits) is too large for buffer (%X)",
+- obj_desc->common_field.bit_length, buffer_length));
++ new_buffer = NULL;
++ required_length =
++ ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
++ /*
++ * We must have a buffer that is at least as long as the field
++ * we are writing to. This is because individual fields are
++ * indivisible and partial writes are not supported -- as per
++ * the ACPI specification.
++ */
++ if (buffer_length < required_length) {
+
+- return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
++ /* We need to create a new buffer */
++
++ new_buffer = ACPI_ALLOCATE_ZEROED(required_length);
++ if (!new_buffer) {
++ return_ACPI_STATUS(AE_NO_MEMORY);
++ }
++
++ /*
++ * Copy the original data to the new buffer, starting
++ * at Byte zero. All unused (upper) bytes of the
++ * buffer will be 0.
++ */
++ ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length);
++ buffer = new_buffer;
++ buffer_length = required_length;
+ }
+
+ /*
+@@ -866,7 +888,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
+ merged_datum,
+ field_offset);
+ if (ACPI_FAILURE(status)) {
+- return_ACPI_STATUS(status);
++ goto exit;
+ }
+
+ field_offset += obj_desc->common_field.access_byte_width;
+@@ -924,5 +946,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
+ mask, merged_datum,
+ field_offset);
+
++ exit:
++ /* Free temporary buffer if we used one */
++
++ if (new_buffer) {
++ ACPI_FREE(new_buffer);
++ }
+ return_ACPI_STATUS(status);
+ }
+diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c
+index f13d1ce..cc956a5 100644
+--- a/drivers/acpi/executer/exmisc.c
++++ b/drivers/acpi/executer/exmisc.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
+index 6748e3e..c873ab4 100644
+--- a/drivers/acpi/executer/exmutex.c
++++ b/drivers/acpi/executer/exmutex.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -126,6 +126,79 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc,
+
+ /*******************************************************************************
+ *
++ * FUNCTION: acpi_ex_acquire_mutex_object
++ *
++ * PARAMETERS: time_desc - Timeout in milliseconds
++ * obj_desc - Mutex object
++ * Thread - Current thread state
++ *
++ * RETURN: Status
++ *
++ * DESCRIPTION: Acquire an AML mutex, low-level interface. Provides a common
++ * path that supports multiple acquires by the same thread.
++ *
++ * MUTEX: Interpreter must be locked
++ *
++ * NOTE: This interface is called from three places:
++ * 1) From acpi_ex_acquire_mutex, via an AML Acquire() operator
++ * 2) From acpi_ex_acquire_global_lock when an AML Field access requires the
++ * global lock
++ * 3) From the external interface, acpi_acquire_global_lock
++ *
++ ******************************************************************************/
++
++acpi_status
++acpi_ex_acquire_mutex_object(u16 timeout,
++ union acpi_operand_object *obj_desc,
++ acpi_thread_id thread_id)
++{
++ acpi_status status;
++
++ ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex_object, obj_desc);
++
++ if (!obj_desc) {
++ return_ACPI_STATUS(AE_BAD_PARAMETER);
++ }
++
++ /* Support for multiple acquires by the owning thread */
++
++ if (obj_desc->mutex.thread_id == thread_id) {
++ /*
++ * The mutex is already owned by this thread, just increment the
++ * acquisition depth
++ */
++ obj_desc->mutex.acquisition_depth++;
++ return_ACPI_STATUS(AE_OK);
++ }
++
++ /* Acquire the mutex, wait if necessary. Special case for Global Lock */
++
++ if (obj_desc == acpi_gbl_global_lock_mutex) {
++ status = acpi_ev_acquire_global_lock(timeout);
++ } else {
++ status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex,
++ timeout);
++ }
++
++ if (ACPI_FAILURE(status)) {
++
++ /* Includes failure from a timeout on time_desc */
++
++ return_ACPI_STATUS(status);
++ }
++
++ /* Acquired the mutex: update mutex object */
++
++ obj_desc->mutex.thread_id = thread_id;
++ obj_desc->mutex.acquisition_depth = 1;
++ obj_desc->mutex.original_sync_level = 0;
++ obj_desc->mutex.owner_thread = NULL; /* Used only for AML Acquire() */
++
++ return_ACPI_STATUS(AE_OK);
++}
++
++/*******************************************************************************
++ *
+ * FUNCTION: acpi_ex_acquire_mutex
+ *
+ * PARAMETERS: time_desc - Timeout integer
+@@ -151,7 +224,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
+- /* Sanity check: we must have a valid thread ID */
++ /* Must have a valid thread ID */
+
+ if (!walk_state->thread) {
+ ACPI_ERROR((AE_INFO,
+@@ -161,7 +234,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
+ }
+
+ /*
+- * Current Sync must be less than or equal to the sync level of the
++ * Current sync level must be less than or equal to the sync level of the
+ * mutex. This mechanism provides some deadlock prevention
+ */
+ if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) {
+@@ -172,51 +245,89 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
+ return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
+ }
+
+- /* Support for multiple acquires by the owning thread */
++ status = acpi_ex_acquire_mutex_object((u16) time_desc->integer.value,
++ obj_desc,
++ walk_state->thread->thread_id);
++ if (ACPI_SUCCESS(status) && obj_desc->mutex.acquisition_depth == 1) {
+
+- if (obj_desc->mutex.owner_thread) {
+- if (obj_desc->mutex.owner_thread->thread_id ==
+- walk_state->thread->thread_id) {
+- /*
+- * The mutex is already owned by this thread, just increment the
+- * acquisition depth
+- */
+- obj_desc->mutex.acquisition_depth++;
+- return_ACPI_STATUS(AE_OK);
+- }
++ /* Save Thread object, original/current sync levels */
++
++ obj_desc->mutex.owner_thread = walk_state->thread;
++ obj_desc->mutex.original_sync_level =
++ walk_state->thread->current_sync_level;
++ walk_state->thread->current_sync_level =
++ obj_desc->mutex.sync_level;
++
++ /* Link the mutex to the current thread for force-unlock at method exit */
++
++ acpi_ex_link_mutex(obj_desc, walk_state->thread);
+ }
+
+- /* Acquire the mutex, wait if necessary. Special case for Global Lock */
++ return_ACPI_STATUS(status);
++}
+
+- if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) {
+- status =
+- acpi_ev_acquire_global_lock((u16) time_desc->integer.value);
+- } else {
+- status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex,
+- (u16) time_desc->integer.
+- value);
++/*******************************************************************************
++ *
++ * FUNCTION: acpi_ex_release_mutex_object
++ *
++ * PARAMETERS: obj_desc - The object descriptor for this op
++ *
++ * RETURN: Status
++ *
++ * DESCRIPTION: Release a previously acquired Mutex, low level interface.
++ * Provides a common path that supports multiple releases (after
++ * previous multiple acquires) by the same thread.
++ *
++ * MUTEX: Interpreter must be locked
++ *
++ * NOTE: This interface is called from three places:
++ * 1) From acpi_ex_release_mutex, via an AML Acquire() operator
++ * 2) From acpi_ex_release_global_lock when an AML Field access requires the
++ * global lock
++ * 3) From the external interface, acpi_release_global_lock
++ *
++ ******************************************************************************/
++
++acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc)
++{
++ acpi_status status = AE_OK;
++
++ ACPI_FUNCTION_TRACE(ex_release_mutex_object);
++
++ if (obj_desc->mutex.acquisition_depth == 0) {
++ return (AE_NOT_ACQUIRED);
+ }
+
+- if (ACPI_FAILURE(status)) {
++ /* Match multiple Acquires with multiple Releases */
+
+- /* Includes failure from a timeout on time_desc */
++ obj_desc->mutex.acquisition_depth--;
++ if (obj_desc->mutex.acquisition_depth != 0) {
+
+- return_ACPI_STATUS(status);
++ /* Just decrement the depth and return */
++
++ return_ACPI_STATUS(AE_OK);
+ }
+
+- /* Have the mutex: update mutex and walk info and save the sync_level */
++ if (obj_desc->mutex.owner_thread) {
+
+- obj_desc->mutex.owner_thread = walk_state->thread;
+- obj_desc->mutex.acquisition_depth = 1;
+- obj_desc->mutex.original_sync_level =
+- walk_state->thread->current_sync_level;
++ /* Unlink the mutex from the owner's list */
+
+- walk_state->thread->current_sync_level = obj_desc->mutex.sync_level;
++ acpi_ex_unlink_mutex(obj_desc);
++ obj_desc->mutex.owner_thread = NULL;
++ }
+
+- /* Link the mutex to the current thread for force-unlock at method exit */
++ /* Release the mutex, special case for Global Lock */
+
+- acpi_ex_link_mutex(obj_desc, walk_state->thread);
+- return_ACPI_STATUS(AE_OK);
++ if (obj_desc == acpi_gbl_global_lock_mutex) {
++ status = acpi_ev_release_global_lock();
++ } else {
++ acpi_os_release_mutex(obj_desc->mutex.os_mutex);
++ }
++
++ /* Clear mutex info */
++
++ obj_desc->mutex.thread_id = 0;
++ return_ACPI_STATUS(status);
+ }
+
+ /*******************************************************************************
+@@ -253,22 +364,13 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
+ return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED);
+ }
+
+- /* Sanity check: we must have a valid thread ID */
+-
+- if (!walk_state->thread) {
+- ACPI_ERROR((AE_INFO,
+- "Cannot release Mutex [%4.4s], null thread info",
+- acpi_ut_get_node_name(obj_desc->mutex.node)));
+- return_ACPI_STATUS(AE_AML_INTERNAL);
+- }
+-
+ /*
+ * The Mutex is owned, but this thread must be the owner.
+ * Special case for Global Lock, any thread can release
+ */
+ if ((obj_desc->mutex.owner_thread->thread_id !=
+ walk_state->thread->thread_id)
+- && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) {
++ && (obj_desc != acpi_gbl_global_lock_mutex)) {
+ ACPI_ERROR((AE_INFO,
+ "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX",
+ (unsigned long)walk_state->thread->thread_id,
+@@ -278,45 +380,37 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
+ return_ACPI_STATUS(AE_AML_NOT_OWNER);
+ }
+
++ /* Must have a valid thread ID */
++
++ if (!walk_state->thread) {
++ ACPI_ERROR((AE_INFO,
++ "Cannot release Mutex [%4.4s], null thread info",
++ acpi_ut_get_node_name(obj_desc->mutex.node)));
++ return_ACPI_STATUS(AE_AML_INTERNAL);
++ }
++
+ /*
+ * The sync level of the mutex must be less than or equal to the current
+ * sync level
+ */
+ if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) {
+ ACPI_ERROR((AE_INFO,
+- "Cannot release Mutex [%4.4s], incorrect SyncLevel",
+- acpi_ut_get_node_name(obj_desc->mutex.node)));
++ "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %d current %d",
++ acpi_ut_get_node_name(obj_desc->mutex.node),
++ obj_desc->mutex.sync_level,
++ walk_state->thread->current_sync_level));
+ return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
+ }
+
+- /* Match multiple Acquires with multiple Releases */
+-
+- obj_desc->mutex.acquisition_depth--;
+- if (obj_desc->mutex.acquisition_depth != 0) {
+-
+- /* Just decrement the depth and return */
+-
+- return_ACPI_STATUS(AE_OK);
+- }
+-
+- /* Unlink the mutex from the owner's list */
++ status = acpi_ex_release_mutex_object(obj_desc);
+
+- acpi_ex_unlink_mutex(obj_desc);
++ if (obj_desc->mutex.acquisition_depth == 0) {
+
+- /* Release the mutex, special case for Global Lock */
++ /* Restore the original sync_level */
+
+- if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) {
+- status = acpi_ev_release_global_lock();
+- } else {
+- acpi_os_release_mutex(obj_desc->mutex.os_mutex);
++ walk_state->thread->current_sync_level =
++ obj_desc->mutex.original_sync_level;
+ }
+-
+- /* Update the mutex and restore sync_level */
+-
+- obj_desc->mutex.owner_thread = NULL;
+- walk_state->thread->current_sync_level =
+- obj_desc->mutex.original_sync_level;
+-
+ return_ACPI_STATUS(status);
+ }
+
+@@ -357,7 +451,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
+
+ /* Release the mutex, special case for Global Lock */
+
+- if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) {
++ if (obj_desc == acpi_gbl_global_lock_mutex) {
+
+ /* Ignore errors */
+
+@@ -369,6 +463,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
+ /* Mark mutex unowned */
+
+ obj_desc->mutex.owner_thread = NULL;
++ obj_desc->mutex.thread_id = 0;
+
+ /* Update Thread sync_level (Last mutex is the important one) */
+
+diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c
+index 308eae5..817e67b 100644
+--- a/drivers/acpi/executer/exnames.c
++++ b/drivers/acpi/executer/exnames.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c
+index 252f10a..7c3bea5 100644
+--- a/drivers/acpi/executer/exoparg1.c
++++ b/drivers/acpi/executer/exoparg1.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -121,6 +121,7 @@ acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state)
+
+ if ((ACPI_FAILURE(status)) || walk_state->result_obj) {
+ acpi_ut_remove_reference(return_desc);
++ walk_state->result_obj = NULL;
+ } else {
+ /* Save the return value */
+
+@@ -739,26 +740,38 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
+ value = acpi_gbl_integer_byte_width;
+ break;
+
+- case ACPI_TYPE_BUFFER:
+- value = temp_desc->buffer.length;
+- break;
+-
+ case ACPI_TYPE_STRING:
+ value = temp_desc->string.length;
+ break;
+
++ case ACPI_TYPE_BUFFER:
++
++ /* Buffer arguments may not be evaluated at this point */
++
++ status = acpi_ds_get_buffer_arguments(temp_desc);
++ value = temp_desc->buffer.length;
++ break;
++
+ case ACPI_TYPE_PACKAGE:
++
++ /* Package arguments may not be evaluated at this point */
++
++ status = acpi_ds_get_package_arguments(temp_desc);
+ value = temp_desc->package.count;
+ break;
+
+ default:
+ ACPI_ERROR((AE_INFO,
+- "Operand is not Buf/Int/Str/Pkg - found type %s",
++ "Operand must be Buffer/Integer/String/Package - found type %s",
+ acpi_ut_get_type_name(type)));
+ status = AE_AML_OPERAND_TYPE;
+ goto cleanup;
+ }
+
++ if (ACPI_FAILURE(status)) {
++ goto cleanup;
++ }
++
+ /*
+ * Now that we have the size of the object, create a result
+ * object to hold the value
+diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c
+index 17e652e..8e8bbb6 100644
+--- a/drivers/acpi/executer/exoparg2.c
++++ b/drivers/acpi/executer/exoparg2.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -241,10 +241,6 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
+ goto cleanup;
+ }
+
+- /* Return the remainder */
+-
+- walk_state->result_obj = return_desc1;
+-
+ cleanup:
+ /*
+ * Since the remainder is not returned indirectly, remove a reference to
+@@ -259,6 +255,12 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
+ acpi_ut_remove_reference(return_desc1);
+ }
+
++ /* Save return object (the remainder) on success */
++
++ else {
++ walk_state->result_obj = return_desc1;
++ }
++
+ return_ACPI_STATUS(status);
+ }
+
+@@ -490,6 +492,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
+
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(return_desc);
++ walk_state->result_obj = NULL;
+ }
+
+ return_ACPI_STATUS(status);
+@@ -583,8 +586,6 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
+ return_desc->integer.value = ACPI_INTEGER_MAX;
+ }
+
+- walk_state->result_obj = return_desc;
+-
+ cleanup:
+
+ /* Delete return object on error */
+@@ -593,5 +594,11 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
+ acpi_ut_remove_reference(return_desc);
+ }
+
++ /* Save return object on success */
++
++ else {
++ walk_state->result_obj = return_desc;
++ }
++
+ return_ACPI_STATUS(status);
+ }
+diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c
+index 7fe67cf..9cb4197 100644
+--- a/drivers/acpi/executer/exoparg3.c
++++ b/drivers/acpi/executer/exoparg3.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -260,6 +260,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
+
+ if (ACPI_FAILURE(status) || walk_state->result_obj) {
+ acpi_ut_remove_reference(return_desc);
++ walk_state->result_obj = NULL;
+ }
+
+ /* Set the return object and exit */
+diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c
+index bd80a9c..67d4873 100644
+--- a/drivers/acpi/executer/exoparg6.c
++++ b/drivers/acpi/executer/exoparg6.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -322,8 +322,6 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
+ goto cleanup;
+ }
+
+- walk_state->result_obj = return_desc;
+-
+ cleanup:
+
+ /* Delete return object on error */
+@@ -332,5 +330,11 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
+ acpi_ut_remove_reference(return_desc);
+ }
+
++ /* Save return object on success */
++
++ else {
++ walk_state->result_obj = return_desc;
++ }
++
+ return_ACPI_STATUS(status);
+ }
+diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c
+index efe5d4b..3a2f8cd 100644
+--- a/drivers/acpi/executer/exprep.c
++++ b/drivers/acpi/executer/exprep.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -412,6 +412,7 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
+ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
+ {
+ union acpi_operand_object *obj_desc;
++ union acpi_operand_object *second_desc = NULL;
+ u32 type;
+ acpi_status status;
+
+@@ -494,6 +495,20 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
+ obj_desc->field.access_byte_width,
+ obj_desc->bank_field.region_obj,
+ obj_desc->bank_field.bank_obj));
++
++ /*
++ * Remember location in AML stream of the field unit
++ * opcode and operands -- since the bank_value
++ * operands must be evaluated.
++ */
++ second_desc = obj_desc->common.next_object;
++ second_desc->extra.aml_start =
++ ((union acpi_parse_object *)(info->data_register_node))->
++ named.data;
++ second_desc->extra.aml_length =
++ ((union acpi_parse_object *)(info->data_register_node))->
++ named.length;
++
+ break;
+
+ case ACPI_TYPE_LOCAL_INDEX_FIELD:
+diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c
+index 3f51b7e..7cd8bb5 100644
+--- a/drivers/acpi/executer/exregion.c
++++ b/drivers/acpi/executer/exregion.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -160,7 +160,7 @@ acpi_ex_system_memory_space_handler(u32 function,
+ if (!mem_info->mapped_logical_address) {
+ ACPI_ERROR((AE_INFO,
+ "Could not map memory at %8.8X%8.8X, size %X",
+- ACPI_FORMAT_UINT64(address),
++ ACPI_FORMAT_NATIVE_UINT(address),
+ (u32) window_size));
+ mem_info->mapped_length = 0;
+ return_ACPI_STATUS(AE_NO_MEMORY);
+@@ -182,7 +182,8 @@ acpi_ex_system_memory_space_handler(u32 function,
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n",
+- bit_width, function, ACPI_FORMAT_UINT64(address)));
++ bit_width, function,
++ ACPI_FORMAT_NATIVE_UINT(address)));
+
+ /*
+ * Perform the memory read or write
+@@ -284,7 +285,8 @@ acpi_ex_system_io_space_handler(u32 function,
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "System-IO (width %d) R/W %d Address=%8.8X%8.8X\n",
+- bit_width, function, ACPI_FORMAT_UINT64(address)));
++ bit_width, function,
++ ACPI_FORMAT_NATIVE_UINT(address)));
+
+ /* Decode the function parameter */
+
+diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c
+index 2b3a01c..5596f42 100644
+--- a/drivers/acpi/executer/exresnte.c
++++ b/drivers/acpi/executer/exresnte.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -116,9 +116,11 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
+ * Several object types require no further processing:
+ * 1) Device/Thermal objects don't have a "real" subobject, return the Node
+ * 2) Method locals and arguments have a pseudo-Node
++ * 3) 10/2007: Added method type to assist with Package construction.
+ */
+ if ((entry_type == ACPI_TYPE_DEVICE) ||
+ (entry_type == ACPI_TYPE_THERMAL) ||
++ (entry_type == ACPI_TYPE_METHOD) ||
+ (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) {
+ return_ACPI_STATUS(AE_OK);
+ }
+@@ -214,7 +216,6 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
+ /* For these objects, just return the object attached to the Node */
+
+ case ACPI_TYPE_MUTEX:
+- case ACPI_TYPE_METHOD:
+ case ACPI_TYPE_POWER:
+ case ACPI_TYPE_PROCESSOR:
+ case ACPI_TYPE_EVENT:
+@@ -238,13 +239,12 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
+ case ACPI_TYPE_LOCAL_REFERENCE:
+
+ switch (source_desc->reference.opcode) {
+- case AML_LOAD_OP:
++ case AML_LOAD_OP: /* This is a ddb_handle */
++ case AML_REF_OF_OP:
++ case AML_INDEX_OP:
+
+- /* This is a ddb_handle */
+ /* Return an additional reference to the object */
+
+- case AML_REF_OF_OP:
+-
+ obj_desc = source_desc;
+ acpi_ut_add_reference(obj_desc);
+ break;
+diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c
+index 6c64e55..b35f7c8 100644
+--- a/drivers/acpi/executer/exresolv.c
++++ b/drivers/acpi/executer/exresolv.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -140,7 +140,6 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
+ {
+ acpi_status status = AE_OK;
+ union acpi_operand_object *stack_desc;
+- void *temp_node;
+ union acpi_operand_object *obj_desc = NULL;
+ u16 opcode;
+
+@@ -156,23 +155,6 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
+ opcode = stack_desc->reference.opcode;
+
+ switch (opcode) {
+- case AML_NAME_OP:
+-
+- /*
+- * Convert name reference to a namespace node
+- * Then, acpi_ex_resolve_node_to_value can be used to get the value
+- */
+- temp_node = stack_desc->reference.object;
+-
+- /* Delete the Reference Object */
+-
+- acpi_ut_remove_reference(stack_desc);
+-
+- /* Return the namespace node */
+-
+- (*stack_ptr) = temp_node;
+- break;
+-
+ case AML_LOCAL_OP:
+ case AML_ARG_OP:
+
+@@ -207,15 +189,25 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
+ switch (stack_desc->reference.target_type) {
+ case ACPI_TYPE_BUFFER_FIELD:
+
+- /* Just return - leave the Reference on the stack */
++ /* Just return - do not dereference */
+ break;
+
+ case ACPI_TYPE_PACKAGE:
+
++ /* If method call or copy_object - do not dereference */
++
++ if ((walk_state->opcode ==
++ AML_INT_METHODCALL_OP)
++ || (walk_state->opcode == AML_COPY_OP)) {
++ break;
++ }
++
++ /* Otherwise, dereference the package_index to a package element */
++
+ obj_desc = *stack_desc->reference.where;
+ if (obj_desc) {
+ /*
+- * Valid obj descriptor, copy pointer to return value
++ * Valid object descriptor, copy pointer to return value
+ * (i.e., dereference the package index)
+ * Delete the ref object, increment the returned object
+ */
+@@ -224,11 +216,11 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
+ *stack_ptr = obj_desc;
+ } else {
+ /*
+- * A NULL object descriptor means an unitialized element of
++ * A NULL object descriptor means an uninitialized element of
+ * the package, can't dereference it
+ */
+ ACPI_ERROR((AE_INFO,
+- "Attempt to deref an Index to NULL pkg element Idx=%p",
++ "Attempt to dereference an Index to NULL package element Idx=%p",
+ stack_desc));
+ status = AE_AML_UNINITIALIZED_ELEMENT;
+ }
+@@ -239,7 +231,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
+ /* Invalid reference object */
+
+ ACPI_ERROR((AE_INFO,
+- "Unknown TargetType %X in Index/Reference obj %p",
++ "Unknown TargetType %X in Index/Reference object %p",
+ stack_desc->reference.target_type,
+ stack_desc));
+ status = AE_AML_INTERNAL;
+@@ -251,7 +243,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
+ case AML_DEBUG_OP:
+ case AML_LOAD_OP:
+
+- /* Just leave the object as-is */
++ /* Just leave the object as-is, do not dereference */
+
+ break;
+
+@@ -390,10 +382,10 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
+ }
+
+ /*
+- * For reference objects created via the ref_of or Index operators,
+- * we need to get to the base object (as per the ACPI specification
+- * of the object_type and size_of operators). This means traversing
+- * the list of possibly many nested references.
++ * For reference objects created via the ref_of, Index, or Load/load_table
++ * operators, we need to get to the base object (as per the ACPI
++ * specification of the object_type and size_of operators). This means
++ * traversing the list of possibly many nested references.
+ */
+ while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
+ switch (obj_desc->reference.opcode) {
+@@ -463,6 +455,11 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
+ }
+ break;
+
++ case AML_LOAD_OP:
++
++ type = ACPI_TYPE_DDB_HANDLE;
++ goto exit;
++
+ case AML_LOCAL_OP:
+ case AML_ARG_OP:
+
+diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c
+index 09d897b..73e29e5 100644
+--- a/drivers/acpi/executer/exresop.c
++++ b/drivers/acpi/executer/exresop.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -137,7 +137,6 @@ acpi_ex_resolve_operands(u16 opcode,
+ union acpi_operand_object *obj_desc;
+ acpi_status status = AE_OK;
+ u8 object_type;
+- void *temp_node;
+ u32 arg_types;
+ const struct acpi_opcode_info *op_info;
+ u32 this_arg_type;
+@@ -239,7 +238,6 @@ acpi_ex_resolve_operands(u16 opcode,
+
+ /*lint -fallthrough */
+
+- case AML_NAME_OP:
+ case AML_INDEX_OP:
+ case AML_REF_OF_OP:
+ case AML_ARG_OP:
+@@ -332,15 +330,6 @@ acpi_ex_resolve_operands(u16 opcode,
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+-
+- if (obj_desc->reference.opcode == AML_NAME_OP) {
+-
+- /* Convert a named reference to the actual named object */
+-
+- temp_node = obj_desc->reference.object;
+- acpi_ut_remove_reference(obj_desc);
+- (*stack_ptr) = temp_node;
+- }
+ goto next_operand;
+
+ case ARGI_DATAREFOBJ: /* Store operator only */
+diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c
+index f4b69a6..76c875b 100644
+--- a/drivers/acpi/executer/exstore.c
++++ b/drivers/acpi/executer/exstore.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -84,8 +84,12 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
+
+ ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc);
+
+- ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s",
+- level, " "));
++ /* Print line header as long as we are not in the middle of an object display */
++
++ if (!((level > 0) && index == 0)) {
++ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s",
++ level, " "));
++ }
+
+ /* Display index for package output only */
+
+@@ -95,12 +99,12 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
+ }
+
+ if (!source_desc) {
+- ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "<Null Object>\n"));
++ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[Null Object]\n"));
+ return_VOID;
+ }
+
+ if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) {
+- ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: ",
++ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s ",
+ acpi_ut_get_object_type_name
+ (source_desc)));
+
+@@ -123,6 +127,8 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
+ return_VOID;
+ }
+
++ /* source_desc is of type ACPI_DESC_TYPE_OPERAND */
++
+ switch (ACPI_GET_OBJECT_TYPE(source_desc)) {
+ case ACPI_TYPE_INTEGER:
+
+@@ -147,7 +153,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
+ (u32) source_desc->buffer.length));
+ ACPI_DUMP_BUFFER(source_desc->buffer.pointer,
+ (source_desc->buffer.length <
+- 32) ? source_desc->buffer.length : 32);
++ 256) ? source_desc->buffer.length : 256);
+ break;
+
+ case ACPI_TYPE_STRING:
+@@ -160,7 +166,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
+ case ACPI_TYPE_PACKAGE:
+
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
+- "[0x%.2X Elements]\n",
++ "[Contains 0x%.2X Elements]\n",
+ source_desc->package.count));
+
+ /* Output the entire contents of the package */
+@@ -180,12 +186,59 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
+ (source_desc->reference.opcode),
+ source_desc->reference.offset));
+ } else {
+- ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]\n",
++ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]",
+ acpi_ps_get_opcode_name
+ (source_desc->reference.opcode)));
+ }
+
+- if (source_desc->reference.object) {
++ if (source_desc->reference.opcode == AML_LOAD_OP) { /* Load and load_table */
++ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
++ " Table OwnerId %p\n",
++ source_desc->reference.object));
++ break;
++ }
++
++ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, " "));
++
++ /* Check for valid node first, then valid object */
++
++ if (source_desc->reference.node) {
++ if (ACPI_GET_DESCRIPTOR_TYPE
++ (source_desc->reference.node) !=
++ ACPI_DESC_TYPE_NAMED) {
++ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
++ " %p - Not a valid namespace node\n",
++ source_desc->reference.
++ node));
++ } else {
++ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
++ "Node %p [%4.4s] ",
++ source_desc->reference.
++ node,
++ (source_desc->reference.
++ node)->name.ascii));
++
++ switch ((source_desc->reference.node)->type) {
++
++ /* These types have no attached object */
++
++ case ACPI_TYPE_DEVICE:
++ acpi_os_printf("Device\n");
++ break;
++
++ case ACPI_TYPE_THERMAL:
++ acpi_os_printf("Thermal Zone\n");
++ break;
++
++ default:
++ acpi_ex_do_debug_object((source_desc->
++ reference.
++ node)->object,
++ level + 4, 0);
++ break;
++ }
++ }
++ } else if (source_desc->reference.object) {
+ if (ACPI_GET_DESCRIPTOR_TYPE
+ (source_desc->reference.object) ==
+ ACPI_DESC_TYPE_NAMED) {
+@@ -198,18 +251,13 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
+ acpi_ex_do_debug_object(source_desc->reference.
+ object, level + 4, 0);
+ }
+- } else if (source_desc->reference.node) {
+- acpi_ex_do_debug_object((source_desc->reference.node)->
+- object, level + 4, 0);
+ }
+ break;
+
+ default:
+
+- ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p %s\n",
+- source_desc,
+- acpi_ut_get_object_type_name
+- (source_desc)));
++ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p\n",
++ source_desc));
+ break;
+ }
+
+@@ -313,7 +361,6 @@ acpi_ex_store(union acpi_operand_object *source_desc,
+ * 4) Store to the debug object
+ */
+ switch (ref_desc->reference.opcode) {
+- case AML_NAME_OP:
+ case AML_REF_OF_OP:
+
+ /* Storing an object into a Name "container" */
+@@ -415,11 +462,24 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
+ */
+ obj_desc = *(index_desc->reference.where);
+
+- status =
+- acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc,
+- walk_state);
+- if (ACPI_FAILURE(status)) {
+- return_ACPI_STATUS(status);
++ if (ACPI_GET_OBJECT_TYPE(source_desc) ==
++ ACPI_TYPE_LOCAL_REFERENCE
++ && source_desc->reference.opcode == AML_LOAD_OP) {
++
++ /* This is a DDBHandle, just add a reference to it */
++
++ acpi_ut_add_reference(source_desc);
++ new_desc = source_desc;
++ } else {
++ /* Normal object, copy it */
++
++ status =
++ acpi_ut_copy_iobject_to_iobject(source_desc,
++ &new_desc,
++ walk_state);
++ if (ACPI_FAILURE(status)) {
++ return_ACPI_STATUS(status);
++ }
+ }
+
+ if (obj_desc) {
+@@ -571,10 +631,17 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
+
+ /* If no implicit conversion, drop into the default case below */
+
+- if ((!implicit_conversion) || (walk_state->opcode == AML_COPY_OP)) {
+-
+- /* Force execution of default (no implicit conversion) */
+-
++ if ((!implicit_conversion) ||
++ ((walk_state->opcode == AML_COPY_OP) &&
++ (target_type != ACPI_TYPE_LOCAL_REGION_FIELD) &&
++ (target_type != ACPI_TYPE_LOCAL_BANK_FIELD) &&
++ (target_type != ACPI_TYPE_LOCAL_INDEX_FIELD))) {
++ /*
++ * Force execution of default (no implicit conversion). Note:
++ * copy_object does not perform an implicit conversion, as per the ACPI
++ * spec -- except in case of region/bank/index fields -- because these
++ * objects must retain their original type permanently.
++ */
+ target_type = ACPI_TYPE_ANY;
+ }
+
+diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c
+index 1d622c6..a6d2168 100644
+--- a/drivers/acpi/executer/exstoren.c
++++ b/drivers/acpi/executer/exstoren.c
+@@ -7,7 +7,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c
+index 8233d40..9a75ff0 100644
+--- a/drivers/acpi/executer/exstorob.c
++++ b/drivers/acpi/executer/exstorob.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c
+index 9460baf..68990f1 100644
+--- a/drivers/acpi/executer/exsystem.c
++++ b/drivers/acpi/executer/exsystem.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -44,7 +44,6 @@
+
+ #include <acpi/acpi.h>
+ #include <acpi/acinterp.h>
+-#include <acpi/acevents.h>
+
+ #define _COMPONENT ACPI_EXECUTER
+ ACPI_MODULE_NAME("exsystem")
+diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c
+index 6b0aecc..86c0388 100644
+--- a/drivers/acpi/executer/exutils.c
++++ b/drivers/acpi/executer/exutils.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -61,7 +61,6 @@
+ #include <acpi/acpi.h>
+ #include <acpi/acinterp.h>
+ #include <acpi/amlcode.h>
+-#include <acpi/acevents.h>
+
+ #define _COMPONENT ACPI_EXECUTER
+ ACPI_MODULE_NAME("exutils")
+@@ -217,9 +216,10 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc)
+
+ /*
+ * Object must be a valid number and we must be executing
+- * a control method
++ * a control method. NS node could be there for AML_INT_NAMEPATH_OP.
+ */
+ if ((!obj_desc) ||
++ (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) ||
+ (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) {
+ return;
+ }
+@@ -240,72 +240,73 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc)
+ * PARAMETERS: field_flags - Flags with Lock rule:
+ * always_lock or never_lock
+ *
+- * RETURN: TRUE/FALSE indicating whether the lock was actually acquired
++ * RETURN: None
+ *
+- * DESCRIPTION: Obtain the global lock and keep track of this fact via two
+- * methods. A global variable keeps the state of the lock, and
+- * the state is returned to the caller.
++ * DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field
++ * flags specifiy that it is to be obtained before field access.
+ *
+ ******************************************************************************/
+
+-u8 acpi_ex_acquire_global_lock(u32 field_flags)
++void acpi_ex_acquire_global_lock(u32 field_flags)
+ {
+- u8 locked = FALSE;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(ex_acquire_global_lock);
+
+- /* Only attempt lock if the always_lock bit is set */
++ /* Only use the lock if the always_lock bit is set */
++
++ if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) {
++ return_VOID;
++ }
+
+- if (field_flags & AML_FIELD_LOCK_RULE_MASK) {
++ /* Attempt to get the global lock, wait forever */
+
+- /* We should attempt to get the lock, wait forever */
++ status = acpi_ex_acquire_mutex_object(ACPI_WAIT_FOREVER,
++ acpi_gbl_global_lock_mutex,
++ acpi_os_get_thread_id());
+
+- status = acpi_ev_acquire_global_lock(ACPI_WAIT_FOREVER);
+- if (ACPI_SUCCESS(status)) {
+- locked = TRUE;
+- } else {
+- ACPI_EXCEPTION((AE_INFO, status,
+- "Could not acquire Global Lock"));
+- }
++ if (ACPI_FAILURE(status)) {
++ ACPI_EXCEPTION((AE_INFO, status,
++ "Could not acquire Global Lock"));
+ }
+
+- return_UINT8(locked);
++ return_VOID;
+ }
+
+ /*******************************************************************************
+ *
+ * FUNCTION: acpi_ex_release_global_lock
+ *
+- * PARAMETERS: locked_by_me - Return value from corresponding call to
+- * acquire_global_lock.
++ * PARAMETERS: field_flags - Flags with Lock rule:
++ * always_lock or never_lock
+ *
+ * RETURN: None
+ *
+- * DESCRIPTION: Release the global lock if it is locked.
++ * DESCRIPTION: Release the ACPI hardware Global Lock
+ *
+ ******************************************************************************/
+
+-void acpi_ex_release_global_lock(u8 locked_by_me)
++void acpi_ex_release_global_lock(u32 field_flags)
+ {
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(ex_release_global_lock);
+
+- /* Only attempt unlock if the caller locked it */
++ /* Only use the lock if the always_lock bit is set */
+
+- if (locked_by_me) {
++ if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) {
++ return_VOID;
++ }
+
+- /* OK, now release the lock */
++ /* Release the global lock */
+
+- status = acpi_ev_release_global_lock();
+- if (ACPI_FAILURE(status)) {
++ status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex);
++ if (ACPI_FAILURE(status)) {
+
+- /* Report the error, but there isn't much else we can do */
++ /* Report the error, but there isn't much else we can do */
+
+- ACPI_EXCEPTION((AE_INFO, status,
+- "Could not release ACPI Global Lock"));
+- }
++ ACPI_EXCEPTION((AE_INFO, status,
++ "Could not release Global Lock"));
+ }
+
+ return_VOID;
+diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
+index c8e3cba..6cf10cb 100644
+--- a/drivers/acpi/fan.c
++++ b/drivers/acpi/fan.c
+@@ -192,17 +192,13 @@ static int acpi_fan_add_fs(struct acpi_device *device)
+ }
+
+ /* 'status' [R/W] */
+- entry = create_proc_entry(ACPI_FAN_FILE_STATE,
+- S_IFREG | S_IRUGO | S_IWUSR,
+- acpi_device_dir(device));
++ entry = proc_create_data(ACPI_FAN_FILE_STATE,
++ S_IFREG | S_IRUGO | S_IWUSR,
++ acpi_device_dir(device),
++ &acpi_fan_state_ops,
++ device);
+ if (!entry)
+ return -ENODEV;
+- else {
+- entry->proc_fops = &acpi_fan_state_ops;
+- entry->data = device;
+- entry->owner = THIS_MODULE;
+- }
+-
+ return 0;
+ }
+
+@@ -260,24 +256,23 @@ static int acpi_fan_add(struct acpi_device *device)
+ result = PTR_ERR(cdev);
+ goto end;
+ }
+- if (cdev) {
+- printk(KERN_INFO PREFIX
+- "%s is registered as cooling_device%d\n",
+- device->dev.bus_id, cdev->id);
+-
+- acpi_driver_data(device) = cdev;
+- result = sysfs_create_link(&device->dev.kobj,
+- &cdev->device.kobj,
+- "thermal_cooling");
+- if (result)
+- return result;
+-
+- result = sysfs_create_link(&cdev->device.kobj,
+- &device->dev.kobj,
+- "device");
+- if (result)
+- return result;
+- }
++
++ printk(KERN_INFO PREFIX
++ "%s is registered as cooling_device%d\n",
++ device->dev.bus_id, cdev->id);
++
++ acpi_driver_data(device) = cdev;
++ result = sysfs_create_link(&device->dev.kobj,
++ &cdev->device.kobj,
++ "thermal_cooling");
++ if (result)
++ printk(KERN_ERR PREFIX "Create sysfs link\n");
++
++ result = sysfs_create_link(&cdev->device.kobj,
++ &device->dev.kobj,
++ "device");
++ if (result)
++ printk(KERN_ERR PREFIX "Create sysfs link\n");
+
+ result = acpi_fan_add_fs(device);
+ if (result)
+diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
+index eda0978..06f8634 100644
+--- a/drivers/acpi/glue.c
++++ b/drivers/acpi/glue.c
+@@ -142,6 +142,7 @@ EXPORT_SYMBOL(acpi_get_physical_device);
+
+ static int acpi_bind_one(struct device *dev, acpi_handle handle)
+ {
++ struct acpi_device *acpi_dev;
+ acpi_status status;
+
+ if (dev->archdata.acpi_handle) {
+@@ -157,6 +158,16 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
+ }
+ dev->archdata.acpi_handle = handle;
+
++ status = acpi_bus_get_device(handle, &acpi_dev);
++ if (!ACPI_FAILURE(status)) {
++ int ret;
++
++ ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
++ "firmware_node");
++ ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
++ "physical_node");
++ }
++
+ return 0;
+ }
+
+@@ -165,8 +176,17 @@ static int acpi_unbind_one(struct device *dev)
+ if (!dev->archdata.acpi_handle)
+ return 0;
+ if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) {
++ struct acpi_device *acpi_dev;
++
+ /* acpi_get_physical_device increase refcnt by one */
+ put_device(dev);
++
++ if (!acpi_bus_get_device(dev->archdata.acpi_handle,
++ &acpi_dev)) {
++ sysfs_remove_link(&dev->kobj, "firmware_node");
++ sysfs_remove_link(&acpi_dev->dev.kobj, "physical_node");
++ }
++
+ acpi_detach_data(dev->archdata.acpi_handle,
+ acpi_glue_data_handler);
+ dev->archdata.acpi_handle = NULL;
+diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c
+index 6031ca1..816894e 100644
+--- a/drivers/acpi/hardware/hwacpi.c
++++ b/drivers/acpi/hardware/hwacpi.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c
+index 117a05c..14bc4f4 100644
+--- a/drivers/acpi/hardware/hwgpe.c
++++ b/drivers/acpi/hardware/hwgpe.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c
+index 73f9c5f..ddf792a 100644
+--- a/drivers/acpi/hardware/hwregs.c
++++ b/drivers/acpi/hardware/hwregs.c
+@@ -7,7 +7,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
+index 4290e01..d9937e0 100644
+--- a/drivers/acpi/hardware/hwsleep.c
++++ b/drivers/acpi/hardware/hwsleep.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -70,9 +70,10 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address)
+
+ /* Get the FACS */
+
+- status =
+- acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
+- (struct acpi_table_header **)&facs);
++ status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
++ ACPI_CAST_INDIRECT_PTR(struct
++ acpi_table_header,
++ &facs));
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+@@ -124,9 +125,10 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address)
+
+ /* Get the FACS */
+
+- status =
+- acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
+- (struct acpi_table_header **)&facs);
++ status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
++ ACPI_CAST_INDIRECT_PTR(struct
++ acpi_table_header,
++ &facs));
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c
+index c32eab6..b53d575 100644
+--- a/drivers/acpi/hardware/hwtimer.c
++++ b/drivers/acpi/hardware/hwtimer.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c
+index 57faf59..c39a7f6 100644
+--- a/drivers/acpi/namespace/nsaccess.c
++++ b/drivers/acpi/namespace/nsaccess.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -208,8 +208,7 @@ acpi_status acpi_ns_root_initialize(void)
+ /* Special case for ACPI Global Lock */
+
+ if (ACPI_STRCMP(init_val->name, "_GL_") == 0) {
+- acpi_gbl_global_lock_mutex =
+- obj_desc->mutex.os_mutex;
++ acpi_gbl_global_lock_mutex = obj_desc;
+
+ /* Create additional counting semaphore for global lock */
+
+@@ -582,44 +581,68 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
+ return_ACPI_STATUS(status);
+ }
+
+- /*
+- * Sanity typecheck of the target object:
+- *
+- * If 1) This is the last segment (num_segments == 0)
+- * 2) And we are looking for a specific type
+- * (Not checking for TYPE_ANY)
+- * 3) Which is not an alias
+- * 4) Which is not a local type (TYPE_SCOPE)
+- * 5) And the type of target object is known (not TYPE_ANY)
+- * 6) And target object does not match what we are looking for
+- *
+- * Then we have a type mismatch. Just warn and ignore it.
+- */
+- if ((num_segments == 0) &&
+- (type_to_check_for != ACPI_TYPE_ANY) &&
+- (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) &&
+- (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) &&
+- (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) &&
+- (this_node->type != ACPI_TYPE_ANY) &&
+- (this_node->type != type_to_check_for)) {
+-
+- /* Complain about a type mismatch */
+-
+- ACPI_WARNING((AE_INFO,
+- "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)",
+- ACPI_CAST_PTR(char, &simple_name),
+- acpi_ut_get_type_name(this_node->type),
+- acpi_ut_get_type_name
+- (type_to_check_for)));
++ /* More segments to follow? */
++
++ if (num_segments > 0) {
++ /*
++ * If we have an alias to an object that opens a scope (such as a
++ * device or processor), we need to dereference the alias here so that
++ * we can access any children of the original node (via the remaining
++ * segments).
++ */
++ if (this_node->type == ACPI_TYPE_LOCAL_ALIAS) {
++ if (acpi_ns_opens_scope
++ (((struct acpi_namespace_node *)this_node->
++ object)->type)) {
++ this_node =
++ (struct acpi_namespace_node *)
++ this_node->object;
++ }
++ }
+ }
+
+- /*
+- * If this is the last name segment and we are not looking for a
+- * specific type, but the type of found object is known, use that type
+- * to see if it opens a scope.
+- */
+- if ((num_segments == 0) && (type == ACPI_TYPE_ANY)) {
+- type = this_node->type;
++ /* Special handling for the last segment (num_segments == 0) */
++
++ else {
++ /*
++ * Sanity typecheck of the target object:
++ *
++ * If 1) This is the last segment (num_segments == 0)
++ * 2) And we are looking for a specific type
++ * (Not checking for TYPE_ANY)
++ * 3) Which is not an alias
++ * 4) Which is not a local type (TYPE_SCOPE)
++ * 5) And the type of target object is known (not TYPE_ANY)
++ * 6) And target object does not match what we are looking for
++ *
++ * Then we have a type mismatch. Just warn and ignore it.
++ */
++ if ((type_to_check_for != ACPI_TYPE_ANY) &&
++ (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) &&
++ (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS)
++ && (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE)
++ && (this_node->type != ACPI_TYPE_ANY)
++ && (this_node->type != type_to_check_for)) {
++
++ /* Complain about a type mismatch */
++
++ ACPI_WARNING((AE_INFO,
++ "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)",
++ ACPI_CAST_PTR(char, &simple_name),
++ acpi_ut_get_type_name(this_node->
++ type),
++ acpi_ut_get_type_name
++ (type_to_check_for)));
++ }
++
++ /*
++ * If this is the last name segment and we are not looking for a
++ * specific type, but the type of found object is known, use that type
++ * to (later) see if it opens a scope.
++ */
++ if (type == ACPI_TYPE_ANY) {
++ type = this_node->type;
++ }
+ }
+
+ /* Point to next name segment and make this node current */
+diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c
+index 1d693d8..3a1740a 100644
+--- a/drivers/acpi/namespace/nsalloc.c
++++ b/drivers/acpi/namespace/nsalloc.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c
+index 1fc4f86..5445751 100644
+--- a/drivers/acpi/namespace/nsdump.c
++++ b/drivers/acpi/namespace/nsdump.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -249,7 +249,9 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
+ acpi_os_printf("ID %X Len %.4X Addr %p\n",
+ obj_desc->processor.proc_id,
+ obj_desc->processor.length,
+- (char *)obj_desc->processor.address);
++ ACPI_CAST_PTR(void,
++ obj_desc->processor.
++ address));
+ break;
+
+ case ACPI_TYPE_DEVICE:
+@@ -320,9 +322,8 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
+ space_id));
+ if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
+ acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n",
+- ACPI_FORMAT_UINT64(obj_desc->
+- region.
+- address),
++ ACPI_FORMAT_NATIVE_UINT
++ (obj_desc->region.address),
+ obj_desc->region.length);
+ } else {
+ acpi_os_printf
+diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c
+index 5097e16..428f50f 100644
+--- a/drivers/acpi/namespace/nsdumpdv.c
++++ b/drivers/acpi/namespace/nsdumpdv.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
+index 97b2ac5..14bdfa9 100644
+--- a/drivers/acpi/namespace/nseval.c
++++ b/drivers/acpi/namespace/nseval.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
+index 33db224..6d6d930 100644
+--- a/drivers/acpi/namespace/nsinit.c
++++ b/drivers/acpi/namespace/nsinit.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -244,6 +244,10 @@ acpi_ns_init_one_object(acpi_handle obj_handle,
+ info->field_count++;
+ break;
+
++ case ACPI_TYPE_LOCAL_BANK_FIELD:
++ info->field_count++;
++ break;
++
+ case ACPI_TYPE_BUFFER:
+ info->buffer_count++;
+ break;
+@@ -287,6 +291,12 @@ acpi_ns_init_one_object(acpi_handle obj_handle,
+ status = acpi_ds_get_buffer_field_arguments(obj_desc);
+ break;
+
++ case ACPI_TYPE_LOCAL_BANK_FIELD:
++
++ info->field_init++;
++ status = acpi_ds_get_bank_field_arguments(obj_desc);
++ break;
++
+ case ACPI_TYPE_BUFFER:
+
+ info->buffer_init++;
+diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c
+index d4f9654..2c92f6c 100644
+--- a/drivers/acpi/namespace/nsload.c
++++ b/drivers/acpi/namespace/nsload.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -107,11 +107,11 @@ acpi_ns_load_table(acpi_native_uint table_index,
+ goto unlock;
+ }
+
+- status = acpi_ns_parse_table(table_index, node->child);
++ status = acpi_ns_parse_table(table_index, node);
+ if (ACPI_SUCCESS(status)) {
+ acpi_tb_set_table_loaded_flag(table_index, TRUE);
+ } else {
+- acpi_tb_release_owner_id(table_index);
++ (void)acpi_tb_release_owner_id(table_index);
+ }
+
+ unlock:
+diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c
+index cbd94af..cffef1b 100644
+--- a/drivers/acpi/namespace/nsnames.c
++++ b/drivers/acpi/namespace/nsnames.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -180,6 +180,12 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
+ next_node = node;
+
+ while (next_node && (next_node != acpi_gbl_root_node)) {
++ if (ACPI_GET_DESCRIPTOR_TYPE(next_node) != ACPI_DESC_TYPE_NAMED) {
++ ACPI_ERROR((AE_INFO,
++ "Invalid NS Node (%p) while traversing path",
++ next_node));
++ return 0;
++ }
+ size += ACPI_PATH_SEGMENT_LENGTH;
+ next_node = acpi_ns_get_parent_node(next_node);
+ }
+diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c
+index d9d7377..15fe09e 100644
+--- a/drivers/acpi/namespace/nsobject.c
++++ b/drivers/acpi/namespace/nsobject.c
+@@ -6,7 +6,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c
+index e696aa8..46a79b0 100644
+--- a/drivers/acpi/namespace/nsparse.c
++++ b/drivers/acpi/namespace/nsparse.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -64,7 +64,8 @@ ACPI_MODULE_NAME("nsparse")
+ ******************************************************************************/
+ acpi_status
+ acpi_ns_one_complete_parse(acpi_native_uint pass_number,
+- acpi_native_uint table_index)
++ acpi_native_uint table_index,
++ struct acpi_namespace_node * start_node)
+ {
+ union acpi_parse_object *parse_root;
+ acpi_status status;
+@@ -111,14 +112,25 @@ acpi_ns_one_complete_parse(acpi_native_uint pass_number,
+ aml_start = (u8 *) table + sizeof(struct acpi_table_header);
+ aml_length = table->length - sizeof(struct acpi_table_header);
+ status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL,
+- aml_start, aml_length, NULL,
+- (u8) pass_number);
++ aml_start, (u32) aml_length,
++ NULL, (u8) pass_number);
+ }
+
+ if (ACPI_FAILURE(status)) {
+ acpi_ds_delete_walk_state(walk_state);
+- acpi_ps_delete_parse_tree(parse_root);
+- return_ACPI_STATUS(status);
++ goto cleanup;
++ }
++
++ /* start_node is the default location to load the table */
++
++ if (start_node && start_node != acpi_gbl_root_node) {
++ status =
++ acpi_ds_scope_stack_push(start_node, ACPI_TYPE_METHOD,
++ walk_state);
++ if (ACPI_FAILURE(status)) {
++ acpi_ds_delete_walk_state(walk_state);
++ goto cleanup;
++ }
+ }
+
+ /* Parse the AML */
+@@ -127,6 +139,7 @@ acpi_ns_one_complete_parse(acpi_native_uint pass_number,
+ (unsigned)pass_number));
+ status = acpi_ps_parse_aml(walk_state);
+
++ cleanup:
+ acpi_ps_delete_parse_tree(parse_root);
+ return_ACPI_STATUS(status);
+ }
+@@ -163,7 +176,9 @@ acpi_ns_parse_table(acpi_native_uint table_index,
+ * performs another complete parse of the AML.
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n"));
+- status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, table_index);
++ status =
++ acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, table_index,
++ start_node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+@@ -178,7 +193,9 @@ acpi_ns_parse_table(acpi_native_uint table_index,
+ * parse objects are all cached.
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n"));
+- status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, table_index);
++ status =
++ acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, table_index,
++ start_node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c
+index e863be6..8399276 100644
+--- a/drivers/acpi/namespace/nssearch.c
++++ b/drivers/acpi/namespace/nssearch.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c
+index 90fd059..64c0398 100644
+--- a/drivers/acpi/namespace/nsutils.c
++++ b/drivers/acpi/namespace/nsutils.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c
+index 280b835..3c905ce 100644
+--- a/drivers/acpi/namespace/nswalk.c
++++ b/drivers/acpi/namespace/nswalk.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -77,9 +77,7 @@ struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, struct
+
+ /* It's really the parent's _scope_ that we want */
+
+- if (parent_node->child) {
+- next_node = parent_node->child;
+- }
++ next_node = parent_node->child;
+ }
+
+ else {
+diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
+index b92133f..a8d5491 100644
+--- a/drivers/acpi/namespace/nsxfeval.c
++++ b/drivers/acpi/namespace/nsxfeval.c
+@@ -6,7 +6,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -467,10 +467,13 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
+ return (AE_CTRL_DEPTH);
+ }
+
+- if (!(flags & ACPI_STA_DEVICE_PRESENT)) {
+-
+- /* Don't examine children of the device if not present */
+-
++ if (!(flags & ACPI_STA_DEVICE_PRESENT) &&
++ !(flags & ACPI_STA_DEVICE_FUNCTIONING)) {
++ /*
++ * Don't examine the children of the device only when the
++ * device is neither present nor functional. See ACPI spec,
++ * description of _STA for more information.
++ */
+ return (AE_CTRL_DEPTH);
+ }
+
+@@ -539,7 +542,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
+ * value is returned to the caller.
+ *
+ * This is a wrapper for walk_namespace, but the callback performs
+- * additional filtering. Please see acpi_get_device_callback.
++ * additional filtering. Please see acpi_ns_get_device_callback.
+ *
+ ******************************************************************************/
+
+diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
+index b489781..a287ed5 100644
+--- a/drivers/acpi/namespace/nsxfname.c
++++ b/drivers/acpi/namespace/nsxfname.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c
+index faa3758..2b375ee 100644
+--- a/drivers/acpi/namespace/nsxfobj.c
++++ b/drivers/acpi/namespace/nsxfobj.c
+@@ -6,7 +6,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
+index a697fb6..235a138 100644
+--- a/drivers/acpi/osl.c
++++ b/drivers/acpi/osl.c
+@@ -4,6 +4,8 @@
+ * Copyright (C) 2000 Andrew Henroid
+ * Copyright (C) 2001, 2002 Andy Grover <andrew.grover at intel.com>
+ * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh at intel.com>
++ * Copyright (c) 2008 Intel Corporation
++ * Author: Matthew Wilcox <willy at linux.intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+@@ -37,15 +39,18 @@
+ #include <linux/workqueue.h>
+ #include <linux/nmi.h>
+ #include <linux/acpi.h>
+-#include <acpi/acpi.h>
+-#include <asm/io.h>
+-#include <acpi/acpi_bus.h>
+-#include <acpi/processor.h>
+-#include <asm/uaccess.h>
+-
+ #include <linux/efi.h>
+ #include <linux/ioport.h>
+ #include <linux/list.h>
++#include <linux/jiffies.h>
++#include <linux/semaphore.h>
++
++#include <asm/io.h>
++#include <asm/uaccess.h>
++
++#include <acpi/acpi.h>
++#include <acpi/acpi_bus.h>
++#include <acpi/processor.h>
+
+ #define _COMPONENT ACPI_OS_SERVICES
+ ACPI_MODULE_NAME("osl");
+@@ -737,6 +742,7 @@ EXPORT_SYMBOL(acpi_os_execute);
+ void acpi_os_wait_events_complete(void *context)
+ {
+ flush_workqueue(kacpid_wq);
++ flush_workqueue(kacpi_notify_wq);
+ }
+
+ EXPORT_SYMBOL(acpi_os_wait_events_complete);
+@@ -764,7 +770,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 +796,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 +809,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 +827,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 +857,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/parser/psargs.c b/drivers/acpi/parser/psargs.c
+index c2b9835..f1e8bf6 100644
+--- a/drivers/acpi/parser/psargs.c
++++ b/drivers/acpi/parser/psargs.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -230,12 +230,12 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
+ struct acpi_parse_state *parser_state,
+ union acpi_parse_object *arg, u8 possible_method_call)
+ {
++ acpi_status status;
+ char *path;
+ union acpi_parse_object *name_op;
+- acpi_status status;
+ union acpi_operand_object *method_desc;
+ struct acpi_namespace_node *node;
+- union acpi_generic_state scope_info;
++ u8 *start = parser_state->aml;
+
+ ACPI_FUNCTION_TRACE(ps_get_next_namepath);
+
+@@ -249,25 +249,18 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
+ return_ACPI_STATUS(AE_OK);
+ }
+
+- /* Setup search scope info */
+-
+- scope_info.scope.node = NULL;
+- node = parser_state->start_node;
+- if (node) {
+- scope_info.scope.node = node;
+- }
+-
+ /*
+- * Lookup the name in the internal namespace. We don't want to add
+- * anything new to the namespace here, however, so we use MODE_EXECUTE.
++ * Lookup the name in the internal namespace, starting with the current
++ * scope. We don't want to add anything new to the namespace here,
++ * however, so we use MODE_EXECUTE.
+ * Allow searching of the parent tree, but don't open a new scope -
+ * we just want to lookup the object (must be mode EXECUTE to perform
+ * the upsearch)
+ */
+- status =
+- acpi_ns_lookup(&scope_info, path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
+- ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
+- NULL, &node);
++ status = acpi_ns_lookup(walk_state->scope_info, path,
++ ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
++ ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
++ NULL, &node);
+
+ /*
+ * If this name is a control method invocation, we must
+@@ -275,6 +268,16 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
+ */
+ if (ACPI_SUCCESS(status) &&
+ possible_method_call && (node->type == ACPI_TYPE_METHOD)) {
++ if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) {
++ /*
++ * acpi_ps_get_next_namestring has increased the AML pointer,
++ * so we need to restore the saved AML pointer for method call.
++ */
++ walk_state->parser_state.aml = start;
++ walk_state->arg_count = 1;
++ acpi_ps_init_op(arg, AML_INT_METHODCALL_OP);
++ return_ACPI_STATUS(AE_OK);
++ }
+
+ /* This name is actually a control method invocation */
+
+@@ -686,9 +689,29 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+- status =
+- acpi_ps_get_next_namepath(walk_state, parser_state,
+- arg, 0);
++ /* To support super_name arg of Unload */
++
++ if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) {
++ status =
++ acpi_ps_get_next_namepath(walk_state,
++ parser_state, arg,
++ 1);
++
++ /*
++ * If the super_name arg of Unload is a method call,
++ * we have restored the AML pointer, just free this Arg
++ */
++ if (arg->common.aml_opcode ==
++ AML_INT_METHODCALL_OP) {
++ acpi_ps_free_op(arg);
++ arg = NULL;
++ }
++ } else {
++ status =
++ acpi_ps_get_next_namepath(walk_state,
++ parser_state, arg,
++ 0);
++ }
+ } else {
+ /* Single complex argument, nothing returned */
+
+diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c
+index 773aee8..c06238e 100644
+--- a/drivers/acpi/parser/psloop.c
++++ b/drivers/acpi/parser/psloop.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -182,6 +182,7 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state,
+ ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state);
+
+ unnamed_op->common.value.arg = NULL;
++ unnamed_op->common.arg_list_length = 0;
+ unnamed_op->common.aml_opcode = walk_state->opcode;
+
+ /*
+@@ -241,7 +242,8 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state,
+ acpi_ps_append_arg(*op, unnamed_op->common.value.arg);
+ acpi_gbl_depth++;
+
+- if ((*op)->common.aml_opcode == AML_REGION_OP) {
++ if ((*op)->common.aml_opcode == AML_REGION_OP ||
++ (*op)->common.aml_opcode == AML_DATA_REGION_OP) {
+ /*
+ * Defer final parsing of an operation_region body, because we don't
+ * have enough info in the first pass to parse it correctly (i.e.,
+@@ -280,6 +282,9 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state,
+ acpi_status status = AE_OK;
+ union acpi_parse_object *op;
+ union acpi_parse_object *named_op = NULL;
++ union acpi_parse_object *parent_scope;
++ u8 argument_count;
++ const struct acpi_opcode_info *op_info;
+
+ ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state);
+
+@@ -320,8 +325,32 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state,
+ op->named.length = 0;
+ }
+
+- acpi_ps_append_arg(acpi_ps_get_parent_scope
+- (&(walk_state->parser_state)), op);
++ if (walk_state->opcode == AML_BANK_FIELD_OP) {
++ /*
++ * Backup to beginning of bank_field declaration
++ * body_length is unknown until we parse the body
++ */
++ op->named.data = aml_op_start;
++ op->named.length = 0;
++ }
++
++ parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state));
++ acpi_ps_append_arg(parent_scope, op);
++
++ if (parent_scope) {
++ op_info =
++ acpi_ps_get_opcode_info(parent_scope->common.aml_opcode);
++ if (op_info->flags & AML_HAS_TARGET) {
++ argument_count =
++ acpi_ps_get_argument_count(op_info->type);
++ if (parent_scope->common.arg_list_length >
++ argument_count) {
++ op->common.flags |= ACPI_PARSEOP_TARGET;
++ }
++ } else if (parent_scope->common.aml_opcode == AML_INCREMENT_OP) {
++ op->common.flags |= ACPI_PARSEOP_TARGET;
++ }
++ }
+
+ if (walk_state->descending_callback != NULL) {
+ /*
+@@ -603,13 +632,6 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state,
+ acpi_ps_pop_scope(&(walk_state->parser_state), op,
+ &walk_state->arg_types,
+ &walk_state->arg_count);
+-
+- if ((*op)->common.aml_opcode != AML_WHILE_OP) {
+- status2 = acpi_ds_result_stack_pop(walk_state);
+- if (ACPI_FAILURE(status2)) {
+- return_ACPI_STATUS(status2);
+- }
+- }
+ }
+
+ /* Close this iteration of the While loop */
+@@ -640,10 +662,6 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state,
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
+ }
+- status2 = acpi_ds_result_stack_pop(walk_state);
+- if (ACPI_FAILURE(status2)) {
+- return_ACPI_STATUS(status2);
+- }
+
+ acpi_ut_delete_generic_state
+ (acpi_ut_pop_generic_state
+@@ -1005,7 +1023,8 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
+ acpi_gbl_depth--;
+ }
+
+- if (op->common.aml_opcode == AML_REGION_OP) {
++ if (op->common.aml_opcode == AML_REGION_OP ||
++ op->common.aml_opcode == AML_DATA_REGION_OP) {
+ /*
+ * Skip parsing of control method or opregion body,
+ * because we don't have enough info in the first pass
+@@ -1030,6 +1049,16 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
+ (u32) (parser_state->aml - op->named.data);
+ }
+
++ if (op->common.aml_opcode == AML_BANK_FIELD_OP) {
++ /*
++ * Backup to beginning of bank_field declaration
++ *
++ * body_length is unknown until we parse the body
++ */
++ op->named.length =
++ (u32) (parser_state->aml - op->named.data);
++ }
++
+ /* This op complete, notify the dispatcher */
+
+ if (walk_state->ascending_callback != NULL) {
+diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
+index 9296e86..f425ab3 100644
+--- a/drivers/acpi/parser/psopcode.c
++++ b/drivers/acpi/parser/psopcode.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -49,6 +49,9 @@
+ #define _COMPONENT ACPI_PARSER
+ ACPI_MODULE_NAME("psopcode")
+
++static const u8 acpi_gbl_argument_count[] =
++ { 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 6 };
++
+ /*******************************************************************************
+ *
+ * NAME: acpi_gbl_aml_op_info
+@@ -59,6 +62,7 @@ ACPI_MODULE_NAME("psopcode")
+ * the operand type.
+ *
+ ******************************************************************************/
++
+ /*
+ * Summary of opcode types/flags
+ *
+@@ -176,6 +180,7 @@ ACPI_MODULE_NAME("psopcode")
+ AML_CREATE_QWORD_FIELD_OP
+
+ ******************************************************************************/
++
+ /*
+ * Master Opcode information table. A summary of everything we know about each
+ * opcode, all in one place.
+@@ -515,9 +520,10 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
+ AML_TYPE_NAMED_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
+ /* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP,
+- ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
++ ACPI_TYPE_LOCAL_BANK_FIELD, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_FIELD,
+- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
++ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD |
++ AML_DEFER),
+
+ /* Internal opcodes that map to invalid AML opcodes */
+
+@@ -619,9 +625,9 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
+ AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R),
+ /* 7C */ ACPI_OP("DataTableRegion", ARGP_DATA_REGION_OP,
+ ARGI_DATA_REGION_OP, ACPI_TYPE_REGION,
+- AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
++ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+- AML_NSNODE | AML_NAMED),
++ AML_NSNODE | AML_NAMED | AML_DEFER),
+ /* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP,
+ ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_NO_OBJ,
+@@ -779,3 +785,25 @@ char *acpi_ps_get_opcode_name(u16 opcode)
+
+ #endif
+ }
++
++/*******************************************************************************
++ *
++ * FUNCTION: acpi_ps_get_argument_count
++ *
++ * PARAMETERS: op_type - Type associated with the AML opcode
++ *
++ * RETURN: Argument count
++ *
++ * DESCRIPTION: Obtain the number of expected arguments for an AML opcode
++ *
++ ******************************************************************************/
++
++u8 acpi_ps_get_argument_count(u32 op_type)
++{
++
++ if (op_type <= AML_TYPE_EXEC_6A_0T_1R) {
++ return (acpi_gbl_argument_count[op_type]);
++ }
++
++ return (0);
++}
+diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
+index 5d63f48..15e1702 100644
+--- a/drivers/acpi/parser/psparse.c
++++ b/drivers/acpi/parser/psparse.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -205,6 +205,8 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
+ || (op->common.parent->common.aml_opcode ==
+ AML_PACKAGE_OP)
+ || (op->common.parent->common.aml_opcode ==
++ AML_BANK_FIELD_OP)
++ || (op->common.parent->common.aml_opcode ==
+ AML_VAR_PACKAGE_OP)) {
+ replacement_op =
+ acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP);
+@@ -349,19 +351,13 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
+
+ parser_state->aml = walk_state->aml_last_while;
+ walk_state->control_state->common.value = FALSE;
+- status = acpi_ds_result_stack_pop(walk_state);
+- if (ACPI_SUCCESS(status)) {
+- status = AE_CTRL_BREAK;
+- }
++ status = AE_CTRL_BREAK;
+ break;
+
+ case AE_CTRL_CONTINUE:
+
+ parser_state->aml = walk_state->aml_last_while;
+- status = acpi_ds_result_stack_pop(walk_state);
+- if (ACPI_SUCCESS(status)) {
+- status = AE_CTRL_CONTINUE;
+- }
++ status = AE_CTRL_CONTINUE;
+ break;
+
+ case AE_CTRL_PENDING:
+@@ -383,10 +379,7 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
+ * Just close out this package
+ */
+ parser_state->aml = acpi_ps_get_next_package_end(parser_state);
+- status = acpi_ds_result_stack_pop(walk_state);
+- if (ACPI_SUCCESS(status)) {
+- status = AE_CTRL_PENDING;
+- }
++ status = AE_CTRL_PENDING;
+ break;
+
+ case AE_CTRL_FALSE:
+@@ -541,7 +534,7 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
+ if ((status == AE_ALREADY_EXISTS) &&
+ (!walk_state->method_desc->method.mutex)) {
+ ACPI_INFO((AE_INFO,
+- "Marking method %4.4s as Serialized",
++ "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error",
+ walk_state->method_node->name.
+ ascii));
+
+@@ -601,6 +594,30 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
+ * The object is deleted
+ */
+ if (!previous_walk_state->return_desc) {
++ /*
++ * In slack mode execution, if there is no return value
++ * we should implicitly return zero (0) as a default value.
++ */
++ if (acpi_gbl_enable_interpreter_slack &&
++ !previous_walk_state->
++ implicit_return_obj) {
++ previous_walk_state->
++ implicit_return_obj =
++ acpi_ut_create_internal_object
++ (ACPI_TYPE_INTEGER);
++ if (!previous_walk_state->
++ implicit_return_obj) {
++ return_ACPI_STATUS
++ (AE_NO_MEMORY);
++ }
++
++ previous_walk_state->
++ implicit_return_obj->
++ integer.value = 0;
++ }
++
++ /* Restart the calling control method */
++
+ status =
+ acpi_ds_restart_control_method
+ (walk_state,
+diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c
+index 77cfa4e..ee50e67 100644
+--- a/drivers/acpi/parser/psscope.c
++++ b/drivers/acpi/parser/psscope.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c
+index 966e7ea..1dd355d 100644
+--- a/drivers/acpi/parser/pstree.c
++++ b/drivers/acpi/parser/pstree.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -171,6 +171,8 @@ acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg)
+ while (arg) {
+ arg->common.parent = op;
+ arg = arg->common.next;
++
++ op->common.arg_list_length++;
+ }
+ }
+
+diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c
+index 8ca5200..7cf1f65 100644
+--- a/drivers/acpi/parser/psutils.c
++++ b/drivers/acpi/parser/psutils.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c
+index 49f9757..8b86ad5 100644
+--- a/drivers/acpi/parser/pswalk.c
++++ b/drivers/acpi/parser/pswalk.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c
+index 94103bc..5258145 100644
+--- a/drivers/acpi/parser/psxface.c
++++ b/drivers/acpi/parser/psxface.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
+index 76bf6d9..81e4f08 100644
+--- a/drivers/acpi/power.c
++++ b/drivers/acpi/power.c
+@@ -93,6 +93,7 @@ struct acpi_power_resource {
+ static struct list_head acpi_power_resource_list;
+
+ static const struct file_operations acpi_power_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_power_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -121,7 +122,7 @@ acpi_power_get_context(acpi_handle handle,
+ }
+
+ *resource = acpi_driver_data(device);
+- if (!resource)
++ if (!*resource)
+ return -ENODEV;
+
+ return 0;
+@@ -543,15 +544,11 @@ static int acpi_power_add_fs(struct acpi_device *device)
+ }
+
+ /* 'status' [R] */
+- entry = create_proc_entry(ACPI_POWER_FILE_STATUS,
+- S_IRUGO, acpi_device_dir(device));
++ entry = proc_create_data(ACPI_POWER_FILE_STATUS,
++ S_IRUGO, acpi_device_dir(device),
++ &acpi_power_fops, acpi_driver_data(device));
+ if (!entry)
+ return -EIO;
+- else {
+- entry->proc_fops = &acpi_power_fops;
+- entry->data = acpi_driver_data(device);
+- }
+-
+ return 0;
+ }
+
+diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
+index a825b43..386e5aa 100644
+--- a/drivers/acpi/processor_core.c
++++ b/drivers/acpi/processor_core.c
+@@ -112,6 +112,7 @@ static struct acpi_driver acpi_processor_driver = {
+ #define UNINSTALL_NOTIFY_HANDLER 2
+
+ static const struct file_operations acpi_processor_info_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_processor_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -326,40 +327,30 @@ static int acpi_processor_add_fs(struct acpi_device *device)
+ acpi_device_dir(device)->owner = THIS_MODULE;
+
+ /* 'info' [R] */
+- entry = create_proc_entry(ACPI_PROCESSOR_FILE_INFO,
+- S_IRUGO, acpi_device_dir(device));
++ entry = proc_create_data(ACPI_PROCESSOR_FILE_INFO,
++ S_IRUGO, acpi_device_dir(device),
++ &acpi_processor_info_fops,
++ acpi_driver_data(device));
+ if (!entry)
+ return -EIO;
+- else {
+- entry->proc_fops = &acpi_processor_info_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
+
+ /* 'throttling' [R/W] */
+- entry = create_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
+- S_IFREG | S_IRUGO | S_IWUSR,
+- acpi_device_dir(device));
++ entry = proc_create_data(ACPI_PROCESSOR_FILE_THROTTLING,
++ S_IFREG | S_IRUGO | S_IWUSR,
++ acpi_device_dir(device),
++ &acpi_processor_throttling_fops,
++ acpi_driver_data(device));
+ if (!entry)
+ return -EIO;
+- else {
+- entry->proc_fops = &acpi_processor_throttling_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
+
+ /* 'limit' [R/W] */
+- entry = create_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
+- S_IFREG | S_IRUGO | S_IWUSR,
+- acpi_device_dir(device));
++ entry = proc_create_data(ACPI_PROCESSOR_FILE_LIMIT,
++ S_IFREG | S_IRUGO | S_IWUSR,
++ acpi_device_dir(device),
++ &acpi_processor_limit_fops,
++ acpi_driver_data(device));
+ if (!entry)
+ return -EIO;
+- else {
+- entry->proc_fops = &acpi_processor_limit_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
+-
+ return 0;
+ }
+
+@@ -612,6 +603,15 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
+ request_region(pr->throttling.address, 6, "ACPI CPU throttle");
+ }
+
++ /*
++ * If ACPI describes a slot number for this CPU, we can use it
++ * ensure we get the right value in the "physical id" field
++ * of /proc/cpuinfo
++ */
++ status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer);
++ if (ACPI_SUCCESS(status))
++ arch_fix_phys_package_id(pr->id, object.integer.value);
++
+ return 0;
+ }
+
+@@ -674,22 +674,21 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
+ result = PTR_ERR(pr->cdev);
+ goto end;
+ }
+- if (pr->cdev) {
+- printk(KERN_INFO PREFIX
+- "%s is registered as cooling_device%d\n",
+- device->dev.bus_id, pr->cdev->id);
+-
+- result = sysfs_create_link(&device->dev.kobj,
+- &pr->cdev->device.kobj,
+- "thermal_cooling");
+- if (result)
+- return result;
+- result = sysfs_create_link(&pr->cdev->device.kobj,
+- &device->dev.kobj,
+- "device");
+- if (result)
+- return result;
+- }
++
++ printk(KERN_INFO PREFIX
++ "%s is registered as cooling_device%d\n",
++ device->dev.bus_id, pr->cdev->id);
++
++ result = sysfs_create_link(&device->dev.kobj,
++ &pr->cdev->device.kobj,
++ "thermal_cooling");
++ if (result)
++ printk(KERN_ERR PREFIX "Create sysfs link\n");
++ result = sysfs_create_link(&pr->cdev->device.kobj,
++ &device->dev.kobj,
++ "device");
++ if (result)
++ printk(KERN_ERR PREFIX "Create sysfs link\n");
+
+ if (pr->flags.throttling) {
+ printk(KERN_INFO PREFIX "%s [%s] (supports",
+diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
+index 788da97..2dd2c1f 100644
+--- a/drivers/acpi/processor_idle.c
++++ b/drivers/acpi/processor_idle.c
+@@ -418,13 +418,12 @@ static void acpi_processor_idle(void)
+
+ cx = pr->power.state;
+ if (!cx || acpi_idle_suspend) {
+- if (pm_idle_save)
+- pm_idle_save();
+- else
++ if (pm_idle_save) {
++ pm_idle_save(); /* enables IRQs */
++ } else {
+ acpi_safe_halt();
+-
+- if (irqs_disabled())
+ local_irq_enable();
++ }
+
+ return;
+ }
+@@ -520,10 +519,12 @@ static void acpi_processor_idle(void)
+ * Use the appropriate idle routine, the one that would
+ * be used without acpi C-states.
+ */
+- if (pm_idle_save)
+- pm_idle_save();
+- else
++ if (pm_idle_save) {
++ pm_idle_save(); /* enables IRQs */
++ } else {
+ acpi_safe_halt();
++ local_irq_enable();
++ }
+
+ /*
+ * TBD: Can't get time duration while in C1, as resumes
+@@ -534,8 +535,6 @@ static void acpi_processor_idle(void)
+ * skew otherwise.
+ */
+ sleep_ticks = 0xFFFFFFFF;
+- if (irqs_disabled())
+- local_irq_enable();
+
+ break;
+
+@@ -848,6 +847,7 @@ static int acpi_processor_get_power_info_default(struct acpi_processor *pr)
+ /* all processors need to support C1 */
+ pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
+ pr->power.states[ACPI_STATE_C1].valid = 1;
++ pr->power.states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_HALT;
+ }
+ /* the C0 state only exists as a filler in our array */
+ pr->power.states[ACPI_STATE_C0].valid = 1;
+@@ -960,6 +960,9 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
+ cx.address);
+ }
+
++ if (cx.type == ACPI_STATE_C1) {
++ cx.valid = 1;
++ }
+
+ obj = &(element->package.elements[2]);
+ if (obj->type != ACPI_TYPE_INTEGER)
+@@ -1283,6 +1286,7 @@ static int acpi_processor_power_open_fs(struct inode *inode, struct file *file)
+ }
+
+ static const struct file_operations acpi_processor_power_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_processor_power_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -1295,6 +1299,8 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
+ {
+ int result = 0;
+
++ if (boot_option_idle_override)
++ return 0;
+
+ if (!pr)
+ return -EINVAL;
+@@ -1734,6 +1740,9 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
+ {
+ int ret;
+
++ if (boot_option_idle_override)
++ return 0;
++
+ if (!pr)
+ return -EINVAL;
+
+@@ -1764,6 +1773,8 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
+ struct proc_dir_entry *entry = NULL;
+ unsigned int i;
+
++ if (boot_option_idle_override)
++ return 0;
+
+ if (!first_run) {
+ dmi_check_system(processor_power_dmi_table);
+@@ -1799,7 +1810,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
+ * Note that we use previously set idle handler will be used on
+ * platforms that only support C1.
+ */
+- if ((pr->flags.power) && (!boot_option_idle_override)) {
++ if (pr->flags.power) {
+ #ifdef CONFIG_CPU_IDLE
+ acpi_processor_setup_cpuidle(pr);
+ pr->power.dev.cpu = pr->id;
+@@ -1823,24 +1834,23 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
+ }
+
+ /* 'power' [R] */
+- entry = create_proc_entry(ACPI_PROCESSOR_FILE_POWER,
+- S_IRUGO, acpi_device_dir(device));
++ entry = proc_create_data(ACPI_PROCESSOR_FILE_POWER,
++ S_IRUGO, acpi_device_dir(device),
++ &acpi_processor_power_fops,
++ acpi_driver_data(device));
+ if (!entry)
+ return -EIO;
+- else {
+- entry->proc_fops = &acpi_processor_power_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
+-
+ return 0;
+ }
+
+ int acpi_processor_power_exit(struct acpi_processor *pr,
+ struct acpi_device *device)
+ {
++ if (boot_option_idle_override)
++ return 0;
++
+ #ifdef CONFIG_CPU_IDLE
+- if ((pr->flags.power) && (!boot_option_idle_override))
++ if (pr->flags.power)
+ cpuidle_unregister_device(&pr->power.dev);
+ #endif
+ pr->flags.power_setup_done = 0;
+diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
+index b477a4b..d80b2d1 100644
+--- a/drivers/acpi/processor_perflib.c
++++ b/drivers/acpi/processor_perflib.c
+@@ -411,6 +411,7 @@ EXPORT_SYMBOL(acpi_processor_notify_smm);
+
+ static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
+ static struct file_operations acpi_processor_perf_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_processor_perf_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -456,7 +457,6 @@ static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
+
+ static void acpi_cpufreq_add_file(struct acpi_processor *pr)
+ {
+- struct proc_dir_entry *entry = NULL;
+ struct acpi_device *device = NULL;
+
+
+@@ -464,14 +464,9 @@ static void acpi_cpufreq_add_file(struct acpi_processor *pr)
+ return;
+
+ /* add file 'performance' [R/W] */
+- entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
+- S_IFREG | S_IRUGO,
+- acpi_device_dir(device));
+- if (entry){
+- entry->proc_fops = &acpi_processor_perf_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
++ proc_create_data(ACPI_PROCESSOR_FILE_PERFORMANCE, S_IFREG | S_IRUGO,
++ acpi_device_dir(device),
++ &acpi_processor_perf_fops, acpi_driver_data(device));
+ return;
+ }
+
+diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
+index 9cb43f5..ef34b18 100644
+--- a/drivers/acpi/processor_thermal.c
++++ b/drivers/acpi/processor_thermal.c
+@@ -97,7 +97,7 @@ static int acpi_processor_apply_limit(struct acpi_processor *pr)
+ #define CPUFREQ_THERMAL_MIN_STEP 0
+ #define CPUFREQ_THERMAL_MAX_STEP 3
+
+-static unsigned int cpufreq_thermal_reduction_pctg[NR_CPUS];
++static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg);
+ static unsigned int acpi_thermal_cpufreq_is_init = 0;
+
+ static int cpu_has_cpufreq(unsigned int cpu)
+@@ -113,9 +113,9 @@ static int acpi_thermal_cpufreq_increase(unsigned int cpu)
+ if (!cpu_has_cpufreq(cpu))
+ return -ENODEV;
+
+- if (cpufreq_thermal_reduction_pctg[cpu] <
++ if (per_cpu(cpufreq_thermal_reduction_pctg, cpu) <
+ CPUFREQ_THERMAL_MAX_STEP) {
+- cpufreq_thermal_reduction_pctg[cpu]++;
++ per_cpu(cpufreq_thermal_reduction_pctg, cpu)++;
+ cpufreq_update_policy(cpu);
+ return 0;
+ }
+@@ -128,14 +128,14 @@ static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
+ if (!cpu_has_cpufreq(cpu))
+ return -ENODEV;
+
+- if (cpufreq_thermal_reduction_pctg[cpu] >
++ if (per_cpu(cpufreq_thermal_reduction_pctg, cpu) >
+ (CPUFREQ_THERMAL_MIN_STEP + 1))
+- cpufreq_thermal_reduction_pctg[cpu]--;
++ per_cpu(cpufreq_thermal_reduction_pctg, cpu)--;
+ else
+- cpufreq_thermal_reduction_pctg[cpu] = 0;
++ per_cpu(cpufreq_thermal_reduction_pctg, cpu) = 0;
+ cpufreq_update_policy(cpu);
+ /* We reached max freq again and can leave passive mode */
+- return !cpufreq_thermal_reduction_pctg[cpu];
++ return !per_cpu(cpufreq_thermal_reduction_pctg, cpu);
+ }
+
+ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,
+@@ -147,9 +147,10 @@ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,
+ if (event != CPUFREQ_ADJUST)
+ goto out;
+
+- max_freq =
+- (policy->cpuinfo.max_freq *
+- (100 - cpufreq_thermal_reduction_pctg[policy->cpu] * 20)) / 100;
++ max_freq = (
++ policy->cpuinfo.max_freq *
++ (100 - per_cpu(cpufreq_thermal_reduction_pctg, policy->cpu) * 20)
++ ) / 100;
+
+ cpufreq_verify_within_limits(policy, 0, max_freq);
+
+@@ -174,7 +175,7 @@ static int cpufreq_get_cur_state(unsigned int cpu)
+ if (!cpu_has_cpufreq(cpu))
+ return 0;
+
+- return cpufreq_thermal_reduction_pctg[cpu];
++ return per_cpu(cpufreq_thermal_reduction_pctg, cpu);
+ }
+
+ static int cpufreq_set_cur_state(unsigned int cpu, int state)
+@@ -182,7 +183,7 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state)
+ if (!cpu_has_cpufreq(cpu))
+ return 0;
+
+- cpufreq_thermal_reduction_pctg[cpu] = state;
++ per_cpu(cpufreq_thermal_reduction_pctg, cpu) = state;
+ cpufreq_update_policy(cpu);
+ return 0;
+ }
+@@ -191,8 +192,9 @@ void acpi_thermal_cpufreq_init(void)
+ {
+ int i;
+
+- for (i = 0; i < NR_CPUS; i++)
+- cpufreq_thermal_reduction_pctg[i] = 0;
++ for (i = 0; i < nr_cpu_ids; i++)
++ if (cpu_present(i))
++ per_cpu(cpufreq_thermal_reduction_pctg, i) = 0;
+
+ i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block,
+ CPUFREQ_POLICY_NOTIFIER);
+@@ -507,6 +509,7 @@ static ssize_t acpi_processor_write_limit(struct file * file,
+ }
+
+ struct file_operations acpi_processor_limit_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_processor_limit_open_fs,
+ .read = seq_read,
+ .write = acpi_processor_write_limit,
+diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
+index 1b8e592..bb06738 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;
+ }
+
+@@ -1252,6 +1252,7 @@ static ssize_t acpi_processor_write_throttling(struct file *file,
+ }
+
+ struct file_operations acpi_processor_throttling_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_processor_throttling_open_fs,
+ .read = seq_read,
+ .write = acpi_processor_write_throttling,
+diff --git a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c
+index 271e615..7f96332 100644
+--- a/drivers/acpi/resources/rsaddr.c
++++ b/drivers/acpi/resources/rsaddr.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c
+index 0dd2ce8..8a112d1 100644
+--- a/drivers/acpi/resources/rscalc.c
++++ b/drivers/acpi/resources/rscalc.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -73,7 +73,7 @@ acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length);
+
+ static u8 acpi_rs_count_set_bits(u16 bit_field)
+ {
+- u8 bits_set;
++ acpi_native_uint bits_set;
+
+ ACPI_FUNCTION_ENTRY();
+
+@@ -81,10 +81,10 @@ static u8 acpi_rs_count_set_bits(u16 bit_field)
+
+ /* Zero the least significant bit that is set */
+
+- bit_field &= (bit_field - 1);
++ bit_field &= (u16) (bit_field - 1);
+ }
+
+- return (bits_set);
++ return ((u8) bits_set);
+ }
+
+ /*******************************************************************************
+@@ -211,6 +211,24 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed)
+ * variable-length fields
+ */
+ switch (resource->type) {
++ case ACPI_RESOURCE_TYPE_IRQ:
++
++ /* Length can be 3 or 2 */
++
++ if (resource->data.irq.descriptor_length == 2) {
++ total_size--;
++ }
++ break;
++
++ case ACPI_RESOURCE_TYPE_START_DEPENDENT:
++
++ /* Length can be 1 or 0 */
++
++ if (resource->data.irq.descriptor_length == 0) {
++ total_size--;
++ }
++ break;
++
+ case ACPI_RESOURCE_TYPE_VENDOR:
+ /*
+ * Vendor Defined Resource:
+diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c
+index 50da494..faddaee 100644
+--- a/drivers/acpi/resources/rscreate.c
++++ b/drivers/acpi/resources/rscreate.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c
+index 46da116..6bbbb7b 100644
+--- a/drivers/acpi/resources/rsdump.c
++++ b/drivers/acpi/resources/rsdump.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -87,8 +87,10 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table);
+ *
+ ******************************************************************************/
+
+-struct acpi_rsdump_info acpi_rs_dump_irq[6] = {
++struct acpi_rsdump_info acpi_rs_dump_irq[7] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL},
++ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.descriptor_length),
++ "Descriptor Length", NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering",
+ acpi_gbl_he_decode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity",
+@@ -115,9 +117,11 @@ struct acpi_rsdump_info acpi_rs_dump_dma[6] = {
+ NULL}
+ };
+
+-struct acpi_rsdump_info acpi_rs_dump_start_dpf[3] = {
++struct acpi_rsdump_info acpi_rs_dump_start_dpf[4] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_start_dpf),
+ "Start-Dependent-Functions", NULL},
++ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(start_dpf.descriptor_length),
++ "Descriptor Length", NULL},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.compatibility_priority),
+ "Compatibility Priority", acpi_gbl_config_decode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.performance_robustness),
+diff --git a/drivers/acpi/resources/rsinfo.c b/drivers/acpi/resources/rsinfo.c
+index 2c2adb6..3f0a1fe 100644
+--- a/drivers/acpi/resources/rsinfo.c
++++ b/drivers/acpi/resources/rsinfo.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c
+index b297bc3..b66d42e 100644
+--- a/drivers/acpi/resources/rsio.c
++++ b/drivers/acpi/resources/rsio.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -185,7 +185,7 @@ struct acpi_rsconvert_info acpi_rs_convert_end_tag[2] = {
+ *
+ ******************************************************************************/
+
+-struct acpi_rsconvert_info acpi_rs_get_start_dpf[5] = {
++struct acpi_rsconvert_info acpi_rs_get_start_dpf[6] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_START_DEPENDENT,
+ ACPI_RS_SIZE(struct acpi_resource_start_dependent),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_get_start_dpf)},
+@@ -196,6 +196,12 @@ struct acpi_rsconvert_info acpi_rs_get_start_dpf[5] = {
+ ACPI_ACCEPTABLE_CONFIGURATION,
+ 2},
+
++ /* Get the descriptor length (0 or 1 for Start Dpf descriptor) */
++
++ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.start_dpf.descriptor_length),
++ AML_OFFSET(start_dpf.descriptor_type),
++ 0},
++
+ /* All done if there is no flag byte present in the descriptor */
+
+ {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 1},
+@@ -219,7 +225,9 @@ struct acpi_rsconvert_info acpi_rs_get_start_dpf[5] = {
+ *
+ ******************************************************************************/
+
+-struct acpi_rsconvert_info acpi_rs_set_start_dpf[6] = {
++struct acpi_rsconvert_info acpi_rs_set_start_dpf[10] = {
++ /* Start with a default descriptor of length 1 */
++
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_START_DEPENDENT,
+ sizeof(struct aml_resource_start_dependent),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_set_start_dpf)},
+@@ -236,6 +244,33 @@ struct acpi_rsconvert_info acpi_rs_set_start_dpf[6] = {
+ AML_OFFSET(start_dpf.flags),
+ 2},
+ /*
++ * All done if the output descriptor length is required to be 1
++ * (i.e., optimization to 0 bytes cannot be attempted)
++ */
++ {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE,
++ ACPI_RS_OFFSET(data.start_dpf.descriptor_length),
++ 1},
++
++ /* Set length to 0 bytes (no flags byte) */
++
++ {ACPI_RSC_LENGTH, 0, 0,
++ sizeof(struct aml_resource_start_dependent_noprio)},
++
++ /*
++ * All done if the output descriptor length is required to be 0.
++ *
++ * TBD: Perhaps we should check for error if input flags are not
++ * compatible with a 0-byte descriptor.
++ */
++ {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE,
++ ACPI_RS_OFFSET(data.start_dpf.descriptor_length),
++ 0},
++
++ /* Reset length to 1 byte (descriptor with flags byte) */
++
++ {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_start_dependent)},
++
++ /*
+ * All done if flags byte is necessary -- if either priority value
+ * is not ACPI_ACCEPTABLE_CONFIGURATION
+ */
+diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c
+index 5657f7b..a8805ef 100644
+--- a/drivers/acpi/resources/rsirq.c
++++ b/drivers/acpi/resources/rsirq.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -52,7 +52,7 @@ ACPI_MODULE_NAME("rsirq")
+ * acpi_rs_get_irq
+ *
+ ******************************************************************************/
+-struct acpi_rsconvert_info acpi_rs_get_irq[7] = {
++struct acpi_rsconvert_info acpi_rs_get_irq[8] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IRQ,
+ ACPI_RS_SIZE(struct acpi_resource_irq),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_get_irq)},
+@@ -69,6 +69,12 @@ struct acpi_rsconvert_info acpi_rs_get_irq[7] = {
+ ACPI_EDGE_SENSITIVE,
+ 1},
+
++ /* Get the descriptor length (2 or 3 for IRQ descriptor) */
++
++ {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.irq.descriptor_length),
++ AML_OFFSET(irq.descriptor_type),
++ 0},
++
+ /* All done if no flag byte present in descriptor */
+
+ {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 3},
+@@ -94,7 +100,9 @@ struct acpi_rsconvert_info acpi_rs_get_irq[7] = {
+ *
+ ******************************************************************************/
+
+-struct acpi_rsconvert_info acpi_rs_set_irq[9] = {
++struct acpi_rsconvert_info acpi_rs_set_irq[13] = {
++ /* Start with a default descriptor of length 3 */
++
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IRQ,
+ sizeof(struct aml_resource_irq),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_set_irq)},
+@@ -105,7 +113,7 @@ struct acpi_rsconvert_info acpi_rs_set_irq[9] = {
+ AML_OFFSET(irq.irq_mask),
+ ACPI_RS_OFFSET(data.irq.interrupt_count)},
+
+- /* Set the flags byte by default */
++ /* Set the flags byte */
+
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering),
+ AML_OFFSET(irq.flags),
+@@ -118,6 +126,33 @@ struct acpi_rsconvert_info acpi_rs_set_irq[9] = {
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable),
+ AML_OFFSET(irq.flags),
+ 4},
++
++ /*
++ * All done if the output descriptor length is required to be 3
++ * (i.e., optimization to 2 bytes cannot be attempted)
++ */
++ {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE,
++ ACPI_RS_OFFSET(data.irq.descriptor_length),
++ 3},
++
++ /* Set length to 2 bytes (no flags byte) */
++
++ {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq_noflags)},
++
++ /*
++ * All done if the output descriptor length is required to be 2.
++ *
++ * TBD: Perhaps we should check for error if input flags are not
++ * compatible with a 2-byte descriptor.
++ */
++ {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE,
++ ACPI_RS_OFFSET(data.irq.descriptor_length),
++ 2},
++
++ /* Reset length to 3 bytes (descriptor with flags byte) */
++
++ {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq)},
++
+ /*
+ * Check if the flags byte is necessary. Not needed if the flags are:
+ * ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE
+@@ -134,7 +169,7 @@ struct acpi_rsconvert_info acpi_rs_set_irq[9] = {
+ ACPI_RS_OFFSET(data.irq.sharable),
+ ACPI_EXCLUSIVE},
+
+- /* irq_no_flags() descriptor can be used */
++ /* We can optimize to a 2-byte irq_no_flags() descriptor */
+
+ {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq_noflags)}
+ };
+diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c
+index ca21e46..b78c7e7 100644
+--- a/drivers/acpi/resources/rslist.c
++++ b/drivers/acpi/resources/rslist.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/resources/rsmemory.c b/drivers/acpi/resources/rsmemory.c
+index 521eab7..63b21ab 100644
+--- a/drivers/acpi/resources/rsmemory.c
++++ b/drivers/acpi/resources/rsmemory.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c
+index c7081af..de1ac38 100644
+--- a/drivers/acpi/resources/rsmisc.c
++++ b/drivers/acpi/resources/rsmisc.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -497,6 +497,17 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
+ }
+ break;
+
++ case ACPI_RSC_EXIT_EQ:
++ /*
++ * Control - Exit conversion if equal
++ */
++ if (*ACPI_ADD_PTR(u8, resource,
++ COMPARE_TARGET(info)) ==
++ COMPARE_VALUE(info)) {
++ goto exit;
++ }
++ break;
++
+ default:
+
+ ACPI_ERROR((AE_INFO, "Invalid conversion opcode"));
+diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c
+index 11c0bd7..befe230 100644
+--- a/drivers/acpi/resources/rsutils.c
++++ b/drivers/acpi/resources/rsutils.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -97,17 +97,17 @@ u8 acpi_rs_decode_bitmask(u16 mask, u8 * list)
+ u16 acpi_rs_encode_bitmask(u8 * list, u8 count)
+ {
+ acpi_native_uint i;
+- u16 mask;
++ acpi_native_uint mask;
+
+ ACPI_FUNCTION_ENTRY();
+
+ /* Encode the list into a single bitmask */
+
+ for (i = 0, mask = 0; i < count; i++) {
+- mask |= (0x0001 << list[i]);
++ mask |= (0x1 << list[i]);
+ }
+
+- return (mask);
++ return ((u16) mask);
+ }
+
+ /*******************************************************************************
+diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c
+index 4c3fd4c..f59f4c4 100644
+--- a/drivers/acpi/resources/rsxface.c
++++ b/drivers/acpi/resources/rsxface.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
+index 585ae3c..10a3651 100644
+--- a/drivers/acpi/sbs.c
++++ b/drivers/acpi/sbs.c
+@@ -483,8 +483,6 @@ acpi_sbs_add_fs(struct proc_dir_entry **dir,
+ struct file_operations *state_fops,
+ struct file_operations *alarm_fops, void *data)
+ {
+- struct proc_dir_entry *entry = NULL;
+-
+ if (!*dir) {
+ *dir = proc_mkdir(dir_name, parent_dir);
+ if (!*dir) {
+@@ -494,34 +492,19 @@ acpi_sbs_add_fs(struct proc_dir_entry **dir,
+ }
+
+ /* 'info' [R] */
+- if (info_fops) {
+- entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir);
+- if (entry) {
+- entry->proc_fops = info_fops;
+- entry->data = data;
+- entry->owner = THIS_MODULE;
+- }
+- }
++ if (info_fops)
++ proc_create_data(ACPI_SBS_FILE_INFO, S_IRUGO, *dir,
++ info_fops, data);
+
+ /* 'state' [R] */
+- if (state_fops) {
+- entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir);
+- if (entry) {
+- entry->proc_fops = state_fops;
+- entry->data = data;
+- entry->owner = THIS_MODULE;
+- }
+- }
++ if (state_fops)
++ proc_create_data(ACPI_SBS_FILE_STATE, S_IRUGO, *dir,
++ state_fops, data);
+
+ /* 'alarm' [R/W] */
+- if (alarm_fops) {
+- entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir);
+- if (entry) {
+- entry->proc_fops = alarm_fops;
+- entry->data = data;
+- entry->owner = THIS_MODULE;
+- }
+- }
++ if (alarm_fops)
++ proc_create_data(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir,
++ alarm_fops, data);
+ return 0;
+ }
+
+diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
+index e6ce262..6d85289 100644
+--- a/drivers/acpi/scan.c
++++ b/drivers/acpi/scan.c
+@@ -677,9 +677,8 @@ acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device,
+ device->wakeup.resources.count = package->package.count - 2;
+ for (i = 0; i < device->wakeup.resources.count; i++) {
+ element = &(package->package.elements[i + 2]);
+- if (element->type != ACPI_TYPE_ANY) {
++ if (element->type != ACPI_TYPE_LOCAL_REFERENCE)
+ return AE_BAD_DATA;
+- }
+
+ device->wakeup.resources.handles[i] = element->reference.handle;
+ }
+@@ -692,6 +691,9 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
+ acpi_status status = 0;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *package = NULL;
++ union acpi_object in_arg[3];
++ struct acpi_object_list arg_list = { 3, in_arg };
++ acpi_status psw_status = AE_OK;
+
+ struct acpi_device_id button_device_ids[] = {
+ {"PNP0C0D", 0},
+@@ -700,7 +702,6 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
+ {"", 0},
+ };
+
+-
+ /* _PRW */
+ status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer);
+ if (ACPI_FAILURE(status)) {
+@@ -718,6 +719,45 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
+ kfree(buffer.pointer);
+
+ device->wakeup.flags.valid = 1;
++ /* Call _PSW/_DSW object to disable its ability to wake the sleeping
++ * system for the ACPI device with the _PRW object.
++ * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW.
++ * So it is necessary to call _DSW object first. Only when it is not
++ * present will the _PSW object used.
++ */
++ /*
++ * Three agruments are needed for the _DSW object.
++ * Argument 0: enable/disable the wake capabilities
++ * When _DSW object is called to disable the wake capabilities, maybe
++ * the first argument is filled. The value of the other two agruments
++ * is meaningless.
++ */
++ in_arg[0].type = ACPI_TYPE_INTEGER;
++ in_arg[0].integer.value = 0;
++ in_arg[1].type = ACPI_TYPE_INTEGER;
++ in_arg[1].integer.value = 0;
++ in_arg[2].type = ACPI_TYPE_INTEGER;
++ in_arg[2].integer.value = 0;
++ psw_status = acpi_evaluate_object(device->handle, "_DSW",
++ &arg_list, NULL);
++ if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND))
++ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in evaluate _DSW\n"));
++ /*
++ * When the _DSW object is not present, OSPM will call _PSW object.
++ */
++ if (psw_status == AE_NOT_FOUND) {
++ /*
++ * Only one agruments is required for the _PSW object.
++ * agrument 0: enable/disable the wake capabilities
++ */
++ arg_list.count = 1;
++ in_arg[0].integer.value = 0;
++ psw_status = acpi_evaluate_object(device->handle, "_PSW",
++ &arg_list, NULL);
++ if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND))
++ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in "
++ "evaluate _PSW\n"));
++ }
+ /* Power button, Lid switch always enable wakeup */
+ if (!acpi_match_device_ids(device, button_device_ids))
+ device->wakeup.flags.run_wake = 1;
+@@ -882,10 +922,7 @@ static void acpi_device_get_busid(struct acpi_device *device,
+ static int
+ acpi_video_bus_match(struct acpi_device *device)
+ {
+- acpi_handle h_dummy1;
+- acpi_handle h_dummy2;
+- acpi_handle h_dummy3;
+-
++ acpi_handle h_dummy;
+
+ if (!device)
+ return -EINVAL;
+@@ -895,18 +932,18 @@ acpi_video_bus_match(struct acpi_device *device)
+ */
+
+ /* Does this device able to support video switching ? */
+- if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy1)) &&
+- ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy2)))
++ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) &&
++ ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy)))
+ return 0;
+
+ /* Does this device able to retrieve a video ROM ? */
+- if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy1)))
++ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy)))
+ return 0;
+
+ /* Does this device able to configure which video head to be POSTed ? */
+- if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy1)) &&
+- ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy2)) &&
+- ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3)))
++ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) &&
++ ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) &&
++ ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy)))
+ return 0;
+
+ return -ENODEV;
+diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
+index 71183ee..c3b0cd8 100644
+--- a/drivers/acpi/sleep/main.c
++++ b/drivers/acpi/sleep/main.c
+@@ -51,7 +51,7 @@ static int acpi_sleep_prepare(u32 acpi_state)
+ }
+
+ #ifdef CONFIG_SUSPEND
+-static struct platform_suspend_ops acpi_pm_ops;
++static struct platform_suspend_ops acpi_suspend_ops;
+
+ extern void do_suspend_lowlevel(void);
+
+@@ -65,11 +65,11 @@ static u32 acpi_suspend_states[] = {
+ static int init_8259A_after_S1;
+
+ /**
+- * acpi_pm_begin - Set the target system sleep state to the state
++ * acpi_suspend_begin - Set the target system sleep state to the state
+ * associated with given @pm_state, if supported.
+ */
+
+-static int acpi_pm_begin(suspend_state_t pm_state)
++static int acpi_suspend_begin(suspend_state_t pm_state)
+ {
+ u32 acpi_state = acpi_suspend_states[pm_state];
+ int error = 0;
+@@ -85,13 +85,13 @@ static int acpi_pm_begin(suspend_state_t pm_state)
+ }
+
+ /**
+- * acpi_pm_prepare - Do preliminary suspend work.
++ * acpi_suspend_prepare - Do preliminary suspend work.
+ *
+ * If necessary, set the firmware waking vector and do arch-specific
+ * nastiness to get the wakeup code to the waking vector.
+ */
+
+-static int acpi_pm_prepare(void)
++static int acpi_suspend_prepare(void)
+ {
+ int error = acpi_sleep_prepare(acpi_target_sleep_state);
+
+@@ -104,7 +104,7 @@ static int acpi_pm_prepare(void)
+ }
+
+ /**
+- * acpi_pm_enter - Actually enter a sleep state.
++ * acpi_suspend_enter - Actually enter a sleep state.
+ * @pm_state: ignored
+ *
+ * Flush caches and go to sleep. For STR we have to call arch-specific
+@@ -112,7 +112,7 @@ static int acpi_pm_prepare(void)
+ * It's unfortunate, but it works. Please fix if you're feeling frisky.
+ */
+
+-static int acpi_pm_enter(suspend_state_t pm_state)
++static int acpi_suspend_enter(suspend_state_t pm_state)
+ {
+ acpi_status status = AE_OK;
+ unsigned long flags = 0;
+@@ -169,13 +169,13 @@ static int acpi_pm_enter(suspend_state_t pm_state)
+ }
+
+ /**
+- * acpi_pm_finish - Instruct the platform to leave a sleep state.
++ * acpi_suspend_finish - Instruct the platform to leave a sleep state.
+ *
+ * This is called after we wake back up (or if entering the sleep state
+ * failed).
+ */
+
+-static void acpi_pm_finish(void)
++static void acpi_suspend_finish(void)
+ {
+ u32 acpi_state = acpi_target_sleep_state;
+
+@@ -196,19 +196,19 @@ static void acpi_pm_finish(void)
+ }
+
+ /**
+- * acpi_pm_end - Finish up suspend sequence.
++ * acpi_suspend_end - Finish up suspend sequence.
+ */
+
+-static void acpi_pm_end(void)
++static void acpi_suspend_end(void)
+ {
+ /*
+- * This is necessary in case acpi_pm_finish() is not called during a
++ * This is necessary in case acpi_suspend_finish() is not called during a
+ * failing transition to a sleep state.
+ */
+ acpi_target_sleep_state = ACPI_STATE_S0;
+ }
+
+-static int acpi_pm_state_valid(suspend_state_t pm_state)
++static int acpi_suspend_state_valid(suspend_state_t pm_state)
+ {
+ u32 acpi_state;
+
+@@ -224,13 +224,13 @@ static int acpi_pm_state_valid(suspend_state_t pm_state)
+ }
+ }
+
+-static struct platform_suspend_ops acpi_pm_ops = {
+- .valid = acpi_pm_state_valid,
+- .begin = acpi_pm_begin,
+- .prepare = acpi_pm_prepare,
+- .enter = acpi_pm_enter,
+- .finish = acpi_pm_finish,
+- .end = acpi_pm_end,
++static struct platform_suspend_ops acpi_suspend_ops = {
++ .valid = acpi_suspend_state_valid,
++ .begin = acpi_suspend_begin,
++ .prepare = acpi_suspend_prepare,
++ .enter = acpi_suspend_enter,
++ .finish = acpi_suspend_finish,
++ .end = acpi_suspend_end,
+ };
+
+ /*
+@@ -492,7 +492,7 @@ int __init acpi_sleep_init(void)
+ }
+ }
+
+- suspend_set_ops(&acpi_pm_ops);
++ suspend_set_ops(&acpi_suspend_ops);
+ #endif
+
+ #ifdef CONFIG_HIBERNATION
+diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
+index f8df521..8a5fe87 100644
+--- a/drivers/acpi/sleep/proc.c
++++ b/drivers/acpi/sleep/proc.c
+@@ -440,6 +440,7 @@ acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file)
+ }
+
+ static const struct file_operations acpi_system_wakeup_device_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_system_wakeup_device_open_fs,
+ .read = seq_read,
+ .write = acpi_system_write_wakeup_device,
+@@ -449,6 +450,7 @@ static const struct file_operations acpi_system_wakeup_device_fops = {
+
+ #ifdef CONFIG_ACPI_PROCFS
+ static const struct file_operations acpi_system_sleep_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_system_sleep_open_fs,
+ .read = seq_read,
+ .write = acpi_system_write_sleep,
+@@ -459,6 +461,7 @@ static const struct file_operations acpi_system_sleep_fops = {
+
+ #ifdef HAVE_ACPI_LEGACY_ALARM
+ static const struct file_operations acpi_system_alarm_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_system_alarm_open_fs,
+ .read = seq_read,
+ .write = acpi_system_write_alarm,
+@@ -477,37 +480,26 @@ static u32 rtc_handler(void *context)
+
+ static int __init acpi_sleep_proc_init(void)
+ {
+- struct proc_dir_entry *entry = NULL;
+-
+ if (acpi_disabled)
+ return 0;
+
+ #ifdef CONFIG_ACPI_PROCFS
+ /* 'sleep' [R/W] */
+- entry =
+- create_proc_entry("sleep", S_IFREG | S_IRUGO | S_IWUSR,
+- acpi_root_dir);
+- if (entry)
+- entry->proc_fops = &acpi_system_sleep_fops;
++ proc_create("sleep", S_IFREG | S_IRUGO | S_IWUSR,
++ acpi_root_dir, &acpi_system_sleep_fops);
+ #endif /* CONFIG_ACPI_PROCFS */
+
+ #ifdef HAVE_ACPI_LEGACY_ALARM
+ /* 'alarm' [R/W] */
+- entry =
+- create_proc_entry("alarm", S_IFREG | S_IRUGO | S_IWUSR,
+- acpi_root_dir);
+- if (entry)
+- entry->proc_fops = &acpi_system_alarm_fops;
++ proc_create("alarm", S_IFREG | S_IRUGO | S_IWUSR,
++ acpi_root_dir, &acpi_system_alarm_fops);
+
+ acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
+ #endif /* HAVE_ACPI_LEGACY_ALARM */
+
+ /* 'wakeup device' [R/W] */
+- entry =
+- create_proc_entry("wakeup", S_IFREG | S_IRUGO | S_IWUSR,
+- acpi_root_dir);
+- if (entry)
+- entry->proc_fops = &acpi_system_wakeup_device_fops;
++ proc_create("wakeup", S_IFREG | S_IRUGO | S_IWUSR,
++ acpi_root_dir, &acpi_system_wakeup_device_fops);
+
+ return 0;
+ }
+diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
+index 4749f37..769f248 100644
+--- a/drivers/acpi/system.c
++++ b/drivers/acpi/system.c
+@@ -396,6 +396,7 @@ static int acpi_system_info_open_fs(struct inode *inode, struct file *file)
+ }
+
+ static const struct file_operations acpi_system_info_ops = {
++ .owner = THIS_MODULE,
+ .open = acpi_system_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -406,6 +407,7 @@ static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t,
+ loff_t *);
+
+ static const struct file_operations acpi_system_dsdt_ops = {
++ .owner = THIS_MODULE,
+ .read = acpi_system_read_dsdt,
+ };
+
+@@ -430,6 +432,7 @@ static ssize_t acpi_system_read_fadt(struct file *, char __user *, size_t,
+ loff_t *);
+
+ static const struct file_operations acpi_system_fadt_ops = {
++ .owner = THIS_MODULE,
+ .read = acpi_system_read_fadt,
+ };
+
+@@ -454,31 +457,23 @@ static int acpi_system_procfs_init(void)
+ {
+ struct proc_dir_entry *entry;
+ int error = 0;
+- char *name;
+
+ /* 'info' [R] */
+- name = ACPI_SYSTEM_FILE_INFO;
+- entry = create_proc_entry(name, S_IRUGO, acpi_root_dir);
++ entry = proc_create(ACPI_SYSTEM_FILE_INFO, S_IRUGO, acpi_root_dir,
++ &acpi_system_info_ops);
+ if (!entry)
+ goto Error;
+- else {
+- entry->proc_fops = &acpi_system_info_ops;
+- }
+
+ /* 'dsdt' [R] */
+- name = ACPI_SYSTEM_FILE_DSDT;
+- entry = create_proc_entry(name, S_IRUSR, acpi_root_dir);
+- if (entry)
+- entry->proc_fops = &acpi_system_dsdt_ops;
+- else
++ entry = proc_create(ACPI_SYSTEM_FILE_DSDT, S_IRUSR, acpi_root_dir,
++ &acpi_system_dsdt_ops);
++ if (!entry)
+ goto Error;
+
+ /* 'fadt' [R] */
+- name = ACPI_SYSTEM_FILE_FADT;
+- entry = create_proc_entry(name, S_IRUSR, acpi_root_dir);
+- if (entry)
+- entry->proc_fops = &acpi_system_fadt_ops;
+- else
++ entry = proc_create(ACPI_SYSTEM_FILE_FADT, S_IRUSR, acpi_root_dir,
++ &acpi_system_fadt_ops);
++ if (!entry)
+ goto Error;
+
+ Done:
+diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c
+index 002bb33..949d411 100644
+--- a/drivers/acpi/tables/tbfadt.c
++++ b/drivers/acpi/tables/tbfadt.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/tables/tbfind.c b/drivers/acpi/tables/tbfind.c
+index 058c064..9ca3afc 100644
+--- a/drivers/acpi/tables/tbfind.c
++++ b/drivers/acpi/tables/tbfind.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -70,12 +70,22 @@ acpi_tb_find_table(char *signature,
+ {
+ acpi_native_uint i;
+ acpi_status status;
++ struct acpi_table_header header;
+
+ ACPI_FUNCTION_TRACE(tb_find_table);
+
++ /* Normalize the input strings */
++
++ ACPI_MEMSET(&header, 0, sizeof(struct acpi_table_header));
++ ACPI_STRNCPY(header.signature, signature, ACPI_NAME_SIZE);
++ ACPI_STRNCPY(header.oem_id, oem_id, ACPI_OEM_ID_SIZE);
++ ACPI_STRNCPY(header.oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE);
++
++ /* Search for the table */
++
+ for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
+ if (ACPI_MEMCMP(&(acpi_gbl_root_table_list.tables[i].signature),
+- signature, ACPI_NAME_SIZE)) {
++ header.signature, ACPI_NAME_SIZE)) {
+
+ /* Not the requested table */
+
+@@ -104,20 +114,24 @@ acpi_tb_find_table(char *signature,
+
+ if (!ACPI_MEMCMP
+ (acpi_gbl_root_table_list.tables[i].pointer->signature,
+- signature, ACPI_NAME_SIZE) && (!oem_id[0]
+- ||
+- !ACPI_MEMCMP
+- (acpi_gbl_root_table_list.
+- tables[i].pointer->oem_id,
+- oem_id, ACPI_OEM_ID_SIZE))
++ header.signature, ACPI_NAME_SIZE) && (!oem_id[0]
++ ||
++ !ACPI_MEMCMP
++ (acpi_gbl_root_table_list.
++ tables[i].pointer->
++ oem_id,
++ header.oem_id,
++ ACPI_OEM_ID_SIZE))
+ && (!oem_table_id[0]
+ || !ACPI_MEMCMP(acpi_gbl_root_table_list.tables[i].
+- pointer->oem_table_id, oem_table_id,
++ pointer->oem_table_id,
++ header.oem_table_id,
+ ACPI_OEM_TABLE_ID_SIZE))) {
+ *table_index = i;
+
+ ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
+- "Found table [%4.4s]\n", signature));
++ "Found table [%4.4s]\n",
++ header.signature));
+ return_ACPI_STATUS(AE_OK);
+ }
+ }
+diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
+index 3bc0c67..402f93e 100644
+--- a/drivers/acpi/tables/tbinstal.c
++++ b/drivers/acpi/tables/tbinstal.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -125,13 +125,20 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc,
+
+ /* The table must be either an SSDT or a PSDT or an OEMx */
+
+- if ((!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT))
+- &&
+- (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT))
+- && (strncmp(table_desc->pointer->signature, "OEM", 3))) {
+- ACPI_ERROR((AE_INFO,
+- "Table has invalid signature [%4.4s], must be SSDT, PSDT or OEMx",
+- table_desc->pointer->signature));
++ if (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT)&&
++ !ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)&&
++ strncmp(table_desc->pointer->signature, "OEM", 3)) {
++ /* Check for a printable name */
++ if (acpi_ut_valid_acpi_name(
++ *(u32 *) table_desc->pointer->signature)) {
++ ACPI_ERROR((AE_INFO, "Table has invalid signature "
++ "[%4.4s], must be SSDT or PSDT",
++ table_desc->pointer->signature));
++ } else {
++ ACPI_ERROR((AE_INFO, "Table has invalid signature "
++ "(0x%8.8X), must be SSDT or PSDT",
++ *(u32 *) table_desc->pointer->signature));
++ }
+ return_ACPI_STATUS(AE_BAD_SIGNATURE);
+ }
+
+@@ -162,6 +169,7 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc,
+
+ acpi_tb_delete_table(table_desc);
+ *table_index = i;
++ status = AE_ALREADY_EXISTS;
+ goto release;
+ }
+
+diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c
+index 010f196..bc019b9 100644
+--- a/drivers/acpi/tables/tbutils.c
++++ b/drivers/acpi/tables/tbutils.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -212,7 +212,7 @@ acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length)
+
+ if (checksum) {
+ ACPI_WARNING((AE_INFO,
+- "Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X",
++ "Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X",
+ table->signature, table->checksum,
+ (u8) (table->checksum - checksum)));
+
+diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
+index a9e3331..fb57b93 100644
+--- a/drivers/acpi/tables/tbxface.c
++++ b/drivers/acpi/tables/tbxface.c
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -635,6 +635,95 @@ acpi_status acpi_load_tables(void)
+ ACPI_EXPORT_SYMBOL(acpi_load_tables)
+
+
++/*******************************************************************************
++ *
++ * FUNCTION: acpi_install_table_handler
++ *
++ * PARAMETERS: Handler - Table event handler
++ * Context - Value passed to the handler on each event
++ *
++ * RETURN: Status
++ *
++ * DESCRIPTION: Install table event handler
++ *
++ ******************************************************************************/
++acpi_status
++acpi_install_table_handler(acpi_tbl_handler handler, void *context)
++{
++ acpi_status status;
++
++ ACPI_FUNCTION_TRACE(acpi_install_table_handler);
++
++ if (!handler) {
++ return_ACPI_STATUS(AE_BAD_PARAMETER);
++ }
++
++ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
++ if (ACPI_FAILURE(status)) {
++ return_ACPI_STATUS(status);
++ }
++
++ /* Don't allow more than one handler */
++
++ if (acpi_gbl_table_handler) {
++ status = AE_ALREADY_EXISTS;
++ goto cleanup;
++ }
++
++ /* Install the handler */
++
++ acpi_gbl_table_handler = handler;
++ acpi_gbl_table_handler_context = context;
++
++ cleanup:
++ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
++ return_ACPI_STATUS(status);
++}
++
++ACPI_EXPORT_SYMBOL(acpi_install_table_handler)
++
++/*******************************************************************************
++ *
++ * FUNCTION: acpi_remove_table_handler
++ *
++ * PARAMETERS: Handler - Table event handler that was installed
++ * previously.
++ *
++ * RETURN: Status
++ *
++ * DESCRIPTION: Remove table event handler
++ *
++ ******************************************************************************/
++acpi_status acpi_remove_table_handler(acpi_tbl_handler handler)
++{
++ acpi_status status;
++
++ ACPI_FUNCTION_TRACE(acpi_remove_table_handler);
++
++ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
++ if (ACPI_FAILURE(status)) {
++ return_ACPI_STATUS(status);
++ }
++
++ /* Make sure that the installed handler is the same */
++
++ if (!handler || handler != acpi_gbl_table_handler) {
++ status = AE_BAD_PARAMETER;
++ goto cleanup;
++ }
++
++ /* Remove the handler */
++
++ acpi_gbl_table_handler = NULL;
++
++ cleanup:
++ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
++ return_ACPI_STATUS(status);
++}
++
++ACPI_EXPORT_SYMBOL(acpi_remove_table_handler)
++
++
+ static int __init acpi_no_auto_ssdt_setup(char *s) {
+
+ printk(KERN_NOTICE "ACPI: SSDT auto-load disabled\n");
+diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c
+index 9ecb4b6..b8c0dfa 100644
+--- a/drivers/acpi/tables/tbxfroot.c
++++ b/drivers/acpi/tables/tbxfroot.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
+index 1bcecc7..504385b 100644
+--- a/drivers/acpi/thermal.c
++++ b/drivers/acpi/thermal.c
+@@ -198,6 +198,7 @@ struct acpi_thermal {
+ };
+
+ static const struct file_operations acpi_thermal_state_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_thermal_state_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -205,6 +206,7 @@ static const struct file_operations acpi_thermal_state_fops = {
+ };
+
+ static const struct file_operations acpi_thermal_temp_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_thermal_temp_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -212,6 +214,7 @@ static const struct file_operations acpi_thermal_temp_fops = {
+ };
+
+ static const struct file_operations acpi_thermal_trip_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_thermal_trip_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -219,6 +222,7 @@ static const struct file_operations acpi_thermal_trip_fops = {
+ };
+
+ static const struct file_operations acpi_thermal_cooling_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_thermal_cooling_open_fs,
+ .read = seq_read,
+ .write = acpi_thermal_write_cooling_mode,
+@@ -227,6 +231,7 @@ static const struct file_operations acpi_thermal_cooling_fops = {
+ };
+
+ static const struct file_operations acpi_thermal_polling_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_thermal_polling_open_fs,
+ .read = seq_read,
+ .write = acpi_thermal_write_polling,
+@@ -884,10 +889,15 @@ static void acpi_thermal_check(void *data)
+ static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf)
+ {
+ struct acpi_thermal *tz = thermal->devdata;
++ int result;
+
+ if (!tz)
+ return -EINVAL;
+
++ result = acpi_thermal_get_temperature(tz);
++ if (result)
++ return result;
++
+ return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(tz->temperature));
+ }
+
+@@ -1012,6 +1022,18 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
+ return -EINVAL;
+ }
+
++static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
++ unsigned long *temperature) {
++ struct acpi_thermal *tz = thermal->devdata;
++
++ if (tz->trips.critical.flags.valid) {
++ *temperature = KELVIN_TO_MILLICELSIUS(
++ tz->trips.critical.temperature);
++ return 0;
++ } else
++ return -EINVAL;
++}
++
+ typedef int (*cb)(struct thermal_zone_device *, int,
+ struct thermal_cooling_device *);
+ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
+@@ -1103,6 +1125,7 @@ static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
+ .set_mode = thermal_set_mode,
+ .get_trip_type = thermal_get_trip_type,
+ .get_trip_temp = thermal_get_trip_temp,
++ .get_crit_temp = thermal_get_crit_temp,
+ };
+
+ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
+@@ -1123,7 +1146,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
+
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
+ tz->trips.active[i].flags.valid; i++, trips++);
+- tz->thermal_zone = thermal_zone_device_register("ACPI thermal zone",
++ tz->thermal_zone = thermal_zone_device_register("acpitz",
+ trips, tz, &acpi_thermal_zone_ops);
+ if (IS_ERR(tz->thermal_zone))
+ return -ENODEV;
+@@ -1419,63 +1442,47 @@ static int acpi_thermal_add_fs(struct acpi_device *device)
+ }
+
+ /* 'state' [R] */
+- entry = create_proc_entry(ACPI_THERMAL_FILE_STATE,
+- S_IRUGO, acpi_device_dir(device));
++ entry = proc_create_data(ACPI_THERMAL_FILE_STATE,
++ S_IRUGO, acpi_device_dir(device),
++ &acpi_thermal_state_fops,
++ acpi_driver_data(device));
+ if (!entry)
+ return -ENODEV;
+- else {
+- entry->proc_fops = &acpi_thermal_state_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
+
+ /* 'temperature' [R] */
+- entry = create_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE,
+- S_IRUGO, acpi_device_dir(device));
++ entry = proc_create_data(ACPI_THERMAL_FILE_TEMPERATURE,
++ S_IRUGO, acpi_device_dir(device),
++ &acpi_thermal_temp_fops,
++ acpi_driver_data(device));
+ if (!entry)
+ return -ENODEV;
+- else {
+- entry->proc_fops = &acpi_thermal_temp_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
+
+ /* 'trip_points' [R] */
+- entry = create_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
+- S_IRUGO,
+- acpi_device_dir(device));
++ entry = proc_create_data(ACPI_THERMAL_FILE_TRIP_POINTS,
++ S_IRUGO,
++ acpi_device_dir(device),
++ &acpi_thermal_trip_fops,
++ acpi_driver_data(device));
+ if (!entry)
+ return -ENODEV;
+- else {
+- entry->proc_fops = &acpi_thermal_trip_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
+
+ /* 'cooling_mode' [R/W] */
+- entry = create_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE,
+- S_IFREG | S_IRUGO | S_IWUSR,
+- acpi_device_dir(device));
++ entry = proc_create_data(ACPI_THERMAL_FILE_COOLING_MODE,
++ S_IFREG | S_IRUGO | S_IWUSR,
++ acpi_device_dir(device),
++ &acpi_thermal_cooling_fops,
++ acpi_driver_data(device));
+ if (!entry)
+ return -ENODEV;
+- else {
+- entry->proc_fops = &acpi_thermal_cooling_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
+
+ /* 'polling_frequency' [R/W] */
+- entry = create_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
+- S_IFREG | S_IRUGO | S_IWUSR,
+- acpi_device_dir(device));
++ entry = proc_create_data(ACPI_THERMAL_FILE_POLLING_FREQ,
++ S_IFREG | S_IRUGO | S_IWUSR,
++ acpi_device_dir(device),
++ &acpi_thermal_polling_fops,
++ acpi_driver_data(device));
+ if (!entry)
+ return -ENODEV;
+- else {
+- entry->proc_fops = &acpi_thermal_polling_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
+-
+ return 0;
+ }
+
+@@ -1710,7 +1717,6 @@ static int acpi_thermal_resume(struct acpi_device *device)
+ return AE_OK;
+ }
+
+-#ifdef CONFIG_DMI
+ static int thermal_act(const struct dmi_system_id *d) {
+
+ if (act == 0) {
+@@ -1785,7 +1791,6 @@ static struct dmi_system_id thermal_dmi_table[] __initdata = {
+ },
+ {}
+ };
+-#endif /* CONFIG_DMI */
+
+ static int __init acpi_thermal_init(void)
+ {
+diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
+index 6e56d5f..ede0848 100644
+--- a/drivers/acpi/utilities/utalloc.c
++++ b/drivers/acpi/utilities/utalloc.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -147,7 +147,7 @@ acpi_status acpi_ut_delete_caches(void)
+
+ if (acpi_gbl_display_final_mem_stats) {
+ ACPI_STRCPY(buffer, "MEMORY");
+- acpi_db_display_statistics(buffer);
++ (void)acpi_db_display_statistics(buffer);
+ }
+ #endif
+
+diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c
+index 285a0f5..245fa80 100644
+--- a/drivers/acpi/utilities/utcache.c
++++ b/drivers/acpi/utilities/utcache.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
+index 879eaa1..655c290 100644
+--- a/drivers/acpi/utilities/utcopy.c
++++ b/drivers/acpi/utilities/utcopy.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -43,6 +43,8 @@
+
+ #include <acpi/acpi.h>
+ #include <acpi/amlcode.h>
++#include <acpi/acnamesp.h>
++
+
+ #define _COMPONENT ACPI_UTILITIES
+ ACPI_MODULE_NAME("utcopy")
+@@ -172,22 +174,21 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
+
+ case ACPI_TYPE_LOCAL_REFERENCE:
+
+- /*
+- * This is an object reference. Attempt to dereference it.
+- */
++ /* This is an object reference. */
++
+ switch (internal_object->reference.opcode) {
+ case AML_INT_NAMEPATH_OP:
+
+ /* For namepath, return the object handle ("reference") */
+
+ default:
+- /*
+- * Use the object type of "Any" to indicate a reference
+- * to object containing a handle to an ACPI named object.
+- */
+- external_object->type = ACPI_TYPE_ANY;
++
++ /* We are referring to the namespace node */
++
+ external_object->reference.handle =
+ internal_object->reference.node;
++ external_object->reference.actual_type =
++ acpi_ns_get_type(internal_object->reference.node);
+ break;
+ }
+ break;
+@@ -215,6 +216,11 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
+ /*
+ * There is no corresponding external object type
+ */
++ ACPI_ERROR((AE_INFO,
++ "Unsupported object type, cannot convert to external object: %s",
++ acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE
++ (internal_object))));
++
+ return_ACPI_STATUS(AE_SUPPORT);
+ }
+
+@@ -455,6 +461,7 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
+ case ACPI_TYPE_STRING:
+ case ACPI_TYPE_BUFFER:
+ case ACPI_TYPE_INTEGER:
++ case ACPI_TYPE_LOCAL_REFERENCE:
+
+ internal_object = acpi_ut_create_internal_object((u8)
+ external_object->
+@@ -464,9 +471,18 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
+ }
+ break;
+
++ case ACPI_TYPE_ANY: /* This is the case for a NULL object */
++
++ *ret_internal_object = NULL;
++ return_ACPI_STATUS(AE_OK);
++
+ default:
+ /* All other types are not supported */
+
++ ACPI_ERROR((AE_INFO,
++ "Unsupported object type, cannot convert to internal object: %s",
++ acpi_ut_get_type_name(external_object->type)));
++
+ return_ACPI_STATUS(AE_SUPPORT);
+ }
+
+@@ -502,6 +518,10 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
+ external_object->buffer.length);
+
+ internal_object->buffer.length = external_object->buffer.length;
++
++ /* Mark buffer data valid */
++
++ internal_object->buffer.flags |= AOPOBJ_DATA_VALID;
+ break;
+
+ case ACPI_TYPE_INTEGER:
+@@ -509,6 +529,15 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
+ internal_object->integer.value = external_object->integer.value;
+ break;
+
++ case ACPI_TYPE_LOCAL_REFERENCE:
++
++ /* TBD: should validate incoming handle */
++
++ internal_object->reference.opcode = AML_INT_NAMEPATH_OP;
++ internal_object->reference.node =
++ external_object->reference.handle;
++ break;
++
+ default:
+ /* Other types can't get here */
+ break;
+@@ -570,13 +599,17 @@ acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
+
+ /* Truncate package and delete it */
+
+- package_object->package.count = i;
++ package_object->package.count = (u32) i;
+ package_elements[i] = NULL;
+ acpi_ut_remove_reference(package_object);
+ return_ACPI_STATUS(status);
+ }
+ }
+
++ /* Mark package data valid */
++
++ package_object->package.flags |= AOPOBJ_DATA_VALID;
++
+ *internal_object = package_object;
+ return_ACPI_STATUS(status);
+ }
+@@ -709,7 +742,15 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
+ /*
+ * We copied the reference object, so we now must add a reference
+ * to the object pointed to by the reference
++ *
++ * DDBHandle reference (from Load/load_table is a special reference,
++ * it's Reference.Object is the table index, so does not need to
++ * increase the reference count
+ */
++ if (source_desc->reference.opcode == AML_LOAD_OP) {
++ break;
++ }
++
+ acpi_ut_add_reference(source_desc->reference.object);
+ break;
+
+diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c
+index 7361204..f938f46 100644
+--- a/drivers/acpi/utilities/utdebug.c
++++ b/drivers/acpi/utilities/utdebug.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -68,9 +68,9 @@ static const char *acpi_ut_trim_function_name(const char *function_name);
+
+ void acpi_ut_init_stack_ptr_trace(void)
+ {
+- u32 current_sp;
++ acpi_size current_sp;
+
+- acpi_gbl_entry_stack_pointer = ACPI_PTR_DIFF(¤t_sp, NULL);
++ acpi_gbl_entry_stack_pointer = ¤t_sp;
+ }
+
+ /*******************************************************************************
+@@ -89,10 +89,8 @@ void acpi_ut_track_stack_ptr(void)
+ {
+ acpi_size current_sp;
+
+- current_sp = ACPI_PTR_DIFF(¤t_sp, NULL);
+-
+- if (current_sp < acpi_gbl_lowest_stack_pointer) {
+- acpi_gbl_lowest_stack_pointer = current_sp;
++ if (¤t_sp < acpi_gbl_lowest_stack_pointer) {
++ acpi_gbl_lowest_stack_pointer = ¤t_sp;
+ }
+
+ if (acpi_gbl_nesting_level > acpi_gbl_deepest_nesting) {
+@@ -203,6 +201,7 @@ acpi_ut_debug_print(u32 requested_debug_level,
+
+ va_start(args, format);
+ acpi_os_vprintf(format, args);
++ va_end(args);
+ }
+
+ ACPI_EXPORT_SYMBOL(acpi_ut_debug_print)
+@@ -240,6 +239,7 @@ acpi_ut_debug_print_raw(u32 requested_debug_level,
+
+ va_start(args, format);
+ acpi_os_vprintf(format, args);
++ va_end(args);
+ }
+
+ ACPI_EXPORT_SYMBOL(acpi_ut_debug_print_raw)
+@@ -524,6 +524,11 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
+ u32 temp32;
+ u8 buf_char;
+
++ if (!buffer) {
++ acpi_os_printf("Null Buffer Pointer in DumpBuffer!\n");
++ return;
++ }
++
+ if ((count < 4) || (count & 0x01)) {
+ display = DB_BYTE_DISPLAY;
+ }
+diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
+index f777ceb..1fbc351 100644
+--- a/drivers/acpi/utilities/utdelete.c
++++ b/drivers/acpi/utilities/utdelete.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -158,7 +158,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
+ "***** Mutex %p, OS Mutex %p\n",
+ object, object->mutex.os_mutex));
+
+- if (object->mutex.os_mutex == acpi_gbl_global_lock_mutex) {
++ if (object == acpi_gbl_global_lock_mutex) {
+
+ /* Global Lock has extra semaphore */
+
+@@ -252,6 +252,17 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
+ }
+ break;
+
++ case ACPI_TYPE_LOCAL_BANK_FIELD:
++
++ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
++ "***** Bank Field %p\n", object));
++
++ second_desc = acpi_ns_get_secondary_object(object);
++ if (second_desc) {
++ acpi_ut_delete_object_desc(second_desc);
++ }
++ break;
++
+ default:
+ break;
+ }
+@@ -524,10 +535,12 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action)
+
+ case ACPI_TYPE_LOCAL_REFERENCE:
+ /*
+- * The target of an Index (a package, string, or buffer) must track
+- * changes to the ref count of the index.
++ * The target of an Index (a package, string, or buffer) or a named
++ * reference must track changes to the ref count of the index or
++ * target object.
+ */
+- if (object->reference.opcode == AML_INDEX_OP) {
++ if ((object->reference.opcode == AML_INDEX_OP) ||
++ (object->reference.opcode == AML_INT_NAMEPATH_OP)) {
+ next_object = object->reference.object;
+ }
+ break;
+diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c
+index 0042b7e..05e61be 100644
+--- a/drivers/acpi/utilities/uteval.c
++++ b/drivers/acpi/utilities/uteval.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
+index 630c9a2..a6e71b8 100644
+--- a/drivers/acpi/utilities/utglobal.c
++++ b/drivers/acpi/utilities/utglobal.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -602,6 +602,48 @@ char *acpi_ut_get_mutex_name(u32 mutex_id)
+
+ return (acpi_gbl_mutex_names[mutex_id]);
+ }
++
++/*******************************************************************************
++ *
++ * FUNCTION: acpi_ut_get_notify_name
++ *
++ * PARAMETERS: notify_value - Value from the Notify() request
++ *
++ * RETURN: String corresponding to the Notify Value.
++ *
++ * DESCRIPTION: Translate a Notify Value to a notify namestring.
++ *
++ ******************************************************************************/
++
++/* Names for Notify() values, used for debug output */
++
++static const char *acpi_gbl_notify_value_names[] = {
++ "Bus Check",
++ "Device Check",
++ "Device Wake",
++ "Eject Request",
++ "Device Check Light",
++ "Frequency Mismatch",
++ "Bus Mode Mismatch",
++ "Power Fault",
++ "Capabilities Check",
++ "Device PLD Check",
++ "Reserved",
++ "System Locality Update"
++};
++
++const char *acpi_ut_get_notify_name(u32 notify_value)
++{
++
++ if (notify_value <= ACPI_NOTIFY_MAX) {
++ return (acpi_gbl_notify_value_names[notify_value]);
++ } else if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
++ return ("Reserved");
++ } else { /* Greater or equal to 0x80 */
++
++ return ("**Device Specific**");
++ }
++}
+ #endif
+
+ /*******************************************************************************
+@@ -675,12 +717,13 @@ void acpi_ut_init_globals(void)
+ acpi_gbl_gpe_fadt_blocks[0] = NULL;
+ acpi_gbl_gpe_fadt_blocks[1] = NULL;
+
+- /* Global notify handlers */
++ /* Global handlers */
+
+ acpi_gbl_system_notify.handler = NULL;
+ acpi_gbl_device_notify.handler = NULL;
+ acpi_gbl_exception_handler = NULL;
+ acpi_gbl_init_handler = NULL;
++ acpi_gbl_table_handler = NULL;
+
+ /* Global Lock support */
+
+@@ -722,7 +765,7 @@ void acpi_ut_init_globals(void)
+ acpi_gbl_root_node_struct.flags = ANOBJ_END_OF_PEER_LIST;
+
+ #ifdef ACPI_DEBUG_OUTPUT
+- acpi_gbl_lowest_stack_pointer = ACPI_SIZE_MAX;
++ acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX);
+ #endif
+
+ #ifdef ACPI_DBG_TRACK_ALLOCATIONS
+diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c
+index ad3c0d0..cae515f 100644
+--- a/drivers/acpi/utilities/utinit.c
++++ b/drivers/acpi/utilities/utinit.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -125,9 +125,12 @@ void acpi_ut_subsystem_shutdown(void)
+ acpi_gbl_startup_flags = 0;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n"));
+
++#ifndef ACPI_ASL_COMPILER
++
+ /* Close the acpi_event Handling */
+
+ acpi_ev_terminate();
++#endif
+
+ /* Close the Namespace */
+
+diff --git a/drivers/acpi/utilities/utmath.c b/drivers/acpi/utilities/utmath.c
+index 0c56a0d..c927324 100644
+--- a/drivers/acpi/utilities/utmath.c
++++ b/drivers/acpi/utilities/utmath.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -276,7 +276,7 @@ acpi_ut_short_divide(acpi_integer in_dividend,
+ *out_quotient = in_dividend / divisor;
+ }
+ if (out_remainder) {
+- *out_remainder = (u32) in_dividend % divisor;
++ *out_remainder = (u32) (in_dividend % divisor);
+ }
+
+ return_ACPI_STATUS(AE_OK);
+diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
+index 2d19f71..e4ba719 100644
+--- a/drivers/acpi/utilities/utmisc.c
++++ b/drivers/acpi/utilities/utmisc.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -1033,6 +1033,7 @@ acpi_ut_error(char *module_name, u32 line_number, char *format, ...)
+ va_start(args, format);
+ acpi_os_vprintf(format, args);
+ acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
++ va_end(args);
+ }
+
+ void ACPI_INTERNAL_VAR_XFACE
+@@ -1061,6 +1062,8 @@ acpi_ut_warning(char *module_name, u32 line_number, char *format, ...)
+ va_start(args, format);
+ acpi_os_vprintf(format, args);
+ acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
++ va_end(args);
++ va_end(args);
+ }
+
+ void ACPI_INTERNAL_VAR_XFACE
+@@ -1077,4 +1080,5 @@ acpi_ut_info(char *module_name, u32 line_number, char *format, ...)
+ va_start(args, format);
+ acpi_os_vprintf(format, args);
+ acpi_os_printf("\n");
++ va_end(args);
+ }
+diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c
+index 4820bc8..f7d602b 100644
+--- a/drivers/acpi/utilities/utmutex.c
++++ b/drivers/acpi/utilities/utmutex.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c
+index e08b3fa..e68466d 100644
+--- a/drivers/acpi/utilities/utobject.c
++++ b/drivers/acpi/utilities/utobject.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -107,6 +107,7 @@ union acpi_operand_object *acpi_ut_create_internal_object_dbg(char *module_name,
+ switch (type) {
+ case ACPI_TYPE_REGION:
+ case ACPI_TYPE_BUFFER_FIELD:
++ case ACPI_TYPE_LOCAL_BANK_FIELD:
+
+ /* These types require a secondary object */
+
+@@ -469,9 +470,8 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
+ case ACPI_TYPE_PROCESSOR:
+ case ACPI_TYPE_POWER:
+
+- /*
+- * No extra data for these types
+- */
++ /* No extra data for these types */
++
+ break;
+
+ case ACPI_TYPE_LOCAL_REFERENCE:
+diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/utilities/utresrc.c
+index b630ee1..c3e3e13 100644
+--- a/drivers/acpi/utilities/utresrc.c
++++ b/drivers/acpi/utilities/utresrc.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c
+index edcaafa..63a6d3d 100644
+--- a/drivers/acpi/utilities/utstate.c
++++ b/drivers/acpi/utilities/utstate.c
+@@ -5,7 +5,7 @@
+ ******************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c
+index 2d49691..f8bdadf 100644
+--- a/drivers/acpi/utilities/utxface.c
++++ b/drivers/acpi/utilities/utxface.c
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -49,6 +49,7 @@
+ #define _COMPONENT ACPI_UTILITIES
+ ACPI_MODULE_NAME("utxface")
+
++#ifndef ACPI_ASL_COMPILER
+ /*******************************************************************************
+ *
+ * FUNCTION: acpi_initialize_subsystem
+@@ -192,24 +193,6 @@ acpi_status acpi_enable_subsystem(u32 flags)
+ }
+ }
+
+- /*
+- * Complete the GPE initialization for the GPE blocks defined in the FADT
+- * (GPE block 0 and 1).
+- *
+- * Note1: This is where the _PRW methods are executed for the GPEs. These
+- * methods can only be executed after the SCI and Global Lock handlers are
+- * installed and initialized.
+- *
+- * Note2: Currently, there seems to be no need to run the _REG methods
+- * before execution of the _PRW methods and enabling of the GPEs.
+- */
+- if (!(flags & ACPI_NO_EVENT_INIT)) {
+- status = acpi_ev_install_fadt_gpes();
+- if (ACPI_FAILURE(status)) {
+- return (status);
+- }
+- }
+-
+ return_ACPI_STATUS(status);
+ }
+
+@@ -280,6 +263,23 @@ acpi_status acpi_initialize_objects(u32 flags)
+ }
+
+ /*
++ * Complete the GPE initialization for the GPE blocks defined in the FADT
++ * (GPE block 0 and 1).
++ *
++ * Note1: This is where the _PRW methods are executed for the GPEs. These
++ * methods can only be executed after the SCI and Global Lock handlers are
++ * installed and initialized.
++ *
++ * Note2: Currently, there seems to be no need to run the _REG methods
++ * before execution of the _PRW methods and enabling of the GPEs.
++ */
++ if (!(flags & ACPI_NO_EVENT_INIT)) {
++ status = acpi_ev_install_fadt_gpes();
++ if (ACPI_FAILURE(status))
++ return (status);
++ }
++
++ /*
+ * Empty the caches (delete the cached objects) on the assumption that
+ * the table load filled them up more than they will be at runtime --
+ * thus wasting non-paged memory.
+@@ -292,6 +292,7 @@ acpi_status acpi_initialize_objects(u32 flags)
+
+ ACPI_EXPORT_SYMBOL(acpi_initialize_objects)
+
++#endif
+ /*******************************************************************************
+ *
+ * FUNCTION: acpi_terminate
+@@ -335,6 +336,7 @@ acpi_status acpi_terminate(void)
+ }
+
+ ACPI_EXPORT_SYMBOL(acpi_terminate)
++#ifndef ACPI_ASL_COMPILER
+ #ifdef ACPI_FUTURE_USAGE
+ /*******************************************************************************
+ *
+@@ -490,3 +492,4 @@ acpi_status acpi_purge_cached_objects(void)
+ }
+
+ ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects)
++#endif
+diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
+index 44ea60c..1009261 100644
+--- a/drivers/acpi/utils.c
++++ b/drivers/acpi/utils.c
+@@ -398,7 +398,7 @@ acpi_evaluate_reference(acpi_handle handle,
+
+ element = &(package->package.elements[i]);
+
+- if (element->type != ACPI_TYPE_ANY) {
++ if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
+ status = AE_BAD_DATA;
+ printk(KERN_ERR PREFIX
+ "Expecting a [Reference] package element, found type %X\n",
+diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
+index 980a741..5e5dda3 100644
+--- a/drivers/acpi/video.c
++++ b/drivers/acpi/video.c
+@@ -57,8 +57,6 @@
+ #define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88
+ #define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89
+
+-#define ACPI_VIDEO_HEAD_INVALID (~0u - 1)
+-#define ACPI_VIDEO_HEAD_END (~0u)
+ #define MAX_NAME_LEN 20
+
+ #define ACPI_VIDEO_DISPLAY_CRT 1
+@@ -192,6 +190,7 @@ struct acpi_video_device {
+ /* bus */
+ static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file);
+ static struct file_operations acpi_video_bus_info_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_video_bus_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -200,6 +199,7 @@ static struct file_operations acpi_video_bus_info_fops = {
+
+ static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file);
+ static struct file_operations acpi_video_bus_ROM_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_video_bus_ROM_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -209,6 +209,7 @@ static struct file_operations acpi_video_bus_ROM_fops = {
+ static int acpi_video_bus_POST_info_open_fs(struct inode *inode,
+ struct file *file);
+ static struct file_operations acpi_video_bus_POST_info_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_video_bus_POST_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -217,6 +218,7 @@ static struct file_operations acpi_video_bus_POST_info_fops = {
+
+ static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file);
+ static struct file_operations acpi_video_bus_POST_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_video_bus_POST_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -225,6 +227,7 @@ static struct file_operations acpi_video_bus_POST_fops = {
+
+ static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file);
+ static struct file_operations acpi_video_bus_DOS_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_video_bus_DOS_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -235,6 +238,7 @@ static struct file_operations acpi_video_bus_DOS_fops = {
+ static int acpi_video_device_info_open_fs(struct inode *inode,
+ struct file *file);
+ static struct file_operations acpi_video_device_info_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_video_device_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -244,6 +248,7 @@ static struct file_operations acpi_video_device_info_fops = {
+ static int acpi_video_device_state_open_fs(struct inode *inode,
+ struct file *file);
+ static struct file_operations acpi_video_device_state_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_video_device_state_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -253,6 +258,7 @@ static struct file_operations acpi_video_device_state_fops = {
+ static int acpi_video_device_brightness_open_fs(struct inode *inode,
+ struct file *file);
+ static struct file_operations acpi_video_device_brightness_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_video_device_brightness_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -262,6 +268,7 @@ static struct file_operations acpi_video_device_brightness_fops = {
+ static int acpi_video_device_EDID_open_fs(struct inode *inode,
+ struct file *file);
+ static struct file_operations acpi_video_device_EDID_fops = {
++ .owner = THIS_MODULE,
+ .open = acpi_video_device_EDID_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -734,21 +741,19 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
+ if (IS_ERR(device->cdev))
+ return;
+
+- if (device->cdev) {
+- printk(KERN_INFO PREFIX
+- "%s is registered as cooling_device%d\n",
+- device->dev->dev.bus_id, device->cdev->id);
+- result = sysfs_create_link(&device->dev->dev.kobj,
+- &device->cdev->device.kobj,
+- "thermal_cooling");
+- if (result)
+- printk(KERN_ERR PREFIX "Create sysfs link\n");
+- result = sysfs_create_link(&device->cdev->device.kobj,
+- &device->dev->dev.kobj,
+- "device");
+- if (result)
+- printk(KERN_ERR PREFIX "Create sysfs link\n");
+- }
++ printk(KERN_INFO PREFIX
++ "%s is registered as cooling_device%d\n",
++ device->dev->dev.bus_id, device->cdev->id);
++ result = sysfs_create_link(&device->dev->dev.kobj,
++ &device->cdev->device.kobj,
++ "thermal_cooling");
++ if (result)
++ printk(KERN_ERR PREFIX "Create sysfs link\n");
++ result = sysfs_create_link(&device->cdev->device.kobj,
++ &device->dev->dev.kobj, "device");
++ if (result)
++ printk(KERN_ERR PREFIX "Create sysfs link\n");
++
+ }
+ if (device->cap._DCS && device->cap._DSS){
+ static int count = 0;
+@@ -1050,87 +1055,82 @@ acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file)
+
+ static int acpi_video_device_add_fs(struct acpi_device *device)
+ {
+- struct proc_dir_entry *entry = NULL;
++ struct proc_dir_entry *entry, *device_dir;
+ struct acpi_video_device *vid_dev;
+
+-
+- if (!device)
+- return -ENODEV;
+-
+ vid_dev = acpi_driver_data(device);
+ if (!vid_dev)
+ return -ENODEV;
+
+- if (!acpi_device_dir(device)) {
+- acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
+- vid_dev->video->dir);
+- if (!acpi_device_dir(device))
+- return -ENODEV;
+- acpi_device_dir(device)->owner = THIS_MODULE;
+- }
++ device_dir = proc_mkdir(acpi_device_bid(device),
++ vid_dev->video->dir);
++ if (!device_dir)
++ return -ENOMEM;
++
++ device_dir->owner = THIS_MODULE;
+
+ /* 'info' [R] */
+- entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
++ entry = proc_create_data("info", S_IRUGO, device_dir,
++ &acpi_video_device_info_fops, acpi_driver_data(device));
+ if (!entry)
+- return -ENODEV;
+- else {
+- entry->proc_fops = &acpi_video_device_info_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
++ goto err_remove_dir;
+
+ /* 'state' [R/W] */
+- entry =
+- create_proc_entry("state", S_IFREG | S_IRUGO | S_IWUSR,
+- acpi_device_dir(device));
++ acpi_video_device_state_fops.write = acpi_video_device_write_state;
++ entry = proc_create_data("state", S_IFREG | S_IRUGO | S_IWUSR,
++ device_dir,
++ &acpi_video_device_state_fops,
++ acpi_driver_data(device));
+ if (!entry)
+- return -ENODEV;
+- else {
+- acpi_video_device_state_fops.write = acpi_video_device_write_state;
+- entry->proc_fops = &acpi_video_device_state_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
++ goto err_remove_info;
+
+ /* 'brightness' [R/W] */
+- entry =
+- create_proc_entry("brightness", S_IFREG | S_IRUGO | S_IWUSR,
+- acpi_device_dir(device));
++ acpi_video_device_brightness_fops.write =
++ acpi_video_device_write_brightness;
++ entry = proc_create_data("brightness", S_IFREG | S_IRUGO | S_IWUSR,
++ device_dir,
++ &acpi_video_device_brightness_fops,
++ acpi_driver_data(device));
+ if (!entry)
+- return -ENODEV;
+- else {
+- acpi_video_device_brightness_fops.write = acpi_video_device_write_brightness;
+- entry->proc_fops = &acpi_video_device_brightness_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
++ goto err_remove_state;
+
+ /* 'EDID' [R] */
+- entry = create_proc_entry("EDID", S_IRUGO, acpi_device_dir(device));
++ entry = proc_create_data("EDID", S_IRUGO, device_dir,
++ &acpi_video_device_EDID_fops,
++ acpi_driver_data(device));
+ if (!entry)
+- return -ENODEV;
+- else {
+- entry->proc_fops = &acpi_video_device_EDID_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
++ goto err_remove_brightness;
++
++ acpi_device_dir(device) = device_dir;
+
+ return 0;
++
++ err_remove_brightness:
++ remove_proc_entry("brightness", device_dir);
++ err_remove_state:
++ remove_proc_entry("state", device_dir);
++ err_remove_info:
++ remove_proc_entry("info", device_dir);
++ err_remove_dir:
++ remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir);
++ return -ENOMEM;
+ }
+
+ static int acpi_video_device_remove_fs(struct acpi_device *device)
+ {
+ struct acpi_video_device *vid_dev;
++ struct proc_dir_entry *device_dir;
+
+ vid_dev = acpi_driver_data(device);
+ if (!vid_dev || !vid_dev->video || !vid_dev->video->dir)
+ return -ENODEV;
+
+- if (acpi_device_dir(device)) {
+- remove_proc_entry("info", acpi_device_dir(device));
+- remove_proc_entry("state", acpi_device_dir(device));
+- remove_proc_entry("brightness", acpi_device_dir(device));
+- remove_proc_entry("EDID", acpi_device_dir(device));
++ device_dir = acpi_device_dir(device);
++ if (device_dir) {
++ remove_proc_entry("info", device_dir);
++ remove_proc_entry("state", device_dir);
++ remove_proc_entry("brightness", device_dir);
++ remove_proc_entry("EDID", device_dir);
+ remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir);
+ acpi_device_dir(device) = NULL;
+ }
+@@ -1337,94 +1337,81 @@ acpi_video_bus_write_DOS(struct file *file,
+
+ static int acpi_video_bus_add_fs(struct acpi_device *device)
+ {
+- struct proc_dir_entry *entry = NULL;
+- struct acpi_video_bus *video;
++ struct acpi_video_bus *video = acpi_driver_data(device);
++ struct proc_dir_entry *device_dir;
++ struct proc_dir_entry *entry;
+
++ device_dir = proc_mkdir(acpi_device_bid(device), acpi_video_dir);
++ if (!device_dir)
++ return -ENOMEM;
+
+- video = acpi_driver_data(device);
+-
+- if (!acpi_device_dir(device)) {
+- acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
+- acpi_video_dir);
+- if (!acpi_device_dir(device))
+- return -ENODEV;
+- video->dir = acpi_device_dir(device);
+- acpi_device_dir(device)->owner = THIS_MODULE;
+- }
++ device_dir->owner = THIS_MODULE;
+
+ /* 'info' [R] */
+- entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
++ entry = proc_create_data("info", S_IRUGO, device_dir,
++ &acpi_video_bus_info_fops,
++ acpi_driver_data(device));
+ if (!entry)
+- return -ENODEV;
+- else {
+- entry->proc_fops = &acpi_video_bus_info_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
++ goto err_remove_dir;
+
+ /* 'ROM' [R] */
+- entry = create_proc_entry("ROM", S_IRUGO, acpi_device_dir(device));
++ entry = proc_create_data("ROM", S_IRUGO, device_dir,
++ &acpi_video_bus_ROM_fops,
++ acpi_driver_data(device));
+ if (!entry)
+- return -ENODEV;
+- else {
+- entry->proc_fops = &acpi_video_bus_ROM_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
++ goto err_remove_info;
+
+ /* 'POST_info' [R] */
+- entry =
+- create_proc_entry("POST_info", S_IRUGO, acpi_device_dir(device));
++ entry = proc_create_data("POST_info", S_IRUGO, device_dir,
++ &acpi_video_bus_POST_info_fops,
++ acpi_driver_data(device));
+ if (!entry)
+- return -ENODEV;
+- else {
+- entry->proc_fops = &acpi_video_bus_POST_info_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
++ goto err_remove_rom;
+
+ /* 'POST' [R/W] */
+- entry =
+- create_proc_entry("POST", S_IFREG | S_IRUGO | S_IRUSR,
+- acpi_device_dir(device));
++ acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST;
++ entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IWUSR,
++ device_dir,
++ &acpi_video_bus_POST_fops,
++ acpi_driver_data(device));
+ if (!entry)
+- return -ENODEV;
+- else {
+- acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST;
+- entry->proc_fops = &acpi_video_bus_POST_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
++ goto err_remove_post_info;
+
+ /* 'DOS' [R/W] */
+- entry =
+- create_proc_entry("DOS", S_IFREG | S_IRUGO | S_IRUSR,
+- acpi_device_dir(device));
++ acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS;
++ entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IWUSR,
++ device_dir,
++ &acpi_video_bus_DOS_fops,
++ acpi_driver_data(device));
+ if (!entry)
+- return -ENODEV;
+- else {
+- acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS;
+- entry->proc_fops = &acpi_video_bus_DOS_fops;
+- entry->data = acpi_driver_data(device);
+- entry->owner = THIS_MODULE;
+- }
++ goto err_remove_post;
+
++ video->dir = acpi_device_dir(device) = device_dir;
+ return 0;
++
++ err_remove_post:
++ remove_proc_entry("POST", device_dir);
++ err_remove_post_info:
++ remove_proc_entry("POST_info", device_dir);
++ err_remove_rom:
++ remove_proc_entry("ROM", device_dir);
++ err_remove_info:
++ remove_proc_entry("info", device_dir);
++ err_remove_dir:
++ remove_proc_entry(acpi_device_bid(device), acpi_video_dir);
++ return -ENOMEM;
+ }
+
+ static int acpi_video_bus_remove_fs(struct acpi_device *device)
+ {
+- struct acpi_video_bus *video;
++ struct proc_dir_entry *device_dir = acpi_device_dir(device);
+
+-
+- video = acpi_driver_data(device);
+-
+- if (acpi_device_dir(device)) {
+- remove_proc_entry("info", acpi_device_dir(device));
+- remove_proc_entry("ROM", acpi_device_dir(device));
+- remove_proc_entry("POST_info", acpi_device_dir(device));
+- remove_proc_entry("POST", acpi_device_dir(device));
+- remove_proc_entry("DOS", acpi_device_dir(device));
++ if (device_dir) {
++ remove_proc_entry("info", device_dir);
++ remove_proc_entry("ROM", device_dir);
++ remove_proc_entry("POST_info", device_dir);
++ remove_proc_entry("POST", device_dir);
++ remove_proc_entry("DOS", device_dir);
+ remove_proc_entry(acpi_device_bid(device), acpi_video_dir);
+ acpi_device_dir(device) = NULL;
+ }
+@@ -1440,11 +1427,15 @@ static int acpi_video_bus_remove_fs(struct acpi_device *device)
+ static struct acpi_video_device_attrib*
+ acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id)
+ {
+- int count;
++ struct acpi_video_enumerated_device *ids;
++ int i;
++
++ for (i = 0; i < video->attached_count; i++) {
++ ids = &video->attached_array[i];
++ if ((ids->value.int_val & 0xffff) == device_id)
++ return &ids->value.attrib;
++ }
+
+- for(count = 0; count < video->attached_count; count++)
+- if((video->attached_array[count].value.int_val & 0xffff) == device_id)
+- return &(video->attached_array[count].value.attrib);
+ return NULL;
+ }
+
+@@ -1571,20 +1562,16 @@ static void
+ acpi_video_device_bind(struct acpi_video_bus *video,
+ struct acpi_video_device *device)
+ {
++ struct acpi_video_enumerated_device *ids;
+ int i;
+
+-#define IDS_VAL(i) video->attached_array[i].value.int_val
+-#define IDS_BIND(i) video->attached_array[i].bind_info
+-
+- for (i = 0; IDS_VAL(i) != ACPI_VIDEO_HEAD_INVALID &&
+- i < video->attached_count; i++) {
+- if (device->device_id == (IDS_VAL(i) & 0xffff)) {
+- IDS_BIND(i) = device;
++ for (i = 0; i < video->attached_count; i++) {
++ ids = &video->attached_array[i];
++ if (device->device_id == (ids->value.int_val & 0xffff)) {
++ ids->bind_info = device;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i));
+ }
+ }
+-#undef IDS_VAL
+-#undef IDS_BIND
+ }
+
+ /*
+@@ -1603,7 +1590,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
+ int status;
+ int count;
+ int i;
+- struct acpi_video_enumerated_device *active_device_list;
++ struct acpi_video_enumerated_device *active_list;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *dod = NULL;
+ union acpi_object *obj;
+@@ -1624,13 +1611,10 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n",
+ dod->package.count));
+
+- active_device_list = kmalloc((1 +
+- dod->package.count) *
+- sizeof(struct
+- acpi_video_enumerated_device),
+- GFP_KERNEL);
+-
+- if (!active_device_list) {
++ active_list = kcalloc(1 + dod->package.count,
++ sizeof(struct acpi_video_enumerated_device),
++ GFP_KERNEL);
++ if (!active_list) {
+ status = -ENOMEM;
+ goto out;
+ }
+@@ -1640,23 +1624,24 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
+ obj = &dod->package.elements[i];
+
+ if (obj->type != ACPI_TYPE_INTEGER) {
+- printk(KERN_ERR PREFIX "Invalid _DOD data\n");
+- active_device_list[i].value.int_val =
+- ACPI_VIDEO_HEAD_INVALID;
++ printk(KERN_ERR PREFIX
++ "Invalid _DOD data in element %d\n", i);
++ continue;
+ }
+- active_device_list[i].value.int_val = obj->integer.value;
+- active_device_list[i].bind_info = NULL;
++
++ active_list[count].value.int_val = obj->integer.value;
++ active_list[count].bind_info = NULL;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i,
+ (int)obj->integer.value));
+ count++;
+ }
+- active_device_list[count].value.int_val = ACPI_VIDEO_HEAD_END;
+
+ kfree(video->attached_array);
+
+- video->attached_array = active_device_list;
++ video->attached_array = active_list;
+ video->attached_count = count;
+- out:
++
++ out:
+ kfree(buffer.pointer);
+ return status;
+ }
+diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
+index 25aba69..1c11df9 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
+@@ -539,11 +566,11 @@ config PATA_RADISYS
+
+ If unsure, say N.
+
+-config PATA_RB500
+- tristate "RouterBoard 500 PATA CompactFlash support"
+- depends on MIKROTIK_RB500
++config PATA_RB532
++ tristate "RouterBoard 532 PATA CompactFlash support"
++ depends on MIKROTIK_RB532
+ help
+- This option enables support for the RouterBoard 500
++ This option enables support for the RouterBoard 532
+ PATA CompactFlash controller.
+
+ If unsure, say N.
+@@ -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..b693d82 100644
+--- a/drivers/ata/Makefile
++++ b/drivers/ata/Makefile
+@@ -55,7 +55,7 @@ obj-$(CONFIG_PATA_PDC2027X) += pata_pdc2027x.o
+ obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o
+ obj-$(CONFIG_PATA_QDI) += pata_qdi.o
+ obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o
+-obj-$(CONFIG_PATA_RB500) += pata_rb500_cf.o
++obj-$(CONFIG_PATA_RB532) += pata_rb532_cf.o
+ obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o
+ obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o
+ obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o
+@@ -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..8cace9a 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,
+@@ -433,10 +358,9 @@ static const struct ata_port_info ahci_port_info[] = {
+ /* board_ahci_sb600 */
+ {
+ AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL |
+- AHCI_HFLAG_32BIT_ONLY |
++ AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
+ 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..3bc4885 100644
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -46,7 +46,6 @@
+ #include <linux/init.h>
+ #include <linux/list.h>
+ #include <linux/mm.h>
+-#include <linux/highmem.h>
+ #include <linux/spinlock.h>
+ #include <linux/blkdev.h>
+ #include <linux/delay.h>
+@@ -62,7 +61,6 @@
+ #include <scsi/scsi_cmnd.h>
+ #include <scsi/scsi_host.h>
+ #include <linux/libata.h>
+-#include <asm/semaphore.h>
+ #include <asm/byteorder.h>
+ #include <linux/cdrom.h>
+
+@@ -74,6 +72,19 @@ const unsigned long sata_deb_timing_normal[] = { 5, 100, 2000 };
+ const unsigned long sata_deb_timing_hotplug[] = { 25, 500, 2000 };
+ const unsigned long sata_deb_timing_long[] = { 100, 2000, 5000 };
+
++const struct ata_port_operations ata_base_port_ops = {
++ .prereset = ata_std_prereset,
++ .postreset = ata_std_postreset,
++ .error_handler = ata_std_error_handler,
++};
++
++const struct ata_port_operations sata_port_ops = {
++ .inherits = &ata_base_port_ops,
++
++ .qc_defer = ata_std_qc_defer,
++ .hardreset = sata_std_hardreset,
++};
++
+ static unsigned int ata_dev_init_params(struct ata_device *dev,
+ u16 heads, u16 sectors);
+ static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
+@@ -1043,50 +1054,6 @@ static void ata_lpm_disable(struct ata_host *host)
+ }
+ #endif /* CONFIG_PM */
+
+-
+-/**
+- * ata_devchk - PATA device presence detection
+- * @ap: ATA channel to examine
+- * @device: Device to examine (starting at zero)
+- *
+- * This technique was originally described in
+- * Hale Landis's ATADRVR (www.ata-atapi.com), and
+- * later found its way into the ATA/ATAPI spec.
+- *
+- * Write a pattern to the ATA shadow registers,
+- * and if a device is present, it will respond by
+- * correctly storing and echoing back the
+- * ATA shadow register contents.
+- *
+- * LOCKING:
+- * caller.
+- */
+-
+-static unsigned int ata_devchk(struct ata_port *ap, unsigned int device)
+-{
+- struct ata_ioports *ioaddr = &ap->ioaddr;
+- u8 nsect, lbal;
+-
+- ap->ops->dev_select(ap, device);
+-
+- iowrite8(0x55, ioaddr->nsect_addr);
+- iowrite8(0xaa, ioaddr->lbal_addr);
+-
+- iowrite8(0xaa, ioaddr->nsect_addr);
+- iowrite8(0x55, ioaddr->lbal_addr);
+-
+- iowrite8(0x55, ioaddr->nsect_addr);
+- iowrite8(0xaa, ioaddr->lbal_addr);
+-
+- nsect = ioread8(ioaddr->nsect_addr);
+- lbal = ioread8(ioaddr->lbal_addr);
+-
+- if ((nsect == 0x55) && (lbal == 0xaa))
+- return 1; /* we found a device */
+-
+- return 0; /* nothing found */
+-}
+-
+ /**
+ * ata_dev_classify - determine device type based on ATA-spec signature
+ * @tf: ATA taskfile register set for device to be identified
+@@ -1147,75 +1114,6 @@ unsigned int ata_dev_classify(const struct ata_taskfile *tf)
+ }
+
+ /**
+- * ata_dev_try_classify - Parse returned ATA device signature
+- * @dev: ATA device to classify (starting at zero)
+- * @present: device seems present
+- * @r_err: Value of error register on completion
+- *
+- * After an event -- SRST, E.D.D., or SATA COMRESET -- occurs,
+- * an ATA/ATAPI-defined set of values is placed in the ATA
+- * shadow registers, indicating the results of device detection
+- * and diagnostics.
+- *
+- * Select the ATA device, and read the values from the ATA shadow
+- * registers. Then parse according to the Error register value,
+- * and the spec-defined values examined by ata_dev_classify().
+- *
+- * LOCKING:
+- * caller.
+- *
+- * RETURNS:
+- * Device type - %ATA_DEV_ATA, %ATA_DEV_ATAPI or %ATA_DEV_NONE.
+- */
+-unsigned int ata_dev_try_classify(struct ata_device *dev, int present,
+- u8 *r_err)
+-{
+- struct ata_port *ap = dev->link->ap;
+- struct ata_taskfile tf;
+- unsigned int class;
+- u8 err;
+-
+- ap->ops->dev_select(ap, dev->devno);
+-
+- memset(&tf, 0, sizeof(tf));
+-
+- ap->ops->tf_read(ap, &tf);
+- err = tf.feature;
+- if (r_err)
+- *r_err = err;
+-
+- /* see if device passed diags: continue and warn later */
+- if (err == 0)
+- /* diagnostic fail : do nothing _YET_ */
+- dev->horkage |= ATA_HORKAGE_DIAGNOSTIC;
+- else if (err == 1)
+- /* do nothing */ ;
+- else if ((dev->devno == 0) && (err == 0x81))
+- /* do nothing */ ;
+- else
+- return ATA_DEV_NONE;
+-
+- /* determine if device is ATA or ATAPI */
+- class = ata_dev_classify(&tf);
+-
+- if (class == ATA_DEV_UNKNOWN) {
+- /* If the device failed diagnostic, it's likely to
+- * have reported incorrect device signature too.
+- * Assume ATA device if the device seems present but
+- * device signature is invalid with diagnostic
+- * failure.
+- */
+- if (present && (dev->horkage & ATA_HORKAGE_DIAGNOSTIC))
+- class = ATA_DEV_ATA;
+- else
+- class = ATA_DEV_NONE;
+- } else if ((class == ATA_DEV_ATA) && (ata_chk_status(ap) == 0))
+- class = ATA_DEV_NONE;
+-
+- return class;
+-}
+-
+-/**
+ * ata_id_string - Convert IDENTIFY DEVICE page into string
+ * @id: IDENTIFY DEVICE results we will examine
+ * @s: string into which data is output
+@@ -1293,7 +1191,7 @@ static u64 ata_id_n_sectors(const u16 *id)
+ }
+ }
+
+-static u64 ata_tf_to_lba48(struct ata_taskfile *tf)
++u64 ata_tf_to_lba48(const struct ata_taskfile *tf)
+ {
+ u64 sectors = 0;
+
+@@ -1304,10 +1202,10 @@ static u64 ata_tf_to_lba48(struct ata_taskfile *tf)
+ sectors |= (tf->lbam & 0xff) << 8;
+ sectors |= (tf->lbal & 0xff);
+
+- return ++sectors;
++ return sectors;
+ }
+
+-static u64 ata_tf_to_lba(struct ata_taskfile *tf)
++u64 ata_tf_to_lba(const struct ata_taskfile *tf)
+ {
+ u64 sectors = 0;
+
+@@ -1316,7 +1214,7 @@ static u64 ata_tf_to_lba(struct ata_taskfile *tf)
+ sectors |= (tf->lbam & 0xff) << 8;
+ sectors |= (tf->lbal & 0xff);
+
+- return ++sectors;
++ return sectors;
+ }
+
+ /**
+@@ -1361,9 +1259,9 @@ static int ata_read_native_max_address(struct ata_device *dev, u64 *max_sectors)
+ }
+
+ if (lba48)
+- *max_sectors = ata_tf_to_lba48(&tf);
++ *max_sectors = ata_tf_to_lba48(&tf) + 1;
+ else
+- *max_sectors = ata_tf_to_lba(&tf);
++ *max_sectors = ata_tf_to_lba(&tf) + 1;
+ if (dev->horkage & ATA_HORKAGE_HPA_SIZE)
+ (*max_sectors)--;
+ return 0;
+@@ -1523,89 +1421,6 @@ static int ata_hpa_resize(struct ata_device *dev)
+ }
+
+ /**
+- * ata_noop_dev_select - Select device 0/1 on ATA bus
+- * @ap: ATA channel to manipulate
+- * @device: ATA device (numbered from zero) to select
+- *
+- * This function performs no actual function.
+- *
+- * May be used as the dev_select() entry in ata_port_operations.
+- *
+- * LOCKING:
+- * caller.
+- */
+-void ata_noop_dev_select(struct ata_port *ap, unsigned int device)
+-{
+-}
+-
+-
+-/**
+- * ata_std_dev_select - Select device 0/1 on ATA bus
+- * @ap: ATA channel to manipulate
+- * @device: ATA device (numbered from zero) to select
+- *
+- * Use the method defined in the ATA specification to
+- * make either device 0, or device 1, active on the
+- * ATA channel. Works with both PIO and MMIO.
+- *
+- * May be used as the dev_select() entry in ata_port_operations.
+- *
+- * LOCKING:
+- * caller.
+- */
+-
+-void ata_std_dev_select(struct ata_port *ap, unsigned int device)
+-{
+- u8 tmp;
+-
+- if (device == 0)
+- tmp = ATA_DEVICE_OBS;
+- else
+- tmp = ATA_DEVICE_OBS | ATA_DEV1;
+-
+- iowrite8(tmp, ap->ioaddr.device_addr);
+- ata_pause(ap); /* needed; also flushes, for mmio */
+-}
+-
+-/**
+- * ata_dev_select - Select device 0/1 on ATA bus
+- * @ap: ATA channel to manipulate
+- * @device: ATA device (numbered from zero) to select
+- * @wait: non-zero to wait for Status register BSY bit to clear
+- * @can_sleep: non-zero if context allows sleeping
+- *
+- * Use the method defined in the ATA specification to
+- * make either device 0, or device 1, active on the
+- * ATA channel.
+- *
+- * This is a high-level version of ata_std_dev_select(),
+- * which additionally provides the services of inserting
+- * the proper pauses and status polling, where needed.
+- *
+- * LOCKING:
+- * caller.
+- */
+-
+-void ata_dev_select(struct ata_port *ap, unsigned int device,
+- unsigned int wait, unsigned int can_sleep)
+-{
+- if (ata_msg_probe(ap))
+- ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, "
+- "device %u, wait %u\n", device, wait);
+-
+- if (wait)
+- ata_wait_idle(ap);
+-
+- ap->ops->dev_select(ap, device);
+-
+- if (wait) {
+- if (can_sleep && ap->link.device[device].class == ATA_DEV_ATAPI)
+- msleep(150);
+- ata_wait_idle(ap);
+- }
+-}
+-
+-/**
+ * ata_dump_id - IDENTIFY DEVICE info debugging output
+ * @id: IDENTIFY DEVICE page to dump
+ *
+@@ -1732,8 +1547,7 @@ unsigned long ata_id_xfermask(const u16 *id)
+ * LOCKING:
+ * Inherited from caller.
+ */
+-static void ata_pio_queue_task(struct ata_port *ap, void *data,
+- unsigned long delay)
++void ata_pio_queue_task(struct ata_port *ap, void *data, unsigned long delay)
+ {
+ ap->port_task_data = data;
+
+@@ -2097,7 +1911,6 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+ if (ata_msg_ctl(ap))
+ ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __func__);
+
+- ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
+ retry:
+ ata_tf_init(dev, &tf);
+
+@@ -2464,7 +2277,7 @@ int ata_dev_configure(struct ata_device *dev)
+ * changed notifications and ATAPI ANs.
+ */
+ if ((ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) &&
+- (!ap->nr_pmp_links ||
++ (!sata_pmp_attached(ap) ||
+ sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) {
+ unsigned int err_mask;
+
+@@ -2558,9 +2371,6 @@ int ata_dev_configure(struct ata_device *dev)
+ }
+ }
+
+- if (ata_msg_probe(ap))
+- ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n",
+- __func__, ata_chk_status(ap));
+ return 0;
+
+ err_out_nosup:
+@@ -2806,7 +2616,7 @@ void ata_port_probe(struct ata_port *ap)
+ * LOCKING:
+ * None.
+ */
+-void sata_print_link_status(struct ata_link *link)
++static void sata_print_link_status(struct ata_link *link)
+ {
+ u32 sstatus, scontrol, tmp;
+
+@@ -2962,7 +2772,7 @@ static int __sata_set_spd_needed(struct ata_link *link, u32 *scontrol)
+ * RETURNS:
+ * 1 if SATA spd configuration is needed, 0 otherwise.
+ */
+-int sata_set_spd_needed(struct ata_link *link)
++static int sata_set_spd_needed(struct ata_link *link)
+ {
+ u32 scontrol;
+
+@@ -3321,16 +3131,21 @@ static int ata_dev_set_mode(struct ata_device *dev)
+ if (rc)
+ return rc;
+
+- /* Old CFA may refuse this command, which is just fine */
+- if (dev->xfer_shift == ATA_SHIFT_PIO && ata_id_is_cfa(dev->id))
+- ign_dev_err = 1;
+-
+- /* Some very old devices and some bad newer ones fail any kind of
+- SET_XFERMODE request but support PIO0-2 timings and no IORDY */
+- if (dev->xfer_shift == ATA_SHIFT_PIO && !ata_id_has_iordy(dev->id) &&
+- dev->pio_mode <= XFER_PIO_2)
+- ign_dev_err = 1;
+-
++ if (dev->xfer_shift == ATA_SHIFT_PIO) {
++ /* Old CFA may refuse this command, which is just fine */
++ if (ata_id_is_cfa(dev->id))
++ ign_dev_err = 1;
++ /* Catch several broken garbage emulations plus some pre
++ ATA devices */
++ if (ata_id_major_version(dev->id) == 0 &&
++ dev->pio_mode <= XFER_PIO_2)
++ ign_dev_err = 1;
++ /* Some very old devices and some bad newer ones fail
++ any kind of SET_XFERMODE request but support PIO0-2
++ timings and no IORDY */
++ if (!ata_id_has_iordy(dev->id) && dev->pio_mode <= XFER_PIO_2)
++ ign_dev_err = 1;
++ }
+ /* Early MWDMA devices do DMA but don't allow DMA mode setting.
+ Don't fail an MWDMA0 set IFF the device indicates it is in MWDMA0 */
+ if (dev->xfer_shift == ATA_SHIFT_MWDMA &&
+@@ -3474,170 +3289,73 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
+ }
+
+ /**
+- * ata_tf_to_host - issue ATA taskfile to host controller
+- * @ap: port to which command is being issued
+- * @tf: ATA taskfile register set
+- *
+- * Issues ATA taskfile register set to ATA host controller,
+- * with proper synchronization with interrupt handler and
+- * other threads.
+- *
+- * LOCKING:
+- * spin_lock_irqsave(host lock)
+- */
+-
+-static inline void ata_tf_to_host(struct ata_port *ap,
+- const struct ata_taskfile *tf)
+-{
+- ap->ops->tf_load(ap, tf);
+- ap->ops->exec_command(ap, tf);
+-}
+-
+-/**
+- * ata_busy_sleep - sleep until BSY clears, or timeout
+- * @ap: port containing status register to be polled
+- * @tmout_pat: impatience timeout
+- * @tmout: overall timeout
+- *
+- * Sleep until ATA Status register bit BSY clears,
+- * or a timeout occurs.
+- *
+- * LOCKING:
+- * Kernel thread context (may sleep).
+- *
+- * RETURNS:
+- * 0 on success, -errno otherwise.
+- */
+-int ata_busy_sleep(struct ata_port *ap,
+- unsigned long tmout_pat, unsigned long tmout)
+-{
+- unsigned long timer_start, timeout;
+- u8 status;
+-
+- status = ata_busy_wait(ap, ATA_BUSY, 300);
+- timer_start = jiffies;
+- timeout = timer_start + tmout_pat;
+- while (status != 0xff && (status & ATA_BUSY) &&
+- time_before(jiffies, timeout)) {
+- msleep(50);
+- status = ata_busy_wait(ap, ATA_BUSY, 3);
+- }
+-
+- if (status != 0xff && (status & ATA_BUSY))
+- ata_port_printk(ap, KERN_WARNING,
+- "port is slow to respond, please be patient "
+- "(Status 0x%x)\n", status);
+-
+- timeout = timer_start + tmout;
+- while (status != 0xff && (status & ATA_BUSY) &&
+- time_before(jiffies, timeout)) {
+- msleep(50);
+- status = ata_chk_status(ap);
+- }
+-
+- if (status == 0xff)
+- return -ENODEV;
+-
+- if (status & ATA_BUSY) {
+- ata_port_printk(ap, KERN_ERR, "port failed to respond "
+- "(%lu secs, Status 0x%x)\n",
+- tmout / HZ, status);
+- return -EBUSY;
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * ata_wait_after_reset - wait before checking status after reset
+- * @ap: port containing status register to be polled
++ * ata_wait_ready - wait for link to become ready
++ * @link: link to be waited on
+ * @deadline: deadline jiffies for the operation
++ * @check_ready: callback to check link readiness
+ *
+- * After reset, we need to pause a while before reading status.
+- * Also, certain combination of controller and device report 0xff
+- * for some duration (e.g. until SATA PHY is up and running)
+- * which is interpreted as empty port in ATA world. This
+- * function also waits for such devices to get out of 0xff
+- * status.
++ * Wait for @link to become ready. @check_ready should return
++ * positive number if @link is ready, 0 if it isn't, -ENODEV if
++ * link doesn't seem to be occupied, other errno for other error
++ * conditions.
+ *
+- * LOCKING:
+- * Kernel thread context (may sleep).
+- */
+-void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline)
+-{
+- unsigned long until = jiffies + ATA_TMOUT_FF_WAIT;
+-
+- if (time_before(until, deadline))
+- deadline = until;
+-
+- /* Spec mandates ">= 2ms" before checking status. We wait
+- * 150ms, because that was the magic delay used for ATAPI
+- * devices in Hale Landis's ATADRVR, for the period of time
+- * between when the ATA command register is written, and then
+- * status is checked. Because waiting for "a while" before
+- * checking status is fine, post SRST, we perform this magic
+- * delay here as well.
+- *
+- * Old drivers/ide uses the 2mS rule and then waits for ready.
+- */
+- msleep(150);
+-
+- /* Wait for 0xff to clear. Some SATA devices take a long time
+- * to clear 0xff after reset. For example, HHD424020F7SV00
+- * iVDR needs >= 800ms while. Quantum GoVault needs even more
+- * than that.
+- *
+- * Note that some PATA controllers (pata_ali) explode if
+- * status register is read more than once when there's no
+- * device attached.
+- */
+- if (ap->flags & ATA_FLAG_SATA) {
+- while (1) {
+- u8 status = ata_chk_status(ap);
+-
+- if (status != 0xff || time_after(jiffies, deadline))
+- return;
+-
+- msleep(50);
+- }
+- }
+-}
+-
+-/**
+- * ata_wait_ready - sleep until BSY clears, or timeout
+- * @ap: port containing status register to be polled
+- * @deadline: deadline jiffies for the operation
+- *
+- * Sleep until ATA Status register bit BSY clears, or timeout
+- * occurs.
++ * Transient -ENODEV conditions are allowed for
++ * ATA_TMOUT_FF_WAIT.
+ *
+ * LOCKING:
+- * Kernel thread context (may sleep).
++ * EH context.
+ *
+ * RETURNS:
+- * 0 on success, -errno otherwise.
++ * 0 if @linke is ready before @deadline; otherwise, -errno.
+ */
+-int ata_wait_ready(struct ata_port *ap, unsigned long deadline)
++int ata_wait_ready(struct ata_link *link, unsigned long deadline,
++ int (*check_ready)(struct ata_link *link))
+ {
+ unsigned long start = jiffies;
++ unsigned long nodev_deadline = start + ATA_TMOUT_FF_WAIT;
+ int warned = 0;
+
++ if (time_after(nodev_deadline, deadline))
++ nodev_deadline = deadline;
++
+ while (1) {
+- u8 status = ata_chk_status(ap);
+ unsigned long now = jiffies;
++ int ready, tmp;
+
+- if (!(status & ATA_BUSY))
++ ready = tmp = check_ready(link);
++ if (ready > 0)
+ return 0;
+- if (!ata_link_online(&ap->link) && status == 0xff)
+- return -ENODEV;
++
++ /* -ENODEV could be transient. Ignore -ENODEV if link
++ * is online. Also, some SATA devices take a long
++ * time to clear 0xff after reset. For example,
++ * HHD424020F7SV00 iVDR needs >= 800ms while Quantum
++ * GoVault needs even more than that. Wait for
++ * ATA_TMOUT_FF_WAIT on -ENODEV if link isn't offline.
++ *
++ * Note that some PATA controllers (pata_ali) explode
++ * if status register is read more than once when
++ * there's no device attached.
++ */
++ if (ready == -ENODEV) {
++ if (ata_link_online(link))
++ ready = 0;
++ else if ((link->ap->flags & ATA_FLAG_SATA) &&
++ !ata_link_offline(link) &&
++ time_before(now, nodev_deadline))
++ ready = 0;
++ }
++
++ if (ready)
++ return ready;
+ if (time_after(now, deadline))
+ return -EBUSY;
+
+ if (!warned && time_after(now, start + 5 * HZ) &&
+ (deadline - now > 3 * HZ)) {
+- ata_port_printk(ap, KERN_WARNING,
+- "port is slow to respond, please be patient "
+- "(Status 0x%x)\n", status);
++ ata_link_printk(link, KERN_WARNING,
++ "link is slow to respond, please be patient "
++ "(ready=%d)\n", tmp);
+ warned = 1;
+ }
+
+@@ -3645,179 +3363,26 @@ int ata_wait_ready(struct ata_port *ap, unsigned long deadline)
+ }
+ }
+
+-static int ata_bus_post_reset(struct ata_port *ap, unsigned int devmask,
+- unsigned long deadline)
+-{
+- struct ata_ioports *ioaddr = &ap->ioaddr;
+- unsigned int dev0 = devmask & (1 << 0);
+- unsigned int dev1 = devmask & (1 << 1);
+- int rc, ret = 0;
+-
+- /* if device 0 was found in ata_devchk, wait for its
+- * BSY bit to clear
+- */
+- if (dev0) {
+- rc = ata_wait_ready(ap, deadline);
+- if (rc) {
+- if (rc != -ENODEV)
+- return rc;
+- ret = rc;
+- }
+- }
+-
+- /* if device 1 was found in ata_devchk, wait for register
+- * access briefly, then wait for BSY to clear.
+- */
+- if (dev1) {
+- int i;
+-
+- ap->ops->dev_select(ap, 1);
+-
+- /* Wait for register access. Some ATAPI devices fail
+- * to set nsect/lbal after reset, so don't waste too
+- * much time on it. We're gonna wait for !BSY anyway.
+- */
+- for (i = 0; i < 2; i++) {
+- u8 nsect, lbal;
+-
+- nsect = ioread8(ioaddr->nsect_addr);
+- lbal = ioread8(ioaddr->lbal_addr);
+- if ((nsect == 1) && (lbal == 1))
+- break;
+- msleep(50); /* give drive a breather */
+- }
+-
+- rc = ata_wait_ready(ap, deadline);
+- if (rc) {
+- if (rc != -ENODEV)
+- return rc;
+- ret = rc;
+- }
+- }
+-
+- /* is all this really necessary? */
+- ap->ops->dev_select(ap, 0);
+- if (dev1)
+- ap->ops->dev_select(ap, 1);
+- if (dev0)
+- ap->ops->dev_select(ap, 0);
+-
+- return ret;
+-}
+-
+-static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
+- unsigned long deadline)
+-{
+- struct ata_ioports *ioaddr = &ap->ioaddr;
+-
+- DPRINTK("ata%u: bus reset via SRST\n", ap->print_id);
+-
+- /* software reset. causes dev0 to be selected */
+- iowrite8(ap->ctl, ioaddr->ctl_addr);
+- udelay(20); /* FIXME: flush */
+- iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
+- udelay(20); /* FIXME: flush */
+- iowrite8(ap->ctl, ioaddr->ctl_addr);
+-
+- /* wait a while before checking status */
+- ata_wait_after_reset(ap, deadline);
+-
+- /* Before we perform post reset processing we want to see if
+- * the bus shows 0xFF because the odd clown forgets the D7
+- * pulldown resistor.
+- */
+- if (ata_chk_status(ap) == 0xFF)
+- return -ENODEV;
+-
+- return ata_bus_post_reset(ap, devmask, deadline);
+-}
+-
+ /**
+- * ata_bus_reset - reset host port and associated ATA channel
+- * @ap: port to reset
++ * ata_wait_after_reset - wait for link to become ready after reset
++ * @link: link to be waited on
++ * @deadline: deadline jiffies for the operation
++ * @check_ready: callback to check link readiness
+ *
+- * This is typically the first time we actually start issuing
+- * commands to the ATA channel. We wait for BSY to clear, then
+- * issue EXECUTE DEVICE DIAGNOSTIC command, polling for its
+- * result. Determine what devices, if any, are on the channel
+- * by looking at the device 0/1 error register. Look at the signature
+- * stored in each device's taskfile registers, to determine if
+- * the device is ATA or ATAPI.
++ * Wait for @link to become ready after reset.
+ *
+ * LOCKING:
+- * PCI/etc. bus probe sem.
+- * Obtains host lock.
++ * EH context.
+ *
+- * SIDE EFFECTS:
+- * Sets ATA_FLAG_DISABLED if bus reset fails.
++ * RETURNS:
++ * 0 if @linke is ready before @deadline; otherwise, -errno.
+ */
+-
+-void ata_bus_reset(struct ata_port *ap)
++int ata_wait_after_reset(struct ata_link *link, unsigned long deadline,
++ int (*check_ready)(struct ata_link *link))
+ {
+- struct ata_device *device = ap->link.device;
+- struct ata_ioports *ioaddr = &ap->ioaddr;
+- unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
+- u8 err;
+- unsigned int dev0, dev1 = 0, devmask = 0;
+- int rc;
+-
+- DPRINTK("ENTER, host %u, port %u\n", ap->print_id, ap->port_no);
+-
+- /* determine if device 0/1 are present */
+- if (ap->flags & ATA_FLAG_SATA_RESET)
+- dev0 = 1;
+- else {
+- dev0 = ata_devchk(ap, 0);
+- if (slave_possible)
+- dev1 = ata_devchk(ap, 1);
+- }
+-
+- if (dev0)
+- devmask |= (1 << 0);
+- if (dev1)
+- devmask |= (1 << 1);
++ msleep(ATA_WAIT_AFTER_RESET_MSECS);
+
+- /* select device 0 again */
+- ap->ops->dev_select(ap, 0);
+-
+- /* issue bus reset */
+- if (ap->flags & ATA_FLAG_SRST) {
+- rc = ata_bus_softreset(ap, devmask, jiffies + 40 * HZ);
+- if (rc && rc != -ENODEV)
+- goto err_out;
+- }
+-
+- /*
+- * determine by signature whether we have ATA or ATAPI devices
+- */
+- device[0].class = ata_dev_try_classify(&device[0], dev0, &err);
+- if ((slave_possible) && (err != 0x81))
+- device[1].class = ata_dev_try_classify(&device[1], dev1, &err);
+-
+- /* is double-select really necessary? */
+- if (device[1].class != ATA_DEV_NONE)
+- ap->ops->dev_select(ap, 1);
+- if (device[0].class != ATA_DEV_NONE)
+- ap->ops->dev_select(ap, 0);
+-
+- /* if no devices were detected, disable this port */
+- if ((device[0].class == ATA_DEV_NONE) &&
+- (device[1].class == ATA_DEV_NONE))
+- goto err_out;
+-
+- if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
+- /* set up device control for ATA_FLAG_SATA_RESET */
+- iowrite8(ap->ctl, ioaddr->ctl_addr);
+- }
+-
+- DPRINTK("EXIT\n");
+- return;
+-
+-err_out:
+- ata_port_printk(ap, KERN_ERR, "disabling port\n");
+- ata_port_disable(ap);
+-
+- DPRINTK("EXIT\n");
++ return ata_wait_ready(link, deadline, check_ready);
+ }
+
+ /**
+@@ -3906,7 +3471,7 @@ int sata_link_debounce(struct ata_link *link, const unsigned long *params,
+ int sata_link_resume(struct ata_link *link, const unsigned long *params,
+ unsigned long deadline)
+ {
+- u32 scontrol;
++ u32 scontrol, serror;
+ int rc;
+
+ if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol)))
+@@ -3922,7 +3487,25 @@ int sata_link_resume(struct ata_link *link, const unsigned long *params,
+ */
+ msleep(200);
+
+- return sata_link_debounce(link, params, deadline);
++ if ((rc = sata_link_debounce(link, params, deadline)))
++ return rc;
++
++ /* Clear SError. PMP and some host PHYs require this to
++ * operate and clearing should be done before checking PHY
++ * online status to avoid race condition (hotplugging between
++ * link resume and status check).
++ */
++ if (!(rc = sata_scr_read(link, SCR_ERROR, &serror)))
++ rc = sata_scr_write(link, SCR_ERROR, serror);
++ if (rc == 0 || rc == -EINVAL) {
++ unsigned long flags;
++
++ spin_lock_irqsave(link->ap->lock, flags);
++ link->eh_info.serror = 0;
++ spin_unlock_irqrestore(link->ap->lock, flags);
++ rc = 0;
++ }
++ return rc;
+ }
+
+ /**
+@@ -3949,17 +3532,6 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline)
+ const unsigned long *timing = sata_ehc_deb_timing(ehc);
+ int rc;
+
+- /* handle link resume */
+- if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
+- (link->flags & ATA_LFLAG_HRST_TO_RESUME))
+- ehc->i.action |= ATA_EH_HARDRESET;
+-
+- /* Some PMPs don't work with only SRST, force hardreset if PMP
+- * is supported.
+- */
+- if (ap->flags & ATA_FLAG_PMP)
+- ehc->i.action |= ATA_EH_HARDRESET;
+-
+ /* if we're about to do hardreset, nothing more to do */
+ if (ehc->i.action & ATA_EH_HARDRESET)
+ return 0;
+@@ -3973,88 +3545,30 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline)
+ "link for reset (errno=%d)\n", rc);
+ }
+
+- /* Wait for !BSY if the controller can wait for the first D2H
+- * Reg FIS and we don't know that no device is attached.
+- */
+- if (!(link->flags & ATA_LFLAG_SKIP_D2H_BSY) && !ata_link_offline(link)) {
+- rc = ata_wait_ready(ap, deadline);
+- if (rc && rc != -ENODEV) {
+- ata_link_printk(link, KERN_WARNING, "device not ready "
+- "(errno=%d), forcing hardreset\n", rc);
+- ehc->i.action |= ATA_EH_HARDRESET;
+- }
+- }
++ /* no point in trying softreset on offline link */
++ if (ata_link_offline(link))
++ ehc->i.action &= ~ATA_EH_SOFTRESET;
+
+ return 0;
+ }
+
+ /**
+- * ata_std_softreset - reset host port via ATA SRST
+- * @link: ATA link to reset
+- * @classes: resulting classes of attached devices
+- * @deadline: deadline jiffies for the operation
+- *
+- * Reset host port using ATA SRST.
+- *
+- * LOCKING:
+- * Kernel thread context (may sleep)
+- *
+- * RETURNS:
+- * 0 on success, -errno otherwise.
+- */
+-int ata_std_softreset(struct ata_link *link, unsigned int *classes,
+- unsigned long deadline)
+-{
+- struct ata_port *ap = link->ap;
+- unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
+- unsigned int devmask = 0;
+- int rc;
+- u8 err;
+-
+- DPRINTK("ENTER\n");
+-
+- if (ata_link_offline(link)) {
+- classes[0] = ATA_DEV_NONE;
+- goto out;
+- }
+-
+- /* determine if device 0/1 are present */
+- if (ata_devchk(ap, 0))
+- devmask |= (1 << 0);
+- if (slave_possible && ata_devchk(ap, 1))
+- devmask |= (1 << 1);
+-
+- /* select device 0 again */
+- ap->ops->dev_select(ap, 0);
+-
+- /* issue bus reset */
+- DPRINTK("about to softreset, devmask=%x\n", devmask);
+- rc = ata_bus_softreset(ap, devmask, deadline);
+- /* if link is occupied, -ENODEV too is an error */
+- if (rc && (rc != -ENODEV || sata_scr_valid(link))) {
+- ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc);
+- return rc;
+- }
+-
+- /* determine by signature whether we have ATA or ATAPI devices */
+- classes[0] = ata_dev_try_classify(&link->device[0],
+- devmask & (1 << 0), &err);
+- if (slave_possible && err != 0x81)
+- classes[1] = ata_dev_try_classify(&link->device[1],
+- devmask & (1 << 1), &err);
+-
+- out:
+- DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
+- return 0;
+-}
+-
+-/**
+ * sata_link_hardreset - reset link via SATA phy reset
+ * @link: link to reset
+ * @timing: timing parameters { interval, duratinon, timeout } in msec
+ * @deadline: deadline jiffies for the operation
++ * @online: optional out parameter indicating link onlineness
++ * @check_ready: optional callback to check link readiness
+ *
+ * SATA phy-reset @link using DET bits of SControl register.
++ * After hardreset, link readiness is waited upon using
++ * ata_wait_ready() if @check_ready is specified. LLDs are
++ * allowed to not specify @check_ready and wait itself after this
++ * function returns. Device classification is LLD's
++ * responsibility.
++ *
++ * *@online is set to one iff reset succeeded and @link is online
++ * after reset.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+@@ -4063,13 +3577,17 @@ int ata_std_softreset(struct ata_link *link, unsigned int *classes,
+ * 0 on success, -errno otherwise.
+ */
+ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
+- unsigned long deadline)
++ unsigned long deadline,
++ bool *online, int (*check_ready)(struct ata_link *))
+ {
+ u32 scontrol;
+ int rc;
+
+ DPRINTK("ENTER\n");
+
++ if (online)
++ *online = false;
++
+ if (sata_set_spd_needed(link)) {
+ /* SATA spec says nothing about how to reconfigure
+ * spd. To be on the safe side, turn off phy during
+@@ -4103,77 +3621,69 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
+
+ /* bring link back */
+ rc = sata_link_resume(link, timing, deadline);
++ if (rc)
++ goto out;
++ /* if link is offline nothing more to do */
++ if (ata_link_offline(link))
++ goto out;
++
++ /* Link is online. From this point, -ENODEV too is an error. */
++ if (online)
++ *online = true;
++
++ if (sata_pmp_supported(link->ap) && ata_is_host_link(link)) {
++ /* If PMP is supported, we have to do follow-up SRST.
++ * Some PMPs don't send D2H Reg FIS after hardreset if
++ * the first port is empty. Wait only for
++ * ATA_TMOUT_PMP_SRST_WAIT.
++ */
++ if (check_ready) {
++ unsigned long pmp_deadline;
++
++ pmp_deadline = jiffies + ATA_TMOUT_PMP_SRST_WAIT;
++ if (time_after(pmp_deadline, deadline))
++ pmp_deadline = deadline;
++ ata_wait_ready(link, pmp_deadline, check_ready);
++ }
++ rc = -EAGAIN;
++ goto out;
++ }
++
++ rc = 0;
++ if (check_ready)
++ rc = ata_wait_ready(link, deadline, check_ready);
+ out:
++ if (rc && rc != -EAGAIN)
++ ata_link_printk(link, KERN_ERR,
++ "COMRESET failed (errno=%d)\n", rc);
+ DPRINTK("EXIT, rc=%d\n", rc);
+ return rc;
+ }
+
+ /**
+- * sata_std_hardreset - reset host port via SATA phy reset
++ * sata_std_hardreset - COMRESET w/o waiting or classification
+ * @link: link to reset
+ * @class: resulting class of attached device
+ * @deadline: deadline jiffies for the operation
+ *
+- * SATA phy-reset host port using DET bits of SControl register,
+- * wait for !BSY and classify the attached device.
++ * Standard SATA COMRESET w/o waiting or classification.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+ *
+ * RETURNS:
+- * 0 on success, -errno otherwise.
++ * 0 if link offline, -EAGAIN if link online, -errno on errors.
+ */
+ int sata_std_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+ {
+- struct ata_port *ap = link->ap;
+ const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
++ bool online;
+ int rc;
+
+- DPRINTK("ENTER\n");
+-
+ /* do hardreset */
+- rc = sata_link_hardreset(link, timing, deadline);
+- if (rc) {
+- ata_link_printk(link, KERN_ERR,
+- "COMRESET failed (errno=%d)\n", rc);
+- return rc;
+- }
+-
+- /* TODO: phy layer with polling, timeouts, etc. */
+- if (ata_link_offline(link)) {
+- *class = ATA_DEV_NONE;
+- DPRINTK("EXIT, link offline\n");
+- return 0;
+- }
+-
+- /* wait a while before checking status */
+- ata_wait_after_reset(ap, deadline);
+-
+- /* If PMP is supported, we have to do follow-up SRST. Note
+- * that some PMPs don't send D2H Reg FIS after hardreset at
+- * all if the first port is empty. Wait for it just for a
+- * second and request follow-up SRST.
+- */
+- if (ap->flags & ATA_FLAG_PMP) {
+- ata_wait_ready(ap, jiffies + HZ);
+- return -EAGAIN;
+- }
+-
+- rc = ata_wait_ready(ap, deadline);
+- /* link occupied, -ENODEV too is an error */
+- if (rc) {
+- ata_link_printk(link, KERN_ERR,
+- "COMRESET failed (errno=%d)\n", rc);
+- return rc;
+- }
+-
+- ap->ops->dev_select(ap, 0); /* probably unnecessary */
+-
+- *class = ata_dev_try_classify(link->device, 1, NULL);
+-
+- DPRINTK("EXIT, class=%u\n", *class);
+- return 0;
++ rc = sata_link_hardreset(link, timing, deadline, &online, NULL);
++ return online ? -EAGAIN : rc;
+ }
+
+ /**
+@@ -4190,35 +3700,11 @@ int sata_std_hardreset(struct ata_link *link, unsigned int *class,
+ */
+ void ata_std_postreset(struct ata_link *link, unsigned int *classes)
+ {
+- struct ata_port *ap = link->ap;
+- u32 serror;
+-
+ DPRINTK("ENTER\n");
+
+ /* print link status */
+ sata_print_link_status(link);
+
+- /* clear SError */
+- if (sata_scr_read(link, SCR_ERROR, &serror) == 0)
+- sata_scr_write(link, SCR_ERROR, serror);
+- link->eh_info.serror = 0;
+-
+- /* is double-select really necessary? */
+- if (classes[0] != ATA_DEV_NONE)
+- ap->ops->dev_select(ap, 1);
+- if (classes[1] != ATA_DEV_NONE)
+- ap->ops->dev_select(ap, 0);
+-
+- /* bail out if no device is present */
+- if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
+- DPRINTK("EXIT, no device\n");
+- return;
+- }
+-
+- /* set up device control */
+- if (ap->ioaddr.ctl_addr)
+- iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
+-
+ DPRINTK("EXIT\n");
+ }
+
+@@ -4447,6 +3933,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
+
+ /* Devices which get the IVB wrong */
+ { "QUANTUM FIREBALLlct10 05", "A03.0900", ATA_HORKAGE_IVB, },
++ /* Maybe we should just blacklist TSSTcorp... */
++ { "TSSTcorp CDDVDW SH-S202H", "SB00", ATA_HORKAGE_IVB, },
++ { "TSSTcorp CDDVDW SH-S202H", "SB01", ATA_HORKAGE_IVB, },
+ { "TSSTcorp CDDVDW SH-S202J", "SB00", ATA_HORKAGE_IVB, },
+ { "TSSTcorp CDDVDW SH-S202J", "SB01", ATA_HORKAGE_IVB, },
+ { "TSSTcorp CDDVDW SH-S202N", "SB00", ATA_HORKAGE_IVB, },
+@@ -4528,6 +4017,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 +4131,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 +4292,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 +4351,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 +4429,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 +4551,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 +4661,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 +4673,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 +4694,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 +4752,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 +4774,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 +4931,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 +5026,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 +5201,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 +5353,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 +5377,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 +5451,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 +5519,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 +5615,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 +5781,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 +6167,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 +6196,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 +6209,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 +6221,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 +6240,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 +6267,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 +6274,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 +6293,7 @@ EXPORT_SYMBOL_GPL(ata_eh_thaw_port);
+ EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
+ EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
+ EXPORT_SYMBOL_GPL(ata_do_eh);
+-EXPORT_SYMBOL_GPL(ata_irq_on);
+-EXPORT_SYMBOL_GPL(ata_dev_try_classify);
++EXPORT_SYMBOL_GPL(ata_std_error_handler);
+
+ EXPORT_SYMBOL_GPL(ata_cable_40wire);
+ EXPORT_SYMBOL_GPL(ata_cable_80wire);
+diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
+index a583032..61dcd00 100644
+--- a/drivers/ata/libata-eh.c
++++ b/drivers/ata/libata-eh.c
+@@ -873,9 +873,9 @@ int sata_async_notification(struct ata_port *ap)
+ if (rc == 0)
+ sata_scr_write(&ap->link, SCR_NOTIFICATION, sntf);
+
+- if (!ap->nr_pmp_links || rc) {
++ if (!sata_pmp_attached(ap) || rc) {
+ /* PMP is not attached or SNTF is not available */
+- if (!ap->nr_pmp_links) {
++ if (!sata_pmp_attached(ap)) {
+ /* PMP is not attached. Check whether ATAPI
+ * AN is configured. If so, notify media
+ * change.
+@@ -1079,19 +1079,6 @@ void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev,
+
+ spin_lock_irqsave(ap->lock, flags);
+
+- /* Reset is represented by combination of actions and EHI
+- * flags. Suck in all related bits before clearing eh_info to
+- * avoid losing requested action.
+- */
+- if (action & ATA_EH_RESET_MASK) {
+- ehc->i.action |= ehi->action & ATA_EH_RESET_MASK;
+- ehc->i.flags |= ehi->flags & ATA_EHI_RESET_MODIFIER_MASK;
+-
+- /* make sure all reset actions are cleared & clear EHI flags */
+- action |= ATA_EH_RESET_MASK;
+- ehi->flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
+- }
+-
+ ata_eh_clear_action(link, dev, ehi, action);
+
+ if (!(ehc->i.flags & ATA_EHI_QUIET))
+@@ -1117,12 +1104,6 @@ void ata_eh_done(struct ata_link *link, struct ata_device *dev,
+ {
+ struct ata_eh_context *ehc = &link->eh_context;
+
+- /* if reset is complete, clear all reset actions & reset modifier */
+- if (action & ATA_EH_RESET_MASK) {
+- action |= ATA_EH_RESET_MASK;
+- ehc->i.flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
+- }
+-
+ ata_eh_clear_action(link, dev, &ehc->i, action);
+ }
+
+@@ -1329,20 +1310,20 @@ static void ata_eh_analyze_serror(struct ata_link *link)
+
+ if (serror & SERR_PERSISTENT) {
+ err_mask |= AC_ERR_ATA_BUS;
+- action |= ATA_EH_HARDRESET;
++ action |= ATA_EH_RESET;
+ }
+ if (serror &
+ (SERR_DATA_RECOVERED | SERR_COMM_RECOVERED | SERR_DATA)) {
+ err_mask |= AC_ERR_ATA_BUS;
+- action |= ATA_EH_SOFTRESET;
++ action |= ATA_EH_RESET;
+ }
+ if (serror & SERR_PROTOCOL) {
+ err_mask |= AC_ERR_HSM;
+- action |= ATA_EH_SOFTRESET;
++ action |= ATA_EH_RESET;
+ }
+ if (serror & SERR_INTERNAL) {
+ err_mask |= AC_ERR_SYSTEM;
+- action |= ATA_EH_HARDRESET;
++ action |= ATA_EH_RESET;
+ }
+
+ /* Determine whether a hotplug event has occurred. Both
+@@ -1421,6 +1402,7 @@ static void ata_eh_analyze_ncq_error(struct ata_link *link)
+ /* we've got the perpetrator, condemn it */
+ qc = __ata_qc_from_tag(ap, tag);
+ memcpy(&qc->result_tf, &tf, sizeof(tf));
++ qc->result_tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
+ qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ;
+ ehc->i.err_mask &= ~AC_ERR_DEV;
+ }
+@@ -1448,7 +1430,7 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
+
+ if ((stat & (ATA_BUSY | ATA_DRQ | ATA_DRDY)) != ATA_DRDY) {
+ qc->err_mask |= AC_ERR_HSM;
+- return ATA_EH_SOFTRESET;
++ return ATA_EH_RESET;
+ }
+
+ if (stat & (ATA_ERR | ATA_DF))
+@@ -1484,7 +1466,7 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
+ }
+
+ if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS))
+- action |= ATA_EH_SOFTRESET;
++ action |= ATA_EH_RESET;
+
+ return action;
+ }
+@@ -1685,7 +1667,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
+ if (verdict & ATA_EH_SPDN_SPEED_DOWN) {
+ /* speed down SATA link speed if possible */
+ if (sata_down_spd_limit(link) == 0) {
+- action |= ATA_EH_HARDRESET;
++ action |= ATA_EH_RESET;
+ goto done;
+ }
+
+@@ -1705,7 +1687,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
+ dev->spdn_cnt++;
+
+ if (ata_down_xfermask_limit(dev, sel) == 0) {
+- action |= ATA_EH_SOFTRESET;
++ action |= ATA_EH_RESET;
+ goto done;
+ }
+ }
+@@ -1719,7 +1701,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
+ (dev->xfer_shift != ATA_SHIFT_PIO)) {
+ if (ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO) == 0) {
+ dev->spdn_cnt = 0;
+- action |= ATA_EH_SOFTRESET;
++ action |= ATA_EH_RESET;
+ goto done;
+ }
+ }
+@@ -1764,9 +1746,9 @@ static void ata_eh_link_autopsy(struct ata_link *link)
+ ehc->i.serror |= serror;
+ ata_eh_analyze_serror(link);
+ } else if (rc != -EOPNOTSUPP) {
+- /* SError read failed, force hardreset and probing */
+- ata_ehi_schedule_probe(&ehc->i);
+- ehc->i.action |= ATA_EH_HARDRESET;
++ /* SError read failed, force reset and probing */
++ ehc->i.probe_mask |= ATA_ALL_DEVICES;
++ ehc->i.action |= ATA_EH_RESET;
+ ehc->i.err_mask |= AC_ERR_OTHER;
+ }
+
+@@ -1804,6 +1786,11 @@ static void ata_eh_link_autopsy(struct ata_link *link)
+ if (qc->flags & ATA_QCFLAG_SENSE_VALID)
+ qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
+
++ /* determine whether the command is worth retrying */
++ if (!(qc->err_mask & AC_ERR_INVALID) &&
++ ((qc->flags & ATA_QCFLAG_IO) || qc->err_mask != AC_ERR_DEV))
++ qc->flags |= ATA_QCFLAG_RETRY;
++
+ /* accumulate error info */
+ ehc->i.dev = qc->dev;
+ all_err_mask |= qc->err_mask;
+@@ -1814,7 +1801,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
+ /* enforce default EH actions */
+ if (ap->pflags & ATA_PFLAG_FROZEN ||
+ all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
+- ehc->i.action |= ATA_EH_SOFTRESET;
++ ehc->i.action |= ATA_EH_RESET;
+ else if (((eflags & ATA_EFLAG_IS_IO) && all_err_mask) ||
+ (!(eflags & ATA_EFLAG_IS_IO) && (all_err_mask & ~AC_ERR_DEV)))
+ ehc->i.action |= ATA_EH_REVALIDATE;
+@@ -1867,7 +1854,7 @@ void ata_eh_autopsy(struct ata_port *ap)
+ /* Autopsy of fanout ports can affect host link autopsy.
+ * Perform host link autopsy last.
+ */
+- if (ap->nr_pmp_links)
++ if (sata_pmp_attached(ap))
+ ata_eh_link_autopsy(&ap->link);
+ }
+
+@@ -2066,41 +2053,29 @@ static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset,
+ classes[dev->devno] = ATA_DEV_UNKNOWN;
+
+ rc = reset(link, classes, deadline);
+- if (rc)
+- return rc;
+
+- /* If any class isn't ATA_DEV_UNKNOWN, consider classification
+- * is complete and convert all ATA_DEV_UNKNOWN to
+- * ATA_DEV_NONE.
+- */
++ /* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */
+ ata_link_for_each_dev(dev, link)
+- if (classes[dev->devno] != ATA_DEV_UNKNOWN)
+- break;
+-
+- if (dev) {
+- ata_link_for_each_dev(dev, link) {
+- if (classes[dev->devno] == ATA_DEV_UNKNOWN)
+- classes[dev->devno] = ATA_DEV_NONE;
+- }
+- }
++ if (classes[dev->devno] == ATA_DEV_UNKNOWN)
++ classes[dev->devno] = ATA_DEV_NONE;
+
+- return 0;
++ return rc;
+ }
+
+ static int ata_eh_followup_srst_needed(struct ata_link *link,
+ int rc, int classify,
+ const unsigned int *classes)
+ {
+- if (link->flags & ATA_LFLAG_NO_SRST)
++ if ((link->flags & ATA_LFLAG_NO_SRST) || ata_link_offline(link))
+ return 0;
+- if (rc == -EAGAIN)
+- return 1;
++ if (rc == -EAGAIN) {
++ if (classify)
++ return 1;
++ rc = 0;
++ }
+ if (rc != 0)
+ return 0;
+- if ((link->ap->flags & ATA_FLAG_PMP) && ata_is_host_link(link))
+- return 1;
+- if (classify && !(link->flags & ATA_LFLAG_ASSUME_CLASS) &&
+- classes[0] == ATA_DEV_UNKNOWN)
++ if (sata_pmp_supported(link->ap) && ata_is_host_link(link))
+ return 1;
+ return 0;
+ }
+@@ -2118,7 +2093,6 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ int try = 0;
+ struct ata_device *dev;
+ unsigned long deadline, now;
+- unsigned int tmp_action;
+ ata_reset_fn_t reset;
+ unsigned long flags;
+ u32 sstatus;
+@@ -2129,7 +2103,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ ap->pflags |= ATA_PFLAG_RESETTING;
+ spin_unlock_irqrestore(ap->lock, flags);
+
+- ata_eh_about_to_do(link, NULL, ehc->i.action & ATA_EH_RESET_MASK);
++ ata_eh_about_to_do(link, NULL, ATA_EH_RESET);
+
+ ata_link_for_each_dev(dev, link) {
+ /* If we issue an SRST then an ATA drive (not ATAPI)
+@@ -2159,17 +2133,20 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ goto done;
+ }
+
+- /* Determine which reset to use and record in ehc->i.action.
+- * prereset() may examine and modify it.
+- */
+- if (softreset && (!hardreset || (!(lflags & ATA_LFLAG_NO_SRST) &&
+- !sata_set_spd_needed(link) &&
+- !(ehc->i.action & ATA_EH_HARDRESET))))
+- tmp_action = ATA_EH_SOFTRESET;
+- else
+- tmp_action = ATA_EH_HARDRESET;
+-
+- ehc->i.action = (ehc->i.action & ~ATA_EH_RESET_MASK) | tmp_action;
++ /* prefer hardreset */
++ ehc->i.action &= ~ATA_EH_RESET;
++ if (hardreset) {
++ reset = hardreset;
++ ehc->i.action = ATA_EH_HARDRESET;
++ } else if (softreset) {
++ reset = softreset;
++ ehc->i.action = ATA_EH_SOFTRESET;
++ } else {
++ ata_link_printk(link, KERN_ERR, "BUG: no reset method, "
++ "please report to linux-ide at vger.kernel.org\n");
++ dump_stack();
++ return -EINVAL;
++ }
+
+ if (prereset) {
+ rc = prereset(link, jiffies + ATA_EH_PRERESET_TIMEOUT);
+@@ -2177,7 +2154,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ if (rc == -ENOENT) {
+ ata_link_printk(link, KERN_DEBUG,
+ "port disabled. ignoring.\n");
+- ehc->i.action &= ~ATA_EH_RESET_MASK;
++ ehc->i.action &= ~ATA_EH_RESET;
+
+ ata_link_for_each_dev(dev, link)
+ classes[dev->devno] = ATA_DEV_NONE;
+@@ -2190,12 +2167,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ }
+ }
+
+- /* prereset() might have modified ehc->i.action */
+- if (ehc->i.action & ATA_EH_HARDRESET)
+- reset = hardreset;
+- else if (ehc->i.action & ATA_EH_SOFTRESET)
+- reset = softreset;
+- else {
++ /* prereset() might have cleared ATA_EH_RESET */
++ if (!(ehc->i.action & ATA_EH_RESET)) {
+ /* prereset told us not to reset, bang classes and return */
+ ata_link_for_each_dev(dev, link)
+ classes[dev->devno] = ATA_DEV_NONE;
+@@ -2203,14 +2176,6 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ goto out;
+ }
+
+- /* did prereset() screw up? if so, fix up to avoid oopsing */
+- if (!reset) {
+- if (softreset)
+- reset = softreset;
+- else
+- reset = hardreset;
+- }
+-
+ retry:
+ deadline = jiffies + ata_eh_reset_timeouts[try++];
+
+@@ -2240,7 +2205,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ goto fail;
+ }
+
+- ata_eh_about_to_do(link, NULL, ATA_EH_RESET_MASK);
++ ata_eh_about_to_do(link, NULL, ATA_EH_RESET);
+ rc = ata_do_reset(link, reset, classes, deadline);
+ }
+
+@@ -2248,21 +2213,6 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ if (rc && rc != -EAGAIN)
+ goto fail;
+
+- /* was classification successful? */
+- if (classify && classes[0] == ATA_DEV_UNKNOWN &&
+- !(lflags & ATA_LFLAG_ASSUME_CLASS)) {
+- if (try < max_tries) {
+- ata_link_printk(link, KERN_WARNING,
+- "classification failed\n");
+- rc = -EINVAL;
+- goto fail;
+- }
+-
+- ata_link_printk(link, KERN_WARNING,
+- "classfication failed, assuming ATA\n");
+- lflags |= ATA_LFLAG_ASSUME_ATA;
+- }
+-
+ done:
+ ata_link_for_each_dev(dev, link) {
+ /* After the reset, the device state is PIO 0 and the
+@@ -2290,7 +2240,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ postreset(link, classes);
+
+ /* reset successful, schedule revalidation */
+- ata_eh_done(link, NULL, ehc->i.action & ATA_EH_RESET_MASK);
++ ata_eh_done(link, NULL, ATA_EH_RESET);
+ ehc->i.action |= ATA_EH_REVALIDATE;
+
+ rc = 0;
+@@ -2305,6 +2255,11 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ return rc;
+
+ fail:
++ /* if SCR isn't accessible on a fan-out port, PMP needs to be reset */
++ if (!ata_is_host_link(link) &&
++ sata_scr_read(link, SCR_STATUS, &sstatus))
++ rc = -ERESTART;
++
+ if (rc == -ERESTART || try >= max_tries)
+ goto out;
+
+@@ -2515,6 +2470,7 @@ static int ata_link_nr_vacant(struct ata_link *link)
+
+ static int ata_eh_skip_recovery(struct ata_link *link)
+ {
++ struct ata_port *ap = link->ap;
+ struct ata_eh_context *ehc = &link->eh_context;
+ struct ata_device *dev;
+
+@@ -2522,9 +2478,13 @@ static int ata_eh_skip_recovery(struct ata_link *link)
+ if (link->flags & ATA_LFLAG_DISABLED)
+ return 1;
+
+- /* thaw frozen port, resume link and recover failed devices */
+- if ((link->ap->pflags & ATA_PFLAG_FROZEN) ||
+- (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_link_nr_enabled(link))
++ /* thaw frozen port and recover failed devices */
++ if ((ap->pflags & ATA_PFLAG_FROZEN) || ata_link_nr_enabled(link))
++ return 0;
++
++ /* reset at least once if reset is requested */
++ if ((ehc->i.action & ATA_EH_RESET) &&
++ !(ehc->i.flags & ATA_EHI_DID_RESET))
+ return 0;
+
+ /* skip if class codes for all vacant slots are ATA_DEV_NONE */
+@@ -2548,7 +2508,7 @@ static int ata_eh_schedule_probe(struct ata_device *dev)
+ ata_eh_detach_dev(dev);
+ ata_dev_init(dev);
+ ehc->did_probe_mask |= (1 << dev->devno);
+- ehc->i.action |= ATA_EH_SOFTRESET;
++ ehc->i.action |= ATA_EH_RESET;
+ ehc->saved_xfer_mode[dev->devno] = 0;
+ ehc->saved_ncq_enabled &= ~(1 << dev->devno);
+
+@@ -2592,12 +2552,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
+
+ return 1;
+ } else {
+- /* soft didn't work? be haaaaard */
+- if (ehc->i.flags & ATA_EHI_DID_RESET)
+- ehc->i.action |= ATA_EH_HARDRESET;
+- else
+- ehc->i.action |= ATA_EH_SOFTRESET;
+-
++ ehc->i.action |= ATA_EH_RESET;
+ return 0;
+ }
+ }
+@@ -2690,7 +2645,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+ ehc->i.action = 0;
+
+ /* do we need to reset? */
+- if (ehc->i.action & ATA_EH_RESET_MASK)
++ if (ehc->i.action & ATA_EH_RESET)
+ reset = 1;
+
+ ata_link_for_each_dev(dev, link)
+@@ -2702,13 +2657,13 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+ /* if PMP is attached, this function only deals with
+ * downstream links, port should stay thawed.
+ */
+- if (!ap->nr_pmp_links)
++ if (!sata_pmp_attached(ap))
+ ata_eh_freeze_port(ap);
+
+ ata_port_for_each_link(link, ap) {
+ struct ata_eh_context *ehc = &link->eh_context;
+
+- if (!(ehc->i.action & ATA_EH_RESET_MASK))
++ if (!(ehc->i.action & ATA_EH_RESET))
+ continue;
+
+ rc = ata_eh_reset(link, ata_link_nr_vacant(link),
+@@ -2721,7 +2676,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+ }
+ }
+
+- if (!ap->nr_pmp_links)
++ if (!sata_pmp_attached(ap))
+ ata_eh_thaw_port(ap);
+ }
+
+@@ -2765,7 +2720,7 @@ dev_fail:
+ /* PMP reset requires working host port.
+ * Can't retry if it's frozen.
+ */
+- if (ap->nr_pmp_links)
++ if (sata_pmp_attached(ap))
+ goto out;
+ break;
+ }
+@@ -2817,18 +2772,11 @@ void ata_eh_finish(struct ata_port *ap)
+ /* FIXME: Once EH migration is complete,
+ * generate sense data in this function,
+ * considering both err_mask and tf.
+- *
+- * There's no point in retrying invalid
+- * (detected by libata) and non-IO device
+- * errors (rejected by device). Finish them
+- * immediately.
+ */
+- if ((qc->err_mask & AC_ERR_INVALID) ||
+- (!(qc->flags & ATA_QCFLAG_IO) &&
+- qc->err_mask == AC_ERR_DEV))
+- ata_eh_qc_complete(qc);
+- else
++ if (qc->flags & ATA_QCFLAG_RETRY)
+ ata_eh_qc_retry(qc);
++ else
++ ata_eh_qc_complete(qc);
+ } else {
+ if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
+ ata_eh_qc_complete(qc);
+@@ -2848,6 +2796,7 @@ void ata_eh_finish(struct ata_port *ap)
+ /**
+ * ata_do_eh - do standard error handling
+ * @ap: host port to handle error for
++ *
+ * @prereset: prereset method (can be NULL)
+ * @softreset: softreset method (can be NULL)
+ * @hardreset: hardreset method (can be NULL)
+@@ -2878,6 +2827,27 @@ void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+ ata_eh_finish(ap);
+ }
+
++/**
++ * ata_std_error_handler - standard error handler
++ * @ap: host port to handle error for
++ *
++ * Standard error handler
++ *
++ * LOCKING:
++ * Kernel thread context (may sleep).
++ */
++void ata_std_error_handler(struct ata_port *ap)
++{
++ struct ata_port_operations *ops = ap->ops;
++ ata_reset_fn_t hardreset = ops->hardreset;
++
++ /* ignore built-in hardreset if SCR access is not available */
++ if (ata_is_builtin_hardreset(hardreset) && !sata_scr_valid(&ap->link))
++ hardreset = NULL;
++
++ ata_do_eh(ap, ops->prereset, ops->softreset, hardreset, ops->postreset);
++}
++
+ #ifdef CONFIG_PM
+ /**
+ * ata_eh_handle_port_suspend - perform port suspend operation
+diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
+index d91f509..ff1822a 100644
+--- a/drivers/ata/libata-pmp.c
++++ b/drivers/ata/libata-pmp.c
+@@ -11,6 +11,14 @@
+ #include <linux/libata.h>
+ #include "libata.h"
+
++const struct ata_port_operations sata_pmp_port_ops = {
++ .inherits = &sata_port_ops,
++ .pmp_prereset = ata_std_prereset,
++ .pmp_hardreset = sata_std_hardreset,
++ .pmp_postreset = ata_std_postreset,
++ .error_handler = sata_pmp_error_handler,
++};
++
+ /**
+ * sata_pmp_read - read PMP register
+ * @link: link to read PMP register for
+@@ -176,140 +184,6 @@ int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val)
+ }
+
+ /**
+- * sata_pmp_std_prereset - prepare PMP link for reset
+- * @link: link to be reset
+- * @deadline: deadline jiffies for the operation
+- *
+- * @link is about to be reset. Initialize it.
+- *
+- * LOCKING:
+- * Kernel thread context (may sleep)
+- *
+- * RETURNS:
+- * 0 on success, -errno otherwise.
+- */
+-int sata_pmp_std_prereset(struct ata_link *link, unsigned long deadline)
+-{
+- struct ata_eh_context *ehc = &link->eh_context;
+- const unsigned long *timing = sata_ehc_deb_timing(ehc);
+- int rc;
+-
+- /* force HRST? */
+- if (link->flags & ATA_LFLAG_NO_SRST)
+- ehc->i.action |= ATA_EH_HARDRESET;
+-
+- /* handle link resume */
+- if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
+- (link->flags & ATA_LFLAG_HRST_TO_RESUME))
+- ehc->i.action |= ATA_EH_HARDRESET;
+-
+- /* if we're about to do hardreset, nothing more to do */
+- if (ehc->i.action & ATA_EH_HARDRESET)
+- return 0;
+-
+- /* resume link */
+- rc = sata_link_resume(link, timing, deadline);
+- if (rc) {
+- /* phy resume failed */
+- ata_link_printk(link, KERN_WARNING, "failed to resume link "
+- "for reset (errno=%d)\n", rc);
+- return rc;
+- }
+-
+- /* clear SError bits including .X which blocks the port when set */
+- rc = sata_scr_write(link, SCR_ERROR, 0xffffffff);
+- if (rc) {
+- ata_link_printk(link, KERN_ERR,
+- "failed to clear SError (errno=%d)\n", rc);
+- return rc;
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * sata_pmp_std_hardreset - standard hardreset method for PMP link
+- * @link: link to be reset
+- * @class: resulting class of attached device
+- * @deadline: deadline jiffies for the operation
+- *
+- * Hardreset PMP port @link. Note that this function doesn't
+- * wait for BSY clearance. There simply isn't a generic way to
+- * wait the event. Instead, this function return -EAGAIN thus
+- * telling libata-EH to followup with softreset.
+- *
+- * LOCKING:
+- * Kernel thread context (may sleep)
+- *
+- * RETURNS:
+- * 0 on success, -errno otherwise.
+- */
+-int sata_pmp_std_hardreset(struct ata_link *link, unsigned int *class,
+- unsigned long deadline)
+-{
+- const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
+- u32 tmp;
+- int rc;
+-
+- DPRINTK("ENTER\n");
+-
+- /* do hardreset */
+- rc = sata_link_hardreset(link, timing, deadline);
+- if (rc) {
+- ata_link_printk(link, KERN_ERR,
+- "COMRESET failed (errno=%d)\n", rc);
+- goto out;
+- }
+-
+- /* clear SError bits including .X which blocks the port when set */
+- rc = sata_scr_write(link, SCR_ERROR, 0xffffffff);
+- if (rc) {
+- ata_link_printk(link, KERN_ERR, "failed to clear SError "
+- "during hardreset (errno=%d)\n", rc);
+- goto out;
+- }
+-
+- /* if device is present, follow up with srst to wait for !BSY */
+- if (ata_link_online(link))
+- rc = -EAGAIN;
+- out:
+- /* if SCR isn't accessible, we need to reset the PMP */
+- if (rc && rc != -EAGAIN && sata_scr_read(link, SCR_STATUS, &tmp))
+- rc = -ERESTART;
+-
+- DPRINTK("EXIT, rc=%d\n", rc);
+- return rc;
+-}
+-
+-/**
+- * ata_std_postreset - standard postreset method for PMP link
+- * @link: the target ata_link
+- * @classes: classes of attached devices
+- *
+- * This function is invoked after a successful reset. Note that
+- * the device might have been reset more than once using
+- * different reset methods before postreset is invoked.
+- *
+- * LOCKING:
+- * Kernel thread context (may sleep)
+- */
+-void sata_pmp_std_postreset(struct ata_link *link, unsigned int *class)
+-{
+- u32 serror;
+-
+- DPRINTK("ENTER\n");
+-
+- /* clear SError */
+- if (sata_scr_read(link, SCR_ERROR, &serror) == 0)
+- sata_scr_write(link, SCR_ERROR, serror);
+-
+- /* print link status */
+- sata_print_link_status(link);
+-
+- DPRINTK("EXIT\n");
+-}
+-
+-/**
+ * sata_pmp_read_gscr - read GSCR block of SATA PMP
+ * @dev: PMP device
+ * @gscr: buffer to read GSCR block into
+@@ -444,9 +318,8 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
+ struct ata_eh_context *ehc = &link->eh_context;
+
+ link->flags = 0;
+- ehc->i.probe_mask |= 1;
+- ehc->i.action |= ATA_EH_SOFTRESET;
+- ehc->i.flags |= ATA_EHI_RESUME_LINK;
++ ehc->i.probe_mask |= ATA_ALL_DEVICES;
++ ehc->i.action |= ATA_EH_RESET;
+ }
+
+ return 0;
+@@ -462,9 +335,6 @@ static void sata_pmp_quirks(struct ata_port *ap)
+ if (vendor == 0x1095 && devid == 0x3726) {
+ /* sil3726 quirks */
+ ata_port_for_each_link(link, ap) {
+- /* SError.N need a kick in the ass to get working */
+- link->flags |= ATA_LFLAG_HRST_TO_RESUME;
+-
+ /* class code report is unreliable */
+ if (link->pmp < 5)
+ link->flags |= ATA_LFLAG_ASSUME_ATA;
+@@ -477,9 +347,6 @@ static void sata_pmp_quirks(struct ata_port *ap)
+ } else if (vendor == 0x1095 && devid == 0x4723) {
+ /* sil4723 quirks */
+ ata_port_for_each_link(link, ap) {
+- /* SError.N need a kick in the ass to get working */
+- link->flags |= ATA_LFLAG_HRST_TO_RESUME;
+-
+ /* class code report is unreliable */
+ if (link->pmp < 2)
+ link->flags |= ATA_LFLAG_ASSUME_ATA;
+@@ -492,9 +359,6 @@ static void sata_pmp_quirks(struct ata_port *ap)
+ } else if (vendor == 0x1095 && devid == 0x4726) {
+ /* sil4726 quirks */
+ ata_port_for_each_link(link, ap) {
+- /* SError.N need a kick in the ass to get working */
+- link->flags |= ATA_LFLAG_HRST_TO_RESUME;
+-
+ /* Class code report is unreliable and SRST
+ * times out under certain configurations.
+ * Config device can be at port 0 or 5 and
+@@ -522,13 +386,6 @@ static void sata_pmp_quirks(struct ata_port *ap)
+ * otherwise. Don't try hard to recover it.
+ */
+ ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY;
+- } else if (vendor == 0x11ab && devid == 0x4140) {
+- /* Marvell 88SM4140 quirks. Fan-out ports require PHY
+- * reset to work; other than that, it behaves very
+- * nicely.
+- */
+- ata_port_for_each_link(link, ap)
+- link->flags |= ATA_LFLAG_HRST_TO_RESUME;
+ }
+ }
+
+@@ -554,7 +411,7 @@ int sata_pmp_attach(struct ata_device *dev)
+ int rc;
+
+ /* is it hanging off the right place? */
+- if (!(ap->flags & ATA_FLAG_PMP)) {
++ if (!sata_pmp_supported(ap)) {
+ ata_dev_printk(dev, KERN_ERR,
+ "host does not support Port Multiplier\n");
+ return -EINVAL;
+@@ -840,13 +697,12 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
+ retry:
+ ehc->classes[0] = ATA_DEV_UNKNOWN;
+
+- if (ehc->i.action & ATA_EH_RESET_MASK) {
++ if (ehc->i.action & ATA_EH_RESET) {
+ struct ata_link *tlink;
+
+ ata_eh_freeze_port(ap);
+
+ /* reset */
+- ehc->i.action = ATA_EH_HARDRESET;
+ rc = ata_eh_reset(link, 0, prereset, softreset, hardreset,
+ postreset);
+ if (rc) {
+@@ -858,8 +714,12 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
+ ata_eh_thaw_port(ap);
+
+ /* PMP is reset, SErrors cannot be trusted, scan all */
+- ata_port_for_each_link(tlink, ap)
+- ata_ehi_schedule_probe(&tlink->eh_context.i);
++ ata_port_for_each_link(tlink, ap) {
++ struct ata_eh_context *ehc = &tlink->eh_context;
++
++ ehc->i.probe_mask |= ATA_ALL_DEVICES;
++ ehc->i.action |= ATA_EH_RESET;
++ }
+ }
+
+ /* If revalidation is requested, revalidate and reconfigure;
+@@ -874,7 +734,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
+ tries--;
+
+ if (rc == -ENODEV) {
+- ehc->i.probe_mask |= 1;
++ ehc->i.probe_mask |= ATA_ALL_DEVICES;
+ detach = 1;
+ /* give it just two more chances */
+ tries = min(tries, 2);
+@@ -890,11 +750,11 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
+ reval_failed = 1;
+
+ ata_dev_printk(dev, KERN_WARNING,
+- "retrying hardreset%s\n",
++ "retrying reset%s\n",
+ sleep ? " in 5 secs" : "");
+ if (sleep)
+ ssleep(5);
+- ehc->i.action |= ATA_EH_HARDRESET;
++ ehc->i.action |= ATA_EH_RESET;
+ goto retry;
+ } else {
+ ata_dev_printk(dev, KERN_ERR, "failed to recover PMP "
+@@ -938,10 +798,8 @@ static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap)
+ /* Some PMPs require hardreset sequence to get
+ * SError.N working.
+ */
+- if ((link->flags & ATA_LFLAG_HRST_TO_RESUME) &&
+- (link->eh_context.i.flags & ATA_EHI_RESUME_LINK))
+- sata_link_hardreset(link, sata_deb_timing_normal,
+- jiffies + ATA_TMOUT_INTERNAL_QUICK);
++ sata_link_hardreset(link, sata_deb_timing_normal,
++ jiffies + ATA_TMOUT_INTERNAL_QUICK, NULL, NULL);
+
+ /* unconditionally clear SError.N */
+ rc = sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG);
+@@ -987,14 +845,6 @@ static int sata_pmp_handle_link_fail(struct ata_link *link, int *link_tries)
+ /**
+ * sata_pmp_eh_recover - recover PMP-enabled port
+ * @ap: ATA port to recover
+- * @prereset: prereset method (can be NULL)
+- * @softreset: softreset method
+- * @hardreset: hardreset method
+- * @postreset: postreset method (can be NULL)
+- * @pmp_prereset: PMP prereset method (can be NULL)
+- * @pmp_softreset: PMP softreset method (can be NULL)
+- * @pmp_hardreset: PMP hardreset method (can be NULL)
+- * @pmp_postreset: PMP postreset method (can be NULL)
+ *
+ * Drive EH recovery operation for PMP enabled port @ap. This
+ * function recovers host and PMP ports with proper retrials and
+@@ -1007,12 +857,9 @@ static int sata_pmp_handle_link_fail(struct ata_link *link, int *link_tries)
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+-static int sata_pmp_eh_recover(struct ata_port *ap,
+- ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
+- ata_reset_fn_t hardreset, ata_postreset_fn_t postreset,
+- ata_prereset_fn_t pmp_prereset, ata_reset_fn_t pmp_softreset,
+- ata_reset_fn_t pmp_hardreset, ata_postreset_fn_t pmp_postreset)
++static int sata_pmp_eh_recover(struct ata_port *ap)
+ {
++ struct ata_port_operations *ops = ap->ops;
+ int pmp_tries, link_tries[SATA_PMP_MAX_PORTS];
+ struct ata_link *pmp_link = &ap->link;
+ struct ata_device *pmp_dev = pmp_link->device;
+@@ -1029,9 +876,9 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+
+ retry:
+ /* PMP attached? */
+- if (!ap->nr_pmp_links) {
+- rc = ata_eh_recover(ap, prereset, softreset, hardreset,
+- postreset, NULL);
++ if (!sata_pmp_attached(ap)) {
++ rc = ata_eh_recover(ap, ops->prereset, ops->softreset,
++ ops->hardreset, ops->postreset, NULL);
+ if (rc) {
+ ata_link_for_each_dev(dev, &ap->link)
+ ata_dev_disable(dev);
+@@ -1049,8 +896,8 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+ }
+
+ /* recover pmp */
+- rc = sata_pmp_eh_recover_pmp(ap, prereset, softreset, hardreset,
+- postreset);
++ rc = sata_pmp_eh_recover_pmp(ap, ops->prereset, ops->softreset,
++ ops->hardreset, ops->postreset);
+ if (rc)
+ goto pmp_fail;
+
+@@ -1060,8 +907,8 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+ goto pmp_fail;
+
+ /* recover links */
+- rc = ata_eh_recover(ap, pmp_prereset, pmp_softreset, pmp_hardreset,
+- pmp_postreset, &link);
++ rc = ata_eh_recover(ap, ops->pmp_prereset, ops->pmp_softreset,
++ ops->pmp_hardreset, ops->pmp_postreset, &link);
+ if (rc)
+ goto link_fail;
+
+@@ -1124,7 +971,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+
+ link_fail:
+ if (sata_pmp_handle_link_fail(link, link_tries)) {
+- pmp_ehc->i.action |= ATA_EH_HARDRESET;
++ pmp_ehc->i.action |= ATA_EH_RESET;
+ goto retry;
+ }
+
+@@ -1136,13 +983,13 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+ if (ap->pflags & ATA_PFLAG_UNLOADING)
+ return rc;
+
+- if (!ap->nr_pmp_links)
++ if (!sata_pmp_attached(ap))
+ goto retry;
+
+ if (--pmp_tries) {
+ ata_port_printk(ap, KERN_WARNING,
+ "failed to recover PMP, retrying in 5 secs\n");
+- pmp_ehc->i.action |= ATA_EH_HARDRESET;
++ pmp_ehc->i.action |= ATA_EH_RESET;
+ ssleep(5);
+ goto retry;
+ }
+@@ -1157,16 +1004,8 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+ }
+
+ /**
+- * sata_pmp_do_eh - do standard error handling for PMP-enabled host
++ * sata_pmp_error_handler - do standard error handling for PMP-enabled host
+ * @ap: host port to handle error for
+- * @prereset: prereset method (can be NULL)
+- * @softreset: softreset method
+- * @hardreset: hardreset method
+- * @postreset: postreset method (can be NULL)
+- * @pmp_prereset: PMP prereset method (can be NULL)
+- * @pmp_softreset: PMP softreset method (can be NULL)
+- * @pmp_hardreset: PMP hardreset method (can be NULL)
+- * @pmp_postreset: PMP postreset method (can be NULL)
+ *
+ * Perform standard error handling sequence for PMP-enabled host
+ * @ap.
+@@ -1174,16 +1013,14 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ */
+-void sata_pmp_do_eh(struct ata_port *ap,
+- ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
+- ata_reset_fn_t hardreset, ata_postreset_fn_t postreset,
+- ata_prereset_fn_t pmp_prereset, ata_reset_fn_t pmp_softreset,
+- ata_reset_fn_t pmp_hardreset, ata_postreset_fn_t pmp_postreset)
++void sata_pmp_error_handler(struct ata_port *ap)
+ {
+ ata_eh_autopsy(ap);
+ ata_eh_report(ap);
+- sata_pmp_eh_recover(ap, prereset, softreset, hardreset, postreset,
+- pmp_prereset, pmp_softreset, pmp_hardreset,
+- pmp_postreset);
++ sata_pmp_eh_recover(ap);
+ ata_eh_finish(ap);
+ }
++
++EXPORT_SYMBOL_GPL(sata_pmp_port_ops);
++EXPORT_SYMBOL_GPL(sata_pmp_qc_defer_cmd_switch);
++EXPORT_SYMBOL_GPL(sata_pmp_error_handler);
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index 1579539..3ce4392 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -49,7 +49,11 @@
+
+ #include "libata.h"
+
+-#define SECTOR_SIZE 512
++#define SECTOR_SIZE 512
++#define ATA_SCSI_RBUF_SIZE 4096
++
++static DEFINE_SPINLOCK(ata_scsi_rbuf_lock);
++static u8 ata_scsi_rbuf[ATA_SCSI_RBUF_SIZE];
+
+ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc);
+
+@@ -131,10 +135,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 +167,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 +179,16 @@ 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_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
++{
++ cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
++
++ scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
++}
+
+ static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
+ void (*done)(struct scsi_cmnd *))
+@@ -1631,53 +1643,48 @@ defer:
+
+ /**
+ * ata_scsi_rbuf_get - Map response buffer.
+- * @cmd: SCSI command containing buffer to be mapped.
+- * @buf_out: Pointer to mapped area.
++ * @flags: unsigned long variable to store irq enable status
++ * @copy_in: copy in from user buffer
+ *
+- * Maps buffer contained within SCSI command @cmd.
++ * Prepare buffer for simulated SCSI commands.
+ *
+ * LOCKING:
+- * spin_lock_irqsave(host lock)
++ * spin_lock_irqsave(ata_scsi_rbuf_lock) on success
+ *
+ * RETURNS:
+- * Length of response buffer.
++ * Pointer to response buffer.
+ */
+-
+-static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
++static void *ata_scsi_rbuf_get(struct scsi_cmnd *cmd, bool copy_in,
++ unsigned long *flags)
+ {
+- u8 *buf;
+- unsigned int buflen;
++ spin_lock_irqsave(&ata_scsi_rbuf_lock, *flags);
+
+- struct scatterlist *sg = scsi_sglist(cmd);
+-
+- if (sg) {
+- buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+- buflen = sg->length;
+- } else {
+- buf = NULL;
+- buflen = 0;
+- }
+-
+- *buf_out = buf;
+- return buflen;
++ memset(ata_scsi_rbuf, 0, ATA_SCSI_RBUF_SIZE);
++ if (copy_in)
++ sg_copy_to_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
++ ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE);
++ return ata_scsi_rbuf;
+ }
+
+ /**
+ * ata_scsi_rbuf_put - Unmap response buffer.
+ * @cmd: SCSI command containing buffer to be unmapped.
+- * @buf: buffer to unmap
++ * @copy_out: copy out result
++ * @flags: @flags passed to ata_scsi_rbuf_get()
+ *
+- * Unmaps response buffer contained within @cmd.
++ * Returns rbuf buffer. The result is copied to @cmd's buffer if
++ * @copy_back is true.
+ *
+ * LOCKING:
+- * spin_lock_irqsave(host lock)
++ * Unlocks ata_scsi_rbuf_lock.
+ */
+-
+-static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
++static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, bool copy_out,
++ unsigned long *flags)
+ {
+- struct scatterlist *sg = scsi_sglist(cmd);
+- if (sg)
+- kunmap_atomic(buf - sg->offset, KM_IRQ0);
++ if (copy_out)
++ sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
++ ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE);
++ spin_unlock_irqrestore(&ata_scsi_rbuf_lock, *flags);
+ }
+
+ /**
+@@ -1695,24 +1702,17 @@ static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+-
+-void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
+- unsigned int (*actor) (struct ata_scsi_args *args,
+- u8 *rbuf, unsigned int buflen))
++static void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
++ unsigned int (*actor)(struct ata_scsi_args *args, u8 *rbuf))
+ {
+ u8 *rbuf;
+- unsigned int buflen, rc;
++ unsigned int rc;
+ struct scsi_cmnd *cmd = args->cmd;
+ unsigned long flags;
+
+- local_irq_save(flags);
+-
+- buflen = ata_scsi_rbuf_get(cmd, &rbuf);
+- memset(rbuf, 0, buflen);
+- rc = actor(args, rbuf, buflen);
+- ata_scsi_rbuf_put(cmd, rbuf);
+-
+- local_irq_restore(flags);
++ rbuf = ata_scsi_rbuf_get(cmd, false, &flags);
++ rc = actor(args, rbuf);
++ ata_scsi_rbuf_put(cmd, rc == 0, &flags);
+
+ if (rc == 0)
+ cmd->result = SAM_STAT_GOOD;
+@@ -1720,26 +1720,9 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
+ }
+
+ /**
+- * ATA_SCSI_RBUF_SET - helper to set values in SCSI response buffer
+- * @idx: byte index into SCSI response buffer
+- * @val: value to set
+- *
+- * To be used by SCSI command simulator functions. This macros
+- * expects two local variables, u8 *rbuf and unsigned int buflen,
+- * are in scope.
+- *
+- * LOCKING:
+- * None.
+- */
+-#define ATA_SCSI_RBUF_SET(idx, val) do { \
+- if ((idx) < buflen) rbuf[(idx)] = (u8)(val); \
+- } while (0)
+-
+-/**
+ * ata_scsiop_inq_std - Simulate INQUIRY command
+ * @args: device IDENTIFY data / SCSI command of interest.
+ * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+- * @buflen: Response buffer length.
+ *
+ * Returns standard device identification data associated
+ * with non-VPD INQUIRY command output.
+@@ -1747,10 +1730,17 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+-
+-unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen)
++static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
+ {
++ const u8 versions[] = {
++ 0x60, /* SAM-3 (no version claimed) */
++
++ 0x03,
++ 0x20, /* SBC-2 (no version claimed) */
++
++ 0x02,
++ 0x60 /* SPC-3 (no version claimed) */
++ };
+ u8 hdr[] = {
+ TYPE_DISK,
+ 0,
+@@ -1759,35 +1749,21 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
+ 95 - 4
+ };
+
++ VPRINTK("ENTER\n");
++
+ /* set scsi removeable (RMB) bit per ata bit */
+ if (ata_id_removeable(args->id))
+ hdr[1] |= (1 << 7);
+
+- VPRINTK("ENTER\n");
+-
+ memcpy(rbuf, hdr, sizeof(hdr));
++ memcpy(&rbuf[8], "ATA ", 8);
++ ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
++ ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
+
+- if (buflen > 35) {
+- memcpy(&rbuf[8], "ATA ", 8);
+- ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
+- ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
+- if (rbuf[32] == 0 || rbuf[32] == ' ')
+- memcpy(&rbuf[32], "n/a ", 4);
+- }
+-
+- if (buflen > 63) {
+- const u8 versions[] = {
+- 0x60, /* SAM-3 (no version claimed) */
+-
+- 0x03,
+- 0x20, /* SBC-2 (no version claimed) */
++ if (rbuf[32] == 0 || rbuf[32] == ' ')
++ memcpy(&rbuf[32], "n/a ", 4);
+
+- 0x02,
+- 0x60 /* SPC-3 (no version claimed) */
+- };
+-
+- memcpy(rbuf + 59, versions, sizeof(versions));
+- }
++ memcpy(rbuf + 59, versions, sizeof(versions));
+
+ return 0;
+ }
+@@ -1796,27 +1772,22 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
+ * ata_scsiop_inq_00 - Simulate INQUIRY VPD page 0, list of pages
+ * @args: device IDENTIFY data / SCSI command of interest.
+ * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+- * @buflen: Response buffer length.
+ *
+ * Returns list of inquiry VPD pages available.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+-
+-unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen)
++static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf)
+ {
+ const u8 pages[] = {
+ 0x00, /* page 0x00, this page */
+ 0x80, /* page 0x80, unit serial no page */
+ 0x83 /* page 0x83, device ident page */
+ };
+- rbuf[3] = sizeof(pages); /* number of supported VPD pages */
+-
+- if (buflen > 6)
+- memcpy(rbuf + 4, pages, sizeof(pages));
+
++ rbuf[3] = sizeof(pages); /* number of supported VPD pages */
++ memcpy(rbuf + 4, pages, sizeof(pages));
+ return 0;
+ }
+
+@@ -1824,16 +1795,13 @@ unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
+ * ata_scsiop_inq_80 - Simulate INQUIRY VPD page 80, device serial number
+ * @args: device IDENTIFY data / SCSI command of interest.
+ * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+- * @buflen: Response buffer length.
+ *
+ * Returns ATA device serial number.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+-
+-unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen)
++static unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf)
+ {
+ const u8 hdr[] = {
+ 0,
+@@ -1841,12 +1809,10 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
+ 0,
+ ATA_ID_SERNO_LEN, /* page len */
+ };
+- memcpy(rbuf, hdr, sizeof(hdr));
+-
+- if (buflen > (ATA_ID_SERNO_LEN + 4 - 1))
+- ata_id_string(args->id, (unsigned char *) &rbuf[4],
+- ATA_ID_SERNO, ATA_ID_SERNO_LEN);
+
++ memcpy(rbuf, hdr, sizeof(hdr));
++ ata_id_string(args->id, (unsigned char *) &rbuf[4],
++ ATA_ID_SERNO, ATA_ID_SERNO_LEN);
+ return 0;
+ }
+
+@@ -1854,7 +1820,6 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
+ * ata_scsiop_inq_83 - Simulate INQUIRY VPD page 83, device identity
+ * @args: device IDENTIFY data / SCSI command of interest.
+ * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+- * @buflen: Response buffer length.
+ *
+ * Yields two logical unit device identification designators:
+ * - vendor specific ASCII containing the ATA serial number
+@@ -1864,41 +1829,37 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+-
+-unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen)
++static unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf)
+ {
+- int num;
+ const int sat_model_serial_desc_len = 68;
++ int num;
+
+ rbuf[1] = 0x83; /* this page code */
+ num = 4;
+
+- if (buflen > (ATA_ID_SERNO_LEN + num + 3)) {
+- /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */
+- rbuf[num + 0] = 2;
+- rbuf[num + 3] = ATA_ID_SERNO_LEN;
+- num += 4;
+- ata_id_string(args->id, (unsigned char *) rbuf + num,
+- ATA_ID_SERNO, ATA_ID_SERNO_LEN);
+- num += ATA_ID_SERNO_LEN;
+- }
+- if (buflen > (sat_model_serial_desc_len + num + 3)) {
+- /* SAT defined lu model and serial numbers descriptor */
+- /* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */
+- rbuf[num + 0] = 2;
+- rbuf[num + 1] = 1;
+- rbuf[num + 3] = sat_model_serial_desc_len;
+- num += 4;
+- memcpy(rbuf + num, "ATA ", 8);
+- num += 8;
+- ata_id_string(args->id, (unsigned char *) rbuf + num,
+- ATA_ID_PROD, ATA_ID_PROD_LEN);
+- num += ATA_ID_PROD_LEN;
+- ata_id_string(args->id, (unsigned char *) rbuf + num,
+- ATA_ID_SERNO, ATA_ID_SERNO_LEN);
+- num += ATA_ID_SERNO_LEN;
+- }
++ /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */
++ rbuf[num + 0] = 2;
++ rbuf[num + 3] = ATA_ID_SERNO_LEN;
++ num += 4;
++ ata_id_string(args->id, (unsigned char *) rbuf + num,
++ ATA_ID_SERNO, ATA_ID_SERNO_LEN);
++ num += ATA_ID_SERNO_LEN;
++
++ /* SAT defined lu model and serial numbers descriptor */
++ /* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */
++ rbuf[num + 0] = 2;
++ rbuf[num + 1] = 1;
++ rbuf[num + 3] = sat_model_serial_desc_len;
++ num += 4;
++ memcpy(rbuf + num, "ATA ", 8);
++ num += 8;
++ ata_id_string(args->id, (unsigned char *) rbuf + num, ATA_ID_PROD,
++ ATA_ID_PROD_LEN);
++ num += ATA_ID_PROD_LEN;
++ ata_id_string(args->id, (unsigned char *) rbuf + num, ATA_ID_SERNO,
++ ATA_ID_SERNO_LEN);
++ num += ATA_ID_SERNO_LEN;
++
+ rbuf[3] = num - 4; /* page len (assume less than 256 bytes) */
+ return 0;
+ }
+@@ -1907,35 +1868,26 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
+ * ata_scsiop_inq_89 - Simulate INQUIRY VPD page 89, ATA info
+ * @args: device IDENTIFY data / SCSI command of interest.
+ * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+- * @buflen: Response buffer length.
+ *
+ * Yields SAT-specified ATA VPD page.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+-
+-static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen)
++static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf)
+ {
+- u8 pbuf[60];
+ struct ata_taskfile tf;
+- unsigned int i;
+
+- if (!buflen)
+- return 0;
+-
+- memset(&pbuf, 0, sizeof(pbuf));
+ memset(&tf, 0, sizeof(tf));
+
+- pbuf[1] = 0x89; /* our page code */
+- pbuf[2] = (0x238 >> 8); /* page size fixed at 238h */
+- pbuf[3] = (0x238 & 0xff);
++ rbuf[1] = 0x89; /* our page code */
++ rbuf[2] = (0x238 >> 8); /* page size fixed at 238h */
++ rbuf[3] = (0x238 & 0xff);
+
+- memcpy(&pbuf[8], "linux ", 8);
+- memcpy(&pbuf[16], "libata ", 16);
+- memcpy(&pbuf[32], DRV_VERSION, 4);
+- ata_id_string(args->id, &pbuf[32], ATA_ID_FW_REV, 4);
++ memcpy(&rbuf[8], "linux ", 8);
++ memcpy(&rbuf[16], "libata ", 16);
++ memcpy(&rbuf[32], DRV_VERSION, 4);
++ ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
+
+ /* we don't store the ATA device signature, so we fake it */
+
+@@ -1943,19 +1895,12 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
+ tf.lbal = 0x1;
+ tf.nsect = 0x1;
+
+- ata_tf_to_fis(&tf, 0, 1, &pbuf[36]); /* TODO: PMP? */
+- pbuf[36] = 0x34; /* force D2H Reg FIS (34h) */
++ ata_tf_to_fis(&tf, 0, 1, &rbuf[36]); /* TODO: PMP? */
++ rbuf[36] = 0x34; /* force D2H Reg FIS (34h) */
+
+- pbuf[56] = ATA_CMD_ID_ATA;
++ rbuf[56] = ATA_CMD_ID_ATA;
+
+- i = min(buflen, 60U);
+- memcpy(rbuf, &pbuf[0], i);
+- buflen -= i;
+-
+- if (!buflen)
+- return 0;
+-
+- memcpy(&rbuf[60], &args->id[0], min(buflen, 512U));
++ memcpy(&rbuf[60], &args->id[0], 512);
+ return 0;
+ }
+
+@@ -1963,7 +1908,6 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
+ * ata_scsiop_noop - Command handler that simply returns success.
+ * @args: device IDENTIFY data / SCSI command of interest.
+ * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+- * @buflen: Response buffer length.
+ *
+ * No operation. Simply returns success to caller, to indicate
+ * that the caller should successfully complete this SCSI command.
+@@ -1971,47 +1915,16 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+-
+-unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen)
++static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf)
+ {
+ VPRINTK("ENTER\n");
+ return 0;
+ }
+
+ /**
+- * ata_msense_push - Push data onto MODE SENSE data output buffer
+- * @ptr_io: (input/output) Location to store more output data
+- * @last: End of output data buffer
+- * @buf: Pointer to BLOB being added to output buffer
+- * @buflen: Length of BLOB
+- *
+- * Store MODE SENSE data on an output buffer.
+- *
+- * LOCKING:
+- * None.
+- */
+-
+-static void ata_msense_push(u8 **ptr_io, const u8 *last,
+- const u8 *buf, unsigned int buflen)
+-{
+- u8 *ptr = *ptr_io;
+-
+- if ((ptr + buflen - 1) > last)
+- return;
+-
+- memcpy(ptr, buf, buflen);
+-
+- ptr += buflen;
+-
+- *ptr_io = ptr;
+-}
+-
+-/**
+ * ata_msense_caching - Simulate MODE SENSE caching info page
+ * @id: device IDENTIFY data
+- * @ptr_io: (input/output) Location to store more output data
+- * @last: End of output data buffer
++ * @buf: output buffer
+ *
+ * Generate a caching info page, which conditionally indicates
+ * write caching to the SCSI layer, depending on device
+@@ -2020,58 +1933,43 @@ static void ata_msense_push(u8 **ptr_io, const u8 *last,
+ * LOCKING:
+ * None.
+ */
+-
+-static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io,
+- const u8 *last)
++static unsigned int ata_msense_caching(u16 *id, u8 *buf)
+ {
+- u8 page[CACHE_MPAGE_LEN];
+-
+- memcpy(page, def_cache_mpage, sizeof(page));
++ memcpy(buf, def_cache_mpage, sizeof(def_cache_mpage));
+ if (ata_id_wcache_enabled(id))
+- page[2] |= (1 << 2); /* write cache enable */
++ buf[2] |= (1 << 2); /* write cache enable */
+ if (!ata_id_rahead_enabled(id))
+- page[12] |= (1 << 5); /* disable read ahead */
+-
+- ata_msense_push(ptr_io, last, page, sizeof(page));
+- return sizeof(page);
++ buf[12] |= (1 << 5); /* disable read ahead */
++ return sizeof(def_cache_mpage);
+ }
+
+ /**
+ * ata_msense_ctl_mode - Simulate MODE SENSE control mode page
+- * @dev: Device associated with this MODE SENSE command
+- * @ptr_io: (input/output) Location to store more output data
+- * @last: End of output data buffer
++ * @buf: output buffer
+ *
+ * Generate a generic MODE SENSE control mode page.
+ *
+ * LOCKING:
+ * None.
+ */
+-
+-static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
++static unsigned int ata_msense_ctl_mode(u8 *buf)
+ {
+- ata_msense_push(ptr_io, last, def_control_mpage,
+- sizeof(def_control_mpage));
++ memcpy(buf, def_control_mpage, sizeof(def_control_mpage));
+ return sizeof(def_control_mpage);
+ }
+
+ /**
+ * ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page
+- * @dev: Device associated with this MODE SENSE command
+- * @ptr_io: (input/output) Location to store more output data
+- * @last: End of output data buffer
++ * @bufp: output buffer
+ *
+ * Generate a generic MODE SENSE r/w error recovery page.
+ *
+ * LOCKING:
+ * None.
+ */
+-
+-static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
++static unsigned int ata_msense_rw_recovery(u8 *buf)
+ {
+-
+- ata_msense_push(ptr_io, last, def_rw_recovery_mpage,
+- sizeof(def_rw_recovery_mpage));
++ memcpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage));
+ return sizeof(def_rw_recovery_mpage);
+ }
+
+@@ -2103,7 +2001,6 @@ static int ata_dev_supports_fua(u16 *id)
+ * ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands
+ * @args: device IDENTIFY data / SCSI command of interest.
+ * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+- * @buflen: Response buffer length.
+ *
+ * Simulate MODE SENSE commands. Assume this is invoked for direct
+ * access devices (e.g. disks) only. There should be no block
+@@ -2112,19 +2009,17 @@ static int ata_dev_supports_fua(u16 *id)
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+-
+-unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen)
++static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
+ {
+ struct ata_device *dev = args->dev;
+- u8 *scsicmd = args->cmd->cmnd, *p, *last;
++ u8 *scsicmd = args->cmd->cmnd, *p = rbuf;
+ const u8 sat_blk_desc[] = {
+ 0, 0, 0, 0, /* number of blocks: sat unspecified */
+ 0,
+ 0, 0x2, 0x0 /* block length: 512 bytes */
+ };
+ u8 pg, spg;
+- unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen;
++ unsigned int ebd, page_control, six_byte;
+ u8 dpofua;
+
+ VPRINTK("ENTER\n");
+@@ -2147,17 +2042,10 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
+ goto invalid_fld;
+ }
+
+- if (six_byte) {
+- output_len = 4 + (ebd ? 8 : 0);
+- alloc_len = scsicmd[4];
+- } else {
+- output_len = 8 + (ebd ? 8 : 0);
+- alloc_len = (scsicmd[7] << 8) + scsicmd[8];
+- }
+- minlen = (alloc_len < buflen) ? alloc_len : buflen;
+-
+- p = rbuf + output_len;
+- last = rbuf + minlen - 1;
++ if (six_byte)
++ p += 4 + (ebd ? 8 : 0);
++ else
++ p += 8 + (ebd ? 8 : 0);
+
+ pg = scsicmd[2] & 0x3f;
+ spg = scsicmd[3];
+@@ -2170,61 +2058,48 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
+
+ switch(pg) {
+ case RW_RECOVERY_MPAGE:
+- output_len += ata_msense_rw_recovery(&p, last);
++ p += ata_msense_rw_recovery(p);
+ break;
+
+ case CACHE_MPAGE:
+- output_len += ata_msense_caching(args->id, &p, last);
++ p += ata_msense_caching(args->id, p);
+ break;
+
+- case CONTROL_MPAGE: {
+- output_len += ata_msense_ctl_mode(&p, last);
++ case CONTROL_MPAGE:
++ p += ata_msense_ctl_mode(p);
+ break;
+- }
+
+ case ALL_MPAGES:
+- output_len += ata_msense_rw_recovery(&p, last);
+- output_len += ata_msense_caching(args->id, &p, last);
+- output_len += ata_msense_ctl_mode(&p, last);
++ p += ata_msense_rw_recovery(p);
++ p += ata_msense_caching(args->id, p);
++ p += ata_msense_ctl_mode(p);
+ break;
+
+ default: /* invalid page code */
+ goto invalid_fld;
+ }
+
+- if (minlen < 1)
+- return 0;
+-
+ dpofua = 0;
+ if (ata_dev_supports_fua(args->id) && (dev->flags & ATA_DFLAG_LBA48) &&
+ (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count))
+ dpofua = 1 << 4;
+
+ if (six_byte) {
+- output_len--;
+- rbuf[0] = output_len;
+- if (minlen > 2)
+- rbuf[2] |= dpofua;
++ rbuf[0] = p - rbuf - 1;
++ rbuf[2] |= dpofua;
+ if (ebd) {
+- if (minlen > 3)
+- rbuf[3] = sizeof(sat_blk_desc);
+- if (minlen > 11)
+- memcpy(rbuf + 4, sat_blk_desc,
+- sizeof(sat_blk_desc));
++ rbuf[3] = sizeof(sat_blk_desc);
++ memcpy(rbuf + 4, sat_blk_desc, sizeof(sat_blk_desc));
+ }
+ } else {
+- output_len -= 2;
++ unsigned int output_len = p - rbuf - 2;
++
+ rbuf[0] = output_len >> 8;
+- if (minlen > 1)
+- rbuf[1] = output_len;
+- if (minlen > 3)
+- rbuf[3] |= dpofua;
++ rbuf[1] = output_len;
++ rbuf[3] |= dpofua;
+ if (ebd) {
+- if (minlen > 7)
+- rbuf[7] = sizeof(sat_blk_desc);
+- if (minlen > 15)
+- memcpy(rbuf + 8, sat_blk_desc,
+- sizeof(sat_blk_desc));
++ rbuf[7] = sizeof(sat_blk_desc);
++ memcpy(rbuf + 8, sat_blk_desc, sizeof(sat_blk_desc));
+ }
+ }
+ return 0;
+@@ -2244,15 +2119,13 @@ saving_not_supp:
+ * ata_scsiop_read_cap - Simulate READ CAPACITY[ 16] commands
+ * @args: device IDENTIFY data / SCSI command of interest.
+ * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+- * @buflen: Response buffer length.
+ *
+ * Simulate READ CAPACITY commands.
+ *
+ * LOCKING:
+ * None.
+ */
+-unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen)
++static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
+ {
+ u64 last_lba = args->dev->n_sectors - 1; /* LBA of the last block */
+
+@@ -2263,28 +2136,28 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
+ last_lba = 0xffffffff;
+
+ /* sector count, 32-bit */
+- ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 3));
+- ATA_SCSI_RBUF_SET(1, last_lba >> (8 * 2));
+- ATA_SCSI_RBUF_SET(2, last_lba >> (8 * 1));
+- ATA_SCSI_RBUF_SET(3, last_lba);
++ rbuf[0] = last_lba >> (8 * 3);
++ rbuf[1] = last_lba >> (8 * 2);
++ rbuf[2] = last_lba >> (8 * 1);
++ rbuf[3] = last_lba;
+
+ /* sector size */
+- ATA_SCSI_RBUF_SET(6, ATA_SECT_SIZE >> 8);
+- ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE & 0xff);
++ rbuf[6] = ATA_SECT_SIZE >> 8;
++ rbuf[7] = ATA_SECT_SIZE & 0xff;
+ } else {
+ /* sector count, 64-bit */
+- ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 7));
+- ATA_SCSI_RBUF_SET(1, last_lba >> (8 * 6));
+- ATA_SCSI_RBUF_SET(2, last_lba >> (8 * 5));
+- ATA_SCSI_RBUF_SET(3, last_lba >> (8 * 4));
+- ATA_SCSI_RBUF_SET(4, last_lba >> (8 * 3));
+- ATA_SCSI_RBUF_SET(5, last_lba >> (8 * 2));
+- ATA_SCSI_RBUF_SET(6, last_lba >> (8 * 1));
+- ATA_SCSI_RBUF_SET(7, last_lba);
++ rbuf[0] = last_lba >> (8 * 7);
++ rbuf[1] = last_lba >> (8 * 6);
++ rbuf[2] = last_lba >> (8 * 5);
++ rbuf[3] = last_lba >> (8 * 4);
++ rbuf[4] = last_lba >> (8 * 3);
++ rbuf[5] = last_lba >> (8 * 2);
++ rbuf[6] = last_lba >> (8 * 1);
++ rbuf[7] = last_lba;
+
+ /* sector size */
+- ATA_SCSI_RBUF_SET(10, ATA_SECT_SIZE >> 8);
+- ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE & 0xff);
++ rbuf[10] = ATA_SECT_SIZE >> 8;
++ rbuf[11] = ATA_SECT_SIZE & 0xff;
+ }
+
+ return 0;
+@@ -2294,16 +2167,13 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
+ * ata_scsiop_report_luns - Simulate REPORT LUNS command
+ * @args: device IDENTIFY data / SCSI command of interest.
+ * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+- * @buflen: Response buffer length.
+ *
+ * Simulate REPORT LUNS command.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+-
+-unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen)
++static unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf)
+ {
+ VPRINTK("ENTER\n");
+ rbuf[3] = 8; /* just one lun, LUN 0, size 8 bytes */
+@@ -2311,57 +2181,6 @@ unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
+ return 0;
+ }
+
+-/**
+- * ata_scsi_set_sense - Set SCSI sense data and status
+- * @cmd: SCSI request to be handled
+- * @sk: SCSI-defined sense key
+- * @asc: SCSI-defined additional sense code
+- * @ascq: SCSI-defined additional sense code qualifier
+- *
+- * Helper function that builds a valid fixed format, current
+- * response code and the given sense key (sk), additional sense
+- * code (asc) and additional sense code qualifier (ascq) with
+- * a SCSI command status of %SAM_STAT_CHECK_CONDITION and
+- * DRIVER_SENSE set in the upper bits of scsi_cmnd::result .
+- *
+- * LOCKING:
+- * Not required
+- */
+-
+-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;
+-}
+-
+-/**
+- * ata_scsi_badcmd - End a SCSI request with an error
+- * @cmd: SCSI request to be handled
+- * @done: SCSI command completion function
+- * @asc: SCSI-defined additional sense code
+- * @ascq: SCSI-defined additional sense code qualifier
+- *
+- * Helper function that completes a SCSI command with
+- * %SAM_STAT_CHECK_CONDITION, with a sense key %ILLEGAL_REQUEST
+- * and the specified additional sense codes.
+- *
+- * LOCKING:
+- * spin_lock_irqsave(host lock)
+- */
+-
+-void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq)
+-{
+- DPRINTK("ENTER\n");
+- ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, asc, ascq);
+-
+- done(cmd);
+-}
+-
+ static void atapi_sense_complete(struct ata_queued_cmd *qc)
+ {
+ if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) {
+@@ -2393,7 +2212,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;
+@@ -2485,13 +2307,10 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
+ u8 *scsicmd = cmd->cmnd;
+
+ if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) {
+- u8 *buf = NULL;
+- unsigned int buflen;
+ unsigned long flags;
++ u8 *buf;
+
+- local_irq_save(flags);
+-
+- buflen = ata_scsi_rbuf_get(cmd, &buf);
++ buf = ata_scsi_rbuf_get(cmd, true, &flags);
+
+ /* ATAPI devices typically report zero for their SCSI version,
+ * and sometimes deviate from the spec WRT response data
+@@ -2506,9 +2325,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
+ buf[3] = 0x32;
+ }
+
+- ata_scsi_rbuf_put(cmd, buf);
+-
+- local_irq_restore(flags);
++ ata_scsi_rbuf_put(cmd, true, &flags);
+ }
+
+ cmd->result = SAM_STAT_GOOD;
+@@ -2615,7 +2432,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 +2449,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 +3307,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 +3324,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 +3333,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+ if (dev) {
+ struct ata_eh_info *ehi = &dev->link->eh_info;
+ ehi->probe_mask |= 1 << dev->devno;
+- ehi->action |= ATA_EH_SOFTRESET;
+- ehi->flags |= ATA_EHI_RESUME_LINK;
++ ehi->action |= ATA_EH_RESET;
+ } else
+ rc = -EINVAL;
+ }
+diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
+index 20dc572..2ec65a8 100644
+--- a/drivers/ata/libata-sff.c
++++ b/drivers/ata/libata-sff.c
+@@ -35,11 +35,377 @@
+ #include <linux/kernel.h>
+ #include <linux/pci.h>
+ #include <linux/libata.h>
++#include <linux/highmem.h>
+
+ #include "libata.h"
+
++const struct ata_port_operations ata_sff_port_ops = {
++ .inherits = &ata_base_port_ops,
++
++ .qc_prep = ata_sff_qc_prep,
++ .qc_issue = ata_sff_qc_issue,
++ .qc_fill_rtf = ata_sff_qc_fill_rtf,
++
++ .freeze = ata_sff_freeze,
++ .thaw = ata_sff_thaw,
++ .prereset = ata_sff_prereset,
++ .softreset = ata_sff_softreset,
++ .hardreset = sata_sff_hardreset,
++ .postreset = ata_sff_postreset,
++ .error_handler = ata_sff_error_handler,
++ .post_internal_cmd = ata_sff_post_internal_cmd,
++
++ .sff_dev_select = ata_sff_dev_select,
++ .sff_check_status = ata_sff_check_status,
++ .sff_tf_load = ata_sff_tf_load,
++ .sff_tf_read = ata_sff_tf_read,
++ .sff_exec_command = ata_sff_exec_command,
++ .sff_data_xfer = ata_sff_data_xfer,
++ .sff_irq_on = ata_sff_irq_on,
++ .sff_irq_clear = ata_sff_irq_clear,
++
++ .port_start = ata_sff_port_start,
++};
++
++const struct ata_port_operations ata_bmdma_port_ops = {
++ .inherits = &ata_sff_port_ops,
++
++ .mode_filter = ata_bmdma_mode_filter,
++
++ .bmdma_setup = ata_bmdma_setup,
++ .bmdma_start = ata_bmdma_start,
++ .bmdma_stop = ata_bmdma_stop,
++ .bmdma_status = ata_bmdma_status,
++};
++
++/**
++ * ata_fill_sg - Fill PCI IDE PRD table
++ * @qc: Metadata associated with taskfile to be transferred
++ *
++ * Fill PCI IDE PRD (scatter-gather) table with segments
++ * associated with the current disk command.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ *
++ */
++static void ata_fill_sg(struct ata_queued_cmd *qc)
++{
++ struct ata_port *ap = qc->ap;
++ struct scatterlist *sg;
++ unsigned int si, pi;
++
++ pi = 0;
++ for_each_sg(qc->sg, sg, qc->n_elem, si) {
++ u32 addr, offset;
++ u32 sg_len, len;
++
++ /* determine if physical DMA addr spans 64K boundary.
++ * Note h/w doesn't support 64-bit, so we unconditionally
++ * truncate dma_addr_t to u32.
++ */
++ addr = (u32) sg_dma_address(sg);
++ sg_len = sg_dma_len(sg);
++
++ while (sg_len) {
++ offset = addr & 0xffff;
++ len = sg_len;
++ if ((offset + sg_len) > 0x10000)
++ len = 0x10000 - offset;
++
++ ap->prd[pi].addr = cpu_to_le32(addr);
++ ap->prd[pi].flags_len = cpu_to_le32(len & 0xffff);
++ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
++
++ pi++;
++ sg_len -= len;
++ addr += len;
++ }
++ }
++
++ ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
++}
++
++/**
++ * ata_fill_sg_dumb - Fill PCI IDE PRD table
++ * @qc: Metadata associated with taskfile to be transferred
++ *
++ * Fill PCI IDE PRD (scatter-gather) table with segments
++ * associated with the current disk command. Perform the fill
++ * so that we avoid writing any length 64K records for
++ * controllers that don't follow the spec.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ *
++ */
++static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
++{
++ struct ata_port *ap = qc->ap;
++ struct scatterlist *sg;
++ unsigned int si, pi;
++
++ pi = 0;
++ for_each_sg(qc->sg, sg, qc->n_elem, si) {
++ u32 addr, offset;
++ u32 sg_len, len, blen;
++
++ /* determine if physical DMA addr spans 64K boundary.
++ * Note h/w doesn't support 64-bit, so we unconditionally
++ * truncate dma_addr_t to u32.
++ */
++ addr = (u32) sg_dma_address(sg);
++ sg_len = sg_dma_len(sg);
++
++ while (sg_len) {
++ offset = addr & 0xffff;
++ len = sg_len;
++ if ((offset + sg_len) > 0x10000)
++ len = 0x10000 - offset;
++
++ blen = len & 0xffff;
++ ap->prd[pi].addr = cpu_to_le32(addr);
++ if (blen == 0) {
++ /* Some PATA chipsets like the CS5530 can't
++ cope with 0x0000 meaning 64K as the spec says */
++ ap->prd[pi].flags_len = cpu_to_le32(0x8000);
++ blen = 0x8000;
++ ap->prd[++pi].addr = cpu_to_le32(addr + 0x8000);
++ }
++ ap->prd[pi].flags_len = cpu_to_le32(blen);
++ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
++
++ pi++;
++ sg_len -= len;
++ addr += len;
++ }
++ }
++
++ ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
++}
++
++/**
++ * ata_sff_qc_prep - Prepare taskfile for submission
++ * @qc: Metadata associated with taskfile to be prepared
++ *
++ * Prepare ATA taskfile for submission.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ */
++void ata_sff_qc_prep(struct ata_queued_cmd *qc)
++{
++ if (!(qc->flags & ATA_QCFLAG_DMAMAP))
++ return;
++
++ ata_fill_sg(qc);
++}
++
++/**
++ * ata_sff_dumb_qc_prep - Prepare taskfile for submission
++ * @qc: Metadata associated with taskfile to be prepared
++ *
++ * Prepare ATA taskfile for submission.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ */
++void ata_sff_dumb_qc_prep(struct ata_queued_cmd *qc)
++{
++ if (!(qc->flags & ATA_QCFLAG_DMAMAP))
++ return;
++
++ ata_fill_sg_dumb(qc);
++}
++
++/**
++ * ata_sff_check_status - Read device status reg & clear interrupt
++ * @ap: port where the device is
++ *
++ * Reads ATA taskfile status register for currently-selected device
++ * and return its value. This also clears pending interrupts
++ * from this device
++ *
++ * LOCKING:
++ * Inherited from caller.
++ */
++u8 ata_sff_check_status(struct ata_port *ap)
++{
++ return ioread8(ap->ioaddr.status_addr);
++}
++
++/**
++ * ata_sff_altstatus - Read device alternate status reg
++ * @ap: port where the device is
++ *
++ * Reads ATA taskfile alternate status register for
++ * currently-selected device and return its value.
++ *
++ * Note: may NOT be used as the check_altstatus() entry in
++ * ata_port_operations.
++ *
++ * LOCKING:
++ * Inherited from caller.
++ */
++u8 ata_sff_altstatus(struct ata_port *ap)
++{
++ if (ap->ops->sff_check_altstatus)
++ return ap->ops->sff_check_altstatus(ap);
++
++ return ioread8(ap->ioaddr.altstatus_addr);
++}
++
++/**
++ * ata_sff_busy_sleep - sleep until BSY clears, or timeout
++ * @ap: port containing status register to be polled
++ * @tmout_pat: impatience timeout
++ * @tmout: overall timeout
++ *
++ * Sleep until ATA Status register bit BSY clears,
++ * or a timeout occurs.
++ *
++ * LOCKING:
++ * Kernel thread context (may sleep).
++ *
++ * RETURNS:
++ * 0 on success, -errno otherwise.
++ */
++int ata_sff_busy_sleep(struct ata_port *ap,
++ unsigned long tmout_pat, unsigned long tmout)
++{
++ unsigned long timer_start, timeout;
++ u8 status;
++
++ status = ata_sff_busy_wait(ap, ATA_BUSY, 300);
++ timer_start = jiffies;
++ timeout = timer_start + tmout_pat;
++ while (status != 0xff && (status & ATA_BUSY) &&
++ time_before(jiffies, timeout)) {
++ msleep(50);
++ status = ata_sff_busy_wait(ap, ATA_BUSY, 3);
++ }
++
++ if (status != 0xff && (status & ATA_BUSY))
++ ata_port_printk(ap, KERN_WARNING,
++ "port is slow to respond, please be patient "
++ "(Status 0x%x)\n", status);
++
++ timeout = timer_start + tmout;
++ while (status != 0xff && (status & ATA_BUSY) &&
++ time_before(jiffies, timeout)) {
++ msleep(50);
++ status = ap->ops->sff_check_status(ap);
++ }
++
++ if (status == 0xff)
++ return -ENODEV;
++
++ if (status & ATA_BUSY) {
++ ata_port_printk(ap, KERN_ERR, "port failed to respond "
++ "(%lu secs, Status 0x%x)\n",
++ tmout / HZ, status);
++ return -EBUSY;
++ }
++
++ return 0;
++}
++
++static int ata_sff_check_ready(struct ata_link *link)
++{
++ u8 status = link->ap->ops->sff_check_status(link->ap);
++
++ if (!(status & ATA_BUSY))
++ return 1;
++ if (status == 0xff)
++ return -ENODEV;
++ return 0;
++}
++
++/**
++ * ata_sff_wait_ready - sleep until BSY clears, or timeout
++ * @link: SFF link to wait ready status for
++ * @deadline: deadline jiffies for the operation
++ *
++ * Sleep until ATA Status register bit BSY clears, or timeout
++ * occurs.
++ *
++ * LOCKING:
++ * Kernel thread context (may sleep).
++ *
++ * RETURNS:
++ * 0 on success, -errno otherwise.
++ */
++int ata_sff_wait_ready(struct ata_link *link, unsigned long deadline)
++{
++ return ata_wait_ready(link, deadline, ata_sff_check_ready);
++}
++
++/**
++ * ata_sff_dev_select - Select device 0/1 on ATA bus
++ * @ap: ATA channel to manipulate
++ * @device: ATA device (numbered from zero) to select
++ *
++ * Use the method defined in the ATA specification to
++ * make either device 0, or device 1, active on the
++ * ATA channel. Works with both PIO and MMIO.
++ *
++ * May be used as the dev_select() entry in ata_port_operations.
++ *
++ * LOCKING:
++ * caller.
++ */
++void ata_sff_dev_select(struct ata_port *ap, unsigned int device)
++{
++ u8 tmp;
++
++ if (device == 0)
++ tmp = ATA_DEVICE_OBS;
++ else
++ tmp = ATA_DEVICE_OBS | ATA_DEV1;
++
++ iowrite8(tmp, ap->ioaddr.device_addr);
++ ata_sff_pause(ap); /* needed; also flushes, for mmio */
++}
++
++/**
++ * ata_dev_select - Select device 0/1 on ATA bus
++ * @ap: ATA channel to manipulate
++ * @device: ATA device (numbered from zero) to select
++ * @wait: non-zero to wait for Status register BSY bit to clear
++ * @can_sleep: non-zero if context allows sleeping
++ *
++ * Use the method defined in the ATA specification to
++ * make either device 0, or device 1, active on the
++ * ATA channel.
++ *
++ * This is a high-level version of ata_sff_dev_select(), which
++ * additionally provides the services of inserting the proper
++ * pauses and status polling, where needed.
++ *
++ * LOCKING:
++ * caller.
++ */
++void ata_dev_select(struct ata_port *ap, unsigned int device,
++ unsigned int wait, unsigned int can_sleep)
++{
++ if (ata_msg_probe(ap))
++ ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, "
++ "device %u, wait %u\n", device, wait);
++
++ if (wait)
++ ata_wait_idle(ap);
++
++ ap->ops->sff_dev_select(ap, device);
++
++ if (wait) {
++ if (can_sleep && ap->link.device[device].class == ATA_DEV_ATAPI)
++ msleep(150);
++ ata_wait_idle(ap);
++ }
++}
++
+ /**
+- * ata_irq_on - Enable interrupts on a port.
++ * ata_sff_irq_on - Enable interrupts on a port.
+ * @ap: Port on which interrupts are enabled.
+ *
+ * Enable interrupts on a legacy IDE device using MMIO or PIO,
+@@ -48,7 +414,7 @@
+ * LOCKING:
+ * Inherited from caller.
+ */
+-u8 ata_irq_on(struct ata_port *ap)
++u8 ata_sff_irq_on(struct ata_port *ap)
+ {
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+ u8 tmp;
+@@ -60,13 +426,34 @@ u8 ata_irq_on(struct ata_port *ap)
+ iowrite8(ap->ctl, ioaddr->ctl_addr);
+ tmp = ata_wait_idle(ap);
+
+- ap->ops->irq_clear(ap);
++ ap->ops->sff_irq_clear(ap);
+
+ return tmp;
+ }
+
+ /**
+- * ata_tf_load - send taskfile registers to host controller
++ * ata_sff_irq_clear - Clear PCI IDE BMDMA interrupt.
++ * @ap: Port associated with this ATA transaction.
++ *
++ * Clear interrupt and error flags in DMA status register.
++ *
++ * May be used as the irq_clear() entry in ata_port_operations.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ */
++void ata_sff_irq_clear(struct ata_port *ap)
++{
++ void __iomem *mmio = ap->ioaddr.bmdma_addr;
++
++ if (!mmio)
++ return;
++
++ iowrite8(ioread8(mmio + ATA_DMA_STATUS), mmio + ATA_DMA_STATUS);
++}
++
++/**
++ * ata_sff_tf_load - send taskfile registers to host controller
+ * @ap: Port to which output is sent
+ * @tf: ATA taskfile register set
+ *
+@@ -75,8 +462,7 @@ u8 ata_irq_on(struct ata_port *ap)
+ * LOCKING:
+ * Inherited from caller.
+ */
+-
+-void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
++void ata_sff_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+ {
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+ unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+@@ -126,26 +512,7 @@ void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+ }
+
+ /**
+- * ata_exec_command - issue ATA command to host controller
+- * @ap: port to which command is being issued
+- * @tf: ATA taskfile register set
+- *
+- * Issues ATA command, with proper synchronization with interrupt
+- * handler / other threads.
+- *
+- * LOCKING:
+- * spin_lock_irqsave(host lock)
+- */
+-void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
+-{
+- DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
+-
+- iowrite8(tf->command, ap->ioaddr.command_addr);
+- ata_pause(ap);
+-}
+-
+-/**
+- * ata_tf_read - input device's ATA taskfile shadow registers
++ * ata_sff_tf_read - input device's ATA taskfile shadow registers
+ * @ap: Port from which input is read
+ * @tf: ATA taskfile register set for storing input
+ *
+@@ -157,11 +524,11 @@ void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
+ * LOCKING:
+ * Inherited from caller.
+ */
+-void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
++void ata_sff_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+ {
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+
+- tf->command = ata_check_status(ap);
++ tf->command = ata_sff_check_status(ap);
+ tf->feature = ioread8(ioaddr->error_addr);
+ tf->nsect = ioread8(ioaddr->nsect_addr);
+ tf->lbal = ioread8(ioaddr->lbal_addr);
+@@ -185,165 +552,1028 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+ }
+
+ /**
+- * ata_check_status - Read device status reg & clear interrupt
+- * @ap: port where the device is
++ * ata_sff_exec_command - issue ATA command to host controller
++ * @ap: port to which command is being issued
++ * @tf: ATA taskfile register set
+ *
+- * Reads ATA taskfile status register for currently-selected device
+- * and return its value. This also clears pending interrupts
+- * from this device
++ * Issues ATA command, with proper synchronization with interrupt
++ * handler / other threads.
+ *
+ * LOCKING:
+- * Inherited from caller.
++ * spin_lock_irqsave(host lock)
+ */
+-u8 ata_check_status(struct ata_port *ap)
++void ata_sff_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
+ {
+- return ioread8(ap->ioaddr.status_addr);
++ DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
++
++ iowrite8(tf->command, ap->ioaddr.command_addr);
++ ata_sff_pause(ap);
+ }
+
+ /**
+- * ata_altstatus - Read device alternate status reg
+- * @ap: port where the device is
++ * ata_tf_to_host - issue ATA taskfile to host controller
++ * @ap: port to which command is being issued
++ * @tf: ATA taskfile register set
+ *
+- * Reads ATA taskfile alternate status register for
+- * currently-selected device and return its value.
++ * Issues ATA taskfile register set to ATA host controller,
++ * with proper synchronization with interrupt handler and
++ * other threads.
+ *
+- * Note: may NOT be used as the check_altstatus() entry in
+- * ata_port_operations.
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ */
++static inline void ata_tf_to_host(struct ata_port *ap,
++ const struct ata_taskfile *tf)
++{
++ ap->ops->sff_tf_load(ap, tf);
++ ap->ops->sff_exec_command(ap, tf);
++}
++
++/**
++ * ata_sff_data_xfer - Transfer data by PIO
++ * @dev: device to target
++ * @buf: data buffer
++ * @buflen: buffer length
++ * @rw: read/write
++ *
++ * Transfer data from/to the device data register by PIO.
+ *
+ * LOCKING:
+ * Inherited from caller.
++ *
++ * RETURNS:
++ * Bytes consumed.
+ */
+-u8 ata_altstatus(struct ata_port *ap)
++unsigned int ata_sff_data_xfer(struct ata_device *dev, unsigned char *buf,
++ unsigned int buflen, int rw)
+ {
+- if (ap->ops->check_altstatus)
+- return ap->ops->check_altstatus(ap);
++ struct ata_port *ap = dev->link->ap;
++ void __iomem *data_addr = ap->ioaddr.data_addr;
++ unsigned int words = buflen >> 1;
+
+- return ioread8(ap->ioaddr.altstatus_addr);
++ /* Transfer multiple of 2 bytes */
++ if (rw == READ)
++ ioread16_rep(data_addr, buf, words);
++ else
++ iowrite16_rep(data_addr, buf, words);
++
++ /* Transfer trailing 1 byte, if any. */
++ if (unlikely(buflen & 0x01)) {
++ __le16 align_buf[1] = { 0 };
++ unsigned char *trailing_buf = buf + buflen - 1;
++
++ if (rw == READ) {
++ align_buf[0] = cpu_to_le16(ioread16(data_addr));
++ memcpy(trailing_buf, align_buf, 1);
++ } else {
++ memcpy(align_buf, trailing_buf, 1);
++ iowrite16(le16_to_cpu(align_buf[0]), data_addr);
++ }
++ words++;
++ }
++
++ return words << 1;
+ }
+
+ /**
+- * ata_bmdma_setup - Set up PCI IDE BMDMA transaction
+- * @qc: Info associated with this ATA transaction.
++ * ata_sff_data_xfer_noirq - Transfer data by PIO
++ * @dev: device to target
++ * @buf: data buffer
++ * @buflen: buffer length
++ * @rw: read/write
++ *
++ * Transfer data from/to the device data register by PIO. Do the
++ * transfer with interrupts disabled.
+ *
+ * LOCKING:
+- * spin_lock_irqsave(host lock)
++ * Inherited from caller.
++ *
++ * RETURNS:
++ * Bytes consumed.
+ */
+-void ata_bmdma_setup(struct ata_queued_cmd *qc)
++unsigned int ata_sff_data_xfer_noirq(struct ata_device *dev, unsigned char *buf,
++ unsigned int buflen, int rw)
++{
++ unsigned long flags;
++ unsigned int consumed;
++
++ local_irq_save(flags);
++ consumed = ata_sff_data_xfer(dev, buf, buflen, rw);
++ local_irq_restore(flags);
++
++ return consumed;
++}
++
++/**
++ * ata_pio_sector - Transfer a sector of data.
++ * @qc: Command on going
++ *
++ * Transfer qc->sect_size bytes of data from/to the ATA device.
++ *
++ * LOCKING:
++ * Inherited from caller.
++ */
++static void ata_pio_sector(struct ata_queued_cmd *qc)
+ {
++ int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+ struct ata_port *ap = qc->ap;
+- unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
+- u8 dmactl;
++ struct page *page;
++ unsigned int offset;
++ unsigned char *buf;
+
+- /* load PRD table addr. */
+- mb(); /* make sure PRD table writes are visible to controller */
+- iowrite32(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
++ if (qc->curbytes == qc->nbytes - qc->sect_size)
++ ap->hsm_task_state = HSM_ST_LAST;
+
+- /* specify data direction, triple-check start bit is clear */
+- dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+- dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
+- if (!rw)
+- dmactl |= ATA_DMA_WR;
+- iowrite8(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++ page = sg_page(qc->cursg);
++ offset = qc->cursg->offset + qc->cursg_ofs;
+
+- /* issue r/w command */
+- ap->ops->exec_command(ap, &qc->tf);
++ /* get the current page and offset */
++ page = nth_page(page, (offset >> PAGE_SHIFT));
++ offset %= PAGE_SIZE;
++
++ DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
++
++ if (PageHighMem(page)) {
++ unsigned long flags;
++
++ /* FIXME: use a bounce buffer */
++ local_irq_save(flags);
++ buf = kmap_atomic(page, KM_IRQ0);
++
++ /* do the actual data transfer */
++ ap->ops->sff_data_xfer(qc->dev, buf + offset, qc->sect_size,
++ do_write);
++
++ kunmap_atomic(buf, KM_IRQ0);
++ local_irq_restore(flags);
++ } else {
++ buf = page_address(page);
++ ap->ops->sff_data_xfer(qc->dev, buf + offset, qc->sect_size,
++ do_write);
++ }
++
++ qc->curbytes += qc->sect_size;
++ qc->cursg_ofs += qc->sect_size;
++
++ if (qc->cursg_ofs == qc->cursg->length) {
++ qc->cursg = sg_next(qc->cursg);
++ qc->cursg_ofs = 0;
++ }
+ }
+
+ /**
+- * ata_bmdma_start - Start a PCI IDE BMDMA transaction
+- * @qc: Info associated with this ATA transaction.
++ * ata_pio_sectors - Transfer one or many sectors.
++ * @qc: Command on going
++ *
++ * Transfer one or many sectors of data from/to the
++ * ATA device for the DRQ request.
+ *
+ * LOCKING:
+- * spin_lock_irqsave(host lock)
++ * Inherited from caller.
+ */
+-void ata_bmdma_start(struct ata_queued_cmd *qc)
++static void ata_pio_sectors(struct ata_queued_cmd *qc)
++{
++ if (is_multi_taskfile(&qc->tf)) {
++ /* READ/WRITE MULTIPLE */
++ unsigned int nsect;
++
++ WARN_ON(qc->dev->multi_count == 0);
++
++ nsect = min((qc->nbytes - qc->curbytes) / qc->sect_size,
++ qc->dev->multi_count);
++ while (nsect--)
++ ata_pio_sector(qc);
++ } else
++ ata_pio_sector(qc);
++
++ ata_sff_altstatus(qc->ap); /* flush */
++}
++
++/**
++ * atapi_send_cdb - Write CDB bytes to hardware
++ * @ap: Port to which ATAPI device is attached.
++ * @qc: Taskfile currently active
++ *
++ * When device has indicated its readiness to accept
++ * a CDB, this function is called. Send the CDB.
++ *
++ * LOCKING:
++ * caller.
++ */
++static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
++{
++ /* send SCSI cdb */
++ DPRINTK("send cdb\n");
++ WARN_ON(qc->dev->cdb_len < 12);
++
++ ap->ops->sff_data_xfer(qc->dev, qc->cdb, qc->dev->cdb_len, 1);
++ ata_sff_altstatus(ap); /* flush */
++
++ switch (qc->tf.protocol) {
++ case ATAPI_PROT_PIO:
++ ap->hsm_task_state = HSM_ST;
++ break;
++ case ATAPI_PROT_NODATA:
++ ap->hsm_task_state = HSM_ST_LAST;
++ break;
++ case ATAPI_PROT_DMA:
++ ap->hsm_task_state = HSM_ST_LAST;
++ /* initiate bmdma */
++ ap->ops->bmdma_start(qc);
++ break;
++ }
++}
++
++/**
++ * __atapi_pio_bytes - Transfer data from/to the ATAPI device.
++ * @qc: Command on going
++ * @bytes: number of bytes
++ *
++ * Transfer Transfer data from/to the ATAPI device.
++ *
++ * LOCKING:
++ * Inherited from caller.
++ *
++ */
++static int __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
+ {
++ int rw = (qc->tf.flags & ATA_TFLAG_WRITE) ? WRITE : READ;
+ struct ata_port *ap = qc->ap;
+- u8 dmactl;
++ struct ata_device *dev = qc->dev;
++ struct ata_eh_info *ehi = &dev->link->eh_info;
++ struct scatterlist *sg;
++ struct page *page;
++ unsigned char *buf;
++ unsigned int offset, count, consumed;
++
++next_sg:
++ sg = qc->cursg;
++ if (unlikely(!sg)) {
++ ata_ehi_push_desc(ehi, "unexpected or too much trailing data "
++ "buf=%u cur=%u bytes=%u",
++ qc->nbytes, qc->curbytes, bytes);
++ return -1;
++ }
+
+- /* start host DMA transaction */
+- dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+- iowrite8(dmactl | ATA_DMA_START, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++ page = sg_page(sg);
++ offset = sg->offset + qc->cursg_ofs;
+
+- /* Strictly, one may wish to issue an ioread8() here, to
+- * flush the mmio write. However, control also passes
+- * to the hardware at this point, and it will interrupt
+- * us when we are to resume control. So, in effect,
+- * we don't care when the mmio write flushes.
+- * Further, a read of the DMA status register _immediately_
+- * following the write may not be what certain flaky hardware
+- * is expected, so I think it is best to not add a readb()
+- * without first all the MMIO ATA cards/mobos.
+- * Or maybe I'm just being paranoid.
+- *
+- * FIXME: The posting of this write means I/O starts are
+- * unneccessarily delayed for MMIO
++ /* get the current page and offset */
++ page = nth_page(page, (offset >> PAGE_SHIFT));
++ offset %= PAGE_SIZE;
++
++ /* don't overrun current sg */
++ count = min(sg->length - qc->cursg_ofs, bytes);
++
++ /* don't cross page boundaries */
++ count = min(count, (unsigned int)PAGE_SIZE - offset);
++
++ DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
++
++ if (PageHighMem(page)) {
++ unsigned long flags;
++
++ /* FIXME: use bounce buffer */
++ local_irq_save(flags);
++ buf = kmap_atomic(page, KM_IRQ0);
++
++ /* do the actual data transfer */
++ consumed = ap->ops->sff_data_xfer(dev, buf + offset, count, rw);
++
++ kunmap_atomic(buf, KM_IRQ0);
++ local_irq_restore(flags);
++ } else {
++ buf = page_address(page);
++ consumed = ap->ops->sff_data_xfer(dev, buf + offset, count, rw);
++ }
++
++ bytes -= min(bytes, consumed);
++ qc->curbytes += count;
++ qc->cursg_ofs += count;
++
++ if (qc->cursg_ofs == sg->length) {
++ qc->cursg = sg_next(qc->cursg);
++ qc->cursg_ofs = 0;
++ }
++
++ /* consumed can be larger than count only for the last transfer */
++ WARN_ON(qc->cursg && count != consumed);
++
++ if (bytes)
++ goto next_sg;
++ return 0;
++}
++
++/**
++ * atapi_pio_bytes - Transfer data from/to the ATAPI device.
++ * @qc: Command on going
++ *
++ * Transfer Transfer data from/to the ATAPI device.
++ *
++ * LOCKING:
++ * Inherited from caller.
++ */
++static void atapi_pio_bytes(struct ata_queued_cmd *qc)
++{
++ struct ata_port *ap = qc->ap;
++ struct ata_device *dev = qc->dev;
++ struct ata_eh_info *ehi = &dev->link->eh_info;
++ unsigned int ireason, bc_lo, bc_hi, bytes;
++ int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0;
++
++ /* Abuse qc->result_tf for temp storage of intermediate TF
++ * here to save some kernel stack usage.
++ * For normal completion, qc->result_tf is not relevant. For
++ * error, qc->result_tf is later overwritten by ata_qc_complete().
++ * So, the correctness of qc->result_tf is not affected.
+ */
++ ap->ops->sff_tf_read(ap, &qc->result_tf);
++ ireason = qc->result_tf.nsect;
++ bc_lo = qc->result_tf.lbam;
++ bc_hi = qc->result_tf.lbah;
++ bytes = (bc_hi << 8) | bc_lo;
++
++ /* shall be cleared to zero, indicating xfer of data */
++ if (unlikely(ireason & (1 << 0)))
++ goto atapi_check;
++
++ /* make sure transfer direction matches expected */
++ i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0;
++ if (unlikely(do_write != i_write))
++ goto atapi_check;
++
++ if (unlikely(!bytes))
++ goto atapi_check;
++
++ VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes);
++
++ if (unlikely(__atapi_pio_bytes(qc, bytes)))
++ goto err_out;
++ ata_sff_altstatus(ap); /* flush */
++
++ return;
++
++ atapi_check:
++ ata_ehi_push_desc(ehi, "ATAPI check failed (ireason=0x%x bytes=%u)",
++ ireason, bytes);
++ err_out:
++ qc->err_mask |= AC_ERR_HSM;
++ ap->hsm_task_state = HSM_ST_ERR;
+ }
+
+ /**
+- * ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt.
+- * @ap: Port associated with this ATA transaction.
++ * ata_hsm_ok_in_wq - Check if the qc can be handled in the workqueue.
++ * @ap: the target ata_port
++ * @qc: qc on going
+ *
+- * Clear interrupt and error flags in DMA status register.
++ * RETURNS:
++ * 1 if ok in workqueue, 0 otherwise.
++ */
++static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc)
++{
++ if (qc->tf.flags & ATA_TFLAG_POLLING)
++ return 1;
++
++ if (ap->hsm_task_state == HSM_ST_FIRST) {
++ if (qc->tf.protocol == ATA_PROT_PIO &&
++ (qc->tf.flags & ATA_TFLAG_WRITE))
++ return 1;
++
++ if (ata_is_atapi(qc->tf.protocol) &&
++ !(qc->dev->flags & ATA_DFLAG_CDB_INTR))
++ return 1;
++ }
++
++ return 0;
++}
++
++/**
++ * ata_hsm_qc_complete - finish a qc running on standard HSM
++ * @qc: Command to complete
++ * @in_wq: 1 if called from workqueue, 0 otherwise
+ *
+- * May be used as the irq_clear() entry in ata_port_operations.
++ * Finish @qc which is running on standard HSM.
+ *
+ * LOCKING:
+- * spin_lock_irqsave(host lock)
++ * If @in_wq is zero, spin_lock_irqsave(host lock).
++ * Otherwise, none on entry and grabs host lock.
+ */
+-void ata_bmdma_irq_clear(struct ata_port *ap)
++static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+ {
+- void __iomem *mmio = ap->ioaddr.bmdma_addr;
++ struct ata_port *ap = qc->ap;
++ unsigned long flags;
+
+- if (!mmio)
+- return;
++ if (ap->ops->error_handler) {
++ if (in_wq) {
++ spin_lock_irqsave(ap->lock, flags);
++
++ /* EH might have kicked in while host lock is
++ * released.
++ */
++ qc = ata_qc_from_tag(ap, qc->tag);
++ if (qc) {
++ if (likely(!(qc->err_mask & AC_ERR_HSM))) {
++ ap->ops->sff_irq_on(ap);
++ ata_qc_complete(qc);
++ } else
++ ata_port_freeze(ap);
++ }
++
++ spin_unlock_irqrestore(ap->lock, flags);
++ } else {
++ if (likely(!(qc->err_mask & AC_ERR_HSM)))
++ ata_qc_complete(qc);
++ else
++ ata_port_freeze(ap);
++ }
++ } else {
++ if (in_wq) {
++ spin_lock_irqsave(ap->lock, flags);
++ ap->ops->sff_irq_on(ap);
++ ata_qc_complete(qc);
++ spin_unlock_irqrestore(ap->lock, flags);
++ } else
++ ata_qc_complete(qc);
++ }
++}
+
+- iowrite8(ioread8(mmio + ATA_DMA_STATUS), mmio + ATA_DMA_STATUS);
++/**
++ * ata_sff_hsm_move - move the HSM to the next state.
++ * @ap: the target ata_port
++ * @qc: qc on going
++ * @status: current device status
++ * @in_wq: 1 if called from workqueue, 0 otherwise
++ *
++ * RETURNS:
++ * 1 when poll next status needed, 0 otherwise.
++ */
++int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
++ u8 status, int in_wq)
++{
++ unsigned long flags = 0;
++ int poll_next;
++
++ WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
++
++ /* Make sure ata_sff_qc_issue() does not throw things
++ * like DMA polling into the workqueue. Notice that
++ * in_wq is not equivalent to (qc->tf.flags & ATA_TFLAG_POLLING).
++ */
++ WARN_ON(in_wq != ata_hsm_ok_in_wq(ap, qc));
++
++fsm_start:
++ DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n",
++ ap->print_id, qc->tf.protocol, ap->hsm_task_state, status);
++
++ switch (ap->hsm_task_state) {
++ case HSM_ST_FIRST:
++ /* Send first data block or PACKET CDB */
++
++ /* If polling, we will stay in the work queue after
++ * sending the data. Otherwise, interrupt handler
++ * takes over after sending the data.
++ */
++ poll_next = (qc->tf.flags & ATA_TFLAG_POLLING);
++
++ /* check device status */
++ if (unlikely((status & ATA_DRQ) == 0)) {
++ /* handle BSY=0, DRQ=0 as error */
++ if (likely(status & (ATA_ERR | ATA_DF)))
++ /* device stops HSM for abort/error */
++ qc->err_mask |= AC_ERR_DEV;
++ else
++ /* HSM violation. Let EH handle this */
++ qc->err_mask |= AC_ERR_HSM;
++
++ ap->hsm_task_state = HSM_ST_ERR;
++ goto fsm_start;
++ }
++
++ /* Device should not ask for data transfer (DRQ=1)
++ * when it finds something wrong.
++ * We ignore DRQ here and stop the HSM by
++ * changing hsm_task_state to HSM_ST_ERR and
++ * let the EH abort the command or reset the device.
++ */
++ if (unlikely(status & (ATA_ERR | ATA_DF))) {
++ /* Some ATAPI tape drives forget to clear the ERR bit
++ * when doing the next command (mostly request sense).
++ * We ignore ERR here to workaround and proceed sending
++ * the CDB.
++ */
++ if (!(qc->dev->horkage & ATA_HORKAGE_STUCK_ERR)) {
++ ata_port_printk(ap, KERN_WARNING,
++ "DRQ=1 with device error, "
++ "dev_stat 0x%X\n", status);
++ qc->err_mask |= AC_ERR_HSM;
++ ap->hsm_task_state = HSM_ST_ERR;
++ goto fsm_start;
++ }
++ }
++
++ /* Send the CDB (atapi) or the first data block (ata pio out).
++ * During the state transition, interrupt handler shouldn't
++ * be invoked before the data transfer is complete and
++ * hsm_task_state is changed. Hence, the following locking.
++ */
++ if (in_wq)
++ spin_lock_irqsave(ap->lock, flags);
++
++ if (qc->tf.protocol == ATA_PROT_PIO) {
++ /* PIO data out protocol.
++ * send first data block.
++ */
++
++ /* ata_pio_sectors() might change the state
++ * to HSM_ST_LAST. so, the state is changed here
++ * before ata_pio_sectors().
++ */
++ ap->hsm_task_state = HSM_ST;
++ ata_pio_sectors(qc);
++ } else
++ /* send CDB */
++ atapi_send_cdb(ap, qc);
++
++ if (in_wq)
++ spin_unlock_irqrestore(ap->lock, flags);
++
++ /* if polling, ata_pio_task() handles the rest.
++ * otherwise, interrupt handler takes over from here.
++ */
++ break;
++
++ case HSM_ST:
++ /* complete command or read/write the data register */
++ if (qc->tf.protocol == ATAPI_PROT_PIO) {
++ /* ATAPI PIO protocol */
++ if ((status & ATA_DRQ) == 0) {
++ /* No more data to transfer or device error.
++ * Device error will be tagged in HSM_ST_LAST.
++ */
++ ap->hsm_task_state = HSM_ST_LAST;
++ goto fsm_start;
++ }
++
++ /* Device should not ask for data transfer (DRQ=1)
++ * when it finds something wrong.
++ * We ignore DRQ here and stop the HSM by
++ * changing hsm_task_state to HSM_ST_ERR and
++ * let the EH abort the command or reset the device.
++ */
++ if (unlikely(status & (ATA_ERR | ATA_DF))) {
++ ata_port_printk(ap, KERN_WARNING, "DRQ=1 with "
++ "device error, dev_stat 0x%X\n",
++ status);
++ qc->err_mask |= AC_ERR_HSM;
++ ap->hsm_task_state = HSM_ST_ERR;
++ goto fsm_start;
++ }
++
++ atapi_pio_bytes(qc);
++
++ if (unlikely(ap->hsm_task_state == HSM_ST_ERR))
++ /* bad ireason reported by device */
++ goto fsm_start;
++
++ } else {
++ /* ATA PIO protocol */
++ if (unlikely((status & ATA_DRQ) == 0)) {
++ /* handle BSY=0, DRQ=0 as error */
++ if (likely(status & (ATA_ERR | ATA_DF)))
++ /* device stops HSM for abort/error */
++ qc->err_mask |= AC_ERR_DEV;
++ else
++ /* HSM violation. Let EH handle this.
++ * Phantom devices also trigger this
++ * condition. Mark hint.
++ */
++ qc->err_mask |= AC_ERR_HSM |
++ AC_ERR_NODEV_HINT;
++
++ ap->hsm_task_state = HSM_ST_ERR;
++ goto fsm_start;
++ }
++
++ /* For PIO reads, some devices may ask for
++ * data transfer (DRQ=1) alone with ERR=1.
++ * We respect DRQ here and transfer one
++ * block of junk data before changing the
++ * hsm_task_state to HSM_ST_ERR.
++ *
++ * For PIO writes, ERR=1 DRQ=1 doesn't make
++ * sense since the data block has been
++ * transferred to the device.
++ */
++ if (unlikely(status & (ATA_ERR | ATA_DF))) {
++ /* data might be corrputed */
++ qc->err_mask |= AC_ERR_DEV;
++
++ if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
++ ata_pio_sectors(qc);
++ status = ata_wait_idle(ap);
++ }
++
++ if (status & (ATA_BUSY | ATA_DRQ))
++ qc->err_mask |= AC_ERR_HSM;
++
++ /* ata_pio_sectors() might change the
++ * state to HSM_ST_LAST. so, the state
++ * is changed after ata_pio_sectors().
++ */
++ ap->hsm_task_state = HSM_ST_ERR;
++ goto fsm_start;
++ }
++
++ ata_pio_sectors(qc);
++
++ if (ap->hsm_task_state == HSM_ST_LAST &&
++ (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
++ /* all data read */
++ status = ata_wait_idle(ap);
++ goto fsm_start;
++ }
++ }
++
++ poll_next = 1;
++ break;
++
++ case HSM_ST_LAST:
++ if (unlikely(!ata_ok(status))) {
++ qc->err_mask |= __ac_err_mask(status);
++ ap->hsm_task_state = HSM_ST_ERR;
++ goto fsm_start;
++ }
++
++ /* no more data to transfer */
++ DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n",
++ ap->print_id, qc->dev->devno, status);
++
++ WARN_ON(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM));
++
++ ap->hsm_task_state = HSM_ST_IDLE;
++
++ /* complete taskfile transaction */
++ ata_hsm_qc_complete(qc, in_wq);
++
++ poll_next = 0;
++ break;
++
++ case HSM_ST_ERR:
++ /* make sure qc->err_mask is available to
++ * know what's wrong and recover
++ */
++ WARN_ON(!(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM)));
++
++ ap->hsm_task_state = HSM_ST_IDLE;
++
++ /* complete taskfile transaction */
++ ata_hsm_qc_complete(qc, in_wq);
++
++ poll_next = 0;
++ break;
++ default:
++ poll_next = 0;
++ BUG();
++ }
++
++ return poll_next;
++}
++
++void ata_pio_task(struct work_struct *work)
++{
++ struct ata_port *ap =
++ container_of(work, struct ata_port, port_task.work);
++ struct ata_queued_cmd *qc = ap->port_task_data;
++ u8 status;
++ int poll_next;
++
++fsm_start:
++ WARN_ON(ap->hsm_task_state == HSM_ST_IDLE);
++
++ /*
++ * This is purely heuristic. This is a fast path.
++ * Sometimes when we enter, BSY will be cleared in
++ * a chk-status or two. If not, the drive is probably seeking
++ * or something. Snooze for a couple msecs, then
++ * chk-status again. If still busy, queue delayed work.
++ */
++ status = ata_sff_busy_wait(ap, ATA_BUSY, 5);
++ if (status & ATA_BUSY) {
++ msleep(2);
++ status = ata_sff_busy_wait(ap, ATA_BUSY, 10);
++ if (status & ATA_BUSY) {
++ ata_pio_queue_task(ap, qc, ATA_SHORT_PAUSE);
++ return;
++ }
++ }
++
++ /* move the HSM */
++ poll_next = ata_sff_hsm_move(ap, qc, status, 1);
++
++ /* another command or interrupt handler
++ * may be running at this point.
++ */
++ if (poll_next)
++ goto fsm_start;
+ }
+
+ /**
+- * ata_bmdma_status - Read PCI IDE BMDMA status
+- * @ap: Port associated with this ATA transaction.
++ * ata_sff_qc_issue - issue taskfile to device in proto-dependent manner
++ * @qc: command to issue to device
+ *
+- * Read and return BMDMA status register.
++ * Using various libata functions and hooks, this function
++ * starts an ATA command. ATA commands are grouped into
++ * classes called "protocols", and issuing each type of protocol
++ * is slightly different.
+ *
+- * May be used as the bmdma_status() entry in ata_port_operations.
++ * May be used as the qc_issue() entry in ata_port_operations.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
++ *
++ * RETURNS:
++ * Zero on success, AC_ERR_* mask on failure
+ */
+-u8 ata_bmdma_status(struct ata_port *ap)
++unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
+ {
+- return ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
++ struct ata_port *ap = qc->ap;
++
++ /* Use polling pio if the LLD doesn't handle
++ * interrupt driven pio and atapi CDB interrupt.
++ */
++ if (ap->flags & ATA_FLAG_PIO_POLLING) {
++ switch (qc->tf.protocol) {
++ case ATA_PROT_PIO:
++ case ATA_PROT_NODATA:
++ case ATAPI_PROT_PIO:
++ case ATAPI_PROT_NODATA:
++ qc->tf.flags |= ATA_TFLAG_POLLING;
++ break;
++ case ATAPI_PROT_DMA:
++ if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
++ /* see ata_dma_blacklisted() */
++ BUG();
++ break;
++ default:
++ break;
++ }
++ }
++
++ /* select the device */
++ ata_dev_select(ap, qc->dev->devno, 1, 0);
++
++ /* start the command */
++ switch (qc->tf.protocol) {
++ case ATA_PROT_NODATA:
++ if (qc->tf.flags & ATA_TFLAG_POLLING)
++ ata_qc_set_polling(qc);
++
++ ata_tf_to_host(ap, &qc->tf);
++ ap->hsm_task_state = HSM_ST_LAST;
++
++ if (qc->tf.flags & ATA_TFLAG_POLLING)
++ ata_pio_queue_task(ap, qc, 0);
++
++ break;
++
++ case ATA_PROT_DMA:
++ WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
++
++ ap->ops->sff_tf_load(ap, &qc->tf); /* load tf registers */
++ ap->ops->bmdma_setup(qc); /* set up bmdma */
++ ap->ops->bmdma_start(qc); /* initiate bmdma */
++ ap->hsm_task_state = HSM_ST_LAST;
++ break;
++
++ case ATA_PROT_PIO:
++ if (qc->tf.flags & ATA_TFLAG_POLLING)
++ ata_qc_set_polling(qc);
++
++ ata_tf_to_host(ap, &qc->tf);
++
++ if (qc->tf.flags & ATA_TFLAG_WRITE) {
++ /* PIO data out protocol */
++ ap->hsm_task_state = HSM_ST_FIRST;
++ ata_pio_queue_task(ap, qc, 0);
++
++ /* always send first data block using
++ * the ata_pio_task() codepath.
++ */
++ } else {
++ /* PIO data in protocol */
++ ap->hsm_task_state = HSM_ST;
++
++ if (qc->tf.flags & ATA_TFLAG_POLLING)
++ ata_pio_queue_task(ap, qc, 0);
++
++ /* if polling, ata_pio_task() handles the rest.
++ * otherwise, interrupt handler takes over from here.
++ */
++ }
++
++ break;
++
++ case ATAPI_PROT_PIO:
++ case ATAPI_PROT_NODATA:
++ if (qc->tf.flags & ATA_TFLAG_POLLING)
++ ata_qc_set_polling(qc);
++
++ ata_tf_to_host(ap, &qc->tf);
++
++ ap->hsm_task_state = HSM_ST_FIRST;
++
++ /* send cdb by polling if no cdb interrupt */
++ if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
++ (qc->tf.flags & ATA_TFLAG_POLLING))
++ ata_pio_queue_task(ap, qc, 0);
++ break;
++
++ case ATAPI_PROT_DMA:
++ WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
++
++ ap->ops->sff_tf_load(ap, &qc->tf); /* load tf registers */
++ ap->ops->bmdma_setup(qc); /* set up bmdma */
++ ap->hsm_task_state = HSM_ST_FIRST;
++
++ /* send cdb by polling if no cdb interrupt */
++ if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
++ ata_pio_queue_task(ap, qc, 0);
++ break;
++
++ default:
++ WARN_ON(1);
++ return AC_ERR_SYSTEM;
++ }
++
++ return 0;
+ }
+
+ /**
+- * ata_bmdma_stop - Stop PCI IDE BMDMA transfer
+- * @qc: Command we are ending DMA for
++ * ata_sff_qc_fill_rtf - fill result TF using ->sff_tf_read
++ * @qc: qc to fill result TF for
+ *
+- * Clears the ATA_DMA_START flag in the dma control register
++ * @qc is finished and result TF needs to be filled. Fill it
++ * using ->sff_tf_read.
+ *
+- * May be used as the bmdma_stop() entry in ata_port_operations.
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ *
++ * RETURNS:
++ * true indicating that result TF is successfully filled.
++ */
++bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc)
++{
++ qc->ap->ops->sff_tf_read(qc->ap, &qc->result_tf);
++ return true;
++}
++
++/**
++ * ata_sff_host_intr - Handle host interrupt for given (port, task)
++ * @ap: Port on which interrupt arrived (possibly...)
++ * @qc: Taskfile currently active in engine
++ *
++ * Handle host interrupt for given queued command. Currently,
++ * only DMA interrupts are handled. All other commands are
++ * handled via polling with interrupts disabled (nIEN bit).
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
++ *
++ * RETURNS:
++ * One if interrupt was handled, zero if not (shared irq).
+ */
+-void ata_bmdma_stop(struct ata_queued_cmd *qc)
++inline unsigned int ata_sff_host_intr(struct ata_port *ap,
++ struct ata_queued_cmd *qc)
+ {
+- struct ata_port *ap = qc->ap;
+- void __iomem *mmio = ap->ioaddr.bmdma_addr;
++ struct ata_eh_info *ehi = &ap->link.eh_info;
++ u8 status, host_stat = 0;
+
+- /* clear start/stop bit */
+- iowrite8(ioread8(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
+- mmio + ATA_DMA_CMD);
++ VPRINTK("ata%u: protocol %d task_state %d\n",
++ ap->print_id, qc->tf.protocol, ap->hsm_task_state);
+
+- /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
+- ata_altstatus(ap); /* dummy read */
++ /* Check whether we are expecting interrupt in this state */
++ switch (ap->hsm_task_state) {
++ case HSM_ST_FIRST:
++ /* Some pre-ATAPI-4 devices assert INTRQ
++ * at this state when ready to receive CDB.
++ */
++
++ /* Check the ATA_DFLAG_CDB_INTR flag is enough here.
++ * The flag was turned on only for atapi devices. No
++ * need to check ata_is_atapi(qc->tf.protocol) again.
++ */
++ if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
++ goto idle_irq;
++ break;
++ case HSM_ST_LAST:
++ if (qc->tf.protocol == ATA_PROT_DMA ||
++ qc->tf.protocol == ATAPI_PROT_DMA) {
++ /* check status of DMA engine */
++ host_stat = ap->ops->bmdma_status(ap);
++ VPRINTK("ata%u: host_stat 0x%X\n",
++ ap->print_id, host_stat);
++
++ /* if it's not our irq... */
++ if (!(host_stat & ATA_DMA_INTR))
++ goto idle_irq;
++
++ /* before we do anything else, clear DMA-Start bit */
++ ap->ops->bmdma_stop(qc);
++
++ if (unlikely(host_stat & ATA_DMA_ERR)) {
++ /* error when transfering data to/from memory */
++ qc->err_mask |= AC_ERR_HOST_BUS;
++ ap->hsm_task_state = HSM_ST_ERR;
++ }
++ }
++ break;
++ case HSM_ST:
++ break;
++ default:
++ goto idle_irq;
++ }
++
++ /* check altstatus */
++ status = ata_sff_altstatus(ap);
++ if (status & ATA_BUSY)
++ goto idle_irq;
++
++ /* check main status, clearing INTRQ */
++ status = ap->ops->sff_check_status(ap);
++ if (unlikely(status & ATA_BUSY))
++ goto idle_irq;
++
++ /* ack bmdma irq events */
++ ap->ops->sff_irq_clear(ap);
++
++ ata_sff_hsm_move(ap, qc, status, 0);
++
++ if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
++ qc->tf.protocol == ATAPI_PROT_DMA))
++ ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
++
++ return 1; /* irq handled */
++
++idle_irq:
++ ap->stats.idle_irq++;
++
++#ifdef ATA_IRQ_TRAP
++ if ((ap->stats.idle_irq % 1000) == 0) {
++ ap->ops->sff_check_status(ap);
++ ap->ops->sff_irq_clear(ap);
++ ata_port_printk(ap, KERN_WARNING, "irq trap\n");
++ return 1;
++ }
++#endif
++ return 0; /* irq not handled */
++}
++
++/**
++ * ata_sff_interrupt - Default ATA host interrupt handler
++ * @irq: irq line (unused)
++ * @dev_instance: pointer to our ata_host information structure
++ *
++ * Default interrupt handler for PCI IDE devices. Calls
++ * ata_sff_host_intr() for each port that is not disabled.
++ *
++ * LOCKING:
++ * Obtains host lock during operation.
++ *
++ * RETURNS:
++ * IRQ_NONE or IRQ_HANDLED.
++ */
++irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
++{
++ struct ata_host *host = dev_instance;
++ unsigned int i;
++ unsigned int handled = 0;
++ unsigned long flags;
++
++ /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
++ spin_lock_irqsave(&host->lock, flags);
++
++ for (i = 0; i < host->n_ports; i++) {
++ struct ata_port *ap;
++
++ ap = host->ports[i];
++ if (ap &&
++ !(ap->flags & ATA_FLAG_DISABLED)) {
++ struct ata_queued_cmd *qc;
++
++ qc = ata_qc_from_tag(ap, ap->link.active_tag);
++ if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
++ (qc->flags & ATA_QCFLAG_ACTIVE))
++ handled |= ata_sff_host_intr(ap, qc);
++ }
++ }
++
++ spin_unlock_irqrestore(&host->lock, flags);
++
++ return IRQ_RETVAL(handled);
+ }
+
+ /**
+- * ata_bmdma_freeze - Freeze BMDMA controller port
++ * ata_sff_freeze - Freeze SFF controller port
+ * @ap: port to freeze
+ *
+ * Freeze BMDMA controller port.
+@@ -351,7 +1581,7 @@ void ata_bmdma_stop(struct ata_queued_cmd *qc)
+ * LOCKING:
+ * Inherited from caller.
+ */
+-void ata_bmdma_freeze(struct ata_port *ap)
++void ata_sff_freeze(struct ata_port *ap)
+ {
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+
+@@ -365,51 +1595,412 @@ void ata_bmdma_freeze(struct ata_port *ap)
+ * ATA_NIEN manipulation. Also, many controllers fail to mask
+ * previously pending IRQ on ATA_NIEN assertion. Clear it.
+ */
+- ata_chk_status(ap);
++ ap->ops->sff_check_status(ap);
+
+- ap->ops->irq_clear(ap);
++ ap->ops->sff_irq_clear(ap);
+ }
+
+ /**
+- * ata_bmdma_thaw - Thaw BMDMA controller port
++ * ata_sff_thaw - Thaw SFF controller port
+ * @ap: port to thaw
+ *
+- * Thaw BMDMA controller port.
++ * Thaw SFF controller port.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+-void ata_bmdma_thaw(struct ata_port *ap)
++void ata_sff_thaw(struct ata_port *ap)
+ {
+ /* clear & re-enable interrupts */
+- ata_chk_status(ap);
+- ap->ops->irq_clear(ap);
+- ap->ops->irq_on(ap);
++ ap->ops->sff_check_status(ap);
++ ap->ops->sff_irq_clear(ap);
++ ap->ops->sff_irq_on(ap);
++}
++
++/**
++ * ata_sff_prereset - prepare SFF link for reset
++ * @link: SFF link to be reset
++ * @deadline: deadline jiffies for the operation
++ *
++ * SFF link @link is about to be reset. Initialize it. It first
++ * calls ata_std_prereset() and wait for !BSY if the port is
++ * being softreset.
++ *
++ * LOCKING:
++ * Kernel thread context (may sleep)
++ *
++ * RETURNS:
++ * 0 on success, -errno otherwise.
++ */
++int ata_sff_prereset(struct ata_link *link, unsigned long deadline)
++{
++ struct ata_eh_context *ehc = &link->eh_context;
++ int rc;
++
++ rc = ata_std_prereset(link, deadline);
++ if (rc)
++ return rc;
++
++ /* if we're about to do hardreset, nothing more to do */
++ if (ehc->i.action & ATA_EH_HARDRESET)
++ return 0;
++
++ /* wait for !BSY if we don't know that no device is attached */
++ if (!ata_link_offline(link)) {
++ rc = ata_sff_wait_ready(link, deadline);
++ if (rc && rc != -ENODEV) {
++ ata_link_printk(link, KERN_WARNING, "device not ready "
++ "(errno=%d), forcing hardreset\n", rc);
++ ehc->i.action |= ATA_EH_HARDRESET;
++ }
++ }
++
++ return 0;
++}
++
++/**
++ * ata_devchk - PATA device presence detection
++ * @ap: ATA channel to examine
++ * @device: Device to examine (starting at zero)
++ *
++ * This technique was originally described in
++ * Hale Landis's ATADRVR (www.ata-atapi.com), and
++ * later found its way into the ATA/ATAPI spec.
++ *
++ * Write a pattern to the ATA shadow registers,
++ * and if a device is present, it will respond by
++ * correctly storing and echoing back the
++ * ATA shadow register contents.
++ *
++ * LOCKING:
++ * caller.
++ */
++static unsigned int ata_devchk(struct ata_port *ap, unsigned int device)
++{
++ struct ata_ioports *ioaddr = &ap->ioaddr;
++ u8 nsect, lbal;
++
++ ap->ops->sff_dev_select(ap, device);
++
++ iowrite8(0x55, ioaddr->nsect_addr);
++ iowrite8(0xaa, ioaddr->lbal_addr);
++
++ iowrite8(0xaa, ioaddr->nsect_addr);
++ iowrite8(0x55, ioaddr->lbal_addr);
++
++ iowrite8(0x55, ioaddr->nsect_addr);
++ iowrite8(0xaa, ioaddr->lbal_addr);
++
++ nsect = ioread8(ioaddr->nsect_addr);
++ lbal = ioread8(ioaddr->lbal_addr);
++
++ if ((nsect == 0x55) && (lbal == 0xaa))
++ return 1; /* we found a device */
++
++ return 0; /* nothing found */
++}
++
++/**
++ * ata_sff_dev_classify - Parse returned ATA device signature
++ * @dev: ATA device to classify (starting at zero)
++ * @present: device seems present
++ * @r_err: Value of error register on completion
++ *
++ * After an event -- SRST, E.D.D., or SATA COMRESET -- occurs,
++ * an ATA/ATAPI-defined set of values is placed in the ATA
++ * shadow registers, indicating the results of device detection
++ * and diagnostics.
++ *
++ * Select the ATA device, and read the values from the ATA shadow
++ * registers. Then parse according to the Error register value,
++ * and the spec-defined values examined by ata_dev_classify().
++ *
++ * LOCKING:
++ * caller.
++ *
++ * RETURNS:
++ * Device type - %ATA_DEV_ATA, %ATA_DEV_ATAPI or %ATA_DEV_NONE.
++ */
++unsigned int ata_sff_dev_classify(struct ata_device *dev, int present,
++ u8 *r_err)
++{
++ struct ata_port *ap = dev->link->ap;
++ struct ata_taskfile tf;
++ unsigned int class;
++ u8 err;
++
++ ap->ops->sff_dev_select(ap, dev->devno);
++
++ memset(&tf, 0, sizeof(tf));
++
++ ap->ops->sff_tf_read(ap, &tf);
++ err = tf.feature;
++ if (r_err)
++ *r_err = err;
++
++ /* see if device passed diags: continue and warn later */
++ if (err == 0)
++ /* diagnostic fail : do nothing _YET_ */
++ dev->horkage |= ATA_HORKAGE_DIAGNOSTIC;
++ else if (err == 1)
++ /* do nothing */ ;
++ else if ((dev->devno == 0) && (err == 0x81))
++ /* do nothing */ ;
++ else
++ return ATA_DEV_NONE;
++
++ /* determine if device is ATA or ATAPI */
++ class = ata_dev_classify(&tf);
++
++ if (class == ATA_DEV_UNKNOWN) {
++ /* If the device failed diagnostic, it's likely to
++ * have reported incorrect device signature too.
++ * Assume ATA device if the device seems present but
++ * device signature is invalid with diagnostic
++ * failure.
++ */
++ if (present && (dev->horkage & ATA_HORKAGE_DIAGNOSTIC))
++ class = ATA_DEV_ATA;
++ else
++ class = ATA_DEV_NONE;
++ } else if ((class == ATA_DEV_ATA) &&
++ (ap->ops->sff_check_status(ap) == 0))
++ class = ATA_DEV_NONE;
++
++ return class;
++}
++
++/**
++ * ata_sff_wait_after_reset - wait for devices to become ready after reset
++ * @link: SFF link which is just reset
++ * @devmask: mask of present devices
++ * @deadline: deadline jiffies for the operation
++ *
++ * Wait devices attached to SFF @link to become ready after
++ * reset. It contains preceding 150ms wait to avoid accessing TF
++ * status register too early.
++ *
++ * LOCKING:
++ * Kernel thread context (may sleep).
++ *
++ * RETURNS:
++ * 0 on success, -ENODEV if some or all of devices in @devmask
++ * don't seem to exist. -errno on other errors.
++ */
++int ata_sff_wait_after_reset(struct ata_link *link, unsigned int devmask,
++ unsigned long deadline)
++{
++ struct ata_port *ap = link->ap;
++ struct ata_ioports *ioaddr = &ap->ioaddr;
++ unsigned int dev0 = devmask & (1 << 0);
++ unsigned int dev1 = devmask & (1 << 1);
++ int rc, ret = 0;
++
++ msleep(ATA_WAIT_AFTER_RESET_MSECS);
++
++ /* always check readiness of the master device */
++ rc = ata_sff_wait_ready(link, deadline);
++ /* -ENODEV means the odd clown forgot the D7 pulldown resistor
++ * and TF status is 0xff, bail out on it too.
++ */
++ if (rc)
++ return rc;
++
++ /* if device 1 was found in ata_devchk, wait for register
++ * access briefly, then wait for BSY to clear.
++ */
++ if (dev1) {
++ int i;
++
++ ap->ops->sff_dev_select(ap, 1);
++
++ /* Wait for register access. Some ATAPI devices fail
++ * to set nsect/lbal after reset, so don't waste too
++ * much time on it. We're gonna wait for !BSY anyway.
++ */
++ for (i = 0; i < 2; i++) {
++ u8 nsect, lbal;
++
++ nsect = ioread8(ioaddr->nsect_addr);
++ lbal = ioread8(ioaddr->lbal_addr);
++ if ((nsect == 1) && (lbal == 1))
++ break;
++ msleep(50); /* give drive a breather */
++ }
++
++ rc = ata_sff_wait_ready(link, deadline);
++ if (rc) {
++ if (rc != -ENODEV)
++ return rc;
++ ret = rc;
++ }
++ }
++
++ /* is all this really necessary? */
++ ap->ops->sff_dev_select(ap, 0);
++ if (dev1)
++ ap->ops->sff_dev_select(ap, 1);
++ if (dev0)
++ ap->ops->sff_dev_select(ap, 0);
++
++ return ret;
++}
++
++static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
++ unsigned long deadline)
++{
++ struct ata_ioports *ioaddr = &ap->ioaddr;
++
++ DPRINTK("ata%u: bus reset via SRST\n", ap->print_id);
++
++ /* software reset. causes dev0 to be selected */
++ iowrite8(ap->ctl, ioaddr->ctl_addr);
++ udelay(20); /* FIXME: flush */
++ iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
++ udelay(20); /* FIXME: flush */
++ iowrite8(ap->ctl, ioaddr->ctl_addr);
++
++ /* wait the port to become ready */
++ return ata_sff_wait_after_reset(&ap->link, devmask, deadline);
++}
++
++/**
++ * ata_sff_softreset - reset host port via ATA SRST
++ * @link: ATA link to reset
++ * @classes: resulting classes of attached devices
++ * @deadline: deadline jiffies for the operation
++ *
++ * Reset host port using ATA SRST.
++ *
++ * LOCKING:
++ * Kernel thread context (may sleep)
++ *
++ * RETURNS:
++ * 0 on success, -errno otherwise.
++ */
++int ata_sff_softreset(struct ata_link *link, unsigned int *classes,
++ unsigned long deadline)
++{
++ struct ata_port *ap = link->ap;
++ unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
++ unsigned int devmask = 0;
++ int rc;
++ u8 err;
++
++ DPRINTK("ENTER\n");
++
++ /* determine if device 0/1 are present */
++ if (ata_devchk(ap, 0))
++ devmask |= (1 << 0);
++ if (slave_possible && ata_devchk(ap, 1))
++ devmask |= (1 << 1);
++
++ /* select device 0 again */
++ ap->ops->sff_dev_select(ap, 0);
++
++ /* issue bus reset */
++ DPRINTK("about to softreset, devmask=%x\n", devmask);
++ rc = ata_bus_softreset(ap, devmask, deadline);
++ /* if link is occupied, -ENODEV too is an error */
++ if (rc && (rc != -ENODEV || sata_scr_valid(link))) {
++ ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc);
++ return rc;
++ }
++
++ /* determine by signature whether we have ATA or ATAPI devices */
++ classes[0] = ata_sff_dev_classify(&link->device[0],
++ devmask & (1 << 0), &err);
++ if (slave_possible && err != 0x81)
++ classes[1] = ata_sff_dev_classify(&link->device[1],
++ devmask & (1 << 1), &err);
++
++ DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
++ return 0;
++}
++
++/**
++ * sata_sff_hardreset - reset host port via SATA phy reset
++ * @link: link to reset
++ * @class: resulting class of attached device
++ * @deadline: deadline jiffies for the operation
++ *
++ * SATA phy-reset host port using DET bits of SControl register,
++ * wait for !BSY and classify the attached device.
++ *
++ * LOCKING:
++ * Kernel thread context (may sleep)
++ *
++ * RETURNS:
++ * 0 on success, -errno otherwise.
++ */
++int sata_sff_hardreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline)
++{
++ struct ata_eh_context *ehc = &link->eh_context;
++ const unsigned long *timing = sata_ehc_deb_timing(ehc);
++ bool online;
++ int rc;
++
++ rc = sata_link_hardreset(link, timing, deadline, &online,
++ ata_sff_check_ready);
++ if (online)
++ *class = ata_sff_dev_classify(link->device, 1, NULL);
++
++ DPRINTK("EXIT, class=%u\n", *class);
++ return rc;
+ }
+
+ /**
+- * ata_bmdma_drive_eh - Perform EH with given methods for BMDMA controller
++ * ata_sff_postreset - SFF postreset callback
++ * @link: the target SFF ata_link
++ * @classes: classes of attached devices
++ *
++ * This function is invoked after a successful reset. It first
++ * calls ata_std_postreset() and performs SFF specific postreset
++ * processing.
++ *
++ * LOCKING:
++ * Kernel thread context (may sleep)
++ */
++void ata_sff_postreset(struct ata_link *link, unsigned int *classes)
++{
++ struct ata_port *ap = link->ap;
++
++ ata_std_postreset(link, classes);
++
++ /* is double-select really necessary? */
++ if (classes[0] != ATA_DEV_NONE)
++ ap->ops->sff_dev_select(ap, 1);
++ if (classes[1] != ATA_DEV_NONE)
++ ap->ops->sff_dev_select(ap, 0);
++
++ /* bail out if no device is present */
++ if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
++ DPRINTK("EXIT, no device\n");
++ return;
++ }
++
++ /* set up device control */
++ if (ap->ioaddr.ctl_addr)
++ iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
++}
++
++/**
++ * ata_sff_error_handler - Stock error handler for BMDMA controller
+ * @ap: port to handle error for
+- * @prereset: prereset method (can be NULL)
+- * @softreset: softreset method (can be NULL)
+- * @hardreset: hardreset method (can be NULL)
+- * @postreset: postreset method (can be NULL)
+ *
+- * Handle error for ATA BMDMA controller. It can handle both
++ * Stock error handler for SFF controller. It can handle both
+ * PATA and SATA controllers. Many controllers should be able to
+ * use this EH as-is or with some added handling before and
+ * after.
+ *
+- * This function is intended to be used for constructing
+- * ->error_handler callback by low level drivers.
+- *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+ */
+-void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+- ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+- ata_postreset_fn_t postreset)
++void ata_sff_error_handler(struct ata_port *ap)
+ {
++ ata_reset_fn_t softreset = ap->ops->softreset;
++ ata_reset_fn_t hardreset = ap->ops->hardreset;
+ struct ata_queued_cmd *qc;
+ unsigned long flags;
+ int thaw = 0;
+@@ -423,7 +2014,8 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+
+ ap->hsm_task_state = HSM_ST_IDLE;
+
+- if (qc && (qc->tf.protocol == ATA_PROT_DMA ||
++ if (ap->ioaddr.bmdma_addr &&
++ qc && (qc->tf.protocol == ATA_PROT_DMA ||
+ qc->tf.protocol == ATAPI_PROT_DMA)) {
+ u8 host_stat;
+
+@@ -442,9 +2034,9 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+ ap->ops->bmdma_stop(qc);
+ }
+
+- ata_altstatus(ap);
+- ata_chk_status(ap);
+- ap->ops->irq_clear(ap);
++ ata_sff_altstatus(ap);
++ ap->ops->sff_check_status(ap);
++ ap->ops->sff_irq_clear(ap);
+
+ spin_unlock_irqrestore(ap->lock, flags);
+
+@@ -452,40 +2044,27 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+ ata_eh_thaw_port(ap);
+
+ /* PIO and DMA engines have been stopped, perform recovery */
+- ata_do_eh(ap, prereset, softreset, hardreset, postreset);
+-}
+-
+-/**
+- * ata_bmdma_error_handler - Stock error handler for BMDMA controller
+- * @ap: port to handle error for
+- *
+- * Stock error handler for BMDMA controller.
+- *
+- * LOCKING:
+- * Kernel thread context (may sleep)
+- */
+-void ata_bmdma_error_handler(struct ata_port *ap)
+-{
+- ata_reset_fn_t softreset = NULL, hardreset = NULL;
+
+- if (ap->ioaddr.ctl_addr)
+- softreset = ata_std_softreset;
+- if (sata_scr_valid(&ap->link))
+- hardreset = sata_std_hardreset;
++ /* Ignore ata_sff_softreset if ctl isn't accessible and
++ * built-in hardresets if SCR access isn't available.
++ */
++ if (softreset == ata_sff_softreset && !ap->ioaddr.ctl_addr)
++ softreset = NULL;
++ if (ata_is_builtin_hardreset(hardreset) && !sata_scr_valid(&ap->link))
++ hardreset = NULL;
+
+- ata_bmdma_drive_eh(ap, ata_std_prereset, softreset, hardreset,
+- ata_std_postreset);
++ ata_do_eh(ap, ap->ops->prereset, softreset, hardreset,
++ ap->ops->postreset);
+ }
+
+ /**
+- * ata_bmdma_post_internal_cmd - Stock post_internal_cmd for
+- * BMDMA controller
++ * ata_sff_post_internal_cmd - Stock post_internal_cmd for SFF controller
+ * @qc: internal command to clean up
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+ */
+-void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
++void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc)
+ {
+ if (qc->ap->ioaddr.bmdma_addr)
+ ata_bmdma_stop(qc);
+@@ -504,7 +2083,6 @@ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
+ * LOCKING:
+ * Inherited from caller.
+ */
+-
+ int ata_sff_port_start(struct ata_port *ap)
+ {
+ if (ap->ioaddr.bmdma_addr)
+@@ -512,24 +2090,262 @@ int ata_sff_port_start(struct ata_port *ap)
+ return 0;
+ }
+
+-#ifdef CONFIG_PCI
++/**
++ * ata_sff_std_ports - initialize ioaddr with standard port offsets.
++ * @ioaddr: IO address structure to be initialized
++ *
++ * Utility function which initializes data_addr, error_addr,
++ * feature_addr, nsect_addr, lbal_addr, lbam_addr, lbah_addr,
++ * device_addr, status_addr, and command_addr to standard offsets
++ * relative to cmd_addr.
++ *
++ * Does not set ctl_addr, altstatus_addr, bmdma_addr, or scr_addr.
++ */
++void ata_sff_std_ports(struct ata_ioports *ioaddr)
++{
++ ioaddr->data_addr = ioaddr->cmd_addr + ATA_REG_DATA;
++ ioaddr->error_addr = ioaddr->cmd_addr + ATA_REG_ERR;
++ ioaddr->feature_addr = ioaddr->cmd_addr + ATA_REG_FEATURE;
++ ioaddr->nsect_addr = ioaddr->cmd_addr + ATA_REG_NSECT;
++ ioaddr->lbal_addr = ioaddr->cmd_addr + ATA_REG_LBAL;
++ ioaddr->lbam_addr = ioaddr->cmd_addr + ATA_REG_LBAM;
++ ioaddr->lbah_addr = ioaddr->cmd_addr + ATA_REG_LBAH;
++ ioaddr->device_addr = ioaddr->cmd_addr + ATA_REG_DEVICE;
++ ioaddr->status_addr = ioaddr->cmd_addr + ATA_REG_STATUS;
++ ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD;
++}
+
+-static int ata_resources_present(struct pci_dev *pdev, int port)
++unsigned long ata_bmdma_mode_filter(struct ata_device *adev,
++ unsigned long xfer_mask)
+ {
+- int i;
++ /* Filter out DMA modes if the device has been configured by
++ the BIOS as PIO only */
+
+- /* Check the PCI resources for this channel are enabled */
+- port = port * 2;
+- for (i = 0; i < 2; i ++) {
+- if (pci_resource_start(pdev, port + i) == 0 ||
+- pci_resource_len(pdev, port + i) == 0)
+- return 0;
++ if (adev->link->ap->ioaddr.bmdma_addr == NULL)
++ xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
++ return xfer_mask;
++}
++
++/**
++ * ata_bmdma_setup - Set up PCI IDE BMDMA transaction
++ * @qc: Info associated with this ATA transaction.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ */
++void ata_bmdma_setup(struct ata_queued_cmd *qc)
++{
++ struct ata_port *ap = qc->ap;
++ unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
++ u8 dmactl;
++
++ /* load PRD table addr. */
++ mb(); /* make sure PRD table writes are visible to controller */
++ iowrite32(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
++
++ /* specify data direction, triple-check start bit is clear */
++ dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++ dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
++ if (!rw)
++ dmactl |= ATA_DMA_WR;
++ iowrite8(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++
++ /* issue r/w command */
++ ap->ops->sff_exec_command(ap, &qc->tf);
++}
++
++/**
++ * ata_bmdma_start - Start a PCI IDE BMDMA transaction
++ * @qc: Info associated with this ATA transaction.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ */
++void ata_bmdma_start(struct ata_queued_cmd *qc)
++{
++ struct ata_port *ap = qc->ap;
++ u8 dmactl;
++
++ /* start host DMA transaction */
++ dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++ iowrite8(dmactl | ATA_DMA_START, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++
++ /* Strictly, one may wish to issue an ioread8() here, to
++ * flush the mmio write. However, control also passes
++ * to the hardware at this point, and it will interrupt
++ * us when we are to resume control. So, in effect,
++ * we don't care when the mmio write flushes.
++ * Further, a read of the DMA status register _immediately_
++ * following the write may not be what certain flaky hardware
++ * is expected, so I think it is best to not add a readb()
++ * without first all the MMIO ATA cards/mobos.
++ * Or maybe I'm just being paranoid.
++ *
++ * FIXME: The posting of this write means I/O starts are
++ * unneccessarily delayed for MMIO
++ */
++}
++
++/**
++ * ata_bmdma_stop - Stop PCI IDE BMDMA transfer
++ * @qc: Command we are ending DMA for
++ *
++ * Clears the ATA_DMA_START flag in the dma control register
++ *
++ * May be used as the bmdma_stop() entry in ata_port_operations.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ */
++void ata_bmdma_stop(struct ata_queued_cmd *qc)
++{
++ struct ata_port *ap = qc->ap;
++ void __iomem *mmio = ap->ioaddr.bmdma_addr;
++
++ /* clear start/stop bit */
++ iowrite8(ioread8(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
++ mmio + ATA_DMA_CMD);
++
++ /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
++ ata_sff_altstatus(ap); /* dummy read */
++}
++
++/**
++ * ata_bmdma_status - Read PCI IDE BMDMA status
++ * @ap: Port associated with this ATA transaction.
++ *
++ * Read and return BMDMA status register.
++ *
++ * May be used as the bmdma_status() entry in ata_port_operations.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ */
++u8 ata_bmdma_status(struct ata_port *ap)
++{
++ return ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
++}
++
++/**
++ * ata_bus_reset - reset host port and associated ATA channel
++ * @ap: port to reset
++ *
++ * This is typically the first time we actually start issuing
++ * commands to the ATA channel. We wait for BSY to clear, then
++ * issue EXECUTE DEVICE DIAGNOSTIC command, polling for its
++ * result. Determine what devices, if any, are on the channel
++ * by looking at the device 0/1 error register. Look at the signature
++ * stored in each device's taskfile registers, to determine if
++ * the device is ATA or ATAPI.
++ *
++ * LOCKING:
++ * PCI/etc. bus probe sem.
++ * Obtains host lock.
++ *
++ * SIDE EFFECTS:
++ * Sets ATA_FLAG_DISABLED if bus reset fails.
++ *
++ * DEPRECATED:
++ * This function is only for drivers which still use old EH and
++ * will be removed soon.
++ */
++void ata_bus_reset(struct ata_port *ap)
++{
++ struct ata_device *device = ap->link.device;
++ struct ata_ioports *ioaddr = &ap->ioaddr;
++ unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
++ u8 err;
++ unsigned int dev0, dev1 = 0, devmask = 0;
++ int rc;
++
++ DPRINTK("ENTER, host %u, port %u\n", ap->print_id, ap->port_no);
++
++ /* determine if device 0/1 are present */
++ if (ap->flags & ATA_FLAG_SATA_RESET)
++ dev0 = 1;
++ else {
++ dev0 = ata_devchk(ap, 0);
++ if (slave_possible)
++ dev1 = ata_devchk(ap, 1);
+ }
+- return 1;
++
++ if (dev0)
++ devmask |= (1 << 0);
++ if (dev1)
++ devmask |= (1 << 1);
++
++ /* select device 0 again */
++ ap->ops->sff_dev_select(ap, 0);
++
++ /* issue bus reset */
++ if (ap->flags & ATA_FLAG_SRST) {
++ rc = ata_bus_softreset(ap, devmask, jiffies + 40 * HZ);
++ if (rc && rc != -ENODEV)
++ goto err_out;
++ }
++
++ /*
++ * determine by signature whether we have ATA or ATAPI devices
++ */
++ device[0].class = ata_sff_dev_classify(&device[0], dev0, &err);
++ if ((slave_possible) && (err != 0x81))
++ device[1].class = ata_sff_dev_classify(&device[1], dev1, &err);
++
++ /* is double-select really necessary? */
++ if (device[1].class != ATA_DEV_NONE)
++ ap->ops->sff_dev_select(ap, 1);
++ if (device[0].class != ATA_DEV_NONE)
++ ap->ops->sff_dev_select(ap, 0);
++
++ /* if no devices were detected, disable this port */
++ if ((device[0].class == ATA_DEV_NONE) &&
++ (device[1].class == ATA_DEV_NONE))
++ goto err_out;
++
++ if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
++ /* set up device control for ATA_FLAG_SATA_RESET */
++ iowrite8(ap->ctl, ioaddr->ctl_addr);
++ }
++
++ DPRINTK("EXIT\n");
++ return;
++
++err_out:
++ ata_port_printk(ap, KERN_ERR, "disabling port\n");
++ ata_port_disable(ap);
++
++ DPRINTK("EXIT\n");
+ }
+
++#ifdef CONFIG_PCI
++
+ /**
+- * ata_pci_init_bmdma - acquire PCI BMDMA resources and init ATA host
++ * ata_pci_bmdma_clear_simplex - attempt to kick device out of simplex
++ * @pdev: PCI device
++ *
++ * Some PCI ATA devices report simplex mode but in fact can be told to
++ * enter non simplex mode. This implements the necessary logic to
++ * perform the task on such devices. Calling it on other devices will
++ * have -undefined- behaviour.
++ */
++int ata_pci_bmdma_clear_simplex(struct pci_dev *pdev)
++{
++ unsigned long bmdma = pci_resource_start(pdev, 4);
++ u8 simplex;
++
++ if (bmdma == 0)
++ return -ENOENT;
++
++ simplex = inb(bmdma + 0x02);
++ outb(simplex & 0x60, bmdma + 0x02);
++ simplex = inb(bmdma + 0x02);
++ if (simplex & 0x80)
++ return -EOPNOTSUPP;
++ return 0;
++}
++
++/**
++ * ata_pci_bmdma_init - acquire PCI BMDMA resources and init ATA host
+ * @host: target ATA host
+ *
+ * Acquire PCI BMDMA resources and initialize @host accordingly.
+@@ -540,7 +2356,7 @@ static int ata_resources_present(struct pci_dev *pdev, int port)
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+-int ata_pci_init_bmdma(struct ata_host *host)
++int ata_pci_bmdma_init(struct ata_host *host)
+ {
+ struct device *gdev = host->dev;
+ struct pci_dev *pdev = to_pci_dev(gdev);
+@@ -585,8 +2401,22 @@ int ata_pci_init_bmdma(struct ata_host *host)
+ return 0;
+ }
+
++static int ata_resources_present(struct pci_dev *pdev, int port)
++{
++ int i;
++
++ /* Check the PCI resources for this channel are enabled */
++ port = port * 2;
++ for (i = 0; i < 2; i ++) {
++ if (pci_resource_start(pdev, port + i) == 0 ||
++ pci_resource_len(pdev, port + i) == 0)
++ return 0;
++ }
++ return 1;
++}
++
+ /**
+- * ata_pci_init_sff_host - acquire native PCI ATA resources and init host
++ * ata_pci_sff_init_host - acquire native PCI ATA resources and init host
+ * @host: target ATA host
+ *
+ * Acquire native PCI ATA resources for @host and initialize the
+@@ -604,7 +2434,7 @@ int ata_pci_init_bmdma(struct ata_host *host)
+ * 0 if at least one port is initialized, -ENODEV if no port is
+ * available.
+ */
+-int ata_pci_init_sff_host(struct ata_host *host)
++int ata_pci_sff_init_host(struct ata_host *host)
+ {
+ struct device *gdev = host->dev;
+ struct pci_dev *pdev = to_pci_dev(gdev);
+@@ -646,7 +2476,7 @@ int ata_pci_init_sff_host(struct ata_host *host)
+ ap->ioaddr.altstatus_addr =
+ ap->ioaddr.ctl_addr = (void __iomem *)
+ ((unsigned long)iomap[base + 1] | ATA_PCI_CTL_OFS);
+- ata_std_ports(&ap->ioaddr);
++ ata_sff_std_ports(&ap->ioaddr);
+
+ ata_port_desc(ap, "cmd 0x%llx ctl 0x%llx",
+ (unsigned long long)pci_resource_start(pdev, base),
+@@ -664,7 +2494,7 @@ int ata_pci_init_sff_host(struct ata_host *host)
+ }
+
+ /**
+- * ata_pci_prepare_sff_host - helper to prepare native PCI ATA host
++ * ata_pci_sff_prepare_host - helper to prepare native PCI ATA host
+ * @pdev: target PCI device
+ * @ppi: array of port_info, must be enough for two ports
+ * @r_host: out argument for the initialized ATA host
+@@ -678,7 +2508,7 @@ int ata_pci_init_sff_host(struct ata_host *host)
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+-int ata_pci_prepare_sff_host(struct pci_dev *pdev,
++int ata_pci_sff_prepare_host(struct pci_dev *pdev,
+ const struct ata_port_info * const * ppi,
+ struct ata_host **r_host)
+ {
+@@ -696,12 +2526,12 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+ goto err_out;
+ }
+
+- rc = ata_pci_init_sff_host(host);
++ rc = ata_pci_sff_init_host(host);
+ if (rc)
+ goto err_out;
+
+ /* init DMA related stuff */
+- rc = ata_pci_init_bmdma(host);
++ rc = ata_pci_bmdma_init(host);
+ if (rc)
+ goto err_bmdma;
+
+@@ -722,7 +2552,7 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+ }
+
+ /**
+- * ata_pci_activate_sff_host - start SFF host, request IRQ and register it
++ * ata_pci_sff_activate_host - start SFF host, request IRQ and register it
+ * @host: target SFF ATA host
+ * @irq_handler: irq_handler used when requesting IRQ(s)
+ * @sht: scsi_host_template to use when registering the host
+@@ -737,7 +2567,7 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+-int ata_pci_activate_sff_host(struct ata_host *host,
++int ata_pci_sff_activate_host(struct ata_host *host,
+ irq_handler_t irq_handler,
+ struct scsi_host_template *sht)
+ {
+@@ -815,9 +2645,11 @@ int ata_pci_activate_sff_host(struct ata_host *host,
+ }
+
+ /**
+- * ata_pci_init_one - Initialize/register PCI IDE host controller
++ * ata_pci_sff_init_one - Initialize/register PCI IDE host controller
+ * @pdev: Controller to be initialized
+ * @ppi: array of port_info, must be enough for two ports
++ * @sht: scsi_host_template to use when registering the host
++ * @host_priv: host private_data
+ *
+ * This is a helper function which can be called from a driver's
+ * xxx_init_one() probe function if the hardware uses traditional
+@@ -837,8 +2669,9 @@ int ata_pci_activate_sff_host(struct ata_host *host,
+ * RETURNS:
+ * Zero on success, negative on errno-based value on error.
+ */
+-int ata_pci_init_one(struct pci_dev *pdev,
+- const struct ata_port_info * const * ppi)
++int ata_pci_sff_init_one(struct pci_dev *pdev,
++ const struct ata_port_info * const * ppi,
++ struct scsi_host_template *sht, void *host_priv)
+ {
+ struct device *dev = &pdev->dev;
+ const struct ata_port_info *pi = NULL;
+@@ -869,13 +2702,13 @@ int ata_pci_init_one(struct pci_dev *pdev,
+ goto out;
+
+ /* prepare and activate SFF host */
+- rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
++ rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+ if (rc)
+ goto out;
++ host->private_data = host_priv;
+
+ pci_set_master(pdev);
+- rc = ata_pci_activate_sff_host(host, pi->port_ops->irq_handler,
+- pi->sht);
++ rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);
+ out:
+ if (rc == 0)
+ devres_remove_group(&pdev->dev, NULL);
+@@ -885,41 +2718,52 @@ int ata_pci_init_one(struct pci_dev *pdev,
+ return rc;
+ }
+
+-/**
+- * ata_pci_clear_simplex - attempt to kick device out of simplex
+- * @pdev: PCI device
+- *
+- * Some PCI ATA devices report simplex mode but in fact can be told to
+- * enter non simplex mode. This implements the necessary logic to
+- * perform the task on such devices. Calling it on other devices will
+- * have -undefined- behaviour.
+- */
+-
+-int ata_pci_clear_simplex(struct pci_dev *pdev)
+-{
+- unsigned long bmdma = pci_resource_start(pdev, 4);
+- u8 simplex;
+-
+- if (bmdma == 0)
+- return -ENOENT;
+-
+- simplex = inb(bmdma + 0x02);
+- outb(simplex & 0x60, bmdma + 0x02);
+- simplex = inb(bmdma + 0x02);
+- if (simplex & 0x80)
+- return -EOPNOTSUPP;
+- return 0;
+-}
+-
+-unsigned long ata_pci_default_filter(struct ata_device *adev, unsigned long xfer_mask)
+-{
+- /* Filter out DMA modes if the device has been configured by
+- the BIOS as PIO only */
+-
+- if (adev->link->ap->ioaddr.bmdma_addr == NULL)
+- xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+- return xfer_mask;
+-}
+-
+ #endif /* CONFIG_PCI */
+
++EXPORT_SYMBOL_GPL(ata_sff_port_ops);
++EXPORT_SYMBOL_GPL(ata_bmdma_port_ops);
++EXPORT_SYMBOL_GPL(ata_sff_qc_prep);
++EXPORT_SYMBOL_GPL(ata_sff_dumb_qc_prep);
++EXPORT_SYMBOL_GPL(ata_sff_dev_select);
++EXPORT_SYMBOL_GPL(ata_sff_check_status);
++EXPORT_SYMBOL_GPL(ata_sff_altstatus);
++EXPORT_SYMBOL_GPL(ata_sff_busy_sleep);
++EXPORT_SYMBOL_GPL(ata_sff_wait_ready);
++EXPORT_SYMBOL_GPL(ata_sff_tf_load);
++EXPORT_SYMBOL_GPL(ata_sff_tf_read);
++EXPORT_SYMBOL_GPL(ata_sff_exec_command);
++EXPORT_SYMBOL_GPL(ata_sff_data_xfer);
++EXPORT_SYMBOL_GPL(ata_sff_data_xfer_noirq);
++EXPORT_SYMBOL_GPL(ata_sff_irq_on);
++EXPORT_SYMBOL_GPL(ata_sff_irq_clear);
++EXPORT_SYMBOL_GPL(ata_sff_hsm_move);
++EXPORT_SYMBOL_GPL(ata_sff_qc_issue);
++EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf);
++EXPORT_SYMBOL_GPL(ata_sff_host_intr);
++EXPORT_SYMBOL_GPL(ata_sff_interrupt);
++EXPORT_SYMBOL_GPL(ata_sff_freeze);
++EXPORT_SYMBOL_GPL(ata_sff_thaw);
++EXPORT_SYMBOL_GPL(ata_sff_prereset);
++EXPORT_SYMBOL_GPL(ata_sff_dev_classify);
++EXPORT_SYMBOL_GPL(ata_sff_wait_after_reset);
++EXPORT_SYMBOL_GPL(ata_sff_softreset);
++EXPORT_SYMBOL_GPL(sata_sff_hardreset);
++EXPORT_SYMBOL_GPL(ata_sff_postreset);
++EXPORT_SYMBOL_GPL(ata_sff_error_handler);
++EXPORT_SYMBOL_GPL(ata_sff_post_internal_cmd);
++EXPORT_SYMBOL_GPL(ata_sff_port_start);
++EXPORT_SYMBOL_GPL(ata_sff_std_ports);
++EXPORT_SYMBOL_GPL(ata_bmdma_mode_filter);
++EXPORT_SYMBOL_GPL(ata_bmdma_setup);
++EXPORT_SYMBOL_GPL(ata_bmdma_start);
++EXPORT_SYMBOL_GPL(ata_bmdma_stop);
++EXPORT_SYMBOL_GPL(ata_bmdma_status);
++EXPORT_SYMBOL_GPL(ata_bus_reset);
++#ifdef CONFIG_PCI
++EXPORT_SYMBOL_GPL(ata_pci_bmdma_clear_simplex);
++EXPORT_SYMBOL_GPL(ata_pci_bmdma_init);
++EXPORT_SYMBOL_GPL(ata_pci_sff_init_host);
++EXPORT_SYMBOL_GPL(ata_pci_sff_prepare_host);
++EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host);
++EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);
++#endif /* CONFIG_PCI */
+diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
+index aa884f7..4514283 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);
+@@ -133,43 +146,10 @@ extern void ata_scsi_scan_host(struct ata_port *ap, int sync);
+ extern int ata_scsi_offline_dev(struct ata_device *dev);
+ extern void ata_scsi_media_change_notify(struct ata_device *dev);
+ extern void ata_scsi_hotplug(struct work_struct *work);
+-extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen);
+-
+-extern unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen);
+-
+-extern unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen);
+-extern unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen);
+-extern unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen);
+-extern unsigned int ata_scsiop_sync_cache(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen);
+-extern unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen);
+-extern unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen);
+-extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
+- unsigned int buflen);
+-extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
+- void (*done)(struct scsi_cmnd *),
+- u8 asc, u8 ascq);
+-extern void ata_scsi_set_sense(struct scsi_cmnd *cmd,
+- u8 sk, u8 asc, u8 ascq);
+-extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
+- unsigned int (*actor) (struct ata_scsi_args *args,
+- u8 *rbuf, unsigned int buflen));
+ 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 +173,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..d7de7ba 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)
+@@ -93,8 +88,8 @@ static void atiixp_set_pio_timing(struct ata_port *ap, struct ata_device *adev,
+ pci_write_config_word(pdev, ATIIXP_IDE_PIO_MODE, pio_mode_data);
+
+ pci_read_config_word(pdev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data);
+- pio_mode_data &= ~(0xFF << timing_shift);
+- pio_mode_data |= (pio_timings[pio] << timing_shift);
++ pio_timing_data &= ~(0xFF << timing_shift);
++ pio_timing_data |= (pio_timings[pio] << timing_shift);
+ pci_write_config_word(pdev, ATIIXP_IDE_PIO_TIMING, pio_timing_data);
+ }
+
+@@ -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..9ab8973 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,34 +1258,34 @@ 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)
+ {
++ dev_dbg(ap->dev, "in atapi dma thaw\n");
+ bfin_check_status(ap);
+- bfin_irq_clear(ap);
+ bfin_irq_on(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");
+@@ -1356,52 +1339,157 @@ static int bfin_port_start(struct ata_port *ap)
+ return 0;
+ }
+
++static unsigned int bfin_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 is_atapi_taskfile(&qc->tf) 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 = ap->ops->sff_check_altstatus(ap);
++ if (status & ATA_BUSY)
++ goto busy_ata;
++
++ /* check main status, clearing INTRQ */
++ status = ap->ops->sff_check_status(ap);
++ if (unlikely(status & ATA_BUSY))
++ goto busy_ata;
++
++ /* 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);
++
++busy_ata:
++ return 1; /* irq handled */
++
++idle_irq:
++ ap->stats.idle_irq++;
++
++#ifdef ATA_IRQ_TRAP
++ if ((ap->stats.idle_irq % 1000) == 0) {
++ ap->ops->irq_ack(ap, 0); /* debug trap */
++ ata_port_printk(ap, KERN_WARNING, "irq trap\n");
++ return 1;
++ }
++#endif
++ return 0; /* irq not handled */
++}
++
++static irqreturn_t bfin_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 |= bfin_ata_host_intr(ap, qc);
++ }
++ }
++
++ spin_unlock_irqrestore(&host->lock, flags);
++
++ return IRQ_RETVAL(handled);
++}
++
++
+ 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 = {
++static 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,
+- .post_internal_cmd = bfin_bmdma_stop,
++ .freeze = bfin_freeze,
++ .thaw = bfin_thaw,
++ .softreset = bfin_softreset,
++ .postreset = bfin_postreset,
+
+- .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 +1497,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 +1533,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 +1623,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) {
++ bfin_ata_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 +1717,4 @@ MODULE_AUTHOR("Sonic Zhang <sonic.zhang at analog.com>");
+ MODULE_DESCRIPTION("PATA driver for blackfin 54x ATAPI controller");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(DRV_VERSION);
++MODULE_ALIAS("platform:" DRV_NAME);
+diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c
+index 43d198f..2de30b9 100644
+--- a/drivers/ata/pata_cmd640.c
++++ b/drivers/ata/pata_cmd640.c
+@@ -107,8 +107,8 @@ static void cmd640_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ pci_write_config_byte(pdev, arttim + 1, (t.active << 4) | t.recover);
+ } else {
+ /* Save the shared timings for channel, they will be loaded
+- by qc_issue_prot. Reloading the setup time is expensive
+- so we keep a merged one loaded */
++ by qc_issue. Reloading the setup time is expensive so we
++ keep a merged one loaded */
+ pci_read_config_byte(pdev, ARTIM23, ®);
+ reg &= 0x3F;
+ reg |= t.setup;
+@@ -119,14 +119,14 @@ static void cmd640_set_piomode(struct ata_port *ap, struct ata_device *adev)
+
+
+ /**
+- * cmd640_qc_issue_prot - command preparation hook
++ * cmd640_qc_issue - command preparation hook
+ * @qc: Command to be issued
+ *
+ * Channel 1 has shared timings. We must reprogram the
+ * clock each drive 2/3 switch we do.
+ */
+
+-static unsigned int cmd640_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int cmd640_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -137,7 +137,7 @@ static unsigned int cmd640_qc_issue_prot(struct ata_queued_cmd *qc)
+ pci_write_config_byte(pdev, DRWTIM23, timing->reg58[adev->devno]);
+ timing->last = adev->devno;
+ }
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ /**
+@@ -166,53 +166,16 @@ static int cmd640_port_start(struct ata_port *ap)
+ }
+
+ static struct scsi_host_template cmd640_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations cmd640_port_ops = {
+- .set_piomode = cmd640_set_piomode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_bmdma_port_ops,
++ /* In theory xfer_noirq is not needed once we kill the prefetcher */
++ .sff_data_xfer = ata_sff_data_xfer_noirq,
++ .qc_issue = cmd640_qc_issue,
+ .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = cmd640_qc_issue_prot,
+-
+- /* In theory this is not needed once we kill the prefetcher */
+- .data_xfer = ata_data_xfer_noirq,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
++ .set_piomode = cmd640_set_piomode,
+ .port_start = cmd640_port_start,
+ };
+
+@@ -248,26 +211,36 @@ static void cmd640_hardware_init(struct pci_dev *pdev)
+ static int cmd640_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &cmd640_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .port_ops = &cmd640_port_ops
+ };
+ const struct ata_port_info *ppi[] = { &info, NULL };
++ int rc;
++
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
+
+ cmd640_hardware_init(pdev);
+- return ata_pci_init_one(pdev, ppi);
++
++ return ata_pci_sff_init_one(pdev, ppi, &cmd640_sht, NULL);
+ }
+
++#ifdef CONFIG_PM
+ static int cmd640_reinit_one(struct pci_dev *pdev)
+ {
++ struct ata_host *host = dev_get_drvdata(&pdev->dev);
++ int rc;
++
++ rc = ata_pci_device_do_resume(pdev);
++ if (rc)
++ return rc;
+ cmd640_hardware_init(pdev);
+-#ifdef CONFIG_PM
+- return ata_pci_device_resume(pdev);
+-#else
++ ata_host_resume(host);
+ return 0;
+-#endif
+ }
++#endif
+
+ static const struct pci_device_id cmd640[] = {
+ { PCI_VDEVICE(CMD, 0x640), 0 },
+@@ -281,8 +254,8 @@ static struct pci_driver cmd640_pci_driver = {
+ .remove = ata_pci_remove_one,
+ #ifdef CONFIG_PM
+ .suspend = ata_pci_device_suspend,
+-#endif
+ .resume = cmd640_reinit_one,
++#endif
+ };
+
+ static int __init cmd640_init(void)
+diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
+index 7acbbd9..ddd09b7 100644
+--- a/drivers/ata/pata_cmd64x.c
++++ b/drivers/ata/pata_cmd64x.c
+@@ -266,120 +266,30 @@ static void cmd646r1_bmdma_stop(struct ata_queued_cmd *qc)
+ }
+
+ static struct scsi_host_template cmd64x_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations cmd64x_port_ops = {
++static const struct ata_port_operations cmd64x_base_ops = {
++ .inherits = &ata_bmdma_port_ops,
+ .set_piomode = cmd64x_set_piomode,
+ .set_dmamode = cmd64x_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_port_start,
+ };
+
+-static struct ata_port_operations cmd646r1_port_ops = {
+- .set_piomode = cmd64x_set_piomode,
+- .set_dmamode = cmd64x_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++static struct ata_port_operations cmd64x_port_ops = {
++ .inherits = &cmd64x_base_ops,
+ .cable_detect = ata_cable_40wire,
++};
+
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
++static struct ata_port_operations cmd646r1_port_ops = {
++ .inherits = &cmd64x_base_ops,
+ .bmdma_stop = cmd646r1_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_port_start,
++ .cable_detect = ata_cable_40wire,
+ };
+
+ static struct ata_port_operations cmd648_port_ops = {
+- .set_piomode = cmd64x_set_piomode,
+- .set_dmamode = cmd64x_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = cmd648_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
++ .inherits = &cmd64x_base_ops,
+ .bmdma_stop = cmd648_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_port_start,
++ .cable_detect = cmd648_cable_detect,
+ };
+
+ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+@@ -388,21 +298,18 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+
+ static const struct ata_port_info cmd_info[6] = {
+ { /* CMD 643 - no UDMA */
+- .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .port_ops = &cmd64x_port_ops
+ },
+ { /* CMD 646 with broken UDMA */
+- .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .port_ops = &cmd64x_port_ops
+ },
+ { /* CMD 646 with working UDMA */
+- .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -410,14 +317,12 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &cmd64x_port_ops
+ },
+ { /* CMD 646 rev 1 */
+- .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .port_ops = &cmd646r1_port_ops
+ },
+ { /* CMD 648 */
+- .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -425,7 +330,6 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &cmd648_port_ops
+ },
+ { /* CMD 649 */
+- .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -435,12 +339,17 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ };
+ const struct ata_port_info *ppi[] = { &cmd_info[id->driver_data], NULL };
+ u8 mrdmode;
++ int rc;
++
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
+
+ pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev);
+ class_rev &= 0xFF;
+
+ if (id->driver_data == 0) /* 643 */
+- ata_pci_clear_simplex(pdev);
++ ata_pci_bmdma_clear_simplex(pdev);
+
+ if (pdev->device == PCI_DEVICE_ID_CMD_646) {
+ /* Does UDMA work ? */
+@@ -464,13 +373,20 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
+ #endif
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &cmd64x_sht, NULL);
+ }
+
+ #ifdef CONFIG_PM
+ static int cmd64x_reinit_one(struct pci_dev *pdev)
+ {
++ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ u8 mrdmode;
++ int rc;
++
++ rc = ata_pci_device_do_resume(pdev);
++ if (rc)
++ return rc;
++
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
+ pci_read_config_byte(pdev, MRDMODE, &mrdmode);
+ mrdmode &= ~ 0x30; /* IRQ set up */
+@@ -479,7 +395,8 @@ static int cmd64x_reinit_one(struct pci_dev *pdev)
+ #ifdef CONFIG_PPC
+ pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
+ #endif
+- return ata_pci_device_resume(pdev);
++ ata_host_resume(host);
++ return 0;
+ }
+ #endif
+
+diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
+index 7ed279b..1186bcd 100644
+--- a/drivers/ata/pata_cs5520.c
++++ b/drivers/ata/pata_cs5520.c
+@@ -140,51 +140,16 @@ static void cs5520_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template cs5520_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
++ ATA_BMDMA_SHT(DRV_NAME),
+ .sg_tablesize = LIBATA_DUMB_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+ };
+
+ static struct ata_port_operations cs5520_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .qc_prep = ata_sff_dumb_qc_prep,
++ .cable_detect = ata_cable_40wire,
+ .set_piomode = cs5520_set_piomode,
+ .set_dmamode = cs5520_set_dmamode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_dumb_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+@@ -203,6 +168,10 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+ struct ata_ioports *ioaddr;
+ int i, rc;
+
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
++
+ /* IDE port enable bits */
+ pci_read_config_byte(pdev, 0x60, &pcicfg);
+
+@@ -258,7 +227,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+ ioaddr->ctl_addr = iomap[1];
+ ioaddr->altstatus_addr = iomap[1];
+ ioaddr->bmdma_addr = iomap[4];
+- ata_std_ports(ioaddr);
++ ata_sff_std_ports(ioaddr);
+
+ ata_port_desc(host->ports[0],
+ "cmd 0x%x ctl 0x%x", cmd_port[0], ctl_port[0]);
+@@ -269,7 +238,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+ ioaddr->ctl_addr = iomap[3];
+ ioaddr->altstatus_addr = iomap[3];
+ ioaddr->bmdma_addr = iomap[4] + 8;
+- ata_std_ports(ioaddr);
++ ata_sff_std_ports(ioaddr);
+
+ ata_port_desc(host->ports[1],
+ "cmd 0x%x ctl 0x%x", cmd_port[1], ctl_port[1]);
+@@ -289,7 +258,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+ continue;
+
+ rc = devm_request_irq(&pdev->dev, irq[ap->port_no],
+- ata_interrupt, 0, DRV_NAME, host);
++ ata_sff_interrupt, 0, DRV_NAME, host);
+ if (rc)
+ return rc;
+
+@@ -310,11 +279,20 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+
+ static int cs5520_reinit_one(struct pci_dev *pdev)
+ {
++ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ u8 pcicfg;
++ int rc;
++
++ rc = ata_pci_device_do_resume(pdev);
++ if (rc)
++ return rc;
++
+ pci_read_config_byte(pdev, 0x60, &pcicfg);
+ if ((pcicfg & 0x40) == 0)
+ pci_write_config_byte(pdev, 0x60, pcicfg | 0x40);
+- return ata_pci_device_resume(pdev);
++
++ ata_host_resume(host);
++ return 0;
+ }
+
+ /**
+diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
+index e1818fd..744beeb 100644
+--- a/drivers/ata/pata_cs5530.c
++++ b/drivers/ata/pata_cs5530.c
+@@ -133,7 +133,7 @@ static void cs5530_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * cs5530_qc_issue_prot - command issue
++ * cs5530_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+@@ -142,7 +142,7 @@ static void cs5530_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ * one MWDMA/UDMA bit.
+ */
+
+-static unsigned int cs5530_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int cs5530_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -157,59 +157,23 @@ static unsigned int cs5530_qc_issue_prot(struct ata_queued_cmd *qc)
+ cs5530_set_dmamode(ap, adev);
+ }
+
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static struct scsi_host_template cs5530_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_DUMB_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
++ .sg_tablesize = LIBATA_DUMB_MAX_PRD,
+ };
+
+ static struct ata_port_operations cs5530_port_ops = {
+- .set_piomode = cs5530_set_piomode,
+- .set_dmamode = cs5530_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_dumb_qc_prep,
+- .qc_issue = cs5530_qc_issue_prot,
++ .inherits = &ata_bmdma_port_ops,
+
+- .data_xfer = ata_data_xfer,
++ .qc_prep = ata_sff_dumb_qc_prep,
++ .qc_issue = cs5530_qc_issue,
+
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .cable_detect = ata_cable_40wire,
++ .set_piomode = cs5530_set_piomode,
++ .set_dmamode = cs5530_set_dmamode,
+ };
+
+ static const struct dmi_system_id palmax_dmi_table[] = {
+@@ -334,7 +298,6 @@ fail_put:
+ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &cs5530_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -343,12 +306,16 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ };
+ /* The docking connector doesn't do UDMA, and it seems not MWDMA */
+ static const struct ata_port_info info_palmax_secondary = {
+- .sht = &cs5530_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .port_ops = &cs5530_port_ops
+ };
+ const struct ata_port_info *ppi[] = { &info, NULL };
++ int rc;
++
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
+
+ /* Chip initialisation */
+ if (cs5530_init_chip())
+@@ -358,16 +325,25 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ ppi[1] = &info_palmax_secondary;
+
+ /* Now kick off ATA set up */
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &cs5530_sht, NULL);
+ }
+
+ #ifdef CONFIG_PM
+ static int cs5530_reinit_one(struct pci_dev *pdev)
+ {
++ struct ata_host *host = dev_get_drvdata(&pdev->dev);
++ int rc;
++
++ rc = ata_pci_device_do_resume(pdev);
++ if (rc)
++ return rc;
++
+ /* If we fail on resume we are doomed */
+ if (cs5530_init_chip())
+- BUG();
+- return ata_pci_device_resume(pdev);
++ return -EIO;
++
++ ata_host_resume(host);
++ return 0;
+ }
+ #endif /* CONFIG_PM */
+
+diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
+index 0132453..f1b6556 100644
+--- a/drivers/ata/pata_cs5535.c
++++ b/drivers/ata/pata_cs5535.c
+@@ -158,55 +158,14 @@ static void cs5535_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template cs5535_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations cs5535_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = cs5535_cable_detect,
+ .set_piomode = cs5535_set_piomode,
+ .set_dmamode = cs5535_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = cs5535_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /**
+@@ -222,7 +181,6 @@ static struct ata_port_operations cs5535_port_ops = {
+ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &cs5535_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -241,7 +199,7 @@ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ rdmsr(ATAC_CH0D1_PIO, timings, dummy);
+ if (CS5535_BAD_PIO(timings))
+ wrmsr(ATAC_CH0D1_PIO, 0xF7F4F7F4UL, 0);
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &cs5535_sht, NULL);
+ }
+
+ static const struct pci_device_id cs5535[] = {
+diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c
+index 1c4ff9b..73f8332 100644
+--- a/drivers/ata/pata_cs5536.c
++++ b/drivers/ata/pata_cs5536.c
+@@ -221,55 +221,14 @@ static void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template cs5536_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations cs5536_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = cs5536_cable_detect,
+ .set_piomode = cs5536_set_piomode,
+ .set_dmamode = cs5536_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = cs5536_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_port_start,
+ };
+
+ /**
+@@ -282,7 +241,6 @@ static struct ata_port_operations cs5536_port_ops = {
+ static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &cs5536_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -303,7 +261,7 @@ static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ return -ENODEV;
+ }
+
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &cs5536_sht, NULL);
+ }
+
+ static const struct pci_device_id cs5536[] = {
+diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c
+index fc5f9c4..a9c3218 100644
+--- a/drivers/ata/pata_cypress.c
++++ b/drivers/ata/pata_cypress.c
+@@ -110,61 +110,19 @@ static void cy82c693_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template cy82c693_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations cy82c693_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = ata_cable_40wire,
+ .set_piomode = cy82c693_set_piomode,
+ .set_dmamode = cy82c693_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &cy82c693_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -178,7 +136,7 @@ static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *i
+ if (PCI_FUNC(pdev->devfn) != 1)
+ return -ENODEV;
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &cy82c693_sht, NULL);
+ }
+
+ static const struct pci_device_id cy82c693[] = {
+diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
+index dc33220..9fba829 100644
+--- a/drivers/ata/pata_efar.c
++++ b/drivers/ata/pata_efar.c
+@@ -45,20 +45,7 @@ static int efar_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (!pci_test_config_bits(pdev, &efar_enable_bits[ap->port_no]))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * efar_probe_reset - Probe specified port on PATA host controller
+- * @ap: Port to probe
+- *
+- * LOCKING:
+- * None (inherited from caller).
+- */
+-
+-static void efar_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, efar_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -233,53 +220,15 @@ static void efar_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template efar_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations efar_ops = {
++static struct ata_port_operations efar_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = efar_cable_detect,
+ .set_piomode = efar_set_piomode,
+ .set_dmamode = efar_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = efar_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = efar_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .prereset = efar_pre_reset,
+ };
+
+
+@@ -301,7 +250,6 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ static int printed_version;
+ static const struct ata_port_info info = {
+- .sht = &efar_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma1-2 */
+@@ -314,7 +262,7 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &efar_sht, NULL);
+ }
+
+ static const struct pci_device_id efar_pci_tbl[] = {
+diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
+index a742efa..f2b83ea 100644
+--- a/drivers/ata/pata_hpt366.c
++++ b/drivers/ata/pata_hpt366.c
+@@ -184,7 +184,7 @@ static unsigned long hpt366_filter(struct ata_device *adev, unsigned long mask)
+ if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4))
+ mask &= ~(0xF0 << ATA_SHIFT_UDMA);
+ }
+- return ata_pci_default_filter(adev, mask);
++ return ata_bmdma_mode_filter(adev, mask);
+ }
+
+ /**
+@@ -290,21 +290,7 @@ static void hpt366_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template hpt36x_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ /*
+@@ -312,37 +298,11 @@ static struct scsi_host_template hpt36x_sht = {
+ */
+
+ static struct ata_port_operations hpt366_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = hpt36x_cable_detect,
++ .mode_filter = hpt366_filter,
+ .set_piomode = hpt366_set_piomode,
+ .set_dmamode = hpt366_set_dmamode,
+- .mode_filter = hpt366_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = hpt36x_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /**
+@@ -390,18 +350,22 @@ static void hpt36x_init_chipset(struct pci_dev *dev)
+ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info_hpt366 = {
+- .sht = &hpt36x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = ATA_UDMA4,
+ .port_ops = &hpt366_port_ops
+ };
+- struct ata_port_info info = info_hpt366;
+- const struct ata_port_info *ppi[] = { &info, NULL };
++ const struct ata_port_info *ppi[] = { &info_hpt366, NULL };
+
++ void *hpriv = NULL;
+ u32 class_rev;
+ u32 reg1;
++ int rc;
++
++ rc = pcim_enable_device(dev);
++ if (rc)
++ return rc;
+
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ class_rev &= 0xFF;
+@@ -419,24 +383,31 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ /* info_hpt366 is safe against re-entry so we can scribble on it */
+ switch((reg1 & 0x700) >> 8) {
+ case 5:
+- info.private_data = &hpt366_40;
++ hpriv = &hpt366_40;
+ break;
+ case 9:
+- info.private_data = &hpt366_25;
++ hpriv = &hpt366_25;
+ break;
+ default:
+- info.private_data = &hpt366_33;
++ hpriv = &hpt366_33;
+ break;
+ }
+ /* Now kick off ATA set up */
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &hpt36x_sht, hpriv);
+ }
+
+ #ifdef CONFIG_PM
+ static int hpt36x_reinit_one(struct pci_dev *dev)
+ {
++ struct ata_host *host = dev_get_drvdata(&dev->dev);
++ int rc;
++
++ rc = ata_pci_device_do_resume(dev);
++ if (rc)
++ return rc;
+ hpt36x_init_chipset(dev);
+- return ata_pci_device_resume(dev);
++ ata_host_resume(host);
++ return 0;
+ }
+ #endif
+
+diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
+index 9a10878..4216399 100644
+--- a/drivers/ata/pata_hpt37x.c
++++ b/drivers/ata/pata_hpt37x.c
+@@ -283,7 +283,7 @@ static unsigned long hpt370_filter(struct ata_device *adev, unsigned long mask)
+ if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5))
+ mask &= ~(0xE0 << ATA_SHIFT_UDMA);
+ }
+- return ata_pci_default_filter(adev, mask);
++ return ata_bmdma_mode_filter(adev, mask);
+ }
+
+ /**
+@@ -299,7 +299,7 @@ static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask)
+ if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5))
+ mask &= ~(0xE0 << ATA_SHIFT_UDMA);
+ }
+- return ata_pci_default_filter(adev, mask);
++ return ata_bmdma_mode_filter(adev, mask);
+ }
+
+ /**
+@@ -338,22 +338,10 @@ static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline)
+ pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
+ udelay(100);
+
+- return ata_std_prereset(link, deadline);
++ return ata_sff_prereset(link, deadline);
+ }
+
+-/**
+- * hpt37x_error_handler - reset the hpt374
+- * @ap: ATA port to reset
+- *
+- * Perform probe for HPT37x, except for HPT374 channel 2
+- */
+-
+-static void hpt37x_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, hpt37x_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+-}
+-
+-static int hpt374_pre_reset(struct ata_link *link, unsigned long deadline)
++static int hpt374_fn1_pre_reset(struct ata_link *link, unsigned long deadline)
+ {
+ static const struct pci_bits hpt37x_enable_bits[] = {
+ { 0x50, 1, 0x04, 0x04 },
+@@ -386,26 +374,7 @@ static int hpt374_pre_reset(struct ata_link *link, unsigned long deadline)
+ pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
+ udelay(100);
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * hpt374_error_handler - reset the hpt374
+- * @classes:
+- *
+- * The 374 cable detect is a little different due to the extra
+- * channels. The function 0 channels work like usual but function 1
+- * is special
+- */
+-
+-static void hpt374_error_handler(struct ata_port *ap)
+-{
+- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+-
+- if (!(PCI_FUNC(pdev->devfn) & 1))
+- hpt37x_error_handler(ap);
+- else
+- ata_bmdma_drive_eh(ap, hpt374_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -619,21 +588,7 @@ static void hpt37x_bmdma_stop(struct ata_queued_cmd *qc)
+
+
+ static struct scsi_host_template hpt37x_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ /*
+@@ -641,36 +596,15 @@ static struct scsi_host_template hpt37x_sht = {
+ */
+
+ static struct ata_port_operations hpt370_port_ops = {
+- .set_piomode = hpt370_set_piomode,
+- .set_dmamode = hpt370_set_dmamode,
+- .mode_filter = hpt370_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
++ .inherits = &ata_bmdma_port_ops,
+
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = hpt37x_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- .bmdma_setup = ata_bmdma_setup,
+ .bmdma_start = hpt370_bmdma_start,
+ .bmdma_stop = hpt370_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+
+- .port_start = ata_sff_port_start,
++ .mode_filter = hpt370_filter,
++ .set_piomode = hpt370_set_piomode,
++ .set_dmamode = hpt370_set_dmamode,
++ .prereset = hpt37x_pre_reset,
+ };
+
+ /*
+@@ -678,36 +612,8 @@ static struct ata_port_operations hpt370_port_ops = {
+ */
+
+ static struct ata_port_operations hpt370a_port_ops = {
+- .set_piomode = hpt370_set_piomode,
+- .set_dmamode = hpt370_set_dmamode,
++ .inherits = &hpt370_port_ops,
+ .mode_filter = hpt370a_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = hpt37x_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = hpt370_bmdma_start,
+- .bmdma_stop = hpt370_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /*
+@@ -716,74 +622,23 @@ static struct ata_port_operations hpt370a_port_ops = {
+ */
+
+ static struct ata_port_operations hpt372_port_ops = {
+- .set_piomode = hpt372_set_piomode,
+- .set_dmamode = hpt372_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
++ .inherits = &ata_bmdma_port_ops,
+
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = hpt37x_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+ .bmdma_stop = hpt37x_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+
+- .port_start = ata_sff_port_start,
++ .set_piomode = hpt372_set_piomode,
++ .set_dmamode = hpt372_set_dmamode,
++ .prereset = hpt37x_pre_reset,
+ };
+
+ /*
+ * Configuration for HPT374. Mode setting works like 372 and friends
+- * but we have a different cable detection procedure.
++ * but we have a different cable detection procedure for function 1.
+ */
+
+-static struct ata_port_operations hpt374_port_ops = {
+- .set_piomode = hpt372_set_piomode,
+- .set_dmamode = hpt372_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = hpt374_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = hpt37x_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++static struct ata_port_operations hpt374_fn1_port_ops = {
++ .inherits = &hpt372_port_ops,
++ .prereset = hpt374_fn1_pre_reset,
+ };
+
+ /**
+@@ -897,7 +752,6 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ /* HPT370 - UDMA100 */
+ static const struct ata_port_info info_hpt370 = {
+- .sht = &hpt37x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -906,7 +760,6 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ };
+ /* HPT370A - UDMA100 */
+ static const struct ata_port_info info_hpt370a = {
+- .sht = &hpt37x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -915,7 +768,6 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ };
+ /* HPT370 - UDMA100 */
+ static const struct ata_port_info info_hpt370_33 = {
+- .sht = &hpt37x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -924,7 +776,6 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ };
+ /* HPT370A - UDMA100 */
+ static const struct ata_port_info info_hpt370a_33 = {
+- .sht = &hpt37x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -933,28 +784,31 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ };
+ /* HPT371, 372 and friends - UDMA133 */
+ static const struct ata_port_info info_hpt372 = {
+- .sht = &hpt37x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &hpt372_port_ops
+ };
+- /* HPT374 - UDMA100 */
+- static const struct ata_port_info info_hpt374 = {
+- .sht = &hpt37x_sht,
++ /* HPT374 - UDMA100, function 1 uses different prereset method */
++ static const struct ata_port_info info_hpt374_fn0 = {
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = ATA_UDMA5,
+- .port_ops = &hpt374_port_ops
++ .port_ops = &hpt372_port_ops
++ };
++ static const struct ata_port_info info_hpt374_fn1 = {
++ .flags = ATA_FLAG_SLAVE_POSS,
++ .pio_mask = 0x1f,
++ .mwdma_mask = 0x07,
++ .udma_mask = ATA_UDMA5,
++ .port_ops = &hpt374_fn1_port_ops
+ };
+
+ static const int MHz[4] = { 33, 40, 50, 66 };
+- const struct ata_port_info *port;
+ void *private_data = NULL;
+- struct ata_port_info port_info;
+- const struct ata_port_info *ppi[] = { &port_info, NULL };
++ const struct ata_port_info *ppi[] = { NULL, NULL };
+
+ u8 irqmask;
+ u32 class_rev;
+@@ -966,6 +820,11 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+
+ const struct hpt_chip *chip_table;
+ int clock_slot;
++ int rc;
++
++ rc = pcim_enable_device(dev);
++ if (rc)
++ return rc;
+
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ class_rev &= 0xFF;
+@@ -981,17 +840,17 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+
+ switch(class_rev) {
+ case 3:
+- port = &info_hpt370;
++ ppi[0] = &info_hpt370;
+ chip_table = &hpt370;
+ prefer_dpll = 0;
+ break;
+ case 4:
+- port = &info_hpt370a;
++ ppi[0] = &info_hpt370a;
+ chip_table = &hpt370a;
+ prefer_dpll = 0;
+ break;
+ case 5:
+- port = &info_hpt372;
++ ppi[0] = &info_hpt372;
+ chip_table = &hpt372;
+ break;
+ default:
+@@ -1004,21 +863,21 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ /* 372N if rev >= 2*/
+ if (class_rev >= 2)
+ return -ENODEV;
+- port = &info_hpt372;
++ ppi[0] = &info_hpt372;
+ chip_table = &hpt372a;
+ break;
+ case PCI_DEVICE_ID_TTI_HPT302:
+ /* 302N if rev > 1 */
+ if (class_rev > 1)
+ return -ENODEV;
+- port = &info_hpt372;
++ ppi[0] = &info_hpt372;
+ /* Check this */
+ chip_table = &hpt302;
+ break;
+ case PCI_DEVICE_ID_TTI_HPT371:
+ if (class_rev > 1)
+ return -ENODEV;
+- port = &info_hpt372;
++ ppi[0] = &info_hpt372;
+ chip_table = &hpt371;
+ /* Single channel device, master is not present
+ but the BIOS (or us for non x86) must mark it
+@@ -1029,7 +888,10 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ break;
+ case PCI_DEVICE_ID_TTI_HPT374:
+ chip_table = &hpt374;
+- port = &info_hpt374;
++ if (!(PCI_FUNC(dev->devfn) & 1))
++ *ppi = &info_hpt374_fn0;
++ else
++ *ppi = &info_hpt374_fn1;
+ break;
+ default:
+ printk(KERN_ERR "pata_hpt37x: PCI table is bogus please report (%d).\n", dev->device);
+@@ -1108,7 +970,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ int dpll, adjust;
+
+ /* Compute DPLL */
+- dpll = (port->udma_mask & 0xC0) ? 3 : 2;
++ dpll = (ppi[0]->udma_mask & 0xC0) ? 3 : 2;
+
+ f_low = (MHz[clock_slot] * 48) / MHz[dpll];
+ f_high = f_low + 2;
+@@ -1148,19 +1010,16 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ * about lack of UDMA133 support on lower clocks
+ */
+
+- if (clock_slot < 2 && port == &info_hpt370)
+- port = &info_hpt370_33;
+- if (clock_slot < 2 && port == &info_hpt370a)
+- port = &info_hpt370a_33;
++ if (clock_slot < 2 && ppi[0] == &info_hpt370)
++ ppi[0] = &info_hpt370_33;
++ if (clock_slot < 2 && ppi[0] == &info_hpt370a)
++ ppi[0] = &info_hpt370a_33;
+ printk(KERN_INFO "pata_hpt37x: %s using %dMHz bus clock.\n",
+ chip_table->name, MHz[clock_slot]);
+ }
+
+ /* Now kick off ATA set up */
+- port_info = *port;
+- port_info.private_data = private_data;
+-
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &hpt37x_sht, private_data);
+ }
+
+ static const struct pci_device_id hpt37x[] = {
+diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
+index 9f1c084..d5c9fd7 100644
+--- a/drivers/ata/pata_hpt3x2n.c
++++ b/drivers/ata/pata_hpt3x2n.c
+@@ -148,7 +148,7 @@ static int hpt3x2n_cable_detect(struct ata_port *ap)
+ * Reset the hardware and state machine,
+ */
+
+-static int hpt3xn_pre_reset(struct ata_link *link, unsigned long deadline)
++static int hpt3x2n_pre_reset(struct ata_link *link, unsigned long deadline)
+ {
+ struct ata_port *ap = link->ap;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+@@ -156,19 +156,7 @@ static int hpt3xn_pre_reset(struct ata_link *link, unsigned long deadline)
+ pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
+ udelay(100);
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * hpt3x2n_error_handler - probe the hpt3x2n bus
+- * @ap: ATA port to reset
+- *
+- * Perform the probe reset handling for the 3x2N
+- */
+-
+-static void hpt3x2n_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, hpt3xn_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -320,7 +308,7 @@ static int hpt3x2n_use_dpll(struct ata_port *ap, int writing)
+ return 0;
+ }
+
+-static unsigned int hpt3x2n_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int hpt3x2n_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_taskfile *tf = &qc->tf;
+ struct ata_port *ap = qc->ap;
+@@ -335,25 +323,11 @@ static unsigned int hpt3x2n_qc_issue_prot(struct ata_queued_cmd *qc)
+ hpt3x2n_set_clock(ap, 0x23);
+ }
+ }
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static struct scsi_host_template hpt3x2n_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ /*
+@@ -361,37 +335,15 @@ static struct scsi_host_template hpt3x2n_sht = {
+ */
+
+ static struct ata_port_operations hpt3x2n_port_ops = {
+- .set_piomode = hpt3x2n_set_piomode,
+- .set_dmamode = hpt3x2n_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = hpt3x2n_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = hpt3x2n_cable_detect,
++ .inherits = &ata_bmdma_port_ops,
+
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+ .bmdma_stop = hpt3x2n_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = hpt3x2n_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
++ .qc_issue = hpt3x2n_qc_issue,
+
+- .port_start = ata_sff_port_start,
++ .cable_detect = hpt3x2n_cable_detect,
++ .set_piomode = hpt3x2n_set_piomode,
++ .set_dmamode = hpt3x2n_set_dmamode,
++ .prereset = hpt3x2n_pre_reset,
+ };
+
+ /**
+@@ -488,15 +440,13 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ /* HPT372N and friends - UDMA133 */
+ static const struct ata_port_info info = {
+- .sht = &hpt3x2n_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &hpt3x2n_port_ops
+ };
+- struct ata_port_info port = info;
+- const struct ata_port_info *ppi[] = { &port, NULL };
++ const struct ata_port_info *ppi[] = { &info, NULL };
+
+ u8 irqmask;
+ u32 class_rev;
+@@ -505,6 +455,12 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ unsigned int f_low, f_high;
+ int adjust;
+ unsigned long iobase = pci_resource_start(dev, 4);
++ void *hpriv = NULL;
++ int rc;
++
++ rc = pcim_enable_device(dev);
++ if (rc)
++ return rc;
+
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ class_rev &= 0xFF;
+@@ -586,9 +542,8 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ pci_mhz);
+ /* Set our private data up. We only need a few flags so we use
+ it directly */
+- port.private_data = NULL;
+ if (pci_mhz > 60) {
+- port.private_data = (void *)PCI66;
++ hpriv = (void *)PCI66;
+ /*
+ * On HPT371N, if ATA clock is 66 MHz we must set bit 2 in
+ * the MISC. register to stretch the UltraDMA Tss timing.
+@@ -599,7 +554,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ }
+
+ /* Now kick off ATA set up */
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &hpt3x2n_sht, hpriv);
+ }
+
+ static const struct pci_device_id hpt3x2n[] = {
+diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
+index cb8bdb6..f11a320 100644
+--- a/drivers/ata/pata_hpt3x3.c
++++ b/drivers/ata/pata_hpt3x3.c
+@@ -102,58 +102,17 @@ static int hpt3x3_atapi_dma(struct ata_queued_cmd *qc)
+ }
+
+ static struct scsi_host_template hpt3x3_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations hpt3x3_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .check_atapi_dma= hpt3x3_atapi_dma,
++ .cable_detect = ata_cable_40wire,
+ .set_piomode = hpt3x3_set_piomode,
+ #if defined(CONFIG_PATA_HPT3X3_DMA)
+ .set_dmamode = hpt3x3_set_dmamode,
+ #endif
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .check_atapi_dma= hpt3x3_atapi_dma,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /**
+@@ -189,7 +148,6 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ static int printed_version;
+ static const struct ata_port_info info = {
+- .sht = &hpt3x3_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ #if defined(CONFIG_PATA_HPT3X3_DMA)
+@@ -244,15 +202,15 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ ioaddr->altstatus_addr =
+ ioaddr->ctl_addr = base + offset_ctl[i];
+ ioaddr->scr_addr = NULL;
+- ata_std_ports(ioaddr);
++ ata_sff_std_ports(ioaddr);
+ ioaddr->bmdma_addr = base + 8 * i;
+
+ ata_port_pbar_desc(ap, 4, -1, "ioport");
+ ata_port_pbar_desc(ap, 4, offset_cmd[i], "cmd");
+ }
+ pci_set_master(pdev);
+- return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+- &hpt3x3_sht);
++ return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++ IRQF_SHARED, &hpt3x3_sht);
+ }
+
+ #ifdef CONFIG_PM
+diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
+index f97068b..1713843 100644
+--- a/drivers/ata/pata_icside.c
++++ b/drivers/ata/pata_icside.c
+@@ -250,7 +250,7 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)
+ set_dma_mode(state->dma, write ? DMA_MODE_WRITE : DMA_MODE_READ);
+
+ /* issue r/w command */
+- ap->ops->exec_command(ap, &qc->tf);
++ ap->ops->sff_exec_command(ap, &qc->tf);
+ }
+
+ static void pata_icside_bmdma_start(struct ata_queued_cmd *qc)
+@@ -270,7 +270,7 @@ static void pata_icside_bmdma_stop(struct ata_queued_cmd *qc)
+ disable_dma(state->dma);
+
+ /* see ata_bmdma_stop */
+- ata_altstatus(ap);
++ ata_sff_altstatus(ap);
+ }
+
+ static u8 pata_icside_bmdma_status(struct ata_port *ap)
+@@ -305,35 +305,18 @@ static int icside_dma_init(struct pata_icside_info *info)
+
+
+ static struct scsi_host_template pata_icside_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
++ ATA_BASE_SHT(DRV_NAME),
+ .sg_tablesize = PATA_ICSIDE_MAX_SG,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+ .dma_boundary = ~0, /* no dma boundaries */
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+ };
+
+-/* wish this was exported from libata-core */
+-static void ata_dummy_noret(struct ata_port *port)
+-{
+-}
+-
+ static void pata_icside_postreset(struct ata_link *link, unsigned int *classes)
+ {
+ struct ata_port *ap = link->ap;
+ struct pata_icside_state *state = ap->host->private_data;
+
+ if (classes[0] != ATA_DEV_NONE || classes[1] != ATA_DEV_NONE)
+- return ata_std_postreset(link, classes);
++ return ata_sff_postreset(link, classes);
+
+ state->port[ap->port_no].disabled = 1;
+
+@@ -349,42 +332,20 @@ static void pata_icside_postreset(struct ata_link *link, unsigned int *classes)
+ }
+ }
+
+-static void pata_icside_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
+- pata_icside_postreset);
+-}
+-
+ static struct ata_port_operations pata_icside_port_ops = {
+- .set_dmamode = pata_icside_set_dmamode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .exec_command = ata_exec_command,
+- .check_status = ata_check_status,
+- .dev_select = ata_std_dev_select,
+-
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = pata_icside_bmdma_setup,
+- .bmdma_start = pata_icside_bmdma_start,
+-
+- .data_xfer = ata_data_xfer_noirq,
+-
++ .inherits = &ata_sff_port_ops,
+ /* no need to build any PRD tables for DMA */
+ .qc_prep = ata_noop_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = pata_icside_error_handler,
+- .post_internal_cmd = pata_icside_bmdma_stop,
+-
+- .irq_clear = ata_dummy_noret,
+- .irq_on = ata_irq_on,
+-
++ .sff_data_xfer = ata_sff_data_xfer_noirq,
++ .bmdma_setup = pata_icside_bmdma_setup,
++ .bmdma_start = pata_icside_bmdma_start,
+ .bmdma_stop = pata_icside_bmdma_stop,
+ .bmdma_status = pata_icside_bmdma_status,
++
++ .cable_detect = ata_cable_40wire,
++ .set_dmamode = pata_icside_set_dmamode,
++ .postreset = pata_icside_postreset,
++ .post_internal_cmd = pata_icside_bmdma_stop,
+ };
+
+ static void __devinit
+@@ -520,7 +481,7 @@ static int __devinit pata_icside_add_ports(struct pata_icside_info *info)
+ pata_icside_setup_ioaddr(ap, info->base, info, info->port[i]);
+ }
+
+- return ata_host_activate(host, ec->irq, ata_interrupt, 0,
++ return ata_host_activate(host, ec->irq, ata_sff_interrupt, 0,
+ &pata_icside_sht);
+ }
+
+diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
+index 4320e79..6a111ba 100644
+--- a/drivers/ata/pata_isapnp.c
++++ b/drivers/ata/pata_isapnp.c
+@@ -20,45 +20,12 @@
+ #define DRV_VERSION "0.2.2"
+
+ static struct scsi_host_template isapnp_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations isapnp_port_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
+ .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /**
+@@ -83,7 +50,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
+
+ if (pnp_irq_valid(idev, 0)) {
+ irq = pnp_irq(idev, 0);
+- handler = ata_interrupt;
++ handler = ata_sff_interrupt;
+ }
+
+ /* allocate host */
+@@ -111,7 +78,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
+ ap->ioaddr.ctl_addr = ctl_addr;
+ }
+
+- ata_std_ports(&ap->ioaddr);
++ ata_sff_std_ports(&ap->ioaddr);
+
+ ata_port_desc(ap, "cmd 0x%llx ctl 0x%llx",
+ (unsigned long long)pnp_port_start(idev, 0),
+diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
+index e0c2cc2..c113d7c 100644
+--- a/drivers/ata/pata_it8213.c
++++ b/drivers/ata/pata_it8213.c
+@@ -40,20 +40,7 @@ static int it8213_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (!pci_test_config_bits(pdev, &it8213_enable_bits[ap->port_no]))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * it8213_error_handler - Probe specified port on PATA host controller
+- * @ap: Port to probe
+- *
+- * LOCKING:
+- * None (inherited from caller).
+- */
+-
+-static void it8213_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, it8213_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -243,53 +230,16 @@ static void it8213_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template it8213_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .max_sectors = ATA_MAX_SECTORS,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations it8213_ops = {
++
++static struct ata_port_operations it8213_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = it8213_cable_detect,
+ .set_piomode = it8213_set_piomode,
+ .set_dmamode = it8213_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = it8213_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = it8213_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .prereset = it8213_pre_reset,
+ };
+
+
+@@ -311,7 +261,6 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en
+ {
+ static int printed_version;
+ static const struct ata_port_info info = {
+- .sht = &it8213_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+@@ -325,7 +274,7 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &it8213_sht, NULL);
+ }
+
+ static const struct pci_device_id it8213_pci_tbl[] = {
+diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
+index 257951d..e108169 100644
+--- a/drivers/ata/pata_it821x.c
++++ b/drivers/ata/pata_it821x.c
+@@ -395,11 +395,11 @@ static void it821x_passthru_dev_select(struct ata_port *ap,
+ it821x_program(ap, adev, itdev->pio[adev->devno]);
+ itdev->last_device = device;
+ }
+- ata_std_dev_select(ap, device);
++ ata_sff_dev_select(ap, device);
+ }
+
+ /**
+- * it821x_smart_qc_issue_prot - wrap qc issue prot
++ * it821x_smart_qc_issue - wrap qc issue prot
+ * @qc: command
+ *
+ * Wrap the command issue sequence for the IT821x. We need to
+@@ -407,7 +407,7 @@ static void it821x_passthru_dev_select(struct ata_port *ap,
+ * usual happenings kick off
+ */
+
+-static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int it821x_smart_qc_issue(struct ata_queued_cmd *qc)
+ {
+ switch(qc->tf.command)
+ {
+@@ -427,14 +427,14 @@ static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc)
+ case ATA_CMD_ID_ATA:
+ /* Arguably should just no-op this one */
+ case ATA_CMD_SET_FEATURES:
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+ printk(KERN_DEBUG "it821x: can't process command 0x%02X\n", qc->tf.command);
+ return AC_ERR_DEV;
+ }
+
+ /**
+- * it821x_passthru_qc_issue_prot - wrap qc issue prot
++ * it821x_passthru_qc_issue - wrap qc issue prot
+ * @qc: command
+ *
+ * Wrap the command issue sequence for the IT821x. We need to
+@@ -442,10 +442,10 @@ static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc)
+ * usual happenings kick off
+ */
+
+-static unsigned int it821x_passthru_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int it821x_passthru_qc_issue(struct ata_queued_cmd *qc)
+ {
+ it821x_passthru_dev_select(qc->ap, qc->dev->devno);
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ /**
+@@ -632,89 +632,34 @@ static int it821x_port_start(struct ata_port *ap)
+ }
+
+ static struct scsi_host_template it821x_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations it821x_smart_port_ops = {
+- .set_mode = it821x_smart_set_mode,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .mode_filter = ata_pci_default_filter,
++ .inherits = &ata_bmdma_port_ops,
+
+- .check_status = ata_check_status,
+ .check_atapi_dma= it821x_check_atapi_dma,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+- .dev_config = it821x_dev_config,
++ .qc_issue = it821x_smart_qc_issue,
+
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .cable_detect = it821x_ident_hack,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = it821x_smart_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
++ .set_mode = it821x_smart_set_mode,
++ .dev_config = it821x_dev_config,
+
+ .port_start = it821x_port_start,
+ };
+
+ static struct ata_port_operations it821x_passthru_port_ops = {
+- .set_piomode = it821x_passthru_set_piomode,
+- .set_dmamode = it821x_passthru_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
++ .inherits = &ata_bmdma_port_ops,
+
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+ .check_atapi_dma= it821x_check_atapi_dma,
+- .dev_select = it821x_passthru_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_unknown,
+-
+- .bmdma_setup = ata_bmdma_setup,
++ .sff_dev_select = it821x_passthru_dev_select,
+ .bmdma_start = it821x_passthru_bmdma_start,
+ .bmdma_stop = it821x_passthru_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = it821x_passthru_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
++ .qc_issue = it821x_passthru_qc_issue,
+
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_handler = ata_interrupt,
+- .irq_on = ata_irq_on,
++ .cable_detect = ata_cable_unknown,
++ .set_piomode = it821x_passthru_set_piomode,
++ .set_dmamode = it821x_passthru_set_dmamode,
+
+ .port_start = it821x_port_start,
+ };
+@@ -742,14 +687,12 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ u8 conf;
+
+ static const struct ata_port_info info_smart = {
+- .sht = &it821x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .port_ops = &it821x_smart_port_ops
+ };
+ static const struct ata_port_info info_passthru = {
+- .sht = &it821x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -759,6 +702,11 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+
+ const struct ata_port_info *ppi[] = { NULL, NULL };
+ static char *mode[2] = { "pass through", "smart" };
++ int rc;
++
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
+
+ /* Force the card into bypass mode if so requested */
+ if (it8212_noraid) {
+@@ -774,16 +722,23 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ else
+ ppi[0] = &info_smart;
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &it821x_sht, NULL);
+ }
+
+ #ifdef CONFIG_PM
+ static int it821x_reinit_one(struct pci_dev *pdev)
+ {
++ struct ata_host *host = dev_get_drvdata(&pdev->dev);
++ int rc;
++
++ rc = ata_pci_device_do_resume(pdev);
++ if (rc)
++ return rc;
+ /* Resume - turn raid back off if need be */
+ if (it8212_noraid)
+ it821x_disable_raid(pdev);
+- return ata_pci_device_resume(pdev);
++ ata_host_resume(host);
++ return rc;
+ }
+ #endif
+
+diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
+index 030878f..de8d186 100644
+--- a/drivers/ata/pata_ixp4xx_cf.c
++++ b/drivers/ata/pata_ixp4xx_cf.c
+@@ -88,48 +88,14 @@ static unsigned int ixp4xx_mmio_data_xfer(struct ata_device *dev,
+ }
+
+ static struct scsi_host_template ixp4xx_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations ixp4xx_port_ops = {
+- .set_mode = ixp4xx_set_mode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .exec_command = ata_exec_command,
+- .check_status = ata_check_status,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ixp4xx_mmio_data_xfer,
++ .inherits = &ata_sff_port_ops,
++ .sff_data_xfer = ixp4xx_mmio_data_xfer,
+ .cable_detect = ata_cable_40wire,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_port_start,
++ .set_mode = ixp4xx_set_mode,
+ };
+
+ static void ixp4xx_setup_port(struct ata_port *ap,
+@@ -144,7 +110,7 @@ static void ixp4xx_setup_port(struct ata_port *ap,
+ ioaddr->altstatus_addr = data->cs1 + 0x06;
+ ioaddr->ctl_addr = data->cs1 + 0x06;
+
+- ata_std_ports(ioaddr);
++ ata_sff_std_ports(ioaddr);
+
+ #ifndef __ARMEB__
+
+@@ -220,7 +186,7 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
+ dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+
+ /* activate host */
+- return ata_host_activate(host, irq, ata_interrupt, 0, &ixp4xx_sht);
++ return ata_host_activate(host, irq, ata_sff_interrupt, 0, &ixp4xx_sht);
+ }
+
+ static __devexit int ixp4xx_pata_remove(struct platform_device *dev)
+@@ -255,6 +221,7 @@ MODULE_AUTHOR("Alessandro Zummo <a.zummo at towertech.it>");
+ MODULE_DESCRIPTION("low-level driver for ixp4xx Compact Flash PATA");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(DRV_VERSION);
++MODULE_ALIAS("platform:" DRV_NAME);
+
+ module_init(ixp4xx_pata_init);
+ module_exit(ixp4xx_pata_exit);
+diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
+index 00bbbbd..73b7596 100644
+--- a/drivers/ata/pata_jmicron.c
++++ b/drivers/ata/pata_jmicron.c
+@@ -102,73 +102,18 @@ static int jmicron_pre_reset(struct ata_link *link, unsigned long deadline)
+ ap->cbl = ATA_CBL_SATA;
+ break;
+ }
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * jmicron_error_handler - Setup and error handler
+- * @ap: Port to handle
+- *
+- * LOCKING:
+- * None (inherited from caller).
+- */
+-
+-static void jmicron_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, jmicron_pre_reset, ata_std_softreset, NULL,
+- ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /* No PIO or DMA methods needed for this device */
+
+ static struct scsi_host_template jmicron_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- /* Use standard CHS mapping rules */
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations jmicron_ops = {
+- /* Task file is PCI ATA format, use helpers */
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = jmicron_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- /* BMDMA handling is PCI ATA format, use helpers */
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- /* IRQ-related hooks */
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- /* Generic PATA PCI ATA helpers */
+- .port_start = ata_port_start,
++static struct ata_port_operations jmicron_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .prereset = jmicron_pre_reset,
+ };
+
+
+@@ -189,7 +134,6 @@ static const struct ata_port_operations jmicron_ops = {
+ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &jmicron_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+
+ .pio_mask = 0x1f,
+@@ -200,7 +144,7 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i
+ };
+ const struct ata_port_info *ppi[] = { &info, NULL };
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &jmicron_sht, NULL);
+ }
+
+ static const struct pci_device_id jmicron_pci_tbl[] = {
+diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
+index 50fe08e..7af4b29 100644
+--- a/drivers/ata/pata_legacy.c
++++ b/drivers/ata/pata_legacy.c
+@@ -208,21 +208,12 @@ static int legacy_set_mode(struct ata_link *link, struct ata_device **unused)
+ }
+
+ static struct scsi_host_template legacy_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
++};
++
++static const struct ata_port_operations legacy_base_port_ops = {
++ .inherits = &ata_sff_port_ops,
++ .cable_detect = ata_cable_40wire,
+ };
+
+ /*
+@@ -234,55 +225,14 @@ static struct scsi_host_template legacy_sht = {
+ */
+
+ static struct ata_port_operations simple_port_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer_noirq,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .inherits = &legacy_base_port_ops,
++ .sff_data_xfer = ata_sff_data_xfer_noirq,
+ };
+
+ static struct ata_port_operations legacy_port_ops = {
++ .inherits = &legacy_base_port_ops,
++ .sff_data_xfer = ata_sff_data_xfer_noirq,
+ .set_mode = legacy_set_mode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+- .cable_detect = ata_cable_40wire,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer_noirq,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /*
+@@ -367,36 +317,15 @@ static unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
+ }
+ local_irq_restore(flags);
+ } else
+- buflen = ata_data_xfer_noirq(dev, buf, buflen, rw);
++ buflen = ata_sff_data_xfer_noirq(dev, buf, buflen, rw);
+
+ return buflen;
+ }
+
+ static struct ata_port_operations pdc20230_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = pdc20230_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = pdc_data_xfer_vlb,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .sff_data_xfer = pdc_data_xfer_vlb,
+ };
+
+ /*
+@@ -427,30 +356,8 @@ static void ht6560a_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct ata_port_operations ht6560a_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = ht6560a_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer, /* Check vlb/noirq */
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /*
+@@ -492,30 +399,8 @@ static void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct ata_port_operations ht6560b_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = ht6560b_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer, /* FIXME: Check 32bit and noirq */
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /*
+@@ -613,30 +498,8 @@ static void opti82c611a_set_piomode(struct ata_port *ap,
+
+
+ static struct ata_port_operations opti82c611a_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = opti82c611a_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /*
+@@ -716,7 +579,7 @@ static void opti82c46x_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * opt82c465mv_qc_issue_prot - command issue
++ * opt82c465mv_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+@@ -730,7 +593,7 @@ static void opti82c46x_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ * FIXME: dual channel needs ->serialize support
+ */
+
+-static unsigned int opti82c46x_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int opti82c46x_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -741,34 +604,13 @@ static unsigned int opti82c46x_qc_issue_prot(struct ata_queued_cmd *qc)
+ && ap->host->private_data != NULL)
+ opti82c46x_set_piomode(ap, adev);
+
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static struct ata_port_operations opti82c46x_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = opti82c46x_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = opti82c46x_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .qc_issue = opti82c46x_qc_issue,
+ };
+
+ static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
+@@ -802,7 +644,7 @@ static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ * @irq: interrupt line
+ *
+ * In dual channel mode the 6580 has one clock per channel and we have
+- * to software clockswitch in qc_issue_prot.
++ * to software clockswitch in qc_issue.
+ */
+
+ static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)
+@@ -868,14 +710,14 @@ static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * qdi_qc_issue_prot - command issue
++ * qdi_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+ * this interface so that we can load the correct ATA timings.
+ */
+
+-static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int qdi_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -888,7 +730,7 @@ static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
+ 2 * ap->port_no);
+ }
+ }
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf,
+@@ -917,7 +759,7 @@ static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf,
+ }
+ return (buflen + 3) & ~3;
+ } else
+- return ata_data_xfer(adev, buf, buflen, rw);
++ return ata_sff_data_xfer(adev, buf, buflen, rw);
+ }
+
+ static int qdi_port(struct platform_device *dev,
+@@ -930,84 +772,22 @@ static int qdi_port(struct platform_device *dev,
+ }
+
+ static struct ata_port_operations qdi6500_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = qdi6500_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = qdi_qc_issue_prot,
+-
+- .data_xfer = vlb32_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .qc_issue = qdi_qc_issue,
++ .sff_data_xfer = vlb32_data_xfer,
+ };
+
+ static struct ata_port_operations qdi6580_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = qdi6580_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = vlb32_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .sff_data_xfer = vlb32_data_xfer,
+ };
+
+ static struct ata_port_operations qdi6580dp_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = qdi6580dp_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = qdi_qc_issue_prot,
+-
+- .data_xfer = vlb32_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .sff_data_xfer = vlb32_data_xfer,
+ };
+
+ static DEFINE_SPINLOCK(winbond_lock);
+@@ -1076,29 +856,9 @@ static int winbond_port(struct platform_device *dev,
+ }
+
+ static struct ata_port_operations winbond_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = winbond_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = vlb32_data_xfer,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .sff_data_xfer = vlb32_data_xfer,
+ };
+
+ static struct legacy_controller controllers[] = {
+@@ -1256,13 +1016,13 @@ static __init int legacy_init_one(struct legacy_probe *probe)
+ ap->ioaddr.cmd_addr = io_addr;
+ ap->ioaddr.altstatus_addr = ctrl_addr;
+ ap->ioaddr.ctl_addr = ctrl_addr;
+- ata_std_ports(&ap->ioaddr);
++ ata_sff_std_ports(&ap->ioaddr);
+ ap->host->private_data = ld;
+
+ ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io, io + 0x0206);
+
+- ret = ata_host_activate(host, probe->irq, ata_interrupt, 0,
+- &legacy_sht);
++ ret = ata_host_activate(host, probe->irq, ata_sff_interrupt, 0,
++ &legacy_sht);
+ if (ret)
+ goto fail;
+ ld->platform_dev = pdev;
+diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
+index a81f25d..24a011b 100644
+--- a/drivers/ata/pata_marvell.c
++++ b/drivers/ata/pata_marvell.c
+@@ -55,7 +55,7 @@ static int marvell_pre_reset(struct ata_link *link, unsigned long deadline)
+ (!(devices & 0x10))) /* PATA enable ? */
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ static int marvell_cable_detect(struct ata_port *ap)
+@@ -75,71 +75,16 @@ static int marvell_cable_detect(struct ata_port *ap)
+ return 0; /* Our BUG macro needs the right markup */
+ }
+
+-/**
+- * marvell_error_handler - Setup and error handler
+- * @ap: Port to handle
+- *
+- * LOCKING:
+- * None (inherited from caller).
+- */
+-
+-static void marvell_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, marvell_pre_reset, ata_std_softreset, NULL,
+- ata_std_postreset);
+-}
+-
+ /* No PIO or DMA methods needed for this device */
+
+ static struct scsi_host_template marvell_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- /* Use standard CHS mapping rules */
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations marvell_ops = {
+- /* Task file is PCI ATA format, use helpers */
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = marvell_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++static struct ata_port_operations marvell_ops = {
++ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = marvell_cable_detect,
+-
+- /* BMDMA handling is PCI ATA format, use helpers */
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- /* Timeout handling */
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- /* Generic PATA PCI ATA helpers */
+- .port_start = ata_sff_port_start,
++ .prereset = marvell_pre_reset,
+ };
+
+
+@@ -160,7 +105,6 @@ static const struct ata_port_operations marvell_ops = {
+ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &marvell_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+
+ .pio_mask = 0x1f,
+@@ -170,7 +114,6 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
+ .port_ops = &marvell_ops,
+ };
+ static const struct ata_port_info info_sata = {
+- .sht = &marvell_sht,
+ /* Slave possible as its magically mapped not real */
+ .flags = ATA_FLAG_SLAVE_POSS,
+
+@@ -185,7 +128,7 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
+ if (pdev->device == 0x6101)
+ ppi[1] = &ata_dummy_port_info;
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &marvell_sht, NULL);
+ }
+
+ static const struct pci_device_id marvell_pci_tbl[] = {
+diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
+index 5413ebf..bc79df6 100644
+--- a/drivers/ata/pata_mpc52xx.c
++++ b/drivers/ata/pata_mpc52xx.c
+@@ -252,53 +252,19 @@ mpc52xx_ata_dev_select(struct ata_port *ap, unsigned int device)
+ if (device != priv->csel)
+ mpc52xx_ata_apply_timings(priv, device);
+
+- ata_std_dev_select(ap,device);
++ ata_sff_dev_select(ap,device);
+ }
+
+-static void
+-mpc52xx_ata_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
+- ata_std_postreset);
+-}
+-
+-
+-
+ static struct scsi_host_template mpc52xx_ata_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .max_sectors = ATA_MAX_SECTORS,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations mpc52xx_ata_port_ops = {
+- .set_piomode = mpc52xx_ata_set_piomode,
+- .dev_select = mpc52xx_ata_dev_select,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = mpc52xx_ata_error_handler,
++ .inherits = &ata_sff_port_ops,
++ .sff_dev_select = mpc52xx_ata_dev_select,
+ .cable_detect = ata_cable_40wire,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+- .port_start = ata_port_start,
++ .set_piomode = mpc52xx_ata_set_piomode,
++ .post_internal_cmd = ATA_OP_NULL,
+ };
+
+ static int __devinit
+@@ -339,7 +305,7 @@ mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv,
+ ata_port_desc(ap, "ata_regs 0x%lx", raw_ata_regs);
+
+ /* activate host */
+- return ata_host_activate(host, priv->ata_irq, ata_interrupt, 0,
++ return ata_host_activate(host, priv->ata_irq, ata_sff_interrupt, 0,
+ &mpc52xx_ata_sht);
+ }
+
+diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
+index c0d9e0c..7d7e3fd 100644
+--- a/drivers/ata/pata_mpiix.c
++++ b/drivers/ata/pata_mpiix.c
+@@ -55,21 +55,7 @@ static int mpiix_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (!pci_test_config_bits(pdev, &mpiix_enable_bits))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * mpiix_error_handler - probe reset
+- * @ap: ATA port
+- *
+- * Perform the ATA probe and bus reset sequence plus specific handling
+- * for this hardware. The MPIIX has the enable bits in a different place
+- * to PIIX4 and friends. As a pure PIO device it has no cable detect
+- */
+-
+-static void mpiix_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, mpiix_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -83,8 +69,8 @@ static void mpiix_error_handler(struct ata_port *ap)
+ *
+ * This would get very ugly because we can only program timing for one
+ * device at a time, the other gets PIO0. Fortunately libata calls
+- * our qc_issue_prot command before a command is issued so we can
+- * flip the timings back and forth to reduce the pain.
++ * our qc_issue command before a command is issued so we can flip the
++ * timings back and forth to reduce the pain.
+ */
+
+ static void mpiix_set_piomode(struct ata_port *ap, struct ata_device *adev)
+@@ -124,7 +110,7 @@ static void mpiix_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * mpiix_qc_issue_prot - command issue
++ * mpiix_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+@@ -134,7 +120,7 @@ static void mpiix_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ * be made PIO0.
+ */
+
+-static unsigned int mpiix_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int mpiix_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -147,50 +133,19 @@ static unsigned int mpiix_qc_issue_prot(struct ata_queued_cmd *qc)
+ if (adev->pio_mode && adev != ap->private_data)
+ mpiix_set_piomode(ap, adev);
+
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static struct scsi_host_template mpiix_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations mpiix_port_ops = {
+- .set_piomode = mpiix_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = mpiix_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
++ .qc_issue = mpiix_qc_issue,
+ .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = mpiix_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_piomode = mpiix_set_piomode,
++ .prereset = mpiix_pre_reset,
+ };
+
+ static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+@@ -252,10 +207,10 @@ static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ ap->ioaddr.altstatus_addr = ctl_addr;
+
+ /* Let libata fill in the port details */
+- ata_std_ports(&ap->ioaddr);
++ ata_sff_std_ports(&ap->ioaddr);
+
+ /* activate host */
+- return ata_host_activate(host, irq, ata_interrupt, IRQF_SHARED,
++ return ata_host_activate(host, irq, ata_sff_interrupt, IRQF_SHARED,
+ &mpiix_sht);
+ }
+
+diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
+index 25c922a..d9719c8 100644
+--- a/drivers/ata/pata_netcell.c
++++ b/drivers/ata/pata_netcell.c
+@@ -21,54 +21,12 @@
+ /* No PIO or DMA methods needed for this device */
+
+ static struct scsi_host_template netcell_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- /* Use standard CHS mapping rules */
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations netcell_ops = {
+- /* Task file is PCI ATA format, use helpers */
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++static struct ata_port_operations netcell_ops = {
++ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = ata_cable_80wire,
+-
+- /* BMDMA handling is PCI ATA format, use helpers */
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- /* IRQ-related hooks */
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- /* Generic PATA PCI ATA helpers */
+- .port_start = ata_sff_port_start,
+ };
+
+
+@@ -90,7 +48,6 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ {
+ static int printed_version;
+ static const struct ata_port_info info = {
+- .sht = &netcell_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ /* Actually we don't really care about these as the
+ firmware deals with it */
+@@ -100,16 +57,21 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ .port_ops = &netcell_ops,
+ };
+ const struct ata_port_info *port_info[] = { &info, NULL };
++ int rc;
+
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
+
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
++
+ /* Any chip specific setup/optimisation/messages here */
+- ata_pci_clear_simplex(pdev);
++ ata_pci_bmdma_clear_simplex(pdev);
+
+ /* And let the library code do the work */
+- return ata_pci_init_one(pdev, port_info);
++ return ata_pci_sff_init_one(pdev, port_info, &netcell_sht, NULL);
+ }
+
+ static const struct pci_device_id netcell_pci_tbl[] = {
+diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c
+index 15dd649..565e67c 100644
+--- a/drivers/ata/pata_ninja32.c
++++ b/drivers/ata/pata_ninja32.c
+@@ -73,60 +73,20 @@ static void ninja32_dev_select(struct ata_port *ap, unsigned int device)
+ struct ata_device *adev = &ap->link.device[device];
+ if (ap->private_data != adev) {
+ iowrite8(0xd6, ap->ioaddr.bmdma_addr + 0x1f);
+- ata_std_dev_select(ap, device);
++ ata_sff_dev_select(ap, device);
+ ninja32_set_piomode(ap, adev);
+ }
+ }
+
+ static struct scsi_host_template ninja32_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations ninja32_port_ops = {
+- .set_piomode = ninja32_set_piomode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ninja32_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_bmdma_port_ops,
++ .sff_dev_select = ninja32_dev_select,
+ .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_piomode = ninja32_set_piomode,
+ };
+
+ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+@@ -172,7 +132,7 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ ap->ioaddr.ctl_addr = base + 0x1E;
+ ap->ioaddr.altstatus_addr = base + 0x1E;
+ ap->ioaddr.bmdma_addr = base;
+- ata_std_ports(&ap->ioaddr);
++ ata_sff_std_ports(&ap->ioaddr);
+
+ iowrite8(0x05, base + 0x01); /* Enable interrupt lines */
+ iowrite8(0xBE, base + 0x02); /* Burst, ?? setup */
+@@ -182,7 +142,7 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ iowrite8(0xa4, base + 0x1c); /* Unknown */
+ iowrite8(0x83, base + 0x1d); /* BMDMA control: WAIT0 */
+ /* FIXME: Should we disable them at remove ? */
+- return ata_host_activate(host, dev->irq, ata_interrupt,
++ return ata_host_activate(host, dev->irq, ata_sff_interrupt,
+ IRQF_SHARED, &ninja32_sht);
+ }
+
+diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
+index 9fe66fd..76d2455 100644
+--- a/drivers/ata/pata_ns87410.c
++++ b/drivers/ata/pata_ns87410.c
+@@ -50,21 +50,7 @@ static int ns87410_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (!pci_test_config_bits(pdev, &ns87410_enable_bits[ap->port_no]))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * ns87410_error_handler - probe reset
+- * @ap: ATA port
+- *
+- * Perform the ATA probe and bus reset sequence plus specific handling
+- * for this hardware. The MPIIX has the enable bits in a different place
+- * to PIIX4 and friends. As a pure PIO device it has no cable detect
+- */
+-
+-static void ns87410_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, ns87410_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -119,7 +105,7 @@ static void ns87410_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * ns87410_qc_issue_prot - command issue
++ * ns87410_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+@@ -127,7 +113,7 @@ static void ns87410_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ * necessary.
+ */
+
+-static unsigned int ns87410_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int ns87410_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -140,64 +126,30 @@ static unsigned int ns87410_qc_issue_prot(struct ata_queued_cmd *qc)
+ if (adev->pio_mode && adev != ap->private_data)
+ ns87410_set_piomode(ap, adev);
+
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static struct scsi_host_template ns87410_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations ns87410_port_ops = {
+- .set_piomode = ns87410_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ns87410_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
++ .qc_issue = ns87410_qc_issue,
+ .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ns87410_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_piomode = ns87410_set_piomode,
++ .prereset = ns87410_pre_reset,
+ };
+
+ static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &ns87410_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x0F,
+ .port_ops = &ns87410_port_ops
+ };
+ const struct ata_port_info *ppi[] = { &info, NULL };
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &ns87410_sht, NULL);
+ }
+
+ static const struct pci_device_id ns87410[] = {
+diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c
+index d0e2e50..ae92b00 100644
+--- a/drivers/ata/pata_ns87415.c
++++ b/drivers/ata/pata_ns87415.c
+@@ -138,7 +138,7 @@ static void ns87415_bmdma_setup(struct ata_queued_cmd *qc)
+ dmactl |= ATA_DMA_WR;
+ iowrite8(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+ /* issue r/w command */
+- ap->ops->exec_command(ap, &qc->tf);
++ ap->ops->sff_exec_command(ap, &qc->tf);
+ }
+
+ /**
+@@ -172,14 +172,14 @@ static void ns87415_bmdma_stop(struct ata_queued_cmd *qc)
+ }
+
+ /**
+- * ns87415_bmdma_irq_clear - Clear interrupt
++ * ns87415_irq_clear - Clear interrupt
+ * @ap: Channel to clear
+ *
+ * Erratum: Due to a chip bug regisers 02 and 0A bit 1 and 2 (the
+ * error bits) are reset by writing to register 00 or 08.
+ */
+
+-static void ns87415_bmdma_irq_clear(struct ata_port *ap)
++static void ns87415_irq_clear(struct ata_port *ap)
+ {
+ void __iomem *mmio = ap->ioaddr.bmdma_addr;
+
+@@ -297,90 +297,32 @@ static u8 ns87560_bmdma_status(struct ata_port *ap)
+ {
+ return ns87560_read_buggy(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ }
+-
+-static const struct ata_port_operations ns87560_pata_ops = {
+- .set_piomode = ns87415_set_piomode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ns87560_tf_read,
+- .check_status = ns87560_check_status,
+- .check_atapi_dma = ns87415_check_atapi_dma,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ns87415_bmdma_setup,
+- .bmdma_start = ns87415_bmdma_start,
+- .bmdma_stop = ns87415_bmdma_stop,
+- .bmdma_status = ns87560_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ns87415_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+-};
+-
+ #endif /* 87560 SuperIO Support */
+
++static struct ata_port_operations ns87415_pata_ops = {
++ .inherits = &ata_bmdma_port_ops,
+
+-static const struct ata_port_operations ns87415_pata_ops = {
+- .set_piomode = ns87415_set_piomode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+ .check_atapi_dma = ns87415_check_atapi_dma,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+ .bmdma_setup = ns87415_bmdma_setup,
+ .bmdma_start = ns87415_bmdma_start,
+ .bmdma_stop = ns87415_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
++ .sff_irq_clear = ns87415_irq_clear,
+
+- .irq_handler = ata_interrupt,
+- .irq_clear = ns87415_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
++ .cable_detect = ata_cable_40wire,
++ .set_piomode = ns87415_set_piomode,
++};
+
+- .port_start = ata_sff_port_start,
++#if defined(CONFIG_SUPERIO)
++static struct ata_port_operations ns87560_pata_ops = {
++ .inherits = &ns87415_pata_ops,
++ .sff_tf_read = ns87560_tf_read,
++ .sff_check_status = ns87560_check_status,
++ .bmdma_status = ns87560_bmdma_status,
+ };
++#endif
+
+ static struct scsi_host_template ns87415_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+
+@@ -403,16 +345,15 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ {
+ static int printed_version;
+ static const struct ata_port_info info = {
+- .sht = &ns87415_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .port_ops = &ns87415_pata_ops,
+ };
+ const struct ata_port_info *ppi[] = { &info, NULL };
++ int rc;
+ #if defined(CONFIG_SUPERIO)
+ static const struct ata_port_info info87560 = {
+- .sht = &ns87415_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+@@ -425,11 +366,16 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
++
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
++
+ /* Select 512 byte sectors */
+ pci_write_config_byte(pdev, 0x55, 0xEE);
+ /* Select PIO0 8bit clocking */
+ pci_write_config_byte(pdev, 0x54, 0xB7);
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &ns87415_sht, NULL);
+ }
+
+ static const struct pci_device_id ns87415_pci_tbl[] = {
+diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
+index 44da09a..e678af3 100644
+--- a/drivers/ata/pata_oldpiix.c
++++ b/drivers/ata/pata_oldpiix.c
+@@ -47,21 +47,7 @@ static int oldpiix_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (!pci_test_config_bits(pdev, &oldpiix_enable_bits[ap->port_no]))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * oldpiix_pata_error_handler - Probe specified port on PATA host controller
+- * @ap: Port to probe
+- * @classes:
+- *
+- * LOCKING:
+- * None (inherited from caller).
+- */
+-
+-static void oldpiix_pata_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, oldpiix_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -195,7 +181,7 @@ static void oldpiix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * oldpiix_qc_issue_prot - command issue
++ * oldpiix_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+@@ -205,7 +191,7 @@ static void oldpiix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ * be made PIO0.
+ */
+
+-static unsigned int oldpiix_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int oldpiix_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -215,58 +201,21 @@ static unsigned int oldpiix_qc_issue_prot(struct ata_queued_cmd *qc)
+ if (adev->dma_mode)
+ oldpiix_set_dmamode(ap, adev);
+ }
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+
+ static struct scsi_host_template oldpiix_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations oldpiix_pata_ops = {
++static struct ata_port_operations oldpiix_pata_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .qc_issue = oldpiix_qc_issue,
++ .cable_detect = ata_cable_40wire,
+ .set_piomode = oldpiix_set_piomode,
+ .set_dmamode = oldpiix_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = oldpiix_pata_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = oldpiix_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .prereset = oldpiix_pre_reset,
+ };
+
+
+@@ -289,7 +238,6 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ {
+ static int printed_version;
+ static const struct ata_port_info info = {
+- .sht = &oldpiix_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma1-2 */
+@@ -301,7 +249,7 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &oldpiix_sht, NULL);
+ }
+
+ static const struct pci_device_id oldpiix_pci_tbl[] = {
+diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
+index 8f79447..fb2cf66 100644
+--- a/drivers/ata/pata_opti.c
++++ b/drivers/ata/pata_opti.c
+@@ -64,22 +64,7 @@ static int opti_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (!pci_test_config_bits(pdev, &opti_enable_bits[ap->port_no]))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * opti_probe_reset - probe reset
+- * @ap: ATA port
+- *
+- * Perform the ATA probe and bus reset sequence plus specific handling
+- * for this hardware. The Opti needs little handling - we have no UDMA66
+- * capability that needs cable detection. All we must do is check the port
+- * is enabled.
+- */
+-
+-static void opti_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, opti_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -165,58 +150,19 @@ static void opti_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template opti_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations opti_port_ops = {
+- .set_piomode = opti_set_piomode,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = opti_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
+ .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_piomode = opti_set_piomode,
++ .prereset = opti_pre_reset,
+ };
+
+ static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &opti_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .port_ops = &opti_port_ops
+@@ -227,7 +173,7 @@ static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &opti_sht, NULL);
+ }
+
+ static const struct pci_device_id opti[] = {
+diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
+index f9b485a..4cd7444 100644
+--- a/drivers/ata/pata_optidma.c
++++ b/drivers/ata/pata_optidma.c
+@@ -64,22 +64,7 @@ static int optidma_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (ap->port_no && !pci_test_config_bits(pdev, &optidma_enable_bits))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * optidma_probe_reset - probe reset
+- * @ap: ATA port
+- *
+- * Perform the ATA probe and bus reset sequence plus specific handling
+- * for this hardware. The Opti needs little handling - we have no UDMA66
+- * capability that needs cable detection. All we must do is check the port
+- * is enabled.
+- */
+-
+-static void optidma_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, optidma_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -350,89 +335,22 @@ static int optidma_set_mode(struct ata_link *link, struct ata_device **r_failed)
+ }
+
+ static struct scsi_host_template optidma_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations optidma_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = ata_cable_40wire,
+ .set_piomode = optidma_set_pio_mode,
+ .set_dmamode = optidma_set_dma_mode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .error_handler = optidma_error_handler,
+ .set_mode = optidma_set_mode,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .prereset = optidma_pre_reset,
+ };
+
+ static struct ata_port_operations optiplus_port_ops = {
++ .inherits = &optidma_port_ops,
+ .set_piomode = optiplus_set_pio_mode,
+ .set_dmamode = optiplus_set_dma_mode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .error_handler = optidma_error_handler,
+- .set_mode = optidma_set_mode,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /**
+@@ -481,14 +399,12 @@ done_nomsg: /* Wrong chip revision */
+ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info_82c700 = {
+- .sht = &optidma_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .port_ops = &optidma_port_ops
+ };
+ static const struct ata_port_info info_82c700_udma = {
+- .sht = &optidma_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -497,10 +413,15 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ };
+ const struct ata_port_info *ppi[] = { &info_82c700, NULL };
+ static int printed_version;
++ int rc;
+
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+
++ rc = pcim_enable_device(dev);
++ if (rc)
++ return rc;
++
+ /* Fixed location chipset magic */
+ inw(0x1F1);
+ inw(0x1F1);
+@@ -509,7 +430,7 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ if (optiplus_with_udma(dev))
+ ppi[0] = &info_82c700_udma;
+
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &optidma_sht, NULL);
+ }
+
+ static const struct pci_device_id optidma[] = {
+diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
+index 3e7f6a9..3d39f9d 100644
+--- a/drivers/ata/pata_pcmcia.c
++++ b/drivers/ata/pata_pcmcia.c
+@@ -128,71 +128,21 @@ static unsigned int ata_data_xfer_8bit(struct ata_device *dev,
+
+
+ static struct scsi_host_template pcmcia_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations pcmcia_port_ops = {
+- .set_mode = pcmcia_set_mode,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
++ .sff_data_xfer = ata_sff_data_xfer_noirq,
+ .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer_noirq,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_mode = pcmcia_set_mode,
+ };
+
+ static struct ata_port_operations pcmcia_8bit_port_ops = {
+- .set_mode = pcmcia_set_mode_8bit,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
++ .sff_data_xfer = ata_data_xfer_8bit,
+ .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer_8bit,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_mode = pcmcia_set_mode_8bit,
+ };
+
+ #define CS_CHECK(fn, ret) \
+@@ -373,13 +323,13 @@ next_entry:
+ ap->ioaddr.cmd_addr = io_addr + 0x10 * p;
+ ap->ioaddr.altstatus_addr = ctl_addr + 0x10 * p;
+ ap->ioaddr.ctl_addr = ctl_addr + 0x10 * p;
+- ata_std_ports(&ap->ioaddr);
++ ata_sff_std_ports(&ap->ioaddr);
+
+ ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io_base, ctl_base);
+ }
+
+ /* activate */
+- ret = ata_host_activate(host, pdev->irq.AssignedIRQ, ata_interrupt,
++ ret = ata_host_activate(host, pdev->irq.AssignedIRQ, ata_sff_interrupt,
+ IRQF_SHARED, &pcmcia_sht);
+ if (ret)
+ goto failed;
+diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
+index 511c89b..0e1c2c1 100644
+--- a/drivers/ata/pata_pdc2027x.c
++++ b/drivers/ata/pata_pdc2027x.c
+@@ -63,7 +63,7 @@ enum {
+ };
+
+ static int pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+-static void pdc2027x_error_handler(struct ata_port *ap);
++static int pdc2027x_prereset(struct ata_link *link, unsigned long deadline);
+ static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev);
+ static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+ static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc);
+@@ -129,84 +129,22 @@ static struct pci_driver pdc2027x_pci_driver = {
+ };
+
+ static struct scsi_host_template pdc2027x_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations pdc2027x_pata100_ops = {
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
++ .inherits = &ata_bmdma_port_ops,
+ .check_atapi_dma = pdc2027x_check_atapi_dma,
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = pdc2027x_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .cable_detect = pdc2027x_cable_detect,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .prereset = pdc2027x_prereset,
+ };
+
+ static struct ata_port_operations pdc2027x_pata133_ops = {
++ .inherits = &pdc2027x_pata100_ops,
++ .mode_filter = pdc2027x_mode_filter,
+ .set_piomode = pdc2027x_set_piomode,
+ .set_dmamode = pdc2027x_set_dmamode,
+ .set_mode = pdc2027x_set_mode,
+- .mode_filter = pdc2027x_mode_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .check_atapi_dma = pdc2027x_check_atapi_dma,
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = pdc2027x_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = pdc2027x_cable_detect,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ static struct ata_port_info pdc2027x_port_info[] = {
+@@ -310,22 +248,7 @@ static int pdc2027x_prereset(struct ata_link *link, unsigned long deadline)
+ /* Check whether port enabled */
+ if (!pdc2027x_port_enabled(link->ap))
+ return -ENOENT;
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * pdc2027x_error_handler - Perform reset on PATA port and classify
+- * @ap: Port to reset
+- *
+- * Reset PATA phy and classify attached devices.
+- *
+- * LOCKING:
+- * None (inherited from caller).
+- */
+-
+-static void pdc2027x_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, pdc2027x_prereset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -342,7 +265,7 @@ static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long
+ struct ata_device *pair = ata_dev_pair(adev);
+
+ if (adev->class != ATA_DEV_ATA || adev->devno == 0 || pair == NULL)
+- return ata_pci_default_filter(adev, mask);
++ return ata_bmdma_mode_filter(adev, mask);
+
+ /* Check for slave of a Maxtor at UDMA6 */
+ ata_id_c_string(pair->id, model_num, ATA_ID_PROD,
+@@ -351,7 +274,7 @@ static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long
+ if (strstr(model_num, "Maxtor") == NULL && pair->dma_mode == XFER_UDMA_6)
+ mask &= ~ (1 << (6 + ATA_SHIFT_UDMA));
+
+- return ata_pci_default_filter(adev, mask);
++ return ata_bmdma_mode_filter(adev, mask);
+ }
+
+ /**
+@@ -836,8 +759,8 @@ static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_de
+ return -EIO;
+
+ pci_set_master(pdev);
+- return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+- &pdc2027x_sht);
++ return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++ IRQF_SHARED, &pdc2027x_sht);
+ }
+
+ /**
+diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
+index 3ed8667..d267306 100644
+--- a/drivers/ata/pata_pdc202xx_old.c
++++ b/drivers/ata/pata_pdc202xx_old.c
+@@ -262,94 +262,34 @@ static int pdc2026x_check_atapi_dma(struct ata_queued_cmd *qc)
+ }
+
+ static struct scsi_host_template pdc202xx_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations pdc2024x_port_ops = {
+- .set_piomode = pdc202xx_set_piomode,
+- .set_dmamode = pdc202xx_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .inherits = &ata_bmdma_port_ops,
++
++ .cable_detect = ata_cable_40wire,
++ .set_piomode = pdc202xx_set_piomode,
++ .set_dmamode = pdc202xx_set_dmamode,
+ };
+
+ static struct ata_port_operations pdc2026x_port_ops = {
+- .set_piomode = pdc202xx_set_piomode,
+- .set_dmamode = pdc202xx_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+- .dev_config = pdc2026x_dev_config,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = pdc2026x_cable_detect,
+-
+- .check_atapi_dma= pdc2026x_check_atapi_dma,
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = pdc2026x_bmdma_start,
+- .bmdma_stop = pdc2026x_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = pdc2026x_port_start,
++ .inherits = &pdc2024x_port_ops,
++
++ .check_atapi_dma = pdc2026x_check_atapi_dma,
++ .bmdma_start = pdc2026x_bmdma_start,
++ .bmdma_stop = pdc2026x_bmdma_stop,
++
++ .cable_detect = pdc2026x_cable_detect,
++ .dev_config = pdc2026x_dev_config,
++
++ .port_start = pdc2026x_port_start,
+ };
+
+ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info[3] = {
+ {
+- .sht = &pdc202xx_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -357,7 +297,6 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
+ .port_ops = &pdc2024x_port_ops
+ },
+ {
+- .sht = &pdc202xx_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -365,7 +304,6 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
+ .port_ops = &pdc2026x_port_ops
+ },
+ {
+- .sht = &pdc202xx_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -386,7 +324,7 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
+ return -ENODEV;
+ }
+ }
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &pdc202xx_sht, NULL);
+ }
+
+ static const struct pci_device_id pdc202xx[] = {
+diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
+index aad7adc..8f65ad6 100644
+--- a/drivers/ata/pata_platform.c
++++ b/drivers/ata/pata_platform.c
+@@ -46,50 +46,16 @@ static int pata_platform_set_mode(struct ata_link *link, struct ata_device **unu
+ return 0;
+ }
+
+-static int ata_dummy_ret0(struct ata_port *ap) { return 0; }
+-
+ static struct scsi_host_template pata_platform_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations pata_platform_port_ops = {
+- .set_mode = pata_platform_set_mode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
++ .sff_data_xfer = ata_sff_data_xfer_noirq,
+ .cable_detect = ata_cable_unknown,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer_noirq,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_dummy_ret0,
++ .set_mode = pata_platform_set_mode,
++ .port_start = ATA_OP_NULL,
+ };
+
+ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
+@@ -210,7 +176,7 @@ int __devinit __pata_platform_probe(struct device *dev,
+ (unsigned long long)ctl_res->start);
+
+ /* activate */
+- return ata_host_activate(host, irq, irq ? ata_interrupt : NULL,
++ return ata_host_activate(host, irq, irq ? ata_sff_interrupt : NULL,
+ irq_flags, &pata_platform_sht);
+ }
+ EXPORT_SYMBOL_GPL(__pata_platform_probe);
+@@ -311,3 +277,4 @@ MODULE_AUTHOR("Paul Mundt");
+ MODULE_DESCRIPTION("low-level driver for platform device ATA");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(DRV_VERSION);
++MODULE_ALIAS("platform:" DRV_NAME);
+diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
+index 9f308ed..bf45cf0 100644
+--- a/drivers/ata/pata_qdi.c
++++ b/drivers/ata/pata_qdi.c
+@@ -102,14 +102,14 @@ static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * qdi_qc_issue_prot - command issue
++ * qdi_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+ * this interface so that we can load the correct ATA timings.
+ */
+
+-static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int qdi_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -121,7 +121,7 @@ static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
+ outb(qdi->clock[adev->devno], qdi->timing);
+ }
+ }
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static unsigned int qdi_data_xfer(struct ata_device *dev, unsigned char *buf,
+@@ -148,79 +148,26 @@ static unsigned int qdi_data_xfer(struct ata_device *dev, unsigned char *buf,
+ buflen += 4 - slop;
+ }
+ } else
+- buflen = ata_data_xfer(dev, buf, buflen, rw);
++ buflen = ata_sff_data_xfer(dev, buf, buflen, rw);
+
+ return buflen;
+ }
+
+ static struct scsi_host_template qdi_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations qdi6500_port_ops = {
+- .set_piomode = qdi6500_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
++ .qc_issue = qdi_qc_issue,
++ .sff_data_xfer = qdi_data_xfer,
+ .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = qdi_qc_issue_prot,
+-
+- .data_xfer = qdi_data_xfer,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_piomode = qdi6500_set_piomode,
+ };
+
+ static struct ata_port_operations qdi6580_port_ops = {
++ .inherits = &qdi6500_port_ops,
+ .set_piomode = qdi6580_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = qdi_qc_issue_prot,
+-
+- .data_xfer = qdi_data_xfer,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /**
+@@ -276,7 +223,7 @@ static __init int qdi_init_one(unsigned long port, int type, unsigned long io, i
+ ap->ioaddr.cmd_addr = io_addr;
+ ap->ioaddr.altstatus_addr = ctl_addr;
+ ap->ioaddr.ctl_addr = ctl_addr;
+- ata_std_ports(&ap->ioaddr);
++ ata_sff_std_ports(&ap->ioaddr);
+
+ ata_port_desc(ap, "cmd %lx ctl %lx", io, ctl);
+
+@@ -292,7 +239,7 @@ static __init int qdi_init_one(unsigned long port, int type, unsigned long io, i
+ printk(KERN_INFO DRV_NAME": qd%d at 0x%lx.\n", type, io);
+
+ /* activate */
+- ret = ata_host_activate(host, irq, ata_interrupt, 0, &qdi_sht);
++ ret = ata_host_activate(host, irq, ata_sff_interrupt, 0, &qdi_sht);
+ if (ret)
+ goto fail;
+
+diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
+index 8109b08..1c0d9fa 100644
+--- a/drivers/ata/pata_radisys.c
++++ b/drivers/ata/pata_radisys.c
+@@ -156,7 +156,7 @@ static void radisys_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * radisys_qc_issue_prot - command issue
++ * radisys_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+@@ -166,7 +166,7 @@ static void radisys_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ * be made PIO0.
+ */
+
+-static unsigned int radisys_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int radisys_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -180,58 +180,20 @@ static unsigned int radisys_qc_issue_prot(struct ata_queued_cmd *qc)
+ radisys_set_piomode(ap, adev);
+ }
+ }
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+
+ static struct scsi_host_template radisys_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations radisys_pata_ops = {
++static struct ata_port_operations radisys_pata_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .qc_issue = radisys_qc_issue,
++ .cable_detect = ata_cable_unknown,
+ .set_piomode = radisys_set_piomode,
+ .set_dmamode = radisys_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_unknown,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = radisys_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+
+@@ -254,7 +216,6 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ {
+ static int printed_version;
+ static const struct ata_port_info info = {
+- .sht = &radisys_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma1-2 */
+@@ -267,7 +228,7 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &radisys_sht, NULL);
+ }
+
+ static const struct pci_device_id radisys_pci_tbl[] = {
+diff --git a/drivers/ata/pata_rb500_cf.c b/drivers/ata/pata_rb500_cf.c
+deleted file mode 100644
+index 4ce9b03..0000000
+--- a/drivers/ata/pata_rb500_cf.c
++++ /dev/null
+@@ -1,314 +0,0 @@
+-/*
+- * A low-level PATA driver to handle a Compact Flash connected on the
+- * Mikrotik's RouterBoard 532 board.
+- *
+- * Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org>
+- * Copyright (C) 2008 Florian Fainelli <florian at openwrt.org>
+- *
+- * This file was based on: drivers/ata/pata_ixp4xx_cf.c
+- * Copyright (C) 2006-07 Tower Technologies
+- * Author: Alessandro Zummo <a.zummo at towertech.it>
+- *
+- * Also was based on the driver for Linux 2.4.xx published by Mikrotik for
+- * their RouterBoard 1xx and 5xx series devices. The original Mikrotik code
+- * seems not to have a license.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- *
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/platform_device.h>
+-
+-#include <linux/io.h>
+-#include <linux/interrupt.h>
+-#include <linux/irq.h>
+-
+-#include <linux/libata.h>
+-#include <scsi/scsi_host.h>
+-
+-#include <asm/gpio.h>
+-
+-#define DRV_NAME "pata-rb500-cf"
+-#define DRV_VERSION "0.1.0"
+-#define DRV_DESC "PATA driver for RouterBOARD 532 Compact Flash"
+-
+-#define RB500_CF_MAXPORTS 1
+-#define RB500_CF_IO_DELAY 400
+-
+-#define RB500_CF_REG_CMD 0x0800
+-#define RB500_CF_REG_CTRL 0x080E
+-#define RB500_CF_REG_DATA 0x0C00
+-
+-struct rb500_cf_info {
+- void __iomem *iobase;
+- unsigned int gpio_line;
+- int frozen;
+- unsigned int irq;
+-};
+-
+-/* ------------------------------------------------------------------------ */
+-
+-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);
+- ndelay(RB500_CF_IO_DELAY);
+-
+- set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
+-}
+-
+-static void rb500_pata_exec_command(struct ata_port *ap,
+- const struct ata_taskfile *tf)
+-{
+- writeb(tf->command, ap->ioaddr.command_addr);
+- rb500_pata_finish_io(ap);
+-}
+-
+-static void rb500_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
+- unsigned int buflen, int write_data)
+-{
+- struct ata_port *ap = adev->link->ap;
+- void __iomem *ioaddr = ap->ioaddr.data_addr;
+-
+- if (write_data) {
+- for (; buflen > 0; buflen--, buf++)
+- writeb(*buf, ioaddr);
+- } else {
+- for (; buflen > 0; buflen--, buf++)
+- *buf = readb(ioaddr);
+- }
+-
+- rb500_pata_finish_io(adev->link->ap);
+-}
+-
+-static void rb500_pata_freeze(struct ata_port *ap)
+-{
+- struct rb500_cf_info *info = ap->host->private_data;
+-
+- info->frozen = 1;
+-}
+-
+-static void rb500_pata_thaw(struct ata_port *ap)
+-{
+- struct rb500_cf_info *info = ap->host->private_data;
+-
+- info->frozen = 0;
+-}
+-
+-static irqreturn_t rb500_pata_irq_handler(int irq, void *dev_instance)
+-{
+- struct ata_host *ah = dev_instance;
+- struct rb500_cf_info *info = ah->private_data;
+-
+- 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);
+- } else {
+- set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
+- }
+-
+- 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,
+-
+- .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,
+-};
+-
+-/* ------------------------------------------------------------------------ */
+-
+-static void rb500_pata_setup_ports(struct ata_host *ah)
+-{
+- struct rb500_cf_info *info = ah->private_data;
+- struct ata_port *ap;
+-
+- ap = ah->ports[0];
+-
+- ap->ops = &rb500_pata_port_ops;
+- ap->pio_mask = 0x1f; /* PIO4 */
+- ap->flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
+-
+- ap->ioaddr.cmd_addr = info->iobase + RB500_CF_REG_CMD;
+- 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);
+-
+- ap->ioaddr.data_addr = info->iobase + RB500_CF_REG_DATA;
+-}
+-
+-static __devinit int rb500_pata_driver_probe(struct platform_device *pdev)
+-{
+- unsigned int irq;
+- int gpio;
+- struct resource *res;
+- struct ata_host *ah;
+- struct rb500_cf_info *info;
+- int ret;
+-
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- if (!res) {
+- dev_err(&pdev->dev, "no IOMEM resource found\n");
+- return -EINVAL;
+- }
+-
+- irq = platform_get_irq(pdev, 0);
+- if (irq <= 0) {
+- dev_err(&pdev->dev, "no IRQ resource found\n");
+- return -ENOENT;
+- }
+-
+- gpio = irq_to_gpio(irq);
+- if (gpio < 0) {
+- dev_err(&pdev->dev, "no GPIO found for irq%d\n", irq);
+- return -ENOENT;
+- }
+-
+- ret = gpio_request(gpio, DRV_NAME);
+- if (ret) {
+- dev_err(&pdev->dev, "GPIO request failed\n");
+- return ret;
+- }
+-
+- /* allocate host */
+- ah = ata_host_alloc(&pdev->dev, RB500_CF_MAXPORTS);
+- if (!ah)
+- return -ENOMEM;
+-
+- platform_set_drvdata(pdev, ah);
+-
+- info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+- if (!info)
+- return -ENOMEM;
+-
+- ah->private_data = info;
+- info->gpio_line = gpio;
+- info->irq = irq;
+-
+- info->iobase = devm_ioremap_nocache(&pdev->dev, res->start,
+- res->end - res->start + 1);
+- if (!info->iobase)
+- return -ENOMEM;
+-
+- ret = gpio_direction_input(gpio);
+- if (ret) {
+- dev_err(&pdev->dev, "unable to set GPIO direction, err=%d\n",
+- ret);
+- goto err_free_gpio;
+- }
+-
+- rb500_pata_setup_ports(ah);
+-
+- ret = ata_host_activate(ah, irq, rb500_pata_irq_handler,
+- IRQF_TRIGGER_LOW, &rb500_pata_sht);
+- if (ret)
+- goto err_free_gpio;
+-
+- return 0;
+-
+-err_free_gpio:
+- gpio_free(gpio);
+-
+- return ret;
+-}
+-
+-static __devexit int rb500_pata_driver_remove(struct platform_device *pdev)
+-{
+- struct ata_host *ah = platform_get_drvdata(pdev);
+- struct rb500_cf_info *info = ah->private_data;
+-
+- ata_host_detach(ah);
+- gpio_free(info->gpio_line);
+-
+- return 0;
+-}
+-
+-static struct platform_driver rb500_pata_platform_driver = {
+- .probe = rb500_pata_driver_probe,
+- .remove = __devexit_p(rb500_pata_driver_remove),
+- .driver = {
+- .name = DRV_NAME,
+- .owner = THIS_MODULE,
+- },
+-};
+-
+-/* ------------------------------------------------------------------------ */
+-
+-#define DRV_INFO DRV_DESC " version " DRV_VERSION
+-
+-static int __init rb500_pata_module_init(void)
+-{
+- printk(KERN_INFO DRV_INFO "\n");
+-
+- return platform_driver_register(&rb500_pata_platform_driver);
+-}
+-
+-static void __exit rb500_pata_module_exit(void)
+-{
+- platform_driver_unregister(&rb500_pata_platform_driver);
+-}
+-
+-MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
+-MODULE_AUTHOR("Florian Fainelli <florian at openwrt.org>");
+-MODULE_DESCRIPTION(DRV_DESC);
+-MODULE_VERSION(DRV_VERSION);
+-MODULE_LICENSE("GPL");
+-
+-module_init(rb500_pata_module_init);
+-module_exit(rb500_pata_module_exit);
+diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c
+new file mode 100644
+index 0000000..a108d25
+--- /dev/null
++++ b/drivers/ata/pata_rb532_cf.c
+@@ -0,0 +1,277 @@
++/*
++ * A low-level PATA driver to handle a Compact Flash connected on the
++ * Mikrotik's RouterBoard 532 board.
++ *
++ * Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org>
++ * Copyright (C) 2008 Florian Fainelli <florian at openwrt.org>
++ *
++ * This file was based on: drivers/ata/pata_ixp4xx_cf.c
++ * Copyright (C) 2006-07 Tower Technologies
++ * Author: Alessandro Zummo <a.zummo at towertech.it>
++ *
++ * Also was based on the driver for Linux 2.4.xx published by Mikrotik for
++ * their RouterBoard 1xx and 5xx series devices. The original Mikrotik code
++ * seems not to have a license.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <linux/io.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++
++#include <linux/libata.h>
++#include <scsi/scsi_host.h>
++
++#include <asm/gpio.h>
++
++#define DRV_NAME "pata-rb532-cf"
++#define DRV_VERSION "0.1.0"
++#define DRV_DESC "PATA driver for RouterBOARD 532 Compact Flash"
++
++#define RB500_CF_MAXPORTS 1
++#define RB500_CF_IO_DELAY 400
++
++#define RB500_CF_REG_CMD 0x0800
++#define RB500_CF_REG_CTRL 0x080E
++#define RB500_CF_REG_DATA 0x0C00
++
++struct rb532_cf_info {
++ void __iomem *iobase;
++ unsigned int gpio_line;
++ int frozen;
++ unsigned int irq;
++};
++
++/* ------------------------------------------------------------------------ */
++
++static inline void rb532_pata_finish_io(struct ata_port *ap)
++{
++ struct ata_host *ah = ap->host;
++ struct rb532_cf_info *info = ah->private_data;
++
++ ata_sff_altstatus(ap);
++ ndelay(RB500_CF_IO_DELAY);
++
++ set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
++}
++
++static void rb532_pata_exec_command(struct ata_port *ap,
++ const struct ata_taskfile *tf)
++{
++ writeb(tf->command, ap->ioaddr.command_addr);
++ rb532_pata_finish_io(ap);
++}
++
++static void rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
++ unsigned int buflen, int write_data)
++{
++ struct ata_port *ap = adev->link->ap;
++ void __iomem *ioaddr = ap->ioaddr.data_addr;
++
++ if (write_data) {
++ for (; buflen > 0; buflen--, buf++)
++ writeb(*buf, ioaddr);
++ } else {
++ for (; buflen > 0; buflen--, buf++)
++ *buf = readb(ioaddr);
++ }
++
++ rb532_pata_finish_io(adev->link->ap);
++}
++
++static void rb532_pata_freeze(struct ata_port *ap)
++{
++ struct rb532_cf_info *info = ap->host->private_data;
++
++ info->frozen = 1;
++}
++
++static void rb532_pata_thaw(struct ata_port *ap)
++{
++ struct rb532_cf_info *info = ap->host->private_data;
++
++ info->frozen = 0;
++}
++
++static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance)
++{
++ struct ata_host *ah = dev_instance;
++ struct rb532_cf_info *info = ah->private_data;
++
++ if (gpio_get_value(info->gpio_line)) {
++ set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW);
++ if (!info->frozen)
++ ata_sff_interrupt(info->irq, dev_instance);
++ } else {
++ set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
++ }
++
++ return IRQ_HANDLED;
++}
++
++static struct ata_port_operations rb532_pata_port_ops = {
++ .inherits = &ata_sff_port_ops,
++ .sff_exec_command = rb532_pata_exec_command,
++ .sff_data_xfer = rb532_pata_data_xfer,
++ .freeze = rb532_pata_freeze,
++ .thaw = rb532_pata_thaw,
++};
++
++/* ------------------------------------------------------------------------ */
++
++static struct scsi_host_template rb532_pata_sht = {
++ ATA_PIO_SHT(DRV_NAME),
++};
++
++/* ------------------------------------------------------------------------ */
++
++static void rb532_pata_setup_ports(struct ata_host *ah)
++{
++ struct rb532_cf_info *info = ah->private_data;
++ struct ata_port *ap;
++
++ ap = ah->ports[0];
++
++ ap->ops = &rb532_pata_port_ops;
++ ap->pio_mask = 0x1f; /* PIO4 */
++ ap->flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
++
++ ap->ioaddr.cmd_addr = info->iobase + RB500_CF_REG_CMD;
++ ap->ioaddr.ctl_addr = info->iobase + RB500_CF_REG_CTRL;
++ ap->ioaddr.altstatus_addr = info->iobase + RB500_CF_REG_CTRL;
++
++ ata_sff_std_ports(&ap->ioaddr);
++
++ ap->ioaddr.data_addr = info->iobase + RB500_CF_REG_DATA;
++}
++
++static __devinit int rb532_pata_driver_probe(struct platform_device *pdev)
++{
++ unsigned int irq;
++ int gpio;
++ struct resource *res;
++ struct ata_host *ah;
++ struct rb532_cf_info *info;
++ int ret;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev, "no IOMEM resource found\n");
++ return -EINVAL;
++ }
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq <= 0) {
++ dev_err(&pdev->dev, "no IRQ resource found\n");
++ return -ENOENT;
++ }
++
++ gpio = irq_to_gpio(irq);
++ if (gpio < 0) {
++ dev_err(&pdev->dev, "no GPIO found for irq%d\n", irq);
++ return -ENOENT;
++ }
++
++ ret = gpio_request(gpio, DRV_NAME);
++ if (ret) {
++ dev_err(&pdev->dev, "GPIO request failed\n");
++ return ret;
++ }
++
++ /* allocate host */
++ ah = ata_host_alloc(&pdev->dev, RB500_CF_MAXPORTS);
++ if (!ah)
++ return -ENOMEM;
++
++ platform_set_drvdata(pdev, ah);
++
++ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
++ if (!info)
++ return -ENOMEM;
++
++ ah->private_data = info;
++ info->gpio_line = gpio;
++ info->irq = irq;
++
++ info->iobase = devm_ioremap_nocache(&pdev->dev, res->start,
++ res->end - res->start + 1);
++ if (!info->iobase)
++ return -ENOMEM;
++
++ ret = gpio_direction_input(gpio);
++ if (ret) {
++ dev_err(&pdev->dev, "unable to set GPIO direction, err=%d\n",
++ ret);
++ goto err_free_gpio;
++ }
++
++ rb532_pata_setup_ports(ah);
++
++ ret = ata_host_activate(ah, irq, rb532_pata_irq_handler,
++ IRQF_TRIGGER_LOW, &rb532_pata_sht);
++ if (ret)
++ goto err_free_gpio;
++
++ return 0;
++
++err_free_gpio:
++ gpio_free(gpio);
++
++ return ret;
++}
++
++static __devexit int rb532_pata_driver_remove(struct platform_device *pdev)
++{
++ struct ata_host *ah = platform_get_drvdata(pdev);
++ struct rb532_cf_info *info = ah->private_data;
++
++ ata_host_detach(ah);
++ gpio_free(info->gpio_line);
++
++ return 0;
++}
++
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:" DRV_NAME);
++
++static struct platform_driver rb532_pata_platform_driver = {
++ .probe = rb532_pata_driver_probe,
++ .remove = __devexit_p(rb532_pata_driver_remove),
++ .driver = {
++ .name = DRV_NAME,
++ .owner = THIS_MODULE,
++ },
++};
++
++/* ------------------------------------------------------------------------ */
++
++#define DRV_INFO DRV_DESC " version " DRV_VERSION
++
++static int __init rb532_pata_module_init(void)
++{
++ printk(KERN_INFO DRV_INFO "\n");
++
++ return platform_driver_register(&rb532_pata_platform_driver);
++}
++
++static void __exit rb532_pata_module_exit(void)
++{
++ platform_driver_unregister(&rb532_pata_platform_driver);
++}
++
++MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
++MODULE_AUTHOR("Florian Fainelli <florian at openwrt.org>");
++MODULE_DESCRIPTION(DRV_DESC);
++MODULE_VERSION(DRV_VERSION);
++MODULE_LICENSE("GPL");
++
++module_init(rb532_pata_module_init);
++module_exit(rb532_pata_module_exit);
+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..2fea6cb 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++)
+@@ -547,11 +464,12 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ }
+ pci_dev_put(isa);
+
+- /* 0x40 low bits indicate enabled channels */
+- pci_read_config_byte(pdev, 0x40 , &enable);
+- enable &= 3;
+- if (enable == 0) {
+- return -ENODEV;
++ if (!(config->flags & VIA_NO_ENABLES)) {
++ /* 0x40 low bits indicate enabled channels */
++ pci_read_config_byte(pdev, 0x40 , &enable);
++ enable &= 3;
++ if (enable == 0)
++ return -ENODEV;
+ }
+
+ /* Initialise the FIFO for the enabled channels. */
+@@ -561,25 +479,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 +512,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 +531,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 +551,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..853559e 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_link *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..842b1a1 100644
+--- a/drivers/ata/sata_mv.c
++++ b/drivers/ata/sata_mv.c
+@@ -1,6 +1,7 @@
+ /*
+ * sata_mv.c - Marvell SATA support
+ *
++ * Copyright 2008: Marvell Corporation, all rights reserved.
+ * Copyright 2005: EMC Corporation, all rights reserved.
+ * Copyright 2005 Red Hat, Inc. All rights reserved.
+ *
+@@ -22,45 +23,34 @@
+ */
+
+ /*
+- sata_mv TODO list:
+-
+- 1) Needs a full errata audit for all chipsets. I implemented most
+- of the errata workarounds found in the Marvell vendor driver, but
+- I distinctly remember a couple workarounds (one related to PCI-X)
+- are still needed.
+-
+- 2) Improve/fix IRQ and error handling sequences.
+-
+- 3) ATAPI support (Marvell claims the 60xx/70xx chips can do it).
+-
+- 4) Think about TCQ support here, and for libata in general
+- with controllers that suppport it via host-queuing hardware
+- (a software-only implementation could be a nightmare).
+-
+- 5) Investigate problems with PCI Message Signalled Interrupts (MSI).
+-
+- 6) Add port multiplier support (intermediate)
+-
+- 8) Develop a low-power-consumption strategy, and implement it.
+-
+- 9) [Experiment, low priority] See if ATAPI can be supported using
+- "unknown FIS" or "vendor-specific FIS" support, or something creative
+- like that.
+-
+- 10) [Experiment, low priority] Investigate interrupt coalescing.
+- Quite often, especially with PCI Message Signalled Interrupts (MSI),
+- the overhead reduced by interrupt mitigation is quite often not
+- worth the latency cost.
+-
+- 11) [Experiment, Marvell value added] Is it possible to use target
+- mode to cross-connect two Linux boxes with Marvell cards? If so,
+- creating LibATA target mode support would be very interesting.
+-
+- Target mode, for those without docs, is the ability to directly
+- connect two SATA controllers.
+-
+-*/
+-
++ * sata_mv TODO list:
++ *
++ * --> Errata workaround for NCQ device errors.
++ *
++ * --> More errata workarounds for PCI-X.
++ *
++ * --> Complete a full errata audit for all chipsets to identify others.
++ *
++ * --> ATAPI support (Marvell claims the 60xx/70xx chips can do it).
++ *
++ * --> Investigate problems with PCI Message Signalled Interrupts (MSI).
++ *
++ * --> Cache frequently-accessed registers in mv_port_priv to reduce overhead.
++ *
++ * --> Develop a low-power-consumption strategy, and implement it.
++ *
++ * --> [Experiment, low priority] Investigate interrupt coalescing.
++ * Quite often, especially with PCI Message Signalled Interrupts (MSI),
++ * the overhead reduced by interrupt mitigation is quite often not
++ * worth the latency cost.
++ *
++ * --> [Experiment, Marvell value added] Is it possible to use target
++ * mode to cross-connect two Linux boxes with Marvell cards? If so,
++ * creating LibATA target mode support would be very interesting.
++ *
++ * Target mode, for those without docs, is the ability to directly
++ * connect two SATA ports.
++ */
+
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+@@ -74,6 +64,7 @@
+ #include <linux/device.h>
+ #include <linux/platform_device.h>
+ #include <linux/ata_platform.h>
++#include <linux/mbus.h>
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi_cmnd.h>
+ #include <scsi/scsi_device.h>
+@@ -121,17 +112,17 @@ enum {
+ MV_MAX_SG_CT = 256,
+ MV_SG_TBL_SZ = (16 * MV_MAX_SG_CT),
+
+- MV_PORTS_PER_HC = 4,
+- /* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
++ /* Determine hc from 0-7 port: hc = port >> MV_PORT_HC_SHIFT */
+ MV_PORT_HC_SHIFT = 2,
+- /* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
+- MV_PORT_MASK = 3,
++ MV_PORTS_PER_HC = (1 << MV_PORT_HC_SHIFT), /* 4 */
++ /* Determine hc port from 0-7 port: hardport = port & MV_PORT_MASK */
++ MV_PORT_MASK = (MV_PORTS_PER_HC - 1), /* 3 */
+
+ /* Host Flags */
+ MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */
+ MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */
+ /* SoC integrated controllers, no PCI interface */
+- MV_FLAG_SOC = (1 << 28),
++ MV_FLAG_SOC = (1 << 28),
+
+ MV_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
+@@ -141,6 +132,7 @@ enum {
+ CRQB_FLAG_READ = (1 << 0),
+ CRQB_TAG_SHIFT = 1,
+ CRQB_IOID_SHIFT = 6, /* CRQB Gen-II/IIE IO Id shift */
++ CRQB_PMP_SHIFT = 12, /* CRQB Gen-II/IIE PMP shift */
+ CRQB_HOSTQ_SHIFT = 17, /* CRQB Gen-II/IIE HostQueTag shift */
+ CRQB_CMD_ADDR_SHIFT = 8,
+ CRQB_CMD_CS = (0x2 << 11),
+@@ -180,12 +172,13 @@ enum {
+ PCIE_IRQ_MASK_OFS = 0x1910,
+ PCIE_UNMASK_ALL_IRQS = 0x40a, /* assorted bits */
+
+- HC_MAIN_IRQ_CAUSE_OFS = 0x1d60,
+- 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 # */
++ /* Host Controller Main Interrupt Cause/Mask registers (1 per-chip) */
++ PCI_HC_MAIN_IRQ_CAUSE_OFS = 0x1d60,
++ PCI_HC_MAIN_IRQ_MASK_OFS = 0x1d64,
++ SOC_HC_MAIN_IRQ_CAUSE_OFS = 0x20020,
++ SOC_HC_MAIN_IRQ_MASK_OFS = 0x20024,
++ 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 +192,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 +205,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 +217,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 +245,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 +305,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 +337,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 +354,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 +361,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().
+@@ -434,8 +446,8 @@ struct mv_host_priv {
+ const struct mv_hw_ops *ops;
+ int n_ports;
+ void __iomem *base;
+- void __iomem *main_cause_reg_addr;
+- void __iomem *main_mask_reg_addr;
++ void __iomem *main_irq_cause_addr;
++ void __iomem *main_irq_mask_addr;
+ u32 irq_cause_ofs;
+ u32 irq_mask_ofs;
+ u32 unmask_all_irqs;
+@@ -461,7 +473,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 +482,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 +516,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 +564,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 +605,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 +613,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 +621,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 +629,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 +712,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 +722,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 main_irq_cause / main_irq_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 +758,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 +782,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 +791,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 +808,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 +843,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 +857,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 +873,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 +1035,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 +1100,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 +1162,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 +1194,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 +1212,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 +1298,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 +1383,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 +1448,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 +1470,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 +1525,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 +1608,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_irq_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_irq_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_irq_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 +1780,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 +1790,7 @@ static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
+ ata_port_freeze(ap);
+ }
+ }
++ return 1; /* handled */
+ }
+
+ /**
+@@ -1810,51 +1811,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_irq_cause, main_irq_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_irq_cause = readl(hpriv->main_irq_cause_addr);
++ main_irq_mask = readl(hpriv->main_irq_mask_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_irq_cause & main_irq_mask) && (main_irq_cause != 0xffffffffU)) {
++ if (unlikely((main_irq_cause & PCI_ERR) && HAS_PCI(host)))
++ handled = mv_pci_error(host, hpriv->base);
++ else
++ handled = mv_host_intr(host, main_irq_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 +1956,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);
+@@ -2049,7 +2028,7 @@ static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio)
+ ZERO(MV_PCI_DISC_TIMER);
+ ZERO(MV_PCI_MSI_TRIGGER);
+ writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
+- ZERO(HC_MAIN_IRQ_MASK_OFS);
++ ZERO(PCI_HC_MAIN_IRQ_MASK_OFS);
+ ZERO(MV_PCI_SERR_MASK);
+ ZERO(hpriv->irq_cause_ofs);
+ ZERO(hpriv->irq_mask_ofs);
+@@ -2200,14 +2179,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 +2235,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 +2297,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 +2338,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 +2371,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_irq_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_irq_mask = readl(hpriv->main_irq_mask_addr);
++ main_irq_mask &= ~((DONE_IRQ | ERR_IRQ) << shift);
++ writelfl(main_irq_mask, hpriv->main_irq_mask_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_irq_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_irq_mask = readl(hpriv->main_irq_mask_addr);
++ main_irq_mask |= ((DONE_IRQ | ERR_IRQ) << shift);
++ writelfl(main_irq_mask, hpriv->main_irq_mask_addr);
+ }
+
+ /**
+@@ -2779,20 +2652,18 @@ 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_irq_cause_addr = mmio + PCI_HC_MAIN_IRQ_CAUSE_OFS;
++ hpriv->main_irq_mask_addr = mmio + PCI_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_irq_cause_addr = mmio + SOC_HC_MAIN_IRQ_CAUSE_OFS;
++ hpriv->main_irq_mask_addr = mmio + SOC_HC_MAIN_IRQ_MASK_OFS;
+ }
+- /* global interrupt mask */
+- writel(0, hpriv->main_mask_reg_addr);
++
++ /* global interrupt mask: 0 == mask everything */
++ writel(0, hpriv->main_irq_mask_addr);
+
+ n_hc = mv_get_hc_count(host->ports[0]->flags);
+
+@@ -2808,19 +2679,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);
+
+@@ -2855,23 +2713,23 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
+ writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
+ if (IS_GEN_I(hpriv))
+ writelfl(~HC_MAIN_MASKED_IRQS_5,
+- hpriv->main_mask_reg_addr);
++ hpriv->main_irq_mask_addr);
+ else
+ writelfl(~HC_MAIN_MASKED_IRQS,
+- hpriv->main_mask_reg_addr);
++ hpriv->main_irq_mask_addr);
+
+ VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
+ "PCI int cause/mask=0x%08x/0x%08x\n",
+- readl(hpriv->main_cause_reg_addr),
+- readl(hpriv->main_mask_reg_addr),
++ readl(hpriv->main_irq_cause_addr),
++ readl(hpriv->main_irq_mask_addr),
+ readl(mmio + hpriv->irq_cause_ofs),
+ readl(mmio + hpriv->irq_mask_ofs));
+ } else {
+ writelfl(~HC_MAIN_MASKED_IRQS_SOC,
+- hpriv->main_mask_reg_addr);
++ hpriv->main_irq_mask_addr);
+ VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x\n",
+- readl(hpriv->main_cause_reg_addr),
+- readl(hpriv->main_mask_reg_addr));
++ readl(hpriv->main_irq_cause_addr),
++ readl(hpriv->main_irq_mask_addr));
+ }
+ done:
+ return rc;
+@@ -2897,6 +2755,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 +2830,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 +3077,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..6adb72a 100644
+--- a/drivers/atm/ambassador.c
++++ b/drivers/atm/ambassador.c
+@@ -33,6 +33,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/poison.h>
+ #include <linux/bitrev.h>
++#include <linux/mutex.h>
+
+ #include <asm/atomic.h>
+ #include <asm/io.h>
+@@ -437,7 +438,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 +457,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 +467,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 +644,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 +676,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 +704,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 +729,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 +762,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 +797,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 +847,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 +855,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);
+@@ -1177,7 +1178,7 @@ static int amb_open (struct atm_vcc * atm_vcc)
+
+ vcc->tx_frame_bits = tx_frame_bits;
+
+- down (&dev->vcc_sf);
++ mutex_lock(&dev->vcc_sf);
+ if (dev->rxer[vci]) {
+ // RXer on the channel already, just modify rate...
+ cmd.request = cpu_to_be32 (SRB_MODIFY_VC_RATE);
+@@ -1203,7 +1204,7 @@ static int amb_open (struct atm_vcc * atm_vcc)
+ schedule();
+ }
+ dev->txer[vci].tx_present = 1;
+- up (&dev->vcc_sf);
++ mutex_unlock(&dev->vcc_sf);
+ }
+
+ if (rxtp->traffic_class != ATM_NONE) {
+@@ -1211,7 +1212,7 @@ static int amb_open (struct atm_vcc * atm_vcc)
+
+ vcc->rx_info.pool = pool;
+
+- down (&dev->vcc_sf);
++ mutex_lock(&dev->vcc_sf);
+ /* grow RX buffer pool */
+ if (!dev->rxq[pool].buffers_wanted)
+ dev->rxq[pool].buffers_wanted = rx_lats;
+@@ -1237,7 +1238,7 @@ static int amb_open (struct atm_vcc * atm_vcc)
+ schedule();
+ // this link allows RX frames through
+ dev->rxer[vci] = atm_vcc;
+- up (&dev->vcc_sf);
++ mutex_unlock(&dev->vcc_sf);
+ }
+
+ // indicate readiness
+@@ -1262,7 +1263,7 @@ static void amb_close (struct atm_vcc * atm_vcc) {
+ if (atm_vcc->qos.txtp.traffic_class != ATM_NONE) {
+ command cmd;
+
+- down (&dev->vcc_sf);
++ mutex_lock(&dev->vcc_sf);
+ if (dev->rxer[vci]) {
+ // RXer still on the channel, just modify rate... XXX not really needed
+ cmd.request = cpu_to_be32 (SRB_MODIFY_VC_RATE);
+@@ -1277,7 +1278,7 @@ static void amb_close (struct atm_vcc * atm_vcc) {
+ dev->txer[vci].tx_present = 0;
+ while (command_do (dev, &cmd))
+ schedule();
+- up (&dev->vcc_sf);
++ mutex_unlock(&dev->vcc_sf);
+ }
+
+ // disable RXing
+@@ -1287,7 +1288,7 @@ static void amb_close (struct atm_vcc * atm_vcc) {
+ // this is (the?) one reason why we need the amb_vcc struct
+ unsigned char pool = vcc->rx_info.pool;
+
+- down (&dev->vcc_sf);
++ mutex_lock(&dev->vcc_sf);
+ if (dev->txer[vci].tx_present) {
+ // TXer still on the channel, just go to pool zero XXX not really needed
+ cmd.request = cpu_to_be32 (SRB_MODIFY_VC_FLAGS);
+@@ -1314,7 +1315,7 @@ static void amb_close (struct atm_vcc * atm_vcc) {
+ dev->rxq[pool].buffers_wanted = 0;
+ drain_rx_pool (dev, pool);
+ }
+- up (&dev->vcc_sf);
++ mutex_unlock(&dev->vcc_sf);
+ }
+
+ // free our structure
+@@ -2188,7 +2189,7 @@ static void setup_dev(amb_dev *dev, struct pci_dev *pci_dev)
+
+ // semaphore for txer/rxer modifications - we cannot use a
+ // spinlock as the critical region needs to switch processes
+- init_MUTEX (&dev->vcc_sf);
++ mutex_init(&dev->vcc_sf);
+ // queue manipulation spinlocks; we want atomic reads and
+ // writes to the queue descriptors (handles IRQ and SMP)
+ // consider replacing "int pending" -> "atomic_t available"
+diff --git a/drivers/atm/ambassador.h b/drivers/atm/ambassador.h
+index ff2a303..df55fa8 100644
+--- a/drivers/atm/ambassador.h
++++ b/drivers/atm/ambassador.h
+@@ -638,7 +638,7 @@ struct amb_dev {
+ amb_txq txq;
+ amb_rxq rxq[NUM_RX_POOLS];
+
+- struct semaphore vcc_sf;
++ struct mutex vcc_sf;
+ amb_tx_info txer[NUM_VCS];
+ struct atm_vcc * rxer[NUM_VCS];
+ unsigned int tx_avail;
+diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
+index 9b2cf25..c0ac728 100644
+--- a/drivers/atm/horizon.c
++++ b/drivers/atm/horizon.c
+@@ -424,7 +424,7 @@ static inline void FLUSH_RX_CHANNEL (hrz_dev * dev, u16 channel) {
+ return;
+ }
+
+-static inline void WAIT_FLUSH_RX_COMPLETE (hrz_dev * dev) {
++static void WAIT_FLUSH_RX_COMPLETE (hrz_dev * dev) {
+ while (rd_regw (dev, RX_CHANNEL_PORT_OFF) & FLUSH_CHANNEL)
+ ;
+ return;
+@@ -435,7 +435,7 @@ static inline void SELECT_RX_CHANNEL (hrz_dev * dev, u16 channel) {
+ return;
+ }
+
+-static inline void WAIT_UPDATE_COMPLETE (hrz_dev * dev) {
++static void WAIT_UPDATE_COMPLETE (hrz_dev * dev) {
+ while (rd_regw (dev, RX_CHANNEL_PORT_OFF) & RX_CHANNEL_UPDATE_IN_PROGRESS)
+ ;
+ return;
+@@ -796,7 +796,7 @@ static void hrz_change_vc_qos (ATM_RXER * rxer, MAAL_QOS * qos) {
+
+ /********** free an skb (as per ATM device driver documentation) **********/
+
+-static inline void hrz_kfree_skb (struct sk_buff * skb) {
++static void hrz_kfree_skb (struct sk_buff * skb) {
+ if (ATM_SKB(skb)->vcc->pop) {
+ ATM_SKB(skb)->vcc->pop (ATM_SKB(skb)->vcc, skb);
+ } else {
+@@ -1076,7 +1076,7 @@ static void rx_schedule (hrz_dev * dev, int irq) {
+
+ /********** handle RX bus master complete events **********/
+
+-static inline void rx_bus_master_complete_handler (hrz_dev * dev) {
++static void rx_bus_master_complete_handler (hrz_dev * dev) {
+ if (test_bit (rx_busy, &dev->flags)) {
+ rx_schedule (dev, 1);
+ } else {
+@@ -1089,7 +1089,7 @@ static inline void rx_bus_master_complete_handler (hrz_dev * dev) {
+
+ /********** (queue to) become the next TX thread **********/
+
+-static inline int tx_hold (hrz_dev * dev) {
++static int tx_hold (hrz_dev * dev) {
+ PRINTD (DBG_TX, "sleeping at tx lock %p %lu", dev, dev->flags);
+ wait_event_interruptible(dev->tx_queue, (!test_and_set_bit(tx_busy, &dev->flags)));
+ PRINTD (DBG_TX, "woken at tx lock %p %lu", dev, dev->flags);
+@@ -1232,7 +1232,7 @@ static void tx_schedule (hrz_dev * const dev, int irq) {
+
+ /********** handle TX bus master complete events **********/
+
+-static inline void tx_bus_master_complete_handler (hrz_dev * dev) {
++static void tx_bus_master_complete_handler (hrz_dev * dev) {
+ if (test_bit (tx_busy, &dev->flags)) {
+ tx_schedule (dev, 1);
+ } else {
+@@ -1246,7 +1246,7 @@ static inline void tx_bus_master_complete_handler (hrz_dev * dev) {
+ /********** move RX Q pointer to next item in circular buffer **********/
+
+ // called only from IRQ sub-handler
+-static inline u32 rx_queue_entry_next (hrz_dev * dev) {
++static u32 rx_queue_entry_next (hrz_dev * dev) {
+ u32 rx_queue_entry;
+ spin_lock (&dev->mem_lock);
+ rx_queue_entry = rd_mem (dev, &dev->rx_q_entry->entry);
+@@ -1270,7 +1270,7 @@ static inline void rx_disabled_handler (hrz_dev * dev) {
+ /********** handle RX data received by device **********/
+
+ // called from IRQ handler
+-static inline void rx_data_av_handler (hrz_dev * dev) {
++static void rx_data_av_handler (hrz_dev * dev) {
+ u32 rx_queue_entry;
+ u32 rx_queue_entry_flags;
+ u16 rx_len;
+@@ -1394,7 +1394,7 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id)
+ irq_ok = 0;
+ while ((int_source = rd_regl (dev, INT_SOURCE_REG_OFF)
+ & INTERESTING_INTERRUPTS)) {
+- // In the interests of fairness, the (inline) handlers below are
++ // In the interests of fairness, the handlers below are
+ // called in sequence and without immediate return to the head of
+ // the while loop. This is only of issue for slow hosts (or when
+ // debugging messages are on). Really slow hosts may find a fast
+@@ -1458,7 +1458,7 @@ static void do_housekeeping (unsigned long arg) {
+ /********** find an idle channel for TX and set it up **********/
+
+ // called with tx_busy set
+-static inline short setup_idle_tx_channel (hrz_dev * dev, hrz_vcc * vcc) {
++static short setup_idle_tx_channel (hrz_dev * dev, hrz_vcc * vcc) {
+ unsigned short idle_channels;
+ short tx_channel = -1;
+ unsigned int spin_count;
+@@ -1777,13 +1777,13 @@ static void hrz_reset (const hrz_dev * dev) {
+
+ /********** read the burnt in address **********/
+
+-static inline void WRITE_IT_WAIT (const hrz_dev *dev, u32 ctrl)
++static void WRITE_IT_WAIT (const hrz_dev *dev, u32 ctrl)
+ {
+ wr_regl (dev, CONTROL_0_REG, ctrl);
+ udelay (5);
+ }
+
+-static inline void CLOCK_IT (const hrz_dev *dev, u32 ctrl)
++static void CLOCK_IT (const hrz_dev *dev, u32 ctrl)
+ {
+ // DI must be valid around rising SK edge
+ WRITE_IT_WAIT(dev, ctrl & ~SEEPROM_SK);
+diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
+index 670c093..5c28ca7 100644
+--- a/drivers/atm/iphase.c
++++ b/drivers/atm/iphase.c
+@@ -60,7 +60,8 @@
+ #include <asm/uaccess.h>
+ #include <asm/string.h>
+ #include <asm/byteorder.h>
+-#include <linux/vmalloc.h>
++#include <linux/vmalloc.h>
++#include <linux/jiffies.h>
+ #include "iphase.h"
+ #include "suni.h"
+ #define swap(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))
+@@ -189,7 +190,7 @@ static u16 get_desc (IADEV *dev, struct ia_vcc *iavcc) {
+ int ltimeout;
+
+ ia_hack_tcq (dev);
+- if(((jiffies - timer)>50)||((dev->ffL.tcq_rd==dev->host_tcq_wr))){
++ if((time_after(jiffies,timer+50)) || ((dev->ffL.tcq_rd==dev->host_tcq_wr))) {
+ timer = jiffies;
+ i=0;
+ while (i < dev->num_tx_desc) {
+@@ -1225,7 +1226,7 @@ static void rx_intr(struct atm_dev *dev)
+ iadev->rx_tmp_jif = jiffies;
+ iadev->rxing = 0;
+ }
+- else if (((jiffies - iadev->rx_tmp_jif) > 50) &&
++ else if ((time_after(jiffies, iadev->rx_tmp_jif + 50)) &&
+ ((iadev->rx_pkt_cnt - iadev->rx_tmp_cnt) == 0)) {
+ for (i = 1; i <= iadev->num_rx_desc; i++)
+ free_desc(dev, i);
+diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
+index 0c205b0..3da804b 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);
+@@ -494,7 +415,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
+ card->pcidev = pcidev;
+ membase = pci_resource_start(pcidev, 1);
+ card->membase = ioremap(membase, NS_IOREMAP_SIZE);
+- if (card->membase == 0)
++ if (!card->membase)
+ {
+ printk("nicstar%d: can't ioremap() membase.\n",i);
+ error = 3;
+@@ -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/base.h b/drivers/base/base.h
+index c044414..2c9ae43 100644
+--- a/drivers/base/base.h
++++ b/drivers/base/base.h
+@@ -64,17 +64,6 @@ extern void sysdev_shutdown(void);
+ extern int sysdev_suspend(pm_message_t state);
+ extern int sysdev_resume(void);
+
+-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);
+-}
+-
+ extern char *make_class_name(const char *name, struct kobject *kobj);
+
+ extern int devres_release_all(struct device *dev);
+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..0ef00e8 100644
+--- a/drivers/base/class.c
++++ b/drivers/base/class.c
+@@ -175,31 +175,17 @@ 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);
+- kfree(class_dev);
+-}
+-
+-/* needed to allow these devices to have parent class devices */
+-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);
+- return 0;
+-}
+-
+ /**
+ * class_create - create a struct class structure
+ * @owner: pointer to the module that is to "own" this struct class
+ * @name: pointer to a string for the name of this class.
+ *
+ * This is used to create a struct class pointer that can then be used
+- * in calls to class_device_create().
++ * in calls to device_create().
+ *
+ * Note, the pointer created here is to be destroyed when finished by
+ * making a call to class_destroy().
+@@ -218,7 +204,6 @@ struct class *class_create(struct module *owner, const char *name)
+ cls->name = name;
+ cls->owner = owner;
+ cls->class_release = class_create_release;
+- cls->release = class_device_create_release;
+
+ retval = class_register(cls);
+ if (retval)
+@@ -246,113 +231,6 @@ void class_destroy(struct class *cls)
+ class_unregister(cls);
+ }
+
+-/* Class Device Stuff */
+-
+-int class_device_create_file(struct class_device *class_dev,
+- const struct class_device_attribute *attr)
+-{
+- int error = -EINVAL;
+- if (class_dev)
+- error = sysfs_create_file(&class_dev->kobj, &attr->attr);
+- return error;
+-}
+-
+-void class_device_remove_file(struct class_device *class_dev,
+- const struct class_device_attribute *attr)
+-{
+- if (class_dev)
+- sysfs_remove_file(&class_dev->kobj, &attr->attr);
+-}
+-
+-int class_device_create_bin_file(struct class_device *class_dev,
+- struct bin_attribute *attr)
+-{
+- int error = -EINVAL;
+- if (class_dev)
+- error = sysfs_create_bin_file(&class_dev->kobj, attr);
+- return error;
+-}
+-
+-void class_device_remove_bin_file(struct class_device *class_dev,
+- struct bin_attribute *attr)
+-{
+- if (class_dev)
+- sysfs_remove_bin_file(&class_dev->kobj, attr);
+-}
+-
+-static ssize_t class_device_attr_show(struct kobject *kobj,
+- struct attribute *attr, char *buf)
+-{
+- struct class_device_attribute *class_dev_attr = to_class_dev_attr(attr);
+- struct class_device *cd = to_class_dev(kobj);
+- ssize_t ret = 0;
+-
+- if (class_dev_attr->show)
+- ret = class_dev_attr->show(cd, buf);
+- return ret;
+-}
+-
+-static ssize_t class_device_attr_store(struct kobject *kobj,
+- struct attribute *attr,
+- const char *buf, size_t count)
+-{
+- struct class_device_attribute *class_dev_attr = to_class_dev_attr(attr);
+- struct class_device *cd = to_class_dev(kobj);
+- ssize_t ret = 0;
+-
+- if (class_dev_attr->store)
+- ret = class_dev_attr->store(cd, buf, count);
+- return ret;
+-}
+-
+-static struct sysfs_ops class_dev_sysfs_ops = {
+- .show = class_device_attr_show,
+- .store = class_device_attr_store,
+-};
+-
+-static void class_dev_release(struct kobject *kobj)
+-{
+- struct class_device *cd = to_class_dev(kobj);
+- struct class *cls = cd->class;
+-
+- pr_debug("device class '%s': release.\n", cd->class_id);
+-
+- if (cd->release)
+- cd->release(cd);
+- else if (cls->release)
+- cls->release(cd);
+- else {
+- printk(KERN_ERR "Class Device '%s' does not have a release() "
+- "function, it is broken and must be fixed.\n",
+- cd->class_id);
+- WARN_ON(1);
+- }
+-}
+-
+-static struct kobj_type class_device_ktype = {
+- .sysfs_ops = &class_dev_sysfs_ops,
+- .release = class_dev_release,
+-};
+-
+-static int class_uevent_filter(struct kset *kset, struct kobject *kobj)
+-{
+- struct kobj_type *ktype = get_ktype(kobj);
+-
+- if (ktype == &class_device_ktype) {
+- struct class_device *class_dev = to_class_dev(kobj);
+- if (class_dev->class)
+- return 1;
+- }
+- return 0;
+-}
+-
+-static const char *class_uevent_name(struct kset *kset, struct kobject *kobj)
+-{
+- struct class_device *class_dev = to_class_dev(kobj);
+-
+- return class_dev->class->name;
+-}
+-
+ #ifdef CONFIG_SYSFS_DEPRECATED
+ char *make_class_name(const char *name, struct kobject *kobj)
+ {
+@@ -370,445 +248,8 @@ char *make_class_name(const char *name, struct kobject *kobj)
+ strcat(class_name, kobject_name(kobj));
+ return class_name;
+ }
+-
+-static int make_deprecated_class_device_links(struct class_device *class_dev)
+-{
+- char *class_name;
+- int error;
+-
+- if (!class_dev->dev)
+- return 0;
+-
+- class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
+- if (class_name)
+- error = sysfs_create_link(&class_dev->dev->kobj,
+- &class_dev->kobj, class_name);
+- else
+- error = -ENOMEM;
+- kfree(class_name);
+- return error;
+-}
+-
+-static void remove_deprecated_class_device_links(struct class_device *class_dev)
+-{
+- char *class_name;
+-
+- if (!class_dev->dev)
+- return;
+-
+- class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
+- if (class_name)
+- sysfs_remove_link(&class_dev->dev->kobj, class_name);
+- kfree(class_name);
+-}
+-#else
+-static inline int make_deprecated_class_device_links(struct class_device *cd)
+-{ return 0; }
+-static void remove_deprecated_class_device_links(struct class_device *cd)
+-{ }
+ #endif
+
+-static int class_uevent(struct kset *kset, struct kobject *kobj,
+- struct kobj_uevent_env *env)
+-{
+- struct class_device *class_dev = to_class_dev(kobj);
+- struct device *dev = class_dev->dev;
+- int retval = 0;
+-
+- pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
+-
+- if (MAJOR(class_dev->devt)) {
+- add_uevent_var(env, "MAJOR=%u", MAJOR(class_dev->devt));
+-
+- add_uevent_var(env, "MINOR=%u", MINOR(class_dev->devt));
+- }
+-
+- if (dev) {
+- const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
+- if (path) {
+- add_uevent_var(env, "PHYSDEVPATH=%s", path);
+- kfree(path);
+- }
+-
+- if (dev->bus)
+- add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
+-
+- if (dev->driver)
+- add_uevent_var(env, "PHYSDEVDRIVER=%s",
+- dev->driver->name);
+- }
+-
+- if (class_dev->uevent) {
+- /* have the class device specific function add its stuff */
+- retval = class_dev->uevent(class_dev, env);
+- if (retval)
+- pr_debug("class_dev->uevent() returned %d\n", retval);
+- } else if (class_dev->class->uevent) {
+- /* have the class specific function add its stuff */
+- retval = class_dev->class->uevent(class_dev, env);
+- if (retval)
+- pr_debug("class->uevent() returned %d\n", retval);
+- }
+-
+- return retval;
+-}
+-
+-static struct kset_uevent_ops class_uevent_ops = {
+- .filter = class_uevent_filter,
+- .name = class_uevent_name,
+- .uevent = class_uevent,
+-};
+-
+-/*
+- * DO NOT copy how this is created, kset_create_and_add() should be
+- * called, but this is a hold-over from the old-way and will be deleted
+- * entirely soon.
+- */
+-static struct kset class_obj_subsys = {
+- .uevent_ops = &class_uevent_ops,
+-};
+-
+-static int class_device_add_attrs(struct class_device *cd)
+-{
+- int i;
+- int error = 0;
+- struct class *cls = cd->class;
+-
+- if (cls->class_dev_attrs) {
+- for (i = 0; attr_name(cls->class_dev_attrs[i]); i++) {
+- error = class_device_create_file(cd,
+- &cls->class_dev_attrs[i]);
+- if (error)
+- goto err;
+- }
+- }
+-done:
+- return error;
+-err:
+- while (--i >= 0)
+- class_device_remove_file(cd, &cls->class_dev_attrs[i]);
+- goto done;
+-}
+-
+-static void class_device_remove_attrs(struct class_device *cd)
+-{
+- int i;
+- struct class *cls = cd->class;
+-
+- if (cls->class_dev_attrs) {
+- for (i = 0; attr_name(cls->class_dev_attrs[i]); i++)
+- class_device_remove_file(cd, &cls->class_dev_attrs[i]);
+- }
+-}
+-
+-static int class_device_add_groups(struct class_device *cd)
+-{
+- int i;
+- int error = 0;
+-
+- if (cd->groups) {
+- for (i = 0; cd->groups[i]; i++) {
+- error = sysfs_create_group(&cd->kobj, cd->groups[i]);
+- if (error) {
+- while (--i >= 0)
+- sysfs_remove_group(&cd->kobj,
+- cd->groups[i]);
+- goto out;
+- }
+- }
+- }
+-out:
+- return error;
+-}
+-
+-static void class_device_remove_groups(struct class_device *cd)
+-{
+- int i;
+- if (cd->groups)
+- for (i = 0; cd->groups[i]; i++)
+- sysfs_remove_group(&cd->kobj, cd->groups[i]);
+-}
+-
+-static ssize_t show_dev(struct class_device *class_dev, char *buf)
+-{
+- return print_dev_t(buf, class_dev->devt);
+-}
+-
+-static struct class_device_attribute class_devt_attr =
+- __ATTR(dev, S_IRUGO, show_dev, NULL);
+-
+-static ssize_t store_uevent(struct class_device *class_dev,
+- const char *buf, size_t count)
+-{
+- kobject_uevent(&class_dev->kobj, KOBJ_ADD);
+- return count;
+-}
+-
+-static struct class_device_attribute class_uevent_attr =
+- __ATTR(uevent, S_IWUSR, NULL, store_uevent);
+-
+-void class_device_initialize(struct class_device *class_dev)
+-{
+- class_dev->kobj.kset = &class_obj_subsys;
+- kobject_init(&class_dev->kobj, &class_device_ktype);
+- INIT_LIST_HEAD(&class_dev->node);
+-}
+-
+-int class_device_add(struct class_device *class_dev)
+-{
+- struct class *parent_class = NULL;
+- struct class_device *parent_class_dev = NULL;
+- struct class_interface *class_intf;
+- int error = -EINVAL;
+-
+- class_dev = class_device_get(class_dev);
+- if (!class_dev)
+- return -EINVAL;
+-
+- if (!strlen(class_dev->class_id))
+- goto out1;
+-
+- parent_class = class_get(class_dev->class);
+- if (!parent_class)
+- goto out1;
+-
+- parent_class_dev = class_device_get(class_dev->parent);
+-
+- pr_debug("CLASS: registering class device: ID = '%s'\n",
+- class_dev->class_id);
+-
+- /* first, register with generic layer. */
+- if (parent_class_dev)
+- class_dev->kobj.parent = &parent_class_dev->kobj;
+- else
+- class_dev->kobj.parent = &parent_class->subsys.kobj;
+-
+- error = kobject_add(&class_dev->kobj, class_dev->kobj.parent,
+- "%s", class_dev->class_id);
+- if (error)
+- goto out2;
+-
+- /* add the needed attributes to this device */
+- error = sysfs_create_link(&class_dev->kobj,
+- &parent_class->subsys.kobj, "subsystem");
+- if (error)
+- goto out3;
+-
+- error = class_device_create_file(class_dev, &class_uevent_attr);
+- if (error)
+- goto out3;
+-
+- if (MAJOR(class_dev->devt)) {
+- error = class_device_create_file(class_dev, &class_devt_attr);
+- if (error)
+- goto out4;
+- }
+-
+- error = class_device_add_attrs(class_dev);
+- if (error)
+- goto out5;
+-
+- if (class_dev->dev) {
+- error = sysfs_create_link(&class_dev->kobj,
+- &class_dev->dev->kobj, "device");
+- if (error)
+- goto out6;
+- }
+-
+- error = class_device_add_groups(class_dev);
+- if (error)
+- goto out7;
+-
+- error = make_deprecated_class_device_links(class_dev);
+- if (error)
+- goto out8;
+-
+- kobject_uevent(&class_dev->kobj, KOBJ_ADD);
+-
+- /* notify any interfaces this device is now here */
+- down(&parent_class->sem);
+- list_add_tail(&class_dev->node, &parent_class->children);
+- list_for_each_entry(class_intf, &parent_class->interfaces, node) {
+- if (class_intf->add)
+- class_intf->add(class_dev, class_intf);
+- }
+- up(&parent_class->sem);
+-
+- goto out1;
+-
+- out8:
+- class_device_remove_groups(class_dev);
+- out7:
+- if (class_dev->dev)
+- sysfs_remove_link(&class_dev->kobj, "device");
+- out6:
+- class_device_remove_attrs(class_dev);
+- out5:
+- if (MAJOR(class_dev->devt))
+- class_device_remove_file(class_dev, &class_devt_attr);
+- out4:
+- class_device_remove_file(class_dev, &class_uevent_attr);
+- out3:
+- kobject_del(&class_dev->kobj);
+- out2:
+- if (parent_class_dev)
+- class_device_put(parent_class_dev);
+- class_put(parent_class);
+- out1:
+- class_device_put(class_dev);
+- return error;
+-}
+-
+-int class_device_register(struct class_device *class_dev)
+-{
+- class_device_initialize(class_dev);
+- return class_device_add(class_dev);
+-}
+-
+-/**
+- * class_device_create - creates a class device and registers it with sysfs
+- * @cls: pointer to the struct class that this device should be registered to.
+- * @parent: pointer to the parent struct class_device of this new device, if
+- * any.
+- * @devt: the dev_t for the char device to be added.
+- * @device: a pointer to a struct device that is assiociated with this class
+- * device.
+- * @fmt: string for the class device's name
+- *
+- * This function can be used by char device classes. A struct
+- * class_device will be created in sysfs, registered to the specified
+- * class.
+- * A "dev" file will be created, showing the dev_t for the device, if
+- * the dev_t is not 0,0.
+- * If a pointer to a parent struct class_device is passed in, the newly
+- * created struct class_device will be a child of that device in sysfs.
+- * The pointer to the struct class_device will be returned from the
+- * call. Any further sysfs files that might be required can be created
+- * using this pointer.
+- *
+- * Note: the struct class passed to this function must have previously
+- * been created with a call to class_create().
+- */
+-struct class_device *class_device_create(struct class *cls,
+- struct class_device *parent,
+- dev_t devt,
+- struct device *device,
+- const char *fmt, ...)
+-{
+- va_list args;
+- struct class_device *class_dev = NULL;
+- int retval = -ENODEV;
+-
+- if (cls == NULL || IS_ERR(cls))
+- goto error;
+-
+- class_dev = kzalloc(sizeof(*class_dev), GFP_KERNEL);
+- if (!class_dev) {
+- retval = -ENOMEM;
+- goto error;
+- }
+-
+- class_dev->devt = devt;
+- class_dev->dev = device;
+- class_dev->class = cls;
+- class_dev->parent = parent;
+- class_dev->release = class_device_create_release;
+- class_dev->uevent = class_device_create_uevent;
+-
+- va_start(args, fmt);
+- vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
+- va_end(args);
+- retval = class_device_register(class_dev);
+- if (retval)
+- goto error;
+-
+- return class_dev;
+-
+-error:
+- kfree(class_dev);
+- return ERR_PTR(retval);
+-}
+-
+-void class_device_del(struct class_device *class_dev)
+-{
+- struct class *parent_class = class_dev->class;
+- struct class_device *parent_device = class_dev->parent;
+- struct class_interface *class_intf;
+-
+- if (parent_class) {
+- down(&parent_class->sem);
+- list_del_init(&class_dev->node);
+- list_for_each_entry(class_intf, &parent_class->interfaces, node)
+- if (class_intf->remove)
+- class_intf->remove(class_dev, class_intf);
+- up(&parent_class->sem);
+- }
+-
+- if (class_dev->dev) {
+- remove_deprecated_class_device_links(class_dev);
+- sysfs_remove_link(&class_dev->kobj, "device");
+- }
+- sysfs_remove_link(&class_dev->kobj, "subsystem");
+- class_device_remove_file(class_dev, &class_uevent_attr);
+- if (MAJOR(class_dev->devt))
+- class_device_remove_file(class_dev, &class_devt_attr);
+- class_device_remove_attrs(class_dev);
+- class_device_remove_groups(class_dev);
+-
+- kobject_uevent(&class_dev->kobj, KOBJ_REMOVE);
+- kobject_del(&class_dev->kobj);
+-
+- class_device_put(parent_device);
+- class_put(parent_class);
+-}
+-
+-void class_device_unregister(struct class_device *class_dev)
+-{
+- pr_debug("CLASS: Unregistering class device. ID = '%s'\n",
+- class_dev->class_id);
+- class_device_del(class_dev);
+- class_device_put(class_dev);
+-}
+-
+-/**
+- * class_device_destroy - removes a class device that was created with class_device_create()
+- * @cls: the pointer to the struct class that this device was registered * with.
+- * @devt: the dev_t of the device that was previously registered.
+- *
+- * This call unregisters and cleans up a class device that was created with a
+- * call to class_device_create()
+- */
+-void class_device_destroy(struct class *cls, dev_t devt)
+-{
+- struct class_device *class_dev = NULL;
+- struct class_device *class_dev_tmp;
+-
+- down(&cls->sem);
+- list_for_each_entry(class_dev_tmp, &cls->children, node) {
+- if (class_dev_tmp->devt == devt) {
+- class_dev = class_dev_tmp;
+- break;
+- }
+- }
+- up(&cls->sem);
+-
+- if (class_dev)
+- class_device_unregister(class_dev);
+-}
+-
+-struct class_device *class_device_get(struct class_device *class_dev)
+-{
+- if (class_dev)
+- return to_class_dev(kobject_get(&class_dev->kobj));
+- return NULL;
+-}
+-
+-void class_device_put(struct class_device *class_dev)
+-{
+- if (class_dev)
+- kobject_put(&class_dev->kobj);
+-}
+-
+ /**
+ * class_for_each_device - device iterator
+ * @class: the class we're iterating
+@@ -897,56 +338,9 @@ struct device *class_find_device(struct class *class, void *data,
+ }
+ EXPORT_SYMBOL_GPL(class_find_device);
+
+-/**
+- * class_find_child - device iterator for locating a particular class_device
+- * @class: the class we're iterating
+- * @data: data for the match function
+- * @match: function to check class_device
+- *
+- * This function returns a reference to a class_device that is 'found' for
+- * later use, as determined by the @match callback.
+- *
+- * The callback should return 0 if the class_device doesn't match and non-zero
+- * if it does. If the callback returns non-zero, this function will
+- * return to the caller and not iterate over any more class_devices.
+- *
+- * Note, you will need to drop the reference with class_device_put() after use.
+- *
+- * We hold class->sem in this function, so it can not be
+- * re-acquired in @match, otherwise it will self-deadlocking. For
+- * example, calls to add or remove class members would be verboten.
+- */
+-struct class_device *class_find_child(struct class *class, void *data,
+- int (*match)(struct class_device *, void *))
+-{
+- struct class_device *dev;
+- int found = 0;
+-
+- if (!class)
+- return NULL;
+-
+- down(&class->sem);
+- list_for_each_entry(dev, &class->children, node) {
+- dev = class_device_get(dev);
+- if (dev) {
+- if (match(dev, data)) {
+- found = 1;
+- break;
+- } else
+- class_device_put(dev);
+- } else
+- break;
+- }
+- up(&class->sem);
+-
+- return found ? dev : NULL;
+-}
+-EXPORT_SYMBOL_GPL(class_find_child);
+-
+ int class_interface_register(struct class_interface *class_intf)
+ {
+ struct class *parent;
+- struct class_device *class_dev;
+ struct device *dev;
+
+ if (!class_intf || !class_intf->class)
+@@ -958,10 +352,6 @@ int class_interface_register(struct class_interface *class_intf)
+
+ down(&parent->sem);
+ list_add_tail(&class_intf->node, &parent->interfaces);
+- if (class_intf->add) {
+- list_for_each_entry(class_dev, &parent->children, node)
+- class_intf->add(class_dev, class_intf);
+- }
+ if (class_intf->add_dev) {
+ list_for_each_entry(dev, &parent->devices, node)
+ class_intf->add_dev(dev, class_intf);
+@@ -974,7 +364,6 @@ int class_interface_register(struct class_interface *class_intf)
+ void class_interface_unregister(struct class_interface *class_intf)
+ {
+ struct class *parent = class_intf->class;
+- struct class_device *class_dev;
+ struct device *dev;
+
+ if (!parent)
+@@ -982,10 +371,6 @@ void class_interface_unregister(struct class_interface *class_intf)
+
+ down(&parent->sem);
+ list_del_init(&class_intf->node);
+- if (class_intf->remove) {
+- list_for_each_entry(class_dev, &parent->children, node)
+- class_intf->remove(class_dev, class_intf);
+- }
+ if (class_intf->remove_dev) {
+ list_for_each_entry(dev, &parent->devices, node)
+ class_intf->remove_dev(dev, class_intf);
+@@ -1000,13 +385,6 @@ int __init classes_init(void)
+ class_kset = kset_create_and_add("class", NULL, NULL);
+ if (!class_kset)
+ return -ENOMEM;
+-
+- /* ick, this is ugly, the things we go through to keep from showing up
+- * in sysfs... */
+- kset_init(&class_obj_subsys);
+- kobject_set_name(&class_obj_subsys.kobj, "class_obj");
+- if (!class_obj_subsys.kobj.parent)
+- class_obj_subsys.kobj.parent = &class_obj_subsys.kobj;
+ return 0;
+ }
+
+@@ -1017,19 +395,5 @@ EXPORT_SYMBOL_GPL(class_unregister);
+ EXPORT_SYMBOL_GPL(class_create);
+ EXPORT_SYMBOL_GPL(class_destroy);
+
+-EXPORT_SYMBOL_GPL(class_device_register);
+-EXPORT_SYMBOL_GPL(class_device_unregister);
+-EXPORT_SYMBOL_GPL(class_device_initialize);
+-EXPORT_SYMBOL_GPL(class_device_add);
+-EXPORT_SYMBOL_GPL(class_device_del);
+-EXPORT_SYMBOL_GPL(class_device_get);
+-EXPORT_SYMBOL_GPL(class_device_put);
+-EXPORT_SYMBOL_GPL(class_device_create);
+-EXPORT_SYMBOL_GPL(class_device_destroy);
+-EXPORT_SYMBOL_GPL(class_device_create_file);
+-EXPORT_SYMBOL_GPL(class_device_remove_file);
+-EXPORT_SYMBOL_GPL(class_device_create_bin_file);
+-EXPORT_SYMBOL_GPL(class_device_remove_bin_file);
+-
+ EXPORT_SYMBOL_GPL(class_interface_register);
+ EXPORT_SYMBOL_GPL(class_interface_unregister);
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index 24198ad..be288b5 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -20,7 +20,7 @@
+ #include <linux/notifier.h>
+ #include <linux/genhd.h>
+ #include <linux/kallsyms.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+
+ #include "base.h"
+ #include "power/power.h"
+@@ -207,7 +207,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
+ retval = dev->bus->uevent(dev, env);
+ if (retval)
+ pr_debug("device: '%s': %s: bus uevent() returned %d\n",
+- dev->bus_id, __FUNCTION__, retval);
++ dev->bus_id, __func__, retval);
+ }
+
+ /* have the class specific function add its stuff */
+@@ -216,7 +216,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
+ if (retval)
+ pr_debug("device: '%s': %s: class uevent() "
+ "returned %d\n", dev->bus_id,
+- __FUNCTION__, retval);
++ __func__, retval);
+ }
+
+ /* have the device type specific fuction add its stuff */
+@@ -225,7 +225,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
+ if (retval)
+ pr_debug("device: '%s': %s: dev_type uevent() "
+ "returned %d\n", dev->bus_id,
+- __FUNCTION__, retval);
++ __func__, retval);
+ }
+
+ return retval;
+@@ -782,11 +782,15 @@ 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);
+
++ /* use parent numa_node */
++ if (parent)
++ set_dev_node(dev, dev_to_node(parent));
++
+ /* first, register with generic layer. */
+ error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev->bus_id);
+ if (error)
+@@ -817,13 +821,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 +846,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 +984,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 +1079,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 +1167,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 +1184,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 +1223,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 +1299,7 @@ int device_move(struct device *dev, struct device *new_parent)
+ new_parent_kobj = get_device_parent(dev, new_parent);
+
+ pr_debug("device: '%s': %s: moving to '%s'\n", dev->bus_id,
+- __FUNCTION__, new_parent ? new_parent->bus_id : "<NULL>");
++ __func__, new_parent ? new_parent->bus_id : "<NULL>");
+ error = kobject_move(&dev->kobj, new_parent_kobj);
+ if (error) {
+ cleanup_glue_dir(dev, new_parent_kobj);
+@@ -1336,8 +1310,11 @@ int device_move(struct device *dev, struct device *new_parent)
+ dev->parent = new_parent;
+ if (old_parent)
+ klist_remove(&dev->knode_parent);
+- if (new_parent)
++ if (new_parent) {
+ klist_add_tail(&dev->knode_parent, &new_parent->klist_children);
++ set_dev_node(dev, dev_to_node(new_parent));
++ }
++
+ if (!dev->class)
+ goto out_put;
+ error = device_move_class_links(dev, old_parent, new_parent);
+@@ -1347,9 +1324,12 @@ int device_move(struct device *dev, struct device *new_parent)
+ if (!kobject_move(&dev->kobj, &old_parent->kobj)) {
+ if (new_parent)
+ klist_remove(&dev->knode_parent);
+- if (old_parent)
++ dev->parent = old_parent;
++ if (old_parent) {
+ klist_add_tail(&dev->knode_parent,
+ &old_parent->klist_children);
++ set_dev_node(dev, dev_to_node(old_parent));
++ }
+ }
+ cleanup_glue_dir(dev, new_parent_kobj);
+ put_device(new_parent);
+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/driver.c b/drivers/base/driver.c
+index 9a6537f..2ef5acf 100644
+--- a/drivers/base/driver.c
++++ b/drivers/base/driver.c
+@@ -217,12 +217,22 @@ static void driver_remove_groups(struct device_driver *drv,
+ int driver_register(struct device_driver *drv)
+ {
+ int ret;
++ struct device_driver *other;
+
+ if ((drv->bus->probe && drv->probe) ||
+ (drv->bus->remove && drv->remove) ||
+ (drv->bus->shutdown && drv->shutdown))
+ printk(KERN_WARNING "Driver '%s' needs updating - please use "
+ "bus_type methods\n", drv->name);
++
++ other = driver_find(drv->name, drv->bus);
++ if (other) {
++ put_driver(other);
++ printk(KERN_ERR "Error: Driver '%s' is already registered, "
++ "aborting...\n", drv->name);
++ return -EEXIST;
++ }
++
+ ret = bus_add_driver(drv);
+ if (ret)
+ return ret;
+diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
+index 4a1b9bf..9fd4a85 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;
+ }
+
+@@ -396,10 +396,12 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
+ if (!firmware_p)
+ return -EINVAL;
+
++ printk(KERN_INFO "firmware: requesting %s\n", 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 +572,13 @@ firmware_class_init(void)
+ int error;
+ error = class_register(&firmware_class);
+ if (error) {
+- printk(KERN_ERR "%s: class_register failed\n", __FUNCTION__);
++ printk(KERN_ERR "%s: class_register failed\n", __func__);
+ return error;
+ }
+ error = class_create_file(&firmware_class, &class_attr_timeout);
+ if (error) {
+ printk(KERN_ERR "%s: class_create_file failed\n",
+- __FUNCTION__);
++ __func__);
+ class_unregister(&firmware_class);
+ }
+ return error;
+diff --git a/drivers/base/memory.c b/drivers/base/memory.c
+index 7ae413f..8ce6de5 100644
+--- a/drivers/base/memory.c
++++ b/drivers/base/memory.c
+@@ -20,6 +20,7 @@
+ #include <linux/kobject.h>
+ #include <linux/memory_hotplug.h>
+ #include <linux/mm.h>
++#include <linux/mutex.h>
+ #include <asm/atomic.h>
+ #include <asm/uaccess.h>
+
+@@ -61,8 +62,8 @@ void unregister_memory_notifier(struct notifier_block *nb)
+ /*
+ * register_memory - Setup a sysfs device for a memory block
+ */
+-int register_memory(struct memory_block *memory, struct mem_section *section,
+- struct node *root)
++static
++int register_memory(struct memory_block *memory, struct mem_section *section)
+ {
+ int error;
+
+@@ -70,26 +71,18 @@ int register_memory(struct memory_block *memory, struct mem_section *section,
+ memory->sysdev.id = __section_nr(section);
+
+ error = sysdev_register(&memory->sysdev);
+-
+- if (root && !error)
+- error = sysfs_create_link(&root->sysdev.kobj,
+- &memory->sysdev.kobj,
+- kobject_name(&memory->sysdev.kobj));
+-
+ return error;
+ }
+
+ static void
+-unregister_memory(struct memory_block *memory, struct mem_section *section,
+- struct node *root)
++unregister_memory(struct memory_block *memory, struct mem_section *section)
+ {
+ BUG_ON(memory->sysdev.cls != &memory_sysdev_class);
+ BUG_ON(memory->sysdev.id != __section_nr(section));
+
++ /* drop the ref. we got in remove_memory_block() */
++ kobject_put(&memory->sysdev.kobj);
+ sysdev_unregister(&memory->sysdev);
+- if (root)
+- sysfs_remove_link(&root->sysdev.kobj,
+- kobject_name(&memory->sysdev.kobj));
+ }
+
+ /*
+@@ -193,7 +186,7 @@ memory_block_action(struct memory_block *mem, unsigned long action)
+ break;
+ default:
+ printk(KERN_WARNING "%s(%p, %ld) unknown action: %ld\n",
+- __FUNCTION__, mem, action, action);
++ __func__, mem, action, action);
+ WARN_ON(1);
+ ret = -EINVAL;
+ }
+@@ -205,7 +198,7 @@ static int memory_block_change_state(struct memory_block *mem,
+ unsigned long to_state, unsigned long from_state_req)
+ {
+ int ret = 0;
+- down(&mem->state_sem);
++ mutex_lock(&mem->state_mutex);
+
+ if (mem->state != from_state_req) {
+ ret = -EINVAL;
+@@ -217,7 +210,7 @@ static int memory_block_change_state(struct memory_block *mem,
+ mem->state = to_state;
+
+ out:
+- up(&mem->state_sem);
++ mutex_unlock(&mem->state_mutex);
+ return ret;
+ }
+
+@@ -341,10 +334,10 @@ static int add_memory_block(unsigned long node_id, struct mem_section *section,
+
+ mem->phys_index = __section_nr(section);
+ mem->state = state;
+- init_MUTEX(&mem->state_sem);
++ mutex_init(&mem->state_mutex);
+ mem->phys_device = phys_device;
+
+- ret = register_memory(mem, section, NULL);
++ ret = register_memory(mem, section);
+ if (!ret)
+ ret = mem_create_simple_file(mem, phys_index);
+ if (!ret)
+@@ -395,7 +388,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
+ mem_remove_simple_file(mem, phys_index);
+ mem_remove_simple_file(mem, state);
+ mem_remove_simple_file(mem, phys_device);
+- unregister_memory(mem, section, NULL);
++ unregister_memory(mem, section);
+
+ return 0;
+ }
+@@ -451,6 +444,6 @@ int __init memory_dev_init(void)
+ ret = err;
+ out:
+ if (ret)
+- printk(KERN_ERR "%s() failed: %d\n", __FUNCTION__, ret);
++ printk(KERN_ERR "%s() failed: %d\n", __func__, ret);
+ return ret;
+ }
+diff --git a/drivers/base/node.c b/drivers/base/node.c
+index e59861f..39f3d1b 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)
+@@ -64,6 +77,7 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
+ "Node %d PageTables: %8lu kB\n"
+ "Node %d NFS_Unstable: %8lu kB\n"
+ "Node %d Bounce: %8lu kB\n"
++ "Node %d WritebackTmp: %8lu kB\n"
+ "Node %d Slab: %8lu kB\n"
+ "Node %d SReclaimable: %8lu kB\n"
+ "Node %d SUnreclaim: %8lu kB\n",
+@@ -86,6 +100,7 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
+ nid, K(node_page_state(nid, NR_PAGETABLE)),
+ nid, K(node_page_state(nid, NR_UNSTABLE_NFS)),
+ nid, K(node_page_state(nid, NR_BOUNCE)),
++ nid, K(node_page_state(nid, NR_WRITEBACK_TEMP)),
+ nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE) +
+ node_page_state(nid, NR_SLAB_UNRECLAIMABLE)),
+ nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE)),
+@@ -149,6 +164,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 +182,7 @@ int register_node(struct node *node, int num, struct node *parent)
+ void unregister_node(struct node *node)
+ {
+ sysdev_remove_file(&node->sysdev, &attr_cpumap);
++ sysdev_remove_file(&node->sysdev, &attr_cpulist);
+ sysdev_remove_file(&node->sysdev, &attr_meminfo);
+ sysdev_remove_file(&node->sysdev, &attr_numastat);
+ sysdev_remove_file(&node->sysdev, &attr_distance);
+diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
+index d887d5c..7b76fd3 100644
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -50,26 +50,37 @@
+ LIST_HEAD(dpm_active);
+ static LIST_HEAD(dpm_off);
+ static LIST_HEAD(dpm_off_irq);
+-static LIST_HEAD(dpm_destroy);
+
+ static DEFINE_MUTEX(dpm_list_mtx);
+
+-static DECLARE_RWSEM(pm_sleep_rwsem);
+-
+-int (*platform_enable_wakeup)(struct device *dev, int is_on);
++/* 'true' if all devices have been suspended, protected by dpm_list_mtx */
++static bool all_sleeping;
+
+ /**
+ * device_pm_add - add a device to the list of active devices
+ * @dev: Device to be added to the list
+ */
+-void device_pm_add(struct device *dev)
++int device_pm_add(struct device *dev)
+ {
++ int error;
++
+ pr_debug("PM: Adding info for %s:%s\n",
+ dev->bus ? dev->bus->name : "No Bus",
+ kobject_name(&dev->kobj));
+ mutex_lock(&dpm_list_mtx);
+- list_add_tail(&dev->power.entry, &dpm_active);
++ if ((dev->parent && dev->parent->power.sleeping) || all_sleeping) {
++ if (dev->parent->power.sleeping)
++ dev_warn(dev, "parent %s is sleeping\n",
++ dev->parent->bus_id);
++ else
++ dev_warn(dev, "all devices are sleeping\n");
++ WARN_ON(true);
++ }
++ error = dpm_sysfs_add(dev);
++ if (!error)
++ list_add_tail(&dev->power.entry, &dpm_active);
+ mutex_unlock(&dpm_list_mtx);
++ return error;
+ }
+
+ /**
+@@ -89,50 +100,6 @@ void device_pm_remove(struct device *dev)
+ mutex_unlock(&dpm_list_mtx);
+ }
+
+-/**
+- * device_pm_schedule_removal - schedule the removal of a suspended device
+- * @dev: Device to destroy
+- *
+- * Moves the device to the dpm_destroy list for further processing by
+- * unregister_dropped_devices().
+- */
+-void device_pm_schedule_removal(struct device *dev)
+-{
+- pr_debug("PM: Preparing for removal: %s:%s\n",
+- dev->bus ? dev->bus->name : "No Bus",
+- kobject_name(&dev->kobj));
+- mutex_lock(&dpm_list_mtx);
+- list_move_tail(&dev->power.entry, &dpm_destroy);
+- mutex_unlock(&dpm_list_mtx);
+-}
+-EXPORT_SYMBOL_GPL(device_pm_schedule_removal);
+-
+-/**
+- * pm_sleep_lock - mutual exclusion for registration and suspend
+- *
+- * Returns 0 if no suspend is underway and device registration
+- * may proceed, otherwise -EBUSY.
+- */
+-int pm_sleep_lock(void)
+-{
+- if (down_read_trylock(&pm_sleep_rwsem))
+- return 0;
+-
+- return -EBUSY;
+-}
+-
+-/**
+- * pm_sleep_unlock - mutual exclusion for registration and suspend
+- *
+- * This routine undoes the effect of device_pm_add_lock
+- * when a device's registration is complete.
+- */
+-void pm_sleep_unlock(void)
+-{
+- up_read(&pm_sleep_rwsem);
+-}
+-
+-
+ /*------------------------- Resume routines -------------------------*/
+
+ /**
+@@ -242,11 +209,13 @@ static int resume_device(struct device *dev)
+ static void dpm_resume(void)
+ {
+ mutex_lock(&dpm_list_mtx);
++ all_sleeping = false;
+ while(!list_empty(&dpm_off)) {
+ struct list_head *entry = dpm_off.next;
+ struct device *dev = to_device(entry);
+
+ list_move_tail(entry, &dpm_active);
++ dev->power.sleeping = false;
+ mutex_unlock(&dpm_list_mtx);
+ resume_device(dev);
+ mutex_lock(&dpm_list_mtx);
+@@ -255,26 +224,6 @@ static void dpm_resume(void)
+ }
+
+ /**
+- * unregister_dropped_devices - Unregister devices scheduled for removal
+- *
+- * Unregister all devices on the dpm_destroy list.
+- */
+-static void unregister_dropped_devices(void)
+-{
+- mutex_lock(&dpm_list_mtx);
+- while (!list_empty(&dpm_destroy)) {
+- struct list_head *entry = dpm_destroy.next;
+- struct device *dev = to_device(entry);
+-
+- mutex_unlock(&dpm_list_mtx);
+- /* This also removes the device from the list */
+- device_unregister(dev);
+- mutex_lock(&dpm_list_mtx);
+- }
+- mutex_unlock(&dpm_list_mtx);
+-}
+-
+-/**
+ * device_resume - Restore state of each device in system.
+ *
+ * Resume all the devices, unlock them all, and allow new
+@@ -284,8 +233,6 @@ void device_resume(void)
+ {
+ might_sleep();
+ dpm_resume();
+- unregister_dropped_devices();
+- up_write(&pm_sleep_rwsem);
+ }
+ EXPORT_SYMBOL_GPL(device_resume);
+
+@@ -377,11 +324,6 @@ static int suspend_device(struct device *dev, pm_message_t state)
+
+ down(&dev->sem);
+
+- if (dev->power.power_state.event) {
+- dev_dbg(dev, "PM: suspend %d-->%d\n",
+- dev->power.power_state.event, state.event);
+- }
+-
+ if (dev->class && dev->class->suspend) {
+ suspend_device_dbg(dev, state, "class ");
+ error = dev->class->suspend(dev, state);
+@@ -426,6 +368,9 @@ static int dpm_suspend(pm_message_t state)
+ struct list_head *entry = dpm_active.prev;
+ struct device *dev = to_device(entry);
+
++ WARN_ON(dev->parent && dev->parent->power.sleeping);
++
++ dev->power.sleeping = true;
+ mutex_unlock(&dpm_list_mtx);
+ error = suspend_device(dev, state);
+ mutex_lock(&dpm_list_mtx);
+@@ -437,11 +382,14 @@ static int dpm_suspend(pm_message_t state)
+ (error == -EAGAIN ?
+ " (please convert to suspend_late)" :
+ ""));
++ dev->power.sleeping = false;
+ break;
+ }
+ if (!list_empty(&dev->power.entry))
+ list_move(&dev->power.entry, &dpm_off);
+ }
++ if (!error)
++ all_sleeping = true;
+ mutex_unlock(&dpm_list_mtx);
+
+ return error;
+@@ -459,7 +407,6 @@ int device_suspend(pm_message_t state)
+ int error;
+
+ might_sleep();
+- down_write(&pm_sleep_rwsem);
+ error = dpm_suspend(state);
+ if (error)
+ device_resume();
+diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
+index e32d3bd..a6894f2 100644
+--- a/drivers/base/power/power.h
++++ b/drivers/base/power/power.h
+@@ -11,30 +11,13 @@ static inline struct device *to_device(struct list_head *entry)
+ return container_of(entry, struct device, power.entry);
+ }
+
+-extern void device_pm_add(struct device *);
++extern int device_pm_add(struct device *);
+ extern void device_pm_remove(struct device *);
+-extern int pm_sleep_lock(void);
+-extern void pm_sleep_unlock(void);
+
+ #else /* CONFIG_PM_SLEEP */
+
+-
+-static inline void device_pm_add(struct device *dev)
+-{
+-}
+-
+-static inline void device_pm_remove(struct device *dev)
+-{
+-}
+-
+-static inline int pm_sleep_lock(void)
+-{
+- return 0;
+-}
+-
+-static inline void pm_sleep_unlock(void)
+-{
+-}
++static inline int device_pm_add(struct device *dev) { return 0; }
++static inline void device_pm_remove(struct device *dev) {}
+
+ #endif
+
+diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
+index f2ed179..d11f74b 100644
+--- a/drivers/base/power/sysfs.c
++++ b/drivers/base/power/sysfs.c
+@@ -6,6 +6,8 @@
+ #include <linux/string.h>
+ #include "power.h"
+
++int (*platform_enable_wakeup)(struct device *dev, int is_on);
++
+
+ /*
+ * wakeup - Report/change current wakeup option for device
+diff --git a/drivers/base/sys.c b/drivers/base/sys.c
+index 8e13fd9..4fbb56b 100644
+--- a/drivers/base/sys.c
++++ b/drivers/base/sys.c
+@@ -167,6 +167,22 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
+ {
+ int err = 0;
+
++ if (!cls) {
++ printk(KERN_WARNING "sysdev: invalid class passed to "
++ "sysdev_driver_register!\n");
++ WARN_ON(1);
++ return -EINVAL;
++ }
++
++ /* Check whether this driver has already been added to a class. */
++ if ((drv->entry.next != drv->entry.prev) ||
++ (drv->entry.next != NULL)) {
++ printk(KERN_WARNING "sysdev: class %s: driver (%p) has already"
++ " been registered to a class, something is wrong, but "
++ "will forge on!\n", cls->name, drv);
++ WARN_ON(1);
++ }
++
+ mutex_lock(&sysdev_drivers_lock);
+ if (cls && kset_get(&cls->kset)) {
+ list_add_tail(&drv->entry, &cls->drivers);
+@@ -179,7 +195,7 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
+ }
+ } else {
+ err = -EINVAL;
+- printk(KERN_ERR "%s: invalid device class\n", __FUNCTION__);
++ printk(KERN_ERR "%s: invalid device class\n", __func__);
+ WARN_ON(1);
+ }
+ mutex_unlock(&sysdev_drivers_lock);
+diff --git a/drivers/base/topology.c b/drivers/base/topology.c
+index e1d3ad4..fdf4044 100644
+--- a/drivers/base/topology.c
++++ b/drivers/base/topology.c
+@@ -40,15 +40,38 @@ static ssize_t show_##name(struct sys_device *dev, char *buf) \
+ return sprintf(buf, "%d\n", topology_##name(cpu)); \
+ }
+
+-#define define_siblings_show_func(name) \
+-static ssize_t show_##name(struct sys_device *dev, char *buf) \
++static ssize_t show_cpumap(int type, cpumask_t *mask, char *buf)
++{
++ ptrdiff_t len = PTR_ALIGN(buf + PAGE_SIZE - 1, PAGE_SIZE) - buf;
++ int n = 0;
++
++ if (len > 1) {
++ n = type?
++ cpulist_scnprintf(buf, len-2, *mask):
++ cpumask_scnprintf(buf, len-2, *mask);
++ buf[n++] = '\n';
++ buf[n] = '\0';
++ }
++ return n;
++}
++
++#define define_siblings_show_map(name) \
++static inline ssize_t show_##name(struct sys_device *dev, char *buf) \
+ { \
+- ssize_t len = -1; \
+ unsigned int cpu = dev->id; \
+- len = cpumask_scnprintf(buf, NR_CPUS+1, topology_##name(cpu)); \
+- return (len + sprintf(buf + len, "\n")); \
++ return show_cpumap(0, &(topology_##name(cpu)), buf); \
+ }
+
++#define define_siblings_show_list(name) \
++static inline ssize_t show_##name##_list(struct sys_device *dev, char *buf) \
++{ \
++ unsigned int cpu = dev->id; \
++ return show_cpumap(1, &(topology_##name(cpu)), buf); \
++}
++
++#define define_siblings_show_func(name) \
++ define_siblings_show_map(name); define_siblings_show_list(name)
++
+ #ifdef topology_physical_package_id
+ define_id_show_func(physical_package_id);
+ define_one_ro(physical_package_id);
+@@ -68,7 +91,9 @@ define_one_ro(core_id);
+ #ifdef topology_thread_siblings
+ define_siblings_show_func(thread_siblings);
+ define_one_ro(thread_siblings);
+-#define ref_thread_siblings_attr &attr_thread_siblings.attr,
++define_one_ro(thread_siblings_list);
++#define ref_thread_siblings_attr \
++ &attr_thread_siblings.attr, &attr_thread_siblings_list.attr,
+ #else
+ #define ref_thread_siblings_attr
+ #endif
+@@ -76,7 +101,9 @@ define_one_ro(thread_siblings);
+ #ifdef topology_core_siblings
+ define_siblings_show_func(core_siblings);
+ define_one_ro(core_siblings);
+-#define ref_core_siblings_attr &attr_core_siblings.attr,
++define_one_ro(core_siblings_list);
++#define ref_core_siblings_attr \
++ &attr_core_siblings.attr, &attr_core_siblings_list.attr,
+ #else
+ #define ref_core_siblings_attr
+ #endif
+diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c
+index 40bca48..84997ef 100644
+--- a/drivers/base/transport_class.c
++++ b/drivers/base/transport_class.c
+@@ -66,7 +66,7 @@ EXPORT_SYMBOL_GPL(transport_class_unregister);
+
+ static int anon_transport_dummy_function(struct transport_container *tc,
+ struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+ /* do nothing */
+ return 0;
+@@ -108,13 +108,14 @@ EXPORT_SYMBOL_GPL(anon_transport_class_register);
+ */
+ void anon_transport_class_unregister(struct anon_transport_class *atc)
+ {
+- attribute_container_unregister(&atc->container);
++ if (unlikely(attribute_container_unregister(&atc->container)))
++ BUG();
+ }
+ EXPORT_SYMBOL_GPL(anon_transport_class_unregister);
+
+ static int transport_setup_classdev(struct attribute_container *cont,
+ struct device *dev,
+- struct class_device *classdev)
++ struct device *classdev)
+ {
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+ struct transport_container *tcont = attribute_container_to_transport_container(cont);
+@@ -148,7 +149,7 @@ EXPORT_SYMBOL_GPL(transport_setup_device);
+
+ static int transport_add_class_device(struct attribute_container *cont,
+ struct device *dev,
+- struct class_device *classdev)
++ struct device *classdev)
+ {
+ int error = attribute_container_add_class_device(classdev);
+ struct transport_container *tcont =
+@@ -180,7 +181,7 @@ EXPORT_SYMBOL_GPL(transport_add_device);
+
+ static int transport_configure(struct attribute_container *cont,
+ struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+ struct transport_container *tcont = attribute_container_to_transport_container(cont);
+@@ -211,7 +212,7 @@ EXPORT_SYMBOL_GPL(transport_configure_device);
+
+ static int transport_remove_classdev(struct attribute_container *cont,
+ struct device *dev,
+- struct class_device *classdev)
++ struct device *classdev)
+ {
+ struct transport_container *tcont =
+ attribute_container_to_transport_container(cont);
+@@ -250,12 +251,12 @@ EXPORT_SYMBOL_GPL(transport_remove_device);
+
+ static void transport_destroy_classdev(struct attribute_container *cont,
+ struct device *dev,
+- struct class_device *classdev)
++ struct device *classdev)
+ {
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+
+ if (tclass->remove != anon_transport_dummy_function)
+- class_device_put(classdev);
++ put_device(classdev);
+ }
+
+
+diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
+index 280e71e..5b4c6e6 100644
+--- a/drivers/block/aoe/aoe.h
++++ b/drivers/block/aoe/aoe.h
+@@ -195,7 +195,6 @@ void aoedev_exit(void);
+ struct aoedev *aoedev_by_aoeaddr(int maj, int min);
+ struct aoedev *aoedev_by_sysminor_m(ulong sysminor);
+ void aoedev_downdev(struct aoedev *d);
+-int aoedev_isbusy(struct aoedev *d);
+ int aoedev_flush(const char __user *str, size_t size);
+
+ int aoenet_init(void);
+diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
+index d00293b..8fc429c 100644
+--- a/drivers/block/aoe/aoecmd.c
++++ b/drivers/block/aoe/aoecmd.c
+@@ -668,16 +668,16 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id)
+ u16 n;
+
+ /* word 83: command set supported */
+- n = le16_to_cpu(get_unaligned((__le16 *) &id[83<<1]));
++ n = get_unaligned_le16(&id[83 << 1]);
+
+ /* word 86: command set/feature enabled */
+- n |= le16_to_cpu(get_unaligned((__le16 *) &id[86<<1]));
++ n |= get_unaligned_le16(&id[86 << 1]);
+
+ if (n & (1<<10)) { /* bit 10: LBA 48 */
+ d->flags |= DEVFL_EXT;
+
+ /* word 100: number lba48 sectors */
+- ssize = le64_to_cpu(get_unaligned((__le64 *) &id[100<<1]));
++ ssize = get_unaligned_le64(&id[100 << 1]);
+
+ /* set as in ide-disk.c:init_idedisk_capacity */
+ d->geo.cylinders = ssize;
+@@ -688,12 +688,12 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id)
+ d->flags &= ~DEVFL_EXT;
+
+ /* number lba28 sectors */
+- ssize = le32_to_cpu(get_unaligned((__le32 *) &id[60<<1]));
++ ssize = get_unaligned_le32(&id[60 << 1]);
+
+ /* NOTE: obsolete in ATA 6 */
+- d->geo.cylinders = le16_to_cpu(get_unaligned((__le16 *) &id[54<<1]));
+- d->geo.heads = le16_to_cpu(get_unaligned((__le16 *) &id[55<<1]));
+- d->geo.sectors = le16_to_cpu(get_unaligned((__le16 *) &id[56<<1]));
++ d->geo.cylinders = get_unaligned_le16(&id[54 << 1]);
++ d->geo.heads = get_unaligned_le16(&id[55 << 1]);
++ d->geo.sectors = get_unaligned_le16(&id[56 << 1]);
+ }
+
+ if (d->ssize != ssize)
+@@ -779,7 +779,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)
+ u16 aoemajor;
+
+ hin = (struct aoe_hdr *) skb_mac_header(skb);
+- aoemajor = be16_to_cpu(get_unaligned(&hin->major));
++ aoemajor = get_unaligned_be16(&hin->major);
+ d = aoedev_by_aoeaddr(aoemajor, hin->minor);
+ if (d == NULL) {
+ snprintf(ebuf, sizeof ebuf, "aoecmd_ata_rsp: ata response "
+@@ -791,7 +791,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)
+
+ spin_lock_irqsave(&d->lock, flags);
+
+- n = be32_to_cpu(get_unaligned(&hin->tag));
++ n = get_unaligned_be32(&hin->tag);
+ t = gettgt(d, hin->src);
+ if (t == NULL) {
+ printk(KERN_INFO "aoe: can't find target e%ld.%d:%012llx\n",
+@@ -806,9 +806,9 @@ aoecmd_ata_rsp(struct sk_buff *skb)
+ snprintf(ebuf, sizeof ebuf,
+ "%15s e%d.%d tag=%08x@%08lx\n",
+ "unexpected rsp",
+- be16_to_cpu(get_unaligned(&hin->major)),
++ get_unaligned_be16(&hin->major),
+ hin->minor,
+- be32_to_cpu(get_unaligned(&hin->tag)),
++ get_unaligned_be32(&hin->tag),
+ jiffies);
+ aoechr_error(ebuf);
+ return;
+@@ -873,7 +873,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)
+ printk(KERN_INFO
+ "aoe: unrecognized ata command %2.2Xh for %d.%d\n",
+ ahout->cmdstat,
+- be16_to_cpu(get_unaligned(&hin->major)),
++ get_unaligned_be16(&hin->major),
+ hin->minor);
+ }
+ }
+diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
+index f9a1cd9..a1d813a 100644
+--- a/drivers/block/aoe/aoedev.c
++++ b/drivers/block/aoe/aoedev.c
+@@ -18,24 +18,6 @@ static void skbpoolfree(struct aoedev *d);
+ static struct aoedev *devlist;
+ static DEFINE_SPINLOCK(devlist_lock);
+
+-int
+-aoedev_isbusy(struct aoedev *d)
+-{
+- struct aoetgt **t, **te;
+- struct frame *f, *e;
+-
+- t = d->targets;
+- te = t + NTARGETS;
+- for (; t < te && *t; t++) {
+- f = (*t)->frames;
+- e = f + (*t)->nframes;
+- for (; f < e; f++)
+- if (f->tag != FREETAG)
+- return 1;
+- }
+- return 0;
+-}
+-
+ struct aoedev *
+ aoedev_by_aoeaddr(int maj, int min)
+ {
+diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
+index 8460ef7..d625169 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);
+@@ -128,7 +128,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
+ skb_push(skb, ETH_HLEN); /* (1) */
+
+ h = (struct aoe_hdr *) skb_mac_header(skb);
+- n = be32_to_cpu(get_unaligned(&h->tag));
++ n = get_unaligned_be32(&h->tag);
+ if ((h->verfl & AOEFL_RSP) == 0 || (n & 1<<31))
+ goto exit;
+
+@@ -140,7 +140,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
+ printk(KERN_ERR
+ "%s%d.%d@%s; ecode=%d '%s'\n",
+ "aoe: error packet from ",
+- be16_to_cpu(get_unaligned(&h->major)),
++ get_unaligned_be16(&h->major),
+ h->minor, skb->dev->name,
+ h->err, aoe_errlist[n]);
+ goto exit;
+diff --git a/drivers/block/brd.c b/drivers/block/brd.c
+index 8536480..a196ef7 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;
+
+@@ -319,7 +319,7 @@ out:
+
+ #ifdef CONFIG_BLK_DEV_XIP
+ static int brd_direct_access (struct block_device *bdev, sector_t sector,
+- unsigned long *data)
++ void **kaddr, unsigned long *pfn)
+ {
+ struct brd_device *brd = bdev->bd_disk->private_data;
+ struct page *page;
+@@ -333,7 +333,8 @@ static int brd_direct_access (struct block_device *bdev, sector_t sector,
+ page = brd_insert_page(brd, sector);
+ if (!page)
+ return -ENOMEM;
+- *data = (unsigned long)page_address(page);
++ *kaddr = page_address(page);
++ *pfn = page_to_pfn(page);
+
+ return 0;
+ }
+@@ -386,10 +387,14 @@ static struct block_device_operations brd_fops = {
+ */
+ static int rd_nr;
+ int rd_size = CONFIG_BLK_DEV_RAM_SIZE;
++static int max_part;
++static int part_shift;
+ module_param(rd_nr, int, 0);
+ MODULE_PARM_DESC(rd_nr, "Maximum number of brd devices");
+ module_param(rd_size, int, 0);
+ MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes.");
++module_param(max_part, int, 0);
++MODULE_PARM_DESC(max_part, "Maximum number of partitions per RAM disk");
+ MODULE_LICENSE("GPL");
+ MODULE_ALIAS_BLOCKDEV_MAJOR(RAMDISK_MAJOR);
+
+@@ -434,11 +439,11 @@ static struct brd_device *brd_alloc(int i)
+ blk_queue_max_sectors(brd->brd_queue, 1024);
+ blk_queue_bounce_limit(brd->brd_queue, BLK_BOUNCE_ANY);
+
+- disk = brd->brd_disk = alloc_disk(1);
++ disk = brd->brd_disk = alloc_disk(1 << part_shift);
+ if (!disk)
+ goto out_free_queue;
+ disk->major = RAMDISK_MAJOR;
+- disk->first_minor = i;
++ disk->first_minor = i << part_shift;
+ disk->fops = &brd_fops;
+ disk->private_data = brd;
+ disk->queue = brd->brd_queue;
+@@ -522,7 +527,12 @@ static int __init brd_init(void)
+ * themselves and have kernel automatically instantiate actual
+ * device on-demand.
+ */
+- if (rd_nr > 1UL << MINORBITS)
++
++ part_shift = 0;
++ if (max_part > 0)
++ part_shift = fls(max_part);
++
++ if (rd_nr > 1UL << (MINORBITS - part_shift))
+ return -EINVAL;
+
+ if (rd_nr) {
+@@ -530,7 +540,7 @@ static int __init brd_init(void)
+ range = rd_nr;
+ } else {
+ nr = CONFIG_BLK_DEV_RAM_COUNT;
+- range = 1UL << MINORBITS;
++ range = 1UL << (MINORBITS - part_shift);
+ }
+
+ if (register_blkdev(RAMDISK_MAJOR, "ramdisk"))
+@@ -569,7 +579,7 @@ static void __exit brd_exit(void)
+ unsigned long range;
+ struct brd_device *brd, *next;
+
+- range = rd_nr ? rd_nr : 1UL << MINORBITS;
++ range = rd_nr ? rd_nr : 1UL << (MINORBITS - part_shift);
+
+ list_for_each_entry_safe(brd, next, &brd_devices, brd_list)
+ brd_del_one(brd);
+diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
+index 9c9627e..e539be5 100644
+--- a/drivers/block/cciss.c
++++ b/drivers/block/cciss.c
+@@ -425,7 +425,7 @@ static void __devinit cciss_procinit(int i)
+ struct proc_dir_entry *pde;
+
+ if (proc_cciss == NULL)
+- proc_cciss = proc_mkdir("cciss", proc_root_driver);
++ proc_cciss = proc_mkdir("driver/cciss", NULL);
+ if (!proc_cciss)
+ return;
+ pde = proc_create(hba[i]->devname, S_IWUSR | S_IRUSR | S_IRGRP |
+@@ -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:
+@@ -3685,7 +3700,7 @@ static void __exit cciss_cleanup(void)
+ cciss_remove_one(hba[i]->pdev);
+ }
+ }
+- remove_proc_entry("cciss", proc_root_driver);
++ remove_proc_entry("driver/cciss", NULL);
+ }
+
+ static void fail_all_cmds(unsigned long ctlr)
+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/cpqarray.c b/drivers/block/cpqarray.c
+index 6919918..09c1434 100644
+--- a/drivers/block/cpqarray.c
++++ b/drivers/block/cpqarray.c
+@@ -214,7 +214,7 @@ static struct proc_dir_entry *proc_array;
+ static void __init ida_procinit(int i)
+ {
+ if (proc_array == NULL) {
+- proc_array = proc_mkdir("cpqarray", proc_root_driver);
++ proc_array = proc_mkdir("driver/cpqarray", NULL);
+ if (!proc_array) return;
+ }
+
+@@ -1796,7 +1796,7 @@ static void __exit cpqarray_exit(void)
+ }
+ }
+
+- remove_proc_entry("cpqarray", proc_root_driver);
++ remove_proc_entry("driver/cpqarray", NULL);
+ }
+
+ module_init(cpqarray_init)
+diff --git a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c
+index 2411678..8b6bb76 100644
+--- a/drivers/block/cryptoloop.c
++++ b/drivers/block/cryptoloop.c
+@@ -27,7 +27,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/loop.h>
+ #include <linux/scatterlist.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
+index 7652e87..395f8ea 100644
+--- a/drivers/block/floppy.c
++++ b/drivers/block/floppy.c
+@@ -4526,14 +4526,15 @@ static void __init parse_floppy_cfg_string(char *cfg)
+ }
+ }
+
+-int __init init_module(void)
++static int __init floppy_module_init(void)
+ {
+ if (floppy)
+ parse_floppy_cfg_string(floppy);
+ return floppy_init();
+ }
++module_init(floppy_module_init);
+
+-void cleanup_module(void)
++static void __exit floppy_module_exit(void)
+ {
+ int drive;
+
+@@ -4562,6 +4563,7 @@ void cleanup_module(void)
+ /* eject disk, if any */
+ fd_eject(0);
+ }
++module_exit(floppy_module_exit);
+
+ module_param(floppy, charp, 0);
+ module_param(FLOPPY_IRQ, int, 0);
+diff --git a/drivers/block/loop.c b/drivers/block/loop.c
+index 91ebb00..d3a25b0 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
+ */
+@@ -543,7 +546,7 @@ static void loop_unplug(struct request_queue *q)
+ {
+ struct loop_device *lo = q->queuedata;
+
+- clear_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags);
++ queue_flag_clear_unlocked(QUEUE_FLAG_PLUGGED, q);
+ blk_run_address_space(lo->lo_backing_file->f_mapping);
+ }
+
+@@ -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/nbd.c b/drivers/block/nbd.c
+index 60cc543..ad98dda 100644
+--- a/drivers/block/nbd.c
++++ b/drivers/block/nbd.c
+@@ -29,6 +29,7 @@
+ #include <linux/kernel.h>
+ #include <net/sock.h>
+ #include <linux/net.h>
++#include <linux/kthread.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+@@ -55,6 +56,7 @@ static unsigned int debugflags;
+
+ static unsigned int nbds_max = 16;
+ static struct nbd_device *nbd_dev;
++static int max_part;
+
+ /*
+ * Use just one lock (or at most 1 per NIC). Two arguments for this:
+@@ -337,7 +339,7 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
+ }
+
+ req = nbd_find_request(lo, *(struct request **)reply.handle);
+- if (unlikely(IS_ERR(req))) {
++ if (IS_ERR(req)) {
+ result = PTR_ERR(req);
+ if (result != -ENOENT)
+ goto harderror;
+@@ -441,6 +443,85 @@ static void nbd_clear_que(struct nbd_device *lo)
+ }
+
+
++static void nbd_handle_req(struct nbd_device *lo, struct request *req)
++{
++ if (!blk_fs_request(req))
++ goto error_out;
++
++ nbd_cmd(req) = NBD_CMD_READ;
++ if (rq_data_dir(req) == WRITE) {
++ nbd_cmd(req) = NBD_CMD_WRITE;
++ if (lo->flags & NBD_READ_ONLY) {
++ printk(KERN_ERR "%s: Write on read-only\n",
++ lo->disk->disk_name);
++ goto error_out;
++ }
++ }
++
++ req->errors = 0;
++
++ mutex_lock(&lo->tx_lock);
++ if (unlikely(!lo->sock)) {
++ mutex_unlock(&lo->tx_lock);
++ printk(KERN_ERR "%s: Attempted send on closed socket\n",
++ lo->disk->disk_name);
++ req->errors++;
++ nbd_end_request(req);
++ return;
++ }
++
++ lo->active_req = req;
++
++ if (nbd_send_req(lo, req) != 0) {
++ printk(KERN_ERR "%s: Request send failed\n",
++ lo->disk->disk_name);
++ req->errors++;
++ nbd_end_request(req);
++ } else {
++ spin_lock(&lo->queue_lock);
++ list_add(&req->queuelist, &lo->queue_head);
++ spin_unlock(&lo->queue_lock);
++ }
++
++ lo->active_req = NULL;
++ mutex_unlock(&lo->tx_lock);
++ wake_up_all(&lo->active_wq);
++
++ return;
++
++error_out:
++ req->errors++;
++ nbd_end_request(req);
++}
++
++static int nbd_thread(void *data)
++{
++ struct nbd_device *lo = data;
++ struct request *req;
++
++ set_user_nice(current, -20);
++ while (!kthread_should_stop() || !list_empty(&lo->waiting_queue)) {
++ /* wait for something to do */
++ wait_event_interruptible(lo->waiting_wq,
++ kthread_should_stop() ||
++ !list_empty(&lo->waiting_queue));
++
++ /* extract request */
++ if (list_empty(&lo->waiting_queue))
++ continue;
++
++ spin_lock_irq(&lo->queue_lock);
++ req = list_entry(lo->waiting_queue.next, struct request,
++ queuelist);
++ list_del_init(&req->queuelist);
++ spin_unlock_irq(&lo->queue_lock);
++
++ /* handle request */
++ nbd_handle_req(lo, req);
++ }
++ return 0;
++}
++
+ /*
+ * We always wait for result of write, for now. It would be nice to make it optional
+ * in future
+@@ -456,65 +537,23 @@ static void do_nbd_request(struct request_queue * q)
+ struct nbd_device *lo;
+
+ blkdev_dequeue_request(req);
++
++ spin_unlock_irq(q->queue_lock);
++
+ dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n",
+ req->rq_disk->disk_name, req, req->cmd_type);
+
+- if (!blk_fs_request(req))
+- goto error_out;
+-
+ lo = req->rq_disk->private_data;
+
+ BUG_ON(lo->magic != LO_MAGIC);
+
+- nbd_cmd(req) = NBD_CMD_READ;
+- if (rq_data_dir(req) == WRITE) {
+- nbd_cmd(req) = NBD_CMD_WRITE;
+- if (lo->flags & NBD_READ_ONLY) {
+- printk(KERN_ERR "%s: Write on read-only\n",
+- lo->disk->disk_name);
+- goto error_out;
+- }
+- }
+-
+- req->errors = 0;
+- spin_unlock_irq(q->queue_lock);
+-
+- mutex_lock(&lo->tx_lock);
+- if (unlikely(!lo->sock)) {
+- mutex_unlock(&lo->tx_lock);
+- printk(KERN_ERR "%s: Attempted send on closed socket\n",
+- lo->disk->disk_name);
+- req->errors++;
+- nbd_end_request(req);
+- spin_lock_irq(q->queue_lock);
+- continue;
+- }
+-
+- lo->active_req = req;
++ spin_lock_irq(&lo->queue_lock);
++ list_add_tail(&req->queuelist, &lo->waiting_queue);
++ spin_unlock_irq(&lo->queue_lock);
+
+- if (nbd_send_req(lo, req) != 0) {
+- printk(KERN_ERR "%s: Request send failed\n",
+- lo->disk->disk_name);
+- req->errors++;
+- nbd_end_request(req);
+- } else {
+- spin_lock(&lo->queue_lock);
+- list_add(&req->queuelist, &lo->queue_head);
+- spin_unlock(&lo->queue_lock);
+- }
+-
+- lo->active_req = NULL;
+- mutex_unlock(&lo->tx_lock);
+- wake_up_all(&lo->active_wq);
++ wake_up(&lo->waiting_wq);
+
+ spin_lock_irq(q->queue_lock);
+- continue;
+-
+-error_out:
+- req->errors++;
+- spin_unlock(q->queue_lock);
+- nbd_end_request(req);
+- spin_lock(q->queue_lock);
+ }
+ }
+
+@@ -524,6 +563,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
+ struct nbd_device *lo = inode->i_bdev->bd_disk->private_data;
+ int error;
+ struct request sreq ;
++ struct task_struct *thread;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+@@ -537,6 +577,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
+ switch (cmd) {
+ case NBD_DISCONNECT:
+ printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);
++ blk_rq_init(NULL, &sreq);
+ sreq.cmd_type = REQ_TYPE_SPECIAL;
+ nbd_cmd(&sreq) = NBD_CMD_DISC;
+ /*
+@@ -571,10 +612,13 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
+ error = -EINVAL;
+ file = fget(arg);
+ if (file) {
++ struct block_device *bdev = inode->i_bdev;
+ inode = file->f_path.dentry->d_inode;
+ if (S_ISSOCK(inode->i_mode)) {
+ lo->file = file;
+ lo->sock = SOCKET_I(inode);
++ if (max_part > 0)
++ bdev->bd_invalidated = 1;
+ error = 0;
+ } else {
+ fput(file);
+@@ -606,7 +650,12 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
+ case NBD_DO_IT:
+ if (!lo->file)
+ return -EINVAL;
++ thread = kthread_create(nbd_thread, lo, lo->disk->disk_name);
++ if (IS_ERR(thread))
++ return PTR_ERR(thread);
++ wake_up_process(thread);
+ error = nbd_do_it(lo);
++ kthread_stop(thread);
+ if (error)
+ return error;
+ sock_shutdown(lo, 1);
+@@ -619,6 +668,8 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
+ lo->bytesize = 0;
+ inode->i_bdev->bd_inode->i_size = 0;
+ set_capacity(lo->disk, 0);
++ if (max_part > 0)
++ ioctl_by_bdev(inode->i_bdev, BLKRRPART, 0);
+ return lo->harderror;
+ case NBD_CLEAR_QUE:
+ /*
+@@ -652,6 +703,7 @@ static int __init nbd_init(void)
+ {
+ int err = -ENOMEM;
+ int i;
++ int part_shift;
+
+ BUILD_BUG_ON(sizeof(struct nbd_request) != 28);
+
+@@ -659,8 +711,17 @@ static int __init nbd_init(void)
+ if (!nbd_dev)
+ return -ENOMEM;
+
++ if (max_part < 0) {
++ printk(KERN_CRIT "nbd: max_part must be >= 0\n");
++ return -EINVAL;
++ }
++
++ part_shift = 0;
++ if (max_part > 0)
++ part_shift = fls(max_part);
++
+ for (i = 0; i < nbds_max; i++) {
+- struct gendisk *disk = alloc_disk(1);
++ struct gendisk *disk = alloc_disk(1 << part_shift);
+ elevator_t *old_e;
+ if (!disk)
+ goto out;
+@@ -695,17 +756,18 @@ static int __init nbd_init(void)
+ nbd_dev[i].file = NULL;
+ nbd_dev[i].magic = LO_MAGIC;
+ nbd_dev[i].flags = 0;
++ INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
+ spin_lock_init(&nbd_dev[i].queue_lock);
+ INIT_LIST_HEAD(&nbd_dev[i].queue_head);
+ mutex_init(&nbd_dev[i].tx_lock);
+ init_waitqueue_head(&nbd_dev[i].active_wq);
++ init_waitqueue_head(&nbd_dev[i].waiting_wq);
+ nbd_dev[i].blksize = 1024;
+ nbd_dev[i].bytesize = 0;
+ disk->major = NBD_MAJOR;
+- disk->first_minor = i;
++ disk->first_minor = i << part_shift;
+ disk->fops = &nbd_fops;
+ disk->private_data = &nbd_dev[i];
+- disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
+ sprintf(disk->disk_name, "nbd%d", i);
+ set_capacity(disk, 0);
+ add_disk(disk);
+@@ -743,7 +805,9 @@ MODULE_DESCRIPTION("Network Block Device");
+ MODULE_LICENSE("GPL");
+
+ module_param(nbds_max, int, 0444);
+-MODULE_PARM_DESC(nbds_max, "How many network block devices to initialize.");
++MODULE_PARM_DESC(nbds_max, "number of network block devices to initialize (default: 16)");
++module_param(max_part, int, 0444);
++MODULE_PARM_DESC(max_part, "number of partitions per device (default: 0)");
+ #ifndef NDEBUG
+ module_param(debugflags, int, 0644);
+ MODULE_PARM_DESC(debugflags, "flags for controlling debug output");
+diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
+index df819f8..570f3b7 100644
+--- a/drivers/block/paride/pd.c
++++ b/drivers/block/paride/pd.c
+@@ -716,10 +716,8 @@ static int pd_special_command(struct pd_unit *disk,
+ struct request rq;
+ int err = 0;
+
+- memset(&rq, 0, sizeof(rq));
+- rq.errors = 0;
++ blk_rq_init(NULL, &rq);
+ rq.rq_disk = disk->gd;
+- rq.ref_count = 1;
+ rq.end_io_data = &wait;
+ rq.end_io = blk_end_sync_rq;
+ blk_insert_request(disk->gd->queue, &rq, 0, func);
+diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
+index 18feb1c..3ba1df9 100644
+--- a/drivers/block/pktcdvd.c
++++ b/drivers/block/pktcdvd.c
+@@ -776,8 +776,6 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
+
+ rq->cmd_len = COMMAND_SIZE(cgc->cmd[0]);
+ memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE);
+- if (sizeof(rq->cmd) > CDROM_PACKET_SIZE)
+- memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE);
+
+ rq->timeout = 60*HZ;
+ rq->cmd_type = REQ_TYPE_BLOCK_PC;
+@@ -2744,7 +2742,6 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
+ int i;
+ int ret = 0;
+ char b[BDEVNAME_SIZE];
+- struct proc_dir_entry *proc;
+ struct block_device *bdev;
+
+ if (pd->pkt_dev == dev) {
+@@ -2788,11 +2785,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
+ goto out_mem;
+ }
+
+- proc = create_proc_entry(pd->name, 0, pkt_proc);
+- if (proc) {
+- proc->data = pd;
+- proc->proc_fops = &pkt_proc_fops;
+- }
++ proc_create_data(pd->name, 0, pkt_proc, &pkt_proc_fops, pd);
+ DPRINTK(DRIVER_NAME": writer %s mapped to %s\n", pd->name, bdevname(bdev, b));
+ return 0;
+
+@@ -3101,7 +3094,7 @@ static int __init pkt_init(void)
+ goto out_misc;
+ }
+
+- pkt_proc = proc_mkdir(DRIVER_NAME, proc_root_driver);
++ pkt_proc = proc_mkdir("driver/"DRIVER_NAME, NULL);
+
+ return 0;
+
+@@ -3117,7 +3110,7 @@ out2:
+
+ static void __exit pkt_exit(void)
+ {
+- remove_proc_entry(DRIVER_NAME, proc_root_driver);
++ remove_proc_entry("driver/"DRIVER_NAME, NULL);
+ misc_deregister(&pkt_misc);
+
+ pkt_debugfs_cleanup();
+diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
+index 7483f94..d797e20 100644
+--- a/drivers/block/ps3disk.c
++++ b/drivers/block/ps3disk.c
+@@ -102,8 +102,7 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
+ dev_dbg(&dev->sbd.core,
+ "%s:%u: bio %u: %u segs %u sectors from %lu\n",
+ __func__, __LINE__, i, bio_segments(iter.bio),
+- bio_sectors(iter.bio),
+- (unsigned long)iter.bio->bi_sector);
++ bio_sectors(iter.bio), iter.bio->bi_sector);
+
+ size = bvec->bv_len;
+ buf = bvec_kmap_irq(bvec, &flags);
+@@ -406,7 +405,6 @@ static void ps3disk_prepare_flush(struct request_queue *q, struct request *req)
+
+ dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
+
+- memset(req->cmd, 0, sizeof(req->cmd));
+ req->cmd_type = REQ_TYPE_FLUSH;
+ }
+
+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/ub.c b/drivers/block/ub.c
+index 27bfe72..e322cce 100644
+--- a/drivers/block/ub.c
++++ b/drivers/block/ub.c
+@@ -2399,7 +2399,7 @@ static void ub_disconnect(struct usb_interface *intf)
+ del_gendisk(lun->disk);
+ /*
+ * I wish I could do:
+- * set_bit(QUEUE_FLAG_DEAD, &q->queue_flags);
++ * queue_flag_set(QUEUE_FLAG_DEAD, q);
+ * As it is, we rely on our internal poisoning and let
+ * the upper levels to spin furiously failing all the I/O.
+ */
+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..f2fff57 100644
+--- a/drivers/block/xen-blkfront.c
++++ b/drivers/block/xen-blkfront.c
+@@ -47,6 +47,7 @@
+
+ #include <xen/interface/grant_table.h>
+ #include <xen/interface/io/blkif.h>
++#include <xen/interface/io/protocols.h>
+
+ #include <asm/xen/hypervisor.h>
+
+@@ -74,7 +75,6 @@ static struct block_device_operations xlvbd_block_fops;
+ struct blkfront_info
+ {
+ struct xenbus_device *xbdev;
+- dev_t dev;
+ struct gendisk *gd;
+ int vdevice;
+ blkif_vdev_t handle;
+@@ -88,6 +88,7 @@ struct blkfront_info
+ struct blk_shadow shadow[BLK_RING_SIZE];
+ unsigned long shadow_free;
+ int feature_barrier;
++ int is_ready;
+
+ /**
+ * The number of people holding this device open. We won't allow a
+@@ -136,7 +137,7 @@ static void blkif_restart_queue_callback(void *arg)
+ schedule_work(&info->work);
+ }
+
+-int blkif_getgeo(struct block_device *bd, struct hd_geometry *hg)
++static int blkif_getgeo(struct block_device *bd, struct hd_geometry *hg)
+ {
+ /* We don't have real geometry info, but let's at least return
+ values consistent with the size of the device */
+@@ -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_ldisc.c b/drivers/bluetooth/hci_ldisc.c
+index 7e31d5f..e5cd856 100644
+--- a/drivers/bluetooth/hci_ldisc.c
++++ b/drivers/bluetooth/hci_ldisc.c
+@@ -143,7 +143,7 @@ restart:
+ int len;
+
+ set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+- len = tty->driver->write(tty, skb->data, skb->len);
++ len = tty->ops->write(tty, skb->data, skb->len);
+ hdev->stat.byte_tx += len;
+
+ skb_pull(skb, len);
+@@ -190,8 +190,7 @@ static int hci_uart_flush(struct hci_dev *hdev)
+
+ /* Flush any pending characters in the driver and discipline. */
+ tty_ldisc_flush(tty);
+- if (tty->driver && tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ tty_driver_flush_buffer(tty);
+
+ if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
+ hu->proto->flush(hu);
+@@ -285,9 +284,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
+
+ if (tty->ldisc.flush_buffer)
+ tty->ldisc.flush_buffer(tty);
+-
+- if (tty->driver && tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ tty_driver_flush_buffer(tty);
+
+ return 0;
+ }
+@@ -373,9 +370,7 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f
+ hu->hdev->stat.byte_rx += count;
+ spin_unlock(&hu->rx_lock);
+
+- if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
+- tty->driver->unthrottle)
+- tty->driver->unthrottle(tty);
++ tty_unthrottle(tty);
+ }
+
+ static int hci_uart_register_dev(struct hci_uart *hu)
+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..69f26eb 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;
+ }
+
+ /*
+@@ -2127,7 +2194,6 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
+ if (ret)
+ break;
+
+- memset(rq->cmd, 0, sizeof(rq->cmd));
+ rq->cmd[0] = GPCMD_READ_CD;
+ rq->cmd[1] = 1 << 2;
+ rq->cmd[2] = (lba >> 24) & 0xff;
+@@ -3309,7 +3375,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 +3496,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 +3515,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 +3639,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..5245a4a 100644
+--- a/drivers/cdrom/viocd.c
++++ b/drivers/cdrom/viocd.c
+@@ -144,6 +144,7 @@ static int proc_viocd_open(struct inode *inode, struct file *file)
+ }
+
+ static const struct file_operations proc_viocd_operations = {
++ .owner = THIS_MODULE,
+ .open = proc_viocd_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -650,10 +651,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);
+@@ -682,7 +680,6 @@ static struct vio_driver viocd_driver = {
+
+ static int __init viocd_init(void)
+ {
+- struct proc_dir_entry *e;
+ int ret = 0;
+
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+@@ -722,12 +719,8 @@ static int __init viocd_init(void)
+ if (ret)
+ goto out_free_info;
+
+- e = create_proc_entry("iSeries/viocd", S_IFREG|S_IRUGO, NULL);
+- if (e) {
+- e->owner = THIS_MODULE;
+- e->proc_fops = &proc_viocd_operations;
+- }
+-
++ proc_create("iSeries/viocd", S_IFREG|S_IRUGO, NULL,
++ &proc_viocd_operations);
+ return 0;
+
+ out_free_info:
+diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
+index 47c6be8..5dce387 100644
+--- a/drivers/char/Kconfig
++++ b/drivers/char/Kconfig
+@@ -80,6 +80,15 @@ config VT_HW_CONSOLE_BINDING
+ information. For framebuffer console users, please refer to
+ <file:Documentation/fb/fbcon.txt>.
+
++config DEVKMEM
++ bool "/dev/kmem virtual device support"
++ default y
++ help
++ Say Y here if you want to support the /dev/kmem device. The
++ /dev/kmem device is rarely used, but can be used for certain
++ kind of kernel debugging operations.
++ When in doubt, say "N".
++
+ config SERIAL_NONSTANDARD
+ bool "Non-standard serial port support"
+ depends on HAS_IOMEM
+@@ -481,6 +490,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
+@@ -704,9 +741,16 @@ config NVRAM
+ To compile this driver as a module, choose M here: the
+ module will be called nvram.
+
++#
++# These legacy RTC drivers just cause too many conflicts with the generic
++# RTC framework ... let's not even try to coexist any more.
++#
++if RTC_LIB=n
++
+ 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 +820,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
+@@ -812,6 +856,8 @@ config DS1302
+ will get access to the real time clock (or hardware clock) built
+ into your computer.
+
++endif # RTC_LIB
++
+ config COBALT_LCD
+ bool "Support for Cobalt LCD"
+ depends on MIPS_COBALT
+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/agp.h b/drivers/char/agp/agp.h
+index c69f795..99e6a40 100644
+--- a/drivers/char/agp/agp.h
++++ b/drivers/char/agp/agp.h
+@@ -35,7 +35,7 @@
+
+ //#define AGP_DEBUG 1
+ #ifdef AGP_DEBUG
+-#define DBG(x,y...) printk (KERN_DEBUG PFX "%s: " x "\n", __FUNCTION__ , ## y)
++#define DBG(x,y...) printk (KERN_DEBUG PFX "%s: " x "\n", __func__ , ## y)
+ #else
+ #define DBG(x,y...) do { } while (0)
+ #endif
+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/amiserial.c b/drivers/char/amiserial.c
+index 3d468f5..37457e5 100644
+--- a/drivers/char/amiserial.c
++++ b/drivers/char/amiserial.c
+@@ -832,33 +832,34 @@ static void change_speed(struct async_struct *info,
+ local_irq_restore(flags);
+ }
+
+-static void rs_put_char(struct tty_struct *tty, unsigned char ch)
++static int rs_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ struct async_struct *info;
+ unsigned long flags;
+
+ if (!tty)
+- return;
++ return 0;
+
+ info = tty->driver_data;
+
+ if (serial_paranoia_check(info, tty->name, "rs_put_char"))
+- return;
++ return 0;
+
+ if (!info->xmit.buf)
+- return;
++ return 0;
+
+ local_irq_save(flags);
+ if (CIRC_SPACE(info->xmit.head,
+ info->xmit.tail,
+ SERIAL_XMIT_SIZE) == 0) {
+ local_irq_restore(flags);
+- return;
++ return 0;
+ }
+
+ info->xmit.buf[info->xmit.head++] = ch;
+ info->xmit.head &= SERIAL_XMIT_SIZE-1;
+ local_irq_restore(flags);
++ return 1;
+ }
+
+ static void rs_flush_chars(struct tty_struct *tty)
+@@ -1074,6 +1075,7 @@ static int get_serial_info(struct async_struct * info,
+ if (!retinfo)
+ return -EFAULT;
+ memset(&tmp, 0, sizeof(tmp));
++ lock_kernel();
+ tmp.type = state->type;
+ tmp.line = state->line;
+ tmp.port = state->port;
+@@ -1084,6 +1086,7 @@ static int get_serial_info(struct async_struct * info,
+ tmp.close_delay = state->close_delay;
+ tmp.closing_wait = state->closing_wait;
+ tmp.custom_divisor = state->custom_divisor;
++ unlock_kernel();
+ if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
+ return -EFAULT;
+ return 0;
+@@ -1099,13 +1102,17 @@ static int set_serial_info(struct async_struct * info,
+
+ if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
+ return -EFAULT;
++
++ lock_kernel();
+ state = info->state;
+ old_state = *state;
+
+ change_irq = new_serial.irq != state->irq;
+ change_port = (new_serial.port != state->port);
+- if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size))
++ if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) {
++ unlock_kernel();
+ return -EINVAL;
++ }
+
+ if (!serial_isroot()) {
+ if ((new_serial.baud_base != state->baud_base) ||
+@@ -1122,8 +1129,10 @@ static int set_serial_info(struct async_struct * info,
+ goto check_and_exit;
+ }
+
+- if (new_serial.baud_base < 9600)
++ if (new_serial.baud_base < 9600) {
++ unlock_kernel();
+ return -EINVAL;
++ }
+
+ /*
+ * OK, past this point, all the error checking has been done.
+@@ -1157,6 +1166,7 @@ check_and_exit:
+ }
+ } else
+ retval = startup(info);
++ unlock_kernel();
+ return retval;
+ }
+
+@@ -1496,8 +1506,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
+ rs_wait_until_sent(tty, info->timeout);
+ }
+ shutdown(info);
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ rs_flush_buffer(tty);
+
+ tty_ldisc_flush(tty);
+ tty->closing = 0;
+@@ -1530,6 +1539,8 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+ return; /* Just in case.... */
+
+ orig_jiffies = jiffies;
++
++ lock_kernel();
+ /*
+ * Set the check interval to be 1/5 of the estimated time to
+ * send a single character, and make it at least 1. The check
+@@ -1570,6 +1581,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+ break;
+ }
+ __set_current_state(TASK_RUNNING);
++ unlock_kernel();
+ #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+ printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
+ #endif
+diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c
+index 17d5431..cdd876d 100644
+--- a/drivers/char/apm-emulation.c
++++ b/drivers/char/apm-emulation.c
+@@ -14,6 +14,7 @@
+ #include <linux/poll.h>
+ #include <linux/slab.h>
+ #include <linux/proc_fs.h>
++#include <linux/seq_file.h>
+ #include <linux/miscdevice.h>
+ #include <linux/apm_bios.h>
+ #include <linux/capability.h>
+@@ -493,11 +494,10 @@ static struct miscdevice apm_device = {
+ * -1: Unknown
+ * 8) min = minutes; sec = seconds
+ */
+-static int apm_get_info(char *buf, char **start, off_t fpos, int length)
++static int proc_apm_show(struct seq_file *m, void *v)
+ {
+ struct apm_power_info info;
+ char *units;
+- int ret;
+
+ info.ac_line_status = 0xff;
+ info.battery_status = 0xff;
+@@ -515,14 +515,27 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
+ case 1: units = "sec"; break;
+ }
+
+- ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
++ seq_printf(m, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
+ driver_version, APM_32_BIT_SUPPORT,
+ info.ac_line_status, info.battery_status,
+ info.battery_flag, info.battery_life,
+ info.time, units);
+
+- return ret;
++ return 0;
+ }
++
++static int proc_apm_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, proc_apm_show, NULL);
++}
++
++static const struct file_operations apm_proc_fops = {
++ .owner = THIS_MODULE,
++ .open = proc_apm_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
+ #endif
+
+ static int kapmd(void *arg)
+@@ -593,7 +606,7 @@ static int __init apm_init(void)
+ wake_up_process(kapmd_tsk);
+
+ #ifdef CONFIG_PROC_FS
+- create_proc_info_entry("apm", 0, NULL, apm_get_info);
++ proc_create("apm", 0, NULL, &apm_proc_fops);
+ #endif
+
+ ret = misc_register(&apm_device);
+diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
+index a7c4990..31d08b6 100644
+--- a/drivers/char/applicom.c
++++ b/drivers/char/applicom.c
+@@ -199,7 +199,7 @@ static int __init applicom_init(void)
+ if (pci_enable_device(dev))
+ return -EIO;
+
+- RamIO = ioremap(pci_resource_start(dev, 0), LEN_RAM_IO);
++ RamIO = ioremap_nocache(pci_resource_start(dev, 0), LEN_RAM_IO);
+
+ if (!RamIO) {
+ printk(KERN_INFO "ac.o: Failed to ioremap PCI memory "
+@@ -254,7 +254,7 @@ static int __init applicom_init(void)
+ /* Now try the specified ISA cards */
+
+ for (i = 0; i < MAX_ISA_BOARD; i++) {
+- RamIO = ioremap(mem + (LEN_RAM_IO * i), LEN_RAM_IO);
++ RamIO = ioremap_nocache(mem + (LEN_RAM_IO * i), LEN_RAM_IO);
+
+ if (!RamIO) {
+ printk(KERN_INFO "ac.o: Failed to ioremap the ISA card's memory space (slot #%d)\n", i + 1);
+diff --git a/drivers/char/bfin-otp.c b/drivers/char/bfin-otp.c
+new file mode 100644
+index 0000000..0a01329
+--- /dev/null
++++ b/drivers/char/bfin-otp.c
+@@ -0,0 +1,189 @@
++/*
++ * Blackfin On-Chip OTP Memory Interface
++ * Supports BF52x/BF54x
++ *
++ * Copyright 2007-2008 Analog Devices Inc.
++ *
++ * Enter bugs at http://blackfin.uclinux.org/
++ *
++ * Licensed under the GPL-2 or later.
++ */
++
++#include <linux/device.h>
++#include <linux/errno.h>
++#include <linux/fs.h>
++#include <linux/init.h>
++#include <linux/miscdevice.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <linux/types.h>
++
++#include <asm/blackfin.h>
++#include <asm/uaccess.h>
++
++#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
++#define stampit() stamp("here i am")
++#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); })
++
++#define DRIVER_NAME "bfin-otp"
++#define PFX DRIVER_NAME ": "
++
++static DEFINE_MUTEX(bfin_otp_lock);
++
++/* OTP Boot ROM functions */
++#define _BOOTROM_OTP_COMMAND 0xEF000018
++#define _BOOTROM_OTP_READ 0xEF00001A
++#define _BOOTROM_OTP_WRITE 0xEF00001C
++
++static u32 (* const otp_command)(u32 command, u32 value) = (void *)_BOOTROM_OTP_COMMAND;
++static u32 (* const otp_read)(u32 page, u32 flags, u64 *page_content) = (void *)_BOOTROM_OTP_READ;
++static u32 (* const otp_write)(u32 page, u32 flags, u64 *page_content) = (void *)_BOOTROM_OTP_WRITE;
++
++/* otp_command(): defines for "command" */
++#define OTP_INIT 0x00000001
++#define OTP_CLOSE 0x00000002
++
++/* otp_{read,write}(): defines for "flags" */
++#define OTP_LOWER_HALF 0x00000000 /* select upper/lower 64-bit half (bit 0) */
++#define OTP_UPPER_HALF 0x00000001
++#define OTP_NO_ECC 0x00000010 /* do not use ECC */
++#define OTP_LOCK 0x00000020 /* sets page protection bit for page */
++#define OTP_ACCESS_READ 0x00001000
++#define OTP_ACCESS_READWRITE 0x00002000
++
++/* Return values for all functions */
++#define OTP_SUCCESS 0x00000000
++#define OTP_MASTER_ERROR 0x001
++#define OTP_WRITE_ERROR 0x003
++#define OTP_READ_ERROR 0x005
++#define OTP_ACC_VIO_ERROR 0x009
++#define OTP_DATA_MULT_ERROR 0x011
++#define OTP_ECC_MULT_ERROR 0x021
++#define OTP_PREV_WR_ERROR 0x041
++#define OTP_DATA_SB_WARN 0x100
++#define OTP_ECC_SB_WARN 0x200
++
++/**
++ * bfin_otp_read - Read OTP pages
++ *
++ * All reads must be in half page chunks (half page == 64 bits).
++ */
++static ssize_t bfin_otp_read(struct file *file, char __user *buff, size_t count, loff_t *pos)
++{
++ ssize_t bytes_done;
++ u32 page, flags, ret;
++ u64 content;
++
++ stampit();
++
++ if (count % sizeof(u64))
++ return -EMSGSIZE;
++
++ if (mutex_lock_interruptible(&bfin_otp_lock))
++ return -ERESTARTSYS;
++
++ bytes_done = 0;
++ page = *pos / (sizeof(u64) * 2);
++ while (bytes_done < count) {
++ flags = (*pos % (sizeof(u64) * 2) ? OTP_UPPER_HALF : OTP_LOWER_HALF);
++ stamp("processing page %i (%s)", page, (flags == OTP_UPPER_HALF ? "upper" : "lower"));
++ ret = otp_read(page, flags, &content);
++ if (ret & OTP_MASTER_ERROR) {
++ bytes_done = -EIO;
++ break;
++ }
++ if (copy_to_user(buff + bytes_done, &content, sizeof(content))) {
++ bytes_done = -EFAULT;
++ break;
++ }
++ if (flags == OTP_UPPER_HALF)
++ ++page;
++ bytes_done += sizeof(content);
++ *pos += sizeof(content);
++ }
++
++ mutex_unlock(&bfin_otp_lock);
++
++ return bytes_done;
++}
++
++#ifdef CONFIG_BFIN_OTP_WRITE_ENABLE
++/**
++ * bfin_otp_write - Write OTP pages
++ *
++ * All writes must be in half page chunks (half page == 64 bits).
++ */
++static ssize_t bfin_otp_write(struct file *filp, const char __user *buff, size_t count, loff_t *pos)
++{
++ stampit();
++
++ if (count % sizeof(u64))
++ return -EMSGSIZE;
++
++ if (mutex_lock_interruptible(&bfin_otp_lock))
++ return -ERESTARTSYS;
++
++ /* need otp_init() documentation before this can be implemented */
++
++ mutex_unlock(&bfin_otp_lock);
++
++ return -EINVAL;
++}
++#else
++# define bfin_otp_write NULL
++#endif
++
++static struct file_operations bfin_otp_fops = {
++ .owner = THIS_MODULE,
++ .read = bfin_otp_read,
++ .write = bfin_otp_write,
++};
++
++static struct miscdevice bfin_otp_misc_device = {
++ .minor = MISC_DYNAMIC_MINOR,
++ .name = DRIVER_NAME,
++ .fops = &bfin_otp_fops,
++};
++
++/**
++ * bfin_otp_init - Initialize module
++ *
++ * Registers the device and notifier handler. Actual device
++ * initialization is handled by bfin_otp_open().
++ */
++static int __init bfin_otp_init(void)
++{
++ int ret;
++
++ stampit();
++
++ ret = misc_register(&bfin_otp_misc_device);
++ if (ret) {
++ pr_init(KERN_ERR PFX "unable to register a misc device\n");
++ return ret;
++ }
++
++ pr_init(KERN_INFO PFX "initialized\n");
++
++ return 0;
++}
++
++/**
++ * bfin_otp_exit - Deinitialize module
++ *
++ * Unregisters the device and notifier handler. Actual device
++ * deinitialization is handled by bfin_otp_close().
++ */
++static void __exit bfin_otp_exit(void)
++{
++ stampit();
++
++ misc_deregister(&bfin_otp_misc_device);
++}
++
++module_init(bfin_otp_init);
++module_exit(bfin_otp_exit);
++
++MODULE_AUTHOR("Mike Frysinger <vapier at gentoo.org>");
++MODULE_DESCRIPTION("Blackfin OTP Memory Interface");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c
+index 6b104e4..4246b8e 100644
+--- a/drivers/char/consolemap.c
++++ b/drivers/char/consolemap.c
+@@ -277,6 +277,7 @@ u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
+ return p->inverse_translations[m][glyph];
+ }
+ }
++EXPORT_SYMBOL_GPL(inverse_translate);
+
+ static void update_user_maps(void)
+ {
+diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c
+index c2d23ca..c0a4a0b 100644
+--- a/drivers/char/cs5535_gpio.c
++++ b/drivers/char/cs5535_gpio.c
+@@ -215,7 +215,7 @@ static int __init cs5535_gpio_init(void)
+ else
+ mask = 0x0b003c66;
+
+- if (request_region(gpio_base, CS5535_GPIO_SIZE, NAME) == 0) {
++ if (!request_region(gpio_base, CS5535_GPIO_SIZE, NAME)) {
+ printk(KERN_ERR NAME ": can't allocate I/O for GPIO\n");
+ return -ENODEV;
+ }
+diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
+index e4f579c..ef73e72 100644
+--- a/drivers/char/cyclades.c
++++ b/drivers/char/cyclades.c
+@@ -21,7 +21,6 @@
+ *
+ * This version supports shared IRQ's (only for PCI boards).
+ *
+- * $Log: cyclades.c,v $
+ * Prevent users from opening non-existing Z ports.
+ *
+ * Revision 2.3.2.8 2000/07/06 18:14:16 ivan
+@@ -62,7 +61,7 @@
+ * Driver now makes sure that the constant SERIAL_XMIT_SIZE is defined;
+ *
+ * Revision 2.3.2.2 1999/10/01 11:27:43 ivan
+- * Fixed bug in cyz_poll that would make all ports but port 0
++ * Fixed bug in cyz_poll that would make all ports but port 0
+ * unable to transmit/receive data (Cyclades-Z only);
+ * Implemented logic to prevent the RX buffer from being stuck with data
+ * due to a driver / firmware race condition in interrupt op mode
+@@ -83,25 +82,25 @@
+ * Revision 2.3.1.1 1999/07/15 16:45:53 ivan
+ * Removed CY_PROC conditional compilation;
+ * Implemented SMP-awareness for the driver;
+- * Implemented a new ISA IRQ autoprobe that uses the irq_probe_[on|off]
++ * Implemented a new ISA IRQ autoprobe that uses the irq_probe_[on|off]
+ * functions;
+ * The driver now accepts memory addresses (maddr=0xMMMMM) and IRQs
+ * (irq=NN) as parameters (only for ISA boards);
+- * Fixed bug in set_line_char that would prevent the Cyclades-Z
++ * Fixed bug in set_line_char that would prevent the Cyclades-Z
+ * ports from being configured at speeds above 115.2Kbps;
+ * Fixed bug in cy_set_termios that would prevent XON/XOFF flow control
+ * switching from working properly;
+- * The driver now only prints IRQ info for the Cyclades-Z if it's
++ * The driver now only prints IRQ info for the Cyclades-Z if it's
+ * configured to work in interrupt mode;
+ *
+ * Revision 2.2.2.3 1999/06/28 11:13:29 ivan
+ * Added support for interrupt mode operation for the Z cards;
+ * Removed the driver inactivity control for the Z;
+- * Added a missing MOD_DEC_USE_COUNT in the cy_open function for when
++ * Added a missing MOD_DEC_USE_COUNT in the cy_open function for when
+ * the Z firmware is not loaded yet;
+- * Replaced the "manual" Z Tx flush buffer by a call to a FW command of
++ * Replaced the "manual" Z Tx flush buffer by a call to a FW command of
+ * same functionality;
+- * Implemented workaround for IRQ setting loss on the PCI configuration
++ * Implemented workaround for IRQ setting loss on the PCI configuration
+ * registers after a PCI bridge EEPROM reload (affects PLX9060 only);
+ *
+ * Revision 2.2.2.2 1999/05/14 17:18:15 ivan
+@@ -112,22 +111,22 @@
+ * BREAK implementation changed in order to make use of the 'break_ctl'
+ * TTY facility;
+ * Fixed typo in TTY structure field 'driver_name';
+- * Included a PCI bridge reset and EEPROM reload in the board
++ * Included a PCI bridge reset and EEPROM reload in the board
+ * initialization code (for both Y and Z series).
+ *
+ * Revision 2.2.2.1 1999/04/08 16:17:43 ivan
+- * Fixed a bug in cy_wait_until_sent that was preventing the port to be
++ * Fixed a bug in cy_wait_until_sent that was preventing the port to be
+ * closed properly after a SIGINT;
+ * Module usage counter scheme revisited;
+ * Added support to the upcoming Y PCI boards (i.e., support to additional
+ * PCI Device ID's).
+- *
++ *
+ * Revision 2.2.1.10 1999/01/20 16:14:29 ivan
+ * Removed all unnecessary page-alignement operations in ioremap calls
+ * (ioremap is currently safe for these operations).
+ *
+ * Revision 2.2.1.9 1998/12/30 18:18:30 ivan
+- * Changed access to PLX PCI bridge registers from I/O to MMIO, in
++ * Changed access to PLX PCI bridge registers from I/O to MMIO, in
+ * order to make PLX9050-based boards work with certain motherboards.
+ *
+ * Revision 2.2.1.8 1998/11/13 12:46:20 ivan
+@@ -148,7 +147,7 @@
+ * Fixed Cyclom-4Yo hardware detection bug.
+ *
+ * Revision 2.2.1.4 1998/08/04 11:02:50 ivan
+- * /proc/cyclades implementation with great collaboration of
++ * /proc/cyclades implementation with great collaboration of
+ * Marc Lewis <marc at blarg.net>;
+ * cyy_interrupt was changed to avoid occurrence of kernel oopses
+ * during PPP operation.
+@@ -157,7 +156,7 @@
+ * General code review in order to comply with 2.1 kernel standards;
+ * data loss prevention for slow devices revisited (cy_wait_until_sent
+ * was created);
+- * removed conditional compilation for new/old PCI structure support
++ * removed conditional compilation for new/old PCI structure support
+ * (now the driver only supports the new PCI structure).
+ *
+ * Revision 2.2.1.1 1998/03/19 16:43:12 ivan
+@@ -168,7 +167,7 @@
+ * cleaned up the data loss fix;
+ * fixed XON/XOFF handling once more (Cyclades-Z);
+ * general review of the driver routines;
+- * introduction of a mechanism to prevent data loss with slow
++ * introduction of a mechanism to prevent data loss with slow
+ * printers, by forcing a delay before closing the port.
+ *
+ * Revision 2.1.1.2 1998/02/17 16:50:00 ivan
+@@ -182,12 +181,12 @@
+ * Code review for the module cleanup routine;
+ * fixed RTS and DTR status report for new CD1400's in get_modem_info;
+ * includes anonymous changes regarding signal_pending.
+- *
++ *
+ * Revision 2.1 1997/11/01 17:42:41 ivan
+ * Changes in the driver to support Alpha systems (except 8Zo V_1);
+ * BREAK fix for the Cyclades-Z boards;
+ * driver inactivity control by FW implemented;
+- * introduction of flag that allows driver to take advantage of
++ * introduction of flag that allows driver to take advantage of
+ * a special CD1400 feature related to HW flow control;
+ * added support for the CD1400 rev. J (Cyclom-Y boards);
+ * introduction of ioctls to:
+@@ -196,17 +195,17 @@
+ * - adjust the polling interval (Cyclades-Z);
+ *
+ * Revision 1.36.4.33 1997/06/27 19:00:00 ivan
+- * Fixes related to kernel version conditional
++ * Fixes related to kernel version conditional
+ * compilation.
+- *
++ *
+ * Revision 1.36.4.32 1997/06/14 19:30:00 ivan
+- * Compatibility issues between kernels 2.0.x and
++ * Compatibility issues between kernels 2.0.x and
+ * 2.1.x (mainly related to clear_bit function).
+- *
++ *
+ * Revision 1.36.4.31 1997/06/03 15:30:00 ivan
+- * Changes to define the memory window according to the
++ * Changes to define the memory window according to the
+ * board type.
+- *
++ *
+ * Revision 1.36.4.30 1997/05/16 15:30:00 daniel
+ * Changes to support new cycladesZ boards.
+ *
+@@ -624,7 +623,7 @@
+ #undef CY_PCI_DEBUG
+
+ /*
+- * Include section
++ * Include section
+ */
+ #include <linux/module.h>
+ #include <linux/errno.h>
+@@ -649,9 +648,9 @@
+ #include <linux/firmware.h>
+
+ #include <asm/system.h>
+-#include <asm/io.h>
++#include <linux/io.h>
+ #include <asm/irq.h>
+-#include <asm/uaccess.h>
++#include <linux/uaccess.h>
+
+ #include <linux/kernel.h>
+ #include <linux/pci.h>
+@@ -668,10 +667,10 @@ static void cy_send_xchar(struct tty_struct *tty, char ch);
+ ((readl(&((struct RUNTIME_9060 __iomem *) \
+ ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0)
+
+-#define ISZLOADED(card) (((ZO_V1==readl(&((struct RUNTIME_9060 __iomem *) \
++#define ISZLOADED(card) (((ZO_V1 == readl(&((struct RUNTIME_9060 __iomem *) \
+ ((card).ctl_addr))->mail_box_0)) || \
+ Z_FPGA_CHECK(card)) && \
+- (ZFIRM_ID==readl(&((struct FIRM_ID __iomem *) \
++ (ZFIRM_ID == readl(&((struct FIRM_ID __iomem *) \
+ ((card).base_addr+ID_ADDRESS))->signature)))
+
+ #ifndef SERIAL_XMIT_SIZE
+@@ -809,12 +808,12 @@ static char baud_cor3[] = { /* receive threshold */
+
+ /*
+ * The Cyclades driver implements HW flow control as any serial driver.
+- * The cyclades_port structure member rflow and the vector rflow_thr
+- * allows us to take advantage of a special feature in the CD1400 to avoid
+- * data loss even when the system interrupt latency is too high. These flags
+- * are to be used only with very special applications. Setting these flags
+- * requires the use of a special cable (DTR and RTS reversed). In the new
+- * CD1400-based boards (rev. 6.00 or later), there is no need for special
++ * The cyclades_port structure member rflow and the vector rflow_thr
++ * allows us to take advantage of a special feature in the CD1400 to avoid
++ * data loss even when the system interrupt latency is too high. These flags
++ * are to be used only with very special applications. Setting these flags
++ * requires the use of a special cable (DTR and RTS reversed). In the new
++ * CD1400-based boards (rev. 6.00 or later), there is no need for special
+ * cables.
+ */
+
+@@ -841,14 +840,22 @@ static int cy_chip_offset[] = { 0x0000,
+
+ #ifdef CONFIG_PCI
+ static struct pci_device_id cy_pci_dev_id[] __devinitdata = {
+- { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) }, /* PCI < 1Mb */
+- { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Hi) }, /* PCI > 1Mb */
+- { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Lo) }, /* 4Y PCI < 1Mb */
+- { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Hi) }, /* 4Y PCI > 1Mb */
+- { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Lo) }, /* 8Y PCI < 1Mb */
+- { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Hi) }, /* 8Y PCI > 1Mb */
+- { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Lo) }, /* Z PCI < 1Mb */
+- { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Hi) }, /* Z PCI > 1Mb */
++ /* PCI < 1Mb */
++ { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) },
++ /* PCI > 1Mb */
++ { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Hi) },
++ /* 4Y PCI < 1Mb */
++ { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Lo) },
++ /* 4Y PCI > 1Mb */
++ { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Hi) },
++ /* 8Y PCI < 1Mb */
++ { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Lo) },
++ /* 8Y PCI > 1Mb */
++ { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Hi) },
++ /* Z PCI < 1Mb */
++ { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Lo) },
++ /* Z PCI > 1Mb */
++ { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Hi) },
+ { } /* end of table */
+ };
+ MODULE_DEVICE_TABLE(pci, cy_pci_dev_id);
+@@ -905,15 +912,14 @@ static inline int serial_paranoia_check(struct cyclades_port *info,
+
+ This function is only called from inside spinlock-protected code.
+ */
+-static int cyy_issue_cmd(void __iomem * base_addr, u_char cmd, int index)
++static int cyy_issue_cmd(void __iomem *base_addr, u_char cmd, int index)
+ {
+ unsigned int i;
+
+ /* Check to see that the previous command has completed */
+ for (i = 0; i < 100; i++) {
+- if (readb(base_addr + (CyCCR << index)) == 0) {
++ if (readb(base_addr + (CyCCR << index)) == 0)
+ break;
+- }
+ udelay(10L);
+ }
+ /* if the CCR never cleared, the previous command
+@@ -929,7 +935,7 @@ static int cyy_issue_cmd(void __iomem * base_addr, u_char cmd, int index)
+
+ #ifdef CONFIG_ISA
+ /* ISA interrupt detection code */
+-static unsigned detect_isa_irq(void __iomem * address)
++static unsigned detect_isa_irq(void __iomem *address)
+ {
+ int irq;
+ unsigned long irqs, flags;
+@@ -1038,7 +1044,7 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
+ if (info->flags & ASYNC_SAK)
+ do_SAK(tty);
+ } else if (data & CyFRAME) {
+- tty_insert_flip_char( tty,
++ tty_insert_flip_char(tty,
+ readb(base_addr + (CyRDSR <<
+ index)), TTY_FRAME);
+ info->icount.rx++;
+@@ -1320,7 +1326,8 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id)
+
+ if (unlikely(cinfo == NULL)) {
+ #ifdef CY_DEBUG_INTERRUPTS
+- printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d\n",irq);
++ printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d\n",
++ irq);
+ #endif
+ return IRQ_NONE; /* spurious interrupt */
+ }
+@@ -1375,12 +1382,12 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id)
+
+ /***********************************************************/
+ /********* End of block of Cyclom-Y specific code **********/
+-/******** Start of block of Cyclades-Z specific code *********/
++/******** Start of block of Cyclades-Z specific code *******/
+ /***********************************************************/
+
+ static int
+ cyz_fetch_msg(struct cyclades_card *cinfo,
+- __u32 * channel, __u8 * cmd, __u32 * param)
++ __u32 *channel, __u8 *cmd, __u32 *param)
+ {
+ struct FIRM_ID __iomem *firm_id;
+ struct ZFW_CTRL __iomem *zfw_ctrl;
+@@ -1388,9 +1395,8 @@ cyz_fetch_msg(struct cyclades_card *cinfo,
+ unsigned long loc_doorbell;
+
+ firm_id = cinfo->base_addr + ID_ADDRESS;
+- if (!ISZLOADED(*cinfo)) {
++ if (!ISZLOADED(*cinfo))
+ return -1;
+- }
+ zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
+ board_ctrl = &zfw_ctrl->board_ctrl;
+
+@@ -1418,9 +1424,9 @@ cyz_issue_cmd(struct cyclades_card *cinfo,
+ unsigned int index;
+
+ firm_id = cinfo->base_addr + ID_ADDRESS;
+- if (!ISZLOADED(*cinfo)) {
++ if (!ISZLOADED(*cinfo))
+ return -1;
+- }
++
+ zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
+ board_ctrl = &zfw_ctrl->board_ctrl;
+
+@@ -1428,9 +1434,8 @@ cyz_issue_cmd(struct cyclades_card *cinfo,
+ pci_doorbell =
+ &((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->pci_doorbell;
+ while ((readl(pci_doorbell) & 0xff) != 0) {
+- if (index++ == 1000) {
++ if (index++ == 1000)
+ return (int)(readl(pci_doorbell) & 0xff);
+- }
+ udelay(50L);
+ }
+ cy_writel(&board_ctrl->hcmd_channel, channel);
+@@ -1504,7 +1509,8 @@ static void cyz_handle_rx(struct cyclades_port *info,
+ while (len--) {
+ data = readb(cinfo->base_addr + rx_bufaddr +
+ new_rx_get);
+- new_rx_get = (new_rx_get + 1)& (rx_bufsize - 1);
++ new_rx_get = (new_rx_get + 1) &
++ (rx_bufsize - 1);
+ tty_insert_flip_char(tty, data, TTY_NORMAL);
+ info->idle_stats.recv_bytes++;
+ info->icount.rx++;
+@@ -1636,7 +1642,8 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
+ special_count = 0;
+ delta_count = 0;
+ info = &cinfo->ports[channel];
+- if ((tty = info->tty) == NULL)
++ tty = info->tty;
++ if (tty == NULL)
+ continue;
+
+ ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
+@@ -1732,7 +1739,8 @@ static irqreturn_t cyz_interrupt(int irq, void *dev_id)
+
+ if (unlikely(cinfo == NULL)) {
+ #ifdef CY_DEBUG_INTERRUPTS
+- printk(KERN_DEBUG "cyz_interrupt: spurious interrupt %d\n",irq);
++ printk(KERN_DEBUG "cyz_interrupt: spurious interrupt %d\n",
++ irq);
+ #endif
+ return IRQ_NONE; /* spurious interrupt */
+ }
+@@ -1851,9 +1859,8 @@ static int startup(struct cyclades_port *info)
+ }
+
+ if (!info->type) {
+- if (info->tty) {
++ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+- }
+ free_page(page);
+ goto errout;
+ }
+@@ -1904,9 +1911,8 @@ static int startup(struct cyclades_port *info)
+ readb(base_addr + (CySRER << index)) | CyRxData);
+ info->flags |= ASYNC_INITIALIZED;
+
+- if (info->tty) {
++ if (info->tty)
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+- }
+ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+ info->breakon = info->breakoff = 0;
+ memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
+@@ -1925,9 +1931,8 @@ static int startup(struct cyclades_port *info)
+ base_addr = card->base_addr;
+
+ firm_id = base_addr + ID_ADDRESS;
+- if (!ISZLOADED(*card)) {
++ if (!ISZLOADED(*card))
+ return -ENODEV;
+- }
+
+ zfw_ctrl = card->base_addr +
+ (readl(&firm_id->zfwctrl_addr) & 0xfffff);
+@@ -1990,9 +1995,8 @@ static int startup(struct cyclades_port *info)
+ /* enable send, recv, modem !!! */
+
+ info->flags |= ASYNC_INITIALIZED;
+- if (info->tty) {
++ if (info->tty)
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+- }
+ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+ info->breakon = info->breakoff = 0;
+ memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
+@@ -2061,9 +2065,8 @@ static void shutdown(struct cyclades_port *info)
+ void __iomem *base_addr;
+ int chip, channel, index;
+
+- if (!(info->flags & ASYNC_INITIALIZED)) {
++ if (!(info->flags & ASYNC_INITIALIZED))
+ return;
+- }
+
+ card = info->card;
+ channel = info->line - card->first_line;
+@@ -2105,9 +2108,8 @@ static void shutdown(struct cyclades_port *info)
+ /* it may be appropriate to clear _XMIT at
+ some later date (after testing)!!! */
+
+- if (info->tty) {
++ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+- }
+ info->flags &= ~ASYNC_INITIALIZED;
+ spin_unlock_irqrestore(&card->card_lock, flags);
+ } else {
+@@ -2124,9 +2126,8 @@ static void shutdown(struct cyclades_port *info)
+ #endif
+
+ firm_id = base_addr + ID_ADDRESS;
+- if (!ISZLOADED(*card)) {
++ if (!ISZLOADED(*card))
+ return;
+- }
+
+ zfw_ctrl = card->base_addr +
+ (readl(&firm_id->zfwctrl_addr) & 0xfffff);
+@@ -2157,9 +2158,8 @@ static void shutdown(struct cyclades_port *info)
+ #endif
+ }
+
+- if (info->tty) {
++ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+- }
+ info->flags &= ~ASYNC_INITIALIZED;
+
+ spin_unlock_irqrestore(&card->card_lock, flags);
+@@ -2204,7 +2204,8 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
+ * If non-blocking mode is set, then make the check up front
+ * and then exit.
+ */
+- if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
++ if ((filp->f_flags & O_NONBLOCK) ||
++ (tty->flags & (1 << TTY_IO_ERROR))) {
+ info->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+ }
+@@ -2301,7 +2302,8 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
+ return -EINVAL;
+ }
+
+- zfw_ctrl = base_addr + (readl(&firm_id->zfwctrl_addr)& 0xfffff);
++ zfw_ctrl = base_addr + (readl(&firm_id->zfwctrl_addr)
++ & 0xfffff);
+ board_ctrl = &zfw_ctrl->board_ctrl;
+ ch_ctrl = zfw_ctrl->ch_ctrl;
+
+@@ -2378,9 +2380,9 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
+ int retval;
+
+ line = tty->index;
+- if ((tty->index < 0) || (NR_PORTS <= line)) {
++ if (tty->index < 0 || NR_PORTS <= line)
+ return -ENODEV;
+- }
++
+ for (i = 0; i < NR_CARDS; i++)
+ if (line < cy_card[i].first_line + cy_card[i].nports &&
+ line >= cy_card[i].first_line)
+@@ -2388,9 +2390,8 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
+ if (i >= NR_CARDS)
+ return -ENODEV;
+ info = &cy_card[i].ports[line - cy_card[i].first_line];
+- if (info->line < 0) {
++ if (info->line < 0)
+ return -ENODEV;
+- }
+
+ /* If the card's firmware hasn't been loaded,
+ treat it as absent from the system. This
+@@ -2456,9 +2457,9 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
+ #endif
+ tty->driver_data = info;
+ info->tty = tty;
+- if (serial_paranoia_check(info, tty->name, "cy_open")) {
++ if (serial_paranoia_check(info, tty->name, "cy_open"))
+ return -ENODEV;
+- }
++
+ #ifdef CY_DEBUG_OPEN
+ printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d\n", info->line,
+ info->count);
+@@ -2482,9 +2483,8 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
+ * Start up serial port
+ */
+ retval = startup(info);
+- if (retval) {
++ if (retval)
+ return retval;
+- }
+
+ retval = block_til_ready(tty, filp, info);
+ if (retval) {
+@@ -2522,6 +2522,7 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
+ return; /* Just in case.... */
+
+ orig_jiffies = jiffies;
++ lock_kernel();
+ /*
+ * Set the check interval to be 1/5 of the estimated time to
+ * send a single character, and make it at least 1. The check
+@@ -2573,11 +2574,47 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
+ }
+ /* Run one more char cycle */
+ msleep_interruptible(jiffies_to_msecs(char_time * 5));
++ unlock_kernel();
+ #ifdef CY_DEBUG_WAIT_UNTIL_SENT
+ printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies);
+ #endif
+ }
+
++static void cy_flush_buffer(struct tty_struct *tty)
++{
++ struct cyclades_port *info = tty->driver_data;
++ struct cyclades_card *card;
++ int channel, retval;
++ unsigned long flags;
++
++#ifdef CY_DEBUG_IO
++ printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line);
++#endif
++
++ if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
++ return;
++
++ card = info->card;
++ channel = info->line - card->first_line;
++
++ spin_lock_irqsave(&card->card_lock, flags);
++ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
++ spin_unlock_irqrestore(&card->card_lock, flags);
++
++ if (IS_CYC_Z(*card)) { /* If it is a Z card, flush the on-board
++ buffers as well */
++ spin_lock_irqsave(&card->card_lock, flags);
++ retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
++ if (retval != 0) {
++ printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
++ "was %x\n", info->line, retval);
++ }
++ spin_unlock_irqrestore(&card->card_lock, flags);
++ }
++ tty_wakeup(tty);
++} /* cy_flush_buffer */
++
++
+ /*
+ * This routine is called when a particular tty device is closed.
+ */
+@@ -2591,9 +2628,8 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
+ printk(KERN_DEBUG "cyc:cy_close ttyC%d\n", info->line);
+ #endif
+
+- if (!info || serial_paranoia_check(info, tty->name, "cy_close")) {
++ if (!info || serial_paranoia_check(info, tty->name, "cy_close"))
+ return;
+- }
+
+ card = info->card;
+
+@@ -2641,9 +2677,9 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
+ */
+ tty->closing = 1;
+ spin_unlock_irqrestore(&card->card_lock, flags);
+- if (info->closing_wait != CY_CLOSING_WAIT_NONE) {
++ if (info->closing_wait != CY_CLOSING_WAIT_NONE)
+ tty_wait_until_sent(tty, info->closing_wait);
+- }
++
+ spin_lock_irqsave(&card->card_lock, flags);
+
+ if (!IS_CYC_Z(*card)) {
+@@ -2657,15 +2693,16 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
+ cy_writeb(base_addr + (CySRER << index),
+ readb(base_addr + (CySRER << index)) & ~CyRxData);
+ if (info->flags & ASYNC_INITIALIZED) {
+- /* Waiting for on-board buffers to be empty before closing
+- the port */
++ /* Waiting for on-board buffers to be empty before
++ closing the port */
+ spin_unlock_irqrestore(&card->card_lock, flags);
+ cy_wait_until_sent(tty, info->timeout);
+ spin_lock_irqsave(&card->card_lock, flags);
+ }
+ } else {
+ #ifdef Z_WAKE
+- /* Waiting for on-board buffers to be empty before closing the port */
++ /* Waiting for on-board buffers to be empty before closing
++ the port */
+ void __iomem *base_addr = card->base_addr;
+ struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS;
+ struct ZFW_CTRL __iomem *zfw_ctrl =
+@@ -2689,8 +2726,7 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
+
+ spin_unlock_irqrestore(&card->card_lock, flags);
+ shutdown(info);
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ cy_flush_buffer(tty);
+ tty_ldisc_flush(tty);
+ spin_lock_irqsave(&card->card_lock, flags);
+
+@@ -2738,17 +2774,16 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
+ printk(KERN_DEBUG "cyc:cy_write ttyC%d\n", info->line);
+ #endif
+
+- if (serial_paranoia_check(info, tty->name, "cy_write")) {
++ if (serial_paranoia_check(info, tty->name, "cy_write"))
+ return 0;
+- }
+
+ if (!info->xmit_buf)
+ return 0;
+
+ spin_lock_irqsave(&info->card->card_lock, flags);
+ while (1) {
+- c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1),
+- (int)(SERIAL_XMIT_SIZE - info->xmit_head)));
++ c = min(count, (int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1));
++ c = min(c, (int)(SERIAL_XMIT_SIZE - info->xmit_head));
+
+ if (c <= 0)
+ break;
+@@ -2766,9 +2801,9 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
+ info->idle_stats.xmit_bytes += ret;
+ info->idle_stats.xmit_idle = jiffies;
+
+- if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
++ if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped)
+ start_xmit(info);
+- }
++
+ return ret;
+ } /* cy_write */
+
+@@ -2779,7 +2814,7 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
+ * done stuffing characters into the driver. If there is no room
+ * in the queue, the character is ignored.
+ */
+-static void cy_put_char(struct tty_struct *tty, unsigned char ch)
++static int cy_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ struct cyclades_port *info = tty->driver_data;
+ unsigned long flags;
+@@ -2789,15 +2824,15 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch)
+ #endif
+
+ if (serial_paranoia_check(info, tty->name, "cy_put_char"))
+- return;
++ return 0;
+
+ if (!info->xmit_buf)
+- return;
++ return 0;
+
+ spin_lock_irqsave(&info->card->card_lock, flags);
+ if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) {
+ spin_unlock_irqrestore(&info->card->card_lock, flags);
+- return;
++ return 0;
+ }
+
+ info->xmit_buf[info->xmit_head++] = ch;
+@@ -2806,11 +2841,12 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch)
+ info->idle_stats.xmit_bytes++;
+ info->idle_stats.xmit_idle = jiffies;
+ spin_unlock_irqrestore(&info->card->card_lock, flags);
++ return 1;
+ } /* cy_put_char */
+
+ /*
+ * This routine is called by the kernel after it has written a
+- * series of characters to the tty device using put_char().
++ * series of characters to the tty device using put_char().
+ */
+ static void cy_flush_chars(struct tty_struct *tty)
+ {
+@@ -2882,6 +2918,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
+ int char_count;
+ __u32 tx_put, tx_get, tx_bufsize;
+
++ lock_kernel();
+ firm_id = card->base_addr + ID_ADDRESS;
+ zfw_ctrl = card->base_addr +
+ (readl(&firm_id->zfwctrl_addr) & 0xfffff);
+@@ -2899,6 +2936,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
+ printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
+ info->line, info->xmit_cnt + char_count);
+ #endif
++ unlock_kernel();
+ return info->xmit_cnt + char_count;
+ }
+ #endif /* Z_EXT_CHARS_IN_BUFFER */
+@@ -2950,12 +2988,12 @@ static void set_line_char(struct cyclades_port *info)
+ int baud, baud_rate = 0;
+ int i;
+
+- if (!info->tty || !info->tty->termios) {
++ if (!info->tty || !info->tty->termios)
+ return;
+- }
+- if (info->line == -1) {
++
++ if (info->line == -1)
+ return;
+- }
++
+ cflag = info->tty->termios->c_cflag;
+ iflag = info->tty->termios->c_iflag;
+
+@@ -2994,13 +3032,11 @@ static void set_line_char(struct cyclades_port *info)
+ }
+ /* find the baud index */
+ for (i = 0; i < 20; i++) {
+- if (baud == baud_table[i]) {
++ if (baud == baud_table[i])
+ break;
+- }
+ }
+- if (i == 20) {
++ if (i == 20)
+ i = 19; /* CD1400_MAX_SPEED */
+- }
+
+ if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) ==
+ ASYNC_SPD_CUST) {
+@@ -3059,18 +3095,16 @@ static void set_line_char(struct cyclades_port *info)
+ info->cor1 = Cy_8_BITS;
+ break;
+ }
+- if (cflag & CSTOPB) {
++ if (cflag & CSTOPB)
+ info->cor1 |= Cy_2_STOP;
+- }
++
+ if (cflag & PARENB) {
+- if (cflag & PARODD) {
++ if (cflag & PARODD)
+ info->cor1 |= CyPARITY_O;
+- } else {
++ else
+ info->cor1 |= CyPARITY_E;
+- }
+- } else {
++ } else
+ info->cor1 |= CyPARITY_NONE;
+- }
+
+ /* CTS flow control flag */
+ if (cflag & CRTSCTS) {
+@@ -3123,7 +3157,8 @@ static void set_line_char(struct cyclades_port *info)
+ cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch |
+ CyCOR3ch, index);
+
+- cy_writeb(base_addr + (CyCAR << index), (u_char) channel); /* !!! Is this needed? */
++ /* !!! Is this needed? */
++ cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+ cy_writeb(base_addr + (CyRTPR << index),
+ (info->default_timeout ? info->default_timeout : 0x02));
+ /* 10ms rx timeout */
+@@ -3191,9 +3226,8 @@ static void set_line_char(struct cyclades_port *info)
+ #endif
+ }
+
+- if (info->tty) {
++ if (info->tty)
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+- }
+ spin_unlock_irqrestore(&card->card_lock, flags);
+
+ } else {
+@@ -3206,9 +3240,8 @@ static void set_line_char(struct cyclades_port *info)
+ int retval;
+
+ firm_id = card->base_addr + ID_ADDRESS;
+- if (!ISZLOADED(*card)) {
++ if (!ISZLOADED(*card))
+ return;
+- }
+
+ zfw_ctrl = card->base_addr +
+ (readl(&firm_id->zfwctrl_addr) & 0xfffff);
+@@ -3268,14 +3301,12 @@ static void set_line_char(struct cyclades_port *info)
+ readl(&ch_ctrl->comm_data_l) | C_DL_1STOP);
+ }
+ if (cflag & PARENB) {
+- if (cflag & PARODD) {
++ if (cflag & PARODD)
+ cy_writel(&ch_ctrl->comm_parity, C_PR_ODD);
+- } else {
++ else
+ cy_writel(&ch_ctrl->comm_parity, C_PR_EVEN);
+- }
+- } else {
++ } else
+ cy_writel(&ch_ctrl->comm_parity, C_PR_NONE);
+- }
+
+ /* CTS flow control flag */
+ if (cflag & CRTSCTS) {
+@@ -3305,11 +3336,10 @@ static void set_line_char(struct cyclades_port *info)
+ }
+
+ /* CD sensitivity */
+- if (cflag & CLOCAL) {
++ if (cflag & CLOCAL)
+ info->flags &= ~ASYNC_CHECK_CD;
+- } else {
++ else
+ info->flags |= ASYNC_CHECK_CD;
+- }
+
+ if (baud == 0) { /* baud rate is zero, turn off line */
+ cy_writel(&ch_ctrl->rs_control,
+@@ -3325,21 +3355,20 @@ static void set_line_char(struct cyclades_port *info)
+ #endif
+ }
+
+- retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM,0L);
++ retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
+ if (retval != 0) {
+ printk(KERN_ERR "cyc:set_line_char(2) retval on ttyC%d "
+ "was %x\n", info->line, retval);
+ }
+
+- if (info->tty) {
++ if (info->tty)
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+- }
+ }
+ } /* set_line_char */
+
+ static int
+ get_serial_info(struct cyclades_port *info,
+- struct serial_struct __user * retinfo)
++ struct serial_struct __user *retinfo)
+ {
+ struct serial_struct tmp;
+ struct cyclades_card *cinfo = info->card;
+@@ -3363,7 +3392,7 @@ get_serial_info(struct cyclades_port *info,
+
+ static int
+ set_serial_info(struct cyclades_port *info,
+- struct serial_struct __user * new_info)
++ struct serial_struct __user *new_info)
+ {
+ struct serial_struct new_serial;
+ struct cyclades_port old_info;
+@@ -3417,7 +3446,7 @@ check_and_exit:
+ * transmit holding register is empty. This functionality
+ * allows an RS485 driver to be written in user space.
+ */
+-static int get_lsr_info(struct cyclades_port *info, unsigned int __user * value)
++static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value)
+ {
+ struct cyclades_card *card;
+ int chip, channel, index;
+@@ -3461,9 +3490,11 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
+ struct BOARD_CTRL __iomem *board_ctrl;
+ struct CH_CTRL __iomem *ch_ctrl;
+
+- if (serial_paranoia_check(info, tty->name, __FUNCTION__))
++ if (serial_paranoia_check(info, tty->name, __func__))
+ return -ENODEV;
+
++ lock_kernel();
++
+ card = info->card;
+ channel = info->line - card->first_line;
+ if (!IS_CYC_Z(*card)) {
+@@ -3506,10 +3537,12 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
+ ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0);
+ } else {
+ result = 0;
++ unlock_kernel();
+ return -ENODEV;
+ }
+
+ }
++ unlock_kernel();
+ return result;
+ } /* cy_tiomget */
+
+@@ -3528,7 +3561,7 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
+ struct CH_CTRL __iomem *ch_ctrl;
+ int retval;
+
+- if (serial_paranoia_check(info, tty->name, __FUNCTION__))
++ if (serial_paranoia_check(info, tty->name, __func__))
+ return -ENODEV;
+
+ card = info->card;
+@@ -3727,8 +3760,8 @@ static void cy_break(struct tty_struct *tty, int break_state)
+ spin_unlock_irqrestore(&card->card_lock, flags);
+ } /* cy_break */
+
+-static int
+-get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon)
++static int get_mon_info(struct cyclades_port *info,
++ struct cyclades_monitor __user *mon)
+ {
+
+ if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
+@@ -3767,8 +3800,8 @@ static int set_threshold(struct cyclades_port *info, unsigned long value)
+ return 0;
+ } /* set_threshold */
+
+-static int
+-get_threshold(struct cyclades_port *info, unsigned long __user * value)
++static int get_threshold(struct cyclades_port *info,
++ unsigned long __user *value)
+ {
+ struct cyclades_card *card;
+ void __iomem *base_addr;
+@@ -3789,15 +3822,15 @@ get_threshold(struct cyclades_port *info, unsigned long __user * value)
+ return 0;
+ } /* get_threshold */
+
+-static int
+-set_default_threshold(struct cyclades_port *info, unsigned long value)
++static int set_default_threshold(struct cyclades_port *info,
++ unsigned long value)
+ {
+ info->default_threshold = value & 0x0f;
+ return 0;
+ } /* set_default_threshold */
+
+-static int
+-get_default_threshold(struct cyclades_port *info, unsigned long __user * value)
++static int get_default_threshold(struct cyclades_port *info,
++ unsigned long __user *value)
+ {
+ return put_user(info->default_threshold, value);
+ } /* get_default_threshold */
+@@ -3824,7 +3857,8 @@ static int set_timeout(struct cyclades_port *info, unsigned long value)
+ return 0;
+ } /* set_timeout */
+
+-static int get_timeout(struct cyclades_port *info, unsigned long __user * value)
++static int get_timeout(struct cyclades_port *info,
++ unsigned long __user *value)
+ {
+ struct cyclades_card *card;
+ void __iomem *base_addr;
+@@ -3851,8 +3885,8 @@ static int set_default_timeout(struct cyclades_port *info, unsigned long value)
+ return 0;
+ } /* set_default_timeout */
+
+-static int
+-get_default_timeout(struct cyclades_port *info, unsigned long __user * value)
++static int get_default_timeout(struct cyclades_port *info,
++ unsigned long __user *value)
+ {
+ return put_user(info->default_timeout, value);
+ } /* get_default_timeout */
+@@ -3880,6 +3914,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
+ printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n",
+ info->line, cmd, arg);
+ #endif
++ lock_kernel();
+
+ switch (cmd) {
+ case CYGETMON:
+@@ -3936,7 +3971,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
+ break;
+ #endif /* CONFIG_CYZ_INTR */
+ case CYSETWAIT:
+- info->closing_wait = (unsigned short)arg *HZ / 100;
++ info->closing_wait = (unsigned short)arg * HZ / 100;
+ ret_val = 0;
+ break;
+ case CYGETWAIT:
+@@ -3988,47 +4023,47 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
+ p_cuser = argp;
+ ret_val = put_user(cnow.cts, &p_cuser->cts);
+ if (ret_val)
+- return ret_val;
++ break;
+ ret_val = put_user(cnow.dsr, &p_cuser->dsr);
+ if (ret_val)
+- return ret_val;
++ break;
+ ret_val = put_user(cnow.rng, &p_cuser->rng);
+ if (ret_val)
+- return ret_val;
++ break;
+ ret_val = put_user(cnow.dcd, &p_cuser->dcd);
+ if (ret_val)
+- return ret_val;
++ break;
+ ret_val = put_user(cnow.rx, &p_cuser->rx);
+ if (ret_val)
+- return ret_val;
++ break;
+ ret_val = put_user(cnow.tx, &p_cuser->tx);
+ if (ret_val)
+- return ret_val;
++ break;
+ ret_val = put_user(cnow.frame, &p_cuser->frame);
+ if (ret_val)
+- return ret_val;
++ break;
+ ret_val = put_user(cnow.overrun, &p_cuser->overrun);
+ if (ret_val)
+- return ret_val;
++ break;
+ ret_val = put_user(cnow.parity, &p_cuser->parity);
+ if (ret_val)
+- return ret_val;
++ break;
+ ret_val = put_user(cnow.brk, &p_cuser->brk);
+ if (ret_val)
+- return ret_val;
++ break;
+ ret_val = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
+ if (ret_val)
+- return ret_val;
++ break;
+ ret_val = 0;
+ break;
+ default:
+ ret_val = -ENOIOCTLCMD;
+ }
++ unlock_kernel();
+
+ #ifdef CY_DEBUG_OTHER
+ printk(KERN_DEBUG "cyc:cy_ioctl done\n");
+ #endif
+-
+ return ret_val;
+ } /* cy_ioctl */
+
+@@ -4113,9 +4148,8 @@ static void cy_throttle(struct tty_struct *tty)
+ tty->ldisc.chars_in_buffer(tty), info->line);
+ #endif
+
+- if (serial_paranoia_check(info, tty->name, "cy_throttle")) {
++ if (serial_paranoia_check(info, tty->name, "cy_throttle"))
+ return;
+- }
+
+ card = info->card;
+
+@@ -4169,12 +4203,11 @@ static void cy_unthrottle(struct tty_struct *tty)
+ char buf[64];
+
+ printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n",
+- tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty),info->line);
++ tty_name(tty, buf), tty_chars_in_buffer(tty), info->line);
+ #endif
+
+- if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) {
++ if (serial_paranoia_check(info, tty->name, "cy_unthrottle"))
+ return;
+- }
+
+ if (I_IXOFF(tty)) {
+ if (info->x_char)
+@@ -4269,47 +4302,14 @@ static void cy_start(struct tty_struct *tty)
+ base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
+
+ spin_lock_irqsave(&cinfo->card_lock, flags);
+- cy_writeb(base_addr + (CyCAR << index), (u_char) (channel & 0x0003)); /* index channel */
++ cy_writeb(base_addr + (CyCAR << index),
++ (u_char) (channel & 0x0003)); /* index channel */
+ cy_writeb(base_addr + (CySRER << index),
+ readb(base_addr + (CySRER << index)) | CyTxRdy);
+ spin_unlock_irqrestore(&cinfo->card_lock, flags);
+ }
+ } /* cy_start */
+
+-static void cy_flush_buffer(struct tty_struct *tty)
+-{
+- struct cyclades_port *info = tty->driver_data;
+- struct cyclades_card *card;
+- int channel, retval;
+- unsigned long flags;
+-
+-#ifdef CY_DEBUG_IO
+- printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line);
+-#endif
+-
+- if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
+- return;
+-
+- card = info->card;
+- channel = info->line - card->first_line;
+-
+- spin_lock_irqsave(&card->card_lock, flags);
+- info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+- spin_unlock_irqrestore(&card->card_lock, flags);
+-
+- if (IS_CYC_Z(*card)) { /* If it is a Z card, flush the on-board
+- buffers as well */
+- spin_lock_irqsave(&card->card_lock, flags);
+- retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
+- if (retval != 0) {
+- printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
+- "was %x\n", info->line, retval);
+- }
+- spin_unlock_irqrestore(&card->card_lock, flags);
+- }
+- tty_wakeup(tty);
+-} /* cy_flush_buffer */
+-
+ /*
+ * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+@@ -4406,10 +4406,11 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
+ info->cor3 = 0x08; /* _very_ small rcv threshold */
+
+ chip_number = (port - cinfo->first_line) / 4;
+- if ((info->chip_rev = readb(cinfo->base_addr +
+- (cy_chip_offset[chip_number] <<
+- index) + (CyGFRCR << index))) >=
+- CD1400_REV_J) {
++ info->chip_rev = readb(cinfo->base_addr +
++ (cy_chip_offset[chip_number] << index) +
++ (CyGFRCR << index));
++
++ if (info->chip_rev >= CD1400_REV_J) {
+ /* It is a CD1400 rev. J or later */
+ info->tbpr = baud_bpr_60[13]; /* Tx BPR */
+ info->tco = baud_co_60[13]; /* Tx CO */
+@@ -4454,7 +4455,8 @@ static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr,
+ /* Cy_ClrIntr is 0x1800 */
+ udelay(500L);
+
+- for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD; chip_number++) {
++ for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD;
++ chip_number++) {
+ base_addr =
+ true_base_addr + (cy_chip_offset[chip_number] << index);
+ mdelay(1);
+@@ -4555,12 +4557,11 @@ static int __init cy_detect_isa(void)
+ /* scan the address table probing for Cyclom-Y/ISA boards */
+ for (i = 0; i < NR_ISA_ADDRS; i++) {
+ unsigned int isa_address = cy_isa_addresses[i];
+- if (isa_address == 0x0000) {
++ if (isa_address == 0x0000)
+ return nboard;
+- }
+
+ /* probe for CD1400... */
+- cy_isa_address = ioremap(isa_address, CyISA_Ywin);
++ cy_isa_address = ioremap_nocache(isa_address, CyISA_Ywin);
+ if (cy_isa_address == NULL) {
+ printk(KERN_ERR "Cyclom-Y/ISA: can't remap base "
+ "address\n");
+@@ -4847,12 +4848,10 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
+ if (mailbox != 0) {
+ /* set window to last 512K of RAM */
+ cy_writel(&ctl_addr->loc_addr_base, WIN_RAM + RAM_SIZE);
+- //sleep(1);
+ for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
+ cy_writeb(tmp, 255);
+ /* set window to beginning of RAM */
+ cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+- //sleep(1);
+ }
+
+ retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, base_addr, NULL);
+@@ -5382,7 +5381,8 @@ static void __exit cy_cleanup_module(void)
+ del_timer_sync(&cyz_timerlist);
+ #endif /* CONFIG_CYZ_INTR */
+
+- if ((e1 = tty_unregister_driver(cy_serial_driver)))
++ e1 = tty_unregister_driver(cy_serial_driver);
++ if (e1)
+ printk(KERN_ERR "failed to unregister Cyclades serial "
+ "driver(%d)\n", e1);
+
+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..213b3ca 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... */
+@@ -162,7 +160,7 @@ struct drm_device;
+ * \param arg arguments
+ */
+ #define DRM_ERROR(fmt, arg...) \
+- printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __FUNCTION__ , ##arg)
++ printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __func__ , ##arg)
+
+ /**
+ * Memory error output.
+@@ -172,7 +170,7 @@ struct drm_device;
+ * \param arg arguments
+ */
+ #define DRM_MEM_ERROR(area, fmt, arg...) \
+- printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __FUNCTION__, \
++ printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __func__, \
+ drm_mem_stats[area].name , ##arg)
+
+ #define DRM_INFO(fmt, arg...) printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg)
+@@ -189,7 +187,7 @@ struct drm_device;
+ if ( drm_debug ) \
+ printk(KERN_DEBUG \
+ "[" DRM_NAME ":%s] " fmt , \
+- __FUNCTION__ , ##arg); \
++ __func__ , ##arg); \
+ } while (0)
+ #else
+ #define DRM_DEBUG(fmt, arg...) do { } while (0)
+@@ -240,7 +238,7 @@ do { \
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \
+ dev->lock.file_priv != file_priv ) { \
+ DRM_ERROR( "%s called without lock held, held %d owner %p %p\n",\
+- __FUNCTION__, _DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ),\
++ __func__, _DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ),\
+ dev->lock.file_priv, file_priv ); \
+ return -EINVAL; \
+ } \
+@@ -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..9a32169 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,9 +31,10 @@
+ */
+ 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__);
++ printk(KERN_ERR "%s\n", __func__);
+
+ if (drm_dev->driver->suspend)
+ return drm_dev->driver->suspend(drm_dev, state);
+@@ -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..a86ab30 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;
+@@ -692,7 +692,7 @@ static void i830EmitState(struct drm_device * dev)
+ drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
+
+- DRM_DEBUG("%s %x\n", __FUNCTION__, dirty);
++ DRM_DEBUG("%s %x\n", __func__, dirty);
+
+ if (dirty & I830_UPLOAD_BUFFERS) {
+ i830EmitDestVerified(dev, sarea_priv->BufferState);
+@@ -1043,7 +1043,7 @@ static void i830_dma_dispatch_flip(struct drm_device * dev)
+ RING_LOCALS;
+
+ DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+- __FUNCTION__,
++ __func__,
+ dev_priv->current_page,
+ dev_priv->sarea_priv->pf_current_page);
+
+@@ -1206,7 +1206,7 @@ static void i830_dma_quiescent(struct drm_device * dev)
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+
+- i830_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
++ i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
+ }
+
+ static int i830_flush_queue(struct drm_device * dev)
+@@ -1223,7 +1223,7 @@ static int i830_flush_queue(struct drm_device * dev)
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+
+- i830_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
++ i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
+
+ for (i = 0; i < dma->buf_count; i++) {
+ struct drm_buf *buf = dma->buflist[i];
+@@ -1344,7 +1344,7 @@ static void i830_do_init_pageflip(struct drm_device * dev)
+ {
+ drm_i830_private_t *dev_priv = dev->dev_private;
+
+- DRM_DEBUG("%s\n", __FUNCTION__);
++ DRM_DEBUG("%s\n", __func__);
+ dev_priv->page_flipping = 1;
+ dev_priv->current_page = 0;
+ dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+@@ -1354,7 +1354,7 @@ static int i830_do_cleanup_pageflip(struct drm_device * dev)
+ {
+ drm_i830_private_t *dev_priv = dev->dev_private;
+
+- DRM_DEBUG("%s\n", __FUNCTION__);
++ DRM_DEBUG("%s\n", __func__);
+ if (dev_priv->current_page != 0)
+ i830_dma_dispatch_flip(dev);
+
+@@ -1367,7 +1367,7 @@ static int i830_flip_bufs(struct drm_device *dev, void *data,
+ {
+ drm_i830_private_t *dev_priv = dev->dev_private;
+
+- DRM_DEBUG("%s\n", __FUNCTION__);
++ DRM_DEBUG("%s\n", __func__);
+
+ LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+@@ -1437,7 +1437,7 @@ static int i830_getparam(struct drm_device *dev, void *data,
+ int value;
+
+ if (!dev_priv) {
+- DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
++ DRM_ERROR("%s called with no initialization\n", __func__);
+ return -EINVAL;
+ }
+
+@@ -1464,7 +1464,7 @@ static int i830_setparam(struct drm_device *dev, void *data,
+ drm_i830_setparam_t *param = data;
+
+ if (!dev_priv) {
+- DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
++ DRM_ERROR("%s called with no initialization\n", __func__);
+ return -EINVAL;
+ }
+
+diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
+index 4caba8c..b5bf8cc 100644
+--- a/drivers/char/drm/i830_drv.h
++++ b/drivers/char/drm/i830_drv.h
+@@ -158,7 +158,7 @@ extern int i830_driver_device_is_agp(struct drm_device * dev);
+ if (I830_VERBOSE) \
+ printk("BEGIN_LP_RING(%d)\n", (n)); \
+ if (dev_priv->ring.space < n*4) \
+- i830_wait_ring(dev, n*4, __FUNCTION__); \
++ i830_wait_ring(dev, n*4, __func__); \
+ outcount = 0; \
+ outring = dev_priv->ring.tail; \
+ ringmask = dev_priv->ring.tail_mask; \
+diff --git a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c
+index a33db5f..91ec2bb 100644
+--- a/drivers/char/drm/i830_irq.c
++++ b/drivers/char/drm/i830_irq.c
+@@ -58,7 +58,7 @@ static int i830_emit_irq(struct drm_device * dev)
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+
+- DRM_DEBUG("%s\n", __FUNCTION__);
++ DRM_DEBUG("%s\n", __func__);
+
+ atomic_inc(&dev_priv->irq_emitted);
+
+@@ -77,7 +77,7 @@ static int i830_wait_irq(struct drm_device * dev, int irq_nr)
+ unsigned long end = jiffies + HZ * 3;
+ int ret = 0;
+
+- DRM_DEBUG("%s\n", __FUNCTION__);
++ DRM_DEBUG("%s\n", __func__);
+
+ if (atomic_read(&dev_priv->irq_received) >= irq_nr)
+ return 0;
+@@ -124,7 +124,7 @@ int i830_irq_emit(struct drm_device *dev, void *data,
+ LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+ if (!dev_priv) {
+- DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
++ DRM_ERROR("%s called with no initialization\n", __func__);
+ return -EINVAL;
+ }
+
+@@ -147,7 +147,7 @@ int i830_irq_wait(struct drm_device *dev, void *data,
+ drm_i830_irq_wait_t *irqwait = data;
+
+ if (!dev_priv) {
+- DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
++ DRM_ERROR("%s called with no initialization\n", __func__);
+ return -EINVAL;
+ }
+
+diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
+index a043bb1..f47e46e 100644
+--- a/drivers/char/drm/i915_dma.c
++++ b/drivers/char/drm/i915_dma.c
+@@ -194,7 +194,7 @@ static int i915_dma_resume(struct drm_device * dev)
+ {
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+- DRM_DEBUG("%s\n", __FUNCTION__);
++ DRM_DEBUG("%s\n", __func__);
+
+ if (!dev_priv->sarea) {
+ DRM_ERROR("can not find sarea!\n");
+@@ -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)
+@@ -564,7 +609,7 @@ static int i915_quiescent(struct drm_device * dev)
+ drm_i915_private_t *dev_priv = dev->dev_private;
+
+ i915_kernel_lost_context(dev);
+- return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
++ return i915_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
+ }
+
+ static int i915_flush_ioctl(struct drm_device *dev, void *data,
+@@ -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..db7001f 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,
+@@ -263,7 +272,7 @@ extern void i915_mem_release(struct drm_device * dev,
+ if (I915_VERBOSE) \
+ DRM_DEBUG("BEGIN_LP_RING(%d)\n", (n)); \
+ if (dev_priv->ring.space < (n)*4) \
+- i915_wait_ring(dev, (n)*4, __FUNCTION__); \
++ i915_wait_ring(dev, (n)*4, __func__); \
+ outcount = 0; \
+ outring = dev_priv->ring.tail; \
+ ringmask = dev_priv->ring.tail_mask; \
+@@ -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_cce.c b/drivers/char/drm/r128_cce.c
+index f36adbd..c31afbd 100644
+--- a/drivers/char/drm/r128_cce.c
++++ b/drivers/char/drm/r128_cce.c
+@@ -817,7 +817,7 @@ static struct drm_buf *r128_freelist_get(struct drm_device * dev)
+ for (i = 0; i < dma->buf_count; i++) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+- if (buf->file_priv == 0)
++ if (!buf->file_priv)
+ return buf;
+ }
+
+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_cp.c b/drivers/char/drm/radeon_cp.c
+index 9072e4a..f6f6c92 100644
+--- a/drivers/char/drm/radeon_cp.c
++++ b/drivers/char/drm/radeon_cp.c
+@@ -894,7 +894,7 @@ static u32 RADEON_READ_IGPGART(drm_radeon_private_t *dev_priv, int addr)
+ #if RADEON_FIFO_DEBUG
+ static void radeon_status(drm_radeon_private_t * dev_priv)
+ {
+- printk("%s:\n", __FUNCTION__);
++ printk("%s:\n", __func__);
+ printk("RBBM_STATUS = 0x%08x\n",
+ (unsigned int)RADEON_READ(RADEON_RBBM_STATUS));
+ printk("CP_RB_RTPR = 0x%08x\n",
+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/ds1286.c b/drivers/char/ds1286.c
+index 59146e3..ea35ab2 100644
+--- a/drivers/char/ds1286.c
++++ b/drivers/char/ds1286.c
+@@ -39,6 +39,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/bcd.h>
+ #include <linux/proc_fs.h>
++#include <linux/jiffies.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+@@ -451,7 +452,7 @@ static void ds1286_get_time(struct rtc_time *rtc_tm)
+ */
+
+ if (ds1286_is_updating() != 0)
+- while (jiffies - uip_watchdog < 2*HZ/100)
++ while (time_before(jiffies, uip_watchdog + 2*HZ/100))
+ barrier();
+
+ /*
+diff --git a/drivers/char/epca.c b/drivers/char/epca.c
+index ffd747c..60a4df7 100644
+--- a/drivers/char/epca.c
++++ b/drivers/char/epca.c
+@@ -38,8 +38,8 @@
+ #include <linux/slab.h>
+ #include <linux/ioport.h>
+ #include <linux/interrupt.h>
+-#include <asm/uaccess.h>
+-#include <asm/io.h>
++#include <linux/uaccess.h>
++#include <linux/io.h>
+ #include <linux/spinlock.h>
+ #include <linux/pci.h>
+ #include "digiPCI.h"
+@@ -73,7 +73,8 @@ static int invalid_lilo_config;
+ */
+ static DEFINE_SPINLOCK(epca_lock);
+
+-/* MAXBOARDS is typically 12, but ISA and EISA cards are restricted to 7 below. */
++/* MAXBOARDS is typically 12, but ISA and EISA cards are restricted
++ to 7 below. */
+ static struct board_info boards[MAXBOARDS];
+
+ static struct tty_driver *pc_driver;
+@@ -157,13 +158,12 @@ static void epca_error(int, char *);
+ static void pc_close(struct tty_struct *, struct file *);
+ static void shutdown(struct channel *);
+ static void pc_hangup(struct tty_struct *);
+-static void pc_put_char(struct tty_struct *, unsigned char);
+ static int pc_write_room(struct tty_struct *);
+ static int pc_chars_in_buffer(struct tty_struct *);
+ static void pc_flush_buffer(struct tty_struct *);
+ static void pc_flush_chars(struct tty_struct *);
+ static int block_til_ready(struct tty_struct *, struct file *,
+- struct channel *);
++ struct channel *);
+ static int pc_open(struct tty_struct *, struct file *);
+ static void post_fep_init(unsigned int crd);
+ static void epcapoll(unsigned long);
+@@ -175,18 +175,18 @@ static unsigned termios2digi_c(struct channel *ch, unsigned);
+ static void epcaparam(struct tty_struct *, struct channel *);
+ static void receive_data(struct channel *);
+ static int pc_ioctl(struct tty_struct *, struct file *,
+- unsigned int, unsigned long);
++ unsigned int, unsigned long);
+ static int info_ioctl(struct tty_struct *, struct file *,
+- unsigned int, unsigned long);
++ unsigned int, unsigned long);
+ static void pc_set_termios(struct tty_struct *, struct ktermios *);
+ static void do_softint(struct work_struct *work);
+ static void pc_stop(struct tty_struct *);
+ static void pc_start(struct tty_struct *);
+-static void pc_throttle(struct tty_struct * tty);
++static void pc_throttle(struct tty_struct *tty);
+ static void pc_unthrottle(struct tty_struct *tty);
+ static void digi_send_break(struct channel *ch, int msec);
+ static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
+-void epca_setup(char *, int *);
++static void epca_setup(char *, int *);
+
+ static int pc_write(struct tty_struct *, const unsigned char *, int);
+ static int pc_init(void);
+@@ -243,7 +243,7 @@ static void assertmemoff(struct channel *ch)
+ /* PCXEM windowing is the same as that used in the PCXR and CX series cards. */
+ static void pcxem_memwinon(struct board_info *b, unsigned int win)
+ {
+- outb_p(FEPWIN|win, b->port + 1);
++ outb_p(FEPWIN | win, b->port + 1);
+ }
+
+ static void pcxem_memwinoff(struct board_info *b, unsigned int win)
+@@ -253,7 +253,7 @@ static void pcxem_memwinoff(struct board_info *b, unsigned int win)
+
+ static void pcxem_globalwinon(struct channel *ch)
+ {
+- outb_p( FEPWIN, (int)ch->board->port + 1);
++ outb_p(FEPWIN, (int)ch->board->port + 1);
+ }
+
+ static void pcxem_rxwinon(struct channel *ch)
+@@ -394,7 +394,7 @@ static struct channel *verifyChannel(struct tty_struct *tty)
+ */
+ if (tty) {
+ struct channel *ch = (struct channel *)tty->driver_data;
+- if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs])) {
++ if (ch >= &digi_channels[0] && ch < &digi_channels[nbdevs]) {
+ if (ch->magic == EPCA_MAGIC)
+ return ch;
+ }
+@@ -414,7 +414,7 @@ static void pc_sched_event(struct channel *ch, int event)
+
+ static void epca_error(int line, char *msg)
+ {
+- printk(KERN_ERR "epca_error (Digi): line = %d %s\n",line,msg);
++ printk(KERN_ERR "epca_error (Digi): line = %d %s\n", line, msg);
+ }
+
+ static void pc_close(struct tty_struct *tty, struct file *filp)
+@@ -425,7 +425,8 @@ static void pc_close(struct tty_struct *tty, struct file *filp)
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+- if ((ch = verifyChannel(tty)) != NULL) {
++ ch = verifyChannel(tty);
++ if (ch != NULL) {
+ spin_lock_irqsave(&epca_lock, flags);
+ if (tty_hung_up_p(filp)) {
+ spin_unlock_irqrestore(&epca_lock, flags);
+@@ -440,7 +441,6 @@ static void pc_close(struct tty_struct *tty, struct file *filp)
+ spin_unlock_irqrestore(&epca_lock, flags);
+ return;
+ }
+-
+ /* Port open only once go ahead with shutdown & reset */
+ BUG_ON(ch->count < 0);
+
+@@ -455,12 +455,13 @@ static void pc_close(struct tty_struct *tty, struct file *filp)
+ spin_unlock_irqrestore(&epca_lock, flags);
+
+ if (ch->asyncflags & ASYNC_INITIALIZED) {
+- /* Setup an event to indicate when the transmit buffer empties */
++ /* Setup an event to indicate when the
++ transmit buffer empties */
+ setup_empty_event(tty, ch);
+- tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
++ /* 30 seconds timeout */
++ tty_wait_until_sent(tty, 3000);
+ }
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ pc_flush_buffer(tty);
+
+ tty_ldisc_flush(tty);
+ shutdown(ch);
+@@ -477,7 +478,7 @@ static void pc_close(struct tty_struct *tty, struct file *filp)
+ wake_up_interruptible(&ch->open_wait);
+ }
+ ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED |
+- ASYNC_CLOSING);
++ ASYNC_CLOSING);
+ wake_up_interruptible(&ch->close_wait);
+ }
+ }
+@@ -524,16 +525,15 @@ static void shutdown(struct channel *ch)
+ static void pc_hangup(struct tty_struct *tty)
+ {
+ struct channel *ch;
+-
+ /*
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+- if ((ch = verifyChannel(tty)) != NULL) {
++ ch = verifyChannel(tty);
++ if (ch != NULL) {
+ unsigned long flags;
+
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ pc_flush_buffer(tty);
+ tty_ldisc_flush(tty);
+ shutdown(ch);
+
+@@ -548,7 +548,7 @@ static void pc_hangup(struct tty_struct *tty)
+ }
+
+ static int pc_write(struct tty_struct *tty,
+- const unsigned char *buf, int bytesAvailable)
++ const unsigned char *buf, int bytesAvailable)
+ {
+ unsigned int head, tail;
+ int dataLen;
+@@ -572,7 +572,8 @@ static int pc_write(struct tty_struct *tty,
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+- if ((ch = verifyChannel(tty)) == NULL)
++ ch = verifyChannel(tty);
++ if (ch == NULL)
+ return 0;
+
+ /* Make a pointer to the channel data structure found on the board. */
+@@ -645,26 +646,19 @@ static int pc_write(struct tty_struct *tty,
+ return amountCopied;
+ }
+
+-static void pc_put_char(struct tty_struct *tty, unsigned char c)
+-{
+- pc_write(tty, &c, 1);
+-}
+-
+ static int pc_write_room(struct tty_struct *tty)
+ {
+- int remain;
++ int remain = 0;
+ struct channel *ch;
+ unsigned long flags;
+ unsigned int head, tail;
+ struct board_chan __iomem *bc;
+-
+- remain = 0;
+-
+ /*
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+- if ((ch = verifyChannel(tty)) != NULL) {
++ ch = verifyChannel(tty);
++ if (ch != NULL) {
+ spin_lock_irqsave(&epca_lock, flags);
+ globalwinon(ch);
+
+@@ -676,8 +670,8 @@ static int pc_write_room(struct tty_struct *tty)
+ tail = readw(&bc->tout);
+ /* Wrap tail if necessary */
+ tail &= (ch->txbufsize - 1);
+-
+- if ((remain = tail - head - 1) < 0 )
++ remain = tail - head - 1;
++ if (remain < 0)
+ remain += ch->txbufsize;
+
+ if (remain && (ch->statusflags & LOWWAIT) == 0) {
+@@ -699,12 +693,12 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
+ unsigned long flags;
+ struct channel *ch;
+ struct board_chan __iomem *bc;
+-
+ /*
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+- if ((ch = verifyChannel(tty)) == NULL)
++ ch = verifyChannel(tty);
++ if (ch == NULL)
+ return 0;
+
+ spin_lock_irqsave(&epca_lock, flags);
+@@ -715,7 +709,8 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
+ head = readw(&bc->tin);
+ ctail = readw(&ch->mailbox->cout);
+
+- if (tail == head && readw(&ch->mailbox->cin) == ctail && readb(&bc->tbusy) == 0)
++ if (tail == head && readw(&ch->mailbox->cin) == ctail &&
++ readb(&bc->tbusy) == 0)
+ chars = 0;
+ else { /* Begin if some space on the card has been used */
+ head = readw(&bc->tin) & (ch->txbufsize - 1);
+@@ -725,7 +720,8 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
+ * pc_write_room here we are finding the amount of bytes in the
+ * buffer filled. Not the amount of bytes empty.
+ */
+- if ((remain = tail - head - 1) < 0 )
++ remain = tail - head - 1;
++ if (remain < 0)
+ remain += ch->txbufsize;
+ chars = (int)(ch->txbufsize - remain);
+ /*
+@@ -736,7 +732,7 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
+ * transmit buffer empties.
+ */
+ if (!(ch->statusflags & EMPTYWAIT))
+- setup_empty_event(tty,ch);
++ setup_empty_event(tty, ch);
+ } /* End if some space on the card has been used */
+ memoff(ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
+@@ -754,7 +750,8 @@ static void pc_flush_buffer(struct tty_struct *tty)
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+- if ((ch = verifyChannel(tty)) == NULL)
++ ch = verifyChannel(tty);
++ if (ch == NULL)
+ return;
+
+ spin_lock_irqsave(&epca_lock, flags);
+@@ -775,23 +772,25 @@ static void pc_flush_chars(struct tty_struct *tty)
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+- if ((ch = verifyChannel(tty)) != NULL) {
++ ch = verifyChannel(tty);
++ if (ch != NULL) {
+ unsigned long flags;
+ spin_lock_irqsave(&epca_lock, flags);
+ /*
+ * If not already set and the transmitter is busy setup an
+ * event to indicate when the transmit empties.
+ */
+- if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT))
+- setup_empty_event(tty,ch);
++ if ((ch->statusflags & TXBUSY) &&
++ !(ch->statusflags & EMPTYWAIT))
++ setup_empty_event(tty, ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
+ }
+ }
+
+ static int block_til_ready(struct tty_struct *tty,
+- struct file *filp, struct channel *ch)
++ struct file *filp, struct channel *ch)
+ {
+- DECLARE_WAITQUEUE(wait,current);
++ DECLARE_WAITQUEUE(wait, current);
+ int retval, do_clocal = 0;
+ unsigned long flags;
+
+@@ -839,8 +838,7 @@ static int block_til_ready(struct tty_struct *tty,
+ while (1) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (tty_hung_up_p(filp) ||
+- !(ch->asyncflags & ASYNC_INITIALIZED))
+- {
++ !(ch->asyncflags & ASYNC_INITIALIZED)) {
+ if (ch->asyncflags & ASYNC_HUP_NOTIFY)
+ retval = -EAGAIN;
+ else
+@@ -880,7 +878,7 @@ static int block_til_ready(struct tty_struct *tty,
+ return 0;
+ }
+
+-static int pc_open(struct tty_struct *tty, struct file * filp)
++static int pc_open(struct tty_struct *tty, struct file *filp)
+ {
+ struct channel *ch;
+ unsigned long flags;
+@@ -923,7 +921,8 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
+ return(-ENODEV);
+ }
+
+- if ((bc = ch->brdchan) == 0) {
++ bc = ch->brdchan;
++ if (bc == NULL) {
+ tty->driver_data = NULL;
+ return -ENODEV;
+ }
+@@ -964,7 +963,7 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
+ * The below routine generally sets up parity, baud, flow control
+ * issues, etc.... It effect both control flags and input flags.
+ */
+- epcaparam(tty,ch);
++ epcaparam(tty, ch);
+ ch->asyncflags |= ASYNC_INITIALIZED;
+ memoff(ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
+@@ -1002,8 +1001,8 @@ static void __exit epca_module_exit(void)
+
+ del_timer_sync(&epca_timer);
+
+- if (tty_unregister_driver(pc_driver) || tty_unregister_driver(pc_info))
+- {
++ if (tty_unregister_driver(pc_driver) ||
++ tty_unregister_driver(pc_info)) {
+ printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n");
+ return;
+ }
+@@ -1034,7 +1033,6 @@ static const struct tty_operations pc_ops = {
+ .flush_buffer = pc_flush_buffer,
+ .chars_in_buffer = pc_chars_in_buffer,
+ .flush_chars = pc_flush_chars,
+- .put_char = pc_put_char,
+ .ioctl = pc_ioctl,
+ .set_termios = pc_set_termios,
+ .stop = pc_stop,
+@@ -1044,7 +1042,7 @@ static const struct tty_operations pc_ops = {
+ .hangup = pc_hangup,
+ };
+
+-static int info_open(struct tty_struct *tty, struct file * filp)
++static int info_open(struct tty_struct *tty, struct file *filp)
+ {
+ return 0;
+ }
+@@ -1099,7 +1097,7 @@ static int __init pc_init(void)
+ * Set up interrupt, we will worry about memory allocation in
+ * post_fep_init.
+ */
+- printk(KERN_INFO "DIGI epca driver version %s loaded.\n",VERSION);
++ printk(KERN_INFO "DIGI epca driver version %s loaded.\n", VERSION);
+
+ /*
+ * NOTE : This code assumes that the number of ports found in the
+@@ -1252,7 +1250,7 @@ static int __init pc_init(void)
+ if ((board_id & 0x30) == 0x30)
+ bd->memory_seg = 0x8000;
+ } else
+- printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n",(int)bd->port);
++ printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n", (int)bd->port);
+ break;
+ }
+ }
+@@ -1326,12 +1324,12 @@ static void post_fep_init(unsigned int crd)
+ */
+ /* PCI cards are already remapped at this point ISA are not */
+ bd->numports = readw(bd->re_map_membase + XEMPORTS);
+- epcaassert(bd->numports <= 64,"PCI returned a invalid number of ports");
++ epcaassert(bd->numports <= 64, "PCI returned a invalid number of ports");
+ nbdevs += (bd->numports);
+ } else {
+ /* Fix up the mappings for ISA/EISA etc */
+ /* FIXME: 64K - can we be smarter ? */
+- bd->re_map_membase = ioremap(bd->membase, 0x10000);
++ bd->re_map_membase = ioremap_nocache(bd->membase, 0x10000);
+ }
+
+ if (crd != 0)
+@@ -1362,7 +1360,8 @@ static void post_fep_init(unsigned int crd)
+ * XEPORTS (address 0xc22) points at the number of channels the card
+ * supports. (For 64XE, XI, XEM, and XR use 0xc02)
+ */
+- if ((bd->type == PCXEVE || bd->type == PCXE) && (readw(memaddr + XEPORTS) < 3))
++ if ((bd->type == PCXEVE || bd->type == PCXE) &&
++ (readw(memaddr + XEPORTS) < 3))
+ shrinkmem = 1;
+ if (bd->type < PCIXEM)
+ if (!request_region((int)bd->port, 4, board_desc[bd->type]))
+@@ -1461,10 +1460,12 @@ static void post_fep_init(unsigned int crd)
+
+ case PCXEVE:
+ case PCXE:
+- ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) & 0x1fff);
++ ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4)
++ & 0x1fff);
+ ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9);
+- ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) & 0x1fff);
+- ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >>9 );
++ ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4)
++ & 0x1fff);
++ ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >> 9);
+ break;
+
+ case PCXI:
+@@ -1518,8 +1519,9 @@ static void post_fep_init(unsigned int crd)
+ }
+
+ printk(KERN_INFO
+- "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n",
+- VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports);
++ "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n",
++ VERSION, board_desc[bd->type], (long)bd->port,
++ (long)bd->membase, bd->numports);
+ memwinoff(bd, 0);
+ }
+
+@@ -1527,7 +1529,7 @@ static void epcapoll(unsigned long ignored)
+ {
+ unsigned long flags;
+ int crd;
+- volatile unsigned int head, tail;
++ unsigned int head, tail;
+ struct channel *ch;
+ struct board_info *bd;
+
+@@ -1593,7 +1595,9 @@ static void doevent(int crd)
+ chan0 = card_ptr[crd];
+ epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range");
+ assertgwinon(chan0);
+- while ((tail = readw(&chan0->mailbox->eout)) != (head = readw(&chan0->mailbox->ein))) { /* Begin while something in event queue */
++ while ((tail = readw(&chan0->mailbox->eout)) !=
++ (head = readw(&chan0->mailbox->ein))) {
++ /* Begin while something in event queue */
+ assertgwinon(chan0);
+ eventbuf = bd->re_map_membase + tail + ISTART;
+ /* Get the channel the event occurred on */
+@@ -1617,7 +1621,8 @@ static void doevent(int crd)
+ goto next;
+ }
+
+- if ((bc = ch->brdchan) == NULL)
++ bc = ch->brdchan;
++ if (bc == NULL)
+ goto next;
+
+ if (event & DATA_IND) { /* Begin DATA_IND */
+@@ -1629,10 +1634,11 @@ static void doevent(int crd)
+ /* A modem signal change has been indicated */
+ ch->imodem = mstat;
+ if (ch->asyncflags & ASYNC_CHECK_CD) {
+- if (mstat & ch->dcd) /* We are now receiving dcd */
++ /* We are now receiving dcd */
++ if (mstat & ch->dcd)
+ wake_up_interruptible(&ch->open_wait);
+- else
+- pc_sched_event(ch, EPCA_EVENT_HANGUP); /* No dcd; hangup */
++ else /* No dcd; hangup */
++ pc_sched_event(ch, EPCA_EVENT_HANGUP);
+ }
+ }
+ tty = ch->tty;
+@@ -1647,7 +1653,8 @@ static void doevent(int crd)
+ tty_wakeup(tty);
+ }
+ } else if (event & EMPTYTX_IND) {
+- /* This event is generated by setup_empty_event */
++ /* This event is generated by
++ setup_empty_event */
+ ch->statusflags &= ~TXBUSY;
+ if (ch->statusflags & EMPTYWAIT) {
+ ch->statusflags &= ~EMPTYWAIT;
+@@ -1655,7 +1662,7 @@ static void doevent(int crd)
+ }
+ }
+ }
+- next:
++next:
+ globalwinon(ch);
+ BUG_ON(!bc);
+ writew(1, &bc->idata);
+@@ -1665,7 +1672,7 @@ static void doevent(int crd)
+ }
+
+ static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
+- int byte2, int ncmds, int bytecmd)
++ int byte2, int ncmds, int bytecmd)
+ {
+ unchar __iomem *memaddr;
+ unsigned int head, cmdTail, cmdStart, cmdMax;
+@@ -1690,8 +1697,10 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
+ memaddr = ch->board->re_map_membase;
+
+ if (head >= (cmdMax - cmdStart) || (head & 03)) {
+- printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__, cmd, head);
+- printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__, cmdMax, cmdStart);
++ printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n",
++ __LINE__, cmd, head);
++ printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n",
++ __LINE__, cmdMax, cmdStart);
+ return;
+ }
+ if (bytecmd) {
+@@ -1770,7 +1779,7 @@ static unsigned termios2digi_h(struct channel *ch, unsigned cflag)
+ static unsigned termios2digi_i(struct channel *ch, unsigned iflag)
+ {
+ unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK |
+- INPCK | ISTRIP|IXON|IXANY|IXOFF);
++ INPCK | ISTRIP | IXON | IXANY | IXOFF);
+ if (ch->digiext.digi_flags & DIGI_AIXON)
+ res |= IAIXON;
+ return res;
+@@ -1838,7 +1847,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
+ unsigned mval, hflow, cflag, iflag;
+
+ bc = ch->brdchan;
+- epcaassert(bc !=0, "bc out of range");
++ epcaassert(bc != NULL, "bc out of range");
+
+ assertgwinon(ch);
+ ts = tty->termios;
+@@ -1884,8 +1893,10 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
+ * Command sets channels iflag structure on the board. Such
+ * things as input soft flow control, handling of parity
+ * errors, and break handling are all set here.
++ *
++ * break handling, parity handling, input stripping,
++ * flow control chars
+ */
+- /* break handling, parity handling, input stripping, flow control chars */
+ fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0);
+ }
+ /*
+@@ -1981,7 +1992,7 @@ static void receive_data(struct channel *ch)
+ return;
+
+ /* If CREAD bit is off or device not open, set TX tail to head */
+- if (!tty || !ts || !(ts->c_cflag & CREAD)) {
++ if (!tty || !ts || !(ts->c_cflag & CREAD)) {
+ writew(head, &bc->rout);
+ return;
+ }
+@@ -1991,18 +2002,21 @@ static void receive_data(struct channel *ch)
+
+ if (readb(&bc->orun)) {
+ writeb(0, &bc->orun);
+- printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",tty->name);
++ printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",
++ tty->name);
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ }
+ rxwinon(ch);
+- while (bytesAvailable > 0) { /* Begin while there is data on the card */
++ while (bytesAvailable > 0) {
++ /* Begin while there is data on the card */
+ wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail;
+ /*
+ * Even if head has wrapped around only report the amount of
+ * data to be equal to the size - tail. Remember memcpy can't
+ * automaticly wrap around the receive buffer.
+ */
+- dataToRead = (wrapgap < bytesAvailable) ? wrapgap : bytesAvailable;
++ dataToRead = (wrapgap < bytesAvailable) ? wrapgap
++ : bytesAvailable;
+ /* Make sure we don't overflow the buffer */
+ dataToRead = tty_prepare_flip_string(tty, &rptr, dataToRead);
+ if (dataToRead == 0)
+@@ -2153,14 +2167,14 @@ static int pc_tiocmset(struct tty_struct *tty, struct file *file,
+ * The below routine generally sets up parity, baud, flow control
+ * issues, etc.... It effect both control flags and input flags.
+ */
+- epcaparam(tty,ch);
++ epcaparam(tty, ch);
+ memoff(ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
+ return 0;
+ }
+
+-static int pc_ioctl(struct tty_struct *tty, struct file * file,
+- unsigned int cmd, unsigned long arg)
++static int pc_ioctl(struct tty_struct *tty, struct file *file,
++ unsigned int cmd, unsigned long arg)
+ {
+ digiflow_t dflow;
+ int retval;
+@@ -2175,7 +2189,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
+ bc = ch->brdchan;
+ else
+ return -EINVAL;
+-
+ /*
+ * For POSIX compliance we need to add more ioctls. See tty_ioctl.c in
+ * /usr/src/linux/drivers/char for a good example. In particular think
+@@ -2186,9 +2199,10 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+- /* Setup an event to indicate when the transmit buffer empties */
++ /* Setup an event to indicate when the transmit
++ buffer empties */
+ spin_lock_irqsave(&epca_lock, flags);
+- setup_empty_event(tty,ch);
++ setup_empty_event(tty, ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
+ tty_wait_until_sent(tty, 0);
+ if (!arg)
+@@ -2198,29 +2212,14 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+-
+- /* Setup an event to indicate when the transmit buffer empties */
++ /* Setup an event to indicate when the transmit buffer
++ empties */
+ spin_lock_irqsave(&epca_lock, flags);
+- setup_empty_event(tty,ch);
++ setup_empty_event(tty, ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
+ tty_wait_until_sent(tty, 0);
+ digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4);
+ return 0;
+- case TIOCGSOFTCAR:
+- if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)arg))
+- return -EFAULT;
+- return 0;
+- case TIOCSSOFTCAR:
+- {
+- unsigned int value;
+-
+- if (get_user(value, (unsigned __user *)argp))
+- return -EFAULT;
+- tty->termios->c_cflag =
+- ((tty->termios->c_cflag & ~CLOCAL) |
+- (value ? CLOCAL : 0));
+- return 0;
+- }
+ case TIOCMODG:
+ mflag = pc_tiocmget(tty, file);
+ if (put_user(mflag, (unsigned long __user *)argp))
+@@ -2253,10 +2252,12 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
+ break;
+ case DIGI_SETAW:
+ case DIGI_SETAF:
++ lock_kernel();
+ if (cmd == DIGI_SETAW) {
+- /* Setup an event to indicate when the transmit buffer empties */
++ /* Setup an event to indicate when the transmit
++ buffer empties */
+ spin_lock_irqsave(&epca_lock, flags);
+- setup_empty_event(tty,ch);
++ setup_empty_event(tty, ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
+ tty_wait_until_sent(tty, 0);
+ } else {
+@@ -2264,6 +2265,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
+ if (tty->ldisc.flush_buffer)
+ tty->ldisc.flush_buffer(tty);
+ }
++ unlock_kernel();
+ /* Fall Thru */
+ case DIGI_SETA:
+ if (copy_from_user(&ch->digiext, argp, sizeof(digi_t)))
+@@ -2285,7 +2287,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
+ * control issues, etc.... It effect both control flags and
+ * input flags.
+ */
+- epcaparam(tty,ch);
++ epcaparam(tty, ch);
+ memoff(ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
+ break;
+@@ -2321,18 +2323,21 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
+ if (copy_from_user(&dflow, argp, sizeof(dflow)))
+ return -EFAULT;
+
+- if (dflow.startc != startc || dflow.stopc != stopc) { /* Begin if setflow toggled */
++ if (dflow.startc != startc || dflow.stopc != stopc) {
++ /* Begin if setflow toggled */
+ spin_lock_irqsave(&epca_lock, flags);
+ globalwinon(ch);
+
+ if (cmd == DIGI_SETFLOW) {
+ ch->fepstartc = ch->startc = dflow.startc;
+ ch->fepstopc = ch->stopc = dflow.stopc;
+- fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
++ fepcmd(ch, SONOFFC, ch->fepstartc,
++ ch->fepstopc, 0, 1);
+ } else {
+ ch->fepstartca = ch->startca = dflow.startc;
+ ch->fepstopca = ch->stopca = dflow.stopc;
+- fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
++ fepcmd(ch, SAUXONOFFC, ch->fepstartca,
++ ch->fepstopca, 0, 1);
+ }
+
+ if (ch->statusflags & TXSTOPPED)
+@@ -2356,7 +2361,9 @@ static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+- if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */
++ ch = verifyChannel(tty);
++
++ if (ch != NULL) { /* Begin if channel valid */
+ spin_lock_irqsave(&epca_lock, flags);
+ globalwinon(ch);
+ epcaparam(tty, ch);
+@@ -2383,7 +2390,7 @@ static void do_softint(struct work_struct *work)
+
+ if (tty && tty->driver_data) {
+ if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) {
+- tty_hangup(tty); /* FIXME: module removal race here - AKPM */
++ tty_hangup(tty);
+ wake_up_interruptible(&ch->open_wait);
+ ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
+ }
+@@ -2403,9 +2410,11 @@ static void pc_stop(struct tty_struct *tty)
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+- if ((ch = verifyChannel(tty)) != NULL) {
++ ch = verifyChannel(tty);
++ if (ch != NULL) {
+ spin_lock_irqsave(&epca_lock, flags);
+- if ((ch->statusflags & TXSTOPPED) == 0) { /* Begin if transmit stop requested */
++ if ((ch->statusflags & TXSTOPPED) == 0) {
++ /* Begin if transmit stop requested */
+ globalwinon(ch);
+ /* STOP transmitting now !! */
+ fepcmd(ch, PAUSETX, 0, 0, 0, 0);
+@@ -2423,11 +2432,14 @@ static void pc_start(struct tty_struct *tty)
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+- if ((ch = verifyChannel(tty)) != NULL) {
++ ch = verifyChannel(tty);
++ if (ch != NULL) {
+ unsigned long flags;
+ spin_lock_irqsave(&epca_lock, flags);
+- /* Just in case output was resumed because of a change in Digi-flow */
+- if (ch->statusflags & TXSTOPPED) { /* Begin transmit resume requested */
++ /* Just in case output was resumed because of a change
++ in Digi-flow */
++ if (ch->statusflags & TXSTOPPED) {
++ /* Begin transmit resume requested */
+ struct board_chan __iomem *bc;
+ globalwinon(ch);
+ bc = ch->brdchan;
+@@ -2457,7 +2469,8 @@ static void pc_throttle(struct tty_struct *tty)
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+- if ((ch = verifyChannel(tty)) != NULL) {
++ ch = verifyChannel(tty);
++ if (ch != NULL) {
+ spin_lock_irqsave(&epca_lock, flags);
+ if ((ch->statusflags & RXSTOPPED) == 0) {
+ globalwinon(ch);
+@@ -2477,8 +2490,10 @@ static void pc_unthrottle(struct tty_struct *tty)
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+- if ((ch = verifyChannel(tty)) != NULL) {
+- /* Just in case output was resumed because of a change in Digi-flow */
++ ch = verifyChannel(tty);
++ if (ch != NULL) {
++ /* Just in case output was resumed because of a change
++ in Digi-flow */
+ spin_lock_irqsave(&epca_lock, flags);
+ if (ch->statusflags & RXSTOPPED) {
+ globalwinon(ch);
+@@ -2490,7 +2505,7 @@ static void pc_unthrottle(struct tty_struct *tty)
+ }
+ }
+
+-void digi_send_break(struct channel *ch, int msec)
++static void digi_send_break(struct channel *ch, int msec)
+ {
+ unsigned long flags;
+
+@@ -2523,7 +2538,7 @@ static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
+ memoff(ch);
+ }
+
+-void epca_setup(char *str, int *ints)
++static void epca_setup(char *str, int *ints)
+ {
+ struct board_info board;
+ int index, loop, last;
+@@ -2552,14 +2567,16 @@ void epca_setup(char *str, int *ints)
+ * instructing the driver to ignore epcaconfig.) For
+ * this reason we check for 2.
+ */
+- if (board.status == 2) { /* Begin ignore epcaconfig as well as lilo cmd line */
++ if (board.status == 2) {
++ /* Begin ignore epcaconfig as well as lilo cmd line */
+ nbdevs = 0;
+ num_cards = 0;
+ return;
+ } /* End ignore epcaconfig as well as lilo cmd line */
+
+ if (board.status > 2) {
+- printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n", board.status);
++ printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n",
++ board.status);
+ invalid_lilo_config = 1;
+ setup_error_code |= INVALID_BOARD_STATUS;
+ return;
+@@ -2613,7 +2630,8 @@ void epca_setup(char *str, int *ints)
+ case 6:
+ board.membase = ints[index];
+ if (ints[index] <= 0) {
+- printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase);
++ printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",
++ (unsigned int)board.membase);
+ invalid_lilo_config = 1;
+ setup_error_code |= INVALID_MEM_BASE;
+ return;
+@@ -2744,7 +2762,7 @@ void epca_setup(char *str, int *ints)
+ t2++;
+
+ if (*t2) {
+- printk(KERN_ERR "epca_setup: Invalid memory base %s\n",str);
++ printk(KERN_ERR "epca_setup: Invalid memory base %s\n", str);
+ invalid_lilo_config = 1;
+ setup_error_code |= INVALID_MEM_BASE;
+ return;
+@@ -2766,7 +2784,7 @@ void epca_setup(char *str, int *ints)
+
+ /* I should REALLY validate the stuff here */
+ /* Copies our local copy of board into boards */
+- memcpy((void *)&boards[num_cards],(void *)&board, sizeof(board));
++ memcpy((void *)&boards[num_cards], (void *)&board, sizeof(board));
+ /* Does this get called once per lilo arg are what ? */
+ printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n",
+ num_cards, board_desc[board.type],
+@@ -2807,9 +2825,9 @@ static int __devinit epca_init_one(struct pci_dev *pdev,
+ if (board_idx >= MAXBOARDS)
+ goto err_out;
+
+- addr = pci_resource_start (pdev, epca_info_tbl[info_idx].bar_idx);
++ addr = pci_resource_start(pdev, epca_info_tbl[info_idx].bar_idx);
+ if (!addr) {
+- printk (KERN_ERR PFX "PCI region #%d not available (size 0)\n",
++ printk(KERN_ERR PFX "PCI region #%d not available (size 0)\n",
+ epca_info_tbl[info_idx].bar_idx);
+ goto err_out;
+ }
+@@ -2820,28 +2838,29 @@ static int __devinit epca_init_one(struct pci_dev *pdev,
+ boards[board_idx].port = addr + PCI_IO_OFFSET;
+ boards[board_idx].membase = addr;
+
+- if (!request_mem_region (addr + PCI_IO_OFFSET, 0x200000, "epca")) {
+- printk (KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
++ if (!request_mem_region(addr + PCI_IO_OFFSET, 0x200000, "epca")) {
++ printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
+ 0x200000, addr + PCI_IO_OFFSET);
+ goto err_out;
+ }
+
+- boards[board_idx].re_map_port = ioremap(addr + PCI_IO_OFFSET, 0x200000);
++ boards[board_idx].re_map_port = ioremap_nocache(addr + PCI_IO_OFFSET,
++ 0x200000);
+ if (!boards[board_idx].re_map_port) {
+- printk (KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
++ printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
+ 0x200000, addr + PCI_IO_OFFSET);
+ goto err_out_free_pciio;
+ }
+
+- if (!request_mem_region (addr, 0x200000, "epca")) {
+- printk (KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
++ if (!request_mem_region(addr, 0x200000, "epca")) {
++ printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
+ 0x200000, addr);
+ goto err_out_free_iounmap;
+ }
+
+- boards[board_idx].re_map_membase = ioremap(addr, 0x200000);
++ boards[board_idx].re_map_membase = ioremap_nocache(addr, 0x200000);
+ if (!boards[board_idx].re_map_membase) {
+- printk (KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
++ printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
+ 0x200000, addr + PCI_IO_OFFSET);
+ goto err_out_free_memregion;
+ }
+@@ -2858,11 +2877,11 @@ static int __devinit epca_init_one(struct pci_dev *pdev,
+ return 0;
+
+ err_out_free_memregion:
+- release_mem_region (addr, 0x200000);
++ release_mem_region(addr, 0x200000);
+ err_out_free_iounmap:
+- iounmap (boards[board_idx].re_map_port);
++ iounmap(boards[board_idx].re_map_port);
+ err_out_free_pciio:
+- release_mem_region (addr + PCI_IO_OFFSET, 0x200000);
++ release_mem_region(addr + PCI_IO_OFFSET, 0x200000);
+ err_out:
+ return -ENODEV;
+ }
+@@ -2878,9 +2897,9 @@ static struct pci_device_id epca_pci_tbl[] = {
+
+ MODULE_DEVICE_TABLE(pci, epca_pci_tbl);
+
+-int __init init_PCI (void)
++static int __init init_PCI(void)
+ {
+- memset (&epca_driver, 0, sizeof (epca_driver));
++ memset(&epca_driver, 0, sizeof(epca_driver));
+ epca_driver.name = "epca";
+ epca_driver.id_table = epca_pci_tbl;
+ epca_driver.probe = epca_init_one;
+diff --git a/drivers/char/esp.c b/drivers/char/esp.c
+index f3fe620..84840ba 100644
+--- a/drivers/char/esp.c
++++ b/drivers/char/esp.c
+@@ -8,7 +8,7 @@
+ * Extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92. Now
+ * much more extensible to support other serial cards based on the
+ * 16450/16550A UART's. Added support for the AST FourPort and the
+- * Accent Async board.
++ * Accent Async board.
+ *
+ * set_serial_info fixed to set the flags, custom divisor, and uart
+ * type fields. Fix suggested by Michael K. Johnson 12/12/92.
+@@ -61,11 +61,11 @@
+ #include <linux/bitops.h>
+
+ #include <asm/system.h>
+-#include <asm/io.h>
++#include <linux/io.h>
+
+ #include <asm/dma.h>
+ #include <linux/slab.h>
+-#include <asm/uaccess.h>
++#include <linux/uaccess.h>
+
+ #include <linux/hayesesp.h>
+
+@@ -127,8 +127,10 @@ static struct tty_driver *esp_driver;
+ #undef SERIAL_DEBUG_FLOW
+
+ #if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
+-#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
+- tty->name, (info->flags), serial_driver.refcount,info->count,tty->count,s)
++#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
++ tty->name, info->flags, \
++ serial_driver.refcount, \
++ info->count, tty->count, s)
+ #else
+ #define DBG_CNT(s)
+ #endif
+@@ -189,7 +191,7 @@ static inline void serial_out(struct esp_struct *info, int offset,
+ */
+ static void rs_stop(struct tty_struct *tty)
+ {
+- struct esp_struct *info = (struct esp_struct *)tty->driver_data;
++ struct esp_struct *info = tty->driver_data;
+ unsigned long flags;
+
+ if (serial_paranoia_check(info, tty->name, "rs_stop"))
+@@ -206,12 +208,12 @@ static void rs_stop(struct tty_struct *tty)
+
+ static void rs_start(struct tty_struct *tty)
+ {
+- struct esp_struct *info = (struct esp_struct *)tty->driver_data;
++ struct esp_struct *info = tty->driver_data;
+ unsigned long flags;
+-
++
+ if (serial_paranoia_check(info, tty->name, "rs_start"))
+ return;
+-
++
+ spin_lock_irqsave(&info->lock, flags);
+ if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) {
+ info->IER |= UART_IER_THRI;
+@@ -233,7 +235,7 @@ static void rs_start(struct tty_struct *tty)
+ * rs_interrupt() should try to keep the interrupt handler as fast as
+ * possible. After you are done making modifications, it is not a bad
+ * idea to do:
+- *
++ *
+ * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
+ *
+ * and look at the resulting assemble code in serial.s.
+@@ -290,7 +292,7 @@ static inline void receive_chars_pio(struct esp_struct *info, int num_bytes)
+ }
+
+ status_mask = (info->read_status_mask >> 2) & 0x07;
+-
++
+ for (i = 0; i < num_bytes - 1; i += 2) {
+ *((unsigned short *)(pio_buf->data + i)) =
+ inw(info->port + UART_ESI_RX);
+@@ -325,8 +327,7 @@ static inline void receive_chars_pio(struct esp_struct *info, int num_bytes)
+ flag = TTY_BREAK;
+ if (info->flags & ASYNC_SAK)
+ do_SAK(tty);
+- }
+- else if (err_buf->data[i] & 0x02)
++ } else if (err_buf->data[i] & 0x02)
+ flag = TTY_FRAME;
+ else if (err_buf->data[i] & 0x01)
+ flag = TTY_PARITY;
+@@ -341,23 +342,29 @@ static inline void receive_chars_pio(struct esp_struct *info, int num_bytes)
+ release_pio_buffer(err_buf);
+ }
+
+-static inline void receive_chars_dma(struct esp_struct *info, int num_bytes)
++static void program_isa_dma(int dma, int dir, unsigned long addr, int len)
+ {
+ unsigned long flags;
++
++ flags = claim_dma_lock();
++ disable_dma(dma);
++ clear_dma_ff(dma);
++ set_dma_mode(dma, dir);
++ set_dma_addr(dma, addr);
++ set_dma_count(dma, len);
++ enable_dma(dma);
++ release_dma_lock(flags);
++}
++
++static void receive_chars_dma(struct esp_struct *info, int num_bytes)
++{
+ info->stat_flags &= ~ESP_STAT_RX_TIMEOUT;
+ dma_bytes = num_bytes;
+ info->stat_flags |= ESP_STAT_DMA_RX;
+-
+- flags=claim_dma_lock();
+- disable_dma(dma);
+- clear_dma_ff(dma);
+- set_dma_mode(dma, DMA_MODE_READ);
+- set_dma_addr(dma, isa_virt_to_bus(dma_buffer));
+- set_dma_count(dma, dma_bytes);
+- enable_dma(dma);
+- release_dma_lock(flags);
+-
+- serial_out(info, UART_ESI_CMD1, ESI_START_DMA_RX);
++
++ program_isa_dma(dma, DMA_MODE_READ, isa_virt_to_bus(dma_buffer),
++ dma_bytes);
++ serial_out(info, UART_ESI_CMD1, ESI_START_DMA_RX);
+ }
+
+ static inline void receive_chars_dma_done(struct esp_struct *info,
+@@ -366,22 +373,22 @@ static inline void receive_chars_dma_done(struct esp_struct *info,
+ struct tty_struct *tty = info->tty;
+ int num_bytes;
+ unsigned long flags;
+-
+- flags=claim_dma_lock();
++
++ flags = claim_dma_lock();
+ disable_dma(dma);
+ clear_dma_ff(dma);
+
+ info->stat_flags &= ~ESP_STAT_DMA_RX;
+ num_bytes = dma_bytes - get_dma_residue(dma);
+ release_dma_lock(flags);
+-
++
+ info->icount.rx += num_bytes;
+
+ if (num_bytes > 0) {
+ tty_insert_flip_string(tty, dma_buffer, num_bytes - 1);
+
+ status &= (0x1c & info->read_status_mask);
+-
++
+ /* Is the status significant or do we throw the last byte ? */
+ if (!(status & info->ignore_status_mask)) {
+ int statflag = 0;
+@@ -393,13 +400,13 @@ static inline void receive_chars_dma_done(struct esp_struct *info,
+ do_SAK(tty);
+ } else if (status & 0x08) {
+ statflag = TTY_FRAME;
+- (info->icount.frame)++;
+- }
+- else if (status & 0x04) {
++ info->icount.frame++;
++ } else if (status & 0x04) {
+ statflag = TTY_PARITY;
+- (info->icount.parity)++;
++ info->icount.parity++;
+ }
+- tty_insert_flip_char(tty, dma_buffer[num_bytes - 1], statflag);
++ tty_insert_flip_char(tty, dma_buffer[num_bytes - 1],
++ statflag);
+ }
+ tty_schedule_flip(tty);
+ }
+@@ -484,8 +491,6 @@ static inline void transmit_chars_pio(struct esp_struct *info,
+ /* Caller must hold info->lock */
+ static inline void transmit_chars_dma(struct esp_struct *info, int num_bytes)
+ {
+- unsigned long flags;
+-
+ dma_bytes = num_bytes;
+
+ if (info->xmit_tail + dma_bytes <= ESP_XMIT_SIZE) {
+@@ -517,26 +522,18 @@ static inline void transmit_chars_dma(struct esp_struct *info, int num_bytes)
+ }
+
+ info->stat_flags |= ESP_STAT_DMA_TX;
+-
+- flags=claim_dma_lock();
+- disable_dma(dma);
+- clear_dma_ff(dma);
+- set_dma_mode(dma, DMA_MODE_WRITE);
+- set_dma_addr(dma, isa_virt_to_bus(dma_buffer));
+- set_dma_count(dma, dma_bytes);
+- enable_dma(dma);
+- release_dma_lock(flags);
+-
+- serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX);
++
++ program_isa_dma(dma, DMA_MODE_WRITE, isa_virt_to_bus(dma_buffer),
++ dma_bytes);
++ serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX);
+ }
+
+ static inline void transmit_chars_dma_done(struct esp_struct *info)
+ {
+ int num_bytes;
+ unsigned long flags;
+-
+
+- flags=claim_dma_lock();
++ flags = claim_dma_lock();
+ disable_dma(dma);
+ clear_dma_ff(dma);
+
+@@ -547,27 +544,21 @@ static inline void transmit_chars_dma_done(struct esp_struct *info)
+ if (dma_bytes != num_bytes) {
+ dma_bytes -= num_bytes;
+ memmove(dma_buffer, dma_buffer + num_bytes, dma_bytes);
+-
+- flags=claim_dma_lock();
+- disable_dma(dma);
+- clear_dma_ff(dma);
+- set_dma_mode(dma, DMA_MODE_WRITE);
+- set_dma_addr(dma, isa_virt_to_bus(dma_buffer));
+- set_dma_count(dma, dma_bytes);
+- enable_dma(dma);
+- release_dma_lock(flags);
+-
+- serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX);
++
++ program_isa_dma(dma, DMA_MODE_WRITE,
++ isa_virt_to_bus(dma_buffer), dma_bytes);
++
++ serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX);
+ } else {
+ dma_bytes = 0;
+ info->stat_flags &= ~ESP_STAT_DMA_TX;
+ }
+ }
+
+-static inline void check_modem_status(struct esp_struct *info)
++static void check_modem_status(struct esp_struct *info)
+ {
+ int status;
+-
++
+ serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
+ status = serial_in(info, UART_ESI_STAT2);
+
+@@ -588,7 +579,7 @@ static inline void check_modem_status(struct esp_struct *info)
+ #if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
+ printk("ttys%d CD now %s...", info->line,
+ (status & UART_MSR_DCD) ? "on" : "off");
+-#endif
++#endif
+ if (status & UART_MSR_DCD)
+ wake_up_interruptible(&info->open_wait);
+ else {
+@@ -605,7 +596,7 @@ static inline void check_modem_status(struct esp_struct *info)
+ */
+ static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
+ {
+- struct esp_struct * info;
++ struct esp_struct *info;
+ unsigned err_status;
+ unsigned int scratch;
+
+@@ -617,7 +608,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
+ scratch = serial_in(info, UART_ESI_SID);
+
+ spin_lock(&info->lock);
+-
++
+ if (!info->tty) {
+ spin_unlock(&info->lock);
+ return IRQ_NONE;
+@@ -637,7 +628,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
+ if (err_status & 0x80) /* Start break */
+ wake_up_interruptible(&info->break_wait);
+ }
+-
++
+ if ((scratch & 0x88) || /* DMA completed or timed out */
+ (err_status & 0x1c) /* receive error */) {
+ if (info->stat_flags & ESP_STAT_DMA_RX)
+@@ -667,7 +658,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
+ receive_chars_dma(info, num_bytes);
+ }
+ }
+-
++
+ if (!(info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) &&
+ (scratch & 0x02) && (info->IER & UART_IER_THRI)) {
+ if ((info->xmit_cnt <= 0) || info->tty->stopped) {
+@@ -722,11 +713,11 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
+ * ---------------------------------------------------------------
+ */
+
+-static inline void esp_basic_init(struct esp_struct * info)
++static void esp_basic_init(struct esp_struct *info)
+ {
+ /* put ESPC in enhanced mode */
+ serial_out(info, UART_ESI_CMD1, ESI_SET_MODE);
+-
++
+ if (info->stat_flags & ESP_STAT_NEVER_DMA)
+ serial_out(info, UART_ESI_CMD2, 0x01);
+ else
+@@ -783,13 +774,13 @@ static inline void esp_basic_init(struct esp_struct * info)
+ serial_out(info, UART_ESI_CMD2, 0xff);
+ }
+
+-static int startup(struct esp_struct * info)
++static int startup(struct esp_struct *info)
+ {
+ unsigned long flags;
+- int retval=0;
+- unsigned int num_chars;
++ int retval = 0;
++ unsigned int num_chars;
+
+- spin_lock_irqsave(&info->lock, flags);
++ spin_lock_irqsave(&info->lock, flags);
+
+ if (info->flags & ASYNC_INITIALIZED)
+ goto out;
+@@ -802,7 +793,8 @@ static int startup(struct esp_struct * info)
+ }
+
+ #ifdef SERIAL_DEBUG_OPEN
+- printk("starting up ttys%d (irq %d)...", info->line, info->irq);
++ printk(KERN_DEBUG "starting up ttys%d (irq %d)...",
++ info->line, info->irq);
+ #endif
+
+ /* Flush the RX buffer. Using the ESI flush command may cause */
+@@ -863,7 +855,7 @@ static int startup(struct esp_struct * info)
+ dma_buffer = NULL;
+ info->stat_flags |= ESP_STAT_USE_PIO;
+ }
+-
++
+ }
+
+ info->MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
+@@ -872,7 +864,7 @@ static int startup(struct esp_struct * info)
+ serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
+ serial_out(info, UART_ESI_CMD2, UART_MCR);
+ serial_out(info, UART_ESI_CMD2, info->MCR);
+-
++
+ /*
+ * Finally, enable interrupts
+ */
+@@ -881,7 +873,7 @@ static int startup(struct esp_struct * info)
+ UART_IER_DMA_TC;
+ serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
+ serial_out(info, UART_ESI_CMD2, info->IER);
+-
++
+ if (info->tty)
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+@@ -900,7 +892,7 @@ static int startup(struct esp_struct * info)
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+ info->tty->alt_speed = 460800;
+ }
+-
++
+ /*
+ * set the speed of the serial port
+ */
+@@ -918,7 +910,7 @@ out_unlocked:
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+-static void shutdown(struct esp_struct * info)
++static void shutdown(struct esp_struct *info)
+ {
+ unsigned long flags, f;
+
+@@ -929,7 +921,7 @@ static void shutdown(struct esp_struct * info)
+ printk("Shutting down serial port %d (irq %d)....", info->line,
+ info->irq);
+ #endif
+-
++
+ spin_lock_irqsave(&info->lock, flags);
+ /*
+ * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
+@@ -941,14 +933,14 @@ static void shutdown(struct esp_struct * info)
+ /* stop a DMA transfer on the port being closed */
+ /* DMA lock is higher priority always */
+ if (info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) {
+- f=claim_dma_lock();
++ f = claim_dma_lock();
+ disable_dma(dma);
+ clear_dma_ff(dma);
+ release_dma_lock(f);
+-
++
+ dma_bytes = 0;
+ }
+-
++
+ /*
+ * Free the IRQ
+ */
+@@ -970,7 +962,7 @@ static void shutdown(struct esp_struct * info)
+ free_pages((unsigned long)dma_buffer,
+ get_order(DMA_BUFFER_SZ));
+ dma_buffer = NULL;
+- }
++ }
+ }
+
+ if (info->xmit_buf) {
+@@ -992,7 +984,7 @@ static void shutdown(struct esp_struct * info)
+
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+-
++
+ info->flags &= ~ASYNC_INITIALIZED;
+ spin_unlock_irqrestore(&info->lock, flags);
+ }
+@@ -1005,7 +997,7 @@ static void change_speed(struct esp_struct *info)
+ {
+ unsigned short port;
+ int quot = 0;
+- unsigned cflag,cval;
++ unsigned cflag, cval;
+ int baud, bits;
+ unsigned char flow1 = 0, flow2 = 0;
+ unsigned long flags;
+@@ -1014,14 +1006,14 @@ static void change_speed(struct esp_struct *info)
+ return;
+ cflag = info->tty->termios->c_cflag;
+ port = info->port;
+-
++
+ /* byte size and parity */
+ switch (cflag & CSIZE) {
+- case CS5: cval = 0x00; bits = 7; break;
+- case CS6: cval = 0x01; bits = 8; break;
+- case CS7: cval = 0x02; bits = 9; break;
+- case CS8: cval = 0x03; bits = 10; break;
+- default: cval = 0x00; bits = 7; break;
++ case CS5: cval = 0x00; bits = 7; break;
++ case CS6: cval = 0x01; bits = 8; break;
++ case CS7: cval = 0x02; bits = 9; break;
++ case CS8: cval = 0x03; bits = 10; break;
++ default: cval = 0x00; bits = 7; break;
+ }
+ if (cflag & CSTOPB) {
+ cval |= 0x04;
+@@ -1037,14 +1029,12 @@ static void change_speed(struct esp_struct *info)
+ if (cflag & CMSPAR)
+ cval |= UART_LCR_SPAR;
+ #endif
+-
+ baud = tty_get_baud_rate(info->tty);
+ if (baud == 38400 &&
+- ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
++ ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
+ quot = info->custom_divisor;
+ else {
+- if (baud == 134)
+- /* Special case since 134 is really 134.5 */
++ if (baud == 134) /* Special case since 134 is really 134.5 */
+ quot = (2*BASE_BAUD / 269);
+ else if (baud)
+ quot = BASE_BAUD / baud;
+@@ -1052,7 +1042,12 @@ static void change_speed(struct esp_struct *info)
+ /* If the quotient is ever zero, default to 9600 bps */
+ if (!quot)
+ quot = BASE_BAUD / 9600;
+-
++
++ if (baud) {
++ /* Actual rate */
++ baud = BASE_BAUD/quot;
++ tty_encode_baud_rate(info->tty, baud, baud);
++ }
+ info->timeout = ((1024 * HZ * bits * quot) / BASE_BAUD) + (HZ / 50);
+
+ /* CTS flow control flag and modem status interrupts */
+@@ -1066,10 +1061,8 @@ static void change_speed(struct esp_struct *info)
+ info->flags &= ~ASYNC_CTS_FLOW;
+ if (cflag & CLOCAL)
+ info->flags &= ~ASYNC_CHECK_CD;
+- else {
++ else
+ info->flags |= ASYNC_CHECK_CD;
+- /* info->IER |= UART_IER_MSI; */
+- }
+
+ /*
+ * Set up parity check flag
+@@ -1079,7 +1072,7 @@ static void change_speed(struct esp_struct *info)
+ info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+ if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
+ info->read_status_mask |= UART_LSR_BI;
+-
++
+ info->ignore_status_mask = 0;
+ #if 0
+ /* This should be safe, but for some broken bits of hardware... */
+@@ -1092,7 +1085,7 @@ static void change_speed(struct esp_struct *info)
+ info->ignore_status_mask |= UART_LSR_BI;
+ info->read_status_mask |= UART_LSR_BI;
+ /*
+- * If we're ignore parity and break indicators, ignore
++ * If we're ignore parity and break indicators, ignore
+ * overruns too. (For real raw support).
+ */
+ if (I_IGNPAR(info->tty)) {
+@@ -1130,19 +1123,19 @@ static void change_speed(struct esp_struct *info)
+ serial_out(info, UART_ESI_CMD2, 0x10);
+ serial_out(info, UART_ESI_CMD2, 0x21);
+ switch (cflag & CSIZE) {
+- case CS5:
+- serial_out(info, UART_ESI_CMD2, 0x1f);
+- break;
+- case CS6:
+- serial_out(info, UART_ESI_CMD2, 0x3f);
+- break;
+- case CS7:
+- case CS8:
+- serial_out(info, UART_ESI_CMD2, 0x7f);
+- break;
+- default:
+- serial_out(info, UART_ESI_CMD2, 0xff);
+- break;
++ case CS5:
++ serial_out(info, UART_ESI_CMD2, 0x1f);
++ break;
++ case CS6:
++ serial_out(info, UART_ESI_CMD2, 0x3f);
++ break;
++ case CS7:
++ case CS8:
++ serial_out(info, UART_ESI_CMD2, 0x7f);
++ break;
++ default:
++ serial_out(info, UART_ESI_CMD2, 0xff);
++ break;
+ }
+ }
+
+@@ -1156,31 +1149,34 @@ static void change_speed(struct esp_struct *info)
+ spin_unlock_irqrestore(&info->lock, flags);
+ }
+
+-static void rs_put_char(struct tty_struct *tty, unsigned char ch)
++static int rs_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+- struct esp_struct *info = (struct esp_struct *)tty->driver_data;
++ struct esp_struct *info = tty->driver_data;
+ unsigned long flags;
++ int ret = 0;
+
+ if (serial_paranoia_check(info, tty->name, "rs_put_char"))
+- return;
++ return 0;
+
+ if (!info->xmit_buf)
+- return;
++ return 0;
+
+ spin_lock_irqsave(&info->lock, flags);
+ if (info->xmit_cnt < ESP_XMIT_SIZE - 1) {
+ info->xmit_buf[info->xmit_head++] = ch;
+ info->xmit_head &= ESP_XMIT_SIZE-1;
+ info->xmit_cnt++;
++ ret = 1;
+ }
+ spin_unlock_irqrestore(&info->lock, flags);
++ return ret;
+ }
+
+ static void rs_flush_chars(struct tty_struct *tty)
+ {
+- struct esp_struct *info = (struct esp_struct *)tty->driver_data;
++ struct esp_struct *info = tty->driver_data;
+ unsigned long flags;
+-
++
+ if (serial_paranoia_check(info, tty->name, "rs_flush_chars"))
+ return;
+
+@@ -1198,11 +1194,11 @@ out:
+ spin_unlock_irqrestore(&info->lock, flags);
+ }
+
+-static int rs_write(struct tty_struct * tty,
++static int rs_write(struct tty_struct *tty,
+ const unsigned char *buf, int count)
+ {
+ int c, t, ret = 0;
+- struct esp_struct *info = (struct esp_struct *)tty->driver_data;
++ struct esp_struct *info = tty->driver_data;
+ unsigned long flags;
+
+ if (serial_paranoia_check(info, tty->name, "rs_write"))
+@@ -1210,19 +1206,19 @@ static int rs_write(struct tty_struct * tty,
+
+ if (!info->xmit_buf)
+ return 0;
+-
++
+ while (1) {
+ /* Thanks to R. Wolff for suggesting how to do this with */
+ /* interrupts enabled */
+
+ c = count;
+ t = ESP_XMIT_SIZE - info->xmit_cnt - 1;
+-
++
+ if (t < c)
+ c = t;
+
+ t = ESP_XMIT_SIZE - info->xmit_head;
+-
++
+ if (t < c)
+ c = t;
+
+@@ -1252,10 +1248,10 @@ static int rs_write(struct tty_struct * tty,
+
+ static int rs_write_room(struct tty_struct *tty)
+ {
+- struct esp_struct *info = (struct esp_struct *)tty->driver_data;
++ struct esp_struct *info = tty->driver_data;
+ int ret;
+ unsigned long flags;
+-
++
+ if (serial_paranoia_check(info, tty->name, "rs_write_room"))
+ return 0;
+
+@@ -1270,8 +1266,8 @@ static int rs_write_room(struct tty_struct *tty)
+
+ static int rs_chars_in_buffer(struct tty_struct *tty)
+ {
+- struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+-
++ struct esp_struct *info = tty->driver_data;
++
+ if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer"))
+ return 0;
+ return info->xmit_cnt;
+@@ -1279,9 +1275,9 @@ static int rs_chars_in_buffer(struct tty_struct *tty)
+
+ static void rs_flush_buffer(struct tty_struct *tty)
+ {
+- struct esp_struct *info = (struct esp_struct *)tty->driver_data;
++ struct esp_struct *info = tty->driver_data;
+ unsigned long flags;
+-
++
+ if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
+ return;
+ spin_lock_irqsave(&info->lock, flags);
+@@ -1293,20 +1289,20 @@ static void rs_flush_buffer(struct tty_struct *tty)
+ /*
+ * ------------------------------------------------------------
+ * rs_throttle()
+- *
++ *
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ * ------------------------------------------------------------
+ */
+-static void rs_throttle(struct tty_struct * tty)
++static void rs_throttle(struct tty_struct *tty)
+ {
+- struct esp_struct *info = (struct esp_struct *)tty->driver_data;
++ struct esp_struct *info = tty->driver_data;
+ unsigned long flags;
+ #ifdef SERIAL_DEBUG_THROTTLE
+ char buf[64];
+-
++
+ printk("throttle %s: %d....\n", tty_name(tty, buf),
+- tty->ldisc.chars_in_buffer(tty));
++ tty_chars_in_buffer(tty));
+ #endif
+
+ if (serial_paranoia_check(info, tty->name, "rs_throttle"))
+@@ -1321,20 +1317,20 @@ static void rs_throttle(struct tty_struct * tty)
+ spin_unlock_irqrestore(&info->lock, flags);
+ }
+
+-static void rs_unthrottle(struct tty_struct * tty)
++static void rs_unthrottle(struct tty_struct *tty)
+ {
+- struct esp_struct *info = (struct esp_struct *)tty->driver_data;
++ struct esp_struct *info = tty->driver_data;
+ unsigned long flags;
+ #ifdef SERIAL_DEBUG_THROTTLE
+ char buf[64];
+-
+- printk("unthrottle %s: %d....\n", tty_name(tty, buf),
+- tty->ldisc.chars_in_buffer(tty));
++
++ printk(KERN_DEBUG "unthrottle %s: %d....\n", tty_name(tty, buf),
++ tty_chars_in_buffer(tty));
+ #endif
+
+ if (serial_paranoia_check(info, tty->name, "rs_unthrottle"))
+ return;
+-
++
+ spin_lock_irqsave(&info->lock, flags);
+ info->IER |= UART_IER_RDI;
+ serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
+@@ -1350,11 +1346,12 @@ static void rs_unthrottle(struct tty_struct * tty)
+ * ------------------------------------------------------------
+ */
+
+-static int get_serial_info(struct esp_struct * info,
++static int get_serial_info(struct esp_struct *info,
+ struct serial_struct __user *retinfo)
+ {
+ struct serial_struct tmp;
+-
++
++ lock_kernel();
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.type = PORT_16550A;
+ tmp.line = info->line;
+@@ -1367,20 +1364,22 @@ static int get_serial_info(struct esp_struct * info,
+ tmp.closing_wait = info->closing_wait;
+ tmp.custom_divisor = info->custom_divisor;
+ tmp.hub6 = 0;
+- if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
++ unlock_kernel();
++ if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+ return -EFAULT;
+ return 0;
+ }
+
+-static int get_esp_config(struct esp_struct * info,
++static int get_esp_config(struct esp_struct *info,
+ struct hayes_esp_config __user *retinfo)
+ {
+ struct hayes_esp_config tmp;
+-
++
+ if (!retinfo)
+ return -EFAULT;
+
+ memset(&tmp, 0, sizeof(tmp));
++ lock_kernel();
+ tmp.rx_timeout = info->config.rx_timeout;
+ tmp.rx_trigger = info->config.rx_trigger;
+ tmp.tx_trigger = info->config.tx_trigger;
+@@ -1388,11 +1387,12 @@ static int get_esp_config(struct esp_struct * info,
+ tmp.flow_on = info->config.flow_on;
+ tmp.pio_threshold = info->config.pio_threshold;
+ tmp.dma_channel = (info->stat_flags & ESP_STAT_NEVER_DMA ? 0 : dma);
++ unlock_kernel();
+
+ return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
+ }
+
+-static int set_serial_info(struct esp_struct * info,
++static int set_serial_info(struct esp_struct *info,
+ struct serial_struct __user *new_info)
+ {
+ struct serial_struct new_serial;
+@@ -1401,7 +1401,7 @@ static int set_serial_info(struct esp_struct * info,
+ int retval = 0;
+ struct esp_struct *current_async;
+
+- if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
++ if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
+ return -EFAULT;
+ old_info = *info;
+
+@@ -1422,7 +1422,7 @@ static int set_serial_info(struct esp_struct * info,
+ return -EINVAL;
+
+ if (!capable(CAP_SYS_ADMIN)) {
+- if (change_irq ||
++ if (change_irq ||
+ (new_serial.close_delay != info->close_delay) ||
+ ((new_serial.flags & ~ASYNC_USR_MASK) !=
+ (info->flags & ~ASYNC_USR_MASK)))
+@@ -1507,8 +1507,8 @@ static int set_serial_info(struct esp_struct * info,
+ return retval;
+ }
+
+-static int set_esp_config(struct esp_struct * info,
+- struct hayes_esp_config __user * new_info)
++static int set_esp_config(struct esp_struct *info,
++ struct hayes_esp_config __user *new_info)
+ {
+ struct hayes_esp_config new_config;
+ unsigned int change_dma;
+@@ -1550,7 +1550,6 @@ static int set_esp_config(struct esp_struct * info,
+ if (new_config.dma_channel) {
+ /* PIO mode to DMA mode transition OR */
+ /* change current DMA channel */
+-
+ current_async = ports;
+
+ while (current_async) {
+@@ -1559,16 +1558,15 @@ static int set_esp_config(struct esp_struct * info,
+ return -EBUSY;
+ } else if (current_async->count)
+ return -EBUSY;
+-
+- current_async =
+- current_async->next_port;
++
++ current_async = current_async->next_port;
+ }
+
+ shutdown(info);
+ dma = new_config.dma_channel;
+ info->stat_flags &= ~ESP_STAT_NEVER_DMA;
+-
+- /* all ports must use the same DMA channel */
++
++ /* all ports must use the same DMA channel */
+
+ spin_lock_irqsave(&info->lock, flags);
+ current_async = ports;
+@@ -1580,7 +1578,6 @@ static int set_esp_config(struct esp_struct * info,
+ spin_unlock_irqrestore(&info->lock, flags);
+ } else {
+ /* DMA mode to PIO mode only */
+-
+ if (info->count > 1)
+ return -EBUSY;
+
+@@ -1596,8 +1593,6 @@ static int set_esp_config(struct esp_struct * info,
+
+ if ((new_config.flow_off != info->config.flow_off) ||
+ (new_config.flow_on != info->config.flow_on)) {
+- unsigned long flags;
+-
+ info->config.flow_off = new_config.flow_off;
+ info->config.flow_on = new_config.flow_on;
+
+@@ -1612,8 +1607,6 @@ static int set_esp_config(struct esp_struct * info,
+
+ if ((new_config.rx_trigger != info->config.rx_trigger) ||
+ (new_config.tx_trigger != info->config.tx_trigger)) {
+- unsigned long flags;
+-
+ info->config.rx_trigger = new_config.rx_trigger;
+ info->config.tx_trigger = new_config.tx_trigger;
+ spin_lock_irqsave(&info->lock, flags);
+@@ -1628,8 +1621,6 @@ static int set_esp_config(struct esp_struct * info,
+ }
+
+ if (new_config.rx_timeout != info->config.rx_timeout) {
+- unsigned long flags;
+-
+ info->config.rx_timeout = new_config.rx_timeout;
+ spin_lock_irqsave(&info->lock, flags);
+
+@@ -1657,9 +1648,9 @@ static int set_esp_config(struct esp_struct * info,
+ * release the bus after transmitting. This must be done when
+ * the transmit shift register is empty, not be done when the
+ * transmit holding register is empty. This functionality
+- * allows an RS485 driver to be written in user space.
++ * allows an RS485 driver to be written in user space.
+ */
+-static int get_lsr_info(struct esp_struct * info, unsigned int __user *value)
++static int get_lsr_info(struct esp_struct *info, unsigned int __user *value)
+ {
+ unsigned char status;
+ unsigned int result;
+@@ -1670,17 +1661,17 @@ static int get_lsr_info(struct esp_struct * info, unsigned int __user *value)
+ status = serial_in(info, UART_ESI_STAT1);
+ spin_unlock_irqrestore(&info->lock, flags);
+ result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
+- return put_user(result,value);
++ return put_user(result, value);
+ }
+
+
+ static int esp_tiocmget(struct tty_struct *tty, struct file *file)
+ {
+- struct esp_struct * info = (struct esp_struct *)tty->driver_data;
++ struct esp_struct *info = tty->driver_data;
+ unsigned char control, status;
+ unsigned long flags;
+
+- if (serial_paranoia_check(info, tty->name, __FUNCTION__))
++ if (serial_paranoia_check(info, tty->name, __func__))
+ return -ENODEV;
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+@@ -1703,10 +1694,10 @@ static int esp_tiocmget(struct tty_struct *tty, struct file *file)
+ static int esp_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+ {
+- struct esp_struct * info = (struct esp_struct *)tty->driver_data;
++ struct esp_struct *info = tty->driver_data;
+ unsigned long flags;
+
+- if (serial_paranoia_check(info, tty->name, __FUNCTION__))
++ if (serial_paranoia_check(info, tty->name, __func__))
+ return -ENODEV;
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+@@ -1736,9 +1727,9 @@ static int esp_tiocmset(struct tty_struct *tty, struct file *file,
+ */
+ static void esp_break(struct tty_struct *tty, int break_state)
+ {
+- struct esp_struct * info = (struct esp_struct *)tty->driver_data;
++ struct esp_struct *info = tty->driver_data;
+ unsigned long flags;
+-
++
+ if (serial_paranoia_check(info, tty->name, "esp_break"))
+ return;
+
+@@ -1758,14 +1749,15 @@ static void esp_break(struct tty_struct *tty, int break_state)
+ }
+ }
+
+-static int rs_ioctl(struct tty_struct *tty, struct file * file,
++static int rs_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+- struct esp_struct * info = (struct esp_struct *)tty->driver_data;
++ struct esp_struct *info = tty->driver_data;
+ struct async_icount cprev, cnow; /* kernel counter temps */
+ struct serial_icounter_struct __user *p_cuser; /* user space */
+ void __user *argp = (void __user *)arg;
+ unsigned long flags;
++ int ret;
+
+ if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
+ return -ENODEV;
+@@ -1778,97 +1770,93 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+ }
+-
+- switch (cmd) {
+- case TIOCGSERIAL:
+- return get_serial_info(info, argp);
+- case TIOCSSERIAL:
+- return set_serial_info(info, argp);
+- case TIOCSERCONFIG:
+- /* do not reconfigure after initial configuration */
+- return 0;
+-
+- case TIOCSERGWILD:
+- return put_user(0L, (unsigned long __user *)argp);
+
+- case TIOCSERGETLSR: /* Get line status register */
+- return get_lsr_info(info, argp);
+-
+- case TIOCSERSWILD:
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+- return 0;
+-
+- /*
+- * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+- * - mask passed in arg for lines of interest
+- * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+- * Caller should use TIOCGICOUNT to see which one it was
+- */
+- case TIOCMIWAIT:
++ switch (cmd) {
++ case TIOCGSERIAL:
++ return get_serial_info(info, argp);
++ case TIOCSSERIAL:
++ lock_kernel();
++ ret = set_serial_info(info, argp);
++ unlock_kernel();
++ return ret;
++ case TIOCSERGWILD:
++ return put_user(0L, (unsigned long __user *)argp);
++ case TIOCSERGETLSR: /* Get line status register */
++ return get_lsr_info(info, argp);
++ case TIOCSERSWILD:
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++ return 0;
++ /*
++ * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
++ * - mask passed in arg for lines of interest
++ * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
++ * Caller should use TIOCGICOUNT to see which one it was
++ */
++ case TIOCMIWAIT:
++ spin_lock_irqsave(&info->lock, flags);
++ cprev = info->icount; /* note the counters on entry */
++ spin_unlock_irqrestore(&info->lock, flags);
++ while (1) {
++ /* FIXME: convert to new style wakeup */
++ interruptible_sleep_on(&info->delta_msr_wait);
++ /* see if a signal did it */
++ if (signal_pending(current))
++ return -ERESTARTSYS;
+ spin_lock_irqsave(&info->lock, flags);
+- cprev = info->icount; /* note the counters on entry */
++ cnow = info->icount; /* atomic copy */
+ spin_unlock_irqrestore(&info->lock, flags);
+- while (1) {
+- /* FIXME: convert to new style wakeup */
+- interruptible_sleep_on(&info->delta_msr_wait);
+- /* see if a signal did it */
+- if (signal_pending(current))
+- return -ERESTARTSYS;
+- spin_lock_irqsave(&info->lock, flags);
+- cnow = info->icount; /* atomic copy */
+- spin_unlock_irqrestore(&info->lock, flags);
+- if (cnow.rng == cprev.rng &&
+- cnow.dsr == cprev.dsr &&
+- cnow.dcd == cprev.dcd &&
+- cnow.cts == cprev.cts)
+- return -EIO; /* no change => error */
+- if (((arg & TIOCM_RNG) &&
+- (cnow.rng != cprev.rng)) ||
+- ((arg & TIOCM_DSR) &&
+- (cnow.dsr != cprev.dsr)) ||
+- ((arg & TIOCM_CD) &&
+- (cnow.dcd != cprev.dcd)) ||
+- ((arg & TIOCM_CTS) &&
+- (cnow.cts != cprev.cts)) ) {
+- return 0;
+- }
+- cprev = cnow;
++ if (cnow.rng == cprev.rng &&
++ cnow.dsr == cprev.dsr &&
++ cnow.dcd == cprev.dcd &&
++ cnow.cts == cprev.cts)
++ return -EIO; /* no change => error */
++ if (((arg & TIOCM_RNG) &&
++ (cnow.rng != cprev.rng)) ||
++ ((arg & TIOCM_DSR) &&
++ (cnow.dsr != cprev.dsr)) ||
++ ((arg & TIOCM_CD) &&
++ (cnow.dcd != cprev.dcd)) ||
++ ((arg & TIOCM_CTS) &&
++ (cnow.cts != cprev.cts))) {
++ return 0;
+ }
+- /* NOTREACHED */
+-
+- /*
+- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+- * Return: write counters to the user passed counter struct
+- * NB: both 1->0 and 0->1 transitions are counted except for
+- * RI where only 0->1 is counted.
+- */
+- case TIOCGICOUNT:
+- spin_lock_irqsave(&info->lock, flags);
+- cnow = info->icount;
+- spin_unlock_irqrestore(&info->lock, flags);
+- p_cuser = argp;
+- if (put_user(cnow.cts, &p_cuser->cts) ||
+- put_user(cnow.dsr, &p_cuser->dsr) ||
+- put_user(cnow.rng, &p_cuser->rng) ||
+- put_user(cnow.dcd, &p_cuser->dcd))
+- return -EFAULT;
+-
++ cprev = cnow;
++ }
++ /* NOTREACHED */
++ /*
++ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
++ * Return: write counters to the user passed counter struct
++ * NB: both 1->0 and 0->1 transitions are counted except for
++ * RI where only 0->1 is counted.
++ */
++ case TIOCGICOUNT:
++ spin_lock_irqsave(&info->lock, flags);
++ cnow = info->icount;
++ spin_unlock_irqrestore(&info->lock, flags);
++ p_cuser = argp;
++ if (put_user(cnow.cts, &p_cuser->cts) ||
++ put_user(cnow.dsr, &p_cuser->dsr) ||
++ put_user(cnow.rng, &p_cuser->rng) ||
++ put_user(cnow.dcd, &p_cuser->dcd))
++ return -EFAULT;
+ return 0;
+ case TIOCGHAYESESP:
+ return get_esp_config(info, argp);
+ case TIOCSHAYESESP:
+- return set_esp_config(info, argp);
+-
+- default:
+- return -ENOIOCTLCMD;
+- }
++ lock_kernel();
++ ret = set_esp_config(info, argp);
++ unlock_kernel();
++ return ret;
++ default:
++ return -ENOIOCTLCMD;
++ }
+ return 0;
+ }
+
+ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+ {
+- struct esp_struct *info = (struct esp_struct *)tty->driver_data;
++ struct esp_struct *info = tty->driver_data;
+ unsigned long flags;
+
+ change_speed(info);
+@@ -1905,32 +1893,33 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+ /*
+ * ------------------------------------------------------------
+ * rs_close()
+- *
++ *
+ * This routine is called when the serial port gets closed. First, we
+ * wait for the last remaining data to be sent. Then, we unlink its
+ * async structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ * ------------------------------------------------------------
+ */
+-static void rs_close(struct tty_struct *tty, struct file * filp)
++static void rs_close(struct tty_struct *tty, struct file *filp)
+ {
+- struct esp_struct * info = (struct esp_struct *)tty->driver_data;
++ struct esp_struct *info = tty->driver_data;
+ unsigned long flags;
+
+ if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
+ return;
+-
++
+ spin_lock_irqsave(&info->lock, flags);
+-
++
+ if (tty_hung_up_p(filp)) {
+ DBG_CNT("before DEC-hung");
+ goto out;
+ }
+-
++
+ #ifdef SERIAL_DEBUG_OPEN
+- printk("rs_close ttys%d, count = %d\n", info->line, info->count);
++ printk(KERN_DEBUG "rs_close ttys%d, count = %d\n",
++ info->line, info->count);
+ #endif
+- if ((tty->count == 1) && (info->count != 1)) {
++ if (tty->count == 1 && info->count != 1) {
+ /*
+ * Uh, oh. tty->count is 1, which means that the tty
+ * structure will be freed. Info->count should always
+@@ -1938,12 +1927,11 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
+ * one, we've got real problems, since it means the
+ * serial port won't be shutdown.
+ */
+- printk("rs_close: bad serial port count; tty->count is 1, "
+- "info->count is %d\n", info->count);
++ printk(KERN_DEBUG "rs_close: bad serial port count; tty->count is 1, info->count is %d\n", info->count);
+ info->count = 1;
+ }
+ if (--info->count < 0) {
+- printk("rs_close: bad serial port count for ttys%d: %d\n",
++ printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n",
+ info->line, info->count);
+ info->count = 0;
+ }
+@@ -1955,7 +1943,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
+
+ spin_unlock_irqrestore(&info->lock, flags);
+ /*
+- * Now we wait for the transmit buffer to clear; and we notify
++ * Now we wait for the transmit buffer to clear; and we notify
+ * the line discipline to only process XON/XOFF characters.
+ */
+ tty->closing = 1;
+@@ -1990,16 +1978,14 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
+ rs_wait_until_sent(tty, info->timeout);
+ }
+ shutdown(info);
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ rs_flush_buffer(tty);
+ tty_ldisc_flush(tty);
+ tty->closing = 0;
+ info->tty = NULL;
+
+ if (info->blocked_open) {
+- if (info->close_delay) {
++ if (info->close_delay)
+ msleep_interruptible(jiffies_to_msecs(info->close_delay));
+- }
+ wake_up_interruptible(&info->open_wait);
+ }
+ info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
+@@ -2012,7 +1998,7 @@ out:
+
+ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+ {
+- struct esp_struct *info = (struct esp_struct *)tty->driver_data;
++ struct esp_struct *info = tty->driver_data;
+ unsigned long orig_jiffies, char_time;
+ unsigned long flags;
+
+@@ -2036,10 +2022,10 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+ msleep_interruptible(jiffies_to_msecs(char_time));
+
+ if (signal_pending(current))
+- break;
++ return;
+
+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
+- break;
++ return;
+
+ spin_lock_irqsave(&info->lock, flags);
+ serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
+@@ -2054,11 +2040,11 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+ */
+ static void esp_hangup(struct tty_struct *tty)
+ {
+- struct esp_struct * info = (struct esp_struct *)tty->driver_data;
+-
++ struct esp_struct *info = tty->driver_data;
++
+ if (serial_paranoia_check(info, tty->name, "esp_hangup"))
+ return;
+-
++
+ rs_flush_buffer(tty);
+ shutdown(info);
+ info->count = 0;
+@@ -2072,7 +2058,7 @@ static void esp_hangup(struct tty_struct *tty)
+ * esp_open() and friends
+ * ------------------------------------------------------------
+ */
+-static int block_til_ready(struct tty_struct *tty, struct file * filp,
++static int block_til_ready(struct tty_struct *tty, struct file *filp,
+ struct esp_struct *info)
+ {
+ DECLARE_WAITQUEUE(wait, current);
+@@ -2121,11 +2107,11 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
+ retval = 0;
+ add_wait_queue(&info->open_wait, &wait);
+ #ifdef SERIAL_DEBUG_OPEN
+- printk("block_til_ready before block: ttys%d, count = %d\n",
++ printk(KERN_DEBUG "block_til_ready before block: ttys%d, count = %d\n",
+ info->line, info->count);
+ #endif
+ spin_lock_irqsave(&info->lock, flags);
+- if (!tty_hung_up_p(filp))
++ if (!tty_hung_up_p(filp))
+ info->count--;
+ info->blocked_open++;
+ while (1) {
+@@ -2147,7 +2133,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
+ if (info->flags & ASYNC_HUP_NOTIFY)
+ retval = -EAGAIN;
+ else
+- retval = -ERESTARTSYS;
++ retval = -ERESTARTSYS;
+ #else
+ retval = -EAGAIN;
+ #endif
+@@ -2166,7 +2152,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
+ break;
+ }
+ #ifdef SERIAL_DEBUG_OPEN
+- printk("block_til_ready blocking: ttys%d, count = %d\n",
++ printk(KERN_DEBUG "block_til_ready blocking: ttys%d, count = %d\n",
+ info->line, info->count);
+ #endif
+ spin_unlock_irqrestore(&info->lock, flags);
+@@ -2180,14 +2166,14 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
+ info->blocked_open--;
+ spin_unlock_irqrestore(&info->lock, flags);
+ #ifdef SERIAL_DEBUG_OPEN
+- printk("block_til_ready after blocking: ttys%d, count = %d\n",
++ printk(KERN_DEBUG "block_til_ready after blocking: ttys%d, count = %d\n",
+ info->line, info->count);
+ #endif
+ if (retval)
+ return retval;
+ info->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+-}
++}
+
+ /*
+ * This routine is called whenever a serial port is opened. It
+@@ -2195,7 +2181,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
+ * the IRQ chain. It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+-static int esp_open(struct tty_struct *tty, struct file * filp)
++static int esp_open(struct tty_struct *tty, struct file *filp)
+ {
+ struct esp_struct *info;
+ int retval, line;
+@@ -2218,7 +2204,7 @@ static int esp_open(struct tty_struct *tty, struct file * filp)
+ }
+
+ #ifdef SERIAL_DEBUG_OPEN
+- printk("esp_open %s, count = %d\n", tty->name, info->count);
++ printk(KERN_DEBUG "esp_open %s, count = %d\n", tty->name, info->count);
+ #endif
+ spin_lock_irqsave(&info->lock, flags);
+ info->count++;
+@@ -2226,7 +2212,7 @@ static int esp_open(struct tty_struct *tty, struct file * filp)
+ info->tty = tty;
+
+ spin_unlock_irqrestore(&info->lock, flags);
+-
++
+ /*
+ * Start up serial port
+ */
+@@ -2237,14 +2223,13 @@ static int esp_open(struct tty_struct *tty, struct file * filp)
+ retval = block_til_ready(tty, filp, info);
+ if (retval) {
+ #ifdef SERIAL_DEBUG_OPEN
+- printk("esp_open returning after block_til_ready with %d\n",
++ printk(KERN_DEBUG "esp_open returning after block_til_ready with %d\n",
+ retval);
+ #endif
+ return retval;
+ }
+-
+ #ifdef SERIAL_DEBUG_OPEN
+- printk("esp_open %s successful...", tty->name);
++ printk(KERN_DEBUG "esp_open %s successful...", tty->name);
+ #endif
+ return 0;
+ }
+@@ -2262,10 +2247,10 @@ static int esp_open(struct tty_struct *tty, struct file * filp)
+ * number, and identifies which options were configured into this
+ * driver.
+ */
+-
+-static inline void show_serial_version(void)
++
++static void show_serial_version(void)
+ {
+- printk(KERN_INFO "%s version %s (DMA %u)\n",
++ printk(KERN_INFO "%s version %s (DMA %u)\n",
+ serial_name, serial_version, dma);
+ }
+
+@@ -2273,7 +2258,7 @@ static inline void show_serial_version(void)
+ * This routine is called by espserial_init() to initialize a specific serial
+ * port.
+ */
+-static inline int autoconfig(struct esp_struct * info)
++static int autoconfig(struct esp_struct *info)
+ {
+ int port_detected = 0;
+ unsigned long flags;
+@@ -2349,14 +2334,14 @@ static const struct tty_operations esp_ops = {
+ static int __init espserial_init(void)
+ {
+ int i, offset;
+- struct esp_struct * info;
++ struct esp_struct *info;
+ struct esp_struct *last_primary = NULL;
+- int esp[] = {0x100,0x140,0x180,0x200,0x240,0x280,0x300,0x380};
++ int esp[] = { 0x100, 0x140, 0x180, 0x200, 0x240, 0x280, 0x300, 0x380 };
+
+ esp_driver = alloc_tty_driver(NR_PORTS);
+ if (!esp_driver)
+ return -ENOMEM;
+-
++
+ for (i = 0; i < NR_PRIMARY; i++) {
+ if (irq[i] != 0) {
+ if ((irq[i] < 2) || (irq[i] > 15) || (irq[i] == 6) ||
+@@ -2378,20 +2363,20 @@ static int __init espserial_init(void)
+
+ if ((flow_off < 1) || (flow_off > 1023))
+ flow_off = 1016;
+-
++
+ if ((flow_on < 1) || (flow_on > 1023))
+ flow_on = 944;
+
+ if ((rx_timeout < 0) || (rx_timeout > 255))
+ rx_timeout = 128;
+-
++
+ if (flow_on >= flow_off)
+ flow_on = flow_off - 1;
+
+ show_serial_version();
+
+ /* Initialize the tty_driver structure */
+-
++
+ esp_driver->owner = THIS_MODULE;
+ esp_driver->name = "ttyP";
+ esp_driver->major = ESP_IN_MAJOR;
+@@ -2401,10 +2386,11 @@ static int __init espserial_init(void)
+ esp_driver->init_termios = tty_std_termios;
+ esp_driver->init_termios.c_cflag =
+ B9600 | CS8 | CREAD | HUPCL | CLOCAL;
++ esp_driver->init_termios.c_ispeed = 9600;
++ esp_driver->init_termios.c_ospeed = 9600;
+ esp_driver->flags = TTY_DRIVER_REAL_RAW;
+ tty_set_operations(esp_driver, &esp_ops);
+- if (tty_register_driver(esp_driver))
+- {
++ if (tty_register_driver(esp_driver)) {
+ printk(KERN_ERR "Couldn't register esp serial driver");
+ put_tty_driver(esp_driver);
+ return 1;
+@@ -2412,8 +2398,7 @@ static int __init espserial_init(void)
+
+ info = kzalloc(sizeof(struct esp_struct), GFP_KERNEL);
+
+- if (!info)
+- {
++ if (!info) {
+ printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n");
+ tty_unregister_driver(esp_driver);
+ put_tty_driver(esp_driver);
+@@ -2476,10 +2461,8 @@ static int __init espserial_init(void)
+ info->stat_flags |= ESP_STAT_NEVER_DMA;
+
+ info = kzalloc(sizeof(struct esp_struct), GFP_KERNEL);
+- if (!info)
+- {
+- printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n");
+-
++ if (!info) {
++ printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n");
+ /* allow use of the already detected ports */
+ return 0;
+ }
+@@ -2503,22 +2486,20 @@ static int __init espserial_init(void)
+ return 0;
+ }
+
+-static void __exit espserial_exit(void)
++static void __exit espserial_exit(void)
+ {
+ int e1;
+ struct esp_struct *temp_async;
+ struct esp_pio_buffer *pio_buf;
+
+- /* printk("Unloading %s: version %s\n", serial_name, serial_version); */
+- if ((e1 = tty_unregister_driver(esp_driver)))
+- printk("SERIAL: failed to unregister serial driver (%d)\n",
+- e1);
++ e1 = tty_unregister_driver(esp_driver);
++ if (e1)
++ printk(KERN_ERR "esp: failed to unregister driver (%d)\n", e1);
+ put_tty_driver(esp_driver);
+
+ while (ports) {
+- if (ports->port) {
++ if (ports->port)
+ release_region(ports->port, REGION_SIZE);
+- }
+ temp_async = ports->next_port;
+ kfree(ports);
+ ports = temp_async;
+diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
+index 8facf3e..252f73e 100644
+--- a/drivers/char/generic_serial.c
++++ b/drivers/char/generic_serial.c
+@@ -28,7 +28,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/tty_flip.h>
+ #include <linux/delay.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #define DEBUG
+@@ -41,27 +40,27 @@ static int gs_debug;
+ #define gs_dprintk(f, str...) /* nothing */
+ #endif
+
+-#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __FUNCTION__)
+-#define func_exit() gs_dprintk (GS_DEBUG_FLOW, "gs: exit %s\n", __FUNCTION__)
++#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __func__)
++#define func_exit() gs_dprintk (GS_DEBUG_FLOW, "gs: exit %s\n", __func__)
+
+ #define RS_EVENT_WRITE_WAKEUP 1
+
+ module_param(gs_debug, int, 0644);
+
+
+-void gs_put_char(struct tty_struct * tty, unsigned char ch)
++int gs_put_char(struct tty_struct * tty, unsigned char ch)
+ {
+ struct gs_port *port;
+
+ func_enter ();
+
+- if (!tty) return;
++ if (!tty) return 0;
+
+ port = tty->driver_data;
+
+- if (!port) return;
++ if (!port) return 0;
+
+- if (! (port->flags & ASYNC_INITIALIZED)) return;
++ if (! (port->flags & ASYNC_INITIALIZED)) return 0;
+
+ /* Take a lock on the serial tranmit buffer! */
+ mutex_lock(& port->port_write_mutex);
+@@ -69,7 +68,7 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch)
+ if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
+ /* Sorry, buffer is full, drop character. Update statistics???? -- REW */
+ mutex_unlock(&port->port_write_mutex);
+- return;
++ return 0;
+ }
+
+ port->xmit_buf[port->xmit_head++] = ch;
+@@ -78,6 +77,7 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch)
+
+ mutex_unlock(&port->port_write_mutex);
+ func_exit ();
++ return 1;
+ }
+
+
+@@ -587,8 +587,7 @@ void gs_close(struct tty_struct * tty, struct file * filp)
+
+ port->flags &= ~GS_ACTIVE;
+
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ gs_flush_buffer(tty);
+
+ tty_ldisc_flush(tty);
+ tty->closing = 0;
+diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
+index 1399971..e7fb0bc 100644
+--- a/drivers/char/hpet.c
++++ b/drivers/char/hpet.c
+@@ -308,7 +308,7 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
+ if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
+ PAGE_SIZE, vma->vm_page_prot)) {
+ printk(KERN_ERR "%s: io_remap_pfn_range failed\n",
+- __FUNCTION__);
++ __func__);
+ return -EAGAIN;
+ }
+
+@@ -748,7 +748,7 @@ int hpet_alloc(struct hpet_data *hdp)
+ */
+ if (hpet_is_known(hdp)) {
+ printk(KERN_DEBUG "%s: duplicate HPET ignored\n",
+- __FUNCTION__);
++ __func__);
+ return 0;
+ }
+
+@@ -869,7 +869,7 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
+
+ if (hpet_is_known(hdp)) {
+ printk(KERN_DEBUG "%s: 0x%lx is busy\n",
+- __FUNCTION__, hdp->hd_phys_address);
++ __func__, hdp->hd_phys_address);
+ iounmap(hdp->hd_address);
+ return AE_ALREADY_EXISTS;
+ }
+@@ -886,7 +886,7 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
+
+ if (hpet_is_known(hdp)) {
+ printk(KERN_DEBUG "%s: 0x%lx is busy\n",
+- __FUNCTION__, hdp->hd_phys_address);
++ __func__, hdp->hd_phys_address);
+ iounmap(hdp->hd_address);
+ return AE_ALREADY_EXISTS;
+ }
+@@ -925,7 +925,7 @@ static int hpet_acpi_add(struct acpi_device *device)
+ return -ENODEV;
+
+ if (!data.hd_address || !data.hd_nirqs) {
+- printk("%s: no address or irqs in _CRS\n", __FUNCTION__);
++ printk("%s: no address or irqs in _CRS\n", __func__);
+ return -ENODEV;
+ }
+
+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/hvsi.c b/drivers/char/hvsi.c
+index d5a752d..59c6f9a 100644
+--- a/drivers/char/hvsi.c
++++ b/drivers/char/hvsi.c
+@@ -246,7 +246,7 @@ static void compact_inbuf(struct hvsi_struct *hp, uint8_t *read_to)
+ {
+ int remaining = (int)(hp->inbuf_end - read_to);
+
+- pr_debug("%s: %i chars remain\n", __FUNCTION__, remaining);
++ pr_debug("%s: %i chars remain\n", __func__, remaining);
+
+ if (read_to != hp->inbuf)
+ memmove(hp->inbuf, read_to, remaining);
+@@ -365,7 +365,7 @@ static int hvsi_version_respond(struct hvsi_struct *hp, uint16_t query_seqno)
+ packet.u.version = HVSI_VERSION;
+ packet.query_seqno = query_seqno+1;
+
+- pr_debug("%s: sending %i bytes\n", __FUNCTION__, packet.len);
++ pr_debug("%s: sending %i bytes\n", __func__, packet.len);
+ dbg_dump_hex((uint8_t*)&packet, packet.len);
+
+ wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
+@@ -437,7 +437,7 @@ static struct tty_struct *hvsi_recv_data(struct hvsi_struct *hp,
+ return NULL;
+
+ if (overflow > 0) {
+- pr_debug("%s: got >TTY_THRESHOLD_THROTTLE bytes\n", __FUNCTION__);
++ pr_debug("%s: got >TTY_THRESHOLD_THROTTLE bytes\n", __func__);
+ datalen = TTY_THRESHOLD_THROTTLE;
+ }
+
+@@ -448,7 +448,7 @@ static struct tty_struct *hvsi_recv_data(struct hvsi_struct *hp,
+ * we still have more data to deliver, so we need to save off the
+ * overflow and send it later
+ */
+- pr_debug("%s: deferring overflow\n", __FUNCTION__);
++ pr_debug("%s: deferring overflow\n", __func__);
+ memcpy(hp->throttle_buf, data + TTY_THRESHOLD_THROTTLE, overflow);
+ hp->n_throttle = overflow;
+ }
+@@ -474,11 +474,11 @@ static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip,
+
+ chunklen = hvsi_read(hp, hp->inbuf_end, HVSI_MAX_READ);
+ if (chunklen == 0) {
+- pr_debug("%s: 0-length read\n", __FUNCTION__);
++ pr_debug("%s: 0-length read\n", __func__);
+ return 0;
+ }
+
+- pr_debug("%s: got %i bytes\n", __FUNCTION__, chunklen);
++ pr_debug("%s: got %i bytes\n", __func__, chunklen);
+ dbg_dump_hex(hp->inbuf_end, chunklen);
+
+ hp->inbuf_end += chunklen;
+@@ -495,7 +495,7 @@ static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip,
+ continue;
+ }
+
+- pr_debug("%s: handling %i-byte packet\n", __FUNCTION__,
++ pr_debug("%s: handling %i-byte packet\n", __func__,
+ len_packet(packet));
+ dbg_dump_packet(packet);
+
+@@ -526,7 +526,7 @@ static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip,
+ packet += len_packet(packet);
+
+ if (*hangup || *handshake) {
+- pr_debug("%s: hangup or handshake\n", __FUNCTION__);
++ pr_debug("%s: hangup or handshake\n", __func__);
+ /*
+ * we need to send the hangup now before receiving any more data.
+ * If we get "data, hangup, data", we can't deliver the second
+@@ -543,7 +543,7 @@ static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip,
+
+ static void hvsi_send_overflow(struct hvsi_struct *hp)
+ {
+- pr_debug("%s: delivering %i bytes overflow\n", __FUNCTION__,
++ pr_debug("%s: delivering %i bytes overflow\n", __func__,
+ hp->n_throttle);
+
+ hvsi_insert_chars(hp, hp->throttle_buf, hp->n_throttle);
+@@ -563,7 +563,7 @@ static irqreturn_t hvsi_interrupt(int irq, void *arg)
+ unsigned long flags;
+ int again = 1;
+
+- pr_debug("%s\n", __FUNCTION__);
++ pr_debug("%s\n", __func__);
+
+ while (again) {
+ spin_lock_irqsave(&hp->lock, flags);
+@@ -647,7 +647,7 @@ static int hvsi_query(struct hvsi_struct *hp, uint16_t verb)
+ packet.seqno = atomic_inc_return(&hp->seqno);
+ packet.verb = verb;
+
+- pr_debug("%s: sending %i bytes\n", __FUNCTION__, packet.len);
++ pr_debug("%s: sending %i bytes\n", __func__, packet.len);
+ dbg_dump_hex((uint8_t*)&packet, packet.len);
+
+ wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
+@@ -674,7 +674,7 @@ static int hvsi_get_mctrl(struct hvsi_struct *hp)
+ return ret;
+ }
+
+- pr_debug("%s: mctrl 0x%x\n", __FUNCTION__, hp->mctrl);
++ pr_debug("%s: mctrl 0x%x\n", __func__, hp->mctrl);
+
+ return 0;
+ }
+@@ -694,7 +694,7 @@ static int hvsi_set_mctrl(struct hvsi_struct *hp, uint16_t mctrl)
+ if (mctrl & TIOCM_DTR)
+ packet.word = HVSI_TSDTR;
+
+- pr_debug("%s: sending %i bytes\n", __FUNCTION__, packet.len);
++ pr_debug("%s: sending %i bytes\n", __func__, packet.len);
+ dbg_dump_hex((uint8_t*)&packet, packet.len);
+
+ wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
+@@ -790,7 +790,7 @@ static void hvsi_close_protocol(struct hvsi_struct *hp)
+ packet.len = 6;
+ packet.verb = VSV_CLOSE_PROTOCOL;
+
+- pr_debug("%s: sending %i bytes\n", __FUNCTION__, packet.len);
++ pr_debug("%s: sending %i bytes\n", __func__, packet.len);
+ dbg_dump_hex((uint8_t*)&packet, packet.len);
+
+ hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
+@@ -803,7 +803,7 @@ static int hvsi_open(struct tty_struct *tty, struct file *filp)
+ int line = tty->index;
+ int ret;
+
+- pr_debug("%s\n", __FUNCTION__);
++ pr_debug("%s\n", __func__);
+
+ if (line < 0 || line >= hvsi_count)
+ return -ENODEV;
+@@ -868,7 +868,7 @@ static void hvsi_close(struct tty_struct *tty, struct file *filp)
+ struct hvsi_struct *hp = tty->driver_data;
+ unsigned long flags;
+
+- pr_debug("%s\n", __FUNCTION__);
++ pr_debug("%s\n", __func__);
+
+ if (tty_hung_up_p(filp))
+ return;
+@@ -920,7 +920,7 @@ static void hvsi_hangup(struct tty_struct *tty)
+ struct hvsi_struct *hp = tty->driver_data;
+ unsigned long flags;
+
+- pr_debug("%s\n", __FUNCTION__);
++ pr_debug("%s\n", __func__);
+
+ spin_lock_irqsave(&hp->lock, flags);
+
+@@ -942,7 +942,7 @@ static void hvsi_push(struct hvsi_struct *hp)
+ n = hvsi_put_chars(hp, hp->outbuf, hp->n_outbuf);
+ if (n > 0) {
+ /* success */
+- pr_debug("%s: wrote %i chars\n", __FUNCTION__, n);
++ pr_debug("%s: wrote %i chars\n", __func__, n);
+ hp->n_outbuf = 0;
+ } else if (n == -EIO) {
+ __set_state(hp, HVSI_FSP_DIED);
+@@ -965,7 +965,7 @@ static void hvsi_write_worker(struct work_struct *work)
+
+ spin_lock_irqsave(&hp->lock, flags);
+
+- pr_debug("%s: %i chars in buffer\n", __FUNCTION__, hp->n_outbuf);
++ pr_debug("%s: %i chars in buffer\n", __func__, hp->n_outbuf);
+
+ if (!is_open(hp)) {
+ /*
+@@ -983,7 +983,7 @@ static void hvsi_write_worker(struct work_struct *work)
+ schedule_delayed_work(&hp->writer, 10);
+ else {
+ #ifdef DEBUG
+- pr_debug("%s: outbuf emptied after %li jiffies\n", __FUNCTION__,
++ pr_debug("%s: outbuf emptied after %li jiffies\n", __func__,
+ jiffies - start_j);
+ start_j = 0;
+ #endif /* DEBUG */
+@@ -1020,11 +1020,11 @@ static int hvsi_write(struct tty_struct *tty,
+
+ spin_lock_irqsave(&hp->lock, flags);
+
+- pr_debug("%s: %i chars in buffer\n", __FUNCTION__, hp->n_outbuf);
++ pr_debug("%s: %i chars in buffer\n", __func__, hp->n_outbuf);
+
+ if (!is_open(hp)) {
+ /* we're either closing or not yet open; don't accept data */
+- pr_debug("%s: not open\n", __FUNCTION__);
++ pr_debug("%s: not open\n", __func__);
+ goto out;
+ }
+
+@@ -1058,7 +1058,7 @@ out:
+ spin_unlock_irqrestore(&hp->lock, flags);
+
+ if (total != origcount)
+- pr_debug("%s: wanted %i, only wrote %i\n", __FUNCTION__, origcount,
++ pr_debug("%s: wanted %i, only wrote %i\n", __func__, origcount,
+ total);
+
+ return total;
+@@ -1072,7 +1072,7 @@ static void hvsi_throttle(struct tty_struct *tty)
+ {
+ struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+
+- pr_debug("%s\n", __FUNCTION__);
++ pr_debug("%s\n", __func__);
+
+ h_vio_signal(hp->vtermno, VIO_IRQ_DISABLE);
+ }
+@@ -1083,7 +1083,7 @@ static void hvsi_unthrottle(struct tty_struct *tty)
+ unsigned long flags;
+ int shouldflip = 0;
+
+- pr_debug("%s\n", __FUNCTION__);
++ pr_debug("%s\n", __func__);
+
+ spin_lock_irqsave(&hp->lock, flags);
+ if (hp->n_throttle) {
+@@ -1302,7 +1302,7 @@ static int __init hvsi_console_init(void)
+ hp->virq = irq_create_mapping(NULL, irq[0]);
+ if (hp->virq == NO_IRQ) {
+ printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n",
+- __FUNCTION__, irq[0]);
++ __func__, irq[0]);
+ continue;
+ }
+
+diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
+index 84cdf90..662d60e 100644
+--- a/drivers/char/hw_random/core.c
++++ b/drivers/char/hw_random/core.c
+@@ -116,6 +116,10 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
+ err = -EAGAIN;
+ if (!bytes_read && (filp->f_flags & O_NONBLOCK))
+ goto out;
++ if (bytes_read < 0) {
++ err = bytes_read;
++ goto out;
++ }
+
+ err = -EFAULT;
+ while (bytes_read && size) {
+@@ -234,11 +238,11 @@ static DEVICE_ATTR(rng_available, S_IRUGO,
+ NULL);
+
+
+-static void unregister_miscdev(bool suspended)
++static void unregister_miscdev(void)
+ {
+ device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available);
+ device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
+- __misc_deregister(&rng_miscdev, suspended);
++ misc_deregister(&rng_miscdev);
+ }
+
+ static int register_miscdev(void)
+@@ -313,7 +317,7 @@ out:
+ }
+ EXPORT_SYMBOL_GPL(hwrng_register);
+
+-void __hwrng_unregister(struct hwrng *rng, bool suspended)
++void hwrng_unregister(struct hwrng *rng)
+ {
+ int err;
+
+@@ -332,11 +336,11 @@ void __hwrng_unregister(struct hwrng *rng, bool suspended)
+ }
+ }
+ if (list_empty(&rng_list))
+- unregister_miscdev(suspended);
++ unregister_miscdev();
+
+ mutex_unlock(&rng_mutex);
+ }
+-EXPORT_SYMBOL_GPL(__hwrng_unregister);
++EXPORT_SYMBOL_GPL(hwrng_unregister);
+
+
+ MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
+diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
+index 7e31995..51738bd 100644
+--- a/drivers/char/hw_random/omap-rng.c
++++ b/drivers/char/hw_random/omap-rng.c
+@@ -1,7 +1,5 @@
+ /*
+- * drivers/char/hw_random/omap-rng.c
+- *
+- * RNG driver for TI OMAP CPU family
++ * omap-rng.c - RNG driver for TI OMAP CPU family
+ *
+ * Author: Deepak Saxena <dsaxena at plexity.net>
+ *
+@@ -15,11 +13,6 @@
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+- *
+- * TODO:
+- *
+- * - Make status updated be interrupt driven so we don't poll
+- *
+ */
+
+ #include <linux/module.h>
+@@ -55,17 +48,16 @@ static void __iomem *rng_base;
+ static struct clk *rng_ick;
+ static struct platform_device *rng_dev;
+
+-static u32 omap_rng_read_reg(int reg)
++static inline u32 omap_rng_read_reg(int reg)
+ {
+ return __raw_readl(rng_base + reg);
+ }
+
+-static void omap_rng_write_reg(int reg, u32 val)
++static inline void omap_rng_write_reg(int reg, u32 val)
+ {
+ __raw_writel(val, rng_base + reg);
+ }
+
+-/* REVISIT: Does the status bit really work on 16xx? */
+ static int omap_rng_data_present(struct hwrng *rng, int wait)
+ {
+ int data, i;
+@@ -74,6 +66,11 @@ static int omap_rng_data_present(struct hwrng *rng, int wait)
+ data = omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
+ if (data || !wait)
+ break;
++ /* RNG produces data fast enough (2+ MBit/sec, even
++ * during "rngtest" loads, that these delays don't
++ * seem to trigger. We *could* use the RNG IRQ, but
++ * that'd be higher overhead ... so why bother?
++ */
+ udelay(10);
+ }
+ return data;
+@@ -101,7 +98,8 @@ static int __init omap_rng_probe(struct platform_device *pdev)
+ * A bit ugly, and it will never actually happen but there can
+ * be only one RNG and this catches any bork
+ */
+- BUG_ON(rng_dev);
++ if (rng_dev)
++ return -EBUSY;
+
+ if (cpu_is_omap24xx()) {
+ rng_ick = clk_get(NULL, "rng_ick");
+@@ -124,7 +122,7 @@ static int __init omap_rng_probe(struct platform_device *pdev)
+ return -EBUSY;
+
+ dev_set_drvdata(&pdev->dev, mem);
+- rng_base = (u32 __iomem *)io_p2v(res->start);
++ rng_base = (u32 __force __iomem *)io_p2v(res->start);
+
+ ret = hwrng_register(&omap_rng_ops);
+ if (ret) {
+@@ -182,6 +180,8 @@ static int omap_rng_resume(struct platform_device *pdev)
+
+ #endif
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:omap_rng");
+
+ static struct platform_driver omap_rng_driver = {
+ .driver = {
+diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
+index 8609b82..f49037b 100644
+--- a/drivers/char/i8k.c
++++ b/drivers/char/i8k.c
+@@ -82,6 +82,7 @@ static int i8k_ioctl(struct inode *, struct file *, unsigned int,
+ unsigned long);
+
+ static const struct file_operations i8k_fops = {
++ .owner = THIS_MODULE,
+ .open = i8k_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -554,13 +555,10 @@ static int __init i8k_init(void)
+ return -ENODEV;
+
+ /* Register the proc entry */
+- proc_i8k = create_proc_entry("i8k", 0, NULL);
++ proc_i8k = proc_create("i8k", 0, NULL, &i8k_fops);
+ if (!proc_i8k)
+ return -ENOENT;
+
+- proc_i8k->proc_fops = &i8k_fops;
+- proc_i8k->owner = THIS_MODULE;
+-
+ printk(KERN_INFO
+ "Dell laptop SMM driver v%s Massimo Dal Zotto (dz at debian.org)\n",
+ I8K_VERSION);
+diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile
+index 553f0a4..eb8a1a8 100644
+--- a/drivers/char/ipmi/Makefile
++++ b/drivers/char/ipmi/Makefile
+@@ -9,7 +9,3 @@ obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o
+ obj-$(CONFIG_IPMI_SI) += ipmi_si.o
+ obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
+ obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o
+-
+-ipmi_si.o: $(ipmi_si-objs)
+- $(LD) -r -o $@ $(ipmi_si-objs)
+-
+diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c
+index e736119..7b98c06 100644
+--- a/drivers/char/ipmi/ipmi_bt_sm.c
++++ b/drivers/char/ipmi/ipmi_bt_sm.c
+@@ -37,26 +37,32 @@
+ #define BT_DEBUG_ENABLE 1 /* Generic messages */
+ #define BT_DEBUG_MSG 2 /* Prints all request/response buffers */
+ #define BT_DEBUG_STATES 4 /* Verbose look at state changes */
+-/* BT_DEBUG_OFF must be zero to correspond to the default uninitialized
+- value */
++/*
++ * BT_DEBUG_OFF must be zero to correspond to the default uninitialized
++ * value
++ */
+
+ static int bt_debug; /* 0 == BT_DEBUG_OFF */
+
+ module_param(bt_debug, int, 0644);
+ MODULE_PARM_DESC(bt_debug, "debug bitmask, 1=enable, 2=messages, 4=states");
+
+-/* Typical "Get BT Capabilities" values are 2-3 retries, 5-10 seconds,
+- and 64 byte buffers. However, one HP implementation wants 255 bytes of
+- buffer (with a documented message of 160 bytes) so go for the max.
+- Since the Open IPMI architecture is single-message oriented at this
+- stage, the queue depth of BT is of no concern. */
++/*
++ * Typical "Get BT Capabilities" values are 2-3 retries, 5-10 seconds,
++ * and 64 byte buffers. However, one HP implementation wants 255 bytes of
++ * buffer (with a documented message of 160 bytes) so go for the max.
++ * Since the Open IPMI architecture is single-message oriented at this
++ * stage, the queue depth of BT is of no concern.
++ */
+
+ #define BT_NORMAL_TIMEOUT 5 /* seconds */
+ #define BT_NORMAL_RETRY_LIMIT 2
+ #define BT_RESET_DELAY 6 /* seconds after warm reset */
+
+-/* States are written in chronological order and usually cover
+- multiple rows of the state table discussion in the IPMI spec. */
++/*
++ * States are written in chronological order and usually cover
++ * multiple rows of the state table discussion in the IPMI spec.
++ */
+
+ enum bt_states {
+ BT_STATE_IDLE = 0, /* Order is critical in this list */
+@@ -76,10 +82,12 @@ enum bt_states {
+ BT_STATE_LONG_BUSY /* BT doesn't get hosed :-) */
+ };
+
+-/* Macros seen at the end of state "case" blocks. They help with legibility
+- and debugging. */
++/*
++ * Macros seen at the end of state "case" blocks. They help with legibility
++ * and debugging.
++ */
+
+-#define BT_STATE_CHANGE(X,Y) { bt->state = X; return Y; }
++#define BT_STATE_CHANGE(X, Y) { bt->state = X; return Y; }
+
+ #define BT_SI_SM_RETURN(Y) { last_printed = BT_STATE_PRINTME; return Y; }
+
+@@ -110,11 +118,13 @@ struct si_sm_data {
+ #define BT_H_BUSY 0x40
+ #define BT_B_BUSY 0x80
+
+-/* Some bits are toggled on each write: write once to set it, once
+- more to clear it; writing a zero does nothing. To absolutely
+- clear it, check its state and write if set. This avoids the "get
+- current then use as mask" scheme to modify one bit. Note that the
+- variable "bt" is hardcoded into these macros. */
++/*
++ * Some bits are toggled on each write: write once to set it, once
++ * more to clear it; writing a zero does nothing. To absolutely
++ * clear it, check its state and write if set. This avoids the "get
++ * current then use as mask" scheme to modify one bit. Note that the
++ * variable "bt" is hardcoded into these macros.
++ */
+
+ #define BT_STATUS bt->io->inputb(bt->io, 0)
+ #define BT_CONTROL(x) bt->io->outputb(bt->io, 0, x)
+@@ -125,8 +135,10 @@ struct si_sm_data {
+ #define BT_INTMASK_R bt->io->inputb(bt->io, 2)
+ #define BT_INTMASK_W(x) bt->io->outputb(bt->io, 2, x)
+
+-/* Convenience routines for debugging. These are not multi-open safe!
+- Note the macros have hardcoded variables in them. */
++/*
++ * Convenience routines for debugging. These are not multi-open safe!
++ * Note the macros have hardcoded variables in them.
++ */
+
+ static char *state2txt(unsigned char state)
+ {
+@@ -182,7 +194,8 @@ static char *status2txt(unsigned char status)
+ static unsigned int bt_init_data(struct si_sm_data *bt, struct si_sm_io *io)
+ {
+ memset(bt, 0, sizeof(struct si_sm_data));
+- if (bt->io != io) { /* external: one-time only things */
++ if (bt->io != io) {
++ /* external: one-time only things */
+ bt->io = io;
+ bt->seq = 0;
+ }
+@@ -229,7 +242,7 @@ static int bt_start_transaction(struct si_sm_data *bt,
+ printk(KERN_WARNING "BT: +++++++++++++++++ New command\n");
+ printk(KERN_WARNING "BT: NetFn/LUN CMD [%d data]:", size - 2);
+ for (i = 0; i < size; i ++)
+- printk (" %02x", data[i]);
++ printk(" %02x", data[i]);
+ printk("\n");
+ }
+ bt->write_data[0] = size + 1; /* all data plus seq byte */
+@@ -246,8 +259,10 @@ static int bt_start_transaction(struct si_sm_data *bt,
+ return 0;
+ }
+
+-/* After the upper state machine has been told SI_SM_TRANSACTION_COMPLETE
+- it calls this. Strip out the length and seq bytes. */
++/*
++ * After the upper state machine has been told SI_SM_TRANSACTION_COMPLETE
++ * it calls this. Strip out the length and seq bytes.
++ */
+
+ static int bt_get_result(struct si_sm_data *bt,
+ unsigned char *data,
+@@ -269,10 +284,10 @@ static int bt_get_result(struct si_sm_data *bt,
+ memcpy(data + 2, bt->read_data + 4, msg_len - 2);
+
+ if (bt_debug & BT_DEBUG_MSG) {
+- printk (KERN_WARNING "BT: result %d bytes:", msg_len);
++ printk(KERN_WARNING "BT: result %d bytes:", msg_len);
+ for (i = 0; i < msg_len; i++)
+ printk(" %02x", data[i]);
+- printk ("\n");
++ printk("\n");
+ }
+ return msg_len;
+ }
+@@ -292,8 +307,10 @@ static void reset_flags(struct si_sm_data *bt)
+ BT_INTMASK_W(BT_BMC_HWRST);
+ }
+
+-/* Get rid of an unwanted/stale response. This should only be needed for
+- BMCs that support multiple outstanding requests. */
++/*
++ * Get rid of an unwanted/stale response. This should only be needed for
++ * BMCs that support multiple outstanding requests.
++ */
+
+ static void drain_BMC2HOST(struct si_sm_data *bt)
+ {
+@@ -326,8 +343,8 @@ static inline void write_all_bytes(struct si_sm_data *bt)
+ printk(KERN_WARNING "BT: write %d bytes seq=0x%02X",
+ bt->write_count, bt->seq);
+ for (i = 0; i < bt->write_count; i++)
+- printk (" %02x", bt->write_data[i]);
+- printk ("\n");
++ printk(" %02x", bt->write_data[i]);
++ printk("\n");
+ }
+ for (i = 0; i < bt->write_count; i++)
+ HOST2BMC(bt->write_data[i]);
+@@ -337,8 +354,10 @@ static inline int read_all_bytes(struct si_sm_data *bt)
+ {
+ unsigned char i;
+
+- /* length is "framing info", minimum = 4: NetFn, Seq, Cmd, cCode.
+- Keep layout of first four bytes aligned with write_data[] */
++ /*
++ * length is "framing info", minimum = 4: NetFn, Seq, Cmd, cCode.
++ * Keep layout of first four bytes aligned with write_data[]
++ */
+
+ bt->read_data[0] = BMC2HOST;
+ bt->read_count = bt->read_data[0];
+@@ -362,8 +381,8 @@ static inline int read_all_bytes(struct si_sm_data *bt)
+ if (max > 16)
+ max = 16;
+ for (i = 0; i < max; i++)
+- printk (" %02x", bt->read_data[i]);
+- printk ("%s\n", bt->read_count == max ? "" : " ...");
++ printk(KERN_CONT " %02x", bt->read_data[i]);
++ printk(KERN_CONT "%s\n", bt->read_count == max ? "" : " ...");
+ }
+
+ /* per the spec, the (NetFn[1], Seq[2], Cmd[3]) tuples must match */
+@@ -402,8 +421,10 @@ static enum si_sm_result error_recovery(struct si_sm_data *bt,
+ printk(KERN_WARNING "IPMI BT: %s in %s %s ", /* open-ended line */
+ reason, STATE2TXT, STATUS2TXT);
+
+- /* Per the IPMI spec, retries are based on the sequence number
+- known only to this module, so manage a restart here. */
++ /*
++ * Per the IPMI spec, retries are based on the sequence number
++ * known only to this module, so manage a restart here.
++ */
+ (bt->error_retries)++;
+ if (bt->error_retries < bt->BT_CAP_retries) {
+ printk("%d retries left\n",
+@@ -412,8 +433,8 @@ static enum si_sm_result error_recovery(struct si_sm_data *bt,
+ return SI_SM_CALL_WITHOUT_DELAY;
+ }
+
+- printk("failed %d retries, sending error response\n",
+- bt->BT_CAP_retries);
++ printk(KERN_WARNING "failed %d retries, sending error response\n",
++ bt->BT_CAP_retries);
+ if (!bt->nonzero_status)
+ printk(KERN_ERR "IPMI BT: stuck, try power cycle\n");
+
+@@ -424,8 +445,10 @@ static enum si_sm_result error_recovery(struct si_sm_data *bt,
+ return SI_SM_CALL_WITHOUT_DELAY;
+ }
+
+- /* Concoct a useful error message, set up the next state, and
+- be done with this sequence. */
++ /*
++ * Concoct a useful error message, set up the next state, and
++ * be done with this sequence.
++ */
+
+ bt->state = BT_STATE_IDLE;
+ switch (cCode) {
+@@ -461,10 +484,12 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
+ last_printed = bt->state;
+ }
+
+- /* Commands that time out may still (eventually) provide a response.
+- This stale response will get in the way of a new response so remove
+- it if possible (hopefully during IDLE). Even if it comes up later
+- it will be rejected by its (now-forgotten) seq number. */
++ /*
++ * Commands that time out may still (eventually) provide a response.
++ * This stale response will get in the way of a new response so remove
++ * it if possible (hopefully during IDLE). Even if it comes up later
++ * it will be rejected by its (now-forgotten) seq number.
++ */
+
+ if ((bt->state < BT_STATE_WRITE_BYTES) && (status & BT_B2H_ATN)) {
+ drain_BMC2HOST(bt);
+@@ -472,7 +497,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
+ }
+
+ if ((bt->state != BT_STATE_IDLE) &&
+- (bt->state < BT_STATE_PRINTME)) { /* check timeout */
++ (bt->state < BT_STATE_PRINTME)) {
++ /* check timeout */
+ bt->timeout -= time;
+ if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1))
+ return error_recovery(bt,
+@@ -482,8 +508,10 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
+
+ switch (bt->state) {
+
+- /* Idle state first checks for asynchronous messages from another
+- channel, then does some opportunistic housekeeping. */
++ /*
++ * Idle state first checks for asynchronous messages from another
++ * channel, then does some opportunistic housekeeping.
++ */
+
+ case BT_STATE_IDLE:
+ if (status & BT_SMS_ATN) {
+@@ -531,16 +559,19 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
+ BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY);
+ BT_CONTROL(BT_H_BUSY); /* set */
+
+- /* Uncached, ordered writes should just proceeed serially but
+- some BMCs don't clear B2H_ATN with one hit. Fast-path a
+- workaround without too much penalty to the general case. */
++ /*
++ * Uncached, ordered writes should just proceeed serially but
++ * some BMCs don't clear B2H_ATN with one hit. Fast-path a
++ * workaround without too much penalty to the general case.
++ */
+
+ BT_CONTROL(BT_B2H_ATN); /* clear it to ACK the BMC */
+ BT_STATE_CHANGE(BT_STATE_CLEAR_B2H,
+ SI_SM_CALL_WITHOUT_DELAY);
+
+ case BT_STATE_CLEAR_B2H:
+- if (status & BT_B2H_ATN) { /* keep hitting it */
++ if (status & BT_B2H_ATN) {
++ /* keep hitting it */
+ BT_CONTROL(BT_B2H_ATN);
+ BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY);
+ }
+@@ -548,7 +579,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
+ SI_SM_CALL_WITHOUT_DELAY);
+
+ case BT_STATE_READ_BYTES:
+- if (!(status & BT_H_BUSY)) /* check in case of retry */
++ if (!(status & BT_H_BUSY))
++ /* check in case of retry */
+ BT_CONTROL(BT_H_BUSY);
+ BT_CONTROL(BT_CLR_RD_PTR); /* start of BMC2HOST buffer */
+ i = read_all_bytes(bt); /* true == packet seq match */
+@@ -599,8 +631,10 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
+ BT_STATE_CHANGE(BT_STATE_XACTION_START,
+ SI_SM_CALL_WITH_DELAY);
+
+- /* Get BT Capabilities, using timing of upper level state machine.
+- Set outreqs to prevent infinite loop on timeout. */
++ /*
++ * Get BT Capabilities, using timing of upper level state machine.
++ * Set outreqs to prevent infinite loop on timeout.
++ */
+ case BT_STATE_CAPABILITIES_BEGIN:
+ bt->BT_CAP_outreqs = 1;
+ {
+@@ -638,10 +672,12 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
+
+ static int bt_detect(struct si_sm_data *bt)
+ {
+- /* It's impossible for the BT status and interrupt registers to be
+- all 1's, (assuming a properly functioning, self-initialized BMC)
+- but that's what you get from reading a bogus address, so we
+- test that first. The calling routine uses negative logic. */
++ /*
++ * It's impossible for the BT status and interrupt registers to be
++ * all 1's, (assuming a properly functioning, self-initialized BMC)
++ * but that's what you get from reading a bogus address, so we
++ * test that first. The calling routine uses negative logic.
++ */
+
+ if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF))
+ return 1;
+@@ -658,8 +694,7 @@ static int bt_size(void)
+ return sizeof(struct si_sm_data);
+ }
+
+-struct si_sm_handlers bt_smi_handlers =
+-{
++struct si_sm_handlers bt_smi_handlers = {
+ .init_data = bt_init_data,
+ .start_transaction = bt_start_transaction,
+ .get_result = bt_get_result,
+diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c
+index c1b8228..8070487 100644
+--- a/drivers/char/ipmi/ipmi_kcs_sm.c
++++ b/drivers/char/ipmi/ipmi_kcs_sm.c
+@@ -60,37 +60,58 @@ MODULE_PARM_DESC(kcs_debug, "debug bitmask, 1=enable, 2=messages, 4=states");
+
+ /* The states the KCS driver may be in. */
+ enum kcs_states {
+- KCS_IDLE, /* The KCS interface is currently
+- doing nothing. */
+- KCS_START_OP, /* We are starting an operation. The
+- data is in the output buffer, but
+- nothing has been done to the
+- interface yet. This was added to
+- the state machine in the spec to
+- wait for the initial IBF. */
+- KCS_WAIT_WRITE_START, /* We have written a write cmd to the
+- interface. */
+- KCS_WAIT_WRITE, /* We are writing bytes to the
+- interface. */
+- KCS_WAIT_WRITE_END, /* We have written the write end cmd
+- to the interface, and still need to
+- write the last byte. */
+- KCS_WAIT_READ, /* We are waiting to read data from
+- the interface. */
+- KCS_ERROR0, /* State to transition to the error
+- handler, this was added to the
+- state machine in the spec to be
+- sure IBF was there. */
+- KCS_ERROR1, /* First stage error handler, wait for
+- the interface to respond. */
+- KCS_ERROR2, /* The abort cmd has been written,
+- wait for the interface to
+- respond. */
+- KCS_ERROR3, /* We wrote some data to the
+- interface, wait for it to switch to
+- read mode. */
+- KCS_HOSED /* The hardware failed to follow the
+- state machine. */
++ /* The KCS interface is currently doing nothing. */
++ KCS_IDLE,
++
++ /*
++ * We are starting an operation. The data is in the output
++ * buffer, but nothing has been done to the interface yet. This
++ * was added to the state machine in the spec to wait for the
++ * initial IBF.
++ */
++ KCS_START_OP,
++
++ /* We have written a write cmd to the interface. */
++ KCS_WAIT_WRITE_START,
++
++ /* We are writing bytes to the interface. */
++ KCS_WAIT_WRITE,
++
++ /*
++ * We have written the write end cmd to the interface, and
++ * still need to write the last byte.
++ */
++ KCS_WAIT_WRITE_END,
++
++ /* We are waiting to read data from the interface. */
++ KCS_WAIT_READ,
++
++ /*
++ * State to transition to the error handler, this was added to
++ * the state machine in the spec to be sure IBF was there.
++ */
++ KCS_ERROR0,
++
++ /*
++ * First stage error handler, wait for the interface to
++ * respond.
++ */
++ KCS_ERROR1,
++
++ /*
++ * The abort cmd has been written, wait for the interface to
++ * respond.
++ */
++ KCS_ERROR2,
++
++ /*
++ * We wrote some data to the interface, wait for it to switch
++ * to read mode.
++ */
++ KCS_ERROR3,
++
++ /* The hardware failed to follow the state machine. */
++ KCS_HOSED
+ };
+
+ #define MAX_KCS_READ_SIZE IPMI_MAX_MSG_LENGTH
+@@ -102,8 +123,7 @@ enum kcs_states {
+ #define MAX_ERROR_RETRIES 10
+ #define ERROR0_OBF_WAIT_JIFFIES (2*HZ)
+
+-struct si_sm_data
+-{
++struct si_sm_data {
+ enum kcs_states state;
+ struct si_sm_io *io;
+ unsigned char write_data[MAX_KCS_WRITE_SIZE];
+@@ -187,7 +207,8 @@ static inline void start_error_recovery(struct si_sm_data *kcs, char *reason)
+ (kcs->error_retries)++;
+ if (kcs->error_retries > MAX_ERROR_RETRIES) {
+ if (kcs_debug & KCS_DEBUG_ENABLE)
+- printk(KERN_DEBUG "ipmi_kcs_sm: kcs hosed: %s\n", reason);
++ printk(KERN_DEBUG "ipmi_kcs_sm: kcs hosed: %s\n",
++ reason);
+ kcs->state = KCS_HOSED;
+ } else {
+ kcs->error0_timeout = jiffies + ERROR0_OBF_WAIT_JIFFIES;
+@@ -271,10 +292,9 @@ static int start_kcs_transaction(struct si_sm_data *kcs, unsigned char *data,
+
+ if (kcs_debug & KCS_DEBUG_MSG) {
+ printk(KERN_DEBUG "start_kcs_transaction -");
+- for (i = 0; i < size; i ++) {
++ for (i = 0; i < size; i++)
+ printk(" %02x", (unsigned char) (data [i]));
+- }
+- printk ("\n");
++ printk("\n");
+ }
+ kcs->error_retries = 0;
+ memcpy(kcs->write_data, data, size);
+@@ -305,9 +325,11 @@ static int get_kcs_result(struct si_sm_data *kcs, unsigned char *data,
+ kcs->read_pos = 3;
+ }
+ if (kcs->truncated) {
+- /* Report a truncated error. We might overwrite
+- another error, but that's too bad, the user needs
+- to know it was truncated. */
++ /*
++ * Report a truncated error. We might overwrite
++ * another error, but that's too bad, the user needs
++ * to know it was truncated.
++ */
+ data[2] = IPMI_ERR_MSG_TRUNCATED;
+ kcs->truncated = 0;
+ }
+@@ -315,9 +337,11 @@ static int get_kcs_result(struct si_sm_data *kcs, unsigned char *data,
+ return kcs->read_pos;
+ }
+
+-/* This implements the state machine defined in the IPMI manual, see
+- that for details on how this works. Divide that flowchart into
+- sections delimited by "Wait for IBF" and this will become clear. */
++/*
++ * This implements the state machine defined in the IPMI manual, see
++ * that for details on how this works. Divide that flowchart into
++ * sections delimited by "Wait for IBF" and this will become clear.
++ */
+ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
+ {
+ unsigned char status;
+@@ -388,11 +412,12 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
+ write_next_byte(kcs);
+ }
+ break;
+-
++
+ case KCS_WAIT_WRITE_END:
+ if (state != KCS_WRITE_STATE) {
+ start_error_recovery(kcs,
+- "Not in write state for write end");
++ "Not in write state"
++ " for write end");
+ break;
+ }
+ clear_obf(kcs, status);
+@@ -413,13 +438,15 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
+ return SI_SM_CALL_WITH_DELAY;
+ read_next_byte(kcs);
+ } else {
+- /* We don't implement this exactly like the state
+- machine in the spec. Some broken hardware
+- does not write the final dummy byte to the
+- read register. Thus obf will never go high
+- here. We just go straight to idle, and we
+- handle clearing out obf in idle state if it
+- happens to come in. */
++ /*
++ * We don't implement this exactly like the state
++ * machine in the spec. Some broken hardware
++ * does not write the final dummy byte to the
++ * read register. Thus obf will never go high
++ * here. We just go straight to idle, and we
++ * handle clearing out obf in idle state if it
++ * happens to come in.
++ */
+ clear_obf(kcs, status);
+ kcs->orig_write_count = 0;
+ kcs->state = KCS_IDLE;
+@@ -430,7 +457,8 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
+ case KCS_ERROR0:
+ clear_obf(kcs, status);
+ status = read_status(kcs);
+- if (GET_STATUS_OBF(status)) /* controller isn't responding */
++ if (GET_STATUS_OBF(status))
++ /* controller isn't responding */
+ if (time_before(jiffies, kcs->error0_timeout))
+ return SI_SM_CALL_WITH_TICK_DELAY;
+ write_cmd(kcs, KCS_GET_STATUS_ABORT);
+@@ -442,7 +470,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
+ write_data(kcs, 0);
+ kcs->state = KCS_ERROR2;
+ break;
+-
++
+ case KCS_ERROR2:
+ if (state != KCS_READ_STATE) {
+ start_error_recovery(kcs,
+@@ -456,7 +484,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
+ write_data(kcs, KCS_READ_BYTE);
+ kcs->state = KCS_ERROR3;
+ break;
+-
++
+ case KCS_ERROR3:
+ if (state != KCS_IDLE_STATE) {
+ start_error_recovery(kcs,
+@@ -475,7 +503,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
+ return SI_SM_TRANSACTION_COMPLETE;
+ }
+ break;
+-
++
+ case KCS_HOSED:
+ break;
+ }
+@@ -495,10 +523,12 @@ static int kcs_size(void)
+
+ static int kcs_detect(struct si_sm_data *kcs)
+ {
+- /* It's impossible for the KCS status register to be all 1's,
+- (assuming a properly functioning, self-initialized BMC)
+- but that's what you get from reading a bogus address, so we
+- test that first. */
++ /*
++ * It's impossible for the KCS status register to be all 1's,
++ * (assuming a properly functioning, self-initialized BMC)
++ * but that's what you get from reading a bogus address, so we
++ * test that first.
++ */
+ if (read_status(kcs) == 0xff)
+ return 1;
+
+@@ -509,8 +539,7 @@ static void kcs_cleanup(struct si_sm_data *kcs)
+ {
+ }
+
+-struct si_sm_handlers kcs_smi_handlers =
+-{
++struct si_sm_handlers kcs_smi_handlers = {
+ .init_data = init_kcs_data,
+ .start_transaction = start_kcs_transaction,
+ .get_result = get_kcs_result,
+diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
+index 32b2b22..8a59aaa 100644
+--- a/drivers/char/ipmi/ipmi_msghandler.c
++++ b/drivers/char/ipmi/ipmi_msghandler.c
+@@ -47,7 +47,7 @@
+
+ #define PFX "IPMI message handler: "
+
+-#define IPMI_DRIVER_VERSION "39.1"
++#define IPMI_DRIVER_VERSION "39.2"
+
+ static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
+ static int ipmi_init_msghandler(void);
+@@ -63,16 +63,16 @@ static struct proc_dir_entry *proc_ipmi_root;
+
+ #define MAX_EVENTS_IN_QUEUE 25
+
+-/* Don't let a message sit in a queue forever, always time it with at lest
+- the max message timer. This is in milliseconds. */
++/*
++ * Don't let a message sit in a queue forever, always time it with at lest
++ * the max message timer. This is in milliseconds.
++ */
+ #define MAX_MSG_TIMEOUT 60000
+
+-
+ /*
+ * The main "user" data structure.
+ */
+-struct ipmi_user
+-{
++struct ipmi_user {
+ struct list_head link;
+
+ /* Set to "0" when the user is destroyed. */
+@@ -91,8 +91,7 @@ struct ipmi_user
+ int gets_events;
+ };
+
+-struct cmd_rcvr
+-{
++struct cmd_rcvr {
+ struct list_head link;
+
+ ipmi_user_t user;
+@@ -106,12 +105,12 @@ struct cmd_rcvr
+ * or change any data until the RCU period completes. So we
+ * use this next variable during mass deletion so we can have
+ * a list and don't have to wait and restart the search on
+- * every individual deletion of a command. */
++ * every individual deletion of a command.
++ */
+ struct cmd_rcvr *next;
+ };
+
+-struct seq_table
+-{
++struct seq_table {
+ unsigned int inuse : 1;
+ unsigned int broadcast : 1;
+
+@@ -119,53 +118,60 @@ struct seq_table
+ unsigned long orig_timeout;
+ unsigned int retries_left;
+
+- /* To verify on an incoming send message response that this is
+- the message that the response is for, we keep a sequence id
+- and increment it every time we send a message. */
++ /*
++ * To verify on an incoming send message response that this is
++ * the message that the response is for, we keep a sequence id
++ * and increment it every time we send a message.
++ */
+ long seqid;
+
+- /* This is held so we can properly respond to the message on a
+- timeout, and it is used to hold the temporary data for
+- retransmission, too. */
++ /*
++ * This is held so we can properly respond to the message on a
++ * timeout, and it is used to hold the temporary data for
++ * retransmission, too.
++ */
+ struct ipmi_recv_msg *recv_msg;
+ };
+
+-/* Store the information in a msgid (long) to allow us to find a
+- sequence table entry from the msgid. */
++/*
++ * Store the information in a msgid (long) to allow us to find a
++ * sequence table entry from the msgid.
++ */
+ #define STORE_SEQ_IN_MSGID(seq, seqid) (((seq&0xff)<<26) | (seqid&0x3ffffff))
+
+ #define GET_SEQ_FROM_MSGID(msgid, seq, seqid) \
+ do { \
+ seq = ((msgid >> 26) & 0x3f); \
+ seqid = (msgid & 0x3fffff); \
+- } while (0)
++ } while (0)
+
+ #define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3fffff)
+
+-struct ipmi_channel
+-{
++struct ipmi_channel {
+ unsigned char medium;
+ unsigned char protocol;
+
+- /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR,
+- but may be changed by the user. */
++ /*
++ * My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR,
++ * but may be changed by the user.
++ */
+ unsigned char address;
+
+- /* My LUN. This should generally stay the SMS LUN, but just in
+- case... */
++ /*
++ * My LUN. This should generally stay the SMS LUN, but just in
++ * case...
++ */
+ unsigned char lun;
+ };
+
+ #ifdef CONFIG_PROC_FS
+-struct ipmi_proc_entry
+-{
++struct ipmi_proc_entry {
+ char *name;
+ struct ipmi_proc_entry *next;
+ };
+ #endif
+
+-struct bmc_device
+-{
++struct bmc_device {
+ struct platform_device *dev;
+ struct ipmi_device_id id;
+ unsigned char guid[16];
+@@ -186,10 +192,108 @@ struct bmc_device
+ struct device_attribute aux_firmware_rev_attr;
+ };
+
++/*
++ * Various statistics for IPMI, these index stats[] in the ipmi_smi
++ * structure.
++ */
++enum ipmi_stat_indexes {
++ /* Commands we got from the user that were invalid. */
++ IPMI_STAT_sent_invalid_commands = 0,
++
++ /* Commands we sent to the MC. */
++ IPMI_STAT_sent_local_commands,
++
++ /* Responses from the MC that were delivered to a user. */
++ IPMI_STAT_handled_local_responses,
++
++ /* Responses from the MC that were not delivered to a user. */
++ IPMI_STAT_unhandled_local_responses,
++
++ /* Commands we sent out to the IPMB bus. */
++ IPMI_STAT_sent_ipmb_commands,
++
++ /* Commands sent on the IPMB that had errors on the SEND CMD */
++ IPMI_STAT_sent_ipmb_command_errs,
++
++ /* Each retransmit increments this count. */
++ IPMI_STAT_retransmitted_ipmb_commands,
++
++ /*
++ * When a message times out (runs out of retransmits) this is
++ * incremented.
++ */
++ IPMI_STAT_timed_out_ipmb_commands,
++
++ /*
++ * This is like above, but for broadcasts. Broadcasts are
++ * *not* included in the above count (they are expected to
++ * time out).
++ */
++ IPMI_STAT_timed_out_ipmb_broadcasts,
++
++ /* Responses I have sent to the IPMB bus. */
++ IPMI_STAT_sent_ipmb_responses,
++
++ /* The response was delivered to the user. */
++ IPMI_STAT_handled_ipmb_responses,
++
++ /* The response had invalid data in it. */
++ IPMI_STAT_invalid_ipmb_responses,
++
++ /* The response didn't have anyone waiting for it. */
++ IPMI_STAT_unhandled_ipmb_responses,
++
++ /* Commands we sent out to the IPMB bus. */
++ IPMI_STAT_sent_lan_commands,
++
++ /* Commands sent on the IPMB that had errors on the SEND CMD */
++ IPMI_STAT_sent_lan_command_errs,
++
++ /* Each retransmit increments this count. */
++ IPMI_STAT_retransmitted_lan_commands,
++
++ /*
++ * When a message times out (runs out of retransmits) this is
++ * incremented.
++ */
++ IPMI_STAT_timed_out_lan_commands,
++
++ /* Responses I have sent to the IPMB bus. */
++ IPMI_STAT_sent_lan_responses,
++
++ /* The response was delivered to the user. */
++ IPMI_STAT_handled_lan_responses,
++
++ /* The response had invalid data in it. */
++ IPMI_STAT_invalid_lan_responses,
++
++ /* The response didn't have anyone waiting for it. */
++ IPMI_STAT_unhandled_lan_responses,
++
++ /* The command was delivered to the user. */
++ IPMI_STAT_handled_commands,
++
++ /* The command had invalid data in it. */
++ IPMI_STAT_invalid_commands,
++
++ /* The command didn't have anyone waiting for it. */
++ IPMI_STAT_unhandled_commands,
++
++ /* Invalid data in an event. */
++ IPMI_STAT_invalid_events,
++
++ /* Events that were received with the proper format. */
++ IPMI_STAT_events,
++
++
++ /* This *must* remain last, add new values above this. */
++ IPMI_NUM_STATS
++};
++
++
+ #define IPMI_IPMB_NUM_SEQ 64
+ #define IPMI_MAX_CHANNELS 16
+-struct ipmi_smi
+-{
++struct ipmi_smi {
+ /* What interface number are we? */
+ int intf_num;
+
+@@ -198,8 +302,10 @@ struct ipmi_smi
+ /* Used for a list of interfaces. */
+ struct list_head link;
+
+- /* The list of upper layers that are using me. seq_lock
+- * protects this. */
++ /*
++ * The list of upper layers that are using me. seq_lock
++ * protects this.
++ */
+ struct list_head users;
+
+ /* Information to supply to users. */
+@@ -213,10 +319,12 @@ struct ipmi_smi
+ char *my_dev_name;
+ char *sysfs_name;
+
+- /* This is the lower-layer's sender routine. Note that you
++ /*
++ * This is the lower-layer's sender routine. Note that you
+ * must either be holding the ipmi_interfaces_mutex or be in
+ * an umpreemptible region to use this. You must fetch the
+- * value into a local variable and make sure it is not NULL. */
++ * value into a local variable and make sure it is not NULL.
++ */
+ struct ipmi_smi_handlers *handlers;
+ void *send_info;
+
+@@ -229,34 +337,45 @@ struct ipmi_smi
+ /* Driver-model device for the system interface. */
+ struct device *si_dev;
+
+- /* A table of sequence numbers for this interface. We use the
+- sequence numbers for IPMB messages that go out of the
+- interface to match them up with their responses. A routine
+- is called periodically to time the items in this list. */
++ /*
++ * A table of sequence numbers for this interface. We use the
++ * sequence numbers for IPMB messages that go out of the
++ * interface to match them up with their responses. A routine
++ * is called periodically to time the items in this list.
++ */
+ spinlock_t seq_lock;
+ struct seq_table seq_table[IPMI_IPMB_NUM_SEQ];
+ int curr_seq;
+
+- /* Messages that were delayed for some reason (out of memory,
+- for instance), will go in here to be processed later in a
+- periodic timer interrupt. */
++ /*
++ * Messages that were delayed for some reason (out of memory,
++ * for instance), will go in here to be processed later in a
++ * periodic timer interrupt.
++ */
+ spinlock_t waiting_msgs_lock;
+ struct list_head waiting_msgs;
+
+- /* The list of command receivers that are registered for commands
+- on this interface. */
++ /*
++ * The list of command receivers that are registered for commands
++ * on this interface.
++ */
+ struct mutex cmd_rcvrs_mutex;
+ struct list_head cmd_rcvrs;
+
+- /* Events that were queues because no one was there to receive
+- them. */
++ /*
++ * Events that were queues because no one was there to receive
++ * them.
++ */
+ spinlock_t events_lock; /* For dealing with event stuff. */
+ struct list_head waiting_events;
+ unsigned int waiting_events_count; /* How many events in queue? */
+- int delivering_events;
++ char delivering_events;
++ char event_msg_printed;
+
+- /* The event receiver for my BMC, only really used at panic
+- shutdown as a place to store this. */
++ /*
++ * The event receiver for my BMC, only really used at panic
++ * shutdown as a place to store this.
++ */
+ unsigned char event_receiver;
+ unsigned char event_receiver_lun;
+ unsigned char local_sel_device;
+@@ -268,14 +387,18 @@ struct ipmi_smi
+ int auto_maintenance_timeout;
+ spinlock_t maintenance_mode_lock; /* Used in a timer... */
+
+- /* A cheap hack, if this is non-null and a message to an
+- interface comes in with a NULL user, call this routine with
+- it. Note that the message will still be freed by the
+- caller. This only works on the system interface. */
++ /*
++ * A cheap hack, if this is non-null and a message to an
++ * interface comes in with a NULL user, call this routine with
++ * it. Note that the message will still be freed by the
++ * caller. This only works on the system interface.
++ */
+ void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_recv_msg *msg);
+
+- /* When we are scanning the channels for an SMI, this will
+- tell which channel we are scanning. */
++ /*
++ * When we are scanning the channels for an SMI, this will
++ * tell which channel we are scanning.
++ */
+ int curr_channel;
+
+ /* Channel information */
+@@ -285,74 +408,14 @@ struct ipmi_smi
+ struct proc_dir_entry *proc_dir;
+ char proc_dir_name[10];
+
+- spinlock_t counter_lock; /* For making counters atomic. */
+-
+- /* Commands we got that were invalid. */
+- unsigned int sent_invalid_commands;
+-
+- /* Commands we sent to the MC. */
+- unsigned int sent_local_commands;
+- /* Responses from the MC that were delivered to a user. */
+- unsigned int handled_local_responses;
+- /* Responses from the MC that were not delivered to a user. */
+- unsigned int unhandled_local_responses;
+-
+- /* Commands we sent out to the IPMB bus. */
+- unsigned int sent_ipmb_commands;
+- /* Commands sent on the IPMB that had errors on the SEND CMD */
+- unsigned int sent_ipmb_command_errs;
+- /* Each retransmit increments this count. */
+- unsigned int retransmitted_ipmb_commands;
+- /* When a message times out (runs out of retransmits) this is
+- incremented. */
+- unsigned int timed_out_ipmb_commands;
+-
+- /* This is like above, but for broadcasts. Broadcasts are
+- *not* included in the above count (they are expected to
+- time out). */
+- unsigned int timed_out_ipmb_broadcasts;
++ atomic_t stats[IPMI_NUM_STATS];
+
+- /* Responses I have sent to the IPMB bus. */
+- unsigned int sent_ipmb_responses;
+-
+- /* The response was delivered to the user. */
+- unsigned int handled_ipmb_responses;
+- /* The response had invalid data in it. */
+- unsigned int invalid_ipmb_responses;
+- /* The response didn't have anyone waiting for it. */
+- unsigned int unhandled_ipmb_responses;
+-
+- /* Commands we sent out to the IPMB bus. */
+- unsigned int sent_lan_commands;
+- /* Commands sent on the IPMB that had errors on the SEND CMD */
+- unsigned int sent_lan_command_errs;
+- /* Each retransmit increments this count. */
+- unsigned int retransmitted_lan_commands;
+- /* When a message times out (runs out of retransmits) this is
+- incremented. */
+- unsigned int timed_out_lan_commands;
+-
+- /* Responses I have sent to the IPMB bus. */
+- unsigned int sent_lan_responses;
+-
+- /* The response was delivered to the user. */
+- unsigned int handled_lan_responses;
+- /* The response had invalid data in it. */
+- unsigned int invalid_lan_responses;
+- /* The response didn't have anyone waiting for it. */
+- unsigned int unhandled_lan_responses;
+-
+- /* The command was delivered to the user. */
+- unsigned int handled_commands;
+- /* The command had invalid data in it. */
+- unsigned int invalid_commands;
+- /* The command didn't have anyone waiting for it. */
+- unsigned int unhandled_commands;
+-
+- /* Invalid data in an event. */
+- unsigned int invalid_events;
+- /* Events that were received with the proper format. */
+- unsigned int events;
++ /*
++ * run_to_completion duplicate of smb_info, smi_info
++ * and ipmi_serial_info structures. Used to decrease numbers of
++ * parameters passed by "low" level IPMI code.
++ */
++ int run_to_completion;
+ };
+ #define to_si_intf_from_dev(device) container_of(device, struct ipmi_smi, dev)
+
+@@ -368,12 +431,19 @@ static DEFINE_MUTEX(ipmidriver_mutex);
+ static LIST_HEAD(ipmi_interfaces);
+ static DEFINE_MUTEX(ipmi_interfaces_mutex);
+
+-/* List of watchers that want to know when smi's are added and
+- deleted. */
++/*
++ * List of watchers that want to know when smi's are added and deleted.
++ */
+ static LIST_HEAD(smi_watchers);
+ static DEFINE_MUTEX(smi_watchers_mutex);
+
+
++#define ipmi_inc_stat(intf, stat) \
++ atomic_inc(&(intf)->stats[IPMI_STAT_ ## stat])
++#define ipmi_get_stat(intf, stat) \
++ ((unsigned int) atomic_read(&(intf)->stats[IPMI_STAT_ ## stat]))
++
++
+ static void free_recv_msg_list(struct list_head *q)
+ {
+ struct ipmi_recv_msg *msg, *msg2;
+@@ -417,10 +487,8 @@ static void clean_up_interface_data(ipmi_smi_t intf)
+
+ for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
+ if ((intf->seq_table[i].inuse)
+- && (intf->seq_table[i].recv_msg))
+- {
++ && (intf->seq_table[i].recv_msg))
+ ipmi_free_recv_msg(intf->seq_table[i].recv_msg);
+- }
+ }
+ }
+
+@@ -487,6 +555,7 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
+ }
+ return -ENOMEM;
+ }
++EXPORT_SYMBOL(ipmi_smi_watcher_register);
+
+ int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher)
+ {
+@@ -495,6 +564,7 @@ int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher)
+ mutex_unlock(&smi_watchers_mutex);
+ return 0;
+ }
++EXPORT_SYMBOL(ipmi_smi_watcher_unregister);
+
+ /*
+ * Must be called with smi_watchers_mutex held.
+@@ -530,8 +600,7 @@ ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2)
+ }
+
+ if ((addr1->addr_type == IPMI_IPMB_ADDR_TYPE)
+- || (addr1->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
+- {
++ || (addr1->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) {
+ struct ipmi_ipmb_addr *ipmb_addr1
+ = (struct ipmi_ipmb_addr *) addr1;
+ struct ipmi_ipmb_addr *ipmb_addr2
+@@ -559,9 +628,8 @@ ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2)
+
+ int ipmi_validate_addr(struct ipmi_addr *addr, int len)
+ {
+- if (len < sizeof(struct ipmi_system_interface_addr)) {
++ if (len < sizeof(struct ipmi_system_interface_addr))
+ return -EINVAL;
+- }
+
+ if (addr->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {
+ if (addr->channel != IPMI_BMC_CHANNEL)
+@@ -575,23 +643,21 @@ int ipmi_validate_addr(struct ipmi_addr *addr, int len)
+ return -EINVAL;
+
+ if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE)
+- || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
+- {
+- if (len < sizeof(struct ipmi_ipmb_addr)) {
++ || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) {
++ if (len < sizeof(struct ipmi_ipmb_addr))
+ return -EINVAL;
+- }
+ return 0;
+ }
+
+ if (addr->addr_type == IPMI_LAN_ADDR_TYPE) {
+- if (len < sizeof(struct ipmi_lan_addr)) {
++ if (len < sizeof(struct ipmi_lan_addr))
+ return -EINVAL;
+- }
+ return 0;
+ }
+
+ return -EINVAL;
+ }
++EXPORT_SYMBOL(ipmi_validate_addr);
+
+ unsigned int ipmi_addr_length(int addr_type)
+ {
+@@ -599,34 +665,28 @@ unsigned int ipmi_addr_length(int addr_type)
+ return sizeof(struct ipmi_system_interface_addr);
+
+ if ((addr_type == IPMI_IPMB_ADDR_TYPE)
+- || (addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
+- {
++ || (addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
+ return sizeof(struct ipmi_ipmb_addr);
+- }
+
+ if (addr_type == IPMI_LAN_ADDR_TYPE)
+ return sizeof(struct ipmi_lan_addr);
+
+ return 0;
+ }
++EXPORT_SYMBOL(ipmi_addr_length);
+
+ static void deliver_response(struct ipmi_recv_msg *msg)
+ {
+ if (!msg->user) {
+ ipmi_smi_t intf = msg->user_msg_data;
+- unsigned long flags;
+
+ /* Special handling for NULL users. */
+ if (intf->null_user_handler) {
+ intf->null_user_handler(intf, msg);
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->handled_local_responses++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, handled_local_responses);
+ } else {
+ /* No handler, so give up. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->unhandled_local_responses++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, unhandled_local_responses);
+ }
+ ipmi_free_recv_msg(msg);
+ } else {
+@@ -646,9 +706,11 @@ deliver_err_response(struct ipmi_recv_msg *msg, int err)
+ deliver_response(msg);
+ }
+
+-/* Find the next sequence number not being used and add the given
+- message with the given timeout to the sequence table. This must be
+- called with the interface's seq_lock held. */
++/*
++ * Find the next sequence number not being used and add the given
++ * message with the given timeout to the sequence table. This must be
++ * called with the interface's seq_lock held.
++ */
+ static int intf_next_seq(ipmi_smi_t intf,
+ struct ipmi_recv_msg *recv_msg,
+ unsigned long timeout,
+@@ -660,10 +722,8 @@ static int intf_next_seq(ipmi_smi_t intf,
+ int rv = 0;
+ unsigned int i;
+
+- for (i = intf->curr_seq;
+- (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq;
+- i = (i+1)%IPMI_IPMB_NUM_SEQ)
+- {
++ for (i = intf->curr_seq; (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq;
++ i = (i+1)%IPMI_IPMB_NUM_SEQ) {
+ if (!intf->seq_table[i].inuse)
+ break;
+ }
+@@ -671,8 +731,10 @@ static int intf_next_seq(ipmi_smi_t intf,
+ if (!intf->seq_table[i].inuse) {
+ intf->seq_table[i].recv_msg = recv_msg;
+
+- /* Start with the maximum timeout, when the send response
+- comes in we will start the real timer. */
++ /*
++ * Start with the maximum timeout, when the send response
++ * comes in we will start the real timer.
++ */
+ intf->seq_table[i].timeout = MAX_MSG_TIMEOUT;
+ intf->seq_table[i].orig_timeout = timeout;
+ intf->seq_table[i].retries_left = retries;
+@@ -685,15 +747,17 @@ static int intf_next_seq(ipmi_smi_t intf,
+ } else {
+ rv = -EAGAIN;
+ }
+-
++
+ return rv;
+ }
+
+-/* Return the receive message for the given sequence number and
+- release the sequence number so it can be reused. Some other data
+- is passed in to be sure the message matches up correctly (to help
+- guard against message coming in after their timeout and the
+- sequence number being reused). */
++/*
++ * Return the receive message for the given sequence number and
++ * release the sequence number so it can be reused. Some other data
++ * is passed in to be sure the message matches up correctly (to help
++ * guard against message coming in after their timeout and the
++ * sequence number being reused).
++ */
+ static int intf_find_seq(ipmi_smi_t intf,
+ unsigned char seq,
+ short channel,
+@@ -712,11 +776,9 @@ static int intf_find_seq(ipmi_smi_t intf,
+ if (intf->seq_table[seq].inuse) {
+ struct ipmi_recv_msg *msg = intf->seq_table[seq].recv_msg;
+
+- if ((msg->addr.channel == channel)
+- && (msg->msg.cmd == cmd)
+- && (msg->msg.netfn == netfn)
+- && (ipmi_addr_equal(addr, &(msg->addr))))
+- {
++ if ((msg->addr.channel == channel) && (msg->msg.cmd == cmd)
++ && (msg->msg.netfn == netfn)
++ && (ipmi_addr_equal(addr, &(msg->addr)))) {
+ *recv_msg = msg;
+ intf->seq_table[seq].inuse = 0;
+ rv = 0;
+@@ -741,11 +803,12 @@ static int intf_start_seq_timer(ipmi_smi_t intf,
+ GET_SEQ_FROM_MSGID(msgid, seq, seqid);
+
+ spin_lock_irqsave(&(intf->seq_lock), flags);
+- /* We do this verification because the user can be deleted
+- while a message is outstanding. */
++ /*
++ * We do this verification because the user can be deleted
++ * while a message is outstanding.
++ */
+ if ((intf->seq_table[seq].inuse)
+- && (intf->seq_table[seq].seqid == seqid))
+- {
++ && (intf->seq_table[seq].seqid == seqid)) {
+ struct seq_table *ent = &(intf->seq_table[seq]);
+ ent->timeout = ent->orig_timeout;
+ rv = 0;
+@@ -770,11 +833,12 @@ static int intf_err_seq(ipmi_smi_t intf,
+ GET_SEQ_FROM_MSGID(msgid, seq, seqid);
+
+ spin_lock_irqsave(&(intf->seq_lock), flags);
+- /* We do this verification because the user can be deleted
+- while a message is outstanding. */
++ /*
++ * We do this verification because the user can be deleted
++ * while a message is outstanding.
++ */
+ if ((intf->seq_table[seq].inuse)
+- && (intf->seq_table[seq].seqid == seqid))
+- {
++ && (intf->seq_table[seq].seqid == seqid)) {
+ struct seq_table *ent = &(intf->seq_table[seq]);
+
+ ent->inuse = 0;
+@@ -800,24 +864,30 @@ int ipmi_create_user(unsigned int if_num,
+ int rv = 0;
+ ipmi_smi_t intf;
+
+- /* There is no module usecount here, because it's not
+- required. Since this can only be used by and called from
+- other modules, they will implicitly use this module, and
+- thus this can't be removed unless the other modules are
+- removed. */
++ /*
++ * There is no module usecount here, because it's not
++ * required. Since this can only be used by and called from
++ * other modules, they will implicitly use this module, and
++ * thus this can't be removed unless the other modules are
++ * removed.
++ */
+
+ if (handler == NULL)
+ return -EINVAL;
+
+- /* Make sure the driver is actually initialized, this handles
+- problems with initialization order. */
++ /*
++ * Make sure the driver is actually initialized, this handles
++ * problems with initialization order.
++ */
+ if (!initialized) {
+ rv = ipmi_init_msghandler();
+ if (rv)
+ return rv;
+
+- /* The init code doesn't return an error if it was turned
+- off, but it won't initialize. Check that. */
++ /*
++ * The init code doesn't return an error if it was turned
++ * off, but it won't initialize. Check that.
++ */
+ if (!initialized)
+ return -ENODEV;
+ }
+@@ -858,8 +928,10 @@ int ipmi_create_user(unsigned int if_num,
+ }
+ }
+
+- /* Hold the lock so intf->handlers is guaranteed to be good
+- * until now */
++ /*
++ * Hold the lock so intf->handlers is guaranteed to be good
++ * until now
++ */
+ mutex_unlock(&ipmi_interfaces_mutex);
+
+ new_user->valid = 1;
+@@ -876,6 +948,7 @@ out_kfree:
+ kfree(new_user);
+ return rv;
+ }
++EXPORT_SYMBOL(ipmi_create_user);
+
+ static void free_user(struct kref *ref)
+ {
+@@ -899,8 +972,7 @@ int ipmi_destroy_user(ipmi_user_t user)
+
+ for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
+ if (intf->seq_table[i].inuse
+- && (intf->seq_table[i].recv_msg->user == user))
+- {
++ && (intf->seq_table[i].recv_msg->user == user)) {
+ intf->seq_table[i].inuse = 0;
+ ipmi_free_recv_msg(intf->seq_table[i].recv_msg);
+ }
+@@ -943,6 +1015,7 @@ int ipmi_destroy_user(ipmi_user_t user)
+
+ return 0;
+ }
++EXPORT_SYMBOL(ipmi_destroy_user);
+
+ void ipmi_get_version(ipmi_user_t user,
+ unsigned char *major,
+@@ -951,6 +1024,7 @@ void ipmi_get_version(ipmi_user_t user,
+ *major = user->intf->ipmi_version_major;
+ *minor = user->intf->ipmi_version_minor;
+ }
++EXPORT_SYMBOL(ipmi_get_version);
+
+ int ipmi_set_my_address(ipmi_user_t user,
+ unsigned int channel,
+@@ -961,6 +1035,7 @@ int ipmi_set_my_address(ipmi_user_t user,
+ user->intf->channels[channel].address = address;
+ return 0;
+ }
++EXPORT_SYMBOL(ipmi_set_my_address);
+
+ int ipmi_get_my_address(ipmi_user_t user,
+ unsigned int channel,
+@@ -971,6 +1046,7 @@ int ipmi_get_my_address(ipmi_user_t user,
+ *address = user->intf->channels[channel].address;
+ return 0;
+ }
++EXPORT_SYMBOL(ipmi_get_my_address);
+
+ int ipmi_set_my_LUN(ipmi_user_t user,
+ unsigned int channel,
+@@ -981,6 +1057,7 @@ int ipmi_set_my_LUN(ipmi_user_t user,
+ user->intf->channels[channel].lun = LUN & 0x3;
+ return 0;
+ }
++EXPORT_SYMBOL(ipmi_set_my_LUN);
+
+ int ipmi_get_my_LUN(ipmi_user_t user,
+ unsigned int channel,
+@@ -991,6 +1068,7 @@ int ipmi_get_my_LUN(ipmi_user_t user,
+ *address = user->intf->channels[channel].lun;
+ return 0;
+ }
++EXPORT_SYMBOL(ipmi_get_my_LUN);
+
+ int ipmi_get_maintenance_mode(ipmi_user_t user)
+ {
+@@ -1075,6 +1153,11 @@ int ipmi_set_gets_events(ipmi_user_t user, int val)
+ list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link)
+ list_move_tail(&msg->link, &msgs);
+ intf->waiting_events_count = 0;
++ if (intf->event_msg_printed) {
++ printk(KERN_WARNING PFX "Event queue no longer"
++ " full\n");
++ intf->event_msg_printed = 0;
++ }
+
+ intf->delivering_events = 1;
+ spin_unlock_irqrestore(&intf->events_lock, flags);
+@@ -1094,6 +1177,7 @@ int ipmi_set_gets_events(ipmi_user_t user, int val)
+
+ return 0;
+ }
++EXPORT_SYMBOL(ipmi_set_gets_events);
+
+ static struct cmd_rcvr *find_cmd_rcvr(ipmi_smi_t intf,
+ unsigned char netfn,
+@@ -1159,6 +1243,7 @@ int ipmi_register_for_cmd(ipmi_user_t user,
+
+ return rv;
+ }
++EXPORT_SYMBOL(ipmi_register_for_cmd);
+
+ int ipmi_unregister_for_cmd(ipmi_user_t user,
+ unsigned char netfn,
+@@ -1196,19 +1281,13 @@ int ipmi_unregister_for_cmd(ipmi_user_t user,
+ }
+ return rv;
+ }
+-
+-void ipmi_user_set_run_to_completion(ipmi_user_t user, int val)
+-{
+- ipmi_smi_t intf = user->intf;
+- if (intf->handlers)
+- intf->handlers->set_run_to_completion(intf->send_info, val);
+-}
++EXPORT_SYMBOL(ipmi_unregister_for_cmd);
+
+ static unsigned char
+ ipmb_checksum(unsigned char *data, int size)
+ {
+ unsigned char csum = 0;
+-
++
+ for (; size > 0; size--, data++)
+ csum += *data;
+
+@@ -1250,8 +1329,10 @@ static inline void format_ipmb_msg(struct ipmi_smi_msg *smi_msg,
+ = ipmb_checksum(&(smi_msg->data[i+6]),
+ smi_msg->data_size-6);
+
+- /* Add on the checksum size and the offset from the
+- broadcast. */
++ /*
++ * Add on the checksum size and the offset from the
++ * broadcast.
++ */
+ smi_msg->data_size += 1 + i;
+
+ smi_msg->msgid = msgid;
+@@ -1287,17 +1368,21 @@ static inline void format_lan_msg(struct ipmi_smi_msg *smi_msg,
+ = ipmb_checksum(&(smi_msg->data[7]),
+ smi_msg->data_size-7);
+
+- /* Add on the checksum size and the offset from the
+- broadcast. */
++ /*
++ * Add on the checksum size and the offset from the
++ * broadcast.
++ */
+ smi_msg->data_size += 1;
+
+ smi_msg->msgid = msgid;
+ }
+
+-/* Separate from ipmi_request so that the user does not have to be
+- supplied in certain circumstances (mainly at panic time). If
+- messages are supplied, they will be freed, even if an error
+- occurs. */
++/*
++ * Separate from ipmi_request so that the user does not have to be
++ * supplied in certain circumstances (mainly at panic time). If
++ * messages are supplied, they will be freed, even if an error
++ * occurs.
++ */
+ static int i_ipmi_request(ipmi_user_t user,
+ ipmi_smi_t intf,
+ struct ipmi_addr *addr,
+@@ -1319,19 +1404,18 @@ static int i_ipmi_request(ipmi_user_t user,
+ struct ipmi_smi_handlers *handlers;
+
+
+- if (supplied_recv) {
++ if (supplied_recv)
+ recv_msg = supplied_recv;
+- } else {
++ else {
+ recv_msg = ipmi_alloc_recv_msg();
+- if (recv_msg == NULL) {
++ if (recv_msg == NULL)
+ return -ENOMEM;
+- }
+ }
+ recv_msg->user_msg_data = user_msg_data;
+
+- if (supplied_smi) {
++ if (supplied_smi)
+ smi_msg = (struct ipmi_smi_msg *) supplied_smi;
+- } else {
++ else {
+ smi_msg = ipmi_alloc_smi_msg();
+ if (smi_msg == NULL) {
+ ipmi_free_recv_msg(recv_msg);
+@@ -1350,8 +1434,10 @@ static int i_ipmi_request(ipmi_user_t user,
+ if (user)
+ kref_get(&user->refcount);
+ recv_msg->msgid = msgid;
+- /* Store the message to send in the receive message so timeout
+- responses can get the proper response data. */
++ /*
++ * Store the message to send in the receive message so timeout
++ * responses can get the proper response data.
++ */
+ recv_msg->msg = *msg;
+
+ if (addr->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {
+@@ -1365,9 +1451,7 @@ static int i_ipmi_request(ipmi_user_t user,
+
+ smi_addr = (struct ipmi_system_interface_addr *) addr;
+ if (smi_addr->lun > 3) {
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->sent_invalid_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, sent_invalid_commands);
+ rv = -EINVAL;
+ goto out_err;
+ }
+@@ -1377,13 +1461,12 @@ static int i_ipmi_request(ipmi_user_t user,
+ if ((msg->netfn == IPMI_NETFN_APP_REQUEST)
+ && ((msg->cmd == IPMI_SEND_MSG_CMD)
+ || (msg->cmd == IPMI_GET_MSG_CMD)
+- || (msg->cmd == IPMI_READ_EVENT_MSG_BUFFER_CMD)))
+- {
+- /* We don't let the user do these, since we manage
+- the sequence numbers. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->sent_invalid_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ || (msg->cmd == IPMI_READ_EVENT_MSG_BUFFER_CMD))) {
++ /*
++ * We don't let the user do these, since we manage
++ * the sequence numbers.
++ */
++ ipmi_inc_stat(intf, sent_invalid_commands);
+ rv = -EINVAL;
+ goto out_err;
+ }
+@@ -1391,14 +1474,12 @@ static int i_ipmi_request(ipmi_user_t user,
+ if (((msg->netfn == IPMI_NETFN_APP_REQUEST)
+ && ((msg->cmd == IPMI_COLD_RESET_CMD)
+ || (msg->cmd == IPMI_WARM_RESET_CMD)))
+- || (msg->netfn == IPMI_NETFN_FIRMWARE_REQUEST))
+- {
++ || (msg->netfn == IPMI_NETFN_FIRMWARE_REQUEST)) {
+ spin_lock_irqsave(&intf->maintenance_mode_lock, flags);
+ intf->auto_maintenance_timeout
+ = IPMI_MAINTENANCE_MODE_TIMEOUT;
+ if (!intf->maintenance_mode
+- && !intf->maintenance_mode_enable)
+- {
++ && !intf->maintenance_mode_enable) {
+ intf->maintenance_mode_enable = 1;
+ maintenance_mode_update(intf);
+ }
+@@ -1407,9 +1488,7 @@ static int i_ipmi_request(ipmi_user_t user,
+ }
+
+ if ((msg->data_len + 2) > IPMI_MAX_MSG_LENGTH) {
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->sent_invalid_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, sent_invalid_commands);
+ rv = -EMSGSIZE;
+ goto out_err;
+ }
+@@ -1421,31 +1500,23 @@ static int i_ipmi_request(ipmi_user_t user,
+ if (msg->data_len > 0)
+ memcpy(&(smi_msg->data[2]), msg->data, msg->data_len);
+ smi_msg->data_size = msg->data_len + 2;
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->sent_local_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, sent_local_commands);
+ } else if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE)
+- || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
+- {
++ || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) {
+ struct ipmi_ipmb_addr *ipmb_addr;
+ unsigned char ipmb_seq;
+ long seqid;
+ int broadcast = 0;
+
+ if (addr->channel >= IPMI_MAX_CHANNELS) {
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->sent_invalid_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, sent_invalid_commands);
+ rv = -EINVAL;
+ goto out_err;
+ }
+
+ if (intf->channels[addr->channel].medium
+- != IPMI_CHANNEL_MEDIUM_IPMB)
+- {
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->sent_invalid_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ != IPMI_CHANNEL_MEDIUM_IPMB) {
++ ipmi_inc_stat(intf, sent_invalid_commands);
+ rv = -EINVAL;
+ goto out_err;
+ }
+@@ -1457,9 +1528,11 @@ static int i_ipmi_request(ipmi_user_t user,
+ retries = 4;
+ }
+ if (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE) {
+- /* Broadcasts add a zero at the beginning of the
+- message, but otherwise is the same as an IPMB
+- address. */
++ /*
++ * Broadcasts add a zero at the beginning of the
++ * message, but otherwise is the same as an IPMB
++ * address.
++ */
+ addr->addr_type = IPMI_IPMB_ADDR_TYPE;
+ broadcast = 1;
+ }
+@@ -1469,21 +1542,19 @@ static int i_ipmi_request(ipmi_user_t user,
+ if (retry_time_ms == 0)
+ retry_time_ms = 1000;
+
+- /* 9 for the header and 1 for the checksum, plus
+- possibly one for the broadcast. */
++ /*
++ * 9 for the header and 1 for the checksum, plus
++ * possibly one for the broadcast.
++ */
+ if ((msg->data_len + 10 + broadcast) > IPMI_MAX_MSG_LENGTH) {
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->sent_invalid_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, sent_invalid_commands);
+ rv = -EMSGSIZE;
+ goto out_err;
+ }
+
+ ipmb_addr = (struct ipmi_ipmb_addr *) addr;
+ if (ipmb_addr->lun > 3) {
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->sent_invalid_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, sent_invalid_commands);
+ rv = -EINVAL;
+ goto out_err;
+ }
+@@ -1491,29 +1562,31 @@ static int i_ipmi_request(ipmi_user_t user,
+ memcpy(&recv_msg->addr, ipmb_addr, sizeof(*ipmb_addr));
+
+ if (recv_msg->msg.netfn & 0x1) {
+- /* It's a response, so use the user's sequence
+- from msgid. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->sent_ipmb_responses++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ /*
++ * It's a response, so use the user's sequence
++ * from msgid.
++ */
++ ipmi_inc_stat(intf, sent_ipmb_responses);
+ format_ipmb_msg(smi_msg, msg, ipmb_addr, msgid,
+ msgid, broadcast,
+ source_address, source_lun);
+
+- /* Save the receive message so we can use it
+- to deliver the response. */
++ /*
++ * Save the receive message so we can use it
++ * to deliver the response.
++ */
+ smi_msg->user_data = recv_msg;
+ } else {
+ /* It's a command, so get a sequence for it. */
+
+ spin_lock_irqsave(&(intf->seq_lock), flags);
+
+- spin_lock(&intf->counter_lock);
+- intf->sent_ipmb_commands++;
+- spin_unlock(&intf->counter_lock);
++ ipmi_inc_stat(intf, sent_ipmb_commands);
+
+- /* Create a sequence number with a 1 second
+- timeout and 4 retries. */
++ /*
++ * Create a sequence number with a 1 second
++ * timeout and 4 retries.
++ */
+ rv = intf_next_seq(intf,
+ recv_msg,
+ retry_time_ms,
+@@ -1522,34 +1595,42 @@ static int i_ipmi_request(ipmi_user_t user,
+ &ipmb_seq,
+ &seqid);
+ if (rv) {
+- /* We have used up all the sequence numbers,
+- probably, so abort. */
++ /*
++ * We have used up all the sequence numbers,
++ * probably, so abort.
++ */
+ spin_unlock_irqrestore(&(intf->seq_lock),
+ flags);
+ goto out_err;
+ }
+
+- /* Store the sequence number in the message,
+- so that when the send message response
+- comes back we can start the timer. */
++ /*
++ * Store the sequence number in the message,
++ * so that when the send message response
++ * comes back we can start the timer.
++ */
+ format_ipmb_msg(smi_msg, msg, ipmb_addr,
+ STORE_SEQ_IN_MSGID(ipmb_seq, seqid),
+ ipmb_seq, broadcast,
+ source_address, source_lun);
+
+- /* Copy the message into the recv message data, so we
+- can retransmit it later if necessary. */
++ /*
++ * Copy the message into the recv message data, so we
++ * can retransmit it later if necessary.
++ */
+ memcpy(recv_msg->msg_data, smi_msg->data,
+ smi_msg->data_size);
+ recv_msg->msg.data = recv_msg->msg_data;
+ recv_msg->msg.data_len = smi_msg->data_size;
+
+- /* We don't unlock until here, because we need
+- to copy the completed message into the
+- recv_msg before we release the lock.
+- Otherwise, race conditions may bite us. I
+- know that's pretty paranoid, but I prefer
+- to be correct. */
++ /*
++ * We don't unlock until here, because we need
++ * to copy the completed message into the
++ * recv_msg before we release the lock.
++ * Otherwise, race conditions may bite us. I
++ * know that's pretty paranoid, but I prefer
++ * to be correct.
++ */
+ spin_unlock_irqrestore(&(intf->seq_lock), flags);
+ }
+ } else if (addr->addr_type == IPMI_LAN_ADDR_TYPE) {
+@@ -1558,21 +1639,16 @@ static int i_ipmi_request(ipmi_user_t user,
+ long seqid;
+
+ if (addr->channel >= IPMI_MAX_CHANNELS) {
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->sent_invalid_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, sent_invalid_commands);
+ rv = -EINVAL;
+ goto out_err;
+ }
+
+ if ((intf->channels[addr->channel].medium
+- != IPMI_CHANNEL_MEDIUM_8023LAN)
++ != IPMI_CHANNEL_MEDIUM_8023LAN)
+ && (intf->channels[addr->channel].medium
+- != IPMI_CHANNEL_MEDIUM_ASYNC))
+- {
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->sent_invalid_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ != IPMI_CHANNEL_MEDIUM_ASYNC)) {
++ ipmi_inc_stat(intf, sent_invalid_commands);
+ rv = -EINVAL;
+ goto out_err;
+ }
+@@ -1585,18 +1661,14 @@ static int i_ipmi_request(ipmi_user_t user,
+
+ /* 11 for the header and 1 for the checksum. */
+ if ((msg->data_len + 12) > IPMI_MAX_MSG_LENGTH) {
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->sent_invalid_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, sent_invalid_commands);
+ rv = -EMSGSIZE;
+ goto out_err;
+ }
+
+ lan_addr = (struct ipmi_lan_addr *) addr;
+ if (lan_addr->lun > 3) {
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->sent_invalid_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, sent_invalid_commands);
+ rv = -EINVAL;
+ goto out_err;
+ }
+@@ -1604,28 +1676,30 @@ static int i_ipmi_request(ipmi_user_t user,
+ memcpy(&recv_msg->addr, lan_addr, sizeof(*lan_addr));
+
+ if (recv_msg->msg.netfn & 0x1) {
+- /* It's a response, so use the user's sequence
+- from msgid. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->sent_lan_responses++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ /*
++ * It's a response, so use the user's sequence
++ * from msgid.
++ */
++ ipmi_inc_stat(intf, sent_lan_responses);
+ format_lan_msg(smi_msg, msg, lan_addr, msgid,
+ msgid, source_lun);
+
+- /* Save the receive message so we can use it
+- to deliver the response. */
++ /*
++ * Save the receive message so we can use it
++ * to deliver the response.
++ */
+ smi_msg->user_data = recv_msg;
+ } else {
+ /* It's a command, so get a sequence for it. */
+
+ spin_lock_irqsave(&(intf->seq_lock), flags);
+
+- spin_lock(&intf->counter_lock);
+- intf->sent_lan_commands++;
+- spin_unlock(&intf->counter_lock);
++ ipmi_inc_stat(intf, sent_lan_commands);
+
+- /* Create a sequence number with a 1 second
+- timeout and 4 retries. */
++ /*
++ * Create a sequence number with a 1 second
++ * timeout and 4 retries.
++ */
+ rv = intf_next_seq(intf,
+ recv_msg,
+ retry_time_ms,
+@@ -1634,40 +1708,46 @@ static int i_ipmi_request(ipmi_user_t user,
+ &ipmb_seq,
+ &seqid);
+ if (rv) {
+- /* We have used up all the sequence numbers,
+- probably, so abort. */
++ /*
++ * We have used up all the sequence numbers,
++ * probably, so abort.
++ */
+ spin_unlock_irqrestore(&(intf->seq_lock),
+ flags);
+ goto out_err;
+ }
+
+- /* Store the sequence number in the message,
+- so that when the send message response
+- comes back we can start the timer. */
++ /*
++ * Store the sequence number in the message,
++ * so that when the send message response
++ * comes back we can start the timer.
++ */
+ format_lan_msg(smi_msg, msg, lan_addr,
+ STORE_SEQ_IN_MSGID(ipmb_seq, seqid),
+ ipmb_seq, source_lun);
+
+- /* Copy the message into the recv message data, so we
+- can retransmit it later if necessary. */
++ /*
++ * Copy the message into the recv message data, so we
++ * can retransmit it later if necessary.
++ */
+ memcpy(recv_msg->msg_data, smi_msg->data,
+ smi_msg->data_size);
+ recv_msg->msg.data = recv_msg->msg_data;
+ recv_msg->msg.data_len = smi_msg->data_size;
+
+- /* We don't unlock until here, because we need
+- to copy the completed message into the
+- recv_msg before we release the lock.
+- Otherwise, race conditions may bite us. I
+- know that's pretty paranoid, but I prefer
+- to be correct. */
++ /*
++ * We don't unlock until here, because we need
++ * to copy the completed message into the
++ * recv_msg before we release the lock.
++ * Otherwise, race conditions may bite us. I
++ * know that's pretty paranoid, but I prefer
++ * to be correct.
++ */
+ spin_unlock_irqrestore(&(intf->seq_lock), flags);
+ }
+ } else {
+ /* Unknown address type. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->sent_invalid_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, sent_invalid_commands);
+ rv = -EINVAL;
+ goto out_err;
+ }
+@@ -1735,6 +1815,7 @@ int ipmi_request_settime(ipmi_user_t user,
+ retries,
+ retry_time_ms);
+ }
++EXPORT_SYMBOL(ipmi_request_settime);
+
+ int ipmi_request_supply_msgs(ipmi_user_t user,
+ struct ipmi_addr *addr,
+@@ -1766,6 +1847,7 @@ int ipmi_request_supply_msgs(ipmi_user_t user,
+ lun,
+ -1, 0);
+ }
++EXPORT_SYMBOL(ipmi_request_supply_msgs);
+
+ #ifdef CONFIG_PROC_FS
+ static int ipmb_file_read_proc(char *page, char **start, off_t off,
+@@ -1790,7 +1872,7 @@ static int version_file_read_proc(char *page, char **start, off_t off,
+ char *out = (char *) page;
+ ipmi_smi_t intf = data;
+
+- return sprintf(out, "%d.%d\n",
++ return sprintf(out, "%u.%u\n",
+ ipmi_version_major(&intf->bmc->id),
+ ipmi_version_minor(&intf->bmc->id));
+ }
+@@ -1801,65 +1883,65 @@ static int stat_file_read_proc(char *page, char **start, off_t off,
+ char *out = (char *) page;
+ ipmi_smi_t intf = data;
+
+- out += sprintf(out, "sent_invalid_commands: %d\n",
+- intf->sent_invalid_commands);
+- out += sprintf(out, "sent_local_commands: %d\n",
+- intf->sent_local_commands);
+- out += sprintf(out, "handled_local_responses: %d\n",
+- intf->handled_local_responses);
+- out += sprintf(out, "unhandled_local_responses: %d\n",
+- intf->unhandled_local_responses);
+- out += sprintf(out, "sent_ipmb_commands: %d\n",
+- intf->sent_ipmb_commands);
+- out += sprintf(out, "sent_ipmb_command_errs: %d\n",
+- intf->sent_ipmb_command_errs);
+- out += sprintf(out, "retransmitted_ipmb_commands: %d\n",
+- intf->retransmitted_ipmb_commands);
+- out += sprintf(out, "timed_out_ipmb_commands: %d\n",
+- intf->timed_out_ipmb_commands);
+- out += sprintf(out, "timed_out_ipmb_broadcasts: %d\n",
+- intf->timed_out_ipmb_broadcasts);
+- out += sprintf(out, "sent_ipmb_responses: %d\n",
+- intf->sent_ipmb_responses);
+- out += sprintf(out, "handled_ipmb_responses: %d\n",
+- intf->handled_ipmb_responses);
+- out += sprintf(out, "invalid_ipmb_responses: %d\n",
+- intf->invalid_ipmb_responses);
+- out += sprintf(out, "unhandled_ipmb_responses: %d\n",
+- intf->unhandled_ipmb_responses);
+- out += sprintf(out, "sent_lan_commands: %d\n",
+- intf->sent_lan_commands);
+- out += sprintf(out, "sent_lan_command_errs: %d\n",
+- intf->sent_lan_command_errs);
+- out += sprintf(out, "retransmitted_lan_commands: %d\n",
+- intf->retransmitted_lan_commands);
+- out += sprintf(out, "timed_out_lan_commands: %d\n",
+- intf->timed_out_lan_commands);
+- out += sprintf(out, "sent_lan_responses: %d\n",
+- intf->sent_lan_responses);
+- out += sprintf(out, "handled_lan_responses: %d\n",
+- intf->handled_lan_responses);
+- out += sprintf(out, "invalid_lan_responses: %d\n",
+- intf->invalid_lan_responses);
+- out += sprintf(out, "unhandled_lan_responses: %d\n",
+- intf->unhandled_lan_responses);
+- out += sprintf(out, "handled_commands: %d\n",
+- intf->handled_commands);
+- out += sprintf(out, "invalid_commands: %d\n",
+- intf->invalid_commands);
+- out += sprintf(out, "unhandled_commands: %d\n",
+- intf->unhandled_commands);
+- out += sprintf(out, "invalid_events: %d\n",
+- intf->invalid_events);
+- out += sprintf(out, "events: %d\n",
+- intf->events);
++ out += sprintf(out, "sent_invalid_commands: %u\n",
++ ipmi_get_stat(intf, sent_invalid_commands));
++ out += sprintf(out, "sent_local_commands: %u\n",
++ ipmi_get_stat(intf, sent_local_commands));
++ out += sprintf(out, "handled_local_responses: %u\n",
++ ipmi_get_stat(intf, handled_local_responses));
++ out += sprintf(out, "unhandled_local_responses: %u\n",
++ ipmi_get_stat(intf, unhandled_local_responses));
++ out += sprintf(out, "sent_ipmb_commands: %u\n",
++ ipmi_get_stat(intf, sent_ipmb_commands));
++ out += sprintf(out, "sent_ipmb_command_errs: %u\n",
++ ipmi_get_stat(intf, sent_ipmb_command_errs));
++ out += sprintf(out, "retransmitted_ipmb_commands: %u\n",
++ ipmi_get_stat(intf, retransmitted_ipmb_commands));
++ out += sprintf(out, "timed_out_ipmb_commands: %u\n",
++ ipmi_get_stat(intf, timed_out_ipmb_commands));
++ out += sprintf(out, "timed_out_ipmb_broadcasts: %u\n",
++ ipmi_get_stat(intf, timed_out_ipmb_broadcasts));
++ out += sprintf(out, "sent_ipmb_responses: %u\n",
++ ipmi_get_stat(intf, sent_ipmb_responses));
++ out += sprintf(out, "handled_ipmb_responses: %u\n",
++ ipmi_get_stat(intf, handled_ipmb_responses));
++ out += sprintf(out, "invalid_ipmb_responses: %u\n",
++ ipmi_get_stat(intf, invalid_ipmb_responses));
++ out += sprintf(out, "unhandled_ipmb_responses: %u\n",
++ ipmi_get_stat(intf, unhandled_ipmb_responses));
++ out += sprintf(out, "sent_lan_commands: %u\n",
++ ipmi_get_stat(intf, sent_lan_commands));
++ out += sprintf(out, "sent_lan_command_errs: %u\n",
++ ipmi_get_stat(intf, sent_lan_command_errs));
++ out += sprintf(out, "retransmitted_lan_commands: %u\n",
++ ipmi_get_stat(intf, retransmitted_lan_commands));
++ out += sprintf(out, "timed_out_lan_commands: %u\n",
++ ipmi_get_stat(intf, timed_out_lan_commands));
++ out += sprintf(out, "sent_lan_responses: %u\n",
++ ipmi_get_stat(intf, sent_lan_responses));
++ out += sprintf(out, "handled_lan_responses: %u\n",
++ ipmi_get_stat(intf, handled_lan_responses));
++ out += sprintf(out, "invalid_lan_responses: %u\n",
++ ipmi_get_stat(intf, invalid_lan_responses));
++ out += sprintf(out, "unhandled_lan_responses: %u\n",
++ ipmi_get_stat(intf, unhandled_lan_responses));
++ out += sprintf(out, "handled_commands: %u\n",
++ ipmi_get_stat(intf, handled_commands));
++ out += sprintf(out, "invalid_commands: %u\n",
++ ipmi_get_stat(intf, invalid_commands));
++ out += sprintf(out, "unhandled_commands: %u\n",
++ ipmi_get_stat(intf, unhandled_commands));
++ out += sprintf(out, "invalid_events: %u\n",
++ ipmi_get_stat(intf, invalid_events));
++ out += sprintf(out, "events: %u\n",
++ ipmi_get_stat(intf, events));
+
+ return (out - ((char *) page));
+ }
+ #endif /* CONFIG_PROC_FS */
+
+ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
+- read_proc_t *read_proc, write_proc_t *write_proc,
++ read_proc_t *read_proc,
+ void *data, struct module *owner)
+ {
+ int rv = 0;
+@@ -1886,7 +1968,6 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
+ } else {
+ file->data = data;
+ file->read_proc = read_proc;
+- file->write_proc = write_proc;
+ file->owner = owner;
+
+ mutex_lock(&smi->proc_entry_lock);
+@@ -1899,6 +1980,7 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
+
+ return rv;
+ }
++EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
+
+ static int add_proc_entries(ipmi_smi_t smi, int num)
+ {
+@@ -1909,23 +1991,22 @@ static int add_proc_entries(ipmi_smi_t smi, int num)
+ smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root);
+ if (!smi->proc_dir)
+ rv = -ENOMEM;
+- else {
++ else
+ smi->proc_dir->owner = THIS_MODULE;
+- }
+
+ if (rv == 0)
+ rv = ipmi_smi_add_proc_entry(smi, "stats",
+- stat_file_read_proc, NULL,
++ stat_file_read_proc,
+ smi, THIS_MODULE);
+
+ if (rv == 0)
+ rv = ipmi_smi_add_proc_entry(smi, "ipmb",
+- ipmb_file_read_proc, NULL,
++ ipmb_file_read_proc,
+ smi, THIS_MODULE);
+
+ if (rv == 0)
+ rv = ipmi_smi_add_proc_entry(smi, "version",
+- version_file_read_proc, NULL,
++ version_file_read_proc,
+ smi, THIS_MODULE);
+ #endif /* CONFIG_PROC_FS */
+
+@@ -2210,37 +2291,47 @@ static int create_files(struct bmc_device *bmc)
+
+ err = device_create_file(&bmc->dev->dev,
+ &bmc->device_id_attr);
+- if (err) goto out;
++ if (err)
++ goto out;
+ err = device_create_file(&bmc->dev->dev,
+ &bmc->provides_dev_sdrs_attr);
+- if (err) goto out_devid;
++ if (err)
++ goto out_devid;
+ err = device_create_file(&bmc->dev->dev,
+ &bmc->revision_attr);
+- if (err) goto out_sdrs;
++ if (err)
++ goto out_sdrs;
+ err = device_create_file(&bmc->dev->dev,
+ &bmc->firmware_rev_attr);
+- if (err) goto out_rev;
++ if (err)
++ goto out_rev;
+ err = device_create_file(&bmc->dev->dev,
+ &bmc->version_attr);
+- if (err) goto out_firm;
++ if (err)
++ goto out_firm;
+ err = device_create_file(&bmc->dev->dev,
+ &bmc->add_dev_support_attr);
+- if (err) goto out_version;
++ if (err)
++ goto out_version;
+ err = device_create_file(&bmc->dev->dev,
+ &bmc->manufacturer_id_attr);
+- if (err) goto out_add_dev;
++ if (err)
++ goto out_add_dev;
+ err = device_create_file(&bmc->dev->dev,
+ &bmc->product_id_attr);
+- if (err) goto out_manu;
++ if (err)
++ goto out_manu;
+ if (bmc->id.aux_firmware_revision_set) {
+ err = device_create_file(&bmc->dev->dev,
+ &bmc->aux_firmware_rev_attr);
+- if (err) goto out_prod_id;
++ if (err)
++ goto out_prod_id;
+ }
+ if (bmc->guid_set) {
+ err = device_create_file(&bmc->dev->dev,
+ &bmc->guid_attr);
+- if (err) goto out_aux_firm;
++ if (err)
++ goto out_aux_firm;
+ }
+
+ return 0;
+@@ -2368,8 +2459,10 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum,
+ "ipmi_msghandler:"
+ " Unable to register bmc device: %d\n",
+ rv);
+- /* Don't go to out_err, you can only do that if
+- the device is registered already. */
++ /*
++ * Don't go to out_err, you can only do that if
++ * the device is registered already.
++ */
+ return rv;
+ }
+
+@@ -2560,17 +2653,18 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
+
+ if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
+ && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE)
+- && (msg->msg.cmd == IPMI_GET_CHANNEL_INFO_CMD))
+- {
++ && (msg->msg.cmd == IPMI_GET_CHANNEL_INFO_CMD)) {
+ /* It's the one we want */
+ if (msg->msg.data[0] != 0) {
+ /* Got an error from the channel, just go on. */
+
+ if (msg->msg.data[0] == IPMI_INVALID_COMMAND_ERR) {
+- /* If the MC does not support this
+- command, that is legal. We just
+- assume it has one IPMB at channel
+- zero. */
++ /*
++ * If the MC does not support this
++ * command, that is legal. We just
++ * assume it has one IPMB at channel
++ * zero.
++ */
+ intf->channels[0].medium
+ = IPMI_CHANNEL_MEDIUM_IPMB;
+ intf->channels[0].protocol
+@@ -2591,7 +2685,7 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
+ intf->channels[chan].medium = msg->msg.data[2] & 0x7f;
+ intf->channels[chan].protocol = msg->msg.data[3] & 0x1f;
+
+- next_channel:
++ next_channel:
+ intf->curr_channel++;
+ if (intf->curr_channel >= IPMI_MAX_CHANNELS)
+ wake_up(&intf->waitq);
+@@ -2619,6 +2713,7 @@ void ipmi_poll_interface(ipmi_user_t user)
+ if (intf->handlers->poll)
+ intf->handlers->poll(intf->send_info);
+ }
++EXPORT_SYMBOL(ipmi_poll_interface);
+
+ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
+ void *send_info,
+@@ -2633,14 +2728,18 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
+ ipmi_smi_t tintf;
+ struct list_head *link;
+
+- /* Make sure the driver is actually initialized, this handles
+- problems with initialization order. */
++ /*
++ * Make sure the driver is actually initialized, this handles
++ * problems with initialization order.
++ */
+ if (!initialized) {
+ rv = ipmi_init_msghandler();
+ if (rv)
+ return rv;
+- /* The init code doesn't return an error if it was turned
+- off, but it won't initialize. Check that. */
++ /*
++ * The init code doesn't return an error if it was turned
++ * off, but it won't initialize. Check that.
++ */
+ if (!initialized)
+ return -ENODEV;
+ }
+@@ -2688,8 +2787,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
+ spin_lock_init(&intf->maintenance_mode_lock);
+ INIT_LIST_HEAD(&intf->cmd_rcvrs);
+ init_waitqueue_head(&intf->waitq);
++ for (i = 0; i < IPMI_NUM_STATS; i++)
++ atomic_set(&intf->stats[i], 0);
+
+- spin_lock_init(&intf->counter_lock);
+ intf->proc_dir = NULL;
+
+ mutex_lock(&smi_watchers_mutex);
+@@ -2717,11 +2817,12 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
+ get_guid(intf);
+
+ if ((intf->ipmi_version_major > 1)
+- || ((intf->ipmi_version_major == 1)
+- && (intf->ipmi_version_minor >= 5)))
+- {
+- /* Start scanning the channels to see what is
+- available. */
++ || ((intf->ipmi_version_major == 1)
++ && (intf->ipmi_version_minor >= 5))) {
++ /*
++ * Start scanning the channels to see what is
++ * available.
++ */
+ intf->null_user_handler = channel_handler;
+ intf->curr_channel = 0;
+ rv = send_channel_info_cmd(intf, 0);
+@@ -2769,6 +2870,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
+
+ return rv;
+ }
++EXPORT_SYMBOL(ipmi_register_smi);
+
+ static void cleanup_smi_msgs(ipmi_smi_t intf)
+ {
+@@ -2803,8 +2905,10 @@ int ipmi_unregister_smi(ipmi_smi_t intf)
+
+ remove_proc_entries(intf);
+
+- /* Call all the watcher interfaces to tell them that
+- an interface is gone. */
++ /*
++ * Call all the watcher interfaces to tell them that
++ * an interface is gone.
++ */
+ list_for_each_entry(w, &smi_watchers, link)
+ w->smi_gone(intf_num);
+ mutex_unlock(&smi_watchers_mutex);
+@@ -2812,22 +2916,21 @@ int ipmi_unregister_smi(ipmi_smi_t intf)
+ kref_put(&intf->refcount, intf_free);
+ return 0;
+ }
++EXPORT_SYMBOL(ipmi_unregister_smi);
+
+ static int handle_ipmb_get_msg_rsp(ipmi_smi_t intf,
+ struct ipmi_smi_msg *msg)
+ {
+ struct ipmi_ipmb_addr ipmb_addr;
+ struct ipmi_recv_msg *recv_msg;
+- unsigned long flags;
+
+-
+- /* This is 11, not 10, because the response must contain a
+- * completion code. */
++ /*
++ * This is 11, not 10, because the response must contain a
++ * completion code.
++ */
+ if (msg->rsp_size < 11) {
+ /* Message not big enough, just ignore it. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->invalid_ipmb_responses++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, invalid_ipmb_responses);
+ return 0;
+ }
+
+@@ -2841,37 +2944,38 @@ static int handle_ipmb_get_msg_rsp(ipmi_smi_t intf,
+ ipmb_addr.channel = msg->rsp[3] & 0x0f;
+ ipmb_addr.lun = msg->rsp[7] & 3;
+
+- /* It's a response from a remote entity. Look up the sequence
+- number and handle the response. */
++ /*
++ * It's a response from a remote entity. Look up the sequence
++ * number and handle the response.
++ */
+ if (intf_find_seq(intf,
+ msg->rsp[7] >> 2,
+ msg->rsp[3] & 0x0f,
+ msg->rsp[8],
+ (msg->rsp[4] >> 2) & (~1),
+ (struct ipmi_addr *) &(ipmb_addr),
+- &recv_msg))
+- {
+- /* We were unable to find the sequence number,
+- so just nuke the message. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->unhandled_ipmb_responses++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ &recv_msg)) {
++ /*
++ * We were unable to find the sequence number,
++ * so just nuke the message.
++ */
++ ipmi_inc_stat(intf, unhandled_ipmb_responses);
+ return 0;
+ }
+
+ memcpy(recv_msg->msg_data,
+ &(msg->rsp[9]),
+ msg->rsp_size - 9);
+- /* THe other fields matched, so no need to set them, except
+- for netfn, which needs to be the response that was
+- returned, not the request value. */
++ /*
++ * The other fields matched, so no need to set them, except
++ * for netfn, which needs to be the response that was
++ * returned, not the request value.
++ */
+ recv_msg->msg.netfn = msg->rsp[4] >> 2;
+ recv_msg->msg.data = recv_msg->msg_data;
+ recv_msg->msg.data_len = msg->rsp_size - 10;
+ recv_msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->handled_ipmb_responses++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, handled_ipmb_responses);
+ deliver_response(recv_msg);
+
+ return 0;
+@@ -2888,14 +2992,11 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
+ ipmi_user_t user = NULL;
+ struct ipmi_ipmb_addr *ipmb_addr;
+ struct ipmi_recv_msg *recv_msg;
+- unsigned long flags;
+ struct ipmi_smi_handlers *handlers;
+
+ if (msg->rsp_size < 10) {
+ /* Message not big enough, just ignore it. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->invalid_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, invalid_commands);
+ return 0;
+ }
+
+@@ -2919,19 +3020,17 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
+
+ if (user == NULL) {
+ /* We didn't find a user, deliver an error response. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->unhandled_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, unhandled_commands);
+
+ msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
+ msg->data[1] = IPMI_SEND_MSG_CMD;
+ msg->data[2] = msg->rsp[3];
+ msg->data[3] = msg->rsp[6];
+- msg->data[4] = ((netfn + 1) << 2) | (msg->rsp[7] & 0x3);
++ msg->data[4] = ((netfn + 1) << 2) | (msg->rsp[7] & 0x3);
+ msg->data[5] = ipmb_checksum(&(msg->data[3]), 2);
+ msg->data[6] = intf->channels[msg->rsp[3] & 0xf].address;
+- /* rqseq/lun */
+- msg->data[7] = (msg->rsp[7] & 0xfc) | (msg->rsp[4] & 0x3);
++ /* rqseq/lun */
++ msg->data[7] = (msg->rsp[7] & 0xfc) | (msg->rsp[4] & 0x3);
+ msg->data[8] = msg->rsp[8]; /* cmd */
+ msg->data[9] = IPMI_INVALID_CMD_COMPLETION_CODE;
+ msg->data[10] = ipmb_checksum(&(msg->data[6]), 4);
+@@ -2950,23 +3049,25 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
+ handlers = intf->handlers;
+ if (handlers) {
+ handlers->sender(intf->send_info, msg, 0);
+- /* We used the message, so return the value
+- that causes it to not be freed or
+- queued. */
++ /*
++ * We used the message, so return the value
++ * that causes it to not be freed or
++ * queued.
++ */
+ rv = -1;
+ }
+ rcu_read_unlock();
+ } else {
+ /* Deliver the message to the user. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->handled_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, handled_commands);
+
+ recv_msg = ipmi_alloc_recv_msg();
+ if (!recv_msg) {
+- /* We couldn't allocate memory for the
+- message, so requeue it for handling
+- later. */
++ /*
++ * We couldn't allocate memory for the
++ * message, so requeue it for handling
++ * later.
++ */
+ rv = 1;
+ kref_put(&user->refcount, free_user);
+ } else {
+@@ -2977,8 +3078,10 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
+ ipmb_addr->lun = msg->rsp[7] & 3;
+ ipmb_addr->channel = msg->rsp[3] & 0xf;
+
+- /* Extract the rest of the message information
+- from the IPMB header.*/
++ /*
++ * Extract the rest of the message information
++ * from the IPMB header.
++ */
+ recv_msg->user = user;
+ recv_msg->recv_type = IPMI_CMD_RECV_TYPE;
+ recv_msg->msgid = msg->rsp[7] >> 2;
+@@ -2986,8 +3089,10 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
+ recv_msg->msg.cmd = msg->rsp[8];
+ recv_msg->msg.data = recv_msg->msg_data;
+
+- /* We chop off 10, not 9 bytes because the checksum
+- at the end also needs to be removed. */
++ /*
++ * We chop off 10, not 9 bytes because the checksum
++ * at the end also needs to be removed.
++ */
+ recv_msg->msg.data_len = msg->rsp_size - 10;
+ memcpy(recv_msg->msg_data,
+ &(msg->rsp[9]),
+@@ -3004,16 +3109,15 @@ static int handle_lan_get_msg_rsp(ipmi_smi_t intf,
+ {
+ struct ipmi_lan_addr lan_addr;
+ struct ipmi_recv_msg *recv_msg;
+- unsigned long flags;
+
+
+- /* This is 13, not 12, because the response must contain a
+- * completion code. */
++ /*
++ * This is 13, not 12, because the response must contain a
++ * completion code.
++ */
+ if (msg->rsp_size < 13) {
+ /* Message not big enough, just ignore it. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->invalid_lan_responses++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, invalid_lan_responses);
+ return 0;
+ }
+
+@@ -3030,37 +3134,38 @@ static int handle_lan_get_msg_rsp(ipmi_smi_t intf,
+ lan_addr.privilege = msg->rsp[3] >> 4;
+ lan_addr.lun = msg->rsp[9] & 3;
+
+- /* It's a response from a remote entity. Look up the sequence
+- number and handle the response. */
++ /*
++ * It's a response from a remote entity. Look up the sequence
++ * number and handle the response.
++ */
+ if (intf_find_seq(intf,
+ msg->rsp[9] >> 2,
+ msg->rsp[3] & 0x0f,
+ msg->rsp[10],
+ (msg->rsp[6] >> 2) & (~1),
+ (struct ipmi_addr *) &(lan_addr),
+- &recv_msg))
+- {
+- /* We were unable to find the sequence number,
+- so just nuke the message. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->unhandled_lan_responses++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ &recv_msg)) {
++ /*
++ * We were unable to find the sequence number,
++ * so just nuke the message.
++ */
++ ipmi_inc_stat(intf, unhandled_lan_responses);
+ return 0;
+ }
+
+ memcpy(recv_msg->msg_data,
+ &(msg->rsp[11]),
+ msg->rsp_size - 11);
+- /* The other fields matched, so no need to set them, except
+- for netfn, which needs to be the response that was
+- returned, not the request value. */
++ /*
++ * The other fields matched, so no need to set them, except
++ * for netfn, which needs to be the response that was
++ * returned, not the request value.
++ */
+ recv_msg->msg.netfn = msg->rsp[6] >> 2;
+ recv_msg->msg.data = recv_msg->msg_data;
+ recv_msg->msg.data_len = msg->rsp_size - 12;
+ recv_msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->handled_lan_responses++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, handled_lan_responses);
+ deliver_response(recv_msg);
+
+ return 0;
+@@ -3077,13 +3182,10 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf,
+ ipmi_user_t user = NULL;
+ struct ipmi_lan_addr *lan_addr;
+ struct ipmi_recv_msg *recv_msg;
+- unsigned long flags;
+
+ if (msg->rsp_size < 12) {
+ /* Message not big enough, just ignore it. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->invalid_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, invalid_commands);
+ return 0;
+ }
+
+@@ -3107,23 +3209,23 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf,
+
+ if (user == NULL) {
+ /* We didn't find a user, just give up. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->unhandled_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, unhandled_commands);
+
+- rv = 0; /* Don't do anything with these messages, just
+- allow them to be freed. */
++ /*
++ * Don't do anything with these messages, just allow
++ * them to be freed.
++ */
++ rv = 0;
+ } else {
+ /* Deliver the message to the user. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->handled_commands++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, handled_commands);
+
+ recv_msg = ipmi_alloc_recv_msg();
+ if (!recv_msg) {
+- /* We couldn't allocate memory for the
+- message, so requeue it for handling
+- later. */
++ /*
++ * We couldn't allocate memory for the
++ * message, so requeue it for handling later.
++ */
+ rv = 1;
+ kref_put(&user->refcount, free_user);
+ } else {
+@@ -3137,8 +3239,10 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf,
+ lan_addr->channel = msg->rsp[3] & 0xf;
+ lan_addr->privilege = msg->rsp[3] >> 4;
+
+- /* Extract the rest of the message information
+- from the IPMB header.*/
++ /*
++ * Extract the rest of the message information
++ * from the IPMB header.
++ */
+ recv_msg->user = user;
+ recv_msg->recv_type = IPMI_CMD_RECV_TYPE;
+ recv_msg->msgid = msg->rsp[9] >> 2;
+@@ -3146,8 +3250,10 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf,
+ recv_msg->msg.cmd = msg->rsp[10];
+ recv_msg->msg.data = recv_msg->msg_data;
+
+- /* We chop off 12, not 11 bytes because the checksum
+- at the end also needs to be removed. */
++ /*
++ * We chop off 12, not 11 bytes because the checksum
++ * at the end also needs to be removed.
++ */
+ recv_msg->msg.data_len = msg->rsp_size - 12;
+ memcpy(recv_msg->msg_data,
+ &(msg->rsp[11]),
+@@ -3163,7 +3269,7 @@ static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg,
+ struct ipmi_smi_msg *msg)
+ {
+ struct ipmi_system_interface_addr *smi_addr;
+-
++
+ recv_msg->msgid = 0;
+ smi_addr = (struct ipmi_system_interface_addr *) &(recv_msg->addr);
+ smi_addr->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+@@ -3189,9 +3295,7 @@ static int handle_read_event_rsp(ipmi_smi_t intf,
+
+ if (msg->rsp_size < 19) {
+ /* Message is too small to be an IPMB event. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->invalid_events++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, invalid_events);
+ return 0;
+ }
+
+@@ -3204,12 +3308,12 @@ static int handle_read_event_rsp(ipmi_smi_t intf,
+
+ spin_lock_irqsave(&intf->events_lock, flags);
+
+- spin_lock(&intf->counter_lock);
+- intf->events++;
+- spin_unlock(&intf->counter_lock);
++ ipmi_inc_stat(intf, events);
+
+- /* Allocate and fill in one message for every user that is getting
+- events. */
++ /*
++ * Allocate and fill in one message for every user that is
++ * getting events.
++ */
+ rcu_read_lock();
+ list_for_each_entry_rcu(user, &intf->users, link) {
+ if (!user->gets_events)
+@@ -3223,9 +3327,11 @@ static int handle_read_event_rsp(ipmi_smi_t intf,
+ list_del(&recv_msg->link);
+ ipmi_free_recv_msg(recv_msg);
+ }
+- /* We couldn't allocate memory for the
+- message, so requeue it for handling
+- later. */
++ /*
++ * We couldn't allocate memory for the
++ * message, so requeue it for handling
++ * later.
++ */
+ rv = 1;
+ goto out;
+ }
+@@ -3246,13 +3352,17 @@ static int handle_read_event_rsp(ipmi_smi_t intf,
+ deliver_response(recv_msg);
+ }
+ } else if (intf->waiting_events_count < MAX_EVENTS_IN_QUEUE) {
+- /* No one to receive the message, put it in queue if there's
+- not already too many things in the queue. */
++ /*
++ * No one to receive the message, put it in queue if there's
++ * not already too many things in the queue.
++ */
+ recv_msg = ipmi_alloc_recv_msg();
+ if (!recv_msg) {
+- /* We couldn't allocate memory for the
+- message, so requeue it for handling
+- later. */
++ /*
++ * We couldn't allocate memory for the
++ * message, so requeue it for handling
++ * later.
++ */
+ rv = 1;
+ goto out;
+ }
+@@ -3260,11 +3370,14 @@ static int handle_read_event_rsp(ipmi_smi_t intf,
+ copy_event_into_recv_msg(recv_msg, msg);
+ list_add_tail(&(recv_msg->link), &(intf->waiting_events));
+ intf->waiting_events_count++;
+- } else {
+- /* There's too many things in the queue, discard this
+- message. */
+- printk(KERN_WARNING PFX "Event queue full, discarding an"
+- " incoming event\n");
++ } else if (!intf->event_msg_printed) {
++ /*
++ * There's too many things in the queue, discard this
++ * message.
++ */
++ printk(KERN_WARNING PFX "Event queue full, discarding"
++ " incoming events\n");
++ intf->event_msg_printed = 1;
+ }
+
+ out:
+@@ -3277,16 +3390,15 @@ static int handle_bmc_rsp(ipmi_smi_t intf,
+ struct ipmi_smi_msg *msg)
+ {
+ struct ipmi_recv_msg *recv_msg;
+- unsigned long flags;
+ struct ipmi_user *user;
+
+ recv_msg = (struct ipmi_recv_msg *) msg->user_data;
+- if (recv_msg == NULL)
+- {
+- printk(KERN_WARNING"IPMI message received with no owner. This\n"
+- "could be because of a malformed message, or\n"
+- "because of a hardware error. Contact your\n"
+- "hardware vender for assistance\n");
++ if (recv_msg == NULL) {
++ printk(KERN_WARNING
++ "IPMI message received with no owner. This\n"
++ "could be because of a malformed message, or\n"
++ "because of a hardware error. Contact your\n"
++ "hardware vender for assistance\n");
+ return 0;
+ }
+
+@@ -3294,16 +3406,12 @@ static int handle_bmc_rsp(ipmi_smi_t intf,
+ /* Make sure the user still exists. */
+ if (user && !user->valid) {
+ /* The user for the message went away, so give up. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->unhandled_local_responses++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, unhandled_local_responses);
+ ipmi_free_recv_msg(recv_msg);
+ } else {
+ struct ipmi_system_interface_addr *smi_addr;
+
+- spin_lock_irqsave(&intf->counter_lock, flags);
+- intf->handled_local_responses++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, handled_local_responses);
+ recv_msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
+ recv_msg->msgid = msg->msgid;
+ smi_addr = ((struct ipmi_system_interface_addr *)
+@@ -3324,9 +3432,11 @@ static int handle_bmc_rsp(ipmi_smi_t intf,
+ return 0;
+ }
+
+-/* Handle a new message. Return 1 if the message should be requeued,
+- 0 if the message should be freed, or -1 if the message should not
+- be freed or requeued. */
++/*
++ * Handle a new message. Return 1 if the message should be requeued,
++ * 0 if the message should be freed, or -1 if the message should not
++ * be freed or requeued.
++ */
+ static int handle_new_recv_msg(ipmi_smi_t intf,
+ struct ipmi_smi_msg *msg)
+ {
+@@ -3351,10 +3461,12 @@ static int handle_new_recv_msg(ipmi_smi_t intf,
+ msg->rsp[1] = msg->data[1];
+ msg->rsp[2] = IPMI_ERR_UNSPECIFIED;
+ msg->rsp_size = 3;
+- } else if (((msg->rsp[0] >> 2) != ((msg->data[0] >> 2) | 1))/* Netfn */
+- || (msg->rsp[1] != msg->data[1])) /* Command */
+- {
+- /* The response is not even marginally correct. */
++ } else if (((msg->rsp[0] >> 2) != ((msg->data[0] >> 2) | 1))
++ || (msg->rsp[1] != msg->data[1])) {
++ /*
++ * The NetFN and Command in the response is not even
++ * marginally correct.
++ */
+ printk(KERN_WARNING PFX "BMC returned incorrect response,"
+ " expected netfn %x cmd %x, got netfn %x cmd %x\n",
+ (msg->data[0] >> 2) | 1, msg->data[1],
+@@ -3369,10 +3481,11 @@ static int handle_new_recv_msg(ipmi_smi_t intf,
+
+ if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2))
+ && (msg->rsp[1] == IPMI_SEND_MSG_CMD)
+- && (msg->user_data != NULL))
+- {
+- /* It's a response to a response we sent. For this we
+- deliver a send message response to the user. */
++ && (msg->user_data != NULL)) {
++ /*
++ * It's a response to a response we sent. For this we
++ * deliver a send message response to the user.
++ */
+ struct ipmi_recv_msg *recv_msg = msg->user_data;
+
+ requeue = 0;
+@@ -3398,8 +3511,7 @@ static int handle_new_recv_msg(ipmi_smi_t intf,
+ recv_msg->msg_data[0] = msg->rsp[2];
+ deliver_response(recv_msg);
+ } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2))
+- && (msg->rsp[1] == IPMI_GET_MSG_CMD))
+- {
++ && (msg->rsp[1] == IPMI_GET_MSG_CMD)) {
+ /* It's from the receive queue. */
+ chan = msg->rsp[3] & 0xf;
+ if (chan >= IPMI_MAX_CHANNELS) {
+@@ -3411,12 +3523,16 @@ static int handle_new_recv_msg(ipmi_smi_t intf,
+ switch (intf->channels[chan].medium) {
+ case IPMI_CHANNEL_MEDIUM_IPMB:
+ if (msg->rsp[4] & 0x04) {
+- /* It's a response, so find the
+- requesting message and send it up. */
++ /*
++ * It's a response, so find the
++ * requesting message and send it up.
++ */
+ requeue = handle_ipmb_get_msg_rsp(intf, msg);
+ } else {
+- /* It's a command to the SMS from some other
+- entity. Handle that. */
++ /*
++ * It's a command to the SMS from some other
++ * entity. Handle that.
++ */
+ requeue = handle_ipmb_get_msg_cmd(intf, msg);
+ }
+ break;
+@@ -3424,25 +3540,30 @@ static int handle_new_recv_msg(ipmi_smi_t intf,
+ case IPMI_CHANNEL_MEDIUM_8023LAN:
+ case IPMI_CHANNEL_MEDIUM_ASYNC:
+ if (msg->rsp[6] & 0x04) {
+- /* It's a response, so find the
+- requesting message and send it up. */
++ /*
++ * It's a response, so find the
++ * requesting message and send it up.
++ */
+ requeue = handle_lan_get_msg_rsp(intf, msg);
+ } else {
+- /* It's a command to the SMS from some other
+- entity. Handle that. */
++ /*
++ * It's a command to the SMS from some other
++ * entity. Handle that.
++ */
+ requeue = handle_lan_get_msg_cmd(intf, msg);
+ }
+ break;
+
+ default:
+- /* We don't handle the channel type, so just
+- * free the message. */
++ /*
++ * We don't handle the channel type, so just
++ * free the message.
++ */
+ requeue = 0;
+ }
+
+ } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2))
+- && (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD))
+- {
++ && (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD)) {
+ /* It's an asyncronous event. */
+ requeue = handle_read_event_rsp(intf, msg);
+ } else {
+@@ -3458,71 +3579,82 @@ static int handle_new_recv_msg(ipmi_smi_t intf,
+ void ipmi_smi_msg_received(ipmi_smi_t intf,
+ struct ipmi_smi_msg *msg)
+ {
+- unsigned long flags;
++ unsigned long flags = 0; /* keep us warning-free. */
+ int rv;
++ int run_to_completion;
+
+
+ if ((msg->data_size >= 2)
+ && (msg->data[0] == (IPMI_NETFN_APP_REQUEST << 2))
+ && (msg->data[1] == IPMI_SEND_MSG_CMD)
+- && (msg->user_data == NULL))
+- {
+- /* This is the local response to a command send, start
+- the timer for these. The user_data will not be
+- NULL if this is a response send, and we will let
+- response sends just go through. */
+-
+- /* Check for errors, if we get certain errors (ones
+- that mean basically we can try again later), we
+- ignore them and start the timer. Otherwise we
+- report the error immediately. */
++ && (msg->user_data == NULL)) {
++ /*
++ * This is the local response to a command send, start
++ * the timer for these. The user_data will not be
++ * NULL if this is a response send, and we will let
++ * response sends just go through.
++ */
++
++ /*
++ * Check for errors, if we get certain errors (ones
++ * that mean basically we can try again later), we
++ * ignore them and start the timer. Otherwise we
++ * report the error immediately.
++ */
+ if ((msg->rsp_size >= 3) && (msg->rsp[2] != 0)
+ && (msg->rsp[2] != IPMI_NODE_BUSY_ERR)
+ && (msg->rsp[2] != IPMI_LOST_ARBITRATION_ERR)
+ && (msg->rsp[2] != IPMI_BUS_ERR)
+- && (msg->rsp[2] != IPMI_NAK_ON_WRITE_ERR))
+- {
++ && (msg->rsp[2] != IPMI_NAK_ON_WRITE_ERR)) {
+ int chan = msg->rsp[3] & 0xf;
+
+ /* Got an error sending the message, handle it. */
+- spin_lock_irqsave(&intf->counter_lock, flags);
+ if (chan >= IPMI_MAX_CHANNELS)
+ ; /* This shouldn't happen */
+ else if ((intf->channels[chan].medium
+ == IPMI_CHANNEL_MEDIUM_8023LAN)
+ || (intf->channels[chan].medium
+ == IPMI_CHANNEL_MEDIUM_ASYNC))
+- intf->sent_lan_command_errs++;
++ ipmi_inc_stat(intf, sent_lan_command_errs);
+ else
+- intf->sent_ipmb_command_errs++;
+- spin_unlock_irqrestore(&intf->counter_lock, flags);
++ ipmi_inc_stat(intf, sent_ipmb_command_errs);
+ intf_err_seq(intf, msg->msgid, msg->rsp[2]);
+- } else {
++ } else
+ /* The message was sent, start the timer. */
+ intf_start_seq_timer(intf, msg->msgid);
+- }
+
+ ipmi_free_smi_msg(msg);
+ goto out;
+ }
+
+- /* To preserve message order, if the list is not empty, we
+- tack this message onto the end of the list. */
+- spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
++ /*
++ * To preserve message order, if the list is not empty, we
++ * tack this message onto the end of the list.
++ */
++ run_to_completion = intf->run_to_completion;
++ if (!run_to_completion)
++ spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
+ if (!list_empty(&intf->waiting_msgs)) {
+ list_add_tail(&msg->link, &intf->waiting_msgs);
+- spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
++ if (!run_to_completion)
++ spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
+ goto out;
+ }
+- spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
+-
++ if (!run_to_completion)
++ spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
++
+ rv = handle_new_recv_msg(intf, msg);
+ if (rv > 0) {
+- /* Could not handle the message now, just add it to a
+- list to handle later. */
+- spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
++ /*
++ * Could not handle the message now, just add it to a
++ * list to handle later.
++ */
++ run_to_completion = intf->run_to_completion;
++ if (!run_to_completion)
++ spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
+ list_add_tail(&msg->link, &intf->waiting_msgs);
+- spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
++ if (!run_to_completion)
++ spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
+ } else if (rv == 0) {
+ ipmi_free_smi_msg(msg);
+ }
+@@ -3530,6 +3662,7 @@ void ipmi_smi_msg_received(ipmi_smi_t intf,
+ out:
+ return;
+ }
++EXPORT_SYMBOL(ipmi_smi_msg_received);
+
+ void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf)
+ {
+@@ -3544,7 +3677,7 @@ void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf)
+ }
+ rcu_read_unlock();
+ }
+-
++EXPORT_SYMBOL(ipmi_smi_watchdog_pretimeout);
+
+ static struct ipmi_smi_msg *
+ smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
+@@ -3552,14 +3685,16 @@ smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
+ {
+ struct ipmi_smi_msg *smi_msg = ipmi_alloc_smi_msg();
+ if (!smi_msg)
+- /* If we can't allocate the message, then just return, we
+- get 4 retries, so this should be ok. */
++ /*
++ * If we can't allocate the message, then just return, we
++ * get 4 retries, so this should be ok.
++ */
+ return NULL;
+
+ memcpy(smi_msg->data, recv_msg->msg.data, recv_msg->msg.data_len);
+ smi_msg->data_size = recv_msg->msg.data_len;
+ smi_msg->msgid = STORE_SEQ_IN_MSGID(seq, seqid);
+-
++
+ #ifdef DEBUG_MSGING
+ {
+ int m;
+@@ -3594,28 +3729,26 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
+ ent->inuse = 0;
+ msg = ent->recv_msg;
+ list_add_tail(&msg->link, timeouts);
+- spin_lock(&intf->counter_lock);
+ if (ent->broadcast)
+- intf->timed_out_ipmb_broadcasts++;
++ ipmi_inc_stat(intf, timed_out_ipmb_broadcasts);
+ else if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE)
+- intf->timed_out_lan_commands++;
++ ipmi_inc_stat(intf, timed_out_lan_commands);
+ else
+- intf->timed_out_ipmb_commands++;
+- spin_unlock(&intf->counter_lock);
++ ipmi_inc_stat(intf, timed_out_ipmb_commands);
+ } else {
+ struct ipmi_smi_msg *smi_msg;
+ /* More retries, send again. */
+
+- /* Start with the max timer, set to normal
+- timer after the message is sent. */
++ /*
++ * Start with the max timer, set to normal timer after
++ * the message is sent.
++ */
+ ent->timeout = MAX_MSG_TIMEOUT;
+ ent->retries_left--;
+- spin_lock(&intf->counter_lock);
+ if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE)
+- intf->retransmitted_lan_commands++;
++ ipmi_inc_stat(intf, retransmitted_lan_commands);
+ else
+- intf->retransmitted_ipmb_commands++;
+- spin_unlock(&intf->counter_lock);
++ ipmi_inc_stat(intf, retransmitted_ipmb_commands);
+
+ smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot,
+ ent->seqid);
+@@ -3624,11 +3757,13 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
+
+ spin_unlock_irqrestore(&intf->seq_lock, *flags);
+
+- /* Send the new message. We send with a zero
+- * priority. It timed out, I doubt time is
+- * that critical now, and high priority
+- * messages are really only for messages to the
+- * local MC, which don't get resent. */
++ /*
++ * Send the new message. We send with a zero
++ * priority. It timed out, I doubt time is that
++ * critical now, and high priority messages are really
++ * only for messages to the local MC, which don't get
++ * resent.
++ */
+ handlers = intf->handlers;
+ if (handlers)
+ intf->handlers->sender(intf->send_info,
+@@ -3659,16 +3794,20 @@ static void ipmi_timeout_handler(long timeout_period)
+ list_del(&smi_msg->link);
+ ipmi_free_smi_msg(smi_msg);
+ } else {
+- /* To preserve message order, quit if we
+- can't handle a message. */
++ /*
++ * To preserve message order, quit if we
++ * can't handle a message.
++ */
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
+
+- /* Go through the seq table and find any messages that
+- have timed out, putting them in the timeouts
+- list. */
++ /*
++ * Go through the seq table and find any messages that
++ * have timed out, putting them in the timeouts
++ * list.
++ */
+ INIT_LIST_HEAD(&timeouts);
+ spin_lock_irqsave(&intf->seq_lock, flags);
+ for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++)
+@@ -3694,8 +3833,7 @@ static void ipmi_timeout_handler(long timeout_period)
+ intf->auto_maintenance_timeout
+ -= timeout_period;
+ if (!intf->maintenance_mode
+- && (intf->auto_maintenance_timeout <= 0))
+- {
++ && (intf->auto_maintenance_timeout <= 0)) {
+ intf->maintenance_mode_enable = 0;
+ maintenance_mode_update(intf);
+ }
+@@ -3713,8 +3851,10 @@ static void ipmi_request_event(void)
+ struct ipmi_smi_handlers *handlers;
+
+ rcu_read_lock();
+- /* Called from the timer, no need to check if handlers is
+- * valid. */
++ /*
++ * Called from the timer, no need to check if handlers is
++ * valid.
++ */
+ list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
+ /* No event requests when in maintenance mode. */
+ if (intf->maintenance_mode_enable)
+@@ -3735,10 +3875,12 @@ static struct timer_list ipmi_timer;
+ /* How many jiffies does it take to get to the timeout time. */
+ #define IPMI_TIMEOUT_JIFFIES ((IPMI_TIMEOUT_TIME * HZ) / 1000)
+
+-/* Request events from the queue every second (this is the number of
+- IPMI_TIMEOUT_TIMES between event requests). Hopefully, in the
+- future, IPMI will add a way to know immediately if an event is in
+- the queue and this silliness can go away. */
++/*
++ * Request events from the queue every second (this is the number of
++ * IPMI_TIMEOUT_TIMES between event requests). Hopefully, in the
++ * future, IPMI will add a way to know immediately if an event is in
++ * the queue and this silliness can go away.
++ */
+ #define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME))
+
+ static atomic_t stop_operation;
+@@ -3782,6 +3924,7 @@ struct ipmi_smi_msg *ipmi_alloc_smi_msg(void)
+ }
+ return rv;
+ }
++EXPORT_SYMBOL(ipmi_alloc_smi_msg);
+
+ static void free_recv_msg(struct ipmi_recv_msg *msg)
+ {
+@@ -3789,7 +3932,7 @@ static void free_recv_msg(struct ipmi_recv_msg *msg)
+ kfree(msg);
+ }
+
+-struct ipmi_recv_msg *ipmi_alloc_recv_msg(void)
++static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void)
+ {
+ struct ipmi_recv_msg *rv;
+
+@@ -3808,6 +3951,7 @@ void ipmi_free_recv_msg(struct ipmi_recv_msg *msg)
+ kref_put(&msg->user->refcount, free_user);
+ msg->done(msg);
+ }
++EXPORT_SYMBOL(ipmi_free_recv_msg);
+
+ #ifdef CONFIG_IPMI_PANIC_EVENT
+
+@@ -3825,8 +3969,7 @@ static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
+ if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
+ && (msg->msg.netfn == IPMI_NETFN_SENSOR_EVENT_RESPONSE)
+ && (msg->msg.cmd == IPMI_GET_EVENT_RECEIVER_CMD)
+- && (msg->msg.data[0] == IPMI_CC_NO_ERROR))
+- {
++ && (msg->msg.data[0] == IPMI_CC_NO_ERROR)) {
+ /* A get event receiver command, save it. */
+ intf->event_receiver = msg->msg.data[1];
+ intf->event_receiver_lun = msg->msg.data[2] & 0x3;
+@@ -3838,10 +3981,11 @@ static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
+ if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
+ && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE)
+ && (msg->msg.cmd == IPMI_GET_DEVICE_ID_CMD)
+- && (msg->msg.data[0] == IPMI_CC_NO_ERROR))
+- {
+- /* A get device id command, save if we are an event
+- receiver or generator. */
++ && (msg->msg.data[0] == IPMI_CC_NO_ERROR)) {
++ /*
++ * A get device id command, save if we are an event
++ * receiver or generator.
++ */
+ intf->local_sel_device = (msg->msg.data[6] >> 2) & 1;
+ intf->local_event_generator = (msg->msg.data[6] >> 5) & 1;
+ }
+@@ -3874,8 +4018,10 @@ static void send_panic_events(char *str)
+ data[4] = 0x6f; /* Sensor specific, IPMI table 36-1 */
+ data[5] = 0xa1; /* Runtime stop OEM bytes 2 & 3. */
+
+- /* Put a few breadcrumbs in. Hopefully later we can add more things
+- to make the panic events more useful. */
++ /*
++ * Put a few breadcrumbs in. Hopefully later we can add more things
++ * to make the panic events more useful.
++ */
+ if (str) {
+ data[3] = str[0];
+ data[6] = str[1];
+@@ -3891,6 +4037,7 @@ static void send_panic_events(char *str)
+ /* Interface is not ready. */
+ continue;
+
++ intf->run_to_completion = 1;
+ /* Send the event announcing the panic. */
+ intf->handlers->set_run_to_completion(intf->send_info, 1);
+ i_ipmi_request(NULL,
+@@ -3908,9 +4055,11 @@ static void send_panic_events(char *str)
+ }
+
+ #ifdef CONFIG_IPMI_PANIC_STRING
+- /* On every interface, dump a bunch of OEM event holding the
+- string. */
+- if (!str)
++ /*
++ * On every interface, dump a bunch of OEM event holding the
++ * string.
++ */
++ if (!str)
+ return;
+
+ /* For every registered interface, send the event. */
+@@ -3931,11 +4080,13 @@ static void send_panic_events(char *str)
+ */
+ smp_rmb();
+
+- /* First job here is to figure out where to send the
+- OEM events. There's no way in IPMI to send OEM
+- events using an event send command, so we have to
+- find the SEL to put them in and stick them in
+- there. */
++ /*
++ * First job here is to figure out where to send the
++ * OEM events. There's no way in IPMI to send OEM
++ * events using an event send command, so we have to
++ * find the SEL to put them in and stick them in
++ * there.
++ */
+
+ /* Get capabilities from the get device id. */
+ intf->local_sel_device = 0;
+@@ -3983,24 +4134,29 @@ static void send_panic_events(char *str)
+ }
+ intf->null_user_handler = NULL;
+
+- /* Validate the event receiver. The low bit must not
+- be 1 (it must be a valid IPMB address), it cannot
+- be zero, and it must not be my address. */
+- if (((intf->event_receiver & 1) == 0)
++ /*
++ * Validate the event receiver. The low bit must not
++ * be 1 (it must be a valid IPMB address), it cannot
++ * be zero, and it must not be my address.
++ */
++ if (((intf->event_receiver & 1) == 0)
+ && (intf->event_receiver != 0)
+- && (intf->event_receiver != intf->channels[0].address))
+- {
+- /* The event receiver is valid, send an IPMB
+- message. */
++ && (intf->event_receiver != intf->channels[0].address)) {
++ /*
++ * The event receiver is valid, send an IPMB
++ * message.
++ */
+ ipmb = (struct ipmi_ipmb_addr *) &addr;
+ ipmb->addr_type = IPMI_IPMB_ADDR_TYPE;
+ ipmb->channel = 0; /* FIXME - is this right? */
+ ipmb->lun = intf->event_receiver_lun;
+ ipmb->slave_addr = intf->event_receiver;
+ } else if (intf->local_sel_device) {
+- /* The event receiver was not valid (or was
+- me), but I am an SEL device, just dump it
+- in my SEL. */
++ /*
++ * The event receiver was not valid (or was
++ * me), but I am an SEL device, just dump it
++ * in my SEL.
++ */
+ si = (struct ipmi_system_interface_addr *) &addr;
+ si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+ si->channel = IPMI_BMC_CHANNEL;
+@@ -4008,7 +4164,6 @@ static void send_panic_events(char *str)
+ } else
+ continue; /* No where to send the event. */
+
+-
+ msg.netfn = IPMI_NETFN_STORAGE_REQUEST; /* Storage. */
+ msg.cmd = IPMI_ADD_SEL_ENTRY_CMD;
+ msg.data = data;
+@@ -4025,8 +4180,10 @@ static void send_panic_events(char *str)
+ data[2] = 0xf0; /* OEM event without timestamp. */
+ data[3] = intf->channels[0].address;
+ data[4] = j++; /* sequence # */
+- /* Always give 11 bytes, so strncpy will fill
+- it with zeroes for me. */
++ /*
++ * Always give 11 bytes, so strncpy will fill
++ * it with zeroes for me.
++ */
+ strncpy(data+5, p, 11);
+ p += size;
+
+@@ -4043,7 +4200,7 @@ static void send_panic_events(char *str)
+ intf->channels[0].lun,
+ 0, 1); /* no retry, and no wait. */
+ }
+- }
++ }
+ #endif /* CONFIG_IPMI_PANIC_STRING */
+ }
+ #endif /* CONFIG_IPMI_PANIC_EVENT */
+@@ -4052,7 +4209,7 @@ static int has_panicked;
+
+ static int panic_event(struct notifier_block *this,
+ unsigned long event,
+- void *ptr)
++ void *ptr)
+ {
+ ipmi_smi_t intf;
+
+@@ -4066,6 +4223,7 @@ static int panic_event(struct notifier_block *this,
+ /* Interface is not ready. */
+ continue;
+
++ intf->run_to_completion = 1;
+ intf->handlers->set_run_to_completion(intf->send_info, 1);
+ }
+
+@@ -4133,11 +4291,16 @@ static __exit void cleanup_ipmi(void)
+
+ atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block);
+
+- /* This can't be called if any interfaces exist, so no worry about
+- shutting down the interfaces. */
++ /*
++ * This can't be called if any interfaces exist, so no worry
++ * about shutting down the interfaces.
++ */
+
+- /* Tell the timer to stop, then wait for it to stop. This avoids
+- problems with race conditions removing the timer here. */
++ /*
++ * Tell the timer to stop, then wait for it to stop. This
++ * avoids problems with race conditions removing the timer
++ * here.
++ */
+ atomic_inc(&stop_operation);
+ del_timer_sync(&ipmi_timer);
+
+@@ -4164,31 +4327,6 @@ module_exit(cleanup_ipmi);
+ module_init(ipmi_init_msghandler_mod);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Corey Minyard <minyard at mvista.com>");
+-MODULE_DESCRIPTION("Incoming and outgoing message routing for an IPMI interface.");
++MODULE_DESCRIPTION("Incoming and outgoing message routing for an IPMI"
++ " interface.");
+ MODULE_VERSION(IPMI_DRIVER_VERSION);
+-
+-EXPORT_SYMBOL(ipmi_create_user);
+-EXPORT_SYMBOL(ipmi_destroy_user);
+-EXPORT_SYMBOL(ipmi_get_version);
+-EXPORT_SYMBOL(ipmi_request_settime);
+-EXPORT_SYMBOL(ipmi_request_supply_msgs);
+-EXPORT_SYMBOL(ipmi_poll_interface);
+-EXPORT_SYMBOL(ipmi_register_smi);
+-EXPORT_SYMBOL(ipmi_unregister_smi);
+-EXPORT_SYMBOL(ipmi_register_for_cmd);
+-EXPORT_SYMBOL(ipmi_unregister_for_cmd);
+-EXPORT_SYMBOL(ipmi_smi_msg_received);
+-EXPORT_SYMBOL(ipmi_smi_watchdog_pretimeout);
+-EXPORT_SYMBOL(ipmi_alloc_smi_msg);
+-EXPORT_SYMBOL(ipmi_addr_length);
+-EXPORT_SYMBOL(ipmi_validate_addr);
+-EXPORT_SYMBOL(ipmi_set_gets_events);
+-EXPORT_SYMBOL(ipmi_smi_watcher_register);
+-EXPORT_SYMBOL(ipmi_smi_watcher_unregister);
+-EXPORT_SYMBOL(ipmi_set_my_address);
+-EXPORT_SYMBOL(ipmi_get_my_address);
+-EXPORT_SYMBOL(ipmi_set_my_LUN);
+-EXPORT_SYMBOL(ipmi_get_my_LUN);
+-EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
+-EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
+-EXPORT_SYMBOL(ipmi_free_recv_msg);
+diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
+index b86186d..a261bd7 100644
+--- a/drivers/char/ipmi/ipmi_poweroff.c
++++ b/drivers/char/ipmi/ipmi_poweroff.c
+@@ -87,7 +87,10 @@ MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog "
+
+ /* parameter definition to allow user to flag power cycle */
+ module_param(poweroff_powercycle, int, 0644);
+-MODULE_PARM_DESC(poweroff_powercycle, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
++MODULE_PARM_DESC(poweroff_powercycle,
++ " Set to non-zero to enable power cycle instead of power"
++ " down. Power cycle is contingent on hardware support,"
++ " otherwise it defaults back to power down.");
+
+ /* Stuff from the get device id command. */
+ static unsigned int mfg_id;
+@@ -95,22 +98,25 @@ static unsigned int prod_id;
+ static unsigned char capabilities;
+ static unsigned char ipmi_version;
+
+-/* We use our own messages for this operation, we don't let the system
+- allocate them, since we may be in a panic situation. The whole
+- thing is single-threaded, anyway, so multiple messages are not
+- required. */
++/*
++ * We use our own messages for this operation, we don't let the system
++ * allocate them, since we may be in a panic situation. The whole
++ * thing is single-threaded, anyway, so multiple messages are not
++ * required.
++ */
++static atomic_t dummy_count = ATOMIC_INIT(0);
+ static void dummy_smi_free(struct ipmi_smi_msg *msg)
+ {
++ atomic_dec(&dummy_count);
+ }
+ static void dummy_recv_free(struct ipmi_recv_msg *msg)
+ {
++ atomic_dec(&dummy_count);
+ }
+-static struct ipmi_smi_msg halt_smi_msg =
+-{
++static struct ipmi_smi_msg halt_smi_msg = {
+ .done = dummy_smi_free
+ };
+-static struct ipmi_recv_msg halt_recv_msg =
+-{
++static struct ipmi_recv_msg halt_recv_msg = {
+ .done = dummy_recv_free
+ };
+
+@@ -127,8 +133,7 @@ static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data)
+ complete(comp);
+ }
+
+-static struct ipmi_user_hndl ipmi_poweroff_handler =
+-{
++static struct ipmi_user_hndl ipmi_poweroff_handler = {
+ .ipmi_recv_hndl = receive_handler
+ };
+
+@@ -152,17 +157,28 @@ static int ipmi_request_wait_for_response(ipmi_user_t user,
+ return halt_recv_msg.msg.data[0];
+ }
+
+-/* We are in run-to-completion mode, no completion is desired. */
++/* Wait for message to complete, spinning. */
+ static int ipmi_request_in_rc_mode(ipmi_user_t user,
+ struct ipmi_addr *addr,
+ struct kernel_ipmi_msg *send_msg)
+ {
+ int rv;
+
++ atomic_set(&dummy_count, 2);
+ rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL,
+ &halt_smi_msg, &halt_recv_msg, 0);
+- if (rv)
++ if (rv) {
++ atomic_set(&dummy_count, 0);
+ return rv;
++ }
++
++ /*
++ * Spin until our message is done.
++ */
++ while (atomic_read(&dummy_count) > 0) {
++ ipmi_poll_interface(user);
++ cpu_relax();
++ }
+
+ return halt_recv_msg.msg.data[0];
+ }
+@@ -184,47 +200,47 @@ static int ipmi_request_in_rc_mode(ipmi_user_t user,
+
+ static void (*atca_oem_poweroff_hook)(ipmi_user_t user);
+
+-static void pps_poweroff_atca (ipmi_user_t user)
++static void pps_poweroff_atca(ipmi_user_t user)
+ {
+- struct ipmi_system_interface_addr smi_addr;
+- struct kernel_ipmi_msg send_msg;
+- int rv;
+- /*
+- * Configure IPMI address for local access
+- */
+- smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+- smi_addr.channel = IPMI_BMC_CHANNEL;
+- smi_addr.lun = 0;
+-
+- printk(KERN_INFO PFX "PPS powerdown hook used");
+-
+- send_msg.netfn = IPMI_NETFN_OEM;
+- send_msg.cmd = IPMI_ATCA_PPS_GRACEFUL_RESTART;
+- send_msg.data = IPMI_ATCA_PPS_IANA;
+- send_msg.data_len = 3;
+- rv = ipmi_request_in_rc_mode(user,
+- (struct ipmi_addr *) &smi_addr,
+- &send_msg);
+- if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE) {
+- printk(KERN_ERR PFX "Unable to send ATCA ,"
+- " IPMI error 0x%x\n", rv);
+- }
++ struct ipmi_system_interface_addr smi_addr;
++ struct kernel_ipmi_msg send_msg;
++ int rv;
++ /*
++ * Configure IPMI address for local access
++ */
++ smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr.channel = IPMI_BMC_CHANNEL;
++ smi_addr.lun = 0;
++
++ printk(KERN_INFO PFX "PPS powerdown hook used");
++
++ send_msg.netfn = IPMI_NETFN_OEM;
++ send_msg.cmd = IPMI_ATCA_PPS_GRACEFUL_RESTART;
++ send_msg.data = IPMI_ATCA_PPS_IANA;
++ send_msg.data_len = 3;
++ rv = ipmi_request_in_rc_mode(user,
++ (struct ipmi_addr *) &smi_addr,
++ &send_msg);
++ if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE) {
++ printk(KERN_ERR PFX "Unable to send ATCA ,"
++ " IPMI error 0x%x\n", rv);
++ }
+ return;
+ }
+
+-static int ipmi_atca_detect (ipmi_user_t user)
++static int ipmi_atca_detect(ipmi_user_t user)
+ {
+ struct ipmi_system_interface_addr smi_addr;
+ struct kernel_ipmi_msg send_msg;
+ int rv;
+ unsigned char data[1];
+
+- /*
+- * Configure IPMI address for local access
+- */
+- smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+- smi_addr.channel = IPMI_BMC_CHANNEL;
+- smi_addr.lun = 0;
++ /*
++ * Configure IPMI address for local access
++ */
++ smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr.channel = IPMI_BMC_CHANNEL;
++ smi_addr.lun = 0;
+
+ /*
+ * Use get address info to check and see if we are ATCA
+@@ -238,28 +254,30 @@ static int ipmi_atca_detect (ipmi_user_t user)
+ (struct ipmi_addr *) &smi_addr,
+ &send_msg);
+
+- printk(KERN_INFO PFX "ATCA Detect mfg 0x%X prod 0x%X\n", mfg_id, prod_id);
+- if((mfg_id == IPMI_MOTOROLA_MANUFACTURER_ID)
+- && (prod_id == IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID)) {
+- printk(KERN_INFO PFX "Installing Pigeon Point Systems Poweroff Hook\n");
++ printk(KERN_INFO PFX "ATCA Detect mfg 0x%X prod 0x%X\n",
++ mfg_id, prod_id);
++ if ((mfg_id == IPMI_MOTOROLA_MANUFACTURER_ID)
++ && (prod_id == IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID)) {
++ printk(KERN_INFO PFX
++ "Installing Pigeon Point Systems Poweroff Hook\n");
+ atca_oem_poweroff_hook = pps_poweroff_atca;
+ }
+ return !rv;
+ }
+
+-static void ipmi_poweroff_atca (ipmi_user_t user)
++static void ipmi_poweroff_atca(ipmi_user_t user)
+ {
+ struct ipmi_system_interface_addr smi_addr;
+ struct kernel_ipmi_msg send_msg;
+ int rv;
+ unsigned char data[4];
+
+- /*
+- * Configure IPMI address for local access
+- */
+- smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+- smi_addr.channel = IPMI_BMC_CHANNEL;
+- smi_addr.lun = 0;
++ /*
++ * Configure IPMI address for local access
++ */
++ smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr.channel = IPMI_BMC_CHANNEL;
++ smi_addr.lun = 0;
+
+ printk(KERN_INFO PFX "Powering down via ATCA power command\n");
+
+@@ -273,23 +291,24 @@ static void ipmi_poweroff_atca (ipmi_user_t user)
+ data[2] = 0; /* Power Level */
+ data[3] = 0; /* Don't change saved presets */
+ send_msg.data = data;
+- send_msg.data_len = sizeof (data);
++ send_msg.data_len = sizeof(data);
+ rv = ipmi_request_in_rc_mode(user,
+ (struct ipmi_addr *) &smi_addr,
+ &send_msg);
+- /** At this point, the system may be shutting down, and most
+- ** serial drivers (if used) will have interrupts turned off
+- ** it may be better to ignore IPMI_UNKNOWN_ERR_COMPLETION_CODE
+- ** return code
+- **/
+- if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE) {
++ /*
++ * At this point, the system may be shutting down, and most
++ * serial drivers (if used) will have interrupts turned off
++ * it may be better to ignore IPMI_UNKNOWN_ERR_COMPLETION_CODE
++ * return code
++ */
++ if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE) {
+ printk(KERN_ERR PFX "Unable to send ATCA powerdown message,"
+ " IPMI error 0x%x\n", rv);
+ goto out;
+ }
+
+- if(atca_oem_poweroff_hook)
+- return atca_oem_poweroff_hook(user);
++ if (atca_oem_poweroff_hook)
++ atca_oem_poweroff_hook(user);
+ out:
+ return;
+ }
+@@ -310,13 +329,13 @@ static void ipmi_poweroff_atca (ipmi_user_t user)
+ #define IPMI_CPI1_PRODUCT_ID 0x000157
+ #define IPMI_CPI1_MANUFACTURER_ID 0x0108
+
+-static int ipmi_cpi1_detect (ipmi_user_t user)
++static int ipmi_cpi1_detect(ipmi_user_t user)
+ {
+ return ((mfg_id == IPMI_CPI1_MANUFACTURER_ID)
+ && (prod_id == IPMI_CPI1_PRODUCT_ID));
+ }
+
+-static void ipmi_poweroff_cpi1 (ipmi_user_t user)
++static void ipmi_poweroff_cpi1(ipmi_user_t user)
+ {
+ struct ipmi_system_interface_addr smi_addr;
+ struct ipmi_ipmb_addr ipmb_addr;
+@@ -328,12 +347,12 @@ static void ipmi_poweroff_cpi1 (ipmi_user_t user)
+ unsigned char aer_addr;
+ unsigned char aer_lun;
+
+- /*
+- * Configure IPMI address for local access
+- */
+- smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+- smi_addr.channel = IPMI_BMC_CHANNEL;
+- smi_addr.lun = 0;
++ /*
++ * Configure IPMI address for local access
++ */
++ smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr.channel = IPMI_BMC_CHANNEL;
++ smi_addr.lun = 0;
+
+ printk(KERN_INFO PFX "Powering down via CPI1 power command\n");
+
+@@ -425,7 +444,7 @@ static void ipmi_poweroff_cpi1 (ipmi_user_t user)
+ */
+
+ #define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00}
+-static int ipmi_dell_chassis_detect (ipmi_user_t user)
++static int ipmi_dell_chassis_detect(ipmi_user_t user)
+ {
+ const char ipmi_version_major = ipmi_version & 0xF;
+ const char ipmi_version_minor = (ipmi_version >> 4) & 0xF;
+@@ -444,25 +463,25 @@ static int ipmi_dell_chassis_detect (ipmi_user_t user)
+ #define IPMI_NETFN_CHASSIS_REQUEST 0
+ #define IPMI_CHASSIS_CONTROL_CMD 0x02
+
+-static int ipmi_chassis_detect (ipmi_user_t user)
++static int ipmi_chassis_detect(ipmi_user_t user)
+ {
+ /* Chassis support, use it. */
+ return (capabilities & 0x80);
+ }
+
+-static void ipmi_poweroff_chassis (ipmi_user_t user)
++static void ipmi_poweroff_chassis(ipmi_user_t user)
+ {
+ struct ipmi_system_interface_addr smi_addr;
+ struct kernel_ipmi_msg send_msg;
+ int rv;
+ unsigned char data[1];
+
+- /*
+- * Configure IPMI address for local access
+- */
+- smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+- smi_addr.channel = IPMI_BMC_CHANNEL;
+- smi_addr.lun = 0;
++ /*
++ * Configure IPMI address for local access
++ */
++ smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr.channel = IPMI_BMC_CHANNEL;
++ smi_addr.lun = 0;
+
+ powercyclefailed:
+ printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n",
+@@ -525,15 +544,13 @@ static struct poweroff_function poweroff_functions[] = {
+
+
+ /* Called on a powerdown request. */
+-static void ipmi_poweroff_function (void)
++static void ipmi_poweroff_function(void)
+ {
+ if (!ready)
+ return;
+
+ /* Use run-to-completion mode, since interrupts may be off. */
+- ipmi_user_set_run_to_completion(ipmi_user, 1);
+ specific_poweroff_func(ipmi_user);
+- ipmi_user_set_run_to_completion(ipmi_user, 0);
+ }
+
+ /* Wait for an IPMI interface to be installed, the first one installed
+@@ -561,13 +578,13 @@ static void ipmi_po_new_smi(int if_num, struct device *device)
+
+ ipmi_ifnum = if_num;
+
+- /*
+- * Do a get device ide and store some results, since this is
++ /*
++ * Do a get device ide and store some results, since this is
+ * used by several functions.
+- */
+- smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+- smi_addr.channel = IPMI_BMC_CHANNEL;
+- smi_addr.lun = 0;
++ */
++ smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr.channel = IPMI_BMC_CHANNEL;
++ smi_addr.lun = 0;
+
+ send_msg.netfn = IPMI_NETFN_APP_REQUEST;
+ send_msg.cmd = IPMI_GET_DEVICE_ID_CMD;
+@@ -632,8 +649,7 @@ static void ipmi_po_smi_gone(int if_num)
+ pm_power_off = old_poweroff_func;
+ }
+
+-static struct ipmi_smi_watcher smi_watcher =
+-{
++static struct ipmi_smi_watcher smi_watcher = {
+ .owner = THIS_MODULE,
+ .new_smi = ipmi_po_new_smi,
+ .smi_gone = ipmi_po_smi_gone
+@@ -675,12 +691,12 @@ static struct ctl_table_header *ipmi_table_header;
+ /*
+ * Startup and shutdown functions.
+ */
+-static int ipmi_poweroff_init (void)
++static int ipmi_poweroff_init(void)
+ {
+ int rv;
+
+- printk (KERN_INFO "Copyright (C) 2004 MontaVista Software -"
+- " IPMI Powerdown via sys_reboot.\n");
++ printk(KERN_INFO "Copyright (C) 2004 MontaVista Software -"
++ " IPMI Powerdown via sys_reboot.\n");
+
+ if (poweroff_powercycle)
+ printk(KERN_INFO PFX "Power cycle is enabled.\n");
+diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
+index 4f560d0..5a54555 100644
+--- a/drivers/char/ipmi/ipmi_si_intf.c
++++ b/drivers/char/ipmi/ipmi_si_intf.c
+@@ -80,7 +80,7 @@
+ #define SI_USEC_PER_JIFFY (1000000/HZ)
+ #define SI_TIMEOUT_JIFFIES (SI_TIMEOUT_TIME_USEC/SI_USEC_PER_JIFFY)
+ #define SI_SHORT_TIMEOUT_USEC 250 /* .25ms when the SM request a
+- short timeout */
++ short timeout */
+
+ /* Bit for BMC global enables. */
+ #define IPMI_BMC_RCV_MSG_INTR 0x01
+@@ -114,14 +114,61 @@ static char *si_to_str[] = { "kcs", "smic", "bt" };
+
+ #define DEVICE_NAME "ipmi_si"
+
+-static struct device_driver ipmi_driver =
+-{
++static struct device_driver ipmi_driver = {
+ .name = DEVICE_NAME,
+ .bus = &platform_bus_type
+ };
+
+-struct smi_info
+-{
++
++/*
++ * Indexes into stats[] in smi_info below.
++ */
++enum si_stat_indexes {
++ /*
++ * Number of times the driver requested a timer while an operation
++ * was in progress.
++ */
++ SI_STAT_short_timeouts = 0,
++
++ /*
++ * Number of times the driver requested a timer while nothing was in
++ * progress.
++ */
++ SI_STAT_long_timeouts,
++
++ /* Number of times the interface was idle while being polled. */
++ SI_STAT_idles,
++
++ /* Number of interrupts the driver handled. */
++ SI_STAT_interrupts,
++
++ /* Number of time the driver got an ATTN from the hardware. */
++ SI_STAT_attentions,
++
++ /* Number of times the driver requested flags from the hardware. */
++ SI_STAT_flag_fetches,
++
++ /* Number of times the hardware didn't follow the state machine. */
++ SI_STAT_hosed_count,
++
++ /* Number of completed messages. */
++ SI_STAT_complete_transactions,
++
++ /* Number of IPMI events received from the hardware. */
++ SI_STAT_events,
++
++ /* Number of watchdog pretimeouts. */
++ SI_STAT_watchdog_pretimeouts,
++
++ /* Number of asyncronous messages received. */
++ SI_STAT_incoming_messages,
++
++
++ /* This *must* remain last, add new values above this. */
++ SI_NUM_STATS
++};
++
++struct smi_info {
+ int intf_num;
+ ipmi_smi_t intf;
+ struct si_sm_data *si_sm;
+@@ -134,8 +181,10 @@ struct smi_info
+ struct ipmi_smi_msg *curr_msg;
+ enum si_intf_state si_state;
+
+- /* Used to handle the various types of I/O that can occur with
+- IPMI */
++ /*
++ * Used to handle the various types of I/O that can occur with
++ * IPMI
++ */
+ struct si_sm_io io;
+ int (*io_setup)(struct smi_info *info);
+ void (*io_cleanup)(struct smi_info *info);
+@@ -146,15 +195,18 @@ struct smi_info
+ void (*addr_source_cleanup)(struct smi_info *info);
+ void *addr_source_data;
+
+- /* Per-OEM handler, called from handle_flags().
+- Returns 1 when handle_flags() needs to be re-run
+- or 0 indicating it set si_state itself.
+- */
++ /*
++ * Per-OEM handler, called from handle_flags(). Returns 1
++ * when handle_flags() needs to be re-run or 0 indicating it
++ * set si_state itself.
++ */
+ int (*oem_data_avail_handler)(struct smi_info *smi_info);
+
+- /* Flags from the last GET_MSG_FLAGS command, used when an ATTN
+- is set to hold the flags until we are done handling everything
+- from the flags. */
++ /*
++ * Flags from the last GET_MSG_FLAGS command, used when an ATTN
++ * is set to hold the flags until we are done handling everything
++ * from the flags.
++ */
+ #define RECEIVE_MSG_AVAIL 0x01
+ #define EVENT_MSG_BUFFER_FULL 0x02
+ #define WDT_PRE_TIMEOUT_INT 0x08
+@@ -162,25 +214,31 @@ struct smi_info
+ #define OEM1_DATA_AVAIL 0x40
+ #define OEM2_DATA_AVAIL 0x80
+ #define OEM_DATA_AVAIL (OEM0_DATA_AVAIL | \
+- OEM1_DATA_AVAIL | \
+- OEM2_DATA_AVAIL)
++ OEM1_DATA_AVAIL | \
++ OEM2_DATA_AVAIL)
+ unsigned char msg_flags;
+
+- /* If set to true, this will request events the next time the
+- state machine is idle. */
++ /*
++ * If set to true, this will request events the next time the
++ * state machine is idle.
++ */
+ atomic_t req_events;
+
+- /* If true, run the state machine to completion on every send
+- call. Generally used after a panic to make sure stuff goes
+- out. */
++ /*
++ * If true, run the state machine to completion on every send
++ * call. Generally used after a panic to make sure stuff goes
++ * out.
++ */
+ int run_to_completion;
+
+ /* The I/O port of an SI interface. */
+ int port;
+
+- /* The space between start addresses of the two ports. For
+- instance, if the first port is 0xca2 and the spacing is 4, then
+- the second port is 0xca6. */
++ /*
++ * The space between start addresses of the two ports. For
++ * instance, if the first port is 0xca2 and the spacing is 4, then
++ * the second port is 0xca6.
++ */
+ unsigned int spacing;
+
+ /* zero if no irq; */
+@@ -195,10 +253,12 @@ struct smi_info
+ /* Used to gracefully stop the timer without race conditions. */
+ atomic_t stop_operation;
+
+- /* The driver will disable interrupts when it gets into a
+- situation where it cannot handle messages due to lack of
+- memory. Once that situation clears up, it will re-enable
+- interrupts. */
++ /*
++ * The driver will disable interrupts when it gets into a
++ * situation where it cannot handle messages due to lack of
++ * memory. Once that situation clears up, it will re-enable
++ * interrupts.
++ */
+ int interrupt_disabled;
+
+ /* From the get device id response... */
+@@ -208,33 +268,28 @@ struct smi_info
+ struct device *dev;
+ struct platform_device *pdev;
+
+- /* True if we allocated the device, false if it came from
+- * someplace else (like PCI). */
++ /*
++ * True if we allocated the device, false if it came from
++ * someplace else (like PCI).
++ */
+ int dev_registered;
+
+ /* Slave address, could be reported from DMI. */
+ unsigned char slave_addr;
+
+ /* Counters and things for the proc filesystem. */
+- spinlock_t count_lock;
+- unsigned long short_timeouts;
+- unsigned long long_timeouts;
+- unsigned long timeout_restarts;
+- unsigned long idles;
+- unsigned long interrupts;
+- unsigned long attentions;
+- unsigned long flag_fetches;
+- unsigned long hosed_count;
+- unsigned long complete_transactions;
+- unsigned long events;
+- unsigned long watchdog_pretimeouts;
+- unsigned long incoming_messages;
+-
+- struct task_struct *thread;
++ atomic_t stats[SI_NUM_STATS];
++
++ struct task_struct *thread;
+
+ struct list_head link;
+ };
+
++#define smi_inc_stat(smi, stat) \
++ atomic_inc(&(smi)->stats[SI_STAT_ ## stat])
++#define smi_get_stat(smi, stat) \
++ ((unsigned int) atomic_read(&(smi)->stats[SI_STAT_ ## stat]))
++
+ #define SI_MAX_PARMS 4
+
+ static int force_kipmid[SI_MAX_PARMS];
+@@ -246,7 +301,7 @@ static int try_smi_init(struct smi_info *smi);
+ static void cleanup_one_si(struct smi_info *to_clean);
+
+ static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list);
+-static int register_xaction_notifier(struct notifier_block * nb)
++static int register_xaction_notifier(struct notifier_block *nb)
+ {
+ return atomic_notifier_chain_register(&xaction_notifier_list, nb);
+ }
+@@ -255,7 +310,7 @@ static void deliver_recv_msg(struct smi_info *smi_info,
+ struct ipmi_smi_msg *msg)
+ {
+ /* Deliver the message to the upper layer with the lock
+- released. */
++ released. */
+ spin_unlock(&(smi_info->si_lock));
+ ipmi_smi_msg_received(smi_info->intf, msg);
+ spin_lock(&(smi_info->si_lock));
+@@ -287,9 +342,12 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
+ struct timeval t;
+ #endif
+
+- /* No need to save flags, we aleady have interrupts off and we
+- already hold the SMI lock. */
+- spin_lock(&(smi_info->msg_lock));
++ /*
++ * No need to save flags, we aleady have interrupts off and we
++ * already hold the SMI lock.
++ */
++ if (!smi_info->run_to_completion)
++ spin_lock(&(smi_info->msg_lock));
+
+ /* Pick the high priority queue first. */
+ if (!list_empty(&(smi_info->hp_xmit_msgs))) {
+@@ -310,7 +368,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
+ link);
+ #ifdef DEBUG_TIMING
+ do_gettimeofday(&t);
+- printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++ printk(KERN_DEBUG "**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec);
+ #endif
+ err = atomic_notifier_call_chain(&xaction_notifier_list,
+ 0, smi_info);
+@@ -322,14 +380,14 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
+ smi_info->si_sm,
+ smi_info->curr_msg->data,
+ smi_info->curr_msg->data_size);
+- if (err) {
++ if (err)
+ return_hosed_msg(smi_info, err);
+- }
+
+ rv = SI_SM_CALL_WITHOUT_DELAY;
+ }
+- out:
+- spin_unlock(&(smi_info->msg_lock));
++ out:
++ if (!smi_info->run_to_completion)
++ spin_unlock(&(smi_info->msg_lock));
+
+ return rv;
+ }
+@@ -338,8 +396,10 @@ static void start_enable_irq(struct smi_info *smi_info)
+ {
+ unsigned char msg[2];
+
+- /* If we are enabling interrupts, we have to tell the
+- BMC to use them. */
++ /*
++ * If we are enabling interrupts, we have to tell the
++ * BMC to use them.
++ */
+ msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
+ msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
+
+@@ -371,10 +431,12 @@ static void start_clear_flags(struct smi_info *smi_info)
+ smi_info->si_state = SI_CLEARING_FLAGS;
+ }
+
+-/* When we have a situtaion where we run out of memory and cannot
+- allocate messages, we just leave them in the BMC and run the system
+- polled until we can allocate some memory. Once we have some
+- memory, we will re-enable the interrupt. */
++/*
++ * When we have a situtaion where we run out of memory and cannot
++ * allocate messages, we just leave them in the BMC and run the system
++ * polled until we can allocate some memory. Once we have some
++ * memory, we will re-enable the interrupt.
++ */
+ static inline void disable_si_irq(struct smi_info *smi_info)
+ {
+ if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
+@@ -396,9 +458,7 @@ static void handle_flags(struct smi_info *smi_info)
+ retry:
+ if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) {
+ /* Watchdog pre-timeout */
+- spin_lock(&smi_info->count_lock);
+- smi_info->watchdog_pretimeouts++;
+- spin_unlock(&smi_info->count_lock);
++ smi_inc_stat(smi_info, watchdog_pretimeouts);
+
+ start_clear_flags(smi_info);
+ smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT;
+@@ -444,12 +504,11 @@ static void handle_flags(struct smi_info *smi_info)
+ smi_info->curr_msg->data_size);
+ smi_info->si_state = SI_GETTING_EVENTS;
+ } else if (smi_info->msg_flags & OEM_DATA_AVAIL &&
+- smi_info->oem_data_avail_handler) {
++ smi_info->oem_data_avail_handler) {
+ if (smi_info->oem_data_avail_handler(smi_info))
+ goto retry;
+- } else {
++ } else
+ smi_info->si_state = SI_NORMAL;
+- }
+ }
+
+ static void handle_transaction_done(struct smi_info *smi_info)
+@@ -459,7 +518,7 @@ static void handle_transaction_done(struct smi_info *smi_info)
+ struct timeval t;
+
+ do_gettimeofday(&t);
+- printk("**Done: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++ printk(KERN_DEBUG "**Done: %d.%9.9d\n", t.tv_sec, t.tv_usec);
+ #endif
+ switch (smi_info->si_state) {
+ case SI_NORMAL:
+@@ -472,9 +531,11 @@ static void handle_transaction_done(struct smi_info *smi_info)
+ smi_info->curr_msg->rsp,
+ IPMI_MAX_MSG_LENGTH);
+
+- /* Do this here becase deliver_recv_msg() releases the
+- lock, and a new message can be put in during the
+- time the lock is released. */
++ /*
++ * Do this here becase deliver_recv_msg() releases the
++ * lock, and a new message can be put in during the
++ * time the lock is released.
++ */
+ msg = smi_info->curr_msg;
+ smi_info->curr_msg = NULL;
+ deliver_recv_msg(smi_info, msg);
+@@ -488,12 +549,13 @@ static void handle_transaction_done(struct smi_info *smi_info)
+ /* We got the flags from the SMI, now handle them. */
+ len = smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
+ if (msg[2] != 0) {
+- /* Error fetching flags, just give up for
+- now. */
++ /* Error fetching flags, just give up for now. */
+ smi_info->si_state = SI_NORMAL;
+ } else if (len < 4) {
+- /* Hmm, no flags. That's technically illegal, but
+- don't use uninitialized data. */
++ /*
++ * Hmm, no flags. That's technically illegal, but
++ * don't use uninitialized data.
++ */
+ smi_info->si_state = SI_NORMAL;
+ } else {
+ smi_info->msg_flags = msg[3];
+@@ -530,9 +592,11 @@ static void handle_transaction_done(struct smi_info *smi_info)
+ smi_info->curr_msg->rsp,
+ IPMI_MAX_MSG_LENGTH);
+
+- /* Do this here becase deliver_recv_msg() releases the
+- lock, and a new message can be put in during the
+- time the lock is released. */
++ /*
++ * Do this here becase deliver_recv_msg() releases the
++ * lock, and a new message can be put in during the
++ * time the lock is released.
++ */
+ msg = smi_info->curr_msg;
+ smi_info->curr_msg = NULL;
+ if (msg->rsp[2] != 0) {
+@@ -543,14 +607,14 @@ static void handle_transaction_done(struct smi_info *smi_info)
+ smi_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
+ handle_flags(smi_info);
+ } else {
+- spin_lock(&smi_info->count_lock);
+- smi_info->events++;
+- spin_unlock(&smi_info->count_lock);
+-
+- /* Do this before we deliver the message
+- because delivering the message releases the
+- lock and something else can mess with the
+- state. */
++ smi_inc_stat(smi_info, events);
++
++ /*
++ * Do this before we deliver the message
++ * because delivering the message releases the
++ * lock and something else can mess with the
++ * state.
++ */
+ handle_flags(smi_info);
+
+ deliver_recv_msg(smi_info, msg);
+@@ -566,9 +630,11 @@ static void handle_transaction_done(struct smi_info *smi_info)
+ smi_info->curr_msg->rsp,
+ IPMI_MAX_MSG_LENGTH);
+
+- /* Do this here becase deliver_recv_msg() releases the
+- lock, and a new message can be put in during the
+- time the lock is released. */
++ /*
++ * Do this here becase deliver_recv_msg() releases the
++ * lock, and a new message can be put in during the
++ * time the lock is released.
++ */
+ msg = smi_info->curr_msg;
+ smi_info->curr_msg = NULL;
+ if (msg->rsp[2] != 0) {
+@@ -579,14 +645,14 @@ static void handle_transaction_done(struct smi_info *smi_info)
+ smi_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
+ handle_flags(smi_info);
+ } else {
+- spin_lock(&smi_info->count_lock);
+- smi_info->incoming_messages++;
+- spin_unlock(&smi_info->count_lock);
+-
+- /* Do this before we deliver the message
+- because delivering the message releases the
+- lock and something else can mess with the
+- state. */
++ smi_inc_stat(smi_info, incoming_messages);
++
++ /*
++ * Do this before we deliver the message
++ * because delivering the message releases the
++ * lock and something else can mess with the
++ * state.
++ */
+ handle_flags(smi_info);
+
+ deliver_recv_msg(smi_info, msg);
+@@ -674,69 +740,70 @@ static void handle_transaction_done(struct smi_info *smi_info)
+ }
+ }
+
+-/* Called on timeouts and events. Timeouts should pass the elapsed
+- time, interrupts should pass in zero. Must be called with
+- si_lock held and interrupts disabled. */
++/*
++ * Called on timeouts and events. Timeouts should pass the elapsed
++ * time, interrupts should pass in zero. Must be called with
++ * si_lock held and interrupts disabled.
++ */
+ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
+ int time)
+ {
+ enum si_sm_result si_sm_result;
+
+ restart:
+- /* There used to be a loop here that waited a little while
+- (around 25us) before giving up. That turned out to be
+- pointless, the minimum delays I was seeing were in the 300us
+- range, which is far too long to wait in an interrupt. So
+- we just run until the state machine tells us something
+- happened or it needs a delay. */
++ /*
++ * There used to be a loop here that waited a little while
++ * (around 25us) before giving up. That turned out to be
++ * pointless, the minimum delays I was seeing were in the 300us
++ * range, which is far too long to wait in an interrupt. So
++ * we just run until the state machine tells us something
++ * happened or it needs a delay.
++ */
+ si_sm_result = smi_info->handlers->event(smi_info->si_sm, time);
+ time = 0;
+ while (si_sm_result == SI_SM_CALL_WITHOUT_DELAY)
+- {
+ si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
+- }
+
+- if (si_sm_result == SI_SM_TRANSACTION_COMPLETE)
+- {
+- spin_lock(&smi_info->count_lock);
+- smi_info->complete_transactions++;
+- spin_unlock(&smi_info->count_lock);
++ if (si_sm_result == SI_SM_TRANSACTION_COMPLETE) {
++ smi_inc_stat(smi_info, complete_transactions);
+
+ handle_transaction_done(smi_info);
+ si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
+- }
+- else if (si_sm_result == SI_SM_HOSED)
+- {
+- spin_lock(&smi_info->count_lock);
+- smi_info->hosed_count++;
+- spin_unlock(&smi_info->count_lock);
++ } else if (si_sm_result == SI_SM_HOSED) {
++ smi_inc_stat(smi_info, hosed_count);
+
+- /* Do the before return_hosed_msg, because that
+- releases the lock. */
++ /*
++ * Do the before return_hosed_msg, because that
++ * releases the lock.
++ */
+ smi_info->si_state = SI_NORMAL;
+ if (smi_info->curr_msg != NULL) {
+- /* If we were handling a user message, format
+- a response to send to the upper layer to
+- tell it about the error. */
++ /*
++ * If we were handling a user message, format
++ * a response to send to the upper layer to
++ * tell it about the error.
++ */
+ return_hosed_msg(smi_info, IPMI_ERR_UNSPECIFIED);
+ }
+ si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
+ }
+
+- /* We prefer handling attn over new messages. */
+- if (si_sm_result == SI_SM_ATTN)
+- {
++ /*
++ * We prefer handling attn over new messages. But don't do
++ * this if there is not yet an upper layer to handle anything.
++ */
++ if (likely(smi_info->intf) && si_sm_result == SI_SM_ATTN) {
+ unsigned char msg[2];
+
+- spin_lock(&smi_info->count_lock);
+- smi_info->attentions++;
+- spin_unlock(&smi_info->count_lock);
++ smi_inc_stat(smi_info, attentions);
+
+- /* Got a attn, send down a get message flags to see
+- what's causing it. It would be better to handle
+- this in the upper layer, but due to the way
+- interrupts work with the SMI, that's not really
+- possible. */
++ /*
++ * Got a attn, send down a get message flags to see
++ * what's causing it. It would be better to handle
++ * this in the upper layer, but due to the way
++ * interrupts work with the SMI, that's not really
++ * possible.
++ */
+ msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
+ msg[1] = IPMI_GET_MSG_FLAGS_CMD;
+
+@@ -748,20 +815,19 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
+
+ /* If we are currently idle, try to start the next message. */
+ if (si_sm_result == SI_SM_IDLE) {
+- spin_lock(&smi_info->count_lock);
+- smi_info->idles++;
+- spin_unlock(&smi_info->count_lock);
++ smi_inc_stat(smi_info, idles);
+
+ si_sm_result = start_next_msg(smi_info);
+ if (si_sm_result != SI_SM_IDLE)
+ goto restart;
+- }
++ }
+
+ if ((si_sm_result == SI_SM_IDLE)
+- && (atomic_read(&smi_info->req_events)))
+- {
+- /* We are idle and the upper layer requested that I fetch
+- events, so do so. */
++ && (atomic_read(&smi_info->req_events))) {
++ /*
++ * We are idle and the upper layer requested that I fetch
++ * events, so do so.
++ */
+ atomic_set(&smi_info->req_events, 0);
+
+ smi_info->curr_msg = ipmi_alloc_smi_msg();
+@@ -803,56 +869,50 @@ static void sender(void *send_info,
+ return;
+ }
+
+- spin_lock_irqsave(&(smi_info->msg_lock), flags);
+ #ifdef DEBUG_TIMING
+ do_gettimeofday(&t);
+ printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec);
+ #endif
+
+ if (smi_info->run_to_completion) {
+- /* If we are running to completion, then throw it in
+- the list and run transactions until everything is
+- clear. Priority doesn't matter here. */
++ /*
++ * If we are running to completion, then throw it in
++ * the list and run transactions until everything is
++ * clear. Priority doesn't matter here.
++ */
++
++ /*
++ * Run to completion means we are single-threaded, no
++ * need for locks.
++ */
+ list_add_tail(&(msg->link), &(smi_info->xmit_msgs));
+
+- /* We have to release the msg lock and claim the smi
+- lock in this case, because of race conditions. */
+- spin_unlock_irqrestore(&(smi_info->msg_lock), flags);
+-
+- spin_lock_irqsave(&(smi_info->si_lock), flags);
+ result = smi_event_handler(smi_info, 0);
+ while (result != SI_SM_IDLE) {
+ udelay(SI_SHORT_TIMEOUT_USEC);
+ result = smi_event_handler(smi_info,
+ SI_SHORT_TIMEOUT_USEC);
+ }
+- spin_unlock_irqrestore(&(smi_info->si_lock), flags);
+ return;
+- } else {
+- if (priority > 0) {
+- list_add_tail(&(msg->link), &(smi_info->hp_xmit_msgs));
+- } else {
+- list_add_tail(&(msg->link), &(smi_info->xmit_msgs));
+- }
+ }
+- spin_unlock_irqrestore(&(smi_info->msg_lock), flags);
+
+- spin_lock_irqsave(&(smi_info->si_lock), flags);
+- if ((smi_info->si_state == SI_NORMAL)
+- && (smi_info->curr_msg == NULL))
+- {
++ spin_lock_irqsave(&smi_info->msg_lock, flags);
++ if (priority > 0)
++ list_add_tail(&msg->link, &smi_info->hp_xmit_msgs);
++ else
++ list_add_tail(&msg->link, &smi_info->xmit_msgs);
++ spin_unlock_irqrestore(&smi_info->msg_lock, flags);
++
++ spin_lock_irqsave(&smi_info->si_lock, flags);
++ if (smi_info->si_state == SI_NORMAL && smi_info->curr_msg == NULL)
+ start_next_msg(smi_info);
+- }
+- spin_unlock_irqrestore(&(smi_info->si_lock), flags);
++ spin_unlock_irqrestore(&smi_info->si_lock, flags);
+ }
+
+ static void set_run_to_completion(void *send_info, int i_run_to_completion)
+ {
+ struct smi_info *smi_info = send_info;
+ enum si_sm_result result;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&(smi_info->si_lock), flags);
+
+ smi_info->run_to_completion = i_run_to_completion;
+ if (i_run_to_completion) {
+@@ -863,8 +923,6 @@ static void set_run_to_completion(void *send_info, int i_run_to_completion)
+ SI_SHORT_TIMEOUT_USEC);
+ }
+ }
+-
+- spin_unlock_irqrestore(&(smi_info->si_lock), flags);
+ }
+
+ static int ipmi_thread(void *data)
+@@ -878,9 +936,8 @@ static int ipmi_thread(void *data)
+ spin_lock_irqsave(&(smi_info->si_lock), flags);
+ smi_result = smi_event_handler(smi_info, 0);
+ spin_unlock_irqrestore(&(smi_info->si_lock), flags);
+- if (smi_result == SI_SM_CALL_WITHOUT_DELAY) {
+- /* do nothing */
+- }
++ if (smi_result == SI_SM_CALL_WITHOUT_DELAY)
++ ; /* do nothing */
+ else if (smi_result == SI_SM_CALL_WITH_DELAY)
+ schedule();
+ else
+@@ -931,7 +988,7 @@ static void smi_timeout(unsigned long data)
+ spin_lock_irqsave(&(smi_info->si_lock), flags);
+ #ifdef DEBUG_TIMING
+ do_gettimeofday(&t);
+- printk("**Timer: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++ printk(KERN_DEBUG "**Timer: %d.%9.9d\n", t.tv_sec, t.tv_usec);
+ #endif
+ jiffies_now = jiffies;
+ time_diff = (((long)jiffies_now - (long)smi_info->last_timeout_jiffies)
+@@ -945,23 +1002,19 @@ static void smi_timeout(unsigned long data)
+ if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
+ /* Running with interrupts, only do long timeouts. */
+ smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
+- spin_lock_irqsave(&smi_info->count_lock, flags);
+- smi_info->long_timeouts++;
+- spin_unlock_irqrestore(&smi_info->count_lock, flags);
++ smi_inc_stat(smi_info, long_timeouts);
+ goto do_add_timer;
+ }
+
+- /* If the state machine asks for a short delay, then shorten
+- the timer timeout. */
++ /*
++ * If the state machine asks for a short delay, then shorten
++ * the timer timeout.
++ */
+ if (smi_result == SI_SM_CALL_WITH_DELAY) {
+- spin_lock_irqsave(&smi_info->count_lock, flags);
+- smi_info->short_timeouts++;
+- spin_unlock_irqrestore(&smi_info->count_lock, flags);
++ smi_inc_stat(smi_info, short_timeouts);
+ smi_info->si_timer.expires = jiffies + 1;
+ } else {
+- spin_lock_irqsave(&smi_info->count_lock, flags);
+- smi_info->long_timeouts++;
+- spin_unlock_irqrestore(&smi_info->count_lock, flags);
++ smi_inc_stat(smi_info, long_timeouts);
+ smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
+ }
+
+@@ -979,13 +1032,11 @@ static irqreturn_t si_irq_handler(int irq, void *data)
+
+ spin_lock_irqsave(&(smi_info->si_lock), flags);
+
+- spin_lock(&smi_info->count_lock);
+- smi_info->interrupts++;
+- spin_unlock(&smi_info->count_lock);
++ smi_inc_stat(smi_info, interrupts);
+
+ #ifdef DEBUG_TIMING
+ do_gettimeofday(&t);
+- printk("**Interrupt: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++ printk(KERN_DEBUG "**Interrupt: %d.%9.9d\n", t.tv_sec, t.tv_usec);
+ #endif
+ smi_event_handler(smi_info, 0);
+ spin_unlock_irqrestore(&(smi_info->si_lock), flags);
+@@ -1028,7 +1079,7 @@ static int smi_start_processing(void *send_info,
+ * The BT interface is efficient enough to not need a thread,
+ * and there is no need for a thread if we have interrupts.
+ */
+- else if ((new_smi->si_type != SI_BT) && (!new_smi->irq))
++ else if ((new_smi->si_type != SI_BT) && (!new_smi->irq))
+ enable = 1;
+
+ if (enable) {
+@@ -1054,8 +1105,7 @@ static void set_maintenance_mode(void *send_info, int enable)
+ atomic_set(&smi_info->req_events, 0);
+ }
+
+-static struct ipmi_smi_handlers handlers =
+-{
++static struct ipmi_smi_handlers handlers = {
+ .owner = THIS_MODULE,
+ .start_processing = smi_start_processing,
+ .sender = sender,
+@@ -1065,8 +1115,10 @@ static struct ipmi_smi_handlers handlers =
+ .poll = poll,
+ };
+
+-/* There can be 4 IO ports passed in (with or without IRQs), 4 addresses,
+- a default IO port, and 1 ACPI/SPMI address. That sets SI_MAX_DRIVERS */
++/*
++ * There can be 4 IO ports passed in (with or without IRQs), 4 addresses,
++ * a default IO port, and 1 ACPI/SPMI address. That sets SI_MAX_DRIVERS.
++ */
+
+ static LIST_HEAD(smi_infos);
+ static DEFINE_MUTEX(smi_infos_lock);
+@@ -1257,10 +1309,9 @@ static void port_cleanup(struct smi_info *info)
+ int idx;
+
+ if (addr) {
+- for (idx = 0; idx < info->io_size; idx++) {
++ for (idx = 0; idx < info->io_size; idx++)
+ release_region(addr + idx * info->io.regspacing,
+ info->io.regsize);
+- }
+ }
+ }
+
+@@ -1274,8 +1325,10 @@ static int port_setup(struct smi_info *info)
+
+ info->io_cleanup = port_cleanup;
+
+- /* Figure out the actual inb/inw/inl/etc routine to use based
+- upon the register size. */
++ /*
++ * Figure out the actual inb/inw/inl/etc routine to use based
++ * upon the register size.
++ */
+ switch (info->io.regsize) {
+ case 1:
+ info->io.inputb = port_inb;
+@@ -1290,17 +1343,18 @@ static int port_setup(struct smi_info *info)
+ info->io.outputb = port_outl;
+ break;
+ default:
+- printk("ipmi_si: Invalid register size: %d\n",
++ printk(KERN_WARNING "ipmi_si: Invalid register size: %d\n",
+ info->io.regsize);
+ return -EINVAL;
+ }
+
+- /* Some BIOSes reserve disjoint I/O regions in their ACPI
++ /*
++ * Some BIOSes reserve disjoint I/O regions in their ACPI
+ * tables. This causes problems when trying to register the
+ * entire I/O region. Therefore we must register each I/O
+ * port separately.
+ */
+- for (idx = 0; idx < info->io_size; idx++) {
++ for (idx = 0; idx < info->io_size; idx++) {
+ if (request_region(addr + idx * info->io.regspacing,
+ info->io.regsize, DEVICE_NAME) == NULL) {
+ /* Undo allocations */
+@@ -1388,8 +1442,10 @@ static int mem_setup(struct smi_info *info)
+
+ info->io_cleanup = mem_cleanup;
+
+- /* Figure out the actual readb/readw/readl/etc routine to use based
+- upon the register size. */
++ /*
++ * Figure out the actual readb/readw/readl/etc routine to use based
++ * upon the register size.
++ */
+ switch (info->io.regsize) {
+ case 1:
+ info->io.inputb = intf_mem_inb;
+@@ -1410,16 +1466,18 @@ static int mem_setup(struct smi_info *info)
+ break;
+ #endif
+ default:
+- printk("ipmi_si: Invalid register size: %d\n",
++ printk(KERN_WARNING "ipmi_si: Invalid register size: %d\n",
+ info->io.regsize);
+ return -EINVAL;
+ }
+
+- /* Calculate the total amount of memory to claim. This is an
++ /*
++ * Calculate the total amount of memory to claim. This is an
+ * unusual looking calculation, but it avoids claiming any
+ * more memory than it has to. It will claim everything
+ * between the first address to the end of the last full
+- * register. */
++ * register.
++ */
+ mapsize = ((info->io_size * info->io.regspacing)
+ - (info->io.regspacing - info->io.regsize));
+
+@@ -1749,9 +1807,11 @@ static __devinit void hardcode_find_bmc(void)
+
+ #include <linux/acpi.h>
+
+-/* Once we get an ACPI failure, we don't try any more, because we go
+- through the tables sequentially. Once we don't find a table, there
+- are no more. */
++/*
++ * Once we get an ACPI failure, we don't try any more, because we go
++ * through the tables sequentially. Once we don't find a table, there
++ * are no more.
++ */
+ static int acpi_failure;
+
+ /* For GPE-type interrupts. */
+@@ -1765,9 +1825,7 @@ static u32 ipmi_acpi_gpe(void *context)
+
+ spin_lock_irqsave(&(smi_info->si_lock), flags);
+
+- spin_lock(&smi_info->count_lock);
+- smi_info->interrupts++;
+- spin_unlock(&smi_info->count_lock);
++ smi_inc_stat(smi_info, interrupts);
+
+ #ifdef DEBUG_TIMING
+ do_gettimeofday(&t);
+@@ -1816,7 +1874,8 @@ static int acpi_gpe_irq_setup(struct smi_info *info)
+
+ /*
+ * Defined at
+- * http://h21007.www2.hp.com/dspp/files/unprotected/devresource/Docs/TechPapers/IA64/hpspmi.pdf
++ * http://h21007.www2.hp.com/dspp/files/unprotected/devresource/
++ * Docs/TechPapers/IA64/hpspmi.pdf
+ */
+ struct SPMITable {
+ s8 Signature[4];
+@@ -1838,14 +1897,18 @@ struct SPMITable {
+ */
+ u8 InterruptType;
+
+- /* If bit 0 of InterruptType is set, then this is the SCI
+- interrupt in the GPEx_STS register. */
++ /*
++ * If bit 0 of InterruptType is set, then this is the SCI
++ * interrupt in the GPEx_STS register.
++ */
+ u8 GPE;
+
+ s16 Reserved;
+
+- /* If bit 1 of InterruptType is set, then this is the I/O
+- APIC/SAPIC interrupt. */
++ /*
++ * If bit 1 of InterruptType is set, then this is the I/O
++ * APIC/SAPIC interrupt.
++ */
+ u32 GlobalSystemInterrupt;
+
+ /* The actual register address. */
+@@ -1863,7 +1926,7 @@ static __devinit int try_init_acpi(struct SPMITable *spmi)
+
+ if (spmi->IPMIlegacy != 1) {
+ printk(KERN_INFO "IPMI: Bad SPMI legacy %d\n", spmi->IPMIlegacy);
+- return -ENODEV;
++ return -ENODEV;
+ }
+
+ if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
+@@ -1880,8 +1943,7 @@ static __devinit int try_init_acpi(struct SPMITable *spmi)
+ info->addr_source = "ACPI";
+
+ /* Figure out the interface type. */
+- switch (spmi->InterfaceType)
+- {
++ switch (spmi->InterfaceType) {
+ case 1: /* KCS */
+ info->si_type = SI_KCS;
+ break;
+@@ -1929,7 +1991,8 @@ static __devinit int try_init_acpi(struct SPMITable *spmi)
+ info->io.addr_type = IPMI_IO_ADDR_SPACE;
+ } else {
+ kfree(info);
+- printk("ipmi_si: Unknown ACPI I/O Address type\n");
++ printk(KERN_WARNING
++ "ipmi_si: Unknown ACPI I/O Address type\n");
+ return -EIO;
+ }
+ info->io.addr_data = spmi->addr.address;
+@@ -1963,8 +2026,7 @@ static __devinit void acpi_find_bmc(void)
+ #endif
+
+ #ifdef CONFIG_DMI
+-struct dmi_ipmi_data
+-{
++struct dmi_ipmi_data {
+ u8 type;
+ u8 addr_space;
+ unsigned long base_addr;
+@@ -1989,11 +2051,10 @@ static int __devinit decode_dmi(const struct dmi_header *dm,
+ /* I/O */
+ base_addr &= 0xFFFE;
+ dmi->addr_space = IPMI_IO_ADDR_SPACE;
+- }
+- else {
++ } else
+ /* Memory */
+ dmi->addr_space = IPMI_MEM_ADDR_SPACE;
+- }
++
+ /* If bit 4 of byte 0x10 is set, then the lsb for the address
+ is odd. */
+ dmi->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
+@@ -2002,7 +2063,7 @@ static int __devinit decode_dmi(const struct dmi_header *dm,
+
+ /* The top two bits of byte 0x10 hold the register spacing. */
+ reg_spacing = (data[0x10] & 0xC0) >> 6;
+- switch(reg_spacing){
++ switch (reg_spacing) {
+ case 0x00: /* Byte boundaries */
+ dmi->offset = 1;
+ break;
+@@ -2018,12 +2079,14 @@ static int __devinit decode_dmi(const struct dmi_header *dm,
+ }
+ } else {
+ /* Old DMI spec. */
+- /* Note that technically, the lower bit of the base
++ /*
++ * Note that technically, the lower bit of the base
+ * address should be 1 if the address is I/O and 0 if
+ * the address is in memory. So many systems get that
+ * wrong (and all that I have seen are I/O) so we just
+ * ignore that bit and assume I/O. Systems that use
+- * memory should use the newer spec, anyway. */
++ * memory should use the newer spec, anyway.
++ */
+ dmi->base_addr = base_addr & 0xfffe;
+ dmi->addr_space = IPMI_IO_ADDR_SPACE;
+ dmi->offset = 1;
+@@ -2230,13 +2293,13 @@ static struct pci_device_id ipmi_pci_devices[] = {
+ MODULE_DEVICE_TABLE(pci, ipmi_pci_devices);
+
+ static struct pci_driver ipmi_pci_driver = {
+- .name = DEVICE_NAME,
+- .id_table = ipmi_pci_devices,
+- .probe = ipmi_pci_probe,
+- .remove = __devexit_p(ipmi_pci_remove),
++ .name = DEVICE_NAME,
++ .id_table = ipmi_pci_devices,
++ .probe = ipmi_pci_probe,
++ .remove = __devexit_p(ipmi_pci_remove),
+ #ifdef CONFIG_PM
+- .suspend = ipmi_pci_suspend,
+- .resume = ipmi_pci_resume,
++ .suspend = ipmi_pci_suspend,
++ .resume = ipmi_pci_resume,
+ #endif
+ };
+ #endif /* CONFIG_PCI */
+@@ -2306,7 +2369,7 @@ static int __devinit ipmi_of_probe(struct of_device *dev,
+ info->io.addr_data, info->io.regsize, info->io.regspacing,
+ info->irq);
+
+- dev->dev.driver_data = (void*) info;
++ dev->dev.driver_data = (void *) info;
+
+ return try_smi_init(info);
+ }
+@@ -2319,14 +2382,16 @@ static int __devexit ipmi_of_remove(struct of_device *dev)
+
+ static struct of_device_id ipmi_match[] =
+ {
+- { .type = "ipmi", .compatible = "ipmi-kcs", .data = (void *)(unsigned long) SI_KCS },
+- { .type = "ipmi", .compatible = "ipmi-smic", .data = (void *)(unsigned long) SI_SMIC },
+- { .type = "ipmi", .compatible = "ipmi-bt", .data = (void *)(unsigned long) SI_BT },
++ { .type = "ipmi", .compatible = "ipmi-kcs",
++ .data = (void *)(unsigned long) SI_KCS },
++ { .type = "ipmi", .compatible = "ipmi-smic",
++ .data = (void *)(unsigned long) SI_SMIC },
++ { .type = "ipmi", .compatible = "ipmi-bt",
++ .data = (void *)(unsigned long) SI_BT },
+ {},
+ };
+
+-static struct of_platform_driver ipmi_of_platform_driver =
+-{
++static struct of_platform_driver ipmi_of_platform_driver = {
+ .name = "ipmi",
+ .match_table = ipmi_match,
+ .probe = ipmi_of_probe,
+@@ -2347,32 +2412,32 @@ static int try_get_dev_id(struct smi_info *smi_info)
+ if (!resp)
+ return -ENOMEM;
+
+- /* Do a Get Device ID command, since it comes back with some
+- useful info. */
++ /*
++ * Do a Get Device ID command, since it comes back with some
++ * useful info.
++ */
+ msg[0] = IPMI_NETFN_APP_REQUEST << 2;
+ msg[1] = IPMI_GET_DEVICE_ID_CMD;
+ smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
+
+ smi_result = smi_info->handlers->event(smi_info->si_sm, 0);
+- for (;;)
+- {
++ for (;;) {
+ if (smi_result == SI_SM_CALL_WITH_DELAY ||
+ smi_result == SI_SM_CALL_WITH_TICK_DELAY) {
+ schedule_timeout_uninterruptible(1);
+ smi_result = smi_info->handlers->event(
+ smi_info->si_sm, 100);
+- }
+- else if (smi_result == SI_SM_CALL_WITHOUT_DELAY)
+- {
++ } else if (smi_result == SI_SM_CALL_WITHOUT_DELAY) {
+ smi_result = smi_info->handlers->event(
+ smi_info->si_sm, 0);
+- }
+- else
++ } else
+ break;
+ }
+ if (smi_result == SI_SM_HOSED) {
+- /* We couldn't get the state machine to run, so whatever's at
+- the port is probably not an IPMI SMI interface. */
++ /*
++ * We couldn't get the state machine to run, so whatever's at
++ * the port is probably not an IPMI SMI interface.
++ */
+ rv = -ENODEV;
+ goto out;
+ }
+@@ -2405,30 +2470,28 @@ static int stat_file_read_proc(char *page, char **start, off_t off,
+
+ out += sprintf(out, "interrupts_enabled: %d\n",
+ smi->irq && !smi->interrupt_disabled);
+- out += sprintf(out, "short_timeouts: %ld\n",
+- smi->short_timeouts);
+- out += sprintf(out, "long_timeouts: %ld\n",
+- smi->long_timeouts);
+- out += sprintf(out, "timeout_restarts: %ld\n",
+- smi->timeout_restarts);
+- out += sprintf(out, "idles: %ld\n",
+- smi->idles);
+- out += sprintf(out, "interrupts: %ld\n",
+- smi->interrupts);
+- out += sprintf(out, "attentions: %ld\n",
+- smi->attentions);
+- out += sprintf(out, "flag_fetches: %ld\n",
+- smi->flag_fetches);
+- out += sprintf(out, "hosed_count: %ld\n",
+- smi->hosed_count);
+- out += sprintf(out, "complete_transactions: %ld\n",
+- smi->complete_transactions);
+- out += sprintf(out, "events: %ld\n",
+- smi->events);
+- out += sprintf(out, "watchdog_pretimeouts: %ld\n",
+- smi->watchdog_pretimeouts);
+- out += sprintf(out, "incoming_messages: %ld\n",
+- smi->incoming_messages);
++ out += sprintf(out, "short_timeouts: %u\n",
++ smi_get_stat(smi, short_timeouts));
++ out += sprintf(out, "long_timeouts: %u\n",
++ smi_get_stat(smi, long_timeouts));
++ out += sprintf(out, "idles: %u\n",
++ smi_get_stat(smi, idles));
++ out += sprintf(out, "interrupts: %u\n",
++ smi_get_stat(smi, interrupts));
++ out += sprintf(out, "attentions: %u\n",
++ smi_get_stat(smi, attentions));
++ out += sprintf(out, "flag_fetches: %u\n",
++ smi_get_stat(smi, flag_fetches));
++ out += sprintf(out, "hosed_count: %u\n",
++ smi_get_stat(smi, hosed_count));
++ out += sprintf(out, "complete_transactions: %u\n",
++ smi_get_stat(smi, complete_transactions));
++ out += sprintf(out, "events: %u\n",
++ smi_get_stat(smi, events));
++ out += sprintf(out, "watchdog_pretimeouts: %u\n",
++ smi_get_stat(smi, watchdog_pretimeouts));
++ out += sprintf(out, "incoming_messages: %u\n",
++ smi_get_stat(smi, incoming_messages));
+
+ return out - page;
+ }
+@@ -2460,7 +2523,7 @@ static int param_read_proc(char *page, char **start, off_t off,
+ static int oem_data_avail_to_receive_msg_avail(struct smi_info *smi_info)
+ {
+ smi_info->msg_flags = ((smi_info->msg_flags & ~OEM_DATA_AVAIL) |
+- RECEIVE_MSG_AVAIL);
++ RECEIVE_MSG_AVAIL);
+ return 1;
+ }
+
+@@ -2502,10 +2565,9 @@ static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info)
+ id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION) {
+ smi_info->oem_data_avail_handler =
+ oem_data_avail_to_receive_msg_avail;
+- }
+- else if (ipmi_version_major(id) < 1 ||
+- (ipmi_version_major(id) == 1 &&
+- ipmi_version_minor(id) < 5)) {
++ } else if (ipmi_version_major(id) < 1 ||
++ (ipmi_version_major(id) == 1 &&
++ ipmi_version_minor(id) < 5)) {
+ smi_info->oem_data_avail_handler =
+ oem_data_avail_to_receive_msg_avail;
+ }
+@@ -2597,8 +2659,10 @@ static void setup_xaction_handlers(struct smi_info *smi_info)
+ static inline void wait_for_timer_and_thread(struct smi_info *smi_info)
+ {
+ if (smi_info->intf) {
+- /* The timer and thread are only running if the
+- interface has been started up and registered. */
++ /*
++ * The timer and thread are only running if the
++ * interface has been started up and registered.
++ */
+ if (smi_info->thread != NULL)
+ kthread_stop(smi_info->thread);
+ del_timer_sync(&smi_info->si_timer);
+@@ -2676,6 +2740,7 @@ static int is_new_interface(struct smi_info *info)
+ static int try_smi_init(struct smi_info *new_smi)
+ {
+ int rv;
++ int i;
+
+ if (new_smi->addr_source) {
+ printk(KERN_INFO "ipmi_si: Trying %s-specified %s state"
+@@ -2722,7 +2787,7 @@ static int try_smi_init(struct smi_info *new_smi)
+ /* Allocate the state machine's data and initialize it. */
+ new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL);
+ if (!new_smi->si_sm) {
+- printk(" Could not allocate state machine memory\n");
++ printk(KERN_ERR "Could not allocate state machine memory\n");
+ rv = -ENOMEM;
+ goto out_err;
+ }
+@@ -2732,13 +2797,12 @@ static int try_smi_init(struct smi_info *new_smi)
+ /* Now that we know the I/O size, we can set up the I/O. */
+ rv = new_smi->io_setup(new_smi);
+ if (rv) {
+- printk(" Could not set up I/O space\n");
++ printk(KERN_ERR "Could not set up I/O space\n");
+ goto out_err;
+ }
+
+ spin_lock_init(&(new_smi->si_lock));
+ spin_lock_init(&(new_smi->msg_lock));
+- spin_lock_init(&(new_smi->count_lock));
+
+ /* Do low-level detection first. */
+ if (new_smi->handlers->detect(new_smi->si_sm)) {
+@@ -2749,8 +2813,10 @@ static int try_smi_init(struct smi_info *new_smi)
+ goto out_err;
+ }
+
+- /* Attempt a get device id command. If it fails, we probably
+- don't have a BMC here. */
++ /*
++ * Attempt a get device id command. If it fails, we probably
++ * don't have a BMC here.
++ */
+ rv = try_get_dev_id(new_smi);
+ if (rv) {
+ if (new_smi->addr_source)
+@@ -2767,22 +2833,28 @@ static int try_smi_init(struct smi_info *new_smi)
+ new_smi->curr_msg = NULL;
+ atomic_set(&new_smi->req_events, 0);
+ new_smi->run_to_completion = 0;
++ for (i = 0; i < SI_NUM_STATS; i++)
++ atomic_set(&new_smi->stats[i], 0);
+
+ new_smi->interrupt_disabled = 0;
+ atomic_set(&new_smi->stop_operation, 0);
+ new_smi->intf_num = smi_num;
+ smi_num++;
+
+- /* Start clearing the flags before we enable interrupts or the
+- timer to avoid racing with the timer. */
++ /*
++ * Start clearing the flags before we enable interrupts or the
++ * timer to avoid racing with the timer.
++ */
+ start_clear_flags(new_smi);
+ /* IRQ is defined to be set when non-zero. */
+ if (new_smi->irq)
+ new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ;
+
+ if (!new_smi->dev) {
+- /* If we don't already have a device from something
+- * else (like PCI), then register a new one. */
++ /*
++ * If we don't already have a device from something
++ * else (like PCI), then register a new one.
++ */
+ new_smi->pdev = platform_device_alloc("ipmi_si",
+ new_smi->intf_num);
+ if (rv) {
+@@ -2820,7 +2892,7 @@ static int try_smi_init(struct smi_info *new_smi)
+ }
+
+ rv = ipmi_smi_add_proc_entry(new_smi->intf, "type",
+- type_file_read_proc, NULL,
++ type_file_read_proc,
+ new_smi, THIS_MODULE);
+ if (rv) {
+ printk(KERN_ERR
+@@ -2830,7 +2902,7 @@ static int try_smi_init(struct smi_info *new_smi)
+ }
+
+ rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats",
+- stat_file_read_proc, NULL,
++ stat_file_read_proc,
+ new_smi, THIS_MODULE);
+ if (rv) {
+ printk(KERN_ERR
+@@ -2840,7 +2912,7 @@ static int try_smi_init(struct smi_info *new_smi)
+ }
+
+ rv = ipmi_smi_add_proc_entry(new_smi->intf, "params",
+- param_read_proc, NULL,
++ param_read_proc,
+ new_smi, THIS_MODULE);
+ if (rv) {
+ printk(KERN_ERR
+@@ -2853,7 +2925,8 @@ static int try_smi_init(struct smi_info *new_smi)
+
+ mutex_unlock(&smi_infos_lock);
+
+- printk(KERN_INFO "IPMI %s interface initialized\n",si_to_str[new_smi->si_type]);
++ printk(KERN_INFO "IPMI %s interface initialized\n",
++ si_to_str[new_smi->si_type]);
+
+ return 0;
+
+@@ -2868,9 +2941,11 @@ static int try_smi_init(struct smi_info *new_smi)
+ if (new_smi->irq_cleanup)
+ new_smi->irq_cleanup(new_smi);
+
+- /* Wait until we know that we are out of any interrupt
+- handlers might have been running before we freed the
+- interrupt. */
++ /*
++ * Wait until we know that we are out of any interrupt
++ * handlers might have been running before we freed the
++ * interrupt.
++ */
+ synchronize_sched();
+
+ if (new_smi->si_sm) {
+@@ -2942,11 +3017,10 @@ static __devinit int init_ipmi_si(void)
+
+ #ifdef CONFIG_PCI
+ rv = pci_register_driver(&ipmi_pci_driver);
+- if (rv){
++ if (rv)
+ printk(KERN_ERR
+ "init_ipmi_si: Unable to register PCI driver: %d\n",
+ rv);
+- }
+ #endif
+
+ #ifdef CONFIG_PPC_OF
+@@ -2975,7 +3049,8 @@ static __devinit int init_ipmi_si(void)
+ of_unregister_platform_driver(&ipmi_of_platform_driver);
+ #endif
+ driver_unregister(&ipmi_driver);
+- printk("ipmi_si: Unable to find any System Interface(s)\n");
++ printk(KERN_WARNING
++ "ipmi_si: Unable to find any System Interface(s)\n");
+ return -ENODEV;
+ } else {
+ mutex_unlock(&smi_infos_lock);
+@@ -2997,13 +3072,17 @@ static void cleanup_one_si(struct smi_info *to_clean)
+ /* Tell the driver that we are shutting down. */
+ atomic_inc(&to_clean->stop_operation);
+
+- /* Make sure the timer and thread are stopped and will not run
+- again. */
++ /*
++ * Make sure the timer and thread are stopped and will not run
++ * again.
++ */
+ wait_for_timer_and_thread(to_clean);
+
+- /* Timeouts are stopped, now make sure the interrupts are off
+- for the device. A little tricky with locks to make sure
+- there are no races. */
++ /*
++ * Timeouts are stopped, now make sure the interrupts are off
++ * for the device. A little tricky with locks to make sure
++ * there are no races.
++ */
+ spin_lock_irqsave(&to_clean->si_lock, flags);
+ while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
+ spin_unlock_irqrestore(&to_clean->si_lock, flags);
+@@ -3074,4 +3153,5 @@ module_exit(cleanup_ipmi_si);
+
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Corey Minyard <minyard at mvista.com>");
+-MODULE_DESCRIPTION("Interface to the IPMI driver for the KCS, SMIC, and BT system interfaces.");
++MODULE_DESCRIPTION("Interface to the IPMI driver for the KCS, SMIC, and BT"
++ " system interfaces.");
+diff --git a/drivers/char/ipmi/ipmi_si_sm.h b/drivers/char/ipmi/ipmi_si_sm.h
+index 4b731b2..df89f73 100644
+--- a/drivers/char/ipmi/ipmi_si_sm.h
++++ b/drivers/char/ipmi/ipmi_si_sm.h
+@@ -34,22 +34,27 @@
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+-/* This is defined by the state machines themselves, it is an opaque
+- data type for them to use. */
++/*
++ * This is defined by the state machines themselves, it is an opaque
++ * data type for them to use.
++ */
+ struct si_sm_data;
+
+-/* The structure for doing I/O in the state machine. The state
+- machine doesn't have the actual I/O routines, they are done through
+- this interface. */
+-struct si_sm_io
+-{
++/*
++ * The structure for doing I/O in the state machine. The state
++ * machine doesn't have the actual I/O routines, they are done through
++ * this interface.
++ */
++struct si_sm_io {
+ unsigned char (*inputb)(struct si_sm_io *io, unsigned int offset);
+ void (*outputb)(struct si_sm_io *io,
+ unsigned int offset,
+ unsigned char b);
+
+- /* Generic info used by the actual handling routines, the
+- state machine shouldn't touch these. */
++ /*
++ * Generic info used by the actual handling routines, the
++ * state machine shouldn't touch these.
++ */
+ void __iomem *addr;
+ int regspacing;
+ int regsize;
+@@ -59,53 +64,67 @@ struct si_sm_io
+ };
+
+ /* Results of SMI events. */
+-enum si_sm_result
+-{
++enum si_sm_result {
+ SI_SM_CALL_WITHOUT_DELAY, /* Call the driver again immediately */
+ SI_SM_CALL_WITH_DELAY, /* Delay some before calling again. */
+- SI_SM_CALL_WITH_TICK_DELAY, /* Delay at least 1 tick before calling again. */
++ SI_SM_CALL_WITH_TICK_DELAY,/* Delay >=1 tick before calling again. */
+ SI_SM_TRANSACTION_COMPLETE, /* A transaction is finished. */
+ SI_SM_IDLE, /* The SM is in idle state. */
+ SI_SM_HOSED, /* The hardware violated the state machine. */
+- SI_SM_ATTN /* The hardware is asserting attn and the
+- state machine is idle. */
++
++ /*
++ * The hardware is asserting attn and the state machine is
++ * idle.
++ */
++ SI_SM_ATTN
+ };
+
+ /* Handlers for the SMI state machine. */
+-struct si_sm_handlers
+-{
+- /* Put the version number of the state machine here so the
+- upper layer can print it. */
++struct si_sm_handlers {
++ /*
++ * Put the version number of the state machine here so the
++ * upper layer can print it.
++ */
+ char *version;
+
+- /* Initialize the data and return the amount of I/O space to
+- reserve for the space. */
++ /*
++ * Initialize the data and return the amount of I/O space to
++ * reserve for the space.
++ */
+ unsigned int (*init_data)(struct si_sm_data *smi,
+ struct si_sm_io *io);
+
+- /* Start a new transaction in the state machine. This will
+- return -2 if the state machine is not idle, -1 if the size
+- is invalid (to large or too small), or 0 if the transaction
+- is successfully completed. */
++ /*
++ * Start a new transaction in the state machine. This will
++ * return -2 if the state machine is not idle, -1 if the size
++ * is invalid (to large or too small), or 0 if the transaction
++ * is successfully completed.
++ */
+ int (*start_transaction)(struct si_sm_data *smi,
+ unsigned char *data, unsigned int size);
+
+- /* Return the results after the transaction. This will return
+- -1 if the buffer is too small, zero if no transaction is
+- present, or the actual length of the result data. */
++ /*
++ * Return the results after the transaction. This will return
++ * -1 if the buffer is too small, zero if no transaction is
++ * present, or the actual length of the result data.
++ */
+ int (*get_result)(struct si_sm_data *smi,
+ unsigned char *data, unsigned int length);
+
+- /* Call this periodically (for a polled interface) or upon
+- receiving an interrupt (for a interrupt-driven interface).
+- If interrupt driven, you should probably poll this
+- periodically when not in idle state. This should be called
+- with the time that passed since the last call, if it is
+- significant. Time is in microseconds. */
++ /*
++ * Call this periodically (for a polled interface) or upon
++ * receiving an interrupt (for a interrupt-driven interface).
++ * If interrupt driven, you should probably poll this
++ * periodically when not in idle state. This should be called
++ * with the time that passed since the last call, if it is
++ * significant. Time is in microseconds.
++ */
+ enum si_sm_result (*event)(struct si_sm_data *smi, long time);
+
+- /* Attempt to detect an SMI. Returns 0 on success or nonzero
+- on failure. */
++ /*
++ * Attempt to detect an SMI. Returns 0 on success or nonzero
++ * on failure.
++ */
+ int (*detect)(struct si_sm_data *smi);
+
+ /* The interface is shutting down, so clean it up. */
+diff --git a/drivers/char/ipmi/ipmi_smic_sm.c b/drivers/char/ipmi/ipmi_smic_sm.c
+index e64ea7d..faed929 100644
+--- a/drivers/char/ipmi/ipmi_smic_sm.c
++++ b/drivers/char/ipmi/ipmi_smic_sm.c
+@@ -85,6 +85,7 @@ enum smic_states {
+ /* SMIC Flags Register Bits */
+ #define SMIC_RX_DATA_READY 0x80
+ #define SMIC_TX_DATA_READY 0x40
++
+ /*
+ * SMIC_SMI and SMIC_EVM_DATA_AVAIL are only used by
+ * a few systems, and then only by Systems Management
+@@ -104,23 +105,22 @@ enum smic_states {
+ #define EC_ILLEGAL_COMMAND 0x04
+ #define EC_BUFFER_FULL 0x05
+
+-struct si_sm_data
+-{
++struct si_sm_data {
+ enum smic_states state;
+ struct si_sm_io *io;
+- unsigned char write_data[MAX_SMIC_WRITE_SIZE];
+- int write_pos;
+- int write_count;
+- int orig_write_count;
+- unsigned char read_data[MAX_SMIC_READ_SIZE];
+- int read_pos;
+- int truncated;
+- unsigned int error_retries;
+- long smic_timeout;
++ unsigned char write_data[MAX_SMIC_WRITE_SIZE];
++ int write_pos;
++ int write_count;
++ int orig_write_count;
++ unsigned char read_data[MAX_SMIC_READ_SIZE];
++ int read_pos;
++ int truncated;
++ unsigned int error_retries;
++ long smic_timeout;
+ };
+
+-static unsigned int init_smic_data (struct si_sm_data *smic,
+- struct si_sm_io *io)
++static unsigned int init_smic_data(struct si_sm_data *smic,
++ struct si_sm_io *io)
+ {
+ smic->state = SMIC_IDLE;
+ smic->io = io;
+@@ -150,11 +150,10 @@ static int start_smic_transaction(struct si_sm_data *smic,
+ return IPMI_NOT_IN_MY_STATE_ERR;
+
+ if (smic_debug & SMIC_DEBUG_MSG) {
+- printk(KERN_INFO "start_smic_transaction -");
+- for (i = 0; i < size; i ++) {
+- printk (" %02x", (unsigned char) (data [i]));
+- }
+- printk ("\n");
++ printk(KERN_DEBUG "start_smic_transaction -");
++ for (i = 0; i < size; i++)
++ printk(" %02x", (unsigned char) data[i]);
++ printk("\n");
+ }
+ smic->error_retries = 0;
+ memcpy(smic->write_data, data, size);
+@@ -173,11 +172,10 @@ static int smic_get_result(struct si_sm_data *smic,
+ int i;
+
+ if (smic_debug & SMIC_DEBUG_MSG) {
+- printk (KERN_INFO "smic_get result -");
+- for (i = 0; i < smic->read_pos; i ++) {
+- printk (" %02x", (smic->read_data [i]));
+- }
+- printk ("\n");
++ printk(KERN_DEBUG "smic_get result -");
++ for (i = 0; i < smic->read_pos; i++)
++ printk(" %02x", smic->read_data[i]);
++ printk("\n");
+ }
+ if (length < smic->read_pos) {
+ smic->read_pos = length;
+@@ -223,8 +221,8 @@ static inline void write_smic_control(struct si_sm_data *smic,
+ smic->io->outputb(smic->io, 1, control);
+ }
+
+-static inline void write_si_sm_data (struct si_sm_data *smic,
+- unsigned char data)
++static inline void write_si_sm_data(struct si_sm_data *smic,
++ unsigned char data)
+ {
+ smic->io->outputb(smic->io, 0, data);
+ }
+@@ -233,10 +231,9 @@ static inline void start_error_recovery(struct si_sm_data *smic, char *reason)
+ {
+ (smic->error_retries)++;
+ if (smic->error_retries > SMIC_MAX_ERROR_RETRIES) {
+- if (smic_debug & SMIC_DEBUG_ENABLE) {
++ if (smic_debug & SMIC_DEBUG_ENABLE)
+ printk(KERN_WARNING
+ "ipmi_smic_drv: smic hosed: %s\n", reason);
+- }
+ smic->state = SMIC_HOSED;
+ } else {
+ smic->write_count = smic->orig_write_count;
+@@ -254,14 +251,14 @@ static inline void write_next_byte(struct si_sm_data *smic)
+ (smic->write_count)--;
+ }
+
+-static inline void read_next_byte (struct si_sm_data *smic)
++static inline void read_next_byte(struct si_sm_data *smic)
+ {
+ if (smic->read_pos >= MAX_SMIC_READ_SIZE) {
+- read_smic_data (smic);
++ read_smic_data(smic);
+ smic->truncated = 1;
+ } else {
+ smic->read_data[smic->read_pos] = read_smic_data(smic);
+- (smic->read_pos)++;
++ smic->read_pos++;
+ }
+ }
+
+@@ -336,7 +333,7 @@ static inline void read_next_byte (struct si_sm_data *smic)
+ SMIC_SC_SMS_RD_END 0xC6
+ */
+
+-static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
++static enum si_sm_result smic_event(struct si_sm_data *smic, long time)
+ {
+ unsigned char status;
+ unsigned char flags;
+@@ -347,13 +344,15 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
+ return SI_SM_HOSED;
+ }
+ if (smic->state != SMIC_IDLE) {
+- if (smic_debug & SMIC_DEBUG_STATES) {
+- printk(KERN_INFO
++ if (smic_debug & SMIC_DEBUG_STATES)
++ printk(KERN_DEBUG
+ "smic_event - smic->smic_timeout = %ld,"
+ " time = %ld\n",
+ smic->smic_timeout, time);
+- }
+-/* FIXME: smic_event is sometimes called with time > SMIC_RETRY_TIMEOUT */
++ /*
++ * FIXME: smic_event is sometimes called with time >
++ * SMIC_RETRY_TIMEOUT
++ */
+ if (time < SMIC_RETRY_TIMEOUT) {
+ smic->smic_timeout -= time;
+ if (smic->smic_timeout < 0) {
+@@ -366,9 +365,9 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
+ if (flags & SMIC_FLAG_BSY)
+ return SI_SM_CALL_WITH_DELAY;
+
+- status = read_smic_status (smic);
++ status = read_smic_status(smic);
+ if (smic_debug & SMIC_DEBUG_STATES)
+- printk(KERN_INFO
++ printk(KERN_DEBUG
+ "smic_event - state = %d, flags = 0x%02x,"
+ " status = 0x%02x\n",
+ smic->state, flags, status);
+@@ -377,9 +376,7 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
+ case SMIC_IDLE:
+ /* in IDLE we check for available messages */
+ if (flags & SMIC_SMS_DATA_AVAIL)
+- {
+ return SI_SM_ATTN;
+- }
+ return SI_SM_IDLE;
+
+ case SMIC_START_OP:
+@@ -391,7 +388,7 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
+
+ case SMIC_OP_OK:
+ if (status != SMIC_SC_SMS_READY) {
+- /* this should not happen */
++ /* this should not happen */
+ start_error_recovery(smic,
+ "state = SMIC_OP_OK,"
+ " status != SMIC_SC_SMS_READY");
+@@ -411,8 +408,10 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
+ "status != SMIC_SC_SMS_WR_START");
+ return SI_SM_CALL_WITH_DELAY;
+ }
+- /* we must not issue WR_(NEXT|END) unless
+- TX_DATA_READY is set */
++ /*
++ * we must not issue WR_(NEXT|END) unless
++ * TX_DATA_READY is set
++ * */
+ if (flags & SMIC_TX_DATA_READY) {
+ if (smic->write_count == 1) {
+ /* last byte */
+@@ -424,10 +423,8 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
+ }
+ write_next_byte(smic);
+ write_smic_flags(smic, flags | SMIC_FLAG_BSY);
+- }
+- else {
++ } else
+ return SI_SM_CALL_WITH_DELAY;
+- }
+ break;
+
+ case SMIC_WRITE_NEXT:
+@@ -442,52 +439,48 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
+ if (smic->write_count == 1) {
+ write_smic_control(smic, SMIC_CC_SMS_WR_END);
+ smic->state = SMIC_WRITE_END;
+- }
+- else {
++ } else {
+ write_smic_control(smic, SMIC_CC_SMS_WR_NEXT);
+ smic->state = SMIC_WRITE_NEXT;
+ }
+ write_next_byte(smic);
+ write_smic_flags(smic, flags | SMIC_FLAG_BSY);
+- }
+- else {
++ } else
+ return SI_SM_CALL_WITH_DELAY;
+- }
+ break;
+
+ case SMIC_WRITE_END:
+ if (status != SMIC_SC_SMS_WR_END) {
+- start_error_recovery (smic,
+- "state = SMIC_WRITE_END, "
+- "status != SMIC_SC_SMS_WR_END");
++ start_error_recovery(smic,
++ "state = SMIC_WRITE_END, "
++ "status != SMIC_SC_SMS_WR_END");
+ return SI_SM_CALL_WITH_DELAY;
+ }
+ /* data register holds an error code */
+ data = read_smic_data(smic);
+ if (data != 0) {
+- if (smic_debug & SMIC_DEBUG_ENABLE) {
+- printk(KERN_INFO
++ if (smic_debug & SMIC_DEBUG_ENABLE)
++ printk(KERN_DEBUG
+ "SMIC_WRITE_END: data = %02x\n", data);
+- }
+ start_error_recovery(smic,
+ "state = SMIC_WRITE_END, "
+ "data != SUCCESS");
+ return SI_SM_CALL_WITH_DELAY;
+- } else {
++ } else
+ smic->state = SMIC_WRITE2READ;
+- }
+ break;
+
+ case SMIC_WRITE2READ:
+- /* we must wait for RX_DATA_READY to be set before we
+- can continue */
++ /*
++ * we must wait for RX_DATA_READY to be set before we
++ * can continue
++ */
+ if (flags & SMIC_RX_DATA_READY) {
+ write_smic_control(smic, SMIC_CC_SMS_RD_START);
+ write_smic_flags(smic, flags | SMIC_FLAG_BSY);
+ smic->state = SMIC_READ_START;
+- } else {
++ } else
+ return SI_SM_CALL_WITH_DELAY;
+- }
+ break;
+
+ case SMIC_READ_START:
+@@ -502,15 +495,16 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
+ write_smic_control(smic, SMIC_CC_SMS_RD_NEXT);
+ write_smic_flags(smic, flags | SMIC_FLAG_BSY);
+ smic->state = SMIC_READ_NEXT;
+- } else {
++ } else
+ return SI_SM_CALL_WITH_DELAY;
+- }
+ break;
+
+ case SMIC_READ_NEXT:
+ switch (status) {
+- /* smic tells us that this is the last byte to be read
+- --> clean up */
++ /*
++ * smic tells us that this is the last byte to be read
++ * --> clean up
++ */
+ case SMIC_SC_SMS_RD_END:
+ read_next_byte(smic);
+ write_smic_control(smic, SMIC_CC_SMS_RD_END);
+@@ -523,9 +517,8 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
+ write_smic_control(smic, SMIC_CC_SMS_RD_NEXT);
+ write_smic_flags(smic, flags | SMIC_FLAG_BSY);
+ smic->state = SMIC_READ_NEXT;
+- } else {
++ } else
+ return SI_SM_CALL_WITH_DELAY;
+- }
+ break;
+ default:
+ start_error_recovery(
+@@ -546,10 +539,9 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
+ data = read_smic_data(smic);
+ /* data register holds an error code */
+ if (data != 0) {
+- if (smic_debug & SMIC_DEBUG_ENABLE) {
+- printk(KERN_INFO
++ if (smic_debug & SMIC_DEBUG_ENABLE)
++ printk(KERN_DEBUG
+ "SMIC_READ_END: data = %02x\n", data);
+- }
+ start_error_recovery(smic,
+ "state = SMIC_READ_END, "
+ "data != SUCCESS");
+@@ -565,7 +557,7 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
+
+ default:
+ if (smic_debug & SMIC_DEBUG_ENABLE) {
+- printk(KERN_WARNING "smic->state = %d\n", smic->state);
++ printk(KERN_DEBUG "smic->state = %d\n", smic->state);
+ start_error_recovery(smic, "state = UNKNOWN");
+ return SI_SM_CALL_WITH_DELAY;
+ }
+@@ -576,10 +568,12 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
+
+ static int smic_detect(struct si_sm_data *smic)
+ {
+- /* It's impossible for the SMIC fnags register to be all 1's,
+- (assuming a properly functioning, self-initialized BMC)
+- but that's what you get from reading a bogus address, so we
+- test that first. */
++ /*
++ * It's impossible for the SMIC fnags register to be all 1's,
++ * (assuming a properly functioning, self-initialized BMC)
++ * but that's what you get from reading a bogus address, so we
++ * test that first.
++ */
+ if (read_smic_flags(smic) == 0xff)
+ return 1;
+
+@@ -595,8 +589,7 @@ static int smic_size(void)
+ return sizeof(struct si_sm_data);
+ }
+
+-struct si_sm_handlers smic_smi_handlers =
+-{
++struct si_sm_handlers smic_smi_handlers = {
+ .init_data = init_smic_data,
+ .start_transaction = start_smic_transaction,
+ .get_result = smic_get_result,
+diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
+index 8f45ca9..1b9a870 100644
+--- a/drivers/char/ipmi/ipmi_watchdog.c
++++ b/drivers/char/ipmi/ipmi_watchdog.c
+@@ -54,13 +54,15 @@
+ #include <asm/atomic.h>
+
+ #ifdef CONFIG_X86
+-/* This is ugly, but I've determined that x86 is the only architecture
+- that can reasonably support the IPMI NMI watchdog timeout at this
+- time. If another architecture adds this capability somehow, it
+- will have to be a somewhat different mechanism and I have no idea
+- how it will work. So in the unlikely event that another
+- architecture supports this, we can figure out a good generic
+- mechanism for it at that time. */
++/*
++ * This is ugly, but I've determined that x86 is the only architecture
++ * that can reasonably support the IPMI NMI watchdog timeout at this
++ * time. If another architecture adds this capability somehow, it
++ * will have to be a somewhat different mechanism and I have no idea
++ * how it will work. So in the unlikely event that another
++ * architecture supports this, we can figure out a good generic
++ * mechanism for it at that time.
++ */
+ #include <asm/kdebug.h>
+ #define HAVE_DIE_NMI
+ #endif
+@@ -95,9 +97,8 @@
+ /* Operations that can be performed on a pretimout. */
+ #define WDOG_PREOP_NONE 0
+ #define WDOG_PREOP_PANIC 1
+-#define WDOG_PREOP_GIVE_DATA 2 /* Cause data to be available to
+- read. Doesn't work in NMI
+- mode. */
++/* Cause data to be available to read. Doesn't work in NMI mode. */
++#define WDOG_PREOP_GIVE_DATA 2
+
+ /* Actions to perform on a full timeout. */
+ #define WDOG_SET_TIMEOUT_ACT(byte, use) \
+@@ -108,8 +109,10 @@
+ #define WDOG_TIMEOUT_POWER_DOWN 2
+ #define WDOG_TIMEOUT_POWER_CYCLE 3
+
+-/* Byte 3 of the get command, byte 4 of the get response is the
+- pre-timeout in seconds. */
++/*
++ * Byte 3 of the get command, byte 4 of the get response is the
++ * pre-timeout in seconds.
++ */
+
+ /* Bits for setting byte 4 of the set command, byte 5 of the get response. */
+ #define WDOG_EXPIRE_CLEAR_BIOS_FRB2 (1 << 1)
+@@ -118,11 +121,13 @@
+ #define WDOG_EXPIRE_CLEAR_SMS_OS (1 << 4)
+ #define WDOG_EXPIRE_CLEAR_OEM (1 << 5)
+
+-/* Setting/getting the watchdog timer value. This is for bytes 5 and
+- 6 (the timeout time) of the set command, and bytes 6 and 7 (the
+- timeout time) and 8 and 9 (the current countdown value) of the
+- response. The timeout value is given in seconds (in the command it
+- is 100ms intervals). */
++/*
++ * Setting/getting the watchdog timer value. This is for bytes 5 and
++ * 6 (the timeout time) of the set command, and bytes 6 and 7 (the
++ * timeout time) and 8 and 9 (the current countdown value) of the
++ * response. The timeout value is given in seconds (in the command it
++ * is 100ms intervals).
++ */
+ #define WDOG_SET_TIMEOUT(byte1, byte2, val) \
+ (byte1) = (((val) * 10) & 0xff), (byte2) = (((val) * 10) >> 8)
+ #define WDOG_GET_TIMEOUT(byte1, byte2) \
+@@ -184,8 +189,10 @@ static int ipmi_set_timeout(int do_heartbeat);
+ static void ipmi_register_watchdog(int ipmi_intf);
+ static void ipmi_unregister_watchdog(int ipmi_intf);
+
+-/* If true, the driver will start running as soon as it is configured
+- and ready. */
++/*
++ * If true, the driver will start running as soon as it is configured
++ * and ready.
++ */
+ static int start_now;
+
+ static int set_param_int(const char *val, struct kernel_param *kp)
+@@ -309,10 +316,12 @@ static int ipmi_ignore_heartbeat;
+ /* Is someone using the watchdog? Only one user is allowed. */
+ static unsigned long ipmi_wdog_open;
+
+-/* If set to 1, the heartbeat command will set the state to reset and
+- start the timer. The timer doesn't normally run when the driver is
+- first opened until the heartbeat is set the first time, this
+- variable is used to accomplish this. */
++/*
++ * If set to 1, the heartbeat command will set the state to reset and
++ * start the timer. The timer doesn't normally run when the driver is
++ * first opened until the heartbeat is set the first time, this
++ * variable is used to accomplish this.
++ */
+ static int ipmi_start_timer_on_heartbeat;
+
+ /* IPMI version of the BMC. */
+@@ -329,10 +338,12 @@ static int nmi_handler_registered;
+
+ static int ipmi_heartbeat(void);
+
+-/* We use a mutex to make sure that only one thing can send a set
+- timeout at one time, because we only have one copy of the data.
+- The mutex is claimed when the set_timeout is sent and freed
+- when both messages are free. */
++/*
++ * We use a mutex to make sure that only one thing can send a set
++ * timeout at one time, because we only have one copy of the data.
++ * The mutex is claimed when the set_timeout is sent and freed
++ * when both messages are free.
++ */
+ static atomic_t set_timeout_tofree = ATOMIC_INIT(0);
+ static DEFINE_MUTEX(set_timeout_lock);
+ static DECLARE_COMPLETION(set_timeout_wait);
+@@ -346,15 +357,13 @@ static void set_timeout_free_recv(struct ipmi_recv_msg *msg)
+ if (atomic_dec_and_test(&set_timeout_tofree))
+ complete(&set_timeout_wait);
+ }
+-static struct ipmi_smi_msg set_timeout_smi_msg =
+-{
++static struct ipmi_smi_msg set_timeout_smi_msg = {
+ .done = set_timeout_free_smi
+ };
+-static struct ipmi_recv_msg set_timeout_recv_msg =
+-{
++static struct ipmi_recv_msg set_timeout_recv_msg = {
+ .done = set_timeout_free_recv
+ };
+-
++
+ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
+ struct ipmi_recv_msg *recv_msg,
+ int *send_heartbeat_now)
+@@ -373,13 +382,14 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
+ WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS);
+
+ if ((ipmi_version_major > 1)
+- || ((ipmi_version_major == 1) && (ipmi_version_minor >= 5)))
+- {
++ || ((ipmi_version_major == 1) && (ipmi_version_minor >= 5))) {
+ /* This is an IPMI 1.5-only feature. */
+ data[0] |= WDOG_DONT_STOP_ON_SET;
+ } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
+- /* In ipmi 1.0, setting the timer stops the watchdog, we
+- need to start it back up again. */
++ /*
++ * In ipmi 1.0, setting the timer stops the watchdog, we
++ * need to start it back up again.
++ */
+ hbnow = 1;
+ }
+
+@@ -465,12 +475,10 @@ static void panic_recv_free(struct ipmi_recv_msg *msg)
+ atomic_dec(&panic_done_count);
+ }
+
+-static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg =
+-{
++static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg = {
+ .done = panic_smi_free
+ };
+-static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg =
+-{
++static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg = {
+ .done = panic_recv_free
+ };
+
+@@ -480,8 +488,10 @@ static void panic_halt_ipmi_heartbeat(void)
+ struct ipmi_system_interface_addr addr;
+ int rv;
+
+- /* Don't reset the timer if we have the timer turned off, that
+- re-enables the watchdog. */
++ /*
++ * Don't reset the timer if we have the timer turned off, that
++ * re-enables the watchdog.
++ */
+ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
+ return;
+
+@@ -505,19 +515,19 @@ static void panic_halt_ipmi_heartbeat(void)
+ atomic_add(2, &panic_done_count);
+ }
+
+-static struct ipmi_smi_msg panic_halt_smi_msg =
+-{
++static struct ipmi_smi_msg panic_halt_smi_msg = {
+ .done = panic_smi_free
+ };
+-static struct ipmi_recv_msg panic_halt_recv_msg =
+-{
++static struct ipmi_recv_msg panic_halt_recv_msg = {
+ .done = panic_recv_free
+ };
+
+-/* Special call, doesn't claim any locks. This is only to be called
+- at panic or halt time, in run-to-completion mode, when the caller
+- is the only CPU and the only thing that will be going is these IPMI
+- calls. */
++/*
++ * Special call, doesn't claim any locks. This is only to be called
++ * at panic or halt time, in run-to-completion mode, when the caller
++ * is the only CPU and the only thing that will be going is these IPMI
++ * calls.
++ */
+ static void panic_halt_ipmi_set_timeout(void)
+ {
+ int send_heartbeat_now;
+@@ -540,10 +550,12 @@ static void panic_halt_ipmi_set_timeout(void)
+ ipmi_poll_interface(watchdog_user);
+ }
+
+-/* We use a semaphore to make sure that only one thing can send a
+- heartbeat at one time, because we only have one copy of the data.
+- The semaphore is claimed when the set_timeout is sent and freed
+- when both messages are free. */
++/*
++ * We use a mutex to make sure that only one thing can send a
++ * heartbeat at one time, because we only have one copy of the data.
++ * The semaphore is claimed when the set_timeout is sent and freed
++ * when both messages are free.
++ */
+ static atomic_t heartbeat_tofree = ATOMIC_INIT(0);
+ static DEFINE_MUTEX(heartbeat_lock);
+ static DECLARE_COMPLETION(heartbeat_wait);
+@@ -557,15 +569,13 @@ static void heartbeat_free_recv(struct ipmi_recv_msg *msg)
+ if (atomic_dec_and_test(&heartbeat_tofree))
+ complete(&heartbeat_wait);
+ }
+-static struct ipmi_smi_msg heartbeat_smi_msg =
+-{
++static struct ipmi_smi_msg heartbeat_smi_msg = {
+ .done = heartbeat_free_smi
+ };
+-static struct ipmi_recv_msg heartbeat_recv_msg =
+-{
++static struct ipmi_recv_msg heartbeat_recv_msg = {
+ .done = heartbeat_free_recv
+ };
+-
++
+ static int ipmi_heartbeat(void)
+ {
+ struct kernel_ipmi_msg msg;
+@@ -580,10 +590,12 @@ static int ipmi_heartbeat(void)
+ ipmi_watchdog_state = action_val;
+ return ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
+ } else if (pretimeout_since_last_heartbeat) {
+- /* A pretimeout occurred, make sure we set the timeout.
+- We don't want to set the action, though, we want to
+- leave that alone (thus it can't be combined with the
+- above operation. */
++ /*
++ * A pretimeout occurred, make sure we set the timeout.
++ * We don't want to set the action, though, we want to
++ * leave that alone (thus it can't be combined with the
++ * above operation.
++ */
+ return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
+ }
+
+@@ -591,8 +603,10 @@ static int ipmi_heartbeat(void)
+
+ atomic_set(&heartbeat_tofree, 2);
+
+- /* Don't reset the timer if we have the timer turned off, that
+- re-enables the watchdog. */
++ /*
++ * Don't reset the timer if we have the timer turned off, that
++ * re-enables the watchdog.
++ */
+ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) {
+ mutex_unlock(&heartbeat_lock);
+ return 0;
+@@ -625,10 +639,12 @@ static int ipmi_heartbeat(void)
+ wait_for_completion(&heartbeat_wait);
+
+ if (heartbeat_recv_msg.msg.data[0] != 0) {
+- /* Got an error in the heartbeat response. It was already
+- reported in ipmi_wdog_msg_handler, but we should return
+- an error here. */
+- rv = -EINVAL;
++ /*
++ * Got an error in the heartbeat response. It was already
++ * reported in ipmi_wdog_msg_handler, but we should return
++ * an error here.
++ */
++ rv = -EINVAL;
+ }
+
+ mutex_unlock(&heartbeat_lock);
+@@ -636,8 +652,7 @@ static int ipmi_heartbeat(void)
+ return rv;
+ }
+
+-static struct watchdog_info ident =
+-{
++static struct watchdog_info ident = {
+ .options = 0, /* WDIOF_SETTIMEOUT, */
+ .firmware_version = 1,
+ .identity = "IPMI"
+@@ -650,7 +665,7 @@ static int ipmi_ioctl(struct inode *inode, struct file *file,
+ int i;
+ int val;
+
+- switch(cmd) {
++ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ i = copy_to_user(argp, &ident, sizeof(ident));
+ return i ? -EFAULT : 0;
+@@ -690,15 +705,13 @@ static int ipmi_ioctl(struct inode *inode, struct file *file,
+ i = copy_from_user(&val, argp, sizeof(int));
+ if (i)
+ return -EFAULT;
+- if (val & WDIOS_DISABLECARD)
+- {
++ if (val & WDIOS_DISABLECARD) {
+ ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
+ ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
+ ipmi_start_timer_on_heartbeat = 0;
+ }
+
+- if (val & WDIOS_ENABLECARD)
+- {
++ if (val & WDIOS_ENABLECARD) {
+ ipmi_watchdog_state = action_val;
+ ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
+ }
+@@ -724,13 +737,13 @@ static ssize_t ipmi_write(struct file *file,
+ int rv;
+
+ if (len) {
+- if (!nowayout) {
+- size_t i;
++ if (!nowayout) {
++ size_t i;
+
+ /* In case it was set long ago */
+ expect_close = 0;
+
+- for (i = 0; i != len; i++) {
++ for (i = 0; i != len; i++) {
+ char c;
+
+ if (get_user(c, buf + i))
+@@ -758,15 +771,17 @@ static ssize_t ipmi_read(struct file *file,
+ if (count <= 0)
+ return 0;
+
+- /* Reading returns if the pretimeout has gone off, and it only does
+- it once per pretimeout. */
++ /*
++ * Reading returns if the pretimeout has gone off, and it only does
++ * it once per pretimeout.
++ */
+ spin_lock(&ipmi_read_lock);
+ if (!data_to_read) {
+ if (file->f_flags & O_NONBLOCK) {
+ rv = -EAGAIN;
+ goto out;
+ }
+-
++
+ init_waitqueue_entry(&wait, current);
+ add_wait_queue(&read_q, &wait);
+ while (!data_to_read) {
+@@ -776,7 +791,7 @@ static ssize_t ipmi_read(struct file *file,
+ spin_lock(&ipmi_read_lock);
+ }
+ remove_wait_queue(&read_q, &wait);
+-
++
+ if (signal_pending(current)) {
+ rv = -ERESTARTSYS;
+ goto out;
+@@ -799,25 +814,27 @@ static ssize_t ipmi_read(struct file *file,
+
+ static int ipmi_open(struct inode *ino, struct file *filep)
+ {
+- switch (iminor(ino)) {
+- case WATCHDOG_MINOR:
++ switch (iminor(ino)) {
++ case WATCHDOG_MINOR:
+ if (test_and_set_bit(0, &ipmi_wdog_open))
+- return -EBUSY;
++ return -EBUSY;
+
+- /* Don't start the timer now, let it start on the
+- first heartbeat. */
++ /*
++ * Don't start the timer now, let it start on the
++ * first heartbeat.
++ */
+ ipmi_start_timer_on_heartbeat = 1;
+ return nonseekable_open(ino, filep);
+
+ default:
+ return (-ENODEV);
+- }
++ }
+ }
+
+ static unsigned int ipmi_poll(struct file *file, poll_table *wait)
+ {
+ unsigned int mask = 0;
+-
++
+ poll_wait(file, &read_q, wait);
+
+ spin_lock(&ipmi_read_lock);
+@@ -851,7 +868,7 @@ static int ipmi_close(struct inode *ino, struct file *filep)
+ clear_bit(0, &ipmi_wdog_open);
+ }
+
+- ipmi_fasync (-1, filep, 0);
++ ipmi_fasync(-1, filep, 0);
+ expect_close = 0;
+
+ return 0;
+@@ -882,7 +899,7 @@ static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
+ msg->msg.data[0],
+ msg->msg.cmd);
+ }
+-
++
+ ipmi_free_recv_msg(msg);
+ }
+
+@@ -902,14 +919,14 @@ static void ipmi_wdog_pretimeout_handler(void *handler_data)
+ }
+ }
+
+- /* On some machines, the heartbeat will give
+- an error and not work unless we re-enable
+- the timer. So do so. */
++ /*
++ * On some machines, the heartbeat will give an error and not
++ * work unless we re-enable the timer. So do so.
++ */
+ pretimeout_since_last_heartbeat = 1;
+ }
+
+-static struct ipmi_user_hndl ipmi_hndlrs =
+-{
++static struct ipmi_user_hndl ipmi_hndlrs = {
+ .ipmi_recv_hndl = ipmi_wdog_msg_handler,
+ .ipmi_watchdog_pretimeout = ipmi_wdog_pretimeout_handler
+ };
+@@ -949,8 +966,10 @@ static void ipmi_register_watchdog(int ipmi_intf)
+ int old_timeout = timeout;
+ int old_preop_val = preop_val;
+
+- /* Set the pretimeout to go off in a second and give
+- ourselves plenty of time to stop the timer. */
++ /*
++ * Set the pretimeout to go off in a second and give
++ * ourselves plenty of time to stop the timer.
++ */
+ ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
+ preop_val = WDOG_PREOP_NONE; /* Make sure nothing happens */
+ pretimeout = 99;
+@@ -974,7 +993,7 @@ static void ipmi_register_watchdog(int ipmi_intf)
+ " occur. The NMI pretimeout will"
+ " likely not work\n");
+ }
+- out_restore:
++ out_restore:
+ testing_nmi = 0;
+ preop_val = old_preop_val;
+ pretimeout = old_pretimeout;
+@@ -1009,9 +1028,11 @@ static void ipmi_unregister_watchdog(int ipmi_intf)
+ /* Make sure no one can call us any more. */
+ misc_deregister(&ipmi_wdog_miscdev);
+
+- /* Wait to make sure the message makes it out. The lower layer has
+- pointers to our buffers, we want to make sure they are done before
+- we release our memory. */
++ /*
++ * Wait to make sure the message makes it out. The lower layer has
++ * pointers to our buffers, we want to make sure they are done before
++ * we release our memory.
++ */
+ while (atomic_read(&set_timeout_tofree))
+ schedule_timeout_uninterruptible(1);
+
+@@ -1052,15 +1073,17 @@ ipmi_nmi(struct notifier_block *self, unsigned long val, void *data)
+ return NOTIFY_STOP;
+ }
+
+- /* If we are not expecting a timeout, ignore it. */
++ /* If we are not expecting a timeout, ignore it. */
+ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
+ return NOTIFY_OK;
+
+ if (preaction_val != WDOG_PRETIMEOUT_NMI)
+ return NOTIFY_OK;
+
+- /* If no one else handled the NMI, we assume it was the IPMI
+- watchdog. */
++ /*
++ * If no one else handled the NMI, we assume it was the IPMI
++ * watchdog.
++ */
+ if (preop_val == WDOG_PREOP_PANIC) {
+ /* On some machines, the heartbeat will give
+ an error and not work unless we re-enable
+@@ -1082,7 +1105,7 @@ static int wdog_reboot_handler(struct notifier_block *this,
+ unsigned long code,
+ void *unused)
+ {
+- static int reboot_event_handled = 0;
++ static int reboot_event_handled;
+
+ if ((watchdog_user) && (!reboot_event_handled)) {
+ /* Make sure we only do this once. */
+@@ -1115,7 +1138,7 @@ static int wdog_panic_handler(struct notifier_block *this,
+ unsigned long event,
+ void *unused)
+ {
+- static int panic_event_handled = 0;
++ static int panic_event_handled;
+
+ /* On a panic, if we have a panic timeout, make sure to extend
+ the watchdog timer to a reasonable value to complete the
+@@ -1125,7 +1148,7 @@ static int wdog_panic_handler(struct notifier_block *this,
+ ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
+ /* Make sure we do this only once. */
+ panic_event_handled = 1;
+-
++
+ timeout = 255;
+ pretimeout = 0;
+ panic_halt_ipmi_set_timeout();
+@@ -1151,8 +1174,7 @@ static void ipmi_smi_gone(int if_num)
+ ipmi_unregister_watchdog(if_num);
+ }
+
+-static struct ipmi_smi_watcher smi_watcher =
+-{
++static struct ipmi_smi_watcher smi_watcher = {
+ .owner = THIS_MODULE,
+ .new_smi = ipmi_new_smi,
+ .smi_gone = ipmi_smi_gone
+diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
+index eba2883..4f3cefa 100644
+--- a/drivers/char/isicom.c
++++ b/drivers/char/isicom.c
+@@ -126,8 +126,8 @@
+ #include <linux/delay.h>
+ #include <linux/ioport.h>
+
+-#include <asm/uaccess.h>
+-#include <asm/io.h>
++#include <linux/uaccess.h>
++#include <linux/io.h>
+ #include <asm/system.h>
+
+ #include <linux/pci.h>
+@@ -189,7 +189,7 @@ struct isi_board {
+ unsigned short status;
+ unsigned short port_status; /* each bit for each port */
+ unsigned short shift_count;
+- struct isi_port * ports;
++ struct isi_port *ports;
+ signed char count;
+ spinlock_t card_lock; /* Card wide lock 11/5/00 -sameer */
+ unsigned long flags;
+@@ -205,11 +205,11 @@ struct isi_port {
+ u16 channel;
+ u16 status;
+ u16 closing_wait;
+- struct isi_board * card;
+- struct tty_struct * tty;
++ struct isi_board *card;
++ struct tty_struct *tty;
+ wait_queue_head_t close_wait;
+ wait_queue_head_t open_wait;
+- unsigned char * xmit_buf;
++ unsigned char *xmit_buf;
+ int xmit_head;
+ int xmit_tail;
+ int xmit_cnt;
+@@ -405,7 +405,7 @@ static void isicom_tx(unsigned long _data)
+
+ /* find next active board */
+ card = (prev_card + 1) & 0x0003;
+- while(count-- > 0) {
++ while (count-- > 0) {
+ if (isi_card[card].status & BOARD_ACTIVE)
+ break;
+ card = (card + 1) & 0x0003;
+@@ -428,7 +428,7 @@ static void isicom_tx(unsigned long _data)
+ if (retries >= 100)
+ goto unlock;
+
+- for (;count > 0;count--, port++) {
++ for (; count > 0; count--, port++) {
+ /* port not active or tx disabled to force flow control */
+ if (!(port->flags & ASYNC_INITIALIZED) ||
+ !(port->status & ISI_TXOK))
+@@ -471,9 +471,10 @@ static void isicom_tx(unsigned long _data)
+ break;
+ }
+ }
+- if (cnt <= 0) break;
++ if (cnt <= 0)
++ break;
+ word_count = cnt >> 1;
+- outsw(base, port->xmit_buf+port->xmit_tail,word_count);
++ outsw(base, port->xmit_buf+port->xmit_tail, word_count);
+ port->xmit_tail = (port->xmit_tail
+ + (word_count << 1)) & (SERIAL_XMIT_SIZE - 1);
+ txcount -= (word_count << 1);
+@@ -556,7 +557,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
+ tty = port->tty;
+ if (tty == NULL) {
+ word_count = byte_count >> 1;
+- while(byte_count > 1) {
++ while (byte_count > 1) {
+ inw(base);
+ byte_count -= 2;
+ }
+@@ -569,7 +570,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
+
+ if (header & 0x8000) { /* Status Packet */
+ header = inw(base);
+- switch(header & 0xff) {
++ switch (header & 0xff) {
+ case 0: /* Change in EIA signals */
+ if (port->flags & ASYNC_CHECK_CD) {
+ if (port->status & ISI_DCD) {
+@@ -656,7 +657,8 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
+ if (byte_count > 0) {
+ pr_dbg("Intr(0x%lx:%d): Flip buffer overflow! dropping "
+ "bytes...\n", base, channel + 1);
+- while(byte_count > 0) { /* drain out unread xtra data */
++ /* drain out unread xtra data */
++ while (byte_count > 0) {
+ inw(base);
+ byte_count -= 2;
+ }
+@@ -679,8 +681,11 @@ static void isicom_config_port(struct isi_port *port)
+ shift_count = card->shift_count;
+ unsigned char flow_ctrl;
+
+- if (!(tty = port->tty) || !tty->termios)
++ tty = port->tty;
++
++ if (tty == NULL)
+ return;
++ /* FIXME: Switch to new tty baud API */
+ baud = C_BAUD(tty);
+ if (baud & CBAUDEX) {
+ baud &= ~CBAUDEX;
+@@ -706,7 +711,7 @@ static void isicom_config_port(struct isi_port *port)
+ if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+ baud++; /* 57.6 Kbps */
+ if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+- baud +=2; /* 115 Kbps */
++ baud += 2; /* 115 Kbps */
+ if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+ baud += 3; /* 230 kbps*/
+ if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+@@ -716,15 +721,14 @@ static void isicom_config_port(struct isi_port *port)
+ /* hang up */
+ drop_dtr(port);
+ return;
+- }
+- else
++ } else
+ raise_dtr(port);
+
+ if (WaitTillCardIsFree(base) == 0) {
+- outw(0x8000 | (channel << shift_count) |0x03, base);
++ outw(0x8000 | (channel << shift_count) | 0x03, base);
+ outw(linuxb_to_isib[baud] << 8 | 0x03, base);
+ channel_setup = 0;
+- switch(C_CSIZE(tty)) {
++ switch (C_CSIZE(tty)) {
+ case CS5:
+ channel_setup |= ISICOM_CS5;
+ break;
+@@ -767,7 +771,7 @@ static void isicom_config_port(struct isi_port *port)
+ flow_ctrl |= ISICOM_INITIATE_XONXOFF;
+
+ if (WaitTillCardIsFree(base) == 0) {
+- outw(0x8000 | (channel << shift_count) |0x04, base);
++ outw(0x8000 | (channel << shift_count) | 0x04, base);
+ outw(flow_ctrl << 8 | 0x05, base);
+ outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
+ InterruptTheCard(base);
+@@ -805,20 +809,17 @@ static int isicom_setup_port(struct isi_port *port)
+ struct isi_board *card = port->card;
+ unsigned long flags;
+
+- if (port->flags & ASYNC_INITIALIZED) {
++ if (port->flags & ASYNC_INITIALIZED)
+ return 0;
+- }
+ if (!port->xmit_buf) {
+- unsigned long page;
+-
+- if (!(page = get_zeroed_page(GFP_KERNEL)))
++ /* Relies on BKL */
++ unsigned long page = get_zeroed_page(GFP_KERNEL);
++ if (page == 0)
+ return -ENOMEM;
+-
+- if (port->xmit_buf) {
++ if (port->xmit_buf)
+ free_page(page);
+- return -ERESTARTSYS;
+- }
+- port->xmit_buf = (unsigned char *) page;
++ else
++ port->xmit_buf = (unsigned char *) page;
+ }
+
+ spin_lock_irqsave(&card->card_lock, flags);
+@@ -949,21 +950,18 @@ static int isicom_open(struct tty_struct *tty, struct file *filp)
+ port->count++;
+ tty->driver_data = port;
+ port->tty = tty;
+- if ((error = isicom_setup_port(port))!=0)
+- return error;
+- if ((error = block_til_ready(tty, filp, port))!=0)
+- return error;
+-
+- return 0;
++ error = isicom_setup_port(port);
++ if (error == 0)
++ error = block_til_ready(tty, filp, port);
++ return error;
+ }
+
+ /* close et all */
+
+ static inline void isicom_shutdown_board(struct isi_board *bp)
+ {
+- if (bp->status & BOARD_ACTIVE) {
++ if (bp->status & BOARD_ACTIVE)
+ bp->status &= ~BOARD_ACTIVE;
+- }
+ }
+
+ /* card->lock HAS to be held */
+@@ -1012,6 +1010,22 @@ static void isicom_shutdown_port(struct isi_port *port)
+ }
+ }
+
++static void isicom_flush_buffer(struct tty_struct *tty)
++{
++ struct isi_port *port = tty->driver_data;
++ struct isi_board *card = port->card;
++ unsigned long flags;
++
++ if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
++ return;
++
++ spin_lock_irqsave(&card->card_lock, flags);
++ port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
++ spin_unlock_irqrestore(&card->card_lock, flags);
++
++ tty_wakeup(tty);
++}
++
+ static void isicom_close(struct tty_struct *tty, struct file *filp)
+ {
+ struct isi_port *port = tty->driver_data;
+@@ -1065,8 +1079,7 @@ static void isicom_close(struct tty_struct *tty, struct file *filp)
+ isicom_shutdown_port(port);
+ spin_unlock_irqrestore(&card->card_lock, flags);
+
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ isicom_flush_buffer(tty);
+ tty_ldisc_flush(tty);
+
+ spin_lock_irqsave(&card->card_lock, flags);
+@@ -1104,7 +1117,7 @@ static int isicom_write(struct tty_struct *tty, const unsigned char *buf,
+
+ spin_lock_irqsave(&card->card_lock, flags);
+
+- while(1) {
++ while (1) {
+ cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt
+ - 1, SERIAL_XMIT_SIZE - port->xmit_head));
+ if (cnt <= 0)
+@@ -1125,28 +1138,29 @@ static int isicom_write(struct tty_struct *tty, const unsigned char *buf,
+ }
+
+ /* put_char et all */
+-static void isicom_put_char(struct tty_struct *tty, unsigned char ch)
++static int isicom_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ struct isi_port *port = tty->driver_data;
+ struct isi_board *card = port->card;
+ unsigned long flags;
+
+ if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
+- return;
++ return 0;
+
+ if (!port->xmit_buf)
+- return;
++ return 0;
+
+ spin_lock_irqsave(&card->card_lock, flags);
+ if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
+ spin_unlock_irqrestore(&card->card_lock, flags);
+- return;
++ return 0;
+ }
+
+ port->xmit_buf[port->xmit_head++] = ch;
+ port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
+ port->xmit_cnt++;
+ spin_unlock_irqrestore(&card->card_lock, flags);
++ return 1;
+ }
+
+ /* flush_chars et all */
+@@ -1258,6 +1272,8 @@ static int isicom_set_serial_info(struct isi_port *port,
+ if (copy_from_user(&newinfo, info, sizeof(newinfo)))
+ return -EFAULT;
+
++ lock_kernel();
++
+ reconfig_port = ((port->flags & ASYNC_SPD_MASK) !=
+ (newinfo.flags & ASYNC_SPD_MASK));
+
+@@ -1265,12 +1281,13 @@ static int isicom_set_serial_info(struct isi_port *port,
+ if ((newinfo.close_delay != port->close_delay) ||
+ (newinfo.closing_wait != port->closing_wait) ||
+ ((newinfo.flags & ~ASYNC_USR_MASK) !=
+- (port->flags & ~ASYNC_USR_MASK)))
++ (port->flags & ~ASYNC_USR_MASK))) {
++ unlock_kernel();
+ return -EPERM;
+- port->flags = ((port->flags & ~ ASYNC_USR_MASK) |
++ }
++ port->flags = ((port->flags & ~ASYNC_USR_MASK) |
+ (newinfo.flags & ASYNC_USR_MASK));
+- }
+- else {
++ } else {
+ port->close_delay = newinfo.close_delay;
+ port->closing_wait = newinfo.closing_wait;
+ port->flags = ((port->flags & ~ASYNC_FLAGS) |
+@@ -1282,6 +1299,7 @@ static int isicom_set_serial_info(struct isi_port *port,
+ isicom_config_port(port);
+ spin_unlock_irqrestore(&port->card->card_lock, flags);
+ }
++ unlock_kernel();
+ return 0;
+ }
+
+@@ -1290,6 +1308,7 @@ static int isicom_get_serial_info(struct isi_port *port,
+ {
+ struct serial_struct out_info;
+
++ lock_kernel();
+ memset(&out_info, 0, sizeof(out_info));
+ /* out_info.type = ? */
+ out_info.line = port - isi_ports;
+@@ -1299,6 +1318,7 @@ static int isicom_get_serial_info(struct isi_port *port,
+ /* out_info.baud_base = ? */
+ out_info.close_delay = port->close_delay;
+ out_info.closing_wait = port->closing_wait;
++ unlock_kernel();
+ if (copy_to_user(info, &out_info, sizeof(out_info)))
+ return -EFAULT;
+ return 0;
+@@ -1314,7 +1334,7 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
+ if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
+ return -ENODEV;
+
+- switch(cmd) {
++ switch (cmd) {
+ case TCSBRK:
+ retval = tty_check_change(tty);
+ if (retval)
+@@ -1331,19 +1351,6 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
+ tty_wait_until_sent(tty, 0);
+ isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
+ return 0;
+-
+- case TIOCGSOFTCAR:
+- return put_user(C_CLOCAL(tty) ? 1 : 0,
+- (unsigned long __user *)argp);
+-
+- case TIOCSSOFTCAR:
+- if (get_user(arg, (unsigned long __user *) argp))
+- return -EFAULT;
+- tty->termios->c_cflag =
+- ((tty->termios->c_cflag & ~CLOCAL) |
+- (arg ? CLOCAL : 0));
+- return 0;
+-
+ case TIOCGSERIAL:
+ return isicom_get_serial_info(port, argp);
+
+@@ -1453,22 +1460,6 @@ static void isicom_hangup(struct tty_struct *tty)
+ wake_up_interruptible(&port->open_wait);
+ }
+
+-/* flush_buffer et all */
+-static void isicom_flush_buffer(struct tty_struct *tty)
+-{
+- struct isi_port *port = tty->driver_data;
+- struct isi_board *card = port->card;
+- unsigned long flags;
+-
+- if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
+- return;
+-
+- spin_lock_irqsave(&card->card_lock, flags);
+- port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+- spin_unlock_irqrestore(&card->card_lock, flags);
+-
+- tty_wakeup(tty);
+-}
+
+ /*
+ * Driver init and deinit functions
+@@ -1592,7 +1583,7 @@ static int __devinit load_firmware(struct pci_dev *pdev,
+ default:
+ dev_err(&pdev->dev, "Unknown signature.\n");
+ goto end;
+- }
++ }
+
+ retval = request_firmware(&fw, name, &pdev->dev);
+ if (retval)
+@@ -1620,7 +1611,8 @@ static int __devinit load_firmware(struct pci_dev *pdev,
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+- if ((status = inw(base + 0x4)) != 0) {
++ status = inw(base + 0x4);
++ if (status != 0) {
+ dev_warn(&pdev->dev, "Card%d rejected load header:\n"
+ KERN_WARNING "Address:0x%x\n"
+ KERN_WARNING "Count:0x%x\n"
+@@ -1637,12 +1629,13 @@ static int __devinit load_firmware(struct pci_dev *pdev,
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+- if ((status = inw(base + 0x4)) != 0) {
++ status = inw(base + 0x4);
++ if (status != 0) {
+ dev_err(&pdev->dev, "Card%d got out of sync.Card "
+ "Status:0x%x\n", index + 1, status);
+ goto errrelfw;
+ }
+- }
++ }
+
+ /* XXX: should we test it by reading it back and comparing with original like
+ * in load firmware package? */
+@@ -1666,7 +1659,8 @@ static int __devinit load_firmware(struct pci_dev *pdev,
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+- if ((status = inw(base + 0x4)) != 0) {
++ status = inw(base + 0x4);
++ if (status != 0) {
+ dev_warn(&pdev->dev, "Card%d rejected verify header:\n"
+ KERN_WARNING "Address:0x%x\n"
+ KERN_WARNING "Count:0x%x\n"
+@@ -1699,7 +1693,8 @@ static int __devinit load_firmware(struct pci_dev *pdev,
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+- if ((status = inw(base + 0x4)) != 0) {
++ status = inw(base + 0x4);
++ if (status != 0) {
+ dev_err(&pdev->dev, "Card%d verify got out of sync. "
+ "Card Status:0x%x\n", index + 1, status);
+ goto errrelfw;
+@@ -1764,7 +1759,7 @@ static int __devinit isicom_probe(struct pci_dev *pdev,
+ index + 1);
+ retval = -EBUSY;
+ goto errdec;
+- }
++ }
+
+ retval = request_irq(board->irq, isicom_interrupt,
+ IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board);
+@@ -1818,7 +1813,7 @@ static int __init isicom_init(void)
+ int retval, idx, channel;
+ struct isi_port *port;
+
+- for(idx = 0; idx < BOARD_COUNT; idx++) {
++ for (idx = 0; idx < BOARD_COUNT; idx++) {
+ port = &isi_ports[idx * 16];
+ isi_card[idx].ports = port;
+ spin_lock_init(&isi_card[idx].card_lock);
+@@ -1832,7 +1827,7 @@ static int __init isicom_init(void)
+ init_waitqueue_head(&port->open_wait);
+ init_waitqueue_head(&port->close_wait);
+ /* . . . */
+- }
++ }
+ isi_card[idx].base = 0;
+ isi_card[idx].irq = 0;
+ }
+diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
+index c645455..7c8b62f 100644
+--- a/drivers/char/istallion.c
++++ b/drivers/char/istallion.c
+@@ -1682,16 +1682,6 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
+ rc = 0;
+
+ switch (cmd) {
+- case TIOCGSOFTCAR:
+- rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
+- (unsigned __user *) arg);
+- break;
+- case TIOCSSOFTCAR:
+- if ((rc = get_user(ival, (unsigned __user *) arg)) == 0)
+- tty->termios->c_cflag =
+- (tty->termios->c_cflag & ~CLOCAL) |
+- (ival ? CLOCAL : 0);
+- break;
+ case TIOCGSERIAL:
+ rc = stli_getserial(portp, argp);
+ break;
+@@ -3267,7 +3257,7 @@ static int stli_initecp(struct stlibrd *brdp)
+ */
+ EBRDINIT(brdp);
+
+- brdp->membase = ioremap(brdp->memaddr, brdp->memsize);
++ brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
+ if (brdp->membase == NULL) {
+ retval = -ENOMEM;
+ goto err_reg;
+@@ -3424,7 +3414,7 @@ static int stli_initonb(struct stlibrd *brdp)
+ */
+ EBRDINIT(brdp);
+
+- brdp->membase = ioremap(brdp->memaddr, brdp->memsize);
++ brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
+ if (brdp->membase == NULL) {
+ retval = -ENOMEM;
+ goto err_reg;
+@@ -3675,7 +3665,7 @@ static int stli_eisamemprobe(struct stlibrd *brdp)
+ */
+ for (i = 0; (i < stli_eisamempsize); i++) {
+ brdp->memaddr = stli_eisamemprobeaddrs[i];
+- brdp->membase = ioremap(brdp->memaddr, brdp->memsize);
++ brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
+ if (brdp->membase == NULL)
+ continue;
+
+@@ -4433,6 +4423,8 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
+ done = 0;
+ rc = 0;
+
++ lock_kernel();
++
+ switch (cmd) {
+ case COM_GETPORTSTATS:
+ rc = stli_getportstats(NULL, argp);
+@@ -4455,6 +4447,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
+ done++;
+ break;
+ }
++ unlock_kernel();
+
+ if (done)
+ return rc;
+@@ -4472,6 +4465,8 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
+ if (brdp->state == 0)
+ return -ENODEV;
+
++ lock_kernel();
++
+ switch (cmd) {
+ case STL_BINTR:
+ EBRDINTR(brdp);
+@@ -4494,6 +4489,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
+ rc = -ENOIOCTLCMD;
+ break;
+ }
++ unlock_kernel();
+ return rc;
+ }
+
+diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
+index 4dbd342..7f7e798 100644
+--- a/drivers/char/keyboard.c
++++ b/drivers/char/keyboard.c
+@@ -42,6 +42,7 @@
+ #include <linux/input.h>
+ #include <linux/reboot.h>
+ #include <linux/notifier.h>
++#include <linux/jiffies.h>
+
+ extern void ctrl_alt_del(void);
+
+@@ -109,6 +110,7 @@ const int max_vals[] = {
+ const int NR_TYPES = ARRAY_SIZE(max_vals);
+
+ struct kbd_struct kbd_table[MAX_NR_CONSOLES];
++EXPORT_SYMBOL_GPL(kbd_table);
+ static struct kbd_struct *kbd = kbd_table;
+
+ struct vt_spawn_console vt_spawn_con = {
+@@ -259,6 +261,7 @@ void kd_mksound(unsigned int hz, unsigned int ticks)
+ } else
+ kd_nosound(0);
+ }
++EXPORT_SYMBOL(kd_mksound);
+
+ /*
+ * Setting the keyboard rate.
+@@ -928,7 +931,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 +1037,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))
+@@ -1227,7 +1232,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
+
+ if (rep &&
+ (!vc_kbd_mode(kbd, VC_REPEAT) ||
+- (tty && !L_ECHO(tty) && tty->driver->chars_in_buffer(tty)))) {
++ (tty && !L_ECHO(tty) && tty_chars_in_buffer(tty)))) {
+ /*
+ * Don't repeat a key if the input buffers are not empty and the
+ * characters get aren't echoed locally. This makes key repeat
+@@ -1237,6 +1242,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 +1291,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..934ffaf 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,20 +339,32 @@ 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;
+ }
+
++#ifdef CONFIG_DEVKMEM
+ static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
+ {
+ unsigned long pfn;
+@@ -315,6 +385,7 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
+ vma->vm_pgoff = pfn;
+ return mmap_mem(file, vma);
+ }
++#endif
+
+ #ifdef CONFIG_CRASH_DUMP
+ /*
+@@ -353,6 +424,7 @@ static ssize_t read_oldmem(struct file *file, char __user *buf,
+ extern long vread(char *buf, char *addr, unsigned long count);
+ extern long vwrite(char *buf, char *addr, unsigned long count);
+
++#ifdef CONFIG_DEVKMEM
+ /*
+ * This function reads the *virtual* memory as seen by the kernel.
+ */
+@@ -557,6 +629,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
+ *ppos = p;
+ return virtr + wrote;
+ }
++#endif
+
+ #ifdef CONFIG_DEVPORT
+ static ssize_t read_port(struct file * file, char __user * buf,
+@@ -734,6 +807,7 @@ static const struct file_operations mem_fops = {
+ .get_unmapped_area = get_unmapped_area_mem,
+ };
+
++#ifdef CONFIG_DEVKMEM
+ static const struct file_operations kmem_fops = {
+ .llseek = memory_lseek,
+ .read = read_kmem,
+@@ -742,6 +816,7 @@ static const struct file_operations kmem_fops = {
+ .open = open_kmem,
+ .get_unmapped_area = get_unmapped_area_mem,
+ };
++#endif
+
+ static const struct file_operations null_fops = {
+ .llseek = null_lseek,
+@@ -820,11 +895,13 @@ static int memory_open(struct inode * inode, struct file * filp)
+ filp->f_mapping->backing_dev_info =
+ &directly_mappable_cdev_bdi;
+ break;
++#ifdef CONFIG_DEVKMEM
+ case 2:
+ filp->f_op = &kmem_fops;
+ filp->f_mapping->backing_dev_info =
+ &directly_mappable_cdev_bdi;
+ break;
++#endif
+ case 3:
+ filp->f_op = &null_fops;
+ break;
+@@ -873,7 +950,9 @@ static const struct {
+ const struct file_operations *fops;
+ } devlist[] = { /* list of minor devices */
+ {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
++#ifdef CONFIG_DEVKMEM
+ {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
++#endif
+ {3, "null", S_IRUGO | S_IWUGO, &null_fops},
+ #ifdef CONFIG_DEVPORT
+ {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
+diff --git a/drivers/char/misc.c b/drivers/char/misc.c
+index a39101f..eaace0d 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,27 +259,30 @@ 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)
+ {
+-#ifdef CONFIG_PROC_FS
+- struct proc_dir_entry *ent;
++ int err;
+
+- ent = create_proc_entry("misc", 0, NULL);
+- if (ent)
+- ent->proc_fops = &misc_proc_fops;
++#ifdef CONFIG_PROC_FS
++ proc_create("misc", 0, NULL, &misc_proc_fops);
+ #endif
+ misc_class = class_create(THIS_MODULE, "misc");
++ err = PTR_ERR(misc_class);
+ if (IS_ERR(misc_class))
+- return PTR_ERR(misc_class);
++ goto fail_remove;
+
+- if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
+- printk("unable to get major %d for misc devices\n",
+- MISC_MAJOR);
+- class_destroy(misc_class);
+- return -EIO;
+- }
++ err = -EIO;
++ if (register_chrdev(MISC_MAJOR,"misc",&misc_fops))
++ goto fail_printk;
+ return 0;
++
++fail_printk:
++ printk("unable to get major %d for misc devices\n", MISC_MAJOR);
++ class_destroy(misc_class);
++fail_remove:
++ remove_proc_entry("misc", NULL);
++ return err;
+ }
+ subsys_initcall(misc_init);
+diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
+index e60a74c..d83db5d 100644
+--- a/drivers/char/mmtimer.c
++++ b/drivers/char/mmtimer.c
+@@ -74,9 +74,8 @@ static const struct file_operations mmtimer_fops = {
+ * We only have comparison registers RTC1-4 currently available per
+ * node. RTC0 is used by SAL.
+ */
+-#define NUM_COMPARATORS 3
+ /* Check for an RTC interrupt pending */
+-static int inline mmtimer_int_pending(int comparator)
++static int mmtimer_int_pending(int comparator)
+ {
+ if (HUB_L((unsigned long *)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED)) &
+ SH_EVENT_OCCURRED_RTC1_INT_MASK << comparator)
+@@ -84,15 +83,16 @@ static int inline mmtimer_int_pending(int comparator)
+ else
+ return 0;
+ }
++
+ /* Clear the RTC interrupt pending bit */
+-static void inline mmtimer_clr_int_pending(int comparator)
++static void mmtimer_clr_int_pending(int comparator)
+ {
+ HUB_S((u64 *)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS),
+ SH_EVENT_OCCURRED_RTC1_INT_MASK << comparator);
+ }
+
+ /* Setup timer on comparator RTC1 */
+-static void inline mmtimer_setup_int_0(u64 expires)
++static void mmtimer_setup_int_0(int cpu, u64 expires)
+ {
+ u64 val;
+
+@@ -106,7 +106,7 @@ static void inline mmtimer_setup_int_0(u64 expires)
+ mmtimer_clr_int_pending(0);
+
+ val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC1_INT_CONFIG_IDX_SHFT) |
+- ((u64)cpu_physical_id(smp_processor_id()) <<
++ ((u64)cpu_physical_id(cpu) <<
+ SH_RTC1_INT_CONFIG_PID_SHFT);
+
+ /* Set configuration */
+@@ -122,7 +122,7 @@ static void inline mmtimer_setup_int_0(u64 expires)
+ }
+
+ /* Setup timer on comparator RTC2 */
+-static void inline mmtimer_setup_int_1(u64 expires)
++static void mmtimer_setup_int_1(int cpu, u64 expires)
+ {
+ u64 val;
+
+@@ -133,7 +133,7 @@ static void inline mmtimer_setup_int_1(u64 expires)
+ mmtimer_clr_int_pending(1);
+
+ val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC2_INT_CONFIG_IDX_SHFT) |
+- ((u64)cpu_physical_id(smp_processor_id()) <<
++ ((u64)cpu_physical_id(cpu) <<
+ SH_RTC2_INT_CONFIG_PID_SHFT);
+
+ HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_CONFIG), val);
+@@ -144,7 +144,7 @@ static void inline mmtimer_setup_int_1(u64 expires)
+ }
+
+ /* Setup timer on comparator RTC3 */
+-static void inline mmtimer_setup_int_2(u64 expires)
++static void mmtimer_setup_int_2(int cpu, u64 expires)
+ {
+ u64 val;
+
+@@ -155,7 +155,7 @@ static void inline mmtimer_setup_int_2(u64 expires)
+ mmtimer_clr_int_pending(2);
+
+ val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC3_INT_CONFIG_IDX_SHFT) |
+- ((u64)cpu_physical_id(smp_processor_id()) <<
++ ((u64)cpu_physical_id(cpu) <<
+ SH_RTC3_INT_CONFIG_PID_SHFT);
+
+ HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_CONFIG), val);
+@@ -170,22 +170,22 @@ static void inline mmtimer_setup_int_2(u64 expires)
+ * in order to insure that the setup succeeds in a deterministic time frame.
+ * It will check if the interrupt setup succeeded.
+ */
+-static int inline mmtimer_setup(int comparator, unsigned long expires)
++static int mmtimer_setup(int cpu, int comparator, unsigned long expires)
+ {
+
+ switch (comparator) {
+ case 0:
+- mmtimer_setup_int_0(expires);
++ mmtimer_setup_int_0(cpu, expires);
+ break;
+ case 1:
+- mmtimer_setup_int_1(expires);
++ mmtimer_setup_int_1(cpu, expires);
+ break;
+ case 2:
+- mmtimer_setup_int_2(expires);
++ mmtimer_setup_int_2(cpu, expires);
+ break;
+ }
+ /* We might've missed our expiration time */
+- if (rtc_time() < expires)
++ if (rtc_time() <= expires)
+ return 1;
+
+ /*
+@@ -195,7 +195,7 @@ static int inline mmtimer_setup(int comparator, unsigned long expires)
+ return mmtimer_int_pending(comparator);
+ }
+
+-static int inline mmtimer_disable_int(long nasid, int comparator)
++static int mmtimer_disable_int(long nasid, int comparator)
+ {
+ switch (comparator) {
+ case 0:
+@@ -216,18 +216,124 @@ static int inline mmtimer_disable_int(long nasid, int comparator)
+ return 0;
+ }
+
+-#define TIMER_OFF 0xbadcabLL
++#define COMPARATOR 1 /* The comparator to use */
+
+-/* There is one of these for each comparator */
+-typedef struct mmtimer {
+- spinlock_t lock ____cacheline_aligned;
++#define TIMER_OFF 0xbadcabLL /* Timer is not setup */
++#define TIMER_SET 0 /* Comparator is set for this timer */
++
++/* There is one of these for each timer */
++struct mmtimer {
++ struct rb_node list;
+ struct k_itimer *timer;
+- int i;
+ int cpu;
++};
++
++struct mmtimer_node {
++ spinlock_t lock ____cacheline_aligned;
++ struct rb_root timer_head;
++ struct rb_node *next;
+ struct tasklet_struct tasklet;
+-} mmtimer_t;
++};
++static struct mmtimer_node *timers;
++
++
++/*
++ * Add a new mmtimer struct to the node's mmtimer list.
++ * This function assumes the struct mmtimer_node is locked.
++ */
++static void mmtimer_add_list(struct mmtimer *n)
++{
++ int nodeid = n->timer->it.mmtimer.node;
++ unsigned long expires = n->timer->it.mmtimer.expires;
++ struct rb_node **link = &timers[nodeid].timer_head.rb_node;
++ struct rb_node *parent = NULL;
++ struct mmtimer *x;
++
++ /*
++ * Find the right place in the rbtree:
++ */
++ while (*link) {
++ parent = *link;
++ x = rb_entry(parent, struct mmtimer, list);
++
++ if (expires < x->timer->it.mmtimer.expires)
++ link = &(*link)->rb_left;
++ else
++ link = &(*link)->rb_right;
++ }
++
++ /*
++ * Insert the timer to the rbtree and check whether it
++ * replaces the first pending timer
++ */
++ rb_link_node(&n->list, parent, link);
++ rb_insert_color(&n->list, &timers[nodeid].timer_head);
++
++ if (!timers[nodeid].next || expires < rb_entry(timers[nodeid].next,
++ struct mmtimer, list)->timer->it.mmtimer.expires)
++ timers[nodeid].next = &n->list;
++}
++
++/*
++ * Set the comparator for the next timer.
++ * This function assumes the struct mmtimer_node is locked.
++ */
++static void mmtimer_set_next_timer(int nodeid)
++{
++ struct mmtimer_node *n = &timers[nodeid];
++ struct mmtimer *x;
++ struct k_itimer *t;
++ int o;
++
++restart:
++ if (n->next == NULL)
++ return;
+
+-static mmtimer_t ** timers;
++ x = rb_entry(n->next, struct mmtimer, list);
++ t = x->timer;
++ if (!t->it.mmtimer.incr) {
++ /* Not an interval timer */
++ if (!mmtimer_setup(x->cpu, COMPARATOR,
++ t->it.mmtimer.expires)) {
++ /* Late setup, fire now */
++ tasklet_schedule(&n->tasklet);
++ }
++ return;
++ }
++
++ /* Interval timer */
++ o = 0;
++ while (!mmtimer_setup(x->cpu, COMPARATOR, t->it.mmtimer.expires)) {
++ unsigned long e, e1;
++ struct rb_node *next;
++ t->it.mmtimer.expires += t->it.mmtimer.incr << o;
++ t->it_overrun += 1 << o;
++ o++;
++ if (o > 20) {
++ printk(KERN_ALERT "mmtimer: cannot reschedule timer\n");
++ t->it.mmtimer.clock = TIMER_OFF;
++ n->next = rb_next(&x->list);
++ rb_erase(&x->list, &n->timer_head);
++ kfree(x);
++ goto restart;
++ }
++
++ e = t->it.mmtimer.expires;
++ next = rb_next(&x->list);
++
++ if (next == NULL)
++ continue;
++
++ e1 = rb_entry(next, struct mmtimer, list)->
++ timer->it.mmtimer.expires;
++ if (e > e1) {
++ n->next = next;
++ rb_erase(&x->list, &n->timer_head);
++ mmtimer_add_list(x);
++ goto restart;
++ }
++ }
++}
+
+ /**
+ * mmtimer_ioctl - ioctl interface for /dev/mmtimer
+@@ -390,35 +496,6 @@ static int sgi_clock_set(clockid_t clockid, struct timespec *tp)
+ return 0;
+ }
+
+-/*
+- * Schedule the next periodic interrupt. This function will attempt
+- * to schedule a periodic interrupt later if necessary. If the scheduling
+- * of an interrupt fails then the time to skip is lengthened
+- * exponentially in order to ensure that the next interrupt
+- * can be properly scheduled..
+- */
+-static int inline reschedule_periodic_timer(mmtimer_t *x)
+-{
+- int n;
+- struct k_itimer *t = x->timer;
+-
+- t->it.mmtimer.clock = x->i;
+- t->it_overrun--;
+-
+- n = 0;
+- do {
+-
+- t->it.mmtimer.expires += t->it.mmtimer.incr << n;
+- t->it_overrun += 1 << n;
+- n++;
+- if (n > 20)
+- return 1;
+-
+- } while (!mmtimer_setup(x->i, t->it.mmtimer.expires));
+-
+- return 0;
+-}
+-
+ /**
+ * mmtimer_interrupt - timer interrupt handler
+ * @irq: irq received
+@@ -435,71 +512,75 @@ static int inline reschedule_periodic_timer(mmtimer_t *x)
+ static irqreturn_t
+ mmtimer_interrupt(int irq, void *dev_id)
+ {
+- int i;
+ unsigned long expires = 0;
+ int result = IRQ_NONE;
+ unsigned indx = cpu_to_node(smp_processor_id());
++ struct mmtimer *base;
+
+- /*
+- * Do this once for each comparison register
+- */
+- for (i = 0; i < NUM_COMPARATORS; i++) {
+- mmtimer_t *base = timers[indx] + i;
+- /* Make sure this doesn't get reused before tasklet_sched */
+- spin_lock(&base->lock);
+- if (base->cpu == smp_processor_id()) {
+- if (base->timer)
+- expires = base->timer->it.mmtimer.expires;
+- /* expires test won't work with shared irqs */
+- if ((mmtimer_int_pending(i) > 0) ||
+- (expires && (expires < rtc_time()))) {
+- mmtimer_clr_int_pending(i);
+- tasklet_schedule(&base->tasklet);
+- result = IRQ_HANDLED;
+- }
++ spin_lock(&timers[indx].lock);
++ base = rb_entry(timers[indx].next, struct mmtimer, list);
++ if (base == NULL) {
++ spin_unlock(&timers[indx].lock);
++ return result;
++ }
++
++ if (base->cpu == smp_processor_id()) {
++ if (base->timer)
++ expires = base->timer->it.mmtimer.expires;
++ /* expires test won't work with shared irqs */
++ if ((mmtimer_int_pending(COMPARATOR) > 0) ||
++ (expires && (expires <= rtc_time()))) {
++ mmtimer_clr_int_pending(COMPARATOR);
++ tasklet_schedule(&timers[indx].tasklet);
++ result = IRQ_HANDLED;
+ }
+- spin_unlock(&base->lock);
+- expires = 0;
+ }
++ spin_unlock(&timers[indx].lock);
+ return result;
+ }
+
+-void mmtimer_tasklet(unsigned long data) {
+- mmtimer_t *x = (mmtimer_t *)data;
+- struct k_itimer *t = x->timer;
++static void mmtimer_tasklet(unsigned long data)
++{
++ int nodeid = data;
++ struct mmtimer_node *mn = &timers[nodeid];
++ struct mmtimer *x = rb_entry(mn->next, struct mmtimer, list);
++ struct k_itimer *t;
+ unsigned long flags;
+
+- if (t == NULL)
+- return;
+-
+ /* Send signal and deal with periodic signals */
+- spin_lock_irqsave(&t->it_lock, flags);
+- spin_lock(&x->lock);
+- /* If timer was deleted between interrupt and here, leave */
+- if (t != x->timer)
++ spin_lock_irqsave(&mn->lock, flags);
++ if (!mn->next)
+ goto out;
+- t->it_overrun = 0;
+
+- if (posix_timer_event(t, 0) != 0) {
++ x = rb_entry(mn->next, struct mmtimer, list);
++ t = x->timer;
++
++ if (t->it.mmtimer.clock == TIMER_OFF)
++ goto out;
++
++ t->it_overrun = 0;
+
+- // printk(KERN_WARNING "mmtimer: cannot deliver signal.\n");
++ mn->next = rb_next(&x->list);
++ rb_erase(&x->list, &mn->timer_head);
+
++ if (posix_timer_event(t, 0) != 0)
+ t->it_overrun++;
+- }
++
+ if(t->it.mmtimer.incr) {
+- /* Periodic timer */
+- if (reschedule_periodic_timer(x)) {
+- printk(KERN_WARNING "mmtimer: unable to reschedule\n");
+- x->timer = NULL;
+- }
++ t->it.mmtimer.expires += t->it.mmtimer.incr;
++ mmtimer_add_list(x);
+ } else {
+ /* Ensure we don't false trigger in mmtimer_interrupt */
++ t->it.mmtimer.clock = TIMER_OFF;
+ t->it.mmtimer.expires = 0;
++ kfree(x);
+ }
++ /* Set comparator for next timer, if there is one */
++ mmtimer_set_next_timer(nodeid);
++
+ t->it_overrun_last = t->it_overrun;
+ out:
+- spin_unlock(&x->lock);
+- spin_unlock_irqrestore(&t->it_lock, flags);
++ spin_unlock_irqrestore(&mn->lock, flags);
+ }
+
+ static int sgi_timer_create(struct k_itimer *timer)
+@@ -516,19 +597,50 @@ static int sgi_timer_create(struct k_itimer *timer)
+ */
+ static int sgi_timer_del(struct k_itimer *timr)
+ {
+- int i = timr->it.mmtimer.clock;
+ cnodeid_t nodeid = timr->it.mmtimer.node;
+- mmtimer_t *t = timers[nodeid] + i;
+ unsigned long irqflags;
+
+- if (i != TIMER_OFF) {
+- spin_lock_irqsave(&t->lock, irqflags);
+- mmtimer_disable_int(cnodeid_to_nasid(nodeid),i);
+- t->timer = NULL;
++ spin_lock_irqsave(&timers[nodeid].lock, irqflags);
++ if (timr->it.mmtimer.clock != TIMER_OFF) {
++ unsigned long expires = timr->it.mmtimer.expires;
++ struct rb_node *n = timers[nodeid].timer_head.rb_node;
++ struct mmtimer *uninitialized_var(t);
++ int r = 0;
++
+ timr->it.mmtimer.clock = TIMER_OFF;
+ timr->it.mmtimer.expires = 0;
+- spin_unlock_irqrestore(&t->lock, irqflags);
++
++ while (n) {
++ t = rb_entry(n, struct mmtimer, list);
++ if (t->timer == timr)
++ break;
++
++ if (expires < t->timer->it.mmtimer.expires)
++ n = n->rb_left;
++ else
++ n = n->rb_right;
++ }
++
++ if (!n) {
++ spin_unlock_irqrestore(&timers[nodeid].lock, irqflags);
++ return 0;
++ }
++
++ if (timers[nodeid].next == n) {
++ timers[nodeid].next = rb_next(n);
++ r = 1;
++ }
++
++ rb_erase(n, &timers[nodeid].timer_head);
++ kfree(t);
++
++ if (r) {
++ mmtimer_disable_int(cnodeid_to_nasid(nodeid),
++ COMPARATOR);
++ mmtimer_set_next_timer(nodeid);
++ }
+ }
++ spin_unlock_irqrestore(&timers[nodeid].lock, irqflags);
+ return 0;
+ }
+
+@@ -557,12 +669,11 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
+ struct itimerspec * new_setting,
+ struct itimerspec * old_setting)
+ {
+-
+- int i;
+ unsigned long when, period, irqflags;
+ int err = 0;
+ cnodeid_t nodeid;
+- mmtimer_t *base;
++ struct mmtimer *base;
++ struct rb_node *n;
+
+ if (old_setting)
+ sgi_timer_get(timr, old_setting);
+@@ -575,6 +686,10 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
+ /* Clear timer */
+ return 0;
+
++ base = kmalloc(sizeof(struct mmtimer), GFP_KERNEL);
++ if (base == NULL)
++ return -ENOMEM;
++
+ if (flags & TIMER_ABSTIME) {
+ struct timespec n;
+ unsigned long now;
+@@ -604,47 +719,38 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
+ preempt_disable();
+
+ nodeid = cpu_to_node(smp_processor_id());
+-retry:
+- /* Don't use an allocated timer, or a deleted one that's pending */
+- for(i = 0; i< NUM_COMPARATORS; i++) {
+- base = timers[nodeid] + i;
+- if (!base->timer && !base->tasklet.state) {
+- break;
+- }
+- }
+-
+- if (i == NUM_COMPARATORS) {
+- preempt_enable();
+- return -EBUSY;
+- }
+
+- spin_lock_irqsave(&base->lock, irqflags);
++ /* Lock the node timer structure */
++ spin_lock_irqsave(&timers[nodeid].lock, irqflags);
+
+- if (base->timer || base->tasklet.state != 0) {
+- spin_unlock_irqrestore(&base->lock, irqflags);
+- goto retry;
+- }
+ base->timer = timr;
+ base->cpu = smp_processor_id();
+
+- timr->it.mmtimer.clock = i;
++ timr->it.mmtimer.clock = TIMER_SET;
+ timr->it.mmtimer.node = nodeid;
+ timr->it.mmtimer.incr = period;
+ timr->it.mmtimer.expires = when;
+
+- if (period == 0) {
+- if (!mmtimer_setup(i, when)) {
+- mmtimer_disable_int(-1, i);
+- posix_timer_event(timr, 0);
+- timr->it.mmtimer.expires = 0;
+- }
+- } else {
+- timr->it.mmtimer.expires -= period;
+- if (reschedule_periodic_timer(base))
+- err = -EINVAL;
++ n = timers[nodeid].next;
++
++ /* Add the new struct mmtimer to node's timer list */
++ mmtimer_add_list(base);
++
++ if (timers[nodeid].next == n) {
++ /* No need to reprogram comparator for now */
++ spin_unlock_irqrestore(&timers[nodeid].lock, irqflags);
++ preempt_enable();
++ return err;
+ }
+
+- spin_unlock_irqrestore(&base->lock, irqflags);
++ /* We need to reprogram the comparator */
++ if (n)
++ mmtimer_disable_int(cnodeid_to_nasid(nodeid), COMPARATOR);
++
++ mmtimer_set_next_timer(nodeid);
++
++ /* Unlock the node timer structure */
++ spin_unlock_irqrestore(&timers[nodeid].lock, irqflags);
+
+ preempt_enable();
+
+@@ -669,7 +775,6 @@ static struct k_clock sgi_clock = {
+ */
+ static int __init mmtimer_init(void)
+ {
+- unsigned i;
+ cnodeid_t node, maxn = -1;
+
+ if (!ia64_platform_is("sn2"))
+@@ -706,31 +811,18 @@ static int __init mmtimer_init(void)
+ maxn++;
+
+ /* Allocate list of node ptrs to mmtimer_t's */
+- timers = kzalloc(sizeof(mmtimer_t *)*maxn, GFP_KERNEL);
++ timers = kzalloc(sizeof(struct mmtimer_node)*maxn, GFP_KERNEL);
+ if (timers == NULL) {
+ printk(KERN_ERR "%s: failed to allocate memory for device\n",
+ MMTIMER_NAME);
+ goto out3;
+ }
+
+- /* Allocate mmtimer_t's for each online node */
++ /* Initialize struct mmtimer's for each online node */
+ for_each_online_node(node) {
+- timers[node] = kmalloc_node(sizeof(mmtimer_t)*NUM_COMPARATORS, GFP_KERNEL, node);
+- if (timers[node] == NULL) {
+- printk(KERN_ERR "%s: failed to allocate memory for device\n",
+- MMTIMER_NAME);
+- goto out4;
+- }
+- for (i=0; i< NUM_COMPARATORS; i++) {
+- mmtimer_t * base = timers[node] + i;
+-
+- spin_lock_init(&base->lock);
+- base->timer = NULL;
+- base->cpu = 0;
+- base->i = i;
+- tasklet_init(&base->tasklet, mmtimer_tasklet,
+- (unsigned long) (base));
+- }
++ spin_lock_init(&timers[node].lock);
++ tasklet_init(&timers[node].tasklet, mmtimer_tasklet,
++ (unsigned long) node);
+ }
+
+ sgi_clock_period = sgi_clock.res = NSEC_PER_SEC / sn_rtc_cycles_per_second;
+@@ -741,11 +833,8 @@ static int __init mmtimer_init(void)
+
+ return 0;
+
+-out4:
+- for_each_online_node(node) {
+- kfree(timers[node]);
+- }
+ out3:
++ kfree(timers);
+ misc_deregister(&mmtimer_miscdev);
+ out2:
+ free_irq(SGI_MMTIMER_VECTOR, NULL);
+@@ -754,4 +843,3 @@ out1:
+ }
+
+ module_init(mmtimer_init);
+-
+diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
+index 64b7b2b..d57d3a6 100644
+--- a/drivers/char/moxa.c
++++ b/drivers/char/moxa.c
+@@ -2,7 +2,8 @@
+ /*
+ * moxa.c -- MOXA Intellio family multiport serial driver.
+ *
+- * Copyright (C) 1999-2000 Moxa Technologies (support at moxa.com.tw).
++ * Copyright (C) 1999-2000 Moxa Technologies (support at moxa.com).
++ * Copyright (c) 2007 Jiri Slaby <jirislaby at gmail.com>
+ *
+ * This code is loosely based on the Linux serial driver, written by
+ * Linus Torvalds, Theodore T'so and others.
+@@ -25,6 +26,7 @@
+ #include <linux/mm.h>
+ #include <linux/ioport.h>
+ #include <linux/errno.h>
++#include <linux/firmware.h>
+ #include <linux/signal.h>
+ #include <linux/sched.h>
+ #include <linux/timer.h>
+@@ -41,21 +43,26 @@
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <linux/bitops.h>
+-#include <linux/completion.h>
+
+ #include <asm/system.h>
+ #include <asm/io.h>
+ #include <asm/uaccess.h>
+
+-#define MOXA_VERSION "5.1k"
++#include "moxa.h"
++
++#define MOXA_VERSION "6.0k"
++
++#define MOXA_FW_HDRLEN 32
+
+ #define MOXAMAJOR 172
+-#define MOXACUMAJOR 173
+
+ #define MAX_BOARDS 4 /* Don't change this value */
+ #define MAX_PORTS_PER_BOARD 32 /* Don't change this value */
+ #define MAX_PORTS (MAX_BOARDS * MAX_PORTS_PER_BOARD)
+
++#define MOXA_IS_320(brd) ((brd)->boardType == MOXA_BOARD_C320_ISA || \
++ (brd)->boardType == MOXA_BOARD_C320_PCI)
++
+ /*
+ * Define the Moxa PCI vendor and device IDs.
+ */
+@@ -92,24 +99,16 @@ static struct pci_device_id moxa_pcibrds[] = {
+ MODULE_DEVICE_TABLE(pci, moxa_pcibrds);
+ #endif /* CONFIG_PCI */
+
+-struct moxa_isa_board_conf {
+- int boardType;
+- int numPorts;
+- unsigned long baseAddr;
+-};
+-
+-static struct moxa_isa_board_conf moxa_isa_boards[] =
+-{
+-/* {MOXA_BOARD_C218_ISA,8,0xDC000}, */
+-};
++struct moxa_port;
+
+ static struct moxa_board_conf {
+ int boardType;
+ int numPorts;
+- unsigned long baseAddr;
+ int busType;
+
+- int loadstat;
++ unsigned int ready;
++
++ struct moxa_port *ports;
+
+ void __iomem *basemem;
+ void __iomem *intNdx;
+@@ -131,30 +130,27 @@ struct moxaq_str {
+ };
+
+ struct moxa_port {
++ struct moxa_board_conf *board;
++ struct tty_struct *tty;
++ void __iomem *tableAddr;
++
+ int type;
+- int port;
+ int close_delay;
+- unsigned short closing_wait;
+- int count;
+- int blocked_open;
+- long event; /* long req'd for set_bit --RR */
++ unsigned int count;
+ int asyncflags;
+- unsigned long statusflags;
+- struct tty_struct *tty;
+ int cflag;
++ unsigned long statusflags;
+ wait_queue_head_t open_wait;
+- struct completion close_wait;
+-
+- struct timer_list emptyTimer;
+
+- char chkPort;
+- char lineCtrl;
+- void __iomem *tableAddr;
+- long curBaud;
+- char DCDState;
+- char lowChkFlag;
++ u8 DCDState;
++ u8 lineCtrl;
++ u8 lowChkFlag;
++};
+
+- ushort breakCnt;
++struct mon_str {
++ int tick;
++ int rxcnt[MAX_PORTS];
++ int txcnt[MAX_PORTS];
+ };
+
+ /* statusflags */
+@@ -168,20 +164,27 @@ struct moxa_port {
+ #define WAKEUP_CHARS 256
+
+ static int ttymajor = MOXAMAJOR;
++static struct mon_str moxaLog;
++static unsigned int moxaFuncTout = HZ / 2;
++static unsigned int moxaLowWaterChk;
++static DEFINE_MUTEX(moxa_openlock);
+ /* Variables for insmod */
+ #ifdef MODULE
+-static int baseaddr[4];
+-static int type[4];
+-static int numports[4];
++static unsigned long baseaddr[MAX_BOARDS];
++static unsigned int type[MAX_BOARDS];
++static unsigned int numports[MAX_BOARDS];
+ #endif
+
+ MODULE_AUTHOR("William Chen");
+ MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");
+ MODULE_LICENSE("GPL");
+ #ifdef MODULE
+-module_param_array(type, int, NULL, 0);
+-module_param_array(baseaddr, int, NULL, 0);
+-module_param_array(numports, int, NULL, 0);
++module_param_array(type, uint, NULL, 0);
++MODULE_PARM_DESC(type, "card type: C218=2, C320=4");
++module_param_array(baseaddr, ulong, NULL, 0);
++MODULE_PARM_DESC(baseaddr, "base address");
++module_param_array(numports, uint, NULL, 0);
++MODULE_PARM_DESC(numports, "numports (ignored for C218)");
+ #endif
+ module_param(ttymajor, int, 0);
+
+@@ -194,9 +197,6 @@ static int moxa_write(struct tty_struct *, const unsigned char *, int);
+ static int moxa_write_room(struct tty_struct *);
+ static void moxa_flush_buffer(struct tty_struct *);
+ static int moxa_chars_in_buffer(struct tty_struct *);
+-static void moxa_flush_chars(struct tty_struct *);
+-static void moxa_put_char(struct tty_struct *, unsigned char);
+-static int moxa_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long);
+ static void moxa_throttle(struct tty_struct *);
+ static void moxa_unthrottle(struct tty_struct *);
+ static void moxa_set_termios(struct tty_struct *, struct ktermios *);
+@@ -208,44 +208,183 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
+ static void moxa_poll(unsigned long);
+ static void moxa_set_tty_param(struct tty_struct *, struct ktermios *);
+-static int moxa_block_till_ready(struct tty_struct *, struct file *,
+- struct moxa_port *);
+ static void moxa_setup_empty_event(struct tty_struct *);
+-static void moxa_check_xmit_empty(unsigned long);
+ static void moxa_shut_down(struct moxa_port *);
+-static void moxa_receive_data(struct moxa_port *);
+ /*
+ * moxa board interface functions:
+ */
+-static void MoxaDriverInit(void);
+-static int MoxaDriverIoctl(unsigned int, unsigned long, int);
+-static int MoxaDriverPoll(void);
+-static int MoxaPortsOfCard(int);
+-static int MoxaPortIsValid(int);
+-static void MoxaPortEnable(int);
+-static void MoxaPortDisable(int);
+-static long MoxaPortGetMaxBaud(int);
+-static long MoxaPortSetBaud(int, long);
+-static int MoxaPortSetTermio(int, struct ktermios *, speed_t);
+-static int MoxaPortGetLineOut(int, int *, int *);
+-static void MoxaPortLineCtrl(int, int, int);
+-static void MoxaPortFlowCtrl(int, int, int, int, int, int);
+-static int MoxaPortLineStatus(int);
+-static int MoxaPortDCDChange(int);
+-static int MoxaPortDCDON(int);
+-static void MoxaPortFlushData(int, int);
+-static int MoxaPortWriteData(int, unsigned char *, int);
+-static int MoxaPortReadData(int, struct tty_struct *tty);
+-static int MoxaPortTxQueue(int);
+-static int MoxaPortRxQueue(int);
+-static int MoxaPortTxFree(int);
+-static void MoxaPortTxDisable(int);
+-static void MoxaPortTxEnable(int);
+-static int MoxaPortResetBrkCnt(int);
+-static void MoxaPortSendBreak(int, int);
++static void MoxaPortEnable(struct moxa_port *);
++static void MoxaPortDisable(struct moxa_port *);
++static int MoxaPortSetTermio(struct moxa_port *, struct ktermios *, speed_t);
++static int MoxaPortGetLineOut(struct moxa_port *, int *, int *);
++static void MoxaPortLineCtrl(struct moxa_port *, int, int);
++static void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int);
++static int MoxaPortLineStatus(struct moxa_port *);
++static void MoxaPortFlushData(struct moxa_port *, int);
++static int MoxaPortWriteData(struct moxa_port *, const unsigned char *, int);
++static int MoxaPortReadData(struct moxa_port *);
++static int MoxaPortTxQueue(struct moxa_port *);
++static int MoxaPortRxQueue(struct moxa_port *);
++static int MoxaPortTxFree(struct moxa_port *);
++static void MoxaPortTxDisable(struct moxa_port *);
++static void MoxaPortTxEnable(struct moxa_port *);
+ static int moxa_get_serial_info(struct moxa_port *, struct serial_struct __user *);
+ static int moxa_set_serial_info(struct moxa_port *, struct serial_struct __user *);
+-static void MoxaSetFifo(int port, int enable);
++static void MoxaSetFifo(struct moxa_port *port, int enable);
++
++/*
++ * I/O functions
++ */
++
++static void moxa_wait_finish(void __iomem *ofsAddr)
++{
++ unsigned long end = jiffies + moxaFuncTout;
++
++ while (readw(ofsAddr + FuncCode) != 0)
++ if (time_after(jiffies, end))
++ return;
++ if (readw(ofsAddr + FuncCode) != 0 && printk_ratelimit())
++ printk(KERN_WARNING "moxa function expired\n");
++}
++
++static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg)
++{
++ writew(arg, ofsAddr + FuncArg);
++ writew(cmd, ofsAddr + FuncCode);
++ moxa_wait_finish(ofsAddr);
++}
++
++static void moxa_low_water_check(void __iomem *ofsAddr)
++{
++ u16 rptr, wptr, mask, len;
++
++ if (readb(ofsAddr + FlagStat) & Xoff_state) {
++ rptr = readw(ofsAddr + RXrptr);
++ wptr = readw(ofsAddr + RXwptr);
++ mask = readw(ofsAddr + RX_mask);
++ len = (wptr - rptr) & mask;
++ if (len <= Low_water)
++ moxafunc(ofsAddr, FC_SendXon, 0);
++ }
++}
++
++/*
++ * TTY operations
++ */
++
++static int moxa_ioctl(struct tty_struct *tty, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ struct moxa_port *ch = tty->driver_data;
++ void __user *argp = (void __user *)arg;
++ int status, ret = 0;
++
++ if (tty->index == MAX_PORTS) {
++ if (cmd != MOXA_GETDATACOUNT && cmd != MOXA_GET_IOQUEUE &&
++ cmd != MOXA_GETMSTATUS)
++ return -EINVAL;
++ } else if (!ch)
++ return -ENODEV;
++
++ switch (cmd) {
++ case MOXA_GETDATACOUNT:
++ moxaLog.tick = jiffies;
++ if (copy_to_user(argp, &moxaLog, sizeof(moxaLog)))
++ ret = -EFAULT;
++ break;
++ case MOXA_FLUSH_QUEUE:
++ MoxaPortFlushData(ch, arg);
++ break;
++ case MOXA_GET_IOQUEUE: {
++ struct moxaq_str __user *argm = argp;
++ struct moxaq_str tmp;
++ struct moxa_port *p;
++ unsigned int i, j;
++
++ mutex_lock(&moxa_openlock);
++ for (i = 0; i < MAX_BOARDS; i++) {
++ p = moxa_boards[i].ports;
++ for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
++ memset(&tmp, 0, sizeof(tmp));
++ if (moxa_boards[i].ready) {
++ tmp.inq = MoxaPortRxQueue(p);
++ tmp.outq = MoxaPortTxQueue(p);
++ }
++ if (copy_to_user(argm, &tmp, sizeof(tmp))) {
++ mutex_unlock(&moxa_openlock);
++ return -EFAULT;
++ }
++ }
++ }
++ mutex_unlock(&moxa_openlock);
++ break;
++ } case MOXA_GET_OQUEUE:
++ status = MoxaPortTxQueue(ch);
++ ret = put_user(status, (unsigned long __user *)argp);
++ break;
++ case MOXA_GET_IQUEUE:
++ status = MoxaPortRxQueue(ch);
++ ret = put_user(status, (unsigned long __user *)argp);
++ break;
++ case MOXA_GETMSTATUS: {
++ struct mxser_mstatus __user *argm = argp;
++ struct mxser_mstatus tmp;
++ struct moxa_port *p;
++ unsigned int i, j;
++
++ mutex_lock(&moxa_openlock);
++ for (i = 0; i < MAX_BOARDS; i++) {
++ p = moxa_boards[i].ports;
++ for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
++ memset(&tmp, 0, sizeof(tmp));
++ if (!moxa_boards[i].ready)
++ goto copy;
++
++ status = MoxaPortLineStatus(p);
++ if (status & 1)
++ tmp.cts = 1;
++ if (status & 2)
++ tmp.dsr = 1;
++ if (status & 4)
++ tmp.dcd = 1;
++
++ if (!p->tty || !p->tty->termios)
++ tmp.cflag = p->cflag;
++ else
++ tmp.cflag = p->tty->termios->c_cflag;
++copy:
++ if (copy_to_user(argm, &tmp, sizeof(tmp))) {
++ mutex_unlock(&moxa_openlock);
++ return -EFAULT;
++ }
++ }
++ }
++ mutex_unlock(&moxa_openlock);
++ break;
++ }
++ case TIOCGSERIAL:
++ mutex_lock(&moxa_openlock);
++ ret = moxa_get_serial_info(ch, argp);
++ mutex_unlock(&moxa_openlock);
++ break;
++ case TIOCSSERIAL:
++ mutex_lock(&moxa_openlock);
++ ret = moxa_set_serial_info(ch, argp);
++ mutex_unlock(&moxa_openlock);
++ break;
++ default:
++ ret = -ENOIOCTLCMD;
++ }
++ return ret;
++}
++
++static void moxa_break_ctl(struct tty_struct *tty, int state)
++{
++ struct moxa_port *port = tty->driver_data;
++
++ moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak,
++ Magic_code);
++}
+
+ static const struct tty_operations moxa_ops = {
+ .open = moxa_open,
+@@ -254,8 +393,6 @@ static const struct tty_operations moxa_ops = {
+ .write_room = moxa_write_room,
+ .flush_buffer = moxa_flush_buffer,
+ .chars_in_buffer = moxa_chars_in_buffer,
+- .flush_chars = moxa_flush_chars,
+- .put_char = moxa_put_char,
+ .ioctl = moxa_ioctl,
+ .throttle = moxa_throttle,
+ .unthrottle = moxa_unthrottle,
+@@ -263,15 +400,509 @@ static const struct tty_operations moxa_ops = {
+ .stop = moxa_stop,
+ .start = moxa_start,
+ .hangup = moxa_hangup,
++ .break_ctl = moxa_break_ctl,
+ .tiocmget = moxa_tiocmget,
+ .tiocmset = moxa_tiocmset,
+ };
+
+ static struct tty_driver *moxaDriver;
+-static struct moxa_port moxa_ports[MAX_PORTS];
+ static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0);
+ static DEFINE_SPINLOCK(moxa_lock);
+
++/*
++ * HW init
++ */
++
++static int moxa_check_fw_model(struct moxa_board_conf *brd, u8 model)
++{
++ switch (brd->boardType) {
++ case MOXA_BOARD_C218_ISA:
++ case MOXA_BOARD_C218_PCI:
++ if (model != 1)
++ goto err;
++ break;
++ case MOXA_BOARD_CP204J:
++ if (model != 3)
++ goto err;
++ break;
++ default:
++ if (model != 2)
++ goto err;
++ break;
++ }
++ return 0;
++err:
++ return -EINVAL;
++}
++
++static int moxa_check_fw(const void *ptr)
++{
++ const __le16 *lptr = ptr;
++
++ if (*lptr != cpu_to_le16(0x7980))
++ return -EINVAL;
++
++ return 0;
++}
++
++static int moxa_load_bios(struct moxa_board_conf *brd, const u8 *buf,
++ size_t len)
++{
++ void __iomem *baseAddr = brd->basemem;
++ u16 tmp;
++
++ writeb(HW_reset, baseAddr + Control_reg); /* reset */
++ msleep(10);
++ memset_io(baseAddr, 0, 4096);
++ memcpy_toio(baseAddr, buf, len); /* download BIOS */
++ writeb(0, baseAddr + Control_reg); /* restart */
++
++ msleep(2000);
++
++ switch (brd->boardType) {
++ case MOXA_BOARD_C218_ISA:
++ case MOXA_BOARD_C218_PCI:
++ tmp = readw(baseAddr + C218_key);
++ if (tmp != C218_KeyCode)
++ goto err;
++ break;
++ case MOXA_BOARD_CP204J:
++ tmp = readw(baseAddr + C218_key);
++ if (tmp != CP204J_KeyCode)
++ goto err;
++ break;
++ default:
++ tmp = readw(baseAddr + C320_key);
++ if (tmp != C320_KeyCode)
++ goto err;
++ tmp = readw(baseAddr + C320_status);
++ if (tmp != STS_init) {
++ printk(KERN_ERR "MOXA: bios upload failed -- CPU/Basic "
++ "module not found\n");
++ return -EIO;
++ }
++ break;
++ }
++
++ return 0;
++err:
++ printk(KERN_ERR "MOXA: bios upload failed -- board not found\n");
++ return -EIO;
++}
++
++static int moxa_load_320b(struct moxa_board_conf *brd, const u8 *ptr,
++ size_t len)
++{
++ void __iomem *baseAddr = brd->basemem;
++
++ if (len < 7168) {
++ printk(KERN_ERR "MOXA: invalid 320 bios -- too short\n");
++ return -EINVAL;
++ }
++
++ writew(len - 7168 - 2, baseAddr + C320bapi_len);
++ writeb(1, baseAddr + Control_reg); /* Select Page 1 */
++ memcpy_toio(baseAddr + DynPage_addr, ptr, 7168);
++ writeb(2, baseAddr + Control_reg); /* Select Page 2 */
++ memcpy_toio(baseAddr + DynPage_addr, ptr + 7168, len - 7168);
++
++ return 0;
++}
++
++static int moxa_real_load_code(struct moxa_board_conf *brd, const void *ptr,
++ size_t len)
++{
++ void __iomem *baseAddr = brd->basemem;
++ const u16 *uptr = ptr;
++ size_t wlen, len2, j;
++ unsigned long key, loadbuf, loadlen, checksum, checksum_ok;
++ unsigned int i, retry;
++ u16 usum, keycode;
++
++ keycode = (brd->boardType == MOXA_BOARD_CP204J) ? CP204J_KeyCode :
++ C218_KeyCode;
++
++ switch (brd->boardType) {
++ case MOXA_BOARD_CP204J:
++ case MOXA_BOARD_C218_ISA:
++ case MOXA_BOARD_C218_PCI:
++ key = C218_key;
++ loadbuf = C218_LoadBuf;
++ loadlen = C218DLoad_len;
++ checksum = C218check_sum;
++ checksum_ok = C218chksum_ok;
++ break;
++ default:
++ key = C320_key;
++ keycode = C320_KeyCode;
++ loadbuf = C320_LoadBuf;
++ loadlen = C320DLoad_len;
++ checksum = C320check_sum;
++ checksum_ok = C320chksum_ok;
++ break;
++ }
++
++ usum = 0;
++ wlen = len >> 1;
++ for (i = 0; i < wlen; i++)
++ usum += le16_to_cpu(uptr[i]);
++ retry = 0;
++ do {
++ wlen = len >> 1;
++ j = 0;
++ while (wlen) {
++ len2 = (wlen > 2048) ? 2048 : wlen;
++ wlen -= len2;
++ memcpy_toio(baseAddr + loadbuf, ptr + j, len2 << 1);
++ j += len2 << 1;
++
++ writew(len2, baseAddr + loadlen);
++ writew(0, baseAddr + key);
++ for (i = 0; i < 100; i++) {
++ if (readw(baseAddr + key) == keycode)
++ break;
++ msleep(10);
++ }
++ if (readw(baseAddr + key) != keycode)
++ return -EIO;
++ }
++ writew(0, baseAddr + loadlen);
++ writew(usum, baseAddr + checksum);
++ writew(0, baseAddr + key);
++ for (i = 0; i < 100; i++) {
++ if (readw(baseAddr + key) == keycode)
++ break;
++ msleep(10);
++ }
++ retry++;
++ } while ((readb(baseAddr + checksum_ok) != 1) && (retry < 3));
++ if (readb(baseAddr + checksum_ok) != 1)
++ return -EIO;
++
++ writew(0, baseAddr + key);
++ for (i = 0; i < 600; i++) {
++ if (readw(baseAddr + Magic_no) == Magic_code)
++ break;
++ msleep(10);
++ }
++ if (readw(baseAddr + Magic_no) != Magic_code)
++ return -EIO;
++
++ if (MOXA_IS_320(brd)) {
++ if (brd->busType == MOXA_BUS_TYPE_PCI) { /* ASIC board */
++ writew(0x3800, baseAddr + TMS320_PORT1);
++ writew(0x3900, baseAddr + TMS320_PORT2);
++ writew(28499, baseAddr + TMS320_CLOCK);
++ } else {
++ writew(0x3200, baseAddr + TMS320_PORT1);
++ writew(0x3400, baseAddr + TMS320_PORT2);
++ writew(19999, baseAddr + TMS320_CLOCK);
++ }
++ }
++ writew(1, baseAddr + Disable_IRQ);
++ writew(0, baseAddr + Magic_no);
++ for (i = 0; i < 500; i++) {
++ if (readw(baseAddr + Magic_no) == Magic_code)
++ break;
++ msleep(10);
++ }
++ if (readw(baseAddr + Magic_no) != Magic_code)
++ return -EIO;
++
++ if (MOXA_IS_320(brd)) {
++ j = readw(baseAddr + Module_cnt);
++ if (j <= 0)
++ return -EIO;
++ brd->numPorts = j * 8;
++ writew(j, baseAddr + Module_no);
++ writew(0, baseAddr + Magic_no);
++ for (i = 0; i < 600; i++) {
++ if (readw(baseAddr + Magic_no) == Magic_code)
++ break;
++ msleep(10);
++ }
++ if (readw(baseAddr + Magic_no) != Magic_code)
++ return -EIO;
++ }
++ brd->intNdx = baseAddr + IRQindex;
++ brd->intPend = baseAddr + IRQpending;
++ brd->intTable = baseAddr + IRQtable;
++
++ return 0;
++}
++
++static int moxa_load_code(struct moxa_board_conf *brd, const void *ptr,
++ size_t len)
++{
++ void __iomem *ofsAddr, *baseAddr = brd->basemem;
++ struct moxa_port *port;
++ int retval, i;
++
++ if (len % 2) {
++ printk(KERN_ERR "MOXA: bios length is not even\n");
++ return -EINVAL;
++ }
++
++ retval = moxa_real_load_code(brd, ptr, len); /* may change numPorts */
++ if (retval)
++ return retval;
++
++ switch (brd->boardType) {
++ case MOXA_BOARD_C218_ISA:
++ case MOXA_BOARD_C218_PCI:
++ case MOXA_BOARD_CP204J:
++ port = brd->ports;
++ for (i = 0; i < brd->numPorts; i++, port++) {
++ port->board = brd;
++ port->DCDState = 0;
++ port->tableAddr = baseAddr + Extern_table +
++ Extern_size * i;
++ ofsAddr = port->tableAddr;
++ writew(C218rx_mask, ofsAddr + RX_mask);
++ writew(C218tx_mask, ofsAddr + TX_mask);
++ writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb);
++ writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb);
++
++ writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb);
++ writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb);
++
++ }
++ break;
++ default:
++ port = brd->ports;
++ for (i = 0; i < brd->numPorts; i++, port++) {
++ port->board = brd;
++ port->DCDState = 0;
++ port->tableAddr = baseAddr + Extern_table +
++ Extern_size * i;
++ ofsAddr = port->tableAddr;
++ switch (brd->numPorts) {
++ case 8:
++ writew(C320p8rx_mask, ofsAddr + RX_mask);
++ writew(C320p8tx_mask, ofsAddr + TX_mask);
++ writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb);
++ writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb);
++ writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb);
++ writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb);
++
++ break;
++ case 16:
++ writew(C320p16rx_mask, ofsAddr + RX_mask);
++ writew(C320p16tx_mask, ofsAddr + TX_mask);
++ writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb);
++ writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb);
++ writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb);
++ writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb);
++ break;
++
++ case 24:
++ writew(C320p24rx_mask, ofsAddr + RX_mask);
++ writew(C320p24tx_mask, ofsAddr + TX_mask);
++ writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb);
++ writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb);
++ writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb);
++ writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
++ break;
++ case 32:
++ writew(C320p32rx_mask, ofsAddr + RX_mask);
++ writew(C320p32tx_mask, ofsAddr + TX_mask);
++ writew(C320p32tx_ofs, ofsAddr + Ofs_txb);
++ writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb);
++ writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb);
++ writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb);
++ writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
++ break;
++ }
++ }
++ break;
++ }
++ return 0;
++}
++
++static int moxa_load_fw(struct moxa_board_conf *brd, const struct firmware *fw)
++{
++ void *ptr = fw->data;
++ char rsn[64];
++ u16 lens[5];
++ size_t len;
++ unsigned int a, lenp, lencnt;
++ int ret = -EINVAL;
++ struct {
++ __le32 magic; /* 0x34303430 */
++ u8 reserved1[2];
++ u8 type; /* UNIX = 3 */
++ u8 model; /* C218T=1, C320T=2, CP204=3 */
++ u8 reserved2[8];
++ __le16 len[5];
++ } *hdr = ptr;
++
++ BUILD_BUG_ON(ARRAY_SIZE(hdr->len) != ARRAY_SIZE(lens));
++
++ if (fw->size < MOXA_FW_HDRLEN) {
++ strcpy(rsn, "too short (even header won't fit)");
++ goto err;
++ }
++ if (hdr->magic != cpu_to_le32(0x30343034)) {
++ sprintf(rsn, "bad magic: %.8x", le32_to_cpu(hdr->magic));
++ goto err;
++ }
++ if (hdr->type != 3) {
++ sprintf(rsn, "not for linux, type is %u", hdr->type);
++ goto err;
++ }
++ if (moxa_check_fw_model(brd, hdr->model)) {
++ sprintf(rsn, "not for this card, model is %u", hdr->model);
++ goto err;
++ }
++
++ len = MOXA_FW_HDRLEN;
++ lencnt = hdr->model == 2 ? 5 : 3;
++ for (a = 0; a < ARRAY_SIZE(lens); a++) {
++ lens[a] = le16_to_cpu(hdr->len[a]);
++ if (lens[a] && len + lens[a] <= fw->size &&
++ moxa_check_fw(&fw->data[len]))
++ printk(KERN_WARNING "MOXA firmware: unexpected input "
++ "at offset %u, but going on\n", (u32)len);
++ if (!lens[a] && a < lencnt) {
++ sprintf(rsn, "too few entries in fw file");
++ goto err;
++ }
++ len += lens[a];
++ }
++
++ if (len != fw->size) {
++ sprintf(rsn, "bad length: %u (should be %u)", (u32)fw->size,
++ (u32)len);
++ goto err;
++ }
++
++ ptr += MOXA_FW_HDRLEN;
++ lenp = 0; /* bios */
++
++ strcpy(rsn, "read above");
++
++ ret = moxa_load_bios(brd, ptr, lens[lenp]);
++ if (ret)
++ goto err;
++
++ /* we skip the tty section (lens[1]), since we don't need it */
++ ptr += lens[lenp] + lens[lenp + 1];
++ lenp += 2; /* comm */
++
++ if (hdr->model == 2) {
++ ret = moxa_load_320b(brd, ptr, lens[lenp]);
++ if (ret)
++ goto err;
++ /* skip another tty */
++ ptr += lens[lenp] + lens[lenp + 1];
++ lenp += 2;
++ }
++
++ ret = moxa_load_code(brd, ptr, lens[lenp]);
++ if (ret)
++ goto err;
++
++ return 0;
++err:
++ printk(KERN_ERR "firmware failed to load, reason: %s\n", rsn);
++ return ret;
++}
++
++static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
++{
++ const struct firmware *fw;
++ const char *file;
++ struct moxa_port *p;
++ unsigned int i;
++ int ret;
++
++ brd->ports = kcalloc(MAX_PORTS_PER_BOARD, sizeof(*brd->ports),
++ GFP_KERNEL);
++ if (brd->ports == NULL) {
++ printk(KERN_ERR "cannot allocate memory for ports\n");
++ ret = -ENOMEM;
++ goto err;
++ }
++
++ for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) {
++ p->type = PORT_16550A;
++ p->close_delay = 5 * HZ / 10;
++ p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
++ init_waitqueue_head(&p->open_wait);
++ }
++
++ switch (brd->boardType) {
++ case MOXA_BOARD_C218_ISA:
++ case MOXA_BOARD_C218_PCI:
++ file = "c218tunx.cod";
++ break;
++ case MOXA_BOARD_CP204J:
++ file = "cp204unx.cod";
++ break;
++ default:
++ file = "c320tunx.cod";
++ break;
++ }
++
++ ret = request_firmware(&fw, file, dev);
++ if (ret) {
++ printk(KERN_ERR "MOXA: request_firmware failed. Make sure "
++ "you've placed '%s' file into your firmware "
++ "loader directory (e.g. /lib/firmware)\n",
++ file);
++ goto err_free;
++ }
++
++ ret = moxa_load_fw(brd, fw);
++
++ release_firmware(fw);
++
++ if (ret)
++ goto err_free;
++
++ spin_lock_bh(&moxa_lock);
++ brd->ready = 1;
++ if (!timer_pending(&moxaTimer))
++ mod_timer(&moxaTimer, jiffies + HZ / 50);
++ spin_unlock_bh(&moxa_lock);
++
++ return 0;
++err_free:
++ kfree(brd->ports);
++err:
++ return ret;
++}
++
++static void moxa_board_deinit(struct moxa_board_conf *brd)
++{
++ unsigned int a, opened;
++
++ mutex_lock(&moxa_openlock);
++ spin_lock_bh(&moxa_lock);
++ brd->ready = 0;
++ spin_unlock_bh(&moxa_lock);
++
++ /* pci hot-un-plug support */
++ for (a = 0; a < brd->numPorts; a++)
++ if (brd->ports[a].asyncflags & ASYNC_INITIALIZED)
++ tty_hangup(brd->ports[a].tty);
++ while (1) {
++ opened = 0;
++ for (a = 0; a < brd->numPorts; a++)
++ if (brd->ports[a].asyncflags & ASYNC_INITIALIZED)
++ opened++;
++ mutex_unlock(&moxa_openlock);
++ if (!opened)
++ break;
++ msleep(50);
++ mutex_lock(&moxa_openlock);
++ }
++
++ iounmap(brd->basemem);
++ brd->basemem = NULL;
++ kfree(brd->ports);
++}
++
+ #ifdef CONFIG_PCI
+ static int __devinit moxa_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+@@ -299,10 +930,17 @@ static int __devinit moxa_pci_probe(struct pci_dev *pdev,
+ }
+
+ board = &moxa_boards[i];
+- board->basemem = pci_iomap(pdev, 2, 0x4000);
++
++ retval = pci_request_region(pdev, 2, "moxa-base");
++ if (retval) {
++ dev_err(&pdev->dev, "can't request pci region 2\n");
++ goto err;
++ }
++
++ board->basemem = ioremap_nocache(pci_resource_start(pdev, 2), 0x4000);
+ if (board->basemem == NULL) {
+ dev_err(&pdev->dev, "can't remap io space 2\n");
+- goto err;
++ goto err_reg;
+ }
+
+ board->boardType = board_type;
+@@ -321,9 +959,21 @@ static int __devinit moxa_pci_probe(struct pci_dev *pdev,
+ }
+ board->busType = MOXA_BUS_TYPE_PCI;
+
++ retval = moxa_init_board(board, &pdev->dev);
++ if (retval)
++ goto err_base;
++
+ pci_set_drvdata(pdev, board);
+
+- return (0);
++ dev_info(&pdev->dev, "board '%s' ready (%u ports, firmware loaded)\n",
++ moxa_brdname[board_type - 1], board->numPorts);
++
++ return 0;
++err_base:
++ iounmap(board->basemem);
++ board->basemem = NULL;
++err_reg:
++ pci_release_region(pdev, 2);
+ err:
+ return retval;
+ }
+@@ -332,8 +982,9 @@ static void __devexit moxa_pci_remove(struct pci_dev *pdev)
+ {
+ struct moxa_board_conf *brd = pci_get_drvdata(pdev);
+
+- pci_iounmap(pdev, brd->basemem);
+- brd->basemem = NULL;
++ moxa_board_deinit(brd);
++
++ pci_release_region(pdev, 2);
+ }
+
+ static struct pci_driver moxa_pci_driver = {
+@@ -346,8 +997,8 @@ static struct pci_driver moxa_pci_driver = {
+
+ static int __init moxa_init(void)
+ {
+- int i, numBoards, retval = 0;
+- struct moxa_port *ch;
++ unsigned int isabrds = 0;
++ int retval = 0;
+
+ printk(KERN_INFO "MOXA Intellio family driver version %s\n",
+ MOXA_VERSION);
+@@ -368,154 +1019,176 @@ static int __init moxa_init(void)
+ moxaDriver->flags = TTY_DRIVER_REAL_RAW;
+ tty_set_operations(moxaDriver, &moxa_ops);
+
+- for (i = 0, ch = moxa_ports; i < MAX_PORTS; i++, ch++) {
+- ch->type = PORT_16550A;
+- ch->port = i;
+- ch->close_delay = 5 * HZ / 10;
+- ch->closing_wait = 30 * HZ;
+- ch->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
+- init_waitqueue_head(&ch->open_wait);
+- init_completion(&ch->close_wait);
+-
+- setup_timer(&ch->emptyTimer, moxa_check_xmit_empty,
+- (unsigned long)ch);
+- }
+-
+- pr_debug("Moxa tty devices major number = %d\n", ttymajor);
+-
+ if (tty_register_driver(moxaDriver)) {
+- printk(KERN_ERR "Couldn't install MOXA Smartio family driver !\n");
++ printk(KERN_ERR "can't register MOXA Smartio tty driver!\n");
+ put_tty_driver(moxaDriver);
+ return -1;
+ }
+
+- mod_timer(&moxaTimer, jiffies + HZ / 50);
+-
+- /* Find the boards defined in source code */
+- numBoards = 0;
+- for (i = 0; i < MAX_BOARDS; i++) {
+- if ((moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA) ||
+- (moxa_isa_boards[i].boardType == MOXA_BOARD_C320_ISA)) {
+- moxa_boards[numBoards].boardType = moxa_isa_boards[i].boardType;
+- if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA)
+- moxa_boards[numBoards].numPorts = 8;
+- else
+- moxa_boards[numBoards].numPorts = moxa_isa_boards[i].numPorts;
+- moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA;
+- moxa_boards[numBoards].baseAddr = moxa_isa_boards[i].baseAddr;
+- pr_debug("Moxa board %2d: %s board(baseAddr=%lx)\n",
+- numBoards + 1,
+- moxa_brdname[moxa_boards[numBoards].boardType-1],
+- moxa_boards[numBoards].baseAddr);
+- numBoards++;
+- }
+- }
+- /* Find the boards defined form module args. */
++ /* Find the boards defined from module args. */
+ #ifdef MODULE
++ {
++ struct moxa_board_conf *brd = moxa_boards;
++ unsigned int i;
+ for (i = 0; i < MAX_BOARDS; i++) {
+- if ((type[i] == MOXA_BOARD_C218_ISA) ||
+- (type[i] == MOXA_BOARD_C320_ISA)) {
++ if (!baseaddr[i])
++ break;
++ if (type[i] == MOXA_BOARD_C218_ISA ||
++ type[i] == MOXA_BOARD_C320_ISA) {
+ pr_debug("Moxa board %2d: %s board(baseAddr=%lx)\n",
+- numBoards + 1, moxa_brdname[type[i] - 1],
+- (unsigned long)baseaddr[i]);
+- if (numBoards >= MAX_BOARDS) {
+- printk(KERN_WARNING "More than %d MOXA "
+- "Intellio family boards found. Board "
+- "is ignored.\n", MAX_BOARDS);
++ isabrds + 1, moxa_brdname[type[i] - 1],
++ baseaddr[i]);
++ brd->boardType = type[i];
++ brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 :
++ numports[i];
++ brd->busType = MOXA_BUS_TYPE_ISA;
++ brd->basemem = ioremap_nocache(baseaddr[i], 0x4000);
++ if (!brd->basemem) {
++ printk(KERN_ERR "MOXA: can't remap %lx\n",
++ baseaddr[i]);
+ continue;
+ }
+- moxa_boards[numBoards].boardType = type[i];
+- if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA)
+- moxa_boards[numBoards].numPorts = 8;
+- else
+- moxa_boards[numBoards].numPorts = numports[i];
+- moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA;
+- moxa_boards[numBoards].baseAddr = baseaddr[i];
+- numBoards++;
++ if (moxa_init_board(brd, NULL)) {
++ iounmap(brd->basemem);
++ brd->basemem = NULL;
++ continue;
++ }
++
++ printk(KERN_INFO "MOXA isa board found at 0x%.8lu and "
++ "ready (%u ports, firmware loaded)\n",
++ baseaddr[i], brd->numPorts);
++
++ brd++;
++ isabrds++;
+ }
+ }
++ }
+ #endif
+
+ #ifdef CONFIG_PCI
+ retval = pci_register_driver(&moxa_pci_driver);
+ if (retval) {
+- printk(KERN_ERR "Can't register moxa pci driver!\n");
+- if (numBoards)
++ printk(KERN_ERR "Can't register MOXA pci driver!\n");
++ if (isabrds)
+ retval = 0;
+ }
+ #endif
+
+- for (i = 0; i < numBoards; i++) {
+- moxa_boards[i].basemem = ioremap(moxa_boards[i].baseAddr,
+- 0x4000);
+- }
+-
+ return retval;
+ }
+
+ static void __exit moxa_exit(void)
+ {
+- int i;
++ unsigned int i;
+
+- del_timer_sync(&moxaTimer);
++#ifdef CONFIG_PCI
++ pci_unregister_driver(&moxa_pci_driver);
++#endif
++
++ for (i = 0; i < MAX_BOARDS; i++) /* ISA boards */
++ if (moxa_boards[i].ready)
++ moxa_board_deinit(&moxa_boards[i]);
+
+- for (i = 0; i < MAX_PORTS; i++)
+- del_timer_sync(&moxa_ports[i].emptyTimer);
++ del_timer_sync(&moxaTimer);
+
+ if (tty_unregister_driver(moxaDriver))
+ printk(KERN_ERR "Couldn't unregister MOXA Intellio family "
+ "serial driver\n");
+ put_tty_driver(moxaDriver);
+-
+-#ifdef CONFIG_PCI
+- pci_unregister_driver(&moxa_pci_driver);
+-#endif
+-
+- for (i = 0; i < MAX_BOARDS; i++)
+- if (moxa_boards[i].basemem)
+- iounmap(moxa_boards[i].basemem);
+ }
+
+ module_init(moxa_init);
+ module_exit(moxa_exit);
+
++static void moxa_close_port(struct moxa_port *ch)
++{
++ moxa_shut_down(ch);
++ MoxaPortFlushData(ch, 2);
++ ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
++ ch->tty->driver_data = NULL;
++ ch->tty = NULL;
++}
++
++static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
++ struct moxa_port *ch)
++{
++ DEFINE_WAIT(wait);
++ int retval = 0;
++ u8 dcd;
++
++ while (1) {
++ prepare_to_wait(&ch->open_wait, &wait, TASK_INTERRUPTIBLE);
++ if (tty_hung_up_p(filp)) {
++#ifdef SERIAL_DO_RESTART
++ retval = -ERESTARTSYS;
++#else
++ retval = -EAGAIN;
++#endif
++ break;
++ }
++ spin_lock_bh(&moxa_lock);
++ dcd = ch->DCDState;
++ spin_unlock_bh(&moxa_lock);
++ if (dcd)
++ break;
++
++ if (signal_pending(current)) {
++ retval = -ERESTARTSYS;
++ break;
++ }
++ schedule();
++ }
++ finish_wait(&ch->open_wait, &wait);
++
++ return retval;
++}
++
+ static int moxa_open(struct tty_struct *tty, struct file *filp)
+ {
++ struct moxa_board_conf *brd;
+ struct moxa_port *ch;
+ int port;
+ int retval;
+
+ port = tty->index;
+ if (port == MAX_PORTS) {
+- return (0);
++ return capable(CAP_SYS_ADMIN) ? 0 : -EPERM;
+ }
+- if (!MoxaPortIsValid(port)) {
+- tty->driver_data = NULL;
+- return (-ENODEV);
++ if (mutex_lock_interruptible(&moxa_openlock))
++ return -ERESTARTSYS;
++ brd = &moxa_boards[port / MAX_PORTS_PER_BOARD];
++ if (!brd->ready) {
++ mutex_unlock(&moxa_openlock);
++ return -ENODEV;
+ }
+
+- ch = &moxa_ports[port];
++ ch = &brd->ports[port % MAX_PORTS_PER_BOARD];
+ ch->count++;
+ tty->driver_data = ch;
+ ch->tty = tty;
+ if (!(ch->asyncflags & ASYNC_INITIALIZED)) {
+ ch->statusflags = 0;
+ moxa_set_tty_param(tty, tty->termios);
+- MoxaPortLineCtrl(ch->port, 1, 1);
+- MoxaPortEnable(ch->port);
++ MoxaPortLineCtrl(ch, 1, 1);
++ MoxaPortEnable(ch);
++ MoxaSetFifo(ch, ch->type == PORT_16550A);
+ ch->asyncflags |= ASYNC_INITIALIZED;
+ }
+- retval = moxa_block_till_ready(tty, filp, ch);
++ mutex_unlock(&moxa_openlock);
+
+- moxa_unthrottle(tty);
+-
+- if (ch->type == PORT_16550A) {
+- MoxaSetFifo(ch->port, 1);
+- } else {
+- MoxaSetFifo(ch->port, 0);
+- }
++ retval = 0;
++ if (!(filp->f_flags & O_NONBLOCK) && !C_CLOCAL(tty))
++ retval = moxa_block_till_ready(tty, filp, ch);
++ mutex_lock(&moxa_openlock);
++ if (retval) {
++ if (ch->count) /* 0 means already hung up... */
++ if (--ch->count == 0)
++ moxa_close_port(ch);
++ } else
++ ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
++ mutex_unlock(&moxa_openlock);
+
+- return (retval);
++ return retval;
+ }
+
+ static void moxa_close(struct tty_struct *tty, struct file *filp)
+@@ -524,23 +1197,14 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
+ int port;
+
+ port = tty->index;
+- if (port == MAX_PORTS) {
+- return;
+- }
+- if (!MoxaPortIsValid(port)) {
+- pr_debug("Invalid portno in moxa_close\n");
+- tty->driver_data = NULL;
+- return;
+- }
+- if (tty->driver_data == NULL) {
++ if (port == MAX_PORTS || tty_hung_up_p(filp))
+ return;
+- }
+- if (tty_hung_up_p(filp)) {
+- return;
+- }
+- ch = (struct moxa_port *) tty->driver_data;
+
+- if ((tty->count == 1) && (ch->count != 1)) {
++ mutex_lock(&moxa_openlock);
++ ch = tty->driver_data;
++ if (ch == NULL)
++ goto unlock;
++ if (tty->count == 1 && ch->count != 1) {
+ printk(KERN_WARNING "moxa_close: bad serial port count; "
+ "tty->count is 1, ch->count is %d\n", ch->count);
+ ch->count = 1;
+@@ -550,59 +1214,35 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
+ "device=%s\n", tty->name);
+ ch->count = 0;
+ }
+- if (ch->count) {
+- return;
+- }
+- ch->asyncflags |= ASYNC_CLOSING;
++ if (ch->count)
++ goto unlock;
+
+ ch->cflag = tty->termios->c_cflag;
+ if (ch->asyncflags & ASYNC_INITIALIZED) {
+ moxa_setup_empty_event(tty);
+ tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */
+- del_timer_sync(&moxa_ports[ch->port].emptyTimer);
+- }
+- moxa_shut_down(ch);
+- MoxaPortFlushData(port, 2);
+-
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
+- tty_ldisc_flush(tty);
+-
+- tty->closing = 0;
+- ch->event = 0;
+- ch->tty = NULL;
+- if (ch->blocked_open) {
+- if (ch->close_delay) {
+- msleep_interruptible(jiffies_to_msecs(ch->close_delay));
+- }
+- wake_up_interruptible(&ch->open_wait);
+ }
+- ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
+- complete_all(&ch->close_wait);
++
++ moxa_close_port(ch);
++unlock:
++ mutex_unlock(&moxa_openlock);
+ }
+
+ static int moxa_write(struct tty_struct *tty,
+ const unsigned char *buf, int count)
+ {
+- struct moxa_port *ch;
+- int len, port;
+- unsigned long flags;
++ struct moxa_port *ch = tty->driver_data;
++ int len;
+
+- ch = (struct moxa_port *) tty->driver_data;
+ if (ch == NULL)
+- return (0);
+- port = ch->port;
++ return 0;
+
+- spin_lock_irqsave(&moxa_lock, flags);
+- len = MoxaPortWriteData(port, (unsigned char *) buf, count);
+- spin_unlock_irqrestore(&moxa_lock, flags);
++ spin_lock_bh(&moxa_lock);
++ len = MoxaPortWriteData(ch, buf, count);
++ spin_unlock_bh(&moxa_lock);
+
+- /*********************************************
+- if ( !(ch->statusflags & LOWWAIT) &&
+- ((len != count) || (MoxaPortTxFree(port) <= 100)) )
+- ************************************************/
+ ch->statusflags |= LOWWAIT;
+- return (len);
++ return len;
+ }
+
+ static int moxa_write_room(struct tty_struct *tty)
+@@ -610,27 +1250,27 @@ static int moxa_write_room(struct tty_struct *tty)
+ struct moxa_port *ch;
+
+ if (tty->stopped)
+- return (0);
+- ch = (struct moxa_port *) tty->driver_data;
++ return 0;
++ ch = tty->driver_data;
+ if (ch == NULL)
+- return (0);
+- return (MoxaPortTxFree(ch->port));
++ return 0;
++ return MoxaPortTxFree(ch);
+ }
+
+ static void moxa_flush_buffer(struct tty_struct *tty)
+ {
+- struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
++ struct moxa_port *ch = tty->driver_data;
+
+ if (ch == NULL)
+ return;
+- MoxaPortFlushData(ch->port, 1);
++ MoxaPortFlushData(ch, 1);
+ tty_wakeup(tty);
+ }
+
+ static int moxa_chars_in_buffer(struct tty_struct *tty)
+ {
++ struct moxa_port *ch = tty->driver_data;
+ int chars;
+- struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
+
+ /*
+ * Sigh...I have to check if driver_data is NULL here, because
+@@ -639,8 +1279,9 @@ static int moxa_chars_in_buffer(struct tty_struct *tty)
+ * routine. And since the open() failed, we return 0 here. TDJ
+ */
+ if (ch == NULL)
+- return (0);
+- chars = MoxaPortTxQueue(ch->port);
++ return 0;
++ lock_kernel();
++ chars = MoxaPortTxQueue(ch);
+ if (chars) {
+ /*
+ * Make it possible to wakeup anything waiting for output
+@@ -649,73 +1290,54 @@ static int moxa_chars_in_buffer(struct tty_struct *tty)
+ if (!(ch->statusflags & EMPTYWAIT))
+ moxa_setup_empty_event(tty);
+ }
+- return (chars);
+-}
+-
+-static void moxa_flush_chars(struct tty_struct *tty)
+-{
+- /*
+- * Don't think I need this, because this is called to empty the TX
+- * buffer for the 16450, 16550, etc.
+- */
+-}
+-
+-static void moxa_put_char(struct tty_struct *tty, unsigned char c)
+-{
+- struct moxa_port *ch;
+- int port;
+- unsigned long flags;
+-
+- ch = (struct moxa_port *) tty->driver_data;
+- if (ch == NULL)
+- return;
+- port = ch->port;
+- spin_lock_irqsave(&moxa_lock, flags);
+- MoxaPortWriteData(port, &c, 1);
+- spin_unlock_irqrestore(&moxa_lock, flags);
+- /************************************************
+- if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) )
+- *************************************************/
+- ch->statusflags |= LOWWAIT;
++ unlock_kernel();
++ return chars;
+ }
+
+ static int moxa_tiocmget(struct tty_struct *tty, struct file *file)
+ {
+- struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
+- int port;
++ struct moxa_port *ch;
+ int flag = 0, dtr, rts;
+
+- port = tty->index;
+- if ((port != MAX_PORTS) && (!ch))
+- return (-EINVAL);
++ mutex_lock(&moxa_openlock);
++ ch = tty->driver_data;
++ if (!ch) {
++ mutex_unlock(&moxa_openlock);
++ return -EINVAL;
++ }
+
+- MoxaPortGetLineOut(ch->port, &dtr, &rts);
++ MoxaPortGetLineOut(ch, &dtr, &rts);
+ if (dtr)
+ flag |= TIOCM_DTR;
+ if (rts)
+ flag |= TIOCM_RTS;
+- dtr = MoxaPortLineStatus(ch->port);
++ dtr = MoxaPortLineStatus(ch);
+ if (dtr & 1)
+ flag |= TIOCM_CTS;
+ if (dtr & 2)
+ flag |= TIOCM_DSR;
+ if (dtr & 4)
+ flag |= TIOCM_CD;
++ mutex_unlock(&moxa_openlock);
+ return flag;
+ }
+
+ static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+ {
+- struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
++ struct moxa_port *ch;
+ int port;
+ int dtr, rts;
+
+ port = tty->index;
+- if ((port != MAX_PORTS) && (!ch))
+- return (-EINVAL);
++ mutex_lock(&moxa_openlock);
++ ch = tty->driver_data;
++ if (!ch) {
++ mutex_unlock(&moxa_openlock);
++ return -EINVAL;
++ }
+
+- MoxaPortGetLineOut(ch->port, &dtr, &rts);
++ MoxaPortGetLineOut(ch, &dtr, &rts);
+ if (set & TIOCM_RTS)
+ rts = 1;
+ if (set & TIOCM_DTR)
+@@ -724,105 +1346,51 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
+ rts = 0;
+ if (clear & TIOCM_DTR)
+ dtr = 0;
+- MoxaPortLineCtrl(ch->port, dtr, rts);
++ MoxaPortLineCtrl(ch, dtr, rts);
++ mutex_unlock(&moxa_openlock);
+ return 0;
+ }
+
+-static int moxa_ioctl(struct tty_struct *tty, struct file *file,
+- unsigned int cmd, unsigned long arg)
+-{
+- struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
+- register int port;
+- void __user *argp = (void __user *)arg;
+- int retval;
+-
+- port = tty->index;
+- if ((port != MAX_PORTS) && (!ch))
+- return (-EINVAL);
+-
+- switch (cmd) {
+- case TCSBRK: /* SVID version: non-zero arg --> no break */
+- retval = tty_check_change(tty);
+- if (retval)
+- return (retval);
+- moxa_setup_empty_event(tty);
+- tty_wait_until_sent(tty, 0);
+- if (!arg)
+- MoxaPortSendBreak(ch->port, 0);
+- return (0);
+- case TCSBRKP: /* support for POSIX tcsendbreak() */
+- retval = tty_check_change(tty);
+- if (retval)
+- return (retval);
+- moxa_setup_empty_event(tty);
+- tty_wait_until_sent(tty, 0);
+- MoxaPortSendBreak(ch->port, arg);
+- return (0);
+- case TIOCGSOFTCAR:
+- return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) argp);
+- case TIOCSSOFTCAR:
+- if(get_user(retval, (unsigned long __user *) argp))
+- return -EFAULT;
+- arg = retval;
+- tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |
+- (arg ? CLOCAL : 0));
+- if (C_CLOCAL(tty))
+- ch->asyncflags &= ~ASYNC_CHECK_CD;
+- else
+- ch->asyncflags |= ASYNC_CHECK_CD;
+- return (0);
+- case TIOCGSERIAL:
+- return moxa_get_serial_info(ch, argp);
+-
+- case TIOCSSERIAL:
+- return moxa_set_serial_info(ch, argp);
+- default:
+- retval = MoxaDriverIoctl(cmd, arg, port);
+- }
+- return (retval);
+-}
+-
+ static void moxa_throttle(struct tty_struct *tty)
+ {
+- struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
++ struct moxa_port *ch = tty->driver_data;
+
+ ch->statusflags |= THROTTLE;
+ }
+
+ static void moxa_unthrottle(struct tty_struct *tty)
+ {
+- struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
++ struct moxa_port *ch = tty->driver_data;
+
+ ch->statusflags &= ~THROTTLE;
+ }
+
+ static void moxa_set_termios(struct tty_struct *tty,
+- struct ktermios *old_termios)
++ struct ktermios *old_termios)
+ {
+- struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
++ struct moxa_port *ch = tty->driver_data;
+
+ if (ch == NULL)
+ return;
+ moxa_set_tty_param(tty, old_termios);
+- if (!(old_termios->c_cflag & CLOCAL) &&
+- (tty->termios->c_cflag & CLOCAL))
++ if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty))
+ wake_up_interruptible(&ch->open_wait);
+ }
+
+ static void moxa_stop(struct tty_struct *tty)
+ {
+- struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
++ struct moxa_port *ch = tty->driver_data;
+
+ if (ch == NULL)
+ return;
+- MoxaPortTxDisable(ch->port);
++ MoxaPortTxDisable(ch);
+ ch->statusflags |= TXSTOPPED;
+ }
+
+
+ static void moxa_start(struct tty_struct *tty)
+ {
+- struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
++ struct moxa_port *ch = tty->driver_data;
+
+ if (ch == NULL)
+ return;
+@@ -830,91 +1398,143 @@ static void moxa_start(struct tty_struct *tty)
+ if (!(ch->statusflags & TXSTOPPED))
+ return;
+
+- MoxaPortTxEnable(ch->port);
++ MoxaPortTxEnable(ch);
+ ch->statusflags &= ~TXSTOPPED;
+ }
+
+ static void moxa_hangup(struct tty_struct *tty)
+ {
+- struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
++ struct moxa_port *ch;
+
+- moxa_flush_buffer(tty);
+- moxa_shut_down(ch);
+- ch->event = 0;
++ mutex_lock(&moxa_openlock);
++ ch = tty->driver_data;
++ if (ch == NULL) {
++ mutex_unlock(&moxa_openlock);
++ return;
++ }
+ ch->count = 0;
+- ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
+- ch->tty = NULL;
++ moxa_close_port(ch);
++ mutex_unlock(&moxa_openlock);
++
+ wake_up_interruptible(&ch->open_wait);
+ }
+
+-static void moxa_poll(unsigned long ignored)
++static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
+ {
+- register int card;
+- struct moxa_port *ch;
+- struct tty_struct *tp;
+- int i, ports;
++ dcd = !!dcd;
+
+- del_timer(&moxaTimer);
++ if (dcd != p->DCDState && p->tty && C_CLOCAL(p->tty)) {
++ if (!dcd)
++ tty_hangup(p->tty);
++ }
++ p->DCDState = dcd;
++}
+
+- if (MoxaDriverPoll() < 0) {
+- mod_timer(&moxaTimer, jiffies + HZ / 50);
+- return;
++static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
++ u16 __iomem *ip)
++{
++ struct tty_struct *tty = p->tty;
++ void __iomem *ofsAddr;
++ unsigned int inited = p->asyncflags & ASYNC_INITIALIZED;
++ u16 intr;
++
++ if (tty) {
++ if ((p->statusflags & EMPTYWAIT) &&
++ MoxaPortTxQueue(p) == 0) {
++ p->statusflags &= ~EMPTYWAIT;
++ tty_wakeup(tty);
++ }
++ if ((p->statusflags & LOWWAIT) && !tty->stopped &&
++ MoxaPortTxQueue(p) <= WAKEUP_CHARS) {
++ p->statusflags &= ~LOWWAIT;
++ tty_wakeup(tty);
++ }
++
++ if (inited && !(p->statusflags & THROTTLE) &&
++ MoxaPortRxQueue(p) > 0) { /* RX */
++ MoxaPortReadData(p);
++ tty_schedule_flip(tty);
++ }
++ } else {
++ p->statusflags &= ~EMPTYWAIT;
++ MoxaPortFlushData(p, 0); /* flush RX */
+ }
++
++ if (!handle) /* nothing else to do */
++ return 0;
++
++ intr = readw(ip); /* port irq status */
++ if (intr == 0)
++ return 0;
++
++ writew(0, ip); /* ACK port */
++ ofsAddr = p->tableAddr;
++ if (intr & IntrTx) /* disable tx intr */
++ writew(readw(ofsAddr + HostStat) & ~WakeupTx,
++ ofsAddr + HostStat);
++
++ if (!inited)
++ return 0;
++
++ if (tty && (intr & IntrBreak) && !I_IGNBRK(tty)) { /* BREAK */
++ tty_insert_flip_char(tty, 0, TTY_BREAK);
++ tty_schedule_flip(tty);
++ }
++
++ if (intr & IntrLine)
++ moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state);
++
++ return 0;
++}
++
++static void moxa_poll(unsigned long ignored)
++{
++ struct moxa_board_conf *brd;
++ u16 __iomem *ip;
++ unsigned int card, port, served = 0;
++
++ spin_lock(&moxa_lock);
+ for (card = 0; card < MAX_BOARDS; card++) {
+- if ((ports = MoxaPortsOfCard(card)) <= 0)
++ brd = &moxa_boards[card];
++ if (!brd->ready)
+ continue;
+- ch = &moxa_ports[card * MAX_PORTS_PER_BOARD];
+- for (i = 0; i < ports; i++, ch++) {
+- if ((ch->asyncflags & ASYNC_INITIALIZED) == 0)
+- continue;
+- if (!(ch->statusflags & THROTTLE) &&
+- (MoxaPortRxQueue(ch->port) > 0))
+- moxa_receive_data(ch);
+- if ((tp = ch->tty) == 0)
+- continue;
+- if (ch->statusflags & LOWWAIT) {
+- if (MoxaPortTxQueue(ch->port) <= WAKEUP_CHARS) {
+- if (!tp->stopped) {
+- ch->statusflags &= ~LOWWAIT;
+- tty_wakeup(tp);
+- }
+- }
+- }
+- if (!I_IGNBRK(tp) && (MoxaPortResetBrkCnt(ch->port) > 0)) {
+- tty_insert_flip_char(tp, 0, TTY_BREAK);
+- tty_schedule_flip(tp);
+- }
+- if (MoxaPortDCDChange(ch->port)) {
+- if (ch->asyncflags & ASYNC_CHECK_CD) {
+- if (MoxaPortDCDON(ch->port))
+- wake_up_interruptible(&ch->open_wait);
+- else {
+- tty_hangup(tp);
+- wake_up_interruptible(&ch->open_wait);
+- ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
+- }
++
++ served++;
++
++ ip = NULL;
++ if (readb(brd->intPend) == 0xff)
++ ip = brd->intTable + readb(brd->intNdx);
++
++ for (port = 0; port < brd->numPorts; port++)
++ moxa_poll_port(&brd->ports[port], !!ip, ip + port);
++
++ if (ip)
++ writeb(0, brd->intPend); /* ACK */
++
++ if (moxaLowWaterChk) {
++ struct moxa_port *p = brd->ports;
++ for (port = 0; port < brd->numPorts; port++, p++)
++ if (p->lowChkFlag) {
++ p->lowChkFlag = 0;
++ moxa_low_water_check(p->tableAddr);
+ }
+- }
+ }
+ }
++ moxaLowWaterChk = 0;
+
+- mod_timer(&moxaTimer, jiffies + HZ / 50);
++ if (served)
++ mod_timer(&moxaTimer, jiffies + HZ / 50);
++ spin_unlock(&moxa_lock);
+ }
+
+ /******************************************************************************/
+
+ static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_termios)
+ {
+- register struct ktermios *ts;
+- struct moxa_port *ch;
++ register struct ktermios *ts = tty->termios;
++ struct moxa_port *ch = tty->driver_data;
+ int rts, cts, txflow, rxflow, xany, baud;
+
+- ch = (struct moxa_port *) tty->driver_data;
+- ts = tty->termios;
+- if (ts->c_cflag & CLOCAL)
+- ch->asyncflags &= ~ASYNC_CHECK_CD;
+- else
+- ch->asyncflags |= ASYNC_CHECK_CD;
+ rts = cts = txflow = rxflow = xany = 0;
+ if (ts->c_cflag & CRTSCTS)
+ rts = cts = 1;
+@@ -927,776 +1547,60 @@ static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_term
+
+ /* Clear the features we don't support */
+ ts->c_cflag &= ~CMSPAR;
+- MoxaPortFlowCtrl(ch->port, rts, cts, txflow, rxflow, xany);
+- baud = MoxaPortSetTermio(ch->port, ts, tty_get_baud_rate(tty));
++ MoxaPortFlowCtrl(ch, rts, cts, txflow, rxflow, xany);
++ baud = MoxaPortSetTermio(ch, ts, tty_get_baud_rate(tty));
+ if (baud == -1)
+ baud = tty_termios_baud_rate(old_termios);
+ /* Not put the baud rate into the termios data */
+ tty_encode_baud_rate(tty, baud, baud);
+ }
+
+-static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
+- struct moxa_port *ch)
+-{
+- DECLARE_WAITQUEUE(wait,current);
+- unsigned long flags;
+- int retval;
+- int do_clocal = C_CLOCAL(tty);
+-
+- /*
+- * If the device is in the middle of being closed, then block
+- * until it's done, and then try again.
+- */
+- if (tty_hung_up_p(filp) || (ch->asyncflags & ASYNC_CLOSING)) {
+- if (ch->asyncflags & ASYNC_CLOSING)
+- wait_for_completion_interruptible(&ch->close_wait);
+-#ifdef SERIAL_DO_RESTART
+- if (ch->asyncflags & ASYNC_HUP_NOTIFY)
+- return (-EAGAIN);
+- else
+- return (-ERESTARTSYS);
+-#else
+- return (-EAGAIN);
+-#endif
+- }
+- /*
+- * If non-blocking mode is set, then make the check up front
+- * and then exit.
+- */
+- if (filp->f_flags & O_NONBLOCK) {
+- ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
+- return (0);
+- }
+- /*
+- * Block waiting for the carrier detect and the line to become free
+- */
+- retval = 0;
+- add_wait_queue(&ch->open_wait, &wait);
+- pr_debug("block_til_ready before block: ttys%d, count = %d\n",
+- ch->port, ch->count);
+- spin_lock_irqsave(&moxa_lock, flags);
+- if (!tty_hung_up_p(filp))
+- ch->count--;
+- ch->blocked_open++;
+- spin_unlock_irqrestore(&moxa_lock, flags);
+-
+- while (1) {
+- set_current_state(TASK_INTERRUPTIBLE);
+- if (tty_hung_up_p(filp) ||
+- !(ch->asyncflags & ASYNC_INITIALIZED)) {
+-#ifdef SERIAL_DO_RESTART
+- if (ch->asyncflags & ASYNC_HUP_NOTIFY)
+- retval = -EAGAIN;
+- else
+- retval = -ERESTARTSYS;
+-#else
+- retval = -EAGAIN;
+-#endif
+- break;
+- }
+- if (!(ch->asyncflags & ASYNC_CLOSING) && (do_clocal ||
+- MoxaPortDCDON(ch->port)))
+- break;
+-
+- if (signal_pending(current)) {
+- retval = -ERESTARTSYS;
+- break;
+- }
+- schedule();
+- }
+- set_current_state(TASK_RUNNING);
+- remove_wait_queue(&ch->open_wait, &wait);
+-
+- spin_lock_irqsave(&moxa_lock, flags);
+- if (!tty_hung_up_p(filp))
+- ch->count++;
+- ch->blocked_open--;
+- spin_unlock_irqrestore(&moxa_lock, flags);
+- pr_debug("block_til_ready after blocking: ttys%d, count = %d\n",
+- ch->port, ch->count);
+- if (retval)
+- return (retval);
+- /* FIXME: review to see if we need to use set_bit on these */
+- ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
+- return 0;
+-}
+-
+ static void moxa_setup_empty_event(struct tty_struct *tty)
+ {
+ struct moxa_port *ch = tty->driver_data;
+- unsigned long flags;
+
+- spin_lock_irqsave(&moxa_lock, flags);
++ spin_lock_bh(&moxa_lock);
+ ch->statusflags |= EMPTYWAIT;
+- mod_timer(&moxa_ports[ch->port].emptyTimer, jiffies + HZ);
+- spin_unlock_irqrestore(&moxa_lock, flags);
+-}
+-
+-static void moxa_check_xmit_empty(unsigned long data)
+-{
+- struct moxa_port *ch;
+-
+- ch = (struct moxa_port *) data;
+- if (ch->tty && (ch->statusflags & EMPTYWAIT)) {
+- if (MoxaPortTxQueue(ch->port) == 0) {
+- ch->statusflags &= ~EMPTYWAIT;
+- tty_wakeup(ch->tty);
+- return;
+- }
+- mod_timer(&moxa_ports[ch->port].emptyTimer,
+- round_jiffies(jiffies + HZ));
+- } else
+- ch->statusflags &= ~EMPTYWAIT;
++ spin_unlock_bh(&moxa_lock);
+ }
+
+ static void moxa_shut_down(struct moxa_port *ch)
+ {
+- struct tty_struct *tp;
++ struct tty_struct *tp = ch->tty;
+
+ if (!(ch->asyncflags & ASYNC_INITIALIZED))
+ return;
+
+- tp = ch->tty;
+-
+- MoxaPortDisable(ch->port);
++ MoxaPortDisable(ch);
+
+ /*
+ * If we're a modem control device and HUPCL is on, drop RTS & DTR.
+ */
+- if (tp->termios->c_cflag & HUPCL)
+- MoxaPortLineCtrl(ch->port, 0, 0);
++ if (C_HUPCL(tp))
++ MoxaPortLineCtrl(ch, 0, 0);
+
++ spin_lock_bh(&moxa_lock);
+ ch->asyncflags &= ~ASYNC_INITIALIZED;
++ spin_unlock_bh(&moxa_lock);
+ }
+
+-static void moxa_receive_data(struct moxa_port *ch)
+-{
+- struct tty_struct *tp;
+- struct ktermios *ts;
+- unsigned long flags;
+-
+- ts = NULL;
+- tp = ch->tty;
+- if (tp)
+- ts = tp->termios;
+- /**************************************************
+- if ( !tp || !ts || !(ts->c_cflag & CREAD) ) {
+- *****************************************************/
+- if (!tp || !ts) {
+- MoxaPortFlushData(ch->port, 0);
+- return;
+- }
+- spin_lock_irqsave(&moxa_lock, flags);
+- MoxaPortReadData(ch->port, tp);
+- spin_unlock_irqrestore(&moxa_lock, flags);
+- tty_schedule_flip(tp);
+-}
+-
+-#define Magic_code 0x404
+-
+-/*
+- * System Configuration
+- */
+-/*
+- * for C218 BIOS initialization
+- */
+-#define C218_ConfBase 0x800
+-#define C218_status (C218_ConfBase + 0) /* BIOS running status */
+-#define C218_diag (C218_ConfBase + 2) /* diagnostic status */
+-#define C218_key (C218_ConfBase + 4) /* WORD (0x218 for C218) */
+-#define C218DLoad_len (C218_ConfBase + 6) /* WORD */
+-#define C218check_sum (C218_ConfBase + 8) /* BYTE */
+-#define C218chksum_ok (C218_ConfBase + 0x0a) /* BYTE (1:ok) */
+-#define C218_TestRx (C218_ConfBase + 0x10) /* 8 bytes for 8 ports */
+-#define C218_TestTx (C218_ConfBase + 0x18) /* 8 bytes for 8 ports */
+-#define C218_RXerr (C218_ConfBase + 0x20) /* 8 bytes for 8 ports */
+-#define C218_ErrFlag (C218_ConfBase + 0x28) /* 8 bytes for 8 ports */
+-
+-#define C218_LoadBuf 0x0F00
+-#define C218_KeyCode 0x218
+-#define CP204J_KeyCode 0x204
+-
+-/*
+- * for C320 BIOS initialization
+- */
+-#define C320_ConfBase 0x800
+-#define C320_LoadBuf 0x0f00
+-#define STS_init 0x05 /* for C320_status */
+-
+-#define C320_status C320_ConfBase + 0 /* BIOS running status */
+-#define C320_diag C320_ConfBase + 2 /* diagnostic status */
+-#define C320_key C320_ConfBase + 4 /* WORD (0320H for C320) */
+-#define C320DLoad_len C320_ConfBase + 6 /* WORD */
+-#define C320check_sum C320_ConfBase + 8 /* WORD */
+-#define C320chksum_ok C320_ConfBase + 0x0a /* WORD (1:ok) */
+-#define C320bapi_len C320_ConfBase + 0x0c /* WORD */
+-#define C320UART_no C320_ConfBase + 0x0e /* WORD */
+-
+-#define C320_KeyCode 0x320
+-
+-#define FixPage_addr 0x0000 /* starting addr of static page */
+-#define DynPage_addr 0x2000 /* starting addr of dynamic page */
+-#define C218_start 0x3000 /* starting addr of C218 BIOS prg */
+-#define Control_reg 0x1ff0 /* select page and reset control */
+-#define HW_reset 0x80
+-
+-/*
+- * Function Codes
+- */
+-#define FC_CardReset 0x80
+-#define FC_ChannelReset 1 /* C320 firmware not supported */
+-#define FC_EnableCH 2
+-#define FC_DisableCH 3
+-#define FC_SetParam 4
+-#define FC_SetMode 5
+-#define FC_SetRate 6
+-#define FC_LineControl 7
+-#define FC_LineStatus 8
+-#define FC_XmitControl 9
+-#define FC_FlushQueue 10
+-#define FC_SendBreak 11
+-#define FC_StopBreak 12
+-#define FC_LoopbackON 13
+-#define FC_LoopbackOFF 14
+-#define FC_ClrIrqTable 15
+-#define FC_SendXon 16
+-#define FC_SetTermIrq 17 /* C320 firmware not supported */
+-#define FC_SetCntIrq 18 /* C320 firmware not supported */
+-#define FC_SetBreakIrq 19
+-#define FC_SetLineIrq 20
+-#define FC_SetFlowCtl 21
+-#define FC_GenIrq 22
+-#define FC_InCD180 23
+-#define FC_OutCD180 24
+-#define FC_InUARTreg 23
+-#define FC_OutUARTreg 24
+-#define FC_SetXonXoff 25
+-#define FC_OutCD180CCR 26
+-#define FC_ExtIQueue 27
+-#define FC_ExtOQueue 28
+-#define FC_ClrLineIrq 29
+-#define FC_HWFlowCtl 30
+-#define FC_GetClockRate 35
+-#define FC_SetBaud 36
+-#define FC_SetDataMode 41
+-#define FC_GetCCSR 43
+-#define FC_GetDataError 45
+-#define FC_RxControl 50
+-#define FC_ImmSend 51
+-#define FC_SetXonState 52
+-#define FC_SetXoffState 53
+-#define FC_SetRxFIFOTrig 54
+-#define FC_SetTxFIFOCnt 55
+-#define FC_UnixRate 56
+-#define FC_UnixResetTimer 57
+-
+-#define RxFIFOTrig1 0
+-#define RxFIFOTrig4 1
+-#define RxFIFOTrig8 2
+-#define RxFIFOTrig14 3
+-
+-/*
+- * Dual-Ported RAM
+- */
+-#define DRAM_global 0
+-#define INT_data (DRAM_global + 0)
+-#define Config_base (DRAM_global + 0x108)
+-
+-#define IRQindex (INT_data + 0)
+-#define IRQpending (INT_data + 4)
+-#define IRQtable (INT_data + 8)
+-
+-/*
+- * Interrupt Status
+- */
+-#define IntrRx 0x01 /* receiver data O.K. */
+-#define IntrTx 0x02 /* transmit buffer empty */
+-#define IntrFunc 0x04 /* function complete */
+-#define IntrBreak 0x08 /* received break */
+-#define IntrLine 0x10 /* line status change
+- for transmitter */
+-#define IntrIntr 0x20 /* received INTR code */
+-#define IntrQuit 0x40 /* received QUIT code */
+-#define IntrEOF 0x80 /* received EOF code */
+-
+-#define IntrRxTrigger 0x100 /* rx data count reach tigger value */
+-#define IntrTxTrigger 0x200 /* tx data count below trigger value */
+-
+-#define Magic_no (Config_base + 0)
+-#define Card_model_no (Config_base + 2)
+-#define Total_ports (Config_base + 4)
+-#define Module_cnt (Config_base + 8)
+-#define Module_no (Config_base + 10)
+-#define Timer_10ms (Config_base + 14)
+-#define Disable_IRQ (Config_base + 20)
+-#define TMS320_PORT1 (Config_base + 22)
+-#define TMS320_PORT2 (Config_base + 24)
+-#define TMS320_CLOCK (Config_base + 26)
+-
+-/*
+- * DATA BUFFER in DRAM
+- */
+-#define Extern_table 0x400 /* Base address of the external table
+- (24 words * 64) total 3K bytes
+- (24 words * 128) total 6K bytes */
+-#define Extern_size 0x60 /* 96 bytes */
+-#define RXrptr 0x00 /* read pointer for RX buffer */
+-#define RXwptr 0x02 /* write pointer for RX buffer */
+-#define TXrptr 0x04 /* read pointer for TX buffer */
+-#define TXwptr 0x06 /* write pointer for TX buffer */
+-#define HostStat 0x08 /* IRQ flag and general flag */
+-#define FlagStat 0x0A
+-#define FlowControl 0x0C /* B7 B6 B5 B4 B3 B2 B1 B0 */
+- /* x x x x | | | | */
+- /* | | | + CTS flow */
+- /* | | +--- RTS flow */
+- /* | +------ TX Xon/Xoff */
+- /* +--------- RX Xon/Xoff */
+-#define Break_cnt 0x0E /* received break count */
+-#define CD180TXirq 0x10 /* if non-0: enable TX irq */
+-#define RX_mask 0x12
+-#define TX_mask 0x14
+-#define Ofs_rxb 0x16
+-#define Ofs_txb 0x18
+-#define Page_rxb 0x1A
+-#define Page_txb 0x1C
+-#define EndPage_rxb 0x1E
+-#define EndPage_txb 0x20
+-#define Data_error 0x22
+-#define RxTrigger 0x28
+-#define TxTrigger 0x2a
+-
+-#define rRXwptr 0x34
+-#define Low_water 0x36
+-
+-#define FuncCode 0x40
+-#define FuncArg 0x42
+-#define FuncArg1 0x44
+-
+-#define C218rx_size 0x2000 /* 8K bytes */
+-#define C218tx_size 0x8000 /* 32K bytes */
+-
+-#define C218rx_mask (C218rx_size - 1)
+-#define C218tx_mask (C218tx_size - 1)
+-
+-#define C320p8rx_size 0x2000
+-#define C320p8tx_size 0x8000
+-#define C320p8rx_mask (C320p8rx_size - 1)
+-#define C320p8tx_mask (C320p8tx_size - 1)
+-
+-#define C320p16rx_size 0x2000
+-#define C320p16tx_size 0x4000
+-#define C320p16rx_mask (C320p16rx_size - 1)
+-#define C320p16tx_mask (C320p16tx_size - 1)
+-
+-#define C320p24rx_size 0x2000
+-#define C320p24tx_size 0x2000
+-#define C320p24rx_mask (C320p24rx_size - 1)
+-#define C320p24tx_mask (C320p24tx_size - 1)
+-
+-#define C320p32rx_size 0x1000
+-#define C320p32tx_size 0x1000
+-#define C320p32rx_mask (C320p32rx_size - 1)
+-#define C320p32tx_mask (C320p32tx_size - 1)
+-
+-#define Page_size 0x2000
+-#define Page_mask (Page_size - 1)
+-#define C218rx_spage 3
+-#define C218tx_spage 4
+-#define C218rx_pageno 1
+-#define C218tx_pageno 4
+-#define C218buf_pageno 5
+-
+-#define C320p8rx_spage 3
+-#define C320p8tx_spage 4
+-#define C320p8rx_pgno 1
+-#define C320p8tx_pgno 4
+-#define C320p8buf_pgno 5
+-
+-#define C320p16rx_spage 3
+-#define C320p16tx_spage 4
+-#define C320p16rx_pgno 1
+-#define C320p16tx_pgno 2
+-#define C320p16buf_pgno 3
+-
+-#define C320p24rx_spage 3
+-#define C320p24tx_spage 4
+-#define C320p24rx_pgno 1
+-#define C320p24tx_pgno 1
+-#define C320p24buf_pgno 2
+-
+-#define C320p32rx_spage 3
+-#define C320p32tx_ofs C320p32rx_size
+-#define C320p32tx_spage 3
+-#define C320p32buf_pgno 1
+-
+-/*
+- * Host Status
+- */
+-#define WakeupRx 0x01
+-#define WakeupTx 0x02
+-#define WakeupBreak 0x08
+-#define WakeupLine 0x10
+-#define WakeupIntr 0x20
+-#define WakeupQuit 0x40
+-#define WakeupEOF 0x80 /* used in VTIME control */
+-#define WakeupRxTrigger 0x100
+-#define WakeupTxTrigger 0x200
+-/*
+- * Flag status
+- */
+-#define Rx_over 0x01
+-#define Xoff_state 0x02
+-#define Tx_flowOff 0x04
+-#define Tx_enable 0x08
+-#define CTS_state 0x10
+-#define DSR_state 0x20
+-#define DCD_state 0x80
+-/*
+- * FlowControl
+- */
+-#define CTS_FlowCtl 1
+-#define RTS_FlowCtl 2
+-#define Tx_FlowCtl 4
+-#define Rx_FlowCtl 8
+-#define IXM_IXANY 0x10
+-
+-#define LowWater 128
+-
+-#define DTR_ON 1
+-#define RTS_ON 2
+-#define CTS_ON 1
+-#define DSR_ON 2
+-#define DCD_ON 8
+-
+-/* mode definition */
+-#define MX_CS8 0x03
+-#define MX_CS7 0x02
+-#define MX_CS6 0x01
+-#define MX_CS5 0x00
+-
+-#define MX_STOP1 0x00
+-#define MX_STOP15 0x04
+-#define MX_STOP2 0x08
+-
+-#define MX_PARNONE 0x00
+-#define MX_PAREVEN 0x40
+-#define MX_PARODD 0xC0
+-
+-/*
+- * Query
+- */
+-
+-struct mon_str {
+- int tick;
+- int rxcnt[MAX_PORTS];
+- int txcnt[MAX_PORTS];
+-};
+-
+-#define DCD_changed 0x01
+-#define DCD_oldstate 0x80
+-
+-static unsigned char moxaBuff[10240];
+-static int moxaLowWaterChk;
+-static int moxaCard;
+-static struct mon_str moxaLog;
+-static int moxaFuncTout = HZ / 2;
+-
+-static void moxafunc(void __iomem *, int, ushort);
+-static void moxa_wait_finish(void __iomem *);
+-static void moxa_low_water_check(void __iomem *);
+-static int moxaloadbios(int, unsigned char __user *, int);
+-static int moxafindcard(int);
+-static int moxaload320b(int, unsigned char __user *, int);
+-static int moxaloadcode(int, unsigned char __user *, int);
+-static int moxaloadc218(int, void __iomem *, int);
+-static int moxaloadc320(int, void __iomem *, int, int *);
+-
+ /*****************************************************************************
+ * Driver level functions: *
+- * 1. MoxaDriverInit(void); *
+- * 2. MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port); *
+- * 3. MoxaDriverPoll(void); *
+ *****************************************************************************/
+-void MoxaDriverInit(void)
+-{
+- struct moxa_port *p;
+- unsigned int i;
+
+- moxaFuncTout = HZ / 2; /* 500 mini-seconds */
+- moxaCard = 0;
+- moxaLog.tick = 0;
+- moxaLowWaterChk = 0;
+- for (i = 0; i < MAX_PORTS; i++) {
+- p = &moxa_ports[i];
+- p->chkPort = 0;
+- p->lowChkFlag = 0;
+- p->lineCtrl = 0;
+- moxaLog.rxcnt[i] = 0;
+- moxaLog.txcnt[i] = 0;
+- }
+-}
+-
+-#define MOXA 0x400
+-#define MOXA_GET_IQUEUE (MOXA + 1) /* get input buffered count */
+-#define MOXA_GET_OQUEUE (MOXA + 2) /* get output buffered count */
+-#define MOXA_INIT_DRIVER (MOXA + 6) /* moxaCard=0 */
+-#define MOXA_LOAD_BIOS (MOXA + 9) /* download BIOS */
+-#define MOXA_FIND_BOARD (MOXA + 10) /* Check if MOXA card exist? */
+-#define MOXA_LOAD_C320B (MOXA + 11) /* download 320B firmware */
+-#define MOXA_LOAD_CODE (MOXA + 12) /* download firmware */
+-#define MOXA_GETDATACOUNT (MOXA + 23)
+-#define MOXA_GET_IOQUEUE (MOXA + 27)
+-#define MOXA_FLUSH_QUEUE (MOXA + 28)
+-#define MOXA_GET_CONF (MOXA + 35) /* configuration */
+-#define MOXA_GET_MAJOR (MOXA + 63)
+-#define MOXA_GET_CUMAJOR (MOXA + 64)
+-#define MOXA_GETMSTATUS (MOXA + 65)
+-
+-struct dl_str {
+- char __user *buf;
+- int len;
+- int cardno;
+-};
+-
+-static struct dl_str dltmp;
+-
+-void MoxaPortFlushData(int port, int mode)
++static void MoxaPortFlushData(struct moxa_port *port, int mode)
+ {
+ void __iomem *ofsAddr;
+- if ((mode < 0) || (mode > 2))
++ if (mode < 0 || mode > 2)
+ return;
+- ofsAddr = moxa_ports[port].tableAddr;
++ ofsAddr = port->tableAddr;
+ moxafunc(ofsAddr, FC_FlushQueue, mode);
+ if (mode != 1) {
+- moxa_ports[port].lowChkFlag = 0;
++ port->lowChkFlag = 0;
+ moxa_low_water_check(ofsAddr);
+ }
+ }
+
+-int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port)
+-{
+- int i;
+- int status;
+- int MoxaPortTxQueue(int), MoxaPortRxQueue(int);
+- void __user *argp = (void __user *)arg;
+-
+- if (port == MAX_PORTS) {
+- if ((cmd != MOXA_GET_CONF) && (cmd != MOXA_INIT_DRIVER) &&
+- (cmd != MOXA_LOAD_BIOS) && (cmd != MOXA_FIND_BOARD) && (cmd != MOXA_LOAD_C320B) &&
+- (cmd != MOXA_LOAD_CODE) && (cmd != MOXA_GETDATACOUNT) &&
+- (cmd != MOXA_GET_IOQUEUE) && (cmd != MOXA_GET_MAJOR) &&
+- (cmd != MOXA_GET_CUMAJOR) && (cmd != MOXA_GETMSTATUS))
+- return (-EINVAL);
+- }
+- switch (cmd) {
+- case MOXA_GET_CONF:
+- if(copy_to_user(argp, &moxa_boards, MAX_BOARDS *
+- sizeof(struct moxa_board_conf)))
+- return -EFAULT;
+- return (0);
+- case MOXA_INIT_DRIVER:
+- if ((int) arg == 0x404)
+- MoxaDriverInit();
+- return (0);
+- case MOXA_GETDATACOUNT:
+- moxaLog.tick = jiffies;
+- if(copy_to_user(argp, &moxaLog, sizeof(struct mon_str)))
+- return -EFAULT;
+- return (0);
+- case MOXA_FLUSH_QUEUE:
+- MoxaPortFlushData(port, arg);
+- return (0);
+- case MOXA_GET_IOQUEUE: {
+- struct moxaq_str __user *argm = argp;
+- struct moxaq_str tmp;
+-
+- for (i = 0; i < MAX_PORTS; i++, argm++) {
+- memset(&tmp, 0, sizeof(tmp));
+- if (moxa_ports[i].chkPort) {
+- tmp.inq = MoxaPortRxQueue(i);
+- tmp.outq = MoxaPortTxQueue(i);
+- }
+- if (copy_to_user(argm, &tmp, sizeof(tmp)))
+- return -EFAULT;
+- }
+- return (0);
+- } case MOXA_GET_OQUEUE:
+- i = MoxaPortTxQueue(port);
+- return put_user(i, (unsigned long __user *)argp);
+- case MOXA_GET_IQUEUE:
+- i = MoxaPortRxQueue(port);
+- return put_user(i, (unsigned long __user *)argp);
+- case MOXA_GET_MAJOR:
+- if(copy_to_user(argp, &ttymajor, sizeof(int)))
+- return -EFAULT;
+- return 0;
+- case MOXA_GET_CUMAJOR:
+- i = 0;
+- if(copy_to_user(argp, &i, sizeof(int)))
+- return -EFAULT;
+- return 0;
+- case MOXA_GETMSTATUS: {
+- struct mxser_mstatus __user *argm = argp;
+- struct mxser_mstatus tmp;
+- struct moxa_port *p;
+-
+- for (i = 0; i < MAX_PORTS; i++, argm++) {
+- p = &moxa_ports[i];
+- memset(&tmp, 0, sizeof(tmp));
+- if (!p->chkPort) {
+- goto copy;
+- } else {
+- status = MoxaPortLineStatus(p->port);
+- if (status & 1)
+- tmp.cts = 1;
+- if (status & 2)
+- tmp.dsr = 1;
+- if (status & 4)
+- tmp.dcd = 1;
+- }
+-
+- if (!p->tty || !p->tty->termios)
+- tmp.cflag = p->cflag;
+- else
+- tmp.cflag = p->tty->termios->c_cflag;
+-copy:
+- if (copy_to_user(argm, &tmp, sizeof(tmp)))
+- return -EFAULT;
+- }
+- return 0;
+- } default:
+- return (-ENOIOCTLCMD);
+- case MOXA_LOAD_BIOS:
+- case MOXA_FIND_BOARD:
+- case MOXA_LOAD_C320B:
+- case MOXA_LOAD_CODE:
+- if (!capable(CAP_SYS_RAWIO))
+- return -EPERM;
+- break;
+- }
+-
+- if(copy_from_user(&dltmp, argp, sizeof(struct dl_str)))
+- return -EFAULT;
+- if(dltmp.cardno < 0 || dltmp.cardno >= MAX_BOARDS || dltmp.len < 0)
+- return -EINVAL;
+-
+- switch(cmd)
+- {
+- case MOXA_LOAD_BIOS:
+- i = moxaloadbios(dltmp.cardno, dltmp.buf, dltmp.len);
+- return (i);
+- case MOXA_FIND_BOARD:
+- return moxafindcard(dltmp.cardno);
+- case MOXA_LOAD_C320B:
+- moxaload320b(dltmp.cardno, dltmp.buf, dltmp.len);
+- default: /* to keep gcc happy */
+- return (0);
+- case MOXA_LOAD_CODE:
+- i = moxaloadcode(dltmp.cardno, dltmp.buf, dltmp.len);
+- if (i == -1)
+- return (-EFAULT);
+- return (i);
+-
+- }
+-}
+-
+-int MoxaDriverPoll(void)
+-{
+- struct moxa_board_conf *brd;
+- register ushort temp;
+- register int card;
+- void __iomem *ofsAddr;
+- void __iomem *ip;
+- int port, p, ports;
+-
+- if (moxaCard == 0)
+- return (-1);
+- for (card = 0; card < MAX_BOARDS; card++) {
+- brd = &moxa_boards[card];
+- if (brd->loadstat == 0)
+- continue;
+- if ((ports = brd->numPorts) == 0)
+- continue;
+- if (readb(brd->intPend) == 0xff) {
+- ip = brd->intTable + readb(brd->intNdx);
+- p = card * MAX_PORTS_PER_BOARD;
+- ports <<= 1;
+- for (port = 0; port < ports; port += 2, p++) {
+- if ((temp = readw(ip + port)) != 0) {
+- writew(0, ip + port);
+- ofsAddr = moxa_ports[p].tableAddr;
+- if (temp & IntrTx)
+- writew(readw(ofsAddr + HostStat) & ~WakeupTx, ofsAddr + HostStat);
+- if (temp & IntrBreak) {
+- moxa_ports[p].breakCnt++;
+- }
+- if (temp & IntrLine) {
+- if (readb(ofsAddr + FlagStat) & DCD_state) {
+- if ((moxa_ports[p].DCDState & DCD_oldstate) == 0)
+- moxa_ports[p].DCDState = (DCD_oldstate |
+- DCD_changed);
+- } else {
+- if (moxa_ports[p].DCDState & DCD_oldstate)
+- moxa_ports[p].DCDState = DCD_changed;
+- }
+- }
+- }
+- }
+- writeb(0, brd->intPend);
+- }
+- if (moxaLowWaterChk) {
+- p = card * MAX_PORTS_PER_BOARD;
+- for (port = 0; port < ports; port++, p++) {
+- if (moxa_ports[p].lowChkFlag) {
+- moxa_ports[p].lowChkFlag = 0;
+- ofsAddr = moxa_ports[p].tableAddr;
+- moxa_low_water_check(ofsAddr);
+- }
+- }
+- }
+- }
+- moxaLowWaterChk = 0;
+- return (0);
+-}
+-
+-/*****************************************************************************
+- * Card level function: *
+- * 1. MoxaPortsOfCard(int cardno); *
+- *****************************************************************************/
+-int MoxaPortsOfCard(int cardno)
+-{
+-
+- if (moxa_boards[cardno].boardType == 0)
+- return (0);
+- return (moxa_boards[cardno].numPorts);
+-}
+-
+-/*****************************************************************************
+- * Port level functions: *
+- * 1. MoxaPortIsValid(int port); *
+- * 2. MoxaPortEnable(int port); *
+- * 3. MoxaPortDisable(int port); *
+- * 4. MoxaPortGetMaxBaud(int port); *
+- * 6. MoxaPortSetBaud(int port, long baud); *
+- * 8. MoxaPortSetTermio(int port, unsigned char *termio); *
+- * 9. MoxaPortGetLineOut(int port, int *dtrState, int *rtsState); *
+- * 10. MoxaPortLineCtrl(int port, int dtrState, int rtsState); *
+- * 11. MoxaPortFlowCtrl(int port, int rts, int cts, int rx, int tx,int xany); *
+- * 12. MoxaPortLineStatus(int port); *
+- * 13. MoxaPortDCDChange(int port); *
+- * 14. MoxaPortDCDON(int port); *
+- * 15. MoxaPortFlushData(int port, int mode); *
+- * 16. MoxaPortWriteData(int port, unsigned char * buffer, int length); *
+- * 17. MoxaPortReadData(int port, struct tty_struct *tty); *
+- * 20. MoxaPortTxQueue(int port); *
+- * 21. MoxaPortTxFree(int port); *
+- * 22. MoxaPortRxQueue(int port); *
+- * 24. MoxaPortTxDisable(int port); *
+- * 25. MoxaPortTxEnable(int port); *
+- * 27. MoxaPortResetBrkCnt(int port); *
+- * 30. MoxaPortSendBreak(int port, int ticks); *
+- *****************************************************************************/
+ /*
+ * Moxa Port Number Description:
+ *
+@@ -1733,33 +1637,6 @@ int MoxaPortsOfCard(int cardno)
+ * -ENOIOCTLCMD
+ *
+ *
+- * Function 3: Moxa driver polling process routine.
+- * Syntax:
+- * int MoxaDriverPoll(void);
+- *
+- * return: 0 ; polling O.K.
+- * -1 : no any Moxa card.
+- *
+- *
+- * Function 4: Get the ports of this card.
+- * Syntax:
+- * int MoxaPortsOfCard(int cardno);
+- *
+- * int cardno : card number (0 - 3)
+- *
+- * return: 0 : this card is invalid
+- * 8/16/24/32
+- *
+- *
+- * Function 5: Check this port is valid or invalid
+- * Syntax:
+- * int MoxaPortIsValid(int port);
+- * int port : port number (0 - 127, ref port description)
+- *
+- * return: 0 : this port is invalid
+- * 1 : this port is valid
+- *
+- *
+ * Function 6: Enable this port to start Tx/Rx data.
+ * Syntax:
+ * void MoxaPortEnable(int port);
+@@ -1772,18 +1649,9 @@ int MoxaPortsOfCard(int cardno)
+ * int port : port number (0 - 127)
+ *
+ *
+- * Function 8: Get the maximun available baud rate of this port.
+- * Syntax:
+- * long MoxaPortGetMaxBaud(int port);
+- * int port : port number (0 - 127)
+- *
+- * return: 0 : this port is invalid
+- * 38400/57600/115200 bps
+- *
+- *
+ * Function 10: Setting baud rate of this port.
+ * Syntax:
+- * long MoxaPortSetBaud(int port, long baud);
++ * speed_t MoxaPortSetBaud(int port, speed_t baud);
+ * int port : port number (0 - 127)
+ * long baud : baud rate (50 - 115200)
+ *
+@@ -1850,25 +1718,6 @@ int MoxaPortsOfCard(int cardno)
+ * Bit 2 - DCD state (0: off, 1: on)
+ *
+ *
+- * Function 17: Check the DCD state has changed since the last read
+- * of this function.
+- * Syntax:
+- * int MoxaPortDCDChange(int port);
+- * int port : port number (0 - 127)
+- *
+- * return: 0 : no changed
+- * 1 : DCD has changed
+- *
+- *
+- * Function 18: Check ths current DCD state is ON or not.
+- * Syntax:
+- * int MoxaPortDCDON(int port);
+- * int port : port number (0 - 127)
+- *
+- * return: 0 : DCD off
+- * 1 : DCD on
+- *
+- *
+ * Function 19: Flush the Rx/Tx buffer data of this port.
+ * Syntax:
+ * void MoxaPortFlushData(int port, int mode);
+@@ -1942,40 +1791,20 @@ int MoxaPortsOfCard(int cardno)
+ * return: 0 - .. : BREAK signal count
+ *
+ *
+- * Function 34: Send out a BREAK signal.
+- * Syntax:
+- * void MoxaPortSendBreak(int port, int ms100);
+- * int port : port number (0 - 127)
+- * int ms100 : break signal time interval.
+- * unit: 100 mini-second. if ms100 == 0, it will
+- * send out a about 250 ms BREAK signal.
+- *
+ */
+-int MoxaPortIsValid(int port)
+-{
+-
+- if (moxaCard == 0)
+- return (0);
+- if (moxa_ports[port].chkPort == 0)
+- return (0);
+- return (1);
+-}
+
+-void MoxaPortEnable(int port)
++static void MoxaPortEnable(struct moxa_port *port)
+ {
+ void __iomem *ofsAddr;
+- int MoxaPortLineStatus(int);
+- short lowwater = 512;
++ u16 lowwater = 512;
+
+- ofsAddr = moxa_ports[port].tableAddr;
++ ofsAddr = port->tableAddr;
+ writew(lowwater, ofsAddr + Low_water);
+- moxa_ports[port].breakCnt = 0;
+- if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
+- (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
++ if (MOXA_IS_320(port->board))
+ moxafunc(ofsAddr, FC_SetBreakIrq, 0);
+- } else {
+- writew(readw(ofsAddr + HostStat) | WakeupBreak, ofsAddr + HostStat);
+- }
++ else
++ writew(readw(ofsAddr + HostStat) | WakeupBreak,
++ ofsAddr + HostStat);
+
+ moxafunc(ofsAddr, FC_SetLineIrq, Magic_code);
+ moxafunc(ofsAddr, FC_FlushQueue, 2);
+@@ -1984,9 +1813,9 @@ void MoxaPortEnable(int port)
+ MoxaPortLineStatus(port);
+ }
+
+-void MoxaPortDisable(int port)
++static void MoxaPortDisable(struct moxa_port *port)
+ {
+- void __iomem *ofsAddr = moxa_ports[port].tableAddr;
++ void __iomem *ofsAddr = port->tableAddr;
+
+ moxafunc(ofsAddr, FC_SetFlowCtl, 0); /* disable flow control */
+ moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code);
+@@ -1994,49 +1823,32 @@ void MoxaPortDisable(int port)
+ moxafunc(ofsAddr, FC_DisableCH, Magic_code);
+ }
+
+-long MoxaPortGetMaxBaud(int port)
+-{
+- if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
+- (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI))
+- return (460800L);
+- else
+- return (921600L);
+-}
+-
+-
+-long MoxaPortSetBaud(int port, long baud)
++static speed_t MoxaPortSetBaud(struct moxa_port *port, speed_t baud)
+ {
+- void __iomem *ofsAddr;
+- long max, clock;
+- unsigned int val;
++ void __iomem *ofsAddr = port->tableAddr;
++ unsigned int clock, val;
++ speed_t max;
+
+- if ((baud < 50L) || ((max = MoxaPortGetMaxBaud(port)) == 0))
+- return (0);
+- ofsAddr = moxa_ports[port].tableAddr;
++ max = MOXA_IS_320(port->board) ? 460800 : 921600;
++ if (baud < 50)
++ return 0;
+ if (baud > max)
+ baud = max;
+- if (max == 38400L)
+- clock = 614400L; /* for 9.8304 Mhz : max. 38400 bps */
+- else if (max == 57600L)
+- clock = 691200L; /* for 11.0592 Mhz : max. 57600 bps */
+- else
+- clock = 921600L; /* for 14.7456 Mhz : max. 115200 bps */
++ clock = 921600;
+ val = clock / baud;
+ moxafunc(ofsAddr, FC_SetBaud, val);
+ baud = clock / val;
+- moxa_ports[port].curBaud = baud;
+- return (baud);
++ return baud;
+ }
+
+-int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud)
++static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio,
++ speed_t baud)
+ {
+ void __iomem *ofsAddr;
+ tcflag_t cflag;
+ tcflag_t mode = 0;
+
+- if (moxa_ports[port].chkPort == 0 || termio == 0)
+- return (-1);
+- ofsAddr = moxa_ports[port].tableAddr;
++ ofsAddr = port->tableAddr;
+ cflag = termio->c_cflag; /* termio->c_cflag */
+
+ mode = termio->c_cflag & CSIZE;
+@@ -2065,13 +1877,11 @@ int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud)
+ } else
+ mode |= MX_PARNONE;
+
+- moxafunc(ofsAddr, FC_SetDataMode, (ushort) mode);
++ moxafunc(ofsAddr, FC_SetDataMode, (u16)mode);
++
++ if (MOXA_IS_320(port->board) && baud >= 921600)
++ return -1;
+
+- if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
+- (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
+- if (baud >= 921600L)
+- return (-1);
+- }
+ baud = MoxaPortSetBaud(port, baud);
+
+ if (termio->c_iflag & (IXON | IXOFF | IXANY)) {
+@@ -2081,51 +1891,37 @@ int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud)
+ moxa_wait_finish(ofsAddr);
+
+ }
+- return (baud);
++ return baud;
+ }
+
+-int MoxaPortGetLineOut(int port, int *dtrState, int *rtsState)
++static int MoxaPortGetLineOut(struct moxa_port *port, int *dtrState,
++ int *rtsState)
+ {
++ if (dtrState)
++ *dtrState = !!(port->lineCtrl & DTR_ON);
++ if (rtsState)
++ *rtsState = !!(port->lineCtrl & RTS_ON);
+
+- if (!MoxaPortIsValid(port))
+- return (-1);
+- if (dtrState) {
+- if (moxa_ports[port].lineCtrl & DTR_ON)
+- *dtrState = 1;
+- else
+- *dtrState = 0;
+- }
+- if (rtsState) {
+- if (moxa_ports[port].lineCtrl & RTS_ON)
+- *rtsState = 1;
+- else
+- *rtsState = 0;
+- }
+- return (0);
++ return 0;
+ }
+
+-void MoxaPortLineCtrl(int port, int dtr, int rts)
++static void MoxaPortLineCtrl(struct moxa_port *port, int dtr, int rts)
+ {
+- void __iomem *ofsAddr;
+- int mode;
++ u8 mode = 0;
+
+- ofsAddr = moxa_ports[port].tableAddr;
+- mode = 0;
+ if (dtr)
+ mode |= DTR_ON;
+ if (rts)
+ mode |= RTS_ON;
+- moxa_ports[port].lineCtrl = mode;
+- moxafunc(ofsAddr, FC_LineControl, mode);
++ port->lineCtrl = mode;
++ moxafunc(port->tableAddr, FC_LineControl, mode);
+ }
+
+-void MoxaPortFlowCtrl(int port, int rts, int cts, int txflow, int rxflow, int txany)
++static void MoxaPortFlowCtrl(struct moxa_port *port, int rts, int cts,
++ int txflow, int rxflow, int txany)
+ {
+- void __iomem *ofsAddr;
+- int mode;
++ int mode = 0;
+
+- ofsAddr = moxa_ports[port].tableAddr;
+- mode = 0;
+ if (rts)
+ mode |= RTS_FlowCtl;
+ if (cts)
+@@ -2136,81 +1932,50 @@ void MoxaPortFlowCtrl(int port, int rts, int cts, int txflow, int rxflow, int tx
+ mode |= Rx_FlowCtl;
+ if (txany)
+ mode |= IXM_IXANY;
+- moxafunc(ofsAddr, FC_SetFlowCtl, mode);
++ moxafunc(port->tableAddr, FC_SetFlowCtl, mode);
+ }
+
+-int MoxaPortLineStatus(int port)
++static int MoxaPortLineStatus(struct moxa_port *port)
+ {
+ void __iomem *ofsAddr;
+ int val;
+
+- ofsAddr = moxa_ports[port].tableAddr;
+- if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
+- (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
++ ofsAddr = port->tableAddr;
++ if (MOXA_IS_320(port->board)) {
+ moxafunc(ofsAddr, FC_LineStatus, 0);
+ val = readw(ofsAddr + FuncArg);
+ } else {
+ val = readw(ofsAddr + FlagStat) >> 4;
+ }
+ val &= 0x0B;
+- if (val & 8) {
++ if (val & 8)
+ val |= 4;
+- if ((moxa_ports[port].DCDState & DCD_oldstate) == 0)
+- moxa_ports[port].DCDState = (DCD_oldstate | DCD_changed);
+- } else {
+- if (moxa_ports[port].DCDState & DCD_oldstate)
+- moxa_ports[port].DCDState = DCD_changed;
+- }
++ spin_lock_bh(&moxa_lock);
++ moxa_new_dcdstate(port, val & 8);
++ spin_unlock_bh(&moxa_lock);
+ val &= 7;
+- return (val);
+-}
+-
+-int MoxaPortDCDChange(int port)
+-{
+- int n;
+-
+- if (moxa_ports[port].chkPort == 0)
+- return (0);
+- n = moxa_ports[port].DCDState;
+- moxa_ports[port].DCDState &= ~DCD_changed;
+- n &= DCD_changed;
+- return (n);
+-}
+-
+-int MoxaPortDCDON(int port)
+-{
+- int n;
+-
+- if (moxa_ports[port].chkPort == 0)
+- return (0);
+- if (moxa_ports[port].DCDState & DCD_oldstate)
+- n = 1;
+- else
+- n = 0;
+- return (n);
++ return val;
+ }
+
+-int MoxaPortWriteData(int port, unsigned char * buffer, int len)
++static int MoxaPortWriteData(struct moxa_port *port,
++ const unsigned char *buffer, int len)
+ {
+- int c, total, i;
+- ushort tail;
+- int cnt;
+- ushort head, tx_mask, spage, epage;
+- ushort pageno, pageofs, bufhead;
+ void __iomem *baseAddr, *ofsAddr, *ofs;
++ unsigned int c, total;
++ u16 head, tail, tx_mask, spage, epage;
++ u16 pageno, pageofs, bufhead;
+
+- ofsAddr = moxa_ports[port].tableAddr;
+- baseAddr = moxa_boards[port / MAX_PORTS_PER_BOARD].basemem;
++ ofsAddr = port->tableAddr;
++ baseAddr = port->board->basemem;
+ tx_mask = readw(ofsAddr + TX_mask);
+ spage = readw(ofsAddr + Page_txb);
+ epage = readw(ofsAddr + EndPage_txb);
+ tail = readw(ofsAddr + TXwptr);
+ head = readw(ofsAddr + TXrptr);
+- c = (head > tail) ? (head - tail - 1)
+- : (head - tail + tx_mask);
++ c = (head > tail) ? (head - tail - 1) : (head - tail + tx_mask);
+ if (c > len)
+ c = len;
+- moxaLog.txcnt[port] += c;
++ moxaLog.txcnt[port->tty->index] += c;
+ total = c;
+ if (spage == epage) {
+ bufhead = readw(ofsAddr + Ofs_txb);
+@@ -2222,249 +1987,179 @@ int MoxaPortWriteData(int port, unsigned char * buffer, int len)
+ len = tx_mask + 1 - tail;
+ len = (c > len) ? len : c;
+ ofs = baseAddr + DynPage_addr + bufhead + tail;
+- for (i = 0; i < len; i++)
+- writeb(*buffer++, ofs + i);
++ memcpy_toio(ofs, buffer, len);
++ buffer += len;
+ tail = (tail + len) & tx_mask;
+ c -= len;
+ }
+- writew(tail, ofsAddr + TXwptr);
+ } else {
+- len = c;
+ pageno = spage + (tail >> 13);
+ pageofs = tail & Page_mask;
+- do {
+- cnt = Page_size - pageofs;
+- if (cnt > c)
+- cnt = c;
+- c -= cnt;
++ while (c > 0) {
++ len = Page_size - pageofs;
++ if (len > c)
++ len = c;
+ writeb(pageno, baseAddr + Control_reg);
+ ofs = baseAddr + DynPage_addr + pageofs;
+- for (i = 0; i < cnt; i++)
+- writeb(*buffer++, ofs + i);
+- if (c == 0) {
+- writew((tail + len) & tx_mask, ofsAddr + TXwptr);
+- break;
+- }
++ memcpy_toio(ofs, buffer, len);
++ buffer += len;
+ if (++pageno == epage)
+ pageno = spage;
+ pageofs = 0;
+- } while (1);
++ c -= len;
++ }
++ tail = (tail + total) & tx_mask;
+ }
++ writew(tail, ofsAddr + TXwptr);
+ writeb(1, ofsAddr + CD180TXirq); /* start to send */
+- return (total);
++ return total;
+ }
+
+-int MoxaPortReadData(int port, struct tty_struct *tty)
++static int MoxaPortReadData(struct moxa_port *port)
+ {
+- register ushort head, pageofs;
+- int i, count, cnt, len, total, remain;
+- ushort tail, rx_mask, spage, epage;
+- ushort pageno, bufhead;
++ struct tty_struct *tty = port->tty;
++ unsigned char *dst;
+ void __iomem *baseAddr, *ofsAddr, *ofs;
++ unsigned int count, len, total;
++ u16 tail, rx_mask, spage, epage;
++ u16 pageno, pageofs, bufhead, head;
+
+- ofsAddr = moxa_ports[port].tableAddr;
+- baseAddr = moxa_boards[port / MAX_PORTS_PER_BOARD].basemem;
++ ofsAddr = port->tableAddr;
++ baseAddr = port->board->basemem;
+ head = readw(ofsAddr + RXrptr);
+ tail = readw(ofsAddr + RXwptr);
+ rx_mask = readw(ofsAddr + RX_mask);
+ spage = readw(ofsAddr + Page_rxb);
+ epage = readw(ofsAddr + EndPage_rxb);
+- count = (tail >= head) ? (tail - head)
+- : (tail - head + rx_mask + 1);
++ count = (tail >= head) ? (tail - head) : (tail - head + rx_mask + 1);
+ if (count == 0)
+ return 0;
+
+ total = count;
+- remain = count - total;
+- moxaLog.rxcnt[port] += total;
+- count = total;
++ moxaLog.rxcnt[tty->index] += total;
+ if (spage == epage) {
+ bufhead = readw(ofsAddr + Ofs_rxb);
+ writew(spage, baseAddr + Control_reg);
+ while (count > 0) {
+- if (tail >= head)
+- len = tail - head;
+- else
+- len = rx_mask + 1 - head;
+- len = (count > len) ? len : count;
+ ofs = baseAddr + DynPage_addr + bufhead + head;
+- for (i = 0; i < len; i++)
+- tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL);
++ len = (tail >= head) ? (tail - head) :
++ (rx_mask + 1 - head);
++ len = tty_prepare_flip_string(tty, &dst,
++ min(len, count));
++ memcpy_fromio(dst, ofs, len);
+ head = (head + len) & rx_mask;
+ count -= len;
+ }
+- writew(head, ofsAddr + RXrptr);
+ } else {
+- len = count;
+ pageno = spage + (head >> 13);
+ pageofs = head & Page_mask;
+- do {
+- cnt = Page_size - pageofs;
+- if (cnt > count)
+- cnt = count;
+- count -= cnt;
++ while (count > 0) {
+ writew(pageno, baseAddr + Control_reg);
+ ofs = baseAddr + DynPage_addr + pageofs;
+- for (i = 0; i < cnt; i++)
+- tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL);
+- if (count == 0) {
+- writew((head + len) & rx_mask, ofsAddr + RXrptr);
+- break;
+- }
+- if (++pageno == epage)
++ len = tty_prepare_flip_string(tty, &dst,
++ min(Page_size - pageofs, count));
++ memcpy_fromio(dst, ofs, len);
++
++ count -= len;
++ pageofs = (pageofs + len) & Page_mask;
++ if (pageofs == 0 && ++pageno == epage)
+ pageno = spage;
+- pageofs = 0;
+- } while (1);
++ }
++ head = (head + total) & rx_mask;
+ }
+- if ((readb(ofsAddr + FlagStat) & Xoff_state) && (remain < LowWater)) {
++ writew(head, ofsAddr + RXrptr);
++ if (readb(ofsAddr + FlagStat) & Xoff_state) {
+ moxaLowWaterChk = 1;
+- moxa_ports[port].lowChkFlag = 1;
++ port->lowChkFlag = 1;
+ }
+- return (total);
++ return total;
+ }
+
+
+-int MoxaPortTxQueue(int port)
++static int MoxaPortTxQueue(struct moxa_port *port)
+ {
+- void __iomem *ofsAddr;
+- ushort rptr, wptr, mask;
+- int len;
++ void __iomem *ofsAddr = port->tableAddr;
++ u16 rptr, wptr, mask;
+
+- ofsAddr = moxa_ports[port].tableAddr;
+ rptr = readw(ofsAddr + TXrptr);
+ wptr = readw(ofsAddr + TXwptr);
+ mask = readw(ofsAddr + TX_mask);
+- len = (wptr - rptr) & mask;
+- return (len);
++ return (wptr - rptr) & mask;
+ }
+
+-int MoxaPortTxFree(int port)
++static int MoxaPortTxFree(struct moxa_port *port)
+ {
+- void __iomem *ofsAddr;
+- ushort rptr, wptr, mask;
+- int len;
++ void __iomem *ofsAddr = port->tableAddr;
++ u16 rptr, wptr, mask;
+
+- ofsAddr = moxa_ports[port].tableAddr;
+ rptr = readw(ofsAddr + TXrptr);
+ wptr = readw(ofsAddr + TXwptr);
+ mask = readw(ofsAddr + TX_mask);
+- len = mask - ((wptr - rptr) & mask);
+- return (len);
++ return mask - ((wptr - rptr) & mask);
+ }
+
+-int MoxaPortRxQueue(int port)
++static int MoxaPortRxQueue(struct moxa_port *port)
+ {
+- void __iomem *ofsAddr;
+- ushort rptr, wptr, mask;
+- int len;
++ void __iomem *ofsAddr = port->tableAddr;
++ u16 rptr, wptr, mask;
+
+- ofsAddr = moxa_ports[port].tableAddr;
+ rptr = readw(ofsAddr + RXrptr);
+ wptr = readw(ofsAddr + RXwptr);
+ mask = readw(ofsAddr + RX_mask);
+- len = (wptr - rptr) & mask;
+- return (len);
++ return (wptr - rptr) & mask;
+ }
+
+-
+-void MoxaPortTxDisable(int port)
++static void MoxaPortTxDisable(struct moxa_port *port)
+ {
+- void __iomem *ofsAddr;
+-
+- ofsAddr = moxa_ports[port].tableAddr;
+- moxafunc(ofsAddr, FC_SetXoffState, Magic_code);
++ moxafunc(port->tableAddr, FC_SetXoffState, Magic_code);
+ }
+
+-void MoxaPortTxEnable(int port)
++static void MoxaPortTxEnable(struct moxa_port *port)
+ {
+- void __iomem *ofsAddr;
+-
+- ofsAddr = moxa_ports[port].tableAddr;
+- moxafunc(ofsAddr, FC_SetXonState, Magic_code);
+-}
+-
+-
+-int MoxaPortResetBrkCnt(int port)
+-{
+- ushort cnt;
+- cnt = moxa_ports[port].breakCnt;
+- moxa_ports[port].breakCnt = 0;
+- return (cnt);
+-}
+-
+-
+-void MoxaPortSendBreak(int port, int ms100)
+-{
+- void __iomem *ofsAddr;
+-
+- ofsAddr = moxa_ports[port].tableAddr;
+- if (ms100) {
+- moxafunc(ofsAddr, FC_SendBreak, Magic_code);
+- msleep(ms100 * 10);
+- } else {
+- moxafunc(ofsAddr, FC_SendBreak, Magic_code);
+- msleep(250);
+- }
+- moxafunc(ofsAddr, FC_StopBreak, Magic_code);
++ moxafunc(port->tableAddr, FC_SetXonState, Magic_code);
+ }
+
+ static int moxa_get_serial_info(struct moxa_port *info,
+- struct serial_struct __user *retinfo)
++ struct serial_struct __user *retinfo)
+ {
+- struct serial_struct tmp;
+-
+- memset(&tmp, 0, sizeof(tmp));
+- tmp.type = info->type;
+- tmp.line = info->port;
+- tmp.port = 0;
+- tmp.irq = 0;
+- tmp.flags = info->asyncflags;
+- tmp.baud_base = 921600;
+- tmp.close_delay = info->close_delay;
+- tmp.closing_wait = info->closing_wait;
+- tmp.custom_divisor = 0;
+- tmp.hub6 = 0;
+- if(copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+- return -EFAULT;
+- return (0);
++ struct serial_struct tmp = {
++ .type = info->type,
++ .line = info->tty->index,
++ .flags = info->asyncflags,
++ .baud_base = 921600,
++ .close_delay = info->close_delay
++ };
++ return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
+ }
+
+
+ static int moxa_set_serial_info(struct moxa_port *info,
+- struct serial_struct __user *new_info)
++ struct serial_struct __user *new_info)
+ {
+ struct serial_struct new_serial;
+
+- if(copy_from_user(&new_serial, new_info, sizeof(new_serial)))
++ if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
+ return -EFAULT;
+
+- if ((new_serial.irq != 0) ||
+- (new_serial.port != 0) ||
+-// (new_serial.type != info->type) ||
+- (new_serial.custom_divisor != 0) ||
+- (new_serial.baud_base != 921600))
+- return (-EPERM);
++ if (new_serial.irq != 0 || new_serial.port != 0 ||
++ new_serial.custom_divisor != 0 ||
++ new_serial.baud_base != 921600)
++ return -EPERM;
+
+ if (!capable(CAP_SYS_ADMIN)) {
+ if (((new_serial.flags & ~ASYNC_USR_MASK) !=
+ (info->asyncflags & ~ASYNC_USR_MASK)))
+- return (-EPERM);
+- } else {
++ return -EPERM;
++ } else
+ info->close_delay = new_serial.close_delay * HZ / 100;
+- info->closing_wait = new_serial.closing_wait * HZ / 100;
+- }
+
+ new_serial.flags = (new_serial.flags & ~ASYNC_FLAGS);
+ new_serial.flags |= (info->asyncflags & ASYNC_FLAGS);
+
+- if (new_serial.type == PORT_16550A) {
+- MoxaSetFifo(info->port, 1);
+- } else {
+- MoxaSetFifo(info->port, 0);
+- }
++ MoxaSetFifo(info, new_serial.type == PORT_16550A);
+
+ info->type = new_serial.type;
+- return (0);
++ return 0;
+ }
+
+
+@@ -2472,374 +2167,10 @@ static int moxa_set_serial_info(struct moxa_port *info,
+ /*****************************************************************************
+ * Static local functions: *
+ *****************************************************************************/
+-static void moxafunc(void __iomem *ofsAddr, int cmd, ushort arg)
+-{
+-
+- writew(arg, ofsAddr + FuncArg);
+- writew(cmd, ofsAddr + FuncCode);
+- moxa_wait_finish(ofsAddr);
+-}
+-
+-static void moxa_wait_finish(void __iomem *ofsAddr)
+-{
+- unsigned long i, j;
+-
+- i = jiffies;
+- while (readw(ofsAddr + FuncCode) != 0) {
+- j = jiffies;
+- if ((j - i) > moxaFuncTout) {
+- return;
+- }
+- }
+-}
+-
+-static void moxa_low_water_check(void __iomem *ofsAddr)
+-{
+- int len;
+- ushort rptr, wptr, mask;
+-
+- if (readb(ofsAddr + FlagStat) & Xoff_state) {
+- rptr = readw(ofsAddr + RXrptr);
+- wptr = readw(ofsAddr + RXwptr);
+- mask = readw(ofsAddr + RX_mask);
+- len = (wptr - rptr) & mask;
+- if (len <= Low_water)
+- moxafunc(ofsAddr, FC_SendXon, 0);
+- }
+-}
+-
+-static int moxaloadbios(int cardno, unsigned char __user *tmp, int len)
+-{
+- void __iomem *baseAddr;
+- int i;
+-
+- if(len < 0 || len > sizeof(moxaBuff))
+- return -EINVAL;
+- if(copy_from_user(moxaBuff, tmp, len))
+- return -EFAULT;
+- baseAddr = moxa_boards[cardno].basemem;
+- writeb(HW_reset, baseAddr + Control_reg); /* reset */
+- msleep(10);
+- for (i = 0; i < 4096; i++)
+- writeb(0, baseAddr + i); /* clear fix page */
+- for (i = 0; i < len; i++)
+- writeb(moxaBuff[i], baseAddr + i); /* download BIOS */
+- writeb(0, baseAddr + Control_reg); /* restart */
+- return (0);
+-}
+-
+-static int moxafindcard(int cardno)
+-{
+- void __iomem *baseAddr;
+- ushort tmp;
+-
+- baseAddr = moxa_boards[cardno].basemem;
+- switch (moxa_boards[cardno].boardType) {
+- case MOXA_BOARD_C218_ISA:
+- case MOXA_BOARD_C218_PCI:
+- if ((tmp = readw(baseAddr + C218_key)) != C218_KeyCode) {
+- return (-1);
+- }
+- break;
+- case MOXA_BOARD_CP204J:
+- if ((tmp = readw(baseAddr + C218_key)) != CP204J_KeyCode) {
+- return (-1);
+- }
+- break;
+- default:
+- if ((tmp = readw(baseAddr + C320_key)) != C320_KeyCode) {
+- return (-1);
+- }
+- if ((tmp = readw(baseAddr + C320_status)) != STS_init) {
+- return (-2);
+- }
+- }
+- return (0);
+-}
+-
+-static int moxaload320b(int cardno, unsigned char __user *tmp, int len)
+-{
+- void __iomem *baseAddr;
+- int i;
+-
+- if(len < 0 || len > sizeof(moxaBuff))
+- return -EINVAL;
+- if(copy_from_user(moxaBuff, tmp, len))
+- return -EFAULT;
+- baseAddr = moxa_boards[cardno].basemem;
+- writew(len - 7168 - 2, baseAddr + C320bapi_len);
+- writeb(1, baseAddr + Control_reg); /* Select Page 1 */
+- for (i = 0; i < 7168; i++)
+- writeb(moxaBuff[i], baseAddr + DynPage_addr + i);
+- writeb(2, baseAddr + Control_reg); /* Select Page 2 */
+- for (i = 0; i < (len - 7168); i++)
+- writeb(moxaBuff[i + 7168], baseAddr + DynPage_addr + i);
+- return (0);
+-}
+-
+-static int moxaloadcode(int cardno, unsigned char __user *tmp, int len)
+-{
+- void __iomem *baseAddr, *ofsAddr;
+- int retval, port, i;
+-
+- if(len < 0 || len > sizeof(moxaBuff))
+- return -EINVAL;
+- if(copy_from_user(moxaBuff, tmp, len))
+- return -EFAULT;
+- baseAddr = moxa_boards[cardno].basemem;
+- switch (moxa_boards[cardno].boardType) {
+- case MOXA_BOARD_C218_ISA:
+- case MOXA_BOARD_C218_PCI:
+- case MOXA_BOARD_CP204J:
+- retval = moxaloadc218(cardno, baseAddr, len);
+- if (retval)
+- return (retval);
+- port = cardno * MAX_PORTS_PER_BOARD;
+- for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) {
+- struct moxa_port *p = &moxa_ports[port];
+-
+- p->chkPort = 1;
+- p->curBaud = 9600L;
+- p->DCDState = 0;
+- p->tableAddr = baseAddr + Extern_table + Extern_size * i;
+- ofsAddr = p->tableAddr;
+- writew(C218rx_mask, ofsAddr + RX_mask);
+- writew(C218tx_mask, ofsAddr + TX_mask);
+- writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb);
+- writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb);
+-
+- writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb);
+- writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb);
+-
+- }
+- break;
+- default:
+- retval = moxaloadc320(cardno, baseAddr, len,
+- &moxa_boards[cardno].numPorts);
+- if (retval)
+- return (retval);
+- port = cardno * MAX_PORTS_PER_BOARD;
+- for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) {
+- struct moxa_port *p = &moxa_ports[port];
+-
+- p->chkPort = 1;
+- p->curBaud = 9600L;
+- p->DCDState = 0;
+- p->tableAddr = baseAddr + Extern_table + Extern_size * i;
+- ofsAddr = p->tableAddr;
+- if (moxa_boards[cardno].numPorts == 8) {
+- writew(C320p8rx_mask, ofsAddr + RX_mask);
+- writew(C320p8tx_mask, ofsAddr + TX_mask);
+- writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb);
+- writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb);
+- writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb);
+- writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb);
+-
+- } else if (moxa_boards[cardno].numPorts == 16) {
+- writew(C320p16rx_mask, ofsAddr + RX_mask);
+- writew(C320p16tx_mask, ofsAddr + TX_mask);
+- writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb);
+- writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb);
+- writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb);
+- writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb);
+-
+- } else if (moxa_boards[cardno].numPorts == 24) {
+- writew(C320p24rx_mask, ofsAddr + RX_mask);
+- writew(C320p24tx_mask, ofsAddr + TX_mask);
+- writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb);
+- writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb);
+- writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb);
+- writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
+- } else if (moxa_boards[cardno].numPorts == 32) {
+- writew(C320p32rx_mask, ofsAddr + RX_mask);
+- writew(C320p32tx_mask, ofsAddr + TX_mask);
+- writew(C320p32tx_ofs, ofsAddr + Ofs_txb);
+- writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb);
+- writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb);
+- writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb);
+- writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
+- }
+- }
+- break;
+- }
+- moxa_boards[cardno].loadstat = 1;
+- return (0);
+-}
+-
+-static int moxaloadc218(int cardno, void __iomem *baseAddr, int len)
+-{
+- char retry;
+- int i, j, len1, len2;
+- ushort usum, *ptr, keycode;
+-
+- if (moxa_boards[cardno].boardType == MOXA_BOARD_CP204J)
+- keycode = CP204J_KeyCode;
+- else
+- keycode = C218_KeyCode;
+- usum = 0;
+- len1 = len >> 1;
+- ptr = (ushort *) moxaBuff;
+- for (i = 0; i < len1; i++)
+- usum += le16_to_cpu(*(ptr + i));
+- retry = 0;
+- do {
+- len1 = len >> 1;
+- j = 0;
+- while (len1) {
+- len2 = (len1 > 2048) ? 2048 : len1;
+- len1 -= len2;
+- for (i = 0; i < len2 << 1; i++)
+- writeb(moxaBuff[i + j], baseAddr + C218_LoadBuf + i);
+- j += i;
+-
+- writew(len2, baseAddr + C218DLoad_len);
+- writew(0, baseAddr + C218_key);
+- for (i = 0; i < 100; i++) {
+- if (readw(baseAddr + C218_key) == keycode)
+- break;
+- msleep(10);
+- }
+- if (readw(baseAddr + C218_key) != keycode) {
+- return (-1);
+- }
+- }
+- writew(0, baseAddr + C218DLoad_len);
+- writew(usum, baseAddr + C218check_sum);
+- writew(0, baseAddr + C218_key);
+- for (i = 0; i < 100; i++) {
+- if (readw(baseAddr + C218_key) == keycode)
+- break;
+- msleep(10);
+- }
+- retry++;
+- } while ((readb(baseAddr + C218chksum_ok) != 1) && (retry < 3));
+- if (readb(baseAddr + C218chksum_ok) != 1) {
+- return (-1);
+- }
+- writew(0, baseAddr + C218_key);
+- for (i = 0; i < 100; i++) {
+- if (readw(baseAddr + Magic_no) == Magic_code)
+- break;
+- msleep(10);
+- }
+- if (readw(baseAddr + Magic_no) != Magic_code) {
+- return (-1);
+- }
+- writew(1, baseAddr + Disable_IRQ);
+- writew(0, baseAddr + Magic_no);
+- for (i = 0; i < 100; i++) {
+- if (readw(baseAddr + Magic_no) == Magic_code)
+- break;
+- msleep(10);
+- }
+- if (readw(baseAddr + Magic_no) != Magic_code) {
+- return (-1);
+- }
+- moxaCard = 1;
+- moxa_boards[cardno].intNdx = baseAddr + IRQindex;
+- moxa_boards[cardno].intPend = baseAddr + IRQpending;
+- moxa_boards[cardno].intTable = baseAddr + IRQtable;
+- return (0);
+-}
+-
+-static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPorts)
+-{
+- ushort usum;
+- int i, j, wlen, len2, retry;
+- ushort *uptr;
+-
+- usum = 0;
+- wlen = len >> 1;
+- uptr = (ushort *) moxaBuff;
+- for (i = 0; i < wlen; i++)
+- usum += le16_to_cpu(uptr[i]);
+- retry = 0;
+- j = 0;
+- do {
+- while (wlen) {
+- if (wlen > 2048)
+- len2 = 2048;
+- else
+- len2 = wlen;
+- wlen -= len2;
+- len2 <<= 1;
+- for (i = 0; i < len2; i++)
+- writeb(moxaBuff[j + i], baseAddr + C320_LoadBuf + i);
+- len2 >>= 1;
+- j += i;
+- writew(len2, baseAddr + C320DLoad_len);
+- writew(0, baseAddr + C320_key);
+- for (i = 0; i < 10; i++) {
+- if (readw(baseAddr + C320_key) == C320_KeyCode)
+- break;
+- msleep(10);
+- }
+- if (readw(baseAddr + C320_key) != C320_KeyCode)
+- return (-1);
+- }
+- writew(0, baseAddr + C320DLoad_len);
+- writew(usum, baseAddr + C320check_sum);
+- writew(0, baseAddr + C320_key);
+- for (i = 0; i < 10; i++) {
+- if (readw(baseAddr + C320_key) == C320_KeyCode)
+- break;
+- msleep(10);
+- }
+- retry++;
+- } while ((readb(baseAddr + C320chksum_ok) != 1) && (retry < 3));
+- if (readb(baseAddr + C320chksum_ok) != 1)
+- return (-1);
+- writew(0, baseAddr + C320_key);
+- for (i = 0; i < 600; i++) {
+- if (readw(baseAddr + Magic_no) == Magic_code)
+- break;
+- msleep(10);
+- }
+- if (readw(baseAddr + Magic_no) != Magic_code)
+- return (-100);
+-
+- if (moxa_boards[cardno].busType == MOXA_BUS_TYPE_PCI) { /* ASIC board */
+- writew(0x3800, baseAddr + TMS320_PORT1);
+- writew(0x3900, baseAddr + TMS320_PORT2);
+- writew(28499, baseAddr + TMS320_CLOCK);
+- } else {
+- writew(0x3200, baseAddr + TMS320_PORT1);
+- writew(0x3400, baseAddr + TMS320_PORT2);
+- writew(19999, baseAddr + TMS320_CLOCK);
+- }
+- writew(1, baseAddr + Disable_IRQ);
+- writew(0, baseAddr + Magic_no);
+- for (i = 0; i < 500; i++) {
+- if (readw(baseAddr + Magic_no) == Magic_code)
+- break;
+- msleep(10);
+- }
+- if (readw(baseAddr + Magic_no) != Magic_code)
+- return (-102);
+-
+- j = readw(baseAddr + Module_cnt);
+- if (j <= 0)
+- return (-101);
+- *numPorts = j * 8;
+- writew(j, baseAddr + Module_no);
+- writew(0, baseAddr + Magic_no);
+- for (i = 0; i < 600; i++) {
+- if (readw(baseAddr + Magic_no) == Magic_code)
+- break;
+- msleep(10);
+- }
+- if (readw(baseAddr + Magic_no) != Magic_code)
+- return (-102);
+- moxaCard = 1;
+- moxa_boards[cardno].intNdx = baseAddr + IRQindex;
+- moxa_boards[cardno].intPend = baseAddr + IRQpending;
+- moxa_boards[cardno].intTable = baseAddr + IRQtable;
+- return (0);
+-}
+
+-static void MoxaSetFifo(int port, int enable)
++static void MoxaSetFifo(struct moxa_port *port, int enable)
+ {
+- void __iomem *ofsAddr = moxa_ports[port].tableAddr;
++ void __iomem *ofsAddr = port->tableAddr;
+
+ if (!enable) {
+ moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0);
+diff --git a/drivers/char/moxa.h b/drivers/char/moxa.h
+new file mode 100644
+index 0000000..87d16ce
+--- /dev/null
++++ b/drivers/char/moxa.h
+@@ -0,0 +1,304 @@
++#ifndef MOXA_H_FILE
++#define MOXA_H_FILE
++
++#define MOXA 0x400
++#define MOXA_GET_IQUEUE (MOXA + 1) /* get input buffered count */
++#define MOXA_GET_OQUEUE (MOXA + 2) /* get output buffered count */
++#define MOXA_GETDATACOUNT (MOXA + 23)
++#define MOXA_GET_IOQUEUE (MOXA + 27)
++#define MOXA_FLUSH_QUEUE (MOXA + 28)
++#define MOXA_GETMSTATUS (MOXA + 65)
++
++/*
++ * System Configuration
++ */
++
++#define Magic_code 0x404
++
++/*
++ * for C218 BIOS initialization
++ */
++#define C218_ConfBase 0x800
++#define C218_status (C218_ConfBase + 0) /* BIOS running status */
++#define C218_diag (C218_ConfBase + 2) /* diagnostic status */
++#define C218_key (C218_ConfBase + 4) /* WORD (0x218 for C218) */
++#define C218DLoad_len (C218_ConfBase + 6) /* WORD */
++#define C218check_sum (C218_ConfBase + 8) /* BYTE */
++#define C218chksum_ok (C218_ConfBase + 0x0a) /* BYTE (1:ok) */
++#define C218_TestRx (C218_ConfBase + 0x10) /* 8 bytes for 8 ports */
++#define C218_TestTx (C218_ConfBase + 0x18) /* 8 bytes for 8 ports */
++#define C218_RXerr (C218_ConfBase + 0x20) /* 8 bytes for 8 ports */
++#define C218_ErrFlag (C218_ConfBase + 0x28) /* 8 bytes for 8 ports */
++
++#define C218_LoadBuf 0x0F00
++#define C218_KeyCode 0x218
++#define CP204J_KeyCode 0x204
++
++/*
++ * for C320 BIOS initialization
++ */
++#define C320_ConfBase 0x800
++#define C320_LoadBuf 0x0f00
++#define STS_init 0x05 /* for C320_status */
++
++#define C320_status C320_ConfBase + 0 /* BIOS running status */
++#define C320_diag C320_ConfBase + 2 /* diagnostic status */
++#define C320_key C320_ConfBase + 4 /* WORD (0320H for C320) */
++#define C320DLoad_len C320_ConfBase + 6 /* WORD */
++#define C320check_sum C320_ConfBase + 8 /* WORD */
++#define C320chksum_ok C320_ConfBase + 0x0a /* WORD (1:ok) */
++#define C320bapi_len C320_ConfBase + 0x0c /* WORD */
++#define C320UART_no C320_ConfBase + 0x0e /* WORD */
++
++#define C320_KeyCode 0x320
++
++#define FixPage_addr 0x0000 /* starting addr of static page */
++#define DynPage_addr 0x2000 /* starting addr of dynamic page */
++#define C218_start 0x3000 /* starting addr of C218 BIOS prg */
++#define Control_reg 0x1ff0 /* select page and reset control */
++#define HW_reset 0x80
++
++/*
++ * Function Codes
++ */
++#define FC_CardReset 0x80
++#define FC_ChannelReset 1 /* C320 firmware not supported */
++#define FC_EnableCH 2
++#define FC_DisableCH 3
++#define FC_SetParam 4
++#define FC_SetMode 5
++#define FC_SetRate 6
++#define FC_LineControl 7
++#define FC_LineStatus 8
++#define FC_XmitControl 9
++#define FC_FlushQueue 10
++#define FC_SendBreak 11
++#define FC_StopBreak 12
++#define FC_LoopbackON 13
++#define FC_LoopbackOFF 14
++#define FC_ClrIrqTable 15
++#define FC_SendXon 16
++#define FC_SetTermIrq 17 /* C320 firmware not supported */
++#define FC_SetCntIrq 18 /* C320 firmware not supported */
++#define FC_SetBreakIrq 19
++#define FC_SetLineIrq 20
++#define FC_SetFlowCtl 21
++#define FC_GenIrq 22
++#define FC_InCD180 23
++#define FC_OutCD180 24
++#define FC_InUARTreg 23
++#define FC_OutUARTreg 24
++#define FC_SetXonXoff 25
++#define FC_OutCD180CCR 26
++#define FC_ExtIQueue 27
++#define FC_ExtOQueue 28
++#define FC_ClrLineIrq 29
++#define FC_HWFlowCtl 30
++#define FC_GetClockRate 35
++#define FC_SetBaud 36
++#define FC_SetDataMode 41
++#define FC_GetCCSR 43
++#define FC_GetDataError 45
++#define FC_RxControl 50
++#define FC_ImmSend 51
++#define FC_SetXonState 52
++#define FC_SetXoffState 53
++#define FC_SetRxFIFOTrig 54
++#define FC_SetTxFIFOCnt 55
++#define FC_UnixRate 56
++#define FC_UnixResetTimer 57
++
++#define RxFIFOTrig1 0
++#define RxFIFOTrig4 1
++#define RxFIFOTrig8 2
++#define RxFIFOTrig14 3
++
++/*
++ * Dual-Ported RAM
++ */
++#define DRAM_global 0
++#define INT_data (DRAM_global + 0)
++#define Config_base (DRAM_global + 0x108)
++
++#define IRQindex (INT_data + 0)
++#define IRQpending (INT_data + 4)
++#define IRQtable (INT_data + 8)
++
++/*
++ * Interrupt Status
++ */
++#define IntrRx 0x01 /* receiver data O.K. */
++#define IntrTx 0x02 /* transmit buffer empty */
++#define IntrFunc 0x04 /* function complete */
++#define IntrBreak 0x08 /* received break */
++#define IntrLine 0x10 /* line status change
++ for transmitter */
++#define IntrIntr 0x20 /* received INTR code */
++#define IntrQuit 0x40 /* received QUIT code */
++#define IntrEOF 0x80 /* received EOF code */
++
++#define IntrRxTrigger 0x100 /* rx data count reach tigger value */
++#define IntrTxTrigger 0x200 /* tx data count below trigger value */
++
++#define Magic_no (Config_base + 0)
++#define Card_model_no (Config_base + 2)
++#define Total_ports (Config_base + 4)
++#define Module_cnt (Config_base + 8)
++#define Module_no (Config_base + 10)
++#define Timer_10ms (Config_base + 14)
++#define Disable_IRQ (Config_base + 20)
++#define TMS320_PORT1 (Config_base + 22)
++#define TMS320_PORT2 (Config_base + 24)
++#define TMS320_CLOCK (Config_base + 26)
++
++/*
++ * DATA BUFFER in DRAM
++ */
++#define Extern_table 0x400 /* Base address of the external table
++ (24 words * 64) total 3K bytes
++ (24 words * 128) total 6K bytes */
++#define Extern_size 0x60 /* 96 bytes */
++#define RXrptr 0x00 /* read pointer for RX buffer */
++#define RXwptr 0x02 /* write pointer for RX buffer */
++#define TXrptr 0x04 /* read pointer for TX buffer */
++#define TXwptr 0x06 /* write pointer for TX buffer */
++#define HostStat 0x08 /* IRQ flag and general flag */
++#define FlagStat 0x0A
++#define FlowControl 0x0C /* B7 B6 B5 B4 B3 B2 B1 B0 */
++ /* x x x x | | | | */
++ /* | | | + CTS flow */
++ /* | | +--- RTS flow */
++ /* | +------ TX Xon/Xoff */
++ /* +--------- RX Xon/Xoff */
++#define Break_cnt 0x0E /* received break count */
++#define CD180TXirq 0x10 /* if non-0: enable TX irq */
++#define RX_mask 0x12
++#define TX_mask 0x14
++#define Ofs_rxb 0x16
++#define Ofs_txb 0x18
++#define Page_rxb 0x1A
++#define Page_txb 0x1C
++#define EndPage_rxb 0x1E
++#define EndPage_txb 0x20
++#define Data_error 0x22
++#define RxTrigger 0x28
++#define TxTrigger 0x2a
++
++#define rRXwptr 0x34
++#define Low_water 0x36
++
++#define FuncCode 0x40
++#define FuncArg 0x42
++#define FuncArg1 0x44
++
++#define C218rx_size 0x2000 /* 8K bytes */
++#define C218tx_size 0x8000 /* 32K bytes */
++
++#define C218rx_mask (C218rx_size - 1)
++#define C218tx_mask (C218tx_size - 1)
++
++#define C320p8rx_size 0x2000
++#define C320p8tx_size 0x8000
++#define C320p8rx_mask (C320p8rx_size - 1)
++#define C320p8tx_mask (C320p8tx_size - 1)
++
++#define C320p16rx_size 0x2000
++#define C320p16tx_size 0x4000
++#define C320p16rx_mask (C320p16rx_size - 1)
++#define C320p16tx_mask (C320p16tx_size - 1)
++
++#define C320p24rx_size 0x2000
++#define C320p24tx_size 0x2000
++#define C320p24rx_mask (C320p24rx_size - 1)
++#define C320p24tx_mask (C320p24tx_size - 1)
++
++#define C320p32rx_size 0x1000
++#define C320p32tx_size 0x1000
++#define C320p32rx_mask (C320p32rx_size - 1)
++#define C320p32tx_mask (C320p32tx_size - 1)
++
++#define Page_size 0x2000U
++#define Page_mask (Page_size - 1)
++#define C218rx_spage 3
++#define C218tx_spage 4
++#define C218rx_pageno 1
++#define C218tx_pageno 4
++#define C218buf_pageno 5
++
++#define C320p8rx_spage 3
++#define C320p8tx_spage 4
++#define C320p8rx_pgno 1
++#define C320p8tx_pgno 4
++#define C320p8buf_pgno 5
++
++#define C320p16rx_spage 3
++#define C320p16tx_spage 4
++#define C320p16rx_pgno 1
++#define C320p16tx_pgno 2
++#define C320p16buf_pgno 3
++
++#define C320p24rx_spage 3
++#define C320p24tx_spage 4
++#define C320p24rx_pgno 1
++#define C320p24tx_pgno 1
++#define C320p24buf_pgno 2
++
++#define C320p32rx_spage 3
++#define C320p32tx_ofs C320p32rx_size
++#define C320p32tx_spage 3
++#define C320p32buf_pgno 1
++
++/*
++ * Host Status
++ */
++#define WakeupRx 0x01
++#define WakeupTx 0x02
++#define WakeupBreak 0x08
++#define WakeupLine 0x10
++#define WakeupIntr 0x20
++#define WakeupQuit 0x40
++#define WakeupEOF 0x80 /* used in VTIME control */
++#define WakeupRxTrigger 0x100
++#define WakeupTxTrigger 0x200
++/*
++ * Flag status
++ */
++#define Rx_over 0x01
++#define Xoff_state 0x02
++#define Tx_flowOff 0x04
++#define Tx_enable 0x08
++#define CTS_state 0x10
++#define DSR_state 0x20
++#define DCD_state 0x80
++/*
++ * FlowControl
++ */
++#define CTS_FlowCtl 1
++#define RTS_FlowCtl 2
++#define Tx_FlowCtl 4
++#define Rx_FlowCtl 8
++#define IXM_IXANY 0x10
++
++#define LowWater 128
++
++#define DTR_ON 1
++#define RTS_ON 2
++#define CTS_ON 1
++#define DSR_ON 2
++#define DCD_ON 8
++
++/* mode definition */
++#define MX_CS8 0x03
++#define MX_CS7 0x02
++#define MX_CS6 0x01
++#define MX_CS5 0x00
++
++#define MX_STOP1 0x00
++#define MX_STOP15 0x04
++#define MX_STOP2 0x08
++
++#define MX_PARNONE 0x00
++#define MX_PAREVEN 0x40
++#define MX_PARODD 0xC0
++
++#endif
+diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
+index ff146c2..fe2a95b 100644
+--- a/drivers/char/mspec.c
++++ b/drivers/char/mspec.c
+@@ -180,7 +180,7 @@ mspec_close(struct vm_area_struct *vma)
+ my_page = vdata->maddr[index];
+ vdata->maddr[index] = 0;
+ if (!mspec_zero_block(my_page, PAGE_SIZE))
+- uncached_free_page(my_page);
++ uncached_free_page(my_page, 1);
+ else
+ printk(KERN_WARNING "mspec_close(): "
+ "failed to zero page %ld\n", my_page);
+@@ -209,7 +209,7 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
+ index = (address - vdata->vm_start) >> PAGE_SHIFT;
+ maddr = (volatile unsigned long) vdata->maddr[index];
+ if (maddr == 0) {
+- maddr = uncached_alloc_page(numa_node_id());
++ maddr = uncached_alloc_page(numa_node_id(), 1);
+ if (maddr == 0)
+ return NOPFN_OOM;
+
+@@ -218,7 +218,7 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
+ vdata->count++;
+ vdata->maddr[index] = maddr;
+ } else {
+- uncached_free_page(maddr);
++ uncached_free_page(maddr, 1);
+ maddr = vdata->maddr[index];
+ }
+ spin_unlock(&vdata->lock);
+@@ -367,7 +367,7 @@ mspec_init(void)
+ int nasid;
+ unsigned long phys;
+
+- scratch_page[nid] = uncached_alloc_page(nid);
++ scratch_page[nid] = uncached_alloc_page(nid, 1);
+ if (scratch_page[nid] == 0)
+ goto free_scratch_pages;
+ phys = __pa(scratch_page[nid]);
+@@ -414,7 +414,7 @@ mspec_init(void)
+ free_scratch_pages:
+ for_each_node(nid) {
+ if (scratch_page[nid] != 0)
+- uncached_free_page(scratch_page[nid]);
++ uncached_free_page(scratch_page[nid], 1);
+ }
+ return ret;
+ }
+@@ -431,7 +431,7 @@ mspec_exit(void)
+
+ for_each_node(nid) {
+ if (scratch_page[nid] != 0)
+- uncached_free_page(scratch_page[nid]);
++ uncached_free_page(scratch_page[nid], 1);
+ }
+ }
+ }
+diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
+index 68c2e92..4b81a85 100644
+--- a/drivers/char/mxser.c
++++ b/drivers/char/mxser.c
+@@ -307,6 +307,200 @@ static unsigned char mxser_msr[MXSER_PORTS + 1];
+ static struct mxser_mon_ext mon_data_ext;
+ static int mxser_set_baud_method[MXSER_PORTS + 1];
+
++static void mxser_enable_must_enchance_mode(unsigned long baseio)
++{
++ u8 oldlcr;
++ u8 efr;
++
++ oldlcr = inb(baseio + UART_LCR);
++ outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
++
++ efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
++ efr |= MOXA_MUST_EFR_EFRB_ENABLE;
++
++ outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
++ outb(oldlcr, baseio + UART_LCR);
++}
++
++static void mxser_disable_must_enchance_mode(unsigned long baseio)
++{
++ u8 oldlcr;
++ u8 efr;
++
++ oldlcr = inb(baseio + UART_LCR);
++ outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
++
++ efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
++ efr &= ~MOXA_MUST_EFR_EFRB_ENABLE;
++
++ outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
++ outb(oldlcr, baseio + UART_LCR);
++}
++
++static void mxser_set_must_xon1_value(unsigned long baseio, u8 value)
++{
++ u8 oldlcr;
++ u8 efr;
++
++ oldlcr = inb(baseio + UART_LCR);
++ outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
++
++ efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
++ efr &= ~MOXA_MUST_EFR_BANK_MASK;
++ efr |= MOXA_MUST_EFR_BANK0;
++
++ outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
++ outb(value, baseio + MOXA_MUST_XON1_REGISTER);
++ outb(oldlcr, baseio + UART_LCR);
++}
++
++static void mxser_set_must_xoff1_value(unsigned long baseio, u8 value)
++{
++ u8 oldlcr;
++ u8 efr;
++
++ oldlcr = inb(baseio + UART_LCR);
++ outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
++
++ efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
++ efr &= ~MOXA_MUST_EFR_BANK_MASK;
++ efr |= MOXA_MUST_EFR_BANK0;
++
++ outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
++ outb(value, baseio + MOXA_MUST_XOFF1_REGISTER);
++ outb(oldlcr, baseio + UART_LCR);
++}
++
++static void mxser_set_must_fifo_value(struct mxser_port *info)
++{
++ u8 oldlcr;
++ u8 efr;
++
++ oldlcr = inb(info->ioaddr + UART_LCR);
++ outb(MOXA_MUST_ENTER_ENCHANCE, info->ioaddr + UART_LCR);
++
++ efr = inb(info->ioaddr + MOXA_MUST_EFR_REGISTER);
++ efr &= ~MOXA_MUST_EFR_BANK_MASK;
++ efr |= MOXA_MUST_EFR_BANK1;
++
++ outb(efr, info->ioaddr + MOXA_MUST_EFR_REGISTER);
++ outb((u8)info->rx_high_water, info->ioaddr + MOXA_MUST_RBRTH_REGISTER);
++ outb((u8)info->rx_trigger, info->ioaddr + MOXA_MUST_RBRTI_REGISTER);
++ outb((u8)info->rx_low_water, info->ioaddr + MOXA_MUST_RBRTL_REGISTER);
++ outb(oldlcr, info->ioaddr + UART_LCR);
++}
++
++static void mxser_set_must_enum_value(unsigned long baseio, u8 value)
++{
++ u8 oldlcr;
++ u8 efr;
++
++ oldlcr = inb(baseio + UART_LCR);
++ outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
++
++ efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
++ efr &= ~MOXA_MUST_EFR_BANK_MASK;
++ efr |= MOXA_MUST_EFR_BANK2;
++
++ outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
++ outb(value, baseio + MOXA_MUST_ENUM_REGISTER);
++ outb(oldlcr, baseio + UART_LCR);
++}
++
++static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId)
++{
++ u8 oldlcr;
++ u8 efr;
++
++ oldlcr = inb(baseio + UART_LCR);
++ outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
++
++ efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
++ efr &= ~MOXA_MUST_EFR_BANK_MASK;
++ efr |= MOXA_MUST_EFR_BANK2;
++
++ outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
++ *pId = inb(baseio + MOXA_MUST_HWID_REGISTER);
++ outb(oldlcr, baseio + UART_LCR);
++}
++
++static void SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(unsigned long baseio)
++{
++ u8 oldlcr;
++ u8 efr;
++
++ oldlcr = inb(baseio + UART_LCR);
++ outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
++
++ efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
++ efr &= ~MOXA_MUST_EFR_SF_MASK;
++
++ outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
++ outb(oldlcr, baseio + UART_LCR);
++}
++
++static void mxser_enable_must_tx_software_flow_control(unsigned long baseio)
++{
++ u8 oldlcr;
++ u8 efr;
++
++ oldlcr = inb(baseio + UART_LCR);
++ outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
++
++ efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
++ efr &= ~MOXA_MUST_EFR_SF_TX_MASK;
++ efr |= MOXA_MUST_EFR_SF_TX1;
++
++ outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
++ outb(oldlcr, baseio + UART_LCR);
++}
++
++static void mxser_disable_must_tx_software_flow_control(unsigned long baseio)
++{
++ u8 oldlcr;
++ u8 efr;
++
++ oldlcr = inb(baseio + UART_LCR);
++ outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
++
++ efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
++ efr &= ~MOXA_MUST_EFR_SF_TX_MASK;
++
++ outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
++ outb(oldlcr, baseio + UART_LCR);
++}
++
++static void mxser_enable_must_rx_software_flow_control(unsigned long baseio)
++{
++ u8 oldlcr;
++ u8 efr;
++
++ oldlcr = inb(baseio + UART_LCR);
++ outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
++
++ efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
++ efr &= ~MOXA_MUST_EFR_SF_RX_MASK;
++ efr |= MOXA_MUST_EFR_SF_RX1;
++
++ outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
++ outb(oldlcr, baseio + UART_LCR);
++}
++
++static void mxser_disable_must_rx_software_flow_control(unsigned long baseio)
++{
++ u8 oldlcr;
++ u8 efr;
++
++ oldlcr = inb(baseio + UART_LCR);
++ outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
++
++ efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
++ efr &= ~MOXA_MUST_EFR_SF_RX_MASK;
++
++ outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
++ outb(oldlcr, baseio + UART_LCR);
++}
++
+ #ifdef CONFIG_PCI
+ static int __devinit CheckIsMoxaMust(unsigned long io)
+ {
+@@ -314,16 +508,16 @@ static int __devinit CheckIsMoxaMust(unsigned long io)
+ int i;
+
+ outb(0, io + UART_LCR);
+- DISABLE_MOXA_MUST_ENCHANCE_MODE(io);
++ mxser_disable_must_enchance_mode(io);
+ oldmcr = inb(io + UART_MCR);
+ outb(0, io + UART_MCR);
+- SET_MOXA_MUST_XON1_VALUE(io, 0x11);
++ mxser_set_must_xon1_value(io, 0x11);
+ if ((hwid = inb(io + UART_MCR)) != 0) {
+ outb(oldmcr, io + UART_MCR);
+ return MOXA_OTHER_UART;
+ }
+
+- GET_MOXA_MUST_HARDWARE_ID(io, &hwid);
++ mxser_get_must_hardware_id(io, &hwid);
+ for (i = 1; i < UART_INFO_NUM; i++) { /* 0 = OTHER_UART */
+ if (hwid == Gpci_uart_info[i].type)
+ return (int)hwid;
+@@ -494,10 +688,10 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)
+ } else
+ quot /= newspd;
+
+- SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, quot);
++ mxser_set_must_enum_value(info->ioaddr, quot);
+ } else
+ #endif
+- SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, 0);
++ mxser_set_must_enum_value(info->ioaddr, 0);
+
+ return 0;
+ }
+@@ -553,14 +747,14 @@ static int mxser_change_speed(struct mxser_port *info,
+ if (info->board->chip_flag) {
+ fcr = UART_FCR_ENABLE_FIFO;
+ fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
+- SET_MOXA_MUST_FIFO_VALUE(info);
++ mxser_set_must_fifo_value(info);
+ } else
+ fcr = 0;
+ } else {
+ fcr = UART_FCR_ENABLE_FIFO;
+ if (info->board->chip_flag) {
+ fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
+- SET_MOXA_MUST_FIFO_VALUE(info);
++ mxser_set_must_fifo_value(info);
+ } else {
+ switch (info->rx_trigger) {
+ case 1:
+@@ -657,17 +851,21 @@ static int mxser_change_speed(struct mxser_port *info,
+ }
+ }
+ if (info->board->chip_flag) {
+- SET_MOXA_MUST_XON1_VALUE(info->ioaddr, START_CHAR(info->tty));
+- SET_MOXA_MUST_XOFF1_VALUE(info->ioaddr, STOP_CHAR(info->tty));
++ mxser_set_must_xon1_value(info->ioaddr, START_CHAR(info->tty));
++ mxser_set_must_xoff1_value(info->ioaddr, STOP_CHAR(info->tty));
+ if (I_IXON(info->tty)) {
+- ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
++ mxser_enable_must_rx_software_flow_control(
++ info->ioaddr);
+ } else {
+- DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
++ mxser_disable_must_rx_software_flow_control(
++ info->ioaddr);
+ }
+ if (I_IXOFF(info->tty)) {
+- ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
++ mxser_enable_must_tx_software_flow_control(
++ info->ioaddr);
+ } else {
+- DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
++ mxser_disable_must_tx_software_flow_control(
++ info->ioaddr);
+ }
+ }
+
+@@ -927,6 +1125,27 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
+ return 0;
+ }
+
++static void mxser_flush_buffer(struct tty_struct *tty)
++{
++ struct mxser_port *info = tty->driver_data;
++ char fcr;
++ unsigned long flags;
++
++
++ spin_lock_irqsave(&info->slock, flags);
++ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
++
++ fcr = inb(info->ioaddr + UART_FCR);
++ outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
++ info->ioaddr + UART_FCR);
++ outb(fcr, info->ioaddr + UART_FCR);
++
++ spin_unlock_irqrestore(&info->slock, flags);
++
++ tty_wakeup(tty);
++}
++
++
+ /*
+ * This routine is called when the serial port gets closed. First, we
+ * wait for the last remaining data to be sent. Then, we unlink its
+@@ -1013,9 +1232,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
+ }
+ mxser_shutdown(info);
+
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
+-
++ mxser_flush_buffer(tty);
+ tty_ldisc_flush(tty);
+
+ tty->closing = 0;
+@@ -1072,16 +1289,16 @@ static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int cou
+ return total;
+ }
+
+-static void mxser_put_char(struct tty_struct *tty, unsigned char ch)
++static int mxser_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ struct mxser_port *info = tty->driver_data;
+ unsigned long flags;
+
+ if (!info->xmit_buf)
+- return;
++ return 0;
+
+ if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
+- return;
++ return 0;
+
+ spin_lock_irqsave(&info->slock, flags);
+ info->xmit_buf[info->xmit_head++] = ch;
+@@ -1099,6 +1316,7 @@ static void mxser_put_char(struct tty_struct *tty, unsigned char ch)
+ spin_unlock_irqrestore(&info->slock, flags);
+ }
+ }
++ return 1;
+ }
+
+
+@@ -1142,26 +1360,6 @@ static int mxser_chars_in_buffer(struct tty_struct *tty)
+ return info->xmit_cnt;
+ }
+
+-static void mxser_flush_buffer(struct tty_struct *tty)
+-{
+- struct mxser_port *info = tty->driver_data;
+- char fcr;
+- unsigned long flags;
+-
+-
+- spin_lock_irqsave(&info->slock, flags);
+- info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+-
+- fcr = inb(info->ioaddr + UART_FCR);
+- outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
+- info->ioaddr + UART_FCR);
+- outb(fcr, info->ioaddr + UART_FCR);
+-
+- spin_unlock_irqrestore(&info->slock, flags);
+-
+- tty_wakeup(tty);
+-}
+-
+ /*
+ * ------------------------------------------------------------
+ * friends of mxser_ioctl()
+@@ -1460,6 +1658,7 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
+ struct mxser_port *port;
+ int result, status;
+ unsigned int i, j;
++ int ret = 0;
+
+ switch (cmd) {
+ case MOXA_GET_MAJOR:
+@@ -1467,18 +1666,21 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
+
+ case MOXA_CHKPORTENABLE:
+ result = 0;
+-
++ lock_kernel();
+ for (i = 0; i < MXSER_BOARDS; i++)
+ for (j = 0; j < MXSER_PORTS_PER_BOARD; j++)
+ if (mxser_boards[i].ports[j].ioaddr)
+ result |= (1 << i);
+-
++ unlock_kernel();
+ return put_user(result, (unsigned long __user *)argp);
+ case MOXA_GETDATACOUNT:
++ lock_kernel();
+ if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log)))
+- return -EFAULT;
+- return 0;
++ ret = -EFAULT;
++ unlock_kernel();
++ return ret;
+ case MOXA_GETMSTATUS:
++ lock_kernel();
+ for (i = 0; i < MXSER_BOARDS; i++)
+ for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
+ port = &mxser_boards[i].ports[j];
+@@ -1515,6 +1717,7 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
+ else
+ GMStatus[i].cts = 0;
+ }
++ unlock_kernel();
+ if (copy_to_user(argp, GMStatus,
+ sizeof(struct mxser_mstatus) * MXSER_PORTS))
+ return -EFAULT;
+@@ -1524,7 +1727,8 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
+ unsigned long opmode;
+ unsigned cflag, iflag;
+
+- for (i = 0; i < MXSER_BOARDS; i++)
++ lock_kernel();
++ for (i = 0; i < MXSER_BOARDS; i++) {
+ for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
+ port = &mxser_boards[i].ports[j];
+ if (!port->ioaddr)
+@@ -1589,13 +1793,14 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
+ mon_data_ext.iftype[i] = opmode;
+
+ }
+- if (copy_to_user(argp, &mon_data_ext,
+- sizeof(mon_data_ext)))
+- return -EFAULT;
+-
+- return 0;
+-
+- } default:
++ }
++ unlock_kernel();
++ if (copy_to_user(argp, &mon_data_ext,
++ sizeof(mon_data_ext)))
++ return -EFAULT;
++ return 0;
++ }
++ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+@@ -1651,16 +1856,20 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
+ opmode != RS422_MODE &&
+ opmode != RS485_4WIRE_MODE)
+ return -EFAULT;
++ lock_kernel();
+ mask = ModeMask[p];
+ shiftbit = p * 2;
+ val = inb(info->opmode_ioaddr);
+ val &= mask;
+ val |= (opmode << shiftbit);
+ outb(val, info->opmode_ioaddr);
++ unlock_kernel();
+ } else {
++ lock_kernel();
+ shiftbit = p * 2;
+ opmode = inb(info->opmode_ioaddr) >> shiftbit;
+ opmode &= OP_MODE_MASK;
++ unlock_kernel();
+ if (put_user(opmode, (int __user *)argp))
+ return -EFAULT;
+ }
+@@ -1687,19 +1896,18 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
+ tty_wait_until_sent(tty, 0);
+ mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
+ return 0;
+- case TIOCGSOFTCAR:
+- return put_user(!!C_CLOCAL(tty), (unsigned long __user *)argp);
+- case TIOCSSOFTCAR:
+- if (get_user(arg, (unsigned long __user *)argp))
+- return -EFAULT;
+- tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
+- return 0;
+ case TIOCGSERIAL:
+- return mxser_get_serial_info(info, argp);
++ lock_kernel();
++ retval = mxser_get_serial_info(info, argp);
++ unlock_kernel();
++ return retval;
+ case TIOCSSERIAL:
+- return mxser_set_serial_info(info, argp);
++ lock_kernel();
++ retval = mxser_set_serial_info(info, argp);
++ unlock_kernel();
++ return retval;
+ case TIOCSERGETLSR: /* Get line status register */
+- return mxser_get_lsr_info(info, argp);
++ return mxser_get_lsr_info(info, argp);
+ /*
+ * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+ * - mask passed in arg for lines of interest
+@@ -1746,24 +1954,27 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
+ case MOXA_HighSpeedOn:
+ return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
+ case MOXA_SDS_RSTICOUNTER:
++ lock_kernel();
+ info->mon_data.rxcnt = 0;
+ info->mon_data.txcnt = 0;
++ unlock_kernel();
+ return 0;
+
+ case MOXA_ASPP_OQUEUE:{
+ int len, lsr;
+
++ lock_kernel();
+ len = mxser_chars_in_buffer(tty);
+-
+ lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT;
+-
+ len += (lsr ? 0 : 1);
++ unlock_kernel();
+
+ return put_user(len, (int __user *)argp);
+ }
+ case MOXA_ASPP_MON: {
+ int mcr, status;
+
++ lock_kernel();
+ status = mxser_get_msr(info->ioaddr, 1, tty->index);
+ mxser_check_modem_status(info, status);
+
+@@ -1782,7 +1993,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
+ info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD;
+ else
+ info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD;
+-
++ unlock_kernel();
+ if (copy_to_user(argp, &info->mon_data,
+ sizeof(struct mxser_mon)))
+ return -EFAULT;
+@@ -1925,7 +2136,8 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi
+
+ if (info->board->chip_flag) {
+ spin_lock_irqsave(&info->slock, flags);
+- DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
++ mxser_disable_must_rx_software_flow_control(
++ info->ioaddr);
+ spin_unlock_irqrestore(&info->slock, flags);
+ }
+
+@@ -1979,6 +2191,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
+ timeout, char_time);
+ printk("jiff=%lu...", jiffies);
+ #endif
++ lock_kernel();
+ while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) {
+ #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+ printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
+@@ -1990,6 +2203,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
+ break;
+ }
+ set_current_state(TASK_RUNNING);
++ unlock_kernel();
+
+ #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+ printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
+@@ -2342,7 +2556,7 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
+
+ /* Enhance mode enabled here */
+ if (brd->chip_flag != MOXA_OTHER_UART)
+- ENABLE_MOXA_MUST_ENCHANCE_MODE(info->ioaddr);
++ mxser_enable_must_enchance_mode(info->ioaddr);
+
+ info->flags = ASYNC_SHARE_IRQ;
+ info->type = brd->uart_type;
+diff --git a/drivers/char/mxser.h b/drivers/char/mxser.h
+index 8441711..41878a6 100644
+--- a/drivers/char/mxser.h
++++ b/drivers/char/mxser.h
+@@ -147,141 +147,4 @@
+ /* Rx software flow control mask */
+ #define MOXA_MUST_EFR_SF_RX_MASK 0x03
+
+-#define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) do { \
+- u8 __oldlcr, __efr; \
+- __oldlcr = inb((baseio)+UART_LCR); \
+- outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+- __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+- __efr |= MOXA_MUST_EFR_EFRB_ENABLE; \
+- outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+- outb(__oldlcr, (baseio)+UART_LCR); \
+-} while (0)
+-
+-#define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) do { \
+- u8 __oldlcr, __efr; \
+- __oldlcr = inb((baseio)+UART_LCR); \
+- outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+- __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+- __efr &= ~MOXA_MUST_EFR_EFRB_ENABLE; \
+- outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+- outb(__oldlcr, (baseio)+UART_LCR); \
+-} while (0)
+-
+-#define SET_MOXA_MUST_XON1_VALUE(baseio, Value) do { \
+- u8 __oldlcr, __efr; \
+- __oldlcr = inb((baseio)+UART_LCR); \
+- outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+- __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+- __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
+- __efr |= MOXA_MUST_EFR_BANK0; \
+- outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+- outb((u8)(Value), (baseio)+MOXA_MUST_XON1_REGISTER); \
+- outb(__oldlcr, (baseio)+UART_LCR); \
+-} while (0)
+-
+-#define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) do { \
+- u8 __oldlcr, __efr; \
+- __oldlcr = inb((baseio)+UART_LCR); \
+- outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+- __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+- __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
+- __efr |= MOXA_MUST_EFR_BANK0; \
+- outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+- outb((u8)(Value), (baseio)+MOXA_MUST_XOFF1_REGISTER); \
+- outb(__oldlcr, (baseio)+UART_LCR); \
+-} while (0)
+-
+-#define SET_MOXA_MUST_FIFO_VALUE(info) do { \
+- u8 __oldlcr, __efr; \
+- __oldlcr = inb((info)->ioaddr+UART_LCR); \
+- outb(MOXA_MUST_ENTER_ENCHANCE, (info)->ioaddr+UART_LCR);\
+- __efr = inb((info)->ioaddr+MOXA_MUST_EFR_REGISTER); \
+- __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
+- __efr |= MOXA_MUST_EFR_BANK1; \
+- outb(__efr, (info)->ioaddr+MOXA_MUST_EFR_REGISTER); \
+- outb((u8)((info)->rx_high_water), (info)->ioaddr+ \
+- MOXA_MUST_RBRTH_REGISTER); \
+- outb((u8)((info)->rx_trigger), (info)->ioaddr+ \
+- MOXA_MUST_RBRTI_REGISTER); \
+- outb((u8)((info)->rx_low_water), (info)->ioaddr+ \
+- MOXA_MUST_RBRTL_REGISTER); \
+- outb(__oldlcr, (info)->ioaddr+UART_LCR); \
+-} while (0)
+-
+-#define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) do { \
+- u8 __oldlcr, __efr; \
+- __oldlcr = inb((baseio)+UART_LCR); \
+- outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+- __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+- __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
+- __efr |= MOXA_MUST_EFR_BANK2; \
+- outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+- outb((u8)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER); \
+- outb(__oldlcr, (baseio)+UART_LCR); \
+-} while (0)
+-
+-#define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) do { \
+- u8 __oldlcr, __efr; \
+- __oldlcr = inb((baseio)+UART_LCR); \
+- outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+- __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+- __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
+- __efr |= MOXA_MUST_EFR_BANK2; \
+- outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+- *pId = inb((baseio)+MOXA_MUST_HWID_REGISTER); \
+- outb(__oldlcr, (baseio)+UART_LCR); \
+-} while (0)
+-
+-#define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) do { \
+- u8 __oldlcr, __efr; \
+- __oldlcr = inb((baseio)+UART_LCR); \
+- outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+- __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+- __efr &= ~MOXA_MUST_EFR_SF_MASK; \
+- outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+- outb(__oldlcr, (baseio)+UART_LCR); \
+-} while (0)
+-
+-#define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) do { \
+- u8 __oldlcr, __efr; \
+- __oldlcr = inb((baseio)+UART_LCR); \
+- outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+- __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+- __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \
+- __efr |= MOXA_MUST_EFR_SF_TX1; \
+- outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+- outb(__oldlcr, (baseio)+UART_LCR); \
+-} while (0)
+-
+-#define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) do { \
+- u8 __oldlcr, __efr; \
+- __oldlcr = inb((baseio)+UART_LCR); \
+- outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+- __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+- __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \
+- outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+- outb(__oldlcr, (baseio)+UART_LCR); \
+-} while (0)
+-
+-#define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) do { \
+- u8 __oldlcr, __efr; \
+- __oldlcr = inb((baseio)+UART_LCR); \
+- outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+- __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+- __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \
+- __efr |= MOXA_MUST_EFR_SF_RX1; \
+- outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+- outb(__oldlcr, (baseio)+UART_LCR); \
+-} while (0)
+-
+-#define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) do { \
+- u8 __oldlcr, __efr; \
+- __oldlcr = inb((baseio)+UART_LCR); \
+- outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+- __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+- __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \
+- outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+- outb(__oldlcr, (baseio)+UART_LCR); \
+-} while (0)
+-
+ #endif
+diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
+index 82bcfb9..a35bfd7 100644
+--- a/drivers/char/n_hdlc.c
++++ b/drivers/char/n_hdlc.c
+@@ -342,12 +342,10 @@ static int n_hdlc_tty_open (struct tty_struct *tty)
+ #endif
+
+ /* Flush any pending characters in the driver and discipline. */
+-
+ if (tty->ldisc.flush_buffer)
+- tty->ldisc.flush_buffer (tty);
++ tty->ldisc.flush_buffer(tty);
+
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer (tty);
++ tty_driver_flush_buffer(tty);
+
+ if (debuglevel >= DEBUG_LEVEL_INFO)
+ printk("%s(%d)n_hdlc_tty_open() success\n",__FILE__,__LINE__);
+@@ -399,7 +397,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty)
+
+ /* Send the next block of data to device */
+ tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+- actual = tty->driver->write(tty, tbuf->buf, tbuf->count);
++ actual = tty->ops->write(tty, tbuf->buf, tbuf->count);
+
+ /* rollback was possible and has been done */
+ if (actual == -ERESTARTSYS) {
+@@ -501,7 +499,7 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,
+ __FILE__,__LINE__, count);
+
+ /* This can happen if stuff comes in on the backup tty */
+- if (n_hdlc == 0 || tty != n_hdlc->tty)
++ if (!n_hdlc || tty != n_hdlc->tty)
+ return;
+
+ /* verify line is using HDLC discipline */
+@@ -578,26 +576,36 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
+ return -EFAULT;
+ }
+
++ lock_kernel();
++
+ for (;;) {
+- if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
++ if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
++ unlock_kernel();
+ return -EIO;
++ }
+
+ n_hdlc = tty2n_hdlc (tty);
+ if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC ||
+- tty != n_hdlc->tty)
++ tty != n_hdlc->tty) {
++ unlock_kernel();
+ return 0;
++ }
+
+ rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list);
+ if (rbuf)
+ break;
+
+ /* no data */
+- if (file->f_flags & O_NONBLOCK)
++ if (file->f_flags & O_NONBLOCK) {
++ unlock_kernel();
+ return -EAGAIN;
++ }
+
+ interruptible_sleep_on (&tty->read_wait);
+- if (signal_pending(current))
++ if (signal_pending(current)) {
++ unlock_kernel();
+ return -EINTR;
++ }
+ }
+
+ if (rbuf->count > nr)
+@@ -618,7 +626,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
+ kfree(rbuf);
+ else
+ n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf);
+-
++ unlock_kernel();
+ return ret;
+
+ } /* end of n_hdlc_tty_read() */
+@@ -661,6 +669,8 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
+ count = maxframe;
+ }
+
++ lock_kernel();
++
+ add_wait_queue(&tty->write_wait, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+@@ -695,7 +705,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
+ n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf);
+ n_hdlc_send_frames(n_hdlc,tty);
+ }
+-
++ unlock_kernel();
+ return error;
+
+ } /* end of n_hdlc_tty_write() */
+@@ -740,8 +750,7 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,
+
+ case TIOCOUTQ:
+ /* get the pending tx byte count in the driver */
+- count = tty->driver->chars_in_buffer ?
+- tty->driver->chars_in_buffer(tty) : 0;
++ count = tty_chars_in_buffer(tty);
+ /* add size of next output frame in queue */
+ spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock,flags);
+ if (n_hdlc->tx_buf_list.head)
+diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
+index 6b918b8..9021690 100644
+--- a/drivers/char/n_r3964.c
++++ b/drivers/char/n_r3964.c
+@@ -376,8 +376,9 @@ static void put_char(struct r3964_info *pInfo, unsigned char ch)
+ if (tty == NULL)
+ return;
+
+- if (tty->driver->put_char) {
+- tty->driver->put_char(tty, ch);
++ /* FIXME: put_char should not be called from an IRQ */
++ if (tty->ops->put_char) {
++ tty->ops->put_char(tty, ch);
+ }
+ pInfo->bcc ^= ch;
+ }
+@@ -386,12 +387,9 @@ static void flush(struct r3964_info *pInfo)
+ {
+ struct tty_struct *tty = pInfo->tty;
+
+- if (tty == NULL)
++ if (tty == NULL || tty->ops->flush_chars == NULL)
+ return;
+-
+- if (tty->driver->flush_chars) {
+- tty->driver->flush_chars(tty);
+- }
++ tty->ops->flush_chars(tty);
+ }
+
+ static void trigger_transmit(struct r3964_info *pInfo)
+@@ -449,12 +447,11 @@ static void transmit_block(struct r3964_info *pInfo)
+ struct r3964_block_header *pBlock = pInfo->tx_first;
+ int room = 0;
+
+- if ((tty == NULL) || (pBlock == NULL)) {
++ if (tty == NULL || pBlock == NULL) {
+ return;
+ }
+
+- if (tty->driver->write_room)
+- room = tty->driver->write_room(tty);
++ room = tty_write_room(tty);
+
+ TRACE_PS("transmit_block %p, room %d, length %d",
+ pBlock, room, pBlock->length);
+@@ -1075,12 +1072,15 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
+
+ TRACE_L("read()");
+
++ lock_kernel();
++
+ pClient = findClient(pInfo, task_pid(current));
+ if (pClient) {
+ pMsg = remove_msg(pInfo, pClient);
+ if (pMsg == NULL) {
+ /* no messages available. */
+ if (file->f_flags & O_NONBLOCK) {
++ unlock_kernel();
+ return -EAGAIN;
+ }
+ /* block until there is a message: */
+@@ -1090,8 +1090,10 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
+
+ /* If we still haven't got a message, we must have been signalled */
+
+- if (!pMsg)
++ if (!pMsg) {
++ unlock_kernel();
+ return -EINTR;
++ }
+
+ /* deliver msg to client process: */
+ theMsg.msg_id = pMsg->msg_id;
+@@ -1102,12 +1104,15 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
+ kfree(pMsg);
+ TRACE_M("r3964_read - msg kfree %p", pMsg);
+
+- if (copy_to_user(buf, &theMsg, count))
++ if (copy_to_user(buf, &theMsg, count)) {
++ unlock_kernel();
+ return -EFAULT;
++ }
+
+ TRACE_PS("read - return %d", count);
+ return count;
+ }
++ unlock_kernel();
+ return -EPERM;
+ }
+
+@@ -1156,6 +1161,8 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
+ pHeader->locks = 0;
+ pHeader->owner = NULL;
+
++ lock_kernel();
++
+ pClient = findClient(pInfo, task_pid(current));
+ if (pClient) {
+ pHeader->owner = pClient;
+@@ -1173,6 +1180,8 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
+ add_tx_queue(pInfo, pHeader);
+ trigger_transmit(pInfo);
+
++ unlock_kernel();
++
+ return 0;
+ }
+
+diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
+index 0c09409..19105ec 100644
+--- a/drivers/char/n_tty.c
++++ b/drivers/char/n_tty.c
+@@ -147,10 +147,8 @@ static void put_tty_queue(unsigned char c, struct tty_struct *tty)
+
+ static void check_unthrottle(struct tty_struct *tty)
+ {
+- if (tty->count &&
+- test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
+- tty->driver->unthrottle)
+- tty->driver->unthrottle(tty);
++ if (tty->count)
++ tty_unthrottle(tty);
+ }
+
+ /**
+@@ -183,22 +181,24 @@ static void reset_buffer_flags(struct tty_struct *tty)
+ * at hangup) or when the N_TTY line discipline internally has to
+ * clean the pending queue (for example some signals).
+ *
+- * FIXME: tty->ctrl_status is not spinlocked and relies on
+- * lock_kernel() still.
++ * Locking: ctrl_lock
+ */
+
+ static void n_tty_flush_buffer(struct tty_struct *tty)
+ {
++ unsigned long flags;
+ /* clear everything and unthrottle the driver */
+ reset_buffer_flags(tty);
+
+ if (!tty->link)
+ return;
+
++ spin_lock_irqsave(&tty->ctrl_lock, flags);
+ if (tty->link->packet) {
+ tty->ctrl_status |= TIOCPKT_FLUSHREAD;
+ wake_up_interruptible(&tty->link->read_wait);
+ }
++ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ }
+
+ /**
+@@ -264,17 +264,18 @@ static inline int is_continuation(unsigned char c, struct tty_struct *tty)
+ * relevant in the world today. If you ever need them, add them here.
+ *
+ * Called from both the receive and transmit sides and can be called
+- * re-entrantly. Relies on lock_kernel() still.
++ * re-entrantly. Relies on lock_kernel() for tty->column state.
+ */
+
+ static int opost(unsigned char c, struct tty_struct *tty)
+ {
+ int space, spaces;
+
+- space = tty->driver->write_room(tty);
++ space = tty_write_room(tty);
+ if (!space)
+ return -1;
+
++ lock_kernel();
+ if (O_OPOST(tty)) {
+ switch (c) {
+ case '\n':
+@@ -283,7 +284,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
+ if (O_ONLCR(tty)) {
+ if (space < 2)
+ return -1;
+- tty->driver->put_char(tty, '\r');
++ tty_put_char(tty, '\r');
+ tty->column = 0;
+ }
+ tty->canon_column = tty->column;
+@@ -305,7 +306,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
+ if (space < spaces)
+ return -1;
+ tty->column += spaces;
+- tty->driver->write(tty, " ", spaces);
++ tty->ops->write(tty, " ", spaces);
+ return 0;
+ }
+ tty->column += spaces;
+@@ -322,7 +323,8 @@ static int opost(unsigned char c, struct tty_struct *tty)
+ break;
+ }
+ }
+- tty->driver->put_char(tty, c);
++ tty_put_char(tty, c);
++ unlock_kernel();
+ return 0;
+ }
+
+@@ -337,7 +339,8 @@ static int opost(unsigned char c, struct tty_struct *tty)
+ * the simple cases normally found and helps to generate blocks of
+ * symbols for the console driver and thus improve performance.
+ *
+- * Called from write_chan under the tty layer write lock.
++ * Called from write_chan under the tty layer write lock. Relies
++ * on lock_kernel for the tty->column state.
+ */
+
+ static ssize_t opost_block(struct tty_struct *tty,
+@@ -347,12 +350,13 @@ static ssize_t opost_block(struct tty_struct *tty,
+ int i;
+ const unsigned char *cp;
+
+- space = tty->driver->write_room(tty);
++ space = tty_write_room(tty);
+ if (!space)
+ return 0;
+ if (nr > space)
+ nr = space;
+
++ lock_kernel();
+ for (i = 0, cp = buf; i < nr; i++, cp++) {
+ switch (*cp) {
+ case '\n':
+@@ -384,27 +388,15 @@ static ssize_t opost_block(struct tty_struct *tty,
+ }
+ }
+ break_out:
+- if (tty->driver->flush_chars)
+- tty->driver->flush_chars(tty);
+- i = tty->driver->write(tty, buf, i);
++ if (tty->ops->flush_chars)
++ tty->ops->flush_chars(tty);
++ i = tty->ops->write(tty, buf, i);
++ unlock_kernel();
+ return i;
+ }
+
+
+ /**
+- * put_char - write character to driver
+- * @c: character (or part of unicode symbol)
+- * @tty: terminal device
+- *
+- * Queue a byte to the driver layer for output
+- */
+-
+-static inline void put_char(unsigned char c, struct tty_struct *tty)
+-{
+- tty->driver->put_char(tty, c);
+-}
+-
+-/**
+ * echo_char - echo characters
+ * @c: unicode byte to echo
+ * @tty: terminal device
+@@ -416,8 +408,8 @@ static inline void put_char(unsigned char c, struct tty_struct *tty)
+ static void echo_char(unsigned char c, struct tty_struct *tty)
+ {
+ if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') {
+- put_char('^', tty);
+- put_char(c ^ 0100, tty);
++ tty_put_char(tty, '^');
++ tty_put_char(tty, c ^ 0100);
+ tty->column += 2;
+ } else
+ opost(c, tty);
+@@ -426,7 +418,7 @@ static void echo_char(unsigned char c, struct tty_struct *tty)
+ static inline void finish_erasing(struct tty_struct *tty)
+ {
+ if (tty->erasing) {
+- put_char('/', tty);
++ tty_put_char(tty, '/');
+ tty->column++;
+ tty->erasing = 0;
+ }
+@@ -510,7 +502,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
+ if (L_ECHO(tty)) {
+ if (L_ECHOPRT(tty)) {
+ if (!tty->erasing) {
+- put_char('\\', tty);
++ tty_put_char(tty, '\\');
+ tty->column++;
+ tty->erasing = 1;
+ }
+@@ -518,7 +510,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
+ echo_char(c, tty);
+ while (--cnt > 0) {
+ head = (head+1) & (N_TTY_BUF_SIZE-1);
+- put_char(tty->read_buf[head], tty);
++ tty_put_char(tty, tty->read_buf[head]);
+ }
+ } else if (kill_type == ERASE && !L_ECHOE(tty)) {
+ echo_char(ERASE_CHAR(tty), tty);
+@@ -546,22 +538,22 @@ static void eraser(unsigned char c, struct tty_struct *tty)
+ /* Now backup to that column. */
+ while (tty->column > col) {
+ /* Can't use opost here. */
+- put_char('\b', tty);
++ tty_put_char(tty, '\b');
+ if (tty->column > 0)
+ tty->column--;
+ }
+ } else {
+ if (iscntrl(c) && L_ECHOCTL(tty)) {
+- put_char('\b', tty);
+- put_char(' ', tty);
+- put_char('\b', tty);
++ tty_put_char(tty, '\b');
++ tty_put_char(tty, ' ');
++ tty_put_char(tty, '\b');
+ if (tty->column > 0)
+ tty->column--;
+ }
+ if (!iscntrl(c) || L_ECHOCTL(tty)) {
+- put_char('\b', tty);
+- put_char(' ', tty);
+- put_char('\b', tty);
++ tty_put_char(tty, '\b');
++ tty_put_char(tty, ' ');
++ tty_put_char(tty, '\b');
+ if (tty->column > 0)
+ tty->column--;
+ }
+@@ -592,8 +584,7 @@ static inline void isig(int sig, struct tty_struct *tty, int flush)
+ kill_pgrp(tty->pgrp, sig, 1);
+ if (flush || !L_NOFLSH(tty)) {
+ n_tty_flush_buffer(tty);
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ tty_driver_flush_buffer(tty);
+ }
+ }
+
+@@ -701,7 +692,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
+
+ if (tty->stopped && !tty->flow_stopped && I_IXON(tty) &&
+ ((I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty)) ||
+- c == INTR_CHAR(tty) || c == QUIT_CHAR(tty)))
++ c == INTR_CHAR(tty) || c == QUIT_CHAR(tty) || c == SUSP_CHAR(tty)))
+ start_tty(tty);
+
+ if (tty->closing) {
+@@ -725,7 +716,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
+ tty->lnext = 0;
+ if (L_ECHO(tty)) {
+ if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
+- put_char('\a', tty); /* beep if no space */
++ tty_put_char(tty, '\a'); /* beep if no space */
+ return;
+ }
+ /* Record the column of first canon char. */
+@@ -739,13 +730,6 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
+ return;
+ }
+
+- if (c == '\r') {
+- if (I_IGNCR(tty))
+- return;
+- if (I_ICRNL(tty))
+- c = '\n';
+- } else if (c == '\n' && I_INLCR(tty))
+- c = '\r';
+ if (I_IXON(tty)) {
+ if (c == START_CHAR(tty)) {
+ start_tty(tty);
+@@ -756,6 +740,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
+ return;
+ }
+ }
++
+ if (L_ISIG(tty)) {
+ int signal;
+ signal = SIGINT;
+@@ -775,8 +760,7 @@ send_signal:
+ */
+ if (!L_NOFLSH(tty)) {
+ n_tty_flush_buffer(tty);
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ tty_driver_flush_buffer(tty);
+ }
+ if (L_ECHO(tty))
+ echo_char(c, tty);
+@@ -785,6 +769,15 @@ send_signal:
+ return;
+ }
+ }
++
++ if (c == '\r') {
++ if (I_IGNCR(tty))
++ return;
++ if (I_ICRNL(tty))
++ c = '\n';
++ } else if (c == '\n' && I_INLCR(tty))
++ c = '\r';
++
+ if (tty->icanon) {
+ if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
+ (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
+@@ -796,8 +789,8 @@ send_signal:
+ if (L_ECHO(tty)) {
+ finish_erasing(tty);
+ if (L_ECHOCTL(tty)) {
+- put_char('^', tty);
+- put_char('\b', tty);
++ tty_put_char(tty, '^');
++ tty_put_char(tty, '\b');
+ }
+ }
+ return;
+@@ -818,7 +811,7 @@ send_signal:
+ if (c == '\n') {
+ if (L_ECHO(tty) || L_ECHONL(tty)) {
+ if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
+- put_char('\a', tty);
++ tty_put_char(tty, '\a');
+ opost('\n', tty);
+ }
+ goto handle_newline;
+@@ -836,7 +829,7 @@ send_signal:
+ */
+ if (L_ECHO(tty)) {
+ if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
+- put_char('\a', tty);
++ tty_put_char(tty, '\a');
+ /* Record the column of first canon char. */
+ if (tty->canon_head == tty->read_head)
+ tty->canon_column = tty->column;
+@@ -866,7 +859,7 @@ handle_newline:
+ finish_erasing(tty);
+ if (L_ECHO(tty)) {
+ if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
+- put_char('\a', tty); /* beep if no space */
++ tty_put_char(tty, '\a'); /* beep if no space */
+ return;
+ }
+ if (c == '\n')
+@@ -970,8 +963,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
+ break;
+ }
+ }
+- if (tty->driver->flush_chars)
+- tty->driver->flush_chars(tty);
++ if (tty->ops->flush_chars)
++ tty->ops->flush_chars(tty);
+ }
+
+ n_tty_set_room(tty);
+@@ -987,12 +980,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
+ * mode. We don't want to throttle the driver if we're in
+ * canonical mode and don't have a newline yet!
+ */
+- if (tty->receive_room < TTY_THRESHOLD_THROTTLE) {
+- /* check TTY_THROTTLED first so it indicates our state */
+- if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
+- tty->driver->throttle)
+- tty->driver->throttle(tty);
+- }
++ if (tty->receive_room < TTY_THRESHOLD_THROTTLE)
++ tty_throttle(tty);
+ }
+
+ int is_ignored(int sig)
+@@ -1076,6 +1065,9 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
+ tty->real_raw = 0;
+ }
+ n_tty_set_room(tty);
++ /* The termios change make the tty ready for I/O */
++ wake_up_interruptible(&tty->write_wait);
++ wake_up_interruptible(&tty->read_wait);
+ }
+
+ /**
+@@ -1194,6 +1186,11 @@ extern ssize_t redirected_tty_write(struct file *, const char __user *,
+ * Perform job control management checks on this file/tty descriptor
+ * and if appropriate send any needed signals and return a negative
+ * error code if action should be taken.
++ *
++ * FIXME:
++ * Locking: None - redirected write test is safe, testing
++ * current->signal should possibly lock current->sighand
++ * pgrp locking ?
+ */
+
+ static int job_control(struct tty_struct *tty, struct file *file)
+@@ -1246,6 +1243,7 @@ static ssize_t read_chan(struct tty_struct *tty, struct file *file,
+ ssize_t size;
+ long timeout;
+ unsigned long flags;
++ int packet;
+
+ do_it_again:
+
+@@ -1289,16 +1287,19 @@ do_it_again:
+ if (mutex_lock_interruptible(&tty->atomic_read_lock))
+ return -ERESTARTSYS;
+ }
++ packet = tty->packet;
+
+ add_wait_queue(&tty->read_wait, &wait);
+ while (nr) {
+ /* First test for status change. */
+- if (tty->packet && tty->link->ctrl_status) {
++ if (packet && tty->link->ctrl_status) {
+ unsigned char cs;
+ if (b != buf)
+ break;
++ spin_lock_irqsave(&tty->link->ctrl_lock, flags);
+ cs = tty->link->ctrl_status;
+ tty->link->ctrl_status = 0;
++ spin_unlock_irqrestore(&tty->link->ctrl_lock, flags);
+ if (tty_put_user(tty, cs, b++)) {
+ retval = -EFAULT;
+ b--;
+@@ -1333,6 +1334,7 @@ do_it_again:
+ retval = -ERESTARTSYS;
+ break;
+ }
++ /* FIXME: does n_tty_set_room need locking ? */
+ n_tty_set_room(tty);
+ timeout = schedule_timeout(timeout);
+ continue;
+@@ -1340,7 +1342,7 @@ do_it_again:
+ __set_current_state(TASK_RUNNING);
+
+ /* Deal with packet mode. */
+- if (tty->packet && b == buf) {
++ if (packet && b == buf) {
+ if (tty_put_user(tty, TIOCPKT_DATA, b++)) {
+ retval = -EFAULT;
+ b--;
+@@ -1388,6 +1390,8 @@ do_it_again:
+ break;
+ } else {
+ int uncopied;
++ /* The copy function takes the read lock and handles
++ locking internally for this case */
+ uncopied = copy_from_read_buf(tty, &b, &nr);
+ uncopied += copy_from_read_buf(tty, &b, &nr);
+ if (uncopied) {
+@@ -1429,7 +1433,6 @@ do_it_again:
+ goto do_it_again;
+
+ n_tty_set_room(tty);
+-
+ return retval;
+ }
+
+@@ -1492,11 +1495,11 @@ static ssize_t write_chan(struct tty_struct *tty, struct file *file,
+ break;
+ b++; nr--;
+ }
+- if (tty->driver->flush_chars)
+- tty->driver->flush_chars(tty);
++ if (tty->ops->flush_chars)
++ tty->ops->flush_chars(tty);
+ } else {
+ while (nr > 0) {
+- c = tty->driver->write(tty, b, nr);
++ c = tty->ops->write(tty, b, nr);
+ if (c < 0) {
+ retval = c;
+ goto break_out;
+@@ -1533,11 +1536,6 @@ break_out:
+ *
+ * This code must be sure never to sleep through a hangup.
+ * Called without the kernel lock held - fine
+- *
+- * FIXME: if someone changes the VMIN or discipline settings for the
+- * terminal while another process is in poll() the poll does not
+- * recompute the new limits. Possibly set_termios should issue
+- * a read wakeup to fix this bug.
+ */
+
+ static unsigned int normal_poll(struct tty_struct *tty, struct file *file,
+@@ -1561,9 +1559,9 @@ static unsigned int normal_poll(struct tty_struct *tty, struct file *file,
+ else
+ tty->minimum_to_wake = 1;
+ }
+- if (!tty_is_writelocked(tty) &&
+- tty->driver->chars_in_buffer(tty) < WAKEUP_CHARS &&
+- tty->driver->write_room(tty) > 0)
++ if (tty->ops->write && !tty_is_writelocked(tty) &&
++ tty_chars_in_buffer(tty) < WAKEUP_CHARS &&
++ tty_write_room(tty) > 0)
+ mask |= POLLOUT | POLLWRNORM;
+ return mask;
+ }
+diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c
+index 6a6843a..66a0f93 100644
+--- a/drivers/char/nozomi.c
++++ b/drivers/char/nozomi.c
+@@ -73,7 +73,7 @@ do { \
+ char tmp[P_BUF_SIZE]; \
+ snprintf(tmp, sizeof(tmp), ##args); \
+ printk(_err_flag_ "[%d] %s(): %s\n", __LINE__, \
+- __FUNCTION__, tmp); \
++ __func__, tmp); \
+ } while (0)
+
+ #define DBG1(args...) D_(0x01, ##args)
+@@ -1407,7 +1407,7 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
+ /* Find out what card type it is */
+ nozomi_get_card_type(dc);
+
+- dc->base_addr = ioremap(start, dc->card_type);
++ dc->base_addr = ioremap_nocache(start, dc->card_type);
+ if (!dc->base_addr) {
+ dev_err(&pdev->dev, "Unable to map card MMIO\n");
+ ret = -ENODEV;
+@@ -1724,6 +1724,8 @@ static int ntty_tiocmget(struct tty_struct *tty, struct file *file)
+ const struct ctrl_dl *ctrl_dl = &port->ctrl_dl;
+ const struct ctrl_ul *ctrl_ul = &port->ctrl_ul;
+
++ /* Note: these could change under us but it is not clear this
++ matters if so */
+ return (ctrl_ul->RTS ? TIOCM_RTS : 0) |
+ (ctrl_ul->DTR ? TIOCM_DTR : 0) |
+ (ctrl_dl->DCD ? TIOCM_CAR : 0) |
+@@ -1849,16 +1851,6 @@ static void ntty_throttle(struct tty_struct *tty)
+ spin_unlock_irqrestore(&dc->spin_mutex, flags);
+ }
+
+-/* just to discard single character writes */
+-static void ntty_put_char(struct tty_struct *tty, unsigned char c)
+-{
+- /*
+- * card does not react correct when we write single chars
+- * to the card, so we discard them
+- */
+- DBG2("PUT CHAR Function: %c", c);
+-}
+-
+ /* Returns number of chars in buffer, called by tty layer */
+ static s32 ntty_chars_in_buffer(struct tty_struct *tty)
+ {
+@@ -1892,7 +1884,6 @@ static const struct tty_operations tty_ops = {
+ .unthrottle = ntty_unthrottle,
+ .throttle = ntty_throttle,
+ .chars_in_buffer = ntty_chars_in_buffer,
+- .put_char = ntty_put_char,
+ .tiocmget = ntty_tiocmget,
+ .tiocmset = ntty_tiocmset,
+ };
+diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
+index 454d732..4a933d4 100644
+--- a/drivers/char/pcmcia/cm4000_cs.c
++++ b/drivers/char/pcmcia/cm4000_cs.c
+@@ -53,7 +53,7 @@ module_param(pc_debug, int, 0600);
+ #define DEBUGP(n, rdr, x, args...) do { \
+ if (pc_debug >= (n)) \
+ dev_printk(KERN_DEBUG, reader_to_dev(rdr), "%s:" x, \
+- __FUNCTION__ , ## args); \
++ __func__ , ## args); \
+ } while (0)
+ #else
+ #define DEBUGP(n, rdr, x, args...)
+diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
+index 5f291bf..035084c 100644
+--- a/drivers/char/pcmcia/cm4040_cs.c
++++ b/drivers/char/pcmcia/cm4040_cs.c
+@@ -47,7 +47,7 @@ module_param(pc_debug, int, 0600);
+ #define DEBUGP(n, rdr, x, args...) do { \
+ if (pc_debug >= (n)) \
+ dev_printk(KERN_DEBUG, reader_to_dev(rdr), "%s:" x, \
+- __FUNCTION__ , ##args); \
++ __func__ , ##args); \
+ } while (0)
+ #else
+ #define DEBUGP(n, rdr, x, args...)
+diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c
+index 1f978ff..fa9d3c9 100644
+--- a/drivers/char/pcmcia/ipwireless/hardware.c
++++ b/drivers/char/pcmcia/ipwireless/hardware.c
+@@ -354,32 +354,6 @@ struct ipw_rx_packet {
+ unsigned int channel_idx;
+ };
+
+-#ifdef IPWIRELESS_STATE_DEBUG
+-int ipwireless_dump_hardware_state(char *p, size_t limit,
+- struct ipw_hardware *hw)
+-{
+- return snprintf(p, limit,
+- "debug: initializing=%d\n"
+- "debug: tx_ready=%d\n"
+- "debug: tx_queued=%d\n"
+- "debug: rx_ready=%d\n"
+- "debug: rx_bytes_queued=%d\n"
+- "debug: blocking_rx=%d\n"
+- "debug: removed=%d\n"
+- "debug: hardware.shutting_down=%d\n"
+- "debug: to_setup=%d\n",
+- hw->initializing,
+- hw->tx_ready,
+- hw->tx_queued,
+- hw->rx_ready,
+- hw->rx_bytes_queued,
+- hw->blocking_rx,
+- hw->removed,
+- hw->shutting_down,
+- hw->to_setup);
+-}
+-#endif
+-
+ static char *data_type(const unsigned char *buf, unsigned length)
+ {
+ struct nl_packet_header *hdr = (struct nl_packet_header *) buf;
+diff --git a/drivers/char/pcmcia/ipwireless/hardware.h b/drivers/char/pcmcia/ipwireless/hardware.h
+index c83190f..19ce5eb 100644
+--- a/drivers/char/pcmcia/ipwireless/hardware.h
++++ b/drivers/char/pcmcia/ipwireless/hardware.h
+@@ -58,7 +58,5 @@ void ipwireless_init_hardware_v1(struct ipw_hardware *hw,
+ void *reboot_cb_data);
+ void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw);
+ void ipwireless_sleep(unsigned int tenths);
+-int ipwireless_dump_hardware_state(char *p, size_t limit,
+- struct ipw_hardware *hw);
+
+ #endif
+diff --git a/drivers/char/pcmcia/ipwireless/network.c b/drivers/char/pcmcia/ipwireless/network.c
+index d793e68..fe914d3 100644
+--- a/drivers/char/pcmcia/ipwireless/network.c
++++ b/drivers/char/pcmcia/ipwireless/network.c
+@@ -63,21 +63,6 @@ struct ipw_network {
+ struct work_struct work_go_offline;
+ };
+
+-
+-#ifdef IPWIRELESS_STATE_DEBUG
+-int ipwireless_dump_network_state(char *p, size_t limit,
+- struct ipw_network *network)
+-{
+- return snprintf(p, limit,
+- "debug: ppp_blocked=%d\n"
+- "debug: outgoing_packets_queued=%d\n"
+- "debug: network.shutting_down=%d\n",
+- network->ppp_blocked,
+- network->outgoing_packets_queued,
+- network->shutting_down);
+-}
+-#endif
+-
+ static void notify_packet_sent(void *callback_data, unsigned int packet_length)
+ {
+ struct ipw_network *network = callback_data;
+diff --git a/drivers/char/pcmcia/ipwireless/network.h b/drivers/char/pcmcia/ipwireless/network.h
+index b0e1e95..ccacd26 100644
+--- a/drivers/char/pcmcia/ipwireless/network.h
++++ b/drivers/char/pcmcia/ipwireless/network.h
+@@ -49,7 +49,4 @@ void ipwireless_ppp_close(struct ipw_network *net);
+ int ipwireless_ppp_channel_index(struct ipw_network *net);
+ int ipwireless_ppp_unit_number(struct ipw_network *net);
+
+-int ipwireless_dump_network_state(char *p, size_t limit,
+- struct ipw_network *net);
+-
+ #endif
+diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
+index 279ff50..1dd0e99 100644
+--- a/drivers/char/pcmcia/synclink_cs.c
++++ b/drivers/char/pcmcia/synclink_cs.c
+@@ -189,20 +189,20 @@ typedef struct _mgslpc_info {
+
+ u32 pending_bh;
+
+- int bh_running;
+- int bh_requested;
++ bool bh_running;
++ bool bh_requested;
+
+ int dcd_chkcount; /* check counts to prevent */
+ int cts_chkcount; /* too many IRQs if a signal */
+ int dsr_chkcount; /* is floating */
+ int ri_chkcount;
+
+- int rx_enabled;
+- int rx_overflow;
++ bool rx_enabled;
++ bool rx_overflow;
+
+- int tx_enabled;
+- int tx_active;
+- int tx_aborting;
++ bool tx_enabled;
++ bool tx_active;
++ bool tx_aborting;
+ u32 idle_mode;
+
+ int if_mode; /* serial interface selection (RS-232, v.35 etc) */
+@@ -216,12 +216,12 @@ typedef struct _mgslpc_info {
+
+ unsigned char serial_signals; /* current serial signal states */
+
+- char irq_occurred; /* for diagnostics use */
++ bool irq_occurred; /* for diagnostics use */
+ char testing_irq;
+ unsigned int init_error; /* startup error (DIAGS) */
+
+ char flag_buf[MAX_ASYNC_BUFFER_SIZE];
+- BOOLEAN drop_rts_on_tx_done;
++ bool drop_rts_on_tx_done;
+
+ struct _input_signal_events input_signal_events;
+
+@@ -402,8 +402,8 @@ static void hdlcdev_exit(MGSLPC_INFO *info);
+
+ static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit);
+
+-static BOOLEAN register_test(MGSLPC_INFO *info);
+-static BOOLEAN irq_test(MGSLPC_INFO *info);
++static bool register_test(MGSLPC_INFO *info);
++static bool irq_test(MGSLPC_INFO *info);
+ static int adapter_test(MGSLPC_INFO *info);
+
+ static int claim_resources(MGSLPC_INFO *info);
+@@ -411,7 +411,7 @@ static void release_resources(MGSLPC_INFO *info);
+ static void mgslpc_add_device(MGSLPC_INFO *info);
+ static void mgslpc_remove_device(MGSLPC_INFO *info);
+
+-static int rx_get_frame(MGSLPC_INFO *info);
++static bool rx_get_frame(MGSLPC_INFO *info);
+ static void rx_reset_buffers(MGSLPC_INFO *info);
+ static int rx_alloc_buffers(MGSLPC_INFO *info);
+ static void rx_free_buffers(MGSLPC_INFO *info);
+@@ -503,20 +503,9 @@ static void* mgslpc_get_text_ptr(void)
+ * The wrappers maintain line discipline references
+ * while calling into the line discipline.
+ *
+- * ldisc_flush_buffer - flush line discipline receive buffers
+ * ldisc_receive_buf - pass receive data to line discipline
+ */
+
+-static void ldisc_flush_buffer(struct tty_struct *tty)
+-{
+- struct tty_ldisc *ld = tty_ldisc_ref(tty);
+- if (ld) {
+- if (ld->flush_buffer)
+- ld->flush_buffer(tty);
+- tty_ldisc_deref(ld);
+- }
+-}
+-
+ static void ldisc_receive_buf(struct tty_struct *tty,
+ const __u8 *data, char *flags, int count)
+ {
+@@ -719,7 +708,7 @@ static int mgslpc_resume(struct pcmcia_device *link)
+ }
+
+
+-static inline int mgslpc_paranoia_check(MGSLPC_INFO *info,
++static inline bool mgslpc_paranoia_check(MGSLPC_INFO *info,
+ char *name, const char *routine)
+ {
+ #ifdef MGSLPC_PARANOIA_CHECK
+@@ -730,17 +719,17 @@ static inline int mgslpc_paranoia_check(MGSLPC_INFO *info,
+
+ if (!info) {
+ printk(badinfo, name, routine);
+- return 1;
++ return true;
+ }
+ if (info->magic != MGSLPC_MAGIC) {
+ printk(badmagic, name, routine);
+- return 1;
++ return true;
+ }
+ #else
+ if (!info)
+- return 1;
++ return true;
+ #endif
+- return 0;
++ return false;
+ }
+
+
+@@ -752,16 +741,16 @@ static inline int mgslpc_paranoia_check(MGSLPC_INFO *info,
+ #define CMD_TXEOM BIT1 // transmit end message
+ #define CMD_TXRESET BIT0 // transmit reset
+
+-static BOOLEAN wait_command_complete(MGSLPC_INFO *info, unsigned char channel)
++static bool wait_command_complete(MGSLPC_INFO *info, unsigned char channel)
+ {
+ int i = 0;
+ /* wait for command completion */
+ while (read_reg(info, (unsigned char)(channel+STAR)) & BIT2) {
+ udelay(1);
+ if (i++ == 1000)
+- return FALSE;
++ return false;
+ }
+- return TRUE;
++ return true;
+ }
+
+ static void issue_command(MGSLPC_INFO *info, unsigned char channel, unsigned char cmd)
+@@ -825,8 +814,8 @@ static int bh_action(MGSLPC_INFO *info)
+
+ if (!rc) {
+ /* Mark BH routine as complete */
+- info->bh_running = 0;
+- info->bh_requested = 0;
++ info->bh_running = false;
++ info->bh_requested = false;
+ }
+
+ spin_unlock_irqrestore(&info->lock,flags);
+@@ -846,7 +835,7 @@ static void bh_handler(struct work_struct *work)
+ printk( "%s(%d):bh_handler(%s) entry\n",
+ __FILE__,__LINE__,info->device_name);
+
+- info->bh_running = 1;
++ info->bh_running = true;
+
+ while((action = bh_action(info)) != 0) {
+
+@@ -913,7 +902,7 @@ static void rx_ready_hdlc(MGSLPC_INFO *info, int eom)
+ /* no more free buffers */
+ issue_command(info, CHA, CMD_RXRESET);
+ info->pending_bh |= BH_RECEIVE;
+- info->rx_overflow = 1;
++ info->rx_overflow = true;
+ info->icount.buf_overrun++;
+ return;
+ }
+@@ -1032,8 +1021,8 @@ static void tx_done(MGSLPC_INFO *info)
+ if (!info->tx_active)
+ return;
+
+- info->tx_active = 0;
+- info->tx_aborting = 0;
++ info->tx_active = false;
++ info->tx_aborting = false;
+
+ if (info->params.mode == MGSL_MODE_ASYNC)
+ return;
+@@ -1047,7 +1036,7 @@ static void tx_done(MGSLPC_INFO *info)
+ info->serial_signals &= ~SerialSignal_RTS;
+ set_signals(info);
+ }
+- info->drop_rts_on_tx_done = 0;
++ info->drop_rts_on_tx_done = false;
+ }
+
+ #if SYNCLINK_GENERIC_HDLC
+@@ -1081,7 +1070,7 @@ static void tx_ready(MGSLPC_INFO *info)
+ return;
+ }
+ if (!info->tx_count)
+- info->tx_active = 0;
++ info->tx_active = false;
+ }
+
+ if (!info->tx_count)
+@@ -1225,17 +1214,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;
+@@ -1263,7 +1250,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id)
+ {
+ isr = read_reg16(info, CHA + ISR);
+ if (isr & IRQ_TIMER) {
+- info->irq_occurred = 1;
++ info->irq_occurred = true;
+ irq_disable(info, CHA, IRQ_TIMER);
+ }
+
+@@ -1320,14 +1307,14 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id)
+ printk("%s(%d):%s queueing bh task.\n",
+ __FILE__,__LINE__,info->device_name);
+ schedule_work(&info->task);
+- info->bh_requested = 1;
++ info->bh_requested = true;
+ }
+
+ spin_unlock(&info->lock);
+
+ 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;
+ }
+@@ -1558,7 +1545,7 @@ static void mgslpc_change_params(MGSLPC_INFO *info)
+
+ /* Add a character to the transmit buffer
+ */
+-static void mgslpc_put_char(struct tty_struct *tty, unsigned char ch)
++static int mgslpc_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
+ unsigned long flags;
+@@ -1569,10 +1556,10 @@ static void mgslpc_put_char(struct tty_struct *tty, unsigned char ch)
+ }
+
+ if (mgslpc_paranoia_check(info, tty->name, "mgslpc_put_char"))
+- return;
++ return 0;
+
+ if (!info->tx_buf)
+- return;
++ return 0;
+
+ spin_lock_irqsave(&info->lock,flags);
+
+@@ -1585,6 +1572,7 @@ static void mgslpc_put_char(struct tty_struct *tty, unsigned char ch)
+ }
+
+ spin_unlock_irqrestore(&info->lock,flags);
++ return 1;
+ }
+
+ /* Enable transmitter so remaining characters in the
+@@ -1992,7 +1980,7 @@ static int tx_abort(MGSLPC_INFO * info)
+ * This results in underrun and abort transmission.
+ */
+ info->tx_count = info->tx_put = info->tx_get = 0;
+- info->tx_aborting = TRUE;
++ info->tx_aborting = true;
+ }
+ spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
+@@ -2469,10 +2457,9 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp)
+ if (info->flags & ASYNC_INITIALIZED)
+ mgslpc_wait_until_sent(tty, info->timeout);
+
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ mgslpc_flush_buffer(tty);
+
+- ldisc_flush_buffer(tty);
++ tty_ldisc_flush(tty);
+
+ shutdown(info);
+
+@@ -2591,7 +2578,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
+ {
+ DECLARE_WAITQUEUE(wait, current);
+ int retval;
+- int do_clocal = 0, extra_count = 0;
++ bool do_clocal = false;
++ bool extra_count = false;
+ unsigned long flags;
+
+ if (debug_level >= DEBUG_LEVEL_INFO)
+@@ -2606,7 +2594,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
+ }
+
+ if (tty->termios->c_cflag & CLOCAL)
+- do_clocal = 1;
++ do_clocal = true;
+
+ /* Wait for carrier detect and the line to become
+ * free (i.e., not in use by the callout). While we are in
+@@ -2624,7 +2612,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
+
+ spin_lock_irqsave(&info->lock, flags);
+ if (!tty_hung_up_p(filp)) {
+- extra_count = 1;
++ extra_count = true;
+ info->count--;
+ }
+ spin_unlock_irqrestore(&info->lock, flags);
+@@ -3495,8 +3483,8 @@ static void rx_stop(MGSLPC_INFO *info)
+ /* MODE:03 RAC Receiver Active, 0=inactive */
+ clear_reg_bits(info, CHA + MODE, BIT3);
+
+- info->rx_enabled = 0;
+- info->rx_overflow = 0;
++ info->rx_enabled = false;
++ info->rx_overflow = false;
+ }
+
+ static void rx_start(MGSLPC_INFO *info)
+@@ -3506,13 +3494,13 @@ static void rx_start(MGSLPC_INFO *info)
+ __FILE__,__LINE__, info->device_name );
+
+ rx_reset_buffers(info);
+- info->rx_enabled = 0;
+- info->rx_overflow = 0;
++ info->rx_enabled = false;
++ info->rx_overflow = false;
+
+ /* MODE:03 RAC Receiver Active, 1=active */
+ set_reg_bits(info, CHA + MODE, BIT3);
+
+- info->rx_enabled = 1;
++ info->rx_enabled = true;
+ }
+
+ static void tx_start(MGSLPC_INFO *info)
+@@ -3525,24 +3513,24 @@ static void tx_start(MGSLPC_INFO *info)
+ /* If auto RTS enabled and RTS is inactive, then assert */
+ /* RTS and set a flag indicating that the driver should */
+ /* negate RTS when the transmission completes. */
+- info->drop_rts_on_tx_done = 0;
++ info->drop_rts_on_tx_done = false;
+
+ if (info->params.flags & HDLC_FLAG_AUTO_RTS) {
+ get_signals(info);
+ if (!(info->serial_signals & SerialSignal_RTS)) {
+ info->serial_signals |= SerialSignal_RTS;
+ set_signals(info);
+- info->drop_rts_on_tx_done = 1;
++ info->drop_rts_on_tx_done = true;
+ }
+ }
+
+ if (info->params.mode == MGSL_MODE_ASYNC) {
+ if (!info->tx_active) {
+- info->tx_active = 1;
++ info->tx_active = true;
+ tx_ready(info);
+ }
+ } else {
+- info->tx_active = 1;
++ info->tx_active = true;
+ tx_ready(info);
+ mod_timer(&info->tx_timer, jiffies +
+ msecs_to_jiffies(5000));
+@@ -3550,7 +3538,7 @@ static void tx_start(MGSLPC_INFO *info)
+ }
+
+ if (!info->tx_enabled)
+- info->tx_enabled = 1;
++ info->tx_enabled = true;
+ }
+
+ static void tx_stop(MGSLPC_INFO *info)
+@@ -3561,8 +3549,8 @@ static void tx_stop(MGSLPC_INFO *info)
+
+ del_timer(&info->tx_timer);
+
+- info->tx_enabled = 0;
+- info->tx_active = 0;
++ info->tx_enabled = false;
++ info->tx_active = false;
+ }
+
+ /* Reset the adapter to a known state and prepare it for further use.
+@@ -3862,19 +3850,19 @@ static void rx_reset_buffers(MGSLPC_INFO *info)
+ /* Attempt to return a received HDLC frame
+ * Only frames received without errors are returned.
+ *
+- * Returns 1 if frame returned, otherwise 0
++ * Returns true if frame returned, otherwise false
+ */
+-static int rx_get_frame(MGSLPC_INFO *info)
++static bool rx_get_frame(MGSLPC_INFO *info)
+ {
+ unsigned short status;
+ RXBUF *buf;
+ unsigned int framesize = 0;
+ unsigned long flags;
+ struct tty_struct *tty = info->tty;
+- int return_frame = 0;
++ bool return_frame = false;
+
+ if (info->rx_frame_count == 0)
+- return 0;
++ return false;
+
+ buf = (RXBUF*)(info->rx_buf + (info->rx_get * info->rx_buf_size));
+
+@@ -3893,7 +3881,7 @@ static int rx_get_frame(MGSLPC_INFO *info)
+ else if (!(status & BIT5)) {
+ info->icount.rxcrc++;
+ if (info->params.crc_type & HDLC_CRC_RETURN_EX)
+- return_frame = 1;
++ return_frame = true;
+ }
+ framesize = 0;
+ #if SYNCLINK_GENERIC_HDLC
+@@ -3904,7 +3892,7 @@ static int rx_get_frame(MGSLPC_INFO *info)
+ }
+ #endif
+ } else
+- return_frame = 1;
++ return_frame = true;
+
+ if (return_frame)
+ framesize = buf->count;
+@@ -3947,16 +3935,16 @@ static int rx_get_frame(MGSLPC_INFO *info)
+ info->rx_get = 0;
+ spin_unlock_irqrestore(&info->lock,flags);
+
+- return 1;
++ return true;
+ }
+
+-static BOOLEAN register_test(MGSLPC_INFO *info)
++static bool register_test(MGSLPC_INFO *info)
+ {
+ static unsigned char patterns[] =
+ { 0x00, 0xff, 0xaa, 0x55, 0x69, 0x96, 0x0f };
+ static unsigned int count = ARRAY_SIZE(patterns);
+ unsigned int i;
+- BOOLEAN rc = TRUE;
++ bool rc = true;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock,flags);
+@@ -3967,7 +3955,7 @@ static BOOLEAN register_test(MGSLPC_INFO *info)
+ write_reg(info, XAD2, patterns[(i + 1) % count]);
+ if ((read_reg(info, XAD1) != patterns[i]) ||
+ (read_reg(info, XAD2) != patterns[(i + 1) % count])) {
+- rc = FALSE;
++ rc = false;
+ break;
+ }
+ }
+@@ -3976,7 +3964,7 @@ static BOOLEAN register_test(MGSLPC_INFO *info)
+ return rc;
+ }
+
+-static BOOLEAN irq_test(MGSLPC_INFO *info)
++static bool irq_test(MGSLPC_INFO *info)
+ {
+ unsigned long end_time;
+ unsigned long flags;
+@@ -3984,10 +3972,10 @@ static BOOLEAN irq_test(MGSLPC_INFO *info)
+ spin_lock_irqsave(&info->lock,flags);
+ reset_device(info);
+
+- info->testing_irq = TRUE;
++ info->testing_irq = true;
+ hdlc_mode(info);
+
+- info->irq_occurred = FALSE;
++ info->irq_occurred = false;
+
+ /* init hdlc mode */
+
+@@ -4002,13 +3990,13 @@ static BOOLEAN irq_test(MGSLPC_INFO *info)
+ msleep_interruptible(10);
+ }
+
+- info->testing_irq = FALSE;
++ info->testing_irq = false;
+
+ spin_lock_irqsave(&info->lock,flags);
+ reset_device(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+- return info->irq_occurred ? TRUE : FALSE;
++ return info->irq_occurred;
+ }
+
+ static int adapter_test(MGSLPC_INFO *info)
+@@ -4081,7 +4069,7 @@ static void tx_timeout(unsigned long context)
+ info->icount.txtimeout++;
+ }
+ spin_lock_irqsave(&info->lock,flags);
+- info->tx_active = 0;
++ info->tx_active = false;
+ info->tx_count = info->tx_put = info->tx_get = 0;
+
+ spin_unlock_irqrestore(&info->lock,flags);
+diff --git a/drivers/char/pty.c b/drivers/char/pty.c
+index 706ff34..0a05c03 100644
+--- a/drivers/char/pty.c
++++ b/drivers/char/pty.c
+@@ -181,6 +181,7 @@ static int pty_set_lock(struct tty_struct *tty, int __user * arg)
+ static void pty_flush_buffer(struct tty_struct *tty)
+ {
+ struct tty_struct *to = tty->link;
++ unsigned long flags;
+
+ if (!to)
+ return;
+@@ -189,8 +190,10 @@ static void pty_flush_buffer(struct tty_struct *tty)
+ to->ldisc.flush_buffer(to);
+
+ if (to->packet) {
++ spin_lock_irqsave(&tty->ctrl_lock, flags);
+ tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
+ wake_up_interruptible(&to->read_wait);
++ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ }
+ }
+
+@@ -251,6 +254,18 @@ static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file,
+ static int legacy_count = CONFIG_LEGACY_PTY_COUNT;
+ module_param(legacy_count, int, 0);
+
++static const struct tty_operations pty_ops_bsd = {
++ .open = pty_open,
++ .close = pty_close,
++ .write = pty_write,
++ .write_room = pty_write_room,
++ .flush_buffer = pty_flush_buffer,
++ .chars_in_buffer = pty_chars_in_buffer,
++ .unthrottle = pty_unthrottle,
++ .set_termios = pty_set_termios,
++ .ioctl = pty_bsd_ioctl,
++};
++
+ static void __init legacy_pty_init(void)
+ {
+ if (legacy_count <= 0)
+@@ -281,7 +296,6 @@ static void __init legacy_pty_init(void)
+ pty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW;
+ pty_driver->other = pty_slave_driver;
+ tty_set_operations(pty_driver, &pty_ops);
+- pty_driver->ioctl = pty_bsd_ioctl;
+
+ pty_slave_driver->owner = THIS_MODULE;
+ pty_slave_driver->driver_name = "pty_slave";
+@@ -374,6 +388,19 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
+ return -ENOIOCTLCMD;
+ }
+
++static const struct tty_operations pty_unix98_ops = {
++ .open = pty_open,
++ .close = pty_close,
++ .write = pty_write,
++ .write_room = pty_write_room,
++ .flush_buffer = pty_flush_buffer,
++ .chars_in_buffer = pty_chars_in_buffer,
++ .unthrottle = pty_unthrottle,
++ .set_termios = pty_set_termios,
++ .ioctl = pty_unix98_ioctl
++};
++
++
+ static void __init unix98_pty_init(void)
+ {
+ ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
+@@ -400,8 +427,7 @@ static void __init unix98_pty_init(void)
+ ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
+ ptm_driver->other = pts_driver;
+- tty_set_operations(ptm_driver, &pty_ops);
+- ptm_driver->ioctl = pty_unix98_ioctl;
++ tty_set_operations(ptm_driver, &pty_unix98_ops);
+
+ pts_driver->owner = THIS_MODULE;
+ pts_driver->driver_name = "pty_slave";
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index f43c89f..0cf98bd 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -272,7 +272,7 @@ static int random_write_wakeup_thresh = 128;
+
+ static int trickle_thresh __read_mostly = INPUT_POOL_WORDS * 28;
+
+-static DEFINE_PER_CPU(int, trickle_count) = 0;
++static DEFINE_PER_CPU(int, trickle_count);
+
+ /*
+ * A pool of size .poolwords is stirred with a primitive polynomial
+@@ -370,17 +370,19 @@ static struct poolinfo {
+ */
+ static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
+ static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
++static struct fasync_struct *fasync;
+
+ #if 0
+-static int debug = 0;
++static int debug;
+ module_param(debug, bool, 0644);
+-#define DEBUG_ENT(fmt, arg...) do { if (debug) \
+- printk(KERN_DEBUG "random %04d %04d %04d: " \
+- fmt,\
+- input_pool.entropy_count,\
+- blocking_pool.entropy_count,\
+- nonblocking_pool.entropy_count,\
+- ## arg); } while (0)
++#define DEBUG_ENT(fmt, arg...) do { \
++ if (debug) \
++ printk(KERN_DEBUG "random %04d %04d %04d: " \
++ fmt,\
++ input_pool.entropy_count,\
++ blocking_pool.entropy_count,\
++ nonblocking_pool.entropy_count,\
++ ## arg); } while (0)
+ #else
+ #define DEBUG_ENT(fmt, arg...) do {} while (0)
+ #endif
+@@ -394,7 +396,7 @@ module_param(debug, bool, 0644);
+
+ struct entropy_store;
+ struct entropy_store {
+- /* mostly-read data: */
++ /* read-only data: */
+ struct poolinfo *poolinfo;
+ __u32 *pool;
+ const char *name;
+@@ -402,7 +404,7 @@ struct entropy_store {
+ struct entropy_store *pull;
+
+ /* read-write data: */
+- spinlock_t lock ____cacheline_aligned_in_smp;
++ spinlock_t lock;
+ unsigned add_ptr;
+ int entropy_count;
+ int input_rotate;
+@@ -438,25 +440,26 @@ static struct entropy_store nonblocking_pool = {
+ };
+
+ /*
+- * This function adds a byte into the entropy "pool". It does not
++ * This function adds bytes into the entropy "pool". It does not
+ * update the entropy estimate. The caller should call
+- * credit_entropy_store if this is appropriate.
++ * credit_entropy_bits if this is appropriate.
+ *
+ * The pool is stirred with a primitive polynomial of the appropriate
+ * degree, and then twisted. We twist by three bits at a time because
+ * it's cheap to do so and helps slightly in the expected case where
+ * the entropy is concentrated in the low-order bits.
+ */
+-static void __add_entropy_words(struct entropy_store *r, const __u32 *in,
+- int nwords, __u32 out[16])
++static void mix_pool_bytes_extract(struct entropy_store *r, const void *in,
++ int nbytes, __u8 out[64])
+ {
+ static __u32 const twist_table[8] = {
+ 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+ 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+- unsigned long i, add_ptr, tap1, tap2, tap3, tap4, tap5;
+- int new_rotate, input_rotate;
++ unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
++ int input_rotate;
+ int wordmask = r->poolinfo->poolwords - 1;
+- __u32 w, next_w;
++ const char *bytes = in;
++ __u32 w;
+ unsigned long flags;
+
+ /* Taps are constant, so we can load them without holding r->lock. */
+@@ -465,78 +468,76 @@ static void __add_entropy_words(struct entropy_store *r, const __u32 *in,
+ tap3 = r->poolinfo->tap3;
+ tap4 = r->poolinfo->tap4;
+ tap5 = r->poolinfo->tap5;
+- next_w = *in++;
+
+ spin_lock_irqsave(&r->lock, flags);
+- prefetch_range(r->pool, wordmask);
+ input_rotate = r->input_rotate;
+- add_ptr = r->add_ptr;
++ i = r->add_ptr;
+
+- while (nwords--) {
+- w = rol32(next_w, input_rotate);
+- if (nwords > 0)
+- next_w = *in++;
+- i = add_ptr = (add_ptr - 1) & wordmask;
+- /*
+- * Normally, we add 7 bits of rotation to the pool.
+- * At the beginning of the pool, add an extra 7 bits
+- * rotation, so that successive passes spread the
+- * input bits across the pool evenly.
+- */
+- new_rotate = input_rotate + 14;
+- if (i)
+- new_rotate = input_rotate + 7;
+- input_rotate = new_rotate & 31;
++ /* mix one byte at a time to simplify size handling and churn faster */
++ while (nbytes--) {
++ w = rol32(*bytes++, input_rotate & 31);
++ i = (i - 1) & wordmask;
+
+ /* XOR in the various taps */
++ w ^= r->pool[i];
+ w ^= r->pool[(i + tap1) & wordmask];
+ w ^= r->pool[(i + tap2) & wordmask];
+ w ^= r->pool[(i + tap3) & wordmask];
+ w ^= r->pool[(i + tap4) & wordmask];
+ w ^= r->pool[(i + tap5) & wordmask];
+- w ^= r->pool[i];
++
++ /* Mix the result back in with a twist */
+ r->pool[i] = (w >> 3) ^ twist_table[w & 7];
++
++ /*
++ * Normally, we add 7 bits of rotation to the pool.
++ * At the beginning of the pool, add an extra 7 bits
++ * rotation, so that successive passes spread the
++ * input bits across the pool evenly.
++ */
++ input_rotate += i ? 7 : 14;
+ }
+
+ r->input_rotate = input_rotate;
+- r->add_ptr = add_ptr;
++ r->add_ptr = i;
+
+- if (out) {
+- for (i = 0; i < 16; i++) {
+- out[i] = r->pool[add_ptr];
+- add_ptr = (add_ptr - 1) & wordmask;
+- }
+- }
++ if (out)
++ for (j = 0; j < 16; j++)
++ ((__u32 *)out)[j] = r->pool[(i - j) & wordmask];
+
+ spin_unlock_irqrestore(&r->lock, flags);
+ }
+
+-static inline void add_entropy_words(struct entropy_store *r, const __u32 *in,
+- int nwords)
++static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes)
+ {
+- __add_entropy_words(r, in, nwords, NULL);
++ mix_pool_bytes_extract(r, in, bytes, NULL);
+ }
+
+ /*
+ * Credit (or debit) the entropy store with n bits of entropy
+ */
+-static void credit_entropy_store(struct entropy_store *r, int nbits)
++static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ {
+ unsigned long flags;
+
++ if (!nbits)
++ return;
++
+ spin_lock_irqsave(&r->lock, flags);
+
+- if (r->entropy_count + nbits < 0) {
+- DEBUG_ENT("negative entropy/overflow (%d+%d)\n",
+- r->entropy_count, nbits);
++ DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
++ r->entropy_count += nbits;
++ if (r->entropy_count < 0) {
++ DEBUG_ENT("negative entropy/overflow\n");
+ r->entropy_count = 0;
+- } else if (r->entropy_count + nbits > r->poolinfo->POOLBITS) {
++ } else if (r->entropy_count > r->poolinfo->POOLBITS)
+ r->entropy_count = r->poolinfo->POOLBITS;
+- } else {
+- r->entropy_count += nbits;
+- if (nbits)
+- DEBUG_ENT("added %d entropy credits to %s\n",
+- nbits, r->name);
++
++ /* should we wake readers? */
++ if (r == &input_pool &&
++ r->entropy_count >= random_read_wakeup_thresh) {
++ wake_up_interruptible(&random_read_wait);
++ kill_fasync(&fasync, SIGIO, POLL_IN);
+ }
+
+ spin_unlock_irqrestore(&r->lock, flags);
+@@ -551,7 +552,7 @@ static void credit_entropy_store(struct entropy_store *r, int nbits)
+ /* There is one of these per entropy source */
+ struct timer_rand_state {
+ cycles_t last_time;
+- long last_delta,last_delta2;
++ long last_delta, last_delta2;
+ unsigned dont_count_entropy:1;
+ };
+
+@@ -586,7 +587,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
+ sample.jiffies = jiffies;
+ sample.cycles = get_cycles();
+ sample.num = num;
+- add_entropy_words(&input_pool, (u32 *)&sample, sizeof(sample)/4);
++ mix_pool_bytes(&input_pool, &sample, sizeof(sample));
+
+ /*
+ * Calculate number of bits of randomness we probably added.
+@@ -620,13 +621,9 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
+ * Round down by 1 bit on general principles,
+ * and limit entropy entimate to 12 bits.
+ */
+- credit_entropy_store(&input_pool,
+- min_t(int, fls(delta>>1), 11));
++ credit_entropy_bits(&input_pool,
++ min_t(int, fls(delta>>1), 11));
+ }
+-
+- if(input_pool.entropy_count >= random_read_wakeup_thresh)
+- wake_up_interruptible(&random_read_wait);
+-
+ out:
+ preempt_enable();
+ }
+@@ -677,7 +674,7 @@ void add_disk_randomness(struct gendisk *disk)
+ *
+ *********************************************************************/
+
+-static ssize_t extract_entropy(struct entropy_store *r, void * buf,
++static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+ size_t nbytes, int min, int rsvd);
+
+ /*
+@@ -704,10 +701,10 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
+ "(%d of %d requested)\n",
+ r->name, bytes * 8, nbytes * 8, r->entropy_count);
+
+- bytes=extract_entropy(r->pull, tmp, bytes,
+- random_read_wakeup_thresh / 8, rsvd);
+- add_entropy_words(r, tmp, (bytes + 3) / 4);
+- credit_entropy_store(r, bytes*8);
++ bytes = extract_entropy(r->pull, tmp, bytes,
++ random_read_wakeup_thresh / 8, rsvd);
++ mix_pool_bytes(r, tmp, bytes);
++ credit_entropy_bits(r, bytes*8);
+ }
+ }
+
+@@ -744,13 +741,15 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
+ if (r->limit && nbytes + reserved >= r->entropy_count / 8)
+ nbytes = r->entropy_count/8 - reserved;
+
+- if(r->entropy_count / 8 >= nbytes + reserved)
++ if (r->entropy_count / 8 >= nbytes + reserved)
+ r->entropy_count -= nbytes*8;
+ else
+ r->entropy_count = reserved;
+
+- if (r->entropy_count < random_write_wakeup_thresh)
++ if (r->entropy_count < random_write_wakeup_thresh) {
+ wake_up_interruptible(&random_write_wait);
++ kill_fasync(&fasync, SIGIO, POLL_OUT);
++ }
+ }
+
+ DEBUG_ENT("debiting %d entropy credits from %s%s\n",
+@@ -764,45 +763,46 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
+ static void extract_buf(struct entropy_store *r, __u8 *out)
+ {
+ int i;
+- __u32 data[16], buf[5 + SHA_WORKSPACE_WORDS];
++ __u32 hash[5], workspace[SHA_WORKSPACE_WORDS];
++ __u8 extract[64];
++
++ /* Generate a hash across the pool, 16 words (512 bits) at a time */
++ sha_init(hash);
++ for (i = 0; i < r->poolinfo->poolwords; i += 16)
++ sha_transform(hash, (__u8 *)(r->pool + i), workspace);
+
+- sha_init(buf);
+ /*
+- * As we hash the pool, we mix intermediate values of
+- * the hash back into the pool. This eliminates
+- * backtracking attacks (where the attacker knows
+- * the state of the pool plus the current outputs, and
+- * attempts to find previous ouputs), unless the hash
+- * function can be inverted.
++ * We mix the hash back into the pool to prevent backtracking
++ * attacks (where the attacker knows the state of the pool
++ * plus the current outputs, and attempts to find previous
++ * ouputs), unless the hash function can be inverted. By
++ * mixing at least a SHA1 worth of hash data back, we make
++ * brute-forcing the feedback as hard as brute-forcing the
++ * hash.
+ */
+- for (i = 0; i < r->poolinfo->poolwords; i += 16) {
+- /* hash blocks of 16 words = 512 bits */
+- sha_transform(buf, (__u8 *)(r->pool + i), buf + 5);
+- /* feed back portion of the resulting hash */
+- add_entropy_words(r, &buf[i % 5], 1);
+- }
++ mix_pool_bytes_extract(r, hash, sizeof(hash), extract);
+
+ /*
+- * To avoid duplicates, we atomically extract a
+- * portion of the pool while mixing, and hash one
+- * final time.
++ * To avoid duplicates, we atomically extract a portion of the
++ * pool while mixing, and hash one final time.
+ */
+- __add_entropy_words(r, &buf[i % 5], 1, data);
+- sha_transform(buf, (__u8 *)data, buf + 5);
++ sha_transform(hash, extract, workspace);
++ memset(extract, 0, sizeof(extract));
++ memset(workspace, 0, sizeof(workspace));
+
+ /*
+- * In case the hash function has some recognizable
+- * output pattern, we fold it in half.
++ * In case the hash function has some recognizable output
++ * pattern, we fold it in half. Thus, we always feed back
++ * twice as much data as we output.
+ */
+-
+- buf[0] ^= buf[3];
+- buf[1] ^= buf[4];
+- buf[2] ^= rol32(buf[2], 16);
+- memcpy(out, buf, EXTRACT_SIZE);
+- memset(buf, 0, sizeof(buf));
++ hash[0] ^= hash[3];
++ hash[1] ^= hash[4];
++ hash[2] ^= rol32(hash[2], 16);
++ memcpy(out, hash, EXTRACT_SIZE);
++ memset(hash, 0, sizeof(hash));
+ }
+
+-static ssize_t extract_entropy(struct entropy_store *r, void * buf,
++static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+ size_t nbytes, int min, int reserved)
+ {
+ ssize_t ret = 0, i;
+@@ -872,7 +872,6 @@ void get_random_bytes(void *buf, int nbytes)
+ {
+ extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
+ }
+-
+ EXPORT_SYMBOL(get_random_bytes);
+
+ /*
+@@ -894,12 +893,11 @@ static void init_std_data(struct entropy_store *r)
+ spin_unlock_irqrestore(&r->lock, flags);
+
+ now = ktime_get_real();
+- add_entropy_words(r, (__u32 *)&now, sizeof(now)/4);
+- add_entropy_words(r, (__u32 *)utsname(),
+- sizeof(*(utsname()))/4);
++ mix_pool_bytes(r, &now, sizeof(now));
++ mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
+ }
+
+-static int __init rand_initialize(void)
++static int rand_initialize(void)
+ {
+ init_std_data(&input_pool);
+ init_std_data(&blocking_pool);
+@@ -940,7 +938,7 @@ void rand_initialize_disk(struct gendisk *disk)
+ #endif
+
+ static ssize_t
+-random_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
++random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ {
+ ssize_t n, retval = 0, count = 0;
+
+@@ -1002,8 +1000,7 @@ random_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
+ }
+
+ static ssize_t
+-urandom_read(struct file * file, char __user * buf,
+- size_t nbytes, loff_t *ppos)
++urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ {
+ return extract_entropy_user(&nonblocking_pool, buf, nbytes);
+ }
+@@ -1038,16 +1035,15 @@ write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
+ count -= bytes;
+ p += bytes;
+
+- add_entropy_words(r, buf, (bytes + 3) / 4);
++ mix_pool_bytes(r, buf, bytes);
+ cond_resched();
+ }
+
+ return 0;
+ }
+
+-static ssize_t
+-random_write(struct file * file, const char __user * buffer,
+- size_t count, loff_t *ppos)
++static ssize_t random_write(struct file *file, const char __user *buffer,
++ size_t count, loff_t *ppos)
+ {
+ size_t ret;
+ struct inode *inode = file->f_path.dentry->d_inode;
+@@ -1064,9 +1060,7 @@ random_write(struct file * file, const char __user * buffer,
+ return (ssize_t)count;
+ }
+
+-static int
+-random_ioctl(struct inode * inode, struct file * file,
+- unsigned int cmd, unsigned long arg)
++static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+ {
+ int size, ent_count;
+ int __user *p = (int __user *)arg;
+@@ -1074,8 +1068,8 @@ random_ioctl(struct inode * inode, struct file * file,
+
+ switch (cmd) {
+ case RNDGETENTCNT:
+- ent_count = input_pool.entropy_count;
+- if (put_user(ent_count, p))
++ /* inherently racy, no point locking */
++ if (put_user(input_pool.entropy_count, p))
+ return -EFAULT;
+ return 0;
+ case RNDADDTOENTCNT:
+@@ -1083,13 +1077,7 @@ random_ioctl(struct inode * inode, struct file * file,
+ return -EPERM;
+ if (get_user(ent_count, p))
+ return -EFAULT;
+- credit_entropy_store(&input_pool, ent_count);
+- /*
+- * Wake up waiting processes if we have enough
+- * entropy.
+- */
+- if (input_pool.entropy_count >= random_read_wakeup_thresh)
+- wake_up_interruptible(&random_read_wait);
++ credit_entropy_bits(&input_pool, ent_count);
+ return 0;
+ case RNDADDENTROPY:
+ if (!capable(CAP_SYS_ADMIN))
+@@ -1104,39 +1092,45 @@ random_ioctl(struct inode * inode, struct file * file,
+ size);
+ if (retval < 0)
+ return retval;
+- credit_entropy_store(&input_pool, ent_count);
+- /*
+- * Wake up waiting processes if we have enough
+- * entropy.
+- */
+- if (input_pool.entropy_count >= random_read_wakeup_thresh)
+- wake_up_interruptible(&random_read_wait);
++ credit_entropy_bits(&input_pool, ent_count);
+ return 0;
+ case RNDZAPENTCNT:
+ case RNDCLEARPOOL:
+ /* Clear the entropy pool counters. */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+- init_std_data(&input_pool);
+- init_std_data(&blocking_pool);
+- init_std_data(&nonblocking_pool);
++ rand_initialize();
+ return 0;
+ default:
+ return -EINVAL;
+ }
+ }
+
++static int random_fasync(int fd, struct file *filp, int on)
++{
++ return fasync_helper(fd, filp, on, &fasync);
++}
++
++static int random_release(struct inode *inode, struct file *filp)
++{
++ return fasync_helper(-1, filp, 0, &fasync);
++}
++
+ const struct file_operations random_fops = {
+ .read = random_read,
+ .write = random_write,
+ .poll = random_poll,
+- .ioctl = random_ioctl,
++ .unlocked_ioctl = random_ioctl,
++ .fasync = random_fasync,
++ .release = random_release,
+ };
+
+ const struct file_operations urandom_fops = {
+ .read = urandom_read,
+ .write = random_write,
+- .ioctl = random_ioctl,
++ .unlocked_ioctl = random_ioctl,
++ .fasync = random_fasync,
++ .release = random_release,
+ };
+
+ /***************************************************************
+@@ -1157,7 +1151,6 @@ void generate_random_uuid(unsigned char uuid_out[16])
+ /* Set the UUID variant to DCE */
+ uuid_out[8] = (uuid_out[8] & 0x3F) | 0x80;
+ }
+-
+ EXPORT_SYMBOL(generate_random_uuid);
+
+ /********************************************************************
+@@ -1339,7 +1332,7 @@ ctl_table random_table[] = {
+
+ #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+
+-static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12])
++static __u32 twothirdsMD4Transform(__u32 const buf[4], __u32 const in[12])
+ {
+ __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+
+@@ -1487,8 +1480,8 @@ __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
+ */
+
+ memcpy(hash, saddr, 16);
+- hash[4]=((__force u16)sport << 16) + (__force u16)dport;
+- memcpy(&hash[5],keyptr->secret,sizeof(__u32) * 7);
++ hash[4] = ((__force u16)sport << 16) + (__force u16)dport;
++ memcpy(&hash[5], keyptr->secret, sizeof(__u32) * 7);
+
+ seq = twothirdsMD4Transform((const __u32 *)daddr, hash) & HASH_MASK;
+ seq += keyptr->count;
+@@ -1538,10 +1531,10 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
+ * Note that the words are placed into the starting vector, which is
+ * then mixed with a partial MD4 over random data.
+ */
+- hash[0]=(__force u32)saddr;
+- hash[1]=(__force u32)daddr;
+- hash[2]=((__force u16)sport << 16) + (__force u16)dport;
+- hash[3]=keyptr->secret[11];
++ hash[0] = (__force u32)saddr;
++ hash[1] = (__force u32)daddr;
++ hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
++ hash[3] = keyptr->secret[11];
+
+ seq = half_md4_transform(hash, keyptr->secret) & HASH_MASK;
+ seq += keyptr->count;
+@@ -1556,10 +1549,7 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
+ * Choosing a clock of 64 ns period is OK. (period of 274 s)
+ */
+ seq += ktime_to_ns(ktime_get_real()) >> 6;
+-#if 0
+- printk("init_seq(%lx, %lx, %d, %d) = %d\n",
+- saddr, daddr, sport, dport, seq);
+-#endif
++
+ return seq;
+ }
+
+@@ -1582,14 +1572,15 @@ u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
+ }
+
+ #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+-u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, __be16 dport)
++u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
++ __be16 dport)
+ {
+ struct keydata *keyptr = get_keyptr();
+ u32 hash[12];
+
+ memcpy(hash, saddr, 16);
+ hash[4] = (__force u32)dport;
+- memcpy(&hash[5],keyptr->secret,sizeof(__u32) * 7);
++ memcpy(&hash[5], keyptr->secret, sizeof(__u32) * 7);
+
+ return twothirdsMD4Transform((const __u32 *)daddr, hash);
+ }
+@@ -1617,13 +1608,9 @@ u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
+
+ seq += ktime_to_ns(ktime_get_real());
+ seq &= (1ull << 48) - 1;
+-#if 0
+- printk("dccp init_seq(%lx, %lx, %d, %d) = %d\n",
+- saddr, daddr, sport, dport, seq);
+-#endif
++
+ return seq;
+ }
+-
+ EXPORT_SYMBOL(secure_dccp_sequence_number);
+ #endif
+
+diff --git a/drivers/char/rio/cirrus.h b/drivers/char/rio/cirrus.h
+index f4f837f..a03a538 100644
+--- a/drivers/char/rio/cirrus.h
++++ b/drivers/char/rio/cirrus.h
+@@ -43,83 +43,83 @@
+ /* Bit fields for particular registers shared with driver */
+
+ /* COR1 - driver and RTA */
+-#define COR1_ODD 0x80 /* Odd parity */
+-#define COR1_EVEN 0x00 /* Even parity */
+-#define COR1_NOP 0x00 /* No parity */
+-#define COR1_FORCE 0x20 /* Force parity */
+-#define COR1_NORMAL 0x40 /* With parity */
+-#define COR1_1STOP 0x00 /* 1 stop bit */
+-#define COR1_15STOP 0x04 /* 1.5 stop bits */
+-#define COR1_2STOP 0x08 /* 2 stop bits */
+-#define COR1_5BITS 0x00 /* 5 data bits */
+-#define COR1_6BITS 0x01 /* 6 data bits */
+-#define COR1_7BITS 0x02 /* 7 data bits */
+-#define COR1_8BITS 0x03 /* 8 data bits */
+-
+-#define COR1_HOST 0xef /* Safe host bits */
++#define RIOC_COR1_ODD 0x80 /* Odd parity */
++#define RIOC_COR1_EVEN 0x00 /* Even parity */
++#define RIOC_COR1_NOP 0x00 /* No parity */
++#define RIOC_COR1_FORCE 0x20 /* Force parity */
++#define RIOC_COR1_NORMAL 0x40 /* With parity */
++#define RIOC_COR1_1STOP 0x00 /* 1 stop bit */
++#define RIOC_COR1_15STOP 0x04 /* 1.5 stop bits */
++#define RIOC_COR1_2STOP 0x08 /* 2 stop bits */
++#define RIOC_COR1_5BITS 0x00 /* 5 data bits */
++#define RIOC_COR1_6BITS 0x01 /* 6 data bits */
++#define RIOC_COR1_7BITS 0x02 /* 7 data bits */
++#define RIOC_COR1_8BITS 0x03 /* 8 data bits */
++
++#define RIOC_COR1_HOST 0xef /* Safe host bits */
+
+ /* RTA only */
+-#define COR1_CINPCK 0x00 /* Check parity of received characters */
+-#define COR1_CNINPCK 0x10 /* Don't check parity */
++#define RIOC_COR1_CINPCK 0x00 /* Check parity of received characters */
++#define RIOC_COR1_CNINPCK 0x10 /* Don't check parity */
+
+ /* COR2 bits for both RTA and driver use */
+-#define COR2_IXANY 0x80 /* IXANY - any character is XON */
+-#define COR2_IXON 0x40 /* IXON - enable tx soft flowcontrol */
+-#define COR2_RTSFLOW 0x02 /* Enable tx hardware flow control */
++#define RIOC_COR2_IXANY 0x80 /* IXANY - any character is XON */
++#define RIOC_COR2_IXON 0x40 /* IXON - enable tx soft flowcontrol */
++#define RIOC_COR2_RTSFLOW 0x02 /* Enable tx hardware flow control */
+
+ /* Additional driver bits */
+-#define COR2_HUPCL 0x20 /* Hang up on close */
+-#define COR2_CTSFLOW 0x04 /* Enable rx hardware flow control */
+-#define COR2_IXOFF 0x01 /* Enable rx software flow control */
+-#define COR2_DTRFLOW 0x08 /* Enable tx hardware flow control */
++#define RIOC_COR2_HUPCL 0x20 /* Hang up on close */
++#define RIOC_COR2_CTSFLOW 0x04 /* Enable rx hardware flow control */
++#define RIOC_COR2_IXOFF 0x01 /* Enable rx software flow control */
++#define RIOC_COR2_DTRFLOW 0x08 /* Enable tx hardware flow control */
+
+ /* RTA use only */
+-#define COR2_ETC 0x20 /* Embedded transmit options */
+-#define COR2_LOCAL 0x10 /* Local loopback mode */
+-#define COR2_REMOTE 0x08 /* Remote loopback mode */
+-#define COR2_HOST 0xc2 /* Safe host bits */
++#define RIOC_COR2_ETC 0x20 /* Embedded transmit options */
++#define RIOC_COR2_LOCAL 0x10 /* Local loopback mode */
++#define RIOC_COR2_REMOTE 0x08 /* Remote loopback mode */
++#define RIOC_COR2_HOST 0xc2 /* Safe host bits */
+
+ /* COR3 - RTA use only */
+-#define COR3_SCDRNG 0x80 /* Enable special char detect for range */
+-#define COR3_SCD34 0x40 /* Special character detect for SCHR's 3 + 4 */
+-#define COR3_FCT 0x20 /* Flow control transparency */
+-#define COR3_SCD12 0x10 /* Special character detect for SCHR's 1 + 2 */
+-#define COR3_FIFO12 0x0c /* 12 chars for receive FIFO threshold */
+-#define COR3_FIFO10 0x0a /* 10 chars for receive FIFO threshold */
+-#define COR3_FIFO8 0x08 /* 8 chars for receive FIFO threshold */
+-#define COR3_FIFO6 0x06 /* 6 chars for receive FIFO threshold */
+-
+-#define COR3_THRESHOLD COR3_FIFO8 /* MUST BE LESS THAN MCOR_THRESHOLD */
+-
+-#define COR3_DEFAULT (COR3_FCT | COR3_THRESHOLD)
++#define RIOC_COR3_SCDRNG 0x80 /* Enable special char detect for range */
++#define RIOC_COR3_SCD34 0x40 /* Special character detect for SCHR's 3 + 4 */
++#define RIOC_COR3_FCT 0x20 /* Flow control transparency */
++#define RIOC_COR3_SCD12 0x10 /* Special character detect for SCHR's 1 + 2 */
++#define RIOC_COR3_FIFO12 0x0c /* 12 chars for receive FIFO threshold */
++#define RIOC_COR3_FIFO10 0x0a /* 10 chars for receive FIFO threshold */
++#define RIOC_COR3_FIFO8 0x08 /* 8 chars for receive FIFO threshold */
++#define RIOC_COR3_FIFO6 0x06 /* 6 chars for receive FIFO threshold */
++
++#define RIOC_COR3_THRESHOLD RIOC_COR3_FIFO8 /* MUST BE LESS THAN MCOR_THRESHOLD */
++
++#define RIOC_COR3_DEFAULT (RIOC_COR3_FCT | RIOC_COR3_THRESHOLD)
+ /* Default bits for COR3 */
+
+ /* COR4 driver and RTA use */
+-#define COR4_IGNCR 0x80 /* Throw away CR's on input */
+-#define COR4_ICRNL 0x40 /* Map CR -> NL on input */
+-#define COR4_INLCR 0x20 /* Map NL -> CR on input */
+-#define COR4_IGNBRK 0x10 /* Ignore Break */
+-#define COR4_NBRKINT 0x08 /* No interrupt on break (-BRKINT) */
+-#define COR4_RAISEMOD 0x01 /* Raise modem output lines on non-zero baud */
++#define RIOC_COR4_IGNCR 0x80 /* Throw away CR's on input */
++#define RIOC_COR4_ICRNL 0x40 /* Map CR -> NL on input */
++#define RIOC_COR4_INLCR 0x20 /* Map NL -> CR on input */
++#define RIOC_COR4_IGNBRK 0x10 /* Ignore Break */
++#define RIOC_COR4_NBRKINT 0x08 /* No interrupt on break (-BRKINT) */
++#define RIOC_COR4_RAISEMOD 0x01 /* Raise modem output lines on non-zero baud */
+
+
+ /* COR4 driver only */
+-#define COR4_IGNPAR 0x04 /* IGNPAR (ignore characters with errors) */
+-#define COR4_PARMRK 0x02 /* PARMRK */
++#define RIOC_COR4_IGNPAR 0x04 /* IGNPAR (ignore characters with errors) */
++#define RIOC_COR4_PARMRK 0x02 /* PARMRK */
+
+-#define COR4_HOST 0xf8 /* Safe host bits */
++#define RIOC_COR4_HOST 0xf8 /* Safe host bits */
+
+ /* COR4 RTA only */
+-#define COR4_CIGNPAR 0x02 /* Thrown away bad characters */
+-#define COR4_CPARMRK 0x04 /* PARMRK characters */
+-#define COR4_CNPARMRK 0x03 /* Don't PARMRK */
++#define RIOC_COR4_CIGNPAR 0x02 /* Thrown away bad characters */
++#define RIOC_COR4_CPARMRK 0x04 /* PARMRK characters */
++#define RIOC_COR4_CNPARMRK 0x03 /* Don't PARMRK */
+
+ /* COR5 driver and RTA use */
+-#define COR5_ISTRIP 0x80 /* Strip input chars to 7 bits */
+-#define COR5_LNE 0x40 /* Enable LNEXT processing */
+-#define COR5_CMOE 0x20 /* Match good and errored characters */
+-#define COR5_ONLCR 0x02 /* NL -> CR NL on output */
+-#define COR5_OCRNL 0x01 /* CR -> NL on output */
++#define RIOC_COR5_ISTRIP 0x80 /* Strip input chars to 7 bits */
++#define RIOC_COR5_LNE 0x40 /* Enable LNEXT processing */
++#define RIOC_COR5_CMOE 0x20 /* Match good and errored characters */
++#define RIOC_COR5_ONLCR 0x02 /* NL -> CR NL on output */
++#define RIOC_COR5_OCRNL 0x01 /* CR -> NL on output */
+
+ /*
+ ** Spare bits - these are not used in the CIRRUS registers, so we use
+@@ -128,86 +128,86 @@
+ /*
+ ** tstop and tbusy indication
+ */
+-#define COR5_TSTATE_ON 0x08 /* Turn on monitoring of tbusy and tstop */
+-#define COR5_TSTATE_OFF 0x04 /* Turn off monitoring of tbusy and tstop */
++#define RIOC_COR5_TSTATE_ON 0x08 /* Turn on monitoring of tbusy and tstop */
++#define RIOC_COR5_TSTATE_OFF 0x04 /* Turn off monitoring of tbusy and tstop */
+ /*
+ ** TAB3
+ */
+-#define COR5_TAB3 0x10 /* TAB3 mode */
++#define RIOC_COR5_TAB3 0x10 /* TAB3 mode */
+
+-#define COR5_HOST 0xc3 /* Safe host bits */
++#define RIOC_COR5_HOST 0xc3 /* Safe host bits */
+
+ /* CCSR */
+-#define CCSR_TXFLOFF 0x04 /* Tx is xoffed */
++#define RIOC_CCSR_TXFLOFF 0x04 /* Tx is xoffed */
+
+ /* MSVR1 */
+ /* NB. DTR / CD swapped from Cirrus spec as the pins are also reversed on the
+ RTA. This is because otherwise DCD would get lost on the 1 parallel / 3
+ serial option.
+ */
+-#define MSVR1_CD 0x80 /* CD (DSR on Cirrus) */
+-#define MSVR1_RTS 0x40 /* RTS (CTS on Cirrus) */
+-#define MSVR1_RI 0x20 /* RI */
+-#define MSVR1_DTR 0x10 /* DTR (CD on Cirrus) */
+-#define MSVR1_CTS 0x01 /* CTS output pin (RTS on Cirrus) */
++#define RIOC_MSVR1_CD 0x80 /* CD (DSR on Cirrus) */
++#define RIOC_MSVR1_RTS 0x40 /* RTS (CTS on Cirrus) */
++#define RIOC_MSVR1_RI 0x20 /* RI */
++#define RIOC_MSVR1_DTR 0x10 /* DTR (CD on Cirrus) */
++#define RIOC_MSVR1_CTS 0x01 /* CTS output pin (RTS on Cirrus) */
+ /* Next two used to indicate state of tbusy and tstop to driver */
+-#define MSVR1_TSTOP 0x08 /* Set if port flow controlled */
+-#define MSVR1_TEMPTY 0x04 /* Set if port tx buffer empty */
++#define RIOC_MSVR1_TSTOP 0x08 /* Set if port flow controlled */
++#define RIOC_MSVR1_TEMPTY 0x04 /* Set if port tx buffer empty */
+
+-#define MSVR1_HOST 0xf3 /* The bits the host wants */
++#define RIOC_MSVR1_HOST 0xf3 /* The bits the host wants */
+
+ /* Defines for the subscripts of a CONFIG packet */
+-#define CONFIG_COR1 1 /* Option register 1 */
+-#define CONFIG_COR2 2 /* Option register 2 */
+-#define CONFIG_COR4 3 /* Option register 4 */
+-#define CONFIG_COR5 4 /* Option register 5 */
+-#define CONFIG_TXXON 5 /* Tx XON character */
+-#define CONFIG_TXXOFF 6 /* Tx XOFF character */
+-#define CONFIG_RXXON 7 /* Rx XON character */
+-#define CONFIG_RXXOFF 8 /* Rx XOFF character */
+-#define CONFIG_LNEXT 9 /* LNEXT character */
+-#define CONFIG_TXBAUD 10 /* Tx baud rate */
+-#define CONFIG_RXBAUD 11 /* Rx baud rate */
+-
+-#define PRE_EMPTIVE 0x80 /* Pre-emptive bit in command field */
++#define RIOC_CONFIG_COR1 1 /* Option register 1 */
++#define RIOC_CONFIG_COR2 2 /* Option register 2 */
++#define RIOC_CONFIG_COR4 3 /* Option register 4 */
++#define RIOC_CONFIG_COR5 4 /* Option register 5 */
++#define RIOC_CONFIG_TXXON 5 /* Tx XON character */
++#define RIOC_CONFIG_TXXOFF 6 /* Tx XOFF character */
++#define RIOC_CONFIG_RXXON 7 /* Rx XON character */
++#define RIOC_CONFIG_RXXOFF 8 /* Rx XOFF character */
++#define RIOC_CONFIG_LNEXT 9 /* LNEXT character */
++#define RIOC_CONFIG_TXBAUD 10 /* Tx baud rate */
++#define RIOC_CONFIG_RXBAUD 11 /* Rx baud rate */
++
++#define RIOC_PRE_EMPTIVE 0x80 /* Pre-emptive bit in command field */
+
+ /* Packet types going from Host to remote - with the exception of OPEN, MOPEN,
+ CONFIG, SBREAK and MEMDUMP the remaining bytes of the data array will not
+ be used
+ */
+-#define OPEN 0x00 /* Open a port */
+-#define CONFIG 0x01 /* Configure a port */
+-#define MOPEN 0x02 /* Modem open (block for DCD) */
+-#define CLOSE 0x03 /* Close a port */
+-#define WFLUSH (0x04 | PRE_EMPTIVE) /* Write flush */
+-#define RFLUSH (0x05 | PRE_EMPTIVE) /* Read flush */
+-#define RESUME (0x06 | PRE_EMPTIVE) /* Resume if xoffed */
+-#define SBREAK 0x07 /* Start break */
+-#define EBREAK 0x08 /* End break */
+-#define SUSPEND (0x09 | PRE_EMPTIVE) /* Susp op (behave as tho xoffed) */
+-#define FCLOSE (0x0a | PRE_EMPTIVE) /* Force close */
+-#define XPRINT 0x0b /* Xprint packet */
+-#define MBIS (0x0c | PRE_EMPTIVE) /* Set modem lines */
+-#define MBIC (0x0d | PRE_EMPTIVE) /* Clear modem lines */
+-#define MSET (0x0e | PRE_EMPTIVE) /* Set modem lines */
+-#define PCLOSE 0x0f /* Pseudo close - Leaves rx/tx enabled */
+-#define MGET (0x10 | PRE_EMPTIVE) /* Force update of modem status */
+-#define MEMDUMP (0x11 | PRE_EMPTIVE) /* Send back mem from addr supplied */
+-#define READ_REGISTER (0x12 | PRE_EMPTIVE) /* Read CD1400 register (debug) */
++#define RIOC_OPEN 0x00 /* Open a port */
++#define RIOC_CONFIG 0x01 /* Configure a port */
++#define RIOC_MOPEN 0x02 /* Modem open (block for DCD) */
++#define RIOC_CLOSE 0x03 /* Close a port */
++#define RIOC_WFLUSH (0x04 | RIOC_PRE_EMPTIVE) /* Write flush */
++#define RIOC_RFLUSH (0x05 | RIOC_PRE_EMPTIVE) /* Read flush */
++#define RIOC_RESUME (0x06 | RIOC_PRE_EMPTIVE) /* Resume if xoffed */
++#define RIOC_SBREAK 0x07 /* Start break */
++#define RIOC_EBREAK 0x08 /* End break */
++#define RIOC_SUSPEND (0x09 | RIOC_PRE_EMPTIVE) /* Susp op (behave as tho xoffed) */
++#define RIOC_FCLOSE (0x0a | RIOC_PRE_EMPTIVE) /* Force close */
++#define RIOC_XPRINT 0x0b /* Xprint packet */
++#define RIOC_MBIS (0x0c | RIOC_PRE_EMPTIVE) /* Set modem lines */
++#define RIOC_MBIC (0x0d | RIOC_PRE_EMPTIVE) /* Clear modem lines */
++#define RIOC_MSET (0x0e | RIOC_PRE_EMPTIVE) /* Set modem lines */
++#define RIOC_PCLOSE 0x0f /* Pseudo close - Leaves rx/tx enabled */
++#define RIOC_MGET (0x10 | RIOC_PRE_EMPTIVE) /* Force update of modem status */
++#define RIOC_MEMDUMP (0x11 | RIOC_PRE_EMPTIVE) /* Send back mem from addr supplied */
++#define RIOC_READ_REGISTER (0x12 | RIOC_PRE_EMPTIVE) /* Read CD1400 register (debug) */
+
+ /* "Command" packets going from remote to host COMPLETE and MODEM_STATUS
+ use data[4] / data[3] to indicate current state and modem status respectively
+ */
+
+-#define COMPLETE (0x20 | PRE_EMPTIVE)
++#define RIOC_COMPLETE (0x20 | RIOC_PRE_EMPTIVE)
+ /* Command complete */
+-#define BREAK_RECEIVED (0x21 | PRE_EMPTIVE)
++#define RIOC_BREAK_RECEIVED (0x21 | RIOC_PRE_EMPTIVE)
+ /* Break received */
+-#define MODEM_STATUS (0x22 | PRE_EMPTIVE)
++#define RIOC_MODEM_STATUS (0x22 | RIOC_PRE_EMPTIVE)
+ /* Change in modem status */
+
+ /* "Command" packet that could go either way - handshake wake-up */
+-#define HANDSHAKE (0x23 | PRE_EMPTIVE)
++#define RIOC_HANDSHAKE (0x23 | RIOC_PRE_EMPTIVE)
+ /* Wake-up to HOST / RTA */
+
+ #endif
+diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
+index 0ce9667..412777c 100644
+--- a/drivers/char/rio/rio_linux.c
++++ b/drivers/char/rio/rio_linux.c
+@@ -344,7 +344,7 @@ int rio_minor(struct tty_struct *tty)
+
+ static int rio_set_real_termios(void *ptr)
+ {
+- return RIOParam((struct Port *) ptr, CONFIG, 1, 1);
++ return RIOParam((struct Port *) ptr, RIOC_CONFIG, 1, 1);
+ }
+
+
+@@ -487,7 +487,7 @@ static int rio_get_CD(void *ptr)
+ int rv;
+
+ func_enter();
+- rv = (PortP->ModemState & MSVR1_CD) != 0;
++ rv = (PortP->ModemState & RIOC_MSVR1_CD) != 0;
+
+ rio_dprintk(RIO_DEBUG_INIT, "Getting CD status: %d\n", rv);
+
+@@ -607,7 +607,8 @@ static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd
+ rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
+ rc = -EIO;
+ } else {
+- if (RIOShortCommand(p, PortP, SBREAK, 2, 250) == RIO_FAIL) {
++ if (RIOShortCommand(p, PortP, RIOC_SBREAK, 2, 250) ==
++ RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
+ rc = -EIO;
+ }
+@@ -622,7 +623,8 @@ static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd
+ l = arg ? arg * 100 : 250;
+ if (l > 255)
+ l = 255;
+- if (RIOShortCommand(p, PortP, SBREAK, 2, arg ? arg * 100 : 250) == RIO_FAIL) {
++ if (RIOShortCommand(p, PortP, RIOC_SBREAK, 2,
++ arg ? arg * 100 : 250) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
+ rc = -EIO;
+ }
+diff --git a/drivers/char/rio/rio_linux.h b/drivers/char/rio/rio_linux.h
+index dc3f005..7f26cd7 100644
+--- a/drivers/char/rio/rio_linux.h
++++ b/drivers/char/rio/rio_linux.h
+@@ -186,9 +186,9 @@ static inline void *rio_memcpy_fromio(void *dest, void __iomem *source, int n)
+
+ #ifdef DEBUG
+ #define rio_dprintk(f, str...) do { if (rio_debug & f) printk (str);} while (0)
+-#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s\n", __FUNCTION__)
+-#define func_exit() rio_dprintk (RIO_DEBUG_FLOW, "rio: exit %s\n", __FUNCTION__)
+-#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s (port %d)\n",__FUNCTION__, port->line)
++#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s\n", __func__)
++#define func_exit() rio_dprintk (RIO_DEBUG_FLOW, "rio: exit %s\n", __func__)
++#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s (port %d)\n",__func__, port->line)
+ #else
+ #define rio_dprintk(f, str...) /* nothing */
+ #define func_enter()
+diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c
+index eca2b95..d956dd3 100644
+--- a/drivers/char/rio/rioboot.c
++++ b/drivers/char/rio/rioboot.c
+@@ -35,7 +35,6 @@
+ #include <linux/termios.h>
+ #include <linux/serial.h>
+ #include <linux/vmalloc.h>
+-#include <asm/semaphore.h>
+ #include <linux/generic_serial.h>
+ #include <linux/errno.h>
+ #include <linux/interrupt.h>
+diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
+index 7321d00..7b96e08 100644
+--- a/drivers/char/rio/riocmd.c
++++ b/drivers/char/rio/riocmd.c
+@@ -41,7 +41,6 @@ static char *_riocmd_c_sccs_ = "@(#)riocmd.c 1.2";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/termios.h>
+@@ -418,7 +417,7 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struc
+ PortP = p->RIOPortp[SysPort];
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ switch (readb(&PktCmdP->Command)) {
+- case BREAK_RECEIVED:
++ case RIOC_BREAK_RECEIVED:
+ rio_dprintk(RIO_DEBUG_CMD, "Received a break!\n");
+ /* If the current line disc. is not multi-threading and
+ the current processor is not the default, reset rup_intr
+@@ -429,16 +428,16 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struc
+ gs_got_break(&PortP->gs);
+ break;
+
+- case COMPLETE:
++ case RIOC_COMPLETE:
+ rio_dprintk(RIO_DEBUG_CMD, "Command complete on phb %d host %Zd\n", readb(&PktCmdP->PhbNum), HostP - p->RIOHosts);
+ subCommand = 1;
+ switch (readb(&PktCmdP->SubCommand)) {
+- case MEMDUMP:
++ case RIOC_MEMDUMP:
+ rio_dprintk(RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n", readb(&PktCmdP->SubCommand), readw(&PktCmdP->SubAddr));
+ break;
+- case READ_REGISTER:
++ case RIOC_READ_REGISTER:
+ rio_dprintk(RIO_DEBUG_CMD, "Read register (0x%x)\n", readw(&PktCmdP->SubAddr));
+- p->CdRegister = (readb(&PktCmdP->ModemStatus) & MSVR1_HOST);
++ p->CdRegister = (readb(&PktCmdP->ModemStatus) & RIOC_MSVR1_HOST);
+ break;
+ default:
+ subCommand = 0;
+@@ -457,14 +456,15 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struc
+ rio_dprintk(RIO_DEBUG_CMD, "No change\n");
+
+ /* FALLTHROUGH */
+- case MODEM_STATUS:
++ case RIOC_MODEM_STATUS:
+ /*
+ ** Knock out the tbusy and tstop bits, as these are not relevant
+ ** to the check for modem status change (they're just there because
+ ** it's a convenient place to put them!).
+ */
+ ReportedModemStatus = readb(&PktCmdP->ModemStatus);
+- if ((PortP->ModemState & MSVR1_HOST) == (ReportedModemStatus & MSVR1_HOST)) {
++ if ((PortP->ModemState & RIOC_MSVR1_HOST) ==
++ (ReportedModemStatus & RIOC_MSVR1_HOST)) {
+ rio_dprintk(RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState);
+ /*
+ ** Update ModemState just in case tbusy or tstop states have
+@@ -498,7 +498,7 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struc
+ /*
+ ** Is there a carrier?
+ */
+- if (PortP->ModemState & MSVR1_CD) {
++ if (PortP->ModemState & RIOC_MSVR1_CD) {
+ /*
+ ** Has carrier just appeared?
+ */
+@@ -692,7 +692,7 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
+ */
+ rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+ FreeMe = RIOCommandRup(p, Rup, HostP, PacketP);
+- if (readb(&PacketP->data[5]) == MEMDUMP) {
++ if (readb(&PacketP->data[5]) == RIOC_MEMDUMP) {
+ rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", readw(&(PacketP->data[6])));
+ rio_memcpy_fromio(p->RIOMemDump, &(PacketP->data[8]), 32);
+ }
+diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c
+index 7ce7761..d65ceb9 100644
+--- a/drivers/char/rio/rioctrl.c
++++ b/drivers/char/rio/rioctrl.c
+@@ -40,7 +40,6 @@ static char *_rioctrl_c_sccs_ = "@(#)rioctrl.c 1.3";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/termios.h>
+@@ -423,7 +422,8 @@ int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su
+ }
+
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+- if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RESUME) == RIO_FAIL) {
++ if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RIOC_RESUME) ==
++ RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME failed\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return -EBUSY;
+@@ -637,7 +637,8 @@ int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su
+ return -ENXIO;
+ }
+ PortP = (p->RIOPortp[PortTty.port]);
+- RIOParam(PortP, CONFIG, PortP->State & RIO_MODEM, OK_TO_SLEEP);
++ RIOParam(PortP, RIOC_CONFIG, PortP->State & RIO_MODEM,
++ OK_TO_SLEEP);
+ return retval;
+
+ case RIO_SET_PORT_PARAMS:
+@@ -1248,7 +1249,7 @@ int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su
+
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+- if (RIOPreemptiveCmd(p, PortP, MEMDUMP) == RIO_FAIL) {
++ if (RIOPreemptiveCmd(p, PortP, RIOC_MEMDUMP) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return -EBUSY;
+@@ -1314,7 +1315,8 @@ int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su
+
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+- if (RIOPreemptiveCmd(p, PortP, READ_REGISTER) == RIO_FAIL) {
++ if (RIOPreemptiveCmd(p, PortP, RIOC_READ_REGISTER) ==
++ RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return -EBUSY;
+@@ -1435,50 +1437,50 @@ int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd)
+ PktCmdP->PhbNum = port;
+
+ switch (Cmd) {
+- case MEMDUMP:
++ case RIOC_MEMDUMP:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk %p "
+ "(addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr);
+- PktCmdP->SubCommand = MEMDUMP;
++ PktCmdP->SubCommand = RIOC_MEMDUMP;
+ PktCmdP->SubAddr = SubCmd.Addr;
+ break;
+- case FCLOSE:
++ case RIOC_FCLOSE:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk %p\n",
+ CmdBlkP);
+ break;
+- case READ_REGISTER:
++ case RIOC_READ_REGISTER:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) "
+ "command blk %p\n", (int) SubCmd.Addr, CmdBlkP);
+- PktCmdP->SubCommand = READ_REGISTER;
++ PktCmdP->SubCommand = RIOC_READ_REGISTER;
+ PktCmdP->SubAddr = SubCmd.Addr;
+ break;
+- case RESUME:
++ case RIOC_RESUME:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk %p\n",
+ CmdBlkP);
+ break;
+- case RFLUSH:
++ case RIOC_RFLUSH:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk %p\n",
+ CmdBlkP);
+ CmdBlkP->PostFuncP = RIORFlushEnable;
+ break;
+- case SUSPEND:
++ case RIOC_SUSPEND:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk %p\n",
+ CmdBlkP);
+ break;
+
+- case MGET:
++ case RIOC_MGET:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk %p\n",
+ CmdBlkP);
+ break;
+
+- case MSET:
+- case MBIC:
+- case MBIS:
++ case RIOC_MSET:
++ case RIOC_MBIC:
++ case RIOC_MBIS:
+ CmdBlkP->Packet.data[4] = (char) PortP->ModemLines;
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command "
+ "blk %p\n", CmdBlkP);
+ break;
+
+- case WFLUSH:
++ case RIOC_WFLUSH:
+ /*
+ ** If we have queued up the maximum number of Write flushes
+ ** allowed then we should not bother sending any more to the
+diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c
+index 0794844..add1718 100644
+--- a/drivers/char/rio/rioinit.c
++++ b/drivers/char/rio/rioinit.c
+@@ -40,7 +40,6 @@ static char *_rioinit_c_sccs_ = "@(#)rioinit.c 1.3";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/termios.h>
+diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c
+index ebc7634..ea21686 100644
+--- a/drivers/char/rio/riointr.c
++++ b/drivers/char/rio/riointr.c
+@@ -42,7 +42,6 @@ static char *_riointr_c_sccs_ = "@(#)riointr.c 1.2";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/termios.h>
+@@ -402,9 +401,8 @@ void RIOServiceHost(struct rio_info *p, struct Host *HostP)
+ PortP->InUse = NOT_INUSE;
+
+ rio_spin_unlock(&PortP->portSem);
+- if (RIOParam(PortP, OPEN, ((PortP->Cor2Copy & (COR2_RTSFLOW | COR2_CTSFLOW)) == (COR2_RTSFLOW | COR2_CTSFLOW)) ? 1 : 0, DONT_SLEEP) == RIO_FAIL) {
++ if (RIOParam(PortP, RIOC_OPEN, ((PortP->Cor2Copy & (RIOC_COR2_RTSFLOW | RIOC_COR2_CTSFLOW)) == (RIOC_COR2_RTSFLOW | RIOC_COR2_CTSFLOW)) ? 1 : 0, DONT_SLEEP) == RIO_FAIL)
+ continue; /* with next port */
+- }
+ rio_spin_lock(&PortP->portSem);
+ PortP->MagicFlags &= ~MAGIC_REBOOT;
+ }
+@@ -430,7 +428,7 @@ void RIOServiceHost(struct rio_info *p, struct Host *HostP)
+ */
+ PktCmdP = (struct PktCmd __iomem *) &PacketP->data[0];
+
+- writeb(WFLUSH, &PktCmdP->Command);
++ writeb(RIOC_WFLUSH, &PktCmdP->Command);
+
+ p = PortP->HostPort % (u16) PORTS_PER_RTA;
+
+diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c
+index bb498d2..4810b84 100644
+--- a/drivers/char/rio/rioparam.c
++++ b/drivers/char/rio/rioparam.c
+@@ -41,7 +41,6 @@ static char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/termios.h>
+@@ -178,7 +177,7 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
+ }
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+- if (cmd == OPEN) {
++ if (cmd == RIOC_OPEN) {
+ /*
+ ** If the port is set to store or lock the parameters, and it is
+ ** paramed with OPEN, we want to restore the saved port termio, but
+@@ -242,50 +241,50 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
+ case CS5:
+ {
+ rio_dprintk(RIO_DEBUG_PARAM, "5 bit data\n");
+- Cor1 |= COR1_5BITS;
++ Cor1 |= RIOC_COR1_5BITS;
+ break;
+ }
+ case CS6:
+ {
+ rio_dprintk(RIO_DEBUG_PARAM, "6 bit data\n");
+- Cor1 |= COR1_6BITS;
++ Cor1 |= RIOC_COR1_6BITS;
+ break;
+ }
+ case CS7:
+ {
+ rio_dprintk(RIO_DEBUG_PARAM, "7 bit data\n");
+- Cor1 |= COR1_7BITS;
++ Cor1 |= RIOC_COR1_7BITS;
+ break;
+ }
+ case CS8:
+ {
+ rio_dprintk(RIO_DEBUG_PARAM, "8 bit data\n");
+- Cor1 |= COR1_8BITS;
++ Cor1 |= RIOC_COR1_8BITS;
+ break;
+ }
+ }
+
+ if (TtyP->termios->c_cflag & CSTOPB) {
+ rio_dprintk(RIO_DEBUG_PARAM, "2 stop bits\n");
+- Cor1 |= COR1_2STOP;
++ Cor1 |= RIOC_COR1_2STOP;
+ } else {
+ rio_dprintk(RIO_DEBUG_PARAM, "1 stop bit\n");
+- Cor1 |= COR1_1STOP;
++ Cor1 |= RIOC_COR1_1STOP;
+ }
+
+ if (TtyP->termios->c_cflag & PARENB) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable parity\n");
+- Cor1 |= COR1_NORMAL;
++ Cor1 |= RIOC_COR1_NORMAL;
+ } else {
+ rio_dprintk(RIO_DEBUG_PARAM, "Disable parity\n");
+- Cor1 |= COR1_NOP;
++ Cor1 |= RIOC_COR1_NOP;
+ }
+ if (TtyP->termios->c_cflag & PARODD) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Odd parity\n");
+- Cor1 |= COR1_ODD;
++ Cor1 |= RIOC_COR1_ODD;
+ } else {
+ rio_dprintk(RIO_DEBUG_PARAM, "Even parity\n");
+- Cor1 |= COR1_EVEN;
++ Cor1 |= RIOC_COR1_EVEN;
+ }
+
+ /*
+@@ -293,11 +292,11 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
+ */
+ if (TtyP->termios->c_iflag & IXON) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop output control\n");
+- Cor2 |= COR2_IXON;
++ Cor2 |= RIOC_COR2_IXON;
+ } else {
+ if (PortP->Config & RIO_IXON) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Force enable start/stop output control\n");
+- Cor2 |= COR2_IXON;
++ Cor2 |= RIOC_COR2_IXON;
+ } else
+ rio_dprintk(RIO_DEBUG_PARAM, "IXON has been disabled.\n");
+ }
+@@ -305,29 +304,29 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
+ if (TtyP->termios->c_iflag & IXANY) {
+ if (PortP->Config & RIO_IXANY) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable any key to restart output\n");
+- Cor2 |= COR2_IXANY;
++ Cor2 |= RIOC_COR2_IXANY;
+ } else
+ rio_dprintk(RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n");
+ }
+
+ if (TtyP->termios->c_iflag & IXOFF) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop input control 2\n");
+- Cor2 |= COR2_IXOFF;
++ Cor2 |= RIOC_COR2_IXOFF;
+ }
+
+ if (TtyP->termios->c_cflag & HUPCL) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Hangup on last close\n");
+- Cor2 |= COR2_HUPCL;
++ Cor2 |= RIOC_COR2_HUPCL;
+ }
+
+ if (C_CRTSCTS(TtyP)) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n");
+- Cor2 |= COR2_CTSFLOW;
+- Cor2 |= COR2_RTSFLOW;
++ Cor2 |= RIOC_COR2_CTSFLOW;
++ Cor2 |= RIOC_COR2_RTSFLOW;
+ } else {
+ rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control disabled\n");
+- Cor2 &= ~COR2_CTSFLOW;
+- Cor2 &= ~COR2_RTSFLOW;
++ Cor2 &= ~RIOC_COR2_CTSFLOW;
++ Cor2 &= ~RIOC_COR2_RTSFLOW;
+ }
+
+
+@@ -342,36 +341,36 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
+ */
+ if (TtyP->termios->c_iflag & IGNBRK) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Ignore break condition\n");
+- Cor4 |= COR4_IGNBRK;
++ Cor4 |= RIOC_COR4_IGNBRK;
+ }
+ if (!(TtyP->termios->c_iflag & BRKINT)) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Break generates NULL condition\n");
+- Cor4 |= COR4_NBRKINT;
++ Cor4 |= RIOC_COR4_NBRKINT;
+ } else {
+ rio_dprintk(RIO_DEBUG_PARAM, "Interrupt on break condition\n");
+ }
+
+ if (TtyP->termios->c_iflag & INLCR) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage return on input\n");
+- Cor4 |= COR4_INLCR;
++ Cor4 |= RIOC_COR4_INLCR;
+ }
+
+ if (TtyP->termios->c_iflag & IGNCR) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Ignore carriage return on input\n");
+- Cor4 |= COR4_IGNCR;
++ Cor4 |= RIOC_COR4_IGNCR;
+ }
+
+ if (TtyP->termios->c_iflag & ICRNL) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on input\n");
+- Cor4 |= COR4_ICRNL;
++ Cor4 |= RIOC_COR4_ICRNL;
+ }
+ if (TtyP->termios->c_iflag & IGNPAR) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Ignore characters with parity errors\n");
+- Cor4 |= COR4_IGNPAR;
++ Cor4 |= RIOC_COR4_IGNPAR;
+ }
+ if (TtyP->termios->c_iflag & PARMRK) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Mark parity errors\n");
+- Cor4 |= COR4_PARMRK;
++ Cor4 |= RIOC_COR4_PARMRK;
+ }
+
+ /*
+@@ -379,22 +378,22 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
+ ** on reception of a config packet.
+ ** The download code handles the zero baud condition.
+ */
+- Cor4 |= COR4_RAISEMOD;
++ Cor4 |= RIOC_COR4_RAISEMOD;
+
+ /*
+ ** COR 5
+ */
+
+- Cor5 = COR5_CMOE;
++ Cor5 = RIOC_COR5_CMOE;
+
+ /*
+ ** Set to monitor tbusy/tstop (or not).
+ */
+
+ if (PortP->MonitorTstate)
+- Cor5 |= COR5_TSTATE_ON;
++ Cor5 |= RIOC_COR5_TSTATE_ON;
+ else
+- Cor5 |= COR5_TSTATE_OFF;
++ Cor5 |= RIOC_COR5_TSTATE_OFF;
+
+ /*
+ ** Could set LNE here if you wanted LNext processing. SVR4 will use it.
+@@ -402,24 +401,24 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
+ if (TtyP->termios->c_iflag & ISTRIP) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Strip input characters\n");
+ if (!(PortP->State & RIO_TRIAD_MODE)) {
+- Cor5 |= COR5_ISTRIP;
++ Cor5 |= RIOC_COR5_ISTRIP;
+ }
+ }
+
+ if (TtyP->termios->c_oflag & ONLCR) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage-return, newline on output\n");
+ if (PortP->CookMode == COOK_MEDIUM)
+- Cor5 |= COR5_ONLCR;
++ Cor5 |= RIOC_COR5_ONLCR;
+ }
+ if (TtyP->termios->c_oflag & OCRNL) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on output\n");
+ if (PortP->CookMode == COOK_MEDIUM)
+- Cor5 |= COR5_OCRNL;
++ Cor5 |= RIOC_COR5_OCRNL;
+ }
+ if ((TtyP->termios->c_oflag & TABDLY) == TAB3) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Tab delay 3 set\n");
+ if (PortP->CookMode == COOK_MEDIUM)
+- Cor5 |= COR5_TAB3;
++ Cor5 |= RIOC_COR5_TAB3;
+ }
+
+ /*
+diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c
+index a99f3d9..7a9df7d 100644
+--- a/drivers/char/rio/rioroute.c
++++ b/drivers/char/rio/rioroute.c
+@@ -39,7 +39,6 @@ static char *_rioroute_c_sccs_ = "@(#)rioroute.c 1.3";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/termios.h>
+@@ -527,7 +526,7 @@ void RIOFixPhbs(struct rio_info *p, struct Host *HostP, unsigned int unit)
+ ** If RTA is not powered on, the tx packets will be
+ ** unset, so go no further.
+ */
+- if (PortP->TxStart == 0) {
++ if (!PortP->TxStart) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ break;
+diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c
+index 9b52892..2b24488 100644
+--- a/drivers/char/rio/riotable.c
++++ b/drivers/char/rio/riotable.c
+@@ -42,7 +42,6 @@ static char *_riotable_c_sccs_ = "@(#)riotable.c 1.2";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/termios.h>
+diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
+index cfa5436..c993548 100644
+--- a/drivers/char/rio/riotty.c
++++ b/drivers/char/rio/riotty.c
+@@ -44,7 +44,6 @@ static char *_riotty_c_sccs_ = "@(#)riotty.c 1.3";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/termios.h>
+@@ -212,7 +211,7 @@ int riotopen(struct tty_struct *tty, struct file *filp)
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for RIO_CLOSING to go away\n");
+ if (repeat_this-- <= 0) {
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
+- RIOPreemptiveCmd(p, PortP, FCLOSE);
++ RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
+ retval = -EINTR;
+ goto bombout;
+ }
+@@ -265,7 +264,7 @@ int riotopen(struct tty_struct *tty, struct file *filp)
+ here. If I read the docs correctly the "open"
+ command piggybacks the parameters immediately.
+ -- REW */
+- RIOParam(PortP, OPEN, 1, OK_TO_SLEEP); /* Open the port */
++ RIOParam(PortP, RIOC_OPEN, 1, OK_TO_SLEEP); /* Open the port */
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+ /*
+@@ -276,7 +275,7 @@ int riotopen(struct tty_struct *tty, struct file *filp)
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n");
+- RIOPreemptiveCmd(p, PortP, FCLOSE);
++ RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
+ func_exit();
+ return -EINTR;
+ }
+@@ -298,7 +297,8 @@ int riotopen(struct tty_struct *tty, struct file *filp)
+ ** insert test for carrier here. -- ???
+ ** I already see that test here. What's the deal? -- REW
+ */
+- if ((PortP->gs.tty->termios->c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD)) {
++ if ((PortP->gs.tty->termios->c_cflag & CLOCAL) ||
++ (PortP->ModemState & RIOC_MSVR1_CD)) {
+ rio_dprintk(RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort);
+ /*
+ tp->tm.c_state |= CARR_ON;
+@@ -326,7 +326,7 @@ int riotopen(struct tty_struct *tty, struct file *filp)
+ ** I think it's OK. -- REW
+ */
+ rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n", SysPort);
+- RIOPreemptiveCmd(p, PortP, FCLOSE);
++ RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
+ /*
+ tp->tm.c_state &= ~WOPEN;
+ */
+@@ -417,7 +417,7 @@ int riotclose(void *ptr)
+ */
+ PortP->State &= ~RIO_MOPEN;
+ PortP->State &= ~RIO_CARR_ON;
+- PortP->ModemState &= ~MSVR1_CD;
++ PortP->ModemState &= ~RIOC_MSVR1_CD;
+ /*
+ ** If the device was open as both a Modem and a tty line
+ ** then we need to wimp out here, as the port has not really
+@@ -454,7 +454,7 @@ int riotclose(void *ptr)
+ if (repeat_this-- <= 0) {
+ rv = -EINTR;
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
+- RIOPreemptiveCmd(p, PortP, FCLOSE);
++ RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
+ goto close_end;
+ }
+ rio_dprintk(RIO_DEBUG_TTY, "Calling timeout to flush in closing\n");
+@@ -493,8 +493,8 @@ int riotclose(void *ptr)
+ /* Can't call RIOShortCommand with the port locked. */
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+
+- if (RIOShortCommand(p, PortP, CLOSE, 1, 0) == RIO_FAIL) {
+- RIOPreemptiveCmd(p, PortP, FCLOSE);
++ if (RIOShortCommand(p, PortP, RIOC_CLOSE, 1, 0) == RIO_FAIL) {
++ RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ goto close_end;
+ }
+@@ -504,7 +504,7 @@ int riotclose(void *ptr)
+ try--;
+ if (time_after(jiffies, end_time)) {
+ rio_dprintk(RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n");
+- RIOPreemptiveCmd(p, PortP, FCLOSE);
++ RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
+ break;
+ }
+ rio_dprintk(RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n", PortP->PortState & PORT_ISOPEN);
+@@ -516,14 +516,14 @@ int riotclose(void *ptr)
+ }
+ if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n");
+- RIOPreemptiveCmd(p, PortP, FCLOSE);
++ RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
+ break;
+ }
+ }
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ rio_dprintk(RIO_DEBUG_TTY, "Close: try was %d on completion\n", try);
+
+- /* RIOPreemptiveCmd(p, PortP, FCLOSE); */
++ /* RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); */
+
+ /*
+ ** 15.10.1998 ARG - ESIL 0761 part fix
+diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
+index 3f9d0a9..f073c71 100644
+--- a/drivers/char/riscom8.c
++++ b/drivers/char/riscom8.c
+@@ -4,9 +4,9 @@
+ * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg at ibi.com)
+ *
+ * This code is loosely based on the Linux serial driver, written by
+- * Linus Torvalds, Theodore T'so and others. The RISCom/8 card
+- * programming info was obtained from various drivers for other OSes
+- * (FreeBSD, ISC, etc), but no source code from those drivers were
++ * Linus Torvalds, Theodore T'so and others. The RISCom/8 card
++ * programming info was obtained from various drivers for other OSes
++ * (FreeBSD, ISC, etc), but no source code from those drivers were
+ * directly included in this driver.
+ *
+ *
+@@ -33,7 +33,7 @@
+
+ #include <linux/module.h>
+
+-#include <asm/io.h>
++#include <linux/io.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+ #include <linux/ioport.h>
+@@ -49,7 +49,7 @@
+ #include <linux/tty_flip.h>
+ #include <linux/spinlock.h>
+
+-#include <asm/uaccess.h>
++#include <linux/uaccess.h>
+
+ #include "riscom8.h"
+ #include "riscom8_reg.h"
+@@ -57,15 +57,15 @@
+ /* Am I paranoid or not ? ;-) */
+ #define RISCOM_PARANOIA_CHECK
+
+-/*
+- * Crazy InteliCom/8 boards sometimes has swapped CTS & DSR signals.
++/*
++ * Crazy InteliCom/8 boards sometimes have swapped CTS & DSR signals.
+ * You can slightly speed up things by #undefing the following option,
+- * if you are REALLY sure that your board is correct one.
++ * if you are REALLY sure that your board is correct one.
+ */
+
+ #define RISCOM_BRAIN_DAMAGED_CTS
+
+-/*
++/*
+ * The following defines are mostly for testing purposes. But if you need
+ * some nice reporting in your syslog, you can define them also.
+ */
+@@ -112,7 +112,7 @@ static unsigned short rc_ioport[] = {
+ #define RC_NIOPORT ARRAY_SIZE(rc_ioport)
+
+
+-static inline int rc_paranoia_check(struct riscom_port const * port,
++static int rc_paranoia_check(struct riscom_port const *port,
+ char *name, const char *routine)
+ {
+ #ifdef RISCOM_PARANOIA_CHECK
+@@ -134,52 +134,53 @@ static inline int rc_paranoia_check(struct riscom_port const * port,
+ }
+
+ /*
+- *
++ *
+ * Service functions for RISCom/8 driver.
+- *
++ *
+ */
+
+ /* Get board number from pointer */
+-static inline int board_No (struct riscom_board const * bp)
++static inline int board_No(struct riscom_board const *bp)
+ {
+ return bp - rc_board;
+ }
+
+ /* Get port number from pointer */
+-static inline int port_No (struct riscom_port const * port)
++static inline int port_No(struct riscom_port const *port)
+ {
+- return RC_PORT(port - rc_port);
++ return RC_PORT(port - rc_port);
+ }
+
+ /* Get pointer to board from pointer to port */
+-static inline struct riscom_board * port_Board(struct riscom_port const * port)
++static inline struct riscom_board *port_Board(struct riscom_port const *port)
+ {
+ return &rc_board[RC_BOARD(port - rc_port)];
+ }
+
+ /* Input Byte from CL CD180 register */
+-static inline unsigned char rc_in(struct riscom_board const * bp, unsigned short reg)
++static inline unsigned char rc_in(struct riscom_board const *bp,
++ unsigned short reg)
+ {
+ return inb(bp->base + RC_TO_ISA(reg));
+ }
+
+ /* Output Byte to CL CD180 register */
+-static inline void rc_out(struct riscom_board const * bp, unsigned short reg,
++static inline void rc_out(struct riscom_board const *bp, unsigned short reg,
+ unsigned char val)
+ {
+ outb(val, bp->base + RC_TO_ISA(reg));
+ }
+
+ /* Wait for Channel Command Register ready */
+-static inline void rc_wait_CCR(struct riscom_board const * bp)
++static void rc_wait_CCR(struct riscom_board const *bp)
+ {
+ unsigned long delay;
+
+ /* FIXME: need something more descriptive then 100000 :) */
+- for (delay = 100000; delay; delay--)
++ for (delay = 100000; delay; delay--)
+ if (!rc_in(bp, CD180_CCR))
+ return;
+-
++
+ printk(KERN_INFO "rc%d: Timeout waiting for CCR.\n", board_No(bp));
+ }
+
+@@ -187,11 +188,11 @@ static inline void rc_wait_CCR(struct riscom_board const * bp)
+ * RISCom/8 probe functions.
+ */
+
+-static inline int rc_request_io_range(struct riscom_board * const bp)
++static int rc_request_io_range(struct riscom_board * const bp)
+ {
+ int i;
+-
+- for (i = 0; i < RC_NIOPORT; i++)
++
++ for (i = 0; i < RC_NIOPORT; i++)
+ if (!request_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1,
+ "RISCom/8")) {
+ goto out_release;
+@@ -200,42 +201,42 @@ static inline int rc_request_io_range(struct riscom_board * const bp)
+ out_release:
+ printk(KERN_INFO "rc%d: Skipping probe at 0x%03x. IO address in use.\n",
+ board_No(bp), bp->base);
+- while(--i >= 0)
++ while (--i >= 0)
+ release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
+ return 1;
+ }
+
+-static inline void rc_release_io_range(struct riscom_board * const bp)
++static void rc_release_io_range(struct riscom_board * const bp)
+ {
+ int i;
+-
+- for (i = 0; i < RC_NIOPORT; i++)
++
++ for (i = 0; i < RC_NIOPORT; i++)
+ release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
+ }
+-
++
+ /* Reset and setup CD180 chip */
+-static void __init rc_init_CD180(struct riscom_board const * bp)
++static void __init rc_init_CD180(struct riscom_board const *bp)
+ {
+ unsigned long flags;
+-
++
+ spin_lock_irqsave(&riscom_lock, flags);
+
+- rc_out(bp, RC_CTOUT, 0); /* Clear timeout */
+- rc_wait_CCR(bp); /* Wait for CCR ready */
+- rc_out(bp, CD180_CCR, CCR_HARDRESET); /* Reset CD180 chip */
++ rc_out(bp, RC_CTOUT, 0); /* Clear timeout */
++ rc_wait_CCR(bp); /* Wait for CCR ready */
++ rc_out(bp, CD180_CCR, CCR_HARDRESET); /* Reset CD180 chip */
+ spin_unlock_irqrestore(&riscom_lock, flags);
+- msleep(50); /* Delay 0.05 sec */
++ msleep(50); /* Delay 0.05 sec */
+ spin_lock_irqsave(&riscom_lock, flags);
+- rc_out(bp, CD180_GIVR, RC_ID); /* Set ID for this chip */
+- rc_out(bp, CD180_GICR, 0); /* Clear all bits */
+- rc_out(bp, CD180_PILR1, RC_ACK_MINT); /* Prio for modem intr */
+- rc_out(bp, CD180_PILR2, RC_ACK_TINT); /* Prio for transmitter intr */
+- rc_out(bp, CD180_PILR3, RC_ACK_RINT); /* Prio for receiver intr */
+-
++ rc_out(bp, CD180_GIVR, RC_ID); /* Set ID for this chip */
++ rc_out(bp, CD180_GICR, 0); /* Clear all bits */
++ rc_out(bp, CD180_PILR1, RC_ACK_MINT); /* Prio for modem intr */
++ rc_out(bp, CD180_PILR2, RC_ACK_TINT); /* Prio for tx intr */
++ rc_out(bp, CD180_PILR3, RC_ACK_RINT); /* Prio for rx intr */
++
+ /* Setting up prescaler. We need 4 ticks per 1 ms */
+ rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8);
+ rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff);
+-
++
+ spin_unlock_irqrestore(&riscom_lock, flags);
+ }
+
+@@ -245,12 +246,12 @@ static int __init rc_probe(struct riscom_board *bp)
+ unsigned char val1, val2;
+ int irqs = 0;
+ int retries;
+-
++
+ bp->irq = 0;
+
+ if (rc_request_io_range(bp))
+ return 1;
+-
++
+ /* Are the I/O ports here ? */
+ rc_out(bp, CD180_PPRL, 0x5a);
+ outb(0xff, 0x80);
+@@ -258,34 +259,34 @@ static int __init rc_probe(struct riscom_board *bp)
+ rc_out(bp, CD180_PPRL, 0xa5);
+ outb(0x00, 0x80);
+ val2 = rc_in(bp, CD180_PPRL);
+-
++
+ if ((val1 != 0x5a) || (val2 != 0xa5)) {
+ printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not found.\n",
+ board_No(bp), bp->base);
+ goto out_release;
+ }
+-
++
+ /* It's time to find IRQ for this board */
+- for (retries = 0; retries < 5 && irqs <= 0; retries++) {
++ for (retries = 0; retries < 5 && irqs <= 0; retries++) {
+ irqs = probe_irq_on();
+- rc_init_CD180(bp); /* Reset CD180 chip */
+- rc_out(bp, CD180_CAR, 2); /* Select port 2 */
++ rc_init_CD180(bp); /* Reset CD180 chip */
++ rc_out(bp, CD180_CAR, 2); /* Select port 2 */
+ rc_wait_CCR(bp);
+- rc_out(bp, CD180_CCR, CCR_TXEN); /* Enable transmitter */
+- rc_out(bp, CD180_IER, IER_TXRDY); /* Enable tx empty intr */
++ rc_out(bp, CD180_CCR, CCR_TXEN); /* Enable transmitter */
++ rc_out(bp, CD180_IER, IER_TXRDY);/* Enable tx empty intr */
+ msleep(50);
+ irqs = probe_irq_off(irqs);
+- val1 = rc_in(bp, RC_BSR); /* Get Board Status reg */
+- val2 = rc_in(bp, RC_ACK_TINT); /* ACK interrupt */
+- rc_init_CD180(bp); /* Reset CD180 again */
+-
++ val1 = rc_in(bp, RC_BSR); /* Get Board Status reg */
++ val2 = rc_in(bp, RC_ACK_TINT); /* ACK interrupt */
++ rc_init_CD180(bp); /* Reset CD180 again */
++
+ if ((val1 & RC_BSR_TINT) || (val2 != (RC_ID | GIVR_IT_TX))) {
+ printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not "
+ "found.\n", board_No(bp), bp->base);
+ goto out_release;
+ }
+ }
+-
++
+ if (irqs <= 0) {
+ printk(KERN_ERR "rc%d: Can't find IRQ for RISCom/8 board "
+ "at 0x%03x.\n", board_No(bp), bp->base);
+@@ -293,113 +294,112 @@ static int __init rc_probe(struct riscom_board *bp)
+ }
+ bp->irq = irqs;
+ bp->flags |= RC_BOARD_PRESENT;
+-
++
+ printk(KERN_INFO "rc%d: RISCom/8 Rev. %c board detected at "
+ "0x%03x, IRQ %d.\n",
+ board_No(bp),
+ (rc_in(bp, CD180_GFRCR) & 0x0f) + 'A', /* Board revision */
+ bp->base, bp->irq);
+-
++
+ return 0;
+ out_release:
+ rc_release_io_range(bp);
+ return 1;
+ }
+
+-/*
+- *
++/*
++ *
+ * Interrupt processing routines.
+- *
++ *
+ */
+
+-static inline struct riscom_port * rc_get_port(struct riscom_board const * bp,
+- unsigned char const * what)
++static struct riscom_port *rc_get_port(struct riscom_board const *bp,
++ unsigned char const *what)
+ {
+ unsigned char channel;
+- struct riscom_port * port;
+-
++ struct riscom_port *port;
++
+ channel = rc_in(bp, CD180_GICR) >> GICR_CHAN_OFF;
+ if (channel < CD180_NCH) {
+ port = &rc_port[board_No(bp) * RC_NPORT + channel];
+- if (port->flags & ASYNC_INITIALIZED) {
++ if (port->flags & ASYNC_INITIALIZED)
+ return port;
+- }
+ }
+- printk(KERN_ERR "rc%d: %s interrupt from invalid port %d\n",
++ printk(KERN_ERR "rc%d: %s interrupt from invalid port %d\n",
+ board_No(bp), what, channel);
+ return NULL;
+ }
+
+-static inline void rc_receive_exc(struct riscom_board const * bp)
++static void rc_receive_exc(struct riscom_board const *bp)
+ {
+ struct riscom_port *port;
+ struct tty_struct *tty;
+ unsigned char status;
+ unsigned char ch, flag;
+-
+- if (!(port = rc_get_port(bp, "Receive")))
++
++ port = rc_get_port(bp, "Receive");
++ if (port == NULL)
+ return;
+
+ tty = port->tty;
+-
+-#ifdef RC_REPORT_OVERRUN
++
++#ifdef RC_REPORT_OVERRUN
+ status = rc_in(bp, CD180_RCSR);
+ if (status & RCSR_OE)
+ port->overrun++;
+ status &= port->mark_mask;
+-#else
++#else
+ status = rc_in(bp, CD180_RCSR) & port->mark_mask;
+-#endif
++#endif
+ ch = rc_in(bp, CD180_RDR);
+- if (!status) {
++ if (!status)
+ return;
+- }
+ if (status & RCSR_TOUT) {
+ printk(KERN_WARNING "rc%d: port %d: Receiver timeout. "
+- "Hardware problems ?\n",
++ "Hardware problems ?\n",
+ board_No(bp), port_No(port));
+ return;
+-
++
+ } else if (status & RCSR_BREAK) {
+ printk(KERN_INFO "rc%d: port %d: Handling break...\n",
+ board_No(bp), port_No(port));
+ flag = TTY_BREAK;
+ if (port->flags & ASYNC_SAK)
+ do_SAK(tty);
+-
+- } else if (status & RCSR_PE)
++
++ } else if (status & RCSR_PE)
+ flag = TTY_PARITY;
+-
+- else if (status & RCSR_FE)
++
++ else if (status & RCSR_FE)
+ flag = TTY_FRAME;
+-
+- else if (status & RCSR_OE)
++
++ else if (status & RCSR_OE)
+ flag = TTY_OVERRUN;
+-
+ else
+ flag = TTY_NORMAL;
+-
++
+ tty_insert_flip_char(tty, ch, flag);
+ tty_flip_buffer_push(tty);
+ }
+
+-static inline void rc_receive(struct riscom_board const * bp)
++static void rc_receive(struct riscom_board const *bp)
+ {
+ struct riscom_port *port;
+ struct tty_struct *tty;
+ unsigned char count;
+-
+- if (!(port = rc_get_port(bp, "Receive")))
++
++ port = rc_get_port(bp, "Receive");
++ if (port == NULL)
+ return;
+-
++
+ tty = port->tty;
+-
++
+ count = rc_in(bp, CD180_RDCR);
+-
++
+ #ifdef RC_REPORT_FIFO
+ port->hits[count > 8 ? 9 : count]++;
+-#endif
+-
++#endif
++
+ while (count--) {
+ if (tty_buffer_request_room(tty, 1) == 0) {
+ printk(KERN_WARNING "rc%d: port %d: Working around "
+@@ -412,26 +412,26 @@ static inline void rc_receive(struct riscom_board const * bp)
+ tty_flip_buffer_push(tty);
+ }
+
+-static inline void rc_transmit(struct riscom_board const * bp)
++static void rc_transmit(struct riscom_board const *bp)
+ {
+ struct riscom_port *port;
+ struct tty_struct *tty;
+ unsigned char count;
+-
+-
+- if (!(port = rc_get_port(bp, "Transmit")))
++
++ port = rc_get_port(bp, "Transmit");
++ if (port == NULL)
+ return;
+-
++
+ tty = port->tty;
+-
+- if (port->IER & IER_TXEMPTY) {
++
++ if (port->IER & IER_TXEMPTY) {
+ /* FIFO drained */
+ rc_out(bp, CD180_CAR, port_No(port));
+ port->IER &= ~IER_TXEMPTY;
+ rc_out(bp, CD180_IER, port->IER);
+ return;
+ }
+-
++
+ if ((port->xmit_cnt <= 0 && !port->break_length)
+ || tty->stopped || tty->hw_stopped) {
+ rc_out(bp, CD180_CAR, port_No(port));
+@@ -439,7 +439,7 @@ static inline void rc_transmit(struct riscom_board const * bp)
+ rc_out(bp, CD180_IER, port->IER);
+ return;
+ }
+-
++
+ if (port->break_length) {
+ if (port->break_length > 0) {
+ if (port->COR2 & COR2_ETC) {
+@@ -451,7 +451,8 @@ static inline void rc_transmit(struct riscom_board const * bp)
+ rc_out(bp, CD180_TDR, CD180_C_ESC);
+ rc_out(bp, CD180_TDR, CD180_C_DELAY);
+ rc_out(bp, CD180_TDR, count);
+- if (!(port->break_length -= count))
++ port->break_length -= count;
++ if (port->break_length == 0)
+ port->break_length--;
+ } else {
+ rc_out(bp, CD180_TDR, CD180_C_ESC);
+@@ -463,7 +464,7 @@ static inline void rc_transmit(struct riscom_board const * bp)
+ }
+ return;
+ }
+-
++
+ count = CD180_NFIFO;
+ do {
+ rc_out(bp, CD180_TDR, port->xmit_buf[port->xmit_tail++]);
+@@ -471,7 +472,7 @@ static inline void rc_transmit(struct riscom_board const * bp)
+ if (--port->xmit_cnt <= 0)
+ break;
+ } while (--count > 0);
+-
++
+ if (port->xmit_cnt <= 0) {
+ rc_out(bp, CD180_CAR, port_No(port));
+ port->IER &= ~IER_TXRDY;
+@@ -481,25 +482,26 @@ static inline void rc_transmit(struct riscom_board const * bp)
+ tty_wakeup(tty);
+ }
+
+-static inline void rc_check_modem(struct riscom_board const * bp)
++static void rc_check_modem(struct riscom_board const *bp)
+ {
+ struct riscom_port *port;
+ struct tty_struct *tty;
+ unsigned char mcr;
+-
+- if (!(port = rc_get_port(bp, "Modem")))
++
++ port = rc_get_port(bp, "Modem");
++ if (port == NULL)
+ return;
+-
++
+ tty = port->tty;
+-
++
+ mcr = rc_in(bp, CD180_MCR);
+- if (mcr & MCR_CDCHG) {
+- if (rc_in(bp, CD180_MSVR) & MSVR_CD)
++ if (mcr & MCR_CDCHG) {
++ if (rc_in(bp, CD180_MSVR) & MSVR_CD)
+ wake_up_interruptible(&port->open_wait);
+ else
+ tty_hangup(tty);
+ }
+-
++
+ #ifdef RISCOM_BRAIN_DAMAGED_CTS
+ if (mcr & MCR_CTSCHG) {
+ if (rc_in(bp, CD180_MSVR) & MSVR_CTS) {
+@@ -526,13 +528,13 @@ static inline void rc_check_modem(struct riscom_board const * bp)
+ rc_out(bp, CD180_IER, port->IER);
+ }
+ #endif /* RISCOM_BRAIN_DAMAGED_CTS */
+-
++
+ /* Clear change bits */
+ rc_out(bp, CD180_MCR, 0);
+ }
+
+ /* The main interrupt processing routine */
+-static irqreturn_t rc_interrupt(int dummy, void * dev_id)
++static irqreturn_t rc_interrupt(int dummy, void *dev_id)
+ {
+ unsigned char status;
+ unsigned char ack;
+@@ -547,13 +549,11 @@ static irqreturn_t rc_interrupt(int dummy, void * dev_id)
+ (RC_BSR_TOUT | RC_BSR_TINT |
+ RC_BSR_MINT | RC_BSR_RINT))) {
+ handled = 1;
+- if (status & RC_BSR_TOUT)
++ if (status & RC_BSR_TOUT)
+ printk(KERN_WARNING "rc%d: Got timeout. Hardware "
+ "error?\n", board_No(bp));
+-
+ else if (status & RC_BSR_RINT) {
+ ack = rc_in(bp, RC_ACK_RINT);
+-
+ if (ack == (RC_ID | GIVR_IT_RCV))
+ rc_receive(bp);
+ else if (ack == (RC_ID | GIVR_IT_REXC))
+@@ -562,29 +562,23 @@ static irqreturn_t rc_interrupt(int dummy, void * dev_id)
+ printk(KERN_WARNING "rc%d: Bad receive ack "
+ "0x%02x.\n",
+ board_No(bp), ack);
+-
+ } else if (status & RC_BSR_TINT) {
+ ack = rc_in(bp, RC_ACK_TINT);
+-
+ if (ack == (RC_ID | GIVR_IT_TX))
+ rc_transmit(bp);
+ else
+ printk(KERN_WARNING "rc%d: Bad transmit ack "
+ "0x%02x.\n",
+ board_No(bp), ack);
+-
+ } else /* if (status & RC_BSR_MINT) */ {
+ ack = rc_in(bp, RC_ACK_MINT);
+-
+- if (ack == (RC_ID | GIVR_IT_MODEM))
++ if (ack == (RC_ID | GIVR_IT_MODEM))
+ rc_check_modem(bp);
+ else
+ printk(KERN_WARNING "rc%d: Bad modem ack "
+ "0x%02x.\n",
+ board_No(bp), ack);
+-
+- }
+-
++ }
+ rc_out(bp, CD180_EOIR, 0); /* Mark end of interrupt */
+ rc_out(bp, RC_CTOUT, 0); /* Clear timeout flag */
+ }
+@@ -596,24 +590,24 @@ static irqreturn_t rc_interrupt(int dummy, void * dev_id)
+ */
+
+ /* Called with disabled interrupts */
+-static int rc_setup_board(struct riscom_board * bp)
++static int rc_setup_board(struct riscom_board *bp)
+ {
+ int error;
+
+- if (bp->flags & RC_BOARD_ACTIVE)
++ if (bp->flags & RC_BOARD_ACTIVE)
+ return 0;
+-
++
+ error = request_irq(bp->irq, rc_interrupt, IRQF_DISABLED,
+ "RISCom/8", bp);
+- if (error)
++ if (error)
+ return error;
+-
++
+ rc_out(bp, RC_CTOUT, 0); /* Just in case */
+ bp->DTR = ~0;
+ rc_out(bp, RC_DTR, bp->DTR); /* Drop DTR on all ports */
+-
++
+ bp->flags |= RC_BOARD_ACTIVE;
+-
++
+ return 0;
+ }
+
+@@ -622,40 +616,40 @@ static void rc_shutdown_board(struct riscom_board *bp)
+ {
+ if (!(bp->flags & RC_BOARD_ACTIVE))
+ return;
+-
++
+ bp->flags &= ~RC_BOARD_ACTIVE;
+-
++
+ free_irq(bp->irq, NULL);
+-
++
+ bp->DTR = ~0;
+ rc_out(bp, RC_DTR, bp->DTR); /* Drop DTR on all ports */
+-
++
+ }
+
+ /*
+- * Setting up port characteristics.
++ * Setting up port characteristics.
+ * Must be called with disabled interrupts
+ */
+ static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
+ {
+- struct tty_struct *tty;
++ struct tty_struct *tty = port->tty;
+ unsigned long baud;
+ long tmp;
+ unsigned char cor1 = 0, cor3 = 0;
+ unsigned char mcor1 = 0, mcor2 = 0;
+-
+- if (!(tty = port->tty) || !tty->termios)
++
++ if (tty == NULL || tty->termios == NULL)
+ return;
+
+ port->IER = 0;
+ port->COR2 = 0;
+ port->MSVR = MSVR_RTS;
+-
++
+ baud = tty_get_baud_rate(tty);
+-
++
+ /* Select port on the board */
+ rc_out(bp, CD180_CAR, port_No(port));
+-
++
+ if (!baud) {
+ /* Drop DTR & exit */
+ bp->DTR |= (1u << port_No(port));
+@@ -666,69 +660,68 @@ static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
+ bp->DTR &= ~(1u << port_No(port));
+ rc_out(bp, RC_DTR, bp->DTR);
+ }
+-
++
+ /*
+- * Now we must calculate some speed depended things
++ * Now we must calculate some speed depended things
+ */
+-
++
+ /* Set baud rate for port */
+ tmp = (((RC_OSCFREQ + baud/2) / baud +
+ CD180_TPC/2) / CD180_TPC);
+
+- rc_out(bp, CD180_RBPRH, (tmp >> 8) & 0xff);
+- rc_out(bp, CD180_TBPRH, (tmp >> 8) & 0xff);
+- rc_out(bp, CD180_RBPRL, tmp & 0xff);
++ rc_out(bp, CD180_RBPRH, (tmp >> 8) & 0xff);
++ rc_out(bp, CD180_TBPRH, (tmp >> 8) & 0xff);
++ rc_out(bp, CD180_RBPRL, tmp & 0xff);
+ rc_out(bp, CD180_TBPRL, tmp & 0xff);
+-
++
+ baud = (baud + 5) / 10; /* Estimated CPS */
+-
++
+ /* Two timer ticks seems enough to wakeup something like SLIP driver */
+- tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO;
++ tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO;
+ port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
+ SERIAL_XMIT_SIZE - 1 : tmp);
+-
++
+ /* Receiver timeout will be transmission time for 1.5 chars */
+ tmp = (RISCOM_TPS + RISCOM_TPS/2 + baud/2) / baud;
+ tmp = (tmp > 0xff) ? 0xff : tmp;
+ rc_out(bp, CD180_RTPR, tmp);
+-
+- switch (C_CSIZE(tty)) {
+- case CS5:
++
++ switch (C_CSIZE(tty)) {
++ case CS5:
+ cor1 |= COR1_5BITS;
+ break;
+- case CS6:
++ case CS6:
+ cor1 |= COR1_6BITS;
+ break;
+- case CS7:
++ case CS7:
+ cor1 |= COR1_7BITS;
+ break;
+- case CS8:
++ case CS8:
+ cor1 |= COR1_8BITS;
+ break;
+ }
+-
+- if (C_CSTOPB(tty))
++ if (C_CSTOPB(tty))
+ cor1 |= COR1_2SB;
+-
++
+ cor1 |= COR1_IGNORE;
+- if (C_PARENB(tty)) {
++ if (C_PARENB(tty)) {
+ cor1 |= COR1_NORMPAR;
+- if (C_PARODD(tty))
++ if (C_PARODD(tty))
+ cor1 |= COR1_ODDP;
+- if (I_INPCK(tty))
++ if (I_INPCK(tty))
+ cor1 &= ~COR1_IGNORE;
+ }
+ /* Set marking of some errors */
+ port->mark_mask = RCSR_OE | RCSR_TOUT;
+- if (I_INPCK(tty))
++ if (I_INPCK(tty))
+ port->mark_mask |= RCSR_FE | RCSR_PE;
+- if (I_BRKINT(tty) || I_PARMRK(tty))
++ if (I_BRKINT(tty) || I_PARMRK(tty))
+ port->mark_mask |= RCSR_BREAK;
+- if (I_IGNPAR(tty))
++ if (I_IGNPAR(tty))
+ port->mark_mask &= ~(RCSR_FE | RCSR_PE);
+- if (I_IGNBRK(tty)) {
++ if (I_IGNBRK(tty)) {
+ port->mark_mask &= ~RCSR_BREAK;
+- if (I_IGNPAR(tty))
++ if (I_IGNPAR(tty))
+ /* Real raw mode. Ignore all */
+ port->mark_mask &= ~RCSR_OE;
+ }
+@@ -738,7 +731,8 @@ static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
+ port->IER |= IER_DSR | IER_CTS;
+ mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
+ mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
+- tty->hw_stopped = !(rc_in(bp, CD180_MSVR) & (MSVR_CTS|MSVR_DSR));
++ tty->hw_stopped = !(rc_in(bp, CD180_MSVR) &
++ (MSVR_CTS|MSVR_DSR));
+ #else
+ port->COR2 |= COR2_CTSAE;
+ #endif
+@@ -761,13 +755,13 @@ static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
+ mcor1 |= MCOR1_CDZD;
+ mcor2 |= MCOR2_CDOD;
+ }
+-
+- if (C_CREAD(tty))
++
++ if (C_CREAD(tty))
+ /* Enable receiver */
+ port->IER |= IER_RXD;
+-
++
+ /* Set input FIFO size (1-8 bytes) */
+- cor3 |= RISCOM_RXFIFO;
++ cor3 |= RISCOM_RXFIFO;
+ /* Setting up CD180 channel registers */
+ rc_out(bp, CD180_COR1, cor1);
+ rc_out(bp, CD180_COR2, port->COR2);
+@@ -791,36 +785,30 @@ static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
+ static int rc_setup_port(struct riscom_board *bp, struct riscom_port *port)
+ {
+ unsigned long flags;
+-
++
+ if (port->flags & ASYNC_INITIALIZED)
+ return 0;
+-
++
+ if (!port->xmit_buf) {
+ /* We may sleep in get_zeroed_page() */
+- unsigned long tmp;
+-
+- if (!(tmp = get_zeroed_page(GFP_KERNEL)))
++ unsigned long tmp = get_zeroed_page(GFP_KERNEL);
++ if (tmp == 0)
+ return -ENOMEM;
+-
+- if (port->xmit_buf) {
++ if (port->xmit_buf)
+ free_page(tmp);
+- return -ERESTARTSYS;
+- }
+- port->xmit_buf = (unsigned char *) tmp;
++ else
++ port->xmit_buf = (unsigned char *) tmp;
+ }
+-
+ spin_lock_irqsave(&riscom_lock, flags);
+
+- if (port->tty)
++ if (port->tty)
+ clear_bit(TTY_IO_ERROR, &port->tty->flags);
+-
+- if (port->count == 1)
++ if (port->count == 1)
+ bp->count++;
+-
+ port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+ rc_change_speed(bp, port);
+ port->flags |= ASYNC_INITIALIZED;
+-
++
+ spin_unlock_irqrestore(&riscom_lock, flags);
+ return 0;
+ }
+@@ -829,38 +817,39 @@ static int rc_setup_port(struct riscom_board *bp, struct riscom_port *port)
+ static void rc_shutdown_port(struct riscom_board *bp, struct riscom_port *port)
+ {
+ struct tty_struct *tty;
+-
+- if (!(port->flags & ASYNC_INITIALIZED))
++
++ if (!(port->flags & ASYNC_INITIALIZED))
+ return;
+-
++
+ #ifdef RC_REPORT_OVERRUN
+ printk(KERN_INFO "rc%d: port %d: Total %ld overruns were detected.\n",
+ board_No(bp), port_No(port), port->overrun);
+-#endif
++#endif
+ #ifdef RC_REPORT_FIFO
+ {
+ int i;
+-
++
+ printk(KERN_INFO "rc%d: port %d: FIFO hits [ ",
+ board_No(bp), port_No(port));
+- for (i = 0; i < 10; i++) {
++ for (i = 0; i < 10; i++)
+ printk("%ld ", port->hits[i]);
+- }
+ printk("].\n");
+ }
+-#endif
++#endif
+ if (port->xmit_buf) {
+ free_page((unsigned long) port->xmit_buf);
+ port->xmit_buf = NULL;
+ }
+
+- if (!(tty = port->tty) || C_HUPCL(tty)) {
++ tty = port->tty;
++
++ if (tty == NULL || C_HUPCL(tty)) {
+ /* Drop DTR */
+ bp->DTR |= (1u << port_No(port));
+ rc_out(bp, RC_DTR, bp->DTR);
+ }
+-
+- /* Select port */
++
++ /* Select port */
+ rc_out(bp, CD180_CAR, port_No(port));
+ /* Reset port */
+ rc_wait_CCR(bp);
+@@ -868,28 +857,26 @@ static void rc_shutdown_port(struct riscom_board *bp, struct riscom_port *port)
+ /* Disable all interrupts from this port */
+ port->IER = 0;
+ rc_out(bp, CD180_IER, port->IER);
+-
+- if (tty)
++
++ if (tty)
+ set_bit(TTY_IO_ERROR, &tty->flags);
+ port->flags &= ~ASYNC_INITIALIZED;
+-
++
+ if (--bp->count < 0) {
+ printk(KERN_INFO "rc%d: rc_shutdown_port: "
+ "bad board count: %d\n",
+ board_No(bp), bp->count);
+ bp->count = 0;
+ }
+-
+ /*
+ * If this is the last opened port on the board
+ * shutdown whole board
+ */
+- if (!bp->count)
++ if (!bp->count)
+ rc_shutdown_board(bp);
+ }
+
+-
+-static int block_til_ready(struct tty_struct *tty, struct file * filp,
++static int block_til_ready(struct tty_struct *tty, struct file *filp,
+ struct riscom_port *port)
+ {
+ DECLARE_WAITQUEUE(wait, current);
+@@ -921,7 +908,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
+ return 0;
+ }
+
+- if (C_CLOCAL(tty))
++ if (C_CLOCAL(tty))
+ do_clocal = 1;
+
+ /*
+@@ -959,7 +946,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
+ if (port->flags & ASYNC_HUP_NOTIFY)
+ retval = -EAGAIN;
+ else
+- retval = -ERESTARTSYS;
++ retval = -ERESTARTSYS;
+ break;
+ }
+ if (!(port->flags & ASYNC_CLOSING) &&
+@@ -978,50 +965,63 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
+ port->blocked_open--;
+ if (retval)
+ return retval;
+-
++
+ port->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+-}
++}
+
+-static int rc_open(struct tty_struct * tty, struct file * filp)
++static int rc_open(struct tty_struct *tty, struct file *filp)
+ {
+ int board;
+ int error;
+- struct riscom_port * port;
+- struct riscom_board * bp;
+-
++ struct riscom_port *port;
++ struct riscom_board *bp;
++
+ board = RC_BOARD(tty->index);
+ if (board >= RC_NBOARD || !(rc_board[board].flags & RC_BOARD_PRESENT))
+ return -ENODEV;
+-
++
+ bp = &rc_board[board];
+ port = rc_port + board * RC_NPORT + RC_PORT(tty->index);
+ if (rc_paranoia_check(port, tty->name, "rc_open"))
+ return -ENODEV;
+-
+- if ((error = rc_setup_board(bp)))
++
++ error = rc_setup_board(bp);
++ if (error)
+ return error;
+-
++
+ port->count++;
+ tty->driver_data = port;
+ port->tty = tty;
+-
+- if ((error = rc_setup_port(bp, port)))
+- return error;
+-
+- if ((error = block_til_ready(tty, filp, port)))
+- return error;
+-
+- return 0;
++
++ error = rc_setup_port(bp, port);
++ if (error == 0)
++ error = block_til_ready(tty, filp, port);
++ return error;
+ }
+
+-static void rc_close(struct tty_struct * tty, struct file * filp)
++static void rc_flush_buffer(struct tty_struct *tty)
++{
++ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
++ unsigned long flags;
++
++ if (rc_paranoia_check(port, tty->name, "rc_flush_buffer"))
++ return;
++
++ spin_lock_irqsave(&riscom_lock, flags);
++ port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
++ spin_unlock_irqrestore(&riscom_lock, flags);
++
++ tty_wakeup(tty);
++}
++
++static void rc_close(struct tty_struct *tty, struct file *filp)
+ {
+ struct riscom_port *port = (struct riscom_port *) tty->driver_data;
+ struct riscom_board *bp;
+ unsigned long flags;
+ unsigned long timeout;
+-
++
+ if (!port || rc_paranoia_check(port, tty->name, "close"))
+ return;
+
+@@ -1029,7 +1029,7 @@ static void rc_close(struct tty_struct * tty, struct file * filp)
+
+ if (tty_hung_up_p(filp))
+ goto out;
+-
++
+ bp = port_Board(port);
+ if ((tty->count == 1) && (port->count != 1)) {
+ printk(KERN_INFO "rc%d: rc_close: bad port count;"
+@@ -1047,7 +1047,7 @@ static void rc_close(struct tty_struct * tty, struct file * filp)
+ goto out;
+ port->flags |= ASYNC_CLOSING;
+ /*
+- * Now we wait for the transmit buffer to clear; and we notify
++ * Now we wait for the transmit buffer to clear; and we notify
+ * the line discipline to only process XON/XOFF characters.
+ */
+ tty->closing = 1;
+@@ -1070,24 +1070,22 @@ static void rc_close(struct tty_struct * tty, struct file * filp)
+ * has completely drained; this is especially
+ * important if there is a transmit FIFO!
+ */
+- timeout = jiffies+HZ;
+- while(port->IER & IER_TXEMPTY) {
++ timeout = jiffies + HZ;
++ while (port->IER & IER_TXEMPTY) {
+ msleep_interruptible(jiffies_to_msecs(port->timeout));
+ if (time_after(jiffies, timeout))
+ break;
+ }
+ }
+ rc_shutdown_port(bp, port);
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ rc_flush_buffer(tty);
+ tty_ldisc_flush(tty);
+
+ tty->closing = 0;
+ port->tty = NULL;
+ if (port->blocked_open) {
+- if (port->close_delay) {
++ if (port->close_delay)
+ msleep_interruptible(jiffies_to_msecs(port->close_delay));
+- }
+ wake_up_interruptible(&port->open_wait);
+ }
+ port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
+@@ -1097,17 +1095,17 @@ out:
+ spin_unlock_irqrestore(&riscom_lock, flags);
+ }
+
+-static int rc_write(struct tty_struct * tty,
++static int rc_write(struct tty_struct *tty,
+ const unsigned char *buf, int count)
+ {
+ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_board *bp;
+ int c, total = 0;
+ unsigned long flags;
+-
++
+ if (rc_paranoia_check(port, tty->name, "rc_write"))
+ return 0;
+-
++
+ bp = port_Board(port);
+
+ if (!tty || !port->xmit_buf)
+@@ -1144,38 +1142,41 @@ static int rc_write(struct tty_struct * tty,
+ return total;
+ }
+
+-static void rc_put_char(struct tty_struct * tty, unsigned char ch)
++static int rc_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ unsigned long flags;
++ int ret = 0;
+
+ if (rc_paranoia_check(port, tty->name, "rc_put_char"))
+- return;
++ return 0;
+
+ if (!tty || !port->xmit_buf)
+- return;
++ return 0;
+
+ spin_lock_irqsave(&riscom_lock, flags);
+-
++
+ if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
+ goto out;
+
+ port->xmit_buf[port->xmit_head++] = ch;
+ port->xmit_head &= SERIAL_XMIT_SIZE - 1;
+ port->xmit_cnt++;
++ ret = 1;
+
+ out:
+ spin_unlock_irqrestore(&riscom_lock, flags);
++ return ret;
+ }
+
+-static void rc_flush_chars(struct tty_struct * tty)
++static void rc_flush_chars(struct tty_struct *tty)
+ {
+ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ unsigned long flags;
+-
++
+ if (rc_paranoia_check(port, tty->name, "rc_flush_chars"))
+ return;
+-
++
+ if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+ !port->xmit_buf)
+ return;
+@@ -1189,11 +1190,11 @@ static void rc_flush_chars(struct tty_struct * tty)
+ spin_unlock_irqrestore(&riscom_lock, flags);
+ }
+
+-static int rc_write_room(struct tty_struct * tty)
++static int rc_write_room(struct tty_struct *tty)
+ {
+ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ int ret;
+-
++
+ if (rc_paranoia_check(port, tty->name, "rc_write_room"))
+ return 0;
+
+@@ -1206,39 +1207,22 @@ static int rc_write_room(struct tty_struct * tty)
+ static int rc_chars_in_buffer(struct tty_struct *tty)
+ {
+ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+-
++
+ if (rc_paranoia_check(port, tty->name, "rc_chars_in_buffer"))
+ return 0;
+-
+- return port->xmit_cnt;
+-}
+-
+-static void rc_flush_buffer(struct tty_struct *tty)
+-{
+- struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+- unsigned long flags;
+-
+- if (rc_paranoia_check(port, tty->name, "rc_flush_buffer"))
+- return;
+-
+- spin_lock_irqsave(&riscom_lock, flags);
+-
+- port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+
+- spin_unlock_irqrestore(&riscom_lock, flags);
+-
+- tty_wakeup(tty);
++ return port->xmit_cnt;
+ }
+
+ static int rc_tiocmget(struct tty_struct *tty, struct file *file)
+ {
+ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+- struct riscom_board * bp;
++ struct riscom_board *bp;
+ unsigned char status;
+ unsigned int result;
+ unsigned long flags;
+
+- if (rc_paranoia_check(port, tty->name, __FUNCTION__))
++ if (rc_paranoia_check(port, tty->name, __func__))
+ return -ENODEV;
+
+ bp = port_Board(port);
+@@ -1266,7 +1250,7 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned long flags;
+ struct riscom_board *bp;
+
+- if (rc_paranoia_check(port, tty->name, __FUNCTION__))
++ if (rc_paranoia_check(port, tty->name, __func__))
+ return -ENODEV;
+
+ bp = port_Board(port);
+@@ -1292,11 +1276,11 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file,
+ return 0;
+ }
+
+-static inline void rc_send_break(struct riscom_port * port, unsigned long length)
++static void rc_send_break(struct riscom_port *port, unsigned long length)
+ {
+ struct riscom_board *bp = port_Board(port);
+ unsigned long flags;
+-
++
+ spin_lock_irqsave(&riscom_lock, flags);
+
+ port->break_length = RISCOM_TPS / HZ * length;
+@@ -1312,17 +1296,17 @@ static inline void rc_send_break(struct riscom_port * port, unsigned long length
+ spin_unlock_irqrestore(&riscom_lock, flags);
+ }
+
+-static inline int rc_set_serial_info(struct riscom_port * port,
+- struct serial_struct __user * newinfo)
++static int rc_set_serial_info(struct riscom_port *port,
++ struct serial_struct __user *newinfo)
+ {
+ struct serial_struct tmp;
+ struct riscom_board *bp = port_Board(port);
+ int change_speed;
+-
++
+ if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
+ return -EFAULT;
+-
+-#if 0
++
++#if 0
+ if ((tmp.irq != bp->irq) ||
+ (tmp.port != bp->base) ||
+ (tmp.type != PORT_CIRRUS) ||
+@@ -1331,16 +1315,16 @@ static inline int rc_set_serial_info(struct riscom_port * port,
+ (tmp.xmit_fifo_size != CD180_NFIFO) ||
+ (tmp.flags & ~RISCOM_LEGAL_FLAGS))
+ return -EINVAL;
+-#endif
+-
++#endif
++
+ change_speed = ((port->flags & ASYNC_SPD_MASK) !=
+ (tmp.flags & ASYNC_SPD_MASK));
+-
++
+ if (!capable(CAP_SYS_ADMIN)) {
+ if ((tmp.close_delay != port->close_delay) ||
+ (tmp.closing_wait != port->closing_wait) ||
+ ((tmp.flags & ~ASYNC_USR_MASK) !=
+- (port->flags & ~ASYNC_USR_MASK)))
++ (port->flags & ~ASYNC_USR_MASK)))
+ return -EPERM;
+ port->flags = ((port->flags & ~ASYNC_USR_MASK) |
+ (tmp.flags & ASYNC_USR_MASK));
+@@ -1360,12 +1344,12 @@ static inline int rc_set_serial_info(struct riscom_port * port,
+ return 0;
+ }
+
+-static inline int rc_get_serial_info(struct riscom_port * port,
++static int rc_get_serial_info(struct riscom_port *port,
+ struct serial_struct __user *retinfo)
+ {
+ struct serial_struct tmp;
+ struct riscom_board *bp = port_Board(port);
+-
++
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.type = PORT_CIRRUS;
+ tmp.line = port - rc_port;
+@@ -1379,19 +1363,18 @@ static inline int rc_get_serial_info(struct riscom_port * port,
+ return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0;
+ }
+
+-static int rc_ioctl(struct tty_struct * tty, struct file * filp,
++static int rc_ioctl(struct tty_struct *tty, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+-
+ {
+ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ void __user *argp = (void __user *)arg;
+- int retval;
+-
++ int retval = 0;
++
+ if (rc_paranoia_check(port, tty->name, "rc_ioctl"))
+ return -ENODEV;
+-
++
+ switch (cmd) {
+- case TCSBRK: /* SVID version: non-zero arg --> no break */
++ case TCSBRK: /* SVID version: non-zero arg --> no break */
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+@@ -1399,45 +1382,40 @@ static int rc_ioctl(struct tty_struct * tty, struct file * filp,
+ if (!arg)
+ rc_send_break(port, HZ/4); /* 1/4 second */
+ break;
+- case TCSBRKP: /* support for POSIX tcsendbreak() */
++ case TCSBRKP: /* support for POSIX tcsendbreak() */
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ rc_send_break(port, arg ? arg*(HZ/10) : HZ/4);
+ break;
+- case TIOCGSOFTCAR:
+- return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned __user *)argp);
+- case TIOCSSOFTCAR:
+- if (get_user(arg,(unsigned __user *) argp))
+- return -EFAULT;
+- tty->termios->c_cflag =
+- ((tty->termios->c_cflag & ~CLOCAL) |
+- (arg ? CLOCAL : 0));
++ case TIOCGSERIAL:
++ lock_kernel();
++ retval = rc_get_serial_info(port, argp);
++ unlock_kernel();
+ break;
+- case TIOCGSERIAL:
+- return rc_get_serial_info(port, argp);
+- case TIOCSSERIAL:
+- return rc_set_serial_info(port, argp);
+- default:
+- return -ENOIOCTLCMD;
++ case TIOCSSERIAL:
++ lock_kernel();
++ retval = rc_set_serial_info(port, argp);
++ unlock_kernel();
++ break;
++ default:
++ retval = -ENOIOCTLCMD;
+ }
+- return 0;
++ return retval;
+ }
+
+-static void rc_throttle(struct tty_struct * tty)
++static void rc_throttle(struct tty_struct *tty)
+ {
+ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_board *bp;
+ unsigned long flags;
+-
++
+ if (rc_paranoia_check(port, tty->name, "rc_throttle"))
+ return;
+-
+ bp = port_Board(port);
+
+ spin_lock_irqsave(&riscom_lock, flags);
+-
+ port->MSVR &= ~MSVR_RTS;
+ rc_out(bp, CD180_CAR, port_No(port));
+ if (I_IXOFF(tty)) {
+@@ -1446,23 +1424,20 @@ static void rc_throttle(struct tty_struct * tty)
+ rc_wait_CCR(bp);
+ }
+ rc_out(bp, CD180_MSVR, port->MSVR);
+-
+ spin_unlock_irqrestore(&riscom_lock, flags);
+ }
+
+-static void rc_unthrottle(struct tty_struct * tty)
++static void rc_unthrottle(struct tty_struct *tty)
+ {
+ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_board *bp;
+ unsigned long flags;
+-
++
+ if (rc_paranoia_check(port, tty->name, "rc_unthrottle"))
+ return;
+-
+ bp = port_Board(port);
+-
+- spin_lock_irqsave(&riscom_lock, flags);
+
++ spin_lock_irqsave(&riscom_lock, flags);
+ port->MSVR |= MSVR_RTS;
+ rc_out(bp, CD180_CAR, port_No(port));
+ if (I_IXOFF(tty)) {
+@@ -1471,62 +1446,58 @@ static void rc_unthrottle(struct tty_struct * tty)
+ rc_wait_CCR(bp);
+ }
+ rc_out(bp, CD180_MSVR, port->MSVR);
+-
+ spin_unlock_irqrestore(&riscom_lock, flags);
+ }
+
+-static void rc_stop(struct tty_struct * tty)
++static void rc_stop(struct tty_struct *tty)
+ {
+ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_board *bp;
+ unsigned long flags;
+-
++
+ if (rc_paranoia_check(port, tty->name, "rc_stop"))
+ return;
+-
++
+ bp = port_Board(port);
+-
+- spin_lock_irqsave(&riscom_lock, flags);
+
++ spin_lock_irqsave(&riscom_lock, flags);
+ port->IER &= ~IER_TXRDY;
+ rc_out(bp, CD180_CAR, port_No(port));
+ rc_out(bp, CD180_IER, port->IER);
+-
+ spin_unlock_irqrestore(&riscom_lock, flags);
+ }
+
+-static void rc_start(struct tty_struct * tty)
++static void rc_start(struct tty_struct *tty)
+ {
+ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_board *bp;
+ unsigned long flags;
+-
++
+ if (rc_paranoia_check(port, tty->name, "rc_start"))
+ return;
+-
++
+ bp = port_Board(port);
+-
++
+ spin_lock_irqsave(&riscom_lock, flags);
+
+- if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
++ if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
+ port->IER |= IER_TXRDY;
+ rc_out(bp, CD180_CAR, port_No(port));
+ rc_out(bp, CD180_IER, port->IER);
+ }
+-
+ spin_unlock_irqrestore(&riscom_lock, flags);
+ }
+
+-static void rc_hangup(struct tty_struct * tty)
++static void rc_hangup(struct tty_struct *tty)
+ {
+ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_board *bp;
+-
++
+ if (rc_paranoia_check(port, tty->name, "rc_hangup"))
+ return;
+-
++
+ bp = port_Board(port);
+-
++
+ rc_shutdown_port(bp, port);
+ port->count = 0;
+ port->flags &= ~ASYNC_NORMAL_ACTIVE;
+@@ -1534,17 +1505,14 @@ static void rc_hangup(struct tty_struct * tty)
+ wake_up_interruptible(&port->open_wait);
+ }
+
+-static void rc_set_termios(struct tty_struct * tty, struct ktermios * old_termios)
++static void rc_set_termios(struct tty_struct *tty,
++ struct ktermios *old_termios)
+ {
+ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ unsigned long flags;
+-
++
+ if (rc_paranoia_check(port, tty->name, "rc_set_termios"))
+ return;
+-
+- if (tty->termios->c_cflag == old_termios->c_cflag &&
+- tty->termios->c_iflag == old_termios->c_iflag)
+- return;
+
+ spin_lock_irqsave(&riscom_lock, flags);
+ rc_change_speed(port_Board(port), port);
+@@ -1583,9 +1551,9 @@ static int __init rc_init_drivers(void)
+ int i;
+
+ riscom_driver = alloc_tty_driver(RC_NBOARD * RC_NPORT);
+- if (!riscom_driver)
++ if (!riscom_driver)
+ return -ENOMEM;
+-
++
+ riscom_driver->owner = THIS_MODULE;
+ riscom_driver->name = "ttyL";
+ riscom_driver->major = RISCOM8_NORMAL_MAJOR;
+@@ -1598,23 +1566,21 @@ static int __init rc_init_drivers(void)
+ riscom_driver->init_termios.c_ospeed = 9600;
+ riscom_driver->flags = TTY_DRIVER_REAL_RAW;
+ tty_set_operations(riscom_driver, &riscom_ops);
+- if ((error = tty_register_driver(riscom_driver))) {
++ error = tty_register_driver(riscom_driver);
++ if (error != 0) {
+ put_tty_driver(riscom_driver);
+ printk(KERN_ERR "rc: Couldn't register RISCom/8 driver, "
+- "error = %d\n",
+- error);
++ "error = %d\n", error);
+ return 1;
+ }
+-
+ memset(rc_port, 0, sizeof(rc_port));
+ for (i = 0; i < RC_NPORT * RC_NBOARD; i++) {
+ rc_port[i].magic = RISCOM8_MAGIC;
+- rc_port[i].close_delay = 50 * HZ/100;
+- rc_port[i].closing_wait = 3000 * HZ/100;
++ rc_port[i].close_delay = 50 * HZ / 100;
++ rc_port[i].closing_wait = 3000 * HZ / 100;
+ init_waitqueue_head(&rc_port[i].open_wait);
+ init_waitqueue_head(&rc_port[i].close_wait);
+ }
+-
+ return 0;
+ }
+
+@@ -1627,13 +1593,13 @@ static void rc_release_drivers(void)
+ #ifndef MODULE
+ /*
+ * Called at boot time.
+- *
++ *
+ * You can specify IO base for up to RC_NBOARD cards,
+ * using line "riscom8=0xiobase1,0xiobase2,.." at LILO prompt.
+ * Note that there will be no probing at default
+ * addresses in this case.
+ *
+- */
++ */
+ static int __init riscom8_setup(char *str)
+ {
+ int ints[RC_NBOARD];
+@@ -1644,7 +1610,7 @@ static int __init riscom8_setup(char *str)
+ for (i = 0; i < RC_NBOARD; i++) {
+ if (i < ints[0])
+ rc_board[i].base = ints[i+1];
+- else
++ else
+ rc_board[i].base = 0;
+ }
+ return 1;
+@@ -1659,8 +1625,8 @@ static char banner[] __initdata =
+ static char no_boards_msg[] __initdata =
+ KERN_INFO "rc: No RISCom/8 boards detected.\n";
+
+-/*
+- * This routine must be called by kernel at boot time
++/*
++ * This routine must be called by kernel at boot time
+ */
+ static int __init riscom8_init(void)
+ {
+@@ -1669,13 +1635,12 @@ static int __init riscom8_init(void)
+
+ printk(banner);
+
+- if (rc_init_drivers())
++ if (rc_init_drivers())
+ return -EIO;
+
+- for (i = 0; i < RC_NBOARD; i++)
+- if (rc_board[i].base && !rc_probe(&rc_board[i]))
++ for (i = 0; i < RC_NBOARD; i++)
++ if (rc_board[i].base && !rc_probe(&rc_board[i]))
+ found++;
+-
+ if (!found) {
+ rc_release_drivers();
+ printk(no_boards_msg);
+@@ -1702,13 +1667,13 @@ MODULE_LICENSE("GPL");
+ * by specifying "iobase=0xXXX iobase1=0xXXX ..." as insmod parameter.
+ *
+ */
+-static int __init riscom8_init_module (void)
++static int __init riscom8_init_module(void)
+ {
+ #ifdef MODULE
+ int i;
+
+ if (iobase || iobase1 || iobase2 || iobase3) {
+- for(i = 0; i < RC_NBOARD; i++)
++ for (i = 0; i < RC_NBOARD; i++)
+ rc_board[i].base = 0;
+ }
+
+@@ -1724,18 +1689,17 @@ static int __init riscom8_init_module (void)
+
+ return riscom8_init();
+ }
+-
+-static void __exit riscom8_exit_module (void)
++
++static void __exit riscom8_exit_module(void)
+ {
+ int i;
+-
++
+ rc_release_drivers();
+- for (i = 0; i < RC_NBOARD; i++)
+- if (rc_board[i].flags & RC_BOARD_PRESENT)
++ for (i = 0; i < RC_NBOARD; i++)
++ if (rc_board[i].flags & RC_BOARD_PRESENT)
+ rc_release_io_range(&rc_board[i]);
+-
++
+ }
+
+ module_init(riscom8_init_module);
+ module_exit(riscom8_exit_module);
+-
+diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
+index f585bc8..743dc80 100644
+--- a/drivers/char/rocket.c
++++ b/drivers/char/rocket.c
+@@ -449,7 +449,8 @@ static void rp_do_transmit(struct r_port *info)
+ while (1) {
+ if (tty->stopped || tty->hw_stopped)
+ break;
+- c = min(info->xmit_fifo_room, min(info->xmit_cnt, XMIT_BUF_SIZE - info->xmit_tail));
++ c = min(info->xmit_fifo_room, info->xmit_cnt);
++ c = min(c, XMIT_BUF_SIZE - info->xmit_tail);
+ if (c <= 0 || info->xmit_fifo_room <= 0)
+ break;
+ sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) (info->xmit_buf + info->xmit_tail), c / 2);
+@@ -1433,29 +1434,38 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file,
+ {
+ struct r_port *info = (struct r_port *) tty->driver_data;
+ void __user *argp = (void __user *)arg;
++ int ret = 0;
+
+ if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl"))
+ return -ENXIO;
+
++ lock_kernel();
++
+ switch (cmd) {
+ case RCKP_GET_STRUCT:
+ if (copy_to_user(argp, info, sizeof (struct r_port)))
+- return -EFAULT;
+- return 0;
++ ret = -EFAULT;
++ break;
+ case RCKP_GET_CONFIG:
+- return get_config(info, argp);
++ ret = get_config(info, argp);
++ break;
+ case RCKP_SET_CONFIG:
+- return set_config(info, argp);
++ ret = set_config(info, argp);
++ break;
+ case RCKP_GET_PORTS:
+- return get_ports(info, argp);
++ ret = get_ports(info, argp);
++ break;
+ case RCKP_RESET_RM2:
+- return reset_rm2(info, argp);
++ ret = reset_rm2(info, argp);
++ break;
+ case RCKP_GET_VERSION:
+- return get_version(info, argp);
++ ret = get_version(info, argp);
++ break;
+ default:
+- return -ENOIOCTLCMD;
++ ret = -ENOIOCTLCMD;
+ }
+- return 0;
++ unlock_kernel();
++ return ret;
+ }
+
+ static void rp_send_xchar(struct tty_struct *tty, char ch)
+@@ -1575,6 +1585,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
+ jiffies);
+ printk(KERN_INFO "cps=%d...\n", info->cps);
+ #endif
++ lock_kernel();
+ while (1) {
+ txcnt = sGetTxCnt(cp);
+ if (!txcnt) {
+@@ -1602,6 +1613,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
+ break;
+ }
+ __set_current_state(TASK_RUNNING);
++ unlock_kernel();
+ #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
+ printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
+ #endif
+@@ -1651,14 +1663,14 @@ static void rp_hangup(struct tty_struct *tty)
+ * writing routines will write directly to transmit FIFO.
+ * Write buffer and counters protected by spinlocks
+ */
+-static void rp_put_char(struct tty_struct *tty, unsigned char ch)
++static int rp_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ struct r_port *info = (struct r_port *) tty->driver_data;
+ CHANNEL_t *cp;
+ unsigned long flags;
+
+ if (rocket_paranoia_check(info, "rp_put_char"))
+- return;
++ return 0;
+
+ /*
+ * Grab the port write mutex, locking out other processes that try to
+@@ -1687,6 +1699,7 @@ static void rp_put_char(struct tty_struct *tty, unsigned char ch)
+ }
+ spin_unlock_irqrestore(&info->slock, flags);
+ mutex_unlock(&info->write_mtx);
++ return 1;
+ }
+
+ /*
+@@ -1749,10 +1762,10 @@ static int rp_write(struct tty_struct *tty,
+
+ /* Write remaining data into the port's xmit_buf */
+ while (1) {
+- if (!info->tty) /* Seemingly obligatory check... */
++ if (!info->tty) /* Seemingly obligatory check... */
+ goto end;
+-
+- c = min(count, min(XMIT_BUF_SIZE - info->xmit_cnt - 1, XMIT_BUF_SIZE - info->xmit_head));
++ c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1);
++ c = min(c, XMIT_BUF_SIZE - info->xmit_head);
+ if (c <= 0)
+ break;
+
+diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h
+index b01d381..143cc43 100644
+--- a/drivers/char/rocket_int.h
++++ b/drivers/char/rocket_int.h
+@@ -55,7 +55,7 @@ static inline void sOutW(unsigned short port, unsigned short value)
+
+ static inline void out32(unsigned short port, Byte_t *p)
+ {
+- u32 value = le32_to_cpu(get_unaligned((__le32 *)p));
++ u32 value = get_unaligned_le32(p);
+ #ifdef ROCKET_DEBUG_IO
+ printk(KERN_DEBUG "out32(%x, %lx)...\n", port, value);
+ #endif
+diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
+index 5c3142b..5f80a9d 100644
+--- a/drivers/char/rtc.c
++++ b/drivers/char/rtc.c
+@@ -88,6 +88,7 @@
+
+ #ifdef CONFIG_SPARC32
+ #include <linux/pci.h>
++#include <linux/jiffies.h>
+ #include <asm/ebus.h>
+
+ static unsigned long rtc_port;
+@@ -1068,10 +1069,8 @@ no_irq:
+ }
+
+ #ifdef CONFIG_PROC_FS
+- ent = create_proc_entry("driver/rtc", 0, NULL);
+- if (ent)
+- ent->proc_fops = &rtc_proc_fops;
+- else
++ ent = proc_create("driver/rtc", 0, NULL, &rtc_proc_fops);
++ if (!ent)
+ printk(KERN_WARNING "rtc: Failed to register with procfs.\n");
+ #endif
+
+@@ -1316,7 +1315,8 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
+ * Once the read clears, read the RTC time (again via ioctl). Easy.
+ */
+
+- while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100)
++ while (rtc_is_updating() != 0 &&
++ time_before(jiffies, uip_watchdog + 2*HZ/100))
+ cpu_relax();
+
+ /*
+diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
+index df8cd0c..fd2db07 100644
+--- a/drivers/char/serial167.c
++++ b/drivers/char/serial167.c
+@@ -1060,7 +1060,7 @@ static void config_setup(struct cyclades_port *info)
+
+ } /* config_setup */
+
+-static void cy_put_char(struct tty_struct *tty, unsigned char ch)
++static int cy_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ unsigned long flags;
+@@ -1070,7 +1070,7 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch)
+ #endif
+
+ if (serial_paranoia_check(info, tty->name, "cy_put_char"))
+- return;
++ return 0;
+
+ if (!info->xmit_buf)
+ return;
+@@ -1078,13 +1078,14 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch)
+ local_irq_save(flags);
+ if (info->xmit_cnt >= PAGE_SIZE - 1) {
+ local_irq_restore(flags);
+- return;
++ return 0;
+ }
+
+ info->xmit_buf[info->xmit_head++] = ch;
+ info->xmit_head &= PAGE_SIZE - 1;
+ info->xmit_cnt++;
+ local_irq_restore(flags);
++ return 1;
+ } /* cy_put_char */
+
+ static void cy_flush_chars(struct tty_struct *tty)
+@@ -1539,6 +1540,8 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
+ printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */
+ #endif
+
++ lock_kernel();
++
+ switch (cmd) {
+ case CYGETMON:
+ ret_val = get_mon_info(info, argp);
+@@ -1584,18 +1587,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
+ break;
+
+ /* The following commands are incompletely implemented!!! */
+- case TIOCGSOFTCAR:
+- ret_val =
+- put_user(C_CLOCAL(tty) ? 1 : 0,
+- (unsigned long __user *)argp);
+- break;
+- case TIOCSSOFTCAR:
+- ret_val = get_user(val, (unsigned long __user *)argp);
+- if (ret_val)
+- break;
+- tty->termios->c_cflag =
+- ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0));
+- break;
+ case TIOCGSERIAL:
+ ret_val = get_serial_info(info, argp);
+ break;
+@@ -1605,6 +1596,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
+ default:
+ ret_val = -ENOIOCTLCMD;
+ }
++ unlock_kernel();
+
+ #ifdef SERIAL_DEBUG_OTHER
+ printk("cy_ioctl done\n");
+@@ -1683,8 +1675,7 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
+ if (info->flags & ASYNC_INITIALIZED)
+ tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
+ shutdown(info);
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ cy_flush_buffer(tty);
+ tty_ldisc_flush(tty);
+ info->tty = NULL;
+ if (info->blocked_open) {
+diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
+index b9c1dba..8fe099a 100644
+--- a/drivers/char/snsc.c
++++ b/drivers/char/snsc.c
+@@ -80,7 +80,7 @@ scdrv_open(struct inode *inode, struct file *file)
+ sd = kzalloc(sizeof (struct subch_data_s), GFP_KERNEL);
+ if (sd == NULL) {
+ printk("%s: couldn't allocate subchannel data\n",
+- __FUNCTION__);
++ __func__);
+ return -ENOMEM;
+ }
+
+@@ -90,7 +90,7 @@ scdrv_open(struct inode *inode, struct file *file)
+
+ if (sd->sd_subch < 0) {
+ kfree(sd);
+- printk("%s: couldn't allocate subchannel\n", __FUNCTION__);
++ printk("%s: couldn't allocate subchannel\n", __func__);
+ return -EBUSY;
+ }
+
+@@ -110,7 +110,7 @@ scdrv_open(struct inode *inode, struct file *file)
+ if (rv) {
+ ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
+ kfree(sd);
+- printk("%s: irq request failed (%d)\n", __FUNCTION__, rv);
++ printk("%s: irq request failed (%d)\n", __func__, rv);
+ return -EBUSY;
+ }
+
+@@ -215,7 +215,7 @@ scdrv_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos)
+ */
+ if (count < len) {
+ pr_debug("%s: only accepting %d of %d bytes\n",
+- __FUNCTION__, (int) count, len);
++ __func__, (int) count, len);
+ }
+ len = min((int) count, len);
+ if (copy_to_user(buf, sd->sd_rb, len))
+@@ -384,7 +384,7 @@ scdrv_init(void)
+ if (alloc_chrdev_region(&first_dev, 0, num_cnodes,
+ SYSCTL_BASENAME) < 0) {
+ printk("%s: failed to register SN system controller device\n",
+- __FUNCTION__);
++ __func__);
+ return -ENODEV;
+ }
+ snsc_class = class_create(THIS_MODULE, SYSCTL_BASENAME);
+@@ -403,7 +403,7 @@ scdrv_init(void)
+ GFP_KERNEL);
+ if (!scd) {
+ printk("%s: failed to allocate device info"
+- "for %s/%s\n", __FUNCTION__,
++ "for %s/%s\n", __func__,
+ SYSCTL_BASENAME, devname);
+ continue;
+ }
+@@ -412,7 +412,7 @@ scdrv_init(void)
+ scd->scd_nasid = cnodeid_to_nasid(cnode);
+ if (!(salbuf = kmalloc(SCDRV_BUFSZ, GFP_KERNEL))) {
+ printk("%s: failed to allocate driver buffer"
+- "(%s%s)\n", __FUNCTION__,
++ "(%s%s)\n", __func__,
+ SYSCTL_BASENAME, devname);
+ kfree(scd);
+ continue;
+@@ -424,7 +424,7 @@ scdrv_init(void)
+ ("%s: failed to initialize SAL for"
+ " system controller communication"
+ " (%s/%s): outdated PROM?\n",
+- __FUNCTION__, SYSCTL_BASENAME, devname);
++ __func__, SYSCTL_BASENAME, devname);
+ kfree(scd);
+ kfree(salbuf);
+ continue;
+@@ -435,7 +435,7 @@ scdrv_init(void)
+ if (cdev_add(&scd->scd_cdev, dev, 1)) {
+ printk("%s: failed to register system"
+ " controller device (%s%s)\n",
+- __FUNCTION__, SYSCTL_BASENAME, devname);
++ __func__, SYSCTL_BASENAME, devname);
+ kfree(scd);
+ kfree(salbuf);
+ continue;
+diff --git a/drivers/char/snsc.h b/drivers/char/snsc.h
+index 8a98169..4be62ed 100644
+--- a/drivers/char/snsc.h
++++ b/drivers/char/snsc.h
+@@ -22,8 +22,8 @@
+ #include <linux/kobject.h>
+ #include <linux/fs.h>
+ #include <linux/cdev.h>
++#include <linux/semaphore.h>
+ #include <asm/sn/types.h>
+-#include <asm/semaphore.h>
+
+ #define CHUNKSIZE 127
+
+diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c
+index 1b75b0b..53b3d44 100644
+--- a/drivers/char/snsc_event.c
++++ b/drivers/char/snsc_event.c
+@@ -63,16 +63,13 @@ static int
+ scdrv_parse_event(char *event, int *src, int *code, int *esp_code, char *desc)
+ {
+ char *desc_end;
+- __be32 from_buf;
+
+ /* record event source address */
+- from_buf = get_unaligned((__be32 *)event);
+- *src = be32_to_cpup(&from_buf);
++ *src = get_unaligned_be32(event);
+ event += 4; /* move on to event code */
+
+ /* record the system controller's event code */
+- from_buf = get_unaligned((__be32 *)event);
+- *code = be32_to_cpup(&from_buf);
++ *code = get_unaligned_be32(event);
+ event += 4; /* move on to event arguments */
+
+ /* how many arguments are in the packet? */
+@@ -86,8 +83,7 @@ scdrv_parse_event(char *event, int *src, int *code, int *esp_code, char *desc)
+ /* not an integer argument, so give up */
+ return -1;
+ }
+- from_buf = get_unaligned((__be32 *)event);
+- *esp_code = be32_to_cpup(&from_buf);
++ *esp_code = get_unaligned_be32(event);
+ event += 4;
+
+ /* parse out the event description */
+@@ -275,7 +271,7 @@ scdrv_event_init(struct sysctl_data_s *scd)
+ event_sd = kzalloc(sizeof (struct subch_data_s), GFP_KERNEL);
+ if (event_sd == NULL) {
+ printk(KERN_WARNING "%s: couldn't allocate subchannel info"
+- " for event monitoring\n", __FUNCTION__);
++ " for event monitoring\n", __func__);
+ return;
+ }
+
+@@ -289,7 +285,7 @@ scdrv_event_init(struct sysctl_data_s *scd)
+ if (event_sd->sd_subch < 0) {
+ kfree(event_sd);
+ printk(KERN_WARNING "%s: couldn't open event subchannel\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+@@ -299,7 +295,7 @@ scdrv_event_init(struct sysctl_data_s *scd)
+ "system controller events", event_sd);
+ if (rv) {
+ printk(KERN_WARNING "%s: irq request failed (%d)\n",
+- __FUNCTION__, rv);
++ __func__, rv);
+ ia64_sn_irtr_close(event_sd->sd_nasid, event_sd->sd_subch);
+ kfree(event_sd);
+ return;
+diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
+index 921c6d2..58533de 100644
+--- a/drivers/char/sonypi.c
++++ b/drivers/char/sonypi.c
+@@ -506,7 +506,7 @@ static struct sonypi_device {
+ while (--n && (command)) \
+ udelay(1); \
+ if (!n && (verbose || !quiet)) \
+- printk(KERN_WARNING "sonypi command failed at %s : %s (line %d)\n", __FILE__, __FUNCTION__, __LINE__); \
++ printk(KERN_WARNING "sonypi command failed at %s : %s (line %d)\n", __FILE__, __func__, __LINE__); \
+ }
+
+ #ifdef CONFIG_ACPI
+@@ -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..2ee4d98 100644
+--- a/drivers/char/specialix.c
++++ b/drivers/char/specialix.c
+@@ -131,8 +131,8 @@ static int sx_rxfifo = SPECIALIX_RXFIFO;
+ #define SX_DEBUG_FIFO 0x0800
+
+
+-#define func_enter() dprintk (SX_DEBUG_FLOW, "io8: enter %s\n",__FUNCTION__)
+-#define func_exit() dprintk (SX_DEBUG_FLOW, "io8: exit %s\n", __FUNCTION__)
++#define func_enter() dprintk (SX_DEBUG_FLOW, "io8: enter %s\n",__func__)
++#define func_exit() dprintk (SX_DEBUG_FLOW, "io8: exit %s\n", __func__)
+
+ #define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
+
+@@ -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);
++ dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__, 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;
+@@ -1506,6 +1504,27 @@ static int sx_open(struct tty_struct * tty, struct file * filp)
+ return 0;
+ }
+
++static void sx_flush_buffer(struct tty_struct *tty)
++{
++ struct specialix_port *port = (struct specialix_port *)tty->driver_data;
++ unsigned long flags;
++ struct specialix_board * bp;
++
++ func_enter();
++
++ if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) {
++ func_exit();
++ return;
++ }
++
++ bp = port_Board(port);
++ spin_lock_irqsave(&port->lock, flags);
++ port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
++ spin_unlock_irqrestore(&port->lock, flags);
++ tty_wakeup(tty);
++
++ func_exit();
++}
+
+ static void sx_close(struct tty_struct * tty, struct file * filp)
+ {
+@@ -1599,8 +1618,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
+ }
+
+ sx_shutdown_port(bp, port);
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ sx_flush_buffer(tty);
+ tty_ldisc_flush(tty);
+ spin_lock_irqsave(&port->lock, flags);
+ tty->closing = 0;
+@@ -1672,7 +1690,7 @@ static int sx_write(struct tty_struct * tty,
+ }
+
+
+-static void sx_put_char(struct tty_struct * tty, unsigned char ch)
++static int sx_put_char(struct tty_struct * tty, unsigned char ch)
+ {
+ struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ unsigned long flags;
+@@ -1682,12 +1700,12 @@ static void sx_put_char(struct tty_struct * tty, unsigned char ch)
+
+ if (sx_paranoia_check(port, tty->name, "sx_put_char")) {
+ func_exit();
+- return;
++ return 0;
+ }
+ dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
+ if (!port->xmit_buf) {
+ func_exit();
+- return;
++ return 0;
+ }
+ bp = port_Board(port);
+ spin_lock_irqsave(&port->lock, flags);
+@@ -1697,7 +1715,7 @@ static void sx_put_char(struct tty_struct * tty, unsigned char ch)
+ spin_unlock_irqrestore(&port->lock, flags);
+ dprintk (SX_DEBUG_TX, "Exit size\n");
+ func_exit();
+- return;
++ return 0;
+ }
+ dprintk (SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf);
+ port->xmit_buf[port->xmit_head++] = ch;
+@@ -1706,6 +1724,7 @@ static void sx_put_char(struct tty_struct * tty, unsigned char ch)
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ func_exit();
++ return 1;
+ }
+
+
+@@ -1772,28 +1791,6 @@ static int sx_chars_in_buffer(struct tty_struct *tty)
+ }
+
+
+-static void sx_flush_buffer(struct tty_struct *tty)
+-{
+- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+- unsigned long flags;
+- struct specialix_board * bp;
+-
+- func_enter();
+-
+- if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) {
+- func_exit();
+- return;
+- }
+-
+- bp = port_Board(port);
+- spin_lock_irqsave(&port->lock, flags);
+- port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+- spin_unlock_irqrestore(&port->lock, flags);
+- tty_wakeup(tty);
+-
+- func_exit();
+-}
+-
+
+ static int sx_tiocmget(struct tty_struct *tty, struct file *file)
+ {
+@@ -1805,7 +1802,7 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file)
+
+ func_enter();
+
+- if (sx_paranoia_check(port, tty->name, __FUNCTION__)) {
++ if (sx_paranoia_check(port, tty->name, __func__)) {
+ func_exit();
+ return -ENODEV;
+ }
+@@ -1847,7 +1844,7 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file,
+
+ func_enter();
+
+- if (sx_paranoia_check(port, tty->name, __FUNCTION__)) {
++ if (sx_paranoia_check(port, tty->name, __func__)) {
+ func_exit();
+ return -ENODEV;
+ }
+@@ -1924,29 +1921,13 @@ static inline int sx_set_serial_info(struct specialix_port * port,
+ int change_speed;
+
+ func_enter();
+- /*
+- if (!access_ok(VERIFY_READ, (void *) newinfo, sizeof(tmp))) {
+- func_exit();
+- return -EFAULT;
+- }
+- */
++
+ if (copy_from_user(&tmp, newinfo, sizeof(tmp))) {
+ func_enter();
+ return -EFAULT;
+ }
+
+-#if 0
+- if ((tmp.irq != bp->irq) ||
+- (tmp.port != bp->base) ||
+- (tmp.type != PORT_CIRRUS) ||
+- (tmp.baud_base != (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC) ||
+- (tmp.custom_divisor != 0) ||
+- (tmp.xmit_fifo_size != CD186x_NFIFO) ||
+- (tmp.flags & ~SPECIALIX_LEGAL_FLAGS)) {
+- func_exit();
+- return -EINVAL;
+- }
+-#endif
++ lock_kernel();
+
+ change_speed = ((port->flags & ASYNC_SPD_MASK) !=
+ (tmp.flags & ASYNC_SPD_MASK));
+@@ -1958,6 +1939,7 @@ static inline int sx_set_serial_info(struct specialix_port * port,
+ ((tmp.flags & ~ASYNC_USR_MASK) !=
+ (port->flags & ~ASYNC_USR_MASK))) {
+ func_exit();
++ unlock_kernel();
+ return -EPERM;
+ }
+ port->flags = ((port->flags & ~ASYNC_USR_MASK) |
+@@ -1974,6 +1956,7 @@ static inline int sx_set_serial_info(struct specialix_port * port,
+ sx_change_speed(bp, port);
+ }
+ func_exit();
++ unlock_kernel();
+ return 0;
+ }
+
+@@ -1986,12 +1969,8 @@ static inline int sx_get_serial_info(struct specialix_port * port,
+
+ func_enter();
+
+- /*
+- if (!access_ok(VERIFY_WRITE, (void *) retinfo, sizeof(tmp)))
+- return -EFAULT;
+- */
+-
+ memset(&tmp, 0, sizeof(tmp));
++ lock_kernel();
+ tmp.type = PORT_CIRRUS;
+ tmp.line = port - sx_port;
+ tmp.port = bp->base;
+@@ -2002,6 +1981,7 @@ static inline int sx_get_serial_info(struct specialix_port * port,
+ tmp.closing_wait = port->closing_wait * HZ/100;
+ tmp.custom_divisor = port->custom_divisor;
+ tmp.xmit_fifo_size = CD186x_NFIFO;
++ unlock_kernel();
+ if (copy_to_user(retinfo, &tmp, sizeof(tmp))) {
+ func_exit();
+ return -EFAULT;
+@@ -2047,23 +2027,6 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp,
+ sx_send_break(port, arg ? arg*(HZ/10) : HZ/4);
+ func_exit();
+ return 0;
+- case TIOCGSOFTCAR:
+- if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)argp)) {
+- func_exit();
+- return -EFAULT;
+- }
+- func_exit();
+- return 0;
+- case TIOCSSOFTCAR:
+- if (get_user(arg, (unsigned long __user *) argp)) {
+- func_exit();
+- return -EFAULT;
+- }
+- tty->termios->c_cflag =
+- ((tty->termios->c_cflag & ~CLOCAL) |
+- (arg ? CLOCAL : 0));
+- func_exit();
+- return 0;
+ case TIOCGSERIAL:
+ func_exit();
+ return sx_get_serial_info(port, argp);
+diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
+index feac54e..d17be10 100644
+--- a/drivers/char/stallion.c
++++ b/drivers/char/stallion.c
+@@ -875,6 +875,7 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
+ timeout = HZ;
+ tend = jiffies + timeout;
+
++ lock_kernel();
+ while (stl_datastate(portp)) {
+ if (signal_pending(current))
+ break;
+@@ -882,6 +883,7 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
+ if (time_after_eq(jiffies, tend))
+ break;
+ }
++ unlock_kernel();
+ }
+
+ /*****************************************************************************/
+@@ -1273,18 +1275,9 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
+
+ rc = 0;
+
++ lock_kernel();
++
+ switch (cmd) {
+- case TIOCGSOFTCAR:
+- rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
+- (unsigned __user *) argp);
+- break;
+- case TIOCSSOFTCAR:
+- if (get_user(ival, (unsigned int __user *) arg))
+- return -EFAULT;
+- tty->termios->c_cflag =
+- (tty->termios->c_cflag & ~CLOCAL) |
+- (ival ? CLOCAL : 0);
+- break;
+ case TIOCGSERIAL:
+ rc = stl_getserial(portp, argp);
+ break;
+@@ -1308,7 +1301,7 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
+ rc = -ENOIOCTLCMD;
+ break;
+ }
+-
++ unlock_kernel();
+ return rc;
+ }
+
+@@ -1645,7 +1638,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/sx.c b/drivers/char/sx.c
+index a6e1c9b..f39f6fd 100644
+--- a/drivers/char/sx.c
++++ b/drivers/char/sx.c
+@@ -384,11 +384,11 @@ static struct real_driver sx_real_driver = {
+ #define sx_dprintk(f, str...) /* nothing */
+ #endif
+
+-#define func_enter() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__FUNCTION__)
+-#define func_exit() sx_dprintk(SX_DEBUG_FLOW, "sx: exit %s\n",__FUNCTION__)
++#define func_enter() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__func__)
++#define func_exit() sx_dprintk(SX_DEBUG_FLOW, "sx: exit %s\n",__func__)
+
+ #define func_enter2() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
+- __FUNCTION__, port->line)
++ __func__, port->line)
+
+ /*
+ * Firmware loader driver specific routines
+@@ -1574,7 +1574,7 @@ static void sx_close(void *ptr)
+ sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n",
+ port->gs.count);
+ /*printk("%s SETTING port count to zero: %p count: %d\n",
+- __FUNCTION__, port, port->gs.count);
++ __func__, port, port->gs.count);
+ port->gs.count = 0;*/
+ }
+
+@@ -1844,6 +1844,7 @@ static void sx_break(struct tty_struct *tty, int flag)
+ int rv;
+
+ func_enter();
++ lock_kernel();
+
+ if (flag)
+ rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK);
+@@ -1852,7 +1853,7 @@ static void sx_break(struct tty_struct *tty, int flag)
+ if (rv != 1)
+ printk(KERN_ERR "sx: couldn't send break (%x).\n",
+ read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
+-
++ unlock_kernel();
+ func_exit();
+ }
+
+@@ -1888,23 +1889,12 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp,
+ int rc;
+ struct sx_port *port = tty->driver_data;
+ void __user *argp = (void __user *)arg;
+- int ival;
+
+ /* func_enter2(); */
+
+ rc = 0;
++ lock_kernel();
+ switch (cmd) {
+- case TIOCGSOFTCAR:
+- rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
+- (unsigned __user *)argp);
+- break;
+- case TIOCSSOFTCAR:
+- if ((rc = get_user(ival, (unsigned __user *)argp)) == 0) {
+- tty->termios->c_cflag =
+- (tty->termios->c_cflag & ~CLOCAL) |
+- (ival ? CLOCAL : 0);
+- }
+- break;
+ case TIOCGSERIAL:
+ rc = gs_getserial(&port->gs, argp);
+ break;
+@@ -1915,6 +1905,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp,
+ rc = -ENOIOCTLCMD;
+ break;
+ }
++ unlock_kernel();
+
+ /* func_exit(); */
+ return rc;
+@@ -2549,7 +2540,7 @@ static int __devinit sx_eisa_probe(struct device *dev)
+ goto err_flag;
+ }
+ board->base2 =
+- board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN);
++ board->base = ioremap_nocache(board->hw_base, SI2_EISA_WINDOW_LEN);
+ if (!board->base) {
+ dev_err(dev, "can't remap memory\n");
+ goto err_reg;
+@@ -2626,7 +2617,7 @@ static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board)
+
+ pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
+ hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
+- rebase = ioremap(hwbase, 0x80);
++ rebase = ioremap_nocache(hwbase, 0x80);
+ t = readl(rebase + CNTRL_REG_OFFSET);
+ if (t != CNTRL_REG_GOODVALUE) {
+ printk(KERN_DEBUG "sx: performing cntrl reg fix: %08x -> "
+@@ -2770,7 +2761,7 @@ static int __init sx_init(void)
+ if (!request_region(board->hw_base, board->hw_len, "sx"))
+ continue;
+ board->base2 =
+- board->base = ioremap(board->hw_base, board->hw_len);
++ board->base = ioremap_nocache(board->hw_base, board->hw_len);
+ if (!board->base)
+ goto err_sx_reg;
+ board->flags &= ~SX_BOARD_TYPE;
+@@ -2794,7 +2785,7 @@ err_sx_reg:
+ if (!request_region(board->hw_base, board->hw_len, "sx"))
+ continue;
+ board->base2 =
+- board->base = ioremap(board->hw_base, board->hw_len);
++ board->base = ioremap_nocache(board->hw_base, board->hw_len);
+ if (!board->base)
+ goto err_si_reg;
+ board->flags &= ~SX_BOARD_TYPE;
+@@ -2817,7 +2808,7 @@ err_si_reg:
+ if (!request_region(board->hw_base, board->hw_len, "sx"))
+ continue;
+ board->base2 =
+- board->base = ioremap(board->hw_base, board->hw_len);
++ board->base = ioremap_nocache(board->hw_base, board->hw_len);
+ if (!board->base)
+ goto err_si1_reg;
+ board->flags &= ~SX_BOARD_TYPE;
+diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
+index ddc74d1..513b7c2 100644
+--- a/drivers/char/synclink.c
++++ b/drivers/char/synclink.c
+@@ -218,9 +218,9 @@ struct mgsl_struct {
+
+ u32 pending_bh;
+
+- int bh_running; /* Protection from multiple */
++ bool bh_running; /* Protection from multiple */
+ int isr_overflow;
+- int bh_requested;
++ bool bh_requested;
+
+ int dcd_chkcount; /* check counts to prevent */
+ int cts_chkcount; /* too many IRQs if a signal */
+@@ -250,12 +250,12 @@ struct mgsl_struct {
+ int tx_holding_count; /* number of tx holding buffers waiting */
+ struct tx_holding_buffer tx_holding_buffers[MAX_TX_HOLDING_BUFFERS];
+
+- int rx_enabled;
+- int rx_overflow;
+- int rx_rcc_underrun;
++ bool rx_enabled;
++ bool rx_overflow;
++ bool rx_rcc_underrun;
+
+- int tx_enabled;
+- int tx_active;
++ bool tx_enabled;
++ bool tx_active;
+ u32 idle_mode;
+
+ u16 cmr_value;
+@@ -269,14 +269,14 @@ struct mgsl_struct {
+
+ unsigned int io_base; /* base I/O address of adapter */
+ unsigned int io_addr_size; /* size of the I/O address range */
+- int io_addr_requested; /* nonzero if I/O address requested */
++ bool io_addr_requested; /* true if I/O address requested */
+
+ unsigned int irq_level; /* interrupt level */
+ unsigned long irq_flags;
+- int irq_requested; /* nonzero if IRQ requested */
++ bool irq_requested; /* true if IRQ requested */
+
+ unsigned int dma_level; /* DMA channel */
+- int dma_requested; /* nonzero if dma channel requested */
++ bool dma_requested; /* true if dma channel requested */
+
+ u16 mbre_bit;
+ u16 loopback_bits;
+@@ -286,27 +286,27 @@ struct mgsl_struct {
+
+ unsigned char serial_signals; /* current serial signal states */
+
+- int irq_occurred; /* for diagnostics use */
++ bool irq_occurred; /* for diagnostics use */
+ unsigned int init_error; /* Initialization startup error (DIAGS) */
+ int fDiagnosticsmode; /* Driver in Diagnostic mode? (DIAGS) */
+
+ u32 last_mem_alloc;
+ unsigned char* memory_base; /* shared memory address (PCI only) */
+ u32 phys_memory_base;
+- int shared_mem_requested;
++ bool shared_mem_requested;
+
+ unsigned char* lcr_base; /* local config registers (PCI only) */
+ u32 phys_lcr_base;
+ u32 lcr_offset;
+- int lcr_mem_requested;
++ bool lcr_mem_requested;
+
+ u32 misc_ctrl_value;
+ char flag_buf[MAX_ASYNC_BUFFER_SIZE];
+ char char_buf[MAX_ASYNC_BUFFER_SIZE];
+- BOOLEAN drop_rts_on_tx_done;
++ bool drop_rts_on_tx_done;
+
+- BOOLEAN loopmode_insert_requested;
+- BOOLEAN loopmode_send_done_requested;
++ bool loopmode_insert_requested;
++ bool loopmode_send_done_requested;
+
+ struct _input_signal_events input_signal_events;
+
+@@ -752,10 +752,10 @@ static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int coun
+ /*
+ * Adapter diagnostic routines
+ */
+-static BOOLEAN mgsl_register_test( struct mgsl_struct *info );
+-static BOOLEAN mgsl_irq_test( struct mgsl_struct *info );
+-static BOOLEAN mgsl_dma_test( struct mgsl_struct *info );
+-static BOOLEAN mgsl_memory_test( struct mgsl_struct *info );
++static bool mgsl_register_test( struct mgsl_struct *info );
++static bool mgsl_irq_test( struct mgsl_struct *info );
++static bool mgsl_dma_test( struct mgsl_struct *info );
++static bool mgsl_memory_test( struct mgsl_struct *info );
+ static int mgsl_adapter_test( struct mgsl_struct *info );
+
+ /*
+@@ -770,8 +770,8 @@ static struct mgsl_struct* mgsl_allocate_device(void);
+ * DMA buffer manupulation functions.
+ */
+ static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex );
+-static int mgsl_get_rx_frame( struct mgsl_struct *info );
+-static int mgsl_get_raw_rx_frame( struct mgsl_struct *info );
++static bool mgsl_get_rx_frame( struct mgsl_struct *info );
++static bool mgsl_get_raw_rx_frame( struct mgsl_struct *info );
+ static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info );
+ static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info );
+ static int num_free_tx_dma_buffers(struct mgsl_struct *info);
+@@ -791,7 +791,7 @@ static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info);
+ static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info);
+ static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info);
+ static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info);
+-static int load_next_tx_holding_buffer(struct mgsl_struct *info);
++static bool load_next_tx_holding_buffer(struct mgsl_struct *info);
+ static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize);
+
+ /*
+@@ -847,7 +847,7 @@ static int mgsl_wait_event(struct mgsl_struct * info, int __user *mask);
+ static int mgsl_loopmode_send_done( struct mgsl_struct * info );
+
+ /* set non-zero on successful registration with PCI subsystem */
+-static int pci_registered;
++static bool pci_registered;
+
+ /*
+ * Global linked list of SyncLink devices
+@@ -1054,8 +1054,8 @@ static int mgsl_bh_action(struct mgsl_struct *info)
+
+ if (!rc) {
+ /* Mark BH routine as complete */
+- info->bh_running = 0;
+- info->bh_requested = 0;
++ info->bh_running = false;
++ info->bh_requested = false;
+ }
+
+ spin_unlock_irqrestore(&info->irq_spinlock,flags);
+@@ -1079,7 +1079,7 @@ static void mgsl_bh_handler(struct work_struct *work)
+ printk( "%s(%d):mgsl_bh_handler(%s) entry\n",
+ __FILE__,__LINE__,info->device_name);
+
+- info->bh_running = 1;
++ info->bh_running = true;
+
+ while((action = mgsl_bh_action(info)) != 0) {
+
+@@ -1113,7 +1113,7 @@ static void mgsl_bh_handler(struct work_struct *work)
+
+ static void mgsl_bh_receive(struct mgsl_struct *info)
+ {
+- int (*get_rx_frame)(struct mgsl_struct *info) =
++ bool (*get_rx_frame)(struct mgsl_struct *info) =
+ (info->params.mode == MGSL_MODE_HDLC ? mgsl_get_rx_frame : mgsl_get_raw_rx_frame);
+
+ if ( debug_level >= DEBUG_LEVEL_BH )
+@@ -1187,7 +1187,7 @@ static void mgsl_isr_receive_status( struct mgsl_struct *info )
+ usc_loopmode_active(info) )
+ {
+ ++info->icount.rxabort;
+- info->loopmode_insert_requested = FALSE;
++ info->loopmode_insert_requested = false;
+
+ /* clear CMR:13 to start echoing RxD to TxD */
+ info->cmr_value &= ~BIT13;
+@@ -1257,7 +1257,7 @@ static void mgsl_isr_transmit_status( struct mgsl_struct *info )
+ else
+ info->icount.txunder++;
+
+- info->tx_active = 0;
++ info->tx_active = false;
+ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+ del_timer(&info->tx_timer);
+
+@@ -1267,7 +1267,7 @@ static void mgsl_isr_transmit_status( struct mgsl_struct *info )
+ info->serial_signals &= ~SerialSignal_RTS;
+ usc_set_serial_signals( info );
+ }
+- info->drop_rts_on_tx_done = 0;
++ info->drop_rts_on_tx_done = false;
+ }
+
+ #if SYNCLINK_GENERIC_HDLC
+@@ -1403,7 +1403,7 @@ static void mgsl_isr_io_pin( struct mgsl_struct *info )
+ usc_OutReg( info, SICR,
+ (unsigned short)(usc_InReg(info,SICR) & ~(SICR_TXC_ACTIVE+SICR_TXC_INACTIVE)) );
+ usc_UnlatchIostatusBits( info, MISCSTATUS_TXC_LATCHED );
+- info->irq_occurred = 1;
++ info->irq_occurred = true;
+ }
+
+ } /* end of mgsl_isr_io_pin() */
+@@ -1431,7 +1431,7 @@ static void mgsl_isr_transmit_data( struct mgsl_struct *info )
+ if ( info->xmit_cnt )
+ usc_load_txfifo( info );
+ else
+- info->tx_active = 0;
++ info->tx_active = false;
+
+ if (info->xmit_cnt < WAKEUP_CHARS)
+ info->pending_bh |= BH_TRANSMIT;
+@@ -1568,7 +1568,7 @@ static void mgsl_isr_misc( struct mgsl_struct *info )
+
+ /* schedule BH handler to restart receiver */
+ info->pending_bh |= BH_RECEIVE;
+- info->rx_rcc_underrun = 1;
++ info->rx_rcc_underrun = true;
+ }
+
+ usc_ClearIrqPendingBits( info, MISC );
+@@ -1626,7 +1626,7 @@ static void mgsl_isr_receive_dma( struct mgsl_struct *info )
+ info->pending_bh |= BH_RECEIVE;
+
+ if ( status & BIT3 ) {
+- info->rx_overflow = 1;
++ info->rx_overflow = true;
+ info->icount.buf_overrun++;
+ }
+
+@@ -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;
+@@ -1749,14 +1745,15 @@ static irqreturn_t mgsl_interrupt(int irq, void *dev_id)
+ printk("%s(%d):%s queueing bh task.\n",
+ __FILE__,__LINE__,info->device_name);
+ schedule_work(&info->task);
+- info->bh_requested = 1;
++ info->bh_requested = true;
+ }
+
+ 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() */
+
+@@ -2029,10 +2026,11 @@ static void mgsl_change_params(struct mgsl_struct *info)
+ *
+ * Return Value: None
+ */
+-static void mgsl_put_char(struct tty_struct *tty, unsigned char ch)
++static int mgsl_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
+ unsigned long flags;
++ int ret;
+
+ if ( debug_level >= DEBUG_LEVEL_INFO ) {
+ printk( "%s(%d):mgsl_put_char(%d) on %s\n",
+@@ -2040,23 +2038,23 @@ static void mgsl_put_char(struct tty_struct *tty, unsigned char ch)
+ }
+
+ if (mgsl_paranoia_check(info, tty->name, "mgsl_put_char"))
+- return;
++ return 0;
+
+ if (!tty || !info->xmit_buf)
+- return;
++ return 0;
+
+ spin_lock_irqsave(&info->irq_spinlock,flags);
+
+ if ( (info->params.mode == MGSL_MODE_ASYNC ) || !info->tx_active ) {
+-
+ if (info->xmit_cnt < SERIAL_XMIT_SIZE - 1) {
+ info->xmit_buf[info->xmit_head++] = ch;
+ info->xmit_head &= SERIAL_XMIT_SIZE-1;
+ info->xmit_cnt++;
++ ret = 1;
+ }
+ }
+-
+ spin_unlock_irqrestore(&info->irq_spinlock,flags);
++ return ret;
+
+ } /* end of mgsl_put_char() */
+
+@@ -2945,6 +2943,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned long arg)
+ {
+ struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data;
++ int ret;
+
+ if (debug_level >= DEBUG_LEVEL_INFO)
+ printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
+@@ -2959,7 +2958,10 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
+ return -EIO;
+ }
+
+- return mgsl_ioctl_common(info, cmd, arg);
++ lock_kernel();
++ ret = mgsl_ioctl_common(info, cmd, arg);
++ unlock_kernel();
++ return ret;
+ }
+
+ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
+@@ -3156,8 +3158,7 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp)
+ if (info->flags & ASYNC_INITIALIZED)
+ mgsl_wait_until_sent(tty, info->timeout);
+
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ mgsl_flush_buffer(tty);
+
+ tty_ldisc_flush(tty);
+
+@@ -3220,7 +3221,8 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)
+ * interval should also be less than the timeout.
+ * Note: use tight timings here to satisfy the NIST-PCTS.
+ */
+-
++
++ lock_kernel();
+ if ( info->params.data_rate ) {
+ char_time = info->timeout/(32 * 5);
+ if (!char_time)
+@@ -3250,6 +3252,7 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)
+ break;
+ }
+ }
++ unlock_kernel();
+
+ exit:
+ if (debug_level >= DEBUG_LEVEL_INFO)
+@@ -3306,7 +3309,8 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
+ {
+ DECLARE_WAITQUEUE(wait, current);
+ int retval;
+- int do_clocal = 0, extra_count = 0;
++ bool do_clocal = false;
++ bool extra_count = false;
+ unsigned long flags;
+
+ if (debug_level >= DEBUG_LEVEL_INFO)
+@@ -3320,7 +3324,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
+ }
+
+ if (tty->termios->c_cflag & CLOCAL)
+- do_clocal = 1;
++ do_clocal = true;
+
+ /* Wait for carrier detect and the line to become
+ * free (i.e., not in use by the callout). While we are in
+@@ -3338,7 +3342,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
+
+ spin_lock_irqsave(&info->irq_spinlock, flags);
+ if (!tty_hung_up_p(filp)) {
+- extra_count = 1;
++ extra_count = true;
+ info->count--;
+ }
+ spin_unlock_irqrestore(&info->irq_spinlock, flags);
+@@ -4046,13 +4050,13 @@ static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info)
+ *
+ * info pointer to device instance data
+ *
+- * Return Value: 1 if next buffered tx request loaded
++ * Return Value: true if next buffered tx request loaded
+ * into adapter's tx dma buffer,
+- * 0 otherwise
++ * false otherwise
+ */
+-static int load_next_tx_holding_buffer(struct mgsl_struct *info)
++static bool load_next_tx_holding_buffer(struct mgsl_struct *info)
+ {
+- int ret = 0;
++ bool ret = false;
+
+ if ( info->tx_holding_count ) {
+ /* determine if we have enough tx dma buffers
+@@ -4076,7 +4080,7 @@ static int load_next_tx_holding_buffer(struct mgsl_struct *info)
+ /* restart transmit timer */
+ mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(5000));
+
+- ret = 1;
++ ret = true;
+ }
+ }
+
+@@ -4122,7 +4126,7 @@ static int mgsl_claim_resources(struct mgsl_struct *info)
+ __FILE__,__LINE__,info->device_name, info->io_base);
+ return -ENODEV;
+ }
+- info->io_addr_requested = 1;
++ info->io_addr_requested = true;
+
+ if ( request_irq(info->irq_level,mgsl_interrupt,info->irq_flags,
+ info->device_name, info ) < 0 ) {
+@@ -4130,7 +4134,7 @@ static int mgsl_claim_resources(struct mgsl_struct *info)
+ __FILE__,__LINE__,info->device_name, info->irq_level );
+ goto errout;
+ }
+- info->irq_requested = 1;
++ info->irq_requested = true;
+
+ if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
+ if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) {
+@@ -4138,15 +4142,16 @@ static int mgsl_claim_resources(struct mgsl_struct *info)
+ __FILE__,__LINE__,info->device_name, info->phys_memory_base);
+ goto errout;
+ }
+- info->shared_mem_requested = 1;
++ info->shared_mem_requested = true;
+ if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclink") == NULL) {
+ printk( "%s(%d):lcr mem addr conflict device %s Addr=%08X\n",
+ __FILE__,__LINE__,info->device_name, info->phys_lcr_base + info->lcr_offset);
+ goto errout;
+ }
+- info->lcr_mem_requested = 1;
++ info->lcr_mem_requested = true;
+
+- info->memory_base = ioremap(info->phys_memory_base,0x40000);
++ info->memory_base = ioremap_nocache(info->phys_memory_base,
++ 0x40000);
+ if (!info->memory_base) {
+ printk( "%s(%d):Cant map shared memory on device %s MemAddr=%08X\n",
+ __FILE__,__LINE__,info->device_name, info->phys_memory_base );
+@@ -4159,12 +4164,14 @@ static int mgsl_claim_resources(struct mgsl_struct *info)
+ goto errout;
+ }
+
+- info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE) + info->lcr_offset;
++ info->lcr_base = ioremap_nocache(info->phys_lcr_base,
++ PAGE_SIZE);
+ if (!info->lcr_base) {
+ printk( "%s(%d):Cant map LCR memory on device %s MemAddr=%08X\n",
+ __FILE__,__LINE__,info->device_name, info->phys_lcr_base );
+ goto errout;
+ }
++ info->lcr_base += info->lcr_offset;
+
+ } else {
+ /* claim DMA channel */
+@@ -4175,7 +4182,7 @@ static int mgsl_claim_resources(struct mgsl_struct *info)
+ mgsl_release_resources( info );
+ return -ENODEV;
+ }
+- info->dma_requested = 1;
++ info->dma_requested = true;
+
+ /* ISA adapter uses bus master DMA */
+ set_dma_mode(info->dma_level,DMA_MODE_CASCADE);
+@@ -4203,12 +4210,12 @@ static void mgsl_release_resources(struct mgsl_struct *info)
+
+ if ( info->irq_requested ) {
+ free_irq(info->irq_level, info);
+- info->irq_requested = 0;
++ info->irq_requested = false;
+ }
+ if ( info->dma_requested ) {
+ disable_dma(info->dma_level);
+ free_dma(info->dma_level);
+- info->dma_requested = 0;
++ info->dma_requested = false;
+ }
+ mgsl_free_dma_buffers(info);
+ mgsl_free_intermediate_rxbuffer_memory(info);
+@@ -4216,15 +4223,15 @@ static void mgsl_release_resources(struct mgsl_struct *info)
+
+ if ( info->io_addr_requested ) {
+ release_region(info->io_base,info->io_addr_size);
+- info->io_addr_requested = 0;
++ info->io_addr_requested = false;
+ }
+ if ( info->shared_mem_requested ) {
+ release_mem_region(info->phys_memory_base,0x40000);
+- info->shared_mem_requested = 0;
++ info->shared_mem_requested = false;
+ }
+ if ( info->lcr_mem_requested ) {
+ release_mem_region(info->phys_lcr_base + info->lcr_offset,128);
+- info->lcr_mem_requested = 0;
++ info->lcr_mem_requested = false;
+ }
+ if (info->memory_base){
+ iounmap(info->memory_base);
+@@ -4489,7 +4496,7 @@ static int __init synclink_init(void)
+ if ((rc = pci_register_driver(&synclink_pci_driver)) < 0)
+ printk("%s:failed to register PCI driver, error=%d\n",__FILE__,rc);
+ else
+- pci_registered = 1;
++ pci_registered = true;
+
+ if ((rc = mgsl_init_tty()) < 0)
+ goto error;
+@@ -4682,7 +4689,7 @@ static u16 usc_InReg( struct mgsl_struct *info, u16 RegAddr )
+ static void usc_set_sdlc_mode( struct mgsl_struct *info )
+ {
+ u16 RegValue;
+- int PreSL1660;
++ bool PreSL1660;
+
+ /*
+ * determine if the IUSC on the adapter is pre-SL1660. If
+@@ -4695,11 +4702,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
+ */
+ usc_OutReg(info,TMCR,0x1f);
+ RegValue=usc_InReg(info,TMDR);
+- if ( RegValue == IUSC_PRE_SL1660 )
+- PreSL1660 = 1;
+- else
+- PreSL1660 = 0;
+-
++ PreSL1660 = (RegValue == IUSC_PRE_SL1660);
+
+ if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
+ {
+@@ -5385,9 +5388,9 @@ static void usc_process_rxoverrun_sync( struct mgsl_struct *info )
+ int start_index;
+ int end_index;
+ int frame_start_index;
+- int start_of_frame_found = FALSE;
+- int end_of_frame_found = FALSE;
+- int reprogram_dma = FALSE;
++ bool start_of_frame_found = false;
++ bool end_of_frame_found = false;
++ bool reprogram_dma = false;
+
+ DMABUFFERENTRY *buffer_list = info->rx_buffer_list;
+ u32 phys_addr;
+@@ -5413,9 +5416,9 @@ static void usc_process_rxoverrun_sync( struct mgsl_struct *info )
+
+ if ( !start_of_frame_found )
+ {
+- start_of_frame_found = TRUE;
++ start_of_frame_found = true;
+ frame_start_index = end_index;
+- end_of_frame_found = FALSE;
++ end_of_frame_found = false;
+ }
+
+ if ( buffer_list[end_index].status )
+@@ -5426,8 +5429,8 @@ static void usc_process_rxoverrun_sync( struct mgsl_struct *info )
+ /* We want to leave the buffers for this frame intact. */
+ /* Move on to next possible frame. */
+
+- start_of_frame_found = FALSE;
+- end_of_frame_found = TRUE;
++ start_of_frame_found = false;
++ end_of_frame_found = true;
+ }
+
+ /* advance to next buffer entry in linked list */
+@@ -5442,8 +5445,8 @@ static void usc_process_rxoverrun_sync( struct mgsl_struct *info )
+ /* completely screwed, reset all receive buffers! */
+ mgsl_reset_rx_dma_buffers( info );
+ frame_start_index = 0;
+- start_of_frame_found = FALSE;
+- reprogram_dma = TRUE;
++ start_of_frame_found = false;
++ reprogram_dma = true;
+ break;
+ }
+ }
+@@ -5469,7 +5472,7 @@ static void usc_process_rxoverrun_sync( struct mgsl_struct *info )
+
+ } while( start_index != end_index );
+
+- reprogram_dma = TRUE;
++ reprogram_dma = true;
+ }
+
+ if ( reprogram_dma )
+@@ -5539,9 +5542,9 @@ static void usc_stop_receiver( struct mgsl_struct *info )
+ usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) );
+ usc_RTCmd( info, RTCmd_PurgeRxFifo );
+
+- info->rx_enabled = 0;
+- info->rx_overflow = 0;
+- info->rx_rcc_underrun = 0;
++ info->rx_enabled = false;
++ info->rx_overflow = false;
++ info->rx_rcc_underrun = false;
+
+ } /* end of stop_receiver() */
+
+@@ -5604,7 +5607,7 @@ static void usc_start_receiver( struct mgsl_struct *info )
+
+ usc_OutReg( info, CCSR, 0x1020 );
+
+- info->rx_enabled = 1;
++ info->rx_enabled = true;
+
+ } /* end of usc_start_receiver() */
+
+@@ -5631,14 +5634,14 @@ static void usc_start_transmitter( struct mgsl_struct *info )
+ /* RTS and set a flag indicating that the driver should */
+ /* negate RTS when the transmission completes. */
+
+- info->drop_rts_on_tx_done = 0;
++ info->drop_rts_on_tx_done = false;
+
+ if ( info->params.flags & HDLC_FLAG_AUTO_RTS ) {
+ usc_get_serial_signals( info );
+ if ( !(info->serial_signals & SerialSignal_RTS) ) {
+ info->serial_signals |= SerialSignal_RTS;
+ usc_set_serial_signals( info );
+- info->drop_rts_on_tx_done = 1;
++ info->drop_rts_on_tx_done = true;
+ }
+ }
+
+@@ -5702,11 +5705,11 @@ static void usc_start_transmitter( struct mgsl_struct *info )
+ mod_timer(&info->tx_timer, jiffies +
+ msecs_to_jiffies(5000));
+ }
+- info->tx_active = 1;
++ info->tx_active = true;
+ }
+
+ if ( !info->tx_enabled ) {
+- info->tx_enabled = 1;
++ info->tx_enabled = true;
+ if ( info->params.flags & HDLC_FLAG_AUTO_CTS )
+ usc_EnableTransmitter(info,ENABLE_AUTO_CTS);
+ else
+@@ -5738,8 +5741,8 @@ static void usc_stop_transmitter( struct mgsl_struct *info )
+ usc_DmaCmd( info, DmaCmd_ResetTxChannel );
+ usc_RTCmd( info, RTCmd_PurgeTxFifo );
+
+- info->tx_enabled = 0;
+- info->tx_active = 0;
++ info->tx_enabled = false;
++ info->tx_active = false;
+
+ } /* end of usc_stop_transmitter() */
+
+@@ -6523,7 +6526,7 @@ static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info )
+ */
+ static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex )
+ {
+- int Done = 0;
++ bool Done = false;
+ DMABUFFERENTRY *pBufEntry;
+ unsigned int Index;
+
+@@ -6537,7 +6540,7 @@ static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int S
+
+ if ( Index == EndIndex ) {
+ /* This is the last buffer of the frame! */
+- Done = 1;
++ Done = true;
+ }
+
+ /* reset current buffer for reuse */
+@@ -6562,18 +6565,18 @@ static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int S
+ * receive DMA buffers. Only frames received without errors are returned.
+ *
+ * Arguments: info pointer to device extension
+- * Return Value: 1 if frame returned, otherwise 0
++ * Return Value: true if frame returned, otherwise false
+ */
+-static int mgsl_get_rx_frame(struct mgsl_struct *info)
++static bool mgsl_get_rx_frame(struct mgsl_struct *info)
+ {
+ unsigned int StartIndex, EndIndex; /* index of 1st and last buffers of Rx frame */
+ unsigned short status;
+ DMABUFFERENTRY *pBufEntry;
+ unsigned int framesize = 0;
+- int ReturnCode = 0;
++ bool ReturnCode = false;
+ unsigned long flags;
+ struct tty_struct *tty = info->tty;
+- int return_frame = 0;
++ bool return_frame = false;
+
+ /*
+ * current_rx_buffer points to the 1st buffer of the next available
+@@ -6632,7 +6635,7 @@ static int mgsl_get_rx_frame(struct mgsl_struct *info)
+ else {
+ info->icount.rxcrc++;
+ if ( info->params.crc_type & HDLC_CRC_RETURN_EX )
+- return_frame = 1;
++ return_frame = true;
+ }
+ framesize = 0;
+ #if SYNCLINK_GENERIC_HDLC
+@@ -6643,7 +6646,7 @@ static int mgsl_get_rx_frame(struct mgsl_struct *info)
+ }
+ #endif
+ } else
+- return_frame = 1;
++ return_frame = true;
+
+ if ( return_frame ) {
+ /* receive frame has no errors, get frame size.
+@@ -6722,7 +6725,7 @@ static int mgsl_get_rx_frame(struct mgsl_struct *info)
+ /* Free the buffers used by this frame. */
+ mgsl_free_rx_frame_buffers( info, StartIndex, EndIndex );
+
+- ReturnCode = 1;
++ ReturnCode = true;
+
+ Cleanup:
+
+@@ -6761,15 +6764,15 @@ Cleanup:
+ * last Rx DMA buffer and return that last portion of the frame.
+ *
+ * Arguments: info pointer to device extension
+- * Return Value: 1 if frame returned, otherwise 0
++ * Return Value: true if frame returned, otherwise false
+ */
+-static int mgsl_get_raw_rx_frame(struct mgsl_struct *info)
++static bool mgsl_get_raw_rx_frame(struct mgsl_struct *info)
+ {
+ unsigned int CurrentIndex, NextIndex;
+ unsigned short status;
+ DMABUFFERENTRY *pBufEntry;
+ unsigned int framesize = 0;
+- int ReturnCode = 0;
++ bool ReturnCode = false;
+ unsigned long flags;
+ struct tty_struct *tty = info->tty;
+
+@@ -6894,7 +6897,7 @@ static int mgsl_get_raw_rx_frame(struct mgsl_struct *info)
+ /* Free the buffers used by this frame. */
+ mgsl_free_rx_frame_buffers( info, CurrentIndex, CurrentIndex );
+
+- ReturnCode = 1;
++ ReturnCode = true;
+ }
+
+
+@@ -7003,15 +7006,15 @@ static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info,
+ * Performs a register test of the 16C32.
+ *
+ * Arguments: info pointer to device instance data
+- * Return Value: TRUE if test passed, otherwise FALSE
++ * Return Value: true if test passed, otherwise false
+ */
+-static BOOLEAN mgsl_register_test( struct mgsl_struct *info )
++static bool mgsl_register_test( struct mgsl_struct *info )
+ {
+ static unsigned short BitPatterns[] =
+ { 0x0000, 0xffff, 0xaaaa, 0x5555, 0x1234, 0x6969, 0x9696, 0x0f0f };
+ static unsigned int Patterncount = ARRAY_SIZE(BitPatterns);
+ unsigned int i;
+- BOOLEAN rc = TRUE;
++ bool rc = true;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->irq_spinlock,flags);
+@@ -7022,10 +7025,10 @@ static BOOLEAN mgsl_register_test( struct mgsl_struct *info )
+ if ( (usc_InReg( info, SICR ) != 0) ||
+ (usc_InReg( info, IVR ) != 0) ||
+ (usc_InDmaReg( info, DIVR ) != 0) ){
+- rc = FALSE;
++ rc = false;
+ }
+
+- if ( rc == TRUE ){
++ if ( rc ){
+ /* Write bit patterns to various registers but do it out of */
+ /* sync, then read back and verify values. */
+
+@@ -7043,7 +7046,7 @@ static BOOLEAN mgsl_register_test( struct mgsl_struct *info )
+ (usc_InReg( info, RCLR ) != BitPatterns[(i+3)%Patterncount]) ||
+ (usc_InReg( info, RSR ) != BitPatterns[(i+4)%Patterncount]) ||
+ (usc_InDmaReg( info, TBCR ) != BitPatterns[(i+5)%Patterncount]) ){
+- rc = FALSE;
++ rc = false;
+ break;
+ }
+ }
+@@ -7059,9 +7062,9 @@ static BOOLEAN mgsl_register_test( struct mgsl_struct *info )
+ /* mgsl_irq_test() Perform interrupt test of the 16C32.
+ *
+ * Arguments: info pointer to device instance data
+- * Return Value: TRUE if test passed, otherwise FALSE
++ * Return Value: true if test passed, otherwise false
+ */
+-static BOOLEAN mgsl_irq_test( struct mgsl_struct *info )
++static bool mgsl_irq_test( struct mgsl_struct *info )
+ {
+ unsigned long EndTime;
+ unsigned long flags;
+@@ -7071,10 +7074,10 @@ static BOOLEAN mgsl_irq_test( struct mgsl_struct *info )
+
+ /*
+ * Setup 16C32 to interrupt on TxC pin (14MHz clock) transition.
+- * The ISR sets irq_occurred to 1.
++ * The ISR sets irq_occurred to true.
+ */
+
+- info->irq_occurred = FALSE;
++ info->irq_occurred = false;
+
+ /* Enable INTEN gate for ISA adapter (Port 6, Bit12) */
+ /* Enable INTEN (Port 6, Bit12) */
+@@ -7100,10 +7103,7 @@ static BOOLEAN mgsl_irq_test( struct mgsl_struct *info )
+ usc_reset(info);
+ spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+- if ( !info->irq_occurred )
+- return FALSE;
+- else
+- return TRUE;
++ return info->irq_occurred;
+
+ } /* end of mgsl_irq_test() */
+
+@@ -7114,16 +7114,16 @@ static BOOLEAN mgsl_irq_test( struct mgsl_struct *info )
+ * using single buffer DMA mode.
+ *
+ * Arguments: info pointer to device instance data
+- * Return Value: TRUE if test passed, otherwise FALSE
++ * Return Value: true if test passed, otherwise false
+ */
+-static BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
++static bool mgsl_dma_test( struct mgsl_struct *info )
+ {
+ unsigned short FifoLevel;
+ unsigned long phys_addr;
+ unsigned int FrameSize;
+ unsigned int i;
+ char *TmpPtr;
+- BOOLEAN rc = TRUE;
++ bool rc = true;
+ unsigned short status=0;
+ unsigned long EndTime;
+ unsigned long flags;
+@@ -7236,7 +7236,7 @@ static BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
+
+ for(;;) {
+ if (time_after(jiffies, EndTime)) {
+- rc = FALSE;
++ rc = false;
+ break;
+ }
+
+@@ -7292,7 +7292,7 @@ static BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
+
+ for(;;) {
+ if (time_after(jiffies, EndTime)) {
+- rc = FALSE;
++ rc = false;
+ break;
+ }
+
+@@ -7312,7 +7312,7 @@ static BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
+ }
+
+
+- if ( rc == TRUE )
++ if ( rc )
+ {
+ /* Enable 16C32 transmitter. */
+
+@@ -7340,7 +7340,7 @@ static BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
+
+ while ( !(status & (BIT6+BIT5+BIT4+BIT2+BIT1)) ) {
+ if (time_after(jiffies, EndTime)) {
+- rc = FALSE;
++ rc = false;
+ break;
+ }
+
+@@ -7351,13 +7351,13 @@ static BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
+ }
+
+
+- if ( rc == TRUE ){
++ if ( rc ){
+ /* CHECK FOR TRANSMIT ERRORS */
+ if ( status & (BIT5 + BIT1) )
+- rc = FALSE;
++ rc = false;
+ }
+
+- if ( rc == TRUE ) {
++ if ( rc ) {
+ /* WAIT FOR RECEIVE COMPLETE */
+
+ /* Wait 100ms */
+@@ -7367,7 +7367,7 @@ static BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
+ status=info->rx_buffer_list[0].status;
+ while ( status == 0 ) {
+ if (time_after(jiffies, EndTime)) {
+- rc = FALSE;
++ rc = false;
+ break;
+ }
+ status=info->rx_buffer_list[0].status;
+@@ -7375,17 +7375,17 @@ static BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
+ }
+
+
+- if ( rc == TRUE ) {
++ if ( rc ) {
+ /* CHECK FOR RECEIVE ERRORS */
+ status = info->rx_buffer_list[0].status;
+
+ if ( status & (BIT8 + BIT3 + BIT1) ) {
+ /* receive error has occurred */
+- rc = FALSE;
++ rc = false;
+ } else {
+ if ( memcmp( info->tx_buffer_list[0].virt_addr ,
+ info->rx_buffer_list[0].virt_addr, FrameSize ) ){
+- rc = FALSE;
++ rc = false;
+ }
+ }
+ }
+@@ -7448,9 +7448,9 @@ static int mgsl_adapter_test( struct mgsl_struct *info )
+ * Test the shared memory on a PCI adapter.
+ *
+ * Arguments: info pointer to device instance data
+- * Return Value: TRUE if test passed, otherwise FALSE
++ * Return Value: true if test passed, otherwise false
+ */
+-static BOOLEAN mgsl_memory_test( struct mgsl_struct *info )
++static bool mgsl_memory_test( struct mgsl_struct *info )
+ {
+ static unsigned long BitPatterns[] =
+ { 0x0, 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
+@@ -7460,7 +7460,7 @@ static BOOLEAN mgsl_memory_test( struct mgsl_struct *info )
+ unsigned long * TestAddr;
+
+ if ( info->bus_type != MGSL_BUS_TYPE_PCI )
+- return TRUE;
++ return true;
+
+ TestAddr = (unsigned long *)info->memory_base;
+
+@@ -7469,7 +7469,7 @@ static BOOLEAN mgsl_memory_test( struct mgsl_struct *info )
+ for ( i = 0 ; i < Patterncount ; i++ ) {
+ *TestAddr = BitPatterns[i];
+ if ( *TestAddr != BitPatterns[i] )
+- return FALSE;
++ return false;
+ }
+
+ /* Test address lines with incrementing pattern over */
+@@ -7484,13 +7484,13 @@ static BOOLEAN mgsl_memory_test( struct mgsl_struct *info )
+
+ for ( i = 0 ; i < TestLimit ; i++ ) {
+ if ( *TestAddr != i * 4 )
+- return FALSE;
++ return false;
+ TestAddr++;
+ }
+
+ memset( info->memory_base, 0, SHARED_MEM_ADDRESS_SIZE );
+
+- return TRUE;
++ return true;
+
+ } /* End Of mgsl_memory_test() */
+
+@@ -7607,7 +7607,7 @@ static void mgsl_tx_timeout(unsigned long context)
+ info->icount.txtimeout++;
+ }
+ spin_lock_irqsave(&info->irq_spinlock,flags);
+- info->tx_active = 0;
++ info->tx_active = false;
+ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+ if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
+@@ -7635,7 +7635,7 @@ static int mgsl_loopmode_send_done( struct mgsl_struct * info )
+ spin_lock_irqsave(&info->irq_spinlock,flags);
+ if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) {
+ if (info->tx_active)
+- info->loopmode_send_done_requested = TRUE;
++ info->loopmode_send_done_requested = true;
+ else
+ usc_loopmode_send_done(info);
+ }
+@@ -7649,7 +7649,7 @@ static int mgsl_loopmode_send_done( struct mgsl_struct * info )
+ */
+ static void usc_loopmode_send_done( struct mgsl_struct * info )
+ {
+- info->loopmode_send_done_requested = FALSE;
++ info->loopmode_send_done_requested = false;
+ /* clear CMR:13 to 0 to start echoing RxData to TxData */
+ info->cmr_value &= ~BIT13;
+ usc_OutReg(info, CMR, info->cmr_value);
+@@ -7671,7 +7671,7 @@ static void usc_loopmode_cancel_transmit( struct mgsl_struct * info )
+ */
+ static void usc_loopmode_insert_request( struct mgsl_struct * info )
+ {
+- info->loopmode_insert_requested = TRUE;
++ info->loopmode_insert_requested = true;
+
+ /* enable RxAbort irq. On next RxAbort, clear CMR:13 to
+ * begin repeating TxData on RxData (complete insertion)
+diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
+index 1f954ac..2001b0e 100644
+--- a/drivers/char/synclink_gt.c
++++ b/drivers/char/synclink_gt.c
+@@ -117,7 +117,7 @@ static struct pci_driver pci_driver = {
+ .remove = __devexit_p(remove_one),
+ };
+
+-static int pci_registered;
++static bool pci_registered;
+
+ /*
+ * module configuration and status
+@@ -151,7 +151,7 @@ static void hangup(struct tty_struct *tty);
+ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios);
+
+ static int write(struct tty_struct *tty, const unsigned char *buf, int count);
+-static void put_char(struct tty_struct *tty, unsigned char ch);
++static int put_char(struct tty_struct *tty, unsigned char ch);
+ static void send_xchar(struct tty_struct *tty, char ch);
+ static void wait_until_sent(struct tty_struct *tty, int timeout);
+ static int write_room(struct tty_struct *tty);
+@@ -289,12 +289,12 @@ struct slgt_info {
+
+ struct work_struct task;
+ u32 pending_bh;
+- int bh_requested;
+- int bh_running;
++ bool bh_requested;
++ bool bh_running;
+
+ int isr_overflow;
+- int irq_requested; /* nonzero if IRQ requested */
+- int irq_occurred; /* for diagnostics use */
++ bool irq_requested; /* true if IRQ requested */
++ bool irq_occurred; /* for diagnostics use */
+
+ /* device configuration */
+
+@@ -304,7 +304,7 @@ struct slgt_info {
+
+ unsigned char __iomem * reg_addr; /* memory mapped registers address */
+ u32 phys_reg_addr;
+- int reg_addr_requested;
++ bool reg_addr_requested;
+
+ MGSL_PARAMS params; /* communications parameters */
+ u32 idle_mode;
+@@ -315,11 +315,11 @@ struct slgt_info {
+
+ /* device status */
+
+- int rx_enabled;
+- int rx_restart;
++ bool rx_enabled;
++ bool rx_restart;
+
+- int tx_enabled;
+- int tx_active;
++ bool tx_enabled;
++ bool tx_active;
+
+ unsigned char signals; /* serial signal states */
+ int init_error; /* initialization error */
+@@ -329,7 +329,7 @@ struct slgt_info {
+
+ char flag_buf[MAX_ASYNC_BUFFER_SIZE];
+ char char_buf[MAX_ASYNC_BUFFER_SIZE];
+- BOOLEAN drop_rts_on_tx_done;
++ bool drop_rts_on_tx_done;
+ struct _input_signal_events input_signal_events;
+
+ int dcd_chkcount; /* check counts to prevent */
+@@ -467,8 +467,8 @@ static void rx_start(struct slgt_info *info);
+ static void reset_rbufs(struct slgt_info *info);
+ static void free_rbufs(struct slgt_info *info, unsigned int first, unsigned int last);
+ static void rdma_reset(struct slgt_info *info);
+-static int rx_get_frame(struct slgt_info *info);
+-static int rx_get_buf(struct slgt_info *info);
++static bool rx_get_frame(struct slgt_info *info);
++static bool rx_get_buf(struct slgt_info *info);
+
+ static void tx_start(struct slgt_info *info);
+ static void tx_stop(struct slgt_info *info);
+@@ -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);
+@@ -772,8 +771,7 @@ static void close(struct tty_struct *tty, struct file *filp)
+
+ if (info->flags & ASYNC_INITIALIZED)
+ wait_until_sent(tty, info->timeout);
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ flush_buffer(tty);
+ tty_ldisc_flush(tty);
+
+ shutdown(info);
+@@ -914,20 +912,24 @@ cleanup:
+ return ret;
+ }
+
+-static void put_char(struct tty_struct *tty, unsigned char ch)
++static int put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
++ int ret;
+
+ if (sanity_check(info, tty->name, "put_char"))
+- return;
++ return 0;
+ DBGINFO(("%s put_char(%d)\n", info->device_name, ch));
+ if (!info->tx_buf)
+- return;
++ return 0;
+ spin_lock_irqsave(&info->lock,flags);
+- if (!info->tx_active && (info->tx_count < info->max_frame_size))
++ if (!info->tx_active && (info->tx_count < info->max_frame_size)) {
+ info->tx_buf[info->tx_count++] = ch;
++ ret = 1;
++ }
+ spin_unlock_irqrestore(&info->lock,flags);
++ return ret;
+ }
+
+ static void send_xchar(struct tty_struct *tty, char ch)
+@@ -968,6 +970,8 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
+ * Note: use tight timings here to satisfy the NIST-PCTS.
+ */
+
++ lock_kernel();
++
+ if (info->params.data_rate) {
+ char_time = info->timeout/(32 * 5);
+ if (!char_time)
+@@ -985,6 +989,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
+ break;
+ }
++ unlock_kernel();
+
+ exit:
+ DBGINFO(("%s wait_until_sent exit\n", info->device_name));
+@@ -1098,6 +1103,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
+ struct serial_icounter_struct __user *p_cuser; /* user space */
+ unsigned long flags;
+ void __user *argp = (void __user *)arg;
++ int ret;
+
+ if (sanity_check(info, tty->name, "ioctl"))
+ return -ENODEV;
+@@ -1109,37 +1115,54 @@ static int ioctl(struct tty_struct *tty, struct file *file,
+ return -EIO;
+ }
+
++ lock_kernel();
++
+ switch (cmd) {
+ case MGSL_IOCGPARAMS:
+- return get_params(info, argp);
++ ret = get_params(info, argp);
++ break;
+ case MGSL_IOCSPARAMS:
+- return set_params(info, argp);
++ ret = set_params(info, argp);
++ break;
+ case MGSL_IOCGTXIDLE:
+- return get_txidle(info, argp);
++ ret = get_txidle(info, argp);
++ break;
+ case MGSL_IOCSTXIDLE:
+- return set_txidle(info, (int)arg);
++ ret = set_txidle(info, (int)arg);
++ break;
+ case MGSL_IOCTXENABLE:
+- return tx_enable(info, (int)arg);
++ ret = tx_enable(info, (int)arg);
++ break;
+ case MGSL_IOCRXENABLE:
+- return rx_enable(info, (int)arg);
++ ret = rx_enable(info, (int)arg);
++ break;
+ case MGSL_IOCTXABORT:
+- return tx_abort(info);
++ ret = tx_abort(info);
++ break;
+ case MGSL_IOCGSTATS:
+- return get_stats(info, argp);
++ ret = get_stats(info, argp);
++ break;
+ case MGSL_IOCWAITEVENT:
+- return wait_mgsl_event(info, argp);
++ ret = wait_mgsl_event(info, argp);
++ break;
+ case TIOCMIWAIT:
+- return modem_input_wait(info,(int)arg);
++ ret = modem_input_wait(info,(int)arg);
++ break;
+ case MGSL_IOCGIF:
+- return get_interface(info, argp);
++ ret = get_interface(info, argp);
++ break;
+ case MGSL_IOCSIF:
+- return set_interface(info,(int)arg);
++ ret = set_interface(info,(int)arg);
++ break;
+ case MGSL_IOCSGPIO:
+- return set_gpio(info, argp);
++ ret = set_gpio(info, argp);
++ break;
+ case MGSL_IOCGGPIO:
+- return get_gpio(info, argp);
++ ret = get_gpio(info, argp);
++ break;
+ case MGSL_IOCWAITGPIO:
+- return wait_gpio(info, argp);
++ ret = wait_gpio(info, argp);
++ break;
+ case TIOCGICOUNT:
+ spin_lock_irqsave(&info->lock,flags);
+ cnow = info->icount;
+@@ -1156,12 +1179,14 @@ static int ioctl(struct tty_struct *tty, struct file *file,
+ put_user(cnow.parity, &p_cuser->parity) ||
+ put_user(cnow.brk, &p_cuser->brk) ||
+ put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
+- return -EFAULT;
+- return 0;
++ ret = -EFAULT;
++ ret = 0;
++ break;
+ default:
+- return -ENOIOCTLCMD;
++ ret = -ENOIOCTLCMD;
+ }
+- return 0;
++ unlock_kernel();
++ return ret;
+ }
+
+ /*
+@@ -1969,8 +1994,8 @@ static int bh_action(struct slgt_info *info)
+ rc = BH_STATUS;
+ } else {
+ /* Mark BH routine as complete */
+- info->bh_running = 0;
+- info->bh_requested = 0;
++ info->bh_running = false;
++ info->bh_requested = false;
+ rc = 0;
+ }
+
+@@ -1989,7 +2014,7 @@ static void bh_handler(struct work_struct *work)
+
+ if (!info)
+ return;
+- info->bh_running = 1;
++ info->bh_running = true;
+
+ while((action = bh_action(info))) {
+ switch (action) {
+@@ -2159,7 +2184,7 @@ static void isr_serial(struct slgt_info *info)
+
+ wr_reg16(info, SSR, status); /* clear pending */
+
+- info->irq_occurred = 1;
++ info->irq_occurred = true;
+
+ if (info->params.mode == MGSL_MODE_ASYNC) {
+ if (status & IRQ_TXIDLE) {
+@@ -2226,7 +2251,7 @@ static void isr_rdma(struct slgt_info *info)
+
+ if (status & (BIT5 + BIT4)) {
+ DBGISR(("%s isr_rdma rx_restart=1\n", info->device_name));
+- info->rx_restart = 1;
++ info->rx_restart = true;
+ }
+ info->pending_bh |= BH_RECEIVE;
+ }
+@@ -2277,14 +2302,14 @@ static void isr_txeom(struct slgt_info *info, unsigned short status)
+ info->icount.txok++;
+ }
+
+- info->tx_active = 0;
++ info->tx_active = false;
+ info->tx_count = 0;
+
+ del_timer(&info->tx_timer);
+
+ if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done) {
+ info->signals &= ~SerialSignal_RTS;
+- info->drop_rts_on_tx_done = 0;
++ info->drop_rts_on_tx_done = false;
+ set_signals(info);
+ }
+
+@@ -2326,23 +2351,19 @@ 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);
+
+ while((gsr = rd_reg32(info, GSR) & 0xffffff00)) {
+ DBGISR(("%s gsr=%08x\n", info->device_name, gsr));
+- info->irq_occurred = 1;
++ info->irq_occurred = true;
+ for(i=0; i < info->port_count ; i++) {
+ if (info->port_array[i] == NULL)
+ continue;
+@@ -2379,13 +2400,13 @@ static irqreturn_t slgt_interrupt(int irq, void *dev_id)
+ !port->bh_requested) {
+ DBGISR(("%s bh queued\n", port->device_name));
+ schedule_work(&port->task);
+- port->bh_requested = 1;
++ port->bh_requested = true;
+ }
+ }
+
+ 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;
+ }
+
+@@ -3115,7 +3136,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
+ {
+ DECLARE_WAITQUEUE(wait, current);
+ int retval;
+- int do_clocal = 0, extra_count = 0;
++ bool do_clocal = false;
++ bool extra_count = false;
+ unsigned long flags;
+
+ DBGINFO(("%s block_til_ready\n", tty->driver->name));
+@@ -3127,7 +3149,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
+ }
+
+ if (tty->termios->c_cflag & CLOCAL)
+- do_clocal = 1;
++ do_clocal = true;
+
+ /* Wait for carrier detect and the line to become
+ * free (i.e., not in use by the callout). While we are in
+@@ -3141,7 +3163,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
+
+ spin_lock_irqsave(&info->lock, flags);
+ if (!tty_hung_up_p(filp)) {
+- extra_count = 1;
++ extra_count = true;
+ info->count--;
+ }
+ spin_unlock_irqrestore(&info->lock, flags);
+@@ -3326,9 +3348,9 @@ static int claim_resources(struct slgt_info *info)
+ goto errout;
+ }
+ else
+- info->reg_addr_requested = 1;
++ info->reg_addr_requested = true;
+
+- info->reg_addr = ioremap(info->phys_reg_addr, SLGT_REG_SIZE);
++ info->reg_addr = ioremap_nocache(info->phys_reg_addr, SLGT_REG_SIZE);
+ if (!info->reg_addr) {
+ DBGERR(("%s cant map device registers, addr=%08X\n",
+ info->device_name, info->phys_reg_addr));
+@@ -3346,12 +3368,12 @@ static void release_resources(struct slgt_info *info)
+ {
+ if (info->irq_requested) {
+ free_irq(info->irq_level, info);
+- info->irq_requested = 0;
++ info->irq_requested = false;
+ }
+
+ if (info->reg_addr_requested) {
+ release_mem_region(info->phys_reg_addr, SLGT_REG_SIZE);
+- info->reg_addr_requested = 0;
++ info->reg_addr_requested = false;
+ }
+
+ if (info->reg_addr) {
+@@ -3516,7 +3538,7 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
+ port_array[0]->device_name,
+ port_array[0]->irq_level));
+ } else {
+- port_array[0]->irq_requested = 1;
++ port_array[0]->irq_requested = true;
+ adapter_test(port_array[0]);
+ for (i=1 ; i < port_count ; i++) {
+ port_array[i]->init_error = port_array[0]->init_error;
+@@ -3659,7 +3681,7 @@ static int __init slgt_init(void)
+ printk("%s pci_register_driver error=%d\n", driver_name, rc);
+ goto error;
+ }
+- pci_registered = 1;
++ pci_registered = true;
+
+ if (!slgt_device_list)
+ printk("%s no devices found\n",driver_name);
+@@ -3817,8 +3839,8 @@ static void rx_stop(struct slgt_info *info)
+
+ rdma_reset(info);
+
+- info->rx_enabled = 0;
+- info->rx_restart = 0;
++ info->rx_enabled = false;
++ info->rx_restart = false;
+ }
+
+ static void rx_start(struct slgt_info *info)
+@@ -3854,8 +3876,8 @@ static void rx_start(struct slgt_info *info)
+ /* enable receiver */
+ wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | BIT1));
+
+- info->rx_restart = 0;
+- info->rx_enabled = 1;
++ info->rx_restart = false;
++ info->rx_enabled = true;
+ }
+
+ static void tx_start(struct slgt_info *info)
+@@ -3863,11 +3885,11 @@ static void tx_start(struct slgt_info *info)
+ if (!info->tx_enabled) {
+ wr_reg16(info, TCR,
+ (unsigned short)((rd_reg16(info, TCR) | BIT1) & ~BIT2));
+- info->tx_enabled = TRUE;
++ info->tx_enabled = true;
+ }
+
+ if (info->tx_count) {
+- info->drop_rts_on_tx_done = 0;
++ info->drop_rts_on_tx_done = false;
+
+ if (info->params.mode != MGSL_MODE_ASYNC) {
+ if (info->params.flags & HDLC_FLAG_AUTO_RTS) {
+@@ -3875,7 +3897,7 @@ static void tx_start(struct slgt_info *info)
+ if (!(info->signals & SerialSignal_RTS)) {
+ info->signals |= SerialSignal_RTS;
+ set_signals(info);
+- info->drop_rts_on_tx_done = 1;
++ info->drop_rts_on_tx_done = true;
+ }
+ }
+
+@@ -3893,7 +3915,7 @@ static void tx_start(struct slgt_info *info)
+ wr_reg16(info, SSR, IRQ_TXIDLE);
+ }
+ tdma_start(info);
+- info->tx_active = 1;
++ info->tx_active = true;
+ }
+ }
+
+@@ -3954,8 +3976,8 @@ static void tx_stop(struct slgt_info *info)
+
+ reset_tbufs(info);
+
+- info->tx_enabled = 0;
+- info->tx_active = 0;
++ info->tx_enabled = false;
++ info->tx_active = false;
+ }
+
+ static void reset_port(struct slgt_info *info)
+@@ -4475,14 +4497,13 @@ static void reset_rbufs(struct slgt_info *info)
+ /*
+ * pass receive HDLC frame to upper layer
+ *
+- * return 1 if frame available, otherwise 0
++ * return true if frame available, otherwise false
+ */
+-static int rx_get_frame(struct slgt_info *info)
++static bool rx_get_frame(struct slgt_info *info)
+ {
+ unsigned int start, end;
+ unsigned short status;
+ unsigned int framesize = 0;
+- int rc = 0;
+ unsigned long flags;
+ struct tty_struct *tty = info->tty;
+ unsigned char addr_field = 0xff;
+@@ -4606,23 +4627,23 @@ check_again:
+ }
+ }
+ free_rbufs(info, start, end);
+- rc = 1;
++ return true;
+
+ cleanup:
+- return rc;
++ return false;
+ }
+
+ /*
+ * pass receive buffer (RAW synchronous mode) to tty layer
+- * return 1 if buffer available, otherwise 0
++ * return true if buffer available, otherwise false
+ */
+-static int rx_get_buf(struct slgt_info *info)
++static bool rx_get_buf(struct slgt_info *info)
+ {
+ unsigned int i = info->rbuf_current;
+ unsigned int count;
+
+ if (!desc_complete(info->rbufs[i]))
+- return 0;
++ return false;
+ count = desc_count(info->rbufs[i]);
+ switch(info->params.mode) {
+ case MGSL_MODE_MONOSYNC:
+@@ -4638,7 +4659,7 @@ static int rx_get_buf(struct slgt_info *info)
+ ldisc_receive_buf(info->tty, info->rbufs[i].buf,
+ info->flag_buf, count);
+ free_rbufs(info, i, i);
+- return 1;
++ return true;
+ }
+
+ static void reset_tbufs(struct slgt_info *info)
+@@ -4763,7 +4784,7 @@ static int irq_test(struct slgt_info *info)
+
+ /* assume failure */
+ info->init_error = DiagStatus_IrqFailure;
+- info->irq_occurred = FALSE;
++ info->irq_occurred = false;
+
+ spin_unlock_irqrestore(&info->lock, flags);
+
+@@ -4896,7 +4917,7 @@ static void tx_timeout(unsigned long context)
+ info->icount.txtimeout++;
+ }
+ spin_lock_irqsave(&info->lock,flags);
+- info->tx_active = 0;
++ info->tx_active = false;
+ info->tx_count = 0;
+ spin_unlock_irqrestore(&info->lock,flags);
+
+diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
+index f3e7807..bec5486 100644
+--- a/drivers/char/synclinkmp.c
++++ b/drivers/char/synclinkmp.c
+@@ -188,9 +188,9 @@ typedef struct _synclinkmp_info {
+
+ u32 pending_bh;
+
+- int bh_running; /* Protection from multiple */
++ bool bh_running; /* Protection from multiple */
+ int isr_overflow;
+- int bh_requested;
++ bool bh_requested;
+
+ int dcd_chkcount; /* check counts to prevent */
+ int cts_chkcount; /* too many IRQs if a signal */
+@@ -213,11 +213,11 @@ typedef struct _synclinkmp_info {
+ unsigned char *tmp_rx_buf;
+ unsigned int tmp_rx_buf_count;
+
+- int rx_enabled;
+- int rx_overflow;
++ bool rx_enabled;
++ bool rx_overflow;
+
+- int tx_enabled;
+- int tx_active;
++ bool tx_enabled;
++ bool tx_active;
+ u32 idle_mode;
+
+ unsigned char ie0_value;
+@@ -238,13 +238,13 @@ typedef struct _synclinkmp_info {
+
+ unsigned int irq_level; /* interrupt level */
+ unsigned long irq_flags;
+- int irq_requested; /* nonzero if IRQ requested */
++ bool irq_requested; /* true if IRQ requested */
+
+ MGSL_PARAMS params; /* communications parameters */
+
+ unsigned char serial_signals; /* current serial signal states */
+
+- int irq_occurred; /* for diagnostics use */
++ bool irq_occurred; /* for diagnostics use */
+ unsigned int init_error; /* Initialization startup error */
+
+ u32 last_mem_alloc;
+@@ -255,7 +255,7 @@ typedef struct _synclinkmp_info {
+ unsigned char* sca_base; /* HD64570 SCA Memory address */
+ u32 phys_sca_base;
+ u32 sca_offset;
+- int sca_base_requested;
++ bool sca_base_requested;
+
+ unsigned char* lcr_base; /* local config registers (PCI only) */
+ u32 phys_lcr_base;
+@@ -265,12 +265,12 @@ typedef struct _synclinkmp_info {
+ unsigned char* statctrl_base; /* status/control register memory */
+ u32 phys_statctrl_base;
+ u32 statctrl_offset;
+- int sca_statctrl_requested;
++ bool sca_statctrl_requested;
+
+ u32 misc_ctrl_value;
+ char flag_buf[MAX_ASYNC_BUFFER_SIZE];
+ char char_buf[MAX_ASYNC_BUFFER_SIZE];
+- BOOLEAN drop_rts_on_tx_done;
++ bool drop_rts_on_tx_done;
+
+ struct _input_signal_events input_signal_events;
+
+@@ -519,7 +519,7 @@ static void hangup(struct tty_struct *tty);
+ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios);
+
+ static int write(struct tty_struct *tty, const unsigned char *buf, int count);
+-static void put_char(struct tty_struct *tty, unsigned char ch);
++static int put_char(struct tty_struct *tty, unsigned char ch);
+ static void send_xchar(struct tty_struct *tty, char ch);
+ static void wait_until_sent(struct tty_struct *tty, int timeout);
+ static int write_room(struct tty_struct *tty);
+@@ -571,12 +571,12 @@ static void shutdown(SLMP_INFO *info);
+ static void program_hw(SLMP_INFO *info);
+ static void change_params(SLMP_INFO *info);
+
+-static int init_adapter(SLMP_INFO *info);
+-static int register_test(SLMP_INFO *info);
+-static int irq_test(SLMP_INFO *info);
+-static int loopback_test(SLMP_INFO *info);
++static bool init_adapter(SLMP_INFO *info);
++static bool register_test(SLMP_INFO *info);
++static bool irq_test(SLMP_INFO *info);
++static bool loopback_test(SLMP_INFO *info);
+ static int adapter_test(SLMP_INFO *info);
+-static int memory_test(SLMP_INFO *info);
++static bool memory_test(SLMP_INFO *info);
+
+ static void reset_adapter(SLMP_INFO *info);
+ static void reset_port(SLMP_INFO *info);
+@@ -587,7 +587,7 @@ static void rx_stop(SLMP_INFO *info);
+ static void rx_start(SLMP_INFO *info);
+ static void rx_reset_buffers(SLMP_INFO *info);
+ static void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int last);
+-static int rx_get_frame(SLMP_INFO *info);
++static bool rx_get_frame(SLMP_INFO *info);
+
+ static void tx_start(SLMP_INFO *info);
+ static void tx_stop(SLMP_INFO *info);
+@@ -862,8 +862,7 @@ static void close(struct tty_struct *tty, struct file *filp)
+ if (info->flags & ASYNC_INITIALIZED)
+ wait_until_sent(tty, info->timeout);
+
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ flush_buffer(tty);
+
+ tty_ldisc_flush(tty);
+
+@@ -1046,10 +1045,11 @@ cleanup:
+
+ /* Add a character to the transmit buffer.
+ */
+-static void put_char(struct tty_struct *tty, unsigned char ch)
++static int put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+ unsigned long flags;
++ int ret = 0;
+
+ if ( debug_level >= DEBUG_LEVEL_INFO ) {
+ printk( "%s(%d):%s put_char(%d)\n",
+@@ -1057,10 +1057,10 @@ static void put_char(struct tty_struct *tty, unsigned char ch)
+ }
+
+ if (sanity_check(info, tty->name, "put_char"))
+- return;
++ return 0;
+
+ if (!info->tx_buf)
+- return;
++ return 0;
+
+ spin_lock_irqsave(&info->lock,flags);
+
+@@ -1072,10 +1072,12 @@ static void put_char(struct tty_struct *tty, unsigned char ch)
+ if (info->tx_put >= info->max_frame_size)
+ info->tx_put -= info->max_frame_size;
+ info->tx_count++;
++ ret = 1;
+ }
+ }
+
+ spin_unlock_irqrestore(&info->lock,flags);
++ return ret;
+ }
+
+ /* Send a high-priority XON/XOFF character
+@@ -1119,6 +1121,8 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
+ if (sanity_check(info, tty->name, "wait_until_sent"))
+ return;
+
++ lock_kernel();
++
+ if (!(info->flags & ASYNC_INITIALIZED))
+ goto exit;
+
+@@ -1161,6 +1165,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
+ }
+
+ exit:
++ unlock_kernel();
+ if (debug_level >= DEBUG_LEVEL_INFO)
+ printk("%s(%d):%s wait_until_sent() exit\n",
+ __FILE__,__LINE__, info->device_name );
+@@ -1176,6 +1181,7 @@ static int write_room(struct tty_struct *tty)
+ if (sanity_check(info, tty->name, "write_room"))
+ return 0;
+
++ lock_kernel();
+ if (info->params.mode == MGSL_MODE_HDLC) {
+ ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE;
+ } else {
+@@ -1183,6 +1189,7 @@ static int write_room(struct tty_struct *tty)
+ if (ret < 0)
+ ret = 0;
+ }
++ unlock_kernel();
+
+ if (debug_level >= DEBUG_LEVEL_INFO)
+ printk("%s(%d):%s write_room()=%d\n",
+@@ -1303,7 +1310,7 @@ static void tx_release(struct tty_struct *tty)
+ *
+ * Return Value: 0 if success, otherwise error code
+ */
+-static int ioctl(struct tty_struct *tty, struct file *file,
++static int do_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+ SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+@@ -1393,6 +1400,16 @@ static int ioctl(struct tty_struct *tty, struct file *file,
+ return 0;
+ }
+
++static int ioctl(struct tty_struct *tty, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ int ret;
++ lock_kernel();
++ ret = do_ioctl(tty, file, cmd, arg);
++ unlock_kernel();
++ return ret;
++}
++
+ /*
+ * /proc fs routines....
+ */
+@@ -1473,7 +1490,7 @@ static inline int line_info(char *buf, SLMP_INFO *info)
+
+ /* Called to print information about devices
+ */
+-int read_proc(char *page, char **start, off_t off, int count,
++static int read_proc(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+ {
+ int len = 0, l;
+@@ -2024,7 +2041,7 @@ static void hdlcdev_exit(SLMP_INFO *info)
+ /* Return next bottom half action to perform.
+ * Return Value: BH action code or 0 if nothing to do.
+ */
+-int bh_action(SLMP_INFO *info)
++static int bh_action(SLMP_INFO *info)
+ {
+ unsigned long flags;
+ int rc = 0;
+@@ -2044,8 +2061,8 @@ int bh_action(SLMP_INFO *info)
+
+ if (!rc) {
+ /* Mark BH routine as complete */
+- info->bh_running = 0;
+- info->bh_requested = 0;
++ info->bh_running = false;
++ info->bh_requested = false;
+ }
+
+ spin_unlock_irqrestore(&info->lock,flags);
+@@ -2055,7 +2072,7 @@ int bh_action(SLMP_INFO *info)
+
+ /* Perform bottom half processing of work items queued by ISR.
+ */
+-void bh_handler(struct work_struct *work)
++static void bh_handler(struct work_struct *work)
+ {
+ SLMP_INFO *info = container_of(work, SLMP_INFO, task);
+ int action;
+@@ -2067,7 +2084,7 @@ void bh_handler(struct work_struct *work)
+ printk( "%s(%d):%s bh_handler() entry\n",
+ __FILE__,__LINE__,info->device_name);
+
+- info->bh_running = 1;
++ info->bh_running = true;
+
+ while((action = bh_action(info)) != 0) {
+
+@@ -2100,7 +2117,7 @@ void bh_handler(struct work_struct *work)
+ __FILE__,__LINE__,info->device_name);
+ }
+
+-void bh_receive(SLMP_INFO *info)
++static void bh_receive(SLMP_INFO *info)
+ {
+ if ( debug_level >= DEBUG_LEVEL_BH )
+ printk( "%s(%d):%s bh_receive()\n",
+@@ -2109,7 +2126,7 @@ void bh_receive(SLMP_INFO *info)
+ while( rx_get_frame(info) );
+ }
+
+-void bh_transmit(SLMP_INFO *info)
++static void bh_transmit(SLMP_INFO *info)
+ {
+ struct tty_struct *tty = info->tty;
+
+@@ -2121,7 +2138,7 @@ void bh_transmit(SLMP_INFO *info)
+ tty_wakeup(tty);
+ }
+
+-void bh_status(SLMP_INFO *info)
++static void bh_status(SLMP_INFO *info)
+ {
+ if ( debug_level >= DEBUG_LEVEL_BH )
+ printk( "%s(%d):%s bh_status() entry\n",
+@@ -2133,7 +2150,7 @@ void bh_status(SLMP_INFO *info)
+ info->cts_chkcount = 0;
+ }
+
+-void isr_timer(SLMP_INFO * info)
++static void isr_timer(SLMP_INFO * info)
+ {
+ unsigned char timer = (info->port_num & 1) ? TIMER2 : TIMER0;
+
+@@ -2152,14 +2169,14 @@ void isr_timer(SLMP_INFO * info)
+ */
+ write_reg(info, (unsigned char)(timer + TMCS), 0);
+
+- info->irq_occurred = TRUE;
++ info->irq_occurred = true;
+
+ if ( debug_level >= DEBUG_LEVEL_ISR )
+ printk("%s(%d):%s isr_timer()\n",
+ __FILE__,__LINE__,info->device_name);
+ }
+
+-void isr_rxint(SLMP_INFO * info)
++static void isr_rxint(SLMP_INFO * info)
+ {
+ struct tty_struct *tty = info->tty;
+ struct mgsl_icount *icount = &info->icount;
+@@ -2218,7 +2235,7 @@ void isr_rxint(SLMP_INFO * info)
+ /*
+ * handle async rx data interrupts
+ */
+-void isr_rxrdy(SLMP_INFO * info)
++static void isr_rxrdy(SLMP_INFO * info)
+ {
+ u16 status;
+ unsigned char DataByte;
+@@ -2232,7 +2249,7 @@ void isr_rxrdy(SLMP_INFO * info)
+ while((status = read_reg(info,CST0)) & BIT0)
+ {
+ int flag = 0;
+- int over = 0;
++ bool over = false;
+ DataByte = read_reg(info,TRB);
+
+ icount->rx++;
+@@ -2265,7 +2282,7 @@ void isr_rxrdy(SLMP_INFO * info)
+ * reported immediately, and doesn't
+ * affect the current character
+ */
+- over = 1;
++ over = true;
+ }
+ }
+ } /* end of if (error) */
+@@ -2318,14 +2335,14 @@ static void isr_txeom(SLMP_INFO * info, unsigned char status)
+ info->icount.txok++;
+ }
+
+- info->tx_active = 0;
++ info->tx_active = false;
+ info->tx_count = info->tx_put = info->tx_get = 0;
+
+ del_timer(&info->tx_timer);
+
+ if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done ) {
+ info->serial_signals &= ~SerialSignal_RTS;
+- info->drop_rts_on_tx_done = 0;
++ info->drop_rts_on_tx_done = false;
+ set_signals(info);
+ }
+
+@@ -2348,7 +2365,7 @@ static void isr_txeom(SLMP_INFO * info, unsigned char status)
+ /*
+ * handle tx status interrupts
+ */
+-void isr_txint(SLMP_INFO * info)
++static void isr_txint(SLMP_INFO * info)
+ {
+ unsigned char status = read_reg(info, SR1) & info->ie1_value & (UDRN + IDLE + CCTS);
+
+@@ -2376,7 +2393,7 @@ void isr_txint(SLMP_INFO * info)
+ /*
+ * handle async tx data interrupts
+ */
+-void isr_txrdy(SLMP_INFO * info)
++static void isr_txrdy(SLMP_INFO * info)
+ {
+ if ( debug_level >= DEBUG_LEVEL_ISR )
+ printk("%s(%d):%s isr_txrdy() tx_count=%d\n",
+@@ -2398,7 +2415,7 @@ void isr_txrdy(SLMP_INFO * info)
+ if ( info->tx_count )
+ tx_load_fifo( info );
+ else {
+- info->tx_active = 0;
++ info->tx_active = false;
+ info->ie0_value &= ~TXRDYE;
+ write_reg(info, IE0, info->ie0_value);
+ }
+@@ -2407,7 +2424,7 @@ void isr_txrdy(SLMP_INFO * info)
+ info->pending_bh |= BH_TRANSMIT;
+ }
+
+-void isr_rxdmaok(SLMP_INFO * info)
++static void isr_rxdmaok(SLMP_INFO * info)
+ {
+ /* BIT7 = EOT (end of transfer)
+ * BIT6 = EOM (end of message/frame)
+@@ -2424,7 +2441,7 @@ void isr_rxdmaok(SLMP_INFO * info)
+ info->pending_bh |= BH_RECEIVE;
+ }
+
+-void isr_rxdmaerror(SLMP_INFO * info)
++static void isr_rxdmaerror(SLMP_INFO * info)
+ {
+ /* BIT5 = BOF (buffer overflow)
+ * BIT4 = COF (counter overflow)
+@@ -2438,11 +2455,11 @@ void isr_rxdmaerror(SLMP_INFO * info)
+ printk("%s(%d):%s isr_rxdmaerror(), status=%02x\n",
+ __FILE__,__LINE__,info->device_name,status);
+
+- info->rx_overflow = TRUE;
++ info->rx_overflow = true;
+ info->pending_bh |= BH_RECEIVE;
+ }
+
+-void isr_txdmaok(SLMP_INFO * info)
++static void isr_txdmaok(SLMP_INFO * info)
+ {
+ unsigned char status_reg1 = read_reg(info, SR1);
+
+@@ -2460,7 +2477,7 @@ void isr_txdmaok(SLMP_INFO * info)
+ write_reg(info, IE0, info->ie0_value);
+ }
+
+-void isr_txdmaerror(SLMP_INFO * info)
++static void isr_txdmaerror(SLMP_INFO * info)
+ {
+ /* BIT5 = BOF (buffer overflow)
+ * BIT4 = COF (counter overflow)
+@@ -2477,7 +2494,7 @@ void isr_txdmaerror(SLMP_INFO * info)
+
+ /* handle input serial signal changes
+ */
+-void isr_io_pin( SLMP_INFO *info, u16 status )
++static void isr_io_pin( SLMP_INFO *info, u16 status )
+ {
+ struct mgsl_icount *icount;
+
+@@ -2586,9 +2603,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 +2614,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 +2628,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) */
+@@ -2695,15 +2708,15 @@ static irqreturn_t synclinkmp_interrupt(int irq, void *dev_id)
+ printk("%s(%d):%s queueing bh task.\n",
+ __FILE__,__LINE__,port->device_name);
+ schedule_work(&port->task);
+- port->bh_requested = 1;
++ port->bh_requested = true;
+ }
+ }
+
+ 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;
+ }
+
+@@ -3324,7 +3337,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
+ {
+ DECLARE_WAITQUEUE(wait, current);
+ int retval;
+- int do_clocal = 0, extra_count = 0;
++ bool do_clocal = false;
++ bool extra_count = false;
+ unsigned long flags;
+
+ if (debug_level >= DEBUG_LEVEL_INFO)
+@@ -3339,7 +3353,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
+ }
+
+ if (tty->termios->c_cflag & CLOCAL)
+- do_clocal = 1;
++ do_clocal = true;
+
+ /* Wait for carrier detect and the line to become
+ * free (i.e., not in use by the callout). While we are in
+@@ -3357,7 +3371,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
+
+ spin_lock_irqsave(&info->lock, flags);
+ if (!tty_hung_up_p(filp)) {
+- extra_count = 1;
++ extra_count = true;
+ info->count--;
+ }
+ spin_unlock_irqrestore(&info->lock, flags);
+@@ -3417,7 +3431,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
+ return retval;
+ }
+
+-int alloc_dma_bufs(SLMP_INFO *info)
++static int alloc_dma_bufs(SLMP_INFO *info)
+ {
+ unsigned short BuffersPerFrame;
+ unsigned short BufferCount;
+@@ -3491,7 +3505,7 @@ int alloc_dma_bufs(SLMP_INFO *info)
+
+ /* Allocate DMA buffers for the transmit and receive descriptor lists.
+ */
+-int alloc_buf_list(SLMP_INFO *info)
++static int alloc_buf_list(SLMP_INFO *info)
+ {
+ unsigned int i;
+
+@@ -3550,7 +3564,7 @@ int alloc_buf_list(SLMP_INFO *info)
+
+ /* Allocate the frame DMA buffers used by the specified buffer list.
+ */
+-int alloc_frame_bufs(SLMP_INFO *info, SCADESC *buf_list,SCADESC_EX *buf_list_ex,int count)
++static int alloc_frame_bufs(SLMP_INFO *info, SCADESC *buf_list,SCADESC_EX *buf_list_ex,int count)
+ {
+ int i;
+ unsigned long phys_addr;
+@@ -3567,7 +3581,7 @@ int alloc_frame_bufs(SLMP_INFO *info, SCADESC *buf_list,SCADESC_EX *buf_list_ex,
+ return 0;
+ }
+
+-void free_dma_bufs(SLMP_INFO *info)
++static void free_dma_bufs(SLMP_INFO *info)
+ {
+ info->buffer_list = NULL;
+ info->rx_buf_list = NULL;
+@@ -3577,7 +3591,7 @@ void free_dma_bufs(SLMP_INFO *info)
+ /* allocate buffer large enough to hold max_frame_size.
+ * This buffer is used to pass an assembled frame to the line discipline.
+ */
+-int alloc_tmp_rx_buf(SLMP_INFO *info)
++static int alloc_tmp_rx_buf(SLMP_INFO *info)
+ {
+ info->tmp_rx_buf = kmalloc(info->max_frame_size, GFP_KERNEL);
+ if (info->tmp_rx_buf == NULL)
+@@ -3585,13 +3599,13 @@ int alloc_tmp_rx_buf(SLMP_INFO *info)
+ return 0;
+ }
+
+-void free_tmp_rx_buf(SLMP_INFO *info)
++static void free_tmp_rx_buf(SLMP_INFO *info)
+ {
+ kfree(info->tmp_rx_buf);
+ info->tmp_rx_buf = NULL;
+ }
+
+-int claim_resources(SLMP_INFO *info)
++static int claim_resources(SLMP_INFO *info)
+ {
+ if (request_mem_region(info->phys_memory_base,SCA_MEM_SIZE,"synclinkmp") == NULL) {
+ printk( "%s(%d):%s mem addr conflict, Addr=%08X\n",
+@@ -3600,7 +3614,7 @@ int claim_resources(SLMP_INFO *info)
+ goto errout;
+ }
+ else
+- info->shared_mem_requested = 1;
++ info->shared_mem_requested = true;
+
+ if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclinkmp") == NULL) {
+ printk( "%s(%d):%s lcr mem addr conflict, Addr=%08X\n",
+@@ -3609,7 +3623,7 @@ int claim_resources(SLMP_INFO *info)
+ goto errout;
+ }
+ else
+- info->lcr_mem_requested = 1;
++ info->lcr_mem_requested = true;
+
+ if (request_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE,"synclinkmp") == NULL) {
+ printk( "%s(%d):%s sca mem addr conflict, Addr=%08X\n",
+@@ -3618,7 +3632,7 @@ int claim_resources(SLMP_INFO *info)
+ goto errout;
+ }
+ else
+- info->sca_base_requested = 1;
++ info->sca_base_requested = true;
+
+ if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE,"synclinkmp") == NULL) {
+ printk( "%s(%d):%s stat/ctrl mem addr conflict, Addr=%08X\n",
+@@ -3627,9 +3641,10 @@ int claim_resources(SLMP_INFO *info)
+ goto errout;
+ }
+ else
+- info->sca_statctrl_requested = 1;
++ info->sca_statctrl_requested = true;
+
+- info->memory_base = ioremap(info->phys_memory_base,SCA_MEM_SIZE);
++ info->memory_base = ioremap_nocache(info->phys_memory_base,
++ SCA_MEM_SIZE);
+ if (!info->memory_base) {
+ printk( "%s(%d):%s Cant map shared memory, MemAddr=%08X\n",
+ __FILE__,__LINE__,info->device_name, info->phys_memory_base );
+@@ -3637,7 +3652,7 @@ int claim_resources(SLMP_INFO *info)
+ goto errout;
+ }
+
+- info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE);
++ info->lcr_base = ioremap_nocache(info->phys_lcr_base, PAGE_SIZE);
+ if (!info->lcr_base) {
+ printk( "%s(%d):%s Cant map LCR memory, MemAddr=%08X\n",
+ __FILE__,__LINE__,info->device_name, info->phys_lcr_base );
+@@ -3646,7 +3661,7 @@ int claim_resources(SLMP_INFO *info)
+ }
+ info->lcr_base += info->lcr_offset;
+
+- info->sca_base = ioremap(info->phys_sca_base,PAGE_SIZE);
++ info->sca_base = ioremap_nocache(info->phys_sca_base, PAGE_SIZE);
+ if (!info->sca_base) {
+ printk( "%s(%d):%s Cant map SCA memory, MemAddr=%08X\n",
+ __FILE__,__LINE__,info->device_name, info->phys_sca_base );
+@@ -3655,7 +3670,8 @@ int claim_resources(SLMP_INFO *info)
+ }
+ info->sca_base += info->sca_offset;
+
+- info->statctrl_base = ioremap(info->phys_statctrl_base,PAGE_SIZE);
++ info->statctrl_base = ioremap_nocache(info->phys_statctrl_base,
++ PAGE_SIZE);
+ if (!info->statctrl_base) {
+ printk( "%s(%d):%s Cant map SCA Status/Control memory, MemAddr=%08X\n",
+ __FILE__,__LINE__,info->device_name, info->phys_statctrl_base );
+@@ -3678,7 +3694,7 @@ errout:
+ return -ENODEV;
+ }
+
+-void release_resources(SLMP_INFO *info)
++static void release_resources(SLMP_INFO *info)
+ {
+ if ( debug_level >= DEBUG_LEVEL_INFO )
+ printk( "%s(%d):%s release_resources() entry\n",
+@@ -3686,24 +3702,24 @@ void release_resources(SLMP_INFO *info)
+
+ if ( info->irq_requested ) {
+ free_irq(info->irq_level, info);
+- info->irq_requested = 0;
++ info->irq_requested = false;
+ }
+
+ if ( info->shared_mem_requested ) {
+ release_mem_region(info->phys_memory_base,SCA_MEM_SIZE);
+- info->shared_mem_requested = 0;
++ info->shared_mem_requested = false;
+ }
+ if ( info->lcr_mem_requested ) {
+ release_mem_region(info->phys_lcr_base + info->lcr_offset,128);
+- info->lcr_mem_requested = 0;
++ info->lcr_mem_requested = false;
+ }
+ if ( info->sca_base_requested ) {
+ release_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE);
+- info->sca_base_requested = 0;
++ info->sca_base_requested = false;
+ }
+ if ( info->sca_statctrl_requested ) {
+ release_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE);
+- info->sca_statctrl_requested = 0;
++ info->sca_statctrl_requested = false;
+ }
+
+ if (info->memory_base){
+@@ -3734,7 +3750,7 @@ void release_resources(SLMP_INFO *info)
+ /* Add the specified device instance data structure to the
+ * global linked list of devices and increment the device count.
+ */
+-void add_device(SLMP_INFO *info)
++static void add_device(SLMP_INFO *info)
+ {
+ info->next_device = NULL;
+ info->line = synclinkmp_device_count;
+@@ -3857,7 +3873,7 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
+ return info;
+ }
+
+-void device_init(int adapter_num, struct pci_dev *pdev)
++static void device_init(int adapter_num, struct pci_dev *pdev)
+ {
+ SLMP_INFO *port_array[SCA_MAX_PORTS];
+ int port;
+@@ -3906,7 +3922,7 @@ void device_init(int adapter_num, struct pci_dev *pdev)
+ port_array[0]->irq_level );
+ }
+ else {
+- port_array[0]->irq_requested = 1;
++ port_array[0]->irq_requested = true;
+ adapter_test(port_array[0]);
+ }
+ }
+@@ -4051,7 +4067,7 @@ module_exit(synclinkmp_exit);
+ * The TxCLK and RxCLK signals are generated from the BRG and
+ * the TxD is looped back to the RxD internally.
+ */
+-void enable_loopback(SLMP_INFO *info, int enable)
++static void enable_loopback(SLMP_INFO *info, int enable)
+ {
+ if (enable) {
+ /* MD2 (Mode Register 2)
+@@ -4098,7 +4114,7 @@ void enable_loopback(SLMP_INFO *info, int enable)
+ * data_rate data rate of clock in bits per second
+ * A data rate of 0 disables the AUX clock.
+ */
+-void set_rate( SLMP_INFO *info, u32 data_rate )
++static void set_rate( SLMP_INFO *info, u32 data_rate )
+ {
+ u32 TMCValue;
+ unsigned char BRValue;
+@@ -4144,7 +4160,7 @@ void set_rate( SLMP_INFO *info, u32 data_rate )
+
+ /* Disable receiver
+ */
+-void rx_stop(SLMP_INFO *info)
++static void rx_stop(SLMP_INFO *info)
+ {
+ if (debug_level >= DEBUG_LEVEL_ISR)
+ printk("%s(%d):%s rx_stop()\n",
+@@ -4159,13 +4175,13 @@ void rx_stop(SLMP_INFO *info)
+ write_reg(info, RXDMA + DCMD, SWABORT); /* reset/init Rx DMA */
+ write_reg(info, RXDMA + DIR, 0); /* disable Rx DMA interrupts */
+
+- info->rx_enabled = 0;
+- info->rx_overflow = 0;
++ info->rx_enabled = false;
++ info->rx_overflow = false;
+ }
+
+ /* enable the receiver
+ */
+-void rx_start(SLMP_INFO *info)
++static void rx_start(SLMP_INFO *info)
+ {
+ int i;
+
+@@ -4215,14 +4231,14 @@ void rx_start(SLMP_INFO *info)
+
+ write_reg(info, CMD, RXENABLE);
+
+- info->rx_overflow = FALSE;
+- info->rx_enabled = 1;
++ info->rx_overflow = false;
++ info->rx_enabled = true;
+ }
+
+ /* Enable the transmitter and send a transmit frame if
+ * one is loaded in the DMA buffers.
+ */
+-void tx_start(SLMP_INFO *info)
++static void tx_start(SLMP_INFO *info)
+ {
+ if (debug_level >= DEBUG_LEVEL_ISR)
+ printk("%s(%d):%s tx_start() tx_count=%d\n",
+@@ -4231,7 +4247,7 @@ void tx_start(SLMP_INFO *info)
+ if (!info->tx_enabled ) {
+ write_reg(info, CMD, TXRESET);
+ write_reg(info, CMD, TXENABLE);
+- info->tx_enabled = TRUE;
++ info->tx_enabled = true;
+ }
+
+ if ( info->tx_count ) {
+@@ -4240,7 +4256,7 @@ void tx_start(SLMP_INFO *info)
+ /* RTS and set a flag indicating that the driver should */
+ /* negate RTS when the transmission completes. */
+
+- info->drop_rts_on_tx_done = 0;
++ info->drop_rts_on_tx_done = false;
+
+ if (info->params.mode != MGSL_MODE_ASYNC) {
+
+@@ -4249,7 +4265,7 @@ void tx_start(SLMP_INFO *info)
+ if ( !(info->serial_signals & SerialSignal_RTS) ) {
+ info->serial_signals |= SerialSignal_RTS;
+ set_signals( info );
+- info->drop_rts_on_tx_done = 1;
++ info->drop_rts_on_tx_done = true;
+ }
+ }
+
+@@ -4286,13 +4302,13 @@ void tx_start(SLMP_INFO *info)
+ write_reg(info, IE0, info->ie0_value);
+ }
+
+- info->tx_active = 1;
++ info->tx_active = true;
+ }
+ }
+
+ /* stop the transmitter and DMA
+ */
+-void tx_stop( SLMP_INFO *info )
++static void tx_stop( SLMP_INFO *info )
+ {
+ if (debug_level >= DEBUG_LEVEL_ISR)
+ printk("%s(%d):%s tx_stop()\n",
+@@ -4312,14 +4328,14 @@ void tx_stop( SLMP_INFO *info )
+ info->ie0_value &= ~TXRDYE;
+ write_reg(info, IE0, info->ie0_value); /* disable tx data interrupts */
+
+- info->tx_enabled = 0;
+- info->tx_active = 0;
++ info->tx_enabled = false;
++ info->tx_active = false;
+ }
+
+ /* Fill the transmit FIFO until the FIFO is full or
+ * there is no more data to load.
+ */
+-void tx_load_fifo(SLMP_INFO *info)
++static void tx_load_fifo(SLMP_INFO *info)
+ {
+ u8 TwoBytes[2];
+
+@@ -4368,7 +4384,7 @@ void tx_load_fifo(SLMP_INFO *info)
+
+ /* Reset a port to a known state
+ */
+-void reset_port(SLMP_INFO *info)
++static void reset_port(SLMP_INFO *info)
+ {
+ if (info->sca_base) {
+
+@@ -4392,7 +4408,7 @@ void reset_port(SLMP_INFO *info)
+
+ /* Reset all the ports to a known state.
+ */
+-void reset_adapter(SLMP_INFO *info)
++static void reset_adapter(SLMP_INFO *info)
+ {
+ int i;
+
+@@ -4404,7 +4420,7 @@ void reset_adapter(SLMP_INFO *info)
+
+ /* Program port for asynchronous communications.
+ */
+-void async_mode(SLMP_INFO *info)
++static void async_mode(SLMP_INFO *info)
+ {
+
+ unsigned char RegValue;
+@@ -4543,7 +4559,7 @@ void async_mode(SLMP_INFO *info)
+
+ /* Program the SCA for HDLC communications.
+ */
+-void hdlc_mode(SLMP_INFO *info)
++static void hdlc_mode(SLMP_INFO *info)
+ {
+ unsigned char RegValue;
+ u32 DpllDivisor;
+@@ -4745,7 +4761,7 @@ void hdlc_mode(SLMP_INFO *info)
+
+ /* Set the transmit HDLC idle mode
+ */
+-void tx_set_idle(SLMP_INFO *info)
++static void tx_set_idle(SLMP_INFO *info)
+ {
+ unsigned char RegValue = 0xff;
+
+@@ -4765,7 +4781,7 @@ void tx_set_idle(SLMP_INFO *info)
+
+ /* Query the adapter for the state of the V24 status (input) signals.
+ */
+-void get_signals(SLMP_INFO *info)
++static void get_signals(SLMP_INFO *info)
+ {
+ u16 status = read_reg(info, SR3);
+ u16 gpstatus = read_status_reg(info);
+@@ -4794,7 +4810,7 @@ void get_signals(SLMP_INFO *info)
+ /* Set the state of DTR and RTS based on contents of
+ * serial_signals member of device context.
+ */
+-void set_signals(SLMP_INFO *info)
++static void set_signals(SLMP_INFO *info)
+ {
+ unsigned char RegValue;
+ u16 EnableBit;
+@@ -4823,7 +4839,7 @@ void set_signals(SLMP_INFO *info)
+ * and set the current buffer to the first buffer. This effectively
+ * makes all buffers free and discards any data in buffers.
+ */
+-void rx_reset_buffers(SLMP_INFO *info)
++static void rx_reset_buffers(SLMP_INFO *info)
+ {
+ rx_free_frame_buffers(info, 0, info->rx_buf_count - 1);
+ }
+@@ -4834,16 +4850,16 @@ void rx_reset_buffers(SLMP_INFO *info)
+ * first index of 1st receive buffer of frame
+ * last index of last receive buffer of frame
+ */
+-void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int last)
++static void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int last)
+ {
+- int done = 0;
++ bool done = false;
+
+ while(!done) {
+ /* reset current buffer for reuse */
+ info->rx_buf_list[first].status = 0xff;
+
+ if (first == last) {
+- done = 1;
++ done = true;
+ /* set new last rx descriptor address */
+ write_reg16(info, RXDMA + EDA, info->rx_buf_list_ex[first].phys_entry);
+ }
+@@ -4860,14 +4876,14 @@ void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int las
+ /* Return a received frame from the receive DMA buffers.
+ * Only frames received without errors are returned.
+ *
+- * Return Value: 1 if frame returned, otherwise 0
++ * Return Value: true if frame returned, otherwise false
+ */
+-int rx_get_frame(SLMP_INFO *info)
++static bool rx_get_frame(SLMP_INFO *info)
+ {
+ unsigned int StartIndex, EndIndex; /* index of 1st and last buffers of Rx frame */
+ unsigned short status;
+ unsigned int framesize = 0;
+- int ReturnCode = 0;
++ bool ReturnCode = false;
+ unsigned long flags;
+ struct tty_struct *tty = info->tty;
+ unsigned char addr_field = 0xff;
+@@ -5018,7 +5034,7 @@ CheckAgain:
+ /* Free the buffers used by this frame. */
+ rx_free_frame_buffers( info, StartIndex, EndIndex );
+
+- ReturnCode = 1;
++ ReturnCode = true;
+
+ Cleanup:
+ if ( info->rx_enabled && info->rx_overflow ) {
+@@ -5037,7 +5053,7 @@ Cleanup:
+
+ /* load the transmit DMA buffer with data
+ */
+-void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count)
++static void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count)
+ {
+ unsigned short copy_count;
+ unsigned int i = 0;
+@@ -5077,12 +5093,12 @@ void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count)
+ info->last_tx_buf = ++i;
+ }
+
+-int register_test(SLMP_INFO *info)
++static bool register_test(SLMP_INFO *info)
+ {
+ static unsigned char testval[] = {0x00, 0xff, 0xaa, 0x55, 0x69, 0x96};
+ static unsigned int count = ARRAY_SIZE(testval);
+ unsigned int i;
+- int rc = TRUE;
++ bool rc = true;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock,flags);
+@@ -5105,7 +5121,7 @@ int register_test(SLMP_INFO *info)
+ (read_reg(info, SA0) != testval[(i+2)%count]) ||
+ (read_reg(info, SA1) != testval[(i+3)%count]) )
+ {
+- rc = FALSE;
++ rc = false;
+ break;
+ }
+ }
+@@ -5116,7 +5132,7 @@ int register_test(SLMP_INFO *info)
+ return rc;
+ }
+
+-int irq_test(SLMP_INFO *info)
++static bool irq_test(SLMP_INFO *info)
+ {
+ unsigned long timeout;
+ unsigned long flags;
+@@ -5128,7 +5144,7 @@ int irq_test(SLMP_INFO *info)
+
+ /* assume failure */
+ info->init_error = DiagStatus_IrqFailure;
+- info->irq_occurred = FALSE;
++ info->irq_occurred = false;
+
+ /* setup timer0 on SCA0 to interrupt */
+
+@@ -5167,7 +5183,7 @@ int irq_test(SLMP_INFO *info)
+
+ /* initialize individual SCA device (2 ports)
+ */
+-static int sca_init(SLMP_INFO *info)
++static bool sca_init(SLMP_INFO *info)
+ {
+ /* set wait controller to single mem partition (low), no wait states */
+ write_reg(info, PABR0, 0); /* wait controller addr boundary 0 */
+@@ -5203,12 +5219,12 @@ static int sca_init(SLMP_INFO *info)
+ */
+ write_reg(info, ITCR, 0);
+
+- return TRUE;
++ return true;
+ }
+
+ /* initialize adapter hardware
+ */
+-int init_adapter(SLMP_INFO *info)
++static bool init_adapter(SLMP_INFO *info)
+ {
+ int i;
+
+@@ -5261,20 +5277,20 @@ int init_adapter(SLMP_INFO *info)
+ sca_init(info->port_array[0]);
+ sca_init(info->port_array[2]);
+
+- return TRUE;
++ return true;
+ }
+
+ /* Loopback an HDLC frame to test the hardware
+ * interrupt and DMA functions.
+ */
+-int loopback_test(SLMP_INFO *info)
++static bool loopback_test(SLMP_INFO *info)
+ {
+ #define TESTFRAMESIZE 20
+
+ unsigned long timeout;
+ u16 count = TESTFRAMESIZE;
+ unsigned char buf[TESTFRAMESIZE];
+- int rc = FALSE;
++ bool rc = false;
+ unsigned long flags;
+
+ struct tty_struct *oldtty = info->tty;
+@@ -5308,16 +5324,16 @@ int loopback_test(SLMP_INFO *info)
+ msleep_interruptible(10);
+
+ if (rx_get_frame(info)) {
+- rc = TRUE;
++ rc = true;
+ break;
+ }
+ }
+
+ /* verify received frame length and contents */
+- if (rc == TRUE &&
+- ( info->tmp_rx_buf_count != count ||
+- memcmp(buf, info->tmp_rx_buf,count))) {
+- rc = FALSE;
++ if (rc &&
++ ( info->tmp_rx_buf_count != count ||
++ memcmp(buf, info->tmp_rx_buf,count))) {
++ rc = false;
+ }
+
+ spin_lock_irqsave(&info->lock,flags);
+@@ -5332,7 +5348,7 @@ int loopback_test(SLMP_INFO *info)
+
+ /* Perform diagnostics on hardware
+ */
+-int adapter_test( SLMP_INFO *info )
++static int adapter_test( SLMP_INFO *info )
+ {
+ unsigned long flags;
+ if ( debug_level >= DEBUG_LEVEL_INFO )
+@@ -5394,7 +5410,7 @@ int adapter_test( SLMP_INFO *info )
+
+ /* Test the shared memory on a PCI adapter.
+ */
+-int memory_test(SLMP_INFO *info)
++static bool memory_test(SLMP_INFO *info)
+ {
+ static unsigned long testval[] = { 0x0, 0x55555555, 0xaaaaaaaa,
+ 0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
+@@ -5408,7 +5424,7 @@ int memory_test(SLMP_INFO *info)
+ for ( i = 0 ; i < count ; i++ ) {
+ *addr = testval[i];
+ if ( *addr != testval[i] )
+- return FALSE;
++ return false;
+ }
+
+ /* Test address lines with incrementing pattern over */
+@@ -5423,12 +5439,12 @@ int memory_test(SLMP_INFO *info)
+
+ for ( i = 0 ; i < limit ; i++ ) {
+ if ( *addr != i * 4 )
+- return FALSE;
++ return false;
+ addr++;
+ }
+
+ memset( info->memory_base, 0, SCA_MEM_SIZE );
+- return TRUE;
++ return true;
+ }
+
+ /* Load data into PCI adapter shared memory.
+@@ -5446,7 +5462,7 @@ int memory_test(SLMP_INFO *info)
+ * the write transation. This allows any pending DMA request to gain control
+ * of the local bus in a timely fasion.
+ */
+-void load_pci_memory(SLMP_INFO *info, char* dest, const char* src, unsigned short count)
++static void load_pci_memory(SLMP_INFO *info, char* dest, const char* src, unsigned short count)
+ {
+ /* A load interval of 16 allows for 4 32-bit writes at */
+ /* 136ns each for a maximum latency of 542ns on the local bus.*/
+@@ -5465,7 +5481,7 @@ void load_pci_memory(SLMP_INFO *info, char* dest, const char* src, unsigned shor
+ memcpy(dest, src, count % sca_pci_load_interval);
+ }
+
+-void trace_block(SLMP_INFO *info,const char* data, int count, int xmit)
++static void trace_block(SLMP_INFO *info,const char* data, int count, int xmit)
+ {
+ int i;
+ int linecount;
+@@ -5500,7 +5516,7 @@ void trace_block(SLMP_INFO *info,const char* data, int count, int xmit)
+ /* called when HDLC frame times out
+ * update stats and do tx completion processing
+ */
+-void tx_timeout(unsigned long context)
++static void tx_timeout(unsigned long context)
+ {
+ SLMP_INFO *info = (SLMP_INFO*)context;
+ unsigned long flags;
+@@ -5512,7 +5528,7 @@ void tx_timeout(unsigned long context)
+ info->icount.txtimeout++;
+ }
+ spin_lock_irqsave(&info->lock,flags);
+- info->tx_active = 0;
++ info->tx_active = false;
+ info->tx_count = info->tx_put = info->tx_get = 0;
+
+ spin_unlock_irqrestore(&info->lock,flags);
+@@ -5527,7 +5543,7 @@ void tx_timeout(unsigned long context)
+
+ /* called to periodically check the DSR/RI modem signal input status
+ */
+-void status_timeout(unsigned long context)
++static void status_timeout(unsigned long context)
+ {
+ u16 status = 0;
+ SLMP_INFO *info = (SLMP_INFO*)context;
+@@ -5578,36 +5594,36 @@ void status_timeout(unsigned long context)
+ }
+
+
+-unsigned char read_reg(SLMP_INFO * info, unsigned char Addr)
++static unsigned char read_reg(SLMP_INFO * info, unsigned char Addr)
+ {
+ CALC_REGADDR();
+ return *RegAddr;
+ }
+-void write_reg(SLMP_INFO * info, unsigned char Addr, unsigned char Value)
++static void write_reg(SLMP_INFO * info, unsigned char Addr, unsigned char Value)
+ {
+ CALC_REGADDR();
+ *RegAddr = Value;
+ }
+
+-u16 read_reg16(SLMP_INFO * info, unsigned char Addr)
++static u16 read_reg16(SLMP_INFO * info, unsigned char Addr)
+ {
+ CALC_REGADDR();
+ return *((u16 *)RegAddr);
+ }
+
+-void write_reg16(SLMP_INFO * info, unsigned char Addr, u16 Value)
++static void write_reg16(SLMP_INFO * info, unsigned char Addr, u16 Value)
+ {
+ CALC_REGADDR();
+ *((u16 *)RegAddr) = Value;
+ }
+
+-unsigned char read_status_reg(SLMP_INFO * info)
++static unsigned char read_status_reg(SLMP_INFO * info)
+ {
+ unsigned char *RegAddr = (unsigned char *)info->statctrl_base;
+ return *RegAddr;
+ }
+
+-void write_control_reg(SLMP_INFO * info)
++static void write_control_reg(SLMP_INFO * info)
+ {
+ unsigned char *RegAddr = (unsigned char *)info->statctrl_base;
+ *RegAddr = info->port_array[0]->ctrlreg_value;
+diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
+index de60e1e..9e9bad8 100644
+--- a/drivers/char/sysrq.c
++++ b/drivers/char/sysrq.c
+@@ -196,6 +196,48 @@ static struct sysrq_key_op sysrq_showlocks_op = {
+ #define sysrq_showlocks_op (*(struct sysrq_key_op *)0)
+ #endif
+
++#ifdef CONFIG_SMP
++static DEFINE_SPINLOCK(show_lock);
++
++static void showacpu(void *dummy)
++{
++ unsigned long flags;
++
++ /* Idle CPUs have no interesting backtrace. */
++ if (idle_cpu(smp_processor_id()))
++ return;
++
++ spin_lock_irqsave(&show_lock, flags);
++ printk(KERN_INFO "CPU%d:\n", smp_processor_id());
++ show_stack(NULL, NULL);
++ spin_unlock_irqrestore(&show_lock, flags);
++}
++
++static void sysrq_showregs_othercpus(struct work_struct *dummy)
++{
++ smp_call_function(showacpu, NULL, 0, 0);
++}
++
++static DECLARE_WORK(sysrq_showallcpus, sysrq_showregs_othercpus);
++
++static void sysrq_handle_showallcpus(int key, struct tty_struct *tty)
++{
++ struct pt_regs *regs = get_irq_regs();
++ if (regs) {
++ printk(KERN_INFO "CPU%d:\n", smp_processor_id());
++ show_regs(regs);
++ }
++ schedule_work(&sysrq_showallcpus);
++}
++
++static struct sysrq_key_op sysrq_showallcpus_op = {
++ .handler = sysrq_handle_showallcpus,
++ .help_msg = "aLlcpus",
++ .action_msg = "Show backtrace of all active CPUs",
++ .enable_mask = SYSRQ_ENABLE_DUMP,
++};
++#endif
++
+ static void sysrq_handle_showregs(int key, struct tty_struct *tty)
+ {
+ struct pt_regs *regs = get_irq_regs();
+@@ -271,8 +313,7 @@ static struct sysrq_key_op sysrq_term_op = {
+
+ static void moom_callback(struct work_struct *ignored)
+ {
+- out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL],
+- GFP_KERNEL, 0);
++ out_of_memory(node_zonelist(0, GFP_KERNEL), GFP_KERNEL, 0);
+ }
+
+ static DECLARE_WORK(moom_work, moom_callback);
+@@ -341,7 +382,11 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
+ &sysrq_kill_op, /* i */
+ NULL, /* j */
+ &sysrq_SAK_op, /* k */
++#ifdef CONFIG_SMP
++ &sysrq_showallcpus_op, /* l */
++#else
+ NULL, /* l */
++#endif
+ &sysrq_showmem_op, /* m */
+ &sysrq_unrt_op, /* n */
+ /* o: This will often be registered as 'Off' at init time */
+diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c
+index ce5ebe3..663cd15 100644
+--- a/drivers/char/toshiba.c
++++ b/drivers/char/toshiba.c
+@@ -426,7 +426,7 @@ static int tosh_probe(void)
+ int i,major,minor,day,year,month,flag;
+ unsigned char signature[7] = { 0x54,0x4f,0x53,0x48,0x49,0x42,0x41 };
+ SMMRegisters regs;
+- void __iomem *bios = ioremap(0xf0000, 0x10000);
++ void __iomem *bios = ioremap_cache(0xf0000, 0x10000);
+
+ if (!bios)
+ return -ENOMEM;
+@@ -520,12 +520,11 @@ static int __init toshiba_init(void)
+ {
+ struct proc_dir_entry *pde;
+
+- pde = create_proc_entry("toshiba", 0, NULL);
++ pde = proc_create("toshiba", 0, NULL, &proc_toshiba_fops);
+ if (!pde) {
+ misc_deregister(&tosh_device);
+ return -ENOMEM;
+ }
+- pde->proc_fops = &proc_toshiba_fops;
+ }
+ #endif
+
+diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
+index 8f3f762..3738cfa 100644
+--- a/drivers/char/tpm/Kconfig
++++ b/drivers/char/tpm/Kconfig
+@@ -23,7 +23,7 @@ if TCG_TPM
+
+ config TCG_TIS
+ tristate "TPM Interface Specification 1.2 Interface"
+- depends on PNPACPI
++ depends on PNP
+ ---help---
+ If you have a TPM security chip that is compliant with the
+ TCG TIS 1.2 TPM specification say Yes and it will be accessible
+@@ -32,7 +32,6 @@ config TCG_TIS
+
+ config TCG_NSC
+ tristate "National Semiconductor TPM Interface"
+- depends on PNPACPI
+ ---help---
+ If you have a TPM security chip from National Semiconductor
+ say Yes and it will be accessible from within Linux. To
+@@ -48,7 +47,7 @@ config TCG_ATMEL
+
+ config TCG_INFINEON
+ tristate "Infineon Technologies TPM Interface"
+- depends on PNPACPI
++ depends on PNP
+ ---help---
+ If you have a TPM security chip from Infineon Technologies
+ (either SLD 9630 TT 1.1 or SLB 9635 TT 1.2) say Yes and it
+diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
+index 6313326..ab18c1e 100644
+--- a/drivers/char/tpm/tpm_nsc.c
++++ b/drivers/char/tpm/tpm_nsc.c
+@@ -264,7 +264,7 @@ static const struct tpm_vendor_specific tpm_nsc = {
+
+ static struct platform_device *pdev = NULL;
+
+-static void __devexit tpm_nsc_remove(struct device *dev)
++static void tpm_nsc_remove(struct device *dev)
+ {
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if ( chip ) {
+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_audit.c b/drivers/char/tty_audit.c
+index 7722466..6342b05 100644
+--- a/drivers/char/tty_audit.c
++++ b/drivers/char/tty_audit.c
+@@ -92,7 +92,7 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
+ get_task_comm(name, tsk);
+ audit_log_untrustedstring(ab, name);
+ audit_log_format(ab, " data=");
+- audit_log_n_untrustedstring(ab, buf->valid, buf->data);
++ audit_log_n_untrustedstring(ab, buf->data, buf->valid);
+ audit_log_end(ab);
+ }
+ buf->valid = 0;
+@@ -151,14 +151,9 @@ void tty_audit_fork(struct signal_struct *sig)
+ /**
+ * tty_audit_push_task - Flush task's pending audit data
+ */
+-void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
++void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid)
+ {
+ struct tty_audit_buf *buf;
+- /* FIXME I think this is correct. Check against netlink once that is
+- * I really need to read this code more closely. But that's for
+- * another patch.
+- */
+- unsigned int sessionid = audit_get_sessionid(tsk);
+
+ spin_lock_irq(&tsk->sighand->siglock);
+ buf = tsk->signal->tty_audit_buf;
+@@ -238,6 +233,10 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
+ if (unlikely(size == 0))
+ return;
+
++ if (tty->driver->type == TTY_DRIVER_TYPE_PTY
++ && tty->driver->subtype == PTY_TYPE_MASTER)
++ return;
++
+ buf = tty_audit_buf_get(tty);
+ if (!buf)
+ return;
+@@ -300,53 +299,3 @@ void tty_audit_push(struct tty_struct *tty)
+ tty_audit_buf_put(buf);
+ }
+ }
+-
+-/**
+- * tty_audit_opening - A TTY is being opened.
+- *
+- * As a special hack, tasks that close all their TTYs and open new ones
+- * are assumed to be system daemons (e.g. getty) and auditing is
+- * automatically disabled for them.
+- */
+-void tty_audit_opening(void)
+-{
+- int disable;
+-
+- disable = 1;
+- spin_lock_irq(¤t->sighand->siglock);
+- if (current->signal->audit_tty == 0)
+- disable = 0;
+- spin_unlock_irq(¤t->sighand->siglock);
+- if (!disable)
+- return;
+-
+- task_lock(current);
+- if (current->files) {
+- struct fdtable *fdt;
+- unsigned i;
+-
+- /*
+- * We don't take a ref to the file, so we must hold ->file_lock
+- * instead.
+- */
+- spin_lock(¤t->files->file_lock);
+- fdt = files_fdtable(current->files);
+- for (i = 0; i < fdt->max_fds; i++) {
+- struct file *filp;
+-
+- filp = fcheck_files(current->files, i);
+- if (filp && is_tty(filp)) {
+- disable = 0;
+- break;
+- }
+- }
+- spin_unlock(¤t->files->file_lock);
+- }
+- task_unlock(current);
+- if (!disable)
+- return;
+-
+- spin_lock_irq(¤t->sighand->siglock);
+- current->signal->audit_tty = 0;
+- spin_unlock_irq(¤t->sighand->siglock);
+-}
+diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
+index 613ec81..1d298c2 100644
+--- a/drivers/char/tty_io.c
++++ b/drivers/char/tty_io.c
+@@ -91,7 +91,6 @@
+ #include <linux/module.h>
+ #include <linux/smp_lock.h>
+ #include <linux/device.h>
+-#include <linux/idr.h>
+ #include <linux/wait.h>
+ #include <linux/bitops.h>
+ #include <linux/delay.h>
+@@ -137,9 +136,6 @@ EXPORT_SYMBOL(tty_mutex);
+
+ #ifdef CONFIG_UNIX98_PTYS
+ extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */
+-extern int pty_limit; /* Config limit on Unix98 ptys */
+-static DEFINE_IDR(allocated_ptys);
+-static DEFINE_MUTEX(allocated_ptys_lock);
+ static int ptmx_open(struct inode *, struct file *);
+ #endif
+
+@@ -152,8 +148,7 @@ ssize_t redirected_tty_write(struct file *, const char __user *,
+ static unsigned int tty_poll(struct file *, poll_table *);
+ static int tty_open(struct inode *, struct file *);
+ static int tty_release(struct inode *, struct file *);
+-int tty_ioctl(struct inode *inode, struct file *file,
+- unsigned int cmd, unsigned long arg);
++long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+ #ifdef CONFIG_COMPAT
+ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg);
+@@ -1109,8 +1104,8 @@ restart:
+ a reference to the old ldisc. If we ended up flipping back
+ to the existing ldisc we have two references to it */
+
+- if (tty->ldisc.num != o_ldisc.num && tty->driver->set_ldisc)
+- tty->driver->set_ldisc(tty);
++ if (tty->ldisc.num != o_ldisc.num && tty->ops->set_ldisc)
++ tty->ops->set_ldisc(tty);
+
+ tty_ldisc_put(o_ldisc.num);
+
+@@ -1155,6 +1150,47 @@ 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 = NULL;
++
++ if (tty_line >= 0 && tty_line <= p->num && p->ops &&
++ p->ops->poll_init && !p->ops->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
+@@ -1163,26 +1199,37 @@ static struct tty_driver *get_tty_driver(dev_t device, int *index)
+ * not in the foreground, send a SIGTTOU. If the signal is blocked or
+ * ignored, go ahead and perform the operation. (POSIX 7.2)
+ *
+- * Locking: none
++ * Locking: ctrl_lock
+ */
+
+ int tty_check_change(struct tty_struct *tty)
+ {
++ unsigned long flags;
++ int ret = 0;
++
+ if (current->signal->tty != tty)
+ return 0;
++
++ spin_lock_irqsave(&tty->ctrl_lock, flags);
++
+ if (!tty->pgrp) {
+ printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
+- return 0;
++ goto out;
+ }
+ if (task_pgrp(current) == tty->pgrp)
+- return 0;
++ goto out;
+ if (is_ignored(SIGTTOU))
+- return 0;
+- if (is_current_pgrp_orphaned())
+- return -EIO;
++ goto out;
++ if (is_current_pgrp_orphaned()) {
++ ret = -EIO;
++ goto out;
++ }
+ kill_pgrp(task_pgrp(current), SIGTTOU, 1);
+ set_thread_flag(TIF_SIGPENDING);
+- return -ERESTARTSYS;
++ ret = -ERESTARTSYS;
++out:
++ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
++ return ret;
+ }
+
+ EXPORT_SYMBOL(tty_check_change);
+@@ -1205,8 +1252,8 @@ static unsigned int hung_up_tty_poll(struct file *filp, poll_table *wait)
+ return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM;
+ }
+
+-static int hung_up_tty_ioctl(struct inode *inode, struct file *file,
+- unsigned int cmd, unsigned long arg)
++static long hung_up_tty_ioctl(struct file *file, unsigned int cmd,
++ unsigned long arg)
+ {
+ return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
+ }
+@@ -1222,7 +1269,7 @@ static const struct file_operations tty_fops = {
+ .read = tty_read,
+ .write = tty_write,
+ .poll = tty_poll,
+- .ioctl = tty_ioctl,
++ .unlocked_ioctl = tty_ioctl,
+ .compat_ioctl = tty_compat_ioctl,
+ .open = tty_open,
+ .release = tty_release,
+@@ -1235,7 +1282,7 @@ static const struct file_operations ptmx_fops = {
+ .read = tty_read,
+ .write = tty_write,
+ .poll = tty_poll,
+- .ioctl = tty_ioctl,
++ .unlocked_ioctl = tty_ioctl,
+ .compat_ioctl = tty_compat_ioctl,
+ .open = ptmx_open,
+ .release = tty_release,
+@@ -1248,7 +1295,7 @@ static const struct file_operations console_fops = {
+ .read = tty_read,
+ .write = redirected_tty_write,
+ .poll = tty_poll,
+- .ioctl = tty_ioctl,
++ .unlocked_ioctl = tty_ioctl,
+ .compat_ioctl = tty_compat_ioctl,
+ .open = tty_open,
+ .release = tty_release,
+@@ -1260,7 +1307,7 @@ static const struct file_operations hung_up_tty_fops = {
+ .read = hung_up_tty_read,
+ .write = hung_up_tty_write,
+ .poll = hung_up_tty_poll,
+- .ioctl = hung_up_tty_ioctl,
++ .unlocked_ioctl = hung_up_tty_ioctl,
+ .compat_ioctl = hung_up_tty_compat_ioctl,
+ .release = tty_release,
+ };
+@@ -1362,6 +1409,7 @@ static void do_tty_hangup(struct work_struct *work)
+ struct task_struct *p;
+ struct tty_ldisc *ld;
+ int closecount = 0, n;
++ unsigned long flags;
+
+ if (!tty)
+ return;
+@@ -1399,8 +1447,7 @@ static void do_tty_hangup(struct work_struct *work)
+ /* We may have no line discipline at this point */
+ if (ld->flush_buffer)
+ ld->flush_buffer(tty);
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ tty_driver_flush_buffer(tty);
+ if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
+ ld->write_wakeup)
+ ld->write_wakeup(tty);
+@@ -1438,19 +1485,24 @@ static void do_tty_hangup(struct work_struct *work)
+ __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
+ __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
+ put_pid(p->signal->tty_old_pgrp); /* A noop */
++ spin_lock_irqsave(&tty->ctrl_lock, flags);
+ if (tty->pgrp)
+ p->signal->tty_old_pgrp = get_pid(tty->pgrp);
++ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ spin_unlock_irq(&p->sighand->siglock);
+ } while_each_pid_task(tty->session, PIDTYPE_SID, p);
+ }
+ read_unlock(&tasklist_lock);
+
++ spin_lock_irqsave(&tty->ctrl_lock, flags);
+ tty->flags = 0;
+ put_pid(tty->session);
+ put_pid(tty->pgrp);
+ tty->session = NULL;
+ tty->pgrp = NULL;
+ tty->ctrl_status = 0;
++ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
++
+ /*
+ * If one of the devices matches a console pointer, we
+ * cannot just call hangup() because that will cause
+@@ -1458,11 +1510,11 @@ static void do_tty_hangup(struct work_struct *work)
+ * So we just call close() the right number of times.
+ */
+ if (cons_filp) {
+- if (tty->driver->close)
++ if (tty->ops->close)
+ for (n = 0; n < closecount; n++)
+- tty->driver->close(tty, cons_filp);
+- } else if (tty->driver->hangup)
+- (tty->driver->hangup)(tty);
++ tty->ops->close(tty, cons_filp);
++ } else if (tty->ops->hangup)
++ (tty->ops->hangup)(tty);
+ /*
+ * We don't want to have driver/ldisc interactions beyond
+ * the ones we did here. The driver layer expects no
+@@ -1584,16 +1636,17 @@ void disassociate_ctty(int on_exit)
+ struct tty_struct *tty;
+ struct pid *tty_pgrp = NULL;
+
+- lock_kernel();
+
+ mutex_lock(&tty_mutex);
+ tty = get_current_tty();
+ if (tty) {
+ tty_pgrp = get_pid(tty->pgrp);
+ mutex_unlock(&tty_mutex);
++ lock_kernel();
+ /* XXX: here we race, there is nothing protecting tty */
+ if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
+ tty_vhangup(tty);
++ unlock_kernel();
+ } else if (on_exit) {
+ struct pid *old_pgrp;
+ spin_lock_irq(¤t->sighand->siglock);
+@@ -1606,7 +1659,6 @@ void disassociate_ctty(int on_exit)
+ put_pid(old_pgrp);
+ }
+ mutex_unlock(&tty_mutex);
+- unlock_kernel();
+ return;
+ }
+ if (tty_pgrp) {
+@@ -1625,10 +1677,13 @@ void disassociate_ctty(int on_exit)
+ /* It is possible that do_tty_hangup has free'd this tty */
+ tty = get_current_tty();
+ if (tty) {
++ unsigned long flags;
++ spin_lock_irqsave(&tty->ctrl_lock, flags);
+ put_pid(tty->session);
+ put_pid(tty->pgrp);
+ tty->session = NULL;
+ tty->pgrp = NULL;
++ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ } else {
+ #ifdef TTY_DEBUG_HANGUP
+ printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
+@@ -1641,7 +1696,6 @@ void disassociate_ctty(int on_exit)
+ read_lock(&tasklist_lock);
+ session_clear_tty(task_session(current));
+ read_unlock(&tasklist_lock);
+- unlock_kernel();
+ }
+
+ /**
+@@ -1651,8 +1705,10 @@ void disassociate_ctty(int on_exit)
+ void no_tty(void)
+ {
+ struct task_struct *tsk = current;
++ lock_kernel();
+ if (tsk->signal->leader)
+ disassociate_ctty(0);
++ unlock_kernel();
+ proc_clear_tty(tsk);
+ }
+
+@@ -1672,21 +1728,26 @@ void no_tty(void)
+ * but not always.
+ *
+ * Locking:
+- * Broken. Relies on BKL which is unsafe here.
++ * Uses the tty control lock internally
+ */
+
+ void stop_tty(struct tty_struct *tty)
+ {
+- if (tty->stopped)
++ unsigned long flags;
++ spin_lock_irqsave(&tty->ctrl_lock, flags);
++ if (tty->stopped) {
++ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ return;
++ }
+ tty->stopped = 1;
+ if (tty->link && tty->link->packet) {
+ tty->ctrl_status &= ~TIOCPKT_START;
+ tty->ctrl_status |= TIOCPKT_STOP;
+ wake_up_interruptible(&tty->link->read_wait);
+ }
+- if (tty->driver->stop)
+- (tty->driver->stop)(tty);
++ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
++ if (tty->ops->stop)
++ (tty->ops->stop)(tty);
+ }
+
+ EXPORT_SYMBOL(stop_tty);
+@@ -1701,21 +1762,26 @@ EXPORT_SYMBOL(stop_tty);
+ * driver start method is invoked and the line discipline woken.
+ *
+ * Locking:
+- * Broken. Relies on BKL which is unsafe here.
++ * ctrl_lock
+ */
+
+ void start_tty(struct tty_struct *tty)
+ {
+- if (!tty->stopped || tty->flow_stopped)
++ unsigned long flags;
++ spin_lock_irqsave(&tty->ctrl_lock, flags);
++ if (!tty->stopped || tty->flow_stopped) {
++ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ return;
++ }
+ tty->stopped = 0;
+ if (tty->link && tty->link->packet) {
+ tty->ctrl_status &= ~TIOCPKT_STOP;
+ tty->ctrl_status |= TIOCPKT_START;
+ wake_up_interruptible(&tty->link->read_wait);
+ }
+- if (tty->driver->start)
+- (tty->driver->start)(tty);
++ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
++ if (tty->ops->start)
++ (tty->ops->start)(tty);
+ /* If we have a running line discipline it may need kicking */
+ tty_wakeup(tty);
+ }
+@@ -1733,10 +1799,8 @@ EXPORT_SYMBOL(start_tty);
+ * for hung up devices before calling the line discipline method.
+ *
+ * Locking:
+- * Locks the line discipline internally while needed
+- * For historical reasons the line discipline read method is
+- * invoked under the BKL. This will go away in time so do not rely on it
+- * in new code. Multiple read calls may be outstanding in parallel.
++ * Locks the line discipline internally while needed. Multiple
++ * read calls may be outstanding in parallel.
+ */
+
+ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
+@@ -1757,13 +1821,11 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
+ /* We want to wait for the line discipline to sort out in this
+ situation */
+ ld = tty_ldisc_ref_wait(tty);
+- lock_kernel();
+ if (ld->read)
+ i = (ld->read)(tty, file, buf, count);
+ else
+ i = -EIO;
+ tty_ldisc_deref(ld);
+- unlock_kernel();
+ if (i > 0)
+ inode->i_atime = current_fs_time(inode->i_sb);
+ return i;
+@@ -1851,9 +1913,7 @@ static inline ssize_t do_tty_write(
+ ret = -EFAULT;
+ if (copy_from_user(tty->write_buf, buf, size))
+ break;
+- lock_kernel();
+ ret = write(tty, file, tty->write_buf, size);
+- unlock_kernel();
+ if (ret <= 0)
+ break;
+ written += ret;
+@@ -1906,10 +1966,13 @@ static ssize_t tty_write(struct file *file, const char __user *buf,
+ tty = (struct tty_struct *)file->private_data;
+ if (tty_paranoia_check(tty, inode, "tty_write"))
+ return -EIO;
+- if (!tty || !tty->driver->write ||
++ if (!tty || !tty->ops->write ||
+ (test_bit(TTY_IO_ERROR, &tty->flags)))
+ return -EIO;
+-
++ /* Short term debug to catch buggy drivers */
++ if (tty->ops->write_room == NULL)
++ printk(KERN_ERR "tty driver %s lacks a write_room method.\n",
++ tty->driver->name);
+ ld = tty_ldisc_ref_wait(tty);
+ if (!ld->write)
+ ret = -EIO;
+@@ -2056,6 +2119,7 @@ static int init_dev(struct tty_driver *driver, int idx,
+ goto fail_no_mem;
+ initialize_tty_struct(tty);
+ tty->driver = driver;
++ tty->ops = driver->ops;
+ tty->index = idx;
+ tty_line_name(driver, idx, tty->name);
+
+@@ -2086,6 +2150,7 @@ static int init_dev(struct tty_driver *driver, int idx,
+ goto free_mem_out;
+ initialize_tty_struct(o_tty);
+ o_tty->driver = driver->other;
++ o_tty->ops = driver->ops;
+ o_tty->index = idx;
+ tty_line_name(driver->other, idx, o_tty->name);
+
+@@ -2390,8 +2455,8 @@ static void release_dev(struct file *filp)
+ }
+ }
+ #endif
+- if (tty->driver->close)
+- tty->driver->close(tty, filp);
++ if (tty->ops->close)
++ tty->ops->close(tty, filp);
+
+ /*
+ * Sanity check: if tty->count is going to zero, there shouldn't be
+@@ -2570,15 +2635,9 @@ static void release_dev(struct file *filp)
+ */
+ release_tty(tty, idx);
+
+-#ifdef CONFIG_UNIX98_PTYS
+ /* Make this pty number available for reallocation */
+- if (devpts) {
+- mutex_lock(&allocated_ptys_lock);
+- idr_remove(&allocated_ptys, idx);
+- mutex_unlock(&allocated_ptys_lock);
+- }
+-#endif
+-
++ if (devpts)
++ devpts_kill_index(idx);
+ }
+
+ /**
+@@ -2674,8 +2733,8 @@ got_driver:
+ printk(KERN_DEBUG "opening %s...", tty->name);
+ #endif
+ if (!retval) {
+- if (tty->driver->open)
+- retval = tty->driver->open(tty, filp);
++ if (tty->ops->open)
++ retval = tty->ops->open(tty, filp);
+ else
+ retval = -ENODEV;
+ }
+@@ -2713,7 +2772,6 @@ got_driver:
+ __proc_set_tty(current, tty);
+ spin_unlock_irq(¤t->sighand->siglock);
+ mutex_unlock(&tty_mutex);
+- tty_audit_opening();
+ return 0;
+ }
+
+@@ -2735,29 +2793,13 @@ static int ptmx_open(struct inode *inode, struct file *filp)
+ struct tty_struct *tty;
+ int retval;
+ int index;
+- int idr_ret;
+
+ nonseekable_open(inode, filp);
+
+ /* find a device that is not in use. */
+- mutex_lock(&allocated_ptys_lock);
+- if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) {
+- mutex_unlock(&allocated_ptys_lock);
+- return -ENOMEM;
+- }
+- idr_ret = idr_get_new(&allocated_ptys, NULL, &index);
+- if (idr_ret < 0) {
+- mutex_unlock(&allocated_ptys_lock);
+- if (idr_ret == -EAGAIN)
+- return -ENOMEM;
+- return -EIO;
+- }
+- if (index >= pty_limit) {
+- idr_remove(&allocated_ptys, index);
+- mutex_unlock(&allocated_ptys_lock);
+- return -EIO;
+- }
+- mutex_unlock(&allocated_ptys_lock);
++ index = devpts_new_index();
++ if (index < 0)
++ return index;
+
+ mutex_lock(&tty_mutex);
+ retval = init_dev(ptm_driver, index, &tty);
+@@ -2770,23 +2812,19 @@ static int ptmx_open(struct inode *inode, struct file *filp)
+ filp->private_data = tty;
+ file_move(filp, &tty->tty_files);
+
+- retval = -ENOMEM;
+- if (devpts_pty_new(tty->link))
++ retval = devpts_pty_new(tty->link);
++ if (retval)
+ goto out1;
+
+- check_tty_count(tty, "tty_open");
+- retval = ptm_driver->open(tty, filp);
+- if (!retval) {
+- tty_audit_opening();
++ check_tty_count(tty, "ptmx_open");
++ retval = ptm_driver->ops->open(tty, filp);
++ if (!retval)
+ return 0;
+- }
+ out1:
+ release_dev(filp);
+ return retval;
+ out:
+- mutex_lock(&allocated_ptys_lock);
+- idr_remove(&allocated_ptys, index);
+- mutex_unlock(&allocated_ptys_lock);
++ devpts_kill_index(index);
+ return retval;
+ }
+ #endif
+@@ -2843,6 +2881,7 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait)
+ static int tty_fasync(int fd, struct file *filp, int on)
+ {
+ struct tty_struct *tty;
++ unsigned long flags;
+ int retval;
+
+ tty = (struct tty_struct *)filp->private_data;
+@@ -2858,6 +2897,7 @@ static int tty_fasync(int fd, struct file *filp, int on)
+ struct pid *pid;
+ if (!waitqueue_active(&tty->read_wait))
+ tty->minimum_to_wake = 1;
++ spin_lock_irqsave(&tty->ctrl_lock, flags);
+ if (tty->pgrp) {
+ pid = tty->pgrp;
+ type = PIDTYPE_PGID;
+@@ -2865,6 +2905,7 @@ static int tty_fasync(int fd, struct file *filp, int on)
+ pid = task_pid(current);
+ type = PIDTYPE_PID;
+ }
++ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ retval = __f_setown(filp, pid, type, 0);
+ if (retval)
+ return retval;
+@@ -2950,6 +2991,8 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
+ struct winsize __user *arg)
+ {
+ struct winsize tmp_ws;
++ struct pid *pgrp, *rpgrp;
++ unsigned long flags;
+
+ if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
+ return -EFAULT;
+@@ -2967,10 +3010,21 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
+ }
+ }
+ #endif
+- if (tty->pgrp)
+- kill_pgrp(tty->pgrp, SIGWINCH, 1);
+- if ((real_tty->pgrp != tty->pgrp) && real_tty->pgrp)
+- kill_pgrp(real_tty->pgrp, SIGWINCH, 1);
++ /* Get the PID values and reference them so we can
++ avoid holding the tty ctrl lock while sending signals */
++ spin_lock_irqsave(&tty->ctrl_lock, flags);
++ pgrp = get_pid(tty->pgrp);
++ rpgrp = get_pid(real_tty->pgrp);
++ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
++
++ if (pgrp)
++ kill_pgrp(pgrp, SIGWINCH, 1);
++ if (rpgrp != pgrp && rpgrp)
++ kill_pgrp(rpgrp, SIGWINCH, 1);
++
++ put_pid(pgrp);
++ put_pid(rpgrp);
++
+ tty->winsize = tmp_ws;
+ real_tty->winsize = tmp_ws;
+ done:
+@@ -3031,10 +3085,13 @@ static int fionbio(struct file *file, int __user *p)
+ if (get_user(nonblock, p))
+ return -EFAULT;
+
++ /* file->f_flags is still BKL protected in the fs layer - vomit */
++ lock_kernel();
+ if (nonblock)
+ file->f_flags |= O_NONBLOCK;
+ else
+ file->f_flags &= ~O_NONBLOCK;
++ unlock_kernel();
+ return 0;
+ }
+
+@@ -3092,6 +3149,27 @@ unlock:
+ }
+
+ /**
++ * tty_get_pgrp - return a ref counted pgrp pid
++ * @tty: tty to read
++ *
++ * Returns a refcounted instance of the pid struct for the process
++ * group controlling the tty.
++ */
++
++struct pid *tty_get_pgrp(struct tty_struct *tty)
++{
++ unsigned long flags;
++ struct pid *pgrp;
++
++ spin_lock_irqsave(&tty->ctrl_lock, flags);
++ pgrp = get_pid(tty->pgrp);
++ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
++
++ return pgrp;
++}
++EXPORT_SYMBOL_GPL(tty_get_pgrp);
++
++/**
+ * tiocgpgrp - get process group
+ * @tty: tty passed by user
+ * @real_tty: tty side of the tty pased by the user if a pty else the tty
+@@ -3105,13 +3183,18 @@ unlock:
+
+ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
+ {
++ struct pid *pid;
++ int ret;
+ /*
+ * (tty == real_tty) is a cheap way of
+ * testing if the tty is NOT a master pty.
+ */
+ if (tty == real_tty && current->signal->tty != real_tty)
+ return -ENOTTY;
+- return put_user(pid_vnr(real_tty->pgrp), p);
++ pid = tty_get_pgrp(real_tty);
++ ret = put_user(pid_vnr(pid), p);
++ put_pid(pid);
++ return ret;
+ }
+
+ /**
+@@ -3123,7 +3206,7 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
+ * Set the process group of the tty to the session passed. Only
+ * permitted where the tty session is our session.
+ *
+- * Locking: None
++ * Locking: RCU, ctrl lock
+ */
+
+ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
+@@ -3131,6 +3214,7 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
+ struct pid *pgrp;
+ pid_t pgrp_nr;
+ int retval = tty_check_change(real_tty);
++ unsigned long flags;
+
+ if (retval == -EIO)
+ return -ENOTTY;
+@@ -3153,8 +3237,10 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
+ if (session_of_pgrp(pgrp) != task_session(current))
+ goto out_unlock;
+ retval = 0;
++ spin_lock_irqsave(&tty->ctrl_lock, flags);
+ put_pid(real_tty->pgrp);
+ real_tty->pgrp = get_pid(pgrp);
++ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ out_unlock:
+ rcu_read_unlock();
+ return retval;
+@@ -3198,10 +3284,16 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _
+ static int tiocsetd(struct tty_struct *tty, int __user *p)
+ {
+ int ldisc;
++ int ret;
+
+ if (get_user(ldisc, p))
+ return -EFAULT;
+- return tty_set_ldisc(tty, ldisc);
++
++ lock_kernel();
++ ret = tty_set_ldisc(tty, ldisc);
++ unlock_kernel();
++
++ return ret;
+ }
+
+ /**
+@@ -3221,18 +3313,18 @@ static int send_break(struct tty_struct *tty, unsigned int duration)
+ {
+ if (tty_write_lock(tty, 0) < 0)
+ return -EINTR;
+- tty->driver->break_ctl(tty, -1);
++ tty->ops->break_ctl(tty, -1);
+ if (!signal_pending(current))
+ msleep_interruptible(duration);
+- tty->driver->break_ctl(tty, 0);
++ tty->ops->break_ctl(tty, 0);
+ tty_write_unlock(tty);
+- if (signal_pending(current))
++ if (!signal_pending(current))
+ return -EINTR;
+ return 0;
+ }
+
+ /**
+- * tiocmget - get modem status
++ * tty_tiocmget - get modem status
+ * @tty: tty device
+ * @file: user file pointer
+ * @p: pointer to result
+@@ -3247,8 +3339,8 @@ static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p
+ {
+ int retval = -EINVAL;
+
+- if (tty->driver->tiocmget) {
+- retval = tty->driver->tiocmget(tty, file);
++ if (tty->ops->tiocmget) {
++ retval = tty->ops->tiocmget(tty, file);
+
+ if (retval >= 0)
+ retval = put_user(retval, p);
+@@ -3257,7 +3349,7 @@ static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p
+ }
+
+ /**
+- * tiocmset - set modem status
++ * tty_tiocmset - set modem status
+ * @tty: tty device
+ * @file: user file pointer
+ * @cmd: command - clear bits, set bits or set all
+@@ -3274,7 +3366,7 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
+ {
+ int retval = -EINVAL;
+
+- if (tty->driver->tiocmset) {
++ if (tty->ops->tiocmset) {
+ unsigned int set, clear, val;
+
+ retval = get_user(val, p);
+@@ -3298,7 +3390,7 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
+ set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
+ clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
+
+- retval = tty->driver->tiocmset(tty, file, set, clear);
++ retval = tty->ops->tiocmset(tty, file, set, clear);
+ }
+ return retval;
+ }
+@@ -3306,20 +3398,18 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
+ /*
+ * Split this up, as gcc can choke on it otherwise..
+ */
+-int tty_ioctl(struct inode *inode, struct file *file,
+- unsigned int cmd, unsigned long arg)
++long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+ struct tty_struct *tty, *real_tty;
+ void __user *p = (void __user *)arg;
+ int retval;
+ struct tty_ldisc *ld;
++ struct inode *inode = file->f_dentry->d_inode;
+
+ tty = (struct tty_struct *)file->private_data;
+ if (tty_paranoia_check(tty, inode, "tty_ioctl"))
+ return -EINVAL;
+
+- /* CHECKME: is this safe as one end closes ? */
+-
+ real_tty = tty;
+ if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
+ tty->driver->subtype == PTY_TYPE_MASTER)
+@@ -3328,21 +3418,28 @@ int tty_ioctl(struct inode *inode, struct file *file,
+ /*
+ * Break handling by driver
+ */
+- if (!tty->driver->break_ctl) {
++
++ retval = -EINVAL;
++
++ if (!tty->ops->break_ctl) {
+ switch (cmd) {
+ case TIOCSBRK:
+ case TIOCCBRK:
+- if (tty->driver->ioctl)
+- return tty->driver->ioctl(tty, file, cmd, arg);
+- return -EINVAL;
++ if (tty->ops->ioctl)
++ retval = tty->ops->ioctl(tty, file, cmd, arg);
++ if (retval != -EINVAL && retval != -ENOIOCTLCMD)
++ printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
++ return retval;
+
+ /* These two ioctl's always return success; even if */
+ /* the driver doesn't support them. */
+ case TCSBRK:
+ case TCSBRKP:
+- if (!tty->driver->ioctl)
++ if (!tty->ops->ioctl)
+ return 0;
+- retval = tty->driver->ioctl(tty, file, cmd, arg);
++ retval = tty->ops->ioctl(tty, file, cmd, arg);
++ if (retval != -EINVAL && retval != -ENOIOCTLCMD)
++ printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
+ if (retval == -ENOIOCTLCMD)
+ retval = 0;
+ return retval;
+@@ -3400,7 +3497,6 @@ int tty_ioctl(struct inode *inode, struct file *file,
+ case TIOCGSID:
+ return tiocgsid(tty, real_tty, p);
+ case TIOCGETD:
+- /* FIXME: check this is ok */
+ return put_user(tty->ldisc.num, (int __user *)p);
+ case TIOCSETD:
+ return tiocsetd(tty, p);
+@@ -3412,11 +3508,13 @@ int tty_ioctl(struct inode *inode, struct file *file,
+ * Break handling
+ */
+ case TIOCSBRK: /* Turn break on, unconditionally */
+- tty->driver->break_ctl(tty, -1);
++ if (tty->ops->break_ctl)
++ tty->ops->break_ctl(tty, -1);
+ return 0;
+
+ case TIOCCBRK: /* Turn break off, unconditionally */
+- tty->driver->break_ctl(tty, 0);
++ if (tty->ops->break_ctl)
++ tty->ops->break_ctl(tty, 0);
+ return 0;
+ case TCSBRK: /* SVID version: non-zero arg --> no break */
+ /* non-zero arg means wait for all output data
+@@ -3445,8 +3543,8 @@ int tty_ioctl(struct inode *inode, struct file *file,
+ }
+ break;
+ }
+- if (tty->driver->ioctl) {
+- retval = (tty->driver->ioctl)(tty, file, cmd, arg);
++ if (tty->ops->ioctl) {
++ retval = (tty->ops->ioctl)(tty, file, cmd, arg);
+ if (retval != -ENOIOCTLCMD)
+ return retval;
+ }
+@@ -3473,8 +3571,8 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
+ if (tty_paranoia_check(tty, inode, "tty_ioctl"))
+ return -EINVAL;
+
+- if (tty->driver->compat_ioctl) {
+- retval = (tty->driver->compat_ioctl)(tty, file, cmd, arg);
++ if (tty->ops->compat_ioctl) {
++ retval = (tty->ops->compat_ioctl)(tty, file, cmd, arg);
+ if (retval != -ENOIOCTLCMD)
+ return retval;
+ }
+@@ -3524,8 +3622,7 @@ void __do_SAK(struct tty_struct *tty)
+
+ tty_ldisc_flush(tty);
+
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ tty_driver_flush_buffer(tty);
+
+ read_lock(&tasklist_lock);
+ /* Kill the entire session */
+@@ -3731,19 +3828,32 @@ static void initialize_tty_struct(struct tty_struct *tty)
+ mutex_init(&tty->atomic_read_lock);
+ mutex_init(&tty->atomic_write_lock);
+ spin_lock_init(&tty->read_lock);
++ spin_lock_init(&tty->ctrl_lock);
+ INIT_LIST_HEAD(&tty->tty_files);
+ INIT_WORK(&tty->SAK_work, do_SAK_work);
+ }
+
+-/*
+- * The default put_char routine if the driver did not define one.
++/**
++ * tty_put_char - write one character to a tty
++ * @tty: tty
++ * @ch: character
++ *
++ * Write one byte to the tty using the provided put_char method
++ * if present. Returns the number of characters successfully output.
++ *
++ * Note: the specific put_char operation in the driver layer may go
++ * away soon. Don't call it directly, use this method
+ */
+
+-static void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
++int tty_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+- tty->driver->write(tty, &ch, 1);
++ if (tty->ops->put_char)
++ return tty->ops->put_char(tty, ch);
++ return tty->ops->write(tty, &ch, 1);
+ }
+
++EXPORT_SYMBOL_GPL(tty_put_char);
++
+ static struct class *tty_class;
+
+ /**
+@@ -3826,32 +3936,8 @@ void put_tty_driver(struct tty_driver *driver)
+ void tty_set_operations(struct tty_driver *driver,
+ const struct tty_operations *op)
+ {
+- driver->open = op->open;
+- driver->close = op->close;
+- driver->write = op->write;
+- driver->put_char = op->put_char;
+- driver->flush_chars = op->flush_chars;
+- driver->write_room = op->write_room;
+- driver->chars_in_buffer = op->chars_in_buffer;
+- driver->ioctl = op->ioctl;
+- driver->compat_ioctl = op->compat_ioctl;
+- driver->set_termios = op->set_termios;
+- driver->throttle = op->throttle;
+- driver->unthrottle = op->unthrottle;
+- driver->stop = op->stop;
+- driver->start = op->start;
+- driver->hangup = op->hangup;
+- driver->break_ctl = op->break_ctl;
+- driver->flush_buffer = op->flush_buffer;
+- driver->set_ldisc = op->set_ldisc;
+- driver->wait_until_sent = op->wait_until_sent;
+- driver->send_xchar = op->send_xchar;
+- driver->read_proc = op->read_proc;
+- driver->write_proc = op->write_proc;
+- driver->tiocmget = op->tiocmget;
+- driver->tiocmset = op->tiocmset;
+-}
+-
++ driver->ops = op;
++};
+
+ EXPORT_SYMBOL(alloc_tty_driver);
+ EXPORT_SYMBOL(put_tty_driver);
+@@ -3914,9 +4000,6 @@ int tty_register_driver(struct tty_driver *driver)
+ return error;
+ }
+
+- if (!driver->put_char)
+- driver->put_char = tty_default_put_char;
+-
+ mutex_lock(&tty_mutex);
+ list_add(&driver->tty_drivers, &tty_drivers);
+ mutex_unlock(&tty_mutex);
+@@ -3992,14 +4075,19 @@ void proc_clear_tty(struct task_struct *p)
+ }
+ EXPORT_SYMBOL(proc_clear_tty);
+
++/* Called under the sighand lock */
++
+ static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
+ {
+ if (tty) {
+- /* We should not have a session or pgrp to here but.... */
++ unsigned long flags;
++ /* We should not have a session or pgrp to put here but.... */
++ spin_lock_irqsave(&tty->ctrl_lock, flags);
+ put_pid(tty->session);
+ put_pid(tty->pgrp);
+- tty->session = get_pid(task_session(tsk));
+ tty->pgrp = get_pid(task_pgrp(tsk));
++ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
++ tty->session = get_pid(task_session(tsk));
+ }
+ put_pid(tsk->signal->tty_old_pgrp);
+ tsk->signal->tty = tty;
+diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
+index f95a80b..b1a757a 100644
+--- a/drivers/char/tty_ioctl.c
++++ b/drivers/char/tty_ioctl.c
+@@ -21,6 +21,7 @@
+ #include <linux/module.h>
+ #include <linux/bitops.h>
+ #include <linux/mutex.h>
++#include <linux/smp_lock.h>
+
+ #include <asm/io.h>
+ #include <asm/uaccess.h>
+@@ -39,6 +40,50 @@
+ #define TERMIOS_OLD 8
+
+
++int tty_chars_in_buffer(struct tty_struct *tty)
++{
++ if (tty->ops->chars_in_buffer)
++ return tty->ops->chars_in_buffer(tty);
++ else
++ return 0;
++}
++
++EXPORT_SYMBOL(tty_chars_in_buffer);
++
++int tty_write_room(struct tty_struct *tty)
++{
++ if (tty->ops->write_room)
++ return tty->ops->write_room(tty);
++ return 2048;
++}
++
++EXPORT_SYMBOL(tty_write_room);
++
++void tty_driver_flush_buffer(struct tty_struct *tty)
++{
++ if (tty->ops->flush_buffer)
++ tty->ops->flush_buffer(tty);
++}
++
++EXPORT_SYMBOL(tty_driver_flush_buffer);
++
++void tty_throttle(struct tty_struct *tty)
++{
++ /* check TTY_THROTTLED first so it indicates our state */
++ if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
++ tty->ops->throttle)
++ tty->ops->throttle(tty);
++}
++EXPORT_SYMBOL(tty_throttle);
++
++void tty_unthrottle(struct tty_struct *tty)
++{
++ if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
++ tty->ops->unthrottle)
++ tty->ops->unthrottle(tty);
++}
++EXPORT_SYMBOL(tty_unthrottle);
++
+ /**
+ * tty_wait_until_sent - wait for I/O to finish
+ * @tty: tty we are waiting for
+@@ -57,15 +102,13 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout)
+
+ printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
+ #endif
+- if (!tty->driver->chars_in_buffer)
+- return;
+ if (!timeout)
+ timeout = MAX_SCHEDULE_TIMEOUT;
+ if (wait_event_interruptible_timeout(tty->write_wait,
+- !tty->driver->chars_in_buffer(tty), timeout) < 0)
+- return;
+- if (tty->driver->wait_until_sent)
+- tty->driver->wait_until_sent(tty, timeout);
++ !tty_chars_in_buffer(tty), timeout) >= 0) {
++ if (tty->ops->wait_until_sent)
++ tty->ops->wait_until_sent(tty, timeout);
++ }
+ }
+ EXPORT_SYMBOL(tty_wait_until_sent);
+
+@@ -393,8 +436,9 @@ EXPORT_SYMBOL(tty_termios_hw_change);
+ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
+ {
+ int canon_change;
+- struct ktermios old_termios = *tty->termios;
++ struct ktermios old_termios;
+ struct tty_ldisc *ld;
++ unsigned long flags;
+
+ /*
+ * Perform the actual termios internal changes under lock.
+@@ -404,7 +448,7 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
+ /* FIXME: we need to decide on some locking/ordering semantics
+ for the set_termios notification eventually */
+ mutex_lock(&tty->termios_mutex);
+-
++ old_termios = *tty->termios;
+ *tty->termios = *new_termios;
+ unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
+ canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
+@@ -429,17 +473,19 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
+ STOP_CHAR(tty) == '\023' &&
+ START_CHAR(tty) == '\021');
+ if (old_flow != new_flow) {
++ spin_lock_irqsave(&tty->ctrl_lock, flags);
+ tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
+ if (new_flow)
+ tty->ctrl_status |= TIOCPKT_DOSTOP;
+ else
+ tty->ctrl_status |= TIOCPKT_NOSTOP;
++ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ wake_up_interruptible(&tty->link->read_wait);
+ }
+ }
+
+- if (tty->driver->set_termios)
+- (*tty->driver->set_termios)(tty, &old_termios);
++ if (tty->ops->set_termios)
++ (*tty->ops->set_termios)(tty, &old_termios);
+ else
+ tty_termios_copy_hw(tty->termios, &old_termios);
+
+@@ -474,7 +520,9 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
+ if (retval)
+ return retval;
+
++ mutex_lock(&tty->termios_mutex);
+ memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
++ mutex_unlock(&tty->termios_mutex);
+
+ if (opt & TERMIOS_TERMIO) {
+ if (user_termio_to_kernel_termios(&tmp_termios,
+@@ -660,12 +708,14 @@ static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
+ {
+ struct tchars tmp;
+
++ mutex_lock(&tty->termios_mutex);
+ tmp.t_intrc = tty->termios->c_cc[VINTR];
+ tmp.t_quitc = tty->termios->c_cc[VQUIT];
+ tmp.t_startc = tty->termios->c_cc[VSTART];
+ tmp.t_stopc = tty->termios->c_cc[VSTOP];
+ tmp.t_eofc = tty->termios->c_cc[VEOF];
+ tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
++ mutex_unlock(&tty->termios_mutex);
+ return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
+ }
+
+@@ -675,12 +725,14 @@ static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
+
+ if (copy_from_user(&tmp, tchars, sizeof(tmp)))
+ return -EFAULT;
++ mutex_lock(&tty->termios_mutex);
+ tty->termios->c_cc[VINTR] = tmp.t_intrc;
+ tty->termios->c_cc[VQUIT] = tmp.t_quitc;
+ tty->termios->c_cc[VSTART] = tmp.t_startc;
+ tty->termios->c_cc[VSTOP] = tmp.t_stopc;
+ tty->termios->c_cc[VEOF] = tmp.t_eofc;
+ tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
++ mutex_unlock(&tty->termios_mutex);
+ return 0;
+ }
+ #endif
+@@ -690,6 +742,7 @@ static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
+ {
+ struct ltchars tmp;
+
++ mutex_lock(&tty->termios_mutex);
+ tmp.t_suspc = tty->termios->c_cc[VSUSP];
+ /* what is dsuspc anyway? */
+ tmp.t_dsuspc = tty->termios->c_cc[VSUSP];
+@@ -698,6 +751,7 @@ static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
+ tmp.t_flushc = tty->termios->c_cc[VEOL2];
+ tmp.t_werasc = tty->termios->c_cc[VWERASE];
+ tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
++ mutex_unlock(&tty->termios_mutex);
+ return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
+ }
+
+@@ -708,6 +762,7 @@ static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
+ if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
+ return -EFAULT;
+
++ mutex_lock(&tty->termios_mutex);
+ tty->termios->c_cc[VSUSP] = tmp.t_suspc;
+ /* what is dsuspc anyway? */
+ tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;
+@@ -716,6 +771,7 @@ static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
+ tty->termios->c_cc[VEOL2] = tmp.t_flushc;
+ tty->termios->c_cc[VWERASE] = tmp.t_werasc;
+ tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
++ mutex_unlock(&tty->termios_mutex);
+ return 0;
+ }
+ #endif
+@@ -732,8 +788,8 @@ static int send_prio_char(struct tty_struct *tty, char ch)
+ {
+ int was_stopped = tty->stopped;
+
+- if (tty->driver->send_xchar) {
+- tty->driver->send_xchar(tty, ch);
++ if (tty->ops->send_xchar) {
++ tty->ops->send_xchar(tty, ch);
+ return 0;
+ }
+
+@@ -742,7 +798,7 @@ static int send_prio_char(struct tty_struct *tty, char ch)
+
+ if (was_stopped)
+ start_tty(tty);
+- tty->driver->write(tty, &ch, 1);
++ tty->ops->write(tty, &ch, 1);
+ if (was_stopped)
+ stop_tty(tty);
+ tty_write_unlock(tty);
+@@ -750,6 +806,33 @@ static int send_prio_char(struct tty_struct *tty, char ch)
+ }
+
+ /**
++ * tty_change_softcar - carrier change ioctl helper
++ * @tty: tty to update
++ * @arg: enable/disable CLOCAL
++ *
++ * Perform a change to the CLOCAL state and call into the driver
++ * layer to make it visible. All done with the termios mutex
++ */
++
++static int tty_change_softcar(struct tty_struct *tty, int arg)
++{
++ int ret = 0;
++ int bit = arg ? CLOCAL : 0;
++ struct ktermios old;
++
++ mutex_lock(&tty->termios_mutex);
++ old = *tty->termios;
++ tty->termios->c_cflag &= ~CLOCAL;
++ tty->termios->c_cflag |= bit;
++ if (tty->ops->set_termios)
++ tty->ops->set_termios(tty, &old);
++ if ((tty->termios->c_cflag & CLOCAL) != bit)
++ ret = -EINVAL;
++ mutex_unlock(&tty->termios_mutex);
++ return ret;
++}
++
++/**
+ * tty_mode_ioctl - mode related ioctls
+ * @tty: tty for the ioctl
+ * @file: file pointer for the tty
+@@ -859,12 +942,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
+ case TIOCSSOFTCAR:
+ if (get_user(arg, (unsigned int __user *) arg))
+ return -EFAULT;
+- mutex_lock(&tty->termios_mutex);
+- tty->termios->c_cflag =
+- ((tty->termios->c_cflag & ~CLOCAL) |
+- (arg ? CLOCAL : 0));
+- mutex_unlock(&tty->termios_mutex);
+- return 0;
++ return tty_change_softcar(tty, arg);
+ default:
+ return -ENOIOCTLCMD;
+ }
+@@ -889,8 +967,7 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
+ ld->flush_buffer(tty);
+ /* fall through */
+ case TCOFLUSH:
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ tty_driver_flush_buffer(tty);
+ break;
+ default:
+ tty_ldisc_deref(ld);
+@@ -905,6 +982,7 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+ struct tty_struct *real_tty;
++ unsigned long flags;
+ int retval;
+
+ if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
+@@ -946,9 +1024,7 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file,
+ case TCFLSH:
+ return tty_perform_flush(tty, arg);
+ case TIOCOUTQ:
+- return put_user(tty->driver->chars_in_buffer ?
+- tty->driver->chars_in_buffer(tty) : 0,
+- (int __user *) arg);
++ return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
+ case TIOCINQ:
+ retval = tty->read_cnt;
+ if (L_ICANON(tty))
+@@ -963,6 +1039,7 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file,
+ return -ENOTTY;
+ if (get_user(pktmode, (int __user *) arg))
+ return -EFAULT;
++ spin_lock_irqsave(&tty->ctrl_lock, flags);
+ if (pktmode) {
+ if (!tty->packet) {
+ tty->packet = 1;
+@@ -970,6 +1047,7 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file,
+ }
+ } else
+ tty->packet = 0;
++ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ return 0;
+ }
+ default:
+diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c
+index 8de6b95..3d3e1c2 100644
+--- a/drivers/char/viocons.c
++++ b/drivers/char/viocons.c
+@@ -628,13 +628,13 @@ static int viotty_write(struct tty_struct *tty, const unsigned char *buf,
+ /*
+ * TTY put_char method
+ */
+-static void viotty_put_char(struct tty_struct *tty, unsigned char ch)
++static int viotty_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ struct port_info *pi;
+
+ pi = get_port_data(tty);
+ if (pi == NULL)
+- return;
++ return 0;
+
+ /* This will append '\r' as well if the char is '\n' */
+ if (viochar_is_console(pi))
+@@ -642,6 +642,7 @@ static void viotty_put_char(struct tty_struct *tty, unsigned char ch)
+
+ if (viopath_isactive(pi->lp))
+ internal_write(pi, &ch, 1);
++ return 1;
+ }
+
+ /*
+@@ -704,8 +705,11 @@ static int viotty_ioctl(struct tty_struct *tty, struct file *file,
+ case KDSKBLED:
+ return 0;
+ }
+-
+- return n_tty_ioctl(tty, file, cmd, arg);
++ /* FIXME: WTF is this being called for ??? */
++ lock_kernel();
++ ret = n_tty_ioctl(tty, file, cmd, arg);
++ unlock_kernel();
++ return ret;
+ }
+
+ /*
+diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
+index db7a731..58aad63 100644
+--- a/drivers/char/viotape.c
++++ b/drivers/char/viotape.c
+@@ -249,6 +249,7 @@ static int proc_viotape_open(struct inode *inode, struct file *file)
+ }
+
+ static const struct file_operations proc_viotape_operations = {
++ .owner = THIS_MODULE,
+ .open = proc_viotape_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -915,7 +916,6 @@ static struct vio_driver viotape_driver = {
+ int __init viotap_init(void)
+ {
+ int ret;
+- struct proc_dir_entry *e;
+
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return -ENODEV;
+@@ -968,11 +968,8 @@ int __init viotap_init(void)
+ if (ret)
+ goto unreg_class;
+
+- e = create_proc_entry("iSeries/viotape", S_IFREG|S_IRUGO, NULL);
+- if (e) {
+- e->owner = THIS_MODULE;
+- e->proc_fops = &proc_viotape_operations;
+- }
++ proc_create("iSeries/viotape", S_IFREG|S_IRUGO, NULL,
++ &proc_viotape_operations);
+
+ return 0;
+
+diff --git a/drivers/char/vt.c b/drivers/char/vt.c
+index 9b58b89..e458b08 100644
+--- a/drivers/char/vt.c
++++ b/drivers/char/vt.c
+@@ -301,7 +301,7 @@ static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
+ d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
+ s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr));
+ scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row);
+- scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_video_erase_char,
++ scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_scrl_erase_char,
+ vc->vc_size_row * nr);
+ }
+
+@@ -319,7 +319,7 @@ static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
+ s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
+ step = vc->vc_cols * nr;
+ scr_memmovew(s + step, s, (b - t - nr) * vc->vc_size_row);
+- scr_memsetw(s, vc->vc_video_erase_char, 2 * step);
++ scr_memsetw(s, vc->vc_scrl_erase_char, 2 * step);
+ }
+
+ static void do_update_region(struct vc_data *vc, unsigned long start, int count)
+@@ -400,7 +400,7 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink,
+ * Bit 7 : blink
+ */
+ {
+- u8 a = vc->vc_color;
++ u8 a = _color;
+ if (!vc->vc_can_do_color)
+ return _intensity |
+ (_italic ? 2 : 0) |
+@@ -434,6 +434,7 @@ static void update_attr(struct vc_data *vc)
+ vc->vc_blink, vc->vc_underline,
+ vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic);
+ vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' ';
++ vc->vc_scrl_erase_char = (build_attr(vc, vc->vc_def_color, 1, false, false, false, false) << 8) | ' ';
+ }
+
+ /* Note: inverting the screen twice should revert to the original state */
+@@ -908,15 +909,21 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
+
+ if (vc->vc_tty) {
+ struct winsize ws, *cws = &vc->vc_tty->winsize;
++ unsigned long flags;
+
+ memset(&ws, 0, sizeof(ws));
+ ws.ws_row = vc->vc_rows;
+ ws.ws_col = vc->vc_cols;
+ ws.ws_ypixel = vc->vc_scan_lines;
++
++ mutex_lock(&vc->vc_tty->termios_mutex);
++ spin_lock_irqsave(&vc->vc_tty->ctrl_lock, flags);
+ if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) &&
+ vc->vc_tty->pgrp)
+ kill_pgrp(vc->vc_tty->pgrp, SIGWINCH, 1);
++ spin_unlock_irqrestore(&vc->vc_tty->ctrl_lock, flags);
+ *cws = ws;
++ mutex_unlock(&vc->vc_tty->termios_mutex);
+ }
+
+ if (CON_IS_VISIBLE(vc))
+@@ -2054,6 +2061,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
+ unsigned long draw_from = 0, draw_to = 0;
+ struct vc_data *vc;
+ unsigned char vc_attr;
++ struct vt_notifier_param param;
+ uint8_t rescan;
+ uint8_t inverse;
+ uint8_t width;
+@@ -2113,6 +2121,8 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
+ if (IS_FG(vc))
+ hide_cursor(vc);
+
++ param.vc = vc;
++
+ while (!tty->stopped && count) {
+ int orig = *buf;
+ c = orig;
+@@ -2201,6 +2211,11 @@ rescan_last_byte:
+ tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c];
+ }
+
++ param.c = tc;
++ if (atomic_notifier_call_chain(&vt_notifier_list, VT_PREWRITE,
++ ¶m) == NOTIFY_STOP)
++ continue;
++
+ /* If the original code was a control character we
+ * only allow a glyph to be displayed if the code is
+ * not normally used (such as for cursor movement) or
+@@ -2532,6 +2547,9 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
+ if (get_user(type, p))
+ return -EFAULT;
+ ret = 0;
++
++ lock_kernel();
++
+ switch (type)
+ {
+ case TIOCL_SETSEL:
+@@ -2551,7 +2569,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
+ ret = sel_loadlut(p);
+ break;
+ case TIOCL_GETSHIFTSTATE:
+-
++
+ /*
+ * Make it possible to react to Shift+Mousebutton.
+ * Note that 'shift_state' is an undocumented
+@@ -2606,6 +2624,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
+ ret = -EINVAL;
+ break;
+ }
++ unlock_kernel();
+ return ret;
+ }
+
+@@ -2623,11 +2642,11 @@ static int con_write(struct tty_struct *tty, const unsigned char *buf, int count
+ return retval;
+ }
+
+-static void con_put_char(struct tty_struct *tty, unsigned char ch)
++static int con_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ if (in_interrupt())
+- return; /* n_r3964 calls put_char() from interrupt context */
+- do_con_write(tty, &ch, 1);
++ return 0; /* n_r3964 calls put_char() from interrupt context */
++ return do_con_write(tty, &ch, 1);
+ }
+
+ static int con_write_room(struct tty_struct *tty)
+@@ -3820,7 +3839,7 @@ static int con_font_get(struct vc_data *vc, struct console_font_op *op)
+ goto out;
+
+ c = (font.width+7)/8 * 32 * font.charcount;
+-
++
+ if (op->data && font.charcount > op->charcount)
+ rc = -ENOSPC;
+ if (!(op->flags & KD_FONT_FLAG_OLD)) {
+@@ -3985,6 +4004,7 @@ u16 screen_glyph(struct vc_data *vc, int offset)
+ c |= 0x100;
+ return c;
+ }
++EXPORT_SYMBOL_GPL(screen_glyph);
+
+ /* used by vcs - note the word offset */
+ unsigned short *screen_pos(struct vc_data *vc, int w_offset, int viewed)
+diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
+index e6f89e8..3211afd 100644
+--- a/drivers/char/vt_ioctl.c
++++ b/drivers/char/vt_ioctl.c
+@@ -373,11 +373,17 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ unsigned char ucval;
+ void __user *up = (void __user *)arg;
+ int i, perm;
+-
++ int ret = 0;
++
+ console = vc->vc_num;
+
+- if (!vc_cons_allocated(console)) /* impossible? */
+- return -ENOIOCTLCMD;
++ lock_kernel();
++
++ if (!vc_cons_allocated(console)) { /* impossible? */
++ ret = -ENOIOCTLCMD;
++ goto out;
++ }
++
+
+ /*
+ * To have permissions to do most of the vt ioctls, we either have
+@@ -391,15 +397,15 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ switch (cmd) {
+ case KIOCSOUND:
+ if (!perm)
+- return -EPERM;
++ goto eperm;
+ if (arg)
+ arg = CLOCK_TICK_RATE / arg;
+ kd_mksound(arg, 0);
+- return 0;
++ break;
+
+ case KDMKTONE:
+ if (!perm)
+- return -EPERM;
++ goto eperm;
+ {
+ unsigned int ticks, count;
+
+@@ -412,7 +418,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ if (count)
+ count = CLOCK_TICK_RATE / count;
+ kd_mksound(count, ticks);
+- return 0;
++ break;
+ }
+
+ case KDGKBTYPE:
+@@ -435,14 +441,18 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ * KDADDIO and KDDELIO may be able to add ports beyond what
+ * we reject here, but to be safe...
+ */
+- if (arg < GPFIRST || arg > GPLAST)
+- return -EINVAL;
+- return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
++ if (arg < GPFIRST || arg > GPLAST) {
++ ret = -EINVAL;
++ break;
++ }
++ ret = sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
++ break;
+
+ case KDENABIO:
+ case KDDISABIO:
+- return sys_ioperm(GPFIRST, GPNUM,
++ ret = sys_ioperm(GPFIRST, GPNUM,
+ (cmd == KDENABIO)) ? -ENXIO : 0;
++ break;
+ #endif
+
+ /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */
+@@ -450,19 +460,20 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ case KDKBDREP:
+ {
+ struct kbd_repeat kbrep;
+- int err;
+
+ if (!capable(CAP_SYS_TTY_CONFIG))
+- return -EPERM;
++ goto eperm;
+
+- if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat)))
+- return -EFAULT;
+- err = kbd_rate(&kbrep);
+- if (err)
+- return err;
++ if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) {
++ ret = -EFAULT;
++ break;
++ }
++ ret = kbd_rate(&kbrep);
++ if (ret)
++ break;
+ if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat)))
+- return -EFAULT;
+- return 0;
++ ret = -EFAULT;
++ break;
+ }
+
+ case KDSETMODE:
+@@ -475,7 +486,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ * need to restore their engine state. --BenH
+ */
+ if (!perm)
+- return -EPERM;
++ goto eperm;
+ switch (arg) {
+ case KD_GRAPHICS:
+ break;
+@@ -485,13 +496,14 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ case KD_TEXT:
+ break;
+ default:
+- return -EINVAL;
++ ret = -EINVAL;
++ goto out;
+ }
+ if (vc->vc_mode == (unsigned char) arg)
+- return 0;
++ break;
+ vc->vc_mode = (unsigned char) arg;
+ if (console != fg_console)
+- return 0;
++ break;
+ /*
+ * explicitly blank/unblank the screen if switching modes
+ */
+@@ -501,7 +513,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ else
+ do_blank_screen(1);
+ release_console_sem();
+- return 0;
++ break;
+
+ case KDGETMODE:
+ ucval = vc->vc_mode;
+@@ -513,11 +525,12 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ * these work like a combination of mmap and KDENABIO.
+ * this could be easily finished.
+ */
+- return -EINVAL;
++ ret = -EINVAL;
++ break;
+
+ case KDSKBMODE:
+ if (!perm)
+- return -EPERM;
++ goto eperm;
+ switch(arg) {
+ case K_RAW:
+ kbd->kbdmode = VC_RAW;
+@@ -534,10 +547,11 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ compute_shiftstate();
+ break;
+ default:
+- return -EINVAL;
++ ret = -EINVAL;
++ goto out;
+ }
+ tty_ldisc_flush(tty);
+- return 0;
++ break;
+
+ case KDGKBMODE:
+ ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
+@@ -557,28 +571,32 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ set_vc_kbd_mode(kbd, VC_META);
+ break;
+ default:
+- return -EINVAL;
++ ret = -EINVAL;
+ }
+- return 0;
++ break;
+
+ case KDGKBMETA:
+ ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT);
+ setint:
+- return put_user(ucval, (int __user *)arg);
++ ret = put_user(ucval, (int __user *)arg);
++ break;
+
+ case KDGETKEYCODE:
+ case KDSETKEYCODE:
+ if(!capable(CAP_SYS_TTY_CONFIG))
+- perm=0;
+- return do_kbkeycode_ioctl(cmd, up, perm);
++ perm = 0;
++ ret = do_kbkeycode_ioctl(cmd, up, perm);
++ break;
+
+ case KDGKBENT:
+ case KDSKBENT:
+- return do_kdsk_ioctl(cmd, up, perm, kbd);
++ ret = do_kdsk_ioctl(cmd, up, perm, kbd);
++ break;
+
+ case KDGKBSENT:
+ case KDSKBSENT:
+- return do_kdgkb_ioctl(cmd, up, perm);
++ ret = do_kdgkb_ioctl(cmd, up, perm);
++ break;
+
+ case KDGKBDIACR:
+ {
+@@ -586,26 +604,31 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ struct kbdiacr diacr;
+ int i;
+
+- if (put_user(accent_table_size, &a->kb_cnt))
+- return -EFAULT;
++ if (put_user(accent_table_size, &a->kb_cnt)) {
++ ret = -EFAULT;
++ break;
++ }
+ for (i = 0; i < accent_table_size; i++) {
+ diacr.diacr = conv_uni_to_8bit(accent_table[i].diacr);
+ diacr.base = conv_uni_to_8bit(accent_table[i].base);
+ diacr.result = conv_uni_to_8bit(accent_table[i].result);
+- if (copy_to_user(a->kbdiacr + i, &diacr, sizeof(struct kbdiacr)))
+- return -EFAULT;
++ if (copy_to_user(a->kbdiacr + i, &diacr, sizeof(struct kbdiacr))) {
++ ret = -EFAULT;
++ break;
++ }
+ }
+- return 0;
++ break;
+ }
+ case KDGKBDIACRUC:
+ {
+ struct kbdiacrsuc __user *a = up;
+
+ if (put_user(accent_table_size, &a->kb_cnt))
+- return -EFAULT;
+- if (copy_to_user(a->kbdiacruc, accent_table, accent_table_size*sizeof(struct kbdiacruc)))
+- return -EFAULT;
+- return 0;
++ ret = -EFAULT;
++ else if (copy_to_user(a->kbdiacruc, accent_table,
++ accent_table_size*sizeof(struct kbdiacruc)))
++ ret = -EFAULT;
++ break;
+ }
+
+ case KDSKBDIACR:
+@@ -616,20 +639,26 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ int i;
+
+ if (!perm)
+- return -EPERM;
+- if (get_user(ct,&a->kb_cnt))
+- return -EFAULT;
+- if (ct >= MAX_DIACR)
+- return -EINVAL;
++ goto eperm;
++ if (get_user(ct,&a->kb_cnt)) {
++ ret = -EFAULT;
++ break;
++ }
++ if (ct >= MAX_DIACR) {
++ ret = -EINVAL;
++ break;
++ }
+ accent_table_size = ct;
+ for (i = 0; i < ct; i++) {
+- if (copy_from_user(&diacr, a->kbdiacr + i, sizeof(struct kbdiacr)))
+- return -EFAULT;
++ if (copy_from_user(&diacr, a->kbdiacr + i, sizeof(struct kbdiacr))) {
++ ret = -EFAULT;
++ break;
++ }
+ accent_table[i].diacr = conv_8bit_to_uni(diacr.diacr);
+ accent_table[i].base = conv_8bit_to_uni(diacr.base);
+ accent_table[i].result = conv_8bit_to_uni(diacr.result);
+ }
+- return 0;
++ break;
+ }
+
+ case KDSKBDIACRUC:
+@@ -638,15 +667,19 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ unsigned int ct;
+
+ if (!perm)
+- return -EPERM;
+- if (get_user(ct,&a->kb_cnt))
+- return -EFAULT;
+- if (ct >= MAX_DIACR)
+- return -EINVAL;
++ goto eperm;
++ if (get_user(ct,&a->kb_cnt)) {
++ ret = -EFAULT;
++ break;
++ }
++ if (ct >= MAX_DIACR) {
++ ret = -EINVAL;
++ break;
++ }
+ accent_table_size = ct;
+ if (copy_from_user(accent_table, a->kbdiacruc, ct*sizeof(struct kbdiacruc)))
+- return -EFAULT;
+- return 0;
++ ret = -EFAULT;
++ break;
+ }
+
+ /* the ioctls below read/set the flags usually shown in the leds */
+@@ -657,26 +690,29 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+
+ case KDSKBLED:
+ if (!perm)
+- return -EPERM;
+- if (arg & ~0x77)
+- return -EINVAL;
++ goto eperm;
++ if (arg & ~0x77) {
++ ret = -EINVAL;
++ break;
++ }
+ kbd->ledflagstate = (arg & 7);
+ kbd->default_ledflagstate = ((arg >> 4) & 7);
+ set_leds();
+- return 0;
++ break;
+
+ /* the ioctls below only set the lights, not the functions */
+ /* for those, see KDGKBLED and KDSKBLED above */
+ case KDGETLED:
+ ucval = getledstate();
+ setchar:
+- return put_user(ucval, (char __user *)arg);
++ ret = put_user(ucval, (char __user *)arg);
++ break;
+
+ case KDSETLED:
+ if (!perm)
+- return -EPERM;
++ goto eperm;
+ setledstate(kbd, arg);
+- return 0;
++ break;
+
+ /*
+ * A process can indicate its willingness to accept signals
+@@ -688,16 +724,17 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ case KDSIGACCEPT:
+ {
+ if (!perm || !capable(CAP_KILL))
+- return -EPERM;
++ goto eperm;
+ if (!valid_signal(arg) || arg < 1 || arg == SIGKILL)
+- return -EINVAL;
+-
+- spin_lock_irq(&vt_spawn_con.lock);
+- put_pid(vt_spawn_con.pid);
+- vt_spawn_con.pid = get_pid(task_pid(current));
+- vt_spawn_con.sig = arg;
+- spin_unlock_irq(&vt_spawn_con.lock);
+- return 0;
++ ret = -EINVAL;
++ else {
++ spin_lock_irq(&vt_spawn_con.lock);
++ put_pid(vt_spawn_con.pid);
++ vt_spawn_con.pid = get_pid(task_pid(current));
++ vt_spawn_con.sig = arg;
++ spin_unlock_irq(&vt_spawn_con.lock);
++ }
++ break;
+ }
+
+ case VT_SETMODE:
+@@ -705,11 +742,15 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ struct vt_mode tmp;
+
+ if (!perm)
+- return -EPERM;
+- if (copy_from_user(&tmp, up, sizeof(struct vt_mode)))
+- return -EFAULT;
+- if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS)
+- return -EINVAL;
++ goto eperm;
++ if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) {
++ ret = -EFAULT;
++ goto out;
++ }
++ if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) {
++ ret = -EINVAL;
++ goto out;
++ }
+ acquire_console_sem();
+ vc->vt_mode = tmp;
+ /* the frsig is ignored, so we set it to 0 */
+@@ -719,7 +760,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ /* no switch is required -- saw at shade.msu.ru */
+ vc->vt_newvt = -1;
+ release_console_sem();
+- return 0;
++ break;
+ }
+
+ case VT_GETMODE:
+@@ -732,7 +773,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ release_console_sem();
+
+ rc = copy_to_user(up, &tmp, sizeof(struct vt_mode));
+- return rc ? -EFAULT : 0;
++ if (rc)
++ ret = -EFAULT;
++ break;
+ }
+
+ /*
+@@ -746,12 +789,16 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ unsigned short state, mask;
+
+ if (put_user(fg_console + 1, &vtstat->v_active))
+- return -EFAULT;
+- state = 1; /* /dev/tty0 is always open */
+- for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
+- if (VT_IS_IN_USE(i))
+- state |= mask;
+- return put_user(state, &vtstat->v_state);
++ ret = -EFAULT;
++ else {
++ state = 1; /* /dev/tty0 is always open */
++ for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask;
++ ++i, mask <<= 1)
++ if (VT_IS_IN_USE(i))
++ state |= mask;
++ ret = put_user(state, &vtstat->v_state);
++ }
++ break;
+ }
+
+ /*
+@@ -771,27 +818,31 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ */
+ case VT_ACTIVATE:
+ if (!perm)
+- return -EPERM;
++ goto eperm;
+ if (arg == 0 || arg > MAX_NR_CONSOLES)
+- return -ENXIO;
+- arg--;
+- acquire_console_sem();
+- i = vc_allocate(arg);
+- release_console_sem();
+- if (i)
+- return i;
+- set_console(arg);
+- return 0;
++ ret = -ENXIO;
++ else {
++ arg--;
++ acquire_console_sem();
++ ret = vc_allocate(arg);
++ release_console_sem();
++ if (ret)
++ break;
++ set_console(arg);
++ }
++ break;
+
+ /*
+ * wait until the specified VT has been activated
+ */
+ case VT_WAITACTIVE:
+ if (!perm)
+- return -EPERM;
++ goto eperm;
+ if (arg == 0 || arg > MAX_NR_CONSOLES)
+- return -ENXIO;
+- return vt_waitactive(arg-1);
++ ret = -ENXIO;
++ else
++ ret = vt_waitactive(arg - 1);
++ break;
+
+ /*
+ * If a vt is under process control, the kernel will not switch to it
+@@ -805,10 +856,12 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ */
+ case VT_RELDISP:
+ if (!perm)
+- return -EPERM;
+- if (vc->vt_mode.mode != VT_PROCESS)
+- return -EINVAL;
++ goto eperm;
+
++ if (vc->vt_mode.mode != VT_PROCESS) {
++ ret = -EINVAL;
++ break;
++ }
+ /*
+ * Switching-from response
+ */
+@@ -829,10 +882,10 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ int newvt;
+ newvt = vc->vt_newvt;
+ vc->vt_newvt = -1;
+- i = vc_allocate(newvt);
+- if (i) {
++ ret = vc_allocate(newvt);
++ if (ret) {
+ release_console_sem();
+- return i;
++ break;
+ }
+ /*
+ * When we actually do the console switch,
+@@ -841,31 +894,27 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ */
+ complete_change_console(vc_cons[newvt].d);
+ }
+- }
+-
+- /*
+- * Switched-to response
+- */
+- else
+- {
++ } else {
++ /*
++ * Switched-to response
++ */
+ /*
+ * If it's just an ACK, ignore it
+ */
+- if (arg != VT_ACKACQ) {
+- release_console_sem();
+- return -EINVAL;
+- }
++ if (arg != VT_ACKACQ)
++ ret = -EINVAL;
+ }
+ release_console_sem();
+-
+- return 0;
++ break;
+
+ /*
+ * Disallocate memory associated to VT (but leave VT1)
+ */
+ case VT_DISALLOCATE:
+- if (arg > MAX_NR_CONSOLES)
+- return -ENXIO;
++ if (arg > MAX_NR_CONSOLES) {
++ ret = -ENXIO;
++ break;
++ }
+ if (arg == 0) {
+ /* deallocate all unused consoles, but leave 0 */
+ acquire_console_sem();
+@@ -877,14 +926,14 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ /* deallocate a single console, if possible */
+ arg--;
+ if (VT_BUSY(arg))
+- return -EBUSY;
+- if (arg) { /* leave 0 */
++ ret = -EBUSY;
++ else if (arg) { /* leave 0 */
+ acquire_console_sem();
+ vc_deallocate(arg);
+ release_console_sem();
+ }
+ }
+- return 0;
++ break;
+
+ case VT_RESIZE:
+ {
+@@ -893,21 +942,21 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+
+ ushort ll,cc;
+ if (!perm)
+- return -EPERM;
++ goto eperm;
+ if (get_user(ll, &vtsizes->v_rows) ||
+ get_user(cc, &vtsizes->v_cols))
+- return -EFAULT;
+-
+- for (i = 0; i < MAX_NR_CONSOLES; i++) {
+- vc = vc_cons[i].d;
++ ret = -EFAULT;
++ else {
++ for (i = 0; i < MAX_NR_CONSOLES; i++) {
++ vc = vc_cons[i].d;
+
+- if (vc) {
+- vc->vc_resize_user = 1;
+- vc_lock_resize(vc_cons[i].d, cc, ll);
++ if (vc) {
++ vc->vc_resize_user = 1;
++ vc_lock_resize(vc_cons[i].d, cc, ll);
++ }
+ }
+ }
+-
+- return 0;
++ break;
+ }
+
+ case VT_RESIZEX:
+@@ -915,10 +964,13 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ struct vt_consize __user *vtconsize = up;
+ ushort ll,cc,vlin,clin,vcol,ccol;
+ if (!perm)
+- return -EPERM;
++ goto eperm;
+ if (!access_ok(VERIFY_READ, vtconsize,
+- sizeof(struct vt_consize)))
+- return -EFAULT;
++ sizeof(struct vt_consize))) {
++ ret = -EFAULT;
++ break;
++ }
++ /* FIXME: Should check the copies properly */
+ __get_user(ll, &vtconsize->v_rows);
+ __get_user(cc, &vtconsize->v_cols);
+ __get_user(vlin, &vtconsize->v_vlin);
+@@ -928,21 +980,28 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ vlin = vlin ? vlin : vc->vc_scan_lines;
+ if (clin) {
+ if (ll) {
+- if (ll != vlin/clin)
+- return -EINVAL; /* Parameters don't add up */
++ if (ll != vlin/clin) {
++ /* Parameters don't add up */
++ ret = -EINVAL;
++ break;
++ }
+ } else
+ ll = vlin/clin;
+ }
+ if (vcol && ccol) {
+ if (cc) {
+- if (cc != vcol/ccol)
+- return -EINVAL;
++ if (cc != vcol/ccol) {
++ ret = -EINVAL;
++ break;
++ }
+ } else
+ cc = vcol/ccol;
+ }
+
+- if (clin > 32)
+- return -EINVAL;
++ if (clin > 32) {
++ ret = -EINVAL;
++ break;
++ }
+
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ if (!vc_cons[i].d)
+@@ -956,19 +1015,20 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ vc_resize(vc_cons[i].d, cc, ll);
+ release_console_sem();
+ }
+- return 0;
++ break;
+ }
+
+ case PIO_FONT: {
+ if (!perm)
+- return -EPERM;
++ goto eperm;
+ op.op = KD_FONT_OP_SET;
+ op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */
+ op.width = 8;
+ op.height = 0;
+ op.charcount = 256;
+ op.data = up;
+- return con_font_op(vc_cons[fg_console].d, &op);
++ ret = con_font_op(vc_cons[fg_console].d, &op);
++ break;
+ }
+
+ case GIO_FONT: {
+@@ -978,100 +1038,124 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
+ op.height = 32;
+ op.charcount = 256;
+ op.data = up;
+- return con_font_op(vc_cons[fg_console].d, &op);
++ ret = con_font_op(vc_cons[fg_console].d, &op);
++ break;
+ }
+
+ case PIO_CMAP:
+ if (!perm)
+- return -EPERM;
+- return con_set_cmap(up);
++ ret = -EPERM;
++ else
++ ret = con_set_cmap(up);
++ break;
+
+ case GIO_CMAP:
+- return con_get_cmap(up);
++ ret = con_get_cmap(up);
++ break;
+
+ case PIO_FONTX:
+ case GIO_FONTX:
+- return do_fontx_ioctl(cmd, up, perm, &op);
++ ret = do_fontx_ioctl(cmd, up, perm, &op);
++ break;
+
+ case PIO_FONTRESET:
+ {
+ if (!perm)
+- return -EPERM;
++ goto eperm;
+
+ #ifdef BROKEN_GRAPHICS_PROGRAMS
+ /* With BROKEN_GRAPHICS_PROGRAMS defined, the default
+ font is not saved. */
+- return -ENOSYS;
++ ret = -ENOSYS;
++ break;
+ #else
+ {
+ op.op = KD_FONT_OP_SET_DEFAULT;
+ op.data = NULL;
+- i = con_font_op(vc_cons[fg_console].d, &op);
+- if (i)
+- return i;
++ ret = con_font_op(vc_cons[fg_console].d, &op);
++ if (ret)
++ break;
+ con_set_default_unimap(vc_cons[fg_console].d);
+- return 0;
++ break;
+ }
+ #endif
+ }
+
+ case KDFONTOP: {
+- if (copy_from_user(&op, up, sizeof(op)))
+- return -EFAULT;
++ if (copy_from_user(&op, up, sizeof(op))) {
++ ret = -EFAULT;
++ break;
++ }
+ if (!perm && op.op != KD_FONT_OP_GET)
+- return -EPERM;
+- i = con_font_op(vc, &op);
+- if (i) return i;
++ goto eperm;
++ ret = con_font_op(vc, &op);
++ if (ret)
++ break;
+ if (copy_to_user(up, &op, sizeof(op)))
+- return -EFAULT;
+- return 0;
++ ret = -EFAULT;
++ break;
+ }
+
+ case PIO_SCRNMAP:
+ if (!perm)
+- return -EPERM;
+- return con_set_trans_old(up);
++ ret = -EPERM;
++ else
++ ret = con_set_trans_old(up);
++ break;
+
+ case GIO_SCRNMAP:
+- return con_get_trans_old(up);
++ ret = con_get_trans_old(up);
++ break;
+
+ case PIO_UNISCRNMAP:
+ if (!perm)
+- return -EPERM;
+- return con_set_trans_new(up);
++ ret = -EPERM;
++ else
++ ret = con_set_trans_new(up);
++ break;
+
+ case GIO_UNISCRNMAP:
+- return con_get_trans_new(up);
++ ret = con_get_trans_new(up);
++ break;
+
+ case PIO_UNIMAPCLR:
+ { struct unimapinit ui;
+ if (!perm)
+- return -EPERM;
+- i = copy_from_user(&ui, up, sizeof(struct unimapinit));
+- if (i) return -EFAULT;
+- con_clear_unimap(vc, &ui);
+- return 0;
++ goto eperm;
++ ret = copy_from_user(&ui, up, sizeof(struct unimapinit));
++ if (!ret)
++ con_clear_unimap(vc, &ui);
++ break;
+ }
+
+ case PIO_UNIMAP:
+ case GIO_UNIMAP:
+- return do_unimap_ioctl(cmd, up, perm, vc);
++ ret = do_unimap_ioctl(cmd, up, perm, vc);
++ break;
+
+ case VT_LOCKSWITCH:
+ if (!capable(CAP_SYS_TTY_CONFIG))
+- return -EPERM;
++ goto eperm;
+ vt_dont_switch = 1;
+- return 0;
++ break;
+ case VT_UNLOCKSWITCH:
+ if (!capable(CAP_SYS_TTY_CONFIG))
+- return -EPERM;
++ goto eperm;
+ vt_dont_switch = 0;
+- return 0;
++ break;
+ case VT_GETHIFONTMASK:
+- return put_user(vc->vc_hi_font_mask, (unsigned short __user *)arg);
++ ret = put_user(vc->vc_hi_font_mask,
++ (unsigned short __user *)arg);
++ break;
+ default:
+- return -ENOIOCTLCMD;
++ ret = -ENOIOCTLCMD;
+ }
++out:
++ unlock_kernel();
++ return ret;
++eperm:
++ ret = -EPERM;
++ goto out;
+ }
+
+ /*
+diff --git a/drivers/char/xilinx_hwicap/buffer_icap.c b/drivers/char/xilinx_hwicap/buffer_icap.c
+index f577dae..aa7f796 100644
+--- a/drivers/char/xilinx_hwicap/buffer_icap.c
++++ b/drivers/char/xilinx_hwicap/buffer_icap.c
+@@ -74,7 +74,7 @@
+
+ /**
+ * buffer_icap_get_status - Get the contents of the status register.
+- * @base_address: is the base address of the device
++ * @drvdata: a pointer to the drvdata.
+ *
+ * The status register contains the ICAP status and the done bit.
+ *
+@@ -88,9 +88,9 @@
+ * D1 - Always 1
+ * D0 - Done bit
+ **/
+-static inline u32 buffer_icap_get_status(void __iomem *base_address)
++u32 buffer_icap_get_status(struct hwicap_drvdata *drvdata)
+ {
+- return in_be32(base_address + XHI_STATUS_REG_OFFSET);
++ return in_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET);
+ }
+
+ /**
+@@ -117,20 +117,8 @@ static inline u32 buffer_icap_get_bram(void __iomem *base_address,
+ **/
+ static inline bool buffer_icap_busy(void __iomem *base_address)
+ {
+- return (buffer_icap_get_status(base_address) & 1) == XHI_NOT_FINISHED;
+-}
+-
+-/**
+- * buffer_icap_busy - Return true if the icap device is not busy
+- * @base_address: is the base address of the device
+- *
+- * The queries the low order bit of the status register, which
+- * indicates whether the current configuration or readback operation
+- * has completed.
+- **/
+-static inline bool buffer_icap_done(void __iomem *base_address)
+-{
+- return (buffer_icap_get_status(base_address) & 1) == XHI_FINISHED;
++ u32 status = in_be32(base_address + XHI_STATUS_REG_OFFSET);
++ return (status & 1) == XHI_NOT_FINISHED;
+ }
+
+ /**
+diff --git a/drivers/char/xilinx_hwicap/buffer_icap.h b/drivers/char/xilinx_hwicap/buffer_icap.h
+index 0318495..c5b1840 100644
+--- a/drivers/char/xilinx_hwicap/buffer_icap.h
++++ b/drivers/char/xilinx_hwicap/buffer_icap.h
+@@ -44,8 +44,6 @@
+ #include <asm/io.h>
+ #include "xilinx_hwicap.h"
+
+-void buffer_icap_reset(struct hwicap_drvdata *drvdata);
+-
+ /* Loads a partial bitstream from system memory. */
+ int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,
+ u32 Size);
+@@ -54,4 +52,7 @@ int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,
+ int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data,
+ u32 Size);
+
++u32 buffer_icap_get_status(struct hwicap_drvdata *drvdata);
++void buffer_icap_reset(struct hwicap_drvdata *drvdata);
++
+ #endif
+diff --git a/drivers/char/xilinx_hwicap/fifo_icap.c b/drivers/char/xilinx_hwicap/fifo_icap.c
+index 6f45dbd..776b505 100644
+--- a/drivers/char/xilinx_hwicap/fifo_icap.c
++++ b/drivers/char/xilinx_hwicap/fifo_icap.c
+@@ -78,13 +78,6 @@
+ #define XHI_CR_READ_MASK 0x00000002 /* Read from ICAP to FIFO */
+ #define XHI_CR_WRITE_MASK 0x00000001 /* Write from FIFO to ICAP */
+
+-/* Status Register (SR) */
+-#define XHI_SR_CFGERR_N_MASK 0x00000100 /* Config Error Mask */
+-#define XHI_SR_DALIGN_MASK 0x00000080 /* Data Alignment Mask */
+-#define XHI_SR_RIP_MASK 0x00000040 /* Read back Mask */
+-#define XHI_SR_IN_ABORT_N_MASK 0x00000020 /* Select Map Abort Mask */
+-#define XHI_SR_DONE_MASK 0x00000001 /* Done bit Mask */
+-
+
+ #define XHI_WFO_MAX_VACANCY 1024 /* Max Write FIFO Vacancy, in words */
+ #define XHI_RFO_MAX_OCCUPANCY 256 /* Max Read FIFO Occupancy, in words */
+@@ -152,13 +145,35 @@ static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata)
+ }
+
+ /**
++ * fifo_icap_get_status - Get the contents of the status register.
++ * @drvdata: a pointer to the drvdata.
++ *
++ * The status register contains the ICAP status and the done bit.
++ *
++ * D8 - cfgerr
++ * D7 - dalign
++ * D6 - rip
++ * D5 - in_abort_l
++ * D4 - Always 1
++ * D3 - Always 1
++ * D2 - Always 1
++ * D1 - Always 1
++ * D0 - Done bit
++ **/
++u32 fifo_icap_get_status(struct hwicap_drvdata *drvdata)
++{
++ u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET);
++ dev_dbg(drvdata->dev, "Getting status = %x\n", status);
++ return status;
++}
++
++/**
+ * fifo_icap_busy - Return true if the ICAP is still processing a transaction.
+ * @drvdata: a pointer to the drvdata.
+ **/
+ static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata)
+ {
+ u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET);
+- dev_dbg(drvdata->dev, "Getting status = %x\n", status);
+ return (status & XHI_SR_DONE_MASK) ? 0 : 1;
+ }
+
+diff --git a/drivers/char/xilinx_hwicap/fifo_icap.h b/drivers/char/xilinx_hwicap/fifo_icap.h
+index 4d3068d..ffabd3b 100644
+--- a/drivers/char/xilinx_hwicap/fifo_icap.h
++++ b/drivers/char/xilinx_hwicap/fifo_icap.h
+@@ -56,6 +56,7 @@ int fifo_icap_set_configuration(
+ u32 *FrameBuffer,
+ u32 NumWords);
+
++u32 fifo_icap_get_status(struct hwicap_drvdata *drvdata);
+ void fifo_icap_reset(struct hwicap_drvdata *drvdata);
+ void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata);
+
+diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+index 2284fa2..dfe6907 100644
+--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
++++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+@@ -36,7 +36,7 @@
+ *****************************************************************************/
+
+ /*
+- * This is the code behind /dev/xilinx_icap -- it allows a user-space
++ * This is the code behind /dev/icap* -- it allows a user-space
+ * application to use the Xilinx ICAP subsystem.
+ *
+ * The following operations are possible:
+@@ -67,7 +67,7 @@
+ * user-space application code that uses this device. The simplest
+ * way to use this interface is simply:
+ *
+- * cp foo.bit /dev/xilinx_icap
++ * cp foo.bit /dev/icap0
+ *
+ * Note that unless foo.bit is an appropriately constructed partial
+ * bitstream, this has a high likelyhood of overwriting the design
+@@ -105,18 +105,14 @@
+ #include "buffer_icap.h"
+ #include "fifo_icap.h"
+
+-#define DRIVER_NAME "xilinx_icap"
++#define DRIVER_NAME "icap"
+
+ #define HWICAP_REGS (0x10000)
+
+-/* dynamically allocate device number */
+-static int xhwicap_major;
+-static int xhwicap_minor;
++#define XHWICAP_MAJOR 259
++#define XHWICAP_MINOR 0
+ #define HWICAP_DEVICES 1
+
+-module_param(xhwicap_major, int, S_IRUGO);
+-module_param(xhwicap_minor, int, S_IRUGO);
+-
+ /* An array, which is set to true when the device is registered. */
+ static bool probed_devices[HWICAP_DEVICES];
+ static struct mutex icap_sem;
+@@ -250,8 +246,26 @@ static int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata,
+ * Create the data to be written to the ICAP.
+ */
+ buffer[index++] = XHI_DUMMY_PACKET;
++ buffer[index++] = XHI_NOOP_PACKET;
+ buffer[index++] = XHI_SYNC_PACKET;
+ buffer[index++] = XHI_NOOP_PACKET;
++ buffer[index++] = XHI_NOOP_PACKET;
++
++ /*
++ * Write the data to the FIFO and initiate the transfer of data present
++ * in the FIFO to the ICAP device.
++ */
++ status = drvdata->config->set_configuration(drvdata,
++ &buffer[0], index);
++ if (status)
++ return status;
++
++ /* If the syncword was not found, then we need to start over. */
++ status = drvdata->config->get_status(drvdata);
++ if ((status & XHI_SR_DALIGN_MASK) != XHI_SR_DALIGN_MASK)
++ return -EIO;
++
++ index = 0;
+ buffer[index++] = hwicap_type_1_read(reg) | 1;
+ buffer[index++] = XHI_NOOP_PACKET;
+ buffer[index++] = XHI_NOOP_PACKET;
+@@ -587,7 +601,7 @@ static int __devinit hwicap_setup(struct device *dev, int id,
+ probed_devices[id] = 1;
+ mutex_unlock(&icap_sem);
+
+- devt = MKDEV(xhwicap_major, xhwicap_minor + id);
++ devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR + id);
+
+ drvdata = kzalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL);
+ if (!drvdata) {
+@@ -664,12 +678,14 @@ static int __devinit hwicap_setup(struct device *dev, int id,
+ static struct hwicap_driver_config buffer_icap_config = {
+ .get_configuration = buffer_icap_get_configuration,
+ .set_configuration = buffer_icap_set_configuration,
++ .get_status = buffer_icap_get_status,
+ .reset = buffer_icap_reset,
+ };
+
+ static struct hwicap_driver_config fifo_icap_config = {
+ .get_configuration = fifo_icap_get_configuration,
+ .set_configuration = fifo_icap_set_configuration,
++ .get_status = fifo_icap_get_status,
+ .reset = fifo_icap_reset,
+ };
+
+@@ -690,7 +706,7 @@ static int __devexit hwicap_remove(struct device *dev)
+ dev_set_drvdata(dev, NULL);
+
+ mutex_lock(&icap_sem);
+- probed_devices[MINOR(dev->devt)-xhwicap_minor] = 0;
++ probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0;
+ mutex_unlock(&icap_sem);
+ return 0; /* success */
+ }
+@@ -787,7 +803,7 @@ static int __devexit hwicap_of_remove(struct of_device *op)
+ }
+
+ /* Match table for of_platform binding */
+-static const struct of_device_id __devinit hwicap_of_match[] = {
++static const struct of_device_id __devinitconst hwicap_of_match[] = {
+ { .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config},
+ { .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config},
+ {},
+@@ -830,23 +846,12 @@ static int __init hwicap_module_init(void)
+ icap_class = class_create(THIS_MODULE, "xilinx_config");
+ mutex_init(&icap_sem);
+
+- if (xhwicap_major) {
+- devt = MKDEV(xhwicap_major, xhwicap_minor);
+- retval = register_chrdev_region(
+- devt,
+- HWICAP_DEVICES,
+- DRIVER_NAME);
+- if (retval < 0)
+- return retval;
+- } else {
+- retval = alloc_chrdev_region(&devt,
+- xhwicap_minor,
+- HWICAP_DEVICES,
+- DRIVER_NAME);
+- if (retval < 0)
+- return retval;
+- xhwicap_major = MAJOR(devt);
+- }
++ devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR);
++ retval = register_chrdev_region(devt,
++ HWICAP_DEVICES,
++ DRIVER_NAME);
++ if (retval < 0)
++ return retval;
+
+ retval = platform_driver_register(&hwicap_platform_driver);
+
+@@ -871,7 +876,7 @@ static int __init hwicap_module_init(void)
+
+ static void __exit hwicap_module_cleanup(void)
+ {
+- dev_t devt = MKDEV(xhwicap_major, xhwicap_minor);
++ dev_t devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR);
+
+ class_destroy(icap_class);
+
+diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h
+index 405fee7..1f9c8b0 100644
+--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.h
++++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h
+@@ -65,10 +65,27 @@ struct hwicap_drvdata {
+ };
+
+ struct hwicap_driver_config {
++ /* Read configuration data given by size into the data buffer.
++ Return 0 if successful. */
+ int (*get_configuration)(struct hwicap_drvdata *drvdata, u32 *data,
+ u32 size);
++ /* Write configuration data given by size from the data buffer.
++ Return 0 if successful. */
+ int (*set_configuration)(struct hwicap_drvdata *drvdata, u32 *data,
+ u32 size);
++ /* Get the status register, bit pattern given by:
++ * D8 - 0 = configuration error
++ * D7 - 1 = alignment found
++ * D6 - 1 = readback in progress
++ * D5 - 0 = abort in progress
++ * D4 - Always 1
++ * D3 - Always 1
++ * D2 - Always 1
++ * D1 - Always 1
++ * D0 - 1 = operation completed
++ */
++ u32 (*get_status)(struct hwicap_drvdata *drvdata);
++ /* Reset the hw */
+ void (*reset)(struct hwicap_drvdata *drvdata);
+ };
+
+@@ -163,6 +180,13 @@ struct config_registers {
+ /* Constant to use for CRC check when CRC has been disabled */
+ #define XHI_DISABLED_AUTO_CRC 0x0000DEFCUL
+
++/* Meanings of the bits returned by get_status */
++#define XHI_SR_CFGERR_N_MASK 0x00000100 /* Config Error Mask */
++#define XHI_SR_DALIGN_MASK 0x00000080 /* Data Alignment Mask */
++#define XHI_SR_RIP_MASK 0x00000040 /* Read back Mask */
++#define XHI_SR_IN_ABORT_N_MASK 0x00000020 /* Select Map Abort Mask */
++#define XHI_SR_DONE_MASK 0x00000001 /* Done bit Mask */
++
+ /**
+ * hwicap_type_1_read - Generates a Type 1 read packet header.
+ * @reg: is the address of the register to be read back.
+diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
+index a522254..1525882 100644
+--- a/drivers/clocksource/Makefile
++++ b/drivers/clocksource/Makefile
+@@ -1,3 +1,4 @@
++obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
+ obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o
+ obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o
+ obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o
+diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
+new file mode 100644
+index 0000000..f450588
+--- /dev/null
++++ b/drivers/clocksource/tcb_clksrc.c
+@@ -0,0 +1,302 @@
++#include <linux/init.h>
++#include <linux/clocksource.h>
++#include <linux/clockchips.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/ioport.h>
++#include <linux/io.h>
++#include <linux/platform_device.h>
++#include <linux/atmel_tc.h>
++
++
++/*
++ * We're configured to use a specific TC block, one that's not hooked
++ * up to external hardware, to provide a time solution:
++ *
++ * - Two channels combine to create a free-running 32 bit counter
++ * with a base rate of 5+ MHz, packaged as a clocksource (with
++ * resolution better than 200 nsec).
++ *
++ * - The third channel may be used to provide a 16-bit clockevent
++ * source, used in either periodic or oneshot mode. This runs
++ * at 32 KiHZ, and can handle delays of up to two seconds.
++ *
++ * A boot clocksource and clockevent source are also currently needed,
++ * unless the relevant platforms (ARM/AT91, AVR32/AT32) are changed so
++ * this code can be used when init_timers() is called, well before most
++ * devices are set up. (Some low end AT91 parts, which can run uClinux,
++ * have only the timers in one TC block... they currently don't support
++ * the tclib code, because of that initialization issue.)
++ *
++ * REVISIT behavior during system suspend states... we should disable
++ * all clocks and save the power. Easily done for clockevent devices,
++ * but clocksources won't necessarily get the needed notifications.
++ * For deeper system sleep states, this will be mandatory...
++ */
++
++static void __iomem *tcaddr;
++
++static cycle_t tc_get_cycles(void)
++{
++ unsigned long flags;
++ u32 lower, upper;
++
++ raw_local_irq_save(flags);
++ do {
++ upper = __raw_readl(tcaddr + ATMEL_TC_REG(1, CV));
++ lower = __raw_readl(tcaddr + ATMEL_TC_REG(0, CV));
++ } while (upper != __raw_readl(tcaddr + ATMEL_TC_REG(1, CV)));
++
++ raw_local_irq_restore(flags);
++ return (upper << 16) | lower;
++}
++
++static struct clocksource clksrc = {
++ .name = "tcb_clksrc",
++ .rating = 200,
++ .read = tc_get_cycles,
++ .mask = CLOCKSOURCE_MASK(32),
++ .shift = 18,
++ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
++};
++
++#ifdef CONFIG_GENERIC_CLOCKEVENTS
++
++struct tc_clkevt_device {
++ struct clock_event_device clkevt;
++ struct clk *clk;
++ void __iomem *regs;
++};
++
++static struct tc_clkevt_device *to_tc_clkevt(struct clock_event_device *clkevt)
++{
++ return container_of(clkevt, struct tc_clkevt_device, clkevt);
++}
++
++/* For now, we always use the 32K clock ... this optimizes for NO_HZ,
++ * because using one of the divided clocks would usually mean the
++ * tick rate can never be less than several dozen Hz (vs 0.5 Hz).
++ *
++ * A divided clock could be good for high resolution timers, since
++ * 30.5 usec resolution can seem "low".
++ */
++static u32 timer_clock;
++
++static void tc_mode(enum clock_event_mode m, struct clock_event_device *d)
++{
++ struct tc_clkevt_device *tcd = to_tc_clkevt(d);
++ void __iomem *regs = tcd->regs;
++
++ if (tcd->clkevt.mode == CLOCK_EVT_MODE_PERIODIC
++ || tcd->clkevt.mode == CLOCK_EVT_MODE_ONESHOT) {
++ __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR));
++ __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
++ clk_disable(tcd->clk);
++ }
++
++ switch (m) {
++
++ /* By not making the gentime core emulate periodic mode on top
++ * of oneshot, we get lower overhead and improved accuracy.
++ */
++ case CLOCK_EVT_MODE_PERIODIC:
++ clk_enable(tcd->clk);
++
++ /* slow clock, count up to RC, then irq and restart */
++ __raw_writel(timer_clock
++ | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
++ regs + ATMEL_TC_REG(2, CMR));
++ __raw_writel((32768 + HZ/2) / HZ, tcaddr + ATMEL_TC_REG(2, RC));
++
++ /* Enable clock and interrupts on RC compare */
++ __raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
++
++ /* go go gadget! */
++ __raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
++ regs + ATMEL_TC_REG(2, CCR));
++ break;
++
++ case CLOCK_EVT_MODE_ONESHOT:
++ clk_enable(tcd->clk);
++
++ /* slow clock, count up to RC, then irq and stop */
++ __raw_writel(timer_clock | ATMEL_TC_CPCSTOP
++ | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
++ regs + ATMEL_TC_REG(2, CMR));
++ __raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
++
++ /* set_next_event() configures and starts the timer */
++ break;
++
++ default:
++ break;
++ }
++}
++
++static int tc_next_event(unsigned long delta, struct clock_event_device *d)
++{
++ __raw_writel(delta, tcaddr + ATMEL_TC_REG(2, RC));
++
++ /* go go gadget! */
++ __raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
++ tcaddr + ATMEL_TC_REG(2, CCR));
++ return 0;
++}
++
++static struct tc_clkevt_device clkevt = {
++ .clkevt = {
++ .name = "tc_clkevt",
++ .features = CLOCK_EVT_FEAT_PERIODIC
++ | CLOCK_EVT_FEAT_ONESHOT,
++ .shift = 32,
++ /* Should be lower than at91rm9200's system timer */
++ .rating = 125,
++ .cpumask = CPU_MASK_CPU0,
++ .set_next_event = tc_next_event,
++ .set_mode = tc_mode,
++ },
++};
++
++static irqreturn_t ch2_irq(int irq, void *handle)
++{
++ struct tc_clkevt_device *dev = handle;
++ unsigned int sr;
++
++ sr = __raw_readl(dev->regs + ATMEL_TC_REG(2, SR));
++ if (sr & ATMEL_TC_CPCS) {
++ dev->clkevt.event_handler(&dev->clkevt);
++ return IRQ_HANDLED;
++ }
++
++ return IRQ_NONE;
++}
++
++static struct irqaction tc_irqaction = {
++ .name = "tc_clkevt",
++ .flags = IRQF_TIMER | IRQF_DISABLED,
++ .handler = ch2_irq,
++};
++
++static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
++{
++ struct clk *t2_clk = tc->clk[2];
++ int irq = tc->irq[2];
++
++ clkevt.regs = tc->regs;
++ clkevt.clk = t2_clk;
++ tc_irqaction.dev_id = &clkevt;
++
++ timer_clock = clk32k_divisor_idx;
++
++ clkevt.clkevt.mult = div_sc(32768, NSEC_PER_SEC, clkevt.clkevt.shift);
++ clkevt.clkevt.max_delta_ns
++ = clockevent_delta2ns(0xffff, &clkevt.clkevt);
++ clkevt.clkevt.min_delta_ns = clockevent_delta2ns(1, &clkevt.clkevt) + 1;
++
++ setup_irq(irq, &tc_irqaction);
++
++ clockevents_register_device(&clkevt.clkevt);
++}
++
++#else /* !CONFIG_GENERIC_CLOCKEVENTS */
++
++static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
++{
++ /* NOTHING */
++}
++
++#endif
++
++static int __init tcb_clksrc_init(void)
++{
++ static char bootinfo[] __initdata
++ = KERN_DEBUG "%s: tc%d at %d.%03d MHz\n";
++
++ struct platform_device *pdev;
++ struct atmel_tc *tc;
++ struct clk *t0_clk;
++ u32 rate, divided_rate = 0;
++ int best_divisor_idx = -1;
++ int clk32k_divisor_idx = -1;
++ int i;
++
++ tc = atmel_tc_alloc(CONFIG_ATMEL_TCB_CLKSRC_BLOCK, clksrc.name);
++ if (!tc) {
++ pr_debug("can't alloc TC for clocksource\n");
++ return -ENODEV;
++ }
++ tcaddr = tc->regs;
++ pdev = tc->pdev;
++
++ t0_clk = tc->clk[0];
++ clk_enable(t0_clk);
++
++ /* How fast will we be counting? Pick something over 5 MHz. */
++ rate = (u32) clk_get_rate(t0_clk);
++ for (i = 0; i < 5; i++) {
++ unsigned divisor = atmel_tc_divisors[i];
++ unsigned tmp;
++
++ /* remember 32 KiHz clock for later */
++ if (!divisor) {
++ clk32k_divisor_idx = i;
++ continue;
++ }
++
++ tmp = rate / divisor;
++ pr_debug("TC: %u / %-3u [%d] --> %u\n", rate, divisor, i, tmp);
++ if (best_divisor_idx > 0) {
++ if (tmp < 5 * 1000 * 1000)
++ continue;
++ }
++ divided_rate = tmp;
++ best_divisor_idx = i;
++ }
++
++ clksrc.mult = clocksource_hz2mult(divided_rate, clksrc.shift);
++
++ printk(bootinfo, clksrc.name, CONFIG_ATMEL_TCB_CLKSRC_BLOCK,
++ divided_rate / 1000000,
++ ((divided_rate + 500000) % 1000000) / 1000);
++
++ /* tclib will give us three clocks no matter what the
++ * underlying platform supports.
++ */
++ clk_enable(tc->clk[1]);
++
++ /* channel 0: waveform mode, input mclk/8, clock TIOA0 on overflow */
++ __raw_writel(best_divisor_idx /* likely divide-by-8 */
++ | ATMEL_TC_WAVE
++ | ATMEL_TC_WAVESEL_UP /* free-run */
++ | ATMEL_TC_ACPA_SET /* TIOA0 rises at 0 */
++ | ATMEL_TC_ACPC_CLEAR, /* (duty cycle 50%) */
++ tcaddr + ATMEL_TC_REG(0, CMR));
++ __raw_writel(0x0000, tcaddr + ATMEL_TC_REG(0, RA));
++ __raw_writel(0x8000, tcaddr + ATMEL_TC_REG(0, RC));
++ __raw_writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR)); /* no irqs */
++ __raw_writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR));
++
++ /* channel 1: waveform mode, input TIOA0 */
++ __raw_writel(ATMEL_TC_XC1 /* input: TIOA0 */
++ | ATMEL_TC_WAVE
++ | ATMEL_TC_WAVESEL_UP, /* free-run */
++ tcaddr + ATMEL_TC_REG(1, CMR));
++ __raw_writel(0xff, tcaddr + ATMEL_TC_REG(1, IDR)); /* no irqs */
++ __raw_writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(1, CCR));
++
++ /* chain channel 0 to channel 1, then reset all the timers */
++ __raw_writel(ATMEL_TC_TC1XC1S_TIOA0, tcaddr + ATMEL_TC_BMR);
++ __raw_writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);
++
++ /* and away we go! */
++ clocksource_register(&clksrc);
++
++ /* channel 2: periodic and oneshot timer support */
++ setup_clkevents(tc, clk32k_divisor_idx);
++
++ return 0;
++}
++arch_initcall(tcb_clksrc_init);
+diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
+index c159ae6..5f076ae 100644
+--- a/drivers/cpufreq/Kconfig
++++ b/drivers/cpufreq/Kconfig
+@@ -69,6 +69,15 @@ config CPU_FREQ_DEFAULT_GOV_PERFORMANCE
+ the frequency statically to the highest frequency supported by
+ the CPU.
+
++config CPU_FREQ_DEFAULT_GOV_POWERSAVE
++ bool "powersave"
++ depends on EMBEDDED
++ select CPU_FREQ_GOV_POWERSAVE
++ help
++ Use the CPUFreq governor 'powersave' as default. This sets
++ the frequency statically to the lowest frequency supported by
++ the CPU.
++
+ config CPU_FREQ_DEFAULT_GOV_USERSPACE
+ bool "userspace"
+ select CPU_FREQ_GOV_USERSPACE
+diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
+index 35a26a3..7fce038 100644
+--- a/drivers/cpufreq/cpufreq.c
++++ b/drivers/cpufreq/cpufreq.c
+@@ -118,9 +118,11 @@ static void handle_update(struct work_struct *work);
+ static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list);
+ static struct srcu_notifier_head cpufreq_transition_notifier_list;
+
++static bool init_cpufreq_transition_notifier_list_called;
+ static int __init init_cpufreq_transition_notifier_list(void)
+ {
+ srcu_init_notifier_head(&cpufreq_transition_notifier_list);
++ init_cpufreq_transition_notifier_list_called = true;
+ return 0;
+ }
+ pure_initcall(init_cpufreq_transition_notifier_list);
+@@ -216,7 +218,7 @@ static void cpufreq_debug_disable_ratelimit(void)
+ }
+
+ void cpufreq_debug_printk(unsigned int type, const char *prefix,
+- const char *fmt, ...)
++ const char *fmt, ...)
+ {
+ char s[256];
+ va_list args;
+@@ -378,7 +380,7 @@ static struct cpufreq_governor *__find_governor(const char *str_governor)
+ /**
+ * cpufreq_parse_governor - parse a governor string
+ */
+-static int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
++static int cpufreq_parse_governor(char *str_governor, unsigned int *policy,
+ struct cpufreq_governor **governor)
+ {
+ int err = -EINVAL;
+@@ -446,7 +448,7 @@ extern struct sysdev_class cpu_sysdev_class;
+
+ #define show_one(file_name, object) \
+ static ssize_t show_##file_name \
+-(struct cpufreq_policy * policy, char *buf) \
++(struct cpufreq_policy *policy, char *buf) \
+ { \
+ return sprintf (buf, "%u\n", policy->object); \
+ }
+@@ -465,7 +467,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
+ */
+ #define store_one(file_name, object) \
+ static ssize_t store_##file_name \
+-(struct cpufreq_policy * policy, const char *buf, size_t count) \
++(struct cpufreq_policy *policy, const char *buf, size_t count) \
+ { \
+ unsigned int ret = -EINVAL; \
+ struct cpufreq_policy new_policy; \
+@@ -490,8 +492,8 @@ store_one(scaling_max_freq,max);
+ /**
+ * show_cpuinfo_cur_freq - current CPU frequency as detected by hardware
+ */
+-static ssize_t show_cpuinfo_cur_freq (struct cpufreq_policy * policy,
+- char *buf)
++static ssize_t show_cpuinfo_cur_freq(struct cpufreq_policy *policy,
++ char *buf)
+ {
+ unsigned int cur_freq = __cpufreq_get(policy->cpu);
+ if (!cur_freq)
+@@ -503,8 +505,7 @@ static ssize_t show_cpuinfo_cur_freq (struct cpufreq_policy * policy,
+ /**
+ * show_scaling_governor - show the current policy for the specified CPU
+ */
+-static ssize_t show_scaling_governor (struct cpufreq_policy * policy,
+- char *buf)
++static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf)
+ {
+ if(policy->policy == CPUFREQ_POLICY_POWERSAVE)
+ return sprintf(buf, "powersave\n");
+@@ -519,8 +520,8 @@ static ssize_t show_scaling_governor (struct cpufreq_policy * policy,
+ /**
+ * store_scaling_governor - store policy for the specified CPU
+ */
+-static ssize_t store_scaling_governor (struct cpufreq_policy * policy,
+- const char *buf, size_t count)
++static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
++ const char *buf, size_t count)
+ {
+ unsigned int ret = -EINVAL;
+ char str_governor[16];
+@@ -554,7 +555,7 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy,
+ /**
+ * show_scaling_driver - show the cpufreq driver currently loaded
+ */
+-static ssize_t show_scaling_driver (struct cpufreq_policy * policy, char *buf)
++static ssize_t show_scaling_driver(struct cpufreq_policy *policy, char *buf)
+ {
+ return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n", cpufreq_driver->name);
+ }
+@@ -562,8 +563,8 @@ static ssize_t show_scaling_driver (struct cpufreq_policy * policy, char *buf)
+ /**
+ * show_scaling_available_governors - show the available CPUfreq governors
+ */
+-static ssize_t show_scaling_available_governors (struct cpufreq_policy *policy,
+- char *buf)
++static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy,
++ char *buf)
+ {
+ ssize_t i = 0;
+ struct cpufreq_governor *t;
+@@ -582,15 +583,13 @@ out:
+ i += sprintf(&buf[i], "\n");
+ return i;
+ }
+-/**
+- * show_affected_cpus - show the CPUs affected by each transition
+- */
+-static ssize_t show_affected_cpus (struct cpufreq_policy * policy, char *buf)
++
++static ssize_t show_cpus(cpumask_t mask, char *buf)
+ {
+ ssize_t i = 0;
+ unsigned int cpu;
+
+- for_each_cpu_mask(cpu, policy->cpus) {
++ for_each_cpu_mask(cpu, mask) {
+ if (i)
+ i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), " ");
+ i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), "%u", cpu);
+@@ -601,8 +600,27 @@ static ssize_t show_affected_cpus (struct cpufreq_policy * policy, char *buf)
+ return i;
+ }
+
++/**
++ * show_related_cpus - show the CPUs affected by each transition even if
++ * hw coordination is in use
++ */
++static ssize_t show_related_cpus(struct cpufreq_policy *policy, char *buf)
++{
++ if (cpus_empty(policy->related_cpus))
++ return show_cpus(policy->cpus, buf);
++ return show_cpus(policy->related_cpus, buf);
++}
++
++/**
++ * show_affected_cpus - show the CPUs affected by each transition
++ */
++static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf)
++{
++ return show_cpus(policy->cpus, buf);
++}
++
+ static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy,
+- const char *buf, size_t count)
++ const char *buf, size_t count)
+ {
+ unsigned int freq = 0;
+ unsigned int ret;
+@@ -645,18 +663,20 @@ define_one_ro(cpuinfo_max_freq);
+ define_one_ro(scaling_available_governors);
+ define_one_ro(scaling_driver);
+ define_one_ro(scaling_cur_freq);
++define_one_ro(related_cpus);
+ define_one_ro(affected_cpus);
+ define_one_rw(scaling_min_freq);
+ define_one_rw(scaling_max_freq);
+ define_one_rw(scaling_governor);
+ define_one_rw(scaling_setspeed);
+
+-static struct attribute * default_attrs[] = {
++static struct attribute *default_attrs[] = {
+ &cpuinfo_min_freq.attr,
+ &cpuinfo_max_freq.attr,
+ &scaling_min_freq.attr,
+ &scaling_max_freq.attr,
+ &affected_cpus.attr,
++ &related_cpus.attr,
+ &scaling_governor.attr,
+ &scaling_driver.attr,
+ &scaling_available_governors.attr,
+@@ -667,10 +687,10 @@ static struct attribute * default_attrs[] = {
+ #define to_policy(k) container_of(k,struct cpufreq_policy,kobj)
+ #define to_attr(a) container_of(a,struct freq_attr,attr)
+
+-static ssize_t show(struct kobject * kobj, struct attribute * attr ,char * buf)
++static ssize_t show(struct kobject *kobj, struct attribute *attr ,char *buf)
+ {
+- struct cpufreq_policy * policy = to_policy(kobj);
+- struct freq_attr * fattr = to_attr(attr);
++ struct cpufreq_policy *policy = to_policy(kobj);
++ struct freq_attr *fattr = to_attr(attr);
+ ssize_t ret = -EINVAL;
+ policy = cpufreq_cpu_get(policy->cpu);
+ if (!policy)
+@@ -691,11 +711,11 @@ no_policy:
+ return ret;
+ }
+
+-static ssize_t store(struct kobject * kobj, struct attribute * attr,
+- const char * buf, size_t count)
++static ssize_t store(struct kobject *kobj, struct attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct cpufreq_policy * policy = to_policy(kobj);
+- struct freq_attr * fattr = to_attr(attr);
++ struct cpufreq_policy *policy = to_policy(kobj);
++ struct freq_attr *fattr = to_attr(attr);
+ ssize_t ret = -EINVAL;
+ policy = cpufreq_cpu_get(policy->cpu);
+ if (!policy)
+@@ -716,9 +736,9 @@ no_policy:
+ return ret;
+ }
+
+-static void cpufreq_sysfs_release(struct kobject * kobj)
++static void cpufreq_sysfs_release(struct kobject *kobj)
+ {
+- struct cpufreq_policy * policy = to_policy(kobj);
++ struct cpufreq_policy *policy = to_policy(kobj);
+ dprintk("last reference is dropped\n");
+ complete(&policy->kobj_unregister);
+ }
+@@ -740,7 +760,7 @@ static struct kobj_type ktype_cpufreq = {
+ *
+ * Adds the cpufreq interface for a CPU device.
+ */
+-static int cpufreq_add_dev (struct sys_device * sys_dev)
++static int cpufreq_add_dev(struct sys_device *sys_dev)
+ {
+ unsigned int cpu = sys_dev->id;
+ int ret = 0;
+@@ -800,7 +820,6 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
+ ret = cpufreq_driver->init(policy);
+ if (ret) {
+ dprintk("initialization failed\n");
+- unlock_policy_rwsem_write(cpu);
+ goto err_out;
+ }
+ policy->user_policy.min = policy->cpuinfo.min_freq;
+@@ -823,7 +842,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
+ /* check for existing affected CPUs. They may not be aware
+ * of it due to CPU Hotplug.
+ */
+- managed_policy = cpufreq_cpu_get(j);
++ managed_policy = cpufreq_cpu_get(j); // FIXME: Where is this released? What about error paths?
+ if (unlikely(managed_policy)) {
+
+ /* Set proper policy_cpu */
+@@ -842,14 +861,11 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
+ ret = sysfs_create_link(&sys_dev->kobj,
+ &managed_policy->kobj,
+ "cpufreq");
+- if (ret) {
+- unlock_policy_rwsem_write(cpu);
++ if (ret)
+ goto err_out_driver_exit;
+- }
+
+ cpufreq_debug_enable_ratelimit();
+ ret = 0;
+- unlock_policy_rwsem_write(cpu);
+ goto err_out_driver_exit; /* call driver->exit() */
+ }
+ }
+@@ -859,33 +875,26 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
+ /* prepare interface data */
+ ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj,
+ "cpufreq");
+- if (ret) {
+- unlock_policy_rwsem_write(cpu);
++ if (ret)
+ goto err_out_driver_exit;
+- }
++
+ /* set up files for this cpu device */
+ drv_attr = cpufreq_driver->attr;
+ while ((drv_attr) && (*drv_attr)) {
+ ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
+- if (ret) {
+- unlock_policy_rwsem_write(cpu);
++ if (ret)
+ goto err_out_driver_exit;
+- }
+ drv_attr++;
+ }
+- if (cpufreq_driver->get){
++ if (cpufreq_driver->get) {
+ ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
+- if (ret) {
+- unlock_policy_rwsem_write(cpu);
++ if (ret)
+ goto err_out_driver_exit;
+- }
+ }
+- if (cpufreq_driver->target){
++ if (cpufreq_driver->target) {
+ ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
+- if (ret) {
+- unlock_policy_rwsem_write(cpu);
++ if (ret)
+ goto err_out_driver_exit;
+- }
+ }
+
+ spin_lock_irqsave(&cpufreq_driver_lock, flags);
+@@ -907,10 +916,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
+ cpu_sys_dev = get_cpu_sysdev(j);
+ ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
+ "cpufreq");
+- if (ret) {
+- unlock_policy_rwsem_write(cpu);
++ if (ret)
+ goto err_out_unregister;
+- }
+ }
+
+ policy->governor = NULL; /* to assure that the starting sequence is
+@@ -950,6 +957,7 @@ err_out_driver_exit:
+ cpufreq_driver->exit(policy);
+
+ err_out:
++ unlock_policy_rwsem_write(cpu);
+ kfree(policy);
+
+ nomem_out:
+@@ -967,7 +975,7 @@ module_out:
+ * Caller should already have policy_rwsem in write mode for this CPU.
+ * This routine frees the rwsem before returning.
+ */
+-static int __cpufreq_remove_dev (struct sys_device * sys_dev)
++static int __cpufreq_remove_dev(struct sys_device *sys_dev)
+ {
+ unsigned int cpu = sys_dev->id;
+ unsigned long flags;
+@@ -1071,7 +1079,7 @@ static int __cpufreq_remove_dev (struct sys_device * sys_dev)
+ }
+
+
+-static int cpufreq_remove_dev (struct sys_device * sys_dev)
++static int cpufreq_remove_dev(struct sys_device *sys_dev)
+ {
+ unsigned int cpu = sys_dev->id;
+ int retval;
+@@ -1138,7 +1146,7 @@ unsigned int cpufreq_quick_get(unsigned int cpu)
+ cpufreq_cpu_put(policy);
+ }
+
+- return (ret_freq);
++ return ret_freq;
+ }
+ EXPORT_SYMBOL(cpufreq_quick_get);
+
+@@ -1149,7 +1157,7 @@ static unsigned int __cpufreq_get(unsigned int cpu)
+ unsigned int ret_freq = 0;
+
+ if (!cpufreq_driver->get)
+- return (ret_freq);
++ return ret_freq;
+
+ ret_freq = cpufreq_driver->get(cpu);
+
+@@ -1163,7 +1171,7 @@ static unsigned int __cpufreq_get(unsigned int cpu)
+ }
+ }
+
+- return (ret_freq);
++ return ret_freq;
+ }
+
+ /**
+@@ -1190,7 +1198,7 @@ unsigned int cpufreq_get(unsigned int cpu)
+ out_policy:
+ cpufreq_cpu_put(policy);
+ out:
+- return (ret_freq);
++ return ret_freq;
+ }
+ EXPORT_SYMBOL(cpufreq_get);
+
+@@ -1199,7 +1207,7 @@ EXPORT_SYMBOL(cpufreq_get);
+ * cpufreq_suspend - let the low level driver prepare for suspend
+ */
+
+-static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)
++static int cpufreq_suspend(struct sys_device *sysdev, pm_message_t pmsg)
+ {
+ int cpu = sysdev->id;
+ int ret = 0;
+@@ -1221,22 +1229,18 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)
+ return -EINVAL;
+
+ /* only handle each CPU group once */
+- if (unlikely(cpu_policy->cpu != cpu)) {
+- cpufreq_cpu_put(cpu_policy);
+- return 0;
+- }
++ if (unlikely(cpu_policy->cpu != cpu))
++ goto out;
+
+ if (cpufreq_driver->suspend) {
+ ret = cpufreq_driver->suspend(cpu_policy, pmsg);
+ if (ret) {
+ printk(KERN_ERR "cpufreq: suspend failed in ->suspend "
+ "step on CPU %u\n", cpu_policy->cpu);
+- cpufreq_cpu_put(cpu_policy);
+- return ret;
++ goto out;
+ }
+ }
+
+-
+ if (cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)
+ goto out;
+
+@@ -1270,7 +1274,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)
+
+ out:
+ cpufreq_cpu_put(cpu_policy);
+- return 0;
++ return ret;
+ }
+
+ /**
+@@ -1281,7 +1285,7 @@ out:
+ * 3.) schedule call cpufreq_update_policy() ASAP as interrupts are
+ * restored.
+ */
+-static int cpufreq_resume(struct sys_device * sysdev)
++static int cpufreq_resume(struct sys_device *sysdev)
+ {
+ int cpu = sysdev->id;
+ int ret = 0;
+@@ -1302,18 +1306,15 @@ static int cpufreq_resume(struct sys_device * sysdev)
+ return -EINVAL;
+
+ /* only handle each CPU group once */
+- if (unlikely(cpu_policy->cpu != cpu)) {
+- cpufreq_cpu_put(cpu_policy);
+- return 0;
+- }
++ if (unlikely(cpu_policy->cpu != cpu))
++ goto fail;
+
+ if (cpufreq_driver->resume) {
+ ret = cpufreq_driver->resume(cpu_policy);
+ if (ret) {
+ printk(KERN_ERR "cpufreq: resume failed in ->resume "
+ "step on CPU %u\n", cpu_policy->cpu);
+- cpufreq_cpu_put(cpu_policy);
+- return ret;
++ goto fail;
+ }
+ }
+
+@@ -1353,6 +1354,7 @@ static int cpufreq_resume(struct sys_device * sysdev)
+
+ out:
+ schedule_work(&cpu_policy->update);
++fail:
+ cpufreq_cpu_put(cpu_policy);
+ return ret;
+ }
+@@ -1386,6 +1388,8 @@ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
+ {
+ int ret;
+
++ WARN_ON(!init_cpufreq_transition_notifier_list_called);
++
+ switch (list) {
+ case CPUFREQ_TRANSITION_NOTIFIER:
+ ret = srcu_notifier_chain_register(
+@@ -1848,7 +1852,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
+ cpufreq_debug_enable_ratelimit();
+ }
+
+- return (ret);
++ return ret;
+ }
+ EXPORT_SYMBOL_GPL(cpufreq_register_driver);
+
+diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c
+index 13fe06b..88d2f44 100644
+--- a/drivers/cpufreq/cpufreq_powersave.c
++++ b/drivers/cpufreq/cpufreq_powersave.c
+@@ -35,12 +35,12 @@ static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
+ return 0;
+ }
+
+-static struct cpufreq_governor cpufreq_gov_powersave = {
++struct cpufreq_governor cpufreq_gov_powersave = {
+ .name = "powersave",
+ .governor = cpufreq_governor_powersave,
+ .owner = THIS_MODULE,
+ };
+-
++EXPORT_SYMBOL(cpufreq_gov_powersave);
+
+ static int __init cpufreq_gov_powersave_init(void)
+ {
+@@ -58,5 +58,9 @@ MODULE_AUTHOR("Dominik Brodowski <linux at brodo.de>");
+ MODULE_DESCRIPTION("CPUfreq policy governor 'powersave'");
+ MODULE_LICENSE("GPL");
+
++#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE
++fs_initcall(cpufreq_gov_powersave_init);
++#else
+ module_init(cpufreq_gov_powersave_init);
++#endif
+ module_exit(cpufreq_gov_powersave_exit);
+diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
+index 070421a..ae70d63 100644
+--- a/drivers/cpufreq/cpufreq_stats.c
++++ b/drivers/cpufreq/cpufreq_stats.c
+@@ -114,7 +114,7 @@ show_trans_table(struct cpufreq_policy *policy, char *buf)
+ stat->freq_table[i]);
+ }
+ if (len >= PAGE_SIZE)
+- return len;
++ return PAGE_SIZE;
+
+ len += snprintf(buf + len, PAGE_SIZE - len, "\n");
+
+@@ -131,8 +131,12 @@ show_trans_table(struct cpufreq_policy *policy, char *buf)
+ len += snprintf(buf + len, PAGE_SIZE - len, "%9u ",
+ stat->trans_table[i*stat->max_state+j]);
+ }
++ if (len >= PAGE_SIZE)
++ break;
+ len += snprintf(buf + len, PAGE_SIZE - len, "\n");
+ }
++ if (len >= PAGE_SIZE)
++ return PAGE_SIZE;
+ return len;
+ }
+ CPUFREQ_STATDEVICE_ATTR(trans_table,0444,show_trans_table);
+@@ -284,7 +288,7 @@ cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val,
+ if (!stat)
+ return 0;
+
+- old_index = freq_table_get_index(stat, freq->old);
++ old_index = stat->last_index;
+ new_index = freq_table_get_index(stat, freq->new);
+
+ cpufreq_stats_update(freq->cpu);
+diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
+index 6b658d8..43b71b6 100644
+--- a/drivers/crypto/Kconfig
++++ b/drivers/crypto/Kconfig
+@@ -27,6 +27,7 @@ config CRYPTO_DEV_PADLOCK_AES
+ tristate "PadLock driver for AES algorithm"
+ depends on CRYPTO_DEV_PADLOCK
+ select CRYPTO_BLKCIPHER
++ select CRYPTO_AES
+ help
+ Use VIA PadLock for AES algorithm.
+
+@@ -64,6 +65,7 @@ config ZCRYPT
+ tristate "Support for PCI-attached cryptographic adapters"
+ depends on S390
+ select ZCRYPT_MONOLITHIC if ZCRYPT="y"
++ select HW_RANDOM
+ help
+ Select this option if you want to use a PCI-attached cryptographic
+ adapter like:
+@@ -100,6 +102,19 @@ config CRYPTO_SHA256_S390
+ This version of SHA implements a 256 bit hash with 128 bits of
+ security against collision attacks.
+
++config CRYPTO_SHA512_S390
++ tristate "SHA384 and SHA512 digest algorithm"
++ depends on S390
++ select CRYPTO_ALGAPI
++ help
++ This is the s390 hardware accelerated implementation of the
++ SHA512 secure hash standard.
++
++ This version of SHA implements a 512 bit hash with 256 bits of
++ security against collision attacks. The code also includes SHA-384,
++ a 384 bit hash with 192 bits of security against collision attacks.
++
++
+ config CRYPTO_DES_S390
+ tristate "DES and Triple DES cipher algorithms"
+ depends on S390
+diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
+index 2f3ad3f..bb30eb9 100644
+--- a/drivers/crypto/padlock-aes.c
++++ b/drivers/crypto/padlock-aes.c
+@@ -5,42 +5,6 @@
+ *
+ * Copyright (c) 2004 Michal Ludvig <michal at logix.cz>
+ *
+- * Key expansion routine taken from crypto/aes_generic.c
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * ---------------------------------------------------------------------------
+- * Copyright (c) 2002, Dr Brian Gladman <brg at gladman.me.uk>, Worcester, UK.
+- * All rights reserved.
+- *
+- * LICENSE TERMS
+- *
+- * The free distribution and use of this software in both source and binary
+- * form is allowed (with or without changes) provided that:
+- *
+- * 1. distributions of this source code include the above copyright
+- * notice, this list of conditions and the following disclaimer;
+- *
+- * 2. distributions in binary form include the above copyright
+- * notice, this list of conditions and the following disclaimer
+- * in the documentation and/or other associated materials;
+- *
+- * 3. the copyright holder's name is not used to endorse products
+- * built using this software without specific written permission.
+- *
+- * ALTERNATIVELY, provided that this notice is retained in full, this product
+- * may be distributed under the terms of the GNU General Public License (GPL),
+- * in which case the provisions of the GPL apply INSTEAD OF those given above.
+- *
+- * DISCLAIMER
+- *
+- * This software is provided 'as is' with no explicit or implied warranties
+- * in respect of its properties, including, but not limited to, correctness
+- * and/or fitness for purpose.
+- * ---------------------------------------------------------------------------
+ */
+
+ #include <crypto/algapi.h>
+@@ -54,9 +18,6 @@
+ #include <asm/byteorder.h>
+ #include "padlock.h"
+
+-#define AES_EXTENDED_KEY_SIZE 64 /* in uint32_t units */
+-#define AES_EXTENDED_KEY_SIZE_B (AES_EXTENDED_KEY_SIZE * sizeof(uint32_t))
+-
+ /* Control word. */
+ struct cword {
+ unsigned int __attribute__ ((__packed__))
+@@ -70,218 +31,23 @@ struct cword {
+
+ /* Whenever making any changes to the following
+ * structure *make sure* you keep E, d_data
+- * and cword aligned on 16 Bytes boundaries!!! */
++ * and cword aligned on 16 Bytes boundaries and
++ * the Hardware can access 16 * 16 bytes of E and d_data
++ * (only the first 15 * 16 bytes matter but the HW reads
++ * more).
++ */
+ struct aes_ctx {
++ u32 E[AES_MAX_KEYLENGTH_U32]
++ __attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
++ u32 d_data[AES_MAX_KEYLENGTH_U32]
++ __attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
+ struct {
+ struct cword encrypt;
+ struct cword decrypt;
+ } cword;
+ u32 *D;
+- int key_length;
+- u32 E[AES_EXTENDED_KEY_SIZE]
+- __attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
+- u32 d_data[AES_EXTENDED_KEY_SIZE]
+- __attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
+ };
+
+-/* ====== Key management routines ====== */
+-
+-static inline uint32_t
+-generic_rotr32 (const uint32_t x, const unsigned bits)
+-{
+- const unsigned n = bits % 32;
+- return (x >> n) | (x << (32 - n));
+-}
+-
+-static inline uint32_t
+-generic_rotl32 (const uint32_t x, const unsigned bits)
+-{
+- const unsigned n = bits % 32;
+- return (x << n) | (x >> (32 - n));
+-}
+-
+-#define rotl generic_rotl32
+-#define rotr generic_rotr32
+-
+-/*
+- * #define byte(x, nr) ((unsigned char)((x) >> (nr*8)))
+- */
+-static inline uint8_t
+-byte(const uint32_t x, const unsigned n)
+-{
+- return x >> (n << 3);
+-}
+-
+-#define E_KEY ctx->E
+-#define D_KEY ctx->D
+-
+-static uint8_t pow_tab[256];
+-static uint8_t log_tab[256];
+-static uint8_t sbx_tab[256];
+-static uint8_t isb_tab[256];
+-static uint32_t rco_tab[10];
+-static uint32_t ft_tab[4][256];
+-static uint32_t it_tab[4][256];
+-
+-static uint32_t fl_tab[4][256];
+-static uint32_t il_tab[4][256];
+-
+-static inline uint8_t
+-f_mult (uint8_t a, uint8_t b)
+-{
+- uint8_t aa = log_tab[a], cc = aa + log_tab[b];
+-
+- return pow_tab[cc + (cc < aa ? 1 : 0)];
+-}
+-
+-#define ff_mult(a,b) (a && b ? f_mult(a, b) : 0)
+-
+-#define f_rn(bo, bi, n, k) \
+- bo[n] = ft_tab[0][byte(bi[n],0)] ^ \
+- ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
+- ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
+- ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
+-
+-#define i_rn(bo, bi, n, k) \
+- bo[n] = it_tab[0][byte(bi[n],0)] ^ \
+- it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
+- it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
+- it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
+-
+-#define ls_box(x) \
+- ( fl_tab[0][byte(x, 0)] ^ \
+- fl_tab[1][byte(x, 1)] ^ \
+- fl_tab[2][byte(x, 2)] ^ \
+- fl_tab[3][byte(x, 3)] )
+-
+-#define f_rl(bo, bi, n, k) \
+- bo[n] = fl_tab[0][byte(bi[n],0)] ^ \
+- fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
+- fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
+- fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
+-
+-#define i_rl(bo, bi, n, k) \
+- bo[n] = il_tab[0][byte(bi[n],0)] ^ \
+- il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
+- il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
+- il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
+-
+-static void
+-gen_tabs (void)
+-{
+- uint32_t i, t;
+- uint8_t p, q;
+-
+- /* log and power tables for GF(2**8) finite field with
+- 0x011b as modular polynomial - the simplest prmitive
+- root is 0x03, used here to generate the tables */
+-
+- for (i = 0, p = 1; i < 256; ++i) {
+- pow_tab[i] = (uint8_t) p;
+- log_tab[p] = (uint8_t) i;
+-
+- p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0);
+- }
+-
+- log_tab[1] = 0;
+-
+- for (i = 0, p = 1; i < 10; ++i) {
+- rco_tab[i] = p;
+-
+- p = (p << 1) ^ (p & 0x80 ? 0x01b : 0);
+- }
+-
+- for (i = 0; i < 256; ++i) {
+- p = (i ? pow_tab[255 - log_tab[i]] : 0);
+- q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2));
+- p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2));
+- sbx_tab[i] = p;
+- isb_tab[p] = (uint8_t) i;
+- }
+-
+- for (i = 0; i < 256; ++i) {
+- p = sbx_tab[i];
+-
+- t = p;
+- fl_tab[0][i] = t;
+- fl_tab[1][i] = rotl (t, 8);
+- fl_tab[2][i] = rotl (t, 16);
+- fl_tab[3][i] = rotl (t, 24);
+-
+- t = ((uint32_t) ff_mult (2, p)) |
+- ((uint32_t) p << 8) |
+- ((uint32_t) p << 16) | ((uint32_t) ff_mult (3, p) << 24);
+-
+- ft_tab[0][i] = t;
+- ft_tab[1][i] = rotl (t, 8);
+- ft_tab[2][i] = rotl (t, 16);
+- ft_tab[3][i] = rotl (t, 24);
+-
+- p = isb_tab[i];
+-
+- t = p;
+- il_tab[0][i] = t;
+- il_tab[1][i] = rotl (t, 8);
+- il_tab[2][i] = rotl (t, 16);
+- il_tab[3][i] = rotl (t, 24);
+-
+- t = ((uint32_t) ff_mult (14, p)) |
+- ((uint32_t) ff_mult (9, p) << 8) |
+- ((uint32_t) ff_mult (13, p) << 16) |
+- ((uint32_t) ff_mult (11, p) << 24);
+-
+- it_tab[0][i] = t;
+- it_tab[1][i] = rotl (t, 8);
+- it_tab[2][i] = rotl (t, 16);
+- it_tab[3][i] = rotl (t, 24);
+- }
+-}
+-
+-#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
+-
+-#define imix_col(y,x) \
+- u = star_x(x); \
+- v = star_x(u); \
+- w = star_x(v); \
+- t = w ^ (x); \
+- (y) = u ^ v ^ w; \
+- (y) ^= rotr(u ^ t, 8) ^ \
+- rotr(v ^ t, 16) ^ \
+- rotr(t,24)
+-
+-/* initialise the key schedule from the user supplied key */
+-
+-#define loop4(i) \
+-{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \
+- t ^= E_KEY[4 * i]; E_KEY[4 * i + 4] = t; \
+- t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t; \
+- t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t; \
+- t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t; \
+-}
+-
+-#define loop6(i) \
+-{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \
+- t ^= E_KEY[6 * i]; E_KEY[6 * i + 6] = t; \
+- t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t; \
+- t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t; \
+- t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t; \
+- t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t; \
+- t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t; \
+-}
+-
+-#define loop8(i) \
+-{ t = rotr(t, 8); ; t = ls_box(t) ^ rco_tab[i]; \
+- t ^= E_KEY[8 * i]; E_KEY[8 * i + 8] = t; \
+- t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t; \
+- t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t; \
+- t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t; \
+- t = E_KEY[8 * i + 4] ^ ls_box(t); \
+- E_KEY[8 * i + 12] = t; \
+- t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t; \
+- t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t; \
+- t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t; \
+-}
+-
+ /* Tells whether the ACE is capable to generate
+ the extended key for a given key_len. */
+ static inline int
+@@ -321,17 +87,13 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ struct aes_ctx *ctx = aes_ctx(tfm);
+ const __le32 *key = (const __le32 *)in_key;
+ u32 *flags = &tfm->crt_flags;
+- uint32_t i, t, u, v, w;
+- uint32_t P[AES_EXTENDED_KEY_SIZE];
+- uint32_t rounds;
++ struct crypto_aes_ctx gen_aes;
+
+ if (key_len % 8) {
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+
+- ctx->key_length = key_len;
+-
+ /*
+ * If the hardware is capable of generating the extended key
+ * itself we must supply the plain key for both encryption
+@@ -339,10 +101,10 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ */
+ ctx->D = ctx->E;
+
+- E_KEY[0] = le32_to_cpu(key[0]);
+- E_KEY[1] = le32_to_cpu(key[1]);
+- E_KEY[2] = le32_to_cpu(key[2]);
+- E_KEY[3] = le32_to_cpu(key[3]);
++ ctx->E[0] = le32_to_cpu(key[0]);
++ ctx->E[1] = le32_to_cpu(key[1]);
++ ctx->E[2] = le32_to_cpu(key[2]);
++ ctx->E[3] = le32_to_cpu(key[3]);
+
+ /* Prepare control words. */
+ memset(&ctx->cword, 0, sizeof(ctx->cword));
+@@ -361,56 +123,13 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ ctx->cword.encrypt.keygen = 1;
+ ctx->cword.decrypt.keygen = 1;
+
+- switch (key_len) {
+- case 16:
+- t = E_KEY[3];
+- for (i = 0; i < 10; ++i)
+- loop4 (i);
+- break;
+-
+- case 24:
+- E_KEY[4] = le32_to_cpu(key[4]);
+- t = E_KEY[5] = le32_to_cpu(key[5]);
+- for (i = 0; i < 8; ++i)
+- loop6 (i);
+- break;
+-
+- case 32:
+- E_KEY[4] = le32_to_cpu(key[4]);
+- E_KEY[5] = le32_to_cpu(key[5]);
+- E_KEY[6] = le32_to_cpu(key[6]);
+- t = E_KEY[7] = le32_to_cpu(key[7]);
+- for (i = 0; i < 7; ++i)
+- loop8 (i);
+- break;
+- }
+-
+- D_KEY[0] = E_KEY[0];
+- D_KEY[1] = E_KEY[1];
+- D_KEY[2] = E_KEY[2];
+- D_KEY[3] = E_KEY[3];
+-
+- for (i = 4; i < key_len + 24; ++i) {
+- imix_col (D_KEY[i], E_KEY[i]);
+- }
+-
+- /* PadLock needs a different format of the decryption key. */
+- rounds = 10 + (key_len - 16) / 4;
+-
+- for (i = 0; i < rounds; i++) {
+- P[((i + 1) * 4) + 0] = D_KEY[((rounds - i - 1) * 4) + 0];
+- P[((i + 1) * 4) + 1] = D_KEY[((rounds - i - 1) * 4) + 1];
+- P[((i + 1) * 4) + 2] = D_KEY[((rounds - i - 1) * 4) + 2];
+- P[((i + 1) * 4) + 3] = D_KEY[((rounds - i - 1) * 4) + 3];
++ if (crypto_aes_expand_key(&gen_aes, in_key, key_len)) {
++ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
++ return -EINVAL;
+ }
+
+- P[0] = E_KEY[(rounds * 4) + 0];
+- P[1] = E_KEY[(rounds * 4) + 1];
+- P[2] = E_KEY[(rounds * 4) + 2];
+- P[3] = E_KEY[(rounds * 4) + 3];
+-
+- memcpy(D_KEY, P, AES_EXTENDED_KEY_SIZE_B);
+-
++ memcpy(ctx->E, gen_aes.key_enc, AES_MAX_KEYLENGTH);
++ memcpy(ctx->D, gen_aes.key_dec, AES_MAX_KEYLENGTH);
+ return 0;
+ }
+
+@@ -675,7 +394,6 @@ static int __init padlock_init(void)
+ return -ENODEV;
+ }
+
+- gen_tabs();
+ if ((ret = crypto_register_alg(&aes_alg)))
+ goto aes_err;
+
+diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
+index 27340a7..6239c3d 100644
+--- a/drivers/dma/Kconfig
++++ b/drivers/dma/Kconfig
+@@ -46,14 +46,6 @@ config FSL_DMA
+ MPC8560/40, MPC8555, MPC8548 and MPC8641 processors.
+ The MPC8349, MPC8360 is also supported.
+
+-config FSL_DMA_SELFTEST
+- bool "Enable the self test for each DMA channel"
+- depends on FSL_DMA
+- default y
+- ---help---
+- Enable the self test for each DMA channel. A self test will be
+- performed after the channel probed to ensure the DMA works well.
+-
+ config DMA_ENGINE
+ bool
+
+diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
+index 8db0e7f..97b329e 100644
+--- a/drivers/dma/dmaengine.c
++++ b/drivers/dma/dmaengine.c
+@@ -42,9 +42,9 @@
+ *
+ * Each device has a kref, which is initialized to 1 when the device is
+ * registered. A kref_get is done for each device registered. When the
+- * device is released, the coresponding kref_put is done in the release
++ * device is released, the corresponding kref_put is done in the release
+ * method. Every time one of the device's channels is allocated to a client,
+- * a kref_get occurs. When the channel is freed, the coresponding kref_put
++ * a kref_get occurs. When the channel is freed, the corresponding kref_put
+ * happens. The device's release function does a completion, so
+ * unregister_device does a remove event, device_unregister, a kref_put
+ * for the first reference, then waits on the completion for all other
+@@ -53,7 +53,7 @@
+ * Each channel has an open-coded implementation of Rusty Russell's "bigref,"
+ * with a kref and a per_cpu local_t. A dma_chan_get is called when a client
+ * signals that it wants to use a channel, and dma_chan_put is called when
+- * a channel is removed or a client using it is unregesitered. A client can
++ * a channel is removed or a client using it is unregistered. A client can
+ * take extra references per outstanding transaction, as is the case with
+ * the NET DMA client. The release function does a kref_put on the device.
+ * -ChrisL, DanW
+@@ -362,7 +362,6 @@ int dma_async_device_register(struct dma_device *device)
+
+ BUG_ON(!device->device_alloc_chan_resources);
+ BUG_ON(!device->device_free_chan_resources);
+- BUG_ON(!device->device_dependency_added);
+ BUG_ON(!device->device_is_tx_complete);
+ BUG_ON(!device->device_issue_pending);
+ BUG_ON(!device->dev);
+@@ -479,7 +478,8 @@ dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest,
+
+ dma_src = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE);
+ dma_dest = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE);
+- tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0);
++ tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len,
++ DMA_CTRL_ACK);
+
+ if (!tx) {
+ dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE);
+@@ -487,7 +487,6 @@ dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest,
+ return -ENOMEM;
+ }
+
+- tx->ack = 1;
+ tx->callback = NULL;
+ cookie = tx->tx_submit(tx);
+
+@@ -525,7 +524,8 @@ dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page,
+
+ dma_src = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE);
+ dma_dest = dma_map_page(dev->dev, page, offset, len, DMA_FROM_DEVICE);
+- tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0);
++ tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len,
++ DMA_CTRL_ACK);
+
+ if (!tx) {
+ dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE);
+@@ -533,7 +533,6 @@ dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page,
+ return -ENOMEM;
+ }
+
+- tx->ack = 1;
+ tx->callback = NULL;
+ cookie = tx->tx_submit(tx);
+
+@@ -574,7 +573,8 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
+ dma_src = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE);
+ dma_dest = dma_map_page(dev->dev, dest_pg, dest_off, len,
+ DMA_FROM_DEVICE);
+- tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0);
++ tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len,
++ DMA_CTRL_ACK);
+
+ if (!tx) {
+ dma_unmap_page(dev->dev, dma_src, len, DMA_TO_DEVICE);
+@@ -582,7 +582,6 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
+ return -ENOMEM;
+ }
+
+- tx->ack = 1;
+ tx->callback = NULL;
+ cookie = tx->tx_submit(tx);
+
+@@ -600,8 +599,6 @@ void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
+ {
+ tx->chan = chan;
+ spin_lock_init(&tx->lock);
+- INIT_LIST_HEAD(&tx->depend_node);
+- INIT_LIST_HEAD(&tx->depend_list);
+ }
+ EXPORT_SYMBOL(dma_async_tx_descriptor_init);
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index df16368..054eabf 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -412,7 +412,7 @@ static void fsl_dma_free_chan_resources(struct dma_chan *chan)
+ }
+
+ static struct dma_async_tx_descriptor *
+-fsl_dma_prep_interrupt(struct dma_chan *chan)
++fsl_dma_prep_interrupt(struct dma_chan *chan, unsigned long flags)
+ {
+ struct fsl_dma_chan *fsl_chan;
+ struct fsl_desc_sw *new;
+@@ -429,7 +429,7 @@ fsl_dma_prep_interrupt(struct dma_chan *chan)
+ }
+
+ new->async_tx.cookie = -EBUSY;
+- new->async_tx.ack = 0;
++ new->async_tx.flags = flags;
+
+ /* Insert the link descriptor to the LD ring */
+ list_add_tail(&new->node, &new->async_tx.tx_list);
+@@ -482,7 +482,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ set_desc_next(fsl_chan, &prev->hw, new->async_tx.phys);
+
+ new->async_tx.cookie = 0;
+- new->async_tx.ack = 1;
++ async_tx_ack(&new->async_tx);
+
+ prev = new;
+ len -= copy;
+@@ -493,7 +493,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ list_add_tail(&new->node, &first->async_tx.tx_list);
+ } while (len);
+
+- new->async_tx.ack = 0; /* client is in control of this ack */
++ new->async_tx.flags = flags; /* client is in control of this ack */
+ new->async_tx.cookie = -EBUSY;
+
+ /* Set End-of-link to the last link descriptor of new list*/
+@@ -658,13 +658,6 @@ static void fsl_dma_memcpy_issue_pending(struct dma_chan *chan)
+ fsl_chan_xfer_ld_queue(fsl_chan);
+ }
+
+-static void fsl_dma_dependency_added(struct dma_chan *chan)
+-{
+- struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
+-
+- fsl_chan_ld_cleanup(fsl_chan);
+-}
+-
+ /**
+ * fsl_dma_is_complete - Determine the DMA status
+ * @fsl_chan : Freescale DMA channel
+@@ -696,6 +689,8 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+ {
+ struct fsl_dma_chan *fsl_chan = (struct fsl_dma_chan *)data;
+ u32 stat;
++ int update_cookie = 0;
++ int xfer_ld_q = 0;
+
+ stat = get_sr(fsl_chan);
+ dev_dbg(fsl_chan->dev, "event: channel %d, stat = 0x%x\n",
+@@ -720,8 +715,8 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+ * Now, update the completed cookie, and continue the
+ * next uncompleted transfer.
+ */
+- fsl_dma_update_completed_cookie(fsl_chan);
+- fsl_chan_xfer_ld_queue(fsl_chan);
++ update_cookie = 1;
++ xfer_ld_q = 1;
+ }
+ stat &= ~FSL_DMA_SR_PE;
+ }
+@@ -734,19 +729,33 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+ dev_dbg(fsl_chan->dev, "event: clndar %p, nlndar %p\n",
+ (void *)get_cdar(fsl_chan), (void *)get_ndar(fsl_chan));
+ stat &= ~FSL_DMA_SR_EOSI;
+- fsl_dma_update_completed_cookie(fsl_chan);
++ update_cookie = 1;
++ }
++
++ /* For MPC8349, EOCDI event need to update cookie
++ * and start the next transfer if it exist.
++ */
++ if (stat & FSL_DMA_SR_EOCDI) {
++ dev_dbg(fsl_chan->dev, "event: End-of-Chain link INT\n");
++ stat &= ~FSL_DMA_SR_EOCDI;
++ update_cookie = 1;
++ xfer_ld_q = 1;
+ }
+
+ /* If it current transfer is the end-of-transfer,
+ * we should clear the Channel Start bit for
+ * prepare next transfer.
+ */
+- if (stat & (FSL_DMA_SR_EOLNI | FSL_DMA_SR_EOCDI)) {
++ if (stat & FSL_DMA_SR_EOLNI) {
+ dev_dbg(fsl_chan->dev, "event: End-of-link INT\n");
+ stat &= ~FSL_DMA_SR_EOLNI;
+- fsl_chan_xfer_ld_queue(fsl_chan);
++ xfer_ld_q = 1;
+ }
+
++ if (update_cookie)
++ fsl_dma_update_completed_cookie(fsl_chan);
++ if (xfer_ld_q)
++ fsl_chan_xfer_ld_queue(fsl_chan);
+ if (stat)
+ dev_dbg(fsl_chan->dev, "event: unhandled sr 0x%02x\n",
+ stat);
+@@ -776,15 +785,13 @@ static void dma_do_tasklet(unsigned long data)
+ fsl_chan_ld_cleanup(fsl_chan);
+ }
+
+-#ifdef FSL_DMA_CALLBACKTEST
+-static void fsl_dma_callback_test(struct fsl_dma_chan *fsl_chan)
++static void fsl_dma_callback_test(void *param)
+ {
++ struct fsl_dma_chan *fsl_chan = param;
+ if (fsl_chan)
+- dev_info(fsl_chan->dev, "selftest: callback is ok!\n");
++ dev_dbg(fsl_chan->dev, "selftest: callback is ok!\n");
+ }
+-#endif
+
+-#ifdef CONFIG_FSL_DMA_SELFTEST
+ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
+ {
+ struct dma_chan *chan;
+@@ -867,7 +874,7 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
+ async_tx_ack(tx3);
+
+ /* Interrupt tx test */
+- tx1 = fsl_dma_prep_interrupt(chan);
++ tx1 = fsl_dma_prep_interrupt(chan, 0);
+ async_tx_ack(tx1);
+ cookie = fsl_dma_tx_submit(tx1);
+
+@@ -875,13 +882,11 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
+ cookie = fsl_dma_tx_submit(tx3);
+ cookie = fsl_dma_tx_submit(tx2);
+
+-#ifdef FSL_DMA_CALLBACKTEST
+ if (dma_has_cap(DMA_INTERRUPT, ((struct fsl_dma_device *)
+ dev_get_drvdata(fsl_chan->dev->parent))->common.cap_mask)) {
+ tx3->callback = fsl_dma_callback_test;
+ tx3->callback_param = fsl_chan;
+ }
+-#endif
+ fsl_dma_memcpy_issue_pending(chan);
+ msleep(2);
+
+@@ -906,7 +911,6 @@ out:
+ kfree(src);
+ return err;
+ }
+-#endif
+
+ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
+ const struct of_device_id *match)
+@@ -997,11 +1001,9 @@ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
+ }
+ }
+
+-#ifdef CONFIG_FSL_DMA_SELFTEST
+ err = fsl_dma_self_test(new_fsl_chan);
+ if (err)
+ goto err;
+-#endif
+
+ dev_info(&dev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id,
+ match->compatible, new_fsl_chan->irq);
+@@ -1080,7 +1082,6 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
+ fdev->common.device_prep_dma_memcpy = fsl_dma_prep_memcpy;
+ fdev->common.device_is_tx_complete = fsl_dma_is_complete;
+ fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending;
+- fdev->common.device_dependency_added = fsl_dma_dependency_added;
+ fdev->common.dev = &dev->dev;
+
+ irq = irq_of_parse_and_map(dev->node, 0);
+diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
+index 4017d9e..318e8a2 100644
+--- a/drivers/dma/ioat_dma.c
++++ b/drivers/dma/ioat_dma.c
+@@ -212,14 +212,14 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
+ u32 copy;
+ size_t len;
+ dma_addr_t src, dst;
+- int orig_ack;
++ unsigned long orig_flags;
+ unsigned int desc_count = 0;
+
+ /* src and dest and len are stored in the initial descriptor */
+ len = first->len;
+ src = first->src;
+ dst = first->dst;
+- orig_ack = first->async_tx.ack;
++ orig_flags = first->async_tx.flags;
+ new = first;
+
+ spin_lock_bh(&ioat_chan->desc_lock);
+@@ -228,7 +228,7 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
+ do {
+ copy = min_t(size_t, len, ioat_chan->xfercap);
+
+- new->async_tx.ack = 1;
++ async_tx_ack(&new->async_tx);
+
+ hw = new->hw;
+ hw->size = copy;
+@@ -264,7 +264,7 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
+ }
+
+ new->tx_cnt = desc_count;
+- new->async_tx.ack = orig_ack; /* client is in control of this ack */
++ new->async_tx.flags = orig_flags; /* client is in control of this ack */
+
+ /* store the original values for use in later cleanup */
+ if (new != first) {
+@@ -304,14 +304,14 @@ static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx)
+ u32 copy;
+ size_t len;
+ dma_addr_t src, dst;
+- int orig_ack;
++ unsigned long orig_flags;
+ unsigned int desc_count = 0;
+
+ /* src and dest and len are stored in the initial descriptor */
+ len = first->len;
+ src = first->src;
+ dst = first->dst;
+- orig_ack = first->async_tx.ack;
++ orig_flags = first->async_tx.flags;
+ new = first;
+
+ /*
+@@ -321,7 +321,7 @@ static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx)
+ do {
+ copy = min_t(size_t, len, ioat_chan->xfercap);
+
+- new->async_tx.ack = 1;
++ async_tx_ack(&new->async_tx);
+
+ hw = new->hw;
+ hw->size = copy;
+@@ -349,7 +349,7 @@ static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx)
+ }
+
+ new->tx_cnt = desc_count;
+- new->async_tx.ack = orig_ack; /* client is in control of this ack */
++ new->async_tx.flags = orig_flags; /* client is in control of this ack */
+
+ /* store the original values for use in later cleanup */
+ if (new != first) {
+@@ -714,7 +714,7 @@ static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy(
+ new->len = len;
+ new->dst = dma_dest;
+ new->src = dma_src;
+- new->async_tx.ack = 0;
++ new->async_tx.flags = flags;
+ return &new->async_tx;
+ } else
+ return NULL;
+@@ -742,7 +742,7 @@ static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy(
+ new->len = len;
+ new->dst = dma_dest;
+ new->src = dma_src;
+- new->async_tx.ack = 0;
++ new->async_tx.flags = flags;
+ return &new->async_tx;
+ } else
+ return NULL;
+@@ -842,7 +842,7 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
+ * a completed entry, but not the last, so clean
+ * up if the client is done with the descriptor
+ */
+- if (desc->async_tx.ack) {
++ if (async_tx_test_ack(&desc->async_tx)) {
+ list_del(&desc->node);
+ list_add_tail(&desc->node,
+ &ioat_chan->free_desc);
+@@ -924,17 +924,6 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
+ spin_unlock_bh(&ioat_chan->cleanup_lock);
+ }
+
+-static void ioat_dma_dependency_added(struct dma_chan *chan)
+-{
+- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+- spin_lock_bh(&ioat_chan->desc_lock);
+- if (ioat_chan->pending == 0) {
+- spin_unlock_bh(&ioat_chan->desc_lock);
+- ioat_dma_memcpy_cleanup(ioat_chan);
+- } else
+- spin_unlock_bh(&ioat_chan->desc_lock);
+-}
+-
+ /**
+ * ioat_dma_is_complete - poll the status of a IOAT DMA transaction
+ * @chan: IOAT DMA channel handle
+@@ -990,7 +979,7 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan)
+ desc->hw->size = 0;
+ desc->hw->src_addr = 0;
+ desc->hw->dst_addr = 0;
+- desc->async_tx.ack = 1;
++ async_tx_ack(&desc->async_tx);
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ desc->hw->next = 0;
+@@ -1316,7 +1305,6 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
+
+ dma_cap_set(DMA_MEMCPY, device->common.cap_mask);
+ device->common.device_is_tx_complete = ioat_dma_is_complete;
+- device->common.device_dependency_added = ioat_dma_dependency_added;
+ switch (device->version) {
+ case IOAT_VER_1_2:
+ device->common.device_prep_dma_memcpy = ioat1_dma_prep_memcpy;
+diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
+index f82b090..762b729 100644
+--- a/drivers/dma/iop-adma.c
++++ b/drivers/dma/iop-adma.c
+@@ -63,7 +63,6 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
+ struct iop_adma_chan *iop_chan, dma_cookie_t cookie)
+ {
+ BUG_ON(desc->async_tx.cookie < 0);
+- spin_lock_bh(&desc->async_tx.lock);
+ if (desc->async_tx.cookie > 0) {
+ cookie = desc->async_tx.cookie;
+ desc->async_tx.cookie = 0;
+@@ -101,7 +100,6 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
+
+ /* run dependent operations */
+ async_tx_run_dependencies(&desc->async_tx);
+- spin_unlock_bh(&desc->async_tx.lock);
+
+ return cookie;
+ }
+@@ -113,7 +111,7 @@ iop_adma_clean_slot(struct iop_adma_desc_slot *desc,
+ /* the client is allowed to attach dependent operations
+ * until 'ack' is set
+ */
+- if (!desc->async_tx.ack)
++ if (!async_tx_test_ack(&desc->async_tx))
+ return 0;
+
+ /* leave the last descriptor in the chain
+@@ -150,7 +148,7 @@ static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+ "this_desc: %#x next_desc: %#x ack: %d\n",
+ iter->async_tx.cookie, iter->idx, busy,
+ iter->async_tx.phys, iop_desc_get_next_desc(iter),
+- iter->async_tx.ack);
++ async_tx_test_ack(&iter->async_tx));
+ prefetch(_iter);
+ prefetch(&_iter->async_tx);
+
+@@ -257,8 +255,6 @@ static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+
+ BUG_ON(!seen_current);
+
+- iop_chan_idle(busy, iop_chan);
+-
+ if (cookie > 0) {
+ iop_chan->completed_cookie = cookie;
+ pr_debug("\tcompleted cookie %d\n", cookie);
+@@ -275,8 +271,11 @@ iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+
+ static void iop_adma_tasklet(unsigned long data)
+ {
+- struct iop_adma_chan *chan = (struct iop_adma_chan *) data;
+- __iop_adma_slot_cleanup(chan);
++ struct iop_adma_chan *iop_chan = (struct iop_adma_chan *) data;
++
++ spin_lock(&iop_chan->lock);
++ __iop_adma_slot_cleanup(iop_chan);
++ spin_unlock(&iop_chan->lock);
+ }
+
+ static struct iop_adma_desc_slot *
+@@ -339,9 +338,7 @@ retry:
+
+ /* pre-ack all but the last descriptor */
+ if (num_slots != slots_per_op)
+- iter->async_tx.ack = 1;
+- else
+- iter->async_tx.ack = 0;
++ async_tx_ack(&iter->async_tx);
+
+ list_add_tail(&iter->chain_node, &chain);
+ alloc_tail = iter;
+@@ -514,7 +511,7 @@ static int iop_adma_alloc_chan_resources(struct dma_chan *chan)
+ }
+
+ static struct dma_async_tx_descriptor *
+-iop_adma_prep_dma_interrupt(struct dma_chan *chan)
++iop_adma_prep_dma_interrupt(struct dma_chan *chan, unsigned long flags)
+ {
+ struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+ struct iop_adma_desc_slot *sw_desc, *grp_start;
+@@ -529,6 +526,7 @@ iop_adma_prep_dma_interrupt(struct dma_chan *chan)
+ grp_start = sw_desc->group_head;
+ iop_desc_init_interrupt(grp_start, iop_chan);
+ grp_start->unmap_len = 0;
++ sw_desc->async_tx.flags = flags;
+ }
+ spin_unlock_bh(&iop_chan->lock);
+
+@@ -561,6 +559,7 @@ iop_adma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dma_dest,
+ iop_desc_set_memcpy_src_addr(grp_start, dma_src);
+ sw_desc->unmap_src_cnt = 1;
+ sw_desc->unmap_len = len;
++ sw_desc->async_tx.flags = flags;
+ }
+ spin_unlock_bh(&iop_chan->lock);
+
+@@ -593,6 +592,7 @@ iop_adma_prep_dma_memset(struct dma_chan *chan, dma_addr_t dma_dest,
+ iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest);
+ sw_desc->unmap_src_cnt = 1;
+ sw_desc->unmap_len = len;
++ sw_desc->async_tx.flags = flags;
+ }
+ spin_unlock_bh(&iop_chan->lock);
+
+@@ -626,6 +626,7 @@ iop_adma_prep_dma_xor(struct dma_chan *chan, dma_addr_t dma_dest,
+ iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest);
+ sw_desc->unmap_src_cnt = src_cnt;
+ sw_desc->unmap_len = len;
++ sw_desc->async_tx.flags = flags;
+ while (src_cnt--)
+ iop_desc_set_xor_src_addr(grp_start, src_cnt,
+ dma_src[src_cnt]);
+@@ -662,6 +663,7 @@ iop_adma_prep_dma_zero_sum(struct dma_chan *chan, dma_addr_t *dma_src,
+ __func__, grp_start->xor_check_result);
+ sw_desc->unmap_src_cnt = src_cnt;
+ sw_desc->unmap_len = len;
++ sw_desc->async_tx.flags = flags;
+ while (src_cnt--)
+ iop_desc_set_zero_sum_src_addr(grp_start, src_cnt,
+ dma_src[src_cnt]);
+@@ -671,12 +673,6 @@ iop_adma_prep_dma_zero_sum(struct dma_chan *chan, dma_addr_t *dma_src,
+ return sw_desc ? &sw_desc->async_tx : NULL;
+ }
+
+-static void iop_adma_dependency_added(struct dma_chan *chan)
+-{
+- struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+- tasklet_schedule(&iop_chan->irq_tasklet);
+-}
+-
+ static void iop_adma_free_chan_resources(struct dma_chan *chan)
+ {
+ struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+@@ -854,11 +850,11 @@ static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
+ src_dma = dma_map_single(dma_chan->device->dev, src,
+ IOP_ADMA_TEST_SIZE, DMA_TO_DEVICE);
+ tx = iop_adma_prep_dma_memcpy(dma_chan, dest_dma, src_dma,
+- IOP_ADMA_TEST_SIZE, 1);
++ IOP_ADMA_TEST_SIZE,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+ cookie = iop_adma_tx_submit(tx);
+ iop_adma_issue_pending(dma_chan);
+- async_tx_ack(tx);
+ msleep(1);
+
+ if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
+@@ -954,11 +950,11 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
+ dma_srcs[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
+ 0, PAGE_SIZE, DMA_TO_DEVICE);
+ tx = iop_adma_prep_dma_xor(dma_chan, dest_dma, dma_srcs,
+- IOP_ADMA_NUM_SRC_TEST, PAGE_SIZE, 1);
++ IOP_ADMA_NUM_SRC_TEST, PAGE_SIZE,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+ cookie = iop_adma_tx_submit(tx);
+ iop_adma_issue_pending(dma_chan);
+- async_tx_ack(tx);
+ msleep(8);
+
+ if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
+@@ -1001,11 +997,11 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
+ DMA_TO_DEVICE);
+ tx = iop_adma_prep_dma_zero_sum(dma_chan, dma_srcs,
+ IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE,
+- &zero_sum_result, 1);
++ &zero_sum_result,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+ cookie = iop_adma_tx_submit(tx);
+ iop_adma_issue_pending(dma_chan);
+- async_tx_ack(tx);
+ msleep(8);
+
+ if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+@@ -1025,11 +1021,11 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
+ /* test memset */
+ dma_addr = dma_map_page(dma_chan->device->dev, dest, 0,
+ PAGE_SIZE, DMA_FROM_DEVICE);
+- tx = iop_adma_prep_dma_memset(dma_chan, dma_addr, 0, PAGE_SIZE, 1);
++ tx = iop_adma_prep_dma_memset(dma_chan, dma_addr, 0, PAGE_SIZE,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+ cookie = iop_adma_tx_submit(tx);
+ iop_adma_issue_pending(dma_chan);
+- async_tx_ack(tx);
+ msleep(8);
+
+ if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+@@ -1057,11 +1053,11 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
+ DMA_TO_DEVICE);
+ tx = iop_adma_prep_dma_zero_sum(dma_chan, dma_srcs,
+ IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE,
+- &zero_sum_result, 1);
++ &zero_sum_result,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+ cookie = iop_adma_tx_submit(tx);
+ iop_adma_issue_pending(dma_chan);
+- async_tx_ack(tx);
+ msleep(8);
+
+ if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+@@ -1177,7 +1173,6 @@ static int __devinit iop_adma_probe(struct platform_device *pdev)
+ dma_dev->device_free_chan_resources = iop_adma_free_chan_resources;
+ dma_dev->device_is_tx_complete = iop_adma_is_complete;
+ dma_dev->device_issue_pending = iop_adma_issue_pending;
+- dma_dev->device_dependency_added = iop_adma_dependency_added;
+ dma_dev->dev = &pdev->dev;
+
+ /* set prep routines based on capability */
+@@ -1232,9 +1227,6 @@ static int __devinit iop_adma_probe(struct platform_device *pdev)
+ }
+
+ spin_lock_init(&iop_chan->lock);
+- init_timer(&iop_chan->cleanup_watchdog);
+- iop_chan->cleanup_watchdog.data = (unsigned long) iop_chan;
+- iop_chan->cleanup_watchdog.function = iop_adma_tasklet;
+ INIT_LIST_HEAD(&iop_chan->chain);
+ INIT_LIST_HEAD(&iop_chan->all_slots);
+ INIT_RCU_HEAD(&iop_chan->common.rcu);
+@@ -1298,7 +1290,7 @@ static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan)
+ grp_start = sw_desc->group_head;
+
+ list_splice_init(&sw_desc->async_tx.tx_list, &iop_chan->chain);
+- sw_desc->async_tx.ack = 1;
++ async_tx_ack(&sw_desc->async_tx);
+ iop_desc_init_memcpy(grp_start, 0);
+ iop_desc_set_byte_count(grp_start, iop_chan, 0);
+ iop_desc_set_dest_addr(grp_start, iop_chan, 0);
+@@ -1354,7 +1346,7 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
+ if (sw_desc) {
+ grp_start = sw_desc->group_head;
+ list_splice_init(&sw_desc->async_tx.tx_list, &iop_chan->chain);
+- sw_desc->async_tx.ack = 1;
++ async_tx_ack(&sw_desc->async_tx);
+ iop_desc_init_null_xor(grp_start, 2, 0);
+ iop_desc_set_byte_count(grp_start, iop_chan, 0);
+ iop_desc_set_dest_addr(grp_start, iop_chan, 0);
+diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
+index 2b38299..6e6c3c4 100644
+--- a/drivers/edac/Kconfig
++++ b/drivers/edac/Kconfig
+@@ -67,7 +67,7 @@ config EDAC_E7XXX
+ E7205, E7500, E7501 and E7505 server chipsets.
+
+ config EDAC_E752X
+- tristate "Intel e752x (e7520, e7525, e7320)"
++ tristate "Intel e752x (e7520, e7525, e7320) and 3100"
+ depends on EDAC_MM_EDAC && PCI && X86 && HOTPLUG
+ help
+ Support for error detection and correction on the Intel
+diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c
+index f220754..2b95f1a 100644
+--- a/drivers/edac/amd76x_edac.c
++++ b/drivers/edac/amd76x_edac.c
+@@ -17,6 +17,7 @@
+ #include <linux/pci.h>
+ #include <linux/pci_ids.h>
+ #include <linux/slab.h>
++#include <linux/edac.h>
+ #include "edac_core.h"
+
+ #define AMD76X_REVISION " Ver: 2.0.2 " __DATE__
+@@ -344,6 +345,9 @@ static struct pci_driver amd76x_driver = {
+
+ static int __init amd76x_init(void)
+ {
++ /* Ensure that the OPSTATE is set correctly for POLL or NMI */
++ opstate_init();
++
+ return pci_register_driver(&amd76x_driver);
+ }
+
+@@ -358,3 +362,6 @@ module_exit(amd76x_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
+ MODULE_DESCRIPTION("MC support for AMD 76x memory controllers");
++
++module_param(edac_op_state, int, 0444);
++MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
+diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
+index 6eb4347..c94a0eb 100644
+--- a/drivers/edac/e752x_edac.c
++++ b/drivers/edac/e752x_edac.c
+@@ -29,6 +29,7 @@
+ #define EDAC_MOD_STR "e752x_edac"
+
+ static int force_function_unhide;
++static int sysbus_parity = -1;
+
+ static struct edac_pci_ctl_info *e752x_pci;
+
+@@ -62,6 +63,14 @@ static struct edac_pci_ctl_info *e752x_pci;
+ #define PCI_DEVICE_ID_INTEL_7320_1_ERR 0x3593
+ #endif /* PCI_DEVICE_ID_INTEL_7320_1_ERR */
+
++#ifndef PCI_DEVICE_ID_INTEL_3100_0
++#define PCI_DEVICE_ID_INTEL_3100_0 0x35B0
++#endif /* PCI_DEVICE_ID_INTEL_3100_0 */
++
++#ifndef PCI_DEVICE_ID_INTEL_3100_1_ERR
++#define PCI_DEVICE_ID_INTEL_3100_1_ERR 0x35B1
++#endif /* PCI_DEVICE_ID_INTEL_3100_1_ERR */
++
+ #define E752X_NR_CSROWS 8 /* number of csrows */
+
+ /* E752X register addresses - device 0 function 0 */
+@@ -152,6 +161,12 @@ static struct edac_pci_ctl_info *e752x_pci;
+ /* error syndrome register (16b) */
+ #define E752X_DEVPRES1 0xF4 /* Device Present 1 register (8b) */
+
++/* 3100 IMCH specific register addresses - device 0 function 1 */
++#define I3100_NSI_FERR 0x48 /* NSI first error reg (32b) */
++#define I3100_NSI_NERR 0x4C /* NSI next error reg (32b) */
++#define I3100_NSI_SMICMD 0x54 /* NSI SMI command register (32b) */
++#define I3100_NSI_EMASK 0x90 /* NSI error mask register (32b) */
++
+ /* ICH5R register addresses - device 30 function 0 */
+ #define ICH5R_PCI_STAT 0x06 /* PCI status register (16b) */
+ #define ICH5R_PCI_2ND_STAT 0x1E /* PCI status secondary reg (16b) */
+@@ -160,7 +175,8 @@ static struct edac_pci_ctl_info *e752x_pci;
+ enum e752x_chips {
+ E7520 = 0,
+ E7525 = 1,
+- E7320 = 2
++ E7320 = 2,
++ I3100 = 3
+ };
+
+ struct e752x_pvt {
+@@ -185,8 +201,10 @@ struct e752x_dev_info {
+ struct e752x_error_info {
+ u32 ferr_global;
+ u32 nerr_global;
+- u8 hi_ferr;
+- u8 hi_nerr;
++ u32 nsi_ferr; /* 3100 only */
++ u32 nsi_nerr; /* 3100 only */
++ u8 hi_ferr; /* all but 3100 */
++ u8 hi_nerr; /* all but 3100 */
+ u16 sysbus_ferr;
+ u16 sysbus_nerr;
+ u8 buf_ferr;
+@@ -215,6 +233,10 @@ static const struct e752x_dev_info e752x_devs[] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR,
+ .ctl_dev = PCI_DEVICE_ID_INTEL_7320_0,
+ .ctl_name = "E7320"},
++ [I3100] = {
++ .err_dev = PCI_DEVICE_ID_INTEL_3100_1_ERR,
++ .ctl_dev = PCI_DEVICE_ID_INTEL_3100_0,
++ .ctl_name = "3100"},
+ };
+
+ static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci,
+@@ -402,7 +424,7 @@ static inline void process_threshold_ce(struct mem_ctl_info *mci, u16 error,
+ static char *global_message[11] = {
+ "PCI Express C1", "PCI Express C", "PCI Express B1",
+ "PCI Express B", "PCI Express A1", "PCI Express A",
+- "DMA Controler", "HUB Interface", "System Bus",
++ "DMA Controler", "HUB or NS Interface", "System Bus",
+ "DRAM Controler", "Internal Buffer"
+ };
+
+@@ -455,6 +477,63 @@ static inline void hub_error(int fatal, u8 errors, int *error_found,
+ do_hub_error(fatal, errors);
+ }
+
++#define NSI_FATAL_MASK 0x0c080081
++#define NSI_NON_FATAL_MASK 0x23a0ba64
++#define NSI_ERR_MASK (NSI_FATAL_MASK | NSI_NON_FATAL_MASK)
++
++static char *nsi_message[30] = {
++ "NSI Link Down", /* NSI_FERR/NSI_NERR bit 0, fatal error */
++ "", /* reserved */
++ "NSI Parity Error", /* bit 2, non-fatal */
++ "", /* reserved */
++ "", /* reserved */
++ "Correctable Error Message", /* bit 5, non-fatal */
++ "Non-Fatal Error Message", /* bit 6, non-fatal */
++ "Fatal Error Message", /* bit 7, fatal */
++ "", /* reserved */
++ "Receiver Error", /* bit 9, non-fatal */
++ "", /* reserved */
++ "Bad TLP", /* bit 11, non-fatal */
++ "Bad DLLP", /* bit 12, non-fatal */
++ "REPLAY_NUM Rollover", /* bit 13, non-fatal */
++ "", /* reserved */
++ "Replay Timer Timeout", /* bit 15, non-fatal */
++ "", /* reserved */
++ "", /* reserved */
++ "", /* reserved */
++ "Data Link Protocol Error", /* bit 19, fatal */
++ "", /* reserved */
++ "Poisoned TLP", /* bit 21, non-fatal */
++ "", /* reserved */
++ "Completion Timeout", /* bit 23, non-fatal */
++ "Completer Abort", /* bit 24, non-fatal */
++ "Unexpected Completion", /* bit 25, non-fatal */
++ "Receiver Overflow", /* bit 26, fatal */
++ "Malformed TLP", /* bit 27, fatal */
++ "", /* reserved */
++ "Unsupported Request" /* bit 29, non-fatal */
++};
++
++static void do_nsi_error(int fatal, u32 errors)
++{
++ int i;
++
++ for (i = 0; i < 30; i++) {
++ if (errors & (1 << i))
++ printk(KERN_WARNING "%sError %s\n",
++ fatal_message[fatal], nsi_message[i]);
++ }
++}
++
++static inline void nsi_error(int fatal, u32 errors, int *error_found,
++ int handle_error)
++{
++ *error_found = 1;
++
++ if (handle_error)
++ do_nsi_error(fatal, errors);
++}
++
+ static char *membuf_message[4] = {
+ "Internal PMWB to DRAM parity",
+ "Internal PMWB to System Bus Parity",
+@@ -546,6 +625,31 @@ static void e752x_check_hub_interface(struct e752x_error_info *info,
+ }
+ }
+
++static void e752x_check_ns_interface(struct e752x_error_info *info,
++ int *error_found, int handle_error)
++{
++ u32 stat32;
++
++ stat32 = info->nsi_ferr;
++ if (stat32 & NSI_ERR_MASK) { /* Error, so process */
++ if (stat32 & NSI_FATAL_MASK) /* check for fatal errors */
++ nsi_error(1, stat32 & NSI_FATAL_MASK, error_found,
++ handle_error);
++ if (stat32 & NSI_NON_FATAL_MASK) /* check for non-fatal ones */
++ nsi_error(0, stat32 & NSI_NON_FATAL_MASK, error_found,
++ handle_error);
++ }
++ stat32 = info->nsi_nerr;
++ if (stat32 & NSI_ERR_MASK) {
++ if (stat32 & NSI_FATAL_MASK)
++ nsi_error(1, stat32 & NSI_FATAL_MASK, error_found,
++ handle_error);
++ if (stat32 & NSI_NON_FATAL_MASK)
++ nsi_error(0, stat32 & NSI_NON_FATAL_MASK, error_found,
++ handle_error);
++ }
++}
++
+ static void e752x_check_sysbus(struct e752x_error_info *info,
+ int *error_found, int handle_error)
+ {
+@@ -653,7 +757,15 @@ static void e752x_get_error_info(struct mem_ctl_info *mci,
+ pci_read_config_dword(dev, E752X_FERR_GLOBAL, &info->ferr_global);
+
+ if (info->ferr_global) {
+- pci_read_config_byte(dev, E752X_HI_FERR, &info->hi_ferr);
++ if (pvt->dev_info->err_dev == PCI_DEVICE_ID_INTEL_3100_1_ERR) {
++ pci_read_config_dword(dev, I3100_NSI_FERR,
++ &info->nsi_ferr);
++ info->hi_ferr = 0;
++ } else {
++ pci_read_config_byte(dev, E752X_HI_FERR,
++ &info->hi_ferr);
++ info->nsi_ferr = 0;
++ }
+ pci_read_config_word(dev, E752X_SYSBUS_FERR,
+ &info->sysbus_ferr);
+ pci_read_config_byte(dev, E752X_BUF_FERR, &info->buf_ferr);
+@@ -669,10 +781,15 @@ static void e752x_get_error_info(struct mem_ctl_info *mci,
+ pci_read_config_dword(dev, E752X_DRAM_RETR_ADD,
+ &info->dram_retr_add);
+
++ /* ignore the reserved bits just in case */
+ if (info->hi_ferr & 0x7f)
+ pci_write_config_byte(dev, E752X_HI_FERR,
+ info->hi_ferr);
+
++ if (info->nsi_ferr & NSI_ERR_MASK)
++ pci_write_config_dword(dev, I3100_NSI_FERR,
++ info->nsi_ferr);
++
+ if (info->sysbus_ferr)
+ pci_write_config_word(dev, E752X_SYSBUS_FERR,
+ info->sysbus_ferr);
+@@ -692,7 +809,15 @@ static void e752x_get_error_info(struct mem_ctl_info *mci,
+ pci_read_config_dword(dev, E752X_NERR_GLOBAL, &info->nerr_global);
+
+ if (info->nerr_global) {
+- pci_read_config_byte(dev, E752X_HI_NERR, &info->hi_nerr);
++ if (pvt->dev_info->err_dev == PCI_DEVICE_ID_INTEL_3100_1_ERR) {
++ pci_read_config_dword(dev, I3100_NSI_NERR,
++ &info->nsi_nerr);
++ info->hi_nerr = 0;
++ } else {
++ pci_read_config_byte(dev, E752X_HI_NERR,
++ &info->hi_nerr);
++ info->nsi_nerr = 0;
++ }
+ pci_read_config_word(dev, E752X_SYSBUS_NERR,
+ &info->sysbus_nerr);
+ pci_read_config_byte(dev, E752X_BUF_NERR, &info->buf_nerr);
+@@ -706,6 +831,10 @@ static void e752x_get_error_info(struct mem_ctl_info *mci,
+ pci_write_config_byte(dev, E752X_HI_NERR,
+ info->hi_nerr);
+
++ if (info->nsi_nerr & NSI_ERR_MASK)
++ pci_write_config_dword(dev, I3100_NSI_NERR,
++ info->nsi_nerr);
++
+ if (info->sysbus_nerr)
+ pci_write_config_word(dev, E752X_SYSBUS_NERR,
+ info->sysbus_nerr);
+@@ -750,6 +879,7 @@ static int e752x_process_error_info(struct mem_ctl_info *mci,
+ global_error(0, stat32, &error_found, handle_errors);
+
+ e752x_check_hub_interface(info, &error_found, handle_errors);
++ e752x_check_ns_interface(info, &error_found, handle_errors);
+ e752x_check_sysbus(info, &error_found, handle_errors);
+ e752x_check_membuf(info, &error_found, handle_errors);
+ e752x_check_dram(mci, info, &error_found, handle_errors);
+@@ -920,15 +1050,53 @@ fail:
+ return 1;
+ }
+
++/* Setup system bus parity mask register.
++ * Sysbus parity supported on:
++ * e7320/e7520/e7525 + Xeon
++ * i3100 + Xeon/Celeron
++ * Sysbus parity not supported on:
++ * i3100 + Pentium M/Celeron M/Core Duo/Core2 Duo
++ */
++static void e752x_init_sysbus_parity_mask(struct e752x_pvt *pvt)
++{
++ char *cpu_id = cpu_data(0).x86_model_id;
++ struct pci_dev *dev = pvt->dev_d0f1;
++ int enable = 1;
++
++ /* Allow module paramter override, else see if CPU supports parity */
++ if (sysbus_parity != -1) {
++ enable = sysbus_parity;
++ } else if (cpu_id[0] &&
++ ((strstr(cpu_id, "Pentium") && strstr(cpu_id, " M ")) ||
++ (strstr(cpu_id, "Celeron") && strstr(cpu_id, " M ")) ||
++ (strstr(cpu_id, "Core") && strstr(cpu_id, "Duo")))) {
++ e752x_printk(KERN_INFO, "System Bus Parity not "
++ "supported by CPU, disabling\n");
++ enable = 0;
++ }
++
++ if (enable)
++ pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x0000);
++ else
++ pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x0309);
++}
++
+ static void e752x_init_error_reporting_regs(struct e752x_pvt *pvt)
+ {
+ struct pci_dev *dev;
+
+ dev = pvt->dev_d0f1;
+ /* Turn off error disable & SMI in case the BIOS turned it on */
+- pci_write_config_byte(dev, E752X_HI_ERRMASK, 0x00);
+- pci_write_config_byte(dev, E752X_HI_SMICMD, 0x00);
+- pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x00);
++ if (pvt->dev_info->err_dev == PCI_DEVICE_ID_INTEL_3100_1_ERR) {
++ pci_write_config_dword(dev, I3100_NSI_EMASK, 0);
++ pci_write_config_dword(dev, I3100_NSI_SMICMD, 0);
++ } else {
++ pci_write_config_byte(dev, E752X_HI_ERRMASK, 0x00);
++ pci_write_config_byte(dev, E752X_HI_SMICMD, 0x00);
++ }
++
++ e752x_init_sysbus_parity_mask(pvt);
++
+ pci_write_config_word(dev, E752X_SYSBUS_SMICMD, 0x00);
+ pci_write_config_byte(dev, E752X_BUF_ERRMASK, 0x00);
+ pci_write_config_byte(dev, E752X_BUF_SMICMD, 0x00);
+@@ -949,16 +1117,6 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
+ debugf0("%s(): mci\n", __func__);
+ debugf0("Starting Probe1\n");
+
+- /* make sure error reporting method is sane */
+- switch (edac_op_state) {
+- case EDAC_OPSTATE_POLL:
+- case EDAC_OPSTATE_NMI:
+- break;
+- default:
+- edac_op_state = EDAC_OPSTATE_POLL;
+- break;
+- }
+-
+ /* check to see if device 0 function 1 is enabled; if it isn't, we
+ * assume the BIOS has reserved it for a reason and is expecting
+ * exclusive access, we take care not to violate that assumption and
+@@ -985,8 +1143,9 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
+
+ debugf3("%s(): init mci\n", __func__);
+ mci->mtype_cap = MEM_FLAG_RDDR;
+- mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED |
+- EDAC_FLAG_S4ECD4ED;
++ /* 3100 IMCH supports SECDEC only */
++ mci->edac_ctl_cap = (dev_idx == I3100) ? EDAC_FLAG_SECDED :
++ (EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED);
+ /* FIXME - what if different memory types are in different csrows? */
+ mci->mod_name = EDAC_MOD_STR;
+ mci->mod_ver = E752X_REVISION;
+@@ -1018,7 +1177,10 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
+ e752x_init_csrows(mci, pdev, ddrcsr);
+ e752x_init_mem_map_table(pdev, pvt);
+
+- mci->edac_cap |= EDAC_FLAG_NONE;
++ if (dev_idx == I3100)
++ mci->edac_cap = EDAC_FLAG_SECDED; /* the only mode supported */
++ else
++ mci->edac_cap |= EDAC_FLAG_NONE;
+ debugf3("%s(): tolm, remapbase, remaplimit\n", __func__);
+
+ /* load the top of low memory, remap base, and remap limit vars */
+@@ -1110,6 +1272,9 @@ static const struct pci_device_id e752x_pci_tbl[] __devinitdata = {
+ PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7320},
+ {
++ PCI_VEND_DEV(INTEL, 3100_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
++ I3100},
++ {
+ 0,
+ } /* 0 terminated list. */
+ };
+@@ -1128,6 +1293,10 @@ static int __init e752x_init(void)
+ int pci_rc;
+
+ debugf3("%s()\n", __func__);
++
++ /* Ensure that the OPSTATE is set correctly for POLL or NMI */
++ opstate_init();
++
+ pci_rc = pci_register_driver(&e752x_driver);
+ return (pci_rc < 0) ? pci_rc : 0;
+ }
+@@ -1143,10 +1312,15 @@ module_exit(e752x_exit);
+
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman\n");
+-MODULE_DESCRIPTION("MC support for Intel e752x memory controllers");
++MODULE_DESCRIPTION("MC support for Intel e752x/3100 memory controllers");
+
+ module_param(force_function_unhide, int, 0444);
+ MODULE_PARM_DESC(force_function_unhide, "if BIOS sets Dev0:Fun1 up as hidden:"
+ " 1=force unhide and hope BIOS doesn't fight driver for Dev0:Fun1 access");
++
+ module_param(edac_op_state, int, 0444);
+ MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
++
++module_param(sysbus_parity, int, 0444);
++MODULE_PARM_DESC(sysbus_parity, "0=disable system bus parity checking,"
++ " 1=enable system bus parity checking, default=auto-detect");
+diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c
+index 96ecc49..c7d11cc 100644
+--- a/drivers/edac/e7xxx_edac.c
++++ b/drivers/edac/e7xxx_edac.c
+@@ -414,16 +414,6 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
+
+ debugf0("%s(): mci\n", __func__);
+
+- /* make sure error reporting method is sane */
+- switch (edac_op_state) {
+- case EDAC_OPSTATE_POLL:
+- case EDAC_OPSTATE_NMI:
+- break;
+- default:
+- edac_op_state = EDAC_OPSTATE_POLL;
+- break;
+- }
+-
+ pci_read_config_dword(pdev, E7XXX_DRC, &drc);
+
+ drc_chan = dual_channel_active(drc, dev_idx);
+@@ -565,6 +555,9 @@ static struct pci_driver e7xxx_driver = {
+
+ static int __init e7xxx_init(void)
+ {
++ /* Ensure that the OPSTATE is set correctly for POLL or NMI */
++ opstate_init();
++
+ return pci_register_driver(&e7xxx_driver);
+ }
+
+diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c
+index b9552bc..63372fa 100644
+--- a/drivers/edac/edac_device.c
++++ b/drivers/edac/edac_device.c
+@@ -36,7 +36,7 @@
+ * is protected by the 'device_ctls_mutex' lock
+ */
+ static DEFINE_MUTEX(device_ctls_mutex);
+-static struct list_head edac_device_list = LIST_HEAD_INIT(edac_device_list);
++static LIST_HEAD(edac_device_list);
+
+ #ifdef CONFIG_EDAC_DEBUG
+ static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev)
+@@ -375,37 +375,6 @@ static void del_edac_device_from_global_list(struct edac_device_ctl_info
+ wait_for_completion(&edac_device->removal_complete);
+ }
+
+-/**
+- * edac_device_find
+- * Search for a edac_device_ctl_info structure whose index is 'idx'.
+- *
+- * If found, return a pointer to the structure.
+- * Else return NULL.
+- *
+- * Caller must hold device_ctls_mutex.
+- */
+-struct edac_device_ctl_info *edac_device_find(int idx)
+-{
+- struct list_head *item;
+- struct edac_device_ctl_info *edac_dev;
+-
+- /* Iterate over list, looking for exact match of ID */
+- list_for_each(item, &edac_device_list) {
+- edac_dev = list_entry(item, struct edac_device_ctl_info, link);
+-
+- if (edac_dev->dev_idx >= idx) {
+- if (edac_dev->dev_idx == idx)
+- return edac_dev;
+-
+- /* not on list, so terminate early */
+- break;
+- }
+- }
+-
+- return NULL;
+-}
+-EXPORT_SYMBOL_GPL(edac_device_find);
+-
+ /*
+ * edac_device_workq_function
+ * performs the operation scheduled by a workq request
+diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
+index 063a1bf..a4cf164 100644
+--- a/drivers/edac/edac_mc.c
++++ b/drivers/edac/edac_mc.c
+@@ -36,7 +36,7 @@
+
+ /* lock to memory controller's control array */
+ static DEFINE_MUTEX(mem_ctls_mutex);
+-static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices);
++static LIST_HEAD(mc_devices);
+
+ #ifdef CONFIG_EDAC_DEBUG
+
+@@ -886,24 +886,3 @@ void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci,
+ mci->csrows[csrow].channels[channel].ce_count++;
+ }
+ EXPORT_SYMBOL(edac_mc_handle_fbd_ce);
+-
+-/*
+- * Iterate over all MC instances and check for ECC, et al, errors
+- */
+-void edac_check_mc_devices(void)
+-{
+- struct list_head *item;
+- struct mem_ctl_info *mci;
+-
+- debugf3("%s()\n", __func__);
+- mutex_lock(&mem_ctls_mutex);
+-
+- list_for_each(item, &mc_devices) {
+- mci = list_entry(item, struct mem_ctl_info, link);
+-
+- if (mci->edac_check != NULL)
+- mci->edac_check(mci);
+- }
+-
+- mutex_unlock(&mem_ctls_mutex);
+-}
+diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h
+index cbc419c..233d479 100644
+--- a/drivers/edac/edac_module.h
++++ b/drivers/edac/edac_module.h
+@@ -27,7 +27,6 @@ extern int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci);
+ extern void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci);
+ extern int edac_create_sysfs_mci_device(struct mem_ctl_info *mci);
+ extern void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci);
+-extern void edac_check_mc_devices(void);
+ extern int edac_get_log_ue(void);
+ extern int edac_get_log_ce(void);
+ extern int edac_get_panic_on_ue(void);
+diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c
+index 32be435..9b24340 100644
+--- a/drivers/edac/edac_pci.c
++++ b/drivers/edac/edac_pci.c
+@@ -29,7 +29,7 @@
+ #include "edac_module.h"
+
+ static DEFINE_MUTEX(edac_pci_ctls_mutex);
+-static struct list_head edac_pci_list = LIST_HEAD_INIT(edac_pci_list);
++static LIST_HEAD(edac_pci_list);
+
+ /*
+ * edac_pci_alloc_ctl_info
+@@ -189,6 +189,9 @@ static void del_edac_pci_from_global_list(struct edac_pci_ctl_info *pci)
+ wait_for_completion(&pci->complete);
+ }
+
++#if 0
++/* Older code, but might use in the future */
++
+ /*
+ * edac_pci_find()
+ * Search for an edac_pci_ctl_info structure whose index is 'idx'
+@@ -219,6 +222,7 @@ struct edac_pci_ctl_info *edac_pci_find(int idx)
+ return NULL;
+ }
+ EXPORT_SYMBOL_GPL(edac_pci_find);
++#endif
+
+ /*
+ * edac_pci_workq_function()
+@@ -422,7 +426,7 @@ EXPORT_SYMBOL_GPL(edac_pci_del_device);
+ *
+ * a Generic parity check API
+ */
+-void edac_pci_generic_check(struct edac_pci_ctl_info *pci)
++static void edac_pci_generic_check(struct edac_pci_ctl_info *pci)
+ {
+ debugf4("%s()\n", __func__);
+ edac_pci_do_parity_check();
+diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c
+index 71c3195..2c1fa1b 100644
+--- a/drivers/edac/edac_pci_sysfs.c
++++ b/drivers/edac/edac_pci_sysfs.c
+@@ -37,17 +37,17 @@ int edac_pci_get_check_errors(void)
+ return check_pci_errors;
+ }
+
+-int edac_pci_get_log_pe(void)
++static int edac_pci_get_log_pe(void)
+ {
+ return edac_pci_log_pe;
+ }
+
+-int edac_pci_get_log_npe(void)
++static int edac_pci_get_log_npe(void)
+ {
+ return edac_pci_log_npe;
+ }
+
+-int edac_pci_get_panic_on_pe(void)
++static int edac_pci_get_panic_on_pe(void)
+ {
+ return edac_pci_panic_on_pe;
+ }
+@@ -197,7 +197,8 @@ error_out:
+ *
+ * unregister the kobj for the EDAC PCI instance
+ */
+-void edac_pci_unregister_sysfs_instance_kobj(struct edac_pci_ctl_info *pci)
++static void edac_pci_unregister_sysfs_instance_kobj(
++ struct edac_pci_ctl_info *pci)
+ {
+ debugf0("%s()\n", __func__);
+
+@@ -337,7 +338,7 @@ static struct kobj_type ktype_edac_pci_main_kobj = {
+ * setup the sysfs for EDAC PCI attributes
+ * assumes edac_class has already been initialized
+ */
+-int edac_pci_main_kobj_setup(void)
++static int edac_pci_main_kobj_setup(void)
+ {
+ int err;
+ struct sysdev_class *edac_class;
+diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c
+index 5d42928..6c9a0f2 100644
+--- a/drivers/edac/i3000_edac.c
++++ b/drivers/edac/i3000_edac.c
+@@ -326,15 +326,6 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx)
+ return -ENODEV;
+ }
+
+- switch (edac_op_state) {
+- case EDAC_OPSTATE_POLL:
+- case EDAC_OPSTATE_NMI:
+- break;
+- default:
+- edac_op_state = EDAC_OPSTATE_POLL;
+- break;
+- }
+-
+ c0dra[0] = readb(window + I3000_C0DRA + 0); /* ranks 0,1 */
+ c0dra[1] = readb(window + I3000_C0DRA + 1); /* ranks 2,3 */
+ c1dra[0] = readb(window + I3000_C1DRA + 0); /* ranks 0,1 */
+@@ -503,6 +494,10 @@ static int __init i3000_init(void)
+ int pci_rc;
+
+ debugf3("MC: %s()\n", __func__);
++
++ /* Ensure that the OPSTATE is set correctly for POLL or NMI */
++ opstate_init();
++
+ pci_rc = pci_register_driver(&i3000_driver);
+ if (pci_rc < 0)
+ goto fail0;
+diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c
+index 5a85201..4a16b5b 100644
+--- a/drivers/edac/i5000_edac.c
++++ b/drivers/edac/i5000_edac.c
+@@ -1286,16 +1286,6 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx)
+ if (PCI_FUNC(pdev->devfn) != 0)
+ return -ENODEV;
+
+- /* make sure error reporting method is sane */
+- switch (edac_op_state) {
+- case EDAC_OPSTATE_POLL:
+- case EDAC_OPSTATE_NMI:
+- break;
+- default:
+- edac_op_state = EDAC_OPSTATE_POLL;
+- break;
+- }
+-
+ /* Ask the devices for the number of CSROWS and CHANNELS so
+ * that we can calculate the memory resources, etc
+ *
+@@ -1478,6 +1468,9 @@ static int __init i5000_init(void)
+
+ debugf2("MC: " __FILE__ ": %s()\n", __func__);
+
++ /* Ensure that the OPSTATE is set correctly for POLL or NMI */
++ opstate_init();
++
+ pci_rc = pci_register_driver(&i5000_driver);
+
+ return (pci_rc < 0) ? pci_rc : 0;
+@@ -1501,5 +1494,6 @@ MODULE_AUTHOR
+ ("Linux Networx (http://lnxi.com) Doug Thompson <norsk5 at xmission.com>");
+ MODULE_DESCRIPTION("MC Driver for Intel I5000 memory controllers - "
+ I5000_REVISION);
++
+ module_param(edac_op_state, int, 0444);
+ MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
+diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c
+index 83bfe37..c5305e3 100644
+--- a/drivers/edac/i82443bxgx_edac.c
++++ b/drivers/edac/i82443bxgx_edac.c
+@@ -29,6 +29,7 @@
+
+ #include <linux/slab.h>
+
++#include <linux/edac.h>
+ #include "edac_core.h"
+
+ #define I82443_REVISION "0.1"
+@@ -386,6 +387,9 @@ static struct pci_driver i82443bxgx_edacmc_driver = {
+
+ static int __init i82443bxgx_edacmc_init(void)
+ {
++ /* Ensure that the OPSTATE is set correctly for POLL or NMI */
++ opstate_init();
++
+ return pci_register_driver(&i82443bxgx_edacmc_driver);
+ }
+
+@@ -400,3 +404,6 @@ module_exit(i82443bxgx_edacmc_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Tim Small <tim at buttersideup.com> - WPAD");
+ MODULE_DESCRIPTION("EDAC MC support for Intel 82443BX/GX memory controllers");
++
++module_param(edac_op_state, int, 0444);
++MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
+diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c
+index f5ecd2c..c0088ba 100644
+--- a/drivers/edac/i82860_edac.c
++++ b/drivers/edac/i82860_edac.c
+@@ -14,6 +14,7 @@
+ #include <linux/pci.h>
+ #include <linux/pci_ids.h>
+ #include <linux/slab.h>
++#include <linux/edac.h>
+ #include "edac_core.h"
+
+ #define I82860_REVISION " Ver: 2.0.2 " __DATE__
+@@ -294,6 +295,9 @@ static int __init i82860_init(void)
+
+ debugf3("%s()\n", __func__);
+
++ /* Ensure that the OPSTATE is set correctly for POLL or NMI */
++ opstate_init();
++
+ if ((pci_rc = pci_register_driver(&i82860_driver)) < 0)
+ goto fail0;
+
+@@ -345,3 +349,6 @@ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com) "
+ "Ben Woodard <woodard at redhat.com>");
+ MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers");
++
++module_param(edac_op_state, int, 0444);
++MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
+diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c
+index 031abad..e43bdc4 100644
+--- a/drivers/edac/i82875p_edac.c
++++ b/drivers/edac/i82875p_edac.c
+@@ -18,6 +18,7 @@
+ #include <linux/pci.h>
+ #include <linux/pci_ids.h>
+ #include <linux/slab.h>
++#include <linux/edac.h>
+ #include "edac_core.h"
+
+ #define I82875P_REVISION " Ver: 2.0.2 " __DATE__
+@@ -393,6 +394,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
+ struct i82875p_error_info discard;
+
+ debugf0("%s()\n", __func__);
++
+ ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL);
+
+ if (i82875p_setup_overfl_dev(pdev, &ovrfl_pdev, &ovrfl_window))
+@@ -532,6 +534,10 @@ static int __init i82875p_init(void)
+ int pci_rc;
+
+ debugf3("%s()\n", __func__);
++
++ /* Ensure that the OPSTATE is set correctly for POLL or NMI */
++ opstate_init();
++
+ pci_rc = pci_register_driver(&i82875p_driver);
+
+ if (pci_rc < 0)
+@@ -586,3 +592,6 @@ module_exit(i82875p_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
+ MODULE_DESCRIPTION("MC support for Intel 82875 memory hub controllers");
++
++module_param(edac_op_state, int, 0444);
++MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
+diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c
+index 0ee8884..2eed3ea 100644
+--- a/drivers/edac/i82975x_edac.c
++++ b/drivers/edac/i82975x_edac.c
+@@ -14,7 +14,7 @@
+ #include <linux/pci.h>
+ #include <linux/pci_ids.h>
+ #include <linux/slab.h>
+-
++#include <linux/edac.h>
+ #include "edac_core.h"
+
+ #define I82975X_REVISION " Ver: 1.0.0 " __DATE__
+@@ -611,6 +611,9 @@ static int __init i82975x_init(void)
+
+ debugf3("%s()\n", __func__);
+
++ /* Ensure that the OPSTATE is set correctly for POLL or NMI */
++ opstate_init();
++
+ pci_rc = pci_register_driver(&i82975x_driver);
+ if (pci_rc < 0)
+ goto fail0;
+@@ -664,3 +667,6 @@ module_exit(i82975x_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Arvind R. <arvind at acarlab.com>");
+ MODULE_DESCRIPTION("MC support for Intel 82975 memory hub controllers");
++
++module_param(edac_op_state, int, 0444);
++MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
+diff --git a/drivers/edac/pasemi_edac.c b/drivers/edac/pasemi_edac.c
+index 9032091..8e6b91b 100644
+--- a/drivers/edac/pasemi_edac.c
++++ b/drivers/edac/pasemi_edac.c
+@@ -26,6 +26,7 @@
+ #include <linux/pci.h>
+ #include <linux/pci_ids.h>
+ #include <linux/slab.h>
++#include <linux/edac.h>
+ #include "edac_core.h"
+
+ #define MODULE_NAME "pasemi_edac"
+@@ -284,6 +285,9 @@ static struct pci_driver pasemi_edac_driver = {
+
+ static int __init pasemi_edac_init(void)
+ {
++ /* Ensure that the OPSTATE is set correctly for POLL or NMI */
++ opstate_init();
++
+ return pci_register_driver(&pasemi_edac_driver);
+ }
+
+@@ -298,3 +302,6 @@ module_exit(pasemi_edac_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Egor Martovetsky <egor at pasemi.com>");
+ MODULE_DESCRIPTION("MC support for PA Semi PWRficient memory controller");
++module_param(edac_op_state, int, 0444);
++MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
++
+diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c
+index e25f712..9900675 100644
+--- a/drivers/edac/r82600_edac.c
++++ b/drivers/edac/r82600_edac.c
+@@ -20,6 +20,7 @@
+ #include <linux/pci.h>
+ #include <linux/pci_ids.h>
+ #include <linux/slab.h>
++#include <linux/edac.h>
+ #include "edac_core.h"
+
+ #define R82600_REVISION " Ver: 2.0.2 " __DATE__
+@@ -393,6 +394,9 @@ static struct pci_driver r82600_driver = {
+
+ static int __init r82600_init(void)
+ {
++ /* Ensure that the OPSTATE is set correctly for POLL or NMI */
++ opstate_init();
++
+ return pci_register_driver(&r82600_driver);
+ }
+
+@@ -412,3 +416,6 @@ MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers");
+ module_param(disable_hardware_scrub, bool, 0644);
+ MODULE_PARM_DESC(disable_hardware_scrub,
+ "If set, disable the chipset's automatic scrub for CEs");
++
++module_param(edac_op_state, int, 0444);
++MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
+diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig
+index 25bdc2d..fb4d391 100644
+--- a/drivers/firewire/Kconfig
++++ b/drivers/firewire/Kconfig
+@@ -54,6 +54,11 @@ config FIREWIRE_OHCI
+ directive, use "install modulename /bin/true" for the modules to be
+ blacklisted.
+
++config FIREWIRE_OHCI_DEBUG
++ bool
++ depends on FIREWIRE_OHCI
++ default y
++
+ config FIREWIRE_SBP2
+ tristate "Support for storage devices (SBP-2 protocol driver)"
+ depends on FIREWIRE && SCSI
+diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
+index a034627..5b4c0d9 100644
+--- a/drivers/firewire/fw-card.c
++++ b/drivers/firewire/fw-card.c
+@@ -167,7 +167,6 @@ fw_core_add_descriptor(struct fw_descriptor *desc)
+
+ return 0;
+ }
+-EXPORT_SYMBOL(fw_core_add_descriptor);
+
+ void
+ fw_core_remove_descriptor(struct fw_descriptor *desc)
+@@ -182,7 +181,6 @@ fw_core_remove_descriptor(struct fw_descriptor *desc)
+
+ mutex_unlock(&card_mutex);
+ }
+-EXPORT_SYMBOL(fw_core_remove_descriptor);
+
+ static const char gap_count_table[] = {
+ 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
+@@ -220,7 +218,7 @@ fw_card_bm_work(struct work_struct *work)
+ struct bm_data bmd;
+ unsigned long flags;
+ int root_id, new_root_id, irm_id, gap_count, generation, grace;
+- int do_reset = 0;
++ bool do_reset = false;
+
+ spin_lock_irqsave(&card->lock, flags);
+ local_node = card->local_node;
+@@ -331,7 +329,7 @@ fw_card_bm_work(struct work_struct *work)
+ */
+ spin_unlock_irqrestore(&card->lock, flags);
+ goto out;
+- } else if (root_device->config_rom[2] & BIB_CMC) {
++ } else if (root_device->cmc) {
+ /*
+ * FIXME: I suppose we should set the cmstr bit in the
+ * STATE_CLEAR register of this node, as described in
+@@ -360,14 +358,14 @@ fw_card_bm_work(struct work_struct *work)
+ gap_count = 63;
+
+ /*
+- * Finally, figure out if we should do a reset or not. If we've
+- * done less that 5 resets with the same physical topology and we
++ * Finally, figure out if we should do a reset or not. If we have
++ * done less than 5 resets with the same physical topology and we
+ * have either a new root or a new gap count setting, let's do it.
+ */
+
+ if (card->bm_retries++ < 5 &&
+ (card->gap_count != gap_count || new_root_id != root_id))
+- do_reset = 1;
++ do_reset = true;
+
+ spin_unlock_irqrestore(&card->lock, flags);
+
+@@ -398,7 +396,6 @@ fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver,
+ {
+ static atomic_t index = ATOMIC_INIT(-1);
+
+- kref_init(&card->kref);
+ atomic_set(&card->device_count, 0);
+ card->index = atomic_inc_return(&index);
+ card->driver = driver;
+@@ -429,12 +426,6 @@ fw_card_add(struct fw_card *card,
+ card->link_speed = link_speed;
+ card->guid = guid;
+
+- /*
+- * The subsystem grabs a reference when the card is added and
+- * drops it when the driver calls fw_core_remove_card.
+- */
+- fw_card_get(card);
+-
+ mutex_lock(&card_mutex);
+ config_rom = generate_config_rom(card, &length);
+ list_add_tail(&card->link, &card_list);
+@@ -540,40 +531,9 @@ fw_core_remove_card(struct fw_card *card)
+ cancel_delayed_work_sync(&card->work);
+ fw_flush_transactions(card);
+ del_timer_sync(&card->flush_timer);
+-
+- fw_card_put(card);
+ }
+ EXPORT_SYMBOL(fw_core_remove_card);
+
+-struct fw_card *
+-fw_card_get(struct fw_card *card)
+-{
+- kref_get(&card->kref);
+-
+- return card;
+-}
+-EXPORT_SYMBOL(fw_card_get);
+-
+-static void
+-release_card(struct kref *kref)
+-{
+- struct fw_card *card = container_of(kref, struct fw_card, kref);
+-
+- kfree(card);
+-}
+-
+-/*
+- * An assumption for fw_card_put() is that the card driver allocates
+- * the fw_card struct with kalloc and that it has been shut down
+- * before the last ref is dropped.
+- */
+-void
+-fw_card_put(struct fw_card *card)
+-{
+- kref_put(&card->kref, release_card);
+-}
+-EXPORT_SYMBOL(fw_card_put);
+-
+ int
+ fw_core_initiate_bus_reset(struct fw_card *card, int short_reset)
+ {
+diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
+index 46bc197..4a54192 100644
+--- a/drivers/firewire/fw-cdev.c
++++ b/drivers/firewire/fw-cdev.c
+@@ -269,21 +269,28 @@ static int ioctl_get_info(struct client *client, void *buffer)
+ {
+ struct fw_cdev_get_info *get_info = buffer;
+ struct fw_cdev_event_bus_reset bus_reset;
++ unsigned long ret = 0;
+
+ client->version = get_info->version;
+ get_info->version = FW_CDEV_VERSION;
+
++ down_read(&fw_device_rwsem);
++
+ if (get_info->rom != 0) {
+ void __user *uptr = u64_to_uptr(get_info->rom);
+ size_t want = get_info->rom_length;
+ size_t have = client->device->config_rom_length * 4;
+
+- if (copy_to_user(uptr, client->device->config_rom,
+- min(want, have)))
+- return -EFAULT;
++ ret = copy_to_user(uptr, client->device->config_rom,
++ min(want, have));
+ }
+ get_info->rom_length = client->device->config_rom_length * 4;
+
++ up_read(&fw_device_rwsem);
++
++ if (ret != 0)
++ return -EFAULT;
++
+ client->bus_reset_closure = get_info->bus_reset_closure;
+ if (get_info->bus_reset != 0) {
+ void __user *uptr = u64_to_uptr(get_info->bus_reset);
+diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
+index 870125a..d9c8daf 100644
+--- a/drivers/firewire/fw-device.c
++++ b/drivers/firewire/fw-device.c
+@@ -25,8 +25,9 @@
+ #include <linux/device.h>
+ #include <linux/delay.h>
+ #include <linux/idr.h>
++#include <linux/string.h>
+ #include <linux/rwsem.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <asm/system.h>
+ #include <linux/ctype.h>
+ #include "fw-transaction.h"
+@@ -160,9 +161,9 @@ static void fw_device_release(struct device *dev)
+ * Take the card lock so we don't set this to NULL while a
+ * FW_NODE_UPDATED callback is being handled.
+ */
+- spin_lock_irqsave(&device->card->lock, flags);
++ spin_lock_irqsave(&card->lock, flags);
+ device->node->data = NULL;
+- spin_unlock_irqrestore(&device->card->lock, flags);
++ spin_unlock_irqrestore(&card->lock, flags);
+
+ fw_node_put(device->node);
+ kfree(device->config_rom);
+@@ -195,7 +196,9 @@ show_immediate(struct device *dev, struct device_attribute *dattr, char *buf)
+ container_of(dattr, struct config_rom_attribute, attr);
+ struct fw_csr_iterator ci;
+ u32 *dir;
+- int key, value;
++ int key, value, ret = -ENOENT;
++
++ down_read(&fw_device_rwsem);
+
+ if (is_fw_unit(dev))
+ dir = fw_unit(dev)->directory;
+@@ -204,11 +207,15 @@ show_immediate(struct device *dev, struct device_attribute *dattr, char *buf)
+
+ fw_csr_iterator_init(&ci, dir);
+ while (fw_csr_iterator_next(&ci, &key, &value))
+- if (attr->key == key)
+- return snprintf(buf, buf ? PAGE_SIZE : 0,
+- "0x%06x\n", value);
++ if (attr->key == key) {
++ ret = snprintf(buf, buf ? PAGE_SIZE : 0,
++ "0x%06x\n", value);
++ break;
++ }
++
++ up_read(&fw_device_rwsem);
+
+- return -ENOENT;
++ return ret;
+ }
+
+ #define IMMEDIATE_ATTR(name, key) \
+@@ -221,9 +228,11 @@ show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf)
+ container_of(dattr, struct config_rom_attribute, attr);
+ struct fw_csr_iterator ci;
+ u32 *dir, *block = NULL, *p, *end;
+- int length, key, value, last_key = 0;
++ int length, key, value, last_key = 0, ret = -ENOENT;
+ char *b;
+
++ down_read(&fw_device_rwsem);
++
+ if (is_fw_unit(dev))
+ dir = fw_unit(dev)->directory;
+ else
+@@ -238,18 +247,20 @@ show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf)
+ }
+
+ if (block == NULL)
+- return -ENOENT;
++ goto out;
+
+ length = min(block[0] >> 16, 256U);
+ if (length < 3)
+- return -ENOENT;
++ goto out;
+
+ if (block[1] != 0 || block[2] != 0)
+ /* Unknown encoding. */
+- return -ENOENT;
++ goto out;
+
+- if (buf == NULL)
+- return length * 4;
++ if (buf == NULL) {
++ ret = length * 4;
++ goto out;
++ }
+
+ b = buf;
+ end = &block[length + 1];
+@@ -259,8 +270,11 @@ show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf)
+ /* Strip trailing whitespace and add newline. */
+ while (b--, (isspace(*b) || *b == '\0') && b > buf);
+ strcpy(b + 1, "\n");
++ ret = b + 2 - buf;
++ out:
++ up_read(&fw_device_rwsem);
+
+- return b + 2 - buf;
++ return ret;
+ }
+
+ #define TEXT_LEAF_ATTR(name, key) \
+@@ -337,19 +351,28 @@ static ssize_t
+ config_rom_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+ struct fw_device *device = fw_device(dev);
++ size_t length;
+
+- memcpy(buf, device->config_rom, device->config_rom_length * 4);
++ down_read(&fw_device_rwsem);
++ length = device->config_rom_length * 4;
++ memcpy(buf, device->config_rom, length);
++ up_read(&fw_device_rwsem);
+
+- return device->config_rom_length * 4;
++ return length;
+ }
+
+ static ssize_t
+ guid_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+ struct fw_device *device = fw_device(dev);
++ int ret;
++
++ down_read(&fw_device_rwsem);
++ ret = snprintf(buf, PAGE_SIZE, "0x%08x%08x\n",
++ device->config_rom[3], device->config_rom[4]);
++ up_read(&fw_device_rwsem);
+
+- return snprintf(buf, PAGE_SIZE, "0x%08x%08x\n",
+- device->config_rom[3], device->config_rom[4]);
++ return ret;
+ }
+
+ static struct device_attribute fw_device_attributes[] = {
+@@ -388,7 +411,7 @@ read_rom(struct fw_device *device, int generation, int index, u32 *data)
+
+ init_completion(&callback_data.done);
+
+- offset = 0xfffff0000400ULL + index * 4;
++ offset = (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4;
+ fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
+ device->node_id, generation, device->max_speed,
+ offset, NULL, 4, complete_transaction, &callback_data);
+@@ -400,6 +423,9 @@ read_rom(struct fw_device *device, int generation, int index, u32 *data)
+ return callback_data.rcode;
+ }
+
++#define READ_BIB_ROM_SIZE 256
++#define READ_BIB_STACK_SIZE 16
++
+ /*
+ * Read the bus info block, perform a speed probe, and read all of the rest of
+ * the config ROM. We do all this with a cached bus generation. If the bus
+@@ -409,16 +435,23 @@ read_rom(struct fw_device *device, int generation, int index, u32 *data)
+ */
+ static int read_bus_info_block(struct fw_device *device, int generation)
+ {
+- static u32 rom[256];
+- u32 stack[16], sp, key;
+- int i, end, length;
++ u32 *rom, *stack, *old_rom, *new_rom;
++ u32 sp, key;
++ int i, end, length, ret = -1;
++
++ rom = kmalloc(sizeof(*rom) * READ_BIB_ROM_SIZE +
++ sizeof(*stack) * READ_BIB_STACK_SIZE, GFP_KERNEL);
++ if (rom == NULL)
++ return -ENOMEM;
++
++ stack = &rom[READ_BIB_ROM_SIZE];
+
+ device->max_speed = SCODE_100;
+
+ /* First read the bus info block. */
+ for (i = 0; i < 5; i++) {
+ if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
+- return -1;
++ goto out;
+ /*
+ * As per IEEE1212 7.2, during power-up, devices can
+ * reply with a 0 for the first quadlet of the config
+@@ -428,7 +461,7 @@ static int read_bus_info_block(struct fw_device *device, int generation)
+ * retry mechanism will try again later.
+ */
+ if (i == 0 && rom[i] == 0)
+- return -1;
++ goto out;
+ }
+
+ device->max_speed = device->node->max_speed;
+@@ -478,26 +511,26 @@ static int read_bus_info_block(struct fw_device *device, int generation)
+ */
+ key = stack[--sp];
+ i = key & 0xffffff;
+- if (i >= ARRAY_SIZE(rom))
++ if (i >= READ_BIB_ROM_SIZE)
+ /*
+ * The reference points outside the standard
+ * config rom area, something's fishy.
+ */
+- return -1;
++ goto out;
+
+ /* Read header quadlet for the block to get the length. */
+ if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
+- return -1;
++ goto out;
+ end = i + (rom[i] >> 16) + 1;
+ i++;
+- if (end > ARRAY_SIZE(rom))
++ if (end > READ_BIB_ROM_SIZE)
+ /*
+ * This block extends outside standard config
+ * area (and the array we're reading it
+ * into). That's broken, so ignore this
+ * device.
+ */
+- return -1;
++ goto out;
+
+ /*
+ * Now read in the block. If this is a directory
+@@ -507,9 +540,9 @@ static int read_bus_info_block(struct fw_device *device, int generation)
+ while (i < end) {
+ if (read_rom(device, generation, i, &rom[i]) !=
+ RCODE_COMPLETE)
+- return -1;
++ goto out;
+ if ((key >> 30) == 3 && (rom[i] >> 30) > 1 &&
+- sp < ARRAY_SIZE(stack))
++ sp < READ_BIB_STACK_SIZE)
+ stack[sp++] = i + rom[i];
+ i++;
+ }
+@@ -517,13 +550,23 @@ static int read_bus_info_block(struct fw_device *device, int generation)
+ length = i;
+ }
+
+- device->config_rom = kmalloc(length * 4, GFP_KERNEL);
+- if (device->config_rom == NULL)
+- return -1;
+- memcpy(device->config_rom, rom, length * 4);
++ old_rom = device->config_rom;
++ new_rom = kmemdup(rom, length * 4, GFP_KERNEL);
++ if (new_rom == NULL)
++ goto out;
++
++ down_write(&fw_device_rwsem);
++ device->config_rom = new_rom;
+ device->config_rom_length = length;
++ up_write(&fw_device_rwsem);
+
+- return 0;
++ kfree(old_rom);
++ ret = 0;
++ device->cmc = rom[2] & 1 << 30;
++ out:
++ kfree(rom);
++
++ return ret;
+ }
+
+ static void fw_unit_release(struct device *dev)
+@@ -592,7 +635,14 @@ static int shutdown_unit(struct device *device, void *data)
+ return 0;
+ }
+
+-static DECLARE_RWSEM(idr_rwsem);
++/*
++ * fw_device_rwsem acts as dual purpose mutex:
++ * - serializes accesses to fw_device_idr,
++ * - serializes accesses to fw_device.config_rom/.config_rom_length and
++ * fw_unit.directory, unless those accesses happen at safe occasions
++ */
++DECLARE_RWSEM(fw_device_rwsem);
++
+ static DEFINE_IDR(fw_device_idr);
+ int fw_cdev_major;
+
+@@ -600,11 +650,11 @@ struct fw_device *fw_device_get_by_devt(dev_t devt)
+ {
+ struct fw_device *device;
+
+- down_read(&idr_rwsem);
++ down_read(&fw_device_rwsem);
+ device = idr_find(&fw_device_idr, MINOR(devt));
+ if (device)
+ fw_device_get(device);
+- up_read(&idr_rwsem);
++ up_read(&fw_device_rwsem);
+
+ return device;
+ }
+@@ -619,9 +669,9 @@ static void fw_device_shutdown(struct work_struct *work)
+ device_for_each_child(&device->device, NULL, shutdown_unit);
+ device_unregister(&device->device);
+
+- down_write(&idr_rwsem);
++ down_write(&fw_device_rwsem);
+ idr_remove(&fw_device_idr, minor);
+- up_write(&idr_rwsem);
++ up_write(&fw_device_rwsem);
+ fw_device_put(device);
+ }
+
+@@ -674,10 +724,10 @@ static void fw_device_init(struct work_struct *work)
+ err = -ENOMEM;
+
+ fw_device_get(device);
+- down_write(&idr_rwsem);
++ down_write(&fw_device_rwsem);
+ if (idr_pre_get(&fw_device_idr, GFP_KERNEL))
+ err = idr_get_new(&fw_device_idr, device, &minor);
+- up_write(&idr_rwsem);
++ up_write(&fw_device_rwsem);
+
+ if (err < 0)
+ goto error;
+@@ -711,7 +761,7 @@ static void fw_device_init(struct work_struct *work)
+ if (atomic_cmpxchg(&device->state,
+ FW_DEVICE_INITIALIZING,
+ FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) {
+- fw_device_shutdown(&device->work.work);
++ fw_device_shutdown(work);
+ } else {
+ if (device->config_rom_retries)
+ fw_notify("created device %s: GUID %08x%08x, S%d00, "
+@@ -725,6 +775,7 @@ static void fw_device_init(struct work_struct *work)
+ device->device.bus_id,
+ device->config_rom[3], device->config_rom[4],
+ 1 << device->max_speed);
++ device->config_rom_retries = 0;
+ }
+
+ /*
+@@ -739,9 +790,9 @@ static void fw_device_init(struct work_struct *work)
+ return;
+
+ error_with_cdev:
+- down_write(&idr_rwsem);
++ down_write(&fw_device_rwsem);
+ idr_remove(&fw_device_idr, minor);
+- up_write(&idr_rwsem);
++ up_write(&fw_device_rwsem);
+ error:
+ fw_device_put(device); /* fw_device_idr's reference */
+
+@@ -771,6 +822,106 @@ static void fw_device_update(struct work_struct *work)
+ device_for_each_child(&device->device, NULL, update_unit);
+ }
+
++enum {
++ REREAD_BIB_ERROR,
++ REREAD_BIB_GONE,
++ REREAD_BIB_UNCHANGED,
++ REREAD_BIB_CHANGED,
++};
++
++/* Reread and compare bus info block and header of root directory */
++static int reread_bus_info_block(struct fw_device *device, int generation)
++{
++ u32 q;
++ int i;
++
++ for (i = 0; i < 6; i++) {
++ if (read_rom(device, generation, i, &q) != RCODE_COMPLETE)
++ return REREAD_BIB_ERROR;
++
++ if (i == 0 && q == 0)
++ return REREAD_BIB_GONE;
++
++ if (i > device->config_rom_length || q != device->config_rom[i])
++ return REREAD_BIB_CHANGED;
++ }
++
++ return REREAD_BIB_UNCHANGED;
++}
++
++static void fw_device_refresh(struct work_struct *work)
++{
++ struct fw_device *device =
++ container_of(work, struct fw_device, work.work);
++ struct fw_card *card = device->card;
++ int node_id = device->node_id;
++
++ switch (reread_bus_info_block(device, device->generation)) {
++ case REREAD_BIB_ERROR:
++ if (device->config_rom_retries < MAX_RETRIES / 2 &&
++ atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
++ device->config_rom_retries++;
++ schedule_delayed_work(&device->work, RETRY_DELAY / 2);
++
++ return;
++ }
++ goto give_up;
++
++ case REREAD_BIB_GONE:
++ goto gone;
++
++ case REREAD_BIB_UNCHANGED:
++ if (atomic_cmpxchg(&device->state,
++ FW_DEVICE_INITIALIZING,
++ FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
++ goto gone;
++
++ fw_device_update(work);
++ device->config_rom_retries = 0;
++ goto out;
++
++ case REREAD_BIB_CHANGED:
++ break;
++ }
++
++ /*
++ * Something changed. We keep things simple and don't investigate
++ * further. We just destroy all previous units and create new ones.
++ */
++ device_for_each_child(&device->device, NULL, shutdown_unit);
++
++ if (read_bus_info_block(device, device->generation) < 0) {
++ if (device->config_rom_retries < MAX_RETRIES &&
++ atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
++ device->config_rom_retries++;
++ schedule_delayed_work(&device->work, RETRY_DELAY);
++
++ return;
++ }
++ goto give_up;
++ }
++
++ create_units(device);
++
++ if (atomic_cmpxchg(&device->state,
++ FW_DEVICE_INITIALIZING,
++ FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
++ goto gone;
++
++ fw_notify("refreshed device %s\n", device->device.bus_id);
++ device->config_rom_retries = 0;
++ goto out;
++
++ give_up:
++ fw_notify("giving up on refresh of device %s\n", device->device.bus_id);
++ gone:
++ atomic_set(&device->state, FW_DEVICE_SHUTDOWN);
++ fw_device_shutdown(work);
++ out:
++ if (node_id == card->root_node->node_id)
++ schedule_delayed_work(&card->work, 0);
++}
++
+ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
+ {
+ struct fw_device *device;
+@@ -780,7 +931,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
+ case FW_NODE_LINK_ON:
+ if (!node->link_on)
+ break;
+-
++ create:
+ device = kzalloc(sizeof(*device), GFP_ATOMIC);
+ if (device == NULL)
+ break;
+@@ -819,6 +970,23 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
+ schedule_delayed_work(&device->work, INITIAL_DELAY);
+ break;
+
++ case FW_NODE_INITIATED_RESET:
++ device = node->data;
++ if (device == NULL)
++ goto create;
++
++ device->node_id = node->node_id;
++ smp_wmb(); /* update node_id before generation */
++ device->generation = card->generation;
++ if (atomic_cmpxchg(&device->state,
++ FW_DEVICE_RUNNING,
++ FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) {
++ PREPARE_DELAYED_WORK(&device->work, fw_device_refresh);
++ schedule_delayed_work(&device->work,
++ node == card->local_node ? 0 : INITIAL_DELAY);
++ }
++ break;
++
+ case FW_NODE_UPDATED:
+ if (!node->link_on || node->data == NULL)
+ break;
+diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
+index 78ecd39..5f131f5 100644
+--- a/drivers/firewire/fw-device.h
++++ b/drivers/firewire/fw-device.h
+@@ -21,6 +21,7 @@
+
+ #include <linux/fs.h>
+ #include <linux/cdev.h>
++#include <linux/rwsem.h>
+ #include <asm/atomic.h>
+
+ enum fw_device_state {
+@@ -46,6 +47,11 @@ struct fw_attribute_group {
+ * fw_device.node_id is guaranteed to be current too.
+ *
+ * The same applies to fw_device.card->node_id vs. fw_device.generation.
++ *
++ * fw_device.config_rom and fw_device.config_rom_length may be accessed during
++ * the lifetime of any fw_unit belonging to the fw_device, before device_del()
++ * was called on the last fw_unit. Alternatively, they may be accessed while
++ * holding fw_device_rwsem.
+ */
+ struct fw_device {
+ atomic_t state;
+@@ -53,6 +59,7 @@ struct fw_device {
+ int node_id;
+ int generation;
+ unsigned max_speed;
++ bool cmc;
+ struct fw_card *card;
+ struct device device;
+ struct list_head link;
+@@ -64,28 +71,24 @@ struct fw_device {
+ struct fw_attribute_group attribute_group;
+ };
+
+-static inline struct fw_device *
+-fw_device(struct device *dev)
++static inline struct fw_device *fw_device(struct device *dev)
+ {
+ return container_of(dev, struct fw_device, device);
+ }
+
+-static inline int
+-fw_device_is_shutdown(struct fw_device *device)
++static inline int fw_device_is_shutdown(struct fw_device *device)
+ {
+ return atomic_read(&device->state) == FW_DEVICE_SHUTDOWN;
+ }
+
+-static inline struct fw_device *
+-fw_device_get(struct fw_device *device)
++static inline struct fw_device *fw_device_get(struct fw_device *device)
+ {
+ get_device(&device->device);
+
+ return device;
+ }
+
+-static inline void
+-fw_device_put(struct fw_device *device)
++static inline void fw_device_put(struct fw_device *device)
+ {
+ put_device(&device->device);
+ }
+@@ -96,20 +99,35 @@ int fw_device_enable_phys_dma(struct fw_device *device);
+ void fw_device_cdev_update(struct fw_device *device);
+ void fw_device_cdev_remove(struct fw_device *device);
+
++extern struct rw_semaphore fw_device_rwsem;
+ extern int fw_cdev_major;
+
++/*
++ * fw_unit.directory must not be accessed after device_del(&fw_unit.device).
++ */
+ struct fw_unit {
+ struct device device;
+ u32 *directory;
+ struct fw_attribute_group attribute_group;
+ };
+
+-static inline struct fw_unit *
+-fw_unit(struct device *dev)
++static inline struct fw_unit *fw_unit(struct device *dev)
+ {
+ return container_of(dev, struct fw_unit, device);
+ }
+
++static inline struct fw_unit *fw_unit_get(struct fw_unit *unit)
++{
++ get_device(&unit->device);
++
++ return unit;
++}
++
++static inline void fw_unit_put(struct fw_unit *unit)
++{
++ put_device(&unit->device);
++}
++
+ #define CSR_OFFSET 0x40
+ #define CSR_LEAF 0x80
+ #define CSR_DIRECTORY 0xc0
+diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c
+index 2b640e9..bcbe794 100644
+--- a/drivers/firewire/fw-iso.c
++++ b/drivers/firewire/fw-iso.c
+@@ -126,7 +126,6 @@ fw_iso_context_create(struct fw_card *card, int type,
+
+ return ctx;
+ }
+-EXPORT_SYMBOL(fw_iso_context_create);
+
+ void fw_iso_context_destroy(struct fw_iso_context *ctx)
+ {
+@@ -134,14 +133,12 @@ void fw_iso_context_destroy(struct fw_iso_context *ctx)
+
+ card->driver->free_iso_context(ctx);
+ }
+-EXPORT_SYMBOL(fw_iso_context_destroy);
+
+ int
+ fw_iso_context_start(struct fw_iso_context *ctx, int cycle, int sync, int tags)
+ {
+ return ctx->card->driver->start_iso(ctx, cycle, sync, tags);
+ }
+-EXPORT_SYMBOL(fw_iso_context_start);
+
+ int
+ fw_iso_context_queue(struct fw_iso_context *ctx,
+@@ -153,11 +150,9 @@ fw_iso_context_queue(struct fw_iso_context *ctx,
+
+ return card->driver->queue_iso(ctx, packet, buffer, payload);
+ }
+-EXPORT_SYMBOL(fw_iso_context_queue);
+
+ int
+ fw_iso_context_stop(struct fw_iso_context *ctx)
+ {
+ return ctx->card->driver->stop_iso(ctx);
+ }
+-EXPORT_SYMBOL(fw_iso_context_stop);
+diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
+index ca6d51e..4f02c55 100644
+--- a/drivers/firewire/fw-ohci.c
++++ b/drivers/firewire/fw-ohci.c
+@@ -27,6 +27,7 @@
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
+ #include <linux/module.h>
++#include <linux/moduleparam.h>
+ #include <linux/pci.h>
+ #include <linux/spinlock.h>
+
+@@ -177,9 +178,10 @@ struct fw_ohci {
+ struct tasklet_struct bus_reset_tasklet;
+ int node_id;
+ int generation;
+- int request_generation;
++ int request_generation; /* for timestamping incoming requests */
+ u32 bus_seconds;
+ bool old_uninorth;
++ bool bus_reset_packet_quirk;
+
+ /*
+ * Spinlock for accessing fw_ohci data. Never call out of
+@@ -237,6 +239,196 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
+
+ static char ohci_driver_name[] = KBUILD_MODNAME;
+
++#ifdef CONFIG_FIREWIRE_OHCI_DEBUG
++
++#define OHCI_PARAM_DEBUG_AT_AR 1
++#define OHCI_PARAM_DEBUG_SELFIDS 2
++#define OHCI_PARAM_DEBUG_IRQS 4
++#define OHCI_PARAM_DEBUG_BUSRESETS 8 /* only effective before chip init */
++
++static int param_debug;
++module_param_named(debug, param_debug, int, 0644);
++MODULE_PARM_DESC(debug, "Verbose logging (default = 0"
++ ", AT/AR events = " __stringify(OHCI_PARAM_DEBUG_AT_AR)
++ ", self-IDs = " __stringify(OHCI_PARAM_DEBUG_SELFIDS)
++ ", IRQs = " __stringify(OHCI_PARAM_DEBUG_IRQS)
++ ", busReset events = " __stringify(OHCI_PARAM_DEBUG_BUSRESETS)
++ ", or a combination, or all = -1)");
++
++static void log_irqs(u32 evt)
++{
++ if (likely(!(param_debug &
++ (OHCI_PARAM_DEBUG_IRQS | OHCI_PARAM_DEBUG_BUSRESETS))))
++ return;
++
++ if (!(param_debug & OHCI_PARAM_DEBUG_IRQS) &&
++ !(evt & OHCI1394_busReset))
++ return;
++
++ printk(KERN_DEBUG KBUILD_MODNAME ": IRQ "
++ "%08x%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
++ evt,
++ evt & OHCI1394_selfIDComplete ? " selfID" : "",
++ evt & OHCI1394_RQPkt ? " AR_req" : "",
++ evt & OHCI1394_RSPkt ? " AR_resp" : "",
++ evt & OHCI1394_reqTxComplete ? " AT_req" : "",
++ evt & OHCI1394_respTxComplete ? " AT_resp" : "",
++ evt & OHCI1394_isochRx ? " IR" : "",
++ evt & OHCI1394_isochTx ? " IT" : "",
++ evt & OHCI1394_postedWriteErr ? " postedWriteErr" : "",
++ evt & OHCI1394_cycleTooLong ? " cycleTooLong" : "",
++ evt & OHCI1394_cycle64Seconds ? " cycle64Seconds" : "",
++ evt & OHCI1394_regAccessFail ? " regAccessFail" : "",
++ evt & OHCI1394_busReset ? " busReset" : "",
++ evt & ~(OHCI1394_selfIDComplete | OHCI1394_RQPkt |
++ OHCI1394_RSPkt | OHCI1394_reqTxComplete |
++ OHCI1394_respTxComplete | OHCI1394_isochRx |
++ OHCI1394_isochTx | OHCI1394_postedWriteErr |
++ OHCI1394_cycleTooLong | OHCI1394_cycle64Seconds |
++ OHCI1394_regAccessFail | OHCI1394_busReset)
++ ? " ?" : "");
++}
++
++static const char *speed[] = {
++ [0] = "S100", [1] = "S200", [2] = "S400", [3] = "beta",
++};
++static const char *power[] = {
++ [0] = "+0W", [1] = "+15W", [2] = "+30W", [3] = "+45W",
++ [4] = "-3W", [5] = " ?W", [6] = "-3..-6W", [7] = "-3..-10W",
++};
++static const char port[] = { '.', '-', 'p', 'c', };
++
++static char _p(u32 *s, int shift)
++{
++ return port[*s >> shift & 3];
++}
++
++static void log_selfids(int node_id, int generation, int self_id_count, u32 *s)
++{
++ if (likely(!(param_debug & OHCI_PARAM_DEBUG_SELFIDS)))
++ return;
++
++ printk(KERN_DEBUG KBUILD_MODNAME ": %d selfIDs, generation %d, "
++ "local node ID %04x\n", self_id_count, generation, node_id);
++
++ for (; self_id_count--; ++s)
++ if ((*s & 1 << 23) == 0)
++ printk(KERN_DEBUG "selfID 0: %08x, phy %d [%c%c%c] "
++ "%s gc=%d %s %s%s%s\n",
++ *s, *s >> 24 & 63, _p(s, 6), _p(s, 4), _p(s, 2),
++ speed[*s >> 14 & 3], *s >> 16 & 63,
++ power[*s >> 8 & 7], *s >> 22 & 1 ? "L" : "",
++ *s >> 11 & 1 ? "c" : "", *s & 2 ? "i" : "");
++ else
++ printk(KERN_DEBUG "selfID n: %08x, phy %d "
++ "[%c%c%c%c%c%c%c%c]\n",
++ *s, *s >> 24 & 63,
++ _p(s, 16), _p(s, 14), _p(s, 12), _p(s, 10),
++ _p(s, 8), _p(s, 6), _p(s, 4), _p(s, 2));
++}
++
++static const char *evts[] = {
++ [0x00] = "evt_no_status", [0x01] = "-reserved-",
++ [0x02] = "evt_long_packet", [0x03] = "evt_missing_ack",
++ [0x04] = "evt_underrun", [0x05] = "evt_overrun",
++ [0x06] = "evt_descriptor_read", [0x07] = "evt_data_read",
++ [0x08] = "evt_data_write", [0x09] = "evt_bus_reset",
++ [0x0a] = "evt_timeout", [0x0b] = "evt_tcode_err",
++ [0x0c] = "-reserved-", [0x0d] = "-reserved-",
++ [0x0e] = "evt_unknown", [0x0f] = "evt_flushed",
++ [0x10] = "-reserved-", [0x11] = "ack_complete",
++ [0x12] = "ack_pending ", [0x13] = "-reserved-",
++ [0x14] = "ack_busy_X", [0x15] = "ack_busy_A",
++ [0x16] = "ack_busy_B", [0x17] = "-reserved-",
++ [0x18] = "-reserved-", [0x19] = "-reserved-",
++ [0x1a] = "-reserved-", [0x1b] = "ack_tardy",
++ [0x1c] = "-reserved-", [0x1d] = "ack_data_error",
++ [0x1e] = "ack_type_error", [0x1f] = "-reserved-",
++ [0x20] = "pending/cancelled",
++};
++static const char *tcodes[] = {
++ [0x0] = "QW req", [0x1] = "BW req",
++ [0x2] = "W resp", [0x3] = "-reserved-",
++ [0x4] = "QR req", [0x5] = "BR req",
++ [0x6] = "QR resp", [0x7] = "BR resp",
++ [0x8] = "cycle start", [0x9] = "Lk req",
++ [0xa] = "async stream packet", [0xb] = "Lk resp",
++ [0xc] = "-reserved-", [0xd] = "-reserved-",
++ [0xe] = "link internal", [0xf] = "-reserved-",
++};
++static const char *phys[] = {
++ [0x0] = "phy config packet", [0x1] = "link-on packet",
++ [0x2] = "self-id packet", [0x3] = "-reserved-",
++};
++
++static void log_ar_at_event(char dir, int speed, u32 *header, int evt)
++{
++ int tcode = header[0] >> 4 & 0xf;
++ char specific[12];
++
++ if (likely(!(param_debug & OHCI_PARAM_DEBUG_AT_AR)))
++ return;
++
++ if (unlikely(evt >= ARRAY_SIZE(evts)))
++ evt = 0x1f;
++
++ if (evt == OHCI1394_evt_bus_reset) {
++ printk(KERN_DEBUG "A%c evt_bus_reset, generation %d\n",
++ dir, (header[2] >> 16) & 0xff);
++ return;
++ }
++
++ if (header[0] == ~header[1]) {
++ printk(KERN_DEBUG "A%c %s, %s, %08x\n",
++ dir, evts[evt], phys[header[0] >> 30 & 0x3],
++ header[0]);
++ return;
++ }
++
++ switch (tcode) {
++ case 0x0: case 0x6: case 0x8:
++ snprintf(specific, sizeof(specific), " = %08x",
++ be32_to_cpu((__force __be32)header[3]));
++ break;
++ case 0x1: case 0x5: case 0x7: case 0x9: case 0xb:
++ snprintf(specific, sizeof(specific), " %x,%x",
++ header[3] >> 16, header[3] & 0xffff);
++ break;
++ default:
++ specific[0] = '\0';
++ }
++
++ switch (tcode) {
++ case 0xe: case 0xa:
++ printk(KERN_DEBUG "A%c %s, %s\n",
++ dir, evts[evt], tcodes[tcode]);
++ break;
++ case 0x0: case 0x1: case 0x4: case 0x5: case 0x9:
++ printk(KERN_DEBUG "A%c spd %x tl %02x, "
++ "%04x -> %04x, %s, "
++ "%s, %04x%08x%s\n",
++ dir, speed, header[0] >> 10 & 0x3f,
++ header[1] >> 16, header[0] >> 16, evts[evt],
++ tcodes[tcode], header[1] & 0xffff, header[2], specific);
++ break;
++ default:
++ printk(KERN_DEBUG "A%c spd %x tl %02x, "
++ "%04x -> %04x, %s, "
++ "%s%s\n",
++ dir, speed, header[0] >> 10 & 0x3f,
++ header[1] >> 16, header[0] >> 16, evts[evt],
++ tcodes[tcode], specific);
++ }
++}
++
++#else
++
++#define log_irqs(evt)
++#define log_selfids(node_id, generation, self_id_count, sid)
++#define log_ar_at_event(dir, speed, header, evt)
++
++#endif /* CONFIG_FIREWIRE_OHCI_DEBUG */
++
+ static inline void reg_write(const struct fw_ohci *ohci, int offset, u32 data)
+ {
+ writel(data, ohci->registers + offset);
+@@ -320,6 +512,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
+ struct fw_ohci *ohci = ctx->ohci;
+ struct fw_packet p;
+ u32 status, length, tcode;
++ int evt;
+
+ p.header[0] = cond_le32_to_cpu(buffer[0]);
+ p.header[1] = cond_le32_to_cpu(buffer[1]);
+@@ -362,12 +555,15 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
+ /* FIXME: What to do about evt_* errors? */
+ length = (p.header_length + p.payload_length + 3) / 4;
+ status = cond_le32_to_cpu(buffer[length]);
++ evt = (status >> 16) & 0x1f;
+
+- p.ack = ((status >> 16) & 0x1f) - 16;
++ p.ack = evt - 16;
+ p.speed = (status >> 21) & 0x7;
+ p.timestamp = status & 0xffff;
+ p.generation = ohci->request_generation;
+
++ log_ar_at_event('R', p.speed, p.header, evt);
++
+ /*
+ * The OHCI bus reset handler synthesizes a phy packet with
+ * the new generation number when a bus reset happens (see
+@@ -376,14 +572,19 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
+ * generation. We only need this for requests; for responses
+ * we use the unique tlabel for finding the matching
+ * request.
++ *
++ * Alas some chips sometimes emit bus reset packets with a
++ * wrong generation. We set the correct generation for these
++ * at a slightly incorrect time (in bus_reset_tasklet).
+ */
+-
+- if (p.ack + 16 == 0x09)
+- ohci->request_generation = (p.header[2] >> 16) & 0xff;
+- else if (ctx == &ohci->ar_request_ctx)
++ if (evt == OHCI1394_evt_bus_reset) {
++ if (!ohci->bus_reset_packet_quirk)
++ ohci->request_generation = (p.header[2] >> 16) & 0xff;
++ } else if (ctx == &ohci->ar_request_ctx) {
+ fw_core_handle_request(&ohci->card, &p);
+- else
++ } else {
+ fw_core_handle_response(&ohci->card, &p);
++ }
+
+ return buffer + length + 1;
+ }
+@@ -770,8 +971,19 @@ at_context_queue_packet(struct context *ctx, struct fw_packet *packet)
+ DESCRIPTOR_IRQ_ALWAYS |
+ DESCRIPTOR_BRANCH_ALWAYS);
+
+- /* FIXME: Document how the locking works. */
+- if (ohci->generation != packet->generation) {
++ /*
++ * If the controller and packet generations don't match, we need to
++ * bail out and try again. If IntEvent.busReset is set, the AT context
++ * is halted, so appending to the context and trying to run it is
++ * futile. Most controllers do the right thing and just flush the AT
++ * queue (per section 7.2.3.2 of the OHCI 1.1 specification), but
++ * some controllers (like a JMicron JMB381 PCI-e) misbehave and wind
++ * up stalling out. So we just bail out in software and try again
++ * later, and everyone is happy.
++ * FIXME: Document how the locking works.
++ */
++ if (ohci->generation != packet->generation ||
++ reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) {
+ if (packet->payload_length > 0)
+ dma_unmap_single(ohci->card.device, payload_bus,
+ packet->payload_length, DMA_TO_DEVICE);
+@@ -817,6 +1029,8 @@ static int handle_at_packet(struct context *context,
+ evt = le16_to_cpu(last->transfer_status) & 0x1f;
+ packet->timestamp = le16_to_cpu(last->res_count);
+
++ log_ar_at_event('T', packet->speed, packet->header, evt);
++
+ switch (evt) {
+ case OHCI1394_evt_timeout:
+ /* Async response transmit timed out. */
+@@ -1019,20 +1233,30 @@ static void bus_reset_tasklet(unsigned long data)
+ ohci->node_id = reg & (OHCI1394_NodeID_busNumber |
+ OHCI1394_NodeID_nodeNumber);
+
++ reg = reg_read(ohci, OHCI1394_SelfIDCount);
++ if (reg & OHCI1394_SelfIDCount_selfIDError) {
++ fw_notify("inconsistent self IDs\n");
++ return;
++ }
+ /*
+ * The count in the SelfIDCount register is the number of
+ * bytes in the self ID receive buffer. Since we also receive
+ * the inverted quadlets and a header quadlet, we shift one
+ * bit extra to get the actual number of self IDs.
+ */
+-
+- self_id_count = (reg_read(ohci, OHCI1394_SelfIDCount) >> 3) & 0x3ff;
++ self_id_count = (reg >> 3) & 0x3ff;
++ if (self_id_count == 0) {
++ fw_notify("inconsistent self IDs\n");
++ return;
++ }
+ generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff;
+ rmb();
+
+ for (i = 1, j = 0; j < self_id_count; i += 2, j++) {
+- if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1])
+- fw_error("inconsistent self IDs\n");
++ if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1]) {
++ fw_notify("inconsistent self IDs\n");
++ return;
++ }
+ ohci->self_id_buffer[j] =
+ cond_le32_to_cpu(ohci->self_id_cpu[i]);
+ }
+@@ -1067,6 +1291,9 @@ static void bus_reset_tasklet(unsigned long data)
+ context_stop(&ohci->at_response_ctx);
+ reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
+
++ if (ohci->bus_reset_packet_quirk)
++ ohci->request_generation = generation;
++
+ /*
+ * This next bit is unrelated to the AT context stuff but we
+ * have to do it under the spinlock also. If a new config rom
+@@ -1097,12 +1324,20 @@ static void bus_reset_tasklet(unsigned long data)
+ reg_write(ohci, OHCI1394_ConfigROMhdr, ohci->next_header);
+ }
+
++#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA
++ reg_write(ohci, OHCI1394_PhyReqFilterHiSet, ~0);
++ reg_write(ohci, OHCI1394_PhyReqFilterLoSet, ~0);
++#endif
++
+ spin_unlock_irqrestore(&ohci->lock, flags);
+
+ if (free_rom)
+ dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+ free_rom, free_rom_bus);
+
++ log_selfids(ohci->node_id, generation,
++ self_id_count, ohci->self_id_buffer);
++
+ fw_core_handle_bus_reset(&ohci->card, ohci->node_id, generation,
+ self_id_count, ohci->self_id_buffer);
+ }
+@@ -1118,7 +1353,9 @@ static irqreturn_t irq_handler(int irq, void *data)
+ if (!event || !~event)
+ return IRQ_NONE;
+
+- reg_write(ohci, OHCI1394_IntEventClear, event);
++ /* busReset must not be cleared yet, see OHCI 1.1 clause 7.2.3.2 */
++ reg_write(ohci, OHCI1394_IntEventClear, event & ~OHCI1394_busReset);
++ log_irqs(event);
+
+ if (event & OHCI1394_selfIDComplete)
+ tasklet_schedule(&ohci->bus_reset_tasklet);
+@@ -1153,6 +1390,10 @@ static irqreturn_t irq_handler(int irq, void *data)
+ iso_event &= ~(1 << i);
+ }
+
++ if (unlikely(event & OHCI1394_regAccessFail))
++ fw_error("Register access failure - "
++ "please notify linux1394-devel at lists.sf.net\n");
++
+ if (unlikely(event & OHCI1394_postedWriteErr))
+ fw_error("PCI posted write error\n");
+
+@@ -1192,6 +1433,8 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
+ {
+ struct fw_ohci *ohci = fw_ohci(card);
+ struct pci_dev *dev = to_pci_dev(card->device);
++ u32 lps;
++ int i;
+
+ if (software_reset(ohci)) {
+ fw_error("Failed to reset ohci card.\n");
+@@ -1203,13 +1446,24 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
+ * most of the registers. In fact, on some cards (ALI M5251),
+ * accessing registers in the SClk domain without LPS enabled
+ * will lock up the machine. Wait 50msec to make sure we have
+- * full link enabled.
++ * full link enabled. However, with some cards (well, at least
++ * a JMicron PCIe card), we have to try again sometimes.
+ */
+ reg_write(ohci, OHCI1394_HCControlSet,
+ OHCI1394_HCControl_LPS |
+ OHCI1394_HCControl_postedWriteEnable);
+ flush_writes(ohci);
+- msleep(50);
++
++ for (lps = 0, i = 0; !lps && i < 3; i++) {
++ msleep(50);
++ lps = reg_read(ohci, OHCI1394_HCControlSet) &
++ OHCI1394_HCControl_LPS;
++ }
++
++ if (!lps) {
++ fw_error("Failed to set Link Power Status\n");
++ return -EIO;
++ }
+
+ reg_write(ohci, OHCI1394_HCControlClear,
+ OHCI1394_HCControl_noByteSwapData);
+@@ -1237,7 +1491,10 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
+ OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
+ OHCI1394_isochRx | OHCI1394_isochTx |
+ OHCI1394_postedWriteErr | OHCI1394_cycleTooLong |
+- OHCI1394_cycle64Seconds | OHCI1394_masterIntEnable);
++ OHCI1394_cycle64Seconds | OHCI1394_regAccessFail |
++ OHCI1394_masterIntEnable);
++ if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
++ reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
+
+ /* Activate link_on bit and contender bit in our self ID packets.*/
+ if (ohci_update_phy_reg(card, 4, 0,
+@@ -1421,6 +1678,7 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
+ if (packet->ack != 0)
+ goto out;
+
++ log_ar_at_event('T', packet->speed, packet->header, 0x20);
+ driver_data->packet = NULL;
+ packet->ack = RCODE_CANCELLED;
+ packet->callback(packet, &ohci->card, packet->ack);
+@@ -1435,6 +1693,9 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
+ static int
+ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation)
+ {
++#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA
++ return 0;
++#else
+ struct fw_ohci *ohci = fw_ohci(card);
+ unsigned long flags;
+ int n, retval = 0;
+@@ -1466,6 +1727,7 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation)
+ out:
+ spin_unlock_irqrestore(&ohci->lock, flags);
+ return retval;
++#endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */
+ }
+
+ static u64
+@@ -2045,17 +2307,9 @@ static const struct fw_card_driver ohci_driver = {
+ .stop_iso = ohci_stop_iso,
+ };
+
+-static int __devinit
+-pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+-{
+- struct fw_ohci *ohci;
+- u32 bus_options, max_receive, link_speed;
+- u64 guid;
+- int err;
+- size_t size;
+-
+ #ifdef CONFIG_PPC_PMAC
+- /* Necessary on some machines if fw-ohci was loaded/ unloaded before */
++static void ohci_pmac_on(struct pci_dev *dev)
++{
+ if (machine_is(powermac)) {
+ struct device_node *ofn = pci_device_to_OF_node(dev);
+
+@@ -2064,8 +2318,33 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+ pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
+ }
+ }
++}
++
++static void ohci_pmac_off(struct pci_dev *dev)
++{
++ if (machine_is(powermac)) {
++ struct device_node *ofn = pci_device_to_OF_node(dev);
++
++ if (ofn) {
++ pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
++ pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
++ }
++ }
++}
++#else
++#define ohci_pmac_on(dev)
++#define ohci_pmac_off(dev)
+ #endif /* CONFIG_PPC_PMAC */
+
++static int __devinit
++pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
++{
++ struct fw_ohci *ohci;
++ u32 bus_options, max_receive, link_speed;
++ u64 guid;
++ int err;
++ size_t size;
++
+ ohci = kzalloc(sizeof(*ohci), GFP_KERNEL);
+ if (ohci == NULL) {
+ fw_error("Could not malloc fw_ohci data.\n");
+@@ -2074,10 +2353,12 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+
+ fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev);
+
++ ohci_pmac_on(dev);
++
+ err = pci_enable_device(dev);
+ if (err) {
+ fw_error("Failed to enable OHCI hardware.\n");
+- goto fail_put_card;
++ goto fail_free;
+ }
+
+ pci_set_master(dev);
+@@ -2088,6 +2369,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+ ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
+ dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
+ #endif
++ ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
++
+ spin_lock_init(&ohci->lock);
+
+ tasklet_init(&ohci->bus_reset_tasklet,
+@@ -2173,8 +2456,9 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+ pci_release_region(dev, 0);
+ fail_disable:
+ pci_disable_device(dev);
+- fail_put_card:
+- fw_card_put(&ohci->card);
++ fail_free:
++ kfree(&ohci->card);
++ ohci_pmac_off(dev);
+
+ return err;
+ }
+@@ -2202,72 +2486,42 @@ static void pci_remove(struct pci_dev *dev)
+ pci_iounmap(dev, ohci->registers);
+ pci_release_region(dev, 0);
+ pci_disable_device(dev);
+- fw_card_put(&ohci->card);
+-
+-#ifdef CONFIG_PPC_PMAC
+- /* On UniNorth, power down the cable and turn off the chip clock
+- * to save power on laptops */
+- if (machine_is(powermac)) {
+- struct device_node *ofn = pci_device_to_OF_node(dev);
+-
+- if (ofn) {
+- pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
+- pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
+- }
+- }
+-#endif /* CONFIG_PPC_PMAC */
++ kfree(&ohci->card);
++ ohci_pmac_off(dev);
+
+ fw_notify("Removed fw-ohci device.\n");
+ }
+
+ #ifdef CONFIG_PM
+-static int pci_suspend(struct pci_dev *pdev, pm_message_t state)
++static int pci_suspend(struct pci_dev *dev, pm_message_t state)
+ {
+- struct fw_ohci *ohci = pci_get_drvdata(pdev);
++ struct fw_ohci *ohci = pci_get_drvdata(dev);
+ int err;
+
+ software_reset(ohci);
+- free_irq(pdev->irq, ohci);
+- err = pci_save_state(pdev);
++ free_irq(dev->irq, ohci);
++ err = pci_save_state(dev);
+ if (err) {
+ fw_error("pci_save_state failed\n");
+ return err;
+ }
+- err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
++ err = pci_set_power_state(dev, pci_choose_state(dev, state));
+ if (err)
+ fw_error("pci_set_power_state failed with %d\n", err);
+-
+-/* PowerMac suspend code comes last */
+-#ifdef CONFIG_PPC_PMAC
+- if (machine_is(powermac)) {
+- struct device_node *ofn = pci_device_to_OF_node(pdev);
+-
+- if (ofn)
+- pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
+- }
+-#endif /* CONFIG_PPC_PMAC */
++ ohci_pmac_off(dev);
+
+ return 0;
+ }
+
+-static int pci_resume(struct pci_dev *pdev)
++static int pci_resume(struct pci_dev *dev)
+ {
+- struct fw_ohci *ohci = pci_get_drvdata(pdev);
++ struct fw_ohci *ohci = pci_get_drvdata(dev);
+ int err;
+
+-/* PowerMac resume code comes first */
+-#ifdef CONFIG_PPC_PMAC
+- if (machine_is(powermac)) {
+- struct device_node *ofn = pci_device_to_OF_node(pdev);
+-
+- if (ofn)
+- pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
+- }
+-#endif /* CONFIG_PPC_PMAC */
+-
+- pci_set_power_state(pdev, PCI_D0);
+- pci_restore_state(pdev);
+- err = pci_enable_device(pdev);
++ ohci_pmac_on(dev);
++ pci_set_power_state(dev, PCI_D0);
++ pci_restore_state(dev);
++ err = pci_enable_device(dev);
+ if (err) {
+ fw_error("pci_enable_device failed\n");
+ return err;
+diff --git a/drivers/firewire/fw-ohci.h b/drivers/firewire/fw-ohci.h
+index dec4f04..a2fbb62 100644
+--- a/drivers/firewire/fw-ohci.h
++++ b/drivers/firewire/fw-ohci.h
+@@ -30,6 +30,7 @@
+ #define OHCI1394_HCControl_softReset 0x00010000
+ #define OHCI1394_SelfIDBuffer 0x064
+ #define OHCI1394_SelfIDCount 0x068
++#define OHCI1394_SelfIDCount_selfIDError 0x80000000
+ #define OHCI1394_IRMultiChanMaskHiSet 0x070
+ #define OHCI1394_IRMultiChanMaskHiClear 0x074
+ #define OHCI1394_IRMultiChanMaskLoSet 0x078
+@@ -124,6 +125,7 @@
+ #define OHCI1394_lockRespErr 0x00000200
+ #define OHCI1394_selfIDComplete 0x00010000
+ #define OHCI1394_busReset 0x00020000
++#define OHCI1394_regAccessFail 0x00040000
+ #define OHCI1394_phy 0x00080000
+ #define OHCI1394_cycleSynch 0x00100000
+ #define OHCI1394_cycle64Seconds 0x00200000
+diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
+index 62b4e47..2a99937 100644
+--- a/drivers/firewire/fw-sbp2.c
++++ b/drivers/firewire/fw-sbp2.c
+@@ -153,6 +153,7 @@ struct sbp2_target {
+ struct list_head lu_list;
+
+ u64 management_agent_address;
++ u64 guid;
+ int directory_id;
+ int node_id;
+ int address_high;
+@@ -173,10 +174,8 @@ struct sbp2_target {
+ #define SBP2_ORB_TIMEOUT 2000U /* Timeout in ms */
+ #define SBP2_ORB_NULL 0x80000000
+ #define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
+-#define SBP2_RETRY_LIMIT 0xf /* 15 retries */
+-
+-#define SBP2_DIRECTION_TO_MEDIA 0x0
+-#define SBP2_DIRECTION_FROM_MEDIA 0x1
++#define SBP2_RETRY_LIMIT 0xf /* 15 retries */
++#define SBP2_CYCLE_LIMIT (0xc8 << 12) /* 200 125us cycles */
+
+ /* Unit directory keys */
+ #define SBP2_CSR_UNIT_CHARACTERISTICS 0x3a
+@@ -224,8 +223,8 @@ struct sbp2_status {
+ };
+
+ struct sbp2_pointer {
+- u32 high;
+- u32 low;
++ __be32 high;
++ __be32 low;
+ };
+
+ struct sbp2_orb {
+@@ -253,8 +252,8 @@ struct sbp2_management_orb {
+ struct {
+ struct sbp2_pointer password;
+ struct sbp2_pointer response;
+- u32 misc;
+- u32 length;
++ __be32 misc;
++ __be32 length;
+ struct sbp2_pointer status_fifo;
+ } request;
+ __be32 response[4];
+@@ -263,20 +262,17 @@ struct sbp2_management_orb {
+ struct sbp2_status status;
+ };
+
+-#define LOGIN_RESPONSE_GET_LOGIN_ID(v) ((v).misc & 0xffff)
+-#define LOGIN_RESPONSE_GET_LENGTH(v) (((v).misc >> 16) & 0xffff)
+-
+ struct sbp2_login_response {
+- u32 misc;
++ __be32 misc;
+ struct sbp2_pointer command_block_agent;
+- u32 reconnect_hold;
++ __be32 reconnect_hold;
+ };
+ #define COMMAND_ORB_DATA_SIZE(v) ((v))
+ #define COMMAND_ORB_PAGE_SIZE(v) ((v) << 16)
+ #define COMMAND_ORB_PAGE_TABLE_PRESENT ((1) << 19)
+ #define COMMAND_ORB_MAX_PAYLOAD(v) ((v) << 20)
+ #define COMMAND_ORB_SPEED(v) ((v) << 24)
+-#define COMMAND_ORB_DIRECTION(v) ((v) << 27)
++#define COMMAND_ORB_DIRECTION ((1) << 27)
+ #define COMMAND_ORB_REQUEST_FORMAT(v) ((v) << 29)
+ #define COMMAND_ORB_NOTIFY ((1) << 31)
+
+@@ -285,7 +281,7 @@ struct sbp2_command_orb {
+ struct {
+ struct sbp2_pointer next;
+ struct sbp2_pointer data_descriptor;
+- u32 misc;
++ __be32 misc;
+ u8 command_block[12];
+ } request;
+ struct scsi_cmnd *cmd;
+@@ -459,8 +455,7 @@ sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
+ unsigned long flags;
+
+ orb->pointer.high = 0;
+- orb->pointer.low = orb->request_bus;
+- fw_memcpy_to_be32(&orb->pointer, &orb->pointer, sizeof(orb->pointer));
++ orb->pointer.low = cpu_to_be32(orb->request_bus);
+
+ spin_lock_irqsave(&device->card->lock, flags);
+ list_add_tail(&orb->link, &lu->orb_list);
+@@ -536,31 +531,31 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
+ if (dma_mapping_error(orb->response_bus))
+ goto fail_mapping_response;
+
+- orb->request.response.high = 0;
+- orb->request.response.low = orb->response_bus;
++ orb->request.response.high = 0;
++ orb->request.response.low = cpu_to_be32(orb->response_bus);
+
+- orb->request.misc =
++ orb->request.misc = cpu_to_be32(
+ MANAGEMENT_ORB_NOTIFY |
+ MANAGEMENT_ORB_FUNCTION(function) |
+- MANAGEMENT_ORB_LUN(lun_or_login_id);
+- orb->request.length =
+- MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response));
++ MANAGEMENT_ORB_LUN(lun_or_login_id));
++ orb->request.length = cpu_to_be32(
++ MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response)));
+
+- orb->request.status_fifo.high = lu->address_handler.offset >> 32;
+- orb->request.status_fifo.low = lu->address_handler.offset;
++ orb->request.status_fifo.high =
++ cpu_to_be32(lu->address_handler.offset >> 32);
++ orb->request.status_fifo.low =
++ cpu_to_be32(lu->address_handler.offset);
+
+ if (function == SBP2_LOGIN_REQUEST) {
+ /* Ask for 2^2 == 4 seconds reconnect grace period */
+- orb->request.misc |=
++ orb->request.misc |= cpu_to_be32(
+ MANAGEMENT_ORB_RECONNECT(2) |
+- MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login);
++ MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login));
+ timeout = lu->tgt->mgt_orb_timeout;
+ } else {
+ timeout = SBP2_ORB_TIMEOUT;
+ }
+
+- fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
+-
+ init_completion(&orb->done);
+ orb->base.callback = complete_management_orb;
+
+@@ -605,8 +600,7 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
+ sizeof(orb->response), DMA_FROM_DEVICE);
+ fail_mapping_response:
+ if (response)
+- fw_memcpy_from_be32(response,
+- orb->response, sizeof(orb->response));
++ memcpy(response, orb->response, sizeof(orb->response));
+ kref_put(&orb->base.kref, free_orb);
+
+ return retval;
+@@ -701,10 +695,8 @@ static void sbp2_conditionally_block(struct sbp2_logical_unit *lu)
+ if (!tgt->dont_block && !lu->blocked &&
+ lu->generation != card->generation) {
+ lu->blocked = true;
+- if (++tgt->blocked == 1) {
++ if (++tgt->blocked == 1)
+ scsi_block_requests(shost);
+- fw_notify("blocked %s\n", lu->tgt->bus_id);
+- }
+ }
+ spin_unlock_irqrestore(&card->lock, flags);
+ }
+@@ -731,10 +723,8 @@ static void sbp2_conditionally_unblock(struct sbp2_logical_unit *lu)
+ }
+ spin_unlock_irqrestore(&card->lock, flags);
+
+- if (unblock) {
++ if (unblock)
+ scsi_unblock_requests(shost);
+- fw_notify("unblocked %s\n", lu->tgt->bus_id);
+- }
+ }
+
+ /*
+@@ -796,7 +786,7 @@ static void sbp2_release_target(struct kref *kref)
+ scsi_remove_host(shost);
+ fw_notify("released %s\n", tgt->bus_id);
+
+- put_device(&tgt->unit->device);
++ fw_unit_put(tgt->unit);
+ scsi_host_put(shost);
+ fw_device_put(device);
+ }
+@@ -825,6 +815,22 @@ complete_set_busy_timeout(struct fw_card *card, int rcode,
+ complete(done);
+ }
+
++/*
++ * Write retransmit retry values into the BUSY_TIMEOUT register.
++ * - The single-phase retry protocol is supported by all SBP-2 devices, but the
++ * default retry_limit value is 0 (i.e. never retry transmission). We write a
++ * saner value after logging into the device.
++ * - The dual-phase retry protocol is optional to implement, and if not
++ * supported, writes to the dual-phase portion of the register will be
++ * ignored. We try to write the original 1394-1995 default here.
++ * - In the case of devices that are also SBP-3-compliant, all writes are
++ * ignored, as the register is read-only, but contains single-phase retry of
++ * 15, which is what we're trying to set for all SBP-2 device anyway, so this
++ * write attempt is safe and yields more consistent behavior for all devices.
++ *
++ * See section 8.3.2.3.5 of the 1394-1995 spec, section 6.2 of the SBP-2 spec,
++ * and section 6.4 of the SBP-3 spec for further details.
++ */
+ static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu)
+ {
+ struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+@@ -832,8 +838,7 @@ static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu)
+ struct fw_transaction t;
+ static __be32 busy_timeout;
+
+- /* FIXME: we should try to set dual-phase cycle_limit too */
+- busy_timeout = cpu_to_be32(SBP2_RETRY_LIMIT);
++ busy_timeout = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT);
+
+ fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST,
+ lu->tgt->node_id, lu->generation, device->max_speed,
+@@ -885,11 +890,10 @@ static void sbp2_login(struct work_struct *work)
+ tgt->address_high = local_node_id << 16;
+ sbp2_set_generation(lu, generation);
+
+- /* Get command block agent offset and login id. */
+ lu->command_block_agent_address =
+- ((u64) (response.command_block_agent.high & 0xffff) << 32) |
+- response.command_block_agent.low;
+- lu->login_id = LOGIN_RESPONSE_GET_LOGIN_ID(response);
++ ((u64)(be32_to_cpu(response.command_block_agent.high) & 0xffff)
++ << 32) | be32_to_cpu(response.command_block_agent.low);
++ lu->login_id = be32_to_cpu(response.misc) & 0xffff;
+
+ fw_notify("%s: logged in to LUN %04x (%d retries)\n",
+ tgt->bus_id, lu->lun, lu->retries);
+@@ -1111,6 +1115,7 @@ static int sbp2_probe(struct device *dev)
+ kref_init(&tgt->kref);
+ INIT_LIST_HEAD(&tgt->lu_list);
+ tgt->bus_id = unit->device.bus_id;
++ tgt->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
+
+ if (fw_device_enable_phys_dma(device) < 0)
+ goto fail_shost_put;
+@@ -1119,6 +1124,7 @@ static int sbp2_probe(struct device *dev)
+ goto fail_shost_put;
+
+ fw_device_get(device);
++ fw_unit_get(unit);
+
+ /* Initialize to values that won't match anything in our table. */
+ firmware_revision = 0xff000000;
+@@ -1134,8 +1140,6 @@ static int sbp2_probe(struct device *dev)
+
+ sbp2_init_workarounds(tgt, model, firmware_revision);
+
+- get_device(&unit->device);
+-
+ /* Do the login in a workqueue so we can easily reschedule retries. */
+ list_for_each_entry(lu, &tgt->lu_list, link)
+ sbp2_queue_work(lu, 0);
+@@ -1367,9 +1371,12 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
+ * tables.
+ */
+ if (count == 1 && sg_dma_len(sg) < SBP2_MAX_SG_ELEMENT_LENGTH) {
+- orb->request.data_descriptor.high = lu->tgt->address_high;
+- orb->request.data_descriptor.low = sg_dma_address(sg);
+- orb->request.misc |= COMMAND_ORB_DATA_SIZE(sg_dma_len(sg));
++ orb->request.data_descriptor.high =
++ cpu_to_be32(lu->tgt->address_high);
++ orb->request.data_descriptor.low =
++ cpu_to_be32(sg_dma_address(sg));
++ orb->request.misc |=
++ cpu_to_be32(COMMAND_ORB_DATA_SIZE(sg_dma_len(sg)));
+ return 0;
+ }
+
+@@ -1390,16 +1397,14 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
+ goto fail_page_table;
+ }
+ l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH);
+- orb->page_table[j].low = sg_addr;
+- orb->page_table[j].high = (l << 16);
++ orb->page_table[j].low = cpu_to_be32(sg_addr);
++ orb->page_table[j].high = cpu_to_be32(l << 16);
+ sg_addr += l;
+ sg_len -= l;
+ j++;
+ }
+ }
+
+- fw_memcpy_to_be32(orb->page_table, orb->page_table,
+- sizeof(orb->page_table[0]) * j);
+ orb->page_table_bus =
+ dma_map_single(device->card->device, orb->page_table,
+ sizeof(orb->page_table), DMA_TO_DEVICE);
+@@ -1413,11 +1418,10 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
+ * initiator (i.e. us), but data_descriptor can refer to data
+ * on other nodes so we need to put our ID in descriptor.high.
+ */
+- orb->request.data_descriptor.high = lu->tgt->address_high;
+- orb->request.data_descriptor.low = orb->page_table_bus;
+- orb->request.misc |=
+- COMMAND_ORB_PAGE_TABLE_PRESENT |
+- COMMAND_ORB_DATA_SIZE(j);
++ orb->request.data_descriptor.high = cpu_to_be32(lu->tgt->address_high);
++ orb->request.data_descriptor.low = cpu_to_be32(orb->page_table_bus);
++ orb->request.misc |= cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT |
++ COMMAND_ORB_DATA_SIZE(j));
+
+ return 0;
+
+@@ -1463,8 +1467,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
+ orb->done = done;
+ orb->cmd = cmd;
+
+- orb->request.next.high = SBP2_ORB_NULL;
+- orb->request.next.low = 0x0;
++ orb->request.next.high = cpu_to_be32(SBP2_ORB_NULL);
+ /*
+ * At speed 100 we can do 512 bytes per packet, at speed 200,
+ * 1024 bytes per packet etc. The SBP-2 max_payload field
+@@ -1473,25 +1476,17 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
+ */
+ max_payload = min(device->max_speed + 7,
+ device->card->max_receive - 1);
+- orb->request.misc =
++ orb->request.misc = cpu_to_be32(
+ COMMAND_ORB_MAX_PAYLOAD(max_payload) |
+ COMMAND_ORB_SPEED(device->max_speed) |
+- COMMAND_ORB_NOTIFY;
++ COMMAND_ORB_NOTIFY);
+
+ if (cmd->sc_data_direction == DMA_FROM_DEVICE)
+- orb->request.misc |=
+- COMMAND_ORB_DIRECTION(SBP2_DIRECTION_FROM_MEDIA);
+- else if (cmd->sc_data_direction == DMA_TO_DEVICE)
+- orb->request.misc |=
+- COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA);
++ orb->request.misc |= cpu_to_be32(COMMAND_ORB_DIRECTION);
+
+ if (scsi_sg_count(cmd) && sbp2_map_scatterlist(orb, device, lu) < 0)
+ goto out;
+
+- fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
+-
+- memset(orb->request.command_block,
+- 0, sizeof(orb->request.command_block));
+ memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
+
+ orb->base.callback = complete_command_orb;
+@@ -1519,11 +1514,8 @@ static int sbp2_scsi_slave_alloc(struct scsi_device *sdev)
+
+ sdev->allow_restart = 1;
+
+- /*
+- * Update the dma alignment (minimum alignment requirements for
+- * start and end of DMA transfers) to be a sector
+- */
+- blk_queue_update_dma_alignment(sdev->request_queue, 511);
++ /* SBP-2 requires quadlet alignment of the data buffers. */
++ blk_queue_update_dma_alignment(sdev->request_queue, 4 - 1);
+
+ if (lu->tgt->workarounds & SBP2_WORKAROUND_INQUIRY_36)
+ sdev->inquiry_len = 36;
+@@ -1581,16 +1573,14 @@ sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr,
+ {
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct sbp2_logical_unit *lu;
+- struct fw_device *device;
+
+ if (!sdev)
+ return 0;
+
+ lu = sdev->hostdata;
+- device = fw_device(lu->tgt->unit->device.parent);
+
+- return sprintf(buf, "%08x%08x:%06x:%04x\n",
+- device->config_rom[3], device->config_rom[4],
++ return sprintf(buf, "%016llx:%06x:%04x\n",
++ (unsigned long long)lu->tgt->guid,
+ lu->tgt->directory_id, lu->lun);
+ }
+
+diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
+index d2c7a3d..213b0ff 100644
+--- a/drivers/firewire/fw-topology.c
++++ b/drivers/firewire/fw-topology.c
+@@ -108,6 +108,7 @@ static struct fw_node *fw_node_create(u32 sid, int port_count, int color)
+ node->node_id = LOCAL_BUS | SELF_ID_PHY_ID(sid);
+ node->link_on = SELF_ID_LINK_ON(sid);
+ node->phy_speed = SELF_ID_PHY_SPEED(sid);
++ node->initiated_reset = SELF_ID_PHY_INITIATOR(sid);
+ node->port_count = port_count;
+
+ atomic_set(&node->ref_count, 1);
+@@ -289,12 +290,11 @@ static struct fw_node *build_tree(struct fw_card *card,
+ beta_repeaters_present = true;
+
+ /*
+- * If all PHYs does not report the same gap count
+- * setting, we fall back to 63 which will force a gap
+- * count reconfiguration and a reset.
++ * If PHYs report different gap counts, set an invalid count
++ * which will force a gap count reconfiguration and a reset.
+ */
+ if (SELF_ID_GAP_COUNT(q) != gap_count)
+- gap_count = 63;
++ gap_count = 0;
+
+ update_hop_count(node);
+
+@@ -431,6 +431,8 @@ update_tree(struct fw_card *card, struct fw_node *root)
+ event = FW_NODE_LINK_OFF;
+ else if (!node0->link_on && node1->link_on)
+ event = FW_NODE_LINK_ON;
++ else if (node1->initiated_reset && node1->link_on)
++ event = FW_NODE_INITIATED_RESET;
+ else
+ event = FW_NODE_UPDATED;
+
+diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h
+index cedc1ec..addb9f8 100644
+--- a/drivers/firewire/fw-topology.h
++++ b/drivers/firewire/fw-topology.h
+@@ -20,11 +20,12 @@
+ #define __fw_topology_h
+
+ enum {
+- FW_NODE_CREATED = 0x00,
+- FW_NODE_UPDATED = 0x01,
+- FW_NODE_DESTROYED = 0x02,
+- FW_NODE_LINK_ON = 0x03,
+- FW_NODE_LINK_OFF = 0x04,
++ FW_NODE_CREATED,
++ FW_NODE_UPDATED,
++ FW_NODE_DESTROYED,
++ FW_NODE_LINK_ON,
++ FW_NODE_LINK_OFF,
++ FW_NODE_INITIATED_RESET,
+ };
+
+ struct fw_node {
+diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
+index e6f1bda..ccf0e4c 100644
+--- a/drivers/firewire/fw-transaction.c
++++ b/drivers/firewire/fw-transaction.c
+@@ -18,6 +18,7 @@
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
++#include <linux/completion.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -28,7 +29,6 @@
+ #include <linux/list.h>
+ #include <linux/kthread.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+
+ #include "fw-transaction.h"
+ #include "fw-topology.h"
+@@ -294,42 +294,40 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
+ }
+ EXPORT_SYMBOL(fw_send_request);
+
++struct fw_phy_packet {
++ struct fw_packet packet;
++ struct completion done;
++};
++
+ static void
+ transmit_phy_packet_callback(struct fw_packet *packet,
+ struct fw_card *card, int status)
+ {
+- kfree(packet);
+-}
+-
+-static void send_phy_packet(struct fw_card *card, u32 data, int generation)
+-{
+- struct fw_packet *packet;
+-
+- packet = kzalloc(sizeof(*packet), GFP_ATOMIC);
+- if (packet == NULL)
+- return;
+-
+- packet->header[0] = data;
+- packet->header[1] = ~data;
+- packet->header_length = 8;
+- packet->payload_length = 0;
+- packet->speed = SCODE_100;
+- packet->generation = generation;
+- packet->callback = transmit_phy_packet_callback;
++ struct fw_phy_packet *p =
++ container_of(packet, struct fw_phy_packet, packet);
+
+- card->driver->send_request(card, packet);
++ complete(&p->done);
+ }
+
+ void fw_send_phy_config(struct fw_card *card,
+ int node_id, int generation, int gap_count)
+ {
+- u32 q;
+-
+- q = PHY_IDENTIFIER(PHY_PACKET_CONFIG) |
+- PHY_CONFIG_ROOT_ID(node_id) |
+- PHY_CONFIG_GAP_COUNT(gap_count);
+-
+- send_phy_packet(card, q, generation);
++ struct fw_phy_packet p;
++ u32 data = PHY_IDENTIFIER(PHY_PACKET_CONFIG) |
++ PHY_CONFIG_ROOT_ID(node_id) |
++ PHY_CONFIG_GAP_COUNT(gap_count);
++
++ p.packet.header[0] = data;
++ p.packet.header[1] = ~data;
++ p.packet.header_length = 8;
++ p.packet.payload_length = 0;
++ p.packet.speed = SCODE_100;
++ p.packet.generation = generation;
++ p.packet.callback = transmit_phy_packet_callback;
++ init_completion(&p.done);
++
++ card->driver->send_request(card, &p.packet);
++ wait_for_completion(&p.done);
+ }
+
+ void fw_flush_transactions(struct fw_card *card)
+@@ -389,21 +387,21 @@ lookup_enclosing_address_handler(struct list_head *list,
+ static DEFINE_SPINLOCK(address_handler_lock);
+ static LIST_HEAD(address_handler_list);
+
+-const struct fw_address_region fw_low_memory_region =
+- { .start = 0x000000000000ULL, .end = 0x000100000000ULL, };
+ const struct fw_address_region fw_high_memory_region =
+ { .start = 0x000100000000ULL, .end = 0xffffe0000000ULL, };
++EXPORT_SYMBOL(fw_high_memory_region);
++
++#if 0
++const struct fw_address_region fw_low_memory_region =
++ { .start = 0x000000000000ULL, .end = 0x000100000000ULL, };
+ const struct fw_address_region fw_private_region =
+ { .start = 0xffffe0000000ULL, .end = 0xfffff0000000ULL, };
+ const struct fw_address_region fw_csr_region =
+- { .start = 0xfffff0000000ULL, .end = 0xfffff0000800ULL, };
++ { .start = CSR_REGISTER_BASE,
++ .end = CSR_REGISTER_BASE | CSR_CONFIG_ROM_END, };
+ const struct fw_address_region fw_unit_space_region =
+ { .start = 0xfffff0000900ULL, .end = 0x1000000000000ULL, };
+-EXPORT_SYMBOL(fw_low_memory_region);
+-EXPORT_SYMBOL(fw_high_memory_region);
+-EXPORT_SYMBOL(fw_private_region);
+-EXPORT_SYMBOL(fw_csr_region);
+-EXPORT_SYMBOL(fw_unit_space_region);
++#endif /* 0 */
+
+ /**
+ * Allocate a range of addresses in the node space of the OHCI
+@@ -747,7 +745,8 @@ fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
+ EXPORT_SYMBOL(fw_core_handle_response);
+
+ static const struct fw_address_region topology_map_region =
+- { .start = 0xfffff0001000ull, .end = 0xfffff0001400ull, };
++ { .start = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP,
++ .end = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP_END, };
+
+ static void
+ handle_topology_map(struct fw_card *card, struct fw_request *request,
+@@ -785,7 +784,8 @@ static struct fw_address_handler topology_map = {
+ };
+
+ static const struct fw_address_region registers_region =
+- { .start = 0xfffff0000000ull, .end = 0xfffff0000400ull, };
++ { .start = CSR_REGISTER_BASE,
++ .end = CSR_REGISTER_BASE | CSR_CONFIG_ROM, };
+
+ static void
+ handle_registers(struct fw_card *card, struct fw_request *request,
+@@ -794,7 +794,7 @@ handle_registers(struct fw_card *card, struct fw_request *request,
+ unsigned long long offset,
+ void *payload, size_t length, void *callback_data)
+ {
+- int reg = offset - CSR_REGISTER_BASE;
++ int reg = offset & ~CSR_REGISTER_BASE;
+ unsigned long long bus_time;
+ __be32 *data = payload;
+
+diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
+index a43bb22..04d3854 100644
+--- a/drivers/firewire/fw-transaction.h
++++ b/drivers/firewire/fw-transaction.h
+@@ -201,11 +201,7 @@ struct fw_address_region {
+ u64 end;
+ };
+
+-extern const struct fw_address_region fw_low_memory_region;
+ extern const struct fw_address_region fw_high_memory_region;
+-extern const struct fw_address_region fw_private_region;
+-extern const struct fw_address_region fw_csr_region;
+-extern const struct fw_address_region fw_unit_space_region;
+
+ int fw_core_add_address_handler(struct fw_address_handler *handler,
+ const struct fw_address_region *region);
+@@ -221,12 +217,9 @@ struct fw_card {
+ const struct fw_card_driver *driver;
+ struct device *device;
+ atomic_t device_count;
+- struct kref kref;
+
+ int node_id;
+ int generation;
+- /* This is the generation used for timestamping incoming requests. */
+- int request_generation;
+ int current_tlabel, tlabel_mask;
+ struct list_head transaction_list;
+ struct timer_list flush_timer;
+@@ -263,9 +256,6 @@ struct fw_card {
+ int bm_generation;
+ };
+
+-struct fw_card *fw_card_get(struct fw_card *card);
+-void fw_card_put(struct fw_card *card);
+-
+ /*
+ * The iso packet format allows for an immediate header/payload part
+ * stored in 'header' immediately after the packet info plus an
+diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
+index 05f02a3..dc2cec6 100644
+--- a/drivers/firmware/Kconfig
++++ b/drivers/firmware/Kconfig
+@@ -17,6 +17,15 @@ config EDD
+ obscure configurations. Most disk controller BIOS vendors do
+ not yet implement this feature.
+
++config EDD_OFF
++ bool "Sets default behavior for EDD detection to off"
++ depends on EDD
++ default n
++ help
++ Say Y if you want EDD disabled by default, even though it is compiled into the
++ kernel. Say N if you want EDD enabled by default. EDD can be dynamically set
++ using the kernel parameter 'edd={on|skipmbr|off}'.
++
+ config EFI_VARS
+ tristate "EFI Variable Support via sysfs"
+ depends on EFI
+@@ -93,4 +102,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..25918f7 100644
+--- a/drivers/firmware/dcdbas.c
++++ b/drivers/firmware/dcdbas.c
+@@ -35,7 +35,6 @@
+ #include <linux/types.h>
+ #include <linux/mutex.h>
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+
+ #include "dcdbas.h"
+
+@@ -64,7 +63,7 @@ static void smi_data_buf_free(void)
+ return;
+
+ dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
+- __FUNCTION__, smi_data_buf_phys_addr, smi_data_buf_size);
++ __func__, smi_data_buf_phys_addr, smi_data_buf_size);
+
+ dma_free_coherent(&dcdbas_pdev->dev, smi_data_buf_size, smi_data_buf,
+ smi_data_buf_handle);
+@@ -93,7 +92,7 @@ static int smi_data_buf_realloc(unsigned long size)
+ if (!buf) {
+ dev_dbg(&dcdbas_pdev->dev,
+ "%s: failed to allocate memory size %lu\n",
+- __FUNCTION__, size);
++ __func__, size);
+ return -ENOMEM;
+ }
+ /* memory zeroed by dma_alloc_coherent */
+@@ -111,7 +110,7 @@ static int smi_data_buf_realloc(unsigned long size)
+ smi_data_buf_size = size;
+
+ dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
+- __FUNCTION__, smi_data_buf_phys_addr, smi_data_buf_size);
++ __func__, smi_data_buf_phys_addr, smi_data_buf_size);
+
+ return 0;
+ }
+@@ -259,16 +258,16 @@ static int smi_request(struct smi_cmd *smi_cmd)
+
+ if (smi_cmd->magic != SMI_CMD_MAGIC) {
+ dev_info(&dcdbas_pdev->dev, "%s: invalid magic value\n",
+- __FUNCTION__);
++ __func__);
+ return -EBADR;
+ }
+
+ /* 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__);
++ __func__);
+ ret = -EBUSY;
+ goto out;
+ }
+@@ -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;
+ }
+
+@@ -429,7 +428,7 @@ static int host_control_smi(void)
+
+ default:
+ dev_dbg(&dcdbas_pdev->dev, "%s: invalid SMI type %u\n",
+- __FUNCTION__, host_control_smi_type);
++ __func__, host_control_smi_type);
+ return -ENOSYS;
+ }
+
+@@ -457,13 +456,13 @@ static void dcdbas_host_control(void)
+ host_control_action = HC_ACTION_NONE;
+
+ if (!smi_data_buf) {
+- dev_dbg(&dcdbas_pdev->dev, "%s: no SMI buffer\n", __FUNCTION__);
++ dev_dbg(&dcdbas_pdev->dev, "%s: no SMI buffer\n", __func__);
+ return;
+ }
+
+ if (smi_data_buf_size < sizeof(struct apm_cmd)) {
+ dev_dbg(&dcdbas_pdev->dev, "%s: SMI buffer too small\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
+index 477a3d0..6a8b1e0 100644
+--- a/drivers/firmware/dell_rbu.c
++++ b/drivers/firmware/dell_rbu.c
+@@ -123,7 +123,7 @@ static int create_packet(void *data, size_t length)
+ if (!newpacket) {
+ printk(KERN_WARNING
+ "dell_rbu:%s: failed to allocate new "
+- "packet\n", __FUNCTION__);
++ "packet\n", __func__);
+ retval = -ENOMEM;
+ spin_lock(&rbu_data.lock);
+ goto out_noalloc;
+@@ -152,7 +152,7 @@ static int create_packet(void *data, size_t length)
+ printk(KERN_WARNING
+ "dell_rbu:%s: failed to allocate "
+ "invalid_addr_packet_array \n",
+- __FUNCTION__);
++ __func__);
+ retval = -ENOMEM;
+ spin_lock(&rbu_data.lock);
+ goto out_alloc_packet;
+@@ -164,7 +164,7 @@ static int create_packet(void *data, size_t length)
+ if (!packet_data_temp_buf) {
+ printk(KERN_WARNING
+ "dell_rbu:%s: failed to allocate new "
+- "packet\n", __FUNCTION__);
++ "packet\n", __func__);
+ retval = -ENOMEM;
+ spin_lock(&rbu_data.lock);
+ goto out_alloc_packet_array;
+@@ -416,7 +416,7 @@ static int img_update_realloc(unsigned long size)
+ */
+ if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {
+ printk(KERN_ERR "dell_rbu:%s: corruption "
+- "check failed\n", __FUNCTION__);
++ "check failed\n", __func__);
+ return -EINVAL;
+ }
+ /*
+@@ -642,7 +642,7 @@ static ssize_t write_rbu_image_type(struct kobject *kobj,
+ if (req_firm_rc) {
+ printk(KERN_ERR
+ "dell_rbu:%s request_firmware_nowait"
+- " failed %d\n", __FUNCTION__, rc);
++ " failed %d\n", __func__, rc);
+ rc = -EIO;
+ } else
+ rbu_data.entry_created = 1;
+@@ -718,7 +718,7 @@ static int __init dcdrbu_init(void)
+ if (IS_ERR(rbu_device)) {
+ printk(KERN_ERR
+ "dell_rbu:%s:platform_device_register_simple "
+- "failed\n", __FUNCTION__);
++ "failed\n", __func__);
+ return PTR_ERR(rbu_device);
+ }
+
+diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
+new file mode 100644
+index 0000000..8024e3b
+--- /dev/null
++++ b/drivers/firmware/iscsi_ibft.c
+@@ -0,0 +1,982 @@
++/*
++ * Copyright 2007 Red Hat, Inc.
++ * by Peter Jones <pjones at redhat.com>
++ * Copyright 2008 IBM, Inc.
++ * by Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Copyright 2008
++ * by Konrad Rzeszutek <ketuzsezr at darnok.org>
++ *
++ * This code exposes the iSCSI Boot Format Table to userland via sysfs.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License v2.0 as published by
++ * the Free Software Foundation
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * Changelog:
++ *
++ * 14 Mar 2008 - Konrad Rzeszutek <ketuzsezr at darnok.org>
++ * Updated comments and copyrights. (v0.4.9)
++ *
++ * 11 Feb 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Converted to using ibft_addr. (v0.4.8)
++ *
++ * 8 Feb 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Combined two functions in one: reserve_ibft_region. (v0.4.7)
++ *
++ * 30 Jan 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Added logic to handle IPv6 addresses. (v0.4.6)
++ *
++ * 25 Jan 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Added logic to handle badly not-to-spec iBFT. (v0.4.5)
++ *
++ * 4 Jan 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Added __init to function declarations. (v0.4.4)
++ *
++ * 21 Dec 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Updated kobject registration, combined unregister functions in one
++ * and code and style cleanup. (v0.4.3)
++ *
++ * 5 Dec 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Added end-markers to enums and re-organized kobject registration. (v0.4.2)
++ *
++ * 4 Dec 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Created 'device' sysfs link to the NIC and style cleanup. (v0.4.1)
++ *
++ * 28 Nov 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Added sysfs-ibft documentation, moved 'find_ibft' function to
++ * in its own file and added text attributes for every struct field. (v0.4)
++ *
++ * 21 Nov 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Added text attributes emulating OpenFirmware /proc/device-tree naming.
++ * Removed binary /sysfs interface (v0.3)
++ *
++ * 29 Aug 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Added functionality in setup.c to reserve iBFT region. (v0.2)
++ *
++ * 27 Aug 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * First version exposing iBFT data via a binary /sysfs. (v0.1)
++ *
++ */
++
++
++#include <linux/blkdev.h>
++#include <linux/capability.h>
++#include <linux/ctype.h>
++#include <linux/device.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/iscsi_ibft.h>
++#include <linux/limits.h>
++#include <linux/module.h>
++#include <linux/pci.h>
++#include <linux/slab.h>
++#include <linux/stat.h>
++#include <linux/string.h>
++#include <linux/types.h>
++
++#define IBFT_ISCSI_VERSION "0.4.9"
++#define IBFT_ISCSI_DATE "2008-Mar-14"
++
++MODULE_AUTHOR("Peter Jones <pjones at redhat.com> and \
++Konrad Rzeszutek <ketuzsezr at darnok.org>");
++MODULE_DESCRIPTION("sysfs interface to BIOS iBFT information");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(IBFT_ISCSI_VERSION);
++
++struct ibft_hdr {
++ u8 id;
++ u8 version;
++ u16 length;
++ u8 index;
++ u8 flags;
++} __attribute__((__packed__));
++
++struct ibft_control {
++ struct ibft_hdr hdr;
++ u16 extensions;
++ u16 initiator_off;
++ u16 nic0_off;
++ u16 tgt0_off;
++ u16 nic1_off;
++ u16 tgt1_off;
++} __attribute__((__packed__));
++
++struct ibft_initiator {
++ struct ibft_hdr hdr;
++ char isns_server[16];
++ char slp_server[16];
++ char pri_radius_server[16];
++ char sec_radius_server[16];
++ u16 initiator_name_len;
++ u16 initiator_name_off;
++} __attribute__((__packed__));
++
++struct ibft_nic {
++ struct ibft_hdr hdr;
++ char ip_addr[16];
++ u8 subnet_mask_prefix;
++ u8 origin;
++ char gateway[16];
++ char primary_dns[16];
++ char secondary_dns[16];
++ char dhcp[16];
++ u16 vlan;
++ char mac[6];
++ u16 pci_bdf;
++ u16 hostname_len;
++ u16 hostname_off;
++} __attribute__((__packed__));
++
++struct ibft_tgt {
++ struct ibft_hdr hdr;
++ char ip_addr[16];
++ u16 port;
++ char lun[8];
++ u8 chap_type;
++ u8 nic_assoc;
++ u16 tgt_name_len;
++ u16 tgt_name_off;
++ u16 chap_name_len;
++ u16 chap_name_off;
++ u16 chap_secret_len;
++ u16 chap_secret_off;
++ u16 rev_chap_name_len;
++ u16 rev_chap_name_off;
++ u16 rev_chap_secret_len;
++ u16 rev_chap_secret_off;
++} __attribute__((__packed__));
++
++/*
++ * The kobject different types and its names.
++ *
++*/
++enum ibft_id {
++ id_reserved = 0, /* We don't support. */
++ id_control = 1, /* Should show up only once and is not exported. */
++ id_initiator = 2,
++ id_nic = 3,
++ id_target = 4,
++ id_extensions = 5, /* We don't support. */
++ id_end_marker,
++};
++
++/*
++ * We do not support the other types, hence the usage of NULL.
++ * This maps to the enum ibft_id.
++ */
++static const char *ibft_id_names[] =
++ {NULL, NULL, "initiator", "ethernet%d", "target%d", NULL, NULL};
++
++/*
++ * The text attributes names for each of the kobjects.
++*/
++enum ibft_eth_properties_enum {
++ ibft_eth_index,
++ ibft_eth_flags,
++ ibft_eth_ip_addr,
++ ibft_eth_subnet_mask,
++ ibft_eth_origin,
++ ibft_eth_gateway,
++ ibft_eth_primary_dns,
++ ibft_eth_secondary_dns,
++ ibft_eth_dhcp,
++ ibft_eth_vlan,
++ ibft_eth_mac,
++ /* ibft_eth_pci_bdf - this is replaced by link to the device itself. */
++ ibft_eth_hostname,
++ ibft_eth_end_marker,
++};
++
++static const char *ibft_eth_properties[] =
++ {"index", "flags", "ip-addr", "subnet-mask", "origin", "gateway",
++ "primary-dns", "secondary-dns", "dhcp", "vlan", "mac", "hostname",
++ NULL};
++
++enum ibft_tgt_properties_enum {
++ ibft_tgt_index,
++ ibft_tgt_flags,
++ ibft_tgt_ip_addr,
++ ibft_tgt_port,
++ ibft_tgt_lun,
++ ibft_tgt_chap_type,
++ ibft_tgt_nic_assoc,
++ ibft_tgt_name,
++ ibft_tgt_chap_name,
++ ibft_tgt_chap_secret,
++ ibft_tgt_rev_chap_name,
++ ibft_tgt_rev_chap_secret,
++ ibft_tgt_end_marker,
++};
++
++static const char *ibft_tgt_properties[] =
++ {"index", "flags", "ip-addr", "port", "lun", "chap-type", "nic-assoc",
++ "target-name", "chap-name", "chap-secret", "rev-chap-name",
++ "rev-chap-name-secret", NULL};
++
++enum ibft_initiator_properties_enum {
++ ibft_init_index,
++ ibft_init_flags,
++ ibft_init_isns_server,
++ ibft_init_slp_server,
++ ibft_init_pri_radius_server,
++ ibft_init_sec_radius_server,
++ ibft_init_initiator_name,
++ ibft_init_end_marker,
++};
++
++static const char *ibft_initiator_properties[] =
++ {"index", "flags", "isns-server", "slp-server", "pri-radius-server",
++ "sec-radius-server", "initiator-name", NULL};
++
++/*
++ * The kobject and attribute structures.
++ */
++
++struct ibft_kobject {
++ struct ibft_table_header *header;
++ union {
++ struct ibft_initiator *initiator;
++ struct ibft_nic *nic;
++ struct ibft_tgt *tgt;
++ struct ibft_hdr *hdr;
++ };
++ struct kobject kobj;
++ struct list_head node;
++};
++
++struct ibft_attribute {
++ struct attribute attr;
++ ssize_t (*show) (struct ibft_kobject *entry,
++ struct ibft_attribute *attr, char *buf);
++ union {
++ struct ibft_initiator *initiator;
++ struct ibft_nic *nic;
++ struct ibft_tgt *tgt;
++ struct ibft_hdr *hdr;
++ };
++ struct kobject *kobj;
++ int type; /* The enum of the type. This can be any value of:
++ ibft_eth_properties_enum, ibft_tgt_properties_enum,
++ or ibft_initiator_properties_enum. */
++ struct list_head node;
++};
++
++static LIST_HEAD(ibft_attr_list);
++static LIST_HEAD(ibft_kobject_list);
++
++static const char nulls[16];
++
++/*
++ * Helper functions to parse data properly.
++ */
++static ssize_t sprintf_ipaddr(char *buf, u8 *ip)
++{
++ char *str = buf;
++
++ if (ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0 &&
++ ip[4] == 0 && ip[5] == 0 && ip[6] == 0 && ip[7] == 0 &&
++ ip[8] == 0 && ip[9] == 0 && ip[10] == 0xff && ip[11] == 0xff) {
++ /*
++ * IPV4
++ */
++ str += sprintf(buf, NIPQUAD_FMT, ip[12],
++ ip[13], ip[14], ip[15]);
++ } else {
++ /*
++ * IPv6
++ */
++ str += sprintf(str, NIP6_FMT, ntohs(ip[0]), ntohs(ip[1]),
++ ntohs(ip[2]), ntohs(ip[3]), ntohs(ip[4]),
++ ntohs(ip[5]), ntohs(ip[6]), ntohs(ip[7]));
++ }
++ str += sprintf(str, "\n");
++ return str - buf;
++}
++
++static ssize_t sprintf_string(char *str, int len, char *buf)
++{
++ return sprintf(str, "%.*s\n", len, buf);
++}
++
++/*
++ * Helper function to verify the IBFT header.
++ */
++static int ibft_verify_hdr(char *t, struct ibft_hdr *hdr, int id, int length)
++{
++ if (hdr->id != id) {
++ printk(KERN_ERR "iBFT error: We expected the " \
++ "field header.id to have %d but " \
++ "found %d instead!\n", id, hdr->id);
++ return -ENODEV;
++ }
++ if (hdr->length != length) {
++ printk(KERN_ERR "iBFT error: We expected the " \
++ "field header.length to have %d but " \
++ "found %d instead!\n", length, hdr->length);
++ return -ENODEV;
++ }
++
++ return 0;
++}
++
++static void ibft_release(struct kobject *kobj)
++{
++ struct ibft_kobject *ibft =
++ container_of(kobj, struct ibft_kobject, kobj);
++ kfree(ibft);
++}
++
++/*
++ * Routines for parsing the iBFT data to be human readable.
++ */
++ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
++ struct ibft_attribute *attr,
++ char *buf)
++{
++ struct ibft_initiator *initiator = entry->initiator;
++ void *ibft_loc = entry->header;
++ char *str = buf;
++
++ if (!initiator)
++ return 0;
++
++ switch (attr->type) {
++ case ibft_init_index:
++ str += sprintf(str, "%d\n", initiator->hdr.index);
++ break;
++ case ibft_init_flags:
++ str += sprintf(str, "%d\n", initiator->hdr.flags);
++ break;
++ case ibft_init_isns_server:
++ str += sprintf_ipaddr(str, initiator->isns_server);
++ break;
++ case ibft_init_slp_server:
++ str += sprintf_ipaddr(str, initiator->slp_server);
++ break;
++ case ibft_init_pri_radius_server:
++ str += sprintf_ipaddr(str, initiator->pri_radius_server);
++ break;
++ case ibft_init_sec_radius_server:
++ str += sprintf_ipaddr(str, initiator->sec_radius_server);
++ break;
++ case ibft_init_initiator_name:
++ str += sprintf_string(str, initiator->initiator_name_len,
++ (char *)ibft_loc +
++ initiator->initiator_name_off);
++ break;
++ default:
++ break;
++ }
++
++ return str - buf;
++}
++
++ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
++ struct ibft_attribute *attr,
++ char *buf)
++{
++ struct ibft_nic *nic = entry->nic;
++ void *ibft_loc = entry->header;
++ char *str = buf;
++ char *mac;
++ int val;
++
++ if (!nic)
++ return 0;
++
++ switch (attr->type) {
++ case ibft_eth_index:
++ str += sprintf(str, "%d\n", nic->hdr.index);
++ break;
++ case ibft_eth_flags:
++ str += sprintf(str, "%d\n", nic->hdr.flags);
++ break;
++ case ibft_eth_ip_addr:
++ str += sprintf_ipaddr(str, nic->ip_addr);
++ break;
++ case ibft_eth_subnet_mask:
++ val = ~((1 << (32-nic->subnet_mask_prefix))-1);
++ str += sprintf(str, NIPQUAD_FMT,
++ (u8)(val >> 24), (u8)(val >> 16),
++ (u8)(val >> 8), (u8)(val));
++ break;
++ case ibft_eth_origin:
++ str += sprintf(str, "%d\n", nic->origin);
++ break;
++ case ibft_eth_gateway:
++ str += sprintf_ipaddr(str, nic->gateway);
++ break;
++ case ibft_eth_primary_dns:
++ str += sprintf_ipaddr(str, nic->primary_dns);
++ break;
++ case ibft_eth_secondary_dns:
++ str += sprintf_ipaddr(str, nic->secondary_dns);
++ break;
++ case ibft_eth_dhcp:
++ str += sprintf_ipaddr(str, nic->dhcp);
++ break;
++ case ibft_eth_vlan:
++ str += sprintf(str, "%d\n", nic->vlan);
++ break;
++ case ibft_eth_mac:
++ mac = nic->mac;
++ str += sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x\n",
++ (u8)mac[0], (u8)mac[1], (u8)mac[2],
++ (u8)mac[3], (u8)mac[4], (u8)mac[5]);
++ break;
++ case ibft_eth_hostname:
++ str += sprintf_string(str, nic->hostname_len,
++ (char *)ibft_loc + nic->hostname_off);
++ break;
++ default:
++ break;
++ }
++
++ return str - buf;
++};
++
++ssize_t ibft_attr_show_target(struct ibft_kobject *entry,
++ struct ibft_attribute *attr,
++ char *buf)
++{
++ struct ibft_tgt *tgt = entry->tgt;
++ void *ibft_loc = entry->header;
++ char *str = buf;
++ int i;
++
++ if (!tgt)
++ return 0;
++
++ switch (attr->type) {
++ case ibft_tgt_index:
++ str += sprintf(str, "%d\n", tgt->hdr.index);
++ break;
++ case ibft_tgt_flags:
++ str += sprintf(str, "%d\n", tgt->hdr.flags);
++ break;
++ case ibft_tgt_ip_addr:
++ str += sprintf_ipaddr(str, tgt->ip_addr);
++ break;
++ case ibft_tgt_port:
++ str += sprintf(str, "%d\n", tgt->port);
++ break;
++ case ibft_tgt_lun:
++ for (i = 0; i < 8; i++)
++ str += sprintf(str, "%x", (u8)tgt->lun[i]);
++ str += sprintf(str, "\n");
++ break;
++ case ibft_tgt_nic_assoc:
++ str += sprintf(str, "%d\n", tgt->nic_assoc);
++ break;
++ case ibft_tgt_chap_type:
++ str += sprintf(str, "%d\n", tgt->chap_type);
++ break;
++ case ibft_tgt_name:
++ str += sprintf_string(str, tgt->tgt_name_len,
++ (char *)ibft_loc + tgt->tgt_name_off);
++ break;
++ case ibft_tgt_chap_name:
++ str += sprintf_string(str, tgt->chap_name_len,
++ (char *)ibft_loc + tgt->chap_name_off);
++ break;
++ case ibft_tgt_chap_secret:
++ str += sprintf_string(str, tgt->chap_secret_len,
++ (char *)ibft_loc + tgt->chap_secret_off);
++ break;
++ case ibft_tgt_rev_chap_name:
++ str += sprintf_string(str, tgt->rev_chap_name_len,
++ (char *)ibft_loc +
++ tgt->rev_chap_name_off);
++ break;
++ case ibft_tgt_rev_chap_secret:
++ str += sprintf_string(str, tgt->rev_chap_secret_len,
++ (char *)ibft_loc +
++ tgt->rev_chap_secret_off);
++ break;
++ default:
++ break;
++ }
++
++ return str - buf;
++}
++
++/*
++ * The routine called for all sysfs attributes.
++ */
++static ssize_t ibft_show_attribute(struct kobject *kobj,
++ struct attribute *attr,
++ char *buf)
++{
++ struct ibft_kobject *dev =
++ container_of(kobj, struct ibft_kobject, kobj);
++ struct ibft_attribute *ibft_attr =
++ container_of(attr, struct ibft_attribute, attr);
++ ssize_t ret = -EIO;
++ char *str = buf;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EACCES;
++
++ if (ibft_attr->show)
++ ret = ibft_attr->show(dev, ibft_attr, str);
++
++ return ret;
++}
++
++static struct sysfs_ops ibft_attr_ops = {
++ .show = ibft_show_attribute,
++};
++
++static struct kobj_type ibft_ktype = {
++ .release = ibft_release,
++ .sysfs_ops = &ibft_attr_ops,
++};
++
++static struct kset *ibft_kset;
++
++static int __init ibft_check_device(void)
++{
++ int len;
++ u8 *pos;
++ u8 csum = 0;
++
++ len = ibft_addr->length;
++
++ /* Sanity checking of iBFT. */
++ if (ibft_addr->revision != 1) {
++ printk(KERN_ERR "iBFT module supports only revision 1, " \
++ "while this is %d.\n", ibft_addr->revision);
++ return -ENOENT;
++ }
++ for (pos = (u8 *)ibft_addr; pos < (u8 *)ibft_addr + len; pos++)
++ csum += *pos;
++
++ if (csum) {
++ printk(KERN_ERR "iBFT has incorrect checksum (0x%x)!\n", csum);
++ return -ENOENT;
++ }
++
++ return 0;
++}
++
++/*
++ * Helper function for ibft_register_kobjects.
++ */
++static int __init ibft_create_kobject(struct ibft_table_header *header,
++ struct ibft_hdr *hdr,
++ struct list_head *list)
++{
++ struct ibft_kobject *ibft_kobj = NULL;
++ struct ibft_nic *nic = (struct ibft_nic *)hdr;
++ struct pci_dev *pci_dev;
++ int rc = 0;
++
++ ibft_kobj = kzalloc(sizeof(*ibft_kobj), GFP_KERNEL);
++ if (!ibft_kobj)
++ return -ENOMEM;
++
++ ibft_kobj->header = header;
++ ibft_kobj->hdr = hdr;
++
++ switch (hdr->id) {
++ case id_initiator:
++ rc = ibft_verify_hdr("initiator", hdr, id_initiator,
++ sizeof(*ibft_kobj->initiator));
++ break;
++ case id_nic:
++ rc = ibft_verify_hdr("ethernet", hdr, id_nic,
++ sizeof(*ibft_kobj->nic));
++ break;
++ case id_target:
++ rc = ibft_verify_hdr("target", hdr, id_target,
++ sizeof(*ibft_kobj->tgt));
++ break;
++ case id_reserved:
++ case id_control:
++ case id_extensions:
++ /* Fields which we don't support. Ignore them */
++ rc = 1;
++ break;
++ default:
++ printk(KERN_ERR "iBFT has unknown structure type (%d). " \
++ "Report this bug to %.6s!\n", hdr->id,
++ header->oem_id);
++ rc = 1;
++ break;
++ }
++
++ if (rc) {
++ /* Skip adding this kobject, but exit with non-fatal error. */
++ kfree(ibft_kobj);
++ goto out_invalid_struct;
++ }
++
++ ibft_kobj->kobj.kset = ibft_kset;
++
++ rc = kobject_init_and_add(&ibft_kobj->kobj, &ibft_ktype,
++ NULL, ibft_id_names[hdr->id], hdr->index);
++
++ if (rc) {
++ kfree(ibft_kobj);
++ goto out;
++ }
++
++ kobject_uevent(&ibft_kobj->kobj, KOBJ_ADD);
++
++ if (hdr->id == id_nic) {
++ /*
++ * We don't search for the device in other domains than
++ * zero. This is because on x86 platforms the BIOS
++ * executes only devices which are in domain 0. Furthermore, the
++ * iBFT spec doesn't have a domain id field :-(
++ */
++ pci_dev = pci_get_bus_and_slot((nic->pci_bdf & 0xff00) >> 8,
++ (nic->pci_bdf & 0xff));
++ if (pci_dev) {
++ rc = sysfs_create_link(&ibft_kobj->kobj,
++ &pci_dev->dev.kobj, "device");
++ pci_dev_put(pci_dev);
++ }
++ }
++
++ /* Nothing broke so lets add it to the list. */
++ list_add_tail(&ibft_kobj->node, list);
++out:
++ return rc;
++out_invalid_struct:
++ /* Unsupported structs are skipped. */
++ return 0;
++}
++
++/*
++ * Scan the IBFT table structure for the NIC and Target fields. When
++ * found add them on the passed-in list. We do not support the other
++ * fields at this point, so they are skipped.
++ */
++static int __init ibft_register_kobjects(struct ibft_table_header *header,
++ struct list_head *list)
++{
++ struct ibft_control *control = NULL;
++ void *ptr, *end;
++ int rc = 0;
++ u16 offset;
++ u16 eot_offset;
++
++ control = (void *)header + sizeof(*header);
++ end = (void *)control + control->hdr.length;
++ eot_offset = (void *)header + header->length -
++ (void *)control - sizeof(*header);
++ rc = ibft_verify_hdr("control", (struct ibft_hdr *)control, id_control,
++ sizeof(*control));
++
++ /* iBFT table safety checking */
++ rc |= ((control->hdr.index) ? -ENODEV : 0);
++ if (rc) {
++ printk(KERN_ERR "iBFT error: Control header is invalid!\n");
++ return rc;
++ }
++ for (ptr = &control->initiator_off; ptr < end; ptr += sizeof(u16)) {
++ offset = *(u16 *)ptr;
++ if (offset && offset < header->length && offset < eot_offset) {
++ rc = ibft_create_kobject(header,
++ (void *)header + offset,
++ list);
++ if (rc)
++ break;
++ }
++ }
++
++ return rc;
++}
++
++static void ibft_unregister(struct list_head *attr_list,
++ struct list_head *kobj_list)
++{
++ struct ibft_kobject *data = NULL, *n;
++ struct ibft_attribute *attr = NULL, *m;
++
++ list_for_each_entry_safe(attr, m, attr_list, node) {
++ sysfs_remove_file(attr->kobj, &attr->attr);
++ list_del(&attr->node);
++ kfree(attr);
++ };
++ list_del_init(attr_list);
++
++ list_for_each_entry_safe(data, n, kobj_list, node) {
++ list_del(&data->node);
++ if (data->hdr->id == id_nic)
++ sysfs_remove_link(&data->kobj, "device");
++ kobject_put(&data->kobj);
++ };
++ list_del_init(kobj_list);
++}
++
++static int __init ibft_create_attribute(struct ibft_kobject *kobj_data,
++ int type,
++ const char *name,
++ ssize_t (*show)(struct ibft_kobject *,
++ struct ibft_attribute*,
++ char *buf),
++ struct list_head *list)
++{
++ struct ibft_attribute *attr = NULL;
++ struct ibft_hdr *hdr = kobj_data->hdr;
++
++ attr = kmalloc(sizeof(*attr), GFP_KERNEL);
++ if (!attr)
++ return -ENOMEM;
++
++ attr->attr.name = name;
++ attr->attr.mode = S_IRUSR;
++ attr->attr.owner = THIS_MODULE;
++
++ attr->hdr = hdr;
++ attr->show = show;
++ attr->kobj = &kobj_data->kobj;
++ attr->type = type;
++
++ list_add_tail(&attr->node, list);
++
++ return 0;
++}
++
++/*
++ * Helper routiners to check to determine if the entry is valid
++ * in the proper iBFT structure.
++ */
++static int __init ibft_check_nic_for(struct ibft_nic *nic, int entry)
++{
++ int rc = 0;
++
++ switch (entry) {
++ case ibft_eth_index:
++ case ibft_eth_flags:
++ rc = 1;
++ break;
++ case ibft_eth_ip_addr:
++ if (!memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
++ rc = 1;
++ break;
++ case ibft_eth_subnet_mask:
++ if (!memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
++ rc = 1;
++ break;
++ case ibft_eth_origin:
++ rc = 1;
++ break;
++ case ibft_eth_gateway:
++ if (memcmp(nic->gateway, nulls, sizeof(nic->gateway)))
++ rc = 1;
++ break;
++ case ibft_eth_primary_dns:
++ if (memcmp(nic->primary_dns, nulls,
++ sizeof(nic->primary_dns)))
++ rc = 1;
++ break;
++ case ibft_eth_secondary_dns:
++ if (memcmp(nic->secondary_dns, nulls,
++ sizeof(nic->secondary_dns)))
++ rc = 1;
++ break;
++ case ibft_eth_dhcp:
++ if (memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
++ rc = 1;
++ break;
++ case ibft_eth_vlan:
++ case ibft_eth_mac:
++ rc = 1;
++ break;
++ case ibft_eth_hostname:
++ if (nic->hostname_off)
++ rc = 1;
++ break;
++ default:
++ break;
++ }
++
++ return rc;
++}
++
++static int __init ibft_check_tgt_for(struct ibft_tgt *tgt, int entry)
++{
++ int rc = 0;
++
++ switch (entry) {
++ case ibft_tgt_index:
++ case ibft_tgt_flags:
++ case ibft_tgt_ip_addr:
++ case ibft_tgt_port:
++ case ibft_tgt_lun:
++ case ibft_tgt_nic_assoc:
++ case ibft_tgt_chap_type:
++ rc = 1;
++ case ibft_tgt_name:
++ if (tgt->tgt_name_len)
++ rc = 1;
++ break;
++ case ibft_tgt_chap_name:
++ case ibft_tgt_chap_secret:
++ if (tgt->chap_name_len)
++ rc = 1;
++ break;
++ case ibft_tgt_rev_chap_name:
++ case ibft_tgt_rev_chap_secret:
++ if (tgt->rev_chap_name_len)
++ rc = 1;
++ break;
++ default:
++ break;
++ }
++
++ return rc;
++}
++
++static int __init ibft_check_initiator_for(struct ibft_initiator *init,
++ int entry)
++{
++ int rc = 0;
++
++ switch (entry) {
++ case ibft_init_index:
++ case ibft_init_flags:
++ rc = 1;
++ break;
++ case ibft_init_isns_server:
++ if (memcmp(init->isns_server, nulls,
++ sizeof(init->isns_server)))
++ rc = 1;
++ break;
++ case ibft_init_slp_server:
++ if (memcmp(init->slp_server, nulls,
++ sizeof(init->slp_server)))
++ rc = 1;
++ break;
++ case ibft_init_pri_radius_server:
++ if (memcmp(init->pri_radius_server, nulls,
++ sizeof(init->pri_radius_server)))
++ rc = 1;
++ break;
++ case ibft_init_sec_radius_server:
++ if (memcmp(init->sec_radius_server, nulls,
++ sizeof(init->sec_radius_server)))
++ rc = 1;
++ break;
++ case ibft_init_initiator_name:
++ if (init->initiator_name_len)
++ rc = 1;
++ break;
++ default:
++ break;
++ }
++
++ return rc;
++}
++
++/*
++ * Register the attributes for all of the kobjects.
++ */
++static int __init ibft_register_attributes(struct list_head *kobject_list,
++ struct list_head *attr_list)
++{
++ int rc = 0, i = 0;
++ struct ibft_kobject *data = NULL;
++ struct ibft_attribute *attr = NULL, *m;
++
++ list_for_each_entry(data, kobject_list, node) {
++ switch (data->hdr->id) {
++ case id_nic:
++ for (i = 0; i < ibft_eth_end_marker && !rc; i++)
++ if (ibft_check_nic_for(data->nic, i))
++ rc = ibft_create_attribute(data, i,
++ ibft_eth_properties[i],
++ ibft_attr_show_nic, attr_list);
++ break;
++ case id_target:
++ for (i = 0; i < ibft_tgt_end_marker && !rc; i++)
++ if (ibft_check_tgt_for(data->tgt, i))
++ rc = ibft_create_attribute(data, i,
++ ibft_tgt_properties[i],
++ ibft_attr_show_target,
++ attr_list);
++ break;
++ case id_initiator:
++ for (i = 0; i < ibft_init_end_marker && !rc; i++)
++ if (ibft_check_initiator_for(
++ data->initiator, i))
++ rc = ibft_create_attribute(data, i,
++ ibft_initiator_properties[i],
++ ibft_attr_show_initiator,
++ attr_list);
++ break;
++ default:
++ break;
++ }
++ if (rc)
++ break;
++ }
++ list_for_each_entry_safe(attr, m, attr_list, node) {
++ rc = sysfs_create_file(attr->kobj, &attr->attr);
++ if (rc) {
++ list_del(&attr->node);
++ kfree(attr);
++ break;
++ }
++ }
++
++ return rc;
++}
++
++/*
++ * ibft_init() - creates sysfs tree entries for the iBFT data.
++ */
++static int __init ibft_init(void)
++{
++ int rc = 0;
++
++ ibft_kset = kset_create_and_add("ibft", NULL, firmware_kobj);
++ if (!ibft_kset)
++ return -ENOMEM;
++
++ if (ibft_addr) {
++ printk(KERN_INFO "iBFT detected at 0x%lx.\n",
++ virt_to_phys((void *)ibft_addr));
++
++ rc = ibft_check_device();
++ if (rc)
++ goto out_firmware_unregister;
++
++ /* Scan the IBFT for data and register the kobjects. */
++ rc = ibft_register_kobjects(ibft_addr, &ibft_kobject_list);
++ if (rc)
++ goto out_free;
++
++ /* Register the attributes */
++ rc = ibft_register_attributes(&ibft_kobject_list,
++ &ibft_attr_list);
++ if (rc)
++ goto out_free;
++ } else
++ printk(KERN_INFO "No iBFT detected.\n");
++
++ return 0;
++
++out_free:
++ ibft_unregister(&ibft_attr_list, &ibft_kobject_list);
++out_firmware_unregister:
++ kset_unregister(ibft_kset);
++ return rc;
++}
++
++static void __exit ibft_exit(void)
++{
++ ibft_unregister(&ibft_attr_list, &ibft_kobject_list);
++ kset_unregister(ibft_kset);
++}
++
++module_init(ibft_init);
++module_exit(ibft_exit);
+diff --git a/drivers/firmware/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c
+new file mode 100644
+index 0000000..11f1744
+--- /dev/null
++++ b/drivers/firmware/iscsi_ibft_find.c
+@@ -0,0 +1,84 @@
++/*
++ * Copyright 2007 Red Hat, Inc.
++ * by Peter Jones <pjones at redhat.com>
++ * Copyright 2007 IBM, Inc.
++ * by Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Copyright 2008
++ * by Konrad Rzeszutek <ketuzsezr at darnok.org>
++ *
++ * This code finds the iSCSI Boot Format Table.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License v2.0 as published by
++ * the Free Software Foundation
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/bootmem.h>
++#include <linux/blkdev.h>
++#include <linux/ctype.h>
++#include <linux/device.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/limits.h>
++#include <linux/module.h>
++#include <linux/pci.h>
++#include <linux/slab.h>
++#include <linux/stat.h>
++#include <linux/string.h>
++#include <linux/types.h>
++
++#include <asm/mmzone.h>
++
++/*
++ * Physical location of iSCSI Boot Format Table.
++ */
++struct ibft_table_header *ibft_addr;
++EXPORT_SYMBOL_GPL(ibft_addr);
++
++#define IBFT_SIGN "iBFT"
++#define IBFT_SIGN_LEN 4
++#define IBFT_START 0x80000 /* 512kB */
++#define IBFT_END 0x100000 /* 1MB */
++#define VGA_MEM 0xA0000 /* VGA buffer */
++#define VGA_SIZE 0x20000 /* 128kB */
++
++
++/*
++ * Routine used to find the iSCSI Boot Format Table. The logical
++ * kernel address is set in the ibft_addr global variable.
++ */
++void __init reserve_ibft_region(void)
++{
++ unsigned long pos;
++ unsigned int len = 0;
++ void *virt;
++
++ ibft_addr = NULL;
++
++ 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/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index d8db2f8..7f138c6 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -43,6 +43,7 @@ struct gpio_desc {
+ /* flag symbols are bit numbers */
+ #define FLAG_REQUESTED 0
+ #define FLAG_IS_OUT 1
++#define FLAG_RESERVED 2
+
+ #ifdef CONFIG_DEBUG_FS
+ const char *label;
+@@ -68,6 +69,9 @@ static void gpio_ensure_requested(struct gpio_desc *desc)
+ if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
+ pr_warning("GPIO-%d autorequested\n", (int)(desc - gpio_desc));
+ desc_set_label(desc, "[auto]");
++ if (!try_module_get(desc->chip->owner))
++ pr_err("GPIO-%d: module can't be gotten \n",
++ (int)(desc - gpio_desc));
+ }
+ }
+
+@@ -77,6 +81,76 @@ static inline struct gpio_chip *gpio_to_chip(unsigned gpio)
+ return gpio_desc[gpio].chip;
+ }
+
++/* dynamic allocation of GPIOs, e.g. on a hotplugged device */
++static int gpiochip_find_base(int ngpio)
++{
++ int i;
++ int spare = 0;
++ int base = -ENOSPC;
++
++ for (i = ARCH_NR_GPIOS - 1; i >= 0 ; i--) {
++ struct gpio_desc *desc = &gpio_desc[i];
++ struct gpio_chip *chip = desc->chip;
++
++ if (!chip && !test_bit(FLAG_RESERVED, &desc->flags)) {
++ spare++;
++ if (spare == ngpio) {
++ base = i;
++ break;
++ }
++ } else {
++ spare = 0;
++ if (chip)
++ i -= chip->ngpio - 1;
++ }
++ }
++
++ if (gpio_is_valid(base))
++ pr_debug("%s: found new base at %d\n", __func__, base);
++ return base;
++}
++
++/**
++ * gpiochip_reserve() - reserve range of gpios to use with platform code only
++ * @start: starting gpio number
++ * @ngpio: number of gpios to reserve
++ * Context: platform init, potentially before irqs or kmalloc will work
++ *
++ * Returns a negative errno if any gpio within the range is already reserved
++ * or registered, else returns zero as a success code. Use this function
++ * to mark a range of gpios as unavailable for dynamic gpio number allocation,
++ * for example because its driver support is not yet loaded.
++ */
++int __init gpiochip_reserve(int start, int ngpio)
++{
++ int ret = 0;
++ unsigned long flags;
++ int i;
++
++ if (!gpio_is_valid(start) || !gpio_is_valid(start + ngpio))
++ return -EINVAL;
++
++ spin_lock_irqsave(&gpio_lock, flags);
++
++ for (i = start; i < start + ngpio; i++) {
++ struct gpio_desc *desc = &gpio_desc[i];
++
++ if (desc->chip || test_bit(FLAG_RESERVED, &desc->flags)) {
++ ret = -EBUSY;
++ goto err;
++ }
++
++ set_bit(FLAG_RESERVED, &desc->flags);
++ }
++
++ pr_debug("%s: reserved gpios from %d to %d\n",
++ __func__, start, start + ngpio - 1);
++err:
++ spin_unlock_irqrestore(&gpio_lock, flags);
++
++ return ret;
++}
++
+ /**
+ * gpiochip_add() - register a gpio_chip
+ * @chip: the chip to register, with chip->base initialized
+@@ -85,38 +159,49 @@ static inline struct gpio_chip *gpio_to_chip(unsigned gpio)
+ * Returns a negative errno if the chip can't be registered, such as
+ * because the chip->base is invalid or already associated with a
+ * different chip. Otherwise it returns zero as a success code.
++ *
++ * If chip->base is negative, this requests dynamic assignment of
++ * a range of valid GPIOs.
+ */
+ int gpiochip_add(struct gpio_chip *chip)
+ {
+ unsigned long flags;
+ int status = 0;
+ unsigned id;
++ int base = chip->base;
+
+- /* NOTE chip->base negative is reserved to mean a request for
+- * dynamic allocation. We don't currently support that.
+- */
+-
+- if (chip->base < 0 || (chip->base + chip->ngpio) >= ARCH_NR_GPIOS) {
++ if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio))
++ && base >= 0) {
+ status = -EINVAL;
+ goto fail;
+ }
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
++ if (base < 0) {
++ base = gpiochip_find_base(chip->ngpio);
++ if (base < 0) {
++ status = base;
++ goto fail_unlock;
++ }
++ chip->base = base;
++ }
++
+ /* these GPIO numbers must not be managed by another gpio_chip */
+- for (id = chip->base; id < chip->base + chip->ngpio; id++) {
++ for (id = base; id < base + chip->ngpio; id++) {
+ if (gpio_desc[id].chip != NULL) {
+ status = -EBUSY;
+ break;
+ }
+ }
+ if (status == 0) {
+- for (id = chip->base; id < chip->base + chip->ngpio; id++) {
++ for (id = base; id < base + chip->ngpio; id++) {
+ gpio_desc[id].chip = chip;
+ gpio_desc[id].flags = 0;
+ }
+ }
+
++fail_unlock:
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ fail:
+ /* failures here can mean systems won't boot... */
+@@ -171,12 +256,15 @@ int gpio_request(unsigned gpio, const char *label)
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
+- if (gpio >= ARCH_NR_GPIOS)
++ if (!gpio_is_valid(gpio))
+ goto done;
+ desc = &gpio_desc[gpio];
+ if (desc->chip == NULL)
+ goto done;
+
++ if (!try_module_get(desc->chip->owner))
++ goto done;
++
+ /* NOTE: gpio_request() can be called in early boot,
+ * before IRQs are enabled.
+ */
+@@ -184,8 +272,10 @@ int gpio_request(unsigned gpio, const char *label)
+ if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
+ desc_set_label(desc, label ? : "?");
+ status = 0;
+- } else
++ } else {
+ status = -EBUSY;
++ module_put(desc->chip->owner);
++ }
+
+ done:
+ if (status)
+@@ -201,7 +291,7 @@ void gpio_free(unsigned gpio)
+ unsigned long flags;
+ struct gpio_desc *desc;
+
+- if (gpio >= ARCH_NR_GPIOS) {
++ if (!gpio_is_valid(gpio)) {
+ WARN_ON(extra_checks);
+ return;
+ }
+@@ -209,9 +299,10 @@ void gpio_free(unsigned gpio)
+ spin_lock_irqsave(&gpio_lock, flags);
+
+ desc = &gpio_desc[gpio];
+- if (desc->chip && test_and_clear_bit(FLAG_REQUESTED, &desc->flags))
++ if (desc->chip && test_and_clear_bit(FLAG_REQUESTED, &desc->flags)) {
+ desc_set_label(desc, NULL);
+- else
++ module_put(desc->chip->owner);
++ } else
+ WARN_ON(extra_checks);
+
+ spin_unlock_irqrestore(&gpio_lock, flags);
+@@ -236,7 +327,7 @@ const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset)
+ {
+ unsigned gpio = chip->base + offset;
+
+- if (gpio >= ARCH_NR_GPIOS || gpio_desc[gpio].chip != chip)
++ if (!gpio_is_valid(gpio) || gpio_desc[gpio].chip != chip)
+ return NULL;
+ if (test_bit(FLAG_REQUESTED, &gpio_desc[gpio].flags) == 0)
+ return NULL;
+@@ -267,7 +358,7 @@ int gpio_direction_input(unsigned gpio)
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
+- if (gpio >= ARCH_NR_GPIOS)
++ if (!gpio_is_valid(gpio))
+ goto fail;
+ chip = desc->chip;
+ if (!chip || !chip->get || !chip->direction_input)
+@@ -291,7 +382,7 @@ fail:
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ if (status)
+ pr_debug("%s: gpio-%d status %d\n",
+- __FUNCTION__, gpio, status);
++ __func__, gpio, status);
+ return status;
+ }
+ EXPORT_SYMBOL_GPL(gpio_direction_input);
+@@ -305,7 +396,7 @@ int gpio_direction_output(unsigned gpio, int value)
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
+- if (gpio >= ARCH_NR_GPIOS)
++ if (!gpio_is_valid(gpio))
+ goto fail;
+ chip = desc->chip;
+ if (!chip || !chip->set || !chip->direction_output)
+@@ -329,7 +420,7 @@ fail:
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ if (status)
+ pr_debug("%s: gpio-%d status %d\n",
+- __FUNCTION__, gpio, status);
++ __func__, gpio, status);
+ return status;
+ }
+ EXPORT_SYMBOL_GPL(gpio_direction_output);
+@@ -522,7 +613,7 @@ static int gpiolib_show(struct seq_file *s, void *unused)
+
+ /* REVISIT this isn't locked against gpio_chip removal ... */
+
+- for (gpio = 0; gpio < ARCH_NR_GPIOS; gpio++) {
++ for (gpio = 0; gpio_is_valid(gpio); gpio++) {
+ if (chip == gpio_desc[gpio].chip)
+ continue;
+ chip = gpio_desc[gpio].chip;
+diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/mcp23s08.c
+index bb60e8c..7fb5b9d 100644
+--- a/drivers/gpio/mcp23s08.c
++++ b/drivers/gpio/mcp23s08.c
+@@ -239,6 +239,7 @@ static int mcp23s08_probe(struct spi_device *spi)
+ mcp->chip.base = pdata->base;
+ mcp->chip.ngpio = 8;
+ mcp->chip.can_sleep = 1;
++ mcp->chip.owner = THIS_MODULE;
+
+ spi_set_drvdata(spi, mcp);
+
+diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
+index 6e72fd3..5a99e81 100644
+--- a/drivers/gpio/pca953x.c
++++ b/drivers/gpio/pca953x.c
+@@ -23,13 +23,7 @@
+ #define PCA953X_INVERT 2
+ #define PCA953X_DIRECTION 3
+
+-/* This is temporary - in 2.6.26 i2c_driver_data should replace it. */
+-struct pca953x_desc {
+- char name[I2C_NAME_SIZE];
+- unsigned long driver_data;
+-};
+-
+-static const struct pca953x_desc pca953x_descs[] = {
++static const struct i2c_device_id pca953x_id[] = {
+ { "pca9534", 8, },
+ { "pca9535", 16, },
+ { "pca9536", 4, },
+@@ -37,7 +31,9 @@ static const struct pca953x_desc pca953x_descs[] = {
+ { "pca9538", 8, },
+ { "pca9539", 16, },
+ /* REVISIT several pca955x parts should work here too */
++ { }
+ };
++MODULE_DEVICE_TABLE(i2c, pca953x_id);
+
+ struct pca953x_chip {
+ unsigned gpio_start;
+@@ -189,28 +185,20 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
+ gc->base = chip->gpio_start;
+ gc->ngpio = gpios;
+ gc->label = chip->client->name;
++ gc->owner = THIS_MODULE;
+ }
+
+-static int __devinit pca953x_probe(struct i2c_client *client)
++static int __devinit pca953x_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct pca953x_platform_data *pdata;
+ struct pca953x_chip *chip;
+ int ret, i;
+- const struct pca953x_desc *id = NULL;
+
+ pdata = client->dev.platform_data;
+ if (pdata == NULL)
+ return -ENODEV;
+
+- /* this loop vanishes when we get i2c_device_id */
+- for (i = 0; i < ARRAY_SIZE(pca953x_descs); i++)
+- if (!strcmp(pca953x_descs[i].name, client->name)) {
+- id = pca953x_descs + i;
+- break;
+- }
+- if (!id)
+- return -ENODEV;
+-
+ chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+@@ -290,6 +278,7 @@ static struct i2c_driver pca953x_driver = {
+ },
+ .probe = pca953x_probe,
+ .remove = pca953x_remove,
++ .id_table = pca953x_id,
+ };
+
+ static int __init pca953x_init(void)
+diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c
+index c6b3b53..aa6cc8b 100644
+--- a/drivers/gpio/pcf857x.c
++++ b/drivers/gpio/pcf857x.c
+@@ -26,6 +26,21 @@
+ #include <asm/gpio.h>
+
+
++static const struct i2c_device_id pcf857x_id[] = {
++ { "pcf8574", 8 },
++ { "pca8574", 8 },
++ { "pca9670", 8 },
++ { "pca9672", 8 },
++ { "pca9674", 8 },
++ { "pcf8575", 16 },
++ { "pca8575", 16 },
++ { "pca9671", 16 },
++ { "pca9673", 16 },
++ { "pca9675", 16 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, pcf857x_id);
++
+ /*
+ * The pcf857x, pca857x, and pca967x chips only expose one read and one
+ * write register. Writing a "one" bit (to match the reset state) lets
+@@ -142,7 +157,8 @@ static void pcf857x_set16(struct gpio_chip *chip, unsigned offset, int value)
+
+ /*-------------------------------------------------------------------------*/
+
+-static int pcf857x_probe(struct i2c_client *client)
++static int pcf857x_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct pcf857x_platform_data *pdata;
+ struct pcf857x *gpio;
+@@ -159,6 +175,7 @@ static int pcf857x_probe(struct i2c_client *client)
+
+ gpio->chip.base = pdata->gpio_base;
+ gpio->chip.can_sleep = 1;
++ gpio->chip.owner = THIS_MODULE;
+
+ /* NOTE: the OnSemi jlc1562b is also largely compatible with
+ * these parts, notably for output. It has a low-resolution
+@@ -171,13 +188,8 @@ static int pcf857x_probe(struct i2c_client *client)
+ *
+ * NOTE: we don't distinguish here between *4 and *4a parts.
+ */
+- if (strcmp(client->name, "pcf8574") == 0
+- || strcmp(client->name, "pca8574") == 0
+- || strcmp(client->name, "pca9670") == 0
+- || strcmp(client->name, "pca9672") == 0
+- || strcmp(client->name, "pca9674") == 0
+- ) {
+- gpio->chip.ngpio = 8;
++ gpio->chip.ngpio = id->driver_data;
++ if (gpio->chip.ngpio == 8) {
+ gpio->chip.direction_input = pcf857x_input8;
+ gpio->chip.get = pcf857x_get8;
+ gpio->chip.direction_output = pcf857x_output8;
+@@ -197,13 +209,7 @@ static int pcf857x_probe(struct i2c_client *client)
+ *
+ * NOTE: we don't distinguish here between '75 and '75c parts.
+ */
+- } else if (strcmp(client->name, "pcf8575") == 0
+- || strcmp(client->name, "pca8575") == 0
+- || strcmp(client->name, "pca9671") == 0
+- || strcmp(client->name, "pca9673") == 0
+- || strcmp(client->name, "pca9675") == 0
+- ) {
+- gpio->chip.ngpio = 16;
++ } else if (gpio->chip.ngpio == 16) {
+ gpio->chip.direction_input = pcf857x_input16;
+ gpio->chip.get = pcf857x_get16;
+ gpio->chip.direction_output = pcf857x_output16;
+@@ -312,6 +318,7 @@ static struct i2c_driver pcf857x_driver = {
},
+ .probe = pcf857x_probe,
+ .remove = pcf857x_remove,
++ .id_table = pcf857x_id,
+ };
+
+ static int __init pcf857x_init(void)
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index f0b00ec..f43d6d3 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;
+@@ -606,7 +606,7 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
+ case 2:
+ if ((end - start) < 2)
+ return NULL;
+- item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start));
++ item->data.u16 = get_unaligned_le16(start);
+ start = (__u8 *)((__le16 *)start + 1);
+ return start;
+
+@@ -614,7 +614,7 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
+ item->size++;
+ if ((end - start) < 4)
+ return NULL;
+- item->data.u32 = le32_to_cpu(get_unaligned((__le32*)start));
++ item->data.u32 = get_unaligned_le32(start);
+ start = (__u8 *)((__le32 *)start + 1);
+ return start;
+ }
+@@ -765,7 +765,7 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
+
+ report += offset >> 3; /* adjust byte index */
+ offset &= 7; /* now only need bit offset into one byte */
+- x = le64_to_cpu(get_unaligned((__le64 *) report));
++ x = get_unaligned_le64(report);
+ x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */
+ return (u32) x;
+ }
+@@ -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..01427c5 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);
+ }
+
/*
-+ * 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",
+@@ -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;
+@@ -651,7 +654,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co
+ ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ HID_REQ_SET_REPORT,
+ USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+- cpu_to_le16(((HID_OUTPUT_REPORT + 1) << 8) | *buf),
++ ((HID_OUTPUT_REPORT + 1) << 8) | *buf,
+ interface->desc.bInterfaceNumber, buf + 1, count - 1,
+ USB_CTRL_SET_TIMEOUT);
+
+@@ -705,9 +708,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ struct hid_descriptor *hdesc;
+ struct hid_device *hid;
+ u32 quirks = 0;
+- unsigned rsize = 0;
++ unsigned int insize = 0, rsize = 0;
+ char *rdesc;
+- int n, len, insize = 0;
++ int n, len;
+ struct usbhid_device *usbhid;
+
+ quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
+@@ -800,6 +803,22 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ goto fail;
+ }
+
++ hid->name[0] = 0;
++
++ if (dev->manufacturer)
++ strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
++
++ if (dev->product) {
++ if (dev->manufacturer)
++ strlcat(hid->name, " ", sizeof(hid->name));
++ strlcat(hid->name, dev->product, sizeof(hid->name));
+ }
++
++ if (!strlen(hid->name))
++ snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
++ le16_to_cpu(dev->descriptor.idVendor),
++ le16_to_cpu(dev->descriptor.idProduct));
++
+ for (n = 0; n < interface->desc.bNumEndpoints; n++) {
+
+ struct usb_endpoint_descriptor *endpoint;
+@@ -812,6 +831,14 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+
+ interval = endpoint->bInterval;
+
++ /* Some vendors give fullspeed interval on highspeed devides */
++ if (quirks & HID_QUIRK_FULLSPEED_INTERVAL &&
++ dev->speed == USB_SPEED_HIGH) {
++ interval = fls(endpoint->bInterval*8);
++ printk(KERN_INFO "%s: Fixing fullspeed to highspeed interval: %d -> %d\n",
++ hid->name, endpoint->bInterval, interval);
++ }
++
+ /* Change the polling interval of mice. */
+ if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
+ interval = hid_mousepoll_interval;
+@@ -844,8 +871,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ goto fail;
+ }
+
+- init_waitqueue_head(&hid->wait);
+-
++ init_waitqueue_head(&usbhid->wait);
+ INIT_WORK(&usbhid->reset_work, hid_reset);
+ setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
+
+@@ -859,22 +885,6 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ usbhid->intf = intf;
+ usbhid->ifnum = interface->desc.bInterfaceNumber;
+
+- hid->name[0] = 0;
+-
+- if (dev->manufacturer)
+- strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
+-
+- if (dev->product) {
+- if (dev->manufacturer)
+- strlcat(hid->name, " ", sizeof(hid->name));
+- strlcat(hid->name, dev->product, sizeof(hid->name));
+- }
+-
+- if (!strlen(hid->name))
+- snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
+- le16_to_cpu(dev->descriptor.idVendor),
+- le16_to_cpu(dev->descriptor.idProduct));
+-
+ hid->bus = BUS_USB;
+ hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
+ hid->product = le16_to_cpu(dev->descriptor.idProduct);
+@@ -932,6 +942,7 @@ static void hid_disconnect(struct usb_interface *intf)
+
+ spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
+ usb_set_intfdata(intf, NULL);
++ set_bit(HID_DISCONNECTED, &usbhid->iofl);
+ spin_unlock_irq(&usbhid->inlock);
+ usb_kill_urb(usbhid->urbin);
+ usb_kill_urb(usbhid->urbout);
+diff --git a/drivers/hid/usbhid/hid-ff.c b/drivers/hid/usbhid/hid-ff.c
+index 4c210e1..1d0dac5 100644
+--- a/drivers/hid/usbhid/hid-ff.c
++++ b/drivers/hid/usbhid/hid-ff.c
+@@ -59,6 +59,9 @@ static struct hid_ff_initializer inits[] = {
+ { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */
+ { 0x46d, 0xca03, hid_lgff_init }, /* Logitech MOMO force wheel */
+ #endif
++#ifdef CONFIG_LOGIRUMBLEPAD2_FF
++ { 0x46d, 0xc218, hid_lg2ff_init }, /* Logitech Rumblepad 2 */
++#endif
+ #ifdef CONFIG_PANTHERLORD_FF
+ { 0x810, 0x0001, hid_plff_init }, /* "Twin USB Joystick" */
+ { 0xe8f, 0x0003, hid_plff_init }, /* "GreenAsia Inc. USB Joystick " */
+diff --git a/drivers/hid/usbhid/hid-lg2ff.c b/drivers/hid/usbhid/hid-lg2ff.c
+new file mode 100644
+index 0000000..d469bd0
+--- /dev/null
++++ b/drivers/hid/usbhid/hid-lg2ff.c
+@@ -0,0 +1,114 @@
++/*
++ * Force feedback support for Logitech Rumblepad 2
++ *
++ * Copyright (c) 2008 Anssi Hannula <anssi.hannula at gmail.com>
++ */
++
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++
++#include <linux/input.h>
++#include <linux/usb.h>
++#include <linux/hid.h>
++#include "usbhid.h"
++
++struct lg2ff_device {
++ struct hid_report *report;
+};
+
-+static 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",
++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;
+ }
-+};
+
-+/*
- * Compression stuff.
++ usbhid_submit_report(hid, lg2ff->report, USB_DIR_OUT);
++ return 0;
++}
++
++int hid_lg2ff_init(struct hid_device *hid)
++{
++ struct lg2ff_device *lg2ff;
++ struct hid_report *report;
++ struct hid_input *hidinput = list_entry(hid->inputs.next,
++ struct hid_input, list);
++ struct list_head *report_list =
++ &hid->report_enum[HID_OUTPUT_REPORT].report_list;
++ struct input_dev *dev = hidinput->input;
++ int error;
++
++ if (list_empty(report_list)) {
++ printk(KERN_ERR "hid-lg2ff: no output report found\n");
++ return -ENODEV;
++ }
++
++ report = list_entry(report_list->next, struct hid_report, list);
++
++ if (report->maxfield < 1) {
++ printk(KERN_ERR "hid-lg2ff: output report is empty\n");
++ return -ENODEV;
++ }
++ if (report->field[0]->report_count < 7) {
++ printk(KERN_ERR "hid-lg2ff: not enough values in the field\n");
++ return -ENODEV;
++ }
++
++ lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL);
++ if (!lg2ff)
++ return -ENOMEM;
++
++ set_bit(FF_RUMBLE, dev->ffbit);
++
++ error = input_ff_create_memless(dev, lg2ff, play_effect);
++ if (error) {
++ kfree(lg2ff);
++ return error;
++ }
++
++ lg2ff->report = report;
++ report->field[0]->value[0] = 0xf3;
++ report->field[0]->value[1] = 0x00;
++ report->field[0]->value[2] = 0x00;
++ report->field[0]->value[3] = 0x00;
++ report->field[0]->value[4] = 0x00;
++ report->field[0]->value[5] = 0x00;
++ report->field[0]->value[6] = 0x00;
++
++ usbhid_submit_report(hid, report, USB_DIR_OUT);
++
++ printk(KERN_INFO "Force feedback for Logitech Rumblepad 2 by "
++ "Anssi Hannula <anssi.hannula at gmail.com>\n");
++
++ return 0;
++}
+diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
+index e29a057..d3f8d91 100644
+--- a/drivers/hid/usbhid/hid-quirks.c
++++ b/drivers/hid/usbhid/hid-quirks.c
+@@ -32,6 +32,9 @@
+ #define USB_VENDOR_ID_ADS_TECH 0x06e1
+ #define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155
+
++#define USB_VENDOR_ID_AFATECH 0x15a4
++#define USB_DEVICE_ID_AFATECH_AF9016 0x9016
++
+ #define USB_VENDOR_ID_AIPTEK 0x08ca
+ #define USB_DEVICE_ID_AIPTEK_01 0x0001
+ #define USB_DEVICE_ID_AIPTEK_10 0x0010
+@@ -124,6 +127,9 @@
+ #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
+ #define USB_DEVICE_ID_DELORME_EM_LT20 0x0200
+
++#define USB_VENDOR_ID_DMI 0x0c0b
++#define USB_DEVICE_ID_DMI_ENC 0x5fab
++
+ #define USB_VENDOR_ID_ELO 0x04E7
+ #define USB_DEVICE_ID_ELO_TS2700 0x0020
+
+@@ -199,17 +205,6 @@
+ #define USB_DEVICE_ID_GTCO_502 0x0502
+ #define USB_DEVICE_ID_GTCO_503 0x0503
+ #define USB_DEVICE_ID_GTCO_504 0x0504
+-#define USB_DEVICE_ID_GTCO_600 0x0600
+-#define USB_DEVICE_ID_GTCO_601 0x0601
+-#define USB_DEVICE_ID_GTCO_602 0x0602
+-#define USB_DEVICE_ID_GTCO_603 0x0603
+-#define USB_DEVICE_ID_GTCO_604 0x0604
+-#define USB_DEVICE_ID_GTCO_605 0x0605
+-#define USB_DEVICE_ID_GTCO_606 0x0606
+-#define USB_DEVICE_ID_GTCO_607 0x0607
+-#define USB_DEVICE_ID_GTCO_608 0x0608
+-#define USB_DEVICE_ID_GTCO_609 0x0609
+-#define USB_DEVICE_ID_GTCO_609 0x0609
+ #define USB_DEVICE_ID_GTCO_1000 0x1000
+ #define USB_DEVICE_ID_GTCO_1001 0x1001
+ #define USB_DEVICE_ID_GTCO_1002 0x1002
+@@ -320,6 +315,7 @@
+ #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
+ #define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
+ #define USB_DEVICE_ID_DINOVO_EDGE 0xc714
++#define USB_DEVICE_ID_DINOVO_MINI 0xc71f
+
+ #define USB_VENDOR_ID_MCC 0x09db
+ #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076
+@@ -332,6 +328,7 @@
+ #define USB_VENDOR_ID_MICROSOFT 0x045e
+ #define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
+ #define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
++#define USB_DEVICE_ID_DESKTOP_RECV_1028 0x00f9
+ #define USB_DEVICE_ID_MS_NE4K 0x00db
+ #define USB_DEVICE_ID_MS_LK6K 0x00f9
+
+@@ -377,6 +374,9 @@
+ #define USB_VENDOR_ID_SUN 0x0430
+ #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab
+
++#define USB_VENDOR_ID_SUNPLUS 0x04fc
++#define USB_DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8
++
+ #define USB_VENDOR_ID_TOPMAX 0x0663
+ #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103
+
+@@ -405,6 +405,9 @@
+ #define USB_VENDOR_ID_YEALINK 0x6993
+ #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001
+
++#define USB_VENDOR_ID_KYE 0x0458
++#define USB_DEVICE_ID_KYE_GPEN_560 0x5003
++
+ /*
+ * Alphabetically sorted blacklist by quirk type.
*/
- #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",
- },
- };
+@@ -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 },
-@@ -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 ",
- },
- };
+ { 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 },
-@@ -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",
- },
- };
+ { 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 },
-@@ -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 ",
- },
+ { 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 },
-@@ -7809,46 +8010,46 @@ static struct comp_testvec lzo_decomp_tv_template[] = {
+ { USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E, HID_QUIRK_RDESC_BUTTON_CONSUMER },
- 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",
+@@ -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)
}
- };
+ }
-@@ -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[] = {
++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;
++ }
++}
++
/*
- * Cipher speed tests
+ * 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 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, },
++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;
-
-- /* End marker */
-- { .klen = 0, .blen = 0, }
--};
+- if (get_user(idx, (int __user *)arg))
+- return -EFAULT;
-
--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, },
+- if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL)
+- return -ENOMEM;
-
-- /* End marker */
-- { .klen = 0, .blen = 0, }
--};
+- if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) {
+- kfree(buf);
+- return -EINVAL;
+- }
-
--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, },
+- if (copy_to_user(user_arg+sizeof(int), buf, len+1)) {
+- kfree(buf);
+- return -EFAULT;
+- }
-
-- /* End marker */
-- { .klen = 0, .blen = 0, }
--};
+- kfree(buf);
-
--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, },
+- 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;
-
-- /* End marker */
-- { .klen = 0, .blen = 0, }
--};
+- rinfo.report_type = uref->report_type;
+- rinfo.report_id = uref->report_id;
+- if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+- goto inval;
-
--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, },
+- if (uref->field_index >= report->maxfield)
+- goto inval;
-
-- /* End marker */
-- { .klen = 0, .blen = 0, }
--};
+- field = report->field[uref->field_index];
+- if (uref->usage_index >= field->maxusage)
+- goto inval;
-
--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, },
+- uref->usage_code = field->usage[uref->usage_index].hid;
-
-- /* End marker */
-- { .klen = 0, .blen = 0, }
+- if (copy_to_user(user_arg, uref, sizeof(*uref)))
+- goto fault;
+-
+- kfree(uref_multi);
+- return 0;
+-
++ /* fall through */
+ case HIDIOCGUSAGE:
+ case HIDIOCSUSAGE:
+ case HIDIOCGUSAGES:
+ case HIDIOCSUSAGES:
+ case HIDIOCGCOLLECTIONINDEX:
+- uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL);
+- if (!uref_multi)
+- return -ENOMEM;
+- uref = &uref_multi->uref;
+- if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
+- if (copy_from_user(uref_multi, user_arg,
+- sizeof(*uref_multi)))
+- goto fault;
+- } else {
+- if (copy_from_user(uref, user_arg, sizeof(*uref)))
+- goto fault;
+- }
+-
+- if (cmd != HIDIOCGUSAGE &&
+- cmd != HIDIOCGUSAGES &&
+- uref->report_type == HID_REPORT_TYPE_INPUT)
+- goto inval;
+-
+- if (uref->report_id == HID_REPORT_ID_UNKNOWN) {
+- field = hiddev_lookup_usage(hid, uref);
+- if (field == NULL)
+- goto inval;
+- } else {
+- rinfo.report_type = uref->report_type;
+- rinfo.report_id = uref->report_id;
+- if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+- goto inval;
+-
+- if (uref->field_index >= report->maxfield)
+- goto inval;
+-
+- field = report->field[uref->field_index];
+-
+- if (cmd == HIDIOCGCOLLECTIONINDEX) {
+- if (uref->usage_index >= field->maxusage)
+- goto inval;
+- } else if (uref->usage_index >= field->report_count)
+- goto inval;
+-
+- else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
+- (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
+- uref->usage_index + uref_multi->num_values > field->report_count))
+- goto inval;
+- }
+-
+- switch (cmd) {
+- case HIDIOCGUSAGE:
+- uref->value = field->value[uref->usage_index];
+- if (copy_to_user(user_arg, uref, sizeof(*uref)))
+- goto fault;
+- goto goodreturn;
+-
+- case HIDIOCSUSAGE:
+- field->value[uref->usage_index] = uref->value;
+- goto goodreturn;
+-
+- case HIDIOCGCOLLECTIONINDEX:
+- kfree(uref_multi);
+- return field->usage[uref->usage_index].collection_index;
+- case HIDIOCGUSAGES:
+- for (i = 0; i < uref_multi->num_values; i++)
+- uref_multi->values[i] =
+- field->value[uref->usage_index + i];
+- if (copy_to_user(user_arg, uref_multi,
+- sizeof(*uref_multi)))
+- goto fault;
+- goto goodreturn;
+- case HIDIOCSUSAGES:
+- for (i = 0; i < uref_multi->num_values; i++)
+- field->value[uref->usage_index + i] =
+- uref_multi->values[i];
+- goto goodreturn;
+- }
+-
+-goodreturn:
+- kfree(uref_multi);
+- return 0;
+-fault:
+- kfree(uref_multi);
+- return -EFAULT;
+-inval:
+- kfree(uref_multi);
+- return -EINVAL;
++ return hiddev_ioctl_usage(hiddev, cmd, user_arg);
+
+ case HIDIOCGCOLLECTIONINFO:
+ if (copy_from_user(&cinfo, user_arg, sizeof(cinfo)))
+diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
+index 0023f96..62d2d7c 100644
+--- a/drivers/hid/usbhid/usbhid.h
++++ b/drivers/hid/usbhid/usbhid.h
+@@ -28,6 +28,7 @@
+ #include <linux/slab.h>
+ #include <linux/list.h>
+ #include <linux/timer.h>
++#include <linux/wait.h>
+ #include <linux/workqueue.h>
+ #include <linux/input.h>
+
+@@ -77,7 +78,7 @@ struct usbhid_device {
+ unsigned long stop_retry; /* Time to give up, in jiffies */
+ unsigned int retry_delay; /* Delay length in ms */
+ struct work_struct reset_work; /* Task context for resets */
+-
++ wait_queue_head_t wait; /* For sleeping */
+ };
+
+ #define hid_to_usb_dev(hid_dev) \
+diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
+index ed71a8b..5c8b6e0 100644
+--- a/drivers/hwmon/ads7828.c
++++ b/drivers/hwmon/ads7828.c
+@@ -224,7 +224,7 @@ static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind)
+ if (in_data & 0xF000) {
+ printk(KERN_DEBUG
+ "%s : Doesn't look like an ads7828 device\n",
+- __FUNCTION__);
++ __func__);
+ goto exit_free;
+ }
+ }
+diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
+index 1464338..dc1f30e 100644
+--- a/drivers/hwmon/f75375s.c
++++ b/drivers/hwmon/f75375s.c
+@@ -117,7 +117,8 @@ struct f75375_data {
+ static int f75375_attach_adapter(struct i2c_adapter *adapter);
+ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind);
+ static int f75375_detach_client(struct i2c_client *client);
+-static int f75375_probe(struct i2c_client *client);
++static int f75375_probe(struct i2c_client *client,
++ const struct i2c_device_id *id);
+ static int f75375_remove(struct i2c_client *client);
+
+ static struct i2c_driver f75375_legacy_driver = {
+@@ -128,12 +129,20 @@ static struct i2c_driver f75375_legacy_driver = {
+ .detach_client = f75375_detach_client,
+ };
+
++static const struct i2c_device_id f75375_id[] = {
++ { "f75373", f75373 },
++ { "f75375", f75375 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, f75375_id);
++
+ static struct i2c_driver f75375_driver = {
+ .driver = {
+ .name = "f75375",
+ },
+ .probe = f75375_probe,
+ .remove = f75375_remove,
++ .id_table = f75375_id,
+ };
+
+ static inline int f75375_read8(struct i2c_client *client, u8 reg)
+@@ -628,7 +637,8 @@ static void f75375_init(struct i2c_client *client, struct f75375_data *data,
+
+ }
+
+-static int f75375_probe(struct i2c_client *client)
++static int f75375_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct f75375_data *data = i2c_get_clientdata(client);
+ struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data;
+@@ -643,15 +653,7 @@ static int f75375_probe(struct i2c_client *client)
+ i2c_set_clientdata(client, data);
+ data->client = client;
+ mutex_init(&data->update_lock);
+-
+- if (strcmp(client->name, "f75375") == 0)
+- data->kind = f75375;
+- else if (strcmp(client->name, "f75373") == 0)
+- data->kind = f75373;
+- else {
+- dev_err(&client->dev, "Unsupported device: %s\n", client->name);
+- return -ENODEV;
+- }
++ data->kind = id->driver_data;
+
+ if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group)))
+ goto exit_free;
+@@ -712,6 +714,7 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
+ u8 version = 0;
+ int err = 0;
+ const char *name = "";
++ struct i2c_device_id id;
+
+ if (!(client = kzalloc(sizeof(*client), GFP_KERNEL))) {
+ err = -ENOMEM;
+@@ -748,7 +751,9 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
+ if ((err = i2c_attach_client(client)))
+ goto exit_free;
+
+- if ((err = f75375_probe(client)) < 0)
++ strlcpy(id.name, name, I2C_NAME_SIZE);
++ id.driver_data = kind;
++ if ((err = f75375_probe(client, &id)) < 0)
+ goto exit_detach;
+
+ return 0;
+diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig
+index 014dfa5..7137a17 100644
+--- a/drivers/i2c/algos/Kconfig
++++ b/drivers/i2c/algos/Kconfig
+@@ -1,45 +1,16 @@
+ #
+-# Character device configuration
++# I2C algorithm drivers configuration
+ #
+
+-menu "I2C Algorithms"
+-
+ config I2C_ALGOBIT
+- tristate "I2C bit-banging interfaces"
+- help
+- This allows you to use a range of I2C adapters called bit-banging
+- adapters. Say Y if you own an I2C adapter belonging to this class
+- and then say Y to the specific driver for you adapter below.
+-
+- This support is also available as a module. If so, the module
+- will be called i2c-algo-bit.
++ tristate
+
+ config I2C_ALGOPCF
+- tristate "I2C PCF 8584 interfaces"
+- help
+- This allows you to use a range of I2C adapters called PCF adapters.
+- Say Y if you own an I2C adapter belonging to this class and then say
+- Y to the specific driver for you adapter below.
+-
+- This support is also available as a module. If so, the module
+- will be called i2c-algo-pcf.
++ tristate
+
+ config I2C_ALGOPCA
+- tristate "I2C PCA 9564 interfaces"
+- help
+- This allows you to use a range of I2C adapters called PCA adapters.
+- Say Y if you own an I2C adapter belonging to this class and then say
+- Y to the specific driver for you adapter below.
+-
+- This support is also available as a module. If so, the module
+- will be called i2c-algo-pca.
++ tristate
+
+ config I2C_ALGO_SGI
+- tristate "I2C SGI interfaces"
++ tristate
+ depends on SGI_IP22 || SGI_IP32 || X86_VISWS
+- help
+- Supports the SGI interfaces like the ones found on SGI Indy VINO
+- or SGI O2 MACE.
+-
+-endmenu
+-
+diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
+index 2a16211..e954a20 100644
+--- a/drivers/i2c/algos/i2c-algo-pca.c
++++ b/drivers/i2c/algos/i2c-algo-pca.c
+@@ -1,6 +1,7 @@
+ /*
+- * i2c-algo-pca.c i2c driver algorithms for PCA9564 adapters
++ * i2c-algo-pca.c i2c driver algorithms for PCA9564 adapters
+ * Copyright (C) 2004 Arcom Control Systems
++ * Copyright (C) 2008 Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -21,14 +22,10 @@
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+ #include <linux/delay.h>
+-#include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/errno.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c-algo-pca.h>
+-#include "i2c-algo-pca.h"
+-
+-#define DRIVER "i2c-algo-pca"
+
+ #define DEB1(fmt, args...) do { if (i2c_debug>=1) printk(fmt, ## args); } while(0)
+ #define DEB2(fmt, args...) do { if (i2c_debug>=2) printk(fmt, ## args); } while(0)
+@@ -36,15 +33,15 @@
+
+ static int i2c_debug;
+
+-#define pca_outw(adap, reg, val) adap->write_byte(adap, reg, val)
+-#define pca_inw(adap, reg) adap->read_byte(adap, reg)
++#define pca_outw(adap, reg, val) adap->write_byte(adap->data, reg, val)
++#define pca_inw(adap, reg) adap->read_byte(adap->data, reg)
+
+ #define pca_status(adap) pca_inw(adap, I2C_PCA_STA)
+-#define pca_clock(adap) adap->get_clock(adap)
+-#define pca_own(adap) adap->get_own(adap)
++#define pca_clock(adap) adap->i2c_clock
+ #define pca_set_con(adap, val) pca_outw(adap, I2C_PCA_CON, val)
+ #define pca_get_con(adap) pca_inw(adap, I2C_PCA_CON)
+-#define pca_wait(adap) adap->wait_for_interrupt(adap)
++#define pca_wait(adap) adap->wait_for_completion(adap->data)
++#define pca_reset(adap) adap->reset_chip(adap->data)
+
+ /*
+ * Generate a start condition on the i2c bus.
+@@ -99,7 +96,7 @@ static void pca_stop(struct i2c_algo_pca_data *adap)
+ *
+ * returns after the address has been sent
+ */
+-static void pca_address(struct i2c_algo_pca_data *adap,
++static void pca_address(struct i2c_algo_pca_data *adap,
+ struct i2c_msg *msg)
+ {
+ int sta = pca_get_con(adap);
+@@ -108,9 +105,9 @@ static void pca_address(struct i2c_algo_pca_data *adap,
+ addr = ( (0x7f & msg->addr) << 1 );
+ if (msg->flags & I2C_M_RD )
+ addr |= 1;
+- DEB2("=== SLAVE ADDRESS %#04x+%c=%#04x\n",
++ DEB2("=== SLAVE ADDRESS %#04x+%c=%#04x\n",
+ msg->addr, msg->flags & I2C_M_RD ? 'R' : 'W', addr);
+-
++
+ pca_outw(adap, I2C_PCA_DAT, addr);
+
+ sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI);
+@@ -124,7 +121,7 @@ static void pca_address(struct i2c_algo_pca_data *adap,
+ *
+ * Returns after the byte has been transmitted
+ */
+-static void pca_tx_byte(struct i2c_algo_pca_data *adap,
++static void pca_tx_byte(struct i2c_algo_pca_data *adap,
+ __u8 b)
+ {
+ int sta = pca_get_con(adap);
+@@ -142,19 +139,19 @@ static void pca_tx_byte(struct i2c_algo_pca_data *adap,
+ *
+ * returns immediately.
+ */
+-static void pca_rx_byte(struct i2c_algo_pca_data *adap,
++static void pca_rx_byte(struct i2c_algo_pca_data *adap,
+ __u8 *b, int ack)
+ {
+ *b = pca_inw(adap, I2C_PCA_DAT);
+ DEB2("=== READ %#04x %s\n", *b, ack ? "ACK" : "NACK");
+ }
+
+-/*
++/*
+ * Setup ACK or NACK for next received byte and wait for it to arrive.
+ *
+ * Returns after next byte has arrived.
+ */
+-static void pca_rx_ack(struct i2c_algo_pca_data *adap,
++static void pca_rx_ack(struct i2c_algo_pca_data *adap,
+ int ack)
+ {
+ int sta = pca_get_con(adap);
+@@ -168,15 +165,6 @@ static void pca_rx_ack(struct i2c_algo_pca_data *adap,
+ pca_wait(adap);
+ }
+
+-/*
+- * Reset the i2c bus / SIO
+- */
+-static void pca_reset(struct i2c_algo_pca_data *adap)
+-{
+- /* apparently only an external reset will do it. not a lot can be done */
+- printk(KERN_ERR DRIVER ": Haven't figured out how to do a reset yet\n");
+-}
+-
+ static int pca_xfer(struct i2c_adapter *i2c_adap,
+ struct i2c_msg *msgs,
+ int num)
+@@ -187,7 +175,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
+ int numbytes = 0;
+ int state;
+ int ret;
+- int timeout = 100;
++ int timeout = i2c_adap->timeout;
+
+ while ((state = pca_status(adap)) != 0xf8 && timeout--) {
+ msleep(10);
+@@ -203,14 +191,14 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
+ for (curmsg = 0; curmsg < num; curmsg++) {
+ int addr, i;
+ msg = &msgs[curmsg];
+-
++
+ addr = (0x7f & msg->addr) ;
+-
++
+ if (msg->flags & I2C_M_RD )
+- printk(KERN_INFO " [%02d] RD %d bytes from %#02x [%#02x, ...]\n",
++ printk(KERN_INFO " [%02d] RD %d bytes from %#02x [%#02x, ...]\n",
+ curmsg, msg->len, addr, (addr<<1) | 1);
+ else {
+- printk(KERN_INFO " [%02d] WR %d bytes to %#02x [%#02x%s",
++ printk(KERN_INFO " [%02d] WR %d bytes to %#02x [%#02x%s",
+ curmsg, msg->len, addr, addr<<1,
+ msg->len == 0 ? "" : ", ");
+ for(i=0; i < msg->len; i++)
+@@ -237,7 +225,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
+ case 0x10: /* A repeated start condition has been transmitted */
+ pca_address(adap, msg);
+ break;
+-
++
+ case 0x18: /* SLA+W has been transmitted; ACK has been received */
+ case 0x28: /* Data byte in I2CDAT has been transmitted; ACK has been received */
+ if (numbytes < msg->len) {
+@@ -287,7 +275,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
+ case 0x38: /* Arbitration lost during SLA+W, SLA+R or data bytes */
+ DEB2("Arbitration lost\n");
+ goto out;
+-
++
+ case 0x58: /* Data byte has been received; NOT ACK has been returned */
+ if ( numbytes == msg->len - 1 ) {
+ pca_rx_byte(adap, &msg->buf[numbytes], 0);
+@@ -317,16 +305,16 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
+ pca_reset(adap);
+ goto out;
+ default:
+- printk(KERN_ERR DRIVER ": unhandled SIO state 0x%02x\n", state);
++ dev_err(&i2c_adap->dev, "unhandled SIO state 0x%02x\n", state);
+ break;
+ }
+-
++
+ }
+
+ ret = curmsg;
+ out:
+ DEB1(KERN_CRIT "}}} transfered %d/%d messages. "
+- "status is %#04x. control is %#04x\n",
++ "status is %#04x. control is %#04x\n",
+ curmsg, num, pca_status(adap),
+ pca_get_con(adap));
+ return ret;
+@@ -337,53 +325,65 @@ static u32 pca_func(struct i2c_adapter *adap)
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+ }
+
+-static int pca_init(struct i2c_algo_pca_data *adap)
++static const struct i2c_algorithm pca_algo = {
++ .master_xfer = pca_xfer,
++ .functionality = pca_func,
++};
++
++static int pca_init(struct i2c_adapter *adap)
+ {
+ static int freqs[] = {330,288,217,146,88,59,44,36};
+- int own, clock;
++ int clock;
++ struct i2c_algo_pca_data *pca_data = adap->algo_data;
++
++ if (pca_data->i2c_clock > 7) {
++ printk(KERN_WARNING "%s: Invalid I2C clock speed selected. Trying default.\n",
++ adap->name);
++ pca_data->i2c_clock = I2C_PCA_CON_59kHz;
++ }
++
++ adap->algo = &pca_algo;
+
+- own = pca_own(adap);
+- clock = pca_clock(adap);
+- DEB1(KERN_INFO DRIVER ": own address is %#04x\n", own);
+- DEB1(KERN_INFO DRIVER ": clock freqeuncy is %dkHz\n", freqs[clock]);
++ pca_reset(pca_data);
+
+- pca_outw(adap, I2C_PCA_ADR, own << 1);
++ clock = pca_clock(pca_data);
++ DEB1(KERN_INFO "%s: Clock frequency is %dkHz\n", adap->name, freqs[clock]);
+
+- pca_set_con(adap, I2C_PCA_CON_ENSIO | clock);
+- udelay(500); /* 500 µs for oscilator to stabilise */
++ pca_set_con(pca_data, I2C_PCA_CON_ENSIO | clock);
++ udelay(500); /* 500 us for oscilator to stabilise */
+
+ return 0;
+ }
+
+-static const struct i2c_algorithm pca_algo = {
+- .master_xfer = pca_xfer,
+- .functionality = pca_func,
-};
-
--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
+-/*
+- * registering functions to load algorithms at runtime
++/*
++ * registering functions to load algorithms at runtime
*/
- 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, }
- };
+ int i2c_pca_add_bus(struct i2c_adapter *adap)
+ {
+- struct i2c_algo_pca_data *pca_adap = adap->algo_data;
+ int rval;
--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, },
+- /* register new adapter to i2c module... */
+- adap->algo = &pca_algo;
++ rval = pca_init(adap);
++ if (rval)
++ return rval;
+
+- adap->timeout = 100; /* default values, should */
+- adap->retries = 3; /* be replaced by defines */
++ return i2c_add_adapter(adap);
++}
++EXPORT_SYMBOL(i2c_pca_add_bus);
+
+- if ((rval = pca_init(pca_adap)))
+- return rval;
++int i2c_pca_add_numbered_bus(struct i2c_adapter *adap)
++{
++ int rval;
+
+- rval = i2c_add_adapter(adap);
++ rval = pca_init(adap);
++ if (rval)
++ return rval;
+
+- return rval;
++ return i2c_add_numbered_adapter(adap);
+ }
+-EXPORT_SYMBOL(i2c_pca_add_bus);
++EXPORT_SYMBOL(i2c_pca_add_numbered_bus);
+
+-MODULE_AUTHOR("Ian Campbell <icampbell at arcom.com>");
++MODULE_AUTHOR("Ian Campbell <icampbell at arcom.com>, "
++ "Wolfram Sang <w.sang at pengutronix.de>");
+ MODULE_DESCRIPTION("I2C-Bus PCA9564 algorithm");
+ MODULE_LICENSE("GPL");
+
+diff --git a/drivers/i2c/algos/i2c-algo-pca.h b/drivers/i2c/algos/i2c-algo-pca.h
+deleted file mode 100644
+index 2fee07e..0000000
+--- a/drivers/i2c/algos/i2c-algo-pca.h
++++ /dev/null
+@@ -1,26 +0,0 @@
+-#ifndef I2C_PCA9564_H
+-#define I2C_PCA9564_H 1
-
-- /* End marker */
-- { .klen = 0, .blen = 0, }
--};
+-#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 */
-
--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, },
+-#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) */
-
-- /* End marker */
-- { .klen = 0, .blen = 0, }
--};
+-#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 /* _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 } }
- };
+-#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
--static int __init init(void)
-+static int __init tea_mod_init(void)
- {
- int ret = 0;
-
-@@ -292,7 +292,7 @@ out:
- return ret;
- }
+ 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.
--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");
+@@ -135,7 +138,7 @@ config I2C_ELEKTOR
+ This supports the PCF8584 ISA bus I2C adapter. Say Y if you own
+ such an adapter.
--module_init(init);
--module_exit(fini);
-+module_init(tea_mod_init);
-+module_exit(tea_mod_fini);
+- 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.
- 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}}
- };
+ 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
--static int __init init(void)
-+static int __init tgr192_mod_init(void)
- {
- int ret = 0;
+ 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.
-@@ -688,7 +688,7 @@ static int __init init(void)
- return ret;
- }
+ 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.
--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");
+ 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.
--module_init(init);
--module_exit(fini);
-+module_init(tgr192_mod_init);
-+module_exit(tgr192_mod_fini);
+- 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-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c
+index e5e96c8..c38a0a1 100644
+--- a/drivers/i2c/busses/i2c-amd756-s4882.c
++++ b/drivers/i2c/busses/i2c-amd756-s4882.c
+@@ -1,7 +1,7 @@
+ /*
+ * i2c-amd756-s4882.c - i2c-amd756 extras for the Tyan S4882 motherboard
+ *
+- * Copyright (C) 2004 Jean Delvare <khali at linux-fr.org>
++ * Copyright (C) 2004, 2008 Jean Delvare <khali at linux-fr.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -231,7 +231,8 @@ ERROR2:
+ kfree(s4882_adapter);
+ s4882_adapter = NULL;
+ ERROR1:
+- i2c_del_adapter(&amd756_smbus);
++ /* Restore physical bus */
++ i2c_add_adapter(&amd756_smbus);
+ ERROR0:
+ return error;
+ }
+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_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 } }
++MODULE_ALIAS("platform:au1xpsc_smbus");
+
+ module_init (i2c_au1550_init);
+ module_exit (i2c_au1550_exit);
+diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
+index 7dbdaeb..48d084b 100644
+--- a/drivers/i2c/busses/i2c-bfin-twi.c
++++ b/drivers/i2c/busses/i2c-bfin-twi.c
+@@ -1,25 +1,11 @@
+ /*
+- * drivers/i2c/busses/i2c-bfin-twi.c
++ * Blackfin On-Chip Two Wire Interface Driver
+ *
+- * Description: Driver for Blackfin Two Wire Interface
++ * Copyright 2005-2007 Analog Devices Inc.
+ *
+- * Author: sonicz <sonic.zhang at analog.com>
++ * Enter bugs at http://blackfin.uclinux.org/
+ *
+- * Copyright (c) 2005-2007 Analog Devices, Inc.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ * Licensed under the GPL-2 or later.
+ */
+
+ #include <linux/module.h>
+@@ -34,14 +20,16 @@
+ #include <linux/platform_device.h>
+
+ #include <asm/blackfin.h>
++#include <asm/portmux.h>
+ #include <asm/irq.h>
+
+ #define POLL_TIMEOUT (2 * HZ)
+
+ /* SMBus mode*/
+-#define TWI_I2C_MODE_STANDARD 0x01
+-#define TWI_I2C_MODE_STANDARDSUB 0x02
+-#define TWI_I2C_MODE_COMBINED 0x04
++#define TWI_I2C_MODE_STANDARD 1
++#define TWI_I2C_MODE_STANDARDSUB 2
++#define TWI_I2C_MODE_COMBINED 3
++#define TWI_I2C_MODE_REPEAT 4
+
+ struct bfin_twi_iface {
+ int irq;
+@@ -58,39 +46,74 @@ struct bfin_twi_iface {
+ struct timer_list timeout_timer;
+ struct i2c_adapter adap;
+ struct completion complete;
++ struct i2c_msg *pmsg;
++ int msg_num;
++ int cur_msg;
++ void __iomem *regs_base;
};
--static int __init init(void)
-+static int __init twofish_mod_init(void)
+-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)
{
- return crypto_register_alg(&alg);
- }
+- 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);
--static void __exit fini(void)
-+static void __exit twofish_mod_fini(void)
+ 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,
{
- crypto_unregister_alg(&alg);
+ 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;
}
--module_init(init);
--module_exit(fini);
-+module_init(twofish_mod_init);
-+module_exit(twofish_mod_fini);
+ /*
+@@ -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;
- 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 } }
- };
+- if (!(bfin_read_TWI_CONTROL() & TWI_ENA))
++ if (!(read_CONTROL(iface) & TWI_ENA))
+ return -ENXIO;
--static int __init init(void)
-+static int __init wp512_mod_init(void)
+- 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)
{
- int ret = 0;
+-/* struct bfin_twi_iface *iface = platform_get_drvdata(dev);*/
++ struct bfin_twi_iface *iface = platform_get_drvdata(dev);
-@@ -1172,7 +1172,7 @@ out:
- return ret;
+ /* 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 void __exit fini(void)
-+static void __exit wp512_mod_fini(void)
+-static int i2c_bfin_twi_probe(struct platform_device *dev)
++static int i2c_bfin_twi_probe(struct platform_device *pdev)
{
- crypto_unregister_alg(&wp512);
- crypto_unregister_alg(&wp384);
-@@ -1182,8 +1182,8 @@ static void __exit fini(void)
- MODULE_ALIAS("wp384");
- MODULE_ALIAS("wp256");
+- struct bfin_twi_iface *iface = &twi_iface;
++ struct bfin_twi_iface *iface;
+ struct i2c_adapter *p_adap;
++ struct resource *res;
+ int rc;
--module_init(init);
--module_exit(fini);
-+module_init(wp512_mod_init);
-+module_exit(wp512_mod_fini);
++ 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;
++ }
- 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"
+ 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)
- source "drivers/uio/Kconfig"
+ 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;
+
-+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);
++ 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;
++ }
--const static struct acpi_device_id ac_device_ids[] = {
-+static const struct acpi_device_id ac_device_ids[] = {
- {"ACPI0003", 0},
- {"", 0},
- };
-diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
-index a697fb6..a498a6c 100644
---- a/drivers/acpi/osl.c
-+++ b/drivers/acpi/osl.c
-@@ -4,6 +4,8 @@
- * Copyright (C) 2000 Andrew Henroid
- * Copyright (C) 2001, 2002 Andy Grover <andrew.grover at intel.com>
- * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh at intel.com>
-+ * Copyright (c) 2008 Intel Corporation
-+ * Author: Matthew Wilcox <willy at linux.intel.com>
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
-@@ -37,15 +39,18 @@
- #include <linux/workqueue.h>
- #include <linux/nmi.h>
- #include <linux/acpi.h>
--#include <acpi/acpi.h>
--#include <asm/io.h>
--#include <acpi/acpi_bus.h>
--#include <acpi/processor.h>
--#include <asm/uaccess.h>
--
- #include <linux/efi.h>
- #include <linux/ioport.h>
- #include <linux/list.h>
-+#include <linux/jiffies.h>
-+#include <linux/semaphore.h>
+ 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;
++ }
+
-+#include <asm/io.h>
-+#include <asm/uaccess.h>
++ platform_set_drvdata(pdev, iface);
+
++ dev_info(&pdev->dev, "Blackfin BF5xx on-chip I2C TWI Contoller, "
++ "regs_base@%p\n", iface->regs_base);
+
-+#include <acpi/acpi.h>
-+#include <acpi/acpi_bus.h>
-+#include <acpi/processor.h>
++ 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;
+ }
- #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;
+@@ -594,6 +707,9 @@ static int i2c_bfin_twi_remove(struct platform_device *pdev)
--
- 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)
+ 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)
{
- struct semaphore *sem = (struct semaphore *)handle;
+- pr_info("I2C: Blackfin I2C TWI driver\n");
+-
+ return platform_driver_register(&i2c_bfin_twi_driver);
+ }
+
+@@ -621,9 +735,10 @@ static void __exit i2c_bfin_twi_exit(void)
+ platform_driver_unregister(&i2c_bfin_twi_driver);
+ }
+-MODULE_AUTHOR("Sonic Zhang <sonic.zhang at analog.com>");
+-MODULE_DESCRIPTION("I2C-Bus adapter routines for Blackfin TWI");
+-MODULE_LICENSE("GPL");
-
- if (!sem)
- return AE_BAD_PARAMETER;
+ 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;
- ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle));
+- dev_dbg(dev->dev, "%s: msgs: %d\n", __FUNCTION__, num);
++ dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
-+ BUG_ON(!list_empty(&sem->wait_list));
- kfree(sem);
- sem = NULL;
+ ret = i2c_davinci_wait_bus_not_busy(dev, 1);
+ if (ret < 0) {
+@@ -342,7 +342,7 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+ return ret;
+ }
+
+- dev_dbg(dev->dev, "%s:%d ret: %d\n", __FUNCTION__, __LINE__, ret);
++ dev_dbg(dev->dev, "%s:%d ret: %d\n", __func__, __LINE__, ret);
+
+ return num;
+ }
+@@ -364,7 +364,7 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
+ u16 w;
+
+ while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) {
+- dev_dbg(dev->dev, "%s: stat=0x%x\n", __FUNCTION__, stat);
++ dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
+ if (count++ == 100) {
+ dev_warn(dev->dev, "Too much work in one IRQ\n");
+ break;
+@@ -553,6 +553,9 @@ static int davinci_i2c_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:i2c_davinci");
++
+ static struct platform_driver davinci_i2c_driver = {
+ .probe = davinci_i2c_probe,
+ .remove = davinci_i2c_remove,
+diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
+index 3ca19fc..7c1b762 100644
+--- a/drivers/i2c/busses/i2c-gpio.c
++++ b/drivers/i2c/busses/i2c-gpio.c
+@@ -220,3 +220,4 @@ module_exit(i2c_gpio_exit);
+ MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen at atmel.com>");
+ MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:i2c-gpio");
+diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
+index 22bb247..85dbf34 100644
+--- a/drivers/i2c/busses/i2c-ibm_iic.c
++++ b/drivers/i2c/busses/i2c-ibm_iic.c
+@@ -6,6 +6,9 @@
+ * Copyright (c) 2003, 2004 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin at zultys.com> or <ebs at ebshome.net>
+ *
++ * Copyright (c) 2008 PIKA Technologies
++ * Sean MacLennan <smaclennan at pikatech.com>
++ *
+ * Based on original work by
+ * Ian DaSilva <idasilva at mvista.com>
+ * Armin Kuster <akuster at mvista.com>
+@@ -39,12 +42,17 @@
+ #include <asm/io.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c-id.h>
++
++#ifdef CONFIG_IBM_OCP
+ #include <asm/ocp.h>
+ #include <asm/ibm4xx.h>
++#else
++#include <linux/of_platform.h>
++#endif
+
+ #include "i2c-ibm_iic.h"
+
+-#define DRIVER_VERSION "2.1"
++#define DRIVER_VERSION "2.2"
+
+ MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION);
+ MODULE_LICENSE("GPL");
+@@ -650,13 +658,14 @@ static inline u8 iic_clckdiv(unsigned int opb)
+ opb /= 1000000;
-@@ -804,21 +808,15 @@ acpi_status acpi_os_delete_semaphore(acpi_handle handle)
+ 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
/*
-- * 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?
+ * Register single IIC interface
*/
- 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;
+@@ -672,7 +681,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
+ ocp->def->index);
--
- if (!sem || (units < 1))
- return AE_BAD_PARAMETER;
+ 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){
+ }
-@@ -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));
+ 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;
-- /*
-- * 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;
+ if ((ret = i2c_add_numbered_adapter(adap)) < 0) {
+- printk(KERN_CRIT "ibm-iic%d: failed to register i2c adapter\n",
++ printk(KERN_ERR "ibm-iic%d: failed to register i2c adapter\n",
+ dev->idx);
+ goto fail;
+ }
+@@ -778,7 +787,7 @@ static void __devexit iic_remove(struct ocp_device *ocp)
+ struct ibm_iic_private* dev = (struct ibm_iic_private*)ocp_get_drvdata(ocp);
+ BUG_ON(dev == NULL);
+ if (i2c_del_adapter(&dev->adap)){
+- printk(KERN_CRIT "ibm-iic%d: failed to delete i2c adapter :(\n",
++ printk(KERN_ERR "ibm-iic%d: failed to delete i2c adapter :(\n",
+ dev->idx);
+ /* That's *very* bad, just shutdown IRQ ... */
+ if (dev->irq >= 0){
+@@ -828,5 +837,181 @@ static void __exit iic_exit(void)
+ ocp_unregister_driver(&ibm_iic_driver);
+ }
+
++#else /* !CONFIG_IBM_OCP */
++
++static int __devinit iic_request_irq(struct of_device *ofdev,
++ struct ibm_iic_private *dev)
++{
++ struct device_node *np = ofdev->node;
++ int irq;
++
++ if (iic_force_poll)
++ return NO_IRQ;
++
++ irq = irq_of_parse_and_map(np, 0);
++ if (irq == NO_IRQ) {
++ dev_err(&ofdev->dev, "irq_of_parse_and_map failed\n");
++ return NO_IRQ;
++ }
++
++ /* Disable interrupts until we finish initialization, assumes
++ * level-sensitive IRQ setup...
++ */
++ iic_interrupt_mode(dev, 0);
++ if (request_irq(irq, iic_handler, 0, "IBM IIC", dev)) {
++ dev_err(&ofdev->dev, "request_irq %d failed\n", irq);
++ /* Fallback to the polling mode */
++ return NO_IRQ;
++ }
++
++ return irq;
++}
++
++/*
++ * Register single IIC interface
++ */
++static int __devinit iic_probe(struct of_device *ofdev,
++ const struct of_device_id *match)
++{
++ struct device_node *np = ofdev->node;
++ struct ibm_iic_private *dev;
++ struct i2c_adapter *adap;
++ const u32 *indexp, *freq;
++ int ret;
++
++ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
++ if (!dev) {
++ dev_err(&ofdev->dev, "failed to allocate device data\n");
++ return -ENOMEM;
++ }
++
++ dev_set_drvdata(&ofdev->dev, dev);
++
++ indexp = of_get_property(np, "index", NULL);
++ if (!indexp) {
++ dev_err(&ofdev->dev, "no index specified\n");
++ ret = -EINVAL;
++ goto error_cleanup;
++ }
++ dev->idx = *indexp;
++
++ dev->vaddr = of_iomap(np, 0);
++ if (dev->vaddr == NULL) {
++ dev_err(&ofdev->dev, "failed to iomap device\n");
++ ret = -ENXIO;
++ goto error_cleanup;
++ }
++
++ init_waitqueue_head(&dev->wq);
++
++ dev->irq = iic_request_irq(ofdev, dev);
++ if (dev->irq == NO_IRQ)
++ dev_warn(&ofdev->dev, "using polling mode\n");
++
++ /* Board specific settings */
++ if (iic_force_fast || of_get_property(np, "fast-mode", NULL))
++ dev->fast_mode = 1;
++
++ freq = of_get_property(np, "clock-frequency", NULL);
++ if (freq == NULL) {
++ freq = of_get_property(np->parent, "clock-frequency", NULL);
++ if (freq == NULL) {
++ dev_err(&ofdev->dev, "Unable to get bus frequency\n");
++ ret = -EINVAL;
++ goto error_cleanup;
++ }
++ }
++
++ dev->clckdiv = iic_clckdiv(*freq);
++ dev_dbg(&ofdev->dev, "clckdiv = %d\n", dev->clckdiv);
++
++ /* Initialize IIC interface */
++ iic_dev_init(dev);
++
++ /* Register it with i2c layer */
++ adap = &dev->adap;
++ adap->dev.parent = &ofdev->dev;
++ strlcpy(adap->name, "IBM IIC", sizeof(adap->name));
++ i2c_set_adapdata(adap, dev);
++ adap->id = I2C_HW_OCP;
++ adap->class = I2C_CLASS_HWMON;
++ adap->algo = &iic_algo;
++ adap->timeout = 1;
++ adap->nr = dev->idx;
++
++ ret = i2c_add_numbered_adapter(adap);
++ if (ret < 0) {
++ dev_err(&ofdev->dev, "failed to register i2c adapter\n");
++ goto error_cleanup;
++ }
++
++ dev_info(&ofdev->dev, "using %s mode\n",
++ dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
++
++ return 0;
++
++error_cleanup:
++ if (dev->irq != NO_IRQ) {
++ iic_interrupt_mode(dev, 0);
++ free_irq(dev->irq, dev);
++ }
++
++ if (dev->vaddr)
++ iounmap(dev->vaddr);
++
++ dev_set_drvdata(&ofdev->dev, NULL);
++ kfree(dev);
++ return ret;
++}
++
++/*
++ * Cleanup initialized IIC interface
++ */
++static int __devexit iic_remove(struct of_device *ofdev)
++{
++ struct ibm_iic_private *dev = dev_get_drvdata(&ofdev->dev);
++
++ dev_set_drvdata(&ofdev->dev, NULL);
++
++ i2c_del_adapter(&dev->adap);
++
++ if (dev->irq != NO_IRQ) {
++ iic_interrupt_mode(dev, 0);
++ free_irq(dev->irq, dev);
++ }
++
++ iounmap(dev->vaddr);
++ kfree(dev);
++
++ return 0;
++}
++
++static const struct of_device_id ibm_iic_match[] = {
++ { .compatible = "ibm,iic-405ex", },
++ { .compatible = "ibm,iic-405gp", },
++ { .compatible = "ibm,iic-440gp", },
++ { .compatible = "ibm,iic-440gpx", },
++ { .compatible = "ibm,iic-440grx", },
++ {}
++};
++
++static struct of_platform_driver ibm_iic_driver = {
++ .name = "ibm-iic",
++ .match_table = ibm_iic_match,
++ .probe = iic_probe,
++ .remove = __devexit_p(iic_remove),
++};
++
++static int __init iic_init(void)
++{
++ return of_register_platform_driver(&ibm_iic_driver);
++}
++
++static void __exit iic_exit(void)
++{
++ of_unregister_platform_driver(&ibm_iic_driver);
++}
++#endif /* CONFIG_IBM_OCP */
++
+ module_init(iic_init);
+ module_exit(iic_exit);
+diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
+index ab41400..39884e7 100644
+--- a/drivers/i2c/busses/i2c-iop3xx.c
++++ b/drivers/i2c/busses/i2c-iop3xx.c
+@@ -550,3 +550,4 @@ module_exit (i2c_iop3xx_exit);
+ MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>");
+ MODULE_DESCRIPTION("IOP3xx iic algorithm and driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:IOP3xx-I2C");
+diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
+index 6352121..5af9e65 100644
+--- a/drivers/i2c/busses/i2c-ixp2000.c
++++ b/drivers/i2c/busses/i2c-ixp2000.c
+@@ -164,4 +164,5 @@ module_exit(ixp2000_i2c_exit);
+ MODULE_AUTHOR ("Deepak Saxena <dsaxena at plexity.net>");
+ MODULE_DESCRIPTION("IXP2000 GPIO-based I2C bus driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:IXP2000-I2C");
+
+diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
+index bbe787b..18beb0a 100644
+--- a/drivers/i2c/busses/i2c-mpc.c
++++ b/drivers/i2c/busses/i2c-mpc.c
+@@ -392,6 +392,9 @@ static int fsl_i2c_remove(struct platform_device *pdev)
+ return 0;
+ };
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:fsl-i2c");
++
+ /* Structure for a device driver */
+ static struct platform_driver fsl_i2c_driver = {
+ .probe = fsl_i2c_probe,
+diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
+index e417c2c..f145692 100644
+--- a/drivers/i2c/busses/i2c-ocores.c
++++ b/drivers/i2c/busses/i2c-ocores.c
+@@ -312,6 +312,9 @@ static int __devexit ocores_i2c_remove(struct platform_device* pdev)
+ return 0;
+ }
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:ocores-i2c");
++
+ static struct platform_driver ocores_i2c_driver = {
+ .probe = ocores_i2c_probe,
+ .remove = __devexit_p(ocores_i2c_remove),
+diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
+index 7ba3177..e7eb7bf 100644
+--- a/drivers/i2c/busses/i2c-omap.c
++++ b/drivers/i2c/busses/i2c-omap.c
+@@ -693,3 +693,4 @@ module_exit(omap_i2c_exit_driver);
+ MODULE_AUTHOR("MontaVista Software, Inc. (and others)");
+ MODULE_DESCRIPTION("TI OMAP I2C bus adapter");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:i2c_omap");
+diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
+index 496ee87..a119784 100644
+--- a/drivers/i2c/busses/i2c-pca-isa.c
++++ b/drivers/i2c/busses/i2c-pca-isa.c
+@@ -1,6 +1,7 @@
+ /*
+ * i2c-pca-isa.c driver for PCA9564 on ISA boards
+ * Copyright (C) 2004 Arcom Control Systems
++ * Copyright (C) 2008 Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -22,11 +23,9 @@
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+ #include <linux/delay.h>
+-#include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/wait.h>
-
-- /*
-- * Wait w/ Timeout:
-- * ----------------
-- */
-- default:
-- // TODO: A better timeout algorithm?
-- {
-- int i = 0;
-- static const int quantum_ms = 1000 / HZ;
+ #include <linux/isa.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c-algo-pca.h>
+@@ -34,13 +33,9 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+
+-#include "../algos/i2c-algo-pca.h"
-
-- ret = down_trylock(sem);
-- for (i = timeout; (i > 0 && ret != 0); i -= quantum_ms) {
-- schedule_timeout_interruptible(1);
-- ret = down_trylock(sem);
-- }
++#define DRIVER "i2c-pca-isa"
+ #define IO_SIZE 4
+
+-#undef DEBUG_IO
+-//#define DEBUG_IO
-
-- 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;
+ static unsigned long base = 0x330;
+ static int irq = 10;
- 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;
+@@ -48,22 +43,9 @@ static int irq = 10;
+ * in the actual clock rate */
+ static int clock = I2C_PCA_CON_59kHz;
+-static int own = 0x55;
-
- if (!sem || (units < 1))
- return AE_BAD_PARAMETER;
+ static wait_queue_head_t pca_wait;
-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);
+-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);
+ }
- return ret;
+-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;
}
-@@ -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);
+
+-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 {
-@@ -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);
+- 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);
}
- /* 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
++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;
+ }
- 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
+ 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,
+ };
-+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).
+ static struct i2c_adapter pca_isa_ops = {
+@@ -117,6 +104,7 @@ static struct i2c_adapter pca_isa_ops = {
+ .id = I2C_HW_A_ISA,
+ .algo_data = &pca_isa_data,
+ .name = "PCA9564 ISA Adapter",
++ .timeout = 100,
+ };
+
+ static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
+@@ -144,6 +132,7 @@ static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
+ }
+ }
+
++ pca_isa_data.i2c_clock = clock;
+ if (i2c_pca_add_bus(&pca_isa_ops) < 0) {
+ dev_err(dev, "Failed to add i2c bus\n");
+ goto out_irq;
+@@ -178,7 +167,7 @@ static struct isa_driver pca_isa_driver = {
+ .remove = __devexit_p(pca_isa_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+- .name = "i2c-pca-isa",
++ .name = DRIVER,
+ }
+ };
+
+@@ -204,7 +193,5 @@ MODULE_PARM_DESC(irq, "IRQ");
+ module_param(clock, int, 0);
+ MODULE_PARM_DESC(clock, "Clock rate as described in table 1 of PCA9564 datasheet");
+
+-module_param(own, int, 0); /* the driver can't do slave mode, so there's no real point in this */
+-
+ module_init(pca_isa_init);
+ module_exit(pca_isa_exit);
+diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c
+new file mode 100644
+index 0000000..9d75f51
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-pca-platform.c
+@@ -0,0 +1,298 @@
++/*
++ * i2c_pca_platform.c
++ *
++ * Platform driver for the PCA9564 I2C controller.
++ *
++ * Copyright (C) 2008 Pengutronix
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++
++ */
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/errno.h>
++#include <linux/i2c.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/i2c-algo-pca.h>
++#include <linux/i2c-pca-platform.h>
++#include <linux/gpio.h>
++
++#include <asm/irq.h>
++#include <asm/io.h>
++
++#define res_len(r) ((r)->end - (r)->start + 1)
++
++struct i2c_pca_pf_data {
++ void __iomem *reg_base;
++ int irq; /* if 0, use polling */
++ int gpio;
++ wait_queue_head_t wait;
++ struct i2c_adapter adap;
++ struct i2c_algo_pca_data algo_data;
++ unsigned long io_base;
++ unsigned long io_size;
++};
++
++/* Read/Write functions for different register alignments */
++
++static int i2c_pca_pf_readbyte8(void *pd, int reg)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++ return ioread8(i2c->reg_base + reg);
++}
++
++static int i2c_pca_pf_readbyte16(void *pd, int reg)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++ return ioread8(i2c->reg_base + reg * 2);
++}
++
++static int i2c_pca_pf_readbyte32(void *pd, int reg)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++ return ioread8(i2c->reg_base + reg * 4);
++}
++
++static void i2c_pca_pf_writebyte8(void *pd, int reg, int val)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++ iowrite8(val, i2c->reg_base + reg);
++}
++
++static void i2c_pca_pf_writebyte16(void *pd, int reg, int val)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++ iowrite8(val, i2c->reg_base + reg * 2);
++}
++
++static void i2c_pca_pf_writebyte32(void *pd, int reg, int val)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++ iowrite8(val, i2c->reg_base + reg * 4);
++}
++
++
++static int i2c_pca_pf_waitforcompletion(void *pd)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++ int ret = 0;
++
++ if (i2c->irq) {
++ ret = wait_event_interruptible(i2c->wait,
++ i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
++ & I2C_PCA_CON_SI);
++ } else {
++ /*
++ * Do polling...
++ * XXX: Could get stuck in extreme cases!
++ * Maybe add timeout, but using irqs is preferred anyhow.
++ */
++ while ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
++ & I2C_PCA_CON_SI) == 0)
++ udelay(100);
++ }
++
++ return ret;
++}
++
++static void i2c_pca_pf_dummyreset(void *pd)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++ printk(KERN_WARNING "%s: No reset-pin found. Chip may get stuck!\n",
++ i2c->adap.name);
++}
++
++static void i2c_pca_pf_resetchip(void *pd)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++
++ gpio_set_value(i2c->gpio, 0);
++ ndelay(100);
++ gpio_set_value(i2c->gpio, 1);
++}
++
++static irqreturn_t i2c_pca_pf_handler(int this_irq, void *dev_id)
++{
++ struct i2c_pca_pf_data *i2c = dev_id;
++
++ if ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0)
++ return IRQ_NONE;
++
++ wake_up_interruptible(&i2c->wait);
++
++ return IRQ_HANDLED;
++}
+
- 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.
++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;
+
-+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.
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ irq = platform_get_irq(pdev, 0);
++ /* If irq is 0, we do polling. */
+
-+ If unsure, say N.
++ if (res == NULL) {
++ ret = -ENODEV;
++ goto e_print;
++ }
+
-+config ATA_SFF
-+ bool "ATA SFF support"
-+ default y
-+ help
-+ This option adds support for ATA controllers with SFF
-+ compliant or similar programming interface.
++ if (!request_mem_region(res->start, res_len(res), res->name)) {
++ ret = -ENOMEM;
++ goto e_print;
++ }
+
-+ 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.
++ i2c = kzalloc(sizeof(struct i2c_pca_pf_data), GFP_KERNEL);
++ if (!i2c) {
++ ret = -ENOMEM;
++ goto e_alloc;
++ }
+
-+ For users with exclusively modern controllers like AHCI,
-+ Silicon Image 3124, or Marvell 6440, you may choose to
-+ disable this uneeded SFF support.
++ init_waitqueue_head(&i2c->wait);
+
-+ If unsure, say Y.
++ 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;
+
-+if ATA_SFF
++ 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;
+
- config SATA_SVW
- tristate "ServerWorks Frodo / Apple K2 SATA support"
- depends on PCI
-@@ -125,14 +169,6 @@ config SATA_SIL
-
- If unsure, say N.
++ i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed;
++ i2c->algo_data.data = i2c;
++
++ switch (res->flags & IORESOURCE_MEM_TYPE_MASK) {
++ case IORESOURCE_MEM_32BIT:
++ i2c->algo_data.write_byte = i2c_pca_pf_writebyte32;
++ i2c->algo_data.read_byte = i2c_pca_pf_readbyte32;
++ break;
++ case IORESOURCE_MEM_16BIT:
++ i2c->algo_data.write_byte = i2c_pca_pf_writebyte16;
++ i2c->algo_data.read_byte = i2c_pca_pf_readbyte16;
++ break;
++ case IORESOURCE_MEM_8BIT:
++ default:
++ i2c->algo_data.write_byte = i2c_pca_pf_writebyte8;
++ i2c->algo_data.read_byte = i2c_pca_pf_readbyte8;
++ break;
++ }
++
++ i2c->algo_data.wait_for_completion = i2c_pca_pf_waitforcompletion;
++
++ i2c->gpio = platform_data->gpio;
++ i2c->algo_data.reset_chip = i2c_pca_pf_dummyreset;
++
++ /* Use gpio_is_valid() when in mainline */
++ if (i2c->gpio > -1) {
++ ret = gpio_request(i2c->gpio, i2c->adap.name);
++ if (ret == 0) {
++ gpio_direction_output(i2c->gpio, 1);
++ i2c->algo_data.reset_chip = i2c_pca_pf_resetchip;
++ } else {
++ printk(KERN_WARNING "%s: Registering gpio failed!\n",
++ i2c->adap.name);
++ i2c->gpio = ret;
++ }
++ }
++
++ if (irq) {
++ ret = request_irq(irq, i2c_pca_pf_handler,
++ IRQF_TRIGGER_FALLING, i2c->adap.name, i2c);
++ if (ret)
++ goto e_reqirq;
++ }
++
++ if (i2c_pca_add_numbered_bus(&i2c->adap) < 0) {
++ ret = -ENODEV;
++ goto e_adapt;
++ }
++
++ platform_set_drvdata(pdev, i2c);
++
++ printk(KERN_INFO "%s registered.\n", i2c->adap.name);
++
++ return 0;
++
++e_adapt:
++ if (irq)
++ free_irq(irq, i2c);
++e_reqirq:
++ if (i2c->gpio > -1)
++ gpio_free(i2c->gpio);
++
++ iounmap(i2c->reg_base);
++e_remap:
++ kfree(i2c);
++e_alloc:
++ release_mem_region(res->start, res_len(res));
++e_print:
++ printk(KERN_ERR "Registering PCA9564 FAILED! (%d)\n", ret);
++ return ret;
++}
++
++static int __devexit i2c_pca_pf_remove(struct platform_device *pdev)
++{
++ struct i2c_pca_pf_data *i2c = platform_get_drvdata(pdev);
++ platform_set_drvdata(pdev, NULL);
++
++ i2c_del_adapter(&i2c->adap);
++
++ if (i2c->irq)
++ free_irq(i2c->irq, i2c);
++
++ if (i2c->gpio > -1)
++ gpio_free(i2c->gpio);
++
++ iounmap(i2c->reg_base);
++ release_mem_region(i2c->io_base, i2c->io_size);
++ kfree(i2c);
++
++ return 0;
++}
++
++static struct platform_driver i2c_pca_pf_driver = {
++ .probe = i2c_pca_pf_probe,
++ .remove = __devexit_p(i2c_pca_pf_remove),
++ .driver = {
++ .name = "i2c-pca-platform",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init i2c_pca_pf_init(void)
++{
++ return platform_driver_register(&i2c_pca_pf_driver);
++}
++
++static void __exit i2c_pca_pf_exit(void)
++{
++ platform_driver_unregister(&i2c_pca_pf_driver);
++}
++
++MODULE_AUTHOR("Wolfram Sang <w.sang at pengutronix.de>");
++MODULE_DESCRIPTION("I2C-PCA9564 platform driver");
++MODULE_LICENSE("GPL");
++
++module_init(i2c_pca_pf_init);
++module_exit(i2c_pca_pf_exit);
++
+diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
+index 9bbe96c..fdc9ad8 100644
+--- a/drivers/i2c/busses/i2c-piix4.c
++++ b/drivers/i2c/busses/i2c-piix4.c
+@@ -38,7 +38,6 @@
+ #include <linux/ioport.h>
+ #include <linux/i2c.h>
+ #include <linux/init.h>
+-#include <linux/apm_bios.h>
+ #include <linux/dmi.h>
+ #include <asm/io.h>
--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.
+@@ -223,7 +222,7 @@ static int piix4_transaction(void)
+ dev_err(&piix4_adapter.dev, "Failed! (%02x)\n", temp);
+ return -1;
+ } else {
+- dev_dbg(&piix4_adapter.dev, "Successfull!\n");
++ dev_dbg(&piix4_adapter.dev, "Successful!\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 PATA_ALI
- tristate "ALi PATA support (Experimental)"
- depends on PCI && EXPERIMENTAL
-@@ -679,4 +706,5 @@ config PATA_BF54X
+@@ -343,12 +342,7 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
- 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
+ switch (size) {
+- case PIIX4_BYTE: /* Where is the result put? I assume here it is in
+- SMBHSTDAT0 but it might just as well be in the
+- SMBHSTCMD. No clue in the docs */
+-
+- data->byte = inb_p(SMBHSTDAT0);
+- break;
++ case PIIX4_BYTE:
+ case PIIX4_BYTE_DATA:
+ data->byte = inb_p(SMBHSTDAT0);
+ break;
+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;
+ }
--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,
+@@ -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;
+ }
- ICH_MAP = 0x90, /* ICH MAP register */
+@@ -627,6 +627,9 @@ static struct i2c_adapter pmcmsptwi_adapter = {
+ .name = DRV_NAME,
};
-@@ -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
- };
++/* 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;
- 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,
- };
+- 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);
--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,
+ /* 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));
- .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,
+- 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);
- .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,
+ /* 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));
- .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,
+- dev_dbg(&adap->dev, "%s(): exit\n", __FUNCTION__);
++ dev_dbg(&adap->dev, "%s(): exit\n", __func__);
-+ .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,
- };
+ return 0;
+ }
+@@ -135,7 +135,7 @@ static void i2c_pnx_stop(struct i2c_adapter *adap)
+ long timeout = 1000;
--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,
-+};
+ dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
+- __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++ __func__, ioread32(I2C_REG_STS(alg_data)));
-- .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,
- };
+ /* 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)
+ }
- #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)
+ dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
+- __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++ __func__, ioread32(I2C_REG_STS(alg_data)));
+ }
- static void ahci_enable_ahci(void __iomem *mmio)
- {
-+ int i;
- u32 tmp;
+ /**
+@@ -164,7 +164,7 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
+ u32 val;
- /* 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);
+ 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);
}
-+
-+ WARN_ON(1);
+
+ 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;
- /**
-@@ -1255,13 +1188,14 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
+ dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
+- __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++ __func__, ioread32(I2C_REG_STS(alg_data)));
- 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;
+ /* 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__);
- /* 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;
+ 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)));
-@@ -1328,10 +1262,21 @@ static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
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;
--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,
+ 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);
- DPRINTK("ENTER\n");
+ /* 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));
-- 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);
+ 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)));
-- /* 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;
- }
+ 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));
--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;
+ 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)));
- 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);
+ bus_reset_if_active(adap);
-- rc = sata_std_hardreset(link, class, deadline);
-+ rc = sata_link_hardreset(link, timing, deadline, &online,
-+ ahci_check_ready);
+@@ -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);
- ahci_start_engine(ap);
+- 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);
-- 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;
+@@ -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);
- 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;
+ /* 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;
- DPRINTK("ENTER\n");
-@@ -1447,11 +1374,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
- ahci_stop_engine(ap);
+ dev_dbg(&adap->dev, "%s(): exiting, stat = %x\n",
+- __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++ __func__, ioread32(I2C_REG_STS(alg_data)));
- 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);
+ if (completed != num)
+ return ((rc < 0) ? rc : -EREMOTEIO);
+@@ -563,7 +563,7 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev)
- ahci_start_engine(ap);
+ if (!i2c_pnx || !i2c_pnx->adapter) {
+ dev_err(&pdev->dev, "%s: no platform data supplied\n",
+- __FUNCTION__);
++ __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+@@ -697,6 +697,7 @@ static void __exit i2c_adap_pnx_exit(void)
+ MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev <source at mvista.com>");
+ MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:pnx-i2c");
-@@ -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;
+ /* 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)
}
- 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);
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:i2c-powermac");
++
+ static struct platform_driver i2c_powermac_driver = {
+ .probe = i2c_powermac_probe,
+ .remove = __devexit_p(i2c_powermac_remove),
+diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
+index 2d2087a..eb69fba 100644
+--- a/drivers/i2c/busses/i2c-pxa.c
++++ b/drivers/i2c/busses/i2c-pxa.c
+@@ -39,6 +39,7 @@
+ #include <asm/io.h>
+ #include <asm/arch/i2c.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
- rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
-- deadline);
-+ deadline, &online, NULL);
+ 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)));
+ }
- ahci_start_engine(ap);
+-#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
-- 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;
+@@ -1131,6 +1132,7 @@ static void __exit i2c_adap_pxa_exit(void)
}
- 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)
- }
- }
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:pxa2xx-i2c");
--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);
+ 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) {
- 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]);
- }
+ case STATE_IDLE:
+- dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __FUNCTION__);
++ dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __func__);
+ goto out;
+ break;
+
+ case STATE_STOP:
+- dev_err(i2c->dev, "%s: called in STATE_STOP\n", __FUNCTION__);
++ dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__);
+ s3c24xx_i2c_disable_irq(i2c);
+ goto out_ack;
+
+@@ -948,3 +948,4 @@ module_exit(i2c_adap_s3c_exit);
+ MODULE_DESCRIPTION("S3C24XX I2C Bus driver");
+ MODULE_AUTHOR("Ben Dooks, <ben at simtec.co.uk>");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:s3c2410-i2c");
+diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c
+new file mode 100644
+index 0000000..5e0e254
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-sh7760.c
+@@ -0,0 +1,577 @@
++/*
++ * I2C bus driver for the SH7760 I2C Interfaces.
++ *
++ * (c) 2005-2008 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau at msc-ge.com>
++ *
++ * licensed under the terms outlined in the file COPYING.
++ *
++ */
++
++#include <linux/completion.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/i2c.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++
++#include <asm/clock.h>
++#include <asm/i2c-sh7760.h>
++#include <asm/io.h>
++
++/* register offsets */
++#define I2CSCR 0x0 /* slave ctrl */
++#define I2CMCR 0x4 /* master ctrl */
++#define I2CSSR 0x8 /* slave status */
++#define I2CMSR 0xC /* master status */
++#define I2CSIER 0x10 /* slave irq enable */
++#define I2CMIER 0x14 /* master irq enable */
++#define I2CCCR 0x18 /* clock dividers */
++#define I2CSAR 0x1c /* slave address */
++#define I2CMAR 0x20 /* master address */
++#define I2CRXTX 0x24 /* data port */
++#define I2CFCR 0x28 /* fifo control */
++#define I2CFSR 0x2C /* fifo status */
++#define I2CFIER 0x30 /* fifo irq enable */
++#define I2CRFDR 0x34 /* rx fifo count */
++#define I2CTFDR 0x38 /* tx fifo count */
++
++#define REGSIZE 0x3C
++
++#define MCR_MDBS 0x80 /* non-fifo mode switch */
++#define MCR_FSCL 0x40 /* override SCL pin */
++#define MCR_FSDA 0x20 /* override SDA pin */
++#define MCR_OBPC 0x10 /* override pins */
++#define MCR_MIE 0x08 /* master if enable */
++#define MCR_TSBE 0x04
++#define MCR_FSB 0x02 /* force stop bit */
++#define MCR_ESG 0x01 /* en startbit gen. */
++
++#define MSR_MNR 0x40 /* nack received */
++#define MSR_MAL 0x20 /* arbitration lost */
++#define MSR_MST 0x10 /* sent a stop */
++#define MSR_MDE 0x08
++#define MSR_MDT 0x04
++#define MSR_MDR 0x02
++#define MSR_MAT 0x01 /* slave addr xfer done */
++
++#define MIE_MNRE 0x40 /* nack irq en */
++#define MIE_MALE 0x20 /* arblos irq en */
++#define MIE_MSTE 0x10 /* stop irq en */
++#define MIE_MDEE 0x08
++#define MIE_MDTE 0x04
++#define MIE_MDRE 0x02
++#define MIE_MATE 0x01 /* address sent irq en */
++
++#define FCR_RFRST 0x02 /* reset rx fifo */
++#define FCR_TFRST 0x01 /* reset tx fifo */
++
++#define FSR_TEND 0x04 /* last byte sent */
++#define FSR_RDF 0x02 /* rx fifo trigger */
++#define FSR_TDFE 0x01 /* tx fifo empty */
++
++#define FIER_TEIE 0x04 /* tx fifo empty irq en */
++#define FIER_RXIE 0x02 /* rx fifo trig irq en */
++#define FIER_TXIE 0x01 /* tx fifo trig irq en */
++
++#define FIFO_SIZE 16
++
++struct cami2c {
++ void __iomem *iobase;
++ struct i2c_adapter adap;
++
++ /* message processing */
++ struct i2c_msg *msg;
++#define IDF_SEND 1
++#define IDF_RECV 2
++#define IDF_STOP 4
++ int flags;
++
++#define IDS_DONE 1
++#define IDS_ARBLOST 2
++#define IDS_NACK 4
++ int status;
++ struct completion xfer_done;
++
++ int irq;
++ struct resource *ioarea;
++};
++
++static inline void OUT32(struct cami2c *cam, int reg, unsigned long val)
++{
++ ctrl_outl(val, (unsigned long)cam->iobase + reg);
++}
++
++static inline unsigned long IN32(struct cami2c *cam, int reg)
++{
++ return ctrl_inl((unsigned long)cam->iobase + reg);
++}
++
++static irqreturn_t sh7760_i2c_irq(int irq, void *ptr)
++{
++ struct cami2c *id = ptr;
++ struct i2c_msg *msg = id->msg;
++ char *data = msg->buf;
++ unsigned long msr, fsr, fier, len;
++
++ msr = IN32(id, I2CMSR);
++ fsr = IN32(id, I2CFSR);
++
++ /* arbitration lost */
++ if (msr & MSR_MAL) {
++ OUT32(id, I2CMCR, 0);
++ OUT32(id, I2CSCR, 0);
++ OUT32(id, I2CSAR, 0);
++ id->status |= IDS_DONE | IDS_ARBLOST;
++ goto out;
++ }
++
++ if (msr & MSR_MNR) {
++ /* NACK handling is very screwed up. After receiving a
++ * NAK IRQ one has to wait a bit before writing to any
++ * registers, or the ctl will lock up. After that delay
++ * do a normal i2c stop. Then wait at least 1 ms before
++ * attempting another transfer or ctl will stop working
++ */
++ udelay(100); /* wait or risk ctl hang */
++ OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
++ OUT32(id, I2CMCR, MCR_MIE | MCR_FSB);
++ OUT32(id, I2CFIER, 0);
++ OUT32(id, I2CMIER, MIE_MSTE);
++ OUT32(id, I2CSCR, 0);
++ OUT32(id, I2CSAR, 0);
++ id->status |= IDS_NACK;
++ msr &= ~MSR_MAT;
++ fsr = 0;
++ /* In some cases the MST bit is also set. */
++ }
++
++ /* i2c-stop was sent */
++ if (msr & MSR_MST) {
++ id->status |= IDS_DONE;
++ goto out;
++ }
++
++ /* i2c slave addr was sent; set to "normal" operation */
++ if (msr & MSR_MAT)
++ OUT32(id, I2CMCR, MCR_MIE);
++
++ fier = IN32(id, I2CFIER);
++
++ if (fsr & FSR_RDF) {
++ len = IN32(id, I2CRFDR);
++ if (msg->len <= len) {
++ if (id->flags & IDF_STOP) {
++ OUT32(id, I2CMCR, MCR_MIE | MCR_FSB);
++ OUT32(id, I2CFIER, 0);
++ /* manual says: wait >= 0.5 SCL times */
++ udelay(5);
++ /* next int should be MST */
++ } else {
++ id->status |= IDS_DONE;
++ /* keep the RDF bit: ctrl holds SCL low
++ * until the setup for the next i2c_msg
++ * clears this bit.
++ */
++ fsr &= ~FSR_RDF;
++ }
++ }
++ while (msg->len && len) {
++ *data++ = IN32(id, I2CRXTX);
++ msg->len--;
++ len--;
++ }
++
++ if (msg->len) {
++ len = (msg->len >= FIFO_SIZE) ? FIFO_SIZE - 1
++ : msg->len - 1;
++
++ OUT32(id, I2CFCR, FCR_TFRST | ((len & 0xf) << 4));
++ }
++
++ } else if (id->flags & IDF_SEND) {
++ if ((fsr & FSR_TEND) && (msg->len < 1)) {
++ if (id->flags & IDF_STOP) {
++ OUT32(id, I2CMCR, MCR_MIE | MCR_FSB);
++ } else {
++ id->status |= IDS_DONE;
++ /* keep the TEND bit: ctl holds SCL low
++ * until the setup for the next i2c_msg
++ * clears this bit.
++ */
++ fsr &= ~FSR_TEND;
++ }
++ }
++ if (fsr & FSR_TDFE) {
++ while (msg->len && (IN32(id, I2CTFDR) < FIFO_SIZE)) {
++ OUT32(id, I2CRXTX, *data++);
++ msg->len--;
++ }
++
++ if (msg->len < 1) {
++ fier &= ~FIER_TXIE;
++ OUT32(id, I2CFIER, fier);
++ } else {
++ len = (msg->len >= FIFO_SIZE) ? 2 : 0;
++ OUT32(id, I2CFCR,
++ FCR_RFRST | ((len & 3) << 2));
++ }
++ }
++ }
++out:
++ if (id->status & IDS_DONE) {
++ OUT32(id, I2CMIER, 0);
++ OUT32(id, I2CFIER, 0);
++ id->msg = NULL;
++ complete(&id->xfer_done);
++ }
++ /* clear status flags and ctrl resumes work */
++ OUT32(id, I2CMSR, ~msr);
++ OUT32(id, I2CFSR, ~fsr);
++ OUT32(id, I2CSSR, 0);
++
++ return IRQ_HANDLED;
++}
++
++
++/* prepare and start a master receive operation */
++static void sh7760_i2c_mrecv(struct cami2c *id)
++{
++ int len;
++
++ id->flags |= IDF_RECV;
++
++ /* set the slave addr reg; otherwise rcv wont work! */
++ OUT32(id, I2CSAR, 0xfe);
++ OUT32(id, I2CMAR, (id->msg->addr << 1) | 1);
++
++ /* adjust rx fifo trigger */
++ if (id->msg->len >= FIFO_SIZE)
++ len = FIFO_SIZE - 1; /* trigger at fifo full */
++ else
++ len = id->msg->len - 1; /* trigger before all received */
++
++ OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
++ OUT32(id, I2CFCR, FCR_TFRST | ((len & 0xF) << 4));
++
++ OUT32(id, I2CMSR, 0);
++ OUT32(id, I2CMCR, MCR_MIE | MCR_ESG);
++ OUT32(id, I2CMIER, MIE_MNRE | MIE_MALE | MIE_MSTE | MIE_MATE);
++ OUT32(id, I2CFIER, FIER_RXIE);
++}
++
++/* prepare and start a master send operation */
++static void sh7760_i2c_msend(struct cami2c *id)
++{
++ int len;
++
++ id->flags |= IDF_SEND;
++
++ /* set the slave addr reg; otherwise xmit wont work! */
++ OUT32(id, I2CSAR, 0xfe);
++ OUT32(id, I2CMAR, (id->msg->addr << 1) | 0);
++
++ /* adjust tx fifo trigger */
++ if (id->msg->len >= FIFO_SIZE)
++ len = 2; /* trig: 2 bytes left in TX fifo */
++ else
++ len = 0; /* trig: 8 bytes left in TX fifo */
++
++ OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
++ OUT32(id, I2CFCR, FCR_RFRST | ((len & 3) << 2));
++
++ while (id->msg->len && IN32(id, I2CTFDR) < FIFO_SIZE) {
++ OUT32(id, I2CRXTX, *(id->msg->buf));
++ (id->msg->len)--;
++ (id->msg->buf)++;
++ }
++
++ OUT32(id, I2CMSR, 0);
++ OUT32(id, I2CMCR, MCR_MIE | MCR_ESG);
++ OUT32(id, I2CFSR, 0);
++ OUT32(id, I2CMIER, MIE_MNRE | MIE_MALE | MIE_MSTE | MIE_MATE);
++ OUT32(id, I2CFIER, FIER_TEIE | (id->msg->len ? FIER_TXIE : 0));
++}
++
++static inline int sh7760_i2c_busy_check(struct cami2c *id)
++{
++ return (IN32(id, I2CMCR) & MCR_FSDA);
++}
++
++static int sh7760_i2c_master_xfer(struct i2c_adapter *adap,
++ struct i2c_msg *msgs,
++ int num)
++{
++ struct cami2c *id = adap->algo_data;
++ int i, retr;
++
++ if (sh7760_i2c_busy_check(id)) {
++ dev_err(&adap->dev, "sh7760-i2c%d: bus busy!\n", adap->nr);
++ return -EBUSY;
++ }
++
++ i = 0;
++ while (i < num) {
++ retr = adap->retries;
++retry:
++ id->flags = ((i == (num-1)) ? IDF_STOP : 0);
++ id->status = 0;
++ id->msg = msgs;
++ init_completion(&id->xfer_done);
++
++ if (msgs->flags & I2C_M_RD)
++ sh7760_i2c_mrecv(id);
++ else
++ sh7760_i2c_msend(id);
++
++ wait_for_completion(&id->xfer_done);
++
++ if (id->status == 0) {
++ num = -EIO;
++ break;
++ }
++
++ if (id->status & IDS_NACK) {
++ /* wait a bit or i2c module stops working */
++ mdelay(1);
++ num = -EREMOTEIO;
++ break;
++ }
++
++ if (id->status & IDS_ARBLOST) {
++ if (retr--) {
++ mdelay(2);
++ goto retry;
++ }
++ num = -EREMOTEIO;
++ break;
++ }
++
++ msgs++;
++ i++;
++ }
++
++ id->msg = NULL;
++ id->flags = 0;
++ id->status = 0;
++
++ OUT32(id, I2CMCR, 0);
++ OUT32(id, I2CMSR, 0);
++ OUT32(id, I2CMIER, 0);
++ OUT32(id, I2CFIER, 0);
++
++ /* reset slave module registers too: master mode enables slave
++ * module for receive ops (ack, data). Without this reset,
++ * eternal bus activity might be reported after NACK / ARBLOST.
++ */
++ OUT32(id, I2CSCR, 0);
++ OUT32(id, I2CSAR, 0);
++ OUT32(id, I2CSSR, 0);
++
++ return num;
++}
++
++static u32 sh7760_i2c_func(struct i2c_adapter *adap)
++{
++ return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
++}
++
++static const struct i2c_algorithm sh7760_i2c_algo = {
++ .master_xfer = sh7760_i2c_master_xfer,
++ .functionality = sh7760_i2c_func,
++};
++
++/* calculate CCR register setting for a desired scl clock. SCL clock is
++ * derived from I2C module clock (iclk) which in turn is derived from
++ * peripheral module clock (mclk, usually around 33MHz):
++ * iclk = mclk/(CDF + 1). iclk must be < 20MHz.
++ * scl = iclk/(SCGD*8 + 20).
++ */
++static int __devinit calc_CCR(unsigned long scl_hz)
++{
++ struct clk *mclk;
++ unsigned long mck, m1, dff, odff, iclk;
++ signed char cdf, cdfm;
++ int scgd, scgdm, scgds;
++
++ mclk = clk_get(NULL, "module_clk");
++ if (IS_ERR(mclk)) {
++ return PTR_ERR(mclk);
++ } else {
++ mck = mclk->rate;
++ clk_put(mclk);
++ }
++
++ odff = scl_hz;
++ scgdm = cdfm = m1 = 0;
++ for (cdf = 3; cdf >= 0; cdf--) {
++ iclk = mck / (1 + cdf);
++ if (iclk >= 20000000)
++ continue;
++ scgds = ((iclk / scl_hz) - 20) >> 3;
++ for (scgd = scgds; (scgd < 63) && scgd <= scgds + 1; scgd++) {
++ m1 = iclk / (20 + (scgd << 3));
++ dff = abs(scl_hz - m1);
++ if (dff < odff) {
++ odff = dff;
++ cdfm = cdf;
++ scgdm = scgd;
++ }
++ }
++ }
++ /* fail if more than 25% off of requested SCL */
++ if (odff > (scl_hz >> 2))
++ return -EINVAL;
++
++ /* create a CCR register value */
++ return ((scgdm << 2) | cdfm);
++}
++
++static int __devinit sh7760_i2c_probe(struct platform_device *pdev)
++{
++ struct sh7760_i2c_platdata *pd;
++ struct resource *res;
++ struct cami2c *id;
++ int ret;
++
++ pd = pdev->dev.platform_data;
++ if (!pd) {
++ dev_err(&pdev->dev, "no platform_data!\n");
++ ret = -ENODEV;
++ goto out0;
++ }
++
++ id = kzalloc(sizeof(struct cami2c), GFP_KERNEL);
++ if (!id) {
++ dev_err(&pdev->dev, "no mem for private data\n");
++ ret = -ENOMEM;
++ goto out0;
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev, "no mmio resources\n");
++ ret = -ENODEV;
++ goto out1;
++ }
++
++ id->ioarea = request_mem_region(res->start, REGSIZE, pdev->name);
++ if (!id->ioarea) {
++ dev_err(&pdev->dev, "mmio already reserved\n");
++ ret = -EBUSY;
++ goto out1;
++ }
++
++ id->iobase = ioremap(res->start, REGSIZE);
++ if (!id->iobase) {
++ dev_err(&pdev->dev, "cannot ioremap\n");
++ ret = -ENODEV;
++ goto out2;
++ }
++
++ id->irq = platform_get_irq(pdev, 0);
++
++ id->adap.nr = pdev->id;
++ id->adap.algo = &sh7760_i2c_algo;
++ id->adap.class = I2C_CLASS_ALL;
++ id->adap.retries = 3;
++ id->adap.algo_data = id;
++ id->adap.dev.parent = &pdev->dev;
++ snprintf(id->adap.name, sizeof(id->adap.name),
++ "SH7760 I2C at %08lx", (unsigned long)res->start);
++
++ OUT32(id, I2CMCR, 0);
++ OUT32(id, I2CMSR, 0);
++ OUT32(id, I2CMIER, 0);
++ OUT32(id, I2CMAR, 0);
++ OUT32(id, I2CSIER, 0);
++ OUT32(id, I2CSAR, 0);
++ OUT32(id, I2CSCR, 0);
++ OUT32(id, I2CSSR, 0);
++ OUT32(id, I2CFIER, 0);
++ OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
++ OUT32(id, I2CFSR, 0);
++
++ ret = calc_CCR(pd->speed_khz * 1000);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "invalid SCL clock: %dkHz\n",
++ pd->speed_khz);
++ goto out3;
++ }
++ OUT32(id, I2CCCR, ret);
++
++ if (request_irq(id->irq, sh7760_i2c_irq, IRQF_DISABLED,
++ SH7760_I2C_DEVNAME, id)) {
++ dev_err(&pdev->dev, "cannot get irq %d\n", id->irq);
++ ret = -EBUSY;
++ goto out3;
++ }
++
++ ret = i2c_add_numbered_adapter(&id->adap);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "reg adap failed: %d\n", ret);
++ goto out4;
++ }
++
++ platform_set_drvdata(pdev, id);
++
++ dev_info(&pdev->dev, "%d kHz mmio %08x irq %d\n",
++ pd->speed_khz, res->start, id->irq);
++
++ return 0;
++
++out4:
++ free_irq(id->irq, id);
++out3:
++ iounmap(id->iobase);
++out2:
++ release_resource(id->ioarea);
++ kfree(id->ioarea);
++out1:
++ kfree(id);
++out0:
++ return ret;
++}
++
++static int __devexit sh7760_i2c_remove(struct platform_device *pdev)
++{
++ struct cami2c *id = platform_get_drvdata(pdev);
++
++ i2c_del_adapter(&id->adap);
++ free_irq(id->irq, id);
++ iounmap(id->iobase);
++ release_resource(id->ioarea);
++ kfree(id->ioarea);
++ kfree(id);
++ platform_set_drvdata(pdev, NULL);
++
++ return 0;
++}
++
++static struct platform_driver sh7760_i2c_drv = {
++ .driver = {
++ .name = SH7760_I2C_DEVNAME,
++ .owner = THIS_MODULE,
++ },
++ .probe = sh7760_i2c_probe,
++ .remove = __devexit_p(sh7760_i2c_remove),
++};
++
++static int __init sh7760_i2c_init(void)
++{
++ return platform_driver_register(&sh7760_i2c_drv);
++}
++
++static void __exit sh7760_i2c_exit(void)
++{
++ platform_driver_unregister(&sh7760_i2c_drv);
++}
++
++module_init(sh7760_i2c_init);
++module_exit(sh7760_i2c_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SH7760 I2C bus driver");
++MODULE_AUTHOR("Manuel Lauss <mano at roarinelk.homelinux.net>");
+diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
+new file mode 100644
+index 0000000..840e634
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-sh_mobile.c
+@@ -0,0 +1,500 @@
++/*
++ * SuperH Mobile I2C Controller
++ *
++ * Copyright (C) 2008 Magnus Damm
++ *
++ * Portions of the code based on out-of-tree driver i2c-sh7343.c
++ * Copyright (c) 2006 Carlos Munoz <carlos at kenati.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/i2c.h>
++#include <linux/err.h>
++#include <linux/clk.h>
++#include <linux/io.h>
++
++enum sh_mobile_i2c_op {
++ OP_START = 0,
++ OP_TX_ONLY,
++ OP_TX_STOP,
++ OP_TX_TO_RX,
++ OP_RX_ONLY,
++ OP_RX_STOP,
++};
++
++struct sh_mobile_i2c_data {
++ struct device *dev;
++ void __iomem *reg;
++ struct i2c_adapter adap;
++
++ struct clk *clk;
++ u_int8_t iccl;
++ u_int8_t icch;
++
++ spinlock_t lock;
++ wait_queue_head_t wait;
++ struct i2c_msg *msg;
++ int pos;
++ int sr;
++};
++
++#define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */
++
++/* Register offsets */
++#define ICDR(pd) (pd->reg + 0x00)
++#define ICCR(pd) (pd->reg + 0x04)
++#define ICSR(pd) (pd->reg + 0x08)
++#define ICIC(pd) (pd->reg + 0x0c)
++#define ICCL(pd) (pd->reg + 0x10)
++#define ICCH(pd) (pd->reg + 0x14)
++
++/* Register bits */
++#define ICCR_ICE 0x80
++#define ICCR_RACK 0x40
++#define ICCR_TRS 0x10
++#define ICCR_BBSY 0x04
++#define ICCR_SCP 0x01
++
++#define ICSR_SCLM 0x80
++#define ICSR_SDAM 0x40
++#define SW_DONE 0x20
++#define ICSR_BUSY 0x10
++#define ICSR_AL 0x08
++#define ICSR_TACK 0x04
++#define ICSR_WAIT 0x02
++#define ICSR_DTE 0x01
++
++#define ICIC_ALE 0x08
++#define ICIC_TACKE 0x04
++#define ICIC_WAITE 0x02
++#define ICIC_DTEE 0x01
++
++static void activate_ch(struct sh_mobile_i2c_data *pd)
++{
++ /* Make sure the clock is enabled */
++ clk_enable(pd->clk);
++
++ /* Enable channel and configure rx ack */
++ iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd));
++
++ /* Mask all interrupts */
++ iowrite8(0, ICIC(pd));
++
++ /* Set the clock */
++ iowrite8(pd->iccl, ICCL(pd));
++ iowrite8(pd->icch, ICCH(pd));
++}
++
++static void deactivate_ch(struct sh_mobile_i2c_data *pd)
++{
++ /* Clear/disable interrupts */
++ iowrite8(0, ICSR(pd));
++ iowrite8(0, ICIC(pd));
++
++ /* Disable channel */
++ iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd));
++
++ /* Disable clock */
++ clk_disable(pd->clk);
++}
++
++static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
++ enum sh_mobile_i2c_op op, unsigned char data)
++{
++ unsigned char ret = 0;
++ unsigned long flags;
++
++ dev_dbg(pd->dev, "op %d, data in 0x%02x\n", op, data);
++
++ spin_lock_irqsave(&pd->lock, flags);
++
++ switch (op) {
++ case OP_START:
++ iowrite8(0x94, ICCR(pd));
++ break;
++ case OP_TX_ONLY:
++ iowrite8(data, ICDR(pd));
++ break;
++ case OP_TX_STOP:
++ iowrite8(data, ICDR(pd));
++ iowrite8(0x90, ICCR(pd));
++ iowrite8(ICIC_ALE | ICIC_TACKE, ICIC(pd));
++ break;
++ case OP_TX_TO_RX:
++ iowrite8(data, ICDR(pd));
++ iowrite8(0x81, ICCR(pd));
++ break;
++ case OP_RX_ONLY:
++ ret = ioread8(ICDR(pd));
++ break;
++ case OP_RX_STOP:
++ ret = ioread8(ICDR(pd));
++ iowrite8(0xc0, ICCR(pd));
++ break;
++ }
++
++ spin_unlock_irqrestore(&pd->lock, flags);
++
++ dev_dbg(pd->dev, "op %d, data out 0x%02x\n", op, ret);
++ return ret;
++}
++
++static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
++{
++ struct platform_device *dev = dev_id;
++ struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
++ struct i2c_msg *msg = pd->msg;
++ unsigned char data, sr;
++ int wakeup = 0;
++
++ sr = ioread8(ICSR(pd));
++ pd->sr |= sr;
++
++ dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr,
++ (msg->flags & I2C_M_RD) ? "read" : "write",
++ pd->pos, msg->len);
++
++ if (sr & (ICSR_AL | ICSR_TACK)) {
++ iowrite8(0, ICIC(pd)); /* disable interrupts */
++ wakeup = 1;
++ goto do_wakeup;
++ }
++
++ if (pd->pos == msg->len) {
++ i2c_op(pd, OP_RX_ONLY, 0);
++ wakeup = 1;
++ goto do_wakeup;
++ }
++
++ if (pd->pos == -1) {
++ data = (msg->addr & 0x7f) << 1;
++ data |= (msg->flags & I2C_M_RD) ? 1 : 0;
++ } else
++ data = msg->buf[pd->pos];
++
++ if ((pd->pos == -1) || !(msg->flags & I2C_M_RD)) {
++ if (msg->flags & I2C_M_RD)
++ i2c_op(pd, OP_TX_TO_RX, data);
++ else if (pd->pos == (msg->len - 1)) {
++ i2c_op(pd, OP_TX_STOP, data);
++ wakeup = 1;
++ } else
++ i2c_op(pd, OP_TX_ONLY, data);
++ } else {
++ if (pd->pos == (msg->len - 1))
++ data = i2c_op(pd, OP_RX_STOP, 0);
++ else
++ data = i2c_op(pd, OP_RX_ONLY, 0);
++
++ msg->buf[pd->pos] = data;
++ }
++ pd->pos++;
++
++ do_wakeup:
++ if (wakeup) {
++ pd->sr |= SW_DONE;
++ wake_up(&pd->wait);
++ }
++
++ return IRQ_HANDLED;
++}
++
++static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg)
++{
++ /* Initialize channel registers */
++ iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd));
++
++ /* Enable channel and configure rx ack */
++ iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd));
++
++ /* Set the clock */
++ iowrite8(pd->iccl, ICCL(pd));
++ iowrite8(pd->icch, ICCH(pd));
++
++ pd->msg = usr_msg;
++ pd->pos = -1;
++ pd->sr = 0;
++
++ /* Enable all interrupts except wait */
++ iowrite8(ioread8(ICIC(pd)) | ICIC_ALE | ICIC_TACKE | ICIC_DTEE,
++ ICIC(pd));
++ return 0;
++}
++
++static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
++ struct i2c_msg *msgs,
++ int num)
++{
++ struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter);
++ struct i2c_msg *msg;
++ int err = 0;
++ u_int8_t val;
++ int i, k, retry_count;
++
++ activate_ch(pd);
++
++ /* Process all messages */
++ for (i = 0; i < num; i++) {
++ msg = &msgs[i];
++
++ err = start_ch(pd, msg);
++ if (err)
++ break;
++
++ i2c_op(pd, OP_START, 0);
++
++ /* The interrupt handler takes care of the rest... */
++ k = wait_event_timeout(pd->wait,
++ pd->sr & (ICSR_TACK | SW_DONE),
++ 5 * HZ);
++ if (!k)
++ dev_err(pd->dev, "Transfer request timed out\n");
++
++ retry_count = 10;
++again:
++ val = ioread8(ICSR(pd));
++
++ dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr);
++
++ if ((val | pd->sr) & (ICSR_TACK | ICSR_AL)) {
++ err = -EIO;
++ break;
++ }
++
++ /* the interrupt handler may wake us up before the
++ * transfer is finished, so poll the hardware
++ * until we're done.
++ */
++
++ if (!(!(val & ICSR_BUSY) && (val & ICSR_SCLM) &&
++ (val & ICSR_SDAM))) {
++ msleep(1);
++ if (retry_count--)
++ goto again;
++
++ err = -EIO;
++ dev_err(pd->dev, "Polling timed out\n");
++ break;
++ }
++ }
++
++ deactivate_ch(pd);
++
++ if (!err)
++ err = num;
++ return err;
++}
++
++static u32 sh_mobile_i2c_func(struct i2c_adapter *adapter)
++{
++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
++}
++
++static struct i2c_algorithm sh_mobile_i2c_algorithm = {
++ .functionality = sh_mobile_i2c_func,
++ .master_xfer = sh_mobile_i2c_xfer,
++};
++
++static void sh_mobile_i2c_setup_channel(struct platform_device *dev)
++{
++ struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
++ unsigned long peripheral_clk = clk_get_rate(pd->clk);
++ u_int32_t num;
++ u_int32_t denom;
++ u_int32_t tmp;
++
++ spin_lock_init(&pd->lock);
++ init_waitqueue_head(&pd->wait);
++
++ /* Calculate the value for iccl. From the data sheet:
++ * iccl = (p clock / transfer rate) * (L / (L + H))
++ * where L and H are the SCL low/high ratio (5/4 in this case).
++ * We also round off the result.
++ */
++ num = peripheral_clk * 5;
++ denom = NORMAL_SPEED * 9;
++ tmp = num * 10 / denom;
++ if (tmp % 10 >= 5)
++ pd->iccl = (u_int8_t)((num/denom) + 1);
++ else
++ pd->iccl = (u_int8_t)(num/denom);
++
++ /* Calculate the value for icch. From the data sheet:
++ icch = (p clock / transfer rate) * (H / (L + H)) */
++ num = peripheral_clk * 4;
++ tmp = num * 10 / denom;
++ if (tmp % 10 >= 5)
++ pd->icch = (u_int8_t)((num/denom) + 1);
++ else
++ pd->icch = (u_int8_t)(num/denom);
++}
++
++static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
++{
++ struct resource *res;
++ int ret = -ENXIO;
++ int q, m;
++ int k = 0;
++ int n = 0;
++
++ while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) {
++ for (n = res->start; hook && n <= res->end; n++) {
++ if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED,
++ dev->dev.bus_id, dev))
++ goto rollback;
++ }
++ k++;
++ }
++
++ if (hook)
++ return k > 0 ? 0 : -ENOENT;
++
++ k--;
++ ret = 0;
++
++ rollback:
++ for (q = k; k >= 0; k--) {
++ for (m = n; m >= res->start; m--)
++ free_irq(m, dev);
++
++ res = platform_get_resource(dev, IORESOURCE_IRQ, k - 1);
++ m = res->end;
++ }
++
++ return ret;
++}
++
++static int sh_mobile_i2c_probe(struct platform_device *dev)
++{
++ struct sh_mobile_i2c_data *pd;
++ struct i2c_adapter *adap;
++ struct resource *res;
++ int size;
++ int ret;
++
++ pd = kzalloc(sizeof(struct sh_mobile_i2c_data), GFP_KERNEL);
++ if (pd == NULL) {
++ dev_err(&dev->dev, "cannot allocate private data\n");
++ return -ENOMEM;
++ }
++
++ pd->clk = clk_get(&dev->dev, "peripheral_clk");
++ if (IS_ERR(pd->clk)) {
++ dev_err(&dev->dev, "cannot get peripheral clock\n");
++ ret = PTR_ERR(pd->clk);
++ goto err;
++ }
++
++ ret = sh_mobile_i2c_hook_irqs(dev, 1);
++ if (ret) {
++ dev_err(&dev->dev, "cannot request IRQ\n");
++ goto err_clk;
++ }
++
++ pd->dev = &dev->dev;
++ platform_set_drvdata(dev, pd);
++
++ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
++ if (res == NULL) {
++ dev_err(&dev->dev, "cannot find IO resource\n");
++ ret = -ENOENT;
++ goto err_irq;
++ }
++
++ size = (res->end - res->start) + 1;
++
++ pd->reg = ioremap(res->start, size);
++ if (pd->reg == NULL) {
++ dev_err(&dev->dev, "cannot map IO\n");
++ ret = -ENXIO;
++ goto err_irq;
++ }
++
++ /* setup the private data */
++ adap = &pd->adap;
++ i2c_set_adapdata(adap, pd);
++
++ adap->owner = THIS_MODULE;
++ adap->algo = &sh_mobile_i2c_algorithm;
++ adap->dev.parent = &dev->dev;
++ adap->retries = 5;
++ adap->nr = dev->id;
++
++ strlcpy(adap->name, dev->name, sizeof(adap->name));
++
++ sh_mobile_i2c_setup_channel(dev);
++
++ ret = i2c_add_numbered_adapter(adap);
++ if (ret < 0) {
++ dev_err(&dev->dev, "cannot add numbered adapter\n");
++ goto err_all;
++ }
++
++ return 0;
++
++ err_all:
++ iounmap(pd->reg);
++ err_irq:
++ sh_mobile_i2c_hook_irqs(dev, 0);
++ err_clk:
++ clk_put(pd->clk);
++ err:
++ kfree(pd);
++ return ret;
++}
++
++static int sh_mobile_i2c_remove(struct platform_device *dev)
++{
++ struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
++
++ i2c_del_adapter(&pd->adap);
++ iounmap(pd->reg);
++ sh_mobile_i2c_hook_irqs(dev, 0);
++ clk_put(pd->clk);
++ kfree(pd);
++ return 0;
++}
++
++static struct platform_driver sh_mobile_i2c_driver = {
++ .driver = {
++ .name = "i2c-sh_mobile",
++ .owner = THIS_MODULE,
++ },
++ .probe = sh_mobile_i2c_probe,
++ .remove = sh_mobile_i2c_remove,
++};
++
++static int __init sh_mobile_i2c_adap_init(void)
++{
++ return platform_driver_register(&sh_mobile_i2c_driver);
++}
++
++static void __exit sh_mobile_i2c_adap_exit(void)
++{
++ platform_driver_unregister(&sh_mobile_i2c_driver);
++}
++
++module_init(sh_mobile_i2c_adap_init);
++module_exit(sh_mobile_i2c_adap_exit);
++
++MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver");
++MODULE_AUTHOR("Magnus Damm");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c
+index 10af8d3..042fda2 100644
+--- a/drivers/i2c/busses/i2c-simtec.c
++++ b/drivers/i2c/busses/i2c-simtec.c
+@@ -159,6 +159,9 @@ static int simtec_i2c_remove(struct platform_device *dev)
-- 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");
- }
+ /* device driver */
- 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");
++/* 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-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
+index 283769c..9ca8f91 100644
+--- a/drivers/i2c/busses/i2c-sis5595.c
++++ b/drivers/i2c/busses/i2c-sis5595.c
+@@ -238,7 +238,7 @@ static int sis5595_transaction(struct i2c_adapter *adap)
+ dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
+ return -1;
+ } else {
+- dev_dbg(&adap->dev, "Successfull!\n");
++ dev_dbg(&adap->dev, "Successful!\n");
+ }
}
- 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");
+@@ -316,14 +316,8 @@ static s32 sis5595_access(struct i2c_adapter *adap, u16 addr,
+ }
+ size = (size == I2C_SMBUS_PROC_CALL) ? SIS5595_PROC_CALL : SIS5595_WORD_DATA;
+ break;
+-/*
+- case I2C_SMBUS_BLOCK_DATA:
+- printk(KERN_WARNING "sis5595.o: Block data not yet implemented!\n");
+- return -1;
+- break;
+-*/
+ default:
+- printk(KERN_WARNING "sis5595.o: Unsupported transaction %d\n", size);
++ dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
+ return -1;
}
-@@ -1704,7 +1603,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
+@@ -338,9 +332,7 @@ static s32 sis5595_access(struct i2c_adapter *adap, u16 addr,
- 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);
+ switch (size) {
+- case SIS5595_BYTE: /* Where is the result put? I assume here it is in
+- SMB_DATA but it might just as well be in the
+- SMB_CMD. No clue in the docs */
++ case SIS5595_BYTE:
+ case SIS5595_BYTE_DATA:
+ data->byte = sis5595_read(SMB_BYTE);
+ break;
+diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
+index 5fd734f..3765dd7 100644
+--- a/drivers/i2c/busses/i2c-sis630.c
++++ b/drivers/i2c/busses/i2c-sis630.c
+@@ -136,7 +136,7 @@ static int sis630_transaction_start(struct i2c_adapter *adap, int size, u8 *oldc
+ dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
+ return -1;
+ } else {
+- dev_dbg(&adap->dev, "Successfull!\n");
++ dev_dbg(&adap->dev, "Successful!\n");
+ }
+ }
- /* 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);
+diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c
+index c2a9f8c..d08eeec 100644
+--- a/drivers/i2c/busses/i2c-stub.c
++++ b/drivers/i2c/busses/i2c-stub.c
+@@ -33,7 +33,7 @@
+ static unsigned short chip_addr[MAX_CHIPS];
+ module_param_array(chip_addr, ushort, NULL, S_IRUGO);
+ MODULE_PARM_DESC(chip_addr,
+- "Chip addresses (up to 10, between 0x03 and 0x77)\n");
++ "Chip addresses (up to 10, between 0x03 and 0x77)");
+
+ struct stub_chip {
+ u8 pointer;
+diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c
+index 1b0cfd5..de9db49 100644
+--- a/drivers/i2c/busses/i2c-taos-evm.c
++++ b/drivers/i2c/busses/i2c-taos-evm.c
+@@ -51,7 +51,6 @@ struct taos_data {
+ /* TAOS TSL2550 EVM */
+ static struct i2c_board_info tsl2550_info = {
+ I2C_BOARD_INFO("tsl2550", 0x39),
+- .type = "tsl2550",
+ };
+
+ /* Instantiate i2c devices based on the adapter name */
+@@ -59,7 +58,7 @@ static struct i2c_client *taos_instantiate_device(struct i2c_adapter *adapter)
+ {
+ if (!strncmp(adapter->name, "TAOS TSL2550 EVM", 16)) {
+ dev_info(&adapter->dev, "Instantiating device %s at 0x%02x\n",
+- tsl2550_info.driver_name, tsl2550_info.addr);
++ tsl2550_info.type, tsl2550_info.addr);
+ return i2c_new_device(adapter, &tsl2550_info);
}
- }
--static void ahci_irq_clear(struct ata_port *ap)
--{
-- /* TODO */
--}
--
- static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
+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/ds1682.c b/drivers/i2c/chips/ds1682.c
+index 9e94542..23be4d4 100644
+--- a/drivers/i2c/chips/ds1682.c
++++ b/drivers/i2c/chips/ds1682.c
+@@ -200,7 +200,8 @@ static struct bin_attribute ds1682_eeprom_attr = {
+ /*
+ * Called when a ds1682 device is matched with this driver
+ */
+-static int ds1682_probe(struct i2c_client *client)
++static int ds1682_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
{
- struct ata_host *host = dev_instance;
-@@ -1854,6 +1748,15 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
+ int rc;
+
+@@ -234,12 +235,19 @@ static int ds1682_remove(struct i2c_client *client)
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 const struct i2c_device_id ds1682_id[] = {
++ { "ds1682", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, ds1682_id);
+
- 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);
+ static struct i2c_driver ds1682_driver = {
+ .driver = {
+ .name = "ds1682",
+ },
+ .probe = ds1682_probe,
+ .remove = ds1682_remove,
++ .id_table = ds1682_id,
+ };
+
+ static int __init ds1682_init(void)
+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;
}
-- /* 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);
+- check_state(isp, __FUNCTION__);
++ check_state(isp, __func__);
+ dump_regs(isp, "otg->isp1301");
}
- 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;
+@@ -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);
}
-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)
+- check_state(isp, __FUNCTION__);
++ check_state(isp, __func__);
+ return ret;
}
- 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
+@@ -837,7 +837,7 @@ static int otg_init(struct isp1301 *isp)
+ if (!otg_dev)
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 */
+- 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));
-@@ -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 */
- };
+- 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);
-@@ -162,7 +159,7 @@ struct piix_host_priv {
+ 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
- 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 },
+ 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);
-@@ -291,170 +289,37 @@ static struct pci_driver piix_pci_driver = {
- };
+- dump_regs(isp, __FUNCTION__);
++ dump_regs(isp, __func__);
- 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),
- };
+ return 0;
--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,
-+};
+@@ -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__);
-- .port_start = ata_port_start,
-+static struct ata_port_operations piix_vmw_ops = {
-+ .inherits = &piix_pata_ops,
-+ .bmdma_status = piix_vmw_bmdma_status,
- };
+ /* 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)
--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,
- };
+ 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
--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,
- };
+- dump_regs(isp, __FUNCTION__);
++ dump_regs(isp, __func__);
--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,
- };
+ #ifdef VERBOSE
+ mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
+diff --git a/drivers/i2c/chips/menelaus.c b/drivers/i2c/chips/menelaus.c
+index 2dea012..b36db17 100644
+--- a/drivers/i2c/chips/menelaus.c
++++ b/drivers/i2c/chips/menelaus.c
+@@ -1149,7 +1149,8 @@ static inline void menelaus_rtc_init(struct menelaus_chip *m)
- 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 i2c_driver menelaus_i2c_driver;
- 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,
- },
+-static int menelaus_probe(struct i2c_client *client)
++static int menelaus_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct menelaus_chip *menelaus;
+ int rev = 0, val;
+@@ -1242,12 +1243,19 @@ static int __exit menelaus_remove(struct i2c_client *client)
+ return 0;
+ }
-- [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,
++static const struct i2c_device_id menelaus_id[] = {
++ { "menelaus", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, menelaus_id);
++
+ static struct i2c_driver menelaus_i2c_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
},
+ .probe = menelaus_probe,
+ .remove = __exit_p(menelaus_remove),
++ .id_table = menelaus_id,
+ };
-- [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[] = {
+ static int __init menelaus_init(void)
+diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
+index 4154a91..8594968 100644
+--- a/drivers/i2c/chips/tps65010.c
++++ b/drivers/i2c/chips/tps65010.c
+@@ -30,9 +30,13 @@
+ #include <linux/debugfs.h>
+ #include <linux/seq_file.h>
+ #include <linux/mutex.h>
++#include <linux/platform_device.h>
- [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,
- },
+ #include <linux/i2c/tps65010.h>
-- [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,
- },
++#include <asm/gpio.h>
++
++
+ /*-------------------------------------------------------------------------*/
-- [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[] = {
+ #define DRIVER_VERSION "2 May 2005"
+@@ -60,7 +64,6 @@ static struct i2c_driver tps65010_driver;
+ * as part of board setup by a bootloader.
+ */
+ enum tps_model {
+- TPS_UNKNOWN = 0,
+ TPS65010,
+ TPS65011,
+ TPS65012,
+@@ -84,7 +87,9 @@ struct tps65010 {
+ u8 chgstatus, regstatus, chgconf;
+ u8 nmask1, nmask2;
- [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, }
+- /* not currently tracking GPIO state */
++ u8 outmask;
++ struct gpio_chip chip;
++ struct platform_device *leds;
};
-@@ -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;
- }
+ #define POWER_POLL_DELAY msecs_to_jiffies(5000)
+@@ -449,26 +454,89 @@ static irqreturn_t tps65010_irq(int irq, void *_tps)
--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;
++/* 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));
+ }
+
- /* 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;
++ /* REVISIT we *could* report LED1/nPG and LED2 state ... */
++ return 0;
++}
++
++
++/*-------------------------------------------------------------------------*/
++
+ static struct tps65010 *the_tps;
- /* 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,
- }
+ static int __exit tps65010_remove(struct i2c_client *client)
+ {
+ struct tps65010 *tps = i2c_get_clientdata(client);
++ struct tps65010_board *board = client->dev.platform_data;
- 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);
++ 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);
+ flush_scheduled_work();
+ debugfs_remove(tps->file);
+ kfree(tps);
++ i2c_set_clientdata(client, NULL);
+ the_tps = NULL;
+ return 0;
}
- 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)
+-static int tps65010_probe(struct i2c_client *client)
++static int tps65010_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
{
- 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);
+ struct tps65010 *tps;
+ int status;
++ struct tps65010_board *board = client->dev.platform_data;
- 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
- }
+ if (the_tps) {
+ dev_dbg(&client->dev, "only one tps6501x chip allowed\n");
+@@ -485,20 +553,7 @@ static int tps65010_probe(struct i2c_client *client)
+ mutex_init(&tps->lock);
+ INIT_DELAYED_WORK(&tps->work, tps65010_work);
+ tps->client = client;
+-
+- if (strcmp(client->name, "tps65010") == 0)
+- tps->model = TPS65010;
+- else if (strcmp(client->name, "tps65011") == 0)
+- tps->model = TPS65011;
+- else if (strcmp(client->name, "tps65012") == 0)
+- tps->model = TPS65012;
+- else if (strcmp(client->name, "tps65013") == 0)
+- tps->model = TPS65013;
+- else {
+- dev_warn(&client->dev, "unknown chip '%s'\n", client->name);
+- status = -ENODEV;
+- goto fail1;
+- }
++ tps->model = id->driver_data;
- 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;
- }
+ /* the IRQ is active low, but many gpio lines can't support that
+ * so this driver uses falling-edge triggers instead.
+@@ -527,9 +582,6 @@ static int tps65010_probe(struct i2c_client *client)
+ case TPS65012:
+ tps->por = 1;
+ break;
+- case TPS_UNKNOWN:
+- printk(KERN_WARNING "%s: unknown TPS chip\n", DRIVER_NAME);
+- break;
+ /* else CHGCONFIG.POR is replaced by AUA, enabling a WAIT mode */
}
- }
-diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
-index be95fdb..51b7d2f 100644
---- a/drivers/ata/libata-core.c
-+++ b/drivers/ata/libata-core.c
-@@ -46,7 +46,6 @@
- #include <linux/init.h>
- #include <linux/list.h>
- #include <linux/mm.h>
--#include <linux/highmem.h>
- #include <linux/spinlock.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
-@@ -62,7 +61,6 @@
- #include <scsi/scsi_cmnd.h>
- #include <scsi/scsi_host.h>
- #include <linux/libata.h>
--#include <asm/semaphore.h>
- #include <asm/byteorder.h>
- #include <linux/cdrom.h>
+ tps->chgconf = i2c_smbus_read_byte_data(client, TPS_CHGCONFIG);
+@@ -548,6 +600,7 @@ static int tps65010_probe(struct i2c_client *client)
+ i2c_smbus_read_byte_data(client, TPS_DEFGPIO),
+ i2c_smbus_read_byte_data(client, TPS_MASK3));
-@@ -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 };
++ i2c_set_clientdata(client, tps);
+ the_tps = tps;
-+const struct ata_port_operations ata_base_port_ops = {
-+ .prereset = ata_std_prereset,
-+ .postreset = ata_std_postreset,
-+ .error_handler = ata_std_error_handler,
-+};
+ #if defined(CONFIG_USB_GADGET) && !defined(CONFIG_USB_OTG)
+@@ -577,18 +630,60 @@ static int tps65010_probe(struct i2c_client *client)
+
+ tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL,
+ tps, DEBUG_FOPS);
+
-+const struct ata_port_operations sata_port_ops = {
-+ .inherits = &ata_base_port_ops,
++ /* optionally register GPIOs */
++ if (board && board->base > 0) {
++ tps->outmask = board->outmask;
+
-+ .qc_defer = ata_std_qc_defer,
-+ .hardreset = sata_std_hardreset,
-+};
++ tps->chip.label = client->name;
+
- 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)
++ 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);
+ return status;
}
- /**
-- * 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 const struct i2c_device_id tps65010_id[] = {
++ { "tps65010", TPS65010 },
++ { "tps65011", TPS65011 },
++ { "tps65012", TPS65012 },
++ { "tps65013", TPS65013 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, tps65010_id);
++
+ static struct i2c_driver tps65010_driver = {
+ .driver = {
+ .name = "tps65010",
+ },
+ .probe = tps65010_probe,
+ .remove = __exit_p(tps65010_remove),
++ .id_table = tps65010_id,
+ };
--static u64 ata_tf_to_lba48(struct ata_taskfile *tf)
-+u64 ata_tf_to_lba48(const struct ata_taskfile *tf)
- {
- u64 sectors = 0;
+ /*-------------------------------------------------------------------------*/
+diff --git a/drivers/i2c/chips/tsl2550.c b/drivers/i2c/chips/tsl2550.c
+index a10fd27..1a9cc13 100644
+--- a/drivers/i2c/chips/tsl2550.c
++++ b/drivers/i2c/chips/tsl2550.c
+@@ -364,7 +364,8 @@ static int tsl2550_init_client(struct i2c_client *client)
+ */
-@@ -1304,10 +1202,10 @@ static u64 ata_tf_to_lba48(struct ata_taskfile *tf)
- sectors |= (tf->lbam & 0xff) << 8;
- sectors |= (tf->lbal & 0xff);
+ static struct i2c_driver tsl2550_driver;
+-static int __devinit tsl2550_probe(struct i2c_client *client)
++static int __devinit tsl2550_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct tsl2550_data *data;
+@@ -451,6 +452,12 @@ static int tsl2550_resume(struct i2c_client *client)
-- return ++sectors;
-+ return sectors;
- }
+ #endif /* CONFIG_PM */
--static u64 ata_tf_to_lba(struct ata_taskfile *tf)
-+u64 ata_tf_to_lba(const struct ata_taskfile *tf)
- {
- u64 sectors = 0;
++static const struct i2c_device_id tsl2550_id[] = {
++ { "tsl2550", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, tsl2550_id);
++
+ static struct i2c_driver tsl2550_driver = {
+ .driver = {
+ .name = TSL2550_DRV_NAME,
+@@ -460,6 +467,7 @@ static struct i2c_driver tsl2550_driver = {
+ .resume = tsl2550_resume,
+ .probe = tsl2550_probe,
+ .remove = __devexit_p(tsl2550_remove),
++ .id_table = tsl2550_id,
+ };
-@@ -1316,7 +1214,7 @@ static u64 ata_tf_to_lba(struct ata_taskfile *tf)
- sectors |= (tf->lbam & 0xff) << 8;
- sectors |= (tf->lbal & 0xff);
+ static int __init tsl2550_init(void)
+diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
+index 8b645c6..26384da 100644
+--- a/drivers/i2c/i2c-core.c
++++ b/drivers/i2c/i2c-core.c
+@@ -35,8 +35,8 @@
+ #include <linux/completion.h>
+ #include <linux/hardirq.h>
+ #include <linux/irqflags.h>
++#include <linux/semaphore.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
-- return ++sectors;
-+ return sectors;
- }
+ #include "i2c-core.h"
- /**
-@@ -1361,9 +1259,9 @@ static int ata_read_native_max_address(struct ata_device *dev, u64 *max_sectors)
- }
+@@ -48,6 +48,17 @@ static DEFINE_IDR(i2c_adapter_idr);
- 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)
++static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
++ const struct i2c_client *client)
++{
++ while (id->name[0]) {
++ if (strcmp(client->name, id->name) == 0)
++ return id;
++ id++;
++ }
++ return NULL;
++}
++
+ static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
- ap->port_task_data = data;
+ struct i2c_client *client = to_i2c_client(dev);
+@@ -59,6 +70,10 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
+ if (!is_newstyle_driver(driver))
+ return 0;
-@@ -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__);
++ /* match on an id table if there is one */
++ if (driver->id_table)
++ return i2c_match_id(driver->id_table, client) != NULL;
++
+ /* new style drivers use the same kind of driver matching policy
+ * as platform devices or SPI: compare device and driver IDs.
+ */
+@@ -73,11 +88,17 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
+ struct i2c_client *client = to_i2c_client(dev);
+
+ /* by definition, legacy drivers can't hotplug */
+- if (dev->driver || !client->driver_name)
++ if (dev->driver)
+ return 0;
-- ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
- retry:
- ata_tf_init(dev, &tf);
+- if (add_uevent_var(env, "MODALIAS=%s", client->driver_name))
+- return -ENOMEM;
++ if (client->driver_name[0]) {
++ if (add_uevent_var(env, "MODALIAS=%s", client->driver_name))
++ return -ENOMEM;
++ } else {
++ if (add_uevent_var(env, "MODALIAS=%s%s",
++ I2C_MODULE_PREFIX, client->name))
++ return -ENOMEM;
++ }
+ dev_dbg(dev, "uevent\n");
+ return 0;
+ }
+@@ -90,13 +111,19 @@ static int i2c_device_probe(struct device *dev)
+ {
+ struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_driver *driver = to_i2c_driver(dev->driver);
++ const struct i2c_device_id *id;
+ int status;
-@@ -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;
+ if (!driver->probe)
+ return -ENODEV;
+ client->driver = driver;
+ dev_dbg(dev, "probe\n");
+- status = driver->probe(client);
++
++ if (driver->id_table)
++ id = i2c_match_id(driver->id_table, client);
++ else
++ id = NULL;
++ status = driver->probe(client, id);
+ if (status)
+ client->driver = NULL;
+ return status;
+@@ -179,9 +206,9 @@ static ssize_t show_client_name(struct device *dev, struct device_attribute *att
+ static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+ struct i2c_client *client = to_i2c_client(dev);
+- return client->driver_name
++ return client->driver_name[0]
+ ? sprintf(buf, "%s\n", client->driver_name)
+- : 0;
++ : sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name);
+ }
-@@ -2558,9 +2371,6 @@ int ata_dev_configure(struct ata_device *dev)
- }
- }
+ static struct device_attribute i2c_dev_attrs[] = {
+@@ -300,15 +327,21 @@ void i2c_unregister_device(struct i2c_client *client)
+ EXPORT_SYMBOL_GPL(i2c_unregister_device);
-- 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)
+-static int dummy_nop(struct i2c_client *client)
++static int dummy_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ return 0;
++}
++
++static int dummy_remove(struct i2c_client *client)
{
- u32 sstatus, scontrol, tmp;
+ return 0;
+ }
-@@ -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;
+ static struct i2c_driver dummy_driver = {
+ .driver.name = "dummy",
+- .probe = dummy_nop,
+- .remove = dummy_nop,
++ .probe = dummy_probe,
++ .remove = dummy_remove,
+ };
-@@ -3321,16 +3131,21 @@ static int ata_dev_set_mode(struct ata_device *dev)
- if (rc)
- return rc;
+ /**
+@@ -1506,7 +1539,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);
+ }
-- /* 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;
+-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;
+ }
- /* 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)
- }
++
++ 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;
- /**
-- * 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;
--}
+ 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;
-
--/**
-- * 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;
+- /* 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;
-
-- if (time_before(until, deadline))
-- deadline = until;
+- rdwr_pa = (struct i2c_msg *)
+- kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
+- GFP_KERNEL);
-
-- /* 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);
+- if (rdwr_pa == NULL) return -ENOMEM;
-
-- /* 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 (copy_from_user(rdwr_pa, rdwr_arg.msgs,
+- rdwr_arg.nmsgs * sizeof(struct i2c_msg))) {
+- kfree(rdwr_pa);
+- return -EFAULT;
+- }
-
-- if (status != 0xff || time_after(jiffies, deadline))
-- return;
+- data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
+- if (data_ptrs == NULL) {
+- kfree(rdwr_pa);
+- return -ENOMEM;
+- }
-
-- msleep(50);
+- 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;
- }
-- }
--}
-
--/**
-- * 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)
- }
- }
+- 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);
--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;
+ 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;
- }
-- }
-
-- /* if device 1 was found in ata_devchk, wait for register
-- * access briefly, then wait for BSY to clear.
-- */
-- if (dev1) {
-- int i;
+- /* Note that command values are always valid! */
-
-- ap->ops->dev_select(ap, 1);
+- 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);
-
-- /* 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;
+- 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);
-
-- nsect = ioread8(ioaddr->nsect_addr);
-- lbal = ioread8(ioaddr->lbal_addr);
-- if ((nsect == 1) && (lbal == 1))
-- break;
-- msleep(50); /* give drive a breather */
+- 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..f702f91 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.
-
-- rc = ata_wait_ready(ap, deadline);
-- if (rc) {
-- if (rc != -ENODEV)
-- return rc;
-- ret = rc;
-- }
-- }
+- Normally, just say N here; you will then use the new driver for all
+- 4 interfaces.
-
-- /* 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);
+ 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.)
-
-- return ret;
--}
+ 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
+@@ -886,40 +862,6 @@ config BLK_DEV_IDE_BAST
+ Say Y here if you want to support the onboard IDE channels on the
+ Simtec BAST or the Thorcom VR1000
+
+-config ETRAX_IDE
+- tristate "ETRAX IDE support"
+- depends on CRIS && BROKEN
+- select BLK_DEV_IDEDMA
+- help
+- Enables the ETRAX IDE driver.
-
--static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
-- unsigned long deadline)
--{
-- struct ata_ioports *ioaddr = &ap->ioaddr;
+- You can't use parallel ports or SCSI ports at the same time.
-
-- DPRINTK("ata%u: bus reset via SRST\n", ap->print_id);
+-config ETRAX_IDE_DELAY
+- int "Delay for drives to regain consciousness"
+- depends on ETRAX_IDE && ETRAX_ARCH_V10
+- default 15
+- help
+- Number of seconds to wait for IDE drives to spin up after an IDE
+- reset.
-
-- /* 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);
+-choice
+- prompt "IDE reset pin"
+- depends on ETRAX_IDE && ETRAX_ARCH_V10
+- default ETRAX_IDE_PB7_RESET
-
-- /* wait a while before checking status */
-- ata_wait_after_reset(ap, deadline);
+-config ETRAX_IDE_PB7_RESET
+- bool "Port_PB_Bit_7"
+- help
+- IDE reset on pin 7 on port B
-
-- /* 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;
+-config ETRAX_IDE_G27_RESET
+- bool "Port_G_Bit_27"
+- help
+- IDE reset on pin 27 on port G
-
-- return ata_bus_post_reset(ap, devmask, deadline);
--}
+-endchoice
-
- /**
-- * 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.
- */
+ config IDE_H8300
+ tristate "H8300 IDE support"
+ depends on H8300
+@@ -1049,19 +991,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 +1056,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
-
--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))
+ 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 +1071,16 @@ config BLK_DEV_HD_ONLY
+ for systems with only older MFM/RLL/ESDI drives. Choosing the old
+ driver can save 13 KB or so of kernel memory.
+
++ If you want to use this driver together with the new one you have
++ to use "hda=noprobe hdb=noprobe" kernel parameters to prevent the new
++ driver from probing the primary interface.
++
+ If you are unsure, then just choose the Enhanced IDE/MFM/RLL driver
+ instead of this one. For more detailed information, read the
+ Disk-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ config BLK_DEV_HD
+- def_bool BLK_DEV_HD_IDE || BLK_DEV_HD_ONLY
++ def_bool BLK_DEV_HD_ONLY
+
+ endif # IDE
+diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
+index a4a4323..f94b679 100644
+--- a/drivers/ide/Makefile
++++ b/drivers/ide/Makefile
+@@ -35,10 +35,10 @@ ifeq ($(CONFIG_BLK_DEV_CMD640), y)
+ obj-y += cmd640-core.o
+ endif
+
+-obj-$(CONFIG_BLK_DEV_IDE) += cris/ ppc/
+-obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o
++obj-$(CONFIG_BLK_DEV_IDE) += ppc/
+ 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..713cef2 100644
+--- a/drivers/ide/arm/bast-ide.c
++++ b/drivers/ide/arm/bast-ide.c
+@@ -21,6 +21,8 @@
+ #include <asm/arch/bast-map.h>
+ #include <asm/arch/bast-irq.h>
+
++#define DRV_NAME "bast-ide"
++
+ static int __init bastide_register(unsigned int base, unsigned int aux, int irq)
{
-- 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);
+ ide_hwif_t *hwif;
+@@ -33,27 +35,23 @@ static int __init bastide_register(unsigned int base, unsigned int aux, int irq)
+ base += BAST_IDE_CS;
+ aux += BAST_IDE_CS;
-- /* 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);
+- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+- hw.io_ports[i] = (unsigned long)base;
++ for (i = 0; i <= 7; i++) {
++ hw.io_ports_array[i] = (unsigned long)base;
+ base += 0x20;
+ }
+
+- hw.io_ports[IDE_CONTROL_OFFSET] = aux + (6 * 0x20);
++ hw.io_ports.ctl_addr = 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_init_port_data(hwif, i);
-
-- DPRINTK("EXIT\n");
-+ return ata_wait_ready(link, deadline, check_ready);
- }
++ ide_init_port_data(hwif, i);
+ ide_init_port_hw(hwif, &hw);
+- hwif->quirkproc = NULL;
++ hwif->port_ops = NULL;
- /**
-@@ -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)
+ idx[0] = i;
+
+@@ -64,6 +62,8 @@ out:
+
+ static int __init bastide_init(void)
{
-- u32 scontrol;
-+ u32 scontrol, serror;
- int rc;
++ unsigned long base = BAST_VA_IDEPRI + BAST_IDE_CS;
++
+ /* we can treat the VR1000 and the BAST the same */
- 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);
+ if (!(machine_is_bast() || machine_is_vr1000()))
+@@ -71,6 +71,11 @@ static int __init bastide_init(void)
-- return sata_link_debounce(link, params, deadline);
-+ if ((rc = sata_link_debounce(link, params, deadline)))
-+ return rc;
+ 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;
++ }
+
-+ /* 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;
+ 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..0614569 100644
+--- a/drivers/ide/arm/icside.c
++++ b/drivers/ide/arm/icside.c
+@@ -191,6 +191,10 @@ static void icside_maskproc(ide_drive_t *drive, int mask)
+ local_irq_restore(flags);
+ }
+
++static const struct ide_port_ops icside_v6_no_dma_port_ops = {
++ .maskproc = icside_maskproc,
++};
+
-+ spin_lock_irqsave(link->ap->lock, flags);
-+ link->eh_info.serror = 0;
-+ spin_unlock_irqrestore(link->ap->lock, flags);
-+ rc = 0;
-+ }
-+ return rc;
+ #ifdef CONFIG_BLK_DEV_IDEDMA_ICS
+ /*
+ * SG-DMA support.
+@@ -266,6 +270,11 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
+ ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
}
- /**
-@@ -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;
++static const struct ide_port_ops icside_v6_port_ops = {
++ .set_dma_mode = icside_set_dma_mode,
++ .maskproc = icside_maskproc,
++};
++
+ static void icside_dma_host_set(ide_drive_t *drive, int on)
+ {
+ }
+@@ -375,48 +384,57 @@ static void icside_dma_lost_irq(ide_drive_t *drive)
+ printk(KERN_ERR "%s: IRQ lost\n", drive->name);
+ }
-- /* 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;
+-static void icside_dma_init(ide_hwif_t *hwif)
++static int icside_dma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
+ {
+ hwif->dmatable_cpu = NULL;
+ hwif->dmatable_dma = 0;
+- hwif->set_dma_mode = icside_set_dma_mode;
-
- /* 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;
+- hwif->dma_host_set = icside_dma_host_set;
+- hwif->dma_setup = icside_dma_setup;
+- hwif->dma_exec_cmd = icside_dma_exec_cmd;
+- hwif->dma_start = icside_dma_start;
+- hwif->ide_dma_end = icside_dma_end;
+- hwif->ide_dma_test_irq = icside_dma_test_irq;
+- hwif->dma_timeout = icside_dma_timeout;
+- hwif->dma_lost_irq = icside_dma_lost_irq;
++
++ return 0;
}
++
++static const struct ide_dma_ops icside_v6_dma_ops = {
++ .dma_host_set = icside_dma_host_set,
++ .dma_setup = icside_dma_setup,
++ .dma_exec_cmd = icside_dma_exec_cmd,
++ .dma_start = icside_dma_start,
++ .dma_end = icside_dma_end,
++ .dma_test_irq = icside_dma_test_irq,
++ .dma_timeout = icside_dma_timeout,
++ .dma_lost_irq = icside_dma_lost_irq,
++};
+ #else
+-#define icside_dma_init(hwif) (0)
++#define icside_v6_dma_ops NULL
+ #endif
- /**
-- * 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 *))
++static int icside_dma_off_init(ide_hwif_t *hwif, const struct ide_port_info *d)
++{
++ return -EOPNOTSUPP;
++}
++
+ static ide_hwif_t *
+ icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *ec)
{
- u32 scontrol;
- int rc;
+ unsigned long port = (unsigned long)base + info->dataoffset;
+ ide_hwif_t *hwif;
- DPRINTK("ENTER\n");
+- hwif = ide_find_port(port);
++ hwif = ide_find_port();
+ if (hwif) {
+- int i;
+-
+ /*
+ * Ensure we're using MMIO
+ */
+ default_hwif_mmiops(hwif);
+- hwif->mmio = 1;
-+ 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,
+- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+- hwif->io_ports[i] = port;
+- port += 1 << info->stepping;
+- }
+- hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)base + info->ctrloffset;
++ hwif->io_ports.data_addr = port;
++ hwif->io_ports.error_addr = port + (1 << info->stepping);
++ hwif->io_ports.nsect_addr = port + (2 << info->stepping);
++ hwif->io_ports.lbal_addr = port + (3 << info->stepping);
++ hwif->io_ports.lbam_addr = port + (4 << info->stepping);
++ hwif->io_ports.lbah_addr = port + (5 << info->stepping);
++ hwif->io_ports.device_addr = port + (6 << info->stepping);
++ hwif->io_ports.status_addr = port + (7 << info->stepping);
++ hwif->io_ports.ctl_addr =
++ (unsigned long)base + info->ctrloffset;
+ hwif->irq = ec->irq;
+- hwif->noprobe = 0;
+ hwif->chipset = ide_acorn;
+ hwif->gendev.parent = &ec->dev;
+ hwif->dev = &ec->dev;
+@@ -462,9 +480,10 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
+ }
+
+ static const struct ide_port_info icside_v6_port_info __initdata = {
+- .host_flags = IDE_HFLAG_SERIALIZE |
+- IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
+- IDE_HFLAG_NO_AUTOTUNE,
++ .init_dma = icside_dma_off_init,
++ .port_ops = &icside_v6_no_dma_port_ops,
++ .dma_ops = &icside_v6_dma_ops,
++ .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO,
+ .mwdma_mask = ATA_MWDMA2,
+ .swdma_mask = ATA_SWDMA2,
+ };
+@@ -526,21 +545,19 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
+ state->hwif[0] = hwif;
+ state->hwif[1] = mate;
+
+- hwif->maskproc = icside_maskproc;
+ hwif->hwif_data = state;
+ hwif->config_data = (unsigned long)ioc_base;
+ hwif->select_data = sel;
+
+- mate->maskproc = icside_maskproc;
+ mate->hwif_data = state;
+ mate->config_data = (unsigned long)ioc_base;
+ mate->select_data = sel | 1;
+
+ if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) {
+- icside_dma_init(hwif);
+- icside_dma_init(mate);
+- } else
+- d.mwdma_mask = d.swdma_mask = 0;
++ d.init_dma = icside_dma_init;
++ d.port_ops = &icside_v6_port_ops;
++ d.dma_ops = NULL;
++ }
- /* 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;
+ idx[0] = hwif->index;
+ idx[1] = mate->index;
+diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c
+index be9ff73..4263ffd 100644
+--- a/drivers/ide/arm/ide_arm.c
++++ b/drivers/ide/arm/ide_arm.c
+@@ -14,6 +14,8 @@
+ #include <asm/mach-types.h>
+ #include <asm/irq.h>
+
++#define DRV_NAME "ide_arm"
+
-+ 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;
+ #ifdef CONFIG_ARCH_CLPS7500
+ # include <asm/arch/hardware.h>
+ #
+@@ -28,13 +30,27 @@ static int __init ide_arm_init(void)
+ {
+ ide_hwif_t *hwif;
+ hw_regs_t hw;
++ unsigned long base = IDE_ARM_IO, ctl = IDE_ARM_IO + 0x206;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+
++ if (!request_region(base, 8, DRV_NAME)) {
++ printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
++ DRV_NAME, base, base + 7);
++ return -EBUSY;
++ }
+
-+ 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;
++ if (!request_region(ctl, 1, DRV_NAME)) {
++ printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
++ DRV_NAME, ctl);
++ release_region(base, 8);
++ return -EBUSY;
+ }
+
-+ 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;
+ memset(&hw, 0, sizeof(hw));
+- ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206);
++ ide_std_init_ports(&hw, base, ctl);
+ 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..96378eb 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;
+@@ -317,17 +317,32 @@ static u8 __devinit palm_bk3710_cable_detect(ide_hwif_t *hwif)
+ return ATA_CBL_PATA80;
}
- /**
-- * 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)
+-static void __devinit palm_bk3710_init_hwif(ide_hwif_t *hwif)
++static int __devinit palm_bk3710_init_dma(ide_hwif_t *hwif,
++ const struct ide_port_info *d)
{
-- struct ata_port *ap = link->ap;
- const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
-+ bool online;
- int rc;
+- hwif->set_pio_mode = palm_bk3710_set_pio_mode;
+- hwif->set_dma_mode = palm_bk3710_set_dma_mode;
++ unsigned long base =
++ hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET;
-- 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;
+- hwif->cable_detect = palm_bk3710_cable_detect;
++ printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name);
++
++ if (ide_allocate_dma_engine(hwif))
++ return -1;
++
++ ide_setup_dma(hwif, base);
++
++ return 0;
}
- /**
-@@ -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");
++static const struct ide_port_ops palm_bk3710_ports_ops = {
++ .set_pio_mode = palm_bk3710_set_pio_mode,
++ .set_dma_mode = palm_bk3710_set_dma_mode,
++ .cable_detect = palm_bk3710_cable_detect,
++};
++
+ static const struct ide_port_info __devinitdata palm_bk3710_port_info = {
+- .init_hwif = palm_bk3710_init_hwif,
+- .host_flags = IDE_HFLAG_NO_DMA, /* hack (no PCI) */
++ .init_dma = palm_bk3710_init_dma,
++ .port_ops = &palm_bk3710_ports_ops,
++ .host_flags = IDE_HFLAG_MMIO,
+ .pio_mask = ATA_PIO4,
+ .udma_mask = ATA_UDMA4, /* (input clk 99MHz) */
+ .mwdma_mask = ATA_MWDMA2,
+@@ -372,30 +387,24 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev)
+
+ pribase = mem->start + IDE_PALM_ATA_PRI_REG_OFFSET;
+ for (i = 0; i < IDE_NR_PORTS - 2; i++)
+- hw.io_ports[i] = pribase + i;
+- hw.io_ports[IDE_CONTROL_OFFSET] = mem->start +
++ hw.io_ports_array[i] = pribase + i;
++ hw.io_ports.ctl_addr = mem->start +
+ IDE_PALM_ATA_PRI_CTL_OFFSET;
+ hw.irq = irq->start;
+ hw.chipset = ide_palm3710;
- /* print link status */
- sata_print_link_status(link);
+- hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++ hwif = ide_find_port();
+ if (hwif == NULL)
+ goto out;
-- /* 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;
-- }
+ i = hwif->index;
+
+- if (hwif->present)
+- ide_unregister(i, 0, 0);
+- else if (!hwif->hold)
+- ide_init_port_data(hwif, i);
-
-- /* set up device control */
-- if (ap->ioaddr.ctl_addr)
-- iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
++ ide_init_port_data(hwif, i);
+ ide_init_port_hw(hwif, &hw);
+
+ hwif->mmio = 1;
+ default_hwif_mmiops(hwif);
+
+- ide_setup_dma(hwif, mem->start);
-
- DPRINTK("EXIT\n");
- }
+ idx[0] = i;
-@@ -4528,6 +4014,53 @@ static int ata_is_40wire(struct ata_device *dev)
+ ide_device_add(idx, &palm_bk3710_port_info);
+@@ -409,9 +418,13 @@ out:
+ return -ENODEV;
}
- /**
-+ * 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;
-+}
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:palm_bk3710");
+
-+/**
- * 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)
+ 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..1747b23 100644
+--- a/drivers/ide/arm/rapide.c
++++ b/drivers/ide/arm/rapide.c
+@@ -17,11 +17,11 @@ static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base,
+ unsigned long port = (unsigned long)base;
+ int i;
+
+- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+- hw->io_ports[i] = port;
++ for (i = 0; i <= 7; i++) {
++ hw->io_ports_array[i] = port;
+ port += sz;
+ }
+- hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
++ hw->io_ports.ctl_addr = (unsigned long)ctrl;
+ hw->irq = irq;
}
- /**
-- * 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)
+@@ -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);
+@@ -53,7 +53,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
+
+ ide_init_port_hw(hwif, &hw);
+
+- hwif->mmio = 1;
++ hwif->host_flags = IDE_HFLAG_MMIO;
+ default_hwif_mmiops(hwif);
+
+ idx[0] = hwif->index;
+@@ -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);
+
+ ecard_release_resources(ec);
+ }
+diff --git a/drivers/ide/cris/Makefile b/drivers/ide/cris/Makefile
+deleted file mode 100644
+index 20b9596..0000000
+--- a/drivers/ide/cris/Makefile
++++ /dev/null
+@@ -1,3 +0,0 @@
+-EXTRA_CFLAGS += -Idrivers/ide
+-
+-obj-$(CONFIG_IDE_ETRAX) += ide-cris.o
+diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
+deleted file mode 100644
+index c8ffbaf..0000000
+--- a/drivers/ide/cris/ide-cris.c
++++ /dev/null
+@@ -1,1071 +0,0 @@
+-/*
+- * Etrax specific IDE functions, like init and PIO-mode setting etc.
+- * Almost the entire ide.c is used for the rest of the Etrax ATA driver.
+- * Copyright (c) 2000-2005 Axis Communications AB
- *
+- * Authors: Bjorn Wesen (initial version)
+- * Mikael Starvik (crisv32 port)
- */
--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;
+-/* Regarding DMA:
+- *
+- * There are two forms of DMA - "DMA handshaking" between the interface and the drive,
+- * and DMA between the memory and the interface. We can ALWAYS use the latter, since it's
+- * something built-in in the Etrax. However only some drives support the DMA-mode handshaking
+- * on the ATA-bus. The normal PC driver and Triton interface disables memory-if DMA when the
+- * device can't do DMA handshaking for some stupid reason. We don't need to do that.
+- */
-
-- /* 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);
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+-#include <linux/interrupt.h>
+-#include <linux/delay.h>
+-#include <linux/blkdev.h>
+-#include <linux/hdreg.h>
+-#include <linux/ide.h>
+-#include <linux/init.h>
-
-- while (sg_len) {
-- offset = addr & 0xffff;
-- len = sg_len;
-- if ((offset + sg_len) > 0x10000)
-- len = 0x10000 - offset;
+-#include <asm/io.h>
+-#include <asm/dma.h>
-
-- 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);
+-/* number of DMA descriptors */
+-#define MAX_DMA_DESCRS 64
-
-- pi++;
-- sg_len -= len;
-- addr += len;
-- }
-- }
+-/* number of times to retry busy-flags when reading/writing IDE-registers
+- * this can't be too high because a hung harddisk might cause the watchdog
+- * to trigger (sometimes INB and OUTB are called with irq's disabled)
+- */
+-
+-#define IDE_REGISTER_TIMEOUT 300
+-
+-#define LOWDB(x)
+-#define D(x)
+-
+-enum /* Transfer types */
+-{
+- TYPE_PIO,
+- TYPE_DMA,
+- TYPE_UDMA
+-};
+-
+-/* CRISv32 specifics */
+-#ifdef CONFIG_ETRAX_ARCH_V32
+-#include <asm/arch/hwregs/ata_defs.h>
+-#include <asm/arch/hwregs/dma_defs.h>
+-#include <asm/arch/hwregs/dma.h>
+-#include <asm/arch/pinmux.h>
+-
+-#define ATA_UDMA2_CYC 2
+-#define ATA_UDMA2_DVS 3
+-#define ATA_UDMA1_CYC 2
+-#define ATA_UDMA1_DVS 4
+-#define ATA_UDMA0_CYC 4
+-#define ATA_UDMA0_DVS 6
+-#define ATA_DMA2_STROBE 7
+-#define ATA_DMA2_HOLD 1
+-#define ATA_DMA1_STROBE 8
+-#define ATA_DMA1_HOLD 3
+-#define ATA_DMA0_STROBE 25
+-#define ATA_DMA0_HOLD 19
+-#define ATA_PIO4_SETUP 3
+-#define ATA_PIO4_STROBE 7
+-#define ATA_PIO4_HOLD 1
+-#define ATA_PIO3_SETUP 3
+-#define ATA_PIO3_STROBE 9
+-#define ATA_PIO3_HOLD 3
+-#define ATA_PIO2_SETUP 3
+-#define ATA_PIO2_STROBE 13
+-#define ATA_PIO2_HOLD 5
+-#define ATA_PIO1_SETUP 5
+-#define ATA_PIO1_STROBE 23
+-#define ATA_PIO1_HOLD 9
+-#define ATA_PIO0_SETUP 9
+-#define ATA_PIO0_STROBE 39
+-#define ATA_PIO0_HOLD 9
-
-- ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+-int
+-cris_ide_ack_intr(ide_hwif_t* hwif)
+-{
+- reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2,
+- int, hwif->io_ports[0]);
+- REG_WR_INT(ata, regi_ata, rw_ack_intr, 1 << ctrl2.sel);
+- return 1;
-}
-
--/**
-- * 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)
+-static inline int
+-cris_ide_busy(void)
-{
-- struct ata_port *ap = qc->ap;
-- struct scatterlist *sg;
-- unsigned int si, pi;
+- reg_ata_rs_stat_data stat_data;
+- stat_data = REG_RD(ata, regi_ata, rs_stat_data);
+- return stat_data.busy;
+-}
-
-- pi = 0;
-- for_each_sg(qc->sg, sg, qc->n_elem, si) {
-- u32 addr, offset;
-- u32 sg_len, len, blen;
+-static inline int
+-cris_ide_ready(void)
+-{
+- return !cris_ide_busy();
+-}
-
-- /* 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);
+-static inline int
+-cris_ide_data_available(unsigned short* data)
+-{
+- reg_ata_rs_stat_data stat_data;
+- stat_data = REG_RD(ata, regi_ata, rs_stat_data);
+- *data = stat_data.data;
+- return stat_data.dav;
+-}
-
-- while (sg_len) {
-- offset = addr & 0xffff;
-- len = sg_len;
-- if ((offset + sg_len) > 0x10000)
-- len = 0x10000 - offset;
+-static void
+-cris_ide_write_command(unsigned long command)
+-{
+- REG_WR_INT(ata, regi_ata, rw_ctrl2, command); /* write data to the drive's register */
+-}
-
-- 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);
+-static void
+-cris_ide_set_speed(int type, int setup, int strobe, int hold)
+-{
+- reg_ata_rw_ctrl0 ctrl0 = REG_RD(ata, regi_ata, rw_ctrl0);
+- reg_ata_rw_ctrl1 ctrl1 = REG_RD(ata, regi_ata, rw_ctrl1);
-
-- pi++;
-- sg_len -= len;
-- addr += len;
-- }
+- if (type == TYPE_PIO) {
+- ctrl0.pio_setup = setup;
+- ctrl0.pio_strb = strobe;
+- ctrl0.pio_hold = hold;
+- } else if (type == TYPE_DMA) {
+- ctrl0.dma_strb = strobe;
+- ctrl0.dma_hold = hold;
+- } else if (type == TYPE_UDMA) {
+- ctrl1.udma_tcyc = setup;
+- ctrl1.udma_tdvs = strobe;
- }
--
-- ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+- REG_WR(ata, regi_ata, rw_ctrl0, ctrl0);
+- REG_WR(ata, regi_ata, rw_ctrl1, ctrl1);
-}
-
--/**
- * 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)
+-static unsigned long
+-cris_ide_base_address(int bus)
-{
-- if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-- return;
--
-- ata_fill_sg(qc);
+- reg_ata_rw_ctrl2 ctrl2 = {0};
+- ctrl2.sel = bus;
+- return REG_TYPE_CONV(int, reg_ata_rw_ctrl2, ctrl2);
-}
-
--/**
-- * 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)
+-static unsigned long
+-cris_ide_reg_addr(unsigned long addr, int cs0, int cs1)
-{
-- if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-- return;
+- reg_ata_rw_ctrl2 ctrl2 = {0};
+- ctrl2.addr = addr;
+- ctrl2.cs1 = cs1;
+- ctrl2.cs0 = cs0;
+- return REG_TYPE_CONV(int, reg_ata_rw_ctrl2, ctrl2);
+-}
-
-- ata_fill_sg_dumb(qc);
+-static __init void
+-cris_ide_reset(unsigned val)
+-{
+- reg_ata_rw_ctrl0 ctrl0 = {0};
+- ctrl0.rst = val ? regk_ata_active : regk_ata_inactive;
+- REG_WR(ata, regi_ata, rw_ctrl0, ctrl0);
-}
-
- 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)
+-static __init void
+-cris_ide_init(void)
-{
-- struct ata_port *ap = dev->link->ap;
-- void __iomem *data_addr = ap->ioaddr.data_addr;
-- unsigned int words = buflen >> 1;
+- reg_ata_rw_ctrl0 ctrl0 = {0};
+- reg_ata_rw_intr_mask intr_mask = {0};
-
-- /* Transfer multiple of 2 bytes */
-- if (rw == READ)
-- ioread16_rep(data_addr, buf, words);
-- else
-- iowrite16_rep(data_addr, buf, words);
+- ctrl0.en = regk_ata_yes;
+- REG_WR(ata, regi_ata, rw_ctrl0, ctrl0);
-
-- /* Transfer trailing 1 byte, if any. */
-- if (unlikely(buflen & 0x01)) {
-- __le16 align_buf[1] = { 0 };
-- unsigned char *trailing_buf = buf + buflen - 1;
+- intr_mask.bus0 = regk_ata_yes;
+- intr_mask.bus1 = regk_ata_yes;
+- intr_mask.bus2 = regk_ata_yes;
+- intr_mask.bus3 = regk_ata_yes;
-
-- 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++;
-- }
+- REG_WR(ata, regi_ata, rw_intr_mask, intr_mask);
-
-- return words << 1;
--}
+- crisv32_request_dma(2, "ETRAX FS built-in ATA", DMA_VERBOSE_ON_ERROR, 0, dma_ata);
+- crisv32_request_dma(3, "ETRAX FS built-in ATA", DMA_VERBOSE_ON_ERROR, 0, dma_ata);
-
--/**
-- * 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;
+- crisv32_pinmux_alloc_fixed(pinmux_ata);
+- crisv32_pinmux_alloc_fixed(pinmux_ata0);
+- crisv32_pinmux_alloc_fixed(pinmux_ata1);
+- crisv32_pinmux_alloc_fixed(pinmux_ata2);
+- crisv32_pinmux_alloc_fixed(pinmux_ata3);
-
-- local_irq_save(flags);
-- consumed = ata_data_xfer(dev, buf, buflen, rw);
-- local_irq_restore(flags);
+- DMA_RESET(regi_dma2);
+- DMA_ENABLE(regi_dma2);
+- DMA_RESET(regi_dma3);
+- DMA_ENABLE(regi_dma3);
-
-- return consumed;
+- DMA_WR_CMD (regi_dma2, regk_dma_set_w_size2);
+- DMA_WR_CMD (regi_dma3, regk_dma_set_w_size2);
-}
-
+-static dma_descr_context mycontext __attribute__ ((__aligned__(32)));
-
--/**
-- * 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.
-- */
+-#define cris_dma_descr_type dma_descr_data
+-#define cris_pio_read regk_ata_rd
+-#define cris_ultra_mask 0x7
+-#define MAX_DESCR_SIZE 0xffffffffUL
-
--static void ata_pio_sector(struct ata_queued_cmd *qc)
+-static unsigned long
+-cris_ide_get_reg(unsigned long reg)
-{
-- int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
-- struct ata_port *ap = qc->ap;
-- struct page *page;
-- unsigned int offset;
-- unsigned char *buf;
+- return (reg & 0x0e000000) >> 25;
+-}
-
-- if (qc->curbytes == qc->nbytes - qc->sect_size)
-- ap->hsm_task_state = HSM_ST_LAST;
+-static void
+-cris_ide_fill_descriptor(cris_dma_descr_type *d, void* buf, unsigned int len, int last)
+-{
+- d->buf = (char*)virt_to_phys(buf);
+- d->after = d->buf + len;
+- d->eol = last;
+-}
-
-- page = sg_page(qc->cursg);
-- offset = qc->cursg->offset + qc->cursg_ofs;
+-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);
+- reg_ata_rw_trf_cnt trf_cnt = {0};
-
-- /* get the current page and offset */
-- page = nth_page(page, (offset >> PAGE_SHIFT));
-- offset %= PAGE_SIZE;
+- mycontext.saved_data = (dma_descr_data*)virt_to_phys(d);
+- mycontext.saved_data_buf = d->buf;
+- /* start the dma channel */
+- DMA_START_CONTEXT(dir ? regi_dma3 : regi_dma2, virt_to_phys(&mycontext));
+-
+- /* initiate a multi word dma read using PIO handshaking */
+- trf_cnt.cnt = len >> 1;
+- /* Due to a "feature" the transfer count has to be one extra word for UDMA. */
+- if (type == TYPE_UDMA)
+- trf_cnt.cnt++;
+- REG_WR(ata, regi_ata, rw_trf_cnt, trf_cnt);
+-
+- ctrl2.rw = dir ? regk_ata_rd : regk_ata_wr;
+- ctrl2.trf_mode = regk_ata_dma;
+- ctrl2.hsh = type == TYPE_PIO ? regk_ata_pio :
+- type == TYPE_DMA ? regk_ata_dma : regk_ata_udma;
+- ctrl2.multi = regk_ata_yes;
+- ctrl2.dma_size = regk_ata_word;
+- REG_WR(ata, regi_ata, rw_ctrl2, ctrl2);
+-}
-
-- DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+-static void
+-cris_ide_wait_dma(int dir)
+-{
+- reg_dma_rw_stat status;
+- do
+- {
+- status = REG_RD(dma, dir ? regi_dma3 : regi_dma2, rw_stat);
+- } while(status.list_state != regk_dma_data_at_eol);
+-}
-
-- if (PageHighMem(page)) {
-- unsigned long flags;
+-static int cris_dma_test_irq(ide_drive_t *drive)
+-{
+- 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);
+- return intr & (1 << ctrl2.sel) ? 1 : 0;
+-}
-
-- /* FIXME: use a bounce buffer */
-- local_irq_save(flags);
-- buf = kmap_atomic(page, KM_IRQ0);
+-static void cris_ide_initialize_dma(int dir)
+-{
+-}
-
-- /* do the actual data transfer */
-- ap->ops->data_xfer(qc->dev, buf + offset, qc->sect_size, do_write);
+-#else
+-/* CRISv10 specifics */
+-#include <asm/arch/svinto.h>
+-#include <asm/arch/io_interface_mux.h>
+-
+-/* PIO timing (in R_ATA_CONFIG)
+- *
+- * _____________________________
+- * ADDRESS : ________/
+- *
+- * _______________
+- * DIOR : ____________/ \__________
+- *
+- * _______________
+- * DATA : XXXXXXXXXXXXXXXX_______________XXXXXXXX
+- *
+- *
+- * DIOR is unbuffered while address and data is buffered.
+- * This creates two problems:
+- * 1. The DIOR pulse is to early (because it is unbuffered)
+- * 2. The rise time of DIOR is long
+- *
+- * There are at least three different plausible solutions
+- * 1. Use a pad capable of larger currents in Etrax
+- * 2. Use an external buffer
+- * 3. Make the strobe pulse longer
+- *
+- * Some of the strobe timings below are modified to compensate
+- * for this. This implies a slight performance decrease.
+- *
+- * THIS SHOULD NEVER BE CHANGED!
+- *
+- * TODO: Is this true for the latest LX boards still ?
+- */
+-
+-#define ATA_UDMA2_CYC 0 /* No UDMA supported, just to make it compile. */
+-#define ATA_UDMA2_DVS 0
+-#define ATA_UDMA1_CYC 0
+-#define ATA_UDMA1_DVS 0
+-#define ATA_UDMA0_CYC 0
+-#define ATA_UDMA0_DVS 0
+-#define ATA_DMA2_STROBE 4
+-#define ATA_DMA2_HOLD 0
+-#define ATA_DMA1_STROBE 4
+-#define ATA_DMA1_HOLD 1
+-#define ATA_DMA0_STROBE 12
+-#define ATA_DMA0_HOLD 9
+-#define ATA_PIO4_SETUP 1
+-#define ATA_PIO4_STROBE 5
+-#define ATA_PIO4_HOLD 0
+-#define ATA_PIO3_SETUP 1
+-#define ATA_PIO3_STROBE 5
+-#define ATA_PIO3_HOLD 1
+-#define ATA_PIO2_SETUP 1
+-#define ATA_PIO2_STROBE 6
+-#define ATA_PIO2_HOLD 2
+-#define ATA_PIO1_SETUP 2
+-#define ATA_PIO1_STROBE 11
+-#define ATA_PIO1_HOLD 4
+-#define ATA_PIO0_SETUP 4
+-#define ATA_PIO0_STROBE 19
+-#define ATA_PIO0_HOLD 4
-
-- 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);
-- }
+-int
+-cris_ide_ack_intr(ide_hwif_t* hwif)
+-{
+- return 1;
+-}
-
-- qc->curbytes += qc->sect_size;
-- qc->cursg_ofs += qc->sect_size;
+-static inline int
+-cris_ide_busy(void)
+-{
+- return *R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy) ;
+-}
-
-- if (qc->cursg_ofs == qc->cursg->length) {
-- qc->cursg = sg_next(qc->cursg);
-- qc->cursg_ofs = 0;
-- }
+-static inline int
+-cris_ide_ready(void)
+-{
+- return *R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, tr_rdy) ;
-}
-
--/**
-- * 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 inline int
+-cris_ide_data_available(unsigned short* data)
+-{
+- unsigned long status = *R_ATA_STATUS_DATA;
+- *data = (unsigned short)status;
+- return status & IO_MASK(R_ATA_STATUS_DATA, dav);
+-}
-
--static void ata_pio_sectors(struct ata_queued_cmd *qc)
+-static void
+-cris_ide_write_command(unsigned long command)
-{
-- if (is_multi_taskfile(&qc->tf)) {
-- /* READ/WRITE MULTIPLE */
-- unsigned int nsect;
+- *R_ATA_CTRL_DATA = command;
+-}
-
-- WARN_ON(qc->dev->multi_count == 0);
+-static void
+-cris_ide_set_speed(int type, int setup, int strobe, int hold)
+-{
+- static int pio_setup = ATA_PIO4_SETUP;
+- static int pio_strobe = ATA_PIO4_STROBE;
+- static int pio_hold = ATA_PIO4_HOLD;
+- static int dma_strobe = ATA_DMA2_STROBE;
+- static int dma_hold = ATA_DMA2_HOLD;
+-
+- if (type == TYPE_PIO) {
+- pio_setup = setup;
+- pio_strobe = strobe;
+- pio_hold = hold;
+- } else if (type == TYPE_DMA) {
+- dma_strobe = strobe;
+- dma_hold = hold;
+- }
+- *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable, 1 ) |
+- IO_FIELD( R_ATA_CONFIG, dma_strobe, dma_strobe ) |
+- IO_FIELD( R_ATA_CONFIG, dma_hold, dma_hold ) |
+- IO_FIELD( R_ATA_CONFIG, pio_setup, pio_setup ) |
+- IO_FIELD( R_ATA_CONFIG, pio_strobe, pio_strobe ) |
+- IO_FIELD( R_ATA_CONFIG, pio_hold, pio_hold ) );
+-}
-
-- nsect = min((qc->nbytes - qc->curbytes) / qc->sect_size,
-- qc->dev->multi_count);
-- while (nsect--)
-- ata_pio_sector(qc);
-- } else
-- ata_pio_sector(qc);
+-static unsigned long
+-cris_ide_base_address(int bus)
+-{
+- return IO_FIELD(R_ATA_CTRL_DATA, sel, bus);
+-}
-
-- ata_altstatus(qc->ap); /* flush */
+-static unsigned long
+-cris_ide_reg_addr(unsigned long addr, int cs0, int cs1)
+-{
+- return IO_FIELD(R_ATA_CTRL_DATA, addr, addr) |
+- IO_FIELD(R_ATA_CTRL_DATA, cs0, cs0) |
+- IO_FIELD(R_ATA_CTRL_DATA, cs1, cs1);
-}
-
--/**
-- * 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 __init void
+-cris_ide_reset(unsigned val)
+-{
+-#ifdef CONFIG_ETRAX_IDE_G27_RESET
+- REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, 27, val);
+-#endif
+-#ifdef CONFIG_ETRAX_IDE_PB7_RESET
+- port_pb_dir_shadow = port_pb_dir_shadow |
+- IO_STATE(R_PORT_PB_DIR, dir7, output);
+- *R_PORT_PB_DIR = port_pb_dir_shadow;
+- REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, 7, val);
+-#endif
+-}
-
--static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
+-static __init void
+-cris_ide_init(void)
-{
-- /* send SCSI cdb */
-- DPRINTK("send cdb\n");
-- WARN_ON(qc->dev->cdb_len < 12);
+- volatile unsigned int dummy;
-
-- ap->ops->data_xfer(qc->dev, qc->cdb, qc->dev->cdb_len, 1);
-- ata_altstatus(ap); /* flush */
+- *R_ATA_CTRL_DATA = 0;
+- *R_ATA_TRANSFER_CNT = 0;
+- *R_ATA_CONFIG = 0;
-
-- 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;
+- if (cris_request_io_interface(if_ata, "ETRAX100LX IDE")) {
+- printk(KERN_CRIT "ide: Failed to get IO interface\n");
+- return;
+- } else if (cris_request_dma(ATA_TX_DMA_NBR,
+- "ETRAX100LX IDE TX",
+- DMA_VERBOSE_ON_ERROR,
+- dma_ata)) {
+- cris_free_io_interface(if_ata);
+- printk(KERN_CRIT "ide: Failed to get Tx DMA channel\n");
+- return;
+- } else if (cris_request_dma(ATA_RX_DMA_NBR,
+- "ETRAX100LX IDE RX",
+- DMA_VERBOSE_ON_ERROR,
+- dma_ata)) {
+- cris_free_dma(ATA_TX_DMA_NBR, "ETRAX100LX IDE Tx");
+- cris_free_io_interface(if_ata);
+- printk(KERN_CRIT "ide: Failed to get Rx DMA channel\n");
+- return;
- }
--}
-
--/**
-- * __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;
+- /* make a dummy read to set the ata controller in a proper state */
+- dummy = *R_ATA_STATUS_DATA;
-
--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;
-- }
+- *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable, 1 ));
+- *R_ATA_CTRL_DATA = ( IO_STATE( R_ATA_CTRL_DATA, rw, read) |
+- IO_FIELD( R_ATA_CTRL_DATA, addr, 1 ) );
-
-- page = sg_page(sg);
-- offset = sg->offset + qc->cursg_ofs;
+- while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); /* wait for busy flag*/
-
-- /* get the current page and offset */
-- page = nth_page(page, (offset >> PAGE_SHIFT));
-- offset %= PAGE_SIZE;
+- *R_IRQ_MASK0_SET = ( IO_STATE( R_IRQ_MASK0_SET, ata_irq0, set ) |
+- IO_STATE( R_IRQ_MASK0_SET, ata_irq1, set ) |
+- IO_STATE( R_IRQ_MASK0_SET, ata_irq2, set ) |
+- IO_STATE( R_IRQ_MASK0_SET, ata_irq3, set ) );
-
-- /* don't overrun current sg */
-- count = min(sg->length - qc->cursg_ofs, bytes);
+- /* reset the dma channels we will use */
-
-- /* don't cross page boundaries */
-- count = min(count, (unsigned int)PAGE_SIZE - offset);
+- RESET_DMA(ATA_TX_DMA_NBR);
+- RESET_DMA(ATA_RX_DMA_NBR);
+- WAIT_DMA(ATA_TX_DMA_NBR);
+- WAIT_DMA(ATA_RX_DMA_NBR);
+-}
-
-- DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+-#define cris_dma_descr_type etrax_dma_descr
+-#define cris_pio_read IO_STATE(R_ATA_CTRL_DATA, rw, read)
+-#define cris_ultra_mask 0x0
+-#define MAX_DESCR_SIZE 0x10000UL
-
-- if (PageHighMem(page)) {
-- unsigned long flags;
+-static unsigned long
+-cris_ide_get_reg(unsigned long reg)
+-{
+- return (reg & 0x0e000000) >> 25;
+-}
-
-- /* FIXME: use bounce buffer */
-- local_irq_save(flags);
-- buf = kmap_atomic(page, KM_IRQ0);
+-static void
+-cris_ide_fill_descriptor(cris_dma_descr_type *d, void* buf, unsigned int len, int last)
+-{
+- d->buf = virt_to_phys(buf);
+- d->sw_len = len == MAX_DESCR_SIZE ? 0 : len;
+- if (last)
+- d->ctrl |= d_eol;
+-}
-
-- /* do the actual data transfer */
-- consumed = ap->ops->data_xfer(dev, buf + offset, count, rw);
+-static void cris_ide_start_dma(ide_drive_t *drive, cris_dma_descr_type *d, int dir, int type, int len)
+-{
+- unsigned long cmd;
+-
+- if (dir) {
+- /* need to do this before RX DMA due to a chip bug
+- * it is enough to just flush the part of the cache that
+- * corresponds to the buffers we start, but since HD transfers
+- * usually are more than 8 kB, it is easier to optimize for the
+- * normal case and just flush the entire cache. its the only
+- * way to be sure! (OB movie quote)
+- */
+- flush_etrax_cache();
+- *R_DMA_CH3_FIRST = virt_to_phys(d);
+- *R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, start);
-
-- kunmap_atomic(buf, KM_IRQ0);
-- local_irq_restore(flags);
- } else {
-- buf = page_address(page);
-- consumed = ap->ops->data_xfer(dev, buf + offset, count, rw);
+- *R_DMA_CH2_FIRST = virt_to_phys(d);
+- *R_DMA_CH2_CMD = IO_STATE(R_DMA_CH2_CMD, cmd, start);
- }
-
-- bytes -= min(bytes, consumed);
-- qc->curbytes += count;
-- qc->cursg_ofs += count;
+- /* initiate a multi word dma read using DMA handshaking */
-
-- if (qc->cursg_ofs == sg->length) {
-- qc->cursg = sg_next(qc->cursg);
-- qc->cursg_ofs = 0;
-- }
+- *R_ATA_TRANSFER_CNT =
+- IO_FIELD(R_ATA_TRANSFER_CNT, count, len >> 1);
-
-- /* consumed can be larger than count only for the last transfer */
-- WARN_ON(qc->cursg && count != consumed);
+- cmd = dir ? IO_STATE(R_ATA_CTRL_DATA, rw, read) : IO_STATE(R_ATA_CTRL_DATA, rw, write);
+- cmd |= type == TYPE_PIO ? IO_STATE(R_ATA_CTRL_DATA, handsh, pio) :
+- IO_STATE(R_ATA_CTRL_DATA, handsh, dma);
+- *R_ATA_CTRL_DATA =
+- cmd |
+- IO_FIELD(R_ATA_CTRL_DATA, data, IDE_DATA_REG) |
+- 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);
+-}
-
-- if (bytes)
-- goto next_sg;
-- return 0;
+-static void
+-cris_ide_wait_dma(int dir)
+-{
+- if (dir)
+- WAIT_DMA(ATA_RX_DMA_NBR);
+- else
+- WAIT_DMA(ATA_TX_DMA_NBR);
-}
-
--/**
-- * 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 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);
+- return intr & (1 << (bus + IO_BITNR(R_IRQ_MASK0_RD, ata_irq0))) ? 1 : 0;
+-}
-
--static void atapi_pio_bytes(struct ata_queued_cmd *qc)
+-
+-static void cris_ide_initialize_dma(int dir)
-{
-- 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;
+- if (dir)
+- {
+- RESET_DMA(ATA_RX_DMA_NBR); /* sometimes the DMA channel get stuck so we need to do this */
+- WAIT_DMA(ATA_RX_DMA_NBR);
+- }
+- else
+- {
+- RESET_DMA(ATA_TX_DMA_NBR); /* sometimes the DMA channel get stuck so we need to do this */
+- WAIT_DMA(ATA_TX_DMA_NBR);
+- }
+-}
-
-- /* 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;
+-#endif
-
-- /* shall be cleared to zero, indicating xfer of data */
-- if (unlikely(ireason & (1 << 0)))
-- goto atapi_check;
+-void
+-cris_ide_outw(unsigned short data, unsigned long reg) {
+- int timeleft;
-
-- /* make sure transfer direction matches expected */
-- i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0;
-- if (unlikely(do_write != i_write))
-- goto atapi_check;
+- LOWDB(printk("ow: data 0x%x, reg 0x%x\n", data, reg));
-
-- if (unlikely(!bytes))
-- goto atapi_check;
+- /* note the lack of handling any timeouts. we stop waiting, but we don't
+- * really notify anybody.
+- */
-
-- VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes);
+- timeleft = IDE_REGISTER_TIMEOUT;
+- /* wait for busy flag */
+- do {
+- timeleft--;
+- } while(timeleft && cris_ide_busy());
-
-- if (unlikely(__atapi_pio_bytes(qc, bytes)))
-- goto err_out;
-- ata_altstatus(ap); /* flush */
+- /*
+- * Fall through at a timeout, so the ongoing command will be
+- * aborted by the write below, which is expected to be a dummy
+- * command to the command register. This happens when a faulty
+- * drive times out on a command. See comment on timeout in
+- * INB.
+- */
+- if(!timeleft)
+- printk("ATA timeout reg 0x%lx := 0x%x\n", reg, data);
-
-- return;
+- cris_ide_write_command(reg|data); /* write data to the drive's register */
-
-- 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;
+- timeleft = IDE_REGISTER_TIMEOUT;
+- /* wait for transmitter ready */
+- do {
+- timeleft--;
+- } while(timeleft && !cris_ide_ready());
-}
-
--/**
-- * 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.
-- */
+-void
+-cris_ide_outb(unsigned char data, unsigned long reg)
+-{
+- cris_ide_outw(data, reg);
+-}
-
--static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc)
+-void
+-cris_ide_outbsync(ide_drive_t *drive, u8 addr, unsigned long port)
-{
-- if (qc->tf.flags & ATA_TFLAG_POLLING)
-- return 1;
+- cris_ide_outw(addr, port);
+-}
-
-- if (ap->hsm_task_state == HSM_ST_FIRST) {
-- if (qc->tf.protocol == ATA_PROT_PIO &&
-- (qc->tf.flags & ATA_TFLAG_WRITE))
-- return 1;
+-unsigned short
+-cris_ide_inw(unsigned long reg) {
+- int timeleft;
+- unsigned short val;
-
-- if (ata_is_atapi(qc->tf.protocol) &&
-- !(qc->dev->flags & ATA_DFLAG_CDB_INTR))
-- return 1;
+- timeleft = IDE_REGISTER_TIMEOUT;
+- /* wait for busy flag */
+- do {
+- timeleft--;
+- } while(timeleft && cris_ide_busy());
+-
+- if(!timeleft) {
+- /*
+- * If we're asked to read the status register, like for
+- * example when a command does not complete for an
+- * extended time, but the ATA interface is stuck in a
+- * busy state at the *ETRAX* ATA interface level (as has
+- * happened repeatedly with at least one bad disk), then
+- * the best thing to do is to pretend that we read
+- * "busy" in the status register, so the IDE driver will
+- * time-out, abort the ongoing command and perform a
+- * reset sequence. Note that the subsequent OUT_BYTE
+- * call will also timeout on busy, but as long as the
+- * write is still performed, everything will be fine.
+- */
+- if (cris_ide_get_reg(reg) == IDE_STATUS_OFFSET)
+- return BUSY_STAT;
+- else
+- /* For other rare cases we assume 0 is good enough. */
+- return 0;
- }
-
-- return 0;
+- cris_ide_write_command(reg | cris_pio_read);
+-
+- timeleft = IDE_REGISTER_TIMEOUT;
+- /* wait for available */
+- do {
+- timeleft--;
+- } while(timeleft && !cris_ide_data_available(&val));
+-
+- if(!timeleft)
+- return 0;
+-
+- LOWDB(printk("inb: 0x%x from reg 0x%x\n", val & 0xff, reg));
+-
+- return val;
-}
-
--/**
-- * 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)
+-unsigned char
+-cris_ide_inb(unsigned long reg)
-{
-- struct ata_port *ap = qc->ap;
-- unsigned long flags;
+- return (unsigned char)cris_ide_inw(reg);
+-}
-
-- if (ap->ops->error_handler) {
-- if (in_wq) {
-- spin_lock_irqsave(ap->lock, flags);
+-static int cris_dma_end (ide_drive_t *drive);
+-static int cris_dma_setup (ide_drive_t *drive);
+-static void cris_dma_exec_cmd (ide_drive_t *drive, u8 command);
+-static int cris_dma_test_irq(ide_drive_t *drive);
+-static void cris_dma_start(ide_drive_t *drive);
+-static void cris_ide_input_data (ide_drive_t *drive, void *, unsigned int);
+-static void cris_ide_output_data (ide_drive_t *drive, void *, unsigned int);
+-static void cris_atapi_input_bytes(ide_drive_t *drive, void *, unsigned int);
+-static void cris_atapi_output_bytes(ide_drive_t *drive, void *, unsigned int);
-
-- /* 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);
-- }
+-static void cris_dma_host_set(ide_drive_t *drive, int on)
+-{
+-}
-
-- 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);
+-static void cris_set_pio_mode(ide_drive_t *drive, const u8 pio)
+-{
+- int setup, strobe, hold;
+-
+- switch(pio)
+- {
+- case 0:
+- setup = ATA_PIO0_SETUP;
+- strobe = ATA_PIO0_STROBE;
+- hold = ATA_PIO0_HOLD;
+- break;
+- case 1:
+- setup = ATA_PIO1_SETUP;
+- strobe = ATA_PIO1_STROBE;
+- hold = ATA_PIO1_HOLD;
+- break;
+- case 2:
+- setup = ATA_PIO2_SETUP;
+- strobe = ATA_PIO2_STROBE;
+- hold = ATA_PIO2_HOLD;
+- break;
+- case 3:
+- setup = ATA_PIO3_SETUP;
+- strobe = ATA_PIO3_STROBE;
+- hold = ATA_PIO3_HOLD;
+- break;
+- case 4:
+- setup = ATA_PIO4_SETUP;
+- strobe = ATA_PIO4_STROBE;
+- hold = ATA_PIO4_HOLD;
+- break;
+- default:
+- return;
- }
+-
+- cris_ide_set_speed(TYPE_PIO, setup, strobe, hold);
-}
-
--/**
-- * 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)
+-static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed)
-{
-- unsigned long flags = 0;
-- int poll_next;
+- int cyc = 0, dvs = 0, strobe = 0, hold = 0;
-
-- WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
+- switch(speed)
+- {
+- case XFER_UDMA_0:
+- cyc = ATA_UDMA0_CYC;
+- dvs = ATA_UDMA0_DVS;
+- break;
+- case XFER_UDMA_1:
+- cyc = ATA_UDMA1_CYC;
+- dvs = ATA_UDMA1_DVS;
+- break;
+- case XFER_UDMA_2:
+- cyc = ATA_UDMA2_CYC;
+- dvs = ATA_UDMA2_DVS;
+- break;
+- case XFER_MW_DMA_0:
+- strobe = ATA_DMA0_STROBE;
+- hold = ATA_DMA0_HOLD;
+- break;
+- case XFER_MW_DMA_1:
+- strobe = ATA_DMA1_STROBE;
+- hold = ATA_DMA1_HOLD;
+- break;
+- case XFER_MW_DMA_2:
+- strobe = ATA_DMA2_STROBE;
+- hold = ATA_DMA2_HOLD;
+- break;
+- }
-
-- /* 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).
+- if (speed >= XFER_UDMA_0)
+- cris_ide_set_speed(TYPE_UDMA, cyc, dvs, 0);
+- else
+- cris_ide_set_speed(TYPE_DMA, 0, strobe, hold);
+-}
+-
+-static void __init cris_setup_ports(hw_regs_t *hw, unsigned long base)
+-{
+- int i;
+-
+- memset(hw, 0, sizeof(*hw));
+-
+- for (i = 0; i <= 7; i++)
+- hw->io_ports[i] = base + cris_ide_reg_addr(i, 0, 1);
+-
+- /*
+- * the IDE control register is at ATA address 6,
+- * with CS1 active instead of CS0
- */
-- WARN_ON(in_wq != ata_hsm_ok_in_wq(ap, qc));
+- hw->io_ports[IDE_CONTROL_OFFSET] = base + cris_ide_reg_addr(6, 1, 0);
-
--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);
+- hw->irq = ide_default_irq(0);
+- hw->ack_intr = cris_ide_ack_intr;
+-}
-
-- switch (ap->hsm_task_state) {
-- case HSM_ST_FIRST:
-- /* Send first data block or PACKET CDB */
+-static const struct ide_port_info cris_port_info __initdata = {
+- .chipset = ide_etrax100,
+- .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
+- IDE_HFLAG_NO_DMA, /* no SFF-style DMA */
+- .pio_mask = ATA_PIO4,
+- .udma_mask = cris_ultra_mask,
+- .mwdma_mask = ATA_MWDMA2,
+-};
-
-- /* 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);
+-static int __init init_e100_ide(void)
+-{
+- hw_regs_t hw;
+- int h;
+- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-
-- /* 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;
+- printk("ide: ETRAX FS built-in ATA DMA controller\n");
-
-- ap->hsm_task_state = HSM_ST_ERR;
-- goto fsm_start;
-- }
+- for (h = 0; h < 4; h++) {
+- ide_hwif_t *hwif = NULL;
-
-- /* 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;
-- }
-- }
+- cris_setup_ports(&hw, cris_ide_base_address(h));
-
-- /* 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);
+- hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+- if (hwif == NULL)
+- continue;
+- ide_init_port_data(hwif, hwif->index);
+- ide_init_port_hw(hwif, &hw);
+- hwif->mmio = 1;
+- hwif->set_pio_mode = &cris_set_pio_mode;
+- hwif->set_dma_mode = &cris_set_dma_mode;
+- hwif->ata_input_data = &cris_ide_input_data;
+- hwif->ata_output_data = &cris_ide_output_data;
+- hwif->atapi_input_bytes = &cris_atapi_input_bytes;
+- hwif->atapi_output_bytes = &cris_atapi_output_bytes;
+- hwif->dma_host_set = &cris_dma_host_set;
+- hwif->ide_dma_end = &cris_dma_end;
+- hwif->dma_setup = &cris_dma_setup;
+- hwif->dma_exec_cmd = &cris_dma_exec_cmd;
+- hwif->ide_dma_test_irq = &cris_dma_test_irq;
+- hwif->dma_start = &cris_dma_start;
+- hwif->OUTB = &cris_ide_outb;
+- hwif->OUTW = &cris_ide_outw;
+- hwif->OUTBSYNC = &cris_ide_outbsync;
+- hwif->INB = &cris_ide_inb;
+- hwif->INW = &cris_ide_inw;
+- hwif->cbl = ATA_CBL_PATA40;
-
-- if (qc->tf.protocol == ATA_PROT_PIO) {
-- /* PIO data out protocol.
-- * send first data block.
-- */
+- idx[h] = hwif->index;
+- }
-
-- /* 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);
+- /* Reset pulse */
+- cris_ide_reset(0);
+- udelay(25);
+- cris_ide_reset(1);
-
-- if (in_wq)
-- spin_unlock_irqrestore(ap->lock, flags);
+- cris_ide_init();
-
-- /* if polling, ata_pio_task() handles the rest.
-- * otherwise, interrupt handler takes over from here.
-- */
-- break;
+- cris_ide_set_speed(TYPE_PIO, ATA_PIO4_SETUP, ATA_PIO4_STROBE, ATA_PIO4_HOLD);
+- cris_ide_set_speed(TYPE_DMA, 0, ATA_DMA2_STROBE, ATA_DMA2_HOLD);
+- cris_ide_set_speed(TYPE_UDMA, ATA_UDMA2_CYC, ATA_UDMA2_DVS, 0);
-
-- 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;
-- }
+- ide_device_add(idx, &cris_port_info);
-
-- /* 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;
-- }
+- return 0;
+-}
-
-- atapi_pio_bytes(qc);
+-static cris_dma_descr_type mydescr __attribute__ ((__aligned__(16)));
-
-- if (unlikely(ap->hsm_task_state == HSM_ST_ERR))
-- /* bad ireason reported by device */
-- goto fsm_start;
+-/*
+- * The following routines are mainly used by the ATAPI drivers.
+- *
+- * These routines will round up any request for an odd number of bytes,
+- * so if an odd bytecount is specified, be sure that there's at least one
+- * extra byte allocated for the buffer.
+- */
+-static void
+-cris_atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
+-{
+- D(printk("atapi_input_bytes, buffer 0x%x, count %d\n",
+- buffer, bytecount));
-
-- } 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;
+- if(bytecount & 1) {
+- printk("warning, odd bytecount in cdrom_in_bytes = %d.\n", bytecount);
+- bytecount++; /* to round off */
+- }
-
-- ap->hsm_task_state = HSM_ST_ERR;
-- goto fsm_start;
-- }
+- /* setup DMA and start transfer */
-
-- /* 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;
+- cris_ide_fill_descriptor(&mydescr, buffer, bytecount, 1);
+- cris_ide_start_dma(drive, &mydescr, 1, TYPE_PIO, bytecount);
-
-- if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
-- ata_pio_sectors(qc);
-- status = ata_wait_idle(ap);
-- }
+- /* wait for completion */
+- LED_DISK_READ(1);
+- cris_ide_wait_dma(1);
+- LED_DISK_READ(0);
+-}
-
-- if (status & (ATA_BUSY | ATA_DRQ))
-- qc->err_mask |= AC_ERR_HSM;
+-static void
+-cris_atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
+-{
+- D(printk("atapi_output_bytes, buffer 0x%x, count %d\n",
+- buffer, bytecount));
-
-- /* 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;
-- }
+- if(bytecount & 1) {
+- printk("odd bytecount %d in atapi_out_bytes!\n", bytecount);
+- bytecount++;
+- }
-
-- ata_pio_sectors(qc);
+- cris_ide_fill_descriptor(&mydescr, buffer, bytecount, 1);
+- cris_ide_start_dma(drive, &mydescr, 0, TYPE_PIO, bytecount);
-
-- 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;
-- }
-- }
+- /* wait for completion */
-
-- poll_next = 1;
-- break;
+- LED_DISK_WRITE(1);
+- LED_DISK_READ(1);
+- cris_ide_wait_dma(0);
+- LED_DISK_WRITE(0);
+-}
-
-- 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;
-- }
+-/*
+- * This is used for most PIO data transfers *from* the IDE interface
+- */
+-static void
+-cris_ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
+-{
+- cris_atapi_input_bytes(drive, buffer, wcount << 2);
+-}
-
-- /* no more data to transfer */
-- DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n",
-- ap->print_id, qc->dev->devno, status);
+-/*
+- * This is used for most PIO data transfers *to* the IDE interface
+- */
+-static void
+-cris_ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
+-{
+- cris_atapi_output_bytes(drive, buffer, wcount << 2);
+-}
-
-- WARN_ON(qc->err_mask);
+-/* we only have one DMA channel on the chip for ATA, so we can keep these statically */
+-static cris_dma_descr_type ata_descrs[MAX_DMA_DESCRS] __attribute__ ((__aligned__(16)));
+-static unsigned int ata_tot_size;
-
-- ap->hsm_task_state = HSM_ST_IDLE;
+-/*
+- * cris_ide_build_dmatable() prepares a dma request.
+- * Returns 0 if all went okay, returns 1 otherwise.
+- */
+-static int cris_ide_build_dmatable (ide_drive_t *drive)
+-{
+- ide_hwif_t *hwif = drive->hwif;
+- struct scatterlist* sg;
+- struct request *rq = drive->hwif->hwgroup->rq;
+- unsigned long size, addr;
+- unsigned int count = 0;
+- int i = 0;
-
-- /* complete taskfile transaction */
-- ata_hsm_qc_complete(qc, in_wq);
+- sg = hwif->sg_table;
-
-- poll_next = 0;
-- break;
+- ata_tot_size = 0;
-
-- case HSM_ST_ERR:
-- /* make sure qc->err_mask is available to
-- * know what's wrong and recover
+- ide_map_sg(drive, rq);
+- i = hwif->sg_nents;
+-
+- while(i) {
+- /*
+- * Determine addr and size of next buffer area. We assume that
+- * individual virtual buffers are always composed linearly in
+- * physical memory. For example, we assume that any 8kB buffer
+- * is always composed of two adjacent physical 4kB pages rather
+- * than two possibly non-adjacent physical 4kB pages.
- */
-- WARN_ON(qc->err_mask == 0);
+- /* group sequential buffers into one large buffer */
+- addr = sg_phys(sg);
+- size = sg_dma_len(sg);
+- while (--i) {
+- sg = sg_next(sg);
+- if ((addr + size) != sg_phys(sg))
+- break;
+- size += sg_dma_len(sg);
+- }
-
-- ap->hsm_task_state = HSM_ST_IDLE;
+- /* did we run out of descriptors? */
-
-- /* complete taskfile transaction */
-- ata_hsm_qc_complete(qc, in_wq);
+- if(count >= MAX_DMA_DESCRS) {
+- printk("%s: too few DMA descriptors\n", drive->name);
+- return 1;
+- }
-
-- poll_next = 0;
-- break;
-- default:
-- poll_next = 0;
-- BUG();
+- /* however, this case is more difficult - rw_trf_cnt cannot be more
+- than 65536 words per transfer, so in that case we need to either
+- 1) use a DMA interrupt to re-trigger rw_trf_cnt and continue with
+- the descriptors, or
+- 2) simply do the request here, and get dma_intr to only ide_end_request on
+- those blocks that were actually set-up for transfer.
+- */
+-
+- if(ata_tot_size + size > 131072) {
+- printk("too large total ATA DMA request, %d + %d!\n", ata_tot_size, (int)size);
+- return 1;
+- }
+-
+- /* If size > MAX_DESCR_SIZE it has to be splitted into new descriptors. Since we
+- don't handle size > 131072 only one split is necessary */
+-
+- if(size > MAX_DESCR_SIZE) {
+- cris_ide_fill_descriptor(&ata_descrs[count], (void*)addr, MAX_DESCR_SIZE, 0);
+- count++;
+- ata_tot_size += MAX_DESCR_SIZE;
+- size -= MAX_DESCR_SIZE;
+- addr += MAX_DESCR_SIZE;
+- }
+-
+- cris_ide_fill_descriptor(&ata_descrs[count], (void*)addr, size,i ? 0 : 1);
+- count++;
+- ata_tot_size += size;
- }
-
-- return poll_next;
+- if (count) {
+- /* return and say all is ok */
+- return 0;
+- }
+-
+- printk("%s: empty DMA table?\n", drive->name);
+- return 1; /* let the PIO routines handle this weirdness */
-}
-
--static void ata_pio_task(struct work_struct *work)
+-/*
+- * cris_dma_intr() is the handler for disk read/write DMA interrupts
+- */
+-static ide_startstop_t cris_dma_intr (ide_drive_t *drive)
-{
-- 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;
+- LED_DISK_READ(0);
+- LED_DISK_WRITE(0);
-
--fsm_start:
-- WARN_ON(ap->hsm_task_state == HSM_ST_IDLE);
+- return ide_dma_intr(drive);
+-}
-
-- /*
-- * 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;
-- }
+-/*
+- * Functions below initiates/aborts DMA read/write operations on a drive.
+- *
+- * The caller is assumed to have selected the drive and programmed the drive's
+- * sector address using CHS or LBA. All that remains is to prepare for DMA
+- * and then issue the actual read/write DMA/PIO command to the drive.
+- *
+- * For ATAPI devices, we just prepare for DMA and return. The caller should
+- * then issue the packet command to the drive and call us again with
+- * cris_dma_start afterwards.
+- *
+- * Returns 0 if all went well.
+- * Returns 1 if DMA read/write could not be started, in which case
+- * the caller should revert to PIO for the current request.
+- */
+-
+-static int cris_dma_end(ide_drive_t *drive)
+-{
+- drive->waiting_for_dma = 0;
+- return 0;
+-}
+-
+-static int cris_dma_setup(ide_drive_t *drive)
+-{
+- struct request *rq = drive->hwif->hwgroup->rq;
+-
+- cris_ide_initialize_dma(!rq_data_dir(rq));
+- if (cris_ide_build_dmatable (drive)) {
+- ide_map_sg(drive, rq);
+- return 1;
- }
-
-- /* move the HSM */
-- poll_next = ata_hsm_move(ap, qc, status, 1);
+- drive->waiting_for_dma = 1;
+- return 0;
+-}
-
-- /* another command or interrupt handler
-- * may be running at this point.
-- */
-- if (poll_next)
-- goto fsm_start;
+-static void cris_dma_exec_cmd(ide_drive_t *drive, u8 command)
+-{
+- ide_execute_command(drive, command, &cris_dma_intr, WAIT_CMD, NULL);
-}
-
--/**
- * 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;
+-static void cris_dma_start(ide_drive_t *drive)
+-{
+- struct request *rq = drive->hwif->hwgroup->rq;
+- int writing = rq_data_dir(rq);
+- int type = TYPE_DMA;
+-
+- if (drive->current_speed >= XFER_UDMA_0)
+- type = TYPE_UDMA;
+-
+- cris_ide_start_dma(drive, &ata_descrs[0], writing ? 0 : 1, type, ata_tot_size);
+-
+- if (writing) {
+- LED_DISK_WRITE(1);
+- } else {
+- LED_DISK_READ(1);
+- }
+-}
+-
+-module_init(init_e100_ide);
+-
+-MODULE_LICENSE("GPL");
+diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c
+index 4108ec4..ecf53bb 100644
+--- a/drivers/ide/h8300/ide-h8300.c
++++ b/drivers/ide/h8300/ide-h8300.c
+@@ -42,6 +42,91 @@ static u16 mm_inw(unsigned long a)
+ return r;
+ }
+
++static void h8300_tf_load(ide_drive_t *drive, ide_task_t *task)
++{
++ ide_hwif_t *hwif = drive->hwif;
++ struct ide_io_ports *io_ports = &hwif->io_ports;
++ struct ide_taskfile *tf = &task->tf;
++ u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
++
++ if (task->tf_flags & IDE_TFLAG_FLAGGED)
++ HIHI = 0xFF;
++
++ ide_set_irq(drive, 1);
++
++ if (task->tf_flags & IDE_TFLAG_OUT_DATA)
++ mm_outw((tf->hob_data << 8) | tf->data, io_ports->data_addr);
++
++ if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
++ outb(tf->hob_feature, io_ports->feature_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
++ outb(tf->hob_nsect, io_ports->nsect_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
++ outb(tf->hob_lbal, io_ports->lbal_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
++ outb(tf->hob_lbam, io_ports->lbam_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
++ outb(tf->hob_lbah, io_ports->lbah_addr);
++
++ if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
++ outb(tf->feature, io_ports->feature_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
++ outb(tf->nsect, io_ports->nsect_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
++ outb(tf->lbal, io_ports->lbal_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
++ outb(tf->lbam, io_ports->lbam_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
++ outb(tf->lbah, io_ports->lbah_addr);
++
++ if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
++ outb((tf->device & HIHI) | drive->select.all,
++ io_ports->device_addr);
++}
++
++static void h8300_tf_read(ide_drive_t *drive, ide_task_t *task)
++{
++ ide_hwif_t *hwif = drive->hwif;
++ struct ide_io_ports *io_ports = &hwif->io_ports;
++ struct ide_taskfile *tf = &task->tf;
++
++ if (task->tf_flags & IDE_TFLAG_IN_DATA) {
++ u16 data = mm_inw(io_ports->data_addr);
++
++ tf->data = data & 0xff;
++ tf->hob_data = (data >> 8) & 0xff;
++ }
++
++ /* be sure we're looking at the low order bits */
++ outb(drive->ctl & ~0x80, io_ports->ctl_addr);
++
++ if (task->tf_flags & IDE_TFLAG_IN_NSECT)
++ tf->nsect = inb(io_ports->nsect_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_LBAL)
++ tf->lbal = inb(io_ports->lbal_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_LBAM)
++ tf->lbam = inb(io_ports->lbam_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_LBAH)
++ tf->lbah = inb(io_ports->lbah_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
++ tf->device = inb(io_ports->device_addr);
++
++ if (task->tf_flags & IDE_TFLAG_LBA48) {
++ outb(drive->ctl | 0x80, io_ports->ctl_addr);
++
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
++ tf->hob_feature = inb(io_ports->feature_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
++ tf->hob_nsect = inb(io_ports->nsect_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
++ tf->hob_lbal = inb(io_ports->lbal_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
++ tf->hob_lbam = inb(io_ports->lbam_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
++ tf->hob_lbah = inb(io_ports->lbah_addr);
++ }
++}
++
+ static void mm_outsw(unsigned long addr, void *buf, u32 len)
+ {
+ unsigned short *bp = (unsigned short *)buf;
+@@ -56,6 +141,18 @@ static void mm_insw(unsigned long addr, void *buf, u32 len)
+ *bp = bswap(*(volatile u16 *)addr);
+ }
+
++static void h8300_input_data(ide_drive_t *drive, struct request *rq,
++ void *buf, unsigned int len)
++{
++ mm_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
++}
++
++static void h8300_output_data(ide_drive_t *drive, struct request *rq,
++ void *buf, unsigned int len)
++{
++ mm_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
++}
++
+ #define H8300_IDE_GAP (2)
+
+ static inline void hw_setup(hw_regs_t *hw)
+@@ -63,9 +160,9 @@ static inline void hw_setup(hw_regs_t *hw)
+ int i;
+
+ memset(hw, 0, sizeof(hw_regs_t));
+- for (i = 0; i <= IDE_STATUS_OFFSET; i++)
+- hw->io_ports[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i;
+- hw->io_ports[IDE_CONTROL_OFFSET] = CONFIG_H8300_IDE_ALT;
++ for (i = 0; i <= 7; i++)
++ hw->io_ports_array[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i;
++ hw->io_ports.ctl_addr = CONFIG_H8300_IDE_ALT;
+ hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ;
+ hw->chipset = ide_generic;
+ }
+@@ -74,13 +171,11 @@ static inline void hwif_setup(ide_hwif_t *hwif)
+ {
+ default_hwif_iops(hwif);
+
+- hwif->mmio = 1;
+- hwif->OUTW = mm_outw;
+- hwif->OUTSW = mm_outsw;
+- hwif->INW = mm_inw;
+- hwif->INSW = mm_insw;
+- hwif->OUTSL = NULL;
+- hwif->INSL = NULL;
++ hwif->tf_load = h8300_tf_load;
++ hwif->tf_read = h8300_tf_read;
++
++ hwif->input_data = h8300_input_data;
++ hwif->output_data = h8300_output_data;
+ }
+
+ static int __init h8300_ide_init(void)
+@@ -99,8 +194,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..9d3601f 100644
+--- a/drivers/ide/ide-acpi.c
++++ b/drivers/ide/ide-acpi.c
+@@ -55,14 +55,22 @@ struct ide_acpi_hwif_link {
+ /* note: adds function name and KERN_DEBUG */
+ #ifdef DEBUGGING
+ #define DEBPRINT(fmt, args...) \
+- printk(KERN_DEBUG "%s: " fmt, __FUNCTION__, ## args)
++ printk(KERN_DEBUG "%s: " fmt, __func__, ## args)
+ #else
+ #define DEBPRINT(fmt, args...) do {} while (0)
+ #endif /* DEBUGGING */
+
+-extern int ide_noacpi;
+-extern int ide_noacpitfs;
+-extern int ide_noacpionboot;
++int ide_noacpi;
++module_param_named(noacpi, ide_noacpi, bool, 0);
++MODULE_PARM_DESC(noacpi, "disable IDE ACPI support");
++
++int ide_acpigtf;
++module_param_named(acpigtf, ide_acpigtf, bool, 0);
++MODULE_PARM_DESC(acpigtf, "enable IDE ACPI _GTF support");
++
++int ide_acpionboot;
++module_param_named(acpionboot, ide_acpionboot, bool, 0);
++MODULE_PARM_DESC(acpionboot, "call IDE ACPI methods on boot");
+
+ static bool ide_noacpi_psx;
+ static int no_acpi_psx(const struct dmi_system_id *id)
+@@ -309,7 +317,7 @@ static int do_drive_get_GTF(ide_drive_t *drive,
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_DEBUG
+ "%s: Run _GTF error: status = 0x%x\n",
+- __FUNCTION__, status);
++ __func__, status);
+ goto out;
+ }
+
+@@ -335,7 +343,7 @@ static int do_drive_get_GTF(ide_drive_t *drive,
+ out_obj->buffer.length % REGS_PER_GTF) {
+ printk(KERN_ERR
+ "%s: unexpected GTF length (%d) or addr (0x%p)\n",
+- __FUNCTION__, out_obj->buffer.length,
++ __func__, out_obj->buffer.length,
+ out_obj->buffer.pointer);
+ err = -ENOENT;
+ kfree(output.pointer);
+@@ -376,7 +384,7 @@ static int taskfile_load_raw(ide_drive_t *drive,
+ memcpy(&args.tf_array[7], >f->tfa, 7);
+ args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+
+- if (ide_noacpitfs) {
++ if (!ide_acpigtf) {
+ DEBPRINT("_GTF execution disabled\n");
+ return err;
+ }
+@@ -384,7 +392,7 @@ static int taskfile_load_raw(ide_drive_t *drive,
+ err = ide_no_data_taskfile(drive, &args);
+ if (err)
+ printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n",
+- __FUNCTION__, err);
++ __func__, err);
+
+ return err;
+ }
+@@ -422,7 +430,7 @@ static int do_drive_set_taskfiles(ide_drive_t *drive,
+
+ if (gtf_length % REGS_PER_GTF) {
+ printk(KERN_ERR "%s: unexpected GTF length (%d)\n",
+- __FUNCTION__, gtf_length);
++ __func__, gtf_length);
+ goto out;
+ }
+
+@@ -547,7 +555,7 @@ void ide_acpi_get_timing(ide_hwif_t *hwif)
+ printk(KERN_ERR
+ "%s: unexpected _GTM length (0x%x)[should be 0x%zx] or "
+ "addr (0x%p)\n",
+- __FUNCTION__, out_obj->buffer.length,
++ __func__, out_obj->buffer.length,
+ sizeof(struct GTM_buffer), out_obj->buffer.pointer);
+ return;
+ }
+@@ -710,6 +718,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;
+
+@@ -719,7 +729,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
+ drive->name, err);
+ }
+
+- if (ide_noacpionboot) {
++ if (!ide_acpionboot) {
+ DEBPRINT("ACPI methods disabled on boot\n");
+ return;
+ }
+diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
+index c8d0e87..68e7f19 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
+@@ -39,19 +39,20 @@
+ #include <linux/mutex.h>
+ #include <linux/bcd.h>
+
+-#include <scsi/scsi.h> /* For SCSI -> ATAPI command conversion */
++/* For SCSI -> ATAPI command conversion */
++#include <scsi/scsi.h>
+
+-#include <asm/irq.h>
+-#include <asm/io.h>
++#include <linux/irq.h>
++#include <linux/io.h>
+ #include <asm/byteorder.h>
+-#include <asm/uaccess.h>
++#include <linux/uaccess.h>
+ #include <asm/unaligned.h>
+
+ #include "ide-cd.h"
+
+ 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)
+@@ -77,19 +78,17 @@ static void ide_cd_put(struct cdrom_info *cd)
+ mutex_unlock(&idecd_ref_mutex);
+ }
+
+-/****************************************************************************
++/*
+ * Generic packet command support and error handling routines.
+ */
+
+-/* Mark that we've seen a media change, and invalidate our internal
+- buffers. */
+-static void cdrom_saw_media_change (ide_drive_t *drive)
++/* Mark that we've seen a media change and invalidate our internal buffers. */
++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,66 +100,65 @@ 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;
+ }
+
+-static
+-void cdrom_analyze_sense_data(ide_drive_t *drive,
++static void cdrom_analyze_sense_data(ide_drive_t *drive,
+ struct request *failed_command,
+ struct request_sense *sense)
+ {
+ unsigned long sector;
+ unsigned long bio_sectors;
+- unsigned long valid;
+ struct cdrom_info *info = drive->driver_data;
+
+ if (!cdrom_log_sense(drive, failed_command, sense))
+ return;
+
+ /*
+- * If a read toc is executed for a CD-R or CD-RW medium where
+- * the first toc has not been recorded yet, it will fail with
+- * 05/24/00 (which is a confusing error)
++ * If a read toc is executed for a CD-R or CD-RW medium where the first
++ * toc has not been recorded yet, it will fail with 05/24/00 (which is a
++ * confusing error)
+ */
+ if (failed_command && failed_command->cmd[0] == GPCMD_READ_TOC_PMA_ATIP)
+ if (sense->sense_key == 0x05 && sense->asc == 0x24)
+ return;
+
+- if (sense->error_code == 0x70) { /* Current Error */
+- switch(sense->sense_key) {
++ /* current error */
++ if (sense->error_code == 0x70) {
++ switch (sense->sense_key) {
+ case MEDIUM_ERROR:
+ case VOLUME_OVERFLOW:
+ case ILLEGAL_REQUEST:
+@@ -174,29 +172,23 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
+ (sense->information[2] << 8) |
+ (sense->information[3]);
+
+- bio_sectors = bio_sectors(failed_command->bio);
+- if (bio_sectors < 4)
+- bio_sectors = 4;
+ if (drive->queue->hardsect_size == 2048)
+- sector <<= 2; /* Device sector size is 2K */
+- sector &= ~(bio_sectors -1);
+- valid = (sector - failed_command->sector) << 9;
++ /* device sector size is 2K */
++ sector <<= 2;
++
++ bio_sectors = max(bio_sectors(failed_command->bio), 4U);
++ sector &= ~(bio_sectors - 1);
+
+- if (valid < 0)
+- valid = 0;
+ if (sector < get_capacity(info->disk) &&
+- drive->probed_capacity - sector < 4 * 75) {
++ drive->probed_capacity - sector < 4 * 75)
+ set_capacity(info->disk, sector);
+- }
+- }
+- }
++ }
++ }
+
+ ide_cd_log_error(drive->name, failed_command, sense);
+ }
+
+-/*
+- * Initialize a ide-cd packet command request
+- */
++/* Initialize a ide-cd packet command request */
+ void ide_cd_init_rq(ide_drive_t *drive, struct request *rq)
+ {
+ struct cdrom_info *cd = drive->driver_data;
+@@ -220,7 +212,8 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
+
+ rq->data = sense;
+ rq->cmd[0] = GPCMD_REQUEST_SENSE;
+- rq->cmd[4] = rq->data_len = 18;
++ rq->cmd[4] = 18;
++ rq->data_len = 18;
+
+ rq->cmd_type = REQ_TYPE_SENSE;
+
+@@ -230,7 +223,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;
+@@ -252,7 +245,7 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
+ }
+ cdrom_analyze_sense_data(drive, failed, sense);
+ /*
+- * now end failed request
++ * now end the failed request
+ */
+ if (blk_fs_request(failed)) {
+ if (ide_end_dequeued_request(drive, failed, 0,
+@@ -280,21 +273,24 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
+ ide_end_request(drive, uptodate, nsectors);
+ }
- qc->result_tf.flags = qc->tf.flags;
-- ap->ops->tf_read(ap, &qc->result_tf);
-+ ap->ops->qc_fill_rtf(qc);
+-static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 stat)
++static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 st)
+ {
+- if (stat & 0x80)
++ if (st & 0x80)
+ return;
+- ide_dump_status(drive, msg, stat);
++ ide_dump_status(drive, msg, st);
}
- 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)
+-/* Returns 0 if the request should be continued.
+- Returns 1 if the request was ended. */
++/*
++ * Returns:
++ * 0: if the request should be continued.
++ * 1: if the request was ended.
++ */
+ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
{
- int nr_done = 0;
- u32 done_mask;
-@@ -5995,8 +4691,6 @@ int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
- continue;
+ struct request *rq = HWGROUP(drive)->rq;
+ int stat, err, sense_key;
+-
+- /* Check for errors. */
++
++ /* check for errors */
+ stat = ide_read_status(drive);
- 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 (stat_ret)
+@@ -303,20 +299,22 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ if (OK_STAT(stat, good_stat, BAD_R_STAT))
+ return 0;
-- /* 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:
- }
+- /* Get the IDE error register. */
++ /* get the IDE error register */
+ err = ide_read_error(drive);
+ sense_key = err >> 4;
+
+ if (rq == NULL) {
+- printk("%s: missing rq in cdrom_decode_status\n", drive->name);
++ printk(KERN_ERR "%s: missing rq in %s\n",
++ drive->name, __func__);
+ return 1;
+ }
- /**
-- * 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
-- */
+ if (blk_sense_request(rq)) {
+- /* We got an error trying to get sense info
+- from the drive (probably while trying
+- to recover from a former error). Just give up. */
-
--unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
--{
-- struct ata_port *ap = qc->ap;
++ /*
++ * We got an error trying to get sense info from the drive
++ * (probably while trying to recover from a former error).
++ * Just give up.
++ */
+ rq->cmd_flags |= REQ_FAILED;
+ cdrom_end_request(drive, 0);
+ ide_error(drive, "request sense failure", stat);
+@@ -332,28 +330,27 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ if (blk_pc_request(rq) && !rq->errors)
+ rq->errors = SAM_STAT_CHECK_CONDITION;
+
+- /* Check for tray open. */
++ /* 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);
+- /*printk("%s: media changed\n",drive->name);*/
++ /* check for media change */
++ cdrom_saw_media_change(drive);
+ 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. */
++ /* otherwise, print an error */
+ ide_dump_status(drive, "packet command error", stat);
+ }
+-
++
+ rq->cmd_flags |= REQ_FAILED;
+
+ /*
+@@ -366,27 +363,30 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ } else if (blk_fs_request(rq)) {
+ int do_end_request = 0;
+
+- /* Handle errors from READ and WRITE requests. */
++ /* handle errors from READ and WRITE requests */
+
+ if (blk_noretry_request(rq))
+ do_end_request = 1;
+
+ if (sense_key == NOT_READY) {
+- /* Tray open. */
++ /* 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);
++ /* fail the request */
++ printk(KERN_ERR "%s: tray open\n", drive->name);
+ do_end_request = 1;
+ } else {
+ struct cdrom_info *info = drive->driver_data;
+
+- /* allow the drive 5 seconds to recover, some
++ /*
++ * Allow the drive 5 seconds to recover, some
+ * devices will return this error while flushing
+- * data from cache */
++ * data from cache.
++ */
+ if (!rq->errors)
+- info->write_timeout = jiffies + ATAPI_WAIT_WRITE_BUSY;
++ info->write_timeout = jiffies +
++ ATAPI_WAIT_WRITE_BUSY;
+ rq->errors = 1;
+ if (time_after(jiffies, info->write_timeout))
+ do_end_request = 1;
+@@ -394,59 +394,68 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ unsigned long flags;
+
+ /*
+- * take a breather relying on the
+- * unplug timer to kick us again
++ * take a breather relying on the unplug
++ * timer to kick us again
+ */
+ 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;
+ }
+ }
+ } else if (sense_key == UNIT_ATTENTION) {
+- /* Media change. */
+- cdrom_saw_media_change (drive);
++ /* 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);
++ /* disk appears blank ?? */
++ 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
+- for other errors. */
++ /* go to the default handler for other errors */
+ ide_error(drive, "cdrom_decode_status", stat);
+ return 1;
+ } else if ((++rq->errors > ERROR_MAX)) {
+- /* We've racked up too many retries. Abort. */
++ /* we've racked up too many retries, abort */
+ do_end_request = 1;
+ }
+
+- /* End a request through request sense analysis when we have
+- sense data. We need this in order to perform end of media
+- processing */
-
-- /* 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();
++ /*
++ * End a request through request sense analysis when we have
++ * sense data. We need this in order to perform end of media
++ * processing.
++ */
+ if (do_end_request)
+ goto end_request;
+
+ /*
+- * If we got a CHECK_CONDITION status,
+- * queue a request sense command.
++ * If we got a CHECK_CONDITION status, queue
++ * a request sense command.
+ */
+ if (stat & ERR_STAT)
+ cdrom_queue_request_sense(drive, NULL, NULL);
+@@ -455,7 +464,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ cdrom_end_request(drive, 0);
+ }
+
+- /* Retry, or handle the next request. */
++ /* retry, or handle the next request */
+ return 1;
+
+ end_request:
+@@ -480,35 +489,37 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
+ unsigned long wait = 0;
+
+ /*
+- * Some commands are *slow* and normally take a long time to
+- * complete. Usually we can use the ATAPI "disconnect" to bypass
+- * this, but not all commands/drives support that. Let
+- * ide_timer_expiry keep polling us for these.
++ * Some commands are *slow* and normally take a long time to complete.
++ * Usually we can use the ATAPI "disconnect" to bypass this, but not all
++ * commands/drives support that. Let 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;
-- }
-- }
--
-- /* 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);
++ 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;
+ }
+
+-/* Set up the device registers for transferring a packet command on DEV,
+- expecting to later transfer XFERLEN bytes. HANDLER is the routine
+- which actually transfers the command to the drive. If this is a
+- drq_interrupt device, this routine will arrange for HANDLER to be
+- called when the interrupt from the drive arrives. Otherwise, HANDLER
+- will be called immediately after the drive is prepared for the transfer. */
+-
++/*
++ * Set up the device registers for transferring a packet command on DEV,
++ * expecting to later transfer XFERLEN bytes. HANDLER is the routine
++ * which actually transfers the command to the drive. If this is a
++ * drq_interrupt device, this routine will arrange for HANDLER to be
++ * called when the interrupt from the drive arrives. Otherwise, HANDLER
++ * will be called immediately after the drive is prepared for the transfer.
++ */
+ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
+ int xferlen,
+ ide_handler_t *handler)
+@@ -517,15 +528,15 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
+ struct cdrom_info *info = drive->driver_data;
+ ide_hwif_t *hwif = drive->hwif;
+
+- /* Wait for the controller to be idle. */
++ /* wait for the controller to be idle */
+ if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY))
+ return startstop;
+
+ /* FIXME: for Virtual DMA we must check harder */
+ if (info->dma)
+- info->dma = !hwif->dma_setup(drive);
++ info->dma = !hwif->dma_ops->dma_setup(drive);
+
+- /* Set up the controller registers. */
++ /* set up the controller registers */
+ ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL |
+ IDE_TFLAG_NO_SELECT_MASK, xferlen, info->dma);
+
+@@ -535,28 +546,24 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
+ drive->waiting_for_dma = 0;
+
+ /* packet command */
+- ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry);
++ ide_execute_command(drive, WIN_PACKETCMD, handler,
++ ATAPI_WAIT_PC, cdrom_timer_expiry);
+ return ide_started;
+ } else {
+- unsigned long flags;
-
-- ata_tf_to_host(ap, &qc->tf);
+- /* packet command */
+- spin_lock_irqsave(&ide_lock, flags);
+- hwif->OUTBSYNC(drive, WIN_PACKETCMD, IDE_COMMAND_REG);
+- ndelay(400);
+- spin_unlock_irqrestore(&ide_lock, flags);
++ ide_execute_pkt_cmd(drive);
+
+ return (*handler) (drive);
+ }
+ }
+
+-/* Send a packet command to DRIVE described by CMD_BUF and CMD_LEN.
+- The device registers must have already been prepared
+- by cdrom_start_packet_command.
+- HANDLER is the interrupt handler to call when the command completes
+- or there's data ready. */
++/*
++ * Send a packet command to DRIVE described by CMD_BUF and CMD_LEN. The device
++ * registers must have already been prepared by cdrom_start_packet_command.
++ * 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)
+ {
+@@ -566,24 +573,26 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
+ ide_startstop_t startstop;
+
+ if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
+- /* Here we should have been called after receiving an interrupt
+- from the device. DRQ should how be set. */
++ /*
++ * Here we should have been called after receiving an interrupt
++ * from the device. DRQ should how be set.
++ */
+
+- /* Check for errors. */
++ /* check for errors */
+ if (cdrom_decode_status(drive, DRQ_STAT, NULL))
+ return ide_stopped;
+
+- /* Ok, next interrupt will be DMA interrupt. */
++ /* ok, next interrupt will be DMA interrupt */
+ if (info->dma)
+ drive->waiting_for_dma = 1;
+ } else {
+- /* Otherwise, we must wait for DRQ to get set. */
++ /* otherwise, we must wait for DRQ to get set */
+ if (ide_wait_stat(&startstop, drive, DRQ_STAT,
+ BUSY_STAT, WAIT_READY))
+ return startstop;
+ }
+
+- /* Arm the interrupt handler. */
++ /* arm the interrupt handler */
+ ide_set_handler(drive, handler, rq->timeout, cdrom_timer_expiry);
+
+ /* ATAPI commands get padded out to 12 bytes minimum */
+@@ -591,25 +600,24 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
+ if (cmd_len < ATAPI_MIN_CDB_BYTES)
+ cmd_len = ATAPI_MIN_CDB_BYTES;
+
+- /* Send the command to the device. */
+- HWIF(drive)->atapi_output_bytes(drive, rq->cmd, cmd_len);
++ /* send the command to the device */
++ hwif->output_data(drive, NULL, rq->cmd, cmd_len);
+
+- /* Start the DMA if need be */
++ /* start the DMA if need be */
+ if (info->dma)
+- hwif->dma_start(drive);
++ hwif->dma_ops->dma_start(drive);
+
+ return ide_started;
+ }
+
+-/****************************************************************************
++/*
+ * Block read functions.
+ */
-
-- ap->hsm_task_state = HSM_ST_FIRST;
+ static void ide_cd_pad_transfer(ide_drive_t *drive, xfer_func_t *xf, int len)
+ {
+ while (len > 0) {
+ int dum = 0;
+- xf(drive, &dum, sizeof(dum));
++ xf(drive, NULL, &dum, sizeof(dum));
+ len -= sizeof(dum);
+ }
+ }
+@@ -619,53 +627,12 @@ static void ide_cd_drain_data(ide_drive_t *drive, int nsects)
+ while (nsects > 0) {
+ static char dum[SECTOR_SIZE];
+
+- drive->hwif->atapi_input_bytes(drive, dum, sizeof(dum));
++ drive->hwif->input_data(drive, NULL, dum, sizeof(dum));
+ 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;
-
-- /* 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;
+- /* 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);
-
-- case ATAPI_PROT_DMA:
-- WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
+- char *dest;
-
-- 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;
+- /* If we couldn't get a buffer, don't try to buffer anything... */
+- if (info->buffer == NULL)
+- sectors_to_buffer = 0;
-
-- /* send cdb by polling if no cdb interrupt */
-- if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
-- ata_pio_queue_task(ap, qc, 0);
-- break;
+- /* If this is the first sector in the buffer, remember its number. */
+- if (info->nsectors_buffered == 0)
+- info->sector_buffered = sector;
-
-- default:
-- WARN_ON(1);
-- return AC_ERR_SYSTEM;
+- /* 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;
- }
-
-- return 0;
+- /* Throw away any remaining data. */
+- ide_cd_drain_data(drive, sectors_to_transfer);
-}
-
--/**
-- * 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).
+-/*
+ * 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.
+@@ -683,22 +650,23 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
+ ide_hwif_t *hwif = drive->hwif;
+ xfer_func_t *xf;
+
+- /* Whoops... */
++ /* 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;
++ xf = rw ? hwif->output_data : hwif->input_data;
+ ide_cd_pad_transfer(drive, xf, len);
+ } else if (rw == 0 && ireason == 1) {
+- /* Some drives (ASUS) seem to tell us that status
+- * info is available. just get it and ignore.
++ /*
++ * Some drives (ASUS) seem to tell us that status info is
++ * available. Just get it and ignore.
+ */
+ (void)ide_read_status(drive);
+ return 0;
+ } else {
+- /* Drive wants a command packet, or invalid ireason... */
++ /* 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 +688,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,72 +701,13 @@ 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.
- */
--
--inline unsigned int ata_host_intr(struct ata_port *ap,
-- struct ata_queued_cmd *qc)
+-static int cdrom_read_from_buffer (ide_drive_t *drive)
-{
-- 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.
-- */
+- struct cdrom_info *info = drive->driver_data;
+- struct request *rq = HWGROUP(drive)->rq;
+- unsigned short sectors_per_frame;
-
-- /* 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);
+- sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
-
-- /* if it's not our irq... */
-- if (!(host_stat & ATA_DMA_INTR))
-- goto idle_irq;
+- /* Can't do anything if there's no buffer. */
+- if (info->buffer == NULL) return 0;
-
-- /* before we do anything else, clear DMA-Start bit */
-- ap->ops->bmdma_stop(qc);
+- /* 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);
-
-- 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;
+- 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;
- }
-
-- /* 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;
+- /* If we've satisfied the current request,
+- terminate it successfully. */
+- if (rq->nr_sectors == 0) {
+- cdrom_end_request(drive, 1);
+- 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;
+- /* Move on to the next buffer if needed. */
+- if (rq->current_nr_sectors == 0)
+- cdrom_end_request(drive, 1);
-
-- 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);
-- }
+- /* 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;
- }
-
-- spin_unlock_irqrestore(&host->lock, flags);
--
-- return IRQ_RETVAL(handled);
+- return 0;
-}
-
--/**
- * 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;
+ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
+
+ /*
+- * Routine to send a read/write packet command to the drive.
+- * This is usually called directly from cdrom_start_{read,write}().
+- * However, for drq_interrupt devices, it is called from an interrupt
+- * when the drive is ready to accept the command.
++ * Routine to send a read/write packet command to the drive. This is usually
++ * called directly from cdrom_start_{read,write}(). However, for drq_interrupt
++ * devices, it is called from an interrupt when the drive is ready to accept
++ * the command.
+ */
+ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
+ {
+@@ -820,11 +729,11 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
+ * is larger than the buffer size.
+ */
+ if (nskip > 0) {
+- /* Sanity check... */
++ /* sanity check... */
+ 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;
+@@ -837,10 +746,10 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
+ /* the immediate bit */
+ rq->cmd[1] = 1 << 3;
+ #endif
+- /* Set up the command */
++ /* set up the command */
+ rq->timeout = ATAPI_WAIT_PC;
+
+- /* Send the command to the drive and return. */
++ /* send the command to the drive and return */
+ return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
}
--int ata_flush_cache(struct ata_device *dev)
--{
-- unsigned int err_mask;
-- u8 cmd;
+@@ -848,7 +757,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;
+@@ -860,26 +769,20 @@ static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
+ info->cd_flags |= IDE_CD_FLAG_SEEKING;
+
+ if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
+- if (--retry == 0) {
+- /*
+- * this condition is far too common, to bother
+- * users about it
+- */
+- /* printk("%s: disabled DSC seek overlap\n", drive->name);*/
++ if (--retry == 0)
+ 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;
+
+ sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS);
+
+- memset(rq->cmd, 0, sizeof(rq->cmd));
++ memset(rq->cmd, 0, BLK_MAX_CDB);
+ rq->cmd[0] = GPCMD_SEEK;
+ put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]);
+
+@@ -887,36 +790,40 @@ 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;
+
+ info->dma = 0;
+ info->start_seek = jiffies;
+- return cdrom_start_packet_command(drive, 0, cdrom_start_seek_continuation);
++ 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;
++ sector_t n =
++ (rq->buffer - (char *)bio_data(rq->bio)) / SECTOR_SIZE;
+
+ rq->buffer = bio_data(rq->bio);
+ rq->nr_sectors += n;
+ rq->sector -= n;
+ }
+- rq->hard_cur_sectors = rq->current_nr_sectors = bio_cur_sectors(rq->bio);
++ rq->current_nr_sectors = bio_cur_sectors(rq->bio);
++ rq->hard_cur_sectors = rq->current_nr_sectors;
+ rq->hard_nr_sectors = rq->nr_sectors;
+ rq->hard_sector = rq->sector;
+ rq->q->prep_rq_fn(rq->q, rq);
+ }
+
+-/****************************************************************************
+- * Execute all other packet commands.
++/*
++ * All other packet commands.
+ */
-
-- if (!ata_try_flush_cache(dev))
-- return 0;
+ static void ide_cd_request_sense_fixup(struct request *rq)
+ {
+ /*
+@@ -940,7 +847,7 @@ int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
+ if (rq->sense == NULL)
+ rq->sense = &sense;
+
+- /* Start of retry loop. */
++ /* start of retry loop */
+ do {
+ int error;
+ unsigned long time = jiffies;
+@@ -949,41 +856,45 @@ 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
+- * in case of failure */
++ /*
++ * 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
+- attention status
+- (usually means media was changed). */
++ /*
++ * The request failed. Retry if it was due to a unit
++ * attention status (usually means media was changed).
++ */
+ struct request_sense *reqbuf = rq->sense;
+
+ if (reqbuf->sense_key == UNIT_ATTENTION)
+ cdrom_saw_media_change(drive);
+ else if (reqbuf->sense_key == NOT_READY &&
+ reqbuf->asc == 4 && reqbuf->ascq != 4) {
+- /* The drive is in the process of loading
+- a disk. Retry, but wait a little to give
+- the drive time to complete the load. */
++ /*
++ * The drive is in the process of loading
++ * a disk. Retry, but wait a little to give
++ * the drive time to complete the load.
++ */
+ ssleep(2);
+ } else {
+- /* Otherwise, don't retry. */
++ /* otherwise, don't retry */
+ retries = 0;
+ }
+ --retries;
+ }
+
+- /* End of retry loop. */
++ /* end of retry loop */
+ } while ((rq->cmd_flags & REQ_FAILED) && retries >= 0);
+
+- /* Return an error if the command failed. */
++ /* return an error if the command failed */
+ return (rq->cmd_flags & REQ_FAILED) ? -EIO : 0;
+ }
+
+ /*
+- * Called from blk_end_request_callback() after the data of the request
+- * is completed and before the request is completed.
+- * By returning value '1', blk_end_request_callback() returns immediately
+- * without completing the request.
++ * Called from blk_end_request_callback() after the data of the request is
++ * completed and before the request itself is completed. By returning value '1',
++ * blk_end_request_callback() returns immediately without completing it.
+ */
+ static int cdrom_newpc_intr_dummy_cb(struct request *rq)
+ {
+@@ -992,6 +903,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;
+@@ -1001,11 +913,11 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ unsigned int timeout;
+ u8 lowcyl, highcyl;
+
+- /* Check for errors. */
++ /* check for errors */
+ dma = info->dma;
+ if (dma) {
+ info->dma = 0;
+- dma_error = HWIF(drive)->ide_dma_end(drive);
++ dma_error = hwif->dma_ops->dma_end(drive);
+ if (dma_error) {
+ printk(KERN_ERR "%s: DMA %s error\n", drive->name,
+ write ? "write" : "read");
+@@ -1016,9 +928,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ if (cdrom_decode_status(drive, 0, &stat))
+ return ide_stopped;
+
+- /*
+- * using dma, transfer is complete now
+- */
++ /* using dma, transfer is complete now */
+ if (dma) {
+ if (dma_error)
+ return ide_error(drive, "dma error", stat);
+@@ -1029,12 +939,10 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ goto end_request;
+ }
+
+- /*
+- * 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);
++ /* ok we fall to pio :/ */
++ ireason = hwif->INB(hwif->io_ports.nsect_addr) & 0x3;
++ lowcyl = hwif->INB(hwif->io_ports.lbam_addr);
++ highcyl = hwif->INB(hwif->io_ports.lbah_addr);
+
+ len = lowcyl + (256 * highcyl);
+
+@@ -1042,9 +950,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ if (thislen > len)
+ thislen = len;
+
+- /*
+- * If DRQ is clear, the command has completed.
+- */
++ /* If DRQ is clear, the command has completed. */
+ if ((stat & DRQ_STAT) == 0) {
+ if (blk_fs_request(rq)) {
+ /*
+@@ -1055,7 +961,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;
+@@ -1065,15 +971,13 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ return ide_stopped;
+ } else if (!blk_pc_request(rq)) {
+ ide_cd_request_sense_fixup(rq);
+- /* Complain if we still have data left to transfer. */
++ /* complain if we still have data left to transfer */
+ uptodate = rq->data_len ? 0 : 1;
+ }
+ goto end_request;
+ }
+
+- /*
+- * check which way to transfer data
+- */
++ /* check which way to transfer data */
+ if (ide_cd_check_ireason(drive, rq, len, ireason, write))
+ return ide_stopped;
+
+@@ -1103,22 +1007,18 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+
+ if (ireason == 0) {
+ write = 1;
+- xferfunc = HWIF(drive)->atapi_output_bytes;
++ xferfunc = hwif->output_data;
+ } else {
+ write = 0;
+- xferfunc = HWIF(drive)->atapi_input_bytes;
++ xferfunc = hwif->input_data;
+ }
+
+- /*
+- * transfer data
+- */
++ /* transfer data */
+ while (thislen > 0) {
+ u8 *ptr = blk_fs_request(rq) ? NULL : rq->data;
+ int blen = rq->data_len;
+
+- /*
+- * bio backed?
+- */
++ /* bio backed? */
+ if (rq->bio) {
+ if (blk_fs_request(rq)) {
+ ptr = rq->buffer;
+@@ -1132,11 +1032,10 @@ 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.
++ * If the buffers are full, pipe the rest into
++ * oblivion.
+ */
+- cdrom_buffer_sectors(drive, rq->sector,
+- thislen >> 9);
++ ide_cd_drain_data(drive, thislen >> 9);
+ else {
+ printk(KERN_ERR "%s: confused, missing data\n",
+ drive->name);
+@@ -1150,7 +1049,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ if (blen > thislen)
+ blen = thislen;
+
+- xferfunc(drive, ptr, blen);
++ xferfunc(drive, NULL, ptr, blen);
+
+ thislen -= blen;
+ len -= blen;
+@@ -1182,9 +1081,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ rq->sense_len += blen;
+ }
+
+- /*
+- * pad, if necessary
+- */
++ /* pad, if necessary */
+ if (!blk_fs_request(rq) && len > 0)
+ ide_cd_pad_transfer(drive, xferfunc, len);
+
+@@ -1228,9 +1125,7 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
+ queue_hardsect_size(drive->queue) >> SECTOR_BITS;
+
+ if (write) {
+- /*
+- * disk has become write protected
+- */
++ /* disk has become write protected */
+ if (cd->disk->policy) {
+ cdrom_end_request(drive, 0);
+ return ide_stopped;
+@@ -1241,15 +1136,9 @@ 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);
-
-- if (dev->flags & ATA_DFLAG_FLUSH_EXT)
-- cmd = ATA_CMD_FLUSH_EXT;
-- else
-- cmd = ATA_CMD_FLUSH;
+- /* Satisfy whatever we can of this request from our cache. */
+- if (cdrom_read_from_buffer(drive))
+- return ide_stopped;
+ }
+
+- /*
+- * use DMA, if possible / writes *must* be hardware frame aligned
+- */
++ /* use DMA, if possible / writes *must* be hardware frame aligned */
+ if ((rq->nr_sectors & (sectors_per_frame - 1)) ||
+ (rq->sector & (sectors_per_frame - 1))) {
+ if (write) {
+@@ -1260,13 +1149,10 @@ 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;
-
-- /* 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;
-- }
+ if (write)
+ cd->devinfo.media_written = 1;
+
+- /* Start sending the read/write request to the drive. */
++ /* start sending the read/write request to the drive */
+ return cdrom_start_packet_command(drive, 32768, cdrom_start_rw_cont);
+ }
+
+@@ -1291,12 +1177,11 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
+
+ info->dma = 0;
+
+- /*
+- * sg request
+- */
++ /* sg request */
+ if (rq->bio) {
+ int mask = drive->queue->dma_alignment;
+- unsigned long addr = (unsigned long) page_address(bio_page(rq->bio));
++ unsigned long addr =
++ (unsigned long)page_address(bio_page(rq->bio));
+
+ info->dma = drive->using_dma;
+
+@@ -1310,15 +1195,16 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
+ info->dma = 0;
+ }
+
+- /* Start sending the command to the drive. */
+- return cdrom_start_packet_command(drive, rq->data_len, cdrom_do_newpc_cont);
++ /* start sending the command to the drive */
++ return cdrom_start_packet_command(drive, rq->data_len,
++ cdrom_do_newpc_cont);
+ }
+
+-/****************************************************************************
++/*
+ * cdrom driver request routine.
+ */
+-static ide_startstop_t
+-ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
++static ide_startstop_t 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;
+@@ -1330,16 +1216,21 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
+
+ if ((stat & SEEK_STAT) != SEEK_STAT) {
+ if (elapsed < IDECD_SEEK_TIMEOUT) {
+- ide_stall_queue(drive, IDECD_SEEK_TIMER);
++ 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;
+@@ -1347,9 +1238,7 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
+ rq->cmd_type == REQ_TYPE_ATA_PC) {
+ return cdrom_do_block_pc(drive, rq);
+ } else if (blk_special_request(rq)) {
+- /*
+- * right now this can only be a reset...
+- */
++ /* right now this can only be a reset... */
+ cdrom_end_request(drive, 1);
+ return ide_stopped;
+ }
+@@ -1361,18 +1250,16 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
+
+
+
+-/****************************************************************************
++/*
+ * Ioctl handling.
+ *
+- * Routines which queue packet commands take as a final argument a pointer
+- * to a request_sense struct. If execution of the command results
+- * in an error with a CHECK CONDITION status, this structure will be filled
+- * with the results of the subsequent request sense command. The pointer
+- * can also be NULL, in which case no sense information is returned.
++ * Routines which queue packet commands take as a final argument a pointer to a
++ * request_sense struct. If execution of the command results in an error with a
++ * CHECK CONDITION status, this structure will be filled with the results of the
++ * subsequent request sense command. The pointer can also be NULL, in which case
++ * no sense information is returned.
+ */
-
-- return 0;
+-static
+-void msf_from_bcd (struct atapi_msf *msf)
++static void msf_from_bcd(struct atapi_msf *msf)
+ {
+ msf->minute = BCD2BIN(msf->minute);
+ msf->second = BCD2BIN(msf->second);
+@@ -1392,8 +1279,8 @@ int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
+ req.cmd_flags |= REQ_QUIET;
+
+ /*
+- * Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to
+- * switch CDs instead of supporting the LOAD_UNLOAD opcode.
++ * Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to switch CDs
++ * instead of supporting the LOAD_UNLOAD opcode.
+ */
+ req.cmd[7] = cdi->sanyo_slot % 3;
+
+@@ -1469,36 +1356,39 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
+ unsigned long sectors_per_frame = SECTORS_PER_FRAME;
+
+ if (toc == NULL) {
+- /* Try to allocate space. */
++ /* 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;
+ }
+
+- /* Check to see if the existing data is still valid.
+- If it is, just return. */
++ /*
++ * Check to see if the existing data is still valid. If it is,
++ * just return.
++ */
+ (void) cdrom_check_status(drive, sense);
+
+ if (info->cd_flags & IDE_CD_FLAG_TOC_VALID)
+ return 0;
+
+- /* Try to get the total cdrom capacity and sector size. */
++ /* try to get the total cdrom capacity and sector size */
+ stat = cdrom_read_capacity(drive, &toc->capacity, §ors_per_frame,
+ sense);
+ if (stat)
+ toc->capacity = 0x1fffff;
+
+ set_capacity(info->disk, toc->capacity * sectors_per_frame);
+- /* Save a private copy of te TOC capacity for error handling */
++ /* save a private copy of the TOC capacity for error handling */
+ drive->probed_capacity = toc->capacity * sectors_per_frame;
+
+ blk_queue_hardsect_size(drive->queue,
+ sectors_per_frame << SECTOR_BITS);
+
+- /* First read just the header, so we know how long the TOC is. */
++ /* first read just the header, so we know how long the TOC is */
+ stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
+ sizeof(struct atapi_toc_header), sense);
+ if (stat)
+@@ -1515,7 +1405,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
+ if (ntracks > MAX_TRACKS)
+ ntracks = MAX_TRACKS;
+
+- /* Now read the whole schmeer. */
++ /* now read the whole schmeer */
+ stat = cdrom_read_tocentry(drive, toc->hdr.first_track, 1, 0,
+ (char *)&toc->hdr,
+ sizeof(struct atapi_toc_header) +
+@@ -1523,15 +1413,18 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
+ sizeof(struct atapi_toc_entry), sense);
+
+ if (stat && toc->hdr.first_track > 1) {
+- /* Cds with CDI tracks only don't have any TOC entries,
+- despite of this the returned values are
+- first_track == last_track = number of CDI tracks + 1,
+- so that this case is indistinguishable from the same
+- layout plus an additional audio track.
+- If we get an error for the regular case, we assume
+- a CDI without additional audio tracks. In this case
+- the readable TOC is empty (CDI tracks are not included)
+- and only holds the Leadout entry. Heiko EiÃfeldt */
++ /*
++ * Cds with CDI tracks only don't have any TOC entries, despite
++ * of this the returned values are
++ * first_track == last_track = number of CDI tracks + 1,
++ * so that this case is indistinguishable from the same layout
++ * plus an additional audio track. If we get an error for the
++ * regular case, we assume a CDI without additional audio
++ * tracks. In this case the readable TOC is empty (CDI tracks
++ * are not included) and only holds the Leadout entry.
++ *
++ * Heiko EiÃfeldt.
++ */
+ ntracks = 0;
+ stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0,
+ (char *)&toc->hdr,
+@@ -1567,14 +1460,13 @@ 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. */
+ if (toc->hdr.first_track != CDROM_LEADOUT) {
+- /* Read the multisession information. */
++ /* read the multisession information */
+ stat = cdrom_read_tocentry(drive, 0, 0, 1, (char *)&ms_tmp,
+ sizeof(ms_tmp), sense);
+ if (stat)
+@@ -1582,26 +1474,27 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
+
+ toc->last_session_lba = be32_to_cpu(ms_tmp.ent.addr.lba);
+ } else {
+- ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT;
++ ms_tmp.hdr.last_track = CDROM_LEADOUT;
++ ms_tmp.hdr.first_track = ms_tmp.hdr.last_track;
+ toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */
+ }
+
+ if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
+- /* Re-read multisession information using MSF format */
++ /* re-read multisession information using MSF format */
+ stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
+ sizeof(ms_tmp), 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);
+ }
+
+ toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
+
+- /* Now try to get the total cdrom capacity. */
++ /* now try to get the total cdrom capacity */
+ stat = cdrom_get_last_written(cdi, &last_written);
+ if (!stat && (last_written > toc->capacity)) {
+ toc->capacity = last_written;
+@@ -1626,7 +1519,8 @@ int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
+ size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
+
+ init_cdrom_command(&cgc, buf, size, CGC_DATA_UNKNOWN);
+- do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
++ do {
++ /* we seem to get stat=0x01,err=0x00 the first time (??) */
+ stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
+ if (!stat)
+ break;
+@@ -1677,7 +1571,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;
+@@ -1695,8 +1589,7 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
+ return register_cdrom(devinfo);
+ }
+
+-static
+-int ide_cdrom_probe_capabilities (ide_drive_t *drive)
++static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
+ {
+ struct cdrom_info *cd = drive->driver_data;
+ struct cdrom_device_info *cdi = &cd->devinfo;
+@@ -1710,7 +1603,8 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
+
+ if (drive->media == ide_optical) {
+ cdi->mask &= ~(CDC_MO_DRIVE | CDC_RAM);
+- printk(KERN_ERR "%s: ATAPI magneto-optical drive\n", drive->name);
++ printk(KERN_ERR "%s: ATAPI magneto-optical drive\n",
++ drive->name);
+ return nslots;
+ }
+
+@@ -1721,11 +1615,10 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
+ }
+
+ /*
+- * we have to cheat a little here. the packet will eventually
+- * be queued with ide_cdrom_packet(), which extracts the
+- * drive from cdi->handle. Since this device hasn't been
+- * registered with the Uniform layer yet, it can't do this.
+- * Same goes for cdi->ops.
++ * We have to cheat a little here. the packet will eventually be queued
++ * with ide_cdrom_packet(), which extracts the drive from cdi->handle.
++ * Since this device hasn't been registered with the Uniform layer yet,
++ * it can't do this. Same goes for cdi->ops.
+ */
+ cdi->handle = drive;
+ cdi->ops = &ide_cdrom_dops;
+@@ -1794,25 +1687,14 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
+ return nslots;
+ }
+
+-#ifdef CONFIG_IDE_PROC_FS
+-static void ide_cdrom_add_settings(ide_drive_t *drive)
+-{
+- ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL);
-}
+-#else
+-static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; }
+-#endif
-
- #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)
+-/*
+- * standard prep_rq_fn that builds 10 byte cmds
+- */
++/* standard prep_rq_fn that builds 10 byte cmds */
+ static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq)
{
-- 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;
+ int hard_sect = queue_hardsect_size(q);
+ long block = (long)rq->hard_sector / (hard_sect >> 9);
+ unsigned long blocks = rq->hard_nr_sectors / (hard_sect >> 9);
-@@ -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
+- memset(rq->cmd, 0, sizeof(rq->cmd));
++ memset(rq->cmd, 0, BLK_MAX_CDB);
-+#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 (rq_data_dir(rq) == READ)
+ rq->cmd[0] = GPCMD_READ_10;
+@@ -1844,9 +1726,7 @@ static int ide_cdrom_prep_pc(struct request *rq)
+ {
+ u8 *c = rq->cmd;
- 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;
+- /*
+- * Transform 6-byte read/write commands to the 10-byte version
+- */
++ /* transform 6-byte read/write commands to the 10-byte version */
+ if (c[0] == READ_6 || c[0] == WRITE_6) {
+ c[8] = c[4];
+ c[5] = c[3];
+@@ -1868,7 +1748,7 @@ static int ide_cdrom_prep_pc(struct request *rq)
+ rq->errors = ILLEGAL_REQUEST;
+ return BLKPREP_KILL;
}
-
- return host;
-@@ -6985,6 +5374,56 @@ static void ata_host_stop(struct device *gendev, void *res)
+-
++
+ return BLKPREP_OK;
}
- /**
-+ * 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)
+@@ -1888,6 +1768,41 @@ struct cd_list_entry {
+ unsigned int cd_flags;
+ };
+
++#ifdef CONFIG_IDE_PROC_FS
++static sector_t ide_cdrom_capacity(ide_drive_t *drive)
+{
-+ 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;
++ unsigned long capacity, sectors_per_frame;
+
-+ spin_lock(&lock);
++ if (cdrom_read_capacity(drive, &capacity, §ors_per_frame, NULL))
++ return 0;
+
-+ for (cur = ops->inherits; cur; cur = cur->inherits) {
-+ void **inherit = (void **)cur;
++ return capacity * sectors_per_frame;
++}
+
-+ for (pp = begin; pp < end; pp++, inherit++)
-+ if (!*pp)
-+ *pp = *inherit;
-+ }
++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;
+
-+ for (pp = begin; pp < end; pp++)
-+ if (IS_ERR(*pp))
-+ *pp = NULL;
++ len = sprintf(page, "%llu\n", (long long)ide_cdrom_capacity(drive));
++ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
++}
+
-+ ops->inherits = NULL;
++static ide_proc_entry_t idecd_proc[] = {
++ { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL },
++ { NULL, 0, NULL, NULL }
++};
+
-+ spin_unlock(&lock);
++static void ide_cdrom_add_settings(ide_drive_t *drive)
++{
++ ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
++ &drive->dsc_overlap, NULL);
+}
++#else
++static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; }
++#endif
+
-+/**
- * 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;
+ static const struct cd_list_entry ide_cd_quirks_list[] = {
+ /* Limit transfer size per interrupt. */
+ { "SAMSUNG CD-ROM SCR-2430", NULL, IDE_CD_FLAG_LIMIT_NFRAMES },
+@@ -1945,8 +1860,7 @@ static unsigned int ide_cd_flags(struct hd_driveid *id)
+ return 0;
+ }
-+ ata_finalize_port_ops(host->ops);
-+
- for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap = host->ports[i];
+-static
+-int ide_cdrom_setup (ide_drive_t *drive)
++static int ide_cdrom_setup(ide_drive_t *drive)
+ {
+ struct cdrom_info *cd = drive->driver_data;
+ struct cdrom_device_info *cdi = &cd->devinfo;
+@@ -1975,21 +1889,19 @@ int ide_cdrom_setup (ide_drive_t *drive)
+ id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
+ cd->cd_flags |= IDE_CD_FLAG_TOCTRACKS_AS_BCD;
+ else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD)
+- cdi->sanyo_slot = 3; /* 3 => use CD in slot 0 */
++ /* 3 => use CD in slot 0 */
++ cdi->sanyo_slot = 3;
-+ ata_finalize_port_ops(ap->ops);
-+
- if (!host->ops && !ata_port_is_dummy(ap))
- host->ops = ap->ops;
+- nslots = ide_cdrom_probe_capabilities (drive);
++ nslots = ide_cdrom_probe_capabilities(drive);
-@@ -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);
+- /*
+- * set correct block size
+- */
++ /* set correct block size */
+ blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE);
-- 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;
+- if (drive->autotune == IDE_TUNE_DEFAULT ||
+- drive->autotune == IDE_TUNE_AUTO)
+- drive->dsc_overlap = (drive->next != drive);
++ drive->dsc_overlap = (drive->next != drive);
- ap->pflags &= ~ATA_PFLAG_INITIALIZING;
-@@ -7336,33 +5778,6 @@ void ata_host_detach(struct ata_host *host)
- ata_acpi_dissociate(host);
+ 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: %s failed to register device with the"
++ " cdrom driver.\n", drive->name, __func__);
+ cd->devinfo.handle = NULL;
+ return 1;
+ }
+@@ -1997,19 +1909,6 @@ int ide_cdrom_setup (ide_drive_t *drive)
+ return 0;
}
--/**
-- * 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)
+-#ifdef CONFIG_IDE_PROC_FS
+-static
+-sector_t ide_cdrom_capacity (ide_drive_t *drive)
-{
-- 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;
--}
+- unsigned long capacity, sectors_per_frame;
-
+- if (cdrom_read_capacity(drive, &capacity, §ors_per_frame, NULL))
+- return 0;
-
- #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) { }
+- return capacity * sectors_per_frame;
+-}
+-#endif
-
--static u8 ata_dummy_check_status(struct ata_port *ap)
-+static unsigned int ata_dummy_qc_issue(struct ata_queued_cmd *qc)
+ static void ide_cd_remove(ide_drive_t *drive)
{
-- return ATA_DRDY;
-+ return AC_ERR_SYSTEM;
- }
+ struct cdrom_info *info = drive->driver_data;
+@@ -2028,11 +1927,9 @@ static void ide_cd_release(struct kref *kref)
+ ide_drive_t *drive = info->drive;
+ struct gendisk *g = info->disk;
--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 */
- }
+- 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);
+@@ -2043,23 +1940,6 @@ static void ide_cd_release(struct kref *kref)
--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,
+ static int ide_cd_probe(ide_drive_t *);
+
+-#ifdef CONFIG_IDE_PROC_FS
+-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);
+-}
+-
+-static ide_proc_entry_t idecd_proc[] = {
+- { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL },
+- { NULL, 0, NULL, NULL }
+-};
+-#endif
+-
+ static ide_driver_t ide_cdrom_driver = {
+ .gen_driver = {
+ .owner = THIS_MODULE,
+@@ -2080,20 +1960,17 @@ static ide_driver_t ide_cdrom_driver = {
+ #endif
};
- 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);
+-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;
- #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 */
+- if (!(info = ide_cd_get(disk)))
++ info = ide_cd_get(disk);
++ if (!info)
+ return -ENXIO;
--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);
+- if (!info->buffer)
+- info->buffer = kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL|__GFP_REPEAT);
-
- 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);
+- if (info->buffer)
+- rc = cdrom_open(&info->devinfo, inode, file);
++ rc = cdrom_open(&info->devinfo, inode, file);
- 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 (rc < 0)
+ ide_cd_put(info);
+@@ -2101,12 +1978,12 @@ static int idecd_open(struct inode * inode, struct file * file)
+ return rc;
+ }
-- 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,
+-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);
- spin_lock_irqsave(ap->lock, flags);
+- cdrom_release (&info->devinfo, file);
++ cdrom_release(&info->devinfo, file);
-- /* 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);
+ ide_cd_put(info);
- if (!(ehc->i.flags & ATA_EHI_QUIET))
-@@ -1117,12 +1104,6 @@ void ata_eh_done(struct ata_link *link, struct ata_device *dev,
+@@ -2138,7 +2015,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 +2024,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 ata_eh_context *ehc = &link->eh_context;
+ struct block_device *bdev = inode->i_bdev;
+@@ -2160,13 +2037,13 @@ static int idecd_ioctl (struct inode *inode, struct file *file,
+ int err;
-- /* 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);
+ 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 +2069,16 @@ static int idecd_revalidate_disk(struct gendisk *disk)
}
-@@ -1329,20 +1310,20 @@ static void ata_eh_analyze_serror(struct ata_link *link)
+ 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
+ };
- 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;
+-/* options */
+-static char *ignore = NULL;
++/* module options */
++static char *ignore;
+
+ module_param(ignore, charp, 0400);
+ MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
+@@ -2221,17 +2098,20 @@ static int ide_cd_probe(ide_drive_t *drive)
+ /* skip drives that we were told to ignore */
+ if (ignore != NULL) {
+ if (strstr(ignore, drive->name)) {
+- printk(KERN_INFO "ide-cd: ignoring drive %s\n", drive->name);
++ printk(KERN_INFO "ide-cd: ignoring drive %s\n",
++ drive->name);
+ goto failed;
+ }
}
- if (serror & SERR_PROTOCOL) {
- err_mask |= AC_ERR_HSM;
-- action |= ATA_EH_SOFTRESET;
-+ action |= ATA_EH_RESET;
+ if (drive->scsi) {
+- printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name);
++ printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi "
++ "emulation.\n", drive->name);
+ goto failed;
}
- if (serror & SERR_INTERNAL) {
- err_mask |= AC_ERR_SYSTEM;
-- action |= ATA_EH_HARDRESET;
-+ action |= ATA_EH_RESET;
+ info = kzalloc(sizeof(struct cdrom_info), GFP_KERNEL);
+ if (info == NULL) {
+- printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name);
++ printk(KERN_ERR "%s: Can't allocate a cdrom structure\n",
++ drive->name);
+ goto failed;
}
- /* 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,
+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 {
- if ((stat & (ATA_BUSY | ATA_DRQ | ATA_DRDY)) != ATA_DRDY) {
- qc->err_mask |= AC_ERR_HSM;
-- return ATA_EH_SOFTRESET;
-+ return ATA_EH_RESET;
- }
+ struct atapi_toc *toc;
- if (stat & (ATA_ERR | ATA_DF))
-@@ -1484,7 +1466,7 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
+- 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-cd_verbose.c b/drivers/ide/ide-cd_verbose.c
+index 6ed7ca0..6490a2d 100644
+--- a/drivers/ide/ide-cd_verbose.c
++++ b/drivers/ide/ide-cd_verbose.c
+@@ -326,7 +326,7 @@ void ide_cd_log_error(const char *name, struct request *failed_command,
+
+ printk(KERN_ERR " The failed \"%s\" packet command "
+ "was: \n \"", s);
+- for (i = 0; i < sizeof(failed_command->cmd); i++)
++ for (i = 0; i < BLK_MAX_CDB; i++)
+ printk(KERN_CONT "%02x ", failed_command->cmd[i]);
+ printk(KERN_CONT "\"\n");
}
+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 @@
- if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS))
-- action |= ATA_EH_SOFTRESET;
-+ action |= ATA_EH_RESET;
+ #define IDEDISK_VERSION "1.18"
- 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;
+-//#define DEBUG
+-
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/string.h>
+@@ -88,7 +86,7 @@ static void ide_disk_put(struct ide_disk_obj *idkp)
+ *
+ * It is called only once for each drive.
+ */
+-static int lba_capacity_is_ok (struct hd_driveid *id)
++static int lba_capacity_is_ok(struct hd_driveid *id)
+ {
+ unsigned long lba_sects, chs_sects, head, tail;
+
+@@ -176,7 +174,8 @@ static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
+ * __ide_do_rw_disk() issues READ and WRITE commands to a disk,
+ * using LBA if supported, or CHS otherwise, to address sectors.
+ */
+-static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block)
++static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
++ sector_t block)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
+ unsigned int dma = drive->using_dma;
+@@ -228,7 +227,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
+ tf->device = (block >> 8) & 0xf;
}
+ } else {
+- unsigned int sect,head,cyl,track;
++ unsigned int sect, head, cyl, track;
++
+ track = (int)block / drive->sect;
+ sect = (int)block % drive->sect + 1;
+ head = track % drive->head;
+@@ -271,7 +271,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
+ * 1073741822 == 549756 MB or 48bit addressing fake drive
+ */
-@@ -1705,7 +1687,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
- dev->spdn_cnt++;
+-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);
- 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;
+@@ -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)
}
+ }
-@@ -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);
+-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;
-+ /* 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;
+ 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");
+
- /* 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);
++ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
}
-@@ -2066,41 +2053,29 @@ static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset,
- classes[dev->devno] = ATA_DEV_UNKNOWN;
+ 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;
- rc = reset(link, classes, deadline);
-- if (rc)
-- return rc;
+- 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);
+ }
-- /* 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;
-- }
+-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;
- }
-+ if (classes[dev->devno] == ATA_DEV_UNKNOWN)
-+ classes[dev->devno] = ATA_DEV_NONE;
+- 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);
+ }
-- return 0;
-+ return rc;
+ 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;
}
- static int ata_eh_followup_srst_needed(struct ata_link *link,
- int rc, int classify,
- const unsigned int *classes)
+@@ -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)
{
-- 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)
+ 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 ((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;
+
+ if (!idedisk_supports_lba48(drive->id))
+- return -EIO;
++ return -EIO;
+ drive->addressing = arg;
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);
+@@ -763,23 +764,35 @@ static void idedisk_add_settings(ide_drive_t *drive)
+ {
+ struct hd_driveid *id = drive->id;
-- ata_eh_about_to_do(link, NULL, ehc->i.action & ATA_EH_RESET_MASK);
-+ ata_eh_about_to_do(link, NULL, ATA_EH_RESET);
+- 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
- 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;
+-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;
+- }
}
-- /* Determine which reset to use and record in ehc->i.action.
-- * prereset() may examine and modify it.
-- */
-- if (softreset && (!hardreset || (!(lflags & ATA_LFLAG_NO_SRST) &&
-- !sata_set_spd_needed(link) &&
-- !(ehc->i.action & ATA_EH_HARDRESET))))
-- tmp_action = ATA_EH_SOFTRESET;
-- else
-- tmp_action = ATA_EH_HARDRESET;
--
-- ehc->i.action = (ehc->i.action & ~ATA_EH_RESET_MASK) | tmp_action;
-+ /* prefer hardreset */
-+ ehc->i.action &= ~ATA_EH_RESET;
-+ if (hardreset) {
-+ reset = hardreset;
-+ ehc->i.action = ATA_EH_HARDRESET;
-+ } else if (softreset) {
-+ reset = softreset;
-+ ehc->i.action = ATA_EH_SOFTRESET;
-+ } else {
-+ ata_link_printk(link, KERN_ERR, "BUG: no reset method, "
-+ "please report to linux-ide at vger.kernel.org\n");
-+ dump_stack();
-+ return -EINVAL;
-+ }
+ (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);
+ }
- 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;
+- 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);
- 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,
- }
- }
+ /* calculate drive capacity, and select LBA if possible */
+- init_idedisk_capacity (drive);
++ init_idedisk_capacity(drive);
-- /* 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;
+ /* 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) {
-- /* 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++];
+ 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;
-@@ -2240,7 +2205,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
- goto fail;
- }
+- if (!(idkp = ide_disk_get(disk)))
++ idkp = ide_disk_get(disk);
++ if (idkp == NULL)
+ return -ENXIO;
-- 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);
- }
+ drive = idkp->drive;
+@@ -1115,13 +1130,13 @@ static int idedisk_revalidate_disk(struct gendisk *disk)
+ }
-@@ -2248,21 +2213,6 @@ int ata_eh_reset(struct ata_link *link, int classify,
- if (rc && rc != -EAGAIN)
- goto fail;
+ 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
+ };
-- /* 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);
+ MODULE_DESCRIPTION("ATA DISK Driver");
+@@ -1184,7 +1199,7 @@ failed:
+ return -ENODEV;
+ }
- /* 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;
+-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..653b1ad 100644
+--- a/drivers/ide/ide-dma.c
++++ b/drivers/ide/ide-dma.c
+@@ -102,7 +102,7 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive)
+ {
+ u8 stat = 0, dma_stat = 0;
- rc = 0;
-@@ -2305,6 +2255,11 @@ int ata_eh_reset(struct ata_link *link, int classify,
- return rc;
+- dma_stat = HWIF(drive)->ide_dma_end(drive);
++ dma_stat = drive->hwif->dma_ops->dma_end(drive);
+ stat = ide_read_status(drive);
- 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;
+ if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
+@@ -394,7 +394,7 @@ void ide_dma_off_quietly(ide_drive_t *drive)
+ drive->using_dma = 0;
+ ide_toggle_bounce(drive, 0);
-@@ -2515,6 +2470,7 @@ static int ata_link_nr_vacant(struct ata_link *link)
+- drive->hwif->dma_host_set(drive, 0);
++ drive->hwif->dma_ops->dma_host_set(drive, 0);
+ }
- 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;
+ EXPORT_SYMBOL(ide_dma_off_quietly);
+@@ -427,7 +427,7 @@ void ide_dma_on(ide_drive_t *drive)
+ drive->using_dma = 1;
+ ide_toggle_bounce(drive, 1);
-@@ -2522,9 +2478,13 @@ static int ata_eh_skip_recovery(struct ata_link *link)
- if (link->flags & ATA_LFLAG_DISABLED)
- return 1;
+- drive->hwif->dma_host_set(drive, 1);
++ drive->hwif->dma_ops->dma_host_set(drive, 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;
+ #ifdef CONFIG_BLK_DEV_IDEDMA_SFF
+@@ -464,9 +464,10 @@ int ide_dma_setup(ide_drive_t *drive)
- /* 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);
+ /* PRD table */
+ if (hwif->mmio)
+- writel(hwif->dmatable_dma, (void __iomem *)hwif->dma_prdtable);
++ writel(hwif->dmatable_dma,
++ (void __iomem *)(hwif->dma_base + ATA_DMA_TABLE_OFS));
+ else
+- outl(hwif->dmatable_dma, hwif->dma_prdtable);
++ outl(hwif->dmatable_dma, hwif->dma_base + ATA_DMA_TABLE_OFS);
-@@ -2592,12 +2552,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
+ /* specify r/w */
+ hwif->OUTB(reading, hwif->dma_command);
+@@ -482,11 +483,12 @@ int ide_dma_setup(ide_drive_t *drive)
+
+ EXPORT_SYMBOL_GPL(ide_dma_setup);
+
+-static void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
++void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
+ {
+ /* issue cmd to drive */
+ ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
+ }
++EXPORT_SYMBOL_GPL(ide_dma_exec_cmd);
+
+ void ide_dma_start(ide_drive_t *drive)
+ {
+@@ -532,7 +534,7 @@ int __ide_dma_end (ide_drive_t *drive)
+ EXPORT_SYMBOL(__ide_dma_end);
+ /* returns 1 if dma irq issued, 0 otherwise */
+-static int __ide_dma_test_irq(ide_drive_t *drive)
++int ide_dma_test_irq(ide_drive_t *drive)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
+ u8 dma_stat = hwif->INB(hwif->dma_status);
+@@ -542,9 +544,10 @@ static int __ide_dma_test_irq(ide_drive_t *drive)
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;
- }
+ if (!drive->waiting_for_dma)
+ printk(KERN_WARNING "%s: (%s) called while not waiting\n",
+- drive->name, __FUNCTION__);
++ drive->name, __func__);
+ return 0;
}
-@@ -2690,7 +2645,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
- ehc->i.action = 0;
++EXPORT_SYMBOL_GPL(ide_dma_test_irq);
+ #else
+ static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; }
+ #endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
+@@ -574,6 +577,7 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
+ {
+ struct hd_driveid *id = drive->id;
+ ide_hwif_t *hwif = drive->hwif;
++ const struct ide_port_ops *port_ops = hwif->port_ops;
+ unsigned int mask = 0;
- /* do we need to reset? */
-- if (ehc->i.action & ATA_EH_RESET_MASK)
-+ if (ehc->i.action & ATA_EH_RESET)
- reset = 1;
+ switch(base) {
+@@ -581,8 +585,8 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
+ if ((id->field_valid & 4) == 0)
+ break;
- 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);
+- if (hwif->udma_filter)
+- mask = hwif->udma_filter(drive);
++ if (port_ops && port_ops->udma_filter)
++ mask = port_ops->udma_filter(drive);
+ else
+ mask = hwif->ultra_mask;
+ mask &= id->dma_ultra;
+@@ -598,8 +602,8 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
+ case XFER_MW_DMA_0:
+ if ((id->field_valid & 2) == 0)
+ break;
+- if (hwif->mdma_filter)
+- mask = hwif->mdma_filter(drive);
++ if (port_ops && port_ops->mdma_filter)
++ mask = port_ops->mdma_filter(drive);
+ else
+ mask = hwif->mwdma_mask;
+ mask &= id->dma_mword;
+@@ -703,17 +707,8 @@ static int ide_tune_dma(ide_drive_t *drive)
- ata_port_for_each_link(link, ap) {
- struct ata_eh_context *ehc = &link->eh_context;
+ speed = ide_max_dma_mode(drive);
-- if (!(ehc->i.action & ATA_EH_RESET_MASK))
-+ if (!(ehc->i.action & ATA_EH_RESET))
- continue;
+- 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;
- 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 (ide_set_dma_mode(drive, speed))
+ return 0;
+@@ -810,15 +805,15 @@ void ide_dma_timeout (ide_drive_t *drive)
-- if (!ap->nr_pmp_links)
-+ if (!sata_pmp_attached(ap))
- ata_eh_thaw_port(ap);
- }
+ printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
-@@ -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);
+- if (hwif->ide_dma_test_irq(drive))
++ if (hwif->dma_ops->dma_test_irq(drive))
+ return;
+
+- hwif->ide_dma_end(drive);
++ hwif->dma_ops->dma_end(drive);
}
-+/**
-+ * ata_std_error_handler - standard error handler
-+ * @ap: host port to handle error for
-+ *
-+ * Standard error handler
-+ *
-+ * LOCKING:
-+ * Kernel thread context (may sleep).
-+ */
-+void ata_std_error_handler(struct ata_port *ap)
-+{
-+ struct ata_port_operations *ops = ap->ops;
-+ ata_reset_fn_t hardreset = ops->hardreset;
-+
-+ /* ignore built-in hardreset if SCR access is not available */
-+ if (ata_is_builtin_hardreset(hardreset) && !sata_scr_valid(&ap->link))
-+ hardreset = NULL;
-+
-+ ata_do_eh(ap, ops->prereset, ops->softreset, hardreset, ops->postreset);
-+}
-+
- #ifdef CONFIG_PM
- /**
- * ata_eh_handle_port_suspend - perform port suspend operation
-diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
-index d91f509..ff1822a 100644
---- a/drivers/ata/libata-pmp.c
-+++ b/drivers/ata/libata-pmp.c
-@@ -11,6 +11,14 @@
- #include <linux/libata.h>
- #include "libata.h"
+ EXPORT_SYMBOL(ide_dma_timeout);
-+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)
+-static void ide_release_dma_engine(ide_hwif_t *hwif)
++void ide_release_dma_engine(ide_hwif_t *hwif)
+ {
+ if (hwif->dmatable_cpu) {
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
+@@ -829,28 +824,7 @@ static void ide_release_dma_engine(ide_hwif_t *hwif)
+ }
}
- /**
-- * 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.
+-static int ide_release_iomio_dma(ide_hwif_t *hwif)
+-{
+- release_region(hwif->dma_base, 8);
+- if (hwif->extra_ports)
+- release_region(hwif->extra_base, hwif->extra_ports);
+- return 1;
+-}
+-
+-/*
+- * Needed for allowing full modular support of ide-driver
- */
--int sata_pmp_std_prereset(struct ata_link *link, unsigned long deadline)
+-int ide_release_dma(ide_hwif_t *hwif)
-{
-- struct ata_eh_context *ehc = &link->eh_context;
-- const unsigned long *timing = sata_ehc_deb_timing(ehc);
-- int rc;
+- ide_release_dma_engine(hwif);
-
-- /* force HRST? */
-- if (link->flags & ATA_LFLAG_NO_SRST)
-- ehc->i.action |= ATA_EH_HARDRESET;
+- if (hwif->mmio)
+- return 1;
+- else
+- return ide_release_iomio_dma(hwif);
+-}
-
-- /* handle link resume */
-- if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
-- (link->flags & ATA_LFLAG_HRST_TO_RESUME))
-- ehc->i.action |= ATA_EH_HARDRESET;
+-static int ide_allocate_dma_engine(ide_hwif_t *hwif)
++int ide_allocate_dma_engine(ide_hwif_t *hwif)
+ {
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
+
+@@ -862,99 +836,33 @@ static int ide_allocate_dma_engine(ide_hwif_t *hwif)
+ return 0;
+
+ printk(KERN_ERR "%s: -- Error, unable to allocate DMA table.\n",
+- hwif->cds->name);
++ hwif->name);
+
+ return 1;
+ }
-
-- /* if we're about to do hardreset, nothing more to do */
-- if (ehc->i.action & ATA_EH_HARDRESET)
-- return 0;
+-static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base)
+-{
+- printk(KERN_INFO " %s: MMIO-DMA ", hwif->name);
-
-- /* 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;
+- return 0;
+-}
+-
+-static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base)
+-{
+- printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx",
+- hwif->name, base, base + 7);
+-
+- if (!request_region(base, 8, hwif->name)) {
+- printk(" -- Error, ports in use.\n");
+- return 1;
- }
-
-- /* 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;
+- if (hwif->cds->extra) {
+- hwif->extra_base = base + (hwif->channel ? 8 : 16);
+-
+- if (!hwif->mate || !hwif->mate->extra_ports) {
+- if (!request_region(hwif->extra_base,
+- hwif->cds->extra, hwif->cds->name)) {
+- printk(" -- Error, extra ports in use.\n");
+- release_region(base, 8);
+- return 1;
+- }
+- hwif->extra_ports = hwif->cds->extra;
+- }
- }
-
- 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)
+-static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base)
-{
-- const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
-- u32 tmp;
-- int rc;
+- if (hwif->mmio)
+- return ide_mapped_mmio_dma(hwif, base);
-
-- DPRINTK("ENTER\n");
+- return ide_iomio_dma(hwif, base);
+-}
++EXPORT_SYMBOL_GPL(ide_allocate_dma_engine);
++
++static const struct ide_dma_ops sff_dma_ops = {
++ .dma_host_set = ide_dma_host_set,
++ .dma_setup = ide_dma_setup,
++ .dma_exec_cmd = ide_dma_exec_cmd,
++ .dma_start = ide_dma_start,
++ .dma_end = __ide_dma_end,
++ .dma_test_irq = ide_dma_test_irq,
++ .dma_timeout = ide_dma_timeout,
++ .dma_lost_irq = ide_dma_lost_irq,
++};
+
+ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base)
+ {
+- u8 dma_stat;
-
-- /* 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;
-- }
+- if (ide_dma_iobase(hwif, base))
+- return;
-
-- /* 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 (ide_allocate_dma_engine(hwif)) {
+- ide_release_dma(hwif);
+- return;
- }
-
-- /* 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;
+ hwif->dma_base = base;
+
+ if (!hwif->dma_command)
+ hwif->dma_command = hwif->dma_base + 0;
+- if (!hwif->dma_vendor1)
+- hwif->dma_vendor1 = hwif->dma_base + 1;
+ if (!hwif->dma_status)
+ hwif->dma_status = hwif->dma_base + 2;
+- if (!hwif->dma_vendor3)
+- hwif->dma_vendor3 = hwif->dma_base + 3;
+- if (!hwif->dma_prdtable)
+- hwif->dma_prdtable = hwif->dma_base + 4;
+-
+- if (!hwif->dma_host_set)
+- hwif->dma_host_set = &ide_dma_host_set;
+- if (!hwif->dma_setup)
+- hwif->dma_setup = &ide_dma_setup;
+- if (!hwif->dma_exec_cmd)
+- hwif->dma_exec_cmd = &ide_dma_exec_cmd;
+- if (!hwif->dma_start)
+- hwif->dma_start = &ide_dma_start;
+- if (!hwif->ide_dma_end)
+- hwif->ide_dma_end = &__ide_dma_end;
+- if (!hwif->ide_dma_test_irq)
+- hwif->ide_dma_test_irq = &__ide_dma_test_irq;
+- if (!hwif->dma_timeout)
+- hwif->dma_timeout = &ide_dma_timeout;
+- if (!hwif->dma_lost_irq)
+- hwif->dma_lost_irq = &ide_dma_lost_irq;
+
+- dma_stat = hwif->INB(hwif->dma_status);
+- printk(KERN_CONT ", BIOS settings: %s:%s, %s:%s\n",
+- hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "PIO",
+- hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "PIO");
++ hwif->dma_ops = &sff_dma_ops;
+ }
+
+ EXPORT_SYMBOL_GPL(ide_setup_dma);
+diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
+index faf22d7..f05fbc2 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;
-
-- DPRINTK("EXIT, rc=%d\n", rc);
-- return rc;
--}
+-/* 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),
+-};
-
--/**
-- * 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)
+ /* 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.
- */
--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);
+-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
+-};
-
-- /* print link status */
-- sata_print_link_status(link);
+-/*
+ * 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);
+-}
-
-- DPRINTK("EXIT\n");
+-static void idefloppy_write_zeros(ide_drive_t *drive, unsigned int bcount)
+-{
+- while (bcount--)
+- HWIF(drive)->OUTB(0, IDE_DATA_REG);
-}
-
--/**
- * 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;
+-
+-/*
+ * 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,9 +228,10 @@ static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs)
+ return 0;
+ }
- 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;
+-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)
+ {
++ ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = pc->rq;
+ struct req_iterator iter;
+ struct bio_vec *bvec;
+@@ -323,9 +247,9 @@ static void ide_floppy_io_buffers(ide_drive_t *drive, idefloppy_pc_t *pc,
+
+ data = bvec_kmap_irq(bvec, &flags);
+ if (direction)
+- drive->hwif->atapi_output_bytes(drive, data, count);
++ hwif->output_data(drive, NULL, data, count);
+ else
+- drive->hwif->atapi_input_bytes(drive, data, count);
++ hwif->input_data(drive, NULL, data, count);
+ bvec_kunmap_irq(data, &flags);
+
+ bcount -= count;
+@@ -333,26 +257,23 @@ static void ide_floppy_io_buffers(ide_drive_t *drive, idefloppy_pc_t *pc,
+ done += count;
}
- 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;
+- 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);
+- else
+- idefloppy_discard_data(drive, bcount);
-
- /* 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;
++ ide_pad_transfer(drive, direction, bcount);
}
}
-@@ -554,7 +411,7 @@ int sata_pmp_attach(struct ata_device *dev)
- int rc;
+-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;
- /* 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;
+ while ((bio = rq->bio) != NULL)
+- idefloppy_do_end_request(drive, 1, 0);
++ idefloppy_end_request(drive, 1, 0);
+ }
-- if (ehc->i.action & ATA_EH_RESET_MASK) {
-+ if (ehc->i.action & ATA_EH_RESET) {
- struct ata_link *tlink;
+ /*
+@@ -360,7 +281,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 +293,7 @@ static void idefloppy_queue_pc_head(ide_drive_t *drive, idefloppy_pc_t *pc,
+ (void) ide_do_drive_cmd(drive, rq, ide_preempt);
+ }
- ata_eh_freeze_port(ap);
+-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;
- /* 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);
+@@ -393,7 +314,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;
- /* 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;
-+ }
+ debug_log("Reached %s\n", __func__);
+
+@@ -418,11 +339,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);
}
+ }
- /* If revalidation is requested, revalidate and reconfigure;
-@@ -874,7 +734,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
- tries--;
+@@ -433,27 +354,27 @@ static void idefloppy_pc_callback(ide_drive_t *drive)
- 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;
+ debug_log("Reached %s\n", __func__);
- 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);
+- idefloppy_do_end_request(drive, floppy->pc->error ? 0 : 1, 0);
++ idefloppy_end_request(drive, floppy->pc->error ? 0 : 1, 0);
+ }
- /* 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 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 +383,7 @@ static void idefloppy_create_request_sense_cmd(idefloppy_pc_t *pc)
*/
--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)
+ static void idefloppy_retry_pc(ide_drive_t *drive)
{
-+ 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,
+- idefloppy_pc_t *pc;
++ struct ide_atapi_pc *pc;
+ struct request *rq;
- 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,
+ (void)ide_read_error(drive);
+@@ -473,11 +394,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;
+@@ -488,13 +409,13 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+ debug_log("Reached %s interrupt handler\n", __func__);
+
+ if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
+- dma_error = hwif->ide_dma_end(drive);
++ dma_error = hwif->dma_ops->dma_end(drive);
+ if (dma_error) {
+ printk(KERN_ERR "%s: DMA %s error\n", drive->name,
+ 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 +427,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 +450,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;
}
- /* 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;
+@@ -542,10 +463,10 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+ }
-@@ -1060,8 +907,8 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
- goto pmp_fail;
+ /* 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.lbah_addr) << 8) |
++ hwif->INB(hwif->io_ports.lbam_addr);
+ /* on this interrupt */
+- ireason = hwif->INB(IDE_IREASON_REG);
++ ireason = hwif->INB(hwif->io_ports.nsect_addr);
- /* 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;
+ if (ireason & CD) {
+ printk(KERN_ERR "ide-floppy: CoD != 0 in %s\n", __func__);
+@@ -561,13 +482,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_pad_transfer(drive, 0, bcount);
-@@ -1124,7 +971,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+ ide_set_handler(drive,
+ &idefloppy_pc_intr,
+@@ -580,19 +501,19 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+ }
+ }
+ if (pc->flags & PC_FLAG_WRITING)
+- xferfunc = hwif->atapi_output_bytes;
++ xferfunc = hwif->output_data;
+ else
+- xferfunc = hwif->atapi_input_bytes;
++ xferfunc = hwif->input_data;
- 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;
+- if (pc->buffer)
+- xferfunc(drive, pc->current_position, bcount);
++ if (pc->buf)
++ xferfunc(drive, NULL, 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 +527,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 +537,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.nsect_addr);
+ if ((ireason & CD) == 0 || (ireason & IO)) {
+ printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while "
+ "issuing a packet command\n");
+@@ -624,8 +546,10 @@ static ide_startstop_t idefloppy_transfer_pc(ide_drive_t *drive)
-@@ -1136,13 +983,13 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
- if (ap->pflags & ATA_PFLAG_UNLOADING)
- return rc;
+ /* Set the interrupt routine */
+ ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);
++
+ /* Send the actual packet */
+- HWIF(drive)->atapi_output_bytes(drive, floppy->pc->c, 12);
++ hwif->output_data(drive, NULL, floppy->pc->c, 12);
++
+ return ide_started;
+ }
-- if (!ap->nr_pmp_links)
-+ if (!sata_pmp_attached(ap))
- goto retry;
+@@ -645,13 +569,15 @@ static int idefloppy_transfer_pc2(ide_drive_t *drive)
+ idefloppy_floppy_t *floppy = drive->driver_data;
- 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;
+ /* Send the actual packet */
+- HWIF(drive)->atapi_output_bytes(drive, floppy->pc->c, 12);
++ drive->hwif->output_data(drive, NULL, floppy->pc->c, 12);
++
+ /* Timeout for the packet command */
+ return IDEFLOPPY_WAIT_CMD;
+ }
+
+ 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 +587,7 @@ static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive)
+ "initiated yet DRQ isn't asserted\n");
+ return startstop;
}
-@@ -1157,16 +1004,8 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+- ireason = drive->hwif->INB(IDE_IREASON_REG);
++ ireason = hwif->INB(hwif->io_ports.nsect_addr);
+ if ((ireason & CD) == 0 || (ireason & IO)) {
+ printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) "
+ "while issuing a packet command\n");
+@@ -682,7 +608,7 @@ static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive)
}
- /**
-- * 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)
+ static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
+- idefloppy_pc_t *pc)
++ struct ide_atapi_pc *pc)
{
- 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);
+ /* supress error messages resulting from Medium not present */
+ if (floppy->sense_key == 0x02 &&
+@@ -698,7 +624,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 +645,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 +653,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;
+@@ -738,7 +664,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
+ dma = 0;
+
+ if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma)
+- dma = !hwif->dma_setup(drive);
++ dma = !hwif->dma_ops->dma_setup(drive);
+
+ ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
+ IDE_TFLAG_OUT_DEVICE, bcount, dma);
+@@ -746,7 +672,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
+ if (dma) {
+ /* Begin DMA, if necessary */
+ pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
+- hwif->dma_start(drive);
++ hwif->dma_ops->dma_start(drive);
+ }
+
+ /* Can we transfer the packet when we get the interrupt or wait? */
+@@ -757,7 +683,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
+ /* immediate */
+ pkt_xfer_routine = &idefloppy_transfer_pc;
+ }
+-
+
-+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;
+ if (floppy->flags & IDEFLOPPY_FLAG_DRQ_INTERRUPT) {
+ /* Issue the packet command */
+ ide_execute_command(drive, WIN_PACKETCMD,
+@@ -767,7 +693,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);
++ ide_execute_pkt_cmd(drive);
+ return (*pkt_xfer_routine) (drive);
+ }
}
-
--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)
+@@ -776,11 +702,11 @@ static void idefloppy_rw_callback(ide_drive_t *drive)
{
-- 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,
+ debug_log("Reached %s\n", __func__);
+
+- idefloppy_do_end_request(drive, 1, 0);
++ idefloppy_end_request(drive, 1, 0);
+ return;
}
- 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)
+-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)
{
-- 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)
+ debug_log("creating prevent removal command, prevent = %d\n", prevent);
- return snprintf(buf, 23, "%s\n", policy);
+@@ -789,39 +715,39 @@ static void idefloppy_create_prevent_cmd(idefloppy_pc_t *pc, int prevent)
+ pc->c[4] = prevent;
}
--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)
+-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)
{
- cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+ idefloppy_init_pc(pc);
+ pc->c[0] = GPCMD_FORMAT_UNIT;
+ pc->c[1] = 0x17;
-- 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);
+- 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;
}
- /**
-@@ -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);
+ /* 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 */
-- 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
+@@ -842,24 +768,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;
+ }
- /* 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 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 struct ata_device *ata_find_dev(struct ata_port *ap, int devno)
+-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)
{
-- 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;
+ idefloppy_init_pc(pc);
+ pc->c[0] = GPCMD_TEST_UNIT_READY;
+ }
- /* 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;
+ 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 +800,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]);
-- 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,
+- 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;
+ }
- 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;
+ 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 +850,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 +858,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 {
- 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;
+ 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;
}
-diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
-index 20dc572..2ec65a8 100644
---- a/drivers/ata/libata-sff.c
-+++ b/drivers/ata/libata-sff.c
-@@ -35,11 +35,377 @@
- #include <linux/kernel.h>
- #include <linux/pci.h>
- #include <linux/libata.h>
-+#include <linux/highmem.h>
-
- #include "libata.h"
-+const struct ata_port_operations ata_sff_port_ops = {
-+ .inherits = &ata_base_port_ops,
-+
-+ .qc_prep = ata_sff_qc_prep,
-+ .qc_issue = ata_sff_qc_issue,
-+ .qc_fill_rtf = ata_sff_qc_fill_rtf,
-+
-+ .freeze = ata_sff_freeze,
-+ .thaw = ata_sff_thaw,
-+ .prereset = ata_sff_prereset,
-+ .softreset = ata_sff_softreset,
-+ .hardreset = sata_sff_hardreset,
-+ .postreset = ata_sff_postreset,
-+ .error_handler = ata_sff_error_handler,
-+ .post_internal_cmd = ata_sff_post_internal_cmd,
-+
-+ .sff_dev_select = ata_sff_dev_select,
-+ .sff_check_status = ata_sff_check_status,
-+ .sff_tf_load = ata_sff_tf_load,
-+ .sff_tf_read = ata_sff_tf_read,
-+ .sff_exec_command = ata_sff_exec_command,
-+ .sff_data_xfer = ata_sff_data_xfer,
-+ .sff_irq_on = ata_sff_irq_on,
-+ .sff_irq_clear = ata_sff_irq_clear,
-+
-+ .port_start = ata_sff_port_start,
-+};
-+
-+const struct ata_port_operations ata_bmdma_port_ops = {
-+ .inherits = &ata_sff_port_ops,
-+
-+ .mode_filter = ata_bmdma_mode_filter,
-+
-+ .bmdma_setup = ata_bmdma_setup,
-+ .bmdma_start = ata_bmdma_start,
-+ .bmdma_stop = ata_bmdma_stop,
-+ .bmdma_status = ata_bmdma_status,
-+};
-+
-+/**
-+ * ata_fill_sg - Fill PCI IDE PRD table
-+ * @qc: Metadata associated with taskfile to be transferred
-+ *
-+ * Fill PCI IDE PRD (scatter-gather) table with segments
-+ * associated with the current disk command.
-+ *
-+ * LOCKING:
-+ * spin_lock_irqsave(host lock)
-+ *
-+ */
-+static void ata_fill_sg(struct ata_queued_cmd *qc)
-+{
-+ struct ata_port *ap = qc->ap;
-+ struct scatterlist *sg;
-+ unsigned int si, pi;
-+
-+ pi = 0;
-+ for_each_sg(qc->sg, sg, qc->n_elem, si) {
-+ u32 addr, offset;
-+ u32 sg_len, len;
-+
-+ /* determine if physical DMA addr spans 64K boundary.
-+ * Note h/w doesn't support 64-bit, so we unconditionally
-+ * truncate dma_addr_t to u32.
-+ */
-+ addr = (u32) sg_dma_address(sg);
-+ sg_len = sg_dma_len(sg);
-+
-+ while (sg_len) {
-+ offset = addr & 0xffff;
-+ len = sg_len;
-+ if ((offset + sg_len) > 0x10000)
-+ len = 0x10000 - offset;
-+
-+ ap->prd[pi].addr = cpu_to_le32(addr);
-+ ap->prd[pi].flags_len = cpu_to_le32(len & 0xffff);
-+ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
-+
-+ pi++;
-+ sg_len -= len;
-+ addr += len;
-+ }
-+ }
-+
-+ ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
-+}
-+
-+/**
-+ * ata_fill_sg_dumb - Fill PCI IDE PRD table
-+ * @qc: Metadata associated with taskfile to be transferred
-+ *
-+ * Fill PCI IDE PRD (scatter-gather) table with segments
-+ * associated with the current disk command. Perform the fill
-+ * so that we avoid writing any length 64K records for
-+ * controllers that don't follow the spec.
-+ *
-+ * LOCKING:
-+ * spin_lock_irqsave(host lock)
-+ *
-+ */
-+static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
-+{
-+ struct ata_port *ap = qc->ap;
-+ struct scatterlist *sg;
-+ unsigned int si, pi;
-+
-+ pi = 0;
-+ for_each_sg(qc->sg, sg, qc->n_elem, si) {
-+ u32 addr, offset;
-+ u32 sg_len, len, blen;
-+
-+ /* determine if physical DMA addr spans 64K boundary.
-+ * Note h/w doesn't support 64-bit, so we unconditionally
-+ * truncate dma_addr_t to u32.
-+ */
-+ addr = (u32) sg_dma_address(sg);
-+ sg_len = sg_dma_len(sg);
-+
-+ while (sg_len) {
-+ offset = addr & 0xffff;
-+ len = sg_len;
-+ if ((offset + sg_len) > 0x10000)
-+ len = 0x10000 - offset;
-+
-+ blen = len & 0xffff;
-+ ap->prd[pi].addr = cpu_to_le32(addr);
-+ if (blen == 0) {
-+ /* Some PATA chipsets like the CS5530 can't
-+ cope with 0x0000 meaning 64K as the spec says */
-+ ap->prd[pi].flags_len = cpu_to_le32(0x8000);
-+ blen = 0x8000;
-+ ap->prd[++pi].addr = cpu_to_le32(addr + 0x8000);
-+ }
-+ ap->prd[pi].flags_len = cpu_to_le32(blen);
-+ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
-+
-+ pi++;
-+ sg_len -= len;
-+ addr += len;
-+ }
-+ }
-+
-+ ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
-+}
-+
-+/**
-+ * ata_sff_qc_prep - Prepare taskfile for submission
-+ * @qc: Metadata associated with taskfile to be prepared
-+ *
-+ * Prepare ATA taskfile for submission.
-+ *
-+ * LOCKING:
-+ * spin_lock_irqsave(host lock)
-+ */
-+void ata_sff_qc_prep(struct ata_queued_cmd *qc)
-+{
-+ if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-+ return;
-+
-+ ata_fill_sg(qc);
-+}
-+
-+/**
-+ * ata_sff_dumb_qc_prep - Prepare taskfile for submission
-+ * @qc: Metadata associated with taskfile to be prepared
-+ *
-+ * Prepare ATA taskfile for submission.
-+ *
-+ * LOCKING:
-+ * spin_lock_irqsave(host lock)
-+ */
-+void ata_sff_dumb_qc_prep(struct ata_queued_cmd *qc)
-+{
-+ if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-+ return;
-+
-+ ata_fill_sg_dumb(qc);
-+}
-+
-+/**
-+ * ata_sff_check_status - Read device status reg & clear interrupt
-+ * @ap: port where the device is
-+ *
-+ * Reads ATA taskfile status register for currently-selected device
-+ * and return its value. This also clears pending interrupts
-+ * from this device
-+ *
-+ * LOCKING:
-+ * Inherited from caller.
-+ */
-+u8 ata_sff_check_status(struct ata_port *ap)
-+{
-+ return ioread8(ap->ioaddr.status_addr);
-+}
-+
-+/**
-+ * ata_sff_altstatus - Read device alternate status reg
-+ * @ap: port where the device is
-+ *
-+ * Reads ATA taskfile alternate status register for
-+ * currently-selected device and return its value.
-+ *
-+ * Note: may NOT be used as the check_altstatus() entry in
-+ * ata_port_operations.
-+ *
-+ * LOCKING:
-+ * Inherited from caller.
-+ */
-+u8 ata_sff_altstatus(struct ata_port *ap)
-+{
-+ if (ap->ops->sff_check_altstatus)
-+ return ap->ops->sff_check_altstatus(ap);
-+
-+ return ioread8(ap->ioaddr.altstatus_addr);
-+}
-+
-+/**
-+ * ata_sff_busy_sleep - sleep until BSY clears, or timeout
-+ * @ap: port containing status register to be polled
-+ * @tmout_pat: impatience timeout
-+ * @tmout: overall timeout
-+ *
-+ * Sleep until ATA Status register bit BSY clears,
-+ * or a timeout occurs.
-+ *
-+ * LOCKING:
-+ * Kernel thread context (may sleep).
-+ *
-+ * RETURNS:
-+ * 0 on success, -errno otherwise.
-+ */
-+int ata_sff_busy_sleep(struct ata_port *ap,
-+ unsigned long tmout_pat, unsigned long tmout)
-+{
-+ unsigned long timer_start, timeout;
-+ u8 status;
-+
-+ status = ata_sff_busy_wait(ap, ATA_BUSY, 300);
-+ timer_start = jiffies;
-+ timeout = timer_start + tmout_pat;
-+ while (status != 0xff && (status & ATA_BUSY) &&
-+ time_before(jiffies, timeout)) {
-+ msleep(50);
-+ status = ata_sff_busy_wait(ap, ATA_BUSY, 3);
-+ }
-+
-+ if (status != 0xff && (status & ATA_BUSY))
-+ ata_port_printk(ap, KERN_WARNING,
-+ "port is slow to respond, please be patient "
-+ "(Status 0x%x)\n", status);
-+
-+ timeout = timer_start + tmout;
-+ while (status != 0xff && (status & ATA_BUSY) &&
-+ time_before(jiffies, timeout)) {
-+ msleep(50);
-+ status = ap->ops->sff_check_status(ap);
-+ }
-+
-+ if (status == 0xff)
-+ return -ENODEV;
-+
-+ if (status & ATA_BUSY) {
-+ ata_port_printk(ap, KERN_ERR, "port failed to respond "
-+ "(%lu secs, Status 0x%x)\n",
-+ tmout / HZ, status);
-+ return -EBUSY;
-+ }
-+
-+ return 0;
-+}
-+
-+static int ata_sff_check_ready(struct ata_link *link)
-+{
-+ u8 status = link->ap->ops->sff_check_status(link->ap);
-+
-+ if (!(status & ATA_BUSY))
-+ return 1;
-+ if (status == 0xff)
-+ return -ENODEV;
-+ return 0;
-+}
-+
-+/**
-+ * ata_sff_wait_ready - sleep until BSY clears, or timeout
-+ * @link: SFF link to wait ready status for
-+ * @deadline: deadline jiffies for the operation
-+ *
-+ * Sleep until ATA Status register bit BSY clears, or timeout
-+ * occurs.
-+ *
-+ * LOCKING:
-+ * Kernel thread context (may sleep).
-+ *
-+ * RETURNS:
-+ * 0 on success, -errno otherwise.
-+ */
-+int ata_sff_wait_ready(struct ata_link *link, unsigned long deadline)
-+{
-+ return ata_wait_ready(link, deadline, ata_sff_check_ready);
-+}
-+
-+/**
-+ * ata_sff_dev_select - Select device 0/1 on ATA bus
-+ * @ap: ATA channel to manipulate
-+ * @device: ATA device (numbered from zero) to select
-+ *
-+ * Use the method defined in the ATA specification to
-+ * make either device 0, or device 1, active on the
-+ * ATA channel. Works with both PIO and MMIO.
-+ *
-+ * May be used as the dev_select() entry in ata_port_operations.
-+ *
-+ * LOCKING:
-+ * caller.
-+ */
-+void ata_sff_dev_select(struct ata_port *ap, unsigned int device)
-+{
-+ u8 tmp;
-+
-+ if (device == 0)
-+ tmp = ATA_DEVICE_OBS;
-+ else
-+ tmp = ATA_DEVICE_OBS | ATA_DEV1;
-+
-+ iowrite8(tmp, ap->ioaddr.device_addr);
-+ ata_sff_pause(ap); /* needed; also flushes, for mmio */
-+}
-+
-+/**
-+ * ata_dev_select - Select device 0/1 on ATA bus
-+ * @ap: ATA channel to manipulate
-+ * @device: ATA device (numbered from zero) to select
-+ * @wait: non-zero to wait for Status register BSY bit to clear
-+ * @can_sleep: non-zero if context allows sleeping
-+ *
-+ * Use the method defined in the ATA specification to
-+ * make either device 0, or device 1, active on the
-+ * ATA channel.
-+ *
-+ * This is a high-level version of ata_sff_dev_select(), which
-+ * additionally provides the services of inserting the proper
-+ * pauses and status polling, where needed.
-+ *
-+ * LOCKING:
-+ * caller.
-+ */
-+void ata_dev_select(struct ata_port *ap, unsigned int device,
-+ unsigned int wait, unsigned int can_sleep)
-+{
-+ if (ata_msg_probe(ap))
-+ ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, "
-+ "device %u, wait %u\n", device, wait);
-+
-+ if (wait)
-+ ata_wait_idle(ap);
-+
-+ ap->ops->sff_dev_select(ap, device);
-+
-+ if (wait) {
-+ if (can_sleep && ap->link.device[device].class == ATA_DEV_ATAPI)
-+ msleep(150);
-+ ata_wait_idle(ap);
-+ }
-+}
-+
- /**
-- * ata_irq_on - Enable interrupts on a port.
-+ * ata_sff_irq_on - Enable interrupts on a port.
- * @ap: Port on which interrupts are enabled.
- *
- * Enable interrupts on a legacy IDE device using MMIO or PIO,
-@@ -48,7 +414,7 @@
- * LOCKING:
- * Inherited from caller.
+@@ -957,7 +883,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.
*/
--u8 ata_irq_on(struct ata_port *ap)
-+u8 ata_sff_irq_on(struct ata_port *ap)
+-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 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);
+ struct ide_floppy_obj *floppy = drive->driver_data;
+ struct request rq;
+@@ -977,7 +903,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 +917,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];
-- ap->ops->irq_clear(ap);
-+ ap->ops->sff_irq_clear(ap);
+- 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];
- return tmp;
- }
+ capacity = cyls * heads * sectors * sector_size;
- /**
-- * 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)
+@@ -1029,7 +955,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
+ static int idefloppy_get_sfrp_bit(ide_drive_t *drive)
{
- 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)
+ 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 +965,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);
}
- /**
-- * 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)
+@@ -1050,7 +976,7 @@ static int idefloppy_get_sfrp_bit(ide_drive_t *drive)
+ static int ide_floppy_get_capacity(ide_drive_t *drive)
{
- struct ata_ioports *ioaddr = &ap->ioaddr;
+ 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 +992,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 */
-- 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)
- }
+ for (i = 0; i < desc_cnt; i++) {
+ unsigned int desc_start = 4 + i*8;
- /**
-- * 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)
+- 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 +1011,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 +1056,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 +1088,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 +1104,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 +1121,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 +1153,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 +1197,39 @@ static sector_t idefloppy_capacity(ide_drive_t *drive)
*/
--u8 ata_check_status(struct ata_port *ap)
-+void ata_sff_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
+ static int idefloppy_identify_device(ide_drive_t *drive, struct hd_driveid *id)
{
-- return ioread8(ap->ioaddr.status_addr);
-+ DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
+- 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;
+
-+ iowrite8(tf->command, ap->ioaddr.command_addr);
-+ ata_sff_pause(ap);
+ #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 +1254,12 @@ static inline void idefloppy_add_settings(ide_drive_t *drive) { ; }
- /**
-- * 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)
+ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
{
-- 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;
+- struct idefloppy_id_gcw gcw;
++ u8 gcw[2];
-- 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++;
-+ }
+ *((u16 *) &gcw) = drive->id->config;
+ floppy->pc = floppy->pc_stack;
+- if (gcw.drq_type == 1)
+
-+ return words << 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 +1346,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 +1359,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 +1422,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 +1454,8 @@ static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+ return 0;
}
- /**
-- * 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)
+-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)
{
-+ 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;
+ if (floppy->openers > 1)
+ return -EBUSY;
+@@ -1551,7 +1484,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;
-- /* 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;
+ if (floppy->openers > 1) {
+ /* Don't format if someone is using the disk */
+@@ -1602,7 +1535,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;
-- /* 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;
-+ }
+@@ -1664,13 +1597,13 @@ static int idefloppy_revalidate_disk(struct gendisk *disk)
}
- /**
-- * 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.
+ 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..a6073e2 100644
+--- a/drivers/ide/ide-generic.c
++++ b/drivers/ide/ide-generic.c
+@@ -1,33 +1,142 @@
+ /*
+ * generic/default IDE host driver
*
- * LOCKING:
-- * spin_lock_irqsave(host lock)
-+ * Inherited from caller.
+- * 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.
*/
--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.
+
++/*
++ * For special cases new interfaces may be added using sysfs, i.e.
+ *
-+ * LOCKING:
-+ * Inherited from caller.
++ * echo -n "0x168:0x36e:10" > /sys/class/ide_generic/add
+ *
++ * will add an interface using I/O ports 0x168-0x16f/0x36e and IRQ 10.
+ */
-+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;
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/ide.h>
-- /* 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);
++#define DRV_NAME "ide_generic"
+
-+ /* don't cross page boundaries */
-+ count = min(count, (unsigned int)PAGE_SIZE - offset);
++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 };
+
-+ DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
++ if (sscanf(buf, "%x:%x:%d", &base, &ctl, &irq) != 3)
++ return -EINVAL;
+
-+ if (PageHighMem(page)) {
-+ unsigned long flags;
++ hwif = ide_find_port();
++ if (hwif == NULL)
++ return -ENOENT;
+
-+ /* FIXME: use bounce buffer */
-+ local_irq_save(flags);
-+ buf = kmap_atomic(page, KM_IRQ0);
++ memset(&hw, 0, sizeof(hw));
++ ide_std_init_ports(&hw, base, ctl);
++ hw.irq = irq;
++ hw.chipset = ide_generic;
+
-+ /* do the actual data transfer */
-+ consumed = ap->ops->sff_data_xfer(dev, buf + offset, count, rw);
++ ide_init_port_hw(hwif, &hw);
+
-+ 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);
-+ }
++ idx[0] = hwif->index;
+
-+ bytes -= min(bytes, consumed);
-+ qc->curbytes += count;
-+ qc->cursg_ofs += count;
++ ide_device_add(idx, NULL);
+
-+ if (qc->cursg_ofs == sg->length) {
-+ qc->cursg = sg_next(qc->cursg);
-+ qc->cursg_ofs = 0;
-+ }
++ return n;
++};
+
-+ /* consumed can be larger than count only for the last transfer */
-+ WARN_ON(qc->cursg && count != consumed);
++static struct class_attribute ide_generic_class_attrs[] = {
++ __ATTR(add, S_IWUSR, NULL, store_add),
++ __ATTR_NULL
++};
+
-+ if (bytes)
-+ goto next_sg;
-+ return 0;
++static void ide_generic_class_release(struct class *cls)
++{
++ kfree(cls);
+}
+
-+/**
-+ * 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)
++static int __init ide_generic_sysfs_init(void)
+{
-+ 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;
++ struct class *cls;
++ int rc;
+
-+ 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;
++ cls = kzalloc(sizeof(*cls), GFP_KERNEL);
++ if (!cls)
++ return -ENOMEM;
+
-+ if (ap->hsm_task_state == HSM_ST_FIRST) {
-+ if (qc->tf.protocol == ATA_PROT_PIO &&
-+ (qc->tf.flags & ATA_TFLAG_WRITE))
-+ return 1;
++ cls->name = DRV_NAME;
++ cls->owner = THIS_MODULE;
++ cls->class_release = ide_generic_class_release;
++ cls->class_attrs = ide_generic_class_attrs;
+
-+ if (ata_is_atapi(qc->tf.protocol) &&
-+ !(qc->dev->flags & ATA_DFLAG_CDB_INTR))
-+ return 1;
++ rc = class_register(cls);
++ if (rc) {
++ kfree(cls);
++ return rc;
+ }
+
+ 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)
+ static int __init ide_generic_init(void)
{
-- 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);
-+ }
-+}
+ u8 idx[MAX_HWIFS];
+ int i;
-- 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;
+ 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;
+
-+ ap->hsm_task_state = HSM_ST_ERR;
-+ goto fsm_start;
-+ }
++ idx[i] = 0xff;
+
-+ /* 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;
++ if (io_addr) {
++ if (!request_region(io_addr, 8, DRV_NAME)) {
++ printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX "
++ "not free.\n",
++ DRV_NAME, io_addr, io_addr + 7);
++ continue;
+ }
-+ }
-+
-+ /* 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;
++ if (!request_region(io_addr + 0x206, 1, DRV_NAME)) {
++ printk(KERN_ERR "%s: I/O resource 0x%lX "
++ "not free.\n",
++ DRV_NAME, io_addr + 0x206);
++ release_region(io_addr, 8);
++ continue;
+ }
+
-+ /* 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.
++ /*
++ * Skip probing if the corresponding
++ * slot is already occupied.
+ */
-+ 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;
++ hwif = ide_find_port();
++ if (hwif == NULL || hwif->index != i) {
++ idx[i] = 0xff;
++ continue;
+ }
+
-+ 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;
++ 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
+- 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");
+
-+ ap->hsm_task_state = HSM_ST_ERR;
-+ goto fsm_start;
-+ }
+ return 0;
+ }
+
+diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
+index 7153796..6965253 100644
+--- a/drivers/ide/ide-io.c
++++ b/drivers/ide/ide-io.c
+@@ -218,7 +218,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
+ * we could be smarter and check for current xfer_speed
+ * in struct drive etc...
+ */
+- if (drive->hwif->dma_host_set == NULL)
++ if (drive->hwif->dma_ops == NULL)
+ break;
+ /*
+ * TODO: respect ->using_dma setting
+@@ -295,48 +295,6 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
+ spin_unlock_irqrestore(&ide_lock, flags);
+ }
+
+-void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+-{
+- ide_hwif_t *hwif = drive->hwif;
+- struct ide_taskfile *tf = &task->tf;
+-
+- if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+- u16 data = hwif->INW(IDE_DATA_REG);
+-
+- 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);
+-
+- if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+- tf->nsect = hwif->INB(IDE_NSECTOR_REG);
+- if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+- tf->lbal = hwif->INB(IDE_SECTOR_REG);
+- if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+- tf->lbam = hwif->INB(IDE_LCYL_REG);
+- if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+- tf->lbah = hwif->INB(IDE_HCYL_REG);
+- if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+- tf->device = hwif->INB(IDE_SELECT_REG);
+-
+- if (task->tf_flags & IDE_TFLAG_LBA48) {
+- hwif->OUTB(drive->ctl | 0x80, IDE_CONTROL_REG);
+-
+- if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+- tf->hob_feature = hwif->INB(IDE_FEATURE_REG);
+- if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+- tf->hob_nsect = hwif->INB(IDE_NSECTOR_REG);
+- if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+- tf->hob_lbal = hwif->INB(IDE_SECTOR_REG);
+- if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+- tf->hob_lbam = hwif->INB(IDE_LCYL_REG);
+- if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+- tf->hob_lbah = hwif->INB(IDE_HCYL_REG);
+- }
+-}
+-
+ /**
+ * ide_end_drive_cmd - end an explicit drive command
+ * @drive: command
+@@ -372,7 +330,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
+ tf->error = err;
+ tf->status = stat;
+
+- ide_tf_read(drive, task);
++ drive->hwif->tf_read(drive, task);
+
+ if (task->tf_flags & IDE_TFLAG_DYN)
+ kfree(task);
+@@ -421,7 +379,7 @@ static void try_to_flush_leftover_data (ide_drive_t *drive)
+ u32 wcount = (i > 16) ? 16 : i;
+
+ i -= wcount;
+- HWIF(drive)->ata_input_data(drive, buffer, wcount);
++ drive->hwif->input_data(drive, NULL, buffer, wcount * 4);
+ }
+ }
+
+@@ -448,7 +406,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.command_addr) ==
++ WIN_SPECIFY)
+ return ide_stopped;
+ } else if ((err & BAD_CRC) == BAD_CRC) {
+ /* UDMA crc error, just retry the operation */
+@@ -500,7 +459,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->OUTBSYNC(drive, WIN_IDLEIMMEDIATE,
++ hwif->io_ports.command_addr);
+
+ if (rq->errors >= ERROR_MAX) {
+ ide_kill_rq(drive, rq);
+@@ -713,15 +673,12 @@ static ide_startstop_t do_special (ide_drive_t *drive)
+ #endif
+ if (s->b.set_tune) {
+ ide_hwif_t *hwif = drive->hwif;
++ const struct ide_port_ops *port_ops = hwif->port_ops;
+ u8 req_pio = drive->tune_req;
+
+ 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
+ */
+@@ -729,10 +686,10 @@ static ide_startstop_t do_special (ide_drive_t *drive)
+ unsigned long flags;
+
+ spin_lock_irqsave(&ide_lock, flags);
+- hwif->set_pio_mode(drive, req_pio);
++ port_ops->set_pio_mode(drive, req_pio);
+ spin_unlock_irqrestore(&ide_lock, flags);
+ } else
+- hwif->set_pio_mode(drive, req_pio);
++ port_ops->set_pio_mode(drive, req_pio);
+ } else {
+ int keep_dma = drive->using_dma;
+
+@@ -1233,12 +1190,12 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
+
+ if (error < 0) {
+ printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
+- (void)HWIF(drive)->ide_dma_end(drive);
++ (void)hwif->dma_ops->dma_end(drive);
+ ret = ide_error(drive, "dma timeout error",
+ ide_read_status(drive));
+ } else {
+ printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
+- hwif->dma_timeout(drive);
++ hwif->dma_ops->dma_timeout(drive);
+ }
+
+ /*
+@@ -1350,7 +1307,7 @@ void ide_timer_expiry (unsigned long data)
+ startstop = handler(drive);
+ } else if (drive_is_ready(drive)) {
+ if (drive->waiting_for_dma)
+- hwgroup->hwif->dma_lost_irq(drive);
++ hwif->dma_ops->dma_lost_irq(drive);
+ (void)ide_ack_intr(hwif);
+ printk(KERN_WARNING "%s: lost interrupt\n", drive->name);
+ startstop = handler(drive);
+@@ -1416,7 +1373,7 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
+ */
+ do {
+ if (hwif->irq == irq) {
+- stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
++ stat = hwif->INB(hwif->io_ports.status_addr);
+ if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
+ /* Try to not flood the console with msgs */
+ static unsigned long last_msgtime, count;
+@@ -1506,7 +1463,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
+ * Whack the status register, just in case
+ * we have a leftover pending IRQ.
+ */
+- (void) hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
++ (void) hwif->INB(hwif->io_ports.status_addr);
+ #endif /* CONFIG_BLK_DEV_IDEPCI */
+ }
+ spin_unlock_irqrestore(&ide_lock, flags);
+@@ -1593,8 +1550,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
+
+ void ide_init_drive_cmd (struct request *rq)
+ {
+- memset(rq, 0, sizeof(*rq));
+- rq->ref_count = 1;
++ blk_rq_init(NULL, rq);
+ }
+
+ EXPORT_SYMBOL(ide_init_drive_cmd);
+@@ -1680,7 +1636,23 @@ void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
+ task.tf.lbam = bcount & 0xff;
+ task.tf.lbah = (bcount >> 8) & 0xff;
+
+- ide_tf_load(drive, &task);
++ ide_tf_dump(drive->name, &task.tf);
++ drive->hwif->tf_load(drive, &task);
+ }
+
+ EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load);
+
-+ /* 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;
++void ide_pad_transfer(ide_drive_t *drive, int write, int len)
++{
++ ide_hwif_t *hwif = drive->hwif;
++ u8 buf[4] = { 0 };
+
-+ if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
-+ ata_pio_sectors(qc);
-+ status = ata_wait_idle(ap);
-+ }
++ while (len > 0) {
++ if (write)
++ hwif->output_data(drive, NULL, buf, min(4, len));
++ else
++ hwif->input_data(drive, NULL, buf, min(4, len));
++ len -= 4;
++ }
++}
++EXPORT_SYMBOL_GPL(ide_pad_transfer);
+diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
+index e77cee0..57d9a9a 100644
+--- a/drivers/ide/ide-iops.c
++++ b/drivers/ide/ide-iops.c
+@@ -37,21 +37,6 @@ static u8 ide_inb (unsigned long port)
+ return (u8) inb(port);
+ }
+
+-static u16 ide_inw (unsigned long port)
+-{
+- return (u16) inw(port);
+-}
+-
+-static void ide_insw (unsigned long port, void *addr, u32 count)
+-{
+- insw(port, addr, count);
+-}
+-
+-static void ide_insl (unsigned long port, void *addr, u32 count)
+-{
+- insl(port, addr, count);
+-}
+-
+ static void ide_outb (u8 val, unsigned long port)
+ {
+ outb(val, port);
+@@ -62,32 +47,11 @@ static void ide_outbsync (ide_drive_t *drive, u8 addr, unsigned long port)
+ outb(addr, port);
+ }
+
+-static void ide_outw (u16 val, unsigned long port)
+-{
+- outw(val, port);
+-}
+-
+-static void ide_outsw (unsigned long port, void *addr, u32 count)
+-{
+- outsw(port, addr, count);
+-}
+-
+-static void ide_outsl (unsigned long port, void *addr, u32 count)
+-{
+- outsl(port, addr, count);
+-}
+-
+ void default_hwif_iops (ide_hwif_t *hwif)
+ {
+ hwif->OUTB = ide_outb;
+ hwif->OUTBSYNC = ide_outbsync;
+- hwif->OUTW = ide_outw;
+- hwif->OUTSW = ide_outsw;
+- hwif->OUTSL = ide_outsl;
+ hwif->INB = ide_inb;
+- hwif->INW = ide_inw;
+- hwif->INSW = ide_insw;
+- hwif->INSL = ide_insl;
+ }
+
+ /*
+@@ -99,21 +63,6 @@ static u8 ide_mm_inb (unsigned long port)
+ return (u8) readb((void __iomem *) port);
+ }
+
+-static u16 ide_mm_inw (unsigned long port)
+-{
+- return (u16) readw((void __iomem *) port);
+-}
+-
+-static void ide_mm_insw (unsigned long port, void *addr, u32 count)
+-{
+- __ide_mm_insw((void __iomem *) port, addr, count);
+-}
+-
+-static void ide_mm_insl (unsigned long port, void *addr, u32 count)
+-{
+- __ide_mm_insl((void __iomem *) port, addr, count);
+-}
+-
+ static void ide_mm_outb (u8 value, unsigned long port)
+ {
+ writeb(value, (void __iomem *) port);
+@@ -124,49 +73,151 @@ static void ide_mm_outbsync (ide_drive_t *drive, u8 value, unsigned long port)
+ writeb(value, (void __iomem *) port);
+ }
+
+-static void ide_mm_outw (u16 value, unsigned long port)
+-{
+- writew(value, (void __iomem *) port);
+-}
+-
+-static void ide_mm_outsw (unsigned long port, void *addr, u32 count)
+-{
+- __ide_mm_outsw((void __iomem *) port, addr, count);
+-}
+-
+-static void ide_mm_outsl (unsigned long port, void *addr, u32 count)
+-{
+- __ide_mm_outsl((void __iomem *) port, addr, count);
+-}
+-
+ void default_hwif_mmiops (ide_hwif_t *hwif)
+ {
+ hwif->OUTB = ide_mm_outb;
+ /* Most systems will need to override OUTBSYNC, alas however
+ this one is controller specific! */
+ hwif->OUTBSYNC = ide_mm_outbsync;
+- hwif->OUTW = ide_mm_outw;
+- hwif->OUTSW = ide_mm_outsw;
+- hwif->OUTSL = ide_mm_outsl;
+ hwif->INB = ide_mm_inb;
+- hwif->INW = ide_mm_inw;
+- hwif->INSW = ide_mm_insw;
+- hwif->INSL = ide_mm_insl;
+ }
+
+ 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;
++ const struct ide_port_ops *port_ops = hwif->port_ops;
+
-+ if (status & (ATA_BUSY | ATA_DRQ))
-+ qc->err_mask |= AC_ERR_HSM;
++ if (port_ops && port_ops->selectproc)
++ port_ops->selectproc(drive);
+
-+ /* 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;
-+ }
++ hwif->OUTB(drive->select.all, hwif->io_ports.device_addr);
+ }
+
+ void SELECT_MASK (ide_drive_t *drive, int mask)
+ {
+- if (HWIF(drive)->maskproc)
+- HWIF(drive)->maskproc(drive, mask);
++ const struct ide_port_ops *port_ops = drive->hwif->port_ops;
+
-+ ata_pio_sectors(qc);
++ if (port_ops && port_ops->maskproc)
++ port_ops->maskproc(drive, mask);
++}
+
-+ 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;
-+ }
-+ }
++static void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
++{
++ ide_hwif_t *hwif = drive->hwif;
++ struct ide_io_ports *io_ports = &hwif->io_ports;
++ struct ide_taskfile *tf = &task->tf;
++ void (*tf_outb)(u8 addr, unsigned long port);
++ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
++ u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
+
-+ poll_next = 1;
-+ break;
++ if (mmio)
++ tf_outb = ide_mm_outb;
++ else
++ tf_outb = ide_outb;
+
-+ 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;
-+ }
++ if (task->tf_flags & IDE_TFLAG_FLAGGED)
++ HIHI = 0xFF;
+
-+ /* no more data to transfer */
-+ DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n",
-+ ap->print_id, qc->dev->devno, status);
++ ide_set_irq(drive, 1);
+
-+ WARN_ON(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM));
++ if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0)
++ SELECT_MASK(drive, 0);
+
-+ ap->hsm_task_state = HSM_ST_IDLE;
++ if (task->tf_flags & IDE_TFLAG_OUT_DATA) {
++ u16 data = (tf->hob_data << 8) | tf->data;
+
-+ /* complete taskfile transaction */
-+ ata_hsm_qc_complete(qc, in_wq);
++ if (mmio)
++ writew(data, (void __iomem *)io_ports->data_addr);
++ else
++ outw(data, io_ports->data_addr);
++ }
+
-+ poll_next = 0;
-+ break;
++ if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
++ tf_outb(tf->hob_feature, io_ports->feature_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
++ tf_outb(tf->hob_nsect, io_ports->nsect_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
++ tf_outb(tf->hob_lbal, io_ports->lbal_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
++ tf_outb(tf->hob_lbam, io_ports->lbam_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
++ tf_outb(tf->hob_lbah, io_ports->lbah_addr);
++
++ if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
++ tf_outb(tf->feature, io_ports->feature_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
++ tf_outb(tf->nsect, io_ports->nsect_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
++ tf_outb(tf->lbal, io_ports->lbal_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
++ tf_outb(tf->lbam, io_ports->lbam_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
++ tf_outb(tf->lbah, io_ports->lbah_addr);
++
++ if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
++ tf_outb((tf->device & HIHI) | drive->select.all,
++ io_ports->device_addr);
++}
+
-+ 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)));
++static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
++{
++ ide_hwif_t *hwif = drive->hwif;
++ struct ide_io_ports *io_ports = &hwif->io_ports;
++ struct ide_taskfile *tf = &task->tf;
++ void (*tf_outb)(u8 addr, unsigned long port);
++ u8 (*tf_inb)(unsigned long port);
++ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
++
++ if (mmio) {
++ tf_outb = ide_mm_outb;
++ tf_inb = ide_mm_inb;
++ } else {
++ tf_outb = ide_outb;
++ tf_inb = ide_inb;
++ }
+
-+ ap->hsm_task_state = HSM_ST_IDLE;
++ if (task->tf_flags & IDE_TFLAG_IN_DATA) {
++ u16 data;
+
-+ /* complete taskfile transaction */
-+ ata_hsm_qc_complete(qc, in_wq);
++ if (mmio)
++ data = readw((void __iomem *)io_ports->data_addr);
++ else
++ data = inw(io_ports->data_addr);
+
-+ poll_next = 0;
-+ break;
-+ default:
-+ poll_next = 0;
-+ BUG();
++ tf->data = data & 0xff;
++ tf->hob_data = (data >> 8) & 0xff;
+ }
+
-+ return poll_next;
-+}
++ /* be sure we're looking at the low order bits */
++ tf_outb(drive->ctl & ~0x80, io_ports->ctl_addr);
+
-+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;
++ if (task->tf_flags & IDE_TFLAG_IN_NSECT)
++ tf->nsect = tf_inb(io_ports->nsect_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_LBAL)
++ tf->lbal = tf_inb(io_ports->lbal_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_LBAM)
++ tf->lbam = tf_inb(io_ports->lbam_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_LBAH)
++ tf->lbah = tf_inb(io_ports->lbah_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
++ tf->device = tf_inb(io_ports->device_addr);
+
-+fsm_start:
-+ WARN_ON(ap->hsm_task_state == HSM_ST_IDLE);
++ if (task->tf_flags & IDE_TFLAG_LBA48) {
++ tf_outb(drive->ctl | 0x80, io_ports->ctl_addr);
+
-+ /*
-+ * 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;
-+ }
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
++ tf->hob_feature = tf_inb(io_ports->feature_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
++ tf->hob_nsect = tf_inb(io_ports->nsect_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
++ tf->hob_lbal = tf_inb(io_ports->lbal_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
++ tf->hob_lbam = tf_inb(io_ports->lbam_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
++ tf->hob_lbah = tf_inb(io_ports->lbah_addr);
+ }
-+
-+ /* 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)
+ /*
+@@ -176,105 +227,112 @@ void SELECT_MASK (ide_drive_t *drive, int mask)
+ * of the sector count register location, with interrupts disabled
+ * to ensure that the reads all happen together.
+ */
+-static void ata_vlb_sync(ide_drive_t *drive, unsigned long port)
++static void ata_vlb_sync(unsigned long port)
+ {
+- (void) HWIF(drive)->INB(port);
+- (void) HWIF(drive)->INB(port);
+- (void) HWIF(drive)->INB(port);
++ (void)inb(port);
++ (void)inb(port);
++ (void)inb(port);
+ }
+
+ /*
+ * This is used for most PIO data transfers *from* the IDE interface
+ *
-+ * RETURNS:
-+ * Zero on success, AC_ERR_* mask on failure
++ * These routines will round up any request for an odd number of bytes,
++ * so if an odd len is specified, be sure that there's at least one
++ * extra byte allocated for the buffer.
*/
--u8 ata_bmdma_status(struct ata_port *ap)
-+unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
+-static void ata_input_data(ide_drive_t *drive, void *buffer, u32 wcount)
++static void ata_input_data(ide_drive_t *drive, struct request *rq,
++ void *buf, unsigned int len)
{
-- 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;
+- ide_hwif_t *hwif = HWIF(drive);
+- u8 io_32bit = drive->io_32bit;
++ ide_hwif_t *hwif = drive->hwif;
++ struct ide_io_ports *io_ports = &hwif->io_ports;
++ unsigned long data_addr = io_ports->data_addr;
++ u8 io_32bit = drive->io_32bit;
++ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+
-+ if (qc->tf.flags & ATA_TFLAG_POLLING)
-+ ata_pio_queue_task(ap, qc, 0);
++ len++;
+
+ if (io_32bit) {
+- if (io_32bit & 2) {
+- unsigned long flags;
++ unsigned long uninitialized_var(flags);
+
-+ /* if polling, ata_pio_task() handles the rest.
-+ * otherwise, interrupt handler takes over from here.
-+ */
++ if ((io_32bit & 2) && !mmio) {
+ local_irq_save(flags);
+- ata_vlb_sync(drive, IDE_NSECTOR_REG);
+- hwif->INSL(IDE_DATA_REG, buffer, wcount);
++ ata_vlb_sync(io_ports->nsect_addr);
+ }
+
-+ 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;
++ if (mmio)
++ __ide_mm_insl((void __iomem *)data_addr, buf, len / 4);
++ else
++ insl(data_addr, buf, len / 4);
+
-+ default:
-+ WARN_ON(1);
-+ return AC_ERR_SYSTEM;
-+ }
++ if ((io_32bit & 2) && !mmio)
+ local_irq_restore(flags);
+- } else
+- hwif->INSL(IDE_DATA_REG, buffer, wcount);
+
-+ return 0;
++ if ((len & 3) >= 2) {
++ if (mmio)
++ __ide_mm_insw((void __iomem *)data_addr,
++ (u8 *)buf + (len & ~3), 1);
++ else
++ insw(data_addr, (u8 *)buf + (len & ~3), 1);
++ }
+ } else {
+- hwif->INSW(IDE_DATA_REG, buffer, wcount<<1);
++ if (mmio)
++ __ide_mm_insw((void __iomem *)data_addr, buf, len / 2);
++ else
++ insw(data_addr, buf, len / 2);
+ }
}
- /**
-- * 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).
+ /*
+ * This is used for most PIO data transfers *to* the IDE interface
*/
--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)
+-static void ata_output_data(ide_drive_t *drive, void *buffer, u32 wcount)
++static void ata_output_data(ide_drive_t *drive, struct request *rq,
++ void *buf, unsigned int len)
{
-- 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;
+- ide_hwif_t *hwif = HWIF(drive);
+- u8 io_32bit = drive->io_32bit;
++ ide_hwif_t *hwif = drive->hwif;
++ struct ide_io_ports *io_ports = &hwif->io_ports;
++ unsigned long data_addr = io_ports->data_addr;
++ u8 io_32bit = drive->io_32bit;
++ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 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);
+ 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);
+- local_irq_restore(flags);
+- } else
+- hwif->OUTSL(IDE_DATA_REG, buffer, wcount);
+- } else {
+- hwif->OUTSW(IDE_DATA_REG, buffer, wcount<<1);
+- }
+-}
+-
+-/*
+- * The following routines are mainly used by the ATAPI drivers.
+- *
+- * These routines will round up any request for an odd number of bytes,
+- * so if an odd bytecount is specified, be sure that there's at least one
+- * extra byte allocated for the buffer.
+- */
++ unsigned long uninitialized_var(flags);
-- /* 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;
-+ }
+-static void atapi_input_bytes(ide_drive_t *drive, void *buffer, u32 bytecount)
+-{
+- ide_hwif_t *hwif = HWIF(drive);
++ if ((io_32bit & 2) && !mmio) {
++ local_irq_save(flags);
++ ata_vlb_sync(io_ports->nsect_addr);
+ }
-+ 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);
+
+- ++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);
+- 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);
+-}
++ if (mmio)
++ __ide_mm_outsl((void __iomem *)data_addr, buf, len / 4);
++ else
++ outsl(data_addr, buf, len / 4);
+
+-static void atapi_output_bytes(ide_drive_t *drive, void *buffer, u32 bytecount)
+-{
+- ide_hwif_t *hwif = HWIF(drive);
++ if ((io_32bit & 2) && !mmio)
++ local_irq_restore(flags);
+
+- ++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);
+- return;
++ if ((len & 3) >= 2) {
++ if (mmio)
++ __ide_mm_outsw((void __iomem *)data_addr,
++ (u8 *)buf + (len & ~3), 1);
++ else
++ outsw(data_addr, (u8 *)buf + (len & ~3), 1);
+ }
-+ }
-+
-+ spin_unlock_irqrestore(&host->lock, flags);
-+
-+ return IRQ_RETVAL(handled);
++ } else {
++ if (mmio)
++ __ide_mm_outsw((void __iomem *)data_addr, buf, len / 2);
++ else
++ outsw(data_addr, buf, len / 2);
+ }
+-#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);
}
- /**
-- * 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)
+ void default_hwif_transport(ide_hwif_t *hwif)
{
- struct ata_ioports *ioaddr = &ap->ioaddr;
+- hwif->ata_input_data = ata_input_data;
+- hwif->ata_output_data = ata_output_data;
+- hwif->atapi_input_bytes = atapi_input_bytes;
+- hwif->atapi_output_bytes = atapi_output_bytes;
++ hwif->tf_load = ide_tf_load;
++ hwif->tf_read = ide_tf_read;
++
++ hwif->input_data = ata_input_data;
++ hwif->output_data = ata_output_data;
+ }
+
+ void ide_fix_driveid (struct hd_driveid *id)
+@@ -416,7 +474,7 @@ int drive_is_ready (ide_drive_t *drive)
+ u8 stat = 0;
+
+ if (drive->waiting_for_dma)
+- return hwif->ide_dma_test_irq(drive);
++ return hwif->dma_ops->dma_test_irq(drive);
-@@ -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.
+ #if 0
+ /* need to guarantee 400ns since last command was issued */
+@@ -429,7 +487,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.
*/
-- ata_chk_status(ap);
-+ ap->ops->sff_check_status(ap);
+- if (IDE_CONTROL_REG)
++ if (hwif->io_ports.ctl_addr)
+ stat = ide_read_altstatus(drive);
+ else
+ /* Note: this may clear a pending IRQ!! */
+@@ -567,6 +625,8 @@ static const struct drive_list_entry ivb_list[] = {
+ { "TSSTcorp CDDVDW SH-S202J" , "SB01" },
+ { "TSSTcorp CDDVDW SH-S202N" , "SB00" },
+ { "TSSTcorp CDDVDW SH-S202N" , "SB01" },
++ { "TSSTcorp CDDVDW SH-S202H" , "SB00" },
++ { "TSSTcorp CDDVDW SH-S202H" , "SB01" },
+ { NULL , NULL }
+ };
-- ap->ops->irq_clear(ap);
-+ ap->ops->sff_irq_clear(ap);
+@@ -631,7 +691,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->OUTBSYNC(drive, WIN_IDENTIFY, hwif->io_ports.command_addr);
+ timeout = jiffies + WAIT_WORSTCASE;
+ do {
+ if (time_after(jiffies, timeout)) {
+@@ -658,7 +718,7 @@ int ide_driveid_update(ide_drive_t *drive)
+ local_irq_restore(flags);
+ return 0;
+ }
+- hwif->ata_input_data(drive, id, SECTOR_WORDS);
++ hwif->input_data(drive, NULL, id, SECTOR_SIZE);
+ (void)ide_read_status(drive); /* clear drive IRQ */
+ local_irq_enable();
+ local_irq_restore(flags);
+@@ -680,6 +740,7 @@ int ide_driveid_update(ide_drive_t *drive)
+ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
+ {
+ ide_hwif_t *hwif = drive->hwif;
++ struct ide_io_ports *io_ports = &hwif->io_ports;
+ int error = 0;
+ u8 stat;
+
+@@ -687,8 +748,8 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
+ // msleep(50);
+
+ #ifdef CONFIG_BLK_DEV_IDEDMA
+- if (hwif->dma_host_set) /* check if host supports DMA */
+- hwif->dma_host_set(drive, 0);
++ if (hwif->dma_ops) /* check if host supports DMA */
++ hwif->dma_ops->dma_host_set(drive, 0);
+ #endif
+
+ /* Skip setting PIO flow-control modes on pre-EIDE drives */
+@@ -718,9 +779,9 @@ 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, io_ports->nsect_addr);
++ hwif->OUTB(SETFEATURES_XFER, io_ports->feature_addr);
++ hwif->OUTBSYNC(drive, WIN_SETFEATURES, io_ports->command_addr);
+ if (drive->quirk_list == 2)
+ ide_set_irq(drive, 1);
+
+@@ -745,8 +806,8 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
+ #ifdef CONFIG_BLK_DEV_IDEDMA
+ if ((speed >= XFER_SW_DMA_0 || (hwif->host_flags & IDE_HFLAG_VDMA)) &&
+ drive->using_dma)
+- hwif->dma_host_set(drive, 1);
+- else if (hwif->dma_host_set) /* check if host supports DMA */
++ hwif->dma_ops->dma_host_set(drive, 1);
++ else if (hwif->dma_ops) /* check if host supports DMA */
+ ide_dma_off_quietly(drive);
+ #endif
+
+@@ -828,7 +889,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.command_addr);
+ /*
+ * Drive takes 400nS to respond, we must avoid the IRQ being
+ * serviced before that.
+@@ -838,9 +899,19 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
+ ndelay(400);
+ spin_unlock_irqrestore(&ide_lock, flags);
}
+-
+ EXPORT_SYMBOL(ide_execute_command);
- /**
-- * 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)
++void ide_execute_pkt_cmd(ide_drive_t *drive)
+{
-+ 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 */
++ ide_hwif_t *hwif = drive->hwif;
++ unsigned long flags;
+
-+ return 0; /* nothing found */
++ spin_lock_irqsave(&ide_lock, flags);
++ hwif->OUTBSYNC(drive, WIN_PACKETCMD, hwif->io_ports.command_addr);
++ ndelay(400);
++ spin_unlock_irqrestore(&ide_lock, flags);
+}
++EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd);
+
+ /* needed below */
+ static ide_startstop_t do_reset1 (ide_drive_t *, int);
+@@ -891,10 +962,11 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
+ {
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
+ ide_hwif_t *hwif = HWIF(drive);
++ const struct ide_port_ops *port_ops = hwif->port_ops;
+ u8 tmp;
+
+- if (hwif->reset_poll != NULL) {
+- if (hwif->reset_poll(drive)) {
++ if (port_ops && port_ops->reset_poll) {
++ if (port_ops->reset_poll(drive)) {
+ printk(KERN_ERR "%s: host reset_poll failure for %s.\n",
+ hwif->name, drive->name);
+ return ide_stopped;
+@@ -960,6 +1032,8 @@ static void ide_disk_pre_reset(ide_drive_t *drive)
+
+ static void pre_reset(ide_drive_t *drive)
+ {
++ const struct ide_port_ops *port_ops = drive->hwif->port_ops;
+
-+/**
-+ * 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));
+ if (drive->media == ide_disk)
+ ide_disk_pre_reset(drive);
+ else
+@@ -980,8 +1054,8 @@ static void pre_reset(ide_drive_t *drive)
+ return;
+ }
+
+- if (HWIF(drive)->pre_reset != NULL)
+- HWIF(drive)->pre_reset(drive);
++ if (port_ops && port_ops->pre_reset)
++ port_ops->pre_reset(drive);
+
+ if (drive->current_speed != 0xff)
+ drive->desired_speed = drive->current_speed;
+@@ -1009,11 +1083,16 @@ 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;
+-
++ struct ide_io_ports *io_ports;
++ const struct ide_port_ops *port_ops;
++ u8 ctl;
+
-+ ap->ops->sff_tf_read(ap, &tf);
-+ err = tf.feature;
-+ if (r_err)
-+ *r_err = err;
+ spin_lock_irqsave(&ide_lock, flags);
+ hwif = HWIF(drive);
+ hwgroup = HWGROUP(drive);
+
++ io_ports = &hwif->io_ports;
+
-+ /* 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 */ ;
+ /* We must not reset with running handlers */
+ BUG_ON(hwgroup->handler != NULL);
+
+@@ -1023,7 +1102,7 @@ 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, io_ports->command_addr);
+ ndelay(400);
+ hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+ hwgroup->polling = 1;
+@@ -1039,7 +1118,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 (io_ports->ctl_addr == 0) {
+ spin_unlock_irqrestore(&ide_lock, flags);
+ return ide_stopped;
+ }
+@@ -1054,16 +1133,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, io_ports->ctl_addr);
+ /* 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
-+ 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;
++ ctl = drive->ctl | 2; /* clear SRST, leave nIEN */
++ hwif->OUTBSYNC(drive, ctl, io_ports->ctl_addr);
+ /* more than enough time */
+ udelay(10);
+ hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+@@ -1075,8 +1152,9 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
+ * state when the disks are reset this way. At least, the Winbond
+ * 553 documentation says that
+ */
+- if (hwif->resetproc)
+- hwif->resetproc(drive);
++ port_ops = hwif->port_ops;
++ if (port_ops && port_ops->resetproc)
++ port_ops->resetproc(drive);
+
+ spin_unlock_irqrestore(&ide_lock, flags);
+ return ide_started;
+@@ -1107,7 +1185,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
+ * about locking issues (2.5 work ?).
+ */
+ mdelay(1);
+- stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
++ stat = hwif->INB(hwif->io_ports.status_addr);
+ if ((stat & BUSY_STAT) == 0)
+ return 0;
+ /*
+diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
+index 7031a8d..47af80d 100644
+--- a/drivers/ide/ide-lib.c
++++ b/drivers/ide/ide-lib.c
+@@ -85,7 +85,7 @@ static u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
+ mode = XFER_PIO_4;
+ }
+
+-// printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed);
++/* printk("%s: mode 0x%02x, speed 0x%02x\n", __func__, mode, speed); */
+
+ return min(speed, mode);
+ }
+@@ -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)
+@@ -298,9 +288,11 @@ EXPORT_SYMBOL_GPL(ide_get_best_pio_mode);
+ void ide_set_pio(ide_drive_t *drive, u8 req_pio)
+ {
+ ide_hwif_t *hwif = drive->hwif;
++ const struct ide_port_ops *port_ops = hwif->port_ops;
+ u8 host_pio, pio;
+
+- if (hwif->set_pio_mode == NULL)
++ if (port_ops == NULL || port_ops->set_pio_mode == NULL ||
++ (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
+ return;
+
+ BUG_ON(hwif->pio_mask == 0x00);
+@@ -352,26 +344,30 @@ void ide_toggle_bounce(ide_drive_t *drive, int on)
+ int ide_set_pio_mode(ide_drive_t *drive, const u8 mode)
+ {
+ ide_hwif_t *hwif = drive->hwif;
++ const struct ide_port_ops *port_ops = hwif->port_ops;
+
-+ ap->ops->sff_dev_select(ap, 1);
++ if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
++ return 0;
+
+- if (hwif->set_pio_mode == NULL)
++ if (port_ops == NULL || port_ops->set_pio_mode == NULL)
+ return -1;
+
+ /*
+ * TODO: temporary hack for some legacy host drivers that didn't
+ * set transfer mode on the device in ->set_pio_mode method...
+ */
+- if (hwif->set_dma_mode == NULL) {
+- hwif->set_pio_mode(drive, mode - XFER_PIO_0);
++ if (port_ops->set_dma_mode == NULL) {
++ port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
+ return 0;
+ }
+
+ if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
+ if (ide_config_drive_speed(drive, mode))
+ return -1;
+- hwif->set_pio_mode(drive, mode - XFER_PIO_0);
++ port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
+ return 0;
+ } else {
+- hwif->set_pio_mode(drive, mode - XFER_PIO_0);
++ port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
+ return ide_config_drive_speed(drive, mode);
+ }
+ }
+@@ -379,17 +375,21 @@ int ide_set_pio_mode(ide_drive_t *drive, const u8 mode)
+ int ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
+ {
+ ide_hwif_t *hwif = drive->hwif;
++ const struct ide_port_ops *port_ops = hwif->port_ops;
+
-+ /* 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;
++ if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
++ return 0;
+
+- if (hwif->set_dma_mode == NULL)
++ if (port_ops == NULL || port_ops->set_dma_mode == NULL)
+ return -1;
+
+ if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
+ if (ide_config_drive_speed(drive, mode))
+ return -1;
+- hwif->set_dma_mode(drive, mode);
++ port_ops->set_dma_mode(drive, mode);
+ return 0;
+ } else {
+- hwif->set_dma_mode(drive, mode);
++ port_ops->set_dma_mode(drive, mode);
+ return ide_config_drive_speed(drive, mode);
+ }
+ }
+@@ -409,8 +409,10 @@ EXPORT_SYMBOL_GPL(ide_set_dma_mode);
+ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
+ {
+ ide_hwif_t *hwif = drive->hwif;
++ const struct ide_port_ops *port_ops = hwif->port_ops;
+
+- if (hwif->set_dma_mode == NULL)
++ if (port_ops == NULL || port_ops->set_dma_mode == NULL ||
++ (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
+ return -1;
+
+ rate = ide_rate_filter(drive, rate);
+@@ -485,7 +487,7 @@ static void ide_dump_sector(ide_drive_t *drive)
+ else
+ task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE;
+
+- ide_tf_read(drive, &task);
++ drive->hwif->tf_read(drive, &task);
+
+ if (lba48 || (tf->device & ATA_LBA))
+ printk(", LBAsect=%llu",
+diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
+index c14bb53..6a8953f 100644
+--- a/drivers/ide/ide-pnp.c
++++ b/drivers/ide/ide-pnp.c
+@@ -11,34 +11,52 @@
+ *
+ * You should have received a copy of the GNU General Public License
+ * (for example /usr/src/linux/COPYING); if not, write to the Free
+- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+ #include <linux/init.h>
+ #include <linux/pnp.h>
+ #include <linux/ide.h>
+
++#define DRV_NAME "ide-pnp"
+
-+ nsect = ioread8(ioaddr->nsect_addr);
-+ lbal = ioread8(ioaddr->lbal_addr);
-+ if ((nsect == 1) && (lbal == 1))
-+ break;
-+ msleep(50); /* give drive a breather */
-+ }
+ /* 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;
++ unsigned long base, ctl;
+
+ if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && pnp_irq_valid(dev, 0)))
+ return -1;
+
++ base = pnp_port_start(dev, 0);
++ ctl = pnp_port_start(dev, 1);
+
-+ rc = ata_sff_wait_ready(link, deadline);
-+ if (rc) {
-+ if (rc != -ENODEV)
-+ return rc;
-+ ret = rc;
-+ }
++ if (!request_region(base, 8, DRV_NAME)) {
++ printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
++ DRV_NAME, base, base + 7);
++ return -EBUSY;
+ }
+
-+ /* 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;
++ if (!request_region(ctl, 1, DRV_NAME)) {
++ printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
++ DRV_NAME, ctl);
++ release_region(base, 8);
++ return -EBUSY;
+ }
+
-+ /* 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);
+ memset(&hw, 0, sizeof(hw));
+- ide_std_init_ports(&hw, pnp_port_start(dev, 0),
+- pnp_port_start(dev, 1));
++ ide_std_init_ports(&hw, base, ctl);
+ 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,24 +65,27 @@ 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);
+
+ return 0;
+ }
+
++ release_region(ctl, 1);
++ release_region(base, 8);
+
-+ DPRINTK("EXIT, class=%u\n", *class);
-+ return rc;
+ return -1;
}
- /**
-- * 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;
+-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);
+- else
+- printk(KERN_ERR "idepnp: Unable to remove device, please report.\n");
++ ide_unregister(hwif);
+
-+ ata_std_postreset(link, classes);
++ release_region(pnp_port_start(dev, 1), 1);
++ release_region(pnp_port_start(dev, 0), 8);
+ }
+
+ static struct pnp_driver idepnp_driver = {
+diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
+index 47a1149..099a0fe 100644
+--- a/drivers/ide/ide-probe.c
++++ b/drivers/ide/ide-probe.c
+@@ -124,7 +124,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
+
+ id = drive->id;
+ /* read 512 bytes of id info */
+- hwif->ata_input_data(drive, id, SECTOR_WORDS);
++ hwif->input_data(drive, NULL, id, SECTOR_SIZE);
+
+ drive->id_read = 1;
+ local_irq_enable();
+@@ -264,6 +264,7 @@ err_misc:
+ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
++ struct ide_io_ports *io_ports = &hwif->io_ports;
+ int use_altstatus = 0, rc;
+ unsigned long timeout;
+ u8 s = 0, a = 0;
+@@ -271,7 +272,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
+ /* take a deep breath */
+ msleep(50);
+
+- if (IDE_CONTROL_REG) {
++ if (io_ports->ctl_addr) {
+ a = ide_read_altstatus(drive);
+ s = ide_read_status(drive);
+ if ((a ^ s) & ~INDEX_STAT)
+@@ -289,10 +290,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, io_ports->feature_addr);
+
+ /* ask drive for ID */
+- hwif->OUTB(cmd, IDE_COMMAND_REG);
++ hwif->OUTBSYNC(drive, cmd, io_ports->command_addr);
+
+ timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
+ timeout += jiffies;
+@@ -353,7 +354,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.ctl_addr) {
+ if (!hwif->irq) {
+ autoprobe = 1;
+ cookie = probe_irq_on();
+@@ -393,7 +394,7 @@ static int ide_busy_sleep(ide_hwif_t *hwif)
+
+ do {
+ msleep(50);
+- stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
++ stat = hwif->INB(hwif->io_ports.status_addr);
+ if ((stat & BUSY_STAT) == 0)
+ return 0;
+ } while (time_before(jiffies, timeout));
+@@ -425,6 +426,7 @@ static int ide_busy_sleep(ide_hwif_t *hwif)
+ static int do_probe (ide_drive_t *drive, u8 cmd)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
++ struct ide_io_ports *io_ports = &hwif->io_ports;
+ int rc;
+ u8 stat;
+
+@@ -445,7 +447,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(io_ports->device_addr) != drive->select.all &&
++ !drive->present) {
+ if (drive->select.b.unit != 0) {
+ /* exit with drive0 selected */
+ SELECT_DRIVE(&hwif->drives[0]);
+@@ -471,15 +474,13 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
+ if (stat == (BUSY_STAT | READY_STAT))
+ return 4;
+
+- if ((rc == 1 && cmd == WIN_PIDENTIFY) &&
+- ((drive->autotune == IDE_TUNE_DEFAULT) ||
+- (drive->autotune == IDE_TUNE_AUTO))) {
++ if (rc == 1 && cmd == WIN_PIDENTIFY) {
+ 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, io_ports->device_addr);
+ msleep(50);
+- hwif->OUTB(WIN_SRST, IDE_COMMAND_REG);
++ hwif->OUTBSYNC(drive, WIN_SRST, io_ports->command_addr);
+ (void)ide_busy_sleep(hwif);
+ rc = try_to_identify(drive, cmd);
+ }
+@@ -515,7 +516,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->OUTBSYNC(drive, EXABYTE_ENABLE_NEST, hwif->io_ports.command_addr);
+
+ if (ide_busy_sleep(hwif)) {
+ printk(KERN_CONT "failed (timeout)\n");
+@@ -623,7 +624,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 +640,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);
++ __func__, ret);
++ goto out;
++ }
+
-+ /* 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);
++ get_device(&hwif->gendev);
+
-+ /* bail out if no device is present */
-+ if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
-+ DPRINTK("EXIT, no device\n");
-+ return;
++ 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;
+ }
+
+ /**
+@@ -756,8 +771,7 @@ static int ide_probe_port(ide_hwif_t *hwif)
+
+ BUG_ON(hwif->present);
+
+- if (hwif->noprobe ||
+- (hwif->drives[0].noprobe && hwif->drives[1].noprobe))
++ if (hwif->drives[0].noprobe && hwif->drives[1].noprobe)
+ return -EACCES;
+
+ /*
+@@ -784,14 +798,9 @@ static int ide_probe_port(ide_hwif_t *hwif)
+ if (drive->present)
+ rc = 0;
+ }
+- if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) {
+- printk(KERN_WARNING "%s: reset\n", hwif->name);
+- hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
+- udelay(10);
+- hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
+- (void)ide_busy_sleep(hwif);
+- }
+
-+ /* set up device control */
-+ if (ap->ioaddr.ctl_addr)
-+ iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
-+}
+ local_irq_restore(flags);
+
-+/**
-+ * 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,
+ /*
+ * Use cached IRQ number. It might be (and is...) changed by probe
+ * code above
+@@ -804,29 +813,25 @@ static int ide_probe_port(ide_hwif_t *hwif)
- ap->hsm_task_state = HSM_ST_IDLE;
+ static void ide_port_tune_devices(ide_hwif_t *hwif)
+ {
++ const struct ide_port_ops *port_ops = hwif->port_ops;
+ int unit;
-- 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;
+ for (unit = 0; unit < MAX_DRIVES; unit++) {
+ ide_drive_t *drive = &hwif->drives[unit];
-@@ -442,9 +2034,9 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
- ap->ops->bmdma_stop(qc);
+- if (drive->present && hwif->quirkproc)
+- hwif->quirkproc(drive);
++ if (drive->present && port_ops && port_ops->quirkproc)
++ port_ops->quirkproc(drive);
}
-- 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);
+ for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ ide_drive_t *drive = &hwif->drives[unit];
- spin_unlock_irqrestore(ap->lock, flags);
+ if (drive->present) {
+- if (drive->autotune == IDE_TUNE_AUTO)
+- ide_set_max_pio(drive);
+-
+- if (drive->autotune != IDE_TUNE_DEFAULT &&
+- drive->autotune != IDE_TUNE_AUTO)
+- continue;
++ ide_set_max_pio(drive);
-@@ -452,40 +2044,27 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
- ata_eh_thaw_port(ap);
+ drive->nice1 = 1;
- /* 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 (hwif->dma_host_set)
++ if (hwif->dma_ops)
+ ide_set_dma(drive);
+ }
+ }
+@@ -949,6 +954,7 @@ static void ide_port_setup_devices(ide_hwif_t *hwif)
+ {
+ int i;
-- 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;
++ mutex_lock(&ide_cfg_mtx);
+ for (i = 0; i < MAX_DRIVES; i++) {
+ ide_drive_t *drive = &hwif->drives[i];
-- 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);
+@@ -963,6 +969,7 @@ static void ide_port_setup_devices(ide_hwif_t *hwif)
+
+ ide_add_drive_to_hwgroup(drive);
+ }
++ mutex_unlock(&ide_cfg_mtx);
}
- /**
-- * 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)
+ /*
+@@ -975,6 +982,7 @@ static void ide_port_setup_devices(ide_hwif_t *hwif)
*/
--void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
-+void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc)
+ static int init_irq (ide_hwif_t *hwif)
{
- 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.
- */
++ struct ide_io_ports *io_ports = &hwif->io_ports;
+ unsigned int index;
+ ide_hwgroup_t *hwgroup;
+ ide_hwif_t *match = NULL;
+@@ -1058,9 +1066,9 @@ static int init_irq (ide_hwif_t *hwif)
+ if (IDE_CHIPSET_IS_PCI(hwif->chipset))
+ sa = IRQF_SHARED;
+
+- if (hwif->io_ports[IDE_CONTROL_OFFSET])
++ if (io_ports->ctl_addr)
+ /* clear nIEN */
+- hwif->OUTB(0x08, hwif->io_ports[IDE_CONTROL_OFFSET]);
++ hwif->OUTB(0x08, io_ports->ctl_addr);
+
+ if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup))
+ goto out_unlink;
+@@ -1076,20 +1084,17 @@ static int init_irq (ide_hwif_t *hwif)
+
+ #if !defined(__mc68000__)
+ printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
+- hwif->io_ports[IDE_DATA_OFFSET],
+- hwif->io_ports[IDE_DATA_OFFSET]+7,
+- hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq);
++ io_ports->data_addr, io_ports->status_addr,
++ io_ports->ctl_addr, hwif->irq);
+ #else
+ printk("%s at 0x%08lx on irq %d", hwif->name,
+- hwif->io_ports[IDE_DATA_OFFSET], hwif->irq);
++ io_ports->data_addr, hwif->irq);
+ #endif /* __mc68000__ */
+ if (match)
+ printk(" (%sed with %s)",
+ hwif->sharing_irq ? "shar" : "serializ", match->name);
+ printk("\n");
+
+- ide_port_setup_devices(hwif);
-
- int ata_sff_port_start(struct ata_port *ap)
+ mutex_unlock(&ide_cfg_mtx);
+ return 0;
+ out_unlink:
+@@ -1199,6 +1204,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,24 +1221,21 @@ 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)
{
- if (ap->ioaddr.bmdma_addr)
-@@ -512,24 +2090,262 @@ int ata_sff_port_start(struct ata_port *ap)
- return 0;
- }
+ int old_irq;
--#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;
-+}
+ if (!hwif->irq) {
+- if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET])))
+- {
++ hwif->irq = ide_default_irq(hwif->io_ports.data_addr);
++ if (!hwif->irq) {
+ printk("%s: DISABLED, NO IRQ\n", hwif->name);
+ 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 */
--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)
+ if (register_blkdev(hwif->major, hwif->name))
+ return 0;
+@@ -1256,7 +1260,8 @@ static int hwif_init(ide_hwif_t *hwif)
+ * It failed to initialise. Find the default IRQ for
+ * this port and try that.
+ */
+- if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) {
++ hwif->irq = ide_default_irq(hwif->io_ports.data_addr);
++ if (!hwif->irq) {
+ printk("%s: Disabled unable to get IRQ %d.\n",
+ hwif->name, old_irq);
+ goto out;
+@@ -1308,6 +1313,7 @@ static void hwif_register_devices(ide_hwif_t *hwif)
+
+ static void ide_port_init_devices(ide_hwif_t *hwif)
{
-- int i;
-+ /* Filter out DMA modes if the device has been configured by
-+ the BIOS as PIO only */
++ const struct ide_port_ops *port_ops = hwif->port_ops;
+ 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;
-+ if (adev->link->ap->ioaddr.bmdma_addr == NULL)
-+ xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
-+ return xfer_mask;
+ for (i = 0; i < MAX_DRIVES; i++) {
+@@ -1319,12 +1325,10 @@ static void ide_port_init_devices(ide_hwif_t *hwif)
+ drive->unmask = 1;
+ if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS)
+ drive->no_unmask = 1;
+- if ((hwif->host_flags & IDE_HFLAG_NO_AUTOTUNE) == 0)
+- drive->autotune = 1;
+ }
+
+- if (hwif->port_init_devs)
+- hwif->port_init_devs(hwif);
++ if (port_ops && port_ops->port_init_devs)
++ port_ops->port_init_devs(hwif);
+ }
+
+ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
+@@ -1339,9 +1343,6 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
+ if (d->init_iops)
+ d->init_iops(hwif);
+
+- if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0)
+- ide_hwif_setup_dma(hwif, d);
+-
+ if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) ||
+ (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS))
+ hwif->irq = port ? 15 : 14;
+@@ -1349,16 +1350,36 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
+ hwif->host_flags = d->host_flags;
+ hwif->pio_mask = d->pio_mask;
+
+- if ((d->host_flags & IDE_HFLAG_SERIALIZE) && hwif->mate)
+- hwif->mate->serialized = hwif->serialized = 1;
++ /* ->set_pio_mode for DTC2278 is currently limited to port 0 */
++ if (hwif->chipset != ide_dtc2278 || hwif->channel == 0)
++ hwif->port_ops = d->port_ops;
++
++ if ((d->host_flags & IDE_HFLAG_SERIALIZE) ||
++ ((d->host_flags & IDE_HFLAG_SERIALIZE_DMA) && hwif->dma_base)) {
++ if (hwif->mate)
++ hwif->mate->serialized = hwif->serialized = 1;
++ }
+
+ hwif->swdma_mask = d->swdma_mask;
+ hwif->mwdma_mask = d->mwdma_mask;
+ hwif->ultra_mask = d->udma_mask;
+
+- /* reset DMA masks only for SFF-style DMA controllers */
+- if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0 && hwif->dma_base == 0)
+- hwif->swdma_mask = hwif->mwdma_mask = hwif->ultra_mask = 0;
++ if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) {
++ int rc;
++
++ if (d->init_dma)
++ rc = d->init_dma(hwif, d);
++ else
++ rc = ide_hwif_setup_dma(hwif, d);
++
++ if (rc < 0) {
++ printk(KERN_INFO "%s: DMA disabled\n", hwif->name);
++ hwif->swdma_mask = 0;
++ hwif->mwdma_mask = 0;
++ hwif->ultra_mask = 0;
++ } else if (d->dma_ops)
++ hwif->dma_ops = d->dma_ops;
++ }
+
+ if (d->host_flags & IDE_HFLAG_RQSIZE_256)
+ hwif->rqsize = 256;
+@@ -1366,26 +1387,138 @@ 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);
+}
+
+- if (hwif->cable_detect && (hwif->ultra_mask & 0x78)) {
++static void ide_port_cable_detect(ide_hwif_t *hwif)
++{
++ const struct ide_port_ops *port_ops = hwif->port_ops;
+
-+/**
-+ * 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)
++ if (port_ops && port_ops->cable_detect && (hwif->ultra_mask & 0x78)) {
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+- hwif->cbl = hwif->cable_detect(hwif);
++ hwif->cbl = port_ops->cable_detect(hwif);
+ }
+ }
+
++static ssize_t store_delete_devices(struct device *portdev,
++ struct device_attribute *attr,
++ const char *buf, size_t n)
+{
-+ struct ata_port *ap = qc->ap;
-+ unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
-+ u8 dmactl;
++ ide_hwif_t *hwif = dev_get_drvdata(portdev);
+
-+ /* 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 (strncmp(buf, "1", n))
++ return -EINVAL;
+
-+ /* 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);
++ ide_port_unregister_devices(hwif);
+
-+ /* issue r/w command */
-+ ap->ops->sff_exec_command(ap, &qc->tf);
-+}
++ return n;
++};
+
-+/**
-+ * 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)
++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)
+{
-+ struct ata_port *ap = qc->ap;
-+ u8 dmactl;
++ ide_hwif_t *hwif = dev_get_drvdata(portdev);
+
-+ /* 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);
++ if (strncmp(buf, "1", n))
++ return -EINVAL;
+
-+ /* 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
-+ */
-+}
++ ide_port_unregister_devices(hwif);
++ ide_port_scan(hwif);
+
-+/**
-+ * 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)
++ 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)
+{
-+ struct ata_port *ap = qc->ap;
-+ void __iomem *mmio = ap->ioaddr.bmdma_addr;
++ int i, rc;
+
-+ /* clear start/stop bit */
-+ iowrite8(ioread8(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
-+ mmio + ATA_DMA_CMD);
++ for (i = 0; ide_port_attrs[i]; i++) {
++ rc = device_create_file(hwif->portdev, ide_port_attrs[i]);
++ if (rc)
++ break;
++ }
+
-+ /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
-+ ata_sff_altstatus(ap); /* dummy read */
++ return rc;
+}
+
+/**
-+ * 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.
++ * ide_find_port_slot - find free ide_hwifs[] slot
++ * @d: IDE port info
+ *
-+ * LOCKING:
-+ * spin_lock_irqsave(host lock)
++ * Return the new hwif. If we are out of free slots return NULL.
+ */
-+u8 ata_bmdma_status(struct ata_port *ap)
++
++ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d)
+{
-+ return ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
++ 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);
+
-+/**
-+ * 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;
+ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+ {
+ ide_hwif_t *hwif, *mate = NULL;
+ int i, rc = 0;
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+- if (d == NULL || idx[i] == 0xff) {
++ if (idx[i] == 0xff) {
+ mate = NULL;
+ continue;
+ }
+
+ hwif = &ide_hwifs[idx[i]];
+
++ ide_port_apply_params(hwif);
+
-+ DPRINTK("ENTER, host %u, port %u\n", ap->print_id, ap->port_no);
++ if (d == NULL) {
++ mate = NULL;
++ continue;
++ }
+
-+ /* 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 (d->chipset != ide_etrax100 && (i & 1) && mate) {
+ hwif->mate = mate;
+ mate->mate = hwif;
+@@ -1394,6 +1527,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);
}
-- return 1;
+
+@@ -1403,25 +1537,15 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+
+ hwif = &ide_hwifs[idx[i]];
+
+- if ((hwif->chipset != ide_4drives || !hwif->mate ||
+- !hwif->mate->present) && ide_hwif_request_regions(hwif)) {
+- printk(KERN_ERR "%s: ports already in use, "
+- "skipping probe\n", hwif->name);
+- continue;
+- }
+-
+- if (ide_probe_port(hwif) < 0) {
+- ide_hwif_release_regions(hwif);
+- continue;
+- }
+-
+- hwif->present = 1;
++ if (ide_probe_port(hwif) == 0)
++ hwif->present = 1;
+
+ if (hwif->chipset != ide_4drives || !hwif->mate ||
+ !hwif->mate->present)
+ ide_register_port(hwif);
+
+- ide_port_tune_devices(hwif);
++ if (hwif->present)
++ ide_port_tune_devices(hwif);
+ }
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+@@ -1430,9 +1554,6 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+
+ hwif = &ide_hwifs[idx[i]];
+
+- if (!hwif->present)
+- continue;
+-
+ if (hwif_init(hwif) == 0) {
+ printk(KERN_INFO "%s: failed to initialize IDE "
+ "interface\n", hwif->name);
+@@ -1441,8 +1562,13 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+ continue;
+ }
+
++ if (hwif->present)
++ ide_port_setup_devices(hwif);
+
-+ if (dev0)
-+ devmask |= (1 << 0);
-+ if (dev1)
-+ devmask |= (1 << 1);
+ ide_acpi_init(hwif);
+- ide_acpi_port_init_devices(hwif);
+
-+ /* select device 0 again */
-+ ap->ops->sff_dev_select(ap, 0);
++ if (hwif->present)
++ ide_acpi_port_init_devices(hwif);
+ }
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+@@ -1451,12 +1577,11 @@ 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)
+- hwif->chipset = ide_generic;
++ if (hwif->chipset == ide_unknown)
++ hwif->chipset = ide_generic;
+
-+ /* 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;
-+ }
++ if (hwif->present)
+ hwif_register_devices(hwif);
+- }
+ }
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+@@ -1465,10 +1590,11 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+
+ hwif = &ide_hwifs[idx[i]];
+
+- if (hwif->present) {
+- ide_proc_register_port(hwif);
++ ide_sysfs_register_port(hwif);
++ ide_proc_register_port(hwif);
+
-+ /*
-+ * 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);
++ if (hwif->present)
+ ide_proc_port_register_devices(hwif);
+- }
+ }
+
+ return rc;
+@@ -1486,3 +1612,86 @@ 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);
+
-+ /* 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);
++void ide_port_scan(ide_hwif_t *hwif)
++{
++ ide_port_apply_params(hwif);
++ ide_port_cable_detect(hwif);
++ ide_port_init_devices(hwif);
+
-+ /* 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 (ide_probe_port(hwif) < 0)
++ return;
+
-+ 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);
++ 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);
++
++static void ide_legacy_init_one(u8 *idx, hw_regs_t *hw, u8 port_no,
++ const struct ide_port_info *d,
++ unsigned long config)
++{
++ ide_hwif_t *hwif;
++ unsigned long base, ctl;
++ int irq;
++
++ if (port_no == 0) {
++ base = 0x1f0;
++ ctl = 0x3f6;
++ irq = 14;
++ } else {
++ base = 0x170;
++ ctl = 0x376;
++ irq = 15;
+ }
+
-+ DPRINTK("EXIT\n");
-+ return;
++ if (!request_region(base, 8, d->name)) {
++ printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
++ d->name, base, base + 7);
++ return;
++ }
+
-+err_out:
-+ ata_port_printk(ap, KERN_ERR, "disabling port\n");
-+ ata_port_disable(ap);
++ if (!request_region(ctl, 1, d->name)) {
++ printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
++ d->name, ctl);
++ release_region(base, 8);
++ return;
++ }
+
-+ DPRINTK("EXIT\n");
- }
-
-+#ifdef CONFIG_PCI
++ ide_std_init_ports(hw, base, ctl);
++ hw->irq = irq;
+
- /**
-- * 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)
++ hwif = ide_find_port_slot(d);
++ if (hwif) {
++ ide_init_port_hw(hwif, hw);
++ if (config)
++ hwif->config_data = config;
++ idx[port_no] = hwif->index;
++ }
++}
++
++int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config)
+{
-+ unsigned long bmdma = pci_resource_start(pdev, 4);
-+ u8 simplex;
++ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++ hw_regs_t hw[2];
+
-+ if (bmdma == 0)
++ memset(&hw, 0, sizeof(hw));
++
++ if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0)
++ ide_legacy_init_one(idx, &hw[0], 0, d, config);
++ ide_legacy_init_one(idx, &hw[1], 1, d, config);
++
++ if (idx[0] == 0xff && idx[1] == 0xff &&
++ (d->host_flags & IDE_HFLAG_SINGLE))
+ return -ENOENT;
+
-+ simplex = inb(bmdma + 0x02);
-+ outb(simplex & 0x60, bmdma + 0x02);
-+ simplex = inb(bmdma + 0x02);
-+ if (simplex & 0x80)
-+ return -EOPNOTSUPP;
++ ide_device_add(idx, d);
++
+ 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.
++EXPORT_SYMBOL_GPL(ide_legacy_device_add);
+diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
+index bab88ca..8d6ad81 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.
*/
--int ata_pci_init_bmdma(struct ata_host *host)
-+int ata_pci_bmdma_init(struct ata_host *host)
+
+-static void __ide_remove_setting (ide_drive_t *drive, char *name)
++static void __ide_remove_setting(ide_drive_t *drive, char *name)
{
- 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)
+ 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);
}
-+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)
+ #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)
{
- 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);
+- 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);
+ }
- 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)
+ 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);
}
- /**
-- * 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)
+ 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)
+@@ -601,14 +599,14 @@ static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
+ err = device_attach(dev);
+ if (err < 0)
+ printk(KERN_WARNING "IDE: %s: device_attach error: %d\n",
+- __FUNCTION__, err);
++ __func__, err);
+ drive->driver_req[0] = 0;
+ if (dev->driver == NULL) {
+ err = device_attach(dev);
+ if (err < 0)
+ printk(KERN_WARNING
+ "IDE: %s: device_attach(2) error: %d\n",
+- __FUNCTION__, err);
++ __func__, err);
+ }
+ if (dev->driver && !strcmp(dev->driver->name, driver))
+ ret = 0;
+@@ -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)
{
-@@ -696,12 +2526,12 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev,
- goto err_out;
+ 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;
}
+ }
-- rc = ata_pci_init_sff_host(host);
-+ rc = ata_pci_sff_init_host(host);
- if (rc)
- goto err_out;
+-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 },
+@@ -804,19 +786,9 @@ void ide_proc_register_port(ide_hwif_t *hwif)
+ }
+ }
- /* init DMA related stuff */
-- rc = ata_pci_init_bmdma(host);
-+ rc = ata_pci_bmdma_init(host);
- if (rc)
- goto err_bmdma;
+-#ifdef CONFIG_BLK_DEV_IDEPCI
+-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;
+@@ -840,7 +812,7 @@ static int ide_drivers_show(struct seq_file *s, void *p)
+ err = bus_for_each_drv(&ide_bus_type, NULL, s, proc_print_driver);
+ if (err < 0)
+ printk(KERN_WARNING "IDE: %s: bus_for_each_drv error: %d\n",
+- __FUNCTION__, err);
++ __func__, err);
+ return 0;
+ }
-@@ -722,7 +2552,7 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+@@ -850,6 +822,7 @@ static int ide_drivers_open(struct inode *inode, struct file *file)
}
- /**
-- * 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)
+ static const struct file_operations ide_drivers_operations = {
++ .owner = THIS_MODULE,
+ .open = ide_drivers_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -858,16 +831,12 @@ static const struct file_operations ide_drivers_operations = {
+
+ void proc_ide_create(void)
{
-@@ -815,9 +2645,11 @@ int ata_pci_activate_sff_host(struct ata_host *host,
+- struct proc_dir_entry *entry;
+-
+ proc_ide_root = proc_mkdir("ide", NULL);
+
+ if (!proc_ide_root)
+ return;
+
+- entry = create_proc_entry("drivers", 0, proc_ide_root);
+- if (entry)
+- entry->proc_fops = &ide_drivers_operations;
++ proc_create("drivers", 0, proc_ide_root, &ide_drivers_operations);
}
- /**
-- * 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.
+ void proc_ide_destroy(void)
+diff --git a/drivers/ide/ide-scan-pci.c b/drivers/ide/ide-scan-pci.c
+index 93d2e41..0e79eff 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
+@@ -107,7 +102,7 @@ static int __init ide_scan_pcibus(void)
+ if (__pci_register_driver(d, d->driver.owner,
+ d->driver.mod_name))
+ printk(KERN_ERR "%s: failed to register %s driver\n",
+- __FUNCTION__, d->driver.mod_name);
++ __func__, d->driver.mod_name);
+ }
+
+ return 0;
+diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
+index 0598ecf..1e1f263 100644
+--- a/drivers/ide/ide-tape.c
++++ b/drivers/ide/ide-tape.c
+@@ -72,26 +72,6 @@ enum {
+ #endif
+
+ /**************************** Tunable parameters *****************************/
+-
+-
+-/*
+- * Pipelined mode parameters.
+- *
+- * We try to use the minimum number of stages which is enough to keep the tape
+- * constantly streaming. To accomplish that, we implement a feedback loop around
+- * the maximum number of stages:
+- *
+- * We start from MIN maximum stages (we will not even use MIN stages if we don't
+- * need them), increment it by RATE*(MAX-MIN) whenever we sense that the
+- * pipeline is empty, until we reach the optimum value or until we reach MAX.
+- *
+- * Setting the following parameter to 0 is illegal: the pipelined mode cannot be
+- * disabled (idetape_calculate_speeds() divides by tape->max_stages.)
+- */
+-#define IDETAPE_MIN_PIPELINE_STAGES 1
+-#define IDETAPE_MAX_PIPELINE_STAGES 400
+-#define IDETAPE_INCREASE_STAGES_RATE 20
+-
+ /*
+ * After each failed packet command we issue a request sense command and retry
+ * the packet command IDETAPE_MAX_PC_RETRIES times.
+@@ -181,56 +161,59 @@ 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.
*/
--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;
+-/* 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
+-
+-/* A pipeline stage. */
+-typedef struct idetape_stage_s {
+- struct request rq; /* The corresponding request */
+- struct idetape_bh *bh; /* The data buffers */
+- struct idetape_stage_s *next; /* Pointer to the next stage */
+-} idetape_stage_t;
++
++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),
++ /* Attempt to auto-detect the current user block size */
++ IDETAPE_FLAG_DETECT_BS = (1 << 3),
++ /* Currently on a filemark */
++ IDETAPE_FLAG_FILEMARK = (1 << 4),
++ /* DRQ interrupt device */
++ IDETAPE_FLAG_DRQ_INTERRUPT = (1 << 5),
++ /* 0 = no tape is loaded, so we don't rewind after ejecting */
++ IDETAPE_FLAG_MEDIUM_PRESENT = (1 << 6),
++};
- /* 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;
+ /*
+ * Most of our global data which we need to save even as we leave the driver due
+@@ -258,11 +241,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];
+@@ -275,9 +258,7 @@ typedef struct ide_tape_obj {
+ * While polling for DSC we use postponed_rq to postpone the current
+ * request so that ide.c will be able to service pending requests on the
+ * other device. Note that at most we will have only one DSC (usually
+- * data transfer) request in the device request queue. Additional
+- * requests can be queued in our internal pipeline, but they will be
+- * visible to ide.c only one at a time.
++ * data transfer) request in the device request queue.
+ */
+ struct request *postponed_rq;
+ /* The time in which we started polling for DSC */
+@@ -317,43 +298,20 @@ typedef struct ide_tape_obj {
+ * At most, there is only one ide-tape originated data transfer request
+ * in the device request queue. This allows ide.c to easily service
+ * requests from the other device when we postpone our active request.
+- * In the pipelined operation mode, we use our internal pipeline
+- * structure to hold more data requests. The data buffer size is chosen
+- * based on the tape's recommendation.
+ */
+- /* ptr to the request which is waiting in the device request queue */
+- struct request *active_data_rq;
++
+ /* Data buffer size chosen based on the tape's recommendation */
+- int stage_size;
+- idetape_stage_t *merge_stage;
+- int merge_stage_size;
++ int buffer_size;
++ /* merge buffer */
++ struct idetape_bh *merge_bh;
++ /* size of the merge buffer */
++ int merge_bh_size;
++ /* pointer to current buffer head within the merge buffer */
+ struct idetape_bh *bh;
+ char *b_data;
+ int b_count;
- 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;
+- /*
+- * Pipeline parameters.
+- *
+- * To accomplish non-pipelined mode, we simply set the following
+- * variables to zero (or NULL, where appropriate).
+- */
+- /* Number of currently used stages */
+- int nr_stages;
+- /* Number of pending stages */
+- int nr_pending_stages;
+- /* We will not allocate more than this number of stages */
+- int max_stages, min_pipeline, max_pipeline;
+- /* The first stage which will be removed from the pipeline */
+- idetape_stage_t *first_stage;
+- /* The currently active stage */
+- idetape_stage_t *active_stage;
+- /* Will be serviced after the currently active request */
+- idetape_stage_t *next_stage;
+- /* New requests will be added to the pipeline here */
+- idetape_stage_t *last_stage;
+- /* Optional free stage which we can use */
+- idetape_stage_t *cache_stage;
+- int pages_per_stage;
++ int pages_per_buffer;
+ /* Wasted space in each stage */
+ int excess_bh_size;
+
+@@ -374,45 +332,6 @@ typedef struct ide_tape_obj {
+ /* the tape is write protected (hardware or opened as read-only) */
+ char write_prot;
+
+- /*
+- * Limit the number of times a request can be postponed, to avoid an
+- * infinite postpone deadlock.
+- */
+- int postpone_cnt;
+-
+- /*
+- * Measures number of frames:
+- *
+- * 1. written/read to/from the driver pipeline (pipeline_head).
+- * 2. written/read to/from the tape buffers (idetape_bh).
+- * 3. written/read by the tape to/from the media (tape_head).
+- */
+- int pipeline_head;
+- int buffer_head;
+- int tape_head;
+- int last_tape_head;
+-
+- /* Speed control at the tape buffers input/output */
+- unsigned long insert_time;
+- int insert_size;
+- int insert_speed;
+- int max_insert_speed;
+- int measure_insert_time;
+-
+- /* Speed regulation negative feedback loop */
+- int speed_control;
+- int pipeline_head_speed;
+- int controlled_pipeline_head_speed;
+- int uncontrolled_pipeline_head_speed;
+- int controlled_last_pipeline_head;
+- unsigned long uncontrolled_pipeline_head_time;
+- unsigned long controlled_pipeline_head_time;
+- int controlled_previous_pipeline_head;
+- int uncontrolled_previous_pipeline_head;
+- unsigned long controlled_previous_head_time;
+- unsigned long uncontrolled_previous_head_time;
+- int restart_speed_control_req;
+-
+ u32 debug_mask;
+ } idetape_tape_t;
+
+@@ -446,58 +365,6 @@ static void ide_tape_put(struct ide_tape_obj *tape)
+ mutex_unlock(&idetape_ref_mutex);
}
--/**
-- * ata_pci_clear_simplex - attempt to kick device out of simplex
-- * @pdev: PCI device
+-/* 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.
- *
-- * 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.
+- * 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.
- */
-
--int ata_pci_clear_simplex(struct pci_dev *pdev)
+-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 +385,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)
-{
-- unsigned long bmdma = pci_resource_start(pdev, 4);
-- u8 simplex;
+- while (bcount--)
+- (void) HWIF(drive)->INB(IDE_DATA_REG);
+-}
-
-- if (bmdma == 0)
-- return -ENOENT;
+-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,13 +395,13 @@ 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_pad_transfer(drive, 0, bcount);
+ return;
+ }
+ count = min(
+ (unsigned int)(bh->b_size - atomic_read(&bh->b_count)),
+ bcount);
+- HWIF(drive)->atapi_input_bytes(drive, bh->b_data +
++ drive->hwif->input_data(drive, NULL, bh->b_data +
+ atomic_read(&bh->b_count), count);
+ bcount -= count;
+ atomic_add(count, &bh->b_count);
+@@ -557,7 +414,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;
+@@ -570,7 +427,7 @@ static void idetape_output_buffers(ide_drive_t *drive, idetape_pc_t *pc,
+ return;
+ }
+ count = min((unsigned int)pc->b_count, (unsigned int)bcount);
+- HWIF(drive)->atapi_output_bytes(drive, pc->b_data, count);
++ drive->hwif->output_data(drive, NULL, pc->b_data, count);
+ bcount -= count;
+ pc->b_data += count;
+ pc->b_count -= count;
+@@ -585,13 +442,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 +471,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 +506,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 +525,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 +534,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,153 +554,61 @@ 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;
+ }
+ }
+
+-static void idetape_activate_next_stage(ide_drive_t *drive)
++/* Free data buffers completely. */
++static void ide_tape_kfree_buffer(idetape_tape_t *tape)
+ {
+- idetape_tape_t *tape = drive->driver_data;
+- idetape_stage_t *stage = tape->next_stage;
+- struct request *rq = &stage->rq;
++ struct idetape_bh *prev_bh, *bh = tape->merge_bh;
+
+- debug_log(DBG_PROCS, "Enter %s\n", __func__);
++ while (bh) {
++ u32 size = bh->b_size;
+
+- if (stage == NULL) {
+- printk(KERN_ERR "ide-tape: bug: Trying to activate a non"
+- " existing stage\n");
+- return;
+- }
++ while (size) {
++ unsigned int order = fls(size >> PAGE_SHIFT)-1;
+
+- rq->rq_disk = tape->disk;
+- rq->buffer = NULL;
+- rq->special = (void *)stage->bh;
+- tape->active_data_rq = rq;
+- tape->active_stage = stage;
+- tape->next_stage = stage->next;
+-}
-
-- simplex = inb(bmdma + 0x02);
-- outb(simplex & 0x60, bmdma + 0x02);
-- simplex = inb(bmdma + 0x02);
-- if (simplex & 0x80)
-- return -EOPNOTSUPP;
-- return 0;
+-/* Free a stage along with its related buffers completely. */
+-static void __idetape_kfree_stage(idetape_stage_t *stage)
+-{
+- struct idetape_bh *prev_bh, *bh = stage->bh;
+- int size;
+-
+- while (bh != NULL) {
+- if (bh->b_data != NULL) {
+- size = (int) bh->b_size;
+- while (size > 0) {
+- free_page((unsigned long) bh->b_data);
+- size -= PAGE_SIZE;
+- bh->b_data += PAGE_SIZE;
+- }
++ if (bh->b_data)
++ free_pages((unsigned long)bh->b_data, order);
++
++ size &= (order-1);
++ bh->b_data += (1 << order) * PAGE_SIZE;
+ }
+ prev_bh = bh;
+ bh = bh->b_reqnext;
+ kfree(prev_bh);
+ }
+- kfree(stage);
-}
-
--unsigned long ata_pci_default_filter(struct ata_device *adev, unsigned long xfer_mask)
+-static void idetape_kfree_stage(idetape_tape_t *tape, idetape_stage_t *stage)
-{
-- /* Filter out DMA modes if the device has been configured by
-- the BIOS as PIO only */
+- __idetape_kfree_stage(stage);
+-}
-
-- if (adev->link->ap->ioaddr.bmdma_addr == NULL)
-- xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
-- return xfer_mask;
+-/*
+- * Remove tape->first_stage from the pipeline. The caller should avoid race
+- * conditions.
+- */
+-static void idetape_remove_stage_head(ide_drive_t *drive)
+-{
+- idetape_tape_t *tape = drive->driver_data;
+- idetape_stage_t *stage;
+-
+- debug_log(DBG_PROCS, "Enter %s\n", __func__);
+-
+- if (tape->first_stage == NULL) {
+- printk(KERN_ERR "ide-tape: bug: tape->first_stage is NULL\n");
+- return;
+- }
+- if (tape->active_stage == tape->first_stage) {
+- printk(KERN_ERR "ide-tape: bug: Trying to free our active "
+- "pipeline stage\n");
+- return;
+- }
+- stage = tape->first_stage;
+- tape->first_stage = stage->next;
+- idetape_kfree_stage(tape, stage);
+- tape->nr_stages--;
+- if (tape->first_stage == NULL) {
+- tape->last_stage = NULL;
+- if (tape->next_stage != NULL)
+- printk(KERN_ERR "ide-tape: bug: tape->next_stage !="
+- " NULL\n");
+- if (tape->nr_stages)
+- printk(KERN_ERR "ide-tape: bug: nr_stages should be 0 "
+- "now\n");
+- }
-}
-
- #endif /* CONFIG_PCI */
+-/*
+- * This will free all the pipeline stages starting from new_last_stage->next
+- * to the end of the list, and point tape->last_stage to new_last_stage.
+- */
+-static void idetape_abort_pipeline(ide_drive_t *drive,
+- idetape_stage_t *new_last_stage)
+-{
+- idetape_tape_t *tape = drive->driver_data;
+- idetape_stage_t *stage = new_last_stage->next;
+- idetape_stage_t *nstage;
+-
+- debug_log(DBG_PROCS, "%s: Enter %s\n", tape->name, __func__);
+-
+- while (stage) {
+- nstage = stage->next;
+- idetape_kfree_stage(tape, stage);
+- --tape->nr_stages;
+- --tape->nr_pending_stages;
+- stage = nstage;
+- }
+- if (new_last_stage)
+- new_last_stage->next = NULL;
+- tape->last_stage = new_last_stage;
+- tape->next_stage = NULL;
++ kfree(tape->merge_bh);
+ }
-+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 *);
- };
+-/*
+- * Finish servicing a request and insert a pending pipeline request into the
+- * main device queue.
+- */
+ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
+ {
+ struct request *rq = HWGROUP(drive)->rq;
+ idetape_tape_t *tape = drive->driver_data;
+ unsigned long flags;
+ int error;
+- int remove_stage = 0;
+- idetape_stage_t *active_stage;
-+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;
-+}
+ debug_log(DBG_PROCS, "Enter %s\n", __func__);
+
+@@ -863,56 +628,8 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
+
+ spin_lock_irqsave(&tape->lock, flags);
+
+- /* The request was a pipelined data transfer request */
+- if (tape->active_data_rq == rq) {
+- active_stage = tape->active_stage;
+- tape->active_stage = NULL;
+- tape->active_data_rq = NULL;
+- tape->nr_pending_stages--;
+- if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
+- remove_stage = 1;
+- if (error) {
+- set_bit(IDETAPE_PIPELINE_ERROR, &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);
+- idetape_abort_pipeline(drive, active_stage);
+- }
+- }
+- if (tape->next_stage != NULL) {
+- idetape_activate_next_stage(drive);
+-
+- /* Insert the next request into the request queue. */
+- (void)ide_do_drive_cmd(drive, tape->active_data_rq,
+- ide_end);
+- } else if (!error) {
+- /*
+- * This is a part of the feedback loop which tries to
+- * find the optimum number of stages. We are starting
+- * from a minimum maximum number of stages, and if we
+- * sense that the pipeline is empty, we try to increase
+- * it, until we reach the user compile time memory
+- * limit.
+- */
+- int i = (tape->max_pipeline - tape->min_pipeline) / 10;
+-
+- tape->max_stages += max(i, 1);
+- tape->max_stages = max(tape->max_stages,
+- tape->min_pipeline);
+- tape->max_stages = min(tape->max_stages,
+- tape->max_pipeline);
+- }
+- }
+ ide_end_drive_cmd(drive, 0, 0);
+
+- if (remove_stage)
+- idetape_remove_stage_head(drive);
+- if (tape->active_data_rq == NULL)
+- clear_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
+ spin_unlock_irqrestore(&tape->lock, flags);
+ return 0;
+ }
+@@ -924,7 +641,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,18 +651,18 @@ 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)
+ {
+- memset(rq, 0, sizeof(*rq));
++ blk_rq_init(NULL, rq);
+ rq->cmd_type = REQ_TYPE_SPECIAL;
+ rq->cmd[0] = cmd;
+ }
+@@ -965,7 +682,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 +701,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 +727,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 +740,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,8 +755,8 @@ 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 (hwif->ide_dma_end(drive) || (stat & ERR_STAT)) {
++ if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
++ if (hwif->dma_ops->dma_end(drive) || (stat & ERR_STAT)) {
+ /*
+ * A DMA error is sometimes expected. For example,
+ * if the tape is crossing a filemark during a
+@@ -1061,9 +778,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 +790,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 +805,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 +821,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 +834,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)) {
+
- /* 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);
++ 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 +846,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.lbah_addr) << 8) |
++ hwif->INB(hwif->io_ports.lbam_addr);
--/* 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);
+- ireason = hwif->INB(IDE_IREASON_REG);
++ ireason = hwif->INB(hwif->io_ports.nsect_addr);
+
+ 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 +863,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_pad_transfer(drive, 0, bcount);
+ ide_set_handler(drive, &idetape_pc_intr,
+ IDETAPE_WAIT_CMD, NULL);
+ return ide_started;
+@@ -1161,20 +880,20 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ "data than expected - allowing transfer\n");
+ }
+ iobuf = &idetape_input_buffers;
+- xferfunc = hwif->atapi_input_bytes;
++ xferfunc = hwif->input_data;
+ } else {
+ iobuf = &idetape_output_buffers;
+- xferfunc = hwif->atapi_output_bytes;
++ xferfunc = hwif->output_data;
+ }
+
+ if (pc->bh)
+ iobuf(drive, pc, bcount);
+ else
+- xferfunc(drive, pc->current_position, bcount);
++ xferfunc(drive, NULL, 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 +943,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 +953,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.nsect_addr);
+ 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.nsect_addr);
+ if (retries == 0) {
+ printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while "
+ "issuing a packet command, ignoring\n");
+@@ -1256,15 +975,17 @@ 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))
+- hwif->dma_start(drive);
++ if (pc->flags & PC_FLAG_DMA_IN_PROGRESS)
++ hwif->dma_ops->dma_start(drive);
+ #endif
+ /* Send the actual packet */
+- HWIF(drive)->atapi_output_bytes(drive, pc->c, 12);
++ hwif->output_data(drive, NULL, pc->c, 12);
++
+ 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 +1004,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 +1025,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)
+- dma_ok = !hwif->dma_setup(drive);
++ if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma)
++ dma_ok = !hwif->dma_ops->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);
++ ide_execute_pkt_cmd(drive);
+ return idetape_transfer_pc(drive);
+ }
+ }
+@@ -1349,7 +1072,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,81 +1091,18 @@ 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;
+-}
-
- /* 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);
+-static void idetape_calculate_speeds(ide_drive_t *drive)
+-{
+- idetape_tape_t *tape = drive->driver_data;
+-
+- if (time_after(jiffies,
+- tape->controlled_pipeline_head_time + 120 * HZ)) {
+- tape->controlled_previous_pipeline_head =
+- tape->controlled_last_pipeline_head;
+- tape->controlled_previous_head_time =
+- tape->controlled_pipeline_head_time;
+- tape->controlled_last_pipeline_head = tape->pipeline_head;
+- tape->controlled_pipeline_head_time = jiffies;
+- }
+- if (time_after(jiffies, tape->controlled_pipeline_head_time + 60 * HZ))
+- tape->controlled_pipeline_head_speed = (tape->pipeline_head -
+- tape->controlled_last_pipeline_head) * 32 * HZ /
+- (jiffies - tape->controlled_pipeline_head_time);
+- else if (time_after(jiffies, tape->controlled_previous_head_time))
+- tape->controlled_pipeline_head_speed = (tape->pipeline_head -
+- tape->controlled_previous_pipeline_head) * 32 *
+- HZ / (jiffies - tape->controlled_previous_head_time);
+-
+- if (tape->nr_pending_stages < tape->max_stages/*- 1 */) {
+- /* -1 for read mode error recovery */
+- if (time_after(jiffies, tape->uncontrolled_previous_head_time +
+- 10 * HZ)) {
+- tape->uncontrolled_pipeline_head_time = jiffies;
+- tape->uncontrolled_pipeline_head_speed =
+- (tape->pipeline_head -
+- tape->uncontrolled_previous_pipeline_head) *
+- 32 * HZ / (jiffies -
+- tape->uncontrolled_previous_head_time);
+- }
+- } else {
+- tape->uncontrolled_previous_head_time = jiffies;
+- tape->uncontrolled_previous_pipeline_head = tape->pipeline_head;
+- if (time_after(jiffies, tape->uncontrolled_pipeline_head_time +
+- 30 * HZ))
+- tape->uncontrolled_pipeline_head_time = jiffies;
+-
+- }
+- tape->pipeline_head_speed = max(tape->uncontrolled_pipeline_head_speed,
+- tape->controlled_pipeline_head_speed);
+-
+- if (tape->speed_control == 1) {
+- if (tape->nr_pending_stages >= tape->max_stages / 2)
+- tape->max_insert_speed = tape->pipeline_head_speed +
+- (1100 - tape->pipeline_head_speed) * 2 *
+- (tape->nr_pending_stages - tape->max_stages / 2)
+- / tape->max_stages;
+- else
+- tape->max_insert_speed = 500 +
+- (tape->pipeline_head_speed - 500) * 2 *
+- tape->nr_pending_stages / tape->max_stages;
+-
+- if (tape->nr_pending_stages >= tape->max_stages * 99 / 100)
+- tape->max_insert_speed = 5000;
+- } else
+- tape->max_insert_speed = tape->speed_control;
+-
+- tape->max_insert_speed = max(tape->max_insert_speed, 500);
++ pc->req_xfer = 50;
++ pc->idetape_callback = &idetape_pc_callback;
+ }
-+/* 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 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,27 +1123,17 @@ 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;
+- if (tape->insert_size > 1024 * 1024)
+- tape->measure_insert_time = 1;
+- if (tape->measure_insert_time) {
+- tape->measure_insert_time = 0;
+- tape->insert_time = jiffies;
+- tape->insert_size = 0;
+- }
+- if (time_after(jiffies, tape->insert_time))
+- tape->insert_speed = tape->insert_size / 1024 * HZ /
+- (jiffies - tape->insert_time);
++
+ if (time_after_eq(jiffies, tape->avg_time + HZ)) {
+ tape->avg_speed = tape->avg_size * HZ /
+ (jiffies - tape->avg_time) / 1024;
+@@ -1502,47 +1152,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->buffer_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->buffer_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,18 +1231,14 @@ 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;
+ }
+
+- if (time_after(jiffies, tape->insert_time))
+- 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;
+@@ -1613,23 +1261,19 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
+ return ide_stopped;
+ }
+ if (rq->cmd[0] & REQ_IDETAPE_READ) {
+- tape->buffer_head++;
+- tape->postpone_cnt = 0;
+ pc = idetape_next_pc_storage(drive);
+ idetape_create_read_cmd(tape, pc, rq->current_nr_sectors,
+ (struct idetape_bh *)rq->special);
+ goto out;
+ }
+ if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
+- tape->buffer_head++;
+- tape->postpone_cnt = 0;
+ pc = idetape_next_pc_storage(drive);
+ idetape_create_write_cmd(tape, pc, rq->current_nr_sectors,
+ (struct idetape_bh *)rq->special);
+ 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;
+@@ -1643,111 +1287,91 @@ out:
+ return idetape_issue_pc(drive, pc);
+ }
+
+-/* Pipeline related functions */
+-static inline int idetape_pipeline_active(idetape_tape_t *tape)
+-{
+- int rc1, rc2;
+-
+- rc1 = test_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
+- rc2 = (tape->active_data_rq != NULL);
+- return rc1;
+-}
+-
+ /*
+- * The function below uses __get_free_page to allocate a pipeline stage, along
+- * with all the necessary small buffers which together make a buffer of size
+- * tape->stage_size (or a bit more). We attempt to combine sequential pages as
++ * The function below uses __get_free_pages to allocate a data buffer of size
++ * tape->buffer_size (or a bit more). We attempt to combine sequential pages as
+ * much as possible.
+ *
+- * It returns a pointer to the new allocated stage, or NULL if we can't (or
+- * don't want to) allocate a stage.
+- *
+- * Pipeline stages are optional and are used to increase performance. If we
+- * can't allocate them, we'll manage without them.
++ * It returns a pointer to the newly allocated buffer, or NULL in case of
++ * failure.
+ */
+-static idetape_stage_t *__idetape_kmalloc_stage(idetape_tape_t *tape, int full,
+- int clear)
++static struct idetape_bh *ide_tape_kmalloc_buffer(idetape_tape_t *tape,
++ int full, int clear)
+ {
+- idetape_stage_t *stage;
+- struct idetape_bh *prev_bh, *bh;
+- int pages = tape->pages_per_stage;
++ struct idetape_bh *prev_bh, *bh, *merge_bh;
++ int pages = tape->pages_per_buffer;
++ unsigned int order, b_allocd;
+ char *b_data = NULL;
+
+- stage = kmalloc(sizeof(idetape_stage_t), GFP_KERNEL);
+- if (!stage)
+- return NULL;
+- stage->next = NULL;
+-
+- stage->bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
+- bh = stage->bh;
++ merge_bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
++ bh = merge_bh;
+ if (bh == NULL)
+ goto abort;
+- bh->b_reqnext = NULL;
+- bh->b_data = (char *) __get_free_page(GFP_KERNEL);
+
-+static inline int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val)
-+{
-+ return -EINVAL;
-+}
++ order = fls(pages) - 1;
++ bh->b_data = (char *) __get_free_pages(GFP_KERNEL, order);
+ if (!bh->b_data)
+ goto abort;
++ b_allocd = (1 << order) * PAGE_SIZE;
++ pages &= (order-1);
+
-+static inline int sata_pmp_attach(struct ata_device *dev)
-+{
-+ return -EINVAL;
-+}
-+#endif /* CONFIG_SATA_PMP */
+ if (clear)
+- memset(bh->b_data, 0, PAGE_SIZE);
+- bh->b_size = PAGE_SIZE;
++ memset(bh->b_data, 0, b_allocd);
++ bh->b_reqnext = NULL;
++ bh->b_size = b_allocd;
+ atomic_set(&bh->b_count, full ? bh->b_size : 0);
+
+- while (--pages) {
+- b_data = (char *) __get_free_page(GFP_KERNEL);
++ while (pages) {
++ order = fls(pages) - 1;
++ b_data = (char *) __get_free_pages(GFP_KERNEL, order);
+ if (!b_data)
+ goto abort;
++ b_allocd = (1 << order) * PAGE_SIZE;
+
- /* 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);
+ if (clear)
+- memset(b_data, 0, PAGE_SIZE);
+- if (bh->b_data == b_data + PAGE_SIZE) {
+- bh->b_size += PAGE_SIZE;
+- bh->b_data -= PAGE_SIZE;
++ memset(b_data, 0, b_allocd);
++
++ /* newly allocated page frames below buffer header or ...*/
++ if (bh->b_data == b_data + b_allocd) {
++ bh->b_size += b_allocd;
++ bh->b_data -= b_allocd;
+ if (full)
+- atomic_add(PAGE_SIZE, &bh->b_count);
++ atomic_add(b_allocd, &bh->b_count);
+ continue;
+ }
++ /* they are above the header */
+ if (b_data == bh->b_data + bh->b_size) {
+- bh->b_size += PAGE_SIZE;
++ bh->b_size += b_allocd;
+ if (full)
+- atomic_add(PAGE_SIZE, &bh->b_count);
++ atomic_add(b_allocd, &bh->b_count);
+ continue;
+ }
+ prev_bh = bh;
+ bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
+ if (!bh) {
+- free_page((unsigned long) b_data);
++ free_pages((unsigned long) b_data, order);
+ goto abort;
+ }
+ bh->b_reqnext = NULL;
+ bh->b_data = b_data;
+- bh->b_size = PAGE_SIZE;
++ bh->b_size = b_allocd;
+ atomic_set(&bh->b_count, full ? bh->b_size : 0);
+ prev_bh->b_reqnext = bh;
++
++ pages &= (order-1);
+ }
++
+ bh->b_size -= tape->excess_bh_size;
+ if (full)
+ atomic_sub(tape->excess_bh_size, &bh->b_count);
+- return stage;
++ return merge_bh;
+ abort:
+- __idetape_kfree_stage(stage);
++ ide_tape_kfree_buffer(tape);
+ return NULL;
+ }
+
+-static idetape_stage_t *idetape_kmalloc_stage(idetape_tape_t *tape)
+-{
+- idetape_stage_t *cache_stage = tape->cache_stage;
-
-+extern void ata_pio_task(struct work_struct *work);
-+#endif /* CONFIG_ATA_SFF */
+- debug_log(DBG_PROCS, "Enter %s\n", __func__);
+-
+- if (tape->nr_stages >= tape->max_stages)
+- return NULL;
+- if (cache_stage != NULL) {
+- tape->cache_stage = NULL;
+- return cache_stage;
+- }
+- return __idetape_kmalloc_stage(tape, 0, 0);
+-}
+-
+ static int idetape_copy_stage_from_user(idetape_tape_t *tape,
+- idetape_stage_t *stage, const char __user *buf, int n)
++ const char __user *buf, int n)
+ {
+ struct idetape_bh *bh = tape->bh;
+ int count;
+@@ -1779,7 +1403,7 @@ static int idetape_copy_stage_from_user(idetape_tape_t *tape,
+ }
- #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;
+ static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf,
+- idetape_stage_t *stage, int n)
++ int n)
+ {
+ struct idetape_bh *bh = tape->bh;
+ int count;
+@@ -1810,11 +1434,11 @@ static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf,
+ return ret;
+ }
-- return ata_std_prereset(link, deadline);
-+ return ata_sff_prereset(link, deadline);
+-static void idetape_init_merge_stage(idetape_tape_t *tape)
++static void idetape_init_merge_buffer(idetape_tape_t *tape)
+ {
+- struct idetape_bh *bh = tape->merge_stage->bh;
++ struct idetape_bh *bh = tape->merge_bh;
++ tape->bh = tape->merge_bh;
+
+- tape->bh = bh;
+ if (tape->chrdev_dir == IDETAPE_DIR_WRITE)
+ atomic_set(&bh->b_count, 0);
+ else {
+@@ -1823,65 +1447,10 @@ static void idetape_init_merge_stage(idetape_tape_t *tape)
+ }
+ }
+
+-static void idetape_switch_buffers(idetape_tape_t *tape, idetape_stage_t *stage)
+-{
+- struct idetape_bh *tmp;
+-
+- tmp = stage->bh;
+- stage->bh = tape->merge_stage->bh;
+- tape->merge_stage->bh = tmp;
+- idetape_init_merge_stage(tape);
+-}
+-
+-/* Add a new stage at the end of the pipeline. */
+-static void idetape_add_stage_tail(ide_drive_t *drive, idetape_stage_t *stage)
+-{
+- idetape_tape_t *tape = drive->driver_data;
+- unsigned long flags;
+-
+- debug_log(DBG_PROCS, "Enter %s\n", __func__);
+-
+- spin_lock_irqsave(&tape->lock, flags);
+- stage->next = NULL;
+- if (tape->last_stage != NULL)
+- tape->last_stage->next = stage;
+- else
+- tape->first_stage = stage;
+- tape->next_stage = stage;
+- tape->last_stage = stage;
+- if (tape->next_stage == NULL)
+- tape->next_stage = tape->last_stage;
+- tape->nr_stages++;
+- tape->nr_pending_stages++;
+- spin_unlock_irqrestore(&tape->lock, flags);
+-}
+-
+-/* Install a completion in a pending request and sleep until it is serviced. The
+- * caller should ensure that the request will not be serviced before we install
+- * the completion (usually by disabling interrupts).
+- */
+-static void idetape_wait_for_request(ide_drive_t *drive, struct request *rq)
+-{
+- DECLARE_COMPLETION_ONSTACK(wait);
+- idetape_tape_t *tape = drive->driver_data;
+-
+- if (rq == NULL || !blk_special_request(rq)) {
+- printk(KERN_ERR "ide-tape: bug: Trying to sleep on non-valid"
+- " request\n");
+- return;
+- }
+- rq->end_io_data = &wait;
+- rq->end_io = blk_end_sync_rq;
+- spin_unlock_irq(&tape->lock);
+- wait_for_completion(&wait);
+- /* The stage and its struct request have been deallocated */
+- spin_lock_irq(&tape->lock);
+-}
+-
+ 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 +1463,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 +1472,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 +1486,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 +1515,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,28 +1526,28 @@ 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;
}
- /**
-@@ -68,20 +68,6 @@ static int pacpi_cable_detect(struct ata_port *ap)
+ 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);
+- if (!__idetape_queue_pc_tail(drive, &pc))
++ if (!idetape_queue_pc_tail(drive, &pc))
+ return 0;
+ if ((tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2)
+ || (tape->asc == 0x3A)) {
+@@ -1987,7 +1556,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
+ return -ENOMEDIUM;
+ idetape_create_load_unload_cmd(drive, &pc,
+ IDETAPE_LU_LOAD_MASK);
+- __idetape_queue_pc_tail(drive, &pc);
++ idetape_queue_pc_tail(drive, &pc);
+ load_attempted = 1;
+ /* not about to be ready */
+ } else if (!(tape->sense_key == 2 && tape->asc == 4 &&
+@@ -1998,14 +1567,9 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
+ return -EIO;
}
- /**
-- * 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)
+-static int idetape_queue_pc_tail(ide_drive_t *drive, idetape_pc_t *pc)
-{
-- ata_bmdma_drive_eh(ap, pacpi_pre_reset, ata_std_softreset, NULL,
-- ata_std_postreset);
+- return __idetape_queue_pc_tail(drive, pc);
-}
-
--/**
- * 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)
+ static int idetape_flush_tape_buffers(ide_drive_t *drive)
{
- 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]);
- }
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
+ int rc;
- /**
-@@ -176,7 +162,7 @@ static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ idetape_create_write_filemark_cmd(drive, &pc, 0);
+@@ -2016,18 +1580,18 @@ static int idetape_flush_tape_buffers(ide_drive_t *drive)
+ return 0;
}
- /**
-- * 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 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 unsigned int pacpi_qc_issue_prot(struct ata_queued_cmd *qc)
-+static unsigned int pacpi_qc_issue(struct ata_queued_cmd *qc)
+ static int idetape_read_position(ide_drive_t *drive)
{
- struct ata_port *ap = qc->ap;
- struct ata_device *adev = qc->dev;
- struct pata_acpi *acpi = ap->private_data;
+ idetape_tape_t *tape = drive->driver_data;
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
+ int position;
- if (acpi->gtm.flags & 0x10)
-- return ata_qc_issue_prot(qc);
-+ return ata_sff_qc_issue(qc);
+ debug_log(DBG_PROCS, "Enter %s\n", __func__);
+@@ -2039,7 +1603,8 @@ static int idetape_read_position(ide_drive_t *drive)
+ return position;
+ }
- 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);
+-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 +1612,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;
}
- /**
-@@ -232,57 +218,17 @@ static int pacpi_port_start(struct ata_port *ap)
+-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,54 +1628,25 @@ 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;
}
- 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 int __idetape_discard_read_pipeline(ide_drive_t *drive)
++static void __ide_tape_discard_merge_buffer(ide_drive_t *drive)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+- unsigned long flags;
+- int cnt;
--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,
+ if (tape->chrdev_dir != IDETAPE_DIR_READ)
+- return 0;
++ return;
+
+- /* Remove merge stage. */
+- cnt = tape->merge_stage_size / tape->blk_size;
+- if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags))
+- ++cnt; /* Filemarks count as 1 sector */
+- tape->merge_stage_size = 0;
+- if (tape->merge_stage != NULL) {
+- __idetape_kfree_stage(tape->merge_stage);
+- tape->merge_stage = NULL;
++ clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags);
++ tape->merge_bh_size = 0;
++ if (tape->merge_bh != NULL) {
++ ide_tape_kfree_buffer(tape);
++ tape->merge_bh = NULL;
+ }
+
+- /* Clear pipeline flags. */
+- clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
+ tape->chrdev_dir = IDETAPE_DIR_NONE;
-
-- .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,
+- /* Remove pipeline stages. */
+- if (tape->first_stage == NULL)
+- return 0;
-
-- /* 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,
+- spin_lock_irqsave(&tape->lock, flags);
+- tape->next_stage = NULL;
+- if (idetape_pipeline_active(tape))
+- idetape_wait_for_request(drive, tape->active_data_rq);
+- spin_unlock_irqrestore(&tape->lock, flags);
-
-- /* Timeout handling */
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- while (tape->first_stage != NULL) {
+- struct request *rq_ptr = &tape->first_stage->rq;
-
-- /* Generic PATA PCI ATA helpers */
-+ .prereset = pacpi_pre_reset,
- .port_start = pacpi_port_start,
- };
+- cnt += rq_ptr->nr_sectors - rq_ptr->current_nr_sectors;
+- if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK)
+- ++cnt;
+- idetape_remove_stage_head(drive);
+- }
+- tape->nr_pending_stages = 0;
+- tape->max_stages = tape->min_pipeline;
+- return cnt;
+ }
-@@ -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)
+ /*
+@@ -2124,10 +1660,10 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
{
- 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);
- }
+ idetape_tape_t *tape = drive->driver_data;
+ int retval;
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
- 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);
+ if (tape->chrdev_dir == IDETAPE_DIR_READ)
+- __idetape_discard_read_pipeline(drive);
++ __ide_tape_discard_merge_buffer(drive);
+ idetape_wait_ready(drive, 60 * 5 * HZ);
+ idetape_create_locate_cmd(drive, &pc, block, partition, skip);
+ retval = idetape_queue_pc_tail(drive, &pc);
+@@ -2138,20 +1674,19 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
+ return (idetape_queue_pc_tail(drive, &pc));
}
- /**
-@@ -339,21 +339,7 @@ static int ali_check_atapi_dma(struct ata_queued_cmd *qc)
- }
+-static void idetape_discard_read_pipeline(ide_drive_t *drive,
++static void ide_tape_discard_merge_buffer(ide_drive_t *drive,
+ int restore_position)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+- int cnt;
+ int seek, position;
- 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),
- };
+- cnt = __idetape_discard_read_pipeline(drive);
++ __ide_tape_discard_merge_buffer(drive);
+ if (restore_position) {
+ position = idetape_read_position(drive);
+- seek = position > cnt ? position - cnt : 0;
++ seek = position > 0 ? position : 0;
+ if (idetape_position_tape(drive, seek, 0, 0)) {
+ printk(KERN_INFO "ide-tape: %s: position_tape failed in"
+- " discard_pipeline()\n", tape->name);
++ " %s\n", tape->name, __func__);
+ return;
+ }
+ }
+@@ -2169,12 +1704,6 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
- /*
-@@ -361,29 +347,15 @@ static struct scsi_host_template ali_sht = {
- */
+ debug_log(DBG_SENSE, "%s: cmd=%d\n", __func__, cmd);
- 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,
+- if (idetape_pipeline_active(tape)) {
+- printk(KERN_ERR "ide-tape: bug: the pipeline is active in %s\n",
+- __func__);
+- return (0);
+- }
-
-- .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,
-+};
+ idetape_init_rq(&rq, cmd);
+ rq.rq_disk = tape->disk;
+ rq.special = (void *)bh;
+@@ -2186,192 +1715,83 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
+ if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0)
+ return 0;
-- .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,
- };
+- if (tape->merge_stage)
+- idetape_init_merge_stage(tape);
++ if (tape->merge_bh)
++ idetape_init_merge_buffer(tape);
+ if (rq.errors == IDETAPE_ERROR_GENERAL)
+ return -EIO;
+ return (tape->blk_size * (blocks-rq.current_nr_sectors));
+ }
- /*
-@@ -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,
+-/* start servicing the pipeline stages, starting from tape->next_stage. */
+-static void idetape_plug_pipeline(ide_drive_t *drive)
+-{
+- idetape_tape_t *tape = drive->driver_data;
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- if (tape->next_stage == NULL)
+- return;
+- if (!idetape_pipeline_active(tape)) {
+- set_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
+- idetape_activate_next_stage(drive);
+- (void) ide_do_drive_cmd(drive, tape->active_data_rq, ide_end);
+- }
+-}
-
-- .port_start = ata_sff_port_start,
- };
+-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;
+ }
- /*
- * 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,
- };
+-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;
+ }
- /*
- * 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,
+-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)
+-{
+- idetape_tape_t *tape = drive->driver_data;
+- unsigned long flags;
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- if (tape->first_stage == NULL)
+- return;
+- spin_lock_irqsave(&tape->lock, flags);
+- if (tape->active_stage == tape->first_stage)
+- idetape_wait_for_request(drive, tape->active_data_rq);
+- spin_unlock_irqrestore(&tape->lock, flags);
+-}
-
-- .port_start = ata_sff_port_start,
- };
+-/*
+- * Try to add a character device originated write request to our pipeline. In
+- * case we don't succeed, we revert to non-pipelined operation mode for this
+- * request. In order to accomplish that, we
+- *
+- * 1. Try to allocate a new pipeline stage.
+- * 2. If we can't, wait for more and more requests to be serviced and try again
+- * each time.
+- * 3. If we still can't allocate a stage, fallback to non-pipelined operation
+- * mode for this request.
+- */
++/* Queue up a character device originated write request. */
+ static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+- idetape_stage_t *new_stage;
+- unsigned long flags;
+- struct request *rq;
+ debug_log(DBG_CHRDEV, "Enter %s\n", __func__);
-@@ -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);
+- /* Attempt to allocate a new stage. Beware possible race conditions. */
+- while ((new_stage = idetape_kmalloc_stage(tape)) == NULL) {
+- spin_lock_irqsave(&tape->lock, flags);
+- if (idetape_pipeline_active(tape)) {
+- idetape_wait_for_request(drive, tape->active_data_rq);
+- spin_unlock_irqrestore(&tape->lock, flags);
+- } else {
+- spin_unlock_irqrestore(&tape->lock, flags);
+- idetape_plug_pipeline(drive);
+- if (idetape_pipeline_active(tape))
+- continue;
+- /*
+- * The machine is short on memory. Fallback to non-
+- * pipelined operation mode for this request.
+- */
+- return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE,
+- blocks, tape->merge_stage->bh);
+- }
+- }
+- rq = &new_stage->rq;
+- idetape_init_rq(rq, REQ_IDETAPE_WRITE);
+- /* Doesn't actually matter - We always assume sequential access */
+- rq->sector = tape->first_frame;
+- rq->current_nr_sectors = blocks;
+- rq->nr_sectors = blocks;
+-
+- idetape_switch_buffers(tape, new_stage);
+- idetape_add_stage_tail(drive, new_stage);
+- tape->pipeline_head++;
+- idetape_calculate_speeds(drive);
+-
+- /*
+- * Estimate whether the tape has stopped writing by checking if our
+- * write pipeline is currently empty. If we are not writing anymore,
+- * wait for the pipeline to be almost completely full (90%) before
+- * starting to service requests, so that we will be able to keep up with
+- * the higher speeds of the tape.
+- */
+- if (!idetape_pipeline_active(tape)) {
+- if (tape->nr_stages >= tape->max_stages * 9 / 10 ||
+- tape->nr_stages >= tape->max_stages -
+- tape->uncontrolled_pipeline_head_speed * 3 * 1024 /
+- tape->blk_size) {
+- tape->measure_insert_time = 1;
+- tape->insert_time = jiffies;
+- tape->insert_size = 0;
+- tape->insert_speed = 0;
+- idetape_plug_pipeline(drive);
+- }
+- }
+- if (test_and_clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags))
+- /* Return a deferred error */
+- return -EIO;
+- return blocks;
++ return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE,
++ blocks, tape->merge_bh);
}
- /**
- * 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)
+
+-/*
+- * Wait until all pending pipeline requests are serviced. Typically called on
+- * device close.
+- */
+-static void idetape_wait_for_pipeline(ide_drive_t *drive)
+-{
+- idetape_tape_t *tape = drive->driver_data;
+- unsigned long flags;
+-
+- while (tape->next_stage || idetape_pipeline_active(tape)) {
+- idetape_plug_pipeline(drive);
+- spin_lock_irqsave(&tape->lock, flags);
+- if (idetape_pipeline_active(tape))
+- idetape_wait_for_request(drive, tape->active_data_rq);
+- spin_unlock_irqrestore(&tape->lock, flags);
+- }
+-}
+-
+-static void idetape_empty_write_pipeline(ide_drive_t *drive)
++static void ide_tape_flush_merge_buffer(ide_drive_t *drive)
{
- 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;
+ idetape_tape_t *tape = drive->driver_data;
+ int blocks, min;
+ struct idetape_bh *bh;
- /*
- * 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);
+ if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
+- printk(KERN_ERR "ide-tape: bug: Trying to empty write pipeline,"
++ printk(KERN_ERR "ide-tape: bug: Trying to empty merge buffer"
+ " but we are not writing.\n");
+ return;
}
-- return ata_pci_init_one(pdev, ppi);
-+ return ata_pci_sff_init_one(pdev, ppi, &ali_sht, NULL);
+- if (tape->merge_stage_size > tape->stage_size) {
++ if (tape->merge_bh_size > tape->buffer_size) {
+ printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n");
+- tape->merge_stage_size = tape->stage_size;
++ tape->merge_bh_size = tape->buffer_size;
+ }
+- if (tape->merge_stage_size) {
+- blocks = tape->merge_stage_size / tape->blk_size;
+- if (tape->merge_stage_size % tape->blk_size) {
++ if (tape->merge_bh_size) {
++ blocks = tape->merge_bh_size / tape->blk_size;
++ if (tape->merge_bh_size % tape->blk_size) {
+ unsigned int i;
+
+ blocks++;
+- i = tape->blk_size - tape->merge_stage_size %
++ i = tape->blk_size - tape->merge_bh_size %
+ tape->blk_size;
+ bh = tape->bh->b_reqnext;
+ while (bh) {
+@@ -2395,74 +1815,33 @@ static void idetape_empty_write_pipeline(ide_drive_t *drive)
+ }
+ }
+ (void) idetape_add_chrdev_write_request(drive, blocks);
+- tape->merge_stage_size = 0;
++ tape->merge_bh_size = 0;
+ }
+- idetape_wait_for_pipeline(drive);
+- if (tape->merge_stage != NULL) {
+- __idetape_kfree_stage(tape->merge_stage);
+- tape->merge_stage = NULL;
++ if (tape->merge_bh != NULL) {
++ ide_tape_kfree_buffer(tape);
++ tape->merge_bh = NULL;
+ }
+- clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
+ tape->chrdev_dir = IDETAPE_DIR_NONE;
+-
+- /*
+- * On the next backup, perform the feedback loop again. (I don't want to
+- * keep sense information between backups, as some systems are
+- * constantly on, and the system load can be totally different on the
+- * next backup).
+- */
+- tape->max_stages = tape->min_pipeline;
+- if (tape->first_stage != NULL ||
+- tape->next_stage != NULL ||
+- tape->last_stage != NULL ||
+- tape->nr_stages != 0) {
+- printk(KERN_ERR "ide-tape: ide-tape pipeline bug, "
+- "first_stage %p, next_stage %p, "
+- "last_stage %p, nr_stages %d\n",
+- tape->first_stage, tape->next_stage,
+- tape->last_stage, tape->nr_stages);
+- }
}
- #ifdef CONFIG_PM
- static int ali_reinit_one(struct pci_dev *pdev)
+-static void idetape_restart_speed_control(ide_drive_t *drive)
++static int idetape_init_read(ide_drive_t *drive)
{
-+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
-+ int rc;
+ idetape_tape_t *tape = drive->driver_data;
+-
+- tape->restart_speed_control_req = 0;
+- tape->pipeline_head = 0;
+- tape->controlled_last_pipeline_head = 0;
+- tape->controlled_previous_pipeline_head = 0;
+- tape->uncontrolled_previous_pipeline_head = 0;
+- tape->controlled_pipeline_head_speed = 5000;
+- tape->pipeline_head_speed = 5000;
+- tape->uncontrolled_pipeline_head_speed = 0;
+- tape->controlled_pipeline_head_time =
+- tape->uncontrolled_pipeline_head_time = jiffies;
+- tape->controlled_previous_head_time =
+- tape->uncontrolled_previous_head_time = jiffies;
+-}
+-
+-static int idetape_init_read(ide_drive_t *drive, int max_stages)
+-{
+- idetape_tape_t *tape = drive->driver_data;
+- idetape_stage_t *new_stage;
+- struct request rq;
+ int bytes_read;
+- u16 blocks = *(u16 *)&tape->caps[12];
+
+ /* Initialize read operation */
+ if (tape->chrdev_dir != IDETAPE_DIR_READ) {
+ if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
+- idetape_empty_write_pipeline(drive);
++ ide_tape_flush_merge_buffer(drive);
+ idetape_flush_tape_buffers(drive);
+ }
+- if (tape->merge_stage || tape->merge_stage_size) {
+- printk(KERN_ERR "ide-tape: merge_stage_size should be"
++ if (tape->merge_bh || tape->merge_bh_size) {
++ printk(KERN_ERR "ide-tape: merge_bh_size should be"
+ " 0 now\n");
+- tape->merge_stage_size = 0;
++ tape->merge_bh_size = 0;
+ }
+- tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0);
+- if (!tape->merge_stage)
++ tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0);
++ if (!tape->merge_bh)
+ return -ENOMEM;
+ tape->chrdev_dir = IDETAPE_DIR_READ;
+
+@@ -2475,94 +1854,34 @@ static int idetape_init_read(ide_drive_t *drive, int max_stages)
+ if (drive->dsc_overlap) {
+ bytes_read = idetape_queue_rw_tail(drive,
+ REQ_IDETAPE_READ, 0,
+- tape->merge_stage->bh);
++ tape->merge_bh);
+ if (bytes_read < 0) {
+- __idetape_kfree_stage(tape->merge_stage);
+- tape->merge_stage = NULL;
++ ide_tape_kfree_buffer(tape);
++ tape->merge_bh = NULL;
+ tape->chrdev_dir = IDETAPE_DIR_NONE;
+ return bytes_read;
+ }
+ }
+ }
+- if (tape->restart_speed_control_req)
+- idetape_restart_speed_control(drive);
+- idetape_init_rq(&rq, REQ_IDETAPE_READ);
+- rq.sector = tape->first_frame;
+- rq.nr_sectors = blocks;
+- rq.current_nr_sectors = blocks;
+- if (!test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags) &&
+- tape->nr_stages < max_stages) {
+- new_stage = idetape_kmalloc_stage(tape);
+- while (new_stage != NULL) {
+- new_stage->rq = rq;
+- idetape_add_stage_tail(drive, new_stage);
+- if (tape->nr_stages >= max_stages)
+- break;
+- new_stage = idetape_kmalloc_stage(tape);
+- }
+- }
+- if (!idetape_pipeline_active(tape)) {
+- if (tape->nr_pending_stages >= 3 * max_stages / 4) {
+- tape->measure_insert_time = 1;
+- tape->insert_time = jiffies;
+- tape->insert_size = 0;
+- tape->insert_speed = 0;
+- idetape_plug_pipeline(drive);
+- }
+- }
+
-+ 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;
+ 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;
+-/*
+- * Called from idetape_chrdev_read() to service a character device read request
+- * and add read-ahead requests to our pipeline.
+- */
++/* called from idetape_chrdev_read() to service a chrdev read request. */
+ static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+- unsigned long flags;
+- struct request *rq_ptr;
+- int bytes_read;
- T = 1000000000 / amd_clock;
-- UT = T / min_t(int, max_t(int, clock, 1), 2);
-+ UT = T;
-+ if (clock >= 2)
-+ UT = T / 2;
+ debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks);
- 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;
+ /* 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;
-- 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);
+- /* 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))
+- return 0;
+- return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks,
+- tape->merge_stage->bh);
+- }
+- idetape_wait_first_stage(drive);
+- rq_ptr = &tape->first_stage->rq;
+- bytes_read = tape->blk_size * (rq_ptr->nr_sectors -
+- rq_ptr->current_nr_sectors);
+- rq_ptr->nr_sectors = 0;
+- rq_ptr->current_nr_sectors = 0;
++ idetape_init_read(drive);
+
+- if (rq_ptr->errors == IDETAPE_ERROR_EOD)
+- return 0;
+- else {
+- idetape_switch_buffers(tape, tape->first_stage);
+- if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK)
+- set_bit(IDETAPE_FILEMARK, &tape->flags);
+- spin_lock_irqsave(&tape->lock, flags);
+- idetape_remove_stage_head(drive);
+- spin_unlock_irqrestore(&tape->lock, flags);
+- tape->pipeline_head++;
+- idetape_calculate_speeds(drive);
+- }
+- if (bytes_read > blocks * tape->blk_size) {
+- printk(KERN_ERR "ide-tape: bug: trying to return more bytes"
+- " than requested\n");
+- bytes_read = blocks * tape->blk_size;
+- }
+- return (bytes_read);
++ return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks,
++ tape->merge_bh);
}
- 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;
+ static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
+@@ -2574,8 +1893,8 @@ static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
+ while (bcount) {
+ unsigned int count;
-- return ata_std_prereset(link, deadline);
+- bh = tape->merge_stage->bh;
+- count = min(tape->stage_size, bcount);
++ bh = tape->merge_bh;
++ count = min(tape->buffer_size, bcount);
+ bcount -= count;
+ blocks = count / tape->blk_size;
+ while (count) {
+@@ -2586,29 +1905,8 @@ static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
+ bh = bh->b_reqnext;
+ }
+ idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks,
+- tape->merge_stage->bh);
+- }
-}
-
--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);
+-static int idetape_pipeline_size(ide_drive_t *drive)
+-{
+- idetape_tape_t *tape = drive->driver_data;
+- idetape_stage_t *stage;
+- struct request *rq;
+- int size = 0;
+-
+- idetape_wait_for_pipeline(drive);
+- stage = tape->first_stage;
+- while (stage != NULL) {
+- rq = &stage->rq;
+- size += tape->blk_size * (rq->nr_sectors -
+- rq->current_nr_sectors);
+- if (rq->errors == IDETAPE_ERROR_FILEMARK)
+- size += tape->blk_size;
+- stage = stage->next;
++ tape->merge_bh);
+ }
+- size += tape->merge_stage_size;
+- return size;
}
- /**
-@@ -353,228 +342,66 @@ static void nv_host_stop(struct ata_host *host)
+ /*
+@@ -2618,7 +1916,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;
+
+@@ -2656,11 +1954,10 @@ static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd,
+ if (copy_from_user(&config, argp, sizeof(config)))
+ return -EFAULT;
+ tape->best_dsc_rw_freq = config.dsc_rw_frequency;
+- tape->max_stages = config.nr_stages;
+ break;
+ case 0x0350:
+ config.dsc_rw_frequency = (int) tape->best_dsc_rw_freq;
+- config.nr_stages = tape->max_stages;
++ config.nr_stages = 1;
+ if (copy_to_user(argp, &config, sizeof(config)))
+ return -EFAULT;
+ break;
+@@ -2670,19 +1967,11 @@ static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd,
+ return 0;
}
- 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,
- };
+-/*
+- * The function below is now a bit more complicated than just passing the
+- * command to the tape since we may have crossed some filemarks during our
+- * pipelined read-ahead mode. As a minor side effect, the pipeline enables us to
+- * support MTFSFM when the filemark is in our internal pipeline even if the tape
+- * doesn't support spacing over filemarks in the reverse direction.
+- */
+ 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;
+- unsigned long flags;
++ struct ide_atapi_pc pc;
+ int retval, count = 0;
+ int sprev = !!(tape->caps[4] & 0x20);
- 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,
- };
+@@ -2695,47 +1984,12 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
+ }
- 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,
- };
+ 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))
++ tape->merge_bh_size = 0;
++ 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);
+- return 0;
+- }
+- spin_lock_irqsave(&tape->lock, flags);
+- if (tape->first_stage == tape->active_stage) {
+- /*
+- * We have reached the active stage in the read
+- * pipeline. There is no point in allowing the
+- * drive to continue reading any farther, so we
+- * stop the pipeline.
+- *
+- * This section should be moved to a separate
+- * subroutine because similar operations are
+- * done in __idetape_discard_read_pipeline(),
+- * for example.
+- */
+- tape->next_stage = NULL;
+- spin_unlock_irqrestore(&tape->lock, flags);
+- idetape_wait_first_stage(drive);
+- tape->next_stage = tape->first_stage->next;
+- } else
+- spin_unlock_irqrestore(&tape->lock, flags);
+- if (tape->first_stage->rq.errors ==
+- IDETAPE_ERROR_FILEMARK)
+- ++count;
+- idetape_remove_stage_head(drive);
+- }
+- idetape_discard_read_pipeline(drive, 0);
++ ide_tape_discard_merge_buffer(drive, 0);
+ }
- 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,
- };
+- /*
+- * The filemark was not found in our internal pipeline; now we can issue
+- * the space command.
+- */
+ switch (mt_op) {
+ case MTFSF:
+ case MTBSF:
+@@ -2786,32 +2040,30 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
+ debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count);
- 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,
-+};
+ 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;
+ }
+- rc = idetape_init_read(drive, tape->max_stages);
++ rc = idetape_init_read(drive);
+ if (rc < 0)
+ return rc;
+ if (count == 0)
+ return (0);
+- if (tape->merge_stage_size) {
+- actually_read = min((unsigned int)(tape->merge_stage_size),
++ if (tape->merge_bh_size) {
++ actually_read = min((unsigned int)(tape->merge_bh_size),
+ (unsigned int)count);
+- if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage,
+- actually_read))
++ if (idetape_copy_stage_to_user(tape, buf, actually_read))
+ ret = -EFAULT;
+ buf += actually_read;
+- tape->merge_stage_size -= actually_read;
++ tape->merge_bh_size -= actually_read;
+ count -= actually_read;
+ }
+- while (count >= tape->stage_size) {
++ while (count >= tape->buffer_size) {
+ bytes_read = idetape_add_chrdev_read_request(drive, ctl);
+ if (bytes_read <= 0)
+ goto finish;
+- if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage,
+- bytes_read))
++ if (idetape_copy_stage_to_user(tape, buf, bytes_read))
+ ret = -EFAULT;
+ buf += bytes_read;
+ count -= bytes_read;
+@@ -2822,14 +2074,13 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
+ if (bytes_read <= 0)
+ goto finish;
+ temp = min((unsigned long)count, (unsigned long)bytes_read);
+- if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage,
+- temp))
++ if (idetape_copy_stage_to_user(tape, buf, temp))
+ ret = -EFAULT;
+ actually_read += temp;
+- tape->merge_stage_size = bytes_read-temp;
++ tape->merge_bh_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);
-- .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,
- };
+ idetape_space_over_filemarks(drive, MTFSF, 1);
+@@ -2857,17 +2108,17 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
+ /* Initialize write operation */
+ if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
+ if (tape->chrdev_dir == IDETAPE_DIR_READ)
+- idetape_discard_read_pipeline(drive, 1);
+- if (tape->merge_stage || tape->merge_stage_size) {
+- printk(KERN_ERR "ide-tape: merge_stage_size "
++ ide_tape_discard_merge_buffer(drive, 1);
++ if (tape->merge_bh || tape->merge_bh_size) {
++ printk(KERN_ERR "ide-tape: merge_bh_size "
+ "should be 0 now\n");
+- tape->merge_stage_size = 0;
++ tape->merge_bh_size = 0;
+ }
+- tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0);
+- if (!tape->merge_stage)
++ tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0);
++ if (!tape->merge_bh)
+ return -ENOMEM;
+ tape->chrdev_dir = IDETAPE_DIR_WRITE;
+- idetape_init_merge_stage(tape);
++ idetape_init_merge_buffer(tape);
- 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,
- };
+ /*
+ * Issue a write 0 command to ensure that DSC handshake is
+@@ -2878,10 +2129,10 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
+ if (drive->dsc_overlap) {
+ ssize_t retval = idetape_queue_rw_tail(drive,
+ REQ_IDETAPE_WRITE, 0,
+- tape->merge_stage->bh);
++ tape->merge_bh);
+ if (retval < 0) {
+- __idetape_kfree_stage(tape->merge_stage);
+- tape->merge_stage = NULL;
++ ide_tape_kfree_buffer(tape);
++ tape->merge_bh = NULL;
+ tape->chrdev_dir = IDETAPE_DIR_NONE;
+ return retval;
+ }
+@@ -2889,56 +2140,51 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
+ }
+ if (count == 0)
+ return (0);
+- if (tape->restart_speed_control_req)
+- idetape_restart_speed_control(drive);
+- if (tape->merge_stage_size) {
+- if (tape->merge_stage_size >= tape->stage_size) {
++ if (tape->merge_bh_size) {
++ if (tape->merge_bh_size >= tape->buffer_size) {
+ printk(KERN_ERR "ide-tape: bug: merge buf too big\n");
+- tape->merge_stage_size = 0;
++ tape->merge_bh_size = 0;
+ }
+ actually_written = min((unsigned int)
+- (tape->stage_size - tape->merge_stage_size),
++ (tape->buffer_size - tape->merge_bh_size),
+ (unsigned int)count);
+- if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf,
+- actually_written))
++ if (idetape_copy_stage_from_user(tape, buf, actually_written))
+ ret = -EFAULT;
+ buf += actually_written;
+- tape->merge_stage_size += actually_written;
++ tape->merge_bh_size += actually_written;
+ count -= actually_written;
+
+- if (tape->merge_stage_size == tape->stage_size) {
++ if (tape->merge_bh_size == tape->buffer_size) {
+ ssize_t retval;
+- tape->merge_stage_size = 0;
++ tape->merge_bh_size = 0;
+ retval = idetape_add_chrdev_write_request(drive, ctl);
+ if (retval <= 0)
+ return (retval);
+ }
+ }
+- while (count >= tape->stage_size) {
++ while (count >= tape->buffer_size) {
+ ssize_t retval;
+- if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf,
+- tape->stage_size))
++ if (idetape_copy_stage_from_user(tape, buf, tape->buffer_size))
+ ret = -EFAULT;
+- buf += tape->stage_size;
+- count -= tape->stage_size;
++ buf += tape->buffer_size;
++ count -= tape->buffer_size;
+ retval = idetape_add_chrdev_write_request(drive, ctl);
+- actually_written += tape->stage_size;
++ actually_written += tape->buffer_size;
+ if (retval <= 0)
+ return (retval);
+ }
+ if (count) {
+ actually_written += count;
+- if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf,
+- count))
++ if (idetape_copy_stage_from_user(tape, buf, count))
+ ret = -EFAULT;
+- tape->merge_stage_size += count;
++ tape->merge_bh_size += count;
+ }
+ return ret ? ret : actually_written;
+ }
- 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 idetape_write_filemark(ide_drive_t *drive)
+ {
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
- static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ /* Write a filemark */
+ idetape_create_write_filemark_cmd(drive, &pc, 1);
+@@ -2955,8 +2201,7 @@ static int idetape_write_filemark(ide_drive_t *drive)
+ *
+ * Note: MTBSF and MTBSFM are not supported when the tape doesn't support
+ * spacing over filemarks in the reverse direction. In this case, MTFSFM is also
+- * usually not supported (it is supported in the rare case in which we crossed
+- * the filemark during our read-ahead pipelined operation mode).
++ * usually not supported.
+ *
+ * The following commands are currently not supported:
+ *
+@@ -2966,13 +2211,12 @@ static int idetape_write_filemark(ide_drive_t *drive)
+ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
{
- 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;
+ idetape_tape_t *tape = drive->driver_data;
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
+ int i, retval;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ debug_log(DBG_ERR, "Handling MTIOCTOP ioctl: mt_op=%d, mt_count=%d\n",
+ mt_op, mt_count);
-+ rc = pcim_enable_device(pdev);
-+ if (rc)
-+ return rc;
-+
- pci_read_config_byte(pdev, 0x41, &fifo);
+- /* Commands which need our pipelined read-ahead stages. */
+ switch (mt_op) {
+ case MTFSF:
+ case MTFSFM:
+@@ -2989,7 +2233,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
+ case MTWEOF:
+ if (tape->write_prot)
+ return -EACCES;
+- idetape_discard_read_pipeline(drive, 1);
++ ide_tape_discard_merge_buffer(drive, 1);
+ for (i = 0; i < mt_count; i++) {
+ retval = idetape_write_filemark(drive);
+ if (retval)
+@@ -2997,12 +2241,12 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
+ }
+ return 0;
+ case MTREW:
+- idetape_discard_read_pipeline(drive, 0);
++ ide_tape_discard_merge_buffer(drive, 0);
+ if (idetape_rewind_tape(drive))
+ return -EIO;
+ return 0;
+ case MTLOAD:
+- idetape_discard_read_pipeline(drive, 0);
++ ide_tape_discard_merge_buffer(drive, 0);
+ idetape_create_load_unload_cmd(drive, &pc,
+ IDETAPE_LU_LOAD_MASK);
+ return idetape_queue_pc_tail(drive, &pc);
+@@ -3017,18 +2261,18 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
+ if (!idetape_queue_pc_tail(drive, &pc))
+ tape->door_locked = DOOR_UNLOCKED;
+ }
+- idetape_discard_read_pipeline(drive, 0);
++ ide_tape_discard_merge_buffer(drive, 0);
+ idetape_create_load_unload_cmd(drive, &pc,
+ !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);
++ ide_tape_discard_merge_buffer(drive, 0);
+ return idetape_flush_tape_buffers(drive);
+ case MTRETEN:
+- idetape_discard_read_pipeline(drive, 0);
++ ide_tape_discard_merge_buffer(drive, 0);
+ idetape_create_load_unload_cmd(drive, &pc,
+ IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK);
+ return idetape_queue_pc_tail(drive, &pc);
+@@ -3045,16 +2289,16 @@ 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);
++ ide_tape_discard_merge_buffer(drive, 0);
+ return idetape_position_tape(drive,
+ mt_count * tape->user_bs_factor, tape->partition, 0);
+ case MTSETPART:
+- idetape_discard_read_pipeline(drive, 0);
++ ide_tape_discard_merge_buffer(drive, 0);
+ return idetape_position_tape(drive, 0, mt_count, 0);
+ case MTFSR:
+ case MTBSR:
+@@ -3099,13 +2343,12 @@ static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
+
+ debug_log(DBG_CHRDEV, "Enter %s, cmd=%u\n", __func__, cmd);
+
+- tape->restart_speed_control_req = 1;
+ if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
+- idetape_empty_write_pipeline(drive);
++ ide_tape_flush_merge_buffer(drive);
+ idetape_flush_tape_buffers(drive);
+ }
+ if (cmd == MTIOCGET || cmd == MTIOCPOS) {
+- block_offset = idetape_pipeline_size(drive) /
++ block_offset = tape->merge_bh_size /
+ (tape->blk_size * tape->user_bs_factor);
+ position = idetape_read_position(drive);
+ if (position < 0)
+@@ -3137,7 +2380,7 @@ static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
+ return 0;
+ default:
+ if (tape->chrdev_dir == IDETAPE_DIR_READ)
+- idetape_discard_read_pipeline(drive, 1);
++ ide_tape_discard_merge_buffer(drive, 1);
+ return idetape_blkdev_ioctl(drive, cmd, arg);
+ }
+ }
+@@ -3149,7 +2392,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;
- /* 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];
+ idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR);
+ if (idetape_queue_pc_tail(drive, &pc)) {
+@@ -3161,10 +2404,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;
+ }
- if (type < 3)
-- ata_pci_clear_simplex(pdev);
-+ ata_pci_bmdma_clear_simplex(pdev);
+ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
+@@ -3172,7 +2415,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;
- /* 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;
+ if (i >= MAX_HWIFS * MAX_DRIVES)
+@@ -3195,25 +2438,22 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
- pci_read_config_dword(pdev, 0x60, &udma);
-- pi.private_data = (void *)(unsigned long)udma;
-+ hpriv = (void *)(unsigned long)udma;
- }
+ filp->private_data = tape;
- /* And fire it up */
-- return ata_pci_init_one(pdev, ppi);
-+ return ata_pci_sff_init_one(pdev, ppi, &amd_sht, hpriv);
- }
+- 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;
+ }
- #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);
+ 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;
}
-- 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;
+ 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);
-- 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).
-- */
+- if (tape->chrdev_dir != IDETAPE_DIR_READ)
+- clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
-
--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);
- }
+ /* Read block size and write protect status from drive. */
+ ide_tape_get_bsize_from_bdesc(drive);
- /**
-@@ -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;
+@@ -3227,7 +2467,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;
+ }
+@@ -3242,8 +2482,6 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
+ }
+ }
+ }
+- idetape_restart_speed_control(drive);
+- tape->restart_speed_control_req = 0;
+ return 0;
-- return ata_std_prereset(link, deadline);
-+ return ata_sff_prereset(link, deadline);
- }
+ out_put_tape:
+@@ -3255,13 +2493,13 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
+ {
+ idetape_tape_t *tape = drive->driver_data;
- /**
-@@ -114,21 +99,6 @@ static int artop6260_cable_detect(struct ata_port *ap)
- }
+- idetape_empty_write_pipeline(drive);
+- tape->merge_stage = __idetape_kmalloc_stage(tape, 1, 0);
+- if (tape->merge_stage != NULL) {
++ ide_tape_flush_merge_buffer(drive);
++ tape->merge_bh = ide_tape_kmalloc_buffer(tape, 1, 0);
++ if (tape->merge_bh != NULL) {
+ idetape_pad_zeros(drive, tape->blk_size *
+ (tape->user_bs_factor - 1));
+- __idetape_kfree_stage(tape->merge_stage);
+- tape->merge_stage = NULL;
++ ide_tape_kfree_buffer(tape);
++ tape->merge_bh = NULL;
+ }
+ idetape_write_filemark(drive);
+ idetape_flush_tape_buffers(drive);
+@@ -3272,7 +2510,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);
- /**
-- * 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)
- }
+ lock_kernel();
+@@ -3284,15 +2522,10 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
+ idetape_write_release(drive, minor);
+ if (tape->chrdev_dir == IDETAPE_DIR_READ) {
+ if (minor < 128)
+- idetape_discard_read_pipeline(drive, 1);
+- else
+- idetape_wait_for_pipeline(drive);
+- }
+- if (tape->cache_stage != NULL) {
+- __idetape_kfree_stage(tape->cache_stage);
+- tape->cache_stage = NULL;
++ ide_tape_discard_merge_buffer(drive, 1);
+ }
+- 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 +2535,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 +2583,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];
- 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),
- };
+ idetape_create_inquiry_cmd(&pc);
+@@ -3359,9 +2592,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);
--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,
- };
+ ide_fixstring(vendor_id, 10, 0);
+ ide_fixstring(product_id, 18, 0);
+@@ -3378,7 +2611,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;
--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,
- };
+@@ -3392,7 +2625,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]);
+@@ -3428,33 +2661,15 @@ static void idetape_add_settings(ide_drive_t *drive)
-@@ -414,7 +322,6 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff,
+ 1, 2, (u16 *)&tape->caps[16], NULL);
+- ide_add_setting(drive, "pipeline_min", SETTING_RW, TYPE_INT, 1, 0xffff,
+- tape->stage_size / 1024, 1, &tape->min_pipeline, NULL);
+- ide_add_setting(drive, "pipeline", SETTING_RW, TYPE_INT, 1, 0xffff,
+- tape->stage_size / 1024, 1, &tape->max_stages, NULL);
+- ide_add_setting(drive, "pipeline_max", SETTING_RW, TYPE_INT, 1, 0xffff,
+- tape->stage_size / 1024, 1, &tape->max_pipeline, NULL);
+- ide_add_setting(drive, "pipeline_used", SETTING_READ, TYPE_INT, 0,
+- 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages,
+- NULL);
+- ide_add_setting(drive, "pipeline_pending", SETTING_READ, TYPE_INT, 0,
+- 0xffff, tape->stage_size / 1024, 1,
+- &tape->nr_pending_stages, NULL);
+ ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff,
+ 1, 1, (u16 *)&tape->caps[14], NULL);
+- ide_add_setting(drive, "stage", SETTING_READ, TYPE_INT, 0, 0xffff, 1,
+- 1024, &tape->stage_size, NULL);
++ ide_add_setting(drive, "buffer_size", SETTING_READ, TYPE_INT, 0, 0xffff,
++ 1, 1024, &tape->buffer_size, NULL);
+ ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN,
+ IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_freq,
+ NULL);
+ ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1,
+ 1, &drive->dsc_overlap, NULL);
+- ide_add_setting(drive, "pipeline_head_speed_c", SETTING_READ, TYPE_INT,
+- 0, 0xffff, 1, 1, &tape->controlled_pipeline_head_speed,
+- NULL);
+- ide_add_setting(drive, "pipeline_head_speed_u", SETTING_READ, TYPE_INT,
+- 0, 0xffff, 1, 1,
+- &tape->uncontrolled_pipeline_head_speed, NULL);
+ ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff,
+ 1, 1, &tape->avg_speed, NULL);
+ ide_add_setting(drive, "debug_mask", SETTING_RW, TYPE_INT, 0, 0xffff, 1,
+@@ -3477,11 +2692,10 @@ static inline void idetape_add_settings(ide_drive_t *drive) { ; }
+ */
+ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
{
- 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;
+- unsigned long t1, tmid, tn, t;
++ unsigned long t;
+ int speed;
+- int stage_size;
++ int buffer_size;
+ u8 gcw[2];
+- struct sysinfo si;
+ u16 *ctl = (u16 *)&tape->caps[12];
+
+ spin_lock_init(&tape->lock);
+@@ -3500,65 +2714,33 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
+ tape->name[2] = '0' + minor;
+ tape->chrdev_dir = IDETAPE_DIR_NONE;
+ tape->pc = tape->pc_stack;
+- tape->max_insert_speed = 10000;
+- tape->speed_control = 1;
+ *((unsigned short *) &gcw) = drive->id->config;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev,
- "version " DRV_VERSION "\n");
+ /* Command packet DRQ type */
+ if (((gcw[0] & 0x60) >> 5) == 1)
+- set_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags);
+-
+- tape->min_pipeline = 10;
+- tape->max_pipeline = 10;
+- tape->max_stages = 10;
++ set_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags);
-+ 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)
+ idetape_get_inquiry_results(drive);
+ idetape_get_mode_sense_results(drive);
+ ide_tape_get_bsize_from_bdesc(drive);
+ tape->user_bs_factor = 1;
+- tape->stage_size = *ctl * tape->blk_size;
+- while (tape->stage_size > 0xffff) {
++ tape->buffer_size = *ctl * tape->blk_size;
++ while (tape->buffer_size > 0xffff) {
+ printk(KERN_NOTICE "ide-tape: decreasing stage size\n");
+ *ctl /= 2;
+- tape->stage_size = *ctl * tape->blk_size;
++ tape->buffer_size = *ctl * tape->blk_size;
+ }
+- stage_size = tape->stage_size;
+- tape->pages_per_stage = stage_size / PAGE_SIZE;
+- if (stage_size % PAGE_SIZE) {
+- tape->pages_per_stage++;
+- tape->excess_bh_size = PAGE_SIZE - stage_size % PAGE_SIZE;
++ buffer_size = tape->buffer_size;
++ tape->pages_per_buffer = buffer_size / PAGE_SIZE;
++ if (buffer_size % PAGE_SIZE) {
++ tape->pages_per_buffer++;
++ tape->excess_bh_size = PAGE_SIZE - buffer_size % PAGE_SIZE;
+ }
+
+- /* Select the "best" DSC read/write polling freq and pipeline size. */
++ /* select the "best" DSC read/write polling freq */
+ speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]);
+
+- tape->max_stages = speed * 1000 * 10 / tape->stage_size;
+-
+- /* Limit memory use for pipeline to 10% of physical memory */
+- si_meminfo(&si);
+- if (tape->max_stages * tape->stage_size >
+- si.totalram * si.mem_unit / 10)
+- tape->max_stages =
+- si.totalram * si.mem_unit / (10 * tape->stage_size);
+-
+- tape->max_stages = min(tape->max_stages, IDETAPE_MAX_PIPELINE_STAGES);
+- tape->min_pipeline = min(tape->max_stages, IDETAPE_MIN_PIPELINE_STAGES);
+- tape->max_pipeline =
+- min(tape->max_stages * 2, IDETAPE_MAX_PIPELINE_STAGES);
+- if (tape->max_stages == 0) {
+- tape->max_stages = 1;
+- tape->min_pipeline = 1;
+- tape->max_pipeline = 1;
+- }
+-
+- t1 = (tape->stage_size * HZ) / (speed * 1000);
+- tmid = (*(u16 *)&tape->caps[16] * 32 * HZ) / (speed * 125);
+- tn = (IDETAPE_FIFO_THRESHOLD * tape->stage_size * HZ) / (speed * 1000);
+-
+- if (tape->max_stages)
+- t = tn;
+- else
+- t = t1;
++ t = (IDETAPE_FIFO_THRESHOLD * tape->buffer_size * HZ) / (speed * 1000);
- BUG_ON(ppi[0] == NULL);
+ /*
+ * Ensure that the number we got makes sense; limit it within
+@@ -3568,11 +2750,10 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
+ min_t(unsigned long, t, IDETAPE_DSC_RW_MAX),
+ IDETAPE_DSC_RW_MIN);
+ printk(KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, "
+- "%dkB pipeline, %lums tDSC%s\n",
++ "%lums tDSC%s\n",
+ drive->name, tape->name, *(u16 *)&tape->caps[14],
+- (*(u16 *)&tape->caps[16] * 512) / tape->stage_size,
+- tape->stage_size / 1024,
+- tape->max_stages * tape->stage_size / 1024,
++ (*(u16 *)&tape->caps[16] * 512) / tape->buffer_size,
++ tape->buffer_size / 1024,
+ tape->best_dsc_rw_freq * 1000 / HZ,
+ drive->using_dma ? ", DMA":"");
-- return ata_pci_init_one(pdev, ppi);
-+ return ata_pci_sff_init_one(pdev, ppi, &artop_sht, NULL);
- }
+@@ -3596,7 +2777,7 @@ static void ide_tape_release(struct kref *kref)
+ ide_drive_t *drive = tape->drive;
+ struct gendisk *g = tape->disk;
- 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)
- }
- }
+- BUG_ON(tape->first_stage != NULL || tape->merge_stage_size);
++ BUG_ON(tape->merge_bh_size);
--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),
- };
+ drive->dsc_overlap = 0;
+ drive->driver_data = NULL;
+diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
+index 4c86a8d..0c908ca 100644
+--- a/drivers/ide/ide-taskfile.c
++++ b/drivers/ide/ide-taskfile.c
+@@ -33,58 +33,18 @@
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
- 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,
+-void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
++void ide_tf_dump(const char *s, struct ide_taskfile *tf)
+ {
+- ide_hwif_t *hwif = drive->hwif;
+- struct ide_taskfile *tf = &task->tf;
+- u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
-
-- .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,
+- if (task->tf_flags & IDE_TFLAG_FLAGGED)
+- HIHI = 0xFF;
-
-- .qc_prep = ata_qc_prep,
-- .qc_issue = ata_qc_issue_prot,
+ #ifdef DEBUG
+ printk("%s: tf: feat 0x%02x nsect 0x%02x lbal 0x%02x "
+ "lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n",
+- drive->name, tf->feature, tf->nsect, tf->lbal,
++ s, tf->feature, tf->nsect, tf->lbal,
+ tf->lbam, tf->lbah, tf->device, tf->command);
+ printk("%s: hob: nsect 0x%02x lbal 0x%02x "
+ "lbam 0x%02x lbah 0x%02x\n",
+- drive->name, tf->hob_nsect, tf->hob_lbal,
++ s, tf->hob_nsect, tf->hob_lbal,
+ tf->hob_lbam, tf->hob_lbah);
+ #endif
-
-- .data_xfer = ata_data_xfer,
+- ide_set_irq(drive, 1);
-
-- .irq_clear = pata_at32_irq_clear,
-- .irq_on = ata_irq_on,
+- if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0)
+- SELECT_MASK(drive, 0);
-
-- .port_start = ata_sff_port_start,
-+ .set_piomode = pata_at32_set_piomode,
- };
+- if (task->tf_flags & IDE_TFLAG_OUT_DATA)
+- hwif->OUTW((tf->hob_data << 8) | tf->data, IDE_DATA_REG);
+-
+- if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+- hwif->OUTB(tf->hob_feature, IDE_FEATURE_REG);
+- if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+- hwif->OUTB(tf->hob_nsect, IDE_NSECTOR_REG);
+- if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+- hwif->OUTB(tf->hob_lbal, IDE_SECTOR_REG);
+- if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+- hwif->OUTB(tf->hob_lbam, IDE_LCYL_REG);
+- if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+- hwif->OUTB(tf->hob_lbah, IDE_HCYL_REG);
+-
+- if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+- hwif->OUTB(tf->feature, IDE_FEATURE_REG);
+- if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+- hwif->OUTB(tf->nsect, IDE_NSECTOR_REG);
+- if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+- hwif->OUTB(tf->lbal, IDE_SECTOR_REG);
+- if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+- hwif->OUTB(tf->lbam, IDE_LCYL_REG);
+- if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+- hwif->OUTB(tf->lbah, IDE_HCYL_REG);
+-
+- if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
+- hwif->OUTB((tf->device & HIHI) | drive->select.all, IDE_SELECT_REG);
+ }
- 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;
+ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
+@@ -133,6 +93,7 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
+ ide_hwif_t *hwif = HWIF(drive);
+ struct ide_taskfile *tf = &task->tf;
+ ide_handler_t *handler = NULL;
++ const struct ide_dma_ops *dma_ops = hwif->dma_ops;
- /* 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);
+ if (task->data_phase == TASKFILE_MULTI_IN ||
+ task->data_phase == TASKFILE_MULTI_OUT) {
+@@ -146,13 +107,15 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
+ if (task->tf_flags & IDE_TFLAG_FLAGGED)
+ task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS;
+
+- if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0)
+- ide_tf_load(drive, task);
++ if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) {
++ ide_tf_dump(drive->name, tf);
++ hwif->tf_load(drive, 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.command_addr);
+ ndelay(400); /* FIXME */
+ return pre_task_out_intr(drive, task->rq);
+ case TASKFILE_MULTI_IN:
+@@ -175,10 +138,10 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
+ return ide_started;
+ default:
+ if (task_dma_ok(task) == 0 || drive->using_dma == 0 ||
+- hwif->dma_setup(drive))
++ dma_ops->dma_setup(drive))
+ return ide_stopped;
+- hwif->dma_exec_cmd(drive, tf->command);
+- hwif->dma_start(drive);
++ dma_ops->dma_exec_cmd(drive, tf->command);
++ dma_ops->dma_start(drive);
+ return ide_started;
+ }
}
-@@ -419,6 +381,9 @@ static int __exit pata_at32_remove(struct platform_device *pdev)
- return 0;
+@@ -280,7 +243,8 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
+ return stat;
}
-+/* 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;
+-static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
++static void ide_pio_sector(ide_drive_t *drive, struct request *rq,
++ unsigned int write)
+ {
+ ide_hwif_t *hwif = drive->hwif;
+ struct scatterlist *sg = hwif->sg_table;
+@@ -320,9 +284,9 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
-- 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);
- }
+ /* do the actual data transfer */
+ if (write)
+- hwif->ata_output_data(drive, buf, SECTOR_WORDS);
++ hwif->output_data(drive, rq, buf, SECTOR_SIZE);
+ else
+- hwif->ata_input_data(drive, buf, SECTOR_WORDS);
++ hwif->input_data(drive, rq, buf, SECTOR_SIZE);
- static int atiixp_cable_detect(struct ata_port *ap)
-@@ -221,60 +216,26 @@ static void atiixp_bmdma_stop(struct ata_queued_cmd *qc)
+ kunmap_atomic(buf, KM_BIO_SRC_IRQ);
+ #ifdef CONFIG_HIGHMEM
+@@ -330,13 +294,14 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
+ #endif
}
- 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 void ide_pio_multi(ide_drive_t *drive, unsigned int write)
++static void ide_pio_multi(ide_drive_t *drive, struct request *rq,
++ unsigned int write)
+ {
+ unsigned int nsect;
- 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,
+ nsect = min_t(unsigned int, drive->hwif->nleft, drive->mult_count);
+ while (nsect--)
+- ide_pio_sector(drive, write);
++ ide_pio_sector(drive, rq, write);
+ }
-- .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,
+ static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
+@@ -359,10 +324,10 @@ static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
+ switch (drive->hwif->data_phase) {
+ case TASKFILE_MULTI_IN:
+ case TASKFILE_MULTI_OUT:
+- ide_pio_multi(drive, write);
++ ide_pio_multi(drive, rq, write);
+ break;
+ default:
+- ide_pio_sector(drive, write);
++ ide_pio_sector(drive, rq, write);
+ break;
+ }
-- .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,
- };
+@@ -452,7 +417,7 @@ static ide_startstop_t task_in_intr(ide_drive_t *drive)
- static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ /* Error? */
+ if (stat & ERR_STAT)
+- return task_error(drive, rq, __FUNCTION__, stat);
++ return task_error(drive, rq, __func__, stat);
+
+ /* Didn't want any data? Odd. */
+ if (!(stat & DRQ_STAT))
+@@ -464,7 +429,7 @@ static ide_startstop_t task_in_intr(ide_drive_t *drive)
+ if (!hwif->nleft) {
+ stat = wait_drive_not_busy(drive);
+ if (!OK_STAT(stat, 0, BAD_STAT))
+- return task_error(drive, rq, __FUNCTION__, stat);
++ return task_error(drive, rq, __func__, stat);
+ task_end_request(drive, rq, stat);
+ return ide_stopped;
+ }
+@@ -485,11 +450,11 @@ static ide_startstop_t task_out_intr (ide_drive_t *drive)
+ u8 stat = ide_read_status(drive);
+
+ if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
+- return task_error(drive, rq, __FUNCTION__, stat);
++ return task_error(drive, rq, __func__, stat);
+
+ /* Deal with unexpected ATA data phase. */
+ if (((stat & DRQ_STAT) == 0) ^ !hwif->nleft)
+- return task_error(drive, rq, __FUNCTION__, stat);
++ return task_error(drive, rq, __func__, stat);
+
+ if (!hwif->nleft) {
+ task_end_request(drive, rq, stat);
+@@ -529,8 +494,7 @@ int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *task, u8 *buf, u16 nsect)
{
- 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);
- }
+ struct request rq;
- 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().
- */
+- memset(&rq, 0, sizeof(rq));
+- rq.ref_count = 1;
++ blk_rq_init(NULL, &rq);
+ rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
+ rq.buffer = buf;
- 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().
- */
+@@ -672,7 +636,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
+ /* (hs): give up if multcount is not set */
+ printk(KERN_ERR "%s: %s Multimode Write " \
+ "multcount is not set\n",
+- drive->name, __FUNCTION__);
++ drive->name, __func__);
+ err = -EPERM;
+ goto abort;
+ }
+@@ -689,7 +653,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
+ /* (hs): give up if multcount is not set */
+ printk(KERN_ERR "%s: %s Multimode Read failure " \
+ "multcount is not set\n",
+- drive->name, __FUNCTION__);
++ drive->name, __func__);
+ err = -EPERM;
+ goto abort;
+ }
+diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
+index fc69fe2..c758dcb 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
- 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().
- */
++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,32 +92,17 @@ 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);
- 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);
+-#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
+-int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
+-#endif
+-
+ int noautodma = 0;
- write_atapi_register(base, ATA_REG_CMD, tf->command);
-- ata_pause(ap);
-+ ata_sff_pause(ap);
- }
+-#ifdef CONFIG_BLK_DEV_IDEACPI
+-int ide_noacpi = 0;
+-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 */
- /**
-@@ -800,14 +800,14 @@ static u8 bfin_check_altstatus(struct ata_port *ap)
- }
+-EXPORT_SYMBOL(ide_hwifs);
++static void ide_port_init_devices_data(ide_hwif_t *);
- /**
-- * 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().
+ /*
+ * Do not even *think* about calling this!
*/
-
--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 ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
{
- 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;
+- unsigned int unit;
+-
+ /* bulk initialize hwif & drive info with zeros */
+ memset(hwif, 0, sizeof(ide_hwif_t));
- write_atapi_register(base, ATA_REG_DEVICE, tmp);
-- ata_pause(ap);
-+ ata_sff_pause(ap);
- }
+@@ -134,8 +121,20 @@ void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
- /**
-@@ -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;
+ 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));
-- bfin_std_dev_select(ap, device);
-+ bfin_dev_select(ap, device);
+ drive->media = ide_disk;
+ drive->select.all = (unit<<4)|0xa0;
+@@ -147,32 +146,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
+-}
- 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);
+ /*
+ * init_ide_data() sets reasonable default values into all fields
+@@ -194,7 +174,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;
- /* 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;
+@@ -204,13 +183,9 @@ static void __init init_ide_data (void)
-- 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 */
+ /* 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
}
- 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);
+@@ -246,219 +221,6 @@ static int ide_system_bus_speed(void)
+ return pci_dev_present(pci_default) ? 33 : 50;
}
- /**
-@@ -1088,26 +1088,21 @@ static unsigned int bfin_bus_softreset(struct ata_port *ap,
+-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)
+-{
+- struct resource *res = request_region(addr, num, hwif->name);
+-
+- if (!res)
+- printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
+- hwif->name, addr, addr+num-1);
+- return res;
+-}
+-
+-/**
+- * ide_hwif_request_regions - request resources for IDE
+- * @hwif: interface to use
+- *
+- * Requests all the needed resources for an interface.
+- * Right now core IDE code does this work which is deeply wrong.
+- * MMIO leaves it to the controller driver,
+- * PIO will migrate this way over time.
+- */
+-
+-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;
+- }
+- }
+- return 0;
+-
+-data_region_busy:
+- addr = hwif->io_ports[IDE_CONTROL_OFFSET];
+- if (addr)
+- release_region(addr, 1);
+-control_region_busy:
+- /* If any errors are return, we drop the hwif interface. */
+- return -EBUSY;
+-}
+-
+-/**
+- * ide_hwif_release_regions - free IDE resources
+- *
+- * Note that we only release the standard ports,
+- * and do not even try to handle any extra ports
+- * allocated for weird IDE interface chipsets.
+- *
+- * Note also that we don't yet handle mmio resources here. More
+- * importantly our caller should be doing this so we need to
+- * restructure this as a helper function for drivers.
+- */
+-
+-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;
+-}
+-
+ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
+ {
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
+@@ -494,11 +256,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);
++
/**
-- * 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
+ * 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
++ * @hwif: IDE interface
*
-- * Note: Original code is ata_std_softreset().
-+ * Note: Original code is ata_sff_softreset().
+ * Perform the final unregister of an IDE interface. At the moment
+ * we don't refcount interfaces so this will also get split up.
+@@ -518,32 +307,19 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
+ * This is raving bonkers.
*/
--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)
+-void ide_unregister(unsigned int index, int init_default, int restore)
++void ide_unregister(ide_hwif_t *hwif)
{
- 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;
-- }
+- ide_drive_t *drive;
+- ide_hwif_t *hwif, *g;
+- static ide_hwif_t tmp_hwif; /* protected by ide_cfg_mtx */
++ ide_hwif_t *g;
+ ide_hwgroup_t *hwgroup;
+- int irq_count = 0, unit;
-
- /* 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().
- */
+- BUG_ON(index >= MAX_HWIFS);
++ int irq_count = 0;
- static unsigned char bfin_irq_on(struct ata_port *ap)
-@@ -1244,13 +1238,13 @@ static unsigned char bfin_irq_on(struct ata_port *ap)
- }
+ BUG_ON(in_interrupt());
+ BUG_ON(irqs_disabled());
+ mutex_lock(&ide_cfg_mtx);
+ spin_lock_irq(&ide_lock);
+- 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;
- /**
-- * 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().
- */
+ spin_unlock_irq(&ide_lock);
+@@ -565,6 +341,7 @@ void ide_unregister(unsigned int index, int init_default, int restore)
--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;
+ ide_remove_port_from_hwgroup(hwif);
-@@ -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);
++ device_unregister(hwif->portdev);
+ device_unregister(&hwif->gendev);
+ wait_for_completion(&hwif->gendev_rel_comp);
- bfin_irq_clear(ap);
- }
+@@ -576,33 +353,11 @@ void ide_unregister(unsigned int index, int init_default, int restore)
+ unregister_blkdev(hwif->major, hwif->name);
+ spin_lock_irq(&ide_lock);
- /**
-- * 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().
- */
+- 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;
+- }
+-
+- ide_hwif_release_regions(hwif);
+-
+- /* copy original settings */
+- tmp_hwif = *hwif;
++ if (hwif->dma_base)
++ ide_release_dma_engine(hwif);
--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)
- }
+ /* 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);
++ ide_init_port_data(hwif, hwif->index);
- /**
-- * 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().
- */
+ abort:
+ spin_unlock_irq(&ide_lock);
+@@ -613,88 +368,14 @@ EXPORT_SYMBOL(ide_unregister);
--static void bfin_std_postreset(struct ata_link *link, unsigned int *classes)
-+static void bfin_postreset(struct ata_link *link, unsigned int *classes)
+ void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
{
- 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);
+- memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports));
++ memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports));
+ hwif->irq = hw->irq;
+- hwif->noprobe = 0;
+ hwif->chipset = hw->chipset;
+ hwif->gendev.parent = hw->dev;
+ hwif->ack_intr = hw->ack_intr;
}
+ 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);
+-
-/**
-- * bfin_error_handler - Stock error handler for DMA controller
-- * @ap: port to handle error for
+- * 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.
- */
-
--static void bfin_error_handler(struct ata_port *ap)
+-int ide_register_hw(hw_regs_t *hw, void (*quirkproc)(ide_drive_t *),
+- ide_hwif_t **hwifp)
-{
-- ata_bmdma_drive_eh(ap, ata_std_prereset, bfin_std_softreset, NULL,
-- bfin_std_postreset);
+- 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;
-}
-
- 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,
- };
+-EXPORT_SYMBOL(ide_register_hw);
+-
+ /*
+ * Locks for IDE setting functionality
+ */
+@@ -779,7 +460,7 @@ int set_using_dma(ide_drive_t *drive, int arg)
+ if (!drive->id || !(drive->id->capability & 1))
+ goto out;
- static const struct ata_port_operations bfin_pata_ops = {
-+ .inherits = &ata_sff_port_ops,
-+
- .set_piomode = bfin_set_piomode,
- .set_dmamode = bfin_set_dmamode,
+- if (hwif->dma_host_set == NULL)
++ if (hwif->dma_ops == NULL)
+ goto out;
-- .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,
+ err = -EBUSY;
+@@ -818,11 +499,14 @@ out:
+ int set_pio_mode(ide_drive_t *drive, int arg)
+ {
+ struct request rq;
++ ide_hwif_t *hwif = drive->hwif;
++ const struct ide_port_ops *port_ops = hwif->port_ops;
- .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,
+ if (arg < 0 || arg > 255)
+ return -EINVAL;
- .qc_prep = ata_noop_qc_prep,
-- .qc_issue = ata_qc_issue_prot,
+- if (drive->hwif->set_pio_mode == NULL)
++ if (port_ops == NULL || port_ops->set_pio_mode == NULL ||
++ (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
+ return -ENOSYS;
-- .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,
+ if (drive->special.b.set_tune)
+@@ -880,7 +564,7 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
+ if (!(drive->dn % 2))
+ ide_acpi_get_timing(hwif);
+
+- memset(&rq, 0, sizeof(rq));
++ blk_rq_init(NULL, &rq);
+ memset(&rqpm, 0, sizeof(rqpm));
+ memset(&args, 0, sizeof(args));
+ rq.cmd_type = REQ_TYPE_PM_SUSPEND;
+@@ -918,7 +602,7 @@ static int generic_ide_resume(struct device *dev)
+
+ ide_acpi_exec_tfs(drive);
+
+- memset(&rq, 0, sizeof(rq));
++ blk_rq_init(NULL, &rq);
+ memset(&rqpm, 0, sizeof(rqpm));
+ memset(&args, 0, sizeof(args));
+ rq.cmd_type = REQ_TYPE_PM_RESUME;
+@@ -997,27 +681,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 +734,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;
+@@ -1167,15 +828,6 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m
+ return 0; /* zero = nothing matched */
+ }
-- .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,
+-extern int probe_ali14xx;
+-extern int probe_umc8672;
+-extern int probe_dtc2278;
+-extern int probe_ht6560b;
+-extern int probe_qd65xx;
+-extern int cmd640_vlb;
+-
+-static int __initdata is_chipset_set[MAX_HWIFS];
+-
+ /*
+ * ide_setup() gets called VERY EARLY during initialization,
+ * to handle kernel "command line" strings beginning with "hdx=" or "ide".
+@@ -1184,14 +836,12 @@ static int __initdata is_chipset_set[MAX_HWIFS];
+ */
+ static int __init ide_setup(char *s)
+ {
+- int i, vals[3];
+ ide_hwif_t *hwif;
+ ide_drive_t *drive;
+ unsigned int hw, unit;
++ int vals[3];
+ const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1);
+- const char max_hwif = '0' + (MAX_HWIFS - 1);
- .port_start = bfin_port_start,
- .port_stop = bfin_port_stop,
-@@ -1409,7 +1381,6 @@ static const struct ata_port_operations bfin_pata_ops = {
+-
+ if (strncmp(s,"hd",2) == 0 && s[2] == '=') /* hd= is for hd.c */
+ return 0; /* driver and not us */
- 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));
+@@ -1207,7 +857,7 @@ static int __init ide_setup(char *s)
- /* 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)
+ printk(" : Enabled support for IDE doublers\n");
+ ide_doubler = 1;
+- return 1;
++ goto obsolete_option;
}
+ #endif /* CONFIG_BLK_DEV_IDEDOUBLER */
- if (ata_host_activate(host, platform_get_irq(pdev, 0),
-- ata_interrupt, IRQF_SHARED, &bfin_sht) != 0) {
-+ ata_sff_interrupt, IRQF_SHARED, &bfin_sht) != 0) {
- peripheral_free_list(atapi_io_port);
- dev_err(&pdev->dev, "Fail to attach ATAPI device\n");
- return -ENODEV;
-@@ -1630,3 +1601,4 @@ MODULE_AUTHOR("Sonic Zhang <sonic.zhang at analog.com>");
- MODULE_DESCRIPTION("PATA driver for blackfin 54x ATAPI controller");
- MODULE_LICENSE("GPL");
- MODULE_VERSION(DRV_VERSION);
-+MODULE_ALIAS("platform:" DRV_NAME);
-diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c
-index 43d198f..2de30b9 100644
---- a/drivers/ata/pata_cmd640.c
-+++ b/drivers/ata/pata_cmd640.c
-@@ -107,8 +107,8 @@ static void cmd640_set_piomode(struct ata_port *ap, struct ata_device *adev)
- pci_write_config_byte(pdev, arttim + 1, (t.active << 4) | t.recover);
- } else {
- /* Save the shared timings for channel, they will be loaded
-- by qc_issue_prot. Reloading the setup time is expensive
-- so we keep a merged one loaded */
-+ by qc_issue. Reloading the setup time is expensive so we
-+ keep a merged one loaded */
- pci_read_config_byte(pdev, ARTIM23, ®);
- reg &= 0x3F;
- reg |= t.setup;
-@@ -119,14 +119,14 @@ static void cmd640_set_piomode(struct ata_port *ap, struct ata_device *adev)
-
-
- /**
-- * cmd640_qc_issue_prot - command preparation hook
-+ * cmd640_qc_issue - command preparation hook
- * @qc: Command to be issued
- *
- * Channel 1 has shared timings. We must reprogram the
- * clock each drive 2/3 switch we do.
- */
-
--static unsigned int cmd640_qc_issue_prot(struct ata_queued_cmd *qc)
-+static unsigned int cmd640_qc_issue(struct ata_queued_cmd *qc)
- {
- struct ata_port *ap = qc->ap;
- struct ata_device *adev = qc->dev;
-@@ -137,7 +137,7 @@ static unsigned int cmd640_qc_issue_prot(struct ata_queued_cmd *qc)
- pci_write_config_byte(pdev, DRWTIM23, timing->reg58[adev->devno]);
- timing->last = adev->devno;
+@@ -1217,29 +867,21 @@ static int __init ide_setup(char *s)
+ goto obsolete_option;
}
-- 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),
- };
+-#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");
+ ide_noacpi = 1;
+- return 1;
++ goto obsolete_option;
+ }
+ if (!strcmp(s, "ide=acpigtf")) {
+ //printk(" : Enable IDE ACPI _GTF support.\n");
+- ide_noacpitfs = 0;
+- return 1;
++ ide_acpigtf = 1;
++ goto obsolete_option;
+ }
+ if (!strcmp(s, "ide=acpionboot")) {
+ //printk(" : Call IDE ACPI methods on boot.\n");
+- ide_noacpionboot = 0;
+- return 1;
++ ide_acpionboot = 1;
++ goto obsolete_option;
+ }
+ #endif /* CONFIG_BLK_DEV_IDEACPI */
- 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,
+@@ -1249,7 +891,7 @@ static int __init ide_setup(char *s)
+ if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {
+ const char *hd_words[] = {
+ "none", "noprobe", "nowerr", "cdrom", "nodma",
+- "autotune", "noautotune", "-8", "-9", "-10",
++ "-6", "-7", "-8", "-9", "-10",
+ "noflush", "remap", "remap63", "scsi", NULL };
+ unit = s[2] - 'a';
+ hw = unit / MAX_DRIVES;
+@@ -1264,30 +906,22 @@ static int __init ide_setup(char *s)
+ case -1: /* "none" */
+ case -2: /* "noprobe" */
+ drive->noprobe = 1;
+- goto done;
++ goto obsolete_option;
+ case -3: /* "nowerr" */
+ drive->bad_wstat = BAD_R_STAT;
+- hwif->noprobe = 0;
+- goto done;
++ goto obsolete_option;
+ case -4: /* "cdrom" */
+ drive->present = 1;
+ drive->media = ide_cdrom;
+ /* an ATAPI device ignores DRDY */
+ drive->ready_stat = 0;
+- hwif->noprobe = 0;
+- goto done;
++ goto obsolete_option;
+ case -5: /* nodma */
+ drive->nodma = 1;
+- goto done;
+- case -6: /* "autotune" */
+- drive->autotune = IDE_TUNE_AUTO;
+- goto obsolete_option;
+- case -7: /* "noautotune" */
+- drive->autotune = IDE_TUNE_NOAUTO;
+ goto obsolete_option;
+ case -11: /* noflush */
+ drive->noflush = 1;
+- goto done;
++ goto obsolete_option;
+ case -12: /* "remap" */
+ drive->remap_0_to_1 = 1;
+ goto obsolete_option;
+@@ -1305,8 +939,7 @@ static int __init ide_setup(char *s)
+ drive->sect = drive->bios_sect = vals[2];
+ drive->present = 1;
+ drive->forced_geom = 1;
+- hwif->noprobe = 0;
+- goto done;
++ goto obsolete_option;
+ default:
+ goto bad_option;
+ }
+@@ -1324,155 +957,15 @@ static int __init ide_setup(char *s)
+ idebus_parameter = vals[0];
+ } else
+ printk(" -- BAD BUS SPEED! Expected value from 20 to 66");
+- goto done;
++ goto obsolete_option;
+ }
+- /*
+- * Look for interface options: "idex="
+- */
+- if (s[3] >= '0' && s[3] <= max_hwif) {
+- /*
+- * Be VERY CAREFUL changing this: note hardcoded indexes below
+- * (-8, -9, -10) are reserved to ease the hardcoding.
+- */
+- static const char *ide_words[] = {
+- "noprobe", "serialize", "minus3", "minus4",
+- "reset", "minus6", "ata66", "minus8", "minus9",
+- "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb",
+- "dtc2278", "umc8672", "ali14xx", NULL };
-
-- .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,
+- hw_regs_t hwregs;
-
-- .bmdma_setup = ata_bmdma_setup,
-- .bmdma_start = ata_bmdma_start,
-- .bmdma_stop = ata_bmdma_stop,
-- .bmdma_status = ata_bmdma_status,
+- hw = s[3] - '0';
+- hwif = &ide_hwifs[hw];
+- i = match_parm(&s[4], ide_words, vals, 3);
-
-- .qc_prep = ata_qc_prep,
-- .qc_issue = cmd640_qc_issue_prot,
+- /*
+- * 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)) {
+- /* chipset already specified */
+- if (is_chipset_set[hw])
+- 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;
+- printk("\n");
+- }
-
-- /* In theory this is not needed once we kill the prefetcher */
-- .data_xfer = ata_data_xfer_noirq,
+- switch (i) {
+-#ifdef CONFIG_BLK_DEV_ALI14XX
+- case -17: /* "ali14xx" */
+- probe_ali14xx = 1;
+- goto obsolete_option;
+-#endif
+-#ifdef CONFIG_BLK_DEV_UMC8672
+- case -16: /* "umc8672" */
+- probe_umc8672 = 1;
+- goto obsolete_option;
+-#endif
+-#ifdef CONFIG_BLK_DEV_DTC2278
+- case -15: /* "dtc2278" */
+- probe_dtc2278 = 1;
+- goto obsolete_option;
+-#endif
+-#ifdef CONFIG_BLK_DEV_CMD640
+- case -14: /* "cmd640_vlb" */
+- cmd640_vlb = 1;
+- goto obsolete_option;
+-#endif
+-#ifdef CONFIG_BLK_DEV_HT6560B
+- case -13: /* "ht6560b" */
+- probe_ht6560b = 1;
+- goto obsolete_option;
+-#endif
+-#ifdef CONFIG_BLK_DEV_QD65XX
+- case -12: /* "qd65xx" */
+- probe_qd65xx = 1;
+- goto obsolete_option;
+-#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;
+- goto obsolete_option;
+- }
+-#endif /* CONFIG_BLK_DEV_4DRIVES */
+- case -10: /* minus10 */
+- case -9: /* minus9 */
+- case -8: /* minus8 */
+- case -6:
+- case -4:
+- case -3:
+- goto bad_option;
+- case -7: /* ata66 */
+-#ifdef CONFIG_BLK_DEV_IDEPCI
+- /*
+- * Use ATA_CBL_PATA40_SHORT so drive side
+- * cable detection is also overriden.
+- */
+- hwif->cbl = ATA_CBL_PATA40_SHORT;
+- goto obsolete_option;
+-#else
+- goto bad_hwif;
+-#endif
+- case -5: /* "reset" */
+- hwif->reset = 1;
+- goto obsolete_option;
+- case -2: /* "serialize" */
+- hwif->mate = &ide_hwifs[hw^1];
+- hwif->mate->mate = hwif;
+- hwif->serialized = hwif->mate->serialized = 1;
+- goto obsolete_option;
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- case -1: /* "noprobe" */
+- hwif->noprobe = 1;
+- goto obsolete_option;
-
-+ .set_piomode = cmd640_set_piomode,
- .port_start = cmd640_port_start,
- };
+- 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;
-@@ -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;
+- case 0: goto bad_option;
+- default:
+- printk(" -- SUPPORT NOT CONFIGURED IN THIS KERNEL\n");
+- return 1;
+- }
+- }
+ bad_option:
+ printk(" -- BAD OPTION\n");
+ return 1;
+ obsolete_option:
+ printk(" -- OBSOLETE OPTION, WILL BE REMOVED SOON!\n");
+ return 1;
+-bad_hwif:
+- printk("-- NOT SUPPORTED ON ide%d", hw);
+-done:
+- printk("\n");
+- return 1;
+ }
- cmd640_hardware_init(pdev);
-- return ata_pci_init_one(pdev, ppi);
+ EXPORT_SYMBOL(ide_lock);
+@@ -1601,6 +1094,192 @@ 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);
+
-+ return ata_pci_sff_init_one(pdev, ppi, &cmd640_sht, NULL);
- }
++ put_device(&hwif->gendev);
++}
++
++int ide_vlb_clk;
++EXPORT_SYMBOL_GPL(ide_vlb_clk);
++
++module_param_named(vlb_clock, ide_vlb_clk, int, 0);
++MODULE_PARM_DESC(vlb_clock, "VLB clock frequency (in MHz)");
++
++int ide_pci_clk;
++EXPORT_SYMBOL_GPL(ide_pci_clk);
++
++module_param_named(pci_clock, ide_pci_clk, int, 0);
++MODULE_PARM_DESC(pci_clock, "PCI bus clock frequency (in MHz)");
++
++static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp)
++{
++ int a, b, i, j = 1;
++ unsigned int *dev_param_mask = (unsigned int *)kp->arg;
++
++ if (sscanf(s, "%d.%d:%d", &a, &b, &j) != 3 &&
++ sscanf(s, "%d.%d", &a, &b) != 2)
++ return -EINVAL;
++
++ i = a * MAX_DRIVES + b;
++
++ if (i >= MAX_HWIFS * MAX_DRIVES || j < 0 || j > 1)
++ return -EINVAL;
++
++ if (j)
++ *dev_param_mask |= (1 << i);
++ else
++ *dev_param_mask &= (1 << i);
++
++ return 0;
++}
++
++static unsigned int ide_nodma;
++
++module_param_call(nodma, ide_set_dev_param_mask, NULL, &ide_nodma, 0);
++MODULE_PARM_DESC(nodma, "disallow DMA for a device");
++
++static unsigned int ide_noflush;
++
++module_param_call(noflush, ide_set_dev_param_mask, NULL, &ide_noflush, 0);
++MODULE_PARM_DESC(noflush, "disable flush requests for a device");
++
++static unsigned int ide_noprobe;
++
++module_param_call(noprobe, ide_set_dev_param_mask, NULL, &ide_noprobe, 0);
++MODULE_PARM_DESC(noprobe, "skip probing for a device");
++
++static unsigned int ide_nowerr;
++
++module_param_call(nowerr, ide_set_dev_param_mask, NULL, &ide_nowerr, 0);
++MODULE_PARM_DESC(nowerr, "ignore the WRERR_STAT bit for a device");
++
++static unsigned int ide_cdroms;
++
++module_param_call(cdrom, ide_set_dev_param_mask, NULL, &ide_cdroms, 0);
++MODULE_PARM_DESC(cdrom, "force device as a CD-ROM");
++
++struct chs_geom {
++ unsigned int cyl;
++ u8 head;
++ u8 sect;
++};
++
++static unsigned int ide_disks;
++static struct chs_geom ide_disks_chs[MAX_HWIFS * MAX_DRIVES];
++
++static int ide_set_disk_chs(const char *str, struct kernel_param *kp)
++{
++ int a, b, c = 0, h = 0, s = 0, i, j = 1;
++
++ if (sscanf(str, "%d.%d:%d,%d,%d", &a, &b, &c, &h, &s) != 5 &&
++ sscanf(str, "%d.%d:%d", &a, &b, &j) != 3)
++ return -EINVAL;
++
++ i = a * MAX_DRIVES + b;
++
++ if (i >= MAX_HWIFS * MAX_DRIVES || j < 0 || j > 1)
++ return -EINVAL;
++
++ if (c > INT_MAX || h > 255 || s > 255)
++ return -EINVAL;
++
++ if (j)
++ ide_disks |= (1 << i);
++ else
++ ide_disks &= (1 << i);
++
++ ide_disks_chs[i].cyl = c;
++ ide_disks_chs[i].head = h;
++ ide_disks_chs[i].sect = s;
++
++ return 0;
++}
++
++module_param_call(chs, ide_set_disk_chs, NULL, NULL, 0);
++MODULE_PARM_DESC(chs, "force device as a disk (using CHS)");
++
++static void ide_dev_apply_params(ide_drive_t *drive)
++{
++ int i = drive->hwif->index * MAX_DRIVES + drive->select.b.unit;
++
++ if (ide_nodma & (1 << i)) {
++ printk(KERN_INFO "ide: disallowing DMA for %s\n", drive->name);
++ drive->nodma = 1;
++ }
++ if (ide_noflush & (1 << i)) {
++ printk(KERN_INFO "ide: disabling flush requests for %s\n",
++ drive->name);
++ drive->noflush = 1;
++ }
++ if (ide_noprobe & (1 << i)) {
++ printk(KERN_INFO "ide: skipping probe for %s\n", drive->name);
++ drive->noprobe = 1;
++ }
++ if (ide_nowerr & (1 << i)) {
++ printk(KERN_INFO "ide: ignoring the WRERR_STAT bit for %s\n",
++ drive->name);
++ drive->bad_wstat = BAD_R_STAT;
++ }
++ if (ide_cdroms & (1 << i)) {
++ printk(KERN_INFO "ide: forcing %s as a CD-ROM\n", drive->name);
++ drive->present = 1;
++ drive->media = ide_cdrom;
++ /* an ATAPI device ignores DRDY */
++ drive->ready_stat = 0;
++ }
++ if (ide_disks & (1 << i)) {
++ drive->cyl = drive->bios_cyl = ide_disks_chs[i].cyl;
++ drive->head = drive->bios_head = ide_disks_chs[i].head;
++ drive->sect = drive->bios_sect = ide_disks_chs[i].sect;
++ drive->forced_geom = 1;
++ printk(KERN_INFO "ide: forcing %s as a disk (%d/%d/%d)\n",
++ drive->name,
++ drive->cyl, drive->head, drive->sect);
++ drive->present = 1;
++ drive->media = ide_disk;
++ drive->ready_stat = READY_STAT;
++ }
++}
++
++static unsigned int ide_ignore_cable;
++
++static int ide_set_ignore_cable(const char *s, struct kernel_param *kp)
++{
++ int i, j = 1;
++
++ if (sscanf(s, "%d:%d", &i, &j) != 2 && sscanf(s, "%d", &i) != 1)
++ return -EINVAL;
++
++ if (i >= MAX_HWIFS || j < 0 || j > 1)
++ return -EINVAL;
++
++ if (j)
++ ide_ignore_cable |= (1 << i);
++ else
++ ide_ignore_cable &= (1 << i);
++
++ return 0;
++}
++
++module_param_call(ignore_cable, ide_set_ignore_cable, NULL, NULL, 0);
++MODULE_PARM_DESC(ignore_cable, "ignore cable detection");
++
++void ide_port_apply_params(ide_hwif_t *hwif)
++{
++ int i;
++
++ if (ide_ignore_cable & (1 << hwif->index)) {
++ printk(KERN_INFO "ide: ignoring cable detection for %s\n",
++ hwif->name);
++ hwif->cbl = ATA_CBL_PATA40_SHORT;
++ }
++
++ for (i = 0; i < MAX_DRIVES; i++)
++ ide_dev_apply_params(&hwif->drives[i]);
++}
++
+ /*
+ * This is gets invoked once during initialization, to set *everything* up
+ */
+@@ -1621,11 +1300,23 @@ static int __init ide_init(void)
+ return ret;
+ }
-+#ifdef CONFIG_PM
- static int cmd640_reinit_one(struct pci_dev *pdev)
- {
-+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
-+ int rc;
++ 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;
+
-+ 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
+ init_ide_data();
- 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
- };
+ proc_ide_create();
- 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)
+ return 0;
++
++out_port_class:
++ bus_unregister(&ide_bus_type);
++
++ return ret;
}
- 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),
- };
+ #ifdef MODULE
+@@ -1655,13 +1346,10 @@ int __init init_module (void)
--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,
+ void __exit cleanup_module (void)
+ {
+- int index;
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- for (index = 0; index < MAX_HWIFS; ++index)
+- ide_unregister(index, 0, 0);
-
-- .port_start = ata_port_start,
- };
+ proc_ide_destroy();
--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,
-+};
++ class_destroy(ide_port_class);
++
+ bus_unregister(&ide_bus_type);
+ }
-- .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,
- };
+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
- 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,
- };
+ 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..90c65cf 100644
+--- a/drivers/ide/legacy/ali14xx.c
++++ b/drivers/ide/legacy/ali14xx.c
+@@ -49,6 +49,8 @@
- 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)
+ #include <asm/io.h>
- 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;
++#define DRV_NAME "ali14xx"
+
-+ rc = pcim_enable_device(pdev);
-+ if (rc)
-+ return rc;
+ /* port addresses for auto-detection */
+ #define ALI_NUM_PORTS 4
+ static const int ports[ALI_NUM_PORTS] __initdata =
+@@ -86,7 +88,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 +97,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);
+@@ -114,7 +116,7 @@ static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ int time1, time2;
+ u8 param1, param2, param3, param4;
+ unsigned long flags;
+- int bus_speed = system_bus_clock();
++ int bus_speed = ide_vlb_clk ? ide_vlb_clk : system_bus_clock();
- pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev);
- class_rev &= 0xFF;
+ /* calculate timing, according to PIO mode */
+ time1 = ide_pio_cycle_time(drive, pio);
+@@ -143,7 +145,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 +177,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;
+@@ -191,16 +194,20 @@ static int __init initRegisters (void) {
+ return t;
+ }
- if (id->driver_data == 0) /* 643 */
-- ata_pci_clear_simplex(pdev);
-+ ata_pci_bmdma_clear_simplex(pdev);
++static const struct ide_port_ops ali14xx_port_ops = {
++ .set_pio_mode = ali14xx_set_pio_mode,
++};
++
+ static const struct ide_port_info ali14xx_port_info = {
++ .name = DRV_NAME,
+ .chipset = ide_ali14xx,
+- .host_flags = IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE,
++ .port_ops = &ali14xx_port_ops,
++ .host_flags = IDE_HFLAG_NO_DMA,
+ .pio_mask = ATA_PIO4,
+ };
- 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
+ static int __init ali14xx_probe(void)
+ {
+- static u8 idx[4] = { 0, 1, 0xff, 0xff };
+-
+ printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n",
+ basePort, regOn);
-- return ata_pci_init_one(pdev, ppi);
-+ return ata_pci_sff_init_one(pdev, ppi, &cmd64x_sht, NULL);
+@@ -210,15 +217,10 @@ 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;
+-
+- ide_device_add(idx, &ali14xx_port_info);
+-
+- return 0;
++ return ide_legacy_device_add(&ali14xx_port_info, 0);
}
- #ifdef CONFIG_PM
- static int cmd64x_reinit_one(struct pci_dev *pdev)
+-int probe_ali14xx = 0;
++static 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..5c730e4 100644
+--- a/drivers/ide/legacy/buddha.c
++++ b/drivers/ide/legacy/buddha.c
+@@ -102,7 +102,7 @@ static int buddha_ack_intr(ide_hwif_t *hwif)
{
-+ 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
+ unsigned char ch;
-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)
- }
+- ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
++ ch = z_readb(hwif->io_ports.irq_addr);
+ if (!(ch & 0x80))
+ return 0;
+ return 1;
+@@ -112,9 +112,9 @@ static int xsurf_ack_intr(ide_hwif_t *hwif)
+ {
+ unsigned char ch;
- 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,
- };
+- ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
++ ch = z_readb(hwif->io_ports.irq_addr);
+ /* X-Surf needs a 0 written to IRQ register to ensure ISA bit A11 stays at 0 */
+- z_writeb(0, hwif->io_ports[IDE_IRQ_OFFSET]);
++ z_writeb(0, hwif->io_ports.irq_addr);
+ if (!(ch & 0x80))
+ return 0;
+ return 1;
+@@ -128,13 +128,13 @@ static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base,
- 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,
- };
+ memset(hw, 0, sizeof(*hw));
- 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;
+- hw->io_ports[IDE_DATA_OFFSET] = base;
++ hw->io_ports.data_addr = base;
-+ rc = pcim_enable_device(pdev);
-+ if (rc)
-+ return rc;
-+
- /* IDE port enable bits */
- pci_read_config_byte(pdev, 0x60, &pcicfg);
+ for (i = 1; i < 8; i++)
+- hw->io_ports[i] = base + 2 + i * 4;
++ hw->io_ports_array[i] = base + 2 + i * 4;
-@@ -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);
+- hw->io_ports[IDE_CONTROL_OFFSET] = ctl;
+- hw->io_ports[IDE_IRQ_OFFSET] = irq_port;
++ hw->io_ports.ctl_addr = ctl;
++ hw->io_ports.irq_addr = irq_port;
- 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);
+ hw->irq = IRQ_AMIGA_PORTS;
+ hw->ack_intr = ack_intr;
+@@ -221,15 +221,13 @@ fail_base2:
- 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;
+ buddha_setup_ports(&hw, base, ctl, irq_port, ack_intr);
- 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;
+- hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++ hwif = ide_find_port();
+ if (hwif) {
+ u8 index = hwif->index;
-@@ -310,11 +279,20 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+ ide_init_port_data(hwif, index);
+ ide_init_port_hw(hwif, &hw);
- 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;
- }
+- hwif->mmio = 1;
+-
+ idx[i] = index;
+ }
+ }
+diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c
+index 73396f7..af791a0 100644
+--- a/drivers/ide/legacy/dtc2278.c
++++ b/drivers/ide/legacy/dtc2278.c
+@@ -16,6 +16,8 @@
- /**
-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)
- }
+ #include <asm/io.h>
- /**
-- * 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.
++#define DRV_NAME "dtc2278"
++
+ /*
+ * Changing this #undef to #define may solve start up problems in some systems.
*/
-
--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);
+@@ -86,29 +88,26 @@ static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio)
}
-
-- 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 const struct ide_port_ops dtc2278_port_ops = {
++ .set_pio_mode = dtc2278_set_pio_mode,
++};
++
+ static const struct ide_port_info dtc2278_port_info __initdata = {
++ .name = DRV_NAME,
+ .chipset = ide_dtc2278,
++ .port_ops = &dtc2278_port_ops,
+ .host_flags = IDE_HFLAG_SERIALIZE |
+ IDE_HFLAG_NO_UNMASK_IRQS |
+ IDE_HFLAG_IO_32BIT |
+ /* disallow ->io_32bit changes */
+ IDE_HFLAG_NO_IO_32BIT |
+- IDE_HFLAG_NO_DMA |
+- IDE_HFLAG_NO_AUTOTUNE,
++ IDE_HFLAG_NO_DMA,
+ .pio_mask = ATA_PIO4,
};
- 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,
+ static int __init dtc2278_probe(void)
+ {
+ unsigned long flags;
+- ide_hwif_t *hwif, *mate;
+- static u8 idx[4] = { 0, 1, 0xff, 0xff };
-
-- .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,
+- hwif = &ide_hwifs[0];
+- mate = &ide_hwifs[1];
-
-- .qc_prep = ata_dumb_qc_prep,
-- .qc_issue = cs5530_qc_issue_prot,
-+ .inherits = &ata_bmdma_port_ops,
+- if (hwif->chipset != ide_unknown || mate->chipset != ide_unknown)
+- return 1;
-- .data_xfer = ata_data_xfer,
-+ .qc_prep = ata_sff_dumb_qc_prep,
-+ .qc_issue = cs5530_qc_issue,
+ local_irq_save(flags);
+ /*
+@@ -128,14 +127,10 @@ static int __init dtc2278_probe(void)
+ #endif
+ local_irq_restore(flags);
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- hwif->set_pio_mode = &dtc2278_set_pio_mode;
-
-- .port_start = ata_sff_port_start,
-+ .cable_detect = ata_cable_40wire,
-+ .set_piomode = cs5530_set_piomode,
-+ .set_dmamode = cs5530_set_dmamode,
- };
+- ide_device_add(idx, &dtc2278_port_info);
+-
+- return 0;
++ return ide_legacy_device_add(&dtc2278_port_info, 0);
+ }
- 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;
+-int probe_dtc2278 = 0;
++static int probe_dtc2278;
- /* 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;
+ module_param_named(probe, probe_dtc2278, bool, 0);
+ MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets");
+diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
+index e950afa..83555ca 100644
+--- a/drivers/ide/legacy/falconide.c
++++ b/drivers/ide/legacy/falconide.c
+@@ -22,6 +22,7 @@
+ #include <asm/atariints.h>
+ #include <asm/atari_stdma.h>
- /* Now kick off ATA set up */
-- return ata_pci_init_one(pdev, ppi);
-+ return ata_pci_sff_init_one(pdev, ppi, &cs5530_sht, NULL);
- }
++#define DRV_NAME "falconide"
- #ifdef CONFIG_PM
- static int cs5530_reinit_one(struct pci_dev *pdev)
- {
-+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
-+ int rc;
+ /*
+ * Base of the IDE interface
+@@ -43,18 +44,40 @@
+ int falconide_intr_lock;
+ EXPORT_SYMBOL(falconide_intr_lock);
+
++static void falconide_input_data(ide_drive_t *drive, struct request *rq,
++ void *buf, unsigned int len)
++{
++ unsigned long data_addr = drive->hwif->io_ports.data_addr;
+
-+ rc = ata_pci_device_do_resume(pdev);
-+ if (rc)
-+ return rc;
++ if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
++ return insw(data_addr, buf, (len + 1) / 2);
+
- /* If we fail on resume we are doomed */
- if (cs5530_init_chip())
-- BUG();
-- return ata_pci_device_resume(pdev);
-+ return -EIO;
++ insw_swapw(data_addr, buf, (len + 1) / 2);
++}
+
-+ ata_host_resume(host);
-+ return 0;
- }
- #endif /* CONFIG_PM */
++static void falconide_output_data(ide_drive_t *drive, struct request *rq,
++ void *buf, unsigned int len)
++{
++ unsigned long data_addr = drive->hwif->io_ports.data_addr;
++
++ if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
++ return outsw(data_adr, buf, (len + 1) / 2);
++
++ outsw_swapw(data_addr, buf, (len + 1) / 2);
++}
++
+ static void __init falconide_setup_ports(hw_regs_t *hw)
+ {
+ int i;
-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)
- }
+ memset(hw, 0, sizeof(*hw));
- 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),
- };
+- hw->io_ports[IDE_DATA_OFFSET] = ATA_HD_BASE;
++ hw->io_ports.data_addr = ATA_HD_BASE;
- 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,
- };
+ for (i = 1; i < 8; i++)
+- hw->io_ports[i] = ATA_HD_BASE + 1 + i * 4;
++ hw->io_ports_array[i] = ATA_HD_BASE + 1 + i * 4;
- /**
-@@ -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);
- }
+- hw->io_ports[IDE_CONTROL_OFFSET] = ATA_HD_BASE + ATA_HD_CONTROL;
++ hw->io_ports.ctl_addr = ATA_HD_BASE + ATA_HD_CONTROL;
- 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)
- }
+ hw->irq = IRQ_MFP_IDE;
+ hw->ack_intr = NULL;
+@@ -74,9 +97,14 @@ static int __init falconide_init(void)
- 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),
- };
+ printk(KERN_INFO "ide: Falcon IDE controller\n");
- 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,
- };
++ 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);
- /**
-@@ -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)
+- 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 };
+@@ -84,6 +112,10 @@ static int __init falconide_init(void)
+ ide_init_port_data(hwif, index);
+ ide_init_port_hw(hwif, &hw);
+
++ /* Atari has a byte-swapped IDE interface */
++ hwif->input_data = falconide_input_data;
++ hwif->output_data = falconide_output_data;
++
+ ide_get_lock(NULL, NULL);
+ ide_device_add(idx, NULL);
+ ide_release_lock();
+diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
+index e3b4638..a9c2593 100644
+--- a/drivers/ide/legacy/gayle.c
++++ b/drivers/ide/legacy/gayle.c
+@@ -63,6 +63,8 @@
+ #define GAYLE_HAS_CONTROL_REG (!ide_doubler)
+ #define GAYLE_IDEREG_SIZE (ide_doubler ? 0x1000 : 0x2000)
+ int ide_doubler = 0; /* support IDE doublers? */
++module_param_named(doubler, ide_doubler, bool, 0);
++MODULE_PARM_DESC(doubler, "enable support for IDE doublers");
+ #endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+
+
+@@ -74,7 +76,7 @@ static int gayle_ack_intr_a4000(ide_hwif_t *hwif)
+ {
+ unsigned char ch;
+
+- ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
++ ch = z_readb(hwif->io_ports.irq_addr);
+ if (!(ch & GAYLE_IRQ_IDE))
+ return 0;
+ return 1;
+@@ -84,11 +86,11 @@ static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
{
- 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;
- }
+ unsigned char ch;
-- return ata_pci_init_one(dev, ppi);
-+ return ata_pci_sff_init_one(dev, ppi, &cs5536_sht, NULL);
+- ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
++ ch = z_readb(hwif->io_ports.irq_addr);
+ if (!(ch & GAYLE_IRQ_IDE))
+ return 0;
+- (void)z_readb(hwif->io_ports[IDE_STATUS_OFFSET]);
+- z_writeb(0x7c, hwif->io_ports[IDE_IRQ_OFFSET]);
++ (void)z_readb(hwif->io_ports.status_addr);
++ z_writeb(0x7c, hwif->io_ports.irq_addr);
+ return 1;
}
- 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)
- }
+@@ -100,13 +102,13 @@ static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base,
- 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),
- };
+ memset(hw, 0, sizeof(*hw));
- 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,
- };
+- hw->io_ports[IDE_DATA_OFFSET] = base;
++ hw->io_ports.data_addr = base;
- 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;
+ for (i = 1; i < 8; i++)
+- hw->io_ports[i] = base + 2 + i * 4;
++ hw->io_ports_array[i] = base + 2 + i * 4;
-- return ata_pci_init_one(pdev, ppi);
-+ return ata_pci_sff_init_one(pdev, ppi, &cy82c693_sht, NULL);
- }
+- hw->io_ports[IDE_CONTROL_OFFSET] = ctl;
+- hw->io_ports[IDE_IRQ_OFFSET] = irq_port;
++ hw->io_ports.ctl_addr = ctl;
++ hw->io_ports.irq_addr = irq_port;
- 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;
+ hw->irq = IRQ_AMIGA_PORTS;
+ hw->ack_intr = ack_intr;
+@@ -175,15 +177,13 @@ found:
-- 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);
- }
+ gayle_setup_ports(&hw, base, ctrlport, irqport, ack_intr);
- /**
-@@ -233,53 +220,15 @@ static void efar_set_dmamode (struct ata_port *ap, struct ata_device *adev)
- }
+- hwif = ide_find_port(base);
++ hwif = ide_find_port();
+ if (hwif) {
+ u8 index = hwif->index;
- 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),
- };
+ ide_init_port_data(hwif, index);
+ ide_init_port_hw(hwif, &hw);
--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,
+- hwif->mmio = 1;
-
-- .port_start = ata_sff_port_start,
-+ .prereset = efar_pre_reset,
+ idx[i] = index;
+ } else
+ release_mem_region(res_start, res_n);
+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;
+ }
-@@ -301,7 +250,6 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+-static void dump_status (const char *msg, unsigned int stat)
++static void dump_status(const char *msg, unsigned int stat)
{
- 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);
+ char *name = "hd?";
+ if (CURRENT)
+@@ -291,7 +291,6 @@ static int controller_ready(unsigned int drive, unsigned int head)
+ return 0;
}
- 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);
+-
+ 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;
}
-- 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)
+ 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 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),
- };
+ static void hd_request (void);
+@@ -344,14 +343,14 @@ static void reset_controller(void)
+ {
+ int i;
- /*
-@@ -312,37 +298,11 @@ static struct scsi_host_template hpt36x_sht = {
- */
+- 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 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,
- };
+ 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);
- /**
-@@ -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)
+ 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)
{
- 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;
+ 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 9:
-- info.private_data = &hpt366_25;
-+ hpriv = &hpt366_25;
+ 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:
-- 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;
+ printk("unknown hd-command\n");
+@@ -655,7 +656,7 @@ repeat:
+ }
}
- #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);
+-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;
}
-- 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);
+@@ -742,7 +743,7 @@ static int __init hd_init(void)
+ goto out;
}
-- 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);
+- 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)
+ }
-- return ata_std_prereset(link, deadline);
-+ return ata_sff_prereset(link, deadline);
+ /* 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;
}
--/**
-- * 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 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..4fe516d 100644
+--- a/drivers/ide/legacy/ht6560b.c
++++ b/drivers/ide/legacy/ht6560b.c
+@@ -35,6 +35,7 @@
+ * Try: http://www.maf.iki.fi/~maf/ht6560b/
+ */
+
++#define DRV_NAME "ht6560b"
+ #define HT6560B_VERSION "v0.08"
+
+ #include <linux/module.h>
+@@ -82,7 +83,7 @@
+ * out how they setup those cycle time interfacing values, as they at Holtek
+ * call them. IDESETUP.COM that is supplied with the drivers figures out
+ * optimal values and fetches those values to drivers. I found out that
+- * they use IDE_SELECT_REG to fetch timings to the ide board right after
++ * they use Select register to fetch timings to the ide board right after
+ * interface switching. After that it was quite easy to add code to
+ * ht6560b.c.
+ *
+@@ -127,6 +128,7 @@
+ */
+ static void ht6560b_selectproc (ide_drive_t *drive)
{
- 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);
++ 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.device_addr);
++ (void)inb(hwif->io_ports.status_addr);
+ #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
+@@ -210,8 +212,8 @@ static u8 ht_pio2timings(ide_drive_t *drive, const u8 pio)
+ {
+ int active_time, recovery_time;
+ int active_cycles, recovery_cycles;
+- int bus_speed = system_bus_clock();
+-
++ int bus_speed = ide_vlb_clk ? ide_vlb_clk : system_bus_clock();
++
+ if (pio) {
+ unsigned int cycle_time;
-- 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);
+@@ -321,54 +323,44 @@ static void __init ht6560b_port_init_devs(ide_hwif_t *hwif)
+ hwif->drives[1].drive_data = t;
}
- /**
-@@ -619,21 +588,7 @@ static void hpt37x_bmdma_stop(struct ata_queued_cmd *qc)
+-int probe_ht6560b = 0;
++static int probe_ht6560b;
+ module_param_named(probe, probe_ht6560b, bool, 0);
+ MODULE_PARM_DESC(probe, "probe for HT6560B chipset");
- 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),
++static const struct ide_port_ops ht6560b_port_ops = {
++ .port_init_devs = ht6560b_port_init_devs,
++ .set_pio_mode = ht6560b_set_pio_mode,
++ .selectproc = ht6560b_selectproc,
++};
++
+ static const struct ide_port_info ht6560b_port_info __initdata = {
++ .name = DRV_NAME,
+ .chipset = ide_ht6560b,
++ .port_ops = &ht6560b_port_ops,
+ .host_flags = IDE_HFLAG_SERIALIZE | /* is this needed? */
+ IDE_HFLAG_NO_DMA |
+- IDE_HFLAG_NO_AUTOTUNE |
+ IDE_HFLAG_ABUSE_PREFETCH,
+ .pio_mask = ATA_PIO4,
};
- /*
-@@ -641,36 +596,15 @@ static struct scsi_host_template hpt37x_sht = {
- */
+ static int __init ht6560b_init(void)
+ {
+- ide_hwif_t *hwif, *mate;
+- static u8 idx[4] = { 0, 1, 0xff, 0xff };
+-
+ if (probe_ht6560b == 0)
+ return -ENODEV;
- static struct ata_port_operations hpt370_port_ops = {
-- .set_piomode = hpt370_set_piomode,
-- .set_dmamode = hpt370_set_dmamode,
-- .mode_filter = hpt370_filter,
+- hwif = &ide_hwifs[0];
+- mate = &ide_hwifs[1];
-
-- .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,
+- 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__);
++ __func__);
+ return -ENODEV;
+ }
-- .freeze = ata_bmdma_freeze,
-- .thaw = ata_bmdma_thaw,
-- .error_handler = hpt37x_error_handler,
-- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+ if (!try_to_init_ht6560b()) {
+- printk(KERN_NOTICE "%s: HBA not found\n", __FUNCTION__);
++ printk(KERN_NOTICE "%s: HBA not found\n", __func__);
+ goto release_region;
+ }
+
+- hwif->selectproc = &ht6560b_selectproc;
+- hwif->set_pio_mode = &ht6560b_set_pio_mode;
-
-- .bmdma_setup = ata_bmdma_setup,
- .bmdma_start = hpt370_bmdma_start,
- .bmdma_stop = hpt370_bmdma_stop,
-- .bmdma_status = ata_bmdma_status,
+- mate->selectproc = &ht6560b_selectproc;
+- mate->set_pio_mode = &ht6560b_set_pio_mode;
-
-- .qc_prep = ata_qc_prep,
-- .qc_issue = ata_qc_issue_prot,
+- hwif->port_init_devs = ht6560b_port_init_devs;
+- mate->port_init_devs = ht6560b_port_init_devs;
-
-- .data_xfer = ata_data_xfer,
+- ide_device_add(idx, &ht6560b_port_info);
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- return 0;
++ return ide_legacy_device_add(&ht6560b_port_info, 0);
-- .port_start = ata_sff_port_start,
-+ .mode_filter = hpt370_filter,
-+ .set_piomode = hpt370_set_piomode,
-+ .set_dmamode = hpt370_set_dmamode,
-+ .prereset = hpt37x_pre_reset,
- };
+ release_region:
+ release_region(HT_CONFIG_PORT, 1);
+diff --git a/drivers/ide/legacy/ide-4drives.c b/drivers/ide/legacy/ide-4drives.c
+new file mode 100644
+index 0000000..ecae916
+--- /dev/null
++++ b/drivers/ide/legacy/ide-4drives.c
+@@ -0,0 +1,72 @@
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/ide.h>
++
++#define DRV_NAME "ide-4drives"
++
++static 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;
++ unsigned long base = 0x1f0, ctl = 0x3f6;
++ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++ hw_regs_t hw;
++
++ if (probe_4drives == 0)
++ return -ENODEV;
++
++ if (!request_region(base, 8, DRV_NAME)) {
++ printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
++ DRV_NAME, base, base + 7);
++ return -EBUSY;
++ }
++
++ if (!request_region(ctl, 1, DRV_NAME)) {
++ printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
++ DRV_NAME, ctl);
++ release_region(base, 8);
++ return -EBUSY;
++ }
++
++ memset(&hw, 0, sizeof(hw));
++
++ ide_std_init_ports(&hw, base, ctl);
++ 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..aa2ea3d 100644
+--- a/drivers/ide/legacy/ide-cs.c
++++ b/drivers/ide/legacy/ide-cs.c
+@@ -51,6 +51,8 @@
+ #include <pcmcia/cisreg.h>
+ #include <pcmcia/ciscode.h>
- /*
-@@ -678,36 +612,8 @@ static struct ata_port_operations hpt370_port_ops = {
- */
++#define DRV_NAME "ide-cs"
++
+ /*====================================================================*/
- 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,
- };
+ /* Module parameters */
+@@ -72,16 +74,11 @@ static char *version =
- /*
-@@ -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,
+-static const char ide_major[] = {
+- IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR,
+- IDE4_MAJOR, IDE5_MAJOR
+-};
-
-- .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,
+ typedef struct ide_info_t {
+ struct pcmcia_device *p_dev;
++ ide_hwif_t *hwif;
+ int ndev;
+ dev_node_t node;
+- int hd;
+ } ide_info_t;
-- .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,
+ static void ide_release(struct pcmcia_device *);
+@@ -136,45 +133,71 @@ static int ide_probe(struct pcmcia_device *link)
-- .port_start = ata_sff_port_start,
-+ .set_piomode = hpt372_set_piomode,
-+ .set_dmamode = hpt372_set_dmamode,
-+ .prereset = hpt37x_pre_reset,
- };
+ static void ide_detach(struct pcmcia_device *link)
+ {
++ ide_info_t *info = link->priv;
++ ide_hwif_t *hwif = info->hwif;
++
+ DEBUG(0, "ide_detach(0x%p)\n", link);
- /*
- * 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.
- */
+ ide_release(link);
--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,
- };
+- kfree(link->priv);
++ release_region(hwif->io_ports.ctl_addr, 1);
++ release_region(hwif->io_ports.data_addr, 8);
++
++ kfree(info);
+ } /* ide_detach */
- /**
-@@ -897,7 +752,6 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+-static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle)
++static const struct ide_port_ops idecs_port_ops = {
++ .quirkproc = ide_undecoded_slave,
++};
++
++static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl,
++ unsigned long irq, struct pcmcia_device *handle)
{
- /* 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
- };
+ ide_hwif_t *hwif;
+ hw_regs_t hw;
+ int i;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- 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 };
++ if (!request_region(io, 8, DRV_NAME)) {
++ printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
++ DRV_NAME, io, io + 7);
++ return NULL;
++ }
++
++ if (!request_region(ctl, 1, DRV_NAME)) {
++ printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
++ DRV_NAME, ctl);
++ release_region(io, 8);
++ return NULL;
++ }
++
+ memset(&hw, 0, sizeof(hw));
+ ide_std_init_ports(&hw, io, ctl);
+ hw.irq = irq;
+ hw.chipset = ide_pci;
+ hw.dev = &handle->dev;
- u8 irqmask;
- u32 class_rev;
-@@ -966,6 +820,11 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+- hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++ hwif = ide_find_port();
+ if (hwif == NULL)
+- return -1;
++ goto out_release;
- const struct hpt_chip *chip_table;
- int clock_slot;
-+ int rc;
+ i = hwif->index;
+
+- if (hwif->present)
+- ide_unregister(i, 0, 0);
+- else if (!hwif->hold)
+- ide_init_port_data(hwif, i);
+-
++ ide_init_port_data(hwif, i);
+ ide_init_port_hw(hwif, &hw);
+- hwif->quirkproc = &ide_undecoded_slave;
++ hwif->port_ops = &idecs_port_ops;
+
+ idx[0] = i;
+
+ ide_device_add(idx, NULL);
+
+- return hwif->present ? i : -1;
++ if (hwif->present)
++ return hwif;
+
-+ rc = pcim_enable_device(dev);
-+ if (rc)
-+ return rc;
++out_release:
++ release_region(ctl, 1);
++ release_region(io, 8);
++ return NULL;
+ }
+
+ /*======================================================================
+@@ -199,8 +222,9 @@ static int ide_config(struct pcmcia_device *link)
+ cistpl_cftable_entry_t dflt;
+ } *stk = NULL;
+ cistpl_cftable_entry_t *cfg;
+- int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0;
++ int i, pass, last_ret = 0, last_fn = 0, is_kme = 0;
+ unsigned long io_base, ctl_base;
++ ide_hwif_t *hwif;
+
+ DEBUG(0, "ide_config(0x%p)\n", link);
+
+@@ -296,14 +320,15 @@ static int ide_config(struct pcmcia_device *link)
+ outb(0x81, ctl_base+1);
+
+ /* retry registration in case device is still spinning up */
+- for (hd = -1, i = 0; i < 10; i++) {
+- hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
+- if (hd >= 0) break;
++ for (i = 0; i < 10; i++) {
++ hwif = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
++ if (hwif)
++ break;
+ if (link->io.NumPorts1 == 0x20) {
+ outb(0x02, ctl_base + 0x10);
+- hd = idecs_register(io_base + 0x10, ctl_base + 0x10,
+- link->irq.AssignedIRQ, link);
+- if (hd >= 0) {
++ hwif = idecs_register(io_base + 0x10, ctl_base + 0x10,
++ link->irq.AssignedIRQ, link);
++ if (hwif) {
+ io_base += 0x10;
+ ctl_base += 0x10;
+ break;
+@@ -312,7 +337,7 @@ static int ide_config(struct pcmcia_device *link)
+ msleep(100);
+ }
- 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)
+- if (hd < 0) {
++ if (hwif == NULL) {
+ printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx"
+ ", irq %u failed\n", io_base, ctl_base,
+ link->irq.AssignedIRQ);
+@@ -320,10 +345,10 @@ static int ide_config(struct pcmcia_device *link)
+ }
- 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;
+ info->ndev = 1;
+- sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2));
+- info->node.major = ide_major[hd];
++ sprintf(info->node.dev_name, "hd%c", 'a' + hwif->index * 2);
++ info->node.major = hwif->major;
+ info->node.minor = 0;
+- info->hd = hd;
++ info->hwif = hwif;
+ link->dev_node = &info->node;
+ printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
+ info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
+@@ -354,13 +379,14 @@ failed:
+ void ide_release(struct pcmcia_device *link)
+ {
+ ide_info_t *info = link->priv;
++ ide_hwif_t *hwif = info->hwif;
- /* Compute DPLL */
-- dpll = (port->udma_mask & 0xC0) ? 3 : 2;
-+ dpll = (ppi[0]->udma_mask & 0xC0) ? 3 : 2;
+ DEBUG(0, "ide_release(0x%p)\n", link);
- 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 (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(hwif);
+ }
+ info->ndev = 0;
-- 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]);
+diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c
+index 688fcae..d3bc3f2 100644
+--- a/drivers/ide/legacy/ide_platform.c
++++ b/drivers/ide/legacy/ide_platform.c
+@@ -30,14 +30,14 @@ static void __devinit plat_ide_setup_ports(hw_regs_t *hw,
+ unsigned long port = (unsigned long)base;
+ int i;
+
+- hw->io_ports[IDE_DATA_OFFSET] = port;
++ hw->io_ports.data_addr = port;
+
+ port += (1 << pdata->ioport_shift);
+- for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET;
++ for (i = 1; i <= 7;
+ i++, port += (1 << pdata->ioport_shift))
+- hw->io_ports[i] = port;
++ hw->io_ports_array[i] = port;
+
+- hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
++ hw->io_ports.ctl_addr = (unsigned long)ctrl;
+
+ hw->irq = irq;
+
+@@ -89,7 +89,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
+ res_alt->start, res_alt->end - res_alt->start + 1);
}
- /* 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);
- }
+- hwif = ide_find_port((unsigned long)base);
++ hwif = ide_find_port();
+ if (!hwif) {
+ ret = -ENODEV;
+ goto out;
+@@ -102,7 +102,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
+ ide_init_port_hw(hwif, &hw);
- 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,
- */
+ if (mmio) {
+- hwif->mmio = 1;
++ hwif->host_flags = IDE_HFLAG_MMIO;
+ default_hwif_mmiops(hwif);
+ }
--static int hpt3xn_pre_reset(struct ata_link *link, unsigned long deadline)
-+static int hpt3x2n_pre_reset(struct ata_link *link, unsigned long deadline)
+@@ -122,7 +122,7 @@ static int __devexit plat_ide_remove(struct platform_device *pdev)
{
- 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);
+ ide_hwif_t *hwif = pdev->dev.driver_data;
-- 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);
- }
+- ide_unregister(hwif->index, 0, 0);
++ ide_unregister(hwif);
- /**
-@@ -320,7 +308,7 @@ static int hpt3x2n_use_dpll(struct ata_port *ap, int writing)
return 0;
}
+@@ -130,6 +130,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 +148,7 @@ static void __exit platform_ide_exit(void)
--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);
- }
+ 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..1f527bb 100644
+--- a/drivers/ide/legacy/macide.c
++++ b/drivers/ide/legacy/macide.c
+@@ -72,9 +72,9 @@ static void __init macide_setup_ports(hw_regs_t *hw, unsigned long base,
+ memset(hw, 0, sizeof(*hw));
+
+ for (i = 0; i < 8; i++)
+- hw->io_ports[i] = base + i * 4;
++ hw->io_ports_array[i] = base + i * 4;
+
+- hw->io_ports[IDE_CONTROL_OFFSET] = base + IDE_CONTROL;
++ hw->io_ports.ctl_addr = base + IDE_CONTROL;
+
+ hw->irq = irq;
+ hw->ack_intr = ack_intr;
+@@ -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 };
+@@ -128,8 +128,6 @@ static int __init macide_init(void)
+ ide_init_port_data(hwif, index);
+ ide_init_port_hw(hwif, &hw);
+
+- hwif->mmio = 1;
+-
+ ide_device_add(idx, NULL);
}
-- 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),
+diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
+index 2da2875..6f535d0 100644
+--- a/drivers/ide/legacy/q40ide.c
++++ b/drivers/ide/legacy/q40ide.c
+@@ -36,23 +36,6 @@ static const unsigned long pcide_bases[Q40IDE_NUM_HWIFS] = {
+ PCIDE_BASE6 */
};
- /*
-@@ -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,
+- /*
+- * Offsets from one of the above bases
+- */
-
-- .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,
+-/* used to do addr translation here but it is easier to do in setup ports */
+-/*#define IDE_OFF_B(x) ((unsigned long)Q40_ISA_IO_B((IDE_##x##_OFFSET)))*/
-
-- .qc_prep = ata_qc_prep,
-- .qc_issue = hpt3x2n_qc_issue_prot,
+-#define IDE_OFF_B(x) ((unsigned long)((IDE_##x##_OFFSET)))
+-#define IDE_OFF_W(x) ((unsigned long)((IDE_##x##_OFFSET)))
-
-- .data_xfer = ata_data_xfer,
+-static const int pcide_offsets[IDE_NR_PORTS] = {
+- IDE_OFF_W(DATA), IDE_OFF_B(ERROR), IDE_OFF_B(NSECTOR), IDE_OFF_B(SECTOR),
+- IDE_OFF_B(LCYL), IDE_OFF_B(HCYL), 6 /*IDE_OFF_B(CURRENT)*/, IDE_OFF_B(STATUS),
+- 518/*IDE_OFF(CMD)*/
+-};
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
-+ .qc_issue = hpt3x2n_qc_issue,
+ static int q40ide_default_irq(unsigned long base)
+ {
+ switch (base) {
+@@ -68,29 +51,48 @@ static int q40ide_default_irq(unsigned long base)
+ /*
+ * Addresses are pretranslated for Q40 ISA access.
+ */
+-void q40_ide_setup_ports ( hw_regs_t *hw,
+- unsigned long base, int *offsets,
+- unsigned long ctrl, unsigned long intr,
++static void q40_ide_setup_ports(hw_regs_t *hw, unsigned long base,
+ ide_ack_intr_t *ack_intr,
+ int irq)
+ {
+- int i;
+-
+ memset(hw, 0, sizeof(hw_regs_t));
+- for (i = 0; i < IDE_NR_PORTS; i++) {
+- /* BIG FAT WARNING:
+- assumption: only DATA port is ever used in 16 bit mode */
+- if ( i==0 )
+- hw->io_ports[i] = Q40_ISA_IO_W(base + offsets[i]);
+- else
+- hw->io_ports[i] = Q40_ISA_IO_B(base + offsets[i]);
+- }
++ /* BIG FAT WARNING:
++ assumption: only DATA port is ever used in 16 bit mode */
++ hw->io_ports.data_addr = Q40_ISA_IO_W(base);
++ hw->io_ports.error_addr = Q40_ISA_IO_B(base + 1);
++ hw->io_ports.nsect_addr = Q40_ISA_IO_B(base + 2);
++ hw->io_ports.lbal_addr = Q40_ISA_IO_B(base + 3);
++ hw->io_ports.lbam_addr = Q40_ISA_IO_B(base + 4);
++ hw->io_ports.lbah_addr = Q40_ISA_IO_B(base + 5);
++ hw->io_ports.device_addr = Q40_ISA_IO_B(base + 6);
++ hw->io_ports.status_addr = Q40_ISA_IO_B(base + 7);
++ hw->io_ports.ctl_addr = Q40_ISA_IO_B(base + 0x206);
-- .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,
- };
+ hw->irq = irq;
+ hw->ack_intr = ack_intr;
+ }
- /**
-@@ -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 };
++static void q40ide_input_data(ide_drive_t *drive, struct request *rq,
++ void *buf, unsigned int len)
++{
++ unsigned long data_addr = drive->hwif->io_ports.data_addr;
++
++ if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
++ return insw(data_addr, buf, (len + 1) / 2);
- 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;
++ insw_swapw(data_addr, buf, (len + 1) / 2);
++}
+
-+ rc = pcim_enable_device(dev);
-+ if (rc)
-+ return rc;
++static void q40ide_output_data(ide_drive_t *drive, struct request *rq,
++ void *buf, unsigned int len)
++{
++ unsigned long data_addr = drive->hwif->io_ports.data_addr;
++
++ if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
++ return outsw(data_addr, buf, (len + 1) / 2);
++
++ outsw_swapw(data_addr, buf, (len + 1) / 2);
++}
- 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)
+ /*
+ * the static array is needed to have the name reported in /proc/ioports,
+@@ -131,17 +133,19 @@ static int __init q40ide_init(void)
+ release_region(pcide_bases[i], 8);
+ continue;
}
+- q40_ide_setup_ports(&hw,(unsigned long) pcide_bases[i], (int *)pcide_offsets,
+- pcide_bases[i]+0x206,
+- 0, NULL,
++ q40_ide_setup_ports(&hw, pcide_bases[i],
++ NULL,
+ // m68kide_iops,
+ q40ide_default_irq(pcide_bases[i]));
- /* Now kick off ATA set up */
-- return ata_pci_init_one(dev, ppi);
-+ return ata_pci_sff_init_one(dev, ppi, &hpt3x2n_sht, hpriv);
- }
+- 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);
+- hwif->mmio = 1;
++
++ /* Q40 has a byte-swapped IDE interface */
++ hwif->input_data = q40ide_input_data;
++ hwif->output_data = q40ide_output_data;
- 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)
- }
+ idx[i] = hwif->index;
+ }
+diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c
+index 2f4f47a..6424af1 100644
+--- a/drivers/ide/legacy/qd65xx.c
++++ b/drivers/ide/legacy/qd65xx.c
+@@ -11,11 +11,7 @@
+ *
+ * QDI QD6500/QD6580 EIDE controller fast support
+ *
+- * Please set local bus speed using kernel parameter idebus
+- * for example, "idebus=33" stands for 33Mhz VLbus
+ * To activate controller support, use "ide0=qd65xx"
+- * To enable tuning, use "hda=autotune hdb=autotune"
+- * To enable 2nd channel tuning (qd6580 only), use "hdc=autotune hdd=autotune"
+ */
- 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),
- };
+ /*
+@@ -37,6 +33,8 @@
+ #include <asm/system.h>
+ #include <asm/io.h>
- 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,
- };
++#define DRV_NAME "qd65xx"
++
+ #include "qd65xx.h"
- /**
-@@ -189,7 +148,6 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ /*
+@@ -88,12 +86,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)
{
- 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;
+ u8 index = (( (QD_TIMREG(drive)) & 0x80 ) >> 7) |
+ (QD_TIMREG(drive) & 0x02);
+@@ -112,17 +110,18 @@ static void qd_select (ide_drive_t *drive)
- ata_port_pbar_desc(ap, 4, -1, "ioport");
- ata_port_pbar_desc(ap, 4, offset_cmd[i], "cmd");
+ static u8 qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time)
+ {
+- u8 active_cycle,recovery_cycle;
++ int clk = ide_vlb_clk ? ide_vlb_clk : system_bus_clock();
++ u8 act_cyc, rec_cyc;
+
+- if (system_bus_clock()<=33) {
+- active_cycle = 9 - IDE_IN(active_time * system_bus_clock() / 1000 + 1, 2, 9);
+- recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 0, 15);
++ if (clk <= 33) {
++ act_cyc = 9 - IDE_IN(active_time * clk / 1000 + 1, 2, 9);
++ rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 0, 15);
+ } else {
+- active_cycle = 8 - IDE_IN(active_time * system_bus_clock() / 1000 + 1, 1, 8);
+- recovery_cycle = 18 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 3, 18);
++ act_cyc = 8 - IDE_IN(active_time * clk / 1000 + 1, 1, 8);
++ rec_cyc = 18 - IDE_IN(recovery_time * clk / 1000 + 1, 3, 18);
}
- 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);
+- return((recovery_cycle<<4) | 0x08 | active_cycle);
++ return (rec_cyc << 4) | 0x08 | act_cyc;
}
- 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);
- }
+ /*
+@@ -133,10 +132,13 @@ static u8 qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery
- 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 u8 qd6580_compute_timing (int active_time, int recovery_time)
+ {
+- u8 active_cycle = 17 - IDE_IN(active_time * system_bus_clock() / 1000 + 1, 2, 17);
+- u8 recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 2, 15);
++ int clk = ide_vlb_clk ? ide_vlb_clk : system_bus_clock();
++ u8 act_cyc, rec_cyc;
++
++ act_cyc = 17 - IDE_IN(active_time * clk / 1000 + 1, 2, 17);
++ rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 2, 15);
+- return((recovery_cycle<<4) | active_cycle);
++ return (rec_cyc << 4) | act_cyc;
+ }
- 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,
- };
+ /*
+@@ -168,36 +170,15 @@ static int qd_find_disk_type (ide_drive_t *drive,
+ }
--/* wish this was exported from libata-core */
--static void ata_dummy_noret(struct ata_port *port)
+ /*
+- * 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 */
-}
-
- static void pata_icside_postreset(struct ata_link *link, unsigned int *classes)
+-/*
+ * 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)
{
- struct ata_port *ap = link->ap;
- struct pata_icside_state *state = ap->host->private_data;
+- 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;
- if (classes[0] != ATA_DEV_NONE || classes[1] != ATA_DEV_NONE)
-- return ata_std_postreset(link, classes);
-+ return ata_sff_postreset(link, classes);
+ printk(KERN_DEBUG "%s: %#x\n", drive->name, timing);
+ }
+@@ -225,10 +206,11 @@ static void qd6500_set_pio_mode(ide_drive_t *drive, const u8 pio)
- state->port[ap->port_no].disabled = 1;
+ 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;
-@@ -349,42 +332,20 @@ static void pata_icside_postreset(struct ata_link *link, unsigned int *classes)
- }
+ if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) {
+ cycle_time = ide_pio_cycle_time(drive, pio);
+@@ -299,21 +281,10 @@ static int __init qd_testreg(int port)
+ return (readreg != QD_TESTVAL);
}
--static void pata_icside_error_handler(struct ata_port *ap)
+-/*
+- * 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)
-{
-- ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
-- pata_icside_postreset);
+- hwif->select_data = base;
+- hwif->config_data = config;
-}
-
- 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,
+ 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 +293,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
+@@ -334,11 +306,23 @@ static void __init qd6580_port_init_devs(ide_hwif_t *hwif)
+ hwif->drives[1].drive_data = t2;
+ }
+
++static const struct ide_port_ops qd6500_port_ops = {
++ .port_init_devs = qd6500_port_init_devs,
++ .set_pio_mode = qd6500_set_pio_mode,
++ .selectproc = qd65xx_select,
++};
+
-+ .cable_detect = ata_cable_40wire,
-+ .set_dmamode = pata_icside_set_dmamode,
-+ .postreset = pata_icside_postreset,
-+ .post_internal_cmd = pata_icside_bmdma_stop,
++static const struct ide_port_ops qd6580_port_ops = {
++ .port_init_devs = qd6580_port_init_devs,
++ .set_pio_mode = qd6580_set_pio_mode,
++ .selectproc = qd65xx_select,
++};
++
+ static const struct ide_port_info qd65xx_port_info __initdata = {
++ .name = DRV_NAME,
+ .chipset = ide_qd65xx,
+ .host_flags = IDE_HFLAG_IO_32BIT |
+- IDE_HFLAG_NO_DMA |
+- IDE_HFLAG_NO_AUTOTUNE,
++ IDE_HFLAG_NO_DMA,
+ .pio_mask = ATA_PIO4,
};
- 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]);
- }
+@@ -351,55 +335,41 @@ static const struct ide_port_info qd65xx_port_info __initdata = {
-- return ata_host_activate(host, ec->irq, ata_interrupt, 0,
-+ return ata_host_activate(host, ec->irq, ata_sff_interrupt, 0,
- &pata_icside_sht);
- }
+ static int __init qd_probe(int base)
+ {
+- ide_hwif_t *hwif;
+- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+- u8 config;
+- u8 unit;
++ int rc;
++ u8 config, unit, control;
++ struct ide_port_info d = qd65xx_port_info;
-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"
+ config = inb(QD_CONFIG_PORT);
- 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),
- };
+ if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) )
+- return 1;
++ return -ENODEV;
- 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,
+ unit = ! (config & QD_CONFIG_IDE_BASEPORT);
+
+- if ((config & 0xf0) == QD_CONFIG_QD6500) {
++ if (unit)
++ d.host_flags |= IDE_HFLAG_QD_2ND_PORT;
+
+- if (qd_testreg(base)) return 1; /* bad register */
++ switch (config & 0xf0) {
++ case QD_CONFIG_QD6500:
++ if (qd_testreg(base))
++ return -ENODEV; /* bad register */
+
+- /* qd6500 found */
-
-- .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,
+- 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);
-
-- .qc_prep = ata_qc_prep,
-- .qc_issue = ata_qc_issue_prot,
+- hwif->port_init_devs = qd6500_port_init_devs;
+- hwif->set_pio_mode = &qd6500_set_pio_mode;
-
-- .data_xfer = ata_data_xfer,
+- idx[unit] = unit;
-
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- ide_device_add(idx, &qd65xx_port_info);
-
-- .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
+- return 1;
+- }
+-
+- if (((config & 0xf0) == QD_CONFIG_QD6580_A) ||
+- ((config & 0xf0) == QD_CONFIG_QD6580_B)) {
+-
+- u8 control;
+-
+- if (qd_testreg(base) || qd_testreg(base+0x02)) return 1;
+- /* bad registers */
++ printk(KERN_NOTICE "qd6500 at %#x\n", base);
++ printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n",
++ config, QD_ID3);
- if (pnp_irq_valid(idev, 0)) {
- irq = pnp_irq(idev, 0);
-- handler = ata_interrupt;
-+ handler = ata_sff_interrupt;
- }
+- /* qd6580 found */
++ d.port_ops = &qd6500_port_ops;
++ d.host_flags |= IDE_HFLAG_SINGLE;
++ break;
++ case QD_CONFIG_QD6580_A:
++ case QD_CONFIG_QD6580_B:
++ if (qd_testreg(base) || qd_testreg(base + 0x02))
++ return -ENODEV; /* bad registers */
- /* 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;
- }
+ control = inb(QD_CONTROL_PORT);
-- ata_std_ports(&ap->ioaddr);
-+ ata_sff_std_ports(&ap->ioaddr);
+@@ -409,69 +379,44 @@ static int __init qd_probe(int base)
- 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;
+ outb(QD_DEF_CONTR, QD_CONTROL_PORT);
-- return ata_std_prereset(link, deadline);
--}
+- if (control & QD_CONTR_SEC_DISABLED) {
+- /* secondary disabled */
-
--/**
-- * it8213_error_handler - Probe specified port on PATA host controller
-- * @ap: Port to probe
-- *
-- * LOCKING:
-- * None (inherited from caller).
-- */
+- hwif = &ide_hwifs[unit];
+- printk(KERN_INFO "%s: qd6580: single IDE board\n",
+- hwif->name);
-
--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),
- };
+- qd_setup(hwif, base, config | (control << 8));
+-
+- hwif->port_init_devs = qd6580_port_init_devs;
+- hwif->set_pio_mode = &qd6580_set_pio_mode;
+-
+- idx[unit] = unit;
++ d.port_ops = &qd6580_port_ops;
++ if (control & QD_CONTR_SEC_DISABLED)
++ d.host_flags |= IDE_HFLAG_SINGLE;
--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,
+- ide_device_add(idx, &qd65xx_port_info);
-
-- .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,
+- return 1;
+- } else {
+- ide_hwif_t *mate;
-
-- .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,
+- hwif = &ide_hwifs[0];
+- mate = &ide_hwifs[1];
+- /* secondary enabled */
+- printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n",
+- hwif->name, mate->name);
-
-- .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,
+- qd_setup(hwif, base, config | (control << 8));
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- hwif->port_init_devs = qd6580_port_init_devs;
+- hwif->set_pio_mode = &qd6580_set_pio_mode;
-
-- .port_start = ata_sff_port_start,
-+ .prereset = it8213_pre_reset,
- };
+- qd_setup(mate, base, config | (control << 8));
+-
+- mate->port_init_devs = qd6580_port_init_devs;
+- mate->set_pio_mode = &qd6580_set_pio_mode;
++ printk(KERN_INFO "qd6580: %s IDE board\n",
++ (control & QD_CONTR_SEC_DISABLED) ? "single" : "dual");
++ break;
++ default:
++ return -ENODEV;
++ }
+- idx[0] = 0;
+- idx[1] = 1;
++ rc = ide_legacy_device_add(&d, (base << 8) | config);
-@@ -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");
+- ide_device_add(idx, &qd65xx_port_info);
++ if (d.host_flags & IDE_HFLAG_SINGLE)
++ return (rc == 0) ? 1 : rc;
-- return ata_pci_init_one(pdev, ppi);
-+ return ata_pci_sff_init_one(pdev, ppi, &it8213_sht, NULL);
+- return 0; /* no other qd65xx possible */
+- }
+- }
+- /* no qd65xx found */
+- return 1;
++ return rc;
}
- 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);
- }
+-int probe_qd65xx = 0;
++static int probe_qd65xx;
- /**
-- * 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
- */
+ module_param_named(probe, probe_qd65xx, bool, 0);
+ MODULE_PARM_DESC(probe, "probe for QD65xx chipsets");
--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)
+ static int __init qd65xx_init(void)
{
- 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
- */
++ int rc1, rc2 = -ENODEV;
++
+ if (probe_qd65xx == 0)
+ return -ENODEV;
--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);
+- 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;
}
- /**
-@@ -632,89 +632,34 @@ static int it821x_port_start(struct ata_port *ap)
- }
+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)
- 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),
- };
+ #define QD_CONFIG(hwif) ((hwif)->config_data & 0x00ff)
+-#define QD_CONTROL(hwif) (((hwif)->config_data & 0xff00) >> 8)
- 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,
+ #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..b54a14a 100644
+--- a/drivers/ide/legacy/umc8672.c
++++ b/drivers/ide/legacy/umc8672.c
+@@ -19,7 +19,7 @@
+ */
-- .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,
+ /*
+- * 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 */
+@@ -51,6 +51,8 @@
-- .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,
+ #include <asm/io.h>
- .port_start = it821x_port_start,
- };
++#define DRV_NAME "umc8672"
++
+ /*
+ * Default speeds. These can be changed with "auto-tune" and/or hdparm.
+ */
+@@ -60,103 +62,103 @@
+ #define UMC_DRIVE3 1 /* In case of crash reduce speed */
- 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,
+ 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 */
-- .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,
+ /* 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}
++};
-- .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,
+-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);
+ }
- .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 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 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)
+-static void umc_set_speeds (u8 speeds[])
++static void umc_set_speeds(u8 speeds[])
+ {
+ int i, tmp;
- 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;
+- outb_p(0x5A,0x108); /* enable umc */
++ outb_p(0x5A, 0x108); /* enable umc */
- /* 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;
+- 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 */
-- return ata_pci_init_one(pdev, ppi);
-+ return ata_pci_sff_init_one(pdev, ppi, &it821x_sht, NULL);
+- 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]);
}
- #ifdef CONFIG_PM
- static int it821x_reinit_one(struct pci_dev *pdev)
+ static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
-+ 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
++ ide_hwif_t *hwif = drive->hwif;
+ unsigned long flags;
+- ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup;
-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,
+ 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);
}
- 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 const struct ide_port_ops umc8672_port_ops = {
++ .set_pio_mode = umc_set_pio_mode,
++};
++
+ static const struct ide_port_info umc8672_port_info __initdata = {
++ .name = DRV_NAME,
+ .chipset = ide_umc8672,
+- .host_flags = IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE,
++ .port_ops = &umc8672_port_ops,
++ .host_flags = IDE_HFLAG_NO_DMA,
+ .pio_mask = ATA_PIO4,
};
- 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,
+ static int __init umc8672_probe(void)
+ {
+ unsigned long flags;
+- static u8 idx[4] = { 0, 1, 0xff, 0xff };
+
+ 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;
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- ide_device_add(idx, &umc8672_port_info);
-
-- .port_start = ata_port_start,
-+ .set_mode = ixp4xx_set_mode,
- };
+- return 0;
++ return ide_legacy_device_add(&umc8672_port_info, 0);
+ }
- 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;
+-int probe_umc8672 = 0;
++static int probe_umc8672;
-- ata_std_ports(ioaddr);
-+ ata_sff_std_ports(ioaddr);
+ 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..1a6c27b 100644
+--- a/drivers/ide/mips/au1xxx-ide.c
++++ b/drivers/ide/mips/au1xxx-ide.c
+@@ -47,9 +47,6 @@
+ #define IDE_AU1XXX_BURSTMODE 1
- #ifndef __ARMEB__
+ static _auide_hwif auide_hwif;
+-static int dbdma_init_done;
+-
+-static int auide_ddma_init(_auide_hwif *auide);
-@@ -220,7 +186,7 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
- dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+ #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA)
- /* 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);
- }
+@@ -61,7 +58,7 @@ void auide_insw(unsigned long port, void *addr, u32 count)
- static __devexit int ixp4xx_pata_remove(struct platform_device *dev)
-@@ -255,6 +221,7 @@ MODULE_AUTHOR("Alessandro Zummo <a.zummo at towertech.it>");
- MODULE_DESCRIPTION("low-level driver for ixp4xx Compact Flash PATA");
- MODULE_LICENSE("GPL");
- MODULE_VERSION(DRV_VERSION);
-+MODULE_ALIAS("platform:" DRV_NAME);
+ if(!put_dest_flags(ahwif->rx_chan, (void*)addr, count << 1,
+ DDMA_FLAGS_NOIE)) {
+- printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__);
++ printk(KERN_ERR "%s failed %d\n", __func__, __LINE__);
+ return;
+ }
+ ctp = *((chan_tab_t **)ahwif->rx_chan);
+@@ -79,7 +76,7 @@ void auide_outsw(unsigned long port, void *addr, u32 count)
- 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;
+ if(!put_source_flags(ahwif->tx_chan, (void*)addr,
+ count << 1, DDMA_FLAGS_NOIE)) {
+- printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__);
++ printk(KERN_ERR "%s failed %d\n", __func__, __LINE__);
+ return;
}
-- 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);
+ ctp = *((chan_tab_t **)ahwif->tx_chan);
+@@ -89,6 +86,17 @@ void auide_outsw(unsigned long port, void *addr, u32 count)
+ ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp);
}
- /* No PIO or DMA methods needed for this device */
++static void au1xxx_input_data(ide_drive_t *drive, struct request *rq,
++ void *buf, unsigned int len)
++{
++ auide_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
++}
++
++static void au1xxx_output_data(ide_drive_t *drive, struct request *rq,
++ void *buf, unsigned int len)
++{
++ auide_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
++}
+ #endif
- 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 void au1xxx_set_pio_mode(ide_drive_t *drive, const u8 pio)
+@@ -250,7 +258,7 @@ static int auide_build_dmatable(ide_drive_t *drive)
+ (void*) sg_virt(sg),
+ tc, flags)) {
+ printk(KERN_ERR "%s failed %d\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ }
+ } else
+ {
+@@ -258,7 +266,7 @@ static int auide_build_dmatable(ide_drive_t *drive)
+ (void*) sg_virt(sg),
+ tc, flags)) {
+ printk(KERN_ERR "%s failed %d\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ }
+ }
--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,
- };
+@@ -315,35 +323,6 @@ static int auide_dma_setup(ide_drive_t *drive)
+ return 0;
+ }
+-static u8 auide_mdma_filter(ide_drive_t *drive)
+-{
+- /*
+- * FIXME: ->white_list and ->black_list are based on completely bogus
+- * ->ide_dma_check implementation which didn't set neither the host
+- * controller timings nor the device for the desired transfer mode.
+- *
+- * They should be either removed or 0x00 MWDMA mask should be
+- * returned for devices on the ->black_list.
+- */
+-
+- if (dbdma_init_done == 0) {
+- auide_hwif.white_list = ide_in_drive_list(drive->id,
+- dma_white_list);
+- auide_hwif.black_list = ide_in_drive_list(drive->id,
+- dma_black_list);
+- auide_hwif.drive = drive;
+- auide_ddma_init(&auide_hwif);
+- dbdma_init_done = 1;
+- }
+-
+- /* Is the drive in our DMA black list? */
+- if (auide_hwif.black_list)
+- printk(KERN_WARNING "%s: Disabling DMA for %s (blacklisted)\n",
+- drive->name, drive->id->model);
+-
+- return drive->hwif->mwdma_mask;
+-}
+-
+ static int auide_dma_test_irq(ide_drive_t *drive)
+ {
+ if (drive->waiting_for_dma == 0)
+@@ -389,48 +368,48 @@ static void auide_ddma_rx_callback(int irq, void *param)
+ static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 devwidth, u32 flags)
+ {
+ dev->dev_id = dev_id;
+- dev->dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR;
++ dev->dev_physaddr = (u32)IDE_PHYS_ADDR;
+ dev->dev_intlevel = 0;
+ dev->dev_intpolarity = 0;
+ dev->dev_tsize = tsize;
+ dev->dev_devwidth = devwidth;
+ dev->dev_flags = flags;
+ }
+-
+-#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
-@@ -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)
++#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+ static void auide_dma_timeout(ide_drive_t *drive)
{
- static const struct ata_port_info info = {
-- .sht = &jmicron_sht,
- .flags = ATA_FLAG_SLAVE_POSS,
+ ide_hwif_t *hwif = HWIF(drive);
- .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 };
+ printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
-- return ata_pci_init_one(pdev, ppi);
-+ return ata_pci_sff_init_one(pdev, ppi, &jmicron_sht, NULL);
+- if (hwif->ide_dma_test_irq(drive))
++ if (auide_dma_test_irq(drive))
+ return;
+
+- hwif->ide_dma_end(drive);
++ auide_dma_end(drive);
}
+-
- 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 int auide_ddma_init(_auide_hwif *auide) {
+-
++static const struct ide_dma_ops au1xxx_dma_ops = {
++ .dma_host_set = auide_dma_host_set,
++ .dma_setup = auide_dma_setup,
++ .dma_exec_cmd = auide_dma_exec_cmd,
++ .dma_start = auide_dma_start,
++ .dma_end = auide_dma_end,
++ .dma_test_irq = auide_dma_test_irq,
++ .dma_lost_irq = auide_dma_lost_irq,
++ .dma_timeout = auide_dma_timeout,
++};
++
++static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
++{
++ _auide_hwif *auide = (_auide_hwif *)hwif->hwif_data;
+ dbdev_tab_t source_dev_tab, target_dev_tab;
+ u32 dev_id, tsize, devwidth, flags;
+- ide_hwif_t *hwif = auide->hwif;
+
+- dev_id = AU1XXX_ATA_DDMA_REQ;
++ dev_id = IDE_DDMA_REQ;
+
+- if (auide->white_list || auide->black_list) {
+- tsize = 8;
+- devwidth = 32;
+- }
+- else {
+- tsize = 1;
+- devwidth = 16;
+-
+- printk(KERN_ERR "au1xxx-ide: %s is not on ide driver whitelist.\n",auide_hwif.drive->id->model);
+- printk(KERN_ERR " please read 'Documentation/mips/AU1xxx_IDE.README'");
+- }
++ tsize = 8; /* 1 */
++ devwidth = 32; /* 16 */
+
+ #ifdef IDE_AU1XXX_BURSTMODE
+ flags = DEV_FLAGS_SYNC | DEV_FLAGS_BURSTABLE;
+@@ -482,9 +461,9 @@ static int auide_ddma_init(_auide_hwif *auide) {
+ return 0;
+ }
+ #else
+-
+-static int auide_ddma_init( _auide_hwif *auide )
++static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
+ {
++ _auide_hwif *auide = (_auide_hwif *)hwif->hwif_data;
+ dbdev_tab_t source_dev_tab;
+ int flags;
+
+@@ -532,20 +511,28 @@ static int auide_ddma_init( _auide_hwif *auide )
+ static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif)
+ {
+ int i;
+- unsigned long *ata_regs = hw->io_ports;
++ unsigned long *ata_regs = hw->io_ports_array;
+
+ /* FIXME? */
+- for (i = 0; i < IDE_CONTROL_OFFSET; i++) {
+- *ata_regs++ = ahwif->regbase + (i << AU1XXX_ATA_REG_OFFSET);
+- }
++ for (i = 0; i < 8; i++)
++ *ata_regs++ = ahwif->regbase + (i << IDE_REG_SHIFT);
+
+ /* set the Alternative Status register */
+- *ata_regs = ahwif->regbase + (14 << AU1XXX_ATA_REG_OFFSET);
++ *ata_regs = ahwif->regbase + (14 << IDE_REG_SHIFT);
}
- 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 ide_port_ops au1xxx_port_ops = {
++ .set_pio_mode = au1xxx_set_pio_mode,
++ .set_dma_mode = auide_set_dma_mode,
+};
+
-+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 const struct ide_port_info au1xxx_port_info = {
++ .init_dma = auide_ddma_init,
++ .port_ops = &au1xxx_port_ops,
++#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
++ .dma_ops = &au1xxx_dma_ops,
++#endif
+ .host_flags = IDE_HFLAG_POST_SET_MODE |
+- IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
+ IDE_HFLAG_NO_IO_32BIT |
+ IDE_HFLAG_UNMASK_IRQS,
+ .pio_mask = ATA_PIO4,
+@@ -599,9 +586,11 @@ static int au_ide_probe(struct device *dev)
+ goto out;
+ }
- 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,
+- /* FIXME: This might possibly break PCMCIA IDE devices */
-
-- .port_start = ata_sff_port_start,
- };
+- hwif = &ide_hwifs[pdev->id];
++ hwif = ide_find_port();
++ if (hwif == NULL) {
++ ret = -ENOENT;
++ goto out;
++ }
- /*
-@@ -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);
+ memset(&hw, 0, sizeof(hw));
+ auide_setup_ports(&hw, ahwif);
+@@ -613,35 +602,13 @@ static int au_ide_probe(struct device *dev)
- return buflen;
- }
+ hwif->dev = dev;
- 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,
+- /* hold should be on in all cases */
+- hwif->hold = 1;
-
-- .qc_prep = ata_qc_prep,
-- .qc_issue = ata_qc_issue_prot,
+- hwif->mmio = 1;
-
-- .data_xfer = pdc_data_xfer_vlb,
+ /* If the user has selected DDMA assisted copies,
+ then set up a few local I/O function entry points
+ */
+
+ #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+- hwif->INSW = auide_insw;
+- hwif->OUTSW = auide_outsw;
+-#endif
+-
+- hwif->set_pio_mode = &au1xxx_set_pio_mode;
+- hwif->set_dma_mode = &auide_set_dma_mode;
+-
+-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+- hwif->dma_timeout = &auide_dma_timeout;
+-
+- hwif->mdma_filter = &auide_mdma_filter;
+-
+- hwif->dma_host_set = &auide_dma_host_set;
+- hwif->dma_exec_cmd = &auide_dma_exec_cmd;
+- hwif->dma_start = &auide_dma_start;
+- hwif->ide_dma_end = &auide_dma_end;
+- hwif->dma_setup = &auide_dma_setup;
+- hwif->ide_dma_test_irq = &auide_dma_test_irq;
+- hwif->dma_lost_irq = &auide_dma_lost_irq;
++ hwif->input_data = au1xxx_input_data;
++ hwif->output_data = au1xxx_output_data;
+ #endif
+ hwif->select_data = 0; /* no chipset-specific code */
+ hwif->config_data = 0; /* no chipset-specific code */
+@@ -649,11 +616,6 @@ static int au_ide_probe(struct device *dev)
+ auide_hwif.hwif = hwif;
+ hwif->hwif_data = &auide_hwif;
+
+-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+- auide_ddma_init(&auide_hwif);
+- dbdma_init_done = 1;
+-#endif
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+ idx[0] = hwif->index;
+
+ ide_device_add(idx, &au1xxx_port_info);
+@@ -673,7 +635,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);
+
+ iounmap((void *)ahwif->regbase);
+
+diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
+index 956259f..712d17b 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;
-
-- .port_start = ata_sff_port_start,
-+ .sff_data_xfer = pdc_data_xfer_vlb,
- };
+ 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));
+@@ -114,16 +109,15 @@ static int __devinit swarm_ide_probe(struct device *dev)
+ base = ioremap(offset, size);
- /*
-@@ -427,30 +356,8 @@ static void ht6560a_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ /* Setup MMIO ops. */
++ hwif->host_flags = IDE_HFLAG_MMIO;
+ default_hwif_mmiops(hwif);
+- /* Prevent resource map manipulation. */
+- hwif->mmio = 1;
++
+ hwif->chipset = ide_generic;
+- hwif->noprobe = 0;
+
+- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+- hwif->io_ports[i] =
++ for (i = 0; i <= 7; i++)
++ hwif->io_ports_array[i] =
+ (unsigned long)(base + ((0x1f0 + i) << 5));
+- hwif->io_ports[IDE_CONTROL_OFFSET] =
++ hwif->io_ports.ctl_addr =
+ (unsigned long)(base + (0x3f6 << 5));
+ hwif->irq = K_INT_GB_IDE;
+
+diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
+index cfb3265..7f46c22 100644
+--- a/drivers/ide/pci/aec62xx.c
++++ b/drivers/ide/pci/aec62xx.c
+@@ -135,12 +135,12 @@ static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
+
+ static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ {
+- drive->hwif->set_dma_mode(drive, pio + XFER_PIO_0);
++ drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0);
}
- 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 */
+ static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const char *name)
+ {
+- int bus_speed = system_bus_clock();
++ int bus_speed = ide_pci_clk ? ide_pci_clk : system_bus_clock();
+
+ if (bus_speed <= 33)
+ pci_set_drvdata(dev, (void *) aec6xxx_33_base);
+@@ -175,27 +175,23 @@ static u8 __devinit atp86x_cable_detect(ide_hwif_t *hwif)
+ return (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+ }
+
+-static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif)
+-{
+- struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- hwif->set_pio_mode = &aec_set_pio_mode;
-
-- .port_start = ata_sff_port_start,
- };
+- if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
+- hwif->set_dma_mode = &aec6210_set_mode;
+- else {
+- hwif->set_dma_mode = &aec6260_set_mode;
++static const struct ide_port_ops atp850_port_ops = {
++ .set_pio_mode = aec_set_pio_mode,
++ .set_dma_mode = aec6210_set_mode,
++};
- /*
-@@ -492,30 +399,8 @@ static void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev)
- }
+- hwif->cable_detect = atp86x_cable_detect;
+- }
+-}
++static const struct ide_port_ops atp86x_port_ops = {
++ .set_pio_mode = aec_set_pio_mode,
++ .set_dma_mode = aec6260_set_mode,
++ .cable_detect = atp86x_cable_detect,
++};
- static struct ata_port_operations ht6560b_port_ops = {
-+ .inherits = &legacy_base_port_ops,
- .set_piomode = ht6560b_set_piomode,
+ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
+ { /* 0 */
+ .name = "AEC6210",
+ .init_chipset = init_chipset_aec62xx,
+- .init_hwif = init_hwif_aec62xx,
+ .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
++ .port_ops = &atp850_port_ops,
+ .host_flags = IDE_HFLAG_SERIALIZE |
+ IDE_HFLAG_NO_ATAPI_DMA |
+ IDE_HFLAG_NO_DSC |
+@@ -207,7 +203,7 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
+ },{ /* 1 */
+ .name = "AEC6260",
+ .init_chipset = init_chipset_aec62xx,
+- .init_hwif = init_hwif_aec62xx,
++ .port_ops = &atp86x_port_ops,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_AUTODMA |
+ IDE_HFLAG_ABUSE_SET_DMA_MODE |
+ IDE_HFLAG_OFF_BOARD,
+@@ -217,17 +213,18 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
+ },{ /* 2 */
+ .name = "AEC6260R",
+ .init_chipset = init_chipset_aec62xx,
+- .init_hwif = init_hwif_aec62xx,
+ .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
++ .port_ops = &atp86x_port_ops,
+ .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,
+ },{ /* 3 */
+ .name = "AEC6280",
+ .init_chipset = init_chipset_aec62xx,
+- .init_hwif = init_hwif_aec62xx,
++ .port_ops = &atp86x_port_ops,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
+ IDE_HFLAG_ABUSE_SET_DMA_MODE |
+ IDE_HFLAG_OFF_BOARD,
+@@ -237,8 +234,8 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
+ },{ /* 4 */
+ .name = "AEC6280R",
+ .init_chipset = init_chipset_aec62xx,
+- .init_hwif = init_hwif_aec62xx,
+ .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
++ .port_ops = &atp86x_port_ops,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
+ IDE_HFLAG_ABUSE_SET_DMA_MODE |
+ IDE_HFLAG_OFF_BOARD,
+diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
+index b3b6f51..c1922f9 100644
+--- a/drivers/ide/pci/alim15x3.c
++++ b/drivers/ide/pci/alim15x3.c
+@@ -38,8 +38,6 @@
+
+ #include <asm/io.h>
+
+-#define DISPLAY_ALI_TIMINGS
-
-- .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,
+ /*
+ * ALi devices are not plug in. Otherwise these static values would
+ * need to go. They ought to go away anyway
+@@ -49,236 +47,6 @@ static u8 m5229_revision;
+ static u8 chip_is_1543c_e;
+ static struct pci_dev *isa_dev;
+
+-#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
+-#include <linux/stat.h>
+-#include <linux/proc_fs.h>
-
-- .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,
+-static u8 ali_proc = 0;
-
-- .qc_prep = ata_qc_prep,
-- .qc_issue = ata_qc_issue_prot,
+-static struct pci_dev *bmide_dev;
-
-- .data_xfer = ata_data_xfer, /* FIXME: Check 32bit and noirq */
+-static char *fifo[4] = {
+- "FIFO Off",
+- "FIFO On ",
+- "DMA mode",
+- "PIO mode" };
+-
+-static char *udmaT[8] = {
+- "1.5T",
+- " 2T",
+- "2.5T",
+- " 3T",
+- "3.5T",
+- " 4T",
+- " 6T",
+- " 8T"
+-};
+-
+-static char *channel_status[8] = {
+- "OK ",
+- "busy ",
+- "DRQ ",
+- "DRQ busy ",
+- "error ",
+- "error busy ",
+- "error DRQ ",
+- "error DRQ busy"
+-};
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+-/**
+- * ali_get_info - generate proc file for ALi IDE
+- * @buffer: buffer to fill
+- * @addr: address of user start in buffer
+- * @offset: offset into 'file'
+- * @count: buffer count
+- *
+- * Walks the Ali devices and outputs summary data on the tuning and
+- * anything else that will help with debugging
+- */
+-
+-static int ali_get_info (char *buffer, char **addr, off_t offset, int count)
+-{
+- unsigned long bibma;
+- u8 reg53h, reg5xh, reg5yh, reg5xh1, reg5yh1, c0, c1, rev, tmp;
+- char *q, *p = buffer;
+-
+- /* fetch rev. */
+- pci_read_config_byte(bmide_dev, 0x08, &rev);
+- if (rev >= 0xc1) /* M1543C or newer */
+- udmaT[7] = " ???";
+- else
+- fifo[3] = " ??? ";
-
-- .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,
+- /* first fetch bibma: */
+-
+- bibma = pci_resource_start(bmide_dev, 4);
-
-- .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,
+- /*
+- * at that point bibma+0x2 et bibma+0xa are byte
+- * registers to investigate:
+- */
+- c0 = inb(bibma + 0x02);
+- c1 = inb(bibma + 0x0a);
-
-- .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,
+- p += sprintf(p,
+- "\n Ali M15x3 Chipset.\n");
+- p += sprintf(p,
+- " ------------------\n");
+- pci_read_config_byte(bmide_dev, 0x78, ®53h);
+- p += sprintf(p, "PCI Clock: %d.\n", reg53h);
+-
+- pci_read_config_byte(bmide_dev, 0x53, ®53h);
+- p += sprintf(p,
+- "CD_ROM FIFO:%s, CD_ROM DMA:%s\n",
+- (reg53h & 0x02) ? "Yes" : "No ",
+- (reg53h & 0x01) ? "Yes" : "No " );
+- pci_read_config_byte(bmide_dev, 0x74, ®53h);
+- p += sprintf(p,
+- "FIFO Status: contains %d Words, runs%s%s\n\n",
+- (reg53h & 0x3f),
+- (reg53h & 0x40) ? " OVERWR" : "",
+- (reg53h & 0x80) ? " OVERRD." : "." );
+-
+- p += sprintf(p,
+- "-------------------primary channel"
+- "-------------------secondary channel"
+- "---------\n\n");
+-
+- pci_read_config_byte(bmide_dev, 0x09, ®53h);
+- p += sprintf(p,
+- "channel status: %s"
+- " %s\n",
+- (reg53h & 0x20) ? "On " : "Off",
+- (reg53h & 0x10) ? "On " : "Off" );
+-
+- p += sprintf(p,
+- "both channels togth: %s"
+- " %s\n",
+- (c0&0x80) ? "No " : "Yes",
+- (c1&0x80) ? "No " : "Yes" );
+-
+- pci_read_config_byte(bmide_dev, 0x76, ®53h);
+- p += sprintf(p,
+- "Channel state: %s %s\n",
+- channel_status[reg53h & 0x07],
+- channel_status[(reg53h & 0x70) >> 4] );
+-
+- pci_read_config_byte(bmide_dev, 0x58, ®5xh);
+- pci_read_config_byte(bmide_dev, 0x5c, ®5yh);
+- p += sprintf(p,
+- "Add. Setup Timing: %dT"
+- " %dT\n",
+- (reg5xh & 0x07) ? (reg5xh & 0x07) : 8,
+- (reg5yh & 0x07) ? (reg5yh & 0x07) : 8 );
+-
+- pci_read_config_byte(bmide_dev, 0x59, ®5xh);
+- pci_read_config_byte(bmide_dev, 0x5d, ®5yh);
+- p += sprintf(p,
+- "Command Act. Count: %dT"
+- " %dT\n"
+- "Command Rec. Count: %dT"
+- " %dT\n\n",
+- (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8,
+- (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8,
+- (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16,
+- (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16 );
+-
+- p += sprintf(p,
+- "----------------drive0-----------drive1"
+- "------------drive0-----------drive1------\n\n");
+- p += sprintf(p,
+- "DMA enabled: %s %s"
+- " %s %s\n",
+- (c0&0x20) ? "Yes" : "No ",
+- (c0&0x40) ? "Yes" : "No ",
+- (c1&0x20) ? "Yes" : "No ",
+- (c1&0x40) ? "Yes" : "No " );
+-
+- pci_read_config_byte(bmide_dev, 0x54, ®5xh);
+- pci_read_config_byte(bmide_dev, 0x55, ®5yh);
+- q = "FIFO threshold: %2d Words %2d Words"
+- " %2d Words %2d Words\n";
+- if (rev < 0xc1) {
+- if ((rev == 0x20) &&
+- (pci_read_config_byte(bmide_dev, 0x4f, &tmp), (tmp &= 0x20))) {
+- p += sprintf(p, q, 8, 8, 8, 8);
+- } else {
+- p += sprintf(p, q,
+- (reg5xh & 0x03) + 12,
+- ((reg5xh & 0x30)>>4) + 12,
+- (reg5yh & 0x03) + 12,
+- ((reg5yh & 0x30)>>4) + 12 );
+- }
+- } else {
+- int t1 = (tmp = (reg5xh & 0x03)) ? (tmp << 3) : 4;
+- int t2 = (tmp = ((reg5xh & 0x30)>>4)) ? (tmp << 3) : 4;
+- int t3 = (tmp = (reg5yh & 0x03)) ? (tmp << 3) : 4;
+- int t4 = (tmp = ((reg5yh & 0x30)>>4)) ? (tmp << 3) : 4;
+- p += sprintf(p, q, t1, t2, t3, t4);
+- }
-
-- .qc_prep = ata_qc_prep,
-- .qc_issue = ata_qc_issue_prot,
+-#if 0
+- p += sprintf(p,
+- "FIFO threshold: %2d Words %2d Words"
+- " %2d Words %2d Words\n",
+- (reg5xh & 0x03) + 12,
+- ((reg5xh & 0x30)>>4) + 12,
+- (reg5yh & 0x03) + 12,
+- ((reg5yh & 0x30)>>4) + 12 );
+-#endif
+-
+- p += sprintf(p,
+- "FIFO mode: %s %s %s %s\n",
+- fifo[((reg5xh & 0x0c) >> 2)],
+- fifo[((reg5xh & 0xc0) >> 6)],
+- fifo[((reg5yh & 0x0c) >> 2)],
+- fifo[((reg5yh & 0xc0) >> 6)] );
+-
+- pci_read_config_byte(bmide_dev, 0x5a, ®5xh);
+- pci_read_config_byte(bmide_dev, 0x5b, ®5xh1);
+- pci_read_config_byte(bmide_dev, 0x5e, ®5yh);
+- pci_read_config_byte(bmide_dev, 0x5f, ®5yh1);
+-
+- p += sprintf(p,/*
+- "------------------drive0-----------drive1"
+- "------------drive0-----------drive1------\n")*/
+- "Dt RW act. Cnt %2dT %2dT"
+- " %2dT %2dT\n"
+- "Dt RW rec. Cnt %2dT %2dT"
+- " %2dT %2dT\n\n",
+- (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8,
+- (reg5xh1 & 0x70) ? ((reg5xh1 & 0x70) >> 4) : 8,
+- (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8,
+- (reg5yh1 & 0x70) ? ((reg5yh1 & 0x70) >> 4) : 8,
+- (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16,
+- (reg5xh1 & 0x0f) ? (reg5xh1 & 0x0f) : 16,
+- (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16,
+- (reg5yh1 & 0x0f) ? (reg5yh1 & 0x0f) : 16 );
+-
+- p += sprintf(p,
+- "-----------------------------------UDMA Timings"
+- "--------------------------------\n\n");
+-
+- pci_read_config_byte(bmide_dev, 0x56, ®5xh);
+- pci_read_config_byte(bmide_dev, 0x57, ®5yh);
+- p += sprintf(p,
+- "UDMA: %s %s"
+- " %s %s\n"
+- "UDMA timings: %s %s"
+- " %s %s\n\n",
+- (reg5xh & 0x08) ? "OK" : "No",
+- (reg5xh & 0x80) ? "OK" : "No",
+- (reg5yh & 0x08) ? "OK" : "No",
+- (reg5yh & 0x80) ? "OK" : "No",
+- udmaT[(reg5xh & 0x07)],
+- udmaT[(reg5xh & 0x70) >> 4],
+- udmaT[reg5yh & 0x07],
+- udmaT[(reg5yh & 0x70) >> 4] );
-
-- .data_xfer = ata_data_xfer,
+- return p-buffer; /* => must be less than 4k! */
+-}
+-#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+ /**
+ * ali_set_pio_mode - set host controller for PIO mode
+ * @drive: drive
+@@ -294,7 +62,7 @@ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ int s_time, a_time, c_time;
+ u8 s_clc, a_clc, r_clc;
+ unsigned long flags;
+- int bus_speed = system_bus_clock();
++ int bus_speed = ide_pci_clk ? ide_pci_clk : system_bus_clock();
+ int port = hwif->channel ? 0x5c : 0x58;
+ int portFIFO = hwif->channel ? 0x55 : 0x54;
+ u8 cd_dma_fifo = 0;
+@@ -465,14 +233,6 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c
+
+ isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
+
+-#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
+- if (!ali_proc) {
+- ali_proc = 1;
+- bmide_dev = dev;
+- ide_pci_create_host_proc("ali", ali_get_info);
+- }
+-#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */
-
-- .port_start = ata_sff_port_start,
- };
+ local_irq_save(flags);
- /*
-@@ -716,7 +579,7 @@ static void opti82c46x_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ if (m5229_revision < 0xC2) {
+@@ -610,7 +370,7 @@ static int ali_cable_override(struct pci_dev *pdev)
}
/**
-- * opt82c465mv_qc_issue_prot - command issue
-+ * opt82c465mv_qc_issue - command issue
- * @qc: command pending
+- * ata66_ali15x3 - check for UDMA 66 support
++ * ali_cable_detect - cable detection
+ * @hwif: IDE interface
*
- * 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
+ * This checks if the controller and the cable are capable
+@@ -620,7 +380,7 @@ static int ali_cable_override(struct pci_dev *pdev)
+ * FIXME: frobs bits that are not defined on newer ALi devicea
*/
--static unsigned int opti82c46x_qc_issue_prot(struct ata_queued_cmd *qc)
-+static unsigned int opti82c46x_qc_issue(struct ata_queued_cmd *qc)
+-static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif)
++static u8 __devinit ali_cable_detect(ide_hwif_t *hwif)
{
- 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);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ unsigned long flags;
+@@ -652,34 +412,14 @@ static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif)
+ return cbl;
}
- 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,
+-/**
+- * init_hwif_common_ali15x3 - Set up ALI IDE hardware
+- * @hwif: IDE interface
+- *
+- * Initialize the IDE structure side of the ALi 15x3 driver.
+- */
+-
+-static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif)
+-{
+- hwif->set_pio_mode = &ali_set_pio_mode;
+- hwif->set_dma_mode = &ali_set_dma_mode;
+- hwif->udma_filter = &ali_udma_filter;
-
-- .qc_prep = ata_qc_prep,
-- .qc_issue = opti82c46x_qc_issue_prot,
+- hwif->cable_detect = ata66_ali15x3;
-
-- .data_xfer = ata_data_xfer,
+- if (hwif->dma_base == 0)
+- return;
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- hwif->dma_setup = &ali15x3_dma_setup;
+-}
-
-- .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
++#if !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC)
+ /**
+ * init_hwif_ali15x3 - Initialize the ALI IDE x86 stuff
+ * @hwif: interface to configure
*
- * 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.
+ * Obtain the IRQ tables for an ALi based IDE solution on the PC
+ * class platforms. This part of the code isn't applicable to the
+- * Sparc systems
++ * Sparc and PowerPC systems.
*/
- 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)
+ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
+@@ -722,35 +462,66 @@ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
+ if(irq >= 0)
+ hwif->irq = irq;
+ }
+-
+- init_hwif_common_ali15x3(hwif);
}
++#else
++#define init_hwif_ali15x3 NULL
++#endif /* !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) */
/**
-- * qdi_qc_issue_prot - command issue
-+ * qdi_qc_issue - command issue
- * @qc: command pending
+ * init_dma_ali15x3 - set up DMA on ALi15x3
+ * @hwif: IDE interface
+- * @dmabase: DMA interface base PCI address
++ * @d: IDE port info
*
- * Called when the libata layer is about to issue a command. We wrap
- * this interface so that we can load the correct ATA timings.
+- * Set up the DMA functionality on the ALi 15x3. For the ALi
+- * controllers this is generic so we can let the generic code do
+- * the actual work.
++ * Set up the DMA functionality on the ALi 15x3.
*/
--static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
-+static unsigned int qdi_qc_issue(struct ata_queued_cmd *qc)
+-static void __devinit init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase)
++static int __devinit init_dma_ali15x3(ide_hwif_t *hwif,
++ const struct ide_port_info *d)
{
- 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);
+- if (m5229_revision < 0x20)
+- return;
++ struct pci_dev *dev = to_pci_dev(hwif->dev);
++ unsigned long base = ide_pci_dma_base(hwif, d);
++
++ if (base == 0 || ide_pci_set_master(dev, d->name) < 0)
++ return -1;
++
+ if (!hwif->channel)
+- outb(inb(dmabase + 2) & 0x60, dmabase + 2);
+- ide_setup_dma(hwif, dmabase);
++ outb(inb(base + 2) & 0x60, base + 2);
++
++ printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n",
++ hwif->name, base, base + 7);
++
++ if (ide_allocate_dma_engine(hwif))
++ return -1;
++
++ ide_setup_dma(hwif, base);
++
++ return 0;
}
- 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 const struct ide_port_ops ali_port_ops = {
++ .set_pio_mode = ali_set_pio_mode,
++ .set_dma_mode = ali_set_dma_mode,
++ .udma_filter = ali_udma_filter,
++ .cable_detect = ali_cable_detect,
++};
++
++static const struct ide_dma_ops ali_dma_ops = {
++ .dma_host_set = ide_dma_host_set,
++ .dma_setup = ali15x3_dma_setup,
++ .dma_exec_cmd = ide_dma_exec_cmd,
++ .dma_start = ide_dma_start,
++ .dma_end = __ide_dma_end,
++ .dma_test_irq = ide_dma_test_irq,
++ .dma_lost_irq = ide_dma_lost_irq,
++ .dma_timeout = ide_dma_timeout,
++};
++
+ static const struct ide_port_info ali15x3_chipset __devinitdata = {
+ .name = "ALI15X3",
+ .init_chipset = init_chipset_ali15x3,
+ .init_hwif = init_hwif_ali15x3,
+ .init_dma = init_dma_ali15x3,
+- .host_flags = IDE_HFLAG_BOOTABLE,
++ .port_ops = &ali_port_ops,
+ .pio_mask = ATA_PIO5,
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
+@@ -793,14 +564,17 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev
+ d.udma_mask = ATA_UDMA5;
+ else
+ d.udma_mask = ATA_UDMA6;
++
++ d.dma_ops = &ali_dma_ops;
++ } else {
++ d.host_flags |= IDE_HFLAG_NO_DMA;
++
++ d.mwdma_mask = d.swdma_mask = 0;
+ }
- static int qdi_port(struct platform_device *dev,
-@@ -930,84 +772,22 @@ static int qdi_port(struct platform_device *dev,
- }
+ if (idx == 0)
+ d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
- 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,
- };
+-#if defined(CONFIG_SPARC64)
+- d.init_hwif = init_hwif_common_ali15x3;
+-#endif /* CONFIG_SPARC64 */
+ return ide_setup_pci_device(dev, &d);
+ }
- 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,
- };
+diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
+index 2ef890c..efcf543 100644
+--- a/drivers/ide/pci/amd74xx.c
++++ b/drivers/ide/pci/amd74xx.c
+@@ -179,7 +179,7 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev,
+ * Determine the system bus clock.
+ */
- 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,
- };
+- amd_clock = system_bus_clock() * 1000;
++ amd_clock = (ide_pci_clk ? ide_pci_clk : system_bus_clock()) * 1000;
- static DEFINE_SPINLOCK(winbond_lock);
-@@ -1076,29 +856,9 @@ static int winbond_port(struct platform_device *dev,
- }
+ switch (amd_clock) {
+ case 33000: amd_clock = 33333; break;
+@@ -210,21 +210,20 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
- 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,
+ if (hwif->irq == 0) /* 0 is bogus but will do for now */
+ hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel);
-
-- .qc_prep = ata_qc_prep,
-- .qc_issue = ata_qc_issue_prot,
--
-- .data_xfer = vlb32_data_xfer,
+- hwif->set_pio_mode = &amd_set_pio_mode;
+- hwif->set_dma_mode = &amd_set_drive;
-
-- .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);
+- hwif->cable_detect = amd_cable_detect;
}
- 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 */
++static const struct ide_port_ops amd_port_ops = {
++ .set_pio_mode = amd_set_pio_mode,
++ .set_dma_mode = amd_set_drive,
++ .cable_detect = amd_cable_detect,
++};
++
+ #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) \
+ { \
+@@ -232,6 +231,7 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
+ .init_chipset = init_chipset_amd74xx, \
+ .init_hwif = init_hwif_amd74xx, \
+ .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, \
++ .port_ops = &amd_port_ops, \
+ .host_flags = IDE_HFLAGS_AMD, \
+ .pio_mask = ATA_PIO5, \
+ .swdma_mask = swdma, \
+@@ -245,6 +245,7 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
+ .init_chipset = init_chipset_amd74xx, \
+ .init_hwif = init_hwif_amd74xx, \
+ .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, \
++ .port_ops = &amd_port_ops, \
+ .host_flags = IDE_HFLAGS_AMD, \
+ .pio_mask = ATA_PIO5, \
+ .swdma_mask = ATA_SWDMA2, \
+diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
+index 7e037c8..8b63718 100644
+--- a/drivers/ide/pci/atiixp.c
++++ b/drivers/ide/pci/atiixp.c
+@@ -130,37 +130,26 @@ static u8 __devinit atiixp_cable_detect(ide_hwif_t *hwif)
+ return ATA_CBL_PATA40;
}
-/**
-- * marvell_error_handler - Setup and error handler
-- * @ap: Port to handle
+- * init_hwif_atiixp - fill in the hwif for the ATIIXP
+- * @hwif: IDE interface
- *
-- * LOCKING:
-- * None (inherited from caller).
+- * Set up the ide_hwif_t for the ATIIXP interface according to the
+- * capabilities of the hardware.
- */
-
--static void marvell_error_handler(struct ata_port *ap)
+-static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
-{
-- ata_bmdma_drive_eh(ap, marvell_pre_reset, ata_std_softreset, NULL,
-- ata_std_postreset);
--}
+- hwif->set_pio_mode = &atiixp_set_pio_mode;
+- hwif->set_dma_mode = &atiixp_set_dma_mode;
-
- /* No PIO or DMA methods needed for this device */
+- hwif->cable_detect = atiixp_cable_detect;
+-}
++static const struct ide_port_ops atiixp_port_ops = {
++ .set_pio_mode = atiixp_set_pio_mode,
++ .set_dma_mode = atiixp_set_dma_mode,
++ .cable_detect = atiixp_cable_detect,
++};
- 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 ide_port_info atiixp_pci_info[] __devinitdata = {
+ { /* 0 */
+ .name = "ATIIXP",
+- .init_hwif = init_hwif_atiixp,
+ .enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
+- .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
++ .port_ops = &atiixp_port_ops,
++ .host_flags = IDE_HFLAG_LEGACY_IRQS,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
+ },{ /* 1 */
+ .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,
++ .port_ops = &atiixp_port_ops,
++ .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..aaf3810 100644
+--- a/drivers/ide/pci/cmd640.c
++++ b/drivers/ide/pci/cmd640.c
+@@ -4,7 +4,7 @@
--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,
- };
+ /*
+ * Original authors: abramov at cecmow.enet.dec.com (Igor Abramov)
+- * mlord at pobox.com (Mark Lord)
++ * mlord at pobox.com (Mark Lord)
+ *
+ * See linux/MAINTAINERS for address of current maintainer.
+ *
+@@ -98,7 +98,7 @@
+ #define CMD640_PREFETCH_MASKS 1
-@@ -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,
+-//#define CMD640_DUMP_REGS
++/*#define CMD640_DUMP_REGS */
- .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,
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+@@ -109,10 +109,9 @@
-@@ -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;
+ #include <asm/io.h>
-- return ata_pci_init_one(pdev, ppi);
-+ return ata_pci_sff_init_one(pdev, ppi, &marvell_sht, NULL);
+-/*
+- * This flag is set in ide.c by the parameter: ide0=cmd640_vlb
+- */
+-int cmd640_vlb = 0;
++#define DRV_NAME "cmd640"
++
++static int cmd640_vlb;
+
+ /*
+ * CMD640 specific registers definition.
+@@ -185,7 +184,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 +205,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 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);
+-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 +219,14 @@ static u8 get_cmd640_reg_pci1 (u16 reg)
-- ata_std_dev_select(ap,device);
-+ ata_sff_dev_select(ap,device);
+ /* 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 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 u8 get_cmd640_reg_pci2 (u16 reg)
++static u8 get_cmd640_reg_pci2(u16 reg)
+ {
+ u8 b;
- 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,
- };
+@@ -240,13 +238,13 @@ static u8 get_cmd640_reg_pci2 (u16 reg)
- 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);
+ /* VLB access */
- /* 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);
+-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);
}
-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;
+-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 +266,11 @@ static void put_cmd640_reg(u16 reg, u8 val)
+ unsigned long flags;
-- 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);
+ spin_lock_irqsave(&cmd640_lock, flags);
+- __put_cmd640_reg(reg,val);
++ __put_cmd640_reg(reg, val);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
}
- /**
-@@ -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 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 +290,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 +306,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 +320,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;
- 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.
+@@ -343,18 +341,18 @@ 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;
--static unsigned int mpiix_qc_issue_prot(struct ata_queued_cmd *qc)
-+static unsigned int mpiix_qc_issue(struct ata_queued_cmd *qc)
+ spin_lock_irqsave(&cmd640_lock, flags);
+
+- outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET); /* select drive0 */
++ outb_p(0x0a, 0x176); /* select drive0 */
+ udelay(100);
+- if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x0a) {
+- outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */
++ if ((inb_p(0x176) & 0x1f) != 0x0a) {
++ outb_p(0x1a, 0x176); /* select drive1 */
+ udelay(100);
+- if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) {
++ if ((inb_p(0x176) & 0x1f) != 0x1a) {
+ spin_unlock_irqrestore(&cmd640_lock, flags);
+ return 0; /* nothing responded */
+ }
+@@ -367,7 +365,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)
{
- 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);
+ unsigned int reg = cmd640_vlb ? 0x50 : 0x00;
-- return ata_qc_issue_prot(qc);
-+ return ata_sff_qc_issue(qc);
+@@ -382,13 +380,13 @@ static void cmd640_dump_regs (void)
}
+ #endif
- 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),
- };
++#ifndef CONFIG_BLK_DEV_CMD640_ENHANCED
+ /*
+ * 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]);
- 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,
+ if (b & prefetch_masks[index]) { /* is prefetch off? */
+@@ -403,39 +401,12 @@ static void __init check_prefetch (unsigned int index)
+ drive->no_io_32bit = 0;
+ }
+ }
-
-- .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,
+-/*
+- * Figure out which devices we control
+- */
+-static void __init setup_device_ptrs (void)
+-{
+- unsigned int i;
-
-- .qc_prep = ata_qc_prep,
-- .qc_issue = mpiix_qc_issue_prot,
-- .data_xfer = ata_data_xfer,
+- 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];
+-}
-
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+-#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
-
-- .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);
++#else
+ /*
+ * 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 +433,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;
- /* 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);
+@@ -481,44 +452,16 @@ 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);
}
-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,
+ /*
+- * This routine retrieves the initial drive timings from the chipset.
+- */
+-static void __init retrieve_drive_counts (unsigned int index)
+-{
+- u8 b;
-
-- .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,
+- /*
+- * Get the internal setup timing, and convert to clock count
+- */
+- 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;
+- }
+- setup_counts[index] = b;
-
-- /* 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,
+- /*
+- * Get the active/recovery counts
+- */
+- b = get_cmd640_reg(drwtim_regs[index]);
+- active_counts[index] = (b >> 4) ? (b >> 4) : 0x10;
+- recovery_counts[index] = (b & 0x0f) ? (b & 0x0f) : 0x10;
+-}
-
-- /* 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,
- };
-
+-/*
+ * 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 +475,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 +493,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 */
+ }
-@@ -90,7 +48,6 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ /*
+@@ -572,11 +518,19 @@ 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)
{
- 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;
+ int setup_time, active_time, recovery_time, clock_time;
+ u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count;
+- int bus_speed = system_bus_clock();
++ int bus_speed;
++
++ if (cmd640_vlb && ide_vlb_clk)
++ bus_speed = ide_vlb_clk;
++ else if (!cmd640_vlb && ide_pci_clk)
++ bus_speed = ide_pci_clk;
++ else
++ bus_speed = system_bus_clock();
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev,
- "version " DRV_VERSION "\n");
+ if (pio_mode > 5)
+ pio_mode = 5;
+@@ -584,15 +538,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);
-+ 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);
+- setup_count = (setup_time + clock_time - 1) / clock_time;
++ setup_count = DIV_ROUND_UP(setup_time, clock_time);
- /* 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);
- }
+- 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 */
- 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);
- }
+- 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 +575,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 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 void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
+@@ -629,32 +583,26 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ unsigned int index = 0, cycle_time;
+ u8 b;
- 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,
+- 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;
-
-- .port_start = ata_sff_port_start,
-+ .set_piomode = ninja32_set_piomode,
- };
+- 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;
+ }
- 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);
+ cycle_time = ide_pio_cycle_time(drive, pio);
+- cmd640_set_mode(index, pio, cycle_time);
++ cmd640_set_mode(drive, index, pio, cycle_time);
- 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);
+ printk("%s: selected cmd640 PIO mode%d (%dns)",
+ drive->name, pio, cycle_time);
+@@ -662,6 +610,9 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ display_clocks(index);
}
-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);
- }
++static const struct ide_port_ops cmd640_port_ops = {
++ .set_pio_mode = cmd640_set_pio_mode,
++};
+ #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
- /**
-@@ -119,7 +105,7 @@ static void ns87410_set_piomode(struct ata_port *ap, struct ata_device *adev)
- }
+ static int pci_conf1(void)
+@@ -703,14 +654,32 @@ static const struct ide_port_info cmd640_port_info __initdata = {
+ .chipset = ide_cmd640,
+ .host_flags = IDE_HFLAG_SERIALIZE |
+ IDE_HFLAG_NO_DMA |
+- IDE_HFLAG_NO_AUTOTUNE |
+ IDE_HFLAG_ABUSE_PREFETCH |
+ IDE_HFLAG_ABUSE_FAST_DEVSEL,
+ #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
++ .port_ops = &cmd640_port_ops,
+ .pio_mask = ATA_PIO5,
+ #endif
+ };
- /**
-- * 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 int cmd640x_init_one(unsigned long base, unsigned long ctl)
++{
++ if (!request_region(base, 8, DRV_NAME)) {
++ printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
++ DRV_NAME, base, base + 7);
++ return -EBUSY;
++ }
++
++ if (!request_region(ctl, 1, DRV_NAME)) {
++ printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
++ DRV_NAME, ctl);
++ release_region(base, 8);
++ return -EBUSY;
++ }
++
++ return 0;
++}
++
+ /*
+ * Probe for a cmd640 chipset, and initialize it if found.
*/
+@@ -719,11 +688,12 @@ static int __init cmd640x_init(void)
+ #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+ int second_port_toggled = 0;
+ #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+- int second_port_cmd640 = 0;
++ int second_port_cmd640 = 0, rc;
+ const char *bus_type, *port2;
+ unsigned int index;
+ u8 b, cfr;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++ hw_regs_t hw[2];
--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);
+ if (cmd640_vlb && probe_for_cmd640_vlb()) {
+ bus_type = "VLB";
+@@ -758,21 +728,41 @@ 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;
+ }
-- return ata_qc_issue_prot(qc);
-+ return ata_sff_qc_issue(qc);
- }
++ rc = cmd640x_init_one(0x1f0, 0x3f6);
++ if (rc)
++ return rc;
++
++ rc = cmd640x_init_one(0x170, 0x376);
++ if (rc) {
++ release_region(0x3f6, 1);
++ release_region(0x1f0, 8);
++ return rc;
++ }
++
++ 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);
+-#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+- cmd_hwif0->set_pio_mode = &cmd640_set_pio_mode;
+-#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+-
+- idx[0] = cmd_hwif0->index;
++ if (cmd_hwif0) {
++ ide_init_port_hw(cmd_hwif0, &hw[0]);
++ idx[0] = cmd_hwif0->index;
++ }
- 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),
- };
+ /*
+ * Ensure compatibility by always using the slowest timings
+@@ -784,11 +774,13 @@ static int __init cmd640x_init(void)
+ put_cmd640_reg(CMDTIM, 0);
+ put_cmd640_reg(BRST, 0x40);
- 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,
++ 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 +811,11 @@ static int __init cmd640x_init(void)
+ /*
+ * Initialize data for secondary cmd640 port, if enabled
+ */
+- if (second_port_cmd640) {
+-#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+- cmd_hwif1->set_pio_mode = &cmd640_set_pio_mode;
+-#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
-
-- .port_start = ata_sff_port_start,
-+ .set_piomode = ns87410_set_piomode,
-+ .prereset = ns87410_pre_reset,
- };
++ if (second_port_cmd640 && cmd_hwif1) {
++ ide_init_port_hw(cmd_hwif1, &hw[1]);
+ 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);
- static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ /*
+@@ -834,35 +823,34 @@ 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];
+-#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.
+- */
+- 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);
+- printk("cmd640: drive%d timings/prefetch cleared\n", index);
+- } else {
+- /*
+- * Record timings/prefetch without changing them.
+- * This preserves any prior BIOS setup.
+- */
+- retrieve_drive_counts (index);
+- check_prefetch (index);
+- printk("cmd640: drive%d timings/prefetch(%s) preserved",
+- index, drive->no_io_32bit ? "off" : "on");
+- display_clocks(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
++ /*
++ * 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(drive, index);
++ set_prefetch_mode(drive, index, 0);
++ printk("cmd640: drive%d timings/prefetch cleared\n", index);
+ #else
+ /*
+ * 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..0867471 100644
+--- a/drivers/ide/pci/cmd64x.c
++++ b/drivers/ide/pci/cmd64x.c
+@@ -68,8 +68,8 @@ static u8 quantize_timing(int timing, int quant)
+ */
+ static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time)
{
- 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);
+- struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+- int clock_time = 1000 / system_bus_clock();
++ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
++ int clock_time = 1000 / (ide_pci_clk ? ide_pci_clk : system_bus_clock());
+ u8 cycle_count, active_count, recovery_count, drwtim;
+ static const u8 recovery_values[] =
+ {15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0};
+@@ -128,7 +128,7 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
+ ide_pio_timings[pio].active_time);
+
+ setup_count = quantize_timing(ide_pio_timings[pio].setup_time,
+- 1000 / system_bus_clock());
++ 1000 / (ide_pci_clk ? ide_pci_clk : system_bus_clock()));
+
+ /*
+ * The primary channel has individual address setup timing registers
+@@ -223,7 +223,7 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ (void) pci_write_config_byte(dev, pciU, regU);
}
- 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);
+-static int cmd648_ide_dma_end (ide_drive_t *drive)
++static int cmd648_dma_end(ide_drive_t *drive)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
+ unsigned long base = hwif->dma_base - (hwif->channel * 8);
+@@ -239,7 +239,7 @@ static int cmd648_ide_dma_end (ide_drive_t *drive)
+ return err;
}
- /**
-@@ -172,14 +172,14 @@ static void ns87415_bmdma_stop(struct ata_queued_cmd *qc)
+-static int cmd64x_ide_dma_end (ide_drive_t *drive)
++static int cmd64x_dma_end(ide_drive_t *drive)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+@@ -256,7 +256,7 @@ static int cmd64x_ide_dma_end (ide_drive_t *drive)
+ return err;
}
- /**
-- * 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 int cmd648_ide_dma_test_irq (ide_drive_t *drive)
++static int cmd648_dma_test_irq(ide_drive_t *drive)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
+ unsigned long base = hwif->dma_base - (hwif->channel * 8);
+@@ -279,7 +279,7 @@ static int cmd648_ide_dma_test_irq (ide_drive_t *drive)
+ return 0;
+ }
--static void ns87415_bmdma_irq_clear(struct ata_port *ap)
-+static void ns87415_irq_clear(struct ata_port *ap)
+-static int cmd64x_ide_dma_test_irq (ide_drive_t *drive)
++static int cmd64x_dma_test_irq(ide_drive_t *drive)
{
- void __iomem *mmio = ap->ioaddr.bmdma_addr;
+ ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+@@ -310,7 +310,7 @@ static int cmd64x_ide_dma_test_irq (ide_drive_t *drive)
+ * event order for DMA transfers.
+ */
-@@ -297,90 +297,32 @@ static u8 ns87560_bmdma_status(struct ata_port *ap)
+-static int cmd646_1_ide_dma_end (ide_drive_t *drive)
++static int cmd646_1_dma_end(ide_drive_t *drive)
{
- return ns87560_read_buggy(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ ide_hwif_t *hwif = HWIF(drive);
+ u8 dma_stat = 0, dma_cmd = 0;
+@@ -370,7 +370,7 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha
+ return 0;
}
--
--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 u8 __devinit ata66_cmd64x(ide_hwif_t *hwif)
++static u8 __devinit cmd64x_cable_detect(ide_hwif_t *hwif)
+ {
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ u8 bmidecsr = 0, mask = hwif->channel ? 0x02 : 0x01;
+@@ -385,91 +385,85 @@ static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif)
+ }
+ }
--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,
+-static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
+-{
+- struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-- .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,
+- hwif->set_pio_mode = &cmd64x_set_pio_mode;
+- hwif->set_dma_mode = &cmd64x_set_dma_mode;
-
- .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,
+- hwif->cable_detect = ata66_cmd64x;
++static const struct ide_port_ops cmd64x_port_ops = {
++ .set_pio_mode = cmd64x_set_pio_mode,
++ .set_dma_mode = cmd64x_set_dma_mode,
++ .cable_detect = cmd64x_cable_detect,
++};
-- .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,
+- if (!hwif->dma_base)
+- return;
++static const struct ide_dma_ops cmd64x_dma_ops = {
++ .dma_host_set = ide_dma_host_set,
++ .dma_setup = ide_dma_setup,
++ .dma_exec_cmd = ide_dma_exec_cmd,
++ .dma_start = ide_dma_start,
++ .dma_end = cmd64x_dma_end,
++ .dma_test_irq = cmd64x_dma_test_irq,
++ .dma_lost_irq = ide_dma_lost_irq,
++ .dma_timeout = ide_dma_timeout,
+};
-- .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
+- /*
+- * UltraDMA only supported on PCI646U and PCI646U2, which
+- * correspond to revisions 0x03, 0x05 and 0x07 respectively.
+- * Actually, although the CMD tech support people won't
+- * tell me the details, the 0x03 revision cannot support
+- * UDMA correctly without hardware modifications, and even
+- * then it only works with Quantum disks due to some
+- * hold time assumptions in the 646U part which are fixed
+- * in the 646U2.
+- *
+- * So we only do UltraDMA on revision 0x05 and 0x07 chipsets.
+- */
+- if (dev->device == PCI_DEVICE_ID_CMD_646 && dev->revision < 5)
+- hwif->ultra_mask = 0x00;
++static const struct ide_dma_ops cmd646_rev1_dma_ops = {
++ .dma_host_set = ide_dma_host_set,
++ .dma_setup = ide_dma_setup,
++ .dma_exec_cmd = ide_dma_exec_cmd,
++ .dma_start = ide_dma_start,
++ .dma_end = cmd646_1_dma_end,
++ .dma_test_irq = ide_dma_test_irq,
++ .dma_lost_irq = ide_dma_lost_irq,
++ .dma_timeout = ide_dma_timeout,
++};
+
+- switch (dev->device) {
+- case PCI_DEVICE_ID_CMD_648:
+- case PCI_DEVICE_ID_CMD_649:
+- alt_irq_bits:
+- hwif->ide_dma_end = &cmd648_ide_dma_end;
+- hwif->ide_dma_test_irq = &cmd648_ide_dma_test_irq;
+- break;
+- case PCI_DEVICE_ID_CMD_646:
+- if (dev->revision == 0x01) {
+- hwif->ide_dma_end = &cmd646_1_ide_dma_end;
+- break;
+- } else if (dev->revision >= 0x03)
+- goto alt_irq_bits;
+- /* fall thru */
+- default:
+- hwif->ide_dma_end = &cmd64x_ide_dma_end;
+- hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq;
+- break;
+- }
+-}
++static const struct ide_dma_ops cmd648_dma_ops = {
++ .dma_host_set = ide_dma_host_set,
++ .dma_setup = ide_dma_setup,
++ .dma_exec_cmd = ide_dma_exec_cmd,
++ .dma_start = ide_dma_start,
++ .dma_end = cmd648_dma_end,
++ .dma_test_irq = cmd648_dma_test_irq,
++ .dma_lost_irq = ide_dma_lost_irq,
++ .dma_timeout = ide_dma_timeout,
++};
- 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),
- };
+ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
+ { /* 0 */
+ .name = "CMD643",
+ .init_chipset = init_chipset_cmd64x,
+- .init_hwif = init_hwif_cmd64x,
+ .enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
++ .port_ops = &cmd64x_port_ops,
++ .dma_ops = &cmd64x_dma_ops,
+ .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 */
+ },{ /* 1 */
+ .name = "CMD646",
+ .init_chipset = init_chipset_cmd64x,
+- .init_hwif = init_hwif_cmd64x,
+ .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
+ .chipset = ide_cmd646,
+- .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
++ .port_ops = &cmd64x_port_ops,
++ .dma_ops = &cmd648_dma_ops,
++ .host_flags = IDE_HFLAG_ABUSE_PREFETCH,
+ .pio_mask = ATA_PIO5,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
+ },{ /* 2 */
+ .name = "CMD648",
+ .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,
++ .port_ops = &cmd64x_port_ops,
++ .dma_ops = &cmd648_dma_ops,
++ .host_flags = IDE_HFLAG_ABUSE_PREFETCH,
+ .pio_mask = ATA_PIO5,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA4,
+ },{ /* 3 */
+ .name = "CMD649",
+ .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,
++ .port_ops = &cmd64x_port_ops,
++ .dma_ops = &cmd648_dma_ops,
++ .host_flags = IDE_HFLAG_ABUSE_PREFETCH,
+ .pio_mask = ATA_PIO5,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
+@@ -483,12 +477,35 @@ static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_devic
+ d = cmd64x_chipsets[idx];
-@@ -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);
+- /*
+- * The original PCI0646 didn't have the primary channel enable bit,
+- * it appeared starting with PCI0646U (i.e. revision ID 3).
+- */
+- if (idx == 1 && dev->revision < 3)
+- d.enablebits[0].reg = 0;
++ if (idx == 1) {
++ /*
++ * UltraDMA only supported on PCI646U and PCI646U2, which
++ * correspond to revisions 0x03, 0x05 and 0x07 respectively.
++ * Actually, although the CMD tech support people won't
++ * tell me the details, the 0x03 revision cannot support
++ * UDMA correctly without hardware modifications, and even
++ * then it only works with Quantum disks due to some
++ * hold time assumptions in the 646U part which are fixed
++ * in the 646U2.
++ *
++ * So we only do UltraDMA on revision 0x05 and 0x07 chipsets.
++ */
++ if (dev->revision < 5) {
++ d.udma_mask = 0x00;
++ /*
++ * The original PCI0646 didn't have the primary
++ * channel enable bit, it appeared starting with
++ * PCI0646U (i.e. revision ID 3).
++ */
++ if (dev->revision < 3) {
++ d.enablebits[0].reg = 0;
++ if (dev->revision == 1)
++ d.dma_ops = &cmd646_rev1_dma_ops;
++ else
++ d.dma_ops = &cmd64x_dma_ops;
++ }
++ }
++ }
+
+ return ide_setup_pci_device(dev, &d);
+ }
+diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
+index 1c163e4..17669a4 100644
+--- a/drivers/ide/pci/cs5520.c
++++ b/drivers/ide/pci/cs5520.c
+@@ -103,27 +103,32 @@ static void cs5520_dma_host_set(ide_drive_t *drive, int on)
+ ide_dma_host_set(drive, on);
}
- 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;
+-static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
+-{
+- hwif->set_pio_mode = &cs5520_set_pio_mode;
+- hwif->set_dma_mode = &cs5520_set_dma_mode;
+-
+- if (hwif->dma_base == 0)
+- return;
++static const struct ide_port_ops cs5520_port_ops = {
++ .set_pio_mode = cs5520_set_pio_mode,
++ .set_dma_mode = cs5520_set_dma_mode,
++};
-- return ata_std_prereset(link, deadline);
+- hwif->dma_host_set = &cs5520_dma_host_set;
-}
++static const struct ide_dma_ops cs5520_dma_ops = {
++ .dma_host_set = cs5520_dma_host_set,
++ .dma_setup = ide_dma_setup,
++ .dma_exec_cmd = ide_dma_exec_cmd,
++ .dma_start = ide_dma_start,
++ .dma_end = __ide_dma_end,
++ .dma_test_irq = ide_dma_test_irq,
++ .dma_lost_irq = ide_dma_lost_irq,
++ .dma_timeout = ide_dma_timeout,
++};
+
+ #define DECLARE_CS_DEV(name_str) \
+ { \
+ .name = name_str, \
+- .init_hwif = init_hwif_cs5520, \
++ .port_ops = &cs5520_port_ops, \
++ .dma_ops = &cs5520_dma_ops, \
+ .host_flags = IDE_HFLAG_ISA_PORTS | \
+ 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..f5534c1 100644
+--- a/drivers/ide/pci/cs5530.c
++++ b/drivers/ide/pci/cs5530.c
+@@ -228,29 +228,27 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
+ unsigned long basereg;
+ u32 d0_timings;
+
+- hwif->set_pio_mode = &cs5530_set_pio_mode;
+- hwif->set_dma_mode = &cs5530_set_dma_mode;
+-
+ basereg = CS5530_BASEREG(hwif);
+ d0_timings = inl(basereg + 0);
+ if (CS5530_BAD_PIO(d0_timings))
+ outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 0);
+ if (CS5530_BAD_PIO(inl(basereg + 8)))
+ outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 8);
-
--/**
-- * oldpiix_pata_error_handler - Probe specified port on PATA host controller
-- * @ap: Port to probe
-- * @classes:
-- *
-- * LOCKING:
-- * None (inherited from caller).
-- */
+- if (hwif->dma_base == 0)
+- return;
-
--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);
+- hwif->udma_filter = cs5530_udma_filter;
}
- /**
-@@ -195,7 +181,7 @@ static void oldpiix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
++static const struct ide_port_ops cs5530_port_ops = {
++ .set_pio_mode = cs5530_set_pio_mode,
++ .set_dma_mode = cs5530_set_dma_mode,
++ .udma_filter = cs5530_udma_filter,
++};
++
+ static const struct ide_port_info cs5530_chipset __devinitdata = {
+ .name = "CS5530",
+ .init_chipset = init_chipset_cs5530,
+ .init_hwif = init_hwif_cs5530,
++ .port_ops = &cs5530_port_ops,
+ .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..99fe91a 100644
+--- a/drivers/ide/pci/cs5535.c
++++ b/drivers/ide/pci/cs5535.c
+@@ -166,27 +166,17 @@ static u8 __devinit cs5535_cable_detect(ide_hwif_t *hwif)
+ return (bit & 1) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
}
- /**
-- * oldpiix_qc_issue_prot - command issue
-+ * oldpiix_qc_issue - command issue
- * @qc: command pending
+-/****
+- * init_hwif_cs5535 - Initialize one ide cannel
+- * @hwif: Channel descriptor
+- *
+- * This gets invoked by the IDE driver once for each channel. It
+- * performs channel-specific pre-initialization before drive probing.
+- *
+- */
+-static void __devinit init_hwif_cs5535(ide_hwif_t *hwif)
+-{
+- hwif->set_pio_mode = &cs5535_set_pio_mode;
+- hwif->set_dma_mode = &cs5535_set_dma_mode;
+-
+- hwif->cable_detect = cs5535_cable_detect;
+-}
++static const struct ide_port_ops cs5535_port_ops = {
++ .set_pio_mode = cs5535_set_pio_mode,
++ .set_dma_mode = cs5535_set_dma_mode,
++ .cable_detect = cs5535_cable_detect,
++};
+
+ static const struct ide_port_info cs5535_chipset __devinitdata = {
+ .name = "CS5535",
+- .init_hwif = init_hwif_cs5535,
++ .port_ops = &cs5535_port_ops,
+ .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..77cc22c 100644
+--- a/drivers/ide/pci/cy82c693.c
++++ b/drivers/ide/pci/cy82c693.c
+@@ -6,7 +6,7 @@
*
- * 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.
+ * 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,10 @@
+ * - 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 +108,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;
--static unsigned int oldpiix_qc_issue_prot(struct ata_queued_cmd *qc)
-+static unsigned int oldpiix_qc_issue(struct ata_queued_cmd *qc)
+- clocks = (time*bus_speed+999)/1000 -1;
++ clocks = (time*bus_speed+999)/1000 - 1;
+
+ if (clocks < 0)
+ clocks = 0;
+@@ -132,11 +130,11 @@ 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)
{
- 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);
+ int clk1, clk2;
+- int bus_speed = system_bus_clock(); /* get speed of PCI bus */
++ int bus_speed = ide_pci_clk ? ide_pci_clk : system_bus_clock();
+
+ /* we don't check against CY82C693's min and max speed,
+ * so you can play with the idebus=xx parameter
+@@ -158,7 +156,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 +184,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 +200,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 +214,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 +240,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 +259,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 +286,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 +297,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 +318,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 +338,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 */
+
+@@ -382,15 +380,6 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c
+ return 0;
+ }
+
+-/*
+- * the init function - called for each ide channel once
+- */
+-static void __devinit init_hwif_cy82c693(ide_hwif_t *hwif)
+-{
+- hwif->set_pio_mode = &cy82c693_set_pio_mode;
+- hwif->set_dma_mode = &cy82c693_set_dma_mode;
+-}
+-
+ static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
+ {
+ static ide_hwif_t *primary;
+@@ -404,14 +393,18 @@ static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
}
-- return ata_qc_issue_prot(qc);
-+ return ata_sff_qc_issue(qc);
}
++static const struct ide_port_ops cy82c693_port_ops = {
++ .set_pio_mode = cy82c693_set_pio_mode,
++ .set_dma_mode = cy82c693_set_dma_mode,
++};
++
+ static const struct ide_port_info cy82c693_chipset __devinitdata = {
+ .name = "CY82C693",
+ .init_chipset = init_chipset_cy82c693,
+ .init_iops = init_iops_cy82c693,
+- .init_hwif = init_hwif_cy82c693,
++ .port_ops = &cy82c693_port_ops,
+ .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 +417,7 @@ static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_dev
- 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),
+ /* 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..b9e4579 100644
+--- a/drivers/ide/pci/delkin_cb.c
++++ b/drivers/ide/pci/delkin_cb.c
+@@ -43,6 +43,10 @@ static const u8 setup[] = {
+ 0x00, 0x00, 0x00, 0x00, 0xa4, 0x83, 0x02, 0x13,
};
--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,
++static const struct ide_port_ops delkin_cb_port_ops = {
++ .quirkproc = ide_undecoded_slave,
++};
++
+ static int __devinit
+ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
+ {
+@@ -71,26 +75,21 @@ 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_init_port_data(hwif, i);
-
-- .port_start = ata_sff_port_start,
-+ .prereset = oldpiix_pre_reset,
- };
++ ide_init_port_data(hwif, i);
+ ide_init_port_hw(hwif, &hw);
+- hwif->quirkproc = &ide_undecoded_slave;
++ hwif->port_ops = &delkin_cb_port_ops;
+ idx[0] = i;
-@@ -289,7 +238,6 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+@@ -110,6 +109,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;
+ }
+@@ -119,9 +119,9 @@ delkin_cb_remove (struct pci_dev *dev)
{
- 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");
+ ide_hwif_t *hwif = pci_get_drvdata(dev);
-- return ata_pci_init_one(pdev, ppi);
-+ return ata_pci_sff_init_one(pdev, ppi, &oldpiix_sht, NULL);
+- if (hwif)
+- ide_unregister(hwif->index, 0, 0);
++ ide_unregister(hwif);
+
++ pci_release_regions(dev);
+ pci_disable_device(dev);
}
- 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;
+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 = {
-- 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)
+ { /* 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..84c36c1 100644
+--- a/drivers/ide/pci/hpt34x.c
++++ b/drivers/ide/pci/hpt34x.c
+@@ -115,11 +115,10 @@ static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev, const cha
+ return dev->irq;
+ }
+
+-static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif)
-{
-- ata_bmdma_drive_eh(ap, opti_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
-+ return ata_sff_prereset(link, deadline);
+- hwif->set_pio_mode = &hpt34x_set_pio_mode;
+- hwif->set_dma_mode = &hpt34x_set_mode;
+-}
++static const struct ide_port_ops hpt34x_port_ops = {
++ .set_pio_mode = hpt34x_set_pio_mode,
++ .set_dma_mode = hpt34x_set_mode,
++};
+
+ #define IDE_HFLAGS_HPT34X \
+ (IDE_HFLAG_NO_ATAPI_DMA | \
+@@ -131,16 +130,14 @@ static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
+ { /* 0 */
+ .name = "HPT343",
+ .init_chipset = init_chipset_hpt34x,
+- .init_hwif = init_hwif_hpt34x,
+- .extra = 16,
+- .host_flags = IDE_HFLAGS_HPT34X,
++ .port_ops = &hpt34x_port_ops,
++ .host_flags = IDE_HFLAGS_HPT34X | IDE_HFLAG_NON_BOOTABLE,
+ .pio_mask = ATA_PIO5,
+ },
+ { /* 1 */
+ .name = "HPT345",
+ .init_chipset = init_chipset_hpt34x,
+- .init_hwif = init_hwif_hpt34x,
+- .extra = 16,
++ .port_ops = &hpt34x_port_ops,
+ .host_flags = IDE_HFLAGS_HPT34X | IDE_HFLAG_OFF_BOARD,
+ .pio_mask = ATA_PIO5,
+ #ifdef CONFIG_HPT34X_AUTODMA
+diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
+index 6357bb6..c929dad 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.ctl_addr);
}
- /**
-@@ -165,58 +150,19 @@ static void opti_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ /*
+@@ -776,7 +776,7 @@ static void hpt366_dma_lost_irq(ide_drive_t *drive)
+ pci_read_config_byte(dev, 0x52, &mcr3);
+ pci_read_config_byte(dev, 0x5a, &scr1);
+ printk("%s: (%s) mcr1=0x%02x, mcr3=0x%02x, scr1=0x%02x\n",
+- drive->name, __FUNCTION__, mcr1, mcr3, scr1);
++ drive->name, __func__, mcr1, mcr3, scr1);
+ if (scr1 & 0x10)
+ pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
+ ide_dma_lost_irq(drive);
+@@ -808,7 +808,7 @@ static void hpt370_irq_timeout(ide_drive_t *drive)
+ hpt370_clear_engine(drive);
}
- 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 void hpt370_ide_dma_start(ide_drive_t *drive)
++static void hpt370_dma_start(ide_drive_t *drive)
+ {
+ #ifdef HPT_RESET_STATE_ENGINE
+ hpt370_clear_engine(drive);
+@@ -816,7 +816,7 @@ static void hpt370_ide_dma_start(ide_drive_t *drive)
+ ide_dma_start(drive);
+ }
- 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 hpt370_ide_dma_end(ide_drive_t *drive)
++static int hpt370_dma_end(ide_drive_t *drive)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
+ u8 dma_stat = inb(hwif->dma_status);
+@@ -838,7 +838,7 @@ static void hpt370_dma_timeout(ide_drive_t *drive)
+ }
- static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ /* returns 1 if DMA IRQ issued, 0 otherwise */
+-static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
++static int hpt374_dma_test_irq(ide_drive_t *drive)
{
- 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");
+ ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+@@ -858,11 +858,11 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
-- return ata_pci_init_one(dev, ppi);
-+ return ata_pci_sff_init_one(dev, ppi, &opti_sht, NULL);
+ if (!drive->waiting_for_dma)
+ printk(KERN_WARNING "%s: (%s) called while not waiting\n",
+- drive->name, __FUNCTION__);
++ drive->name, __func__);
+ return 0;
}
- 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;
+-static int hpt374_ide_dma_end(ide_drive_t *drive)
++static int hpt374_dma_end(ide_drive_t *drive)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+@@ -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);
+ }
-- return ata_std_prereset(link, deadline);
--}
--
--/**
-- * optidma_probe_reset - probe reset
-- * @ap: ATA port
+-/*
+- * Set/get power state for a drive.
+- * NOTE: affects both drives on each channel.
- *
-- * 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.
+- * When we turn the power back on, we need to re-initialize things.
- */
+-#define TRISTATE_BIT 0x8000
-
--static void optidma_error_handler(struct ata_port *ap)
+-static int hpt3xx_busproc(ide_drive_t *drive, int state)
-{
-- 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,
+- 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;
-
-- .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,
+- hwif->bus_state = state;
-
-- .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,
+- /* Grab the status. */
+- pci_read_config_word(dev, mcr_addr, &mcr);
+- pci_read_config_byte(dev, 0x59, &bsr2);
-
-- .bmdma_setup = ata_bmdma_setup,
-- .bmdma_start = ata_bmdma_start,
-- .bmdma_stop = ata_bmdma_stop,
-- .bmdma_status = ata_bmdma_status,
+- /*
+- * 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;
-
-- .qc_prep = ata_qc_prep,
-- .qc_issue = ata_qc_issue_prot,
+- 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;
+- }
-
-- .data_xfer = ata_data_xfer,
+- hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
+- hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- pci_write_config_word(dev, mcr_addr, mcr);
+- pci_write_config_byte(dev, 0x59, bsr2 | resetmask);
+- return 0;
+-}
-
-- .port_start = ata_sff_port_start,
-+ .prereset = optidma_pre_reset,
- };
+ /**
+ * hpt37x_calibrate_dpll - calibrate the DPLL
+ * @dev: PCI device
+@@ -1329,18 +1271,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
+ /* Cache the channel's MISC. control registers' offset */
+ hwif->select_data = hwif->channel ? 0x54 : 0x50;
- 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,
+- hwif->set_pio_mode = &hpt3xx_set_pio_mode;
+- hwif->set_dma_mode = &hpt3xx_set_mode;
-
-- .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,
+- hwif->quirkproc = &hpt3xx_quirkproc;
+- hwif->maskproc = &hpt3xx_maskproc;
+- hwif->busproc = &hpt3xx_busproc;
-
-- .bmdma_setup = ata_bmdma_setup,
-- .bmdma_start = ata_bmdma_start,
-- .bmdma_stop = ata_bmdma_stop,
-- .bmdma_status = ata_bmdma_status,
+- hwif->udma_filter = &hpt3xx_udma_filter;
+- hwif->mdma_filter = &hpt3xx_mdma_filter;
-
-- .qc_prep = ata_qc_prep,
-- .qc_issue = ata_qc_issue_prot,
+- hwif->cable_detect = hpt3xx_cable_detect;
-
-- .data_xfer = ata_data_xfer,
+ /*
+ * HPT3xxN chips have some complications:
+ *
+@@ -1382,29 +1312,19 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
+
+ if (new_mcr != old_mcr)
+ pci_write_config_byte(dev, hwif->select_data + 1, new_mcr);
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- if (hwif->dma_base == 0)
+- return;
-
-- .port_start = ata_sff_port_start,
- };
+- if (chip_type >= HPT374) {
+- hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
+- hwif->ide_dma_end = &hpt374_ide_dma_end;
+- } else if (chip_type >= HPT370) {
+- hwif->dma_start = &hpt370_ide_dma_start;
+- hwif->ide_dma_end = &hpt370_ide_dma_end;
+- hwif->dma_timeout = &hpt370_dma_timeout;
+- } else
+- hwif->dma_lost_irq = &hpt366_dma_lost_irq;
+ }
- /**
-@@ -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 void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
++static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
++ const struct ide_port_info *d)
{
- 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");
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+- u8 masterdma = 0, slavedma = 0;
+- u8 dma_new = 0, dma_old = 0;
+- unsigned long flags;
++ unsigned long flags, base = ide_pci_dma_base(hwif, d);
++ u8 dma_old, dma_new, masterdma = 0, slavedma = 0;
-+ rc = pcim_enable_device(dev);
-+ if (rc)
-+ return rc;
+- dma_old = inb(dmabase + 2);
++ if (base == 0 || ide_pci_set_master(dev, d->name) < 0)
++ return -1;
+
- /* 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;
++ dma_old = inb(base + 2);
-- return ata_pci_init_one(dev, ppi);
-+ return ata_pci_sff_init_one(dev, ppi, &optidma_sht, NULL);
+ local_irq_save(flags);
+
+@@ -1415,11 +1335,21 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
+ if (masterdma & 0x30) dma_new |= 0x20;
+ if ( slavedma & 0x30) dma_new |= 0x40;
+ if (dma_new != dma_old)
+- outb(dma_new, dmabase + 2);
++ outb(dma_new, base + 2);
+
+ local_irq_restore(flags);
+
+- ide_setup_dma(hwif, dmabase);
++ printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n",
++ hwif->name, base, base + 7);
++
++ hwif->extra_base = base + (hwif->channel ? 8 : 16);
++
++ if (ide_allocate_dma_engine(hwif))
++ return -1;
++
++ ide_setup_dma(hwif, base);
++
++ return 0;
}
- 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 void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2)
+@@ -1475,6 +1405,49 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
+ IDE_HFLAG_ABUSE_SET_DMA_MODE | \
+ IDE_HFLAG_OFF_BOARD)
++static const struct ide_port_ops hpt3xx_port_ops = {
++ .set_pio_mode = hpt3xx_set_pio_mode,
++ .set_dma_mode = hpt3xx_set_mode,
++ .quirkproc = hpt3xx_quirkproc,
++ .maskproc = hpt3xx_maskproc,
++ .mdma_filter = hpt3xx_mdma_filter,
++ .udma_filter = hpt3xx_udma_filter,
++ .cable_detect = hpt3xx_cable_detect,
++};
++
++static const struct ide_dma_ops hpt37x_dma_ops = {
++ .dma_host_set = ide_dma_host_set,
++ .dma_setup = ide_dma_setup,
++ .dma_exec_cmd = ide_dma_exec_cmd,
++ .dma_start = ide_dma_start,
++ .dma_end = hpt374_dma_end,
++ .dma_test_irq = hpt374_dma_test_irq,
++ .dma_lost_irq = ide_dma_lost_irq,
++ .dma_timeout = ide_dma_timeout,
++};
++
++static const struct ide_dma_ops hpt370_dma_ops = {
++ .dma_host_set = ide_dma_host_set,
++ .dma_setup = ide_dma_setup,
++ .dma_exec_cmd = ide_dma_exec_cmd,
++ .dma_start = hpt370_dma_start,
++ .dma_end = hpt370_dma_end,
++ .dma_test_irq = ide_dma_test_irq,
++ .dma_lost_irq = ide_dma_lost_irq,
++ .dma_timeout = hpt370_dma_timeout,
++};
++
++static const struct ide_dma_ops hpt36x_dma_ops = {
++ .dma_host_set = ide_dma_host_set,
++ .dma_setup = ide_dma_setup,
++ .dma_exec_cmd = ide_dma_exec_cmd,
++ .dma_start = ide_dma_start,
++ .dma_end = __ide_dma_end,
++ .dma_test_irq = ide_dma_test_irq,
++ .dma_lost_irq = hpt366_dma_lost_irq,
++ .dma_timeout = ide_dma_timeout,
++};
++
+ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+ { /* 0 */
+ .name = "HPT36x",
+@@ -1488,7 +1461,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+ * Bit 4 is for the primary channel, bit 5 for the secondary.
+ */
+ .enablebits = {{0x50,0x10,0x10}, {0x54,0x04,0x04}},
+- .extra = 240,
++ .port_ops = &hpt3xx_port_ops,
++ .dma_ops = &hpt36x_dma_ops,
+ .host_flags = IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+@@ -1498,7 +1472,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+ .init_hwif = init_hwif_hpt366,
+ .init_dma = init_dma_hpt366,
+ .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+- .extra = 240,
++ .port_ops = &hpt3xx_port_ops,
++ .dma_ops = &hpt37x_dma_ops,
+ .host_flags = IDE_HFLAGS_HPT3XX,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+@@ -1508,7 +1483,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+ .init_hwif = init_hwif_hpt366,
+ .init_dma = init_dma_hpt366,
+ .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+- .extra = 240,
++ .port_ops = &hpt3xx_port_ops,
++ .dma_ops = &hpt37x_dma_ops,
+ .host_flags = IDE_HFLAGS_HPT3XX,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+@@ -1518,7 +1494,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+ .init_hwif = init_hwif_hpt366,
+ .init_dma = init_dma_hpt366,
+ .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+- .extra = 240,
++ .port_ops = &hpt3xx_port_ops,
++ .dma_ops = &hpt37x_dma_ops,
+ .host_flags = IDE_HFLAGS_HPT3XX,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+@@ -1529,7 +1506,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+ .init_dma = init_dma_hpt366,
+ .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ .udma_mask = ATA_UDMA5,
+- .extra = 240,
++ .port_ops = &hpt3xx_port_ops,
++ .dma_ops = &hpt37x_dma_ops,
+ .host_flags = IDE_HFLAGS_HPT3XX,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+@@ -1539,7 +1517,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+ .init_hwif = init_hwif_hpt366,
+ .init_dma = init_dma_hpt366,
+ .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+- .extra = 240,
++ .port_ops = &hpt3xx_port_ops,
++ .dma_ops = &hpt37x_dma_ops,
+ .host_flags = IDE_HFLAGS_HPT3XX,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+@@ -1602,6 +1581,10 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic
+ d.name = info->chip_name;
+ d.udma_mask = info->udma_mask;
+
++ /* fixup ->dma_ops for HPT370/HPT370A */
++ if (info == &hpt370 || info == &hpt370a)
++ d.dma_ops = &hpt370_dma_ops;
++
+ pci_set_drvdata(dev, (void *)info);
- 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),
- };
+ if (info == &hpt36x || info == &hpt374)
+@@ -1616,7 +1599,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;
+ }
- 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,
- };
+ ret = ide_setup_pci_devices(dev, dev2, &d);
+diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
+index e3427ea..9053c87 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 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,
+- 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);
+@@ -150,29 +149,18 @@ static u8 __devinit it8213_cable_detect(ide_hwif_t *hwif)
+ return (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+ }
+
+-/**
+- * init_hwif_it8213 - set up hwif structs
+- * @hwif: interface to set up
+- *
+- * We do the basic set up of the interface structure.
+- */
-
-- .data_xfer = ata_data_xfer_8bit,
+-static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
+-{
+- hwif->set_dma_mode = &it8213_set_dma_mode;
+- hwif->set_pio_mode = &it8213_set_pio_mode;
-
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- hwif->cable_detect = it8213_cable_detect;
+-}
-
-- .port_start = ata_sff_port_start,
-+ .set_mode = pcmcia_set_mode_8bit,
- };
++static const struct ide_port_ops it8213_port_ops = {
++ .set_pio_mode = it8213_set_pio_mode,
++ .set_dma_mode = it8213_set_dma_mode,
++ .cable_detect = it8213_cable_detect,
++};
- #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);
+ #define DECLARE_ITE_DEV(name_str) \
+ { \
+ .name = name_str, \
+- .init_hwif = init_hwif_it8213, \
+- .enablebits = {{0x41,0x80,0x80}}, \
+- .host_flags = IDE_HFLAG_SINGLE | \
+- IDE_HFLAG_BOOTABLE, \
++ .enablebits = { {0x41, 0x80, 0x80} }, \
++ .port_ops = &it8213_port_ops, \
++ .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..6ab0411 100644
+--- a/drivers/ide/pci/it821x.c
++++ b/drivers/ide/pci/it821x.c
+@@ -418,7 +418,7 @@ static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ }
- ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io_base, ctl_base);
- }
+ /**
+- * ata66_it821x - check for 80 pin cable
++ * it821x_cable_detect - cable detection
+ * @hwif: interface to check
+ *
+ * Check for the presence of an ATA66 capable cable on the
+@@ -426,7 +426,7 @@ static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ * the needed logic onboard.
+ */
- /* 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 u8 __devinit ata66_it821x(ide_hwif_t *hwif)
++static u8 __devinit it821x_cable_detect(ide_hwif_t *hwif)
+ {
+ /* The reference driver also only does disk side */
+ return ATA_CBL_PATA80;
+@@ -511,6 +511,11 @@ static void __devinit it821x_quirkproc(ide_drive_t *drive)
- 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 ide_dma_ops it821x_pass_through_dma_ops = {
++ .dma_start = it821x_dma_start,
++ .dma_end = it821x_dma_end,
++};
++
+ /**
+ * init_hwif_it821x - set up hwif structs
+ * @hwif: interface to set up
+@@ -523,16 +528,10 @@ 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;
- 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,
+- hwif->quirkproc = &it821x_quirkproc;
-
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- if (idev == NULL) {
+- printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n");
+- return;
+- }
-
-- .port_start = ata_sff_port_start,
-+ .prereset = pdc2027x_prereset,
- };
+ ide_set_hwifdata(hwif, idev);
- 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,
- };
+ pci_read_config_byte(dev, 0x50, &conf);
+@@ -567,17 +566,11 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
+ }
- 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);
--}
+ if (idev->smart == 0) {
+- hwif->set_pio_mode = &it821x_set_pio_mode;
+- hwif->set_dma_mode = &it821x_set_dma_mode;
-
--/**
-- * 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).
-- */
+ /* MWDMA/PIO clock switching for pass through mode */
+- hwif->dma_start = &it821x_dma_start;
+- hwif->ide_dma_end = &it821x_dma_end;
++ hwif->dma_ops = &it821x_pass_through_dma_ops;
+ } else
+ hwif->host_flags |= IDE_HFLAG_NO_SET_MODE;
+
+- hwif->cable_detect = ata66_it821x;
-
--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);
+ if (hwif->dma_base == 0)
+ return;
+
+@@ -617,13 +610,20 @@ static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const cha
+ return 0;
}
- /**
-@@ -342,7 +265,7 @@ static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long
- struct ata_device *pair = ata_dev_pair(adev);
++static const struct ide_port_ops it821x_port_ops = {
++ /* it821x_set_{pio,dma}_mode() are only used in pass-through mode */
++ .set_pio_mode = it821x_set_pio_mode,
++ .set_dma_mode = it821x_set_dma_mode,
++ .quirkproc = it821x_quirkproc,
++ .cable_detect = it821x_cable_detect,
++};
- 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);
+ #define DECLARE_ITE_DEV(name_str) \
+ { \
+ .name = name_str, \
+ .init_chipset = init_chipset_it821x, \
+ .init_hwif = init_hwif_it821x, \
+- .host_flags = IDE_HFLAG_BOOTABLE, \
++ .port_ops = &it821x_port_ops, \
+ .pio_mask = ATA_PIO4, \
+ }
- /* 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));
+@@ -642,6 +642,22 @@ static const struct ide_port_info it821x_chipsets[] __devinitdata = {
-- return ata_pci_default_filter(adev, mask);
-+ return ata_bmdma_mode_filter(adev, mask);
+ 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..96ef739 100644
+--- a/drivers/ide/pci/jmicron.c
++++ b/drivers/ide/pci/jmicron.c
+@@ -19,13 +19,13 @@ typedef enum {
+ } port_type;
+
/**
-@@ -836,8 +759,8 @@ static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_de
- return -EIO;
+- * ata66_jmicron - Cable check
++ * jmicron_cable_detect - cable detection
+ * @hwif: IDE port
+ *
+ * Returns the cable type.
+ */
- 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);
- }
+-static u8 __devinit ata66_jmicron(ide_hwif_t *hwif)
++static u8 __devinit jmicron_cable_detect(ide_hwif_t *hwif)
+ {
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
- /**
-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)
+@@ -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;
+@@ -96,26 +95,16 @@ static void jmicron_set_dma_mode(ide_drive_t *drive, const u8 mode)
+ {
}
- 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,
+-/**
+- * init_hwif_jmicron - set up hwif structs
+- * @hwif: interface to set up
+- *
+- * Minimal set up is required for the Jmicron hardware.
+- */
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+-static void __devinit init_hwif_jmicron(ide_hwif_t *hwif)
+-{
+- hwif->set_pio_mode = &jmicron_set_pio_mode;
+- hwif->set_dma_mode = &jmicron_set_dma_mode;
-
-- .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,
- };
+- hwif->cable_detect = ata66_jmicron;
+-}
++static const struct ide_port_ops jmicron_port_ops = {
++ .set_pio_mode = jmicron_set_pio_mode,
++ .set_dma_mode = jmicron_set_dma_mode,
++ .cable_detect = jmicron_cable_detect,
++};
- 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,
+ 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 } },
++ .port_ops = &jmicron_port_ops,
+ .pio_mask = ATA_PIO5,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA6,
+diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
+index bf0d3b2..fec4955 100644
+--- a/drivers/ide/pci/ns87415.c
++++ b/drivers/ide/pci/ns87415.c
+@@ -63,6 +63,48 @@ static u8 superio_ide_inb (unsigned long port)
+ return inb(port);
+ }
+
++static void superio_tf_read(ide_drive_t *drive, ide_task_t *task)
++{
++ struct ide_io_ports *io_ports = &drive->hwif->io_ports;
++ struct ide_taskfile *tf = &task->tf;
+
-+ .check_atapi_dma = pdc2026x_check_atapi_dma,
-+ .bmdma_start = pdc2026x_bmdma_start,
-+ .bmdma_stop = pdc2026x_bmdma_stop,
++ if (task->tf_flags & IDE_TFLAG_IN_DATA) {
++ u16 data = inw(io_ports->data_addr);
+
-+ .cable_detect = pdc2026x_cable_detect,
-+ .dev_config = pdc2026x_dev_config,
++ tf->data = data & 0xff;
++ tf->hob_data = (data >> 8) & 0xff;
++ }
+
-+ .port_start = pdc2026x_port_start,
- };
++ /* be sure we're looking at the low order bits */
++ outb(drive->ctl & ~0x80, io_ports->ctl_addr);
++
++ if (task->tf_flags & IDE_TFLAG_IN_NSECT)
++ tf->nsect = inb(io_ports->nsect_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_LBAL)
++ tf->lbal = inb(io_ports->lbal_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_LBAM)
++ tf->lbam = inb(io_ports->lbam_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_LBAH)
++ tf->lbah = inb(io_ports->lbah_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
++ tf->device = superio_ide_inb(io_ports->device_addr);
++
++ if (task->tf_flags & IDE_TFLAG_LBA48) {
++ outb(drive->ctl | 0x80, io_ports->ctl_addr);
++
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
++ tf->hob_feature = inb(io_ports->feature_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
++ tf->hob_nsect = inb(io_ports->nsect_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
++ tf->hob_lbal = inb(io_ports->lbal_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
++ tf->hob_lbam = inb(io_ports->lbam_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
++ tf->hob_lbah = inb(io_ports->lbah_addr);
++ }
++}
++
+ static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
+ {
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
+@@ -72,14 +114,16 @@ static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
+ base = pci_resource_start(pdev, port * 2) & ~3;
+ dmabase = pci_resource_start(pdev, 4) & ~3;
- static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+- superio_ide_status[port] = base + IDE_STATUS_OFFSET;
+- superio_ide_select[port] = base + IDE_SELECT_OFFSET;
++ superio_ide_status[port] = base + 7;
++ superio_ide_select[port] = base + 6;
+ superio_ide_dma_status[port] = dmabase + (!port ? 2 : 0xa);
+
+ /* Clear error/interrupt, enable dma */
+ tmp = superio_ide_inb(superio_ide_dma_status[port]);
+ outb(tmp | 0x66, superio_ide_dma_status[port]);
+
++ hwif->tf_read = superio_tf_read;
++
+ /* We need to override inb to workaround a SuperIO errata */
+ hwif->INB = superio_ide_inb;
+ }
+@@ -150,7 +194,7 @@ static void ns87415_selectproc (ide_drive_t *drive)
+ ns87415_prepare_drive (drive, drive->using_dma);
+ }
+
+-static int ns87415_ide_dma_end (ide_drive_t *drive)
++static int ns87415_dma_end(ide_drive_t *drive)
{
- 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);
+ ide_hwif_t *hwif = HWIF(drive);
+ u8 dma_stat = 0, dma_cmd = 0;
+@@ -170,7 +214,7 @@ static int ns87415_ide_dma_end (ide_drive_t *drive)
+ return (dma_stat & 7) != 4;
}
- 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 ns87415_ide_dma_setup(ide_drive_t *drive)
++static int ns87415_dma_setup(ide_drive_t *drive)
+ {
+ /* select DMA xfer */
+ ns87415_prepare_drive(drive, 1);
+@@ -181,6 +225,10 @@ static int ns87415_ide_dma_setup(ide_drive_t *drive)
+ return 1;
}
--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),
- };
++#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);
+@@ -191,8 +239,6 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
+ u8 stat;
+ #endif
- 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,
+- hwif->selectproc = &ns87415_selectproc;
-
-- .port_start = ata_dummy_ret0,
-+ .set_mode = pata_platform_set_mode,
-+ .port_start = ATA_OP_NULL,
- };
+ /*
+ * We cannot probe for IRQ: both ports share common IRQ on INTA.
+ * Also, leave IRQ masked during drive probing, to prevent infinite
+@@ -229,12 +275,12 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
+ * SELECT_DRIVE() properly during first ide_probe_port().
+ */
+ timeout = 10000;
+- outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
++ outb(12, hwif->io_ports.ctl_addr);
+ udelay(10);
+- outb(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
++ outb(8, hwif->io_ports.ctl_addr);
+ do {
+ udelay(50);
+- stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
++ stat = hwif->INB(hwif->io_ports.status_addr);
+ if (stat == 0xff)
+ break;
+ } while ((stat & BUSY_STAT) && --timeout);
+@@ -242,7 +288,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
+ }
+
+ if (!using_inta)
+- hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]);
++ hwif->irq = ide_default_irq(hwif->io_ports.data_addr);
+ else if (!hwif->irq && hwif->mate && hwif->mate->irq)
+ hwif->irq = hwif->mate->irq; /* share IRQ with mate */
- 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);
+@@ -250,19 +296,33 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
+ return;
- /* 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)
- }
+ outb(0x60, hwif->dma_status);
+- hwif->dma_setup = &ns87415_ide_dma_setup;
+- hwif->ide_dma_end = &ns87415_ide_dma_end;
+ }
+
++static const struct ide_port_ops ns87415_port_ops = {
++ .selectproc = ns87415_selectproc,
++};
++
++static const struct ide_dma_ops ns87415_dma_ops = {
++ .dma_host_set = ide_dma_host_set,
++ .dma_setup = ns87415_dma_setup,
++ .dma_exec_cmd = ide_dma_exec_cmd,
++ .dma_start = ide_dma_start,
++ .dma_end = ns87415_dma_end,
++ .dma_test_irq = ide_dma_test_irq,
++ .dma_lost_irq = ide_dma_lost_irq,
++ .dma_timeout = ide_dma_timeout,
++};
++
+ static const struct ide_port_info ns87415_chipset __devinitdata = {
+ .name = "NS87415",
+ #ifdef CONFIG_SUPERIO
+ .init_iops = init_iops_ns87415,
+ #endif
+ .init_hwif = init_hwif_ns87415,
++ .port_ops = &ns87415_port_ops,
++ .dma_ops = &ns87415_dma_ops,
+ .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+- IDE_HFLAG_NO_ATAPI_DMA |
+- IDE_HFLAG_BOOTABLE,
++ IDE_HFLAG_NO_ATAPI_DMA,
+ };
- /**
-- * qdi_qc_issue_prot - command issue
-+ * qdi_qc_issue - command issue
- * @qc: command pending
+ 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..6e99080 100644
+--- a/drivers/ide/pci/opti621.c
++++ b/drivers/ide/pci/opti621.c
+@@ -53,13 +53,12 @@
+ * If you then set the second drive to another PIO, the old value
+ * (automatically selected) will be overrided by yours.
+ * There is a 25/33MHz switch in configuration
+- * register, but driver is written for use at any frequency which get
+- * (use idebus=xx to select PCI bus speed).
++ * register, but driver is written for use at any frequency.
*
- * Called when the libata layer is about to issue a command. We wrap
- * this interface so that we can load the correct ATA timings.
- */
+ * 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 +74,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 +207,34 @@ typedef struct pio_clocks_s {
--static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
-+static unsigned int qdi_qc_issue(struct ata_queued_cmd *qc)
+ static void compute_clocks(int pio, pio_clocks_t *clks)
{
- 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);
- }
+- 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;
++ if (pio != PIO_NOT_EXIST) {
++ int adr_setup, data_pls;
++ int bus_speed = ide_pci_clk ? ide_pci_clk : 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;
+ } else {
+ clks->address_time = 1;
+ clks->data_time = 1;
+ clks->recovery_time = 2;
+ /* minimal values */
}
-- 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);
+ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
+@@ -247,8 +251,8 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
- return buflen;
- }
+ /* 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;
- 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),
- };
+ compute_clocks(pio1, &first);
+ compute_clocks(pio2, &second);
+@@ -275,7 +279,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
- 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,
- };
+ spin_lock_irqsave(&opti621_lock, flags);
- 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,
- };
+- reg_base = hwif->io_ports[IDE_DATA_OFFSET];
++ reg_base = hwif->io_ports.data_addr;
- /**
-@@ -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);
+ /* allow Register-B */
+ outb(0xc0, reg_base + CNTRL_REG);
+@@ -321,31 +325,25 @@ static void __devinit opti621_port_init_devs(ide_hwif_t *hwif)
+ hwif->drives[1].drive_data = PIO_DONT_KNOW;
+ }
- ata_port_desc(ap, "cmd %lx ctl %lx", io, ctl);
+-/*
+- * init_hwif_opti621() is called once for each hwif found at boot.
+- */
+-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;
+-}
++static const struct ide_port_ops opti621_port_ops = {
++ .port_init_devs = opti621_port_init_devs,
++ .set_pio_mode = opti621_set_pio_mode,
++};
-@@ -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);
+ 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} },
++ .port_ops = &opti621_port_ops,
++ .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} },
++ .port_ops = &opti621_port_ops,
++ .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/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
+index 1c8cb77..070df8a 100644
+--- a/drivers/ide/pci/pdc202xx_new.c
++++ b/drivers/ide/pci/pdc202xx_new.c
+@@ -34,7 +34,7 @@
+ #undef DEBUG
- /* 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;
+ #ifdef DEBUG
+-#define DBG(fmt, args...) printk("%s: " fmt, __FUNCTION__, ## args)
++#define DBG(fmt, args...) printk("%s: " fmt, __func__, ## args)
+ #else
+ #define DBG(fmt, args...)
+ #endif
+@@ -83,8 +83,8 @@ static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index)
+ {
+ u8 value;
-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)
- }
+- outb(index, hwif->dma_vendor1);
+- value = inb(hwif->dma_vendor3);
++ outb(index, hwif->dma_base + 1);
++ value = inb(hwif->dma_base + 3);
- /**
-- * 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.
+ DBG("index[%02X] value[%02X]\n", index, value);
+ return value;
+@@ -97,8 +97,8 @@ static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index)
*/
-
--static unsigned int radisys_qc_issue_prot(struct ata_queued_cmd *qc)
-+static unsigned int radisys_qc_issue(struct ata_queued_cmd *qc)
+ static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value)
{
- 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);
+- outb(index, hwif->dma_vendor1);
+- outb(value, hwif->dma_vendor3);
++ outb(index, hwif->dma_base + 1);
++ outb(value, hwif->dma_base + 3);
+ DBG("index[%02X] value[%02X]\n", index, value);
}
+@@ -442,17 +442,6 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
+ return dev->irq;
+ }
- 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,
+-static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
+-{
+- hwif->set_pio_mode = &pdcnew_set_pio_mode;
+- hwif->set_dma_mode = &pdcnew_set_dma_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 = radisys_qc_issue_prot,
-- .data_xfer = ata_data_xfer,
+- hwif->quirkproc = &pdcnew_quirkproc;
+- hwif->resetproc = &pdcnew_reset;
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- hwif->cable_detect = pdcnew_cable_detect;
+-}
-
-- .port_start = ata_sff_port_start,
- };
+ static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
+ {
+ struct pci_dev *dev2;
+@@ -476,11 +465,19 @@ static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
+ return NULL;
+ }
++static const struct ide_port_ops pdcnew_port_ops = {
++ .set_pio_mode = pdcnew_set_pio_mode,
++ .set_dma_mode = pdcnew_set_dma_mode,
++ .quirkproc = pdcnew_quirkproc,
++ .resetproc = pdcnew_reset,
++ .cable_detect = pdcnew_cable_detect,
++};
++
+ #define DECLARE_PDCNEW_DEV(name_str, udma) \
+ { \
+ .name = name_str, \
+ .init_chipset = init_chipset_pdcnew, \
+- .init_hwif = init_hwif_pdc202new, \
++ .port_ops = &pdcnew_port_ops, \
+ .host_flags = IDE_HFLAG_POST_SET_MODE | \
+ IDE_HFLAG_ERROR_STOPS_FIFO | \
+ IDE_HFLAG_OFF_BOARD, \
+diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
+index 150422e..fca89ed 100644
+--- a/drivers/ide/pci/pdc202xx_old.c
++++ b/drivers/ide/pci/pdc202xx_old.c
+@@ -115,7 +115,7 @@ static void pdc202xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ pdc202xx_set_mode(drive, XFER_PIO_0 + pio);
+ }
-@@ -254,7 +216,6 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+-static u8 __devinit pdc2026x_old_cable_detect(ide_hwif_t *hwif)
++static u8 __devinit pdc2026x_cable_detect(ide_hwif_t *hwif)
{
- 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);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ u16 CIS, mask = hwif->channel ? (1 << 11) : (1 << 10);
+@@ -163,7 +163,7 @@ static void pdc202xx_quirkproc(ide_drive_t *drive)
+ drive->quirk_list = 0;
}
- 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;
+-static void pdc202xx_old_ide_dma_start(ide_drive_t *drive)
++static void pdc202xx_dma_start(ide_drive_t *drive)
+ {
+ if (drive->current_speed > XFER_UDMA_2)
+ pdc_old_enable_66MHz_clock(drive->hwif);
+@@ -185,7 +185,7 @@ static void pdc202xx_old_ide_dma_start(ide_drive_t *drive)
+ ide_dma_start(drive);
+ }
-- ata_altstatus(ap);
-+ ata_sff_altstatus(ap);
- ndelay(RB500_CF_IO_DELAY);
+-static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
++static int pdc202xx_dma_end(ide_drive_t *drive)
+ {
+ if (drive->media != ide_disk || drive->addressing == 1) {
+ ide_hwif_t *hwif = HWIF(drive);
+@@ -202,7 +202,7 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
+ return __ide_dma_end(drive);
+ }
- 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 int pdc202xx_old_ide_dma_test_irq(ide_drive_t *drive)
++static int pdc202xx_dma_test_irq(ide_drive_t *drive)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
+ unsigned long high_16 = hwif->extra_base - 16;
+@@ -226,26 +226,6 @@ somebody_else:
+ return (dma_stat & 4) == 4; /* return 1 if INTR asserted */
}
--static void rb500_pata_irq_clear(struct ata_port *ap)
+-static void pdc202xx_dma_lost_irq(ide_drive_t *drive)
-{
+- ide_hwif_t *hwif = HWIF(drive);
+-
+- if (hwif->resetproc != NULL)
+- hwif->resetproc(drive);
+-
+- ide_dma_lost_irq(drive);
-}
-
--static int rb500_pata_port_start(struct ata_port *ap)
+-static void pdc202xx_dma_timeout(ide_drive_t *drive)
-{
-- return 0;
+- ide_hwif_t *hwif = HWIF(drive);
+-
+- if (hwif->resetproc != NULL)
+- hwif->resetproc(drive);
+-
+- ide_dma_timeout(drive);
-}
-
- static struct ata_port_operations rb500_pata_port_ops = {
-- .tf_load = ata_tf_load,
-- .tf_read = ata_tf_read,
+ static void pdc202xx_reset_host (ide_hwif_t *hwif)
+ {
+ unsigned long high_16 = hwif->extra_base - 16;
+@@ -271,68 +251,46 @@ static void pdc202xx_reset (ide_drive_t *drive)
+ ide_set_max_pio(drive);
+ }
+
+-static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev,
+- const char *name)
++static void pdc202xx_dma_lost_irq(ide_drive_t *drive)
+ {
+- return dev->irq;
++ pdc202xx_reset(drive);
++ ide_dma_lost_irq(drive);
+ }
+
+-static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif)
++static void pdc202xx_dma_timeout(ide_drive_t *drive)
+ {
+- struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-- .exec_command = rb500_pata_exec_command,
-- .check_status = ata_check_status,
-- .dev_select = ata_std_dev_select,
+- hwif->set_pio_mode = &pdc202xx_set_pio_mode;
+- hwif->set_dma_mode = &pdc202xx_set_mode;
-
-- .data_xfer = rb500_pata_data_xfer,
+- hwif->quirkproc = &pdc202xx_quirkproc;
-
-- .qc_prep = ata_qc_prep,
-- .qc_issue = ata_qc_issue_prot,
+- if (dev->device != PCI_DEVICE_ID_PROMISE_20246) {
+- hwif->resetproc = &pdc202xx_reset;
-
-+ .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,
+- hwif->cable_detect = pdc2026x_old_cable_detect;
+- }
-
-- .irq_handler = rb500_pata_irq_handler,
-- .irq_clear = rb500_pata_irq_clear,
-- .irq_on = ata_irq_on,
+- if (hwif->dma_base == 0)
+- return;
-
-- .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,
+- hwif->dma_lost_irq = &pdc202xx_dma_lost_irq;
+- hwif->dma_timeout = &pdc202xx_dma_timeout;
-
-- .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),
- };
+- if (dev->device != PCI_DEVICE_ID_PROMISE_20246) {
+- hwif->dma_start = &pdc202xx_old_ide_dma_start;
+- hwif->ide_dma_end = &pdc202xx_old_ide_dma_end;
+- }
+- hwif->ide_dma_test_irq = &pdc202xx_old_ide_dma_test_irq;
++ pdc202xx_reset(drive);
++ ide_dma_timeout(drive);
+ }
- /* ------------------------------------------------------------------------ */
-@@ -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;
+-static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase)
++static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev,
++ const char *name)
+ {
++ unsigned long dmabase = pci_resource_start(dev, 4);
+ u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0;
-- ata_std_ports(&ap->ioaddr);
-+ ata_sff_std_ports(&ap->ioaddr);
+- if (hwif->channel) {
+- ide_setup_dma(hwif, dmabase);
+- return;
+- }
++ if (dmabase == 0)
++ goto out;
- 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;
+ udma_speed_flag = inb(dmabase | 0x1f);
+ primary_mode = inb(dmabase | 0x1a);
+ secondary_mode = inb(dmabase | 0x1b);
+ printk(KERN_INFO "%s: (U)DMA Burst Bit %sABLED " \
+ "Primary %s Mode " \
+- "Secondary %s Mode.\n", hwif->cds->name,
++ "Secondary %s Mode.\n", pci_name(dev),
+ (udma_speed_flag & 1) ? "EN" : "DIS",
+ (primary_mode & 1) ? "MASTER" : "PCI",
+ (secondary_mode & 1) ? "MASTER" : "PCI" );
+
+ if (!(udma_speed_flag & 1)) {
+ printk(KERN_INFO "%s: FORCING BURST BIT 0x%02x->0x%02x ",
+- hwif->cds->name, udma_speed_flag,
++ pci_name(dev), udma_speed_flag,
+ (udma_speed_flag|1));
+ outb(udma_speed_flag | 1, dmabase | 0x1f);
+ printk("%sACTIVE\n", (inb(dmabase | 0x1f) & 1) ? "" : "IN");
+ }
+-
+- ide_setup_dma(hwif, dmabase);
++out:
++ return dev->irq;
}
-+/* 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 void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
+@@ -357,13 +315,48 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
+ IDE_HFLAG_ABUSE_SET_DMA_MODE | \
+ IDE_HFLAG_OFF_BOARD)
- 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 const struct ide_port_ops pdc20246_port_ops = {
++ .set_pio_mode = pdc202xx_set_pio_mode,
++ .set_dma_mode = pdc202xx_set_mode,
++ .quirkproc = pdc202xx_quirkproc,
++};
++
++static const struct ide_port_ops pdc2026x_port_ops = {
++ .set_pio_mode = pdc202xx_set_pio_mode,
++ .set_dma_mode = pdc202xx_set_mode,
++ .quirkproc = pdc202xx_quirkproc,
++ .resetproc = pdc202xx_reset,
++ .cable_detect = pdc2026x_cable_detect,
++};
++
++static const struct ide_dma_ops pdc20246_dma_ops = {
++ .dma_host_set = ide_dma_host_set,
++ .dma_setup = ide_dma_setup,
++ .dma_exec_cmd = ide_dma_exec_cmd,
++ .dma_start = ide_dma_start,
++ .dma_end = __ide_dma_end,
++ .dma_test_irq = pdc202xx_dma_test_irq,
++ .dma_lost_irq = pdc202xx_dma_lost_irq,
++ .dma_timeout = pdc202xx_dma_timeout,
++};
++
++static const struct ide_dma_ops pdc2026x_dma_ops = {
++ .dma_host_set = ide_dma_host_set,
++ .dma_setup = ide_dma_setup,
++ .dma_exec_cmd = ide_dma_exec_cmd,
++ .dma_start = pdc202xx_dma_start,
++ .dma_end = pdc202xx_dma_end,
++ .dma_test_irq = pdc202xx_dma_test_irq,
++ .dma_lost_irq = pdc202xx_dma_lost_irq,
++ .dma_timeout = pdc202xx_dma_timeout,
++};
++
+ #define DECLARE_PDC2026X_DEV(name_str, udma, extra_flags) \
+ { \
+ .name = name_str, \
+ .init_chipset = init_chipset_pdc202xx, \
+- .init_hwif = init_hwif_pdc202xx, \
+- .init_dma = init_dma_pdc202xx, \
+- .extra = 48, \
++ .port_ops = &pdc2026x_port_ops, \
++ .dma_ops = &pdc2026x_dma_ops, \
+ .host_flags = IDE_HFLAGS_PDC202XX | extra_flags, \
+ .pio_mask = ATA_PIO4, \
+ .mwdma_mask = ATA_MWDMA2, \
+@@ -374,9 +367,8 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
+ { /* 0 */
+ .name = "PDC20246",
+ .init_chipset = init_chipset_pdc202xx,
+- .init_hwif = init_hwif_pdc202xx,
+- .init_dma = init_dma_pdc202xx,
+- .extra = 16,
++ .port_ops = &pdc20246_port_ops,
++ .dma_ops = &pdc20246_dma_ops,
+ .host_flags = IDE_HFLAGS_PDC202XX,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
+index decef0f..f04738d 100644
+--- a/drivers/ide/pci/piix.c
++++ b/drivers/ide/pci/piix.c
+@@ -250,6 +250,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, }
};
+@@ -285,11 +286,6 @@ static u8 __devinit piix_cable_detect(ide_hwif_t *hwif)
- 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,
+ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
+ {
+- hwif->set_pio_mode = &piix_set_pio_mode;
+- hwif->set_dma_mode = &piix_set_dma_mode;
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- hwif->cable_detect = piix_cable_detect;
-
-- .port_start = ata_sff_port_start,
-+ .set_mode = rz1000_set_mode,
- };
+ if (!hwif->dma_base)
+ return;
- 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");
+@@ -306,10 +302,16 @@ static void __devinit init_hwif_ich(ide_hwif_t *hwif)
+ hwif->ide_dma_clear_irq = &piix_dma_clear_irq;
+ }
- if (rz1000_fifo_disable(pdev) == 0)
-- return ata_pci_init_one(pdev, ppi);
-+ return ata_pci_sff_init_one(pdev, ppi, &rz1000_sht, NULL);
++static const struct ide_port_ops piix_port_ops = {
++ .set_pio_mode = piix_set_pio_mode,
++ .set_dma_mode = piix_set_dma_mode,
++ .cable_detect = piix_cable_detect,
++};
++
+ #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
- 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)
- }
+ #define DECLARE_PIIX_DEV(name_str, udma) \
+@@ -317,6 +319,7 @@ static void __devinit init_hwif_ich(ide_hwif_t *hwif)
+ .name = name_str, \
+ .init_hwif = init_hwif_piix, \
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
++ .port_ops = &piix_port_ops, \
+ .host_flags = IDE_HFLAGS_PIIX, \
+ .pio_mask = ATA_PIO4, \
+ .swdma_mask = ATA_SWDMA2_ONLY, \
+@@ -330,6 +333,7 @@ static void __devinit init_hwif_ich(ide_hwif_t *hwif)
+ .init_chipset = init_chipset_ich, \
+ .init_hwif = init_hwif_ich, \
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
++ .port_ops = &piix_port_ops, \
+ .host_flags = IDE_HFLAGS_PIIX, \
+ .pio_mask = ATA_PIO4, \
+ .swdma_mask = ATA_SWDMA2_ONLY, \
+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,
+ };
- /**
-- * sc1200_qc_issue_prot - command issue
-+ * sc1200_qc_issue - command issue
- * @qc: command pending
+ 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..14c787b 100644
+--- a/drivers/ide/pci/sc1200.c
++++ b/drivers/ide/pci/sc1200.c
+@@ -165,7 +165,7 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
*
- * 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.
+ * returns 1 on error, 0 otherwise
*/
-
--static unsigned int sc1200_qc_issue_prot(struct ata_queued_cmd *qc)
-+static unsigned int sc1200_qc_issue(struct ata_queued_cmd *qc)
+-static int sc1200_ide_dma_end (ide_drive_t *drive)
++static int sc1200_dma_end(ide_drive_t *drive)
{
- 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);
+ ide_hwif_t *hwif = HWIF(drive);
+ unsigned long dma_base = hwif->dma_base;
+@@ -214,7 +214,7 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ printk("SC1200: %s: changing (U)DMA mode\n", drive->name);
+ ide_dma_off_quietly(drive);
+ if (ide_set_dma_mode(drive, mode) == 0 && drive->using_dma)
+- hwif->dma_host_set(drive, 1);
++ hwif->dma_ops->dma_host_set(drive, 1);
+ return;
}
-- return ata_qc_issue_prot(qc);
-+ return ata_sff_qc_issue(qc);
+@@ -286,29 +286,30 @@ static int sc1200_resume (struct pci_dev *dev)
}
+ #endif
- 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,
+-/*
+- * This gets invoked by the IDE driver once for each channel,
+- * and performs channel-specific pre-initialization before drive probing.
+- */
+-static void __devinit init_hwif_sc1200 (ide_hwif_t *hwif)
+-{
+- hwif->set_pio_mode = &sc1200_set_pio_mode;
+- hwif->set_dma_mode = &sc1200_set_dma_mode;
-
-- .port_start = ata_sff_port_start,
- };
+- if (hwif->dma_base == 0)
+- return;
++static const struct ide_port_ops sc1200_port_ops = {
++ .set_pio_mode = sc1200_set_pio_mode,
++ .set_dma_mode = sc1200_set_dma_mode,
++ .udma_filter = sc1200_udma_filter,
++};
+
+- hwif->udma_filter = sc1200_udma_filter;
+- hwif->ide_dma_end = &sc1200_ide_dma_end;
+-}
++static const struct ide_dma_ops sc1200_dma_ops = {
++ .dma_host_set = ide_dma_host_set,
++ .dma_setup = ide_dma_setup,
++ .dma_exec_cmd = ide_dma_exec_cmd,
++ .dma_start = ide_dma_start,
++ .dma_end = sc1200_dma_end,
++ .dma_test_irq = ide_dma_test_irq,
++ .dma_lost_irq = ide_dma_lost_irq,
++ .dma_timeout = ide_dma_timeout,
++};
+
+ static const struct ide_port_info sc1200_chipset __devinitdata = {
+ .name = "SC1200",
+- .init_hwif = init_hwif_sc1200,
++ .port_ops = &sc1200_port_ops,
++ .dma_ops = &sc1200_dma_ops,
+ .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..910fb00 100644
+--- a/drivers/ide/pci/scc_pata.c
++++ b/drivers/ide/pci/scc_pata.c
+@@ -65,7 +65,7 @@
- /**
-@@ -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 };
+ 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];
-- return ata_pci_init_one(dev, ppi);
-+ return ata_pci_sff_init_one(dev, ppi, &sc1200_sht, NULL);
+ /* PIO transfer mode table */
+@@ -126,12 +126,6 @@ static u8 scc_ide_inb(unsigned long port)
+ return (u8)data;
}
- 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);
+-static u16 scc_ide_inw(unsigned long port)
+-{
+- u32 data = in_be32((void*)port);
+- return (u16)data;
+-}
+-
+ static void scc_ide_insw(unsigned long port, void *addr, u32 count)
+ {
+ u16 *ptr = (u16 *)addr;
+@@ -154,11 +148,6 @@ static void scc_ide_outb(u8 addr, unsigned long port)
+ out_be32((void*)port, addr);
}
- /**
-@@ -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_ide_outw(u16 addr, unsigned long port)
+-{
+- out_be32((void*)port, addr);
+-}
+-
+ static void
+ scc_ide_outbsync(ide_drive_t * drive, u8 addr, unsigned long port)
+ {
+@@ -271,6 +260,20 @@ static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ out_be32((void __iomem *)udenvt_port, reg);
+ }
- 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_dma_host_set(ide_drive_t *drive, int on)
++{
++ ide_hwif_t *hwif = drive->hwif;
++ u8 unit = (drive->select.b.unit & 0x01);
++ u8 dma_stat = scc_ide_inb(hwif->dma_status);
++
++ if (on)
++ dma_stat |= (1 << (5 + unit));
++ else
++ dma_stat &= ~(1 << (5 + unit));
++
++ scc_ide_outb(dma_stat, hwif->dma_status);
++}
++
+ /**
+ * scc_ide_dma_setup - begin a DMA phase
+ * @drive: target device
+@@ -301,7 +304,7 @@ static int scc_dma_setup(ide_drive_t *drive)
+ }
- 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);
+ /* PRD table */
+- out_be32((void __iomem *)hwif->dma_prdtable, hwif->dmatable_dma);
++ out_be32((void __iomem *)(hwif->dma_base + 8), hwif->dmatable_dma);
- out_be32(ap->ioaddr.command_addr, tf->command);
-- ata_pause(ap);
-+ ata_sff_pause(ap);
+ /* specify r/w */
+ out_be32((void __iomem *)hwif->dma_command, reading);
+@@ -315,16 +318,48 @@ static int scc_dma_setup(ide_drive_t *drive)
+ return 0;
}
- /**
-@@ -396,14 +396,14 @@ static u8 scc_check_altstatus (struct ata_port *ap)
- }
++static void scc_dma_start(ide_drive_t *drive)
++{
++ ide_hwif_t *hwif = drive->hwif;
++ u8 dma_cmd = scc_ide_inb(hwif->dma_command);
++
++ /* start DMA */
++ scc_ide_outb(dma_cmd | 1, hwif->dma_command);
++ hwif->dma = 1;
++ wmb();
++}
++
++static int __scc_dma_end(ide_drive_t *drive)
++{
++ ide_hwif_t *hwif = drive->hwif;
++ u8 dma_stat, dma_cmd;
++
++ drive->waiting_for_dma = 0;
++ /* get DMA command mode */
++ dma_cmd = scc_ide_inb(hwif->dma_command);
++ /* stop DMA */
++ scc_ide_outb(dma_cmd & ~1, hwif->dma_command);
++ /* get DMA status */
++ dma_stat = scc_ide_inb(hwif->dma_status);
++ /* clear the INTR & ERROR bits */
++ scc_ide_outb(dma_stat | 6, hwif->dma_status);
++ /* purge DMA mappings */
++ ide_destroy_dmatable(drive);
++ /* verify good DMA status */
++ hwif->dma = 0;
++ wmb();
++ return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
++}
/**
-- * 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
+- * scc_ide_dma_end - Stop DMA
++ * scc_dma_end - Stop DMA
+ * @drive: IDE drive
*
-- * Note: Original code is ata_std_dev_select().
-+ * Note: Original code is ata_sff_dev_select().
+ * Check and clear INT Status register.
+- * Then call __ide_dma_end().
++ * Then call __scc_dma_end().
*/
--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)
+-static int scc_ide_dma_end(ide_drive_t * drive)
++static int scc_dma_end(ide_drive_t *drive)
{
- u8 tmp;
+ ide_hwif_t *hwif = HWIF(drive);
+ unsigned long intsts_port = hwif->dma_base + 0x014;
+@@ -334,7 +369,8 @@ static int scc_ide_dma_end(ide_drive_t * drive)
-@@ -413,7 +413,7 @@ static void scc_std_dev_select (struct ata_port *ap, unsigned int device)
- tmp = ATA_DEVICE_OBS | ATA_DEV1;
+ /* 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.ctl_addr)
++ & ERR_STAT) &&
+ drive->media == ide_disk && drive->current_speed > XFER_UDMA_4) {
+ reg = in_be32((void __iomem *)intsts_port);
+ if (!(reg & INTSTS_ACTEINT)) {
+@@ -424,7 +460,7 @@ static int scc_ide_dma_end(ide_drive_t * drive)
+ break;
+ }
- out_be32(ap->ioaddr.device_addr, tmp);
-- ata_pause(ap);
-+ ata_sff_pause(ap);
- }
+- dma_stat = __ide_dma_end(drive);
++ dma_stat = __scc_dma_end(drive);
+ if (data_loss)
+ dma_stat |= 2; /* emulate DMA error (to retry command) */
+ return dma_stat;
+@@ -437,7 +473,8 @@ static int scc_dma_test_irq(ide_drive_t *drive)
+ u32 int_stat = in_be32((void __iomem *)hwif->dma_base + 0x014);
- /**
-@@ -441,7 +441,7 @@ static void scc_bmdma_setup (struct ata_queued_cmd *qc)
- out_be32(mmio + SCC_DMA_CMD, dmactl);
+ /* SCC errata A252,A308 workaround: Step4 */
+- if ((in_be32((void __iomem *)IDE_ALTSTATUS_REG) & ERR_STAT) &&
++ if ((in_be32((void __iomem *)hwif->io_ports.ctl_addr)
++ & ERR_STAT) &&
+ (int_stat & INTSTS_INTRQ))
+ return 1;
- /* issue r/w command */
-- ap->ops->exec_command(ap, &qc->tf);
-+ ap->ops->sff_exec_command(ap, &qc->tf);
+@@ -447,7 +484,7 @@ static int scc_dma_test_irq(ide_drive_t *drive)
+
+ if (!drive->waiting_for_dma)
+ printk(KERN_WARNING "%s: (%s) called while not waiting\n",
+- drive->name, __FUNCTION__);
++ drive->name, __func__);
+ return 0;
}
- /**
-@@ -476,7 +476,7 @@ static unsigned int scc_devchk (struct ata_port *ap,
- struct ata_ioports *ioaddr = &ap->ioaddr;
- u8 nsect, lbal;
+@@ -481,7 +518,7 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name)
+ unsigned long dma_size = pci_resource_len(dev, 1);
+ void __iomem *ctl_addr;
+ void __iomem *dma_addr;
+- int i;
++ int i, ret;
-- ap->ops->dev_select(ap, device);
-+ ap->ops->sff_dev_select(ap, device);
+ for (i = 0; i < MAX_HWIFS; i++) {
+ if (scc_ports[i].ctl == 0)
+@@ -490,21 +527,17 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name)
+ if (i >= MAX_HWIFS)
+ return -ENOMEM;
- 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,
+- if (!request_mem_region(ctl_base, ctl_size, name)) {
+- printk(KERN_WARNING "%s: IDE controller MMIO ports not available.\n", SCC_PATA_NAME);
+- goto fail_0;
+- }
+-
+- if (!request_mem_region(dma_base, dma_size, name)) {
+- printk(KERN_WARNING "%s: IDE controller MMIO ports not available.\n", SCC_PATA_NAME);
+- goto fail_1;
++ ret = pci_request_selected_regions(dev, (1 << 2) - 1, name);
++ if (ret < 0) {
++ printk(KERN_ERR "%s: can't reserve resources\n", name);
++ return ret;
+ }
+
+ if ((ctl_addr = ioremap(ctl_base, ctl_size)) == NULL)
+- goto fail_2;
++ goto fail_0;
+
+ if ((dma_addr = ioremap(dma_base, dma_size)) == NULL)
+- goto fail_3;
++ goto fail_1;
+
+ pci_set_master(dev);
+ scc_ports[i].ctl = (unsigned long)ctl_addr;
+@@ -513,16 +546,44 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name)
+
+ return 1;
+
+- fail_3:
+- iounmap(ctl_addr);
+- fail_2:
+- release_mem_region(dma_base, dma_size);
+ fail_1:
+- release_mem_region(ctl_base, ctl_size);
++ iounmap(ctl_addr);
+ fail_0:
+ 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 = 0; i <= 8; i++)
++ hw.io_ports_array[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;
++
++ idx[0] = hwif->index;
++
++ ide_device_add(idx, d);
++
++ return 0;
++}
++
/**
-- * 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
- */
+ * init_setup_scc - set up an SCC PATA Controller
+ * @dev: PCI device
+@@ -545,10 +606,13 @@ static int __devinit init_setup_scc(struct pci_dev *dev,
+ struct scc_ports *ports;
+ int rc;
--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;
++ rc = pci_enable_device(dev);
++ if (rc)
++ goto end;
+
-+ /* 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;
+ rc = setup_mmio_scc(dev, d->name);
+- if (rc < 0) {
+- return rc;
- }
-+ msleep(150);
++ if (rc < 0)
++ goto end;
-- /* 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;
+ ports = pci_get_drvdata(dev);
+ ctl_base = ports->ctl;
+@@ -583,7 +647,126 @@ static int __devinit init_setup_scc(struct pci_dev *dev,
+ out_be32((void*)mode_port, MODE_JCUSFEN);
+ out_be32((void*)intmask_port, INTMASK_MSK);
-- 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;
+- return ide_setup_pci_device(dev, d);
++ rc = scc_ide_setup_pci_device(dev, d);
+
-+ ap->ops->sff_dev_select(ap, 1);
++ end:
++ return rc;
++}
+
-+ /* 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;
++static void scc_tf_load(ide_drive_t *drive, ide_task_t *task)
++{
++ struct ide_io_ports *io_ports = &drive->hwif->io_ports;
++ struct ide_taskfile *tf = &task->tf;
++ u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
++
++ if (task->tf_flags & IDE_TFLAG_FLAGGED)
++ HIHI = 0xFF;
++
++ ide_set_irq(drive, 1);
++
++ if (task->tf_flags & IDE_TFLAG_OUT_DATA)
++ out_be32((void *)io_ports->data_addr,
++ (tf->hob_data << 8) | tf->data);
++
++ if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
++ scc_ide_outb(tf->hob_feature, io_ports->feature_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
++ scc_ide_outb(tf->hob_nsect, io_ports->nsect_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
++ scc_ide_outb(tf->hob_lbal, io_ports->lbal_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
++ scc_ide_outb(tf->hob_lbam, io_ports->lbam_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
++ scc_ide_outb(tf->hob_lbah, io_ports->lbah_addr);
++
++ if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
++ scc_ide_outb(tf->feature, io_ports->feature_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
++ scc_ide_outb(tf->nsect, io_ports->nsect_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
++ scc_ide_outb(tf->lbal, io_ports->lbal_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
++ scc_ide_outb(tf->lbam, io_ports->lbam_addr);
++ if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
++ scc_ide_outb(tf->lbah, io_ports->lbah_addr);
++
++ if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
++ scc_ide_outb((tf->device & HIHI) | drive->select.all,
++ io_ports->device_addr);
++}
++
++static void scc_tf_read(ide_drive_t *drive, ide_task_t *task)
++{
++ struct ide_io_ports *io_ports = &drive->hwif->io_ports;
++ struct ide_taskfile *tf = &task->tf;
++
++ if (task->tf_flags & IDE_TFLAG_IN_DATA) {
++ u16 data = (u16)in_be32((void *)io_ports->data_addr);
++
++ tf->data = data & 0xff;
++ tf->hob_data = (data >> 8) & 0xff;
++ }
++
++ /* be sure we're looking at the low order bits */
++ scc_ide_outb(drive->ctl & ~0x80, io_ports->ctl_addr);
++
++ if (task->tf_flags & IDE_TFLAG_IN_NSECT)
++ tf->nsect = scc_ide_inb(io_ports->nsect_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_LBAL)
++ tf->lbal = scc_ide_inb(io_ports->lbal_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_LBAM)
++ tf->lbam = scc_ide_inb(io_ports->lbam_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_LBAH)
++ tf->lbah = scc_ide_inb(io_ports->lbah_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
++ tf->device = scc_ide_inb(io_ports->device_addr);
++
++ if (task->tf_flags & IDE_TFLAG_LBA48) {
++ scc_ide_outb(drive->ctl | 0x80, io_ports->ctl_addr);
++
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
++ tf->hob_feature = scc_ide_inb(io_ports->feature_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
++ tf->hob_nsect = scc_ide_inb(io_ports->nsect_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
++ tf->hob_lbal = scc_ide_inb(io_ports->lbal_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
++ tf->hob_lbam = scc_ide_inb(io_ports->lbam_addr);
++ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
++ tf->hob_lbah = scc_ide_inb(io_ports->lbah_addr);
++ }
++}
+
-+ nsect = in_be32(ioaddr->nsect_addr);
-+ lbal = in_be32(ioaddr->lbal_addr);
-+ if ((nsect == 1) && (lbal == 1))
-+ break;
-+ msleep(50); /* give drive a breather */
-+ }
++static void scc_input_data(ide_drive_t *drive, struct request *rq,
++ void *buf, unsigned int len)
++{
++ unsigned long data_addr = drive->hwif->io_ports.data_addr;
+
-+ rc = ata_sff_wait_ready(link, deadline);
-+ if (rc) {
-+ if (rc != -ENODEV)
-+ return rc;
-+ ret = rc;
-+ }
- }
++ len++;
++
++ if (drive->io_32bit) {
++ scc_ide_insl(data_addr, buf, len / 4);
++
++ if ((len & 3) >= 2)
++ scc_ide_insw(data_addr, (u8 *)buf + (len & ~3), 1);
++ } else
++ scc_ide_insw(data_addr, buf, len / 2);
++}
++
++static void scc_output_data(ide_drive_t *drive, struct request *rq,
++ void *buf, unsigned int len)
++{
++ unsigned long data_addr = drive->hwif->io_ports.data_addr;
++
++ len++;
++
++ if (drive->io_32bit) {
++ scc_ide_outsl(data_addr, buf, len / 4);
++
++ if ((len & 3) >= 2)
++ scc_ide_outsw(data_addr, (u8 *)buf + (len & ~3), 1);
++ } else
++ scc_ide_outsw(data_addr, buf, len / 2);
+ }
+
+ /**
+@@ -600,27 +783,16 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
+
+ ide_set_hwifdata(hwif, ports);
+
++ hwif->tf_load = scc_tf_load;
++ hwif->tf_read = scc_tf_read;
++
++ hwif->input_data = scc_input_data;
++ hwif->output_data = scc_output_data;
++
+ hwif->INB = scc_ide_inb;
+- hwif->INW = scc_ide_inw;
+- hwif->INSW = scc_ide_insw;
+- hwif->INSL = scc_ide_insl;
+ hwif->OUTB = scc_ide_outb;
+ hwif->OUTBSYNC = scc_ide_outbsync;
+- hwif->OUTW = scc_ide_outw;
+- 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,37 +834,46 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
+ {
+ struct scc_ports *ports = ide_get_hwifdata(hwif);
- /* 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);
+- ports->hwif_id = hwif->index;
++ ports->hwif = hwif;
-- return 0;
-+ return ret;
- }
+ hwif->dma_command = hwif->dma_base;
+ hwif->dma_status = hwif->dma_base + 0x04;
+- hwif->dma_prdtable = hwif->dma_base + 0x08;
- /**
-@@ -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);
+ /* PTERADD */
+ out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma);
-- /* wait a while before checking status */
-- ata_wait_after_reset(ap, deadline);
+- hwif->dma_setup = scc_dma_setup;
+- hwif->ide_dma_end = scc_ide_dma_end;
+- hwif->set_pio_mode = scc_set_pio_mode;
+- hwif->set_dma_mode = scc_set_dma_mode;
+- hwif->ide_dma_test_irq = scc_dma_test_irq;
+- hwif->udma_filter = scc_udma_filter;
-
-- /* 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;
+ if (in_be32((void __iomem *)(hwif->config_data + 0xff0)) & CCKCTRL_ATACLKOEN)
+ hwif->ultra_mask = ATA_UDMA6; /* 133MHz */
+ else
+ hwif->ultra_mask = ATA_UDMA5; /* 100MHz */
-
-- scc_bus_post_reset(ap, devmask, deadline);
-+ scc_wait_after_reset(&ap->link, devmask, deadline);
-
- return 0;
+- hwif->cable_detect = scc_cable_detect;
}
- /**
-- * 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 const struct ide_port_ops scc_port_ops = {
++ .set_pio_mode = scc_set_pio_mode,
++ .set_dma_mode = scc_set_dma_mode,
++ .udma_filter = scc_udma_filter,
++ .cable_detect = scc_cable_detect,
++};
++
++static const struct ide_dma_ops scc_dma_ops = {
++ .dma_host_set = scc_dma_host_set,
++ .dma_setup = scc_dma_setup,
++ .dma_exec_cmd = ide_dma_exec_cmd,
++ .dma_start = scc_dma_start,
++ .dma_end = scc_dma_end,
++ .dma_test_irq = scc_dma_test_irq,
++ .dma_lost_irq = ide_dma_lost_irq,
++ .dma_timeout = ide_dma_timeout,
++};
++
+ #define DECLARE_SCC_DEV(name_str) \
+ { \
+ .name = name_str, \
+ .init_iops = init_iops_scc, \
+ .init_hwif = init_hwif_scc, \
+- .host_flags = IDE_HFLAG_SINGLE | \
+- IDE_HFLAG_BOOTABLE, \
++ .port_ops = &scc_port_ops, \
++ .dma_ops = &scc_dma_ops, \
++ .host_flags = IDE_HFLAG_SINGLE, \
+ .pio_mask = ATA_PIO4, \
+ }
--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)
+@@ -724,11 +905,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 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);
+ struct scc_ports *ports = pci_get_drvdata(dev);
+- ide_hwif_t *hwif = &ide_hwifs[ports->hwif_id];
+- 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);
+- unsigned long dma_size = pci_resource_len(dev, 1);
++ ide_hwif_t *hwif = ports->hwif;
- /* 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,
+ if (hwif->dmatable_cpu) {
+ pci_free_consistent(dev, PRD_ENTRIES * PRD_BYTES,
+@@ -736,13 +913,11 @@ static void __devexit scc_remove(struct pci_dev *dev)
+ hwif->dmatable_cpu = NULL;
}
- /* 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);
+- ide_unregister(hwif->index, 0, 0);
++ ide_unregister(hwif);
-- out:
- DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
- return 0;
+- hwif->chipset = ide_unknown;
+ iounmap((void*)ports->dma);
+ iounmap((void*)ports->ctl);
+- release_mem_region(dma_base, dma_size);
+- release_mem_region(ctl_base, ctl_size);
++ pci_release_selected_regions(dev, (1 << 2) - 1);
+ memset(ports, 0, sizeof(*ports));
}
-@@ -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 */
+diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
+index c11880b..a1fb208 100644
+--- a/drivers/ide/pci/serverworks.c
++++ b/drivers/ide/pci/serverworks.c
+@@ -312,7 +312,7 @@ static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif)
+ return ATA_CBL_PATA40;
}
- /**
-@@ -742,7 +747,7 @@ static u8 scc_bmdma_status (struct ata_port *ap)
- return host_stat;
+-static u8 __devinit ata66_svwks(ide_hwif_t *hwif)
++static u8 __devinit svwks_cable_detect(ide_hwif_t *hwif)
+ {
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
- /* 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);
+@@ -336,28 +336,28 @@ static u8 __devinit ata66_svwks(ide_hwif_t *hwif)
+ return ATA_CBL_PATA40;
+ }
- /* 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 void __devinit init_hwif_svwks (ide_hwif_t *hwif)
+-{
+- struct pci_dev *dev = to_pci_dev(hwif->dev);
+-
+- hwif->set_pio_mode = &svwks_set_pio_mode;
+- hwif->set_dma_mode = &svwks_set_dma_mode;
+- hwif->udma_filter = &svwks_udma_filter;
++static const struct ide_port_ops osb4_port_ops = {
++ .set_pio_mode = svwks_set_pio_mode,
++ .set_dma_mode = svwks_set_dma_mode,
++ .udma_filter = svwks_udma_filter,
++};
- 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;
+- if (dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE)
+- hwif->cable_detect = ata66_svwks;
+-}
++static const struct ide_port_ops svwks_port_ops = {
++ .set_pio_mode = svwks_set_pio_mode,
++ .set_dma_mode = svwks_set_dma_mode,
++ .udma_filter = svwks_udma_filter,
++ .cable_detect = svwks_cable_detect,
++};
- /* 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]));
+ #define IDE_HFLAGS_SVWKS \
+ (IDE_HFLAG_LEGACY_IRQS | \
+- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
+- IDE_HFLAG_BOOTABLE)
++ IDE_HFLAG_ABUSE_SET_DMA_MODE)
- /* 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;
+ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
+ { /* 0 */
+ .name = "SvrWks OSB4",
+ .init_chipset = init_chipset_svwks,
+- .init_hwif = init_hwif_svwks,
++ .port_ops = &osb4_port_ops,
+ .host_flags = IDE_HFLAGS_SVWKS,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+@@ -365,7 +365,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
+ },{ /* 1 */
+ .name = "SvrWks CSB5",
+ .init_chipset = init_chipset_svwks,
+- .init_hwif = init_hwif_svwks,
++ .port_ops = &svwks_port_ops,
+ .host_flags = IDE_HFLAGS_SVWKS,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+@@ -373,7 +373,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
+ },{ /* 2 */
+ .name = "SvrWks CSB6",
+ .init_chipset = init_chipset_svwks,
+- .init_hwif = init_hwif_svwks,
++ .port_ops = &svwks_port_ops,
+ .host_flags = IDE_HFLAGS_SVWKS,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+@@ -381,7 +381,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
+ },{ /* 3 */
+ .name = "SvrWks CSB6",
+ .init_chipset = init_chipset_svwks,
+- .init_hwif = init_hwif_svwks,
++ .port_ops = &svwks_port_ops,
+ .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+@@ -389,7 +389,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
+ },{ /* 4 */
+ .name = "SvrWks HT1000",
+ .init_chipset = init_chipset_svwks,
+- .init_hwif = init_hwif_svwks,
++ .port_ops = &svwks_port_ops,
+ .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+@@ -418,7 +418,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..16a0bce 100644
+--- a/drivers/ide/pci/sgiioc4.c
++++ b/drivers/ide/pci/sgiioc4.c
+@@ -98,29 +98,28 @@ sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
+ int i;
- 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().
- */
+ /* Registers are word (32 bit) aligned */
+- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+- hw->io_ports[i] = reg + i * 4;
++ for (i = 0; i <= 7; i++)
++ hw->io_ports_array[i] = reg + i * 4;
- 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);
+ if (ctrl_port)
+- hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
++ hw->io_ports.ctl_addr = ctrl_port;
-- ap->ops->irq_clear(ap);
-+ ap->ops->sff_irq_clear(ap);
+ if (irq_port)
+- hw->io_ports[IDE_IRQ_OFFSET] = irq_port;
++ hw->io_ports.irq_addr = irq_port;
+ }
- return tmp;
+ 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.ctl_addr);
}
- /**
-- * 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 int
+ sgiioc4_checkirq(ide_hwif_t * hwif)
+ {
+ unsigned long intr_addr =
+- hwif->io_ports[IDE_IRQ_OFFSET] + IOC4_INTR_REG * 4;
++ hwif->io_ports.irq_addr + IOC4_INTR_REG * 4;
--static void scc_bmdma_freeze (struct ata_port *ap)
-+static void scc_freeze (struct ata_port *ap)
+ if ((u8)readl((void __iomem *)intr_addr) & 0x03)
+ return 1;
+@@ -135,25 +134,25 @@ sgiioc4_clearirq(ide_drive_t * drive)
{
- struct ata_ioports *ioaddr = &ap->ioaddr;
+ u32 intr_reg;
+ ide_hwif_t *hwif = HWIF(drive);
+- unsigned long other_ir =
+- hwif->io_ports[IDE_IRQ_OFFSET] + (IOC4_INTR_REG << 2);
++ struct ide_io_ports *io_ports = &hwif->io_ports;
++ unsigned long other_ir = io_ports->irq_addr + (IOC4_INTR_REG << 2);
-@@ -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);
+ /* Code to check for PCI error conditions */
+ 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(io_ports->status_addr);
+ int count = 0;
+- stat = sgiioc4_INB(IDE_STATUS_REG);
++ stat = sgiioc4_INB(io_ports->status_addr);
+ while ((stat & 0x80) && (count++ < 100)) {
+ udelay(1);
+- stat = sgiioc4_INB(IDE_STATUS_REG);
++ stat = sgiioc4_INB(io_ports->status_addr);
+ }
-- ap->ops->irq_clear(ap);
-+ ap->ops->sff_irq_clear(ap);
+ if (intr_reg & 0x02) {
+@@ -163,18 +162,18 @@ sgiioc4_clearirq(ide_drive_t * drive)
+ pci_stat_cmd_reg;
+
+ pci_err_addr_low =
+- readl((void __iomem *)hwif->io_ports[IDE_IRQ_OFFSET]);
++ readl((void __iomem *)io_ports->irq_addr);
+ pci_err_addr_high =
+- readl((void __iomem *)(hwif->io_ports[IDE_IRQ_OFFSET] + 4));
++ readl((void __iomem *)(io_ports->irq_addr + 4));
+ pci_read_config_dword(dev, PCI_COMMAND,
+ &pci_stat_cmd_reg);
+ printk(KERN_ERR
+ "%s(%s) : PCI Bus Error when doing DMA:"
+ " status-cmd reg is 0x%x\n",
+- __FUNCTION__, drive->name, pci_stat_cmd_reg);
++ __func__, drive->name, pci_stat_cmd_reg);
+ printk(KERN_ERR
+ "%s(%s) : PCI Error Address is 0x%x%x\n",
+- __FUNCTION__, drive->name,
++ __func__, drive->name,
+ pci_err_addr_high, pci_err_addr_low);
+ /* Clear the PCI Error indicator */
+ pci_write_config_dword(dev, PCI_COMMAND, 0x00000146);
+@@ -189,7 +188,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
+ return intr_reg & 3;
}
- /**
-@@ -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)
+-static void sgiioc4_ide_dma_start(ide_drive_t * drive)
++static void sgiioc4_dma_start(ide_drive_t *drive)
{
- link->ap->cbl = ATA_CBL_PATA80;
-- return ata_std_prereset(link, deadline);
-+ return ata_sff_prereset(link, deadline);
+ ide_hwif_t *hwif = HWIF(drive);
+ unsigned long ioc4_dma_addr = hwif->dma_base + IOC4_DMA_CTRL * 4;
+@@ -216,8 +215,7 @@ sgiioc4_ide_dma_stop(ide_hwif_t *hwif, u64 dma_base)
}
- /**
-- * 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)
+ /* Stops the IOC4 DMA Engine */
+-static int
+-sgiioc4_ide_dma_end(ide_drive_t * drive)
++static int sgiioc4_dma_end(ide_drive_t *drive)
{
- struct ata_port *ap = link->ap;
-
-@@ -887,9 +892,9 @@ static void scc_std_postreset(struct ata_link *link, unsigned int *classes)
+ u32 ioc4_dma, bc_dev, bc_mem, num, valid = 0, cnt = 0;
+ ide_hwif_t *hwif = HWIF(drive);
+@@ -233,7 +231,7 @@ sgiioc4_ide_dma_end(ide_drive_t * drive)
+ printk(KERN_ERR
+ "%s(%s): IOC4 DMA STOP bit is still 1 :"
+ "ioc4_dma_reg 0x%x\n",
+- __FUNCTION__, drive->name, ioc4_dma);
++ __func__, drive->name, ioc4_dma);
+ dma_stat = 1;
+ }
- /* 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);
+@@ -252,7 +250,7 @@ sgiioc4_ide_dma_end(ide_drive_t * drive)
+ udelay(1);
+ }
+ if (!valid) {
+- printk(KERN_ERR "%s(%s) : DMA incomplete\n", __FUNCTION__,
++ printk(KERN_ERR "%s(%s) : DMA incomplete\n", __func__,
+ drive->name);
+ dma_stat = 1;
+ }
+@@ -265,7 +263,7 @@ sgiioc4_ide_dma_end(ide_drive_t * drive)
+ printk(KERN_ERR
+ "%s(%s): WARNING!! byte_count_dev %d "
+ "!= byte_count_mem %d\n",
+- __FUNCTION__, drive->name, bc_dev, bc_mem);
++ __func__, drive->name, bc_dev, bc_mem);
+ }
+ }
- /* 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)
+@@ -280,8 +278,7 @@ static void sgiioc4_set_dma_mode(ide_drive_t *drive, const u8 speed)
}
- /**
-- * 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)
+ /* returns 1 if dma irq issued, 0 otherwise */
+-static int
+-sgiioc4_ide_dma_test_irq(ide_drive_t * drive)
++static int sgiioc4_dma_test_irq(ide_drive_t *drive)
{
- void __iomem *mmio = ap->ioaddr.bmdma_addr;
-
-@@ -968,52 +962,37 @@ static void scc_port_stop (struct ata_port *ap)
+ return sgiioc4_checkirq(HWIF(drive));
+ }
+@@ -295,7 +292,7 @@ static void sgiioc4_dma_host_set(ide_drive_t *drive, int on)
+ static void
+ sgiioc4_resetproc(ide_drive_t * drive)
+ {
+- sgiioc4_ide_dma_end(drive);
++ sgiioc4_dma_end(drive);
+ sgiioc4_clearirq(drive);
}
- 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),
- };
+@@ -330,13 +327,17 @@ sgiioc4_INB(unsigned long port)
--static const struct ata_port_operations scc_pata_ops = {
-+static struct ata_port_operations scc_pata_ops = {
-+ .inherits = &ata_bmdma_port_ops,
+ /* Creates a dma map for the scatter-gather list entries */
+ static int __devinit
+-ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
++ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d)
+ {
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
++ unsigned long dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET;
+ void __iomem *virt_dma_base;
+ int num_ports = sizeof (ioc4_dma_regs_t);
+ void *pad;
+
++ if (dma_base == 0)
++ return -1;
+
- .set_piomode = scc_set_piomode,
- .set_dmamode = scc_set_dmamode,
- .mode_filter = scc_mode_filter,
+ printk(KERN_INFO "%s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name,
+ dma_base, dma_base + num_ports - 1);
-- .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,
+@@ -344,7 +345,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
+ printk(KERN_ERR
+ "%s(%s) -- ERROR, Addresses 0x%p to 0x%p "
+ "ALREADY in use\n",
+- __FUNCTION__, hwif->name, (void *) dma_base,
++ __func__, hwif->name, (void *) dma_base,
+ (void *) dma_base + num_ports - 1);
+ return -1;
+ }
+@@ -353,7 +354,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
+ if (virt_dma_base == NULL) {
+ printk(KERN_ERR
+ "%s(%s) -- ERROR, Unable to map addresses 0x%lx to 0x%lx\n",
+- __FUNCTION__, hwif->name, dma_base, dma_base + num_ports - 1);
++ __func__, hwif->name, dma_base, dma_base + num_ports - 1);
+ goto dma_remap_failure;
+ }
+ hwif->dma_base = (unsigned long) virt_dma_base;
+@@ -379,7 +380,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
+ hwif->dmatable_cpu, hwif->dmatable_dma);
+ printk(KERN_INFO
+ "%s() -- Error! Unable to allocate DMA Maps for drive %s\n",
+- __FUNCTION__, hwif->name);
++ __func__, hwif->name);
+ printk(KERN_INFO
+ "Changing from DMA to PIO mode for Drive %s\n", hwif->name);
- .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,
+@@ -407,14 +408,14 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
+ if (ioc4_dma & IOC4_S_DMA_ACTIVE) {
+ printk(KERN_WARNING
+ "%s(%s):Warning!! DMA from previous transfer was still active\n",
+- __FUNCTION__, drive->name);
++ __func__, drive->name);
+ writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
+ ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
-- .error_handler = scc_error_handler,
-+ .freeze = scc_freeze,
-+ .prereset = scc_pata_prereset,
-+ .softreset = scc_softreset,
-+ .postreset = scc_postreset,
- .post_internal_cmd = scc_bmdma_stop,
+ if (ioc4_dma & IOC4_S_DMA_STOP)
+ printk(KERN_ERR
+ "%s(%s) : IOC4 Dma STOP bit is still 1\n",
+- __FUNCTION__, drive->name);
++ __func__, drive->name);
+ }
-- .irq_clear = scc_bmdma_irq_clear,
-- .irq_on = scc_irq_on,
-+ .sff_irq_clear = scc_irq_clear,
-+ .sff_irq_on = scc_irq_on,
+ ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
+@@ -422,14 +423,14 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
+ printk(KERN_WARNING
+ "%s(%s) : Warning!! - DMA Error during Previous"
+ " transfer | status 0x%x\n",
+- __FUNCTION__, drive->name, ioc4_dma);
++ __func__, drive->name, ioc4_dma);
+ writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
+ ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
- .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;
+ if (ioc4_dma & IOC4_S_DMA_STOP)
+ printk(KERN_ERR
+ "%s(%s) : IOC4 DMA STOP bit is still 1\n",
+- __FUNCTION__, drive->name);
++ __func__, drive->name);
+ }
-- 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);
+ /* Address of the Scatter Gather List */
+@@ -520,7 +521,7 @@ use_pio_instead:
+ return 0; /* revert to PIO for this request */
}
- 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
+-static int sgiioc4_ide_dma_setup(ide_drive_t *drive)
++static int sgiioc4_dma_setup(ide_drive_t *drive)
{
- if (adev->class == ATA_DEV_ATA)
- mask &= ~ATA_MASK_UDMA;
-- return ata_pci_default_filter(adev, mask);
-+ return ata_bmdma_mode_filter(adev, mask);
+ struct request *rq = HWGROUP(drive)->rq;
+ unsigned int count = 0;
+@@ -549,63 +550,46 @@ static int sgiioc4_ide_dma_setup(ide_drive_t *drive)
+ return 0;
}
+-static void __devinit
+-ide_init_sgiioc4(ide_hwif_t * hwif)
+-{
+- hwif->mmio = 1;
+- hwif->set_pio_mode = NULL; /* Sets timing for PIO mode */
+- hwif->set_dma_mode = &sgiioc4_set_dma_mode;
+- hwif->selectproc = NULL;/* Use the default routine to select drive */
+- hwif->reset_poll = NULL;/* No HBA specific reset_poll needed */
+- hwif->pre_reset = NULL; /* No HBA specific pre_set needed */
+- hwif->resetproc = &sgiioc4_resetproc;/* Reset DMA engine,
+- clear interrupts */
+- hwif->maskproc = &sgiioc4_maskproc; /* Mask on/off NIEN register */
+- hwif->quirkproc = NULL;
+- hwif->busproc = NULL;
+-
+- hwif->INB = &sgiioc4_INB;
+-
+- if (hwif->dma_base == 0)
+- return;
++static const struct ide_port_ops sgiioc4_port_ops = {
++ .set_dma_mode = sgiioc4_set_dma_mode,
++ /* reset DMA engine, clear IRQs */
++ .resetproc = sgiioc4_resetproc,
++ /* mask on/off NIEN register */
++ .maskproc = sgiioc4_maskproc,
++};
+
+- hwif->dma_host_set = &sgiioc4_dma_host_set;
+- hwif->dma_setup = &sgiioc4_ide_dma_setup;
+- hwif->dma_start = &sgiioc4_ide_dma_start;
+- hwif->ide_dma_end = &sgiioc4_ide_dma_end;
+- hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
+- hwif->dma_lost_irq = &sgiioc4_dma_lost_irq;
+- hwif->dma_timeout = &ide_dma_timeout;
+-}
++static const struct ide_dma_ops sgiioc4_dma_ops = {
++ .dma_host_set = sgiioc4_dma_host_set,
++ .dma_setup = sgiioc4_dma_setup,
++ .dma_start = sgiioc4_dma_start,
++ .dma_end = sgiioc4_dma_end,
++ .dma_test_irq = sgiioc4_dma_test_irq,
++ .dma_lost_irq = sgiioc4_dma_lost_irq,
++ .dma_timeout = ide_dma_timeout,
++};
+
+ static const struct ide_port_info sgiioc4_port_info __devinitdata = {
+ .chipset = ide_pci,
+- .host_flags = IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
+- IDE_HFLAG_NO_AUTOTUNE,
++ .init_dma = ide_dma_sgiioc4,
++ .port_ops = &sgiioc4_port_ops,
++ .dma_ops = &sgiioc4_dma_ops,
++ .host_flags = IDE_HFLAG_MMIO,
+ .mwdma_mask = ATA_MWDMA2_ONLY,
+ };
+
+ static int __devinit
+ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
+ {
+- unsigned long cmd_base, dma_base, irqport;
++ unsigned long cmd_base, irqport;
+ 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;
-@@ -219,7 +219,7 @@ static unsigned long serverworks_csb_filter(struct ata_device *adev, unsigned lo
+- /*
+- * 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;
+@@ -622,7 +606,6 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
+ cmd_base = (unsigned long) virt_base + IOC4_CMD_OFFSET;
+ ctl = (unsigned long) virt_base + IOC4_CTRL_OFFSET;
+ irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET;
+- dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET;
+
+ cmd_phys_base = bar0 + IOC4_CMD_OFFSET;
+ if (!request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
+@@ -630,7 +613,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
+ printk(KERN_ERR
+ "%s : %s -- ERROR, Addresses "
+ "0x%p to 0x%p ALREADY in use\n",
+- __FUNCTION__, hwif->name, (void *) cmd_phys_base,
++ __func__, hwif->name, (void *) cmd_phys_base,
+ (void *) cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
+ return -ENOMEM;
+ }
+@@ -651,13 +634,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
+ /* Initializing chipset IRQ Registers */
+ writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
+
+- if (dma_base == 0 || ide_dma_sgiioc4(hwif, dma_base)) {
+- printk(KERN_INFO "%s: %s Bus-Master DMA disabled\n",
+- hwif->name, DRV_NAME);
+- d.mwdma_mask = 0;
+- }
+-
+- ide_init_sgiioc4(hwif);
++ hwif->INB = &sgiioc4_INB;
- /* Disk, UDMA */
- if (adev->class != ATA_DEV_ATA)
-- return ata_pci_default_filter(adev, mask);
-+ return ata_bmdma_mode_filter(adev, mask);
+ idx[0] = hwif->index;
- /* 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);
+diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
+index 8d624af..0006b9e 100644
+--- a/drivers/ide/pci/siimage.c
++++ b/drivers/ide/pci/siimage.c
+@@ -1,8 +1,8 @@
+ /*
+ * Copyright (C) 2001-2002 Andre Hedrick <andre at linux-ide.org>
+ * Copyright (C) 2003 Red Hat <alan at redhat.com>
+- * Copyright (C) 2007 MontaVista Software, Inc.
+- * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
++ * Copyright (C) 2007-2008 MontaVista Software, Inc.
++ * Copyright (C) 2007-2008 Bartlomiej Zolnierkiewicz
+ *
+ * May be copied or modified under the terms of the GNU General Public License
+ *
+@@ -17,10 +17,10 @@
+ *
+ * FAQ Items:
+ * If you are using Marvell SATA-IDE adapters with Maxtor drives
+- * ensure the system is set up for ATA100/UDMA5 not UDMA6.
++ * ensure the system is set up for ATA100/UDMA5, not UDMA6.
+ *
+ * If you are using WD drives with SATA bridges you must set the
+- * drive to "Single". "Master" will hang
++ * drive to "Single". "Master" will hang.
+ *
+ * If you have strange problems with nVidia chipset systems please
+ * see the SI support documentation and update your system BIOS
+@@ -42,25 +42,24 @@
+ #include <linux/hdreg.h>
+ #include <linux/ide.h>
+ #include <linux/init.h>
+-
+-#include <asm/io.h>
++#include <linux/io.h>
+
+ /**
+ * pdev_is_sata - check if device is SATA
+ * @pdev: PCI device to check
+- *
++ *
+ * Returns true if this is a SATA controller
+ */
+-
++
+ static int pdev_is_sata(struct pci_dev *pdev)
+ {
+ #ifdef CONFIG_BLK_DEV_IDE_SATA
+- switch(pdev->device) {
+- case PCI_DEVICE_ID_SII_3112:
+- case PCI_DEVICE_ID_SII_1210SA:
+- return 1;
+- case PCI_DEVICE_ID_SII_680:
+- return 0;
++ switch (pdev->device) {
++ case PCI_DEVICE_ID_SII_3112:
++ case PCI_DEVICE_ID_SII_1210SA:
++ return 1;
++ case PCI_DEVICE_ID_SII_680:
++ return 0;
}
-- return ata_pci_default_filter(adev, mask);
-+ return ata_bmdma_mode_filter(adev, mask);
+ BUG();
+ #endif
+@@ -70,10 +69,10 @@ static int pdev_is_sata(struct pci_dev *pdev)
+ /**
+ * is_sata - check if hwif is SATA
+ * @hwif: interface to check
+- *
++ *
+ * Returns true if this is a SATA controller
+ */
+-
++
+ static inline int is_sata(ide_hwif_t *hwif)
+ {
+ return pdev_is_sata(to_pci_dev(hwif->dev));
+@@ -86,21 +85,22 @@ static inline int is_sata(ide_hwif_t *hwif)
+ *
+ * Turn a config register offset into the right address in either
+ * PCI space or MMIO space to access the control register in question
+- * Thankfully this is a configuration operation so isnt performance
+- * criticial.
++ * Thankfully this is a configuration operation, so isn't performance
++ * critical.
+ */
+-
++
+ static unsigned long siimage_selreg(ide_hwif_t *hwif, int r)
+ {
+ unsigned long base = (unsigned long)hwif->hwif_data;
++
+ base += 0xA0 + r;
+- if(hwif->mmio)
+- base += (hwif->channel << 6);
++ if (hwif->mmio)
++ base += hwif->channel << 6;
+ else
+- base += (hwif->channel << 4);
++ base += hwif->channel << 4;
+ return base;
+ }
+-
++
+ /**
+ * siimage_seldev - return register base
+ * @hwif: interface
+@@ -110,20 +110,69 @@ static unsigned long siimage_selreg(ide_hwif_t *hwif, int r)
+ * PCI space or MMIO space to access the control register in question
+ * including accounting for the unit shift.
+ */
+-
++
+ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
+- unsigned long base = (unsigned long)hwif->hwif_data;
++ unsigned long base = (unsigned long)hwif->hwif_data;
++
+ base += 0xA0 + r;
+- if(hwif->mmio)
+- base += (hwif->channel << 6);
++ if (hwif->mmio)
++ base += hwif->channel << 6;
+ else
+- base += (hwif->channel << 4);
++ base += hwif->channel << 4;
+ base |= drive->select.b.unit << drive->select.b.unit;
+ return base;
}
++static u8 sil_ioread8(struct pci_dev *dev, unsigned long addr)
++{
++ u8 tmp = 0;
++
++ if (pci_get_drvdata(dev))
++ tmp = readb((void __iomem *)addr);
++ else
++ pci_read_config_byte(dev, addr, &tmp);
++
++ return tmp;
++}
++
++static u16 sil_ioread16(struct pci_dev *dev, unsigned long addr)
++{
++ u16 tmp = 0;
++
++ if (pci_get_drvdata(dev))
++ tmp = readw((void __iomem *)addr);
++ else
++ pci_read_config_word(dev, addr, &tmp);
++
++ return tmp;
++}
++
++static void sil_iowrite8(struct pci_dev *dev, u8 val, unsigned long addr)
++{
++ if (pci_get_drvdata(dev))
++ writeb(val, (void __iomem *)addr);
++ else
++ pci_write_config_byte(dev, addr, val);
++}
++
++static void sil_iowrite16(struct pci_dev *dev, u16 val, unsigned long addr)
++{
++ if (pci_get_drvdata(dev))
++ writew(val, (void __iomem *)addr);
++ else
++ pci_write_config_word(dev, addr, val);
++}
++
++static void sil_iowrite32(struct pci_dev *dev, u32 val, unsigned long addr)
++{
++ if (pci_get_drvdata(dev))
++ writel(val, (void __iomem *)addr);
++ else
++ pci_write_config_dword(dev, addr, val);
++}
++
/**
-@@ -298,89 +298,20 @@ static void serverworks_set_dmamode(struct ata_port *ap, struct ata_device *adev
+ * sil_udma_filter - compute UDMA mask
+ * @drive: IDE device
+@@ -136,24 +185,26 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
+
+ static u8 sil_pata_udma_filter(ide_drive_t *drive)
+ {
+- ide_hwif_t *hwif = drive->hwif;
+- struct pci_dev *dev = to_pci_dev(hwif->dev);
+- unsigned long base = (unsigned long) hwif->hwif_data;
+- u8 mask = 0, scsc = 0;
++ ide_hwif_t *hwif = drive->hwif;
++ struct pci_dev *dev = to_pci_dev(hwif->dev);
++ unsigned long base = (unsigned long)hwif->hwif_data;
++ u8 scsc, mask = 0;
+
+- if (hwif->mmio)
+- scsc = hwif->INB(base + 0x4A);
+- else
+- pci_read_config_byte(dev, 0x8A, &scsc);
++ scsc = sil_ioread8(dev, base + (hwif->mmio ? 0x4A : 0x8A));
+
+- if ((scsc & 0x30) == 0x10) /* 133 */
++ switch (scsc & 0x30) {
++ case 0x10: /* 133 */
+ mask = ATA_UDMA6;
+- else if ((scsc & 0x30) == 0x20) /* 2xPCI */
++ break;
++ case 0x20: /* 2xPCI */
+ mask = ATA_UDMA6;
+- else if ((scsc & 0x30) == 0x00) /* 100 */
++ break;
++ case 0x00: /* 100 */
+ mask = ATA_UDMA5;
+- else /* Disabled ? */
++ break;
++ default: /* Disabled ? */
+ BUG();
++ }
+
+ return mask;
}
+@@ -175,15 +226,16 @@ static u8 sil_sata_udma_filter(ide_drive_t *drive)
- 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 void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
+ {
+- const u16 tf_speed[] = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 };
+- const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 };
++ static const u16 tf_speed[] = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 };
++ static const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 };
- 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,
+ ide_hwif_t *hwif = HWIF(drive);
++ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ ide_drive_t *pair = ide_get_paired_drive(drive);
+ u32 speedt = 0;
+ u16 speedp = 0;
+ unsigned long addr = siimage_seldev(drive, 0x04);
+- unsigned long tfaddr = siimage_selreg(hwif, 0x02);
++ unsigned long tfaddr = siimage_selreg(hwif, 0x02);
+ unsigned long base = (unsigned long)hwif->hwif_data;
+ u8 tf_pio = pio;
+ u8 addr_mask = hwif->channel ? (hwif->mmio ? 0xF4 : 0x84)
+@@ -203,36 +255,20 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
+ speedp = data_speed[pio];
+ speedt = tf_speed[tf_pio];
+
+- if (hwif->mmio) {
+- hwif->OUTW(speedp, addr);
+- hwif->OUTW(speedt, tfaddr);
+- /* Now set up IORDY */
+- if (pio > 2)
+- hwif->OUTW(hwif->INW(tfaddr-2)|0x200, tfaddr-2);
+- else
+- hwif->OUTW(hwif->INW(tfaddr-2)&~0x200, tfaddr-2);
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- mode = hwif->INB(base + addr_mask);
+- mode &= ~(unit ? 0x30 : 0x03);
+- mode |= (unit ? 0x10 : 0x01);
+- hwif->OUTB(mode, base + addr_mask);
+- } else {
+- struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-- .port_start = ata_sff_port_start,
- };
+- pci_write_config_word(dev, addr, speedp);
+- pci_write_config_word(dev, tfaddr, speedt);
+- pci_read_config_word(dev, tfaddr - 2, &speedp);
+- speedp &= ~0x200;
+- /* Set IORDY for mode 3 or 4 */
+- if (pio > 2)
+- speedp |= 0x200;
+- pci_write_config_word(dev, tfaddr - 2, speedp);
+-
+- pci_read_config_byte(dev, addr_mask, &mode);
+- mode &= ~(unit ? 0x30 : 0x03);
+- mode |= (unit ? 0x10 : 0x01);
+- pci_write_config_byte(dev, addr_mask, mode);
+- }
++ sil_iowrite16(dev, speedp, addr);
++ sil_iowrite16(dev, speedt, tfaddr);
++
++ /* now set up IORDY */
++ speedp = sil_ioread16(dev, tfaddr - 2);
++ speedp &= ~0x200;
++ if (pio > 2)
++ speedp |= 0x200;
++ sil_iowrite16(dev, speedp, tfaddr - 2);
++
++ mode = sil_ioread8(dev, base + addr_mask);
++ mode &= ~(unit ? 0x30 : 0x03);
++ mode |= unit ? 0x10 : 0x01;
++ sil_iowrite8(dev, mode, base + addr_mask);
+ }
- 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,
- };
+ /**
+@@ -245,63 +281,49 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
- 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 void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
- 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);
+- u8 ultra6[] = { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 };
+- u8 ultra5[] = { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01 };
+- u16 dma[] = { 0x2208, 0x10C2, 0x10C1 };
++ static const u8 ultra6[] = { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 };
++ static const u8 ultra5[] = { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01 };
++ static const u16 dma[] = { 0x2208, 0x10C2, 0x10C1 };
- if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
-- ata_pci_clear_simplex(pdev);
-+ ata_pci_bmdma_clear_simplex(pdev);
+ ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ u16 ultra = 0, multi = 0;
+ u8 mode = 0, unit = drive->select.b.unit;
+ unsigned long base = (unsigned long)hwif->hwif_data;
+- u8 scsc = 0, addr_mask = ((hwif->channel) ?
+- ((hwif->mmio) ? 0xF4 : 0x84) :
+- ((hwif->mmio) ? 0xB4 : 0x80));
+-
++ u8 scsc = 0, addr_mask = hwif->channel ?
++ (hwif->mmio ? 0xF4 : 0x84) :
++ (hwif->mmio ? 0xB4 : 0x80);
+ unsigned long ma = siimage_seldev(drive, 0x08);
+ unsigned long ua = siimage_seldev(drive, 0x0C);
+
+- if (hwif->mmio) {
+- scsc = hwif->INB(base + 0x4A);
+- mode = hwif->INB(base + addr_mask);
+- multi = hwif->INW(ma);
+- ultra = hwif->INW(ua);
+- } else {
+- pci_read_config_byte(dev, 0x8A, &scsc);
+- pci_read_config_byte(dev, addr_mask, &mode);
+- pci_read_config_word(dev, ma, &multi);
+- pci_read_config_word(dev, ua, &ultra);
+- }
++ scsc = sil_ioread8 (dev, base + (hwif->mmio ? 0x4A : 0x8A));
++ mode = sil_ioread8 (dev, base + addr_mask);
++ multi = sil_ioread16(dev, ma);
++ ultra = sil_ioread16(dev, ua);
+
+- mode &= ~((unit) ? 0x30 : 0x03);
++ mode &= ~(unit ? 0x30 : 0x03);
+ ultra &= ~0x3F;
+ scsc = ((scsc & 0x30) == 0x00) ? 0 : 1;
+
+ scsc = is_sata(hwif) ? 1 : scsc;
+
+ if (speed >= XFER_UDMA_0) {
+- multi = dma[2];
+- ultra |= (scsc ? ultra6[speed - XFER_UDMA_0] :
+- ultra5[speed - XFER_UDMA_0]);
+- mode |= (unit ? 0x30 : 0x03);
++ multi = dma[2];
++ ultra |= scsc ? ultra6[speed - XFER_UDMA_0] :
++ ultra5[speed - XFER_UDMA_0];
++ mode |= unit ? 0x30 : 0x03;
+ } else {
+ multi = dma[speed - XFER_MW_DMA_0];
+- mode |= (unit ? 0x20 : 0x02);
++ mode |= unit ? 0x20 : 0x02;
+ }
-- return ata_pci_init_one(pdev, ppi);
-+ return ata_pci_sff_init_one(pdev, ppi, &serverworks_sht, NULL);
+- if (hwif->mmio) {
+- hwif->OUTB(mode, base + addr_mask);
+- hwif->OUTW(multi, ma);
+- hwif->OUTW(ultra, ua);
+- } else {
+- pci_write_config_byte(dev, addr_mask, mode);
+- pci_write_config_word(dev, ma, multi);
+- pci_write_config_word(dev, ua, ultra);
+- }
++ sil_iowrite8 (dev, mode, base + addr_mask);
++ sil_iowrite16(dev, multi, ma);
++ sil_iowrite16(dev, ultra, ua);
}
- #ifdef CONFIG_PM
- static int serverworks_reinit_one(struct pci_dev *pdev)
+ /* returns 1 if dma irq issued, 0 otherwise */
+-static int siimage_io_ide_dma_test_irq (ide_drive_t *drive)
++static int siimage_io_dma_test_irq(ide_drive_t *drive)
{
-+ 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);
+ ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+@@ -309,25 +331,26 @@ static int siimage_io_ide_dma_test_irq (ide_drive_t *drive)
+ unsigned long addr = siimage_selreg(hwif, 1);
-- 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
+ /* return 1 if INTR asserted */
+- if ((hwif->INB(hwif->dma_status) & 4) == 4)
++ if (hwif->INB(hwif->dma_status) & 4)
+ return 1;
-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)
+ /* return 1 if Device INTR asserted */
+ pci_read_config_byte(dev, addr, &dma_altstat);
+ if (dma_altstat & 8)
+- return 0; //return 1;
++ return 0; /* return 1; */
++
+ return 0;
}
- 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)
+- * siimage_mmio_ide_dma_test_irq - check we caused an IRQ
++ * siimage_mmio_dma_test_irq - check we caused an IRQ
+ * @drive: drive we are testing
+ *
+ * Check if we caused an IDE DMA interrupt. We may also have caused
+ * SATA status interrupts, if so we clean them up and continue.
+ */
+-
+-static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
++
++static int siimage_mmio_dma_test_irq(ide_drive_t *drive)
{
- 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");
+ ide_hwif_t *hwif = HWIF(drive);
+ unsigned long addr = siimage_selreg(hwif, 0x1);
+@@ -335,9 +358,9 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
+ = (void __iomem *)hwif->sata_scr[SATA_ERROR_OFFSET];
+
+ if (sata_error_addr) {
+- unsigned long base = (unsigned long)hwif->hwif_data;
+- u32 ext_stat = readl((void __iomem *)(base + 0x10));
+- u8 watchdog = 0;
++ unsigned long base = (unsigned long)hwif->hwif_data;
++ u32 ext_stat = readl((void __iomem *)(base + 0x10));
++ u8 watchdog = 0;
+
+ if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) {
+ u32 sata_error = readl(sata_error_addr);
+@@ -346,69 +369,32 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
+ watchdog = (sata_error & 0x00680000) ? 1 : 0;
+ printk(KERN_WARNING "%s: sata_error = 0x%08x, "
+ "watchdog = %d, %s\n",
+- drive->name, sata_error, watchdog,
+- __FUNCTION__);
+-
+- } else {
++ drive->name, sata_error, watchdog, __func__);
++ } else
+ watchdog = (ext_stat & 0x8000) ? 1 : 0;
+- }
+- ext_stat >>= 16;
-+ 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);
++ ext_stat >>= 16;
+ if (!(ext_stat & 0x0404) && !watchdog)
+ return 0;
+ }
- /* 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);
+ /* return 1 if INTR asserted */
+- if ((readb((void __iomem *)hwif->dma_status) & 0x04) == 0x04)
++ if (readb((void __iomem *)hwif->dma_status) & 0x04)
+ return 1;
- use_ioports:
-- return ata_pci_init_one(pdev, ppi);
-+ return ata_pci_sff_init_one(pdev, ppi, &sil680_sht, NULL);
+ /* return 1 if Device INTR asserted */
+- if ((readb((void __iomem *)addr) & 8) == 8)
+- return 0; //return 1;
++ if (readb((void __iomem *)addr) & 8)
++ return 0; /* return 1; */
+
+ return 0;
}
- #ifdef CONFIG_PM
- static int sil680_reinit_one(struct pci_dev *pdev)
+-/**
+- * 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)
++static int siimage_dma_test_irq(ide_drive_t *drive)
{
-- 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;
+- 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);
++ if (drive->hwif->mmio)
++ return siimage_mmio_dma_test_irq(drive);
+ 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;
++ return siimage_io_dma_test_irq(drive);
}
- #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);
+ /**
+@@ -457,63 +443,33 @@ static void sil_sata_pre_reset(ide_drive_t *drive)
}
-
/**
-- * sis_error_handler - Probe specified port on PATA host controller
-- * @ap: Port to probe
+- * proc_reports_siimage - add siimage controller to proc
+- * @dev: PCI device
+- * @clocking: SCSC value
+- * @name: controller name
- *
-- * LOCKING:
-- * None (inherited from caller).
+- * Report the clocking mode of the controller and add it to
+- * the /proc interface layer
- */
--
--static void sis_error_handler(struct ata_port *ap)
+-
+-static void proc_reports_siimage (struct pci_dev *dev, u8 clocking, const char *name)
-{
-- ata_bmdma_drive_eh(ap, sis_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+- if (!pdev_is_sata(dev)) {
+- printk(KERN_INFO "%s: BASE CLOCK ", name);
+- clocking &= 0x03;
+- switch (clocking) {
+- case 0x03: printk("DISABLED!\n"); break;
+- case 0x02: printk("== 2X PCI\n"); break;
+- case 0x01: printk("== 133\n"); break;
+- case 0x00: printk("== 100\n"); break;
+- }
+- }
-}
-
-/**
- * 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),
- };
+- * setup_mmio_siimage - switch an SI controller into MMIO
++ * setup_mmio_siimage - switch controller into MMIO mode
+ * @dev: PCI device we are configuring
+ * @name: device name
+ *
+- * Attempt to put the device into mmio mode. There are some slight
+- * complications here with certain systems where the mmio bar isnt
+- * mapped so we have to be sure we can fall back to I/O.
++ * Attempt to put the device into MMIO mode. There are some slight
++ * complications here with certain systems where the MMIO BAR isn't
++ * mapped, so we have to be sure that we can fall back to I/O.
+ */
+-
+-static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name)
++
++static unsigned int setup_mmio_siimage(struct pci_dev *dev, const char *name)
+ {
+ resource_size_t bar5 = pci_resource_start(dev, 5);
+ unsigned long barsize = pci_resource_len(dev, 5);
+- u8 tmpbyte = 0;
+ void __iomem *ioaddr;
+- u32 tmp, irq_mask;
--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,
-+};
+ /*
+- * Drop back to PIO if we can't map the mmio. Some
+- * systems seem to get terminally confused in the PCI
+- * spaces.
++ * Drop back to PIO if we can't map the MMIO. Some systems
++ * seem to get terminally confused in the PCI spaces.
+ */
+-
+- if(!request_mem_region(bar5, barsize, name))
+- {
+- printk(KERN_WARNING "siimage: IDE controller MMIO ports not available.\n");
++ if (!request_mem_region(bar5, barsize, name)) {
++ printk(KERN_WARNING "siimage: IDE controller MMIO ports not "
++ "available.\n");
+ return 0;
+ }
+-
+- ioaddr = ioremap(bar5, barsize);
-- .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,
- };
+- if (ioaddr == NULL)
+- {
++ ioaddr = ioremap(bar5, barsize);
++ if (ioaddr == NULL) {
+ release_mem_region(bar5, barsize);
+ return 0;
+ }
+@@ -521,62 +477,6 @@ static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name)
+ pci_set_master(dev);
+ pci_set_drvdata(dev, (void *) ioaddr);
--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,
+- if (pdev_is_sata(dev)) {
+- /* make sure IDE0/1 interrupts are not masked */
+- irq_mask = (1 << 22) | (1 << 23);
+- tmp = readl(ioaddr + 0x48);
+- if (tmp & irq_mask) {
+- tmp &= ~irq_mask;
+- writel(tmp, ioaddr + 0x48);
+- readl(ioaddr + 0x48); /* flush */
+- }
+- writel(0, ioaddr + 0x148);
+- writel(0, ioaddr + 0x1C8);
+- }
+-
+- writeb(0, ioaddr + 0xB4);
+- writeb(0, ioaddr + 0xF4);
+- tmpbyte = readb(ioaddr + 0x4A);
+-
+- switch(tmpbyte & 0x30) {
+- case 0x00:
+- /* In 100 MHz clocking, try and switch to 133 */
+- writeb(tmpbyte|0x10, ioaddr + 0x4A);
+- break;
+- case 0x10:
+- /* On 133Mhz clocking */
+- break;
+- case 0x20:
+- /* On PCIx2 clocking */
+- break;
+- case 0x30:
+- /* Clocking is disabled */
+- /* 133 clock attempt to force it on */
+- writeb(tmpbyte & ~0x20, ioaddr + 0x4A);
+- break;
+- }
+-
+- writeb( 0x72, ioaddr + 0xA1);
+- writew( 0x328A, ioaddr + 0xA2);
+- writel(0x62DD62DD, ioaddr + 0xA4);
+- writel(0x43924392, ioaddr + 0xA8);
+- writel(0x40094009, ioaddr + 0xAC);
+- writeb( 0x72, ioaddr + 0xE1);
+- writew( 0x328A, ioaddr + 0xE2);
+- writel(0x62DD62DD, ioaddr + 0xE4);
+- writel(0x43924392, ioaddr + 0xE8);
+- writel(0x40094009, ioaddr + 0xEC);
+-
+- if (pdev_is_sata(dev)) {
+- writel(0xFFFF0000, ioaddr + 0x108);
+- writel(0xFFFF0000, ioaddr + 0x188);
+- writel(0x00680000, ioaddr + 0x148);
+- writel(0x00680000, ioaddr + 0x1C8);
+- }
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- tmpbyte = readb(ioaddr + 0x4A);
-
-- .port_start = ata_sff_port_start,
- };
+- proc_reports_siimage(dev, (tmpbyte>>4), name);
+ return 1;
+ }
--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,
- };
+@@ -586,55 +486,92 @@ static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name)
+ * @name: device name
+ *
+ * Perform the initial PCI set up for this device. Attempt to switch
+- * to 133MHz clocking if the system isn't already set up to do it.
++ * to 133 MHz clocking if the system isn't already set up to do it.
+ */
--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 unsigned int __devinit init_chipset_siimage(struct pci_dev *dev, const char *name)
++static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev,
++ const char *name)
+ {
+- u8 rev = dev->revision, tmpbyte = 0, BA5_EN = 0;
++ unsigned long base, scsc_addr;
++ void __iomem *ioaddr = NULL;
++ u8 rev = dev->revision, tmp, BA5_EN;
+
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, rev ? 1 : 255);
+
+ pci_read_config_byte(dev, 0x8A, &BA5_EN);
+- if ((BA5_EN & 0x01) || (pci_resource_start(dev, 5))) {
+- if (setup_mmio_siimage(dev, name)) {
+- return 0;
++
++ if ((BA5_EN & 0x01) || pci_resource_start(dev, 5))
++ if (setup_mmio_siimage(dev, name))
++ ioaddr = pci_get_drvdata(dev);
++
++ base = (unsigned long)ioaddr;
++
++ if (ioaddr && pdev_is_sata(dev)) {
++ u32 tmp32, irq_mask;
++
++ /* make sure IDE0/1 interrupts are not masked */
++ irq_mask = (1 << 22) | (1 << 23);
++ tmp32 = readl(ioaddr + 0x48);
++ if (tmp32 & irq_mask) {
++ tmp32 &= ~irq_mask;
++ writel(tmp32, ioaddr + 0x48);
++ readl(ioaddr + 0x48); /* flush */
+ }
++ writel(0, ioaddr + 0x148);
++ writel(0, ioaddr + 0x1C8);
+ }
+
+- pci_write_config_byte(dev, 0x80, 0x00);
+- pci_write_config_byte(dev, 0x84, 0x00);
+- pci_read_config_byte(dev, 0x8A, &tmpbyte);
+- switch(tmpbyte & 0x30) {
+- case 0x00:
+- /* 133 clock attempt to force it on */
+- pci_write_config_byte(dev, 0x8A, tmpbyte|0x10);
+- case 0x30:
+- /* if clocking is disabled */
+- /* 133 clock attempt to force it on */
+- pci_write_config_byte(dev, 0x8A, tmpbyte & ~0x20);
+- case 0x10:
+- /* 133 already */
+- break;
+- case 0x20:
+- /* BIOS set PCI x2 clocking */
+- break;
++ sil_iowrite8(dev, 0, base ? (base + 0xB4) : 0x80);
++ sil_iowrite8(dev, 0, base ? (base + 0xF4) : 0x84);
++
++ scsc_addr = base ? (base + 0x4A) : 0x8A;
++ tmp = sil_ioread8(dev, scsc_addr);
++
++ switch (tmp & 0x30) {
++ case 0x00:
++ /* On 100 MHz clocking, try and switch to 133 MHz */
++ sil_iowrite8(dev, tmp | 0x10, scsc_addr);
++ break;
++ case 0x30:
++ /* Clocking is disabled, attempt to force 133MHz clocking. */
++ sil_iowrite8(dev, tmp & ~0x20, scsc_addr);
++ case 0x10:
++ /* On 133Mhz clocking. */
++ break;
++ case 0x20:
++ /* On PCIx2 clocking. */
++ break;
++ }
++
++ tmp = sil_ioread8(dev, scsc_addr);
++
++ sil_iowrite8 (dev, 0x72, base + 0xA1);
++ sil_iowrite16(dev, 0x328A, base + 0xA2);
++ sil_iowrite32(dev, 0x62DD62DD, base + 0xA4);
++ sil_iowrite32(dev, 0x43924392, base + 0xA8);
++ sil_iowrite32(dev, 0x40094009, base + 0xAC);
++ sil_iowrite8 (dev, 0x72, base ? (base + 0xE1) : 0xB1);
++ sil_iowrite16(dev, 0x328A, base ? (base + 0xE2) : 0xB2);
++ sil_iowrite32(dev, 0x62DD62DD, base ? (base + 0xE4) : 0xB4);
++ sil_iowrite32(dev, 0x43924392, base ? (base + 0xE8) : 0xB8);
++ sil_iowrite32(dev, 0x40094009, base ? (base + 0xEC) : 0xBC);
++
++ if (base && pdev_is_sata(dev)) {
++ writel(0xFFFF0000, ioaddr + 0x108);
++ writel(0xFFFF0000, ioaddr + 0x188);
++ writel(0x00680000, ioaddr + 0x148);
++ writel(0x00680000, ioaddr + 0x1C8);
+ }
+
+- pci_read_config_byte(dev, 0x8A, &tmpbyte);
++ /* report the clocking mode of the controller */
++ if (!pdev_is_sata(dev)) {
++ static const char *clk_str[] =
++ { "== 100", "== 133", "== 2X PCI", "DISABLED!" };
+
+- pci_write_config_byte(dev, 0xA1, 0x72);
+- pci_write_config_word(dev, 0xA2, 0x328A);
+- pci_write_config_dword(dev, 0xA4, 0x62DD62DD);
+- pci_write_config_dword(dev, 0xA8, 0x43924392);
+- pci_write_config_dword(dev, 0xAC, 0x40094009);
+- pci_write_config_byte(dev, 0xB1, 0x72);
+- pci_write_config_word(dev, 0xB2, 0x328A);
+- pci_write_config_dword(dev, 0xB4, 0x62DD62DD);
+- pci_write_config_dword(dev, 0xB8, 0x43924392);
+- pci_write_config_dword(dev, 0xBC, 0x40094009);
++ tmp >>= 4;
++ printk(KERN_INFO "%s: BASE CLOCK %s\n", name, clk_str[tmp & 3]);
++ }
+
+- proc_reports_siimage(dev, (tmpbyte>>4), name);
+ return 0;
+ }
+
+@@ -644,8 +581,7 @@ static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev, const ch
+ *
+ * The basic setup here is fairly simple, we can use standard MMIO
+ * operations. However we do have to set the taskfile register offsets
+- * by hand as there isnt a standard defined layout for them this
+- * time.
++ * by hand as there isn't a standard defined layout for them this time.
+ *
+ * The hardware supports buffered taskfiles and also some rather nice
+ * extended PRD tables. For better SI3112 support use the libata driver
+@@ -656,23 +592,21 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ void *addr = pci_get_drvdata(dev);
+ u8 ch = hwif->channel;
+- hw_regs_t hw;
+- unsigned long base;
++ struct ide_io_ports *io_ports = &hwif->io_ports;
++ unsigned long base;
--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,
+ /*
+- * Fill in the basic HWIF bits
++ * Fill in the basic hwif bits
+ */
-
-- .port_start = ata_sff_port_start,
- };
++ hwif->host_flags |= IDE_HFLAG_MMIO;
+ default_hwif_mmiops(hwif);
+- hwif->hwif_data = addr;
++ hwif->hwif_data = addr;
--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,
+ /*
+- * Now set up the hw. We have to do this ourselves as
+- * the MMIO layout isnt the same as the standard port
+- * based I/O
++ * Now set up the hw. We have to do this ourselves as the
++ * MMIO layout isn't the same as the standard port based I/O.
+ */
-
-- .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;
+- memset(&hw, 0, sizeof(hw_regs_t));
++ memset(io_ports, 0, sizeof(*io_ports));
-+ /* 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;
+ base = (unsigned long)addr;
+ if (ch)
+@@ -681,21 +615,18 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
+ base += 0x80;
-- port = *chipset->info;
-- port.private_data = chipset;
-+ ppi[0] = chipset->info;
+ /*
+- * The buffered task file doesn't have status/control
+- * so we can't currently use it sanely since we want to
+- * use LBA48 mode.
+- */
+- hw.io_ports[IDE_DATA_OFFSET] = base;
+- hw.io_ports[IDE_ERROR_OFFSET] = base + 1;
+- hw.io_ports[IDE_NSECTOR_OFFSET] = base + 2;
+- hw.io_ports[IDE_SECTOR_OFFSET] = base + 3;
+- hw.io_ports[IDE_LCYL_OFFSET] = base + 4;
+- hw.io_ports[IDE_HCYL_OFFSET] = base + 5;
+- hw.io_ports[IDE_SELECT_OFFSET] = base + 6;
+- hw.io_ports[IDE_STATUS_OFFSET] = base + 7;
+- hw.io_ports[IDE_CONTROL_OFFSET] = base + 10;
+-
+- hw.io_ports[IDE_IRQ_OFFSET] = 0;
++ * The buffered task file doesn't have status/control, so we
++ * can't currently use it sanely since we want to use LBA48 mode.
++ */
++ io_ports->data_addr = base;
++ io_ports->error_addr = base + 1;
++ io_ports->nsect_addr = base + 2;
++ io_ports->lbal_addr = base + 3;
++ io_ports->lbam_addr = base + 4;
++ io_ports->lbah_addr = base + 5;
++ io_ports->device_addr = base + 6;
++ io_ports->status_addr = base + 7;
++ io_ports->ctl_addr = base + 10;
+
+ if (pdev_is_sata(dev)) {
+ base = (unsigned long)addr;
+@@ -706,8 +637,6 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
+ hwif->sata_scr[SATA_CONTROL_OFFSET] = base + 0x100;
+ }
+
+- memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
+-
+ hwif->irq = dev->irq;
+
+ hwif->dma_base = (unsigned long)addr + (ch ? 0x08 : 0x00);
+@@ -717,19 +646,17 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
+
+ static int is_dev_seagate_sata(ide_drive_t *drive)
+ {
+- const char *s = &drive->id->model[0];
+- unsigned len;
++ const char *s = &drive->id->model[0];
++ unsigned len = strnlen(s, sizeof(drive->id->model));
+
+- len = strnlen(s, sizeof(drive->id->model));
+-
+- if ((len > 4) && (!memcmp(s, "ST", 2))) {
++ if ((len > 4) && (!memcmp(s, "ST", 2)))
+ if ((!memcmp(s + len - 2, "AS", 2)) ||
+ (!memcmp(s + len - 3, "ASL", 3))) {
+ printk(KERN_INFO "%s: applying pessimistic Seagate "
+ "errata fix\n", drive->name);
+ return 1;
+ }
+- }
++
+ return 0;
+ }
- sis_fixup(pdev, chipset);
+@@ -746,7 +673,7 @@ static void __devinit sil_quirkproc(ide_drive_t *drive)
+ {
+ ide_hwif_t *hwif = drive->hwif;
-- return ata_pci_init_one(pdev, ppi);
-+ return ata_pci_sff_init_one(pdev, ppi, &sis_sht, chipset);
+- /* Try and raise the rqsize */
++ /* Try and rise the rqsize */
+ if (!is_sata(hwif) || !is_dev_seagate_sata(drive))
+ hwif->rqsize = 128;
+ }
+@@ -777,104 +704,98 @@ static void __devinit init_iops_siimage(ide_hwif_t *hwif)
}
- 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)
+ /**
+- * ata66_siimage - check for 80 pin cable
++ * sil_cable_detect - cable detection
+ * @hwif: interface to check
+ *
+- * Check for the presence of an ATA66 capable cable on the
+- * interface.
++ * Check for the presence of an ATA66 capable cable on the interface.
+ */
- if (ap->port_no && !pci_test_config_bits(pdev, &sl82c105_enable_bits[ap->port_no]))
- return -ENOENT;
-- return ata_std_prereset(link, deadline);
--}
--
+-static u8 __devinit ata66_siimage(ide_hwif_t *hwif)
++static u8 __devinit sil_cable_detect(ide_hwif_t *hwif)
+ {
+- struct pci_dev *dev = to_pci_dev(hwif->dev);
+- unsigned long addr = siimage_selreg(hwif, 0);
+- u8 ata66 = 0;
-
--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);
- }
-
+- if (pci_get_drvdata(dev) == NULL)
+- pci_read_config_byte(dev, addr, &ata66);
+- else
+- ata66 = hwif->INB(addr);
++ struct pci_dev *dev = to_pci_dev(hwif->dev);
++ unsigned long addr = siimage_selreg(hwif, 0);
++ u8 ata66 = sil_ioread8(dev, addr);
-@@ -235,55 +229,17 @@ static int sl82c105_qc_defer(struct ata_queued_cmd *qc)
+ return (ata66 & 0x01) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
}
- 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,
+-/**
+- * init_hwif_siimage - set up hwif structs
+- * @hwif: interface to set up
+- *
+- * We do the basic set up of the interface structure. The SIIMAGE
+- * requires several custom handlers so we override the default
+- * ide DMA handlers appropriately
+- */
-
-- .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,
+-static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
+-{
+- u8 sata = is_sata(hwif);
-
-- .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,
+- hwif->set_pio_mode = &sil_set_pio_mode;
+- hwif->set_dma_mode = &sil_set_dma_mode;
+- hwif->quirkproc = &sil_quirkproc;
-
-- .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,
+- if (sata) {
+- static int first = 1;
-
-- .qc_defer = sl82c105_qc_defer,
-- .qc_prep = ata_qc_prep,
-- .qc_issue = ata_qc_issue_prot,
+- 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;
-
-- .data_xfer = ata_data_xfer,
+- if (first) {
+- printk(KERN_INFO "siimage: For full SATA support you should use the libata sata_sil module.\n");
+- first = 0;
+- }
+- } else
+- hwif->udma_filter = &sil_pata_udma_filter;
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- hwif->cable_detect = ata66_siimage;
-
-- .port_start = ata_sff_port_start,
-+ .cable_detect = ata_cable_40wire,
-+ .set_piomode = sl82c105_set_piomode,
-+ .prereset = sl82c105_pre_reset,
+- if (hwif->dma_base == 0)
+- return;
++static const struct ide_port_ops sil_pata_port_ops = {
++ .set_pio_mode = sil_set_pio_mode,
++ .set_dma_mode = sil_set_dma_mode,
++ .quirkproc = sil_quirkproc,
++ .udma_filter = sil_pata_udma_filter,
++ .cable_detect = sil_cable_detect,
++};
+
+- if (sata)
+- hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
++static const struct ide_port_ops sil_sata_port_ops = {
++ .set_pio_mode = sil_set_pio_mode,
++ .set_dma_mode = sil_set_dma_mode,
++ .reset_poll = sil_sata_reset_poll,
++ .pre_reset = sil_sata_pre_reset,
++ .quirkproc = sil_quirkproc,
++ .udma_filter = sil_sata_udma_filter,
++ .cable_detect = sil_cable_detect,
++};
+
+- if (hwif->mmio) {
+- hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq;
+- } else {
+- hwif->ide_dma_test_irq = & siimage_io_ide_dma_test_irq;
+- }
+-}
++static const struct ide_dma_ops sil_dma_ops = {
++ .dma_host_set = ide_dma_host_set,
++ .dma_setup = ide_dma_setup,
++ .dma_exec_cmd = ide_dma_exec_cmd,
++ .dma_start = ide_dma_start,
++ .dma_end = __ide_dma_end,
++ .dma_test_irq = siimage_dma_test_irq,
++ .dma_timeout = ide_dma_timeout,
++ .dma_lost_irq = ide_dma_lost_irq,
++};
+
+-#define DECLARE_SII_DEV(name_str) \
++#define DECLARE_SII_DEV(name_str, p_ops) \
+ { \
+ .name = name_str, \
+ .init_chipset = init_chipset_siimage, \
+ .init_iops = init_iops_siimage, \
+- .init_hwif = init_hwif_siimage, \
+- .host_flags = IDE_HFLAG_BOOTABLE, \
++ .port_ops = p_ops, \
++ .dma_ops = &sil_dma_ops, \
+ .pio_mask = ATA_PIO4, \
+ .mwdma_mask = ATA_MWDMA2, \
+ .udma_mask = ATA_UDMA6, \
+ }
+
+ static const struct ide_port_info siimage_chipsets[] __devinitdata = {
+- /* 0 */ DECLARE_SII_DEV("SiI680"),
+- /* 1 */ DECLARE_SII_DEV("SiI3112 Serial ATA"),
+- /* 2 */ DECLARE_SII_DEV("Adaptec AAR-1210SA")
++ /* 0 */ DECLARE_SII_DEV("SiI680", &sil_pata_port_ops),
++ /* 1 */ DECLARE_SII_DEV("SiI3112 Serial ATA", &sil_sata_port_ops),
++ /* 2 */ DECLARE_SII_DEV("Adaptec AAR-1210SA", &sil_sata_port_ops)
};
/**
-@@ -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)
+- * siimage_init_one - pci layer discovery entry
++ * siimage_init_one - PCI layer discovery entry
+ * @dev: PCI device
+ * @id: ident table entry
+ *
+- * Called by the PCI code when it finds an SI680 or SI3112 controller.
++ * Called by the PCI code when it finds an SiI680 or SiI3112 controller.
+ * We then use the IDE PCI generic helper to do most of the work.
+ */
+-
+-static int __devinit siimage_init_one(struct pci_dev *dev, const struct pci_device_id *id)
++
++static int __devinit siimage_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;
+- return ide_setup_pci_device(dev, &siimage_chipsets[id->driver_data]);
++ struct ide_port_info d;
++ u8 idx = id->driver_data;
+
-+ 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);
++ d = siimage_chipsets[idx];
++
++ if (idx) {
++ static int first = 1;
++
++ if (first) {
++ printk(KERN_INFO "siimage: For full SATA support you "
++ "should use the libata sata_sil module.\n");
++ first = 0;
++ }
++
++ d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
++ }
++
++ return ide_setup_pci_device(dev, &d);
}
+ static const struct pci_device_id siimage_pci_tbl[] = {
+diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
+index 512bb4c..4b0b85d 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;
--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)
- }
+@@ -111,69 +111,70 @@ static const struct {
+ Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */
- 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),
+ /* {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 */
};
-
- 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,
+ /* 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 },
};
- static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ /*
+ * 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)
{
- 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");
+ ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+@@ -346,7 +347,7 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ sis_program_timings(drive, speed);
+ }
-- return ata_pci_init_one(dev, ppi);
-+ return ata_pci_sff_init_one(dev, ppi, &triflex_sht, NULL);
+-static u8 sis5513_ata133_udma_filter(ide_drive_t *drive)
++static u8 sis_ata133_udma_filter(ide_drive_t *drive)
+ {
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+ u32 regdw = 0;
+@@ -358,8 +359,7 @@ static u8 sis5513_ata133_udma_filter(ide_drive_t *drive)
+ return (regdw & 0x08) ? ATA_UDMA6 : ATA_UDMA5;
}
- 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;
+-/* 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
+ }
}
-- return ata_std_prereset(link, deadline);
-+ return ata_sff_prereset(link, deadline);
- }
+- 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 */
- /**
-- * via_error_handler - reset for VIA chips
-- * @ap: ATA port
-- *
-- * Handle the reset callback for the later chips with cable detect
-- */
+- {
+- u8 reg;
+- u16 regw;
-
--static void via_error_handler(struct ata_port *ap)
--{
-- ata_bmdma_drive_eh(ap, via_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
--}
+- 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);
-
--/**
- * 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)
- }
+- /* 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;
+ }
- 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),
+ return 0;
+@@ -517,7 +514,7 @@ static const struct sis_laptop sis_laptop[] = {
+ { 0, }
};
- 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 u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
++static u8 __devinit sis_cable_detect(ide_hwif_t *hwif)
+ {
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
+ const struct sis_laptop *lap = &sis_laptop[0];
+@@ -546,38 +543,44 @@ static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
+ return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+ }
- 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,
+-static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
+-{
+- u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f };
-
-- .qc_prep = ata_qc_prep,
-- .qc_issue = ata_qc_issue_prot,
+- hwif->set_pio_mode = &sis_set_pio_mode;
+- hwif->set_dma_mode = &sis_set_dma_mode;
-
-- .data_xfer = ata_data_xfer_noirq,
+- if (chipset_family >= ATA_133)
+- hwif->udma_filter = sis5513_ata133_udma_filter;
-
-- .irq_handler = ata_interrupt,
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- hwif->cable_detect = ata66_sis5513;
-
-- .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 (hwif->dma_base == 0)
+- return;
++static const struct ide_port_ops sis_port_ops = {
++ .set_pio_mode = sis_set_pio_mode,
++ .set_dma_mode = sis_set_dma_mode,
++ .cable_detect = sis_cable_detect,
++};
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+- hwif->ultra_mask = udma_rates[chipset_family];
+-}
++static const struct ide_port_ops sis_ata133_port_ops = {
++ .set_pio_mode = sis_set_pio_mode,
++ .set_dma_mode = sis_set_dma_mode,
++ .udma_filter = sis_ata133_udma_filter,
++ .cable_detect = sis_cable_detect,
++};
-+ 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)
- }
+ 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,
+ };
- /* 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);
+ 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;
++
++ if (chipset_family >= ATA_133)
++ d.port_ops = &sis_ata133_port_ops;
++ else
++ d.port_ops = &sis_port_ops;
++
++ d.udma_mask = udma_rates[chipset_family];
++
++ return ide_setup_pci_device(dev, &d);
}
- #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;
+ 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..ce84fa0 100644
+--- a/drivers/ide/pci/sl82c105.c
++++ b/drivers/ide/pci/sl82c105.c
+@@ -179,7 +179,7 @@ static void sl82c105_dma_start(ide_drive_t *drive)
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ int reg = 0x44 + drive->dn * 4;
- via_config_fifo(pdev, config->flags);
+- DBG(("%s(drive:%s)\n", __FUNCTION__, drive->name));
++ DBG(("%s(drive:%s)\n", __func__, drive->name));
-@@ -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
+ pci_write_config_word(dev, reg, drive->drive_data >> 16);
-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);
+@@ -203,7 +203,7 @@ static int sl82c105_dma_end(ide_drive_t *drive)
+ int reg = 0x44 + drive->dn * 4;
+ int ret;
- return buflen;
- }
+- DBG(("%s(drive:%s)\n", __FUNCTION__, drive->name));
++ DBG(("%s(drive:%s)\n", __func__, drive->name));
- 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),
- };
+ ret = __ide_dma_end(drive);
- static struct ata_port_operations winbond_port_ops = {
-- .set_piomode = winbond_set_piomode,
+@@ -232,7 +232,7 @@ static void sl82c105_resetproc(ide_drive_t *drive)
+ * Return the revision of the Winbond bridge
+ * which this function is part of.
+ */
+-static unsigned int sl82c105_bridge_revision(struct pci_dev *dev)
++static u8 sl82c105_bridge_revision(struct pci_dev *dev)
+ {
+ struct pci_dev *bridge;
+
+@@ -282,60 +282,59 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c
+ return dev->irq;
+ }
+
+-/*
+- * Initialise IDE channel
+- */
+-static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
+-{
+- struct pci_dev *dev = to_pci_dev(hwif->dev);
+- unsigned int rev;
-
-- .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,
+- DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index));
-
-- .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,
+- hwif->set_pio_mode = &sl82c105_set_pio_mode;
+- hwif->set_dma_mode = &sl82c105_set_dma_mode;
+- hwif->resetproc = &sl82c105_resetproc;
-
-- .qc_prep = ata_qc_prep,
-- .qc_issue = ata_qc_issue_prot,
+- if (!hwif->dma_base)
+- return;
-
-- .data_xfer = winbond_data_xfer,
+- rev = sl82c105_bridge_revision(dev);
+- if (rev <= 5) {
+- /*
+- * Never ever EVER under any circumstances enable
+- * DMA when the bridge is this old.
+- */
+- printk(" %s: Winbond W83C553 bridge revision %d, "
+- "BM-DMA disabled\n", hwif->name, rev);
+- return;
+- }
-
-- .irq_clear = ata_bmdma_irq_clear,
-- .irq_on = ata_irq_on,
+- hwif->mwdma_mask = ATA_MWDMA2;
-
-- .port_start = ata_sff_port_start,
-+ .set_piomode = winbond_set_piomode,
+- hwif->dma_lost_irq = &sl82c105_dma_lost_irq;
+- hwif->dma_start = &sl82c105_dma_start;
+- hwif->ide_dma_end = &sl82c105_dma_end;
+- hwif->dma_timeout = &sl82c105_dma_timeout;
++static const struct ide_port_ops sl82c105_port_ops = {
++ .set_pio_mode = sl82c105_set_pio_mode,
++ .set_dma_mode = sl82c105_set_dma_mode,
++ .resetproc = sl82c105_resetproc,
++};
+
+- if (hwif->mate)
+- hwif->serialized = hwif->mate->serialized = 1;
+-}
++static const struct ide_dma_ops sl82c105_dma_ops = {
++ .dma_host_set = ide_dma_host_set,
++ .dma_setup = ide_dma_setup,
++ .dma_exec_cmd = ide_dma_exec_cmd,
++ .dma_start = sl82c105_dma_start,
++ .dma_end = sl82c105_dma_end,
++ .dma_test_irq = ide_dma_test_irq,
++ .dma_lost_irq = sl82c105_dma_lost_irq,
++ .dma_timeout = sl82c105_dma_timeout,
++};
+
+ static const struct ide_port_info sl82c105_chipset __devinitdata = {
+ .name = "W82C105",
+ .init_chipset = init_chipset_sl82c105,
+- .init_hwif = init_hwif_sl82c105,
+ .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}},
++ .port_ops = &sl82c105_port_ops,
++ .dma_ops = &sl82c105_dma_ops,
+ .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_SERIALIZE_DMA |
++ IDE_HFLAG_NO_AUTODMA,
+ .pio_mask = ATA_PIO5,
++ .mwdma_mask = ATA_MWDMA2,
};
- /**
-@@ -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);
+ static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+- return ide_setup_pci_device(dev, &sl82c105_chipset);
++ struct ide_port_info d = sl82c105_chipset;
++ u8 rev = sl82c105_bridge_revision(dev);
++
++ if (rev <= 5) {
++ /*
++ * Never ever EVER under any circumstances enable
++ * DMA when the bridge is this old.
++ */
++ printk(KERN_INFO "W82C105_IDE: Winbond W83C553 bridge "
++ "revision %d, BM-DMA disabled\n", rev);
++ d.dma_ops = NULL;
++ d.mwdma_mask = 0;
++ d.host_flags &= ~IDE_HFLAG_SERIALIZE_DMA;
++ }
++
++ return ide_setup_pci_device(dev, &d);
+ }
- /* 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;
+ static const struct pci_device_id sl82c105_pci_tbl[] = {
+diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
+index 65f4c2f..dae6e2c 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 },
+@@ -125,19 +125,17 @@ static u8 __devinit slc90e66_cable_detect(ide_hwif_t *hwif)
+ return (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+ }
- /* 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 void __devinit init_hwif_slc90e66(ide_hwif_t *hwif)
+-{
+- hwif->set_pio_mode = &slc90e66_set_pio_mode;
+- hwif->set_dma_mode = &slc90e66_set_dma_mode;
+-
+- hwif->cable_detect = slc90e66_cable_detect;
+-}
++static const struct ide_port_ops slc90e66_port_ops = {
++ .set_pio_mode = slc90e66_set_pio_mode,
++ .set_dma_mode = slc90e66_set_dma_mode,
++ .cable_detect = slc90e66_cable_detect,
++};
- 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 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} },
++ .port_ops = &slc90e66_port_ops,
++ .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..9b4b27a 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);
--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,
- };
+ 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;
+ }
- 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 */
+ 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 void adma_bmdma_stop(struct ata_queued_cmd *qc)
+-static int tc86c001_busproc(ide_drive_t *drive, int state)
-{
-- /* nothing */
--}
+- ide_hwif_t *hwif = HWIF(drive);
+- unsigned long sc_base = hwif->config_data;
+- u16 scr1;
-
--static u8 adma_bmdma_status(struct ata_port *ap)
--{
-- return 0;
--}
+- /* System Control 1 Register bit 11 (ATA Hard Reset) read */
+- scr1 = inw(sc_base + 0x00);
-
--static void adma_irq_clear(struct ata_port *ap)
--{
-- /* nothing */
+- 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 void adma_reset_engine(struct ata_port *ap)
+ static u8 __devinit tc86c001_cable_detect(ide_hwif_t *hwif)
{
- 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)
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+@@ -191,13 +157,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
+ /* Store the system control register base for convenience... */
+ hwif->config_data = sc_base;
- /* mask/clear ATA interrupts */
- writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
-- ata_check_status(ap);
-+ ata_sff_check_status(ap);
+- 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)
+ return;
- /* 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);
+@@ -209,8 +168,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
-- return ata_std_prereset(link, deadline);
--}
+ /* Sector Count Register limit */
+ hwif->rqsize = 0xffff;
-
--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);
+- hwif->dma_start = &tc86c001_dma_start;
}
- static int adma_fill_sg(struct ata_queued_cmd *qc)
-@@ -366,7 +322,7 @@ static void adma_qc_prep(struct ata_queued_cmd *qc)
+ static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev,
+@@ -223,10 +180,29 @@ static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev,
+ return err;
+ }
- adma_enter_reg_mode(qc->ap);
- if (qc->tf.protocol != ATA_PROT_DMA) {
-- ata_qc_prep(qc);
-+ ata_sff_qc_prep(qc);
- return;
- }
++static const struct ide_port_ops tc86c001_port_ops = {
++ .set_pio_mode = tc86c001_set_pio_mode,
++ .set_dma_mode = tc86c001_set_mode,
++ .cable_detect = tc86c001_cable_detect,
++};
++
++static const struct ide_dma_ops tc86c001_dma_ops = {
++ .dma_host_set = ide_dma_host_set,
++ .dma_setup = ide_dma_setup,
++ .dma_exec_cmd = ide_dma_exec_cmd,
++ .dma_start = tc86c001_dma_start,
++ .dma_end = __ide_dma_end,
++ .dma_test_irq = ide_dma_test_irq,
++ .dma_lost_irq = ide_dma_lost_irq,
++ .dma_timeout = ide_dma_timeout,
++};
++
+ static const struct ide_port_info tc86c001_chipset __devinitdata = {
+ .name = "TC86C001",
+ .init_chipset = init_chipset_tc86c001,
+ .init_hwif = init_hwif_tc86c001,
++ .port_ops = &tc86c001_port_ops,
++ .dma_ops = &tc86c001_dma_ops,
+ .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD |
+ IDE_HFLAG_ABUSE_SET_DMA_MODE,
+ .pio_mask = ATA_PIO4,
+diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
+index a67d02a..db65a55 100644
+--- a/drivers/ide/pci/triflex.c
++++ b/drivers/ide/pci/triflex.c
+@@ -87,17 +87,15 @@ static void triflex_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ triflex_set_mode(drive, XFER_PIO_0 + pio);
+ }
-@@ -465,7 +421,7 @@ static unsigned int adma_qc_issue(struct ata_queued_cmd *qc)
- }
+-static void __devinit init_hwif_triflex(ide_hwif_t *hwif)
+-{
+- hwif->set_pio_mode = &triflex_set_pio_mode;
+- hwif->set_dma_mode = &triflex_set_mode;
+-}
++static const struct ide_port_ops triflex_port_ops = {
++ .set_pio_mode = triflex_set_pio_mode,
++ .set_dma_mode = triflex_set_mode,
++};
- pp->state = adma_state_mmio;
-- return ata_qc_issue_prot(qc);
-+ return ata_sff_qc_issue(qc);
+ 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,
++ .port_ops = &triflex_port_ops,
+ .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..a8a3138 100644
+--- a/drivers/ide/pci/trm290.c
++++ b/drivers/ide/pci/trm290.c
+@@ -214,7 +214,7 @@ static void trm290_dma_start(ide_drive_t *drive)
+ {
}
- 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))) {
+-static int trm290_ide_dma_end (ide_drive_t *drive)
++static int trm290_dma_end(ide_drive_t *drive)
+ {
+ u16 status;
- /* 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);
+@@ -225,7 +225,7 @@ static int trm290_ide_dma_end (ide_drive_t *drive)
+ return status != 0x00ff;
}
--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)
+-static int trm290_ide_dma_test_irq (ide_drive_t *drive)
++static int trm290_dma_test_irq(ide_drive_t *drive)
{
- 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,
+ u16 status;
- 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;
+@@ -254,22 +254,11 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
+ hwif->config_data = cfg_base;
+ hwif->dma_base = (cfg_base + 4) ^ (hwif->channel ? 0x80 : 0);
+
+- printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx",
++ printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n",
+ hwif->name, hwif->dma_base, hwif->dma_base + 3);
+
+- if (!request_region(hwif->dma_base, 4, hwif->name)) {
+- printk(KERN_CONT " -- Error, ports in use.\n");
++ if (ide_allocate_dma_engine(hwif))
+ return;
+- }
-
-- /*
-- * 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.
-- */
+- hwif->dmatable_cpu = pci_alloc_consistent(dev, PRD_ENTRIES * PRD_BYTES,
+- &hwif->dmatable_dma);
+- if (!hwif->dmatable_cpu) {
+- printk(KERN_CONT " -- Error, unable to allocate DMA table.\n");
+- release_region(hwif->dma_base, 4);
+- return;
+- }
+- printk(KERN_CONT "\n");
+
+ local_irq_save(flags);
+ /* put config reg into first byte of hwif->select_data */
+@@ -291,14 +280,6 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
+ /* sharing IRQ with mate */
+ hwif->irq = hwif->mate->irq;
+
+- hwif->dma_host_set = &trm290_dma_host_set;
+- hwif->dma_setup = &trm290_dma_setup;
+- hwif->dma_exec_cmd = &trm290_dma_exec_cmd;
+- hwif->dma_start = &trm290_dma_start;
+- hwif->ide_dma_end = &trm290_ide_dma_end;
+- hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq;
-
-- struct ata_taskfile tf;
+- hwif->selectproc = &trm290_selectproc;
+ #if 1
+ {
+ /*
+@@ -317,7 +298,7 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
+ if (old != compat && old_mask == 0xff) {
+ /* leave lower 10 bits untouched */
+ compat += (next_offset += 0x400);
+- hwif->io_ports[IDE_CONTROL_OFFSET] = compat + 2;
++ hwif->io_ports.ctl_addr = compat + 2;
+ outw(compat | 1, hwif->config_data);
+ new = inw(hwif->config_data);
+ printk(KERN_INFO "%s: control basereg workaround: "
+@@ -328,16 +309,32 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
+ #endif
+ }
+
++static const struct ide_port_ops trm290_port_ops = {
++ .selectproc = trm290_selectproc,
++};
++
++static struct ide_dma_ops trm290_dma_ops = {
++ .dma_host_set = trm290_dma_host_set,
++ .dma_setup = trm290_dma_setup,
++ .dma_exec_cmd = trm290_dma_exec_cmd,
++ .dma_start = trm290_dma_start,
++ .dma_end = trm290_dma_end,
++ .dma_test_irq = trm290_dma_test_irq,
++ .dma_lost_irq = ide_dma_lost_irq,
++ .dma_timeout = ide_dma_timeout,
++};
++
+ static const struct ide_port_info trm290_chipset __devinitdata = {
+ .name = "TRM290",
+ .init_hwif = init_hwif_trm290,
+ .chipset = ide_trm290,
++ .port_ops = &trm290_port_ops,
++ .dma_ops = &trm290_dma_ops,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
+ #if 0 /* play it safe for now */
+ IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+ #endif
+ IDE_HFLAG_NO_AUTODMA |
+- IDE_HFLAG_BOOTABLE |
+ IDE_HFLAG_NO_LBA48,
};
- /*
-@@ -465,6 +453,20 @@ static unsigned int sata_fsl_qc_issue(struct ata_queued_cmd *qc)
- return 0;
- }
+diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
+index 9004e75..566e0ec 100644
+--- a/drivers/ide/pci/via82cxxx.c
++++ b/drivers/ide/pci/via82cxxx.c
+@@ -340,7 +340,7 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const
+ * Determine system bus clock.
+ */
-+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));
+- via_clock = system_bus_clock() * 1000;
++ via_clock = (ide_pci_clk ? ide_pci_clk : system_bus_clock()) * 1000;
+
+ switch (via_clock) {
+ case 33000: via_clock = 33333; break;
+@@ -415,25 +415,21 @@ static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif)
+ return ATA_CBL_PATA40;
}
--/*
-- * 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)
+-static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
-{
-- struct sata_fsl_port_priv *pp = ap->private_data;
+- hwif->set_pio_mode = &via_set_pio_mode;
+- hwif->set_dma_mode = &via_set_drive;
-
-- *tf = pp->tf;
+- hwif->cable_detect = via82cxxx_cable_detect;
-}
--
- 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 const struct ide_port_ops via_port_ops = {
++ .set_pio_mode = via_set_pio_mode,
++ .set_dma_mode = via_set_drive,
++ .cable_detect = via82cxxx_cable_detect,
++};
-+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 const struct ide_port_info via82cxxx_chipset __devinitdata = {
+ .name = "VP_IDE",
+ .init_chipset = init_chipset_via82cxxx,
+- .init_hwif = init_hwif_via82cxxx,
+ .enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
++ .port_ops = &via_port_ops,
+ .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..f0e638d 100644
+--- a/drivers/ide/ppc/mpc8xx.c
++++ b/drivers/ide/ppc/mpc8xx.c
+@@ -36,6 +36,8 @@
+ #include <asm/machdep.h>
+ #include <asm/irq.h>
+
++#define DRV_NAME "ide-mpc8xx"
+
- static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline)
- {
-@@ -913,16 +892,6 @@ err:
- return -EIO;
- }
+ 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 )
--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)
+-/*
+- * IDE stuff.
+- */
+-static int
+-m8xx_ide_default_irq(unsigned long base)
-{
-- /* unused */
+-#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 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)
+-static unsigned long
+-m8xx_ide_default_io_base(int index)
-{
-- if (qc->flags & ATA_QCFLAG_RESULT_TF) {
-- DPRINTK("xx_qc_complete called\n");
-- sata_fsl_cache_taskfile_from_d2h_fis(qc, qc->ap);
-- }
+- return index;
-}
-
- 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));
+ #define M8XX_PCMCIA_CD2(slot) (0x10000000 >> (slot << 4))
+ #define M8XX_PCMCIA_CD1(slot) (0x08000000 >> (slot << 4))
-- 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
+@@ -149,14 +125,13 @@ static int pcmcia_schlvl = PCMCIA_SCHLVL;
*/
- 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,
+ /*
+- * 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;
++ unsigned long *p = hw->io_ports_array;
+ int i;
- .scr_read = sata_fsl_scr_read,
- .scr_write = sata_fsl_scr_write,
+ typedef struct {
+@@ -173,8 +148,6 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ unsigned long base;
- .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,
+ *p = 0;
+- if (irq)
+- *irq = 0;
- .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;
+ pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
-- /* 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);
+@@ -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);
-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 {
- };
++ 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);
- 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),
- };
+@@ -248,9 +228,6 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ }
+ }
- 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);
+- 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 */
+ }
- /* issue r/w command */
-- ap->ops->exec_command(ap, &qc->tf);
-+ ap->ops->sff_exec_command(ap, &qc->tf);
- }
+ 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];
+ }
- 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;
- }
+- 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;
--static void inic_irq_clear(struct ata_port *ap)
--{
-- /* noop */
--}
+- *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 */
+ }
-
- 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);
+- 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 */
- 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;
- }
+ /* Enable Harddisk Interrupt,
+ * and make it edge sensitive
+@@ -329,18 +302,19 @@ 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 */
-- if (likely(ata_host_intr(ap, qc)))
-+ if (likely(ata_sff_host_intr(ap, qc)))
- return;
+ /*
+- * 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;
++ unsigned long *p = hw->io_ports_array;
+ int i;
-- 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;
- }
+ u32 ide_phy_base;
+@@ -349,8 +323,6 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
+ unsigned long base;
-- return ata_qc_issue_prot(qc);
-+ return ata_sff_qc_issue(qc);
- }
+ *p = 0;
+- if (irq)
+- *irq = 0;
- static void inic_freeze(struct ata_port *ap)
-@@ -384,7 +365,7 @@ static void inic_freeze(struct ata_port *ap)
+ if (!ide_base) {
- __inic_set_pirq_mask(ap, PIRQ_MASK_FREEZE);
+@@ -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);
-- ata_chk_status(ap);
-+ ap->ops->sff_check_status(ap);
- writeb(0xff, port_base + PORT_IRQ_STAT);
+@@ -372,9 +349,6 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
+ #endif
+ }
- 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);
+- 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];
+ }
-- ata_chk_status(ap);
-+ ap->ops->sff_check_status(ap);
- writeb(0xff, port_base + PORT_IRQ_STAT);
+- 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;
- __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;
+ /* 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 */
-- /* 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;
- }
++ return 0;
++}
+ #endif /* CONFIG_IDE_8xx_DIRECT */
-- 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);
+@@ -468,10 +438,14 @@ static void m8xx_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ #elif defined(CONFIG_IDE_EXT_DIRECT)
- /* 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);
+ printk("%s[%d] %s: not implemented yet!\n",
+- __FILE__,__LINE__,__FUNCTION__);
++ __FILE__, __LINE__, __func__);
+ #endif /* defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_PCMCIA */
}
- 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 const struct ide_port_ops m8xx_port_ops = {
++ .set_pio_mode = m8xx_ide_set_pio_mode,
++};
++
+ static void
+ ide_interrupt_ack (void *dev)
+ {
+@@ -829,21 +803,37 @@ static int identify (volatile u8 *p)
+ return (0); /* don't know */
}
- 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,
+-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;
+-}
-
-- .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,
+ static int __init mpc8xx_ide_probe(void)
+ {
++ hw_regs_t hw;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-- .port_resume = inic_port_resume,
-+ .scr_read = inic_scr_read,
-+ .scr_write = inic_scr_write,
+ #ifdef IDE0_BASE_OFFSET
+- idx[0] = 0;
++ memset(&hw, 0, sizeof(hw));
++ if (!m8xx_ide_init_ports(&hw, 0)) {
++ ide_hwif_t *hwif = ide_find_port();
++
++ if (hwif) {
++ ide_init_port_hw(hwif, &hw);
++ hwif->pio_mask = ATA_PIO4;
++ hwif->port_ops = &m8xx_port_ops;
++
++ idx[0] = hwif->index;
++ }
++ }
+ #ifdef IDE1_BASE_OFFSET
+- idx[1] = 1;
++ memset(&hw, 0, sizeof(hw));
++ if (!m8xx_ide_init_ports(&hw, 1)) {
++ ide_hwif_t *mate = ide_find_port();
++
++ if (mate) {
++ ide_init_port_hw(mate, &hw);
++ mate->pio_mask = ATA_PIO4;
++ mate->port_ops = &m8xx_port_ops;
++
++ idx[1] = mate->index;
++ }
++ }
+ #endif
+ #endif
-+ .port_resume = inic_port_resume,
- .port_start = inic_port_start,
- };
+diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
+index d9ca52e..48aa019 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;
-@@ -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;
+-static pmac_ide_hwif_t pmac_ide[MAX_HWIFS];
+-static int pmac_ide_count;
+-
+ enum {
+ controller_ohare, /* OHare based */
+ controller_heathrow, /* Heathrow/Paddington */
+@@ -412,45 +409,15 @@ kauai_lookup_timing(struct kauai_timing* table, int cycle_time)
+ */
+ #define IDE_WAKEUP_DELAY (1*HZ)
-- ata_std_ports(port);
-+ ata_sff_std_ports(port);
+-static int pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif);
++static int pmac_ide_init_dma(ide_hwif_t *, const struct ide_port_info *);
+ static int pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq);
+ static void pmac_ide_selectproc(ide_drive_t *drive);
+ static void pmac_ide_kauai_selectproc(ide_drive_t *drive);
- 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 @@
- */
+ #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
- /*
-- sata_mv TODO list:
+-/*
+- * 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;
-
-- 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.
+- if (data_port == 0)
+- return;
-
-- 2) Improve/fix IRQ and error handling sequences.
+- for (ix = 0; ix < MAX_HWIFS; ++ix)
+- if (data_port == pmac_ide[ix].regbase)
+- break;
-
-- 3) ATAPI support (Marvell claims the 60xx/70xx chips can do it).
+- if (ix >= MAX_HWIFS)
+- return; /* not an IDE PMAC interface */
-
-- 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).
+- for (i = 0; i < 8; ++i)
+- hw->io_ports[i] = data_port + i * 0x10;
+- hw->io_ports[8] = data_port + 0x160;
-
-- 5) Investigate problems with PCI Message Signalled Interrupts (MSI).
+- if (irq != NULL)
+- *irq = pmac_ide[ix].irq;
-
-- 6) Add port multiplier support (intermediate)
+- hw->dev = &pmac_ide[ix].mdev->ofdev.dev;
+-}
-
-- 8) Develop a low-power-consumption strategy, and implement it.
+-#define PMAC_IDE_REG(x) ((void __iomem *)(IDE_DATA_REG+(x)))
++#define PMAC_IDE_REG(x) \
++ ((void __iomem *)((drive)->hwif->io_ports.data_addr + (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;
+-}
-
-- 9) [Experiment, low priority] See if ATAPI can be supported using
-- "unknown FIS" or "vendor-specific FIS" support, or something creative
-- like that.
+-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;
+-}
-
-- 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.
+-int
+-pmac_ide_get_irq(unsigned long base)
+-{
+- int ix;
-
-- 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.
+- for (ix = 0; ix < MAX_HWIFS; ++ix)
+- if (base == pmac_ide[ix].regbase)
+- return pmac_ide[ix].irq;
+- return 0;
+-}
-
-- Target mode, for those without docs, is the ability to directly
-- connect two SATA controllers.
+-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);
+- }
+- }
-
-+ * 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.
-+ */
+- return 0;
+-}
+-
+ /* Suspend call back, should be called after the child devices
+ * have actually been suspended
+ */
+@@ -1003,12 +918,30 @@ pmac_ide_do_resume(ide_hwif_t *hwif)
+ return 0;
+ }
- #include <linux/kernel.h>
- #include <linux/module.h>
-@@ -74,6 +64,7 @@
- #include <linux/device.h>
- #include <linux/platform_device.h>
- #include <linux/ata_platform.h>
-+#include <linux/mbus.h>
- #include <scsi/scsi_host.h>
- #include <scsi/scsi_cmnd.h>
- #include <scsi/scsi_device.h>
-@@ -121,17 +112,17 @@ enum {
- MV_MAX_SG_CT = 256,
- MV_SG_TBL_SZ = (16 * MV_MAX_SG_CT),
++static const struct ide_port_ops pmac_ide_ata6_port_ops = {
++ .set_pio_mode = pmac_ide_set_pio_mode,
++ .set_dma_mode = pmac_ide_set_dma_mode,
++ .selectproc = pmac_ide_kauai_selectproc,
++};
++
++static const struct ide_port_ops pmac_ide_port_ops = {
++ .set_pio_mode = pmac_ide_set_pio_mode,
++ .set_dma_mode = pmac_ide_set_dma_mode,
++ .selectproc = pmac_ide_selectproc,
++};
++
++static const struct ide_dma_ops pmac_dma_ops;
++
+ static const struct ide_port_info pmac_port_info = {
++ .init_dma = pmac_ide_init_dma,
+ .chipset = ide_pmac,
++#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
++ .dma_ops = &pmac_dma_ops,
++#endif
++ .port_ops = &pmac_ide_port_ops,
+ .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_MMIO |
+ IDE_HFLAG_UNMASK_IRQS,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+@@ -1033,12 +966,15 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
+ pmif->broken_dma = pmif->broken_dma_warn = 0;
+ if (of_device_is_compatible(np, "shasta-ata")) {
+ pmif->kind = controller_sh_ata6;
++ d.port_ops = &pmac_ide_ata6_port_ops;
+ d.udma_mask = ATA_UDMA6;
+ } else if (of_device_is_compatible(np, "kauai-ata")) {
+ pmif->kind = controller_un_ata6;
++ d.port_ops = &pmac_ide_ata6_port_ops;
+ d.udma_mask = ATA_UDMA5;
+ } else if (of_device_is_compatible(np, "K2-UATA")) {
+ pmif->kind = controller_k2_ata6;
++ d.port_ops = &pmac_ide_ata6_port_ops;
+ d.udma_mask = ATA_UDMA5;
+ } else if (of_device_is_compatible(np, "keylargo-ata")) {
+ if (strcmp(np->name, "ata-4") == 0) {
+@@ -1088,7 +1024,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)
+@@ -1114,38 +1051,29 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
+ default_hwif_mmiops(hwif);
+ hwif->OUTBSYNC = pmac_outbsync;
-- 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 */
+- /* Tell common code _not_ to mess with resources */
+- hwif->mmio = 1;
+ 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
+- || pmif->kind == controller_k2_ata6
+- || pmif->kind == controller_sh_ata6)
+- hwif->selectproc = pmac_ide_kauai_selectproc;
+- else
+- hwif->selectproc = pmac_ide_selectproc;
+- hwif->set_dma_mode = pmac_ide_set_dma_mode;
- /* 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),
+ printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n",
+ hwif->index, model_name[pmif->kind], pmif->aapl_bus_id,
+ pmif->mediabay ? " (mediabay)" : "", hwif->irq);
+-
++
++ if (pmif->mediabay) {
+ #ifdef CONFIG_PMAC_MEDIABAY
+- if (pmif->mediabay && check_media_bay_by_base(pmif->regbase, MB_CD) == 0)
+- hwif->noprobe = 0;
+-#endif /* CONFIG_PMAC_MEDIABAY */
++ if (check_media_bay_by_base(pmif->regbase, MB_CD)) {
++#else
++ if (1) {
++#endif
++ hwif->drives[0].noprobe = 1;
++ hwif->drives[1].noprobe = 1;
++ }
++ }
- 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,
+ #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+ if (pmif->cable_80 == 0)
+ d.udma_mask &= ATA_UDMA2;
+- /* has a DBDMA controller channel */
+- if (pmif->dma_regs == 0 || pmac_ide_setup_dma(pmif, hwif) < 0)
+ #endif
+- d.udma_mask = d.mwdma_mask = 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 # */
+ idx[0] = hwif->index;
- /* 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,
+@@ -1154,6 +1082,16 @@ 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;
+
-+ LTMODE_OFS = 0x30c,
-+ LTMODE_BIT8 = (1 << 8), /* unknown, but necessary */
++ for (i = 0; i < 8; ++i)
++ hw->io_ports_array[i] = base + i * 0x10;
+
- PHY_MODE3 = 0x310,
- PHY_MODE4 = 0x314,
- PHY_MODE2 = 0x330,
-+ SATA_IFCTL_OFS = 0x344,
-+ SATA_IFSTAT_OFS = 0x34c,
-+ VENDOR_UNIQUE_FIS_OFS = 0x35c,
++ hw->io_ports.ctl_addr = base + 0x160;
++}
+
-+ FIS_CFG_OFS = 0x360,
-+ FIS_CFG_SINGLE_SYNC = (1 << 16), /* SYNC on DMA activation */
+ /*
+ * Attach to a macio probed interface
+ */
+@@ -1162,35 +1100,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;
+
- MV5_PHY_MODE = 0x74,
- MV5_LT_MODE = 0x30,
- MV5_PHY_CTL = 0x0C,
-- SATA_INTERFACE_CTL = 0x050,
-+ SATA_INTERFACE_CFG = 0x050,
++ 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;
+ }
- MV_M2_PREAMP_MASK = 0x7e0,
+- 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;
+ }
-@@ -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 */
+ /* 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 +1138,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 +1157,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 +1168,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
+ dev_set_drvdata(&mdev->ofdev.dev, hwif);
- 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,
+ 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;
-+ GEN_II_NCQ_MAX_SECTORS = 256, /* max sects/io on Gen2 w/NCQ */
+@@ -1240,11 +1181,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;
+
- /* 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? */
- };
++out_free_pmif:
++ kfree(pmif);
++ return rc;
+ }
- #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))
+ static int
+@@ -1289,7 +1234,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;
-+#define WINDOW_CTRL(i) (0x20030 + ((i) << 4))
-+#define WINDOW_BASE(i) (0x20034 + ((i) << 4))
+ np = pci_device_to_OF_node(pdev);
+@@ -1297,30 +1242,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) {
+
- 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);
++ pmif = kzalloc(sizeof(*pmif), GFP_KERNEL);
++ if (pmif == NULL)
++ return -ENOMEM;
+
-+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);
++ 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;
+ }
- /* .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,
- };
+- 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;
+ }
- 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,
- };
+ hwif->dev = &pdev->dev;
+@@ -1341,7 +1288,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
+ pci_set_drvdata(pdev, hwif);
--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,
+ 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;
- .qc_prep = mv_qc_prep,
- .qc_issue = mv_qc_issue,
-- .data_xfer = ata_data_xfer,
+@@ -1350,11 +1297,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);
+ }
-- .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,
+ return rc;
++
++out_free_pmif:
++ kfree(pmif);
++ return rc;
+ }
- .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 int
+@@ -1726,18 +1677,31 @@ pmac_ide_dma_lost_irq (ide_drive_t *drive)
+ printk(KERN_ERR "ide-pmac lost interrupt, dma status: %lx\n", status);
+ }
--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,
++static const struct ide_dma_ops pmac_dma_ops = {
++ .dma_host_set = pmac_ide_dma_host_set,
++ .dma_setup = pmac_ide_dma_setup,
++ .dma_exec_cmd = pmac_ide_dma_exec_cmd,
++ .dma_start = pmac_ide_dma_start,
++ .dma_end = pmac_ide_dma_end,
++ .dma_test_irq = pmac_ide_dma_test_irq,
++ .dma_timeout = ide_dma_timeout,
++ .dma_lost_irq = pmac_ide_dma_lost_irq,
++};
++
+ /*
+ * Allocate the data structures needed for using DMA with an interface
+ * and fill the proper list of functions pointers
+ */
+-static int __devinit pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
++static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif,
++ const struct ide_port_info *d)
+ {
++ pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
-- .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,
- };
+ /* We won't need pci_dev if we switch to generic consistent
+ * DMA routines ...
+ */
+- if (dev == NULL)
++ if (dev == NULL || pmif->dma_regs == 0)
+ return -ENODEV;
+ /*
+ * Allocate space for the DBDMA commands.
+@@ -1756,18 +1720,14 @@ static int __devinit pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
--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,
+ hwif->sg_max_nents = MAX_DCMDS;
+
+- hwif->dma_host_set = &pmac_ide_dma_host_set;
+- hwif->dma_setup = &pmac_ide_dma_setup;
+- hwif->dma_exec_cmd = &pmac_ide_dma_exec_cmd;
+- hwif->dma_start = &pmac_ide_dma_start;
+- hwif->ide_dma_end = &pmac_ide_dma_end;
+- hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq;
+- hwif->dma_timeout = &ide_dma_timeout;
+- hwif->dma_lost_irq = &pmac_ide_dma_lost_irq;
-
-- .cable_detect = ata_cable_sata,
+ return 0;
+ }
-
-+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,
++#else
++static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif,
++ const struct ide_port_info *d)
++{
++ return -EOPNOTSUPP;
++}
+ #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+
+ module_init(pmac_ide_probe);
+diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
+index 634e3f6..5171601 100644
+--- a/drivers/ide/setup-pci.c
++++ b/drivers/ide/setup-pci.c
+@@ -20,84 +20,6 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+
-
-- .irq_clear = mv_irq_clear,
-- .irq_on = ata_irq_on,
+-/**
+- * 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
+- */
-
-- .error_handler = mv_error_handler,
-- .freeze = mv_eh_freeze,
-- .thaw = mv_eh_thaw,
-- .qc_defer = ata_std_qc_defer,
+-static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char *name)
+-{
+- int h;
+- ide_hwif_t *hwif;
-
-- .scr_read = mv_scr_read,
-- .scr_write = mv_scr_write,
+- /*
+- * 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;
+-}
-
-- .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,
- },
- };
+ /**
+ * 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;
-@@ -757,11 +711,6 @@ static inline void writelfl(unsigned long data, void __iomem *addr)
- (void) readl(addr); /* flush to avoid PCI posted write */
+@@ -150,16 +72,16 @@ static void ide_pci_clear_simplex(unsigned long dma_base, const char *name)
}
--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)
+ /**
+- * ide_get_or_set_dma_base - setup BMIBA
+- * @d: IDE port info
++ * ide_pci_dma_base - setup BMIBA
+ * @hwif: IDE interface
++ * @d: IDE port info
+ *
+ * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space.
+ * Where a device has a partner that is already in DMA mode we check
+ * and enforce IDE simplex rules.
+ */
+
+-static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_hwif_t *hwif)
++unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d)
{
- 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;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ unsigned long dma_base = 0;
+@@ -210,6 +132,31 @@ static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_
+ out:
+ return dma_base;
}
-
++EXPORT_SYMBOL_GPL(ide_pci_dma_base);
++
+/*
-+ * 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.
++ * Set up BM-DMA capability (PnP BIOS should have done this)
+ */
-+#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)
++int ide_pci_set_master(struct pci_dev *dev, const char *name)
+{
-+ return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
-+}
++ u16 pcicmd;
+
- 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;
++ pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
+
-+ return hc_mmio + ofs;
-+}
++ if ((pcicmd & PCI_COMMAND_MASTER) == 0) {
++ pci_set_master(dev);
+
- 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);
- }
++ if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) ||
++ (pcicmd & PCI_COMMAND_MASTER) == 0) {
++ printk(KERN_ERR "%s: error updating PCICMD on %s\n",
++ name, pci_name(dev));
++ return -EIO;
++ }
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(ide_pci_set_master);
+ #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
--static void mv_irq_clear(struct ata_port *ap)
--{
--}
+ void ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d)
+@@ -218,7 +165,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));
+ }
-
- 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;
+ EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
- /* 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);
- }
+@@ -231,13 +177,13 @@ 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
+ */
-- mv_edma_cfg(pp, hpriv, port_mmio, want_ncq);
-+ mv_edma_cfg(ap, want_ncq);
+ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
+ {
+- int ret;
++ int ret, bars;
- /* 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;
+ if (pci_enable_device(dev)) {
+ ret = pci_enable_device_io(dev);
+@@ -260,13 +206,21 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
+ goto out;
}
-- 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);
+- /* FIXME: Temporary - until we put in the hotplug interface logic
+- Check that the bits we want are not in use by someone else. */
+- ret = pci_request_region(dev, 4, "ide_tmp");
+- if (ret < 0)
+- goto out;
++ if (d->host_flags & IDE_HFLAG_SINGLE)
++ bars = (1 << 2) - 1;
++ else
++ bars = (1 << 4) - 1;
++
++ if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) {
++ if (d->host_flags & IDE_HFLAG_CS5520)
++ bars |= (1 << 2);
++ else
++ bars |= (1 << 4);
++ }
-- /* 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);
+- pci_release_region(dev, 4);
++ ret = pci_request_selected_regions(dev, bars, d->name);
++ if (ret < 0)
++ printk(KERN_ERR "%s: can't reserve resources\n", d->name);
+ out:
+ return ret;
+ }
+@@ -290,8 +244,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;
}
--
-- return err;
-+ return -EIO;
- }
+@@ -312,26 +266,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 mv_stop_dma(struct ata_port *ap)
-+static int mv_stop_edma(struct ata_port *ap)
+-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)
{
-- 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;
+ ulong flags = pci_resource_flags(dev, bar);
+-
++
+ /* Unconfigured ? */
+ if (!flags || pci_resource_len(dev, bar) == 0)
+ return 0;
-- 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;
+- /* I/O space */
+- if(flags & PCI_BASE_ADDRESS_IO_MASK)
++ /* I/O space */
++ if (flags & IORESOURCE_IO)
+ return 0;
+-
++
+ /* Bad */
+- printk(KERN_ERR "%s: IO baseregs (BIOS) are reported "
+- "as MEM, report to "
+- "<andre at linux-ide.org>.\n", d->name);
+ return -EINVAL;
}
- #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)
+@@ -355,15 +307,16 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
{
- /*
-+ * 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);
+ 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;
+ }
-+ }
-+}
+
-+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;
+ ctl = pci_resource_start(dev, 2*port+1);
+ base = pci_resource_start(dev, 2*port);
+ if ((ctl && !base) || (base && !ctl)) {
+@@ -372,31 +325,28 @@ 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;
+ }
-+ 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);
+
+ 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;
+
+ return hwif;
}
+@@ -412,40 +362,33 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
+ * state
+ */
--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)
+-void ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
++int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
{
- 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);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+- u16 pcicmd;
+-
+- pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
- /* 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 ((d->host_flags & IDE_HFLAG_NO_AUTODMA) == 0 ||
+ ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
+ (dev->class & 0x80))) {
+- unsigned long dma_base = ide_get_or_set_dma_base(d, hwif);
+- if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
+- /*
+- * 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",
+- hwif->name, d->name);
+- dma_base = 0;
+- }
+- }
+- if (dma_base) {
+- if (d->init_dma) {
+- d->init_dma(hwif, dma_base);
+- } else {
+- ide_setup_dma(hwif, dma_base);
+- }
+- } else {
+- printk(KERN_INFO "%s: %s Bus-Master DMA disabled "
+- "(BIOS)\n", hwif->name, d->name);
+- }
++ unsigned long base = ide_pci_dma_base(hwif, d);
+
-+ 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 (base == 0 || ide_pci_set_master(dev, d->name) < 0)
++ return -1;
++
++ if (hwif->mmio)
++ printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name);
++ else
++ printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n",
++ hwif->name, base, base + 7);
++
++ hwif->extra_base = base + (hwif->channel ? 8 : 16);
++
++ if (ide_allocate_dma_engine(hwif))
++ return -1;
++
++ ide_setup_dma(hwif, base);
}
++
++ return 0;
+ }
+ #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
- 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];
- }
+@@ -532,7 +475,6 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int
+ *(idx + port) = hwif->index;
}
+ }
-
-- spin_lock_irqsave(&ap->host->lock, flags);
--
-- mv_edma_cfg(pp, hpriv, port_mmio, 0);
-- mv_set_edma_ptrs(port_mmio, hpriv, pp);
+ EXPORT_SYMBOL_GPL(ide_pci_setup_ports);
+
+ /*
+@@ -615,7 +557,6 @@ int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d)
+
+ return ret;
+ }
-
-- spin_unlock_irqrestore(&ap->host->lock, flags);
+ EXPORT_SYMBOL_GPL(ide_setup_pci_device);
+
+ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
+@@ -639,5 +580,4 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
+ out:
+ return ret;
+ }
-
-- /* 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;
+ 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;
+ }
- out_port_free_dma_mem:
-@@ -1220,7 +1211,7 @@ out_port_free_dma_mem:
+- 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.
*/
- static void mv_port_stop(struct ata_port *ap)
- {
-- mv_stop_dma(ap);
-+ mv_stop_edma(ap);
- mv_port_free_dma_mem(ap);
- }
++#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[] = {
+ };
-@@ -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;
+ MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table);
++#endif /* MODULE */
- /* get current queue index from software */
-- in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
-+ in_index = pp->req_idx;
+ static struct hpsb_protocol_driver dv1394_driver = {
+- .name = "dv1394",
+- .id_table = dv1394_id_table,
++ .name = "dv1394",
+ };
- 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;
+@@ -2568,7 +2569,6 @@ static int __init dv1394_init_module(void)
- 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;
+ 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;
+ }
- /* get current queue index from software */
-- in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
-+ in_index = pp->req_idx;
+@@ -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,
- 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 (((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;
+ }
- 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);
+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;
}
- mv_start_dma(ap, port_mmio, pp, qc->tf.protocol);
+@@ -373,6 +373,8 @@ static void build_speed_map(struct hpsb_host *host, int nodecount)
+ if (sid->port2 == SELFID_PORT_CHILD) cldcnt[n]++;
-- 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;
+ 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 {
- /* 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;
- }
+ /* how many times the buffer has overflowed or underflowed */
+ atomic_t overflows;
++ /* how many cycles were skipped for a given context */
++ atomic_t skips;
-+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;
+ /* Current number of bytes lost in discarded packets */
+ int bytes_discarded;
+diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
+index 511e432..29d833e 100644
+--- a/drivers/ieee1394/nodemgr.c
++++ b/drivers/ieee1394/nodemgr.c
+@@ -18,8 +18,8 @@
+ #include <linux/moduleparam.h>
+ #include <linux/mutex.h>
+ #include <linux/freezer.h>
++#include <linux/semaphore.h>
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+
+ #include "csr.h"
+ #include "highlevel.h"
+@@ -701,7 +701,11 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
+ return 0;
+
+ driver = container_of(drv, struct hpsb_protocol_driver, driver);
+- for (id = driver->id_table; id->match_flags != 0; id++) {
++ id = driver->id_table;
++ if (!id)
++ return 0;
+
-+ 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;
-+}
++ 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;
+
-+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 = "";
++ /* unwrap */
++ if (cycle_diff < 0) {
++ cycle_diff += 8000;
++ if (cycle_diff < 0)
++ PRINT(KERN_ERR, "bogus cycle diff %d\n",
++ cycle_diff);
++ }
+
-+ /*
-+ * 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);
-+}
++ skip = cycle_diff - 1;
++ if (skip > 0) {
++ DBGMSG("skipped %d cycles without packet loss", skip);
++ atomic_add(skip, &iso->skips);
++ }
++ }
++ xmit->last_cycle = cycle;
+
- /**
- * 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;
+ /* tell the subsystem the packet has gone out */
+ hpsb_iso_packet_sent(iso, cycle, event != 0x11);
- ata_ehi_clear_desc(ehi);
+@@ -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);
-- 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.
++ * 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.
+ */
- edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
-+ writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
++ 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)
-- ata_ehi_push_desc(ehi, "edma_err 0x%08x", edma_err_cause);
-+ ata_ehi_push_desc(ehi, "edma_err_cause=%08x", edma_err_cause);
+ spin_lock_irqsave(&d->lock, flags);
- /*
-- * 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");
+- 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;
}
- 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;
+@@ -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);
-+ /*
-+ * 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 (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;
}
--
- 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;
+@@ -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 *
+ ***********************************/
-- /* Clear EDMA now that SERR cleanup done */
-- writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+-#define FAIL(err, fmt, args...) \
+-do { \
+- PRINT_G(KERN_ERR, fmt , ## args); \
+- ohci1394_pci_remove(dev); \
+- return err; \
+-} while (0)
-
- if (!err_mask) {
- err_mask = AC_ERR_OTHER;
-- action |= ATA_EH_HARDRESET;
-+ action |= ATA_EH_RESET;
- }
+-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);
- 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);
- }
+@@ -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 */
--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);
+- 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);
-- /* 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;
+ host = hpsb_alloc_host(&ohci1394_driver, sizeof(struct ti_ohci), &dev->dev);
+- if (!host) FAIL(-ENOMEM, "Failed to allocate host structure");
-
-- /* 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);
++ 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));
--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);
+ 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;
-- /* 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;
+ 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);
-- 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];
+@@ -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;
-- /* 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;
+ /* 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;
-- /* 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;
+ 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");
-
-- /* 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;
++ 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");
-
-- qc = ata_qc_from_tag(ap, tag);
++ 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");
-
-- /* 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;
-- }
++ 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");
-
-- /* 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;
- }
++ 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);
-
-- /* 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++;
- }
++ 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);
-+ /* 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);
+@@ -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;
}
- /**
- * 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)
+-static void ohci1394_pci_remove(struct pci_dev *pdev)
++static void ohci1394_pci_remove(struct pci_dev *dev)
{
- 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;
+ struct ti_ohci *ohci;
+- struct device *dev;
++ struct device *device;
-- 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)
+- 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);
-
-- 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 (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 */
-
-- 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);
- }
+ case OHCI_INIT_ALLOC_HOST:
+- pci_set_drvdata(ohci->dev, NULL);
++ pci_set_drvdata(dev, NULL);
}
-- 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 */
+- if (dev)
+- put_device(dev);
++ if (device)
++ put_device(device);
++out:
++ ohci1394_pmac_off(dev);
}
- /**
-@@ -1810,51 +1810,26 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
+ #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)
{
- 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;
+ int err;
+- struct ti_ohci *ohci = pci_get_drvdata(pdev);
++ struct ti_ohci *ohci = pci_get_drvdata(dev);
- 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);
+ 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);
-
--out_unlock:
- spin_unlock(&host->lock);
+-/* PowerMac suspend code comes last */
+-#ifdef CONFIG_PPC_PMAC
+- if (machine_is(powermac)) {
+- struct device_node *ofn = pci_device_to_OF_node(pdev);
-
- return IRQ_RETVAL(handled);
+- if (ofn)
+- pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
+- }
+-#endif /* CONFIG_PPC_PMAC */
++ ohci1394_pmac_off(dev);
+
+ return 0;
}
--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,
+-static int ohci1394_pci_resume(struct pci_dev *pdev)
++static int ohci1394_pci_resume(struct pci_dev *dev)
{
- void __iomem *port_mmio = mv_port_base(mmio, port);
+ int err;
+- struct ti_ohci *ohci = pci_get_drvdata(pdev);
++ struct ti_ohci *ohci = pci_get_drvdata(dev);
-- writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
+ 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);
-
-- 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);
+- 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;
+ }
- 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);
+@@ -238,7 +238,7 @@ static int get_phy_reg(struct ti_lynx *lynx, int addr)
- if (hp_flags & MV_HP_ERRATA_60X1B2)
-- tmp = readl(port_mmio + 0x310);
-+ tmp = readl(port_mmio + PHY_MODE3);
+ 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)
-+ /* workaround for errata FEr SATA#10 (part 1) */
- m4 = (m4 & ~(1 << 1)) | (1 << 0);
+ 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;
+ }
- writel(m4, port_mmio + PHY_MODE4);
+ 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;
+ }
- if (hp_flags & MV_HP_ERRATA_60X1B2)
-- writel(tmp, port_mmio + 0x310);
-+ writel(tmp, port_mmio + PHY_MODE3);
- }
+@@ -287,7 +287,7 @@ static int sel_phy_reg_page(struct ti_lynx *lynx, int page)
- /* 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,
+ 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)
{
- void __iomem *port_mmio = mv_port_base(mmio, port);
++ 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;
+ }
-- 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);
+@@ -2437,6 +2440,8 @@ static int raw1394_iso_get_status(struct file_info *fi, void __user * uaddr)
- 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;
+ /* 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[] = {
+ };
--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)
+ 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)
+{
-+ u32 ifctl = readl(port_mmio + SATA_INTERFACE_CFG);
++ return (__force u32) a < (__force u32) b;
++}
+
-+ ifctl = (ifctl & 0xf7f) | 0x9b1000; /* from chip spec */
-+ if (want_gen2i)
-+ ifctl |= (1 << 7); /* enable gen2i speed */
-+ writelfl(ifctl, port_mmio + SATA_INTERFACE_CFG);
++static int be32_gt(__be32 a, __be32 b)
++{
++ return (__force u32) a > (__force u32) b;
+}
+
-+/*
-+ * 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)
++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)
{
- void __iomem *port_mmio = mv_port_base(mmio, port_no);
-
-+ mv_stop_edma_engine(port_mmio);
- writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
+ 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 (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);
+ 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
}
--
-- 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);
+- 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);
}
--/**
-- * 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)
+-static int ib_device_uevent(struct class_device *cdev,
++static int ib_device_uevent(struct device *device,
+ struct kobj_uevent_env *env)
{
-- 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;
+- struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
++ struct ib_device *dev = container_of(device, struct ib_device, dev);
-- /* 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);
-+ }
+ 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)
}
--
-- /* 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)
+-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 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);
-+}
+- 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;
-- 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);
+@@ -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 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,
+-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 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;
+- 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);
+ }
-- 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;
+ 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");
-- /* 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);
+ 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;
+ };
-- /* 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);
+@@ -1171,7 +1171,7 @@ static int ib_ucm_open(struct inode *inode, struct file *filp)
--static void mv_error_handler(struct ata_port *ap)
--{
-- ata_do_eh(ap, mv_prereset, ata_std_softreset,
-- mv_hardreset, mv_postreset);
-+ return rc;
+ 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 mv_eh_freeze(struct ata_port *ap)
+-static void ucm_release_class_dev(struct class_device *class_dev)
++static void ib_ucm_release_dev(struct device *dev)
{
- 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;
+- struct ib_ucm_device *dev;
++ struct ib_ucm_device *ucm_dev;
- /* FIXME: handle coalescing completion events properly */
+- 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);
+ }
-- 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);
+ static const struct file_operations ucm_fops = {
+@@ -1220,14 +1220,15 @@ static const struct file_operations ucm_fops = {
+ .poll = ib_ucm_poll,
+ };
- /* 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 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 mv_eh_thaw(struct ata_port *ap)
+ static void ib_ucm_add_one(struct ib_device *device)
{
- 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;
+@@ -1249,32 +1250,31 @@ static void ib_ucm_add_one(struct ib_device *device)
- /* FIXME: handle coalescing completion events properly */
+ set_bit(ucm_dev->devnum, dev_map);
-- 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);
+- 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;
- /* clear EDMA errors on this port */
- writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+- 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;
- /* 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);
+- 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;
- /* 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);
+ 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);
}
- /**
-@@ -2779,19 +2651,17 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
+ 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;
- rc = mv_chip_id(host, board_idx);
- if (rc)
-- goto done;
-+ goto done;
+- 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/umem.c b/drivers/infiniband/core/umem.c
+index 4e3128f..fe78f7d 100644
+--- a/drivers/infiniband/core/umem.c
++++ b/drivers/infiniband/core/umem.c
+@@ -38,6 +38,7 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/sched.h>
+ #include <linux/hugetlb.h>
++#include <linux/dma-attrs.h>
- 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 */
+ #include "uverbs.h"
+
+@@ -72,9 +73,10 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d
+ * @addr: userspace virtual address to start at
+ * @size: length of region to pin
+ * @access: IB_ACCESS_xxx flags for memory being pinned
++ * @dmasync: flush in-flight DMA when the memory region is written
+ */
+ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
+- size_t size, int access)
++ size_t size, int access, int dmasync)
+ {
+ struct ib_umem *umem;
+ struct page **page_list;
+@@ -87,6 +89,10 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
+ int ret;
+ int off;
+ int i;
++ DEFINE_DMA_ATTRS(attrs);
+
-+ /* global interrupt mask: 0 == mask everything */
- writel(0, hpriv->main_mask_reg_addr);
++ if (dmasync)
++ dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
- 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);
+ if (!can_do_mlock())
+ return ERR_PTR(-EPERM);
+@@ -174,10 +180,11 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
+ sg_set_page(&chunk->page_list[i], page_list[i + off], PAGE_SIZE, 0);
+ }
- 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);
+- chunk->nmap = ib_dma_map_sg(context->device,
+- &chunk->page_list[0],
+- chunk->nents,
+- DMA_BIDIRECTIONAL);
++ chunk->nmap = ib_dma_map_sg_attrs(context->device,
++ &chunk->page_list[0],
++ chunk->nents,
++ DMA_BIDIRECTIONAL,
++ &attrs);
+ if (chunk->nmap <= 0) {
+ for (i = 0; i < chunk->nents; ++i)
+ put_page(sg_page(&chunk->page_list[i]));
+diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
+index 4e91510..3aa2db5 100644
+--- a/drivers/infiniband/core/user_mad.c
++++ b/drivers/infiniband/core/user_mad.c
+@@ -46,9 +46,9 @@
+ #include <linux/mutex.h>
+ #include <linux/kref.h>
+ #include <linux/compat.h>
++#include <linux/semaphore.h>
-@@ -2897,6 +2754,27 @@ static int mv_create_dma_pools(struct mv_host_priv *hpriv, struct device *dev)
- return 0;
- }
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
-+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;
+ #include <rdma/ib_mad.h>
+ #include <rdma/ib_user_mad.h>
+@@ -88,11 +88,11 @@ enum {
+ */
-+ /*
-+ * (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);
+ struct ib_umad_port {
+- struct cdev *dev;
+- struct class_device *class_dev;
++ struct cdev *cdev;
++ struct device *dev;
- #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 = {
- };
+- struct cdev *sm_dev;
+- struct class_device *sm_class_dev;
++ struct cdev *sm_cdev;
++ struct device *sm_dev;
+ struct semaphore sm_sem;
- 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),
+ struct mutex file_mutex;
+@@ -948,27 +948,29 @@ static struct ib_client umad_client = {
+ .remove = ib_umad_remove_one
};
- 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 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);
- 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,
- };
+ if (!port)
+ return -ENODEV;
--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,
- };
+ 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 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 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);
--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,
- };
+ if (!port)
+ return -ENODEV;
--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,
- };
+ 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 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,
- };
+ 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);
-+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 }
+- 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;
+
- 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),
- },
- };
++ 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;
-@@ -640,8 +531,8 @@ MODULE_LICENSE("GPL");
- MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
- MODULE_VERSION(DRV_VERSION);
+- 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;
--static int adma_enabled = 1;
--static int swncq_enabled;
-+static int adma_enabled;
-+static int swncq_enabled = 1;
+- 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);
- 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);
+- 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;
-- ata_tf_read(ap, tf);
-+ ata_sff_tf_read(ap, tf);
- }
+ 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,
- 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)
+ return 0;
- /* 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;
- }
+-err_sm_class:
+- class_device_destroy(umad_class, port->sm_dev->dev);
++err_sm_dev:
++ device_destroy(umad_class, port->sm_cdev->dev);
- /* handle interrupt */
-- return ata_host_intr(ap, qc);
-+ return ata_sff_host_intr(ap, qc);
- }
+ err_sm_cdev:
+- cdev_del(port->sm_dev);
++ cdev_del(port->sm_cdev);
- 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];
+-err_class:
+- class_device_destroy(umad_class, port->dev->dev);
++err_dev:
++ device_destroy(umad_class, port->cdev->dev);
- if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
-- ata_bmdma_irq_clear(ap);
-+ ata_sff_irq_clear(ap);
- return;
- }
+ err_cdev:
+- cdev_del(port->dev);
++ cdev_del(port->cdev);
+ clear_bit(port->dev_num, dev_map);
-@@ -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;
+ return -1;
+@@ -1065,14 +1066,14 @@ static void ib_umad_kill_port(struct ib_umad_port *port)
+ int already_dead;
+ int id;
- if (pp->flags & NV_ADMA_PORT_REGISTER_MODE)
-- ata_bmdma_post_internal_cmd(qc);
-+ ata_sff_post_internal_cmd(qc);
- }
+- 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);
- 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;
- }
+- 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);
-@@ -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);
+- cdev_del(port->dev);
+- cdev_del(port->sm_dev);
++ cdev_del(port->cdev);
++ cdev_del(port->sm_cdev);
-@@ -1545,11 +1436,11 @@ static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance)
+ 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;
+ };
- 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);
- }
+ 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;
+ };
- }
-@@ -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);
- }
+ 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;
- 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);
- }
+ 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;
- static int nv_hardreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline)
- {
-- unsigned int dummy;
-+ int rc;
+ 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;
- /* 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;
- }
+ 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;
- 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 */
+ 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;
-- ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
-- nv_hardreset, ata_std_postreset);
-+ ata_sff_error_handler(ap);
- }
+ 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;
- 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);
+ *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;
+ }
- 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));
+- 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;
- sactive = readl(pp->sactive_block);
-@@ -1881,7 +1768,7 @@ static void nv_swncq_ncq_stop(struct ata_port *ap)
- }
+ return filp;
+@@ -696,27 +690,29 @@ static struct ib_client uverbs_client = {
+ .remove = ib_uverbs_remove_one
+ };
- 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)
+-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 (ap->link.sactive) {
- nv_swncq_ncq_stop(ap);
-- ehc->i.action |= ATA_EH_HARDRESET;
-+ ehc->i.action |= ATA_EH_RESET;
- }
+ if (!dev)
+ return -ENODEV;
-- ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
-- nv_hardreset, ata_std_postreset);
-+ ata_sff_error_handler(ap);
+ 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);
- #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)
+-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)
{
- if (qc->tf.protocol != ATA_PROT_NCQ) {
-- ata_qc_prep(qc);
-+ ata_sff_qc_prep(qc);
- return;
- }
+- struct ib_uverbs_device *dev = class_get_devdata(class_dev);
++ struct ib_uverbs_device *dev = dev_get_drvdata(device);
-@@ -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);
+ if (!dev)
+ return -ENODEV;
-- 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);
+ 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);
- DPRINTK("Issued tag %u\n", qc->tag);
+ 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;
-@@ -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;
+- 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;
- if (qc->tf.protocol != ATA_PROT_NCQ)
-- return ata_qc_issue_prot(qc);
-+ return ata_sff_qc_issue(qc);
+- 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;
- DPRINTK("Enter\n");
+- class_set_devdata(uverbs_dev->class_dev, uverbs_dev);
++ dev_set_drvdata(uverbs_dev->dev, uverbs_dev);
-@@ -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;
- }
+- 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;
-- ap->ops->irq_clear(ap);
-+ ap->ops->sff_irq_clear(ap);
- __ata_bmdma_stop(ap);
+ spin_lock(&map_lock);
+@@ -782,10 +777,10 @@ static void ib_uverbs_add_one(struct ib_device *device)
+ return;
- 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;
+ err_class:
+- class_device_destroy(uverbs_class, uverbs_dev->dev->dev);
++ device_destroy(uverbs_class, uverbs_dev->cdev->dev);
-- 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);
+ 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;
- }
-@@ -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;
+- 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);
-@@ -2429,6 +2315,7 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 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)
{
- 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)
- }
+- 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);
- 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;
+@@ -628,6 +630,13 @@ struct ib_cq *ib_create_cq(struct ib_device *device,
+ }
+ EXPORT_SYMBOL(ib_create_cq);
-@@ -2503,8 +2391,8 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
- nv_swncq_host_init(host);
++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;
- 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);
- }
++ 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);
- #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/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;
-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);
+ /* 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);
- 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,
- };
+ elem->skb = NULL;
+@@ -179,13 +179,13 @@ static int c2_rx_ring_alloc(struct c2_ring *rx_ring, void *vaddr,
+ rx_desc->status = 0;
--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,
+ /* 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);
-+ .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,
+ 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;
-- .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,
- };
+ __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);
--/* 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,
- };
+ 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);
--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,
-+};
+ 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);
+ }
-- .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,
- };
+@@ -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));
-@@ -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;
+ 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);
- /* 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 */
- }
+ 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);
+ }
--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);
+@@ -787,9 +790,12 @@ static int c2_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ elem->maplen = maplen;
-- /* 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);
- }
+ /* 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);
- 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 */
- }
+ 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;
--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;
+ /* 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,
}
-- return ata_qc_issue_prot(qc);
-+ return ata_sff_qc_issue(qc);
- }
+ /* 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,
+ }
- 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);
- }
+ /* 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,
- 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);
- }
+ /* 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);
- 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);
+ /* Request an interrupt line for the driver */
+@@ -1090,7 +1096,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ }
- 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,
- };
+ /* 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));
--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,
- };
+ /* 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,
- static const struct ata_port_info qs_port_info[] = {
-@@ -211,11 +199,6 @@ static u8 qs_bmdma_status(struct ata_port *ap)
- return 0;
- }
+ /* Remap the PCI registers in adapter BAR0 to kernel VA space */
+ c2dev->regs = ioremap_nocache(reg0_start, reg0_len);
+- if (c2dev->regs == 0UL) {
++ if (!c2dev->regs) {
+ printk(KERN_ERR PFX "Unable to remap BAR0\n");
+ ret = -EIO;
+ goto bail8;
+@@ -1139,7 +1145,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ c2dev->pa = reg4_start + C2_PCI_REGS_OFFSET;
+ c2dev->kva = ioremap_nocache(reg4_start + C2_PCI_REGS_OFFSET,
+ kva_map_size);
+- if (c2dev->kva == 0UL) {
++ if (!c2dev->kva) {
+ printk(KERN_ERR PFX "Unable to remap BAR4\n");
+ ret = -EIO;
+ goto bail9;
+diff --git a/drivers/infiniband/hw/amso1100/c2.h b/drivers/infiniband/hw/amso1100/c2.h
+index fa58200..d12a24a 100644
+--- a/drivers/infiniband/hw/amso1100/c2.h
++++ b/drivers/infiniband/hw/amso1100/c2.h
+@@ -40,7 +40,6 @@
+ #include <linux/pci.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/idr.h>
+-#include <asm/semaphore.h>
--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;
+ #include "c2_provider.h"
+ #include "c2_mq.h"
+@@ -346,7 +345,7 @@ struct c2_dev {
+ // spinlock_t aeq_lock;
+ // spinlock_t rnic_lock;
- qs_reset_channel_logic(ap);
-- return ata_std_prereset(link, deadline);
-+ return ata_sff_prereset(link, deadline);
- }
+- u16 *hint_count;
++ __be16 *hint_count;
+ dma_addr_t hint_count_dma;
+ u16 hints_read;
- 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);
- }
+@@ -425,10 +424,10 @@ static inline void __raw_writeq(u64 val, void __iomem * addr)
+ #endif
- 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)
+ #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)
- qs_enter_reg_mode(qc->ap);
- if (qc->tf.protocol != ATA_PROT_DMA) {
-- ata_qc_prep(qc);
-+ ata_sff_qc_prep(qc);
- return;
- }
+ #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))
-@@ -380,7 +362,7 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
- }
+ 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);
- pp->state = qs_state_mmio;
-- return ata_qc_issue_prot(qc);
-+ return ata_sff_qc_issue(qc);
+ /* 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;
+ }
}
-
- 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);
+@@ -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)
}
- 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,
+-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;
- /*
- * Controller IDs
-@@ -168,54 +167,23 @@ static struct pci_driver sil_pci_driver = {
- };
+@@ -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;
+ }
- 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),
- };
+-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);
--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,
- };
+ /* Link head to new mqsp */
+- *mqsp = head->head;
++ *mqsp = (__force __be16) head->head;
- 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)
+ /* 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;
- 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);
+ 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;
}
-@@ -440,15 +405,15 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
+- 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);
}
+ }
- /* 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;
+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..2acf9b6 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);
- /* ack bmdma irq events */
-- ata_bmdma_irq_clear(ap);
-+ ata_sff_irq_clear(ap);
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
- /* kick HSM in the ass */
-- ata_hsm_move(ap, qc, status, 0);
-+ ata_sff_hsm_move(ap, qc, status, 0);
+ *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__);
- 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;
+ 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;
+ }
- /* clear IRQ */
-- ata_chk_status(ap);
-- ata_bmdma_irq_clear(ap);
-+ ap->ops->sff_check_status(ap);
-+ ata_sff_irq_clear(ap);
+ 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);
- /* 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);
+- 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);
- 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 */
+@@ -134,7 +134,7 @@ static struct ib_ucontext *c2_alloc_ucontext(struct ib_device *ibdev,
+ {
+ struct c2_ucontext *context;
- 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" },
- };
+- 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,
-@@ -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 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 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 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;
+ }
- 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,
- };
+@@ -162,7 +162,7 @@ static struct ib_pd *c2_alloc_pd(struct ib_device *ibdev,
+ struct c2_pd *pd;
+ int err;
--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,
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
- .qc_defer = sil24_qc_defer,
- .qc_prep = sil24_qc_prep,
- .qc_issue = sil24_qc_issue,
-+ .qc_fill_rtf = sil24_qc_fill_rtf,
+ pd = kmalloc(sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+@@ -187,7 +187,7 @@ static struct ib_pd *c2_alloc_pd(struct ib_device *ibdev,
-- .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,
+ 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);
- .scr_read = sil24_scr_read,
- .scr_write = sil24_scr_write,
--
- .pmp_attach = sil24_pmp_attach,
- .pmp_detach = sil24_pmp_detach,
+@@ -196,13 +196,13 @@ static int c2_dealloc_pd(struct ib_pd *pd)
-- .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 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 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)
+ static int c2_ah_destroy(struct ib_ah *ah)
{
-- void __iomem *port = dev->link->ap->ioaddr.cmd_addr;
-+ void __iomem *port = sil24_port_base(dev->link->ap);
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ return -ENOSYS;
+ }
- 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)
+@@ -230,7 +230,7 @@ struct ib_qp *c2_get_qp(struct ib_device *device, int qpn)
- 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];
+ 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));
-@@ -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);
- }
+ 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;
--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[] = {
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
++
++ if (init_attr->create_flags)
++ return ERR_PTR(-EINVAL);
- 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;
+ 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,
- 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)
+ 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);
- 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;
+ 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
- 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;
- }
+ 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);
+ }
--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)
+ 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)
{
-- void __iomem *port = ap->ioaddr.cmd_addr;
-+ void __iomem *port = sil24_port_base(ap);
+ struct c2_cq *cq = to_c2cq(ib_cq);
- /* configure IRQ WoC */
- if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC)
-@@ -575,7 +556,7 @@ static void sil24_config_port(struct ata_port *ap)
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
- 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);
+ 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;
- 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)
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
- 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;
+ /* AMSO1100 limit */
+ bl.size = 0xffffffff;
+@@ -442,14 +445,14 @@ 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;
- writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_CLR);
-@@ -600,12 +581,12 @@ static void sil24_clear_pmp(struct ata_port *ap)
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
- 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;
+ c2mr = kmalloc(sizeof(*c2mr), GFP_KERNEL);
+ if (!c2mr)
+ return ERR_PTR(-ENOMEM);
+ c2mr->pd = c2pd;
- /* clear PMP error status */
-- if (ap->nr_pmp_links)
-+ if (sata_pmp_attached(ap))
- sil24_clear_pmp(ap);
+- c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc);
++ c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
+ if (IS_ERR(c2mr->umem)) {
+ err = PTR_ERR(c2mr->umem);
+ kfree(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;
- writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
-@@ -616,7 +597,7 @@ static int sil24_init_port(struct ata_port *ap)
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
- 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;
- }
+ 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;
+ }
-@@ -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)
+-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)
{
-- 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;
+- 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 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)
+-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 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,
+- 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));
+ }
- DPRINTK("ENTER\n");
+-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");
+ }
-- 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);
+-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");
+ }
-- if (*class == ATA_DEV_UNKNOWN)
-- *class = ATA_DEV_NONE;
--
-- out:
- DPRINTK("EXIT, class=%u\n", *class);
- return 0;
+-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);
-@@ -723,17 +695,11 @@ static int sil24_do_softreset(struct ata_link *link, unsigned int *class,
- return -EIO;
- }
+-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 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)
+ 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)
{
- 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;
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ return -ENOSYS;
}
--static void sil24_irq_clear(struct ata_port *ap)
-+static bool sil24_qc_fill_rtf(struct ata_queued_cmd *qc)
+ static int c2_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
{
-- /* unused */
-+ sil24_read_tf(qc->ap, qc->tag, &qc->result_tf);
-+ return true;
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ return -ENOSYS;
}
- 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);
+@@ -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 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)
+ static int c2_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
{
-@@ -960,12 +921,12 @@ static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,
- return rc;
- }
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
-- return sata_pmp_std_hardreset(link, class, deadline);
-+ return sata_std_hardreset(link, class, deadline);
- }
+ /* 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 void sil24_freeze(struct ata_port *ap)
+ static int c2_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
{
-- 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)
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
- static void sil24_thaw(struct ata_port *ap)
+ /* 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)
{
-- void __iomem *port = ap->ioaddr.cmd_addr;
-+ void __iomem *port = sil24_port_base(ap);
- u32 tmp;
+ int err;
- /* clear IRQ */
-@@ -988,7 +949,7 @@ static void sil24_thaw(struct ata_port *ap)
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
- static void sil24_error_intr(struct ata_port *ap)
+ 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)
{
-- 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)
+ int err;
- 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;
+- 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;
}
-@@ -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;
+@@ -780,7 +787,7 @@ int c2_register_device(struct c2_dev *dev)
+ if (ret)
+ goto out2;
-@@ -1064,7 +1025,7 @@ static void sil24_error_intr(struct ata_port *ap)
- irq_stat);
+- 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 {
- err_mask |= AC_ERR_HSM;
-- action |= ATA_EH_HARDRESET;
-+ action |= ATA_EH_RESET;
- freeze = 1;
+- 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);
}
- } 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;
+- 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);
- ehi->action |= action;
+ /* 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);
- /* if PMP, resume */
-- if (ap->nr_pmp_links)
-+ if (sata_pmp_attached(ap))
- writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_STAT);
+ /* 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);
-@@ -1114,18 +1074,9 @@ static void sil24_error_intr(struct ata_port *ap)
+ /* 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);
--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;
+ /* 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 {
+ };
-@@ -1147,13 +1098,13 @@ static inline void sil24_host_intr(struct ata_port *ap)
- }
+ struct c2_netaddr {
+- u32 ip_addr;
+- u32 netmask;
++ __be32 ip_addr;
++ __be32 netmask;
+ u32 mtu;
+ };
- 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);
+@@ -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;
+ };
-- /* 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);
+ /*
+@@ -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;
- pp->do_port_rst = 0;
- }
-@@ -1239,8 +1186,6 @@ static int sil24_port_start(struct ata_port *ap)
- if (!pp)
- return -ENOMEM;
+ /* 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));
-- 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)
+ 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)) ;
- ap->private_data = pp;
+ 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)) ;
-+ 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;
- }
+@@ -585,40 +585,40 @@ enum c2wr_qp_flags {
-@@ -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);
-+
+ 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)) ;
- /* 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;
+ 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)) ;
- /* 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;
+@@ -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)) ;
-- 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 = {
- };
+@@ -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)) ;
- 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),
- };
+@@ -759,25 +759,25 @@ union c2wr_nsmr_stag_alloc {
--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,
- };
+ 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)) ;
- 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;
+ struct c2wr_nsmr_register_rep {
+ struct c2wr_hdr hdr;
+ u32 pbl_depth;
+- u32 stag_index;
++ __be32 stag_index;
+ } __attribute__((packed)) ;
- if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
-- return 0xffffffff;
-+ return -EINVAL;
+ 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)) ;
- pci_read_config_byte(pdev, SIS_PMR, &pmr);
+ 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)) ;
-@@ -190,14 +158,14 @@ static u32 sis_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
- return 0;
- }
+ 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)) ;
--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;
+@@ -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));
- if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
-- return;
-+ return -EINVAL;
+@@ -996,9 +996,9 @@ union c2wr_send {
- pci_read_config_byte(pdev, SIS_PMR, &pmr);
+ 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));
-@@ -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;
- }
+@@ -1009,11 +1009,11 @@ union c2wr_rdma_write {
- 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);
+ 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));
- 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;
+ 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)
- 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;
+ 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)
-- rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
-+ rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
- if (rc)
- return rc;
+ 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)
-@@ -359,8 +329,8 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 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)
- 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);
+ 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..ed2ee4b 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;
}
- 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)
+@@ -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;
- /* 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);
- }
+- 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;
- /**
-@@ -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);
+- 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));
+@@ -456,12 +456,13 @@ void cxio_count_scqes(struct t3_cq *cq, struct t3_wq *wq, int *count)
+ ptr = cq->sw_rptr;
+ while (!Q_EMPTY(ptr, cq->sw_wptr)) {
+ cqe = cq->sw_queue + (Q_PTR2IDX(ptr, cq->size_log2));
+- if ((SQ_TYPE(*cqe) || (CQE_OPCODE(*cqe) == T3_READ_RESP)) &&
++ if ((SQ_TYPE(*cqe) ||
++ ((CQE_OPCODE(*cqe) == T3_READ_RESP) && wq->oldest_read)) &&
+ (CQE_QPID(*cqe) == wq->qpid))
+ (*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 +471,7 @@ void cxio_count_rcqes(struct t3_cq *cq, struct t3_wq *wq, int *count)
+ u32 ptr;
-@@ -327,50 +327,23 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,
+ *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 +480,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 +507,12 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p)
- 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,
- };
+ 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 +522,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 +592,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 +631,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 +702,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 +719,7 @@ static int __cxio_tpt_op(struct cxio_rdev *rdev_p, u32 reset_tpt_entry,
+ if (pbl) {
--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,
- };
+ 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 +815,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) |
+@@ -829,7 +830,8 @@ int cxio_rdma_init(struct cxio_rdev *rdev_p, struct t3_rdma_init_attr *attr)
+ wqe->mpaattrs = attr->mpaattrs;
+ wqe->qpcaps = attr->qpcaps;
+ wqe->ulpdu_size = cpu_to_be16(attr->tcp_emss);
+- wqe->flags = cpu_to_be32(attr->flags);
++ wqe->rqe_count = cpu_to_be16(attr->rqe_count);
++ wqe->flags_rtr_type = cpu_to_be16(attr->flags|V_RTR_TYPE(attr->rtr_type));
+ wqe->ord = cpu_to_be32(attr->ord);
+ wqe->ird = cpu_to_be32(attr->ird);
+ wqe->qp_dma_addr = cpu_to_be64(attr->qp_dma_addr);
+@@ -856,7 +858,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 +870,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 +910,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;
+ }
- 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);
+ list_add_tail(&rdev_p->entry, &rdev_list);
- 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);
- }
+- 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 +925,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;
+ }
- /* 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);
+@@ -947,7 +949,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 +963,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 +971,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 +1045,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 +1114,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));
+@@ -1135,6 +1137,18 @@ int cxio_poll_cq(struct t3_wq *wq, struct t3_cq *cq, struct t3_cqe *cqe,
+ if (RQ_TYPE(*hw_cqe) && (CQE_OPCODE(*hw_cqe) == T3_READ_RESP)) {
- 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,
- };
+ /*
++ * If this is an unsolicited read response, then the read
++ * was generated by the kernel driver as part of peer-2-peer
++ * connection setup. So ignore the completion.
++ */
++ if (!wq->oldest_read) {
++ if (CQE_STATUS(*hw_cqe))
++ wq->error = 1;
++ ret = -1;
++ goto skip_cqe;
++ }
++
++ /*
+ * Don't write to the HWCQ, so create a new read req CQE
+ * in local memory.
+ */
+@@ -1215,7 +1229,7 @@ int cxio_poll_cq(struct t3_wq *wq, struct t3_cq *cq, struct t3_cqe *cqe,
+ struct t3_swsq *sqp;
--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,
- };
+ 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 +1248,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 +1269,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;
-@@ -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];
+ /*
+diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.h b/drivers/infiniband/hw/cxgb3/cxio_hal.h
+index 99543d6..2bcff7f 100644
+--- a/drivers/infiniband/hw/cxgb3/cxio_hal.h
++++ b/drivers/infiniband/hw/cxgb3/cxio_hal.h
+@@ -53,6 +53,7 @@
+ #define T3_MAX_PBL_SIZE 256
+ #define T3_MAX_RQ_SIZE 1024
+ #define T3_MAX_NUM_STAG (1<<15)
++#define T3_MAX_MR_SIZE 0x100000000ULL
- WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
+ #define T3_STAG_UNSET 0xffffffff
-@@ -693,7 +683,7 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc)
- }
+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;
}
--static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
-+static unsigned int pdc20621_qc_issue(struct ata_queued_cmd *qc)
+ void cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid)
{
- 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);
+- PDBG("%s qpid 0x%x\n", __FUNCTION__, qpid);
++ PDBG("%s qpid 0x%x\n", __func__, qpid);
+ cxio_hal_put_resource(rscp->qpid_fifo, qpid);
}
- 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)
+@@ -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)
{
- WARN_ON(tf->protocol == ATA_PROT_DMA ||
- tf->protocol == ATA_PROT_NODATA);
-- ata_tf_load(ap, tf);
-+ ata_sff_tf_load(ap, tf);
+ 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);
+ }
-@@ -917,7 +907,7 @@ static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile
+@@ -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)
{
- WARN_ON(tf->protocol == ATA_PROT_DMA ||
- tf->protocol == ATA_PROT_NODATA);
-- ata_exec_command(ap, tf);
-+ ata_sff_exec_command(ap, tf);
+ 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/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 = {
- };
+diff --git a/drivers/infiniband/hw/cxgb3/cxio_wr.h b/drivers/infiniband/hw/cxgb3/cxio_wr.h
+index 969d4d9..f1a25a8 100644
+--- a/drivers/infiniband/hw/cxgb3/cxio_wr.h
++++ b/drivers/infiniband/hw/cxgb3/cxio_wr.h
+@@ -278,6 +278,17 @@ enum t3_qp_caps {
+ uP_RI_QP_STAG0_ENABLE = 0x10
+ } __attribute__ ((packed));
- 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),
++enum rdma_init_rtr_types {
++ RTR_READ = 1,
++ RTR_WRITE = 2,
++ RTR_SEND = 3,
++};
++
++#define S_RTR_TYPE 2
++#define M_RTR_TYPE 0x3
++#define V_RTR_TYPE(x) ((x) << S_RTR_TYPE)
++#define G_RTR_TYPE(x) ((((x) >> S_RTR_TYPE)) & M_RTR_TYPE)
++
+ struct t3_rdma_init_attr {
+ u32 tid;
+ u32 qpid;
+@@ -293,7 +304,9 @@ struct t3_rdma_init_attr {
+ u32 ird;
+ u64 qp_dma_addr;
+ u32 qp_dma_size;
+- u32 flags;
++ enum rdma_init_rtr_types rtr_type;
++ u16 flags;
++ u16 rqe_count;
+ u32 irs;
};
--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,
+@@ -309,8 +322,8 @@ struct t3_rdma_init_wr {
+ u8 mpaattrs; /* 5 */
+ u8 qpcaps;
+ __be16 ulpdu_size;
+- __be32 flags; /* bits 31-1 - reservered */
+- /* bit 0 - set if RECV posted */
++ __be16 flags_rtr_type;
++ __be16 rqe_count;
+ __be32 ord; /* 6 */
+ __be32 ird;
+ __be64 qp_dma_addr; /* 7 */
+@@ -324,7 +337,7 @@ struct t3_genbit {
+ };
+
+ enum rdma_init_wr_flags {
+- RECVS_POSTED = (1<<0),
++ MPA_INITIATOR = (1<<0),
+ PRIV_QP = (1<<1),
};
- 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)
+diff --git a/drivers/infiniband/hw/cxgb3/iwch.c b/drivers/infiniband/hw/cxgb3/iwch.c
+index 0315c9d..71554ea 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch.c
++++ b/drivers/infiniband/hw/cxgb3/iwch.c
+@@ -65,7 +65,7 @@ static DEFINE_MUTEX(dev_mutex);
- 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 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);
+@@ -83,6 +83,7 @@ static void rnic_init(struct iwch_dev *rnicp)
+ rnicp->attr.max_phys_buf_entries = T3_MAX_PBL_SIZE;
+ rnicp->attr.max_pds = T3_MAX_NUM_PD - 1;
+ rnicp->attr.mem_pgsizes_bitmask = 0x7FFF; /* 4KB-128MB */
++ rnicp->attr.max_mr_size = T3_MAX_MR_SIZE;
+ rnicp->attr.can_resize_wq = 0;
+ rnicp->attr.max_rdma_reads_per_qp = 8;
+ rnicp->attr.max_rdma_read_resources =
+@@ -106,7 +107,7 @@ static void open_rnic_dev(struct t3cdev *tdev)
+ struct iwch_dev *rnicp;
+ static int vers_printed;
- 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 = {
- };
+- 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 +145,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..d2409a5 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch.h
++++ b/drivers/infiniband/hw/cxgb3/iwch.h
+@@ -66,6 +66,7 @@ struct iwch_rnic_attributes {
+ * size (4k)^i. Phys block list mode unsupported.
+ */
+ u32 mem_pgsizes_bitmask;
++ u64 max_mr_size;
+ u8 can_resize_wq;
- 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),
- };
+ /*
+@@ -147,7 +148,7 @@ static inline int insert_handle(struct iwch_dev *rhp, struct idr *idr,
+ void *handle, u32 id)
+ {
+ int ret;
+- u32 newid;
++ int newid;
--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,
+ 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..d44a6df 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
+@@ -63,6 +63,10 @@ static char *states[] = {
+ NULL,
};
--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,
- };
++int peer2peer = 0;
++module_param(peer2peer, int, 0644);
++MODULE_PARM_DESC(peer2peer, "Support peer2peer ULPs (default=0)");
++
+ static int ep_timeout_secs = 10;
+ module_param(ep_timeout_secs, int, 0644);
+ MODULE_PARM_DESC(ep_timeout_secs, "CM Endpoint operation timeout "
+@@ -110,9 +114,9 @@ static void connect_reply_upcall(struct iwch_ep *ep, int status);
--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 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 +128,13 @@ static void start_ep_timer(struct iwch_ep *ep)
- 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);
+ static void stop_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)) {
++ printk(KERN_ERR "%s timer stopped when its not running! ep %p state %u\n",
++ __func__, ep, ep->com.state);
++ WARN_ON(1);
++ return;
++ }
+ del_timer_sync(&ep->timer);
+ put_ep(&ep->com);
}
+@@ -190,7 +200,7 @@ int iwch_resume_tid(struct iwch_ep *ep)
- /**
-@@ -320,23 +236,17 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline)
+ 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 +230,7 @@ static void state_set(struct iwch_ep_common *epc, enum iwch_ep_state new)
+ unsigned long flags;
- if (!online) {
- /* tell EH to bail */
-- ehc->i.action &= ~ATA_EH_RESET_MASK;
-+ ehc->i.action &= ~ATA_EH_RESET;
- return 0;
+ 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 +246,7 @@ static void *alloc_ep(int size, gfp_t gfp)
+ spin_lock_init(&epc->lock);
+ init_waitqueue_head(&epc->waitq);
}
-
- skip_scr:
- /* wait for !BSY */
-- ata_wait_ready(ap, deadline);
-+ ata_sff_wait_ready(link, deadline);
-
- return 0;
+- PDBG("%s alloc ep %p\n", __FUNCTION__, epc);
++ PDBG("%s alloc ep %p\n", __func__, epc);
+ return epc;
}
--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)
+@@ -244,13 +254,13 @@ void __free_ep(struct kref *kref)
{
- 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);
+ 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 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);
+ 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 +359,7 @@ static unsigned int find_best_mtu(const struct t3c_data *d, unsigned short mtu)
- /* 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);
+ 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);
}
- /*
-@@ -300,46 +300,18 @@ out:
+@@ -370,7 +380,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 +390,10 @@ static int send_halfclose(struct iwch_ep *ep, gfp_t gfp)
+ struct cpl_close_con_req *req;
+ struct sk_buff *skb;
- 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),
- };
+- 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 +410,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 +436,12 @@ static int send_connect(struct iwch_ep *ep)
+ unsigned int mtu_idx;
+ int wscale;
--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,
- };
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
- 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
+ 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 +480,7 @@ static void send_mpa_req(struct iwch_ep *ep, struct sk_buff *skb)
+ struct mpa_message *mpa;
+ int len;
- /* see limitations under Hardware Features */
+- PDBG("%s ep %p pd_len %d\n", __FUNCTION__, ep, ep->plen);
++ PDBG("%s ep %p pd_len %d\n", __func__, ep, ep->plen);
--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) {
+ BUG_ON(skb_cloned(skb));
- /********** free an skb (as per ATM device driver documentation) **********/
+@@ -508,7 +518,7 @@ static void send_mpa_req(struct iwch_ep *ep, struct sk_buff *skb)
+ skb_reset_transport_header(skb);
+ len = skb->len;
+ req = (struct tx_data_wr *) skb_push(skb, sizeof(*req));
+- req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA));
++ req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA)|F_WR_COMPL);
+ req->wr_lo = htonl(V_WR_TID(ep->hwtid));
+ req->len = htonl(len);
+ req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
+@@ -530,13 +540,13 @@ static int send_mpa_reject(struct iwch_ep *ep, const void *pdata, u8 plen)
+ struct mpa_message *mpa;
+ struct sk_buff *skb;
--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) {
+- PDBG("%s ep %p plen %d\n", __FUNCTION__, ep, plen);
++ PDBG("%s ep %p plen %d\n", __func__, ep, plen);
- /********** TX completion **********/
+ mpalen = sizeof(*mpa) + plen;
--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) {
+ 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));
+@@ -559,7 +569,7 @@ static int send_mpa_reject(struct iwch_ep *ep, const void *pdata, u8 plen)
+ set_arp_failure_handler(skb, arp_failure_discard);
+ skb_reset_transport_header(skb);
+ req = (struct tx_data_wr *) skb_push(skb, sizeof(*req));
+- req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA));
++ req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA)|F_WR_COMPL);
+ req->wr_lo = htonl(V_WR_TID(ep->hwtid));
+ req->len = htonl(mpalen);
+ req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
+@@ -580,13 +590,13 @@ static int send_mpa_reply(struct iwch_ep *ep, const void *pdata, u8 plen)
+ int len;
+ struct sk_buff *skb;
- /********** TX queue pair **********/
+- PDBG("%s ep %p plen %d\n", __FUNCTION__, ep, plen);
++ PDBG("%s ep %p plen %d\n", __func__, ep, plen);
--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) {
- }
- }
+ mpalen = sizeof(*mpa) + plen;
--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) {
+ 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;
+@@ -611,7 +621,7 @@ static int send_mpa_reply(struct iwch_ep *ep, const void *pdata, u8 plen)
+ skb_reset_transport_header(skb);
+ len = skb->len;
+ req = (struct tx_data_wr *) skb_push(skb, sizeof(*req));
+- req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA));
++ req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA)|F_WR_COMPL);
+ req->wr_lo = htonl(V_WR_TID(ep->hwtid));
+ req->len = htonl(len);
+ req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
+@@ -630,7 +640,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);
- /********** RX queue pairs **********/
+- PDBG("%s ep %p tid %d\n", __FUNCTION__, ep, tid);
++ PDBG("%s ep %p tid %d\n", __func__, ep, tid);
--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) {
- }
- }
+ dst_confirm(ep->dst);
--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 **********/
+@@ -663,7 +673,7 @@ static void close_complete_upcall(struct iwch_ep *ep)
+ {
+ struct iw_cm_event event;
- /* 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);
- }
+- 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 +690,7 @@ static void peer_close_upcall(struct iwch_ep *ep)
+ {
+ struct iw_cm_event event;
--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)
+- 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 +704,7 @@ static void peer_abort_upcall(struct iwch_ep *ep)
{
- rx_in rx;
-@@ -846,7 +846,7 @@ static void fill_rx_pools (amb_dev * dev) {
+ struct iw_cm_event event;
- /********** enable host interrupts **********/
+- 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 +722,7 @@ static void connect_reply_upcall(struct iwch_ep *ep, int status)
+ {
+ struct iw_cm_event event;
--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) {
+- 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 +734,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 +749,7 @@ static void connect_request_upcall(struct iwch_ep *ep)
+ {
+ struct iw_cm_event event;
- /********** disable host interrupts **********/
+- 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 +769,11 @@ static void established_upcall(struct iwch_ep *ep)
+ {
+ struct iw_cm_event event;
--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;
+- 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 +783,7 @@ static int update_rx_credits(struct iwch_ep *ep, u32 credits)
+ struct cpl_rx_data_ack *req;
+ struct sk_buff *skb;
--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;
- }
+- 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 +807,7 @@ static void process_mpa_reply(struct iwch_ep *ep, struct sk_buff *skb)
+ enum iwch_qp_attr_mask mask;
+ int err;
--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) {
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
- /********** free an skb (as per ATM device driver documentation) **********/
+ /*
+ * Stop mpa timer. If it expired, then the state has
+@@ -879,12 +889,13 @@ static void process_mpa_reply(struct iwch_ep *ep, struct sk_buff *skb)
+ * the MPA header is valid.
+ */
+ state_set(&ep->com, FPDU_MODE);
++ ep->mpa_attr.initiator = 1;
+ ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
+ ep->mpa_attr.recv_marker_enabled = markers_enabled;
+ 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);
--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) {
+@@ -901,8 +912,14 @@ static void process_mpa_reply(struct iwch_ep *ep, struct sk_buff *skb)
+ /* bind QP and TID with INIT_WR */
+ err = iwch_modify_qp(ep->com.qp->rhp,
+ ep->com.qp, mask, &attrs, 1);
+- if (!err)
+- goto out;
++ if (err)
++ goto err;
++
++ if (peer2peer && iwch_rqes_posted(ep->com.qp) == 0) {
++ iwch_post_zb_read(ep->com.qp);
++ }
++
++ goto out;
+ err:
+ abort_connection(ep, skb, GFP_KERNEL);
+ out:
+@@ -915,7 +932,7 @@ static void process_mpa_request(struct iwch_ep *ep, struct sk_buff *skb)
+ struct mpa_message *mpa;
+ u16 plen;
- /********** handle RX bus master complete events **********/
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
--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) {
+ /*
+ * Stop mpa timer. If it expired, then the state has
+@@ -935,7 +952,7 @@ static void process_mpa_request(struct iwch_ep *ep, struct sk_buff *skb)
+ return;
+ }
- /********** (queue to) become the next TX thread **********/
+- PDBG("%s enter (%s line %u)\n", __FUNCTION__, __FILE__, __LINE__);
++ PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__);
--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) {
+ /*
+ * Copy the new data into our accumulation buffer.
+@@ -950,7 +967,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;
- /********** handle TX bus master complete events **********/
+ /*
+@@ -995,12 +1012,13 @@ static void process_mpa_request(struct iwch_ep *ep, struct sk_buff *skb)
+ * If we get here we have accumulated the entire mpa
+ * start reply message including private data.
+ */
++ ep->mpa_attr.initiator = 0;
+ ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
+ ep->mpa_attr.recv_marker_enabled = markers_enabled;
+ 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);
--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 **********/
+@@ -1017,7 +1035,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);
- // 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 **********/
+- PDBG("%s ep %p dlen %u\n", __FUNCTION__, ep, dlen);
++ PDBG("%s ep %p dlen %u\n", __func__, ep, dlen);
- // 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 **********/
+ skb_pull(skb, sizeof(*hdr));
+ skb_trim(skb, dlen);
+@@ -1037,7 +1055,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);
- // 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) {
+ /*
+ * The ep will timeout and inform the ULP of the failure.
+@@ -1063,19 +1081,35 @@ 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);
- /********** read the burnt in address **********/
+- PDBG("%s ep %p credits %u\n", __FUNCTION__, ep, credits);
++ PDBG("%s ep %p credits %u\n", __func__, ep, credits);
--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);
+- if (credits == 0)
++ if (credits == 0) {
++ PDBG(KERN_ERR "%s 0 credit ack ep %p state %u\n",
++ __func__, ep, state_read(&ep->com));
+ return CPL_RET_BUF_DONE;
++ }
++
+ BUG_ON(credits != 1);
+- BUG_ON(ep->mpa_skb == NULL);
+- kfree_skb(ep->mpa_skb);
+- ep->mpa_skb = NULL;
+ dst_confirm(ep->dst);
+- if (state_read(&ep->com) == MPA_REP_SENT) {
+- ep->com.rpl_done = 1;
+- PDBG("waking up ep %p\n", ep);
+- wake_up(&ep->com.waitq);
++ if (!ep->mpa_skb) {
++ PDBG("%s rdma_init wr_ack ep %p state %u\n",
++ __func__, ep, state_read(&ep->com));
++ if (ep->mpa_attr.initiator) {
++ PDBG("%s initiator ep %p state %u\n",
++ __func__, ep, state_read(&ep->com));
++ if (peer2peer)
++ iwch_post_zb_read(ep->com.qp);
++ } else {
++ PDBG("%s responder ep %p state %u\n",
++ __func__, ep, state_read(&ep->com));
++ ep->com.rpl_done = 1;
++ wake_up(&ep->com.waitq);
++ }
++ } else {
++ PDBG("%s lsm ack ep %p state %u freeing skb\n",
++ __func__, ep, state_read(&ep->com));
++ kfree_skb(ep->mpa_skb);
++ ep->mpa_skb = NULL;
+ }
+ return CPL_RET_BUF_DONE;
}
-
--static inline void CLOCK_IT (const hrz_dev *dev, u32 ctrl)
-+static void CLOCK_IT (const hrz_dev *dev, u32 ctrl)
+@@ -1083,8 +1117,11 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ static int abort_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
{
- // DI must be valid around rising SK edge
- WRITE_IT_WAIT(dev, ctrl & ~SEEPROM_SK);
-diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
-index 670c093..5c28ca7 100644
---- a/drivers/atm/iphase.c
-+++ b/drivers/atm/iphase.c
-@@ -60,7 +60,8 @@
- #include <asm/uaccess.h>
- #include <asm/string.h>
- #include <asm/byteorder.h>
--#include <linux/vmalloc.h>
-+#include <linux/vmalloc.h>
-+#include <linux/jiffies.h>
- #include "iphase.h"
- #include "suni.h"
- #define swap(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))
-@@ -189,7 +190,7 @@ static u16 get_desc (IADEV *dev, struct ia_vcc *iavcc) {
- int ltimeout;
+ struct iwch_ep *ep = ctx;
++ unsigned long flags;
++ int release = 0;
- 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
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
++ BUG_ON(!ep);
-- /* 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 */
--
+ /*
+ * We get 2 abort replies from the HW. The first one must
+@@ -1095,9 +1132,22 @@ static int abort_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ return CPL_RET_BUF_DONE;
+ }
- /* Function declarations ******************************************************/
+- close_complete_upcall(ep);
+- state_set(&ep->com, DEAD);
+- release_ep_resources(ep);
++ spin_lock_irqsave(&ep->com.lock, flags);
++ switch (ep->com.state) {
++ case ABORTING:
++ close_complete_upcall(ep);
++ __state_set(&ep->com, DEAD);
++ release = 1;
++ break;
++ default:
++ printk(KERN_ERR "%s ep %p state %d\n",
++ __func__, ep, ep->com.state);
++ break;
++ }
++ spin_unlock_irqrestore(&ep->com.lock, flags);
++
++ if (release)
++ release_ep_resources(ep);
+ return CPL_RET_BUF_DONE;
+ }
-@@ -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;
- }
+@@ -1115,7 +1165,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);
-- ns_grab_res_lock(card, flags);
-+ spin_lock_irqsave(&card->res_lock, flags);
+- 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 +1183,7 @@ static int listen_start(struct iwch_listen_ep *ep)
+ struct sk_buff *skb;
+ struct cpl_pass_open_req *req;
- while (CMD_BUSY(card));
- writel(addr2, card->membase + DR3);
-@@ -1206,7 +1127,7 @@ static irqreturn_t ns_irq_handler(int irq, void *dev_id)
+- 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 +1212,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);
- PRINTK("nicstar%d: NICStAR generated an interrupt\n", card->index);
+- 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 +1226,10 @@ static int listen_stop(struct iwch_listen_ep *ep)
+ struct sk_buff *skb;
+ struct cpl_close_listserv_req *req;
-- ns_grab_int_lock(card, flags);
-+ spin_lock_irqsave(&card->int_lock, flags);
-
- stat_r = readl(card->membase + STAT);
+- 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 +1247,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);
-@@ -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)
+- 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 +1261,7 @@ static void accept_cr(struct iwch_ep *ep, __be32 peer_ip, struct sk_buff *skb)
+ u32 opt0h, opt0l, opt2;
+ int wscale;
- 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;
+- 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 +1294,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 +1329,11 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ struct rtable *rt;
+ struct iff_mac tim;
-- ns_grab_scq_lock(card, scq, flags);
-+ spin_lock_irqsave(&scq->lock, flags);
+- PDBG("%s parent ep %p tid %u\n", __FUNCTION__, parent_ep, hwtid);
++ PDBG("%s parent ep %p tid %u\n", __func__, parent_ep, hwtid);
- 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 (state_read(&parent_ep->com) != LISTEN) {
+ printk(KERN_ERR "%s - listening ep not in LISTEN\n",
+- __FUNCTION__);
++ __func__);
+ goto reject;
+ }
- 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);
- }
+@@ -1295,7 +1345,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 +1363,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 +1412,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);
- if (!scq->full)
-@@ -2090,7 +2011,7 @@ static void drain_scq(ns_dev *card, scq_info *scq, int pos)
- return;
- }
+- 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);
-- 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;
+@@ -1383,7 +1433,7 @@ static int peer_close(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ int disconnect = 1;
+ int release = 0;
-- 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;
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ dst_confirm(ep->dst);
-- 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);
+ spin_lock_irqsave(&ep->com.lock, flags);
+@@ -1470,10 +1520,11 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ struct sk_buff *rpl_skb;
+ struct iwch_qp_attributes attrs;
+ int ret;
+- int state;
++ int release = 0;
++ unsigned long 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;
+ 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;
+@@ -1488,9 +1539,9 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ return CPL_RET_BUF_DONE;
+ }
- 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;
+- state = state_read(&ep->com);
+- PDBG("%s ep %p state %u\n", __FUNCTION__, ep, state);
+- switch (state) {
++ spin_lock_irqsave(&ep->com.lock, flags);
++ PDBG("%s ep %p state %u\n", __func__, ep, ep->com.state);
++ switch (ep->com.state) {
+ case CONNECTING:
+ break;
+ case MPA_REQ_WAIT:
+@@ -1528,29 +1579,33 @@ 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__);
++ spin_unlock_irqrestore(&ep->com.lock, flags);
+ return CPL_RET_BUF_DONE;
+ default:
+ BUG_ON(1);
+ break;
+ }
+ dst_confirm(ep->dst);
++ if (ep->com.state != ABORTING) {
++ __state_set(&ep->com, DEAD);
++ release = 1;
++ }
++ spin_unlock_irqrestore(&ep->com.lock, flags);
- 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 @@
+ rpl_skb = get_skb(skb, sizeof(*rpl), GFP_KERNEL);
+ if (!rpl_skb) {
+ printk(KERN_ERR MOD "%s - cannot allocate skb!\n",
+- __FUNCTION__);
+- dst_release(ep->dst);
+- l2t_release(L2DATA(ep->com.tdev), ep->l2t);
+- put_ep(&ep->com);
+- return CPL_RET_BUF_DONE;
++ __func__);
++ release = 1;
++ goto out;
+ }
+ rpl_skb->priority = CPL_PRIORITY_DATA;
+ rpl = (struct cpl_abort_rpl *) skb_put(rpl_skb, sizeof(*rpl));
+@@ -1559,10 +1614,9 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_ABORT_RPL, ep->hwtid));
+ rpl->cmd = CPL_ABORT_NO_RST;
+ cxgb3_ofld_send(ep->com.tdev, rpl_skb);
+- if (state != ABORTING) {
+- state_set(&ep->com, DEAD);
++out:
++ if (release)
+ release_ep_resources(ep);
+- }
+ return CPL_RET_BUF_DONE;
+ }
- /* Options ********************************************************************/
+@@ -1573,7 +1627,7 @@ static int close_con_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ unsigned long flags;
+ int release = 0;
--#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;
+- 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 +1678,9 @@ static int terminate(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ {
+ struct iwch_ep *ep = ctx;
-@@ -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;
+- 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 +1693,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;
-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;
- };
+ 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,
+@@ -1661,15 +1715,18 @@ static void ep_timeout(unsigned long arg)
+ struct iwch_ep *ep = (struct iwch_ep *)arg;
+ struct iwch_qp_attributes attrs;
+ unsigned long flags;
++ int abort = 1;
- 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);
+ 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:
++ __state_set(&ep->com, ABORTING);
+ connect_reply_upcall(ep, -ETIMEDOUT);
+ break;
+ case MPA_REQ_WAIT:
++ __state_set(&ep->com, ABORTING);
+ break;
+ case CLOSING:
+ case MORIBUND:
+@@ -1679,13 +1736,17 @@ static void ep_timeout(unsigned long arg)
+ ep->com.qp, IWCH_QP_ATTR_NEXT_STATE,
+ &attrs, 1);
+ }
++ __state_set(&ep->com, ABORTING);
+ break;
+ default:
+- BUG();
++ printk(KERN_ERR "%s unexpected state ep %p state %u\n",
++ __func__, ep, ep->com.state);
++ WARN_ON(1);
++ abort = 0;
+ }
+- __state_set(&ep->com, CLOSING);
+ spin_unlock_irqrestore(&ep->com.lock, flags);
+- abort_connection(ep, NULL, GFP_ATOMIC);
++ if (abort)
++ abort_connection(ep, NULL, GFP_ATOMIC);
+ put_ep(&ep->com);
}
- static void internal_container_klist_put(struct klist_node *n)
+@@ -1693,7 +1754,7 @@ int iwch_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
{
- struct internal_container *ic =
- container_of(n, struct internal_container, node);
-- class_device_put(&ic->classdev);
-+ put_device(&ic->classdev);
- }
-
+ 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);
-@@ -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);
+ if (state_read(&ep->com) == DEAD) {
+ put_ep(&ep->com);
+@@ -1718,7 +1779,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);
- /* 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;
+- 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;
- 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;
+@@ -1739,7 +1800,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);
-@@ -163,11 +163,11 @@ attribute_container_add_device(struct device *dev,
- }
+ get_ep(&ep->com);
- 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;
+@@ -1762,16 +1823,19 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ if (err)
+ goto err;
-@@ -224,14 +223,14 @@ attribute_container_remove_device(struct device *dev,
- continue;
++ /* if needed, wait for wr_ack */
++ if (iwch_rqes_posted(qp)) {
++ wait_event(ep->com.waitq, ep->com.rpl_done);
++ err = ep->com.rpl_err;
++ if (err)
++ goto err;
++ }
++
+ err = send_mpa_reply(ep, conn_param->private_data,
+ conn_param->private_data_len);
+ if (err)
+ goto err;
- 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;
+- /* wait for wr_ack */
+- wait_event(ep->com.waitq, ep->com.rpl_done);
+- err = ep->com.rpl_err;
+- if (err)
+- goto err;
-@@ -270,7 +269,7 @@ attribute_container_device_trigger(struct device *dev,
- }
+ state_set(&ep->com, FPDU_MODE);
+ established_upcall(ep);
+@@ -1810,7 +1874,7 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
- klist_for_each_entry(ic, &cont->containers, node, &iter) {
-- if (dev == ic->classdev.dev)
-+ if (dev == ic->classdev.parent)
- fn(cont, dev, &ic->classdev);
- }
+ 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;
}
-@@ -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;
+@@ -1827,7 +1891,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);
- 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);
+ /*
+@@ -1835,7 +1899,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 +1911,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 +1921,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 +1958,11 @@ int iwch_create_listen(struct iw_cm_id *cm_id, int backlog)
- 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;
+ 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;
}
-@@ -338,18 +337,18 @@ attribute_container_add_attrs(struct class_device *classdev)
- }
+- 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 +1974,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 +2006,7 @@ int iwch_destroy_listen(struct iw_cm_id *cm_id)
+ int err;
+ struct iwch_listen_ep *ep = to_listen_ep(cm_id);
- /**
-- * 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;
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
- if (!attrs && !cont->grp)
-@@ -392,7 +391,7 @@ attribute_container_remove_attrs(struct class_device *classdev)
- }
+ might_sleep();
+ state_set(&ep->com, DEAD);
+@@ -1965,43 +2029,42 @@ int iwch_ep_disconnect(struct iwch_ep *ep, int abrupt, gfp_t gfp)
- for (i = 0; attrs[i]; i++)
-- class_device_remove_file(classdev, attrs[i]);
-+ device_remove_file(classdev, attrs[i]);
- }
+ spin_lock_irqsave(&ep->com.lock, flags);
- /**
-@@ -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);
- }
+- 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);
- /**
-@@ -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;
+- if (ep->com.state == DEAD) {
+- PDBG("%s already dead ep %p\n", __FUNCTION__, ep);
+- goto out;
+- }
+-
+- if (abrupt) {
+- if (ep->com.state != ABORTING) {
+- ep->com.state = ABORTING;
+- close = 1;
+- }
+- goto out;
+- }
+-
+ switch (ep->com.state) {
+ case MPA_REQ_WAIT:
+ case MPA_REQ_SENT:
+ case MPA_REQ_RCVD:
+ case MPA_REP_SENT:
+ case FPDU_MODE:
+- start_ep_timer(ep);
+- ep->com.state = CLOSING;
+ close = 1;
++ if (abrupt)
++ ep->com.state = ABORTING;
++ else {
++ ep->com.state = CLOSING;
++ start_ep_timer(ep);
++ }
+ break;
+ case CLOSING:
+- ep->com.state = MORIBUND;
+ close = 1;
++ if (abrupt) {
++ stop_ep_timer(ep);
++ ep->com.state = ABORTING;
++ } else
++ ep->com.state = MORIBUND;
+ break;
+ case MORIBUND:
++ case ABORTING:
++ case DEAD:
++ PDBG("%s ignoring disconnect ep %p state %u\n",
++ __func__, ep, ep->com.state);
+ break;
+ default:
+ BUG();
+ break;
+ }
+-out:
++
+ spin_unlock_irqrestore(&ep->com.lock, flags);
+ if (close) {
+ if (abrupt)
+@@ -2020,7 +2083,7 @@ int iwch_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new,
+ if (ep->dst != old)
+ return 0;
- 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);
+- 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..d7c7e09 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_cm.h
++++ b/drivers/infiniband/hw/cxgb3/iwch_cm.h
+@@ -54,13 +54,14 @@
+ #define MPA_FLAGS_MASK 0xE0
-- pr_debug("driver: '%s': %s\n", kobject_name(kobj), __FUNCTION__);
-+ pr_debug("driver: '%s': %s\n", kobject_name(kobj), __func__);
- kfree(drv_priv);
+ #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))); \
++ WARN_ON(atomic_read(&((ep)->kref.refcount)) < 1); \
+ kref_put(&((ep)->kref), __free_ep); \
}
-@@ -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;
- }
+ #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)); \
}
+@@ -225,5 +226,6 @@ int iwch_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new, st
-@@ -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);
+ int __init iwch_cm_init(void);
+ void __exit iwch_cm_term(void);
++extern int peer2peer;
+
+ #endif /* _IWCH_CM_H_ */
+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);
- 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)
+ 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,
- 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);
- }
+ 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;
+ }
- 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);
+ 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;
}
-@@ -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);
+@@ -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;
}
-@@ -415,7 +415,7 @@ static int class_uevent(struct kset *kset, struct kobject *kobj,
- struct device *dev = class_dev->dev;
- int retval = 0;
+@@ -163,7 +163,7 @@ int build_phys_page_list(struct ib_phys_buf *buffer_list,
+ ((u64) j << *shift));
-- pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
-+ pr_debug("%s - name = %s\n", __func__, class_dev->class_id);
+ 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);
- if (MAJOR(class_dev->devt)) {
- add_uevent_var(env, "MAJOR=%u", MAJOR(class_dev->devt));
-diff --git a/drivers/base/core.c b/drivers/base/core.c
-index 24198ad..9248e09 100644
---- a/drivers/base/core.c
-+++ b/drivers/base/core.c
-@@ -20,7 +20,7 @@
- #include <linux/notifier.h>
- #include <linux/genhd.h>
- #include <linux/kallsyms.h>
--#include <asm/semaphore.h>
-+#include <linux/semaphore.h>
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
+index b2ea921..d07d3a3 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;
- #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);
- }
+- 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);
- /* 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);
- }
+- 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;
- /* 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);
- }
+- PDBG("%s ib_cq %p\n", __FUNCTION__, ib_cq);
++ PDBG("%s ib_cq %p\n", __func__, ib_cq);
+ chp = to_iwch_cq(ib_cq);
- return retval;
-@@ -782,7 +782,7 @@ int device_add(struct device *dev)
- goto Done;
- }
+ 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;
-- pr_debug("device: '%s': %s\n", dev->bus_id, __FUNCTION__);
-+ pr_debug("device: '%s': %s\n", dev->bus_id, __func__);
+- 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;
- 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);
+- PDBG("%s ib_cq %p cqe %d\n", __FUNCTION__, cq, cqe);
++ PDBG("%s ib_cq %p cqe %d\n", __func__, cq, cqe);
- 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);
- }
+ /* 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);
+ }
-@@ -1164,35 +1163,6 @@ void device_destroy(struct class *class, dev_t devt)
- }
- EXPORT_SYMBOL_GPL(device_destroy);
+ /* 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;
--#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;
+- 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);
- pr_debug("device: '%s': %s: renaming to '%s'\n", dev->bus_id,
-- __FUNCTION__, new_name);
-+ __func__, new_name);
+ if (vma->vm_start & (PAGE_SIZE-1)) {
+@@ -390,7 +390,7 @@ static int iwch_deallocate_pd(struct ib_pd *pd)
- #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);
+ 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);
}
}
- #endif
-@@ -1325,7 +1295,7 @@ int device_move(struct device *dev, struct device *new_parent)
- new_parent_kobj = get_device_parent(dev, new_parent);
-
- pr_debug("device: '%s': %s: moving to '%s'\n", dev->bus_id,
-- __FUNCTION__, new_parent ? new_parent->bus_id : "<NULL>");
-+ __func__, new_parent ? new_parent->bus_id : "<NULL>");
- error = kobject_move(&dev->kobj, new_parent_kobj);
- if (error) {
- cleanup_glue_dir(dev, new_parent_kobj);
-diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
-index 499b003..6fe4174 100644
---- a/drivers/base/cpu.c
-+++ b/drivers/base/cpu.c
-@@ -28,7 +28,7 @@ static ssize_t show_online(struct sys_device *dev, char *buf)
- return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id));
+- 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;
}
--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);
+@@ -432,7 +432,7 @@ static int iwch_dereg_mr(struct ib_mr *ib_mr)
+ struct iwch_mr *mhp;
+ u32 mmid;
--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);
+- 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;
}
-@@ -103,6 +103,51 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
- #endif
+@@ -467,7 +467,7 @@ static struct ib_mr *iwch_register_phys_mem(struct ib_pd *pd,
+ struct iwch_mr *mhp;
+ int ret;
- /*
-+ * 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;
+- PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
++ PDBG("%s ib_pd %p\n", __func__, pd);
+ php = to_iwch_pd(pd);
+ rhp = php->rhp;
- 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;
- }
+@@ -531,7 +531,7 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr,
+ int npages;
+ int ret;
- pr_debug("driver: '%s': %s: bound to device '%s'\n", dev->bus_id,
-- __FUNCTION__, dev->driver->name);
-+ __func__, dev->driver->name);
+- PDBG("%s ib_mr %p ib_pd %p\n", __FUNCTION__, mr, pd);
++ PDBG("%s ib_mr %p ib_pd %p\n", __func__, mr, pd);
- 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)
+ /* 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;
- 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));
+- PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
++ PDBG("%s ib_pd %p\n", __func__, pd);
- 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;
- }
+ php = to_iwch_pd(pd);
+ rhp = php->rhp;
+@@ -602,7 +602,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+ if (!mhp)
+ return ERR_PTR(-ENOMEM);
-@@ -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;
+- mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc);
++ mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
+ if (IS_ERR(mhp->umem)) {
+ err = PTR_ERR(mhp->umem);
+ kfree(mhp);
+@@ -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);
- 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;
+ 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;
- 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);
+- PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
++ PDBG("%s ib_pd %p\n", __func__, pd);
- ret = really_probe(dev, drv);
+ /*
+ * 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);
+ }
-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;
+@@ -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;
+ }
- 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;
- }
+@@ -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);
- 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;
- }
+- 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;
-@@ -399,7 +399,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
- *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
- if (!firmware) {
- printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
-- __FUNCTION__);
-+ __func__);
- retval = -ENOMEM;
- goto out;
- }
-@@ -570,13 +570,13 @@ firmware_class_init(void)
- int error;
- error = class_register(&firmware_class);
- if (error) {
-- printk(KERN_ERR "%s: class_register failed\n", __FUNCTION__);
-+ printk(KERN_ERR "%s: class_register failed\n", __func__);
- return error;
- }
- error = class_create_file(&firmware_class, &class_attr_timeout);
- if (error) {
- printk(KERN_ERR "%s: class_create_file failed\n",
-- __FUNCTION__);
-+ __func__);
- class_unregister(&firmware_class);
- }
- return error;
-diff --git a/drivers/base/memory.c b/drivers/base/memory.c
-index 7ae413f..8ce6de5 100644
---- a/drivers/base/memory.c
-+++ b/drivers/base/memory.c
-@@ -20,6 +20,7 @@
- #include <linux/kobject.h>
- #include <linux/memory_hotplug.h>
- #include <linux/mm.h>
-+#include <linux/mutex.h>
- #include <asm/atomic.h>
- #include <asm/uaccess.h>
+- 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;
-@@ -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;
+- PDBG("%s ib_qp %p\n", __FUNCTION__, ibqp);
++ PDBG("%s ib_qp %p\n", __func__, ibqp);
-@@ -70,26 +71,18 @@ int register_memory(struct memory_block *memory, struct mem_section *section,
- memory->sysdev.id = __section_nr(section);
+ /* 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,
- 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;
+ 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));
}
- 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)
+ void iwch_qp_rem_ref(struct ib_qp *qp)
{
- 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));
+- 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));
}
- /*
-@@ -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)
+ static struct ib_qp *iwch_get_qp(struct ib_device *dev, int qpn)
{
- 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;
+- 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);
}
-@@ -341,10 +334,10 @@ static int add_memory_block(unsigned long node_id, struct mem_section *section,
+@@ -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;
- mem->phys_index = __section_nr(section);
- mem->state = state;
-- init_MUTEX(&mem->state_sem);
-+ mutex_init(&mem->state_mutex);
- mem->phys_device = phys_device;
+ 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,
+ {
-- 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);
+ 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);
+@@ -998,7 +998,7 @@ static int iwch_query_device(struct ib_device *ibdev,
+ props->device_cap_flags = dev->device_cap_flags;
+ props->vendor_id = (u32)dev->rdev.rnic_info.pdev->vendor;
+ props->vendor_part_id = (u32)dev->rdev.rnic_info.pdev->device;
+- props->max_mr_size = ~0ull;
++ props->max_mr_size = dev->attr.max_mr_size;
+ props->max_qp = dev->attr.max_qps;
+ props->max_qp_wr = dev->attr.max_wrs;
+ props->max_sge = dev->attr.max_sge_per_wr;
+@@ -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;
}
-@@ -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)
+-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 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;
+- 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);
+ }
-- /* 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));
+-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;
-- 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;
+- 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 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);
+-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;
- #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)
+- 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);
+ }
- 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)
+-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)
{
- 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);
+- 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 DEFINE_MUTEX(dpm_list_mtx);
+-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 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;
+-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
+ };
- /**
- * 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;
- }
+ int iwch_register_device(struct iwch_dev *dev)
+@@ -1103,14 +1102,13 @@ int iwch_register_device(struct iwch_dev *dev)
+ int ret;
+ int i;
- /**
-@@ -89,50 +100,6 @@ void device_pm_remove(struct device *dev)
- mutex_unlock(&dpm_list_mtx);
- }
+- 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);
--/**
-- * 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 -------------------------*/
+ 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;
- /**
-@@ -242,11 +209,13 @@ static int resume_device(struct device *dev)
- static void dpm_resume(void)
+ 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)
{
- 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);
+ int i;
- 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)
+- 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..db5100d 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_provider.h
++++ b/drivers/infiniband/hw/cxgb3/iwch_provider.h
+@@ -118,6 +118,7 @@ enum IWCH_QP_FLAGS {
+ };
- /**
-- * 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)
+ struct iwch_mpa_attributes {
++ u8 initiator;
+ u8 recv_marker_enabled;
+ u8 xmit_marker_enabled; /* iWARP: enable inbound Read Resp. */
+ u8 crc_enabled;
+@@ -213,7 +214,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 +227,7 @@ static inline void insert_mmap(struct iwch_ucontext *ucontext,
+ struct iwch_mm_entry *mm)
{
- might_sleep();
- dpm_resume();
-- unregister_dropped_devices();
-- up_write(&pm_sleep_rwsem);
- }
- EXPORT_SYMBOL_GPL(device_resume);
+ 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);
+@@ -322,6 +323,7 @@ enum iwch_qp_query_flags {
+ IWCH_QP_QUERY_TEST_USERWRITE = 0x32 /* Test special */
+ };
-@@ -377,11 +324,6 @@ static int suspend_device(struct device *dev, pm_message_t state)
++u16 iwch_rqes_posted(struct iwch_qp *qhp);
+ int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ struct ib_send_wr **bad_wr);
+ int iwch_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+@@ -331,6 +333,7 @@ int iwch_bind_mw(struct ib_qp *qp,
+ struct ib_mw_bind *mw_bind);
+ int iwch_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
+ int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg);
++int iwch_post_zb_read(struct iwch_qp *qhp);
+ int iwch_register_device(struct iwch_dev *dev);
+ void iwch_unregister_device(struct iwch_dev *dev);
+ int iwch_quiesce_qps(struct iwch_cq *chp);
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
+index ea2cdd7..9b4be88 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,
- down(&dev->sem);
+ 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,
-- 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);
+ 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;
+ }
-+ 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;
+ 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;
}
- if (!list_empty(&dev->power.entry))
- list_move(&dev->power.entry, &dpm_off);
+@@ -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;
}
-+ 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;
+ 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);
- 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);
+@@ -586,6 +586,36 @@ static inline void build_term_codes(struct respQ_msg_t *rsp_msg,
+ }
}
--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) {}
++int iwch_post_zb_read(struct iwch_qp *qhp)
++{
++ union t3_wr *wqe;
++ struct sk_buff *skb;
++ u8 flit_cnt = sizeof(struct t3_rdma_read_wr) >> 3;
++
++ PDBG("%s enter\n", __func__);
++ skb = alloc_skb(40, GFP_KERNEL);
++ if (!skb) {
++ printk(KERN_ERR "%s cannot send zb_read!!\n", __func__);
++ return -ENOMEM;
++ }
++ wqe = (union t3_wr *)skb_put(skb, sizeof(struct t3_rdma_read_wr));
++ memset(wqe, 0, sizeof(struct t3_rdma_read_wr));
++ wqe->read.rdmaop = T3_READ_REQ;
++ wqe->read.reserved[0] = 0;
++ wqe->read.reserved[1] = 0;
++ wqe->read.reserved[2] = 0;
++ wqe->read.rem_stag = cpu_to_be32(1);
++ wqe->read.rem_to = cpu_to_be64(1);
++ wqe->read.local_stag = cpu_to_be32(1);
++ wqe->read.local_len = cpu_to_be32(0);
++ wqe->read.local_to = cpu_to_be64(1);
++ wqe->send.wrh.op_seop_flags = cpu_to_be32(V_FW_RIWR_OP(T3_WR_READ));
++ wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(qhp->ep->hwtid)|
++ V_FW_RIWR_LEN(flit_cnt));
++ skb->priority = CPL_PRIORITY_DATA;
++ return cxgb3_ofld_send(qhp->rhp->rdev.t3cdev_p, skb);
++}
++
+ /*
+ * This posts a TERMINATE with layer=RDMA, type=catastrophic.
+ */
+@@ -595,10 +625,10 @@ int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg)
+ struct terminate_message *term;
+ struct sk_buff *skb;
- #endif
+- 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 +659,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);
-diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
-index f2ed179..d11f74b 100644
---- a/drivers/base/power/sysfs.c
-+++ b/drivers/base/power/sysfs.c
-@@ -6,6 +6,8 @@
- #include <linux/string.h>
- #include "power.h"
+- 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);
+@@ -671,11 +701,18 @@ static void flush_qp(struct iwch_qp *qhp, unsigned long *flag)
-+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)
+- * Return non zero if at least one RECV was pre-posted.
++ * Return count of RECV WRs posted
+ */
+-static int rqes_posted(struct iwch_qp *qhp)
++u16 iwch_rqes_posted(struct iwch_qp *qhp)
{
- 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);
+- return fw_riwrh_opcode((struct fw_riwrh *)qhp->wq.queue) == T3_WR_RCV;
++ union t3_wr *wqe = qhp->wq.queue;
++ u16 count = 0;
++ while ((count+1) != 0 && fw_riwrh_opcode((struct fw_riwrh *)wqe) == T3_WR_RCV) {
++ count++;
++ wqe++;
+ }
-+
- 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)); \
++ PDBG("%s qhp %p count %u\n", __func__, qhp, count);
++ return count;
}
--#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); \
+ static int rdma_init(struct iwch_dev *rhp, struct iwch_qp *qhp,
+@@ -716,15 +753,24 @@ static int rdma_init(struct iwch_dev *rhp, struct iwch_qp *qhp,
+ init_attr.ird = qhp->attr.max_ird;
+ init_attr.qp_dma_addr = qhp->wq.dma_addr;
+ init_attr.qp_dma_size = (1UL << qhp->wq.size_log2);
+- init_attr.flags = rqes_posted(qhp) ? RECVS_POSTED : 0;
++ init_attr.rqe_count = iwch_rqes_posted(qhp);
++ init_attr.flags = qhp->attr.mpa_attr.initiator ? MPA_INITIATOR : 0;
+ init_attr.flags |= capable(CAP_NET_BIND_SERVICE) ? PRIV_QP : 0;
++ if (peer2peer) {
++ init_attr.rtr_type = RTR_READ;
++ if (init_attr.ord == 0 && qhp->attr.mpa_attr.initiator)
++ init_attr.ord = 1;
++ if (init_attr.ird == 0 && !qhp->attr.mpa_attr.initiator)
++ init_attr.ird = 1;
++ } else
++ init_attr.rtr_type = 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;
}
-+#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);
+@@ -742,7 +788,7 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
+ int free = 0;
+ struct iwch_ep *ep = NULL;
- 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();
+- 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);
+
+@@ -832,6 +878,7 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
+ abort=0;
+ disconnect = 1;
+ ep = qhp->ep;
++ get_ep(&ep->com);
+ }
+ flush_qp(qhp, &flag);
+ break;
+@@ -848,6 +895,7 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
+ abort=1;
+ disconnect = 1;
+ ep = qhp->ep;
++ get_ep(&ep->com);
+ }
+ goto err;
+ break;
+@@ -899,14 +947,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 */
+@@ -929,8 +977,10 @@ out:
+ * on the EP. This can be a normal close (RTS->CLOSING) or
+ * an abnormal close (RTS/CLOSING->ERROR).
+ */
+- if (disconnect)
++ if (disconnect) {
+ iwch_ep_disconnect(ep, abort, GFP_KERNEL);
++ put_ep(&ep->com);
++ }
+
+ /*
+ * If free is 1, then we've disassociated the EP from the QP
+@@ -939,7 +989,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;
}
- 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);
+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.
+ */
- static int transport_add_class_device(struct attribute_container *cont,
- struct device *dev,
-- struct class_device *classdev)
-+ struct device *classdev)
+-
+-#include <asm/current.h>
+-
+ #include "ehca_tools.h"
+ #include "ehca_iverbs.h"
+ #include "hcp_if.h"
+@@ -170,17 +167,8 @@ int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
{
- int error = attribute_container_add_class_device(classdev);
- struct transport_container *tcont =
-@@ -180,7 +181,7 @@ EXPORT_SYMBOL_GPL(transport_add_device);
+ 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;
+- }
- static int transport_configure(struct attribute_container *cont,
- struct device *dev,
-- struct class_device *cdev)
-+ struct device *cdev)
+ 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 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);
+ 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;
+- }
- 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);
+ 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)
- static void transport_destroy_classdev(struct attribute_container *cont,
- struct device *dev,
-- struct class_device *classdev)
-+ struct device *classdev)
+ int ehca_destroy_ah(struct ib_ah *ah)
{
- struct transport_class *tclass = class_to_transport_class(cont->class);
-
- if (tclass->remove != anon_transport_dummy_function)
-- class_device_put(classdev);
-+ put_device(classdev);
- }
+- 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..00bab60 100644
+--- a/drivers/infiniband/hw/ehca/ehca_classes.h
++++ b/drivers/infiniband/hw/ehca/ehca_classes.h
+@@ -66,6 +66,7 @@ struct ehca_av;
+ #include "ehca_irq.h"
-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;
+ #define EHCA_EQE_CACHE_SIZE 20
++#define EHCA_MAX_NUM_QUEUES 0xffff
-- if (ifp->nd_net != &init_net)
-+ if (dev_net(ifp) != &init_net)
- goto exit;
+ struct ehca_eqe_cache_entry {
+ struct ehca_eqe *eqe;
+@@ -127,12 +128,13 @@ struct ehca_shca {
+ /* MR pgsize: bit 0-3 means 4K, 64K, 1M, 16M respectively */
+ u32 hca_cap_mr_pgsize;
+ int max_mtu;
++ atomic_t num_cqs;
++ atomic_t num_qps;
+ };
- 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;
+ 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];
+@@ -161,6 +163,7 @@ struct ehca_qp {
+ };
+ u32 qp_type;
+ enum ehca_ext_qp_type ext_type;
++ enum ib_qp_state state;
+ struct ipz_queue ipz_squeue;
+ struct ipz_queue ipz_rqueue;
+ struct h_galpas galpas;
+@@ -215,7 +218,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;
+@@ -345,6 +347,8 @@ extern int ehca_use_hp_mr;
+ extern int ehca_scaling_code;
+ extern int ehca_lock_hcalls;
+ extern int ehca_nr_ports;
++extern int ehca_max_cq;
++extern int ehca_max_qp;
-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);
+ struct ipzu_queue_resp {
+ u32 qe_size; /* queue entry size */
+diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
+index 0467c15..5540b27 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.
+ */
-+ /* 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);
+-#include <asm/current.h>
+-
+ #include "ehca_iverbs.h"
+ #include "ehca_classes.h"
+ #include "ehca_irq.h"
+@@ -134,10 +132,19 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
+ if (cqe >= 0xFFFFFFFF - 64 - additional_cqe)
+ return ERR_PTR(-EINVAL);
-+ /* 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]);
++ if (!atomic_add_unless(&shca->num_cqs, 1, ehca_max_cq)) {
++ ehca_err(device, "Unable to create CQ, max number of %i "
++ "CQs reached.", ehca_max_cq);
++ ehca_err(device, "To increase the maximum number of CQs "
++ "use the number_of_cqs module parameter.\n");
++ return ERR_PTR(-ENOSPC);
++ }
+
- return 1;
+ my_cq = kmem_cache_zalloc(cq_cache, GFP_KERNEL);
+ if (!my_cq) {
+ ehca_err(device, "Out of memory for ehca_cq struct device=%p",
+ device);
++ atomic_dec(&shca->num_cqs);
+ return ERR_PTR(-ENOMEM);
+ }
- 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);
- }
+@@ -148,7 +155,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;
- static int
-diff --git a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c
-index 2411678..8b6bb76 100644
---- a/drivers/block/cryptoloop.c
-+++ b/drivers/block/cryptoloop.c
-@@ -27,7 +27,6 @@
- #include <linux/blkdev.h>
- #include <linux/loop.h>
- #include <linux/scatterlist.h>
--#include <asm/semaphore.h>
- #include <asm/uaccess.h>
+ cq = &my_cq->ib_cq;
- 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);
+@@ -308,6 +314,7 @@ create_cq_exit2:
+ create_cq_exit1:
+ kmem_cache_free(cq_cache, my_cq);
-+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;
++ atomic_dec(&shca->num_cqs);
+ return cq;
+ }
- fput(old_file);
-+ if (max_part > 0)
-+ ioctl_by_bdev(bdev, BLKRRPART, 0);
- return 0;
+@@ -320,7 +327,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;
- out_putf:
-@@ -819,6 +824,8 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
+ if (cq->uobject) {
+@@ -329,12 +335,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;
+- }
}
- 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);
+ /*
+@@ -369,20 +369,12 @@ int ehca_destroy_cq(struct ib_cq *cq)
+ ipz_queue_dtor(NULL, &my_cq->ipz_queue);
+ kmem_cache_free(cq_cache, my_cq);
+
++ atomic_dec(&shca->num_cqs);
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);
+ 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");
-@@ -1412,7 +1423,7 @@ static struct loop_device *loop_alloc(int i)
- if (!lo->lo_queue)
- goto out_free_dev;
+diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c
+index b4ac617..49660df 100644
+--- a/drivers/infiniband/hw/ehca/ehca_eq.c
++++ b/drivers/infiniband/hw/ehca/ehca_eq.c
+@@ -54,7 +54,8 @@ int ehca_create_eq(struct ehca_shca *shca,
+ struct ehca_eq *eq,
+ const enum ehca_eq_type type, const u32 length)
+ {
+- u64 ret;
++ int ret;
++ u64 h_ret;
+ u32 nr_pages;
+ u32 i;
+ void *vpage;
+@@ -73,15 +74,15 @@ int ehca_create_eq(struct ehca_shca *shca,
+ return -EINVAL;
+ }
-- disk = lo->lo_disk = alloc_disk(1);
-+ disk = lo->lo_disk = alloc_disk(1 << part_shift);
- if (!disk)
- goto out_free_queue;
+- ret = hipz_h_alloc_resource_eq(shca->ipz_hca_handle,
+- &eq->pf,
+- type,
+- length,
+- &eq->ipz_eq_handle,
+- &eq->length,
+- &nr_pages, &eq->ist);
++ h_ret = hipz_h_alloc_resource_eq(shca->ipz_hca_handle,
++ &eq->pf,
++ type,
++ length,
++ &eq->ipz_eq_handle,
++ &eq->length,
++ &nr_pages, &eq->ist);
+
+- if (ret != H_SUCCESS) {
++ if (h_ret != H_SUCCESS) {
+ ehca_err(ib_dev, "Can't allocate EQ/NEQ. eq=%p", eq);
+ return -EINVAL;
+ }
+@@ -97,24 +98,22 @@ int ehca_create_eq(struct ehca_shca *shca,
+ u64 rpage;
-@@ -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);
+ vpage = ipz_qpageit_get_inc(&eq->ipz_queue);
+- if (!vpage) {
+- ret = H_RESOURCE;
++ if (!vpage)
+ goto create_eq_exit2;
+- }
+
+ rpage = virt_to_abs(vpage);
+- ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle,
+- eq->ipz_eq_handle,
+- &eq->pf,
+- 0, 0, rpage, 1);
++ h_ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle,
++ eq->ipz_eq_handle,
++ &eq->pf,
++ 0, 0, rpage, 1);
+
+ if (i == (nr_pages - 1)) {
+ /* last page */
+ vpage = ipz_qpageit_get_inc(&eq->ipz_queue);
+- if (ret != H_SUCCESS || vpage)
++ if (h_ret != H_SUCCESS || vpage)
+ goto create_eq_exit2;
+ } else {
+- if (ret != H_PAGE_REGISTERED || !vpage)
++ if (h_ret != H_PAGE_REGISTERED || !vpage)
+ goto create_eq_exit2;
+ }
+ }
+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);
++}
+
-+ if (max_loop > 1UL << (MINORBITS - part_shift))
- return -EINVAL;
+ 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 (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 (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;
}
- if (register_blkdev(LOOP_MAJOR, "loop"))
-@@ -1549,7 +1565,7 @@ static void __exit loop_exit(void)
- unsigned long range;
- struct loop_device *lo, *next;
+- 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);
-- range = max_loop ? max_loop : 1UL << MINORBITS;
-+ range = max_loop ? max_loop : 1UL << (MINORBITS - part_shift);
+ /* translate device capabilities */
+ props->device_cap_flags = IB_DEVICE_SYS_IMAGE_GUID |
+@@ -128,6 +136,46 @@ query_device1:
+ return ret;
+ }
- 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
++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,
- /* 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
+ memset(props, 0, sizeof(struct ib_port_attr));
-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)
- };
+- 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);
- 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 @@
+ if (rblock->state && rblock->phys_width) {
+ props->phys_state = rblock->phys_pstate;
+@@ -314,7 +345,7 @@ query_gid1:
+ return ret;
+ }
- #include <xen/interface/grant_table.h>
- #include <xen/interface/io/blkif.h>
-+#include <xen/interface/io/protocols.h>
+-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_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
+index b5ca94c..ca5eb0c 100644
+--- a/drivers/infiniband/hw/ehca/ehca_irq.c
++++ b/drivers/infiniband/hw/ehca/ehca_irq.c
+@@ -633,7 +633,7 @@ static inline int find_next_online_cpu(struct ehca_comp_pool *pool)
+ unsigned long flags;
- #include <asm/xen/hypervisor.h>
+ WARN_ON_ONCE(!in_interrupt());
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 3)
+ ehca_dmp(&cpu_online_map, sizeof(cpumask_t), "");
-@@ -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;
+ spin_lock_irqsave(&pool->last_cpu_lock, flags);
+diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
+index a86ebcc..482103e 100644
+--- a/drivers/infiniband/hw/ehca/ehca_main.c
++++ b/drivers/infiniband/hw/ehca/ehca_main.c
+@@ -50,65 +50,70 @@
+ #include "ehca_tools.h"
+ #include "hcp_if.h"
- /**
- * 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;
+-#define HCAD_VERSION "0025"
++#define HCAD_VERSION "0026"
+
+ MODULE_LICENSE("Dual BSD/GPL");
+ MODULE_AUTHOR("Christoph Raisch <raisch at de.ibm.com>");
+ MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
+ MODULE_VERSION(HCAD_VERSION);
+
+-int ehca_open_aqp1 = 0;
++static int ehca_open_aqp1 = 0;
++static int ehca_hw_level = 0;
++static int ehca_poll_all_eqs = 1;
++
+ 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);
+-module_param_named(debug_level, ehca_debug_level, int, S_IRUGO);
+-module_param_named(hw_level, ehca_hw_level, int, S_IRUGO);
+-module_param_named(nr_ports, ehca_nr_ports, int, S_IRUGO);
+-module_param_named(use_hp_mr, ehca_use_hp_mr, int, S_IRUGO);
+-module_param_named(port_act_time, ehca_port_act_time, int, S_IRUGO);
+-module_param_named(poll_all_eqs, ehca_poll_all_eqs, int, S_IRUGO);
+-module_param_named(static_rate, ehca_static_rate, int, S_IRUGO);
+-module_param_named(scaling_code, ehca_scaling_code, int, S_IRUGO);
+-module_param_named(mr_largepage, ehca_mr_largepage, int, S_IRUGO);
++int ehca_max_cq = -1;
++int ehca_max_qp = -1;
++
++module_param_named(open_aqp1, ehca_open_aqp1, bool, S_IRUGO);
++module_param_named(debug_level, ehca_debug_level, int, S_IRUGO);
++module_param_named(hw_level, ehca_hw_level, int, S_IRUGO);
++module_param_named(nr_ports, ehca_nr_ports, int, S_IRUGO);
++module_param_named(use_hp_mr, ehca_use_hp_mr, bool, S_IRUGO);
++module_param_named(port_act_time, ehca_port_act_time, int, S_IRUGO);
++module_param_named(poll_all_eqs, ehca_poll_all_eqs, bool, S_IRUGO);
++module_param_named(static_rate, ehca_static_rate, int, S_IRUGO);
++module_param_named(scaling_code, ehca_scaling_code, bool, S_IRUGO);
+ module_param_named(lock_hcalls, ehca_lock_hcalls, bool, S_IRUGO);
++module_param_named(number_of_cqs, ehca_max_cq, int, S_IRUGO);
++module_param_named(number_of_qps, ehca_max_qp, int, S_IRUGO);
+
+ MODULE_PARM_DESC(open_aqp1,
+- "AQP1 on startup (0: no (default), 1: yes)");
++ "Open AQP1 on startup (default: no)");
+ MODULE_PARM_DESC(debug_level,
+- "debug level"
+- " (0: no debug traces (default), 1: with debug traces)");
++ "Amount of debug output (0: none (default), 1: traces, "
++ "2: some dumps, 3: lots)");
+ MODULE_PARM_DESC(hw_level,
+- "hardware level"
+- " (0: autosensing (default), 1: v. 0.20, 2: v. 0.21)");
++ "Hardware level (0: autosensing (default), "
++ "0x10..0x14: eHCA, 0x20..0x23: eHCA2)");
+ MODULE_PARM_DESC(nr_ports,
+ "number of connected ports (-1: autodetect, 1: port one only, "
+ "2: two ports (default)");
+ MODULE_PARM_DESC(use_hp_mr,
+- "high performance MRs (0: no (default), 1: yes)");
++ "Use high performance MRs (default: no)");
+ MODULE_PARM_DESC(port_act_time,
+- "time to wait for port activation (default: 30 sec)");
++ "Time to wait for port activation (default: 30 sec)");
+ MODULE_PARM_DESC(poll_all_eqs,
+- "polls all event queues periodically"
+- " (0: no, 1: yes (default))");
++ "Poll all event queues periodically (default: yes)");
+ MODULE_PARM_DESC(static_rate,
+- "set permanent static rate (default: disabled)");
++ "Set permanent static rate (default: no static rate)");
+ MODULE_PARM_DESC(scaling_code,
+- "set scaling code (0: disabled/default, 1: enabled)");
+-MODULE_PARM_DESC(mr_largepage,
+- "use large page for MR (0: use PAGE_SIZE (default), "
+- "1: use large page depending on MR size");
++ "Enable scaling code (default: no)");
+ MODULE_PARM_DESC(lock_hcalls,
+- "serialize all hCalls made by the driver "
++ "Serialize all hCalls made by the driver "
+ "(default: autodetect)");
++MODULE_PARM_DESC(number_of_cqs,
++ "Max number of CQs which can be allocated "
++ "(default: autodetect)");
++MODULE_PARM_DESC(number_of_qps,
++ "Max number of QPs which can be allocated "
++ "(default: autodetect)");
+
+ DEFINE_RWLOCK(ehca_qp_idr_lock);
+ DEFINE_RWLOCK(ehca_cq_idr_lock);
+@@ -274,6 +279,7 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
+ u64 h_ret;
+ struct hipz_query_hca *rblock;
+ struct hipz_query_port *port;
++ const char *loc_code;
+
+ static const u32 pgsize_map[] = {
+ HCA_CAP_MR_PGSIZE_4K, 0x1000,
+@@ -282,6 +288,12 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
+ HCA_CAP_MR_PGSIZE_16M, 0x1000000,
+ };
+
++ ehca_gen_dbg("Probing adapter %s...",
++ shca->ofdev->node->full_name);
++ loc_code = of_get_property(shca->ofdev->node, "ibm,loc-code", NULL);
++ if (loc_code)
++ ehca_gen_dbg(" ... location lode=%s", loc_code);
++
+ rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+ if (!rblock) {
+ ehca_gen_err("Cannot allocate rblock memory.");
+@@ -349,10 +361,27 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
+
+ /* translate supported MR page sizes; always support 4K */
+ shca->hca_cap_mr_pgsize = EHCA_PAGESIZE;
+- if (ehca_mr_largepage) { /* support extra sizes only if enabled */
+- for (i = 0; i < ARRAY_SIZE(pgsize_map); i += 2)
+- if (rblock->memory_page_size_supported & pgsize_map[i])
+- shca->hca_cap_mr_pgsize |= pgsize_map[i + 1];
++ for (i = 0; i < ARRAY_SIZE(pgsize_map); i += 2)
++ if (rblock->memory_page_size_supported & pgsize_map[i])
++ shca->hca_cap_mr_pgsize |= pgsize_map[i + 1];
++
++ /* Set maximum number of CQs and QPs to calculate EQ size */
++ if (ehca_max_qp == -1)
++ ehca_max_qp = min_t(int, rblock->max_qp, EHCA_MAX_NUM_QUEUES);
++ else if (ehca_max_qp < 1 || ehca_max_qp > rblock->max_qp) {
++ ehca_gen_err("Requested number of QPs is out of range (1 - %i) "
++ "specified by HW", rblock->max_qp);
++ ret = -EINVAL;
++ goto sense_attributes1;
+ }
++
++ if (ehca_max_cq == -1)
++ ehca_max_cq = min_t(int, rblock->max_cq, EHCA_MAX_NUM_QUEUES);
++ else if (ehca_max_cq < 1 || ehca_max_cq > rblock->max_cq) {
++ ehca_gen_err("Requested number of CQs is out of range (1 - %i) "
++ "specified by HW", rblock->max_cq);
++ ret = -EINVAL;
++ goto sense_attributes1;
+ }
- 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);
+ /* query max MTU from first port -- it's the same for all ports */
+@@ -396,7 +425,7 @@ init_node_guid1:
+ return ret;
+ }
- add_disk(info->gd);
-+
-+ info->is_ready = 1;
+-int ehca_init_device(struct ehca_shca *shca)
++static int ehca_init_device(struct ehca_shca *shca)
+ {
+ int ret;
+
+@@ -566,8 +595,7 @@ static int ehca_destroy_aqp1(struct ehca_sport *sport)
+
+ static ssize_t ehca_show_debug_level(struct device_driver *ddp, char *buf)
+ {
+- return snprintf(buf, PAGE_SIZE, "%d\n",
+- ehca_debug_level);
++ return snprintf(buf, PAGE_SIZE, "%d\n", ehca_debug_level);
}
- /**
-@@ -896,7 +905,7 @@ static void backend_changed(struct xenbus_device *dev,
- break;
+ static ssize_t ehca_store_debug_level(struct device_driver *ddp,
+@@ -579,8 +607,8 @@ static ssize_t ehca_store_debug_level(struct device_driver *ddp,
+ return 1;
+ }
- case XenbusStateClosing:
-- bd = bdget(info->dev);
-+ bd = bdget_disk(info->gd, 0);
- if (bd == NULL)
- xenbus_dev_fatal(dev, -ENODEV, "bdget failed");
+-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);
-@@ -925,6 +934,13 @@ static int blkfront_remove(struct xenbus_device *dev)
- return 0;
+ static struct attribute *ehca_drv_attrs[] = {
+ &driver_attr_debug_level.attr,
+@@ -656,14 +684,6 @@ static ssize_t ehca_show_adapter_handle(struct device *dev,
}
+ static DEVICE_ATTR(adapter_handle, S_IRUGO, ehca_show_adapter_handle, NULL);
-+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 ssize_t ehca_show_mr_largepage(struct device *dev,
+- struct device_attribute *attr,
+- char *buf)
+-{
+- return sprintf(buf, "%d\n", ehca_mr_largepage);
+-}
+-static DEVICE_ATTR(mr_largepage, S_IRUGO, ehca_show_mr_largepage, NULL);
+-
+ static struct attribute *ehca_dev_attrs[] = {
+ &dev_attr_adapter_handle.attr,
+ &dev_attr_num_ports.attr,
+@@ -680,7 +700,6 @@ static struct attribute *ehca_dev_attrs[] = {
+ &dev_attr_cur_mw.attr,
+ &dev_attr_max_pd.attr,
+ &dev_attr_max_ah.attr,
+- &dev_attr_mr_largepage.attr,
+ NULL
};
- 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;
+@@ -694,7 +713,7 @@ static int __devinit ehca_probe(struct of_device *dev,
+ struct ehca_shca *shca;
+ const u64 *handle;
+ struct ib_pd *ibpd;
+- int ret, i;
++ int ret, i, eq_size;
- #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);
+ handle = of_get_property(dev->node, "ibm,hca-handle", NULL);
+ if (!handle) {
+@@ -715,6 +734,8 @@ static int __devinit ehca_probe(struct of_device *dev,
+ return -ENOMEM;
}
- 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);
- }
+ mutex_init(&shca->modify_mutex);
++ atomic_set(&shca->num_cqs, 0);
++ atomic_set(&shca->num_qps, 0);
+ for (i = 0; i < ARRAY_SIZE(shca->sport); i++)
+ spin_lock_init(&shca->sport[i].mod_sqp_lock);
+
+@@ -734,8 +755,9 @@ static int __devinit ehca_probe(struct of_device *dev,
+ goto probe1;
}
+
++ eq_size = 2 * ehca_max_cq + 4 * ehca_max_qp;
+ /* create event queues */
+- ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, 2048);
++ ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, eq_size);
+ if (ret) {
+ ehca_err(&shca->ib_device, "Cannot create EQ.");
+ goto probe1;
+@@ -941,7 +963,7 @@ void ehca_poll_eqs(unsigned long data)
+ spin_unlock(&shca_list_lock);
}
-@@ -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;
+-int __init ehca_module_init(void)
++static int __init ehca_module_init(void)
+ {
+ int ret;
+
+@@ -988,7 +1010,7 @@ module_init1:
+ return ret;
};
--static inline void _urb_free(struct _urb *_urb)
--{
-- kfree(_urb);
--}
--
- static inline void _urb_queue_init(struct _urb_queue *q)
+-void __exit ehca_module_exit(void)
++static void __exit ehca_module_exit(void)
{
- 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);
+ 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..f974367 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.
+ */
- static int cdrom_get_disc_info(struct cdrom_device_info *cdi, disc_information *di);
+-#include <asm/current.h>
+-
+ #include <rdma/ib_umem.h>
--#ifdef CONFIG_SYSCTL
- static void cdrom_sysctl_register(void);
--#endif /* CONFIG_SYSCTL */
--static struct cdrom_device_info *topCdromPtr;
-+
-+static LIST_HEAD(cdrom_list);
+ #include "ehca_iverbs.h"
+@@ -325,7 +323,7 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+ }
- 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");
+ e_mr->umem = ib_umem_get(pd->uobject->context, start, length,
+- mr_access_flags);
++ mr_access_flags, 0);
+ if (IS_ERR(e_mr->umem)) {
+ ib_mr = (void *)e_mr->umem;
+ goto reg_user_mr_exit1;
+@@ -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 (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 */
- }
+ 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;
- ENSURE(drive_status, CDC_DRIVE_STATUS );
-@@ -439,35 +436,18 @@ int register_cdrom(struct cdrom_device_info *cdi)
+- 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;
+- }
- 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;
+ if ((e_mr->flags & EHCA_MR_FLAG_FMR)) {
+ ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p "
+@@ -1826,8 +1794,9 @@ static int ehca_check_kpages_per_ate(struct scatterlist *page_list,
+ int t;
+ for (t = start_idx; t <= end_idx; t++) {
+ u64 pgaddr = page_to_pfn(sg_page(&page_list[t])) << PAGE_SHIFT;
+- ehca_gen_dbg("chunk_page=%lx value=%016lx", pgaddr,
+- *(u64 *)abs_to_virt(phys_to_abs(pgaddr)));
++ if (ehca_debug_level >= 3)
++ ehca_gen_dbg("chunk_page=%lx value=%016lx", pgaddr,
++ *(u64 *)abs_to_virt(phys_to_abs(pgaddr)));
+ if (pgaddr - PAGE_SIZE != *prev_pgaddr) {
+ ehca_gen_err("uncontiguous page found pgaddr=%lx "
+ "prev_pgaddr=%lx page_list_i=%x",
+@@ -1894,10 +1863,13 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
+ pgaddr &
+ ~(pginfo->hwpage_size - 1));
+ }
+- ehca_gen_dbg("kpage=%lx chunk_page=%lx "
+- "value=%016lx", *kpage, pgaddr,
+- *(u64 *)abs_to_virt(
+- phys_to_abs(pgaddr)));
++ if (ehca_debug_level >= 3) {
++ u64 val = *(u64 *)abs_to_virt(
++ phys_to_abs(pgaddr));
++ ehca_gen_dbg("kpage=%lx chunk_page=%lx "
++ "value=%016lx",
++ *kpage, pgaddr, val);
++ }
+ prev_pgaddr = pgaddr;
+ i++;
+ pginfo->kpage_cnt++;
+@@ -1952,9 +1924,8 @@ next_kpage:
+ return ret;
}
- #undef ENSURE
--int unregister_cdrom(struct cdrom_device_info *unreg)
-+void unregister_cdrom(struct cdrom_device_info *cdi)
+-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)
{
-- struct cdrom_device_info *cdi, *prev;
- cdinfo(CD_OPEN, "entering unregister_cdrom\n");
+ int ret = 0;
+ struct ib_phys_buf *pbuf;
+@@ -2012,9 +1983,8 @@ int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
+ return ret;
+ }
-- 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;
+-int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
+- u32 number,
+- u64 *kpage)
++static int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
++ u32 number, u64 *kpage)
+ {
+ int ret = 0;
+ u64 *fmrlist;
+diff --git a/drivers/infiniband/hw/ehca/ehca_pd.c b/drivers/infiniband/hw/ehca/ehca_pd.c
+index 43bcf08..2fe5548 100644
+--- a/drivers/infiniband/hw/ehca/ehca_pd.c
++++ b/drivers/infiniband/hw/ehca/ehca_pd.c
+@@ -38,8 +38,6 @@
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+-#include <asm/current.h>
-
-+ list_del(&cdi->list);
- mutex_unlock(&cdrom_mutex);
+ #include "ehca_tools.h"
+ #include "ehca_iverbs.h"
- if (cdi->exit)
-@@ -475,34 +455,43 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
+@@ -58,7 +56,6 @@ struct ib_pd *ehca_alloc_pd(struct ib_device *device,
+ return ERR_PTR(-ENOMEM);
+ }
- cdi->ops->n_minors--;
- cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
-- return 0;
- }
+- 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 cdrom_get_media_event(struct cdrom_device_info *cdi,
- struct media_event_desc *med)
+ int ehca_dealloc_pd(struct ib_pd *pd)
{
- 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;
+- 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;
-- init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
-+ buffer = kmalloc(8, GFP_KERNEL);
-+ if (!buffer)
-+ return -ENOMEM;
+- 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..18fba92 100644
+--- a/drivers/infiniband/hw/ehca/ehca_qp.c
++++ b/drivers/infiniband/hw/ehca/ehca_qp.c
+@@ -43,9 +43,6 @@
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+-
+-#include <asm/current.h>
+-
+ #include "ehca_classes.h"
+ #include "ehca_tools.h"
+ #include "ehca_qes.h"
+@@ -424,6 +421,19 @@ static struct ehca_qp *internal_create_qp(
+ u32 swqe_size = 0, rwqe_size = 0, ib_qp_num;
+ unsigned long flags;
+
++ if (!atomic_add_unless(&shca->num_qps, 1, ehca_max_qp)) {
++ ehca_err(pd->device, "Unable to create QP, max number of %i "
++ "QPs reached.", ehca_max_qp);
++ ehca_err(pd->device, "To increase the maximum number of QPs "
++ "use the number_of_qps module parameter.\n");
++ return ERR_PTR(-ENOSPC);
++ }
+
-+ eh = (struct event_header *)buffer;
++ if (init_attr->create_flags) {
++ atomic_dec(&shca->num_qps);
++ return ERR_PTR(-EINVAL);
++ }
+
-+ 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;
+ memset(&parms, 0, sizeof(parms));
+ qp_type = init_attr->qp_type;
- if (cdi->ops->generic_packet(cdi, &cgc))
-- return 1;
-+ goto err;
+@@ -431,6 +441,7 @@ static struct ehca_qp *internal_create_qp(
+ init_attr->sq_sig_type != IB_SIGNAL_ALL_WR) {
+ ehca_err(pd->device, "init_attr->sg_sig_type=%x not allowed",
+ init_attr->sq_sig_type);
++ atomic_dec(&shca->num_qps);
+ return ERR_PTR(-EINVAL);
+ }
- if (be16_to_cpu(eh->data_len) < sizeof(*med))
-- return 1;
-+ goto err;
+@@ -455,6 +466,7 @@ static struct ehca_qp *internal_create_qp(
- if (eh->nea || eh->notification_class != 0x4)
-- return 1;
-+ goto err;
+ if (is_llqp && has_srq) {
+ ehca_err(pd->device, "LLQPs can't have an SRQ");
++ atomic_dec(&shca->num_qps);
+ return ERR_PTR(-EINVAL);
+ }
-- memcpy(med, &buffer[sizeof(*eh)], sizeof(*med));
-- return 0;
-+ memcpy(med, buffer + sizeof(*eh), sizeof(*med));
-+ ret = 0;
-+err:
-+ kfree(buffer);
-+ return ret;
+@@ -466,6 +478,7 @@ static struct ehca_qp *internal_create_qp(
+ ehca_err(pd->device, "no more than three SGEs "
+ "supported for SRQ pd=%p max_sge=%x",
+ pd, init_attr->cap.max_recv_sge);
++ atomic_dec(&shca->num_qps);
+ return ERR_PTR(-EINVAL);
+ }
+ }
+@@ -477,6 +490,7 @@ static struct ehca_qp *internal_create_qp(
+ qp_type != IB_QPT_SMI &&
+ qp_type != IB_QPT_GSI) {
+ ehca_err(pd->device, "wrong QP Type=%x", qp_type);
++ atomic_dec(&shca->num_qps);
+ return ERR_PTR(-EINVAL);
+ }
+
+@@ -490,6 +504,7 @@ static struct ehca_qp *internal_create_qp(
+ "or max_rq_wr=%x for RC LLQP",
+ init_attr->cap.max_send_wr,
+ init_attr->cap.max_recv_wr);
++ atomic_dec(&shca->num_qps);
+ return ERR_PTR(-EINVAL);
+ }
+ break;
+@@ -497,6 +512,7 @@ static struct ehca_qp *internal_create_qp(
+ if (!EHCA_BMASK_GET(HCA_CAP_UD_LL_QP, shca->hca_cap)) {
+ ehca_err(pd->device, "UD LLQP not supported "
+ "by this adapter");
++ atomic_dec(&shca->num_qps);
+ return ERR_PTR(-ENOSYS);
+ }
+ if (!(init_attr->cap.max_send_sge <= 5
+@@ -508,20 +524,22 @@ static struct ehca_qp *internal_create_qp(
+ "or max_recv_sge=%x for UD LLQP",
+ init_attr->cap.max_send_sge,
+ init_attr->cap.max_recv_sge);
++ atomic_dec(&shca->num_qps);
+ return ERR_PTR(-EINVAL);
+ } else if (init_attr->cap.max_send_wr > 255) {
+ ehca_err(pd->device,
+ "Invalid Number of "
+ "max_send_wr=%x for UD QP_TYPE=%x",
+ init_attr->cap.max_send_wr, qp_type);
++ atomic_dec(&shca->num_qps);
+ return ERR_PTR(-EINVAL);
+ }
+ break;
+ default:
+ ehca_err(pd->device, "unsupported LL QP Type=%x",
+ qp_type);
++ atomic_dec(&shca->num_qps);
+ return ERR_PTR(-EINVAL);
+- break;
+ }
+ } else {
+ int max_sge = (qp_type == IB_QPT_UD || qp_type == IB_QPT_SMI
+@@ -533,6 +551,7 @@ static struct ehca_qp *internal_create_qp(
+ "send_sge=%x recv_sge=%x max_sge=%x",
+ init_attr->cap.max_send_sge,
+ init_attr->cap.max_recv_sge, max_sge);
++ atomic_dec(&shca->num_qps);
+ return ERR_PTR(-EINVAL);
+ }
+ }
+@@ -543,6 +562,7 @@ static struct ehca_qp *internal_create_qp(
+ my_qp = kmem_cache_zalloc(qp_cache, GFP_KERNEL);
+ if (!my_qp) {
+ ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd);
++ atomic_dec(&shca->num_qps);
+ return ERR_PTR(-ENOMEM);
+ }
+
+@@ -550,6 +570,7 @@ static struct ehca_qp *internal_create_qp(
+ spin_lock_init(&my_qp->spinlock_r);
+ my_qp->qp_type = qp_type;
+ my_qp->ext_type = parms.ext_type;
++ my_qp->state = IB_QPS_RESET;
+
+ if (init_attr->recv_cq)
+ my_qp->recv_cq =
+@@ -822,6 +843,7 @@ create_qp_exit1:
+
+ create_qp_exit0:
+ kmem_cache_free(qp_cache, my_qp);
++ atomic_dec(&shca->num_qps);
+ return ERR_PTR(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)
+@@ -965,7 +987,7 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,
+ qp_num, bad_send_wqe_p);
+ /* convert wqe pointer to vadr */
+ bad_send_wqe_v = abs_to_virt((u64)bad_send_wqe_p);
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 2)
+ ehca_dmp(bad_send_wqe_v, 32, "qp_num=%x bad_wqe", qp_num);
+ squeue = &my_qp->ipz_squeue;
+ if (ipz_queue_abs_to_offset(squeue, (u64)bad_send_wqe_p, &q_ofs)) {
+@@ -978,7 +1000,7 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,
+ wqe = (struct ehca_wqe *)ipz_qeit_calc(squeue, q_ofs);
+ *bad_wqe_cnt = 0;
+ while (wqe->optype != 0xff && wqe->wqef != 0xff) {
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 2)
+ ehca_dmp(wqe, 32, "qp_num=%x wqe", qp_num);
+ wqe->nr_of_data_seg = 0; /* suppress data access */
+ wqe->wqef = WQEF_PURGE; /* WQE to be purged */
+@@ -1450,7 +1472,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
+ /* no support for max_send/recv_sge yet */
+ }
+
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 2)
+ ehca_dmp(mqpcb, 4*70, "qp_num=%x", ibqp->qp_num);
+
+ h_ret = hipz_h_modify_qp(shca->ipz_hca_handle,
+@@ -1508,6 +1530,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
+ if (attr_mask & IB_QP_QKEY)
+ my_qp->qkey = attr->qkey;
+
++ my_qp->state = qp_new_state;
++
+ modify_qp_exit2:
+ if (squeue_locked) { /* this means: sqe -> rts */
+ spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
+@@ -1526,16 +1550,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 +1650,13 @@ int ehca_query_qp(struct ib_qp *qp,
+ int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
{
- struct packet_command cgc;
-- char buffer[16];
-+ char *buffer;
-+ int ret = 1;
+ 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;
-- 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);
+- 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 ",
+@@ -1783,7 +1787,7 @@ int ehca_query_qp(struct ib_qp *qp,
+ if (qp_init_attr)
+ *qp_init_attr = my_qp->init_attr;
+
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 2)
+ ehca_dmp(qpcb, 4*70, "qp_num=%x", qp->qp_num);
- cgc.timeout = HZ;
- cgc.quiet = 1;
+ query_qp_exit1:
+@@ -1797,8 +1801,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 +1808,6 @@ int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ u64 h_ret;
+ int ret = 0;
- 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;
- }
+- 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;
+- }
-
-- return 1;
-+ kfree(buffer);
-+ return ret;
- }
+ mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+ if (!mqpcb) {
+ ehca_err(ibsrq->device, "Could not get zeroed page for mqpcb "
+@@ -1841,7 +1835,7 @@ int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ goto modify_srq_exit0;
+ }
- 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;
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 2)
+ ehca_dmp(mqpcb, 4*70, "qp_num=%x", my_qp->real_qp_num);
- *write = 0;
-+ buffer = kmalloc(16, GFP_KERNEL);
-+ if (!buffer)
-+ return -ENOMEM;
+ h_ret = hipz_h_modify_qp(shca->ipz_hca_handle, my_qp->ipz_qp_handle,
+@@ -1864,22 +1858,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;
-- init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
-+ init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
+- 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 "
+@@ -1903,7 +1888,7 @@ int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr)
+ srq_attr->srq_limit = EHCA_BMASK_GET(
+ MQPCB_CURR_SRQ_LIMIT, qpcb->curr_srq_limit);
+
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 2)
+ ehca_dmp(qpcb, 4*70, "qp_num=%x", my_qp->real_qp_num);
- cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
- cgc.cmd[3] = CDF_MRW;
-- cgc.cmd[8] = sizeof(buffer);
-+ cgc.cmd[8] = 16;
- cgc.quiet = 1;
+ query_srq_exit1:
+@@ -1919,7 +1904,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 +1918,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 ((ret = cdi->ops->generic_packet(cdi, &cgc)))
-- return ret;
-+ goto err;
+ if (my_qp->send_cq) {
+@@ -1990,6 +1969,7 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
+ if (HAS_SQ(my_qp))
+ ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
+ kmem_cache_free(qp_cache, my_qp);
++ atomic_dec(&shca->num_qps);
+ return 0;
+ }
- 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;
+diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
+index 2ce8cff..bbe0436 100644
+--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
++++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
+@@ -81,7 +81,7 @@ static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue,
+ recv_wr->sg_list[cnt_ds].length;
+ }
- if ((ret = cdrom_mrw_probe_pc(cdi))) {
- *write = 0;
-- return ret;
+- if (ehca_debug_level) {
++ if (ehca_debug_level >= 3) {
+ ehca_gen_dbg("RECEIVE WQE written into ipz_rqueue=%p",
+ ipz_rqueue);
+ ehca_dmp(wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "recv wqe");
+@@ -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;
}
--
-- 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;
+@@ -281,7 +281,7 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
+ return -EINVAL;
+ }
- printk(KERN_INFO "cdrom: %sstarting format\n", cont ? "Re" : "");
+- if (ehca_debug_level) {
++ if (ehca_debug_level >= 3) {
+ ehca_gen_dbg("SEND WQE written into queue qp=%p ", qp);
+ ehca_dmp( wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "send wqe");
+ }
+@@ -421,6 +421,11 @@ int ehca_post_send(struct ib_qp *qp,
+ int ret = 0;
+ unsigned long flags;
-+ buffer = kmalloc(12, GFP_KERNEL);
-+ if (!buffer)
-+ return -ENOMEM;
++ if (unlikely(my_qp->state != IB_QPS_RTS)) {
++ ehca_err(qp->device, "QP not in RTS state qpn=%x", qp->qp_num);
++ return -EINVAL;
++ }
+
- /*
- * 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");
+ /* LOCK the QUEUE */
+ spin_lock_irqsave(&my_qp->spinlock_s, flags);
-+ kfree(buffer);
+@@ -454,13 +459,14 @@ int ehca_post_send(struct ib_qp *qp,
+ goto post_send_exit0;
+ }
+ wqe_cnt++;
+- ehca_dbg(qp->device, "ehca_qp=%p qp_num=%x wqe_cnt=%d",
+- my_qp, qp->qp_num, wqe_cnt);
+ } /* eof for cur_send_wr */
+
+ post_send_exit0:
+ iosync(); /* serialize GAL register access */
+ hipz_update_sqa(my_qp, wqe_cnt);
++ if (unlikely(ret || ehca_debug_level >= 2))
++ ehca_dbg(qp->device, "ehca_qp=%p qp_num=%x wqe_cnt=%d ret=%i",
++ my_qp, qp->qp_num, wqe_cnt, ret);
+ my_qp->message_count += wqe_cnt;
+ spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
+ return ret;
+@@ -520,13 +526,14 @@ static int internal_post_recv(struct ehca_qp *my_qp,
+ goto post_recv_exit0;
+ }
+ wqe_cnt++;
+- ehca_dbg(dev, "ehca_qp=%p qp_num=%x wqe_cnt=%d",
+- my_qp, my_qp->real_qp_num, wqe_cnt);
+ } /* eof for cur_recv_wr */
+
+ post_recv_exit0:
+ iosync(); /* serialize GAL register access */
+ hipz_update_rqa(my_qp, wqe_cnt);
++ if (unlikely(ret || ehca_debug_level >= 2))
++ ehca_dbg(dev, "ehca_qp=%p qp_num=%x wqe_cnt=%d ret=%i",
++ my_qp, my_qp->real_qp_num, wqe_cnt, ret);
+ spin_unlock_irqrestore(&my_qp->spinlock_r, flags);
return ret;
}
+@@ -570,16 +577,17 @@ static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc)
+ struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
+ struct ehca_cqe *cqe;
+ struct ehca_qp *my_qp;
+- int cqe_count = 0;
++ int cqe_count = 0, is_error;
+
+ poll_cq_one_read_cqe:
+ cqe = (struct ehca_cqe *)
+ ipz_qeit_get_inc_valid(&my_cq->ipz_queue);
+ if (!cqe) {
+ ret = -EAGAIN;
+- ehca_dbg(cq->device, "Completion queue is empty ehca_cq=%p "
+- "cq_num=%x ret=%i", my_cq, my_cq->cq_number, ret);
+- goto poll_cq_one_exit0;
++ if (ehca_debug_level >= 3)
++ ehca_dbg(cq->device, "Completion queue is empty "
++ "my_cq=%p cq_num=%x", my_cq, my_cq->cq_number);
++ goto poll_cq_one_exit0;
+ }
+
+ /* prevents loads being reordered across this point */
+@@ -609,7 +617,7 @@ poll_cq_one_read_cqe:
+ ehca_dbg(cq->device,
+ "Got CQE with purged bit qp_num=%x src_qp=%x",
+ cqe->local_qp_number, cqe->remote_qp_number);
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 2)
+ ehca_dmp(cqe, 64, "qp_num=%x src_qp=%x",
+ cqe->local_qp_number,
+ cqe->remote_qp_number);
+@@ -622,11 +630,13 @@ poll_cq_one_read_cqe:
+ }
+ }
+
+- /* tracing cqe */
+- if (unlikely(ehca_debug_level)) {
++ is_error = cqe->status & WC_STATUS_ERROR_BIT;
++
++ /* trace error CQEs if debug_level >= 1, trace all CQEs if >= 3 */
++ if (unlikely(ehca_debug_level >= 3 || (ehca_debug_level && is_error))) {
+ ehca_dbg(cq->device,
+- "Received COMPLETION ehca_cq=%p cq_num=%x -----",
+- my_cq, my_cq->cq_number);
++ "Received %sCOMPLETION ehca_cq=%p cq_num=%x -----",
++ is_error ? "ERROR " : "", my_cq, my_cq->cq_number);
+ ehca_dmp(cqe, 64, "ehca_cq=%p cq_num=%x",
+ my_cq, my_cq->cq_number);
+ ehca_dbg(cq->device,
+@@ -649,8 +659,9 @@ poll_cq_one_read_cqe:
+ /* update also queue adder to throw away this entry!!! */
+ goto poll_cq_one_exit0;
+ }
++
+ /* eval ib_wc_status */
+- if (unlikely(cqe->status & WC_STATUS_ERROR_BIT)) {
++ if (unlikely(is_error)) {
+ /* complete with errors */
+ map_ib_wc_status(cqe->status, &wc->status);
+ wc->vendor_err = wc->status;
+@@ -671,14 +682,6 @@ poll_cq_one_read_cqe:
+ wc->imm_data = cpu_to_be32(cqe->immediate_data);
+ wc->sl = cqe->service_level;
+
+- if (unlikely(wc->status != IB_WC_SUCCESS))
+- ehca_dbg(cq->device,
+- "ehca_cq=%p cq_num=%x WARNING unsuccessful cqe "
+- "OPType=%x status=%x qp_num=%x src_qp=%x wr_id=%lx "
+- "cqe=%p", my_cq, my_cq->cq_number, cqe->optype,
+- cqe->status, cqe->local_qp_number,
+- cqe->remote_qp_number, cqe->work_request_id, cqe);
+-
+ poll_cq_one_exit0:
+ if (cqe_count > 0)
+ hipz_update_feca(my_cq, cqe_count);
+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)
-@@ -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;
+ #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)
-- init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
-+ buffer = kmalloc(16, GFP_KERNEL);
-+ if (!buffer)
-+ return -ENOMEM;
+ #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)
-- cgc.buffer = buffer;
-- cgc.buflen = sizeof(buffer);
-+ init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
+ #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)
- if ((ret = cdrom_mode_sense(cdi, &cgc, cdi->mrw_mode_page, 0)))
-- return ret;
-+ goto err;
+ /* 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)
- 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;
+ #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)
- if ((ret = cdrom_mode_select(cdi, &cgc)))
-- return ret;
-+ goto err;
+ #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)
- 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;
- }
+ /**
+ * 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..e43ed8f 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.
+ */
- 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;
+-#include <asm/current.h>
+-
+ #include "ehca_classes.h"
+ #include "ehca_iverbs.h"
+ #include "ehca_mrmw.h"
+@@ -213,8 +211,7 @@ static int ehca_mmap_qp(struct vm_area_struct *vma, struct ehca_qp *qp,
+ break;
-- 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);
+ case 1: /* qp rqueue_addr */
+- ehca_dbg(qp->ib_qp.device, "qp_num=%x rqueue",
+- qp->ib_qp.qp_num);
++ ehca_dbg(qp->ib_qp.device, "qp_num=%x rq", qp->ib_qp.qp_num);
+ ret = ehca_mmap_queue(vma, &qp->ipz_rqueue,
+ &qp->mm_count_rqueue);
+ if (unlikely(ret)) {
+@@ -226,8 +223,7 @@ static int ehca_mmap_qp(struct vm_area_struct *vma, struct ehca_qp *qp,
+ break;
- 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;
+ case 2: /* qp squeue_addr */
+- ehca_dbg(qp->ib_qp.device, "qp_num=%x squeue",
+- qp->ib_qp.qp_num);
++ ehca_dbg(qp->ib_qp.device, "qp_num=%x sq", qp->ib_qp.qp_num);
+ ret = ehca_mmap_queue(vma, &qp->ipz_squeue,
+ &qp->mm_count_squeue);
+ if (unlikely(ret)) {
+@@ -253,11 +249,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;
- if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
-- return ret;
-+ goto err;
+ switch (q_type) {
+@@ -270,13 +264,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+ if (!cq)
+ return -EINVAL;
- memcpy(rfd, &buffer[sizeof(struct feature_header)], sizeof (*rfd));
-- return 0;
-+ ret = 0;
-+err:
-+ kfree(buffer);
-+ return ret;
- }
+- 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;
- 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;
+@@ -298,14 +285,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+ if (!qp)
+ return -EINVAL;
-- 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);
+- 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/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
+index 7029aa6..5245e13 100644
+--- a/drivers/infiniband/hw/ehca/hcp_if.c
++++ b/drivers/infiniband/hw/ehca/hcp_if.c
+@@ -123,8 +123,9 @@ static long ehca_plpar_hcall_norets(unsigned long opcode,
+ int i, sleep_msecs;
+ unsigned long flags = 0;
- cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
- cgc.cmd[3] = CDF_HWDM;
-- cgc.cmd[8] = sizeof(buffer);
-+ cgc.cmd[8] = 16;
- cgc.quiet = 1;
+- ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
+- opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
++ if (unlikely(ehca_debug_level >= 2))
++ ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
++ opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
- if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
-- return ret;
-+ goto err;
+ for (i = 0; i < 5; i++) {
+ /* serialize hCalls to work around firmware issue */
+@@ -148,7 +149,8 @@ static long ehca_plpar_hcall_norets(unsigned long opcode,
+ opcode, ret, arg1, arg2, arg3,
+ arg4, arg5, arg6, arg7);
+ else
+- ehca_gen_dbg("opcode=%lx ret=%li", opcode, ret);
++ if (unlikely(ehca_debug_level >= 2))
++ ehca_gen_dbg("opcode=%lx ret=%li", opcode, ret);
- 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;
- }
+ return ret;
+ }
+@@ -172,8 +174,10 @@ static long ehca_plpar_hcall9(unsigned long opcode,
+ int i, sleep_msecs;
+ unsigned long flags = 0;
+- ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,
+- arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
++ if (unlikely(ehca_debug_level >= 2))
++ ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,
++ arg1, arg2, arg3, arg4, arg5,
++ arg6, arg7, arg8, arg9);
-@@ -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;
+ for (i = 0; i < 5; i++) {
+ /* serialize hCalls to work around firmware issue */
+@@ -201,7 +205,7 @@ static long ehca_plpar_hcall9(unsigned long opcode,
+ ret, outs[0], outs[1], outs[2], outs[3],
+ outs[4], outs[5], outs[6], outs[7],
+ outs[8]);
+- } else
++ } else if (unlikely(ehca_debug_level >= 2))
+ ehca_gen_dbg("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,
+ ret, outs[0], outs[1], outs[2], outs[3],
+ outs[4], outs[5], outs[6], outs[7],
+@@ -381,7 +385,7 @@ u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
+ r_cb, /* r6 */
+ 0, 0, 0, 0);
+
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 2)
+ ehca_dmp(query_port_response_block, 64, "response_block");
-- init_cdrom_command(&cgc, &buffer, 4, CGC_DATA_READ);
-+ buffer = kmalloc(255, GFP_KERNEL);
-+ if (!buffer)
-+ return -ENOMEM;
+ return ret;
+@@ -731,9 +735,6 @@ u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
+ u64 ret;
+ u64 outs[PLPAR_HCALL9_BUFSIZE];
+
+- ehca_gen_dbg("kernel PAGE_SIZE=%x access_ctrl=%016x "
+- "vaddr=%lx length=%lx",
+- (u32)PAGE_SIZE, access_ctrl, vaddr, length);
+ ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
+ adapter_handle.handle, /* r4 */
+ 5, /* r5 */
+@@ -758,7 +759,7 @@ u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
+ {
+ u64 ret;
+
+- if (unlikely(ehca_debug_level >= 2)) {
++ if (unlikely(ehca_debug_level >= 3)) {
+ if (count > 1) {
+ u64 *kpage;
+ int i;
+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.
++ */
+
-+ init_cdrom_command(&cgc, buffer, 4, CGC_DATA_READ);
- cgc.quiet = 1;
++/*
++ * 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 */
- /*
-@@ -837,10 +861,15 @@ static int mo_open_write(struct cdrom_device_info *cdi)
- }
+ /*
+ * 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
- /* drive gave us no info, let the user go ahead */
-- if (ret)
-- return 0;
-+ if (ret) {
-+ ret = 0;
-+ goto err;
-+ }
+@@ -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 */
-- return buffer[3] & 0x80;
-+ ret = buffer[3] & 0x80;
-+err:
-+ kfree(buffer);
-+ return ret;
- }
+ /*
+ * 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 {
- 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;
+ /* 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
-- 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);
+@@ -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
- 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;
+ /* 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
- 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];
+ /* 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;
+ }
- cdi->mmc3_profile = mmc3_profile;
-+ kfree(buffer);
+ 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 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;
++static inline __u32 ipath_hdrget_seq(const __le32 *rbuf)
++{
++ return (__le32_to_cpu(rbuf[1]) >> INFINIPATH_RHF_SEQ_SHIFT)
++ & INFINIPATH_RHF_SEQ_MASK;
++}
+
-+ buf = kzalloc(20, GFP_KERNEL);
-+ if (!buf)
-+ return -ENOMEM;
++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 */
-- memset(buf, 0, sizeof(buf));
- init_cdrom_command(&cgc, buf, 0, CGC_DATA_READ);
+ #else /* _IPATH_DEBUGGING */
- 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);
+@@ -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 */
- if ((ret = cdo->generic_packet(cdi, &cgc)))
-- return ret;
-+ goto err;
+ #endif /* _IPATH_DEBUGGING */
- 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);
+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 = {
- if ((ret = cdo->generic_packet(cdi, &cgc)))
-- return ret;
-+ goto err;
+ 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;
- 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);
+ 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 = cdo->generic_packet(cdi, &cgc)))
-- return ret;
-+ goto err;
+ if (ret) {
+ ipath_dev_err(dd, "Couldn't create ipath_diagpkt "
+@@ -102,7 +102,7 @@ int ipath_diag_add(struct ipath_devdata *dd)
- 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;
+ 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);
- if ((ret = cdo->generic_packet(cdi, &cgc)))
-- return ret;
-+ goto err;
+- ipath_cdev_cleanup(&dd->diag_cdev, &dd->diag_class_dev);
++ ipath_cdev_cleanup(&dd->diag_cdev, &dd->diag_dev);
+ }
- 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;
+ /**
+@@ -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 */
- 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 (count != sizeof(dp)) {
++ if (count < sizeof(odp)) {
+ ret = -EINVAL;
+ goto bail;
+ }
- if ((ret = cdo->generic_packet(cdi, &cgc)))
-- return ret;
-+ goto err;
+- 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;
+ }
- ai->type = DVD_LU_SEND_KEY1;
- break;
-@@ -1689,7 +1726,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+- 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 ((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;
+ 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 @@
- /* 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;
+ #include "ipath_kernel.h"
+ #include "ipath_verbs.h"
+-#include "ipath_common.h"
- if ((ret = cdo->generic_packet(cdi, &cgc)))
-- return ret;
-+ goto err;
+ static void ipath_update_pio_bufs(struct ipath_devdata *);
-- 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;
+@@ -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);
- /* 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;
++unsigned ipath_mtu4096 = 1; /* max 4KB IB mtu by default, if supported */
++module_param_named(mtu4096, ipath_mtu4096, uint, S_IRUGO);
++MODULE_PARM_DESC(mtu4096, "enable MTU of 4096 bytes, if supported");
++
++static unsigned ipath_hol_timeout_ms = 13000;
++module_param_named(hol_timeout_ms, ipath_hol_timeout_ms, uint, S_IRUGO);
++MODULE_PARM_DESC(hol_timeout_ms,
++ "duration of user app suspension after link failure");
++
++unsigned ipath_linkrecovery = 1;
++module_param_named(linkrecovery, ipath_linkrecovery, uint, S_IWUSR | S_IRUGO);
++MODULE_PARM_DESC(linkrecovery, "enable workaround for link recovery issue");
++
+ MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("QLogic <support at pathscale.com>");
++MODULE_AUTHOR("QLogic <support at qlogic.com>");
+ MODULE_DESCRIPTION("QLogic InfiniPath driver");
- if ((ret = cdo->generic_packet(cdi, &cgc)))
-- return ret;
-+ goto err;
- break;
++/*
++ * 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"
+ };
- 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 void __devexit ipath_remove_one(struct pci_dev *);
+@@ -102,8 +129,10 @@ static int __devinit ipath_init_one(struct pci_dev *,
- 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;
+ /* 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
-- 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;
+ /* 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, }
+ };
- if ((ret = cdo->generic_packet(cdi, &cgc)))
-- return ret;
-+ goto err;
+@@ -126,19 +156,6 @@ static struct pci_driver ipath_driver = {
+ },
+ };
- 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;
+-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);
-- return 0;
-+ ret = 0;
-+err:
-+ kfree(buf);
-+ return ret;
+- 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;
}
- static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s)
+-int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp)
++int ipath_count_units(int *npresentp, int *nupp, int *maxportsp)
{
- int ret;
-- u_char buf[8];
-+ u_char *buf;
- struct packet_command cgc;
- struct cdrom_device_ops *cdo = cdi->ops;
+ int nunits, npresent, nup;
+ struct ipath_devdata *dd;
+ unsigned long flags;
+- u32 maxports;
++ int maxports;
-- 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;
+ nunits = npresent = nup = maxports = 0;
- if ((ret = cdo->generic_packet(cdi, &cgc)))
-- return ret;
-+ goto err;
+@@ -304,7 +319,7 @@ static void ipath_verify_pioperf(struct ipath_devdata *dd)
+ u32 *addr;
+ u64 msecs, emsecs;
- s->copyright.cpst = buf[4];
- s->copyright.rmi = buf[5];
+- 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)
-- return 0;
-+ ret = 0;
-+err:
-+ kfree(buf);
-+ return ret;
- }
+ ipath_disable_armlaunch(dd);
- 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;
+- 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();
-- 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;
+ /*
+@@ -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;
- if ((ret = cdo->generic_packet(cdi, &cgc)))
-- return ret;
-+ goto err;
+ 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);
- 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;
+@@ -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;
}
- 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;
+- 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;
-+ 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 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);
- if ((ret = cdo->generic_packet(cdi, &cgc)))
-- return ret;
-+ goto err;
+- /*
+- * 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);
- 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];
+- /* Check that card status in STATUS_TIMEOUT seconds. */
+- schedule_delayed_work(&dd->status_work, HZ * STATUS_TIMEOUT);
+-
+ goto bail;
-- return 0;
-+ ret = 0;
-+err:
-+ kfree(buffer);
-+ return ret;
- }
+ bail_irqsetup:
+- if (pdev->irq) free_irq(pdev->irq, dd);
++ if (pdev->irq)
++ free_irq(pdev->irq, dd);
- /*
-@@ -3309,7 +3376,7 @@ static int cdrom_print_info(const char *header, int val, char *info,
+ 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);
+ }
- *pos += ret;
++ 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;
+ }
-- 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;
+ /*
+@@ -738,7 +770,6 @@ static void __devexit ipath_remove_one(struct pci_dev *pdev)
+ */
+ ipath_shutdown_device(dd);
-- 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;
+- 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);
}
-+ mutex_unlock(&cdrom_mutex);
+-
+- /*
+- * 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);
}
- 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);
+ /**
+@@ -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;
}
-+#else /* CONFIG_SYSCTL */
-+
-+static void cdrom_sysctl_register(void)
++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;
+
-+static void cdrom_sysctl_unregister(void)
-+{
++ 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);
++ }
+}
+
- #endif /* CONFIG_SYSCTL */
-
- static int __init cdrom_init(void)
+ /*
+ * 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)
{
--#ifdef CONFIG_SYSCTL
- cdrom_sysctl_register();
--#endif
-+
- return 0;
+ 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;
}
-
- static void __exit cdrom_exit(void)
+@@ -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)
{
- printk(KERN_INFO "Uniform CD-ROM driver unloaded\n");
--#ifdef CONFIG_SYSCTL
- cdrom_sysctl_unregister();
--#endif
- }
+ char emsg[128];
+- struct ipath_message_header *hdr;
- 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;
- }
+ 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);
- 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)
+@@ -1112,55 +1170,52 @@ static void ipath_rcv_hdrerr(struct ipath_devdata *dd,
+ */
+ void ipath_kreceive(struct ipath_portdata *pd)
{
- struct disk_info *d = &viocd_diskinfo[vdev->unit_address];
+- 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;
-- 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
+ 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);
- It's safe to say N here.
+- 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();
++ }
-+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.
+- 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 unsure, say N.
++ 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;
+
- 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
++ /* 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;
+ }
+ }
+ }
- 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 (!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.
*/
- 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;
+-#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;
}
--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 @@
+-/**
+- * ipath_getpiobuf - find an available pio buffer
+- * @dd: the infinipath device
+- * @pbufnum: the buffer number is placed here
+/*
-+ * Blackfin On-Chip OTP Memory Interface
-+ * Supports BF52x/BF54x
-+ *
-+ * Copyright 2007-2008 Analog Devices Inc.
-+ *
-+ * Enter bugs at http://blackfin.uclinux.org/
-+ *
-+ * Licensed under the GPL-2 or later.
-+ */
-+
-+#include <linux/device.h>
-+#include <linux/errno.h>
-+#include <linux/fs.h>
-+#include <linux/init.h>
-+#include <linux/miscdevice.h>
-+#include <linux/module.h>
-+#include <linux/mutex.h>
-+#include <linux/types.h>
-+
-+#include <asm/blackfin.h>
-+#include <asm/uaccess.h>
-+
-+#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
-+#define stampit() stamp("here i am")
-+#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); })
-+
-+#define DRIVER_NAME "bfin-otp"
-+#define PFX DRIVER_NAME ": "
-+
-+static DEFINE_MUTEX(bfin_otp_lock);
-+
-+/* OTP Boot ROM functions */
-+#define _BOOTROM_OTP_COMMAND 0xEF000018
-+#define _BOOTROM_OTP_READ 0xEF00001A
-+#define _BOOTROM_OTP_WRITE 0xEF00001C
-+
-+static u32 (* const otp_command)(u32 command, u32 value) = (void *)_BOOTROM_OTP_COMMAND;
-+static u32 (* const otp_read)(u32 page, u32 flags, u64 *page_content) = (void *)_BOOTROM_OTP_READ;
-+static u32 (* const otp_write)(u32 page, u32 flags, u64 *page_content) = (void *)_BOOTROM_OTP_WRITE;
-+
-+/* otp_command(): defines for "command" */
-+#define OTP_INIT 0x00000001
-+#define OTP_CLOSE 0x00000002
-+
-+/* otp_{read,write}(): defines for "flags" */
-+#define OTP_LOWER_HALF 0x00000000 /* select upper/lower 64-bit half (bit 0) */
-+#define OTP_UPPER_HALF 0x00000001
-+#define OTP_NO_ECC 0x00000010 /* do not use ECC */
-+#define OTP_LOCK 0x00000020 /* sets page protection bit for page */
-+#define OTP_ACCESS_READ 0x00001000
-+#define OTP_ACCESS_READWRITE 0x00002000
-+
-+/* Return values for all functions */
-+#define OTP_SUCCESS 0x00000000
-+#define OTP_MASTER_ERROR 0x001
-+#define OTP_WRITE_ERROR 0x003
-+#define OTP_READ_ERROR 0x005
-+#define OTP_ACC_VIO_ERROR 0x009
-+#define OTP_DATA_MULT_ERROR 0x011
-+#define OTP_ECC_MULT_ERROR 0x021
-+#define OTP_PREV_WR_ERROR 0x041
-+#define OTP_DATA_SB_WARN 0x100
-+#define OTP_ECC_SB_WARN 0x200
-+
-+/**
-+ * bfin_otp_read - Read OTP pages
-+ *
-+ * All reads must be in half page chunks (half page == 64 bits).
++ * debugging code and stats updates if no pio buffers available.
+ */
-+static ssize_t bfin_otp_read(struct file *file, char __user *buff, size_t count, loff_t *pos)
++static noinline void no_pio_bufs(struct ipath_devdata *dd)
+{
-+ ssize_t bytes_done;
-+ u32 page, flags, ret;
-+ u64 content;
-+
-+ stampit();
-+
-+ if (count % sizeof(u64))
-+ return -EMSGSIZE;
++ unsigned long *shadow = dd->ipath_pioavailshadow;
++ __le64 *dma = (__le64 *)dd->ipath_pioavailregs_dma;
+
-+ if (mutex_lock_interruptible(&bfin_otp_lock))
-+ return -ERESTARTSYS;
++ dd->ipath_upd_pio_shadow = 1;
+
-+ 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);
++ /*
++ * 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]);
+ }
++}
+
-+ mutex_unlock(&bfin_otp_lock);
++/*
++ * 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;
+ }
+
-+ return bytes_done;
++ 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;
+}
-+
-+#ifdef CONFIG_BFIN_OTP_WRITE_ENABLE
+
+-bail:
+/**
-+ * bfin_otp_write - Write OTP pages
-+ *
-+ * All writes must be in half page chunks (half page == 64 bits).
++ * 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
+ */
-+static ssize_t bfin_otp_write(struct file *filp, const char __user *buff, size_t count, loff_t *pos)
++u32 __iomem *ipath_getpiobuf(struct ipath_devdata *dd, u32 plen, u32 *pbufnum)
+{
-+ 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
++ u32 __iomem *buf;
++ u32 pnum, nbufs;
++ u32 first, lasti;
+
-+static struct file_operations bfin_otp_fops = {
-+ .owner = THIS_MODULE,
-+ .read = bfin_otp_read,
-+ .write = bfin_otp_write,
-+};
++ 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);
+
-+static struct miscdevice bfin_otp_misc_device = {
-+ .minor = MISC_DYNAMIC_MINOR,
-+ .name = DRIVER_NAME,
-+ .fops = &bfin_otp_fops,
-+};
++ 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;
+
-+/**
-+ * bfin_otp_init - Initialize module
-+ *
-+ * Registers the device and notifier handler. Actual device
-+ * initialization is handled by bfin_otp_open().
++ }
+ 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
+ */
-+static int __init bfin_otp_init(void)
++void ipath_chg_pioavailkernel(struct ipath_devdata *dd, unsigned start,
++ unsigned len, int avail)
+{
-+ int ret;
++ unsigned long flags;
++ unsigned end;
+
-+ stampit();
++ /* There are two bits per send buffer (busy and generation) */
++ start *= 2;
++ len *= 2;
++ end = start + len;
+
-+ ret = misc_register(&bfin_otp_misc_device);
-+ if (ret) {
-+ pr_init(KERN_ERR PFX "unable to register a misc device\n");
-+ return ret;
++ /* 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;
+ }
-+
-+ pr_init(KERN_INFO PFX "initialized\n");
-+
-+ return 0;
++ spin_unlock_irqrestore(&ipath_pioavail_lock, flags);
+}
+
+/**
-+ * 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);
+ * 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;
+
-+MODULE_AUTHOR("Mike Frysinger <vapier at gentoo.org>");
-+MODULE_DESCRIPTION("Blackfin OTP Memory Interface");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
-index 141f4df..b710426 100644
---- a/drivers/char/drm/ati_pcigart.c
-+++ b/drivers/char/drm/ati_pcigart.c
-@@ -167,13 +167,6 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
- page_base += ATI_PCIGART_PAGE_SIZE;
++ if (!(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);
}
- }
--
-- 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;
- };
+- pd->port_rcvhdrqtailaddr_phys = phys_hdrqtail;
-+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)
+ pd->port_rcvhdrq_size = amt;
- #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
+@@ -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);
- /***********************************************************************/
- /** \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);
+- ret = 0;
+ bail:
+ return ret;
+ }
+@@ -1632,52 +1776,149 @@ bail:
+ */
+ void ipath_cancel_sends(struct ipath_devdata *dd, int restore_sendctrl)
+ {
++ unsigned long flags;
+
-+ /**
-+ * 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.
++ 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"
+ */
-+ int (*enable_vblank) (struct drm_device *dev, int crtc);
++ if (dd->ipath_flags & IPATH_HAS_SEND_DMA) {
++ int skip_cancel;
++ u64 *statp = &dd->ipath_sdma_status;
+
-+ /**
-+ * 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
++ 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;
++ }
+
- /**
-- * 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;
+ ipath_dbg("Cancelling all in-progress send buffers\n");
+- dd->ipath_lastcancel = jiffies+HZ/2; /* skip armlaunch errs a bit */
+
-+ 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);
++ /* skip armlaunch errs for a while */
++ dd->ipath_lastcancel = jiffies + HZ / 2;
+
-+ /* 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;
+ /*
+- * 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);
+
- extern struct class *drm_class;
- extern struct proc_dir_entry *drm_proc_root;
-
-+extern struct idr drm_minors_idr;
++ /* 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);
+
- 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);
++ 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);
++ }
- /*
- * 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);
+- /* 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:;
}
- /**
-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");
- }
++/*
++ * 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);
++}
--void drm_exit(struct drm_driver *driver)
-+int drm_minors_cleanup(int id, void *ptr, void *data)
+-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)
{
-- 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;
++ 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 (minor->type != DRM_MINOR_LEGACY)
-+ return 0;
-
-+ if (dev)
-+ pci_dev_put(dev->pdev);
-+ drm_cleanup(dev);
-+ return 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();
++ }
+
-+void drm_exit(struct drm_driver *driver)
-+{
- DRM_DEBUG("\n");
++ 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))]);
-- 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");
+ 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);
}
-@@ -357,13 +358,7 @@ static int __init drm_core_init(void)
- {
- int ret = -ENOMEM;
+ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
+@@ -1687,30 +1928,28 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
-- 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);
+ 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;
- 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)
+ 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;
- unregister_chrdev(DRM_MAJOR, "drm");
+ 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;
-- drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
-+ idr_destroy(&drm_minors_idr);
- }
+ 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;
- 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,
+@@ -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;
- 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);
+ 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;
- 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)
+ 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)
{
- 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;
+@@ -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 (!drm_heads[minor])
-- return -ENODEV;
+ 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);
-
-- if (!(dev = drm_heads[minor]->dev))
-+ if (!(dev = minor->dev))
- return -ENODEV;
+- 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;
+ }
- 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)
+-int ipath_set_lid(struct ipath_devdata *dd, u32 arg, u8 lmc)
++int ipath_set_lid(struct ipath_devdata *dd, u32 lid, u8 lmc)
{
- 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;
+- dd->ipath_lid = arg;
++ dd->ipath_lid = lid;
+ dd->ipath_lmc = lmc;
- DRM_DEBUG("\n");
++ 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;
+ }
-- 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;
+@@ -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);
-- if (!(dev = drm_heads[minor]->dev))
-+ if (!(dev = minor->dev))
- return -ENODEV;
+ 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);
+- }
+ }
- 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;
+ /**
+@@ -1989,6 +2249,8 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
-@@ -234,7 +232,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
- if (!drm_cpu_valid())
- return -EINVAL;
+ ipath_dbg("Shutting down the device\n");
-- 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);
++ 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);
- 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;
++ 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);
- 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;
+- 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);
-@@ -341,14 +338,14 @@ int drm_release(struct inode *inode, struct file *filp)
++ /*
++ * 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);
- 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);
+ /* disable IBC */
+@@ -2038,10 +2309,20 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
+ */
+ dd->ipath_f_quiet_serdes(dd);
- 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;
++ /* 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);
++ }
- 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));
+ /*
+ * 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 (!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;
++ 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;
}
-+static void vblank_disable_fn(unsigned long arg)
++/*
++ * 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)
+{
-+ struct drm_device *dev = (struct drm_device *)arg;
-+ unsigned long irqflags;
-+ int i;
++ int i, sub, any = 0;
++ pid_t pid;
+
-+ 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;
++ 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++;
+ }
-+ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+ }
++ return any;
+}
+
-+static void drm_vblank_cleanup(struct drm_device *dev)
++static void ipath_hol_signal_down(struct ipath_devdata *dd)
+{
-+ /* Bail if the driver didn't call drm_vblank_init() */
-+ if (dev->num_crtcs == 0)
-+ return;
++ if (ipath_signal_procs(dd, SIGSTOP))
++ ipath_dbg("Stopped some processes\n");
++ ipath_cancel_sends(dd, 1);
++}
+
-+ del_timer(&dev->vblank_disable_timer);
+
-+ vblank_disable_fn((unsigned long)dev);
++static void ipath_hol_signal_up(struct ipath_devdata *dd)
++{
++ if (ipath_signal_procs(dd, SIGCONT))
++ ipath_dbg("Continued some processes\n");
++}
+
-+ 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);
++/*
++ * 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);
++}
+
-+ dev->num_crtcs = 0;
++/*
++ * 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;
+}
+
-+int drm_vblank_init(struct drm_device *dev, int num_crtcs)
++/*
++ * 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)
+{
-+ int i, ret = -ENOMEM;
++ struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
+
-+ 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;
++ 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);
++ }
++}
+
-+ dev->vbl_queue = drm_alloc(sizeof(wait_queue_head_t) * num_crtcs,
-+ DRM_MEM_DRIVER);
-+ if (!dev->vbl_queue)
-+ goto err;
+ 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 ) {
+
-+ dev->vbl_sigs = drm_alloc(sizeof(struct list_head) * num_crtcs,
-+ DRM_MEM_DRIVER);
-+ if (!dev->vbl_sigs)
-+ goto err;
++ 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)
+
-+ dev->_vblank_count = drm_alloc(sizeof(atomic_t) * num_crtcs,
-+ DRM_MEM_DRIVER);
-+ if (!dev->_vblank_count)
-+ goto err;
++/*
++ * 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 }
++};
+
-+ dev->vblank_refcount = drm_alloc(sizeof(atomic_t) * num_crtcs,
-+ DRM_MEM_DRIVER);
-+ if (!dev->vblank_refcount)
-+ goto err;
+ 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;
+
-+ dev->vblank_enabled = drm_calloc(num_crtcs, sizeof(int),
-+ DRM_MEM_DRIVER);
-+ if (!dev->vblank_enabled)
-+ goto err;
++ data = 0;
+
-+ dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
-+ if (!dev->last_vblank)
-+ goto err;
++ 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;
++}
+
-+ dev->vblank_premodeset = drm_calloc(num_crtcs, sizeof(u32),
-+ DRM_MEM_DRIVER);
-+ if (!dev->vblank_premodeset)
-+ goto err;
++/**
+ * 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;
+
-+ dev->vblank_offset = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
-+ if (!dev->vblank_offset)
-+ goto err;
++ 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;
++}
+
-+ /* 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);
++/*
++ * 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;
+ }
+
-+ return 0;
++ /*
++ * Old EEPROM (first entry) may require a reset after probe,
++ * rather than being able to "start" after "stop"
++ */
++ if (idx == 0)
++ eeprom_reset(dd);
+
-+err:
-+ drm_vblank_cleanup(dev);
-+ return ret;
++ 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;
+}
-+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);
+ 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 (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
-- init_waitqueue_head(&dev->vbl_queue);
--
-- spin_lock_init(&dev->vbl_lock);
+- if (!eeprom_init)
+- eeprom_reset(dd);
-
-- INIT_LIST_HEAD(&dev->vbl_sigs);
-- INIT_LIST_HEAD(&dev->vbl_sigs2);
+- 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);
+- }
-
-- dev->vbl_pending = 0;
-- }
++ /* get and store data */
++ *bp++ = rd_byte(dd);
+ /* send ack if not the last byte */
+ if (len)
+ send_ack(dd);
-
- /* Before installing handler */
- dev->driver->irq_preinstall(dev);
-
-@@ -137,9 +237,14 @@ static int drm_irq_install(struct drm_device * dev)
+- *((u8 *) buffer) = single_byte;
+- buffer++;
}
- /* 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;
+ stop_cmd(dd);
+@@ -418,31 +544,40 @@ bail:
+ return ret;
}
- /**
-@@ -170,6 +275,8 @@ int drm_irq_uninstall(struct drm_device * dev)
+-
+-/**
+- * 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;
- free_irq(dev->irq, dev);
+- if (!eeprom_init)
+- eeprom_reset(dd);
++ ret = 1;
++ icd = ipath_i2c_type(dd);
++ if (!icd)
++ goto bail;
-+ drm_vblank_cleanup(dev);
-+
- dev->locked_tasklet_func = NULL;
+ 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;
++ }
+ }
- return 0;
-@@ -214,6 +321,148 @@ int drm_control(struct drm_device *dev, void *data,
+ 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;
}
- /**
-+ * 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);
-+
+-/*
+- * The public entry-points ipath_eeprom_read() and ipath_eeprom_write()
+- * are now just wrappers around the internal functions.
+/**
-+ * 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.
++ * 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
+ */
-+void drm_update_vblank_count(struct drm_device *dev, int crtc)
+ 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)
+{
-+ unsigned long irqflags;
-+ u32 cur_vblank, diff;
++ 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;
++ }
+ /*
-+ * 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.
++ * We can only clock out one byte per command, sensibly
+ */
-+ 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);
++ ret = rd_byte(dd);
++ stop_cmd(dd);
+
-+ atomic_add(diff, &dev->_vblank_count[crtc]);
++bail:
++ return ret;
+}
-+EXPORT_SYMBOL(drm_update_vblank_count);
++
++#define VALID_TS_RD_REG_MASK 0xBF
+
+/**
-+ * 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.
++ * ipath_tempsense_read - read register of temp sensor via I2C
++ * @dd: the infinipath device
++ * @regnum: register to read from
+ *
-+ * RETURNS
-+ * Zero on success, nonzero on failure.
++ * returns reg contents (0..255) or < 0 for error
+ */
-+int drm_vblank_get(struct drm_device *dev, int crtc)
++int ipath_tempsense_read(struct ipath_devdata *dd, u8 regnum)
+{
-+ unsigned long irqflags;
-+ int ret = 0;
++ int ret;
+
-+ 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;
++ 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);
+ }
-+ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+
++ /*
++ * 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;
+}
-+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)
++static int ipath_tempsense_internal_write(struct ipath_devdata *dd,
++ u8 regnum, u8 data)
+{
-+ /* Last user schedules interrupt disable */
-+ if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
-+ mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
++ 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;
+}
-+EXPORT_SYMBOL(drm_vblank_put);
++
++#define VALID_TS_WR_REG_MASK ((1 << 9) | (1 << 0xB) | (1 << 0xD))
+
+/**
-+ * drm_modeset_ctl - handle vblank event counter changes across mode switch
-+ * @DRM_IOCTL_ARGS: standard ioctl arguments
++ * ipath_tempsense_write - write register of temp sensor via I2C
++ * @dd: the infinipath device
++ * @regnum: register to write
++ * @data: data to write
+ *
-+ * Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET
-+ * ioctls around modesetting so that any lost vblank events are accounted for.
++ * returns 0 for success or < 0 for error
+ */
-+int drm_modeset_ctl(struct drm_device *dev, void *data,
-+ struct drm_file *file_priv)
++int ipath_tempsense_write(struct ipath_devdata *dd, u8 regnum, u8 data)
+{
-+ struct drm_modeset_ctl *modeset = data;
-+ int crtc, ret = 0;
-+ u32 new;
++ int ret;
+
-+ crtc = modeset->arg;
-+ if (crtc >= dev->num_crtcs) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
++ if (regnum > 15 || !((1 << regnum) & VALID_TS_WR_REG_MASK))
++ return -EINVAL;
+
-+ 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;
++ ret = mutex_lock_interruptible(&dd->ipath_eep_lock);
++ if (!ret) {
++ ret = ipath_tempsense_internal_write(dd, regnum, data);
++ mutex_unlock(&dd->ipath_eep_lock);
+ }
+
-+out:
++ /*
++ * 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;
+}
-+
-+/**
- * Wait for VBLANK.
- *
- * \param inode device inode.
-@@ -232,12 +481,13 @@ int drm_control(struct drm_device *dev, void *data,
+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.
*
- * 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;
+ * This software is available to you under a choice of one of two
+@@ -36,21 +36,28 @@
+ #include <linux/cdev.h>
+ #include <linux/swap.h>
+ #include <linux/vmalloc.h>
++#include <linux/highmem.h>
++#include <linux/io.h>
++#include <linux/jiffies.h>
+ #include <asm/pgtable.h>
-- 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);
+ #include "ipath_kernel.h"
+ #include "ipath_common.h"
++#include "ipath_user_sdma.h"
- 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
+ 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 *);
- 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;
+ 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;
- 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
- }
- }
+ 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 (dev->vbl_pending >= 100) {
-+ if (atomic_read(&dev->vbl_signal_pending) >= 100) {
- spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
- return -EBUSY;
- }
+- 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;
+ }
-- dev->vbl_pending++;
--
- spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+ 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);
-- 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;
++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;
+
-+ ret = drm_vblank_get(dev, crtc);
-+ if (ret) {
-+ drm_free(vbl_sig, sizeof(struct drm_vbl_sig),
-+ DRM_MEM_DRIVER);
-+ return ret;
- }
++ 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);
-- memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
-+ atomic_inc(&dev->vbl_signal_pending);
+ done:
+@@ -1922,22 +1974,25 @@ static int ipath_do_user_init(struct file *fp,
+ pd->port_hdrqfull_poll = pd->port_hdrqfull;
- 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
+ /*
+- * 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;
- 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;
++ 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;
+ }
+
-+ 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);
++ dd = pd->port_dd;
+
- vblwait->reply.tval_sec = now.tv_sec;
- vblwait->reply.tval_usec = now.tv_usec;
-+ vblwait->reply.sequence = cur_vblank;
++ /* 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;
- 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;
+ 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)
- spin_lock_irqsave(&dev->vbl_lock, flags);
+ i = dd->ipath_pbufsport * (port - 1);
+ ipath_disarm_piobufs(dd, i, dd->ipath_pbufsport);
++ ipath_chg_pioavailkernel(dd, i, dd->ipath_pbufsport, 1);
-- 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);
+ dd->ipath_f_clear_tids(dd, pd->port_port);
-- 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);
+@@ -2140,17 +2203,31 @@ static int ipath_get_slave_info(struct ipath_portdata *pd,
+ return ret;
+ }
-- list_del(&vbl_sig->head);
-+ list_del(&vbl_sig->head);
+-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);
-- 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_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;
}
- spin_unlock_irqrestore(&dev->vbl_lock, flags);
+ if (ret >= 0)
+@@ -2319,14 +2417,28 @@ bail:
+ return ret;
}
--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)
++static ssize_t ipath_writev(struct kiocb *iocb, const struct iovec *iov,
++ unsigned long dim, loff_t off)
+{
-+ drm_update_vblank_count(dev, crtc);
-+ DRM_WAKEUP(&dev->vbl_queue[crtc]);
-+ drm_vbl_send_signals(dev, crtc);
++ 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);
+}
-+EXPORT_SYMBOL(drm_handle_vblank);
++
+ static struct class *ipath_class;
- /**
- * 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)
+ 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)
{
- struct proc_dir_entry *ent;
- int i, j;
- char name[64];
+ const dev_t dev = MKDEV(IPATH_MAJOR, minor);
+ struct cdev *cdev = NULL;
+- struct class_device *class_dev = NULL;
++ struct device *device = NULL;
+ int ret;
-- 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;
+ cdev = cdev_alloc();
+@@ -2350,12 +2462,12 @@ static int init_cdev(int minor, char *name, const struct file_operations *fops,
+ goto err_cdev;
}
- 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;
+- 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 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)
+ 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)
{
- int i;
- char name[64];
+- return init_cdev(minor, name, fops, cdevp, class_devp);
++ return init_cdev(minor, name, fops, cdevp, devp);
+ }
-- if (!root || !dev_root)
-+ if (!root || !minor->dev_root)
- return 0;
+ 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;
- 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);
+- if (class_dev) {
+- class_device_unregister(class_dev);
+- *class_devp = NULL;
++ if (dev) {
++ device_unregister(dev);
++ *devp = NULL;
+ }
- 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 (*cdevp) {
+@@ -2401,13 +2513,13 @@ static void cleanup_cdev(struct cdev **cdevp,
+ }
- 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)
+ void ipath_cdev_cleanup(struct cdev **cdevp,
+- struct class_device **class_devp)
++ struct device **devp)
{
-- struct drm_device *dev = (struct drm_device *) data;
-+ struct drm_minor *minor = (struct drm_minor *) data;
-+ struct drm_device *dev = minor->dev;
- int ret;
+- cleanup_cdev(cdevp, class_devp);
++ cleanup_cdev(cdevp, devp);
+ }
- 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;
+ static struct cdev *wildcard_cdev;
+-static struct class_device *wildcard_class_dev;
++static struct device *wildcard_dev;
- 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;
+ static const dev_t dev = MKDEV(IPATH_MAJOR, 0);
- 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;
+@@ -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);
-@@ -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;
+ 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:
- 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)
+ void ipath_user_remove(struct ipath_devdata *dd)
{
-- struct drm_device *dev = (struct drm_device *) data;
-+ struct drm_minor *minor = (struct drm_minor *) data;
-+ struct drm_device *dev = minor->dev;
- int ret;
+- cleanup_cdev(&dd->user_cdev, &dd->user_class_dev);
++ cleanup_cdev(&dd->user_cdev, &dd->user_dev);
- 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"
+ if (atomic_dec_return(&user_count) == 0) {
+ if (atomic_read(&user_setup) == 0)
+ goto bail;
--unsigned int drm_cards_limit = 16; /* Enough for one machine */
- unsigned int drm_debug = 0; /* 1 to enable debug output */
- EXPORT_SYMBOL(drm_debug);
+- cleanup_cdev(&wildcard_cdev, &wildcard_class_dev);
++ cleanup_cdev(&wildcard_cdev, &wildcard_dev);
+ user_cleanup();
- 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");
+ atomic_set(&user_setup, 0);
+diff --git a/drivers/infiniband/hw/ipath/ipath_iba6110.c b/drivers/infiniband/hw/ipath/ipath_iba6110.c
+index 9e2ced3..02831ad 100644
+--- a/drivers/infiniband/hw/ipath/ipath_iba6110.c
++++ b/drivers/infiniband/hw/ipath/ipath_iba6110.c
+@@ -40,6 +40,7 @@
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+ #include <linux/htirq.h>
++#include <rdma/ib_verbs.h>
--module_param_named(cards_limit, drm_cards_limit, int, 0444);
- module_param_named(debug, drm_debug, int, 0600);
+ #include "ipath_kernel.h"
+ #include "ipath_registers.h"
+@@ -305,7 +306,9 @@ static const struct ipath_cregs ipath_ht_cregs = {
--struct drm_head **drm_heads;
-+struct idr drm_minors_idr;
-+
- struct class *drm_class;
- struct proc_dir_entry *drm_proc_root;
+ /* 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
-+static int drm_minor_get_id(struct drm_device *dev, int type)
+ /* 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)
+{
-+ 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;
++ ++ipath_stats.sps_txeparity;
++ dev_info(&dd->pcidev->dev,
++ "Recovering from TXE PIO parity error\n");
+}
+
- 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);
+ /**
+ * 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 (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;
+ 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));
}
-+ } 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;
- }
+@@ -904,7 +912,7 @@ static void slave_or_pri_blk(struct ipath_devdata *dd, struct pci_dev *pdev,
+ break;
+ }
-@@ -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;
+- 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;
}
-- if ((ret = drm_get_head(dev, &dev->primary)))
-+ if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
- goto err_g2;
++
++ snprintf(dd->ipath_lbus_info, sizeof(dd->ipath_lbus_info),
++ "HyperTransport,%uMHz,x%u\n",
++ dd->ipath_lbus_speed,
++ dd->ipath_lbus_width);
+ }
- 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);
+ static int ipath_ht_intconfig(struct ipath_devdata *dd)
+@@ -1653,22 +1666,6 @@ static int ipath_ht_early_init(struct ipath_devdata *dd)
+ }
- 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;
+-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;
+-}
-
-- 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;
+ * ipath_init_ht_get_base_info - set chip-specific flags for user code
+ * @dd: the infinipath device
+diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c
+index c7a2f50..421cc2a 100644
+--- a/drivers/infiniband/hw/ipath/ipath_iba6120.c
++++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -38,7 +38,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+-
++#include <rdma/ib_verbs.h>
-- 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";
+ #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)
+ };
-- err = device_register(&dev->dev);
-+ snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index);
++/* kr_control bits */
++#define INFINIPATH_C_RESET 1U
+
-+ 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;
+ /* 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
- 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;
+ /* 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
-- 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;
++/* kr_xgxsconfig bits */
++#define INFINIPATH_XGXS_RESET 0x5ULL
++
+ #define _IPATH_GPIO_SDA_NUM 1
+ #define _IPATH_GPIO_SCL_NUM 0
- 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;
+@@ -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))
- 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 = {
++#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
- 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;
+@@ -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)
- 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 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));
- 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;
+ 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);
+ }
-- 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 (*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;
+ }
-- 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;
+-
+ /*
+ * 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);
- 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();
+- 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);
}
-+int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush)
++static void ipath_6120_pcie_params(struct ipath_devdata *dd)
+{
-+ 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);
++ u16 linkstat, speed;
++ int pos;
+
-+ BEGIN_LP_RING(4);
-+ OUT_RING(flush_cmd);
-+ OUT_RING(0);
-+ OUT_RING(0);
-+ OUT_RING(0);
-+ ADVANCE_LP_RING();
++ 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;
++ }
+
-+ return 0;
-+}
++ 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;
+
- 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;
++ switch (speed) {
+ case 1:
-+ dspbase = dev_priv->sarea_priv->back_offset;
++ dd->ipath_lbus_speed = 2500; /* Gen1, 2.5GHz */
+ break;
+ case 2:
-+ dspbase = dev_priv->sarea_priv->third_offset;
++ dd->ipath_lbus_speed = 5000; /* Gen1, 5GHz */
+ 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");
++ default: /* not defined, assume gen1 */
++ dd->ipath_lbus_speed = 2500;
++ break;
++ }
+
-+ 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));
++ 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);
+
-+ planes |= 1 << i;
-+ }
++ 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);
+
-+ if (planes)
-+ i915_dispatch_flip(dev, planes, 0);
++ return;
++}
+
- 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;
+ /**
+ * 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");
+
-+ DRM_DEBUG("\n");
++ ipath_6120_pcie_params(dd);
- LOCK_TEST_WITH_RETURN(dev, file_priv);
+ 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;
-- 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;
+- 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 */
}
- 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;
+@@ -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);
-+ 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));
+ /* 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 */
-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;
+ bail:
++ if (ret)
++ ipath_6120_pcie_params(dd);
+ return ret;
+ }
-- 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;
+@@ -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;
+
-+ /* 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)
++ if (!dd->ipath_kregbase)
++ return;
-+/* Asynchronous page flipping:
-+ */
-+typedef struct drm_i915_flip {
+ 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);
+ /*
-+ * 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.
++ * Assumes tidptr always > ipath_egrtidbase
++ * if type == RCVHQ_RCV_TYPE_EAGER.
+ */
-+ int pipes;
-+} drm_i915_flip_t;
++ tidx = tidptr - dd->ipath_egrtidbase;
+
- /* 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)
++ 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);
+ }
+
-
- #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
+ /**
+ * 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;
+
-+#define PIPEADSL 0x70000
-+#define PIPEBDSL 0x71000
++ if (!dd->ipath_kregbase)
++ return;
- #define I915REG_PIPEASTAT 0x70024
- #define I915REG_PIPEBSTAT 0x71024
+ 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 @@
+/*
-+ * The two pipe frame counter registers are not synchronized, so
-+ * reading a stable value is somewhat tricky. The following code
-+ * should work:
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
-+ * 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;
++ * 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.
+ */
-+#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.
++ * This file contains all of the code that is specific to the
++ * InfiniPath 7220 chip (except that specific to the SerDes)
+ */
-+#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;
++#include <linux/interrupt.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <rdma/ib_verbs.h>
+
-+ dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR);
++#include "ipath_kernel.h"
++#include "ipath_registers.h"
++#include "ipath_7220.h"
+
-+ return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0;
-+}
++static void ipath_setup_7220_setextled(struct ipath_devdata *, u64, u64);
+
-+/**
-+ * 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;
-+}
++static unsigned ipath_compat_ddr_negotiate = 1;
+
-+/**
-+ * i915_pipe_enabled - check if a pipe is enabled
-+ * @dev: DRM device
-+ * @pipe: pipe to check
++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.
+ *
-+ * 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.
++ * This lists the InfiniPath registers, in the actual chip layout.
++ * This structure should never be directly accessed.
+ */
-+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;
++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];
++};
+
-+ if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
-+ return 1;
++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;
++};
+
-+ return 0;
-+}
++#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))
+
-+/**
-+ * 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;
++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),
+
-+ /* If the window is visible on the other plane, we have to flip on that
-+ * plane as well.
++ .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()
+ */
-+ 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;
-+ }
++ .kr_rcvhdraddr = IPATH_KREG_OFFSET(RcvHdrAddr0),
++ .kr_rcvhdrtailaddr = IPATH_KREG_OFFSET(RcvHdrTailAddr0),
+
-+ if (x2 > 0 && y2 > 0) {
-+ int i, num_rects = drw->num_rects;
-+ struct drm_clip_rect *rect = drw->rects;
++ /*
++ * 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),
+
-+ 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;
++ .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)
++};
+
-+ break;
-+ }
-+ }
++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),
++};
+
-+ i915_dispatch_flip(dev, pf_planes, 1);
-+}
++/* kr_control bits */
++#define INFINIPATH_C_RESET (1U<<7)
+
-+/**
- * 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;
-+ }
++/* 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)
+
-+ counter[0] = drm_vblank_count(dev, 0);
-+ counter[1] = drm_vblank_count(dev, 1);
++/* 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
+
- 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];
++#define IBA7220_IBCS_LINKTRAININGSTATE_MASK 0x1F
++#define IBA7220_IBCS_LINKSTATE_SHIFT 5
++#define IBA7220_IBCS_LINKSPEED_SHIFT 8
++#define IBA7220_IBCS_LINKWIDTH_SHIFT 9
+
-+ 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;
++#define IBA7220_IBCC_LINKINITCMD_MASK 0x7ULL
++#define IBA7220_IBCC_LINKCMD_SHIFT 19
++#define IBA7220_IBCC_MAXPKTLEN_SHIFT 21
+
- 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;
++/* kr_ibcddrctrl bits */
++#define IBA7220_IBC_DLIDLMC_MASK 0xFFFFFFFFUL
++#define IBA7220_IBC_DLIDLMC_SHIFT 32
++#define IBA7220_IBC_HRTBT_MASK 3
++#define IBA7220_IBC_HRTBT_SHIFT 16
++#define IBA7220_IBC_HRTBT_ENB 0x10000UL
++#define IBA7220_IBC_LANE_REV_SUPPORTED (1<<8)
++#define IBA7220_IBC_LREV_MASK 1
++#define IBA7220_IBC_LREV_SHIFT 8
++#define IBA7220_IBC_RXPOL_MASK 1
++#define IBA7220_IBC_RXPOL_SHIFT 7
++#define IBA7220_IBC_WIDTH_SHIFT 5
++#define IBA7220_IBC_WIDTH_MASK 0x3
++#define IBA7220_IBC_WIDTH_1X_ONLY (0<<IBA7220_IBC_WIDTH_SHIFT)
++#define IBA7220_IBC_WIDTH_4X_ONLY (1<<IBA7220_IBC_WIDTH_SHIFT)
++#define IBA7220_IBC_WIDTH_AUTONEG (2<<IBA7220_IBC_WIDTH_SHIFT)
++#define IBA7220_IBC_SPEED_AUTONEG (1<<1)
++#define IBA7220_IBC_SPEED_SDR (1<<2)
++#define IBA7220_IBC_SPEED_DDR (1<<3)
++#define IBA7220_IBC_SPEED_AUTONEG_MASK (0x7<<1)
++#define IBA7220_IBC_IBTA_1_2_MASK (1)
+
-+ if (swap_hit->flip) {
-+ i915_dispatch_vsync_flip(dev, drw, plane);
-+ continue;
-+ }
++/* kr_ibcddrstatus */
++/* link latency shift is 0, don't bother defining */
++#define IBA7220_DDRSTAT_LINKLAT_MASK 0x3ffffff
+
-+ if (init_drawrect) {
-+ int width = sarea_priv->width;
-+ int height = sarea_priv->height;
-+ if (IS_I965G(dev)) {
-+ BEGIN_LP_RING(4);
++/* kr_extstatus bits */
++#define INFINIPATH_EXTS_FREQSEL 0x2
++#define INFINIPATH_EXTS_SERDESSEL 0x4
++#define INFINIPATH_EXTS_MEMBIST_ENDTEST 0x0000000000004000
++#define INFINIPATH_EXTS_MEMBIST_DISABLED 0x0000000000008000
+
-+ OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
-+ OUT_RING(0);
-+ OUT_RING(((width - 1) & 0xffff) | ((height - 1) << 16));
-+ OUT_RING(0);
++/* kr_xgxsconfig bits */
++#define INFINIPATH_XGXS_RESET 0x5ULL
++#define INFINIPATH_XGXS_FC_SAFE (1ULL<<63)
+
-+ ADVANCE_LP_RING();
-+ } else {
-+ BEGIN_LP_RING(6);
++/* kr_rcvpktledcnt */
++#define IBA7220_LEDBLINK_ON_SHIFT 32 /* 4ns period on after packet */
++#define IBA7220_LEDBLINK_OFF_SHIFT 0 /* 4ns period off before next on */
+
-+ 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);
++#define _IPATH_GPIO_SDA_NUM 1
++#define _IPATH_GPIO_SCL_NUM 0
+
-+ ADVANCE_LP_RING();
-+ }
++#define IPATH_GPIO_SDA (1ULL << \
++ (_IPATH_GPIO_SDA_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
++#define IPATH_GPIO_SCL (1ULL << \
++ (_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
+
-+ sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
++#define IBA7220_R_INTRAVAIL_SHIFT 17
++#define IBA7220_R_TAILUPD_SHIFT 35
++#define IBA7220_R_PORTCFG_SHIFT 36
+
-+ init_drawrect = 0;
-+ }
++#define INFINIPATH_JINT_PACKETSHIFT 16
++#define INFINIPATH_JINT_DEFAULT_IDLE_TICKS 0
++#define INFINIPATH_JINT_DEFAULT_MAX_PACKETS 0
+
- rect = drw->rects;
-- pipe = swap_hit->pipe;
-- top = upper[pipe];
-- bottom = lower[pipe];
-+ top = upper[plane];
-+ bottom = lower[plane];
++#define IBA7220_HDRHEAD_PKTINT_SHIFT 32 /* interrupt cnt in upper 32 bits */
+
-+ 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;
++/*
++ * the size bits give us 2^N, in KB units. 0 marks as invalid,
++ * and 7 is reserved. We currently use only 2KB and 4KB
++ */
++#define IBA7220_TID_SZ_SHIFT 37 /* shift to 3bit size selector */
++#define IBA7220_TID_SZ_2K (1UL<<IBA7220_TID_SZ_SHIFT) /* 2KB */
++#define IBA7220_TID_SZ_4K (2UL<<IBA7220_TID_SZ_SHIFT) /* 4KB */
++#define IBA7220_TID_PA_SHIFT 11U /* TID addr in chip stored w/o low bits */
+
-+ pipe = i915_get_pipe(dev, plane);
-+ high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
-+ low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
++#define IPATH_AUTONEG_TRIES 5 /* sequential retries to negotiate DDR */
+
-+ if (!i915_pipe_enabled(dev, pipe)) {
-+ printk(KERN_ERR "trying to get vblank count for disabled "
-+ "pipe %d\n", pipe);
-+ return 0;
-+ }
++static char int_type[16] = "auto";
++module_param_string(interrupt_type, int_type, sizeof(int_type), 0444);
++MODULE_PARM_DESC(int_type, " interrupt_type=auto|force_msi|force_intx\n");
++
++/* packet rate matching delay; chip has support */
++static u8 rate_to_delay[2][2] = {
++ /* 1x, 4x */
++ { 8, 2 }, /* SDR */
++ { 4, 1 } /* DDR */
++};
+
++/* 7220 specific hardware errors... */
++static const struct ipath_hwerror_msgs ipath_7220_hwerror_msgs[] = {
++ INFINIPATH_HWE_MSG(PCIEPOISONEDTLP, "PCIe Poisoned TLP"),
++ INFINIPATH_HWE_MSG(PCIECPLTIMEOUT, "PCIe completion timeout"),
+ /*
-+ * 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.
++ * In practice, it's unlikely wthat we'll see PCIe PLL, or bus
++ * parity or memory parity error failures, because most likely we
++ * won't be able to talk to the core of the chip. Nonetheless, we
++ * might see them, if they are in parts of the PCIe core that aren't
++ * essential.
+ */
-+ 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);
++ INFINIPATH_HWE_MSG(PCIE1PLLFAILED, "PCIePLL1"),
++ INFINIPATH_HWE_MSG(PCIE0PLLFAILED, "PCIePLL0"),
++ INFINIPATH_HWE_MSG(PCIEBUSPARITYXTLH, "PCIe XTLH core parity"),
++ INFINIPATH_HWE_MSG(PCIEBUSPARITYXADM, "PCIe ADM TX core parity"),
++ INFINIPATH_HWE_MSG(PCIEBUSPARITYRADM, "PCIe ADM RX core parity"),
++ INFINIPATH_HWE_MSG(RXDSYNCMEMPARITYERR, "Rx Dsync"),
++ INFINIPATH_HWE_MSG(SERDESPLLFAILED, "SerDes PLL"),
++ INFINIPATH_HWE_MSG(PCIECPLDATAQUEUEERR, "PCIe cpl header queue"),
++ INFINIPATH_HWE_MSG(PCIECPLHDRQUEUEERR, "PCIe cpl data queue"),
++ INFINIPATH_HWE_MSG(SDMAMEMREADERR, "Send DMA memory read"),
++ INFINIPATH_HWE_MSG(CLK_UC_PLLNOTLOCKED, "uC PLL clock not locked"),
++ INFINIPATH_HWE_MSG(PCIESERDESQ0PCLKNOTDETECT,
++ "PCIe serdes Q0 no clock"),
++ INFINIPATH_HWE_MSG(PCIESERDESQ1PCLKNOTDETECT,
++ "PCIe serdes Q1 no clock"),
++ INFINIPATH_HWE_MSG(PCIESERDESQ2PCLKNOTDETECT,
++ "PCIe serdes Q2 no clock"),
++ INFINIPATH_HWE_MSG(PCIESERDESQ3PCLKNOTDETECT,
++ "PCIe serdes Q3 no clock"),
++ INFINIPATH_HWE_MSG(DDSRXEQMEMORYPARITYERR,
++ "DDS RXEQ memory parity"),
++ INFINIPATH_HWE_MSG(IB_UC_MEMORYPARITYERR, "IB uC memory parity"),
++ INFINIPATH_HWE_MSG(PCIE_UC_OCT0MEMORYPARITYERR,
++ "PCIe uC oct0 memory parity"),
++ INFINIPATH_HWE_MSG(PCIE_UC_OCT1MEMORYPARITYERR,
++ "PCIe uC oct1 memory parity"),
++};
+
-+ count = (high1 << 8) | low;
++static void autoneg_work(struct work_struct *);
+
-+ /* 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;
++/*
++ * the offset is different for different configured port numbers, since
++ * port0 is fixed in size, but others can vary. Make it a function to
++ * make the issue more obvious.
++*/
++static inline u32 port_egrtid_idx(struct ipath_devdata *dd, unsigned port)
++{
++ return port ? dd->ipath_p0_rcvegrcnt +
++ (port-1) * dd->ipath_rcvegrcnt : 0;
++}
+
-+ return count;
++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);
+}
+
- 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;
++/**
++ * 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;
+ }
-
-- 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);
++ ipath_stats.sps_hwerrs++;
++
+ /*
-+ * Clear the PIPE(A|B)STAT regs before the IIR otherwise
-+ * we may get extra interrupts.
++ * 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.
+ */
-+ 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));
++ 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;
++ }
+ }
-+ 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));
++ 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);
+ }
-+ 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);
++
++ *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);
+ }
-+ 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;
++ 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);
+ }
+
-+ 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;
++#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) {
+ /*
-+ * Clear any pending status
++ * If it occurs, it is left masked since the eternal
++ * interface is unused.
+ */
-+ pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
-+ I915_VBLANK_INTERRUPT_STATUS);
-+ I915_WRITE(pipestat_reg, pipestat);
++ dd->ipath_hwerrmask &= ~INFINIPATH_HWE_SERDESPLLFAILED;
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
++ dd->ipath_hwerrmask);
+ }
-+ I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+
-+ return 0;
++ 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:;
+}
+
-+void i915_disable_vblank(struct drm_device *dev, int plane)
++/**
++ * 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)
+{
-+ 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;
++ char *n = NULL;
++ u8 boardrev = dd->ipath_boardrev;
++ int ret;
+
-+ switch (pipe) {
++ if (boardrev == 15) {
++ /*
++ * Emulator sometimes comes up all-ones, rather than zero.
++ */
++ boardrev = 0;
++ dd->ipath_boardrev = boardrev;
++ }
++ switch (boardrev) {
+ case 0:
-+ pipestat_reg = I915REG_PIPEASTAT;
-+ dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
++ n = "InfiniPath_7220_Emulation";
+ break;
+ case 1:
-+ pipestat_reg = I915REG_PIPEBSTAT;
-+ dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
++ 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:
-+ DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
-+ pipe);
++ 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);
+
-+ 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);
-+ }
-+}
++ if (dd->ipath_majrev != 5 || !dd->ipath_minrev ||
++ dd->ipath_minrev > 2) {
++ ipath_dev_err(dd, "Unsupported InfiniPath hardware "
++ "revision %u.%u!\n",
++ dd->ipath_majrev, dd->ipath_minrev);
++ ret = 1;
++ } else if (dd->ipath_minrev == 1) {
++ /* Rev1 chips are prototype. Complain, but allow use */
++ ipath_dev_err(dd, "Unsupported hardware "
++ "revision %u.%u, Contact support at qlogic.com\n",
++ dd->ipath_majrev, dd->ipath_minrev);
++ ret = 0;
++ } else
++ ret = 0;
+
- 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.
++ /*
++ * Set here not in ipath_init_*_funcs because we have to do
++ * it after we can read chip registers.
+ */
- 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);
++ dd->ipath_ureg_align = 0x10000; /* 64KB alignment */
+
-+ return 0;
-+ }
-+ }
++ return ret;
++}
+
- 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;
-+ }
++/**
++ * 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;
+
- 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);
++ extsval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
+
-+ 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;
++ 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");
+
-+ ret = drm_vblank_init(dev, num_pipes);
-+ if (ret)
-+ return ret;
++ val = ~0ULL; /* barring bugs, all hwerrors become interrupts, */
+
-+ dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
++ if (!dd->ipath_boardrev) /* no PLL for Emulator */
++ val &= ~INFINIPATH_HWE_SERDESPLLFAILED;
+
- i915_enable_interrupt(dev);
- DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
++ if (dd->ipath_minrev == 1)
++ val &= ~(1ULL << 42); /* TXE LaunchFIFO Parity rev1 issue */
++
++ val &= ~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR;
++ dd->ipath_hwerrmask = val;
+
+ /*
-+ * Initialize the hardware status page IRQ location.
++ * 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;
++}
+
-+ 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);
++/*
++ * 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().
++ */
+
-+ 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)
++/**
++ * ipath_7220_bringup_serdes - bring up the serdes
++ * @dd: the infinipath device
++ */
++static int ipath_7220_bringup_serdes(struct ipath_devdata *dd)
+{
-+ const drm_mga_private_t *const dev_priv =
-+ (drm_mga_private_t *) dev->dev_private;
++ int ret = 0;
++ u64 val, prev_val, guid;
++ int was_reset; /* Note whether uC was reset */
+
-+ if (crtc != 0) {
-+ return 0;
-+ }
++ 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);
++ }
+
-+ return atomic_read(&dev_priv->vbl_received);
-+}
++ 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;
+
- 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;
++ /* 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;
+ }
-
-- *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);
-+ }
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcddrctrl,
++ dd->ipath_ibcddrctrl);
+
-+ /* 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;
++ ipath_write_kreg(dd, IPATH_KREG_OFFSET(IBNCModeCtrl), 0Ull);
+
-+ 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;
++ /* 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));
+
- 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 (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);
++ }
+
-+ if (crtc != 0)
-+ return 0;
++ 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);
+
-+ return atomic_read(&dev_priv->vbl_received);
-+}
++ ipath_cdbg(VERBOSE, "done: xgxs=%llx from %llx\n",
++ (unsigned long long)
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig),
++ prev_val);
+
- 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;
++ 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;
+}
+
-+void r128_disable_vblank(struct drm_device *dev, int crtc)
++static void ipath_7220_config_jint(struct ipath_devdata *dd,
++ u16 idle_ticks, u16 max_packets)
+{
-+ 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);
++ * We can request a receive interrupt for 1 or more packets
++ * from current offset.
+ */
- }
-
- 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;
++ 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
-+ dev_priv->irq_enable_reg &= ~mask;
++ /* Turn off RcvHdrHead interrupts if using mitigation */
++ dd->ipath_rhdrhead_intr_off = 0ULL;
+
-+ RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
++ /* 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);
+}
+
-+int radeon_enable_vblank(struct drm_device *dev, int crtc)
++/**
++ * 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)
+{
-+ 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;
-+ }
++ 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;
+}
+
-+void radeon_disable_vblank(struct drm_device *dev, int crtc)
++/**
++ * 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)
+{
-+ 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;
++ 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);
+}
+
-+static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv)
++/*
++ * Similar to pci_intx(pdev, 1), except that we make sure
++ * msi is off...
++ */
++static void ipath_enable_intx(struct pci_dev *pdev)
+{
-+ 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);
++ u16 cw, new;
++ int pos;
+
- 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;
++ /* 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);
+
- 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;
++ /* 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);
+ }
-
-- 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;
++static int ipath_msi_enabled(struct pci_dev *pdev)
++{
++ int pos, ret = 0;
+
-+ radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
++ pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
++ if (pos) {
++ u16 cw;
+
-+ 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);
++ pci_read_config_word(pdev, pos + PCI_MSI_FLAGS, &cw);
++ ret = !!(cw & PCI_MSI_FLAGS_ENABLE);
++ }
++ return ret;
+}
+
-+u32 via_get_vblank_counter(struct drm_device *dev, int crtc)
++/*
++ * 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)
+{
-+ drm_via_private_t *dev_priv = dev->dev_private;
-+ if (crtc != 0)
-+ return 0;
++ dd->ipath_msi_lo = 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;
++ 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);
++ }
+}
-
-- *sequence = cur_vblank;
-- return ret;
-+void via_disable_vblank(struct drm_device *dev, int crtc)
++
++/*
++ * 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)
+{
-+ drm_via_private_t *dev_priv = dev->dev_private;
++ ipath_7220_nomsi(dd);
++}
+
-+ VIA_WRITE8(0x83d4, 0x11);
-+ VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
+
-+ if (crtc != 0)
-+ DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
- }
-
- static int
-@@ -292,23 +303,25 @@ void via_driver_irq_preinstall(struct drm_device * dev)
- }
- }
-
--void via_driver_irq_postinstall(struct drm_device * dev)
-+int via_driver_irq_postinstall(struct drm_device * dev)
- {
- drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
- u32 status;
-
-- DRM_DEBUG("\n");
-- if (dev_priv) {
-- status = VIA_READ(VIA_REG_INTERRUPT);
-- VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
-- | dev_priv->irq_enable_mask);
-+ DRM_DEBUG("via_driver_irq_postinstall\n");
-+ if (!dev_priv)
-+ return -EINVAL;
-
-- /* Some magic, oh for some data sheets ! */
-+ drm_vblank_init(dev, 1);
-+ status = VIA_READ(VIA_REG_INTERRUPT);
-+ VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
-+ | dev_priv->irq_enable_mask);
-
-- VIA_WRITE8(0x83d4, 0x11);
-- VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
-+ /* Some magic, oh for some data sheets ! */
-+ VIA_WRITE8(0x83d4, 0x11);
-+ VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
-
-- }
-+ return 0;
- }
-
- void via_driver_irq_uninstall(struct drm_device * dev)
-diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
-index 8facf3e..7ed7da1 100644
---- a/drivers/char/generic_serial.c
-+++ b/drivers/char/generic_serial.c
-@@ -28,7 +28,6 @@
- #include <linux/interrupt.h>
- #include <linux/tty_flip.h>
- #include <linux/delay.h>
--#include <asm/semaphore.h>
- #include <asm/uaccess.h>
-
- #define DEBUG
-diff --git a/drivers/char/hvc_beat.c b/drivers/char/hvc_beat.c
-index e74bb94..91cdb35 100644
---- a/drivers/char/hvc_beat.c
-+++ b/drivers/char/hvc_beat.c
-@@ -78,8 +78,8 @@ static int hvc_beat_put_chars(uint32_t vtermno, const char *buf, int cnt)
- for (rest = cnt; rest > 0; rest -= nlen) {
- nlen = (rest > 16) ? 16 : rest;
- memcpy(kb, buf, nlen);
-- beat_put_term_char(vtermno, rest, kb[0], kb[1]);
-- rest -= nlen;
-+ beat_put_term_char(vtermno, nlen, kb[0], kb[1]);
-+ buf += nlen;
- }
- return cnt;
- }
-diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
-index 84cdf90..662d60e 100644
---- a/drivers/char/hw_random/core.c
-+++ b/drivers/char/hw_random/core.c
-@@ -116,6 +116,10 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
- err = -EAGAIN;
- if (!bytes_read && (filp->f_flags & O_NONBLOCK))
- goto out;
-+ if (bytes_read < 0) {
-+ err = bytes_read;
-+ goto out;
-+ }
-
- err = -EFAULT;
- while (bytes_read && size) {
-@@ -234,11 +238,11 @@ static DEVICE_ATTR(rng_available, S_IRUGO,
- NULL);
-
-
--static void unregister_miscdev(bool suspended)
-+static void unregister_miscdev(void)
- {
- device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available);
- device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
-- __misc_deregister(&rng_miscdev, suspended);
-+ misc_deregister(&rng_miscdev);
- }
-
- static int register_miscdev(void)
-@@ -313,7 +317,7 @@ out:
- }
- EXPORT_SYMBOL_GPL(hwrng_register);
-
--void __hwrng_unregister(struct hwrng *rng, bool suspended)
-+void hwrng_unregister(struct hwrng *rng)
- {
- int err;
-
-@@ -332,11 +336,11 @@ void __hwrng_unregister(struct hwrng *rng, bool suspended)
- }
- }
- if (list_empty(&rng_list))
-- unregister_miscdev(suspended);
-+ unregister_miscdev();
-
- mutex_unlock(&rng_mutex);
- }
--EXPORT_SYMBOL_GPL(__hwrng_unregister);
-+EXPORT_SYMBOL_GPL(hwrng_unregister);
-
-
- MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
-diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
-index 7e31995..51738bd 100644
---- a/drivers/char/hw_random/omap-rng.c
-+++ b/drivers/char/hw_random/omap-rng.c
-@@ -1,7 +1,5 @@
- /*
-- * drivers/char/hw_random/omap-rng.c
-- *
-- * RNG driver for TI OMAP CPU family
-+ * omap-rng.c - RNG driver for TI OMAP CPU family
- *
- * Author: Deepak Saxena <dsaxena at plexity.net>
- *
-@@ -15,11 +13,6 @@
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
-- *
-- * TODO:
-- *
-- * - Make status updated be interrupt driven so we don't poll
-- *
- */
-
- #include <linux/module.h>
-@@ -55,17 +48,16 @@ static void __iomem *rng_base;
- static struct clk *rng_ick;
- static struct platform_device *rng_dev;
-
--static u32 omap_rng_read_reg(int reg)
-+static inline u32 omap_rng_read_reg(int reg)
- {
- return __raw_readl(rng_base + reg);
- }
-
--static void omap_rng_write_reg(int reg, u32 val)
-+static inline void omap_rng_write_reg(int reg, u32 val)
- {
- __raw_writel(val, rng_base + reg);
- }
-
--/* REVISIT: Does the status bit really work on 16xx? */
- static int omap_rng_data_present(struct hwrng *rng, int wait)
- {
- int data, i;
-@@ -74,6 +66,11 @@ static int omap_rng_data_present(struct hwrng *rng, int wait)
- data = omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
- if (data || !wait)
- break;
-+ /* RNG produces data fast enough (2+ MBit/sec, even
-+ * during "rngtest" loads, that these delays don't
-+ * seem to trigger. We *could* use the RNG IRQ, but
-+ * that'd be higher overhead ... so why bother?
-+ */
- udelay(10);
- }
- return data;
-@@ -101,7 +98,8 @@ static int __init omap_rng_probe(struct platform_device *pdev)
- * A bit ugly, and it will never actually happen but there can
- * be only one RNG and this catches any bork
- */
-- BUG_ON(rng_dev);
-+ if (rng_dev)
-+ return -EBUSY;
-
- if (cpu_is_omap24xx()) {
- rng_ick = clk_get(NULL, "rng_ick");
-@@ -124,7 +122,7 @@ static int __init omap_rng_probe(struct platform_device *pdev)
- return -EBUSY;
-
- dev_set_drvdata(&pdev->dev, mem);
-- rng_base = (u32 __iomem *)io_p2v(res->start);
-+ rng_base = (u32 __force __iomem *)io_p2v(res->start);
-
- ret = hwrng_register(&omap_rng_ops);
- if (ret) {
-@@ -182,6 +180,8 @@ static int omap_rng_resume(struct platform_device *pdev)
-
- #endif
-
-+/* work with hotplug and coldplug */
-+MODULE_ALIAS("platform:omap_rng");
-
- static struct platform_driver omap_rng_driver = {
- .driver = {
-diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
-index 4dbd342..60b934a 100644
---- a/drivers/char/keyboard.c
-+++ b/drivers/char/keyboard.c
-@@ -42,6 +42,7 @@
- #include <linux/input.h>
- #include <linux/reboot.h>
- #include <linux/notifier.h>
-+#include <linux/jiffies.h>
-
- extern void ctrl_alt_del(void);
-
-@@ -928,7 +929,8 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
- if (up_flag) {
- if (brl_timeout) {
- if (!committing ||
-- jiffies - releasestart > (brl_timeout * HZ) / 1000) {
-+ time_after(jiffies,
-+ releasestart + msecs_to_jiffies(brl_timeout))) {
- committing = pressed;
- releasestart = jiffies;
- }
-@@ -1033,7 +1035,8 @@ DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
- #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
- defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
- defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
-- (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC))
-+ (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC)) ||\
-+ defined(CONFIG_AVR32)
-
- #define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
- ((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
-@@ -1237,6 +1240,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
- }
-
- param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
-+ param.ledstate = kbd->ledflagstate;
- key_map = key_maps[shift_final];
-
- if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYCODE, ¶m) == NOTIFY_STOP || !key_map) {
-@@ -1285,6 +1289,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
-
- (*k_handler[type])(vc, keysym & 0xff, !down);
-
-+ param.ledstate = kbd->ledflagstate;
- atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, ¶m);
-
- if (type != KT_SLOCK)
-diff --git a/drivers/char/mem.c b/drivers/char/mem.c
-index 20070b7..e83623e 100644
---- a/drivers/char/mem.c
-+++ b/drivers/char/mem.c
-@@ -41,36 +41,7 @@
- */
- static inline int uncached_access(struct file *file, unsigned long addr)
- {
--#if defined(__i386__) && !defined(__arch_um__)
-- /*
-- * On the PPro and successors, the MTRRs are used to set
-- * memory types for physical addresses outside main memory,
-- * so blindly setting PCD or PWT on those pages is wrong.
-- * For Pentiums and earlier, the surround logic should disable
-- * caching for the high addresses through the KEN pin, but
-- * we maintain the tradition of paranoia in this code.
-- */
-- if (file->f_flags & O_SYNC)
-- return 1;
-- return !( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ||
-- test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ||
-- test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
-- test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) )
-- && addr >= __pa(high_memory);
--#elif defined(__x86_64__) && !defined(__arch_um__)
-- /*
-- * This is broken because it can generate memory type aliases,
-- * which can cause cache corruptions
-- * But it is only available for root and we have to be bug-to-bug
-- * compatible with i386.
-- */
-- if (file->f_flags & O_SYNC)
-- return 1;
-- /* same behaviour as i386. PAT always set to cached and MTRRs control the
-- caching behaviour.
-- Hopefully a full PAT implementation will fix that soon. */
-- return 0;
--#elif defined(CONFIG_IA64)
-+#if defined(CONFIG_IA64)
- /*
- * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases.
- */
-@@ -108,6 +79,36 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
- }
- #endif
-
-+#ifdef CONFIG_NONPROMISC_DEVMEM
-+static inline int range_is_allowed(unsigned long pfn, unsigned long size)
++static void ipath_7220_pcie_params(struct ipath_devdata *dd, u32 boardrev)
+{
-+ u64 from = ((u64)pfn) << PAGE_SHIFT;
-+ u64 to = from + size;
-+ u64 cursor = from;
++ u16 linkstat, minwidth, speed;
++ int pos;
+
-+ 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++;
++ 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;
+ }
-+ return 1;
-+}
-+#else
-+static inline int range_is_allowed(unsigned long pfn, unsigned long size)
-+{
-+ return 1;
++
++ 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;
+}
-+#endif
+
-+void __attribute__((weak)) unxlate_dev_mem_ptr(unsigned long phys, void *addr)
++
++/**
++ * 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;
+
- /*
- * 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;
++ dd->ipath_msi_lo = 0; /* used as a flag during reset processing */
+
- /*
- * 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;
++ 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;
+ }
+
-+ unxlate_dev_mem_ptr(p, ptr);
++ 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");
+
- 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;
++ dd->ipath_irq = pdev->irq;
+
- /*
- * 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;
- }
++ /*
++ * We save the cachelinesize also, although it doesn't
++ * really matter.
++ */
++ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE,
++ &dd->ipath_pci_cacheline);
+
-+ unxlate_dev_mem_ptr(p, ptr);
++ /*
++ * 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;
+
- 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;
-+}
++ ipath_7220_pcie_params(dd, boardrev);
+
- #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. */
++ 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;
+}
+
-+void __attribute__((weak))
-+unmap_devmem(unsigned long pfn, unsigned long len, pgprot_t prot)
++static void ipath_init_7220_variables(struct ipath_devdata *dd)
+{
-+ /* nothing. architectures can override. */
-+}
++ /*
++ * setup the register offsets, since they are different for each
++ * chip
++ */
++ dd->ipath_kregs = &ipath_7220_kregs;
++ dd->ipath_cregs = &ipath_7220_cregs;
+
-+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);
-+}
++ /*
++ * 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;
+
-+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);
-+}
++ /*
++ * 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);
+
-+static struct vm_operations_struct mmap_mem_ops = {
-+ .open = mmap_mem_open,
-+ .close = mmap_mem_close
-+};
++ /*
++ * 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;
+
- 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;
++ /* 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;
+
-+ if (!phys_mem_access_prot_allowed(file, vma->vm_pgoff, size,
-+ &vma->vm_page_prot))
-+ return -EINVAL;
++ /* 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;
+
- vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
- size,
- vma->vm_page_prot);
-
-+ vma->vm_ops = &mmap_mem_ops;
++ 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;
+
- /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
- if (remap_pfn_range(vma,
- vma->vm_start,
- vma->vm_pgoff,
- size,
-- vma->vm_page_prot))
-+ vma->vm_page_prot)) {
-+ unmap_devmem(vma->vm_pgoff, size, vma->vm_page_prot);
- return -EAGAIN;
-+ }
- return 0;
- }
-
-diff --git a/drivers/char/misc.c b/drivers/char/misc.c
-index a39101f..4d058da 100644
---- a/drivers/char/misc.c
-+++ b/drivers/char/misc.c
-@@ -232,9 +232,8 @@ int misc_register(struct miscdevice * misc)
- }
-
- /**
-- * __misc_deregister - unregister a miscellaneous device
-+ * misc_deregister - unregister a miscellaneous device
- * @misc: device to unregister
-- * @suspended: to be set if the function is used during suspend/resume
- *
- * Unregister a miscellaneous device that was previously
- * successfully registered with misc_register(). Success
-@@ -242,7 +241,7 @@ int misc_register(struct miscdevice * misc)
- * indicates an error.
- */
-
--int __misc_deregister(struct miscdevice *misc, bool suspended)
-+int misc_deregister(struct miscdevice *misc)
- {
- int i = misc->minor;
-
-@@ -251,11 +250,7 @@ int __misc_deregister(struct miscdevice *misc, bool suspended)
-
- mutex_lock(&misc_mtx);
- list_del(&misc->list);
-- if (suspended)
-- destroy_suspended_device(misc_class,
-- MKDEV(MISC_MAJOR, misc->minor));
-- else
-- device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
-+ device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
- if (i < DYNAMIC_MINORS && i>0) {
- misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
- }
-@@ -264,7 +259,7 @@ int __misc_deregister(struct miscdevice *misc, bool suspended)
- }
-
- EXPORT_SYMBOL(misc_register);
--EXPORT_SYMBOL(__misc_deregister);
-+EXPORT_SYMBOL(misc_deregister);
-
- static int __init misc_init(void)
- {
-diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
-index 279ff50..4e84d23 100644
---- a/drivers/char/pcmcia/synclink_cs.c
-+++ b/drivers/char/pcmcia/synclink_cs.c
-@@ -1225,17 +1225,15 @@ static void ri_change(MGSLPC_INFO *info)
- * irq interrupt number that caused interrupt
- * dev_id device ID supplied during interrupt registration
- */
--static irqreturn_t mgslpc_isr(int irq, void *dev_id)
-+static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
- {
-- MGSLPC_INFO * info = (MGSLPC_INFO *)dev_id;
-+ MGSLPC_INFO *info = dev_id;
- unsigned short isr;
- unsigned char gis, pis;
- int count=0;
-
- if (debug_level >= DEBUG_LEVEL_ISR)
-- printk("mgslpc_isr(%d) entry.\n", irq);
-- if (!info)
-- return IRQ_NONE;
-+ printk("mgslpc_isr(%d) entry.\n", info->irq_level);
-
- if (!(info->p_dev->_locked))
- return IRQ_HANDLED;
-@@ -1327,7 +1325,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id)
-
- if (debug_level >= DEBUG_LEVEL_ISR)
- printk("%s(%d):mgslpc_isr(%d)exit.\n",
-- __FILE__,__LINE__,irq);
-+ __FILE__, __LINE__, info->irq_level);
-
- return IRQ_HANDLED;
- }
-diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c
-index eca2b95..d956dd3 100644
---- a/drivers/char/rio/rioboot.c
-+++ b/drivers/char/rio/rioboot.c
-@@ -35,7 +35,6 @@
- #include <linux/termios.h>
- #include <linux/serial.h>
- #include <linux/vmalloc.h>
--#include <asm/semaphore.h>
- #include <linux/generic_serial.h>
- #include <linux/errno.h>
- #include <linux/interrupt.h>
-diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
-index 7321d00..bf36959 100644
---- a/drivers/char/rio/riocmd.c
-+++ b/drivers/char/rio/riocmd.c
-@@ -41,7 +41,6 @@ static char *_riocmd_c_sccs_ = "@(#)riocmd.c 1.2";
- #include <asm/io.h>
- #include <asm/system.h>
- #include <asm/string.h>
--#include <asm/semaphore.h>
- #include <asm/uaccess.h>
-
- #include <linux/termios.h>
-diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c
-index 7ce7761..d8eb2bc 100644
---- a/drivers/char/rio/rioctrl.c
-+++ b/drivers/char/rio/rioctrl.c
-@@ -40,7 +40,6 @@ static char *_rioctrl_c_sccs_ = "@(#)rioctrl.c 1.3";
- #include <asm/io.h>
- #include <asm/system.h>
- #include <asm/string.h>
--#include <asm/semaphore.h>
- #include <asm/uaccess.h>
-
- #include <linux/termios.h>
-diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c
-index 0794844..add1718 100644
---- a/drivers/char/rio/rioinit.c
-+++ b/drivers/char/rio/rioinit.c
-@@ -40,7 +40,6 @@ static char *_rioinit_c_sccs_ = "@(#)rioinit.c 1.3";
- #include <asm/io.h>
- #include <asm/system.h>
- #include <asm/string.h>
--#include <asm/semaphore.h>
- #include <asm/uaccess.h>
-
- #include <linux/termios.h>
-diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c
-index ebc7634..4734e26 100644
---- a/drivers/char/rio/riointr.c
-+++ b/drivers/char/rio/riointr.c
-@@ -42,7 +42,6 @@ static char *_riointr_c_sccs_ = "@(#)riointr.c 1.2";
- #include <asm/io.h>
- #include <asm/system.h>
- #include <asm/string.h>
--#include <asm/semaphore.h>
- #include <asm/uaccess.h>
-
- #include <linux/termios.h>
-diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c
-index bb498d2..da276ed 100644
---- a/drivers/char/rio/rioparam.c
-+++ b/drivers/char/rio/rioparam.c
-@@ -41,7 +41,6 @@ static char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3";
- #include <asm/io.h>
- #include <asm/system.h>
- #include <asm/string.h>
--#include <asm/semaphore.h>
- #include <asm/uaccess.h>
-
- #include <linux/termios.h>
-diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c
-index a99f3d9..85091ff 100644
---- a/drivers/char/rio/rioroute.c
-+++ b/drivers/char/rio/rioroute.c
-@@ -39,7 +39,6 @@ static char *_rioroute_c_sccs_ = "@(#)rioroute.c 1.3";
- #include <asm/io.h>
- #include <asm/system.h>
- #include <asm/string.h>
--#include <asm/semaphore.h>
- #include <asm/uaccess.h>
-
- #include <linux/termios.h>
-diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c
-index 9b52892..2b24488 100644
---- a/drivers/char/rio/riotable.c
-+++ b/drivers/char/rio/riotable.c
-@@ -42,7 +42,6 @@ static char *_riotable_c_sccs_ = "@(#)riotable.c 1.2";
- #include <asm/io.h>
- #include <asm/system.h>
- #include <asm/string.h>
--#include <asm/semaphore.h>
- #include <asm/uaccess.h>
-
- #include <linux/termios.h>
-diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
-index cfa5436..1cb8580 100644
---- a/drivers/char/rio/riotty.c
-+++ b/drivers/char/rio/riotty.c
-@@ -44,7 +44,6 @@ static char *_riotty_c_sccs_ = "@(#)riotty.c 1.3";
- #include <asm/io.h>
- #include <asm/system.h>
- #include <asm/string.h>
--#include <asm/semaphore.h>
- #include <asm/uaccess.h>
-
- #include <linux/termios.h>
-diff --git a/drivers/char/snsc.h b/drivers/char/snsc.h
-index 8a98169..4be62ed 100644
---- a/drivers/char/snsc.h
-+++ b/drivers/char/snsc.h
-@@ -22,8 +22,8 @@
- #include <linux/kobject.h>
- #include <linux/fs.h>
- #include <linux/cdev.h>
-+#include <linux/semaphore.h>
- #include <asm/sn/types.h>
--#include <asm/semaphore.h>
-
- #define CHUNKSIZE 127
-
-diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
-index 921c6d2..c03ad16 100644
---- a/drivers/char/sonypi.c
-+++ b/drivers/char/sonypi.c
-@@ -1147,7 +1147,7 @@ static int sonypi_acpi_remove(struct acpi_device *device, int type)
- return 0;
- }
-
--const static struct acpi_device_id sonypi_device_ids[] = {
-+static const struct acpi_device_id sonypi_device_ids[] = {
- {"SNY6001", 0},
- {"", 0},
- };
-diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
-index 5ff83df..4b5b5b7 100644
---- a/drivers/char/specialix.c
-+++ b/drivers/char/specialix.c
-@@ -443,8 +443,7 @@ void missed_irq (unsigned long data)
- spin_unlock_irqrestore(&bp->lock, flags);
- if (irq) {
- printk (KERN_INFO "Missed interrupt... Calling int from timer. \n");
-- sx_interrupt (((struct specialix_board *)data)->irq,
-- (void*)data);
-+ sx_interrupt (-1, bp);
- }
- mod_timer(&missed_irq_timer, jiffies + sx_poll);
- }
-@@ -862,23 +861,22 @@ static inline void sx_check_modem(struct specialix_board * bp)
-
-
- /* The main interrupt processing routine */
--static irqreturn_t sx_interrupt(int irq, void *dev_id)
-+static irqreturn_t sx_interrupt(int dummy, void *dev_id)
- {
- unsigned char status;
- unsigned char ack;
-- struct specialix_board *bp;
-+ struct specialix_board *bp = dev_id;
- unsigned long loop = 0;
- int saved_reg;
- unsigned long flags;
-
- func_enter();
-
-- bp = dev_id;
- spin_lock_irqsave(&bp->lock, flags);
-
- dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __FUNCTION__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
- if (!(bp->flags & SX_BOARD_ACTIVE)) {
-- dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", irq);
-+ dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", bp->irq);
- spin_unlock_irqrestore(&bp->lock, flags);
- func_exit();
- return IRQ_NONE;
-diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
-index feac54e..874aaa0 100644
---- a/drivers/char/stallion.c
-+++ b/drivers/char/stallion.c
-@@ -1645,7 +1645,7 @@ static irqreturn_t stl_intr(int irq, void *dev_id)
- {
- struct stlbrd *brdp = dev_id;
-
-- pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq);
-+ pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
-
- return IRQ_RETVAL((* brdp->isr)(brdp));
- }
-diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
-index ddc74d1..a3237d4 100644
---- a/drivers/char/synclink.c
-+++ b/drivers/char/synclink.c
-@@ -1695,20 +1695,16 @@ static void mgsl_isr_transmit_dma( struct mgsl_struct *info )
- *
- * Return Value: None
- */
--static irqreturn_t mgsl_interrupt(int irq, void *dev_id)
-+static irqreturn_t mgsl_interrupt(int dummy, void *dev_id)
- {
-- struct mgsl_struct * info;
-+ struct mgsl_struct *info = dev_id;
- u16 UscVector;
- u16 DmaVector;
-
- if ( debug_level >= DEBUG_LEVEL_ISR )
-- printk("%s(%d):mgsl_interrupt(%d)entry.\n",
-- __FILE__,__LINE__,irq);
-+ printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)entry.\n",
-+ __FILE__, __LINE__, info->irq_level);
-
-- info = (struct mgsl_struct *)dev_id;
-- if (!info)
-- return IRQ_NONE;
--
- spin_lock(&info->irq_spinlock);
-
- for(;;) {
-@@ -1732,8 +1728,8 @@ static irqreturn_t mgsl_interrupt(int irq, void *dev_id)
- mgsl_isr_receive_dma(info);
-
- if ( info->isr_overflow ) {
-- printk(KERN_ERR"%s(%d):%s isr overflow irq=%d\n",
-- __FILE__,__LINE__,info->device_name, irq);
-+ printk(KERN_ERR "%s(%d):%s isr overflow irq=%d\n",
-+ __FILE__, __LINE__, info->device_name, info->irq_level);
- usc_DisableMasterIrqBit(info);
- usc_DisableDmaInterrupts(info,DICR_MASTER);
- break;
-@@ -1755,8 +1751,9 @@ static irqreturn_t mgsl_interrupt(int irq, void *dev_id)
- spin_unlock(&info->irq_spinlock);
-
- if ( debug_level >= DEBUG_LEVEL_ISR )
-- printk("%s(%d):mgsl_interrupt(%d)exit.\n",
-- __FILE__,__LINE__,irq);
-+ printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)exit.\n",
-+ __FILE__, __LINE__, info->irq_level);
++ /*
++ * 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;
+
- 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
++ 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];
++}
+
-+/**
-+ * 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.
++
++/*
++ * 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().
+ */
-+struct tty_driver *tty_find_polling_driver(char *name, int *line)
++static int ipath_reinit_msi(struct ipath_devdata *dd)
+{
-+ struct tty_driver *p, *res = NULL;
-+ int tty_line = 0;
-+ char *str;
++ int ret = 0;
+
-+ 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;
++ int pos;
++ u16 control;
++ if (!dd->ipath_msi_lo) /* Using intX, or init problem */
++ goto bail;
+
-+ if (tty_line >= 0 && tty_line <= p->num && p->poll_init &&
-+ !p->poll_init(p, tty_line, str)) {
++ 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;
+
-+ res = p;
-+ *line = tty_line;
-+ break;
-+ }
++bail:
++ if (!ret) {
++ ipath_dbg("Using INTx, MSI disabled or not configured\n");
++ ipath_enable_intx(dd->pcidev);
++ ret = 1;
+ }
-+ mutex_unlock(&tty_mutex);
++ /*
++ * 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 res;
++ return ret;
+}
-+EXPORT_SYMBOL_GPL(tty_find_polling_driver);
-+#endif
+
- /**
- * tty_check_change - check for POSIX terminal changes
- * @tty: tty to check
-@@ -3850,6 +3892,11 @@ void tty_set_operations(struct tty_driver *driver,
- driver->write_proc = op->write_proc;
- driver->tiocmget = op->tiocmget;
- driver->tiocmset = op->tiocmset;
-+#ifdef CONFIG_CONSOLE_POLL
-+ driver->poll_init = op->poll_init;
-+ driver->poll_get_char = op->poll_get_char;
-+ driver->poll_put_char = op->poll_put_char;
-+#endif
- }
-
-
-diff --git a/drivers/char/xilinx_hwicap/buffer_icap.c b/drivers/char/xilinx_hwicap/buffer_icap.c
-index f577dae..aa7f796 100644
---- a/drivers/char/xilinx_hwicap/buffer_icap.c
-+++ b/drivers/char/xilinx_hwicap/buffer_icap.c
-@@ -74,7 +74,7 @@
-
- /**
- * buffer_icap_get_status - Get the contents of the status register.
-- * @base_address: is the base address of the device
-+ * @drvdata: a pointer to the drvdata.
- *
- * The status register contains the ICAP status and the done bit.
- *
-@@ -88,9 +88,9 @@
- * D1 - Always 1
- * D0 - Done bit
- **/
--static inline u32 buffer_icap_get_status(void __iomem *base_address)
-+u32 buffer_icap_get_status(struct hwicap_drvdata *drvdata)
- {
-- return in_be32(base_address + XHI_STATUS_REG_OFFSET);
-+ return in_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET);
- }
-
- /**
-@@ -117,20 +117,8 @@ static inline u32 buffer_icap_get_bram(void __iomem *base_address,
- **/
- static inline bool buffer_icap_busy(void __iomem *base_address)
- {
-- return (buffer_icap_get_status(base_address) & 1) == XHI_NOT_FINISHED;
--}
--
--/**
-- * buffer_icap_busy - Return true if the icap device is not busy
-- * @base_address: is the base address of the device
-- *
-- * The queries the low order bit of the status register, which
-- * indicates whether the current configuration or readback operation
-- * has completed.
-- **/
--static inline bool buffer_icap_done(void __iomem *base_address)
--{
-- return (buffer_icap_get_status(base_address) & 1) == XHI_FINISHED;
-+ u32 status = in_be32(base_address + XHI_STATUS_REG_OFFSET);
-+ return (status & 1) == XHI_NOT_FINISHED;
- }
-
- /**
-diff --git a/drivers/char/xilinx_hwicap/buffer_icap.h b/drivers/char/xilinx_hwicap/buffer_icap.h
-index 0318495..c5b1840 100644
---- a/drivers/char/xilinx_hwicap/buffer_icap.h
-+++ b/drivers/char/xilinx_hwicap/buffer_icap.h
-@@ -44,8 +44,6 @@
- #include <asm/io.h>
- #include "xilinx_hwicap.h"
-
--void buffer_icap_reset(struct hwicap_drvdata *drvdata);
--
- /* Loads a partial bitstream from system memory. */
- int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,
- u32 Size);
-@@ -54,4 +52,7 @@ int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,
- int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data,
- u32 Size);
-
-+u32 buffer_icap_get_status(struct hwicap_drvdata *drvdata);
-+void buffer_icap_reset(struct hwicap_drvdata *drvdata);
++/*
++ * 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;
+
- #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.
++ 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
+ *
-+ * The status register contains the ICAP status and the done bit.
++ * 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
+ *
-+ * 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)
++ * 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)
+{
-+ u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET);
-+ dev_dbg(drvdata->dev, "Getting status = %x\n", status);
-+ return status;
++ 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);
+}
+
+/**
- * 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;
++ * 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;
++ }
+
+ /*
-+ * Write the data to the FIFO and initiate the transfer of data present
-+ * in the FIFO to the ICAP device.
++ * 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.
+ */
-+ status = drvdata->config->set_configuration(drvdata,
-+ &buffer[0], index);
-+ if (status)
-+ return status;
++ if (ipath_sdma_fetch_arb && (dd->ipath_minrev > 1))
++ dd->ipath_control |= 1<<4;
+
-+ /* 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;
++ dd->ipath_flags |= IPATH_4BYTE_TID;
+
-+ 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
++ /*
++ * 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.
+ */
-+ 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 */
++ dd->ipath_rcvhdrentsize = 24;
++ dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE;
++ dd->ipath_rhf_offset =
++ dd->ipath_rcvhdrentsize - sizeof(u64) / sizeof(u32);
+
- /**
- * hwicap_type_1_read - Generates a Type 1 read packet header.
- * @reg: is the address of the register to be read back.
-diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
-index a522254..1525882 100644
---- a/drivers/clocksource/Makefile
-+++ b/drivers/clocksource/Makefile
-@@ -1,3 +1,4 @@
-+obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
- obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o
- obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o
- obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o
-diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
-new file mode 100644
-index 0000000..f450588
---- /dev/null
-+++ b/drivers/clocksource/tcb_clksrc.c
-@@ -0,0 +1,302 @@
-+#include <linux/init.h>
-+#include <linux/clocksource.h>
-+#include <linux/clockchips.h>
-+#include <linux/interrupt.h>
-+#include <linux/irq.h>
++ 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;
+
-+#include <linux/clk.h>
-+#include <linux/err.h>
-+#include <linux/ioport.h>
-+#include <linux/io.h>
-+#include <linux/platform_device.h>
-+#include <linux/atmel_tc.h>
++ 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);
+
-+/*
-+ * 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...
-+ */
++ /* 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);
+
-+static void __iomem *tcaddr;
++ 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));
+
-+static cycle_t tc_get_cycles(void)
-+{
-+ unsigned long flags;
-+ u32 lower, upper;
++ 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);
+
-+ 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)));
++ 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);
+
-+ raw_local_irq_restore(flags);
-+ return (upper << 16) | lower;
++ return 0;
+}
+
-+static struct clocksource clksrc = {
-+ .name = "tcb_clksrc",
-+ .rating = 200,
-+ .read = tc_get_cycles,
-+ .mask = CLOCKSOURCE_MASK(32),
-+ .shift = 18,
-+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-+};
++/**
++ * 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;
+
-+#ifdef CONFIG_GENERIC_CLOCKEVENTS
++ kinfo->spi_runtime_flags |=
++ IPATH_RUNTIME_PCIE | IPATH_RUNTIME_NODMA_RTAIL |
++ IPATH_RUNTIME_SDMA;
+
-+struct tc_clkevt_device {
-+ struct clock_event_device clkevt;
-+ struct clk *clk;
-+ void __iomem *regs;
-+};
++ return 0;
++}
+
-+static struct tc_clkevt_device *to_tc_clkevt(struct clock_event_device *clkevt)
++static void ipath_7220_free_irq(struct ipath_devdata *dd)
+{
-+ return container_of(clkevt, struct tc_clkevt_device, clkevt);
++ free_irq(dd->ipath_irq, dd);
++ dd->ipath_irq = 0;
+}
+
-+/* 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)
++static struct ipath_message_header *
++ipath_7220_get_msgheader(struct ipath_devdata *dd, __le32 *rhf_addr)
+{
-+ struct tc_clkevt_device *tcd = to_tc_clkevt(d);
-+ void __iomem *regs = tcd->regs;
++ u32 offset = ipath_hdrget_offset(rhf_addr);
+
-+ 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);
-+ }
++ return (struct ipath_message_header *)
++ (rhf_addr - dd->ipath_rhf_offset + offset);
++}
+
-+ switch (m) {
++static void ipath_7220_config_ports(struct ipath_devdata *dd, ushort cfgports)
++{
++ u32 nchipports;
+
-+ /* By not making the gentime core emulate periodic mode on top
-+ * of oneshot, we get lower overhead and improved accuracy.
++ 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).
+ */
-+ case CLOCK_EVT_MODE_PERIODIC:
-+ clk_enable(tcd->clk);
++ 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 */
++}
+
-+ /* 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));
++static int ipath_7220_get_ib_cfg(struct ipath_devdata *dd, int which)
++{
++ int lsb, ret = 0;
++ u64 maskr; /* right-justified mask */
+
-+ /* go go gadget! */
-+ __raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
-+ regs + ATMEL_TC_REG(2, CCR));
++ switch (which) {
++ case IPATH_IB_CFG_HRTBT: /* Get Heartbeat off/enable/auto */
++ lsb = IBA7220_IBC_HRTBT_SHIFT;
++ maskr = IBA7220_IBC_HRTBT_MASK;
+ break;
+
-+ case CLOCK_EVT_MODE_ONESHOT:
-+ clk_enable(tcd->clk);
++ case IPATH_IB_CFG_LWID_ENB: /* Get allowed Link-width */
++ ret = dd->ipath_link_width_enabled;
++ goto done;
+
-+ /* 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));
++ case IPATH_IB_CFG_LWID: /* Get currently active Link-width */
++ ret = dd->ipath_link_width_active;
++ goto done;
+
-+ /* set_next_event() configures and starts the timer */
++ 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;
+
-+ default:
++ 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 tc_next_event(unsigned long delta, struct clock_event_device *d)
++static int ipath_7220_set_ib_cfg(struct ipath_devdata *dd, int which, u32 val)
+{
-+ __raw_writel(delta, tcaddr + ATMEL_TC_REG(2, RC));
++ int lsb, ret = 0, setforce = 0;
++ u64 maskr; /* right-justified mask */
+
-+ /* go go gadget! */
-+ __raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
-+ tcaddr + ATMEL_TC_REG(2, CCR));
-+ return 0;
-+}
++ 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;
+
-+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,
-+ },
-+};
++ 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;
+
-+static irqreturn_t ch2_irq(int irq, void *handle)
-+{
-+ struct tc_clkevt_device *dev = handle;
-+ unsigned int sr;
++ 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;
+
-+ sr = __raw_readl(dev->regs + ATMEL_TC_REG(2, SR));
-+ if (sr & ATMEL_TC_CPCS) {
-+ dev->clkevt.event_handler(&dev->clkevt);
-+ return IRQ_HANDLED;
++ 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;
++}
+
-+ return IRQ_NONE;
++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);
+}
+
-+static struct irqaction tc_irqaction = {
-+ .name = "tc_clkevt",
-+ .flags = IRQF_TIMER | IRQF_DISABLED,
-+ .handler = ch2_irq,
-+};
++/* 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;
++}
+
-+static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
++/*
++ * 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)
+{
-+ struct clk *t2_clk = tc->clk[2];
-+ int irq = tc->irq[2];
++ u64 val, prev_val;
+
-+ clkevt.regs = tc->regs;
-+ clkevt.clk = t2_clk;
-+ tc_irqaction.dev_id = &clkevt;
++ 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);
++}
+
-+ 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;
++/* 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;
+
-+ setup_irq(irq, &tc_irqaction);
++ 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();
++}
+
-+ clockevents_register_device(&clkevt.clkevt);
++/*
++ * _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);
+}
+
-+#else /* !CONFIG_GENERIC_CLOCKEVENTS */
+
-+static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
++
++/*
++ * 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)
+{
-+ /* NOTHING */
++ 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);
+}
+
-+#endif
+
-+static int __init tcb_clksrc_init(void)
++/*
++ * 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)
+{
-+ 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;
++ /*
++ * 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));
++}
+
-+ 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);
++static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
++{
++ int ret = 0;
++ u32 ltstate = ipath_ib_linkstate(dd, ibcs);
+
-+ /* 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;
++ 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;
+
-+ /* remember 32 KiHz clock for later */
-+ if (!divisor) {
-+ clk32k_divisor_idx = i;
-+ continue;
++ 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 */
++ }
+ }
+
-+ 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;
++ 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);
+ }
-+ divided_rate = tmp;
-+ best_divisor_idx = i;
+ }
+
-+ clksrc.mult = clocksource_hz2mult(divided_rate, clksrc.shift);
++ if (!ret)
++ ipath_setup_7220_setextled(dd, ipath_ib_linkstate(dd, ibcs),
++ ltstate);
++ return ret;
++}
+
-+ 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.
++/*
++ * 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.
+ */
-+ clk_enable(tc->clk[1]);
++ 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);
++ }
+
-+ /* 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));
++ if (!(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG))
++ goto done; /* we got there early or told to stop */
+
-+ /* 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));
++ /* 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;
+
-+ /* 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);
++ ipath_toggle_rclkrls(dd);
+
-+ /* and away we go! */
-+ clocksource_register(&clksrc);
++ /* 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;
+
-+ /* channel 2: periodic and oneshot timer support */
-+ setup_clkevents(tc, clk32k_divisor_idx);
++ set_speed_fast(dd, IPATH_IB_SDR);
++ ipath_toggle_rclkrls(dd);
+
-+ return 0;
++ /*
++ * 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);
++ }
+}
-+arch_initcall(tcb_clksrc_init);
-diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
-index 6b658d8..43b71b6 100644
---- a/drivers/crypto/Kconfig
-+++ b/drivers/crypto/Kconfig
-@@ -27,6 +27,7 @@ config CRYPTO_DEV_PADLOCK_AES
- tristate "PadLock driver for AES algorithm"
- depends on CRYPTO_DEV_PADLOCK
- select CRYPTO_BLKCIPHER
-+ select CRYPTO_AES
- help
- Use VIA PadLock for AES algorithm.
-
-@@ -64,6 +65,7 @@ config ZCRYPT
- tristate "Support for PCI-attached cryptographic adapters"
- depends on S390
- select ZCRYPT_MONOLITHIC if ZCRYPT="y"
-+ select HW_RANDOM
- help
- Select this option if you want to use a PCI-attached cryptographic
- adapter like:
-@@ -100,6 +102,19 @@ config CRYPTO_SHA256_S390
- This version of SHA implements a 256 bit hash with 128 bits of
- security against collision attacks.
-
-+config CRYPTO_SHA512_S390
-+ tristate "SHA384 and SHA512 digest algorithm"
-+ depends on S390
-+ select CRYPTO_ALGAPI
-+ help
-+ This is the s390 hardware accelerated implementation of the
-+ SHA512 secure hash standard.
-+
-+ This version of SHA implements a 512 bit hash with 256 bits of
-+ security against collision attacks. The code also includes SHA-384,
-+ a 384 bit hash with 192 bits of security against collision attacks.
+
+
- config CRYPTO_DES_S390
- tristate "DES and Triple DES cipher algorithms"
- depends on S390
-diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
-index 2f3ad3f..bb30eb9 100644
---- a/drivers/crypto/padlock-aes.c
-+++ b/drivers/crypto/padlock-aes.c
-@@ -5,42 +5,6 @@
- *
- * Copyright (c) 2004 Michal Ludvig <michal at logix.cz>
- *
-- * Key expansion routine taken from crypto/aes_generic.c
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * ---------------------------------------------------------------------------
-- * Copyright (c) 2002, Dr Brian Gladman <brg at gladman.me.uk>, Worcester, UK.
-- * All rights reserved.
-- *
-- * LICENSE TERMS
-- *
-- * The free distribution and use of this software in both source and binary
-- * form is allowed (with or without changes) provided that:
-- *
-- * 1. distributions of this source code include the above copyright
-- * notice, this list of conditions and the following disclaimer;
-- *
-- * 2. distributions in binary form include the above copyright
-- * notice, this list of conditions and the following disclaimer
-- * in the documentation and/or other associated materials;
-- *
-- * 3. the copyright holder's name is not used to endorse products
-- * built using this software without specific written permission.
-- *
-- * ALTERNATIVELY, provided that this notice is retained in full, this product
-- * may be distributed under the terms of the GNU General Public License (GPL),
-- * in which case the provisions of the GPL apply INSTEAD OF those given above.
-- *
-- * DISCLAIMER
-- *
-- * This software is provided 'as is' with no explicit or implied warranties
-- * in respect of its properties, including, but not limited to, correctness
-- * and/or fitness for purpose.
-- * ---------------------------------------------------------------------------
- */
-
- #include <crypto/algapi.h>
-@@ -54,9 +18,6 @@
- #include <asm/byteorder.h>
- #include "padlock.h"
-
--#define AES_EXTENDED_KEY_SIZE 64 /* in uint32_t units */
--#define AES_EXTENDED_KEY_SIZE_B (AES_EXTENDED_KEY_SIZE * sizeof(uint32_t))
--
- /* Control word. */
- struct cword {
- unsigned int __attribute__ ((__packed__))
-@@ -70,218 +31,23 @@ struct cword {
-
- /* Whenever making any changes to the following
- * structure *make sure* you keep E, d_data
-- * and cword aligned on 16 Bytes boundaries!!! */
-+ * and cword aligned on 16 Bytes boundaries and
-+ * the Hardware can access 16 * 16 bytes of E and d_data
-+ * (only the first 15 * 16 bytes matter but the HW reads
-+ * more).
++/**
++ * 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.
+ */
- 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 @@
++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.
*
- * 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);
+ * 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);
-@@ -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);
+ /*
+- * 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;
- 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;
+- /* 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;
}
-
-- 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)
+ return pd;
}
- 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)
+-static int init_chip_first(struct ipath_devdata *dd,
+- struct ipath_portdata **pdp)
++static int init_chip_first(struct ipath_devdata *dd)
{
- 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);
+- struct ipath_portdata *pd = NULL;
++ struct ipath_portdata *pd;
+ int ret = 0;
+ u64 val;
-- 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;
++ 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);
- /* 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);
+- 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;
}
--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)
+ * 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)
{
- 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;
-+ }
+ u32 rtmp;
++ int i;
++ unsigned long flags;
+
-+ /* For MPC8349, EOCDI event need to update cookie
-+ * and start the next transfer if it exist.
++ /*
++ * ensure chip does no sends or receives, tail updates, or
++ * pioavail updates while we re-initialize
+ */
-+ 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;
- }
++ 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);
-+ 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);
- }
+- *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);
--#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");
+- 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;
}
--#endif
--#ifdef CONFIG_FSL_DMA_SELFTEST
- static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
+-static void enable_chip(struct ipath_devdata *dd,
+- struct ipath_portdata *pd, int reinit)
++static void enable_chip(struct ipath_devdata *dd, int reinit)
{
- 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);
+ u32 val;
++ u64 rcvmask;
+ unsigned long flags;
+ int i;
-- new->async_tx.ack = 1;
-+ async_tx_ack(&new->async_tx);
+@@ -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);
- hw = new->hw;
- hw->size = copy;
-@@ -264,7 +264,7 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
- }
+ /*
+- * 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);
- 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 */
+@@ -505,16 +519,16 @@ static void enable_chip(struct ipath_devdata *dd,
+ dd->ipath_flags |= IPATH_INITTED;
- /* 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;
+ /*
+- * 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);
- /* 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;
+ /* 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);
/*
-@@ -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);
+ * 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;
- hw = new->hw;
- hw->size = copy;
-@@ -349,7 +349,7 @@ static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx)
+ /*
+ * 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);
}
-
- 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);
+ /* can get counters, stats, etc. */
+ dd->ipath_flags |= IPATH_PRESENT;
}
--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)
+-static int init_housekeeping(struct ipath_devdata *dd,
+- struct ipath_portdata **pdp, int reinit)
++static int init_housekeeping(struct ipath_devdata *dd, int reinit)
{
- 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;
+- char boardn[32];
++ char boardn[40];
+ int ret = 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);
+ /*
+@@ -600,18 +615,9 @@ static int init_housekeeping(struct ipath_devdata *dd,
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear,
+ INFINIPATH_E_RESET);
-@@ -257,8 +255,6 @@ static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+- 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);
- BUG_ON(!seen_current);
+ 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,
-- 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)
+ ipath_dbg("%s", dd->ipath_boardversion);
- 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;
++ if (ret)
++ goto done;
+
-+ spin_lock(&iop_chan->lock);
-+ __iop_adma_slot_cleanup(iop_chan);
-+ spin_unlock(&iop_chan->lock);
++ if (reinit)
++ ret = init_chip_reset(dd);
++ else
++ ret = init_chip_first(dd);
++
+ done:
+ return ret;
}
- 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);
++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);
++}
- 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)
- }
+ /**
+ * 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;
- 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);
+- ret = init_housekeeping(dd, &pd, reinit);
++ ret = init_housekeeping(dd, reinit);
+ if (ret)
+ goto done;
-@@ -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);
+@@ -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);
-@@ -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;
+@@ -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);
}
- 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);
+- 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;
++ }
- 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;
+- 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);
- /* set prep routines based on capability */
-@@ -1232,9 +1227,6 @@ static int __devinit iop_adma_probe(struct platform_device *pdev)
+- /* 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;
}
- 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.
+- (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);
-+config FIREWIRE_OHCI_DEBUG
-+ bool
-+ depends on FIREWIRE_OHCI
-+ default y
++ dd->ipath_f_tidtemplate(dd);
+
- 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.
+ * 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.
*/
-
- 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);
++ 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);
-
- 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;
++ enable_chip(dd, reinit);
-+ 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 (!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 (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));
+- 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;
}
- get_info->rom_length = client->device->config_rom_length * 4;
-+ up_read(&fw_device_rwsem);
-+
-+ if (ret != 0)
-+ return -EFAULT;
++ /* Set up SendDMA if chip supports it */
++ if (dd->ipath_flags & IPATH_HAS_SEND_DMA)
++ ret = setup_sdma(dd);
+
- client->bus_reset_closure = get_info->bus_reset_closure;
- if (get_info->bus_reset != 0) {
- void __user *uptr = u64_to_uptr(get_info->bus_reset);
-diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
-index 870125a..d9c8daf 100644
---- a/drivers/firewire/fw-device.c
-+++ b/drivers/firewire/fw-device.c
-@@ -25,8 +25,9 @@
- #include <linux/device.h>
- #include <linux/delay.h>
- #include <linux/idr.h>
-+#include <linux/string.h>
- #include <linux/rwsem.h>
--#include <asm/semaphore.h>
-+#include <linux/semaphore.h>
- #include <asm/system.h>
- #include <linux/ctype.h>
- #include "fw-transaction.h"
-@@ -160,9 +161,9 @@ static void fw_device_release(struct device *dev)
- * Take the card lock so we don't set this to NULL while a
- * FW_NODE_UPDATED callback is being handled.
- */
-- spin_lock_irqsave(&device->card->lock, flags);
-+ spin_lock_irqsave(&card->lock, flags);
- device->node->data = NULL;
-- spin_unlock_irqrestore(&device->card->lock, flags);
-+ spin_unlock_irqrestore(&card->lock, flags);
-
- fw_node_put(device->node);
- kfree(device->config_rom);
-@@ -195,7 +196,9 @@ show_immediate(struct device *dev, struct device_attribute *dattr, char *buf)
- container_of(dattr, struct config_rom_attribute, attr);
- struct fw_csr_iterator ci;
- u32 *dir;
-- int key, value;
-+ int key, value, ret = -ENOENT;
++ /* 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;
+
-+ 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;
-+ }
+ 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;
+
-+ up_read(&fw_device_rwsem);
-
-- return -ENOENT;
-+ return ret;
- }
++ /*
++ * 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 @@
+ */
- #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;
+ #include <linux/pci.h>
++#include <linux/delay.h>
-+ down_read(&fw_device_rwsem);
+ #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;
+
- 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;
++ /* no flush required, since already in freeze */
++ writel(dwcnt + 1, pbuf);
++ while (--dwcnt)
++ writel(0, pbuf++);
}
- #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)
+ /*
+@@ -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)
{
- 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);
+ 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;
-- return device->config_rom_length * 4;
-+ return length;
+ if (sbuf[0] || sbuf[1] || (piobcnt > 128 && (sbuf[2] || sbuf[3]))) {
+ int i;
+@@ -254,24 +259,20 @@ void ipath_format_hwerrors(u64 hwerrs,
}
- static ssize_t
- guid_show(struct device *dev, struct device_attribute *attr, char *buf)
+ /* 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)
{
- 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);
+ char *ret;
++ u32 state;
-- return snprintf(buf, PAGE_SIZE, "0x%08x%08x\n",
-- device->config_rom[3], device->config_rom[4]);
-+ return ret;
+- 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;
}
- 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;
+@@ -286,103 +287,172 @@ void signal_ib_event(struct ipath_devdata *dd, enum ib_event_type ev)
}
-+#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 void handle_e_ibstatuschanged(struct ipath_devdata *dd,
+- ipath_err_t errs, int noprint)
++ ipath_err_t errs)
{
-- 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;
+- 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);
+
-+ stack = &rom[READ_BIB_ROM_SIZE];
++ 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 */
- device->max_speed = SCODE_100;
+ /*
+- * 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;
- /* 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;
+ /*
+- * 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;
- 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;
-
+ 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);
/*
- * 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++;
+- * 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;
}
-@@ -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;
+- dd->ipath_ibpollcnt = 0; /* some state other than 2 or 3 */
+
-+ 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);
++ dd->ipath_ibpollcnt = 0; /* not poll*, now */
+ ipath_stats.sps_iblink++;
+- if (ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP) {
+
-+ 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);
++ 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;
++ }
++ }
+
- 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 (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]);
+- }
- 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;
+- 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)
+ {
/*
-@@ -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 */
+ * 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,
-@@ -771,6 +822,106 @@ static void fw_device_update(struct work_struct *work)
- device_for_each_child(&device->device, NULL, update_unit);
+ 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;
}
-+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)
++static void handle_sdma_errors(struct ipath_devdata *dd, ipath_err_t errs)
+{
-+ 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;
++ unsigned long flags;
++ int expected;
+
-+ if (i > device->config_rom_length || q != device->config_rom[i])
-+ return REREAD_BIB_CHANGED;
++ 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);
+ }
+
-+ return REREAD_BIB_UNCHANGED;
++ 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 fw_device_refresh(struct work_struct *work)
++static void handle_sdma_intr(struct ipath_devdata *dd, u64 istat)
+{
-+ 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);
++ unsigned long flags;
++ int expected;
+
-+ return;
-+ }
-+ goto give_up;
++ if ((istat & INFINIPATH_I_SDMAINT) &&
++ !test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
++ ipath_sdma_intr(dd);
+
-+ case REREAD_BIB_GONE:
-+ goto gone;
++ 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);
++ }
++}
+
-+ case REREAD_BIB_UNCHANGED:
-+ if (atomic_cmpxchg(&device->state,
-+ FW_DEVICE_INITIALIZING,
-+ FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
-+ goto gone;
++static int handle_hdrq_full(struct ipath_devdata *dd)
++{
++ int chkerrpkts = 0;
++ u32 hd, tl;
++ u32 i;
+
-+ fw_device_update(work);
-+ device->config_rom_retries = 0;
-+ goto out;
++ ipath_stats.sps_hdrqfull++;
++ for (i = 0; i < dd->ipath_cfgports; i++) {
++ struct ipath_portdata *pd = dd->ipath_pd[i];
+
-+ case REREAD_BIB_CHANGED:
-+ break;
-+ }
++ 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;
++ }
+
-+ /*
-+ * 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);
++ /* Skip if user context is not open */
++ if (!pd || !pd->port_cnt)
++ continue;
+
-+ 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);
++ /* 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;
+
-+ return;
++ 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);
+ }
-+ goto give_up;
+ }
+
-+ create_units(device);
++ return chkerrpkts;
++}
+
-+ if (atomic_cmpxchg(&device->state,
-+ FW_DEVICE_INITIALIZING,
-+ FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
-+ goto gone;
+ 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);
+
-+ fw_notify("refreshed device %s\n", device->device.bus_id);
-+ device->config_rom_retries = 0;
-+ goto out;
+ 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;
+
-+ 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);
-+}
+ 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);
++ }
+
- 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;
++ /* 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);
+ }
-+ case FW_NODE_INITIATED_RESET:
-+ device = node->data;
-+ if (device == NULL)
-+ goto create;
+ 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;
+
-+ 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;
++ /* if we're in debug, then don't mask SDMADISABLED msgs */
++ if (ipath_debug & __IPATH_DBG)
++ mask &= ~INFINIPATH_E_SDMADISABLED;
+
- 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 @@
++ ipath_decode_err(dd, msg, sizeof msg, errs & ~mask);
++ } else
+ /* so we don't need if (!noprint) at strlcat's below */
+ *msg = 0;
- #include <linux/fs.h>
- #include <linux/cdev.h>
-+#include <linux/rwsem.h>
- #include <asm/atomic.h>
+@@ -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];
- 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;
- };
+@@ -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;
+ }
--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);
- }
+ /*
+@@ -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);
--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;
+- 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;
}
--static inline struct fw_device *
--fw_device_get(struct fw_device *device)
-+static inline struct fw_device *fw_device_get(struct fw_device *device)
+-
+ /*
+ * 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)
{
- get_device(&device->device);
+ int i, im;
+- __le64 val;
+- unsigned long flags;
++ u64 val;
- return device;
- }
+ /* 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);
--static inline void
--fw_device_put(struct fw_device *device)
-+static inline void fw_device_put(struct fw_device *device)
+ /* 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)
{
- 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);
+ u64 portr;
+ int i;
+@@ -966,12 +1084,13 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
+ * and ipath_poll_next()...
+ */
+ rmb();
+- portr = ((istat >> INFINIPATH_I_RCVAVAIL_SHIFT) &
+- dd->ipath_i_rcvavail_mask)
+- | ((istat >> INFINIPATH_I_RCVURG_SHIFT) &
+- dd->ipath_i_rcvurg_mask);
++ portr = ((istat >> dd->ipath_i_rcvavail_shift) &
++ dd->ipath_i_rcvavail_mask) |
++ ((istat >> dd->ipath_i_rcvurg_shift) &
++ dd->ipath_i_rcvurg_mask);
+ for (i = 1; i < dd->ipath_cfgports; i++) {
+ struct ipath_portdata *pd = dd->ipath_pd[i];
++
+ if (portr & (1 << i) && pd && pd->port_cnt) {
+ if (test_and_clear_bit(IPATH_PORT_WAITING_RCV,
+ &pd->port_flag)) {
+@@ -988,7 +1107,7 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
+ }
+ if (rcvdint) {
+ /* only want to take one interrupt, so turn off the rcv
+- * interrupt for all the ports that we did the wakeup on
++ * interrupt for all the ports that we set the rcv_waiting
+ * (but never for kernel port)
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+@@ -999,12 +1118,11 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
+ irqreturn_t ipath_intr(int irq, void *data)
+ {
+ struct ipath_devdata *dd = data;
+- u32 istat, chk0rcv = 0;
++ u64 istat, chk0rcv = 0;
+ ipath_err_t estat = 0;
+ irqreturn_t ret;
+ static unsigned unexpected = 0;
+- static const u32 port0rbits = (1U<<INFINIPATH_I_RCVAVAIL_SHIFT) |
+- (1U<<INFINIPATH_I_RCVURG_SHIFT);
++ u64 kportrbits;
-+extern struct rw_semaphore fw_device_rwsem;
- extern int fw_cdev_major;
+ ipath_stats.sps_ints++;
-+/*
-+ * 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;
- };
+@@ -1053,17 +1171,17 @@ irqreturn_t ipath_intr(int irq, void *data)
--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);
- }
+ if (unlikely(istat & ~dd->ipath_i_bitsextant))
+ ipath_dev_err(dd,
+- "interrupt with unknown interrupts %x set\n",
+- istat & (u32) ~ dd->ipath_i_bitsextant);
+- else
+- ipath_cdbg(VERBOSE, "intr stat=0x%x\n", istat);
++ "interrupt with unknown interrupts %Lx set\n",
++ istat & ~dd->ipath_i_bitsextant);
++ else if (istat & ~INFINIPATH_I_ERROR) /* errors do own printing */
++ ipath_cdbg(VERBOSE, "intr stat=0x%Lx\n", istat);
-+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,
+- 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);
+ }
- return ctx;
- }
--EXPORT_SYMBOL(fw_iso_context_create);
+ if (istat & INFINIPATH_I_GPIO) {
+@@ -1093,8 +1209,7 @@ irqreturn_t ipath_intr(int irq, void *data)
- void fw_iso_context_destroy(struct fw_iso_context *ctx)
- {
-@@ -134,14 +133,12 @@ void fw_iso_context_destroy(struct fw_iso_context *ctx)
+ 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;
- card->driver->free_iso_context(ctx);
- }
--EXPORT_SYMBOL(fw_iso_context_destroy);
+ /*
+ * 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);
- 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);
+ /*
+- * 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;
+ }
- int
- fw_iso_context_queue(struct fw_iso_context *ctx,
-@@ -153,11 +150,9 @@ fw_iso_context_queue(struct fw_iso_context *ctx,
+- 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);
- return card->driver->queue_iso(ctx, packet, buffer, payload);
- }
--EXPORT_SYMBOL(fw_iso_context_queue);
++ if (istat & (INFINIPATH_I_SDMAINT | INFINIPATH_I_SDMADISABLED))
++ handle_sdma_intr(dd, istat);
++
+ if (istat & INFINIPATH_I_SPIOBUFAVAIL) {
+ unsigned long flags;
- int
- fw_iso_context_stop(struct fw_iso_context *ctx)
- {
- return ctx->card->driver->stop_iso(ctx);
- }
--EXPORT_SYMBOL(fw_iso_context_stop);
-diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
-index ca6d51e..4f02c55 100644
---- a/drivers/firewire/fw-ohci.c
-+++ b/drivers/firewire/fw-ohci.c
-@@ -27,6 +27,7 @@
- #include <linux/kernel.h>
- #include <linux/mm.h>
- #include <linux/module.h>
-+#include <linux/moduleparam.h>
+@@ -1195,7 +1312,10 @@ irqreturn_t ipath_intr(int irq, void *data)
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
+
+- handle_layer_pioavail(dd);
++ if (!(dd->ipath_flags & IPATH_HAS_SEND_DMA))
++ handle_layer_pioavail(dd);
++ else
++ ipath_dbg("unexpected BUFAVAIL intr\n");
+ }
+
+ ret = IRQ_HANDLED;
+diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
+index ecf3f7f..202337a 100644
+--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
++++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
+@@ -1,7 +1,7 @@
+ #ifndef _IPATH_KERNEL_H
+ #define _IPATH_KERNEL_H
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -42,6 +42,8 @@
#include <linux/pci.h>
- #include <linux/spinlock.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/mutex.h>
++#include <linux/list.h>
++#include <linux/scatterlist.h>
+ #include <asm/io.h>
+ #include <rdma/ib_verbs.h>
-@@ -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;
+@@ -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;
+ };
- /*
- * 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)
+ struct sk_buff;
++struct ipath_sge_state;
++struct ipath_verbs_txreq;
- static char ohci_driver_name[] = KBUILD_MODNAME;
+ /*
+ * control information for layered drivers
+@@ -191,6 +197,40 @@ struct ipath_skbinfo {
+ dma_addr_t phys;
+ };
-+#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",
++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 */
+};
-+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-",
++struct ipath_sdma_desc {
++ __le64 qw[2];
+};
+
-+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;
++#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
+
-+ if (evt == OHCI1394_evt_bus_reset) {
-+ printk(KERN_DEBUG "A%c evt_bus_reset, generation %d\n",
-+ dir, (header[2] >> 16) & 0xff);
-+ return;
-+ }
++#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
+
-+ 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;
-+ }
++/* max dwords in small buffer packet */
++#define IPATH_SMALLBUF_DWORDS (dd->ipath_piosize2k >> 2)
+
-+ 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';
-+ }
+ /*
+ * 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;
+
-+ 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);
-+ }
-+}
++ 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;
+
-+#else
++ dma_addr_t ipath_sdma_descq_phys;
++ volatile __le64 *ipath_sdma_head_dma;
++ dma_addr_t ipath_sdma_head_phys;
+
-+#define log_irqs(evt)
-+#define log_selfids(node_id, generation, self_id_count, sid)
-+#define log_ar_at_event(dir, speed, header, evt)
+ unsigned long ipath_ureg_align; /* user register alignment */
+
++ struct delayed_work ipath_autoneg_work;
++ wait_queue_head_t ipath_autoneg_wait;
+
-+#endif /* CONFIG_FIREWIRE_OHCI_DEBUG */
++ /* HoL blocking / user app forward-progress state */
++ unsigned ipath_hol_state;
++ unsigned ipath_hol_next;
++ struct timer_list ipath_hol_timer;
+
- 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;
+ /*
+ * 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;
- 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;
+ /* these are the "32 bit" regs */
-- p.ack = ((status >> 16) & 0x1f) - 16;
-+ p.ack = evt - 16;
- p.speed = (status >> 21) & 0x7;
- p.timestamp = status & 0xffff;
- p.generation = ohci->request_generation;
+@@ -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;
-+ log_ar_at_event('R', p.speed, p.header, evt);
-+
+ /* 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;
/*
- * 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).
+ * 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;
-
-- 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);
+- 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;
-+ log_ar_at_event('T', packet->speed, packet->header, evt);
++ u8 ipath_r_portenable_shift;
++ u8 ipath_r_intravail_shift;
++ u8 ipath_r_tailupd_shift;
++ u8 ipath_r_portcfg_shift;
+
- 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);
++ /* 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;
-+ reg = reg_read(ohci, OHCI1394_SelfIDCount);
-+ if (reg & OHCI1394_SelfIDCount_selfIDError) {
-+ fw_notify("inconsistent self IDs\n");
-+ return;
-+ }
+- /* status check work */
+- struct delayed_work status_work;
+-
/*
- * 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.
+ * 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.
*/
--
-- 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();
+- 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;
- 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);
+@@ -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;
-+ if (ohci->bus_reset_packet_quirk)
-+ ohci->request_generation = generation;
+@@ -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 */
+
- /*
- * 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);
- }
++ /*
++ * 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 */
+ };
-+#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA
-+ reg_write(ohci, OHCI1394_PhyReqFilterHiSet, ~0);
-+ reg_write(ohci, OHCI1394_PhyReqFilterLoSet, ~0);
-+#endif
++/* 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
+
- 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);
++/* 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
+
- 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);
++/* bit combinations that correspond to abort states */
++#define IPATH_SDMA_ABORT_NONE 0
++#define IPATH_SDMA_ABORT_ABORTING (1UL << IPATH_SDMA_ABORTING)
++#define IPATH_SDMA_ABORT_DISARMED ((1UL << IPATH_SDMA_ABORTING) | \
++ (1UL << IPATH_SDMA_DISARMED))
++#define IPATH_SDMA_ABORT_DISABLED ((1UL << IPATH_SDMA_ABORTING) | \
++ (1UL << IPATH_SDMA_DISABLED))
++#define IPATH_SDMA_ABORT_ABORTED ((1UL << IPATH_SDMA_ABORTING) | \
++ (1UL << IPATH_SDMA_DISARMED) | (1UL << IPATH_SDMA_DISABLED))
++#define IPATH_SDMA_ABORT_MASK ((1UL<<IPATH_SDMA_ABORTING) | \
++ (1UL << IPATH_SDMA_DISARMED) | (1UL << IPATH_SDMA_DISABLED))
++
++#define IPATH_SDMA_BUF_NONE 0
++#define IPATH_SDMA_BUF_MASK (1UL<<IPATH_SDMA_LAYERBUF)
++
+ /* Private data for file operations */
+ struct ipath_filedata {
+ struct ipath_portdata *pd;
+ unsigned subport;
+ unsigned tidcursor;
++ struct ipath_user_sdma_queue *pq;
+ };
+ extern struct list_head ipath_dev_list;
+ extern spinlock_t ipath_devs_lock;
+@@ -718,15 +848,15 @@ extern struct ipath_devdata *ipath_lookup(int unit);
+ int ipath_init_chip(struct ipath_devdata *, int);
+ int ipath_enable_wc(struct ipath_devdata *dd);
+ void ipath_disable_wc(struct ipath_devdata *dd);
+-int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp);
++int ipath_count_units(int *npresentp, int *nupp, int *maxportsp);
+ void ipath_shutdown_device(struct ipath_devdata *);
+ void ipath_clear_freeze(struct ipath_devdata *);
- 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);
- }
+ struct file_operations;
+ int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,
+- struct cdev **cdevp, struct class_device **class_devp);
++ struct cdev **cdevp, struct device **devp);
+ void ipath_cdev_cleanup(struct cdev **cdevp,
+- struct class_device **class_devp);
++ struct device **devp);
-+ if (unlikely(event & OHCI1394_regAccessFail))
-+ fw_error("Register access failure - "
-+ "please notify linux1394-devel at lists.sf.net\n");
-+
- if (unlikely(event & OHCI1394_postedWriteErr))
- fw_error("PCI posted write error\n");
+ int ipath_diag_add(struct ipath_devdata *);
+ void ipath_diag_remove(struct ipath_devdata *);
+@@ -741,7 +871,8 @@ struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd, gfp_t);
+ extern int ipath_diag_inuse;
-@@ -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;
+ irqreturn_t ipath_intr(int irq, void *devid);
+-int ipath_decode_err(char *buf, size_t blen, ipath_err_t err);
++int ipath_decode_err(struct ipath_devdata *dd, char *buf, size_t blen,
++ ipath_err_t err);
+ #if __IPATH_INFO || __IPATH_DBG
+ extern const char *ipath_ibcstatus_str[];
+ #endif
+@@ -774,6 +905,13 @@ int ipath_set_lid(struct ipath_devdata *, u32, u8);
+ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
+ void ipath_enable_armlaunch(struct ipath_devdata *);
+ void ipath_disable_armlaunch(struct ipath_devdata *);
++void ipath_hol_down(struct ipath_devdata *);
++void ipath_hol_up(struct ipath_devdata *);
++void ipath_hol_event(unsigned long);
++void ipath_toggle_rclkrls(struct ipath_devdata *);
++void ipath_sd7220_clr_ibpar(struct ipath_devdata *);
++void ipath_set_relock_poll(struct ipath_devdata *, int);
++void ipath_shutdown_relock_poll(struct ipath_devdata *);
- 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;
-+ }
+ /* for use in system calls, where we want to know device type, etc. */
+ #define port_fp(fp) ((struct ipath_filedata *)(fp)->private_data)->pd
+@@ -781,11 +919,15 @@ void ipath_disable_armlaunch(struct ipath_devdata *);
+ ((struct ipath_filedata *)(fp)->private_data)->subport
+ #define tidcursor_fp(fp) \
+ ((struct ipath_filedata *)(fp)->private_data)->tidcursor
++#define user_sdma_queue_fp(fp) \
++ ((struct ipath_filedata *)(fp)->private_data)->pq
- 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);
+ /*
+ * 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 */
- /* 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;
+ /* Bits in GPIO for the added interrupts */
+ #define IPATH_GPIO_PORT0_BIT 2
+@@ -847,13 +1001,18 @@ void ipath_disable_armlaunch(struct ipath_devdata *);
-+ 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 */
- }
+ /* 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);
- static u64
-@@ -2045,17 +2307,9 @@ static const struct fw_card_driver ohci_driver = {
- .stop_iso = ohci_stop_iso,
- };
+ /*
+@@ -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);
--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)
++/* 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)
+{
- 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);
- }
- }
++ return dd->ipath_sdma_descq_cnt -
++ (dd->ipath_sdma_descq_added - dd->ipath_sdma_descq_removed) -
++ 1 - dd->ipath_sdma_desc_nreserved;
+}
+
-+static void ohci_pmac_off(struct pci_dev *dev)
++static inline void ipath_sdma_desc_reserve(struct ipath_devdata *dd, u16 cnt)
+{
-+ 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);
-+ }
-+ }
++ dd->ipath_sdma_desc_nreserved += cnt;
+}
-+#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;
++static inline void ipath_sdma_desc_unreserve(struct ipath_devdata *dd, u16 cnt)
++{
++ dd->ipath_sdma_desc_nreserved -= cnt;
++}
+
- spin_lock_init(&ohci->lock);
+ /*
+ * 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);
- 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);
+ /* 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,
- 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);
+ /*
+ * 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().
+ */
- fw_notify("Removed fw-ohci device.\n");
+ /**
+@@ -1001,6 +1189,27 @@ static inline u32 ipath_get_rcvhdrtail(const struct ipath_portdata *pd)
+ pd->port_rcvhdrtail_kvaddr));
}
- #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)
++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)
{
-- struct fw_ohci *ohci = pci_get_drvdata(pdev);
-+ struct fw_ohci *ohci = pci_get_drvdata(dev);
- int err;
+ return (dd->ipath_flags & IPATH_INTREG_64) ?
+@@ -1029,6 +1238,21 @@ static inline u32 ipath_ib_linktrstate(struct ipath_devdata *dd, u64 ibcs)
+ }
- 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);
+ /*
++ * 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.
+ */
- return 0;
- }
+@@ -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);
--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;
+ /*
+ * 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
--/* PowerMac resume code comes first */
--#ifdef CONFIG_PPC_PMAC
-- if (machine_is(powermac)) {
-- struct device_node *ofn = pci_device_to_OF_node(pdev);
+ extern unsigned ipath_debug; /* debugging bit mask */
-
-- if (ofn)
-- pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
-- }
--#endif /* CONFIG_PPC_PMAC */
+-#define IPATH_MAX_PARITY_ATTEMPTS 10000 /* max times to try recovery */
-
-- 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 */
+-const char *ipath_get_unit_name(int unit);
-
--#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;
- };
++extern unsigned ipath_linkrecovery;
++extern unsigned ipath_mtu4096;
+ extern struct mutex ipath_mutex;
--#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)
+ #define IPATH_DRV_NAME "ib_ipath"
+@@ -1096,7 +1318,7 @@ extern struct mutex ipath_mutex;
-@@ -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;
+ # 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);
+ }
- 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);
++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);
++}
- 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;
+ 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,
+ }
-- 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);
+ dev = to_idev(ibdev);
++ dd = dev->dd;
-- 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)));
+ /* 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;
++ }
-- 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);
+ ret = reply(smp);
- 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;
+@@ -444,19 +461,25 @@ static int recv_subn_set_portinfo(struct ib_smp *smp,
+ ib_dispatch_event(&event);
}
-- fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
--
- init_completion(&orb->done);
- orb->base.callback = complete_management_orb;
+- /* 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);
++ }
-@@ -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);
+- /* 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);
++ }
- 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);
-- }
+ /* 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,
}
- spin_unlock_irqrestore(&card->lock, flags);
- }
-@@ -731,10 +723,8 @@ static void sbp2_conditionally_unblock(struct sbp2_logical_unit *lu)
+
+ /* 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_mr.c b/drivers/infiniband/hw/ipath/ipath_mr.c
+index db4ba92..9d343b7 100644
+--- a/drivers/infiniband/hw/ipath/ipath_mr.c
++++ b/drivers/infiniband/hw/ipath/ipath_mr.c
+@@ -195,7 +195,8 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+ goto bail;
}
- spin_unlock_irqrestore(&card->lock, flags);
-- if (unblock) {
-+ if (unblock)
- scsi_unblock_requests(shost);
-- fw_notify("unblocked %s\n", lu->tgt->bus_id);
-- }
- }
+- umem = ib_umem_get(pd->uobject->context, start, length, mr_access_flags);
++ umem = ib_umem_get(pd->uobject->context, start, length,
++ mr_access_flags, 0);
+ if (IS_ERR(umem))
+ return (void *) umem;
+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 @@
/*
-@@ -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;
+- * 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);
- 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];
+ 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;
- 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;
+ /*
+- * 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;
- fw_device_get(device);
-+ fw_unit_get(unit);
+ 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;
- /* 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)
+- 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);
++ }
- sbp2_init_workarounds(tgt, model, firmware_revision);
+ 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;
-- 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;
+- 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;
}
-@@ -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++;
- }
+- 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;
}
-- 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));
++ /* 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;
- return 0;
+@@ -945,12 +959,20 @@ int ipath_destroy_qp(struct ib_qp *ibqp)
+ /* Stop the sending tasklet. */
+ tasklet_kill(&qp->s_task);
-@@ -1463,8 +1467,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
- orb->done = done;
- orb->cmd = cmd;
++ 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);
-- 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);
+@@ -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);
- 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);
+ 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.
+ */
- if (scsi_sg_count(cmd) && sbp2_map_scatterlist(orb, device, lu) < 0)
- goto out;
++#include <linux/io.h>
++
+ #include "ipath_verbs.h"
+ #include "ipath_kernel.h"
-- 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));
+@@ -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;
- orb->base.callback = complete_command_orb;
-@@ -1519,11 +1514,8 @@ static int sbp2_scsi_slave_alloc(struct scsi_device *sdev)
++ 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;
- sdev->allow_restart = 1;
++ 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);
- /*
-- * Update the dma alignment (minimum alignment requirements for
-- * start and end of DMA transfers) to be a sector
+- * If we can send the ACK, clear the ACK state.
- */
-- 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;
+- if (ipath_verbs_send(qp, &hdr, hwords, NULL, 0) == 0) {
+- dev->n_unicast_xmit++;
+- goto done;
+- }
++ writeq(hwords + 1, piobuf);
- atomic_set(&node->ref_count, 1);
-@@ -289,12 +290,11 @@ static struct fw_node *build_tree(struct fw_card *card,
- beta_repeaters_present = true;
+- /*
+- * 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;
- /*
-- * 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;
+ 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
- update_hop_count(node);
+ /* kr_sendctrl bits */
+ #define INFINIPATH_S_DISARMPIOBUF_SHIFT 16
++#define INFINIPATH_S_UPDTHRESH_SHIFT 24
++#define INFINIPATH_S_UPDTHRESH_MASK 0x1f
-@@ -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;
+ #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
-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
+ #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)
- 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,
- };
+-/* 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)
- 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.
- */
+ /* 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
-+#include <linux/completion.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/init.h>
-@@ -28,7 +29,6 @@
- #include <linux/list.h>
- #include <linux/kthread.h>
- #include <asm/uaccess.h>
--#include <asm/semaphore.h>
+ /* 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
- #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);
+ /*
+ * this is used to print "common" packet errors only when the
+@@ -134,6 +159,17 @@
+ | INFINIPATH_E_RICRC | INFINIPATH_E_RSHORTPKTLEN \
+ | INFINIPATH_E_REBP )
-+struct fw_phy_packet {
-+ struct fw_packet packet;
-+ struct completion done;
-+};
++/* 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)
+
- 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);
+ /* 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
-- card->driver->send_request(card, packet);
-+ complete(&p->done);
- }
+ /* 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
- 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);
+ /* 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
+
-+ 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);
+ #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
--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 */
+-/* combination link status states that we use with some frequency */
+-#define IPATH_IBSTATE_MASK ((INFINIPATH_IBCS_LINKTRAININGSTATE_MASK \
+- << INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) | \
+- (INFINIPATH_IBCS_LINKSTATE_MASK \
+- <<INFINIPATH_IBCS_LINKSTATE_SHIFT))
+-#define IPATH_IBSTATE_INIT ((INFINIPATH_IBCS_L_STATE_INIT \
+- << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+- (INFINIPATH_IBCS_LT_STATE_LINKUP \
+- <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+-#define IPATH_IBSTATE_ARM ((INFINIPATH_IBCS_L_STATE_ARM \
+- << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+- (INFINIPATH_IBCS_LT_STATE_LINKUP \
+- <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+-#define IPATH_IBSTATE_ACTIVE ((INFINIPATH_IBCS_L_STATE_ACTIVE \
+- << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+- (INFINIPATH_IBCS_LT_STATE_LINKUP \
+- <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
- /**
- * 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);
+ /* kr_extstatus bits */
+ #define INFINIPATH_EXTS_SERDESPLLLOCK 0x1
+@@ -286,8 +304,7 @@
+ /* L1 Power down; use with RXDETECT, Otherwise not used on IB side */
+ #define INFINIPATH_SERDC0_L1PWR_DN 0xF0ULL
- 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, };
+-/* kr_xgxsconfig bits */
+-#define INFINIPATH_XGXS_RESET 0x7ULL
++/* common kr_xgxsconfig bits (or safe in all, even if not implemented) */
+ #define INFINIPATH_XGXS_RX_POL_SHIFT 19
+ #define INFINIPATH_XGXS_RX_POL_MASK 0xfULL
- static void
- handle_topology_map(struct fw_card *card, struct fw_request *request,
-@@ -785,7 +784,8 @@ static struct fw_address_handler topology_map = {
+@@ -417,6 +434,29 @@ struct ipath_kregs {
+ ipath_kreg kr_pcieq1serdesconfig0;
+ ipath_kreg kr_pcieq1serdesconfig1;
+ ipath_kreg kr_pcieq1serdesstatus;
++ ipath_kreg kr_hrtbt_guid;
++ ipath_kreg kr_ibcddrctrl;
++ ipath_kreg kr_ibcddrstatus;
++ ipath_kreg kr_jintreload;
++
++ /* send dma related regs */
++ ipath_kreg kr_senddmabase;
++ ipath_kreg kr_senddmalengen;
++ ipath_kreg kr_senddmatail;
++ ipath_kreg kr_senddmahead;
++ ipath_kreg kr_senddmaheadaddr;
++ ipath_kreg kr_senddmabufmask0;
++ ipath_kreg kr_senddmabufmask1;
++ ipath_kreg kr_senddmabufmask2;
++ ipath_kreg kr_senddmastatus;
++
++ /* SerDes related regs (IBA7220-only) */
++ ipath_kreg kr_ibserdesctrl;
++ ipath_kreg kr_ib_epbacc;
++ ipath_kreg kr_ib_epbtrans;
++ ipath_kreg kr_pcie_epbacc;
++ ipath_kreg kr_pcie_epbtrans;
++ ipath_kreg kr_ib_ddsrxeq;
};
- static const struct fw_address_region registers_region =
-- { .start = 0xfffff0000000ull, .end = 0xfffff0000400ull, };
-+ { .start = CSR_REGISTER_BASE,
-+ .end = CSR_REGISTER_BASE | CSR_CONFIG_ROM, };
+ struct ipath_cregs {
+diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
+index a59bdbd..8ac5c1d 100644
+--- a/drivers/infiniband/hw/ipath/ipath_ruc.c
++++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
+@@ -310,7 +310,7 @@ again:
+ switch (wqe->wr.opcode) {
+ case IB_WR_SEND_WITH_IMM:
+ wc.wc_flags = IB_WC_WITH_IMM;
+- wc.imm_data = wqe->wr.imm_data;
++ wc.imm_data = wqe->wr.ex.imm_data;
+ /* FALLTHROUGH */
+ case IB_WR_SEND:
+ if (!ipath_get_rwqe(qp, 0)) {
+@@ -339,7 +339,7 @@ again:
+ goto err;
+ }
+ wc.wc_flags = IB_WC_WITH_IMM;
+- wc.imm_data = wqe->wr.imm_data;
++ wc.imm_data = wqe->wr.ex.imm_data;
+ if (!ipath_get_rwqe(qp, 1))
+ goto rnr_nak;
+ /* FALLTHROUGH */
+@@ -483,14 +483,16 @@ done:
- static void
- 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)
+ static void want_buffer(struct ipath_devdata *dd)
{
-- 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);
+- unsigned long flags;
-
- /*
- * 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.
+- 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;
+
- endmenu
-diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
-index 8d4ebc8..4c91471 100644
---- a/drivers/firmware/Makefile
-+++ b/drivers/firmware/Makefile
-@@ -8,3 +8,5 @@ obj-$(CONFIG_EFI_PCDP) += pcdp.o
- obj-$(CONFIG_DELL_RBU) += dell_rbu.o
- obj-$(CONFIG_DCDBAS) += dcdbas.o
- obj-$(CONFIG_DMIID) += dmi-id.o
-+obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o
-+obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o
-diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
-index 1636806..f235940 100644
---- a/drivers/firmware/dcdbas.c
-+++ b/drivers/firmware/dcdbas.c
-@@ -35,7 +35,6 @@
- #include <linux/types.h>
- #include <linux/mutex.h>
- #include <asm/io.h>
--#include <asm/semaphore.h>
-
- #include "dcdbas.h"
-
-@@ -265,7 +264,7 @@ static int smi_request(struct smi_cmd *smi_cmd)
-
- /* SMI requires CPU 0 */
- old_mask = current->cpus_allowed;
-- set_cpus_allowed(current, cpumask_of_cpu(0));
-+ set_cpus_allowed_ptr(current, &cpumask_of_cpu(0));
- if (smp_processor_id() != 0) {
- dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
- __FUNCTION__);
-@@ -285,7 +284,7 @@ static int smi_request(struct smi_cmd *smi_cmd)
- );
-
- out:
-- set_cpus_allowed(current, old_mask);
-+ set_cpus_allowed_ptr(current, &old_mask);
- return ret;
++ 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/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
+ /**
+diff --git a/drivers/infiniband/hw/ipath/ipath_sd7220.c b/drivers/infiniband/hw/ipath/ipath_sd7220.c
new file mode 100644
-index 0000000..8024e3b
+index 0000000..aa47eb5
--- /dev/null
-+++ b/drivers/firmware/iscsi_ibft.c
-@@ -0,0 +1,982 @@
++++ b/drivers/infiniband/hw/ipath/ipath_sd7220.c
+@@ -0,0 +1,1462 @@
+/*
-+ * Copyright 2007 Red Hat, Inc.
-+ * by Peter Jones <pjones at redhat.com>
-+ * Copyright 2008 IBM, Inc.
-+ * by Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
-+ * Copyright 2008
-+ * by Konrad Rzeszutek <ketuzsezr at darnok.org>
-+ *
-+ * This code exposes the iSCSI Boot Format Table to userland via sysfs.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License v2.0 as published by
-+ * the Free Software Foundation
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * Changelog:
-+ *
-+ * 14 Mar 2008 - Konrad Rzeszutek <ketuzsezr at darnok.org>
-+ * Updated comments and copyrights. (v0.4.9)
-+ *
-+ * 11 Feb 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
-+ * Converted to using ibft_addr. (v0.4.8)
-+ *
-+ * 8 Feb 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
-+ * Combined two functions in one: reserve_ibft_region. (v0.4.7)
-+ *
-+ * 30 Jan 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
-+ * Added logic to handle IPv6 addresses. (v0.4.6)
-+ *
-+ * 25 Jan 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
-+ * Added logic to handle badly not-to-spec iBFT. (v0.4.5)
-+ *
-+ * 4 Jan 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
-+ * Added __init to function declarations. (v0.4.4)
-+ *
-+ * 21 Dec 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
-+ * Updated kobject registration, combined unregister functions in one
-+ * and code and style cleanup. (v0.4.3)
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
-+ * 5 Dec 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
-+ * Added end-markers to enums and re-organized kobject registration. (v0.4.2)
++ * 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:
+ *
-+ * 4 Dec 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
-+ * Created 'device' sysfs link to the NIC and style cleanup. (v0.4.1)
++ * Redistribution and use in source and binary forms, with or
++ * without modification, are permitted provided that the following
++ * conditions are met:
+ *
-+ * 28 Nov 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
-+ * Added sysfs-ibft documentation, moved 'find_ibft' function to
-+ * in its own file and added text attributes for every struct field. (v0.4)
++ * - Redistributions of source code must retain the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer.
+ *
-+ * 21 Nov 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
-+ * Added text attributes emulating OpenFirmware /proc/device-tree naming.
-+ * Removed binary /sysfs interface (v0.3)
++ * - 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.
+ *
-+ * 29 Aug 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
-+ * Added functionality in setup.c to reserve iBFT region. (v0.2)
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++/*
++ * This file contains all of the code that is specific to the SerDes
++ * on the InfiniPath 7220 chip.
++ */
++
++#include <linux/pci.h>
++#include <linux/delay.h>
++
++#include "ipath_kernel.h"
++#include "ipath_registers.h"
++#include "ipath_7220.h"
++
++/*
++ * The IBSerDesMappTable is a memory that holds values to be stored in
++ * various SerDes registers by IBC. It is not part of the normal kregs
++ * map and is used in exactly one place, hence the #define below.
++ */
++#define KR_IBSerDesMappTable (0x94000 / (sizeof(uint64_t)))
++
++/*
++ * Below used for sdnum parameter, selecting one of the two sections
++ * used for PCIe, or the single SerDes used for IB.
++ */
++#define PCIE_SERDES0 0
++#define PCIE_SERDES1 1
++
++/*
++ * The EPB requires addressing in a particular form. EPB_LOC() is intended
++ * to make #definitions a little more readable.
++ */
++#define EPB_ADDR_SHF 8
++#define EPB_LOC(chn, elt, reg) \
++ (((elt & 0xf) | ((chn & 7) << 4) | ((reg & 0x3f) << 9)) << \
++ EPB_ADDR_SHF)
++#define EPB_IB_QUAD0_CS_SHF (25)
++#define EPB_IB_QUAD0_CS (1U << EPB_IB_QUAD0_CS_SHF)
++#define EPB_IB_UC_CS_SHF (26)
++#define EPB_PCIE_UC_CS_SHF (27)
++#define EPB_GLOBAL_WR (1U << (EPB_ADDR_SHF + 8))
++
++/* Forward declarations. */
++static int ipath_sd7220_reg_mod(struct ipath_devdata *dd, int sdnum, u32 loc,
++ u32 data, u32 mask);
++static int ibsd_mod_allchnls(struct ipath_devdata *dd, int loc, int val,
++ int mask);
++static int ipath_sd_trimdone_poll(struct ipath_devdata *dd);
++static void ipath_sd_trimdone_monitor(struct ipath_devdata *dd,
++ const char *where);
++static int ipath_sd_setvals(struct ipath_devdata *dd);
++static int ipath_sd_early(struct ipath_devdata *dd);
++static int ipath_sd_dactrim(struct ipath_devdata *dd);
++/* Set the registers that IBC may muck with to their default "preset" values */
++int ipath_sd7220_presets(struct ipath_devdata *dd);
++static int ipath_internal_presets(struct ipath_devdata *dd);
++/* Tweak the register (CMUCTRL5) that contains the TRIMSELF controls */
++static int ipath_sd_trimself(struct ipath_devdata *dd, int val);
++static int epb_access(struct ipath_devdata *dd, int sdnum, int claim);
++
++void ipath_set_relock_poll(struct ipath_devdata *dd, int ibup);
++
++/*
++ * Below keeps track of whether the "once per power-on" initialization has
++ * been done, because uC code Version 1.32.17 or higher allows the uC to
++ * be reset at will, and Automatic Equalization may require it. So the
++ * state of the reset "pin", as reflected in was_reset parameter to
++ * ipath_sd7220_init() is no longer valid. Instead, we check for the
++ * actual uC code having been loaded.
++ */
++static int ipath_ibsd_ucode_loaded(struct ipath_devdata *dd)
++{
++ if (!dd->serdes_first_init_done && (ipath_sd7220_ib_vfy(dd) > 0))
++ dd->serdes_first_init_done = 1;
++ return dd->serdes_first_init_done;
++}
++
++/* repeat #define for local use. "Real" #define is in ipath_iba7220.c */
++#define INFINIPATH_HWE_IB_UC_MEMORYPARITYERR 0x0000004000000000ULL
++#define IB_MPREG5 (EPB_LOC(6, 0, 0xE) | (1L << EPB_IB_UC_CS_SHF))
++#define IB_MPREG6 (EPB_LOC(6, 0, 0xF) | (1U << EPB_IB_UC_CS_SHF))
++#define UC_PAR_CLR_D 8
++#define UC_PAR_CLR_M 0xC
++#define IB_CTRL2(chn) (EPB_LOC(chn, 7, 3) | EPB_IB_QUAD0_CS)
++#define START_EQ1(chan) EPB_LOC(chan, 7, 0x27)
++
++void ipath_sd7220_clr_ibpar(struct ipath_devdata *dd)
++{
++ int ret;
++
++ /* clear, then re-enable parity errs */
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6,
++ UC_PAR_CLR_D, UC_PAR_CLR_M);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed clearing IBSerDes Parity err\n");
++ goto bail;
++ }
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0,
++ UC_PAR_CLR_M);
++
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ udelay(4);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
++ INFINIPATH_HWE_IB_UC_MEMORYPARITYERR);
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++bail:
++ return;
++}
++
++/*
++ * After a reset or other unusual event, the epb interface may need
++ * to be re-synchronized, between the host and the uC.
++ * returns <0 for failure to resync within IBSD_RESYNC_TRIES (not expected)
++ */
++#define IBSD_RESYNC_TRIES 3
++#define IB_PGUDP(chn) (EPB_LOC((chn), 2, 1) | EPB_IB_QUAD0_CS)
++#define IB_CMUDONE(chn) (EPB_LOC((chn), 7, 0xF) | EPB_IB_QUAD0_CS)
++
++static int ipath_resync_ibepb(struct ipath_devdata *dd)
++{
++ int ret, pat, tries, chn;
++ u32 loc;
++
++ ret = -1;
++ chn = 0;
++ for (tries = 0; tries < (4 * IBSD_RESYNC_TRIES); ++tries) {
++ loc = IB_PGUDP(chn);
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, 0, 0);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed read in resync\n");
++ continue;
++ }
++ if (ret != 0xF0 && ret != 0x55 && tries == 0)
++ ipath_dev_err(dd, "unexpected pattern in resync\n");
++ pat = ret ^ 0xA5; /* alternate F0 and 55 */
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, pat, 0xFF);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed write in resync\n");
++ continue;
++ }
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, 0, 0);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed re-read in resync\n");
++ continue;
++ }
++ if (ret != pat) {
++ ipath_dev_err(dd, "Failed compare1 in resync\n");
++ continue;
++ }
++ loc = IB_CMUDONE(chn);
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, 0, 0);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed CMUDONE rd in resync\n");
++ continue;
++ }
++ if ((ret & 0x70) != ((chn << 4) | 0x40)) {
++ ipath_dev_err(dd, "Bad CMUDONE value %02X, chn %d\n",
++ ret, chn);
++ continue;
++ }
++ if (++chn == 4)
++ break; /* Success */
++ }
++ ipath_cdbg(VERBOSE, "Resync in %d tries\n", tries);
++ return (ret > 0) ? 0 : ret;
++}
++
++/*
++ * Localize the stuff that should be done to change IB uC reset
++ * returns <0 for errors.
++ */
++static int ipath_ibsd_reset(struct ipath_devdata *dd, int assert_rst)
++{
++ u64 rst_val;
++ int ret = 0;
++ unsigned long flags;
++
++ rst_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibserdesctrl);
++ if (assert_rst) {
++ /*
++ * Vendor recommends "interrupting" uC before reset, to
++ * minimize possible glitches.
++ */
++ spin_lock_irqsave(&dd->ipath_sdepb_lock, flags);
++ epb_access(dd, IB_7220_SERDES, 1);
++ rst_val |= 1ULL;
++ /* Squelch possible parity error from _asserting_ reset */
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
++ dd->ipath_hwerrmask &
++ ~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibserdesctrl, rst_val);
++ /* flush write, delay to ensure it took effect */
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ udelay(2);
++ /* once it's reset, can remove interrupt */
++ epb_access(dd, IB_7220_SERDES, -1);
++ spin_unlock_irqrestore(&dd->ipath_sdepb_lock, flags);
++ } else {
++ /*
++ * Before we de-assert reset, we need to deal with
++ * possible glitch on the Parity-error line.
++ * Suppress it around the reset, both in chip-level
++ * hwerrmask and in IB uC control reg. uC will allow
++ * it again during startup.
++ */
++ u64 val;
++ rst_val &= ~(1ULL);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
++ dd->ipath_hwerrmask &
++ ~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR);
++
++ ret = ipath_resync_ibepb(dd);
++ if (ret < 0)
++ ipath_dev_err(dd, "unable to re-sync IB EPB\n");
++
++ /* set uC control regs to suppress parity errs */
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG5, 1, 1);
++ if (ret < 0)
++ goto bail;
++ /* IB uC code past Version 1.32.17 allow suppression of wdog */
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0x80,
++ 0x80);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed to set WDOG disable\n");
++ goto bail;
++ }
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibserdesctrl, rst_val);
++ /* flush write, delay for startup */
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ udelay(1);
++ /* clear, then re-enable parity errs */
++ ipath_sd7220_clr_ibpar(dd);
++ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
++ if (val & INFINIPATH_HWE_IB_UC_MEMORYPARITYERR) {
++ ipath_dev_err(dd, "IBUC Parity still set after RST\n");
++ dd->ipath_hwerrmask &=
++ ~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR;
++ }
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
++ dd->ipath_hwerrmask);
++ }
++
++bail:
++ return ret;
++}
++
++static void ipath_sd_trimdone_monitor(struct ipath_devdata *dd,
++ const char *where)
++{
++ int ret, chn, baduns;
++ u64 val;
++
++ if (!where)
++ where = "?";
++
++ /* give time for reset to settle out in EPB */
++ udelay(2);
++
++ ret = ipath_resync_ibepb(dd);
++ if (ret < 0)
++ ipath_dev_err(dd, "not able to re-sync IB EPB (%s)\n", where);
++
++ /* Do "sacrificial read" to get EPB in sane state after reset */
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(0), 0, 0);
++ if (ret < 0)
++ ipath_dev_err(dd, "Failed TRIMDONE 1st read, (%s)\n", where);
++
++ /* Check/show "summary" Trim-done bit in IBCStatus */
++ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
++ if (val & (1ULL << 11))
++ ipath_cdbg(VERBOSE, "IBCS TRIMDONE set (%s)\n", where);
++ else
++ ipath_dev_err(dd, "IBCS TRIMDONE clear (%s)\n", where);
++
++ udelay(2);
++
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0x80, 0x80);
++ if (ret < 0)
++ ipath_dev_err(dd, "Failed Dummy RMW, (%s)\n", where);
++ udelay(10);
++
++ baduns = 0;
++
++ for (chn = 3; chn >= 0; --chn) {
++ /* Read CTRL reg for each channel to check TRIMDONE */
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
++ IB_CTRL2(chn), 0, 0);
++ if (ret < 0)
++ ipath_dev_err(dd, "Failed checking TRIMDONE, chn %d"
++ " (%s)\n", chn, where);
++
++ if (!(ret & 0x10)) {
++ int probe;
++ baduns |= (1 << chn);
++ ipath_dev_err(dd, "TRIMDONE cleared on chn %d (%02X)."
++ " (%s)\n", chn, ret, where);
++ probe = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
++ IB_PGUDP(0), 0, 0);
++ ipath_dev_err(dd, "probe is %d (%02X)\n",
++ probe, probe);
++ probe = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
++ IB_CTRL2(chn), 0, 0);
++ ipath_dev_err(dd, "re-read: %d (%02X)\n",
++ probe, probe);
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
++ IB_CTRL2(chn), 0x10, 0x10);
++ if (ret < 0)
++ ipath_dev_err(dd,
++ "Err on TRIMDONE rewrite1\n");
++ }
++ }
++ for (chn = 3; chn >= 0; --chn) {
++ /* Read CTRL reg for each channel to check TRIMDONE */
++ if (baduns & (1 << chn)) {
++ ipath_dev_err(dd,
++ "Reseting TRIMDONE on chn %d (%s)\n",
++ chn, where);
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
++ IB_CTRL2(chn), 0x10, 0x10);
++ if (ret < 0)
++ ipath_dev_err(dd, "Failed re-setting "
++ "TRIMDONE, chn %d (%s)\n",
++ chn, where);
++ }
++ }
++}
++
++/*
++ * Below is portion of IBA7220-specific bringup_serdes() that actually
++ * deals with registers and memory within the SerDes itself.
++ * Post IB uC code version 1.32.17, was_reset being 1 is not really
++ * informative, so we double-check.
++ */
++int ipath_sd7220_init(struct ipath_devdata *dd, int was_reset)
++{
++ int ret = 1; /* default to failure */
++ int first_reset;
++ int val_stat;
++
++ if (!was_reset) {
++ /* entered with reset not asserted, we need to do it */
++ ipath_ibsd_reset(dd, 1);
++ ipath_sd_trimdone_monitor(dd, "Driver-reload");
++ }
++
++ /* Substitute our deduced value for was_reset */
++ ret = ipath_ibsd_ucode_loaded(dd);
++ if (ret < 0) {
++ ret = 1;
++ goto done;
++ }
++ first_reset = !ret; /* First reset if IBSD uCode not yet loaded */
++
++ /*
++ * Alter some regs per vendor latest doc, reset-defaults
++ * are not right for IB.
++ */
++ ret = ipath_sd_early(dd);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed to set IB SERDES early defaults\n");
++ ret = 1;
++ goto done;
++ }
++
++ /*
++ * Set DAC manual trim IB.
++ * We only do this once after chip has been reset (usually
++ * same as once per system boot).
++ */
++ if (first_reset) {
++ ret = ipath_sd_dactrim(dd);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed IB SERDES DAC trim\n");
++ ret = 1;
++ goto done;
++ }
++ }
++
++ /*
++ * Set various registers (DDS and RXEQ) that will be
++ * controlled by IBC (in 1.2 mode) to reasonable preset values
++ * Calling the "internal" version avoids the "check for needed"
++ * and "trimdone monitor" that might be counter-productive.
++ */
++ ret = ipath_internal_presets(dd);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed to set IB SERDES presets\n");
++ ret = 1;
++ goto done;
++ }
++ ret = ipath_sd_trimself(dd, 0x80);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed to set IB SERDES TRIMSELF\n");
++ ret = 1;
++ goto done;
++ }
++
++ /* Load image, then try to verify */
++ ret = 0; /* Assume success */
++ if (first_reset) {
++ int vfy;
++ int trim_done;
++ ipath_dbg("SerDes uC was reset, reloading PRAM\n");
++ ret = ipath_sd7220_ib_load(dd);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed to load IB SERDES image\n");
++ ret = 1;
++ goto done;
++ }
++
++ /* Loaded image, try to verify */
++ vfy = ipath_sd7220_ib_vfy(dd);
++ if (vfy != ret) {
++ ipath_dev_err(dd, "SERDES PRAM VFY failed\n");
++ ret = 1;
++ goto done;
++ }
++ /*
++ * Loaded and verified. Almost good...
++ * hold "success" in ret
++ */
++ ret = 0;
++
++ /*
++ * Prev steps all worked, continue bringup
++ * De-assert RESET to uC, only in first reset, to allow
++ * trimming.
++ *
++ * Since our default setup sets START_EQ1 to
++ * PRESET, we need to clear that for this very first run.
++ */
++ ret = ibsd_mod_allchnls(dd, START_EQ1(0), 0, 0x38);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed clearing START_EQ1\n");
++ ret = 1;
++ goto done;
++ }
++
++ ipath_ibsd_reset(dd, 0);
++ /*
++ * If this is not the first reset, trimdone should be set
++ * already.
++ */
++ trim_done = ipath_sd_trimdone_poll(dd);
++ /*
++ * Whether or not trimdone succeeded, we need to put the
++ * uC back into reset to avoid a possible fight with the
++ * IBC state-machine.
++ */
++ ipath_ibsd_reset(dd, 1);
++
++ if (!trim_done) {
++ ipath_dev_err(dd, "No TRIMDONE seen\n");
++ ret = 1;
++ goto done;
++ }
++
++ ipath_sd_trimdone_monitor(dd, "First-reset");
++ /* Remember so we do not re-do the load, dactrim, etc. */
++ dd->serdes_first_init_done = 1;
++ }
++ /*
++ * Setup for channel training and load values for
++ * RxEq and DDS in tables used by IBC in IB1.2 mode
++ */
++
++ val_stat = ipath_sd_setvals(dd);
++ if (val_stat < 0)
++ ret = 1;
++done:
++ /* start relock timer regardless, but start at 1 second */
++ ipath_set_relock_poll(dd, -1);
++ return ret;
++}
++
++#define EPB_ACC_REQ 1
++#define EPB_ACC_GNT 0x100
++#define EPB_DATA_MASK 0xFF
++#define EPB_RD (1ULL << 24)
++#define EPB_TRANS_RDY (1ULL << 31)
++#define EPB_TRANS_ERR (1ULL << 30)
++#define EPB_TRANS_TRIES 5
++
++/*
++ * query, claim, release ownership of the EPB (External Parallel Bus)
++ * for a specified SERDES.
++ * the "claim" parameter is >0 to claim, <0 to release, 0 to query.
++ * Returns <0 for errors, >0 if we had ownership, else 0.
++ */
++static int epb_access(struct ipath_devdata *dd, int sdnum, int claim)
++{
++ u16 acc;
++ u64 accval;
++ int owned = 0;
++ u64 oct_sel = 0;
++
++ switch (sdnum) {
++ case IB_7220_SERDES :
++ /*
++ * The IB SERDES "ownership" is fairly simple. A single each
++ * request/grant.
++ */
++ acc = dd->ipath_kregs->kr_ib_epbacc;
++ break;
++ case PCIE_SERDES0 :
++ case PCIE_SERDES1 :
++ /* PCIe SERDES has two "octants", need to select which */
++ acc = dd->ipath_kregs->kr_pcie_epbacc;
++ oct_sel = (2 << (sdnum - PCIE_SERDES0));
++ break;
++ default :
++ return 0;
++ }
++
++ /* Make sure any outstanding transaction was seen */
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ udelay(15);
++
++ accval = ipath_read_kreg32(dd, acc);
++
++ owned = !!(accval & EPB_ACC_GNT);
++ if (claim < 0) {
++ /* Need to release */
++ u64 pollval;
++ /*
++ * The only writeable bits are the request and CS.
++ * Both should be clear
++ */
++ u64 newval = 0;
++ ipath_write_kreg(dd, acc, newval);
++ /* First read after write is not trustworthy */
++ pollval = ipath_read_kreg32(dd, acc);
++ udelay(5);
++ pollval = ipath_read_kreg32(dd, acc);
++ if (pollval & EPB_ACC_GNT)
++ owned = -1;
++ } else if (claim > 0) {
++ /* Need to claim */
++ u64 pollval;
++ u64 newval = EPB_ACC_REQ | oct_sel;
++ ipath_write_kreg(dd, acc, newval);
++ /* First read after write is not trustworthy */
++ pollval = ipath_read_kreg32(dd, acc);
++ udelay(5);
++ pollval = ipath_read_kreg32(dd, acc);
++ if (!(pollval & EPB_ACC_GNT))
++ owned = -1;
++ }
++ return owned;
++}
++
++/*
++ * Lemma to deal with race condition of write..read to epb regs
++ */
++static int epb_trans(struct ipath_devdata *dd, u16 reg, u64 i_val, u64 *o_vp)
++{
++ int tries;
++ u64 transval;
++
++
++ ipath_write_kreg(dd, reg, i_val);
++ /* Throw away first read, as RDY bit may be stale */
++ transval = ipath_read_kreg64(dd, reg);
++
++ for (tries = EPB_TRANS_TRIES; tries; --tries) {
++ transval = ipath_read_kreg32(dd, reg);
++ if (transval & EPB_TRANS_RDY)
++ break;
++ udelay(5);
++ }
++ if (transval & EPB_TRANS_ERR)
++ return -1;
++ if (tries > 0 && o_vp)
++ *o_vp = transval;
++ return tries;
++}
++
++/**
+ *
-+ * 27 Aug 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
-+ * First version exposing iBFT data via a binary /sysfs. (v0.1)
++ * 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;
++}
+
-+#include <linux/blkdev.h>
-+#include <linux/capability.h>
-+#include <linux/ctype.h>
-+#include <linux/device.h>
-+#include <linux/err.h>
-+#include <linux/init.h>
-+#include <linux/iscsi_ibft.h>
-+#include <linux/limits.h>
-+#include <linux/module.h>
-+#include <linux/pci.h>
-+#include <linux/slab.h>
-+#include <linux/stat.h>
-+#include <linux/string.h>
-+#include <linux/types.h>
++#define PROG_CHUNK 64
+
-+#define IBFT_ISCSI_VERSION "0.4.9"
-+#define IBFT_ISCSI_DATE "2008-Mar-14"
++int ipath_sd7220_prog_ld(struct ipath_devdata *dd, int sdnum,
++ u8 *img, int len, int offset)
++{
++ int cnt, sofar, req;
+
-+MODULE_AUTHOR("Peter Jones <pjones at redhat.com> and \
-+Konrad Rzeszutek <ketuzsezr at darnok.org>");
-+MODULE_DESCRIPTION("sysfs interface to BIOS iBFT information");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION(IBFT_ISCSI_VERSION);
++ 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;
++}
+
-+struct ibft_hdr {
-+ u8 id;
-+ u8 version;
-+ u16 length;
-+ u8 index;
-+ u8 flags;
-+} __attribute__((__packed__));
++#define VFY_CHUNK 64
++#define SD_PRAM_ERROR_LIMIT 42
+
-+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__));
++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];
+
-+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__));
++ 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;
++}
+
-+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__));
++/* IRQ not set up at this point in init, so we poll. */
++#define IB_SERDES_TRIM_DONE (1ULL << 11)
++#define TRIM_TMO (30)
+
-+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__));
++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)
+
+/*
-+ * 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,
++ * 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)
+};
+
+/*
-+ * We do not support the other types, hence the usage of NULL.
-+ * This maps to the enum ibft_id.
++ * Next, values related to Receive Equalization.
++ * In comments, FDR (Full) is IB DDR, HDR (Half) is IB SDR
+ */
-+static const char *ibft_id_names[] =
-+ {NULL, NULL, "initiator", "ethernet%d", "target%d", NULL, NULL};
++/* 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)} }
+
-+/*
-+ * 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,
-+};
++#define RXEQ_VAL_ALL(elt, adr, val) \
++ {RXEQ_INIT_RDESC((elt), (adr)), {(val), (val), (val), (val)} }
+
-+static const char *ibft_eth_properties[] =
-+ {"index", "flags", "ip-addr", "subnet-mask", "origin", "gateway",
-+ "primary-dns", "secondary-dns", "dhcp", "vlan", "mac", "hostname",
-+ NULL};
++#define RXEQ_SDR_DFELTH 0
++#define RXEQ_SDR_TLTH 0
++#define RXEQ_SDR_G1CNT_Z1CNT 0x11
++#define RXEQ_SDR_ZCNT 23
+
-+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 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 */
+};
+
-+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};
++/* 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)
+
-+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 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;
+
-+static const char *ibft_initiator_properties[] =
-+ {"index", "flags", "isns-server", "slp-server", "pri-radius-server",
-+ "sec-radius-server", "initiator-name", NULL};
++ taddr = dd->ipath_kregbase + KR_IBSerDesMappTable;
++ iaddr = dd->ipath_kregbase + dd->ipath_kregs->kr_ib_ddsrxeq;
+
-+/*
-+ * The kobject and attribute structures.
-+ */
++ /*
++ * 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);
+
-+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;
-+};
++ /*
++ * 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) */
+
-+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;
-+};
++ /*
++ * 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;
+
-+static LIST_HEAD(ibft_attr_list);
-+static LIST_HEAD(ibft_kobject_list);
++ /* 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;
++}
+
-+static const char nulls[16];
++#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;
++}
+
+/*
-+ * Helper functions to parse data properly.
++ * 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 ssize_t sprintf_ipaddr(char *buf, u8 *ip)
++static int ibsd_mod_allchnls(struct ipath_devdata *dd, int loc, int val,
++ int mask)
+{
-+ char *str = buf;
++ int ret = -1;
++ int chnl;
+
-+ 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 {
++ if (loc & EPB_GLOBAL_WR) {
+ /*
-+ * IPv6
++ * 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.
+ */
-+ 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]));
++ 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;
+ }
-+ 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);
++ /* 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;
+}
+
+/*
-+ * Helper function to verify the IBFT header.
++ * 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 ibft_verify_hdr(char *t, struct ibft_hdr *hdr, int id, int length)
++static int set_dds_vals(struct ipath_devdata *dd, struct dds_init *ddi)
+{
-+ 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;
-+ }
++ int ret;
++ int idx, reg, data;
++ uint32_t regmap;
+
-+ return 0;
++ 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;
+}
+
-+static void ibft_release(struct kobject *kobj)
++/*
++ * 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)
+{
-+ struct ibft_kobject *ibft =
-+ container_of(kobj, struct ibft_kobject, kobj);
-+ kfree(ibft);
++ 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;
+}
+
+/*
-+ * Routines for parsing the iBFT data to be human readable.
++ * 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.
+ */
-+ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
-+ struct ibft_attribute *attr,
-+ char *buf)
++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)
+{
-+ struct ibft_initiator *initiator = entry->initiator;
-+ void *ibft_loc = entry->header;
-+ char *str = buf;
++ int ret = 0;
+
-+ if (!initiator)
-+ return 0;
++ ret = set_dds_vals(dd, dds_init_vals + DDS_3M);
+
-+ 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;
-+ }
++ 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;
++}
+
-+ return str - buf;
++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;
+}
+
-+ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
-+ struct ibft_attribute *attr,
-+ char *buf)
++static int ipath_sd_trimself(struct ipath_devdata *dd, int val)
+{
-+ struct ibft_nic *nic = entry->nic;
-+ void *ibft_loc = entry->header;
-+ char *str = buf;
-+ char *mac;
-+ int val;
++ return ibsd_sto_noisy(dd, CMUCTRL5, val, 0xFF);
++}
+
-+ if (!nic)
-+ return 0;
++static int ipath_sd_early(struct ipath_devdata *dd)
++{
++ int ret = -1; /* Default failed */
++ int chnl;
+
-+ 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;
++ 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;
++}
+
-+ return str - buf;
-+};
++#define BACTRL(chnl) EPB_LOC(chnl, 6, 0x0E)
++#define LDOUTCTRL1(chnl) EPB_LOC(chnl, 7, 6)
++#define RXHSSTATUS(chnl) EPB_LOC(chnl, 6, 0xF)
+
-+ssize_t ibft_attr_show_target(struct ibft_kobject *entry,
-+ struct ibft_attribute *attr,
-+ char *buf)
++static int ipath_sd_dactrim(struct ipath_devdata *dd)
+{
-+ struct ibft_tgt *tgt = entry->tgt;
-+ void *ibft_loc = entry->header;
-+ char *str = buf;
-+ int i;
-+
-+ if (!tgt)
-+ return 0;
++ int ret = -1; /* Default failed */
++ int chnl;
+
-+ 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;
++ 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;
++}
+
-+ return str - buf;
++#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);
+}
+
+/*
-+ * The routine called for all sysfs attributes.
++ * 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
+ */
-+static ssize_t ibft_show_attribute(struct kobject *kobj,
-+ struct attribute *attr,
-+ char *buf)
++void ipath_shutdown_relock_poll(struct ipath_devdata *dd)
+{
-+ 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;
++ 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);
++ }
++}
+
-+ if (!capable(CAP_SYS_ADMIN))
-+ return -EACCES;
++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");
+
-+ if (ibft_attr->show)
-+ ret = ibft_attr->show(dev, ibft_attr, str);
++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;
+
-+ return ret;
-+}
++ 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;
++ }
+
-+static struct sysfs_ops ibft_attr_ops = {
-+ .show = ibft_show_attribute,
-+};
++ /*
++ * 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);
+
-+static struct kobj_type ibft_ktype = {
-+ .release = ibft_release,
-+ .sysfs_ops = &ibft_attr_ops,
-+};
++ 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;
+
-+static struct kset *ibft_kset;
++ 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);
++ }
++}
+
-+static int __init ibft_check_device(void)
++void ipath_set_relock_poll(struct ipath_devdata *dd, int ibup)
+{
-+ int len;
-+ u8 *pos;
-+ u8 csum = 0;
-+
-+ len = ibft_addr->length;
++ struct ipath_relock *irp = &dd->ipath_relock_singleton;
+
-+ /* 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;
++ 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);
++ }
+ }
-+ 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;
-+ }
+diff --git a/drivers/infiniband/hw/ipath/ipath_sd7220_img.c b/drivers/infiniband/hw/ipath/ipath_sd7220_img.c
+new file mode 100644
+index 0000000..5ef59da
+--- /dev/null
++++ b/drivers/infiniband/hw/ipath/ipath_sd7220_img.c
+@@ -0,0 +1,1082 @@
++/*
++ * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses. You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ * Redistribution and use in source and binary forms, with or
++ * without modification, are permitted provided that the following
++ * conditions are met:
++ *
++ * - Redistributions of source code must retain the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer.
++ *
++ * - Redistributions in binary form must reproduce the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer in the documentation and/or other materials
++ * provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++/*
++ * This file contains the memory image from the vendor, to be copied into
++ * the IB SERDES of the IBA7220 during initialization.
++ * The file also includes the two functions which use this image.
++ */
++#include <linux/pci.h>
++#include <linux/delay.h>
++
++#include "ipath_kernel.h"
++#include "ipath_registers.h"
++#include "ipath_7220.h"
++
++static unsigned char ipath_sd7220_ib_img[] = {
++/*0000*/0x02, 0x0A, 0x29, 0x02, 0x0A, 0x87, 0xE5, 0xE6,
++ 0x30, 0xE6, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F,
++/*0010*/0x00, 0xE5, 0xE2, 0x30, 0xE4, 0x04, 0x7E, 0x01,
++ 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x5F, 0x60, 0x08,
++/*0020*/0x53, 0xF9, 0xF7, 0xE4, 0xF5, 0xFE, 0x80, 0x08,
++ 0x7F, 0x0A, 0x12, 0x17, 0x31, 0x12, 0x0E, 0xA2,
++/*0030*/0x75, 0xFC, 0x08, 0xE4, 0xF5, 0xFD, 0xE5, 0xE7,
++ 0x20, 0xE7, 0x03, 0x43, 0xF9, 0x08, 0x22, 0x00,
++/*0040*/0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x75,
++ 0x51, 0x01, 0xE4, 0xF5, 0x52, 0xF5, 0x53, 0xF5,
++/*0050*/0x52, 0xF5, 0x7E, 0x7F, 0x04, 0x02, 0x04, 0x38,
++ 0xC2, 0x36, 0x05, 0x52, 0xE5, 0x52, 0xD3, 0x94,
++/*0060*/0x0C, 0x40, 0x05, 0x75, 0x52, 0x01, 0xD2, 0x36,
++ 0x90, 0x07, 0x0C, 0x74, 0x07, 0xF0, 0xA3, 0x74,
++/*0070*/0xFF, 0xF0, 0xE4, 0xF5, 0x0C, 0xA3, 0xF0, 0x90,
++ 0x07, 0x14, 0xF0, 0xA3, 0xF0, 0x75, 0x0B, 0x20,
++/*0080*/0xF5, 0x09, 0xE4, 0xF5, 0x08, 0xE5, 0x08, 0xD3,
++ 0x94, 0x30, 0x40, 0x03, 0x02, 0x04, 0x04, 0x12,
++/*0090*/0x00, 0x06, 0x15, 0x0B, 0xE5, 0x08, 0x70, 0x04,
++ 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x09,
++/*00A0*/0x70, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00,
++ 0xEE, 0x5F, 0x60, 0x05, 0x12, 0x18, 0x71, 0xD2,
++/*00B0*/0x35, 0x53, 0xE1, 0xF7, 0xE5, 0x08, 0x45, 0x09,
++ 0xFF, 0xE5, 0x0B, 0x25, 0xE0, 0x25, 0xE0, 0x24,
++/*00C0*/0x83, 0xF5, 0x82, 0xE4, 0x34, 0x07, 0xF5, 0x83,
++ 0xEF, 0xF0, 0x85, 0xE2, 0x20, 0xE5, 0x52, 0xD3,
++/*00D0*/0x94, 0x01, 0x40, 0x0D, 0x12, 0x19, 0xF3, 0xE0,
++ 0x54, 0xA0, 0x64, 0x40, 0x70, 0x03, 0x02, 0x03,
++/*00E0*/0xFB, 0x53, 0xF9, 0xF8, 0x90, 0x94, 0x70, 0xE4,
++ 0xF0, 0xE0, 0xF5, 0x10, 0xAF, 0x09, 0x12, 0x1E,
++/*00F0*/0xB3, 0xAF, 0x08, 0xEF, 0x44, 0x08, 0xF5, 0x82,
++ 0x75, 0x83, 0x80, 0xE0, 0xF5, 0x29, 0xEF, 0x44,
++/*0100*/0x07, 0x12, 0x1A, 0x3C, 0xF5, 0x22, 0x54, 0x40,
++ 0xD3, 0x94, 0x00, 0x40, 0x1E, 0xE5, 0x29, 0x54,
++/*0110*/0xF0, 0x70, 0x21, 0x12, 0x19, 0xF3, 0xE0, 0x44,
++ 0x80, 0xF0, 0xE5, 0x22, 0x54, 0x30, 0x65, 0x08,
++/*0120*/0x70, 0x09, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xBF,
++ 0xF0, 0x80, 0x09, 0x12, 0x19, 0xF3, 0x74, 0x40,
++/*0130*/0xF0, 0x02, 0x03, 0xFB, 0x12, 0x1A, 0x12, 0x75,
++ 0x83, 0xAE, 0x74, 0xFF, 0xF0, 0xAF, 0x08, 0x7E,
++/*0140*/0x00, 0xEF, 0x44, 0x07, 0xF5, 0x82, 0xE0, 0xFD,
++ 0xE5, 0x0B, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x81,
++/*0150*/0xF5, 0x82, 0xE4, 0x34, 0x07, 0xF5, 0x83, 0xED,
++ 0xF0, 0x90, 0x07, 0x0E, 0xE0, 0x04, 0xF0, 0xEF,
++/*0160*/0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0x98, 0xE0,
++ 0xF5, 0x28, 0x12, 0x1A, 0x23, 0x40, 0x0C, 0x12,
++/*0170*/0x19, 0xF3, 0xE0, 0x44, 0x01, 0x12, 0x1A, 0x32,
++ 0x02, 0x03, 0xF6, 0xAF, 0x08, 0x7E, 0x00, 0x74,
++/*0180*/0x80, 0xCD, 0xEF, 0xCD, 0x8D, 0x82, 0xF5, 0x83,
++ 0xE0, 0x30, 0xE0, 0x0A, 0x12, 0x19, 0xF3, 0xE0,
++/*0190*/0x44, 0x20, 0xF0, 0x02, 0x03, 0xFB, 0x12, 0x19,
++ 0xF3, 0xE0, 0x54, 0xDF, 0xF0, 0xEE, 0x44, 0xAE,
++/*01A0*/0x12, 0x1A, 0x43, 0x30, 0xE4, 0x03, 0x02, 0x03,
++ 0xFB, 0x74, 0x9E, 0x12, 0x1A, 0x05, 0x20, 0xE0,
++/*01B0*/0x03, 0x02, 0x03, 0xFB, 0x8F, 0x82, 0x8E, 0x83,
++ 0xE0, 0x20, 0xE0, 0x03, 0x02, 0x03, 0xFB, 0x12,
++/*01C0*/0x19, 0xF3, 0xE0, 0x44, 0x10, 0xF0, 0xE5, 0xE3,
++ 0x20, 0xE7, 0x08, 0xE5, 0x08, 0x12, 0x1A, 0x3A,
++/*01D0*/0x44, 0x04, 0xF0, 0xAF, 0x08, 0x7E, 0x00, 0xEF,
++ 0x12, 0x1A, 0x3A, 0x20, 0xE2, 0x34, 0x12, 0x19,
++/*01E0*/0xF3, 0xE0, 0x44, 0x08, 0xF0, 0xE5, 0xE4, 0x30,
++ 0xE6, 0x04, 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00,
++/*01F0*/0xE5, 0x7E, 0xC3, 0x94, 0x04, 0x50, 0x04, 0x7C,
++ 0x01, 0x80, 0x02, 0x7C, 0x00, 0xEC, 0x4D, 0x60,
++/*0200*/0x05, 0xC2, 0x35, 0x02, 0x03, 0xFB, 0xEE, 0x44,
++ 0xD2, 0x12, 0x1A, 0x43, 0x44, 0x40, 0xF0, 0x02,
++/*0210*/0x03, 0xFB, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xF7,
++ 0xF0, 0x12, 0x1A, 0x12, 0x75, 0x83, 0xD2, 0xE0,
++/*0220*/0x54, 0xBF, 0xF0, 0x90, 0x07, 0x14, 0xE0, 0x04,
++ 0xF0, 0xE5, 0x7E, 0x70, 0x03, 0x75, 0x7E, 0x01,
++/*0230*/0xAF, 0x08, 0x7E, 0x00, 0x12, 0x1A, 0x23, 0x40,
++ 0x12, 0x12, 0x19, 0xF3, 0xE0, 0x44, 0x01, 0x12,
++/*0240*/0x19, 0xF2, 0xE0, 0x54, 0x02, 0x12, 0x1A, 0x32,
++ 0x02, 0x03, 0xFB, 0x12, 0x19, 0xF3, 0xE0, 0x44,
++/*0250*/0x02, 0x12, 0x19, 0xF2, 0xE0, 0x54, 0xFE, 0xF0,
++ 0xC2, 0x35, 0xEE, 0x44, 0x8A, 0x8F, 0x82, 0xF5,
++/*0260*/0x83, 0xE0, 0xF5, 0x17, 0x54, 0x8F, 0x44, 0x40,
++ 0xF0, 0x74, 0x90, 0xFC, 0xE5, 0x08, 0x44, 0x07,
++/*0270*/0xFD, 0xF5, 0x82, 0x8C, 0x83, 0xE0, 0x54, 0x3F,
++ 0x90, 0x07, 0x02, 0xF0, 0xE0, 0x54, 0xC0, 0x8D,
++/*0280*/0x82, 0x8C, 0x83, 0xF0, 0x74, 0x92, 0x12, 0x1A,
++ 0x05, 0x90, 0x07, 0x03, 0x12, 0x1A, 0x19, 0x74,
++/*0290*/0x82, 0x12, 0x1A, 0x05, 0x90, 0x07, 0x04, 0x12,
++ 0x1A, 0x19, 0x74, 0xB4, 0x12, 0x1A, 0x05, 0x90,
++/*02A0*/0x07, 0x05, 0x12, 0x1A, 0x19, 0x74, 0x94, 0xFE,
++ 0xE5, 0x08, 0x44, 0x06, 0x12, 0x1A, 0x0A, 0xF5,
++/*02B0*/0x10, 0x30, 0xE0, 0x04, 0xD2, 0x37, 0x80, 0x02,
++ 0xC2, 0x37, 0xE5, 0x10, 0x54, 0x7F, 0x8F, 0x82,
++/*02C0*/0x8E, 0x83, 0xF0, 0x30, 0x44, 0x30, 0x12, 0x1A,
++ 0x03, 0x54, 0x80, 0xD3, 0x94, 0x00, 0x40, 0x04,
++/*02D0*/0xD2, 0x39, 0x80, 0x02, 0xC2, 0x39, 0x8F, 0x82,
++ 0x8E, 0x83, 0xE0, 0x44, 0x80, 0xF0, 0x12, 0x1A,
++/*02E0*/0x03, 0x54, 0x40, 0xD3, 0x94, 0x00, 0x40, 0x04,
++ 0xD2, 0x3A, 0x80, 0x02, 0xC2, 0x3A, 0x8F, 0x82,
++/*02F0*/0x8E, 0x83, 0xE0, 0x44, 0x40, 0xF0, 0x74, 0x92,
++ 0xFE, 0xE5, 0x08, 0x44, 0x06, 0x12, 0x1A, 0x0A,
++/*0300*/0x30, 0xE7, 0x04, 0xD2, 0x38, 0x80, 0x02, 0xC2,
++ 0x38, 0x8F, 0x82, 0x8E, 0x83, 0xE0, 0x54, 0x7F,
++/*0310*/0xF0, 0x12, 0x1E, 0x46, 0xE4, 0xF5, 0x0A, 0x20,
++ 0x03, 0x02, 0x80, 0x03, 0x30, 0x43, 0x03, 0x12,
++/*0320*/0x19, 0x95, 0x20, 0x02, 0x02, 0x80, 0x03, 0x30,
++ 0x42, 0x03, 0x12, 0x0C, 0x8F, 0x30, 0x30, 0x06,
++/*0330*/0x12, 0x19, 0x95, 0x12, 0x0C, 0x8F, 0x12, 0x0D,
++ 0x47, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xFB, 0xF0,
++/*0340*/0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40, 0x46, 0x43,
++ 0xE1, 0x08, 0x12, 0x19, 0xF3, 0xE0, 0x44, 0x04,
++/*0350*/0xF0, 0xE5, 0xE4, 0x20, 0xE7, 0x2A, 0x12, 0x1A,
++ 0x12, 0x75, 0x83, 0xD2, 0xE0, 0x54, 0x08, 0xD3,
++/*0360*/0x94, 0x00, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02,
++ 0x7F, 0x00, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40,
++/*0370*/0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF,
++ 0x5E, 0x60, 0x05, 0x12, 0x1D, 0xD7, 0x80, 0x17,
++/*0380*/0x12, 0x1A, 0x12, 0x75, 0x83, 0xD2, 0xE0, 0x44,
++ 0x08, 0xF0, 0x02, 0x03, 0xFB, 0x12, 0x1A, 0x12,
++/*0390*/0x75, 0x83, 0xD2, 0xE0, 0x54, 0xF7, 0xF0, 0x12,
++ 0x1E, 0x46, 0x7F, 0x08, 0x12, 0x17, 0x31, 0x74,
++/*03A0*/0x8E, 0xFE, 0x12, 0x1A, 0x12, 0x8E, 0x83, 0xE0,
++ 0xF5, 0x10, 0x54, 0xFE, 0xF0, 0xE5, 0x10, 0x44,
++/*03B0*/0x01, 0xFF, 0xE5, 0x08, 0xFD, 0xED, 0x44, 0x07,
++ 0xF5, 0x82, 0xEF, 0xF0, 0xE5, 0x10, 0x54, 0xFE,
++/*03C0*/0xFF, 0xED, 0x44, 0x07, 0xF5, 0x82, 0xEF, 0x12,
++ 0x1A, 0x11, 0x75, 0x83, 0x86, 0xE0, 0x44, 0x10,
++/*03D0*/0x12, 0x1A, 0x11, 0xE0, 0x44, 0x10, 0xF0, 0x12,
++ 0x19, 0xF3, 0xE0, 0x54, 0xFD, 0x44, 0x01, 0xFF,
++/*03E0*/0x12, 0x19, 0xF3, 0xEF, 0x12, 0x1A, 0x32, 0x30,
++ 0x32, 0x0C, 0xE5, 0x08, 0x44, 0x08, 0xF5, 0x82,
++/*03F0*/0x75, 0x83, 0x82, 0x74, 0x05, 0xF0, 0xAF, 0x0B,
++ 0x12, 0x18, 0xD7, 0x74, 0x10, 0x25, 0x08, 0xF5,
++/*0400*/0x08, 0x02, 0x00, 0x85, 0x05, 0x09, 0xE5, 0x09,
++ 0xD3, 0x94, 0x07, 0x50, 0x03, 0x02, 0x00, 0x82,
++/*0410*/0xE5, 0x7E, 0xD3, 0x94, 0x00, 0x40, 0x04, 0x7F,
++ 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x7E, 0xC3,
++/*0420*/0x94, 0xFA, 0x50, 0x04, 0x7E, 0x01, 0x80, 0x02,
++ 0x7E, 0x00, 0xEE, 0x5F, 0x60, 0x02, 0x05, 0x7E,
++/*0430*/0x30, 0x35, 0x0B, 0x43, 0xE1, 0x01, 0x7F, 0x09,
++ 0x12, 0x17, 0x31, 0x02, 0x00, 0x58, 0x53, 0xE1,
++/*0440*/0xFE, 0x02, 0x00, 0x58, 0x8E, 0x6A, 0x8F, 0x6B,
++ 0x8C, 0x6C, 0x8D, 0x6D, 0x75, 0x6E, 0x01, 0x75,
++/*0450*/0x6F, 0x01, 0x75, 0x70, 0x01, 0xE4, 0xF5, 0x73,
++ 0xF5, 0x74, 0xF5, 0x75, 0x90, 0x07, 0x2F, 0xF0,
++/*0460*/0xF5, 0x3C, 0xF5, 0x3E, 0xF5, 0x46, 0xF5, 0x47,
++ 0xF5, 0x3D, 0xF5, 0x3F, 0xF5, 0x6F, 0xE5, 0x6F,
++/*0470*/0x70, 0x0F, 0xE5, 0x6B, 0x45, 0x6A, 0x12, 0x07,
++ 0x2A, 0x75, 0x83, 0x80, 0x74, 0x3A, 0xF0, 0x80,
++/*0480*/0x09, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x80, 0x74,
++ 0x1A, 0xF0, 0xE4, 0xF5, 0x6E, 0xC3, 0x74, 0x3F,
++/*0490*/0x95, 0x6E, 0xFF, 0x12, 0x08, 0x65, 0x75, 0x83,
++ 0x82, 0xEF, 0xF0, 0x12, 0x1A, 0x4D, 0x12, 0x08,
++/*04A0*/0xC6, 0xE5, 0x33, 0xF0, 0x12, 0x08, 0xFA, 0x12,
++ 0x08, 0xB1, 0x40, 0xE1, 0xE5, 0x6F, 0x70, 0x0B,
++/*04B0*/0x12, 0x07, 0x2A, 0x75, 0x83, 0x80, 0x74, 0x36,
++ 0xF0, 0x80, 0x09, 0x12, 0x07, 0x2A, 0x75, 0x83,
++/*04C0*/0x80, 0x74, 0x16, 0xF0, 0x75, 0x6E, 0x01, 0x12,
++ 0x07, 0x2A, 0x75, 0x83, 0xB4, 0xE5, 0x6E, 0xF0,
++/*04D0*/0x12, 0x1A, 0x4D, 0x74, 0x3F, 0x25, 0x6E, 0xF5,
++ 0x82, 0xE4, 0x34, 0x00, 0xF5, 0x83, 0xE5, 0x33,
++/*04E0*/0xF0, 0x74, 0xBF, 0x25, 0x6E, 0xF5, 0x82, 0xE4,
++ 0x34, 0x00, 0x12, 0x08, 0xB1, 0x40, 0xD8, 0xE4,
++/*04F0*/0xF5, 0x70, 0xF5, 0x46, 0xF5, 0x47, 0xF5, 0x6E,
++ 0x12, 0x08, 0xFA, 0xF5, 0x83, 0xE0, 0xFE, 0x12,
++/*0500*/0x08, 0xC6, 0xE0, 0x7C, 0x00, 0x24, 0x00, 0xFF,
++ 0xEC, 0x3E, 0xFE, 0xAD, 0x3B, 0xD3, 0xEF, 0x9D,
++/*0510*/0xEE, 0x9C, 0x50, 0x04, 0x7B, 0x01, 0x80, 0x02,
++ 0x7B, 0x00, 0xE5, 0x70, 0x70, 0x04, 0x7A, 0x01,
++/*0520*/0x80, 0x02, 0x7A, 0x00, 0xEB, 0x5A, 0x60, 0x06,
++ 0x85, 0x6E, 0x46, 0x75, 0x70, 0x01, 0xD3, 0xEF,
++/*0530*/0x9D, 0xEE, 0x9C, 0x50, 0x04, 0x7F, 0x01, 0x80,
++ 0x02, 0x7F, 0x00, 0xE5, 0x70, 0xB4, 0x01, 0x04,
++/*0540*/0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF, 0x5E,
++ 0x60, 0x03, 0x85, 0x6E, 0x47, 0x05, 0x6E, 0xE5,
++/*0550*/0x6E, 0x64, 0x7F, 0x70, 0xA3, 0xE5, 0x46, 0x60,
++ 0x05, 0xE5, 0x47, 0xB4, 0x7E, 0x03, 0x85, 0x46,
++/*0560*/0x47, 0xE5, 0x6F, 0x70, 0x08, 0x85, 0x46, 0x76,
++ 0x85, 0x47, 0x77, 0x80, 0x0E, 0xC3, 0x74, 0x7F,
++/*0570*/0x95, 0x46, 0xF5, 0x78, 0xC3, 0x74, 0x7F, 0x95,
++ 0x47, 0xF5, 0x79, 0xE5, 0x6F, 0x70, 0x37, 0xE5,
++/*0580*/0x46, 0x65, 0x47, 0x70, 0x0C, 0x75, 0x73, 0x01,
++ 0x75, 0x74, 0x01, 0xF5, 0x3C, 0xF5, 0x3D, 0x80,
++/*0590*/0x35, 0xE4, 0xF5, 0x4E, 0xC3, 0xE5, 0x47, 0x95,
++ 0x46, 0xF5, 0x3C, 0xC3, 0x13, 0xF5, 0x71, 0x25,
++/*05A0*/0x46, 0xF5, 0x72, 0xC3, 0x94, 0x3F, 0x40, 0x05,
++ 0xE4, 0xF5, 0x3D, 0x80, 0x40, 0xC3, 0x74, 0x3F,
++/*05B0*/0x95, 0x72, 0xF5, 0x3D, 0x80, 0x37, 0xE5, 0x46,
++ 0x65, 0x47, 0x70, 0x0F, 0x75, 0x73, 0x01, 0x75,
++/*05C0*/0x75, 0x01, 0xF5, 0x3E, 0xF5, 0x3F, 0x75, 0x4E,
++ 0x01, 0x80, 0x22, 0xE4, 0xF5, 0x4E, 0xC3, 0xE5,
++/*05D0*/0x47, 0x95, 0x46, 0xF5, 0x3E, 0xC3, 0x13, 0xF5,
++ 0x71, 0x25, 0x46, 0xF5, 0x72, 0xD3, 0x94, 0x3F,
++/*05E0*/0x50, 0x05, 0xE4, 0xF5, 0x3F, 0x80, 0x06, 0xE5,
++ 0x72, 0x24, 0xC1, 0xF5, 0x3F, 0x05, 0x6F, 0xE5,
++/*05F0*/0x6F, 0xC3, 0x94, 0x02, 0x50, 0x03, 0x02, 0x04,
++ 0x6E, 0xE5, 0x6D, 0x45, 0x6C, 0x70, 0x02, 0x80,
++/*0600*/0x04, 0xE5, 0x74, 0x45, 0x75, 0x90, 0x07, 0x2F,
++ 0xF0, 0x7F, 0x01, 0xE5, 0x3E, 0x60, 0x04, 0xE5,
++/*0610*/0x3C, 0x70, 0x14, 0xE4, 0xF5, 0x3C, 0xF5, 0x3D,
++ 0xF5, 0x3E, 0xF5, 0x3F, 0x12, 0x08, 0xD2, 0x70,
++/*0620*/0x04, 0xF0, 0x02, 0x06, 0xA4, 0x80, 0x7A, 0xE5,
++ 0x3C, 0xC3, 0x95, 0x3E, 0x40, 0x07, 0xE5, 0x3C,
++/*0630*/0x95, 0x3E, 0xFF, 0x80, 0x06, 0xC3, 0xE5, 0x3E,
++ 0x95, 0x3C, 0xFF, 0xE5, 0x76, 0xD3, 0x95, 0x79,
++/*0640*/0x40, 0x05, 0x85, 0x76, 0x7A, 0x80, 0x03, 0x85,
++ 0x79, 0x7A, 0xE5, 0x77, 0xC3, 0x95, 0x78, 0x50,
++/*0650*/0x05, 0x85, 0x77, 0x7B, 0x80, 0x03, 0x85, 0x78,
++ 0x7B, 0xE5, 0x7B, 0xD3, 0x95, 0x7A, 0x40, 0x30,
++/*0660*/0xE5, 0x7B, 0x95, 0x7A, 0xF5, 0x3C, 0xF5, 0x3E,
++ 0xC3, 0xE5, 0x7B, 0x95, 0x7A, 0x90, 0x07, 0x19,
++/*0670*/0xF0, 0xE5, 0x3C, 0xC3, 0x13, 0xF5, 0x71, 0x25,
++ 0x7A, 0xF5, 0x72, 0xC3, 0x94, 0x3F, 0x40, 0x05,
++/*0680*/0xE4, 0xF5, 0x3D, 0x80, 0x1F, 0xC3, 0x74, 0x3F,
++ 0x95, 0x72, 0xF5, 0x3D, 0xF5, 0x3F, 0x80, 0x14,
++/*0690*/0xE4, 0xF5, 0x3C, 0xF5, 0x3E, 0x90, 0x07, 0x19,
++ 0xF0, 0x12, 0x08, 0xD2, 0x70, 0x03, 0xF0, 0x80,
++/*06A0*/0x03, 0x74, 0x01, 0xF0, 0x12, 0x08, 0x65, 0x75,
++ 0x83, 0xD0, 0xE0, 0x54, 0x0F, 0xFE, 0xAD, 0x3C,
++/*06B0*/0x70, 0x02, 0x7E, 0x07, 0xBE, 0x0F, 0x02, 0x7E,
++ 0x80, 0xEE, 0xFB, 0xEF, 0xD3, 0x9B, 0x74, 0x80,
++/*06C0*/0xF8, 0x98, 0x40, 0x1F, 0xE4, 0xF5, 0x3C, 0xF5,
++ 0x3E, 0x12, 0x08, 0xD2, 0x70, 0x03, 0xF0, 0x80,
++/*06D0*/0x12, 0x74, 0x01, 0xF0, 0xE5, 0x08, 0xFB, 0xEB,
++ 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xD2, 0xE0,
++/*06E0*/0x44, 0x10, 0xF0, 0xE5, 0x08, 0xFB, 0xEB, 0x44,
++ 0x09, 0xF5, 0x82, 0x75, 0x83, 0x9E, 0xED, 0xF0,
++/*06F0*/0xEB, 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xCA,
++ 0xED, 0xF0, 0x12, 0x08, 0x65, 0x75, 0x83, 0xCC,
++/*0700*/0xEF, 0xF0, 0x22, 0xE5, 0x08, 0x44, 0x07, 0xF5,
++ 0x82, 0x75, 0x83, 0xBC, 0xE0, 0x54, 0xF0, 0xF0,
++/*0710*/0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83,
++ 0xBE, 0xE0, 0x54, 0xF0, 0xF0, 0xE5, 0x08, 0x44,
++/*0720*/0x07, 0xF5, 0x82, 0x75, 0x83, 0xC0, 0xE0, 0x54,
++ 0xF0, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82,
++/*0730*/0x22, 0xF0, 0x90, 0x07, 0x28, 0xE0, 0xFE, 0xA3,
++ 0xE0, 0xF5, 0x82, 0x8E, 0x83, 0x22, 0x85, 0x42,
++/*0740*/0x42, 0x85, 0x41, 0x41, 0x85, 0x40, 0x40, 0x74,
++ 0xC0, 0x2F, 0xF5, 0x82, 0x74, 0x02, 0x3E, 0xF5,
++/*0750*/0x83, 0xE5, 0x42, 0xF0, 0x74, 0xE0, 0x2F, 0xF5,
++ 0x82, 0x74, 0x02, 0x3E, 0xF5, 0x83, 0x22, 0xE5,
++/*0760*/0x42, 0x29, 0xFD, 0xE4, 0x33, 0xFC, 0xE5, 0x3C,
++ 0xC3, 0x9D, 0xEC, 0x64, 0x80, 0xF8, 0x74, 0x80,
++/*0770*/0x98, 0x22, 0xF5, 0x83, 0xE0, 0x90, 0x07, 0x22,
++ 0x54, 0x1F, 0xFD, 0xE0, 0xFA, 0xA3, 0xE0, 0xF5,
++/*0780*/0x82, 0x8A, 0x83, 0xED, 0xF0, 0x22, 0x90, 0x07,
++ 0x22, 0xE0, 0xFC, 0xA3, 0xE0, 0xF5, 0x82, 0x8C,
++/*0790*/0x83, 0x22, 0x90, 0x07, 0x24, 0xFF, 0xED, 0x44,
++ 0x07, 0xCF, 0xF0, 0xA3, 0xEF, 0xF0, 0x22, 0x85,
++/*07A0*/0x38, 0x38, 0x85, 0x39, 0x39, 0x85, 0x3A, 0x3A,
++ 0x74, 0xC0, 0x2F, 0xF5, 0x82, 0x74, 0x02, 0x3E,
++/*07B0*/0xF5, 0x83, 0x22, 0x90, 0x07, 0x26, 0xFF, 0xED,
++ 0x44, 0x07, 0xCF, 0xF0, 0xA3, 0xEF, 0xF0, 0x22,
++/*07C0*/0xF0, 0x74, 0xA0, 0x2F, 0xF5, 0x82, 0x74, 0x02,
++ 0x3E, 0xF5, 0x83, 0x22, 0x74, 0xC0, 0x25, 0x11,
++/*07D0*/0xF5, 0x82, 0xE4, 0x34, 0x01, 0xF5, 0x83, 0x22,
++ 0x74, 0x00, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34,
++/*07E0*/0x02, 0xF5, 0x83, 0x22, 0x74, 0x60, 0x25, 0x11,
++ 0xF5, 0x82, 0xE4, 0x34, 0x03, 0xF5, 0x83, 0x22,
++/*07F0*/0x74, 0x80, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34,
++ 0x03, 0xF5, 0x83, 0x22, 0x74, 0xE0, 0x25, 0x11,
++/*0800*/0xF5, 0x82, 0xE4, 0x34, 0x03, 0xF5, 0x83, 0x22,
++ 0x74, 0x40, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34,
++/*0810*/0x06, 0xF5, 0x83, 0x22, 0x74, 0x80, 0x2F, 0xF5,
++ 0x82, 0x74, 0x02, 0x3E, 0xF5, 0x83, 0x22, 0xAF,
++/*0820*/0x08, 0x7E, 0x00, 0xEF, 0x44, 0x07, 0xF5, 0x82,
++ 0x22, 0xF5, 0x83, 0xE5, 0x82, 0x44, 0x07, 0xF5,
++/*0830*/0x82, 0xE5, 0x40, 0xF0, 0x22, 0x74, 0x40, 0x25,
++ 0x11, 0xF5, 0x82, 0xE4, 0x34, 0x02, 0xF5, 0x83,
++/*0840*/0x22, 0x74, 0xC0, 0x25, 0x11, 0xF5, 0x82, 0xE4,
++ 0x34, 0x03, 0xF5, 0x83, 0x22, 0x74, 0x00, 0x25,
++/*0850*/0x11, 0xF5, 0x82, 0xE4, 0x34, 0x06, 0xF5, 0x83,
++ 0x22, 0x74, 0x20, 0x25, 0x11, 0xF5, 0x82, 0xE4,
++/*0860*/0x34, 0x06, 0xF5, 0x83, 0x22, 0xE5, 0x08, 0xFD,
++ 0xED, 0x44, 0x07, 0xF5, 0x82, 0x22, 0xE5, 0x41,
++/*0870*/0xF0, 0xE5, 0x65, 0x64, 0x01, 0x45, 0x64, 0x22,
++ 0x7E, 0x00, 0xFB, 0x7A, 0x00, 0xFD, 0x7C, 0x00,
++/*0880*/0x22, 0x74, 0x20, 0x25, 0x11, 0xF5, 0x82, 0xE4,
++ 0x34, 0x02, 0x22, 0x74, 0xA0, 0x25, 0x11, 0xF5,
++/*0890*/0x82, 0xE4, 0x34, 0x03, 0x22, 0x85, 0x3E, 0x42,
++ 0x85, 0x3F, 0x41, 0x8F, 0x40, 0x22, 0x85, 0x3C,
++/*08A0*/0x42, 0x85, 0x3D, 0x41, 0x8F, 0x40, 0x22, 0x75,
++ 0x45, 0x3F, 0x90, 0x07, 0x20, 0xE4, 0xF0, 0xA3,
++/*08B0*/0x22, 0xF5, 0x83, 0xE5, 0x32, 0xF0, 0x05, 0x6E,
++ 0xE5, 0x6E, 0xC3, 0x94, 0x40, 0x22, 0xF0, 0xE5,
++/*08C0*/0x08, 0x44, 0x06, 0xF5, 0x82, 0x22, 0x74, 0x00,
++ 0x25, 0x6E, 0xF5, 0x82, 0xE4, 0x34, 0x00, 0xF5,
++/*08D0*/0x83, 0x22, 0xE5, 0x6D, 0x45, 0x6C, 0x90, 0x07,
++ 0x2F, 0x22, 0xE4, 0xF9, 0xE5, 0x3C, 0xD3, 0x95,
++/*08E0*/0x3E, 0x22, 0x74, 0x80, 0x2E, 0xF5, 0x82, 0xE4,
++ 0x34, 0x02, 0xF5, 0x83, 0xE0, 0x22, 0x74, 0xA0,
++/*08F0*/0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x02, 0xF5, 0x83,
++ 0xE0, 0x22, 0x74, 0x80, 0x25, 0x6E, 0xF5, 0x82,
++/*0900*/0xE4, 0x34, 0x00, 0x22, 0x25, 0x42, 0xFD, 0xE4,
++ 0x33, 0xFC, 0x22, 0x85, 0x42, 0x42, 0x85, 0x41,
++/*0910*/0x41, 0x85, 0x40, 0x40, 0x22, 0xED, 0x4C, 0x60,
++ 0x03, 0x02, 0x09, 0xE5, 0xEF, 0x4E, 0x70, 0x37,
++/*0920*/0x90, 0x07, 0x26, 0x12, 0x07, 0x89, 0xE0, 0xFD,
++ 0x12, 0x07, 0xCC, 0xED, 0xF0, 0x90, 0x07, 0x28,
++/*0930*/0x12, 0x07, 0x89, 0xE0, 0xFD, 0x12, 0x07, 0xD8,
++ 0xED, 0xF0, 0x12, 0x07, 0x86, 0xE0, 0x54, 0x1F,
++/*0940*/0xFD, 0x12, 0x08, 0x81, 0xF5, 0x83, 0xED, 0xF0,
++ 0x90, 0x07, 0x24, 0x12, 0x07, 0x89, 0xE0, 0x54,
++/*0950*/0x1F, 0xFD, 0x12, 0x08, 0x35, 0xED, 0xF0, 0xEF,
++ 0x64, 0x04, 0x4E, 0x70, 0x37, 0x90, 0x07, 0x26,
++/*0960*/0x12, 0x07, 0x89, 0xE0, 0xFD, 0x12, 0x07, 0xE4,
++ 0xED, 0xF0, 0x90, 0x07, 0x28, 0x12, 0x07, 0x89,
++/*0970*/0xE0, 0xFD, 0x12, 0x07, 0xF0, 0xED, 0xF0, 0x12,
++ 0x07, 0x86, 0xE0, 0x54, 0x1F, 0xFD, 0x12, 0x08,
++/*0980*/0x8B, 0xF5, 0x83, 0xED, 0xF0, 0x90, 0x07, 0x24,
++ 0x12, 0x07, 0x89, 0xE0, 0x54, 0x1F, 0xFD, 0x12,
++/*0990*/0x08, 0x41, 0xED, 0xF0, 0xEF, 0x64, 0x01, 0x4E,
++ 0x70, 0x04, 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00,
++/*09A0*/0xEF, 0x64, 0x02, 0x4E, 0x70, 0x04, 0x7F, 0x01,
++ 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x4D, 0x60, 0x78,
++/*09B0*/0x90, 0x07, 0x26, 0x12, 0x07, 0x35, 0xE0, 0xFF,
++ 0x12, 0x07, 0xFC, 0xEF, 0x12, 0x07, 0x31, 0xE0,
++/*09C0*/0xFF, 0x12, 0x08, 0x08, 0xEF, 0xF0, 0x90, 0x07,
++ 0x22, 0x12, 0x07, 0x35, 0xE0, 0x54, 0x1F, 0xFF,
++/*09D0*/0x12, 0x08, 0x4D, 0xEF, 0xF0, 0x90, 0x07, 0x24,
++ 0x12, 0x07, 0x35, 0xE0, 0x54, 0x1F, 0xFF, 0x12,
++/*09E0*/0x08, 0x59, 0xEF, 0xF0, 0x22, 0x12, 0x07, 0xCC,
++ 0xE4, 0xF0, 0x12, 0x07, 0xD8, 0xE4, 0xF0, 0x12,
++/*09F0*/0x08, 0x81, 0xF5, 0x83, 0xE4, 0xF0, 0x12, 0x08,
++ 0x35, 0x74, 0x14, 0xF0, 0x12, 0x07, 0xE4, 0xE4,
++/*0A00*/0xF0, 0x12, 0x07, 0xF0, 0xE4, 0xF0, 0x12, 0x08,
++ 0x8B, 0xF5, 0x83, 0xE4, 0xF0, 0x12, 0x08, 0x41,
++/*0A10*/0x74, 0x14, 0xF0, 0x12, 0x07, 0xFC, 0xE4, 0xF0,
++ 0x12, 0x08, 0x08, 0xE4, 0xF0, 0x12, 0x08, 0x4D,
++/*0A20*/0xE4, 0xF0, 0x12, 0x08, 0x59, 0x74, 0x14, 0xF0,
++ 0x22, 0x53, 0xF9, 0xF7, 0x75, 0xFC, 0x10, 0xE4,
++/*0A30*/0xF5, 0xFD, 0x75, 0xFE, 0x30, 0xF5, 0xFF, 0xE5,
++ 0xE7, 0x20, 0xE7, 0x03, 0x43, 0xF9, 0x08, 0xE5,
++/*0A40*/0xE6, 0x20, 0xE7, 0x0B, 0x78, 0xFF, 0xE4, 0xF6,
++ 0xD8, 0xFD, 0x53, 0xE6, 0xFE, 0x80, 0x09, 0x78,
++/*0A50*/0x08, 0xE4, 0xF6, 0xD8, 0xFD, 0x53, 0xE6, 0xFE,
++ 0x75, 0x81, 0x80, 0xE4, 0xF5, 0xA8, 0xD2, 0xA8,
++/*0A60*/0xC2, 0xA9, 0xD2, 0xAF, 0xE5, 0xE2, 0x20, 0xE5,
++ 0x05, 0x20, 0xE6, 0x02, 0x80, 0x03, 0x43, 0xE1,
++/*0A70*/0x02, 0xE5, 0xE2, 0x20, 0xE0, 0x0E, 0x90, 0x00,
++ 0x00, 0x7F, 0x00, 0x7E, 0x08, 0xE4, 0xF0, 0xA3,
++/*0A80*/0xDF, 0xFC, 0xDE, 0xFA, 0x02, 0x0A, 0xDB, 0x43,
++ 0xFA, 0x01, 0xC0, 0xE0, 0xC0, 0xF0, 0xC0, 0x83,
++/*0A90*/0xC0, 0x82, 0xC0, 0xD0, 0x12, 0x1C, 0xE7, 0xD0,
++ 0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0,
++/*0AA0*/0xE0, 0x53, 0xFA, 0xFE, 0x32, 0x02, 0x1B, 0x55,
++ 0xE4, 0x93, 0xA3, 0xF8, 0xE4, 0x93, 0xA3, 0xF6,
++/*0AB0*/0x08, 0xDF, 0xF9, 0x80, 0x29, 0xE4, 0x93, 0xA3,
++ 0xF8, 0x54, 0x07, 0x24, 0x0C, 0xC8, 0xC3, 0x33,
++/*0AC0*/0xC4, 0x54, 0x0F, 0x44, 0x20, 0xC8, 0x83, 0x40,
++ 0x04, 0xF4, 0x56, 0x80, 0x01, 0x46, 0xF6, 0xDF,
++/*0AD0*/0xE4, 0x80, 0x0B, 0x01, 0x02, 0x04, 0x08, 0x10,
++ 0x20, 0x40, 0x80, 0x90, 0x00, 0x3F, 0xE4, 0x7E,
++/*0AE0*/0x01, 0x93, 0x60, 0xC1, 0xA3, 0xFF, 0x54, 0x3F,
++ 0x30, 0xE5, 0x09, 0x54, 0x1F, 0xFE, 0xE4, 0x93,
++/*0AF0*/0xA3, 0x60, 0x01, 0x0E, 0xCF, 0x54, 0xC0, 0x25,
++ 0xE0, 0x60, 0xAD, 0x40, 0xB8, 0x80, 0xFE, 0x8C,
++/*0B00*/0x64, 0x8D, 0x65, 0x8A, 0x66, 0x8B, 0x67, 0xE4,
++ 0xF5, 0x69, 0xEF, 0x4E, 0x70, 0x03, 0x02, 0x1D,
++/*0B10*/0x55, 0xE4, 0xF5, 0x68, 0xE5, 0x67, 0x45, 0x66,
++ 0x70, 0x32, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x90,
++/*0B20*/0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE4,
++ 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0xE4, 0x12,
++/*0B30*/0x08, 0x70, 0x70, 0x29, 0x12, 0x07, 0x2A, 0x75,
++ 0x83, 0x92, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83,
++/*0B40*/0xC6, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC8,
++ 0xE4, 0xF0, 0x80, 0x11, 0x90, 0x07, 0x26, 0x12,
++/*0B50*/0x07, 0x35, 0xE4, 0x12, 0x08, 0x70, 0x70, 0x05,
++ 0x12, 0x07, 0x32, 0xE4, 0xF0, 0x12, 0x1D, 0x55,
++/*0B60*/0x12, 0x1E, 0xBF, 0xE5, 0x67, 0x45, 0x66, 0x70,
++ 0x33, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x90, 0xE5,
++/*0B70*/0x41, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE5,
++ 0x41, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0x12,
++/*0B80*/0x08, 0x6E, 0x70, 0x29, 0x12, 0x07, 0x2A, 0x75,
++ 0x83, 0x92, 0xE5, 0x40, 0x12, 0x07, 0x29, 0x75,
++/*0B90*/0x83, 0xC6, 0xE5, 0x40, 0x12, 0x07, 0x29, 0x75,
++ 0x83, 0xC8, 0x80, 0x0E, 0x90, 0x07, 0x26, 0x12,
++/*0BA0*/0x07, 0x35, 0x12, 0x08, 0x6E, 0x70, 0x06, 0x12,
++ 0x07, 0x32, 0xE5, 0x40, 0xF0, 0xAF, 0x69, 0x7E,
++/*0BB0*/0x00, 0xAD, 0x67, 0xAC, 0x66, 0x12, 0x04, 0x44,
++ 0x12, 0x07, 0x2A, 0x75, 0x83, 0xCA, 0xE0, 0xD3,
++/*0BC0*/0x94, 0x00, 0x50, 0x0C, 0x05, 0x68, 0xE5, 0x68,
++ 0xC3, 0x94, 0x05, 0x50, 0x03, 0x02, 0x0B, 0x14,
++/*0BD0*/0x22, 0x8C, 0x60, 0x8D, 0x61, 0x12, 0x08, 0xDA,
++ 0x74, 0x20, 0x40, 0x0D, 0x2F, 0xF5, 0x82, 0x74,
++/*0BE0*/0x03, 0x3E, 0xF5, 0x83, 0xE5, 0x3E, 0xF0, 0x80,
++ 0x0B, 0x2F, 0xF5, 0x82, 0x74, 0x03, 0x3E, 0xF5,
++/*0BF0*/0x83, 0xE5, 0x3C, 0xF0, 0xE5, 0x3C, 0xD3, 0x95,
++ 0x3E, 0x40, 0x3C, 0xE5, 0x61, 0x45, 0x60, 0x70,
++/*0C00*/0x10, 0xE9, 0x12, 0x09, 0x04, 0xE5, 0x3E, 0x12,
++ 0x07, 0x68, 0x40, 0x3B, 0x12, 0x08, 0x95, 0x80,
++/*0C10*/0x18, 0xE5, 0x3E, 0xC3, 0x95, 0x38, 0x40, 0x1D,
++ 0x85, 0x3E, 0x38, 0xE5, 0x3E, 0x60, 0x05, 0x85,
++/*0C20*/0x3F, 0x39, 0x80, 0x03, 0x85, 0x39, 0x39, 0x8F,
++ 0x3A, 0x12, 0x08, 0x14, 0xE5, 0x3E, 0x12, 0x07,
++/*0C30*/0xC0, 0xE5, 0x3F, 0xF0, 0x22, 0x80, 0x43, 0xE5,
++ 0x61, 0x45, 0x60, 0x70, 0x19, 0x12, 0x07, 0x5F,
++/*0C40*/0x40, 0x05, 0x12, 0x08, 0x9E, 0x80, 0x27, 0x12,
++ 0x09, 0x0B, 0x12, 0x08, 0x14, 0xE5, 0x42, 0x12,
++/*0C50*/0x07, 0xC0, 0xE5, 0x41, 0xF0, 0x22, 0xE5, 0x3C,
++ 0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3C, 0x38,
++/*0C60*/0xE5, 0x3C, 0x60, 0x05, 0x85, 0x3D, 0x39, 0x80,
++ 0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12, 0x08,
++/*0C70*/0x14, 0xE5, 0x3C, 0x12, 0x07, 0xC0, 0xE5, 0x3D,
++ 0xF0, 0x22, 0x85, 0x38, 0x38, 0x85, 0x39, 0x39,
++/*0C80*/0x85, 0x3A, 0x3A, 0x12, 0x08, 0x14, 0xE5, 0x38,
++ 0x12, 0x07, 0xC0, 0xE5, 0x39, 0xF0, 0x22, 0x7F,
++/*0C90*/0x06, 0x12, 0x17, 0x31, 0x12, 0x1D, 0x23, 0x12,
++ 0x0E, 0x04, 0x12, 0x0E, 0x33, 0xE0, 0x44, 0x0A,
++/*0CA0*/0xF0, 0x74, 0x8E, 0xFE, 0x12, 0x0E, 0x04, 0x12,
++ 0x0E, 0x0B, 0xEF, 0xF0, 0xE5, 0x28, 0x30, 0xE5,
++/*0CB0*/0x03, 0xD3, 0x80, 0x01, 0xC3, 0x40, 0x05, 0x75,
++ 0x14, 0x20, 0x80, 0x03, 0x75, 0x14, 0x08, 0x12,
++/*0CC0*/0x0E, 0x04, 0x75, 0x83, 0x8A, 0xE5, 0x14, 0xF0,
++ 0xB4, 0xFF, 0x05, 0x75, 0x12, 0x80, 0x80, 0x06,
++/*0CD0*/0xE5, 0x14, 0xC3, 0x13, 0xF5, 0x12, 0xE4, 0xF5,
++ 0x16, 0xF5, 0x7F, 0x12, 0x19, 0x36, 0x12, 0x13,
++/*0CE0*/0xA3, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x50, 0x09,
++ 0x05, 0x16, 0xE5, 0x16, 0xC3, 0x94, 0x14, 0x40,
++/*0CF0*/0xEA, 0xE5, 0xE4, 0x20, 0xE7, 0x28, 0x12, 0x0E,
++ 0x04, 0x75, 0x83, 0xD2, 0xE0, 0x54, 0x08, 0xD3,
++/*0D00*/0x94, 0x00, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02,
++ 0x7F, 0x00, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40,
++/*0D10*/0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF,
++ 0x5E, 0x60, 0x03, 0x12, 0x1D, 0xD7, 0xE5, 0x7F,
++/*0D20*/0xC3, 0x94, 0x11, 0x40, 0x14, 0x12, 0x0E, 0x04,
++ 0x75, 0x83, 0xD2, 0xE0, 0x44, 0x80, 0xF0, 0xE5,
++/*0D30*/0xE4, 0x20, 0xE7, 0x0F, 0x12, 0x1D, 0xD7, 0x80,
++ 0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0xD2, 0xE0,
++/*0D40*/0x54, 0x7F, 0xF0, 0x12, 0x1D, 0x23, 0x22, 0x74,
++ 0x8A, 0x85, 0x08, 0x82, 0xF5, 0x83, 0xE5, 0x17,
++/*0D50*/0xF0, 0x12, 0x0E, 0x3A, 0xE4, 0xF0, 0x90, 0x07,
++ 0x02, 0xE0, 0x12, 0x0E, 0x17, 0x75, 0x83, 0x90,
++/*0D60*/0xEF, 0xF0, 0x74, 0x92, 0xFE, 0xE5, 0x08, 0x44,
++ 0x07, 0xFF, 0xF5, 0x82, 0x8E, 0x83, 0xE0, 0x54,
++/*0D70*/0xC0, 0xFD, 0x90, 0x07, 0x03, 0xE0, 0x54, 0x3F,
++ 0x4D, 0x8F, 0x82, 0x8E, 0x83, 0xF0, 0x90, 0x07,
++/*0D80*/0x04, 0xE0, 0x12, 0x0E, 0x17, 0x75, 0x83, 0x82,
++ 0xEF, 0xF0, 0x90, 0x07, 0x05, 0xE0, 0xFF, 0xED,
++/*0D90*/0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xB4, 0xEF,
++ 0x12, 0x0E, 0x03, 0x75, 0x83, 0x80, 0xE0, 0x54,
++/*0DA0*/0xBF, 0xF0, 0x30, 0x37, 0x0A, 0x12, 0x0E, 0x91,
++ 0x75, 0x83, 0x94, 0xE0, 0x44, 0x80, 0xF0, 0x30,
++/*0DB0*/0x38, 0x0A, 0x12, 0x0E, 0x91, 0x75, 0x83, 0x92,
++ 0xE0, 0x44, 0x80, 0xF0, 0xE5, 0x28, 0x30, 0xE4,
++/*0DC0*/0x1A, 0x20, 0x39, 0x0A, 0x12, 0x0E, 0x04, 0x75,
++ 0x83, 0x88, 0xE0, 0x54, 0x7F, 0xF0, 0x20, 0x3A,
++/*0DD0*/0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0x88, 0xE0,
++ 0x54, 0xBF, 0xF0, 0x74, 0x8C, 0xFE, 0x12, 0x0E,
++/*0DE0*/0x04, 0x8E, 0x83, 0xE0, 0x54, 0x0F, 0x12, 0x0E,
++ 0x03, 0x75, 0x83, 0x86, 0xE0, 0x54, 0xBF, 0xF0,
++/*0DF0*/0xE5, 0x08, 0x44, 0x06, 0x12, 0x0D, 0xFD, 0x75,
++ 0x83, 0x8A, 0xE4, 0xF0, 0x22, 0xF5, 0x82, 0x75,
++/*0E00*/0x83, 0x82, 0xE4, 0xF0, 0xE5, 0x08, 0x44, 0x07,
++ 0xF5, 0x82, 0x22, 0x8E, 0x83, 0xE0, 0xF5, 0x10,
++/*0E10*/0x54, 0xFE, 0xF0, 0xE5, 0x10, 0x44, 0x01, 0xFF,
++ 0xE5, 0x08, 0xFD, 0xED, 0x44, 0x07, 0xF5, 0x82,
++/*0E20*/0x22, 0xE5, 0x15, 0xC4, 0x54, 0x07, 0xFF, 0xE5,
++ 0x08, 0xFD, 0xED, 0x44, 0x08, 0xF5, 0x82, 0x75,
++/*0E30*/0x83, 0x82, 0x22, 0x75, 0x83, 0x80, 0xE0, 0x44,
++ 0x40, 0xF0, 0xE5, 0x08, 0x44, 0x08, 0xF5, 0x82,
++/*0E40*/0x75, 0x83, 0x8A, 0x22, 0xE5, 0x16, 0x25, 0xE0,
++ 0x25, 0xE0, 0x24, 0xAF, 0xF5, 0x82, 0xE4, 0x34,
++/*0E50*/0x1A, 0xF5, 0x83, 0xE4, 0x93, 0xF5, 0x0D, 0x22,
++ 0x43, 0xE1, 0x10, 0x43, 0xE1, 0x80, 0x53, 0xE1,
++/*0E60*/0xFD, 0x85, 0xE1, 0x10, 0x22, 0xE5, 0x16, 0x25,
++ 0xE0, 0x25, 0xE0, 0x24, 0xB2, 0xF5, 0x82, 0xE4,
++/*0E70*/0x34, 0x1A, 0xF5, 0x83, 0xE4, 0x93, 0x22, 0x85,
++ 0x55, 0x82, 0x85, 0x54, 0x83, 0xE5, 0x15, 0xF0,
++/*0E80*/0x22, 0xE5, 0xE2, 0x54, 0x20, 0xD3, 0x94, 0x00,
++ 0x22, 0xE5, 0xE2, 0x54, 0x40, 0xD3, 0x94, 0x00,
++/*0E90*/0x22, 0xE5, 0x08, 0x44, 0x06, 0xF5, 0x82, 0x22,
++ 0xFD, 0xE5, 0x08, 0xFB, 0xEB, 0x44, 0x07, 0xF5,
++/*0EA0*/0x82, 0x22, 0x53, 0xF9, 0xF7, 0x75, 0xFE, 0x30,
++ 0x22, 0xEF, 0x4E, 0x70, 0x26, 0x12, 0x07, 0xCC,
++/*0EB0*/0xE0, 0xFD, 0x90, 0x07, 0x26, 0x12, 0x07, 0x7B,
++ 0x12, 0x07, 0xD8, 0xE0, 0xFD, 0x90, 0x07, 0x28,
++/*0EC0*/0x12, 0x07, 0x7B, 0x12, 0x08, 0x81, 0x12, 0x07,
++ 0x72, 0x12, 0x08, 0x35, 0xE0, 0x90, 0x07, 0x24,
++/*0ED0*/0x12, 0x07, 0x78, 0xEF, 0x64, 0x04, 0x4E, 0x70,
++ 0x29, 0x12, 0x07, 0xE4, 0xE0, 0xFD, 0x90, 0x07,
++/*0EE0*/0x26, 0x12, 0x07, 0x7B, 0x12, 0x07, 0xF0, 0xE0,
++ 0xFD, 0x90, 0x07, 0x28, 0x12, 0x07, 0x7B, 0x12,
++/*0EF0*/0x08, 0x8B, 0x12, 0x07, 0x72, 0x12, 0x08, 0x41,
++ 0xE0, 0x54, 0x1F, 0xFD, 0x90, 0x07, 0x24, 0x12,
++/*0F00*/0x07, 0x7B, 0xEF, 0x64, 0x01, 0x4E, 0x70, 0x04,
++ 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, 0xEF, 0x64,
++/*0F10*/0x02, 0x4E, 0x70, 0x04, 0x7F, 0x01, 0x80, 0x02,
++ 0x7F, 0x00, 0xEF, 0x4D, 0x60, 0x35, 0x12, 0x07,
++/*0F20*/0xFC, 0xE0, 0xFF, 0x90, 0x07, 0x26, 0x12, 0x07,
++ 0x89, 0xEF, 0xF0, 0x12, 0x08, 0x08, 0xE0, 0xFF,
++/*0F30*/0x90, 0x07, 0x28, 0x12, 0x07, 0x89, 0xEF, 0xF0,
++ 0x12, 0x08, 0x4D, 0xE0, 0x54, 0x1F, 0xFF, 0x12,
++/*0F40*/0x07, 0x86, 0xEF, 0xF0, 0x12, 0x08, 0x59, 0xE0,
++ 0x54, 0x1F, 0xFF, 0x90, 0x07, 0x24, 0x12, 0x07,
++/*0F50*/0x89, 0xEF, 0xF0, 0x22, 0xE4, 0xF5, 0x53, 0x12,
++ 0x0E, 0x81, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02,
++/*0F60*/0x7F, 0x00, 0x12, 0x0E, 0x89, 0x40, 0x04, 0x7E,
++ 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x70,
++/*0F70*/0x03, 0x02, 0x0F, 0xF6, 0x85, 0xE1, 0x10, 0x43,
++ 0xE1, 0x02, 0x53, 0xE1, 0x0F, 0x85, 0xE1, 0x10,
++/*0F80*/0xE4, 0xF5, 0x51, 0xE5, 0xE3, 0x54, 0x3F, 0xF5,
++ 0x52, 0x12, 0x0E, 0x89, 0x40, 0x1D, 0xAD, 0x52,
++/*0F90*/0xAF, 0x51, 0x12, 0x11, 0x18, 0xEF, 0x60, 0x08,
++ 0x85, 0xE1, 0x10, 0x43, 0xE1, 0x40, 0x80, 0x0B,
++/*0FA0*/0x53, 0xE1, 0xBF, 0x12, 0x0E, 0x58, 0x12, 0x00,
++ 0x06, 0x80, 0xFB, 0xE5, 0xE3, 0x54, 0x3F, 0xF5,
++/*0FB0*/0x51, 0xE5, 0xE4, 0x54, 0x3F, 0xF5, 0x52, 0x12,
++ 0x0E, 0x81, 0x40, 0x1D, 0xAD, 0x52, 0xAF, 0x51,
++/*0FC0*/0x12, 0x11, 0x18, 0xEF, 0x60, 0x08, 0x85, 0xE1,
++ 0x10, 0x43, 0xE1, 0x20, 0x80, 0x0B, 0x53, 0xE1,
++/*0FD0*/0xDF, 0x12, 0x0E, 0x58, 0x12, 0x00, 0x06, 0x80,
++ 0xFB, 0x12, 0x0E, 0x81, 0x40, 0x04, 0x7F, 0x01,
++/*0FE0*/0x80, 0x02, 0x7F, 0x00, 0x12, 0x0E, 0x89, 0x40,
++ 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE,
++/*0FF0*/0x4F, 0x60, 0x03, 0x12, 0x0E, 0x5B, 0x22, 0x12,
++ 0x0E, 0x21, 0xEF, 0xF0, 0x12, 0x10, 0x91, 0x22,
++/*1000*/0x02, 0x11, 0x00, 0x02, 0x10, 0x40, 0x02, 0x10,
++ 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1010*/0x01, 0x20, 0x01, 0x20, 0xE4, 0xF5, 0x57, 0x12,
++ 0x16, 0xBD, 0x12, 0x16, 0x44, 0xE4, 0x12, 0x10,
++/*1020*/0x56, 0x12, 0x14, 0xB7, 0x90, 0x07, 0x26, 0x12,
++ 0x07, 0x35, 0xE4, 0x12, 0x07, 0x31, 0xE4, 0xF0,
++/*1030*/0x12, 0x10, 0x56, 0x12, 0x14, 0xB7, 0x90, 0x07,
++ 0x26, 0x12, 0x07, 0x35, 0xE5, 0x41, 0x12, 0x07,
++/*1040*/0x31, 0xE5, 0x40, 0xF0, 0xAF, 0x57, 0x7E, 0x00,
++ 0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44, 0xAF,
++/*1050*/0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0xFF, 0x90,
++ 0x07, 0x20, 0xA3, 0xE0, 0xFD, 0xE4, 0xF5, 0x56,
++/*1060*/0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA, 0x12,
++ 0x11, 0x51, 0x7F, 0x0F, 0x7D, 0x18, 0xE4, 0xF5,
++/*1070*/0x56, 0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA,
++ 0x12, 0x15, 0x41, 0xAF, 0x56, 0x7E, 0x00, 0x12,
++/*1080*/0x1A, 0xFF, 0xE4, 0xFF, 0xF5, 0x56, 0x7D, 0x1F,
++ 0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA, 0x22,
++/*1090*/0x22, 0xE4, 0xF5, 0x55, 0xE5, 0x08, 0xFD, 0x74,
++ 0xA0, 0xF5, 0x56, 0xED, 0x44, 0x07, 0xF5, 0x57,
++/*10A0*/0xE5, 0x28, 0x30, 0xE5, 0x03, 0xD3, 0x80, 0x01,
++ 0xC3, 0x40, 0x05, 0x7F, 0x28, 0xEF, 0x80, 0x04,
++/*10B0*/0x7F, 0x14, 0xEF, 0xC3, 0x13, 0xF5, 0x54, 0xE4,
++ 0xF9, 0x12, 0x0E, 0x18, 0x75, 0x83, 0x8E, 0xE0,
++/*10C0*/0xF5, 0x10, 0xCE, 0xEF, 0xCE, 0xEE, 0xD3, 0x94,
++ 0x00, 0x40, 0x26, 0xE5, 0x10, 0x54, 0xFE, 0x12,
++/*10D0*/0x0E, 0x98, 0x75, 0x83, 0x8E, 0xED, 0xF0, 0xE5,
++ 0x10, 0x44, 0x01, 0xFD, 0xEB, 0x44, 0x07, 0xF5,
++/*10E0*/0x82, 0xED, 0xF0, 0x85, 0x57, 0x82, 0x85, 0x56,
++ 0x83, 0xE0, 0x30, 0xE3, 0x01, 0x09, 0x1E, 0x80,
++/*10F0*/0xD4, 0xC2, 0x34, 0xE9, 0xC3, 0x95, 0x54, 0x40,
++ 0x02, 0xD2, 0x34, 0x22, 0x02, 0x00, 0x06, 0x22,
++/*1100*/0x30, 0x30, 0x11, 0x90, 0x10, 0x00, 0xE4, 0x93,
++ 0xF5, 0x10, 0x90, 0x10, 0x10, 0xE4, 0x93, 0xF5,
++/*1110*/0x10, 0x12, 0x10, 0x90, 0x12, 0x11, 0x50, 0x22,
++ 0xE4, 0xFC, 0xC3, 0xED, 0x9F, 0xFA, 0xEF, 0xF5,
++/*1120*/0x83, 0x75, 0x82, 0x00, 0x79, 0xFF, 0xE4, 0x93,
++ 0xCC, 0x6C, 0xCC, 0xA3, 0xD9, 0xF8, 0xDA, 0xF6,
++/*1130*/0xE5, 0xE2, 0x30, 0xE4, 0x02, 0x8C, 0xE5, 0xED,
++ 0x24, 0xFF, 0xFF, 0xEF, 0x75, 0x82, 0xFF, 0xF5,
++/*1140*/0x83, 0xE4, 0x93, 0x6C, 0x70, 0x03, 0x7F, 0x01,
++ 0x22, 0x7F, 0x00, 0x22, 0x22, 0x11, 0x00, 0x00,
++/*1150*/0x22, 0x8E, 0x58, 0x8F, 0x59, 0x8C, 0x5A, 0x8D,
++ 0x5B, 0x8A, 0x5C, 0x8B, 0x5D, 0x75, 0x5E, 0x01,
++/*1160*/0xE4, 0xF5, 0x5F, 0xF5, 0x60, 0xF5, 0x62, 0x12,
++ 0x07, 0x2A, 0x75, 0x83, 0xD0, 0xE0, 0xFF, 0xC4,
++/*1170*/0x54, 0x0F, 0xF5, 0x61, 0x12, 0x1E, 0xA5, 0x85,
++ 0x59, 0x5E, 0xD3, 0xE5, 0x5E, 0x95, 0x5B, 0xE5,
++/*1180*/0x5A, 0x12, 0x07, 0x6B, 0x50, 0x4B, 0x12, 0x07,
++ 0x03, 0x75, 0x83, 0xBC, 0xE0, 0x45, 0x5E, 0x12,
++/*1190*/0x07, 0x29, 0x75, 0x83, 0xBE, 0xE0, 0x45, 0x5E,
++ 0x12, 0x07, 0x29, 0x75, 0x83, 0xC0, 0xE0, 0x45,
++/*11A0*/0x5E, 0xF0, 0xAF, 0x5F, 0xE5, 0x60, 0x12, 0x08,
++ 0x78, 0x12, 0x0A, 0xFF, 0xAF, 0x62, 0x7E, 0x00,
++/*11B0*/0xAD, 0x5D, 0xAC, 0x5C, 0x12, 0x04, 0x44, 0xE5,
++ 0x61, 0xAF, 0x5E, 0x7E, 0x00, 0xB4, 0x03, 0x05,
++/*11C0*/0x12, 0x1E, 0x21, 0x80, 0x07, 0xAD, 0x5D, 0xAC,
++ 0x5C, 0x12, 0x13, 0x17, 0x05, 0x5E, 0x02, 0x11,
++/*11D0*/0x7A, 0x12, 0x07, 0x03, 0x75, 0x83, 0xBC, 0xE0,
++ 0x45, 0x40, 0x12, 0x07, 0x29, 0x75, 0x83, 0xBE,
++/*11E0*/0xE0, 0x45, 0x40, 0x12, 0x07, 0x29, 0x75, 0x83,
++ 0xC0, 0xE0, 0x45, 0x40, 0xF0, 0x22, 0x8E, 0x58,
++/*11F0*/0x8F, 0x59, 0x75, 0x5A, 0x01, 0x79, 0x01, 0x75,
++ 0x5B, 0x01, 0xE4, 0xFB, 0x12, 0x07, 0x2A, 0x75,
++/*1200*/0x83, 0xAE, 0xE0, 0x54, 0x1A, 0xFF, 0x12, 0x08,
++ 0x65, 0xE0, 0xC4, 0x13, 0x54, 0x07, 0xFE, 0xEF,
++/*1210*/0x70, 0x0C, 0xEE, 0x65, 0x35, 0x70, 0x07, 0x90,
++ 0x07, 0x2F, 0xE0, 0xB4, 0x01, 0x0D, 0xAF, 0x35,
++/*1220*/0x7E, 0x00, 0x12, 0x0E, 0xA9, 0xCF, 0xEB, 0xCF,
++ 0x02, 0x1E, 0x60, 0xE5, 0x59, 0x64, 0x02, 0x45,
++/*1230*/0x58, 0x70, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F,
++ 0x00, 0xE5, 0x59, 0x45, 0x58, 0x70, 0x04, 0x7E,
++/*1240*/0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x60,
++ 0x23, 0x85, 0x41, 0x49, 0x85, 0x40, 0x4B, 0xE5,
++/*1250*/0x59, 0x45, 0x58, 0x70, 0x2C, 0xAF, 0x5A, 0xFE,
++ 0xCD, 0xE9, 0xCD, 0xFC, 0xAB, 0x59, 0xAA, 0x58,
++/*1260*/0x12, 0x0A, 0xFF, 0xAF, 0x5B, 0x7E, 0x00, 0x12,
++ 0x1E, 0x60, 0x80, 0x15, 0xAF, 0x5B, 0x7E, 0x00,
++/*1270*/0x12, 0x1E, 0x60, 0x90, 0x07, 0x26, 0x12, 0x07,
++ 0x35, 0xE5, 0x49, 0x12, 0x07, 0x31, 0xE5, 0x4B,
++/*1280*/0xF0, 0xE4, 0xFD, 0xAF, 0x35, 0xFE, 0xFC, 0x12,
++ 0x09, 0x15, 0x22, 0x8C, 0x64, 0x8D, 0x65, 0x12,
++/*1290*/0x08, 0xDA, 0x40, 0x3C, 0xE5, 0x65, 0x45, 0x64,
++ 0x70, 0x10, 0x12, 0x09, 0x04, 0xC3, 0xE5, 0x3E,
++/*12A0*/0x12, 0x07, 0x69, 0x40, 0x3B, 0x12, 0x08, 0x95,
++ 0x80, 0x18, 0xE5, 0x3E, 0xC3, 0x95, 0x38, 0x40,
++/*12B0*/0x1D, 0x85, 0x3E, 0x38, 0xE5, 0x3E, 0x60, 0x05,
++ 0x85, 0x3F, 0x39, 0x80, 0x03, 0x85, 0x39, 0x39,
++/*12C0*/0x8F, 0x3A, 0x12, 0x07, 0xA8, 0xE5, 0x3E, 0x12,
++ 0x07, 0x53, 0xE5, 0x3F, 0xF0, 0x22, 0x80, 0x3B,
++/*12D0*/0xE5, 0x65, 0x45, 0x64, 0x70, 0x11, 0x12, 0x07,
++ 0x5F, 0x40, 0x05, 0x12, 0x08, 0x9E, 0x80, 0x1F,
++/*12E0*/0x12, 0x07, 0x3E, 0xE5, 0x41, 0xF0, 0x22, 0xE5,
++ 0x3C, 0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3C,
++/*12F0*/0x38, 0xE5, 0x3C, 0x60, 0x05, 0x85, 0x3D, 0x39,
++ 0x80, 0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12,
++/*1300*/0x07, 0xA8, 0xE5, 0x3C, 0x12, 0x07, 0x53, 0xE5,
++ 0x3D, 0xF0, 0x22, 0x12, 0x07, 0x9F, 0xE5, 0x38,
++/*1310*/0x12, 0x07, 0x53, 0xE5, 0x39, 0xF0, 0x22, 0x8C,
++ 0x63, 0x8D, 0x64, 0x12, 0x08, 0xDA, 0x40, 0x3C,
++/*1320*/0xE5, 0x64, 0x45, 0x63, 0x70, 0x10, 0x12, 0x09,
++ 0x04, 0xC3, 0xE5, 0x3E, 0x12, 0x07, 0x69, 0x40,
++/*1330*/0x3B, 0x12, 0x08, 0x95, 0x80, 0x18, 0xE5, 0x3E,
++ 0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3E, 0x38,
++/*1340*/0xE5, 0x3E, 0x60, 0x05, 0x85, 0x3F, 0x39, 0x80,
++ 0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12, 0x07,
++/*1350*/0xA8, 0xE5, 0x3E, 0x12, 0x07, 0x53, 0xE5, 0x3F,
++ 0xF0, 0x22, 0x80, 0x3B, 0xE5, 0x64, 0x45, 0x63,
++/*1360*/0x70, 0x11, 0x12, 0x07, 0x5F, 0x40, 0x05, 0x12,
++ 0x08, 0x9E, 0x80, 0x1F, 0x12, 0x07, 0x3E, 0xE5,
++/*1370*/0x41, 0xF0, 0x22, 0xE5, 0x3C, 0xC3, 0x95, 0x38,
++ 0x40, 0x1D, 0x85, 0x3C, 0x38, 0xE5, 0x3C, 0x60,
++/*1380*/0x05, 0x85, 0x3D, 0x39, 0x80, 0x03, 0x85, 0x39,
++ 0x39, 0x8F, 0x3A, 0x12, 0x07, 0xA8, 0xE5, 0x3C,
++/*1390*/0x12, 0x07, 0x53, 0xE5, 0x3D, 0xF0, 0x22, 0x12,
++ 0x07, 0x9F, 0xE5, 0x38, 0x12, 0x07, 0x53, 0xE5,
++/*13A0*/0x39, 0xF0, 0x22, 0xE5, 0x0D, 0xFE, 0xE5, 0x08,
++ 0x8E, 0x54, 0x44, 0x05, 0xF5, 0x55, 0x75, 0x15,
++/*13B0*/0x0F, 0xF5, 0x82, 0x12, 0x0E, 0x7A, 0x12, 0x17,
++ 0xA3, 0x20, 0x31, 0x05, 0x75, 0x15, 0x03, 0x80,
++/*13C0*/0x03, 0x75, 0x15, 0x0B, 0xE5, 0x0A, 0xC3, 0x94,
++ 0x01, 0x50, 0x38, 0x12, 0x14, 0x20, 0x20, 0x31,
++/*13D0*/0x06, 0x05, 0x15, 0x05, 0x15, 0x80, 0x04, 0x15,
++ 0x15, 0x15, 0x15, 0xE5, 0x0A, 0xC3, 0x94, 0x01,
++/*13E0*/0x50, 0x21, 0x12, 0x14, 0x20, 0x20, 0x31, 0x04,
++ 0x05, 0x15, 0x80, 0x02, 0x15, 0x15, 0xE5, 0x0A,
++/*13F0*/0xC3, 0x94, 0x01, 0x50, 0x0E, 0x12, 0x0E, 0x77,
++ 0x12, 0x17, 0xA3, 0x20, 0x31, 0x05, 0x05, 0x15,
++/*1400*/0x12, 0x0E, 0x77, 0xE5, 0x15, 0xB4, 0x08, 0x04,
++ 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x15,
++/*1410*/0xB4, 0x07, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E,
++ 0x00, 0xEE, 0x4F, 0x60, 0x02, 0x05, 0x7F, 0x22,
++/*1420*/0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xE5, 0x15,
++ 0xF0, 0x12, 0x17, 0xA3, 0x22, 0x12, 0x07, 0x2A,
++/*1430*/0x75, 0x83, 0xAE, 0x74, 0xFF, 0x12, 0x07, 0x29,
++ 0xE0, 0x54, 0x1A, 0xF5, 0x34, 0xE0, 0xC4, 0x13,
++/*1440*/0x54, 0x07, 0xF5, 0x35, 0x24, 0xFE, 0x60, 0x24,
++ 0x24, 0xFE, 0x60, 0x3C, 0x24, 0x04, 0x70, 0x63,
++/*1450*/0x75, 0x31, 0x2D, 0xE5, 0x08, 0xFD, 0x74, 0xB6,
++ 0x12, 0x07, 0x92, 0x74, 0xBC, 0x90, 0x07, 0x22,
++/*1460*/0x12, 0x07, 0x95, 0x74, 0x90, 0x12, 0x07, 0xB3,
++ 0x74, 0x92, 0x80, 0x3C, 0x75, 0x31, 0x3A, 0xE5,
++/*1470*/0x08, 0xFD, 0x74, 0xBA, 0x12, 0x07, 0x92, 0x74,
++ 0xC0, 0x90, 0x07, 0x22, 0x12, 0x07, 0xB6, 0x74,
++/*1480*/0xC4, 0x12, 0x07, 0xB3, 0x74, 0xC8, 0x80, 0x20,
++ 0x75, 0x31, 0x35, 0xE5, 0x08, 0xFD, 0x74, 0xB8,
++/*1490*/0x12, 0x07, 0x92, 0x74, 0xBE, 0xFF, 0xED, 0x44,
++ 0x07, 0x90, 0x07, 0x22, 0xCF, 0xF0, 0xA3, 0xEF,
++/*14A0*/0xF0, 0x74, 0xC2, 0x12, 0x07, 0xB3, 0x74, 0xC6,
++ 0xFF, 0xED, 0x44, 0x07, 0xA3, 0xCF, 0xF0, 0xA3,
++/*14B0*/0xEF, 0xF0, 0x22, 0x75, 0x34, 0x01, 0x22, 0x8E,
++ 0x58, 0x8F, 0x59, 0x8C, 0x5A, 0x8D, 0x5B, 0x8A,
++/*14C0*/0x5C, 0x8B, 0x5D, 0x75, 0x5E, 0x01, 0xE4, 0xF5,
++ 0x5F, 0x12, 0x1E, 0xA5, 0x85, 0x59, 0x5E, 0xD3,
++/*14D0*/0xE5, 0x5E, 0x95, 0x5B, 0xE5, 0x5A, 0x12, 0x07,
++ 0x6B, 0x50, 0x57, 0xE5, 0x5D, 0x45, 0x5C, 0x70,
++/*14E0*/0x30, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x92, 0xE5,
++ 0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC6, 0xE5,
++/*14F0*/0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC8, 0xE5,
++ 0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0x90, 0xE5,
++/*1500*/0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE5,
++ 0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0x80,
++/*1510*/0x03, 0x12, 0x07, 0x32, 0xE5, 0x5E, 0xF0, 0xAF,
++ 0x5F, 0x7E, 0x00, 0xAD, 0x5D, 0xAC, 0x5C, 0x12,
++/*1520*/0x04, 0x44, 0xAF, 0x5E, 0x7E, 0x00, 0xAD, 0x5D,
++ 0xAC, 0x5C, 0x12, 0x0B, 0xD1, 0x05, 0x5E, 0x02,
++/*1530*/0x14, 0xCF, 0xAB, 0x5D, 0xAA, 0x5C, 0xAD, 0x5B,
++ 0xAC, 0x5A, 0xAF, 0x59, 0xAE, 0x58, 0x02, 0x1B,
++/*1540*/0xFB, 0x8C, 0x5C, 0x8D, 0x5D, 0x8A, 0x5E, 0x8B,
++ 0x5F, 0x75, 0x60, 0x01, 0xE4, 0xF5, 0x61, 0xF5,
++/*1550*/0x62, 0xF5, 0x63, 0x12, 0x1E, 0xA5, 0x8F, 0x60,
++ 0xD3, 0xE5, 0x60, 0x95, 0x5D, 0xE5, 0x5C, 0x12,
++/*1560*/0x07, 0x6B, 0x50, 0x61, 0xE5, 0x5F, 0x45, 0x5E,
++ 0x70, 0x27, 0x12, 0x07, 0x2A, 0x75, 0x83, 0xB6,
++/*1570*/0xE5, 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0xB8,
++ 0xE5, 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0xBA,
++/*1580*/0xE5, 0x60, 0xF0, 0xAF, 0x61, 0x7E, 0x00, 0xE5,
++ 0x62, 0x12, 0x08, 0x7A, 0x12, 0x0A, 0xFF, 0x80,
++/*1590*/0x19, 0x90, 0x07, 0x24, 0x12, 0x07, 0x35, 0xE5,
++ 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0x8E, 0xE4,
++/*15A0*/0x12, 0x07, 0x29, 0x74, 0x01, 0x12, 0x07, 0x29,
++ 0xE4, 0xF0, 0xAF, 0x63, 0x7E, 0x00, 0xAD, 0x5F,
++/*15B0*/0xAC, 0x5E, 0x12, 0x04, 0x44, 0xAF, 0x60, 0x7E,
++ 0x00, 0xAD, 0x5F, 0xAC, 0x5E, 0x12, 0x12, 0x8B,
++/*15C0*/0x05, 0x60, 0x02, 0x15, 0x58, 0x22, 0x90, 0x11,
++ 0x4D, 0xE4, 0x93, 0x90, 0x07, 0x2E, 0xF0, 0x12,
++/*15D0*/0x08, 0x1F, 0x75, 0x83, 0xAE, 0xE0, 0x54, 0x1A,
++ 0xF5, 0x34, 0x70, 0x67, 0xEF, 0x44, 0x07, 0xF5,
++/*15E0*/0x82, 0x75, 0x83, 0xCE, 0xE0, 0xFF, 0x13, 0x13,
++ 0x13, 0x54, 0x07, 0xF5, 0x36, 0x54, 0x0F, 0xD3,
++/*15F0*/0x94, 0x00, 0x40, 0x06, 0x12, 0x14, 0x2D, 0x12,
++ 0x1B, 0xA9, 0xE5, 0x36, 0x54, 0x0F, 0x24, 0xFE,
++/*1600*/0x60, 0x0C, 0x14, 0x60, 0x0C, 0x14, 0x60, 0x19,
++ 0x24, 0x03, 0x70, 0x37, 0x80, 0x10, 0x02, 0x1E,
++/*1610*/0x91, 0x12, 0x1E, 0x91, 0x12, 0x07, 0x2A, 0x75,
++ 0x83, 0xCE, 0xE0, 0x54, 0xEF, 0xF0, 0x02, 0x1D,
++/*1620*/0xAE, 0x12, 0x10, 0x14, 0xE4, 0xF5, 0x55, 0x12,
++ 0x1D, 0x85, 0x05, 0x55, 0xE5, 0x55, 0xC3, 0x94,
++/*1630*/0x05, 0x40, 0xF4, 0x12, 0x07, 0x2A, 0x75, 0x83,
++ 0xCE, 0xE0, 0x54, 0xC7, 0x12, 0x07, 0x29, 0xE0,
++/*1640*/0x44, 0x08, 0xF0, 0x22, 0xE4, 0xF5, 0x58, 0xF5,
++ 0x59, 0xAF, 0x08, 0xEF, 0x44, 0x07, 0xF5, 0x82,
++/*1650*/0x75, 0x83, 0xD0, 0xE0, 0xFD, 0xC4, 0x54, 0x0F,
++ 0xF5, 0x5A, 0xEF, 0x44, 0x07, 0xF5, 0x82, 0x75,
++/*1660*/0x83, 0x80, 0x74, 0x01, 0xF0, 0x12, 0x08, 0x21,
++ 0x75, 0x83, 0x82, 0xE5, 0x45, 0xF0, 0xEF, 0x44,
++/*1670*/0x07, 0xF5, 0x82, 0x75, 0x83, 0x8A, 0x74, 0xFF,
++ 0xF0, 0x12, 0x1A, 0x4D, 0x12, 0x07, 0x2A, 0x75,
++/*1680*/0x83, 0xBC, 0xE0, 0x54, 0xEF, 0x12, 0x07, 0x29,
++ 0x75, 0x83, 0xBE, 0xE0, 0x54, 0xEF, 0x12, 0x07,
++/*1690*/0x29, 0x75, 0x83, 0xC0, 0xE0, 0x54, 0xEF, 0x12,
++ 0x07, 0x29, 0x75, 0x83, 0xBC, 0xE0, 0x44, 0x10,
++/*16A0*/0x12, 0x07, 0x29, 0x75, 0x83, 0xBE, 0xE0, 0x44,
++ 0x10, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC0, 0xE0,
++/*16B0*/0x44, 0x10, 0xF0, 0xAF, 0x58, 0xE5, 0x59, 0x12,
++ 0x08, 0x78, 0x02, 0x0A, 0xFF, 0xE4, 0xF5, 0x58,
++/*16C0*/0x7D, 0x01, 0xF5, 0x59, 0xAF, 0x35, 0xFE, 0xFC,
++ 0x12, 0x09, 0x15, 0x12, 0x07, 0x2A, 0x75, 0x83,
++/*16D0*/0xB6, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++ 0xB8, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++/*16E0*/0xBA, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++ 0xBC, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++/*16F0*/0xBE, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++ 0xC0, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++/*1700*/0x90, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2,
++ 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0xE4,
++/*1710*/0x12, 0x07, 0x29, 0x75, 0x83, 0x92, 0xE4, 0x12,
++ 0x07, 0x29, 0x75, 0x83, 0xC6, 0xE4, 0x12, 0x07,
++/*1720*/0x29, 0x75, 0x83, 0xC8, 0xE4, 0xF0, 0xAF, 0x58,
++ 0xFE, 0xE5, 0x59, 0x12, 0x08, 0x7A, 0x02, 0x0A,
++/*1730*/0xFF, 0xE5, 0xE2, 0x30, 0xE4, 0x6C, 0xE5, 0xE7,
++ 0x54, 0xC0, 0x64, 0x40, 0x70, 0x64, 0xE5, 0x09,
++/*1740*/0xC4, 0x54, 0x30, 0xFE, 0xE5, 0x08, 0x25, 0xE0,
++ 0x25, 0xE0, 0x54, 0xC0, 0x4E, 0xFE, 0xEF, 0x54,
++/*1750*/0x3F, 0x4E, 0xFD, 0xE5, 0x2B, 0xAE, 0x2A, 0x78,
++ 0x02, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9,
++/*1760*/0xF5, 0x82, 0x8E, 0x83, 0xED, 0xF0, 0xE5, 0x2B,
++ 0xAE, 0x2A, 0x78, 0x02, 0xC3, 0x33, 0xCE, 0x33,
++/*1770*/0xCE, 0xD8, 0xF9, 0xFF, 0xF5, 0x82, 0x8E, 0x83,
++ 0xA3, 0xE5, 0xFE, 0xF0, 0x8F, 0x82, 0x8E, 0x83,
++/*1780*/0xA3, 0xA3, 0xE5, 0xFD, 0xF0, 0x8F, 0x82, 0x8E,
++ 0x83, 0xA3, 0xA3, 0xA3, 0xE5, 0xFC, 0xF0, 0xC3,
++/*1790*/0xE5, 0x2B, 0x94, 0xFA, 0xE5, 0x2A, 0x94, 0x00,
++ 0x50, 0x08, 0x05, 0x2B, 0xE5, 0x2B, 0x70, 0x02,
++/*17A0*/0x05, 0x2A, 0x22, 0xE4, 0xFF, 0xE4, 0xF5, 0x58,
++ 0xF5, 0x56, 0xF5, 0x57, 0x74, 0x82, 0xFC, 0x12,
++/*17B0*/0x0E, 0x04, 0x8C, 0x83, 0xE0, 0xF5, 0x10, 0x54,
++ 0x7F, 0xF0, 0xE5, 0x10, 0x44, 0x80, 0x12, 0x0E,
++/*17C0*/0x98, 0xED, 0xF0, 0x7E, 0x0A, 0x12, 0x0E, 0x04,
++ 0x75, 0x83, 0xA0, 0xE0, 0x20, 0xE0, 0x26, 0xDE,
++/*17D0*/0xF4, 0x05, 0x57, 0xE5, 0x57, 0x70, 0x02, 0x05,
++ 0x56, 0xE5, 0x14, 0x24, 0x01, 0xFD, 0xE4, 0x33,
++/*17E0*/0xFC, 0xD3, 0xE5, 0x57, 0x9D, 0xE5, 0x56, 0x9C,
++ 0x40, 0xD9, 0xE5, 0x0A, 0x94, 0x20, 0x50, 0x02,
++/*17F0*/0x05, 0x0A, 0x43, 0xE1, 0x08, 0xC2, 0x31, 0x12,
++ 0x0E, 0x04, 0x75, 0x83, 0xA6, 0xE0, 0x55, 0x12,
++/*1800*/0x65, 0x12, 0x70, 0x03, 0xD2, 0x31, 0x22, 0xC2,
++ 0x31, 0x22, 0x90, 0x07, 0x26, 0xE0, 0xFA, 0xA3,
++/*1810*/0xE0, 0xF5, 0x82, 0x8A, 0x83, 0xE0, 0xF5, 0x41,
++ 0xE5, 0x39, 0xC3, 0x95, 0x41, 0x40, 0x26, 0xE5,
++/*1820*/0x39, 0x95, 0x41, 0xC3, 0x9F, 0xEE, 0x12, 0x07,
++ 0x6B, 0x40, 0x04, 0x7C, 0x01, 0x80, 0x02, 0x7C,
++/*1830*/0x00, 0xE5, 0x41, 0x64, 0x3F, 0x60, 0x04, 0x7B,
++ 0x01, 0x80, 0x02, 0x7B, 0x00, 0xEC, 0x5B, 0x60,
++/*1840*/0x29, 0x05, 0x41, 0x80, 0x28, 0xC3, 0xE5, 0x41,
++ 0x95, 0x39, 0xC3, 0x9F, 0xEE, 0x12, 0x07, 0x6B,
++/*1850*/0x40, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00,
++ 0xE5, 0x41, 0x60, 0x04, 0x7E, 0x01, 0x80, 0x02,
++/*1860*/0x7E, 0x00, 0xEF, 0x5E, 0x60, 0x04, 0x15, 0x41,
++ 0x80, 0x03, 0x85, 0x39, 0x41, 0x85, 0x3A, 0x40,
++/*1870*/0x22, 0xE5, 0xE2, 0x30, 0xE4, 0x60, 0xE5, 0xE1,
++ 0x30, 0xE2, 0x5B, 0xE5, 0x09, 0x70, 0x04, 0x7F,
++/*1880*/0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x08, 0x70,
++ 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE,
++/*1890*/0x5F, 0x60, 0x43, 0x53, 0xF9, 0xF8, 0xE5, 0xE2,
++ 0x30, 0xE4, 0x3B, 0xE5, 0xE1, 0x30, 0xE2, 0x2E,
++/*18A0*/0x43, 0xFA, 0x02, 0x53, 0xFA, 0xFB, 0xE4, 0xF5,
++ 0x10, 0x90, 0x94, 0x70, 0xE5, 0x10, 0xF0, 0xE5,
++/*18B0*/0xE1, 0x30, 0xE2, 0xE7, 0x90, 0x94, 0x70, 0xE0,
++ 0x65, 0x10, 0x60, 0x03, 0x43, 0xFA, 0x04, 0x05,
++/*18C0*/0x10, 0x90, 0x94, 0x70, 0xE5, 0x10, 0xF0, 0x70,
++ 0xE6, 0x12, 0x00, 0x06, 0x80, 0xE1, 0x53, 0xFA,
++/*18D0*/0xFD, 0x53, 0xFA, 0xFB, 0x80, 0xC0, 0x22, 0x8F,
++ 0x54, 0x12, 0x00, 0x06, 0xE5, 0xE1, 0x30, 0xE0,
++/*18E0*/0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5,
++ 0x7E, 0xD3, 0x94, 0x05, 0x40, 0x04, 0x7E, 0x01,
++/*18F0*/0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x60, 0x3D,
++ 0x85, 0x54, 0x11, 0xE5, 0xE2, 0x20, 0xE1, 0x32,
++/*1900*/0x74, 0xCE, 0x12, 0x1A, 0x05, 0x30, 0xE7, 0x04,
++ 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, 0x8F, 0x82,
++/*1910*/0x8E, 0x83, 0xE0, 0x30, 0xE6, 0x04, 0x7F, 0x01,
++ 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x5D, 0x70, 0x15,
++/*1920*/0x12, 0x15, 0xC6, 0x74, 0xCE, 0x12, 0x1A, 0x05,
++ 0x30, 0xE6, 0x07, 0xE0, 0x44, 0x80, 0xF0, 0x43,
++/*1930*/0xF9, 0x80, 0x12, 0x18, 0x71, 0x22, 0x12, 0x0E,
++ 0x44, 0xE5, 0x16, 0x25, 0xE0, 0x25, 0xE0, 0x24,
++/*1940*/0xB0, 0xF5, 0x82, 0xE4, 0x34, 0x1A, 0xF5, 0x83,
++ 0xE4, 0x93, 0xF5, 0x0F, 0xE5, 0x16, 0x25, 0xE0,
++/*1950*/0x25, 0xE0, 0x24, 0xB1, 0xF5, 0x82, 0xE4, 0x34,
++ 0x1A, 0xF5, 0x83, 0xE4, 0x93, 0xF5, 0x0E, 0x12,
++/*1960*/0x0E, 0x65, 0xF5, 0x10, 0xE5, 0x0F, 0x54, 0xF0,
++ 0x12, 0x0E, 0x17, 0x75, 0x83, 0x8C, 0xEF, 0xF0,
++/*1970*/0xE5, 0x0F, 0x30, 0xE0, 0x0C, 0x12, 0x0E, 0x04,
++ 0x75, 0x83, 0x86, 0xE0, 0x44, 0x40, 0xF0, 0x80,
++/*1980*/0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0x86, 0xE0,
++ 0x54, 0xBF, 0xF0, 0x12, 0x0E, 0x91, 0x75, 0x83,
++/*1990*/0x82, 0xE5, 0x0E, 0xF0, 0x22, 0x7F, 0x05, 0x12,
++ 0x17, 0x31, 0x12, 0x0E, 0x04, 0x12, 0x0E, 0x33,
++/*19A0*/0x74, 0x02, 0xF0, 0x74, 0x8E, 0xFE, 0x12, 0x0E,
++ 0x04, 0x12, 0x0E, 0x0B, 0xEF, 0xF0, 0x75, 0x15,
++/*19B0*/0x70, 0x12, 0x0F, 0xF7, 0x20, 0x34, 0x05, 0x75,
++ 0x15, 0x10, 0x80, 0x03, 0x75, 0x15, 0x50, 0x12,
++/*19C0*/0x0F, 0xF7, 0x20, 0x34, 0x04, 0x74, 0x10, 0x80,
++ 0x02, 0x74, 0xF0, 0x25, 0x15, 0xF5, 0x15, 0x12,
++/*19D0*/0x0E, 0x21, 0xEF, 0xF0, 0x12, 0x10, 0x91, 0x20,
++ 0x34, 0x17, 0xE5, 0x15, 0x64, 0x30, 0x60, 0x0C,
++/*19E0*/0x74, 0x10, 0x25, 0x15, 0xF5, 0x15, 0xB4, 0x80,
++ 0x03, 0xE4, 0xF5, 0x15, 0x12, 0x0E, 0x21, 0xEF,
++/*19F0*/0xF0, 0x22, 0xF0, 0xE5, 0x0B, 0x25, 0xE0, 0x25,
++ 0xE0, 0x24, 0x82, 0xF5, 0x82, 0xE4, 0x34, 0x07,
++/*1A00*/0xF5, 0x83, 0x22, 0x74, 0x88, 0xFE, 0xE5, 0x08,
++ 0x44, 0x07, 0xFF, 0xF5, 0x82, 0x8E, 0x83, 0xE0,
++/*1A10*/0x22, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82,
++ 0x22, 0xF0, 0xE0, 0x54, 0xC0, 0x8F, 0x82, 0x8E,
++/*1A20*/0x83, 0xF0, 0x22, 0xEF, 0x44, 0x07, 0xF5, 0x82,
++ 0x75, 0x83, 0x86, 0xE0, 0x54, 0x10, 0xD3, 0x94,
++/*1A30*/0x00, 0x22, 0xF0, 0x90, 0x07, 0x15, 0xE0, 0x04,
++ 0xF0, 0x22, 0x44, 0x06, 0xF5, 0x82, 0x75, 0x83,
++/*1A40*/0x9E, 0xE0, 0x22, 0xFE, 0xEF, 0x44, 0x07, 0xF5,
++ 0x82, 0x8E, 0x83, 0xE0, 0x22, 0xE4, 0x90, 0x07,
++/*1A50*/0x2A, 0xF0, 0xA3, 0xF0, 0x12, 0x07, 0x2A, 0x75,
++ 0x83, 0x82, 0xE0, 0x54, 0x7F, 0x12, 0x07, 0x29,
++/*1A60*/0xE0, 0x44, 0x80, 0xF0, 0x12, 0x10, 0xFC, 0x12,
++ 0x08, 0x1F, 0x75, 0x83, 0xA0, 0xE0, 0x20, 0xE0,
++/*1A70*/0x1A, 0x90, 0x07, 0x2B, 0xE0, 0x04, 0xF0, 0x70,
++ 0x06, 0x90, 0x07, 0x2A, 0xE0, 0x04, 0xF0, 0x90,
++/*1A80*/0x07, 0x2A, 0xE0, 0xB4, 0x10, 0xE1, 0xA3, 0xE0,
++ 0xB4, 0x00, 0xDC, 0xEE, 0x44, 0xA6, 0xFC, 0xEF,
++/*1A90*/0x44, 0x07, 0xF5, 0x82, 0x8C, 0x83, 0xE0, 0xF5,
++ 0x32, 0xEE, 0x44, 0xA8, 0xFE, 0xEF, 0x44, 0x07,
++/*1AA0*/0xF5, 0x82, 0x8E, 0x83, 0xE0, 0xF5, 0x33, 0x22,
++ 0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x90,
++/*1AB0*/0x00, 0x20, 0x0F, 0x92, 0x00, 0x21, 0x0F, 0x94,
++ 0x00, 0x22, 0x0F, 0x96, 0x00, 0x23, 0x0F, 0x98,
++/*1AC0*/0x00, 0x24, 0x0F, 0x9A, 0x00, 0x25, 0x0F, 0x9C,
++ 0x00, 0x26, 0x0F, 0x9E, 0x00, 0x27, 0x0F, 0xA0,
++/*1AD0*/0x01, 0x20, 0x01, 0xA2, 0x01, 0x21, 0x01, 0xA4,
++ 0x01, 0x22, 0x01, 0xA6, 0x01, 0x23, 0x01, 0xA8,
++/*1AE0*/0x01, 0x24, 0x01, 0xAA, 0x01, 0x25, 0x01, 0xAC,
++ 0x01, 0x26, 0x01, 0xAE, 0x01, 0x27, 0x01, 0xB0,
++/*1AF0*/0x01, 0x28, 0x01, 0xB4, 0x00, 0x28, 0x0F, 0xB6,
++ 0x40, 0x28, 0x0F, 0xB8, 0x61, 0x28, 0x01, 0xCB,
++/*1B00*/0xEF, 0xCB, 0xCA, 0xEE, 0xCA, 0x7F, 0x01, 0xE4,
++ 0xFD, 0xEB, 0x4A, 0x70, 0x24, 0xE5, 0x08, 0xF5,
++/*1B10*/0x82, 0x74, 0xB6, 0x12, 0x08, 0x29, 0xE5, 0x08,
++ 0xF5, 0x82, 0x74, 0xB8, 0x12, 0x08, 0x29, 0xE5,
++/*1B20*/0x08, 0xF5, 0x82, 0x74, 0xBA, 0x12, 0x08, 0x29,
++ 0x7E, 0x00, 0x7C, 0x00, 0x12, 0x0A, 0xFF, 0x80,
++/*1B30*/0x12, 0x90, 0x07, 0x26, 0x12, 0x07, 0x35, 0xE5,
++ 0x41, 0xF0, 0x90, 0x07, 0x24, 0x12, 0x07, 0x35,
++/*1B40*/0xE5, 0x40, 0xF0, 0x12, 0x07, 0x2A, 0x75, 0x83,
++ 0x8E, 0xE4, 0x12, 0x07, 0x29, 0x74, 0x01, 0x12,
++/*1B50*/0x07, 0x29, 0xE4, 0xF0, 0x22, 0xE4, 0xF5, 0x26,
++ 0xF5, 0x27, 0x53, 0xE1, 0xFE, 0xF5, 0x2A, 0x75,
++/*1B60*/0x2B, 0x01, 0xF5, 0x08, 0x7F, 0x01, 0x12, 0x17,
++ 0x31, 0x30, 0x30, 0x1C, 0x90, 0x1A, 0xA9, 0xE4,
++/*1B70*/0x93, 0xF5, 0x10, 0x90, 0x1F, 0xF9, 0xE4, 0x93,
++ 0xF5, 0x10, 0x90, 0x00, 0x41, 0xE4, 0x93, 0xF5,
++/*1B80*/0x10, 0x90, 0x1E, 0xCA, 0xE4, 0x93, 0xF5, 0x10,
++ 0x7F, 0x02, 0x12, 0x17, 0x31, 0x12, 0x0F, 0x54,
++/*1B90*/0x7F, 0x03, 0x12, 0x17, 0x31, 0x12, 0x00, 0x06,
++ 0xE5, 0xE2, 0x30, 0xE7, 0x09, 0x12, 0x10, 0x00,
++/*1BA0*/0x30, 0x30, 0x03, 0x12, 0x11, 0x00, 0x02, 0x00,
++ 0x47, 0x12, 0x08, 0x1F, 0x75, 0x83, 0xD0, 0xE0,
++/*1BB0*/0xC4, 0x54, 0x0F, 0xFD, 0x75, 0x43, 0x01, 0x75,
++ 0x44, 0xFF, 0x12, 0x08, 0xAA, 0x74, 0x04, 0xF0,
++/*1BC0*/0x75, 0x3B, 0x01, 0xED, 0x14, 0x60, 0x0C, 0x14,
++ 0x60, 0x0B, 0x14, 0x60, 0x0F, 0x24, 0x03, 0x70,
++/*1BD0*/0x0B, 0x80, 0x09, 0x80, 0x00, 0x12, 0x08, 0xA7,
++ 0x04, 0xF0, 0x80, 0x06, 0x12, 0x08, 0xA7, 0x74,
++/*1BE0*/0x04, 0xF0, 0xEE, 0x44, 0x82, 0xFE, 0xEF, 0x44,
++ 0x07, 0xF5, 0x82, 0x8E, 0x83, 0xE5, 0x45, 0x12,
++/*1BF0*/0x08, 0xBE, 0x75, 0x83, 0x82, 0xE5, 0x31, 0xF0,
++ 0x02, 0x11, 0x4C, 0x8E, 0x60, 0x8F, 0x61, 0x12,
++/*1C00*/0x1E, 0xA5, 0xE4, 0xFF, 0xCE, 0xED, 0xCE, 0xEE,
++ 0xD3, 0x95, 0x61, 0xE5, 0x60, 0x12, 0x07, 0x6B,
++/*1C10*/0x40, 0x39, 0x74, 0x20, 0x2E, 0xF5, 0x82, 0xE4,
++ 0x34, 0x03, 0xF5, 0x83, 0xE0, 0x70, 0x03, 0xFF,
++/*1C20*/0x80, 0x26, 0x12, 0x08, 0xE2, 0xFD, 0xC3, 0x9F,
++ 0x40, 0x1E, 0xCF, 0xED, 0xCF, 0xEB, 0x4A, 0x70,
++/*1C30*/0x0B, 0x8D, 0x42, 0x12, 0x08, 0xEE, 0xF5, 0x41,
++ 0x8E, 0x40, 0x80, 0x0C, 0x12, 0x08, 0xE2, 0xF5,
++/*1C40*/0x38, 0x12, 0x08, 0xEE, 0xF5, 0x39, 0x8E, 0x3A,
++ 0x1E, 0x80, 0xBC, 0x22, 0x75, 0x58, 0x01, 0xE5,
++/*1C50*/0x35, 0x70, 0x0C, 0x12, 0x07, 0xCC, 0xE0, 0xF5,
++ 0x4A, 0x12, 0x07, 0xD8, 0xE0, 0xF5, 0x4C, 0xE5,
++/*1C60*/0x35, 0xB4, 0x04, 0x0C, 0x12, 0x07, 0xE4, 0xE0,
++ 0xF5, 0x4A, 0x12, 0x07, 0xF0, 0xE0, 0xF5, 0x4C,
++/*1C70*/0xE5, 0x35, 0xB4, 0x01, 0x04, 0x7F, 0x01, 0x80,
++ 0x02, 0x7F, 0x00, 0xE5, 0x35, 0xB4, 0x02, 0x04,
++/*1C80*/0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F,
++ 0x60, 0x0C, 0x12, 0x07, 0xFC, 0xE0, 0xF5, 0x4A,
++/*1C90*/0x12, 0x08, 0x08, 0xE0, 0xF5, 0x4C, 0x85, 0x41,
++ 0x49, 0x85, 0x40, 0x4B, 0x22, 0x75, 0x5B, 0x01,
++/*1CA0*/0x90, 0x07, 0x24, 0x12, 0x07, 0x35, 0xE0, 0x54,
++ 0x1F, 0xFF, 0xD3, 0x94, 0x02, 0x50, 0x04, 0x8F,
++/*1CB0*/0x58, 0x80, 0x05, 0xEF, 0x24, 0xFE, 0xF5, 0x58,
++ 0xEF, 0xC3, 0x94, 0x18, 0x40, 0x05, 0x75, 0x59,
++/*1CC0*/0x18, 0x80, 0x04, 0xEF, 0x04, 0xF5, 0x59, 0x85,
++ 0x43, 0x5A, 0xAF, 0x58, 0x7E, 0x00, 0xAD, 0x59,
++/*1CD0*/0x7C, 0x00, 0xAB, 0x5B, 0x7A, 0x00, 0x12, 0x15,
++ 0x41, 0xAF, 0x5A, 0x7E, 0x00, 0x12, 0x18, 0x0A,
++/*1CE0*/0xAF, 0x5B, 0x7E, 0x00, 0x02, 0x1A, 0xFF, 0xE5,
++ 0xE2, 0x30, 0xE7, 0x0E, 0x12, 0x10, 0x03, 0xC2,
++/*1CF0*/0x30, 0x30, 0x30, 0x03, 0x12, 0x10, 0xFF, 0x20,
++ 0x33, 0x28, 0xE5, 0xE7, 0x30, 0xE7, 0x05, 0x12,
++/*1D00*/0x0E, 0xA2, 0x80, 0x0D, 0xE5, 0xFE, 0xC3, 0x94,
++ 0x20, 0x50, 0x06, 0x12, 0x0E, 0xA2, 0x43, 0xF9,
++/*1D10*/0x08, 0xE5, 0xF2, 0x30, 0xE7, 0x03, 0x53, 0xF9,
++ 0x7F, 0xE5, 0xF1, 0x54, 0x70, 0xD3, 0x94, 0x00,
++/*1D20*/0x50, 0xD8, 0x22, 0x12, 0x0E, 0x04, 0x75, 0x83,
++ 0x80, 0xE4, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0x12,
++/*1D30*/0x0D, 0xFD, 0x75, 0x83, 0x84, 0x12, 0x0E, 0x02,
++ 0x75, 0x83, 0x86, 0x12, 0x0E, 0x02, 0x75, 0x83,
++/*1D40*/0x8C, 0xE0, 0x54, 0xF3, 0x12, 0x0E, 0x03, 0x75,
++ 0x83, 0x8E, 0x12, 0x0E, 0x02, 0x75, 0x83, 0x94,
++/*1D50*/0xE0, 0x54, 0xFB, 0xF0, 0x22, 0x12, 0x07, 0x2A,
++ 0x75, 0x83, 0x8E, 0xE4, 0x12, 0x07, 0x29, 0x74,
++/*1D60*/0x01, 0x12, 0x07, 0x29, 0xE4, 0x12, 0x08, 0xBE,
++ 0x75, 0x83, 0x8C, 0xE0, 0x44, 0x20, 0x12, 0x08,
++/*1D70*/0xBE, 0xE0, 0x54, 0xDF, 0xF0, 0x74, 0x84, 0x85,
++ 0x08, 0x82, 0xF5, 0x83, 0xE0, 0x54, 0x7F, 0xF0,
++/*1D80*/0xE0, 0x44, 0x80, 0xF0, 0x22, 0x75, 0x56, 0x01,
++ 0xE4, 0xFD, 0xF5, 0x57, 0xAF, 0x35, 0xFE, 0xFC,
++/*1D90*/0x12, 0x09, 0x15, 0x12, 0x1C, 0x9D, 0x12, 0x1E,
++ 0x7A, 0x12, 0x1C, 0x4C, 0xAF, 0x57, 0x7E, 0x00,
++/*1DA0*/0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44, 0xAF,
++ 0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0x75, 0x56,
++/*1DB0*/0x01, 0xE4, 0xFD, 0xF5, 0x57, 0xAF, 0x35, 0xFE,
++ 0xFC, 0x12, 0x09, 0x15, 0x12, 0x1C, 0x9D, 0x12,
++/*1DC0*/0x1E, 0x7A, 0x12, 0x1C, 0x4C, 0xAF, 0x57, 0x7E,
++ 0x00, 0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44,
++/*1DD0*/0xAF, 0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0xE4,
++ 0xF5, 0x16, 0x12, 0x0E, 0x44, 0xFE, 0xE5, 0x08,
++/*1DE0*/0x44, 0x05, 0xFF, 0x12, 0x0E, 0x65, 0x8F, 0x82,
++ 0x8E, 0x83, 0xF0, 0x05, 0x16, 0xE5, 0x16, 0xC3,
++/*1DF0*/0x94, 0x14, 0x40, 0xE6, 0xE5, 0x08, 0x12, 0x0E,
++ 0x2B, 0xE4, 0xF0, 0x22, 0xE4, 0xF5, 0x58, 0xF5,
++/*1E00*/0x59, 0xF5, 0x5A, 0xFF, 0xFE, 0xAD, 0x58, 0xFC,
++ 0x12, 0x09, 0x15, 0x7F, 0x04, 0x7E, 0x00, 0xAD,
++/*1E10*/0x58, 0x7C, 0x00, 0x12, 0x09, 0x15, 0x7F, 0x02,
++ 0x7E, 0x00, 0xAD, 0x58, 0x7C, 0x00, 0x02, 0x09,
++/*1E20*/0x15, 0xE5, 0x3C, 0x25, 0x3E, 0xFC, 0xE5, 0x42,
++ 0x24, 0x00, 0xFB, 0xE4, 0x33, 0xFA, 0xEC, 0xC3,
++/*1E30*/0x9B, 0xEA, 0x12, 0x07, 0x6B, 0x40, 0x0B, 0x8C,
++ 0x42, 0xE5, 0x3D, 0x25, 0x3F, 0xF5, 0x41, 0x8F,
++/*1E40*/0x40, 0x22, 0x12, 0x09, 0x0B, 0x22, 0x74, 0x84,
++ 0xF5, 0x18, 0x85, 0x08, 0x19, 0x85, 0x19, 0x82,
++/*1E50*/0x85, 0x18, 0x83, 0xE0, 0x54, 0x7F, 0xF0, 0xE0,
++ 0x44, 0x80, 0xF0, 0xE0, 0x44, 0x80, 0xF0, 0x22,
++/*1E60*/0xEF, 0x4E, 0x70, 0x0B, 0x12, 0x07, 0x2A, 0x75,
++ 0x83, 0xD2, 0xE0, 0x54, 0xDF, 0xF0, 0x22, 0x12,
++/*1E70*/0x07, 0x2A, 0x75, 0x83, 0xD2, 0xE0, 0x44, 0x20,
++ 0xF0, 0x22, 0x75, 0x58, 0x01, 0x90, 0x07, 0x26,
++/*1E80*/0x12, 0x07, 0x35, 0xE0, 0x54, 0x3F, 0xF5, 0x41,
++ 0x12, 0x07, 0x32, 0xE0, 0x54, 0x3F, 0xF5, 0x40,
++/*1E90*/0x22, 0x75, 0x56, 0x02, 0xE4, 0xF5, 0x57, 0x12,
++ 0x1D, 0xFC, 0xAF, 0x57, 0x7E, 0x00, 0xAD, 0x56,
++/*1EA0*/0x7C, 0x00, 0x02, 0x04, 0x44, 0xE4, 0xF5, 0x42,
++ 0xF5, 0x41, 0xF5, 0x40, 0xF5, 0x38, 0xF5, 0x39,
++/*1EB0*/0xF5, 0x3A, 0x22, 0xEF, 0x54, 0x07, 0xFF, 0xE5,
++ 0xF9, 0x54, 0xF8, 0x4F, 0xF5, 0xF9, 0x22, 0x7F,
++/*1EC0*/0x01, 0xE4, 0xFE, 0x0F, 0x0E, 0xBE, 0xFF, 0xFB,
++ 0x22, 0x01, 0x20, 0x00, 0x01, 0x04, 0x20, 0x00,
++/*1ED0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1EE0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1EF0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F00*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F10*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F20*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F30*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F40*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F50*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F60*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F70*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F80*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F90*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FA0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FB0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FC0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FD0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FE0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FF0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x81
++};
+
-+ return 0;
++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 @@
+/*
-+ * Helper function for ibft_register_kobjects.
++ * 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.
+ */
-+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;
-+ }
++#include <linux/spinlock.h>
+
-+ ibft_kobj->kobj.kset = ibft_kset;
++#include "ipath_kernel.h"
++#include "ipath_verbs.h"
++#include "ipath_common.h"
+
-+ rc = kobject_init_and_add(&ibft_kobj->kobj, &ibft_ktype,
-+ NULL, ibft_id_names[hdr->id], hdr->index);
++#define SDMA_DESCQ_SZ PAGE_SIZE /* 256 entries per 4KB page */
+
-+ if (rc) {
-+ kfree(ibft_kobj);
-+ goto out;
++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);
+ }
++}
+
-+ 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);
-+ }
++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);
+ }
-+
-+ /* 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)
++static void vl15_watchdog_timeout(unsigned long opaque)
+{
-+ 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));
++ struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
+
-+ /* 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;
-+ }
++ 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");
+ }
-+
-+ return rc;
+}
+
-+static void ibft_unregister(struct list_head *attr_list,
-+ struct list_head *kobj_list)
++static void unmap_desc(struct ipath_devdata *dd, unsigned head)
+{
-+ struct ibft_kobject *data = NULL, *n;
-+ struct ibft_attribute *attr = NULL, *m;
++ __le64 *descqp = &dd->ipath_sdma_descq[head].qw[0];
++ u64 desc[2];
++ dma_addr_t addr;
++ size_t len;
+
-+ 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);
++ desc[0] = le64_to_cpu(descqp[0]);
++ desc[1] = le64_to_cpu(descqp[1]);
+
-+ 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);
++ addr = (desc[1] << 32) | (desc[0] >> 32);
++ len = (desc[0] >> 14) & (0x7ffULL << 2);
++ dma_unmap_single(&dd->pcidev->dev, addr, len, DMA_TO_DEVICE);
+}
+
-+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)
++/*
++ * ipath_sdma_lock should be locked before calling this.
++ */
++int ipath_sdma_make_progress(struct ipath_devdata *dd)
+{
-+ struct ibft_attribute *attr = NULL;
-+ struct ibft_hdr *hdr = kobj_data->hdr;
++ struct list_head *lp = NULL;
++ struct ipath_sdma_txreq *txp = NULL;
++ u16 dmahead;
++ u16 start_idx = 0;
++ int progress = 0;
+
-+ attr = kmalloc(sizeof(*attr), GFP_KERNEL);
-+ if (!attr)
-+ return -ENOMEM;
++ 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;
++ }
+
-+ attr->attr.name = name;
-+ attr->attr.mode = S_IRUSR;
-+ attr->attr.owner = THIS_MODULE;
++ /*
++ * 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;
+
-+ attr->hdr = hdr;
-+ attr->show = show;
-+ attr->kobj = &kobj_data->kobj;
-+ attr->type = type;
++ 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;
++ }
+
-+ list_add_tail(&attr->node, list);
++ /* 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;
+
-+ return 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;
+}
+
-+/*
-+ * 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)
++static void ipath_sdma_notify(struct ipath_devdata *dd, struct list_head *list)
+{
-+ int rc = 0;
++ struct ipath_sdma_txreq *txp, *txp_next;
+
-+ 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;
-+ }
++ list_for_each_entry_safe(txp, txp_next, list, list) {
++ list_del_init(&txp->list);
+
-+ return rc;
++ if (txp->callback)
++ (*txp->callback)(txp->callback_cookie,
++ txp->callback_status);
++ }
+}
+
-+static int __init ibft_check_tgt_for(struct ibft_tgt *tgt, int entry)
++static void sdma_notify_taskbody(struct ipath_devdata *dd)
+{
-+ int rc = 0;
++ unsigned long flags;
++ struct list_head list;
+
-+ 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;
-+ }
++ INIT_LIST_HEAD(&list);
+
-+ return rc;
-+}
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
+
-+static int __init ibft_check_initiator_for(struct ibft_initiator *init,
-+ int entry)
-+{
-+ int rc = 0;
++ list_splice_init(&dd->ipath_sdma_notifylist, &list);
+
-+ 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;
-+ }
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
+
-+ return rc;
++ 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);
+}
+
-+/*
-+ * Register the attributes for all of the kobjects.
-+ */
-+static int __init ibft_register_attributes(struct list_head *kobject_list,
-+ struct list_head *attr_list)
++static void sdma_notify_task(unsigned long opaque)
+{
-+ 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;
-+ }
-+ }
++ struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
+
-+ return rc;
++ if (!test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
++ sdma_notify_taskbody(dd);
+}
+
-+/*
-+ * ibft_init() - creates sysfs tree entries for the iBFT data.
-+ */
-+static int __init ibft_init(void)
++static void dump_sdma_state(struct ipath_devdata *dd)
+{
-+ int rc = 0;
++ unsigned long reg;
+
-+ ibft_kset = kset_create_and_add("ibft", NULL, firmware_kobj);
-+ if (!ibft_kset)
-+ return -ENOMEM;
++ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmastatus);
++ ipath_cdbg(VERBOSE, "kr_senddmastatus: 0x%016lx\n", reg);
+
-+ if (ibft_addr) {
-+ printk(KERN_INFO "iBFT detected at 0x%lx.\n",
-+ virt_to_phys((void *)ibft_addr));
++ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendctrl);
++ ipath_cdbg(VERBOSE, "kr_sendctrl: 0x%016lx\n", reg);
+
-+ rc = ibft_check_device();
-+ if (rc)
-+ goto out_firmware_unregister;
++ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmabufmask0);
++ ipath_cdbg(VERBOSE, "kr_senddmabufmask0: 0x%016lx\n", reg);
+
-+ /* Scan the IBFT for data and register the kobjects. */
-+ rc = ibft_register_kobjects(ibft_addr, &ibft_kobject_list);
-+ if (rc)
-+ goto out_free;
++ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmabufmask1);
++ ipath_cdbg(VERBOSE, "kr_senddmabufmask1: 0x%016lx\n", reg);
+
-+ /* 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");
++ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmabufmask2);
++ ipath_cdbg(VERBOSE, "kr_senddmabufmask2: 0x%016lx\n", reg);
+
-+ return 0;
++ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmatail);
++ ipath_cdbg(VERBOSE, "kr_senddmatail: 0x%016lx\n", reg);
+
-+out_free:
-+ ibft_unregister(&ibft_attr_list, &ibft_kobject_list);
-+out_firmware_unregister:
-+ kset_unregister(ibft_kset);
-+ return rc;
++ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmahead);
++ ipath_cdbg(VERBOSE, "kr_senddmahead: 0x%016lx\n", reg);
+}
+
-+static void __exit ibft_exit(void)
++static void sdma_abort_task(unsigned long opaque)
+{
-+ ibft_unregister(&ibft_attr_list, &ibft_kobject_list);
-+ kset_unregister(ibft_kset);
-+}
-+
-+module_init(ibft_init);
-+module_exit(ibft_exit);
-diff --git a/drivers/firmware/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c
-new file mode 100644
-index 0000000..d0e5fa4
---- /dev/null
-+++ b/drivers/firmware/iscsi_ibft_find.c
-@@ -0,0 +1,84 @@
-+/*
-+ * Copyright 2007 Red Hat, Inc.
-+ * by Peter Jones <pjones at redhat.com>
-+ * Copyright 2007 IBM, Inc.
-+ * by Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
-+ * Copyright 2008
-+ * by Konrad Rzeszutek <ketuzsezr at darnok.org>
-+ *
-+ * This code finds the iSCSI Boot Format Table.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License v2.0 as published by
-+ * the Free Software Foundation
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
++ struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
++ u64 status;
++ unsigned long flags;
+
-+#include <linux/bootmem.h>
-+#include <linux/blkdev.h>
-+#include <linux/ctype.h>
-+#include <linux/device.h>
-+#include <linux/err.h>
-+#include <linux/init.h>
-+#include <linux/limits.h>
-+#include <linux/module.h>
-+#include <linux/pci.h>
-+#include <linux/slab.h>
-+#include <linux/stat.h>
-+#include <linux/string.h>
-+#include <linux/types.h>
++ if (test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
++ return;
+
-+#include <asm/mmzone.h>
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
+
-+/*
-+ * Physical location of iSCSI Boot Format Table.
-+ */
-+struct ibft_table_header *ibft_addr;
-+EXPORT_SYMBOL_GPL(ibft_addr);
++ status = dd->ipath_sdma_status & IPATH_SDMA_ABORT_MASK;
+
-+#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 */
++ /* 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;
++ }
+
-+/*
-+ * 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;
++ /* 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;
+
-+ ibft_addr = 0;
++ hwstatus = ipath_read_kreg64(dd,
++ dd->ipath_kregs->kr_senddmastatus);
+
-+ 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 (/* 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);
+ }
-+ }
-+ 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
++ /* 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);
+
- 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 }
++ /* 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;
+
-+ { VENDOR_ID_SUNPLUS, DEVICE_ID_SUNPLUS_WDESKTOP, quirk_sunplus_wdesktop },
++ /* Reset SendDmaLenGen */
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmalengen,
++ (u64) dd->ipath_sdma_descq_cnt | (1ULL << 18));
+
-+ { 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.
++ /* done with sdma state for a bit */
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
+
- 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;
++ /*
++ * 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);
+
-+ if (dev->manufacturer)
-+ strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
++ /* make sure I see next message */
++ dd->ipath_sdma_abort_jiffies = 0;
+
-+ if (dev->product) {
-+ if (dev->manufacturer)
-+ strlcat(hid->name, " ", sizeof(hid->name));
-+ strlcat(hid->name, dev->product, sizeof(hid->name));
++ goto done;
+ }
+
-+ 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);
-+ }
++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;
+
- /* Change the polling interval of mice. */
- if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
- interval = hid_mousepoll_interval;
-@@ -844,8 +871,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
- goto fail;
- }
-
-- init_waitqueue_head(&hid->wait);
--
-+ init_waitqueue_head(&usbhid->wait);
- INIT_WORK(&usbhid->reset_work, hid_reset);
- setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
-
-@@ -859,22 +885,6 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
- usbhid->intf = intf;
- usbhid->ifnum = interface->desc.bInterfaceNumber;
-
-- hid->name[0] = 0;
--
-- if (dev->manufacturer)
-- strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
--
-- if (dev->product) {
-- if (dev->manufacturer)
-- strlcat(hid->name, " ", sizeof(hid->name));
-- strlcat(hid->name, dev->product, sizeof(hid->name));
-- }
--
-- if (!strlen(hid->name))
-- snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
-- le16_to_cpu(dev->descriptor.idVendor),
-- le16_to_cpu(dev->descriptor.idProduct));
--
- hid->bus = BUS_USB;
- hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
- hid->product = le16_to_cpu(dev->descriptor.idProduct);
-@@ -932,6 +942,7 @@ static void hid_disconnect(struct usb_interface *intf)
-
- spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
- usb_set_intfdata(intf, NULL);
-+ set_bit(HID_DISCONNECTED, &usbhid->iofl);
- spin_unlock_irq(&usbhid->inlock);
- usb_kill_urb(usbhid->urbin);
- usb_kill_urb(usbhid->urbout);
-diff --git a/drivers/hid/usbhid/hid-ff.c b/drivers/hid/usbhid/hid-ff.c
-index 4c210e1..1d0dac5 100644
---- a/drivers/hid/usbhid/hid-ff.c
-+++ b/drivers/hid/usbhid/hid-ff.c
-@@ -59,6 +59,9 @@ static struct hid_ff_initializer inits[] = {
- { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */
- { 0x46d, 0xca03, hid_lgff_init }, /* Logitech MOMO force wheel */
- #endif
-+#ifdef CONFIG_LOGIRUMBLEPAD2_FF
-+ { 0x46d, 0xc218, hid_lg2ff_init }, /* Logitech Rumblepad 2 */
-+#endif
- #ifdef CONFIG_PANTHERLORD_FF
- { 0x810, 0x0001, hid_plff_init }, /* "Twin USB Joystick" */
- { 0xe8f, 0x0003, hid_plff_init }, /* "GreenAsia Inc. USB Joystick " */
-diff --git a/drivers/hid/usbhid/hid-lg2ff.c b/drivers/hid/usbhid/hid-lg2ff.c
-new file mode 100644
-index 0000000..d469bd0
---- /dev/null
-+++ b/drivers/hid/usbhid/hid-lg2ff.c
-@@ -0,0 +1,114 @@
-+/*
-+ * Force feedback support for Logitech Rumblepad 2
-+ *
-+ * Copyright (c) 2008 Anssi Hannula <anssi.hannula at gmail.com>
-+ */
++unlock:
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++done:
++ return;
++}
+
+/*
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You 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
++ * This is called from interrupt context.
+ */
-+
-+
-+#include <linux/input.h>
-+#include <linux/usb.h>
-+#include <linux/hid.h>
-+#include "usbhid.h"
-+
-+struct lg2ff_device {
-+ struct hid_report *report;
-+};
-+
-+static int play_effect(struct input_dev *dev, void *data,
-+ struct ff_effect *effect)
++void ipath_sdma_intr(struct ipath_devdata *dd)
+{
-+ 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;
++ unsigned long flags;
+
-+ if (weak || strong) {
-+ weak = weak * 0xff / 0xffff;
-+ strong = strong * 0xff / 0xffff;
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
+
-+ 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;
-+ }
++ (void) ipath_sdma_make_progress(dd);
+
-+ usbhid_submit_report(hid, lg2ff->report, USB_DIR_OUT);
-+ return 0;
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
+}
+
-+int hid_lg2ff_init(struct hid_device *hid)
++static int alloc_sdma(struct ipath_devdata *dd)
+{
-+ 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;
-+ }
++ int ret = 0;
+
-+ report = list_entry(report_list->next, struct hid_report, list);
++ /* 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 (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;
++ if (!dd->ipath_sdma_descq) {
++ ipath_dev_err(dd, "failed to allocate SendDMA descriptor "
++ "FIFO memory\n");
++ ret = -ENOMEM;
++ goto done;
+ }
+
-+ lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL);
-+ if (!lg2ff)
-+ return -ENOMEM;
-+
-+ set_bit(FF_RUMBLE, dev->ffbit);
++ dd->ipath_sdma_descq_cnt =
++ SDMA_DESCQ_SZ / sizeof(struct ipath_sdma_desc);
+
-+ error = input_ff_create_memless(dev, lg2ff, play_effect);
-+ if (error) {
-+ kfree(lg2ff);
-+ return error;
++ /* 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;
+
-+ lg2ff->report = report;
-+ report->field[0]->value[0] = 0xf3;
-+ report->field[0]->value[1] = 0x00;
-+ report->field[0]->value[2] = 0x00;
-+ report->field[0]->value[3] = 0x00;
-+ report->field[0]->value[4] = 0x00;
-+ report->field[0]->value[5] = 0x00;
-+ report->field[0]->value[6] = 0x00;
-+
-+ usbhid_submit_report(hid, report, USB_DIR_OUT);
-+
-+ printk(KERN_INFO "Force feedback for Logitech Rumblepad 2 by "
-+ "Anssi Hannula <anssi.hannula at gmail.com>\n");
-+
-+ return 0;
-+}
-diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
-index e29a057..d3f8d91 100644
---- a/drivers/hid/usbhid/hid-quirks.c
-+++ b/drivers/hid/usbhid/hid-quirks.c
-@@ -32,6 +32,9 @@
- #define USB_VENDOR_ID_ADS_TECH 0x06e1
- #define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155
-
-+#define USB_VENDOR_ID_AFATECH 0x15a4
-+#define USB_DEVICE_ID_AFATECH_AF9016 0x9016
-+
- #define USB_VENDOR_ID_AIPTEK 0x08ca
- #define USB_DEVICE_ID_AIPTEK_01 0x0001
- #define USB_DEVICE_ID_AIPTEK_10 0x0010
-@@ -124,6 +127,9 @@
- #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
- #define USB_DEVICE_ID_DELORME_EM_LT20 0x0200
-
-+#define USB_VENDOR_ID_DMI 0x0c0b
-+#define USB_DEVICE_ID_DMI_ENC 0x5fab
-+
- #define USB_VENDOR_ID_ELO 0x04E7
- #define USB_DEVICE_ID_ELO_TS2700 0x0020
-
-@@ -199,17 +205,6 @@
- #define USB_DEVICE_ID_GTCO_502 0x0502
- #define USB_DEVICE_ID_GTCO_503 0x0503
- #define USB_DEVICE_ID_GTCO_504 0x0504
--#define USB_DEVICE_ID_GTCO_600 0x0600
--#define USB_DEVICE_ID_GTCO_601 0x0601
--#define USB_DEVICE_ID_GTCO_602 0x0602
--#define USB_DEVICE_ID_GTCO_603 0x0603
--#define USB_DEVICE_ID_GTCO_604 0x0604
--#define USB_DEVICE_ID_GTCO_605 0x0605
--#define USB_DEVICE_ID_GTCO_606 0x0606
--#define USB_DEVICE_ID_GTCO_607 0x0607
--#define USB_DEVICE_ID_GTCO_608 0x0608
--#define USB_DEVICE_ID_GTCO_609 0x0609
--#define USB_DEVICE_ID_GTCO_609 0x0609
- #define USB_DEVICE_ID_GTCO_1000 0x1000
- #define USB_DEVICE_ID_GTCO_1001 0x1001
- #define USB_DEVICE_ID_GTCO_1002 0x1002
-@@ -320,6 +315,7 @@
- #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
- #define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
- #define USB_DEVICE_ID_DINOVO_EDGE 0xc714
-+#define USB_DEVICE_ID_DINOVO_MINI 0xc71f
-
- #define USB_VENDOR_ID_MCC 0x09db
- #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076
-@@ -332,6 +328,7 @@
- #define USB_VENDOR_ID_MICROSOFT 0x045e
- #define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
- #define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
-+#define USB_DEVICE_ID_DESKTOP_RECV_1028 0x00f9
- #define USB_DEVICE_ID_MS_NE4K 0x00db
- #define USB_DEVICE_ID_MS_LK6K 0x00f9
-
-@@ -377,6 +374,9 @@
- #define USB_VENDOR_ID_SUN 0x0430
- #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab
-
-+#define USB_VENDOR_ID_SUNPLUS 0x04fc
-+#define USB_DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8
-+
- #define USB_VENDOR_ID_TOPMAX 0x0663
- #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103
-
-@@ -405,6 +405,9 @@
- #define USB_VENDOR_ID_YEALINK 0x6993
- #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001
-
-+#define USB_VENDOR_ID_KYE 0x0458
-+#define USB_DEVICE_ID_KYE_GPEN_560 0x5003
-+
- /*
- * Alphabetically sorted blacklist by quirk type.
- */
-@@ -435,9 +438,13 @@ static const struct hid_blacklist {
- { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
-
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
-+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI, HID_QUIRK_DUPLICATE_USAGES },
++ 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);
+
-+ { 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 },
++ goto done;
+
- { 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;
-+ }
++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;
+}
+
- /*
- * 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)
++int setup_sdma(struct ipath_devdata *dd)
+{
-+ 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);
++ int ret = 0;
++ unsigned i, n;
++ u64 tmp64;
++ u64 senddmabufmask[3] = { 0 };
++ unsigned long flags;
+
-+ 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;
++ ret = alloc_sdma(dd);
++ if (ret)
++ goto done;
+
-+ 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 (!dd->ipath_sdma_descq) {
++ ipath_dev_err(dd, "SendDMA memory not allocated\n");
++ goto done;
+ }
+
-+ 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];
++ 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;
+
-+ if (cmd == HIDIOCGCOLLECTIONINDEX) {
-+ if (uref->usage_index >= field->maxusage)
-+ goto inval;
-+ } else if (uref->usage_index >= field->report_count)
-+ goto inval;
++ /* 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);
+
-+ 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;
-+ }
++ /* 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]);
+
-+ switch (cmd) {
-+ case HIDIOCGUSAGE:
-+ uref->value = field->value[uref->usage_index];
-+ if (copy_to_user(user_arg, uref, sizeof(*uref)))
-+ goto fault;
-+ goto goodreturn;
++ INIT_LIST_HEAD(&dd->ipath_sdma_activelist);
++ INIT_LIST_HEAD(&dd->ipath_sdma_notifylist);
+
-+ case HIDIOCSUSAGE:
-+ field->value[uref->usage_index] = uref->value;
-+ goto goodreturn;
++ 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);
+
-+ 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;
-+ }
++ /*
++ * 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);
+
-+goodreturn:
-+ kfree(uref_multi);
-+ return 0;
-+fault:
-+ kfree(uref_multi);
-+ return -EFAULT;
-+inval:
-+ kfree(uref_multi);
-+ return -EINVAL;
-+ }
++done:
++ return ret;
+}
+
-+static noinline int hiddev_ioctl_string(struct hiddev *hiddev, unsigned int cmd, void __user *user_arg)
++void teardown_sdma(struct ipath_devdata *dd)
+{
-+ struct hid_device *hid = hiddev->hid;
-+ struct usb_device *dev = hid_to_usb_dev(hid);
-+ int idx, len;
-+ char *buf;
++ 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;
+
-+ if (get_user(idx, (int __user *)user_arg))
-+ return -EFAULT;
++ 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);
+
-+ if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL)
-+ return -ENOMEM;
++ tasklet_kill(&dd->ipath_sdma_abort_task);
++ tasklet_kill(&dd->ipath_sdma_notify_task);
+
-+ if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) {
-+ kfree(buf);
-+ return -EINVAL;
-+ }
++ /* 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);
+
-+ if (copy_to_user(user_arg+sizeof(int), buf, len+1)) {
-+ kfree(buf);
-+ return -EFAULT;
++ 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);
+
-+ kfree(buf);
-+
-+ return len;
-+}
-+
- static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
- {
- struct hiddev_list *list = file->private_data;
-@@ -402,8 +549,6 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
- struct hiddev_collection_info cinfo;
- struct hiddev_report_info rinfo;
- struct hiddev_field_info finfo;
-- struct hiddev_usage_ref_multi *uref_multi = NULL;
-- struct hiddev_usage_ref *uref;
- struct hiddev_devinfo dinfo;
- struct hid_report *report;
- struct hid_field *field;
-@@ -470,30 +615,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
- }
-
- case HIDIOCGSTRING:
-- {
-- int idx, len;
-- char *buf;
--
-- if (get_user(idx, (int __user *)arg))
-- return -EFAULT;
--
-- if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL)
-- return -ENOMEM;
--
-- if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) {
-- kfree(buf);
-- return -EINVAL;
-- }
--
-- if (copy_to_user(user_arg+sizeof(int), buf, len+1)) {
-- kfree(buf);
-- return -EFAULT;
-- }
--
-- kfree(buf);
--
-- return len;
-- }
-+ return hiddev_ioctl_string(hiddev, cmd, user_arg);
-
- case HIDIOCINITREPORT:
- usbhid_init_reports(hid);
-@@ -578,121 +700,13 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
- return 0;
-
- case HIDIOCGUCODE:
-- uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL);
-- if (!uref_multi)
-- return -ENOMEM;
-- uref = &uref_multi->uref;
-- if (copy_from_user(uref, user_arg, sizeof(*uref)))
-- goto fault;
--
-- rinfo.report_type = uref->report_type;
-- rinfo.report_id = uref->report_id;
-- if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-- goto inval;
--
-- if (uref->field_index >= report->maxfield)
-- goto inval;
--
-- field = report->field[uref->field_index];
-- if (uref->usage_index >= field->maxusage)
-- goto inval;
--
-- uref->usage_code = field->usage[uref->usage_index].hid;
--
-- if (copy_to_user(user_arg, uref, sizeof(*uref)))
-- goto fault;
--
-- kfree(uref_multi);
-- return 0;
--
-+ /* fall through */
- case HIDIOCGUSAGE:
- case HIDIOCSUSAGE:
- case HIDIOCGUSAGES:
- case HIDIOCSUSAGES:
- case HIDIOCGCOLLECTIONINDEX:
-- uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL);
-- if (!uref_multi)
-- return -ENOMEM;
-- uref = &uref_multi->uref;
-- if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
-- if (copy_from_user(uref_multi, user_arg,
-- sizeof(*uref_multi)))
-- goto fault;
-- } else {
-- if (copy_from_user(uref, user_arg, sizeof(*uref)))
-- goto fault;
-- }
--
-- if (cmd != HIDIOCGUSAGE &&
-- cmd != HIDIOCGUSAGES &&
-- uref->report_type == HID_REPORT_TYPE_INPUT)
-- goto inval;
--
-- if (uref->report_id == HID_REPORT_ID_UNKNOWN) {
-- field = hiddev_lookup_usage(hid, uref);
-- if (field == NULL)
-- goto inval;
-- } else {
-- rinfo.report_type = uref->report_type;
-- rinfo.report_id = uref->report_id;
-- if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-- goto inval;
--
-- if (uref->field_index >= report->maxfield)
-- goto inval;
--
-- field = report->field[uref->field_index];
--
-- if (cmd == HIDIOCGCOLLECTIONINDEX) {
-- if (uref->usage_index >= field->maxusage)
-- goto inval;
-- } else if (uref->usage_index >= field->report_count)
-- goto inval;
--
-- else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
-- (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
-- uref->usage_index + uref_multi->num_values > field->report_count))
-- goto inval;
-- }
--
-- switch (cmd) {
-- case HIDIOCGUSAGE:
-- uref->value = field->value[uref->usage_index];
-- if (copy_to_user(user_arg, uref, sizeof(*uref)))
-- goto fault;
-- goto goodreturn;
--
-- case HIDIOCSUSAGE:
-- field->value[uref->usage_index] = uref->value;
-- goto goodreturn;
--
-- case HIDIOCGCOLLECTIONINDEX:
-- kfree(uref_multi);
-- return field->usage[uref->usage_index].collection_index;
-- case HIDIOCGUSAGES:
-- for (i = 0; i < uref_multi->num_values; i++)
-- uref_multi->values[i] =
-- field->value[uref->usage_index + i];
-- if (copy_to_user(user_arg, uref_multi,
-- sizeof(*uref_multi)))
-- goto fault;
-- goto goodreturn;
-- case HIDIOCSUSAGES:
-- for (i = 0; i < uref_multi->num_values; i++)
-- field->value[uref->usage_index + i] =
-- uref_multi->values[i];
-- goto goodreturn;
-- }
--
--goodreturn:
-- kfree(uref_multi);
-- return 0;
--fault:
-- kfree(uref_multi);
-- return -EFAULT;
--inval:
-- kfree(uref_multi);
-- return -EINVAL;
-+ return hiddev_ioctl_usage(hiddev, cmd, user_arg);
-
- case HIDIOCGCOLLECTIONINFO:
- if (copy_from_user(&cinfo, user_arg, sizeof(cinfo)))
-diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
-index 0023f96..62d2d7c 100644
---- a/drivers/hid/usbhid/usbhid.h
-+++ b/drivers/hid/usbhid/usbhid.h
-@@ -28,6 +28,7 @@
- #include <linux/slab.h>
- #include <linux/list.h>
- #include <linux/timer.h>
-+#include <linux/wait.h>
- #include <linux/workqueue.h>
- #include <linux/input.h>
-
-@@ -77,7 +78,7 @@ struct usbhid_device {
- unsigned long stop_retry; /* Time to give up, in jiffies */
- unsigned int retry_delay; /* Delay length in ms */
- struct work_struct reset_work; /* Task context for resets */
--
-+ wait_queue_head_t wait; /* For sleeping */
- };
-
- #define hid_to_usb_dev(hid_dev) \
-diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig
-index 014dfa5..7137a17 100644
---- a/drivers/i2c/algos/Kconfig
-+++ b/drivers/i2c/algos/Kconfig
-@@ -1,45 +1,16 @@
- #
--# Character device configuration
-+# I2C algorithm drivers configuration
- #
-
--menu "I2C Algorithms"
--
- config I2C_ALGOBIT
-- tristate "I2C bit-banging interfaces"
-- help
-- This allows you to use a range of I2C adapters called bit-banging
-- adapters. Say Y if you own an I2C adapter belonging to this class
-- and then say Y to the specific driver for you adapter below.
--
-- This support is also available as a module. If so, the module
-- will be called i2c-algo-bit.
-+ tristate
-
- config I2C_ALGOPCF
-- tristate "I2C PCF 8584 interfaces"
-- help
-- This allows you to use a range of I2C adapters called PCF adapters.
-- Say Y if you own an I2C adapter belonging to this class and then say
-- Y to the specific driver for you adapter below.
--
-- This support is also available as a module. If so, the module
-- will be called i2c-algo-pcf.
-+ tristate
-
- config I2C_ALGOPCA
-- tristate "I2C PCA 9564 interfaces"
-- help
-- This allows you to use a range of I2C adapters called PCA adapters.
-- Say Y if you own an I2C adapter belonging to this class and then say
-- Y to the specific driver for you adapter below.
--
-- This support is also available as a module. If so, the module
-- will be called i2c-algo-pca.
-+ tristate
-
- config I2C_ALGO_SGI
-- tristate "I2C SGI interfaces"
-+ tristate
- depends on SGI_IP22 || SGI_IP32 || X86_VISWS
-- help
-- Supports the SGI interfaces like the ones found on SGI Indy VINO
-- or SGI O2 MACE.
--
--endmenu
--
-diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
-index 2a16211..e954a20 100644
---- a/drivers/i2c/algos/i2c-algo-pca.c
-+++ b/drivers/i2c/algos/i2c-algo-pca.c
-@@ -1,6 +1,7 @@
- /*
-- * i2c-algo-pca.c i2c driver algorithms for PCA9564 adapters
-+ * i2c-algo-pca.c i2c driver algorithms for PCA9564 adapters
- * Copyright (C) 2004 Arcom Control Systems
-+ * Copyright (C) 2008 Pengutronix
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -21,14 +22,10 @@
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/delay.h>
--#include <linux/slab.h>
- #include <linux/init.h>
- #include <linux/errno.h>
- #include <linux/i2c.h>
- #include <linux/i2c-algo-pca.h>
--#include "i2c-algo-pca.h"
--
--#define DRIVER "i2c-algo-pca"
-
- #define DEB1(fmt, args...) do { if (i2c_debug>=1) printk(fmt, ## args); } while(0)
- #define DEB2(fmt, args...) do { if (i2c_debug>=2) printk(fmt, ## args); } while(0)
-@@ -36,15 +33,15 @@
-
- static int i2c_debug;
-
--#define pca_outw(adap, reg, val) adap->write_byte(adap, reg, val)
--#define pca_inw(adap, reg) adap->read_byte(adap, reg)
-+#define pca_outw(adap, reg, val) adap->write_byte(adap->data, reg, val)
-+#define pca_inw(adap, reg) adap->read_byte(adap->data, reg)
-
- #define pca_status(adap) pca_inw(adap, I2C_PCA_STA)
--#define pca_clock(adap) adap->get_clock(adap)
--#define pca_own(adap) adap->get_own(adap)
-+#define pca_clock(adap) adap->i2c_clock
- #define pca_set_con(adap, val) pca_outw(adap, I2C_PCA_CON, val)
- #define pca_get_con(adap) pca_inw(adap, I2C_PCA_CON)
--#define pca_wait(adap) adap->wait_for_interrupt(adap)
-+#define pca_wait(adap) adap->wait_for_completion(adap->data)
-+#define pca_reset(adap) adap->reset_chip(adap->data)
-
- /*
- * Generate a start condition on the i2c bus.
-@@ -99,7 +96,7 @@ static void pca_stop(struct i2c_algo_pca_data *adap)
- *
- * returns after the address has been sent
- */
--static void pca_address(struct i2c_algo_pca_data *adap,
-+static void pca_address(struct i2c_algo_pca_data *adap,
- struct i2c_msg *msg)
- {
- int sta = pca_get_con(adap);
-@@ -108,9 +105,9 @@ static void pca_address(struct i2c_algo_pca_data *adap,
- addr = ( (0x7f & msg->addr) << 1 );
- if (msg->flags & I2C_M_RD )
- addr |= 1;
-- DEB2("=== SLAVE ADDRESS %#04x+%c=%#04x\n",
-+ DEB2("=== SLAVE ADDRESS %#04x+%c=%#04x\n",
- msg->addr, msg->flags & I2C_M_RD ? 'R' : 'W', addr);
--
-+
- pca_outw(adap, I2C_PCA_DAT, addr);
-
- sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI);
-@@ -124,7 +121,7 @@ static void pca_address(struct i2c_algo_pca_data *adap,
- *
- * Returns after the byte has been transmitted
- */
--static void pca_tx_byte(struct i2c_algo_pca_data *adap,
-+static void pca_tx_byte(struct i2c_algo_pca_data *adap,
- __u8 b)
- {
- int sta = pca_get_con(adap);
-@@ -142,19 +139,19 @@ static void pca_tx_byte(struct i2c_algo_pca_data *adap,
- *
- * returns immediately.
- */
--static void pca_rx_byte(struct i2c_algo_pca_data *adap,
-+static void pca_rx_byte(struct i2c_algo_pca_data *adap,
- __u8 *b, int ack)
- {
- *b = pca_inw(adap, I2C_PCA_DAT);
- DEB2("=== READ %#04x %s\n", *b, ack ? "ACK" : "NACK");
- }
-
--/*
-+/*
- * Setup ACK or NACK for next received byte and wait for it to arrive.
- *
- * Returns after next byte has arrived.
- */
--static void pca_rx_ack(struct i2c_algo_pca_data *adap,
-+static void pca_rx_ack(struct i2c_algo_pca_data *adap,
- int ack)
- {
- int sta = pca_get_con(adap);
-@@ -168,15 +165,6 @@ static void pca_rx_ack(struct i2c_algo_pca_data *adap,
- pca_wait(adap);
- }
-
--/*
-- * Reset the i2c bus / SIO
-- */
--static void pca_reset(struct i2c_algo_pca_data *adap)
--{
-- /* apparently only an external reset will do it. not a lot can be done */
-- printk(KERN_ERR DRIVER ": Haven't figured out how to do a reset yet\n");
--}
--
- static int pca_xfer(struct i2c_adapter *i2c_adap,
- struct i2c_msg *msgs,
- int num)
-@@ -187,7 +175,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
- int numbytes = 0;
- int state;
- int ret;
-- int timeout = 100;
-+ int timeout = i2c_adap->timeout;
-
- while ((state = pca_status(adap)) != 0xf8 && timeout--) {
- msleep(10);
-@@ -203,14 +191,14 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
- for (curmsg = 0; curmsg < num; curmsg++) {
- int addr, i;
- msg = &msgs[curmsg];
--
-+
- addr = (0x7f & msg->addr) ;
--
++ sdma_notify_taskbody(dd);
+
- 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;
--
++ del_timer_sync(&dd->ipath_sdma_vl15_timer);
+
- 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;
--
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
+
- 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;
- }
--
++ dd->ipath_sdma_abort_jiffies = 0;
+
- }
-
- 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,
-+};
++ 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);
+
-+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 (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 (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;
++ 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;
+ }
+
-+ 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
++ 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);
++}
++
+/*
-+ * 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);
++ * [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;
+}
-+EXPORT_SYMBOL(i2c_pca_add_bus);
-
-- if ((rval = pca_init(pca_adap)))
-- return rval;
-+int i2c_pca_add_numbered_bus(struct i2c_adapter *adap)
++
++static inline void make_sdma_desc(struct ipath_devdata *dd,
++ u64 *sdmadesc, u64 addr, u64 dwlen, u64 dwoffset)
+{
-+ int rval;
-
-- rval = i2c_add_adapter(adap);
-+ rval = pca_init(adap);
-+ if (rval)
-+ return rval;
-
-- return rval;
-+ return i2c_add_numbered_adapter(adap);
- }
--EXPORT_SYMBOL(i2c_pca_add_bus);
-+EXPORT_SYMBOL(i2c_pca_add_numbered_bus);
-
--MODULE_AUTHOR("Ian Campbell <icampbell at arcom.com>");
-+MODULE_AUTHOR("Ian Campbell <icampbell at arcom.com>, "
-+ "Wolfram Sang <w.sang at pengutronix.de>");
- MODULE_DESCRIPTION("I2C-Bus PCA9564 algorithm");
- MODULE_LICENSE("GPL");
-
-diff --git a/drivers/i2c/algos/i2c-algo-pca.h b/drivers/i2c/algos/i2c-algo-pca.h
-deleted file mode 100644
-index 2fee07e..0000000
---- a/drivers/i2c/algos/i2c-algo-pca.h
-+++ /dev/null
-@@ -1,26 +0,0 @@
--#ifndef I2C_PCA9564_H
--#define I2C_PCA9564_H 1
--
--#define I2C_PCA_STA 0x00 /* STATUS Read Only */
--#define I2C_PCA_TO 0x00 /* TIMEOUT Write Only */
--#define I2C_PCA_DAT 0x01 /* DATA Read/Write */
--#define I2C_PCA_ADR 0x02 /* OWN ADR Read/Write */
--#define I2C_PCA_CON 0x03 /* CONTROL Read/Write */
--
--#define I2C_PCA_CON_AA 0x80 /* Assert Acknowledge */
--#define I2C_PCA_CON_ENSIO 0x40 /* Enable */
--#define I2C_PCA_CON_STA 0x20 /* Start */
--#define I2C_PCA_CON_STO 0x10 /* Stop */
--#define I2C_PCA_CON_SI 0x08 /* Serial Interrupt */
--#define I2C_PCA_CON_CR 0x07 /* Clock Rate (MASK) */
--
--#define I2C_PCA_CON_330kHz 0x00
--#define I2C_PCA_CON_288kHz 0x01
--#define I2C_PCA_CON_217kHz 0x02
--#define I2C_PCA_CON_146kHz 0x03
--#define I2C_PCA_CON_88kHz 0x04
--#define I2C_PCA_CON_59kHz 0x05
--#define I2C_PCA_CON_44kHz 0x06
--#define I2C_PCA_CON_36kHz 0x07
--
--#endif /* I2C_PCA9564_H */
-diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
-index 5fa9c3c..48438cc 100644
---- a/drivers/i2c/busses/Kconfig
-+++ b/drivers/i2c/busses/Kconfig
-@@ -100,9 +100,12 @@ config I2C_AU1550
-
- config I2C_BLACKFIN_TWI
- tristate "Blackfin TWI I2C support"
-- depends on BF534 || BF536 || BF537
-+ depends on BLACKFIN
- help
-- This is the TWI I2C device driver for Blackfin 534/536/537/54x.
-+ This is the TWI I2C device driver for Blackfin BF522, BF525,
-+ BF527, BF534, BF536, BF537 and BF54x. For other Blackfin processors,
-+ please don't use this driver.
++ 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 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.
--
++/*
++ * 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)
++{
+
- 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.
++ unsigned long flags;
++ struct ipath_sge *sge;
++ int ret = 0;
++ u16 tail;
++ __le64 *descqp;
++ u64 sdmadesc[2];
++ u32 dwoffset;
++ dma_addr_t addr;
+
- 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.
++ 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;
++ }
+
-+ This driver can also be built as a module. If so, the module
-+ will be called i2c-pca-platform.
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
+
- 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.
++retry:
++ if (unlikely(test_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status))) {
++ ret = -EBUSY;
++ goto unlock;
++ }
+
-+ This driver can also be built as a module. If so, the module
-+ will be called i2c-sh7760.
++ if (tx->txreq.sg_count > ipath_sdma_descq_freecnt(dd)) {
++ if (ipath_sdma_make_progress(dd))
++ goto retry;
++ ret = -ENOBUFS;
++ goto unlock;
++ }
+
-+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.
++ 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;
++ }
+
-+ This driver can also be built as a module. If so, the module
-+ will be called i2c-sh_mobile.
++ dwoffset = tx->map_len >> 2;
++ make_sdma_desc(dd, sdmadesc, (u64) addr, dwoffset, 0);
+
- endmenu
-diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
-index ea7068f..e8c882a 100644
---- a/drivers/i2c/busses/Makefile
-+++ b/drivers/i2c/busses/Makefile
-@@ -30,6 +30,7 @@ obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
- obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
- obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o
- obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
-+obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
- obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
- obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
- obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
-@@ -37,6 +38,8 @@ obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o
- obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
- obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
- obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o
-+obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
-+obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o
- obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
- obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
- obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
-diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
-index c09b036..73d6194 100644
---- a/drivers/i2c/busses/i2c-at91.c
-+++ b/drivers/i2c/busses/i2c-at91.c
-@@ -298,7 +298,7 @@ static int at91_i2c_resume(struct platform_device *pdev)
- #endif
-
- /* work with "modprobe at91_i2c" from hotplugging or coldplugging */
--MODULE_ALIAS("at91_i2c");
-+MODULE_ALIAS("platform:at91_i2c");
-
- static struct platform_driver at91_i2c_driver = {
- .probe = at91_i2c_probe,
-diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
-index 1953b26..491718f 100644
---- a/drivers/i2c/busses/i2c-au1550.c
-+++ b/drivers/i2c/busses/i2c-au1550.c
-@@ -472,6 +472,7 @@ i2c_au1550_exit(void)
- MODULE_AUTHOR("Dan Malek, Embedded Edge, LLC.");
- MODULE_DESCRIPTION("SMBus adapter Alchemy pb1550");
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:au1xpsc_smbus");
-
- module_init (i2c_au1550_init);
- module_exit (i2c_au1550_exit);
-diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
-index 7dbdaeb..48d084b 100644
---- a/drivers/i2c/busses/i2c-bfin-twi.c
-+++ b/drivers/i2c/busses/i2c-bfin-twi.c
-@@ -1,25 +1,11 @@
- /*
-- * drivers/i2c/busses/i2c-bfin-twi.c
-+ * Blackfin On-Chip Two Wire Interface Driver
- *
-- * Description: Driver for Blackfin Two Wire Interface
-+ * Copyright 2005-2007 Analog Devices Inc.
- *
-- * Author: sonicz <sonic.zhang at analog.com>
-+ * Enter bugs at http://blackfin.uclinux.org/
- *
-- * Copyright (c) 2005-2007 Analog Devices, Inc.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ * Licensed under the GPL-2 or later.
- */
-
- #include <linux/module.h>
-@@ -34,14 +20,16 @@
- #include <linux/platform_device.h>
-
- #include <asm/blackfin.h>
-+#include <asm/portmux.h>
- #include <asm/irq.h>
-
- #define POLL_TIMEOUT (2 * HZ)
-
- /* SMBus mode*/
--#define TWI_I2C_MODE_STANDARD 0x01
--#define TWI_I2C_MODE_STANDARDSUB 0x02
--#define TWI_I2C_MODE_COMBINED 0x04
-+#define TWI_I2C_MODE_STANDARD 1
-+#define TWI_I2C_MODE_STANDARDSUB 2
-+#define TWI_I2C_MODE_COMBINED 3
-+#define TWI_I2C_MODE_REPEAT 4
-
- struct bfin_twi_iface {
- int irq;
-@@ -58,39 +46,74 @@ struct bfin_twi_iface {
- struct timer_list timeout_timer;
- struct i2c_adapter adap;
- struct completion complete;
-+ struct i2c_msg *pmsg;
-+ int msg_num;
-+ int cur_msg;
-+ void __iomem *regs_base;
- };
-
--static struct bfin_twi_iface twi_iface;
++ /* SDmaFirstDesc */
++ sdmadesc[0] |= 1ULL << 12;
++ if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_USELARGEBUF)
++ sdmadesc[0] |= 1ULL << 14; /* SDmaUseLargeBuf */
+
-+#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); }
++ /* 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]);
+
-+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)
++ if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_FREEDESC)
++ tx->txreq.start_idx = tail;
+
-+static const u16 pin_req[2][3] = {
-+ {P_TWI0_SCL, P_TWI0_SDA, 0},
-+ {P_TWI1_SCL, P_TWI1_SDA, 0},
-+};
++ /* 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;
- 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);
+ *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 (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();
+- 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);
}
- /* 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;
+ dd->ipath_lastport0rcv_cnt = ipath_stats.sps_port0pkts;
}
- 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);
+@@ -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);
}
-@@ -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;
+ /* 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;
}
-- 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();
- }
-+ }
+diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c
+index 56dfc8a..a6c8efb 100644
+--- a/drivers/infiniband/hw/ipath/ipath_sysfs.c
++++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -34,6 +34,7 @@
+ #include <linux/ctype.h>
-- /* clear int stat */
-- bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV);
-+ /* clear int stat */
-+ write_INT_STAT(iface, MERR | MCOMP | XMTSERV | RCVSERV);
+ #include "ipath_kernel.h"
++#include "ipath_verbs.h"
+ #include "ipath_common.h"
-- /* 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();
+ /**
+@@ -163,6 +164,15 @@ static ssize_t show_boardversion(struct device *dev,
+ return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_boardversion);
+ }
-- 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;
-+ }
++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,
-- iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
-- add_timer(&iface->timeout_timer);
-+ iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
-+ add_timer(&iface->timeout_timer);
+ dd->ipath_guid = new_guid;
+ dd->ipath_nguid = 1;
++ if (dd->verbs_dev)
++ dd->verbs_dev->ibdev.node_guid = new_guid;
-- /* 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();
+ ret = strlen(buf);
+ goto bail;
+@@ -919,21 +931,21 @@ static ssize_t store_rx_polinv_enb(struct device *dev,
+ u16 val;
-- wait_for_completion(&iface->complete);
-+ wait_for_completion(&iface->complete);
+ 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;
++ }
-- rc = iface->result;
-- if (rc == 1)
-- ret++;
-- else if (rc == -1)
-- break;
+ r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_RXPOL_ENB, val);
+- if (r < 0) {
++ if (r < 0)
+ ret = r;
+- goto bail;
- }
-+ rc = iface->result;
-- return ret;
-+ if (rc == 1)
-+ return num;
-+ else
-+ return rc;
+- goto bail;
+-invalid:
+- ipath_dev_err(dd, "attempt to set invalid Rx Polarity (enable)\n");
+ bail:
+ return ret;
}
-
++
/*
-@@ -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,
+ * Get/Set RX lane-reversal enable. 0=no, 1=yes.
+ */
+@@ -988,6 +1000,75 @@ static struct attribute_group driver_attr_group = {
+ .attrs = driver_attributes
+ };
- 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();
++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);
- 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();
+ 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
+ };
- 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,
- }
+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;
}
-- 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;
+ 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)
-+ 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;
-+ }
+ if (swqe->wr.opcode == IB_WR_SEND_WITH_IMM) {
+ wc.wc_flags = IB_WC_WITH_IMM;
+- wc.imm_data = swqe->wr.imm_data;
++ wc.imm_data = swqe->wr.ex.imm_data;
+ } else {
+ wc.wc_flags = 0;
+ wc.imm_data = 0;
+@@ -303,6 +303,7 @@ int ipath_make_ud_req(struct ipath_qp *qp)
+ qp->s_hdrwords = 7;
+ qp->s_cur_size = wqe->length;
+ qp->s_cur_sge = &qp->s_sge;
++ qp->s_dmult = ah_attr->static_rate;
+ qp->s_wqe = wqe;
+ qp->s_sge.sge = wqe->sg_list[0];
+ qp->s_sge.sg_list = wqe->sg_list + 1;
+@@ -326,7 +327,7 @@ int ipath_make_ud_req(struct ipath_qp *qp)
+ }
+ if (wqe->wr.opcode == IB_WR_SEND_WITH_IMM) {
+ qp->s_hdrwords++;
+- ohdr->u.ud.imm_data = wqe->wr.imm_data;
++ ohdr->u.ud.imm_data = wqe->wr.ex.imm_data;
+ bth0 = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE << 24;
+ } else
+ bth0 = IB_OPCODE_UD_SEND_ONLY << 24;
+diff --git a/drivers/infiniband/hw/ipath/ipath_user_sdma.c b/drivers/infiniband/hw/ipath/ipath_user_sdma.c
+new file mode 100644
+index 0000000..86e0169
+--- /dev/null
++++ b/drivers/infiniband/hw/ipath/ipath_user_sdma.c
+@@ -0,0 +1,879 @@
++/*
++ * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses. You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ * Redistribution and use in source and binary forms, with or
++ * without modification, are permitted provided that the following
++ * conditions are met:
++ *
++ * - Redistributions of source code must retain the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer.
++ *
++ * - Redistributions in binary form must reproduce the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer in the documentation and/or other materials
++ * provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++#include <linux/mm.h>
++#include <linux/types.h>
++#include <linux/device.h>
++#include <linux/dmapool.h>
++#include <linux/slab.h>
++#include <linux/list.h>
++#include <linux/highmem.h>
++#include <linux/io.h>
++#include <linux/uio.h>
++#include <linux/rbtree.h>
++#include <linux/spinlock.h>
++#include <linux/delay.h>
+
- spin_lock_init(&(iface->lock));
-- init_completion(&(iface->complete));
-- iface->irq = IRQ_TWI;
++#include "ipath_kernel.h"
++#include "ipath_user_sdma.h"
+
-+ /* 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;
-+ }
++/* 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)
+
-+ 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;
-+ }
++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 */
+
-+ 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;
++ 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 */
++};
+
-+ 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;
++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;
+ }
-
- 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;
++
++ 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;
+ }
+
-+ platform_set_drvdata(pdev, iface);
-
-+ dev_info(&pdev->dev, "Blackfin BF5xx on-chip I2C TWI Contoller, "
-+ "regs_base@%p\n", iface->regs_base);
++ 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;
++ }
+
-+ return 0;
++ ipath_user_sdma_init_frag(pkt, 1, 0, len, 0, 1, page, mpage_save,
++ dma_addr);
++ pkt->naddr = 2;
+
-+out_error_add_adapter:
-+ free_irq(iface->irq, iface);
-+out_error_req_irq:
-+out_error_no_irq:
-+ peripheral_free_list(pin_req[pdev->id]);
-+out_error_pin_mux:
-+ iounmap(iface->regs_base);
-+out_error_ioremap:
-+out_error_get_res:
-+ kfree(iface);
-+out_error_nomem:
- return rc;
- }
-
-@@ -594,6 +707,9 @@ static int i2c_bfin_twi_remove(struct platform_device *pdev)
-
- i2c_del_adapter(&(iface->adap));
- free_irq(iface->irq, iface);
-+ peripheral_free_list(pin_req[pdev->id]);
-+ iounmap(iface->regs_base);
-+ kfree(iface);
-
- return 0;
- }
-@@ -611,8 +727,6 @@ static struct platform_driver i2c_bfin_twi_driver = {
-
- static int __init i2c_bfin_twi_init(void)
- {
-- pr_info("I2C: Blackfin I2C TWI driver\n");
--
- return platform_driver_register(&i2c_bfin_twi_driver);
- }
-
-@@ -621,9 +735,10 @@ static void __exit i2c_bfin_twi_exit(void)
- platform_driver_unregister(&i2c_bfin_twi_driver);
- }
-
--MODULE_AUTHOR("Sonic Zhang <sonic.zhang at analog.com>");
--MODULE_DESCRIPTION("I2C-Bus adapter routines for Blackfin TWI");
--MODULE_LICENSE("GPL");
--
- module_init(i2c_bfin_twi_init);
- module_exit(i2c_bfin_twi_exit);
++ goto done;
+
-+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");
++free_unmap:
++ kunmap(page);
++ __free_page(page);
++done:
++ return ret;
++}
+
- static struct platform_driver davinci_i2c_driver = {
- .probe = davinci_i2c_probe,
- .remove = davinci_i2c_remove,
-diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
-index 3ca19fc..7c1b762 100644
---- a/drivers/i2c/busses/i2c-gpio.c
-+++ b/drivers/i2c/busses/i2c-gpio.c
-@@ -220,3 +220,4 @@ module_exit(i2c_gpio_exit);
- MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen at atmel.com>");
- MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver");
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:i2c-gpio");
-diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
-index 22bb247..85dbf34 100644
---- a/drivers/i2c/busses/i2c-ibm_iic.c
-+++ b/drivers/i2c/busses/i2c-ibm_iic.c
-@@ -6,6 +6,9 @@
- * Copyright (c) 2003, 2004 Zultys Technologies.
- * Eugene Surovegin <eugene.surovegin at zultys.com> or <ebs at ebshome.net>
- *
-+ * Copyright (c) 2008 PIKA Technologies
-+ * Sean MacLennan <smaclennan at pikatech.com>
-+ *
- * Based on original work by
- * Ian DaSilva <idasilva at mvista.com>
- * Armin Kuster <akuster at mvista.com>
-@@ -39,12 +42,17 @@
- #include <asm/io.h>
- #include <linux/i2c.h>
- #include <linux/i2c-id.h>
++/* 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;
+
-+#ifdef CONFIG_IBM_OCP
- #include <asm/ocp.h>
- #include <asm/ibm4xx.h>
-+#else
-+#include <linux/of_platform.h>
-+#endif
-
- #include "i2c-ibm_iic.h"
-
--#define DRIVER_VERSION "2.1"
-+#define DRIVER_VERSION "2.2"
-
- MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION);
- MODULE_LICENSE("GPL");
-@@ -650,13 +658,14 @@ static inline u8 iic_clckdiv(unsigned int opb)
- opb /= 1000000;
-
- if (opb < 20 || opb > 150){
-- printk(KERN_CRIT "ibm-iic: invalid OPB clock frequency %u MHz\n",
-+ printk(KERN_WARNING "ibm-iic: invalid OPB clock frequency %u MHz\n",
- opb);
- opb = opb < 20 ? 20 : 150;
- }
- return (u8)((opb + 9) / 10 - 1);
- }
-
-+#ifdef CONFIG_IBM_OCP
- /*
- * Register single IIC interface
- */
-@@ -672,7 +681,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
- ocp->def->index);
-
- if (!(dev = kzalloc(sizeof(*dev), GFP_KERNEL))) {
-- printk(KERN_CRIT "ibm-iic%d: failed to allocate device data\n",
-+ printk(KERN_ERR "ibm-iic%d: failed to allocate device data\n",
- ocp->def->index);
- return -ENOMEM;
- }
-@@ -687,7 +696,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
- }
-
- if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){
-- printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n",
-+ printk(KERN_ERR "ibm-iic%d: failed to ioremap device registers\n",
- dev->idx);
- ret = -ENXIO;
- goto fail2;
-@@ -745,7 +754,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
- adap->nr = dev->idx >= 0 ? dev->idx : 0;
-
- if ((ret = i2c_add_numbered_adapter(adap)) < 0) {
-- printk(KERN_CRIT "ibm-iic%d: failed to register i2c adapter\n",
-+ printk(KERN_ERR "ibm-iic%d: failed to register i2c adapter\n",
- dev->idx);
- goto fail;
- }
-@@ -778,7 +787,7 @@ static void __devexit iic_remove(struct ocp_device *ocp)
- struct ibm_iic_private* dev = (struct ibm_iic_private*)ocp_get_drvdata(ocp);
- BUG_ON(dev == NULL);
- if (i2c_del_adapter(&dev->adap)){
-- printk(KERN_CRIT "ibm-iic%d: failed to delete i2c adapter :(\n",
-+ printk(KERN_ERR "ibm-iic%d: failed to delete i2c adapter :(\n",
- dev->idx);
- /* That's *very* bad, just shutdown IRQ ... */
- if (dev->irq >= 0){
-@@ -828,5 +837,181 @@ static void __exit iic_exit(void)
- ocp_unregister_driver(&ibm_iic_driver);
- }
-
-+#else /* !CONFIG_IBM_OCP */
++ return 1 + ((epage - spage) >> PAGE_SHIFT);
++}
+
-+static int __devinit iic_request_irq(struct of_device *ofdev,
-+ struct ibm_iic_private *dev)
++/* truncate length to page boundry */
++static int ipath_user_sdma_page_length(unsigned long addr, unsigned long len)
+{
-+ struct device_node *np = ofdev->node;
-+ int irq;
++ const unsigned long offset = addr & ~PAGE_MASK;
++
++ return ((offset + len) > PAGE_SIZE) ? (PAGE_SIZE - offset) : len;
++}
+
-+ if (iic_force_poll)
-+ return NO_IRQ;
++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;
+
-+ 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;
-+ }
++ 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);
+
-+ /* 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;
-+ }
++ if (pkt->addr[i].kvaddr)
++ kunmap(pkt->addr[i].page);
+
-+ return irq;
++ 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);
+}
+
-+/*
-+ * Register single IIC interface
-+ */
-+static int __devinit iic_probe(struct of_device *ofdev,
-+ const struct of_device_id *match)
++/* 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 device_node *np = ofdev->node;
-+ struct ibm_iic_private *dev;
-+ struct i2c_adapter *adap;
-+ const u32 *indexp, *freq;
++ struct page *pages[2];
++ int j;
+ int ret;
+
-+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-+ if (!dev) {
-+ dev_err(&ofdev->dev, "failed to allocate device data\n");
-+ return -ENOMEM;
-+ }
++ ret = get_user_pages(current, current->mm, addr,
++ npages, 0, 1, pages, NULL);
+
-+ dev_set_drvdata(&ofdev->dev, dev);
++ if (ret != npages) {
++ int i;
+
-+ 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;
++ for (i = 0; i < ret; i++)
++ put_page(pages[i]);
+
-+ dev->vaddr = of_iomap(np, 0);
-+ if (dev->vaddr == NULL) {
-+ dev_err(&ofdev->dev, "failed to iomap device\n");
-+ ret = -ENXIO;
-+ goto error_cleanup;
++ ret = -ENOMEM;
++ goto done;
+ }
+
-+ init_waitqueue_head(&dev->wq);
++ 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;
+
-+ dev->irq = iic_request_irq(ofdev, dev);
-+ if (dev->irq == NO_IRQ)
-+ dev_warn(&ofdev->dev, "using polling mode\n");
++ if (dma_mapping_error(dma_addr)) {
++ ret = -ENOMEM;
++ goto done;
++ }
+
-+ /* Board specific settings */
-+ if (iic_force_fast || of_get_property(np, "fast-mode", NULL))
-+ dev->fast_mode = 1;
++ ipath_user_sdma_init_frag(pkt, pkt->naddr, fofs, flen, 1, 1,
++ pages[j], kmap(pages[j]),
++ dma_addr);
+
-+ 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;
-+ }
++ pkt->naddr++;
++ addr += flen;
++ tlen -= flen;
+ }
+
-+ dev->clckdiv = iic_clckdiv(*freq);
-+ dev_dbg(&ofdev->dev, "clckdiv = %d\n", dev->clckdiv);
++done:
++ return ret;
++}
+
-+ /* Initialize IIC interface */
-+ iic_dev_init(dev);
++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;
+
-+ /* 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;
++ 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 = i2c_add_numbered_adapter(adap);
-+ if (ret < 0) {
-+ dev_err(&ofdev->dev, "failed to register i2c adapter\n");
-+ goto error_cleanup;
++ ret = ipath_user_sdma_pin_pages(dd, pkt,
++ addr, iov[idx].iov_len,
++ npages);
++ if (ret < 0)
++ goto free_pkt;
+ }
+
-+ dev_info(&ofdev->dev, "using %s mode\n",
-+ dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
++ goto done;
+
-+ return 0;
++free_pkt:
++ for (idx = 0; idx < pkt->naddr; idx++)
++ ipath_user_sdma_free_pkt_frag(&dd->pcidev->dev, pq, pkt, idx);
+
-+error_cleanup:
-+ if (dev->irq != NO_IRQ) {
-+ iic_interrupt_mode(dev, 0);
-+ free_irq(dev->irq, dev);
-+ }
++done:
++ return ret;
++}
+
-+ if (dev->vaddr)
-+ iounmap(dev->vaddr);
++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);
+
-+ dev_set_drvdata(&ofdev->dev, NULL);
-+ kfree(dev);
+ 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);
++ }
++}
++
+/*
-+ * Cleanup initialized IIC interface
++ * 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 __devexit iic_remove(struct of_device *ofdev)
++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)
+{
-+ struct ibm_iic_private *dev = dev_get_drvdata(&ofdev->dev);
++ 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;
+
-+ dev_set_drvdata(&ofdev->dev, NULL);
++ 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;
+
-+ i2c_del_adapter(&dev->adap);
++ dma_mapped = 0;
++ len = iov[idx].iov_len;
++ nw = len >> 2;
++ page = NULL;
+
-+ if (dev->irq != NO_IRQ) {
-+ iic_interrupt_mode(dev, 0);
-+ free_irq(dev->irq, dev);
-+ }
++ pkt = kmem_cache_alloc(pq->pkt_slab, GFP_KERNEL);
++ if (!pkt) {
++ ret = -ENOMEM;
++ goto free_list;
++ }
+
-+ iounmap(dev->vaddr);
-+ kfree(dev);
++ if (len < IPATH_USER_SDMA_MIN_HEADER_LENGTH ||
++ len > PAGE_SIZE || len & 3 || addr & 3) {
++ ret = -EINVAL;
++ goto free_pkt;
++ }
+
-+ return 0;
-+}
++ if (len == IPATH_USER_SDMA_EXP_HEADER_LENGTH)
++ pbc = dma_pool_alloc(pq->header_cache, GFP_KERNEL,
++ &dma_addr);
++ else
++ pbc = NULL;
+
-+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", },
-+ {}
-+};
++ if (!pbc) {
++ page = alloc_page(GFP_KERNEL);
++ if (!page) {
++ ret = -ENOMEM;
++ goto free_pkt;
++ }
++ pbc = kmap(page);
++ }
+
-+static struct of_platform_driver ibm_iic_driver = {
-+ .name = "ibm-iic",
-+ .match_table = ibm_iic_match,
-+ .probe = iic_probe,
-+ .remove = __devexit_p(iic_remove),
-+};
++ cfur = copy_from_user(pbc, iov[idx].iov_base, len);
++ if (cfur) {
++ ret = -EFAULT;
++ goto free_pbc;
++ }
+
-+static int __init iic_init(void)
-+{
-+ return of_register_platform_driver(&ibm_iic_driver);
++ /*
++ * 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 __exit iic_exit(void)
++static void ipath_user_sdma_set_complete_counter(struct ipath_user_sdma_queue *pq,
++ u32 c)
+{
-+ of_unregister_platform_driver(&ibm_iic_driver);
++ pq->sent_counter = c;
+}
-+#endif /* CONFIG_IBM_OCP */
+
- module_init(iic_init);
- module_exit(iic_exit);
-diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
-index ab41400..39884e7 100644
---- a/drivers/i2c/busses/i2c-iop3xx.c
-+++ b/drivers/i2c/busses/i2c-iop3xx.c
-@@ -550,3 +550,4 @@ module_exit (i2c_iop3xx_exit);
- MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>");
- MODULE_DESCRIPTION("IOP3xx iic algorithm and driver");
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:IOP3xx-I2C");
-diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
-index 6352121..5af9e65 100644
---- a/drivers/i2c/busses/i2c-ixp2000.c
-+++ b/drivers/i2c/busses/i2c-ixp2000.c
-@@ -164,4 +164,5 @@ module_exit(ixp2000_i2c_exit);
- MODULE_AUTHOR ("Deepak Saxena <dsaxena at plexity.net>");
- MODULE_DESCRIPTION("IXP2000 GPIO-based I2C bus driver");
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:IXP2000-I2C");
-
-diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
-index bbe787b..18beb0a 100644
---- a/drivers/i2c/busses/i2c-mpc.c
-+++ b/drivers/i2c/busses/i2c-mpc.c
-@@ -392,6 +392,9 @@ static int fsl_i2c_remove(struct platform_device *pdev)
- return 0;
- };
-
-+/* work with hotplug and coldplug */
-+MODULE_ALIAS("platform:fsl-i2c");
++/* 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;
+
- /* 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");
++ INIT_LIST_HEAD(&free_list);
+
- static struct platform_driver ocores_i2c_driver = {
- .probe = ocores_i2c_probe,
- .remove = __devexit_p(ocores_i2c_remove),
-diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
-index 7ba3177..e7eb7bf 100644
---- a/drivers/i2c/busses/i2c-omap.c
-+++ b/drivers/i2c/busses/i2c-omap.c
-@@ -693,3 +693,4 @@ module_exit(omap_i2c_exit_driver);
- MODULE_AUTHOR("MontaVista Software, Inc. (and others)");
- MODULE_DESCRIPTION("TI OMAP I2C bus adapter");
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:i2c_omap");
-diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
-index 496ee87..a119784 100644
---- a/drivers/i2c/busses/i2c-pca-isa.c
-+++ b/drivers/i2c/busses/i2c-pca-isa.c
-@@ -1,6 +1,7 @@
- /*
- * i2c-pca-isa.c driver for PCA9564 on ISA boards
- * Copyright (C) 2004 Arcom Control Systems
-+ * Copyright (C) 2008 Pengutronix
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -22,11 +23,9 @@
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/delay.h>
--#include <linux/slab.h>
- #include <linux/init.h>
- #include <linux/interrupt.h>
- #include <linux/wait.h>
--
- #include <linux/isa.h>
- #include <linux/i2c.h>
- #include <linux/i2c-algo-pca.h>
-@@ -34,13 +33,9 @@
- #include <asm/io.h>
- #include <asm/irq.h>
-
--#include "../algos/i2c-algo-pca.h"
--
-+#define DRIVER "i2c-pca-isa"
- #define IO_SIZE 4
-
--#undef DEBUG_IO
--//#define DEBUG_IO
--
- static unsigned long base = 0x330;
- static int irq = 10;
-
-@@ -48,22 +43,9 @@ static int irq = 10;
- * in the actual clock rate */
- static int clock = I2C_PCA_CON_59kHz;
-
--static int own = 0x55;
--
- static wait_queue_head_t pca_wait;
-
--static int pca_isa_getown(struct i2c_algo_pca_data *adap)
--{
-- return (own);
--}
--
--static int pca_isa_getclock(struct i2c_algo_pca_data *adap)
--{
-- return (clock);
--}
--
--static void
--pca_isa_writebyte(struct i2c_algo_pca_data *adap, int reg, int val)
-+static void pca_isa_writebyte(void *pd, int reg, int val)
- {
- #ifdef DEBUG_IO
- static char *names[] = { "T/O", "DAT", "ADR", "CON" };
-@@ -72,44 +54,49 @@ pca_isa_writebyte(struct i2c_algo_pca_data *adap, int reg, int val)
- outb(val, base+reg);
- }
-
--static int
--pca_isa_readbyte(struct i2c_algo_pca_data *adap, int reg)
-+static int pca_isa_readbyte(void *pd, int reg)
- {
- int res = inb(base+reg);
- #ifdef DEBUG_IO
- {
-- static char *names[] = { "STA", "DAT", "ADR", "CON" };
-+ static char *names[] = { "STA", "DAT", "ADR", "CON" };
- printk("*** read %s => %#04x\n", names[reg], res);
- }
- #endif
- return res;
- }
-
--static int pca_isa_waitforinterrupt(struct i2c_algo_pca_data *adap)
-+static int pca_isa_waitforcompletion(void *pd)
- {
- int ret = 0;
-
- if (irq > -1) {
- ret = wait_event_interruptible(pca_wait,
-- pca_isa_readbyte(adap, I2C_PCA_CON) & I2C_PCA_CON_SI);
-+ pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI);
- } else {
-- while ((pca_isa_readbyte(adap, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0)
-+ while ((pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0)
- udelay(100);
- }
- return ret;
- }
-
-+static void pca_isa_resetchip(void *pd)
-+{
-+ /* apparently only an external reset will do it. not a lot can be done */
-+ printk(KERN_WARNING DRIVER ": Haven't figured out how to do a reset yet\n");
-+}
++ list_for_each_entry_safe(pkt, pkt_prev, &pq->sent, list) {
++ s64 descd = dd->ipath_sdma_descq_removed - pkt->added;
+
- 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.
++ if (descd < 0)
++ break;
+
-+ */
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/delay.h>
-+#include <linux/errno.h>
-+#include <linux/i2c.h>
-+#include <linux/interrupt.h>
-+#include <linux/platform_device.h>
-+#include <linux/i2c-algo-pca.h>
-+#include <linux/i2c-pca-platform.h>
-+#include <linux/gpio.h>
++ list_move_tail(&pkt->list, &free_list);
+
-+#include <asm/irq.h>
-+#include <asm/io.h>
++ /* one more packet cleaned */
++ ret++;
++ }
+
-+#define res_len(r) ((r)->end - (r)->start + 1)
++ if (!list_empty(&free_list)) {
++ u32 counter;
+
-+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;
-+};
++ pkt = list_entry(free_list.prev,
++ struct ipath_user_sdma_pkt, list);
++ counter = pkt->counter;
+
-+/* Read/Write functions for different register alignments */
++ ipath_user_sdma_free_pkt_list(&dd->pcidev->dev, pq, &free_list);
++ ipath_user_sdma_set_complete_counter(pq, counter);
++ }
+
-+static int i2c_pca_pf_readbyte8(void *pd, int reg)
++ return ret;
++}
++
++void ipath_user_sdma_queue_destroy(struct ipath_user_sdma_queue *pq)
+{
-+ struct i2c_pca_pf_data *i2c = pd;
-+ return ioread8(i2c->reg_base + reg);
++ if (!pq)
++ return;
++
++ kmem_cache_destroy(pq->pkt_slab);
++ dma_pool_destroy(pq->header_cache);
++ kfree(pq);
+}
+
-+static int i2c_pca_pf_readbyte16(void *pd, int reg)
++/* clean descriptor queue, returns > 0 if some elements cleaned */
++static int ipath_user_sdma_hwqueue_clean(struct ipath_devdata *dd)
+{
-+ struct i2c_pca_pf_data *i2c = pd;
-+ return ioread8(i2c->reg_base + reg * 2);
++ 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;
+}
+
-+static int i2c_pca_pf_readbyte32(void *pd, int reg)
++/* 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)
+{
-+ struct i2c_pca_pf_data *i2c = pd;
-+ return ioread8(i2c->reg_base + reg * 4);
++ 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 void i2c_pca_pf_writebyte8(void *pd, int reg, int val)
++static inline __le64 ipath_sdma_make_desc0(struct ipath_devdata *dd,
++ u64 addr, u64 dwlen, u64 dwoffset)
+{
-+ struct i2c_pca_pf_data *i2c = pd;
-+ iowrite8(val, i2c->reg_base + reg);
++ 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 void i2c_pca_pf_writebyte16(void *pd, int reg, int val)
++static inline __le64 ipath_sdma_make_first_desc0(__le64 descq)
+{
-+ struct i2c_pca_pf_data *i2c = pd;
-+ iowrite8(val, i2c->reg_base + reg * 2);
++ return descq | __constant_cpu_to_le64(1ULL << 12);
+}
+
-+static void i2c_pca_pf_writebyte32(void *pd, int reg, int val)
++static inline __le64 ipath_sdma_make_last_desc0(__le64 descq)
+{
-+ struct i2c_pca_pf_data *i2c = pd;
-+ iowrite8(val, i2c->reg_base + reg * 4);
++ /* 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 int i2c_pca_pf_waitforcompletion(void *pd)
++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)
+{
-+ struct i2c_pca_pf_data *i2c = pd;
+ 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 (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.
++ * 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.
+ */
-+ while ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
-+ & I2C_PCA_CON_SI) == 0)
-+ udelay(100);
++ 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;
+}
+
-+static void i2c_pca_pf_dummyreset(void *pd)
++int ipath_user_sdma_writev(struct ipath_devdata *dd,
++ struct ipath_user_sdma_queue *pq,
++ const struct iovec *iov,
++ unsigned long dim)
+{
-+ struct i2c_pca_pf_data *i2c = pd;
-+ printk(KERN_WARNING "%s: No reset-pin found. Chip may get stuck!\n",
-+ i2c->adap.name);
-+}
++ int ret = 0;
++ struct list_head list;
++ int npkts = 0;
+
-+static void i2c_pca_pf_resetchip(void *pd)
-+{
-+ struct i2c_pca_pf_data *i2c = pd;
++ INIT_LIST_HEAD(&list);
+
-+ gpio_set_value(i2c->gpio, 0);
-+ ndelay(100);
-+ gpio_set_value(i2c->gpio, 1);
++ 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;
+}
+
-+static irqreturn_t i2c_pca_pf_handler(int this_irq, void *dev_id)
++int ipath_user_sdma_make_progress(struct ipath_devdata *dd,
++ struct ipath_user_sdma_queue *pq)
+{
-+ 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;
++ int ret = 0;
+
-+ wake_up_interruptible(&i2c->wait);
++ mutex_lock(&pq->lock);
++ ipath_user_sdma_hwqueue_clean(dd);
++ ret = ipath_user_sdma_queue_clean(dd, pq);
++ mutex_unlock(&pq->lock);
+
-+ return IRQ_HANDLED;
++ return ret;
+}
+
++u32 ipath_user_sdma_complete_counter(const struct ipath_user_sdma_queue *pq)
++{
++ return pq->sent_counter;
++}
+
-+static int __devinit i2c_pca_pf_probe(struct platform_device *pdev)
++u32 ipath_user_sdma_inflight_counter(struct ipath_user_sdma_queue *pq)
+{
-+ 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;
++ return pq->counter;
++}
+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ irq = platform_get_irq(pdev, 0);
-+ /* If irq is 0, we do polling. */
+diff --git a/drivers/infiniband/hw/ipath/ipath_user_sdma.h b/drivers/infiniband/hw/ipath/ipath_user_sdma.h
+new file mode 100644
+index 0000000..e70946c
+--- /dev/null
++++ b/drivers/infiniband/hw/ipath/ipath_user_sdma.h
+@@ -0,0 +1,54 @@
++/*
++ * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses. You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ * Redistribution and use in source and binary forms, with or
++ * without modification, are permitted provided that the following
++ * conditions are met:
++ *
++ * - Redistributions of source code must retain the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer.
++ *
++ * - Redistributions in binary form must reproduce the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer in the documentation and/or other materials
++ * provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++#include <linux/device.h>
+
-+ if (res == NULL) {
-+ ret = -ENODEV;
-+ goto e_print;
-+ }
++struct ipath_user_sdma_queue;
+
-+ if (!request_mem_region(res->start, res_len(res), res->name)) {
-+ ret = -ENOMEM;
-+ goto e_print;
-+ }
++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);
+
-+ i2c = kzalloc(sizeof(struct i2c_pca_pf_data), GFP_KERNEL);
-+ if (!i2c) {
-+ ret = -ENOMEM;
-+ goto e_alloc;
-+ }
++int ipath_user_sdma_writev(struct ipath_devdata *dd,
++ struct ipath_user_sdma_queue *pq,
++ const struct iovec *iov,
++ unsigned long dim);
+
-+ init_waitqueue_head(&i2c->wait);
++int ipath_user_sdma_make_progress(struct ipath_devdata *dd,
++ struct ipath_user_sdma_queue *pq);
+
-+ 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;
++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);
+
-+ 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;
++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 */
+
-+ i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed;
-+ i2c->algo_data.data = i2c;
++ while (length) {
++ u32 len = sge.length;
+
-+ 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;
++ 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;
++}
+
-+ i2c->algo_data.wait_for_completion = i2c_pca_pf_waitforcompletion;
++/*
++ * 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;
+
-+ i2c->gpio = platform_data->gpio;
-+ i2c->algo_data.reset_chip = i2c_pca_pf_dummyreset;
++ while (length) {
++ u32 len = sge->length;
+
-+ /* 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 (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;
+ }
++}
+
-+ if (irq) {
-+ ret = request_irq(irq, i2c_pca_pf_handler,
-+ IRQF_TRIGGER_FALLING, i2c->adap.name, i2c);
-+ if (ret)
-+ goto e_reqirq;
+ /**
+ * 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;
+ }
++}
+
-+ if (i2c_pca_add_numbered_bus(&i2c->adap) < 0) {
-+ ret = -ENODEV;
-+ goto e_adapt;
++/*
++ * 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;
+ }
++}
+
-+ platform_set_drvdata(pdev, i2c);
++static inline struct ipath_verbs_txreq *get_txreq(struct ipath_ibdev *dev)
++{
++ struct ipath_verbs_txreq *tx = NULL;
++ unsigned long flags;
+
-+ printk(KERN_INFO "%s registered.\n", i2c->adap.name);
++ spin_lock_irqsave(&dev->pending_lock, flags);
++ if (!list_empty(&dev->txreq_free)) {
++ struct list_head *l = dev->txreq_free.next;
+
-+ return 0;
++ list_del(l);
++ tx = list_entry(l, struct ipath_verbs_txreq, txreq.list);
++ }
++ spin_unlock_irqrestore(&dev->pending_lock, flags);
++ return tx;
++}
+
-+e_adapt:
-+ if (irq)
-+ free_irq(irq, i2c);
-+e_reqirq:
-+ if (i2c->gpio > -1)
-+ gpio_free(i2c->gpio);
++static inline void put_txreq(struct ipath_ibdev *dev,
++ struct ipath_verbs_txreq *tx)
++{
++ unsigned long flags;
+
-+ 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;
++ spin_lock_irqsave(&dev->pending_lock, flags);
++ list_add(&tx->txreq.list, &dev->txreq_free);
++ spin_unlock_irqrestore(&dev->pending_lock, flags);
+}
+
-+static int __devexit i2c_pca_pf_remove(struct platform_device *pdev)
++static void sdma_complete(void *cookie, int status)
+{
-+ struct i2c_pca_pf_data *i2c = platform_get_drvdata(pdev);
-+ platform_set_drvdata(pdev, NULL);
-+
-+ i2c_del_adapter(&i2c->adap);
++ struct ipath_verbs_txreq *tx = cookie;
++ struct ipath_qp *qp = tx->qp;
++ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+
-+ if (i2c->irq)
-+ free_irq(i2c->irq, i2c);
++ /* 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;
+
-+ if (i2c->gpio > -1)
-+ gpio_free(i2c->gpio);
++ ipath_send_complete(qp, tx->wqe, ibs);
++ }
+
-+ iounmap(i2c->reg_base);
-+ release_mem_region(i2c->io_base, i2c->io_size);
-+ kfree(i2c);
++ if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_FREEBUF)
++ kfree(tx->txreq.map_addr);
++ put_txreq(dev, tx);
+
-+ return 0;
++ if (atomic_dec_and_test(&qp->refcount))
++ wake_up(&qp->wait);
+}
+
-+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)
++/*
++ * 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 platform_driver_register(&i2c_pca_pf_driver);
++ return (rcv_mult > snd_mult) ?
++ (plen * (rcv_mult - snd_mult) + 1) >> 1 : 0;
+}
+
-+static void __exit i2c_pca_pf_exit(void)
++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)
+{
-+ platform_driver_unregister(&i2c_pca_pf_driver);
-+}
++ 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;
+
-+MODULE_AUTHOR("Wolfram Sang <w.sang at pengutronix.de>");
-+MODULE_DESCRIPTION("I2C-PCA9564 platform driver");
-+MODULE_LICENSE("GPL");
++ 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;
++ }
+
-+module_init(i2c_pca_pf_init);
-+module_exit(i2c_pca_pf_exit);
++ tx = get_txreq(dev);
++ if (!tx) {
++ ret = -EBUSY;
++ goto bail;
++ }
+
-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);
++ /*
++ * 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);
+
- 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)
++ 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 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));
+ struct ipath_devdata *dd = to_idev(qp->ibqp.device)->dd;
++ u32 *hdr = (u32 *) ibhdr;
+ u32 __iomem *piobuf;
+ unsigned flush_wc;
++ u32 control;
+ int ret;
-- dev_dbg(&adap->dev, "%s(): exit\n", __FUNCTION__);
-+ dev_dbg(&adap->dev, "%s(): exit\n", __func__);
+- piobuf = ipath_getpiobuf(dd, NULL);
++ piobuf = ipath_getpiobuf(dd, plen, NULL);
+ if (unlikely(piobuf == NULL)) {
+ ret = -EBUSY;
+ goto bail;
+ }
- return 0;
- }
-@@ -135,7 +135,7 @@ static void i2c_pnx_stop(struct i2c_adapter *adap)
- long timeout = 1000;
+ /*
+- * 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;
- dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
-- __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
-+ __func__, ioread32(I2C_REG_STS(alg_data)));
+ 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;
- /* 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)
- }
+- /* 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);
- dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
-- __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
-+ __func__, ioread32(I2C_REG_STS(alg_data)));
+ 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;
- /**
-@@ -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));
+ ret = 0;
-- 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);
+@@ -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;
- 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);
+- /*
+- * 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,
- dev_dbg(&adap->dev, "%s(): Waking up xfer routine.\n",
-- __FUNCTION__);
-+ __func__);
+ /* ib_create_ah() will initialize ah->ibah. */
+ ah->attr = *ah_attr;
++ ah->attr.static_rate = ipath_ib_rate_to_mult(ah_attr->static_rate);
- 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__);
+ ret = &ah->ibah;
- complete(&alg_data->mif.complete);
- }
+@@ -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);
- dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
-- __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
-+ __func__, ioread32(I2C_REG_STS(alg_data)));
+ *ah_attr = ah->attr;
++ ah_attr->static_rate = ipath_mult_to_ib_rate(ah->attr.static_rate);
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)));
+@@ -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;
- /* 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__);
+ idev = (struct ipath_ibdev *)ib_alloc_device(sizeof *idev);
+@@ -1591,6 +1932,17 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
- 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);
+ dev = &idev->ibdev;
- alg_data->mif.len--;
-@@ -300,7 +300,7 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
- }
++ 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 */
- dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
-- __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
-+ __func__, ioread32(I2C_REG_STS(alg_data)));
+ /* 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;
- return 0;
++ 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);
}
-@@ -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)));
+-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);
- bus_reset_if_active(adap);
+ return sprintf(buf, "%x\n", dev->dd->ipath_pcirev);
+ }
-@@ -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);
+-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;
-- 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);
+ ret = dev->dd->ipath_f_get_boardname(dev->dd, buf, 128);
+@@ -1835,10 +2197,11 @@ bail:
+ return ret;
+ }
-@@ -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);
+-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;
- /* 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;
+@@ -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];
- dev_dbg(&adap->dev, "%s(): exiting, stat = %x\n",
-- __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
-+ __func__, ioread32(I2C_REG_STS(alg_data)));
+@@ -1874,16 +2239,16 @@ static ssize_t show_stats(struct class_device *cdev, char *buf)
+ return len;
+ }
- if (completed != num)
- return ((rc < 0) ? rc : -EREMOTEIO);
-@@ -563,7 +563,7 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev)
+-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);
- if (!i2c_pnx || !i2c_pnx->adapter) {
- dev_err(&pdev->dev, "%s: no platform data supplied\n",
-- __FUNCTION__);
-+ __func__);
- ret = -EINVAL;
- goto out;
- }
-@@ -697,6 +697,7 @@ static void __exit i2c_adap_pnx_exit(void)
- MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev <source at mvista.com>");
- MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses");
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:pnx-i2c");
+-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
+ };
- /* 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)
- }
+ 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));
-+/* work with hotplug and coldplug */
-+MODULE_ALIAS("platform:i2c-powermac");
++struct ipath_pio_header {
++ __le32 pbc[2];
++ struct ipath_ib_header hdr;
++} __attribute__ ((packed));
+
- static struct platform_driver i2c_powermac_driver = {
- .probe = i2c_powermac_probe,
- .remove = __devexit_p(i2c_powermac_remove),
-diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
-index 2d2087a..eb69fba 100644
---- a/drivers/i2c/busses/i2c-pxa.c
-+++ b/drivers/i2c/busses/i2c-pxa.c
-@@ -39,6 +39,7 @@
- #include <asm/io.h>
- #include <asm/arch/i2c.h>
- #include <asm/arch/pxa-regs.h>
-+#include <asm/arch/pxa2xx-gpio.h>
-
- struct pxa_i2c {
- spinlock_t lock;
-@@ -154,7 +155,7 @@ static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname)
- readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
- }
+ /*
+ * 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;
+ };
--#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
+ /*
+@@ -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;
+ };
-@@ -1131,6 +1132,7 @@ static void __exit i2c_adap_pxa_exit(void)
- }
++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);
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:pxa2xx-i2c");
+ void ipath_get_credit(struct ipath_qp *qp, u32 aeth);
- 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) {
++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);
- 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;
+-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);
- 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;
+ 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..2f199c5 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);
+ }
-@@ -948,3 +948,4 @@ module_exit(i2c_adap_s3c_exit);
- MODULE_DESCRIPTION("S3C24XX I2C Bus driver");
- MODULE_AUTHOR("Ben Dooks, <ben at simtec.co.uk>");
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:s3c2410-i2c");
-diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c
-new file mode 100644
-index 0000000..5e0e254
---- /dev/null
-+++ b/drivers/i2c/busses/i2c-sh7760.c
-@@ -0,0 +1,577 @@
-+/*
-+ * I2C bus driver for the SH7760 I2C Interfaces.
-+ *
-+ * (c) 2005-2008 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau at msc-ge.com>
-+ *
-+ * licensed under the terms outlined in the file COPYING.
-+ *
-+ */
-+
-+#include <linux/completion.h>
-+#include <linux/delay.h>
-+#include <linux/err.h>
-+#include <linux/i2c.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/ioport.h>
-+#include <linux/platform_device.h>
-+#include <linux/slab.h>
-+
-+#include <asm/clock.h>
-+#include <asm/i2c-sh7760.h>
-+#include <asm/io.h>
-+
-+/* register offsets */
-+#define I2CSCR 0x0 /* slave ctrl */
-+#define I2CMCR 0x4 /* master ctrl */
-+#define I2CSSR 0x8 /* slave status */
-+#define I2CMSR 0xC /* master status */
-+#define I2CSIER 0x10 /* slave irq enable */
-+#define I2CMIER 0x14 /* master irq enable */
-+#define I2CCCR 0x18 /* clock dividers */
-+#define I2CSAR 0x1c /* slave address */
-+#define I2CMAR 0x20 /* master address */
-+#define I2CRXTX 0x24 /* data port */
-+#define I2CFCR 0x28 /* fifo control */
-+#define I2CFSR 0x2C /* fifo status */
-+#define I2CFIER 0x30 /* fifo irq enable */
-+#define I2CRFDR 0x34 /* rx fifo count */
-+#define I2CTFDR 0x38 /* tx fifo count */
-+
-+#define REGSIZE 0x3C
-+
-+#define MCR_MDBS 0x80 /* non-fifo mode switch */
-+#define MCR_FSCL 0x40 /* override SCL pin */
-+#define MCR_FSDA 0x20 /* override SDA pin */
-+#define MCR_OBPC 0x10 /* override pins */
-+#define MCR_MIE 0x08 /* master if enable */
-+#define MCR_TSBE 0x04
-+#define MCR_FSB 0x02 /* force stop bit */
-+#define MCR_ESG 0x01 /* en startbit gen. */
-+
-+#define MSR_MNR 0x40 /* nack received */
-+#define MSR_MAL 0x20 /* arbitration lost */
-+#define MSR_MST 0x10 /* sent a stop */
-+#define MSR_MDE 0x08
-+#define MSR_MDT 0x04
-+#define MSR_MDR 0x02
-+#define MSR_MAT 0x01 /* slave addr xfer done */
-+
-+#define MIE_MNRE 0x40 /* nack irq en */
-+#define MIE_MALE 0x20 /* arblos irq en */
-+#define MIE_MSTE 0x10 /* stop irq en */
-+#define MIE_MDEE 0x08
-+#define MIE_MDTE 0x04
-+#define MIE_MDRE 0x02
-+#define MIE_MATE 0x01 /* address sent irq en */
-+
-+#define FCR_RFRST 0x02 /* reset rx fifo */
-+#define FCR_TFRST 0x01 /* reset tx fifo */
-+
-+#define FSR_TEND 0x04 /* last byte sent */
-+#define FSR_RDF 0x02 /* rx fifo trigger */
-+#define FSR_TDFE 0x01 /* tx fifo empty */
-+
-+#define FIER_TEIE 0x04 /* tx fifo empty irq en */
-+#define FIER_RXIE 0x02 /* rx fifo trig irq en */
-+#define FIER_TXIE 0x01 /* tx fifo trig irq en */
-+
-+#define FIFO_SIZE 16
-+
-+struct cami2c {
-+ void __iomem *iobase;
-+ struct i2c_adapter adap;
-+
-+ /* message processing */
-+ struct i2c_msg *msg;
-+#define IDF_SEND 1
-+#define IDF_RECV 2
-+#define IDF_STOP 4
-+ int flags;
-+
-+#define IDS_DONE 1
-+#define IDS_ARBLOST 2
-+#define IDS_NACK 4
-+ int status;
-+ struct completion xfer_done;
-+
-+ int irq;
-+ struct resource *ioarea;
-+};
-+
-+static inline void OUT32(struct cami2c *cam, int reg, unsigned long val)
++int mlx4_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period)
+{
-+ ctrl_outl(val, (unsigned long)cam->iobase + reg);
-+}
++ struct mlx4_ib_cq *mcq = to_mcq(cq);
++ struct mlx4_ib_dev *dev = to_mdev(cq->device);
+
-+static inline unsigned long IN32(struct cami2c *cam, int reg)
-+{
-+ return ctrl_inl((unsigned long)cam->iobase + reg);
++ return mlx4_cq_modify(dev->dev, &mcq->mcq, cq_count, cq_period);
+}
+
-+static irqreturn_t sh7760_i2c_irq(int irq, void *ptr)
++static int mlx4_ib_alloc_cq_buf(struct mlx4_ib_dev *dev, struct mlx4_ib_cq_buf *buf, int nent)
+{
-+ 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;
-+ }
++ int err;
+
-+ 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. */
-+ }
++ err = mlx4_buf_alloc(dev->dev, nent * sizeof(struct mlx4_cqe),
++ PAGE_SIZE * 2, &buf->buf);
+
-+ /* i2c-stop was sent */
-+ if (msr & MSR_MST) {
-+ id->status |= IDS_DONE;
++ if (err)
+ goto out;
-+ }
-+
-+ /* i2c slave addr was sent; set to "normal" operation */
-+ if (msr & MSR_MAT)
-+ OUT32(id, I2CMCR, MCR_MIE);
+
-+ fier = IN32(id, I2CFIER);
++ err = mlx4_mtt_init(dev->dev, buf->buf.npages, buf->buf.page_shift,
++ &buf->mtt);
++ if (err)
++ goto err_buf;
+
-+ 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--;
-+ }
++ err = mlx4_buf_write_mtt(dev->dev, &buf->mtt, &buf->buf);
++ if (err)
++ goto err_mtt;
+
-+ if (msg->len) {
-+ len = (msg->len >= FIFO_SIZE) ? FIFO_SIZE - 1
-+ : msg->len - 1;
++ return 0;
+
-+ OUT32(id, I2CFCR, FCR_TFRST | ((len & 0xf) << 4));
-+ }
++err_mtt:
++ mlx4_mtt_cleanup(dev->dev, &buf->mtt);
+
-+ } 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--;
-+ }
++err_buf:
++ mlx4_buf_free(dev->dev, nent * sizeof(struct mlx4_cqe),
++ &buf->buf);
+
-+ 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;
++ return err;
+}
+
-+
-+/* prepare and start a master receive operation */
-+static void sh7760_i2c_mrecv(struct cami2c *id)
++static void mlx4_ib_free_cq_buf(struct mlx4_ib_dev *dev, struct mlx4_ib_cq_buf *buf, int cqe)
+{
-+ 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);
++ mlx4_buf_free(dev->dev, (cqe + 1) * sizeof(struct mlx4_cqe), &buf->buf);
+}
+
-+/* prepare and start a master send operation */
-+static void sh7760_i2c_msend(struct cami2c *id)
++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 len;
++ int err;
+
-+ id->flags |= IDF_SEND;
++ *umem = ib_umem_get(context, buf_addr, cqe * sizeof (struct mlx4_cqe),
++ IB_ACCESS_LOCAL_WRITE, 1);
++ if (IS_ERR(*umem))
++ return PTR_ERR(*umem);
+
-+ /* set the slave addr reg; otherwise xmit wont work! */
-+ OUT32(id, I2CSAR, 0xfe);
-+ OUT32(id, I2CMAR, (id->msg->addr << 1) | 0);
++ err = mlx4_mtt_init(dev->dev, ib_umem_page_count(*umem),
++ ilog2((*umem)->page_size), &buf->mtt);
++ if (err)
++ goto err_buf;
+
-+ /* 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 */
++ err = mlx4_ib_umem_write_mtt(dev, &buf->mtt, *umem);
++ if (err)
++ goto err_mtt;
+
-+ OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
-+ OUT32(id, I2CFCR, FCR_RFRST | ((len & 3) << 2));
++ return 0;
+
-+ while (id->msg->len && IN32(id, I2CTFDR) < FIFO_SIZE) {
-+ OUT32(id, I2CRXTX, *(id->msg->buf));
-+ (id->msg->len)--;
-+ (id->msg->buf)++;
-+ }
++err_mtt:
++ mlx4_mtt_cleanup(dev->dev, &buf->mtt);
+
-+ 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));
-+}
++err_buf:
++ ib_umem_release(*umem);
+
-+static inline int sh7760_i2c_busy_check(struct cami2c *id)
-+{
-+ return (IN32(id, I2CMCR) & MCR_FSDA);
++ return err;
+}
+
-+static int sh7760_i2c_master_xfer(struct i2c_adapter *adap,
-+ struct i2c_msg *msgs,
-+ int num)
+ 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);
+@@ -138,7 +204,7 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
+
+ uar = &to_mucontext(context)->uar;
+ } else {
+- err = mlx4_ib_db_alloc(dev, &cq->db, 1);
++ err = mlx4_db_alloc(dev->dev, &cq->db, 1);
+ if (err)
+ goto err_cq;
+
+@@ -147,25 +213,15 @@ 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;
+ }
+
+ err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar,
+- cq->db.dma, &cq->mcq);
++ cq->db.dma, &cq->mcq, 0);
+ if (err)
+ goto err_dbmap;
+
+@@ -187,16 +243,14 @@ 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)
+- mlx4_ib_db_free(dev, &cq->db);
++ mlx4_db_free(dev->dev, &cq->db);
+
+ err_cq:
+ kfree(cq);
+@@ -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)
+{
-+ struct cami2c *id = adap->algo_data;
-+ int i, retr;
++ int err;
+
-+ if (sh7760_i2c_busy_check(id)) {
-+ dev_err(&adap->dev, "sh7760-i2c%d: bus busy!\n", adap->nr);
++ if (cq->resize_buf)
+ 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;
++ cq->resize_buf = kmalloc(sizeof *cq->resize_buf, GFP_ATOMIC);
++ if (!cq->resize_buf)
++ return -ENOMEM;
+
-+ mclk = clk_get(NULL, "module_clk");
-+ if (IS_ERR(mclk)) {
-+ return PTR_ERR(mclk);
-+ } else {
-+ mck = mclk->rate;
-+ clk_put(mclk);
++ err = mlx4_ib_alloc_cq_buf(dev, &cq->resize_buf->buf, entries);
++ if (err) {
++ kfree(cq->resize_buf);
++ cq->resize_buf = NULL;
++ return err;
+ }
+
-+ 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;
++ cq->resize_buf->cqe = entries - 1;
+
-+ /* create a CCR register value */
-+ return ((scgdm << 2) | cdfm);
++ return 0;
+}
+
-+static int __devinit sh7760_i2c_probe(struct platform_device *pdev)
++static int mlx4_alloc_resize_umem(struct mlx4_ib_dev *dev, struct mlx4_ib_cq *cq,
++ int entries, struct ib_udata *udata)
+{
-+ 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);
++ struct mlx4_ib_resize_cq ucmd;
++ int err;
+
-+ 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);
++ if (cq->resize_umem)
++ return -EBUSY;
+
-+ 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 (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
++ return -EFAULT;
+
-+ 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;
-+ }
++ cq->resize_buf = kmalloc(sizeof *cq->resize_buf, GFP_ATOMIC);
++ if (!cq->resize_buf)
++ return -ENOMEM;
+
-+ ret = i2c_add_numbered_adapter(&id->adap);
-+ if (ret < 0) {
-+ dev_err(&pdev->dev, "reg adap failed: %d\n", ret);
-+ goto out4;
++ 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;
+ }
+
-+ 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);
++ cq->resize_buf->cqe = entries - 1;
+
+ return 0;
+}
+
-+static struct platform_driver sh7760_i2c_drv = {
-+ .driver = {
-+ .name = SH7760_I2C_DEVNAME,
-+ .owner = THIS_MODULE,
-+ },
-+ .probe = sh7760_i2c_probe,
-+ .remove = __devexit_p(sh7760_i2c_remove),
-+};
-+
-+static int __init sh7760_i2c_init(void)
-+{
-+ return platform_driver_register(&sh7760_i2c_drv);
-+}
-+
-+static void __exit sh7760_i2c_exit(void)
-+{
-+ platform_driver_unregister(&sh7760_i2c_drv);
-+}
-+
-+module_init(sh7760_i2c_init);
-+module_exit(sh7760_i2c_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("SH7760 I2C bus driver");
-+MODULE_AUTHOR("Manuel Lauss <mano at roarinelk.homelinux.net>");
-diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
-new file mode 100644
-index 0000000..840e634
---- /dev/null
-+++ b/drivers/i2c/busses/i2c-sh_mobile.c
-@@ -0,0 +1,500 @@
-+/*
-+ * SuperH Mobile I2C Controller
-+ *
-+ * Copyright (C) 2008 Magnus Damm
-+ *
-+ * Portions of the code based on out-of-tree driver i2c-sh7343.c
-+ * Copyright (c) 2006 Carlos Munoz <carlos at kenati.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/platform_device.h>
-+#include <linux/interrupt.h>
-+#include <linux/i2c.h>
-+#include <linux/err.h>
-+#include <linux/clk.h>
-+#include <linux/io.h>
-+
-+enum sh_mobile_i2c_op {
-+ OP_START = 0,
-+ OP_TX_ONLY,
-+ OP_TX_STOP,
-+ OP_TX_TO_RX,
-+ OP_RX_ONLY,
-+ OP_RX_STOP,
-+};
-+
-+struct sh_mobile_i2c_data {
-+ struct device *dev;
-+ void __iomem *reg;
-+ struct i2c_adapter adap;
-+
-+ struct clk *clk;
-+ u_int8_t iccl;
-+ u_int8_t icch;
-+
-+ spinlock_t lock;
-+ wait_queue_head_t wait;
-+ struct i2c_msg *msg;
-+ int pos;
-+ int sr;
-+};
-+
-+#define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */
-+
-+/* Register offsets */
-+#define ICDR(pd) (pd->reg + 0x00)
-+#define ICCR(pd) (pd->reg + 0x04)
-+#define ICSR(pd) (pd->reg + 0x08)
-+#define ICIC(pd) (pd->reg + 0x0c)
-+#define ICCL(pd) (pd->reg + 0x10)
-+#define ICCH(pd) (pd->reg + 0x14)
-+
-+/* Register bits */
-+#define ICCR_ICE 0x80
-+#define ICCR_RACK 0x40
-+#define ICCR_TRS 0x10
-+#define ICCR_BBSY 0x04
-+#define ICCR_SCP 0x01
-+
-+#define ICSR_SCLM 0x80
-+#define ICSR_SDAM 0x40
-+#define SW_DONE 0x20
-+#define ICSR_BUSY 0x10
-+#define ICSR_AL 0x08
-+#define ICSR_TACK 0x04
-+#define ICSR_WAIT 0x02
-+#define ICSR_DTE 0x01
-+
-+#define ICIC_ALE 0x08
-+#define ICIC_TACKE 0x04
-+#define ICIC_WAITE 0x02
-+#define ICIC_DTEE 0x01
-+
-+static void activate_ch(struct sh_mobile_i2c_data *pd)
-+{
-+ /* Make sure the clock is enabled */
-+ clk_enable(pd->clk);
-+
-+ /* Enable channel and configure rx ack */
-+ iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd));
-+
-+ /* Mask all interrupts */
-+ iowrite8(0, ICIC(pd));
-+
-+ /* Set the clock */
-+ iowrite8(pd->iccl, ICCL(pd));
-+ iowrite8(pd->icch, ICCH(pd));
-+}
-+
-+static void deactivate_ch(struct sh_mobile_i2c_data *pd)
++static int mlx4_ib_get_outstanding_cqes(struct mlx4_ib_cq *cq)
+{
-+ /* Clear/disable interrupts */
-+ iowrite8(0, ICSR(pd));
-+ iowrite8(0, ICIC(pd));
++ u32 i;
+
-+ /* Disable channel */
-+ iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd));
++ i = cq->mcq.cons_index;
++ while (get_sw_cqe(cq, i & cq->ibcq.cqe))
++ ++i;
+
-+ /* Disable clock */
-+ clk_disable(pd->clk);
++ return i - cq->mcq.cons_index;
+}
+
-+static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
-+ enum sh_mobile_i2c_op op, unsigned char data)
++static void mlx4_ib_cq_resize_copy_cqes(struct mlx4_ib_cq *cq)
+{
-+ 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);
++ struct mlx4_cqe *cqe;
++ int i;
+
-+ 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;
++ 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);
+ }
-+
-+ spin_unlock_irqrestore(&pd->lock, flags);
-+
-+ dev_dbg(pd->dev, "op %d, data out 0x%02x\n", op, ret);
-+ return ret;
++ ++cq->mcq.cons_index;
+}
+
-+static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
++int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
+{
-+ 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;
++ struct mlx4_ib_dev *dev = to_mdev(ibcq->device);
++ struct mlx4_ib_cq *cq = to_mcq(ibcq);
++ int outst_cqe;
++ int err;
+
-+ 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);
++ mutex_lock(&cq->resize_mutex);
+
-+ if (sr & (ICSR_AL | ICSR_TACK)) {
-+ iowrite8(0, ICIC(pd)); /* disable interrupts */
-+ wakeup = 1;
-+ goto do_wakeup;
++ if (entries < 1 || entries > dev->dev->caps.max_cqes) {
++ err = -EINVAL;
++ goto out;
+ }
+
-+ if (pd->pos == msg->len) {
-+ i2c_op(pd, OP_RX_ONLY, 0);
-+ wakeup = 1;
-+ goto do_wakeup;
++ entries = roundup_pow_of_two(entries + 1);
++ if (entries == ibcq->cqe + 1) {
++ err = 0;
++ goto out;
+ }
+
-+ 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);
++ if (ibcq->uobject) {
++ err = mlx4_alloc_resize_umem(dev, cq, entries, udata);
++ if (err)
++ goto out;
+ } 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];
++ /* 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 = start_ch(pd, msg);
++ err = mlx4_alloc_resize_buf(dev, cq, entries);
+ if (err)
-+ break;
-+
-+ i2c_op(pd, OP_START, 0);
++ goto out;
++ }
+
-+ /* 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");
++ err = mlx4_cq_resize(dev->dev, &cq->mcq, entries, &cq->resize_buf->buf.mtt);
++ if (err)
++ goto err_buf;
+
-+ retry_count = 10;
-+again:
-+ val = ioread8(ICSR(pd));
++ 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;
+
-+ dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr);
++ 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;
+
-+ if ((val | pd->sr) & (ICSR_TACK | ICSR_AL)) {
-+ err = -EIO;
-+ break;
++ kfree(cq->resize_buf);
++ cq->resize_buf = NULL;
+ }
++ spin_unlock_irq(&cq->lock);
++ }
+
-+ /* the interrupt handler may wake us up before the
-+ * transfer is finished, so poll the hardware
-+ * until we're done.
-+ */
++ goto out;
+
-+ if (!(!(val & ICSR_BUSY) && (val & ICSR_SCLM) &&
-+ (val & ICSR_SDAM))) {
-+ msleep(1);
-+ if (retry_count--)
-+ goto again;
++err_buf:
++ if (!ibcq->uobject)
++ mlx4_ib_free_cq_buf(dev, &cq->resize_buf->buf,
++ cq->resize_buf->cqe);
+
-+ err = -EIO;
-+ dev_err(pd->dev, "Polling timed out\n");
-+ break;
-+ }
-+ }
++ kfree(cq->resize_buf);
++ cq->resize_buf = NULL;
+
-+ deactivate_ch(pd);
++ if (cq->resize_umem) {
++ ib_umem_release(cq->resize_umem);
++ cq->resize_umem = NULL;
++ }
+
-+ if (!err)
-+ err = num;
++out:
++ mutex_unlock(&cq->resize_mutex);
+ return err;
+}
+
-+static u32 sh_mobile_i2c_func(struct i2c_adapter *adapter)
+ int mlx4_ib_destroy_cq(struct ib_cq *cq)
+ {
+ struct mlx4_ib_dev *dev = to_mdev(cq->device);
+@@ -216,9 +434,8 @@ 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_db_free(dev, &mcq->db);
++ mlx4_ib_free_cq_buf(dev, &mcq->buf, cq->cqe + 1);
++ mlx4_db_free(dev->dev, &mcq->db);
+ }
+
+ kfree(mcq);
+@@ -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 I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
++ 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 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 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);
+
-+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;
++ mlx4_ib_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe);
++ cq->buf = cq->resize_buf->buf;
++ cq->ibcq.cqe = cq->resize_buf->cqe;
+
-+ 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;
++ kfree(cq->resize_buf);
++ cq->resize_buf = NULL;
+ }
-+ 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;
++ goto repoll;
+ }
+
-+ 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;
-+ }
+ 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/doorbell.c b/drivers/infiniband/hw/mlx4/doorbell.c
+index 1c36087..8aee423 100644
+--- a/drivers/infiniband/hw/mlx4/doorbell.c
++++ b/drivers/infiniband/hw/mlx4/doorbell.c
+@@ -34,124 +34,6 @@
+
+ #include "mlx4_ib.h"
+
+-struct mlx4_ib_db_pgdir {
+- struct list_head list;
+- DECLARE_BITMAP(order0, MLX4_IB_DB_PER_PAGE);
+- DECLARE_BITMAP(order1, MLX4_IB_DB_PER_PAGE / 2);
+- unsigned long *bits[2];
+- __be32 *db_page;
+- dma_addr_t db_dma;
+-};
+-
+-static struct mlx4_ib_db_pgdir *mlx4_ib_alloc_db_pgdir(struct mlx4_ib_dev *dev)
+-{
+- struct mlx4_ib_db_pgdir *pgdir;
+-
+- pgdir = kzalloc(sizeof *pgdir, GFP_KERNEL);
+- if (!pgdir)
+- return NULL;
+-
+- bitmap_fill(pgdir->order1, MLX4_IB_DB_PER_PAGE / 2);
+- pgdir->bits[0] = pgdir->order0;
+- pgdir->bits[1] = pgdir->order1;
+- pgdir->db_page = dma_alloc_coherent(dev->ib_dev.dma_device,
+- PAGE_SIZE, &pgdir->db_dma,
+- GFP_KERNEL);
+- if (!pgdir->db_page) {
+- kfree(pgdir);
+- return NULL;
+- }
+-
+- return pgdir;
+-}
+-
+-static int mlx4_ib_alloc_db_from_pgdir(struct mlx4_ib_db_pgdir *pgdir,
+- struct mlx4_ib_db *db, int order)
+-{
+- int o;
+- int i;
+-
+- for (o = order; o <= 1; ++o) {
+- i = find_first_bit(pgdir->bits[o], MLX4_IB_DB_PER_PAGE >> o);
+- if (i < MLX4_IB_DB_PER_PAGE >> o)
+- goto found;
+- }
+-
+- return -ENOMEM;
+-
+-found:
+- clear_bit(i, pgdir->bits[o]);
+-
+- i <<= o;
+-
+- if (o > order)
+- set_bit(i ^ 1, pgdir->bits[order]);
+-
+- db->u.pgdir = pgdir;
+- db->index = i;
+- db->db = pgdir->db_page + db->index;
+- db->dma = pgdir->db_dma + db->index * 4;
+- db->order = order;
+-
+- return 0;
+-}
+-
+-int mlx4_ib_db_alloc(struct mlx4_ib_dev *dev, struct mlx4_ib_db *db, int order)
+-{
+- struct mlx4_ib_db_pgdir *pgdir;
+- int ret = 0;
+-
+- mutex_lock(&dev->pgdir_mutex);
+-
+- list_for_each_entry(pgdir, &dev->pgdir_list, list)
+- if (!mlx4_ib_alloc_db_from_pgdir(pgdir, db, order))
+- goto out;
+-
+- pgdir = mlx4_ib_alloc_db_pgdir(dev);
+- if (!pgdir) {
+- ret = -ENOMEM;
+- goto out;
+- }
+-
+- list_add(&pgdir->list, &dev->pgdir_list);
+-
+- /* This should never fail -- we just allocated an empty page: */
+- WARN_ON(mlx4_ib_alloc_db_from_pgdir(pgdir, db, order));
+-
+-out:
+- mutex_unlock(&dev->pgdir_mutex);
+-
+- return ret;
+-}
+-
+-void mlx4_ib_db_free(struct mlx4_ib_dev *dev, struct mlx4_ib_db *db)
+-{
+- int o;
+- int i;
+-
+- mutex_lock(&dev->pgdir_mutex);
+-
+- o = db->order;
+- i = db->index;
+-
+- if (db->order == 0 && test_bit(i ^ 1, db->u.pgdir->order0)) {
+- clear_bit(i ^ 1, db->u.pgdir->order0);
+- ++o;
+- }
+-
+- i >>= o;
+- set_bit(i, db->u.pgdir->bits[o]);
+-
+- if (bitmap_full(db->u.pgdir->order1, MLX4_IB_DB_PER_PAGE / 2)) {
+- dma_free_coherent(dev->ib_dev.dma_device, PAGE_SIZE,
+- db->u.pgdir->db_page, db->u.pgdir->db_dma);
+- list_del(&db->u.pgdir->list);
+- kfree(db->u.pgdir);
+- }
+-
+- mutex_unlock(&dev->pgdir_mutex);
+-}
+-
+ struct mlx4_ib_user_db_page {
+ struct list_head list;
+ struct ib_umem *umem;
+@@ -160,7 +42,7 @@ struct mlx4_ib_user_db_page {
+ };
+
+ int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt,
+- struct mlx4_ib_db *db)
++ struct mlx4_db *db)
+ {
+ struct mlx4_ib_user_db_page *page;
+ struct ib_umem_chunk *chunk;
+@@ -181,7 +63,7 @@ int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt,
+ page->user_virt = (virt & PAGE_MASK);
+ page->refcnt = 0;
+ page->umem = ib_umem_get(&context->ibucontext, virt & PAGE_MASK,
+- PAGE_SIZE, 0);
++ PAGE_SIZE, 0, 0);
+ if (IS_ERR(page->umem)) {
+ err = PTR_ERR(page->umem);
+ kfree(page);
+@@ -202,7 +84,7 @@ out:
+ return err;
+ }
+
+-void mlx4_ib_db_unmap_user(struct mlx4_ib_ucontext *context, struct mlx4_ib_db *db)
++void mlx4_ib_db_unmap_user(struct mlx4_ib_ucontext *context, struct mlx4_db *db)
+ {
+ mutex_lock(&context->db_page_mutex);
+
+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..4d61e32 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)
+@@ -544,9 +557,6 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
+ goto err_uar;
+ MLX4_INIT_DOORBELL_LOCK(&ibdev->uar_lock);
+
+- INIT_LIST_HEAD(&ibdev->pgdir_list);
+- mutex_init(&ibdev->pgdir_mutex);
+-
+ ibdev->dev = dev;
+
+ strlcpy(ibdev->ib_dev.name, "mlx4_%d", IB_DEVICE_NAME_MAX);
+@@ -567,6 +577,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 +616,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 +646,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 +688,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;
+
-+ size = (res->end - res->start) + 1;
++ case MLX4_DEV_EVENT_PORT_DOWN:
++ ibev.event = IB_EVENT_PORT_ERR;
+ break;
+
+- case MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR:
++ 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..5cf9947 100644
+--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
++++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
+@@ -43,24 +43,6 @@
+ #include <linux/mlx4/device.h>
+ #include <linux/mlx4/doorbell.h>
+
+-enum {
+- MLX4_IB_DB_PER_PAGE = PAGE_SIZE / 4
+-};
+-
+-struct mlx4_ib_db_pgdir;
+-struct mlx4_ib_user_db_page;
+-
+-struct mlx4_ib_db {
+- __be32 *db;
+- union {
+- struct mlx4_ib_db_pgdir *pgdir;
+- struct mlx4_ib_user_db_page *user_page;
+- } u;
+- dma_addr_t dma;
+- int index;
+- int order;
+-};
+-
+ struct mlx4_ib_ucontext {
+ struct ib_ucontext ibucontext;
+ struct mlx4_uar uar;
+@@ -78,13 +60,21 @@ struct mlx4_ib_cq_buf {
+ struct mlx4_mtt mtt;
+ };
+
++struct mlx4_ib_cq_resize {
++ struct mlx4_ib_cq_buf buf;
++ int cqe;
++};
+
-+ pd->reg = ioremap(res->start, size);
-+ if (pd->reg == NULL) {
-+ dev_err(&dev->dev, "cannot map IO\n");
-+ ret = -ENXIO;
-+ goto err_irq;
-+ }
+ struct mlx4_ib_cq {
+ struct ib_cq ibcq;
+ struct mlx4_cq mcq;
+ struct mlx4_ib_cq_buf buf;
+- struct mlx4_ib_db db;
++ struct mlx4_ib_cq_resize *resize_buf;
++ struct mlx4_db db;
+ spinlock_t lock;
++ struct mutex resize_mutex;
+ struct ib_umem *umem;
++ struct ib_umem *resize_umem;
+ };
+
+ struct mlx4_ib_mr {
+@@ -110,12 +100,16 @@ struct mlx4_ib_wq {
+ unsigned tail;
+ };
+
++enum mlx4_ib_qp_flags {
++ MLX4_IB_QP_LSO = 1 << 0
++};
+
-+ /* setup the private data */
-+ adap = &pd->adap;
-+ i2c_set_adapdata(adap, pd);
+ struct mlx4_ib_qp {
+ struct ib_qp ibqp;
+ struct mlx4_qp mqp;
+ struct mlx4_buf buf;
+
+- struct mlx4_ib_db db;
++ struct mlx4_db db;
+ struct mlx4_ib_wq rq;
+
+ u32 doorbell_qpn;
+@@ -129,6 +123,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;
+@@ -141,7 +136,7 @@ struct mlx4_ib_srq {
+ struct ib_srq ibsrq;
+ struct mlx4_srq msrq;
+ struct mlx4_buf buf;
+- struct mlx4_ib_db db;
++ struct mlx4_db db;
+ u64 *wrid;
+ spinlock_t lock;
+ int head;
+@@ -162,9 +157,6 @@ struct mlx4_ib_dev {
+ struct mlx4_dev *dev;
+ void __iomem *uar_map;
+
+- struct list_head pgdir_list;
+- struct mutex pgdir_mutex;
+-
+ struct mlx4_uar priv_uar;
+ u32 priv_pdn;
+ MLX4_DECLARE_DOORBELL_LOCK(uar_lock);
+@@ -235,11 +227,9 @@ static inline struct mlx4_ib_ah *to_mah(struct ib_ah *ibah)
+ return container_of(ibah, struct mlx4_ib_ah, ibah);
+ }
+
+-int mlx4_ib_db_alloc(struct mlx4_ib_dev *dev, struct mlx4_ib_db *db, int order);
+-void mlx4_ib_db_free(struct mlx4_ib_dev *dev, struct mlx4_ib_db *db);
+ int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt,
+- struct mlx4_ib_db *db);
+-void mlx4_ib_db_unmap_user(struct mlx4_ib_ucontext *context, struct mlx4_ib_db *db);
++ struct mlx4_db *db);
++void mlx4_ib_db_unmap_user(struct mlx4_ib_ucontext *context, struct mlx4_db *db);
+
+ struct ib_mr *mlx4_ib_get_dma_mr(struct ib_pd *pd, int acc);
+ int mlx4_ib_umem_write_mtt(struct mlx4_ib_dev *dev, struct mlx4_mtt *mtt,
+@@ -249,6 +239,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/mr.c b/drivers/infiniband/hw/mlx4/mr.c
+index fe2c2e9..68e9248 100644
+--- a/drivers/infiniband/hw/mlx4/mr.c
++++ b/drivers/infiniband/hw/mlx4/mr.c
+@@ -132,7 +132,8 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+ if (!mr)
+ return ERR_PTR(-ENOMEM);
+
+- mr->umem = ib_umem_get(pd->uobject->context, start, length, access_flags);
++ mr->umem = ib_umem_get(pd->uobject->context, start, length,
++ access_flags, 0);
+ if (IS_ERR(mr->umem)) {
+ err = PTR_ERR(mr->umem);
+ goto err_free;
+diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
+index 958e205..8e02ecf 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);
+@@ -479,7 +482,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
+ goto err;
+
+ qp->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr,
+- qp->buf_size, 0);
++ qp->buf_size, 0, 0);
+ if (IS_ERR(qp->umem)) {
+ err = PTR_ERR(qp->umem);
+ goto err;
+@@ -503,12 +506,15 @@ 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;
+
-+ adap->owner = THIS_MODULE;
-+ adap->algo = &sh_mobile_i2c_algorithm;
-+ adap->dev.parent = &dev->dev;
-+ adap->retries = 5;
-+ adap->nr = dev->id;
+ err = set_kernel_sq_size(dev, &init_attr->cap, init_attr->qp_type, qp);
+ if (err)
+ goto err;
+
+ if (!init_attr->srq) {
+- err = mlx4_ib_db_alloc(dev, &qp->db, 0);
++ err = mlx4_db_alloc(dev->dev, &qp->db, 0);
+ if (err)
+ goto err;
+
+@@ -574,7 +580,7 @@ err_buf:
+
+ err_db:
+ if (!pd->uobject && !init_attr->srq)
+- mlx4_ib_db_free(dev, &qp->db);
++ mlx4_db_free(dev->dev, &qp->db);
+
+ err:
+ return err;
+@@ -660,7 +666,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
+ kfree(qp->rq.wrid);
+ mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
+ if (!qp->ibqp.srq)
+- mlx4_ib_db_free(dev, &qp->db);
++ mlx4_db_free(dev->dev, &qp->db);
+ }
+ }
+
+@@ -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);
+
-+ strlcpy(adap->name, dev->name, sizeof(adap->name));
+ 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);
+
-+ sh_mobile_i2c_setup_channel(dev);
++ /*
++ * This is a temporary limitation and will be removed in
++ * a forthcoming FW release:
++ */
++ if (unlikely(halign > 64))
++ return -EINVAL;
+
-+ ret = i2c_add_numbered_adapter(adap);
-+ if (ret < 0) {
-+ dev_err(&dev->dev, "cannot add numbered adapter\n");
-+ goto err_all;
-+ }
++ if (unlikely(!(qp->flags & MLX4_IB_QP_LSO) &&
++ wr->num_sge > qp->sq.max_gs - (halign >> 4)))
++ return -EINVAL;
+
-+ return 0;
++ memcpy(wqe->header, wr->wr.ud.header, wr->wr.ud.hlen);
+
-+ 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;
-+}
++ /* make sure LSO header is written before overwriting stamping */
++ wmb();
+
-+static int sh_mobile_i2c_remove(struct platform_device *dev)
-+{
-+ struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
++ wqe->mss_hdr_size = cpu_to_be32((wr->wr.ud.mss - wr->wr.ud.hlen) << 16 |
++ wr->wr.ud.hlen);
+
-+ i2c_del_adapter(&pd->adap);
-+ iounmap(pd->reg);
-+ sh_mobile_i2c_hook_irqs(dev, 0);
-+ clk_put(pd->clk);
-+ kfree(pd);
++ *lso_seg_len = halign;
+ 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);
-+}
+ 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;
+
-+module_init(sh_mobile_i2c_adap_init);
-+module_exit(sh_mobile_i2c_adap_exit);
++ 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;
+
-+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)
++ mutex_lock(&qp->mutex);
- /* device driver */
+ 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
+ }
-+/* work with hotplug and coldplug */
-+MODULE_ALIAS("platform:simtec-i2c");
+ 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/mlx4/srq.c b/drivers/infiniband/hw/mlx4/srq.c
+index beaa3b0..12d6bc6 100644
+--- a/drivers/infiniband/hw/mlx4/srq.c
++++ b/drivers/infiniband/hw/mlx4/srq.c
+@@ -109,7 +109,7 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
+ }
+
+ srq->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr,
+- buf_size, 0);
++ buf_size, 0, 0);
+ if (IS_ERR(srq->umem)) {
+ err = PTR_ERR(srq->umem);
+ goto err_srq;
+@@ -129,7 +129,7 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
+ if (err)
+ goto err_mtt;
+ } else {
+- err = mlx4_ib_db_alloc(dev, &srq->db, 0);
++ err = mlx4_db_alloc(dev->dev, &srq->db, 0);
+ if (err)
+ goto err_srq;
+
+@@ -200,7 +200,7 @@ err_buf:
+
+ err_db:
+ if (!pd->uobject)
+- mlx4_ib_db_free(dev, &srq->db);
++ mlx4_db_free(dev->dev, &srq->db);
+
+ err_srq:
+ kfree(srq);
+@@ -267,7 +267,7 @@ int mlx4_ib_destroy_srq(struct ib_srq *srq)
+ kfree(msrq->wrid);
+ mlx4_buf_free(dev->dev, msrq->msrq.max << msrq->msrq.wqe_shift,
+ &msrq->buf);
+- mlx4_ib_db_free(dev, &msrq->db);
++ mlx4_db_free(dev->dev, &msrq->db);
+ }
+
+ kfree(msrq);
+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);
+
- 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);
+ /* We leave wqe_quota, responder_exu, etc as 0 (default) */
- 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;
+ /* QPC/EEC/CQC/EQC/RDB attributes */
+diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h
+index 2f976f2..8928ca4 100644
+--- a/drivers/infiniband/hw/mthca/mthca_cmd.h
++++ b/drivers/infiniband/hw/mthca/mthca_cmd.h
+@@ -103,6 +103,7 @@ enum {
+ DEV_LIM_FLAG_RAW_IPV6 = 1 << 4,
+ DEV_LIM_FLAG_RAW_ETHER = 1 << 5,
+ DEV_LIM_FLAG_SRQ = 1 << 6,
++ DEV_LIM_FLAG_IPOIB_CSUM = 1 << 7,
+ DEV_LIM_FLAG_BAD_PKEY_CNTR = 1 << 8,
+ DEV_LIM_FLAG_BAD_QKEY_CNTR = 1 << 9,
+ DEV_LIM_FLAG_MW = 1 << 16,
+diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
+index 1e1e336..20401d2 100644
+--- a/drivers/infiniband/hw/mthca/mthca_cq.c
++++ b/drivers/infiniband/hw/mthca/mthca_cq.c
+@@ -119,7 +119,8 @@ struct mthca_cqe {
+ __be32 my_qpn;
+ __be32 my_ee;
+ __be32 rqpn;
+- __be16 sl_g_mlpath;
++ u8 sl_ipok;
++ u8 g_mlpath;
+ __be16 rlid;
+ __be32 imm_etype_pkey_eec;
+ __be32 byte_cnt;
+@@ -493,6 +494,7 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
+ int is_send;
+ int free_cqe = 1;
+ int err = 0;
++ u16 checksum;
+
+ cqe = next_cqe_sw(cq);
+ if (!cqe)
+@@ -635,12 +637,14 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
+ break;
+ }
+ entry->slid = be16_to_cpu(cqe->rlid);
+- entry->sl = be16_to_cpu(cqe->sl_g_mlpath) >> 12;
++ entry->sl = cqe->sl_ipok >> 4;
+ entry->src_qp = be32_to_cpu(cqe->rqpn) & 0xffffff;
+- entry->dlid_path_bits = be16_to_cpu(cqe->sl_g_mlpath) & 0x7f;
++ entry->dlid_path_bits = cqe->g_mlpath & 0x7f;
+ entry->pkey_index = be32_to_cpu(cqe->imm_etype_pkey_eec) >> 16;
+- entry->wc_flags |= be16_to_cpu(cqe->sl_g_mlpath) & 0x80 ?
+- IB_WC_GRH : 0;
++ entry->wc_flags |= cqe->g_mlpath & 0x80 ? IB_WC_GRH : 0;
++ checksum = (be32_to_cpu(cqe->rqpn) >> 24) |
++ ((be32_to_cpu(cqe->my_ee) >> 16) & 0xff00);
++ entry->csum_ok = (cqe->sl_ipok & 1 && checksum == 0xffff);
+ }
+
+ entry->status = IB_WC_SUCCESS;
+diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
+index 7bbdd1f..7bc32f8 100644
+--- a/drivers/infiniband/hw/mthca/mthca_dev.h
++++ b/drivers/infiniband/hw/mthca/mthca_dev.h
+@@ -46,16 +46,15 @@
+ #include <linux/timer.h>
+ #include <linux/mutex.h>
+ #include <linux/list.h>
+-
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
-- 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
+ #include "mthca_provider.h"
+ #include "mthca_doorbell.h"
- 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;
- }
+ #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"
-- check_state(isp, __FUNCTION__);
-+ check_state(isp, __func__);
- dump_regs(isp, "otg->isp1301");
- }
+ 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)
-@@ -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);
- }
+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;
+ }
-- check_state(isp, __FUNCTION__);
-+ check_state(isp, __func__);
- return ret;
+-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;
-@@ -837,7 +837,7 @@ static int otg_init(struct isp1301 *isp)
- if (!otg_dev)
- return -ENODEV;
+- 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;
-- 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));
++ 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;
+ }
-- 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);
+ 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;
- 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
+- 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;
++ }
- 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);
+ 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;
-- dump_regs(isp, __FUNCTION__);
-+ dump_regs(isp, __func__);
+@@ -653,7 +660,7 @@ static int mthca_init_arbel(struct mthca_dev *mdev)
+ profile.num_srq = dev_lim.max_srqs;
- return 0;
+ 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;
-@@ -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__);
+- 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);
- /* 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)
+ 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);
+ }
- 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
+diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
+index 3538da1..820205d 100644
+--- a/drivers/infiniband/hw/mthca/mthca_mr.c
++++ b/drivers/infiniband/hw/mthca/mthca_mr.c
+@@ -818,15 +818,9 @@ int mthca_arbel_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list,
-- dump_regs(isp, __FUNCTION__);
-+ dump_regs(isp, __func__);
+ void mthca_tavor_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr)
+ {
+- u32 key;
+-
+ if (!fmr->maps)
+ return;
- #ifdef VERBOSE
- mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
-diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
-index 4154a91..b67f69c 100644
---- a/drivers/i2c/chips/tps65010.c
-+++ b/drivers/i2c/chips/tps65010.c
-@@ -30,9 +30,13 @@
- #include <linux/debugfs.h>
- #include <linux/seq_file.h>
- #include <linux/mutex.h>
-+#include <linux/platform_device.h>
+- key = tavor_key_to_hw_index(fmr->ibmr.lkey);
+- key &= dev->limits.num_mpts - 1;
+- fmr->ibmr.lkey = fmr->ibmr.rkey = tavor_hw_index_to_key(key);
+-
+ fmr->maps = 0;
- #include <linux/i2c/tps65010.h>
+ writeb(MTHCA_MPT_STATUS_SW, fmr->mem.tavor.mpt);
+@@ -834,16 +828,9 @@ void mthca_tavor_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr)
-+#include <asm/gpio.h>
-+
-+
- /*-------------------------------------------------------------------------*/
+ void mthca_arbel_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr)
+ {
+- u32 key;
+-
+ if (!fmr->maps)
+ return;
- #define DRIVER_VERSION "2 May 2005"
-@@ -84,7 +88,9 @@ struct tps65010 {
- u8 chgstatus, regstatus, chgconf;
- u8 nmask1, nmask2;
+- key = arbel_key_to_hw_index(fmr->ibmr.lkey);
+- key &= dev->limits.num_mpts - 1;
+- key = adjust_key(dev, key);
+- fmr->ibmr.lkey = fmr->ibmr.rkey = arbel_hw_index_to_key(key);
+-
+ fmr->maps = 0;
-- /* not currently tracking GPIO state */
-+ u8 outmask;
-+ struct gpio_chip chip;
-+ struct platform_device *leds;
+ *(u8 *) fmr->mem.arbel.mpt = MTHCA_MPT_STATUS_SW;
+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
};
- #define POWER_POLL_DELAY msecs_to_jiffies(5000)
-@@ -449,12 +455,72 @@ static irqreturn_t tps65010_irq(int irq, void *_tps)
+-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;
+ };
-+/* 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;
-+}
-+
-+
-+/*-------------------------------------------------------------------------*/
+-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..be34f99 100644
+--- a/drivers/infiniband/hw/mthca/mthca_provider.c
++++ b/drivers/infiniband/hw/mthca/mthca_provider.c
+@@ -39,6 +39,8 @@
+ #include <rdma/ib_smi.h>
+ #include <rdma/ib_umem.h>
+ #include <rdma/ib_user_verbs.h>
+
- static struct tps65010 *the_tps;
++#include <linux/sched.h>
+ #include <linux/mm.h>
- static int __exit tps65010_remove(struct i2c_client *client)
- {
- struct tps65010 *tps = i2c_get_clientdata(client);
-+ struct tps65010_board *board = client->dev.platform_data;
+ #include "mthca_dev.h"
+@@ -60,7 +62,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);
-+ 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;
+ u8 status;
- 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)
+@@ -367,6 +369,8 @@ static struct ib_ucontext *mthca_alloc_ucontext(struct ib_device *ibdev,
+ return ERR_PTR(-EFAULT);
+ }
- 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;
++ context->reg_mr_warned = 0;
+
-+ /* NOTE: only partial support for inputs; nyet IRQs */
-+ tps->chip.get = tps65010_gpio_get;
+ return &context->ibucontext;
+ }
+
+@@ -540,6 +544,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);
+
-+ tps->chip.base = board->base;
-+ tps->chip.ngpio = 6;
-+ tps->chip.can_sleep = 1;
+ switch (init_attr->qp_type) {
+ case IB_QPT_RC:
+ case IB_QPT_UC:
+@@ -1003,17 +1010,31 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+ struct mthca_dev *dev = to_mdev(pd->device);
+ struct ib_umem_chunk *chunk;
+ struct mthca_mr *mr;
++ struct mthca_reg_mr ucmd;
+ u64 *pages;
+ int shift, n, len;
+ int i, j, k;
+ int err = 0;
+ int write_mtt_size;
+
++ if (udata->inlen - sizeof (struct ib_uverbs_cmd_hdr) < sizeof ucmd) {
++ if (!to_mucontext(pd->uobject->context)->reg_mr_warned) {
++ mthca_warn(dev, "Process '%s' did not pass in MR attrs.\n",
++ current->comm);
++ mthca_warn(dev, " Update libmthca to fix this.\n");
++ }
++ ++to_mucontext(pd->uobject->context)->reg_mr_warned;
++ ucmd.mr_attrs = 0;
++ } else if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
++ return ERR_PTR(-EFAULT);
+
-+ 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;
-+ }
-+ }
-+ }
+ mr = kmalloc(sizeof *mr, GFP_KERNEL);
+ if (!mr)
+ return ERR_PTR(-ENOMEM);
+
+- mr->umem = ib_umem_get(pd->uobject->context, start, length, acc);
++ mr->umem = ib_umem_get(pd->uobject->context, start, length, acc,
++ ucmd.mr_attrs & MTHCA_MR_DMASYNC);
+
+ if (IS_ERR(mr->umem)) {
+ err = PTR_ERR(mr->umem);
+ goto err;
+@@ -1167,23 +1188,29 @@ static int mthca_unmap_fmr(struct list_head *fmr_list)
return 0;
- fail1:
- kfree(tps);
-diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
-index 8b645c6..6c7fa8d 100644
---- a/drivers/i2c/i2c-core.c
-+++ b/drivers/i2c/i2c-core.c
-@@ -35,8 +35,8 @@
- #include <linux/completion.h>
- #include <linux/hardirq.h>
- #include <linux/irqflags.h>
-+#include <linux/semaphore.h>
- #include <asm/uaccess.h>
--#include <asm/semaphore.h>
+ }
- #include "i2c-core.h"
+-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);
+ }
-@@ -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 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 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)
+-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 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;
+- 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 +1226,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 +1405,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_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h
+index 262616c..934bf95 100644
+--- a/drivers/infiniband/hw/mthca/mthca_provider.h
++++ b/drivers/infiniband/hw/mthca/mthca_provider.h
+@@ -67,6 +67,7 @@ struct mthca_ucontext {
+ struct ib_ucontext ibucontext;
+ struct mthca_uar uar;
+ struct mthca_user_db_table *db_tab;
++ int reg_mr_warned;
+ };
+
+ struct mthca_mtt;
+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 (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;
+ 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);
+
-+ /* Note that command values are always valid! */
++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_user.h b/drivers/infiniband/hw/mthca/mthca_user.h
+index 02cc0a7..e1262c9 100644
+--- a/drivers/infiniband/hw/mthca/mthca_user.h
++++ b/drivers/infiniband/hw/mthca/mthca_user.h
+@@ -61,6 +61,16 @@ struct mthca_alloc_pd_resp {
+ __u32 reserved;
+ };
+
++struct mthca_reg_mr {
++/*
++ * Mark the memory region with a DMA attribute that causes
++ * in-flight DMA to be flushed when the region is written to:
++ */
++#define MTHCA_MR_DMASYNC 0x1
++ __u32 mr_attrs;
++ __u32 reserved;
++};
+
-+ 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);
+ struct mthca_create_cq {
+ __u32 lkey;
+ __u32 pdn;
+diff --git a/drivers/infiniband/hw/mthca/mthca_wqe.h b/drivers/infiniband/hw/mthca/mthca_wqe.h
+index f6a66fe..b3551a8 100644
+--- a/drivers/infiniband/hw/mthca/mthca_wqe.h
++++ b/drivers/infiniband/hw/mthca/mthca_wqe.h
+@@ -38,14 +38,16 @@
+ #include <linux/types.h>
+
+ enum {
+- MTHCA_NEXT_DBD = 1 << 7,
+- MTHCA_NEXT_FENCE = 1 << 6,
+- MTHCA_NEXT_CQ_UPDATE = 1 << 3,
+- MTHCA_NEXT_EVENT_GEN = 1 << 2,
+- MTHCA_NEXT_SOLICIT = 1 << 1,
+-
+- MTHCA_MLX_VL15 = 1 << 17,
+- MTHCA_MLX_SLR = 1 << 16
++ MTHCA_NEXT_DBD = 1 << 7,
++ MTHCA_NEXT_FENCE = 1 << 6,
++ MTHCA_NEXT_CQ_UPDATE = 1 << 3,
++ MTHCA_NEXT_EVENT_GEN = 1 << 2,
++ MTHCA_NEXT_SOLICIT = 1 << 1,
++ MTHCA_NEXT_IP_CSUM = 1 << 4,
++ MTHCA_NEXT_TCP_UDP_CSUM = 1 << 5,
+
-+ if (data_arg.data == NULL) {
-+ dev_dbg(&client->adapter->dev,
-+ "data is NULL pointer in ioctl I2C_SMBUS.\n");
-+ return -EINVAL;
-+ }
++ MTHCA_MLX_VL15 = 1 << 17,
++ MTHCA_MLX_SLR = 1 << 16
+ };
+
+ enum {
+diff --git a/drivers/infiniband/hw/nes/Kconfig b/drivers/infiniband/hw/nes/Kconfig
+index 2aeb7ac..d449eb6 100644
+--- a/drivers/infiniband/hw/nes/Kconfig
++++ b/drivers/infiniband/hw/nes/Kconfig
+@@ -2,6 +2,7 @@ config INFINIBAND_NES
+ tristate "NetEffect RNIC Driver"
+ depends on PCI && INET && INFINIBAND
+ select LIBCRC32C
++ select INET_LRO
+ ---help---
+ This is a low-level driver for NetEffect RDMA enabled
+ Network Interface Cards (RNIC).
+diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
+index b2112f5..9f7364a 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;
+
+
+@@ -92,23 +91,15 @@ unsigned int nes_debug_level = 0;
+ module_param_named(debug_level, nes_debug_level, uint, 0644);
+ MODULE_PARM_DESC(debug_level, "Enable debug output level");
+
++unsigned int nes_lro_max_aggr = NES_LRO_MAX_AGGR;
++module_param(nes_lro_max_aggr, int, NES_LRO_MAX_AGGR);
++MODULE_PARM_DESC(nes_mro_max_aggr, " nic LRO MAX packet aggregation");
+
-+ 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);
+ 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);
+
-+ 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 unsigned int ee_flsh_adapter;
+ static unsigned int sysfs_nonidx_addr;
+ static unsigned int sysfs_idx_addr;
+@@ -152,8 +143,9 @@ static int nes_inetaddr_event(struct notifier_block *notifier,
+
+ addr = ntohl(ifa->ifa_address);
+ mask = ntohl(ifa->ifa_mask);
+- nes_debug(NES_DBG_NETDEV, "nes_inetaddr_event: ip address %08X, netmask %08X.\n",
+- addr, mask);
++ nes_debug(NES_DBG_NETDEV, "nes_inetaddr_event: ip address " NIPQUAD_FMT
++ ", netmask " NIPQUAD_FMT ".\n",
++ HIPQUAD(addr), HIPQUAD(mask));
+ list_for_each_entry(nesdev, &nes_dev_list, list) {
+ nes_debug(NES_DBG_NETDEV, "Nesdev list entry = 0x%p. (%s)\n",
+ nesdev, nesdev->netdev[0]->name);
+@@ -310,7 +302,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();
+ }
+
+@@ -366,13 +358,11 @@ struct ib_qp *nes_get_qp(struct ib_device *device, int qpn)
+ */
+ static void nes_print_macaddr(struct net_device *netdev)
+ {
+- nes_debug(NES_DBG_INIT, "%s: MAC %02X:%02X:%02X:%02X:%02X:%02X, IRQ %u\n",
+- netdev->name,
+- netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
+- netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5],
+- netdev->irq);
+-}
++ DECLARE_MAC_BUF(mac);
+
++ nes_debug(NES_DBG_INIT, "%s: %s, IRQ %u\n",
++ netdev->name, print_mac(mac, netdev->dev_addr), netdev->irq);
+}
+
+ /**
+ * nes_interrupt - handle interrupts
+@@ -751,13 +741,13 @@ static void __devexit nes_remove(struct pci_dev *pcidev)
+
+ list_del(&nesdev->list);
+ nes_destroy_cqp(nesdev);
+
-+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;
++ free_irq(pcidev->irq, nesdev);
+ tasklet_kill(&nesdev->dpc_tasklet);
- 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);
+ /* Deallocate the Adapter Structure */
+ nes_destroy_adapter(nesdev->nesadapter);
- case I2C_RDWR:
-- if (copy_from_user(&rdwr_arg,
-- (struct i2c_rdwr_ioctl_data __user *)arg,
-- sizeof(rdwr_arg)))
-- return -EFAULT;
--
-- /* Put an arbitrary limit on the number of messages that can
-- * be sent at once */
-- if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
-- return -EINVAL;
--
-- rdwr_pa = (struct i2c_msg *)
-- kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
-- GFP_KERNEL);
--
-- if (rdwr_pa == NULL) return -ENOMEM;
--
-- if (copy_from_user(rdwr_pa, rdwr_arg.msgs,
-- rdwr_arg.nmsgs * sizeof(struct i2c_msg))) {
-- kfree(rdwr_pa);
-- return -EFAULT;
-- }
--
-- data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
-- if (data_ptrs == NULL) {
-- kfree(rdwr_pa);
-- return -ENOMEM;
-- }
--
-- res = 0;
-- for( i=0; i<rdwr_arg.nmsgs; i++ ) {
-- /* Limit the size of the message to a sane amount;
-- * and don't let length change either. */
-- if ((rdwr_pa[i].len > 8192) ||
-- (rdwr_pa[i].flags & I2C_M_RECV_LEN)) {
-- res = -EINVAL;
-- break;
-- }
-- data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf;
-- rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL);
-- if(rdwr_pa[i].buf == NULL) {
-- res = -ENOMEM;
-- break;
-- }
-- if(copy_from_user(rdwr_pa[i].buf,
-- data_ptrs[i],
-- rdwr_pa[i].len)) {
-- ++i; /* Needs to be kfreed too */
-- res = -EFAULT;
-- break;
-- }
-- }
-- if (res < 0) {
-- int j;
-- for (j = 0; j < i; ++j)
-- kfree(rdwr_pa[j].buf);
-- kfree(data_ptrs);
-- kfree(rdwr_pa);
-- return res;
-- }
+- free_irq(pcidev->irq, nesdev);
-
-- 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);
+ 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..1f9f7bf 100644
+--- a/drivers/infiniband/hw/nes/nes.h
++++ b/drivers/infiniband/hw/nes/nes.h
+@@ -43,7 +43,6 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/workqueue.h>
+ #include <linux/slab.h>
+-#include <asm/semaphore.h>
+ #include <linux/version.h>
+ #include <asm/io.h>
+ #include <linux/crc32c.h>
+@@ -143,12 +142,12 @@
+ #ifdef CONFIG_INFINIBAND_NES_DEBUG
+ #define nes_debug(level, fmt, args...) \
+ if (level & nes_debug_level) \
+- printk(KERN_ERR PFX "%s[%u]: " fmt, __FUNCTION__, __LINE__, ##args)
++ printk(KERN_ERR PFX "%s[%u]: " fmt, __func__, __LINE__, ##args)
- 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;
-- }
+ #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;
+@@ -175,11 +173,9 @@ extern int disable_mpa_crc;
+ extern unsigned int send_first;
+ extern unsigned int nes_drv_opt;
+ extern unsigned int nes_debug_level;
++extern unsigned int nes_lro_max_aggr;
+
+ extern struct list_head nes_adapter_list;
+-extern struct list_head nes_dev_list;
-
-- /* Note that command values are always valid! */
+-extern struct nes_cm_core *g_cm_core;
+
+ extern atomic_t cm_connects;
+ extern atomic_t cm_accepts;
+@@ -209,7 +205,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 +214,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;
-
-- 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);
+ struct nes_device {
+ struct nes_adapter *nesadapter;
+ void __iomem *regs;
+@@ -412,7 +399,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 +497,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 +504,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 *);
-- 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);
+ /* 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 +520,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,14 +531,13 @@ 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 *);
+ void nes_write_1G_phy_reg(struct nes_device *, u8, u8, u16);
+ void nes_read_1G_phy_reg(struct nes_device *, u8, u8, u16 *);
+-void nes_write_10G_phy_reg(struct nes_device *, u16, u8, u16);
+-void nes_read_10G_phy_reg(struct nes_device *, u16, u8);
++void nes_write_10G_phy_reg(struct nes_device *, u16, u8, u16, u16);
++void nes_read_10G_phy_reg(struct nes_device *, u8, u8, u16);
+ struct nes_cqp_request *nes_get_cqp_request(struct nes_device *);
+ void nes_post_cqp_request(struct nes_device *, struct nes_cqp_request *, int);
+ int nes_arp_table(struct nes_device *, u32, u8 *, u32);
+diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
+index 0bef878..9a4b40f 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 *);
-
-- 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
++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);
- If unsure, say N.
+ /* 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
+ };
--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"
+-struct nes_cm_core *g_cm_core;
++static struct nes_cm_core *g_cm_core;
- config IDE_GENERIC
- tristate "generic/default IDE chipset support"
-+ depends on ALPHA || X86 || IA64 || M32R || MIPS || PPC32
- help
- If unsure, say N.
+ 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));
-@@ -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.
+ nes_debug(NES_DBG_CM, "State : %u \n", core->state);
-- 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.
+@@ -395,7 +418,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
+ }
-@@ -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.
+ 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);
- 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
+ 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;
+@@ -571,7 +594,7 @@ void nes_cm_timer_tick(unsigned long pass)
+ continue;
+ }
+ /* this seems like the correct place, but leave send entry unprotected */
+- // spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
++ /* spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); */
+ atomic_inc(&send_entry->skb->users);
+ cm_packets_retrans++;
+ nes_debug(NES_DBG_CM, "Retransmitting send_entry %p for node %p,"
+@@ -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;
- # no isa -> no vlb
--if ISA
-+if ISA && (ALPHA || X86 || MIPS)
+@@ -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;
- comment "Other IDE chipsets support"
- comment "Note: most of these also require special kernel boot parameters"
+@@ -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;
- 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.
+@@ -830,13 +852,12 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
+ /* get a handle on the hte */
+ hte = &cm_core->connected_nodes;
+
+- nes_debug(NES_DBG_CM, "Searching for an owner node:%x:%x from core %p->%p\n",
+- loc_addr, loc_port, cm_core, hte);
++ nes_debug(NES_DBG_CM, "Searching for an owner node: " NIPQUAD_FMT ":%x from core %p->%p\n",
++ HIPQUAD(loc_addr), loc_port, cm_core, hte);
- 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
+ /* 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;
--config IDE_ARCH_OBSOLETE_INIT
-- def_bool ALPHA || (ARM && !ARCH_L7200) || BLACKFIN || X86 || IA64 || M32R || MIPS || PARISC || PPC || (SUPERH64 && BLK_DEV_IDEPCI) || SPARC
--
- endif
+ /* 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) &&
+@@ -883,8 +902,8 @@ static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
+ }
+ spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
- 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.
+- nes_debug(NES_DBG_CM, "Unable to find listener- %x:%x\n",
+- dst_addr, dst_port);
++ nes_debug(NES_DBG_CM, "Unable to find listener for " NIPQUAD_FMT ":%x\n",
++ HIPQUAD(dst_addr), dst_port);
-+ If you want to use this driver together with the new one you have
-+ to use "hda=noprobe hdb=noprobe" kernel parameters to prevent the new
-+ driver from probing the primary interface.
-+
- If you are unsure, then just choose the Enhanced IDE/MFM/RLL driver
- instead of this one. For more detailed information, read the
- Disk-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
+ /* no listener */
+ return NULL;
+@@ -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;
+ }
- config BLK_DEV_HD
-- def_bool BLK_DEV_HD_IDE || BLK_DEV_HD_ONLY
-+ def_bool BLK_DEV_HD_ONLY
+@@ -1035,6 +1054,7 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
+ int arpindex = 0;
+ struct nes_device *nesdev;
+ struct nes_adapter *nesadapter;
++ DECLARE_MAC_BUF(mac);
- 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
+ /* create an hte and cm_node for this instance */
+ cm_node = kzalloc(sizeof(*cm_node), GFP_ATOMIC);
+@@ -1047,8 +1067,9 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
+ cm_node->loc_port = cm_info->loc_port;
+ cm_node->rem_port = cm_info->rem_port;
+ cm_node->send_write0 = send_first;
+- nes_debug(NES_DBG_CM, "Make node addresses : loc = %x:%x, rem = %x:%x\n",
+- cm_node->loc_addr, cm_node->loc_port, cm_node->rem_addr, cm_node->rem_port);
++ nes_debug(NES_DBG_CM, "Make node addresses : loc = " NIPQUAD_FMT ":%x, rem = " NIPQUAD_FMT ":%x\n",
++ HIPQUAD(cm_node->loc_addr), cm_node->loc_port,
++ HIPQUAD(cm_node->rem_addr), cm_node->rem_port);
+ cm_node->listener = listener;
+ cm_node->netdev = nesvnic->netdev;
+ cm_node->cm_id = cm_info->cm_id;
+@@ -1077,8 +1098,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;
+@@ -1099,11 +1118,8 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
- 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
+ /* copy the mac addr to node context */
+ memcpy(cm_node->rem_mac, nesadapter->arp_table[arpindex].mac_addr, ETH_ALEN);
+- nes_debug(NES_DBG_CM, "Remote mac addr from arp table:%02x,"
+- " %02x, %02x, %02x, %02x, %02x\n",
+- cm_node->rem_mac[0], cm_node->rem_mac[1],
+- cm_node->rem_mac[2], cm_node->rem_mac[3],
+- cm_node->rem_mac[4], cm_node->rem_mac[5]);
++ nes_debug(NES_DBG_CM, "Remote mac addr from arp table: %s\n",
++ print_mac(mac, cm_node->rem_mac));
+
+ add_hte_node(cm_core, cm_node);
+ atomic_inc(&cm_nodes_created);
+@@ -1239,7 +1255,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 +1288,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;
+@@ -1319,7 +1335,7 @@ int process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
+ cm_node->loc_addr, cm_node->loc_port,
+ cm_node->rem_addr, cm_node->rem_port,
+ cm_node->state, atomic_read(&cm_node->ref_count));
+- // create event
++ /* create event */
+ cm_node->state = NES_CM_STATE_CLOSED;
- ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o
+ create_event(cm_node, NES_CM_EVENT_ABORTED);
+@@ -1360,7 +1376,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 +1621,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);
-diff --git a/drivers/ide/arm/bast-ide.c b/drivers/ide/arm/bast-ide.c
-index 161d30c..a80b957 100644
---- a/drivers/ide/arm/bast-ide.c
-+++ b/drivers/ide/arm/bast-ide.c
-@@ -21,6 +21,8 @@
- #include <asm/arch/bast-map.h>
- #include <asm/arch/bast-irq.h>
+- 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 +1645,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;
+@@ -1654,7 +1669,7 @@ struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
+ if (!cm_node)
+ return NULL;
-+#define DRV_NAME "bast-ide"
-+
- static int __init bastide_register(unsigned int base, unsigned int aux, int irq)
+- // set our node side to client (active) side
++ /* set our node side to client (active) side */
+ cm_node->tcp_cntxt.client = 1;
+ cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE;
+
+@@ -1679,7 +1694,7 @@ struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
+ loopbackremotenode->mpa_frame_size = mpa_frame_size -
+ sizeof(struct ietf_mpa_frame);
+
+- // we are done handling this state, set node to a TSA state
++ /* we are done handling this state, set node to a TSA state */
+ cm_node->state = NES_CM_STATE_TSA;
+ cm_node->tcp_cntxt.rcv_nxt = loopbackremotenode->tcp_cntxt.loc_seq_num;
+ loopbackremotenode->tcp_cntxt.rcv_nxt = cm_node->tcp_cntxt.loc_seq_num;
+@@ -1717,8 +1732,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)
{
- 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;
+ return 0;
+ }
+@@ -1727,9 +1742,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 +1776,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;
-- hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
-+ hwif = ide_find_port();
- if (hwif == NULL)
- goto out;
+@@ -1808,8 +1823,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;
+@@ -1834,8 +1849,10 @@ int mini_cm_recv_pkt(struct nes_cm_core *cm_core, struct nes_vnic *nesvnic,
+ nfo.rem_addr = ntohl(iph->saddr);
+ nfo.rem_port = ntohs(tcph->source);
+
+- nes_debug(NES_DBG_CM, "Received packet: dest=0x%08X:0x%04X src=0x%08X:0x%04X\n",
+- iph->daddr, tcph->dest, iph->saddr, tcph->source);
++ nes_debug(NES_DBG_CM, "Received packet: dest=" NIPQUAD_FMT
++ ":0x%04X src=" NIPQUAD_FMT ":0x%04X\n",
++ NIPQUAD(iph->daddr), tcph->dest,
++ NIPQUAD(iph->saddr), tcph->source);
+
+ /* note: this call is going to increment cm_node ref count */
+ cm_node = find_node(cm_core,
+@@ -1898,7 +1915,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;
- i = hwif->index;
+@@ -1919,7 +1936,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;
- if (hwif->present)
-- ide_unregister(i, 0, 0);
-- else if (!hwif->hold)
-+ ide_unregister(i);
-+ else
- ide_init_port_data(hwif, i);
+- atomic_set(&cm_core->session_id, 0);
+ atomic_set(&cm_core->events_posted, 0);
- ide_init_port_hw(hwif, &hw);
-+ hwif->mmio = 1;
- hwif->quirkproc = NULL;
+ /* init the packet lists */
+@@ -1958,7 +1974,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);
- idx[0] = i;
-@@ -64,6 +67,8 @@ out:
+@@ -1983,7 +1999,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 +2008,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;
- static int __init bastide_init(void)
+@@ -2109,7 +2125,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)
{
-+ unsigned long base = BAST_VA_IDEPRI + BAST_IDE_CS;
-+
- /* we can treat the VR1000 and the BAST the same */
+ struct nes_qp *nesqp = container_of(work, struct nes_qp, disconn_work);
- if (!(machine_is_bast() || machine_is_vr1000()))
-@@ -71,6 +76,11 @@ static int __init bastide_init(void)
+@@ -2122,7 +2138,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 +2281,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 +2498,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);
- printk("BAST: IDE driver, (c) 2003-2004 Simtec Electronics\n");
+ return 0;
+ }
+@@ -2650,7 +2666,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;
+ }
-+ 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);
+@@ -2740,7 +2756,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 +2880,7 @@ void cm_event_connected(struct nes_cm_event *event)
-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;
+ 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 );
-- hwif = ide_find_port(port);
-+ hwif = ide_find_port();
- if (hwif) {
- int i;
+@@ -2877,7 +2893,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 +2935,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);
-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;
+@@ -2930,7 +2946,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 +2989,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 +3023,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);
-- 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;
+ return;
+ }
+@@ -3019,7 +3035,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 {
- /* 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;
+ 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 {
- /* 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);
+ /* per connection node and node state information */
+ struct nes_cm_node {
+- u64 session_id;
+ u32 hashkey;
- /* 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;
+ nes_addr_t loc_addr, rem_addr;
+@@ -327,7 +325,6 @@ struct nes_cm_event {
-@@ -168,9 +168,9 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
- struct ide_timing *t;
+ struct nes_cm_core {
+ enum nes_cm_node_state state;
+- atomic_t session_id;
- /* 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);
+ 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);
+ };
- t2i = t0 - t2 - 1;
- t2 -= 1;
-@@ -192,8 +192,8 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
+-
+-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);
- /* 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);
+ 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);
- 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;
+ 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);
-- hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
-+ hwif = ide_find_port();
- if (hwif == NULL)
- goto out;
+-/* 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..8dc70f9 100644
+--- a/drivers/infiniband/hw/nes/nes_hw.c
++++ b/drivers/infiniband/hw/nes/nes_hw.c
+@@ -38,10 +38,11 @@
+ #include <linux/ip.h>
+ #include <linux/tcp.h>
+ #include <linux/if_vlan.h>
++#include <linux/inet_lro.h>
- i = hwif->index;
+ #include "nes.h"
- if (hwif->present)
-- ide_unregister(i, 0, 0);
-- else if (!hwif->hold)
-+ ide_unregister(i);
-+ else
- ide_init_port_data(hwif, i);
+-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 +54,17 @@ u32 int_mod_cq_depth_1;
- ide_init_port_hw(hwif, &hw);
-@@ -409,9 +409,13 @@ out:
- return -ENODEV;
- }
+ #include "nes_cm.h"
-+/* work with hotplug and coldplug */
-+MODULE_ALIAS("platform:palm_bk3710");
++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 +382,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 +394,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 +584,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 +595,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;
+@@ -625,6 +637,15 @@ unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode)
+ nes_debug(NES_DBG_INIT, "Did not see full soft reset done.\n");
+ return 0;
+ }
+
- 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;
++ i = 0;
++ while ((nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS) != 0x80) && i++ < 10000)
++ mdelay(1);
++ if (i >= 10000) {
++ printk(KERN_ERR PFX "Internal CPU not ready, status = %02X\n",
++ nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS));
++ return 0;
++ }
}
-- 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)
+ /* port reset */
+@@ -673,17 +694,6 @@ unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode)
+ }
+ }
- ecard_set_drvdata(ec, NULL);
+-
+-
+- i = 0;
+- while ((nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS) != 0x80) && i++ < 10000)
+- mdelay(1);
+- if (i >= 10000) {
+- printk(KERN_ERR PFX "Internal CPU not ready, status = %02X\n",
+- nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS));
+- return 0;
+- }
+-
+ return port_count;
+ }
-- ide_unregister(hwif->index, 0, 0);
-+ ide_unregister(hwif->index);
+@@ -691,7 +701,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 +750,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 +771,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;
- ecard_release_resources(ec);
+@@ -822,7 +833,7 @@ void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count)
+ nes_write_indexed(nesdev, 0x00000900, 0x20000001);
+ nes_write_indexed(nesdev, 0x000060C0, 0x0000028e);
+ nes_write_indexed(nesdev, 0x000060C8, 0x00000020);
+- //
++
+ nes_write_indexed(nesdev, 0x000001EC, 0x7b2625a0);
+ /* nes_write_indexed(nesdev, 0x000001EC, 0x5f2625a0); */
+
+@@ -1197,14 +1208,19 @@ int nes_init_phy(struct nes_device *nesdev)
+ {
+ struct nes_adapter *nesadapter = nesdev->nesadapter;
+ u32 counter = 0;
++ u32 sds_common_control0;
+ u32 mac_index = nesdev->mac_index;
+- u32 tx_config;
++ u32 tx_config = 0;
+ u16 phy_data;
++ u32 temp_phy_data = 0;
++ u32 temp_phy_data2 = 0;
++ u32 i = 0;
+
+- if (nesadapter->OneG_Mode) {
++ if ((nesadapter->OneG_Mode) &&
++ (nesadapter->phy_type[mac_index] != NES_PHY_TYPE_PUMA_1G)) {
+ 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);
+@@ -1213,7 +1229,7 @@ int nes_init_phy(struct nes_device *nesdev)
+ nes_read_1G_phy_reg(nesdev, 1, nesadapter->phy_index[mac_index], &phy_data);
+ nes_debug(NES_DBG_PHY, "Phy data from register 1 phy address %u = 0x%X.\n",
+ nesadapter->phy_index[mac_index], phy_data);
+- nes_write_1G_phy_reg(nesdev, 23, nesadapter->phy_index[mac_index], 0xb000);
++ nes_write_1G_phy_reg(nesdev, 23, nesadapter->phy_index[mac_index], 0xb000);
+
+ /* Reset the PHY */
+ nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], 0x8000);
+@@ -1267,12 +1283,126 @@ int nes_init_phy(struct nes_device *nesdev)
+ nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], &phy_data);
+ nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], phy_data | 0x0300);
+ } else {
+- if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_IRIS) {
++ if ((nesadapter->phy_type[mac_index] == NES_PHY_TYPE_IRIS) ||
++ (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_ARGUS)) {
+ /* setup 10G MDIO operation */
+ tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
+ tx_config |= 0x14;
+ nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
+ }
++ if ((nesadapter->phy_type[mac_index] == NES_PHY_TYPE_ARGUS)) {
++ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0xd7ee);
++
++ temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
++ mdelay(10);
++ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0xd7ee);
++ temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
++
++ /*
++ * if firmware is already running (like from a
++ * driver un-load/load, don't do anything.
++ */
++ if (temp_phy_data == temp_phy_data2) {
++ /* configure QT2505 AMCC PHY */
++ nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0x0000, 0x8000);
++ nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc300, 0x0000);
++ nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc302, 0x0044);
++ nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc318, 0x0052);
++ nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc319, 0x0008);
++ nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc31a, 0x0098);
++ nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0026, 0x0E00);
++ nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0027, 0x0000);
++ nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0028, 0xA528);
++
++ /*
++ * remove micro from reset; chip boots from ROM,
++ * uploads EEPROM f/w image, uC executes f/w
++ */
++ nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc300, 0x0002);
++
++ /*
++ * wait for heart beat to start to
++ * know loading is done
++ */
++ counter = 0;
++ do {
++ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0xd7ee);
++ temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
++ if (counter++ > 1000) {
++ nes_debug(NES_DBG_PHY, "AMCC PHY- breaking from heartbeat check <this is bad!!!> \n");
++ break;
++ }
++ mdelay(100);
++ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0xd7ee);
++ temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
++ } while ((temp_phy_data2 == temp_phy_data));
++
++ /*
++ * wait for tracking to start to know
++ * f/w is good to go
++ */
++ counter = 0;
++ do {
++ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0xd7fd);
++ temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
++ if (counter++ > 1000) {
++ nes_debug(NES_DBG_PHY, "AMCC PHY- breaking from status check <this is bad!!!> \n");
++ break;
++ }
++ mdelay(1000);
++ /*
++ * nes_debug(NES_DBG_PHY, "AMCC PHY- phy_status not ready yet = 0x%02X\n",
++ * temp_phy_data);
++ */
++ } while (((temp_phy_data & 0xff) != 0x50) && ((temp_phy_data & 0xff) != 0x70));
++
++ /* set LOS Control invert RXLOSB_I_PADINV */
++ nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xd003, 0x0000);
++ /* set LOS Control to mask of RXLOSB_I */
++ nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc314, 0x0042);
++ /* set LED1 to input mode (LED1 and LED2 share same LED) */
++ nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xd006, 0x0007);
++ /* set LED2 to RX link_status and activity */
++ nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xd007, 0x000A);
++ /* set LED3 to RX link_status */
++ nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xd008, 0x0009);
++
++ /*
++ * reset the res-calibration on t2
++ * serdes; ensures it is stable after
++ * the amcc phy is stable
++ */
++
++ sds_common_control0 = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0);
++ sds_common_control0 |= 0x1;
++ nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, sds_common_control0);
++
++ /* release the res-calibration reset */
++ sds_common_control0 &= 0xfffffffe;
++ nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, sds_common_control0);
++
++ i = 0;
++ while (((nes_read32(nesdev->regs + NES_SOFTWARE_RESET) & 0x00000040) != 0x00000040)
++ && (i++ < 5000)) {
++ /* mdelay(1); */
++ }
++
++ /*
++ * wait for link train done before moving on,
++ * or will get an interupt storm
++ */
++ counter = 0;
++ do {
++ temp_phy_data = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
++ (0x200 * (nesdev->mac_index & 1)));
++ if (counter++ > 1000) {
++ nes_debug(NES_DBG_PHY, "AMCC PHY- breaking from link train wait <this is bad, link didnt train!!!>\n");
++ break;
++ }
++ mdelay(1);
++ } while (((temp_phy_data & 0x0f1f0000) != 0x0f0f0000));
++ }
++ }
+ }
+ return 0;
}
-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)
+@@ -1358,13 +1488,32 @@ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)
+ static void nes_rq_wqes_timeout(unsigned long parm)
{
-- reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, int, IDE_DATA_REG);
-+ ide_hwif_t *hwif = drive->hwif;
+ 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);
+ }
+
+
++static int nes_lro_get_skb_hdr(struct sk_buff *skb, void **iphdr,
++ void **tcph, u64 *hdr_flags, void *priv)
++{
++ unsigned int ip_len;
++ struct iphdr *iph;
++ skb_reset_network_header(skb);
++ iph = ip_hdr(skb);
++ if (iph->protocol != IPPROTO_TCP)
++ return -1;
++ ip_len = ip_hdrlen(skb);
++ skb_set_transport_header(skb, ip_len);
++ *tcph = tcp_hdr(skb);
++
++ *hdr_flags = LRO_IPV4 | LRO_TCP;
++ *iphdr = iph;
++ return 0;
++}
+
-+ 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};
++
+ /**
+ * nes_init_nic_qp
+ */
+@@ -1510,10 +1659,10 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
+ }
- mycontext.saved_data = (dma_descr_data*)virt_to_phys(d);
-@@ -264,8 +267,12 @@ cris_ide_wait_dma(int dir)
+ u64temp = (u64)nesvnic->nic.sq_pbase;
+- nic_context->context_words[NES_NIC_CTX_SQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
++ nic_context->context_words[NES_NIC_CTX_SQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
+ nic_context->context_words[NES_NIC_CTX_SQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
+ u64temp = (u64)nesvnic->nic.rq_pbase;
+- nic_context->context_words[NES_NIC_CTX_RQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
++ nic_context->context_words[NES_NIC_CTX_RQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
+ nic_context->context_words[NES_NIC_CTX_RQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
+
+ cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_CREATE_QP |
+@@ -1565,7 +1714,7 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
+ nic_rqe = &nesvnic->nic.rq_vbase[counter];
+ nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32(nesvnic->max_frame_size);
+ nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
+- nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] = cpu_to_le32((u32)pmem);
++ nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] = cpu_to_le32((u32)pmem);
+ nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] = cpu_to_le32((u32)((u64)pmem >> 32));
+ nesvnic->nic.rx_skb[counter] = skb;
+ }
+@@ -1582,15 +1731,21 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
+ nesvnic->rq_wqes_timer.function = nes_rq_wqes_timeout;
+ nesvnic->rq_wqes_timer.data = (unsigned long)nesvnic;
+ nes_debug(NES_DBG_INIT, "NAPI support Enabled\n");
+-
+ if (nesdev->nesadapter->et_use_adaptive_rx_coalesce)
+ {
+ nes_nic_init_timer(nesdev);
+ if (netdev->mtu > 1500)
+ jumbomode = 1;
+- nes_nic_init_timer_defaults(nesdev, jumbomode);
+- }
+-
++ nes_nic_init_timer_defaults(nesdev, jumbomode);
++ }
++ nesvnic->lro_mgr.max_aggr = NES_LRO_MAX_AGGR;
++ nesvnic->lro_mgr.max_desc = NES_MAX_LRO_DESCRIPTORS;
++ nesvnic->lro_mgr.lro_arr = nesvnic->lro_desc;
++ nesvnic->lro_mgr.get_skb_header = nes_lro_get_skb_hdr;
++ nesvnic->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
++ nesvnic->lro_mgr.dev = netdev;
++ nesvnic->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
++ nesvnic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
+ return 0;
+ }
+
+@@ -1610,8 +1765,8 @@ void nes_destroy_nic_qp(struct nes_vnic *nesvnic)
+
+ /* Free remaining NIC receive buffers */
+ while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) {
+- nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
+- wqe_frag = (u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
++ nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
++ wqe_frag = (u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
+ wqe_frag |= ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32;
+ pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag,
+ nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+@@ -1694,17 +1849,17 @@ int nes_napi_isr(struct nes_device *nesdev)
+ /* iff NIC, process here, else wait for DPC */
+ if ((int_stat) && ((int_stat & 0x0000ff00) == int_stat)) {
+ nesdev->napi_isr_ran = 0;
+- nes_write32(nesdev->regs+NES_INT_STAT,
+- (int_stat &
+- ~(NES_INT_INTF|NES_INT_TIMER|NES_INT_MAC0|NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3)));
++ nes_write32(nesdev->regs + NES_INT_STAT,
++ (int_stat &
++ ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0 | NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3)));
+
+ /* Process the CEQs */
+ nes_process_ceq(nesdev, &nesdev->nesadapter->ceq[nesdev->nic_ceq_index]);
+
+ if (unlikely((((nesadapter->et_rx_coalesce_usecs_irq) &&
+- (!nesadapter->et_use_adaptive_rx_coalesce)) ||
+- ((nesadapter->et_use_adaptive_rx_coalesce) &&
+- (nesdev->deepcq_count > nesadapter->et_pkt_rate_low)))) ) {
++ (!nesadapter->et_use_adaptive_rx_coalesce)) ||
++ ((nesadapter->et_use_adaptive_rx_coalesce) &&
++ (nesdev->deepcq_count > nesadapter->et_pkt_rate_low))))) {
+ if ((nesdev->int_req & NES_INT_TIMER) == 0) {
+ /* Enable Periodic timer interrupts */
+ nesdev->int_req |= NES_INT_TIMER;
+@@ -1782,12 +1937,12 @@ void nes_dpc(unsigned long param)
+ }
+
+ if (int_stat) {
+- if (int_stat & ~(NES_INT_INTF|NES_INT_TIMER|NES_INT_MAC0|
+- NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3)) {
++ if (int_stat & ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0|
++ NES_INT_MAC1|NES_INT_MAC2 | NES_INT_MAC3)) {
+ /* Ack the interrupts */
+ nes_write32(nesdev->regs+NES_INT_STAT,
+- (int_stat & ~(NES_INT_INTF|NES_INT_TIMER|NES_INT_MAC0|
+- NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3)));
++ (int_stat & ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0|
++ NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3)));
+ }
- static int cris_dma_test_irq(ide_drive_t *drive)
+ temp_int_stat = int_stat;
+@@ -1852,8 +2007,8 @@ void nes_dpc(unsigned long param)
+ }
+ }
+ /* Don't use the interface interrupt bit stay in loop */
+- int_stat &= ~NES_INT_INTF|NES_INT_TIMER|NES_INT_MAC0|
+- NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3;
++ int_stat &= ~NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0 |
++ NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3;
+ } while ((int_stat != 0) && (loop_counter++ < MAX_DPC_ITERATIONS));
+
+ if (timer_ints == 1) {
+@@ -1864,9 +2019,9 @@ void nes_dpc(unsigned long param)
+ nesdev->timer_only_int_count = 0;
+ nesdev->int_req &= ~NES_INT_TIMER;
+ nes_write32(nesdev->regs + NES_INTF_INT_MASK, ~(nesdev->intf_int_req));
+- nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);
++ nes_write32(nesdev->regs + NES_INT_MASK, ~nesdev->int_req);
+ } else {
+- nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff|(~nesdev->int_req));
++ nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
+ }
+ } else {
+ if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
+@@ -1874,7 +2029,7 @@ void nes_dpc(unsigned long param)
+ nes_nic_init_timer(nesdev);
+ }
+ nesdev->timer_only_int_count = 0;
+- nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff|(~nesdev->int_req));
++ nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
+ }
+ } else {
+ nesdev->timer_only_int_count = 0;
+@@ -1909,7 +2064,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)
{
-+ 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);
+ u64 u64temp;
+ struct nes_hw_cq *cq;
+@@ -1923,7 +2078,7 @@ void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq)
+ do {
+ if (le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX]) &
+ NES_CEQE_VALID) {
+- u64temp = (((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX])))<<32) |
++ u64temp = (((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX]))) << 32) |
+ ((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_LOW_IDX])));
+ u64temp <<= 1;
+ cq = *((struct nes_hw_cq **)&u64temp);
+@@ -1949,9 +2104,9 @@ 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;
++ /* u64 u64temp; */
+ u32 head;
+ u32 aeq_size;
+ u32 aeqe_misc;
+@@ -1970,8 +2125,10 @@ void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq)
+ if (aeqe_misc & (NES_AEQE_QP|NES_AEQE_CQ)) {
+ if (aeqe_cq_id >= NES_FIRST_QPN) {
+ /* dealing with an accelerated QP related AE */
+-// u64temp = (((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])))<<32) |
+-// ((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX])));
++ /*
++ * u64temp = (((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX]))) << 32) |
++ * ((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX])));
++ */
+ nes_process_iwarp_aeqe(nesdev, (struct nes_hw_aeqe *)aeqe);
+ } else {
+ /* TODO: dealing with a CQP related AE */
+@@ -2060,7 +2217,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;
+@@ -2071,6 +2228,8 @@ void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
+ u32 u32temp;
+ u16 phy_data;
+ u16 temp_phy_data;
++ u32 pcs_val = 0x0f0f0000;
++ u32 pcs_mask = 0x0f1f0000;
+
+ spin_lock_irqsave(&nesadapter->phy_lock, flags);
+ if (nesadapter->mac_sw_state[mac_number] != NES_MAC_SW_IDLE) {
+@@ -2134,13 +2293,30 @@ void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
+ nes_debug(NES_DBG_PHY, "Eth SERDES Common Status: 0=0x%08X, 1=0x%08X\n",
+ nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0),
+ nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0+0x200));
+- pcs_control_status = nes_read_indexed(nesdev,
+- NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index&1)*0x200));
+- pcs_control_status = nes_read_indexed(nesdev,
+- NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index&1)*0x200));
+
-+ reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, int,
-+ hwif->io_ports[IDE_DATA_OFFSET]);
++ if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_PUMA_1G) {
++ switch (mac_index) {
++ case 1:
++ case 3:
++ pcs_control_status = nes_read_indexed(nesdev,
++ NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
++ break;
++ default:
++ pcs_control_status = nes_read_indexed(nesdev,
++ NES_IDX_PHY_PCS_CONTROL_STATUS0);
++ break;
++ }
++ } else {
++ pcs_control_status = nes_read_indexed(nesdev,
++ NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index & 1) * 0x200));
++ pcs_control_status = nes_read_indexed(nesdev,
++ NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index & 1) * 0x200));
++ }
++
+ nes_debug(NES_DBG_PHY, "PCS PHY Control/Status%u: 0x%08X\n",
+ mac_index, pcs_control_status);
+- if (nesadapter->OneG_Mode) {
++ if ((nesadapter->OneG_Mode) &&
++ (nesadapter->phy_type[mac_index] != NES_PHY_TYPE_PUMA_1G)) {
+ u32temp = 0x01010000;
+ if (nesadapter->port_count > 2) {
+ u32temp |= 0x02020000;
+@@ -2149,24 +2325,59 @@ void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
+ phy_data = 0;
+ nes_debug(NES_DBG_PHY, "PCS says the link is down\n");
+ }
+- } else if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_IRIS) {
+- nes_read_10G_phy_reg(nesdev, 1, nesadapter->phy_index[mac_index]);
+- temp_phy_data = (u16)nes_read_indexed(nesdev,
+- NES_IDX_MAC_MDIO_CONTROL);
+- u32temp = 20;
+- do {
+- nes_read_10G_phy_reg(nesdev, 1, nesadapter->phy_index[mac_index]);
+- phy_data = (u16)nes_read_indexed(nesdev,
+- NES_IDX_MAC_MDIO_CONTROL);
+- if ((phy_data == temp_phy_data) || (!(--u32temp)))
+- break;
+- 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");
+-
+ } else {
+- phy_data = (0x0f0f0000 == (pcs_control_status & 0x0f1f0000)) ? 4 : 0;
++ switch (nesadapter->phy_type[mac_index]) {
++ case NES_PHY_TYPE_IRIS:
++ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1);
++ temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
++ u32temp = 20;
++ do {
++ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1);
++ phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
++ if ((phy_data == temp_phy_data) || (!(--u32temp)))
++ break;
++ temp_phy_data = phy_data;
++ } while (1);
++ nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",
++ __func__, phy_data, nesadapter->mac_link_down[mac_index] ? "DOWN" : "UP");
++ break;
+
- 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]);
++ case NES_PHY_TYPE_ARGUS:
++ /* clear the alarms */
++ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0x0008);
++ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc001);
++ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc002);
++ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc005);
++ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc006);
++ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9003);
++ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9004);
++ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9005);
++ /* check link status */
++ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1);
++ temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
++ u32temp = 100;
++ do {
++ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1);
+
- 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)
++ phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
++ if ((phy_data == temp_phy_data) || (!(--u32temp)))
++ break;
++ temp_phy_data = phy_data;
++ } while (1);
++ nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",
++ __func__, phy_data, nesadapter->mac_link_down ? "DOWN" : "UP");
++ break;
++
++ case NES_PHY_TYPE_PUMA_1G:
++ if (mac_index < 2)
++ pcs_val = pcs_mask = 0x01010000;
++ else
++ pcs_val = pcs_mask = 0x02020000;
++ /* fall through */
++ default:
++ phy_data = (pcs_val == (pcs_control_status & pcs_mask)) ? 0x4 : 0x0;
++ break;
++ }
+ }
- cris_setup_ports(&hw, cris_ide_base_address(h));
+ if (phy_data & 0x0004) {
+@@ -2175,8 +2386,8 @@ void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
+ nes_debug(NES_DBG_PHY, "The Link is UP!!. linkup was %d\n",
+ nesvnic->linkup);
+ if (nesvnic->linkup == 0) {
+- printk(PFX "The Link is now up for port %u, netdev %p.\n",
+- mac_index, nesvnic->netdev);
++ printk(PFX "The Link is now up for port %s, netdev %p.\n",
++ nesvnic->netdev->name, nesvnic->netdev);
+ if (netif_queue_stopped(nesvnic->netdev))
+ netif_start_queue(nesvnic->netdev);
+ nesvnic->linkup = 1;
+@@ -2189,8 +2400,8 @@ void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
+ nes_debug(NES_DBG_PHY, "The Link is Down!!. linkup was %d\n",
+ nesvnic->linkup);
+ if (nesvnic->linkup == 1) {
+- printk(PFX "The Link is now down for port %u, netdev %p.\n",
+- mac_index, nesvnic->netdev);
++ printk(PFX "The Link is now down for port %s, netdev %p.\n",
++ nesvnic->netdev->name, nesvnic->netdev);
+ if (!(netif_queue_stopped(nesvnic->netdev)))
+ netif_stop_queue(nesvnic->netdev);
+ nesvnic->linkup = 0;
+@@ -2205,7 +2416,7 @@ void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
-- 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];
+-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);
-+ memset(drive->acpidata, 0, sizeof(*drive->acpidata));
-+
- if (!drive->present)
- continue;
+@@ -2244,10 +2455,13 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
+ u16 pkt_type;
+ u16 rqes_processed = 0;
+ u8 sq_cqes = 0;
++ u8 nes_use_lro = 0;
+
+ head = cq->cq_head;
+ cq_size = cq->cq_size;
+ cq->cqes_pending = 1;
++ if (nesvnic->netdev->features & NETIF_F_LRO)
++ nes_use_lro = 1;
+ do {
+ if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]) &
+ NES_NIC_CQE_VALID) {
+@@ -2262,8 +2476,10 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
+ /* bump past the vlan tag */
+ wqe_fragment_length++;
+ if (le16_to_cpu(wqe_fragment_length[wqe_fragment_index]) != 0) {
+- u64temp = (u64) le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+wqe_fragment_index*2]);
+- u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX+wqe_fragment_index*2]))<<32;
++ u64temp = (u64) le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX +
++ wqe_fragment_index * 2]);
++ u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX +
++ wqe_fragment_index * 2])) << 32;
+ bus_address = (dma_addr_t)u64temp;
+ if (test_and_clear_bit(nesnic->sq_tail, nesnic->first_frag_overflow)) {
+ pci_unmap_single(nesdev->pcidev,
+@@ -2273,8 +2489,10 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
+ }
+ for (; wqe_fragment_index < 5; wqe_fragment_index++) {
+ if (wqe_fragment_length[wqe_fragment_index]) {
+- u64temp = le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+wqe_fragment_index*2]);
+- u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX+wqe_fragment_index*2]))<<32;
++ u64temp = le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX +
++ wqe_fragment_index * 2]);
++ u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX
++ + wqe_fragment_index * 2])) <<32;
+ bus_address = (dma_addr_t)u64temp;
+ pci_unmap_page(nesdev->pcidev,
+ bus_address,
+@@ -2321,7 +2539,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
+ if (atomic_read(&nesvnic->rx_skbs_needed) > (nesvnic->nic.rq_size>>1)) {
+ nes_write32(nesdev->regs+NES_CQE_ALLOC,
+ cq->cq_number | (cqe_count << 16));
+-// nesadapter->tune_timer.cq_count += cqe_count;
++ /* nesadapter->tune_timer.cq_count += cqe_count; */
+ nesdev->currcq_count += cqe_count;
+ cqe_count = 0;
+ nes_replenish_nic_rq(nesvnic);
+@@ -2369,9 +2587,16 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
+ >> 16);
+ nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n",
+ nesvnic->netdev->name, vlan_tag);
+- nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag);
++ if (nes_use_lro)
++ lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb,
++ nesvnic->vlan_grp, vlan_tag, NULL);
++ else
++ nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag);
+ } else {
+- nes_netif_rx(rx_skb);
++ if (nes_use_lro)
++ lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL);
++ else
++ nes_netif_rx(rx_skb);
+ }
+ }
-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 @@
+@@ -2389,7 +2614,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
+ /* Replenish Nic CQ */
+ nes_write32(nesdev->regs+NES_CQE_ALLOC,
+ cq->cq_number | (cqe_count << 16));
+-// nesdev->nesadapter->tune_timer.cq_count += cqe_count;
++ /* nesdev->nesadapter->tune_timer.cq_count += cqe_count; */
+ nesdev->currcq_count += cqe_count;
+ cqe_count = 0;
+ }
+@@ -2403,32 +2628,33 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
- static DEFINE_MUTEX(idecd_ref_mutex);
+ } while (1);
--#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref)
-+#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref)
++ if (nes_use_lro)
++ lro_flush_all(&nesvnic->lro_mgr);
+ if (sq_cqes) {
+ barrier();
+ /* restart the queue if it had been stopped */
+ if (netif_queue_stopped(nesvnic->netdev))
+ netif_wake_queue(nesvnic->netdev);
+ }
+-
+ cq->cq_head = head;
+ /* nes_debug(NES_DBG_CQ, "CQ%u Processed = %u cqes, new head = %u.\n",
+ cq->cq_number, cqe_count, cq->cq_head); */
+ cq->cqe_allocs_pending = cqe_count;
+ if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
+ {
+-// nesdev->nesadapter->tune_timer.cq_count += cqe_count;
++ /* nesdev->nesadapter->tune_timer.cq_count += cqe_count; */
+ nesdev->currcq_count += cqe_count;
+ nes_nic_tune_timer(nesdev);
+ }
+ if (atomic_read(&nesvnic->rx_skbs_needed))
+ nes_replenish_nic_rq(nesvnic);
+- }
++}
- #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)
+ /**
+ * 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)
{
- struct cdrom_info *cd = drive->driver_data;
+ u64 u64temp;
+ unsigned long flags;
+@@ -2451,7 +2677,7 @@ void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
- cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
- cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
-- cd->nsectors_buffered = 0;
- }
+ if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {
+ u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
+- cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX])))<<32) |
++ cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
+ ((u64)(le32_to_cpu(cq->cq_vbase[head].
+ cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
+ cqp = *((struct nes_hw_cqp **)&u64temp);
+@@ -2468,7 +2694,7 @@ void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
+ }
- 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;
+ u64temp = (((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
+- wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX])))<<32) |
++ wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) |
+ ((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
+ wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX])));
+ cqp_request = *((struct nes_cqp_request **)&u64temp);
+@@ -2505,7 +2731,7 @@ void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
+ } else {
+ nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) freed.\n",
+ cqp_request,
+- le32_to_cpu(cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f);
++ le32_to_cpu(cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_OPCODE_IDX]) & 0x3f);
+ if (cqp_request->dynamic) {
+ kfree(cqp_request);
+ } else {
+@@ -2519,7 +2745,7 @@ void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
+ }
- 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)
+ cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0;
+- nes_write32(nesdev->regs+NES_CQE_ALLOC, cq->cq_number | (1 << 16));
++ nes_write32(nesdev->regs + NES_CQE_ALLOC, cq->cq_number | (1 << 16));
+ if (++cqp->sq_tail >= cqp->sq_size)
+ cqp->sq_tail = 0;
+
+@@ -2567,7 +2793,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;
+@@ -2587,13 +2814,13 @@ void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe)
+ nes_debug(NES_DBG_AEQ, "\n");
+ aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
+ if ((NES_AEQE_INBOUND_RDMA&aeq_info) || (!(NES_AEQE_QP&aeq_info))) {
+- context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
++ context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
+ context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32;
+ } else {
+ aeqe_context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
+ aeqe_context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32;
+ context = (unsigned long)nesadapter->qp_table[le32_to_cpu(
+- aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN];
++ aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN];
+ BUG_ON(!context);
+ }
+
+@@ -2606,7 +2833,6 @@ 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]), aeqe,
+ nes_tcp_state_str[tcp_state], nes_iwarp_state_str[iwarp_state]);
+
+-
+ switch (async_event_id) {
+ case NES_AEQE_AEID_LLP_FIN_RECEIVED:
+ nesqp = *((struct nes_qp **)&context);
+@@ -2819,7 +3045,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;
-+ 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;
+ case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER:
+@@ -3010,7 +3236,7 @@ void nes_manage_arp_cache(struct net_device *netdev, unsigned char *mac_addr,
+ cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_ARP_VALID);
+ cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = cpu_to_le32(
+ (((u32)mac_addr[2]) << 24) | (((u32)mac_addr[3]) << 16) |
+- (((u32)mac_addr[4]) << 8) | (u32)mac_addr[5]);
++ (((u32)mac_addr[4]) << 8) | (u32)mac_addr[5]);
+ cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = cpu_to_le32(
+ (((u32)mac_addr[0]) << 16) | (u32)mac_addr[1]);
+ } else {
+diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
+index b7e2844..745bf94 100644
+--- a/drivers/infiniband/hw/nes/nes_hw.h
++++ b/drivers/infiniband/hw/nes/nes_hw.h
+@@ -33,8 +33,12 @@
+ #ifndef __NES_HW_H
+ #define __NES_HW_H
-- 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;
+-#define NES_PHY_TYPE_1G 2
+-#define NES_PHY_TYPE_IRIS 3
++#include <linux/inet_lro.h>
++
++#define NES_PHY_TYPE_1G 2
++#define NES_PHY_TYPE_IRIS 3
++#define NES_PHY_TYPE_ARGUS 4
++#define NES_PHY_TYPE_PUMA_1G 5
+ #define NES_PHY_TYPE_PUMA_10G 6
+
+ #define NES_MULTICAST_PF_MAX 8
+@@ -905,7 +909,7 @@ struct nes_hw_qp {
+ };
+
+ struct nes_hw_cq {
+- struct nes_hw_cqe volatile *cq_vbase; /* PCI memory for host rings */
++ struct nes_hw_cqe *cq_vbase; /* PCI memory for host rings */
+ void (*ce_handler)(struct nes_device *nesdev, struct nes_hw_cq *cq);
+ dma_addr_t cq_pbase; /* PCI memory for host rings */
+ u16 cq_head;
+@@ -965,7 +969,7 @@ struct nes_arp_entry {
+ #define NES_NIC_CQ_DOWNWARD_TREND 16
+
+ struct nes_hw_tune_timer {
+- //u16 cq_count;
++ /* u16 cq_count; */
+ u16 threshold_low;
+ u16 threshold_target;
+ u16 threshold_high;
+@@ -982,8 +986,10 @@ struct nes_hw_tune_timer {
+ #define NES_TIMER_INT_LIMIT 2
+ #define NES_TIMER_INT_LIMIT_DYNAMIC 10
+ #define NES_TIMER_ENABLE_LIMIT 4
+-#define NES_MAX_LINK_INTERRUPTS 128
+-#define NES_MAX_LINK_CHECK 200
++#define NES_MAX_LINK_INTERRUPTS 128
++#define NES_MAX_LINK_CHECK 200
++#define NES_MAX_LRO_DESCRIPTORS 32
++#define NES_LRO_MAX_AGGR 64
+
+ struct nes_adapter {
+ u64 fw_ver;
+@@ -1183,6 +1189,9 @@ struct nes_vnic {
+ u8 of_device_registered;
+ u8 rdma_enabled;
+ u8 rx_checksum_disabled;
++ u32 lro_max_aggr;
++ struct net_lro_mgr lro_mgr;
++ struct net_lro_desc lro_desc[NES_MAX_LRO_DESCRIPTORS];
+ };
- 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);
- }
-- }
-- }
-+ }
-+ }
+ struct nes_ib_device {
+diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
+index eee77da..1b0938c 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;
- 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 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
+ */
+@@ -194,12 +185,13 @@ static int nes_netdev_open(struct net_device *netdev)
+ nic_active |= nic_active_bit;
+ nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active);
+
+- macaddr_high = ((u16)netdev->dev_addr[0]) << 8;
++ macaddr_high = ((u16)netdev->dev_addr[0]) << 8;
+ macaddr_high += (u16)netdev->dev_addr[1];
+- macaddr_low = ((u32)netdev->dev_addr[2]) << 24;
+- macaddr_low += ((u32)netdev->dev_addr[3]) << 16;
+- macaddr_low += ((u32)netdev->dev_addr[4]) << 8;
+- macaddr_low += (u32)netdev->dev_addr[5];
++
++ macaddr_low = ((u32)netdev->dev_addr[2]) << 24;
++ macaddr_low += ((u32)netdev->dev_addr[3]) << 16;
++ macaddr_low += ((u32)netdev->dev_addr[4]) << 8;
++ macaddr_low += (u32)netdev->dev_addr[5];
+
+ /* Program the various MAC regs */
+ for (i = 0; i < NES_MAX_PORT_COUNT; i++) {
+@@ -460,7 +452,7 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+ __le16 *wqe_fragment_length;
+ u32 nr_frags;
+ u32 original_first_length;
+-// u64 *wqe_fragment_address;
++ /* u64 *wqe_fragment_address; */
+ /* first fragment (0) is used by copy buffer */
+ u16 wqe_fragment_index=1;
+ u16 hoffset;
+@@ -470,11 +462,12 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+ u32 old_head;
+ u32 wqe_misc;
+
+- /* nes_debug(NES_DBG_NIC_TX, "%s Request to tx NIC packet length %u, headlen %u,"
+- " (%u frags), tso_size=%u\n",
+- netdev->name, skb->len, skb_headlen(skb),
+- skb_shinfo(skb)->nr_frags, skb_is_gso(skb));
+- */
++ /*
++ * nes_debug(NES_DBG_NIC_TX, "%s Request to tx NIC packet length %u, headlen %u,"
++ * " (%u frags), tso_size=%u\n",
++ * netdev->name, skb->len, skb_headlen(skb),
++ * skb_shinfo(skb)->nr_frags, skb_is_gso(skb));
++ */
--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);
+ if (!netif_carrier_ok(netdev))
+ return NETDEV_TX_OK;
+@@ -796,22 +789,20 @@ static int nes_netdev_set_mac_address(struct net_device *netdev, void *p)
+ int i;
+ u32 macaddr_low;
+ u16 macaddr_high;
++ DECLARE_MAC_BUF(mac);
-@@ -334,26 +334,26 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ if (!is_valid_ether_addr(mac_addr->sa_data))
+ return -EADDRNOTAVAIL;
- /* 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;
+ 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,
+- 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]);
+- macaddr_high = ((u16)netdev->dev_addr[0]) << 8;
++ printk(PFX "%s: Address length = %d, Address = %s\n",
++ __func__, netdev->addr_len, print_mac(mac, mac_addr->sa_data));
++ macaddr_high = ((u16)netdev->dev_addr[0]) << 8;
+ macaddr_high += (u16)netdev->dev_addr[1];
+- macaddr_low = ((u32)netdev->dev_addr[2]) << 24;
+- macaddr_low += ((u32)netdev->dev_addr[3]) << 16;
+- macaddr_low += ((u32)netdev->dev_addr[4]) << 8;
+- macaddr_low += (u32)netdev->dev_addr[5];
++ macaddr_low = ((u32)netdev->dev_addr[2]) << 24;
++ macaddr_low += ((u32)netdev->dev_addr[3]) << 16;
++ macaddr_low += ((u32)netdev->dev_addr[4]) << 8;
++ macaddr_low += (u32)netdev->dev_addr[5];
- /*
-@@ -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);
+ for (i = 0; i < NES_MAX_PORT_COUNT; i++) {
+ if (nesvnic->qp_nic_index[i] == 0xf) {
+@@ -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;
+@@ -887,17 +878,17 @@ void nes_netdev_set_multicast_list(struct net_device *netdev)
+ if (mc_nic_index < 0)
+ mc_nic_index = nesvnic->nic_index;
+ if (multicast_addr) {
+- nes_debug(NES_DBG_NIC_RX, "Assigning MC Address = %02X%02X%02X%02X%02X%02X to register 0x%04X nic_idx=%d\n",
+- multicast_addr->dmi_addr[0], multicast_addr->dmi_addr[1],
+- multicast_addr->dmi_addr[2], multicast_addr->dmi_addr[3],
+- multicast_addr->dmi_addr[4], multicast_addr->dmi_addr[5],
+- perfect_filter_register_address+(mc_index * 8), mc_nic_index);
+- macaddr_high = ((u16)multicast_addr->dmi_addr[0]) << 8;
++ DECLARE_MAC_BUF(mac);
++ nes_debug(NES_DBG_NIC_RX, "Assigning MC Address %s to register 0x%04X nic_idx=%d\n",
++ print_mac(mac, multicast_addr->dmi_addr),
++ perfect_filter_register_address+(mc_index * 8),
++ mc_nic_index);
++ macaddr_high = ((u16)multicast_addr->dmi_addr[0]) << 8;
+ macaddr_high += (u16)multicast_addr->dmi_addr[1];
+- macaddr_low = ((u32)multicast_addr->dmi_addr[2]) << 24;
+- macaddr_low += ((u32)multicast_addr->dmi_addr[3]) << 16;
+- macaddr_low += ((u32)multicast_addr->dmi_addr[4]) << 8;
+- macaddr_low += (u32)multicast_addr->dmi_addr[5];
++ macaddr_low = ((u32)multicast_addr->dmi_addr[2]) << 24;
++ macaddr_low += ((u32)multicast_addr->dmi_addr[3]) << 16;
++ macaddr_low += ((u32)multicast_addr->dmi_addr[4]) << 8;
++ macaddr_low += (u32)multicast_addr->dmi_addr[5];
+ nes_write_indexed(nesdev,
+ perfect_filter_register_address+(mc_index * 8),
+ macaddr_low);
+@@ -921,23 +912,23 @@ void nes_netdev_set_multicast_list(struct net_device *netdev)
+ /**
+ * nes_netdev_change_mtu
+ */
+-static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu)
++static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu)
+ {
+ struct nes_vnic *nesvnic = netdev_priv(netdev);
+- struct nes_device *nesdev = nesvnic->nesdev;
+- int ret = 0;
+- u8 jumbomode=0;
++ struct nes_device *nesdev = nesvnic->nesdev;
++ int ret = 0;
++ u8 jumbomode = 0;
- /* 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);
+- if ((new_mtu < ETH_ZLEN) || (new_mtu > max_mtu))
++ if ((new_mtu < ETH_ZLEN) || (new_mtu > max_mtu))
+ return -EINVAL;
-- /* 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,
+- netdev->mtu = new_mtu;
++ netdev->mtu = new_mtu;
+ nesvnic->max_frame_size = new_mtu + VLAN_ETH_HLEN;
- /* 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);
+ if (netdev->mtu > 1500) {
+ jumbomode=1;
+ }
+- nes_nic_init_timer_defaults(nesdev, jumbomode);
++ nes_nic_init_timer_defaults(nesdev, jumbomode);
-@@ -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)
+ if (netif_running(netdev)) {
+ nes_netdev_stop(netdev);
+@@ -947,30 +938,7 @@ static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu)
+ return ret;
}
- /*
-- * 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.)
+-
+-/**
+- * nes_netdev_exit - destroy network device
- */
--static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
-- int sectors_to_transfer)
+-void nes_netdev_exit(struct nes_vnic *nesvnic)
-{
-- 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;
+- struct net_device *netdev = nesvnic->netdev;
+- struct nes_ib_device *nesibdev = nesvnic->nesibdev;
-
-- /* If this is the first sector in the buffer, remember its number. */
-- if (info->nsectors_buffered == 0)
-- info->sector_buffered = sector;
+- nes_debug(NES_DBG_SHUTDOWN, "\n");
-
-- /* 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;
+- // 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;
- }
--
-- /* Throw away any remaining data. */
-- ide_cd_drain_data(drive, sectors_to_transfer);
+- unregister_netdev(netdev);
+- nes_debug(NES_DBG_SHUTDOWN, "\n");
-}
-
--/*
- * 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,
+-
+-#define NES_ETHTOOL_STAT_COUNT 55
+-static const char nes_ethtool_stringset[NES_ETHTOOL_STAT_COUNT][ETH_GSTRING_LEN] = {
++static const char nes_ethtool_stringset[][ETH_GSTRING_LEN] = {
+ "Link Change Interrupts",
+ "Linearized SKBs",
+ "T/GSO Requests",
+@@ -1026,8 +994,12 @@ static const char nes_ethtool_stringset[NES_ETHTOOL_STAT_COUNT][ETH_GSTRING_LEN]
+ "CQ Depth 32",
+ "CQ Depth 128",
+ "CQ Depth 256",
++ "LRO aggregated",
++ "LRO flushed",
++ "LRO no_desc",
+ };
- /* Whoops... */
- printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
-- drive->name, __FUNCTION__);
-+ drive->name, __func__);
++#define NES_ETHTOOL_STAT_COUNT ARRAY_SIZE(nes_ethtool_stringset)
- 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);
- }
+ /**
+ * nes_netdev_get_rx_csum
+@@ -1222,6 +1194,9 @@ static void nes_netdev_get_ethtool_stats(struct net_device *netdev,
+ target_stat_values[52] = int_mod_cq_depth_32;
+ target_stat_values[53] = int_mod_cq_depth_128;
+ target_stat_values[54] = int_mod_cq_depth_256;
++ target_stat_values[55] = nesvnic->lro_mgr.stats.aggregated;
++ target_stat_values[56] = nesvnic->lro_mgr.stats.flushed;
++ target_stat_values[57] = nesvnic->lro_mgr.stats.no_desc;
- 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);
+@@ -1252,14 +1227,14 @@ static int nes_netdev_set_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *et_coalesce)
+ {
+ struct nes_vnic *nesvnic = netdev_priv(netdev);
+- struct nes_device *nesdev = nesvnic->nesdev;
++ struct nes_device *nesdev = nesvnic->nesdev;
+ struct nes_adapter *nesadapter = nesdev->nesadapter;
+ struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
+ unsigned long flags;
- 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;
- }
+- spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);
++ spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);
+ if (et_coalesce->rx_max_coalesced_frames_low) {
+- shared_timer->threshold_low = et_coalesce->rx_max_coalesced_frames_low;
++ shared_timer->threshold_low = et_coalesce->rx_max_coalesced_frames_low;
+ }
+ if (et_coalesce->rx_max_coalesced_frames_irq) {
+ shared_timer->threshold_target = et_coalesce->rx_max_coalesced_frames_irq;
+@@ -1279,14 +1254,14 @@ static int nes_netdev_set_coalesce(struct net_device *netdev,
+ nesadapter->et_rx_coalesce_usecs_irq = et_coalesce->rx_coalesce_usecs_irq;
+ if (et_coalesce->use_adaptive_rx_coalesce) {
+ nesadapter->et_use_adaptive_rx_coalesce = 1;
+- nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT_DYNAMIC;
++ nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT_DYNAMIC;
+ nesadapter->et_rx_coalesce_usecs_irq = 0;
+ if (et_coalesce->pkt_rate_low) {
+- nesadapter->et_pkt_rate_low = et_coalesce->pkt_rate_low;
++ nesadapter->et_pkt_rate_low = et_coalesce->pkt_rate_low;
+ }
+ } else {
+ nesadapter->et_use_adaptive_rx_coalesce = 0;
+- nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT;
++ nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT;
+ if (nesadapter->et_rx_coalesce_usecs_irq) {
+ nes_write32(nesdev->regs+NES_PERIODIC_CONTROL,
+ 0x80000000 | ((u32)(nesadapter->et_rx_coalesce_usecs_irq*8)));
+@@ -1303,28 +1278,28 @@ static int nes_netdev_get_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *et_coalesce)
+ {
+ struct nes_vnic *nesvnic = netdev_priv(netdev);
+- struct nes_device *nesdev = nesvnic->nesdev;
++ struct nes_device *nesdev = nesvnic->nesdev;
+ struct nes_adapter *nesadapter = nesdev->nesadapter;
+ struct ethtool_coalesce temp_et_coalesce;
+ struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
+ unsigned long flags;
--/*
-- * 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 *);
+ memset(&temp_et_coalesce, 0, sizeof(temp_et_coalesce));
+- temp_et_coalesce.rx_coalesce_usecs_irq = nesadapter->et_rx_coalesce_usecs_irq;
+- temp_et_coalesce.use_adaptive_rx_coalesce = nesadapter->et_use_adaptive_rx_coalesce;
+- temp_et_coalesce.rate_sample_interval = nesadapter->et_rate_sample_interval;
++ temp_et_coalesce.rx_coalesce_usecs_irq = nesadapter->et_rx_coalesce_usecs_irq;
++ temp_et_coalesce.use_adaptive_rx_coalesce = nesadapter->et_use_adaptive_rx_coalesce;
++ temp_et_coalesce.rate_sample_interval = nesadapter->et_rate_sample_interval;
+ temp_et_coalesce.pkt_rate_low = nesadapter->et_pkt_rate_low;
+ spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);
+- temp_et_coalesce.rx_max_coalesced_frames_low = shared_timer->threshold_low;
+- temp_et_coalesce.rx_max_coalesced_frames_irq = shared_timer->threshold_target;
++ temp_et_coalesce.rx_max_coalesced_frames_low = shared_timer->threshold_low;
++ temp_et_coalesce.rx_max_coalesced_frames_irq = shared_timer->threshold_target;
+ temp_et_coalesce.rx_max_coalesced_frames_high = shared_timer->threshold_high;
+- temp_et_coalesce.rx_coalesce_usecs_low = shared_timer->timer_in_use_min;
++ temp_et_coalesce.rx_coalesce_usecs_low = shared_timer->timer_in_use_min;
+ temp_et_coalesce.rx_coalesce_usecs_high = shared_timer->timer_in_use_max;
+ if (nesadapter->et_use_adaptive_rx_coalesce) {
+ temp_et_coalesce.rx_coalesce_usecs_irq = shared_timer->timer_in_use;
+ }
+ spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
+- memcpy(et_coalesce, &temp_et_coalesce, sizeof(*et_coalesce));
++ memcpy(et_coalesce, &temp_et_coalesce, sizeof(*et_coalesce));
+ return 0;
+ }
- /*
-@@ -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 */
+@@ -1403,30 +1378,38 @@ static int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd
+ u16 phy_data;
--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;
+ et_cmd->duplex = DUPLEX_FULL;
+- et_cmd->port = PORT_MII;
++ et_cmd->port = PORT_MII;
++
+ if (nesadapter->OneG_Mode) {
+- et_cmd->supported = SUPPORTED_1000baseT_Full|SUPPORTED_Autoneg;
+- et_cmd->advertising = ADVERTISED_1000baseT_Full|ADVERTISED_Autoneg;
+ et_cmd->speed = SPEED_1000;
+- nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[nesdev->mac_index],
+- &phy_data);
+- if (phy_data&0x1000) {
+- et_cmd->autoneg = AUTONEG_ENABLE;
++ if (nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_PUMA_1G) {
++ et_cmd->supported = SUPPORTED_1000baseT_Full;
++ et_cmd->advertising = ADVERTISED_1000baseT_Full;
++ et_cmd->autoneg = AUTONEG_DISABLE;
++ et_cmd->transceiver = XCVR_INTERNAL;
++ et_cmd->phy_address = nesdev->mac_index;
+ } else {
+- et_cmd->autoneg = AUTONEG_DISABLE;
++ et_cmd->supported = SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg;
++ et_cmd->advertising = ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg;
++ nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[nesdev->mac_index], &phy_data);
++ if (phy_data & 0x1000)
++ et_cmd->autoneg = AUTONEG_ENABLE;
++ else
++ et_cmd->autoneg = AUTONEG_DISABLE;
++ et_cmd->transceiver = XCVR_EXTERNAL;
++ et_cmd->phy_address = nesadapter->phy_index[nesdev->mac_index];
}
- }
- return ide_stopped;
- }
+- et_cmd->transceiver = XCVR_EXTERNAL;
+- et_cmd->phy_address = nesadapter->phy_index[nesdev->mac_index];
+ } else {
+- if (nesadapter->phy_type[nesvnic->logical_port] == NES_PHY_TYPE_IRIS) {
++ if ((nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_IRIS) ||
++ (nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_ARGUS)) {
+ et_cmd->transceiver = XCVR_EXTERNAL;
+- et_cmd->port = PORT_FIBRE;
+- et_cmd->supported = SUPPORTED_FIBRE;
++ et_cmd->port = PORT_FIBRE;
++ et_cmd->supported = SUPPORTED_FIBRE;
+ et_cmd->advertising = ADVERTISED_FIBRE;
+ et_cmd->phy_address = nesadapter->phy_index[nesdev->mac_index];
+ } else {
+ et_cmd->transceiver = XCVR_INTERNAL;
+- et_cmd->supported = SUPPORTED_10000baseT_Full;
++ et_cmd->supported = SUPPORTED_10000baseT_Full;
+ et_cmd->advertising = ADVERTISED_10000baseT_Full;
+ et_cmd->phy_address = nesdev->mac_index;
+ }
+@@ -1449,14 +1432,15 @@ static int nes_netdev_set_settings(struct net_device *netdev, struct ethtool_cmd
+ struct nes_adapter *nesadapter = nesdev->nesadapter;
+ u16 phy_data;
--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);
- }
+- if (nesadapter->OneG_Mode) {
++ if ((nesadapter->OneG_Mode) &&
++ (nesadapter->phy_type[nesdev->mac_index] != NES_PHY_TYPE_PUMA_1G)) {
+ nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[nesdev->mac_index],
+ &phy_data);
+ if (et_cmd->autoneg) {
+ /* Turn on Full duplex, Autoneg, and restart autonegotiation */
+ phy_data |= 0x1300;
+ } else {
+- // Turn off autoneg
++ /* Turn off autoneg */
+ phy_data &= ~0x1000;
+ }
+ nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[nesdev->mac_index],
+@@ -1487,6 +1471,8 @@ static struct ethtool_ops nes_ethtool_ops = {
+ .set_sg = ethtool_op_set_sg,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = ethtool_op_set_tso,
++ .get_flags = ethtool_op_get_flags,
++ .set_flags = ethtool_op_set_flags,
+ };
--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)
+
+@@ -1640,27 +1626,34 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
+ list_add_tail(&nesvnic->list, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]);
+
+ if ((nesdev->netdev_count == 0) &&
+- (PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index)) {
+- nes_debug(NES_DBG_INIT, "Setting up PHY interrupt mask. Using register index 0x%04X\n",
+- NES_IDX_PHY_PCS_CONTROL_STATUS0+(0x200*(nesvnic->logical_port&1)));
++ ((PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index) ||
++ ((nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_PUMA_1G) &&
++ (((PCI_FUNC(nesdev->pcidev->devfn) == 1) && (nesdev->mac_index == 2)) ||
++ ((PCI_FUNC(nesdev->pcidev->devfn) == 2) && (nesdev->mac_index == 1)))))) {
++ /*
++ * nes_debug(NES_DBG_INIT, "Setting up PHY interrupt mask. Using register index 0x%04X\n",
++ * NES_IDX_PHY_PCS_CONTROL_STATUS0 + (0x200 * (nesvnic->logical_port & 1)));
++ */
+ u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
+- (0x200*(nesvnic->logical_port&1)));
+- u32temp |= 0x00200000;
+- nes_write_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
+- (0x200*(nesvnic->logical_port&1)), u32temp);
++ (0x200 * (nesdev->mac_index & 1)));
++ if (nesdev->nesadapter->phy_type[nesdev->mac_index] != NES_PHY_TYPE_PUMA_1G) {
++ u32temp |= 0x00200000;
++ nes_write_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
++ (0x200 * (nesdev->mac_index & 1)), u32temp);
++ }
++
+ u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
+- (0x200*(nesvnic->logical_port&1)) );
++ (0x200 * (nesdev->mac_index & 1)));
++
+ if ((u32temp&0x0f1f0000) == 0x0f0f0000) {
+- if (nesdev->nesadapter->phy_type[nesvnic->logical_port] == NES_PHY_TYPE_IRIS) {
++ if (nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_IRIS) {
+ nes_init_phy(nesdev);
+- nes_read_10G_phy_reg(nesdev, 1,
+- nesdev->nesadapter->phy_index[nesvnic->logical_port]);
++ nes_read_10G_phy_reg(nesdev, nesdev->nesadapter->phy_index[nesdev->mac_index], 1, 1);
+ temp_phy_data = (u16)nes_read_indexed(nesdev,
+ NES_IDX_MAC_MDIO_CONTROL);
+ u32temp = 20;
+ do {
+- nes_read_10G_phy_reg(nesdev, 1,
+- nesdev->nesadapter->phy_index[nesvnic->logical_port]);
++ nes_read_10G_phy_reg(nesdev, nesdev->nesadapter->phy_index[nesdev->mac_index], 1, 1);
+ phy_data = (u16)nes_read_indexed(nesdev,
+ NES_IDX_MAC_MDIO_CONTROL);
+ if ((phy_data == temp_phy_data) || (!(--u32temp)))
+@@ -1677,6 +1670,14 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
+ nes_debug(NES_DBG_INIT, "The Link is UP!!.\n");
+ nesvnic->linkup = 1;
+ }
++ } else if (nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_PUMA_1G) {
++ nes_debug(NES_DBG_INIT, "mac_index=%d, logical_port=%d, u32temp=0x%04X, PCI_FUNC=%d\n",
++ nesdev->mac_index, nesvnic->logical_port, u32temp, PCI_FUNC(nesdev->pcidev->devfn));
++ if (((nesdev->mac_index < 2) && ((u32temp&0x01010000) == 0x01010000)) ||
++ ((nesdev->mac_index > 1) && ((u32temp&0x02020000) == 0x02020000))) {
++ nes_debug(NES_DBG_INIT, "The Link is UP!!.\n");
++ nesvnic->linkup = 1;
++ }
+ }
+ /* clear the MAC interrupt status, assumes direct logical to physical mapping */
+ u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index));
+diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c
+index c4ec6ac..fe83d1b 100644
+--- a/drivers/infiniband/hw/nes/nes_utils.c
++++ b/drivers/infiniband/hw/nes/nes_utils.c
+@@ -444,15 +444,13 @@ void nes_read_1G_phy_reg(struct nes_device *nesdev, u8 phy_reg, u8 phy_addr, u16
+ /**
+ * nes_write_10G_phy_reg
+ */
+-void nes_write_10G_phy_reg(struct nes_device *nesdev, u16 phy_reg,
+- u8 phy_addr, u16 data)
++void nes_write_10G_phy_reg(struct nes_device *nesdev, u16 phy_addr, u8 dev_addr, u16 phy_reg,
++ u16 data)
{
- struct cdrom_info *info = drive->driver_data;
+- u32 dev_addr;
+ u32 port_addr;
+ u32 u32temp;
+ u32 counter;
-@@ -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);
- }
+- dev_addr = 1;
+ port_addr = phy_addr;
--/* 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)
+ /* set address */
+@@ -492,14 +490,12 @@ void nes_write_10G_phy_reg(struct nes_device *nesdev, u16 phy_reg,
+ * This routine only issues the read, the data must be read
+ * separately.
+ */
+-void nes_read_10G_phy_reg(struct nes_device *nesdev, u16 phy_reg, u8 phy_addr)
++void nes_read_10G_phy_reg(struct nes_device *nesdev, u8 phy_addr, u8 dev_addr, u16 phy_reg)
{
- 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;
+- u32 dev_addr;
+ u32 port_addr;
+ u32 u32temp;
+ u32 counter;
-- /* 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)
+- dev_addr = 1;
+ port_addr = phy_addr;
- 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]);
+ /* set address */
+@@ -566,7 +562,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__);
- len = lowcyl + (256 * highcyl);
+ return cqp_request;
+ }
+@@ -660,7 +656,9 @@ int nes_arp_table(struct nes_device *nesdev, u32 ip_addr, u8 *mac_addr, u32 acti
-@@ -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;
+ /* DELETE or RESOLVE */
+ if (arp_index == nesadapter->arp_table_size) {
+- nes_debug(NES_DBG_NETDEV, "mac address not in ARP table - cannot delete or resolve\n");
++ nes_debug(NES_DBG_NETDEV, "MAC for " NIPQUAD_FMT " not in ARP table - cannot %s\n",
++ HIPQUAD(ip_addr),
++ action == NES_ARP_RESOLVE ? "resolve" : "delete");
+ return -1;
}
- /*
-@@ -1260,9 +1164,6 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
- } else
- cd->dma = drive->using_dma;
+diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
+index a651e9d..99b3c4a 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;
-- /* Clear the local sector buffer. */
-- cd->nsectors_buffered = 0;
--
- if (write)
- cd->devinfo.media_written = 1;
++static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev);
-@@ -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)
- */
+ /**
+ * 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;
- 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;
+ 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:
+@@ -1262,7 +1266,7 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
+ sq_size = init_attr->cap.max_send_wr;
+ rq_size = init_attr->cap.max_recv_wr;
+
+- // check if the encoded sizes are OK or not...
++ /* check if the encoded sizes are OK or not... */
+ sq_encoded_size = nes_get_encoded_size(&sq_size);
+ rq_encoded_size = nes_get_encoded_size(&rq_size);
+
+@@ -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);
}
- 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);
+ } 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);
}
-- 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);
+ opcode |= NES_CQP_CQ_4KB_CHUNK;
}
+@@ -1972,7 +1976,7 @@ static int nes_destroy_cq(struct ib_cq *ib_cq)
- /* 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;
+ if (nescq->cq_mem_size)
+ pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size,
+- (void *)nescq->hw_cq.cq_vbase, nescq->hw_cq.cq_pbase);
++ nescq->hw_cq.cq_vbase, nescq->hw_cq.cq_pbase);
+ kfree(nescq);
-- 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);
+ return ret;
+@@ -2373,7 +2377,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+ u8 single_page = 1;
+ u8 stag_key;
+
+- region = ib_umem_get(pd->uobject->context, start, length, acc);
++ region = ib_umem_get(pd->uobject->context, start, length, acc, 0);
+ if (IS_ERR(region)) {
+ return (struct ib_mr *)region;
}
+@@ -2653,10 +2657,10 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
-@@ -1677,7 +1578,7 @@ static struct cdrom_device_ops ide_cdrom_dops = {
- .generic_packet = ide_cdrom_packet,
- };
+ 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);
--static int ide_cdrom_register (ide_drive_t *drive, int nslots)
-+static int ide_cdrom_register(ide_drive_t *drive, int nslots)
+ 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 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)
- }
+ 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;
- static
--int ide_cdrom_probe_capabilities (ide_drive_t *drive)
-+int ide_cdrom_probe_capabilities(ide_drive_t *drive)
+ 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 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;
- }
+ 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;
-@@ -1946,7 +1847,7 @@ static unsigned int ide_cd_flags(struct hd_driveid *id)
+ 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
--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);
+-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);
- /*
- * set correct block size
-@@ -1989,7 +1890,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
- drive->dsc_overlap = (drive->next != drive);
+-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
+ };
- 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;
+@@ -3602,6 +3610,12 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
+ while (cqe_count < num_entries) {
+ if (le32_to_cpu(nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) &
+ NES_CQE_VALID) {
++ /*
++ * Make sure we read CQ entry contents *after*
++ * we've checked the valid bit.
++ */
++ rmb();
++
+ cqe = nescq->hw_cq.cq_vbase[head];
+ nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0;
+ u32temp = le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]);
+@@ -3778,7 +3792,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 +3887,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 +3909,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;
-
-- return capacity * sectors_per_frame;
--}
--#endif
+- 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..9044f88 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib.h
++++ b/drivers/infiniband/ulp/ipoib/ipoib.h
+@@ -56,11 +56,11 @@
+ /* constants */
+
+ enum {
+- IPOIB_PACKET_SIZE = 2048,
+- IPOIB_BUF_SIZE = IPOIB_PACKET_SIZE + IB_GRH_BYTES,
-
- 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;
+ IPOIB_ENCAP_LEN = 4,
-- 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 *);
++ IPOIB_UD_HEAD_SIZE = IB_GRH_BYTES + IPOIB_ENCAP_LEN,
++ IPOIB_UD_RX_SG = 2, /* max buffer needed for 4K mtu */
++
+ IPOIB_CM_MTU = 0x10000 - 0x10, /* padding to align header to 16 */
+ IPOIB_CM_BUF_SIZE = IPOIB_CM_MTU + IPOIB_ENCAP_LEN,
+ IPOIB_CM_HEAD_SIZE = IPOIB_CM_BUF_SIZE % PAGE_SIZE,
+@@ -87,6 +87,7 @@ enum {
+ IPOIB_MCAST_STARTED = 8,
+ IPOIB_FLAG_ADMIN_CM = 9,
+ IPOIB_FLAG_UMCAST = 10,
++ IPOIB_FLAG_CSUM = 11,
- #ifdef CONFIG_IDE_PROC_FS
-+static sector_t ide_cdrom_capacity(ide_drive_t *drive)
-+{
-+ unsigned long capacity, sectors_per_frame;
+ IPOIB_MAX_BACKOFF_SECONDS = 16,
+
+@@ -94,6 +95,8 @@ enum {
+ IPOIB_MCAST_FLAG_SENDONLY = 1,
+ IPOIB_MCAST_FLAG_BUSY = 2, /* joining or already joined */
+ IPOIB_MCAST_FLAG_ATTACHED = 3,
+
-+ if (cdrom_read_capacity(drive, &capacity, §ors_per_frame, NULL))
-+ return 0;
++ MAX_SEND_CQE = 16,
+ };
+
+ #define IPOIB_OP_RECV (1ul << 31)
+@@ -138,7 +141,7 @@ struct ipoib_mcast {
+
+ struct ipoib_rx_buf {
+ struct sk_buff *skb;
+- u64 mapping;
++ u64 mapping[IPOIB_UD_RX_SG];
+ };
+
+ struct ipoib_tx_buf {
+@@ -241,6 +244,11 @@ struct ipoib_cm_dev_priv {
+ int num_frags;
+ };
+
++struct ipoib_ethtool_st {
++ u16 coalesce_usecs;
++ u16 max_coalesced_frames;
++};
+
-+ return capacity * sectors_per_frame;
-+}
+ /*
+ * Device private locking: tx_lock protects members used in TX fast
+ * path (and we use LLTX so upper layers don't do extra locking).
+@@ -279,7 +287,8 @@ struct ipoib_dev_priv {
+ u16 pkey_index;
+ struct ib_pd *pd;
+ struct ib_mr *mr;
+- struct ib_cq *cq;
++ struct ib_cq *recv_cq;
++ struct ib_cq *send_cq;
+ struct ib_qp *qp;
+ u32 qkey;
+
+@@ -288,6 +297,7 @@ struct ipoib_dev_priv {
+
+ unsigned int admin_mtu;
+ unsigned int mcast_mtu;
++ unsigned int max_ib_mtu;
+
+ struct ipoib_rx_buf *rx_ring;
+
+@@ -298,6 +308,10 @@ struct ipoib_dev_priv {
+ struct ib_sge tx_sge[MAX_SKB_FRAGS + 1];
+ struct ib_send_wr tx_wr;
+ unsigned tx_outstanding;
++ struct ib_wc send_wc[MAX_SEND_CQE];
+
- 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;
++ struct ib_recv_wr rx_wr;
++ struct ib_sge rx_sge[IPOIB_UD_RX_SG];
-- 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);
- }
+ struct ib_wc ibwc[IPOIB_NUM_WC];
- static ide_proc_entry_t idecd_proc[] = {
-@@ -2080,20 +1976,17 @@ static ide_driver_t ide_cdrom_driver = {
+@@ -318,6 +332,8 @@ struct ipoib_dev_priv {
+ struct dentry *mcg_dentry;
+ struct dentry *path_dentry;
#endif
++ int hca_caps;
++ struct ipoib_ethtool_st ethtool;
};
--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;
+ struct ipoib_ah {
+@@ -358,6 +374,14 @@ struct ipoib_neigh {
+ struct list_head list;
+ };
-- if (!(info = ide_cd_get(disk)))
-+ info = ide_cd_get(disk);
-+ if (!info)
- return -ENXIO;
++#define IPOIB_UD_MTU(ib_mtu) (ib_mtu - IPOIB_ENCAP_LEN)
++#define IPOIB_UD_BUF_SIZE(ib_mtu) (ib_mtu + IB_GRH_BYTES)
++
++static inline int ipoib_ud_need_sg(unsigned int ib_mtu)
++{
++ return IPOIB_UD_BUF_SIZE(ib_mtu) > PAGE_SIZE;
++}
++
+ /*
+ * We stash a pointer to our private neighbour information after our
+ * hardware address in neigh->ha. The ALIGN() expression here makes
+@@ -458,6 +482,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);
-- 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);
++void ipoib_set_ethtool_ops(struct net_device *dev);
++
+ #ifdef CONFIG_INFINIBAND_IPOIB_CM
- if (rc < 0)
- ide_cd_put(info);
-@@ -2101,12 +1994,12 @@ static int idecd_open(struct inode * inode, struct file * file)
- return rc;
- }
+ #define IPOIB_FLAGS_RC 0x80
+@@ -640,7 +666,6 @@ static inline int ipoib_register_debugfs(void) { return 0; }
+ static inline void ipoib_unregister_debugfs(void) { }
+ #endif
--static int idecd_release(struct inode * inode, struct file * file)
-+static int idecd_release(struct inode *inode, struct file *file)
+-
+ #define ipoib_printk(level, priv, format, arg...) \
+ printk(level "%s: " format, ((struct ipoib_dev_priv *) priv)->dev->name , ## arg)
+ #define ipoib_warn(priv, format, arg...) \
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+index 2490b2d..97e67d3 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+@@ -249,8 +249,8 @@ static struct ib_qp *ipoib_cm_create_rx_qp(struct net_device *dev,
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+ struct ib_qp_init_attr attr = {
+ .event_handler = ipoib_cm_rx_event_handler,
+- .send_cq = priv->cq, /* For drain WR */
+- .recv_cq = priv->cq,
++ .send_cq = priv->recv_cq, /* For drain WR */
++ .recv_cq = priv->recv_cq,
+ .srq = priv->cm.srq,
+ .cap.max_send_wr = 1, /* For drain WR */
+ .cap.max_send_sge = 1, /* FIXME: 0 Seems not to work */
+@@ -951,8 +951,8 @@ static struct ib_qp *ipoib_cm_create_tx_qp(struct net_device *dev, struct ipoib_
{
- 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);
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+ struct ib_qp_init_attr attr = {
+- .send_cq = priv->cq,
+- .recv_cq = priv->cq,
++ .send_cq = priv->recv_cq,
++ .recv_cq = priv->recv_cq,
+ .srq = priv->cm.srq,
+ .cap.max_send_wr = ipoib_sendq_size,
+ .cap.max_send_sge = 1,
+@@ -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;
+ }
- ide_cd_put(info);
+@@ -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;
+ }
-@@ -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;
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
+new file mode 100644
+index 0000000..10279b7
+--- /dev/null
++++ b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
+@@ -0,0 +1,99 @@
++/*
++ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses. You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ * Redistribution and use in source and binary forms, with or
++ * without modification, are permitted provided that the following
++ * conditions are met:
++ *
++ * - Redistributions of source code must retain the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer.
++ *
++ * - Redistributions in binary form must reproduce the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer in the documentation and/or other materials
++ * provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <linux/kernel.h>
++#include <linux/ethtool.h>
++#include <linux/netdevice.h>
++
++#include "ipoib.h"
++
++static void ipoib_get_drvinfo(struct net_device *netdev,
++ struct ethtool_drvinfo *drvinfo)
++{
++ strncpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver) - 1);
++}
++
++static int ipoib_get_coalesce(struct net_device *dev,
++ struct ethtool_coalesce *coal)
++{
++ struct ipoib_dev_priv *priv = netdev_priv(dev);
++
++ coal->rx_coalesce_usecs = priv->ethtool.coalesce_usecs;
++ coal->tx_coalesce_usecs = priv->ethtool.coalesce_usecs;
++ coal->rx_max_coalesced_frames = priv->ethtool.max_coalesced_frames;
++ coal->tx_max_coalesced_frames = priv->ethtool.max_coalesced_frames;
++
++ return 0;
++}
++
++static int ipoib_set_coalesce(struct net_device *dev,
++ struct ethtool_coalesce *coal)
++{
++ struct ipoib_dev_priv *priv = netdev_priv(dev);
++ int ret;
++
++ /*
++ * Since IPoIB uses a single CQ for both rx and tx, we assume
++ * that rx params dictate the configuration. These values are
++ * saved in the private data and returned when ipoib_get_coalesce()
++ * is called.
++ */
++ if (coal->rx_coalesce_usecs > 0xffff ||
++ coal->rx_max_coalesced_frames > 0xffff)
++ return -EINVAL;
++
++ ret = ib_modify_cq(priv->recv_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..97b815c 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+@@ -39,6 +39,8 @@
+ #include <linux/dma-mapping.h>
- init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
+ #include <rdma/ib_cache.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
-@@ -2147,12 +2040,12 @@ static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg)
- return stat;
+ #include "ipoib.h"
- 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;
+@@ -87,28 +89,59 @@ void ipoib_free_ah(struct kref *kref)
+ spin_unlock_irqrestore(&priv->lock, flags);
}
--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)
++static void ipoib_ud_dma_unmap_rx(struct ipoib_dev_priv *priv,
++ u64 mapping[IPOIB_UD_RX_SG])
++{
++ if (ipoib_ud_need_sg(priv->max_ib_mtu)) {
++ ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_UD_HEAD_SIZE,
++ DMA_FROM_DEVICE);
++ ib_dma_unmap_page(priv->ca, mapping[1], PAGE_SIZE,
++ DMA_FROM_DEVICE);
++ } else
++ ib_dma_unmap_single(priv->ca, mapping[0],
++ IPOIB_UD_BUF_SIZE(priv->max_ib_mtu),
++ DMA_FROM_DEVICE);
++}
++
++static void ipoib_ud_skb_put_frags(struct ipoib_dev_priv *priv,
++ struct sk_buff *skb,
++ unsigned int length)
++{
++ if (ipoib_ud_need_sg(priv->max_ib_mtu)) {
++ skb_frag_t *frag = &skb_shinfo(skb)->frags[0];
++ unsigned int size;
++ /*
++ * There is only two buffers needed for max_payload = 4K,
++ * first buf size is IPOIB_UD_HEAD_SIZE
++ */
++ skb->tail += IPOIB_UD_HEAD_SIZE;
++ skb->len += length;
++
++ size = length - IPOIB_UD_HEAD_SIZE;
++
++ frag->size = size;
++ skb->data_len += size;
++ skb->truesize += size;
++ } else
++ skb_put(skb, length);
++
++}
++
+ static int ipoib_ib_post_receive(struct net_device *dev, int id)
{
- struct block_device *bdev = inode->i_bdev;
-@@ -2160,13 +2053,13 @@ static int idecd_ioctl (struct inode *inode, struct file *file,
- int err;
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+- struct ib_sge list;
+- struct ib_recv_wr param;
+ struct ib_recv_wr *bad_wr;
+ int ret;
- 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;
-- }
-+ }
+- list.addr = priv->rx_ring[id].mapping;
+- list.length = IPOIB_BUF_SIZE;
+- list.lkey = priv->mr->lkey;
++ priv->rx_wr.wr_id = id | IPOIB_OP_RECV;
++ priv->rx_sge[0].addr = priv->rx_ring[id].mapping[0];
++ priv->rx_sge[1].addr = priv->rx_ring[id].mapping[1];
+
+- param.next = NULL;
+- param.wr_id = id | IPOIB_OP_RECV;
+- param.sg_list = &list;
+- param.num_sge = 1;
- 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)
+- ret = ib_post_recv(priv->qp, ¶m, &bad_wr);
++ ret = ib_post_recv(priv->qp, &priv->rx_wr, &bad_wr);
+ if (unlikely(ret)) {
+ ipoib_warn(priv, "receive failed for buf %d (%d)\n", id, ret);
+- ib_dma_unmap_single(priv->ca, priv->rx_ring[id].mapping,
+- IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
++ ipoib_ud_dma_unmap_rx(priv, priv->rx_ring[id].mapping);
+ dev_kfree_skb_any(priv->rx_ring[id].skb);
+ priv->rx_ring[id].skb = NULL;
+ }
+@@ -116,15 +149,21 @@ static int ipoib_ib_post_receive(struct net_device *dev, int id)
+ return ret;
}
- 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
- };
+-static int ipoib_alloc_rx_skb(struct net_device *dev, int id)
++static struct sk_buff *ipoib_alloc_rx_skb(struct net_device *dev, int id)
+ {
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+ struct sk_buff *skb;
+- u64 addr;
++ int buf_size;
++ u64 *mapping;
++
++ if (ipoib_ud_need_sg(priv->max_ib_mtu))
++ buf_size = IPOIB_UD_HEAD_SIZE;
++ else
++ buf_size = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu);
- /* options */
--static char *ignore = NULL;
-+static char *ignore;
+- skb = dev_alloc_skb(IPOIB_BUF_SIZE + 4);
+- if (!skb)
+- return -ENOMEM;
++ skb = dev_alloc_skb(buf_size + 4);
++ if (unlikely(!skb))
++ return NULL;
- 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 {
+ /*
+ * IB will leave a 40 byte gap for a GRH and IPoIB adds a 4 byte
+@@ -133,17 +172,32 @@ static int ipoib_alloc_rx_skb(struct net_device *dev, int id)
+ */
+ skb_reserve(skb, 4);
- struct atapi_toc *toc;
+- addr = ib_dma_map_single(priv->ca, skb->data, IPOIB_BUF_SIZE,
+- DMA_FROM_DEVICE);
+- if (unlikely(ib_dma_mapping_error(priv->ca, addr))) {
+- dev_kfree_skb_any(skb);
+- return -EIO;
++ mapping = priv->rx_ring[id].mapping;
++ mapping[0] = ib_dma_map_single(priv->ca, skb->data, buf_size,
++ DMA_FROM_DEVICE);
++ if (unlikely(ib_dma_mapping_error(priv->ca, mapping[0])))
++ goto error;
++
++ if (ipoib_ud_need_sg(priv->max_ib_mtu)) {
++ struct page *page = alloc_page(GFP_ATOMIC);
++ if (!page)
++ goto partial_error;
++ skb_fill_page_desc(skb, 0, page, 0, PAGE_SIZE);
++ mapping[1] =
++ ib_dma_map_page(priv->ca, skb_shinfo(skb)->frags[0].page,
++ 0, PAGE_SIZE, DMA_FROM_DEVICE);
++ if (unlikely(ib_dma_mapping_error(priv->ca, mapping[1])))
++ goto partial_error;
+ }
-- 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 @@
+- priv->rx_ring[id].skb = skb;
+- priv->rx_ring[id].mapping = addr;
++ priv->rx_ring[id].skb = skb;
++ return skb;
- #define IDEDISK_VERSION "1.18"
+- return 0;
++partial_error:
++ ib_dma_unmap_single(priv->ca, mapping[0], buf_size, DMA_FROM_DEVICE);
++error:
++ dev_kfree_skb_any(skb);
++ return NULL;
+ }
--//#define DEBUG
--
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/string.h>
-@@ -88,7 +86,7 @@ static void ide_disk_put(struct ide_disk_obj *idkp)
- *
- * It is called only once for each drive.
- */
--static int lba_capacity_is_ok (struct hd_driveid *id)
-+static int lba_capacity_is_ok(struct hd_driveid *id)
- {
- unsigned long lba_sects, chs_sects, head, tail;
+ static int ipoib_ib_post_receives(struct net_device *dev)
+@@ -152,7 +206,7 @@ static int ipoib_ib_post_receives(struct net_device *dev)
+ int i;
-@@ -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;
+ for (i = 0; i < ipoib_recvq_size; ++i) {
+- if (ipoib_alloc_rx_skb(dev, i)) {
++ if (!ipoib_alloc_rx_skb(dev, i)) {
+ ipoib_warn(priv, "failed to allocate receive buffer %d\n", i);
+ return -ENOMEM;
}
- } 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
- */
+@@ -170,7 +224,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+ unsigned int wr_id = wc->wr_id & ~IPOIB_OP_RECV;
+ struct sk_buff *skb;
+- u64 addr;
++ u64 mapping[IPOIB_UD_RX_SG];
--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);
+ ipoib_dbg_data(priv, "recv completion: id %d, status: %d\n",
+ wr_id, wc->status);
+@@ -182,15 +236,13 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
+ }
+
+ skb = priv->rx_ring[wr_id].skb;
+- addr = priv->rx_ring[wr_id].mapping;
+
+ if (unlikely(wc->status != IB_WC_SUCCESS)) {
+ if (wc->status != IB_WC_WR_FLUSH_ERR)
+ ipoib_warn(priv, "failed recv event "
+ "(status=%d, wrid=%d vend_err %x)\n",
+ wc->status, wr_id, wc->vendor_err);
+- ib_dma_unmap_single(priv->ca, addr,
+- IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
++ ipoib_ud_dma_unmap_rx(priv, priv->rx_ring[wr_id].mapping);
+ dev_kfree_skb_any(skb);
+ priv->rx_ring[wr_id].skb = NULL;
+ return;
+@@ -203,11 +255,14 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
+ if (wc->slid == priv->local_lid && wc->src_qp == priv->qp->qp_num)
+ goto repost;
-@@ -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;
++ memcpy(mapping, priv->rx_ring[wr_id].mapping,
++ IPOIB_UD_RX_SG * sizeof *mapping);
++
/*
-@@ -479,7 +480,7 @@ static void init_idedisk_capacity (ide_drive_t *drive)
+ * If we can't allocate a new RX buffer, dump
+ * this packet and reuse the old buffer.
+ */
+- if (unlikely(ipoib_alloc_rx_skb(dev, wr_id))) {
++ if (unlikely(!ipoib_alloc_rx_skb(dev, wr_id))) {
+ ++dev->stats.rx_dropped;
+ goto repost;
}
- }
+@@ -215,9 +270,9 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
+ ipoib_dbg_data(priv, "received %d bytes, SLID 0x%04x\n",
+ wc->byte_len, wc->slid);
--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;
+- ib_dma_unmap_single(priv->ca, addr, IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
++ ipoib_ud_dma_unmap_rx(priv, mapping);
++ ipoib_ud_skb_put_frags(priv, skb, wc->byte_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);
- }
+- skb_put(skb, wc->byte_len);
+ skb_pull(skb, IB_GRH_BYTES);
- 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;
+ skb->protocol = ((struct ipoib_header *) skb->data)->proto;
+@@ -231,6 +286,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);
-- 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));
+ repost:
+@@ -245,29 +304,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;
+
-+ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
- }
++ 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;
--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;
+- 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;
-- 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;
+ 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;
}
-- 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);
-+}
+ return 0;
-- 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);
+ 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;
}
- 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;
+@@ -277,12 +344,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;
-- ide_init_drive_cmd (&rq);
-+ ide_init_drive_cmd(&rq);
- rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
+- 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;
- 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;
+ 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);
+ }
}
+@@ -292,7 +364,6 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+ unsigned int wr_id = wc->wr_id;
+ struct ipoib_tx_buf *tx_req;
+- unsigned long flags;
-@@ -706,7 +707,7 @@ static int write_cache(ide_drive_t *drive, int arg)
- return err;
+ ipoib_dbg_data(priv, "send completion: id %d, status: %d\n",
+ wr_id, wc->status);
+@@ -312,13 +383,11 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
+
+ dev_kfree_skb_any(tx_req->skb);
+
+- spin_lock_irqsave(&priv->tx_lock, flags);
+ ++priv->tx_tail;
+ if (unlikely(--priv->tx_outstanding == ipoib_sendq_size >> 1) &&
+ netif_queue_stopped(dev) &&
+ test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
+ netif_wake_queue(dev);
+- spin_unlock_irqrestore(&priv->tx_lock, flags);
+
+ if (wc->status != IB_WC_SUCCESS &&
+ wc->status != IB_WC_WR_FLUSH_ERR)
+@@ -327,6 +396,17 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
+ wc->status, wr_id, wc->vendor_err);
}
--static int do_idedisk_flushcache (ide_drive_t *drive)
-+static int do_idedisk_flushcache(ide_drive_t *drive)
++static int poll_tx(struct ipoib_dev_priv *priv)
++{
++ int n, i;
++
++ n = ib_poll_cq(priv->send_cq, MAX_SEND_CQE, priv->send_wc);
++ for (i = 0; i < n; ++i)
++ ipoib_ib_handle_tx_wc(priv->dev, priv->send_wc + i);
++
++ return n == MAX_SEND_CQE;
++}
++
+ int ipoib_poll(struct napi_struct *napi, int budget)
{
- ide_task_t args;
+ struct ipoib_dev_priv *priv = container_of(napi, struct ipoib_dev_priv, napi);
+@@ -342,7 +422,7 @@ poll_more:
+ int max = (budget - done);
-@@ -719,7 +720,7 @@ static int do_idedisk_flushcache (ide_drive_t *drive)
- return ide_no_data_taskfile(drive, &args);
- }
+ t = min(IPOIB_NUM_WC, max);
+- n = ib_poll_cq(priv->cq, t, priv->ibwc);
++ n = ib_poll_cq(priv->recv_cq, t, priv->ibwc);
--static int set_acoustic (ide_drive_t *drive, int arg)
-+static int set_acoustic(ide_drive_t *drive, int arg)
- {
- ide_task_t args;
+ for (i = 0; i < n; i++) {
+ struct ib_wc *wc = priv->ibwc + i;
+@@ -353,12 +433,8 @@ poll_more:
+ ipoib_cm_handle_rx_wc(dev, wc);
+ else
+ ipoib_ib_handle_rx_wc(dev, wc);
+- } else {
+- if (wc->wr_id & IPOIB_OP_CM)
+- ipoib_cm_handle_tx_wc(dev, wc);
+- else
+- ipoib_ib_handle_tx_wc(dev, wc);
+- }
++ } else
++ ipoib_cm_handle_tx_wc(priv->dev, wc);
+ }
-@@ -753,7 +754,7 @@ static int set_lba_addressing(ide_drive_t *drive, int arg)
- return 0;
+ if (n != t)
+@@ -367,7 +443,7 @@ poll_more:
- 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)
+ if (done < budget) {
+ netif_rx_complete(dev, napi);
+- if (unlikely(ib_req_notify_cq(priv->cq,
++ if (unlikely(ib_req_notify_cq(priv->recv_cq,
+ IB_CQ_NEXT_COMP |
+ IB_CQ_REPORT_MISSED_EVENTS)) &&
+ netif_rx_reschedule(dev, napi))
+@@ -388,24 +464,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 hd_driveid *id = drive->id;
+ 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;
-- 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);
+- 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);
}
- #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)
+@@ -414,14 +506,30 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
{
- 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;
-- }
+ 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;
}
- (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);
+ ipoib_dbg_data(priv, "sending packet, length=%d address=%p qpn=0x%06x\n",
+@@ -442,10 +550,13 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
+ return;
}
-- 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);
++ 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);
+@@ -455,12 +566,16 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
- /* 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)
+ address->last_send = priv->tx_head;
+ ++priv->tx_head;
++ skb_orphan(skb);
- 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;
+ if (++priv->tx_outstanding == ipoib_sendq_size) {
+ ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n");
+ netif_stop_queue(dev);
+ }
}
-@@ -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 (unlikely(priv->tx_outstanding > MAX_SEND_CQE))
++ poll_tx(priv);
+ }
-- if (!(idkp = ide_disk_get(disk)))
-+ idkp = ide_disk_get(disk);
-+ if (idkp == NULL)
- return -ENXIO;
+ static void __ipoib_reap_ah(struct net_device *dev)
+@@ -540,7 +655,7 @@ static void ipoib_pkey_dev_check_presence(struct net_device *dev)
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+ u16 pkey_index = 0;
- drive = idkp->drive;
-@@ -1115,13 +1130,13 @@ static int idedisk_revalidate_disk(struct gendisk *disk)
+- 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);
+@@ -607,7 +722,7 @@ void ipoib_drain_cq(struct net_device *dev)
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+ int i, n;
+ do {
+- n = ib_poll_cq(priv->cq, IPOIB_NUM_WC, priv->ibwc);
++ n = ib_poll_cq(priv->recv_cq, IPOIB_NUM_WC, priv->ibwc);
+ for (i = 0; i < n; ++i) {
+ /*
+ * Convert any successful completions to flush
+@@ -622,14 +737,13 @@ void ipoib_drain_cq(struct net_device *dev)
+ ipoib_cm_handle_rx_wc(dev, priv->ibwc + i);
+ else
+ ipoib_ib_handle_rx_wc(dev, priv->ibwc + i);
+- } else {
+- if (priv->ibwc[i].wr_id & IPOIB_OP_CM)
+- ipoib_cm_handle_tx_wc(dev, priv->ibwc + i);
+- else
+- ipoib_ib_handle_tx_wc(dev, priv->ibwc + i);
+- }
++ } else
++ ipoib_cm_handle_tx_wc(dev, priv->ibwc + i);
+ }
+ } while (n == IPOIB_NUM_WC);
++
++ while (poll_tx(priv))
++ ; /* nothing */
}
- 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
- };
+ int ipoib_ib_dev_stop(struct net_device *dev, int flush)
+@@ -679,10 +793,8 @@ int ipoib_ib_dev_stop(struct net_device *dev, int flush)
+ rx_req = &priv->rx_ring[i];
+ if (!rx_req->skb)
+ continue;
+- ib_dma_unmap_single(priv->ca,
+- rx_req->mapping,
+- IPOIB_BUF_SIZE,
+- DMA_FROM_DEVICE);
++ ipoib_ud_dma_unmap_rx(priv,
++ priv->rx_ring[i].mapping);
+ dev_kfree_skb_any(rx_req->skb);
+ rx_req->skb = NULL;
+ }
+@@ -721,7 +833,7 @@ timeout:
+ msleep(1);
+ }
- MODULE_DESCRIPTION("ATA DISK Driver");
-@@ -1184,7 +1199,7 @@ failed:
- return -ENODEV;
- }
+- ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP);
++ ib_req_notify_cq(priv->recv_cq, IB_CQ_NEXT_COMP);
--static void __exit idedisk_exit (void)
-+static void __exit idedisk_exit(void)
- {
- driver_unregister(&idedisk_driver.gen_driver);
+ return 0;
}
-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)
+@@ -781,13 +893,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);
- speed = ide_max_dma_mode(drive);
+ /* 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..2442090 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
+@@ -195,7 +195,7 @@ static int ipoib_change_mtu(struct net_device *dev, int new_mtu)
+ return 0;
+ }
-- 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 (new_mtu > IPOIB_PACKET_SIZE - IPOIB_ENCAP_LEN)
++ if (new_mtu > IPOIB_UD_MTU(priv->max_ib_mtu))
+ return -EINVAL;
- 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)
+ priv->admin_mtu = new_mtu;
+@@ -359,8 +359,7 @@ void ipoib_flush_paths(struct net_device *dev)
+ spin_lock_irq(&priv->tx_lock);
+ spin_lock(&priv->lock);
--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 */
+- list_splice(&priv->path_list, &remove_list);
+- INIT_LIST_HEAD(&priv->path_list);
++ list_splice_init(&priv->path_list, &remove_list);
- /* 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
+ 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;
- /*
-- * 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)
- }
++ ipoib_set_ethtool_ops(dev);
++
+ netif_napi_add(dev, &priv->napi, ipoib_poll, 100);
- /*
-- * 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);
--}
--
+ dev->watchdog_timeo = HZ;
+@@ -970,10 +971,6 @@ static void ipoib_setup(struct net_device *dev)
+ NETIF_F_LLTX |
+ NETIF_F_HIGHDMA);
+
+- /* MTU will be reset when mcast join happens */
+- dev->mtu = IPOIB_PACKET_SIZE - IPOIB_ENCAP_LEN;
+- priv->mcast_mtu = priv->admin_mtu = dev->mtu;
-
--/*
- * 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)
+ memcpy(dev->broadcast, ipv4_bcast_addr, INFINIBAND_ALEN);
+
+ netif_carrier_off(dev);
+@@ -1105,6 +1102,8 @@ static struct net_device *ipoib_add_port(const char *format,
+ struct ib_device *hca, u8 port)
{
- 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;
- }
+ struct ipoib_dev_priv *priv;
++ struct ib_device_attr *device_attr;
++ struct ib_port_attr attr;
+ int result = -ENOMEM;
+
+ priv = ipoib_intf_alloc(format);
+@@ -1113,6 +1112,18 @@ static struct net_device *ipoib_add_port(const char *format,
+
+ SET_NETDEV_DEV(priv->dev, hca->dma_device);
+
++ if (!ib_query_port(hca, port, &attr))
++ priv->max_ib_mtu = ib_mtu_enum_to_int(attr.max_mtu);
++ else {
++ printk(KERN_WARNING "%s: ib_query_port %d failed\n",
++ hca->name, port);
++ goto device_init_failed;
++ }
++
++ /* MTU will be reset when mcast join happens */
++ priv->dev->mtu = IPOIB_UD_MTU(priv->max_ib_mtu);
++ priv->mcast_mtu = priv->admin_mtu = priv->dev->mtu;
++
+ result = ib_query_pkey(hca, port, 0, &priv->pkey);
+ if (result) {
+ printk(KERN_WARNING "%s: ib_query_pkey port %d failed (ret = %d)\n",
+@@ -1120,6 +1131,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 +1171,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));
--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;
+-
+ 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 +1188,9 @@ static struct net_device *ipoib_add_port(const char *format,
+ goto event_failed;
}
-- idefloppy_do_end_request(drive, 1, done >> 9);
-+ idefloppy_end_request(drive, 1, done >> 9);
++ 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",
+@@ -1262,7 +1298,8 @@ static int __init ipoib_init_module(void)
- 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);
+ ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size);
+ ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE);
+- ipoib_sendq_size = max(ipoib_sendq_size, IPOIB_MIN_QUEUE_SIZE);
++ ipoib_sendq_size = max(ipoib_sendq_size, max(2 * MAX_SEND_CQE,
++ IPOIB_MIN_QUEUE_SIZE));
+ #ifdef CONFIG_INFINIBAND_IPOIB_CM
+ ipoib_max_conn_qp = min(ipoib_max_conn_qp, IPOIB_CM_MAX_CONN_QP);
+ #endif
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+index 31a53c5..d00a2c1 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+@@ -567,8 +567,7 @@ void ipoib_mcast_join_task(struct work_struct *work)
+ return;
}
- }
--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;
+- priv->mcast_mtu = ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu) -
+- IPOIB_ENCAP_LEN;
++ priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu));
- while ((bio = rq->bio) != NULL)
-- idefloppy_do_end_request(drive, 1, 0);
-+ idefloppy_end_request(drive, 1, 0);
- }
+ if (!ipoib_cm_admin_enabled(dev))
+ dev->mtu = min(priv->mcast_mtu, priv->admin_mtu);
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+index a3aeb91..c1e7ece 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+@@ -150,7 +150,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
+ .max_send_wr = ipoib_sendq_size,
+ .max_recv_wr = ipoib_recvq_size,
+ .max_send_sge = 1,
+- .max_recv_sge = 1
++ .max_recv_sge = IPOIB_UD_RX_SG
+ },
+ .sq_sig_type = IB_SIGNAL_ALL_WR,
+ .qp_type = IB_QPT_UD
+@@ -171,26 +171,36 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
+ goto out_free_pd;
+ }
- /*
-@@ -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);
- }
+- size = ipoib_sendq_size + ipoib_recvq_size + 1;
++ size = ipoib_recvq_size + 1;
+ ret = ipoib_cm_dev_init(dev);
+ if (!ret) {
++ size += ipoib_sendq_size;
+ if (ipoib_cm_has_srq(dev))
+ size += ipoib_recvq_size + 1; /* 1 extra for rx_drain_qp */
+ else
+ size += ipoib_recvq_size * ipoib_max_conn_qp;
+ }
--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;
+- priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size, 0);
+- if (IS_ERR(priv->cq)) {
+- printk(KERN_WARNING "%s: failed to create CQ\n", ca->name);
++ priv->recv_cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size, 0);
++ if (IS_ERR(priv->recv_cq)) {
++ printk(KERN_WARNING "%s: failed to create receive CQ\n", ca->name);
+ goto out_free_mr;
+ }
-@@ -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;
+- if (ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP))
+- goto out_free_cq;
++ priv->send_cq = ib_create_cq(priv->ca, NULL, NULL, dev, ipoib_sendq_size, 0);
++ if (IS_ERR(priv->send_cq)) {
++ printk(KERN_WARNING "%s: failed to create send CQ\n", ca->name);
++ goto out_free_recv_cq;
++ }
++
++ if (ib_req_notify_cq(priv->recv_cq, IB_CQ_NEXT_COMP))
++ goto out_free_send_cq;
- debug_log("Reached %s\n", __func__);
+- init_attr.send_cq = priv->cq;
+- init_attr.recv_cq = priv->cq;
++ init_attr.send_cq = priv->send_cq;
++ init_attr.recv_cq = priv->recv_cq;
++
++ if (priv->hca_caps & IB_DEVICE_UD_TSO)
++ init_attr.create_flags = IB_QP_CREATE_IPOIB_UD_LSO;
-@@ -418,11 +341,11 @@ static void idefloppy_request_sense_callback(ide_drive_t *drive)
- floppy->ascq);
+ if (dev->features & NETIF_F_SG)
+ init_attr.cap.max_send_sge = MAX_SKB_FRAGS + 1;
+@@ -198,7 +208,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
+ priv->qp = ib_create_qp(priv->pd, &init_attr);
+ if (IS_ERR(priv->qp)) {
+ printk(KERN_WARNING "%s: failed to create QP\n", ca->name);
+- goto out_free_cq;
++ goto out_free_send_cq;
+ }
+
+ priv->dev->dev_addr[1] = (priv->qp->qp_num >> 16) & 0xff;
+@@ -212,10 +222,26 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
+ priv->tx_wr.sg_list = priv->tx_sge;
+ priv->tx_wr.send_flags = IB_SEND_SIGNALED;
+
++ priv->rx_sge[0].lkey = priv->mr->lkey;
++ if (ipoib_ud_need_sg(priv->max_ib_mtu)) {
++ priv->rx_sge[0].length = IPOIB_UD_HEAD_SIZE;
++ priv->rx_sge[1].length = PAGE_SIZE;
++ priv->rx_sge[1].lkey = priv->mr->lkey;
++ priv->rx_wr.num_sge = IPOIB_UD_RX_SG;
++ } else {
++ priv->rx_sge[0].length = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu);
++ priv->rx_wr.num_sge = 1;
++ }
++ priv->rx_wr.next = NULL;
++ priv->rx_wr.sg_list = priv->rx_sge;
++
+ return 0;
+-out_free_cq:
+- ib_destroy_cq(priv->cq);
++out_free_send_cq:
++ ib_destroy_cq(priv->send_cq);
++
++out_free_recv_cq:
++ ib_destroy_cq(priv->recv_cq);
-- 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);
+ out_free_mr:
+ ib_dereg_mr(priv->mr);
+@@ -238,8 +264,11 @@ void ipoib_transport_dev_cleanup(struct net_device *dev)
+ clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
}
- }
-@@ -433,27 +356,27 @@ static void idefloppy_pc_callback(ide_drive_t *drive)
-
- debug_log("Reached %s\n", __func__);
+- if (ib_destroy_cq(priv->cq))
+- ipoib_warn(priv, "ib_cq_destroy failed\n");
++ if (ib_destroy_cq(priv->send_cq))
++ ipoib_warn(priv, "ib_cq_destroy (send) failed\n");
++
++ if (ib_destroy_cq(priv->recv_cq))
++ ipoib_warn(priv, "ib_cq_destroy (recv) failed\n");
+
+ ipoib_cm_dev_cleanup(dev);
+
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+index 293f5b8..1cdb5cf 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+@@ -89,6 +89,10 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
+ goto err;
+ }
-- idefloppy_do_end_request(drive, floppy->pc->error ? 0 : 1, 0);
-+ idefloppy_end_request(drive, floppy->pc->error ? 0 : 1, 0);
++ priv->max_ib_mtu = ppriv->max_ib_mtu;
++ /* MTU will be reset when mcast join happens */
++ priv->dev->mtu = IPOIB_UD_MTU(priv->max_ib_mtu);
++ priv->mcast_mtu = priv->admin_mtu = priv->dev->mtu;
+ set_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags);
+
+ priv->pkey = pkey;
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index be1b9fb..aeb58ca 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -473,13 +473,15 @@ iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *s
+ stats->r2t_pdus = conn->r2t_pdus_cnt; /* always 0 */
+ stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
+ stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
+- stats->custom_length = 3;
++ stats->custom_length = 4;
+ strcpy(stats->custom[0].desc, "qp_tx_queue_full");
+ stats->custom[0].value = 0; /* TB iser_conn->qp_tx_queue_full; */
+ strcpy(stats->custom[1].desc, "fmr_map_not_avail");
+ stats->custom[1].value = 0; /* TB iser_conn->fmr_map_not_avail */;
+ strcpy(stats->custom[2].desc, "eh_abort_cnt");
+ stats->custom[2].value = conn->eh_abort_cnt;
++ strcpy(stats->custom[3].desc, "fmr_unalign_cnt");
++ stats->custom[3].value = conn->fmr_unalign_cnt;
}
--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 int
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
+index 1ee867b..a8c1b30 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
+@@ -71,6 +71,13 @@
+
+ #define iser_dbg(fmt, arg...) \
+ do { \
++ if (iser_debug_level > 1) \
++ printk(KERN_DEBUG PFX "%s:" fmt,\
++ __func__ , ## arg); \
++ } while (0)
++
++#define iser_warn(fmt, arg...) \
++ do { \
+ if (iser_debug_level > 0) \
+ printk(KERN_DEBUG PFX "%s:" fmt,\
+ __func__ , ## arg); \
+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;
--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;
- }
+ 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;
- /*
-@@ -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;
+- itt = ntohl(hdr->itt);
++ itt = (__force uint32_t)hdr->itt;
+ data_seg_len = ntoh24(hdr->dlength);
+ buf_offset = ntohl(hdr->offset);
- (void)ide_read_error(drive);
-@@ -473,11 +396,11 @@ static void idefloppy_retry_pc(ide_drive_t *drive)
- }
+diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c
+index 4a17743..cac50c4 100644
+--- a/drivers/infiniband/ulp/iser/iser_memory.c
++++ b/drivers/infiniband/ulp/iser/iser_memory.c
+@@ -334,8 +334,11 @@ static void iser_data_buf_dump(struct iser_data_buf *data,
+ struct scatterlist *sg;
+ int i;
- /* 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;
++ if (iser_debug_level == 0)
++ return;
++
+ for_each_sg(sgl, sg, data->dma_nents, i)
+- iser_err("sg[%d] dma_addr:0x%lX page:0x%p "
++ iser_warn("sg[%d] dma_addr:0x%lX page:0x%p "
+ "off:0x%x sz:0x%x dma_len:0x%x\n",
+ i, (unsigned long)ib_sg_dma_address(ibdev, sg),
+ sg_page(sg), sg->offset,
+@@ -420,6 +423,7 @@ void iser_dma_unmap_task_data(struct iscsi_iser_cmd_task *iser_ctask)
+ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
+ enum iser_data_dir cmd_dir)
+ {
++ struct iscsi_conn *iscsi_conn = iser_ctask->iser_conn->iscsi_conn;
+ struct iser_conn *ib_conn = iser_ctask->iser_conn->ib_conn;
+ struct iser_device *device = ib_conn->device;
+ struct ib_device *ibdev = device->ib_device;
+@@ -434,7 +438,8 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
+
+ aligned_len = iser_data_buf_aligned_len(mem, ibdev);
+ if (aligned_len != mem->dma_nents) {
+- iser_err("rdma alignment violation %d/%d aligned\n",
++ iscsi_conn->fmr_unalign_cnt++;
++ iser_warn("rdma alignment violation %d/%d aligned\n",
+ aligned_len, mem->size);
+ iser_data_buf_dump(mem, ibdev);
- 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;
- }
+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;
-@@ -542,10 +465,10 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
- }
+ 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)");
- /* 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]);
+ static int topspin_workarounds = 1;
- 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);
+@@ -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;
- 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;
+- 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;
-- 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));
+ iu->size = size;
+@@ -161,7 +162,8 @@ static void srp_free_iu(struct srp_host *host, struct srp_iu *iu)
+ if (!iu)
+ return;
- /* Update the current position */
-- pc->actually_transferred += bcount;
-- pc->current_position += bcount;
-+ pc->xferred += bcount;
-+ pc->cur_pos += bcount;
+- 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;
- /* 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)
+- 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)
{
-+ 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;
+ 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);
}
-- 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;
+ 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;
}
-- 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,
+- 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);
}
- 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;
+@@ -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;
- floppy->failed_pc = NULL;
-- pc->callback(drive);
-+ pc->idefloppy_callback(drive);
- return ide_stopped;
- }
+@@ -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);
-@@ -727,9 +652,9 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
+- dev = target->srp_host->dev;
++ dev = target->srp_host->srp_dev;
+ ibdev = dev->dev;
- 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);
+ 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));
- 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__);
+@@ -855,7 +857,7 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
-- idefloppy_do_end_request(drive, 1, 0);
-+ idefloppy_end_request(drive, 1, 0);
- return;
- }
+ iu = target->rx_ring[wc->wr_id & ~SRP_OP_RECV];
--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);
+- 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);
-@@ -789,39 +714,39 @@ static void idefloppy_create_prevent_cmd(idefloppy_pc_t *pc, int prevent)
- pc->c[4] = prevent;
- }
+@@ -937,7 +939,7 @@ static int __srp_post_recv(struct srp_target_port *target)
--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;
- }
+ 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;
--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;
+ wr.next = NULL;
+ wr.sg_list = &list;
+@@ -996,7 +998,7 @@ static int __srp_post_send(struct srp_target_port *target,
-- 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 */
+ list.addr = iu->dma;
+ list.length = len;
+- list.lkey = target->srp_host->dev->mr->lkey;
++ list.lkey = target->srp_host->srp_dev->mr->lkey;
- 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;
+ 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;
-- 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;
+- 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;
}
- /* 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)
+-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)
{
- u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */
+- struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++ struct srp_target_port *target = host_to_target(class_to_shost(dev));
-@@ -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;
+ 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 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)
+-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)
{
- idefloppy_init_pc(pc);
- pc->c[0] = GPCMD_START_STOP_UNIT;
- pc->c[4] = start;
+- 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 void idefloppy_create_test_unit_ready_cmd(idefloppy_pc_t *pc)
-+static void idefloppy_create_test_unit_ready_cmd(struct ide_atapi_pc *pc)
+-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)
{
- idefloppy_init_pc(pc);
- pc->c[0] = GPCMD_TEST_UNIT_READY;
+- 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 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)
+-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)
{
- 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]);
+- struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++ struct srp_target_port *target = host_to_target(class_to_shost(dev));
-- 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;
+ 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 void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy,
-- idefloppy_pc_t *pc, struct request *rq)
-+ struct ide_atapi_pc *pc, struct request *rq)
+-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)
{
- 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;
+- 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 ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
- struct request *rq, sector_t block_s)
+-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)
{
- idefloppy_floppy_t *floppy = drive->driver_data;
-- idefloppy_pc_t *pc;
-+ struct ide_atapi_pc *pc;
- unsigned long block = (unsigned long)block_s;
+- struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++ struct srp_target_port *target = host_to_target(class_to_shost(dev));
- 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;
- }
+ 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]));
+ }
-@@ -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)
+-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)
{
- 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];
+- struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++ struct srp_target_port *target = host_to_target(class_to_shost(dev));
- capacity = cyls * heads * sectors * sector_size;
+ 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);
+ }
-@@ -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)
+-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)
{
- 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;
+- struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++ struct srp_target_port *target = host_to_target(class_to_shost(dev));
-- floppy->srfp = pc.buffer[8 + 2] & 0x40;
-+ floppy->srfp = pc.buf[8 + 2] & 0x40;
- return (0);
+ return sprintf(buf, "%d\n", target->srp_host->port);
}
-@@ -1050,7 +975,7 @@ static int idefloppy_get_sfrp_bit(ide_drive_t *drive)
- static int ide_floppy_get_capacity(ide_drive_t *drive)
+-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)
{
- 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 */
+- struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++ struct srp_target_port *target = host_to_target(class_to_shost(dev));
- for (i = 0; i < desc_cnt; i++) {
- unsigned int desc_start = 4 + i*8;
+- return sprintf(buf, "%s\n", target->srp_host->dev->dev->name);
++ return sprintf(buf, "%s\n", target->srp_host->srp_dev->dev->name);
+ }
-- 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]);
+-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
+ };
- 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
- */
+@@ -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));
-- 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);
- }
+- 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;
- /* Clik! disk does not support get_flexible_disk_page */
-@@ -1162,7 +1087,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
+ 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 int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
+-static void srp_release_class_dev(struct class_device *class_dev)
++static void srp_release_dev(struct device *dev)
{
-- 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 */
+ struct srp_host *host =
+- container_of(class_dev, struct srp_host, class_dev);
++ container_of(dev, struct srp_host, dev);
- 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 */
+ complete(&host->released);
+ }
-- 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]);
+ static struct class srp_class = {
+ .name = "infiniband_srp",
+- .release = srp_release_class_dev
++ .dev_release = srp_release_dev
+ };
- 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;
+ /*
+@@ -1835,11 +1846,12 @@ out:
+ return ret;
+ }
- 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)
+-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 idefloppy_id_gcw gcw;
-+ u8 gcw[2];
-+ u8 device_type, protocol, removable, drq_type, packet_size;
-
- *((u16 *) &gcw) = id->config;
+ 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;
-+ 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
+- 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);
-- 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;
+ 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;
}
-@@ -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)
+-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 idefloppy_id_gcw gcw;
-+ u8 gcw[2];
+- struct srp_host *host =
+- container_of(class_dev, struct srp_host, class_dev);
++ struct srp_host *host = container_of(dev, struct srp_host, dev);
- *((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;
+- return sprintf(buf, "%s\n", host->dev->dev->name);
++ return sprintf(buf, "%s\n", host->srp_dev->dev->name);
+ }
- 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;
+-static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
++static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
- debug_log("Reached %s\n", __func__);
+-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);
-@@ -1521,8 +1453,8 @@ static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
- return 0;
+ return sprintf(buf, "%d\n", host->port);
}
--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)
+-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)
{
- int blocks, length, flags, err = 0;
-- idefloppy_pc_t pc;
-+ struct ide_atapi_pc pc;
+@@ -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;
- 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;
+- 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);
-@@ -1664,13 +1596,13 @@ static int idefloppy_revalidate_disk(struct gendisk *disk)
- }
+- 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;
- 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
- };
+ return host;
- 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.
- */
+ err_class:
+- class_device_unregister(&host->class_dev);
++ device_unregister(&host->dev);
-+/*
-+ * For special cases new interfaces may be added using sysfs, i.e.
-+ *
-+ * echo -n "0x168:0x36e:10" > /sys/class/ide_generic/add
-+ *
-+ * will add an interface using I/O ports 0x168-0x16f/0x36e and IRQ 10.
-+ */
-+
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/ide.h>
+ 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);
-+#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)
+ 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)
{
- u8 idx[MAX_HWIFS];
- int i;
+ int ret;
- 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;
-+ }
++ if (srp_sg_tablesize > 255) {
++ printk(KERN_WARNING PFX "Clamping srp_sg_tablesize to 255\n");
++ srp_sg_tablesize = 255;
++ }
+
-+ 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;
- }
+ 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 {
+ };
- ide_device_add_all(idx, NULL);
+ 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.
-+ if (ide_generic_sysfs_init())
-+ printk(KERN_ERR DRV_NAME ": failed to create ide_generic "
-+ "class\n");
++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.
+
- return 0;
- }
+ comment "Input Device Drivers"
-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;
+ 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/
- 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]);
+ 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)
- tf->data = data & 0xff;
- tf->hob_data = (data >> 8) & 0xff;
- }
+ 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;
- /* 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]);
+ error = input_polldev_start_workqueue();
+@@ -91,7 +91,7 @@ static int input_open_polled_device(struct input_dev *input)
- 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]);
+ 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);
- 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]);
+ 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;
- 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]);
- }
- }
++ 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;
-@@ -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
+diff --git a/drivers/input/input.c b/drivers/input/input.c
+index f02c242..27006fc 100644
+--- a/drivers/input/input.c
++++ b/drivers/input/input.c
+@@ -898,30 +898,26 @@ static int __init input_proc_init(void)
+ {
+ struct proc_dir_entry *entry;
- 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]);
+- proc_bus_input_dir = proc_mkdir("input", proc_bus);
++ proc_bus_input_dir = proc_mkdir("bus/input", NULL);
+ if (!proc_bus_input_dir)
+ return -ENOMEM;
- 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;
+ proc_bus_input_dir->owner = THIS_MODULE;
- if (set_pio_mode_abuse(drive->hwif, req_pio)) {
+- entry = create_proc_entry("devices", 0, proc_bus_input_dir);
++ entry = proc_create("devices", 0, proc_bus_input_dir,
++ &input_devices_fileops);
+ if (!entry)
+ goto fail1;
+
+- entry->owner = THIS_MODULE;
+- entry->proc_fops = &input_devices_fileops;
-
-- if (hwif->set_pio_mode == NULL)
-- return ide_stopped;
+- entry = create_proc_entry("handlers", 0, proc_bus_input_dir);
++ entry = proc_create("handlers", 0, proc_bus_input_dir,
++ &input_handlers_fileops);
+ if (!entry)
+ goto fail2;
+
+- entry->owner = THIS_MODULE;
+- entry->proc_fops = &input_handlers_fileops;
-
- /*
- * 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);
+ return 0;
- 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]);
+ fail2: remove_proc_entry("devices", proc_bus_input_dir);
+- fail1: remove_proc_entry("input", proc_bus);
++ fail1: remove_proc_entry("bus/input", NULL);
+ return -ENOMEM;
}
- 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);
+@@ -929,7 +925,7 @@ static void input_proc_exit(void)
+ {
+ remove_proc_entry("devices", proc_bus_input_dir);
+ remove_proc_entry("handlers", proc_bus_input_dir);
+- remove_proc_entry("input", proc_bus);
++ remove_proc_entry("bus/input", NULL);
}
- /*
-@@ -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;
+ #else /* !CONFIG_PROC_FS */
+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.
+
- 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);
- }
++ 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
- /*
-@@ -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);
- }
+-obj-$(CONFIG_JOYSTICK_IFORCE) += iforce/
+diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
+index 1457b73..7fb3cf8 100644
+--- a/drivers/input/joystick/iforce/iforce-usb.c
++++ b/drivers/input/joystick/iforce/iforce-usb.c
+@@ -159,7 +159,7 @@ static int iforce_usb_probe(struct usb_interface *intf,
+
+ iforce->cr.bRequestType = USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_INTERFACE;
+ iforce->cr.wIndex = 0;
+- iforce->cr.wLength = 16;
++ iforce->cr.wLength = cpu_to_le16(16);
- 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);
- }
+ usb_fill_int_urb(iforce->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress),
+ iforce->data, 16, iforce_usb_irq, iforce, epirq->bInterval);
+diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
+index 0380597..b29e3af 100644
+--- a/drivers/input/joystick/xpad.c
++++ b/drivers/input/joystick/xpad.c
+@@ -1,5 +1,5 @@
+ /*
+- * X-Box gamepad - v0.0.6
++ * X-Box gamepad driver
+ *
+ * Copyright (c) 2002 Marko Friedemann <mfr at bmx-chemnitz.de>
+ * 2004 Oliver Schwartz <Oliver.Schwartz at gmx.de>,
+@@ -68,6 +68,8 @@
+ * - dance pads will map D-PAD to buttons, not axes
+ * - pass the module paramater 'dpad_to_buttons' to force
+ * the D-PAD to map to buttons if your pad is not detected
++ *
++ * Later changes can be tracked in SCM.
+ */
- 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);
+ #include <linux/kernel.h>
+@@ -77,7 +79,6 @@
+ #include <linux/module.h>
+ #include <linux/usb/input.h>
-@@ -828,7 +842,7 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
+-#define DRIVER_VERSION "v0.0.6"
+ #define DRIVER_AUTHOR "Marko Friedemann <mfr at bmx-chemnitz.de>"
+ #define DRIVER_DESC "X-Box pad driver"
- 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]);
+@@ -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
-- 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);
-- }
- }
+ #define XTYPE_XBOX 0
+ #define XTYPE_XBOX360 1
++#define XTYPE_XBOX360W 2
++#define XTYPE_UNKNOWN 3
- 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;
+ 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 }
+ };
-- if (hwif->set_pio_mode == NULL)
-+ if (hwif->set_pio_mode == NULL ||
-+ (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
- return;
+-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 */
+ };
- 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;
++/* 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 */
+ };
-+ if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
-+ return 0;
+-/* 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) }
+
- if (hwif->set_pio_mode == NULL)
- return -1;
+ 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 */
+ { }
+ };
-@@ -380,6 +374,9 @@ int ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
- {
- ide_hwif_t *hwif = drive->hwif;
+@@ -188,10 +216,15 @@ struct usb_xpad {
+ struct input_dev *dev; /* input device interface */
+ struct usb_device *udev; /* usb device */
-+ if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
-+ return 0;
++ int pad_present;
+
- if (hwif->set_dma_mode == NULL)
- return -1;
+ struct urb *irq_in; /* urb for interrupt in report */
+ unsigned char *idata; /* input data */
+ dma_addr_t idata_dma;
-@@ -410,7 +407,8 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
- {
- ide_hwif_t *hwif = drive->hwif;
++ 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)));
-- if (hwif->set_dma_mode == NULL)
-+ if (hwif->set_dma_mode == NULL ||
-+ (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
- return -1;
+ /* 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)));
- 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.
- */
+ /* 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)));
- #include <linux/init.h>
-@@ -20,12 +20,12 @@
+ /* 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)));
- /* 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 = ""}
- };
+ /* 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);
+ }
--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)
++/*
++ * 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)
{
- 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);
+ struct usb_xpad *xpad = urb->context;
+- int retval;
++ int retval, status;
- printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index);
-- pnp_set_drvdata(dev,hwif);
-+ pnp_set_drvdata(dev, hwif);
+- 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;
+ }
- ide_device_add(idx, NULL);
+- 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);
++ }
-@@ -57,12 +57,12 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
- return -1;
+ exit:
+ retval = usb_submit_urb (urb, GFP_ATOMIC);
+@@ -370,12 +444,31 @@ exit:
+ __FUNCTION__, retval);
}
--static void idepnp_remove(struct pnp_dev * dev)
-+static void idepnp_remove(struct pnp_dev *dev)
++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);
++ }
++}
++
+ #if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
+ static void xpad_irq_out(struct urb *urb)
{
- ide_hwif_t *hwif = pnp_get_drvdata(dev);
+- int retval;
++ int retval, status;
- 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);
+- switch (urb->status) {
++ status = urb->status;
++
++ switch (status) {
+ case 0:
+ /* success */
+ break;
+@@ -384,11 +477,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;
+ }
-- 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]);
+@@ -408,7 +501,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
+ return 0;
- /* ask drive for ID */
-- hwif->OUTB(cmd, IDE_COMMAND_REG);
-+ hwif->OUTB(cmd, hwif->io_ports[IDE_COMMAND_OFFSET]);
+ 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;
- 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]);
+@@ -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);
+ }
- 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);
- }
+@@ -477,6 +571,9 @@ static int xpad_play_effect(struct input_dev *dev, void *data,
--static void ide_register_port(ide_hwif_t *hwif)
-+static int ide_register_port(ide_hwif_t *hwif)
+ static int xpad_init_ff(struct usb_xpad *xpad)
{
- int ret;
++ if (xpad->xtype != XTYPE_XBOX360)
++ return 0;
++
+ input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
-@@ -639,9 +642,23 @@ static void ide_register_port(ide_hwif_t *hwif)
+ 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);
}
- 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;
- }
+@@ -574,6 +672,10 @@ static int xpad_open(struct input_dev *dev)
+ {
+ struct usb_xpad *xpad = input_get_drvdata(dev);
- /**
-@@ -949,6 +966,7 @@ static void ide_port_setup_devices(ide_hwif_t *hwif)
++ /* 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)
{
- int i;
+ struct usb_xpad *xpad = input_get_drvdata(dev);
-+ mutex_lock(&ide_cfg_mtx);
- for (i = 0; i < MAX_DRIVES; i++) {
- ide_drive_t *drive = &hwif->drives[i];
+- usb_kill_urb(xpad->irq_in);
++ if(xpad->xtype != XTYPE_XBOX360W)
++ usb_kill_urb(xpad->irq_in);
+ xpad_stop_output(xpad);
+ }
-@@ -963,6 +981,7 @@ static void ide_port_setup_devices(ide_hwif_t *hwif)
+@@ -632,7 +735,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
+ goto fail1;
- ide_add_drive_to_hwgroup(drive);
- }
-+ mutex_unlock(&ide_cfg_mtx);
- }
+ xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN,
+- GFP_ATOMIC, &xpad->idata_dma);
++ GFP_KERNEL, &xpad->idata_dma);
+ if (!xpad->idata)
+ goto fail1;
- /*
-@@ -1088,8 +1107,6 @@ static int init_irq (ide_hwif_t *hwif)
- hwif->sharing_irq ? "shar" : "serializ", match->name);
- printk("\n");
+@@ -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);
-- 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);
+ /* 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;
-+ ide_proc_unregister_device(drive);
+ 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;
+
- 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
++ 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;
++ }
+
- 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);
-+}
++ 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;
-+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);
- }
++ 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;
}
-+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);
+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
++ *
++ */
+
-+ if (strncmp(buf, "1", n))
-+ return -EINVAL;
++/*
++ * Driver to use 4CH RC transmitter using Zhen Hua 5-byte protocol (Walkera Lama,
++ * EasyCopter etc.) as a joystick under Linux.
++ *
++ * RC transmitters using Zhen Hua 5-byte protocol are cheap four channels
++ * transmitters for control a RC planes or RC helicopters with possibility to
++ * connect on a serial port.
++ * Data coming from transmitter is in this order:
++ * 1. byte = synchronisation byte
++ * 2. byte = X axis
++ * 3. byte = Y axis
++ * 4. byte = RZ axis
++ * 5. byte = Z axis
++ * (and this is repeated)
++ *
++ * For questions or feedback regarding this driver module please contact:
++ * Martin Kebert <gkmarty at gmail.com> - but I am not a C-programmer nor kernel
++ * coder :-(
++ */
+
-+ ide_port_unregister_devices(hwif);
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
-+ return n;
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/input.h>
++#include <linux/serio.h>
++#include <linux/init.h>
++
++#define DRIVER_DESC "RC transmitter with 5-byte Zhen Hua protocol joystick driver"
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_LICENSE("GPL");
++
++/*
++ * Constants.
++ */
++
++#define ZHENHUA_MAX_LENGTH 5
++
++/*
++ * Zhen Hua data.
++ */
++
++struct zhenhua {
++ struct input_dev *dev;
++ int idx;
++ unsigned char data[ZHENHUA_MAX_LENGTH];
++ char phys[32];
+};
+
-+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)
++/* bits in all incoming bytes needs to be "reversed" */
++static int zhenhua_bitreverse(int x)
+{
-+ ide_hwif_t *hwif = dev_get_drvdata(portdev);
++ x = ((x & 0xaa) >> 1) | ((x & 0x55) << 1);
++ x = ((x & 0xcc) >> 2) | ((x & 0x33) << 2);
++ x = ((x & 0xf0) >> 4) | ((x & 0x0f) << 4);
++ return x;
++}
+
-+ if (strncmp(buf, "1", n))
-+ return -EINVAL;
++/*
++ * zhenhua_process_packet() decodes packets the driver receives from the
++ * RC transmitter. It updates the data accordingly.
++ */
+
-+ ide_port_unregister_devices(hwif);
-+ ide_port_scan(hwif);
++static void zhenhua_process_packet(struct zhenhua *zhenhua)
++{
++ struct input_dev *dev = zhenhua->dev;
++ unsigned char *data = zhenhua->data;
+
-+ return n;
-+};
++ 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]);
+
-+static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
++ input_sync(dev);
++}
+
-+static struct device_attribute *ide_port_attrs[] = {
-+ &dev_attr_delete_devices,
-+ &dev_attr_scan,
-+ NULL
-+};
++/*
++ * 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 int ide_sysfs_register_port(ide_hwif_t *hwif)
++static irqreturn_t zhenhua_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
+{
-+ int i, rc;
++ struct zhenhua *zhenhua = serio_get_drvdata(serio);
+
-+ for (i = 0; ide_port_attrs[i]; i++) {
-+ rc = device_create_file(hwif->portdev, ide_port_attrs[i]);
-+ if (rc)
-+ break;
++ /* 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 rc;
++ return IRQ_HANDLED;
+}
+
-+/**
-+ * 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.
++/*
++ * zhenhua_disconnect() is the opposite of zhenhua_connect()
+ */
+
-+ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d)
++static void zhenhua_disconnect(struct serio *serio)
+{
-+ ide_hwif_t *hwif;
-+ int i;
-+ u8 bootable = (d && (d->host_flags & IDE_HFLAG_NON_BOOTABLE)) ? 0 : 1;
++ struct zhenhua *zhenhua = serio_get_drvdata(serio);
+
-+ /*
-+ * 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;
++ serio_close(serio);
++ serio_set_drvdata(serio, NULL);
++ input_unregister_device(zhenhua->dev);
++ kfree(zhenhua);
++}
+
-+ 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;
-+ }
-+ }
++/*
++ * 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.
++ */
+
-+ return NULL;
++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;
+}
-+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);
- }
++/*
++ * 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.
-@@ -1441,6 +1561,8 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
- continue;
- }
++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;
+ }
-+ ide_port_setup_devices(hwif);
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:aaed2000-keyboard");
+
- 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]];
+ static struct platform_driver aaedkbd_driver = {
+ .probe = aaedkbd_probe,
+ .remove = __devexit_p(aaedkbd_remove),
+ .driver = {
+ .name = "aaed2000-keyboard",
++ .owner = THIS_MODULE,
+ },
+ };
- 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]];
+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)
- 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);
+ bfin_write_KPAD_CTL(bfin_read_KPAD_CTL() | KPAD_EN);
+
++ device_init_wakeup(&pdev->dev, 1);
+
-+void ide_port_scan(ide_hwif_t *hwif)
+ 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)
+{
-+ ide_port_cable_detect(hwif);
-+ ide_port_init_devices(hwif);
++ struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
+
-+ if (ide_probe_port(hwif) < 0)
-+ return;
++ if (device_may_wakeup(&pdev->dev))
++ enable_irq_wake(bf54x_kpad->irq);
+
-+ hwif->present = 1;
++ return 0;
++}
+
-+ 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);
++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;
+}
-+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;
++#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,
+ };
-- /*
-- * 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 __init bfin_kpad_init(void)
+@@ -378,3 +408,4 @@ module_exit(bfin_kpad_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Michael Hennerich <hennerich at blackfin.uclinux.org>");
+ MODULE_DESCRIPTION("Keypad driver for BF54x Processors");
++MODULE_ALIAS("platform:bf54x-keys");
+diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
+index 790fed3..29fbec6 100644
+--- a/drivers/input/keyboard/corgikbd.c
++++ b/drivers/input/keyboard/corgikbd.c
+@@ -23,6 +23,7 @@
+ #include <asm/arch/corgi.h>
+ #include <asm/arch/hardware.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/hardware/scoop.h>
- 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);
- }
+ #define KB_ROWS 8
+@@ -392,6 +393,7 @@ static struct platform_driver corgikbd_driver = {
+ .resume = corgikbd_resume,
+ .driver = {
+ .name = "corgi-keyboard",
++ .owner = THIS_MODULE,
+ },
+ };
- 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);
- }
+@@ -411,3 +413,4 @@ module_exit(corgikbd_exit);
+ MODULE_AUTHOR("Richard Purdie <rpurdie at rpsys.net>");
+ MODULE_DESCRIPTION("Corgi Keyboard Driver");
+ MODULE_LICENSE("GPLv2");
++MODULE_ALIAS("platform:corgi-keyboard");
+diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
+index 6a9ca4b..bbd00c3 100644
+--- a/drivers/input/keyboard/gpio_keys.c
++++ b/drivers/input/keyboard/gpio_keys.c
+@@ -43,10 +43,11 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
- static int proc_ide_read_identify
-@@ -123,7 +120,7 @@ static int proc_ide_read_identify
- len = out - page;
+ input_event(input, type, button->code, !!state);
+ input_sync(input);
++ return IRQ_HANDLED;
}
}
-- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
-+ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+
+- return IRQ_HANDLED;
++ return IRQ_NONE;
}
- /**
-@@ -200,7 +197,7 @@ EXPORT_SYMBOL(ide_add_setting);
- * The caller must hold the setting semaphore.
- */
+ 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,
+ }
+ };
--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;
+@@ -232,3 +234,4 @@ module_exit(gpio_keys_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Phil Blundell <pb at handhelds.org>");
+ MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
++MODULE_ALIAS("platform:gpio-keys");
+diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c
+index a23633a..9387da3 100644
+--- a/drivers/input/keyboard/jornada680_kbd.c
++++ b/drivers/input/keyboard/jornada680_kbd.c
+@@ -254,6 +254,7 @@ static int __devexit jornada680kbd_remove(struct platform_device *pdev)
+ static struct platform_driver jornada680kbd_driver = {
+ .driver = {
+ .name = "jornada680_kbd",
++ .owner = THIS_MODULE,
+ },
+ .probe = jornada680kbd_probe,
+ .remove = __devexit_p(jornada680kbd_remove),
+@@ -275,3 +276,4 @@ module_exit(jornada680kbd_exit);
+ MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson at gmail.com>");
+ MODULE_DESCRIPTION("HP Jornada 620/660/680/690 Keyboard Driver");
+ MODULE_LICENSE("GPLv2");
++MODULE_ALIAS("platform:jornada680_kbd");
+diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c
+index 986f93c..a1164a0 100644
+--- a/drivers/input/keyboard/jornada720_kbd.c
++++ b/drivers/input/keyboard/jornada720_kbd.c
+@@ -162,9 +162,13 @@ static int __devexit jornada720_kbd_remove(struct platform_device *pdev)
+ return 0;
+ }
-@@ -208,7 +205,8 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name)
++/* 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
- while ((*p) && strcmp((*p)->name, name))
- p = &((*p)->next);
-- if ((setting = (*p)) == NULL)
-+ setting = (*p);
-+ if (setting == NULL)
- return;
+-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
- (*p) = setting->next;
-@@ -226,7 +224,7 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name)
- * caller must hold ide_setting_mtx.
- */
+ #define KB_DELAY 8
+ #define SCAN_INTERVAL (HZ/10)
+-#define LOCOMOKBD_PRESSED 1
--static void auto_remove_settings (ide_drive_t *drive)
-+static void auto_remove_settings(ide_drive_t *drive)
+ 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)
{
- ide_settings_t *setting;
- repeat:
-@@ -282,16 +280,16 @@ static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
+- 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)
- 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;
+ 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;
}
- 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;
+ locomokbd_reset_col(membase, col);
}
- spin_unlock_irq(&ide_lock);
- return 0;
-@@ -393,7 +391,7 @@ void ide_add_generic_settings (ide_drive_t *drive)
+@@ -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;
- static void proc_ide_settings_warn(void)
+ 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)
{
-- 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);
+ struct locomokbd *locomokbd = (struct locomokbd *) data;
++
+ locomokbd_scankeyboard(locomokbd);
}
- #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)
+-static int locomokbd_probe(struct locomo_dev *dev)
++static int __devinit locomokbd_probe(struct locomo_dev *dev)
{
-- 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);
- }
+ struct locomokbd *locomokbd;
+ struct input_dev *input_dev;
+@@ -211,7 +232,6 @@ static int locomokbd_probe(struct locomo_dev *dev)
+ goto err_free_mem;
+ }
- EXPORT_SYMBOL_GPL(proc_ide_read_capacity);
-@@ -549,13 +547,13 @@ int proc_ide_read_geometry
- char *out = page;
- int len;
+- locomokbd->ldev = dev;
+ locomo_set_drvdata(dev, locomokbd);
-- 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);
+ 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;
- len = out - page;
-- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
-+ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
- }
++ locomokbd->suspend_jiffies = jiffies;
++
+ locomokbd->input = input_dev;
+ strcpy(locomokbd->phys, "locomokbd/input0");
- EXPORT_SYMBOL(proc_ide_read_geometry);
-@@ -569,7 +567,7 @@ static int proc_ide_read_dmodel
+@@ -233,9 +255,10 @@ static int locomokbd_probe(struct locomo_dev *dev)
+ input_dev->id.version = 0x0100;
+ input_dev->dev.parent = &dev->dev;
- 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);
- }
+- 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);
- 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);
+ memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode));
+@@ -268,7 +291,7 @@ static int locomokbd_probe(struct locomo_dev *dev)
+ return err;
}
- 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 int locomokbd_remove(struct locomo_dev *dev)
++static int __devexit locomokbd_remove(struct locomo_dev *dev)
+ {
+ struct locomokbd *locomokbd = locomo_get_drvdata(dev);
- 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 }
+@@ -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),
};
-@@ -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 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;
}
- }
--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
+ 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]);
- 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;
+ 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,
+ },
+ };
- 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);
+@@ -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;
+ }
- /*
- * 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;
++/* 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,
+ },
};
--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
+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.
++ */
+
-+/* Some defines for the SPACE command */
-+#define IDETAPE_SPACE_OVER_FILEMARK 1
-+#define IDETAPE_SPACE_TO_EOD 3
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/input.h>
++#include <linux/io.h>
++#include <asm/sh_keysc.h>
+
-+/* 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
++#define KYCR1_OFFS 0x00
++#define KYCR2_OFFS 0x04
++#define KYINDR_OFFS 0x08
++#define KYOUTDR_OFFS 0x0c
+
-+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),
++#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 },
+};
+
-+/* 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
++struct sh_keysc_priv {
++ void __iomem *iomem_base;
++ unsigned long last_keys;
++ struct input_dev *input;
++ struct sh_keysc_info pdata;
++};
+
-+/* Structures related to the SELECT SENSE / MODE SENSE packet commands. */
-+#define IDETAPE_BLOCK_DESCRIPTOR 0
-+#define IDETAPE_CAPABILITIES_PAGE 0x2a
++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;
+
-+/* 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),
++ dev_dbg(&pdev->dev, "isr!\n");
++
++ keys1 = ~0;
++ keys0 = 0;
++
++ do {
++ keys = 0;
++ keyin_set = 0;
++
++ iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS);
++
++ for (i = 0; i < sh_keysc_mode[pdata->mode].keyout; i++) {
++ iowrite16(0xfff ^ (3 << (i * 2)),
++ priv->iomem_base + KYOUTDR_OFFS);
++ udelay(pdata->delay);
++ tmp = ioread16(priv->iomem_base + KYINDR_OFFS);
++ keys |= tmp << (sh_keysc_mode[pdata->mode].keyin * i);
++ tmp ^= (1 << sh_keysc_mode[pdata->mode].keyin) - 1;
++ keyin_set |= tmp;
++ }
++
++ iowrite16(0, priv->iomem_base + KYOUTDR_OFFS);
++ iowrite16(KYCR2_IRQ_LEVEL | (keyin_set << 8),
++ priv->iomem_base + KYCR2_OFFS);
++
++ keys ^= ~0;
++ keys &= (1 << (sh_keysc_mode[pdata->mode].keyin *
++ sh_keysc_mode[pdata->mode].keyout)) - 1;
++ keys1 &= keys;
++ keys0 |= keys;
++
++ dev_dbg(&pdev->dev, "keys 0x%08lx\n", keys);
++
++ } while (ioread16(priv->iomem_base + KYCR2_OFFS) & 0x01);
++
++ dev_dbg(&pdev->dev, "last_keys 0x%08lx keys0 0x%08lx keys1 0x%08lx\n",
++ priv->last_keys, keys0, keys1);
++
++ for (i = 0; i < SH_KEYSC_MAXKEYS; i++) {
++ k = pdata->keycodes[i];
++ if (!k)
++ continue;
++
++ mask = 1 << i;
++
++ if (!((priv->last_keys ^ keys0) & mask))
++ continue;
++
++ if ((keys1 | keys0) & mask) {
++ input_event(priv->input, EV_KEY, k, 1);
++ priv->last_keys |= mask;
++ }
++
++ if (!(keys1 & mask)) {
++ input_event(priv->input, EV_KEY, k, 0);
++ priv->last_keys &= ~mask;
++ }
++
++ }
++ input_sync(priv->input);
++
++ return IRQ_HANDLED;
++}
++
++#define res_size(res) ((res)->end - (res)->start + 1)
++
++static int __devinit sh_keysc_probe(struct platform_device *pdev)
++{
++ struct sh_keysc_priv *priv;
++ struct sh_keysc_info *pdata;
++ struct resource *res;
++ struct input_dev *input;
++ int i, k;
++ int irq, error;
++
++ if (!pdev->dev.platform_data) {
++ dev_err(&pdev->dev, "no platform data defined\n");
++ error = -EINVAL;
++ goto err0;
++ }
++
++ error = -ENXIO;
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (res == NULL) {
++ dev_err(&pdev->dev, "failed to get I/O memory\n");
++ goto err0;
++ }
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_err(&pdev->dev, "failed to get irq\n");
++ goto err0;
++ }
++
++ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++ if (priv == NULL) {
++ dev_err(&pdev->dev, "failed to allocate driver data\n");
++ error = -ENOMEM;
++ goto err0;
++ }
++
++ platform_set_drvdata(pdev, priv);
++ memcpy(&priv->pdata, pdev->dev.platform_data, sizeof(priv->pdata));
++ pdata = &priv->pdata;
++
++ res = request_mem_region(res->start, res_size(res), pdev->name);
++ if (res == NULL) {
++ dev_err(&pdev->dev, "failed to request I/O memory\n");
++ error = -EBUSY;
++ goto err1;
++ }
++
++ priv->iomem_base = ioremap_nocache(res->start, res_size(res));
++ if (priv->iomem_base == NULL) {
++ dev_err(&pdev->dev, "failed to remap I/O memory\n");
++ error = -ENXIO;
++ goto err2;
++ }
++
++ priv->input = input_allocate_device();
++ if (!priv->input) {
++ dev_err(&pdev->dev, "failed to allocate input device\n");
++ error = -ENOMEM;
++ goto err3;
++ }
++
++ input = priv->input;
++ input->evbit[0] = BIT_MASK(EV_KEY);
++
++ input->name = pdev->name;
++ input->phys = "sh-keysc-keys/input0";
++ input->dev.parent = &pdev->dev;
++
++ input->id.bustype = BUS_HOST;
++ input->id.vendor = 0x0001;
++ input->id.product = 0x0001;
++ input->id.version = 0x0100;
++
++ error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev);
++ if (error) {
++ dev_err(&pdev->dev, "failed to request IRQ\n");
++ goto err4;
++ }
++
++ for (i = 0; i < SH_KEYSC_MAXKEYS; i++) {
++ k = pdata->keycodes[i];
++ if (k)
++ input_set_capability(input, EV_KEY, k);
++ }
++
++ error = input_register_device(input);
++ if (error) {
++ dev_err(&pdev->dev, "failed to register input device\n");
++ goto err5;
++ }
++
++ iowrite16((sh_keysc_mode[pdata->mode].kymd << 8) |
++ pdata->scan_timing, priv->iomem_base + KYCR1_OFFS);
++ iowrite16(0, priv->iomem_base + KYOUTDR_OFFS);
++ iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS);
++ return 0;
++ err5:
++ free_irq(irq, pdev);
++ err4:
++ input_free_device(input);
++ err3:
++ iounmap(priv->iomem_base);
++ err2:
++ release_mem_region(res->start, res_size(res));
++ err1:
++ platform_set_drvdata(pdev, NULL);
++ kfree(priv);
++ err0:
++ return error;
++}
++
++static int __devexit sh_keysc_remove(struct platform_device *pdev)
++{
++ struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
++ struct resource *res;
++
++ iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS);
++
++ input_unregister_device(priv->input);
++ free_irq(platform_get_irq(pdev, 0), pdev);
++ iounmap(priv->iomem_base);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ release_mem_region(res->start, res_size(res));
++
++ platform_set_drvdata(pdev, NULL);
++ kfree(priv);
++ return 0;
++}
++
++
++#define sh_keysc_suspend NULL
++#define sh_keysc_resume NULL
++
++struct platform_driver sh_keysc_device_driver = {
++ .probe = sh_keysc_probe,
++ .remove = __devexit_p(sh_keysc_remove),
++ .suspend = sh_keysc_suspend,
++ .resume = sh_keysc_resume,
++ .driver = {
++ .name = "sh_keysc",
++ }
+};
++
++static int __init sh_keysc_init(void)
++{
++ return platform_driver_register(&sh_keysc_device_driver);
++}
++
++static void __exit sh_keysc_exit(void)
++{
++ platform_driver_unregister(&sh_keysc_device_driver);
++}
++
++module_init(sh_keysc_init);
++module_exit(sh_keysc_exit);
++
++MODULE_AUTHOR("Magnus Damm");
++MODULE_DESCRIPTION("SuperH KEYSC Keypad Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
+index 1d59a2d..61e401b 100644
+--- a/drivers/input/keyboard/spitzkbd.c
++++ b/drivers/input/keyboard/spitzkbd.c
+@@ -23,6 +23,7 @@
+ #include <asm/arch/spitz.h>
+ #include <asm/arch/hardware.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
- /* 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
+ #define KB_ROWS 7
+ #define KB_COLS 11
+@@ -494,3 +495,4 @@ module_exit(spitzkbd_exit);
+ MODULE_AUTHOR("Richard Purdie <rpurdie at rpsys.net>");
+ MODULE_DESCRIPTION("Spitz Keyboard Driver");
+ MODULE_LICENSE("GPLv2");
++MODULE_ALIAS("platform:spitz-keyboard");
+diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c
+index 3884d1e..94e444b 100644
+--- a/drivers/input/keyboard/tosakbd.c
++++ b/drivers/input/keyboard/tosakbd.c
+@@ -52,7 +52,7 @@ KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_
+ struct tosakbd {
+ unsigned int keycode[ARRAY_SIZE(tosakbd_keycode)];
+ struct input_dev *input;
-
- /*
- * 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;
- }
++ int suspended;
+ spinlock_t lock; /* protect kbd scanning */
+ struct timer_list timer;
+ };
+@@ -133,6 +133,9 @@ static void tosakbd_scankeyboard(struct platform_device *dev)
--/*
-- * 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;
+ 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);
}
--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)
+@@ -200,6 +204,7 @@ static irqreturn_t tosakbd_interrupt(int irq, void *__dev)
+ static void tosakbd_timer_callback(unsigned long __dev)
{
- struct idetape_bh *bh = pc->bh;
-@@ -585,13 +537,13 @@ static void idetape_output_buffers(ide_drive_t *drive, idetape_pc_t *pc,
- }
+ struct platform_device *dev = (struct platform_device *)__dev;
++
+ tosakbd_scankeyboard(dev);
}
--static void idetape_update_buffers(idetape_pc_t *pc)
-+static void idetape_update_buffers(struct ide_atapi_pc *pc)
+@@ -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 idetape_bh *bh = pc->bh;
- int count;
-- unsigned int bcount = pc->actually_transferred;
-+ unsigned int bcount = pc->xferred;
+ 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);
-- 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;
+ del_timer_sync(&tosakbd->timer);
-@@ -649,14 +601,14 @@ static struct request *idetape_next_rq_storage(ide_drive_t *drive)
- return (&tape->rq_stack[tape->rq_stack_index++]);
- }
+@@ -215,6 +227,9 @@ static int tosakbd_suspend(struct platform_device *dev, pm_message_t state)
--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)
+ static int tosakbd_resume(struct platform_device *dev)
{
- 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);
++ struct tosakbd *tosakbd = platform_get_drvdata(dev);
++
++ tosakbd->suspended = 0;
+ tosakbd_scankeyboard(dev);
-- /* 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;
+@@ -365,8 +380,8 @@ fail:
+ return error;
}
--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 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);
- 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;
+@@ -394,6 +409,7 @@ static struct platform_driver tosakbd_driver = {
+ .resume = tosakbd_resume,
+ .driver = {
+ .name = "tosa-keyboard",
++ .owner = THIS_MODULE,
+ },
+ };
- (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);
+@@ -413,3 +429,4 @@ module_exit(tosakbd_exit);
+ MODULE_AUTHOR("Dirk Opfer <Dirk at Opfer-Online.de>");
+ MODULE_DESCRIPTION("Tosa Keyboard Driver");
+ MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:tosa-keyboard");
+diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
+index c5263d6..92b6834 100644
+--- a/drivers/input/misc/Kconfig
++++ b/drivers/input/misc/Kconfig
+@@ -15,6 +15,7 @@ if INPUT_MISC
+ config INPUT_PCSPKR
+ tristate "PC Speaker support"
+ depends on ALPHA || X86 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES
++ depends on SND_PCSP=n
+ help
+ Say Y here if you want the standard PC Speaker to be used for
+ bells and whistles.
+diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c
+index 5511ef0..6a1f48b 100644
+--- a/drivers/input/misc/cobalt_btns.c
++++ b/drivers/input/misc/cobalt_btns.c
+@@ -148,6 +148,9 @@ static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
+ return 0;
}
--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)) {
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:Cobalt buttons");
+
-+ 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);
+ static struct platform_driver cobalt_buttons_driver = {
+ .probe = cobalt_buttons_probe,
+ .remove = __devexit_p(cobalt_buttons_remove),
+diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
+index fed3c37..d8765cc 100644
+--- a/drivers/input/misc/sparcspkr.c
++++ b/drivers/input/misc/sparcspkr.c
+@@ -2,33 +2,69 @@
+ * Driver for PC-speaker like devices found on various Sparc systems.
+ *
+ * Copyright (c) 2002 Vojtech Pavlik
+- * Copyright (c) 2002, 2006 David S. Miller (davem at davemloft.net)
++ * Copyright (c) 2002, 2006, 2008 David S. Miller (davem at davemloft.net)
+ */
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/input.h>
+-#include <linux/platform_device.h>
++#include <linux/of_device.h>
- /* Update the current position */
-- pc->actually_transferred += bcount;
-- pc->current_position += bcount;
-+ pc->xferred += bcount;
-+ pc->cur_pos += bcount;
+ #include <asm/io.h>
+-#include <asm/ebus.h>
+-#include <asm/isa.h>
- 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;
- }
+ MODULE_AUTHOR("David S. Miller <davem at davemloft.net>");
+ MODULE_DESCRIPTION("Sparc Speaker beeper driver");
+ MODULE_LICENSE("GPL");
--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;
++struct grover_beep_info {
++ void __iomem *freq_regs;
++ void __iomem *enable_reg;
++};
++
++struct bbc_beep_info {
++ u32 clock_freq;
++ void __iomem *regs;
++};
++
+ struct sparcspkr_state {
+ const char *name;
+- unsigned long iobase;
+ int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
+ spinlock_t lock;
+ struct input_dev *input_dev;
++ union {
++ struct grover_beep_info grover;
++ struct bbc_beep_info bbc;
++ } u;
+ };
- 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]);
+-static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
++static u32 bbc_count_to_reg(struct bbc_beep_info *info, unsigned int count)
++{
++ u32 val, clock_freq = info->clock_freq;
++ int i;
++
++ if (!count)
++ return 0;
++
++ if (count <= clock_freq >> 20)
++ return 1 << 18;
++
++ if (count >= clock_freq >> 12)
++ return 1 << 10;
++
++ val = 1 << 18;
++ for (i = 19; i >= 11; i--) {
++ val >>= 1;
++ if (count <= clock_freq >> i)
++ break;
++ }
++
++ return val;
++}
++
++static int bbc_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+ {
+ struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent);
++ struct bbc_beep_info *info = &state->u.bbc;
+ unsigned int count = 0;
+ unsigned long flags;
- 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;
+@@ -44,24 +80,29 @@ static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned in
+ if (value > 20 && value < 32767)
+ count = 1193182 / value;
-- 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);
++ count = bbc_count_to_reg(info, count);
++
+ spin_lock_irqsave(&state->lock, flags);
- ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
- IDE_TFLAG_OUT_DEVICE, bcount, dma_ok);
+- /* EBUS speaker only has on/off state, the frequency does not
+- * appear to be programmable.
+- */
+- if (state->iobase & 0x2UL)
+- outb(!!count, state->iobase);
+- else
+- outl(!!count, state->iobase);
++ if (count) {
++ outb(0x01, info->regs + 0);
++ outb(0x00, info->regs + 2);
++ outb((count >> 16) & 0xff, info->regs + 3);
++ outb((count >> 8) & 0xff, info->regs + 4);
++ outb(0x00, info->regs + 5);
++ } else {
++ outb(0x00, info->regs + 0);
++ }
-- 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)
- }
+ spin_unlock_irqrestore(&state->lock, flags);
- /* 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;
+ return 0;
}
- 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)
+-static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
++static int grover_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
- idetape_tape_t *tape = drive->driver_data;
-- idetape_pc_t *pc = tape->pc;
-+ struct ide_atapi_pc *pc = tape->pc;
- u8 stat;
+ struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent);
++ struct grover_beep_info *info = &state->u.grover;
+ unsigned int count = 0;
+ unsigned long flags;
- 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;
+@@ -81,15 +122,15 @@ static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int
+
+ if (count) {
+ /* enable counter 2 */
+- outb(inb(state->iobase + 0x61) | 3, state->iobase + 0x61);
++ outb(inb(info->enable_reg) | 3, info->enable_reg);
+ /* set command for counter 2, 2 byte write */
+- outb(0xB6, state->iobase + 0x43);
++ outb(0xB6, info->freq_regs + 1);
+ /* select desired HZ */
+- outb(count & 0xff, state->iobase + 0x42);
+- outb((count >> 8) & 0xff, state->iobase + 0x42);
++ outb(count & 0xff, info->freq_regs + 0);
++ outb((count >> 8) & 0xff, info->freq_regs + 0);
+ } else {
+ /* disable counter 2 */
+- outb(inb_p(state->iobase + 0x61) & 0xFC, state->iobase + 0x61);
++ outb(inb_p(info->enable_reg) & 0xFC, info->enable_reg);
}
-- return pc->callback(drive);
-+ return pc->idetape_callback(drive);
+
+ spin_unlock_irqrestore(&state->lock, flags);
+@@ -131,7 +172,7 @@ static int __devinit sparcspkr_probe(struct device *dev)
+ return 0;
}
- static ide_startstop_t idetape_rw_callback(ide_drive_t *drive)
+-static int __devexit sparcspkr_remove(struct of_device *dev)
++static int sparcspkr_shutdown(struct of_device *dev)
{
- 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;
+ struct sparcspkr_state *state = dev_get_drvdata(&dev->dev);
+ struct input_dev *input_dev = state->input_dev;
+@@ -139,115 +180,180 @@ static int __devexit sparcspkr_remove(struct of_device *dev)
+ /* turn off the speaker */
+ state->event(input_dev, EV_SND, SND_BELL, 0);
- 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;
+- input_unregister_device(input_dev);
+-
+- dev_set_drvdata(&dev->dev, NULL);
+- kfree(state);
+-
+ return 0;
}
--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)
+-static int sparcspkr_shutdown(struct of_device *dev)
++static int __devinit bbc_beep_probe(struct of_device *op, const struct of_device_id *match)
{
- 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;
- }
+- struct sparcspkr_state *state = dev_get_drvdata(&dev->dev);
+- struct input_dev *input_dev = state->input_dev;
++ struct sparcspkr_state *state;
++ struct bbc_beep_info *info;
++ struct device_node *dp;
++ int err = -ENOMEM;
--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;
+- /* turn off the speaker */
+- state->event(input_dev, EV_SND, SND_BELL, 0);
++ state = kzalloc(sizeof(*state), GFP_KERNEL);
++ if (!state)
++ goto out_err;
++
++ state->name = "Sparc BBC Speaker";
++ state->event = bbc_spkr_event;
++ spin_lock_init(&state->lock);
++
++ dp = of_find_node_by_path("/");
++ err = -ENODEV;
++ if (!dp)
++ goto out_free;
++
++ info = &state->u.bbc;
++ info->clock_freq = of_getintprop_default(dp, "clock-frequency", 0);
++ if (!info->clock_freq)
++ goto out_free;
++
++ info->regs = of_ioremap(&op->resource[0], 0, 6, "bbc beep");
++ if (!info->regs)
++ goto out_free;
++
++ dev_set_drvdata(&op->dev, state);
++
++ err = sparcspkr_probe(&op->dev);
++ if (err)
++ goto out_clear_drvdata;
+
+ return 0;
++
++out_clear_drvdata:
++ dev_set_drvdata(&op->dev, NULL);
++ of_iounmap(&op->resource[0], info->regs, 6);
++
++out_free:
++ kfree(state);
++out_err:
++ return err;
}
- static ide_startstop_t idetape_do_request(ide_drive_t *drive,
- struct request *rq, sector_t block)
+-static int __devinit ebus_beep_probe(struct of_device *dev, const struct of_device_id *match)
++static int bbc_remove(struct of_device *op)
{
- 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;
+- struct linux_ebus_device *edev = to_ebus_device(&dev->dev);
+- struct sparcspkr_state *state;
+- int err;
++ struct sparcspkr_state *state = dev_get_drvdata(&op->dev);
++ struct input_dev *input_dev = state->input_dev;
++ struct bbc_beep_info *info = &state->u.bbc;
-@@ -1579,10 +1540,10 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
- stat = ide_read_status(drive);
+- state = kzalloc(sizeof(*state), GFP_KERNEL);
+- if (!state)
+- return -ENOMEM;
++ /* turn off the speaker */
++ state->event(input_dev, EV_SND, SND_BELL, 0);
- 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);
+- state->name = "Sparc EBUS Speaker";
+- state->iobase = edev->resource[0].start;
+- state->event = ebus_spkr_event;
+- spin_lock_init(&state->lock);
++ input_unregister_device(input_dev);
- if (drive->post_reset == 1) {
-- set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
-+ set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
- drive->post_reset = 0;
- }
+- dev_set_drvdata(&dev->dev, state);
++ of_iounmap(&op->resource[0], info->regs, 6);
-@@ -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;
+- err = sparcspkr_probe(&dev->dev);
+- if (err) {
+- dev_set_drvdata(&dev->dev, NULL);
+- kfree(state);
+- }
++ dev_set_drvdata(&op->dev, NULL);
++ kfree(state);
-- 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;
+ return 0;
}
-@@ -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__);
+-static struct of_device_id ebus_beep_match[] = {
++static struct of_device_id bbc_beep_match[] = {
+ {
+ .name = "beep",
++ .compatible = "SUNW,bbc-beep",
+ },
+ {},
+ };
-@@ -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 struct of_platform_driver ebus_beep_driver = {
+- .name = "beep",
+- .match_table = ebus_beep_match,
+- .probe = ebus_beep_probe,
+- .remove = __devexit_p(sparcspkr_remove),
++static struct of_platform_driver bbc_beep_driver = {
++ .name = "bbcbeep",
++ .match_table = bbc_beep_match,
++ .probe = bbc_beep_probe,
++ .remove = __devexit_p(bbc_remove),
+ .shutdown = sparcspkr_shutdown,
+ };
--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)
+-static int __devinit isa_beep_probe(struct of_device *dev, const struct of_device_id *match)
++static int __devinit grover_beep_probe(struct of_device *op, const struct of_device_id *match)
{
- idetape_init_pc(pc);
- pc->c[0] = TEST_UNIT_READY;
-- pc->callback = &idetape_pc_callback;
-+ pc->idetape_callback = &idetape_pc_callback;
- }
+- struct sparc_isa_device *idev = to_isa_device(&dev->dev);
+ struct sparcspkr_state *state;
+- int err;
++ struct grover_beep_info *info;
++ int err = -ENOMEM;
- /*
-@@ -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);
- }
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+- return -ENOMEM;
++ goto out_err;
--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;
- }
+- state->name = "Sparc ISA Speaker";
+- state->iobase = idev->resource.start;
+- state->event = isa_spkr_event;
++ state->name = "Sparc Grover Speaker";
++ state->event = grover_spkr_event;
+ spin_lock_init(&state->lock);
+
+- dev_set_drvdata(&dev->dev, state);
++ info = &state->u.grover;
++ info->freq_regs = of_ioremap(&op->resource[2], 0, 2, "grover beep freq");
++ if (!info->freq_regs)
++ goto out_free;
- 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;
+- err = sparcspkr_probe(&dev->dev);
+- if (err) {
+- dev_set_drvdata(&dev->dev, NULL);
+- kfree(state);
+- }
++ info->enable_reg = of_ioremap(&op->resource[3], 0, 1, "grover beep enable");
++ if (!info->enable_reg)
++ goto out_unmap_freq_regs;
++
++ dev_set_drvdata(&op->dev, state);
++
++ err = sparcspkr_probe(&op->dev);
++ if (err)
++ goto out_clear_drvdata;
++
++ return 0;
++
++out_clear_drvdata:
++ dev_set_drvdata(&op->dev, NULL);
++ of_iounmap(&op->resource[3], info->enable_reg, 1);
++
++out_unmap_freq_regs:
++ of_iounmap(&op->resource[2], info->freq_regs, 2);
++out_free:
++ kfree(state);
++out_err:
++ return err;
++}
++
++static int grover_remove(struct of_device *op)
++{
++ struct sparcspkr_state *state = dev_get_drvdata(&op->dev);
++ struct grover_beep_info *info = &state->u.grover;
++ struct input_dev *input_dev = state->input_dev;
++
++ /* turn off the speaker */
++ state->event(input_dev, EV_SND, SND_BELL, 0);
++
++ input_unregister_device(input_dev);
++
++ of_iounmap(&op->resource[3], info->enable_reg, 1);
++ of_iounmap(&op->resource[2], info->freq_regs, 2);
++
++ dev_set_drvdata(&op->dev, NULL);
++ kfree(state);
- /* 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;
+ return 0;
}
--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 struct of_device_id isa_beep_match[] = {
++static struct of_device_id grover_beep_match[] = {
+ {
+- .name = "dma",
++ .name = "beep",
++ .compatible = "SUNW,smbus-beep",
+ },
+ {},
+ };
- static int idetape_flush_tape_buffers(ide_drive_t *drive)
+-static struct of_platform_driver isa_beep_driver = {
+- .name = "beep",
+- .match_table = isa_beep_match,
+- .probe = isa_beep_probe,
+- .remove = __devexit_p(sparcspkr_remove),
++static struct of_platform_driver grover_beep_driver = {
++ .name = "groverbeep",
++ .match_table = grover_beep_match,
++ .probe = grover_beep_probe,
++ .remove = __devexit_p(grover_remove),
+ .shutdown = sparcspkr_shutdown,
+ };
+
+ static int __init sparcspkr_init(void)
+ {
+- int err = of_register_driver(&ebus_beep_driver, &ebus_bus_type);
++ int err = of_register_driver(&bbc_beep_driver,
++ &of_platform_bus_type);
+
+ if (!err) {
+- err = of_register_driver(&isa_beep_driver, &isa_bus_type);
++ err = of_register_driver(&grover_beep_driver,
++ &of_platform_bus_type);
+ if (err)
+- of_unregister_driver(&ebus_beep_driver);
++ of_unregister_driver(&bbc_beep_driver);
+ }
+
+ return err;
+@@ -255,8 +361,8 @@ static int __init sparcspkr_init(void)
+
+ static void __exit sparcspkr_exit(void)
{
-- idetape_pc_t pc;
-+ struct ide_atapi_pc pc;
- int rc;
+- of_unregister_driver(&ebus_beep_driver);
+- of_unregister_driver(&isa_beep_driver);
++ of_unregister_driver(&bbc_beep_driver);
++ of_unregister_driver(&grover_beep_driver);
+ }
- idetape_create_write_filemark_cmd(drive, &pc, 0);
-@@ -2016,18 +1977,18 @@ static int idetape_flush_tape_buffers(ide_drive_t *drive)
+ module_init(sparcspkr_init);
+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;
}
--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;
- }
++/* 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,
+ }
+ };
- 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;
+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.
- debug_log(DBG_PROCS, "Enter %s\n", __func__);
-@@ -2039,7 +2000,8 @@ static int idetape_read_position(ide_drive_t *drive)
- return position;
- }
++config SERIO_AT32PSIF
++ tristate "AVR32 PSIF PS/2 keyboard and mouse controller"
++ depends on AVR32
++ help
++ Say Y here if you want to use the PSIF peripheral on AVR32 devices
++ and connect a PS/2 keyboard and/or mouse to it.
++
++ To compile this driver as a module, choose M here: the module will
++ be called at32psif.
++
+ config SERIO_AMBAKMI
+ tristate "AMBA KMI keyboard controller"
+ depends on ARM_AMBA
+diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
+index 4155197..38b8868 100644
+--- a/drivers/input/serio/Makefile
++++ b/drivers/input/serio/Makefile
+@@ -12,6 +12,7 @@ obj-$(CONFIG_SERIO_CT82C710) += ct82c710.o
+ obj-$(CONFIG_SERIO_RPCKBD) += rpckbd.o
+ obj-$(CONFIG_SERIO_SA1111) += sa1111ps2.o
+ obj-$(CONFIG_SERIO_AMBAKMI) += ambakmi.o
++obj-$(CONFIG_SERIO_AT32PSIF) += at32psif.o
+ obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o
+ obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o
+ obj-$(CONFIG_HP_SDC) += hp_sdc.o
+diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c
+new file mode 100644
+index 0000000..41fda8c
+--- /dev/null
++++ b/drivers/input/serio/at32psif.c
+@@ -0,0 +1,375 @@
++/*
++ * Copyright (C) 2007 Atmel Corporation
++ *
++ * Driver for the AT32AP700X PS/2 controller (PSIF).
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/init.h>
++#include <linux/serio.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++
++/* PSIF register offsets */
++#define PSIF_CR 0x00
++#define PSIF_RHR 0x04
++#define PSIF_THR 0x08
++#define PSIF_SR 0x10
++#define PSIF_IER 0x14
++#define PSIF_IDR 0x18
++#define PSIF_IMR 0x1c
++#define PSIF_PSR 0x24
++
++/* Bitfields in control register. */
++#define PSIF_CR_RXDIS_OFFSET 1
++#define PSIF_CR_RXDIS_SIZE 1
++#define PSIF_CR_RXEN_OFFSET 0
++#define PSIF_CR_RXEN_SIZE 1
++#define PSIF_CR_SWRST_OFFSET 15
++#define PSIF_CR_SWRST_SIZE 1
++#define PSIF_CR_TXDIS_OFFSET 9
++#define PSIF_CR_TXDIS_SIZE 1
++#define PSIF_CR_TXEN_OFFSET 8
++#define PSIF_CR_TXEN_SIZE 1
++
++/* Bitfields in interrupt disable, enable, mask and status register. */
++#define PSIF_NACK_OFFSET 8
++#define PSIF_NACK_SIZE 1
++#define PSIF_OVRUN_OFFSET 5
++#define PSIF_OVRUN_SIZE 1
++#define PSIF_PARITY_OFFSET 9
++#define PSIF_PARITY_SIZE 1
++#define PSIF_RXRDY_OFFSET 4
++#define PSIF_RXRDY_SIZE 1
++#define PSIF_TXEMPTY_OFFSET 1
++#define PSIF_TXEMPTY_SIZE 1
++#define PSIF_TXRDY_OFFSET 0
++#define PSIF_TXRDY_SIZE 1
++
++/* Bitfields in prescale register. */
++#define PSIF_PSR_PRSCV_OFFSET 0
++#define PSIF_PSR_PRSCV_SIZE 12
++
++/* Bitfields in receive hold register. */
++#define PSIF_RHR_RXDATA_OFFSET 0
++#define PSIF_RHR_RXDATA_SIZE 8
++
++/* Bitfields in transmit hold register. */
++#define PSIF_THR_TXDATA_OFFSET 0
++#define PSIF_THR_TXDATA_SIZE 8
++
++/* Bit manipulation macros */
++#define PSIF_BIT(name) \
++ (1 << PSIF_##name##_OFFSET)
++
++#define PSIF_BF(name, value) \
++ (((value) & ((1 << PSIF_##name##_SIZE) - 1)) \
++ << PSIF_##name##_OFFSET)
++
++#define PSIF_BFEXT(name, value) \
++ (((value) >> PSIF_##name##_OFFSET) \
++ & ((1 << PSIF_##name##_SIZE) - 1))
++
++#define PSIF_BFINS(name, value, old) \
++ (((old) & ~(((1 << PSIF_##name##_SIZE) - 1) \
++ << PSIF_##name##_OFFSET)) \
++ | PSIF_BF(name, value))
++
++/* Register access macros */
++#define psif_readl(port, reg) \
++ __raw_readl((port)->regs + PSIF_##reg)
++
++#define psif_writel(port, reg, value) \
++ __raw_writel((value), (port)->regs + PSIF_##reg)
++
++struct psif {
++ struct platform_device *pdev;
++ struct clk *pclk;
++ struct serio *io;
++ void __iomem *regs;
++ unsigned int irq;
++ unsigned int open;
++ /* Prevent concurrent writes to PSIF THR. */
++ spinlock_t lock;
++};
++
++static irqreturn_t psif_interrupt(int irq, void *_ptr)
++{
++ struct psif *psif = _ptr;
++ int retval = IRQ_NONE;
++ unsigned int io_flags = 0;
++ unsigned long status;
++
++ status = psif_readl(psif, SR);
++
++ if (status & PSIF_BIT(RXRDY)) {
++ unsigned char val = (unsigned char) psif_readl(psif, RHR);
++
++ if (status & PSIF_BIT(PARITY))
++ io_flags |= SERIO_PARITY;
++ if (status & PSIF_BIT(OVRUN))
++ dev_err(&psif->pdev->dev, "overrun read error\n");
++
++ serio_interrupt(psif->io, val, io_flags);
++
++ retval = IRQ_HANDLED;
++ }
++
++ return retval;
++}
++
++static int psif_write(struct serio *io, unsigned char val)
++{
++ struct psif *psif = io->port_data;
++ unsigned long flags;
++ int timeout = 10;
++ int retval = 0;
++
++ spin_lock_irqsave(&psif->lock, flags);
++
++ while (!(psif_readl(psif, SR) & PSIF_BIT(TXEMPTY)) && timeout--)
++ msleep(10);
++
++ if (timeout >= 0) {
++ psif_writel(psif, THR, val);
++ } else {
++ dev_dbg(&psif->pdev->dev, "timeout writing to THR\n");
++ retval = -EBUSY;
++ }
++
++ spin_unlock_irqrestore(&psif->lock, flags);
++
++ return retval;
++}
++
++static int psif_open(struct serio *io)
++{
++ struct psif *psif = io->port_data;
++ int retval;
++
++ retval = clk_enable(psif->pclk);
++ if (retval)
++ goto out;
++
++ psif_writel(psif, CR, PSIF_BIT(CR_TXEN) | PSIF_BIT(CR_RXEN));
++ psif_writel(psif, IER, PSIF_BIT(RXRDY));
++
++ psif->open = 1;
++out:
++ return retval;
++}
++
++static void psif_close(struct serio *io)
++{
++ struct psif *psif = io->port_data;
++
++ psif->open = 0;
++
++ psif_writel(psif, IDR, ~0UL);
++ psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS));
++
++ clk_disable(psif->pclk);
++}
++
++static void psif_set_prescaler(struct psif *psif)
++{
++ unsigned long prscv;
++ unsigned long rate = clk_get_rate(psif->pclk);
++
++ /* PRSCV = Pulse length (100 us) * PSIF module frequency. */
++ prscv = 100 * (rate / 1000000UL);
++
++ if (prscv > ((1<<PSIF_PSR_PRSCV_SIZE) - 1)) {
++ prscv = (1<<PSIF_PSR_PRSCV_SIZE) - 1;
++ dev_dbg(&psif->pdev->dev, "pclk too fast, "
++ "prescaler set to max\n");
++ }
++
++ clk_enable(psif->pclk);
++ psif_writel(psif, PSR, prscv);
++ clk_disable(psif->pclk);
++}
++
++static int __init psif_probe(struct platform_device *pdev)
++{
++ struct resource *regs;
++ struct psif *psif;
++ struct serio *io;
++ struct clk *pclk;
++ int irq;
++ int ret;
++
++ psif = kzalloc(sizeof(struct psif), GFP_KERNEL);
++ if (!psif) {
++ dev_dbg(&pdev->dev, "out of memory\n");
++ ret = -ENOMEM;
++ goto out;
++ }
++ psif->pdev = pdev;
++
++ io = kzalloc(sizeof(struct serio), GFP_KERNEL);
++ if (!io) {
++ dev_dbg(&pdev->dev, "out of memory\n");
++ ret = -ENOMEM;
++ goto out_free_psif;
++ }
++ psif->io = io;
++
++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!regs) {
++ dev_dbg(&pdev->dev, "no mmio resources defined\n");
++ ret = -ENOMEM;
++ goto out_free_io;
++ }
++
++ psif->regs = ioremap(regs->start, regs->end - regs->start + 1);
++ if (!psif->regs) {
++ ret = -ENOMEM;
++ dev_dbg(&pdev->dev, "could not map I/O memory\n");
++ goto out_free_io;
++ }
++
++ pclk = clk_get(&pdev->dev, "pclk");
++ if (IS_ERR(pclk)) {
++ dev_dbg(&pdev->dev, "could not get peripheral clock\n");
++ ret = PTR_ERR(pclk);
++ goto out_iounmap;
++ }
++ psif->pclk = pclk;
++
++ /* Reset the PSIF to enter at a known state. */
++ ret = clk_enable(pclk);
++ if (ret) {
++ dev_dbg(&pdev->dev, "could not enable pclk\n");
++ goto out_put_clk;
++ }
++ psif_writel(psif, CR, PSIF_BIT(CR_SWRST));
++ clk_disable(pclk);
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_dbg(&pdev->dev, "could not get irq\n");
++ ret = -ENXIO;
++ goto out_put_clk;
++ }
++ ret = request_irq(irq, psif_interrupt, IRQF_SHARED, "at32psif", psif);
++ if (ret) {
++ dev_dbg(&pdev->dev, "could not request irq %d\n", irq);
++ goto out_put_clk;
++ }
++ psif->irq = irq;
++
++ io->id.type = SERIO_8042;
++ io->write = psif_write;
++ io->open = psif_open;
++ io->close = psif_close;
++ snprintf(io->name, sizeof(io->name), "AVR32 PS/2 port%d", pdev->id);
++ snprintf(io->phys, sizeof(io->phys), "at32psif/serio%d", pdev->id);
++ io->port_data = psif;
++ io->dev.parent = &pdev->dev;
++
++ psif_set_prescaler(psif);
++
++ spin_lock_init(&psif->lock);
++ serio_register_port(psif->io);
++ platform_set_drvdata(pdev, psif);
++
++ dev_info(&pdev->dev, "Atmel AVR32 PSIF PS/2 driver on 0x%08x irq %d\n",
++ (int)psif->regs, psif->irq);
++
++ return 0;
++
++out_put_clk:
++ clk_put(psif->pclk);
++out_iounmap:
++ iounmap(psif->regs);
++out_free_io:
++ kfree(io);
++out_free_psif:
++ kfree(psif);
++out:
++ return ret;
++}
++
++static int __exit psif_remove(struct platform_device *pdev)
++{
++ struct psif *psif = platform_get_drvdata(pdev);
++
++ psif_writel(psif, IDR, ~0UL);
++ psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS));
++
++ serio_unregister_port(psif->io);
++ iounmap(psif->regs);
++ free_irq(psif->irq, psif);
++ clk_put(psif->pclk);
++ kfree(psif);
++
++ platform_set_drvdata(pdev, NULL);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int psif_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ struct psif *psif = platform_get_drvdata(pdev);
++
++ if (psif->open) {
++ psif_writel(psif, CR, PSIF_BIT(CR_RXDIS) | PSIF_BIT(CR_TXDIS));
++ clk_disable(psif->pclk);
++ }
++
++ return 0;
++}
++
++static int psif_resume(struct platform_device *pdev)
++{
++ struct psif *psif = platform_get_drvdata(pdev);
++
++ if (psif->open) {
++ clk_enable(psif->pclk);
++ psif_set_prescaler(psif);
++ psif_writel(psif, CR, PSIF_BIT(CR_RXEN) | PSIF_BIT(CR_TXEN));
++ }
++
++ return 0;
++}
++#else
++#define psif_suspend NULL
++#define psif_resume NULL
++#endif
++
++static struct platform_driver psif_driver = {
++ .remove = __exit_p(psif_remove),
++ .driver = {
++ .name = "atmel_psif",
++ },
++ .suspend = psif_suspend,
++ .resume = psif_resume,
++};
++
++static int __init psif_init(void)
++{
++ return platform_driver_probe(&psif_driver, psif_probe);
++}
++
++static void __exit psif_exit(void)
++{
++ platform_driver_unregister(&psif_driver);
++}
++
++module_init(psif_init);
++module_exit(psif_exit);
++
++MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt at atmel.com>");
++MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
+index c45ea74..f1fd3b6 100644
+--- a/drivers/input/serio/hp_sdc_mlc.c
++++ b/drivers/input/serio/hp_sdc_mlc.c
+@@ -40,7 +40,7 @@
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/string.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
--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;
- }
+ #define PREFIX "HP SDC MLC: "
--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;
+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);
-@@ -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;
- }
+- 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));
+ }
-@@ -2078,7 +2040,7 @@ static int __idetape_discard_read_pipeline(ide_drive_t *drive)
+ 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);
- /* 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)
+- 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));
}
- /* Clear pipeline flags. */
-- clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
-+ clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags);
- tape->chrdev_dir = IDETAPE_DIR_NONE;
+ 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");
- /* Remove pipeline stages. */
-@@ -2124,7 +2086,7 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
+ static int rpckbd_write(struct serio *port, unsigned char val)
{
- idetape_tape_t *tape = drive->driver_data;
- int retval;
-- idetape_pc_t pc;
-+ struct ide_atapi_pc pc;
+@@ -140,6 +141,7 @@ static struct platform_driver rpckbd_driver = {
+ .remove = __devexit_p(rpckbd_remove),
+ .driver = {
+ .name = "kart",
++ .owner = THIS_MODULE,
+ },
+ };
- 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);
- }
+diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
+index e1a3a79..7ff71ba 100644
+--- a/drivers/input/serio/serport.c
++++ b/drivers/input/serio/serport.c
+@@ -46,7 +46,7 @@ struct serport {
+ static int serport_serio_write(struct serio *serio, unsigned char data)
+ {
+ struct serport *serport = serio->port_data;
+- return -(serport->tty->driver->write(serport->tty, &data, 1) != 1);
++ return -(serport->tty->ops->write(serport->tty, &data, 1) != 1);
}
--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 int serport_serio_open(struct serio *serio)
+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.
--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;
- }
+ 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.
--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;
- }
+ 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..55c1134 100644
+--- a/drivers/input/tablet/aiptek.c
++++ b/drivers/input/tablet/aiptek.c
+@@ -184,6 +184,7 @@
+ */
--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;
- }
+ #define USB_VENDOR_ID_AIPTEK 0x08ca
++#define USB_VENDOR_ID_KYE 0x0458
+ #define USB_REQ_GET_REPORT 0x01
+ #define USB_REQ_SET_REPORT 0x09
+
+@@ -527,9 +528,9 @@ static void aiptek_irq(struct urb *urb)
+ (aiptek->curSetting.pointerMode)) {
+ aiptek->diagnostic = AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED;
+ } else {
+- x = le16_to_cpu(get_unaligned((__le16 *) (data + 1)));
+- y = le16_to_cpu(get_unaligned((__le16 *) (data + 3)));
+- z = le16_to_cpu(get_unaligned((__le16 *) (data + 6)));
++ x = get_unaligned_le16(data + 1);
++ y = get_unaligned_le16(data + 3);
++ z = get_unaligned_le16(data + 6);
+
+ dv = (data[5] & 0x01) != 0 ? 1 : 0;
+ p = (data[5] & 0x02) != 0 ? 1 : 0;
+@@ -612,8 +613,8 @@ static void aiptek_irq(struct urb *urb)
+ (aiptek->curSetting.pointerMode)) {
+ aiptek->diagnostic = AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED;
+ } else {
+- x = le16_to_cpu(get_unaligned((__le16 *) (data + 1)));
+- y = le16_to_cpu(get_unaligned((__le16 *) (data + 3)));
++ x = get_unaligned_le16(data + 1);
++ y = get_unaligned_le16(data + 3);
+
+ jitterable = data[5] & 0x1c;
+
+@@ -678,7 +679,7 @@ static void aiptek_irq(struct urb *urb)
+ pck = (data[1] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0;
+
+ macro = dv && p && tip && !(data[3] & 1) ? (data[3] >> 1) : -1;
+- z = le16_to_cpu(get_unaligned((__le16 *) (data + 4)));
++ z = get_unaligned_le16(data + 4);
+
+ if (dv) {
+ /* If the selected tool changed, reset the old
+@@ -756,7 +757,7 @@ static void aiptek_irq(struct urb *urb)
+ * hat switches (which just so happen to be the macroKeys.)
+ */
+ else if (data[0] == 6) {
+- macro = le16_to_cpu(get_unaligned((__le16 *) (data + 1)));
++ macro = get_unaligned_le16(data + 1);
+ if (macro > 0) {
+ input_report_key(inputdev, macroKeyEvents[macro - 1],
+ 0);
+@@ -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)},
+ {}
+ };
- 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);
+@@ -950,7 +952,7 @@ aiptek_query(struct aiptek *aiptek, unsigned char command, unsigned char data)
+ buf[0], buf[1], buf[2]);
+ ret = -EIO;
+ } else {
+- ret = le16_to_cpu(get_unaligned((__le16 *) (buf + 1)));
++ ret = get_unaligned_le16(buf + 1);
+ }
+ kfree(buf);
+ return ret;
+diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c
+index d2c6da2..c5a8661 100644
+--- a/drivers/input/tablet/gtco.c
++++ b/drivers/input/tablet/gtco.c
+@@ -245,11 +245,11 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
+ data = report[i];
+ break;
+ case 2:
+- data16 = le16_to_cpu(get_unaligned((__le16 *)&report[i]));
++ data16 = get_unaligned_le16(&report[i]);
+ break;
+ case 3:
+ size = 4;
+- data32 = le32_to_cpu(get_unaligned((__le32 *)&report[i]));
++ data32 = get_unaligned_le32(&report[i]);
+ break;
}
+
+@@ -695,10 +695,10 @@ static void gtco_urb_callback(struct urb *urbinfo)
+ /* Fall thru */
+ case 1:
+ /* All reports have X and Y coords in the same place */
+- val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1]));
++ val = get_unaligned_le16(&device->buffer[1]);
+ input_report_abs(inputdev, ABS_X, val);
+
+- val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3]));
++ val = get_unaligned_le16(&device->buffer[3]);
+ input_report_abs(inputdev, ABS_Y, val);
+
+ /* Ditto for proximity bit */
+@@ -762,7 +762,7 @@ static void gtco_urb_callback(struct urb *urbinfo)
+ le_buffer[1] = (u8)(device->buffer[4] >> 1);
+ le_buffer[1] |= (u8)((device->buffer[5] & 0x1) << 7);
+
+- val = le16_to_cpu(get_unaligned((__le16 *)le_buffer));
++ val = get_unaligned_le16(le_buffer);
+ input_report_abs(inputdev, ABS_Y, val);
+
+ /*
+@@ -772,10 +772,10 @@ static void gtco_urb_callback(struct urb *urbinfo)
+ buttonbyte = device->buffer[5] >> 1;
+ } else {
+
+- val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1]));
++ val = get_unaligned_le16(&device->buffer[1]);
+ input_report_abs(inputdev, ABS_X, val);
+
+- val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3]));
++ val = get_unaligned_le16(&device->buffer[3]);
+ input_report_abs(inputdev, ABS_Y, val);
+
+ buttonbyte = device->buffer[5];
+@@ -897,7 +897,7 @@ static int gtco_probe(struct usb_interface *usbinterface,
+ dbg("Extra descriptor success: type:%d len:%d",
+ hid_desc->bDescriptorType, hid_desc->wDescriptorLength);
+
+- report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
++ report = kzalloc(le16_to_cpu(hid_desc->wDescriptorLength), GFP_KERNEL);
+ if (!report) {
+ err("No more memory for report");
+ error = -ENOMEM;
+@@ -913,16 +913,16 @@ static int gtco_probe(struct usb_interface *usbinterface,
+ REPORT_DEVICE_TYPE << 8,
+ 0, /* interface */
+ report,
+- hid_desc->wDescriptorLength,
++ le16_to_cpu(hid_desc->wDescriptorLength),
+ 5000); /* 5 secs */
+
+- if (result == hid_desc->wDescriptorLength)
++ if (result == le16_to_cpu(hid_desc->wDescriptorLength))
+ break;
}
-- 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;
+
+ /* If we didn't get the report, fail */
+ dbg("usb_control_msg result: :%d", result);
+- if (result != hid_desc->wDescriptorLength) {
++ if (result != le16_to_cpu(hid_desc->wDescriptorLength)) {
+ err("Failed to get HID Report Descriptor of size: %d",
+ hid_desc->wDescriptorLength);
+ error = -EIO;
+diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c
+index 1182fc1..f23f5a9 100644
+--- a/drivers/input/tablet/kbtab.c
++++ b/drivers/input/tablet/kbtab.c
+@@ -63,8 +63,8 @@ static void kbtab_irq(struct urb *urb)
+ goto exit;
}
-- 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);
+- kbtab->x = le16_to_cpu(get_unaligned((__le16 *) &data[1]));
+- kbtab->y = le16_to_cpu(get_unaligned((__le16 *) &data[3]));
++ kbtab->x = get_unaligned_le16(&data[1]);
++ kbtab->y = get_unaligned_le16(&data[3]);
- /* 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;
+ kbtab->pressure = (data[5]);
- /* 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;
+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];
+ };
-@@ -2681,7 +2644,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
- int mt_count)
+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)
{
- 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);
+ struct wacom *wacom = input_get_drvdata(dev);
- 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);
++ 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;
- idetape_space_over_filemarks(drive, MTFSF, 1);
-@@ -2938,7 +2902,7 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
++ mutex_unlock(&wacom->lock);
+ return 0;
+ }
- static int idetape_write_filemark(ide_drive_t *drive)
+@@ -135,7 +151,11 @@ static void wacom_close(struct input_dev *dev)
{
-- idetape_pc_t pc;
-+ struct ide_atapi_pc pc;
+ struct wacom *wacom = input_get_drvdata(dev);
- /* 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;
++ mutex_lock(&wacom->lock);
+ usb_kill_urb(wacom->irq);
++ wacom->open = 0;
++ wacom->intf->needs_remote_wakeup = 0;
++ mutex_unlock(&wacom->lock);
+ }
- 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)
+ 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)
{
- idetape_tape_t *tape = drive->driver_data;
-- idetape_pc_t pc;
-+ struct ide_atapi_pc pc;
+- struct wacom *wacom = usb_get_intfdata (intf);
++ struct wacom *wacom = usb_get_intfdata(intf);
- 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;
+ 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 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;
+ 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,
+ };
- if (i >= MAX_HWIFS * MAX_DRIVES)
-@@ -3195,24 +3159,24 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
+ 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.
- filp->private_data = tape;
++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 @@
-- 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;
- }
+ # Each configuration option enables a list of files.
- 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;
- }
++wm97xx-ts-y := wm97xx-core.o
++
+ obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
+ obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
+ obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o
+@@ -19,3 +21,8 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
+ obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
+ obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
+ obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
++obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
++wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
++wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
++wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
++obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
+diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
+index 57a1c28..907a45f 100644
+--- a/drivers/input/touchscreen/ads7846.c
++++ b/drivers/input/touchscreen/ads7846.c
+@@ -28,13 +28,6 @@
+ #include <linux/spi/ads7846.h>
+ #include <asm/irq.h>
- 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);
+-#ifdef CONFIG_ARM
+-#include <asm/mach-types.h>
+-#ifdef CONFIG_ARCH_OMAP
+-#include <asm/arch/gpio.h>
+-#endif
+-#endif
+-
- if (tape->chrdev_dir != IDETAPE_DIR_READ)
-- clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
-+ clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags);
+ /*
+ * This code has been heavily tested on a Nokia 770, and lightly
+@@ -87,6 +80,7 @@ struct ads7846 {
+ #endif
- /* 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);
+ 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");
- 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;
+ 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;
}
-- 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)
- }
+
+ 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;
}
- }
-- 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];
+ 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)
- 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);
+ ts->spi = spi;
+ ts->input = input_dev;
++ ts->vref_mv = pdata->vref_mv;
- 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)
+ 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)
{
- idetape_tape_t *tape = drive->driver_data;
-- idetape_pc_t pc;
-+ struct ide_atapi_pc pc;
- u8 *caps;
- u8 speed, max_speed;
+- /* 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);
-@@ -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];
+diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
+index 99d92f5..4e9d8ee 100644
+--- a/drivers/input/touchscreen/corgi_ts.c
++++ b/drivers/input/touchscreen/corgi_ts.c
+@@ -22,6 +22,7 @@
+ #include <asm/arch/sharpsl.h>
+ #include <asm/arch/hardware.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
- /* 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);
+ #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,
+ },
+ };
- 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);
+@@ -380,3 +382,4 @@ module_exit(corgits_exit);
+ MODULE_AUTHOR("Richard Purdie <rpurdie at rpsys.net>");
+ MODULE_DESCRIPTION("Corgi TouchScreen Driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:corgi-ts");
+diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c
+index 42a1c9a..7422421 100644
+--- a/drivers/input/touchscreen/jornada720_ts.c
++++ b/drivers/input/touchscreen/jornada720_ts.c
+@@ -160,11 +160,15 @@ static int __devexit jornada720_ts_remove(struct platform_device *pdev)
+ return 0;
+ }
- 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]);
++/* 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,
+ },
+ };
- 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]);
+diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c
+new file mode 100644
+index 0000000..a79f029
+--- /dev/null
++++ b/drivers/input/touchscreen/mainstone-wm97xx.c
+@@ -0,0 +1,302 @@
++/*
++ * mainstone-wm97xx.c -- Mainstone Continuous Touch screen driver for
++ * Wolfson WM97xx AC97 Codecs.
++ *
++ * Copyright 2004, 2007 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ * liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro at f2s.com>
++ * Andrew Zabolotny <zap at homelink.ru>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * Notes:
++ * This is a wm97xx extended touch driver to capture touch
++ * data in a continuous manner on the Intel XScale archictecture
++ *
++ * Features:
++ * - codecs supported:- WM9705, WM9712, WM9713
++ * - processors supported:- Intel XScale PXA25x, PXA26x, PXA27x
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/wm97xx.h>
++#include <linux/io.h>
++#include <asm/arch/pxa-regs.h>
++
++#define VERSION "0.13"
++
++struct continuous {
++ u16 id; /* codec id */
++ u8 code; /* continuous code */
++ u8 reads; /* number of coord reads per read cycle */
++ u32 speed; /* number of coords per second */
++};
++
++#define WM_READS(sp) ((sp / HZ) + 1)
++
++static const struct continuous cinfo[] = {
++ {WM9705_ID2, 0, WM_READS(94), 94},
++ {WM9705_ID2, 1, WM_READS(188), 188},
++ {WM9705_ID2, 2, WM_READS(375), 375},
++ {WM9705_ID2, 3, WM_READS(750), 750},
++ {WM9712_ID2, 0, WM_READS(94), 94},
++ {WM9712_ID2, 1, WM_READS(188), 188},
++ {WM9712_ID2, 2, WM_READS(375), 375},
++ {WM9712_ID2, 3, WM_READS(750), 750},
++ {WM9713_ID2, 0, WM_READS(94), 94},
++ {WM9713_ID2, 1, WM_READS(120), 120},
++ {WM9713_ID2, 2, WM_READS(154), 154},
++ {WM9713_ID2, 3, WM_READS(188), 188},
++};
++
++/* continuous speed index */
++static int sp_idx;
++static u16 last, tries;
++
++/*
++ * Pen sampling frequency (Hz) in continuous mode.
++ */
++static int cont_rate = 200;
++module_param(cont_rate, int, 0);
++MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
++
++/*
++ * Pen down detection.
++ *
++ * This driver can either poll or use an interrupt to indicate a pen down
++ * event. If the irq request fails then it will fall back to polling mode.
++ */
++static int pen_int;
++module_param(pen_int, int, 0);
++MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)");
++
++/*
++ * Pressure readback.
++ *
++ * Set to 1 to read back pen down pressure
++ */
++static int pressure;
++module_param(pressure, int, 0);
++MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
++
++/*
++ * AC97 touch data slot.
++ *
++ * Touch screen readback data ac97 slot
++ */
++static int ac97_touch_slot = 5;
++module_param(ac97_touch_slot, int, 0);
++MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
++
++
++/* flush AC97 slot 5 FIFO on pxa machines */
++#ifdef CONFIG_PXA27x
++static void wm97xx_acc_pen_up(struct wm97xx *wm)
++{
++ schedule_timeout_uninterruptible(1);
++
++ while (MISR & (1 << 2))
++ MODR;
++}
++#else
++static void wm97xx_acc_pen_up(struct wm97xx *wm)
++{
++ int count = 16;
++ schedule_timeout_uninterruptible(1);
++
++ while (count < 16) {
++ MODR;
++ count--;
++ }
++}
++#endif
++
++static int wm97xx_acc_pen_down(struct wm97xx *wm)
++{
++ u16 x, y, p = 0x100 | WM97XX_ADCSEL_PRES;
++ int reads = 0;
++
++ /* When the AC97 queue has been drained we need to allow time
++ * to buffer up samples otherwise we end up spinning polling
++ * for samples. The controller can't have a suitably low
++ * threashold set to use the notifications it gives.
++ */
++ schedule_timeout_uninterruptible(1);
++
++ if (tries > 5) {
++ tries = 0;
++ return RC_PENUP;
++ }
++
++ x = MODR;
++ if (x == last) {
++ tries++;
++ return RC_AGAIN;
++ }
++ last = x;
++ do {
++ if (reads)
++ x = MODR;
++ y = MODR;
++ if (pressure)
++ p = MODR;
++
++ /* are samples valid */
++ if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X ||
++ (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y ||
++ (p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES)
++ goto up;
++
++ /* coordinate is good */
++ tries = 0;
++ input_report_abs(wm->input_dev, ABS_X, x & 0xfff);
++ input_report_abs(wm->input_dev, ABS_Y, y & 0xfff);
++ input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff);
++ input_sync(wm->input_dev);
++ reads++;
++ } while (reads < cinfo[sp_idx].reads);
++up:
++ return RC_PENDOWN | RC_AGAIN;
++}
++
++static int wm97xx_acc_startup(struct wm97xx *wm)
++{
++ int idx = 0;
++
++ /* check we have a codec */
++ if (wm->ac97 == NULL)
++ return -ENODEV;
++
++ /* Go you big red fire engine */
++ for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
++ if (wm->id != cinfo[idx].id)
++ continue;
++ sp_idx = idx;
++ if (cont_rate <= cinfo[idx].speed)
++ break;
++ }
++ wm->acc_rate = cinfo[sp_idx].code;
++ wm->acc_slot = ac97_touch_slot;
++ dev_info(wm->dev,
++ "mainstone accelerated touchscreen driver, %d samples/sec\n",
++ cinfo[sp_idx].speed);
++
++ /* codec specific irq config */
++ if (pen_int) {
++ switch (wm->id) {
++ case WM9705_ID2:
++ wm->pen_irq = IRQ_GPIO(4);
++ set_irq_type(IRQ_GPIO(4), IRQT_BOTHEDGE);
++ break;
++ case WM9712_ID2:
++ case WM9713_ID2:
++ /* enable pen down interrupt */
++ /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */
++ wm->pen_irq = MAINSTONE_AC97_IRQ;
++ wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
++ WM97XX_GPIO_POL_HIGH,
++ WM97XX_GPIO_STICKY,
++ WM97XX_GPIO_WAKE);
++ wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT,
++ WM97XX_GPIO_POL_HIGH,
++ WM97XX_GPIO_NOTSTICKY,
++ WM97XX_GPIO_NOWAKE);
++ break;
++ default:
++ dev_err(wm->dev,
++ "pen down irq not supported on this device\n");
++ pen_int = 0;
++ break;
++ }
++ }
++
++ return 0;
++}
++
++static void wm97xx_acc_shutdown(struct wm97xx *wm)
++{
++ /* codec specific deconfig */
++ if (pen_int) {
++ switch (wm->id & 0xffff) {
++ case WM9705_ID2:
++ wm->pen_irq = 0;
++ break;
++ case WM9712_ID2:
++ case WM9713_ID2:
++ /* disable interrupt */
++ wm->pen_irq = 0;
++ break;
++ }
++ }
++}
++
++static void wm97xx_irq_enable(struct wm97xx *wm, int enable)
++{
++ if (enable)
++ enable_irq(wm->pen_irq);
++ else
++ disable_irq(wm->pen_irq);
++}
++
++static struct wm97xx_mach_ops mainstone_mach_ops = {
++ .acc_enabled = 1,
++ .acc_pen_up = wm97xx_acc_pen_up,
++ .acc_pen_down = wm97xx_acc_pen_down,
++ .acc_startup = wm97xx_acc_startup,
++ .acc_shutdown = wm97xx_acc_shutdown,
++ .irq_enable = wm97xx_irq_enable,
++ .irq_gpio = WM97XX_GPIO_2,
++};
++
++static int mainstone_wm97xx_probe(struct platform_device *pdev)
++{
++ struct wm97xx *wm = platform_get_drvdata(pdev);
++
++ return wm97xx_register_mach_ops(wm, &mainstone_mach_ops);
++}
++
++static int mainstone_wm97xx_remove(struct platform_device *pdev)
++{
++ struct wm97xx *wm = platform_get_drvdata(pdev);
++
++ wm97xx_unregister_mach_ops(wm);
++ return 0;
++}
++
++static struct platform_driver mainstone_wm97xx_driver = {
++ .probe = mainstone_wm97xx_probe,
++ .remove = mainstone_wm97xx_remove,
++ .driver = {
++ .name = "wm97xx-touch",
++ },
++};
++
++static int __init mainstone_wm97xx_init(void)
++{
++ return platform_driver_register(&mainstone_wm97xx_driver);
++}
++
++static void __exit mainstone_wm97xx_exit(void)
++{
++ platform_driver_unregister(&mainstone_wm97xx_driver);
++}
++
++module_init(mainstone_wm97xx_init);
++module_exit(mainstone_wm97xx_exit);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
++MODULE_DESCRIPTION("wm97xx continuous touch driver for mainstone");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
+index 607f993..bce018e 100644
+--- a/drivers/input/touchscreen/ucb1400_ts.c
++++ b/drivers/input/touchscreen/ucb1400_ts.c
+@@ -427,10 +427,6 @@ static int ucb1400_detect_irq(struct ucb1400 *ucb)
+ unsigned long mask, timeout;
- 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]);
+ mask = probe_irq_on();
+- if (!mask) {
+- probe_irq_off(mask);
+- return -EBUSY;
+- }
- 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]);
+ /* 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;
}
- 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;
+diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c
+new file mode 100644
+index 0000000..978e1a1
+--- /dev/null
++++ b/drivers/input/touchscreen/wm9705.c
+@@ -0,0 +1,353 @@
++/*
++ * wm9705.c -- Codec driver for Wolfson WM9705 AC97 Codec.
++ *
++ * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ * liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro at f2s.com>
++ * Andrew Zabolotny <zap at homelink.ru>
++ * Russell King <rmk at arm.linux.org.uk>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/input.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/wm97xx.h>
++
++#define TS_NAME "wm97xx"
++#define WM9705_VERSION "1.00"
++#define DEFAULT_PRESSURE 0xb0c0
++
++/*
++ * Module parameters
++ */
++
++/*
++ * Set current used for pressure measurement.
++ *
++ * Set pil = 2 to use 400uA
++ * pil = 1 to use 200uA and
++ * pil = 0 to disable pressure measurement.
++ *
++ * This is used to increase the range of values returned by the adc
++ * when measureing touchpanel pressure.
++ */
++static int pil;
++module_param(pil, int, 0);
++MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
++
++/*
++ * Set threshold for pressure measurement.
++ *
++ * Pen down pressure below threshold is ignored.
++ */
++static int pressure = DEFAULT_PRESSURE & 0xfff;
++module_param(pressure, int, 0);
++MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
+
- 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);
++/*
++ * 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.");
+
-+ ide_port_init_devices_data(hwif);
++/*
++ * 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]);
+}
-+EXPORT_SYMBOL_GPL(ide_init_port_data);
+
-+static void ide_port_init_devices_data(ide_hwif_t *hwif)
++/*
++ * set up the physical settings of the WM9705
++ */
++static void wm9705_phy_init(struct wm97xx *wm)
+{
-+ int unit;
++ u16 dig1 = 0, dig2 = WM97XX_RPR;
+
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
-+ u8 j = (hwif->index * MAX_DRIVES) + unit;
++ /*
++ * 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);
+
-+ 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;
++ /* 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;
+
- 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];
++ /* 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]);
+
- 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;
++ /* WM9705 pdd */
++ dig2 |= (pdd & 0x000f);
++ dev_dbg(wm->dev, "setting pdd to Vmid/%d", 1 - (pdd & 0x000f));
+
- addr = hwif->io_ports[IDE_CONTROL_OFFSET];
++ /* mask */
++ dig2 |= ((mask & 0x3) << 4);
+
- if (addr && !hwif_request_region(hwif, addr, 1))
- goto control_region_busy;
-- hwif->straight8 = 0;
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
++}
+
- 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]);
++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);
++}
+
-+ if (!hwif_request_region(hwif, addr, 8))
-+ goto data_region_busy;
++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);
++}
+
- 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;
++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]);
++}
+
- 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)
++static inline int is_pden(struct wm97xx *wm)
+{
-+ int i;
++ return wm->dig[2] & WM9705_PDEN;
++}
+
-+ for (i = 0; i < MAX_DRIVES; i++) {
-+ ide_drive_t *drive = &hwif->drives[i];
++/*
++ * 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 (drive->present) {
-+ spin_unlock_irq(&ide_lock);
-+ device_unregister(&drive->gendev);
-+ wait_for_completion(&drive->gendev_rel_comp);
-+ spin_lock_irq(&ide_lock);
-+ }
++ 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;
+}
+
-+void ide_port_unregister_devices(ide_hwif_t *hwif)
++/*
++ * Sample the WM9705 touchscreen in polling mode
++ */
++static int wm9705_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
+{
-+ 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);
++ 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;
+}
-+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)
++/*
++ * Enable WM9705 continuous mode, i.e. touch data is streamed across
++ * an AC97 slot
++ */
++static int wm9705_acc_enable(struct wm97xx *wm, int enable)
+{
-+ ide_hwif_t *hwif = dev_get_drvdata(portdev);
++ u16 dig1, dig2;
++ int ret = 0;
+
-+ put_device(&hwif->gendev);
++ 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;
+}
+
- /*
- * 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;
++struct wm97xx_codec_drv wm9705_codec = {
++ .id = WM9705_ID2,
++ .name = "wm9705",
++ .poll_sample = wm9705_poll_sample,
++ .poll_touch = wm9705_poll_touch,
++ .acc_enable = wm9705_acc_enable,
++ .phy_init = wm9705_phy_init,
++ .dig_enable = wm9705_dig_enable,
++ .dig_restore = wm9705_dig_restore,
++ .aux_prepare = wm9705_aux_prepare,
++};
++EXPORT_SYMBOL_GPL(wm9705_codec);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
++MODULE_DESCRIPTION("WM9705 Touch Screen Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c
+new file mode 100644
+index 0000000..0b6e4cf
+--- /dev/null
++++ b/drivers/input/touchscreen/wm9712.c
+@@ -0,0 +1,462 @@
++/*
++ * wm9712.c -- Codec driver for Wolfson WM9712 AC97 Codecs.
++ *
++ * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ * liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro at f2s.com>
++ * Andrew Zabolotny <zap at homelink.ru>
++ * Russell King <rmk at arm.linux.org.uk>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/input.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/wm97xx.h>
++
++#define TS_NAME "wm97xx"
++#define WM9712_VERSION "1.00"
++#define DEFAULT_PRESSURE 0xb0c0
++
++/*
++ * Module parameters
++ */
++
++/*
++ * Set internal pull up for pen detect.
++ *
++ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
++ * i.e. pull up resistance = 64k Ohms / rpu.
++ *
++ * Adjust this value if you are having problems with pen detect not
++ * detecting any down event.
++ */
++static int rpu = 8;
++module_param(rpu, int, 0);
++MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
++
++/*
++ * Set current used for pressure measurement.
++ *
++ * Set pil = 2 to use 400uA
++ * pil = 1 to use 200uA and
++ * pil = 0 to disable pressure measurement.
++ *
++ * This is used to increase the range of values returned by the adc
++ * when measureing touchpanel pressure.
++ */
++static int pil;
++module_param(pil, int, 0);
++MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
++
++/*
++ * Set threshold for pressure measurement.
++ *
++ * Pen down pressure below threshold is ignored.
++ */
++static int pressure = DEFAULT_PRESSURE & 0xfff;
++module_param(pressure, int, 0);
++MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
++
++/*
++ * Set adc sample delay.
++ *
++ * For accurate touchpanel measurements, some settling time may be
++ * required between the switch matrix applying a voltage across the
++ * touchpanel plate and the ADC sampling the signal.
++ *
++ * This delay can be set by setting delay = n, where n is the array
++ * position of the delay in the array delay_table below.
++ * Long delays > 1ms are supported for completeness, but are not
++ * recommended.
++ */
++static int delay = 3;
++module_param(delay, int, 0);
++MODULE_PARM_DESC(delay, "Set adc sample delay.");
++
++/*
++ * Set five_wire = 1 to use a 5 wire touchscreen.
++ *
++ * NOTE: Five wire mode does not allow for readback of pressure.
++ */
++static int five_wire;
++module_param(five_wire, int, 0);
++MODULE_PARM_DESC(five_wire, "Set to '1' to use 5-wire touchscreen.");
++
++/*
++ * Set adc mask function.
++ *
++ * Sources of glitch noise, such as signals driving an LCD display, may feed
++ * through to the touch screen plates and affect measurement accuracy. In
++ * order to minimise this, a signal may be applied to the MASK pin to delay or
++ * synchronise the sampling.
++ *
++ * 0 = No delay or sync
++ * 1 = High on pin stops conversions
++ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
++ * 3 = Edge triggered, edge on pin starts conversion after delay param
++ */
++static int mask;
++module_param(mask, int, 0);
++MODULE_PARM_DESC(mask, "Set adc mask function.");
++
++/*
++ * Coordinate Polling Enable.
++ *
++ * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
++ * for every poll.
++ */
++static int coord;
++module_param(coord, int, 0);
++MODULE_PARM_DESC(coord, "Polling coordinate mode");
++
++/*
++ * ADC sample delay times in uS
++ */
++static const int delay_table[] = {
++ 21, /* 1 AC97 Link frames */
++ 42, /* 2 */
++ 84, /* 4 */
++ 167, /* 8 */
++ 333, /* 16 */
++ 667, /* 32 */
++ 1000, /* 48 */
++ 1333, /* 64 */
++ 2000, /* 96 */
++ 2667, /* 128 */
++ 3333, /* 160 */
++ 4000, /* 192 */
++ 4667, /* 224 */
++ 5333, /* 256 */
++ 6000, /* 288 */
++ 0 /* No delay, switch matrix always on */
++};
++
++/*
++ * Delay after issuing a POLL command.
++ *
++ * The delay is 3 AC97 link frames + the touchpanel settling delay
++ */
++static inline void poll_delay(int d)
++{
++ udelay(3 * AC97_LINK_FRAME + delay_table[d]);
++}
++
++/*
++ * set up the physical settings of the WM9712
++ */
++static void wm9712_phy_init(struct wm97xx *wm)
++{
++ u16 dig1 = 0;
++ u16 dig2 = WM97XX_RPR | WM9712_RPU(1);
++
++ /* WM9712 rpu */
++ if (rpu) {
++ dig2 &= 0xffc0;
++ dig2 |= WM9712_RPU(rpu);
++ dev_dbg(wm->dev, "setting pen detect pull-up to %d Ohms",
++ 64000 / rpu);
+ }
-+ ide_port_class->dev_release = ide_port_class_release;
+
- init_ide_data();
-
- proc_ide_create();
-
- return 0;
++ /* 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;
+
-+out_port_class:
-+ bus_unregister(&ide_bus_type);
++ /* WM9712 five wire */
++ if (five_wire) {
++ dig2 |= WM9712_45W;
++ dev_dbg(wm->dev, "setting 5-wire touchscreen mode.");
++ }
+
-+ 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);
++ /* 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]);
+
- 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)
++ /* 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)
+{
- 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));
++ u16 dig2 = wm->dig[2];
+
-+ ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
-+ hw[0].irq = 14;
++ 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);
++}
+
-+ ide_std_init_ports(&hw[1], 0x170, 0x376);
-+ hw[1].irq = 15;
++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);
++}
+
-+ 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;
++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;
+ }
+
-+ 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;
++ /* 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--;
+ }
-
- 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;
++ 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;
++ }
+
-+ ide_std_init_ports(&hw[1], 0x170, 0x376);
-+ hw[1].irq = 15;
++ *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++ if (wm->mach_ops && wm->mach_ops->post_sample)
++ wm->mach_ops->post_sample(adcsel);
+
-+ 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;
++ /* 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;
+ }
+
-+ mate = ide_find_port();
-+ if (mate) {
-+ ide_init_port_hw(mate, &hw[1]);
-+ idx[1] = mate->index;
++ if (!(*sample & WM97XX_PEN_DOWN)) {
++ wm->pen_probably_down = 0;
++ return RC_PENUP;
+ }
-
- ide_device_add(idx, &dtc2278_port_info);
-
-diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
-index e950afa..8c9c9f7 100644
---- a/drivers/ide/legacy/falconide.c
-+++ b/drivers/ide/legacy/falconide.c
-@@ -22,6 +22,7 @@
- #include <asm/atariints.h>
- #include <asm/atari_stdma.h>
-
-+#define DRV_NAME "falconide"
-
- /*
- * Base of the IDE interface
-@@ -74,15 +75,21 @@ static int __init falconide_init(void)
-
- printk(KERN_INFO "ide: Falcon IDE controller\n");
-
-+ if (!request_mem_region(ATA_HD_BASE, 0x40, DRV_NAME)) {
-+ printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
-+ return -EBUSY;
++
++ 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;
+ }
+
- 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;
- };
--
++ /* set up digitiser */
++ if (wm->mach_ops && wm->mach_ops->pre_sample)
++ wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
+
- #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)
++ 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 ints[6];
-
- (void) get_options(line, ARRAY_SIZE(ints), ints);
-diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c
-index 78ca68e..60f52f5 100644
---- a/drivers/ide/legacy/ht6560b.c
-+++ b/drivers/ide/legacy/ht6560b.c
-@@ -35,6 +35,7 @@
- * Try: http://www.maf.iki.fi/~maf/ht6560b/
- */
-
-+#define DRV_NAME "ht6560b"
- #define HT6560B_VERSION "v0.08"
-
- #include <linux/module.h>
-@@ -82,7 +83,7 @@
- * out how they setup those cycle time interfacing values, as they at Holtek
- * call them. IDESETUP.COM that is supplied with the drivers figures out
- * optimal values and fetches those values to drivers. I found out that
-- * they use IDE_SELECT_REG to fetch timings to the ide board right after
-+ * they use Select register to fetch timings to the ide board right after
- * interface switching. After that it was quite easy to add code to
- * ht6560b.c.
- *
-@@ -127,6 +128,7 @@
- */
- static void ht6560b_selectproc (ide_drive_t *drive)
- {
-+ ide_hwif_t *hwif = drive->hwif;
- unsigned long flags;
- static u8 current_select = 0;
- static u8 current_timing = 0;
-@@ -155,8 +157,8 @@ static void ht6560b_selectproc (ide_drive_t *drive)
- /*
- * Set timing for this drive:
- */
-- outb(timing, IDE_SELECT_REG);
-- (void)inb(IDE_STATUS_REG);
-+ outb(timing, hwif->io_ports[IDE_SELECT_OFFSET]);
-+ (void)inb(hwif->io_ports[IDE_STATUS_OFFSET]);
- #ifdef DEBUG
- printk("ht6560b: %s: select=%#x timing=%#x\n",
- drive->name, select, timing);
-@@ -193,9 +195,9 @@ static int __init try_to_init_ht6560b(void)
- * Ht6560b autodetected
- */
- outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT);
-- outb(HT_TIMING_DEFAULT, 0x1f6); /* IDE_SELECT_REG */
-- (void) inb(0x1f7); /* IDE_STATUS_REG */
--
-+ outb(HT_TIMING_DEFAULT, 0x1f6); /* Select register */
-+ (void)inb(0x1f7); /* Status register */
++ int rc;
++
++ if (coord) {
++ rc = wm9712_poll_coord(wm, data);
++ if (rc != RC_VALID)
++ return rc;
++ } else {
++ rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X, &data->x);
++ if (rc != RC_VALID)
++ return rc;
++
++ rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y);
++ if (rc != RC_VALID)
++ return rc;
++
++ if (pil && !five_wire) {
++ rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES,
++ &data->p);
++ if (rc != RC_VALID)
++ return rc;
++ } else
++ data->p = DEFAULT_PRESSURE;
++ }
++ return RC_VALID;
++}
++
++/*
++ * Enable WM9712 continuous mode, i.e. touch data is streamed across
++ * an AC97 slot
++ */
++static int wm9712_acc_enable(struct wm97xx *wm, int enable)
++{
++ u16 dig1, dig2;
++ int ret = 0;
++
++ dig1 = wm->dig[1];
++ dig2 = wm->dig[2];
++
++ if (enable) {
++ /* continous mode */
++ if (wm->mach_ops->acc_startup) {
++ ret = wm->mach_ops->acc_startup(wm);
++ if (ret < 0)
++ return ret;
++ }
++ dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
++ WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
++ dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
++ WM97XX_DELAY(delay) |
++ WM97XX_SLT(wm->acc_slot) |
++ WM97XX_RATE(wm->acc_rate);
++ if (pil)
++ dig1 |= WM97XX_ADCSEL_PRES;
++ dig2 |= WM9712_PDEN;
++ } else {
++ dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
++ dig2 &= ~WM9712_PDEN;
++ if (wm->mach_ops->acc_shutdown)
++ wm->mach_ops->acc_shutdown(wm);
++ }
++
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
++
++ return 0;
++}
++
++struct wm97xx_codec_drv wm9712_codec = {
++ .id = WM9712_ID2,
++ .name = "wm9712",
++ .poll_sample = wm9712_poll_sample,
++ .poll_touch = wm9712_poll_touch,
++ .acc_enable = wm9712_acc_enable,
++ .phy_init = wm9712_phy_init,
++ .dig_enable = wm9712_dig_enable,
++ .dig_restore = wm9712_dig_restore,
++ .aux_prepare = wm9712_aux_prepare,
++};
++EXPORT_SYMBOL_GPL(wm9712_codec);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
++MODULE_DESCRIPTION("WM9712 Touch Screen Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c
+new file mode 100644
+index 0000000..01278bd
+--- /dev/null
++++ b/drivers/input/touchscreen/wm9713.c
+@@ -0,0 +1,460 @@
++/*
++ * wm9713.c -- Codec touch driver for Wolfson WM9713 AC97 Codec.
++ *
++ * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ * liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro at f2s.com>
++ * Andrew Zabolotny <zap at homelink.ru>
++ * Russell King <rmk at arm.linux.org.uk>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/input.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/wm97xx.h>
++
++#define TS_NAME "wm97xx"
++#define WM9713_VERSION "1.00"
++#define DEFAULT_PRESSURE 0xb0c0
++
++/*
++ * Module parameters
++ */
++
++/*
++ * Set internal pull up for pen detect.
++ *
++ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
++ * i.e. pull up resistance = 64k Ohms / rpu.
++ *
++ * Adjust this value if you are having problems with pen detect not
++ * detecting any down event.
++ */
++static int rpu = 8;
++module_param(rpu, int, 0);
++MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
++
++/*
++ * Set current used for pressure measurement.
++ *
++ * Set pil = 2 to use 400uA
++ * pil = 1 to use 200uA and
++ * pil = 0 to disable pressure measurement.
++ *
++ * This is used to increase the range of values returned by the adc
++ * when measureing touchpanel pressure.
++ */
++static int pil;
++module_param(pil, int, 0);
++MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
++
++/*
++ * Set threshold for pressure measurement.
++ *
++ * Pen down pressure below threshold is ignored.
++ */
++static int pressure = DEFAULT_PRESSURE & 0xfff;
++module_param(pressure, int, 0);
++MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
++
++/*
++ * Set adc sample delay.
++ *
++ * For accurate touchpanel measurements, some settling time may be
++ * required between the switch matrix applying a voltage across the
++ * touchpanel plate and the ADC sampling the signal.
++ *
++ * This delay can be set by setting delay = n, where n is the array
++ * position of the delay in the array delay_table below.
++ * Long delays > 1ms are supported for completeness, but are not
++ * recommended.
++ */
++static int delay = 4;
++module_param(delay, int, 0);
++MODULE_PARM_DESC(delay, "Set adc sample delay.");
++
++/*
++ * Set adc mask function.
++ *
++ * Sources of glitch noise, such as signals driving an LCD display, may feed
++ * through to the touch screen plates and affect measurement accuracy. In
++ * order to minimise this, a signal may be applied to the MASK pin to delay or
++ * synchronise the sampling.
++ *
++ * 0 = No delay or sync
++ * 1 = High on pin stops conversions
++ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
++ * 3 = Edge triggered, edge on pin starts conversion after delay param
++ */
++static int mask;
++module_param(mask, int, 0);
++MODULE_PARM_DESC(mask, "Set adc mask function.");
++
++/*
++ * Coordinate Polling Enable.
++ *
++ * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
++ * for every poll.
++ */
++static int coord;
++module_param(coord, int, 0);
++MODULE_PARM_DESC(coord, "Polling coordinate mode");
++
++/*
++ * ADC sample delay times in uS
++ */
++static const int delay_table[] = {
++ 21, /* 1 AC97 Link frames */
++ 42, /* 2 */
++ 84, /* 4 */
++ 167, /* 8 */
++ 333, /* 16 */
++ 667, /* 32 */
++ 1000, /* 48 */
++ 1333, /* 64 */
++ 2000, /* 96 */
++ 2667, /* 128 */
++ 3333, /* 160 */
++ 4000, /* 192 */
++ 4667, /* 224 */
++ 5333, /* 256 */
++ 6000, /* 288 */
++ 0 /* No delay, switch matrix always on */
++};
++
++/*
++ * Delay after issuing a POLL command.
++ *
++ * The delay is 3 AC97 link frames + the touchpanel settling delay
++ */
++static inline void poll_delay(int d)
++{
++ udelay(3 * AC97_LINK_FRAME + delay_table[d]);
++}
++
++/*
++ * set up the physical settings of the WM9713
++ */
++static void wm9713_phy_init(struct wm97xx *wm)
++{
++ u16 dig1 = 0, dig2, dig3;
++
++ /* default values */
++ dig2 = WM97XX_DELAY(4) | WM97XX_SLT(5);
++ dig3 = WM9712_RPU(1);
++
++ /* rpu */
++ if (rpu) {
++ dig3 &= 0xffc0;
++ dig3 |= WM9712_RPU(rpu);
++ dev_info(wm->dev, "setting pen detect pull-up to %d Ohms\n",
++ 64000 / rpu);
++ }
++
++ /* touchpanel pressure */
++ if (pil == 2) {
++ dig3 |= WM9712_PIL;
++ dev_info(wm->dev,
++ "setting pressure measurement current to 400uA.");
++ } else if (pil)
++ dev_info(wm->dev,
++ "setting pressure measurement current to 200uA.");
++ if (!pil)
++ pressure = 0;
++
++ /* sample settling delay */
++ if (delay < 0 || delay > 15) {
++ dev_info(wm->dev, "supplied delay out of range.");
++ delay = 4;
++ dev_info(wm->dev, "setting adc sample delay to %d u Secs.",
++ delay_table[delay]);
++ }
++ dig2 &= 0xff0f;
++ dig2 |= WM97XX_DELAY(delay);
++
++ /* mask */
++ dig3 |= ((mask & 0x3) << 4);
++ if (coord)
++ dig3 |= WM9713_WAIT;
++
++ wm->misc = wm97xx_reg_read(wm, 0x5a);
++
++ wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
++ wm97xx_reg_write(wm, AC97_GPIO_STICKY, 0x0);
++}
++
++static void wm9713_dig_enable(struct wm97xx *wm, int enable)
++{
++ u16 val;
++
++ if (enable) {
++ val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
++ wm97xx_reg_write(wm, AC97_EXTENDED_MID, val & 0x7fff);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] |
++ WM97XX_PRP_DET_DIG);
++ wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
++ } else {
++ wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] &
++ ~WM97XX_PRP_DET_DIG);
++ val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
++ wm97xx_reg_write(wm, AC97_EXTENDED_MID, val | 0x8000);
++ }
++}
++
++static void wm9713_dig_restore(struct wm97xx *wm)
++{
++ wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig_save[0]);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig_save[1]);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig_save[2]);
++}
++
++static void wm9713_aux_prepare(struct wm97xx *wm)
++{
++ memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
++ wm97xx_reg_write(wm, AC97_WM9713_DIG1, 0);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG2, 0);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG3, WM97XX_PRP_DET_DIG);
++}
++
++static inline int is_pden(struct wm97xx *wm)
++{
++ return wm->dig[2] & WM9713_PDEN;
++}
++
++/*
++ * Read a sample from the WM9713 adc in polling mode.
++ */
++static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
++{
++ u16 dig1;
++ int timeout = 5 * delay;
++
++ if (!wm->pen_probably_down) {
++ u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++ if (!(data & WM97XX_PEN_DOWN))
++ return RC_PENUP;
++ wm->pen_probably_down = 1;
++ }
++
++ /* set up digitiser */
++ if (adcsel & 0x8000)
++ adcsel = 1 << ((adcsel & 0x7fff) + 3);
++
++ dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
++ dig1 &= ~WM9713_ADCSEL_MASK;
++
++ if (wm->mach_ops && wm->mach_ops->pre_sample)
++ wm->mach_ops->pre_sample(adcsel);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | adcsel | WM9713_POLL);
+
- 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));
++ /* wait 3 AC97 time slots + delay for conversion */
++ poll_delay(delay);
+
-+ 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;
++ /* wait for POLL to go low */
++ while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL) &&
++ timeout) {
++ udelay(AC97_LINK_FRAME);
++ timeout--;
+ }
+
-+ 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;
++ 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;
+ }
-
- ide_device_add(idx, &ht6560b_port_info);
-
-diff --git a/drivers/ide/legacy/ide-4drives.c b/drivers/ide/legacy/ide-4drives.c
-new file mode 100644
-index 0000000..c352f12
---- /dev/null
-+++ b/drivers/ide/legacy/ide-4drives.c
-@@ -0,0 +1,56 @@
+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/ide.h>
++ *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++ if (wm->mach_ops && wm->mach_ops->post_sample)
++ wm->mach_ops->post_sample(adcsel);
+
-+int probe_4drives;
++ /* 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;
++ }
+
-+module_param_named(probe, probe_4drives, bool, 0);
-+MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port");
++ if (!(*sample & WM97XX_PEN_DOWN)) {
++ wm->pen_probably_down = 0;
++ return RC_PENUP;
++ }
+
-+static int __init ide_4drives_init(void)
++ 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)
+{
-+ ide_hwif_t *hwif, *mate;
-+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-+ hw_regs_t hw;
++ u16 dig1;
++ int timeout = 5 * delay;
+
-+ if (probe_4drives == 0)
-+ return -ENODEV;
++ 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;
++ }
+
-+ memset(&hw, 0, sizeof(hw));
++ /* set up digitiser */
++ dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
++ dig1 &= ~WM9713_ADCSEL_MASK;
++ if (pil)
++ dig1 |= WM9713_ADCSEL_PRES;
+
-+ ide_std_init_ports(&hw, 0x1f0, 0x3f6);
-+ hw.irq = 14;
-+ hw.chipset = ide_4drives;
++ 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);
+
-+ hwif = ide_find_port();
-+ if (hwif) {
-+ ide_init_port_hw(hwif, &hw);
-+ idx[0] = hwif->index;
++ /* 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--;
+ }
+
-+ 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;
-+ }
++ 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;
+ }
+
-+ ide_device_add(idx, NULL);
++ /* 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;
+}
+
-+module_init(ide_4drives_init);
++/*
++ * Sample the WM9713 touchscreen in polling mode
++ */
++static int wm9713_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
++{
++ int rc;
+
-+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;
++ 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;
++}
+
-+ memset(&hw, 0, sizeof(hw));
++/*
++ * 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;
+
-+ ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
-+ hw[0].irq = 14;
++ dig1 = wm->dig[0];
++ dig2 = wm->dig[1];
++ dig3 = wm->dig[2];
+
-+ ide_std_init_ports(&hw[1], 0x170, 0x376);
-+ hw[1].irq = 15;
++ if (enable) {
++ /* continous mode */
++ if (wm->mach_ops->acc_startup &&
++ (ret = wm->mach_ops->acc_startup(wm)) < 0)
++ return ret;
+
- 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);
++ 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);
++ }
+
-+ d.host_flags |= IDE_HFLAG_SINGLE;
++ wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
+
-+ hwif = ide_find_port_slot(&d);
-+ if (hwif == NULL)
-+ return -ENOENT;
++ return ret;
++}
+
-+ ide_init_port_hw(hwif, &hw[unit]);
++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);
+
-+ 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");
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
++MODULE_DESCRIPTION("WM9713 Touch Screen Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
+new file mode 100644
+index 0000000..e9c7ea4
+--- /dev/null
++++ b/drivers/input/touchscreen/wm97xx-core.c
+@@ -0,0 +1,829 @@
++/*
++ * wm97xx-core.c -- Touch screen driver core for Wolfson WM9705, WM9712
++ * and WM9713 AC97 Codecs.
++ *
++ * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ * liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro at f2s.com>
++ * Andrew Zabolotny <zap at homelink.ru>
++ * Russell King <rmk at arm.linux.org.uk>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * Notes:
++ *
++ * Features:
++ * - supports WM9705, WM9712, WM9713
++ * - polling mode
++ * - continuous mode (arch-dependent)
++ * - adjustable rpu/dpp settings
++ * - adjustable pressure current
++ * - adjustable sample settle delay
++ * - 4 and 5 wire touchscreens (5 wire is WM9712 only)
++ * - pen down detection
++ * - battery monitor
++ * - sample AUX adcs
++ * - power management
++ * - codec GPIO
++ * - codec event notification
++ * Todo
++ * - Support for async sampling control for noisy LCDs.
++ *
++ */
+
-+ d.host_flags |= IDE_HFLAG_SINGLE;
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/string.h>
++#include <linux/proc_fs.h>
++#include <linux/pm.h>
++#include <linux/interrupt.h>
++#include <linux/bitops.h>
++#include <linux/workqueue.h>
++#include <linux/wm97xx.h>
++#include <linux/uaccess.h>
++#include <linux/io.h>
+
-+ 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]);
++#define TS_NAME "wm97xx"
++#define WM_CORE_VERSION "1.00"
++#define DEFAULT_PRESSURE 0xb0c0
+
-+ 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;
-+ }
++/*
++ * 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.
++ */
+
-+ 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;
++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");
+
- 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);
++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");
+
-+ if (rc1 < 0 && rc2 < 0)
- return -ENODEV;
++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");
+
- 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));
++/*
++ * 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);
+
-+ ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
-+ hw[0].irq = 14;
++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;
+
-+ ide_std_init_ports(&hw[1], 0x170, 0x376);
-+ hw[1].irq = 15;
++ /* cache gpio regs */
++ if (reg >= AC97_GPIO_CFG && reg <= AC97_MISC_AFE)
++ wm->gpio[(reg - AC97_GPIO_CFG) >> 1] = val;
+
-+ 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;
-+ }
++ /* wm9713 irq reg */
++ if (reg == 0x5a)
++ wm->misc = val;
+
-+ 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;
++ 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);
+ }
-
- memset(&hw, 0, sizeof(hw));
- auide_setup_ports(&hw, ahwif);
-@@ -613,9 +615,6 @@ static int au_ide_probe(struct device *dev)
-
- hwif->dev = dev;
-
-- /* hold should be on in all cases */
-- hwif->hold = 1;
--
- hwif->mmio = 1;
-
- /* If the user has selected DDMA assisted copies,
-@@ -673,7 +672,7 @@ static int au_ide_remove(struct device *dev)
- ide_hwif_t *hwif = dev_get_drvdata(dev);
- _auide_hwif *ahwif = &auide_hwif;
-
-- ide_unregister(hwif->index, 0, 0);
-+ ide_unregister(hwif->index);
-
- iounmap((void *)ahwif->regbase);
-
-diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
-index 956259f..bbe8d58 100644
---- a/drivers/ide/mips/swarm.c
-+++ b/drivers/ide/mips/swarm.c
-@@ -76,17 +76,12 @@ static int __devinit swarm_ide_probe(struct device *dev)
- if (!SIBYTE_HAVE_IDE)
- return -ENODEV;
-
-- /* Find an empty slot. */
-- for (i = 0; i < MAX_HWIFS; i++)
-- if (!ide_hwifs[i].io_ports[IDE_DATA_OFFSET])
-- break;
-- if (i >= MAX_HWIFS) {
-+ hwif = ide_find_port();
-+ if (hwif == NULL) {
- printk(KERN_ERR DRV_NAME ": no free slot for interface\n");
- return -ENOMEM;
- }
-
-- hwif = ide_hwifs + i;
--
- base = ioremap(A_IO_EXT_BASE, 0x800);
- offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS));
- size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS));
-diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
-index cfb3265..c9ba15a 100644
---- a/drivers/ide/pci/aec62xx.c
-+++ b/drivers/ide/pci/aec62xx.c
-@@ -220,7 +220,8 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
- .init_hwif = init_hwif_aec62xx,
- .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
- .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
-- IDE_HFLAG_ABUSE_SET_DMA_MODE,
-+ IDE_HFLAG_ABUSE_SET_DMA_MODE |
-+ IDE_HFLAG_NON_BOOTABLE,
- .pio_mask = ATA_PIO4,
- .mwdma_mask = ATA_MWDMA2,
- .udma_mask = ATA_UDMA4,
-diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
-index b3b6f51..3fa2d9f 100644
---- a/drivers/ide/pci/alim15x3.c
-+++ b/drivers/ide/pci/alim15x3.c
-@@ -750,7 +750,6 @@ static const struct ide_port_info ali15x3_chipset __devinitdata = {
- .init_chipset = init_chipset_ali15x3,
- .init_hwif = init_hwif_ali15x3,
- .init_dma = init_dma_ali15x3,
-- .host_flags = IDE_HFLAG_BOOTABLE,
- .pio_mask = ATA_PIO5,
- .swdma_mask = ATA_SWDMA2,
- .mwdma_mask = ATA_MWDMA2,
-diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
-index 2ef890c..ff684d3 100644
---- a/drivers/ide/pci/amd74xx.c
-+++ b/drivers/ide/pci/amd74xx.c
-@@ -219,12 +219,10 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
-
- #define IDE_HFLAGS_AMD \
- (IDE_HFLAG_PIO_NO_BLACKLIST | \
-- IDE_HFLAG_PIO_NO_DOWNGRADE | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
- IDE_HFLAG_POST_SET_MODE | \
- IDE_HFLAG_IO_32BIT | \
-- IDE_HFLAG_UNMASK_IRQS | \
-- IDE_HFLAG_BOOTABLE)
-+ IDE_HFLAG_UNMASK_IRQS)
-
- #define DECLARE_AMD_DEV(name_str, swdma, udma) \
- { \
-diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
-index 7e037c8..91722f8 100644
---- a/drivers/ide/pci/atiixp.c
-+++ b/drivers/ide/pci/atiixp.c
-@@ -151,7 +151,7 @@ static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
- .name = "ATIIXP",
- .init_hwif = init_hwif_atiixp,
- .enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
-- .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
-+ .host_flags = IDE_HFLAG_LEGACY_IRQS,
- .pio_mask = ATA_PIO4,
- .mwdma_mask = ATA_MWDMA2,
- .udma_mask = ATA_UDMA5,
-@@ -159,8 +159,7 @@ static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
- .name = "SB600_PATA",
- .init_hwif = init_hwif_atiixp,
- .enablebits = {{0x48,0x01,0x00}, {0x00,0x00,0x00}},
-- .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS |
-- IDE_HFLAG_BOOTABLE,
-+ .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS,
- .pio_mask = ATA_PIO4,
- .mwdma_mask = ATA_MWDMA2,
- .udma_mask = ATA_UDMA5,
-diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
-index 29fbc5e..b076dbf 100644
---- a/drivers/ide/pci/cmd640.c
-+++ b/drivers/ide/pci/cmd640.c
-@@ -4,7 +4,7 @@
-
- /*
- * Original authors: abramov at cecmow.enet.dec.com (Igor Abramov)
-- * mlord at pobox.com (Mark Lord)
-+ * mlord at pobox.com (Mark Lord)
- *
- * See linux/MAINTAINERS for address of current maintainer.
- *
-@@ -98,7 +98,7 @@
-
- #define CMD640_PREFETCH_MASKS 1
-
--//#define CMD640_DUMP_REGS
-+/*#define CMD640_DUMP_REGS */
-
- #include <linux/types.h>
- #include <linux/kernel.h>
-@@ -112,7 +112,7 @@
- /*
- * This flag is set in ide.c by the parameter: ide0=cmd640_vlb
- */
--int cmd640_vlb = 0;
-+int cmd640_vlb;
-
- /*
- * CMD640 specific registers definition.
-@@ -185,7 +185,6 @@ static DEFINE_SPINLOCK(cmd640_lock);
- * These are initialized to point at the devices we control
- */
- static ide_hwif_t *cmd_hwif0, *cmd_hwif1;
--static ide_drive_t *cmd_drives[4];
-
- /*
- * Interface to access cmd640x registers
-@@ -207,13 +206,13 @@ static unsigned int cmd640_chip_version;
-
- /* PCI method 1 access */
-
--static void put_cmd640_reg_pci1 (u16 reg, u8 val)
-+static void put_cmd640_reg_pci1(u16 reg, u8 val)
- {
- outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
- outb_p(val, (reg & 3) | 0xcfc);
- }
-
--static u8 get_cmd640_reg_pci1 (u16 reg)
-+static u8 get_cmd640_reg_pci1(u16 reg)
- {
- outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
- return inb_p((reg & 3) | 0xcfc);
-@@ -221,14 +220,14 @@ static u8 get_cmd640_reg_pci1 (u16 reg)
-
- /* PCI method 2 access (from CMD datasheet) */
-
--static void put_cmd640_reg_pci2 (u16 reg, u8 val)
-+static void put_cmd640_reg_pci2(u16 reg, u8 val)
- {
- outb_p(0x10, 0xcf8);
- outb_p(val, cmd640_key + reg);
- outb_p(0, 0xcf8);
- }
-
--static u8 get_cmd640_reg_pci2 (u16 reg)
-+static u8 get_cmd640_reg_pci2(u16 reg)
- {
- u8 b;
-
-@@ -240,13 +239,13 @@ static u8 get_cmd640_reg_pci2 (u16 reg)
-
- /* VLB access */
-
--static void put_cmd640_reg_vlb (u16 reg, u8 val)
-+static void put_cmd640_reg_vlb(u16 reg, u8 val)
- {
- outb_p(reg, cmd640_key);
- outb_p(val, cmd640_key + 4);
- }
-
--static u8 get_cmd640_reg_vlb (u16 reg)
-+static u8 get_cmd640_reg_vlb(u16 reg)
- {
- outb_p(reg, cmd640_key);
- return inb_p(cmd640_key + 4);
-@@ -268,11 +267,11 @@ static void put_cmd640_reg(u16 reg, u8 val)
- unsigned long flags;
-
- spin_lock_irqsave(&cmd640_lock, flags);
-- __put_cmd640_reg(reg,val);
-+ __put_cmd640_reg(reg, val);
- spin_unlock_irqrestore(&cmd640_lock, flags);
- }
-
--static int __init match_pci_cmd640_device (void)
-+static int __init match_pci_cmd640_device(void)
- {
- const u8 ven_dev[4] = {0x95, 0x10, 0x40, 0x06};
- unsigned int i;
-@@ -292,7 +291,7 @@ static int __init match_pci_cmd640_device (void)
- /*
- * Probe for CMD640x -- pci method 1
- */
--static int __init probe_for_cmd640_pci1 (void)
-+static int __init probe_for_cmd640_pci1(void)
- {
- __get_cmd640_reg = get_cmd640_reg_pci1;
- __put_cmd640_reg = put_cmd640_reg_pci1;
-@@ -308,7 +307,7 @@ static int __init probe_for_cmd640_pci1 (void)
- /*
- * Probe for CMD640x -- pci method 2
- */
--static int __init probe_for_cmd640_pci2 (void)
-+static int __init probe_for_cmd640_pci2(void)
- {
- __get_cmd640_reg = get_cmd640_reg_pci2;
- __put_cmd640_reg = put_cmd640_reg_pci2;
-@@ -322,7 +321,7 @@ static int __init probe_for_cmd640_pci2 (void)
- /*
- * Probe for CMD640x -- vlb
- */
--static int __init probe_for_cmd640_vlb (void)
-+static int __init probe_for_cmd640_vlb(void)
- {
- u8 b;
-
-@@ -343,7 +342,7 @@ static int __init probe_for_cmd640_vlb (void)
- * Returns 1 if an IDE interface/drive exists at 0x170,
- * Returns 0 otherwise.
- */
--static int __init secondary_port_responding (void)
-+static int __init secondary_port_responding(void)
- {
- unsigned long flags;
-
-@@ -367,7 +366,7 @@ static int __init secondary_port_responding (void)
- /*
- * Dump out all cmd640 registers. May be called from ide.c
- */
--static void cmd640_dump_regs (void)
-+static void cmd640_dump_regs(void)
- {
- unsigned int reg = cmd640_vlb ? 0x50 : 0x00;
-
-@@ -386,9 +385,8 @@ static void cmd640_dump_regs (void)
- * Check whether prefetch is on for a drive,
- * and initialize the unmask flags for safe operation.
- */
--static void __init check_prefetch (unsigned int index)
-+static void __init check_prefetch(ide_drive_t *drive, unsigned int index)
- {
-- ide_drive_t *drive = cmd_drives[index];
- u8 b = get_cmd640_reg(prefetch_regs[index]);
-
- if (b & prefetch_masks[index]) { /* is prefetch off? */
-@@ -404,38 +402,13 @@ static void __init check_prefetch (unsigned int index)
- }
- }
-
--/*
-- * Figure out which devices we control
-- */
--static void __init setup_device_ptrs (void)
--{
-- unsigned int i;
--
-- cmd_hwif0 = &ide_hwifs[0]; /* default, if not found below */
-- cmd_hwif1 = &ide_hwifs[1]; /* default, if not found below */
-- for (i = 0; i < MAX_HWIFS; i++) {
-- ide_hwif_t *hwif = &ide_hwifs[i];
-- if (hwif->chipset == ide_unknown || hwif->chipset == ide_forced) {
-- if (hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0)
-- cmd_hwif0 = hwif;
-- else if (hwif->io_ports[IDE_DATA_OFFSET] == 0x170)
-- cmd_hwif1 = hwif;
-- }
-- }
-- cmd_drives[0] = &cmd_hwif0->drives[0];
-- cmd_drives[1] = &cmd_hwif0->drives[1];
-- cmd_drives[2] = &cmd_hwif1->drives[0];
-- cmd_drives[3] = &cmd_hwif1->drives[1];
--}
--
- #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
-
- /*
- * Sets prefetch mode for a drive.
- */
--static void set_prefetch_mode (unsigned int index, int mode)
-+static void set_prefetch_mode(ide_drive_t *drive, unsigned int index, int mode)
- {
-- ide_drive_t *drive = cmd_drives[index];
- unsigned long flags;
- int reg = prefetch_regs[index];
- u8 b;
-@@ -462,7 +435,7 @@ static void set_prefetch_mode (unsigned int index, int mode)
- /*
- * Dump out current drive clocks settings
- */
--static void display_clocks (unsigned int index)
-+static void display_clocks(unsigned int index)
- {
- u8 active_count, recovery_count;
-
-@@ -481,7 +454,7 @@ static void display_clocks (unsigned int index)
- * Pack active and recovery counts into single byte representation
- * used by controller
- */
--static inline u8 pack_nibbles (u8 upper, u8 lower)
-+static inline u8 pack_nibbles(u8 upper, u8 lower)
- {
- return ((upper & 0x0f) << 4) | (lower & 0x0f);
- }
-@@ -489,7 +462,7 @@ static inline u8 pack_nibbles (u8 upper, u8 lower)
- /*
- * This routine retrieves the initial drive timings from the chipset.
- */
--static void __init retrieve_drive_counts (unsigned int index)
-+static void __init retrieve_drive_counts(unsigned int index)
- {
- u8 b;
-
-@@ -498,10 +471,10 @@ static void __init retrieve_drive_counts (unsigned int index)
- */
- b = get_cmd640_reg(arttim_regs[index]) & ~0x3f;
- switch (b) {
-- case 0x00: b = 4; break;
-- case 0x80: b = 3; break;
-- case 0x40: b = 2; break;
-- default: b = 5; break;
-+ case 0x00: b = 4; break;
-+ case 0x80: b = 3; break;
-+ case 0x40: b = 2; break;
-+ default: b = 5; break;
- }
- setup_counts[index] = b;
-
-@@ -518,7 +491,7 @@ static void __init retrieve_drive_counts (unsigned int index)
- * This routine writes the prepared setup/active/recovery counts
- * for a drive into the cmd640 chipset registers to active them.
- */
--static void program_drive_counts (unsigned int index)
-+static void program_drive_counts(ide_drive_t *drive, unsigned int index)
- {
- unsigned long flags;
- u8 setup_count = setup_counts[index];
-@@ -532,8 +505,11 @@ static void program_drive_counts (unsigned int index)
- * so we merge the timings, using the slowest value for each timing.
- */
- if (index > 1) {
-- unsigned int mate;
-- if (cmd_drives[mate = index ^ 1]->present) {
-+ ide_hwif_t *hwif = drive->hwif;
-+ ide_drive_t *peer = &hwif->drives[!drive->select.b.unit];
-+ unsigned int mate = index ^ 1;
+
-+ if (peer->present) {
- if (setup_count < setup_counts[mate])
- setup_count = setup_counts[mate];
- if (active_count < active_counts[mate])
-@@ -547,11 +523,11 @@ static void program_drive_counts (unsigned int index)
- * Convert setup_count to internal chipset representation
- */
- switch (setup_count) {
-- case 4: setup_count = 0x00; break;
-- case 3: setup_count = 0x80; break;
-- case 1:
-- case 2: setup_count = 0x40; break;
-- default: setup_count = 0xc0; /* case 5 */
-+ case 4: setup_count = 0x00; break;
-+ case 3: setup_count = 0x80; break;
-+ case 1:
-+ case 2: setup_count = 0x40; break;
-+ default: setup_count = 0xc0; /* case 5 */
- }
-
- /*
-@@ -572,7 +548,8 @@ static void program_drive_counts (unsigned int index)
- /*
- * Set a specific pio_mode for a drive
- */
--static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle_time)
-+static void cmd640_set_mode(ide_drive_t *drive, unsigned int index,
-+ u8 pio_mode, unsigned int cycle_time)
- {
- int setup_time, active_time, recovery_time, clock_time;
- u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count;
-@@ -584,15 +561,15 @@ static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle
- active_time = ide_pio_timings[pio_mode].active_time;
- recovery_time = cycle_time - (setup_time + active_time);
- clock_time = 1000 / bus_speed;
-- cycle_count = (cycle_time + clock_time - 1) / clock_time;
-+ cycle_count = DIV_ROUND_UP(cycle_time, clock_time);
-
-- setup_count = (setup_time + clock_time - 1) / clock_time;
-+ setup_count = DIV_ROUND_UP(setup_time, clock_time);
-
-- active_count = (active_time + clock_time - 1) / clock_time;
-+ active_count = DIV_ROUND_UP(active_time, clock_time);
- if (active_count < 2)
- active_count = 2; /* minimum allowed by cmd640 */
-
-- recovery_count = (recovery_time + clock_time - 1) / clock_time;
-+ recovery_count = DIV_ROUND_UP(recovery_time, clock_time);
- recovery_count2 = cycle_count - (setup_count + active_count);
- if (recovery_count2 > recovery_count)
- recovery_count = recovery_count2;
-@@ -621,7 +598,7 @@ static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle
- * 1) this is the wrong place to do it (proper is do_special() in ide.c)
- * 2) in practice this is rarely, if ever, necessary
- */
-- program_drive_counts (index);
-+ program_drive_counts(drive, index);
- }
-
- static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
-@@ -629,32 +606,26 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
- unsigned int index = 0, cycle_time;
- u8 b;
-
-- while (drive != cmd_drives[index]) {
-- if (++index > 3) {
-- printk(KERN_ERR "%s: bad news in %s\n",
-- drive->name, __FUNCTION__);
-- return;
-- }
-- }
- switch (pio) {
-- case 6: /* set fast-devsel off */
-- case 7: /* set fast-devsel on */
-- b = get_cmd640_reg(CNTRL) & ~0x27;
-- if (pio & 1)
-- b |= 0x27;
-- put_cmd640_reg(CNTRL, b);
-- printk("%s: %sabled cmd640 fast host timing (devsel)\n", drive->name, (pio & 1) ? "en" : "dis");
-- return;
--
-- case 8: /* set prefetch off */
-- case 9: /* set prefetch on */
-- set_prefetch_mode(index, pio & 1);
-- printk("%s: %sabled cmd640 prefetch\n", drive->name, (pio & 1) ? "en" : "dis");
-- return;
-+ case 6: /* set fast-devsel off */
-+ case 7: /* set fast-devsel on */
-+ b = get_cmd640_reg(CNTRL) & ~0x27;
-+ if (pio & 1)
-+ b |= 0x27;
-+ put_cmd640_reg(CNTRL, b);
-+ printk("%s: %sabled cmd640 fast host timing (devsel)\n",
-+ drive->name, (pio & 1) ? "en" : "dis");
-+ return;
-+ case 8: /* set prefetch off */
-+ case 9: /* set prefetch on */
-+ set_prefetch_mode(drive, index, pio & 1);
-+ printk("%s: %sabled cmd640 prefetch\n",
-+ drive->name, (pio & 1) ? "en" : "dis");
-+ return;
- }
-
- cycle_time = ide_pio_cycle_time(drive, pio);
-- cmd640_set_mode(index, pio, cycle_time);
-+ cmd640_set_mode(drive, index, pio, cycle_time);
-
- printk("%s: selected cmd640 PIO mode%d (%dns)",
- drive->name, pio, cycle_time);
-@@ -724,6 +695,7 @@ static int __init cmd640x_init(void)
- unsigned int index;
- u8 b, cfr;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-+ hw_regs_t hw[2];
-
- if (cmd640_vlb && probe_for_cmd640_vlb()) {
- bus_type = "VLB";
-@@ -758,21 +730,34 @@ static int __init cmd640x_init(void)
- cfr = get_cmd640_reg(CFR);
- cmd640_chip_version = cfr & CFR_DEVREV;
- if (cmd640_chip_version == 0) {
-- printk ("ide: bad cmd640 revision: %d\n", cmd640_chip_version);
-+ printk("ide: bad cmd640 revision: %d\n", cmd640_chip_version);
- return 0;
- }
-
-+ memset(&hw, 0, sizeof(hw));
++ /* Prepare the codec for AUX reading */
++ wm->codec->aux_prepare(wm);
+
-+ ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
-+ hw[0].irq = 14;
++ /* Turn polling mode on to read AUX ADC */
++ wm->pen_probably_down = 1;
++ wm->codec->poll_sample(wm, adcsel, &auxval);
+
-+ ide_std_init_ports(&hw[1], 0x170, 0x376);
-+ hw[1].irq = 15;
++ if (power_adc)
++ wm97xx_reg_write(wm, AC97_EXTENDED_MID, power | 0x8000);
+
-+ printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x"
-+ "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr);
++ wm->codec->dig_restore(wm);
+
-+ cmd_hwif0 = ide_find_port();
++ wm->pen_probably_down = 0;
+
- /*
- * 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();
++ mutex_unlock(&wm->codec_mutex);
++ return auxval & 0xfff;
++}
++EXPORT_SYMBOL_GPL(wm97xx_read_aux_adc);
+
- /*
- * 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;
++/**
++ * wm97xx_get_gpio - Get the status of a codec GPIO.
++ * @wm: wm97xx device.
++ * @gpio: gpio
++ *
++ * Get the status of a codec GPIO pin
++ */
+
-+ 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];
-+ }
++enum wm97xx_gpio_status wm97xx_get_gpio(struct wm97xx *wm, u32 gpio)
++{
++ u16 status;
++ enum wm97xx_gpio_status ret;
+
- #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)
++ 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
+ */
-+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);
--
++void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio,
++ enum wm97xx_gpio_status status)
++{
++ u16 reg;
+
- 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);
--
++ mutex_lock(&wm->codec_mutex);
++ reg = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
+
- 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);
++ if (status & WM97XX_GPIO_HIGH)
++ reg |= gpio;
++ else
++ reg &= ~gpio;
+
-+ 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);
++ if (wm->id == WM9712_ID2)
++ wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1);
+ 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.
- */
--
++ wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg);
++ mutex_unlock(&wm->codec_mutex);
++}
++EXPORT_SYMBOL_GPL(wm97xx_set_gpio);
+
- 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 {
++/*
++ * 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
- 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;
++ wm97xx_reg_write(wm, AC97_GPIO_STATUS, status &
++ ~WM97XX_GPIO_13);
++ mutex_unlock(&wm->codec_mutex);
++ }
+
-+ 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;
++ /* 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);
+ }
+
-+ itdevs[i] = itdev;
++ /* Let ts_reader report the pen up for debounce. */
++ if (!wm->pen_is_down && pen_was_down)
++ wm->pen_is_down = 1;
+ }
+
-+ pci_set_drvdata(dev, itdevs);
++ if (!wm->pen_is_down && wm->mach_ops->acc_enabled)
++ wm->mach_ops->acc_pen_up(wm);
+
- 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
++ wm->mach_ops->irq_enable(wm, 1);
++}
+
- 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.
-- *
++/*
++ * Codec PENDOWN irq handler
+ *
- * 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)
++ * 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 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;
++ struct wm97xx *wm = dev_id;
+
-+ 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;
++ if (!work_pending(&wm->pen_event_work)) {
++ wm->mach_ops->irq_enable(wm, 0);
++ queue_work(wm->ts_workq, &wm->pen_event_work);
+ }
+
-+ 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;
++ return IRQ_HANDLED;
++}
+
-+ idx[0] = hwif->index;
++/*
++ * initialise pen IRQ handler and workqueue
++ */
++static int wm97xx_init_pen_irq(struct wm97xx *wm)
++{
++ u16 reg;
+
-+ ide_device_add(idx, d);
++ /* 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;
+}
+
- /**
- * 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;
++static int wm97xx_read_samples(struct wm97xx *wm)
++{
++ struct wm97xx_data data;
++ int rc;
+
- 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);
++ mutex_lock(&wm->codec_mutex);
+
-+ end:
++ 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;
- }
-
- /**
-@@ -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;
++/*
++* 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);
+}
-
-+static unsigned int __devinit init_chipset_sis5513(struct pci_dev *dev,
-+ const char *name)
++
++/**
++ * 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)
+{
- /* 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;
++ struct wm97xx *wm = input_get_drvdata(idev);
+
-+ 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);
++ wm->ts_workq = create_singlethread_workqueue("kwm97xx");
++ if (wm->ts_workq == NULL) {
++ dev_err(wm->dev,
++ "Failed to create workqueue\n");
++ return -EINVAL;
++ }
+
-+ /* 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);
++ /* 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;
-+ 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);
++#endif
++#ifdef CONFIG_TOUCHSCREEN_WM9712
++ case 0x12:
++ wm->codec = &wm9712_codec;
+ 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 };
++#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;
++ }
+
-+ if (sis_find_family(dev) == 0)
-+ return -ENOTSUPP;
++ wm->input_dev = input_allocate_device();
++ if (wm->input_dev == NULL) {
++ ret = -ENOMEM;
++ goto alloc_err;
++ }
+
-+ d.udma_mask = udma_rates[chipset_family];
++ /* 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;
+
-+ return ide_setup_pci_device(dev, &d);
- }
-
- static const struct pci_device_id sis5513_pci_tbl[] = {
-diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
-index ee261ae..40b3eeb 100644
---- a/drivers/ide/pci/sl82c105.c
-+++ b/drivers/ide/pci/sl82c105.c
-@@ -328,8 +328,11 @@ static const struct ide_port_info sl82c105_chipset __devinitdata = {
- .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}},
- .host_flags = IDE_HFLAG_IO_32BIT |
- IDE_HFLAG_UNMASK_IRQS |
-- IDE_HFLAG_NO_AUTODMA |
-- IDE_HFLAG_BOOTABLE,
-+/* FIXME: check for Compatibility mode in generic IDE PCI code */
-+#if defined(CONFIG_LOPEC) || defined(CONFIG_SANDPOINT)
-+ IDE_HFLAG_FORCE_LEGACY_IRQS |
-+#endif
-+ IDE_HFLAG_NO_AUTODMA,
- .pio_mask = ATA_PIO5,
- };
-
-diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
-index 65f4c2f..eab557c 100644
---- a/drivers/ide/pci/slc90e66.c
-+++ b/drivers/ide/pci/slc90e66.c
-@@ -27,9 +27,9 @@ static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
- unsigned long flags;
- u16 master_data;
- u8 slave_data;
-- int control = 0;
-+ int control = 0;
- /* ISP RTC */
-- static const u8 timings[][2]= {
-+ static const u8 timings[][2] = {
- { 0, 0 },
- { 0, 0 },
- { 1, 0 },
-@@ -136,8 +136,8 @@ static void __devinit init_hwif_slc90e66(ide_hwif_t *hwif)
- static const struct ide_port_info slc90e66_chipset __devinitdata = {
- .name = "SLC90E66",
- .init_hwif = init_hwif_slc90e66,
-- .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-- .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
-+ .enablebits = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} },
-+ .host_flags = IDE_HFLAG_LEGACY_IRQS,
- .pio_mask = ATA_PIO4,
- .swdma_mask = ATA_SWDMA2_ONLY,
- .mwdma_mask = ATA_MWDMA12_ONLY,
-diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
-index 2ef2ed2..c154351 100644
---- a/drivers/ide/pci/tc86c001.c
-+++ b/drivers/ide/pci/tc86c001.c
-@@ -18,20 +18,20 @@ static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed)
- u16 mode, scr = inw(scr_port);
-
- switch (speed) {
-- case XFER_UDMA_4: mode = 0x00c0; break;
-- case XFER_UDMA_3: mode = 0x00b0; break;
-- case XFER_UDMA_2: mode = 0x00a0; break;
-- case XFER_UDMA_1: mode = 0x0090; break;
-- case XFER_UDMA_0: mode = 0x0080; break;
-- case XFER_MW_DMA_2: mode = 0x0070; break;
-- case XFER_MW_DMA_1: mode = 0x0060; break;
-- case XFER_MW_DMA_0: mode = 0x0050; break;
-- case XFER_PIO_4: mode = 0x0400; break;
-- case XFER_PIO_3: mode = 0x0300; break;
-- case XFER_PIO_2: mode = 0x0200; break;
-- case XFER_PIO_1: mode = 0x0100; break;
-- case XFER_PIO_0:
-- default: mode = 0x0000; break;
-+ case XFER_UDMA_4: mode = 0x00c0; break;
-+ case XFER_UDMA_3: mode = 0x00b0; break;
-+ case XFER_UDMA_2: mode = 0x00a0; break;
-+ case XFER_UDMA_1: mode = 0x0090; break;
-+ case XFER_UDMA_0: mode = 0x0080; break;
-+ case XFER_MW_DMA_2: mode = 0x0070; break;
-+ case XFER_MW_DMA_1: mode = 0x0060; break;
-+ case XFER_MW_DMA_0: mode = 0x0050; break;
-+ case XFER_PIO_4: mode = 0x0400; break;
-+ case XFER_PIO_3: mode = 0x0300; break;
-+ case XFER_PIO_2: mode = 0x0200; break;
-+ case XFER_PIO_1: mode = 0x0100; break;
-+ case XFER_PIO_0:
-+ default: mode = 0x0000; break;
- }
-
- scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f;
-@@ -126,40 +126,6 @@ static void tc86c001_dma_start(ide_drive_t *drive)
- ide_dma_start(drive);
- }
-
--static int tc86c001_busproc(ide_drive_t *drive, int state)
--{
-- ide_hwif_t *hwif = HWIF(drive);
-- unsigned long sc_base = hwif->config_data;
-- u16 scr1;
--
-- /* System Control 1 Register bit 11 (ATA Hard Reset) read */
-- scr1 = inw(sc_base + 0x00);
--
-- switch (state) {
-- case BUSSTATE_ON:
-- if (!(scr1 & 0x0800))
-- return 0;
-- scr1 &= ~0x0800;
--
-- hwif->drives[0].failures = hwif->drives[1].failures = 0;
-- break;
-- case BUSSTATE_OFF:
-- if (scr1 & 0x0800)
-- return 0;
-- scr1 |= 0x0800;
--
-- hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
-- hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
-- break;
-- default:
-- return -EINVAL;
-- }
--
-- /* System Control 1 Register bit 11 (ATA Hard Reset) write */
-- outw(scr1, sc_base + 0x00);
-- return 0;
--}
--
- static u8 __devinit tc86c001_cable_detect(ide_hwif_t *hwif)
- {
- struct pci_dev *dev = to_pci_dev(hwif->dev);
-@@ -194,8 +160,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
- hwif->set_pio_mode = &tc86c001_set_pio_mode;
- hwif->set_dma_mode = &tc86c001_set_mode;
-
-- hwif->busproc = &tc86c001_busproc;
--
- hwif->cable_detect = tc86c001_cable_detect;
-
- if (!hwif->dma_base)
-diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
-index a67d02a..3316b19 100644
---- a/drivers/ide/pci/triflex.c
-+++ b/drivers/ide/pci/triflex.c
-@@ -97,7 +97,6 @@ static const struct ide_port_info triflex_device __devinitdata = {
- .name = "TRIFLEX",
- .init_hwif = init_hwif_triflex,
- .enablebits = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
-- .host_flags = IDE_HFLAG_BOOTABLE,
- .pio_mask = ATA_PIO4,
- .swdma_mask = ATA_SWDMA2,
- .mwdma_mask = ATA_MWDMA2,
-diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
-index de750f7..2b8f3a2 100644
---- a/drivers/ide/pci/trm290.c
-+++ b/drivers/ide/pci/trm290.c
-@@ -337,7 +337,6 @@ static const struct ide_port_info trm290_chipset __devinitdata = {
- IDE_HFLAG_TRUST_BIOS_FOR_DMA |
- #endif
- IDE_HFLAG_NO_AUTODMA |
-- IDE_HFLAG_BOOTABLE |
- IDE_HFLAG_NO_LBA48,
- };
-
-diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
-index 9004e75..cff3caf 100644
---- a/drivers/ide/pci/via82cxxx.c
-+++ b/drivers/ide/pci/via82cxxx.c
-@@ -429,11 +429,9 @@ static const struct ide_port_info via82cxxx_chipset __devinitdata = {
- .init_hwif = init_hwif_via82cxxx,
- .enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
- .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST |
-- IDE_HFLAG_PIO_NO_DOWNGRADE |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
- IDE_HFLAG_POST_SET_MODE |
-- IDE_HFLAG_IO_32BIT |
-- IDE_HFLAG_BOOTABLE,
-+ IDE_HFLAG_IO_32BIT,
- .pio_mask = ATA_PIO5,
- .swdma_mask = ATA_SWDMA2,
- .mwdma_mask = ATA_MWDMA2,
-diff --git a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c
-index ebaba01..467656f 100644
---- a/drivers/ide/ppc/mpc8xx.c
-+++ b/drivers/ide/ppc/mpc8xx.c
-@@ -36,6 +36,8 @@
- #include <asm/machdep.h>
- #include <asm/irq.h>
-
-+#define DRV_NAME "ide-mpc8xx"
++ /* set up physical characteristics */
++ wm->codec->phy_init(wm);
+
- 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;
-+ }
++ /* 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);
+
- 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;
++ /* 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;
+
- #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 */
++ /* 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;
+}
- #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;
++#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);
++ }
+
- 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;
++#else
++#define wm97xx_suspend NULL
++#define wm97xx_resume NULL
++#endif
+
-+ idx[0] = 0;
++/*
++ * 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;
+ }
- #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];
++ wm->mach_ops = mach_ops;
++ mutex_unlock(&wm->codec_mutex);
+
-+ ide_init_port_hw(mate, &hw);
-+ mate->mmio = 1;
-+ mate->pio_mask = ATA_PIO4;
-+ mate->set_pio_mode = m8xx_ide_set_pio_mode;
++ return 0;
++}
++EXPORT_SYMBOL_GPL(wm97xx_register_mach_ops);
++
++void wm97xx_unregister_mach_ops(struct wm97xx *wm)
++{
++ mutex_lock(&wm->codec_mutex);
++ wm->mach_ops = NULL;
++ mutex_unlock(&wm->codec_mutex);
++}
++EXPORT_SYMBOL_GPL(wm97xx_unregister_mach_ops);
++
++static struct device_driver wm97xx_driver = {
++ .name = "ac97",
++ .bus = &ac97_bus_type,
++ .owner = THIS_MODULE,
++ .probe = wm97xx_probe,
++ .remove = wm97xx_remove,
++ .suspend = wm97xx_suspend,
++ .resume = wm97xx_resume,
++};
++
++static int __init wm97xx_init(void)
++{
++ return driver_register(&wm97xx_driver);
++}
++
++static void __exit wm97xx_exit(void)
++{
++ driver_unregister(&wm97xx_driver);
++}
++
++module_init(wm97xx_init);
++module_exit(wm97xx_exit);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
++MODULE_DESCRIPTION("WM97xx Core - Touch Screen / AUX ADC / GPIO Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c
+new file mode 100644
+index 0000000..0f47f46
+--- /dev/null
++++ b/drivers/input/xen-kbdfront.c
+@@ -0,0 +1,340 @@
++/*
++ * Xen para-virtual input device
++ *
++ * Copyright (C) 2005 Anthony Liguori <aliguori at us.ibm.com>
++ * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru at redhat.com>
++ *
++ * Based on linux/drivers/input/mouse/sermouse.c
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive for
++ * more details.
++ */
++
++/*
++ * TODO:
++ *
++ * Switch to grant tables together with xen-fbfront.c.
++ */
++
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/module.h>
++#include <linux/input.h>
++#include <asm/xen/hypervisor.h>
++#include <xen/events.h>
++#include <xen/page.h>
++#include <xen/interface/io/fbif.h>
++#include <xen/interface/io/kbdif.h>
++#include <xen/xenbus.h>
++
++struct xenkbd_info {
++ struct input_dev *kbd;
++ struct input_dev *ptr;
++ struct xenkbd_page *page;
++ int irq;
++ struct xenbus_device *xbdev;
++ char phys[32];
++};
++
++static int xenkbd_remove(struct xenbus_device *);
++static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
++static void xenkbd_disconnect_backend(struct xenkbd_info *);
++
++/*
++ * Note: if you need to send out events, see xenfb_do_update() for how
++ * to do that.
++ */
++
++static irqreturn_t input_handler(int rq, void *dev_id)
++{
++ struct xenkbd_info *info = dev_id;
++ struct xenkbd_page *page = info->page;
++ __u32 cons, prod;
++
++ prod = page->in_prod;
++ if (prod == page->in_cons)
++ return IRQ_HANDLED;
++ rmb(); /* ensure we see ring contents up to prod */
++ for (cons = page->in_cons; cons != prod; cons++) {
++ union xenkbd_in_event *event;
++ struct input_dev *dev;
++ event = &XENKBD_IN_RING_REF(page, cons);
+
-+ idx[1] = 1;
++ 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);
+ }
- #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)
++ 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)
+{
-+ int i;
++ if (info->irq >= 0)
++ unbind_from_irqhandler(info->irq, info);
++ info->irq = -1;
++}
+
-+ for (i = 0; i < 8; ++i)
-+ hw->io_ports[i] = base + i * 0x10;
-+ hw->io_ports[8] = base + 0x160;
++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;
++ }
+}
+
- /*
- * 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;
++static struct xenbus_device_id xenkbd_ids[] = {
++ { "vkbd" },
++ { "" }
++};
+
-+ 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;
++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/capi/capi.c b/drivers/isdn/capi/capi.c
+index 23ae66c..6ca0bb9 100644
+--- a/drivers/isdn/capi/capi.c
++++ b/drivers/isdn/capi/capi.c
+@@ -350,7 +350,7 @@ static void capincci_free(struct capidev *cdev, u32 ncci)
+ if (ncci == 0xffffffff || np->ncci == ncci) {
+ *pp = (*pp)->next;
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+- if ((mp = np->minorp) != 0) {
++ if ((mp = np->minorp) != NULL) {
+ #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
+ capifs_free_ncci(mp->minor);
+ #endif
+@@ -366,7 +366,7 @@ static void capincci_free(struct capidev *cdev, u32 ncci)
+ }
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+ kfree(np);
+- if (*pp == 0) return;
++ if (*pp == NULL) return;
+ } else {
+ pp = &(*pp)->next;
+ }
+@@ -483,7 +483,7 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
+ #endif
+ goto bad;
}
-
-- 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;
+- if ((nskb = gen_data_b3_resp_for(mp, skb)) == 0) {
++ if ((nskb = gen_data_b3_resp_for(mp, skb)) == NULL) {
+ printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
+ goto bad;
}
-
- /* 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;
+@@ -512,7 +512,7 @@ bad:
+ static void handle_minor_recv(struct capiminor *mp)
+ {
+ struct sk_buff *skb;
+- while ((skb = skb_dequeue(&mp->inqueue)) != 0) {
++ while ((skb = skb_dequeue(&mp->inqueue)) != NULL) {
+ unsigned int len = skb->len;
+ mp->inbytes -= len;
+ if (handle_recv_skb(mp, skb) < 0) {
+@@ -538,7 +538,7 @@ static int handle_minor_send(struct capiminor *mp)
+ return 0;
}
-
- /* 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;
+- while ((skb = skb_dequeue(&mp->outqueue)) != 0) {
++ while ((skb = skb_dequeue(&mp->outqueue)) != NULL) {
+ datahandle = mp->datahandle;
+ len = (u16)skb->len;
+ skb_push(skb, CAPI_DATA_B3_REQ_LEN);
+@@ -689,19 +689,19 @@ capi_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+ if (!cdev->ap.applid)
+ return -ENODEV;
-@@ -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);
+- if ((skb = skb_dequeue(&cdev->recvqueue)) == 0) {
++ if ((skb = skb_dequeue(&cdev->recvqueue)) == NULL) {
+
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+
+ for (;;) {
+ interruptible_sleep_on(&cdev->recvwait);
+- if ((skb = skb_dequeue(&cdev->recvqueue)) != 0)
++ if ((skb = skb_dequeue(&cdev->recvqueue)) != NULL)
+ break;
+ if (signal_pending(current))
+ break;
}
-- memset(pmif, 0, sizeof(*pmif));
- macio_release_resource(mdev, 0);
-+ kfree(pmif);
+- if (skb == 0)
++ if (skb == NULL)
+ return -ERESTARTNOHAND;
}
+ if (skb->len > count) {
+@@ -940,12 +940,12 @@ capi_ioctl(struct inode *inode, struct file *file,
+ return -EFAULT;
- return rc;
-+
-+out_free_pmif:
-+ kfree(pmif);
-+ return rc;
- }
+ mutex_lock(&cdev->ncci_list_mtx);
+- if ((nccip = capincci_find(cdev, (u32) ncci)) == 0) {
++ if ((nccip = capincci_find(cdev, (u32) ncci)) == NULL) {
+ mutex_unlock(&cdev->ncci_list_mtx);
+ return 0;
+ }
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+- if ((mp = nccip->minorp) != 0) {
++ if ((mp = nccip->minorp) != NULL) {
+ count += atomic_read(&mp->ttyopencount);
+ }
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+@@ -966,7 +966,7 @@ capi_ioctl(struct inode *inode, struct file *file,
+ return -EFAULT;
+ mutex_lock(&cdev->ncci_list_mtx);
+ nccip = capincci_find(cdev, (u32) ncci);
+- if (!nccip || (mp = nccip->minorp) == 0) {
++ if (!nccip || (mp = nccip->minorp) == NULL) {
+ mutex_unlock(&cdev->ncci_list_mtx);
+ return -ESRCH;
+ }
+@@ -986,7 +986,7 @@ capi_open(struct inode *inode, struct file *file)
+ if (file->private_data)
+ return -EEXIST;
- 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;
+- if ((file->private_data = capidev_alloc()) == 0)
++ if ((file->private_data = capidev_alloc()) == NULL)
+ return -ENOMEM;
- 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;
- }
+ return nonseekable_open(inode, file);
+@@ -1023,9 +1023,9 @@ static int capinc_tty_open(struct tty_struct * tty, struct file * file)
+ struct capiminor *mp;
+ unsigned long flags;
-- 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;
+- if ((mp = capiminor_find(iminor(file->f_path.dentry->d_inode))) == 0)
++ if ((mp = capiminor_find(iminor(file->f_path.dentry->d_inode))) == NULL)
+ return -ENXIO;
+- if (mp->nccip == 0)
++ if (mp->nccip == NULL)
+ return -ENXIO;
+
+ tty->driver_data = (void *)mp;
+@@ -1058,7 +1058,7 @@ static void capinc_tty_close(struct tty_struct * tty, struct file * file)
+ #ifdef _DEBUG_REFCOUNT
+ printk(KERN_DEBUG "capinc_tty_close ocount=%d\n", atomic_read(&mp->ttyopencount));
+ #endif
+- if (mp->nccip == 0)
++ if (mp->nccip == NULL)
+ capiminor_free(mp);
}
- 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);
+@@ -1111,11 +1111,12 @@ static int capinc_tty_write(struct tty_struct * tty,
+ return count;
+ }
- 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;
+-static void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
++static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ struct capiminor *mp = (struct capiminor *)tty->driver_data;
+ struct sk_buff *skb;
+ unsigned long flags;
++ int ret = 1;
-@@ -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);
+ #ifdef _DEBUG_TTYFUNCS
+ printk(KERN_DEBUG "capinc_put_char(%u)\n", ch);
+@@ -1125,7 +1126,7 @@ static void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
+ #ifdef _DEBUG_TTYFUNCS
+ printk(KERN_DEBUG "capinc_tty_put_char: mp or mp->ncci NULL\n");
+ #endif
+- return;
++ return 0;
}
- return rc;
-+
-+out_free_pmif:
-+ kfree(pmif);
-+ return rc;
+ spin_lock_irqsave(&workaround_lock, flags);
+@@ -1134,7 +1135,7 @@ static void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
+ if (skb_tailroom(skb) > 0) {
+ *(skb_put(skb, 1)) = ch;
+ spin_unlock_irqrestore(&workaround_lock, flags);
+- return;
++ return 1;
+ }
+ mp->ttyskb = NULL;
+ skb_queue_tail(&mp->outqueue, skb);
+@@ -1148,8 +1149,10 @@ static void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
+ mp->ttyskb = skb;
+ } else {
+ printk(KERN_ERR "capinc_put_char: char %u lost\n", ch);
++ ret = 0;
+ }
+ spin_unlock_irqrestore(&workaround_lock, flags);
++ return ret;
}
- static int
-diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
-index 634e3f6..6302010 100644
---- a/drivers/ide/setup-pci.c
-+++ b/drivers/ide/setup-pci.c
-@@ -20,84 +20,6 @@
- #include <asm/io.h>
- #include <asm/irq.h>
+ static void capinc_tty_flush_chars(struct tty_struct *tty)
+@@ -1526,9 +1529,9 @@ static int __init capi_init(void)
+ char *compileinfo;
+ int major_ret;
+
+- if ((p = strchr(revision, ':')) != 0 && p[1]) {
++ if ((p = strchr(revision, ':')) != NULL && p[1]) {
+ strlcpy(rev, p + 2, sizeof(rev));
+- if ((p = strchr(rev, '$')) != 0 && p > rev)
++ if ((p = strchr(rev, '$')) != NULL && p > rev)
+ *(p-1) = 0;
+ } else
+ strcpy(rev, "1.0");
+diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
+index cb42b69..d5b4cc3 100644
+--- a/drivers/isdn/capi/capidrv.c
++++ b/drivers/isdn/capi/capidrv.c
+@@ -335,7 +335,7 @@ static capidrv_plci *new_plci(capidrv_contr * card, int chan)
--
--/**
-- * 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;
+ plcip = kzalloc(sizeof(capidrv_plci), GFP_ATOMIC);
-@@ -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);
+- if (plcip == 0)
++ if (plcip == NULL)
+ return NULL;
+ plcip->state = ST_PLCI_NONE;
+@@ -404,7 +404,7 @@ static inline capidrv_ncci *new_ncci(capidrv_contr * card,
-@@ -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
- */
+ nccip = kzalloc(sizeof(capidrv_ncci), GFP_ATOMIC);
-@@ -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;
+- if (nccip == 0)
++ if (nccip == NULL)
+ return NULL;
+
+ nccip->ncci = ncci;
+@@ -426,7 +426,7 @@ static inline capidrv_ncci *find_ncci(capidrv_contr * card, u32 ncci)
+ capidrv_plci *plcip;
+ capidrv_ncci *p;
+
+- if ((plcip = find_plci_by_ncci(card, ncci)) == 0)
++ if ((plcip = find_plci_by_ncci(card, ncci)) == NULL)
+ return NULL;
+
+ for (p = plcip->ncci_list; p; p = p->next)
+@@ -441,7 +441,7 @@ static inline capidrv_ncci *find_ncci_by_msgid(capidrv_contr * card,
+ capidrv_plci *plcip;
+ capidrv_ncci *p;
+
+- if ((plcip = find_plci_by_ncci(card, ncci)) == 0)
++ if ((plcip = find_plci_by_ncci(card, ncci)) == NULL)
+ return NULL;
+
+ for (p = plcip->ncci_list; p; p = p->next)
+@@ -755,7 +755,7 @@ static inline int new_bchan(capidrv_contr * card)
+ {
+ int i;
+ for (i = 0; i < card->nbchan; i++) {
+- if (card->bchans[i].plcip == 0) {
++ if (card->bchans[i].plcip == NULL) {
+ card->bchans[i].disconnecting = 0;
+ return i;
+ }
+@@ -877,7 +877,7 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
+ return;
}
-@@ -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
+ bchan = &card->bchans[chan];
+- if ((plcip = new_plci(card, chan)) == 0) {
++ if ((plcip = new_plci(card, chan)) == NULL) {
+ printk(KERN_ERR "capidrv-%d: incoming call: no memory, sorry.\n", card->contrnr);
+ return;
+ }
+@@ -1388,12 +1388,12 @@ static void capidrv_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
+ _cdebbuf *cdb = capi_cmsg2str(&s_cmsg);
+
+ if (cdb) {
+- printk(KERN_DEBUG "%s: applid=%d %s\n", __FUNCTION__,
++ printk(KERN_DEBUG "%s: applid=%d %s\n", __func__,
+ ap->applid, cdb->buf);
+ cdebbuf_free(cdb);
+ } else
+ printk(KERN_DEBUG "%s: applid=%d %s not traced\n",
+- __FUNCTION__, ap->applid,
++ __func__, ap->applid,
+ capi_cmd2str(s_cmsg.Command, s_cmsg.Subcommand));
+ }
+ if (s_cmsg.Command == CAPI_DATA_B3
+@@ -1661,7 +1661,7 @@ static int capidrv_command(isdn_ctrl * c, capidrv_contr * card)
+ NULL, /* Useruserdata */
+ NULL /* Facilitydataarray */
+ );
+- if ((plcip = new_plci(card, (c->arg % card->nbchan))) == 0) {
++ if ((plcip = new_plci(card, (c->arg % card->nbchan))) == NULL) {
+ cmd.command = ISDN_STAT_DHUP;
+ cmd.driver = card->myid;
+ cmd.arg = (c->arg % card->nbchan);
+@@ -1966,7 +1966,7 @@ static void enable_dchannel_trace(capidrv_contr *card)
+ card->name, errcode);
+ return;
+ }
+- if (strstr(manufacturer, "AVM") == 0) {
++ if (strstr(manufacturer, "AVM") == NULL) {
+ printk(KERN_ERR "%s: not from AVM, no d-channel trace possible (%s)\n",
+ card->name, manufacturer);
+ return;
+@@ -2291,10 +2291,10 @@ static int __init capidrv_init(void)
+ u32 ncontr, contr;
+ u16 errcode;
+
+- if ((p = strchr(revision, ':')) != 0 && p[1]) {
++ if ((p = strchr(revision, ':')) != NULL && p[1]) {
+ strncpy(rev, p + 2, sizeof(rev));
+ rev[sizeof(rev)-1] = 0;
+- if ((p = strchr(rev, '$')) != 0 && p > rev)
++ if ((p = strchr(rev, '$')) != NULL && p > rev)
+ *(p-1) = 0;
+ } else
+ strcpy(rev, "1.0");
+@@ -2335,10 +2335,10 @@ static void __exit capidrv_exit(void)
+ char rev[32];
+ char *p;
+
+- if ((p = strchr(revision, ':')) != 0) {
++ if ((p = strchr(revision, ':')) != NULL) {
+ strncpy(rev, p + 1, sizeof(rev));
+ rev[sizeof(rev)-1] = 0;
+- if ((p = strchr(rev, '$')) != 0)
++ if ((p = strchr(rev, '$')) != NULL)
+ *p = 0;
+ } else {
+ strcpy(rev, " ??? ");
+diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c
+index 6d7c47e..550e80f 100644
+--- a/drivers/isdn/capi/capifs.c
++++ b/drivers/isdn/capi/capifs.c
+@@ -69,6 +69,7 @@ static int capifs_remount(struct super_block *s, int *flags, char *data)
+ } else if (sscanf(this_char, "mode=%o%c", &n, &dummy) == 1)
+ mode = n & ~S_IFMT;
+ else {
++ kfree(new_opt);
+ printk("capifs: called with bogus options\n");
+ return -EINVAL;
+ }
+@@ -189,9 +190,9 @@ static int __init capifs_init(void)
+ char *p;
+ int err;
+
+- if ((p = strchr(revision, ':')) != 0 && p[1]) {
++ if ((p = strchr(revision, ':')) != NULL && p[1]) {
+ strlcpy(rev, p + 2, sizeof(rev));
+- if ((p = strchr(rev, '$')) != 0 && p > rev)
++ if ((p = strchr(rev, '$')) != NULL && p > rev)
+ *(p-1) = 0;
+ } else
+ strcpy(rev, "1.0");
+diff --git a/drivers/isdn/capi/capilib.c b/drivers/isdn/capi/capilib.c
+index 68409d9..fcaa124 100644
+--- a/drivers/isdn/capi/capilib.c
++++ b/drivers/isdn/capi/capilib.c
+@@ -4,7 +4,7 @@
+ #include <linux/isdn/capilli.h>
+
+ #define DBG(format, arg...) do { \
+-printk(KERN_DEBUG "%s: " format "\n" , __FUNCTION__ , ## arg); \
++printk(KERN_DEBUG "%s: " format "\n" , __func__ , ## arg); \
+ } while (0)
+
+ struct capilib_msgidqueue {
+@@ -44,7 +44,7 @@ static inline void mq_init(struct capilib_ncci * np)
+ static inline int mq_enqueue(struct capilib_ncci * np, u16 msgid)
+ {
+ struct capilib_msgidqueue *mq;
+- if ((mq = np->msgidfree) == 0)
++ if ((mq = np->msgidfree) == NULL)
+ return 0;
+ np->msgidfree = mq->next;
+ mq->msgid = msgid;
+diff --git a/drivers/isdn/capi/capiutil.c b/drivers/isdn/capi/capiutil.c
+index 22379b9..ebef4ce 100644
+--- a/drivers/isdn/capi/capiutil.c
++++ b/drivers/isdn/capi/capiutil.c
+@@ -450,7 +450,7 @@ static void pars_2_message(_cmsg * cmsg)
+ cmsg->l += 4;
+ break;
+ case _CSTRUCT:
+- if (*(u8 **) OFF == 0) {
++ if (*(u8 **) OFF == NULL) {
+ *(cmsg->m + cmsg->l) = '\0';
+ cmsg->l++;
+ } else if (**(_cstruct *) OFF != 0xff) {
+diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
+index f555318..75726ea 100644
+--- a/drivers/isdn/capi/kcapi.c
++++ b/drivers/isdn/capi/kcapi.c
+@@ -10,7 +10,7 @@
*
-- * 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;
+-#define CONFIG_AVMB1_COMPAT
++#define AVMB1_COMPAT
-- /* I/O space */
-- if(flags & PCI_BASE_ADDRESS_IO_MASK)
-+ /* I/O space */
-+ if (flags & IORESOURCE_IO)
- return 0;
--
-+
- /* Bad */
-- printk(KERN_ERR "%s: IO baseregs (BIOS) are reported "
-- "as MEM, report to "
-- "<andre at linux-ide.org>.\n", d->name);
- return -EINVAL;
+ #include "kcapi.h"
+ #include <linux/module.h>
+@@ -29,7 +29,7 @@
+ #include <asm/uaccess.h>
+ #include <linux/isdn/capicmd.h>
+ #include <linux/isdn/capiutil.h>
+-#ifdef CONFIG_AVMB1_COMPAT
++#ifdef AVMB1_COMPAT
+ #include <linux/b1lli.h>
+ #endif
+ #include <linux/mutex.h>
+@@ -154,7 +154,7 @@ static void register_appl(struct capi_ctr *card, u16 applid, capi_register_param
+ if (card)
+ card->register_appl(card, applid, rparam);
+ else
+- printk(KERN_WARNING "%s: cannot get card resources\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: cannot get card resources\n", __func__);
}
-@@ -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;
- }
+@@ -178,7 +178,7 @@ static void notify_up(u32 contr)
+ printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr);
}
-- if (!ctl)
-- {
-+ if (!ctl) {
- /* Use default values */
- ctl = port ? 0x374 : 0x3f4;
- base = port ? 0x170 : 0x1f0;
+ if (!card) {
+- printk(KERN_WARNING "%s: invalid contr %d\n", __FUNCTION__, contr);
++ printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr);
+ return;
}
-- 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);
+ for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
+@@ -740,7 +740,7 @@ u16 capi20_get_profile(u32 contr, struct capi_profile *profp)
-- 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);
+ EXPORT_SYMBOL(capi20_get_profile);
-- hwif->noprobe = oldnoprobe;
--
- hwif->dev = &dev->dev;
- hwif->cds = d;
+-#ifdef CONFIG_AVMB1_COMPAT
++#ifdef AVMB1_COMPAT
+ static int old_capi_manufacturer(unsigned int cmd, void __user *data)
+ {
+ avmb1_loadandconfigdef ldef;
+@@ -826,7 +826,7 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data)
+ card = capi_ctr_get(card);
+ if (!card)
+ return -ESRCH;
+- if (card->load_firmware == 0) {
++ if (card->load_firmware == NULL) {
+ printk(KERN_DEBUG "kcapi: load: no load function\n");
+ return -ESRCH;
+ }
+@@ -835,7 +835,7 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data)
+ printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len);
+ return -EINVAL;
+ }
+- if (ldef.t4file.data == 0) {
++ if (ldef.t4file.data == NULL) {
+ printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n");
+ return -EINVAL;
+ }
+@@ -904,7 +904,7 @@ int capi20_manufacturer(unsigned int cmd, void __user *data)
+ struct capi_ctr *card;
-@@ -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);
+ switch (cmd) {
+-#ifdef CONFIG_AVMB1_COMPAT
++#ifdef AVMB1_COMPAT
+ case AVMB1_LOAD:
+ case AVMB1_LOAD_AND_CONFIG:
+ case AVMB1_RESETCARD:
+@@ -951,7 +951,7 @@ int capi20_manufacturer(unsigned int cmd, void __user *data)
+ if (strcmp(driver->name, cdef.driver) == 0)
+ break;
+ }
+- if (driver == 0) {
++ if (driver == NULL) {
+ printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n",
+ cdef.driver);
+ return -ESRCH;
+@@ -1004,9 +1004,9 @@ static int __init kcapi_init(void)
+ return ret;
+ kcapi_proc_init();
- /*
-@@ -615,7 +532,6 @@ int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d)
+- if ((p = strchr(revision, ':')) != 0 && p[1]) {
++ if ((p = strchr(revision, ':')) != NULL && p[1]) {
+ strlcpy(rev, p + 2, sizeof(rev));
+- if ((p = strchr(rev, '$')) != 0 && p > rev)
++ if ((p = strchr(rev, '$')) != NULL && p > rev)
+ *(p-1) = 0;
+ } else
+ strcpy(rev, "1.0");
+diff --git a/drivers/isdn/capi/kcapi.h b/drivers/isdn/capi/kcapi.h
+index 1cb2c40..244711f 100644
+--- a/drivers/isdn/capi/kcapi.h
++++ b/drivers/isdn/capi/kcapi.h
+@@ -17,7 +17,7 @@
- return ret;
+ #ifdef KCAPI_DEBUG
+ #define DBG(format, arg...) do { \
+-printk(KERN_DEBUG "%s: " format "\n" , __FUNCTION__ , ## arg); \
++printk(KERN_DEBUG "%s: " format "\n" , __func__ , ## arg); \
+ } while (0)
+ #else
+ #define DBG(format, arg...) /* */
+diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c
+index 845a797..c29208b 100644
+--- a/drivers/isdn/capi/kcapi_proc.c
++++ b/drivers/isdn/capi/kcapi_proc.c
+@@ -114,6 +114,7 @@ static int seq_contrstats_open(struct inode *inode, struct file *file)
}
--
- 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;
- }
+ static const struct file_operations proc_controller_ops = {
++ .owner = THIS_MODULE,
+ .open = seq_controller_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -121,6 +122,7 @@ static const struct file_operations proc_controller_ops = {
+ };
-- 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));
+ static const struct file_operations proc_contrstats_ops = {
++ .owner = THIS_MODULE,
+ .open = seq_contrstats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -219,6 +221,7 @@ seq_applstats_open(struct inode *inode, struct file *file)
+ }
-- 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[] = {
+ static const struct file_operations proc_applications_ops = {
++ .owner = THIS_MODULE,
+ .open = seq_applications_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -226,21 +229,13 @@ static const struct file_operations proc_applications_ops = {
};
- 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",
+ static const struct file_operations proc_applstats_ops = {
++ .owner = THIS_MODULE,
+ .open = seq_applstats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
};
+-static void
+-create_seq_entry(char *name, mode_t mode, const struct file_operations *f)
+-{
+- struct proc_dir_entry *entry;
+- entry = create_proc_entry(name, mode, NULL);
+- if (entry)
+- entry->proc_fops = f;
+-}
+-
+ // ---------------------------------------------------------------------------
-@@ -2568,7 +2569,6 @@ static int __init dv1394_init_module(void)
+ static void *capi_driver_start(struct seq_file *seq, loff_t *pos)
+@@ -283,6 +278,7 @@ seq_capi_driver_open(struct inode *inode, struct file *file)
+ }
- 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;
+ static const struct file_operations proc_driver_ops = {
++ .owner = THIS_MODULE,
+ .open = seq_capi_driver_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -296,11 +292,11 @@ kcapi_proc_init(void)
+ {
+ proc_mkdir("capi", NULL);
+ proc_mkdir("capi/controllers", NULL);
+- create_seq_entry("capi/controller", 0, &proc_controller_ops);
+- create_seq_entry("capi/contrstats", 0, &proc_contrstats_ops);
+- create_seq_entry("capi/applications", 0, &proc_applications_ops);
+- create_seq_entry("capi/applstats", 0, &proc_applstats_ops);
+- create_seq_entry("capi/driver", 0, &proc_driver_ops);
++ proc_create("capi/controller", 0, NULL, &proc_controller_ops);
++ proc_create("capi/contrstats", 0, NULL, &proc_contrstats_ops);
++ proc_create("capi/applications", 0, NULL, &proc_applications_ops);
++ proc_create("capi/applstats", 0, NULL, &proc_applstats_ops);
++ proc_create("capi/driver", 0, NULL, &proc_driver_ops);
+ }
+
+ void __exit
+diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
+index 4fd4c46..8b256a6 100644
+--- a/drivers/isdn/divert/divert_procfs.c
++++ b/drivers/isdn/divert/divert_procfs.c
+@@ -288,13 +288,12 @@ divert_dev_init(void)
+ isdn_proc_entry = proc_mkdir("isdn", init_net.proc_net);
+ if (!isdn_proc_entry)
+ return (-1);
+- isdn_divert_entry = create_proc_entry("divert", S_IFREG | S_IRUGO, isdn_proc_entry);
++ isdn_divert_entry = proc_create("divert", S_IFREG | S_IRUGO,
++ isdn_proc_entry, &isdn_fops);
+ if (!isdn_divert_entry) {
+ remove_proc_entry("isdn", init_net.proc_net);
+ return (-1);
}
+- isdn_divert_entry->proc_fops = &isdn_fops;
+- isdn_divert_entry->owner = THIS_MODULE;
+ #endif /* CONFIG_PROC_FS */
-@@ -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;
+ return (0);
+diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
+index fceeb1d..45d1ee9 100644
+--- a/drivers/isdn/gigaset/ser-gigaset.c
++++ b/drivers/isdn/gigaset/ser-gigaset.c
+@@ -68,10 +68,10 @@ static int write_modem(struct cardstate *cs)
+ struct tty_struct *tty = cs->hw.ser->tty;
+ struct bc_state *bcs = &cs->bcs[0]; /* only one channel */
+ struct sk_buff *skb = bcs->tx_skb;
+- int sent;
++ int sent = -EOPNOTSUPP;
+
+ if (!tty || !tty->driver || !skb)
+- return -EFAULT;
++ return -EINVAL;
+
+ if (!skb->len) {
+ dev_kfree_skb_any(skb);
+@@ -80,7 +80,8 @@ static int write_modem(struct cardstate *cs)
}
-@@ -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__);
+ set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+- sent = tty->driver->write(tty, skb->data, skb->len);
++ if (tty->ops->write)
++ sent = tty->ops->write(tty, skb->data, skb->len);
+ gig_dbg(DEBUG_OUTPUT, "write_modem: sent %d", sent);
+ if (sent < 0) {
+ /* error */
+@@ -120,7 +121,7 @@ static int send_cb(struct cardstate *cs)
+
+ if (cb->len) {
+ set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+- sent = tty->driver->write(tty, cb->buf + cb->offset, cb->len);
++ sent = tty->ops->write(tty, cb->buf + cb->offset, cb->len);
+ if (sent < 0) {
+ /* error */
+ gig_dbg(DEBUG_OUTPUT, "send_cb: write error %d", sent);
+@@ -440,14 +441,14 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, unsi
+ struct tty_struct *tty = cs->hw.ser->tty;
+ unsigned int set, clear;
+
+- if (!tty || !tty->driver || !tty->driver->tiocmset)
+- return -EFAULT;
++ if (!tty || !tty->driver || !tty->ops->tiocmset)
++ return -EINVAL;
+ set = new_state & ~old_state;
+ clear = old_state & ~new_state;
+ if (!set && !clear)
return 0;
- }
+ gig_dbg(DEBUG_IF, "tiocmset set %x clear %x", set, clear);
+- return tty->driver->tiocmset(tty, NULL, set, clear);
++ return tty->ops->tiocmset(tty, NULL, set, clear);
+ }
+
+ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
+diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c
+index 4484a64..abf05ec 100644
+--- a/drivers/isdn/hardware/avm/b1.c
++++ b/drivers/isdn/hardware/avm/b1.c
+@@ -661,11 +661,11 @@ int b1ctl_read_proc(char *page, char **start, off_t off,
+ len += sprintf(page+len, "%-16s %s\n", "type", s);
+ if (card->cardtype == avm_t1isa)
+ len += sprintf(page+len, "%-16s %d\n", "cardnr", card->cardnr);
+- if ((s = cinfo->version[VER_DRIVER]) != 0)
++ if ((s = cinfo->version[VER_DRIVER]) != NULL)
+ len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
+- if ((s = cinfo->version[VER_CARDTYPE]) != 0)
++ if ((s = cinfo->version[VER_CARDTYPE]) != NULL)
+ len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
+- if ((s = cinfo->version[VER_SERIAL]) != 0)
++ if ((s = cinfo->version[VER_SERIAL]) != NULL)
+ len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
+
+ if (card->cardtype != avm_m1) {
+@@ -788,9 +788,9 @@ static int __init b1_init(void)
+ char *p;
+ char rev[32];
+
+- if ((p = strchr(revision, ':')) != 0 && p[1]) {
++ if ((p = strchr(revision, ':')) != NULL && p[1]) {
+ strlcpy(rev, p + 2, 32);
+- if ((p = strchr(rev, '$')) != 0 && p > rev)
++ if ((p = strchr(rev, '$')) != NULL && p > rev)
+ *(p-1) = 0;
+ } else
+ strcpy(rev, "1.0");
+diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c
+index 669f6f6..da34b98 100644
+--- a/drivers/isdn/hardware/avm/b1dma.c
++++ b/drivers/isdn/hardware/avm/b1dma.c
+@@ -883,11 +883,11 @@ int b1dmactl_read_proc(char *page, char **start, off_t off,
+ default: s = "???"; break;
+ }
+ len += sprintf(page+len, "%-16s %s\n", "type", s);
+- if ((s = cinfo->version[VER_DRIVER]) != 0)
++ if ((s = cinfo->version[VER_DRIVER]) != NULL)
+ len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
+- if ((s = cinfo->version[VER_CARDTYPE]) != 0)
++ if ((s = cinfo->version[VER_CARDTYPE]) != NULL)
+ len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
+- if ((s = cinfo->version[VER_SERIAL]) != 0)
++ if ((s = cinfo->version[VER_SERIAL]) != NULL)
+ len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
+
+ if (card->cardtype != avm_m1) {
+@@ -970,9 +970,9 @@ static int __init b1dma_init(void)
+ char *p;
+ char rev[32];
+
+- if ((p = strchr(revision, ':')) != 0 && p[1]) {
++ if ((p = strchr(revision, ':')) != NULL && p[1]) {
+ strlcpy(rev, p + 2, sizeof(rev));
+- if ((p = strchr(rev, '$')) != 0 && p > rev)
++ if ((p = strchr(rev, '$')) != NULL && p > rev)
+ *(p-1) = 0;
+ } else
+ strcpy(rev, "1.0");
+diff --git a/drivers/isdn/hardware/avm/b1isa.c b/drivers/isdn/hardware/avm/b1isa.c
+index 80fb488..1e288ee 100644
+--- a/drivers/isdn/hardware/avm/b1isa.c
++++ b/drivers/isdn/hardware/avm/b1isa.c
+@@ -203,9 +203,9 @@ static int __init b1isa_init(void)
+ char rev[32];
+ int i;
-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;
- }
+- if ((p = strchr(revision, ':')) != 0 && p[1]) {
++ if ((p = strchr(revision, ':')) != NULL && p[1]) {
+ strlcpy(rev, p + 2, 32);
+- if ((p = strchr(rev, '$')) != 0 && p > rev)
++ if ((p = strchr(rev, '$')) != NULL && p > rev)
+ *(p-1) = 0;
+ } else
+ strcpy(rev, "1.0");
+diff --git a/drivers/isdn/hardware/avm/b1pci.c b/drivers/isdn/hardware/avm/b1pci.c
+index 90e2e66..5b314a2 100644
+--- a/drivers/isdn/hardware/avm/b1pci.c
++++ b/drivers/isdn/hardware/avm/b1pci.c
+@@ -382,9 +382,9 @@ static int __init b1pci_init(void)
+ char rev[32];
+ int err;
-@@ -373,6 +373,8 @@ static void build_speed_map(struct hpsb_host *host, int nodecount)
- if (sid->port2 == SELFID_PORT_CHILD) cldcnt[n]++;
+- if ((p = strchr(revision, ':')) != 0 && p[1]) {
++ if ((p = strchr(revision, ':')) != NULL && p[1]) {
+ strlcpy(rev, p + 2, 32);
+- if ((p = strchr(rev, '$')) != 0 && p > rev)
++ if ((p = strchr(rev, '$')) != NULL && p > rev)
+ *(p-1) = 0;
+ } else
+ strcpy(rev, "1.0");
+diff --git a/drivers/isdn/hardware/avm/b1pcmcia.c b/drivers/isdn/hardware/avm/b1pcmcia.c
+index e479c0a..7740403 100644
+--- a/drivers/isdn/hardware/avm/b1pcmcia.c
++++ b/drivers/isdn/hardware/avm/b1pcmcia.c
+@@ -201,9 +201,9 @@ static int __init b1pcmcia_init(void)
+ char *p;
+ char rev[32];
+
+- if ((p = strchr(revision, ':')) != 0 && p[1]) {
++ if ((p = strchr(revision, ':')) != NULL && p[1]) {
+ strlcpy(rev, p + 2, 32);
+- if ((p = strchr(rev, '$')) != 0 && p > rev)
++ if ((p = strchr(rev, '$')) != NULL && p > rev)
+ *(p-1) = 0;
+ } else
+ strcpy(rev, "1.0");
+diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c
+index 4bbbbe6..9df1d3f 100644
+--- a/drivers/isdn/hardware/avm/c4.c
++++ b/drivers/isdn/hardware/avm/c4.c
+@@ -1088,11 +1088,11 @@ static int c4_read_proc(char *page, char **start, off_t off,
+ default: s = "???"; break;
+ }
+ len += sprintf(page+len, "%-16s %s\n", "type", s);
+- if ((s = cinfo->version[VER_DRIVER]) != 0)
++ if ((s = cinfo->version[VER_DRIVER]) != NULL)
+ len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
+- if ((s = cinfo->version[VER_CARDTYPE]) != 0)
++ if ((s = cinfo->version[VER_CARDTYPE]) != NULL)
+ len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
+- if ((s = cinfo->version[VER_SERIAL]) != 0)
++ if ((s = cinfo->version[VER_SERIAL]) != NULL)
+ len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
+
+ if (card->cardtype != avm_m1) {
+@@ -1167,7 +1167,7 @@ static int c4_add_card(struct capicardparams *p, struct pci_dev *dev,
+ }
+
+ card->mbase = ioremap(card->membase, 128);
+- if (card->mbase == 0) {
++ if (card->mbase == NULL) {
+ printk(KERN_NOTICE "c4: can't remap memory at 0x%lx\n",
+ card->membase);
+ retval = -EIO;
+@@ -1291,9 +1291,9 @@ static int __init c4_init(void)
+ char rev[32];
+ int err;
- 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 {
+- if ((p = strchr(revision, ':')) != 0 && p[1]) {
++ if ((p = strchr(revision, ':')) != NULL && p[1]) {
+ strlcpy(rev, p + 2, 32);
+- if ((p = strchr(rev, '$')) != 0 && p > rev)
++ if ((p = strchr(rev, '$')) != NULL && p > rev)
+ *(p-1) = 0;
+ } else
+ strcpy(rev, "1.0");
+diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c
+index 6130724..e772449 100644
+--- a/drivers/isdn/hardware/avm/t1isa.c
++++ b/drivers/isdn/hardware/avm/t1isa.c
+@@ -551,9 +551,9 @@ static int __init t1isa_init(void)
+ char *p;
+ int i;
- /* how many times the buffer has overflowed or underflowed */
- atomic_t overflows;
-+ /* how many cycles were skipped for a given context */
-+ atomic_t skips;
+- if ((p = strchr(revision, ':')) != 0 && p[1]) {
++ if ((p = strchr(revision, ':')) != NULL && p[1]) {
+ strlcpy(rev, p + 2, 32);
+- if ((p = strchr(rev, '$')) != 0 && p > rev)
++ if ((p = strchr(rev, '$')) != NULL && p > rev)
+ *(p-1) = 0;
+ } else
+ strcpy(rev, "1.0");
+diff --git a/drivers/isdn/hardware/avm/t1pci.c b/drivers/isdn/hardware/avm/t1pci.c
+index d1e253c..e6d298d 100644
+--- a/drivers/isdn/hardware/avm/t1pci.c
++++ b/drivers/isdn/hardware/avm/t1pci.c
+@@ -233,9 +233,9 @@ static int __init t1pci_init(void)
+ char rev[32];
+ int err;
- /* Current number of bytes lost in discarded packets */
- int bytes_discarded;
-diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
-index 511e432..29d833e 100644
---- a/drivers/ieee1394/nodemgr.c
-+++ b/drivers/ieee1394/nodemgr.c
-@@ -18,8 +18,8 @@
- #include <linux/moduleparam.h>
- #include <linux/mutex.h>
- #include <linux/freezer.h>
-+#include <linux/semaphore.h>
- #include <asm/atomic.h>
--#include <asm/semaphore.h>
+- if ((p = strchr(revision, ':')) != 0 && p[1]) {
++ if ((p = strchr(revision, ':')) != NULL && p[1]) {
+ strlcpy(rev, p + 2, 32);
+- if ((p = strchr(rev, '$')) != 0 && p > rev)
++ if ((p = strchr(rev, '$')) != NULL && p > rev)
+ *(p-1) = 0;
+ } else
+ strcpy(rev, "1.0");
+diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
+index 6d39f93..5fcbdcc 100644
+--- a/drivers/isdn/hardware/eicon/divasmain.c
++++ b/drivers/isdn/hardware/eicon/divasmain.c
+@@ -393,7 +393,7 @@ void diva_free_dma_map(void *hdev, struct _diva_dma_map_entry *pmap)
+ dma_addr_t dma_handle;
+ void *addr_handle;
+
+- for (i = 0; (pmap != 0); i++) {
++ for (i = 0; (pmap != NULL); i++) {
+ diva_get_dma_map_entry(pmap, i, &cpu_addr, &phys_addr);
+ if (!cpu_addr) {
+ break;
+diff --git a/drivers/isdn/hardware/eicon/divasproc.c b/drivers/isdn/hardware/eicon/divasproc.c
+index 0632a26..fae8958 100644
+--- a/drivers/isdn/hardware/eicon/divasproc.c
++++ b/drivers/isdn/hardware/eicon/divasproc.c
+@@ -125,15 +125,11 @@ static const struct file_operations divas_fops = {
+
+ int create_divas_proc(void)
+ {
+- divas_proc_entry = create_proc_entry(divas_proc_name,
+- S_IFREG | S_IRUGO,
+- proc_net_eicon);
++ proc_create(divas_proc_name, S_IFREG | S_IRUGO, proc_net_eicon,
++ &divas_fops);
+ if (!divas_proc_entry)
+ return (0);
- #include "csr.h"
- #include "highlevel.h"
-@@ -701,7 +701,11 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
- return 0;
+- divas_proc_entry->proc_fops = &divas_fops;
+- divas_proc_entry->owner = THIS_MODULE;
+-
+ return (1);
+ }
- 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).");
+diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c
+index 1ff98e7..599fed8 100644
+--- a/drivers/isdn/hardware/eicon/message.c
++++ b/drivers/isdn/hardware/eicon/message.c
+@@ -742,7 +742,7 @@ static void start_internal_command (dword Id, PLCI *plci, t_std_internal_comma
+ else
+ {
+ i = 1;
+- while (plci->internal_command_queue[i] != 0)
++ while (plci->internal_command_queue[i] != NULL)
+ i++;
+ plci->internal_command_queue[i] = command_function;
+ }
+@@ -758,7 +758,7 @@ static void next_internal_command (dword Id, PLCI *plci)
- 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;
+ plci->internal_command = 0;
+ plci->internal_command_queue[0] = NULL;
+- while (plci->internal_command_queue[1] != 0)
++ while (plci->internal_command_queue[1] != NULL)
+ {
+ for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
+ plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
+@@ -9119,7 +9119,7 @@ word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, byte ho
+ dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
+ return 0x2001; /* codec in use by another application */
+ }
+- if(plci!=0)
++ if(plci!=NULL)
+ {
+ a->AdvSignalPLCI = plci;
+ plci->tel=ADV_VOICE;
+@@ -9144,7 +9144,7 @@ word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, byte ho
+ }
+ /* indicate D-ch connect if */
+ } /* codec is connected OK */
+- if(plci!=0)
++ if(plci!=NULL)
+ {
+ a->AdvSignalPLCI = plci;
+ plci->tel=ADV_VOICE;
+@@ -9170,7 +9170,7 @@ word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, byte ho
+ {
+ if(hook_listen) return 0x300B; /* Facility not supported */
+ /* no hook with SCOM */
+- if(plci!=0) plci->tel = CODEC;
++ if(plci!=NULL) plci->tel = CODEC;
+ dbug(1,dprintf("S/SCOM codec"));
+ /* first time we use the scom-s codec we must shut down the internal */
+ /* handset application of the card. This can be done by an assign with */
+@@ -14604,7 +14604,7 @@ static void channel_xmit_extended_xon (PLCI * plci) {
+ int max_ch = ARRAY_SIZE(a->ch_flow_control);
+ int i, one_requested = 0;
+
+- if ((!plci) || (!plci->Id) || ((a = plci->adapter) == 0)) {
++ if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
+ return;
+ }
- 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);
+diff --git a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c
+index 61e69e9..1f879b5 100644
+--- a/drivers/isdn/hisax/asuscom.c
++++ b/drivers/isdn/hisax/asuscom.c
+@@ -20,8 +20,6 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
- dma_prog_region_init(&xmit->prog);
+-extern const char *CardType[];
+-
+ static const char *Asuscom_revision = "$Revision: 1.14.2.4 $";
-@@ -1856,6 +1860,26 @@ static void ohci_iso_xmit_task(unsigned long data)
- /* parse cycle */
- cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF;
+ #define byteout(addr,val) outb(val,addr)
+@@ -346,7 +344,7 @@ setup_asuscom(struct IsdnCard *card)
+ err = pnp_activate_dev(pnp_d);
+ if (err<0) {
+ printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+- __FUNCTION__, err);
++ __func__, err);
+ return(0);
+ }
+ card->para[1] = pnp_port_start(pnp_d, 0);
+@@ -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"
-+ 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);
+-extern const char *CardType[];
+ static const char *avm_revision = "$Revision: 2.15.2.4 $";
-@@ -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);
+ #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);
-+ /*
-+ * 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)
+- 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/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
+index 0f1db1f..7cabc5a 100644
+--- a/drivers/isdn/hisax/avm_pci.c
++++ b/drivers/isdn/hisax/avm_pci.c
+@@ -797,7 +797,7 @@ static int __devinit avm_pnp_setup(struct IsdnCardState *cs)
+ err = pnp_activate_dev(pnp_avm_d);
+ if (err<0) {
+ printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+- __FUNCTION__, err);
++ __func__, err);
+ return(0);
+ }
+ cs->hw.avm.cfg_reg =
+diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
+index 3d1bdc8..9ca2ee5 100644
+--- a/drivers/isdn/hisax/bkm_a4t.c
++++ b/drivers/isdn/hisax/bkm_a4t.c
+@@ -20,8 +20,6 @@
+ #include <linux/pci.h>
+ #include "bkm_ax.h"
- spin_lock_irqsave(&d->lock, flags);
+-extern const char *CardType[];
+-
+ static const char *bkm_a4t_revision = "$Revision: 1.22.2.4 $";
-- 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);
+@@ -284,15 +282,16 @@ static int __devinit a4t_cs_init(struct IsdnCard *card,
+ I20_REGISTER_FILE *pI20_Regs;
- 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;
+ 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);
}
-@@ -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);
+ 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;
- 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;
+- 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);
}
-@@ -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;
+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;
}
-@@ -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;
+ 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)
+ }
}
-@@ -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;
+ 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);
}
-@@ -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;
+ #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 */
}
-@@ -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 *
- ***********************************/
+ 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;
--#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);
+- 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;
-@@ -3010,15 +3029,45 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
- pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
+- 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/diva.c b/drivers/isdn/hisax/diva.c
+index 2d67085..018bd29 100644
+--- a/drivers/isdn/hisax/diva.c
++++ b/drivers/isdn/hisax/diva.c
+@@ -1088,7 +1088,7 @@ static int __devinit setup_diva_isapnp(struct IsdnCard *card)
+ err = pnp_activate_dev(pnp_d);
+ if (err<0) {
+ printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+- __FUNCTION__, err);
++ __func__, err);
+ return(0);
+ }
+ card->para[1] = pnp_port_start(pnp_d, 0);
+diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
+index d272d8c..aa29d1c 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);
}
}
-+}
-+
-+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 */
+ #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
+@@ -937,7 +937,7 @@ setup_elsa_isapnp(struct IsdnCard *card)
+ err = pnp_activate_dev(pnp_d);
+ if (err<0) {
+ printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+- __FUNCTION__, err);
++ __func__, err);
+ return(0);
+ }
+ card->para[1] = pnp_port_start(pnp_d, 0);
+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)
+ }
-- 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));
+-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
- 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;
+ do {
+diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
+index f66620a..0ea3b46 100644
+--- a/drivers/isdn/hisax/gazel.c
++++ b/drivers/isdn/hisax/gazel.c
+@@ -19,7 +19,6 @@
+ #include "ipac.h"
+ #include <linux/pci.h>
- 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);
+-extern const char *CardType[];
+ static const char *gazel_revision = "$Revision: 2.19.2.4 $";
-@@ -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;
+ #define R647 1
+@@ -479,8 +478,8 @@ reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs)
+ return 0;
- /* 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;
+ 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;
+ }
- 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);
+diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
+index fba8b62..f126566 100644
+--- a/drivers/isdn/hisax/hfc_pci.c
++++ b/drivers/isdn/hisax/hfc_pci.c
+@@ -22,8 +22,6 @@
+ #include <linux/pci.h>
+ #include <linux/interrupt.h>
+
+-extern const char *CardType[];
-
-+ 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);
+ static const char *hfcpci_revision = "$Revision: 1.48.2.4 $";
-@@ -3194,25 +3257,28 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
- host->middle_addr_space = OHCI1394_MIDDLE_ADDRESS_SPACE;
+ /* 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..d92e8d6 100644
+--- a/drivers/isdn/hisax/hfc_sx.c
++++ b/drivers/isdn/hisax/hfc_sx.c
+@@ -18,8 +18,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/isapnp.h>
- /* Tell the highlevel this host is ready */
-- if (hpsb_add_host(host))
-- FAIL(-ENOMEM, "Failed to register host with highlevel");
+-extern const char *CardType[];
-
-+ if (hpsb_add_host(host)) {
-+ PRINT_G(KERN_ERR, "Failed to register host with highlevel");
-+ goto err;
-+ }
- ohci->init_state = OHCI_INIT_DONE;
+ static const char *hfcsx_revision = "$Revision: 1.12.2.5 $";
- return 0;
--#undef FAIL
-+err:
-+ ohci1394_pci_remove(dev);
-+ return err;
+ /***************************************/
+@@ -1419,7 +1417,7 @@ setup_hfcsx(struct IsdnCard *card)
+ err = pnp_activate_dev(pnp_d);
+ if (err<0) {
+ printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+- __FUNCTION__, err);
++ __func__, err);
+ return(0);
+ }
+ card->para[1] = pnp_port_start(pnp_d, 0);
+diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
+index 98b0149..8df889b 100644
+--- a/drivers/isdn/hisax/hfc_usb.c
++++ b/drivers/isdn/hisax/hfc_usb.c
+@@ -905,7 +905,7 @@ rx_int_complete(struct urb *urb)
+ if (status) {
+ printk(KERN_INFO
+ "HFC-S USB: %s error resubmitting URB fifo(%d)\n",
+- __FUNCTION__, fifon);
++ __func__, fifon);
+ }
}
--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);
+@@ -1543,14 +1543,14 @@ hfc_usb_disconnect(struct usb_interface *intf)
+ stop_isoc_chain(&context->fifos[i]);
+ DBG(HFCUSB_DBG_INIT,
+ "HFC-S USB: %s stopping ISOC chain Fifo(%i)",
+- __FUNCTION__, i);
++ __func__, i);
+ }
+ } else {
+ if (context->fifos[i].active > 0) {
+ context->fifos[i].active = 0;
+ DBG(HFCUSB_DBG_INIT,
+ "HFC-S USB: %s unlinking URB for Fifo(%i)",
+- __FUNCTION__, i);
++ __func__, i);
+ }
+ usb_kill_urb(context->fifos[i].urb);
+ usb_free_urb(context->fifos[i].urb);
+diff --git a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c
+index 909d670..cf08266 100644
+--- a/drivers/isdn/hisax/hfcscard.c
++++ b/drivers/isdn/hisax/hfcscard.c
+@@ -193,7 +193,7 @@ setup_hfcs(struct IsdnCard *card)
+ err = pnp_activate_dev(pnp_d);
+ if (err<0) {
+ printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+- __FUNCTION__, err);
++ __func__, err);
+ return(0);
+ }
+ card->para[1] = pnp_port_start(pnp_d, 0);
+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;
+ };
- 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);
++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/hisax_debug.h b/drivers/isdn/hisax/hisax_debug.h
+index ceafecd..5ed3b1c 100644
+--- a/drivers/isdn/hisax/hisax_debug.h
++++ b/drivers/isdn/hisax/hisax_debug.h
+@@ -27,14 +27,14 @@
+
+ #define DBG(level, format, arg...) do { \
+ if (level & __debug_variable) \
+-printk(KERN_DEBUG "%s: " format "\n" , __FUNCTION__ , ## arg); \
++printk(KERN_DEBUG "%s: " format "\n" , __func__ , ## arg); \
+ } while (0)
- 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);
+ #define DBG_PACKET(level,data,count) \
+- if (level & __debug_variable) dump_packet(__FUNCTION__,data,count)
++ if (level & __debug_variable) dump_packet(__func__,data,count)
- 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);
+ #define DBG_SKB(level,skb) \
+- if ((level & __debug_variable) && skb) dump_packet(__FUNCTION__,skb->data,skb->len)
++ if ((level & __debug_variable) && skb) dump_packet(__func__,skb->data,skb->len)
-@@ -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);
+ static void __attribute__((unused))
+diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
+index 76043de..c0b4db2 100644
+--- a/drivers/isdn/hisax/hisax_fcpcipnp.c
++++ b/drivers/isdn/hisax/hisax_fcpcipnp.c
+@@ -68,7 +68,7 @@ static struct pci_device_id fcpci_ids[] = {
--#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);
- }
+ MODULE_DEVICE_TABLE(pci, fcpci_ids);
-- if (dev)
-- put_device(dev);
-+ if (device)
-+ put_device(device);
-+out:
-+ ohci1394_pmac_off(dev);
+-#ifdef __ISAPNP__
++#ifdef CONFIG_PNP
+ static struct pnp_device_id fcpnp_ids[] __devinitdata = {
+ {
+ .id = "AVM0900",
+@@ -914,7 +914,7 @@ static int __devinit fcpci_probe(struct pci_dev *pdev,
+ return retval;
}
- #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)
+-#ifdef __ISAPNP__
++#ifdef CONFIG_PNP
+ static int __devinit fcpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
{
- 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;
+ struct fritz_adapter *adapter;
+@@ -935,7 +935,7 @@ static int __devinit fcpnp_probe(struct pnp_dev *pdev, const struct pnp_device_i
+ pnp_disable_dev(pdev);
+ retval = pnp_activate_dev(pdev);
+ if (retval < 0) {
+- printk(KERN_WARNING "%s: pnp_activate_dev(%s) ret(%d)\n", __FUNCTION__,
++ printk(KERN_WARNING "%s: pnp_activate_dev(%s) ret(%d)\n", __func__,
+ (char *)dev_id->driver_data, retval);
+ goto err_free;
}
-- 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);
+@@ -974,6 +974,8 @@ static struct pnp_driver fcpnp_driver = {
+ .remove = __devexit_p(fcpnp_remove),
+ .id_table = fcpnp_ids,
+ };
++#else
++static struct pnp_driver fcpnp_driver;
+ #endif
- return 0;
- }
+ static void __devexit fcpci_remove(struct pci_dev *pdev)
+@@ -1001,7 +1003,7 @@ static int __init hisax_fcpcipnp_init(void)
+ retval = pci_register_driver(&fcpci_driver);
+ if (retval)
+ return retval;
+-#ifdef __ISAPNP__
++#ifdef CONFIG_PNP
+ retval = pnp_register_driver(&fcpnp_driver);
+ if (retval < 0) {
+ pci_unregister_driver(&fcpci_driver);
+@@ -1013,7 +1015,7 @@ static int __init hisax_fcpcipnp_init(void)
--static int ohci1394_pci_resume(struct pci_dev *pdev)
-+static int ohci1394_pci_resume(struct pci_dev *dev)
+ static void __exit hisax_fcpcipnp_exit(void)
{
- 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");
+-#ifdef __ISAPNP__
++#ifdef CONFIG_PNP
+ pnp_unregister_driver(&fcpnp_driver);
+ #endif
+ pci_unregister_driver(&fcpci_driver);
+diff --git a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c
+index 55de069..ca41617 100644
+--- a/drivers/isdn/hisax/isurf.c
++++ b/drivers/isdn/hisax/isurf.c
+@@ -17,8 +17,6 @@
+ #include "isdnl1.h"
+ #include <linux/isapnp.h>
--/* 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 */
+-extern const char *CardType[];
-
-- 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)
+ static const char *ISurf_revision = "$Revision: 1.12.2.4 $";
- 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;
- }
+ #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..a92bf0d 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"
- 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;
- }
+-extern const char *CardType[];
+ static const char *ix1_revision = "$Revision: 2.12.2.4 $";
-@@ -287,7 +287,7 @@ static int sel_phy_reg_page(struct ti_lynx *lynx, int page)
+ #define byteout(addr,val) outb(val,addr)
+@@ -253,7 +252,7 @@ setup_ix1micro(struct IsdnCard *card)
+ err = pnp_activate_dev(pnp_d);
+ if (err<0) {
+ printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+- __FUNCTION__, err);
++ __func__, err);
+ return(0);
+ }
+ card->para[1] = pnp_port_start(pnp_d, 0);
+@@ -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"
- 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;
- }
+-extern const char *CardType[];
+-
+ static const char *mic_revision = "$Revision: 1.12.2.4 $";
-@@ -309,7 +309,7 @@ static int sel_phy_reg_port(struct ti_lynx *lynx, int port)
+ #define byteout(addr,val) outb(val,addr)
+@@ -210,8 +208,7 @@ setup_mic(struct IsdnCard *card)
- 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;
- }
+ 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 @@
+ *
+ */
-@@ -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);
+-extern const char *CardType[];
+-
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
- 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);
+diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
+index bd99211..ef00633 100644
+--- a/drivers/isdn/hisax/niccy.c
++++ b/drivers/isdn/hisax/niccy.c
+@@ -21,7 +21,6 @@
+ #include <linux/pci.h>
+ #include <linux/isapnp.h>
- 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;
- }
+-extern const char *CardType[];
+ static const char *niccy_revision = "$Revision: 1.21.2.4 $";
-@@ -2437,6 +2440,8 @@ static int raw1394_iso_get_status(struct file_info *fi, void __user * uaddr)
+ #define byteout(addr,val) outb(val,addr)
+@@ -256,7 +255,7 @@ int __devinit setup_niccy(struct IsdnCard *card)
+ err = pnp_activate_dev(pnp_d);
+ if (err < 0) {
+ printk(KERN_WARNING "%s: pnp_activate_dev "
+- "ret(%d)\n", __FUNCTION__, err);
++ "ret(%d)\n", __func__, err);
+ return 0;
+ }
+ card->para[1] = pnp_port_start(pnp_d, 0);
+@@ -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"
- /* reset overflow counter */
- atomic_set(&iso->overflows, 0);
-+ /* reset skip counter */
-+ atomic_set(&iso->skips, 0);
+-extern const char *CardType[];
+ static const char *s0box_revision = "$Revision: 2.6.2.4 $";
- 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[] = {
- };
+ 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"
- MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table);
-+#endif /* MODULE */
+-extern const char *CardType[];
+ static char *saphir_rev = "$Revision: 1.10.2.4 $";
- static struct hpsb_protocol_driver raw1394_driver = {
- .name = "raw1394",
-- .id_table = raw1394_id_table,
- };
+ #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);
+ }
- /******************************************************************************/
-@@ -3004,7 +3010,6 @@ static int __init init_raw1394(void)
+- 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);
- 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)
+ setup_isac(cs);
+ cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
+diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
+index 95425f3..a10dfa8 100644
+--- a/drivers/isdn/hisax/sedlbauer.c
++++ b/drivers/isdn/hisax/sedlbauer.c
+@@ -555,7 +555,7 @@ setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt)
+ err = pnp_activate_dev(pnp_d);
+ if (err<0) {
+ printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+- __FUNCTION__, err);
++ __func__, err);
+ return(0);
+ }
+ card->para[1] = pnp_port_start(pnp_d, 0);
+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"
- 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;
+-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/st5481.h b/drivers/isdn/hisax/st5481.h
+index 04416ba..2044e71 100644
+--- a/drivers/isdn/hisax/st5481.h
++++ b/drivers/isdn/hisax/st5481.h
+@@ -218,13 +218,13 @@ enum {
+ #define L1_EVENT_COUNT (EV_TIMER3 + 1)
+
+ #define ERR(format, arg...) \
+-printk(KERN_ERR "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg)
++printk(KERN_ERR "%s:%s: " format "\n" , __FILE__, __func__ , ## arg)
+
+ #define WARN(format, arg...) \
+-printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg)
++printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__, __func__ , ## arg)
+
+ #define INFO(format, arg...) \
+-printk(KERN_INFO "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg)
++printk(KERN_INFO "%s:%s: " format "\n" , __FILE__, __func__ , ## arg)
+
+ #include "isdnhdlc.h"
+ #include "fsm.h"
+@@ -406,7 +406,7 @@ struct st5481_adapter {
+
+ /*
+ * Submit an URB with error reporting. This is a macro so
+- * the __FUNCTION__ returns the caller function name.
++ * the __func__ returns the caller function name.
+ */
+ #define SUBMIT_URB(urb, mem_flags) \
+ ({ \
+@@ -470,7 +470,7 @@ extern int st5481_debug;
+ #ifdef CONFIG_HISAX_DEBUG
+
+ #define DBG_ISO_PACKET(level,urb) \
+- if (level & __debug_variable) dump_iso_packet(__FUNCTION__,urb)
++ if (level & __debug_variable) dump_iso_packet(__func__,urb)
+
+ static void __attribute__((unused))
+ dump_iso_packet(const char *name, struct urb *urb)
+diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
+index 4ada66b..427a8b0 100644
+--- a/drivers/isdn/hisax/st5481_usb.c
++++ b/drivers/isdn/hisax/st5481_usb.c
+@@ -342,7 +342,7 @@ void st5481_release_usb(struct st5481_adapter *adapter)
+ usb_kill_urb(intr->urb);
+ kfree(intr->urb->transfer_buffer);
+ usb_free_urb(intr->urb);
+- ctrl->urb = NULL;
++ intr->urb = NULL;
}
-@@ -1985,11 +1985,8 @@ static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
- lu->sdev = sdev;
- sdev->allow_restart = 1;
+ /*
+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"
-- /*
-- * 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);
+-extern const char *CardType[];
+-
+ static const char *TeleInt_revision = "$Revision: 1.16.2.5 $";
- 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[] = {
- };
+ #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/teles3.c b/drivers/isdn/hisax/teles3.c
+index 6a5e379..5dc9f1a 100644
+--- a/drivers/isdn/hisax/teles3.c
++++ b/drivers/isdn/hisax/teles3.c
+@@ -301,7 +301,7 @@ setup_teles3(struct IsdnCard *card)
+ err = pnp_activate_dev(pnp_d);
+ if (err<0) {
+ printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+- __FUNCTION__, err);
++ __func__, err);
+ return(0);
+ }
+ card->para[3] = pnp_port_start(pnp_d, 2);
+diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
+index 4393003..28b08de 100644
+--- a/drivers/isdn/hisax/telespci.c
++++ b/drivers/isdn/hisax/telespci.c
+@@ -19,7 +19,6 @@
+ #include "isdnl1.h"
+ #include <linux/pci.h>
- MODULE_DEVICE_TABLE(ieee1394, video1394_id_table);
-+#endif /* MODULE */
+-extern const char *CardType[];
+ static const char *telespci_revision = "$Revision: 2.23.2.3 $";
- static struct hpsb_protocol_driver video1394_driver = {
-- .name = VIDEO1394_DRIVER_NAME,
-- .id_table = video1394_id_table,
-+ .name = VIDEO1394_DRIVER_NAME,
- };
+ #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);
-@@ -1504,7 +1505,6 @@ static int __init video1394_init_module (void)
+ 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
- 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);
- }
+-extern const char *CardType[];
+-
+ static const char *w6692_revision = "$Revision: 1.18.2.4 $";
-+/*
-+ * 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)
+ #define DBUSY_TIMER_VALUE 80
+diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c
+index 27d890b..877be99 100644
+--- a/drivers/isdn/hysdn/hysdn_procconf.c
++++ b/drivers/isdn/hysdn/hysdn_procconf.c
+@@ -370,6 +370,7 @@ hysdn_conf_close(struct inode *ino, struct file *filep)
+ /******************************************************/
+ static const struct file_operations conf_fops =
{
- 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;
++ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .read = hysdn_conf_read,
+ .write = hysdn_conf_write,
+@@ -402,11 +403,9 @@ hysdn_procconf_init(void)
+ while (card) {
+
+ sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid);
+- if ((card->procconf = (void *) create_proc_entry(conf_name,
+- S_IFREG | S_IRUGO | S_IWUSR,
+- hysdn_proc_entry)) != NULL) {
+- ((struct proc_dir_entry *) card->procconf)->proc_fops = &conf_fops;
+- ((struct proc_dir_entry *) card->procconf)->owner = THIS_MODULE;
++ if ((card->procconf = (void *) proc_create(conf_name,
++ S_IFREG | S_IRUGO | S_IWUSR,
++ hysdn_proc_entry)) != NULL) {
+ hysdn_proclog_init(card); /* init the log file entry */
+ }
+ card = card->next; /* next entry */
+diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
+index 27b3991..8991d2c 100644
+--- a/drivers/isdn/hysdn/hysdn_proclog.c
++++ b/drivers/isdn/hysdn/hysdn_proclog.c
+@@ -380,6 +380,7 @@ hysdn_log_poll(struct file *file, poll_table * wait)
+ /**************************************************/
+ static const struct file_operations log_fops =
+ {
++ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .read = hysdn_log_read,
+ .write = hysdn_log_write,
+@@ -402,10 +403,9 @@ hysdn_proclog_init(hysdn_card * card)
+
+ if ((pd = kzalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) {
+ sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid);
+- if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) {
+- pd->log->proc_fops = &log_fops;
+- pd->log->owner = THIS_MODULE;
+- }
++ pd->log = proc_create(pd->log_name,
++ S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry,
++ &log_fops);
+
+ init_waitqueue_head(&(pd->rd_queue));
+
+diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
+index d4ad699..0f3c66d 100644
+--- a/drivers/isdn/i4l/isdn_common.c
++++ b/drivers/isdn/i4l/isdn_common.c
+@@ -1924,7 +1924,7 @@ isdn_free_channel(int di, int ch, int usage)
+
+ if ((di < 0) || (ch < 0)) {
+ printk(KERN_WARNING "%s: called with invalid drv(%d) or channel(%d)\n",
+- __FUNCTION__, di, ch);
++ __func__, di, ch);
+ return;
}
-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
+ for (i = 0; i < ISDN_MAX_CHANNELS; i++)
+diff --git a/drivers/isdn/i4l/isdn_net.h b/drivers/isdn/i4l/isdn_net.h
+index bc2f0dd..be49497 100644
+--- a/drivers/isdn/i4l/isdn_net.h
++++ b/drivers/isdn/i4l/isdn_net.h
+@@ -108,7 +108,7 @@ static __inline__ void isdn_net_add_to_bundle(isdn_net_dev *nd, isdn_net_local *
+
+ lp = nd->queue;
+ // printk(KERN_DEBUG "%s: lp:%s(%p) nlp:%s(%p) last(%p)\n",
+-// __FUNCTION__, lp->name, lp, nlp->name, nlp, lp->last);
++// __func__, lp->name, lp, nlp->name, nlp, lp->last);
+ nlp->last = lp->last;
+ lp->last->next = nlp;
+ lp->last = nlp;
+@@ -129,7 +129,7 @@ static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp)
+ master_lp = (isdn_net_local *) lp->master->priv;
+
+ // printk(KERN_DEBUG "%s: lp:%s(%p) mlp:%s(%p) last(%p) next(%p) mndq(%p)\n",
+-// __FUNCTION__, lp->name, lp, master_lp->name, master_lp, lp->last, lp->next, master_lp->netdev->queue);
++// __func__, lp->name, lp, master_lp->name, master_lp, lp->last, lp->next, master_lp->netdev->queue);
+ spin_lock_irqsave(&master_lp->netdev->queue_lock, flags);
+ lp->last->next = lp->next;
+ lp->next->last = lp->last;
+@@ -141,7 +141,7 @@ static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp)
+ }
+ lp->next = lp->last = lp; /* (re)set own pointers */
+ // printk(KERN_DEBUG "%s: mndq(%p)\n",
+-// __FUNCTION__, master_lp->netdev->queue);
++// __func__, master_lp->netdev->queue);
+ spin_unlock_irqrestore(&master_lp->netdev->queue_lock, flags);
+ }
+
+diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
+index 9f5fe37..127cfda 100644
+--- a/drivers/isdn/i4l/isdn_ppp.c
++++ b/drivers/isdn/i4l/isdn_ppp.c
+@@ -110,7 +110,7 @@ isdn_ppp_free(isdn_net_local * lp)
+
+ if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
+ printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
+- __FUNCTION__, lp->ppp_slot);
++ __func__, lp->ppp_slot);
+ return 0;
}
-- 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)
+@@ -127,7 +127,7 @@ isdn_ppp_free(isdn_net_local * lp)
+ #endif /* CONFIG_ISDN_MPP */
+ if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
+ printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n",
+- __FUNCTION__, lp->ppp_slot);
++ __func__, lp->ppp_slot);
+ return 0;
+ }
+ is = ippp_table[lp->ppp_slot];
+@@ -226,7 +226,7 @@ isdn_ppp_wakeup_daemon(isdn_net_local * lp)
{
-- struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
-+ struct ib_device *dev = container_of(device, struct ib_device, dev);
+ if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
+ printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
+- __FUNCTION__, lp->ppp_slot);
++ __func__, lp->ppp_slot);
+ return;
+ }
+ ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
+@@ -245,7 +245,7 @@ isdn_ppp_closewait(int slot)
- kfree(dev);
- }
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
+ printk(KERN_ERR "%s: slot(%d) out of range\n",
+- __FUNCTION__, slot);
++ __func__, slot);
+ return 0;
+ }
+ is = ippp_table[slot];
+@@ -343,7 +343,7 @@ isdn_ppp_release(int min, struct file *file)
+ is = file->private_data;
+
+ if (!is) {
+- printk(KERN_ERR "%s: no file->private_data\n", __FUNCTION__);
++ printk(KERN_ERR "%s: no file->private_data\n", __func__);
+ return;
+ }
+ if (is->debug & 0x1)
+@@ -353,7 +353,7 @@ isdn_ppp_release(int min, struct file *file)
+ isdn_net_dev *p = is->lp->netdev;
+
+ if (!p) {
+- printk(KERN_ERR "%s: no lp->netdev\n", __FUNCTION__);
++ printk(KERN_ERR "%s: no lp->netdev\n", __func__);
+ return;
+ }
+ is->state &= ~IPPP_CONNECT; /* -> effect: no call of wakeup */
+@@ -1080,7 +1080,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
+ printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
+ if (net_dev->local->ppp_slot < 0) {
+ printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
+- __FUNCTION__, net_dev->local->ppp_slot);
++ __func__, net_dev->local->ppp_slot);
+ goto drop_packet;
+ }
+ if (slhc_remember(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
+@@ -1107,7 +1107,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
+ skb_old->len);
+ if (net_dev->local->ppp_slot < 0) {
+ printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
+- __FUNCTION__, net_dev->local->ppp_slot);
++ __func__, net_dev->local->ppp_slot);
+ goto drop_packet;
+ }
+ pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp,
+@@ -1553,7 +1553,7 @@ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
--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 (lp->ppp_slot < 0) {
+ printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+- __FUNCTION__, lp->ppp_slot);
++ __func__, lp->ppp_slot);
+ return(-EINVAL);
+ }
+
+@@ -1604,7 +1604,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
+ slot = lp->ppp_slot;
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
+ printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
+- __FUNCTION__, lp->ppp_slot);
++ __func__, lp->ppp_slot);
+ stats->frame_drops++;
+ dev_kfree_skb(skb);
+ spin_unlock_irqrestore(&mp->lock, flags);
+@@ -1641,7 +1641,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
+ slot = lpq->ppp_slot;
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
+ printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
+- __FUNCTION__, lpq->ppp_slot);
++ __func__, lpq->ppp_slot);
+ } else {
+ u32 lls = ippp_table[slot]->last_link_seqno;
+ if (MP_LT(lls, minseq))
+@@ -1875,7 +1875,7 @@ void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
+
+ if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
+ printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+- __FUNCTION__, lp->ppp_slot);
++ __func__, lp->ppp_slot);
+ return;
+ }
+ if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) {
+@@ -2655,7 +2655,7 @@ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
+ lp->ppp_slot);
+ if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
+ printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+- __FUNCTION__, lp->ppp_slot);
++ __func__, lp->ppp_slot);
+ return;
+ }
+ is = ippp_table[lp->ppp_slot];
+@@ -2665,7 +2665,7 @@ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
+ int slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
+ printk(KERN_ERR "%s: slot(%d) out of range\n",
+- __FUNCTION__, slot);
++ __func__, slot);
+ return;
+ }
+ mis = ippp_table[slot];
+@@ -2829,7 +2829,7 @@ static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct
+ return;
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
+ printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+- __FUNCTION__, slot);
++ __func__, slot);
+ return;
+ }
+ is = ippp_table[slot];
+@@ -2852,7 +2852,7 @@ static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct
+ slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
+ printk(KERN_ERR "%s: slot(%d) out of range\n",
+- __FUNCTION__, slot);
++ __func__, slot);
+ return;
+ }
+ mis = ippp_table[slot];
+diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
+index 133eb18..1a2222c 100644
+--- a/drivers/isdn/i4l/isdn_tty.c
++++ b/drivers/isdn/i4l/isdn_tty.c
+@@ -1347,17 +1347,19 @@ isdn_tty_tiocmget(struct tty_struct *tty, struct file *file)
+ modem_info *info = (modem_info *) tty->driver_data;
+ u_char control, status;
- if (add_uevent_var(env, "NAME=%s", dev->name))
- return -ENOMEM;
-@@ -567,9 +567,10 @@ err_put:
- return ret;
- }
+- if (isdn_tty_paranoia_check(info, tty->name, __FUNCTION__))
++ if (isdn_tty_paranoia_check(info, tty->name, __func__))
+ return -ENODEV;
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
--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)
++ lock_kernel();
+ #ifdef ISDN_DEBUG_MODEM_IOCTL
+ printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
+ #endif
+
+ control = info->mcr;
+ status = info->msr;
++ unlock_kernel();
+ return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
+ | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
+ | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
+@@ -1372,7 +1374,7 @@ isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
{
-- struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
-+ struct ib_device *dev = container_of(device, struct ib_device, dev);
+ modem_info *info = (modem_info *) tty->driver_data;
- if (!ibdev_is_alive(dev))
+- if (isdn_tty_paranoia_check(info, tty->name, __FUNCTION__))
++ if (isdn_tty_paranoia_check(info, tty->name, __func__))
return -ENODEV;
-@@ -583,9 +584,10 @@ static ssize_t show_node_type(struct class_device *cdev, char *buf)
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+@@ -1381,6 +1383,7 @@ isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
+ printk(KERN_DEBUG "ttyI%d ioctl TIOCMxxx: %x %x\n", info->line, set, clear);
+ #endif
+
++ lock_kernel();
+ if (set & TIOCM_RTS)
+ info->mcr |= UART_MCR_RTS;
+ if (set & TIOCM_DTR) {
+@@ -1402,6 +1405,7 @@ isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
+ isdn_tty_modem_hup(info, 1);
+ }
}
++ unlock_kernel();
+ return 0;
}
--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]));
+@@ -1435,21 +1439,6 @@ isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ return 0;
+- case TIOCGSOFTCAR:
+-#ifdef ISDN_DEBUG_MODEM_IOCTL
+- printk(KERN_DEBUG "ttyI%d ioctl TIOCGSOFTCAR\n", info->line);
+-#endif
+- return put_user(C_CLOCAL(tty) ? 1 : 0, (ulong __user *) arg);
+- case TIOCSSOFTCAR:
+-#ifdef ISDN_DEBUG_MODEM_IOCTL
+- printk(KERN_DEBUG "ttyI%d ioctl TIOCSSOFTCAR\n", info->line);
+-#endif
+- if (get_user(arg, (ulong __user *) arg))
+- return -EFAULT;
+- tty->termios->c_cflag =
+- ((tty->termios->c_cflag & ~CLOCAL) |
+- (arg ? CLOCAL : 0));
+- return 0;
+ case TIOCSERGETLSR: /* Get line status register */
+ #ifdef ISDN_DEBUG_MODEM_IOCTL
+ printk(KERN_DEBUG "ttyI%d ioctl TIOCSERGETLSR\n", info->line);
+@@ -1472,13 +1461,14 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+ if (!old_termios)
+ isdn_tty_change_speed(info);
+ else {
+- if (tty->termios->c_cflag == old_termios->c_cflag)
++ if (tty->termios->c_cflag == old_termios->c_cflag &&
++ tty->termios->c_ispeed == old_termios->c_ispeed &&
++ tty->termios->c_ospeed == old_termios->c_ospeed)
+ return;
+ isdn_tty_change_speed(info);
+ if ((old_termios->c_cflag & CRTSCTS) &&
+- !(tty->termios->c_cflag & CRTSCTS)) {
++ !(tty->termios->c_cflag & CRTSCTS))
+ tty->hw_stopped = 0;
+- }
+ }
}
--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))
+@@ -1608,7 +1598,7 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp)
+ if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open"))
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]));
- }
+ if (!try_module_get(info->owner)) {
+- printk(KERN_WARNING "%s: cannot reserve module\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: cannot reserve module\n", __func__);
+ return -ENODEV;
+ }
+ #ifdef ISDN_DEBUG_MODEM_OPEN
+@@ -1718,9 +1708,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
+ }
+ dev->modempoll--;
+ isdn_tty_shutdown(info);
+-
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ isdn_tty_flush_buffer(tty);
+ tty_ldisc_flush(tty);
+ info->tty = NULL;
+ info->ncarrier = 0;
+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).
--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);
+-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.
- return sprintf(buf, "%.64s\n", dev->node_desc);
- }
++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
--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;
+ This module can drive the mail LED for the following notebooks:
-@@ -642,44 +647,43 @@ static ssize_t set_node_desc(struct class_device *cdev, const char *buf,
- return count;
- }
++ 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)
--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);
++ If your model is not listed here you can try the "nodetect"
++ module paramter.
+
-+static struct device_attribute *ib_class_attributes[] = {
-+ &dev_attr_node_type,
-+ &dev_attr_sys_image_guid,
-+ &dev_attr_node_guid,
-+ &dev_attr_node_desc
- };
+ To compile this driver as a module, choose M here: the
+ module will be called leds-clevo-mail.
- 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,
- };
+@@ -181,4 +183,11 @@ config LEDS_TRIGGER_HEARTBEAT
+ load average.
+ If unsure, say Y.
- 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;
++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
- 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);
+ # 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..b3c54be 100644
+--- a/drivers/leds/led-class.c
++++ b/drivers/leds/led-class.c
+@@ -24,6 +24,12 @@
- INIT_LIST_HEAD(&device->port_list);
+ static struct class *leds_class;
-- ret = class_device_register(class_dev);
-+ ret = device_register(class_dev);
- if (ret)
- goto err;
++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;
- 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);
+ /* no lock needed for this */
++ led_update_brightness(led_cdev);
+ sprintf(buf, "%u\n", led_cdev->brightness);
+ ret = strlen(buf) + 1;
- err_unregister:
-- class_device_unregister(class_dev);
-+ device_unregister(class_dev);
+@@ -51,6 +58,9 @@ static ssize_t led_brightness_store(struct device *dev,
- err:
- return ret;
-@@ -744,7 +748,7 @@ void ib_device_unregister_sysfs(struct ib_device *device)
+ if (count == size) {
+ ret = count;
++
++ if (state == LED_OFF)
++ led_trigger_remove(led_cdev);
+ led_set_brightness(led_cdev, state);
}
- kobject_put(device->ports_parent);
-- class_device_unregister(&device->class_dev);
-+ device_unregister(&device->dev);
- }
+@@ -95,7 +105,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
- 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");
+ led_cdev->dev = device_create(leds_class, parent, 0, "%s",
+ led_cdev->name);
+- if (unlikely(IS_ERR(led_cdev->dev)))
++ if (IS_ERR(led_cdev->dev))
+ return PTR_ERR(led_cdev->dev);
- 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;
- };
+ dev_set_drvdata(led_cdev->dev, led_cdev);
+@@ -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);
-@@ -1171,7 +1171,7 @@ static int ib_ucm_open(struct inode *inode, struct file *filp)
++ led_update_brightness(led_cdev);
++
+ #ifdef CONFIG_LEDS_TRIGGERS
+ init_rwsem(&led_cdev->trigger_lock);
- 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);
+@@ -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
- return 0;
- }
-@@ -1202,14 +1202,14 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
- return 0;
+- 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 void ucm_release_class_dev(struct class_device *class_dev)
-+static void ib_ucm_release_dev(struct device *dev)
+ static int __init leds_init(void)
{
-- struct ib_ucm_device *dev;
-+ struct ib_ucm_device *ucm_dev;
+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"
-- 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);
- }
+ DECLARE_RWSEM(leds_list_lock);
+-LIST_HEAD(leds_list);
++EXPORT_SYMBOL_GPL(leds_list_lock);
- static const struct file_operations ucm_fops = {
-@@ -1220,14 +1220,15 @@ static const struct file_operations ucm_fops = {
- .poll = ib_ucm_poll,
- };
++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);
--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)
++ /* Used by LED Class */
++
+ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
-- struct ib_ucm_device *dev;
-+ struct ib_ucm_device *ucm_dev;
+@@ -45,9 +47,7 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
+ trigger_name[len - 1] = '\0';
-- 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);
+ 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;
}
--static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
-+static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
+-
++EXPORT_SYMBOL_GPL(led_trigger_store);
- static void ib_ucm_add_one(struct ib_device *device)
+ 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)
{
-@@ -1249,32 +1250,31 @@ static void ib_ucm_add_one(struct ib_device *device)
+@@ -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 */
- set_bit(ucm_dev->devnum, dev_map);
+ int led_trigger_register(struct led_trigger *trigger)
+ {
+@@ -181,26 +177,7 @@ int led_trigger_register(struct led_trigger *trigger)
-- 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;
+ 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);
-- 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;
+ 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);
-- 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;
+ 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);
- ib_set_client_data(device, &ucm_client, ucm_dev);
- return;
+ 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
--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;
+-MODULE_AUTHOR("Márton Németh <nm127 at freemail.hu>");
++MODULE_AUTHOR("Márton Németh <nm127 at freemail.hu>");
+ MODULE_DESCRIPTION("Clevo mail LED driver");
+ MODULE_LICENSE("GPL");
-- class_device_unregister(&ucm_dev->class_dev);
-+ device_unregister(&ucm_dev->dev);
+@@ -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 ssize_t show_abi_version(struct class *class, char *buf)
-diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
-index 15937eb..ca4cf3a 100644
---- a/drivers/infiniband/core/ucma.c
-+++ b/drivers/infiniband/core/ucma.c
-@@ -614,7 +614,7 @@ static ssize_t ucma_query_route(struct ucma_file *file,
- if (!ctx->cm_id->device)
- goto out;
-
-- resp.node_guid = ctx->cm_id->device->node_guid;
-+ resp.node_guid = (__force __u64) ctx->cm_id->device->node_guid;
- resp.port_num = ctx->cm_id->port_num;
- switch (rdma_node_get_transport(ctx->cm_id->device->node_type)) {
- case RDMA_TRANSPORT_IB:
-diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
-index 4e91510..3aa2db5 100644
---- a/drivers/infiniband/core/user_mad.c
-+++ b/drivers/infiniband/core/user_mad.c
-@@ -46,9 +46,9 @@
- #include <linux/mutex.h>
- #include <linux/kref.h>
- #include <linux/compat.h>
-+#include <linux/semaphore.h>
+ 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;
- #include <asm/uaccess.h>
--#include <asm/semaphore.h>
+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;
- #include <rdma/ib_mad.h>
- #include <rdma/ib_user_mad.h>
-@@ -88,11 +88,11 @@ enum {
+ static void qube_front_led_set(struct led_classdev *led_cdev,
+- enum led_brightness brightness)
++ enum led_brightness brightness)
+ {
+ if (brightness)
+ led_value = LED_FRONT_LEFT | LED_FRONT_RIGHT;
+diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c
+index 6ebfff3..ff0e8c3 100644
+--- a/drivers/leds/leds-cobalt-raq.c
++++ b/drivers/leds/leds-cobalt-raq.c
+@@ -15,7 +15,7 @@
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+ #include <linux/init.h>
+ #include <linux/io.h>
+@@ -33,7 +33,7 @@ static u8 led_value;
+ static DEFINE_SPINLOCK(led_value_lock);
- 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;
+ static void raq_web_led_set(struct led_classdev *led_cdev,
+- enum led_brightness brightness)
++ enum led_brightness brightness)
+ {
+ unsigned long flags;
- struct mutex file_mutex;
-@@ -948,27 +948,29 @@ static struct ib_client umad_client = {
- .remove = ib_umad_remove_one
+@@ -54,7 +54,7 @@ static struct led_classdev raq_web_led = {
};
--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)
+ static void raq_power_off_led_set(struct led_classdev *led_cdev,
+- enum led_brightness brightness)
++ enum led_brightness brightness)
{
-- struct ib_umad_port *port = class_get_devdata(class_dev);
-+ struct ib_umad_port *port = dev_get_drvdata(dev);
+ unsigned long flags;
- if (!port)
- return -ENODEV;
+diff --git a/drivers/leds/leds-corgi.c b/drivers/leds/leds-corgi.c
+index 29e931f..a709704 100644
+--- a/drivers/leds/leds-corgi.c
++++ b/drivers/leds/leds-corgi.c
+@@ -21,7 +21,8 @@
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/hardware/scoop.h>
- return sprintf(buf, "%s\n", port->ib_dev->name);
+-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 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)
+-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)
{
-- 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);
+ 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 ssize_t show_abi_version(struct class *class, char *buf)
+ static void __exit corgiled_exit(void)
{
-@@ -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);
+- platform_driver_unregister(&corgiled_driver);
++ platform_driver_unregister(&corgiled_driver);
+ }
-- 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;
+ module_init(corgiled_init);
+diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c
+new file mode 100644
+index 0000000..a7421b8
+--- /dev/null
++++ b/drivers/leds/leds-fsg.c
+@@ -0,0 +1,261 @@
++/*
++ * LED Driver for the Freecom FSG-3
++ *
++ * Copyright (c) 2008 Rod Whitby <rod at whitby.id.au>
++ *
++ * Author: Rod Whitby <rod at whitby.id.au>
++ *
++ * Based on leds-spitz.c
++ * Copyright 2005-2006 Openedhand Ltd.
++ * Author: Richard Purdie <rpurdie at openedhand.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/leds.h>
++#include <asm/arch/hardware.h>
++#include <asm/io.h>
++
++static short __iomem *latch_address;
++static unsigned short latch_value;
++
++
++static void fsg_led_wlan_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
++{
++ if (value) {
++ latch_value &= ~(1 << FSG_LED_WLAN_BIT);
++ *latch_address = latch_value;
++ } else {
++ latch_value |= (1 << FSG_LED_WLAN_BIT);
++ *latch_address = latch_value;
++ }
++}
++
++static void fsg_led_wan_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
++{
++ if (value) {
++ latch_value &= ~(1 << FSG_LED_WAN_BIT);
++ *latch_address = latch_value;
++ } else {
++ latch_value |= (1 << FSG_LED_WAN_BIT);
++ *latch_address = latch_value;
++ }
++}
++
++static void fsg_led_sata_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
++{
++ if (value) {
++ latch_value &= ~(1 << FSG_LED_SATA_BIT);
++ *latch_address = latch_value;
++ } else {
++ latch_value |= (1 << FSG_LED_SATA_BIT);
++ *latch_address = latch_value;
++ }
++}
++
++static void fsg_led_usb_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
++{
++ if (value) {
++ latch_value &= ~(1 << FSG_LED_USB_BIT);
++ *latch_address = latch_value;
++ } else {
++ latch_value |= (1 << FSG_LED_USB_BIT);
++ *latch_address = latch_value;
++ }
++}
++
++static void fsg_led_sync_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
++{
++ if (value) {
++ latch_value &= ~(1 << FSG_LED_SYNC_BIT);
++ *latch_address = latch_value;
++ } else {
++ latch_value |= (1 << FSG_LED_SYNC_BIT);
++ *latch_address = latch_value;
++ }
++}
++
++static void fsg_led_ring_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
++{
++ if (value) {
++ latch_value &= ~(1 << FSG_LED_RING_BIT);
++ *latch_address = latch_value;
++ } else {
++ latch_value |= (1 << FSG_LED_RING_BIT);
++ *latch_address = latch_value;
++ }
++}
++
++
++
++static struct led_classdev fsg_wlan_led = {
++ .name = "fsg:blue:wlan",
++ .brightness_set = fsg_led_wlan_set,
++};
++
++static struct led_classdev fsg_wan_led = {
++ .name = "fsg:blue:wan",
++ .brightness_set = fsg_led_wan_set,
++};
++
++static struct led_classdev fsg_sata_led = {
++ .name = "fsg:blue:sata",
++ .brightness_set = fsg_led_sata_set,
++};
++
++static struct led_classdev fsg_usb_led = {
++ .name = "fsg:blue:usb",
++ .brightness_set = fsg_led_usb_set,
++};
++
++static struct led_classdev fsg_sync_led = {
++ .name = "fsg:blue:sync",
++ .brightness_set = fsg_led_sync_set,
++};
++
++static struct led_classdev fsg_ring_led = {
++ .name = "fsg:blue:ring",
++ .brightness_set = fsg_led_ring_set,
++};
++
++
++
++#ifdef CONFIG_PM
++static int fsg_led_suspend(struct platform_device *dev, pm_message_t state)
++{
++ led_classdev_suspend(&fsg_wlan_led);
++ led_classdev_suspend(&fsg_wan_led);
++ led_classdev_suspend(&fsg_sata_led);
++ led_classdev_suspend(&fsg_usb_led);
++ led_classdev_suspend(&fsg_sync_led);
++ led_classdev_suspend(&fsg_ring_led);
++ return 0;
++}
++
++static int fsg_led_resume(struct platform_device *dev)
++{
++ led_classdev_resume(&fsg_wlan_led);
++ led_classdev_resume(&fsg_wan_led);
++ led_classdev_resume(&fsg_sata_led);
++ led_classdev_resume(&fsg_usb_led);
++ led_classdev_resume(&fsg_sync_led);
++ led_classdev_resume(&fsg_ring_led);
++ return 0;
++}
++#endif
++
++
++static int fsg_led_probe(struct platform_device *pdev)
++{
++ int ret;
++
++ ret = led_classdev_register(&pdev->dev, &fsg_wlan_led);
++ if (ret < 0)
++ goto failwlan;
++
++ ret = led_classdev_register(&pdev->dev, &fsg_wan_led);
++ if (ret < 0)
++ goto failwan;
++
++ ret = led_classdev_register(&pdev->dev, &fsg_sata_led);
++ if (ret < 0)
++ goto failsata;
++
++ ret = led_classdev_register(&pdev->dev, &fsg_usb_led);
++ if (ret < 0)
++ goto failusb;
++
++ ret = led_classdev_register(&pdev->dev, &fsg_sync_led);
++ if (ret < 0)
++ goto failsync;
++
++ ret = led_classdev_register(&pdev->dev, &fsg_ring_led);
++ if (ret < 0)
++ goto failring;
++
++ /* Map the LED chip select address space */
++ latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
++ if (!latch_address) {
++ ret = -ENOMEM;
++ goto failremap;
++ }
++
++ latch_value = 0xffff;
++ *latch_address = latch_value;
++
++ return ret;
++
++ failremap:
++ led_classdev_unregister(&fsg_ring_led);
++ failring:
++ led_classdev_unregister(&fsg_sync_led);
++ failsync:
++ led_classdev_unregister(&fsg_usb_led);
++ failusb:
++ led_classdev_unregister(&fsg_sata_led);
++ failsata:
++ led_classdev_unregister(&fsg_wan_led);
++ failwan:
++ led_classdev_unregister(&fsg_wlan_led);
++ failwlan:
++
++ return ret;
++}
++
++static int fsg_led_remove(struct platform_device *pdev)
++{
++ iounmap(latch_address);
++
++ led_classdev_unregister(&fsg_wlan_led);
++ led_classdev_unregister(&fsg_wan_led);
++ led_classdev_unregister(&fsg_sata_led);
++ led_classdev_unregister(&fsg_usb_led);
++ led_classdev_unregister(&fsg_sync_led);
++ led_classdev_unregister(&fsg_ring_led);
++
++ return 0;
++}
++
++
++static struct platform_driver fsg_led_driver = {
++ .probe = fsg_led_probe,
++ .remove = fsg_led_remove,
++#ifdef CONFIG_PM
++ .suspend = fsg_led_suspend,
++ .resume = fsg_led_resume,
++#endif
++ .driver = {
++ .name = "fsg-led",
++ },
++};
++
++
++static int __init fsg_led_init(void)
++{
++ return platform_driver_register(&fsg_led_driver);
++}
++
++static void __exit fsg_led_exit(void)
++{
++ platform_driver_unregister(&fsg_led_driver);
++}
++
++
++module_init(fsg_led_init);
++module_exit(fsg_led_exit);
++
++MODULE_AUTHOR("Rod Whitby <rod at whitby.id.au>");
++MODULE_DESCRIPTION("Freecom FSG-3 LED driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
+index 1aae8b3..b13bd29 100644
+--- a/drivers/leds/leds-gpio.c
++++ b/drivers/leds/leds-gpio.c
+@@ -24,6 +24,8 @@ struct gpio_led_data {
+ u8 new_level;
+ u8 can_sleep;
+ u8 active_low;
++ int (*platform_gpio_blink_set)(unsigned gpio,
++ unsigned long *delay_on, unsigned long *delay_off);
+ };
-- 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;
+ 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);
+ }
-- 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;
++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);
+
-+ 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;
++ 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;
-- 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;
+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;
+ }
+ }
-- 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);
+@@ -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;
+ }
+ }
-- 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;
+@@ -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);
+ }
- 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,
+ }
+diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c
+index 870f5a3..844d597 100644
+--- a/drivers/leds/leds-hp6xx.c
++++ b/drivers/leds/leds-hp6xx.c
+@@ -17,7 +17,8 @@
+ #include <asm/hd64461.h>
+ #include <asm/hp6xx.h>
- return 0;
+-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;
--err_sm_class:
-- class_device_destroy(umad_class, port->sm_dev->dev);
-+err_sm_dev:
-+ device_destroy(umad_class, port->sm_cdev->dev);
+@@ -28,7 +29,8 @@ static void hp6xxled_green_set(struct led_classdev *led_cdev, enum led_brightnes
+ outb(v8 | PKDR_LED_GREEN, PKDR);
+ }
- err_sm_cdev:
-- cdev_del(port->sm_dev);
-+ cdev_del(port->sm_cdev);
+-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;
--err_class:
-- class_device_destroy(umad_class, port->dev->dev);
-+err_dev:
-+ device_destroy(umad_class, port->cdev->dev);
+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,
- err_cdev:
-- cdev_del(port->dev);
-+ cdev_del(port->cdev);
- clear_bit(port->dev_num, dev_map);
+ 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);
- 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);
+@@ -151,7 +151,7 @@ static int __init s3c24xx_led_init(void)
-- 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);
+ static void __exit s3c24xx_led_exit(void)
+ {
+- platform_driver_unregister(&s3c24xx_led_driver);
++ platform_driver_unregister(&s3c24xx_led_driver);
+ }
-- cdev_del(port->dev);
-- cdev_del(port->sm_dev);
-+ cdev_del(port->cdev);
-+ cdev_del(port->sm_cdev);
+ module_init(s3c24xx_led_init);
+diff --git a/drivers/leds/leds-spitz.c b/drivers/leds/leds-spitz.c
+index 87007cc..e75e854 100644
+--- a/drivers/leds/leds-spitz.c
++++ b/drivers/leds/leds-spitz.c
+@@ -21,7 +21,8 @@
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/spitz.h>
- 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;
- };
+-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);
+ }
- 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;
- };
+-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)
- 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;
+ static void __exit spitzled_exit(void)
+ {
+- platform_driver_unregister(&spitzled_driver);
++ platform_driver_unregister(&spitzled_driver);
+ }
- 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;
+ module_init(spitzled_init);
+diff --git a/drivers/leds/leds-tosa.c b/drivers/leds/leds-tosa.c
+deleted file mode 100644
+index 7ebecc4..0000000
+--- a/drivers/leds/leds-tosa.c
++++ /dev/null
+@@ -1,132 +0,0 @@
+-/*
+- * LED Triggers Core
+- *
+- * Copyright 2005 Dirk Opfer
+- *
+- * Author: Dirk Opfer <Dirk at Opfer-Online.de>
+- * based on spitz.c
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- *
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/leds.h>
+-#include <asm/hardware/scoop.h>
+-#include <asm/mach-types.h>
+-#include <asm/arch/hardware.h>
+-#include <asm/arch/pxa-regs.h>
+-#include <asm/arch/tosa.h>
+-
+-static void tosaled_amber_set(struct led_classdev *led_cdev,
+- enum led_brightness value)
+-{
+- if (value)
+- set_scoop_gpio(&tosascoop_jc_device.dev,
+- TOSA_SCOOP_JC_CHRG_ERR_LED);
+- else
+- reset_scoop_gpio(&tosascoop_jc_device.dev,
+- TOSA_SCOOP_JC_CHRG_ERR_LED);
+-}
+-
+-static void tosaled_green_set(struct led_classdev *led_cdev,
+- enum led_brightness value)
+-{
+- if (value)
+- set_scoop_gpio(&tosascoop_jc_device.dev,
+- TOSA_SCOOP_JC_NOTE_LED);
+- else
+- reset_scoop_gpio(&tosascoop_jc_device.dev,
+- TOSA_SCOOP_JC_NOTE_LED);
+-}
+-
+-static struct led_classdev tosa_amber_led = {
+- .name = "tosa:amber:charge",
+- .default_trigger = "sharpsl-charge",
+- .brightness_set = tosaled_amber_set,
+-};
+-
+-static struct led_classdev tosa_green_led = {
+- .name = "tosa:green:mail",
+- .default_trigger = "nand-disk",
+- .brightness_set = tosaled_green_set,
+-};
+-
+-#ifdef CONFIG_PM
+-static int tosaled_suspend(struct platform_device *dev, pm_message_t state)
+-{
+-#ifdef CONFIG_LEDS_TRIGGERS
+- if (tosa_amber_led.trigger && strcmp(tosa_amber_led.trigger->name,
+- "sharpsl-charge"))
+-#endif
+- led_classdev_suspend(&tosa_amber_led);
+- led_classdev_suspend(&tosa_green_led);
+- return 0;
+-}
+-
+-static int tosaled_resume(struct platform_device *dev)
+-{
+- led_classdev_resume(&tosa_amber_led);
+- led_classdev_resume(&tosa_green_led);
+- return 0;
+-}
+-#else
+-#define tosaled_suspend NULL
+-#define tosaled_resume NULL
+-#endif
+-
+-static int tosaled_probe(struct platform_device *pdev)
+-{
+- int ret;
+-
+- ret = led_classdev_register(&pdev->dev, &tosa_amber_led);
+- if (ret < 0)
+- return ret;
+-
+- ret = led_classdev_register(&pdev->dev, &tosa_green_led);
+- if (ret < 0)
+- led_classdev_unregister(&tosa_amber_led);
+-
+- return ret;
+-}
+-
+-static int tosaled_remove(struct platform_device *pdev)
+-{
+- led_classdev_unregister(&tosa_amber_led);
+- led_classdev_unregister(&tosa_green_led);
+-
+- return 0;
+-}
+-
+-static struct platform_driver tosaled_driver = {
+- .probe = tosaled_probe,
+- .remove = tosaled_remove,
+- .suspend = tosaled_suspend,
+- .resume = tosaled_resume,
+- .driver = {
+- .name = "tosa-led",
+- .owner = THIS_MODULE,
+- },
+-};
+-
+-static int __init tosaled_init(void)
+-{
+- return platform_driver_register(&tosaled_driver);
+-}
+-
+-static void __exit tosaled_exit(void)
+-{
+- platform_driver_unregister(&tosaled_driver);
+-}
+-
+-module_init(tosaled_init);
+-module_exit(tosaled_exit);
+-
+-MODULE_AUTHOR("Dirk Opfer <Dirk at Opfer-Online.de>");
+-MODULE_DESCRIPTION("Tosa LED driver");
+-MODULE_LICENSE("GPL");
+-MODULE_ALIAS("platform:tosa-led");
+diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
+index 12b6fe9..5edbf52 100644
+--- a/drivers/leds/leds.h
++++ b/drivers/leds/leds.h
+@@ -27,6 +27,11 @@ static inline void led_set_brightness(struct led_classdev *led_cdev,
+ led_cdev->brightness_set(led_cdev, value);
+ }
- 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;
++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;
- 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;
+@@ -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
- spin_lock_irqsave(&file->lock, flags);
-- if (!file->file) {
-+ if (file->is_closed) {
- spin_unlock_irqrestore(&file->lock, flags);
- return;
+ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
+diff --git a/drivers/leds/ledtrig-default-on.c b/drivers/leds/ledtrig-default-on.c
+new file mode 100644
+index 0000000..92995e4
+--- /dev/null
++++ b/drivers/leds/ledtrig-default-on.c
+@@ -0,0 +1,45 @@
++/*
++ * LED Kernel Default ON Trigger
++ *
++ * Copyright 2008 Nick Forbes <nick.forbes at incepta.com>
++ *
++ * Based on Richard Purdie's ledtrig-timer.c.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/leds.h>
++#include "leds.h"
++
++static void defon_trig_activate(struct led_classdev *led_cdev)
++{
++ led_set_brightness(led_cdev, LED_FULL);
++}
++
++static struct led_trigger defon_led_trigger = {
++ .name = "default-on",
++ .activate = defon_trig_activate,
++};
++
++static int __init defon_trig_init(void)
++{
++ return led_trigger_register(&defon_led_trigger);
++}
++
++static void __exit defon_trig_exit(void)
++{
++ led_trigger_unregister(&defon_led_trigger);
++}
++
++module_init(defon_trig_init);
++module_exit(defon_trig_exit);
++
++MODULE_AUTHOR("Nick Forbes <nick.forbes at incepta.com>");
++MODULE_DESCRIPTION("Default-ON LED trigger");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/leds/ledtrig-ide-disk.c b/drivers/leds/ledtrig-ide-disk.c
+index 54b155c..883a577 100644
+--- a/drivers/leds/ledtrig-ide-disk.c
++++ b/drivers/leds/ledtrig-ide-disk.c
+@@ -38,7 +38,7 @@ static void ledtrig_ide_timerfunc(unsigned long data)
+ if (ide_lastactivity != ide_activity) {
+ ide_lastactivity = ide_activity;
+ led_trigger_event(ledtrig_ide, LED_FULL);
+- mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
++ mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
+ } else {
+ led_trigger_event(ledtrig_ide, LED_OFF);
}
-@@ -423,7 +423,7 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
- unsigned long flags;
+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"
- 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;
+ 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;
- *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;
+ if (!timer_data->delay_on || !timer_data->delay_off) {
+ led_set_brightness(led_cdev, LED_OFF);
+ return;
}
-- 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;
+- 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;
+ }
- return filp;
-@@ -696,27 +690,29 @@ static struct ib_client uverbs_client = {
- .remove = ib_uverbs_remove_one
- };
+ 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 show_ibdev(struct class_device *class_dev, char *buf)
-+static ssize_t show_ibdev(struct device *device, struct device_attribute *attr,
-+ char *buf)
+-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 ib_uverbs_device *dev = class_get_devdata(class_dev);
-+ struct ib_uverbs_device *dev = dev_get_drvdata(device);
+ 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;
+ }
- if (!dev)
- return -ENODEV;
+-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;
+ }
- return sprintf(buf, "%s\n", dev->ib_dev->name);
+-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 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)
+-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 ib_uverbs_device *dev = class_get_devdata(class_dev);
-+ struct ib_uverbs_device *dev = dev_get_drvdata(device);
+ 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;
- if (!dev)
- return -ENODEV;
++ 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;
- return sprintf(buf, "%d\n", dev->ib_dev->uverbs_abi_ver);
+ init_timer(&timer_data->timer);
+diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
+index 2337e1a..005bd04 100644
+--- a/drivers/lguest/lg.h
++++ b/drivers/lguest/lg.h
+@@ -10,7 +10,6 @@
+ #include <linux/wait.h>
+ #include <linux/hrtimer.h>
+ #include <linux/err.h>
+-#include <asm/semaphore.h>
+
+ #include <asm/lguest.h>
+
+diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
+index 77f50b6..b526596 100644
+--- a/drivers/macintosh/Kconfig
++++ b/drivers/macintosh/Kconfig
+@@ -234,6 +234,14 @@ config WINDFARM_PM112
+ which are the recent dual and quad G5 machines using the
+ 970MP dual-core processor.
+
++config WINDFARM_PM121
++ tristate "Support for thermal management on PowerMac12,1"
++ depends on WINDFARM && I2C && PMAC_SMU
++ select I2C_POWERMAC
++ help
++ This driver provides thermal control for the PowerMac12,1
++ which is the iMac G5 (iSight).
++
+ config ANSLCD
+ tristate "Support for ANS LCD display"
+ depends on ADB_CUDA && PPC_PMAC
+diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile
+index 2dfc3f4..e3132ef 100644
+--- a/drivers/macintosh/Makefile
++++ b/drivers/macintosh/Makefile
+@@ -42,4 +42,9 @@ obj-$(CONFIG_WINDFARM_PM112) += windfarm_pm112.o windfarm_smu_sat.o \
+ windfarm_smu_sensors.o \
+ windfarm_max6690_sensor.o \
+ windfarm_lm75_sensor.o windfarm_pid.o
++obj-$(CONFIG_WINDFARM_PM121) += windfarm_pm121.o windfarm_smu_sat.o \
++ windfarm_smu_controls.o \
++ windfarm_smu_sensors.o \
++ windfarm_max6690_sensor.o \
++ windfarm_lm75_sensor.o windfarm_pid.o
+ obj-$(CONFIG_PMAC_RACKMETER) += rack-meter.o
+diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
+index 2895810..2097820 100644
+--- a/drivers/macintosh/adb.c
++++ b/drivers/macintosh/adb.c
+@@ -37,9 +37,9 @@
+ #include <linux/device.h>
+ #include <linux/kthread.h>
+ #include <linux/platform_device.h>
++#include <linux/semaphore.h>
+
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #ifdef CONFIG_PPC
+ #include <asm/prom.h>
+ #include <asm/machdep.h>
+diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
+index 8930230..cc9f275 100644
+--- a/drivers/macintosh/mac_hid.c
++++ b/drivers/macintosh/mac_hid.c
+@@ -103,6 +103,9 @@ int mac_hid_mouse_emulate_buttons(int caller, unsigned int keycode, int down)
+ return 0;
}
--static 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)
++static struct lock_class_key emumousebtn_event_class;
++static struct lock_class_key emumousebtn_mutex_class;
++
+ static int emumousebtn_input_register(void)
{
-@@ -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;
+ int ret;
+@@ -111,6 +114,9 @@ static int emumousebtn_input_register(void)
+ if (!emumousebtn)
+ return -ENOMEM;
-- 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;
++ 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)
+ }
-- 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;
+ 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;
-- class_set_devdata(uverbs_dev->class_dev, uverbs_dev);
-+ dev_set_drvdata(uverbs_dev->dev, uverbs_dev);
+@@ -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 (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;
+ if (bay->mdev && which_bay == bay->mdev->ofdev.node) {
+- int timeout = 5000;
++ int timeout = 5000, index = hwif->index;
+
+ down(&bay->lock);
- spin_lock(&map_lock);
-@@ -782,10 +777,10 @@ static void ib_uverbs_add_one(struct ib_device *device)
- return;
++ bay->cd_port = hwif;
+ bay->cd_base = (void __iomem *) base;
+ bay->cd_irq = irq;
- err_class:
-- class_device_destroy(uverbs_class, uverbs_dev->dev->dev);
-+ device_destroy(uverbs_class, uverbs_dev->cdev->dev);
+@@ -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_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c
+index 7e10c3a..b92b959 100644
+--- a/drivers/macintosh/windfarm_lm75_sensor.c
++++ b/drivers/macintosh/windfarm_lm75_sensor.c
+@@ -127,6 +127,12 @@ static struct wf_lm75_sensor *wf_lm75_create(struct i2c_adapter *adapter,
+ */
+ if (!strcmp(loc, "Hard drive") || !strcmp(loc, "DRIVE BAY"))
+ lm->sens.name = "hd-temp";
++ else if (!strcmp(loc, "Incoming Air Temp"))
++ lm->sens.name = "incoming-air-temp";
++ else if (!strcmp(loc, "ODD Temp"))
++ lm->sens.name = "optical-drive-temp";
++ else if (!strcmp(loc, "HD Temp"))
++ lm->sens.name = "hard-drive-temp";
+ else
+ goto fail;
- err_cdev:
-- cdev_del(uverbs_dev->dev);
-+ cdev_del(uverbs_dev->cdev);
- clear_bit(uverbs_dev->devnum, dev_map);
+diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c
+index 5f03aab..e207a90 100644
+--- a/drivers/macintosh/windfarm_max6690_sensor.c
++++ b/drivers/macintosh/windfarm_max6690_sensor.c
+@@ -77,18 +77,28 @@ static struct wf_sensor_ops wf_max6690_ops = {
+ .owner = THIS_MODULE,
+ };
- err:
-@@ -802,9 +797,9 @@ static void ib_uverbs_remove_one(struct ib_device *device)
- if (!uverbs_dev)
- return;
+-static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr)
++static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr,
++ const char *loc)
+ {
+ struct wf_6690_sensor *max;
+- char *name = "backside-temp";
++ char *name;
-- 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);
+ max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL);
+ if (max == NULL) {
+ printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor %s: "
+- "no memory\n", name);
++ "no memory\n", loc);
+ return;
+ }
- 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);
++ if (!strcmp(loc, "BACKSIDE"))
++ name = "backside-temp";
++ else if (!strcmp(loc, "NB Ambient"))
++ name = "north-bridge-temp";
++ else if (!strcmp(loc, "GPU Ambient"))
++ name = "gpu-temp";
++ else
++ goto fail;
++
+ max->sens.ops = &wf_max6690_ops;
+ max->sens.name = name;
+ max->i2c.addr = addr >> 1;
+@@ -138,9 +148,7 @@ static int wf_max6690_attach(struct i2c_adapter *adapter)
+ if (loc == NULL || addr == 0)
+ continue;
+ printk("found max6690, loc=%s addr=0x%02x\n", loc, addr);
+- if (strcmp(loc, "BACKSIDE"))
+- continue;
+- wf_max6690_create(adapter, addr);
++ wf_max6690_create(adapter, addr, loc);
+ }
-@@ -628,6 +630,13 @@ struct ib_cq *ib_create_cq(struct ib_device *device,
- }
- EXPORT_SYMBOL(ib_create_cq);
+ return 0;
+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,
+ },
+ };
-+int ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period)
+@@ -711,3 +711,4 @@ module_exit(wf_pm112_exit);
+ MODULE_AUTHOR("Paul Mackerras <paulus at samba.org>");
+ MODULE_DESCRIPTION("Thermal control for PowerMac11,2");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:windfarm");
+diff --git a/drivers/macintosh/windfarm_pm121.c b/drivers/macintosh/windfarm_pm121.c
+new file mode 100644
+index 0000000..66ec4fb
+--- /dev/null
++++ b/drivers/macintosh/windfarm_pm121.c
+@@ -0,0 +1,1040 @@
++/*
++ * Windfarm PowerMac thermal control. iMac G5 iSight
++ *
++ * (c) Copyright 2007 Ãtienne Bersac <bersace at gmail.com>
++ *
++ * Bits & pieces from windfarm_pm81.c by (c) Copyright 2005 Benjamin
++ * Herrenschmidt, IBM Corp. <benh at kernel.crashing.org>
++ *
++ * Released under the term of the GNU GPL v2.
++ *
++ *
++ *
++ * PowerMac12,1
++ * ============
++ *
++ *
++ * The algorithm used is the PID control algorithm, used the same way
++ * the published Darwin code does, using the same values that are
++ * present in the Darwin 8.10 snapshot property lists (note however
++ * that none of the code has been re-used, it's a complete
++ * re-implementation
++ *
++ * There is two models using PowerMac12,1. Model 2 is iMac G5 iSight
++ * 17" while Model 3 is iMac G5 20". They do have both the same
++ * controls with a tiny difference. The control-ids of hard-drive-fan
++ * and cpu-fan is swapped.
++ *
++ *
++ * Target Correction :
++ *
++ * controls have a target correction calculated as :
++ *
++ * new_min = ((((average_power * slope) >> 16) + offset) >> 16) + min_value
++ * new_value = max(new_value, max(new_min, 0))
++ *
++ * OD Fan control correction.
++ *
++ * # model_id: 2
++ * offset : -19563152
++ * slope : 1956315
++ *
++ * # model_id: 3
++ * offset : -15650652
++ * slope : 1565065
++ *
++ * HD Fan control correction.
++ *
++ * # model_id: 2
++ * offset : -15650652
++ * slope : 1565065
++ *
++ * # model_id: 3
++ * offset : -19563152
++ * slope : 1956315
++ *
++ * CPU Fan control correction.
++ *
++ * # model_id: 2
++ * offset : -25431900
++ * slope : 2543190
++ *
++ * # model_id: 3
++ * offset : -15650652
++ * slope : 1565065
++ *
++ *
++ * Target rubber-banding :
++ *
++ * Some controls have a target correction which depends on another
++ * control value. The correction is computed in the following way :
++ *
++ * new_min = ref_value * slope + offset
++ *
++ * ref_value is the value of the reference control. If new_min is
++ * greater than 0, then we correct the target value using :
++ *
++ * new_target = max (new_target, new_min >> 16)
++ *
++ *
++ * # model_id : 2
++ * control : cpu-fan
++ * ref : optical-drive-fan
++ * offset : -15650652
++ * slope : 1565065
++ *
++ * # model_id : 3
++ * control : optical-drive-fan
++ * ref : hard-drive-fan
++ * offset : -32768000
++ * slope : 65536
++ *
++ *
++ * In order to have the moste efficient correction with those
++ * dependencies, we must trigger HD loop before OD loop before CPU
++ * loop.
++ *
++ *
++ * The various control loops found in Darwin config file are:
++ *
++ * HD Fan control loop.
++ *
++ * # model_id: 2
++ * control : hard-drive-fan
++ * sensor : hard-drive-temp
++ * PID params : G_d = 0x00000000
++ * G_p = 0x002D70A3
++ * G_r = 0x00019999
++ * History = 2 entries
++ * Input target = 0x370000
++ * Interval = 5s
++ *
++ * # model_id: 3
++ * control : hard-drive-fan
++ * sensor : hard-drive-temp
++ * PID params : G_d = 0x00000000
++ * G_p = 0x002170A3
++ * G_r = 0x00019999
++ * History = 2 entries
++ * Input target = 0x370000
++ * Interval = 5s
++ *
++ * OD Fan control loop.
++ *
++ * # model_id: 2
++ * control : optical-drive-fan
++ * sensor : optical-drive-temp
++ * PID params : G_d = 0x00000000
++ * G_p = 0x001FAE14
++ * G_r = 0x00019999
++ * History = 2 entries
++ * Input target = 0x320000
++ * Interval = 5s
++ *
++ * # model_id: 3
++ * control : optical-drive-fan
++ * sensor : optical-drive-temp
++ * PID params : G_d = 0x00000000
++ * G_p = 0x001FAE14
++ * G_r = 0x00019999
++ * History = 2 entries
++ * Input target = 0x320000
++ * Interval = 5s
++ *
++ * GPU Fan control loop.
++ *
++ * # model_id: 2
++ * control : hard-drive-fan
++ * sensor : gpu-temp
++ * PID params : G_d = 0x00000000
++ * G_p = 0x002A6666
++ * G_r = 0x00019999
++ * History = 2 entries
++ * Input target = 0x5A0000
++ * Interval = 5s
++ *
++ * # model_id: 3
++ * control : cpu-fan
++ * sensor : gpu-temp
++ * PID params : G_d = 0x00000000
++ * G_p = 0x0010CCCC
++ * G_r = 0x00019999
++ * History = 2 entries
++ * Input target = 0x500000
++ * Interval = 5s
++ *
++ * KODIAK (aka northbridge) Fan control loop.
++ *
++ * # model_id: 2
++ * control : optical-drive-fan
++ * sensor : north-bridge-temp
++ * PID params : G_d = 0x00000000
++ * G_p = 0x003BD70A
++ * G_r = 0x00019999
++ * History = 2 entries
++ * Input target = 0x550000
++ * Interval = 5s
++ *
++ * # model_id: 3
++ * control : hard-drive-fan
++ * sensor : north-bridge-temp
++ * PID params : G_d = 0x00000000
++ * G_p = 0x0030F5C2
++ * G_r = 0x00019999
++ * History = 2 entries
++ * Input target = 0x550000
++ * Interval = 5s
++ *
++ * CPU Fan control loop.
++ *
++ * control : cpu-fan
++ * sensors : cpu-temp, cpu-power
++ * PID params : from SDB partition
++ *
++ *
++ * CPU Slew control loop.
++ *
++ * control : cpufreq-clamp
++ * sensor : cpu-temp
++ *
++ */
++
++#undef DEBUG
++
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/spinlock.h>
++#include <linux/wait.h>
++#include <linux/kmod.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <asm/prom.h>
++#include <asm/machdep.h>
++#include <asm/io.h>
++#include <asm/system.h>
++#include <asm/sections.h>
++#include <asm/smu.h>
++
++#include "windfarm.h"
++#include "windfarm_pid.h"
++
++#define VERSION "0.3"
++
++static int pm121_mach_model; /* machine model id */
++
++/* Controls & sensors */
++static struct wf_sensor *sensor_cpu_power;
++static struct wf_sensor *sensor_cpu_temp;
++static struct wf_sensor *sensor_cpu_voltage;
++static struct wf_sensor *sensor_cpu_current;
++static struct wf_sensor *sensor_gpu_temp;
++static struct wf_sensor *sensor_north_bridge_temp;
++static struct wf_sensor *sensor_hard_drive_temp;
++static struct wf_sensor *sensor_optical_drive_temp;
++static struct wf_sensor *sensor_incoming_air_temp; /* unused ! */
++
++enum {
++ FAN_CPU,
++ FAN_HD,
++ FAN_OD,
++ CPUFREQ,
++ N_CONTROLS
++};
++static struct wf_control *controls[N_CONTROLS] = {};
++
++/* Set to kick the control loop into life */
++static int pm121_all_controls_ok, pm121_all_sensors_ok, pm121_started;
++
++enum {
++ FAILURE_FAN = 1 << 0,
++ FAILURE_SENSOR = 1 << 1,
++ FAILURE_OVERTEMP = 1 << 2
++};
++
++/* All sys loops. Note the HD before the OD loop in order to have it
++ run before. */
++enum {
++ LOOP_GPU, /* control = hd or cpu, but luckily,
++ it doesn't matter */
++ LOOP_HD, /* control = hd */
++ LOOP_KODIAK, /* control = hd or od */
++ LOOP_OD, /* control = od */
++ N_LOOPS
++};
++
++static const char *loop_names[N_LOOPS] = {
++ "GPU",
++ "HD",
++ "KODIAK",
++ "OD",
++};
++
++#define PM121_NUM_CONFIGS 2
++
++static unsigned int pm121_failure_state;
++static int pm121_readjust, pm121_skipping;
++static s32 average_power;
++
++struct pm121_correction {
++ int offset;
++ int slope;
++};
++
++static struct pm121_correction corrections[N_CONTROLS][PM121_NUM_CONFIGS] = {
++ /* FAN_OD */
++ {
++ /* MODEL 2 */
++ { .offset = -19563152,
++ .slope = 1956315
++ },
++ /* MODEL 3 */
++ { .offset = -15650652,
++ .slope = 1565065
++ },
++ },
++ /* FAN_HD */
++ {
++ /* MODEL 2 */
++ { .offset = -15650652,
++ .slope = 1565065
++ },
++ /* MODEL 3 */
++ { .offset = -19563152,
++ .slope = 1956315
++ },
++ },
++ /* FAN_CPU */
++ {
++ /* MODEL 2 */
++ { .offset = -25431900,
++ .slope = 2543190
++ },
++ /* MODEL 3 */
++ { .offset = -15650652,
++ .slope = 1565065
++ },
++ },
++ /* CPUFREQ has no correction (and is not implemented at all) */
++};
++
++struct pm121_connection {
++ unsigned int control_id;
++ unsigned int ref_id;
++ struct pm121_correction correction;
++};
++
++static struct pm121_connection pm121_connections[] = {
++ /* MODEL 2 */
++ { .control_id = FAN_CPU,
++ .ref_id = FAN_OD,
++ { .offset = -32768000,
++ .slope = 65536
++ }
++ },
++ /* MODEL 3 */
++ { .control_id = FAN_OD,
++ .ref_id = FAN_HD,
++ { .offset = -32768000,
++ .slope = 65536
++ }
++ },
++};
++
++/* pointer to the current model connection */
++static struct pm121_connection *pm121_connection;
++
++/*
++ * ****** System Fans Control Loop ******
++ *
++ */
++
++/* Since each loop handles only one control and we want to avoid
++ * writing virtual control, we store the control correction with the
++ * loop params. Some data are not set, there are common to all loop
++ * and thus, hardcoded.
++ */
++struct pm121_sys_param {
++ /* purely informative since we use mach_model-2 as index */
++ int model_id;
++ struct wf_sensor **sensor; /* use sensor_id instead ? */
++ s32 gp, itarget;
++ unsigned int control_id;
++};
++
++static struct pm121_sys_param
++pm121_sys_all_params[N_LOOPS][PM121_NUM_CONFIGS] = {
++ /* GPU Fan control loop */
++ {
++ { .model_id = 2,
++ .sensor = &sensor_gpu_temp,
++ .gp = 0x002A6666,
++ .itarget = 0x5A0000,
++ .control_id = FAN_HD,
++ },
++ { .model_id = 3,
++ .sensor = &sensor_gpu_temp,
++ .gp = 0x0010CCCC,
++ .itarget = 0x500000,
++ .control_id = FAN_CPU,
++ },
++ },
++ /* HD Fan control loop */
++ {
++ { .model_id = 2,
++ .sensor = &sensor_hard_drive_temp,
++ .gp = 0x002D70A3,
++ .itarget = 0x370000,
++ .control_id = FAN_HD,
++ },
++ { .model_id = 3,
++ .sensor = &sensor_hard_drive_temp,
++ .gp = 0x002170A3,
++ .itarget = 0x370000,
++ .control_id = FAN_HD,
++ },
++ },
++ /* KODIAK Fan control loop */
++ {
++ { .model_id = 2,
++ .sensor = &sensor_north_bridge_temp,
++ .gp = 0x003BD70A,
++ .itarget = 0x550000,
++ .control_id = FAN_OD,
++ },
++ { .model_id = 3,
++ .sensor = &sensor_north_bridge_temp,
++ .gp = 0x0030F5C2,
++ .itarget = 0x550000,
++ .control_id = FAN_HD,
++ },
++ },
++ /* OD Fan control loop */
++ {
++ { .model_id = 2,
++ .sensor = &sensor_optical_drive_temp,
++ .gp = 0x001FAE14,
++ .itarget = 0x320000,
++ .control_id = FAN_OD,
++ },
++ { .model_id = 3,
++ .sensor = &sensor_optical_drive_temp,
++ .gp = 0x001FAE14,
++ .itarget = 0x320000,
++ .control_id = FAN_OD,
++ },
++ },
++};
++
++/* the hardcoded values */
++#define PM121_SYS_GD 0x00000000
++#define PM121_SYS_GR 0x00019999
++#define PM121_SYS_HISTORY_SIZE 2
++#define PM121_SYS_INTERVAL 5
++
++/* State data used by the system fans control loop
++ */
++struct pm121_sys_state {
++ int ticks;
++ s32 setpoint;
++ struct wf_pid_state pid;
++};
++
++struct pm121_sys_state *pm121_sys_state[N_LOOPS] = {};
++
++/*
++ * ****** CPU Fans Control Loop ******
++ *
++ */
++
++#define PM121_CPU_INTERVAL 1
++
++/* State data used by the cpu fans control loop
++ */
++struct pm121_cpu_state {
++ int ticks;
++ s32 setpoint;
++ struct wf_cpu_pid_state pid;
++};
++
++static struct pm121_cpu_state *pm121_cpu_state;
++
++
++
++/*
++ * ***** Implementation *****
++ *
++ */
++
++/* correction the value using the output-low-bound correction algo */
++static s32 pm121_correct(s32 new_setpoint,
++ unsigned int control_id,
++ s32 min)
+{
-+ return cq->device->modify_cq ?
-+ cq->device->modify_cq(cq, cq_count, cq_period) : -ENOSYS;
++ s32 new_min;
++ struct pm121_correction *correction;
++ correction = &corrections[control_id][pm121_mach_model - 2];
++
++ new_min = (average_power * correction->slope) >> 16;
++ new_min += correction->offset;
++ new_min = (new_min >> 16) + min;
++
++ return max(new_setpoint, max(new_min, 0));
+}
-+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);
++static s32 pm121_connect(unsigned int control_id, s32 setpoint)
++{
++ s32 new_min, value, new_setpoint;
+
- 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;
++ if (pm121_connection->control_id == control_id) {
++ controls[control_id]->ops->get_value(controls[control_id],
++ &value);
++ new_min = value * pm121_connection->correction.slope;
++ new_min += pm121_connection->correction.offset;
++ if (new_min > 0) {
++ new_setpoint = max(setpoint, (new_min >> 16));
++ if (new_setpoint != setpoint) {
++ pr_debug("pm121: %s depending on %s, "
++ "corrected from %d to %d RPM\n",
++ controls[control_id]->name,
++ controls[pm121_connection->ref_id]->name,
++ (int) setpoint, (int) new_setpoint);
++ }
++ } else
++ new_setpoint = setpoint;
++ }
++ /* no connection */
++ else
++ new_setpoint = setpoint;
++
++ return new_setpoint;
++}
++
++/* FAN LOOPS */
++static void pm121_create_sys_fans(int loop_id)
++{
++ struct pm121_sys_param *param = NULL;
++ struct wf_pid_param pid_param;
++ struct wf_control *control = NULL;
++ int i;
++
++ /* First, locate the params for this model */
++ for (i = 0; i < PM121_NUM_CONFIGS; i++) {
++ if (pm121_sys_all_params[loop_id][i].model_id == pm121_mach_model) {
++ param = &(pm121_sys_all_params[loop_id][i]);
++ break;
++ }
++ }
++
++ /* No params found, put fans to max */
++ if (param == NULL) {
++ printk(KERN_WARNING "pm121: %s fan config not found "
++ " for this machine model\n",
++ loop_names[loop_id]);
++ goto fail;
++ }
++
++ control = controls[param->control_id];
++
++ /* Alloc & initialize state */
++ pm121_sys_state[loop_id] = kmalloc(sizeof(struct pm121_sys_state),
++ GFP_KERNEL);
++ if (pm121_sys_state[loop_id] == NULL) {
++ printk(KERN_WARNING "pm121: Memory allocation error\n");
++ goto fail;
++ }
++ pm121_sys_state[loop_id]->ticks = 1;
++
++ /* Fill PID params */
++ pid_param.gd = PM121_SYS_GD;
++ pid_param.gp = param->gp;
++ pid_param.gr = PM121_SYS_GR;
++ pid_param.interval = PM121_SYS_INTERVAL;
++ pid_param.history_len = PM121_SYS_HISTORY_SIZE;
++ pid_param.itarget = param->itarget;
++ pid_param.min = control->ops->get_min(control);
++ pid_param.max = control->ops->get_max(control);
++
++ wf_pid_init(&pm121_sys_state[loop_id]->pid, &pid_param);
++
++ pr_debug("pm121: %s Fan control loop initialized.\n"
++ " itarged=%d.%03d, min=%d RPM, max=%d RPM\n",
++ loop_names[loop_id], FIX32TOPRINT(pid_param.itarget),
++ pid_param.min, pid_param.max);
++ return;
++
++ fail:
++ /* note that this is not optimal since another loop may still
++ control the same control */
++ printk(KERN_WARNING "pm121: failed to set up %s loop "
++ "setting \"%s\" to max speed.\n",
++ loop_names[loop_id], control->name);
++
++ if (control)
++ wf_control_set_max(control);
++}
++
++static void pm121_sys_fans_tick(int loop_id)
++{
++ struct pm121_sys_param *param;
++ struct pm121_sys_state *st;
++ struct wf_sensor *sensor;
++ struct wf_control *control;
++ s32 temp, new_setpoint;
++ int rc;
++
++ param = &(pm121_sys_all_params[loop_id][pm121_mach_model-2]);
++ st = pm121_sys_state[loop_id];
++ sensor = *(param->sensor);
++ control = controls[param->control_id];
++
++ if (--st->ticks != 0) {
++ if (pm121_readjust)
++ goto readjust;
++ return;
++ }
++ st->ticks = PM121_SYS_INTERVAL;
++
++ rc = sensor->ops->get_value(sensor, &temp);
++ if (rc) {
++ printk(KERN_WARNING "windfarm: %s sensor error %d\n",
++ sensor->name, rc);
++ pm121_failure_state |= FAILURE_SENSOR;
++ return;
++ }
++
++ pr_debug("pm121: %s Fan tick ! %s: %d.%03d\n",
++ loop_names[loop_id], sensor->name,
++ FIX32TOPRINT(temp));
++
++ new_setpoint = wf_pid_run(&st->pid, temp);
++
++ /* correction */
++ new_setpoint = pm121_correct(new_setpoint,
++ param->control_id,
++ st->pid.param.min);
++ /* linked corretion */
++ new_setpoint = pm121_connect(param->control_id, new_setpoint);
++
++ if (new_setpoint == st->setpoint)
++ return;
++ st->setpoint = new_setpoint;
++ pr_debug("pm121: %s corrected setpoint: %d RPM\n",
++ control->name, (int)new_setpoint);
++ readjust:
++ if (control && pm121_failure_state == 0) {
++ rc = control->ops->set_value(control, st->setpoint);
++ if (rc) {
++ printk(KERN_WARNING "windfarm: %s fan error %d\n",
++ control->name, rc);
++ pm121_failure_state |= FAILURE_FAN;
++ }
++ }
++}
++
++
++/* CPU LOOP */
++static void pm121_create_cpu_fans(void)
++{
++ struct wf_cpu_pid_param pid_param;
++ const struct smu_sdbp_header *hdr;
++ struct smu_sdbp_cpupiddata *piddata;
++ struct smu_sdbp_fvt *fvt;
++ struct wf_control *fan_cpu;
++ s32 tmax, tdelta, maxpow, powadj;
++
++ fan_cpu = controls[FAN_CPU];
++
++ /* First, locate the PID params in SMU SBD */
++ hdr = smu_get_sdb_partition(SMU_SDB_CPUPIDDATA_ID, NULL);
++ if (hdr == 0) {
++ printk(KERN_WARNING "pm121: CPU PID fan config not found.\n");
++ goto fail;
++ }
++ piddata = (struct smu_sdbp_cpupiddata *)&hdr[1];
++
++ /* Get the FVT params for operating point 0 (the only supported one
++ * for now) in order to get tmax
++ */
++ hdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL);
++ if (hdr) {
++ fvt = (struct smu_sdbp_fvt *)&hdr[1];
++ tmax = ((s32)fvt->maxtemp) << 16;
++ } else
++ tmax = 0x5e0000; /* 94 degree default */
++
++ /* Alloc & initialize state */
++ pm121_cpu_state = kmalloc(sizeof(struct pm121_cpu_state),
++ GFP_KERNEL);
++ if (pm121_cpu_state == NULL)
++ goto fail;
++ pm121_cpu_state->ticks = 1;
++
++ /* Fill PID params */
++ pid_param.interval = PM121_CPU_INTERVAL;
++ pid_param.history_len = piddata->history_len;
++ if (pid_param.history_len > WF_CPU_PID_MAX_HISTORY) {
++ printk(KERN_WARNING "pm121: History size overflow on "
++ "CPU control loop (%d)\n", piddata->history_len);
++ pid_param.history_len = WF_CPU_PID_MAX_HISTORY;
++ }
++ pid_param.gd = piddata->gd;
++ pid_param.gp = piddata->gp;
++ pid_param.gr = piddata->gr / pid_param.history_len;
++
++ tdelta = ((s32)piddata->target_temp_delta) << 16;
++ maxpow = ((s32)piddata->max_power) << 16;
++ powadj = ((s32)piddata->power_adj) << 16;
++
++ pid_param.tmax = tmax;
++ pid_param.ttarget = tmax - tdelta;
++ pid_param.pmaxadj = maxpow - powadj;
++
++ pid_param.min = fan_cpu->ops->get_min(fan_cpu);
++ pid_param.max = fan_cpu->ops->get_max(fan_cpu);
++
++ wf_cpu_pid_init(&pm121_cpu_state->pid, &pid_param);
++
++ pr_debug("pm121: CPU Fan control initialized.\n");
++ pr_debug(" ttarged=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM,\n",
++ FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax),
++ pid_param.min, pid_param.max);
++
++ return;
++
++ fail:
++ printk(KERN_WARNING "pm121: CPU fan config not found, max fan speed\n");
++
++ if (controls[CPUFREQ])
++ wf_control_set_max(controls[CPUFREQ]);
++ if (fan_cpu)
++ wf_control_set_max(fan_cpu);
++}
++
++
++static void pm121_cpu_fans_tick(struct pm121_cpu_state *st)
++{
++ s32 new_setpoint, temp, power;
++ struct wf_control *fan_cpu = NULL;
++ int rc;
++
++ if (--st->ticks != 0) {
++ if (pm121_readjust)
++ goto readjust;
++ return;
++ }
++ st->ticks = PM121_CPU_INTERVAL;
++
++ fan_cpu = controls[FAN_CPU];
++
++ rc = sensor_cpu_temp->ops->get_value(sensor_cpu_temp, &temp);
++ if (rc) {
++ printk(KERN_WARNING "pm121: CPU temp sensor error %d\n",
++ rc);
++ pm121_failure_state |= FAILURE_SENSOR;
++ return;
++ }
++
++ rc = sensor_cpu_power->ops->get_value(sensor_cpu_power, &power);
++ if (rc) {
++ printk(KERN_WARNING "pm121: CPU power sensor error %d\n",
++ rc);
++ pm121_failure_state |= FAILURE_SENSOR;
++ return;
++ }
++
++ pr_debug("pm121: CPU Fans tick ! CPU temp: %d.%03d°C, power: %d.%03d\n",
++ FIX32TOPRINT(temp), FIX32TOPRINT(power));
++
++ if (temp > st->pid.param.tmax)
++ pm121_failure_state |= FAILURE_OVERTEMP;
++
++ new_setpoint = wf_cpu_pid_run(&st->pid, power, temp);
++
++ /* correction */
++ new_setpoint = pm121_correct(new_setpoint,
++ FAN_CPU,
++ st->pid.param.min);
++
++ /* connected correction */
++ new_setpoint = pm121_connect(FAN_CPU, new_setpoint);
++
++ if (st->setpoint == new_setpoint)
++ return;
++ st->setpoint = new_setpoint;
++ pr_debug("pm121: CPU corrected setpoint: %d RPM\n", (int)new_setpoint);
++
++ readjust:
++ if (fan_cpu && pm121_failure_state == 0) {
++ rc = fan_cpu->ops->set_value(fan_cpu, st->setpoint);
++ if (rc) {
++ printk(KERN_WARNING "pm121: %s fan error %d\n",
++ fan_cpu->name, rc);
++ pm121_failure_state |= FAILURE_FAN;
++ }
++ }
++}
++
++/*
++ * ****** Common ******
++ *
++ */
++
++static void pm121_tick(void)
++{
++ unsigned int last_failure = pm121_failure_state;
++ unsigned int new_failure;
++ s32 total_power;
++ int i;
++
++ if (!pm121_started) {
++ pr_debug("pm121: creating control loops !\n");
++ for (i = 0; i < N_LOOPS; i++)
++ pm121_create_sys_fans(i);
++
++ pm121_create_cpu_fans();
++ pm121_started = 1;
++ }
++
++ /* skipping ticks */
++ if (pm121_skipping && --pm121_skipping)
++ return;
++
++ /* compute average power */
++ total_power = 0;
++ for (i = 0; i < pm121_cpu_state->pid.param.history_len; i++)
++ total_power += pm121_cpu_state->pid.powers[i];
++
++ average_power = total_power / pm121_cpu_state->pid.param.history_len;
++
++
++ pm121_failure_state = 0;
++ for (i = 0 ; i < N_LOOPS; i++) {
++ if (pm121_sys_state[i])
++ pm121_sys_fans_tick(i);
++ }
++
++ if (pm121_cpu_state)
++ pm121_cpu_fans_tick(pm121_cpu_state);
++
++ pm121_readjust = 0;
++ new_failure = pm121_failure_state & ~last_failure;
++
++ /* If entering failure mode, clamp cpufreq and ramp all
++ * fans to full speed.
++ */
++ if (pm121_failure_state && !last_failure) {
++ for (i = 0; i < N_CONTROLS; i++) {
++ if (controls[i])
++ wf_control_set_max(controls[i]);
++ }
++ }
++
++ /* If leaving failure mode, unclamp cpufreq and readjust
++ * all fans on next iteration
++ */
++ if (!pm121_failure_state && last_failure) {
++ if (controls[CPUFREQ])
++ wf_control_set_min(controls[CPUFREQ]);
++ pm121_readjust = 1;
++ }
++
++ /* Overtemp condition detected, notify and start skipping a couple
++ * ticks to let the temperature go down
++ */
++ if (new_failure & FAILURE_OVERTEMP) {
++ wf_set_overtemp();
++ pm121_skipping = 2;
++ }
++
++ /* We only clear the overtemp condition if overtemp is cleared
++ * _and_ no other failure is present. Since a sensor error will
++ * clear the overtemp condition (can't measure temperature) at
++ * the control loop levels, but we don't want to keep it clear
++ * here in this case
++ */
++ if (new_failure == 0 && last_failure & FAILURE_OVERTEMP)
++ wf_clear_overtemp();
++}
++
++
++static struct wf_control* pm121_register_control(struct wf_control *ct,
++ const char *match,
++ unsigned int id)
++{
++ if (controls[id] == NULL && !strcmp(ct->name, match)) {
++ if (wf_get_control(ct) == 0)
++ controls[id] = ct;
++ }
++ return controls[id];
++}
++
++static void pm121_new_control(struct wf_control *ct)
++{
++ int all = 1;
++
++ if (pm121_all_controls_ok)
++ return;
++
++ all = pm121_register_control(ct, "optical-drive-fan", FAN_OD) && all;
++ all = pm121_register_control(ct, "hard-drive-fan", FAN_HD) && all;
++ all = pm121_register_control(ct, "cpu-fan", FAN_CPU) && all;
++ all = pm121_register_control(ct, "cpufreq-clamp", CPUFREQ) && all;
++
++ if (all)
++ pm121_all_controls_ok = 1;
++}
++
++
++
++
++static struct wf_sensor* pm121_register_sensor(struct wf_sensor *sensor,
++ const char *match,
++ struct wf_sensor **var)
++{
++ if (*var == NULL && !strcmp(sensor->name, match)) {
++ if (wf_get_sensor(sensor) == 0)
++ *var = sensor;
++ }
++ return *var;
++}
++
++static void pm121_new_sensor(struct wf_sensor *sr)
++{
++ int all = 1;
++
++ if (pm121_all_sensors_ok)
++ return;
++
++ all = pm121_register_sensor(sr, "cpu-temp",
++ &sensor_cpu_temp) && all;
++ all = pm121_register_sensor(sr, "cpu-current",
++ &sensor_cpu_current) && all;
++ all = pm121_register_sensor(sr, "cpu-voltage",
++ &sensor_cpu_voltage) && all;
++ all = pm121_register_sensor(sr, "cpu-power",
++ &sensor_cpu_power) && all;
++ all = pm121_register_sensor(sr, "hard-drive-temp",
++ &sensor_hard_drive_temp) && all;
++ all = pm121_register_sensor(sr, "optical-drive-temp",
++ &sensor_optical_drive_temp) && all;
++ all = pm121_register_sensor(sr, "incoming-air-temp",
++ &sensor_incoming_air_temp) && all;
++ all = pm121_register_sensor(sr, "north-bridge-temp",
++ &sensor_north_bridge_temp) && all;
++ all = pm121_register_sensor(sr, "gpu-temp",
++ &sensor_gpu_temp) && all;
++
++ if (all)
++ pm121_all_sensors_ok = 1;
++}
++
++
++
++static int pm121_notify(struct notifier_block *self,
++ unsigned long event, void *data)
++{
++ switch (event) {
++ case WF_EVENT_NEW_CONTROL:
++ pr_debug("pm121: new control %s detected\n",
++ ((struct wf_control *)data)->name);
++ pm121_new_control(data);
++ break;
++ case WF_EVENT_NEW_SENSOR:
++ pr_debug("pm121: new sensor %s detected\n",
++ ((struct wf_sensor *)data)->name);
++ pm121_new_sensor(data);
++ break;
++ case WF_EVENT_TICK:
++ if (pm121_all_controls_ok && pm121_all_sensors_ok)
++ pm121_tick();
++ break;
++ }
++
++ return 0;
++}
++
++static struct notifier_block pm121_events = {
++ .notifier_call = pm121_notify,
++};
++
++static int pm121_init_pm(void)
++{
++ const struct smu_sdbp_header *hdr;
++
++ hdr = smu_get_sdb_partition(SMU_SDB_SENSORTREE_ID, NULL);
++ if (hdr != 0) {
++ struct smu_sdbp_sensortree *st =
++ (struct smu_sdbp_sensortree *)&hdr[1];
++ pm121_mach_model = st->model_id;
++ }
++
++ pm121_connection = &pm121_connections[pm121_mach_model - 2];
++
++ printk(KERN_INFO "pm121: Initializing for iMac G5 iSight model ID %d\n",
++ pm121_mach_model);
++
++ return 0;
++}
++
++
++static int pm121_probe(struct platform_device *ddev)
++{
++ wf_register_client(&pm121_events);
++
++ return 0;
++}
++
++static int __devexit pm121_remove(struct platform_device *ddev)
++{
++ wf_unregister_client(&pm121_events);
++ return 0;
++}
++
++static struct platform_driver pm121_driver = {
++ .probe = pm121_probe,
++ .remove = __devexit_p(pm121_remove),
++ .driver = {
++ .name = "windfarm",
++ .bus = &platform_bus_type,
++ },
++};
++
++
++static int __init pm121_init(void)
++{
++ int rc = -ENODEV;
++
++ if (machine_is_compatible("PowerMac12,1"))
++ rc = pm121_init_pm();
++
++ if (rc == 0) {
++ request_module("windfarm_smu_controls");
++ request_module("windfarm_smu_sensors");
++ request_module("windfarm_smu_sat");
++ request_module("windfarm_lm75_sensor");
++ request_module("windfarm_max6690_sensor");
++ request_module("windfarm_cpufreq_clamp");
++ platform_driver_register(&pm121_driver);
++ }
++
++ return rc;
++}
++
++static void __exit pm121_exit(void)
++{
++
++ platform_driver_unregister(&pm121_driver);
++}
++
++
++module_init(pm121_init);
++module_exit(pm121_exit);
++
++MODULE_AUTHOR("Ãtienne Bersac <bersace at gmail.com>");
++MODULE_DESCRIPTION("Thermal control logic for iMac G5 (iSight)");
++MODULE_LICENSE("GPL");
++
+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,
+ },
+ };
- /* 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);
+@@ -810,4 +810,4 @@ module_exit(wf_smu_exit);
+ MODULE_AUTHOR("Benjamin Herrenschmidt <benh at kernel.crashing.org>");
+ MODULE_DESCRIPTION("Thermal control logic for iMac G5");
+ MODULE_LICENSE("GPL");
+-
++MODULE_ALIAS("platform:windfarm");
+diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c
+index 26eee69..764c525 100644
+--- a/drivers/macintosh/windfarm_pm91.c
++++ b/drivers/macintosh/windfarm_pm91.c
+@@ -702,7 +702,7 @@ static struct platform_driver wf_smu_driver = {
+ .remove = __devexit_p(wf_smu_remove),
+ .driver = {
+ .name = "windfarm",
+- .bus = &platform_bus_type,
++ .owner = THIS_MODULE,
+ },
+ };
- elem->skb = NULL;
-@@ -179,13 +179,13 @@ static int c2_rx_ring_alloc(struct c2_ring *rx_ring, void *vaddr,
- rx_desc->status = 0;
+@@ -742,3 +742,4 @@ MODULE_AUTHOR("Benjamin Herrenschmidt <benh at kernel.crashing.org>");
+ MODULE_DESCRIPTION("Thermal control logic for PowerMac9,1");
+ MODULE_LICENSE("GPL");
- /* 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);
++MODULE_ALIAS("platform:windfarm");
+diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c
+index 58c2590..961fa0e 100644
+--- a/drivers/macintosh/windfarm_smu_controls.c
++++ b/drivers/macintosh/windfarm_smu_controls.c
+@@ -218,6 +218,10 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node,
+ fct->ctrl.name = "cpu-fan";
+ else if (!strcmp(l, "Hard Drive") || !strcmp(l, "Hard drive"))
+ fct->ctrl.name = "drive-bay-fan";
++ else if (!strcmp(l, "HDD Fan")) /* seen on iMac G5 iSight */
++ fct->ctrl.name = "hard-drive-fan";
++ else if (!strcmp(l, "ODD Fan")) /* same */
++ fct->ctrl.name = "optical-drive-fan";
- 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;
+ /* Unrecognized fan, bail out */
+ if (fct->ctrl.name == NULL)
+diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
+index f449d77..797918d 100644
+--- a/drivers/macintosh/windfarm_smu_sat.c
++++ b/drivers/macintosh/windfarm_smu_sat.c
+@@ -13,7 +13,7 @@
+ #include <linux/init.h>
+ #include <linux/wait.h>
+ #include <linux/i2c.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <asm/prom.h>
+ #include <asm/smu.h>
+ #include <asm/pmac_low_i2c.h>
+diff --git a/drivers/mca/mca-legacy.c b/drivers/mca/mca-legacy.c
+index 0c7bfa7..494f0c2 100644
+--- a/drivers/mca/mca-legacy.c
++++ b/drivers/mca/mca-legacy.c
+@@ -282,24 +282,6 @@ void mca_set_adapter_name(int slot, char* name)
+ EXPORT_SYMBOL(mca_set_adapter_name);
- __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);
+ /**
+- * mca_is_adapter_used - check if claimed by driver
+- * @slot: slot to check
+- *
+- * Returns 1 if the slot has been claimed by a driver
+- */
+-
+-int mca_is_adapter_used(int slot)
+-{
+- struct mca_device *mca_dev = mca_find_device_by_slot(slot);
+-
+- if(!mca_dev)
+- return 0;
+-
+- return mca_device_claimed(mca_dev);
+-}
+-EXPORT_SYMBOL(mca_is_adapter_used);
+-
+-/**
+ * mca_mark_as_used - claim an MCA device
+ * @slot: slot to claim
+ * FIXME: should we make this threadsafe
+diff --git a/drivers/mca/mca-proc.c b/drivers/mca/mca-proc.c
+index 33d5e08..81ea0d3 100644
+--- a/drivers/mca/mca-proc.c
++++ b/drivers/mca/mca-proc.c
+@@ -183,7 +183,7 @@ void __init mca_do_proc_init(void)
+ struct proc_dir_entry* node = NULL;
+ struct mca_device *mca_dev;
+
+- proc_mca = proc_mkdir("mca", &proc_root);
++ proc_mca = proc_mkdir("mca", NULL);
+ create_proc_read_entry("pos",0,proc_mca,get_mca_info,NULL);
+ create_proc_read_entry("machine",0,proc_mca,get_mca_machine_info,NULL);
- 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);
+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 @@
+ #
- 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);
- }
+ 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
-@@ -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));
+ quiet_cmd_unroll = UNROLL $@
+diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c
+index 6b91b9a..3ea5ad4 100644
+--- a/drivers/md/dm-emc.c
++++ b/drivers/md/dm-emc.c
+@@ -110,8 +110,6 @@ static struct request *get_failover_req(struct emc_handler *h,
+ memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+ rq->sense_len = 0;
+
+- memset(&rq->cmd, 0, BLK_MAX_CDB);
+-
+ rq->timeout = EMC_FAILOVER_TIMEOUT;
+ rq->cmd_type = REQ_TYPE_BLOCK_PC;
+ rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
+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 @@
- 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);
+ #include "dm.h"
+ #include "dm-snap.h"
+-#include "dm-io.h"
+-#include "kcopyd.h"
- 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);
- }
+ #include <linux/mm.h>
+ #include <linux/pagemap.h>
+ #include <linux/vmalloc.h>
+ #include <linux/slab.h>
++#include <linux/dm-io.h>
++#include <linux/dm-kcopyd.h>
-@@ -787,9 +790,12 @@ static int c2_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
- elem->maplen = maplen;
+ #define DM_MSG_PREFIX "snapshots"
+ #define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */
+@@ -131,7 +131,7 @@ struct pstore {
- /* 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);
+ static unsigned sectors_to_pages(unsigned sectors)
+ {
+- return sectors / (PAGE_SIZE >> 9);
++ return DIV_ROUND_UP(sectors, PAGE_SIZE >> 9);
+ }
- 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;
+ static int alloc_area(struct pstore *ps)
+@@ -159,7 +159,7 @@ static void free_area(struct pstore *ps)
+ }
- /* 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);
+ 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.
+ */
- 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,
- }
+-#include "dm-io.h"
++#include "dm.h"
- /* 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,
- }
+ #include <linux/bio.h>
+ #include <linux/mempool.h>
+ #include <linux/module.h>
+ #include <linux/sched.h>
+ #include <linux/slab.h>
++#include <linux/dm-io.h>
- /* 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,
+ struct dm_io_client {
+ mempool_t *pool;
+@@ -20,7 +21,7 @@ struct dm_io_client {
- /* 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);
+ /* 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);
- /* Request an interrupt line for the driver */
-@@ -1090,7 +1096,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
- }
+ if (atomic_dec_and_test(&io->count)) {
+ if (io->sleeper)
+ wake_up_process(io->sleeper);
- /* 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));
+ else {
+- unsigned long r = io->error;
++ unsigned long r = io->error_bits;
+ io_notify_fn fn = io->callback;
+ void *context = io->context;
- /* 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,
+@@ -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,
+ }
- /* Remap the PCI registers in adapter BAR0 to kernel VA space */
- c2dev->regs = ioremap_nocache(reg0_start, reg0_len);
-- if (c2dev->regs == 0UL) {
-+ if (!c2dev->regs) {
- printk(KERN_ERR PFX "Unable to remap BAR0\n");
- ret = -EIO;
- goto bail8;
-@@ -1139,7 +1145,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
- c2dev->pa = reg4_start + C2_PCI_REGS_OFFSET;
- c2dev->kva = ioremap_nocache(reg4_start + C2_PCI_REGS_OFFSET,
- kva_map_size);
-- if (c2dev->kva == 0UL) {
-+ if (!c2dev->kva) {
- printk(KERN_ERR PFX "Unable to remap BAR4\n");
- ret = -EIO;
- goto bail9;
-diff --git a/drivers/infiniband/hw/amso1100/c2.h b/drivers/infiniband/hw/amso1100/c2.h
-index fa58200..d12a24a 100644
---- a/drivers/infiniband/hw/amso1100/c2.h
-+++ b/drivers/infiniband/hw/amso1100/c2.h
-@@ -40,7 +40,6 @@
- #include <linux/pci.h>
- #include <linux/dma-mapping.h>
- #include <linux/idr.h>
--#include <asm/semaphore.h>
+ 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,
+ }
- #include "c2_provider.h"
- #include "c2_mq.h"
-@@ -346,7 +345,7 @@ struct c2_dev {
- // spinlock_t aeq_lock;
- // spinlock_t rnic_lock;
+ 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;
-- u16 *hint_count;
-+ __be16 *hint_count;
- dma_addr_t hint_count_dma;
- u16 hints_read;
+- if (num_regions > 1 && rw != WRITE) {
++ if (num_regions > 1 && (rw & RW_MASK) != WRITE) {
+ WARN_ON(1);
+ return -EIO;
+ }
-@@ -425,10 +424,10 @@ static inline void __raw_writeq(u64 val, void __iomem * addr)
- #endif
+- 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;
- #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)
+ if (error_bits)
+- *error_bits = io.error;
++ *error_bits = io.error_bits;
- #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))
+- return io.error ? -EIO : 0;
++ return io.error_bits ? -EIO : 0;
+ }
- static inline struct c2_dev *to_c2dev(struct ib_device *ibdev)
+ 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)
{
-@@ -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);
+ struct io *io;
- /* 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);
+- if (num_regions > 1 && rw != WRITE) {
++ if (num_regions > 1 && (rw & RW_MASK) != WRITE) {
+ WARN_ON(1);
+ fn(1, context);
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)
- }
+
+ 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)
}
--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)
+ /*
+- * 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)
{
- u16 mqsp;
+ int r;
+ struct dpages dp;
+diff --git a/drivers/md/dm-io.h b/drivers/md/dm-io.h
+deleted file mode 100644
+index f647e2c..0000000
+--- a/drivers/md/dm-io.h
++++ /dev/null
+@@ -1,79 +0,0 @@
+-/*
+- * Copyright (C) 2003 Sistina Software
+- *
+- * This file is released under the GPL.
+- */
+-
+-#ifndef _DM_IO_H
+-#define _DM_IO_H
+-
+-#include "dm.h"
+-
+-struct io_region {
+- struct block_device *bdev;
+- sector_t sector;
+- sector_t count; /* If this is zero the region is ignored. */
+-};
+-
+-struct page_list {
+- struct page_list *next;
+- struct page *page;
+-};
+-
+-typedef void (*io_notify_fn)(unsigned long error, void *context);
+-
+-enum dm_io_mem_type {
+- DM_IO_PAGE_LIST,/* Page list */
+- DM_IO_BVEC, /* Bio vector */
+- DM_IO_VMA, /* Virtual memory area */
+- DM_IO_KMEM, /* Kernel memory */
+-};
+-
+-struct dm_io_memory {
+- enum dm_io_mem_type type;
+-
+- union {
+- struct page_list *pl;
+- struct bio_vec *bvec;
+- void *vma;
+- void *addr;
+- } ptr;
+-
+- unsigned offset;
+-};
+-
+-struct dm_io_notify {
+- io_notify_fn fn; /* Callback for asynchronous requests */
+- void *context; /* Passed to callback */
+-};
+-
+-/*
+- * IO request structure
+- */
+-struct dm_io_client;
+-struct dm_io_request {
+- int bi_rw; /* READ|WRITE - not READA */
+- struct dm_io_memory mem; /* Memory to use for io */
+- struct dm_io_notify notify; /* Synchronous if notify.fn is NULL */
+- struct dm_io_client *client; /* Client memory handler */
+-};
+-
+-/*
+- * For async io calls, users can alternatively use the dm_io() function below
+- * and dm_io_client_create() to create private mempools for the client.
+- *
+- * Create/destroy may block.
+- */
+-struct dm_io_client *dm_io_client_create(unsigned num_pages);
+-int dm_io_client_resize(unsigned num_pages, struct dm_io_client *client);
+-void dm_io_client_destroy(struct dm_io_client *client);
+-
+-/*
+- * IO interface using private per-client pools.
+- * Each bit in the optional 'sync_error_bits' bitset indicates whether an
+- * error occurred doing io to the corresponding region.
+- */
+-int dm_io(struct dm_io_request *io_req, unsigned num_regions,
+- struct io_region *region, unsigned long *sync_error_bits);
+-
+-#endif
+diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
+new file mode 100644
+index 0000000..996802b
+--- /dev/null
++++ b/drivers/md/dm-kcopyd.c
+@@ -0,0 +1,654 @@
++/*
++ * Copyright (C) 2002 Sistina Software (UK) Limited.
++ * Copyright (C) 2006 Red Hat GmbH
++ *
++ * This file is released under the GPL.
++ *
++ * Kcopyd provides a simple interface for copying an area of one
++ * block-device to one or more other block-devices, with an asynchronous
++ * completion notification.
++ */
++
++#include <linux/types.h>
++#include <asm/atomic.h>
++#include <linux/blkdev.h>
++#include <linux/fs.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/mempool.h>
++#include <linux/module.h>
++#include <linux/pagemap.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/workqueue.h>
++#include <linux/mutex.h>
++#include <linux/dm-kcopyd.h>
++
++#include "dm.h"
++
++/*-----------------------------------------------------------------
++ * Each kcopyd client has its own little pool of preallocated
++ * pages for kcopyd io.
++ *---------------------------------------------------------------*/
++struct dm_kcopyd_client {
++ spinlock_t lock;
++ struct page_list *pages;
++ unsigned int nr_pages;
++ unsigned int nr_free_pages;
++
++ struct dm_io_client *io_client;
++
++ wait_queue_head_t destroyq;
++ atomic_t nr_jobs;
++
++ mempool_t *job_pool;
++
++ struct workqueue_struct *kcopyd_wq;
++ struct work_struct kcopyd_work;
++
++/*
++ * We maintain three lists of jobs:
++ *
++ * i) jobs waiting for pages
++ * ii) jobs that have pages, and are waiting for the io to be issued.
++ * iii) jobs that have completed.
++ *
++ * All three of these are protected by job_lock.
++ */
++ spinlock_t job_lock;
++ struct list_head complete_jobs;
++ struct list_head io_jobs;
++ struct list_head pages_jobs;
++};
++
++static void wake(struct dm_kcopyd_client *kc)
++{
++ queue_work(kc->kcopyd_wq, &kc->kcopyd_work);
++}
++
++static struct page_list *alloc_pl(void)
++{
++ struct page_list *pl;
++
++ pl = kmalloc(sizeof(*pl), GFP_KERNEL);
++ if (!pl)
++ return NULL;
++
++ pl->page = alloc_page(GFP_KERNEL);
++ if (!pl->page) {
++ kfree(pl);
++ return NULL;
++ }
++
++ return pl;
++}
++
++static void free_pl(struct page_list *pl)
++{
++ __free_page(pl->page);
++ kfree(pl);
++}
++
++static int kcopyd_get_pages(struct dm_kcopyd_client *kc,
++ unsigned int nr, struct page_list **pages)
++{
++ struct page_list *pl;
++
++ spin_lock(&kc->lock);
++ if (kc->nr_free_pages < nr) {
++ spin_unlock(&kc->lock);
++ return -ENOMEM;
++ }
++
++ kc->nr_free_pages -= nr;
++ for (*pages = pl = kc->pages; --nr; pl = pl->next)
++ ;
++
++ kc->pages = pl->next;
++ pl->next = NULL;
++
++ spin_unlock(&kc->lock);
++
++ return 0;
++}
++
++static void kcopyd_put_pages(struct dm_kcopyd_client *kc, struct page_list *pl)
++{
++ struct page_list *cursor;
++
++ spin_lock(&kc->lock);
++ for (cursor = pl; cursor->next; cursor = cursor->next)
++ kc->nr_free_pages++;
++
++ kc->nr_free_pages++;
++ cursor->next = kc->pages;
++ kc->pages = pl;
++ spin_unlock(&kc->lock);
++}
++
++/*
++ * These three functions resize the page pool.
++ */
++static void drop_pages(struct page_list *pl)
++{
++ struct page_list *next;
++
++ while (pl) {
++ next = pl->next;
++ free_pl(pl);
++ pl = next;
++ }
++}
++
++static int client_alloc_pages(struct dm_kcopyd_client *kc, unsigned int nr)
++{
++ unsigned int i;
++ struct page_list *pl = NULL, *next;
++
++ for (i = 0; i < nr; i++) {
++ next = alloc_pl();
++ if (!next) {
++ if (pl)
++ drop_pages(pl);
++ return -ENOMEM;
++ }
++ next->next = pl;
++ pl = next;
++ }
++
++ kcopyd_put_pages(kc, pl);
++ kc->nr_pages += nr;
++ return 0;
++}
++
++static void client_free_pages(struct dm_kcopyd_client *kc)
++{
++ BUG_ON(kc->nr_free_pages != kc->nr_pages);
++ drop_pages(kc->pages);
++ kc->pages = NULL;
++ kc->nr_free_pages = kc->nr_pages = 0;
++}
++
++/*-----------------------------------------------------------------
++ * kcopyd_jobs need to be allocated by the *clients* of kcopyd,
++ * for this reason we use a mempool to prevent the client from
++ * ever having to do io (which could cause a deadlock).
++ *---------------------------------------------------------------*/
++struct kcopyd_job {
++ struct dm_kcopyd_client *kc;
++ struct list_head list;
++ unsigned long flags;
++
++ /*
++ * Error state of the job.
++ */
++ int read_err;
++ unsigned long write_err;
++
++ /*
++ * Either READ or WRITE
++ */
++ int rw;
++ struct dm_io_region source;
++
++ /*
++ * The destinations for the transfer.
++ */
++ unsigned int num_dests;
++ struct dm_io_region dests[DM_KCOPYD_MAX_REGIONS];
++
++ sector_t offset;
++ unsigned int nr_pages;
++ struct page_list *pages;
++
++ /*
++ * Set this to ensure you are notified when the job has
++ * completed. 'context' is for callback to use.
++ */
++ dm_kcopyd_notify_fn fn;
++ void *context;
++
++ /*
++ * These fields are only used if the job has been split
++ * into more manageable parts.
++ */
++ struct mutex lock;
++ atomic_t sub_jobs;
++ sector_t progress;
++};
++
++/* FIXME: this should scale with the number of pages */
++#define MIN_JOBS 512
++
++static struct kmem_cache *_job_cache;
++
++int __init dm_kcopyd_init(void)
++{
++ _job_cache = KMEM_CACHE(kcopyd_job, 0);
++ if (!_job_cache)
++ return -ENOMEM;
++
++ return 0;
++}
++
++void dm_kcopyd_exit(void)
++{
++ kmem_cache_destroy(_job_cache);
++ _job_cache = NULL;
++}
++
++/*
++ * Functions to push and pop a job onto the head of a given job
++ * list.
++ */
++static struct kcopyd_job *pop(struct list_head *jobs,
++ struct dm_kcopyd_client *kc)
++{
++ struct kcopyd_job *job = NULL;
++ unsigned long flags;
++
++ spin_lock_irqsave(&kc->job_lock, flags);
++
++ if (!list_empty(jobs)) {
++ job = list_entry(jobs->next, struct kcopyd_job, list);
++ list_del(&job->list);
++ }
++ spin_unlock_irqrestore(&kc->job_lock, flags);
++
++ return job;
++}
++
++static void push(struct list_head *jobs, struct kcopyd_job *job)
++{
++ unsigned long flags;
++ struct dm_kcopyd_client *kc = job->kc;
++
++ spin_lock_irqsave(&kc->job_lock, flags);
++ list_add_tail(&job->list, jobs);
++ spin_unlock_irqrestore(&kc->job_lock, flags);
++}
++
++/*
++ * These three functions process 1 item from the corresponding
++ * job list.
++ *
++ * They return:
++ * < 0: error
++ * 0: success
++ * > 0: can't process yet.
++ */
++static int run_complete_job(struct kcopyd_job *job)
++{
++ void *context = job->context;
++ int read_err = job->read_err;
++ unsigned long write_err = job->write_err;
++ dm_kcopyd_notify_fn fn = job->fn;
++ struct dm_kcopyd_client *kc = job->kc;
++
++ kcopyd_put_pages(kc, job->pages);
++ mempool_free(job, kc->job_pool);
++ fn(read_err, write_err, context);
++
++ if (atomic_dec_and_test(&kc->nr_jobs))
++ wake_up(&kc->destroyq);
++
++ return 0;
++}
++
++static void complete_io(unsigned long error, void *context)
++{
++ struct kcopyd_job *job = (struct kcopyd_job *) context;
++ struct dm_kcopyd_client *kc = job->kc;
++
++ if (error) {
++ if (job->rw == WRITE)
++ job->write_err |= error;
++ else
++ job->read_err = 1;
++
++ if (!test_bit(DM_KCOPYD_IGNORE_ERROR, &job->flags)) {
++ push(&kc->complete_jobs, job);
++ wake(kc);
++ return;
++ }
++ }
++
++ if (job->rw == WRITE)
++ push(&kc->complete_jobs, job);
++
++ else {
++ job->rw = WRITE;
++ push(&kc->io_jobs, job);
++ }
++
++ wake(kc);
++}
++
++/*
++ * Request io on as many buffer heads as we can currently get for
++ * a particular job.
++ */
++static int run_io_job(struct kcopyd_job *job)
++{
++ int r;
++ struct dm_io_request io_req = {
++ .bi_rw = job->rw | (1 << BIO_RW_SYNC),
++ .mem.type = DM_IO_PAGE_LIST,
++ .mem.ptr.pl = job->pages,
++ .mem.offset = job->offset,
++ .notify.fn = complete_io,
++ .notify.context = job,
++ .client = job->kc->io_client,
++ };
++
++ if (job->rw == READ)
++ r = dm_io(&io_req, 1, &job->source, NULL);
++ else
++ r = dm_io(&io_req, job->num_dests, job->dests, NULL);
++
++ return r;
++}
++
++static int run_pages_job(struct kcopyd_job *job)
++{
++ int r;
++
++ job->nr_pages = dm_div_up(job->dests[0].count + job->offset,
++ PAGE_SIZE >> 9);
++ r = kcopyd_get_pages(job->kc, job->nr_pages, &job->pages);
++ if (!r) {
++ /* this job is ready for io */
++ push(&job->kc->io_jobs, job);
++ return 0;
++ }
++
++ if (r == -ENOMEM)
++ /* can't complete now */
++ return 1;
++
++ return r;
++}
++
++/*
++ * Run through a list for as long as possible. Returns the count
++ * of successful jobs.
++ */
++static int process_jobs(struct list_head *jobs, struct dm_kcopyd_client *kc,
++ int (*fn) (struct kcopyd_job *))
++{
++ struct kcopyd_job *job;
++ int r, count = 0;
++
++ while ((job = pop(jobs, kc))) {
++
++ r = fn(job);
++
++ if (r < 0) {
++ /* error this rogue job */
++ if (job->rw == WRITE)
++ job->write_err = (unsigned long) -1L;
++ else
++ job->read_err = 1;
++ push(&kc->complete_jobs, job);
++ break;
++ }
++
++ if (r > 0) {
++ /*
++ * We couldn't service this job ATM, so
++ * push this job back onto the list.
++ */
++ push(jobs, job);
++ break;
++ }
++
++ count++;
++ }
++
++ return count;
++}
++
++/*
++ * kcopyd does this every time it's woken up.
++ */
++static void do_work(struct work_struct *work)
++{
++ struct dm_kcopyd_client *kc = container_of(work,
++ struct dm_kcopyd_client, kcopyd_work);
++
++ /*
++ * The order that these are called is *very* important.
++ * complete jobs can free some pages for pages jobs.
++ * Pages jobs when successful will jump onto the io jobs
++ * list. io jobs call wake when they complete and it all
++ * starts again.
++ */
++ process_jobs(&kc->complete_jobs, kc, run_complete_job);
++ process_jobs(&kc->pages_jobs, kc, run_pages_job);
++ process_jobs(&kc->io_jobs, kc, run_io_job);
++}
++
++/*
++ * If we are copying a small region we just dispatch a single job
++ * to do the copy, otherwise the io has to be split up into many
++ * jobs.
++ */
++static void dispatch_job(struct kcopyd_job *job)
++{
++ struct dm_kcopyd_client *kc = job->kc;
++ atomic_inc(&kc->nr_jobs);
++ push(&kc->pages_jobs, job);
++ wake(kc);
++}
++
++#define SUB_JOB_SIZE 128
++static void segment_complete(int read_err, unsigned long write_err,
++ void *context)
++{
++ /* FIXME: tidy this function */
++ sector_t progress = 0;
++ sector_t count = 0;
++ struct kcopyd_job *job = (struct kcopyd_job *) context;
++
++ mutex_lock(&job->lock);
++
++ /* update the error */
++ if (read_err)
++ job->read_err = 1;
++
++ if (write_err)
++ job->write_err |= write_err;
++
++ /*
++ * Only dispatch more work if there hasn't been an error.
++ */
++ if ((!job->read_err && !job->write_err) ||
++ test_bit(DM_KCOPYD_IGNORE_ERROR, &job->flags)) {
++ /* get the next chunk of work */
++ progress = job->progress;
++ count = job->source.count - progress;
++ if (count) {
++ if (count > SUB_JOB_SIZE)
++ count = SUB_JOB_SIZE;
++
++ job->progress += count;
++ }
++ }
++ mutex_unlock(&job->lock);
++
++ if (count) {
++ int i;
++ struct kcopyd_job *sub_job = mempool_alloc(job->kc->job_pool,
++ GFP_NOIO);
++
++ *sub_job = *job;
++ sub_job->source.sector += progress;
++ sub_job->source.count = count;
++
++ for (i = 0; i < job->num_dests; i++) {
++ sub_job->dests[i].sector += progress;
++ sub_job->dests[i].count = count;
++ }
++
++ sub_job->fn = segment_complete;
++ sub_job->context = job;
++ dispatch_job(sub_job);
++
++ } else if (atomic_dec_and_test(&job->sub_jobs)) {
++
++ /*
++ * To avoid a race we must keep the job around
++ * until after the notify function has completed.
++ * Otherwise the client may try and stop the job
++ * after we've completed.
++ */
++ job->fn(read_err, write_err, job->context);
++ mempool_free(job, job->kc->job_pool);
++ }
++}
++
++/*
++ * Create some little jobs that will do the move between
++ * them.
++ */
++#define SPLIT_COUNT 8
++static void split_job(struct kcopyd_job *job)
++{
++ int i;
++
++ atomic_set(&job->sub_jobs, SPLIT_COUNT);
++ for (i = 0; i < SPLIT_COUNT; i++)
++ segment_complete(0, 0u, job);
++}
++
++int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
++ unsigned int num_dests, struct dm_io_region *dests,
++ unsigned int flags, dm_kcopyd_notify_fn fn, void *context)
++{
++ struct kcopyd_job *job;
++
++ /*
++ * Allocate a new job.
++ */
++ job = mempool_alloc(kc->job_pool, GFP_NOIO);
++
++ /*
++ * set up for the read.
++ */
++ job->kc = kc;
++ job->flags = flags;
++ job->read_err = 0;
++ job->write_err = 0;
++ job->rw = READ;
++
++ job->source = *from;
++
++ job->num_dests = num_dests;
++ memcpy(&job->dests, dests, sizeof(*dests) * num_dests);
++
++ job->offset = 0;
++ job->nr_pages = 0;
++ job->pages = NULL;
++
++ job->fn = fn;
++ job->context = context;
++
++ if (job->source.count < SUB_JOB_SIZE)
++ dispatch_job(job);
++
++ else {
++ mutex_init(&job->lock);
++ job->progress = 0;
++ split_job(job);
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL(dm_kcopyd_copy);
++
++/*
++ * Cancels a kcopyd job, eg. someone might be deactivating a
++ * mirror.
++ */
++#if 0
++int kcopyd_cancel(struct kcopyd_job *job, int block)
++{
++ /* FIXME: finish */
++ return -1;
++}
++#endif /* 0 */
++
++/*-----------------------------------------------------------------
++ * Client setup
++ *---------------------------------------------------------------*/
++int dm_kcopyd_client_create(unsigned int nr_pages,
++ struct dm_kcopyd_client **result)
++{
++ int r = -ENOMEM;
++ struct dm_kcopyd_client *kc;
++
++ kc = kmalloc(sizeof(*kc), GFP_KERNEL);
++ if (!kc)
++ return -ENOMEM;
++
++ spin_lock_init(&kc->lock);
++ spin_lock_init(&kc->job_lock);
++ INIT_LIST_HEAD(&kc->complete_jobs);
++ INIT_LIST_HEAD(&kc->io_jobs);
++ INIT_LIST_HEAD(&kc->pages_jobs);
++
++ kc->job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache);
++ if (!kc->job_pool)
++ goto bad_slab;
++
++ INIT_WORK(&kc->kcopyd_work, do_work);
++ kc->kcopyd_wq = create_singlethread_workqueue("kcopyd");
++ if (!kc->kcopyd_wq)
++ goto bad_workqueue;
++
++ kc->pages = NULL;
++ kc->nr_pages = kc->nr_free_pages = 0;
++ r = client_alloc_pages(kc, nr_pages);
++ if (r)
++ goto bad_client_pages;
++
++ kc->io_client = dm_io_client_create(nr_pages);
++ if (IS_ERR(kc->io_client)) {
++ r = PTR_ERR(kc->io_client);
++ goto bad_io_client;
++ }
++
++ init_waitqueue_head(&kc->destroyq);
++ atomic_set(&kc->nr_jobs, 0);
++
++ *result = kc;
++ return 0;
++
++bad_io_client:
++ client_free_pages(kc);
++bad_client_pages:
++ destroy_workqueue(kc->kcopyd_wq);
++bad_workqueue:
++ mempool_destroy(kc->job_pool);
++bad_slab:
++ kfree(kc);
++
++ return r;
++}
++EXPORT_SYMBOL(dm_kcopyd_client_create);
++
++void dm_kcopyd_client_destroy(struct dm_kcopyd_client *kc)
++{
++ /* Wait for completion of all jobs submitted by this client. */
++ wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs));
++
++ BUG_ON(!list_empty(&kc->complete_jobs));
++ BUG_ON(!list_empty(&kc->io_jobs));
++ BUG_ON(!list_empty(&kc->pages_jobs));
++ destroy_workqueue(kc->kcopyd_wq);
++ dm_io_client_destroy(kc->io_client);
++ client_free_pages(kc);
++ mempool_destroy(kc->job_pool);
++ kfree(kc);
++}
++EXPORT_SYMBOL(dm_kcopyd_client_destroy);
+diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
+index 2a74b21..67a6f31 100644
+--- a/drivers/md/dm-log.c
++++ b/drivers/md/dm-log.c
+@@ -1,5 +1,6 @@
+ /*
+ * Copyright (C) 2003 Sistina Software
++ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the LGPL.
+ */
+@@ -8,64 +9,58 @@
+ #include <linux/slab.h>
+ #include <linux/module.h>
+ #include <linux/vmalloc.h>
++#include <linux/dm-io.h>
++#include <linux/dm-dirty-log.h>
-@@ -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;
- }
+-#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);
--void c2_free_mqsp(u16 * mqsp)
-+void c2_free_mqsp(__be16 *mqsp)
+-int dm_unregister_dirty_log_type(struct dirty_log_type *type)
++static struct dm_dirty_log_internal *__find_dirty_log_type(const char *name)
{
- 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);
+- 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;
- /* Link head to new mqsp */
-- *mqsp = head->head;
-+ *mqsp = (__force __be16) head->head;
+- spin_unlock(&_lock);
++ list_for_each_entry(log_type, &_log_types, list)
++ if (!strcmp(name, log_type->type->name))
++ return log_type;
- /* 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;
+- return 0;
++ return NULL;
+ }
- 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;
- }
+-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;
-- err = c2_errno(reply_msg);
-+ if (reply_msg)
-+ err = c2_errno(reply_msg);
-+ else
-+ err = -ENOMEM;
+ 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;
+- }
+
- 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.
++ 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 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)
+-static struct dirty_log_type *get_type(const char *type_name)
++static struct dm_dirty_log_type *get_type(const char *type_name)
{
-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);
- }
- }
+ char *p, *type_name_dup;
+- struct dirty_log_type *type;
++ struct dm_dirty_log_internal *log_type;
++
++ if (!type_name)
++ return NULL;
-@@ -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);
+- 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)
}
- }
-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);
+ 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';
+ }
-- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
-+ pr_debug("%s:%u\n", __func__, __LINE__);
+- if (!type)
++ if (!log_type)
+ DMWARN("Module for logging type \"%s\" not found.", type_name);
- *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__);
+ kfree(type_name_dup);
- 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;
+- return type;
++ return log_type ? log_type->type : NULL;
}
- static int c2_query_pkey(struct ib_device *ibdev,
- u8 port, u16 index, u16 * pkey)
+-static void put_type(struct dirty_log_type *type)
++static void put_type(struct dm_dirty_log_type *type)
{
-- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
-+ pr_debug("%s:%u\n", __func__, __LINE__);
- *pkey = 0;
- return 0;
++ 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);
}
-@@ -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 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 c2_ucontext *context;
+- 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;
-- 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,
+ 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
- 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;
+ return log;
}
++EXPORT_SYMBOL(dm_dirty_log_create);
- static int c2_mmap_uar(struct ib_ucontext *context, struct vm_area_struct *vma)
+-void dm_destroy_dirty_log(struct dirty_log *log)
++void dm_dirty_log_destroy(struct dm_dirty_log *log)
{
-- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
-+ pr_debug("%s:%u\n", __func__, __LINE__);
- return -ENOSYS;
+ log->type->dtr(log);
+ put_type(log->type);
+ kfree(log);
}
++EXPORT_SYMBOL(dm_dirty_log_destroy);
-@@ -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);
+ /*-----------------------------------------------------------------
+ * 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;
-@@ -196,13 +196,13 @@ static int c2_dealloc_pd(struct ib_pd *pd)
+- struct io_region header_location;
++ struct dm_io_region header_location;
+ struct log_header *disk_header;
+ };
- static struct ib_ah *c2_ah_create(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
+@@ -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)
{
-- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
-+ pr_debug("%s:%u\n", __func__, __LINE__);
- return ERR_PTR(-ENOSYS);
+ return ext2_test_bit(bit, (unsigned long *) bs) ? 1 : 0;
}
-
- static int c2_ah_destroy(struct ib_ah *ah)
+@@ -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)
{
-- 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;
+@@ -315,7 +387,7 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti,
+ int r;
-- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
-+ pr_debug("%s:%u\n", __func__, __LINE__);
-+
-+ if (init_attr->create_flags)
-+ return ERR_PTR(-EINVAL);
+ if (argc < 1 || argc > 2) {
+- DMWARN("wrong number of arguments to mirror log");
++ DMWARN("wrong number of arguments to dirty region log");
+ return -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);
+@@ -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;
}
- 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);
}
+@@ -434,7 +506,7 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti,
+ return 0;
+ }
- 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)
+-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)
{
- 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;
+ return create_log_context(log, ti, argc, argv, NULL);
+@@ -447,7 +519,7 @@ static void destroy_log_context(struct log_c *lc)
+ kfree(lc);
+ }
-- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
-+ pr_debug("%s:%u\n", __func__, __LINE__);
+-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;
- 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;
+@@ -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;
-- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
-+ pr_debug("%s:%u\n", __func__, __LINE__);
+ 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;
+ }
- 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;
+@@ -485,7 +557,7 @@ static int disk_ctr(struct dirty_log *log, struct dm_target *ti,
+ 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)
+-static void disk_dtr(struct dirty_log *log)
++static void disk_dtr(struct dm_dirty_log *log)
{
-- 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);
+ 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 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)
+-static int disk_resume(struct dirty_log *log)
++static int disk_resume(struct dm_dirty_log *log)
{
-- 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));
+ 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 ssize_t show_hca(struct class_device *cdev, char *buf)
-+static ssize_t show_hca(struct device *dev, struct device_attribute *attr,
-+ char *buf)
+-static uint32_t core_get_region_size(struct dirty_log *log)
++static uint32_t core_get_region_size(struct dm_dirty_log *log)
{
-- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
-+ pr_debug("%s:%u\n", __func__, __LINE__);
- return sprintf(buf, "AMSO1100\n");
+ struct log_c *lc = (struct log_c *) log->context;
+ return lc->region_size;
}
--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)
+-static int core_resume(struct dirty_log *log)
++static int core_resume(struct dm_dirty_log *log)
{
-- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
-+ pr_debug("%s:%u\n", __func__, __LINE__);
- return sprintf(buf, "%.*s\n", 32, "AMSO1100 Board ID");
+ struct log_c *lc = (struct log_c *) log->context;
+ lc->sync_search = 0;
+ return 0;
}
--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)
+-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)
{
-- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
-+ pr_debug("%s:%u\n", __func__, __LINE__);
- return -ENOSYS;
+ struct log_c *lc = (struct log_c *) log->context;
+ return log_test_bit(lc->clean_bits, region);
}
- static int c2_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
+-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)
{
-- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
-+ pr_debug("%s:%u\n", __func__, __LINE__);
- return -ENOSYS;
+ struct log_c *lc = (struct log_c *) log->context;
+ return log_test_bit(lc->sync_bits, region);
}
-@@ -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)
+-static int core_flush(struct dirty_log *log)
++static int core_flush(struct dm_dirty_log *log)
{
-- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
-+ pr_debug("%s:%u\n", __func__, __LINE__);
- return -ENOSYS;
+ /* no op */
+ return 0;
}
- static int c2_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
+-static int disk_flush(struct dirty_log *log)
++static int disk_flush(struct dm_dirty_log *log)
{
-- 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)
+ 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 int c2_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
+-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)
{
-- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
-+ pr_debug("%s:%u\n", __func__, __LINE__);
+ struct log_c *lc = (struct log_c *) log->context;
+ log_clear_bit(lc, lc->clean_bits, region);
+ }
- /* 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)
+-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)
{
- int err;
-
-- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
-+ pr_debug("%s:%u\n", __func__, __LINE__);
+ struct log_c *lc = (struct log_c *) log->context;
+ log_set_bit(lc, lc->clean_bits, region);
+ }
- 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)
+-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)
{
- int err;
+ struct log_c *lc = (struct log_c *) log->context;
-- 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;
+@@ -654,7 +726,7 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region)
+ return 1;
}
-@@ -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;
+-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,
}
-@@ -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)
+-static region_t core_get_sync_count(struct dirty_log *log)
++static region_t core_get_sync_count(struct dm_dirty_log *log)
{
-- 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,
+ struct log_c *lc = (struct log_c *) log->context;
- 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);
- }
+@@ -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" : "")
-- 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)
+-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)
{
- 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 {
- };
+ int sz = 0;
+@@ -700,7 +772,7 @@ static int core_status(struct dirty_log *log, status_type_t status,
+ return sz;
+ }
- struct c2_netaddr {
-- u32 ip_addr;
-- u32 netmask;
-+ __be32 ip_addr;
-+ __be32 netmask;
- u32 mtu;
- };
+-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;
+ }
-@@ -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;
+-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,
};
- /*
-@@ -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)
+-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)
{
- 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)
+ int r;
- 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)
+- r = dm_register_dirty_log_type(&_core_type);
++ r = dm_dirty_log_type_register(&_core_type);
+ if (r)
+ DMWARN("couldn't register core log");
- 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;
+- 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);
}
-@@ -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;
+ return r;
}
-@@ -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)
+-void dm_dirty_log_exit(void)
++void __exit dm_dirty_log_exit(void)
{
- 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);
+- 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);
}
- 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);
+-EXPORT_SYMBOL(dm_register_dirty_log_type);
+-EXPORT_SYMBOL(dm_unregister_dirty_log_type);
+-EXPORT_SYMBOL(dm_create_dirty_log);
+-EXPORT_SYMBOL(dm_destroy_dirty_log);
++module_init(dm_dirty_log_init);
++module_exit(dm_dirty_log_exit);
++
++MODULE_DESCRIPTION(DM_NAME " dirty region log");
++MODULE_AUTHOR("Joe Thornber, Heinz Mauelshagen <dm-devel at redhat.com>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/md/dm-log.h b/drivers/md/dm-log.h
+deleted file mode 100644
+index 3fae87e..0000000
+--- a/drivers/md/dm-log.h
++++ /dev/null
+@@ -1,131 +0,0 @@
+-/*
+- * Copyright (C) 2003 Sistina Software
+- *
+- * This file is released under the LGPL.
+- */
+-
+-#ifndef DM_DIRTY_LOG
+-#define DM_DIRTY_LOG
+-
+-#include "dm.h"
+-
+-typedef sector_t region_t;
+-
+-struct dirty_log_type;
+-
+-struct dirty_log {
+- struct dirty_log_type *type;
+- void *context;
+-};
+-
+-struct dirty_log_type {
+- struct list_head list;
+- const char *name;
+- struct module *module;
+- unsigned int use_count;
+-
+- int (*ctr)(struct dirty_log *log, struct dm_target *ti,
+- unsigned int argc, char **argv);
+- void (*dtr)(struct dirty_log *log);
+-
+- /*
+- * There are times when we don't want the log to touch
+- * the disk.
+- */
+- int (*presuspend)(struct dirty_log *log);
+- int (*postsuspend)(struct dirty_log *log);
+- int (*resume)(struct dirty_log *log);
+-
+- /*
+- * Retrieves the smallest size of region that the log can
+- * deal with.
+- */
+- uint32_t (*get_region_size)(struct dirty_log *log);
+-
+- /*
+- * A predicate to say whether a region is clean or not.
+- * May block.
+- */
+- int (*is_clean)(struct dirty_log *log, region_t region);
+-
+- /*
+- * Returns: 0, 1, -EWOULDBLOCK, < 0
+- *
+- * A predicate function to check the area given by
+- * [sector, sector + len) is in sync.
+- *
+- * If -EWOULDBLOCK is returned the state of the region is
+- * unknown, typically this will result in a read being
+- * passed to a daemon to deal with, since a daemon is
+- * allowed to block.
+- */
+- int (*in_sync)(struct dirty_log *log, region_t region, int can_block);
+-
+- /*
+- * Flush the current log state (eg, to disk). This
+- * function may block.
+- */
+- int (*flush)(struct dirty_log *log);
+-
+- /*
+- * Mark an area as clean or dirty. These functions may
+- * block, though for performance reasons blocking should
+- * be extremely rare (eg, allocating another chunk of
+- * memory for some reason).
+- */
+- void (*mark_region)(struct dirty_log *log, region_t region);
+- void (*clear_region)(struct dirty_log *log, region_t region);
+-
+- /*
+- * Returns: <0 (error), 0 (no region), 1 (region)
+- *
+- * The mirrord will need perform recovery on regions of
+- * the mirror that are in the NOSYNC state. This
+- * function asks the log to tell the caller about the
+- * next region that this machine should recover.
+- *
+- * Do not confuse this function with 'in_sync()', one
+- * tells you if an area is synchronised, the other
+- * assigns recovery work.
+- */
+- int (*get_resync_work)(struct dirty_log *log, region_t *region);
+-
+- /*
+- * This notifies the log that the resync status of a region
+- * has changed. It also clears the region from the recovering
+- * list (if present).
+- */
+- void (*set_region_sync)(struct dirty_log *log,
+- region_t region, int in_sync);
+-
+- /*
+- * Returns the number of regions that are in sync.
+- */
+- region_t (*get_sync_count)(struct dirty_log *log);
+-
+- /*
+- * Support function for mirror status requests.
+- */
+- int (*status)(struct dirty_log *log, status_type_t status_type,
+- char *result, unsigned int maxlen);
+-};
+-
+-int dm_register_dirty_log_type(struct dirty_log_type *type);
+-int dm_unregister_dirty_log_type(struct dirty_log_type *type);
+-
+-
+-/*
+- * Make sure you use these two functions, rather than calling
+- * type->constructor/destructor() directly.
+- */
+-struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *ti,
+- unsigned int argc, char **argv);
+-void dm_destroy_dirty_log(struct dirty_log *log);
+-
+-/*
+- * init/exit functions.
+- */
+-int dm_dirty_log_init(void);
+-void dm_dirty_log_exit(void);
+-
+-#endif
+diff --git a/drivers/md/dm-mpath-hp-sw.c b/drivers/md/dm-mpath-hp-sw.c
+index 204bf42..b63a0ab 100644
+--- a/drivers/md/dm-mpath-hp-sw.c
++++ b/drivers/md/dm-mpath-hp-sw.c
+@@ -137,7 +137,6 @@ static struct request *hp_sw_get_request(struct dm_path *path)
+ req->sense = h->sense;
+ memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
+
+- memset(&req->cmd, 0, BLK_MAX_CDB);
+ req->cmd[0] = START_STOP;
+ req->cmd[4] = 1;
+ req->cmd_len = COMMAND_SIZE(req->cmd[0]);
+diff --git a/drivers/md/dm-mpath-rdac.c b/drivers/md/dm-mpath-rdac.c
+index e04eb5c..95e7773 100644
+--- a/drivers/md/dm-mpath-rdac.c
++++ b/drivers/md/dm-mpath-rdac.c
+@@ -284,7 +284,6 @@ static struct request *get_rdac_req(struct rdac_handler *h,
+ return NULL;
}
- 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;
- }
+- memset(&rq->cmd, 0, BLK_MAX_CDB);
+ rq->sense = h->sense;
+ memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+ rq->sense_len = 0;
+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"
- list_add_tail(&rdev_p->entry, &rdev_list);
+ #include <linux/ctype.h>
+ #include <linux/init.h>
+@@ -22,6 +19,9 @@
+ #include <linux/workqueue.h>
+ #include <linux/log2.h>
+ #include <linux/hardirq.h>
++#include <linux/dm-io.h>
++#include <linux/dm-dirty-log.h>
++#include <linux/dm-kcopyd.h>
-- 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;
- }
+ #define DM_MSG_PREFIX "raid1"
+ #define DM_IO_PAGES 64
+@@ -74,7 +74,7 @@ struct region_hash {
+ unsigned region_shift;
-@@ -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,
+ /* holds persistent region state */
+- struct dirty_log *log;
++ struct dm_dirty_log *log;
- 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;
+ /* 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;
- 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;
+ spinlock_t lock; /* protects the lists */
+@@ -154,6 +154,9 @@ struct mirror_set {
- /*
-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;
- }
+ struct workqueue_struct *kmirrord_wq;
+ struct work_struct kmirrord_work;
++ struct timer_list timer;
++ unsigned long timer_pending;
++
+ struct work_struct trigger_event;
- 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);
+ unsigned int nr_mirrors;
+@@ -178,13 +181,32 @@ static void wake(struct mirror_set *ms)
+ queue_work(ms->kmirrord_wq, &ms->kmirrord_work);
}
-@@ -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;
- }
++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);
- void cxio_hal_pblpool_free(struct cxio_rdev *rdev_p, u32 addr, int size)
+ #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)
{
-- 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);
- }
+ unsigned int nr_buckets, max_buckets;
+@@ -249,7 +271,7 @@ static void rh_exit(struct region_hash *rh)
+ }
-@@ -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;
- }
+ 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);
- 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);
- }
+ list_for_each_entry(reg, &clean, list)
+ list_del(®->hash_list);
+ }
-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);
+ 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);
- 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;
+ list_for_each_entry (reg, &recovered, list)
+ list_del(®->hash_list);
+ }
-- 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)
+ 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 ret;
-- u32 newid;
-+ int newid;
+ 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;
- 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);
+@@ -822,9 +842,9 @@ static int recover(struct mirror_set *ms, struct region *reg)
+ }
- 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)
+ /* 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);
- 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);
+ return r;
}
-@@ -190,7 +190,7 @@ int iwch_resume_tid(struct iwch_ep *ep)
-
- static void set_emss(struct iwch_ep *ep, u16 opt)
+@@ -833,7 +853,7 @@ static void do_recovery(struct mirror_set *ms)
{
-- 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;
+ int r;
+ struct region *reg;
+- struct dirty_log *log = ms->rh.log;
++ struct dm_dirty_log *log = ms->rh.log;
- 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;
+ /*
+ * 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);
}
-@@ -244,13 +244,13 @@ void __free_ep(struct kref *kref)
+-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)
{
- 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)
+ 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)
{
-- 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)
+- 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,
{
-- PDBG("%s t3cdev %p\n", __FUNCTION__, dev);
-+ PDBG("%s t3cdev %p\n", __func__, dev);
- kfree_skb(skb);
+ 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);
}
-@@ -370,7 +370,7 @@ static void abort_arp_failure(struct t3cdev *dev, struct sk_buff *skb)
+ 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 cpl_abort_req *req = cplhdr(skb);
+ 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);
-- 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);
+- 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);
}
-@@ -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)
+
+@@ -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)
{
- struct cpl_abort_req *req;
+ size_t len;
+ struct mirror_set *ms = NULL;
+@@ -1403,12 +1408,12 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
+ /*
+ * Create dirty log: log_type #log_params <log_params>
+ */
+-static struct dirty_log *create_dirty_log(struct dm_target *ti,
++static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
+ unsigned int argc, char **argv,
+ unsigned int *args_used)
+ {
+ unsigned int param_count;
+- struct dirty_log *dl;
++ struct dm_dirty_log *dl;
-- 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;
+ 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;
}
- 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);
+- 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,
- skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
- if (!skb) {
- printk(KERN_ERR MOD "%s - failed to alloc skb.\n",
-- __FUNCTION__);
-+ __func__);
- return -ENOMEM;
+ 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;
}
- 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);
+@@ -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;
- BUG_ON(skb_cloned(skb));
+ 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;
-@@ -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;
+ 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;
+ }
-- PDBG("%s ep %p plen %d\n", __FUNCTION__, ep, plen);
-+ PDBG("%s ep %p plen %d\n", __func__, ep, plen);
+@@ -1516,13 +1521,13 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
- mpalen = sizeof(*mpa) + plen;
+ if (argc < nr_mirrors * 2) {
+ ti->error = "Too few mirror arguments";
+- dm_destroy_dirty_log(dl);
++ dm_dirty_log_destroy(dl);
+ return -EINVAL;
+ }
- 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__);
+ 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;
}
- 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;
+@@ -1547,6 +1552,8 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ goto err_free_context;
}
- 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);
+ INIT_WORK(&ms->kmirrord_work, do_mirror);
++ init_timer(&ms->timer);
++ ms->timer_pending = 0;
+ INIT_WORK(&ms->trigger_event, trigger_event);
-- PDBG("%s ep %p tid %d\n", __FUNCTION__, ep, tid);
-+ PDBG("%s ep %p tid %d\n", __func__, ep, tid);
+ 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;
+ }
- dst_confirm(ep->dst);
+- 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;
-@@ -663,7 +663,7 @@ static void close_complete_upcall(struct iwch_ep *ep)
+@@ -1589,8 +1596,9 @@ static void mirror_dtr(struct dm_target *ti)
{
- struct iw_cm_event event;
+ struct mirror_set *ms = (struct mirror_set *) ti->private;
-- 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)
++ 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 iw_cm_event event;
+ struct mirror_set *ms = (struct mirror_set *) ti->private;
+- struct dirty_log *log = ms->rh.log;
++ struct dm_dirty_log *log = ms->rh.log;
-- 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)
+ 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 iw_cm_event event;
+ struct mirror_set *ms = ti->private;
+- struct dirty_log *log = ms->rh.log;
++ struct dm_dirty_log *log = ms->rh.log;
-- 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)
+ 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 iw_cm_event event;
+ struct mirror_set *ms = ti->private;
+- struct dirty_log *log = ms->rh.log;
++ struct dm_dirty_log *log = ms->rh.log;
-- 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)
+ 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,
{
- struct iw_cm_event event;
+ 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];
-- 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)
+ switch (type) {
+@@ -1864,15 +1872,9 @@ static int __init dm_mirror_init(void)
{
- struct iw_cm_event event;
+ int r;
-- 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);
- }
+- 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();
}
-@@ -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;
+ /* Module hooks */
+diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
+index 4dc8a43..1ba8a47 100644
+--- a/drivers/md/dm-snap.c
++++ b/drivers/md/dm-snap.c
+@@ -18,10 +18,10 @@
+ #include <linux/slab.h>
+ #include <linux/vmalloc.h>
+ #include <linux/log2.h>
++#include <linux/dm-kcopyd.h>
-- PDBG("%s ep %p\n", __FUNCTION__, ep);
-+ PDBG("%s ep %p\n", __func__, ep);
+ #include "dm-snap.h"
+ #include "dm-bio-list.h"
+-#include "kcopyd.h"
- /*
- * 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);
+ #define DM_MSG_PREFIX "snapshots"
-@@ -915,7 +915,7 @@ static void process_mpa_request(struct iwch_ep *ep, struct sk_buff *skb)
- struct mpa_message *mpa;
- u16 plen;
+@@ -36,9 +36,9 @@
+ #define SNAPSHOT_COPY_PRIORITY 2
-- PDBG("%s ep %p\n", __FUNCTION__, ep);
-+ PDBG("%s ep %p\n", __func__, ep);
+ /*
+- * 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)
- /*
- * 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;
- }
+ 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;
-- PDBG("%s enter (%s line %u)\n", __FUNCTION__, __FILE__, __LINE__);
-+ PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__);
+ /* 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;
+ }
- /*
- * 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;
+- 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;
- /*
-@@ -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);
+ bad6:
+- kcopyd_client_destroy(s->kcopyd_client);
++ dm_kcopyd_client_destroy(s->kcopyd_client);
-@@ -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);
+ bad5:
+ s->store.destroy(&s->store);
+@@ -613,7 +613,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
-- PDBG("%s ep %p dlen %u\n", __FUNCTION__, ep, dlen);
-+ PDBG("%s ep %p dlen %u\n", __func__, ep, dlen);
+ 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;
- 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);
+ exit_exception_table(&s->pending, pending_cache);
+@@ -699,7 +699,7 @@ static void __invalidate_snapshot(struct dm_snapshot *s, int err)
- /*
- * 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);
+ s->valid = 0;
-- PDBG("%s ep %p credits %u\n", __FUNCTION__, ep, credits);
-+ PDBG("%s ep %p credits %u\n", __func__, ep, credits);
+- dm_table_event(s->table);
++ dm_table_event(s->ti->table);
+ }
- 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)
+ 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 iwch_ep *ep = ctx;
+ 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;
-- PDBG("%s ep %p\n", __FUNCTION__, ep);
-+ PDBG("%s ep %p\n", __func__, ep);
+@@ -839,7 +839,7 @@ static void start_copy(struct dm_snap_pending_exception *pe)
+ dest.count = src.count;
- /*
- * 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);
+ /* Hand over to kcopyd */
+- kcopyd_copy(s->kcopyd_client,
++ dm_kcopyd_copy(s->kcopyd_client,
+ &src, 1, &dest, 0, copy_callback, pe);
+ }
-- 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;
+@@ -1060,7 +1060,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
+ goto next_snapshot;
-- 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);
+ /* 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;
-- 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;
+ /*
+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 {
-- 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);
+ struct dm_snapshot {
+ struct rw_semaphore lock;
+- struct dm_table *table;
++ struct dm_target *ti;
-- 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;
+ struct dm_dev *origin;
+ struct dm_dev *cow;
+@@ -169,7 +169,7 @@ struct dm_snapshot {
+ /* The on disk metadata handler */
+ struct exception_store store;
-- 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;
+- struct kcopyd_client *kcopyd_client;
++ struct dm_kcopyd_client *kcopyd_client;
-- PDBG("%s parent ep %p tid %u\n", __FUNCTION__, parent_ep, hwtid);
-+ PDBG("%s parent ep %p tid %u\n", __func__, parent_ep, hwtid);
+ /* 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..94116ea 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;
+ }
- if (state_read(&parent_ep->com) != LISTEN) {
- printk(KERN_ERR "%s - listening ep not in LISTEN\n",
-- __FUNCTION__);
-+ __func__);
- goto reject;
- }
+-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;
+@@ -911,10 +873,11 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q)
+ q->max_hw_sectors = t->limits.max_hw_sectors;
+ q->seg_boundary_mask = t->limits.seg_boundary_mask;
+ q->bounce_pfn = t->limits.bounce_pfn;
++
+ if (t->limits.no_cluster)
+- q->queue_flags &= ~(1 << QUEUE_FLAG_CLUSTER);
++ queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q);
+ else
+- q->queue_flags |= (1 << QUEUE_FLAG_CLUSTER);
++ queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q);
-@@ -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);
+@@ -954,7 +917,7 @@ void dm_table_presuspend_targets(struct dm_table *t)
+ if (!t)
+ return;
-@@ -1383,7 +1383,7 @@ static int peer_close(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
- int disconnect = 1;
- int release = 0;
+- return suspend_targets(t, 0);
++ suspend_targets(t, 0);
+ }
-- PDBG("%s ep %p\n", __FUNCTION__, ep);
-+ PDBG("%s ep %p\n", __func__, ep);
- dst_confirm(ep->dst);
+ void dm_table_postsuspend_targets(struct dm_table *t)
+@@ -962,7 +925,7 @@ void dm_table_postsuspend_targets(struct dm_table *t)
+ if (!t)
+ return;
- 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;
+- return suspend_targets(t, 1);
++ suspend_targets(t, 1);
+ }
- 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)
+ int dm_table_resume_targets(struct dm_table *t)
+diff --git a/drivers/md/dm-uevent.c b/drivers/md/dm-uevent.c
+index 50377e5..6f65883 100644
+--- a/drivers/md/dm-uevent.c
++++ b/drivers/md/dm-uevent.c
+@@ -78,7 +78,7 @@ static struct dm_uevent *dm_build_path_uevent(struct mapped_device *md,
+
+ event = dm_uevent_alloc(md);
+ if (!event) {
+- DMERR("%s: dm_uevent_alloc() failed", __FUNCTION__);
++ DMERR("%s: dm_uevent_alloc() failed", __func__);
+ goto err_nomem;
}
- 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;
+@@ -86,32 +86,32 @@ static struct dm_uevent *dm_build_path_uevent(struct mapped_device *md,
-- 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;
+ if (add_uevent_var(&event->ku_env, "DM_TARGET=%s", ti->type->name)) {
+ DMERR("%s: add_uevent_var() for DM_TARGET failed",
+- __FUNCTION__);
++ __func__);
+ goto err_add;
+ }
- 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;
+ if (add_uevent_var(&event->ku_env, "DM_ACTION=%s", dm_action)) {
+ DMERR("%s: add_uevent_var() for DM_ACTION failed",
+- __FUNCTION__);
++ __func__);
+ goto err_add;
+ }
- 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 (add_uevent_var(&event->ku_env, "DM_SEQNUM=%u",
+ dm_next_uevent_seq(md))) {
+ DMERR("%s: add_uevent_var() for DM_SEQNUM failed",
+- __FUNCTION__);
++ __func__);
+ goto err_add;
+ }
- 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);
+ if (add_uevent_var(&event->ku_env, "DM_PATH=%s", path)) {
+- DMERR("%s: add_uevent_var() for DM_PATH failed", __FUNCTION__);
++ DMERR("%s: add_uevent_var() for DM_PATH failed", __func__);
+ goto err_add;
+ }
-- 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;
+ if (add_uevent_var(&event->ku_env, "DM_NR_VALID_PATHS=%d",
+ nr_valid_paths)) {
+ DMERR("%s: add_uevent_var() for DM_NR_VALID_PATHS failed",
+- __FUNCTION__);
++ __func__);
+ goto err_add;
+ }
-@@ -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);
+@@ -146,25 +146,25 @@ void dm_send_uevents(struct list_head *events, struct kobject *kobj)
+ if (dm_copy_name_and_uuid(event->md, event->name,
+ event->uuid)) {
+ DMERR("%s: dm_copy_name_and_uuid() failed",
+- __FUNCTION__);
++ __func__);
+ goto uevent_free;
+ }
- get_ep(&ep->com);
+ if (add_uevent_var(&event->ku_env, "DM_NAME=%s", event->name)) {
+ DMERR("%s: add_uevent_var() for DM_NAME failed",
+- __FUNCTION__);
++ __func__);
+ goto uevent_free;
+ }
-@@ -1810,7 +1810,7 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ if (add_uevent_var(&event->ku_env, "DM_UUID=%s", event->uuid)) {
+ DMERR("%s: add_uevent_var() for DM_UUID failed",
+- __FUNCTION__);
++ __func__);
+ goto uevent_free;
+ }
- 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;
+ r = kobject_uevent_env(kobj, event->action, event->ku_env.envp);
+ if (r)
+- DMERR("%s: kobject_uevent_env failed", __FUNCTION__);
++ DMERR("%s: kobject_uevent_env failed", __func__);
+ uevent_free:
+ dm_uevent_free(event);
+ }
+@@ -187,7 +187,7 @@ void dm_path_uevent(enum dm_uevent_type event_type, struct dm_target *ti,
+ struct dm_uevent *event;
+
+ if (event_type >= ARRAY_SIZE(_dm_uevent_type_names)) {
+- DMERR("%s: Invalid event_type %d", __FUNCTION__, event_type);
++ DMERR("%s: Invalid event_type %d", __func__, event_type);
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)
+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,
+ };
- 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);
+@@ -212,6 +213,7 @@ static void (*_exits[])(void) = {
+ dm_target_exit,
+ dm_linear_exit,
+ dm_stripe_exit,
++ dm_kcopyd_exit,
+ dm_interface_exit,
+ };
-- PDBG("%s ep %p\n", __FUNCTION__, ep);
-+ PDBG("%s ep %p\n", __func__, ep);
+@@ -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;
- might_sleep();
- state_set(&ep->com, DEAD);
-@@ -1965,11 +1965,11 @@ int iwch_ep_disconnect(struct iwch_ep *ep, int abrupt, gfp_t gfp)
+@@ -955,7 +957,7 @@ out:
+ return r;
+ }
- spin_lock_irqsave(&ep->com.lock, flags);
+-static int next_free_minor(struct mapped_device *md, int *minor)
++static int next_free_minor(int *minor)
+ {
+ int r, m;
-- 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);
+@@ -966,9 +968,8 @@ static int next_free_minor(struct mapped_device *md, int *minor)
+ spin_lock(&_minor_lock);
- if (ep->com.state == DEAD) {
-- PDBG("%s already dead ep %p\n", __FUNCTION__, ep);
-+ PDBG("%s already dead ep %p\n", __func__, ep);
+ r = idr_get_new(&_minor_idr, MINOR_ALLOCED, &m);
+- if (r) {
++ if (r)
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); \
- }
+ 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;
- #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);
+ if (!md) {
+@@ -1004,13 +1005,12 @@ static struct mapped_device *alloc_dev(int minor)
- 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,
+ /* 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;
- 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;
- }
+- memset(md, 0, sizeof(*md));
+ init_rwsem(&md->io_lock);
+ mutex_init(&md->suspend_lock);
+ spin_lock_init(&md->pushback_lock);
+diff --git a/drivers/md/dm.h b/drivers/md/dm.h
+index b4584a3..8c03b63 100644
+--- a/drivers/md/dm.h
++++ b/drivers/md/dm.h
+@@ -16,67 +16,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/hdreg.h>
- 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;
+-#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);
}
-@@ -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;
- }
+-/*
+- * 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);
-@@ -163,7 +163,7 @@ int build_phys_page_list(struct ib_phys_buf *buffer_list,
- ((u64) j << *shift));
+ /*
+@@ -189,4 +100,13 @@ int dm_lock_for_deletion(struct mapped_device *md);
- 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);
+ void dm_kobject_uevent(struct mapped_device *md);
-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;
++/*
++ * Dirty log
++ */
++int dm_dirty_log_init(void);
++void dm_dirty_log_exit(void);
++
++int dm_kcopyd_init(void);
++void dm_kcopyd_exit(void);
++
+ #endif
+diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
+deleted file mode 100644
+index e76b52a..0000000
+--- a/drivers/md/kcopyd.c
++++ /dev/null
+@@ -1,708 +0,0 @@
+-/*
+- * Copyright (C) 2002 Sistina Software (UK) Limited.
+- * Copyright (C) 2006 Red Hat GmbH
+- *
+- * This file is released under the GPL.
+- *
+- * Kcopyd provides a simple interface for copying an area of one
+- * block-device to one or more other block-devices, with an asynchronous
+- * completion notification.
+- */
+-
+-#include <asm/types.h>
+-#include <asm/atomic.h>
+-
+-#include <linux/blkdev.h>
+-#include <linux/fs.h>
+-#include <linux/init.h>
+-#include <linux/list.h>
+-#include <linux/mempool.h>
+-#include <linux/module.h>
+-#include <linux/pagemap.h>
+-#include <linux/slab.h>
+-#include <linux/vmalloc.h>
+-#include <linux/workqueue.h>
+-#include <linux/mutex.h>
+-
+-#include "kcopyd.h"
+-
+-static struct workqueue_struct *_kcopyd_wq;
+-static struct work_struct _kcopyd_work;
+-
+-static void wake(void)
+-{
+- queue_work(_kcopyd_wq, &_kcopyd_work);
+-}
+-
+-/*-----------------------------------------------------------------
+- * Each kcopyd client has its own little pool of preallocated
+- * pages for kcopyd io.
+- *---------------------------------------------------------------*/
+-struct kcopyd_client {
+- struct list_head list;
+-
+- spinlock_t lock;
+- struct page_list *pages;
+- unsigned int nr_pages;
+- unsigned int nr_free_pages;
+-
+- struct dm_io_client *io_client;
+-
+- wait_queue_head_t destroyq;
+- atomic_t nr_jobs;
+-};
+-
+-static struct page_list *alloc_pl(void)
+-{
+- struct page_list *pl;
+-
+- pl = kmalloc(sizeof(*pl), GFP_KERNEL);
+- if (!pl)
+- return NULL;
+-
+- pl->page = alloc_page(GFP_KERNEL);
+- if (!pl->page) {
+- kfree(pl);
+- return NULL;
+- }
+-
+- return pl;
+-}
+-
+-static void free_pl(struct page_list *pl)
+-{
+- __free_page(pl->page);
+- kfree(pl);
+-}
+-
+-static int kcopyd_get_pages(struct kcopyd_client *kc,
+- unsigned int nr, struct page_list **pages)
+-{
+- struct page_list *pl;
+-
+- spin_lock(&kc->lock);
+- if (kc->nr_free_pages < nr) {
+- spin_unlock(&kc->lock);
+- return -ENOMEM;
+- }
+-
+- kc->nr_free_pages -= nr;
+- for (*pages = pl = kc->pages; --nr; pl = pl->next)
+- ;
+-
+- kc->pages = pl->next;
+- pl->next = NULL;
+-
+- spin_unlock(&kc->lock);
+-
+- return 0;
+-}
+-
+-static void kcopyd_put_pages(struct kcopyd_client *kc, struct page_list *pl)
+-{
+- struct page_list *cursor;
+-
+- spin_lock(&kc->lock);
+- for (cursor = pl; cursor->next; cursor = cursor->next)
+- kc->nr_free_pages++;
+-
+- kc->nr_free_pages++;
+- cursor->next = kc->pages;
+- kc->pages = pl;
+- spin_unlock(&kc->lock);
+-}
+-
+-/*
+- * These three functions resize the page pool.
+- */
+-static void drop_pages(struct page_list *pl)
+-{
+- struct page_list *next;
+-
+- while (pl) {
+- next = pl->next;
+- free_pl(pl);
+- pl = next;
+- }
+-}
+-
+-static int client_alloc_pages(struct kcopyd_client *kc, unsigned int nr)
+-{
+- unsigned int i;
+- struct page_list *pl = NULL, *next;
+-
+- for (i = 0; i < nr; i++) {
+- next = alloc_pl();
+- if (!next) {
+- if (pl)
+- drop_pages(pl);
+- return -ENOMEM;
+- }
+- next->next = pl;
+- pl = next;
+- }
+-
+- kcopyd_put_pages(kc, pl);
+- kc->nr_pages += nr;
+- return 0;
+-}
+-
+-static void client_free_pages(struct kcopyd_client *kc)
+-{
+- BUG_ON(kc->nr_free_pages != kc->nr_pages);
+- drop_pages(kc->pages);
+- kc->pages = NULL;
+- kc->nr_free_pages = kc->nr_pages = 0;
+-}
+-
+-/*-----------------------------------------------------------------
+- * kcopyd_jobs need to be allocated by the *clients* of kcopyd,
+- * for this reason we use a mempool to prevent the client from
+- * ever having to do io (which could cause a deadlock).
+- *---------------------------------------------------------------*/
+-struct kcopyd_job {
+- struct kcopyd_client *kc;
+- struct list_head list;
+- unsigned long flags;
+-
+- /*
+- * Error state of the job.
+- */
+- int read_err;
+- unsigned long write_err;
+-
+- /*
+- * Either READ or WRITE
+- */
+- int rw;
+- struct io_region source;
+-
+- /*
+- * The destinations for the transfer.
+- */
+- unsigned int num_dests;
+- struct io_region dests[KCOPYD_MAX_REGIONS];
+-
+- sector_t offset;
+- unsigned int nr_pages;
+- struct page_list *pages;
+-
+- /*
+- * Set this to ensure you are notified when the job has
+- * completed. 'context' is for callback to use.
+- */
+- kcopyd_notify_fn fn;
+- void *context;
+-
+- /*
+- * These fields are only used if the job has been split
+- * into more manageable parts.
+- */
+- struct mutex lock;
+- atomic_t sub_jobs;
+- sector_t progress;
+-};
+-
+-/* FIXME: this should scale with the number of pages */
+-#define MIN_JOBS 512
+-
+-static struct kmem_cache *_job_cache;
+-static mempool_t *_job_pool;
+-
+-/*
+- * We maintain three lists of jobs:
+- *
+- * i) jobs waiting for pages
+- * ii) jobs that have pages, and are waiting for the io to be issued.
+- * iii) jobs that have completed.
+- *
+- * All three of these are protected by job_lock.
+- */
+-static DEFINE_SPINLOCK(_job_lock);
+-
+-static LIST_HEAD(_complete_jobs);
+-static LIST_HEAD(_io_jobs);
+-static LIST_HEAD(_pages_jobs);
+-
+-static int jobs_init(void)
+-{
+- _job_cache = KMEM_CACHE(kcopyd_job, 0);
+- if (!_job_cache)
+- return -ENOMEM;
+-
+- _job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache);
+- if (!_job_pool) {
+- kmem_cache_destroy(_job_cache);
+- return -ENOMEM;
+- }
+-
+- return 0;
+-}
+-
+-static void jobs_exit(void)
+-{
+- BUG_ON(!list_empty(&_complete_jobs));
+- BUG_ON(!list_empty(&_io_jobs));
+- BUG_ON(!list_empty(&_pages_jobs));
+-
+- mempool_destroy(_job_pool);
+- kmem_cache_destroy(_job_cache);
+- _job_pool = NULL;
+- _job_cache = NULL;
+-}
+-
+-/*
+- * Functions to push and pop a job onto the head of a given job
+- * list.
+- */
+-static struct kcopyd_job *pop(struct list_head *jobs)
+-{
+- struct kcopyd_job *job = NULL;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&_job_lock, flags);
+-
+- if (!list_empty(jobs)) {
+- job = list_entry(jobs->next, struct kcopyd_job, list);
+- list_del(&job->list);
+- }
+- spin_unlock_irqrestore(&_job_lock, flags);
+-
+- return job;
+-}
+-
+-static void push(struct list_head *jobs, struct kcopyd_job *job)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&_job_lock, flags);
+- list_add_tail(&job->list, jobs);
+- spin_unlock_irqrestore(&_job_lock, flags);
+-}
+-
+-/*
+- * These three functions process 1 item from the corresponding
+- * job list.
+- *
+- * They return:
+- * < 0: error
+- * 0: success
+- * > 0: can't process yet.
+- */
+-static int run_complete_job(struct kcopyd_job *job)
+-{
+- void *context = job->context;
+- int read_err = job->read_err;
+- unsigned long write_err = job->write_err;
+- kcopyd_notify_fn fn = job->fn;
+- struct kcopyd_client *kc = job->kc;
+-
+- kcopyd_put_pages(kc, job->pages);
+- mempool_free(job, _job_pool);
+- fn(read_err, write_err, context);
+-
+- if (atomic_dec_and_test(&kc->nr_jobs))
+- wake_up(&kc->destroyq);
+-
+- return 0;
+-}
+-
+-static void complete_io(unsigned long error, void *context)
+-{
+- struct kcopyd_job *job = (struct kcopyd_job *) context;
+-
+- if (error) {
+- if (job->rw == WRITE)
+- job->write_err |= error;
+- else
+- job->read_err = 1;
+-
+- if (!test_bit(KCOPYD_IGNORE_ERROR, &job->flags)) {
+- push(&_complete_jobs, job);
+- wake();
+- return;
+- }
+- }
+-
+- if (job->rw == WRITE)
+- push(&_complete_jobs, job);
+-
+- else {
+- job->rw = WRITE;
+- push(&_io_jobs, job);
+- }
+-
+- wake();
+-}
+-
+-/*
+- * Request io on as many buffer heads as we can currently get for
+- * a particular job.
+- */
+-static int run_io_job(struct kcopyd_job *job)
+-{
+- int r;
+- struct dm_io_request io_req = {
+- .bi_rw = job->rw,
+- .mem.type = DM_IO_PAGE_LIST,
+- .mem.ptr.pl = job->pages,
+- .mem.offset = job->offset,
+- .notify.fn = complete_io,
+- .notify.context = job,
+- .client = job->kc->io_client,
+- };
+-
+- if (job->rw == READ)
+- r = dm_io(&io_req, 1, &job->source, NULL);
+- else
+- r = dm_io(&io_req, job->num_dests, job->dests, NULL);
+-
+- return r;
+-}
+-
+-static int run_pages_job(struct kcopyd_job *job)
+-{
+- int r;
+-
+- job->nr_pages = dm_div_up(job->dests[0].count + job->offset,
+- PAGE_SIZE >> 9);
+- r = kcopyd_get_pages(job->kc, job->nr_pages, &job->pages);
+- if (!r) {
+- /* this job is ready for io */
+- push(&_io_jobs, job);
+- return 0;
+- }
+-
+- if (r == -ENOMEM)
+- /* can't complete now */
+- return 1;
+-
+- return r;
+-}
+-
+-/*
+- * Run through a list for as long as possible. Returns the count
+- * of successful jobs.
+- */
+-static int process_jobs(struct list_head *jobs, int (*fn) (struct kcopyd_job *))
+-{
+- struct kcopyd_job *job;
+- int r, count = 0;
+-
+- while ((job = pop(jobs))) {
+-
+- r = fn(job);
+-
+- if (r < 0) {
+- /* error this rogue job */
+- if (job->rw == WRITE)
+- job->write_err = (unsigned long) -1L;
+- else
+- job->read_err = 1;
+- push(&_complete_jobs, job);
+- break;
+- }
+-
+- if (r > 0) {
+- /*
+- * We couldn't service this job ATM, so
+- * push this job back onto the list.
+- */
+- push(jobs, job);
+- break;
+- }
+-
+- count++;
+- }
+-
+- return count;
+-}
+-
+-/*
+- * kcopyd does this every time it's woken up.
+- */
+-static void do_work(struct work_struct *ignored)
+-{
+- /*
+- * The order that these are called is *very* important.
+- * complete jobs can free some pages for pages jobs.
+- * Pages jobs when successful will jump onto the io jobs
+- * list. io jobs call wake when they complete and it all
+- * starts again.
+- */
+- process_jobs(&_complete_jobs, run_complete_job);
+- process_jobs(&_pages_jobs, run_pages_job);
+- process_jobs(&_io_jobs, run_io_job);
+-}
+-
+-/*
+- * If we are copying a small region we just dispatch a single job
+- * to do the copy, otherwise the io has to be split up into many
+- * jobs.
+- */
+-static void dispatch_job(struct kcopyd_job *job)
+-{
+- atomic_inc(&job->kc->nr_jobs);
+- push(&_pages_jobs, job);
+- wake();
+-}
+-
+-#define SUB_JOB_SIZE 128
+-static void segment_complete(int read_err, unsigned long write_err,
+- void *context)
+-{
+- /* FIXME: tidy this function */
+- sector_t progress = 0;
+- sector_t count = 0;
+- struct kcopyd_job *job = (struct kcopyd_job *) context;
+-
+- mutex_lock(&job->lock);
+-
+- /* update the error */
+- if (read_err)
+- job->read_err = 1;
+-
+- if (write_err)
+- job->write_err |= write_err;
+-
+- /*
+- * Only dispatch more work if there hasn't been an error.
+- */
+- if ((!job->read_err && !job->write_err) ||
+- test_bit(KCOPYD_IGNORE_ERROR, &job->flags)) {
+- /* get the next chunk of work */
+- progress = job->progress;
+- count = job->source.count - progress;
+- if (count) {
+- if (count > SUB_JOB_SIZE)
+- count = SUB_JOB_SIZE;
+-
+- job->progress += count;
+- }
+- }
+- mutex_unlock(&job->lock);
+-
+- if (count) {
+- int i;
+- struct kcopyd_job *sub_job = mempool_alloc(_job_pool, GFP_NOIO);
+-
+- *sub_job = *job;
+- sub_job->source.sector += progress;
+- sub_job->source.count = count;
+-
+- for (i = 0; i < job->num_dests; i++) {
+- sub_job->dests[i].sector += progress;
+- sub_job->dests[i].count = count;
+- }
+-
+- sub_job->fn = segment_complete;
+- sub_job->context = job;
+- dispatch_job(sub_job);
+-
+- } else if (atomic_dec_and_test(&job->sub_jobs)) {
+-
+- /*
+- * To avoid a race we must keep the job around
+- * until after the notify function has completed.
+- * Otherwise the client may try and stop the job
+- * after we've completed.
+- */
+- job->fn(read_err, write_err, job->context);
+- mempool_free(job, _job_pool);
+- }
+-}
+-
+-/*
+- * Create some little jobs that will do the move between
+- * them.
+- */
+-#define SPLIT_COUNT 8
+-static void split_job(struct kcopyd_job *job)
+-{
+- int i;
+-
+- atomic_set(&job->sub_jobs, SPLIT_COUNT);
+- for (i = 0; i < SPLIT_COUNT; i++)
+- segment_complete(0, 0u, job);
+-}
+-
+-int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
+- unsigned int num_dests, struct io_region *dests,
+- unsigned int flags, kcopyd_notify_fn fn, void *context)
+-{
+- struct kcopyd_job *job;
+-
+- /*
+- * Allocate a new job.
+- */
+- job = mempool_alloc(_job_pool, GFP_NOIO);
+-
+- /*
+- * set up for the read.
+- */
+- job->kc = kc;
+- job->flags = flags;
+- job->read_err = 0;
+- job->write_err = 0;
+- job->rw = READ;
+-
+- job->source = *from;
+-
+- job->num_dests = num_dests;
+- memcpy(&job->dests, dests, sizeof(*dests) * num_dests);
+-
+- job->offset = 0;
+- job->nr_pages = 0;
+- job->pages = NULL;
+-
+- job->fn = fn;
+- job->context = context;
+-
+- if (job->source.count < SUB_JOB_SIZE)
+- dispatch_job(job);
+-
+- else {
+- mutex_init(&job->lock);
+- job->progress = 0;
+- split_job(job);
+- }
+-
+- return 0;
+-}
+-
+-/*
+- * Cancels a kcopyd job, eg. someone might be deactivating a
+- * mirror.
+- */
+-#if 0
+-int kcopyd_cancel(struct kcopyd_job *job, int block)
+-{
+- /* FIXME: finish */
+- return -1;
+-}
+-#endif /* 0 */
+-
+-/*-----------------------------------------------------------------
+- * Unit setup
+- *---------------------------------------------------------------*/
+-static DEFINE_MUTEX(_client_lock);
+-static LIST_HEAD(_clients);
+-
+-static void client_add(struct kcopyd_client *kc)
+-{
+- mutex_lock(&_client_lock);
+- list_add(&kc->list, &_clients);
+- mutex_unlock(&_client_lock);
+-}
+-
+-static void client_del(struct kcopyd_client *kc)
+-{
+- mutex_lock(&_client_lock);
+- list_del(&kc->list);
+- mutex_unlock(&_client_lock);
+-}
+-
+-static DEFINE_MUTEX(kcopyd_init_lock);
+-static int kcopyd_clients = 0;
+-
+-static int kcopyd_init(void)
+-{
+- int r;
+-
+- mutex_lock(&kcopyd_init_lock);
+-
+- if (kcopyd_clients) {
+- /* Already initialized. */
+- kcopyd_clients++;
+- mutex_unlock(&kcopyd_init_lock);
+- return 0;
+- }
+-
+- r = jobs_init();
+- if (r) {
+- mutex_unlock(&kcopyd_init_lock);
+- return r;
+- }
+-
+- _kcopyd_wq = create_singlethread_workqueue("kcopyd");
+- if (!_kcopyd_wq) {
+- jobs_exit();
+- mutex_unlock(&kcopyd_init_lock);
+- return -ENOMEM;
+- }
+-
+- kcopyd_clients++;
+- INIT_WORK(&_kcopyd_work, do_work);
+- mutex_unlock(&kcopyd_init_lock);
+- return 0;
+-}
+-
+-static void kcopyd_exit(void)
+-{
+- mutex_lock(&kcopyd_init_lock);
+- kcopyd_clients--;
+- if (!kcopyd_clients) {
+- jobs_exit();
+- destroy_workqueue(_kcopyd_wq);
+- _kcopyd_wq = NULL;
+- }
+- mutex_unlock(&kcopyd_init_lock);
+-}
+-
+-int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result)
+-{
+- int r = 0;
+- struct kcopyd_client *kc;
+-
+- r = kcopyd_init();
+- if (r)
+- return r;
+-
+- kc = kmalloc(sizeof(*kc), GFP_KERNEL);
+- if (!kc) {
+- kcopyd_exit();
+- return -ENOMEM;
+- }
+-
+- spin_lock_init(&kc->lock);
+- kc->pages = NULL;
+- kc->nr_pages = kc->nr_free_pages = 0;
+- r = client_alloc_pages(kc, nr_pages);
+- if (r) {
+- kfree(kc);
+- kcopyd_exit();
+- return r;
+- }
+-
+- kc->io_client = dm_io_client_create(nr_pages);
+- if (IS_ERR(kc->io_client)) {
+- r = PTR_ERR(kc->io_client);
+- client_free_pages(kc);
+- kfree(kc);
+- kcopyd_exit();
+- return r;
+- }
+-
+- init_waitqueue_head(&kc->destroyq);
+- atomic_set(&kc->nr_jobs, 0);
+-
+- client_add(kc);
+- *result = kc;
+- return 0;
+-}
+-
+-void kcopyd_client_destroy(struct kcopyd_client *kc)
+-{
+- /* Wait for completion of all jobs submitted by this client. */
+- wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs));
+-
+- dm_io_client_destroy(kc->io_client);
+- client_free_pages(kc);
+- client_del(kc);
+- kfree(kc);
+- kcopyd_exit();
+-}
+-
+-EXPORT_SYMBOL(kcopyd_client_create);
+-EXPORT_SYMBOL(kcopyd_client_destroy);
+-EXPORT_SYMBOL(kcopyd_copy);
+diff --git a/drivers/md/kcopyd.h b/drivers/md/kcopyd.h
+deleted file mode 100644
+index 4845f2a..0000000
+--- a/drivers/md/kcopyd.h
++++ /dev/null
+@@ -1,42 +0,0 @@
+-/*
+- * Copyright (C) 2001 Sistina Software
+- *
+- * This file is released under the GPL.
+- *
+- * Kcopyd provides a simple interface for copying an area of one
+- * block-device to one or more other block-devices, with an asynchronous
+- * completion notification.
+- */
+-
+-#ifndef DM_KCOPYD_H
+-#define DM_KCOPYD_H
+-
+-#include "dm-io.h"
+-
+-/* FIXME: make this configurable */
+-#define KCOPYD_MAX_REGIONS 8
+-
+-#define KCOPYD_IGNORE_ERROR 1
+-
+-/*
+- * To use kcopyd you must first create a kcopyd client object.
+- */
+-struct kcopyd_client;
+-int kcopyd_client_create(unsigned int num_pages, struct kcopyd_client **result);
+-void kcopyd_client_destroy(struct kcopyd_client *kc);
+-
+-/*
+- * Submit a copy job to kcopyd. This is built on top of the
+- * previous three fns.
+- *
+- * read_err is a boolean,
+- * write_err is a bitset, with 1 bit for each destination region
+- */
+-typedef void (*kcopyd_notify_fn)(int read_err, unsigned long write_err,
+- void *context);
+-
+-int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
+- unsigned int num_dests, struct io_region *dests,
+- unsigned int flags, kcopyd_notify_fn fn, void *context);
+-
+-#endif
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 61ccbd2..83eb78b 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -276,13 +276,15 @@ static mddev_t * mddev_find(dev_t unit)
+ init_waitqueue_head(&new->sb_wait);
+ new->reshape_position = MaxSector;
+ new->resync_max = MaxSector;
++ new->level = LEVEL_NONE;
-- 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);
+ new->queue = blk_alloc_queue(GFP_KERNEL);
+ if (!new->queue) {
+ kfree(new);
+ return NULL;
+ }
+- set_bit(QUEUE_FLAG_CLUSTER, &new->queue->queue_flags);
++ /* Can be unlocked because the queue is new: no concurrency */
++ queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, new->queue);
-- 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;
+ blk_queue_make_request(new->queue, md_fail_request);
-- PDBG("%s ib_cq %p\n", __FUNCTION__, ib_cq);
-+ PDBG("%s ib_cq %p\n", __func__, ib_cq);
- chp = to_iwch_cq(ib_cq);
+@@ -731,9 +733,9 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
+ else
+ rdev->desc_nr = sb->this_disk.number;
- 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;
+- if (refdev == 0)
++ if (!refdev) {
+ ret = 1;
+- else {
++ } else {
+ __u64 ev1, ev2;
+ mdp_super_t *refsb = (mdp_super_t*)page_address(refdev->sb_page);
+ if (!uuid_equal(refsb, sb)) {
+@@ -1116,9 +1118,9 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
+ else
+ rdev->desc_nr = le32_to_cpu(sb->dev_number);
-- 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;
+- if (refdev == 0)
++ if (!refdev) {
+ ret = 1;
+- else {
++ } else {
+ __u64 ev1, ev2;
+ struct mdp_superblock_1 *refsb =
+ (struct mdp_superblock_1*)page_address(refdev->sb_page);
+@@ -1368,6 +1370,11 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
+ MD_BUG();
+ return -EINVAL;
+ }
++
++ /* prevent duplicates */
++ if (find_rdev(mddev, rdev->bdev->bd_dev))
++ return -EEXIST;
++
+ /* make sure rdev->size exceeds mddev->size */
+ if (rdev->size && (mddev->size == 0 || rdev->size < mddev->size)) {
+ if (mddev->pers) {
+@@ -1651,6 +1658,8 @@ static void md_update_sb(mddev_t * mddev, int force_change)
+ int sync_req;
+ int nospares = 0;
-- PDBG("%s ib_cq %p cqe %d\n", __FUNCTION__, cq, cqe);
-+ PDBG("%s ib_cq %p cqe %d\n", __func__, cq, cqe);
++ if (mddev->external)
++ return;
+ repeat:
+ spin_lock_irq(&mddev->write_lock);
- /* 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);
+@@ -1819,6 +1828,10 @@ state_show(mdk_rdev_t *rdev, char *page)
+ len += sprintf(page+len, "%swrite_mostly",sep);
+ sep = ",";
+ }
++ if (test_bit(Blocked, &rdev->flags)) {
++ len += sprintf(page+len, "%sblocked", sep);
++ sep = ",";
++ }
+ if (!test_bit(Faulty, &rdev->flags) &&
+ !test_bit(In_sync, &rdev->flags)) {
+ len += sprintf(page+len, "%sspare", sep);
+@@ -1835,6 +1848,8 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+ * remove - disconnects the device
+ * writemostly - sets write_mostly
+ * -writemostly - clears write_mostly
++ * blocked - sets the Blocked flag
++ * -blocked - clears the Blocked flag
+ */
+ int err = -EINVAL;
+ if (cmd_match(buf, "faulty") && rdev->mddev->pers) {
+@@ -1857,6 +1872,16 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+ } else if (cmd_match(buf, "-writemostly")) {
+ clear_bit(WriteMostly, &rdev->flags);
+ err = 0;
++ } else if (cmd_match(buf, "blocked")) {
++ set_bit(Blocked, &rdev->flags);
++ err = 0;
++ } else if (cmd_match(buf, "-blocked")) {
++ clear_bit(Blocked, &rdev->flags);
++ wake_up(&rdev->blocked_wait);
++ set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery);
++ md_wakeup_thread(rdev->mddev->thread);
++
++ err = 0;
+ }
+ return err ? err : len;
+ }
+@@ -2096,7 +2121,7 @@ rdev_attr_store(struct kobject *kobj, struct attribute *attr,
+ rv = -EBUSY;
+ else
+ rv = entry->store(rdev, page, length);
+- mddev_unlock(rdev->mddev);
++ mddev_unlock(mddev);
+ }
+ return rv;
+ }
+@@ -2185,7 +2210,9 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
+ goto abort_free;
+ }
}
++
+ INIT_LIST_HEAD(&rdev->same_set);
++ init_waitqueue_head(&rdev->blocked_wait);
- /* 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;
+ return rdev;
-- 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);
+@@ -2456,7 +2483,6 @@ resync_start_show(mddev_t *mddev, char *page)
+ static ssize_t
+ resync_start_store(mddev_t *mddev, const char *buf, size_t len)
+ {
+- /* can only set chunk_size if array is not yet active */
+ char *e;
+ unsigned long long n = simple_strtoull(buf, &e, 10);
- if (vma->vm_start & (PAGE_SIZE-1)) {
-@@ -390,7 +390,7 @@ static int iwch_deallocate_pd(struct ib_pd *pd)
+@@ -2590,15 +2616,20 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
+ err = do_md_stop(mddev, 1);
+ else {
+ mddev->ro = 1;
++ set_disk_ro(mddev->gendisk, 1);
+ err = do_md_run(mddev);
+ }
+ break;
+ case read_auto:
+- /* stopping an active array */
+ if (mddev->pers) {
+- err = do_md_stop(mddev, 1);
+- if (err == 0)
+- mddev->ro = 2; /* FIXME mark devices writable */
++ if (mddev->ro != 1)
++ err = do_md_stop(mddev, 1);
++ else
++ err = restart_array(mddev);
++ if (err == 0) {
++ mddev->ro = 2;
++ set_disk_ro(mddev->gendisk, 0);
++ }
+ } else {
+ mddev->ro = 2;
+ err = do_md_run(mddev);
+@@ -2611,6 +2642,8 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
+ if (atomic_read(&mddev->writes_pending) == 0) {
+ if (mddev->in_sync == 0) {
+ mddev->in_sync = 1;
++ if (mddev->safemode == 1)
++ mddev->safemode = 0;
+ if (mddev->persistent)
+ set_bit(MD_CHANGE_CLEAN,
+ &mddev->flags);
+@@ -2634,6 +2667,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
+ err = 0;
+ } else {
+ mddev->ro = 0;
++ set_disk_ro(mddev->gendisk, 0);
+ err = do_md_run(mddev);
+ }
+ break;
+@@ -3711,6 +3745,30 @@ static int do_md_stop(mddev_t * mddev, int mode)
+ mddev->reshape_position = MaxSector;
+ mddev->external = 0;
+ mddev->persistent = 0;
++ mddev->level = LEVEL_NONE;
++ mddev->clevel[0] = 0;
++ mddev->flags = 0;
++ mddev->ro = 0;
++ mddev->metadata_type[0] = 0;
++ mddev->chunk_size = 0;
++ mddev->ctime = mddev->utime = 0;
++ mddev->layout = 0;
++ mddev->max_disks = 0;
++ mddev->events = 0;
++ mddev->delta_disks = 0;
++ mddev->new_level = LEVEL_NONE;
++ mddev->new_layout = 0;
++ mddev->new_chunk = 0;
++ mddev->curr_resync = 0;
++ mddev->resync_mismatches = 0;
++ mddev->suspend_lo = mddev->suspend_hi = 0;
++ mddev->sync_speed_min = mddev->sync_speed_max = 0;
++ mddev->recovery = 0;
++ mddev->in_sync = 0;
++ mddev->changed = 0;
++ mddev->degraded = 0;
++ mddev->barriers_work = 0;
++ mddev->safemode = 0;
+
+ } else if (mddev->pers)
+ printk(KERN_INFO "md: %s switched to read-only mode.\n",
+@@ -4152,7 +4210,7 @@ static int hot_remove_disk(mddev_t * mddev, dev_t dev)
- 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;
+ 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;
+ }
+@@ -4918,6 +4976,9 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
-- 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);
- }
+ if (!rdev || test_bit(Faulty, &rdev->flags))
+ return;
++
++ if (mddev->external)
++ set_bit(Blocked, &rdev->flags);
+ /*
+ dprintk("md_error dev:%s, rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",
+ mdname(mddev),
+@@ -5364,6 +5425,8 @@ void md_write_start(mddev_t *mddev, struct bio *bi)
+ md_wakeup_thread(mddev->sync_thread);
+ }
+ atomic_inc(&mddev->writes_pending);
++ if (mddev->safemode == 1)
++ mddev->safemode = 0;
+ if (mddev->in_sync) {
+ spin_lock_irq(&mddev->write_lock);
+ if (mddev->in_sync) {
+@@ -5718,7 +5781,7 @@ static int remove_and_add_spares(mddev_t *mddev)
+
+ rdev_for_each(rdev, rtmp, mddev)
+ if (rdev->raid_disk >= 0 &&
+- !mddev->external &&
++ !test_bit(Blocked, &rdev->flags) &&
+ (test_bit(Faulty, &rdev->flags) ||
+ ! test_bit(In_sync, &rdev->flags)) &&
+ atomic_read(&rdev->nr_pending)==0) {
+@@ -5788,7 +5851,7 @@ void md_check_recovery(mddev_t *mddev)
+ return;
+
+ if (signal_pending(current)) {
+- if (mddev->pers->sync_request) {
++ if (mddev->pers->sync_request && !mddev->external) {
+ printk(KERN_INFO "md: %s in immediate safe mode\n",
+ mdname(mddev));
+ mddev->safemode = 2;
+@@ -5800,7 +5863,7 @@ void md_check_recovery(mddev_t *mddev)
+ (mddev->flags && !mddev->external) ||
+ test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
+ test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
+- (mddev->safemode == 1) ||
++ (mddev->external == 0 && mddev->safemode == 1) ||
+ (mddev->safemode == 2 && ! atomic_read(&mddev->writes_pending)
+ && !mddev->in_sync && mddev->recovery_cp == MaxSector)
+ ))
+@@ -5809,16 +5872,20 @@ void md_check_recovery(mddev_t *mddev)
+ if (mddev_trylock(mddev)) {
+ int spares = 0;
+
+- spin_lock_irq(&mddev->write_lock);
+- if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
+- !mddev->in_sync && mddev->recovery_cp == MaxSector) {
+- mddev->in_sync = 1;
+- if (mddev->persistent)
+- set_bit(MD_CHANGE_CLEAN, &mddev->flags);
++ if (!mddev->external) {
++ spin_lock_irq(&mddev->write_lock);
++ if (mddev->safemode &&
++ !atomic_read(&mddev->writes_pending) &&
++ !mddev->in_sync &&
++ mddev->recovery_cp == MaxSector) {
++ mddev->in_sync = 1;
++ if (mddev->persistent)
++ set_bit(MD_CHANGE_CLEAN, &mddev->flags);
++ }
++ if (mddev->safemode == 1)
++ mddev->safemode = 0;
++ spin_unlock_irq(&mddev->write_lock);
+ }
+- if (mddev->safemode == 1)
+- mddev->safemode = 0;
+- spin_unlock_irq(&mddev->write_lock);
+
+ if (mddev->flags)
+ md_update_sb(mddev, 0);
+@@ -5913,6 +5980,16 @@ void md_check_recovery(mddev_t *mddev)
+ }
+ }
+
++void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
++{
++ sysfs_notify(&rdev->kobj, NULL, "state");
++ wait_event_timeout(rdev->blocked_wait,
++ !test_bit(Blocked, &rdev->flags),
++ msecs_to_jiffies(5000));
++ rdev_dec_pending(rdev, mddev);
++}
++EXPORT_SYMBOL(md_wait_for_blocked_rdev);
++
+ static int md_notify_reboot(struct notifier_block *this,
+ unsigned long code, void *x)
+ {
+@@ -5947,13 +6024,9 @@ static struct notifier_block md_notifier = {
+
+ static void md_geninit(void)
+ {
+- struct proc_dir_entry *p;
+-
+ dprintk("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t));
+
+- p = create_proc_entry("mdstat", S_IRUGO, NULL);
+- if (p)
+- p->proc_fops = &md_seq_fops;
++ proc_create("mdstat", S_IRUGO, NULL, &md_seq_fops);
+ }
+
+ static int __init md_init(void)
+diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
+index 3f299d8..42ee1a2 100644
+--- a/drivers/md/multipath.c
++++ b/drivers/md/multipath.c
+@@ -244,7 +244,8 @@ static void multipath_error (mddev_t *mddev, mdk_rdev_t *rdev)
+ conf->working_disks--;
+ mddev->degraded++;
+ printk(KERN_ALERT "multipath: IO failure on %s,"
+- " disabling IO path. \n Operation continuing"
++ " disabling IO path.\n"
++ "multipath: Operation continuing"
+ " on %d IO paths.\n",
+ bdevname (rdev->bdev,b),
+ conf->working_disks);
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index ff61b30..6778b7c 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -773,7 +773,6 @@ static int make_request(struct request_queue *q, struct bio * bio)
+ r1bio_t *r1_bio;
+ struct bio *read_bio;
+ int i, targets = 0, disks;
+- mdk_rdev_t *rdev;
+ struct bitmap *bitmap = mddev->bitmap;
+ unsigned long flags;
+ struct bio_list bl;
+@@ -781,6 +780,7 @@ static int make_request(struct request_queue *q, struct bio * bio)
+ const int rw = bio_data_dir(bio);
+ const int do_sync = bio_sync(bio);
+ int do_barriers;
++ mdk_rdev_t *blocked_rdev;
+
+ /*
+ * Register the new request and wait if the reconstruction
+@@ -862,10 +862,17 @@ static int make_request(struct request_queue *q, struct bio * bio)
+ first = 0;
}
-- 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;
- }
+ #endif
++ retry_write:
++ blocked_rdev = NULL;
+ rcu_read_lock();
+ for (i = 0; i < disks; i++) {
+- if ((rdev=rcu_dereference(conf->mirrors[i].rdev)) != NULL &&
+- !test_bit(Faulty, &rdev->flags)) {
++ mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
++ if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
++ atomic_inc(&rdev->nr_pending);
++ blocked_rdev = rdev;
++ break;
++ }
++ if (rdev && !test_bit(Faulty, &rdev->flags)) {
+ atomic_inc(&rdev->nr_pending);
+ if (test_bit(Faulty, &rdev->flags)) {
+ rdev_dec_pending(rdev, mddev);
+@@ -878,6 +885,20 @@ static int make_request(struct request_queue *q, struct bio * bio)
+ }
+ rcu_read_unlock();
-@@ -432,7 +432,7 @@ static int iwch_dereg_mr(struct ib_mr *ib_mr)
- struct iwch_mr *mhp;
- u32 mmid;
++ if (unlikely(blocked_rdev)) {
++ /* Wait for this device to become unblocked */
++ int j;
++
++ for (j = 0; j < i; j++)
++ if (r1_bio->bios[j])
++ rdev_dec_pending(conf->mirrors[j].rdev, mddev);
++
++ allow_barrier(conf);
++ md_wait_for_blocked_rdev(blocked_rdev, mddev);
++ wait_barrier(conf);
++ goto retry_write;
++ }
++
+ BUG_ON(targets == 0); /* we never fail the last device */
-- 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;
+ if (targets < conf->raid_disks) {
+@@ -1008,8 +1029,8 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
+ } else
+ set_bit(Faulty, &rdev->flags);
+ set_bit(MD_CHANGE_DEVS, &mddev->flags);
+- printk(KERN_ALERT "raid1: Disk failure on %s, disabling device. \n"
+- " Operation continuing on %d devices\n",
++ printk(KERN_ALERT "raid1: Disk failure on %s, disabling device.\n"
++ "raid1: Operation continuing on %d devices.\n",
+ bdevname(rdev->bdev,b), conf->raid_disks - mddev->degraded);
+ }
+
+diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
+index 32389d2..5938fa9 100644
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -790,6 +790,7 @@ static int make_request(struct request_queue *q, struct bio * bio)
+ const int do_sync = bio_sync(bio);
+ struct bio_list bl;
+ unsigned long flags;
++ mdk_rdev_t *blocked_rdev;
-- PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
-+ PDBG("%s ib_pd %p\n", __func__, pd);
- php = to_iwch_pd(pd);
- rhp = php->rhp;
+ if (unlikely(bio_barrier(bio))) {
+ bio_endio(bio, -EOPNOTSUPP);
+@@ -879,17 +880,23 @@ static int make_request(struct request_queue *q, struct bio * bio)
+ /*
+ * WRITE:
+ */
+- /* first select target devices under spinlock and
++ /* first select target devices under rcu_lock and
+ * inc refcount on their rdev. Record them by setting
+ * bios[x] to bio
+ */
+ raid10_find_phys(conf, r10_bio);
++ retry_write:
++ blocked_rdev = 0;
+ rcu_read_lock();
+ for (i = 0; i < conf->copies; i++) {
+ int d = r10_bio->devs[i].devnum;
+ mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[d].rdev);
+- if (rdev &&
+- !test_bit(Faulty, &rdev->flags)) {
++ if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
++ atomic_inc(&rdev->nr_pending);
++ blocked_rdev = rdev;
++ break;
++ }
++ if (rdev && !test_bit(Faulty, &rdev->flags)) {
+ atomic_inc(&rdev->nr_pending);
+ r10_bio->devs[i].bio = bio;
+ } else {
+@@ -899,6 +906,22 @@ static int make_request(struct request_queue *q, struct bio * bio)
+ }
+ rcu_read_unlock();
-@@ -531,7 +531,7 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr,
- int npages;
- int ret;
++ if (unlikely(blocked_rdev)) {
++ /* Have to wait for this device to get unblocked, then retry */
++ int j;
++ int d;
++
++ for (j = 0; j < i; j++)
++ if (r10_bio->devs[j].bio) {
++ d = r10_bio->devs[j].devnum;
++ rdev_dec_pending(conf->mirrors[d].rdev, mddev);
++ }
++ allow_barrier(conf);
++ md_wait_for_blocked_rdev(blocked_rdev, mddev);
++ wait_barrier(conf);
++ goto retry_write;
++ }
++
+ atomic_set(&r10_bio->remaining, 0);
+
+ bio_list_init(&bl);
+@@ -1001,8 +1024,8 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
+ }
+ set_bit(Faulty, &rdev->flags);
+ set_bit(MD_CHANGE_DEVS, &mddev->flags);
+- printk(KERN_ALERT "raid10: Disk failure on %s, disabling device. \n"
+- " Operation continuing on %d devices\n",
++ printk(KERN_ALERT "raid10: Disk failure on %s, disabling device.\n"
++ "raid10: Operation continuing on %d devices.\n",
+ bdevname(rdev->bdev,b), conf->raid_disks - mddev->degraded);
+ }
+
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index b162b83..087eee0 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -63,6 +63,7 @@
+ #define STRIPE_SHIFT (PAGE_SHIFT - 9)
+ #define STRIPE_SECTORS (STRIPE_SIZE>>9)
+ #define IO_THRESHOLD 1
++#define BYPASS_THRESHOLD 1
+ #define NR_HASH (PAGE_SIZE / sizeof(struct hlist_head))
+ #define HASH_MASK (NR_HASH - 1)
-- PDBG("%s ib_mr %p ib_pd %p\n", __FUNCTION__, mr, pd);
-+ PDBG("%s ib_mr %p ib_pd %p\n", __func__, mr, pd);
+@@ -398,6 +399,7 @@ static void ops_run_io(struct stripe_head *sh)
- /* 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;
+ might_sleep();
-- PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
-+ PDBG("%s ib_pd %p\n", __func__, pd);
++ set_bit(STRIPE_IO_STARTED, &sh->state);
+ for (i = disks; i--; ) {
+ int rw;
+ struct bio *bi;
+@@ -433,7 +435,7 @@ static void ops_run_io(struct stripe_head *sh)
+
+ bi->bi_bdev = rdev->bdev;
+ pr_debug("%s: for %llu schedule op %ld on disc %d\n",
+- __FUNCTION__, (unsigned long long)sh->sector,
++ __func__, (unsigned long long)sh->sector,
+ bi->bi_rw, i);
+ atomic_inc(&sh->count);
+ bi->bi_sector = sh->sector + rdev->data_offset;
+@@ -520,7 +522,7 @@ static void ops_complete_biofill(void *stripe_head_ref)
+ raid5_conf_t *conf = sh->raid_conf;
+ int i;
- 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);
+- pr_debug("%s: stripe %llu\n", __FUNCTION__,
++ pr_debug("%s: stripe %llu\n", __func__,
+ (unsigned long long)sh->sector);
+
+ /* clear completed biofills */
+@@ -569,7 +571,7 @@ static void ops_run_biofill(struct stripe_head *sh)
+ raid5_conf_t *conf = sh->raid_conf;
+ int i;
- 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;
+- pr_debug("%s: stripe %llu\n", __FUNCTION__,
++ pr_debug("%s: stripe %llu\n", __func__,
+ (unsigned long long)sh->sector);
+
+ for (i = sh->disks; i--; ) {
+@@ -600,7 +602,7 @@ static void ops_complete_compute5(void *stripe_head_ref)
+ int target = sh->ops.target;
+ struct r5dev *tgt = &sh->dev[target];
+
+- pr_debug("%s: stripe %llu\n", __FUNCTION__,
++ pr_debug("%s: stripe %llu\n", __func__,
+ (unsigned long long)sh->sector);
-- PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
-+ PDBG("%s ib_pd %p\n", __func__, pd);
+ set_bit(R5_UPTODATE, &tgt->flags);
+@@ -625,7 +627,7 @@ ops_run_compute5(struct stripe_head *sh, unsigned long pending)
+ int i;
- /*
- * 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);
- }
+ pr_debug("%s: stripe %llu block: %d\n",
+- __FUNCTION__, (unsigned long long)sh->sector, target);
++ __func__, (unsigned long long)sh->sector, target);
+ BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));
-@@ -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;
- }
+ for (i = disks; i--; )
+@@ -653,7 +655,7 @@ static void ops_complete_prexor(void *stripe_head_ref)
+ {
+ struct stripe_head *sh = stripe_head_ref;
-@@ -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);
+- pr_debug("%s: stripe %llu\n", __FUNCTION__,
++ pr_debug("%s: stripe %llu\n", __func__,
+ (unsigned long long)sh->sector);
-- 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;
+ set_bit(STRIPE_OP_PREXOR, &sh->ops.complete);
+@@ -670,7 +672,7 @@ ops_run_prexor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+ /* existing parity data subtracted */
+ struct page *xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
-- 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;
+- pr_debug("%s: stripe %llu\n", __FUNCTION__,
++ pr_debug("%s: stripe %llu\n", __func__,
+ (unsigned long long)sh->sector);
-- PDBG("%s ib_qp %p\n", __FUNCTION__, ibqp);
-+ PDBG("%s ib_qp %p\n", __func__, ibqp);
+ for (i = disks; i--; ) {
+@@ -699,7 +701,7 @@ ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
+ */
+ int prexor = test_bit(STRIPE_OP_PREXOR, &pending);
- /* 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,
+- pr_debug("%s: stripe %llu\n", __FUNCTION__,
++ pr_debug("%s: stripe %llu\n", __func__,
+ (unsigned long long)sh->sector);
- void iwch_qp_add_ref(struct ib_qp *qp)
+ for (i = disks; i--; ) {
+@@ -744,7 +746,7 @@ static void ops_complete_postxor(void *stripe_head_ref)
{
-- PDBG("%s ib_qp %p\n", __FUNCTION__, qp);
-+ PDBG("%s ib_qp %p\n", __func__, qp);
- atomic_inc(&(to_iwch_qp(qp)->refcnt));
- }
+ struct stripe_head *sh = stripe_head_ref;
- 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));
- }
+- pr_debug("%s: stripe %llu\n", __FUNCTION__,
++ pr_debug("%s: stripe %llu\n", __func__,
+ (unsigned long long)sh->sector);
- 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);
- }
+ set_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+@@ -757,7 +759,7 @@ static void ops_complete_write(void *stripe_head_ref)
+ struct stripe_head *sh = stripe_head_ref;
+ int disks = sh->disks, i, pd_idx = sh->pd_idx;
-@@ -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;
+- pr_debug("%s: stripe %llu\n", __FUNCTION__,
++ pr_debug("%s: stripe %llu\n", __func__,
+ (unsigned long long)sh->sector);
+
+ for (i = disks; i--; ) {
+@@ -787,7 +789,7 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
+ unsigned long flags;
+ dma_async_tx_callback callback;
+
+- pr_debug("%s: stripe %llu\n", __FUNCTION__,
++ pr_debug("%s: stripe %llu\n", __func__,
+ (unsigned long long)sh->sector);
+
+ /* check if prexor is active which means only process blocks
+@@ -837,7 +839,7 @@ static void ops_complete_check(void *stripe_head_ref)
+ struct stripe_head *sh = stripe_head_ref;
+ int pd_idx = sh->pd_idx;
+
+- pr_debug("%s: stripe %llu\n", __FUNCTION__,
++ pr_debug("%s: stripe %llu\n", __func__,
+ (unsigned long long)sh->sector);
+
+ if (test_and_clear_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending) &&
+@@ -859,7 +861,7 @@ static void ops_run_check(struct stripe_head *sh)
+ int count = 0, pd_idx = sh->pd_idx, i;
+ struct page *xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
+
+- pr_debug("%s: stripe %llu\n", __FUNCTION__,
++ pr_debug("%s: stripe %llu\n", __func__,
+ (unsigned long long)sh->sector);
+
+ for (i = disks; i--; ) {
+@@ -1260,8 +1262,8 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
+ }
+ set_bit(Faulty, &rdev->flags);
+ printk (KERN_ALERT
+- "raid5: Disk failure on %s, disabling device."
+- " Operation continuing on %d devices\n",
++ "raid5: Disk failure on %s, disabling device.\n"
++ "raid5: Operation continuing on %d devices.\n",
+ bdevname(rdev->bdev,b), conf->raid_disks - mddev->degraded);
+ }
}
-@@ -977,7 +977,7 @@ static int iwch_query_gid(struct ib_device *ibdev, u8 port,
- struct iwch_dev *dev;
+@@ -1720,6 +1722,9 @@ handle_write_operations5(struct stripe_head *sh, int rcw, int expand)
+ locked++;
+ }
+ }
++ if (locked + 1 == disks)
++ if (!test_and_set_bit(STRIPE_FULL_WRITE, &sh->state))
++ atomic_inc(&sh->raid_conf->pending_full_writes);
+ } else {
+ BUG_ON(!(test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags) ||
+ test_bit(R5_Wantcompute, &sh->dev[pd_idx].flags)));
+@@ -1759,7 +1764,7 @@ handle_write_operations5(struct stripe_head *sh, int rcw, int expand)
+ locked++;
- 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,
- {
+ pr_debug("%s: stripe %llu locked: %d pending: %lx\n",
+- __FUNCTION__, (unsigned long long)sh->sector,
++ __func__, (unsigned long long)sh->sector,
+ locked, sh->ops.pending);
- struct iwch_dev *dev;
-- PDBG("%s ibdev %p\n", __FUNCTION__, ibdev);
-+ PDBG("%s ibdev %p\n", __func__, ibdev);
+ return locked;
+@@ -1947,6 +1952,9 @@ handle_requests_to_failed_array(raid5_conf_t *conf, struct stripe_head *sh,
+ STRIPE_SECTORS, 0, 0);
+ }
- 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;
++ if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state))
++ if (atomic_dec_and_test(&conf->pending_full_writes))
++ md_wakeup_thread(conf->mddev->thread);
}
--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);
+ /* __handle_issuing_new_read_requests5 - returns 0 if there are no more disks
+@@ -2149,6 +2157,10 @@ static void handle_completed_write_requests(raid5_conf_t *conf,
+ 0);
+ }
+ }
++
++ if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state))
++ if (atomic_dec_and_test(&conf->pending_full_writes))
++ md_wakeup_thread(conf->mddev->thread);
}
--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;
+ static void handle_issuing_new_write_requests5(raid5_conf_t *conf,
+@@ -2333,6 +2345,9 @@ static void handle_issuing_new_write_requests6(raid5_conf_t *conf,
+ s->locked++;
+ set_bit(R5_Wantwrite, &sh->dev[i].flags);
+ }
++ if (s->locked == disks)
++ if (!test_and_set_bit(STRIPE_FULL_WRITE, &sh->state))
++ atomic_inc(&conf->pending_full_writes);
+ /* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
+ set_bit(STRIPE_INSYNC, &sh->state);
-- 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);
+@@ -2592,6 +2607,7 @@ static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh,
+ }
}
--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;
++
+ /*
+ * handle_stripe - do things to a stripe.
+ *
+@@ -2617,6 +2633,7 @@ static void handle_stripe5(struct stripe_head *sh)
+ struct stripe_head_state s;
+ struct r5dev *dev;
+ unsigned long pending = 0;
++ mdk_rdev_t *blocked_rdev = NULL;
-- 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);
- }
+ memset(&s, 0, sizeof(s));
+ pr_debug("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d "
+@@ -2676,6 +2693,11 @@ static void handle_stripe5(struct stripe_head *sh)
+ if (dev->written)
+ s.written++;
+ rdev = rcu_dereference(conf->disks[i].rdev);
++ if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
++ blocked_rdev = rdev;
++ atomic_inc(&rdev->nr_pending);
++ break;
++ }
+ if (!rdev || !test_bit(In_sync, &rdev->flags)) {
+ /* The ReadError flag will just be confusing now */
+ clear_bit(R5_ReadError, &dev->flags);
+@@ -2690,6 +2712,11 @@ static void handle_stripe5(struct stripe_head *sh)
+ }
+ rcu_read_unlock();
--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);
- }
++ if (unlikely(blocked_rdev)) {
++ set_bit(STRIPE_HANDLE, &sh->state);
++ goto unlock;
++ }
++
+ if (s.to_fill && !test_and_set_bit(STRIPE_OP_BIOFILL, &sh->ops.pending))
+ sh->ops.count++;
--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);
+@@ -2879,8 +2906,13 @@ static void handle_stripe5(struct stripe_head *sh)
+ if (sh->ops.count)
+ pending = get_stripe_work(sh);
--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
- };
++ unlock:
+ spin_unlock(&sh->lock);
- int iwch_register_device(struct iwch_dev *dev)
-@@ -1103,14 +1102,13 @@ int iwch_register_device(struct iwch_dev *dev)
- int ret;
- int i;
++ /* wait for this device to become unblocked */
++ if (unlikely(blocked_rdev))
++ md_wait_for_blocked_rdev(blocked_rdev, conf->mddev);
++
+ if (pending)
+ raid5_run_ops(sh, pending);
+
+@@ -2897,6 +2929,7 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
+ struct stripe_head_state s;
+ struct r6_state r6s;
+ struct r5dev *dev, *pdev, *qdev;
++ mdk_rdev_t *blocked_rdev = NULL;
+
+ r6s.qd_idx = raid6_next_disk(pd_idx, disks);
+ pr_debug("handling stripe %llu, state=%#lx cnt=%d, "
+@@ -2960,6 +2993,11 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
+ if (dev->written)
+ s.written++;
+ rdev = rcu_dereference(conf->disks[i].rdev);
++ if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
++ blocked_rdev = rdev;
++ atomic_inc(&rdev->nr_pending);
++ break;
++ }
+ if (!rdev || !test_bit(In_sync, &rdev->flags)) {
+ /* The ReadError flag will just be confusing now */
+ clear_bit(R5_ReadError, &dev->flags);
+@@ -2974,6 +3012,11 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
+ set_bit(R5_Insync, &dev->flags);
+ }
+ rcu_read_unlock();
++
++ if (unlikely(blocked_rdev)) {
++ set_bit(STRIPE_HANDLE, &sh->state);
++ goto unlock;
++ }
+ pr_debug("locked=%d uptodate=%d to_read=%d"
+ " to_write=%d failed=%d failed_num=%d,%d\n",
+ s.locked, s.uptodate, s.to_read, s.to_write, s.failed,
+@@ -3079,8 +3122,13 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
+ !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending))
+ handle_stripe_expansion(conf, sh, &r6s);
-- 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);
++ unlock:
+ spin_unlock(&sh->lock);
- 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;
++ /* wait for this device to become unblocked */
++ if (unlikely(blocked_rdev))
++ md_wait_for_blocked_rdev(blocked_rdev, conf->mddev);
++
+ return_io(return_bi);
- 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;
+ for (i=disks; i-- ;) {
+@@ -3094,6 +3142,8 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
+ else
+ continue;
-- 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;
++ set_bit(STRIPE_IO_STARTED, &sh->state);
++
+ bi = &sh->dev[i].req;
+
+ bi->bi_rw = rw;
+@@ -3164,7 +3214,7 @@ static void raid5_activate_delayed(raid5_conf_t *conf)
+ clear_bit(STRIPE_DELAYED, &sh->state);
+ if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
+ atomic_inc(&conf->preread_active_stripes);
+- list_add_tail(&sh->lru, &conf->handle_list);
++ list_add_tail(&sh->lru, &conf->hold_list);
}
-@@ -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,
+ } else
+ blk_plug_device(conf->mddev->queue);
+@@ -3442,6 +3492,58 @@ static int chunk_aligned_read(struct request_queue *q, struct bio * raid_bio)
+ }
+ }
- 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,
++/* __get_priority_stripe - get the next stripe to process
++ *
++ * Full stripe writes are allowed to pass preread active stripes up until
++ * the bypass_threshold is exceeded. In general the bypass_count
++ * increments when the handle_list is handled before the hold_list; however, it
++ * will not be incremented when STRIPE_IO_STARTED is sampled set signifying a
++ * stripe with in flight i/o. The bypass_count will be reset when the
++ * head of the hold_list has changed, i.e. the head was promoted to the
++ * handle_list.
++ */
++static struct stripe_head *__get_priority_stripe(raid5_conf_t *conf)
++{
++ struct stripe_head *sh;
++
++ pr_debug("%s: handle: %s hold: %s full_writes: %d bypass_count: %d\n",
++ __func__,
++ list_empty(&conf->handle_list) ? "empty" : "busy",
++ list_empty(&conf->hold_list) ? "empty" : "busy",
++ atomic_read(&conf->pending_full_writes), conf->bypass_count);
++
++ if (!list_empty(&conf->handle_list)) {
++ sh = list_entry(conf->handle_list.next, typeof(*sh), lru);
++
++ if (list_empty(&conf->hold_list))
++ conf->bypass_count = 0;
++ else if (!test_bit(STRIPE_IO_STARTED, &sh->state)) {
++ if (conf->hold_list.next == conf->last_hold)
++ conf->bypass_count++;
++ else {
++ conf->last_hold = conf->hold_list.next;
++ conf->bypass_count -= conf->bypass_threshold;
++ if (conf->bypass_count < 0)
++ conf->bypass_count = 0;
++ }
++ }
++ } else if (!list_empty(&conf->hold_list) &&
++ ((conf->bypass_threshold &&
++ conf->bypass_count > conf->bypass_threshold) ||
++ atomic_read(&conf->pending_full_writes) == 0)) {
++ sh = list_entry(conf->hold_list.next,
++ typeof(*sh), lru);
++ conf->bypass_count -= conf->bypass_threshold;
++ if (conf->bypass_count < 0)
++ conf->bypass_count = 0;
++ } else
++ return NULL;
++
++ list_del_init(&sh->lru);
++ atomic_inc(&sh->count);
++ BUG_ON(atomic_read(&sh->count) != 1);
++ return sh;
++}
- 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;
- }
+ static int make_request(struct request_queue *q, struct bio * bi)
+ {
+@@ -3914,7 +4016,6 @@ static void raid5d(mddev_t *mddev)
+ handled = 0;
+ spin_lock_irq(&conf->device_lock);
+ while (1) {
+- struct list_head *first;
+ struct bio *bio;
- 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;
+ if (conf->seq_flush != conf->seq_write) {
+@@ -3936,17 +4037,12 @@ static void raid5d(mddev_t *mddev)
+ handled++;
}
- 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;
+
+- if (list_empty(&conf->handle_list)) {
++ sh = __get_priority_stripe(conf);
++
++ if (!sh) {
+ async_tx_issue_pending_all();
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);
+-
+- first = conf->handle_list.next;
+- sh = list_entry(first, struct stripe_head, lru);
+-
+- list_del_init(first);
+- atomic_inc(&sh->count);
+- BUG_ON(atomic_read(&sh->count)!= 1);
+ spin_unlock_irq(&conf->device_lock);
+
+ handled++;
+@@ -3978,15 +4074,13 @@ static ssize_t
+ raid5_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len)
+ {
+ raid5_conf_t *conf = mddev_to_conf(mddev);
+- char *end;
+- int new;
++ unsigned long new;
+ if (len >= PAGE_SIZE)
+ return -EINVAL;
+ if (!conf)
+ return -ENODEV;
-- 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;
- }
+- new = simple_strtoul(page, &end, 10);
+- if (!*page || (*end && *end != '\n') )
++ if (strict_strtoul(page, 10, &new))
+ return -EINVAL;
+ if (new <= 16 || new > 32768)
+ return -EINVAL;
+@@ -4011,6 +4105,40 @@ raid5_stripecache_size = __ATTR(stripe_cache_size, S_IRUGO | S_IWUSR,
+ raid5_store_stripe_cache_size);
-@@ -742,7 +742,7 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
- int free = 0;
- struct iwch_ep *ep = NULL;
+ static ssize_t
++raid5_show_preread_threshold(mddev_t *mddev, char *page)
++{
++ raid5_conf_t *conf = mddev_to_conf(mddev);
++ if (conf)
++ return sprintf(page, "%d\n", conf->bypass_threshold);
++ else
++ return 0;
++}
++
++static ssize_t
++raid5_store_preread_threshold(mddev_t *mddev, const char *page, size_t len)
++{
++ raid5_conf_t *conf = mddev_to_conf(mddev);
++ unsigned long new;
++ if (len >= PAGE_SIZE)
++ return -EINVAL;
++ if (!conf)
++ return -ENODEV;
++
++ if (strict_strtoul(page, 10, &new))
++ return -EINVAL;
++ if (new > conf->max_nr_stripes)
++ return -EINVAL;
++ conf->bypass_threshold = new;
++ return len;
++}
++
++static struct md_sysfs_entry
++raid5_preread_bypass_threshold = __ATTR(preread_bypass_threshold,
++ S_IRUGO | S_IWUSR,
++ raid5_show_preread_threshold,
++ raid5_store_preread_threshold);
++
++static ssize_t
+ stripe_cache_active_show(mddev_t *mddev, char *page)
+ {
+ raid5_conf_t *conf = mddev_to_conf(mddev);
+@@ -4026,6 +4154,7 @@ raid5_stripecache_active = __ATTR_RO(stripe_cache_active);
+ static struct attribute *raid5_attrs[] = {
+ &raid5_stripecache_size.attr,
+ &raid5_stripecache_active.attr,
++ &raid5_preread_bypass_threshold.attr,
+ NULL,
+ };
+ static struct attribute_group raid5_attrs_group = {
+@@ -4130,12 +4259,14 @@ static int run(mddev_t *mddev)
+ init_waitqueue_head(&conf->wait_for_stripe);
+ init_waitqueue_head(&conf->wait_for_overlap);
+ INIT_LIST_HEAD(&conf->handle_list);
++ INIT_LIST_HEAD(&conf->hold_list);
+ INIT_LIST_HEAD(&conf->delayed_list);
+ INIT_LIST_HEAD(&conf->bitmap_list);
+ INIT_LIST_HEAD(&conf->inactive_list);
+ atomic_set(&conf->active_stripes, 0);
+ atomic_set(&conf->preread_active_stripes, 0);
+ atomic_set(&conf->active_aligned_reads, 0);
++ conf->bypass_threshold = BYPASS_THRESHOLD;
+
+ pr_debug("raid5: run(%s) called.\n", mdname(mddev));
+
+diff --git a/drivers/md/raid6algos.c b/drivers/md/raid6algos.c
+index 77a6e4b..21987e3 100644
+--- a/drivers/md/raid6algos.c
++++ b/drivers/md/raid6algos.c
+@@ -121,7 +121,8 @@ int __init raid6_select_algo(void)
+ j0 = jiffies;
+ while ( (j1 = jiffies) == j0 )
+ cpu_relax();
+- while ( (jiffies-j1) < (1 << RAID6_TIME_JIFFIES_LG2) ) {
++ while (time_before(jiffies,
++ j1 + (1<<RAID6_TIME_JIFFIES_LG2))) {
+ (*algo)->gen_syndrome(disks, PAGE_SIZE, dptrs);
+ perf++;
+ }
+diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
+index 1195069..ddf57e1 100644
+--- a/drivers/media/Kconfig
++++ b/drivers/media/Kconfig
+@@ -5,16 +5,20 @@
+ menu "Multimedia devices"
+ depends on HAS_IOMEM
-- 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);
++comment "Multimedia core support"
++
++#
++# V4L core and enabled API's
++#
++
+ config VIDEO_DEV
+ tristate "Video For Linux"
+ ---help---
+- Support for audio/video capture and overlay devices and FM radio
+- cards. The exact capabilities of each device vary.
++ V4L core support for video capture and overlay devices, webcams and
++ AM/FM radio cards.
+
+ This kernel includes support for the new Video for Linux Two API,
+- (V4L2) as well as the original system. Drivers and applications
+- need to be rewritten to use V4L2, but drivers for popular cards
+- and applications for most video capture functions already exist.
++ (V4L2).
+
+ Additional info and docs are available on the web at
+ <http://linuxtv.org>
+@@ -30,14 +34,17 @@ config VIDEO_V4L2_COMMON
+ depends on (I2C || I2C=n) && VIDEO_DEV
+ default (I2C || I2C=n) && VIDEO_DEV
-@@ -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);
+-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
+ select VIDEO_V4L1_COMPAT
+ ---help---
+- Enables a compatibility API used by most V4L2 devices to allow
+- its usage with legacy applications that supports only V4L1 api.
++ Enables drivers based on the legacy V4L1 API.
++
++ This api were developed to be used at Kernel 2.2 and 2.4, but
++ lacks support for several video standards. There are several
++ drivers at kernel that still depends on it.
- /* disassociate the LLP connection */
-@@ -939,7 +939,7 @@ out:
- if (free)
- put_ep(&ep->com);
+ If you are unsure as to whether this is required, answer Y.
-- PDBG("%s exit state %d\n", __FUNCTION__, qhp->attr.state);
-+ PDBG("%s exit state %d\n", __func__, qhp->attr.state);
- return ret;
- }
+@@ -46,9 +53,8 @@ config VIDEO_V4L1_COMPAT
+ depends on VIDEO_DEV
+ default VIDEO_DEV
+ ---help---
+- This api were developed to be used at Kernel 2.2 and 2.4, but
+- lacks support for several video standards. There are several
+- drivers at kernel that still depends on it.
++ Enables a compatibility API used by most V4L2 devices to allow
++ its usage with legacy applications that supports only V4L1 api.
+
+ Documentation for the original API is included in the file
+ <Documentation/video4linux/API.html>.
+@@ -58,130 +64,57 @@ config VIDEO_V4L1_COMPAT
-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.
- */
+ If you are unsure as to whether this is required, answer Y.
+-config VIDEO_V4L2
+- bool
+- depends on VIDEO_DEV && VIDEO_V4L2_COMMON
+- default VIDEO_DEV && VIDEO_V4L2_COMMON
-
--#include <asm/current.h>
+-source "drivers/media/video/Kconfig"
-
- #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;
+-source "drivers/media/radio/Kconfig"
-
-- 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;
-- }
+-source "drivers/media/dvb/Kconfig"
+-
+-source "drivers/media/common/Kconfig"
++#
++# DVB Core
++#
- 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;
+-config VIDEO_TUNER
+- tristate
+- depends on I2C
+- select TUNER_XC2028 if !VIDEO_TUNER_CUSTOMIZE
+- select TUNER_MT20XX if !VIDEO_TUNER_CUSTOMIZE
+- select TUNER_TDA8290 if !VIDEO_TUNER_CUSTOMIZE
+- select TUNER_TEA5761 if !VIDEO_TUNER_CUSTOMIZE
+- select TUNER_TEA5767 if !VIDEO_TUNER_CUSTOMIZE
+- select TUNER_SIMPLE if !VIDEO_TUNER_CUSTOMIZE
+- select TUNER_TDA9887 if !VIDEO_TUNER_CUSTOMIZE
+-
+-menuconfig VIDEO_TUNER_CUSTOMIZE
+- bool "Customize analog tuner modules to build"
+- depends on VIDEO_TUNER
++config DVB_CORE
++ tristate "DVB for Linux"
++ depends on NET && INET
++ select CRC32
+ help
+- This allows the user to deselect tuner drivers unnecessary
+- for their hardware from the build. Use this option with care
+- as deselecting tuner drivers which are in fact necessary will
+- result in V4L devices which cannot be tuned due to lack of
+- driver support
+-
+- If unsure say N.
+-
+-if VIDEO_TUNER_CUSTOMIZE
++ DVB core utility functions for device handling, software fallbacks etc.
+
+-config TUNER_XC2028
+- tristate "XCeive xc2028/xc3028 tuners"
+- depends on I2C && FW_LOADER
+- default m if VIDEO_TUNER_CUSTOMIZE
+- help
+- Say Y here to include support for the xc2028/xc3028 tuners.
++ Enable this if you own a DVB/ATSC adapter and want to use it or if
++ you compile Linux for a digital SetTopBox.
+
+-config TUNER_MT20XX
+- tristate "Microtune 2032 / 2050 tuners"
+- depends on I2C
+- default m if VIDEO_TUNER_CUSTOMIZE
+- help
+- Say Y here to include support for the MT2032 / MT2050 tuner.
-
-- 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;
-- }
+-config TUNER_TDA8290
+- tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo"
+- depends on I2C
+- select DVB_TDA827X
+- select DVB_TDA18271
+- default m if VIDEO_TUNER_CUSTOMIZE
+- help
+- Say Y here to include support for Philips TDA8290+8275(a) tuner.
++ Say Y when you have a DVB or an ATSC card and want to use it.
- 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)
+-config TUNER_TEA5761
+- tristate "TEA 5761 radio tuner (EXPERIMENTAL)"
+- depends on I2C && EXPERIMENTAL
+- default m if VIDEO_TUNER_CUSTOMIZE
+- help
+- Say Y here to include support for the Philips TEA5761 radio tuner.
++ API specs and user tools are available from <http://www.linuxtv.org/>.
- 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));
+-config TUNER_TEA5767
+- tristate "TEA 5767 radio tuner"
+- depends on I2C
+- default m if VIDEO_TUNER_CUSTOMIZE
+- help
+- Say Y here to include support for the Philips TEA5767 radio tuner.
++ Please report problems regarding this support to the LinuxDVB
++ mailing list.
+
+-config TUNER_SIMPLE
+- tristate "Simple tuner support"
+- depends on I2C
+- select TUNER_TDA9887
+- default m if VIDEO_TUNER_CUSTOMIZE
+- help
+- Say Y here to include support for various simple tuners.
++ If unsure say N.
- 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.
- */
+-config TUNER_TDA9887
+- tristate "TDA 9885/6/7 analog IF demodulator"
+- depends on I2C
+- default m if VIDEO_TUNER_CUSTOMIZE
+- help
+- Say Y here to include support for Philips TDA9885/6/7
+- analog IF demodulator.
++config VIDEO_MEDIA
++ tristate
++ default DVB_CORE || VIDEO_DEV
++ depends on DVB_CORE || VIDEO_DEV
--#include <asm/current.h>
--
- #include "ehca_iverbs.h"
- #include "ehca_classes.h"
- #include "ehca_irq.h"
-@@ -148,7 +146,6 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
- spin_lock_init(&my_cq->task_lock);
- atomic_set(&my_cq->nr_events, 0);
- init_waitqueue_head(&my_cq->wait_completion);
-- my_cq->ownpid = current->tgid;
+-endif # VIDEO_TUNER_CUSTOMIZE
++comment "Multimedia drivers"
- cq = &my_cq->ib_cq;
+-config VIDEOBUF_GEN
+- tristate
++source "drivers/media/common/Kconfig"
-@@ -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;
+-config VIDEOBUF_DMA_SG
+- depends on PCI
+- select VIDEOBUF_GEN
+- tristate
++#
++# Tuner drivers for DVB and V4L
++#
- 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;
-- }
- }
+-config VIDEOBUF_VMALLOC
+- select VIDEOBUF_GEN
+- tristate
++source "drivers/media/common/tuners/Kconfig"
- /*
-@@ -374,15 +364,6 @@ int ehca_destroy_cq(struct ib_cq *cq)
+-config VIDEOBUF_DVB
+- tristate
+- select VIDEOBUF_GEN
+- select VIDEOBUF_DMA_SG
++#
++# Video/Radio/Hybrid adapters
++#
- 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");
+-config VIDEO_BTCX
+- tristate
++source "drivers/media/video/Kconfig"
-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"
+-config VIDEO_IR_I2C
+- tristate
++source "drivers/media/radio/Kconfig"
-+static unsigned int limit_uint(unsigned int value)
+-config VIDEO_IR
+- tristate
+- depends on INPUT
+- select VIDEO_IR_I2C if I2C
++#
++# DVB adapters
++#
+
+-config VIDEO_TVEEPROM
+- tristate
+- depends on I2C
++source "drivers/media/dvb/Kconfig"
+
+ config DAB
+ boolean "DAB adapters"
+diff --git a/drivers/media/Makefile b/drivers/media/Makefile
+index 7b8bb69..73f742c 100644
+--- a/drivers/media/Makefile
++++ b/drivers/media/Makefile
+@@ -2,10 +2,10 @@
+ # Makefile for the kernel multimedia device drivers.
+ #
+
+-obj-y := common/
+-obj-y += video/
++obj-$(CONFIG_VIDEO_MEDIA) += common/
++
++# Since hybrid devices are here, should be compiled if DVB and/or V4L
++obj-$(CONFIG_VIDEO_MEDIA) += video/
++
+ obj-$(CONFIG_VIDEO_DEV) += radio/
+ obj-$(CONFIG_DVB_CORE) += dvb/
+-ifeq ($(CONFIG_DVB_CORE),)
+- obj-$(CONFIG_VIDEO_TUNER) += dvb/frontends/
+-endif
+diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile
+index 8e74482..351b98b 100644
+--- a/drivers/media/common/Makefile
++++ b/drivers/media/common/Makefile
+@@ -2,6 +2,7 @@ saa7146-objs := saa7146_i2c.o saa7146_core.o
+ saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o
+ ir-common-objs := ir-functions.o ir-keymaps.o
+
++obj-y += tuners/
+ obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o
+ obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o
+ obj-$(CONFIG_VIDEO_IR) += ir-common.o
+diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c
+index bb2a027..2665052 100644
+--- a/drivers/media/common/ir-functions.c
++++ b/drivers/media/common/ir-functions.c
+@@ -34,7 +34,7 @@ static int repeat = 1;
+ module_param(repeat, int, 0444);
+ MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)");
+
+-static int debug = 0; /* debug level (0,1,2) */
++static int debug; /* debug level (0,1,2) */
+ module_param(debug, int, 0644);
+
+ #define dprintk(level, fmt, arg...) if (debug >= level) \
+diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c
+index 2ab5a12..a348581 100644
+--- a/drivers/media/common/ir-keymaps.c
++++ b/drivers/media/common/ir-keymaps.c
+@@ -212,6 +212,51 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = {
+
+ EXPORT_SYMBOL_GPL(ir_codes_pixelview);
+
++/*
++ Mauro Carvalho Chehab <mchehab at infradead.org>
++ present on PV MPEG 8000GT
++ */
++IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE] = {
++ [0x3c] = KEY_PAUSE, /* Timeshift */
++ [0x12] = KEY_POWER,
++
++ [0x3d] = KEY_1,
++ [0x38] = KEY_2,
++ [0x18] = KEY_3,
++ [0x35] = KEY_4,
++ [0x39] = KEY_5,
++ [0x15] = KEY_6,
++ [0x36] = KEY_7,
++ [0x3a] = KEY_8,
++ [0x1e] = KEY_9,
++ [0x3e] = KEY_0,
++
++ [0x1c] = KEY_AGAIN, /* LOOP */
++ [0x3f] = KEY_MEDIA, /* Source */
++ [0x1f] = KEY_LAST, /* +100 */
++ [0x1b] = KEY_MUTE,
++
++ [0x17] = KEY_CHANNELDOWN,
++ [0x16] = KEY_CHANNELUP,
++ [0x10] = KEY_VOLUMEUP,
++ [0x14] = KEY_VOLUMEDOWN,
++ [0x13] = KEY_ZOOM,
++
++ [0x19] = KEY_SHUFFLE, /* SNAPSHOT */
++ [0x1a] = KEY_SEARCH, /* scan */
++
++ [0x37] = KEY_REWIND, /* << */
++ [0x32] = KEY_RECORD, /* o (red) */
++ [0x33] = KEY_FORWARD, /* >> */
++ [0x11] = KEY_STOP, /* square */
++ [0x3b] = KEY_PLAY, /* > */
++ [0x30] = KEY_PLAYPAUSE, /* || */
++
++ [0x31] = KEY_TV,
++ [0x34] = KEY_RADIO,
++};
++EXPORT_SYMBOL_GPL(ir_codes_pixelview_new);
++
+ IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = {
+ [ 0x00 ] = KEY_0,
+ [ 0x01 ] = KEY_1,
+@@ -726,7 +771,11 @@ IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = {
+ [ 0x12 ] = KEY_CHANNELUP, // Channel +
+ [ 0x13 ] = KEY_CHANNELDOWN, // Channel -
+ [ 0x06 ] = KEY_AGAIN, // Recall
+- [ 0x10 ] = KEY_ENTER, // Enter
++ [ 0x10 ] = KEY_ENTER, // Enter
++
++ [ 0x19 ] = KEY_BACK, // Rewind ( <<< )
++ [ 0x1f ] = KEY_FORWARD, // Forward ( >>> )
++ [ 0x0a ] = KEY_ANGLE, // (no label, may be used as the PAUSE button)
+ };
+
+ EXPORT_SYMBOL_GPL(ir_codes_flyvideo);
+@@ -1157,7 +1206,8 @@ EXPORT_SYMBOL_GPL(ir_codes_purpletv);
+
+ /* Mapping for the 28 key remote control as seen at
+ http://www.sednacomputer.com/photo/cardbus-tv.jpg
+- Pavel Mihaylov <bin at bash.info> */
++ Pavel Mihaylov <bin at bash.info>
++ Also for the remote bundled with Kozumi KTV-01C card */
+ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = {
+ [ 0x00 ] = KEY_0,
+ [ 0x01 ] = KEY_1,
+@@ -1188,6 +1238,11 @@ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = {
+ [ 0x1c ] = KEY_RADIO, /* FM Radio */
+ [ 0x1d ] = KEY_RECORD,
+ [ 0x1e ] = KEY_PAUSE,
++ /* additional codes for Kozumi's remote */
++ [0x14] = KEY_INFO, /* OSD */
++ [0x16] = KEY_OK, /* OK */
++ [0x17] = KEY_DIGITS, /* Plus */
++ [0x1f] = KEY_PLAY, /* Play */
+ };
+
+ EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna);
+@@ -1988,6 +2043,76 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = {
+
+ EXPORT_SYMBOL_GPL(ir_codes_behold);
+
++/* Beholder Intl. Ltd. 2008
++ * Dmitry Belimov d.belimov at google.com
++ * Keytable is used by BeholdTV Columbus
++ * The "ascii-art picture" below (in comments, first row
++ * is the keycode in hex, and subsequent row(s) shows
++ * the button labels (several variants when appropriate)
++ * helps to descide which keycodes to assign to the buttons.
++ */
++IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = {
++
++ /* 0x13 0x11 0x1C 0x12 *
++ * Mute Source TV/FM Power *
++ * */
++
++ [0x13] = KEY_MUTE,
++ [0x11] = KEY_PROPS,
++ [0x1C] = KEY_TUNER, /* KEY_TV/KEY_RADIO */
++ [0x12] = KEY_POWER,
++
++ /* 0x01 0x02 0x03 0x0D *
++ * 1 2 3 Stereo *
++ * *
++ * 0x04 0x05 0x06 0x19 *
++ * 4 5 6 Snapshot *
++ * *
++ * 0x07 0x08 0x09 0x10 *
++ * 7 8 9 Zoom *
++ * */
++ [0x01] = KEY_1,
++ [0x02] = KEY_2,
++ [0x03] = KEY_3,
++ [0x0D] = KEY_SETUP, /* Setup key */
++ [0x04] = KEY_4,
++ [0x05] = KEY_5,
++ [0x06] = KEY_6,
++ [0x19] = KEY_BOOKMARKS, /* Snapshot key */
++ [0x07] = KEY_7,
++ [0x08] = KEY_8,
++ [0x09] = KEY_9,
++ [0x10] = KEY_ZOOM,
++
++ /* 0x0A 0x00 0x0B 0x0C *
++ * RECALL 0 ChannelUp VolumeUp *
++ * */
++ [0x0A] = KEY_AGAIN,
++ [0x00] = KEY_0,
++ [0x0B] = KEY_CHANNELUP,
++ [0x0C] = KEY_VOLUMEUP,
++
++ /* 0x1B 0x1D 0x15 0x18 *
++ * Timeshift Record ChannelDown VolumeDown *
++ * */
++
++ [0x1B] = KEY_REWIND,
++ [0x1D] = KEY_RECORD,
++ [0x15] = KEY_CHANNELDOWN,
++ [0x18] = KEY_VOLUMEDOWN,
++
++ /* 0x0E 0x1E 0x0F 0x1A *
++ * Stop Pause Previouse Next *
++ * */
++
++ [0x0E] = KEY_STOP,
++ [0x1E] = KEY_PAUSE,
++ [0x0F] = KEY_PREVIOUS,
++ [0x1A] = KEY_NEXT,
++
++};
++EXPORT_SYMBOL_GPL(ir_codes_behold_columbus);
++
+ /*
+ * Remote control for the Genius TVGO A11MCE
+ * Adrian Pardini <pardo.bsso at gmail.com>
+@@ -2033,3 +2158,46 @@ IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE] = {
+ [0x50] = KEY_BLUE,
+ };
+ EXPORT_SYMBOL_GPL(ir_codes_genius_tvgo_a11mce);
++
++/*
++ * Remote control for Powercolor Real Angel 330
++ * Daniel Fraga <fragabr at gmail.com>
++ */
++IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = {
++ [0x38] = KEY_SWITCHVIDEOMODE, /* switch inputs */
++ [0x0c] = KEY_MEDIA, /* Turn ON/OFF App */
++ [0x00] = KEY_0,
++ [0x01] = KEY_1,
++ [0x02] = KEY_2,
++ [0x03] = KEY_3,
++ [0x04] = KEY_4,
++ [0x05] = KEY_5,
++ [0x06] = KEY_6,
++ [0x07] = KEY_7,
++ [0x08] = KEY_8,
++ [0x09] = KEY_9,
++ [0x0a] = KEY_DIGITS, /* single, double, tripple digit */
++ [0x29] = KEY_PREVIOUS, /* previous channel */
++ [0x12] = KEY_BRIGHTNESSUP,
++ [0x13] = KEY_BRIGHTNESSDOWN,
++ [0x2b] = KEY_MODE, /* stereo/mono */
++ [0x2c] = KEY_TEXT, /* teletext */
++ [0x20] = KEY_UP, /* channel up */
++ [0x21] = KEY_DOWN, /* channel down */
++ [0x10] = KEY_RIGHT, /* volume up */
++ [0x11] = KEY_LEFT, /* volume down */
++ [0x0d] = KEY_MUTE,
++ [0x1f] = KEY_RECORD,
++ [0x17] = KEY_PLAY,
++ [0x16] = KEY_PAUSE,
++ [0x0b] = KEY_STOP,
++ [0x27] = KEY_FASTFORWARD,
++ [0x26] = KEY_REWIND,
++ [0x1e] = KEY_SEARCH, /* autoscan */
++ [0x0e] = KEY_SHUFFLE, /* snapshot */
++ [0x2d] = KEY_SETUP,
++ [0x0f] = KEY_SCREEN, /* full screen */
++ [0x14] = KEY_RADIO, /* FM radio */
++ [0x25] = KEY_POWER, /* power */
++};
++EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel);
+diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
+index 7707b8c..89c7660 100644
+--- a/drivers/media/common/saa7146_core.c
++++ b/drivers/media/common/saa7146_core.c
+@@ -74,7 +74,7 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
+ if (err) {
+ printk(KERN_ERR "%s: %s timed out while waiting for "
+ "registers getting programmed\n",
+- dev->name, __FUNCTION__);
++ dev->name, __func__);
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+@@ -89,7 +89,7 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
+ saa7146_read(dev, MC2);
+ if (err) {
+ DEB_S(("%s: %s timed out while waiting for transfer "
+- "completion\n", dev->name, __FUNCTION__));
++ "completion\n", dev->name, __func__));
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+@@ -111,7 +111,7 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
+ if (!loops--) {
+ printk(KERN_ERR "%s: %s timed out while waiting for "
+ "registers getting programmed\n",
+- dev->name, __FUNCTION__);
++ dev->name, __func__);
+ return -ETIMEDOUT;
+ }
+ udelay(1);
+@@ -125,7 +125,7 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
+ saa7146_read(dev, MC2);
+ if (!loops--) {
+ DEB_S(("%s: %s timed out while waiting for transfer "
+- "completion\n", dev->name, __FUNCTION__));
++ "completion\n", dev->name, __func__));
+ return -ETIMEDOUT;
+ }
+ udelay(5);
+diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
+index 7e7689a..35b01ec 100644
+--- a/drivers/media/common/saa7146_i2c.c
++++ b/drivers/media/common/saa7146_i2c.c
+@@ -203,7 +203,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
+ return -ERESTARTSYS;
+
+ printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n",
+- dev->name, __FUNCTION__);
++ dev->name, __func__);
+ return -EIO;
+ }
+ status = saa7146_read(dev, I2C_STATUS);
+@@ -221,7 +221,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
+ }
+ if (time_after(jiffies,timeout)) {
+ printk(KERN_WARNING "%s %s: timed out waiting for MC2\n",
+- dev->name, __FUNCTION__);
++ dev->name, __func__);
+ return -EIO;
+ }
+ }
+@@ -238,7 +238,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
+ * (no answer from nonexisistant device...)
+ */
+ printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n",
+- dev->name, __FUNCTION__);
++ dev->name, __func__);
+ return -EIO;
+ }
+ if (++trial < 50 && short_delay)
+diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c
+index bfbd5a8..74e2b56 100644
+--- a/drivers/media/common/saa7146_vbi.c
++++ b/drivers/media/common/saa7146_vbi.c
+@@ -407,8 +407,8 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
+ fh->vbi_fmt.start[1] = 312;
+ fh->vbi_fmt.count[1] = 16;
+
+- videobuf_queue_pci_init(&fh->vbi_q, &vbi_qops,
+- dev->pci, &dev->slock,
++ videobuf_queue_sg_init(&fh->vbi_q, &vbi_qops,
++ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VBI_CAPTURE,
+ V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
+ sizeof(struct saa7146_buf),
+diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
+index 66fdbd0..3cbc6eb 100644
+--- a/drivers/media/common/saa7146_video.c
++++ b/drivers/media/common/saa7146_video.c
+@@ -1410,8 +1410,8 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
+ sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+ fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;
+
+- videobuf_queue_pci_init(&fh->video_q, &video_qops,
+- dev->pci, &dev->slock,
++ videobuf_queue_sg_init(&fh->video_q, &video_qops,
++ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct saa7146_buf),
+diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig
+new file mode 100644
+index 0000000..5be85ff
+--- /dev/null
++++ b/drivers/media/common/tuners/Kconfig
+@@ -0,0 +1,151 @@
++config MEDIA_ATTACH
++ bool "Load and attach frontend and tuner driver modules as needed"
++ depends on DVB_CORE
++ depends on MODULES
++ help
++ Remove the static dependency of DVB card drivers on all
++ frontend modules for all possible card variants. Instead,
++ allow the card drivers to only load the frontend modules
++ they require.
++
++ Also, tuner module will automatically load a tuner driver
++ when needed, for analog mode.
++
++ This saves several KBytes of memory.
++
++ Note: You will need module-init-tools v3.2 or later for this feature.
++
++ If unsure say Y.
++
++config MEDIA_TUNER
++ tristate
++ default DVB_CORE || VIDEO_DEV
++ depends on DVB_CORE || VIDEO_DEV
++ select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE
++ select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE
++ select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMIZE
++ select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE
++ select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMIZE
++ select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMIZE
++ select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
++ select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMIZE
++
++menuconfig MEDIA_TUNER_CUSTOMIZE
++ bool "Customize analog and hybrid tuner modules to build"
++ depends on MEDIA_TUNER
++ help
++ This allows the user to deselect tuner drivers unnecessary
++ for their hardware from the build. Use this option with care
++ as deselecting tuner drivers which are in fact necessary will
++ result in V4L/DVB devices which cannot be tuned due to lack of
++ driver support
++
++ If unsure say N.
++
++if MEDIA_TUNER_CUSTOMIZE
++
++config MEDIA_TUNER_SIMPLE
++ tristate "Simple tuner support"
++ depends on I2C
++ select MEDIA_TUNER_TDA9887
++ default m if MEDIA_TUNER_CUSTOMIZE
++ help
++ Say Y here to include support for various simple tuners.
++
++config MEDIA_TUNER_TDA8290
++ tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo"
++ depends on I2C
++ select MEDIA_TUNER_TDA827X
++ select MEDIA_TUNER_TDA18271
++ default m if MEDIA_TUNER_CUSTOMIZE
++ help
++ Say Y here to include support for Philips TDA8290+8275(a) tuner.
++
++config MEDIA_TUNER_TDA827X
++ tristate "Philips TDA827X silicon tuner"
++ depends on DVB_CORE && I2C
++ default m if DVB_FE_CUSTOMISE
++ help
++ A DVB-T silicon tuner module. Say Y when you want to support this tuner.
++
++config MEDIA_TUNER_TDA18271
++ tristate "NXP TDA18271 silicon tuner"
++ depends on I2C
++ default m if DVB_FE_CUSTOMISE
++ help
++ A silicon tuner module. Say Y when you want to support this tuner.
++
++config MEDIA_TUNER_TDA9887
++ tristate "TDA 9885/6/7 analog IF demodulator"
++ depends on I2C
++ default m if MEDIA_TUNER_CUSTOMIZE
++ help
++ Say Y here to include support for Philips TDA9885/6/7
++ analog IF demodulator.
++
++config MEDIA_TUNER_TEA5761
++ tristate "TEA 5761 radio tuner (EXPERIMENTAL)"
++ depends on I2C && EXPERIMENTAL
++ default m if MEDIA_TUNER_CUSTOMIZE
++ help
++ Say Y here to include support for the Philips TEA5761 radio tuner.
++
++config MEDIA_TUNER_TEA5767
++ tristate "TEA 5767 radio tuner"
++ depends on I2C
++ default m if MEDIA_TUNER_CUSTOMIZE
++ help
++ Say Y here to include support for the Philips TEA5767 radio tuner.
++
++config MEDIA_TUNER_MT20XX
++ tristate "Microtune 2032 / 2050 tuners"
++ depends on I2C
++ default m if MEDIA_TUNER_CUSTOMIZE
++ help
++ Say Y here to include support for the MT2032 / MT2050 tuner.
++
++config MEDIA_TUNER_MT2060
++ tristate "Microtune MT2060 silicon IF tuner"
++ depends on I2C
++ default m if DVB_FE_CUSTOMISE
++ help
++ A driver for the silicon IF tuner MT2060 from Microtune.
++
++config MEDIA_TUNER_MT2266
++ tristate "Microtune MT2266 silicon tuner"
++ depends on I2C
++ default m if DVB_FE_CUSTOMISE
++ help
++ A driver for the silicon baseband tuner MT2266 from Microtune.
++
++config MEDIA_TUNER_MT2131
++ tristate "Microtune MT2131 silicon tuner"
++ depends on I2C
++ default m if DVB_FE_CUSTOMISE
++ help
++ A driver for the silicon baseband tuner MT2131 from Microtune.
++
++config MEDIA_TUNER_QT1010
++ tristate "Quantek QT1010 silicon tuner"
++ depends on DVB_CORE && I2C
++ default m if DVB_FE_CUSTOMISE
++ help
++ A driver for the silicon tuner QT1010 from Quantek.
++
++config MEDIA_TUNER_XC2028
++ tristate "XCeive xc2028/xc3028 tuners"
++ depends on I2C && FW_LOADER
++ default m if MEDIA_TUNER_CUSTOMIZE
++ help
++ Say Y here to include support for the xc2028/xc3028 tuners.
++
++config MEDIA_TUNER_XC5000
++ tristate "Xceive XC5000 silicon tuner"
++ depends on I2C
++ default m if DVB_FE_CUSTOMISE
++ help
++ A driver for the silicon tuner XC5000 from Xceive.
++ This device is only used inside a SiP called togther with a
++ demodulator for now.
++
++endif # MEDIA_TUNER_CUSTOMIZE
+diff --git a/drivers/media/common/tuners/Makefile b/drivers/media/common/tuners/Makefile
+new file mode 100644
+index 0000000..236d993
+--- /dev/null
++++ b/drivers/media/common/tuners/Makefile
+@@ -0,0 +1,25 @@
++#
++# Makefile for common V4L/DVB tuners
++#
++
++tda18271-objs := tda18271-maps.o tda18271-common.o tda18271-fe.o
++
++obj-$(CONFIG_MEDIA_TUNER_XC2028) += tuner-xc2028.o
++obj-$(CONFIG_MEDIA_TUNER_SIMPLE) += tuner-simple.o
++# tuner-types will be merged into tuner-simple, in the future
++obj-$(CONFIG_MEDIA_TUNER_SIMPLE) += tuner-types.o
++obj-$(CONFIG_MEDIA_TUNER_MT20XX) += mt20xx.o
++obj-$(CONFIG_MEDIA_TUNER_TDA8290) += tda8290.o
++obj-$(CONFIG_MEDIA_TUNER_TEA5767) += tea5767.o
++obj-$(CONFIG_MEDIA_TUNER_TEA5761) += tea5761.o
++obj-$(CONFIG_MEDIA_TUNER_TDA9887) += tda9887.o
++obj-$(CONFIG_MEDIA_TUNER_TDA827X) += tda827x.o
++obj-$(CONFIG_MEDIA_TUNER_TDA18271) += tda18271.o
++obj-$(CONFIG_MEDIA_TUNER_XC5000) += xc5000.o
++obj-$(CONFIG_MEDIA_TUNER_MT2060) += mt2060.o
++obj-$(CONFIG_MEDIA_TUNER_MT2266) += mt2266.o
++obj-$(CONFIG_MEDIA_TUNER_QT1010) += qt1010.o
++obj-$(CONFIG_MEDIA_TUNER_MT2131) += mt2131.o
++
++EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
++EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+diff --git a/drivers/media/common/tuners/mt2060.c b/drivers/media/common/tuners/mt2060.c
+new file mode 100644
+index 0000000..1305b0e
+--- /dev/null
++++ b/drivers/media/common/tuners/mt2060.c
+@@ -0,0 +1,369 @@
++/*
++ * Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
++ *
++ * Copyright (c) 2006 Olivier DANET <odanet at caramail.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ */
++
++/* In that file, frequencies are expressed in kiloHertz to avoid 32 bits overflows */
++
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/dvb/frontend.h>
++#include <linux/i2c.h>
++
++#include "dvb_frontend.h"
++
++#include "mt2060.h"
++#include "mt2060_priv.h"
++
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
++
++#define dprintk(args...) do { if (debug) {printk(KERN_DEBUG "MT2060: " args); printk("\n"); }} while (0)
++
++// Reads a single register
++static int mt2060_readreg(struct mt2060_priv *priv, u8 reg, u8 *val)
++{
++ struct i2c_msg msg[2] = {
++ { .addr = priv->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 },
++ { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val, .len = 1 },
++ };
++
++ if (i2c_transfer(priv->i2c, msg, 2) != 2) {
++ printk(KERN_WARNING "mt2060 I2C read failed\n");
++ return -EREMOTEIO;
++ }
++ return 0;
++}
++
++// Writes a single register
++static int mt2060_writereg(struct mt2060_priv *priv, u8 reg, u8 val)
++{
++ u8 buf[2] = { reg, val };
++ struct i2c_msg msg = {
++ .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2
++ };
++
++ if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
++ printk(KERN_WARNING "mt2060 I2C write failed\n");
++ return -EREMOTEIO;
++ }
++ return 0;
++}
++
++// Writes a set of consecutive registers
++static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len)
++{
++ struct i2c_msg msg = {
++ .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = len
++ };
++ if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
++ printk(KERN_WARNING "mt2060 I2C write failed (len=%i)\n",(int)len);
++ return -EREMOTEIO;
++ }
++ return 0;
++}
++
++// Initialisation sequences
++// LNABAND=3, NUM1=0x3C, DIV1=0x74, NUM2=0x1080, DIV2=0x49
++static u8 mt2060_config1[] = {
++ REG_LO1C1,
++ 0x3F, 0x74, 0x00, 0x08, 0x93
++};
++
++// FMCG=2, GP2=0, GP1=0
++static u8 mt2060_config2[] = {
++ REG_MISC_CTRL,
++ 0x20, 0x1E, 0x30, 0xff, 0x80, 0xff, 0x00, 0x2c, 0x42
++};
++
++// VGAG=3, V1CSE=1
++
++#ifdef MT2060_SPURCHECK
++/* The function below calculates the frequency offset between the output frequency if2
++ and the closer cross modulation subcarrier between lo1 and lo2 up to the tenth harmonic */
++static int mt2060_spurcalc(u32 lo1,u32 lo2,u32 if2)
++{
++ int I,J;
++ int dia,diamin,diff;
++ diamin=1000000;
++ for (I = 1; I < 10; I++) {
++ J = ((2*I*lo1)/lo2+1)/2;
++ diff = I*(int)lo1-J*(int)lo2;
++ if (diff < 0) diff=-diff;
++ dia = (diff-(int)if2);
++ if (dia < 0) dia=-dia;
++ if (diamin > dia) diamin=dia;
++ }
++ return diamin;
++}
++
++#define BANDWIDTH 4000 // kHz
++
++/* Calculates the frequency offset to add to avoid spurs. Returns 0 if no offset is needed */
++static int mt2060_spurcheck(u32 lo1,u32 lo2,u32 if2)
++{
++ u32 Spur,Sp1,Sp2;
++ int I,J;
++ I=0;
++ J=1000;
++
++ Spur=mt2060_spurcalc(lo1,lo2,if2);
++ if (Spur < BANDWIDTH) {
++ /* Potential spurs detected */
++ dprintk("Spurs before : f_lo1: %d f_lo2: %d (kHz)",
++ (int)lo1,(int)lo2);
++ I=1000;
++ Sp1 = mt2060_spurcalc(lo1+I,lo2+I,if2);
++ Sp2 = mt2060_spurcalc(lo1-I,lo2-I,if2);
++
++ if (Sp1 < Sp2) {
++ J=-J; I=-I; Spur=Sp2;
++ } else
++ Spur=Sp1;
++
++ while (Spur < BANDWIDTH) {
++ I += J;
++ Spur = mt2060_spurcalc(lo1+I,lo2+I,if2);
++ }
++ dprintk("Spurs after : f_lo1: %d f_lo2: %d (kHz)",
++ (int)(lo1+I),(int)(lo2+I));
++ }
++ return I;
++}
++#endif
++
++#define IF2 36150 // IF2 frequency = 36.150 MHz
++#define FREF 16000 // Quartz oscillator 16 MHz
++
++static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
++{
++ struct mt2060_priv *priv;
++ int ret=0;
++ int i=0;
++ u32 freq;
++ u8 lnaband;
++ u32 f_lo1,f_lo2;
++ u32 div1,num1,div2,num2;
++ u8 b[8];
++ u32 if1;
++
++ priv = fe->tuner_priv;
++
++ if1 = priv->if1_freq;
++ b[0] = REG_LO1B1;
++ b[1] = 0xFF;
++
++ mt2060_writeregs(priv,b,2);
++
++ freq = params->frequency / 1000; // Hz -> kHz
++ priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
++
++ f_lo1 = freq + if1 * 1000;
++ f_lo1 = (f_lo1 / 250) * 250;
++ f_lo2 = f_lo1 - freq - IF2;
++ // From the Comtech datasheet, the step used is 50kHz. The tuner chip could be more precise
++ f_lo2 = ((f_lo2 + 25) / 50) * 50;
++ priv->frequency = (f_lo1 - f_lo2 - IF2) * 1000,
++
++#ifdef MT2060_SPURCHECK
++ // LO-related spurs detection and correction
++ num1 = mt2060_spurcheck(f_lo1,f_lo2,IF2);
++ f_lo1 += num1;
++ f_lo2 += num1;
++#endif
++ //Frequency LO1 = 16MHz * (DIV1 + NUM1/64 )
++ num1 = f_lo1 / (FREF / 64);
++ div1 = num1 / 64;
++ num1 &= 0x3f;
++
++ // Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 )
++ num2 = f_lo2 * 64 / (FREF / 128);
++ div2 = num2 / 8192;
++ num2 &= 0x1fff;
++
++ if (freq <= 95000) lnaband = 0xB0; else
++ if (freq <= 180000) lnaband = 0xA0; else
++ if (freq <= 260000) lnaband = 0x90; else
++ if (freq <= 335000) lnaband = 0x80; else
++ if (freq <= 425000) lnaband = 0x70; else
++ if (freq <= 480000) lnaband = 0x60; else
++ if (freq <= 570000) lnaband = 0x50; else
++ if (freq <= 645000) lnaband = 0x40; else
++ if (freq <= 730000) lnaband = 0x30; else
++ if (freq <= 810000) lnaband = 0x20; else lnaband = 0x10;
++
++ b[0] = REG_LO1C1;
++ b[1] = lnaband | ((num1 >>2) & 0x0F);
++ b[2] = div1;
++ b[3] = (num2 & 0x0F) | ((num1 & 3) << 4);
++ b[4] = num2 >> 4;
++ b[5] = ((num2 >>12) & 1) | (div2 << 1);
++
++ dprintk("IF1: %dMHz",(int)if1);
++ dprintk("PLL freq=%dkHz f_lo1=%dkHz f_lo2=%dkHz",(int)freq,(int)f_lo1,(int)f_lo2);
++ dprintk("PLL div1=%d num1=%d div2=%d num2=%d",(int)div1,(int)num1,(int)div2,(int)num2);
++ dprintk("PLL [1..5]: %2x %2x %2x %2x %2x",(int)b[1],(int)b[2],(int)b[3],(int)b[4],(int)b[5]);
++
++ mt2060_writeregs(priv,b,6);
++
++ //Waits for pll lock or timeout
++ i = 0;
++ do {
++ mt2060_readreg(priv,REG_LO_STATUS,b);
++ if ((b[0] & 0x88)==0x88)
++ break;
++ msleep(4);
++ i++;
++ } while (i<10);
++
++ return ret;
++}
++
++static void mt2060_calibrate(struct mt2060_priv *priv)
++{
++ u8 b = 0;
++ int i = 0;
++
++ if (mt2060_writeregs(priv,mt2060_config1,sizeof(mt2060_config1)))
++ return;
++ if (mt2060_writeregs(priv,mt2060_config2,sizeof(mt2060_config2)))
++ return;
++
++ /* initialize the clock output */
++ mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x30);
++
++ do {
++ b |= (1 << 6); // FM1SS;
++ mt2060_writereg(priv, REG_LO2C1,b);
++ msleep(20);
++
++ if (i == 0) {
++ b |= (1 << 7); // FM1CA;
++ mt2060_writereg(priv, REG_LO2C1,b);
++ b &= ~(1 << 7); // FM1CA;
++ msleep(20);
++ }
++
++ b &= ~(1 << 6); // FM1SS
++ mt2060_writereg(priv, REG_LO2C1,b);
++
++ msleep(20);
++ i++;
++ } while (i < 9);
++
++ i = 0;
++ while (i++ < 10 && mt2060_readreg(priv, REG_MISC_STAT, &b) == 0 && (b & (1 << 6)) == 0)
++ msleep(20);
++
++ if (i < 10) {
++ mt2060_readreg(priv, REG_FM_FREQ, &priv->fmfreq); // now find out, what is fmreq used for :)
++ dprintk("calibration was successful: %d", (int)priv->fmfreq);
++ } else
++ dprintk("FMCAL timed out");
++}
++
++static int mt2060_get_frequency(struct dvb_frontend *fe, u32 *frequency)
++{
++ struct mt2060_priv *priv = fe->tuner_priv;
++ *frequency = priv->frequency;
++ return 0;
++}
++
++static int mt2060_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
++{
++ struct mt2060_priv *priv = fe->tuner_priv;
++ *bandwidth = priv->bandwidth;
++ return 0;
++}
++
++static int mt2060_init(struct dvb_frontend *fe)
++{
++ struct mt2060_priv *priv = fe->tuner_priv;
++ return mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x33);
++}
++
++static int mt2060_sleep(struct dvb_frontend *fe)
++{
++ struct mt2060_priv *priv = fe->tuner_priv;
++ return mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x30);
++}
++
++static int mt2060_release(struct dvb_frontend *fe)
++{
++ kfree(fe->tuner_priv);
++ fe->tuner_priv = NULL;
++ return 0;
++}
++
++static const struct dvb_tuner_ops mt2060_tuner_ops = {
++ .info = {
++ .name = "Microtune MT2060",
++ .frequency_min = 48000000,
++ .frequency_max = 860000000,
++ .frequency_step = 50000,
++ },
++
++ .release = mt2060_release,
++
++ .init = mt2060_init,
++ .sleep = mt2060_sleep,
++
++ .set_params = mt2060_set_params,
++ .get_frequency = mt2060_get_frequency,
++ .get_bandwidth = mt2060_get_bandwidth
++};
++
++/* This functions tries to identify a MT2060 tuner by reading the PART/REV register. This is hasty. */
++struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
++{
++ struct mt2060_priv *priv = NULL;
++ u8 id = 0;
++
++ priv = kzalloc(sizeof(struct mt2060_priv), GFP_KERNEL);
++ if (priv == NULL)
++ return NULL;
++
++ priv->cfg = cfg;
++ priv->i2c = i2c;
++ priv->if1_freq = if1;
++
++ if (mt2060_readreg(priv,REG_PART_REV,&id) != 0) {
++ kfree(priv);
++ return NULL;
++ }
++
++ if (id != PART_REV) {
++ kfree(priv);
++ return NULL;
++ }
++ printk(KERN_INFO "MT2060: successfully identified (IF1 = %d)\n", if1);
++ memcpy(&fe->ops.tuner_ops, &mt2060_tuner_ops, sizeof(struct dvb_tuner_ops));
++
++ fe->tuner_priv = priv;
++
++ mt2060_calibrate(priv);
++
++ return fe;
++}
++EXPORT_SYMBOL(mt2060_attach);
++
++MODULE_AUTHOR("Olivier DANET");
++MODULE_DESCRIPTION("Microtune MT2060 silicon tuner driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/common/tuners/mt2060.h b/drivers/media/common/tuners/mt2060.h
+new file mode 100644
+index 0000000..cb60caf
+--- /dev/null
++++ b/drivers/media/common/tuners/mt2060.h
+@@ -0,0 +1,43 @@
++/*
++ * Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
++ *
++ * Copyright (c) 2006 Olivier DANET <odanet at caramail.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ */
++
++#ifndef MT2060_H
++#define MT2060_H
++
++struct dvb_frontend;
++struct i2c_adapter;
++
++struct mt2060_config {
++ u8 i2c_address;
++ u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */
++};
++
++#if defined(CONFIG_MEDIA_TUNER_MT2060) || (defined(CONFIG_MEDIA_TUNER_MT2060_MODULE) && defined(MODULE))
++extern struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1);
++#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", __func__);
++ return NULL;
++}
++#endif // CONFIG_MEDIA_TUNER_MT2060
++
++#endif
+diff --git a/drivers/media/common/tuners/mt2060_priv.h b/drivers/media/common/tuners/mt2060_priv.h
+new file mode 100644
+index 0000000..5eaccde
+--- /dev/null
++++ b/drivers/media/common/tuners/mt2060_priv.h
+@@ -0,0 +1,105 @@
++/*
++ * Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
++ *
++ * Copyright (c) 2006 Olivier DANET <odanet at caramail.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ */
++
++#ifndef MT2060_PRIV_H
++#define MT2060_PRIV_H
++
++// Uncomment the #define below to enable spurs checking. The results where quite unconvincing.
++// #define MT2060_SPURCHECK
++
++/* This driver is based on the information available in the datasheet of the
++ "Comtech SDVBT-3K6M" tuner ( K1000737843.pdf ) which features the MT2060 register map :
++
++ I2C Address : 0x60
++
++ Reg.No | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | ( defaults )
++ --------------------------------------------------------------------------------
++ 00 | [ PART ] | [ REV ] | R = 0x63
++ 01 | [ LNABAND ] | [ NUM1(5:2) ] | RW = 0x3F
++ 02 | [ DIV1 ] | RW = 0x74
++ 03 | FM1CA | FM1SS | [ NUM1(1:0) ] | [ NUM2(3:0) ] | RW = 0x00
++ 04 | NUM2(11:4) ] | RW = 0x08
++ 05 | [ DIV2 ] |NUM2(12)| RW = 0x93
++ 06 | L1LK | [ TAD1 ] | L2LK | [ TAD2 ] | R
++ 07 | [ FMF ] | R
++ 08 | ? | FMCAL | ? | ? | ? | ? | ? | TEMP | R
++ 09 | 0 | 0 | [ FMGC ] | 0 | GP02 | GP01 | 0 | RW = 0x20
++ 0A | ??
++ 0B | 0 | 0 | 1 | 1 | 0 | 0 | [ VGAG ] | RW = 0x30
++ 0C | V1CSE | 1 | 1 | 1 | 1 | 1 | 1 | 1 | RW = 0xFF
++ 0D | 1 | 0 | [ V1CS ] | RW = 0xB0
++ 0E | ??
++ 0F | ??
++ 10 | ??
++ 11 | [ LOTO ] | 0 | 0 | 1 | 0 | RW = 0x42
++
++ PART : Part code : 6 for MT2060
++ REV : Revision code : 3 for current revision
++ LNABAND : Input frequency range : ( See code for details )
++ NUM1 / DIV1 / NUM2 / DIV2 : Frequencies programming ( See code for details )
++ FM1CA : Calibration Start Bit
++ FM1SS : Calibration Single Step bit
++ L1LK : LO1 Lock Detect
++ TAD1 : Tune Line ADC ( ? )
++ L2LK : LO2 Lock Detect
++ TAD2 : Tune Line ADC ( ? )
++ FMF : Estimated first IF Center frequency Offset ( ? )
++ FM1CAL : Calibration done bit
++ TEMP : On chip temperature sensor
++ FMCG : Mixer 1 Cap Gain ( ? )
++ GP01 / GP02 : Programmable digital outputs. Unconnected pins ?
++ V1CSE : LO1 VCO Automatic Capacitor Select Enable ( ? )
++ V1CS : LO1 Capacitor Selection Value ( ? )
++ LOTO : LO Timeout ( ? )
++ VGAG : Tuner Output gain
++*/
++
++#define I2C_ADDRESS 0x60
++
++#define REG_PART_REV 0
++#define REG_LO1C1 1
++#define REG_LO1C2 2
++#define REG_LO2C1 3
++#define REG_LO2C2 4
++#define REG_LO2C3 5
++#define REG_LO_STATUS 6
++#define REG_FM_FREQ 7
++#define REG_MISC_STAT 8
++#define REG_MISC_CTRL 9
++#define REG_RESERVED_A 0x0A
++#define REG_VGAG 0x0B
++#define REG_LO1B1 0x0C
++#define REG_LO1B2 0x0D
++#define REG_LOTO 0x11
++
++#define PART_REV 0x63 // The current driver works only with PART=6 and REV=3 chips
++
++struct mt2060_priv {
++ struct mt2060_config *cfg;
++ struct i2c_adapter *i2c;
++
++ u32 frequency;
++ u32 bandwidth;
++ u16 if1_freq;
++ u8 fmfreq;
++};
++
++#endif
+diff --git a/drivers/media/common/tuners/mt20xx.c b/drivers/media/common/tuners/mt20xx.c
+new file mode 100644
+index 0000000..fbcb282
+--- /dev/null
++++ b/drivers/media/common/tuners/mt20xx.c
+@@ -0,0 +1,670 @@
++/*
++ * i2c tv tuner chip device driver
++ * controls microtune tuners, mt2032 + mt2050 at the moment.
++ *
++ * This "mt20xx" module was split apart from the original "tuner" module.
++ */
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <linux/videodev.h>
++#include "tuner-i2c.h"
++#include "mt20xx.h"
++
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "enable verbose debug messages");
++
++/* ---------------------------------------------------------------------- */
++
++static unsigned int optimize_vco = 1;
++module_param(optimize_vco, int, 0644);
++
++static unsigned int tv_antenna = 1;
++module_param(tv_antenna, int, 0644);
++
++static unsigned int radio_antenna;
++module_param(radio_antenna, int, 0644);
++
++/* ---------------------------------------------------------------------- */
++
++#define MT2032 0x04
++#define MT2030 0x06
++#define MT2040 0x07
++#define MT2050 0x42
++
++static char *microtune_part[] = {
++ [ MT2030 ] = "MT2030",
++ [ MT2032 ] = "MT2032",
++ [ MT2040 ] = "MT2040",
++ [ MT2050 ] = "MT2050",
++};
++
++struct microtune_priv {
++ struct tuner_i2c_props i2c_props;
++
++ unsigned int xogc;
++ //unsigned int radio_if2;
++
++ u32 frequency;
++};
++
++static int microtune_release(struct dvb_frontend *fe)
++{
++ kfree(fe->tuner_priv);
++ fe->tuner_priv = NULL;
++
++ return 0;
++}
++
++static int microtune_get_frequency(struct dvb_frontend *fe, u32 *frequency)
++{
++ struct microtune_priv *priv = fe->tuner_priv;
++ *frequency = priv->frequency;
++ return 0;
++}
++
++// IsSpurInBand()?
++static int mt2032_spurcheck(struct dvb_frontend *fe,
++ int f1, int f2, int spectrum_from,int spectrum_to)
++{
++ struct microtune_priv *priv = fe->tuner_priv;
++ int n1=1,n2,f;
++
++ f1=f1/1000; //scale to kHz to avoid 32bit overflows
++ f2=f2/1000;
++ spectrum_from/=1000;
++ spectrum_to/=1000;
++
++ tuner_dbg("spurcheck f1=%d f2=%d from=%d to=%d\n",
++ f1,f2,spectrum_from,spectrum_to);
++
++ do {
++ n2=-n1;
++ f=n1*(f1-f2);
++ do {
++ n2--;
++ f=f-f2;
++ tuner_dbg("spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f);
++
++ if( (f>spectrum_from) && (f<spectrum_to))
++ tuner_dbg("mt2032 spurcheck triggered: %d\n",n1);
++ } while ( (f>(f2-spectrum_to)) || (n2>-5));
++ n1++;
++ } while (n1<5);
++
++ return 1;
++}
++
++static int mt2032_compute_freq(struct dvb_frontend *fe,
++ unsigned int rfin,
++ unsigned int if1, unsigned int if2,
++ unsigned int spectrum_from,
++ unsigned int spectrum_to,
++ unsigned char *buf,
++ int *ret_sel,
++ unsigned int xogc) //all in Hz
++{
++ struct microtune_priv *priv = fe->tuner_priv;
++ unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1,
++ desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq;
++
++ fref= 5250 *1000; //5.25MHz
++ desired_lo1=rfin+if1;
++
++ lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000);
++ lo1n=lo1/8;
++ lo1a=lo1-(lo1n*8);
++
++ s=rfin/1000/1000+1090;
++
++ if(optimize_vco) {
++ if(s>1890) sel=0;
++ else if(s>1720) sel=1;
++ else if(s>1530) sel=2;
++ else if(s>1370) sel=3;
++ else sel=4; // >1090
++ }
++ else {
++ if(s>1790) sel=0; // <1958
++ else if(s>1617) sel=1;
++ else if(s>1449) sel=2;
++ else if(s>1291) sel=3;
++ else sel=4; // >1090
++ }
++ *ret_sel=sel;
++
++ lo1freq=(lo1a+8*lo1n)*fref;
++
++ tuner_dbg("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n",
++ rfin,lo1,lo1n,lo1a,sel,lo1freq);
++
++ desired_lo2=lo1freq-rfin-if2;
++ lo2=(desired_lo2)/fref;
++ lo2n=lo2/8;
++ lo2a=lo2-(lo2n*8);
++ lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith
++ lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000;
++
++ tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n",
++ rfin,lo2,lo2n,lo2a,lo2num,lo2freq);
++
++ if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) {
++ tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n",
++ lo1a, lo1n, lo2a,lo2n);
++ return(-1);
++ }
++
++ mt2032_spurcheck(fe, lo1freq, desired_lo2, spectrum_from, spectrum_to);
++ // should recalculate lo1 (one step up/down)
++
++ // set up MT2032 register map for transfer over i2c
++ buf[0]=lo1n-1;
++ buf[1]=lo1a | (sel<<4);
++ buf[2]=0x86; // LOGC
++ buf[3]=0x0f; //reserved
++ buf[4]=0x1f;
++ buf[5]=(lo2n-1) | (lo2a<<5);
++ if(rfin >400*1000*1000)
++ buf[6]=0xe4;
++ else
++ buf[6]=0xf4; // set PKEN per rev 1.2
++ buf[7]=8+xogc;
++ buf[8]=0xc3; //reserved
++ buf[9]=0x4e; //reserved
++ buf[10]=0xec; //reserved
++ buf[11]=(lo2num&0xff);
++ buf[12]=(lo2num>>8) |0x80; // Lo2RST
++
++ return 0;
++}
++
++static int mt2032_check_lo_lock(struct dvb_frontend *fe)
++{
++ struct microtune_priv *priv = fe->tuner_priv;
++ int try,lock=0;
++ unsigned char buf[2];
++
++ for(try=0;try<10;try++) {
++ buf[0]=0x0e;
++ tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
++ tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
++ tuner_dbg("mt2032 Reg.E=0x%02x\n",buf[0]);
++ lock=buf[0] &0x06;
++
++ if (lock==6)
++ break;
++
++ tuner_dbg("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]);
++ udelay(1000);
++ }
++ return lock;
++}
++
++static int mt2032_optimize_vco(struct dvb_frontend *fe,int sel,int lock)
++{
++ struct microtune_priv *priv = fe->tuner_priv;
++ unsigned char buf[2];
++ int tad1;
++
++ buf[0]=0x0f;
++ tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
++ tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
++ tuner_dbg("mt2032 Reg.F=0x%02x\n",buf[0]);
++ tad1=buf[0]&0x07;
++
++ if(tad1 ==0) return lock;
++ if(tad1 ==1) return lock;
++
++ if(tad1==2) {
++ if(sel==0)
++ return lock;
++ else sel--;
++ }
++ else {
++ if(sel<4)
++ sel++;
++ else
++ return lock;
++ }
++
++ tuner_dbg("mt2032 optimize_vco: sel=%d\n",sel);
++
++ buf[0]=0x0f;
++ buf[1]=sel;
++ tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
++ lock=mt2032_check_lo_lock(fe);
++ return lock;
++}
++
++
++static void mt2032_set_if_freq(struct dvb_frontend *fe, unsigned int rfin,
++ unsigned int if1, unsigned int if2,
++ unsigned int from, unsigned int to)
++{
++ unsigned char buf[21];
++ int lint_try,ret,sel,lock=0;
++ struct microtune_priv *priv = fe->tuner_priv;
++
++ tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n",
++ rfin,if1,if2,from,to);
++
++ buf[0]=0;
++ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
++ tuner_i2c_xfer_recv(&priv->i2c_props,buf,21);
++
++ buf[0]=0;
++ ret=mt2032_compute_freq(fe,rfin,if1,if2,from,to,&buf[1],&sel,priv->xogc);
++ if (ret<0)
++ return;
++
++ // send only the relevant registers per Rev. 1.2
++ buf[0]=0;
++ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,4);
++ buf[5]=5;
++ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,4);
++ buf[11]=11;
++ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+11,3);
++ if(ret!=3)
++ tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret);
++
++ // wait for PLLs to lock (per manual), retry LINT if not.
++ for(lint_try=0; lint_try<2; lint_try++) {
++ lock=mt2032_check_lo_lock(fe);
++
++ if(optimize_vco)
++ lock=mt2032_optimize_vco(fe,sel,lock);
++ if(lock==6) break;
++
++ tuner_dbg("mt2032: re-init PLLs by LINT\n");
++ buf[0]=7;
++ buf[1]=0x80 +8+priv->xogc; // set LINT to re-init PLLs
++ tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
++ mdelay(10);
++ buf[1]=8+priv->xogc;
++ tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
++ }
++
++ if (lock!=6)
++ tuner_warn("MT2032 Fatal Error: PLLs didn't lock.\n");
++
++ buf[0]=2;
++ buf[1]=0x20; // LOGC for optimal phase noise
++ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
++ if (ret!=2)
++ tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
++}
++
++
++static int mt2032_set_tv_freq(struct dvb_frontend *fe,
++ struct analog_parameters *params)
++{
++ int if2,from,to;
++
++ // signal bandwidth and picture carrier
++ if (params->std & V4L2_STD_525_60) {
++ // NTSC
++ from = 40750*1000;
++ to = 46750*1000;
++ if2 = 45750*1000;
++ } else {
++ // PAL
++ from = 32900*1000;
++ to = 39900*1000;
++ if2 = 38900*1000;
++ }
++
++ mt2032_set_if_freq(fe, params->frequency*62500,
++ 1090*1000*1000, if2, from, to);
++
++ return 0;
++}
++
++static int mt2032_set_radio_freq(struct dvb_frontend *fe,
++ struct analog_parameters *params)
++{
++ struct microtune_priv *priv = fe->tuner_priv;
++ int if2;
++
++ if (params->std & V4L2_STD_525_60) {
++ tuner_dbg("pinnacle ntsc\n");
++ if2 = 41300 * 1000;
++ } else {
++ tuner_dbg("pinnacle pal\n");
++ if2 = 33300 * 1000;
++ }
++
++ // per Manual for FM tuning: first if center freq. 1085 MHz
++ mt2032_set_if_freq(fe, params->frequency * 125 / 2,
++ 1085*1000*1000,if2,if2,if2);
++
++ return 0;
++}
++
++static int mt2032_set_params(struct dvb_frontend *fe,
++ struct analog_parameters *params)
++{
++ struct microtune_priv *priv = fe->tuner_priv;
++ int ret = -EINVAL;
++
++ switch (params->mode) {
++ case V4L2_TUNER_RADIO:
++ ret = mt2032_set_radio_freq(fe, params);
++ priv->frequency = params->frequency * 125 / 2;
++ break;
++ case V4L2_TUNER_ANALOG_TV:
++ case V4L2_TUNER_DIGITAL_TV:
++ ret = mt2032_set_tv_freq(fe, params);
++ priv->frequency = params->frequency * 62500;
++ break;
++ }
++
++ return ret;
++}
++
++static struct dvb_tuner_ops mt2032_tuner_ops = {
++ .set_analog_params = mt2032_set_params,
++ .release = microtune_release,
++ .get_frequency = microtune_get_frequency,
++};
++
++// Initialization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
++static int mt2032_init(struct dvb_frontend *fe)
++{
++ struct microtune_priv *priv = fe->tuner_priv;
++ unsigned char buf[21];
++ int ret,xogc,xok=0;
++
++ // Initialize Registers per spec.
++ buf[1]=2; // Index to register 2
++ buf[2]=0xff;
++ buf[3]=0x0f;
++ buf[4]=0x1f;
++ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+1,4);
++
++ buf[5]=6; // Index register 6
++ buf[6]=0xe4;
++ buf[7]=0x8f;
++ buf[8]=0xc3;
++ buf[9]=0x4e;
++ buf[10]=0xec;
++ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,6);
++
++ buf[12]=13; // Index register 13
++ buf[13]=0x32;
++ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+12,2);
++
++ // Adjust XOGC (register 7), wait for XOK
++ xogc=7;
++ do {
++ tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
++ mdelay(10);
++ buf[0]=0x0e;
++ tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
++ tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
++ xok=buf[0]&0x01;
++ tuner_dbg("mt2032: xok = 0x%02x\n",xok);
++ if (xok == 1) break;
++
++ xogc--;
++ tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
++ if (xogc == 3) {
++ xogc=4; // min. 4 per spec
++ break;
++ }
++ buf[0]=0x07;
++ buf[1]=0x88 + xogc;
++ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
++ if (ret!=2)
++ tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
++ } while (xok != 1 );
++ priv->xogc=xogc;
++
++ memcpy(&fe->ops.tuner_ops, &mt2032_tuner_ops, sizeof(struct dvb_tuner_ops));
++
++ return(1);
++}
++
++static void mt2050_set_antenna(struct dvb_frontend *fe, unsigned char antenna)
++{
++ struct microtune_priv *priv = fe->tuner_priv;
++ unsigned char buf[2];
++ int ret;
++
++ buf[0] = 6;
++ buf[1] = antenna ? 0x11 : 0x10;
++ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
++ tuner_dbg("mt2050: enabled antenna connector %d\n", antenna);
++}
++
++static void mt2050_set_if_freq(struct dvb_frontend *fe,unsigned int freq, unsigned int if2)
++{
++ struct microtune_priv *priv = fe->tuner_priv;
++ unsigned int if1=1218*1000*1000;
++ unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b;
++ int ret;
++ unsigned char buf[6];
++
++ tuner_dbg("mt2050_set_if_freq freq=%d if1=%d if2=%d\n",
++ freq,if1,if2);
++
++ f_lo1=freq+if1;
++ f_lo1=(f_lo1/1000000)*1000000;
++
++ f_lo2=f_lo1-freq-if2;
++ f_lo2=(f_lo2/50000)*50000;
++
++ lo1=f_lo1/4000000;
++ lo2=f_lo2/4000000;
++
++ f_lo1_modulo= f_lo1-(lo1*4000000);
++ f_lo2_modulo= f_lo2-(lo2*4000000);
++
++ num1=4*f_lo1_modulo/4000000;
++ num2=4096*(f_lo2_modulo/1000)/4000;
++
++ // todo spurchecks
++
++ div1a=(lo1/12)-1;
++ div1b=lo1-(div1a+1)*12;
++
++ div2a=(lo2/8)-1;
++ div2b=lo2-(div2a+1)*8;
++
++ if (debug > 1) {
++ tuner_dbg("lo1 lo2 = %d %d\n", lo1, lo2);
++ tuner_dbg("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n",
++ num1,num2,div1a,div1b,div2a,div2b);
++ }
++
++ buf[0]=1;
++ buf[1]= 4*div1b + num1;
++ if(freq<275*1000*1000) buf[1] = buf[1]|0x80;
++
++ buf[2]=div1a;
++ buf[3]=32*div2b + num2/256;
++ buf[4]=num2-(num2/256)*256;
++ buf[5]=div2a;
++ if(num2!=0) buf[5]=buf[5]|0x40;
++
++ if (debug > 1) {
++ int i;
++ tuner_dbg("bufs is: ");
++ for(i=0;i<6;i++)
++ printk("%x ",buf[i]);
++ printk("\n");
++ }
++
++ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,6);
++ if (ret!=6)
++ tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret);
++}
++
++static int mt2050_set_tv_freq(struct dvb_frontend *fe,
++ struct analog_parameters *params)
++{
++ unsigned int if2;
++
++ if (params->std & V4L2_STD_525_60) {
++ // NTSC
++ if2 = 45750*1000;
++ } else {
++ // PAL
++ if2 = 38900*1000;
++ }
++ if (V4L2_TUNER_DIGITAL_TV == params->mode) {
++ // DVB (pinnacle 300i)
++ if2 = 36150*1000;
++ }
++ mt2050_set_if_freq(fe, params->frequency*62500, if2);
++ mt2050_set_antenna(fe, tv_antenna);
++
++ return 0;
++}
++
++static int mt2050_set_radio_freq(struct dvb_frontend *fe,
++ struct analog_parameters *params)
++{
++ struct microtune_priv *priv = fe->tuner_priv;
++ int if2;
++
++ if (params->std & V4L2_STD_525_60) {
++ tuner_dbg("pinnacle ntsc\n");
++ if2 = 41300 * 1000;
++ } else {
++ tuner_dbg("pinnacle pal\n");
++ if2 = 33300 * 1000;
++ }
++
++ mt2050_set_if_freq(fe, params->frequency * 125 / 2, if2);
++ mt2050_set_antenna(fe, radio_antenna);
++
++ return 0;
++}
++
++static int mt2050_set_params(struct dvb_frontend *fe,
++ struct analog_parameters *params)
++{
++ struct microtune_priv *priv = fe->tuner_priv;
++ int ret = -EINVAL;
++
++ switch (params->mode) {
++ case V4L2_TUNER_RADIO:
++ ret = mt2050_set_radio_freq(fe, params);
++ priv->frequency = params->frequency * 125 / 2;
++ break;
++ case V4L2_TUNER_ANALOG_TV:
++ case V4L2_TUNER_DIGITAL_TV:
++ ret = mt2050_set_tv_freq(fe, params);
++ priv->frequency = params->frequency * 62500;
++ break;
++ }
++
++ return ret;
++}
++
++static struct dvb_tuner_ops mt2050_tuner_ops = {
++ .set_analog_params = mt2050_set_params,
++ .release = microtune_release,
++ .get_frequency = microtune_get_frequency,
++};
++
++static int mt2050_init(struct dvb_frontend *fe)
++{
++ struct microtune_priv *priv = fe->tuner_priv;
++ unsigned char buf[2];
++ int ret;
++
++ buf[0]=6;
++ buf[1]=0x10;
++ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // power
++
++ buf[0]=0x0f;
++ buf[1]=0x0f;
++ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // m1lo
++
++ buf[0]=0x0d;
++ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
++ tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
++
++ tuner_dbg("mt2050: sro is %x\n",buf[0]);
++
++ memcpy(&fe->ops.tuner_ops, &mt2050_tuner_ops, sizeof(struct dvb_tuner_ops));
++
++ return 0;
++}
++
++struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
++ struct i2c_adapter* i2c_adap,
++ u8 i2c_addr)
++{
++ struct microtune_priv *priv = NULL;
++ char *name;
++ unsigned char buf[21];
++ int company_code;
++
++ priv = kzalloc(sizeof(struct microtune_priv), GFP_KERNEL);
++ if (priv == NULL)
++ return NULL;
++ fe->tuner_priv = priv;
++
++ 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 */
++
++ memset(buf,0,sizeof(buf));
++
++ name = "unknown";
++
++ tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
++ tuner_i2c_xfer_recv(&priv->i2c_props,buf,21);
++ if (debug) {
++ int i;
++ tuner_dbg("MT20xx hexdump:");
++ for(i=0;i<21;i++) {
++ printk(" %02x",buf[i]);
++ if(((i+1)%8)==0) printk(" ");
++ }
++ printk("\n");
++ }
++ company_code = buf[0x11] << 8 | buf[0x12];
++ tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n",
++ company_code,buf[0x13],buf[0x14]);
++
++
++ if (buf[0x13] < ARRAY_SIZE(microtune_part) &&
++ NULL != microtune_part[buf[0x13]])
++ name = microtune_part[buf[0x13]];
++ switch (buf[0x13]) {
++ case MT2032:
++ mt2032_init(fe);
++ break;
++ case MT2050:
++ mt2050_init(fe);
++ break;
++ default:
++ tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n",
++ name);
++ return NULL;
++ }
++
++ strlcpy(fe->ops.tuner_ops.info.name, name,
++ sizeof(fe->ops.tuner_ops.info.name));
++ tuner_info("microtune %s found, OK\n",name);
++ return fe;
++}
++
++EXPORT_SYMBOL_GPL(microtune_attach);
++
++MODULE_DESCRIPTION("Microtune tuner driver");
++MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
++MODULE_LICENSE("GPL");
++
++/*
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-basic-offset: 8
++ * End:
++ */
+diff --git a/drivers/media/common/tuners/mt20xx.h b/drivers/media/common/tuners/mt20xx.h
+new file mode 100644
+index 0000000..259553a
+--- /dev/null
++++ b/drivers/media/common/tuners/mt20xx.h
+@@ -0,0 +1,37 @@
++/*
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You 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 __MT20XX_H__
++#define __MT20XX_H__
++
++#include <linux/i2c.h>
++#include "dvb_frontend.h"
++
++#if defined(CONFIG_MEDIA_TUNER_MT20XX) || (defined(CONFIG_MEDIA_TUNER_MT20XX_MODULE) && defined(MODULE))
++extern struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
++ struct i2c_adapter* i2c_adap,
++ u8 i2c_addr);
++#else
++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", __func__);
++ return NULL;
++}
++#endif
++
++#endif /* __MT20XX_H__ */
+diff --git a/drivers/media/common/tuners/mt2131.c b/drivers/media/common/tuners/mt2131.c
+new file mode 100644
+index 0000000..e254bcf
+--- /dev/null
++++ b/drivers/media/common/tuners/mt2131.c
+@@ -0,0 +1,314 @@
++/*
++ * Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
++ *
++ * Copyright (c) 2006 Steven Toth <stoth at hauppauge.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/dvb/frontend.h>
++#include <linux/i2c.h>
++
++#include "dvb_frontend.h"
++
++#include "mt2131.h"
++#include "mt2131_priv.h"
++
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
++
++#define dprintk(level,fmt, arg...) if (debug >= level) \
++ printk(KERN_INFO "%s: " fmt, "mt2131", ## arg)
++
++static u8 mt2131_config1[] = {
++ 0x01,
++ 0x50, 0x00, 0x50, 0x80, 0x00, 0x49, 0xfa, 0x88,
++ 0x08, 0x77, 0x41, 0x04, 0x00, 0x00, 0x00, 0x32,
++ 0x7f, 0xda, 0x4c, 0x00, 0x10, 0xaa, 0x78, 0x80,
++ 0xff, 0x68, 0xa0, 0xff, 0xdd, 0x00, 0x00
++};
++
++static u8 mt2131_config2[] = {
++ 0x10,
++ 0x7f, 0xc8, 0x0a, 0x5f, 0x00, 0x04
++};
++
++static int mt2131_readreg(struct mt2131_priv *priv, u8 reg, u8 *val)
++{
++ struct i2c_msg msg[2] = {
++ { .addr = priv->cfg->i2c_address, .flags = 0,
++ .buf = ®, .len = 1 },
++ { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD,
++ .buf = val, .len = 1 },
++ };
++
++ if (i2c_transfer(priv->i2c, msg, 2) != 2) {
++ printk(KERN_WARNING "mt2131 I2C read failed\n");
++ return -EREMOTEIO;
++ }
++ return 0;
++}
++
++static int mt2131_writereg(struct mt2131_priv *priv, u8 reg, u8 val)
++{
++ u8 buf[2] = { reg, val };
++ struct i2c_msg msg = { .addr = priv->cfg->i2c_address, .flags = 0,
++ .buf = buf, .len = 2 };
++
++ if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
++ printk(KERN_WARNING "mt2131 I2C write failed\n");
++ return -EREMOTEIO;
++ }
++ return 0;
++}
++
++static int mt2131_writeregs(struct mt2131_priv *priv,u8 *buf, u8 len)
++{
++ struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
++ .flags = 0, .buf = buf, .len = len };
++
++ if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
++ printk(KERN_WARNING "mt2131 I2C write failed (len=%i)\n",
++ (int)len);
++ return -EREMOTEIO;
++ }
++ return 0;
++}
++
++static int mt2131_set_params(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *params)
++{
++ struct mt2131_priv *priv;
++ int ret=0, i;
++ u32 freq;
++ u8 if_band_center;
++ u32 f_lo1, f_lo2;
++ u32 div1, num1, div2, num2;
++ u8 b[8];
++ u8 lockval = 0;
++
++ priv = fe->tuner_priv;
++ if (fe->ops.info.type == FE_OFDM)
++ priv->bandwidth = params->u.ofdm.bandwidth;
++ else
++ priv->bandwidth = 0;
++
++ freq = params->frequency / 1000; // Hz -> kHz
++ dprintk(1, "%s() freq=%d\n", __func__, freq);
++
++ f_lo1 = freq + MT2131_IF1 * 1000;
++ f_lo1 = (f_lo1 / 250) * 250;
++ f_lo2 = f_lo1 - freq - MT2131_IF2;
++
++ priv->frequency = (f_lo1 - f_lo2 - MT2131_IF2) * 1000;
++
++ /* Frequency LO1 = 16MHz * (DIV1 + NUM1/8192 ) */
++ num1 = f_lo1 * 64 / (MT2131_FREF / 128);
++ div1 = num1 / 8192;
++ num1 &= 0x1fff;
++
++ /* Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 ) */
++ num2 = f_lo2 * 64 / (MT2131_FREF / 128);
++ div2 = num2 / 8192;
++ num2 &= 0x1fff;
++
++ if (freq <= 82500) if_band_center = 0x00; else
++ if (freq <= 137500) if_band_center = 0x01; else
++ if (freq <= 192500) if_band_center = 0x02; else
++ if (freq <= 247500) if_band_center = 0x03; else
++ if (freq <= 302500) if_band_center = 0x04; else
++ if (freq <= 357500) if_band_center = 0x05; else
++ if (freq <= 412500) if_band_center = 0x06; else
++ if (freq <= 467500) if_band_center = 0x07; else
++ if (freq <= 522500) if_band_center = 0x08; else
++ if (freq <= 577500) if_band_center = 0x09; else
++ if (freq <= 632500) if_band_center = 0x0A; else
++ if (freq <= 687500) if_band_center = 0x0B; else
++ if (freq <= 742500) if_band_center = 0x0C; else
++ if (freq <= 797500) if_band_center = 0x0D; else
++ if (freq <= 852500) if_band_center = 0x0E; else
++ if (freq <= 907500) if_band_center = 0x0F; else
++ if (freq <= 962500) if_band_center = 0x10; else
++ if (freq <= 1017500) if_band_center = 0x11; else
++ if (freq <= 1072500) if_band_center = 0x12; else if_band_center = 0x13;
++
++ b[0] = 1;
++ b[1] = (num1 >> 5) & 0xFF;
++ b[2] = (num1 & 0x1F);
++ b[3] = div1;
++ b[4] = (num2 >> 5) & 0xFF;
++ b[5] = num2 & 0x1F;
++ b[6] = div2;
++
++ dprintk(1, "IF1: %dMHz IF2: %dMHz\n", MT2131_IF1, MT2131_IF2);
++ dprintk(1, "PLL freq=%dkHz band=%d\n", (int)freq, (int)if_band_center);
++ dprintk(1, "PLL f_lo1=%dkHz f_lo2=%dkHz\n", (int)f_lo1, (int)f_lo2);
++ dprintk(1, "PLL div1=%d num1=%d div2=%d num2=%d\n",
++ (int)div1, (int)num1, (int)div2, (int)num2);
++ dprintk(1, "PLL [1..6]: %2x %2x %2x %2x %2x %2x\n",
++ (int)b[1], (int)b[2], (int)b[3], (int)b[4], (int)b[5],
++ (int)b[6]);
++
++ ret = mt2131_writeregs(priv,b,7);
++ if (ret < 0)
++ return ret;
++
++ mt2131_writereg(priv, 0x0b, if_band_center);
++
++ /* Wait for lock */
++ i = 0;
++ do {
++ mt2131_readreg(priv, 0x08, &lockval);
++ if ((lockval & 0x88) == 0x88)
++ break;
++ msleep(4);
++ i++;
++ } while (i < 10);
++
++ return ret;
++}
++
++static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
++{
++ struct mt2131_priv *priv = fe->tuner_priv;
++ dprintk(1, "%s()\n", __func__);
++ *frequency = priv->frequency;
++ return 0;
++}
++
++static int mt2131_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
++{
++ struct mt2131_priv *priv = fe->tuner_priv;
++ dprintk(1, "%s()\n", __func__);
++ *bandwidth = priv->bandwidth;
++ return 0;
++}
++
++static int mt2131_get_status(struct dvb_frontend *fe, u32 *status)
++{
++ struct mt2131_priv *priv = fe->tuner_priv;
++ u8 lock_status = 0;
++ u8 afc_status = 0;
++
++ *status = 0;
++
++ mt2131_readreg(priv, 0x08, &lock_status);
++ if ((lock_status & 0x88) == 0x88)
++ *status = TUNER_STATUS_LOCKED;
++
++ mt2131_readreg(priv, 0x09, &afc_status);
++ dprintk(1, "%s() - LO Status = 0x%x, AFC Status = 0x%x\n",
++ __func__, lock_status, afc_status);
++
++ return 0;
++}
++
++static int mt2131_init(struct dvb_frontend *fe)
++{
++ struct mt2131_priv *priv = fe->tuner_priv;
++ int ret;
++ dprintk(1, "%s()\n", __func__);
++
++ if ((ret = mt2131_writeregs(priv, mt2131_config1,
++ sizeof(mt2131_config1))) < 0)
++ return ret;
++
++ mt2131_writereg(priv, 0x0b, 0x09);
++ mt2131_writereg(priv, 0x15, 0x47);
++ mt2131_writereg(priv, 0x07, 0xf2);
++ mt2131_writereg(priv, 0x0b, 0x01);
++
++ if ((ret = mt2131_writeregs(priv, mt2131_config2,
++ sizeof(mt2131_config2))) < 0)
++ return ret;
++
++ return ret;
++}
++
++static int mt2131_release(struct dvb_frontend *fe)
++{
++ dprintk(1, "%s()\n", __func__);
++ kfree(fe->tuner_priv);
++ fe->tuner_priv = NULL;
++ return 0;
++}
++
++static const struct dvb_tuner_ops mt2131_tuner_ops = {
++ .info = {
++ .name = "Microtune MT2131",
++ .frequency_min = 48000000,
++ .frequency_max = 860000000,
++ .frequency_step = 50000,
++ },
++
++ .release = mt2131_release,
++ .init = mt2131_init,
++
++ .set_params = mt2131_set_params,
++ .get_frequency = mt2131_get_frequency,
++ .get_bandwidth = mt2131_get_bandwidth,
++ .get_status = mt2131_get_status
++};
++
++struct dvb_frontend * mt2131_attach(struct dvb_frontend *fe,
++ struct i2c_adapter *i2c,
++ struct mt2131_config *cfg, u16 if1)
++{
++ struct mt2131_priv *priv = NULL;
++ u8 id = 0;
++
++ dprintk(1, "%s()\n", __func__);
++
++ priv = kzalloc(sizeof(struct mt2131_priv), GFP_KERNEL);
++ if (priv == NULL)
++ return NULL;
++
++ priv->cfg = cfg;
++ priv->bandwidth = 6000000; /* 6MHz */
++ priv->i2c = i2c;
++
++ if (mt2131_readreg(priv, 0, &id) != 0) {
++ kfree(priv);
++ return NULL;
++ }
++ if ( (id != 0x3E) && (id != 0x3F) ) {
++ printk(KERN_ERR "MT2131: Device not found at addr 0x%02x\n",
++ cfg->i2c_address);
++ kfree(priv);
++ return NULL;
++ }
++
++ printk(KERN_INFO "MT2131: successfully identified at address 0x%02x\n",
++ cfg->i2c_address);
++ memcpy(&fe->ops.tuner_ops, &mt2131_tuner_ops,
++ sizeof(struct dvb_tuner_ops));
++
++ fe->tuner_priv = priv;
++ return fe;
++}
++EXPORT_SYMBOL(mt2131_attach);
++
++MODULE_AUTHOR("Steven Toth");
++MODULE_DESCRIPTION("Microtune MT2131 silicon tuner driver");
++MODULE_LICENSE("GPL");
++
++/*
++ * Local variables:
++ * c-basic-offset: 8
++ */
+diff --git a/drivers/media/common/tuners/mt2131.h b/drivers/media/common/tuners/mt2131.h
+new file mode 100644
+index 0000000..cd8376f
+--- /dev/null
++++ b/drivers/media/common/tuners/mt2131.h
+@@ -0,0 +1,54 @@
++/*
++ * Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
++ *
++ * Copyright (c) 2006 Steven Toth <stoth at hauppauge.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __MT2131_H__
++#define __MT2131_H__
++
++struct dvb_frontend;
++struct i2c_adapter;
++
++struct mt2131_config {
++ u8 i2c_address;
++ u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */
++};
++
++#if defined(CONFIG_MEDIA_TUNER_MT2131) || (defined(CONFIG_MEDIA_TUNER_MT2131_MODULE) && defined(MODULE))
++extern struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
++ struct i2c_adapter *i2c,
++ struct mt2131_config *cfg,
++ u16 if1);
++#else
++static inline struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
++ struct i2c_adapter *i2c,
++ struct mt2131_config *cfg,
++ u16 if1)
++{
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++ return NULL;
++}
++#endif /* CONFIG_MEDIA_TUNER_MT2131 */
++
++#endif /* __MT2131_H__ */
++
++/*
++ * Local variables:
++ * c-basic-offset: 8
++ */
+diff --git a/drivers/media/common/tuners/mt2131_priv.h b/drivers/media/common/tuners/mt2131_priv.h
+new file mode 100644
+index 0000000..e930759
+--- /dev/null
++++ b/drivers/media/common/tuners/mt2131_priv.h
+@@ -0,0 +1,49 @@
++/*
++ * Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
++ *
++ * Copyright (c) 2006 Steven Toth <stoth at hauppauge.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __MT2131_PRIV_H__
++#define __MT2131_PRIV_H__
++
++/* Regs */
++#define MT2131_PWR 0x07
++#define MT2131_UPC_1 0x0b
++#define MT2131_AGC_RL 0x10
++#define MT2131_MISC_2 0x15
++
++/* frequency values in KHz */
++#define MT2131_IF1 1220
++#define MT2131_IF2 44000
++#define MT2131_FREF 16000
++
++struct mt2131_priv {
++ struct mt2131_config *cfg;
++ struct i2c_adapter *i2c;
++
++ u32 frequency;
++ u32 bandwidth;
++};
++
++#endif /* __MT2131_PRIV_H__ */
++
++/*
++ * Local variables:
++ * c-basic-offset: 8
++ */
+diff --git a/drivers/media/common/tuners/mt2266.c b/drivers/media/common/tuners/mt2266.c
+new file mode 100644
+index 0000000..54b18f9
+--- /dev/null
++++ b/drivers/media/common/tuners/mt2266.c
+@@ -0,0 +1,351 @@
++/*
++ * Driver for Microtune MT2266 "Direct conversion low power broadband tuner"
++ *
++ * Copyright (c) 2007 Olivier DANET <odanet at caramail.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/dvb/frontend.h>
++#include <linux/i2c.h>
++
++#include "dvb_frontend.h"
++#include "mt2266.h"
++
++#define I2C_ADDRESS 0x60
++
++#define REG_PART_REV 0
++#define REG_TUNE 1
++#define REG_BAND 6
++#define REG_BANDWIDTH 8
++#define REG_LOCK 0x12
++
++#define PART_REV 0x85
++
++struct mt2266_priv {
++ struct mt2266_config *cfg;
++ struct i2c_adapter *i2c;
++
++ u32 frequency;
++ u32 bandwidth;
++ u8 band;
++};
++
++#define MT2266_VHF 1
++#define MT2266_UHF 0
++
++/* Here, frequencies are expressed in kiloHertz to avoid 32 bits overflows */
++
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
++
++#define dprintk(args...) do { if (debug) {printk(KERN_DEBUG "MT2266: " args); printk("\n"); }} while (0)
++
++// Reads a single register
++static int mt2266_readreg(struct mt2266_priv *priv, u8 reg, u8 *val)
+{
-+ return min_t(unsigned int, value, INT_MAX);
++ struct i2c_msg msg[2] = {
++ { .addr = priv->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 },
++ { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val, .len = 1 },
++ };
++ if (i2c_transfer(priv->i2c, msg, 2) != 2) {
++ printk(KERN_WARNING "MT2266 I2C read failed\n");
++ return -EREMOTEIO;
++ }
++ return 0;
+}
+
- 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)
++// Writes a single register
++static int mt2266_writereg(struct mt2266_priv *priv, u8 reg, u8 val)
+{
-+ 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;
++ u8 buf[2] = { reg, val };
++ struct i2c_msg msg = {
++ .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2
++ };
++ if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
++ printk(KERN_WARNING "MT2266 I2C write failed\n");
++ return -EREMOTEIO;
+ }
++ return 0;
+}
+
-+static int map_number_of_vls(struct ehca_shca *shca, u32 vl_cap)
++// Writes a set of consecutive registers
++static int mt2266_writeregs(struct mt2266_priv *priv,u8 *buf, u8 len)
+{
-+ 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;
++ struct i2c_msg msg = {
++ .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = len
++ };
++ if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
++ printk(KERN_WARNING "MT2266 I2C write failed (len=%i)\n",(int)len);
++ return -EREMOTEIO;
+ }
++ 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;
++// Initialisation sequences
++static u8 mt2266_init1[] = { REG_TUNE, 0x00, 0x00, 0x28,
++ 0x00, 0x52, 0x99, 0x3f };
++
++static u8 mt2266_init2[] = {
++ 0x17, 0x6d, 0x71, 0x61, 0xc0, 0xbf, 0xff, 0xdc, 0x00, 0x0a, 0xd4,
++ 0x03, 0x64, 0x64, 0x64, 0x64, 0x22, 0xaa, 0xf2, 0x1e, 0x80, 0x14,
++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7f, 0x5e, 0x3f, 0xff, 0xff,
++ 0xff, 0x00, 0x77, 0x0f, 0x2d
++};
++
++static u8 mt2266_init_8mhz[] = { REG_BANDWIDTH, 0x22, 0x22, 0x22, 0x22,
++ 0x22, 0x22, 0x22, 0x22 };
++
++static u8 mt2266_init_7mhz[] = { REG_BANDWIDTH, 0x32, 0x32, 0x32, 0x32,
++ 0x32, 0x32, 0x32, 0x32 };
++
++static u8 mt2266_init_6mhz[] = { REG_BANDWIDTH, 0xa7, 0xa7, 0xa7, 0xa7,
++ 0xa7, 0xa7, 0xa7, 0xa7 };
++
++static u8 mt2266_uhf[] = { 0x1d, 0xdc, 0x00, 0x0a, 0xd4, 0x03, 0x64, 0x64,
++ 0x64, 0x64, 0x22, 0xaa, 0xf2, 0x1e, 0x80, 0x14 };
++
++static u8 mt2266_vhf[] = { 0x1d, 0xfe, 0x00, 0x00, 0xb4, 0x03, 0xa5, 0xa5,
++ 0xa5, 0xa5, 0x82, 0xaa, 0xf1, 0x17, 0x80, 0x1f };
++
++#define FREF 30000 // Quartz oscillator 30 MHz
++
++static int mt2266_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
++{
++ struct mt2266_priv *priv;
++ int ret=0;
++ u32 freq;
++ u32 tune;
++ u8 lnaband;
++ u8 b[10];
++ int i;
++ u8 band;
++
++ priv = fe->tuner_priv;
++
++ freq = params->frequency / 1000; // Hz -> kHz
++ if (freq < 470000 && freq > 230000)
++ return -EINVAL; /* Gap between VHF and UHF bands */
++ priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
++ priv->frequency = freq * 1000;
++
++ tune = 2 * freq * (8192/16) / (FREF/16);
++ band = (freq < 300000) ? MT2266_VHF : MT2266_UHF;
++ if (band == MT2266_VHF)
++ tune *= 2;
++
++ switch (params->u.ofdm.bandwidth) {
++ case BANDWIDTH_6_MHZ:
++ mt2266_writeregs(priv, mt2266_init_6mhz,
++ sizeof(mt2266_init_6mhz));
++ break;
++ case BANDWIDTH_7_MHZ:
++ mt2266_writeregs(priv, mt2266_init_7mhz,
++ sizeof(mt2266_init_7mhz));
++ break;
++ case BANDWIDTH_8_MHZ:
++ default:
++ mt2266_writeregs(priv, mt2266_init_8mhz,
++ sizeof(mt2266_init_8mhz));
++ break;
++ }
++
++ if (band == MT2266_VHF && priv->band == MT2266_UHF) {
++ dprintk("Switch from UHF to VHF");
++ mt2266_writereg(priv, 0x05, 0x04);
++ mt2266_writereg(priv, 0x19, 0x61);
++ mt2266_writeregs(priv, mt2266_vhf, sizeof(mt2266_vhf));
++ } else if (band == MT2266_UHF && priv->band == MT2266_VHF) {
++ dprintk("Switch from VHF to UHF");
++ mt2266_writereg(priv, 0x05, 0x52);
++ mt2266_writereg(priv, 0x19, 0x61);
++ mt2266_writeregs(priv, mt2266_uhf, sizeof(mt2266_uhf));
++ }
++ msleep(10);
++
++ if (freq <= 495000)
++ lnaband = 0xEE;
++ else if (freq <= 525000)
++ lnaband = 0xDD;
++ else if (freq <= 550000)
++ lnaband = 0xCC;
++ else if (freq <= 580000)
++ lnaband = 0xBB;
++ else if (freq <= 605000)
++ lnaband = 0xAA;
++ else if (freq <= 630000)
++ lnaband = 0x99;
++ else if (freq <= 655000)
++ lnaband = 0x88;
++ else if (freq <= 685000)
++ lnaband = 0x77;
++ else if (freq <= 710000)
++ lnaband = 0x66;
++ else if (freq <= 735000)
++ lnaband = 0x55;
++ else if (freq <= 765000)
++ lnaband = 0x44;
++ else if (freq <= 802000)
++ lnaband = 0x33;
++ else if (freq <= 840000)
++ lnaband = 0x22;
+ else
-+ props->max_msg_sz = 0x1 << 31;
- props->bad_pkey_cntr = rblock->bad_pkey_cntr;
- props->qkey_viol_cntr = rblock->qkey_viol_cntr;
- props->pkey_tbl_len = rblock->pkey_tbl_len;
-@@ -186,6 +216,7 @@ int ehca_query_port(struct ib_device *ibdev,
- props->sm_sl = rblock->sm_sl;
- props->subnet_timeout = rblock->subnet_timeout;
- props->init_type_reply = rblock->init_type_reply;
-+ props->max_vl_num = map_number_of_vls(shca, rblock->vl_cap);
-
- if (rblock->state && rblock->phys_width) {
- props->phys_state = rblock->phys_pstate;
-@@ -314,7 +345,7 @@ query_gid1:
- return ret;
- }
-
--const u32 allowed_port_caps = (
-+static const u32 allowed_port_caps = (
- IB_PORT_SM | IB_PORT_LED_INFO_SUP | IB_PORT_CM_SUP |
- IB_PORT_SNMP_TUNNEL_SUP | IB_PORT_DEVICE_MGMT_SUP |
- IB_PORT_VENDOR_CLASS_SUP);
-diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
-index a86ebcc..65b3362 100644
---- a/drivers/infiniband/hw/ehca/ehca_main.c
-+++ b/drivers/infiniband/hw/ehca/ehca_main.c
-@@ -57,16 +57,17 @@ MODULE_AUTHOR("Christoph Raisch <raisch at de.ibm.com>");
- MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
- MODULE_VERSION(HCAD_VERSION);
-
--int ehca_open_aqp1 = 0;
-+static int ehca_open_aqp1 = 0;
-+static int ehca_hw_level = 0;
-+static int ehca_poll_all_eqs = 1;
-+static int ehca_mr_largepage = 1;
++ lnaband = 0x11;
+
- int ehca_debug_level = 0;
--int ehca_hw_level = 0;
- int ehca_nr_ports = 2;
- int ehca_use_hp_mr = 0;
- int ehca_port_act_time = 30;
--int ehca_poll_all_eqs = 1;
- int ehca_static_rate = -1;
- int ehca_scaling_code = 0;
--int ehca_mr_largepage = 1;
- int ehca_lock_hcalls = -1;
-
- module_param_named(open_aqp1, ehca_open_aqp1, int, S_IRUGO);
-@@ -396,7 +397,7 @@ init_node_guid1:
- return ret;
- }
-
--int ehca_init_device(struct ehca_shca *shca)
-+static int ehca_init_device(struct ehca_shca *shca)
- {
- int ret;
-
-@@ -579,8 +580,8 @@ static ssize_t ehca_store_debug_level(struct device_driver *ddp,
- return 1;
- }
-
--DRIVER_ATTR(debug_level, S_IRUSR | S_IWUSR,
-- ehca_show_debug_level, ehca_store_debug_level);
-+static DRIVER_ATTR(debug_level, S_IRUSR | S_IWUSR,
-+ ehca_show_debug_level, ehca_store_debug_level);
-
- static struct attribute *ehca_drv_attrs[] = {
- &driver_attr_debug_level.attr,
-@@ -941,7 +942,7 @@ void ehca_poll_eqs(unsigned long data)
- spin_unlock(&shca_list_lock);
- }
-
--int __init ehca_module_init(void)
-+static int __init ehca_module_init(void)
- {
- int ret;
-
-@@ -988,7 +989,7 @@ module_init1:
- return ret;
- };
-
--void __exit ehca_module_exit(void)
-+static void __exit ehca_module_exit(void)
- {
- if (ehca_poll_all_eqs == 1)
- del_timer_sync(&poll_eqs_timer);
-diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
-index e239bbf..f26997f 100644
---- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
-+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
-@@ -40,8 +40,6 @@
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
--#include <asm/current.h>
--
- #include <rdma/ib_umem.h>
-
- #include "ehca_iverbs.h"
-@@ -419,7 +417,6 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
- struct ehca_shca *shca =
- container_of(mr->device, struct ehca_shca, ib_device);
- struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
-- struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd);
- u64 new_size;
- u64 *new_start;
- u32 new_acl;
-@@ -429,15 +426,6 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
- u32 num_kpages = 0;
- u32 num_hwpages = 0;
- struct ehca_mr_pginfo pginfo;
-- u32 cur_pid = current->tgid;
--
-- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
-- (my_pd->ownpid != cur_pid)) {
-- ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x",
-- cur_pid, my_pd->ownpid);
-- ret = -EINVAL;
-- goto rereg_phys_mr_exit0;
-- }
-
- if (!(mr_rereg_mask & IB_MR_REREG_TRANS)) {
- /* TODO not supported, because PHYP rereg hCall needs pages */
-@@ -577,19 +565,9 @@ int ehca_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr)
- struct ehca_shca *shca =
- container_of(mr->device, struct ehca_shca, ib_device);
- struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
-- struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd);
-- u32 cur_pid = current->tgid;
- unsigned long sl_flags;
- struct ehca_mr_hipzout_parms hipzout;
-
-- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
-- (my_pd->ownpid != cur_pid)) {
-- ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x",
-- cur_pid, my_pd->ownpid);
-- ret = -EINVAL;
-- goto query_mr_exit0;
-- }
--
- if ((e_mr->flags & EHCA_MR_FLAG_FMR)) {
- ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p "
- "e_mr->flags=%x", mr, e_mr, e_mr->flags);
-@@ -634,16 +612,6 @@ int ehca_dereg_mr(struct ib_mr *mr)
- struct ehca_shca *shca =
- container_of(mr->device, struct ehca_shca, ib_device);
- struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
-- struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd);
-- u32 cur_pid = current->tgid;
--
-- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
-- (my_pd->ownpid != cur_pid)) {
-- ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x",
-- cur_pid, my_pd->ownpid);
-- ret = -EINVAL;
-- goto dereg_mr_exit0;
-- }
-
- if ((e_mr->flags & EHCA_MR_FLAG_FMR)) {
- ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p "
-@@ -1952,9 +1920,8 @@ next_kpage:
- return ret;
- }
-
--int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
-- u32 number,
-- u64 *kpage)
-+static int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
-+ u32 number, u64 *kpage)
- {
- int ret = 0;
- struct ib_phys_buf *pbuf;
-@@ -2012,9 +1979,8 @@ int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
- return ret;
- }
-
--int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
-- u32 number,
-- u64 *kpage)
-+static int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
-+ u32 number, u64 *kpage)
- {
- int ret = 0;
- u64 *fmrlist;
-diff --git a/drivers/infiniband/hw/ehca/ehca_pd.c b/drivers/infiniband/hw/ehca/ehca_pd.c
-index 43bcf08..2fe5548 100644
---- a/drivers/infiniband/hw/ehca/ehca_pd.c
-+++ b/drivers/infiniband/hw/ehca/ehca_pd.c
-@@ -38,8 +38,6 @@
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
--#include <asm/current.h>
--
- #include "ehca_tools.h"
- #include "ehca_iverbs.h"
-
-@@ -58,7 +56,6 @@ struct ib_pd *ehca_alloc_pd(struct ib_device *device,
- return ERR_PTR(-ENOMEM);
- }
-
-- pd->ownpid = current->tgid;
- for (i = 0; i < 2; i++) {
- INIT_LIST_HEAD(&pd->free[i]);
- INIT_LIST_HEAD(&pd->full[i]);
-@@ -85,18 +82,10 @@ struct ib_pd *ehca_alloc_pd(struct ib_device *device,
-
- int ehca_dealloc_pd(struct ib_pd *pd)
- {
-- u32 cur_pid = current->tgid;
- struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd);
- int i, leftovers = 0;
- struct ipz_small_queue_page *page, *tmp;
-
-- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
-- my_pd->ownpid != cur_pid) {
-- ehca_err(pd->device, "Invalid caller pid=%x ownpid=%x",
-- cur_pid, my_pd->ownpid);
-- return -EINVAL;
-- }
--
- for (i = 0; i < 2; i++) {
- list_splice(&my_pd->full[i], &my_pd->free[i]);
- list_for_each_entry_safe(page, tmp, &my_pd->free[i], list) {
-diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
-index 1012f15..3eb14a5 100644
---- a/drivers/infiniband/hw/ehca/ehca_qp.c
-+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
-@@ -43,9 +43,6 @@
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
--
--#include <asm/current.h>
--
- #include "ehca_classes.h"
- #include "ehca_tools.h"
- #include "ehca_qes.h"
-@@ -424,6 +421,9 @@ static struct ehca_qp *internal_create_qp(
- u32 swqe_size = 0, rwqe_size = 0, ib_qp_num;
- unsigned long flags;
-
-+ if (init_attr->create_flags)
-+ return ERR_PTR(-EINVAL);
++ b[0] = REG_TUNE;
++ b[1] = (tune >> 8) & 0x1F;
++ b[2] = tune & 0xFF;
++ b[3] = tune >> 13;
++ mt2266_writeregs(priv,b,4);
++
++ dprintk("set_parms: tune=%d band=%d %s",
++ (int) tune, (int) lnaband,
++ (band == MT2266_UHF) ? "UHF" : "VHF");
++ dprintk("set_parms: [1..3]: %2x %2x %2x",
++ (int) b[1], (int) b[2], (int)b[3]);
++
++ if (band == MT2266_UHF) {
++ b[0] = 0x05;
++ b[1] = (priv->band == MT2266_VHF) ? 0x52 : 0x62;
++ b[2] = lnaband;
++ mt2266_writeregs(priv, b, 3);
++ }
+
- memset(&parms, 0, sizeof(parms));
- qp_type = init_attr->qp_type;
-
-@@ -1526,16 +1526,6 @@ int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
- struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,
- ib_device);
- struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
-- struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
-- ib_pd);
-- u32 cur_pid = current->tgid;
--
-- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
-- my_pd->ownpid != cur_pid) {
-- ehca_err(ibqp->pd->device, "Invalid caller pid=%x ownpid=%x",
-- cur_pid, my_pd->ownpid);
-- return -EINVAL;
-- }
-
- /* The if-block below caches qp_attr to be modified for GSI and SMI
- * qps during the initialization by ib_mad. When the respective port
-@@ -1636,23 +1626,13 @@ int ehca_query_qp(struct ib_qp *qp,
- int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
- {
- struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
-- struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
-- ib_pd);
- struct ehca_shca *shca = container_of(qp->device, struct ehca_shca,
- ib_device);
- struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
- struct hcp_modify_qp_control_block *qpcb;
-- u32 cur_pid = current->tgid;
- int cnt, ret = 0;
- u64 h_ret;
-
-- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
-- my_pd->ownpid != cur_pid) {
-- ehca_err(qp->device, "Invalid caller pid=%x ownpid=%x",
-- cur_pid, my_pd->ownpid);
-- return -EINVAL;
-- }
--
- if (qp_attr_mask & QP_ATTR_QUERY_NOT_SUPPORTED) {
- ehca_err(qp->device, "Invalid attribute mask "
- "ehca_qp=%p qp_num=%x qp_attr_mask=%x ",
-@@ -1797,8 +1777,6 @@ int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
- {
- struct ehca_qp *my_qp =
- container_of(ibsrq, struct ehca_qp, ib_srq);
-- struct ehca_pd *my_pd =
-- container_of(ibsrq->pd, struct ehca_pd, ib_pd);
- struct ehca_shca *shca =
- container_of(ibsrq->pd->device, struct ehca_shca, ib_device);
- struct hcp_modify_qp_control_block *mqpcb;
-@@ -1806,14 +1784,6 @@ int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
- u64 h_ret;
- int ret = 0;
-
-- u32 cur_pid = current->tgid;
-- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
-- my_pd->ownpid != cur_pid) {
-- ehca_err(ibsrq->pd->device, "Invalid caller pid=%x ownpid=%x",
-- cur_pid, my_pd->ownpid);
-- return -EINVAL;
-- }
--
- mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
- if (!mqpcb) {
- ehca_err(ibsrq->device, "Could not get zeroed page for mqpcb "
-@@ -1864,22 +1834,13 @@ modify_srq_exit0:
- int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr)
- {
- struct ehca_qp *my_qp = container_of(srq, struct ehca_qp, ib_srq);
-- struct ehca_pd *my_pd = container_of(srq->pd, struct ehca_pd, ib_pd);
- struct ehca_shca *shca = container_of(srq->device, struct ehca_shca,
- ib_device);
- struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
- struct hcp_modify_qp_control_block *qpcb;
-- u32 cur_pid = current->tgid;
- int ret = 0;
- u64 h_ret;
-
-- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
-- my_pd->ownpid != cur_pid) {
-- ehca_err(srq->device, "Invalid caller pid=%x ownpid=%x",
-- cur_pid, my_pd->ownpid);
-- return -EINVAL;
-- }
--
- qpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
- if (!qpcb) {
- ehca_err(srq->device, "Out of memory for qpcb "
-@@ -1919,7 +1880,6 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
- struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
- ib_pd);
- struct ehca_sport *sport = &shca->sport[my_qp->init_attr.port_num - 1];
-- u32 cur_pid = current->tgid;
- u32 qp_num = my_qp->real_qp_num;
- int ret;
- u64 h_ret;
-@@ -1934,11 +1894,6 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
- "user space qp_num=%x", qp_num);
- return -EINVAL;
- }
-- if (my_pd->ownpid != cur_pid) {
-- ehca_err(dev, "Invalid caller pid=%x ownpid=%x",
-- cur_pid, my_pd->ownpid);
-- return -EINVAL;
-- }
- }
-
- if (my_qp->send_cq) {
-diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
-index 2ce8cff..a20bbf4 100644
---- a/drivers/infiniband/hw/ehca/ehca_reqs.c
-+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
-@@ -188,7 +188,7 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
- if (send_wr->opcode == IB_WR_SEND_WITH_IMM ||
- send_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) {
- /* this might not work as long as HW does not support it */
-- wqe_p->immediate_data = be32_to_cpu(send_wr->imm_data);
-+ wqe_p->immediate_data = be32_to_cpu(send_wr->ex.imm_data);
- wqe_p->wr_flag |= WQE_WRFLAG_IMM_DATA_PRESENT;
- }
-
-diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h
-index 4a8346a..ec950bf 100644
---- a/drivers/infiniband/hw/ehca/ehca_tools.h
-+++ b/drivers/infiniband/hw/ehca/ehca_tools.h
-@@ -73,37 +73,37 @@ extern int ehca_debug_level;
- if (unlikely(ehca_debug_level)) \
- dev_printk(KERN_DEBUG, (ib_dev)->dma_device, \
- "PU%04x EHCA_DBG:%s " format "\n", \
-- raw_smp_processor_id(), __FUNCTION__, \
-+ raw_smp_processor_id(), __func__, \
- ## arg); \
- } while (0)
-
- #define ehca_info(ib_dev, format, arg...) \
- dev_info((ib_dev)->dma_device, "PU%04x EHCA_INFO:%s " format "\n", \
-- raw_smp_processor_id(), __FUNCTION__, ## arg)
-+ raw_smp_processor_id(), __func__, ## arg)
-
- #define ehca_warn(ib_dev, format, arg...) \
- dev_warn((ib_dev)->dma_device, "PU%04x EHCA_WARN:%s " format "\n", \
-- raw_smp_processor_id(), __FUNCTION__, ## arg)
-+ raw_smp_processor_id(), __func__, ## arg)
-
- #define ehca_err(ib_dev, format, arg...) \
- dev_err((ib_dev)->dma_device, "PU%04x EHCA_ERR:%s " format "\n", \
-- raw_smp_processor_id(), __FUNCTION__, ## arg)
-+ raw_smp_processor_id(), __func__, ## arg)
-
- /* use this one only if no ib_dev available */
- #define ehca_gen_dbg(format, arg...) \
- do { \
- if (unlikely(ehca_debug_level)) \
- printk(KERN_DEBUG "PU%04x EHCA_DBG:%s " format "\n", \
-- raw_smp_processor_id(), __FUNCTION__, ## arg); \
-+ raw_smp_processor_id(), __func__, ## arg); \
- } while (0)
-
- #define ehca_gen_warn(format, arg...) \
- printk(KERN_INFO "PU%04x EHCA_WARN:%s " format "\n", \
-- raw_smp_processor_id(), __FUNCTION__, ## arg)
-+ raw_smp_processor_id(), __func__, ## arg)
-
- #define ehca_gen_err(format, arg...) \
- printk(KERN_ERR "PU%04x EHCA_ERR:%s " format "\n", \
-- raw_smp_processor_id(), __FUNCTION__, ## arg)
-+ raw_smp_processor_id(), __func__, ## arg)
-
- /**
- * ehca_dmp - printk a memory block, whose length is n*8 bytes.
-@@ -118,7 +118,7 @@ extern int ehca_debug_level;
- for (x = 0; x < l; x += 16) { \
- printk(KERN_INFO "EHCA_DMP:%s " format \
- " adr=%p ofs=%04x %016lx %016lx\n", \
-- __FUNCTION__, ##args, deb, x, \
-+ __func__, ##args, deb, x, \
- *((u64 *)&deb[0]), *((u64 *)&deb[8])); \
- deb += 16; \
- } \
-diff --git a/drivers/infiniband/hw/ehca/ehca_uverbs.c b/drivers/infiniband/hw/ehca/ehca_uverbs.c
-index 5234d6c..1b07f2b 100644
---- a/drivers/infiniband/hw/ehca/ehca_uverbs.c
-+++ b/drivers/infiniband/hw/ehca/ehca_uverbs.c
-@@ -40,8 +40,6 @@
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
--#include <asm/current.h>
--
- #include "ehca_classes.h"
- #include "ehca_iverbs.h"
- #include "ehca_mrmw.h"
-@@ -253,11 +251,9 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
- u32 idr_handle = fileoffset & 0x1FFFFFF;
- u32 q_type = (fileoffset >> 27) & 0x1; /* CQ, QP,... */
- u32 rsrc_type = (fileoffset >> 25) & 0x3; /* sq,rq,cmnd_window */
-- u32 cur_pid = current->tgid;
- u32 ret;
- struct ehca_cq *cq;
- struct ehca_qp *qp;
-- struct ehca_pd *pd;
- struct ib_uobject *uobject;
-
- switch (q_type) {
-@@ -270,13 +266,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
- if (!cq)
- return -EINVAL;
-
-- if (cq->ownpid != cur_pid) {
-- ehca_err(cq->ib_cq.device,
-- "Invalid caller pid=%x ownpid=%x",
-- cur_pid, cq->ownpid);
-- return -ENOMEM;
-- }
--
- if (!cq->ib_cq.uobject || cq->ib_cq.uobject->context != context)
- return -EINVAL;
-
-@@ -298,14 +287,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
- if (!qp)
- return -EINVAL;
-
-- pd = container_of(qp->ib_qp.pd, struct ehca_pd, ib_pd);
-- if (pd->ownpid != cur_pid) {
-- ehca_err(qp->ib_qp.device,
-- "Invalid caller pid=%x ownpid=%x",
-- cur_pid, pd->ownpid);
-- return -ENOMEM;
-- }
--
- uobject = IS_SRQ(qp) ? qp->ib_srq.uobject : qp->ib_qp.uobject;
- if (!uobject || uobject->context != context)
- return -EINVAL;
-diff --git a/drivers/infiniband/hw/ipath/Kconfig b/drivers/infiniband/hw/ipath/Kconfig
-index 044da58..3c7968f 100644
---- a/drivers/infiniband/hw/ipath/Kconfig
-+++ b/drivers/infiniband/hw/ipath/Kconfig
-@@ -1,6 +1,6 @@
- config INFINIBAND_IPATH
- tristate "QLogic InfiniPath Driver"
-- depends on (PCI_MSI || HT_IRQ) && 64BIT && NET
-+ depends on 64BIT && NET
- ---help---
- This is a driver for QLogic InfiniPath host channel adapters,
- including InfiniBand verbs support. This driver allows these
-diff --git a/drivers/infiniband/hw/ipath/Makefile b/drivers/infiniband/hw/ipath/Makefile
-index fe67388..bf94500 100644
---- a/drivers/infiniband/hw/ipath/Makefile
-+++ b/drivers/infiniband/hw/ipath/Makefile
-@@ -20,14 +20,19 @@ ib_ipath-y := \
- ipath_qp.o \
- ipath_rc.o \
- ipath_ruc.o \
-+ ipath_sdma.o \
- ipath_srq.o \
- ipath_stats.o \
- ipath_sysfs.o \
- ipath_uc.o \
- ipath_ud.o \
- ipath_user_pages.o \
-+ ipath_user_sdma.o \
- ipath_verbs_mcast.o \
-- ipath_verbs.o
-+ ipath_verbs.o \
-+ ipath_iba7220.o \
-+ ipath_sd7220.o \
-+ ipath_sd7220_img.o
-
- ib_ipath-$(CONFIG_HT_IRQ) += ipath_iba6110.o
- ib_ipath-$(CONFIG_PCI_MSI) += ipath_iba6120.o
-diff --git a/drivers/infiniband/hw/ipath/ipath_7220.h b/drivers/infiniband/hw/ipath/ipath_7220.h
++ /* Wait for pll lock or timeout */
++ i = 0;
++ do {
++ mt2266_readreg(priv,REG_LOCK,b);
++ if (b[0] & 0x40)
++ break;
++ msleep(10);
++ i++;
++ } while (i<10);
++ dprintk("Lock when i=%i",(int)i);
++
++ if (band == MT2266_UHF && priv->band == MT2266_VHF)
++ mt2266_writereg(priv, 0x05, 0x62);
++
++ priv->band = band;
++
++ return ret;
++}
++
++static void mt2266_calibrate(struct mt2266_priv *priv)
++{
++ mt2266_writereg(priv, 0x11, 0x03);
++ mt2266_writereg(priv, 0x11, 0x01);
++ mt2266_writeregs(priv, mt2266_init1, sizeof(mt2266_init1));
++ mt2266_writeregs(priv, mt2266_init2, sizeof(mt2266_init2));
++ mt2266_writereg(priv, 0x33, 0x5e);
++ mt2266_writereg(priv, 0x10, 0x10);
++ mt2266_writereg(priv, 0x10, 0x00);
++ mt2266_writeregs(priv, mt2266_init_8mhz, sizeof(mt2266_init_8mhz));
++ msleep(25);
++ mt2266_writereg(priv, 0x17, 0x6d);
++ mt2266_writereg(priv, 0x1c, 0x00);
++ msleep(75);
++ mt2266_writereg(priv, 0x17, 0x6d);
++ mt2266_writereg(priv, 0x1c, 0xff);
++}
++
++static int mt2266_get_frequency(struct dvb_frontend *fe, u32 *frequency)
++{
++ struct mt2266_priv *priv = fe->tuner_priv;
++ *frequency = priv->frequency;
++ return 0;
++}
++
++static int mt2266_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
++{
++ struct mt2266_priv *priv = fe->tuner_priv;
++ *bandwidth = priv->bandwidth;
++ return 0;
++}
++
++static int mt2266_init(struct dvb_frontend *fe)
++{
++ int ret;
++ struct mt2266_priv *priv = fe->tuner_priv;
++ ret = mt2266_writereg(priv, 0x17, 0x6d);
++ if (ret < 0)
++ return ret;
++ ret = mt2266_writereg(priv, 0x1c, 0xff);
++ if (ret < 0)
++ return ret;
++ return 0;
++}
++
++static int mt2266_sleep(struct dvb_frontend *fe)
++{
++ struct mt2266_priv *priv = fe->tuner_priv;
++ mt2266_writereg(priv, 0x17, 0x6d);
++ mt2266_writereg(priv, 0x1c, 0x00);
++ return 0;
++}
++
++static int mt2266_release(struct dvb_frontend *fe)
++{
++ kfree(fe->tuner_priv);
++ fe->tuner_priv = NULL;
++ return 0;
++}
++
++static const struct dvb_tuner_ops mt2266_tuner_ops = {
++ .info = {
++ .name = "Microtune MT2266",
++ .frequency_min = 174000000,
++ .frequency_max = 862000000,
++ .frequency_step = 50000,
++ },
++ .release = mt2266_release,
++ .init = mt2266_init,
++ .sleep = mt2266_sleep,
++ .set_params = mt2266_set_params,
++ .get_frequency = mt2266_get_frequency,
++ .get_bandwidth = mt2266_get_bandwidth
++};
++
++struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg)
++{
++ struct mt2266_priv *priv = NULL;
++ u8 id = 0;
++
++ priv = kzalloc(sizeof(struct mt2266_priv), GFP_KERNEL);
++ if (priv == NULL)
++ return NULL;
++
++ priv->cfg = cfg;
++ priv->i2c = i2c;
++ priv->band = MT2266_UHF;
++
++ if (mt2266_readreg(priv, 0, &id)) {
++ kfree(priv);
++ return NULL;
++ }
++ if (id != PART_REV) {
++ kfree(priv);
++ return NULL;
++ }
++ printk(KERN_INFO "MT2266: successfully identified\n");
++ memcpy(&fe->ops.tuner_ops, &mt2266_tuner_ops, sizeof(struct dvb_tuner_ops));
++
++ fe->tuner_priv = priv;
++ mt2266_calibrate(priv);
++ return fe;
++}
++EXPORT_SYMBOL(mt2266_attach);
++
++MODULE_AUTHOR("Olivier DANET");
++MODULE_DESCRIPTION("Microtune MT2266 silicon tuner driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/common/tuners/mt2266.h b/drivers/media/common/tuners/mt2266.h
new file mode 100644
-index 0000000..74fa5cc
+index 0000000..4d08388
--- /dev/null
-+++ b/drivers/infiniband/hw/ipath/ipath_7220.h
-@@ -0,0 +1,57 @@
-+#ifndef _IPATH_7220_H
-+#define _IPATH_7220_H
++++ b/drivers/media/common/tuners/mt2266.h
+@@ -0,0 +1,37 @@
+/*
-+ * 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:
++ * Driver for Microtune MT2266 "Direct conversion low power broadband tuner"
+ *
-+ * - Redistributions of source code must retain the above
-+ * copyright notice, this list of conditions and the following
-+ * disclaimer.
++ * Copyright (c) 2007 Olivier DANET <odanet at caramail.com>
+ *
-+ * - 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.
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the 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 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 program is distributed in the hope that it will be useful,
++ * but WITHOUT 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 MT2266_H
++#define MT2266_H
++
++struct dvb_frontend;
++struct i2c_adapter;
++
++struct mt2266_config {
++ u8 i2c_address;
++};
++
++#if defined(CONFIG_MEDIA_TUNER_MT2266) || (defined(CONFIG_MEDIA_TUNER_MT2266_MODULE) && defined(MODULE))
++extern struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg);
++#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", __func__);
++ return NULL;
++}
++#endif // CONFIG_MEDIA_TUNER_MT2266
++
++#endif
+diff --git a/drivers/media/common/tuners/qt1010.c b/drivers/media/common/tuners/qt1010.c
+new file mode 100644
+index 0000000..825aa14
+--- /dev/null
++++ b/drivers/media/common/tuners/qt1010.c
+@@ -0,0 +1,485 @@
+/*
-+ * 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
++ * Driver for Quantek QT1010 silicon tuner
++ *
++ * Copyright (C) 2006 Antti Palosaari <crope at iki.fi>
++ * Aapo Tahkola <aet at rasterburn.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
-+#define IB_7220_SERDES 2
++#include "qt1010.h"
++#include "qt1010_priv.h"
+
-+int ipath_sd7220_ib_load(struct ipath_devdata *dd);
-+int ipath_sd7220_ib_vfy(struct ipath_devdata *dd);
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
-+#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;
++#define dprintk(args...) \
++ do { \
++ if (debug) printk(KERN_DEBUG "QT1010: " args); \
++ } while (0)
+
-+ /*
-+ * 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)
++/* read single register */
++static int qt1010_readreg(struct qt1010_priv *priv, u8 reg, u8 *val)
+{
-+ return (__le32_to_cpu(rbuf[1]) >> INFINIPATH_RHF_SEQ_SHIFT)
-+ & INFINIPATH_RHF_SEQ_MASK;
++ struct i2c_msg msg[2] = {
++ { .addr = priv->cfg->i2c_address,
++ .flags = 0, .buf = ®, .len = 1 },
++ { .addr = priv->cfg->i2c_address,
++ .flags = I2C_M_RD, .buf = val, .len = 1 },
++ };
++
++ if (i2c_transfer(priv->i2c, msg, 2) != 2) {
++ printk(KERN_WARNING "qt1010 I2C read failed\n");
++ return -EREMOTEIO;
++ }
++ return 0;
+}
+
-+static inline __u32 ipath_hdrget_offset(const __le32 *rbuf)
++/* write single register */
++static int qt1010_writereg(struct qt1010_priv *priv, u8 reg, u8 val)
+{
-+ return (__le32_to_cpu(rbuf[1]) >> INFINIPATH_RHF_HDRQ_OFFSET_SHIFT)
-+ & INFINIPATH_RHF_HDRQ_OFFSET_MASK;
++ u8 buf[2] = { reg, val };
++ struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
++ .flags = 0, .buf = buf, .len = 2 };
++
++ if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
++ printk(KERN_WARNING "qt1010 I2C write failed\n");
++ return -EREMOTEIO;
++ }
++ return 0;
+}
+
-+static inline __u32 ipath_hdrget_use_egr_buf(const __le32 *rbuf)
++/* dump all registers */
++static void qt1010_dump_regs(struct qt1010_priv *priv)
+{
-+ return __le32_to_cpu(rbuf[0]) & INFINIPATH_RHF_L_USE_EGR;
-+}
++ char buf[52], buf2[4];
++ u8 reg, val;
+
- 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;
++ for (reg = 0; ; reg++) {
++ if (reg % 16 == 0) {
++ if (reg)
++ printk("%s\n", buf);
++ sprintf(buf, "%02x: ", reg);
+ }
-+ } 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 */
++ if (qt1010_readreg(priv, reg, &val) == 0)
++ sprintf(buf2, "%02x ", val);
++ else
++ strcpy(buf2, "-- ");
++ strcat(buf, buf2);
++ if (reg == 0x2f)
++ break;
++ }
++ printk("%s\n", buf);
++}
+
-+ 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 int qt1010_set_params(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *params)
++{
++ struct qt1010_priv *priv;
++ int err;
++ u32 freq, div, mod1, mod2;
++ u8 i, tmpval, reg05;
++ qt1010_i2c_oper_t rd[48] = {
++ { QT1010_WR, 0x01, 0x80 },
++ { QT1010_WR, 0x02, 0x3f },
++ { QT1010_WR, 0x05, 0xff }, /* 02 c write */
++ { QT1010_WR, 0x06, 0x44 },
++ { QT1010_WR, 0x07, 0xff }, /* 04 c write */
++ { QT1010_WR, 0x08, 0x08 },
++ { QT1010_WR, 0x09, 0xff }, /* 06 c write */
++ { QT1010_WR, 0x0a, 0xff }, /* 07 c write */
++ { QT1010_WR, 0x0b, 0xff }, /* 08 c write */
++ { QT1010_WR, 0x0c, 0xe1 },
++ { QT1010_WR, 0x1a, 0xff }, /* 10 c write */
++ { QT1010_WR, 0x1b, 0x00 },
++ { QT1010_WR, 0x1c, 0x89 },
++ { QT1010_WR, 0x11, 0xff }, /* 13 c write */
++ { QT1010_WR, 0x12, 0xff }, /* 14 c write */
++ { QT1010_WR, 0x22, 0xff }, /* 15 c write */
++ { QT1010_WR, 0x1e, 0x00 },
++ { QT1010_WR, 0x1e, 0xd0 },
++ { QT1010_RD, 0x22, 0xff }, /* 16 c read */
++ { QT1010_WR, 0x1e, 0x00 },
++ { QT1010_RD, 0x05, 0xff }, /* 20 c read */
++ { QT1010_RD, 0x22, 0xff }, /* 21 c read */
++ { QT1010_WR, 0x23, 0xd0 },
++ { QT1010_WR, 0x1e, 0x00 },
++ { QT1010_WR, 0x1e, 0xe0 },
++ { QT1010_RD, 0x23, 0xff }, /* 25 c read */
++ { QT1010_RD, 0x23, 0xff }, /* 26 c read */
++ { QT1010_WR, 0x1e, 0x00 },
++ { QT1010_WR, 0x24, 0xd0 },
++ { QT1010_WR, 0x1e, 0x00 },
++ { QT1010_WR, 0x1e, 0xf0 },
++ { QT1010_RD, 0x24, 0xff }, /* 31 c read */
++ { QT1010_WR, 0x1e, 0x00 },
++ { QT1010_WR, 0x14, 0x7f },
++ { QT1010_WR, 0x15, 0x7f },
++ { QT1010_WR, 0x05, 0xff }, /* 35 c write */
++ { QT1010_WR, 0x06, 0x00 },
++ { QT1010_WR, 0x15, 0x1f },
++ { QT1010_WR, 0x16, 0xff },
++ { QT1010_WR, 0x18, 0xff },
++ { QT1010_WR, 0x1f, 0xff }, /* 40 c write */
++ { QT1010_WR, 0x20, 0xff }, /* 41 c write */
++ { QT1010_WR, 0x21, 0x53 },
++ { QT1010_WR, 0x25, 0xff }, /* 43 c write */
++ { QT1010_WR, 0x26, 0x15 },
++ { QT1010_WR, 0x00, 0xff }, /* 45 c write */
++ { QT1010_WR, 0x02, 0x00 },
++ { QT1010_WR, 0x01, 0x00 }
++ };
+
-+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");
++#define FREQ1 32000000 /* 32 MHz */
++#define FREQ2 4000000 /* 4 MHz Quartz oscillator in the stick? */
+
-+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");
++ priv = fe->tuner_priv;
++ freq = params->frequency;
++ div = (freq + QT1010_OFFSET) / QT1010_STEP;
++ freq = (div * QT1010_STEP) - QT1010_OFFSET;
++ mod1 = (freq + QT1010_OFFSET) % FREQ1;
++ mod2 = (freq + QT1010_OFFSET) % FREQ2;
++ priv->bandwidth =
++ (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
++ priv->frequency = freq;
+
- MODULE_LICENSE("GPL");
--MODULE_AUTHOR("QLogic <support at pathscale.com>");
-+MODULE_AUTHOR("QLogic <support at qlogic.com>");
- MODULE_DESCRIPTION("QLogic InfiniPath driver");
-
-+/*
-+ * Table to translate the LINKTRAININGSTATE portion of
-+ * IBCStatus to a human-readable form.
-+ */
- const char *ipath_ibcstatus_str[] = {
- "Disabled",
- "LinkUp",
-@@ -91,9 +107,20 @@ const char *ipath_ibcstatus_str[] = {
- "CfgWaitRmt",
- "CfgIdle",
- "RecovRetrain",
-- "LState0xD", /* unused */
-+ "CfgTxRevLane", /* unused before IBA7220 */
- "RecovWaitRmt",
- "RecovIdle",
-+ /* below were added for IBA7220 */
-+ "CfgEnhanced",
-+ "CfgTest",
-+ "CfgWaitRmtTest",
-+ "CfgWaitCfgEnhanced",
-+ "SendTS_T",
-+ "SendTstIdles",
-+ "RcvTS_T",
-+ "SendTst_TS1s",
-+ "LTState18", "LTState19", "LTState1A", "LTState1B",
-+ "LTState1C", "LTState1D", "LTState1E", "LTState1F"
- };
-
- static void __devexit ipath_remove_one(struct pci_dev *);
-@@ -102,8 +129,10 @@ static int __devinit ipath_init_one(struct pci_dev *,
-
- /* Only needed for registration, nothing else needs this info */
- #define PCI_VENDOR_ID_PATHSCALE 0x1fc1
-+#define PCI_VENDOR_ID_QLOGIC 0x1077
- #define PCI_DEVICE_ID_INFINIPATH_HT 0xd
- #define PCI_DEVICE_ID_INFINIPATH_PE800 0x10
-+#define PCI_DEVICE_ID_INFINIPATH_7220 0x7220
-
- /* Number of seconds before our card status check... */
- #define STATUS_TIMEOUT 60
-@@ -111,6 +140,7 @@ static int __devinit ipath_init_one(struct pci_dev *,
- static const struct pci_device_id ipath_pci_tbl[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_HT) },
- { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_PE800) },
-+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_INFINIPATH_7220) },
- { 0, }
- };
-
-@@ -126,19 +156,6 @@ static struct pci_driver ipath_driver = {
- },
- };
-
--static void ipath_check_status(struct work_struct *work)
--{
-- struct ipath_devdata *dd = container_of(work, struct ipath_devdata,
-- status_work.work);
--
-- /*
-- * If we don't have any interrupts, let the user know and
-- * don't bother checking again.
-- */
-- if (dd->ipath_int_counter == 0)
-- dev_err(&dd->pcidev->dev, "No interrupts detected.\n");
--}
--
- static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev,
- u32 *bar0, u32 *bar1)
- {
-@@ -206,8 +223,6 @@ static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev)
- dd->pcidev = pdev;
- pci_set_drvdata(pdev, dd);
-
-- INIT_DELAYED_WORK(&dd->status_work, ipath_check_status);
--
- list_add(&dd->ipath_list, &ipath_dev_list);
-
- bail_unlock:
-@@ -234,12 +249,12 @@ struct ipath_devdata *ipath_lookup(int unit)
- return dd;
- }
-
--int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp)
-+int ipath_count_units(int *npresentp, int *nupp, int *maxportsp)
- {
- int nunits, npresent, nup;
- struct ipath_devdata *dd;
- unsigned long flags;
-- u32 maxports;
-+ int maxports;
-
- nunits = npresent = nup = maxports = 0;
-
-@@ -304,7 +319,7 @@ static void ipath_verify_pioperf(struct ipath_devdata *dd)
- u32 *addr;
- u64 msecs, emsecs;
-
-- piobuf = ipath_getpiobuf(dd, &pbnum);
-+ piobuf = ipath_getpiobuf(dd, 0, &pbnum);
- if (!piobuf) {
- dev_info(&dd->pcidev->dev,
- "No PIObufs for checking perf, skipping\n");
-@@ -336,7 +351,14 @@ static void ipath_verify_pioperf(struct ipath_devdata *dd)
-
- ipath_disable_armlaunch(dd);
-
-- writeq(0, piobuf); /* length 0, no dwords actually sent */
-+ /*
-+ * length 0, no dwords actually sent, and mark as VL15
-+ * on chips where that may matter (due to IB flowcontrol)
-+ */
-+ if ((dd->ipath_flags & IPATH_HAS_PBC_CNT))
-+ writeq(1UL << 63, piobuf);
-+ else
-+ writeq(0, piobuf);
- ipath_flush_wc();
-
- /*
-@@ -377,6 +399,7 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
- struct ipath_devdata *dd;
- unsigned long long addr;
- u32 bar0 = 0, bar1 = 0;
-+ u8 rev;
-
- dd = ipath_alloc_devdata(pdev);
- if (IS_ERR(dd)) {
-@@ -408,7 +431,7 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
- }
- addr = pci_resource_start(pdev, 0);
- len = pci_resource_len(pdev, 0);
-- ipath_cdbg(VERBOSE, "regbase (0) %llx len %d pdev->irq %d, vend %x/%x "
-+ ipath_cdbg(VERBOSE, "regbase (0) %llx len %d irq %d, vend %x/%x "
- "driver_data %lx\n", addr, len, pdev->irq, ent->vendor,
- ent->device, ent->driver_data);
-
-@@ -512,6 +535,13 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
- "CONFIG_PCI_MSI is not enabled\n", ent->device);
- return -ENODEV;
- #endif
-+ case PCI_DEVICE_ID_INFINIPATH_7220:
-+#ifndef CONFIG_PCI_MSI
-+ ipath_dbg("CONFIG_PCI_MSI is not enabled, "
-+ "using INTx for unit %u\n", dd->ipath_unit);
-+#endif
-+ ipath_init_iba7220_funcs(dd);
-+ break;
- default:
- ipath_dev_err(dd, "Found unknown QLogic deviceid 0x%x, "
- "failing\n", ent->device);
-@@ -533,7 +563,13 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
- goto bail_regions;
- }
-
-- dd->ipath_pcirev = pdev->revision;
-+ ret = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-+ if (ret) {
-+ ipath_dev_err(dd, "Failed to read PCI revision ID unit "
-+ "%u: err %d\n", dd->ipath_unit, -ret);
-+ goto bail_regions; /* shouldn't ever happen */
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
++
++ /* reg 05 base value */
++ if (freq < 290000000) reg05 = 0x14; /* 290 MHz */
++ else if (freq < 610000000) reg05 = 0x34; /* 610 MHz */
++ else if (freq < 802000000) reg05 = 0x54; /* 802 MHz */
++ else reg05 = 0x74;
++
++ /* 0x5 */
++ rd[2].val = reg05;
++
++ /* 07 - set frequency: 32 MHz scale */
++ rd[4].val = (freq + QT1010_OFFSET) / FREQ1;
++
++ /* 09 - changes every 8/24 MHz */
++ if (mod1 < 8000000) rd[6].val = 0x1d;
++ else rd[6].val = 0x1c;
++
++ /* 0a - set frequency: 4 MHz scale (max 28 MHz) */
++ if (mod1 < 1*FREQ2) rd[7].val = 0x09; /* +0 MHz */
++ else if (mod1 < 2*FREQ2) rd[7].val = 0x08; /* +4 MHz */
++ else if (mod1 < 3*FREQ2) rd[7].val = 0x0f; /* +8 MHz */
++ else if (mod1 < 4*FREQ2) rd[7].val = 0x0e; /* +12 MHz */
++ else if (mod1 < 5*FREQ2) rd[7].val = 0x0d; /* +16 MHz */
++ else if (mod1 < 6*FREQ2) rd[7].val = 0x0c; /* +20 MHz */
++ else if (mod1 < 7*FREQ2) rd[7].val = 0x0b; /* +24 MHz */
++ else rd[7].val = 0x0a; /* +28 MHz */
++
++ /* 0b - changes every 2/2 MHz */
++ if (mod2 < 2000000) rd[8].val = 0x45;
++ else rd[8].val = 0x44;
++
++ /* 1a - set frequency: 125 kHz scale (max 3875 kHz)*/
++ tmpval = 0x78; /* byte, overflows intentionally */
++ rd[10].val = tmpval-((mod2/QT1010_STEP)*0x08);
++
++ /* 11 */
++ rd[13].val = 0xfd; /* TODO: correct value calculation */
++
++ /* 12 */
++ rd[14].val = 0x91; /* TODO: correct value calculation */
++
++ /* 22 */
++ if (freq < 450000000) rd[15].val = 0xd0; /* 450 MHz */
++ else if (freq < 482000000) rd[15].val = 0xd1; /* 482 MHz */
++ else if (freq < 514000000) rd[15].val = 0xd4; /* 514 MHz */
++ else if (freq < 546000000) rd[15].val = 0xd7; /* 546 MHz */
++ else if (freq < 610000000) rd[15].val = 0xda; /* 610 MHz */
++ else rd[15].val = 0xd0;
++
++ /* 05 */
++ rd[35].val = (reg05 & 0xf0);
++
++ /* 1f */
++ if (mod1 < 8000000) tmpval = 0x00;
++ else if (mod1 < 12000000) tmpval = 0x01;
++ else if (mod1 < 16000000) tmpval = 0x02;
++ else if (mod1 < 24000000) tmpval = 0x03;
++ else if (mod1 < 28000000) tmpval = 0x04;
++ else tmpval = 0x05;
++ rd[40].val = (priv->reg1f_init_val + 0x0e + tmpval);
++
++ /* 20 */
++ if (mod1 < 8000000) tmpval = 0x00;
++ else if (mod1 < 12000000) tmpval = 0x01;
++ else if (mod1 < 20000000) tmpval = 0x02;
++ else if (mod1 < 24000000) tmpval = 0x03;
++ else if (mod1 < 28000000) tmpval = 0x04;
++ else tmpval = 0x05;
++ rd[41].val = (priv->reg20_init_val + 0x0d + tmpval);
++
++ /* 25 */
++ rd[43].val = priv->reg25_init_val;
++
++ /* 00 */
++ rd[45].val = 0x92; /* TODO: correct value calculation */
++
++ dprintk("freq:%u 05:%02x 07:%02x 09:%02x 0a:%02x 0b:%02x " \
++ "1a:%02x 11:%02x 12:%02x 22:%02x 05:%02x 1f:%02x " \
++ "20:%02x 25:%02x 00:%02x", \
++ freq, rd[2].val, rd[4].val, rd[6].val, rd[7].val, rd[8].val, \
++ rd[10].val, rd[13].val, rd[14].val, rd[15].val, rd[35].val, \
++ rd[40].val, rd[41].val, rd[43].val, rd[45].val);
++
++ for (i = 0; i < ARRAY_SIZE(rd); i++) {
++ if (rd[i].oper == QT1010_WR) {
++ err = qt1010_writereg(priv, rd[i].reg, rd[i].val);
++ } else { /* read is required to proper locking */
++ err = qt1010_readreg(priv, rd[i].reg, &tmpval);
++ }
++ if (err) return err;
+ }
-+ 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);
++ if (debug)
++ qt1010_dump_regs(priv);
+
-+ 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)
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
++
++ return 0;
++}
++
++static int qt1010_init_meas1(struct qt1010_priv *priv,
++ u8 oper, u8 reg, u8 reg_init_val, u8 *retval)
+{
-+ 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" },
++ u8 i, val1, val2;
++ int err;
++
++ qt1010_i2c_oper_t i2c_data[] = {
++ { QT1010_WR, reg, reg_init_val },
++ { QT1010_WR, 0x1e, 0x00 },
++ { QT1010_WR, 0x1e, oper },
++ { QT1010_RD, reg, 0xff }
+ };
-+ 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);
++ for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
++ if (i2c_data[i].oper == QT1010_WR) {
++ err = qt1010_writereg(priv, i2c_data[i].reg,
++ i2c_data[i].val);
++ } else {
++ err = qt1010_readreg(priv, i2c_data[i].reg, &val2);
++ }
++ if (err) return err;
+ }
++
++ do {
++ val1 = val2;
++ err = qt1010_readreg(priv, reg, &val2);
++ if (err) return err;
++ dprintk("compare reg:%02x %02x %02x", reg, val1, val2);
++ } while (val1 != val2);
++ *retval = val1;
++
++ return qt1010_writereg(priv, 0x1e, 0x00);
+}
+
- /*
- * 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();
++static u8 qt1010_init_meas2(struct qt1010_priv *priv,
++ u8 reg_init_val, u8 *retval)
++{
++ u8 i, val;
++ int err;
++ qt1010_i2c_oper_t i2c_data[] = {
++ { QT1010_WR, 0x07, reg_init_val },
++ { QT1010_WR, 0x22, 0xd0 },
++ { QT1010_WR, 0x1e, 0x00 },
++ { QT1010_WR, 0x1e, 0xd0 },
++ { QT1010_RD, 0x22, 0xff },
++ { QT1010_WR, 0x1e, 0x00 },
++ { QT1010_WR, 0x22, 0xff }
++ };
++ for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
++ if (i2c_data[i].oper == QT1010_WR) {
++ err = qt1010_writereg(priv, i2c_data[i].reg,
++ i2c_data[i].val);
++ } else {
++ err = qt1010_readreg(priv, i2c_data[i].reg, &val);
++ }
++ if (err) return err;
+ }
-
-- 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);
++ *retval = val;
++ return 0;
++}
+
-+ 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;
++static int qt1010_init(struct dvb_frontend *fe)
++{
++ struct qt1010_priv *priv = fe->tuner_priv;
++ struct dvb_frontend_parameters params;
++ int err = 0;
++ u8 i, tmpval, *valptr = NULL;
+
-+ /* 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)
++ qt1010_i2c_oper_t i2c_data[] = {
++ { QT1010_WR, 0x01, 0x80 },
++ { QT1010_WR, 0x0d, 0x84 },
++ { QT1010_WR, 0x0e, 0xb7 },
++ { QT1010_WR, 0x2a, 0x23 },
++ { QT1010_WR, 0x2c, 0xdc },
++ { QT1010_M1, 0x25, 0x40 }, /* get reg 25 init value */
++ { QT1010_M1, 0x81, 0xff }, /* get reg 25 init value */
++ { QT1010_WR, 0x2b, 0x70 },
++ { QT1010_WR, 0x2a, 0x23 },
++ { QT1010_M1, 0x26, 0x08 },
++ { QT1010_M1, 0x82, 0xff },
++ { QT1010_WR, 0x05, 0x14 },
++ { QT1010_WR, 0x06, 0x44 },
++ { QT1010_WR, 0x07, 0x28 },
++ { QT1010_WR, 0x08, 0x0b },
++ { QT1010_WR, 0x11, 0xfd },
++ { QT1010_M1, 0x22, 0x0d },
++ { QT1010_M1, 0xd0, 0xff },
++ { QT1010_WR, 0x06, 0x40 },
++ { QT1010_WR, 0x16, 0xf0 },
++ { QT1010_WR, 0x02, 0x38 },
++ { QT1010_WR, 0x03, 0x18 },
++ { QT1010_WR, 0x20, 0xe0 },
++ { QT1010_M1, 0x1f, 0x20 }, /* get reg 1f init value */
++ { QT1010_M1, 0x84, 0xff }, /* get reg 1f init value */
++ { QT1010_RD, 0x20, 0x20 }, /* get reg 20 init value */
++ { QT1010_WR, 0x03, 0x19 },
++ { QT1010_WR, 0x02, 0x3f },
++ { QT1010_WR, 0x21, 0x53 },
++ { QT1010_RD, 0x21, 0xff },
++ { QT1010_WR, 0x11, 0xfd },
++ { QT1010_WR, 0x05, 0x34 },
++ { QT1010_WR, 0x06, 0x44 },
++ { QT1010_WR, 0x08, 0x08 }
++ };
++
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
++
++ for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
++ switch (i2c_data[i].oper) {
++ case QT1010_WR:
++ err = qt1010_writereg(priv, i2c_data[i].reg,
++ i2c_data[i].val);
++ break;
++ case QT1010_RD:
++ if (i2c_data[i].val == 0x20)
++ valptr = &priv->reg20_init_val;
++ else
++ valptr = &tmpval;
++ err = qt1010_readreg(priv, i2c_data[i].reg, valptr);
++ break;
++ case QT1010_M1:
++ if (i2c_data[i].val == 0x25)
++ valptr = &priv->reg25_init_val;
++ else if (i2c_data[i].val == 0x1f)
++ valptr = &priv->reg1f_init_val;
++ else
++ valptr = &tmpval;
++ err = qt1010_init_meas1(priv, i2c_data[i+1].reg,
++ i2c_data[i].reg,
++ i2c_data[i].val, valptr);
++ i++;
++ break;
++ }
++ if (err) return err;
++ }
++
++ for (i = 0x31; i < 0x3a; i++) /* 0x31 - 0x39 */
++ if ((err = qt1010_init_meas2(priv, i, &tmpval)))
++ return err;
++
++ params.frequency = 545000000; /* Sigmatek DVB-110 545000000 */
++ /* MSI Megasky 580 GL861 533000000 */
++ return qt1010_set_params(fe, ¶ms);
++}
++
++static int qt1010_release(struct dvb_frontend *fe)
+{
-+ unsigned long *shadow = dd->ipath_pioavailshadow;
-+ __le64 *dma = (__le64 *)dd->ipath_pioavailregs_dma;
++ kfree(fe->tuner_priv);
++ fe->tuner_priv = NULL;
++ return 0;
++}
+
-+ dd->ipath_upd_pio_shadow = 1;
++static int qt1010_get_frequency(struct dvb_frontend *fe, u32 *frequency)
++{
++ struct qt1010_priv *priv = fe->tuner_priv;
++ *frequency = priv->frequency;
++ return 0;
++}
+
-+ /*
-+ * 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]);
++static int qt1010_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
++{
++ struct qt1010_priv *priv = fe->tuner_priv;
++ *bandwidth = priv->bandwidth;
++ return 0;
++}
++
++static const struct dvb_tuner_ops qt1010_tuner_ops = {
++ .info = {
++ .name = "Quantek QT1010",
++ .frequency_min = QT1010_MIN_FREQ,
++ .frequency_max = QT1010_MAX_FREQ,
++ .frequency_step = QT1010_STEP,
++ },
++
++ .release = qt1010_release,
++ .init = qt1010_init,
++ /* TODO: implement sleep */
++
++ .set_params = qt1010_set_params,
++ .get_frequency = qt1010_get_frequency,
++ .get_bandwidth = qt1010_get_bandwidth
++};
++
++struct dvb_frontend * qt1010_attach(struct dvb_frontend *fe,
++ struct i2c_adapter *i2c,
++ struct qt1010_config *cfg)
++{
++ struct qt1010_priv *priv = NULL;
++ u8 id;
++
++ priv = kzalloc(sizeof(struct qt1010_priv), GFP_KERNEL);
++ if (priv == NULL)
++ return NULL;
++
++ priv->cfg = cfg;
++ priv->i2c = i2c;
++
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
++
++
++ /* Try to detect tuner chip. Probably this is not correct register. */
++ if (qt1010_readreg(priv, 0x29, &id) != 0 || (id != 0x39)) {
++ kfree(priv);
++ return NULL;
+ }
++
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
++
++ printk(KERN_INFO "Quantek QT1010 successfully identified.\n");
++ memcpy(&fe->ops.tuner_ops, &qt1010_tuner_ops,
++ sizeof(struct dvb_tuner_ops));
++
++ fe->tuner_priv = priv;
++ return fe;
+}
++EXPORT_SYMBOL(qt1010_attach);
+
++MODULE_DESCRIPTION("Quantek QT1010 silicon tuner driver");
++MODULE_AUTHOR("Antti Palosaari <crope at iki.fi>");
++MODULE_AUTHOR("Aapo Tahkola <aet at rasterburn.org>");
++MODULE_VERSION("0.1");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/common/tuners/qt1010.h b/drivers/media/common/tuners/qt1010.h
+new file mode 100644
+index 0000000..807fb7b
+--- /dev/null
++++ b/drivers/media/common/tuners/qt1010.h
+@@ -0,0 +1,53 @@
+/*
-+ * 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;
- }
++ * Driver for Quantek QT1010 silicon tuner
++ *
++ * Copyright (C) 2006 Antti Palosaari <crope at iki.fi>
++ * Aapo Tahkola <aet at rasterburn.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef QT1010_H
++#define QT1010_H
++
++#include "dvb_frontend.h"
++
++struct qt1010_config {
++ u8 i2c_address;
++};
+
-+ 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
++ * Attach a qt1010 tuner to the supplied frontend structure.
++ *
++ * @param fe frontend to attach to
++ * @param i2c i2c adapter to use
++ * @param cfg tuner hw based configuration
++ * @return fe pointer on success, NULL on failure
++ */
++#if defined(CONFIG_MEDIA_TUNER_QT1010) || (defined(CONFIG_MEDIA_TUNER_QT1010_MODULE) && defined(MODULE))
++extern struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
++ struct i2c_adapter *i2c,
++ struct qt1010_config *cfg);
++#else
++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", __func__);
++ return NULL;
++}
++#endif // CONFIG_MEDIA_TUNER_QT1010
++
++#endif
+diff --git a/drivers/media/common/tuners/qt1010_priv.h b/drivers/media/common/tuners/qt1010_priv.h
+new file mode 100644
+index 0000000..090cf47
+--- /dev/null
++++ b/drivers/media/common/tuners/qt1010_priv.h
+@@ -0,0 +1,105 @@
++/*
++ * Driver for Quantek QT1010 silicon tuner
++ *
++ * Copyright (C) 2006 Antti Palosaari <crope at iki.fi>
++ * Aapo Tahkola <aet at rasterburn.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
-+u32 __iomem *ipath_getpiobuf(struct ipath_devdata *dd, u32 plen, u32 *pbufnum)
++
++#ifndef QT1010_PRIV_H
++#define QT1010_PRIV_H
++
++/*
++reg def meaning
++=== === =======
++00 00 ?
++01 a0 ? operation start/stop; start=80, stop=00
++02 00 ?
++03 19 ?
++04 00 ?
++05 00 ? maybe band selection
++06 00 ?
++07 2b set frequency: 32 MHz scale, n*32 MHz
++08 0b ?
++09 10 ? changes every 8/24 MHz; values 1d/1c
++0a 08 set frequency: 4 MHz scale, n*4 MHz
++0b 41 ? changes every 2/2 MHz; values 45/45
++0c e1 ?
++0d 94 ?
++0e b6 ?
++0f 2c ?
++10 10 ?
++11 f1 ? maybe device specified adjustment
++12 11 ? maybe device specified adjustment
++13 3f ?
++14 1f ?
++15 3f ?
++16 ff ?
++17 ff ?
++18 f7 ?
++19 80 ?
++1a d0 set frequency: 125 kHz scale, n*125 kHz
++1b 00 ?
++1c 89 ?
++1d 00 ?
++1e 00 ? looks like operation register; write cmd here, read result from 1f-26
++1f 20 ? chip initialization
++20 e0 ? chip initialization
++21 20 ?
++22 d0 ?
++23 d0 ?
++24 d0 ?
++25 40 ? chip initialization
++26 08 ?
++27 29 ?
++28 55 ?
++29 39 ?
++2a 13 ?
++2b 01 ?
++2c ea ?
++2d 00 ?
++2e 00 ? not used?
++2f 00 ? not used?
++*/
++
++#define QT1010_STEP 125000 /* 125 kHz used by Windows drivers,
++ hw could be more precise but we don't
++ know how to use */
++#define QT1010_MIN_FREQ 48000000 /* 48 MHz */
++#define QT1010_MAX_FREQ 860000000 /* 860 MHz */
++#define QT1010_OFFSET 1246000000 /* 1246 MHz */
++
++#define QT1010_WR 0
++#define QT1010_RD 1
++#define QT1010_M1 3
++
++typedef struct {
++ u8 oper, reg, val;
++} qt1010_i2c_oper_t;
++
++struct qt1010_priv {
++ struct qt1010_config *cfg;
++ struct i2c_adapter *i2c;
++
++ u8 reg1f_init_val;
++ u8 reg20_init_val;
++ u8 reg25_init_val;
++
++ u32 frequency;
++ u32 bandwidth;
++};
++
++#endif
+diff --git a/drivers/media/common/tuners/tda18271-common.c b/drivers/media/common/tuners/tda18271-common.c
+new file mode 100644
+index 0000000..e27a762
+--- /dev/null
++++ b/drivers/media/common/tuners/tda18271-common.c
+@@ -0,0 +1,666 @@
++/*
++ tda18271-common.c - driver for the Philips / NXP TDA18271 silicon tuner
++
++ Copyright (C) 2007, 2008 Michael Krufky <mkrufky at linuxtv.org>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You 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 "tda18271-priv.h"
++
++static int tda18271_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
-+ u32 __iomem *buf;
-+ u32 pnum, nbufs;
-+ u32 first, lasti;
++ struct tda18271_priv *priv = fe->tuner_priv;
++ enum tda18271_i2c_gate gate;
++ int ret = 0;
+
-+ if (plen + 1 >= IPATH_SMALLBUF_DWORDS) {
-+ first = dd->ipath_piobcnt2k;
-+ lasti = dd->ipath_lastpioindexl;
-+ } else {
-+ first = 0;
-+ lasti = dd->ipath_lastpioindex;
++ switch (priv->gate) {
++ case TDA18271_GATE_DIGITAL:
++ case TDA18271_GATE_ANALOG:
++ gate = priv->gate;
++ break;
++ case TDA18271_GATE_AUTO:
++ default:
++ switch (priv->mode) {
++ case TDA18271_DIGITAL:
++ gate = TDA18271_GATE_DIGITAL;
++ break;
++ case TDA18271_ANALOG:
++ default:
++ gate = TDA18271_GATE_ANALOG;
++ break;
++ }
+ }
-+ 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;
+
++ switch (gate) {
++ case TDA18271_GATE_ANALOG:
++ if (fe->ops.analog_ops.i2c_gate_ctrl)
++ ret = fe->ops.analog_ops.i2c_gate_ctrl(fe, enable);
++ break;
++ case TDA18271_GATE_DIGITAL:
++ if (fe->ops.i2c_gate_ctrl)
++ ret = fe->ops.i2c_gate_ctrl(fe, enable);
++ break;
++ default:
++ ret = -EINVAL;
++ break;
+ }
- 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)
++
++ return ret;
++};
++
++/*---------------------------------------------------------------------*/
++
++static void tda18271_dump_regs(struct dvb_frontend *fe, int extended)
+{
-+ unsigned long flags;
-+ unsigned end;
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
+
-+ /* There are two bits per send buffer (busy and generation) */
-+ start *= 2;
-+ len *= 2;
-+ end = start + len;
++ tda_reg("=== TDA18271 REG DUMP ===\n");
++ tda_reg("ID_BYTE = 0x%02x\n", 0xff & regs[R_ID]);
++ tda_reg("THERMO_BYTE = 0x%02x\n", 0xff & regs[R_TM]);
++ tda_reg("POWER_LEVEL_BYTE = 0x%02x\n", 0xff & regs[R_PL]);
++ tda_reg("EASY_PROG_BYTE_1 = 0x%02x\n", 0xff & regs[R_EP1]);
++ tda_reg("EASY_PROG_BYTE_2 = 0x%02x\n", 0xff & regs[R_EP2]);
++ tda_reg("EASY_PROG_BYTE_3 = 0x%02x\n", 0xff & regs[R_EP3]);
++ tda_reg("EASY_PROG_BYTE_4 = 0x%02x\n", 0xff & regs[R_EP4]);
++ tda_reg("EASY_PROG_BYTE_5 = 0x%02x\n", 0xff & regs[R_EP5]);
++ tda_reg("CAL_POST_DIV_BYTE = 0x%02x\n", 0xff & regs[R_CPD]);
++ tda_reg("CAL_DIV_BYTE_1 = 0x%02x\n", 0xff & regs[R_CD1]);
++ tda_reg("CAL_DIV_BYTE_2 = 0x%02x\n", 0xff & regs[R_CD2]);
++ tda_reg("CAL_DIV_BYTE_3 = 0x%02x\n", 0xff & regs[R_CD3]);
++ tda_reg("MAIN_POST_DIV_BYTE = 0x%02x\n", 0xff & regs[R_MPD]);
++ tda_reg("MAIN_DIV_BYTE_1 = 0x%02x\n", 0xff & regs[R_MD1]);
++ tda_reg("MAIN_DIV_BYTE_2 = 0x%02x\n", 0xff & regs[R_MD2]);
++ tda_reg("MAIN_DIV_BYTE_3 = 0x%02x\n", 0xff & regs[R_MD3]);
+
-+ /* 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);
++ /* only dump extended regs if DBG_ADV is set */
++ if (!(tda18271_debug & DBG_ADV))
++ return;
++
++ /* W indicates write-only registers.
++ * Register dump for write-only registers shows last value written. */
++
++ tda_reg("EXTENDED_BYTE_1 = 0x%02x\n", 0xff & regs[R_EB1]);
++ tda_reg("EXTENDED_BYTE_2 = 0x%02x\n", 0xff & regs[R_EB2]);
++ tda_reg("EXTENDED_BYTE_3 = 0x%02x\n", 0xff & regs[R_EB3]);
++ tda_reg("EXTENDED_BYTE_4 = 0x%02x\n", 0xff & regs[R_EB4]);
++ tda_reg("EXTENDED_BYTE_5 = 0x%02x\n", 0xff & regs[R_EB5]);
++ tda_reg("EXTENDED_BYTE_6 = 0x%02x\n", 0xff & regs[R_EB6]);
++ tda_reg("EXTENDED_BYTE_7 = 0x%02x\n", 0xff & regs[R_EB7]);
++ tda_reg("EXTENDED_BYTE_8 = 0x%02x\n", 0xff & regs[R_EB8]);
++ tda_reg("EXTENDED_BYTE_9 W = 0x%02x\n", 0xff & regs[R_EB9]);
++ tda_reg("EXTENDED_BYTE_10 = 0x%02x\n", 0xff & regs[R_EB10]);
++ tda_reg("EXTENDED_BYTE_11 = 0x%02x\n", 0xff & regs[R_EB11]);
++ tda_reg("EXTENDED_BYTE_12 = 0x%02x\n", 0xff & regs[R_EB12]);
++ tda_reg("EXTENDED_BYTE_13 = 0x%02x\n", 0xff & regs[R_EB13]);
++ tda_reg("EXTENDED_BYTE_14 = 0x%02x\n", 0xff & regs[R_EB14]);
++ tda_reg("EXTENDED_BYTE_15 = 0x%02x\n", 0xff & regs[R_EB15]);
++ tda_reg("EXTENDED_BYTE_16 W = 0x%02x\n", 0xff & regs[R_EB16]);
++ tda_reg("EXTENDED_BYTE_17 W = 0x%02x\n", 0xff & regs[R_EB17]);
++ tda_reg("EXTENDED_BYTE_18 = 0x%02x\n", 0xff & regs[R_EB18]);
++ tda_reg("EXTENDED_BYTE_19 W = 0x%02x\n", 0xff & regs[R_EB19]);
++ tda_reg("EXTENDED_BYTE_20 W = 0x%02x\n", 0xff & regs[R_EB20]);
++ tda_reg("EXTENDED_BYTE_21 = 0x%02x\n", 0xff & regs[R_EB21]);
++ tda_reg("EXTENDED_BYTE_22 = 0x%02x\n", 0xff & regs[R_EB22]);
++ tda_reg("EXTENDED_BYTE_23 = 0x%02x\n", 0xff & regs[R_EB23]);
+}
+
-+/**
- * 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;
++int tda18271_read_regs(struct dvb_frontend *fe)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
++ unsigned char buf = 0x00;
++ int ret;
++ struct i2c_msg msg[] = {
++ { .addr = priv->i2c_props.addr, .flags = 0,
++ .buf = &buf, .len = 1 },
++ { .addr = priv->i2c_props.addr, .flags = I2C_M_RD,
++ .buf = regs, .len = 16 }
++ };
+
-+ 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;
++ tda18271_i2c_gate_ctrl(fe, 1);
+
-+ 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;
++ /* read all registers */
++ ret = i2c_transfer(priv->i2c_props.adap, msg, 2);
+
-+ 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;
-+ }
++ tda18271_i2c_gate_ctrl(fe, 0);
+
- ipath_dbg("Cancelling all in-progress send buffers\n");
-- dd->ipath_lastcancel = jiffies+HZ/2; /* skip armlaunch errs a bit */
++ if (ret != 2)
++ tda_err("ERROR: i2c_transfer returned: %d\n", ret);
+
-+ /* skip armlaunch errs for a while */
-+ dd->ipath_lastcancel = jiffies + HZ / 2;
++ if (tda18271_debug & DBG_REG)
++ tda18271_dump_regs(fe, 0);
+
- /*
-- * 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);
++ return (ret == 2 ? 0 : ret);
++}
+
-+ /* 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);
++int tda18271_read_extended(struct dvb_frontend *fe)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
++ unsigned char regdump[TDA18271_NUM_REGS];
++ unsigned char buf = 0x00;
++ int ret, i;
++ struct i2c_msg msg[] = {
++ { .addr = priv->i2c_props.addr, .flags = 0,
++ .buf = &buf, .len = 1 },
++ { .addr = priv->i2c_props.addr, .flags = I2C_M_RD,
++ .buf = regdump, .len = TDA18271_NUM_REGS }
++ };
+
-+ 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);
++ tda18271_i2c_gate_ctrl(fe, 1);
++
++ /* read all registers */
++ ret = i2c_transfer(priv->i2c_props.adap, msg, 2);
++
++ tda18271_i2c_gate_ctrl(fe, 0);
++
++ if (ret != 2)
++ tda_err("ERROR: i2c_transfer returned: %d\n", ret);
++
++ for (i = 0; i < TDA18271_NUM_REGS; i++) {
++ /* don't update write-only registers */
++ if ((i != R_EB9) &&
++ (i != R_EB16) &&
++ (i != R_EB17) &&
++ (i != R_EB19) &&
++ (i != R_EB20))
++ regs[i] = regdump[i];
+ }
-+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)
++
++ if (tda18271_debug & DBG_REG)
++ tda18271_dump_regs(fe, 1);
++
++ return (ret == 2 ? 0 : ret);
++}
++
++int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
+{
-+ unsigned long flags;
++ 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_props.addr, .flags = 0,
++ .buf = buf, .len = len + 1 };
++ int i, ret;
+
-+ 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);
++ BUG_ON((len == 0) || (idx + len > sizeof(buf)));
++
++ buf[0] = idx;
++ for (i = 1; i <= len; i++)
++ buf[i] = regs[idx - 1 + i];
++
++ tda18271_i2c_gate_ctrl(fe, 1);
++
++ /* write registers */
++ ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
++
++ tda18271_i2c_gate_ctrl(fe, 0);
++
++ if (ret != 1)
++ tda_err("ERROR: i2c_transfer returned: %d\n", ret);
++
++ return (ret == 1 ? 0 : ret);
+}
-
--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);
++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;
+
- /*
- * 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);
++ int r_cp = (pll == TDA18271_CAL_PLL) ? R_EB7 : R_EB4;
+
-+ /* 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;
++ regs[r_cp] &= ~0x20;
++ regs[r_cp] |= ((force & 1) << 5);
++ tda18271_write_regs(fe, r_cp, 1);
+
-+ /*
-+ * 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;
++ return 0;
++}
+
-+ 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);
++int tda18271_init_regs(struct dvb_frontend *fe)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
+
-+ dev_info(&dd->pcidev->dev, "We got a lid: 0x%x\n", lid);
++ tda_dbg("initializing registers for device @ %d-%04x\n",
++ i2c_adapter_id(priv->i2c_props.adap),
++ priv->i2c_props.addr);
+
- 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 {
++ /* initialize registers */
++ switch (priv->id) {
++ case TDA18271HDC1:
++ regs[R_ID] = 0x83;
++ break;
++ case TDA18271HDC2:
++ regs[R_ID] = 0x84;
++ break;
++ };
++
++ regs[R_TM] = 0x08;
++ regs[R_PL] = 0x80;
++ regs[R_EP1] = 0xc6;
++ regs[R_EP2] = 0xdf;
++ regs[R_EP3] = 0x16;
++ regs[R_EP4] = 0x60;
++ regs[R_EP5] = 0x80;
++ regs[R_CPD] = 0x80;
++ regs[R_CD1] = 0x00;
++ regs[R_CD2] = 0x00;
++ regs[R_CD3] = 0x00;
++ regs[R_MPD] = 0x00;
++ regs[R_MD1] = 0x00;
++ regs[R_MD2] = 0x00;
++ regs[R_MD3] = 0x00;
++
++ switch (priv->id) {
++ case TDA18271HDC1:
++ regs[R_EB1] = 0xff;
++ break;
++ case TDA18271HDC2:
++ regs[R_EB1] = 0xfc;
++ break;
++ };
++
++ regs[R_EB2] = 0x01;
++ regs[R_EB3] = 0x84;
++ regs[R_EB4] = 0x41;
++ regs[R_EB5] = 0x01;
++ regs[R_EB6] = 0x84;
++ regs[R_EB7] = 0x40;
++ regs[R_EB8] = 0x07;
++ regs[R_EB9] = 0x00;
++ regs[R_EB10] = 0x00;
++ regs[R_EB11] = 0x96;
++
++ switch (priv->id) {
++ case TDA18271HDC1:
++ regs[R_EB12] = 0x0f;
++ break;
++ case TDA18271HDC2:
++ regs[R_EB12] = 0x33;
++ break;
++ };
++
++ regs[R_EB13] = 0xc1;
++ regs[R_EB14] = 0x00;
++ regs[R_EB15] = 0x8f;
++ regs[R_EB16] = 0x00;
++ regs[R_EB17] = 0x00;
++
++ switch (priv->id) {
++ case TDA18271HDC1:
++ regs[R_EB18] = 0x00;
++ break;
++ case TDA18271HDC2:
++ regs[R_EB18] = 0x8c;
++ break;
++ };
++
++ regs[R_EB19] = 0x00;
++ regs[R_EB20] = 0x20;
++
++ switch (priv->id) {
++ case TDA18271HDC1:
++ regs[R_EB21] = 0x33;
++ break;
++ case TDA18271HDC2:
++ regs[R_EB21] = 0xb3;
++ break;
++ };
++
++ regs[R_EB22] = 0x48;
++ regs[R_EB23] = 0xb0;
++
++ if (priv->small_i2c) {
++ tda18271_write_regs(fe, 0x00, 0x10);
++ tda18271_write_regs(fe, 0x10, 0x10);
++ tda18271_write_regs(fe, 0x20, 0x07);
+ } 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 */
++ tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
+
- 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);
++ /* setup agc1 gain */
++ regs[R_EB17] = 0x00;
++ tda18271_write_regs(fe, R_EB17, 1);
++ regs[R_EB17] = 0x03;
++ tda18271_write_regs(fe, R_EB17, 1);
++ regs[R_EB17] = 0x43;
++ tda18271_write_regs(fe, R_EB17, 1);
++ regs[R_EB17] = 0x4c;
++ tda18271_write_regs(fe, R_EB17, 1);
++
++ /* setup agc2 gain */
++ if ((priv->id) == TDA18271HDC1) {
++ regs[R_EB20] = 0xa0;
++ tda18271_write_regs(fe, R_EB20, 1);
++ regs[R_EB20] = 0xa7;
++ tda18271_write_regs(fe, R_EB20, 1);
++ regs[R_EB20] = 0xe7;
++ tda18271_write_regs(fe, R_EB20, 1);
++ regs[R_EB20] = 0xec;
++ tda18271_write_regs(fe, R_EB20, 1);
++ }
++
++ /* image rejection calibration */
++
++ /* low-band */
++ regs[R_EP3] = 0x1f;
++ regs[R_EP4] = 0x66;
++ regs[R_EP5] = 0x81;
++ regs[R_CPD] = 0xcc;
++ regs[R_CD1] = 0x6c;
++ regs[R_CD2] = 0x00;
++ regs[R_CD3] = 0x00;
++ regs[R_MPD] = 0xcd;
++ regs[R_MD1] = 0x77;
++ regs[R_MD2] = 0x08;
++ regs[R_MD3] = 0x00;
+
- /*
- * 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 */
++ tda18271_write_regs(fe, R_EP3, 11);
+
-+ 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);
++ if ((priv->id) == TDA18271HDC2) {
++ /* main pll cp source on */
++ tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1);
++ msleep(1);
++
++ /* main pll cp source off */
++ tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 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;
- }
-
++ msleep(5); /* pll locking */
++
++ /* launch detector */
++ tda18271_write_regs(fe, R_EP1, 1);
++ msleep(5); /* wanted low measurement */
++
++ regs[R_EP5] = 0x85;
++ regs[R_CPD] = 0xcb;
++ regs[R_CD1] = 0x66;
++ regs[R_CD2] = 0x70;
++
++ tda18271_write_regs(fe, R_EP3, 7);
++ msleep(5); /* pll locking */
++
++ /* launch optimization algorithm */
++ tda18271_write_regs(fe, R_EP2, 1);
++ msleep(30); /* image low optimization completion */
++
++ /* mid-band */
++ regs[R_EP5] = 0x82;
++ regs[R_CPD] = 0xa8;
++ regs[R_CD2] = 0x00;
++ regs[R_MPD] = 0xa9;
++ regs[R_MD1] = 0x73;
++ regs[R_MD2] = 0x1a;
++
++ 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 */
++
++ regs[R_EP5] = 0x86;
++ regs[R_CPD] = 0xa8;
++ regs[R_CD1] = 0x66;
++ regs[R_CD2] = 0xa0;
++
++ tda18271_write_regs(fe, R_EP3, 7);
++ msleep(5); /* pll locking */
++
++ /* launch optimization algorithm */
++ tda18271_write_regs(fe, R_EP2, 1);
++ msleep(30); /* image mid optimization completion */
++
++ /* high-band */
++ regs[R_EP5] = 0x83;
++ regs[R_CPD] = 0x98;
++ regs[R_CD1] = 0x65;
++ regs[R_CD2] = 0x00;
++ regs[R_MPD] = 0x99;
++ regs[R_MD1] = 0x71;
++ regs[R_MD2] = 0xcd;
++
++ tda18271_write_regs(fe, R_EP3, 11);
++ msleep(5); /* pll locking */
++
++ /* launch detector */
++ tda18271_write_regs(fe, R_EP1, 1);
++ msleep(5); /* wanted high measurement */
++
++ regs[R_EP5] = 0x87;
++ regs[R_CD1] = 0x65;
++ regs[R_CD2] = 0x50;
++
++ tda18271_write_regs(fe, R_EP3, 7);
++ msleep(5); /* pll locking */
++
++ /* launch optimization algorithm */
++ tda18271_write_regs(fe, R_EP2, 1);
++ msleep(30); /* image high optimization completion */
++
++ /* return to normal mode */
++ regs[R_EP4] = 0x64;
++ tda18271_write_regs(fe, R_EP4, 1);
++
++ /* synchronize */
++ tda18271_write_regs(fe, R_EP1, 1);
++
++ return 0;
++}
++
++/*---------------------------------------------------------------------*/
++
+/*
-+ * 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.
++ * Standby modes, EP3 [7:5]
++ *
++ * | SM || SM_LT || SM_XT || mode description
++ * |=====\\=======\\=======\\===================================
++ * | 0 || 0 || 0 || normal mode
++ * |-----||-------||-------||-----------------------------------
++ * | || || || standby mode w/ slave tuner output
++ * | 1 || 0 || 0 || & loop thru & xtal oscillator on
++ * |-----||-------||-------||-----------------------------------
++ * | 1 || 1 || 0 || standby mode w/ xtal oscillator on
++ * |-----||-------||-------||-----------------------------------
++ * | 1 || 1 || 1 || power off
++ *
+ */
-+static int ipath_signal_procs(struct ipath_devdata *dd, int sig)
++
++int tda18271_set_standby_mode(struct dvb_frontend *fe,
++ int sm, int sm_lt, int sm_xt)
+{
-+ int i, sub, any = 0;
-+ pid_t pid;
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
+
-+ 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++;
-+ }
++ tda_dbg("sm = %d, sm_lt = %d, sm_xt = %d\n", sm, sm_lt, sm_xt);
++
++ regs[R_EP3] &= ~0xe0; /* clear sm, sm_lt, sm_xt */
++ regs[R_EP3] |= sm ? (1 << 7) : 0 |
++ sm_lt ? (1 << 6) : 0 |
++ sm_xt ? (1 << 5) : 0;
++
++ tda18271_write_regs(fe, R_EP3, 1);
++
++ return 0;
++}
++
++/*---------------------------------------------------------------------*/
++
++int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq)
++{
++ /* sets main post divider & divider bytes, but does not write them */
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
++ u8 d, pd;
++ u32 div;
++
++ int ret = tda18271_lookup_pll_map(fe, MAIN_PLL, &freq, &pd, &d);
++ if (ret < 0)
++ goto fail;
++
++ regs[R_MPD] = (0x77 & pd);
++
++ switch (priv->mode) {
++ case TDA18271_ANALOG:
++ regs[R_MPD] &= ~0x08;
++ break;
++ case TDA18271_DIGITAL:
++ regs[R_MPD] |= 0x08;
++ break;
+ }
-+ return any;
++
++ div = ((d * (freq / 1000)) << 7) / 125;
++
++ regs[R_MD1] = 0x7f & (div >> 16);
++ regs[R_MD2] = 0xff & (div >> 8);
++ regs[R_MD3] = 0xff & div;
++fail:
++ return ret;
+}
+
-+static void ipath_hol_signal_down(struct ipath_devdata *dd)
++int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq)
+{
-+ if (ipath_signal_procs(dd, SIGSTOP))
-+ ipath_dbg("Stopped some processes\n");
-+ ipath_cancel_sends(dd, 1);
++ /* sets cal post divider & divider bytes, but does not write them */
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
++ u8 d, pd;
++ u32 div;
++
++ int ret = tda18271_lookup_pll_map(fe, CAL_PLL, &freq, &pd, &d);
++ if (ret < 0)
++ goto fail;
++
++ regs[R_CPD] = pd;
++
++ div = ((d * (freq / 1000)) << 7) / 125;
++
++ regs[R_CD1] = 0x7f & (div >> 16);
++ regs[R_CD2] = 0xff & (div >> 8);
++ regs[R_CD3] = 0xff & div;
++fail:
++ return ret;
+}
+
++/*---------------------------------------------------------------------*/
+
-+static void ipath_hol_signal_up(struct ipath_devdata *dd)
++int tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq)
+{
-+ if (ipath_signal_procs(dd, SIGCONT))
-+ ipath_dbg("Continued some processes\n");
++ /* sets bp filter bits, but does not write them */
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
++ u8 val;
++
++ int ret = tda18271_lookup_map(fe, BP_FILTER, freq, &val);
++ if (ret < 0)
++ goto fail;
++
++ regs[R_EP1] &= ~0x07; /* clear bp filter bits */
++ regs[R_EP1] |= (0x07 & val);
++fail:
++ return ret;
+}
+
-+/*
-+ * 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)
++int tda18271_calc_km(struct dvb_frontend *fe, u32 *freq)
+{
-+ 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);
++ /* sets K & M bits, but does not write them */
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
++ u8 val;
++
++ int ret = tda18271_lookup_map(fe, RF_CAL_KMCO, freq, &val);
++ if (ret < 0)
++ goto fail;
++
++ regs[R_EB13] &= ~0x7c; /* clear k & m bits */
++ regs[R_EB13] |= (0x7c & val);
++fail:
++ return ret;
+}
+
-+/*
-+ * 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)
++int tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq)
+{
-+ ipath_hol_signal_up(dd);
-+ dd->ipath_hol_state = IPATH_HOL_UP;
++ /* sets rf band bits, but does not write them */
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
++ u8 val;
++
++ int ret = tda18271_lookup_map(fe, RF_BAND, freq, &val);
++ if (ret < 0)
++ goto fail;
++
++ regs[R_EP2] &= ~0xe0; /* clear rf band bits */
++ regs[R_EP2] |= (0xe0 & (val << 5));
++fail:
++ return ret;
+}
+
-+/*
-+ * 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)
++int tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq)
+{
-+ struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
++ /* sets gain taper bits, but does not write them */
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
++ u8 val;
+
-+ 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 ret = tda18271_lookup_map(fe, GAIN_TAPER, freq, &val);
++ if (ret < 0)
++ goto fail;
++
++ regs[R_EP2] &= ~0x1f; /* clear gain taper bits */
++ regs[R_EP2] |= (0x1f & val);
++fail:
++ return ret;
+}
+
- 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 ) {
++int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq)
++{
++ /* sets IR Meas bits, but does not write them */
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
++ u8 val;
+
-+ 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)
++ int ret = tda18271_lookup_map(fe, IR_MEASURE, freq, &val);
++ if (ret < 0)
++ goto fail;
+
-+/*
-+ * 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 }
-+};
++ regs[R_EP5] &= ~0x07;
++ regs[R_EP5] |= (0x07 & val);
++fail:
++ return ret;
++}
+
- 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 tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq)
+{
-+ int bit_cntr, data;
++ /* sets rf cal byte (RFC_Cprog), but does not write it */
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
++ u8 val;
+
-+ data = 0;
++ tda18271_lookup_map(fe, RF_CAL, freq, &val);
+
-+ 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;
++ regs[R_EB14] = val;
++
++ return 0;
+}
+
-+/**
- * 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)
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-basic-offset: 8
++ * End:
++ */
+diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c
+new file mode 100644
+index 0000000..b262100
+--- /dev/null
++++ b/drivers/media/common/tuners/tda18271-fe.c
+@@ -0,0 +1,1153 @@
++/*
++ tda18271-fe.c - driver for the Philips / NXP TDA18271 silicon tuner
++
++ Copyright (C) 2007, 2008 Michael Krufky <mkrufky at linuxtv.org>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++*/
++
++#include <linux/delay.h>
++#include <linux/videodev2.h>
++#include "tda18271-priv.h"
++
++int tda18271_debug;
++module_param_named(debug, tda18271_debug, int, 0644);
++MODULE_PARM_DESC(debug, "set debug level "
++ "(info=1, map=2, reg=4, adv=8, cal=16 (or-able))");
++
++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 DEFINE_MUTEX(tda18271_list_mutex);
++static LIST_HEAD(hybrid_tuner_instance_list);
++
++/*---------------------------------------------------------------------*/
++
++static inline int charge_pump_source(struct dvb_frontend *fe, int force)
+{
-+ int ret = 0;
++ struct tda18271_priv *priv = fe->tuner_priv;
++ return tda18271_charge_pump_source(fe,
++ (priv->role == TDA18271_SLAVE) ?
++ TDA18271_CAL_PLL :
++ TDA18271_MAIN_PLL, force);
++}
+
-+ ret = eeprom_reset(dd);
-+ if (ret) {
-+ ipath_dev_err(dd, "Failed reset probing device 0x%02X\n",
-+ devaddr);
-+ return ret;
++static int tda18271_channel_configuration(struct dvb_frontend *fe,
++ struct tda18271_std_map_item *map,
++ u32 freq, u32 bw)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
++ u32 N;
++
++ /* update TV broadcast parameters */
++
++ /* set standard */
++ regs[R_EP3] &= ~0x1f; /* clear std bits */
++ 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_MPD] |= 0x80; /* IF notch = 1 */
++ break;
+ }
-+ /*
-+ * 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);
++
++ /* update FM_RFn */
++ regs[R_EP4] &= ~0x80;
++ regs[R_EP4] |= map->fm_rfn << 7;
++
++ /* update rf top / if top */
++ regs[R_EB22] = 0x00;
++ regs[R_EB22] |= map->rfagc_top;
++ tda18271_write_regs(fe, R_EB22, 1);
++
++ /* --------------------------------------------------------------- */
++
++ /* disable Power Level Indicator */
++ regs[R_EP1] |= 0x40;
++
++ /* frequency dependent parameters */
++
++ tda18271_calc_ir_measure(fe, &freq);
++
++ tda18271_calc_bp_filter(fe, &freq);
++
++ tda18271_calc_rf_band(fe, &freq);
++
++ tda18271_calc_gain_taper(fe, &freq);
++
++ /* --------------------------------------------------------------- */
++
++ /* dual tuner and agc1 extra configuration */
++
++ switch (priv->role) {
++ case TDA18271_MASTER:
++ regs[R_EB1] |= 0x04; /* main vco */
++ break;
++ case TDA18271_SLAVE:
++ regs[R_EB1] &= ~0x04; /* cal vco */
++ break;
+ }
-+ return ret;
++
++ /* agc1 always active */
++ regs[R_EB1] &= ~0x02;
++
++ /* agc1 has priority on agc2 */
++ regs[R_EB1] &= ~0x01;
++
++ tda18271_write_regs(fe, R_EB1, 1);
++
++ /* --------------------------------------------------------------- */
++
++ N = map->if_freq * 1000 + freq;
++
++ 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);
++
++ /* force charge pump source */
++ charge_pump_source(fe, 1);
++
++ msleep(1);
++
++ /* return pll to normal operation */
++ charge_pump_source(fe, 0);
++
++ 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;
+}
+
-+/*
-+ * 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)
++static int tda18271_read_thermometer(struct dvb_frontend *fe)
+{
-+ int idx;
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
++ int tm;
+
-+ /* 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;
++ /* switch thermometer on */
++ regs[R_TM] |= 0x10;
++ tda18271_write_regs(fe, R_TM, 1);
+
-+ 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;
++ /* read thermometer info */
++ tda18271_read_regs(fe);
++
++ if ((((regs[R_TM] & 0x0f) == 0x00) && ((regs[R_TM] & 0x20) == 0x20)) ||
++ (((regs[R_TM] & 0x0f) == 0x08) && ((regs[R_TM] & 0x20) == 0x00))) {
++
++ if ((regs[R_TM] & 0x20) == 0x20)
++ regs[R_TM] &= ~0x20;
++ else
++ regs[R_TM] |= 0x20;
++
++ tda18271_write_regs(fe, R_TM, 1);
++
++ msleep(10); /* temperature sensing */
++
++ /* read thermometer info */
++ tda18271_read_regs(fe);
+ }
+
-+ /*
-+ * Old EEPROM (first entry) may require a reset after probe,
-+ * rather than being able to "start" after "stop"
-+ */
-+ if (idx == 0)
-+ eeprom_reset(dd);
++ tm = tda18271_lookup_thermometer(fe);
+
-+ 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;
++ /* switch thermometer off */
++ regs[R_TM] &= ~0x10;
++ tda18271_write_regs(fe, R_TM, 1);
++
++ /* set CAL mode to normal */
++ regs[R_EP4] &= ~0x03;
++ tda18271_write_regs(fe, R_EP4, 1);
++
++ return tm;
+}
-
- 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);
++
++/* ------------------------------------------------------------------ */
++
++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;
++ unsigned char *regs = priv->tda18271_regs;
++ int tm_current, rfcal_comp, approx, i;
++ u8 dc_over_dt, rf_tab;
++
++ /* power up */
++ tda18271_set_standby_mode(fe, 0, 0, 0);
++
++ /* read die current temperature */
++ tm_current = tda18271_read_thermometer(fe);
++
++ /* frequency dependent parameters */
++
++ tda18271_calc_rf_cal(fe, &freq);
++ rf_tab = regs[R_EB14];
++
++ i = tda18271_lookup_rf_band(fe, &freq, NULL);
++ if (i < 0)
++ return -EINVAL;
++
++ if ((0 == map[i].rf3) || (freq / 1000 < map[i].rf2)) {
++ approx = map[i].rf_a1 *
++ (freq / 1000 - map[i].rf1) + map[i].rf_b1 + rf_tab;
+ } 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);
++ approx = map[i].rf_a2 *
++ (freq / 1000 - map[i].rf2) + map[i].rf_b2 + rf_tab;
+ }
-+ 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)
++ if (approx < 0)
++ approx = 0;
++ if (approx > 255)
++ approx = 255;
++
++ tda18271_lookup_map(fe, RF_CAL_DC_OVER_DT, &freq, &dc_over_dt);
++
++ /* calculate temperature compensation */
++ rfcal_comp = dc_over_dt * (tm_current - priv->tm_rfcal);
++
++ regs[R_EB14] = approx + rfcal_comp;
++ tda18271_write_regs(fe, R_EB14, 1);
++
++ return 0;
++}
++
++static int tda18271_por(struct dvb_frontend *fe)
+{
-+ int ret;
-+ struct i2c_chain_desc *icd;
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
+
-+ ret = -ENOENT;
++ /* power up detector 1 */
++ regs[R_EB12] &= ~0x20;
++ tda18271_write_regs(fe, R_EB12, 1);
+
-+ icd = ipath_i2c_type(dd);
-+ if (!icd)
-+ goto bail;
++ regs[R_EB18] &= ~0x80; /* turn agc1 loop on */
++ regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */
++ tda18271_write_regs(fe, R_EB18, 1);
+
-+ if (icd->temp_dev == IPATH_NO_DEV) {
-+ /* tempsense only exists on new, real-I2C boards */
-+ ret = -ENXIO;
-+ goto bail;
-+ }
++ regs[R_EB21] |= 0x03; /* set agc2_gain to -6 dB */
+
-+ 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);
++ /* POR mode */
++ tda18271_set_standby_mode(fe, 1, 0, 0);
+
-+bail:
-+ return ret;
++ /* disable 1.5 MHz low pass filter */
++ regs[R_EB23] &= ~0x04; /* forcelp_fc2_en = 0 */
++ regs[R_EB23] &= ~0x02; /* XXX: lp_fc[2] = 0 */
++ tda18271_write_regs(fe, R_EB21, 3);
++
++ return 0;
+}
+
-+#define VALID_TS_RD_REG_MASK 0xBF
++static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
++ u32 N;
+
-+/**
-+ * 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)
++ /* set CAL mode to normal */
++ regs[R_EP4] &= ~0x03;
++ tda18271_write_regs(fe, R_EP4, 1);
++
++ /* switch off agc1 */
++ regs[R_EP3] |= 0x40; /* sm_lt = 1 */
++
++ regs[R_EB18] |= 0x03; /* set agc1_gain to 15 dB */
++ tda18271_write_regs(fe, R_EB18, 1);
++
++ /* frequency dependent parameters */
++
++ tda18271_calc_bp_filter(fe, &freq);
++ tda18271_calc_gain_taper(fe, &freq);
++ tda18271_calc_rf_band(fe, &freq);
++ tda18271_calc_km(fe, &freq);
++
++ tda18271_write_regs(fe, R_EP1, 3);
++ tda18271_write_regs(fe, R_EB13, 1);
++
++ /* main pll charge pump source */
++ tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1);
++
++ /* cal pll charge pump source */
++ tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 1);
++
++ /* force dcdc converter to 0 V */
++ regs[R_EB14] = 0x00;
++ tda18271_write_regs(fe, R_EB14, 1);
++
++ /* disable plls lock */
++ regs[R_EB20] &= ~0x20;
++ tda18271_write_regs(fe, R_EB20, 1);
++
++ /* set CAL mode to RF tracking filter calibration */
++ regs[R_EP4] |= 0x03;
++ tda18271_write_regs(fe, R_EP4, 2);
++
++ /* --------------------------------------------------------------- */
++
++ /* set the internal calibration signal */
++ N = freq;
++
++ tda18271_calc_cal_pll(fe, N);
++ tda18271_write_regs(fe, R_CPD, 4);
++
++ /* downconvert internal calibration */
++ N += 1000000;
++
++ tda18271_calc_main_pll(fe, N);
++ tda18271_write_regs(fe, R_MPD, 4);
++
++ msleep(5);
++
++ tda18271_write_regs(fe, R_EP2, 1);
++ tda18271_write_regs(fe, R_EP1, 1);
++ tda18271_write_regs(fe, R_EP2, 1);
++ tda18271_write_regs(fe, R_EP1, 1);
++
++ /* --------------------------------------------------------------- */
++
++ /* normal operation for the main pll */
++ tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0);
++
++ /* normal operation for the cal pll */
++ tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 0);
++
++ msleep(10); /* plls locking */
++
++ /* launch the rf tracking filters calibration */
++ regs[R_EB20] |= 0x20;
++ tda18271_write_regs(fe, R_EB20, 1);
++
++ msleep(60); /* calibration */
++
++ /* --------------------------------------------------------------- */
++
++ /* set CAL mode to normal */
++ regs[R_EP4] &= ~0x03;
++
++ /* switch on agc1 */
++ regs[R_EP3] &= ~0x40; /* sm_lt = 0 */
++
++ regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */
++ tda18271_write_regs(fe, R_EB18, 1);
++
++ tda18271_write_regs(fe, R_EP3, 2);
++
++ /* synchronization */
++ tda18271_write_regs(fe, R_EP1, 1);
++
++ /* get calibration result */
++ tda18271_read_extended(fe);
++
++ return regs[R_EB14];
++}
++
++static int tda18271_powerscan(struct dvb_frontend *fe,
++ u32 *freq_in, u32 *freq_out)
+{
-+ int ret;
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
++ int sgn, bcal, count, wait;
++ u8 cid_target;
++ u16 count_limit;
++ u32 freq;
+
-+ if (regnum > 7)
-+ return -EINVAL;
++ freq = *freq_in;
+
-+ /* return a bogus value for (the one) register we do not have */
-+ if (!((1 << regnum) & VALID_TS_RD_REG_MASK))
-+ return 0;
++ tda18271_calc_rf_band(fe, &freq);
++ tda18271_calc_rf_cal(fe, &freq);
++ tda18271_calc_gain_taper(fe, &freq);
++ tda18271_lookup_cid_target(fe, &freq, &cid_target, &count_limit);
+
-+ ret = mutex_lock_interruptible(&dd->ipath_eep_lock);
-+ if (!ret) {
-+ ret = ipath_tempsense_internal_read(dd, regnum);
-+ mutex_unlock(&dd->ipath_eep_lock);
++ tda18271_write_regs(fe, R_EP2, 1);
++ tda18271_write_regs(fe, R_EB14, 1);
++
++ /* downconvert frequency */
++ freq += 1000000;
++
++ tda18271_calc_main_pll(fe, freq);
++ tda18271_write_regs(fe, R_MPD, 4);
++
++ msleep(5); /* pll locking */
++
++ /* detection mode */
++ regs[R_EP4] &= ~0x03;
++ regs[R_EP4] |= 0x01;
++ tda18271_write_regs(fe, R_EP4, 1);
++
++ /* launch power detection measurement */
++ tda18271_write_regs(fe, R_EP2, 1);
++
++ /* read power detection info, stored in EB10 */
++ tda18271_read_extended(fe);
++
++ /* algorithm initialization */
++ sgn = 1;
++ *freq_out = *freq_in;
++ bcal = 0;
++ count = 0;
++ wait = false;
++
++ while ((regs[R_EB10] & 0x3f) < cid_target) {
++ /* downconvert updated freq to 1 MHz */
++ freq = *freq_in + (sgn * count) + 1000000;
++
++ tda18271_calc_main_pll(fe, freq);
++ tda18271_write_regs(fe, R_MPD, 4);
++
++ if (wait) {
++ msleep(5); /* pll locking */
++ wait = false;
++ } else
++ udelay(100); /* pll locking */
++
++ /* launch power detection measurement */
++ tda18271_write_regs(fe, R_EP2, 1);
++
++ /* read power detection info, stored in EB10 */
++ tda18271_read_extended(fe);
++
++ count += 200;
++
++ if (count <= count_limit)
++ continue;
++
++ if (sgn <= 0)
++ break;
++
++ sgn = -1 * sgn;
++ count = 200;
++ wait = true;
+ }
+
-+ /*
-+ * 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;
++ if ((regs[R_EB10] & 0x3f) >= cid_target) {
++ bcal = 1;
++ *freq_out = freq - 1000000;
++ } else
++ bcal = 0;
++
++ tda_cal("bcal = %d, freq_in = %d, freq_out = %d (freq = %d)\n",
++ bcal, *freq_in, *freq_out, freq);
++
++ return bcal;
+}
+
-+static int ipath_tempsense_internal_write(struct ipath_devdata *dd,
-+ u8 regnum, u8 data)
++static int tda18271_powerscan_init(struct dvb_frontend *fe)
+{
-+ int ret = -ENOENT;
-+ struct i2c_chain_desc *icd;
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
+
-+ icd = ipath_i2c_type(dd);
-+ if (!icd)
-+ goto bail;
++ /* set standard to digital */
++ regs[R_EP3] &= ~0x1f; /* clear std bits */
++ regs[R_EP3] |= 0x12;
+
-+ 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;
++ /* set cal mode to normal */
++ regs[R_EP4] &= ~0x03;
++
++ /* update IF output level & IF notch frequency */
++ regs[R_EP4] &= ~0x1c; /* clear if level bits */
++
++ tda18271_write_regs(fe, R_EP3, 2);
++
++ regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */
++ tda18271_write_regs(fe, R_EB18, 1);
++
++ regs[R_EB21] &= ~0x03; /* set agc2_gain to -15 dB */
++
++ /* 1.5 MHz low pass filter */
++ regs[R_EB23] |= 0x04; /* forcelp_fc2_en = 1 */
++ regs[R_EB23] |= 0x02; /* lp_fc[2] = 1 */
++
++ tda18271_write_regs(fe, R_EB21, 3);
++
++ return 0;
++}
++
++static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++ struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state;
++ unsigned char *regs = priv->tda18271_regs;
++ int bcal, rf, i;
++#define RF1 0
++#define RF2 1
++#define RF3 2
++ u32 rf_default[3];
++ u32 rf_freq[3];
++ u8 prog_cal[3];
++ u8 prog_tab[3];
++
++ i = tda18271_lookup_rf_band(fe, &freq, NULL);
++
++ if (i < 0)
++ return i;
++
++ rf_default[RF1] = 1000 * map[i].rf1_def;
++ rf_default[RF2] = 1000 * map[i].rf2_def;
++ rf_default[RF3] = 1000 * map[i].rf3_def;
++
++ for (rf = RF1; rf <= RF3; rf++) {
++ if (0 == rf_default[rf])
++ return 0;
++ tda_cal("freq = %d, rf = %d\n", freq, rf);
++
++ /* look for optimized calibration frequency */
++ bcal = tda18271_powerscan(fe, &rf_default[rf], &rf_freq[rf]);
++
++ tda18271_calc_rf_cal(fe, &rf_freq[rf]);
++ prog_tab[rf] = regs[R_EB14];
++
++ if (1 == bcal)
++ prog_cal[rf] = tda18271_calibrate_rf(fe, rf_freq[rf]);
++ else
++ prog_cal[rf] = prog_tab[rf];
++
++ switch (rf) {
++ case RF1:
++ map[i].rf_a1 = 0;
++ map[i].rf_b1 = prog_cal[RF1] - prog_tab[RF1];
++ map[i].rf1 = rf_freq[RF1] / 1000;
++ break;
++ case RF2:
++ map[i].rf_a1 = (prog_cal[RF2] - prog_tab[RF2] -
++ prog_cal[RF1] + prog_tab[RF1]) /
++ ((rf_freq[RF2] - rf_freq[RF1]) / 1000);
++ map[i].rf2 = rf_freq[RF2] / 1000;
++ break;
++ case RF3:
++ map[i].rf_a2 = (prog_cal[RF3] - prog_tab[RF3] -
++ prog_cal[RF2] + prog_tab[RF2]) /
++ ((rf_freq[RF3] - rf_freq[RF2]) / 1000);
++ map[i].rf_b2 = prog_cal[RF2] - prog_tab[RF2];
++ map[i].rf3 = rf_freq[RF3] / 1000;
++ break;
++ default:
++ BUG();
++ }
+ }
+
-+bail:
-+ return ret;
++ return 0;
+}
+
-+#define VALID_TS_WR_REG_MASK ((1 << 9) | (1 << 0xB) | (1 << 0xD))
++static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned int i;
+
-+/**
-+ * 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)
++ tda_info("tda18271: performing RF tracking filter calibration\n");
++
++ /* wait for die temperature stabilization */
++ msleep(200);
++
++ tda18271_powerscan_init(fe);
++
++ /* rf band calibration */
++ for (i = 0; priv->rf_cal_state[i].rfmax != 0; i++)
++ tda18271_rf_tracking_filters_init(fe, 1000 *
++ priv->rf_cal_state[i].rfmax);
++
++ priv->tm_rfcal = tda18271_read_thermometer(fe);
++
++ return 0;
++}
++
++/* ------------------------------------------------------------------ */
++
++static int tda18271c2_rf_cal_init(struct dvb_frontend *fe)
+{
-+ int ret;
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
+
-+ if (regnum > 15 || !((1 << regnum) & VALID_TS_WR_REG_MASK))
-+ return -EINVAL;
++ /* test RF_CAL_OK to see if we need init */
++ if ((regs[R_EP1] & 0x10) == 0)
++ priv->cal_initialized = false;
+
-+ ret = mutex_lock_interruptible(&dd->ipath_eep_lock);
-+ if (!ret) {
-+ ret = ipath_tempsense_internal_write(dd, regnum, data);
-+ mutex_unlock(&dd->ipath_eep_lock);
-+ }
++ if (priv->cal_initialized)
++ return 0;
+
-+ /*
-+ * 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;
++ tda18271_calc_rf_filter_curve(fe);
++
++ tda18271_por(fe);
++
++ tda_info("tda18271: RF tracking filter calibration complete\n");
++
++ priv->cal_initialized = true;
++
++ return 0;
+}
-diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
-index 7e025c8..8b17522 100644
---- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
-+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
-@@ -1,5 +1,5 @@
- /*
-- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
-+ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
- * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
-@@ -36,21 +36,28 @@
- #include <linux/cdev.h>
- #include <linux/swap.h>
- #include <linux/vmalloc.h>
-+#include <linux/highmem.h>
-+#include <linux/io.h>
-+#include <linux/jiffies.h>
- #include <asm/pgtable.h>
-
- #include "ipath_kernel.h"
- #include "ipath_common.h"
-+#include "ipath_user_sdma.h"
-
- static int ipath_open(struct inode *, struct file *);
- static int ipath_close(struct inode *, struct file *);
- static ssize_t ipath_write(struct file *, const char __user *, size_t,
- loff_t *);
-+static ssize_t ipath_writev(struct kiocb *, const struct iovec *,
-+ unsigned long , loff_t);
- static unsigned int ipath_poll(struct file *, struct poll_table_struct *);
- static int ipath_mmap(struct file *, struct vm_area_struct *);
-
- static const struct file_operations ipath_file_ops = {
- .owner = THIS_MODULE,
- .write = ipath_write,
-+ .aio_write = ipath_writev,
- .open = ipath_open,
- .release = ipath_close,
- .poll = ipath_poll,
-@@ -184,6 +191,29 @@ static int ipath_get_base_info(struct file *fp,
- kinfo->spi_piobufbase = (u64) pd->port_piobufs +
- dd->ipath_palign * kinfo->spi_piocnt * slave;
- }
+
-+ /*
-+ * Set the PIO avail update threshold to no larger
-+ * than the number of buffers per process. Note that
-+ * we decrease it here, but won't ever increase it.
-+ */
-+ if (dd->ipath_pioupd_thresh &&
-+ kinfo->spi_piocnt < dd->ipath_pioupd_thresh) {
-+ unsigned long flags;
++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;
+
-+ 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);
-+ }
++ /* calculate bp filter */
++ tda18271_calc_bp_filter(fe, &freq);
++ tda18271_write_regs(fe, R_EP1, 1);
+
- 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;
++ regs[R_EB4] &= 0x07;
++ regs[R_EB4] |= 0x60;
++ tda18271_write_regs(fe, R_EB4, 1);
+
-+ fd->pq = ipath_user_sdma_queue_create(&dd->pcidev->dev,
-+ dd->ipath_unit,
-+ pd->port_port,
-+ fd->subport);
++ regs[R_EB7] = 0x60;
++ tda18271_write_regs(fe, R_EB7, 1);
+
-+ if (!fd->pq)
-+ ret = -ENOMEM;
++ regs[R_EB14] = 0x00;
++ tda18271_write_regs(fe, R_EB14, 1);
++
++ regs[R_EB20] = 0xcc;
++ tda18271_write_regs(fe, R_EB20, 1);
++
++ /* set cal mode to RF tracking filter calibration */
++ regs[R_EP4] |= 0x03;
++
++ /* calculate cal pll */
++
++ switch (priv->mode) {
++ case TDA18271_ANALOG:
++ N = freq - 1250000;
++ break;
++ case TDA18271_DIGITAL:
++ N = freq + bw / 2;
++ break;
+ }
+
- 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));
++ tda18271_calc_cal_pll(fe, N);
++
++ /* calculate main pll */
++
++ switch (priv->mode) {
++ case TDA18271_ANALOG:
++ N = freq - 250000;
++ break;
++ case TDA18271_DIGITAL:
++ N = freq + bw / 2 + 1000000;
++ break;
+ }
- 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;
- }
++ tda18271_calc_main_pll(fe, N);
+
-+ dd = pd->port_dd;
++ tda18271_write_regs(fe, R_EP3, 11);
++ msleep(5); /* RF tracking filter calibration initialization */
+
-+ /* drain user sdma queue */
-+ ipath_user_sdma_queue_drain(dd, fd->pq);
-+ ipath_user_sdma_queue_destroy(fd->pq);
++ /* search for K,M,CO for RF calibration */
++ tda18271_calc_km(fe, &freq);
++ tda18271_write_regs(fe, R_EB13, 1);
+
- 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;
++ /* search for rf band */
++ tda18271_calc_rf_band(fe, &freq);
++
++ /* search for gain taper */
++ tda18271_calc_gain_taper(fe, &freq);
++
++ tda18271_write_regs(fe, R_EP2, 1);
++ tda18271_write_regs(fe, R_EP1, 1);
++ tda18271_write_regs(fe, R_EP2, 1);
++ tda18271_write_regs(fe, R_EP1, 1);
++
++ regs[R_EB4] &= 0x07;
++ regs[R_EB4] |= 0x40;
++ tda18271_write_regs(fe, R_EB4, 1);
++
++ regs[R_EB7] = 0x40;
++ tda18271_write_regs(fe, R_EB7, 1);
++ msleep(10); /* pll locking */
++
++ regs[R_EB20] = 0xec;
++ tda18271_write_regs(fe, R_EB20, 1);
++ msleep(60); /* RF tracking filter calibration completion */
++
++ regs[R_EP4] &= ~0x03; /* set cal mode to normal */
++ tda18271_write_regs(fe, R_EP4, 1);
++
++ tda18271_write_regs(fe, R_EP1, 1);
++
++ /* RF tracking filter correction for VHF_Low band */
++ if (0 == tda18271_calc_rf_cal(fe, &freq))
++ tda18271_write_regs(fe, R_EB14, 1);
++
++ return 0;
++}
++
++/* ------------------------------------------------------------------ */
++
++static int tda18271_ir_cal_init(struct dvb_frontend *fe)
++{
++ 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;
++}
++
++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)
++ tda18271c2_rf_cal_init(fe);
++
++ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
-+static int ipath_sdma_get_complete(struct ipath_devdata *dd,
-+ struct ipath_user_sdma_queue *pq,
-+ u32 __user *completep)
++static int tda18271_tune(struct dvb_frontend *fe,
++ struct tda18271_std_map_item *map, u32 freq, u32 bw)
+{
-+ u32 val;
-+ int err;
++ struct tda18271_priv *priv = fe->tuner_priv;
+
-+ err = ipath_user_sdma_make_progress(dd, pq);
-+ if (err < 0)
-+ return err;
++ tda_dbg("freq = %d, ifc = %d, bw = %d, agc_mode = %d, std = %d\n",
++ freq, map->if_freq, bw, map->agc_mode, map->std);
+
-+ 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);
++ tda18271_init(fe);
++
++ mutex_lock(&priv->lock);
++
++ switch (priv->id) {
++ case TDA18271HDC1:
++ tda18271c1_rf_tracking_filter_calibration(fe, freq, bw);
+ 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);
++ case TDA18271HDC2:
++ tda18271c2_rf_tracking_filters_correction(fe, freq);
+ 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;
++ }
++ tda18271_channel_configuration(fe, map, freq, bw);
+
-+ if (!dim)
-+ return -EINVAL;
++ mutex_unlock(&priv->lock);
+
-+ return ipath_user_sdma_writev(pd->port_dd, pq, iov, dim);
++ return 0;
+}
+
- static struct class *ipath_class;
-
- static int init_cdev(int minor, char *name, const struct file_operations *fops,
-- struct cdev **cdevp, struct class_device **class_devp)
-+ struct cdev **cdevp, struct device **devp)
- {
- const dev_t dev = MKDEV(IPATH_MAJOR, minor);
- struct cdev *cdev = NULL;
-- struct class_device *class_dev = NULL;
-+ struct device *device = NULL;
- int ret;
-
- cdev = cdev_alloc();
-@@ -2350,12 +2462,12 @@ static int init_cdev(int minor, char *name, const struct file_operations *fops,
- goto err_cdev;
- }
-
-- class_dev = class_device_create(ipath_class, NULL, dev, NULL, name);
-+ device = device_create(ipath_class, NULL, dev, name);
-
-- if (IS_ERR(class_dev)) {
-- ret = PTR_ERR(class_dev);
-+ if (IS_ERR(device)) {
-+ ret = PTR_ERR(device);
- printk(KERN_ERR IPATH_DRV_NAME ": Could not create "
-- "class_dev for minor %d, %s (err %d)\n",
-+ "device for minor %d, %s (err %d)\n",
- minor, name, -ret);
- goto err_cdev;
- }
-@@ -2369,29 +2481,29 @@ err_cdev:
- done:
- if (ret >= 0) {
- *cdevp = cdev;
-- *class_devp = class_dev;
-+ *devp = device;
- } else {
- *cdevp = NULL;
-- *class_devp = NULL;
-+ *devp = NULL;
- }
-
- return ret;
- }
-
- int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,
-- struct cdev **cdevp, struct class_device **class_devp)
-+ struct cdev **cdevp, struct device **devp)
- {
-- return init_cdev(minor, name, fops, cdevp, class_devp);
-+ return init_cdev(minor, name, fops, cdevp, devp);
- }
-
- static void cleanup_cdev(struct cdev **cdevp,
-- struct class_device **class_devp)
-+ struct device **devp)
- {
-- struct class_device *class_dev = *class_devp;
-+ struct device *dev = *devp;
-
-- if (class_dev) {
-- class_device_unregister(class_dev);
-- *class_devp = NULL;
-+ if (dev) {
-+ device_unregister(dev);
-+ *devp = NULL;
- }
-
- if (*cdevp) {
-@@ -2401,13 +2513,13 @@ static void cleanup_cdev(struct cdev **cdevp,
- }
-
- void ipath_cdev_cleanup(struct cdev **cdevp,
-- struct class_device **class_devp)
-+ struct device **devp)
- {
-- cleanup_cdev(cdevp, class_devp);
-+ cleanup_cdev(cdevp, devp);
- }
-
- static struct cdev *wildcard_cdev;
--static struct class_device *wildcard_class_dev;
-+static struct device *wildcard_dev;
-
- static const dev_t dev = MKDEV(IPATH_MAJOR, 0);
-
-@@ -2464,7 +2576,7 @@ int ipath_user_add(struct ipath_devdata *dd)
- goto bail;
- }
- ret = init_cdev(0, "ipath", &ipath_file_ops, &wildcard_cdev,
-- &wildcard_class_dev);
-+ &wildcard_dev);
- if (ret < 0) {
- ipath_dev_err(dd, "Could not create wildcard "
- "minor: error %d\n", -ret);
-@@ -2477,7 +2589,7 @@ int ipath_user_add(struct ipath_devdata *dd)
- snprintf(name, sizeof(name), "ipath%d", dd->ipath_unit);
-
- ret = init_cdev(dd->ipath_unit + 1, name, &ipath_file_ops,
-- &dd->user_cdev, &dd->user_class_dev);
-+ &dd->user_cdev, &dd->user_dev);
- if (ret < 0)
- ipath_dev_err(dd, "Could not create user minor %d, %s\n",
- dd->ipath_unit + 1, name);
-@@ -2492,13 +2604,13 @@ bail:
-
- void ipath_user_remove(struct ipath_devdata *dd)
- {
-- cleanup_cdev(&dd->user_cdev, &dd->user_class_dev);
-+ cleanup_cdev(&dd->user_cdev, &dd->user_dev);
-
- if (atomic_dec_return(&user_count) == 0) {
- if (atomic_read(&user_setup) == 0)
- goto bail;
-
-- cleanup_cdev(&wildcard_cdev, &wildcard_class_dev);
-+ cleanup_cdev(&wildcard_cdev, &wildcard_dev);
- user_cleanup();
-
- atomic_set(&user_setup, 0);
-diff --git a/drivers/infiniband/hw/ipath/ipath_iba6110.c b/drivers/infiniband/hw/ipath/ipath_iba6110.c
-index 9e2ced3..02831ad 100644
---- a/drivers/infiniband/hw/ipath/ipath_iba6110.c
-+++ b/drivers/infiniband/hw/ipath/ipath_iba6110.c
-@@ -40,6 +40,7 @@
- #include <linux/pci.h>
- #include <linux/delay.h>
- #include <linux/htirq.h>
-+#include <rdma/ib_verbs.h>
-
- #include "ipath_kernel.h"
- #include "ipath_registers.h"
-@@ -305,7 +306,9 @@ static const struct ipath_cregs ipath_ht_cregs = {
-
- /* kr_intstatus, kr_intclear, kr_intmask bits */
- #define INFINIPATH_I_RCVURG_MASK ((1U<<9)-1)
-+#define INFINIPATH_I_RCVURG_SHIFT 0
- #define INFINIPATH_I_RCVAVAIL_MASK ((1U<<9)-1)
-+#define INFINIPATH_I_RCVAVAIL_SHIFT 12
-
- /* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
- #define INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT 0
-@@ -476,7 +479,13 @@ static const struct ipath_hwerror_msgs ipath_6110_hwerror_msgs[] = {
- #define RXE_EAGER_PARITY (INFINIPATH_HWE_RXEMEMPARITYERR_EAGERTID \
- << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT)
-
--static int ipath_ht_txe_recover(struct ipath_devdata *);
-+static void ipath_ht_txe_recover(struct ipath_devdata *dd)
++/* ------------------------------------------------------------------ */
++
++static int tda18271_set_params(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *params)
+{
-+ ++ipath_stats.sps_txeparity;
-+ dev_info(&dd->pcidev->dev,
-+ "Recovering from TXE PIO parity error\n");
-+}
++ struct tda18271_priv *priv = fe->tuner_priv;
++ struct tda18271_std_map *std_map = &priv->std;
++ struct tda18271_std_map_item *map;
++ int ret;
++ u32 bw, freq = params->frequency;
+
-
- /**
- * 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");
-+ }
++ priv->mode = TDA18271_DIGITAL;
+
- 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;
- }
++ if (fe->ops.info.type == FE_ATSC) {
++ switch (params->u.vsb.modulation) {
++ case VSB_8:
++ case VSB_16:
++ map = &std_map->atsc_6;
++ break;
++ case QAM_64:
++ case QAM_256:
++ map = &std_map->qam_6;
++ break;
++ default:
++ tda_warn("modulation not set!\n");
++ return -EINVAL;
++ }
++#if 0
++ /* userspace request is already center adjusted */
++ freq += 1750000; /* Adjust to center (+1.75MHZ) */
++#endif
++ bw = 6000000;
++ } else if (fe->ops.info.type == FE_OFDM) {
++ switch (params->u.ofdm.bandwidth) {
++ case BANDWIDTH_6_MHZ:
++ bw = 6000000;
++ map = &std_map->dvbt_6;
++ break;
++ case BANDWIDTH_7_MHZ:
++ bw = 7000000;
++ map = &std_map->dvbt_7;
++ break;
++ case BANDWIDTH_8_MHZ:
++ bw = 8000000;
++ map = &std_map->dvbt_8;
++ break;
++ default:
++ tda_warn("bandwidth not set!\n");
++ return -EINVAL;
++ }
++ } else {
++ tda_warn("modulation type not supported!\n");
++ return -EINVAL;
++ }
+
-+ snprintf(dd->ipath_lbus_info, sizeof(dd->ipath_lbus_info),
-+ "HyperTransport,%uMHz,x%u\n",
-+ dd->ipath_lbus_speed,
-+ dd->ipath_lbus_width);
- }
-
- static int ipath_ht_intconfig(struct ipath_devdata *dd)
-@@ -1653,22 +1666,6 @@ static int ipath_ht_early_init(struct ipath_devdata *dd)
- }
-
-
--static int ipath_ht_txe_recover(struct ipath_devdata *dd)
--{
-- int cnt = ++ipath_stats.sps_txeparity;
-- if (cnt >= IPATH_MAX_PARITY_ATTEMPTS) {
-- if (cnt == IPATH_MAX_PARITY_ATTEMPTS)
-- ipath_dev_err(dd,
-- "Too many attempts to recover from "
-- "TXE parity, giving up\n");
-- return 0;
-- }
-- dev_info(&dd->pcidev->dev,
-- "Recovering from TXE PIO parity error\n");
-- return 1;
--}
--
--
- /**
- * ipath_init_ht_get_base_info - set chip-specific flags for user code
- * @dd: the infinipath device
-diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c
-index c7a2f50..421cc2a 100644
---- a/drivers/infiniband/hw/ipath/ipath_iba6120.c
-+++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c
-@@ -1,5 +1,5 @@
- /*
-- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
-+ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
- * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
-@@ -38,7 +38,7 @@
- #include <linux/interrupt.h>
- #include <linux/pci.h>
- #include <linux/delay.h>
--
-+#include <rdma/ib_verbs.h>
-
- #include "ipath_kernel.h"
- #include "ipath_registers.h"
-@@ -311,9 +311,14 @@ static const struct ipath_cregs ipath_pe_cregs = {
- .cr_ibsymbolerrcnt = IPATH_CREG_OFFSET(IBSymbolErrCnt)
- };
-
-+/* kr_control bits */
-+#define INFINIPATH_C_RESET 1U
++ /* When tuning digital, the analog demod must be tri-stated */
++ if (fe->ops.analog_ops.standby)
++ fe->ops.analog_ops.standby(fe);
+
- /* 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
++ ret = tda18271_tune(fe, map, freq, bw);
+
- #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
++ if (ret < 0)
++ goto fail;
+
- #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 */
++ priv->frequency = freq;
++ priv->bandwidth = (fe->ops.info.type == FE_OFDM) ?
++ params->u.ofdm.bandwidth : 0;
++fail:
++ return ret;
++}
+
-+ 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)
++static int tda18271_set_analog_params(struct dvb_frontend *fe,
++ struct analog_parameters *params)
+{
-+ u16 linkstat, speed;
-+ int pos;
++ 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;
++ u32 freq = params->frequency * 62500;
+
-+ 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;
++ priv->mode = TDA18271_ANALOG;
++
++ if (params->mode == V4L2_TUNER_RADIO) {
++ freq = freq / 1000;
++ map = &std_map->fm_radio;
++ mode = "fm";
++ } else if (params->std & V4L2_STD_MN) {
++ map = &std_map->atv_mn;
++ mode = "MN";
++ } else if (params->std & V4L2_STD_B) {
++ map = &std_map->atv_b;
++ mode = "B";
++ } else if (params->std & V4L2_STD_GH) {
++ map = &std_map->atv_gh;
++ mode = "GH";
++ } else if (params->std & V4L2_STD_PAL_I) {
++ map = &std_map->atv_i;
++ mode = "I";
++ } else if (params->std & V4L2_STD_DK) {
++ map = &std_map->atv_dk;
++ mode = "DK";
++ } else if (params->std & V4L2_STD_SECAM_L) {
++ map = &std_map->atv_l;
++ mode = "L";
++ } else if (params->std & V4L2_STD_SECAM_LC) {
++ map = &std_map->atv_lc;
++ mode = "L'";
++ } else {
++ map = &std_map->atv_i;
++ mode = "xx";
+ }
+
-+ 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;
++ tda_dbg("setting tda18271 to system %s\n", mode);
+
-+ 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;
-+ }
++ ret = tda18271_tune(fe, map, freq, 0);
+
-+ 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 (ret < 0)
++ goto fail;
+
-+ 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);
++ priv->frequency = freq;
++ priv->bandwidth = 0;
++fail:
++ return ret;
++}
+
-+ return;
++static int tda18271_sleep(struct dvb_frontend *fe)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++
++ mutex_lock(&priv->lock);
++
++ /* standby mode w/ slave tuner output
++ * & loop thru & xtal oscillator on */
++ tda18271_set_standby_mode(fe, 1, 0, 0);
++
++ mutex_unlock(&priv->lock);
++
++ return 0;
+}
+
- /**
- * 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");
++static int tda18271_release(struct dvb_frontend *fe)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
+
-+ 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;
++ mutex_lock(&tda18271_list_mutex);
+
-+ 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 (priv)
++ hybrid_tuner_release_state(priv);
+
-+ 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;
++ mutex_unlock(&tda18271_list_mutex);
+
-+ 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);
- }
++ fe->tuner_priv = NULL;
+
- /**
- * 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;
++ return 0;
++}
+
-+ 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)
-+ */
++static int tda18271_get_frequency(struct dvb_frontend *fe, u32 *frequency)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++ *frequency = priv->frequency;
++ return 0;
++}
+
-+#include <linux/interrupt.h>
-+#include <linux/pci.h>
-+#include <linux/delay.h>
-+#include <linux/io.h>
-+#include <rdma/ib_verbs.h>
++static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++ *bandwidth = priv->bandwidth;
++ return 0;
++}
+
-+#include "ipath_kernel.h"
-+#include "ipath_registers.h"
-+#include "ipath_7220.h"
++/* ------------------------------------------------------------------ */
+
-+static void ipath_setup_7220_setextled(struct ipath_devdata *, u64, u64);
++#define tda18271_update_std(std_cfg, name) do { \
++ 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)
+
-+static unsigned ipath_compat_ddr_negotiate = 1;
++#define tda18271_dump_std_item(std_cfg, name) do { \
++ 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)
+
-+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 int tda18271_dump_std_map(struct dvb_frontend *fe)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++ struct tda18271_std_map *std = &priv->std;
+
-+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");
++ tda_dbg("========== STANDARD MAP SETTINGS ==========\n");
++ 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 ");
+
-+/*
-+ * 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];
-+};
++ return 0;
++}
+
-+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;
-+};
++static int tda18271_update_std_map(struct dvb_frontend *fe,
++ struct tda18271_std_map *map)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++ struct tda18271_std_map *std = &priv->std;
+
-+#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))
++ if (!map)
++ return -EINVAL;
+
-+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),
++ tda18271_update_std(fm_radio, "fm");
++ tda18271_update_std(atv_b, "atv b");
++ tda18271_update_std(atv_dk, "atv dk");
++ tda18271_update_std(atv_gh, "atv gh");
++ tda18271_update_std(atv_i, "atv i");
++ tda18271_update_std(atv_l, "atv l");
++ tda18271_update_std(atv_lc, "atv l'");
++ tda18271_update_std(atv_mn, "atv mn");
++ tda18271_update_std(atsc_6, "atsc 6");
++ tda18271_update_std(dvbt_6, "dvbt 6");
++ tda18271_update_std(dvbt_7, "dvbt 7");
++ tda18271_update_std(dvbt_8, "dvbt 8");
++ tda18271_update_std(qam_6, "qam 6");
++ tda18271_update_std(qam_8, "qam 8");
+
-+ .kr_xgxsconfig = IPATH_KREG_OFFSET(XGXSConfig),
++ return 0;
++}
+
-+ /* 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),
++static int tda18271_get_id(struct dvb_frontend *fe)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
++ char *name;
++ int ret = 0;
+
-+ /* 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),
++ mutex_lock(&priv->lock);
++ tda18271_read_regs(fe);
++ mutex_unlock(&priv->lock);
+
-+ /*
-+ * 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),
++ switch (regs[R_ID] & 0x7f) {
++ case 3:
++ name = "TDA18271HD/C1";
++ priv->id = TDA18271HDC1;
++ break;
++ case 4:
++ name = "TDA18271HD/C2";
++ priv->id = TDA18271HDC2;
++ break;
++ default:
++ name = "Unknown device";
++ ret = -EINVAL;
++ break;
++ }
+
-+ /*
-+ * 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),
++ tda_info("%s detected @ %d-%04x%s\n", name,
++ i2c_adapter_id(priv->i2c_props.adap),
++ priv->i2c_props.addr,
++ (0 == ret) ? "" : ", device not supported.");
+
-+ .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)
-+};
++ return ret;
++}
+
-+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),
++static struct dvb_tuner_ops tda18271_tuner_ops = {
++ .info = {
++ .name = "NXP TDA18271HD",
++ .frequency_min = 45000000,
++ .frequency_max = 864000000,
++ .frequency_step = 62500
++ },
++ .init = tda18271_init,
++ .sleep = tda18271_sleep,
++ .set_params = tda18271_set_params,
++ .set_analog_params = tda18271_set_analog_params,
++ .release = tda18271_release,
++ .get_frequency = tda18271_get_frequency,
++ .get_bandwidth = tda18271_get_bandwidth,
+};
+
-+/* kr_control bits */
-+#define INFINIPATH_C_RESET (1U<<7)
++struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
++ struct i2c_adapter *i2c,
++ struct tda18271_config *cfg)
++{
++ struct tda18271_priv *priv = NULL;
++ int instance;
+
-+/* 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)
++ mutex_lock(&tda18271_list_mutex);
+
-+/* 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
++ 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);
+
-+#define IBA7220_IBCS_LINKTRAININGSTATE_MASK 0x1F
-+#define IBA7220_IBCS_LINKSTATE_SHIFT 5
-+#define IBA7220_IBCS_LINKSPEED_SHIFT 8
-+#define IBA7220_IBCS_LINKWIDTH_SHIFT 9
++ fe->tuner_priv = priv;
+
-+#define IBA7220_IBCC_LINKINITCMD_MASK 0x7ULL
-+#define IBA7220_IBCC_LINKCMD_SHIFT 19
-+#define IBA7220_IBCC_MAXPKTLEN_SHIFT 21
++ if (cfg)
++ priv->small_i2c = cfg->small_i2c;
+
-+/* kr_ibcddrctrl bits */
-+#define IBA7220_IBC_DLIDLMC_MASK 0xFFFFFFFFUL
-+#define IBA7220_IBC_DLIDLMC_SHIFT 32
-+#define IBA7220_IBC_HRTBT_MASK 3
-+#define IBA7220_IBC_HRTBT_SHIFT 16
-+#define IBA7220_IBC_HRTBT_ENB 0x10000UL
-+#define IBA7220_IBC_LANE_REV_SUPPORTED (1<<8)
-+#define IBA7220_IBC_LREV_MASK 1
-+#define IBA7220_IBC_LREV_SHIFT 8
-+#define IBA7220_IBC_RXPOL_MASK 1
-+#define IBA7220_IBC_RXPOL_SHIFT 7
-+#define IBA7220_IBC_WIDTH_SHIFT 5
-+#define IBA7220_IBC_WIDTH_MASK 0x3
-+#define IBA7220_IBC_WIDTH_1X_ONLY (0<<IBA7220_IBC_WIDTH_SHIFT)
-+#define IBA7220_IBC_WIDTH_4X_ONLY (1<<IBA7220_IBC_WIDTH_SHIFT)
-+#define IBA7220_IBC_WIDTH_AUTONEG (2<<IBA7220_IBC_WIDTH_SHIFT)
-+#define IBA7220_IBC_SPEED_AUTONEG (1<<1)
-+#define IBA7220_IBC_SPEED_SDR (1<<2)
-+#define IBA7220_IBC_SPEED_DDR (1<<3)
-+#define IBA7220_IBC_SPEED_AUTONEG_MASK (0x7<<1)
-+#define IBA7220_IBC_IBTA_1_2_MASK (1)
++ if (tda18271_get_id(fe) < 0)
++ goto fail;
+
-+/* kr_ibcddrstatus */
-+/* link latency shift is 0, don't bother defining */
-+#define IBA7220_DDRSTAT_LINKLAT_MASK 0x3ffffff
++ if (tda18271_assign_map_layout(fe) < 0)
++ goto fail;
+
-+/* kr_extstatus bits */
-+#define INFINIPATH_EXTS_FREQSEL 0x2
-+#define INFINIPATH_EXTS_SERDESSEL 0x4
-+#define INFINIPATH_EXTS_MEMBIST_ENDTEST 0x0000000000004000
-+#define INFINIPATH_EXTS_MEMBIST_DISABLED 0x0000000000008000
++ mutex_lock(&priv->lock);
++ tda18271_init_regs(fe);
+
-+/* kr_xgxsconfig bits */
-+#define INFINIPATH_XGXS_RESET 0x5ULL
-+#define INFINIPATH_XGXS_FC_SAFE (1ULL<<63)
++ if ((tda18271_cal_on_startup) && (priv->id == TDA18271HDC2))
++ tda18271c2_rf_cal_init(fe);
+
-+/* kr_rcvpktledcnt */
-+#define IBA7220_LEDBLINK_ON_SHIFT 32 /* 4ns period on after packet */
-+#define IBA7220_LEDBLINK_OFF_SHIFT 0 /* 4ns period off before next on */
++ mutex_unlock(&priv->lock);
++ break;
++ default:
++ /* existing tuner instance */
++ fe->tuner_priv = priv;
+
-+#define _IPATH_GPIO_SDA_NUM 1
-+#define _IPATH_GPIO_SCL_NUM 0
++ /* allow dvb driver to override i2c gate setting */
++ if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG))
++ priv->gate = cfg->gate;
++ break;
++ }
+
-+#define IPATH_GPIO_SDA (1ULL << \
-+ (_IPATH_GPIO_SDA_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
-+#define IPATH_GPIO_SCL (1ULL << \
-+ (_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
++ /* override default std map with values in config struct */
++ if ((cfg) && (cfg->std_map))
++ tda18271_update_std_map(fe, cfg->std_map);
+
-+#define IBA7220_R_INTRAVAIL_SHIFT 17
-+#define IBA7220_R_TAILUPD_SHIFT 35
-+#define IBA7220_R_PORTCFG_SHIFT 36
++ mutex_unlock(&tda18271_list_mutex);
+
-+#define INFINIPATH_JINT_PACKETSHIFT 16
-+#define INFINIPATH_JINT_DEFAULT_IDLE_TICKS 0
-+#define INFINIPATH_JINT_DEFAULT_MAX_PACKETS 0
++ memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
++ sizeof(struct dvb_tuner_ops));
+
-+#define IBA7220_HDRHEAD_PKTINT_SHIFT 32 /* interrupt cnt in upper 32 bits */
++ if (tda18271_debug & (DBG_MAP | DBG_ADV))
++ tda18271_dump_std_map(fe);
++
++ return fe;
++fail:
++ mutex_unlock(&tda18271_list_mutex);
++
++ tda18271_release(fe);
++ return NULL;
++}
++EXPORT_SYMBOL_GPL(tda18271_attach);
++MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver");
++MODULE_AUTHOR("Michael Krufky <mkrufky at linuxtv.org>");
++MODULE_LICENSE("GPL");
++MODULE_VERSION("0.3");
+
+/*
-+ * the size bits give us 2^N, in KB units. 0 marks as invalid,
-+ * and 7 is reserved. We currently use only 2KB and 4KB
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-basic-offset: 8
++ * End:
+ */
-+#define IBA7220_TID_SZ_SHIFT 37 /* shift to 3bit size selector */
-+#define IBA7220_TID_SZ_2K (1UL<<IBA7220_TID_SZ_SHIFT) /* 2KB */
-+#define IBA7220_TID_SZ_4K (2UL<<IBA7220_TID_SZ_SHIFT) /* 4KB */
-+#define IBA7220_TID_PA_SHIFT 11U /* TID addr in chip stored w/o low bits */
+diff --git a/drivers/media/common/tuners/tda18271-maps.c b/drivers/media/common/tuners/tda18271-maps.c
+new file mode 100644
+index 0000000..83e7561
+--- /dev/null
++++ b/drivers/media/common/tuners/tda18271-maps.c
+@@ -0,0 +1,1313 @@
++/*
++ tda18271-tables.c - driver for the Philips / NXP TDA18271 silicon tuner
+
-+#define IPATH_AUTONEG_TRIES 5 /* sequential retries to negotiate DDR */
++ Copyright (C) 2007, 2008 Michael Krufky <mkrufky at linuxtv.org>
+
-+static char int_type[16] = "auto";
-+module_param_string(interrupt_type, int_type, sizeof(int_type), 0444);
-+MODULE_PARM_DESC(int_type, " interrupt_type=auto|force_msi|force_intx\n");
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
+
-+/* packet rate matching delay; chip has support */
-+static u8 rate_to_delay[2][2] = {
-+ /* 1x, 4x */
-+ { 8, 2 }, /* SDR */
-+ { 4, 1 } /* DDR */
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You 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 "tda18271-priv.h"
++
++struct tda18271_pll_map {
++ u32 lomax;
++ u8 pd; /* post div */
++ u8 d; /* div */
+};
+
-+/* 7220 specific hardware errors... */
-+static const struct ipath_hwerror_msgs ipath_7220_hwerror_msgs[] = {
-+ INFINIPATH_HWE_MSG(PCIEPOISONEDTLP, "PCIe Poisoned TLP"),
-+ INFINIPATH_HWE_MSG(PCIECPLTIMEOUT, "PCIe completion timeout"),
-+ /*
-+ * In practice, it's unlikely wthat we'll see PCIe PLL, or bus
-+ * parity or memory parity error failures, because most likely we
-+ * won't be able to talk to the core of the chip. Nonetheless, we
-+ * might see them, if they are in parts of the PCIe core that aren't
-+ * essential.
-+ */
-+ INFINIPATH_HWE_MSG(PCIE1PLLFAILED, "PCIePLL1"),
-+ INFINIPATH_HWE_MSG(PCIE0PLLFAILED, "PCIePLL0"),
-+ INFINIPATH_HWE_MSG(PCIEBUSPARITYXTLH, "PCIe XTLH core parity"),
-+ INFINIPATH_HWE_MSG(PCIEBUSPARITYXADM, "PCIe ADM TX core parity"),
-+ INFINIPATH_HWE_MSG(PCIEBUSPARITYRADM, "PCIe ADM RX core parity"),
-+ INFINIPATH_HWE_MSG(RXDSYNCMEMPARITYERR, "Rx Dsync"),
-+ INFINIPATH_HWE_MSG(SERDESPLLFAILED, "SerDes PLL"),
-+ INFINIPATH_HWE_MSG(PCIECPLDATAQUEUEERR, "PCIe cpl header queue"),
-+ INFINIPATH_HWE_MSG(PCIECPLHDRQUEUEERR, "PCIe cpl data queue"),
-+ INFINIPATH_HWE_MSG(SDMAMEMREADERR, "Send DMA memory read"),
-+ INFINIPATH_HWE_MSG(CLK_UC_PLLNOTLOCKED, "uC PLL clock not locked"),
-+ INFINIPATH_HWE_MSG(PCIESERDESQ0PCLKNOTDETECT,
-+ "PCIe serdes Q0 no clock"),
-+ INFINIPATH_HWE_MSG(PCIESERDESQ1PCLKNOTDETECT,
-+ "PCIe serdes Q1 no clock"),
-+ INFINIPATH_HWE_MSG(PCIESERDESQ2PCLKNOTDETECT,
-+ "PCIe serdes Q2 no clock"),
-+ INFINIPATH_HWE_MSG(PCIESERDESQ3PCLKNOTDETECT,
-+ "PCIe serdes Q3 no clock"),
-+ INFINIPATH_HWE_MSG(DDSRXEQMEMORYPARITYERR,
-+ "DDS RXEQ memory parity"),
-+ INFINIPATH_HWE_MSG(IB_UC_MEMORYPARITYERR, "IB uC memory parity"),
-+ INFINIPATH_HWE_MSG(PCIE_UC_OCT0MEMORYPARITYERR,
-+ "PCIe uC oct0 memory parity"),
-+ INFINIPATH_HWE_MSG(PCIE_UC_OCT1MEMORYPARITYERR,
-+ "PCIe uC oct1 memory parity"),
++struct tda18271_map {
++ u32 rfmax;
++ u8 val;
+};
+
-+static void autoneg_work(struct work_struct *);
++/*---------------------------------------------------------------------*/
+
-+/*
-+ * the offset is different for different configured port numbers, since
-+ * port0 is fixed in size, but others can vary. Make it a function to
-+ * make the issue more obvious.
-+*/
-+static inline u32 port_egrtid_idx(struct ipath_devdata *dd, unsigned port)
-+{
-+ return port ? dd->ipath_p0_rcvegrcnt +
-+ (port-1) * dd->ipath_rcvegrcnt : 0;
-+}
++static struct tda18271_pll_map tda18271c1_main_pll[] = {
++ { .lomax = 32000, .pd = 0x5f, .d = 0xf0 },
++ { .lomax = 35000, .pd = 0x5e, .d = 0xe0 },
++ { .lomax = 37000, .pd = 0x5d, .d = 0xd0 },
++ { .lomax = 41000, .pd = 0x5c, .d = 0xc0 },
++ { .lomax = 44000, .pd = 0x5b, .d = 0xb0 },
++ { .lomax = 49000, .pd = 0x5a, .d = 0xa0 },
++ { .lomax = 54000, .pd = 0x59, .d = 0x90 },
++ { .lomax = 61000, .pd = 0x58, .d = 0x80 },
++ { .lomax = 65000, .pd = 0x4f, .d = 0x78 },
++ { .lomax = 70000, .pd = 0x4e, .d = 0x70 },
++ { .lomax = 75000, .pd = 0x4d, .d = 0x68 },
++ { .lomax = 82000, .pd = 0x4c, .d = 0x60 },
++ { .lomax = 89000, .pd = 0x4b, .d = 0x58 },
++ { .lomax = 98000, .pd = 0x4a, .d = 0x50 },
++ { .lomax = 109000, .pd = 0x49, .d = 0x48 },
++ { .lomax = 123000, .pd = 0x48, .d = 0x40 },
++ { .lomax = 131000, .pd = 0x3f, .d = 0x3c },
++ { .lomax = 141000, .pd = 0x3e, .d = 0x38 },
++ { .lomax = 151000, .pd = 0x3d, .d = 0x34 },
++ { .lomax = 164000, .pd = 0x3c, .d = 0x30 },
++ { .lomax = 179000, .pd = 0x3b, .d = 0x2c },
++ { .lomax = 197000, .pd = 0x3a, .d = 0x28 },
++ { .lomax = 219000, .pd = 0x39, .d = 0x24 },
++ { .lomax = 246000, .pd = 0x38, .d = 0x20 },
++ { .lomax = 263000, .pd = 0x2f, .d = 0x1e },
++ { .lomax = 282000, .pd = 0x2e, .d = 0x1c },
++ { .lomax = 303000, .pd = 0x2d, .d = 0x1a },
++ { .lomax = 329000, .pd = 0x2c, .d = 0x18 },
++ { .lomax = 359000, .pd = 0x2b, .d = 0x16 },
++ { .lomax = 395000, .pd = 0x2a, .d = 0x14 },
++ { .lomax = 438000, .pd = 0x29, .d = 0x12 },
++ { .lomax = 493000, .pd = 0x28, .d = 0x10 },
++ { .lomax = 526000, .pd = 0x1f, .d = 0x0f },
++ { .lomax = 564000, .pd = 0x1e, .d = 0x0e },
++ { .lomax = 607000, .pd = 0x1d, .d = 0x0d },
++ { .lomax = 658000, .pd = 0x1c, .d = 0x0c },
++ { .lomax = 718000, .pd = 0x1b, .d = 0x0b },
++ { .lomax = 790000, .pd = 0x1a, .d = 0x0a },
++ { .lomax = 877000, .pd = 0x19, .d = 0x09 },
++ { .lomax = 987000, .pd = 0x18, .d = 0x08 },
++ { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */
++};
++
++static struct tda18271_pll_map tda18271c2_main_pll[] = {
++ { .lomax = 33125, .pd = 0x57, .d = 0xf0 },
++ { .lomax = 35500, .pd = 0x56, .d = 0xe0 },
++ { .lomax = 38188, .pd = 0x55, .d = 0xd0 },
++ { .lomax = 41375, .pd = 0x54, .d = 0xc0 },
++ { .lomax = 45125, .pd = 0x53, .d = 0xb0 },
++ { .lomax = 49688, .pd = 0x52, .d = 0xa0 },
++ { .lomax = 55188, .pd = 0x51, .d = 0x90 },
++ { .lomax = 62125, .pd = 0x50, .d = 0x80 },
++ { .lomax = 66250, .pd = 0x47, .d = 0x78 },
++ { .lomax = 71000, .pd = 0x46, .d = 0x70 },
++ { .lomax = 76375, .pd = 0x45, .d = 0x68 },
++ { .lomax = 82750, .pd = 0x44, .d = 0x60 },
++ { .lomax = 90250, .pd = 0x43, .d = 0x58 },
++ { .lomax = 99375, .pd = 0x42, .d = 0x50 },
++ { .lomax = 110375, .pd = 0x41, .d = 0x48 },
++ { .lomax = 124250, .pd = 0x40, .d = 0x40 },
++ { .lomax = 132500, .pd = 0x37, .d = 0x3c },
++ { .lomax = 142000, .pd = 0x36, .d = 0x38 },
++ { .lomax = 152750, .pd = 0x35, .d = 0x34 },
++ { .lomax = 165500, .pd = 0x34, .d = 0x30 },
++ { .lomax = 180500, .pd = 0x33, .d = 0x2c },
++ { .lomax = 198750, .pd = 0x32, .d = 0x28 },
++ { .lomax = 220750, .pd = 0x31, .d = 0x24 },
++ { .lomax = 248500, .pd = 0x30, .d = 0x20 },
++ { .lomax = 265000, .pd = 0x27, .d = 0x1e },
++ { .lomax = 284000, .pd = 0x26, .d = 0x1c },
++ { .lomax = 305500, .pd = 0x25, .d = 0x1a },
++ { .lomax = 331000, .pd = 0x24, .d = 0x18 },
++ { .lomax = 361000, .pd = 0x23, .d = 0x16 },
++ { .lomax = 397500, .pd = 0x22, .d = 0x14 },
++ { .lomax = 441500, .pd = 0x21, .d = 0x12 },
++ { .lomax = 497000, .pd = 0x20, .d = 0x10 },
++ { .lomax = 530000, .pd = 0x17, .d = 0x0f },
++ { .lomax = 568000, .pd = 0x16, .d = 0x0e },
++ { .lomax = 611000, .pd = 0x15, .d = 0x0d },
++ { .lomax = 662000, .pd = 0x14, .d = 0x0c },
++ { .lomax = 722000, .pd = 0x13, .d = 0x0b },
++ { .lomax = 795000, .pd = 0x12, .d = 0x0a },
++ { .lomax = 883000, .pd = 0x11, .d = 0x09 },
++ { .lomax = 994000, .pd = 0x10, .d = 0x08 },
++ { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */
++};
++
++static struct tda18271_pll_map tda18271c1_cal_pll[] = {
++ { .lomax = 33000, .pd = 0xdd, .d = 0xd0 },
++ { .lomax = 36000, .pd = 0xdc, .d = 0xc0 },
++ { .lomax = 40000, .pd = 0xdb, .d = 0xb0 },
++ { .lomax = 44000, .pd = 0xda, .d = 0xa0 },
++ { .lomax = 49000, .pd = 0xd9, .d = 0x90 },
++ { .lomax = 55000, .pd = 0xd8, .d = 0x80 },
++ { .lomax = 63000, .pd = 0xd3, .d = 0x70 },
++ { .lomax = 67000, .pd = 0xcd, .d = 0x68 },
++ { .lomax = 73000, .pd = 0xcc, .d = 0x60 },
++ { .lomax = 80000, .pd = 0xcb, .d = 0x58 },
++ { .lomax = 88000, .pd = 0xca, .d = 0x50 },
++ { .lomax = 98000, .pd = 0xc9, .d = 0x48 },
++ { .lomax = 110000, .pd = 0xc8, .d = 0x40 },
++ { .lomax = 126000, .pd = 0xc3, .d = 0x38 },
++ { .lomax = 135000, .pd = 0xbd, .d = 0x34 },
++ { .lomax = 147000, .pd = 0xbc, .d = 0x30 },
++ { .lomax = 160000, .pd = 0xbb, .d = 0x2c },
++ { .lomax = 176000, .pd = 0xba, .d = 0x28 },
++ { .lomax = 196000, .pd = 0xb9, .d = 0x24 },
++ { .lomax = 220000, .pd = 0xb8, .d = 0x20 },
++ { .lomax = 252000, .pd = 0xb3, .d = 0x1c },
++ { .lomax = 271000, .pd = 0xad, .d = 0x1a },
++ { .lomax = 294000, .pd = 0xac, .d = 0x18 },
++ { .lomax = 321000, .pd = 0xab, .d = 0x16 },
++ { .lomax = 353000, .pd = 0xaa, .d = 0x14 },
++ { .lomax = 392000, .pd = 0xa9, .d = 0x12 },
++ { .lomax = 441000, .pd = 0xa8, .d = 0x10 },
++ { .lomax = 505000, .pd = 0xa3, .d = 0x0e },
++ { .lomax = 543000, .pd = 0x9d, .d = 0x0d },
++ { .lomax = 589000, .pd = 0x9c, .d = 0x0c },
++ { .lomax = 642000, .pd = 0x9b, .d = 0x0b },
++ { .lomax = 707000, .pd = 0x9a, .d = 0x0a },
++ { .lomax = 785000, .pd = 0x99, .d = 0x09 },
++ { .lomax = 883000, .pd = 0x98, .d = 0x08 },
++ { .lomax = 1010000, .pd = 0x93, .d = 0x07 },
++ { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */
++};
++
++static struct tda18271_pll_map tda18271c2_cal_pll[] = {
++ { .lomax = 33813, .pd = 0xdd, .d = 0xd0 },
++ { .lomax = 36625, .pd = 0xdc, .d = 0xc0 },
++ { .lomax = 39938, .pd = 0xdb, .d = 0xb0 },
++ { .lomax = 43938, .pd = 0xda, .d = 0xa0 },
++ { .lomax = 48813, .pd = 0xd9, .d = 0x90 },
++ { .lomax = 54938, .pd = 0xd8, .d = 0x80 },
++ { .lomax = 62813, .pd = 0xd3, .d = 0x70 },
++ { .lomax = 67625, .pd = 0xcd, .d = 0x68 },
++ { .lomax = 73250, .pd = 0xcc, .d = 0x60 },
++ { .lomax = 79875, .pd = 0xcb, .d = 0x58 },
++ { .lomax = 87875, .pd = 0xca, .d = 0x50 },
++ { .lomax = 97625, .pd = 0xc9, .d = 0x48 },
++ { .lomax = 109875, .pd = 0xc8, .d = 0x40 },
++ { .lomax = 125625, .pd = 0xc3, .d = 0x38 },
++ { .lomax = 135250, .pd = 0xbd, .d = 0x34 },
++ { .lomax = 146500, .pd = 0xbc, .d = 0x30 },
++ { .lomax = 159750, .pd = 0xbb, .d = 0x2c },
++ { .lomax = 175750, .pd = 0xba, .d = 0x28 },
++ { .lomax = 195250, .pd = 0xb9, .d = 0x24 },
++ { .lomax = 219750, .pd = 0xb8, .d = 0x20 },
++ { .lomax = 251250, .pd = 0xb3, .d = 0x1c },
++ { .lomax = 270500, .pd = 0xad, .d = 0x1a },
++ { .lomax = 293000, .pd = 0xac, .d = 0x18 },
++ { .lomax = 319500, .pd = 0xab, .d = 0x16 },
++ { .lomax = 351500, .pd = 0xaa, .d = 0x14 },
++ { .lomax = 390500, .pd = 0xa9, .d = 0x12 },
++ { .lomax = 439500, .pd = 0xa8, .d = 0x10 },
++ { .lomax = 502500, .pd = 0xa3, .d = 0x0e },
++ { .lomax = 541000, .pd = 0x9d, .d = 0x0d },
++ { .lomax = 586000, .pd = 0x9c, .d = 0x0c },
++ { .lomax = 639000, .pd = 0x9b, .d = 0x0b },
++ { .lomax = 703000, .pd = 0x9a, .d = 0x0a },
++ { .lomax = 781000, .pd = 0x99, .d = 0x09 },
++ { .lomax = 879000, .pd = 0x98, .d = 0x08 },
++ { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */
++};
++
++static struct tda18271_map tda18271_bp_filter[] = {
++ { .rfmax = 62000, .val = 0x00 },
++ { .rfmax = 84000, .val = 0x01 },
++ { .rfmax = 100000, .val = 0x02 },
++ { .rfmax = 140000, .val = 0x03 },
++ { .rfmax = 170000, .val = 0x04 },
++ { .rfmax = 180000, .val = 0x05 },
++ { .rfmax = 865000, .val = 0x06 },
++ { .rfmax = 0, .val = 0x00 }, /* end */
++};
++
++static struct tda18271_map tda18271c1_km[] = {
++ { .rfmax = 61100, .val = 0x74 },
++ { .rfmax = 350000, .val = 0x40 },
++ { .rfmax = 720000, .val = 0x30 },
++ { .rfmax = 865000, .val = 0x40 },
++ { .rfmax = 0, .val = 0x00 }, /* end */
++};
++
++static struct tda18271_map tda18271c2_km[] = {
++ { .rfmax = 47900, .val = 0x38 },
++ { .rfmax = 61100, .val = 0x44 },
++ { .rfmax = 350000, .val = 0x30 },
++ { .rfmax = 720000, .val = 0x24 },
++ { .rfmax = 865000, .val = 0x3c },
++ { .rfmax = 0, .val = 0x00 }, /* end */
++};
++
++static struct tda18271_map tda18271_rf_band[] = {
++ { .rfmax = 47900, .val = 0x00 },
++ { .rfmax = 61100, .val = 0x01 },
++/* { .rfmax = 152600, .val = 0x02 }, */
++ { .rfmax = 121200, .val = 0x02 },
++ { .rfmax = 164700, .val = 0x03 },
++ { .rfmax = 203500, .val = 0x04 },
++ { .rfmax = 457800, .val = 0x05 },
++ { .rfmax = 865000, .val = 0x06 },
++ { .rfmax = 0, .val = 0x00 }, /* end */
++};
++
++static struct tda18271_map tda18271_gain_taper[] = {
++ { .rfmax = 45400, .val = 0x1f },
++ { .rfmax = 45800, .val = 0x1e },
++ { .rfmax = 46200, .val = 0x1d },
++ { .rfmax = 46700, .val = 0x1c },
++ { .rfmax = 47100, .val = 0x1b },
++ { .rfmax = 47500, .val = 0x1a },
++ { .rfmax = 47900, .val = 0x19 },
++ { .rfmax = 49600, .val = 0x17 },
++ { .rfmax = 51200, .val = 0x16 },
++ { .rfmax = 52900, .val = 0x15 },
++ { .rfmax = 54500, .val = 0x14 },
++ { .rfmax = 56200, .val = 0x13 },
++ { .rfmax = 57800, .val = 0x12 },
++ { .rfmax = 59500, .val = 0x11 },
++ { .rfmax = 61100, .val = 0x10 },
++ { .rfmax = 67600, .val = 0x0d },
++ { .rfmax = 74200, .val = 0x0c },
++ { .rfmax = 80700, .val = 0x0b },
++ { .rfmax = 87200, .val = 0x0a },
++ { .rfmax = 93800, .val = 0x09 },
++ { .rfmax = 100300, .val = 0x08 },
++ { .rfmax = 106900, .val = 0x07 },
++ { .rfmax = 113400, .val = 0x06 },
++ { .rfmax = 119900, .val = 0x05 },
++ { .rfmax = 126500, .val = 0x04 },
++ { .rfmax = 133000, .val = 0x03 },
++ { .rfmax = 139500, .val = 0x02 },
++ { .rfmax = 146100, .val = 0x01 },
++ { .rfmax = 152600, .val = 0x00 },
++ { .rfmax = 154300, .val = 0x1f },
++ { .rfmax = 156100, .val = 0x1e },
++ { .rfmax = 157800, .val = 0x1d },
++ { .rfmax = 159500, .val = 0x1c },
++ { .rfmax = 161200, .val = 0x1b },
++ { .rfmax = 163000, .val = 0x1a },
++ { .rfmax = 164700, .val = 0x19 },
++ { .rfmax = 170200, .val = 0x17 },
++ { .rfmax = 175800, .val = 0x16 },
++ { .rfmax = 181300, .val = 0x15 },
++ { .rfmax = 186900, .val = 0x14 },
++ { .rfmax = 192400, .val = 0x13 },
++ { .rfmax = 198000, .val = 0x12 },
++ { .rfmax = 203500, .val = 0x11 },
++ { .rfmax = 216200, .val = 0x14 },
++ { .rfmax = 228900, .val = 0x13 },
++ { .rfmax = 241600, .val = 0x12 },
++ { .rfmax = 254400, .val = 0x11 },
++ { .rfmax = 267100, .val = 0x10 },
++ { .rfmax = 279800, .val = 0x0f },
++ { .rfmax = 292500, .val = 0x0e },
++ { .rfmax = 305200, .val = 0x0d },
++ { .rfmax = 317900, .val = 0x0c },
++ { .rfmax = 330700, .val = 0x0b },
++ { .rfmax = 343400, .val = 0x0a },
++ { .rfmax = 356100, .val = 0x09 },
++ { .rfmax = 368800, .val = 0x08 },
++ { .rfmax = 381500, .val = 0x07 },
++ { .rfmax = 394200, .val = 0x06 },
++ { .rfmax = 406900, .val = 0x05 },
++ { .rfmax = 419700, .val = 0x04 },
++ { .rfmax = 432400, .val = 0x03 },
++ { .rfmax = 445100, .val = 0x02 },
++ { .rfmax = 457800, .val = 0x01 },
++ { .rfmax = 476300, .val = 0x19 },
++ { .rfmax = 494800, .val = 0x18 },
++ { .rfmax = 513300, .val = 0x17 },
++ { .rfmax = 531800, .val = 0x16 },
++ { .rfmax = 550300, .val = 0x15 },
++ { .rfmax = 568900, .val = 0x14 },
++ { .rfmax = 587400, .val = 0x13 },
++ { .rfmax = 605900, .val = 0x12 },
++ { .rfmax = 624400, .val = 0x11 },
++ { .rfmax = 642900, .val = 0x10 },
++ { .rfmax = 661400, .val = 0x0f },
++ { .rfmax = 679900, .val = 0x0e },
++ { .rfmax = 698400, .val = 0x0d },
++ { .rfmax = 716900, .val = 0x0c },
++ { .rfmax = 735400, .val = 0x0b },
++ { .rfmax = 753900, .val = 0x0a },
++ { .rfmax = 772500, .val = 0x09 },
++ { .rfmax = 791000, .val = 0x08 },
++ { .rfmax = 809500, .val = 0x07 },
++ { .rfmax = 828000, .val = 0x06 },
++ { .rfmax = 846500, .val = 0x05 },
++ { .rfmax = 865000, .val = 0x04 },
++ { .rfmax = 0, .val = 0x00 }, /* end */
++};
++
++static struct tda18271_map tda18271c1_rf_cal[] = {
++ { .rfmax = 41000, .val = 0x1e },
++ { .rfmax = 43000, .val = 0x30 },
++ { .rfmax = 45000, .val = 0x43 },
++ { .rfmax = 46000, .val = 0x4d },
++ { .rfmax = 47000, .val = 0x54 },
++ { .rfmax = 47900, .val = 0x64 },
++ { .rfmax = 49100, .val = 0x20 },
++ { .rfmax = 50000, .val = 0x22 },
++ { .rfmax = 51000, .val = 0x2a },
++ { .rfmax = 53000, .val = 0x32 },
++ { .rfmax = 55000, .val = 0x35 },
++ { .rfmax = 56000, .val = 0x3c },
++ { .rfmax = 57000, .val = 0x3f },
++ { .rfmax = 58000, .val = 0x48 },
++ { .rfmax = 59000, .val = 0x4d },
++ { .rfmax = 60000, .val = 0x58 },
++ { .rfmax = 61100, .val = 0x5f },
++ { .rfmax = 0, .val = 0x00 }, /* end */
++};
++
++static struct tda18271_map tda18271c2_rf_cal[] = {
++ { .rfmax = 41000, .val = 0x0f },
++ { .rfmax = 43000, .val = 0x1c },
++ { .rfmax = 45000, .val = 0x2f },
++ { .rfmax = 46000, .val = 0x39 },
++ { .rfmax = 47000, .val = 0x40 },
++ { .rfmax = 47900, .val = 0x50 },
++ { .rfmax = 49100, .val = 0x16 },
++ { .rfmax = 50000, .val = 0x18 },
++ { .rfmax = 51000, .val = 0x20 },
++ { .rfmax = 53000, .val = 0x28 },
++ { .rfmax = 55000, .val = 0x2b },
++ { .rfmax = 56000, .val = 0x32 },
++ { .rfmax = 57000, .val = 0x35 },
++ { .rfmax = 58000, .val = 0x3e },
++ { .rfmax = 59000, .val = 0x43 },
++ { .rfmax = 60000, .val = 0x4e },
++ { .rfmax = 61100, .val = 0x55 },
++ { .rfmax = 63000, .val = 0x0f },
++ { .rfmax = 64000, .val = 0x11 },
++ { .rfmax = 65000, .val = 0x12 },
++ { .rfmax = 66000, .val = 0x15 },
++ { .rfmax = 67000, .val = 0x16 },
++ { .rfmax = 68000, .val = 0x17 },
++ { .rfmax = 70000, .val = 0x19 },
++ { .rfmax = 71000, .val = 0x1c },
++ { .rfmax = 72000, .val = 0x1d },
++ { .rfmax = 73000, .val = 0x1f },
++ { .rfmax = 74000, .val = 0x20 },
++ { .rfmax = 75000, .val = 0x21 },
++ { .rfmax = 76000, .val = 0x24 },
++ { .rfmax = 77000, .val = 0x25 },
++ { .rfmax = 78000, .val = 0x27 },
++ { .rfmax = 80000, .val = 0x28 },
++ { .rfmax = 81000, .val = 0x29 },
++ { .rfmax = 82000, .val = 0x2d },
++ { .rfmax = 83000, .val = 0x2e },
++ { .rfmax = 84000, .val = 0x2f },
++ { .rfmax = 85000, .val = 0x31 },
++ { .rfmax = 86000, .val = 0x33 },
++ { .rfmax = 87000, .val = 0x34 },
++ { .rfmax = 88000, .val = 0x35 },
++ { .rfmax = 89000, .val = 0x37 },
++ { .rfmax = 90000, .val = 0x38 },
++ { .rfmax = 91000, .val = 0x39 },
++ { .rfmax = 93000, .val = 0x3c },
++ { .rfmax = 94000, .val = 0x3e },
++ { .rfmax = 95000, .val = 0x3f },
++ { .rfmax = 96000, .val = 0x40 },
++ { .rfmax = 97000, .val = 0x42 },
++ { .rfmax = 99000, .val = 0x45 },
++ { .rfmax = 100000, .val = 0x46 },
++ { .rfmax = 102000, .val = 0x48 },
++ { .rfmax = 103000, .val = 0x4a },
++ { .rfmax = 105000, .val = 0x4d },
++ { .rfmax = 106000, .val = 0x4e },
++ { .rfmax = 107000, .val = 0x50 },
++ { .rfmax = 108000, .val = 0x51 },
++ { .rfmax = 110000, .val = 0x54 },
++ { .rfmax = 111000, .val = 0x56 },
++ { .rfmax = 112000, .val = 0x57 },
++ { .rfmax = 113000, .val = 0x58 },
++ { .rfmax = 114000, .val = 0x59 },
++ { .rfmax = 115000, .val = 0x5c },
++ { .rfmax = 116000, .val = 0x5d },
++ { .rfmax = 117000, .val = 0x5f },
++ { .rfmax = 119000, .val = 0x60 },
++ { .rfmax = 120000, .val = 0x64 },
++ { .rfmax = 121000, .val = 0x65 },
++ { .rfmax = 122000, .val = 0x66 },
++ { .rfmax = 123000, .val = 0x68 },
++ { .rfmax = 124000, .val = 0x69 },
++ { .rfmax = 125000, .val = 0x6c },
++ { .rfmax = 126000, .val = 0x6d },
++ { .rfmax = 127000, .val = 0x6e },
++ { .rfmax = 128000, .val = 0x70 },
++ { .rfmax = 129000, .val = 0x71 },
++ { .rfmax = 130000, .val = 0x75 },
++ { .rfmax = 131000, .val = 0x77 },
++ { .rfmax = 132000, .val = 0x78 },
++ { .rfmax = 133000, .val = 0x7b },
++ { .rfmax = 134000, .val = 0x7e },
++ { .rfmax = 135000, .val = 0x81 },
++ { .rfmax = 136000, .val = 0x82 },
++ { .rfmax = 137000, .val = 0x87 },
++ { .rfmax = 138000, .val = 0x88 },
++ { .rfmax = 139000, .val = 0x8d },
++ { .rfmax = 140000, .val = 0x8e },
++ { .rfmax = 141000, .val = 0x91 },
++ { .rfmax = 142000, .val = 0x95 },
++ { .rfmax = 143000, .val = 0x9a },
++ { .rfmax = 144000, .val = 0x9d },
++ { .rfmax = 145000, .val = 0xa1 },
++ { .rfmax = 146000, .val = 0xa2 },
++ { .rfmax = 147000, .val = 0xa4 },
++ { .rfmax = 148000, .val = 0xa9 },
++ { .rfmax = 149000, .val = 0xae },
++ { .rfmax = 150000, .val = 0xb0 },
++ { .rfmax = 151000, .val = 0xb1 },
++ { .rfmax = 152000, .val = 0xb7 },
++ { .rfmax = 153000, .val = 0xbd },
++ { .rfmax = 154000, .val = 0x20 },
++ { .rfmax = 155000, .val = 0x22 },
++ { .rfmax = 156000, .val = 0x24 },
++ { .rfmax = 157000, .val = 0x25 },
++ { .rfmax = 158000, .val = 0x27 },
++ { .rfmax = 159000, .val = 0x29 },
++ { .rfmax = 160000, .val = 0x2c },
++ { .rfmax = 161000, .val = 0x2d },
++ { .rfmax = 163000, .val = 0x2e },
++ { .rfmax = 164000, .val = 0x2f },
++ { .rfmax = 165000, .val = 0x30 },
++ { .rfmax = 166000, .val = 0x11 },
++ { .rfmax = 167000, .val = 0x12 },
++ { .rfmax = 168000, .val = 0x13 },
++ { .rfmax = 169000, .val = 0x14 },
++ { .rfmax = 170000, .val = 0x15 },
++ { .rfmax = 172000, .val = 0x16 },
++ { .rfmax = 173000, .val = 0x17 },
++ { .rfmax = 174000, .val = 0x18 },
++ { .rfmax = 175000, .val = 0x1a },
++ { .rfmax = 176000, .val = 0x1b },
++ { .rfmax = 178000, .val = 0x1d },
++ { .rfmax = 179000, .val = 0x1e },
++ { .rfmax = 180000, .val = 0x1f },
++ { .rfmax = 181000, .val = 0x20 },
++ { .rfmax = 182000, .val = 0x21 },
++ { .rfmax = 183000, .val = 0x22 },
++ { .rfmax = 184000, .val = 0x24 },
++ { .rfmax = 185000, .val = 0x25 },
++ { .rfmax = 186000, .val = 0x26 },
++ { .rfmax = 187000, .val = 0x27 },
++ { .rfmax = 188000, .val = 0x29 },
++ { .rfmax = 189000, .val = 0x2a },
++ { .rfmax = 190000, .val = 0x2c },
++ { .rfmax = 191000, .val = 0x2d },
++ { .rfmax = 192000, .val = 0x2e },
++ { .rfmax = 193000, .val = 0x2f },
++ { .rfmax = 194000, .val = 0x30 },
++ { .rfmax = 195000, .val = 0x33 },
++ { .rfmax = 196000, .val = 0x35 },
++ { .rfmax = 198000, .val = 0x36 },
++ { .rfmax = 200000, .val = 0x38 },
++ { .rfmax = 201000, .val = 0x3c },
++ { .rfmax = 202000, .val = 0x3d },
++ { .rfmax = 203500, .val = 0x3e },
++ { .rfmax = 206000, .val = 0x0e },
++ { .rfmax = 208000, .val = 0x0f },
++ { .rfmax = 212000, .val = 0x10 },
++ { .rfmax = 216000, .val = 0x11 },
++ { .rfmax = 217000, .val = 0x12 },
++ { .rfmax = 218000, .val = 0x13 },
++ { .rfmax = 220000, .val = 0x14 },
++ { .rfmax = 222000, .val = 0x15 },
++ { .rfmax = 225000, .val = 0x16 },
++ { .rfmax = 228000, .val = 0x17 },
++ { .rfmax = 231000, .val = 0x18 },
++ { .rfmax = 234000, .val = 0x19 },
++ { .rfmax = 235000, .val = 0x1a },
++ { .rfmax = 236000, .val = 0x1b },
++ { .rfmax = 237000, .val = 0x1c },
++ { .rfmax = 240000, .val = 0x1d },
++ { .rfmax = 242000, .val = 0x1f },
++ { .rfmax = 247000, .val = 0x20 },
++ { .rfmax = 249000, .val = 0x21 },
++ { .rfmax = 252000, .val = 0x22 },
++ { .rfmax = 253000, .val = 0x23 },
++ { .rfmax = 254000, .val = 0x24 },
++ { .rfmax = 256000, .val = 0x25 },
++ { .rfmax = 259000, .val = 0x26 },
++ { .rfmax = 262000, .val = 0x27 },
++ { .rfmax = 264000, .val = 0x28 },
++ { .rfmax = 267000, .val = 0x29 },
++ { .rfmax = 269000, .val = 0x2a },
++ { .rfmax = 271000, .val = 0x2b },
++ { .rfmax = 273000, .val = 0x2c },
++ { .rfmax = 275000, .val = 0x2d },
++ { .rfmax = 277000, .val = 0x2e },
++ { .rfmax = 279000, .val = 0x2f },
++ { .rfmax = 282000, .val = 0x30 },
++ { .rfmax = 284000, .val = 0x31 },
++ { .rfmax = 286000, .val = 0x32 },
++ { .rfmax = 287000, .val = 0x33 },
++ { .rfmax = 290000, .val = 0x34 },
++ { .rfmax = 293000, .val = 0x35 },
++ { .rfmax = 295000, .val = 0x36 },
++ { .rfmax = 297000, .val = 0x37 },
++ { .rfmax = 300000, .val = 0x38 },
++ { .rfmax = 303000, .val = 0x39 },
++ { .rfmax = 305000, .val = 0x3a },
++ { .rfmax = 306000, .val = 0x3b },
++ { .rfmax = 307000, .val = 0x3c },
++ { .rfmax = 310000, .val = 0x3d },
++ { .rfmax = 312000, .val = 0x3e },
++ { .rfmax = 315000, .val = 0x3f },
++ { .rfmax = 318000, .val = 0x40 },
++ { .rfmax = 320000, .val = 0x41 },
++ { .rfmax = 323000, .val = 0x42 },
++ { .rfmax = 324000, .val = 0x43 },
++ { .rfmax = 325000, .val = 0x44 },
++ { .rfmax = 327000, .val = 0x45 },
++ { .rfmax = 331000, .val = 0x46 },
++ { .rfmax = 334000, .val = 0x47 },
++ { .rfmax = 337000, .val = 0x48 },
++ { .rfmax = 339000, .val = 0x49 },
++ { .rfmax = 340000, .val = 0x4a },
++ { .rfmax = 341000, .val = 0x4b },
++ { .rfmax = 343000, .val = 0x4c },
++ { .rfmax = 345000, .val = 0x4d },
++ { .rfmax = 349000, .val = 0x4e },
++ { .rfmax = 352000, .val = 0x4f },
++ { .rfmax = 353000, .val = 0x50 },
++ { .rfmax = 355000, .val = 0x51 },
++ { .rfmax = 357000, .val = 0x52 },
++ { .rfmax = 359000, .val = 0x53 },
++ { .rfmax = 361000, .val = 0x54 },
++ { .rfmax = 362000, .val = 0x55 },
++ { .rfmax = 364000, .val = 0x56 },
++ { .rfmax = 368000, .val = 0x57 },
++ { .rfmax = 370000, .val = 0x58 },
++ { .rfmax = 372000, .val = 0x59 },
++ { .rfmax = 375000, .val = 0x5a },
++ { .rfmax = 376000, .val = 0x5b },
++ { .rfmax = 377000, .val = 0x5c },
++ { .rfmax = 379000, .val = 0x5d },
++ { .rfmax = 382000, .val = 0x5e },
++ { .rfmax = 384000, .val = 0x5f },
++ { .rfmax = 385000, .val = 0x60 },
++ { .rfmax = 386000, .val = 0x61 },
++ { .rfmax = 388000, .val = 0x62 },
++ { .rfmax = 390000, .val = 0x63 },
++ { .rfmax = 393000, .val = 0x64 },
++ { .rfmax = 394000, .val = 0x65 },
++ { .rfmax = 396000, .val = 0x66 },
++ { .rfmax = 397000, .val = 0x67 },
++ { .rfmax = 398000, .val = 0x68 },
++ { .rfmax = 400000, .val = 0x69 },
++ { .rfmax = 402000, .val = 0x6a },
++ { .rfmax = 403000, .val = 0x6b },
++ { .rfmax = 407000, .val = 0x6c },
++ { .rfmax = 408000, .val = 0x6d },
++ { .rfmax = 409000, .val = 0x6e },
++ { .rfmax = 410000, .val = 0x6f },
++ { .rfmax = 411000, .val = 0x70 },
++ { .rfmax = 412000, .val = 0x71 },
++ { .rfmax = 413000, .val = 0x72 },
++ { .rfmax = 414000, .val = 0x73 },
++ { .rfmax = 417000, .val = 0x74 },
++ { .rfmax = 418000, .val = 0x75 },
++ { .rfmax = 420000, .val = 0x76 },
++ { .rfmax = 422000, .val = 0x77 },
++ { .rfmax = 423000, .val = 0x78 },
++ { .rfmax = 424000, .val = 0x79 },
++ { .rfmax = 427000, .val = 0x7a },
++ { .rfmax = 428000, .val = 0x7b },
++ { .rfmax = 429000, .val = 0x7d },
++ { .rfmax = 432000, .val = 0x7f },
++ { .rfmax = 434000, .val = 0x80 },
++ { .rfmax = 435000, .val = 0x81 },
++ { .rfmax = 436000, .val = 0x83 },
++ { .rfmax = 437000, .val = 0x84 },
++ { .rfmax = 438000, .val = 0x85 },
++ { .rfmax = 439000, .val = 0x86 },
++ { .rfmax = 440000, .val = 0x87 },
++ { .rfmax = 441000, .val = 0x88 },
++ { .rfmax = 442000, .val = 0x89 },
++ { .rfmax = 445000, .val = 0x8a },
++ { .rfmax = 446000, .val = 0x8b },
++ { .rfmax = 447000, .val = 0x8c },
++ { .rfmax = 448000, .val = 0x8e },
++ { .rfmax = 449000, .val = 0x8f },
++ { .rfmax = 450000, .val = 0x90 },
++ { .rfmax = 452000, .val = 0x91 },
++ { .rfmax = 453000, .val = 0x93 },
++ { .rfmax = 454000, .val = 0x94 },
++ { .rfmax = 456000, .val = 0x96 },
++ { .rfmax = 457000, .val = 0x98 },
++ { .rfmax = 461000, .val = 0x11 },
++ { .rfmax = 468000, .val = 0x12 },
++ { .rfmax = 472000, .val = 0x13 },
++ { .rfmax = 473000, .val = 0x14 },
++ { .rfmax = 474000, .val = 0x15 },
++ { .rfmax = 481000, .val = 0x16 },
++ { .rfmax = 486000, .val = 0x17 },
++ { .rfmax = 491000, .val = 0x18 },
++ { .rfmax = 498000, .val = 0x19 },
++ { .rfmax = 499000, .val = 0x1a },
++ { .rfmax = 501000, .val = 0x1b },
++ { .rfmax = 506000, .val = 0x1c },
++ { .rfmax = 511000, .val = 0x1d },
++ { .rfmax = 516000, .val = 0x1e },
++ { .rfmax = 520000, .val = 0x1f },
++ { .rfmax = 521000, .val = 0x20 },
++ { .rfmax = 525000, .val = 0x21 },
++ { .rfmax = 529000, .val = 0x22 },
++ { .rfmax = 533000, .val = 0x23 },
++ { .rfmax = 539000, .val = 0x24 },
++ { .rfmax = 541000, .val = 0x25 },
++ { .rfmax = 547000, .val = 0x26 },
++ { .rfmax = 549000, .val = 0x27 },
++ { .rfmax = 551000, .val = 0x28 },
++ { .rfmax = 556000, .val = 0x29 },
++ { .rfmax = 561000, .val = 0x2a },
++ { .rfmax = 563000, .val = 0x2b },
++ { .rfmax = 565000, .val = 0x2c },
++ { .rfmax = 569000, .val = 0x2d },
++ { .rfmax = 571000, .val = 0x2e },
++ { .rfmax = 577000, .val = 0x2f },
++ { .rfmax = 580000, .val = 0x30 },
++ { .rfmax = 582000, .val = 0x31 },
++ { .rfmax = 584000, .val = 0x32 },
++ { .rfmax = 588000, .val = 0x33 },
++ { .rfmax = 591000, .val = 0x34 },
++ { .rfmax = 596000, .val = 0x35 },
++ { .rfmax = 598000, .val = 0x36 },
++ { .rfmax = 603000, .val = 0x37 },
++ { .rfmax = 604000, .val = 0x38 },
++ { .rfmax = 606000, .val = 0x39 },
++ { .rfmax = 612000, .val = 0x3a },
++ { .rfmax = 615000, .val = 0x3b },
++ { .rfmax = 617000, .val = 0x3c },
++ { .rfmax = 621000, .val = 0x3d },
++ { .rfmax = 622000, .val = 0x3e },
++ { .rfmax = 625000, .val = 0x3f },
++ { .rfmax = 632000, .val = 0x40 },
++ { .rfmax = 633000, .val = 0x41 },
++ { .rfmax = 634000, .val = 0x42 },
++ { .rfmax = 642000, .val = 0x43 },
++ { .rfmax = 643000, .val = 0x44 },
++ { .rfmax = 647000, .val = 0x45 },
++ { .rfmax = 650000, .val = 0x46 },
++ { .rfmax = 652000, .val = 0x47 },
++ { .rfmax = 657000, .val = 0x48 },
++ { .rfmax = 661000, .val = 0x49 },
++ { .rfmax = 662000, .val = 0x4a },
++ { .rfmax = 665000, .val = 0x4b },
++ { .rfmax = 667000, .val = 0x4c },
++ { .rfmax = 670000, .val = 0x4d },
++ { .rfmax = 673000, .val = 0x4e },
++ { .rfmax = 676000, .val = 0x4f },
++ { .rfmax = 677000, .val = 0x50 },
++ { .rfmax = 681000, .val = 0x51 },
++ { .rfmax = 683000, .val = 0x52 },
++ { .rfmax = 686000, .val = 0x53 },
++ { .rfmax = 688000, .val = 0x54 },
++ { .rfmax = 689000, .val = 0x55 },
++ { .rfmax = 691000, .val = 0x56 },
++ { .rfmax = 695000, .val = 0x57 },
++ { .rfmax = 698000, .val = 0x58 },
++ { .rfmax = 703000, .val = 0x59 },
++ { .rfmax = 704000, .val = 0x5a },
++ { .rfmax = 705000, .val = 0x5b },
++ { .rfmax = 707000, .val = 0x5c },
++ { .rfmax = 710000, .val = 0x5d },
++ { .rfmax = 712000, .val = 0x5e },
++ { .rfmax = 717000, .val = 0x5f },
++ { .rfmax = 718000, .val = 0x60 },
++ { .rfmax = 721000, .val = 0x61 },
++ { .rfmax = 722000, .val = 0x62 },
++ { .rfmax = 723000, .val = 0x63 },
++ { .rfmax = 725000, .val = 0x64 },
++ { .rfmax = 727000, .val = 0x65 },
++ { .rfmax = 730000, .val = 0x66 },
++ { .rfmax = 732000, .val = 0x67 },
++ { .rfmax = 735000, .val = 0x68 },
++ { .rfmax = 740000, .val = 0x69 },
++ { .rfmax = 741000, .val = 0x6a },
++ { .rfmax = 742000, .val = 0x6b },
++ { .rfmax = 743000, .val = 0x6c },
++ { .rfmax = 745000, .val = 0x6d },
++ { .rfmax = 747000, .val = 0x6e },
++ { .rfmax = 748000, .val = 0x6f },
++ { .rfmax = 750000, .val = 0x70 },
++ { .rfmax = 752000, .val = 0x71 },
++ { .rfmax = 754000, .val = 0x72 },
++ { .rfmax = 757000, .val = 0x73 },
++ { .rfmax = 758000, .val = 0x74 },
++ { .rfmax = 760000, .val = 0x75 },
++ { .rfmax = 763000, .val = 0x76 },
++ { .rfmax = 764000, .val = 0x77 },
++ { .rfmax = 766000, .val = 0x78 },
++ { .rfmax = 767000, .val = 0x79 },
++ { .rfmax = 768000, .val = 0x7a },
++ { .rfmax = 773000, .val = 0x7b },
++ { .rfmax = 774000, .val = 0x7c },
++ { .rfmax = 776000, .val = 0x7d },
++ { .rfmax = 777000, .val = 0x7e },
++ { .rfmax = 778000, .val = 0x7f },
++ { .rfmax = 779000, .val = 0x80 },
++ { .rfmax = 781000, .val = 0x81 },
++ { .rfmax = 783000, .val = 0x82 },
++ { .rfmax = 784000, .val = 0x83 },
++ { .rfmax = 785000, .val = 0x84 },
++ { .rfmax = 786000, .val = 0x85 },
++ { .rfmax = 793000, .val = 0x86 },
++ { .rfmax = 794000, .val = 0x87 },
++ { .rfmax = 795000, .val = 0x88 },
++ { .rfmax = 797000, .val = 0x89 },
++ { .rfmax = 799000, .val = 0x8a },
++ { .rfmax = 801000, .val = 0x8b },
++ { .rfmax = 802000, .val = 0x8c },
++ { .rfmax = 803000, .val = 0x8d },
++ { .rfmax = 804000, .val = 0x8e },
++ { .rfmax = 810000, .val = 0x90 },
++ { .rfmax = 811000, .val = 0x91 },
++ { .rfmax = 812000, .val = 0x92 },
++ { .rfmax = 814000, .val = 0x93 },
++ { .rfmax = 816000, .val = 0x94 },
++ { .rfmax = 817000, .val = 0x96 },
++ { .rfmax = 818000, .val = 0x97 },
++ { .rfmax = 820000, .val = 0x98 },
++ { .rfmax = 821000, .val = 0x99 },
++ { .rfmax = 822000, .val = 0x9a },
++ { .rfmax = 828000, .val = 0x9b },
++ { .rfmax = 829000, .val = 0x9d },
++ { .rfmax = 830000, .val = 0x9f },
++ { .rfmax = 831000, .val = 0xa0 },
++ { .rfmax = 833000, .val = 0xa1 },
++ { .rfmax = 835000, .val = 0xa2 },
++ { .rfmax = 836000, .val = 0xa3 },
++ { .rfmax = 837000, .val = 0xa4 },
++ { .rfmax = 838000, .val = 0xa6 },
++ { .rfmax = 840000, .val = 0xa8 },
++ { .rfmax = 842000, .val = 0xa9 },
++ { .rfmax = 845000, .val = 0xaa },
++ { .rfmax = 846000, .val = 0xab },
++ { .rfmax = 847000, .val = 0xad },
++ { .rfmax = 848000, .val = 0xae },
++ { .rfmax = 852000, .val = 0xaf },
++ { .rfmax = 853000, .val = 0xb0 },
++ { .rfmax = 858000, .val = 0xb1 },
++ { .rfmax = 860000, .val = 0xb2 },
++ { .rfmax = 861000, .val = 0xb3 },
++ { .rfmax = 862000, .val = 0xb4 },
++ { .rfmax = 863000, .val = 0xb6 },
++ { .rfmax = 864000, .val = 0xb8 },
++ { .rfmax = 865000, .val = 0xb9 },
++ { .rfmax = 0, .val = 0x00 }, /* end */
++};
++
++static struct tda18271_map tda18271_ir_measure[] = {
++ { .rfmax = 30000, .val = 4 },
++ { .rfmax = 200000, .val = 5 },
++ { .rfmax = 600000, .val = 6 },
++ { .rfmax = 865000, .val = 7 },
++ { .rfmax = 0, .val = 0 }, /* end */
++};
++
++static struct tda18271_map tda18271_rf_cal_dc_over_dt[] = {
++ { .rfmax = 47900, .val = 0x00 },
++ { .rfmax = 55000, .val = 0x00 },
++ { .rfmax = 61100, .val = 0x0a },
++ { .rfmax = 64000, .val = 0x0a },
++ { .rfmax = 82000, .val = 0x14 },
++ { .rfmax = 84000, .val = 0x19 },
++ { .rfmax = 119000, .val = 0x1c },
++ { .rfmax = 124000, .val = 0x20 },
++ { .rfmax = 129000, .val = 0x2a },
++ { .rfmax = 134000, .val = 0x32 },
++ { .rfmax = 139000, .val = 0x39 },
++ { .rfmax = 144000, .val = 0x3e },
++ { .rfmax = 149000, .val = 0x3f },
++ { .rfmax = 152600, .val = 0x40 },
++ { .rfmax = 154000, .val = 0x40 },
++ { .rfmax = 164700, .val = 0x41 },
++ { .rfmax = 203500, .val = 0x32 },
++ { .rfmax = 353000, .val = 0x19 },
++ { .rfmax = 356000, .val = 0x1a },
++ { .rfmax = 359000, .val = 0x1b },
++ { .rfmax = 363000, .val = 0x1c },
++ { .rfmax = 366000, .val = 0x1d },
++ { .rfmax = 369000, .val = 0x1e },
++ { .rfmax = 373000, .val = 0x1f },
++ { .rfmax = 376000, .val = 0x20 },
++ { .rfmax = 379000, .val = 0x21 },
++ { .rfmax = 383000, .val = 0x22 },
++ { .rfmax = 386000, .val = 0x23 },
++ { .rfmax = 389000, .val = 0x24 },
++ { .rfmax = 393000, .val = 0x25 },
++ { .rfmax = 396000, .val = 0x26 },
++ { .rfmax = 399000, .val = 0x27 },
++ { .rfmax = 402000, .val = 0x28 },
++ { .rfmax = 404000, .val = 0x29 },
++ { .rfmax = 407000, .val = 0x2a },
++ { .rfmax = 409000, .val = 0x2b },
++ { .rfmax = 412000, .val = 0x2c },
++ { .rfmax = 414000, .val = 0x2d },
++ { .rfmax = 417000, .val = 0x2e },
++ { .rfmax = 419000, .val = 0x2f },
++ { .rfmax = 422000, .val = 0x30 },
++ { .rfmax = 424000, .val = 0x31 },
++ { .rfmax = 427000, .val = 0x32 },
++ { .rfmax = 429000, .val = 0x33 },
++ { .rfmax = 432000, .val = 0x34 },
++ { .rfmax = 434000, .val = 0x35 },
++ { .rfmax = 437000, .val = 0x36 },
++ { .rfmax = 439000, .val = 0x37 },
++ { .rfmax = 442000, .val = 0x38 },
++ { .rfmax = 444000, .val = 0x39 },
++ { .rfmax = 447000, .val = 0x3a },
++ { .rfmax = 449000, .val = 0x3b },
++ { .rfmax = 457800, .val = 0x3c },
++ { .rfmax = 465000, .val = 0x0f },
++ { .rfmax = 477000, .val = 0x12 },
++ { .rfmax = 483000, .val = 0x14 },
++ { .rfmax = 502000, .val = 0x19 },
++ { .rfmax = 508000, .val = 0x1b },
++ { .rfmax = 519000, .val = 0x1c },
++ { .rfmax = 522000, .val = 0x1d },
++ { .rfmax = 524000, .val = 0x1e },
++ { .rfmax = 534000, .val = 0x1f },
++ { .rfmax = 549000, .val = 0x20 },
++ { .rfmax = 554000, .val = 0x22 },
++ { .rfmax = 584000, .val = 0x24 },
++ { .rfmax = 589000, .val = 0x26 },
++ { .rfmax = 658000, .val = 0x27 },
++ { .rfmax = 664000, .val = 0x2c },
++ { .rfmax = 669000, .val = 0x2d },
++ { .rfmax = 699000, .val = 0x2e },
++ { .rfmax = 704000, .val = 0x30 },
++ { .rfmax = 709000, .val = 0x31 },
++ { .rfmax = 714000, .val = 0x32 },
++ { .rfmax = 724000, .val = 0x33 },
++ { .rfmax = 729000, .val = 0x36 },
++ { .rfmax = 739000, .val = 0x38 },
++ { .rfmax = 744000, .val = 0x39 },
++ { .rfmax = 749000, .val = 0x3b },
++ { .rfmax = 754000, .val = 0x3c },
++ { .rfmax = 759000, .val = 0x3d },
++ { .rfmax = 764000, .val = 0x3e },
++ { .rfmax = 769000, .val = 0x3f },
++ { .rfmax = 774000, .val = 0x40 },
++ { .rfmax = 779000, .val = 0x41 },
++ { .rfmax = 784000, .val = 0x43 },
++ { .rfmax = 789000, .val = 0x46 },
++ { .rfmax = 794000, .val = 0x48 },
++ { .rfmax = 799000, .val = 0x4b },
++ { .rfmax = 804000, .val = 0x4f },
++ { .rfmax = 809000, .val = 0x54 },
++ { .rfmax = 814000, .val = 0x59 },
++ { .rfmax = 819000, .val = 0x5d },
++ { .rfmax = 824000, .val = 0x61 },
++ { .rfmax = 829000, .val = 0x68 },
++ { .rfmax = 834000, .val = 0x6e },
++ { .rfmax = 839000, .val = 0x75 },
++ { .rfmax = 844000, .val = 0x7e },
++ { .rfmax = 849000, .val = 0x82 },
++ { .rfmax = 854000, .val = 0x84 },
++ { .rfmax = 859000, .val = 0x8f },
++ { .rfmax = 865000, .val = 0x9a },
++ { .rfmax = 0, .val = 0x00 }, /* end */
++};
+
-+static void ipath_7220_txe_recover(struct ipath_devdata *dd)
++/*---------------------------------------------------------------------*/
++
++struct tda18271_thermo_map {
++ u8 d;
++ u8 r0;
++ u8 r1;
++};
++
++static struct tda18271_thermo_map tda18271_thermometer[] = {
++ { .d = 0x00, .r0 = 60, .r1 = 92 },
++ { .d = 0x01, .r0 = 62, .r1 = 94 },
++ { .d = 0x02, .r0 = 66, .r1 = 98 },
++ { .d = 0x03, .r0 = 64, .r1 = 96 },
++ { .d = 0x04, .r0 = 74, .r1 = 106 },
++ { .d = 0x05, .r0 = 72, .r1 = 104 },
++ { .d = 0x06, .r0 = 68, .r1 = 100 },
++ { .d = 0x07, .r0 = 70, .r1 = 102 },
++ { .d = 0x08, .r0 = 90, .r1 = 122 },
++ { .d = 0x09, .r0 = 88, .r1 = 120 },
++ { .d = 0x0a, .r0 = 84, .r1 = 116 },
++ { .d = 0x0b, .r0 = 86, .r1 = 118 },
++ { .d = 0x0c, .r0 = 76, .r1 = 108 },
++ { .d = 0x0d, .r0 = 78, .r1 = 110 },
++ { .d = 0x0e, .r0 = 82, .r1 = 114 },
++ { .d = 0x0f, .r0 = 80, .r1 = 112 },
++ { .d = 0x00, .r0 = 0, .r1 = 0 }, /* end */
++};
++
++int tda18271_lookup_thermometer(struct dvb_frontend *fe)
+{
-+ ++ipath_stats.sps_txeparity;
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
++ int val, i = 0;
+
-+ dev_info(&dd->pcidev->dev,
-+ "Recovering from TXE PIO parity error\n");
-+ ipath_disarm_senderrbufs(dd, 1);
++ while (tda18271_thermometer[i].d < (regs[R_TM] & 0x0f)) {
++ if (tda18271_thermometer[i + 1].d == 0)
++ break;
++ i++;
++ }
++
++ if ((regs[R_TM] & 0x20) == 0x20)
++ val = tda18271_thermometer[i].r1;
++ else
++ val = tda18271_thermometer[i].r0;
++
++ tda_map("(%d) tm = %d\n", i, val);
++
++ return val;
+}
+
++/*---------------------------------------------------------------------*/
++
++struct tda18271_cid_target_map {
++ u32 rfmax;
++ u8 target;
++ u16 limit;
++};
++
++static struct tda18271_cid_target_map tda18271_cid_target[] = {
++ { .rfmax = 46000, .target = 0x04, .limit = 1800 },
++ { .rfmax = 52200, .target = 0x0a, .limit = 1500 },
++ { .rfmax = 79100, .target = 0x01, .limit = 4000 },
++ { .rfmax = 136800, .target = 0x18, .limit = 4000 },
++ { .rfmax = 156700, .target = 0x18, .limit = 4000 },
++ { .rfmax = 156700, .target = 0x18, .limit = 4000 },
++ { .rfmax = 186250, .target = 0x0a, .limit = 4000 },
++ { .rfmax = 230000, .target = 0x0a, .limit = 4000 },
++ { .rfmax = 345000, .target = 0x18, .limit = 4000 },
++ { .rfmax = 426000, .target = 0x0e, .limit = 4000 },
++ { .rfmax = 489500, .target = 0x1e, .limit = 4000 },
++ { .rfmax = 697500, .target = 0x32, .limit = 4000 },
++ { .rfmax = 842000, .target = 0x3a, .limit = 4000 },
++ { .rfmax = 0, .target = 0x00, .limit = 0 }, /* end */
++};
+
-+/**
-+ * 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)
++int tda18271_lookup_cid_target(struct dvb_frontend *fe,
++ u32 *freq, u8 *cid_target, u16 *count_limit)
+{
-+ ipath_err_t hwerrs;
-+ u32 bits, ctrl;
-+ int isfatal = 0;
-+ char bitsmsg[64];
-+ int log_idx;
++ int i = 0;
+
-+ 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;
++ while ((tda18271_cid_target[i].rfmax * 1000) < *freq) {
++ if (tda18271_cid_target[i + 1].rfmax == 0)
++ break;
++ i++;
+ }
-+ ipath_stats.sps_hwerrs++;
++ *cid_target = tda18271_cid_target[i].target;
++ *count_limit = tda18271_cid_target[i].limit;
+
-+ /*
-+ * 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);
++ tda_map("(%d) cid_target = %02x, count_limit = %d\n", i,
++ tda18271_cid_target[i].target, tda18271_cid_target[i].limit);
+
-+ hwerrs &= dd->ipath_hwerrmask;
++ return 0;
++}
+
-+ /* 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));
++static struct tda18271_rf_tracking_filter_cal tda18271_rf_band_template[] = {
++ { .rfmax = 47900, .rfband = 0x00,
++ .rf1_def = 46000, .rf2_def = 0, .rf3_def = 0 },
++ { .rfmax = 61100, .rfband = 0x01,
++ .rf1_def = 52200, .rf2_def = 0, .rf3_def = 0 },
++ { .rfmax = 152600, .rfband = 0x02,
++ .rf1_def = 70100, .rf2_def = 136800, .rf3_def = 0 },
++ { .rfmax = 164700, .rfband = 0x03,
++ .rf1_def = 156700, .rf2_def = 0, .rf3_def = 0 },
++ { .rfmax = 203500, .rfband = 0x04,
++ .rf1_def = 186250, .rf2_def = 0, .rf3_def = 0 },
++ { .rfmax = 457800, .rfband = 0x05,
++ .rf1_def = 230000, .rf2_def = 345000, .rf3_def = 426000 },
++ { .rfmax = 865000, .rfband = 0x06,
++ .rf1_def = 489500, .rf2_def = 697500, .rf3_def = 842000 },
++ { .rfmax = 0, .rfband = 0x00,
++ .rf1_def = 0, .rf2_def = 0, .rf3_def = 0 }, /* end */
++};
+
-+ if (hwerrs & INFINIPATH_HWE_IB_UC_MEMORYPARITYERR)
-+ ipath_sd7220_clr_ibpar(dd);
++int tda18271_lookup_rf_band(struct dvb_frontend *fe, u32 *freq, u8 *rf_band)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++ struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state;
++ int i = 0;
+
-+ 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);
-+ }
++ while ((map[i].rfmax * 1000) < *freq) {
++ if (tda18271_debug & DBG_ADV)
++ tda_map("(%d) rfmax = %d < freq = %d, "
++ "rf1_def = %d, rf2_def = %d, rf3_def = %d, "
++ "rf1 = %d, rf2 = %d, rf3 = %d, "
++ "rf_a1 = %d, rf_a2 = %d, "
++ "rf_b1 = %d, rf_b2 = %d\n",
++ i, map[i].rfmax * 1000, *freq,
++ map[i].rf1_def, map[i].rf2_def, map[i].rf3_def,
++ map[i].rf1, map[i].rf2, map[i].rf3,
++ map[i].rf_a1, map[i].rf_a2,
++ map[i].rf_b1, map[i].rf_b2);
++ if (map[i].rfmax == 0)
++ return -EINVAL;
++ i++;
+ }
++ if (rf_band)
++ *rf_band = map[i].rfband;
+
-+ *msg = '\0';
++ tda_map("(%d) rf_band = %02x\n", i, map[i].rfband);
+
-+ 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);
-+ }
++ return i;
++}
+
-+ 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);
-+ }
++struct tda18271_map_layout {
++ struct tda18271_pll_map *main_pll;
++ struct tda18271_pll_map *cal_pll;
++
++ struct tda18271_map *rf_cal;
++ struct tda18271_map *rf_cal_kmco;
++ struct tda18271_map *rf_cal_dc_over_dt;
++
++ struct tda18271_map *bp_filter;
++ struct tda18271_map *rf_band;
++ struct tda18271_map *gain_taper;
++ struct tda18271_map *ir_measure;
++};
+
-+#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);
++int tda18271_lookup_pll_map(struct dvb_frontend *fe,
++ enum tda18271_map_type map_type,
++ u32 *freq, u8 *post_div, u8 *div)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++ struct tda18271_pll_map *map = NULL;
++ unsigned int i = 0;
++ char *map_name;
++ int ret = 0;
++
++ BUG_ON(!priv->maps);
++
++ switch (map_type) {
++ case MAIN_PLL:
++ map = priv->maps->main_pll;
++ map_name = "main_pll";
++ break;
++ case CAL_PLL:
++ map = priv->maps->cal_pll;
++ map_name = "cal_pll";
++ break;
++ default:
++ /* we should never get here */
++ map_name = "undefined";
++ break;
+ }
+
-+ 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);
++ if (!map) {
++ tda_warn("%s map is not set!\n", map_name);
++ ret = -EINVAL;
++ goto fail;
+ }
+
-+ 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:;
++ while ((map[i].lomax * 1000) < *freq) {
++ if (map[i + 1].lomax == 0) {
++ tda_map("%s: frequency (%d) out of range\n",
++ map_name, *freq);
++ ret = -ERANGE;
++ break;
++ }
++ i++;
++ }
++ *post_div = map[i].pd;
++ *div = map[i].d;
++
++ tda_map("(%d) %s: post div = 0x%02x, div = 0x%02x\n",
++ i, map_name, *post_div, *div);
++fail:
++ return ret;
+}
+
-+/**
-+ * 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)
++int tda18271_lookup_map(struct dvb_frontend *fe,
++ enum tda18271_map_type map_type,
++ u32 *freq, u8 *val)
+{
-+ char *n = NULL;
-+ u8 boardrev = dd->ipath_boardrev;
-+ int ret;
++ struct tda18271_priv *priv = fe->tuner_priv;
++ struct tda18271_map *map = NULL;
++ unsigned int i = 0;
++ char *map_name;
++ int ret = 0;
+
-+ 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";
++ BUG_ON(!priv->maps);
++
++ switch (map_type) {
++ case BP_FILTER:
++ map = priv->maps->bp_filter;
++ map_name = "bp_filter";
++ break;
++ case RF_CAL_KMCO:
++ map = priv->maps->rf_cal_kmco;
++ map_name = "km";
++ break;
++ case RF_BAND:
++ map = priv->maps->rf_band;
++ map_name = "rf_band";
++ break;
++ case GAIN_TAPER:
++ map = priv->maps->gain_taper;
++ map_name = "gain_taper";
++ break;
++ case RF_CAL:
++ map = priv->maps->rf_cal;
++ map_name = "rf_cal";
++ break;
++ case IR_MEASURE:
++ map = priv->maps->ir_measure;
++ map_name = "ir_measure";
++ break;
++ case RF_CAL_DC_OVER_DT:
++ map = priv->maps->rf_cal_dc_over_dt;
++ map_name = "rf_cal_dc_over_dt";
+ 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);
++ /* we should never get here */
++ map_name = "undefined";
+ break;
+ }
-+ if (n)
-+ snprintf(name, namelen, "%s", n);
+
-+ if (dd->ipath_majrev != 5 || !dd->ipath_minrev ||
-+ dd->ipath_minrev > 2) {
-+ ipath_dev_err(dd, "Unsupported InfiniPath hardware "
-+ "revision %u.%u!\n",
-+ dd->ipath_majrev, dd->ipath_minrev);
-+ ret = 1;
-+ } else if (dd->ipath_minrev == 1) {
-+ /* Rev1 chips are prototype. Complain, but allow use */
-+ ipath_dev_err(dd, "Unsupported hardware "
-+ "revision %u.%u, Contact support at qlogic.com\n",
-+ dd->ipath_majrev, dd->ipath_minrev);
-+ ret = 0;
-+ } else
-+ ret = 0;
++ if (!map) {
++ tda_warn("%s map is not set!\n", map_name);
++ ret = -EINVAL;
++ goto fail;
++ }
+
-+ /*
-+ * 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 */
++ while ((map[i].rfmax * 1000) < *freq) {
++ if (map[i + 1].rfmax == 0) {
++ tda_map("%s: frequency (%d) out of range\n",
++ map_name, *freq);
++ ret = -ERANGE;
++ break;
++ }
++ i++;
++ }
++ *val = map[i].val;
+
++ tda_map("(%d) %s: 0x%02x\n", i, map_name, *val);
++fail:
+ 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);
++static struct tda18271_std_map tda18271c1_std_map = {
++ .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 */
++};
+
-+ 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");
++static struct tda18271_std_map tda18271c2_std_map = {
++ .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 */
++};
+
-+ val = ~0ULL; /* barring bugs, all hwerrors become interrupts, */
++/*---------------------------------------------------------------------*/
+
-+ if (!dd->ipath_boardrev) /* no PLL for Emulator */
-+ val &= ~INFINIPATH_HWE_SERDESPLLFAILED;
++static struct tda18271_map_layout tda18271c1_map_layout = {
++ .main_pll = tda18271c1_main_pll,
++ .cal_pll = tda18271c1_cal_pll,
+
-+ if (dd->ipath_minrev == 1)
-+ val &= ~(1ULL << 42); /* TXE LaunchFIFO Parity rev1 issue */
++ .rf_cal = tda18271c1_rf_cal,
++ .rf_cal_kmco = tda18271c1_km,
+
-+ val &= ~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR;
-+ dd->ipath_hwerrmask = val;
++ .bp_filter = tda18271_bp_filter,
++ .rf_band = tda18271_rf_band,
++ .gain_taper = tda18271_gain_taper,
++ .ir_measure = tda18271_ir_measure,
++};
+
-+ /*
-+ * 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;
++static struct tda18271_map_layout tda18271c2_map_layout = {
++ .main_pll = tda18271c2_main_pll,
++ .cal_pll = tda18271c2_cal_pll,
++
++ .rf_cal = tda18271c2_rf_cal,
++ .rf_cal_kmco = tda18271c2_km,
++
++ .rf_cal_dc_over_dt = tda18271_rf_cal_dc_over_dt,
++
++ .bp_filter = tda18271_bp_filter,
++ .rf_band = tda18271_rf_band,
++ .gain_taper = tda18271_gain_taper,
++ .ir_measure = tda18271_ir_measure,
++};
++
++int tda18271_assign_map_layout(struct dvb_frontend *fe)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++ int ret = 0;
++
++ switch (priv->id) {
++ case TDA18271HDC1:
++ priv->maps = &tda18271c1_map_layout;
++ memcpy(&priv->std, &tda18271c1_std_map,
++ sizeof(struct tda18271_std_map));
++ break;
++ case TDA18271HDC2:
++ priv->maps = &tda18271c2_map_layout;
++ memcpy(&priv->std, &tda18271c2_std_map,
++ sizeof(struct tda18271_std_map));
++ break;
++ default:
++ ret = -EINVAL;
++ break;
++ }
++ memcpy(priv->rf_cal_state, &tda18271_rf_band_template,
++ sizeof(tda18271_rf_band_template));
++
++ return ret;
+}
+
+/*
-+ * 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().
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-basic-offset: 8
++ * End:
+ */
+diff --git a/drivers/media/common/tuners/tda18271-priv.h b/drivers/media/common/tuners/tda18271-priv.h
+new file mode 100644
+index 0000000..2bc5eb3
+--- /dev/null
++++ b/drivers/media/common/tuners/tda18271-priv.h
+@@ -0,0 +1,220 @@
++/*
++ tda18271-priv.h - private header for the NXP TDA18271 silicon tuner
+
-+/**
-+ * 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 */
++ Copyright (C) 2007, 2008 Michael Krufky <mkrufky at linuxtv.org>
+
-+ ipath_dbg("Trying to bringup serdes\n");
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the 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 (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);
-+ }
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
+
-+ if (!dd->ipath_ibcddrctrl) {
-+ /* not on re-init after reset */
-+ dd->ipath_ibcddrctrl =
-+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcddrctrl);
++ You 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.
++*/
+
-+ 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;
++#ifndef __TDA18271_PRIV_H__
++#define __TDA18271_PRIV_H__
+
-+ /* 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;
-+ }
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/mutex.h>
++#include "tuner-i2c.h"
++#include "tda18271.h"
+
-+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcddrctrl,
-+ dd->ipath_ibcddrctrl);
++#define R_ID 0x00 /* ID byte */
++#define R_TM 0x01 /* Thermo byte */
++#define R_PL 0x02 /* Power level byte */
++#define R_EP1 0x03 /* Easy Prog byte 1 */
++#define R_EP2 0x04 /* Easy Prog byte 2 */
++#define R_EP3 0x05 /* Easy Prog byte 3 */
++#define R_EP4 0x06 /* Easy Prog byte 4 */
++#define R_EP5 0x07 /* Easy Prog byte 5 */
++#define R_CPD 0x08 /* Cal Post-Divider byte */
++#define R_CD1 0x09 /* Cal Divider byte 1 */
++#define R_CD2 0x0a /* Cal Divider byte 2 */
++#define R_CD3 0x0b /* Cal Divider byte 3 */
++#define R_MPD 0x0c /* Main Post-Divider byte */
++#define R_MD1 0x0d /* Main Divider byte 1 */
++#define R_MD2 0x0e /* Main Divider byte 2 */
++#define R_MD3 0x0f /* Main Divider byte 3 */
++#define R_EB1 0x10 /* Extended byte 1 */
++#define R_EB2 0x11 /* Extended byte 2 */
++#define R_EB3 0x12 /* Extended byte 3 */
++#define R_EB4 0x13 /* Extended byte 4 */
++#define R_EB5 0x14 /* Extended byte 5 */
++#define R_EB6 0x15 /* Extended byte 6 */
++#define R_EB7 0x16 /* Extended byte 7 */
++#define R_EB8 0x17 /* Extended byte 8 */
++#define R_EB9 0x18 /* Extended byte 9 */
++#define R_EB10 0x19 /* Extended byte 10 */
++#define R_EB11 0x1a /* Extended byte 11 */
++#define R_EB12 0x1b /* Extended byte 12 */
++#define R_EB13 0x1c /* Extended byte 13 */
++#define R_EB14 0x1d /* Extended byte 14 */
++#define R_EB15 0x1e /* Extended byte 15 */
++#define R_EB16 0x1f /* Extended byte 16 */
++#define R_EB17 0x20 /* Extended byte 17 */
++#define R_EB18 0x21 /* Extended byte 18 */
++#define R_EB19 0x22 /* Extended byte 19 */
++#define R_EB20 0x23 /* Extended byte 20 */
++#define R_EB21 0x24 /* Extended byte 21 */
++#define R_EB22 0x25 /* Extended byte 22 */
++#define R_EB23 0x26 /* Extended byte 23 */
+
-+ ipath_write_kreg(dd, IPATH_KREG_OFFSET(IBNCModeCtrl), 0Ull);
++#define TDA18271_NUM_REGS 39
++
++/*---------------------------------------------------------------------*/
++
++struct tda18271_rf_tracking_filter_cal {
++ u32 rfmax;
++ u8 rfband;
++ u32 rf1_def;
++ u32 rf2_def;
++ u32 rf3_def;
++ u32 rf1;
++ u32 rf2;
++ u32 rf3;
++ int rf_a1;
++ int rf_b1;
++ int rf_a2;
++ int rf_b2;
++};
++
++enum tda18271_pll {
++ TDA18271_MAIN_PLL,
++ TDA18271_CAL_PLL,
++};
++
++enum tda18271_mode {
++ TDA18271_ANALOG,
++ TDA18271_DIGITAL,
++};
++
++struct tda18271_map_layout;
++
++enum tda18271_ver {
++ TDA18271HDC1,
++ TDA18271HDC2,
++};
++
++struct tda18271_priv {
++ unsigned char tda18271_regs[TDA18271_NUM_REGS];
++
++ 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 tm_rfcal;
++ unsigned int cal_initialized:1;
++ unsigned int small_i2c:1;
++
++ struct tda18271_map_layout *maps;
++ struct tda18271_std_map std;
++ struct tda18271_rf_tracking_filter_cal rf_cal_state[8];
++
++ struct mutex lock;
++
++ u32 frequency;
++ u32 bandwidth;
++};
++
++/*---------------------------------------------------------------------*/
++
++extern int tda18271_debug;
++
++#define DBG_INFO 1
++#define DBG_MAP 2
++#define DBG_REG 4
++#define DBG_ADV 8
++#define DBG_CAL 16
++
++#define tda_printk(kern, fmt, arg...) \
++ printk(kern "%s: " fmt, __func__, ##arg)
++
++#define dprintk(kern, lvl, fmt, arg...) do {\
++ if (tda18271_debug & lvl) \
++ tda_printk(kern, fmt, ##arg); } while (0)
++
++#define tda_info(fmt, arg...) printk(KERN_INFO fmt, ##arg)
++#define tda_warn(fmt, arg...) tda_printk(KERN_WARNING, fmt, ##arg)
++#define tda_err(fmt, arg...) tda_printk(KERN_ERR, fmt, ##arg)
++#define tda_dbg(fmt, arg...) dprintk(KERN_DEBUG, DBG_INFO, fmt, ##arg)
++#define tda_map(fmt, arg...) dprintk(KERN_DEBUG, DBG_MAP, fmt, ##arg)
++#define tda_reg(fmt, arg...) dprintk(KERN_DEBUG, DBG_REG, fmt, ##arg)
++#define tda_cal(fmt, arg...) dprintk(KERN_DEBUG, DBG_CAL, fmt, ##arg)
++
++/*---------------------------------------------------------------------*/
++
++enum tda18271_map_type {
++ /* tda18271_pll_map */
++ MAIN_PLL,
++ CAL_PLL,
++ /* tda18271_map */
++ RF_CAL,
++ RF_CAL_KMCO,
++ RF_CAL_DC_OVER_DT,
++ BP_FILTER,
++ RF_BAND,
++ GAIN_TAPER,
++ IR_MEASURE,
++};
++
++extern int tda18271_lookup_pll_map(struct dvb_frontend *fe,
++ enum tda18271_map_type map_type,
++ u32 *freq, u8 *post_div, u8 *div);
++extern int tda18271_lookup_map(struct dvb_frontend *fe,
++ enum tda18271_map_type map_type,
++ u32 *freq, u8 *val);
++
++extern int tda18271_lookup_thermometer(struct dvb_frontend *fe);
++
++extern int tda18271_lookup_rf_band(struct dvb_frontend *fe,
++ u32 *freq, u8 *rf_band);
++
++extern int tda18271_lookup_cid_target(struct dvb_frontend *fe,
++ u32 *freq, u8 *cid_target,
++ u16 *count_limit);
++
++extern int tda18271_assign_map_layout(struct dvb_frontend *fe);
++
++/*---------------------------------------------------------------------*/
++
++extern int tda18271_read_regs(struct dvb_frontend *fe);
++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);
++
++extern int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq);
++extern int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq);
++
++extern int tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq);
++extern int tda18271_calc_km(struct dvb_frontend *fe, u32 *freq);
++extern int tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq);
++extern int tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq);
++extern int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq);
++extern int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq);
++
++#endif /* __TDA18271_PRIV_H__ */
++
++/*
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-basic-offset: 8
++ * End:
++ */
+diff --git a/drivers/media/common/tuners/tda18271.h b/drivers/media/common/tuners/tda18271.h
+new file mode 100644
+index 0000000..7db9831
+--- /dev/null
++++ b/drivers/media/common/tuners/tda18271.h
+@@ -0,0 +1,99 @@
++/*
++ tda18271.h - header for the Philips / NXP TDA18271 silicon tuner
++
++ Copyright (C) 2007, 2008 Michael Krufky <mkrufky at linuxtv.org>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You 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.
++*/
+
-+ /* 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));
++#ifndef __TDA18271_H__
++#define __TDA18271_H__
+
-+ 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);
-+ }
++#include <linux/i2c.h>
++#include "dvb_frontend.h"
+
-+ 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);
++struct tda18271_std_map_item {
++ u16 if_freq;
+
-+ ipath_cdbg(VERBOSE, "done: xgxs=%llx from %llx\n",
-+ (unsigned long long)
-+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig),
-+ prev_val);
++ /* 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;
++};
+
-+ guid = be64_to_cpu(dd->ipath_guid);
++struct tda18271_std_map {
++ struct tda18271_std_map_item fm_radio;
++ struct tda18271_std_map_item atv_b;
++ struct tda18271_std_map_item atv_dk;
++ struct tda18271_std_map_item atv_gh;
++ struct tda18271_std_map_item atv_i;
++ struct tda18271_std_map_item atv_l;
++ struct tda18271_std_map_item atv_lc;
++ struct tda18271_std_map_item atv_mn;
++ struct tda18271_std_map_item atsc_6;
++ struct tda18271_std_map_item dvbt_6;
++ struct tda18271_std_map_item dvbt_7;
++ struct tda18271_std_map_item dvbt_8;
++ struct tda18271_std_map_item qam_6;
++ struct tda18271_std_map_item qam_8;
++};
+
-+ 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;
-+}
++enum tda18271_role {
++ TDA18271_MASTER = 0,
++ TDA18271_SLAVE,
++};
+
-+static void ipath_7220_config_jint(struct ipath_devdata *dd,
-+ u16 idle_ticks, u16 max_packets)
-+{
++enum tda18271_i2c_gate {
++ TDA18271_GATE_AUTO = 0,
++ TDA18271_GATE_ANALOG,
++ TDA18271_GATE_DIGITAL,
++};
+
-+ /*
-+ * 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;
++struct tda18271_config {
++ /* override default if freq / std settings (optional) */
++ struct tda18271_std_map *std_map;
+
-+ /* refresh kernel RcvHdrHead registers... */
-+ ipath_write_ureg(dd, ur_rcvhdrhead,
-+ dd->ipath_rhdrhead_intr_off |
-+ dd->ipath_pd[0]->port_head, 0);
++ /* master / slave tuner: master uses main pll, slave uses cal pll */
++ enum tda18271_role role;
+
-+ 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);
-+}
++ /* use i2c gate provided by analog or digital demod */
++ enum tda18271_i2c_gate gate;
+
-+/**
-+ * 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);
-+}
++ /* some i2c providers cant write all 39 registers at once */
++ unsigned int small_i2c:1;
++};
+
-+static int ipath_7220_intconfig(struct ipath_devdata *dd)
++#if defined(CONFIG_MEDIA_TUNER_TDA18271) || (defined(CONFIG_MEDIA_TUNER_TDA18271_MODULE) && defined(MODULE))
++extern struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
++ struct i2c_adapter *i2c,
++ struct tda18271_config *cfg);
++#else
++static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe,
++ u8 addr,
++ struct i2c_adapter *i2c,
++ struct tda18271_config *cfg)
+{
-+ ipath_7220_config_jint(dd, dd->ipath_jint_idle_ticks,
-+ dd->ipath_jint_max_packets);
-+ return 0;
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++ return NULL;
+}
++#endif
+
-+/**
-+ * ipath_setup_7220_setextled - set the state of the two external LEDs
-+ * @dd: the infinipath device
-+ * @lst: the L state
-+ * @ltst: the LT state
++#endif /* __TDA18271_H__ */
+diff --git a/drivers/media/common/tuners/tda827x.c b/drivers/media/common/tuners/tda827x.c
+new file mode 100644
+index 0000000..d30d2c9
+--- /dev/null
++++ b/drivers/media/common/tuners/tda827x.c
+@@ -0,0 +1,852 @@
++/*
+ *
-+ * 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),
++ * (c) 2005 Hartmut Hackmann
++ * (c) 2007 Michael Krufky
+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
+ *
++ * You 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.
+ */
-+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;
++#include <linux/module.h>
++#include <asm/types.h>
++#include <linux/dvb/frontend.h>
++#include <linux/videodev2.h>
+
-+ /* 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;
-+ }
++#include "tda827x.h"
+
-+ 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);
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
-+ if (ledblink) /* blink the LED on packet receive */
-+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvpktledcnt,
-+ ledblink);
-+}
++#define dprintk(args...) \
++ do { \
++ if (debug) printk(KERN_DEBUG "tda827x: " args); \
++ } while (0)
+
-+/*
-+ * 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;
++struct tda827x_priv {
++ int i2c_addr;
++ struct i2c_adapter *i2c_adap;
++ struct tda827x_config *cfg;
+
-+ /* 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);
++ unsigned int sgIF;
++ unsigned char lpsel;
+
-+ /* 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);
-+ }
-+}
++ u32 frequency;
++ u32 bandwidth;
++};
+
-+static int ipath_msi_enabled(struct pci_dev *pdev)
++static void tda827x_set_std(struct dvb_frontend *fe,
++ struct analog_parameters *params)
+{
-+ int pos, ret = 0;
-+
-+ pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
-+ if (pos) {
-+ u16 cw;
++ struct tda827x_priv *priv = fe->tuner_priv;
++ char *mode;
+
-+ pci_read_config_word(pdev, pos + PCI_MSI_FLAGS, &cw);
-+ ret = !!(cw & PCI_MSI_FLAGS_ENABLE);
++ priv->lpsel = 0;
++ if (params->std & V4L2_STD_MN) {
++ priv->sgIF = 92;
++ priv->lpsel = 1;
++ mode = "MN";
++ } else if (params->std & V4L2_STD_B) {
++ priv->sgIF = 108;
++ mode = "B";
++ } else if (params->std & V4L2_STD_GH) {
++ priv->sgIF = 124;
++ mode = "GH";
++ } else if (params->std & V4L2_STD_PAL_I) {
++ priv->sgIF = 124;
++ mode = "I";
++ } else if (params->std & V4L2_STD_DK) {
++ priv->sgIF = 124;
++ mode = "DK";
++ } else if (params->std & V4L2_STD_SECAM_L) {
++ priv->sgIF = 124;
++ mode = "L";
++ } else if (params->std & V4L2_STD_SECAM_LC) {
++ priv->sgIF = 20;
++ mode = "LC";
++ } else {
++ priv->sgIF = 124;
++ mode = "xx";
+ }
-+ 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 (params->mode == V4L2_TUNER_RADIO)
++ priv->sgIF = 88; /* if frequency is 5.5 MHz */
+
-+ 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);
-+ }
++ dprintk("setting tda827x to system %s\n", mode);
+}
+
-+/*
-+ * 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)
++struct tda827x_data {
++ u32 lomax;
++ u8 spd;
++ u8 bs;
++ u8 bp;
++ u8 cp;
++ u8 gc3;
++ u8 div1p5;
++};
++
++static const struct tda827x_data tda827x_table[] = {
++ { .lomax = 62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
++ { .lomax = 66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
++ { .lomax = 76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
++ { .lomax = 84000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
++ { .lomax = 93000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
++ { .lomax = 98000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
++ { .lomax = 109000000, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
++ { .lomax = 123000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
++ { .lomax = 133000000, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
++ { .lomax = 151000000, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
++ { .lomax = 154000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
++ { .lomax = 181000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0},
++ { .lomax = 185000000, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
++ { .lomax = 217000000, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
++ { .lomax = 244000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
++ { .lomax = 265000000, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
++ { .lomax = 302000000, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
++ { .lomax = 324000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
++ { .lomax = 370000000, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
++ { .lomax = 454000000, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
++ { .lomax = 493000000, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
++ { .lomax = 530000000, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
++ { .lomax = 554000000, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
++ { .lomax = 604000000, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
++ { .lomax = 696000000, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
++ { .lomax = 740000000, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
++ { .lomax = 820000000, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
++ { .lomax = 865000000, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
++ { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0}
++};
++
++static int tda827xo_set_params(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *params)
+{
-+ u16 linkstat, minwidth, speed;
-+ int pos;
++ struct tda827x_priv *priv = fe->tuner_priv;
++ u8 buf[14];
+
-+ 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;
-+ }
++ struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
++ .buf = buf, .len = sizeof(buf) };
++ int i, tuner_freq, if_freq;
++ u32 N;
+
-+ 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 */
++ dprintk("%s:\n", __func__);
++ switch (params->u.ofdm.bandwidth) {
++ case BANDWIDTH_6_MHZ:
++ if_freq = 4000000;
+ break;
-+ default:
-+ minwidth = 8; /* x8 capable boards */
++ case BANDWIDTH_7_MHZ:
++ if_freq = 4500000;
++ break;
++ default: /* 8 MHz or Auto */
++ if_freq = 5000000;
+ break;
+ }
++ tuner_freq = params->frequency + if_freq;
+
-+ 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;
++ i = 0;
++ while (tda827x_table[i].lomax < tuner_freq) {
++ if (tda827x_table[i + 1].lomax == 0)
++ break;
++ i++;
+ }
+
-+ 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);
++ N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2);
++ buf[0] = 0;
++ buf[1] = (N>>8) | 0x40;
++ buf[2] = N & 0xff;
++ buf[3] = 0;
++ buf[4] = 0x52;
++ buf[5] = (tda827x_table[i].spd << 6) + (tda827x_table[i].div1p5 << 5) +
++ (tda827x_table[i].bs << 3) +
++ tda827x_table[i].bp;
++ buf[6] = (tda827x_table[i].gc3 << 4) + 0x8f;
++ buf[7] = 0xbf;
++ buf[8] = 0x2a;
++ buf[9] = 0x05;
++ buf[10] = 0xff;
++ buf[11] = 0x00;
++ buf[12] = 0x00;
++ buf[13] = 0x40;
+
-+ if (speed != 1)
-+ ipath_dev_err(dd,
-+ "PCIe linkspeed %u is incorrect; "
-+ "should be 1 (2500)!\n", speed);
++ msg.len = 14;
++ if (fe->ops.i2c_gate_ctrl)
++ 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",
++ __func__, priv->i2c_addr << 1);
++ return -EIO;
++ }
++ msleep(500);
++ /* correct CP value */
++ buf[0] = 0x30;
++ buf[1] = 0x50 + tda827x_table[i].cp;
++ msg.len = 2;
+
-+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;
-+}
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
++ priv->frequency = tuner_freq - if_freq; // FIXME
++ priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+
-+/**
-+ * 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)
++ return 0;
++}
++
++static int tda827xo_sleep(struct dvb_frontend *fe)
+{
-+ int pos, ret = -1;
-+ u32 boardrev;
++ struct tda827x_priv *priv = fe->tuner_priv;
++ static u8 buf[] = { 0x30, 0xd0 };
++ struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
++ .buf = buf, .len = sizeof(buf) };
+
-+ dd->ipath_msi_lo = 0; /* used as a flag during reset processing */
++ dprintk("%s:\n", __func__);
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ 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;
-+ }
++ if (priv->cfg && priv->cfg->sleep)
++ priv->cfg->sleep(fe);
+
-+ 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");
++ return 0;
++}
+
-+ 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);
++static int tda827xo_set_analog_params(struct dvb_frontend *fe,
++ struct analog_parameters *params)
++{
++ unsigned char tuner_reg[8];
++ unsigned char reg2[2];
++ u32 N;
++ int i;
++ struct tda827x_priv *priv = fe->tuner_priv;
++ struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0 };
++ unsigned int freq = params->frequency;
+
-+ /*
-+ * 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;
++ tda827x_set_std(fe, params);
+
-+ ipath_7220_pcie_params(dd, boardrev);
++ if (params->mode == V4L2_TUNER_RADIO)
++ freq = freq / 1000;
+
-+ 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;
-+}
++ N = freq + priv->sgIF;
+
-+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;
++ i = 0;
++ while (tda827x_table[i].lomax < N * 62500) {
++ if (tda827x_table[i + 1].lomax == 0)
++ break;
++ i++;
++ }
+
-+ /*
-+ * 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;
++ N = N << tda827x_table[i].spd;
+
-+ /*
-+ * 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);
++ tuner_reg[0] = 0;
++ tuner_reg[1] = (unsigned char)(N>>8);
++ tuner_reg[2] = (unsigned char) N;
++ tuner_reg[3] = 0x40;
++ tuner_reg[4] = 0x52 + (priv->lpsel << 5);
++ tuner_reg[5] = (tda827x_table[i].spd << 6) +
++ (tda827x_table[i].div1p5 << 5) +
++ (tda827x_table[i].bs << 3) + tda827x_table[i].bp;
++ tuner_reg[6] = 0x8f + (tda827x_table[i].gc3 << 4);
++ tuner_reg[7] = 0x8f;
+
-+ /*
-+ * 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;
++ msg.buf = tuner_reg;
++ msg.len = 8;
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ /* 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;
++ msg.buf = reg2;
++ msg.len = 2;
++ reg2[0] = 0x80;
++ reg2[1] = 0;
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ /* 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;
++ reg2[0] = 0x60;
++ reg2[1] = 0xbf;
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ 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;
++ reg2[0] = 0x30;
++ reg2[1] = tuner_reg[4] + 0x80;
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ /*
-+ * 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;
++ msleep(1);
++ reg2[0] = 0x30;
++ reg2[1] = tuner_reg[4] + 4;
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ dd->ipath_eep_st_masks[1].hwerrs_to_log =
-+ INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
-+ INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT;
++ msleep(1);
++ reg2[0] = 0x30;
++ reg2[1] = tuner_reg[4];
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ dd->ipath_eep_st_masks[2].errs_to_log = INFINIPATH_E_RESET;
++ msleep(550);
++ reg2[0] = 0x30;
++ reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_table[i].cp;
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ ipath_linkrecovery = 0;
++ reg2[0] = 0x60;
++ reg2[1] = 0x3f;
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ init_waitqueue_head(&dd->ipath_autoneg_wait);
-+ INIT_DELAYED_WORK(&dd->ipath_autoneg_work, autoneg_work);
++ reg2[0] = 0x80;
++ reg2[1] = 0x08; /* Vsync en */
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ dd->ipath_link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X;
-+ dd->ipath_link_speed_supported = IPATH_IB_SDR | IPATH_IB_DDR;
++ priv->frequency = freq * 62500;
+
-+ 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];
++ return 0;
+}
+
++static void tda827xo_agcf(struct dvb_frontend *fe)
++{
++ struct tda827x_priv *priv = fe->tuner_priv;
++ unsigned char data[] = { 0x80, 0x0c };
++ struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
++ .buf = data, .len = 2};
+
-+/*
-+ * 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)
++ i2c_transfer(priv->i2c_adap, &msg, 1);
++}
++
++/* ------------------------------------------------------------------ */
++
++struct tda827xa_data {
++ u32 lomax;
++ u8 svco;
++ u8 spd;
++ u8 scr;
++ u8 sbs;
++ u8 gc3;
++};
++
++static const struct tda827xa_data tda827xa_dvbt[] = {
++ { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1},
++ { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
++ { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
++ { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
++ { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
++ { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
++ { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
++ { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
++ { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
++ { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
++ { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
++ { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
++ { .lomax = 290000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
++ { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
++ { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
++ { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
++ { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
++ { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
++ { .lomax = 550000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
++ { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
++ { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
++ { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
++ { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
++ { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
++ { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
++ { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
++ { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
++};
++
++static struct tda827xa_data tda827xa_analog[] = {
++ { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3},
++ { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
++ { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
++ { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
++ { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
++ { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
++ { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
++ { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
++ { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
++ { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
++ { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3},
++ { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3},
++ { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
++ { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
++ { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
++ { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
++ { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
++ { .lomax = 554000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
++ { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
++ { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
++ { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
++ { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
++ { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
++ { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
++ { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
++ { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
++};
++
++static int tda827xa_sleep(struct dvb_frontend *fe)
+{
-+ int ret = 0;
++ 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) };
+
-+ int pos;
-+ u16 control;
-+ if (!dd->ipath_msi_lo) /* Using intX, or init problem */
-+ goto bail;
++ dprintk("%s:\n", __func__);
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
+
-+ 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;
++ 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;
+ }
-+ 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);
++ if (priv->cfg->config) {
++ if (high)
++ dprintk("setting LNA to high gain\n");
++ else
++ dprintk("setting LNA to low gain\n");
+ }
-+ /* 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;
++ 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;
+ }
-+ /*
-+ * 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)
++static int tda827xa_set_params(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *params)
+{
-+ u64 val;
-+ int i;
-+ int ret;
-+ u16 cmdval;
++ struct tda827x_priv *priv = fe->tuner_priv;
++ u8 buf[11];
+
-+ pci_read_config_word(dd->pcidev, PCI_COMMAND, &cmdval);
++ struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
++ .buf = buf, .len = sizeof(buf) };
+
-+ /* Use dev_err so it shows up in logs, etc. */
-+ ipath_dev_err(dd, "Resetting InfiniPath unit %u\n", dd->ipath_unit);
++ int i, tuner_freq, if_freq;
++ u32 N;
+
-+ /* 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();
++ dprintk("%s:\n", __func__);
+
-+ for (i = 1; i <= 5; i++) {
-+ int r;
++ tda827xa_lna_gain(fe, 1, NULL);
++ msleep(20);
+
-+ /*
-+ * 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);
++ switch (params->u.ofdm.bandwidth) {
++ case BANDWIDTH_6_MHZ:
++ if_freq = 4000000;
++ break;
++ case BANDWIDTH_7_MHZ:
++ if_freq = 4500000;
++ break;
++ default: /* 8 MHz or Auto */
++ if_freq = 5000000;
++ break;
+ }
-+ ret = 0; /* failed */
++ tuner_freq = params->frequency + if_freq;
+
-+bail:
-+ if (ret)
-+ ipath_7220_pcie_params(dd, dd->ipath_boardrev);
++ i = 0;
++ while (tda827xa_dvbt[i].lomax < tuner_freq) {
++ if(tda827xa_dvbt[i + 1].lomax == 0)
++ break;
++ i++;
++ }
+
-+ return ret;
-+}
++ N = ((tuner_freq + 31250) / 62500) << tda827xa_dvbt[i].spd;
++ buf[0] = 0; // subaddress
++ buf[1] = N >> 8;
++ buf[2] = N & 0xff;
++ buf[3] = 0;
++ buf[4] = 0x16;
++ buf[5] = (tda827xa_dvbt[i].spd << 5) + (tda827xa_dvbt[i].svco << 3) +
++ tda827xa_dvbt[i].sbs;
++ buf[6] = 0x4b + (tda827xa_dvbt[i].gc3 << 4);
++ buf[7] = 0x1c;
++ buf[8] = 0x06;
++ buf[9] = 0x24;
++ buf[10] = 0x00;
++ msg.len = 11;
++ if (fe->ops.i2c_gate_ctrl)
++ 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",
++ __func__, priv->i2c_addr << 1);
++ return -EIO;
++ }
++ buf[0] = 0x90;
++ buf[1] = 0xff;
++ buf[2] = 0x60;
++ buf[3] = 0x00;
++ buf[4] = 0x59; // lpsel, for 6MHz + 2
++ msg.len = 5;
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+/**
-+ * 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;
++ buf[0] = 0xa0;
++ buf[1] = 0x40;
++ msg.len = 2;
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ /* 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;
-+ }
++ msleep(11);
++ msg.flags = I2C_M_RD;
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++ i2c_transfer(priv->i2c_adap, &msg, 1);
++ msg.flags = 0;
+
-+ 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();
-+}
++ buf[1] >>= 4;
++ dprintk("tda8275a AGC2 gain is: %d\n", buf[1]);
++ if ((buf[1]) < 2) {
++ tda827xa_lna_gain(fe, 0, NULL);
++ buf[0] = 0x60;
++ buf[1] = 0x0c;
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++ i2c_transfer(priv->i2c_adap, &msg, 1);
++ }
+
-+/**
-+ * 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;
++ buf[0] = 0xc0;
++ buf[1] = 0x99; // lpsel, for 6MHz + 2
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ if (!dd->ipath_kregbase)
-+ return;
++ buf[0] = 0x60;
++ buf[1] = 0x3c;
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ ipath_cdbg(VERBOSE, "Invalidate TIDs for port %u\n", port);
++ /* correct CP value */
++ buf[0] = 0x30;
++ buf[1] = 0x10 + tda827xa_dvbt[i].scr;
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ tidinv = dd->ipath_tidinvalid;
-+ tidbase = (u64 __iomem *)
-+ ((char __iomem *)(dd->ipath_kregbase) +
-+ dd->ipath_rcvtidbase +
-+ port * dd->ipath_rcvtidcnt * sizeof(*tidbase));
++ msleep(163);
++ buf[0] = 0xc0;
++ buf[1] = 0x39; // lpsel, for 6MHz + 2
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ for (i = 0; i < dd->ipath_rcvtidcnt; i++)
-+ ipath_7220_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EXPECTED,
-+ tidinv);
++ msleep(3);
++ /* freeze AGC1 */
++ buf[0] = 0x50;
++ buf[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4);
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ tidbase = (u64 __iomem *)
-+ ((char __iomem *)(dd->ipath_kregbase) +
-+ dd->ipath_rcvegrbase + port_egrtid_idx(dd, port)
-+ * sizeof(*tidbase));
++ priv->frequency = tuner_freq - if_freq; // FIXME
++ priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+
-+ 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);
++ return 0;
+}
+
-+/**
-+ * 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)
++static int tda827xa_set_analog_params(struct dvb_frontend *fe,
++ struct analog_parameters *params)
+{
-+ u32 i, s;
++ unsigned char tuner_reg[11];
++ u32 N;
++ int i;
++ struct tda827x_priv *priv = fe->tuner_priv;
++ struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
++ .buf = tuner_reg, .len = sizeof(tuner_reg) };
++ unsigned int freq = params->frequency;
+
-+ 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;
++ tda827x_set_std(fe, params);
++
++ tda827xa_lna_gain(fe, 1, params);
++ msleep(10);
++
++ if (params->mode == V4L2_TUNER_RADIO)
++ freq = freq / 1000;
++
++ N = freq + priv->sgIF;
++
++ i = 0;
++ while (tda827xa_analog[i].lomax < N * 62500) {
++ if (tda827xa_analog[i + 1].lomax == 0)
++ break;
++ i++;
+ }
+
-+ /*
-+ * 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;
++ N = N << tda827xa_analog[i].spd;
+
-+ dd->ipath_flags |= IPATH_4BYTE_TID;
++ tuner_reg[0] = 0;
++ tuner_reg[1] = (unsigned char)(N>>8);
++ tuner_reg[2] = (unsigned char) N;
++ tuner_reg[3] = 0;
++ tuner_reg[4] = 0x16;
++ tuner_reg[5] = (tda827xa_analog[i].spd << 5) +
++ (tda827xa_analog[i].svco << 3) +
++ tda827xa_analog[i].sbs;
++ tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4);
++ tuner_reg[7] = 0x1c;
++ tuner_reg[8] = 4;
++ tuner_reg[9] = 0x20;
++ tuner_reg[10] = 0x00;
++ msg.len = 11;
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ /*
-+ * 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);
++ tuner_reg[0] = 0x90;
++ tuner_reg[1] = 0xff;
++ tuner_reg[2] = 0xe0;
++ tuner_reg[3] = 0;
++ tuner_reg[4] = 0x99 + (priv->lpsel << 1);
++ msg.len = 5;
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ 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;
++ tuner_reg[0] = 0xa0;
++ tuner_reg[1] = 0xc0;
++ msg.len = 2;
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ ipath_7220_config_jint(dd, INFINIPATH_JINT_DEFAULT_IDLE_TICKS,
-+ INFINIPATH_JINT_DEFAULT_MAX_PACKETS);
++ tuner_reg[0] = 0x30;
++ tuner_reg[1] = 0x10 + tda827xa_analog[i].scr;
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ if (dd->ipath_boardrev) /* no eeprom on emulator */
-+ ipath_get_eeprom_info(dd);
++ msg.flags = I2C_M_RD;
++ i2c_transfer(priv->i2c_adap, &msg, 1);
++ msg.flags = 0;
++ tuner_reg[1] >>= 4;
++ dprintk("AGC2 gain is: %d\n", tuner_reg[1]);
++ if (tuner_reg[1] < 1)
++ tda827xa_lna_gain(fe, 0, params);
+
-+ /* 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);
++ msleep(100);
++ tuner_reg[0] = 0x60;
++ tuner_reg[1] = 0x3c;
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ 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));
++ msleep(163);
++ tuner_reg[0] = 0x50;
++ tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4);
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ 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);
++ tuner_reg[0] = 0x80;
++ tuner_reg[1] = 0x28;
++ i2c_transfer(priv->i2c_adap, &msg, 1);
+
-+ 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);
++ tuner_reg[0] = 0xb0;
++ tuner_reg[1] = 0x01;
++ i2c_transfer(priv->i2c_adap, &msg, 1);
++
++ tuner_reg[0] = 0xc0;
++ tuner_reg[1] = 0x19 + (priv->lpsel << 1);
++ i2c_transfer(priv->i2c_adap, &msg, 1);
++
++ priv->frequency = freq * 62500;
+
+ 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)
++static void tda827xa_agcf(struct dvb_frontend *fe)
+{
-+ struct ipath_base_info *kinfo = kbase;
++ struct tda827x_priv *priv = fe->tuner_priv;
++ unsigned char data[] = {0x80, 0x2c};
++ struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0,
++ .buf = data, .len = 2};
++ i2c_transfer(priv->i2c_adap, &msg, 1);
++}
+
-+ kinfo->spi_runtime_flags |=
-+ IPATH_RUNTIME_PCIE | IPATH_RUNTIME_NODMA_RTAIL |
-+ IPATH_RUNTIME_SDMA;
++/* ------------------------------------------------------------------ */
+
++static int tda827x_release(struct dvb_frontend *fe)
++{
++ kfree(fe->tuner_priv);
++ fe->tuner_priv = NULL;
+ return 0;
+}
+
-+static void ipath_7220_free_irq(struct ipath_devdata *dd)
++static int tda827x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
-+ free_irq(dd->ipath_irq, dd);
-+ dd->ipath_irq = 0;
++ struct tda827x_priv *priv = fe->tuner_priv;
++ *frequency = priv->frequency;
++ return 0;
+}
+
-+static struct ipath_message_header *
-+ipath_7220_get_msgheader(struct ipath_devdata *dd, __le32 *rhf_addr)
++static int tda827x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
-+ u32 offset = ipath_hdrget_offset(rhf_addr);
-+
-+ return (struct ipath_message_header *)
-+ (rhf_addr - dd->ipath_rhf_offset + offset);
++ struct tda827x_priv *priv = fe->tuner_priv;
++ *bandwidth = priv->bandwidth;
++ return 0;
+}
+
-+static void ipath_7220_config_ports(struct ipath_devdata *dd, ushort cfgports)
++static int tda827x_init(struct dvb_frontend *fe)
+{
-+ u32 nchipports;
-+
-+ nchipports = ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
-+ if (!cfgports) {
-+ int ncpus = num_online_cpus();
++ struct tda827x_priv *priv = fe->tuner_priv;
++ dprintk("%s:\n", __func__);
++ if (priv->cfg && priv->cfg->init)
++ priv->cfg->init(fe);
+
-+ 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 */
++ return 0;
+}
+
++static int tda827x_probe_version(struct dvb_frontend *fe);
+
-+static int ipath_7220_get_ib_cfg(struct ipath_devdata *dd, int which)
++static int tda827x_initial_init(struct dvb_frontend *fe)
+{
-+ int lsb, ret = 0;
-+ u64 maskr; /* right-justified mask */
++ int ret;
++ ret = tda827x_probe_version(fe);
++ if (ret)
++ return ret;
++ return fe->ops.tuner_ops.init(fe);
++}
+
-+ switch (which) {
-+ case IPATH_IB_CFG_HRTBT: /* Get Heartbeat off/enable/auto */
-+ lsb = IBA7220_IBC_HRTBT_SHIFT;
-+ maskr = IBA7220_IBC_HRTBT_MASK;
-+ break;
++static int tda827x_initial_sleep(struct dvb_frontend *fe)
++{
++ int ret;
++ ret = tda827x_probe_version(fe);
++ if (ret)
++ return ret;
++ return fe->ops.tuner_ops.sleep(fe);
++}
+
-+ case IPATH_IB_CFG_LWID_ENB: /* Get allowed Link-width */
-+ ret = dd->ipath_link_width_enabled;
-+ goto done;
++static struct dvb_tuner_ops tda827xo_tuner_ops = {
++ .info = {
++ .name = "Philips TDA827X",
++ .frequency_min = 55000000,
++ .frequency_max = 860000000,
++ .frequency_step = 250000
++ },
++ .release = tda827x_release,
++ .init = tda827x_initial_init,
++ .sleep = tda827x_initial_sleep,
++ .set_params = tda827xo_set_params,
++ .set_analog_params = tda827xo_set_analog_params,
++ .get_frequency = tda827x_get_frequency,
++ .get_bandwidth = tda827x_get_bandwidth,
++};
+
-+ case IPATH_IB_CFG_LWID: /* Get currently active Link-width */
-+ ret = dd->ipath_link_width_active;
-+ goto done;
++static struct dvb_tuner_ops tda827xa_tuner_ops = {
++ .info = {
++ .name = "Philips TDA827XA",
++ .frequency_min = 44000000,
++ .frequency_max = 906000000,
++ .frequency_step = 62500
++ },
++ .release = tda827x_release,
++ .init = tda827x_init,
++ .sleep = tda827xa_sleep,
++ .set_params = tda827xa_set_params,
++ .set_analog_params = tda827xa_set_analog_params,
++ .get_frequency = tda827x_get_frequency,
++ .get_bandwidth = tda827x_get_bandwidth,
++};
+
-+ case IPATH_IB_CFG_SPD_ENB: /* Get allowed Link speeds */
-+ ret = dd->ipath_link_speed_enabled;
-+ goto done;
++static int tda827x_probe_version(struct dvb_frontend *fe)
++{ u8 data;
++ struct tda827x_priv *priv = fe->tuner_priv;
++ struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = I2C_M_RD,
++ .buf = &data, .len = 1 };
++ if (fe->ops.i2c_gate_ctrl)
++ 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",
++ __func__, msg.addr << 1);
++ return -EIO;
++ }
++ if ((data & 0x3c) == 0) {
++ dprintk("tda827x tuner found\n");
++ fe->ops.tuner_ops.init = tda827x_init;
++ fe->ops.tuner_ops.sleep = tda827xo_sleep;
++ if (priv->cfg)
++ priv->cfg->agcf = tda827xo_agcf;
++ } else {
++ dprintk("tda827xa tuner found\n");
++ memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops));
++ if (priv->cfg)
++ priv->cfg->agcf = tda827xa_agcf;
++ }
++ return 0;
++}
+
-+ case IPATH_IB_CFG_SPD: /* Get current Link spd */
-+ ret = dd->ipath_link_speed_active;
-+ goto done;
++struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr,
++ struct i2c_adapter *i2c,
++ struct tda827x_config *cfg)
++{
++ struct tda827x_priv *priv = NULL;
+
-+ case IPATH_IB_CFG_RXPOL_ENB: /* Get Auto-RX-polarity enable */
-+ lsb = IBA7220_IBC_RXPOL_SHIFT;
-+ maskr = IBA7220_IBC_RXPOL_MASK;
-+ break;
++ dprintk("%s:\n", __func__);
++ priv = kzalloc(sizeof(struct tda827x_priv), GFP_KERNEL);
++ if (priv == NULL)
++ return NULL;
+
-+ case IPATH_IB_CFG_LREV_ENB: /* Get Auto-Lane-reversal enable */
-+ lsb = IBA7220_IBC_LREV_SHIFT;
-+ maskr = IBA7220_IBC_LREV_MASK;
-+ break;
++ priv->i2c_addr = addr;
++ priv->i2c_adap = i2c;
++ priv->cfg = cfg;
++ memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops));
++ fe->tuner_priv = priv;
+
-+ case IPATH_IB_CFG_LINKLATENCY:
-+ ret = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcddrstatus)
-+ & IBA7220_DDRSTAT_LINKLAT_MASK;
-+ goto done;
++ dprintk("type set to %s\n", fe->ops.tuner_ops.info.name);
+
-+ default:
-+ ret = -ENOTSUPP;
-+ goto done;
-+ }
-+ ret = (int)((dd->ipath_ibcddrctrl >> lsb) & maskr);
-+done:
-+ return ret;
++ return fe;
+}
++EXPORT_SYMBOL_GPL(tda827x_attach);
+
-+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;
++MODULE_DESCRIPTION("DVB TDA827x driver");
++MODULE_AUTHOR("Hartmut Hackmann <hartmut.hackmann at t-online.de>");
++MODULE_AUTHOR("Michael Krufky <mkrufky at linuxtv.org>");
++MODULE_LICENSE("GPL");
+
-+ 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;
++/*
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-basic-offset: 8
++ * End:
++ */
+diff --git a/drivers/media/common/tuners/tda827x.h b/drivers/media/common/tuners/tda827x.h
+new file mode 100644
+index 0000000..7850a9a
+--- /dev/null
++++ b/drivers/media/common/tuners/tda827x.h
+@@ -0,0 +1,69 @@
++ /*
++ DVB Driver for Philips tda827x / tda827xa Silicon tuners
+
-+ 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;
++ (c) 2005 Hartmut Hackmann
++ (c) 2007 Michael Krufky
+
-+ 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;
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++
++ GNU General Public License for more details.
++
++ You 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.
+
-+ 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;
++#ifndef __DVB_TDA827X_H__
++#define __DVB_TDA827X_H__
+
-+ 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;
-+}
++#include <linux/i2c.h>
++#include "dvb_frontend.h"
+
-+static void ipath_7220_read_counters(struct ipath_devdata *dd,
-+ struct infinipath_counters *cntrs)
++struct tda827x_config
+{
-+ u64 *counters = (u64 *) cntrs;
-+ int i;
++ /* saa7134 - provided callbacks */
++ int (*init) (struct dvb_frontend *fe);
++ int (*sleep) (struct dvb_frontend *fe);
+
-+ for (i = 0; i < sizeof(*cntrs) / sizeof(u64); i++)
-+ counters[i] = ipath_snap_cntr(dd, i);
-+}
++ /* interface to tda829x driver */
++ unsigned int config;
++ int switch_addr;
++ int (*tuner_callback) (void *dev, int command, int arg);
+
-+/* if we are using MSI, try to fallback to INTx */
-+static int ipath_7220_intr_fallback(struct ipath_devdata *dd)
++ void (*agcf)(struct dvb_frontend *fe);
++};
++
++
++/**
++ * Attach a tda827x tuner to the supplied frontend structure.
++ *
++ * @param fe Frontend to attach to.
++ * @param addr i2c address of the tuner.
++ * @param i2c i2c adapter to use.
++ * @param cfg optional callback function pointers.
++ * @return FE pointer on success, NULL on failure.
++ */
++#if defined(CONFIG_MEDIA_TUNER_TDA827X) || (defined(CONFIG_MEDIA_TUNER_TDA827X_MODULE) && defined(MODULE))
++extern struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe, int addr,
++ struct i2c_adapter *i2c,
++ struct tda827x_config *cfg);
++#else
++static inline struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe,
++ int addr,
++ struct i2c_adapter *i2c,
++ struct tda827x_config *cfg)
+{
-+ 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;
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++ return NULL;
+}
++#endif // CONFIG_MEDIA_TUNER_TDA827X
+
++#endif // __DVB_TDA827X_H__
+diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c
+new file mode 100644
+index 0000000..91204d3
+--- /dev/null
++++ b/drivers/media/common/tuners/tda8290.c
+@@ -0,0 +1,804 @@
+/*
-+ * 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);
-+}
++ i2c tv tuner chip device driver
++ controls the philips tda8290+75 tuner chip combo.
+
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
+
-+/* 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;
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
+
-+ 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();
-+}
++ You 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.
+
-+/*
-+ * _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;
-+ }
++ This "tda8290" module was split apart from the original "tuner" module.
++*/
+
-+ data = which ? madpayload_done : madpayload_start;
-+ ipath_cdbg(PKT, "Sending %s special MADs\n", which?"done":"start");
++#include <linux/i2c.h>
++#include <linux/delay.h>
++#include <linux/videodev.h>
++#include "tuner-i2c.h"
++#include "tda8290.h"
++#include "tda827x.h"
++#include "tda18271.h"
+
-+ 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);
-+}
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
++/* ---------------------------------------------------------------------- */
+
++struct tda8290_priv {
++ struct tuner_i2c_props i2c_props;
+
-+/*
-+ * 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));
++ unsigned char tda8290_easy_mode;
+
-+ 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;
++ unsigned char tda827x_addr;
+
-+ /*
-+ * 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);
-+}
++ unsigned char ver;
++#define TDA8290 1
++#define TDA8295 2
++#define TDA8275 4
++#define TDA8275A 8
++#define TDA18271 16
+
++ struct tda827x_config cfg;
++};
+
-+/*
-+ * 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)
++/*---------------------------------------------------------------------*/
++
++static int tda8290_i2c_bridge(struct dvb_frontend *fe, int close)
+{
-+ /*
-+ * 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));
-+}
++ struct tda8290_priv *priv = fe->analog_demod_priv;
++
++ unsigned char enable[2] = { 0x21, 0xC0 };
++ unsigned char disable[2] = { 0x21, 0x00 };
++ unsigned char *msg;
++
++ if (close) {
++ msg = enable;
++ tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
++ /* let the bridge stabilize */
++ msleep(20);
++ } else {
++ msg = disable;
++ tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
++ }
+
++ return 0;
++}
+
-+static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
++static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close)
+{
-+ int ret = 0;
-+ u32 ltstate = ipath_ib_linkstate(dd, ibcs);
++ struct tda8290_priv *priv = fe->analog_demod_priv;
+
-+ 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;
++ unsigned char enable[2] = { 0x45, 0xc1 };
++ unsigned char disable[2] = { 0x46, 0x00 };
++ unsigned char buf[3] = { 0x45, 0x01, 0x00 };
++ unsigned char *msg;
+
-+ 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);
++ if (close) {
++ msg = enable;
++ tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
++ /* let the bridge stabilize */
++ msleep(20);
+ } 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];
++ msg = disable;
++ tuner_i2c_xfer_send(&priv->i2c_props, msg, 1);
++ tuner_i2c_xfer_recv(&priv->i2c_props, &msg[1], 1);
++
++ buf[2] = msg[1];
++ buf[2] &= ~0x04;
++ tuner_i2c_xfer_send(&priv->i2c_props, buf, 3);
++ msleep(5);
+
-+ ipath_set_relock_poll(dd, ibup);
-+ }
++ msg[1] |= 0x04;
++ tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
+ }
+
-+ if (!ret)
-+ ipath_setup_7220_setextled(dd, ipath_ib_linkstate(dd, ibcs),
-+ ltstate);
-+ return ret;
++ return 0;
+}
+
++/*---------------------------------------------------------------------*/
+
-+/*
-+ * Handle the empirically determined mechanism for auto-negotiation
-+ * of DDR speed with switches.
-+ */
-+static void autoneg_work(struct work_struct *work)
++static void set_audio(struct dvb_frontend *fe,
++ struct analog_parameters *params)
+{
-+ struct ipath_devdata *dd;
-+ u64 startms;
-+ u32 lastlts, i;
++ struct tda8290_priv *priv = fe->analog_demod_priv;
++ char* mode;
+
-+ dd = container_of(work, struct ipath_devdata,
-+ ipath_autoneg_work.work);
++ if (params->std & V4L2_STD_MN) {
++ priv->tda8290_easy_mode = 0x01;
++ mode = "MN";
++ } else if (params->std & V4L2_STD_B) {
++ priv->tda8290_easy_mode = 0x02;
++ mode = "B";
++ } else if (params->std & V4L2_STD_GH) {
++ priv->tda8290_easy_mode = 0x04;
++ mode = "GH";
++ } else if (params->std & V4L2_STD_PAL_I) {
++ priv->tda8290_easy_mode = 0x08;
++ mode = "I";
++ } else if (params->std & V4L2_STD_DK) {
++ priv->tda8290_easy_mode = 0x10;
++ mode = "DK";
++ } else if (params->std & V4L2_STD_SECAM_L) {
++ priv->tda8290_easy_mode = 0x20;
++ mode = "L";
++ } else if (params->std & V4L2_STD_SECAM_LC) {
++ priv->tda8290_easy_mode = 0x40;
++ mode = "LC";
++ } else {
++ priv->tda8290_easy_mode = 0x10;
++ mode = "xx";
++ }
+
-+ startms = jiffies_to_msecs(jiffies);
++ tuner_dbg("setting tda829x to system %s\n", mode);
++}
+
-+ /*
-+ * 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);
-+ }
++static void tda8290_set_params(struct dvb_frontend *fe,
++ struct analog_parameters *params)
++{
++ struct tda8290_priv *priv = fe->analog_demod_priv;
++
++ unsigned char soft_reset[] = { 0x00, 0x00 };
++ unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode };
++ unsigned char expert_mode[] = { 0x01, 0x80 };
++ unsigned char agc_out_on[] = { 0x02, 0x00 };
++ unsigned char gainset_off[] = { 0x28, 0x14 };
++ unsigned char if_agc_spd[] = { 0x0f, 0x88 };
++ unsigned char adc_head_6[] = { 0x05, 0x04 };
++ unsigned char adc_head_9[] = { 0x05, 0x02 };
++ unsigned char adc_head_12[] = { 0x05, 0x01 };
++ unsigned char pll_bw_nom[] = { 0x0d, 0x47 };
++ unsigned char pll_bw_low[] = { 0x0d, 0x27 };
++ unsigned char gainset_2[] = { 0x28, 0x64 };
++ unsigned char agc_rst_on[] = { 0x0e, 0x0b };
++ unsigned char agc_rst_off[] = { 0x0e, 0x09 };
++ unsigned char if_agc_set[] = { 0x0f, 0x81 };
++ unsigned char addr_adc_sat = 0x1a;
++ unsigned char addr_agc_stat = 0x1d;
++ unsigned char addr_pll_stat = 0x1b;
++ unsigned char adc_sat, agc_stat,
++ pll_stat;
++ int i;
+
-+ if (!(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG))
-+ goto done; /* we got there early or told to stop */
++ set_audio(fe, params);
+
-+ /* 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;
++ if (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);
++ msleep(1);
+
-+ ipath_toggle_rclkrls(dd);
++ expert_mode[1] = priv->tda8290_easy_mode + 0x80;
++ tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2);
++ tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2);
++ tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2);
++ if (priv->tda8290_easy_mode & 0x60)
++ tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2);
++ else
++ tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2);
++ tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2);
+
-+ /* 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;
++ tda8290_i2c_bridge(fe, 1);
+
-+ set_speed_fast(dd, IPATH_IB_SDR);
-+ ipath_toggle_rclkrls(dd);
++ if (fe->ops.tuner_ops.set_analog_params)
++ fe->ops.tuner_ops.set_analog_params(fe, params);
+
-+ /*
-+ * 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;
++ for (i = 0; i < 3; i++) {
++ tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
++ tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
++ if (pll_stat & 0x80) {
++ tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1);
++ tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1);
++ tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
++ tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
++ tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat);
++ break;
++ } else {
++ tuner_dbg("tda8290 not locked, no signal?\n");
++ msleep(100);
++ }
++ }
++ /* adjust headroom resp. gain */
++ if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat < 20))) {
++ tuner_dbg("adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d\n",
++ agc_stat, adc_sat, pll_stat & 0x80);
++ tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2);
++ msleep(100);
++ tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
++ tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
++ tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
++ tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
++ if ((agc_stat > 115) || !(pll_stat & 0x80)) {
++ tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n",
++ agc_stat, pll_stat & 0x80);
++ if (priv->cfg.agcf)
++ priv->cfg.agcf(fe);
++ msleep(100);
++ tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
++ tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
++ tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
++ tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
++ if((agc_stat > 115) || !(pll_stat & 0x80)) {
++ tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat);
++ tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2);
++ tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_low, 2);
++ msleep(100);
++ }
++ }
++ }
++
++ /* l/ l' deadlock? */
++ if(priv->tda8290_easy_mode & 0x60) {
++ tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1);
++ tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1);
++ tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
++ tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
++ if ((adc_sat > 20) || !(pll_stat & 0x80)) {
++ tuner_dbg("trying to resolve SECAM L deadlock\n");
++ tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2);
++ msleep(40);
++ tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_off, 2);
+ }
-+ set_speed_fast(dd, dd->ipath_link_speed_enabled);
+ }
++
++ tda8290_i2c_bridge(fe, 0);
++ tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2);
+}
+
++/*---------------------------------------------------------------------*/
+
-+/**
-+ * 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)
++static void tda8295_power(struct dvb_frontend *fe, int enable)
+{
-+ 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;
++ struct tda8290_priv *priv = fe->analog_demod_priv;
++ unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */
+
-+ /* initialize chip-specific variables */
-+ ipath_init_7220_variables(dd);
++ tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
++ tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
++
++ if (enable)
++ buf[1] = 0x01;
++ else
++ buf[1] = 0x03;
++
++ tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
+}
-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;
++static void tda8295_set_easy_mode(struct dvb_frontend *fe, int enable)
++{
++ struct tda8290_priv *priv = fe->analog_demod_priv;
++ unsigned char buf[] = { 0x01, 0x00 };
+
-+ /*
-+ * 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);
++ tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
++ tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
+
-+ 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;
++ if (enable)
++ buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */
++ else
++ buf[1] = 0x00; /* reset active bit */
+
-+ /*
-+ * 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);
++ tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
++}
+
- 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;
++static void tda8295_set_video_std(struct dvb_frontend *fe)
++{
++ struct tda8290_priv *priv = fe->analog_demod_priv;
++ unsigned char buf[] = { 0x00, priv->tda8290_easy_mode };
++
++ tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
++
++ tda8295_set_easy_mode(fe, 1);
++ msleep(20);
++ tda8295_set_easy_mode(fe, 0);
++}
++
++/*---------------------------------------------------------------------*/
+
-+ if (reinit)
-+ ret = init_chip_reset(dd);
++static void tda8295_agc1_out(struct dvb_frontend *fe, int enable)
++{
++ struct tda8290_priv *priv = fe->analog_demod_priv;
++ unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */
++
++ tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
++ tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
++
++ if (enable)
++ buf[1] &= ~0x40;
+ else
-+ ret = init_chip_first(dd);
++ buf[1] |= 0x40;
+
- done:
- return ret;
- }
-
-+static void verify_interrupt(unsigned long opaque)
++ tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
++}
++
++static void tda8295_agc2_out(struct dvb_frontend *fe, int enable)
+{
-+ struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
++ struct tda8290_priv *priv = fe->analog_demod_priv;
++ unsigned char set_gpio_cf[] = { 0x44, 0x00 };
++ unsigned char set_gpio_val[] = { 0x46, 0x00 };
+
-+ if (!dd)
-+ return; /* being torn down */
++ tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_cf[0], 1);
++ tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_cf[1], 1);
++ tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_val[0], 1);
++ tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_val[1], 1);
+
-+ /*
-+ * 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;
-+ }
++ set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */
+
-+ ret = dd->ipath_f_early_init(dd);
-+ if (ret) {
-+ ipath_dev_err(dd, "Early initialization failure\n");
-+ goto done;
++ if (enable) {
++ set_gpio_cf[1] |= 0x01; /* config GPIO_0 as Open Drain Out */
++ set_gpio_val[1] &= 0xfe; /* set GPIO_0 pin low */
+ }
-
-- 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);
++ tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_cf, 2);
++ tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2);
++}
+
- /*
- * 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;
++static int tda8295_has_signal(struct dvb_frontend *fe)
++{
++ struct tda8290_priv *priv = fe->analog_demod_priv;
+
-+ /*
-+ * 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);
++ unsigned char hvpll_stat = 0x26;
++ unsigned char ret;
+
-+ /* 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;
++ tuner_i2c_xfer_send(&priv->i2c_props, &hvpll_stat, 1);
++ tuner_i2c_xfer_recv(&priv->i2c_props, &ret, 1);
++ return (ret & 0x01) ? 65535 : 0;
++}
+
- done:
- if (!ret) {
- *dd->ipath_statusp |= IPATH_STATUS_CHIP_PRESENT;
-@@ -934,6 +1002,20 @@ done:
- 0ULL);
- /* chip is usable; mark it as initialized */
- *dd->ipath_statusp |= IPATH_STATUS_INITTED;
++/*---------------------------------------------------------------------*/
+
-+ /*
-+ * setup to verify we get an interrupt, and fallback
-+ * to an alternate if necessary and possible
-+ */
-+ if (!reinit) {
-+ init_timer(&dd->ipath_intrchk_timer);
-+ dd->ipath_intrchk_timer.function =
-+ verify_interrupt;
-+ dd->ipath_intrchk_timer.data =
-+ (unsigned long) dd;
-+ }
-+ dd->ipath_intrchk_timer.expires = jiffies + HZ/2;
-+ add_timer(&dd->ipath_intrchk_timer);
- } else
- ipath_dev_err(dd, "No interrupts enabled, couldn't "
- "setup interrupt address\n");
-diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
-index 92e58c9..1b58f47 100644
---- a/drivers/infiniband/hw/ipath/ipath_intr.c
-+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
-@@ -1,5 +1,5 @@
- /*
-- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
-+ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
- * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
-@@ -32,6 +32,7 @@
- */
-
- #include <linux/pci.h>
-+#include <linux/delay.h>
-
- #include "ipath_kernel.h"
- #include "ipath_verbs.h"
-@@ -59,9 +60,11 @@ static void ipath_clrpiobuf(struct ipath_devdata *dd, u32 pnum)
- dev_info(&dd->pcidev->dev,
- "Rewrite PIO buffer %u, to recover from parity error\n",
- pnum);
-- *pbuf = dwcnt+1; /* no flush required, since already in freeze */
-- while(--dwcnt)
-- *pbuf++ = 0;
++static void tda8295_set_params(struct dvb_frontend *fe,
++ struct analog_parameters *params)
++{
++ struct tda8290_priv *priv = fe->analog_demod_priv;
+
-+ /* 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);
-- }
++ unsigned char blanking_mode[] = { 0x1d, 0x00 };
++
++ set_audio(fe, params);
++
++ tuner_dbg("%s: freq = %d\n", __func__, params->frequency);
++
++ tda8295_power(fe, 1);
++ tda8295_agc1_out(fe, 1);
++
++ tuner_i2c_xfer_send(&priv->i2c_props, &blanking_mode[0], 1);
++ tuner_i2c_xfer_recv(&priv->i2c_props, &blanking_mode[1], 1);
++
++ tda8295_set_video_std(fe);
++
++ blanking_mode[1] = 0x03;
++ tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2);
++ msleep(20);
++
++ tda8295_i2c_bridge(fe, 1);
++
++ if (fe->ops.tuner_ops.set_analog_params)
++ fe->ops.tuner_ops.set_analog_params(fe, params);
++
++ if (priv->cfg.agcf)
++ priv->cfg.agcf(fe);
++
++ if (tda8295_has_signal(fe))
++ tuner_dbg("tda8295 is locked\n");
+ 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:
++ tuner_dbg("tda8295 not locked, no signal?\n");
++
++ tda8295_i2c_bridge(fe, 0);
++}
++
++/*---------------------------------------------------------------------*/
++
++static int tda8290_has_signal(struct dvb_frontend *fe)
++{
++ struct tda8290_priv *priv = fe->analog_demod_priv;
++
++ unsigned char i2c_get_afc[1] = { 0x1B };
++ unsigned char afc = 0;
++
++ tuner_i2c_xfer_send(&priv->i2c_props, i2c_get_afc, ARRAY_SIZE(i2c_get_afc));
++ tuner_i2c_xfer_recv(&priv->i2c_props, &afc, 1);
++ return (afc & 0x80)? 65535:0;
++}
++
++/*---------------------------------------------------------------------*/
++
++static void tda8290_standby(struct dvb_frontend *fe)
++{
++ struct tda8290_priv *priv = fe->analog_demod_priv;
++
++ unsigned char cb1[] = { 0x30, 0xD0 };
++ unsigned char tda8290_standby[] = { 0x00, 0x02 };
++ unsigned char tda8290_agc_tri[] = { 0x02, 0x20 };
++ struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2};
++
++ tda8290_i2c_bridge(fe, 1);
++ if (priv->ver & TDA8275A)
++ cb1[1] = 0x90;
++ i2c_transfer(priv->i2c_props.adap, &msg, 1);
++ tda8290_i2c_bridge(fe, 0);
++ tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2);
++ tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2);
++}
++
++static void tda8295_standby(struct dvb_frontend *fe)
++{
++ tda8295_agc1_out(fe, 0); /* Put AGC in tri-state */
++
++ tda8295_power(fe, 0);
++}
++
++static void tda8290_init_if(struct dvb_frontend *fe)
++{
++ struct tda8290_priv *priv = fe->analog_demod_priv;
++
++ unsigned char set_VS[] = { 0x30, 0x6F };
++ unsigned char set_GP00_CF[] = { 0x20, 0x01 };
++ unsigned char set_GP01_CF[] = { 0x20, 0x0B };
++
++ if ((priv->cfg.config == 1) || (priv->cfg.config == 2))
++ tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2);
+ 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);
++ tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2);
++ tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2);
++}
+
-+ 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);
++static void tda8295_init_if(struct dvb_frontend *fe)
++{
++ struct tda8290_priv *priv = fe->analog_demod_priv;
+
-+ /*
-+ * 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 */
++ static unsigned char set_adc_ctl[] = { 0x33, 0x14 };
++ static unsigned char set_adc_ctl2[] = { 0x34, 0x00 };
++ static unsigned char set_pll_reg6[] = { 0x3e, 0x63 };
++ static unsigned char set_pll_reg0[] = { 0x38, 0x23 };
++ static unsigned char set_pll_reg7[] = { 0x3f, 0x01 };
++ static unsigned char set_pll_reg10[] = { 0x42, 0x61 };
++ static unsigned char set_gpio_reg0[] = { 0x44, 0x0b };
++
++ tda8295_power(fe, 1);
++
++ tda8295_set_easy_mode(fe, 0);
++ tda8295_set_video_std(fe);
++
++ tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl, 2);
++ tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl2, 2);
++ tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg6, 2);
++ tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg0, 2);
++ tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg7, 2);
++ tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg10, 2);
++ tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_reg0, 2);
++
++ tda8295_agc1_out(fe, 0);
++ tda8295_agc2_out(fe, 0);
++}
++
++static void tda8290_init_tuner(struct dvb_frontend *fe)
++{
++ struct tda8290_priv *priv = fe->analog_demod_priv;
++ unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf,
++ 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 };
++ unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b,
++ 0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b };
++ struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0,
++ .buf=tda8275_init, .len = 14};
++ if (priv->ver & TDA8275A)
++ msg.buf = tda8275a_init;
++
++ tda8290_i2c_bridge(fe, 1);
++ i2c_transfer(priv->i2c_props.adap, &msg, 1);
++ tda8290_i2c_bridge(fe, 0);
++}
+
-+ 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;
++static void tda829x_release(struct dvb_frontend *fe)
++{
++ struct tda8290_priv *priv = fe->analog_demod_priv;
++
++ /* only try to release the tuner if we've
++ * attached it from within this module */
++ if (priv->ver & (TDA18271 | TDA8275 | TDA8275A))
++ if (fe->ops.tuner_ops.release)
++ fe->ops.tuner_ops.release(fe);
++
++ kfree(fe->analog_demod_priv);
++ fe->analog_demod_priv = NULL;
++}
++
++static struct tda18271_config tda829x_tda18271_config = {
++ .gate = TDA18271_GATE_ANALOG,
++};
++
++static int tda829x_find_tuner(struct dvb_frontend *fe)
++{
++ struct tda8290_priv *priv = fe->analog_demod_priv;
++ struct analog_demod_ops *analog_ops = &fe->ops.analog_ops;
++ int i, ret, tuners_found;
++ u32 tuner_addrs;
++ u8 data;
++ struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 };
++
++ if (NULL == analog_ops->i2c_gate_ctrl)
++ return -EINVAL;
++
++ analog_ops->i2c_gate_ctrl(fe, 1);
++
++ /* probe for tuner chip */
++ tuners_found = 0;
++ tuner_addrs = 0;
++ for (i = 0x60; i <= 0x63; i++) {
++ msg.addr = i;
++ ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
++ if (ret == 1) {
++ tuners_found++;
++ tuner_addrs = (tuner_addrs << 8) + i;
++ }
++ }
++ /* if there is more than one tuner, we expect the right one is
++ behind the bridge and we choose the highest address that doesn't
++ give a response now
++ */
++
++ analog_ops->i2c_gate_ctrl(fe, 0);
++
++ if (tuners_found > 1)
++ for (i = 0; i < tuners_found; i++) {
++ msg.addr = tuner_addrs & 0xff;
++ ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
++ if (ret == 1)
++ tuner_addrs = tuner_addrs >> 8;
++ else
++ break;
+ }
++
++ if (tuner_addrs == 0) {
++ tuner_addrs = 0x60;
++ tuner_info("could not clearly identify tuner address, "
++ "defaulting to %x\n", tuner_addrs);
++ } else {
++ tuner_addrs = tuner_addrs & 0xff;
++ tuner_info("setting tuner address to %x\n", tuner_addrs);
+ }
++ priv->tda827x_addr = tuner_addrs;
++ msg.addr = tuner_addrs;
+
-+ 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);
-+ }
++ analog_ops->i2c_gate_ctrl(fe, 1);
++ ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
+
-+ /*
-+ * 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));
++ if (ret != 1) {
++ tuner_warn("tuner access failed!\n");
++ return -EREMOTEIO;
++ }
++
++ if ((data == 0x83) || (data == 0x84)) {
++ priv->ver |= TDA18271;
++ dvb_attach(tda18271_attach, fe, priv->tda827x_addr,
++ priv->i2c_props.adap, &tda829x_tda18271_config);
++ } else {
++ if ((data & 0x3c) == 0)
++ priv->ver |= TDA8275;
+ 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);
- }
++ priv->ver |= TDA8275A;
+
- 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))
++ dvb_attach(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);
+
-+ mask = INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
-+ INFINIPATH_E_PKTERRS | INFINIPATH_E_SDMADISABLED;
++ if (fe->ops.tuner_ops.sleep)
++ fe->ops.tuner_ops.sleep(fe);
+
-+ /* if we're in debug, then don't mask SDMADISABLED msgs */
-+ if (ipath_debug & __IPATH_DBG)
-+ mask &= ~INFINIPATH_E_SDMADISABLED;
++ analog_ops->i2c_gate_ctrl(fe, 0);
+
-+ 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)
++ return 0;
++}
++
++static int tda8290_probe(struct tuner_i2c_props *i2c_props)
+{
-+ unsigned long flags;
-+ int expected;
++#define TDA8290_ID 0x89
++ unsigned char tda8290_id[] = { 0x1f, 0x00 };
+
-+ 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);
++ /* detect tda8290 */
++ tuner_i2c_xfer_send(i2c_props, &tda8290_id[0], 1);
++ tuner_i2c_xfer_recv(i2c_props, &tda8290_id[1], 1);
++
++ if (tda8290_id[1] == TDA8290_ID) {
++ if (debug)
++ printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n",
++ __func__, i2c_adapter_id(i2c_props->adap),
++ i2c_props->addr);
++ return 0;
+ }
-+ 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);
++
++ return -ENODEV;
++}
++
++static int tda8295_probe(struct tuner_i2c_props *i2c_props)
++{
++#define TDA8295_ID 0x8a
++ unsigned char tda8295_id[] = { 0x2f, 0x00 };
++
++ /* detect tda8295 */
++ tuner_i2c_xfer_send(i2c_props, &tda8295_id[0], 1);
++ tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1);
++
++ if (tda8295_id[1] == TDA8295_ID) {
++ if (debug)
++ printk(KERN_DEBUG "%s: tda8295 detected @ %d-%04x\n",
++ __func__, i2c_adapter_id(i2c_props->adap),
++ i2c_props->addr);
++ return 0;
+ }
+
-+ 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);
++ return -ENODEV;
+}
+
-+static void handle_sdma_intr(struct ipath_devdata *dd, u64 istat)
++static struct analog_demod_ops tda8290_ops = {
++ .set_params = tda8290_set_params,
++ .has_signal = tda8290_has_signal,
++ .standby = tda8290_standby,
++ .release = tda829x_release,
++ .i2c_gate_ctrl = tda8290_i2c_bridge,
++};
++
++static struct analog_demod_ops tda8295_ops = {
++ .set_params = tda8295_set_params,
++ .has_signal = tda8295_has_signal,
++ .standby = tda8295_standby,
++ .release = tda829x_release,
++ .i2c_gate_ctrl = tda8295_i2c_bridge,
++};
++
++struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
++ struct i2c_adapter *i2c_adap, u8 i2c_addr,
++ struct tda829x_config *cfg)
+{
-+ unsigned long flags;
-+ int expected;
++ struct tda8290_priv *priv = NULL;
++ char *name;
+
-+ if ((istat & INFINIPATH_I_SDMAINT) &&
-+ !test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
-+ ipath_sdma_intr(dd);
++ priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL);
++ if (priv == NULL)
++ return NULL;
++ fe->analog_demod_priv = priv;
+
-+ 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);
++ 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;
++ }
++
++ if (tda8290_probe(&priv->i2c_props) == 0) {
++ priv->ver = TDA8290;
++ memcpy(&fe->ops.analog_ops, &tda8290_ops,
++ sizeof(struct analog_demod_ops));
++ }
++
++ if (tda8295_probe(&priv->i2c_props) == 0) {
++ priv->ver = TDA8295;
++ memcpy(&fe->ops.analog_ops, &tda8295_ops,
++ sizeof(struct analog_demod_ops));
++ }
++
++ if ((!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) &&
++ (tda829x_find_tuner(fe) < 0))
++ goto fail;
++
++ switch (priv->ver) {
++ case TDA8290:
++ name = "tda8290";
++ break;
++ case TDA8295:
++ name = "tda8295";
++ break;
++ case TDA8290 | TDA8275:
++ name = "tda8290+75";
++ break;
++ case TDA8295 | TDA8275:
++ name = "tda8295+75";
++ break;
++ case TDA8290 | TDA8275A:
++ name = "tda8290+75a";
++ break;
++ case TDA8295 | TDA8275A:
++ name = "tda8295+75a";
++ break;
++ case TDA8290 | TDA18271:
++ name = "tda8290+18271";
++ break;
++ case TDA8295 | TDA18271:
++ name = "tda8295+18271";
++ break;
++ default:
++ goto fail;
+ }
++ tuner_info("type set to %s\n", name);
++
++ fe->ops.analog_ops.info.name = name;
++
++ if (priv->ver & TDA8290) {
++ tda8290_init_tuner(fe);
++ tda8290_init_if(fe);
++ } else if (priv->ver & TDA8295)
++ tda8295_init_if(fe);
++
++ return fe;
++
++fail:
++ tda829x_release(fe);
++ return NULL;
+}
++EXPORT_SYMBOL_GPL(tda829x_attach);
+
-+static int handle_hdrq_full(struct ipath_devdata *dd)
++int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
+{
-+ int chkerrpkts = 0;
-+ u32 hd, tl;
-+ u32 i;
++ struct tuner_i2c_props i2c_props = {
++ .adap = i2c_adap,
++ .addr = i2c_addr,
++ };
+
-+ ipath_stats.sps_hdrqfull++;
-+ for (i = 0; i < dd->ipath_cfgports; i++) {
-+ struct ipath_portdata *pd = dd->ipath_pd[i];
++ unsigned char soft_reset[] = { 0x00, 0x00 };
++ unsigned char easy_mode_b[] = { 0x01, 0x02 };
++ unsigned char easy_mode_g[] = { 0x01, 0x04 };
++ unsigned char restore_9886[] = { 0x00, 0xd6, 0x30 };
++ unsigned char addr_dto_lsb = 0x07;
++ unsigned char data;
++#define PROBE_BUFFER_SIZE 8
++ unsigned char buf[PROBE_BUFFER_SIZE];
++ int 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;
-+ }
++ /* rule out tda9887, which would return the same byte repeatedly */
++ tuner_i2c_xfer_send(&i2c_props, soft_reset, 1);
++ tuner_i2c_xfer_recv(&i2c_props, buf, PROBE_BUFFER_SIZE);
++ for (i = 1; i < PROBE_BUFFER_SIZE; i++) {
++ if (buf[i] != buf[0])
++ break;
++ }
+
-+ /* Skip if user context is not open */
-+ if (!pd || !pd->port_cnt)
-+ continue;
++ /* all bytes are equal, not a tda829x - probably a tda9887 */
++ if (i == PROBE_BUFFER_SIZE)
++ return -ENODEV;
+
-+ /* 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;
++ if ((tda8290_probe(&i2c_props) == 0) ||
++ (tda8295_probe(&i2c_props) == 0))
++ return 0;
+
-+ 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);
++ /* fall back to old probing method */
++ tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2);
++ tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
++ tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1);
++ tuner_i2c_xfer_recv(&i2c_props, &data, 1);
++ if (data == 0) {
++ tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2);
++ tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
++ tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1);
++ tuner_i2c_xfer_recv(&i2c_props, &data, 1);
++ if (data == 0x7b) {
++ return 0;
+ }
+ }
++ tuner_i2c_xfer_send(&i2c_props, restore_9886, 3);
++ return -ENODEV;
++}
++EXPORT_SYMBOL_GPL(tda829x_probe);
+
-+ return chkerrpkts;
++MODULE_DESCRIPTION("Philips/NXP TDA8290/TDA8295 analog IF demodulator driver");
++MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky");
++MODULE_LICENSE("GPL");
++
++/*
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-basic-offset: 8
++ * End:
++ */
+diff --git a/drivers/media/common/tuners/tda8290.h b/drivers/media/common/tuners/tda8290.h
+new file mode 100644
+index 0000000..aa074f3
+--- /dev/null
++++ b/drivers/media/common/tuners/tda8290.h
+@@ -0,0 +1,57 @@
++/*
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You 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 __TDA8290_H__
++#define __TDA8290_H__
++
++#include <linux/i2c.h>
++#include "dvb_frontend.h"
++
++struct tda829x_config {
++ unsigned int lna_cfg;
++ int (*tuner_callback) (void *dev, int command, int arg);
++
++ unsigned int probe_tuner:1;
++#define TDA829X_PROBE_TUNER 0
++#define TDA829X_DONT_PROBE 1
++};
++
++#if defined(CONFIG_MEDIA_TUNER_TDA8290) || (defined(CONFIG_MEDIA_TUNER_TDA8290_MODULE) && defined(MODULE))
++extern int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr);
++
++extern struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
++ struct i2c_adapter *i2c_adap,
++ u8 i2c_addr,
++ struct tda829x_config *cfg);
++#else
++static inline int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
++{
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++ return -EINVAL;
+}
+
- 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);
++static inline struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
++ struct i2c_adapter *i2c_adap,
++ u8 i2c_addr,
++ struct tda829x_config *cfg)
++{
++ printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
++ __func__);
++ return NULL;
++}
++#endif
+
- 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;
++#endif /* __TDA8290_H__ */
+diff --git a/drivers/media/common/tuners/tda9887.c b/drivers/media/common/tuners/tda9887.c
+new file mode 100644
+index 0000000..a0545ba
+--- /dev/null
++++ b/drivers/media/common/tuners/tda9887.c
+@@ -0,0 +1,717 @@
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/i2c.h>
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/videodev.h>
++#include <media/v4l2-common.h>
++#include <media/tuner.h>
++#include "tuner-i2c.h"
++#include "tda9887.h"
+
- 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);
++
++/* Chips:
++ TDA9885 (PAL, NTSC)
++ TDA9886 (PAL, SECAM, NTSC)
++ TDA9887 (PAL, SECAM, NTSC, FM Radio)
++
++ Used as part of several tuners
++*/
++
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "enable verbose debug messages");
++
++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;
++ unsigned int mode;
++ unsigned int audmode;
++ v4l2_std_id std;
++};
++
++/* ---------------------------------------------------------------------- */
++
++#define UNSET (-1U)
++
++struct tvnorm {
++ v4l2_std_id std;
++ char *name;
++ unsigned char b;
++ unsigned char c;
++ unsigned char e;
++};
++
++/* ---------------------------------------------------------------------- */
++
++//
++// TDA defines
++//
++
++//// first reg (b)
++#define cVideoTrapBypassOFF 0x00 // bit b0
++#define cVideoTrapBypassON 0x01 // bit b0
++
++#define cAutoMuteFmInactive 0x00 // bit b1
++#define cAutoMuteFmActive 0x02 // bit b1
++
++#define cIntercarrier 0x00 // bit b2
++#define cQSS 0x04 // bit b2
++
++#define cPositiveAmTV 0x00 // bit b3:4
++#define cFmRadio 0x08 // bit b3:4
++#define cNegativeFmTV 0x10 // bit b3:4
++
++
++#define cForcedMuteAudioON 0x20 // bit b5
++#define cForcedMuteAudioOFF 0x00 // bit b5
++
++#define cOutputPort1Active 0x00 // bit b6
++#define cOutputPort1Inactive 0x40 // bit b6
++
++#define cOutputPort2Active 0x00 // bit b7
++#define cOutputPort2Inactive 0x80 // bit b7
++
++
++//// second reg (c)
++#define cDeemphasisOFF 0x00 // bit c5
++#define cDeemphasisON 0x20 // bit c5
++
++#define cDeemphasis75 0x00 // bit c6
++#define cDeemphasis50 0x40 // bit c6
++
++#define cAudioGain0 0x00 // bit c7
++#define cAudioGain6 0x80 // bit c7
++
++#define cTopMask 0x1f // bit c0:4
++#define cTopDefault 0x10 // bit c0:4
++
++//// third reg (e)
++#define cAudioIF_4_5 0x00 // bit e0:1
++#define cAudioIF_5_5 0x01 // bit e0:1
++#define cAudioIF_6_0 0x02 // bit e0:1
++#define cAudioIF_6_5 0x03 // bit e0:1
++
++
++#define cVideoIFMask 0x1c // bit e2:4
++/* Video IF selection in TV Mode (bit B3=0) */
++#define cVideoIF_58_75 0x00 // bit e2:4
++#define cVideoIF_45_75 0x04 // bit e2:4
++#define cVideoIF_38_90 0x08 // bit e2:4
++#define cVideoIF_38_00 0x0C // bit e2:4
++#define cVideoIF_33_90 0x10 // bit e2:4
++#define cVideoIF_33_40 0x14 // bit e2:4
++#define cRadioIF_45_75 0x18 // bit e2:4
++#define cRadioIF_38_90 0x1C // bit e2:4
++
++/* IF1 selection in Radio Mode (bit B3=1) */
++#define cRadioIF_33_30 0x00 // bit e2,4 (also 0x10,0x14)
++#define cRadioIF_41_30 0x04 // bit e2,4
++
++/* Output of AFC pin in radio mode when bit E7=1 */
++#define cRadioAGC_SIF 0x00 // bit e3
++#define cRadioAGC_FM 0x08 // bit e3
++
++#define cTunerGainNormal 0x00 // bit e5
++#define cTunerGainLow 0x20 // bit e5
++
++#define cGating_18 0x00 // bit e6
++#define cGating_36 0x40 // bit e6
++
++#define cAgcOutON 0x80 // bit e7
++#define cAgcOutOFF 0x00 // bit e7
++
++/* ---------------------------------------------------------------------- */
++
++static struct tvnorm tvnorms[] = {
++ {
++ .std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N,
++ .name = "PAL-BGHN",
++ .b = ( cNegativeFmTV |
++ cQSS ),
++ .c = ( cDeemphasisON |
++ cDeemphasis50 |
++ cTopDefault),
++ .e = ( cGating_36 |
++ cAudioIF_5_5 |
++ cVideoIF_38_90 ),
++ },{
++ .std = V4L2_STD_PAL_I,
++ .name = "PAL-I",
++ .b = ( cNegativeFmTV |
++ cQSS ),
++ .c = ( cDeemphasisON |
++ cDeemphasis50 |
++ cTopDefault),
++ .e = ( cGating_36 |
++ cAudioIF_6_0 |
++ cVideoIF_38_90 ),
++ },{
++ .std = V4L2_STD_PAL_DK,
++ .name = "PAL-DK",
++ .b = ( cNegativeFmTV |
++ cQSS ),
++ .c = ( cDeemphasisON |
++ cDeemphasis50 |
++ cTopDefault),
++ .e = ( cGating_36 |
++ cAudioIF_6_5 |
++ cVideoIF_38_90 ),
++ },{
++ .std = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc,
++ .name = "PAL-M/Nc",
++ .b = ( cNegativeFmTV |
++ cQSS ),
++ .c = ( cDeemphasisON |
++ cDeemphasis75 |
++ cTopDefault),
++ .e = ( cGating_36 |
++ cAudioIF_4_5 |
++ cVideoIF_45_75 ),
++ },{
++ .std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
++ .name = "SECAM-BGH",
++ .b = ( cPositiveAmTV |
++ cQSS ),
++ .c = ( cTopDefault),
++ .e = ( cGating_36 |
++ cAudioIF_5_5 |
++ cVideoIF_38_90 ),
++ },{
++ .std = V4L2_STD_SECAM_L,
++ .name = "SECAM-L",
++ .b = ( cPositiveAmTV |
++ cQSS ),
++ .c = ( cTopDefault),
++ .e = ( cGating_36 |
++ cAudioIF_6_5 |
++ cVideoIF_38_90 ),
++ },{
++ .std = V4L2_STD_SECAM_LC,
++ .name = "SECAM-L'",
++ .b = ( cOutputPort2Inactive |
++ cPositiveAmTV |
++ cQSS ),
++ .c = ( cTopDefault),
++ .e = ( cGating_36 |
++ cAudioIF_6_5 |
++ cVideoIF_33_90 ),
++ },{
++ .std = V4L2_STD_SECAM_DK,
++ .name = "SECAM-DK",
++ .b = ( cNegativeFmTV |
++ cQSS ),
++ .c = ( cDeemphasisON |
++ cDeemphasis50 |
++ cTopDefault),
++ .e = ( cGating_36 |
++ cAudioIF_6_5 |
++ cVideoIF_38_90 ),
++ },{
++ .std = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
++ .name = "NTSC-M",
++ .b = ( cNegativeFmTV |
++ cQSS ),
++ .c = ( cDeemphasisON |
++ cDeemphasis75 |
++ cTopDefault),
++ .e = ( cGating_36 |
++ cAudioIF_4_5 |
++ cVideoIF_45_75 ),
++ },{
++ .std = V4L2_STD_NTSC_M_JP,
++ .name = "NTSC-M-JP",
++ .b = ( cNegativeFmTV |
++ cQSS ),
++ .c = ( cDeemphasisON |
++ cDeemphasis50 |
++ cTopDefault),
++ .e = ( cGating_36 |
++ cAudioIF_4_5 |
++ cVideoIF_58_75 ),
+ }
++};
+
-+ /* 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;
++static struct tvnorm radio_stereo = {
++ .name = "Radio Stereo",
++ .b = ( cFmRadio |
++ cQSS ),
++ .c = ( cDeemphasisOFF |
++ cAudioGain6 |
++ cTopDefault),
++ .e = ( cTunerGainLow |
++ cAudioIF_5_5 |
++ cRadioIF_38_90 ),
++};
++
++static struct tvnorm radio_mono = {
++ .name = "Radio Mono",
++ .b = ( cFmRadio |
++ cQSS ),
++ .c = ( cDeemphasisON |
++ cDeemphasis75 |
++ cTopDefault),
++ .e = ( cTunerGainLow |
++ cAudioIF_5_5 |
++ cRadioIF_38_90 ),
++};
+
-+ /* 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];
++static void dump_read_message(struct dvb_frontend *fe, unsigned char *buf)
++{
++ struct tda9887_priv *priv = fe->analog_demod_priv;
+
- if (portr & (1 << i) && pd && pd->port_cnt) {
- if (test_and_clear_bit(IPATH_PORT_WAITING_RCV,
- &pd->port_flag)) {
-@@ -988,7 +1107,7 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
- }
- if (rcvdint) {
- /* only want to take one interrupt, so turn off the rcv
-- * interrupt for all the ports that we did the wakeup on
-+ * interrupt for all the ports that we set the rcv_waiting
- * (but never for kernel port)
- */
- ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
-@@ -999,12 +1118,11 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
- irqreturn_t ipath_intr(int irq, void *data)
- {
- struct ipath_devdata *dd = data;
-- u32 istat, chk0rcv = 0;
-+ u64 istat, chk0rcv = 0;
- ipath_err_t estat = 0;
- irqreturn_t ret;
- static unsigned unexpected = 0;
-- static const u32 port0rbits = (1U<<INFINIPATH_I_RCVAVAIL_SHIFT) |
-- (1U<<INFINIPATH_I_RCVURG_SHIFT);
-+ u64 kportrbits;
-
- ipath_stats.sps_ints++;
-
-@@ -1053,17 +1171,17 @@ irqreturn_t ipath_intr(int irq, void *data)
-
- if (unlikely(istat & ~dd->ipath_i_bitsextant))
- ipath_dev_err(dd,
-- "interrupt with unknown interrupts %x set\n",
-- istat & (u32) ~ dd->ipath_i_bitsextant);
-- else
-- ipath_cdbg(VERBOSE, "intr stat=0x%x\n", istat);
-+ "interrupt with unknown interrupts %Lx set\n",
-+ istat & ~dd->ipath_i_bitsextant);
-+ else if (istat & ~INFINIPATH_I_ERROR) /* errors do own printing */
-+ ipath_cdbg(VERBOSE, "intr stat=0x%Lx\n", istat);
-
-- if (unlikely(istat & INFINIPATH_I_ERROR)) {
-+ if (istat & INFINIPATH_I_ERROR) {
- ipath_stats.sps_errints++;
- estat = ipath_read_kreg64(dd,
- dd->ipath_kregs->kr_errorstatus);
- if (!estat)
-- dev_info(&dd->pcidev->dev, "error interrupt (%x), "
-+ dev_info(&dd->pcidev->dev, "error interrupt (%Lx), "
- "but no error bits set!\n", istat);
- else if (estat == -1LL)
- /*
-@@ -1073,9 +1191,7 @@ irqreturn_t ipath_intr(int irq, void *data)
- ipath_dev_err(dd, "Read of error status failed "
- "(all bits set); ignoring\n");
- else
-- if (handle_errors(dd, estat))
-- /* force calling ipath_kreceive() */
-- chk0rcv = 1;
-+ chk0rcv |= handle_errors(dd, estat);
- }
-
- if (istat & INFINIPATH_I_GPIO) {
-@@ -1093,8 +1209,7 @@ irqreturn_t ipath_intr(int irq, void *data)
-
- gpiostatus = ipath_read_kreg32(
- dd, dd->ipath_kregs->kr_gpio_status);
-- /* First the error-counter case.
-- */
-+ /* First the error-counter case. */
- if ((gpiostatus & IPATH_GPIO_ERRINTR_MASK) &&
- (dd->ipath_flags & IPATH_GPIO_ERRINTRS)) {
- /* want to clear the bits we see asserted. */
-@@ -1156,7 +1271,6 @@ irqreturn_t ipath_intr(int irq, void *data)
- (u64) to_clear);
- }
- }
-- chk0rcv |= istat & port0rbits;
-
- /*
- * Clear the interrupt bits we found set, unless they are receive
-@@ -1169,22 +1283,25 @@ irqreturn_t ipath_intr(int irq, void *data)
- ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, istat);
-
- /*
-- * handle port0 receive before checking for pio buffers available,
-- * since receives can overflow; piobuf waiters can afford a few
-- * extra cycles, since they were waiting anyway, and user's waiting
-- * for receive are at the bottom.
-+ * Handle kernel receive queues before checking for pio buffers
-+ * available since receives can overflow; piobuf waiters can afford
-+ * a few extra cycles, since they were waiting anyway, and user's
-+ * waiting for receive are at the bottom.
- */
-- if (chk0rcv) {
-+ kportrbits = (1ULL << dd->ipath_i_rcvavail_shift) |
-+ (1ULL << dd->ipath_i_rcvurg_shift);
-+ if (chk0rcv || (istat & kportrbits)) {
-+ istat &= ~kportrbits;
- ipath_kreceive(dd->ipath_pd[0]);
-- istat &= ~port0rbits;
- }
-
-- if (istat & ((dd->ipath_i_rcvavail_mask <<
-- INFINIPATH_I_RCVAVAIL_SHIFT)
-- | (dd->ipath_i_rcvurg_mask <<
-- INFINIPATH_I_RCVURG_SHIFT)))
-+ if (istat & ((dd->ipath_i_rcvavail_mask << dd->ipath_i_rcvavail_shift) |
-+ (dd->ipath_i_rcvurg_mask << dd->ipath_i_rcvurg_shift)))
- handle_urcv(dd, istat);
-
-+ if (istat & (INFINIPATH_I_SDMAINT | INFINIPATH_I_SDMADISABLED))
-+ handle_sdma_intr(dd, istat);
++ static char *afc[16] = {
++ "- 12.5 kHz",
++ "- 37.5 kHz",
++ "- 62.5 kHz",
++ "- 87.5 kHz",
++ "-112.5 kHz",
++ "-137.5 kHz",
++ "-162.5 kHz",
++ "-187.5 kHz [min]",
++ "+187.5 kHz [max]",
++ "+162.5 kHz",
++ "+137.5 kHz",
++ "+112.5 kHz",
++ "+ 87.5 kHz",
++ "+ 62.5 kHz",
++ "+ 37.5 kHz",
++ "+ 12.5 kHz",
++ };
++ tuner_info("read: 0x%2x\n", buf[0]);
++ tuner_info(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no");
++ tuner_info(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]);
++ tuner_info(" fmif level : %s\n", (buf[0] & 0x20) ? "high" : "low");
++ tuner_info(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out");
++ tuner_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low");
++}
+
- 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);
++static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf)
++{
++ struct tda9887_priv *priv = fe->analog_demod_priv;
++
++ static char *sound[4] = {
++ "AM/TV",
++ "FM/radio",
++ "FM/TV",
++ "FM/radio"
++ };
++ static char *adjust[32] = {
++ "-16", "-15", "-14", "-13", "-12", "-11", "-10", "-9",
++ "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1",
++ "0", "+1", "+2", "+3", "+4", "+5", "+6", "+7",
++ "+8", "+9", "+10", "+11", "+12", "+13", "+14", "+15"
++ };
++ static char *deemph[4] = {
++ "no", "no", "75", "50"
++ };
++ static char *carrier[4] = {
++ "4.5 MHz",
++ "5.5 MHz",
++ "6.0 MHz",
++ "6.5 MHz / AM"
++ };
++ static char *vif[8] = {
++ "58.75 MHz",
++ "45.75 MHz",
++ "38.9 MHz",
++ "38.0 MHz",
++ "33.9 MHz",
++ "33.4 MHz",
++ "45.75 MHz + pin13",
++ "38.9 MHz + pin13",
++ };
++ static char *rif[4] = {
++ "44 MHz",
++ "52 MHz",
++ "52 MHz",
++ "44 MHz",
++ };
++
++ tuner_info("write: byte B 0x%02x\n", buf[1]);
++ tuner_info(" B0 video mode : %s\n",
++ (buf[1] & 0x01) ? "video trap" : "sound trap");
++ tuner_info(" B1 auto mute fm : %s\n",
++ (buf[1] & 0x02) ? "yes" : "no");
++ tuner_info(" B2 carrier mode : %s\n",
++ (buf[1] & 0x04) ? "QSS" : "Intercarrier");
++ tuner_info(" B3-4 tv sound/radio : %s\n",
++ sound[(buf[1] & 0x18) >> 3]);
++ tuner_info(" B5 force mute audio: %s\n",
++ (buf[1] & 0x20) ? "yes" : "no");
++ tuner_info(" B6 output port 1 : %s\n",
++ (buf[1] & 0x40) ? "high (inactive)" : "low (active)");
++ tuner_info(" B7 output port 2 : %s\n",
++ (buf[1] & 0x80) ? "high (inactive)" : "low (active)");
++
++ tuner_info("write: byte C 0x%02x\n", buf[2]);
++ tuner_info(" C0-4 top adjustment : %s dB\n",
++ adjust[buf[2] & 0x1f]);
++ tuner_info(" C5-6 de-emphasis : %s\n",
++ deemph[(buf[2] & 0x60) >> 5]);
++ tuner_info(" C7 audio gain : %s\n",
++ (buf[2] & 0x80) ? "-6" : "0");
++
++ tuner_info("write: byte E 0x%02x\n", buf[3]);
++ tuner_info(" E0-1 sound carrier : %s\n",
++ carrier[(buf[3] & 0x03)]);
++ tuner_info(" E6 l pll gating : %s\n",
++ (buf[3] & 0x40) ? "36" : "13");
++
++ if (buf[1] & 0x08) {
++ /* radio */
++ tuner_info(" E2-4 video if : %s\n",
++ rif[(buf[3] & 0x0c) >> 2]);
++ tuner_info(" E7 vif agc output : %s\n",
++ (buf[3] & 0x80)
++ ? ((buf[3] & 0x10) ? "fm-agc radio" :
++ "sif-agc radio")
++ : "fm radio carrier afc");
++ } else {
++ /* video */
++ tuner_info(" E2-4 video if : %s\n",
++ vif[(buf[3] & 0x1c) >> 2]);
++ tuner_info(" E5 tuner gain : %s\n",
++ (buf[3] & 0x80)
++ ? ((buf[3] & 0x20) ? "external" : "normal")
++ : ((buf[3] & 0x20) ? "minimum" : "normal"));
++ tuner_info(" E7 vif agc output : %s\n",
++ (buf[3] & 0x80) ? ((buf[3] & 0x20)
++ ? "pin3 port, pin22 vif agc out"
++ : "pin22 port, pin3 vif acg ext in")
++ : "pin3+pin22 port");
++ }
++ tuner_info("--\n");
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int tda9887_set_tvnorm(struct dvb_frontend *fe)
++{
++ struct tda9887_priv *priv = fe->analog_demod_priv;
++ struct tvnorm *norm = NULL;
++ char *buf = priv->data;
++ int i;
++
++ if (priv->mode == V4L2_TUNER_RADIO) {
++ if (priv->audmode == V4L2_TUNER_MODE_MONO)
++ norm = &radio_mono;
+ else
-+ ipath_dbg("unexpected BUFAVAIL intr\n");
- }
-
- ret = IRQ_HANDLED;
-diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
-index ecf3f7f..202337a 100644
---- a/drivers/infiniband/hw/ipath/ipath_kernel.h
-+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
-@@ -1,7 +1,7 @@
- #ifndef _IPATH_KERNEL_H
- #define _IPATH_KERNEL_H
- /*
-- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
-+ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
- * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
-@@ -42,6 +42,8 @@
- #include <linux/pci.h>
- #include <linux/dma-mapping.h>
- #include <linux/mutex.h>
-+#include <linux/list.h>
-+#include <linux/scatterlist.h>
- #include <asm/io.h>
- #include <rdma/ib_verbs.h>
-
-@@ -175,9 +177,13 @@ struct ipath_portdata {
- u16 poll_type;
- /* port rcvhdrq head offset */
- u32 port_head;
-+ /* receive packet sequence counter */
-+ u32 port_seq_cnt;
- };
-
- struct sk_buff;
-+struct ipath_sge_state;
-+struct ipath_verbs_txreq;
-
- /*
- * control information for layered drivers
-@@ -191,6 +197,40 @@ struct ipath_skbinfo {
- dma_addr_t phys;
- };
-
-+struct ipath_sdma_txreq {
-+ int flags;
-+ int sg_count;
-+ union {
-+ struct scatterlist *sg;
-+ void *map_addr;
++ norm = &radio_stereo;
++ } else {
++ for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
++ if (tvnorms[i].std & priv->std) {
++ norm = tvnorms+i;
++ break;
++ }
++ }
++ }
++ if (NULL == norm) {
++ tuner_dbg("Unsupported tvnorm entry - audio muted\n");
++ return -1;
++ }
++
++ tuner_dbg("configure for: %s\n", norm->name);
++ buf[1] = norm->b;
++ buf[2] = norm->c;
++ buf[3] = norm->e;
++ return 0;
++}
++
++static unsigned int port1 = UNSET;
++static unsigned int port2 = UNSET;
++static unsigned int qss = UNSET;
++static unsigned int adjust = UNSET;
++
++module_param(port1, int, 0644);
++module_param(port2, int, 0644);
++module_param(qss, int, 0644);
++module_param(adjust, int, 0644);
++
++static int tda9887_set_insmod(struct dvb_frontend *fe)
++{
++ struct tda9887_priv *priv = fe->analog_demod_priv;
++ char *buf = priv->data;
++
++ if (UNSET != port1) {
++ if (port1)
++ buf[1] |= cOutputPort1Inactive;
++ else
++ buf[1] &= ~cOutputPort1Inactive;
++ }
++ if (UNSET != port2) {
++ if (port2)
++ buf[1] |= cOutputPort2Inactive;
++ else
++ buf[1] &= ~cOutputPort2Inactive;
++ }
++
++ if (UNSET != qss) {
++ if (qss)
++ buf[1] |= cQSS;
++ else
++ buf[1] &= ~cQSS;
++ }
++
++ if (adjust >= 0x00 && adjust < 0x20) {
++ buf[2] &= ~cTopMask;
++ buf[2] |= adjust;
++ }
++ return 0;
++}
++
++static int tda9887_do_config(struct dvb_frontend *fe)
++{
++ struct tda9887_priv *priv = fe->analog_demod_priv;
++ char *buf = priv->data;
++
++ if (priv->config & TDA9887_PORT1_ACTIVE)
++ buf[1] &= ~cOutputPort1Inactive;
++ if (priv->config & TDA9887_PORT1_INACTIVE)
++ buf[1] |= cOutputPort1Inactive;
++ if (priv->config & TDA9887_PORT2_ACTIVE)
++ buf[1] &= ~cOutputPort2Inactive;
++ if (priv->config & TDA9887_PORT2_INACTIVE)
++ buf[1] |= cOutputPort2Inactive;
++
++ if (priv->config & TDA9887_QSS)
++ buf[1] |= cQSS;
++ if (priv->config & TDA9887_INTERCARRIER)
++ buf[1] &= ~cQSS;
++
++ if (priv->config & TDA9887_AUTOMUTE)
++ buf[1] |= cAutoMuteFmActive;
++ if (priv->config & TDA9887_DEEMPHASIS_MASK) {
++ buf[2] &= ~0x60;
++ switch (priv->config & TDA9887_DEEMPHASIS_MASK) {
++ case TDA9887_DEEMPHASIS_NONE:
++ buf[2] |= cDeemphasisOFF;
++ break;
++ case TDA9887_DEEMPHASIS_50:
++ buf[2] |= cDeemphasisON | cDeemphasis50;
++ break;
++ case TDA9887_DEEMPHASIS_75:
++ buf[2] |= cDeemphasisON | cDeemphasis75;
++ break;
++ }
++ }
++ if (priv->config & TDA9887_TOP_SET) {
++ buf[2] &= ~cTopMask;
++ buf[2] |= (priv->config >> 8) & cTopMask;
++ }
++ if ((priv->config & TDA9887_INTERCARRIER_NTSC) &&
++ (priv->std & V4L2_STD_NTSC))
++ buf[1] &= ~cQSS;
++ if (priv->config & TDA9887_GATING_18)
++ buf[3] &= ~cGating_36;
++
++ if (priv->mode == V4L2_TUNER_RADIO) {
++ if (priv->config & TDA9887_RIF_41_3) {
++ buf[3] &= ~cVideoIFMask;
++ buf[3] |= cRadioIF_41_30;
++ }
++ if (priv->config & TDA9887_GAIN_NORMAL)
++ buf[3] &= ~cTunerGainLow;
++ }
++
++ return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int tda9887_status(struct dvb_frontend *fe)
++{
++ struct tda9887_priv *priv = fe->analog_demod_priv;
++ unsigned char buf[1];
++ int rc;
++
++ memset(buf,0,sizeof(buf));
++ if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,buf,1)))
++ tuner_info("i2c i/o error: rc == %d (should be 1)\n", rc);
++ dump_read_message(fe, buf);
++ return 0;
++}
++
++static void tda9887_configure(struct dvb_frontend *fe)
++{
++ struct tda9887_priv *priv = fe->analog_demod_priv;
++ int rc;
++
++ memset(priv->data,0,sizeof(priv->data));
++ tda9887_set_tvnorm(fe);
++
++ /* A note on the port settings:
++ These settings tend to depend on the specifics of the board.
++ By default they are set to inactive (bit value 1) by this driver,
++ overwriting any changes made by the tvnorm. This means that it
++ is the responsibility of the module using the tda9887 to set
++ these values in case of changes in the tvnorm.
++ In many cases port 2 should be made active (0) when selecting
++ SECAM-L, and port 2 should remain inactive (1) for SECAM-L'.
++
++ For the other standards the tda9887 application note says that
++ the ports should be set to active (0), but, again, that may
++ differ depending on the precise hardware configuration.
++ */
++ priv->data[1] |= cOutputPort1Inactive;
++ priv->data[1] |= cOutputPort2Inactive;
++
++ tda9887_do_config(fe);
++ tda9887_set_insmod(fe);
++
++ if (priv->mode == T_STANDBY)
++ priv->data[1] |= cForcedMuteAudioON;
++
++ tuner_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
++ priv->data[1], priv->data[2], priv->data[3]);
++ if (debug > 1)
++ dump_write_message(fe, priv->data);
++
++ if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4)))
++ tuner_info("i2c i/o error: rc == %d (should be 4)\n", rc);
++
++ if (debug > 2) {
++ msleep_interruptible(1000);
++ tda9887_status(fe);
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void tda9887_tuner_status(struct dvb_frontend *fe)
++{
++ struct tda9887_priv *priv = fe->analog_demod_priv;
++ tuner_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n",
++ priv->data[1], priv->data[2], priv->data[3]);
++}
++
++static int tda9887_get_afc(struct dvb_frontend *fe)
++{
++ struct tda9887_priv *priv = fe->analog_demod_priv;
++ static int AFC_BITS_2_kHz[] = {
++ -12500, -37500, -62500, -97500,
++ -112500, -137500, -162500, -187500,
++ 187500, 162500, 137500, 112500,
++ 97500 , 62500, 37500 , 12500
+ };
-+ 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 */
-+};
++ int afc=0;
++ __u8 reg = 0;
+
-+struct ipath_sdma_desc {
-+ __le64 qw[2];
-+};
++ if (1 == tuner_i2c_xfer_recv(&priv->i2c_props,®,1))
++ afc = AFC_BITS_2_kHz[(reg>>1)&0x0f];
+
-+#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
++ return afc;
++}
+
-+#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
++static void tda9887_standby(struct dvb_frontend *fe)
++{
++ struct tda9887_priv *priv = fe->analog_demod_priv;
+
-+/* max dwords in small buffer packet */
-+#define IPATH_SMALLBUF_DWORDS (dd->ipath_piosize2k >> 2)
++ priv->mode = T_STANDBY;
+
- /*
- * 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;
++ tda9887_configure(fe);
++}
+
-+ 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;
++static void tda9887_set_params(struct dvb_frontend *fe,
++ struct analog_parameters *params)
++{
++ struct tda9887_priv *priv = fe->analog_demod_priv;
+
-+ dma_addr_t ipath_sdma_descq_phys;
-+ volatile __le64 *ipath_sdma_head_dma;
-+ dma_addr_t ipath_sdma_head_phys;
++ priv->mode = params->mode;
++ priv->audmode = params->audmode;
++ priv->std = params->std;
++ tda9887_configure(fe);
++}
+
- unsigned long ipath_ureg_align; /* user register alignment */
-
-+ struct delayed_work ipath_autoneg_work;
-+ wait_queue_head_t ipath_autoneg_wait;
++static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg)
++{
++ struct tda9887_priv *priv = fe->analog_demod_priv;
+
-+ /* HoL blocking / user app forward-progress state */
-+ unsigned ipath_hol_state;
-+ unsigned ipath_hol_next;
-+ struct timer_list ipath_hol_timer;
++ priv->config = *(unsigned int *)priv_cfg;
++ tda9887_configure(fe);
+
- /*
- * 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;
++ return 0;
++}
+
-+ /* unit # of this chip, if present */
-+ int ipath_unit;
++static void tda9887_release(struct dvb_frontend *fe)
++{
++ struct tda9887_priv *priv = fe->analog_demod_priv;
+
- /* 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 */
++ mutex_lock(&tda9887_list_mutex);
+
-+ /*
-+ * 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
++ if (priv)
++ hybrid_tuner_release_state(priv);
+
-+/* 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
++ mutex_unlock(&tda9887_list_mutex);
+
-+/* bit combinations that correspond to abort states */
-+#define IPATH_SDMA_ABORT_NONE 0
-+#define IPATH_SDMA_ABORT_ABORTING (1UL << IPATH_SDMA_ABORTING)
-+#define IPATH_SDMA_ABORT_DISARMED ((1UL << IPATH_SDMA_ABORTING) | \
-+ (1UL << IPATH_SDMA_DISARMED))
-+#define IPATH_SDMA_ABORT_DISABLED ((1UL << IPATH_SDMA_ABORTING) | \
-+ (1UL << IPATH_SDMA_DISABLED))
-+#define IPATH_SDMA_ABORT_ABORTED ((1UL << IPATH_SDMA_ABORTING) | \
-+ (1UL << IPATH_SDMA_DISARMED) | (1UL << IPATH_SDMA_DISABLED))
-+#define IPATH_SDMA_ABORT_MASK ((1UL<<IPATH_SDMA_ABORTING) | \
-+ (1UL << IPATH_SDMA_DISARMED) | (1UL << IPATH_SDMA_DISABLED))
++ fe->analog_demod_priv = NULL;
++}
+
-+#define IPATH_SDMA_BUF_NONE 0
-+#define IPATH_SDMA_BUF_MASK (1UL<<IPATH_SDMA_LAYERBUF)
++static struct analog_demod_ops tda9887_ops = {
++ .info = {
++ .name = "tda9887",
++ },
++ .set_params = tda9887_set_params,
++ .standby = tda9887_standby,
++ .tuner_status = tda9887_tuner_status,
++ .get_afc = tda9887_get_afc,
++ .release = tda9887_release,
++ .set_config = tda9887_set_config,
++};
+
- /* Private data for file operations */
- struct ipath_filedata {
- struct ipath_portdata *pd;
- unsigned subport;
- unsigned tidcursor;
-+ struct ipath_user_sdma_queue *pq;
- };
- extern struct list_head ipath_dev_list;
- extern spinlock_t ipath_devs_lock;
-@@ -718,15 +848,15 @@ extern struct ipath_devdata *ipath_lookup(int unit);
- int ipath_init_chip(struct ipath_devdata *, int);
- int ipath_enable_wc(struct ipath_devdata *dd);
- void ipath_disable_wc(struct ipath_devdata *dd);
--int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp);
-+int ipath_count_units(int *npresentp, int *nupp, int *maxportsp);
- void ipath_shutdown_device(struct ipath_devdata *);
- void ipath_clear_freeze(struct ipath_devdata *);
-
- struct file_operations;
- int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,
-- struct cdev **cdevp, struct class_device **class_devp);
-+ struct cdev **cdevp, struct device **devp);
- void ipath_cdev_cleanup(struct cdev **cdevp,
-- struct class_device **class_devp);
-+ struct device **devp);
-
- int ipath_diag_add(struct ipath_devdata *);
- void ipath_diag_remove(struct ipath_devdata *);
-@@ -741,7 +871,8 @@ struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd, gfp_t);
- extern int ipath_diag_inuse;
-
- irqreturn_t ipath_intr(int irq, void *devid);
--int ipath_decode_err(char *buf, size_t blen, ipath_err_t err);
-+int ipath_decode_err(struct ipath_devdata *dd, char *buf, size_t blen,
-+ ipath_err_t err);
- #if __IPATH_INFO || __IPATH_DBG
- extern const char *ipath_ibcstatus_str[];
- #endif
-@@ -774,6 +905,13 @@ int ipath_set_lid(struct ipath_devdata *, u32, u8);
- int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
- void ipath_enable_armlaunch(struct ipath_devdata *);
- void ipath_disable_armlaunch(struct ipath_devdata *);
-+void ipath_hol_down(struct ipath_devdata *);
-+void ipath_hol_up(struct ipath_devdata *);
-+void ipath_hol_event(unsigned long);
-+void ipath_toggle_rclkrls(struct ipath_devdata *);
-+void ipath_sd7220_clr_ibpar(struct ipath_devdata *);
-+void ipath_set_relock_poll(struct ipath_devdata *, int);
-+void ipath_shutdown_relock_poll(struct ipath_devdata *);
-
- /* for use in system calls, where we want to know device type, etc. */
- #define port_fp(fp) ((struct ipath_filedata *)(fp)->private_data)->pd
-@@ -781,11 +919,15 @@ void ipath_disable_armlaunch(struct ipath_devdata *);
- ((struct ipath_filedata *)(fp)->private_data)->subport
- #define tidcursor_fp(fp) \
- ((struct ipath_filedata *)(fp)->private_data)->tidcursor
-+#define user_sdma_queue_fp(fp) \
-+ ((struct ipath_filedata *)(fp)->private_data)->pq
-
- /*
- * values for ipath_flags
- */
--/* The chip is up and initted */
-+ /* chip can report link latency (IB 1.2) */
-+#define IPATH_HAS_LINK_LATENCY 0x1
-+ /* The chip is up and initted */
- #define IPATH_INITTED 0x2
- /* set if any user code has set kr_rcvhdrsize */
- #define IPATH_RCVHDRSZ_SET 0x4
-@@ -809,6 +951,8 @@ void ipath_disable_armlaunch(struct ipath_devdata *);
- #define IPATH_LINKUNK 0x400
- /* Write combining flush needed for PIO */
- #define IPATH_PIO_FLUSH_WC 0x1000
-+ /* DMA Receive tail pointer */
-+#define IPATH_NODMA_RTAIL 0x2000
- /* no IB cable, or no device on IB cable */
- #define IPATH_NOCABLE 0x4000
- /* Supports port zero per packet receive interrupts via
-@@ -819,16 +963,26 @@ void ipath_disable_armlaunch(struct ipath_devdata *);
- /* packet/word counters are 32 bit, else those 4 counters
- * are 64bit */
- #define IPATH_32BITCOUNTERS 0x20000
-- /* can miss port0 rx interrupts */
- /* Interrupt register is 64 bits */
- #define IPATH_INTREG_64 0x40000
-+ /* can miss port0 rx interrupts */
- #define IPATH_DISABLED 0x80000 /* administratively disabled */
- /* Use GPIO interrupts for new counters */
- #define IPATH_GPIO_ERRINTRS 0x100000
- #define IPATH_SWAP_PIOBUFS 0x200000
-+ /* Supports Send DMA */
-+#define IPATH_HAS_SEND_DMA 0x400000
-+ /* Supports Send Count (not just word count) in PBC */
-+#define IPATH_HAS_PBC_CNT 0x800000
- /* Suppress heartbeat, even if turning off loopback */
- #define IPATH_NO_HRTBT 0x1000000
-+#define IPATH_HAS_THRESH_UPDATE 0x4000000
- #define IPATH_HAS_MULT_IB_SPEED 0x8000000
-+#define IPATH_IB_AUTONEG_INPROG 0x10000000
-+#define IPATH_IB_AUTONEG_FAILED 0x20000000
-+ /* Linkdown-disable intentionally, Do not attempt to bring up */
-+#define IPATH_IB_LINK_DISABLED 0x40000000
-+#define IPATH_IB_FORCE_NOTIFY 0x80000000 /* force notify on next ib change */
-
- /* Bits in GPIO for the added interrupts */
- #define IPATH_GPIO_PORT0_BIT 2
-@@ -847,13 +1001,18 @@ void ipath_disable_armlaunch(struct ipath_devdata *);
-
- /* free up any allocated data at closes */
- void ipath_free_data(struct ipath_portdata *dd);
--u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32 *);
-+u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32, u32 *);
-+void ipath_chg_pioavailkernel(struct ipath_devdata *dd, unsigned start,
-+ unsigned len, int avail);
-+void ipath_init_iba7220_funcs(struct ipath_devdata *);
- void ipath_init_iba6120_funcs(struct ipath_devdata *);
- void ipath_init_iba6110_funcs(struct ipath_devdata *);
- void ipath_get_eeprom_info(struct ipath_devdata *);
- int ipath_update_eeprom_log(struct ipath_devdata *dd);
- void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr);
- u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg);
-+void ipath_disarm_senderrbufs(struct ipath_devdata *, int);
-+void ipath_force_pio_avail_update(struct ipath_devdata *);
- void signal_ib_event(struct ipath_devdata *dd, enum ib_event_type ev);
-
- /*
-@@ -865,6 +1024,34 @@ void signal_ib_event(struct ipath_devdata *dd, enum ib_event_type ev);
- #define IPATH_LED_LOG 2 /* Logical (link) YELLOW LED */
- void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val);
-
-+/* send dma routines */
-+int setup_sdma(struct ipath_devdata *);
-+void teardown_sdma(struct ipath_devdata *);
-+void ipath_restart_sdma(struct ipath_devdata *);
-+void ipath_sdma_intr(struct ipath_devdata *);
-+int ipath_sdma_verbs_send(struct ipath_devdata *, struct ipath_sge_state *,
-+ u32, struct ipath_verbs_txreq *);
-+/* ipath_sdma_lock should be locked before calling this. */
-+int ipath_sdma_make_progress(struct ipath_devdata *dd);
++struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
++ struct i2c_adapter *i2c_adap,
++ u8 i2c_addr)
++{
++ struct tda9887_priv *priv = NULL;
++ int instance;
++
++ mutex_lock(&tda9887_list_mutex);
++
++ 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;
++ }
++
++ mutex_unlock(&tda9887_list_mutex);
++
++ memcpy(&fe->ops.analog_ops, &tda9887_ops,
++ sizeof(struct analog_demod_ops));
++
++ return fe;
++}
++EXPORT_SYMBOL_GPL(tda9887_attach);
++
++MODULE_LICENSE("GPL");
++
++/*
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-basic-offset: 8
++ * End:
++ */
+diff --git a/drivers/media/common/tuners/tda9887.h b/drivers/media/common/tuners/tda9887.h
+new file mode 100644
+index 0000000..acc419e
+--- /dev/null
++++ b/drivers/media/common/tuners/tda9887.h
+@@ -0,0 +1,38 @@
++/*
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
+
-+/* must be called under ipath_sdma_lock */
-+static inline u16 ipath_sdma_descq_freecnt(const struct ipath_devdata *dd)
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You 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 __TDA9887_H__
++#define __TDA9887_H__
++
++#include <linux/i2c.h>
++#include "dvb_frontend.h"
++
++/* ------------------------------------------------------------------------ */
++#if defined(CONFIG_MEDIA_TUNER_TDA9887) || (defined(CONFIG_MEDIA_TUNER_TDA9887_MODULE) && defined(MODULE))
++extern struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
++ struct i2c_adapter *i2c_adap,
++ u8 i2c_addr);
++#else
++static inline struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
++ struct i2c_adapter *i2c_adap,
++ u8 i2c_addr)
+{
-+ return dd->ipath_sdma_descq_cnt -
-+ (dd->ipath_sdma_descq_added - dd->ipath_sdma_descq_removed) -
-+ 1 - dd->ipath_sdma_desc_nreserved;
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++ return NULL;
+}
++#endif
+
-+static inline void ipath_sdma_desc_reserve(struct ipath_devdata *dd, u16 cnt)
++#endif /* __TDA9887_H__ */
+diff --git a/drivers/media/common/tuners/tea5761.c b/drivers/media/common/tuners/tea5761.c
+new file mode 100644
+index 0000000..b93cdef
+--- /dev/null
++++ b/drivers/media/common/tuners/tea5761.c
+@@ -0,0 +1,324 @@
++/*
++ * For Philips TEA5761 FM Chip
++ * I2C address is allways 0x20 (0x10 at 7-bit mode).
++ *
++ * Copyright (c) 2005-2007 Mauro Carvalho Chehab (mchehab at infradead.org)
++ * This code is placed under the terms of the GNUv2 General Public License
++ *
++ */
++
++#include <linux/i2c.h>
++#include <linux/delay.h>
++#include <linux/videodev.h>
++#include <media/tuner.h>
++#include "tuner-i2c.h"
++#include "tea5761.h"
++
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "enable verbose debug messages");
++
++struct tea5761_priv {
++ struct tuner_i2c_props i2c_props;
++
++ u32 frequency;
++};
++
++/*****************************************************************************/
++
++/***************************
++ * TEA5761HN I2C registers *
++ ***************************/
++
++/* INTREG - Read: bytes 0 and 1 / Write: byte 0 */
++
++ /* first byte for reading */
++#define TEA5761_INTREG_IFFLAG 0x10
++#define TEA5761_INTREG_LEVFLAG 0x8
++#define TEA5761_INTREG_FRRFLAG 0x2
++#define TEA5761_INTREG_BLFLAG 0x1
++
++ /* second byte for reading / byte for writing */
++#define TEA5761_INTREG_IFMSK 0x10
++#define TEA5761_INTREG_LEVMSK 0x8
++#define TEA5761_INTREG_FRMSK 0x2
++#define TEA5761_INTREG_BLMSK 0x1
++
++/* FRQSET - Read: bytes 2 and 3 / Write: byte 1 and 2 */
++
++ /* First byte */
++#define TEA5761_FRQSET_SEARCH_UP 0x80 /* 1=Station search from botton to up */
++#define TEA5761_FRQSET_SEARCH_MODE 0x40 /* 1=Search mode */
++
++ /* Bits 0-5 for divider MSB */
++
++ /* Second byte */
++ /* Bits 0-7 for divider LSB */
++
++/* TNCTRL - Read: bytes 4 and 5 / Write: Bytes 3 and 4 */
++
++ /* first byte */
++
++#define TEA5761_TNCTRL_PUPD_0 0x40 /* Power UP/Power Down MSB */
++#define TEA5761_TNCTRL_BLIM 0X20 /* 1= Japan Frequencies, 0= European frequencies */
++#define TEA5761_TNCTRL_SWPM 0x10 /* 1= software port is FRRFLAG */
++#define TEA5761_TNCTRL_IFCTC 0x08 /* 1= IF count time 15.02 ms, 0= IF count time 2.02 ms */
++#define TEA5761_TNCTRL_AFM 0x04
++#define TEA5761_TNCTRL_SMUTE 0x02 /* 1= Soft mute */
++#define TEA5761_TNCTRL_SNC 0x01
++
++ /* second byte */
++
++#define TEA5761_TNCTRL_MU 0x80 /* 1=Hard mute */
++#define TEA5761_TNCTRL_SSL_1 0x40
++#define TEA5761_TNCTRL_SSL_0 0x20
++#define TEA5761_TNCTRL_HLSI 0x10
++#define TEA5761_TNCTRL_MST 0x08 /* 1 = mono */
++#define TEA5761_TNCTRL_SWP 0x04
++#define TEA5761_TNCTRL_DTC 0x02 /* 1 = deemphasis 50 us, 0 = deemphasis 75 us */
++#define TEA5761_TNCTRL_AHLSI 0x01
++
++/* FRQCHECK - Read: bytes 6 and 7 */
++ /* First byte */
++
++ /* Bits 0-5 for divider MSB */
++
++ /* Second byte */
++ /* Bits 0-7 for divider LSB */
++
++/* TUNCHECK - Read: bytes 8 and 9 */
++
++ /* First byte */
++#define TEA5761_TUNCHECK_IF_MASK 0x7e /* IF count */
++#define TEA5761_TUNCHECK_TUNTO 0x01
++
++ /* Second byte */
++#define TEA5761_TUNCHECK_LEV_MASK 0xf0 /* Level Count */
++#define TEA5761_TUNCHECK_LD 0x08
++#define TEA5761_TUNCHECK_STEREO 0x04
++
++/* TESTREG - Read: bytes 10 and 11 / Write: bytes 5 and 6 */
++
++ /* All zero = no test mode */
++
++/* MANID - Read: bytes 12 and 13 */
++
++ /* First byte - should be 0x10 */
++#define TEA5767_MANID_VERSION_MASK 0xf0 /* Version = 1 */
++#define TEA5767_MANID_ID_MSB_MASK 0x0f /* Manufacurer ID - should be 0 */
++
++ /* Second byte - Should be 0x2b */
++
++#define TEA5767_MANID_ID_LSB_MASK 0xfe /* Manufacturer ID - should be 0x15 */
++#define TEA5767_MANID_IDAV 0x01 /* 1 = Chip has ID, 0 = Chip has no ID */
++
++/* Chip ID - Read: bytes 14 and 15 */
++
++ /* First byte - should be 0x57 */
++
++ /* Second byte - should be 0x61 */
++
++/*****************************************************************************/
++
++#define FREQ_OFFSET 0 /* for TEA5767, it is 700 to give the right freq */
++static void tea5761_status_dump(unsigned char *buffer)
+{
-+ dd->ipath_sdma_desc_nreserved += cnt;
++ unsigned int div, frq;
++
++ div = ((buffer[2] & 0x3f) << 8) | buffer[3];
++
++ frq = 1000 * (div * 32768 / 1000 + FREQ_OFFSET + 225) / 4; /* Freq in KHz */
++
++ printk(KERN_INFO "tea5761: Frequency %d.%03d KHz (divider = 0x%04x)\n",
++ frq / 1000, frq % 1000, div);
+}
+
-+static inline void ipath_sdma_desc_unreserve(struct ipath_devdata *dd, u16 cnt)
++/* Freq should be specifyed at 62.5 Hz */
++static int set_radio_freq(struct dvb_frontend *fe,
++ struct analog_parameters *params)
+{
-+ dd->ipath_sdma_desc_nreserved -= cnt;
++ struct tea5761_priv *priv = fe->tuner_priv;
++ unsigned int frq = params->frequency;
++ unsigned char buffer[7] = {0, 0, 0, 0, 0, 0, 0 };
++ unsigned div;
++ int rc;
++
++ tuner_dbg("radio freq counter %d\n", frq);
++
++ if (params->mode == T_STANDBY) {
++ tuner_dbg("TEA5761 set to standby mode\n");
++ buffer[5] |= TEA5761_TNCTRL_MU;
++ } else {
++ buffer[4] |= TEA5761_TNCTRL_PUPD_0;
++ }
++
++
++ if (params->audmode == V4L2_TUNER_MODE_MONO) {
++ tuner_dbg("TEA5761 set to mono\n");
++ buffer[5] |= TEA5761_TNCTRL_MST;
++ } else {
++ tuner_dbg("TEA5761 set to stereo\n");
++ }
++
++ div = (1000 * (frq * 4 / 16 + 700 + 225) ) >> 15;
++ buffer[1] = (div >> 8) & 0x3f;
++ buffer[2] = div & 0xff;
++
++ if (debug)
++ tea5761_status_dump(buffer);
++
++ if (7 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 7)))
++ tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
++
++ priv->frequency = frq * 125 / 2;
++
++ return 0;
+}
+
- /*
- * 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)
++static int tea5761_read_status(struct dvb_frontend *fe, char *buffer)
+{
-+ const struct ipath_devdata *dd = pd->port_dd;
-+ u32 hdrqtail;
++ struct tea5761_priv *priv = fe->tuner_priv;
++ int rc;
+
-+ if (dd->ipath_flags & IPATH_NODMA_RTAIL) {
-+ __le32 *rhf_addr;
-+ u32 seq;
++ memset(buffer, 0, 16);
++ if (16 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 16))) {
++ tuner_warn("i2c i/o error: rc == %d (should be 16)\n", rc);
++ return -EREMOTEIO;
++ }
+
-+ 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 0;
++}
+
-+ return hdrqtail;
++static inline int tea5761_signal(struct dvb_frontend *fe, const char *buffer)
++{
++ struct tea5761_priv *priv = fe->tuner_priv;
++
++ int signal = ((buffer[9] & TEA5761_TUNCHECK_LEV_MASK) << (13 - 4));
++
++ tuner_dbg("Signal strength: %d\n", signal);
++
++ return signal;
+}
+
- 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)
++static inline int tea5761_stereo(struct dvb_frontend *fe, const char *buffer)
+{
-+ 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;
++ struct tea5761_priv *priv = fe->tuner_priv;
++
++ int stereo = buffer[9] & TEA5761_TUNCHECK_STEREO;
++
++ tuner_dbg("Radio ST GET = %02x\n", stereo);
++
++ return (stereo ? V4L2_TUNER_SUB_STEREO : 0);
+}
+
-+/*
- * 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)
++static int tea5761_get_status(struct dvb_frontend *fe, u32 *status)
+{
-+ (void) dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB, w);
++ unsigned char buffer[16];
++
++ *status = 0;
++
++ if (0 == tea5761_read_status(fe, buffer)) {
++ if (tea5761_signal(fe, buffer))
++ *status = TUNER_STATUS_LOCKED;
++ if (tea5761_stereo(fe, buffer))
++ *status |= TUNER_STATUS_STEREO;
++ }
++
++ return 0;
+}
+
-+static void set_link_speed_enabled(struct ipath_devdata *dd, u32 s)
++static int tea5761_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
+{
-+ (void) dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB, s);
++ unsigned char buffer[16];
++
++ *strength = 0;
++
++ if (0 == tea5761_read_status(fe, buffer))
++ *strength = tea5761_signal(fe, buffer);
++
++ return 0;
+}
-
- 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;
++int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
++{
++ unsigned char buffer[16];
++ int rc;
++ struct tuner_i2c_props i2c = { .adap = i2c_adap, .addr = i2c_addr };
+
-+ 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;
-+ }
++ 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;
+ }
+
- 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);
++ 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: TEA%02x%02x detected. "
++ "Manufacturer ID= 0x%02x\n",
++ buffer[14], buffer[15], buffer[13]);
+
- /* Make sure the QP isn't on the timeout list. */
- spin_lock_irqsave(&dev->pending_lock, flags);
- if (!list_empty(&qp->timerwait))
- list_del_init(&qp->timerwait);
- if (!list_empty(&qp->piowait))
- list_del_init(&qp->piowait);
-+ if (qp->s_tx)
-+ list_add(&qp->s_tx->txreq.list, &dev->txreq_free);
- spin_unlock_irqrestore(&dev->pending_lock, flags);
-
- /*
-@@ -1021,7 +1043,6 @@ void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc)
- qp->ibqp.qp_num, qp->remote_qpn, wc->status);
-
- spin_lock(&dev->pending_lock);
-- /* XXX What if its already removed by the timeout code? */
- if (!list_empty(&qp->timerwait))
- list_del_init(&qp->timerwait);
- if (!list_empty(&qp->piowait))
-diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c
-index 40f3e37..c405dfb 100644
---- a/drivers/infiniband/hw/ipath/ipath_rc.c
-+++ b/drivers/infiniband/hw/ipath/ipath_rc.c
-@@ -1,5 +1,5 @@
- /*
-- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
-+ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
- * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
-@@ -31,6 +31,8 @@
- * SOFTWARE.
- */
-
-+#include <linux/io.h>
++ return 0;
++}
+
- #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);
++static int tea5761_release(struct dvb_frontend *fe)
++{
++ kfree(fe->tuner_priv);
++ fe->tuner_priv = NULL;
+
- /* 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);
++ return 0;
++}
+
-+ 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;
-+ }
++static int tea5761_get_frequency(struct dvb_frontend *fe, u32 *frequency)
++{
++ struct tea5761_priv *priv = fe->tuner_priv;
++ *frequency = priv->frequency;
++ return 0;
++}
+
- /* 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;
++static struct dvb_tuner_ops tea5761_tuner_ops = {
++ .info = {
++ .name = "tea5761", // Philips TEA5761HN FM Radio
++ },
++ .set_analog_params = set_radio_freq,
++ .release = tea5761_release,
++ .get_frequency = tea5761_get_frequency,
++ .get_status = tea5761_get_status,
++ .get_rf_strength = tea5761_get_rf_strength,
++};
+
-+ 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);
++struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
++ struct i2c_adapter* i2c_adap,
++ u8 i2c_addr)
++{
++ struct tea5761_priv *priv = NULL;
+
-+ ipath_flush_wc();
++ if (tea5761_autodetection(i2c_adap, i2c_addr) == EINVAL)
++ return NULL;
+
-+ 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)
++ priv = kzalloc(sizeof(struct tea5761_priv), GFP_KERNEL);
++ if (priv == NULL)
++ return NULL;
++ fe->tuner_priv = priv;
+
- /* 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
++ priv->i2c_props.addr = i2c_addr;
++ priv->i2c_props.adap = i2c_adap;
++ priv->i2c_props.name = "tea5761";
+
- #define INFINIPATH_IBCS_TXREADY 0x40000000
- #define INFINIPATH_IBCS_TXCREDITOK 0x80000000
- /* link training states (shift by
-@@ -222,30 +257,13 @@
- #define INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN 0x0c
- #define INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT 0x0e
- #define INFINIPATH_IBCS_LT_STATE_RECOVERIDLE 0x0f
--/* link state machine states (shift by INFINIPATH_IBCS_LINKSTATE_SHIFT) */
-+/* link state machine states (shift by ibcs_ls_shift) */
- #define INFINIPATH_IBCS_L_STATE_DOWN 0x0
- #define INFINIPATH_IBCS_L_STATE_INIT 0x1
- #define INFINIPATH_IBCS_L_STATE_ARM 0x2
- #define INFINIPATH_IBCS_L_STATE_ACTIVE 0x3
- #define INFINIPATH_IBCS_L_STATE_ACT_DEFER 0x4
-
--/* combination link status states that we use with some frequency */
--#define IPATH_IBSTATE_MASK ((INFINIPATH_IBCS_LINKTRAININGSTATE_MASK \
-- << INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) | \
-- (INFINIPATH_IBCS_LINKSTATE_MASK \
-- <<INFINIPATH_IBCS_LINKSTATE_SHIFT))
--#define IPATH_IBSTATE_INIT ((INFINIPATH_IBCS_L_STATE_INIT \
-- << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
-- (INFINIPATH_IBCS_LT_STATE_LINKUP \
-- <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
--#define IPATH_IBSTATE_ARM ((INFINIPATH_IBCS_L_STATE_ARM \
-- << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
-- (INFINIPATH_IBCS_LT_STATE_LINKUP \
-- <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
--#define IPATH_IBSTATE_ACTIVE ((INFINIPATH_IBCS_L_STATE_ACTIVE \
-- << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
-- (INFINIPATH_IBCS_LT_STATE_LINKUP \
-- <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
-
- /* kr_extstatus bits */
- #define INFINIPATH_EXTS_SERDESPLLLOCK 0x1
-@@ -286,8 +304,7 @@
- /* L1 Power down; use with RXDETECT, Otherwise not used on IB side */
- #define INFINIPATH_SERDC0_L1PWR_DN 0xF0ULL
-
--/* kr_xgxsconfig bits */
--#define INFINIPATH_XGXS_RESET 0x7ULL
-+/* common kr_xgxsconfig bits (or safe in all, even if not implemented) */
- #define INFINIPATH_XGXS_RX_POL_SHIFT 19
- #define INFINIPATH_XGXS_RX_POL_MASK 0xfULL
-
-@@ -417,6 +434,29 @@ struct ipath_kregs {
- ipath_kreg kr_pcieq1serdesconfig0;
- ipath_kreg kr_pcieq1serdesconfig1;
- ipath_kreg kr_pcieq1serdesstatus;
-+ ipath_kreg kr_hrtbt_guid;
-+ ipath_kreg kr_ibcddrctrl;
-+ ipath_kreg kr_ibcddrstatus;
-+ ipath_kreg kr_jintreload;
++ memcpy(&fe->ops.tuner_ops, &tea5761_tuner_ops,
++ sizeof(struct dvb_tuner_ops));
+
-+ /* send dma related regs */
-+ ipath_kreg kr_senddmabase;
-+ ipath_kreg kr_senddmalengen;
-+ ipath_kreg kr_senddmatail;
-+ ipath_kreg kr_senddmahead;
-+ ipath_kreg kr_senddmaheadaddr;
-+ ipath_kreg kr_senddmabufmask0;
-+ ipath_kreg kr_senddmabufmask1;
-+ ipath_kreg kr_senddmabufmask2;
-+ ipath_kreg kr_senddmastatus;
++ tuner_info("type set to %s\n", "Philips TEA5761HN FM Radio");
+
-+ /* SerDes related regs (IBA7220-only) */
-+ ipath_kreg kr_ibserdesctrl;
-+ ipath_kreg kr_ib_epbacc;
-+ ipath_kreg kr_ib_epbtrans;
-+ ipath_kreg kr_pcie_epbacc;
-+ ipath_kreg kr_pcie_epbtrans;
-+ ipath_kreg kr_ib_ddsrxeq;
- };
-
- struct ipath_cregs {
-diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
-index a59bdbd..8ac5c1d 100644
---- a/drivers/infiniband/hw/ipath/ipath_ruc.c
-+++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
-@@ -310,7 +310,7 @@ again:
- switch (wqe->wr.opcode) {
- case IB_WR_SEND_WITH_IMM:
- wc.wc_flags = IB_WC_WITH_IMM;
-- wc.imm_data = wqe->wr.imm_data;
-+ wc.imm_data = wqe->wr.ex.imm_data;
- /* FALLTHROUGH */
- case IB_WR_SEND:
- if (!ipath_get_rwqe(qp, 0)) {
-@@ -339,7 +339,7 @@ again:
- goto err;
- }
- wc.wc_flags = IB_WC_WITH_IMM;
-- wc.imm_data = wqe->wr.imm_data;
-+ wc.imm_data = wqe->wr.ex.imm_data;
- if (!ipath_get_rwqe(qp, 1))
- goto rnr_nak;
- /* FALLTHROUGH */
-@@ -483,14 +483,16 @@ done:
-
- static void want_buffer(struct ipath_devdata *dd)
- {
-- unsigned long flags;
--
-- spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
-- dd->ipath_sendctrl |= INFINIPATH_S_PIOINTBUFAVAIL;
-- ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
-- dd->ipath_sendctrl);
-- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
-- spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
-+ if (!(dd->ipath_flags & IPATH_HAS_SEND_DMA)) {
-+ unsigned long flags;
++ return fe;
++}
+
-+ 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
++
++EXPORT_SYMBOL_GPL(tea5761_attach);
++EXPORT_SYMBOL_GPL(tea5761_autodetection);
++
++MODULE_DESCRIPTION("Philips TEA5761 FM tuner driver");
++MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab at infradead.org>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/common/tuners/tea5761.h b/drivers/media/common/tuners/tea5761.h
new file mode 100644
-index 0000000..aa47eb5
+index 0000000..2e2ff82
--- /dev/null
-+++ b/drivers/infiniband/hw/ipath/ipath_sd7220.c
-@@ -0,0 +1,1462 @@
++++ b/drivers/media/common/tuners/tea5761.h
+@@ -0,0 +1,47 @@
+/*
-+ * 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:
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You 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 __TEA5761_H__
++#define __TEA5761_H__
++
++#include <linux/i2c.h>
++#include "dvb_frontend.h"
++
++#if defined(CONFIG_MEDIA_TUNER_TEA5761) || (defined(CONFIG_MEDIA_TUNER_TEA5761_MODULE) && defined(MODULE))
++extern int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr);
++
++extern struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
++ struct i2c_adapter* i2c_adap,
++ u8 i2c_addr);
++#else
++static inline int tea5761_autodetection(struct i2c_adapter* i2c_adap,
++ u8 i2c_addr)
++{
++ printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
++ __func__);
++ return -EINVAL;
++}
++
++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", __func__);
++ return NULL;
++}
++#endif
++
++#endif /* __TEA5761_H__ */
+diff --git a/drivers/media/common/tuners/tea5767.c b/drivers/media/common/tuners/tea5767.c
+new file mode 100644
+index 0000000..f6e7d7a
+--- /dev/null
++++ b/drivers/media/common/tuners/tea5767.c
+@@ -0,0 +1,474 @@
++/*
++ * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview
++ * I2C address is allways 0xC0.
+ *
-+ * - 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.
++ * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab at infradead.org)
++ * This code is placed under the terms of the GNU General Public License
+ *
-+ * 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.
++ * tea5767 autodetection thanks to Torsten Seeboth and Atsushi Nakagawa
++ * from their contributions on DScaler.
+ */
+
-+#include <linux/pci.h>
++#include <linux/i2c.h>
+#include <linux/delay.h>
++#include <linux/videodev.h>
++#include "tuner-i2c.h"
++#include "tea5767.h"
+
-+#include "ipath_kernel.h"
-+#include "ipath_registers.h"
-+#include "ipath_7220.h"
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
-+/*
-+ * 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
++struct tea5767_priv {
++ struct tuner_i2c_props i2c_props;
++ u32 frequency;
++ struct tea5767_ctrl ctrl;
++};
+
-+/*
-+ * 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);
++/******************************
++ * Write mode register values *
++ ******************************/
+
-+void ipath_set_relock_poll(struct ipath_devdata *dd, int ibup);
++/* First register */
++#define TEA5767_MUTE 0x80 /* Mutes output */
++#define TEA5767_SEARCH 0x40 /* Activates station search */
++/* Bits 0-5 for divider MSB */
+
-+/*
-+ * 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;
-+}
++/* Second register */
++/* Bits 0-7 for divider LSB */
+
-+/* 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)
++/* Third register */
+
-+void ipath_sd7220_clr_ibpar(struct ipath_devdata *dd)
++/* Station search from botton to up */
++#define TEA5767_SEARCH_UP 0x80
++
++/* Searches with ADC output = 10 */
++#define TEA5767_SRCH_HIGH_LVL 0x60
++
++/* Searches with ADC output = 10 */
++#define TEA5767_SRCH_MID_LVL 0x40
++
++/* Searches with ADC output = 5 */
++#define TEA5767_SRCH_LOW_LVL 0x20
++
++/* if on, div=4*(Frf+Fif)/Fref otherwise, div=4*(Frf-Fif)/Freq) */
++#define TEA5767_HIGH_LO_INJECT 0x10
++
++/* Disable stereo */
++#define TEA5767_MONO 0x08
++
++/* Disable right channel and turns to mono */
++#define TEA5767_MUTE_RIGHT 0x04
++
++/* Disable left channel and turns to mono */
++#define TEA5767_MUTE_LEFT 0x02
++
++#define TEA5767_PORT1_HIGH 0x01
++
++/* Fourth register */
++#define TEA5767_PORT2_HIGH 0x80
++/* Chips stops working. Only I2C bus remains on */
++#define TEA5767_STDBY 0x40
++
++/* Japan freq (76-108 MHz. If disabled, 87.5-108 MHz */
++#define TEA5767_JAPAN_BAND 0x20
++
++/* Unselected means 32.768 KHz freq as reference. Otherwise Xtal at 13 MHz */
++#define TEA5767_XTAL_32768 0x10
++
++/* Cuts weak signals */
++#define TEA5767_SOFT_MUTE 0x08
++
++/* Activates high cut control */
++#define TEA5767_HIGH_CUT_CTRL 0x04
++
++/* Activates stereo noise control */
++#define TEA5767_ST_NOISE_CTL 0x02
++
++/* If activate PORT 1 indicates SEARCH or else it is used as PORT1 */
++#define TEA5767_SRCH_IND 0x01
++
++/* Fifth register */
++
++/* By activating, it will use Xtal at 13 MHz as reference for divider */
++#define TEA5767_PLLREF_ENABLE 0x80
++
++/* By activating, deemphasis=50, or else, deemphasis of 50us */
++#define TEA5767_DEEMPH_75 0X40
++
++/*****************************
++ * Read mode register values *
++ *****************************/
++
++/* First register */
++#define TEA5767_READY_FLAG_MASK 0x80
++#define TEA5767_BAND_LIMIT_MASK 0X40
++/* Bits 0-5 for divider MSB after search or preset */
++
++/* Second register */
++/* Bits 0-7 for divider LSB after search or preset */
++
++/* Third register */
++#define TEA5767_STEREO_MASK 0x80
++#define TEA5767_IF_CNTR_MASK 0x7f
++
++/* Fourth register */
++#define TEA5767_ADC_LEVEL_MASK 0xf0
++
++/* should be 0 */
++#define TEA5767_CHIP_ID_MASK 0x0f
++
++/* Fifth register */
++/* Reserved for future extensions */
++#define TEA5767_RESERVED_MASK 0xff
++
++/*****************************************************************************/
++
++static void tea5767_status_dump(struct tea5767_priv *priv,
++ unsigned char *buffer)
+{
-+ int ret;
++ unsigned int div, frq;
+
-+ /* 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;
++ if (TEA5767_READY_FLAG_MASK & buffer[0])
++ tuner_info("Ready Flag ON\n");
++ else
++ tuner_info("Ready Flag OFF\n");
++
++ if (TEA5767_BAND_LIMIT_MASK & buffer[0])
++ tuner_info("Tuner at band limit\n");
++ else
++ tuner_info("Tuner not at band limit\n");
++
++ div = ((buffer[0] & 0x3f) << 8) | buffer[1];
++
++ switch (priv->ctrl.xtal_freq) {
++ case TEA5767_HIGH_LO_13MHz:
++ frq = (div * 50000 - 700000 - 225000) / 4; /* Freq in KHz */
++ break;
++ case TEA5767_LOW_LO_13MHz:
++ frq = (div * 50000 + 700000 + 225000) / 4; /* Freq in KHz */
++ break;
++ case TEA5767_LOW_LO_32768:
++ frq = (div * 32768 + 700000 + 225000) / 4; /* Freq in KHz */
++ break;
++ case TEA5767_HIGH_LO_32768:
++ default:
++ frq = (div * 32768 - 700000 - 225000) / 4; /* Freq in KHz */
++ break;
+ }
-+ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0,
-+ UC_PAR_CLR_M);
++ buffer[0] = (div >> 8) & 0x3f;
++ buffer[1] = div & 0xff;
+
-+ 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;
++ tuner_info("Frequency %d.%03d KHz (divider = 0x%04x)\n",
++ frq / 1000, frq % 1000, div);
++
++ if (TEA5767_STEREO_MASK & buffer[2])
++ tuner_info("Stereo\n");
++ else
++ tuner_info("Mono\n");
++
++ tuner_info("IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK);
++
++ tuner_info("ADC Level = %d\n",
++ (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4);
++
++ tuner_info("Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK));
++
++ tuner_info("Reserved = 0x%02x\n",
++ (buffer[4] & TEA5767_RESERVED_MASK));
+}
+
-+/*
-+ * 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)
++/* Freq should be specifyed at 62.5 Hz */
++static int set_radio_freq(struct dvb_frontend *fe,
++ struct analog_parameters *params)
++{
++ struct tea5767_priv *priv = fe->tuner_priv;
++ unsigned int frq = params->frequency;
++ unsigned char buffer[5];
++ unsigned div;
++ int rc;
+
-+static int ipath_resync_ibepb(struct ipath_devdata *dd)
++ tuner_dbg("radio freq = %d.%03d MHz\n", frq/16000,(frq/16)%1000);
++
++ buffer[2] = 0;
++
++ if (priv->ctrl.port1)
++ buffer[2] |= TEA5767_PORT1_HIGH;
++
++ if (params->audmode == V4L2_TUNER_MODE_MONO) {
++ tuner_dbg("TEA5767 set to mono\n");
++ buffer[2] |= TEA5767_MONO;
++ } else {
++ tuner_dbg("TEA5767 set to stereo\n");
++ }
++
++
++ buffer[3] = 0;
++
++ if (priv->ctrl.port2)
++ buffer[3] |= TEA5767_PORT2_HIGH;
++
++ if (priv->ctrl.high_cut)
++ buffer[3] |= TEA5767_HIGH_CUT_CTRL;
++
++ if (priv->ctrl.st_noise)
++ buffer[3] |= TEA5767_ST_NOISE_CTL;
++
++ if (priv->ctrl.soft_mute)
++ buffer[3] |= TEA5767_SOFT_MUTE;
++
++ if (priv->ctrl.japan_band)
++ buffer[3] |= TEA5767_JAPAN_BAND;
++
++ buffer[4] = 0;
++
++ if (priv->ctrl.deemph_75)
++ buffer[4] |= TEA5767_DEEMPH_75;
++
++ if (priv->ctrl.pllref)
++ buffer[4] |= TEA5767_PLLREF_ENABLE;
++
++
++ /* Rounds freq to next decimal value - for 62.5 KHz step */
++ /* frq = 20*(frq/16)+radio_frq[frq%16]; */
++
++ switch (priv->ctrl.xtal_freq) {
++ case TEA5767_HIGH_LO_13MHz:
++ tuner_dbg("radio HIGH LO inject xtal @ 13 MHz\n");
++ buffer[2] |= TEA5767_HIGH_LO_INJECT;
++ div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000;
++ break;
++ case TEA5767_LOW_LO_13MHz:
++ tuner_dbg("radio LOW LO inject xtal @ 13 MHz\n");
++
++ div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000;
++ break;
++ case TEA5767_LOW_LO_32768:
++ tuner_dbg("radio LOW LO inject xtal @ 32,768 MHz\n");
++ buffer[3] |= TEA5767_XTAL_32768;
++ /* const 700=4000*175 Khz - to adjust freq to right value */
++ div = ((frq * (4000 / 16) - 700000 - 225000) + 16384) >> 15;
++ break;
++ case TEA5767_HIGH_LO_32768:
++ default:
++ tuner_dbg("radio HIGH LO inject xtal @ 32,768 MHz\n");
++
++ buffer[2] |= TEA5767_HIGH_LO_INJECT;
++ buffer[3] |= TEA5767_XTAL_32768;
++ div = ((frq * (4000 / 16) + 700000 + 225000) + 16384) >> 15;
++ break;
++ }
++ buffer[0] = (div >> 8) & 0x3f;
++ buffer[1] = div & 0xff;
++
++ if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5)))
++ tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
++
++ if (debug) {
++ if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5)))
++ tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
++ else
++ tea5767_status_dump(priv, buffer);
++ }
++
++ priv->frequency = frq * 125 / 2;
++
++ return 0;
++}
++
++static int tea5767_read_status(struct dvb_frontend *fe, char *buffer)
+{
-+ int ret, pat, tries, chn;
-+ u32 loc;
++ struct tea5767_priv *priv = fe->tuner_priv;
++ int rc;
+
-+ 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 */
++ memset(buffer, 0, 5);
++ if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5))) {
++ tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
++ return -EREMOTEIO;
+ }
-+ ipath_cdbg(VERBOSE, "Resync in %d tries\n", tries);
-+ return (ret > 0) ? 0 : ret;
++
++ return 0;
+}
+
-+/*
-+ * 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)
++static inline int tea5767_signal(struct dvb_frontend *fe, const char *buffer)
+{
-+ u64 rst_val;
-+ int ret = 0;
-+ unsigned long flags;
++ struct tea5767_priv *priv = fe->tuner_priv;
+
-+ 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);
++ int signal = ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << 8);
+
-+ ret = ipath_resync_ibepb(dd);
-+ if (ret < 0)
-+ ipath_dev_err(dd, "unable to re-sync IB EPB\n");
++ tuner_dbg("Signal strength: %d\n", signal);
+
-+ /* 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);
-+ }
++ return signal;
++}
+
-+bail:
-+ return ret;
++static inline int tea5767_stereo(struct dvb_frontend *fe, const char *buffer)
++{
++ struct tea5767_priv *priv = fe->tuner_priv;
++
++ int stereo = buffer[2] & TEA5767_STEREO_MASK;
++
++ tuner_dbg("Radio ST GET = %02x\n", stereo);
++
++ return (stereo ? V4L2_TUNER_SUB_STEREO : 0);
+}
+
-+static void ipath_sd_trimdone_monitor(struct ipath_devdata *dd,
-+ const char *where)
++static int tea5767_get_status(struct dvb_frontend *fe, u32 *status)
+{
-+ int ret, chn, baduns;
-+ u64 val;
++ unsigned char buffer[5];
+
-+ if (!where)
-+ where = "?";
++ *status = 0;
+
-+ /* give time for reset to settle out in EPB */
-+ udelay(2);
++ if (0 == tea5767_read_status(fe, buffer)) {
++ if (tea5767_signal(fe, buffer))
++ *status = TUNER_STATUS_LOCKED;
++ if (tea5767_stereo(fe, buffer))
++ *status |= TUNER_STATUS_STEREO;
++ }
+
-+ ret = ipath_resync_ibepb(dd);
-+ if (ret < 0)
-+ ipath_dev_err(dd, "not able to re-sync IB EPB (%s)\n", where);
++ return 0;
++}
+
-+ /* 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);
++static int tea5767_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
++{
++ unsigned char buffer[5];
+
-+ /* 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);
++ *strength = 0;
+
-+ udelay(2);
++ if (0 == tea5767_read_status(fe, buffer))
++ *strength = tea5767_signal(fe, buffer);
+
-+ 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);
++ return 0;
++}
+
-+ baduns = 0;
++static int tea5767_standby(struct dvb_frontend *fe)
++{
++ unsigned char buffer[5];
++ struct tea5767_priv *priv = fe->tuner_priv;
++ unsigned div, rc;
+
-+ 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);
++ div = (87500 * 4 + 700 + 225 + 25) / 50; /* Set frequency to 87.5 MHz */
++ buffer[0] = (div >> 8) & 0x3f;
++ buffer[1] = div & 0xff;
++ buffer[2] = TEA5767_PORT1_HIGH;
++ buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL |
++ TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND | TEA5767_STDBY;
++ buffer[4] = 0;
+
-+ 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);
-+ }
-+ }
++ if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5)))
++ tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
++
++ return 0;
+}
+
-+/*
-+ * 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 tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
+{
-+ int ret = 1; /* default to failure */
-+ int first_reset;
-+ int val_stat;
++ struct tuner_i2c_props i2c = { .adap = i2c_adap, .addr = i2c_addr };
++ unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
++ int rc;
+
-+ 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");
++ if ((rc = tuner_i2c_xfer_recv(&i2c, buffer, 7))< 5) {
++ printk(KERN_WARNING "It is not a TEA5767. Received %i bytes.\n", rc);
++ return EINVAL;
+ }
+
-+ /* Substitute our deduced value for was_reset */
-+ ret = ipath_ibsd_ucode_loaded(dd);
-+ if (ret < 0) {
-+ ret = 1;
-+ goto done;
++ /* If all bytes are the same then it's a TV tuner and not a tea5767 */
++ if (buffer[0] == buffer[1] && buffer[0] == buffer[2] &&
++ buffer[0] == buffer[3] && buffer[0] == buffer[4]) {
++ printk(KERN_WARNING "All bytes are equal. It is not a TEA5767\n");
++ return EINVAL;
+ }
-+ 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.
++ /* Status bytes:
++ * Byte 4: bit 3:1 : CI (Chip Identification) == 0
++ * bit 0 : internally set to 0
++ * Byte 5: bit 7:0 : == 0
+ */
-+ ret = ipath_sd_early(dd);
-+ if (ret < 0) {
-+ ipath_dev_err(dd, "Failed to set IB SERDES early defaults\n");
-+ ret = 1;
-+ goto done;
++ if (((buffer[3] & 0x0f) != 0x00) || (buffer[4] != 0x00)) {
++ printk(KERN_WARNING "Chip ID is not zero. It is not a TEA5767\n");
++ return EINVAL;
+ }
+
-+ /*
-+ * 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;
-+ }
++ return 0;
++}
+
-+ /* 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;
-+ }
++static int tea5767_release(struct dvb_frontend *fe)
++{
++ kfree(fe->tuner_priv);
++ fe->tuner_priv = NULL;
+
-+ /* 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;
++ return 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;
-+ }
++static int tea5767_get_frequency(struct dvb_frontend *fe, u32 *frequency)
++{
++ struct tea5767_priv *priv = fe->tuner_priv;
++ *frequency = priv->frequency;
+
-+ 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);
++ return 0;
++}
+
-+ if (!trim_done) {
-+ ipath_dev_err(dd, "No TRIMDONE seen\n");
-+ ret = 1;
-+ goto done;
-+ }
++static int tea5767_set_config (struct dvb_frontend *fe, void *priv_cfg)
++{
++ struct tea5767_priv *priv = fe->tuner_priv;
+
-+ 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
-+ */
++ memcpy(&priv->ctrl, priv_cfg, sizeof(priv->ctrl));
+
-+ 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;
++ return 0;
+}
+
-+#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
++static struct dvb_tuner_ops tea5767_tuner_ops = {
++ .info = {
++ .name = "tea5767", // Philips TEA5767HN FM Radio
++ },
+
-+/*
-+ * 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)
++ .set_analog_params = set_radio_freq,
++ .set_config = tea5767_set_config,
++ .sleep = tea5767_standby,
++ .release = tea5767_release,
++ .get_frequency = tea5767_get_frequency,
++ .get_status = tea5767_get_status,
++ .get_rf_strength = tea5767_get_rf_strength,
++};
++
++struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
++ struct i2c_adapter* i2c_adap,
++ u8 i2c_addr)
+{
-+ u16 acc;
-+ u64 accval;
-+ int owned = 0;
-+ u64 oct_sel = 0;
++ struct tea5767_priv *priv = NULL;
+
-+ 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;
-+ }
++ priv = kzalloc(sizeof(struct tea5767_priv), GFP_KERNEL);
++ if (priv == NULL)
++ return NULL;
++ fe->tuner_priv = priv;
+
-+ /* Make sure any outstanding transaction was seen */
-+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
-+ udelay(15);
++ priv->i2c_props.addr = i2c_addr;
++ priv->i2c_props.adap = i2c_adap;
++ priv->i2c_props.name = "tea5767";
+
-+ accval = ipath_read_kreg32(dd, acc);
++ priv->ctrl.xtal_freq = TEA5767_HIGH_LO_32768;
++ priv->ctrl.port1 = 1;
++ priv->ctrl.port2 = 1;
++ priv->ctrl.high_cut = 1;
++ priv->ctrl.st_noise = 1;
++ priv->ctrl.japan_band = 1;
+
-+ 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;
++ memcpy(&fe->ops.tuner_ops, &tea5767_tuner_ops,
++ sizeof(struct dvb_tuner_ops));
++
++ tuner_info("type set to %s\n", "Philips TEA5767HN FM Radio");
++
++ return fe;
+}
+
++EXPORT_SYMBOL_GPL(tea5767_attach);
++EXPORT_SYMBOL_GPL(tea5767_autodetection);
++
++MODULE_DESCRIPTION("Philips TEA5767 FM tuner driver");
++MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab at infradead.org>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/common/tuners/tea5767.h b/drivers/media/common/tuners/tea5767.h
+new file mode 100644
+index 0000000..d30ab1b
+--- /dev/null
++++ b/drivers/media/common/tuners/tea5767.h
+@@ -0,0 +1,66 @@
+/*
-+ * 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)
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You 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 __TEA5767_H__
++#define __TEA5767_H__
++
++#include <linux/i2c.h>
++#include "dvb_frontend.h"
++
++enum tea5767_xtal {
++ TEA5767_LOW_LO_32768 = 0,
++ TEA5767_HIGH_LO_32768 = 1,
++ TEA5767_LOW_LO_13MHz = 2,
++ TEA5767_HIGH_LO_13MHz = 3,
++};
++
++struct tea5767_ctrl {
++ unsigned int port1:1;
++ unsigned int port2:1;
++ unsigned int high_cut:1;
++ unsigned int st_noise:1;
++ unsigned int soft_mute:1;
++ unsigned int japan_band:1;
++ unsigned int deemph_75:1;
++ unsigned int pllref:1;
++ enum tea5767_xtal xtal_freq;
++};
++
++#if defined(CONFIG_MEDIA_TUNER_TEA5767) || (defined(CONFIG_MEDIA_TUNER_TEA5767_MODULE) && defined(MODULE))
++extern int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr);
++
++extern struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
++ struct i2c_adapter* i2c_adap,
++ u8 i2c_addr);
++#else
++static inline int tea5767_autodetection(struct i2c_adapter* i2c_adap,
++ u8 i2c_addr)
+{
-+ int tries;
-+ u64 transval;
++ printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
++ __func__);
++ return -EINVAL;
++}
+
++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", __func__);
++ return NULL;
++}
++#endif
+
-+ ipath_write_kreg(dd, reg, i_val);
-+ /* Throw away first read, as RDY bit may be stale */
-+ transval = ipath_read_kreg64(dd, reg);
++#endif /* __TEA5767_H__ */
+diff --git a/drivers/media/common/tuners/tuner-i2c.h b/drivers/media/common/tuners/tuner-i2c.h
+new file mode 100644
+index 0000000..3ad6c8e
+--- /dev/null
++++ b/drivers/media/common/tuners/tuner-i2c.h
+@@ -0,0 +1,173 @@
++/*
++ tuner-i2c.h - i2c interface for different tuners
+
-+ 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;
++ Copyright (C) 2007 Michael Krufky (mkrufky at linuxtv.org)
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You 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 __TUNER_I2C_H__
++#define __TUNER_I2C_H__
++
++#include <linux/i2c.h>
++
++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)
++{
++ struct i2c_msg msg = { .addr = props->addr, .flags = 0,
++ .buf = buf, .len = len };
++ int ret = i2c_transfer(props->adap, &msg, 1);
++
++ return (ret == 1) ? len : ret;
+}
+
-+/**
++static inline int tuner_i2c_xfer_recv(struct tuner_i2c_props *props, char *buf, int len)
++{
++ struct i2c_msg msg = { .addr = props->addr, .flags = I2C_M_RD,
++ .buf = buf, .len = len };
++ int ret = i2c_transfer(props->adap, &msg, 1);
++
++ return (ret == 1) ? len : ret;
++}
++
++static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props,
++ char *obuf, int olen,
++ char *ibuf, int ilen)
++{
++ struct i2c_msg msg[2] = { { .addr = props->addr, .flags = 0,
++ .buf = obuf, .len = olen },
++ { .addr = props->addr, .flags = I2C_M_RD,
++ .buf = ibuf, .len = ilen } };
++ int ret = i2c_transfer(props->adap, msg, 2);
++
++ return (ret == 2) ? ilen : ret;
++}
++
++/* Callers must declare as a global for the module:
+ *
-+ * 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.
++ * static LIST_HEAD(hybrid_tuner_instance_list);
+ *
-+ * 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.
++ * 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.
+ */
-+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;
-+ }
++#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)
+
-+ /*
-+ * All access is locked in software (vs other host threads) and
-+ * hardware (vs uC access).
-+ */
-+ spin_lock_irqsave(&dd->ipath_sdepb_lock, flags);
++/* TO DO: convert all callers of these macros to pass in
++ * struct tuner_i2c_props, then remove the macro wrappers */
+
-+ 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);
-+ }
++#define __tuner_warn(i2cprops, fmt, arg...) do { \
++ tuner_printk(KERN_WARNING, i2cprops, fmt, ##arg); \
++ } while (0)
+
-+ 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? */
++#define __tuner_info(i2cprops, fmt, arg...) do { \
++ tuner_printk(KERN_INFO, i2cprops, fmt, ##arg); \
++ } while (0)
+
-+ /*
-+ * Release bus. Failure is an error.
-+ */
-+ if (epb_access(dd, sdnum, -1) < 0)
-+ ret = -1;
-+ else
-+ ret = transval & EPB_DATA_MASK;
++#define __tuner_err(i2cprops, fmt, arg...) do { \
++ tuner_printk(KERN_ERR, i2cprops, fmt, ##arg); \
++ } while (0)
+
-+ spin_unlock_irqrestore(&dd->ipath_sdepb_lock, flags);
-+ if (tries <= 0)
-+ ret = -1;
-+ return ret;
-+}
++#define __tuner_dbg(i2cprops, fmt, arg...) do { \
++ if ((debug)) \
++ tuner_printk(KERN_DEBUG, i2cprops, fmt, ##arg); \
++ } while (0)
+
-+#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 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 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;
++#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; \
++})
+
-+ /* 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;
-+ }
++#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/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c
+new file mode 100644
+index 0000000..be8d903
+--- /dev/null
++++ b/drivers/media/common/tuners/tuner-simple.c
+@@ -0,0 +1,1093 @@
++/*
++ * i2c tv tuner chip device driver
++ * controls all those simple 4-control-bytes style tuners.
++ *
++ * This "tuner-simple" module was split apart from the original "tuner" module.
++ */
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <linux/videodev.h>
++#include <media/tuner.h>
++#include <media/v4l2-common.h>
++#include <media/tuner-types.h>
++#include "tuner-i2c.h"
++#include "tuner-simple.h"
+
-+ op = rd_notwr ? "Rd" : "Wr";
-+ spin_lock_irqsave(&dd->ipath_sdepb_lock, flags);
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
-+ 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;
-+ }
++#define TUNER_SIMPLE_MAX 64
++static unsigned int simple_devcount;
+
-+ /*
-+ * 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);
-+ }
++static int offset;
++module_param(offset, int, 0664);
++MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner");
+
-+ 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.
-+ */
++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");
+
-+ /* 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);
-+ }
++/* tv standard selection for Temic 4046 FM5
++ this value takes the low bits of control byte 2
++ from datasheet Rev.01, Feb.00
++ standard BG I L L2 D
++ picture IF 38.9 38.9 38.9 33.95 38.9
++ sound 1 33.4 32.9 32.4 40.45 32.4
++ sound 2 33.16
++ NICAM 33.05 32.348 33.05 33.05
++ */
++#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_BG 0x0c
+
-+ ret = sofar;
-+ /* Release bus. Failure is an error */
-+ if (epb_access(dd, sdnum, -1) < 0)
-+ ret = -1;
++/* tv tuner system standard selection for Philips FQ1216ME
++ this value takes the low bits of control byte 2
++ from datasheet "1999 Nov 16" (supersedes "1999 Mar 23")
++ standard BG DK I L L`
++ picture carrier 38.90 38.90 38.90 38.90 33.95
++ colour 34.47 34.47 34.47 34.47 38.38
++ sound 1 33.40 32.40 32.90 32.40 40.45
++ sound 2 33.16 - - - -
++ NICAM 33.05 33.05 32.35 33.05 39.80
++ */
++#define PHILIPS_SET_PAL_I 0x01 /* Bit 2 always zero !*/
++#define PHILIPS_SET_PAL_BGDK 0x09
++#define PHILIPS_SET_PAL_L2 0x0a
++#define PHILIPS_SET_PAL_L 0x0b
++
++/* system switching for Philips FI1216MF MK2
++ from datasheet "1996 Jul 09",
++ standard BG L L'
++ picture carrier 38.90 38.90 33.95
++ colour 34.47 34.37 38.38
++ sound 1 33.40 32.40 40.45
++ sound 2 33.16 - -
++ NICAM 33.05 33.05 39.80
++ */
++#define PHILIPS_MF_SET_STD_BG 0x01 /* Bit 2 must be zero, Bit 3 is system output */
++#define PHILIPS_MF_SET_STD_L 0x03 /* Used on Secam France */
++#define PHILIPS_MF_SET_STD_LC 0x02 /* Used on SECAM L' */
++
++/* Control byte */
++
++#define TUNER_RATIO_MASK 0x06 /* Bit cb1:cb2 */
++#define TUNER_RATIO_SELECT_50 0x00
++#define TUNER_RATIO_SELECT_32 0x02
++#define TUNER_RATIO_SELECT_166 0x04
++#define TUNER_RATIO_SELECT_62 0x06
++
++#define TUNER_CHARGE_PUMP 0x40 /* Bit cb6 */
++
++/* Status byte */
++
++#define TUNER_POR 0x80
++#define TUNER_FL 0x40
++#define TUNER_MODE 0x38
++#define TUNER_AFC 0x07
++#define TUNER_SIGNAL 0x07
++#define TUNER_STEREO 0x10
+
-+ 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 TUNER_PLL_LOCKED 0x40
++#define TUNER_STEREO_MK3 0x04
+
-+#define PROG_CHUNK 64
++static DEFINE_MUTEX(tuner_simple_list_mutex);
++static LIST_HEAD(hybrid_tuner_instance_list);
+
-+int ipath_sd7220_prog_ld(struct ipath_devdata *dd, int sdnum,
-+ u8 *img, int len, int offset)
-+{
-+ int cnt, sofar, req;
++struct tuner_simple_priv {
++ unsigned int nr;
++ u16 last_div;
+
-+ 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;
-+}
++ struct tuner_i2c_props i2c_props;
++ struct list_head hybrid_tuner_instance_list;
+
-+#define VFY_CHUNK 64
-+#define SD_PRAM_ERROR_LIMIT 42
++ unsigned int type;
++ struct tunertype *tun;
+
-+int ipath_sd7220_prog_vfy(struct ipath_devdata *dd, int sdnum,
-+ const u8 *img, int len, int offset)
++ u32 frequency;
++ u32 bandwidth;
++};
++
++/* ---------------------------------------------------------------------- */
++
++static int tuner_read_status(struct dvb_frontend *fe)
+{
-+ int cnt, sofar, req, idx, errors;
-+ unsigned char readback[VFY_CHUNK];
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ unsigned char byte;
+
-+ 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;
-+}
++ if (1 != tuner_i2c_xfer_recv(&priv->i2c_props, &byte, 1))
++ return 0;
+
-+/* IRQ not set up at this point in init, so we poll. */
-+#define IB_SERDES_TRIM_DONE (1ULL << 11)
-+#define TRIM_TMO (30)
++ return byte;
++}
+
-+static int ipath_sd_trimdone_poll(struct ipath_devdata *dd)
++static inline int tuner_signal(const int status)
+{
-+ int trim_tmo, ret;
-+ uint64_t val;
++ return (status & TUNER_SIGNAL) << 13;
++}
+
-+ /*
-+ * 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;
++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;
+ }
-+ return ret;
+}
+
-+#define TX_FAST_ELT (9)
++static inline int tuner_islocked(const int status)
++{
++ return (status & TUNER_FL);
++}
+
-+/*
-+ * 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.
-+ */
++static inline int tuner_afcstatus(const int status)
++{
++ return (status & TUNER_AFC) - 2;
++}
+
-+#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 int simple_get_status(struct dvb_frontend *fe, u32 *status)
++{
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ int tuner_status;
+
-+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)
-+};
++ if (priv->i2c_props.adap == NULL)
++ return -EINVAL;
+
-+/*
-+ * 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)} }
++ tuner_status = tuner_read_status(fe);
+
-+#define RXEQ_VAL_ALL(elt, adr, val) \
-+ {RXEQ_INIT_RDESC((elt), (adr)), {(val), (val), (val), (val)} }
++ *status = 0;
+
-+#define RXEQ_SDR_DFELTH 0
-+#define RXEQ_SDR_TLTH 0
-+#define RXEQ_SDR_G1CNT_Z1CNT 0x11
-+#define RXEQ_SDR_ZCNT 23
++ if (tuner_islocked(tuner_status))
++ *status = TUNER_STATUS_LOCKED;
++ if (tuner_stereo(priv->type, tuner_status))
++ *status |= TUNER_STATUS_STEREO;
+
-+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 */
-+};
++ tuner_dbg("AFC Status: %d\n", tuner_afcstatus(tuner_status));
+
-+/* 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)
++ return 0;
++}
+
-+static int ipath_sd_setvals(struct ipath_devdata *dd)
++static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
+{
-+ 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;
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ int signal;
+
-+ taddr = dd->ipath_kregbase + KR_IBSerDesMappTable;
-+ iaddr = dd->ipath_kregbase + dd->ipath_kregs->kr_ib_ddsrxeq;
++ if (priv->i2c_props.adap == NULL)
++ return -EINVAL;
+
-+ /*
-+ * 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);
++ signal = tuner_signal(tuner_read_status(fe));
+
-+ /*
-+ * 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) */
++ *strength = signal;
+
-+ /*
-+ * 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;
++ tuner_dbg("Signal strength: %d\n", signal);
+
-+ /* 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)
++static inline char *tuner_param_name(enum param_type type)
+{
-+ int ret = -1;
-+ int sloc; /* shifted loc, for messages */
-+
-+ loc |= (1U << EPB_IB_QUAD0_CS_SHF);
-+ sloc = loc >> EPB_ADDR_SHF;
++ char *name;
+
-+ 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;
++ 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;
+}
+
-+/*
-+ * 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)
++static struct tuner_params *simple_tuner_params(struct dvb_frontend *fe,
++ enum param_type desired_type)
+{
-+ int ret = -1;
-+ int chnl;
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ struct tunertype *tun = priv->tun;
++ int i;
+
-+ 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);
++ for (i = 0; i < tun->count; i++)
++ if (desired_type == tun->params[i].type)
+ break;
-+ }
++
++ /* 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;
+ }
-+ return ret;
++
++ tuner_dbg("using tuner params #%d (%s)\n", i,
++ tuner_param_name(tun->params[i].type));
++
++ return &tun->params[i];
+}
+
-+/*
-+ * 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)
++static int simple_config_lookup(struct dvb_frontend *fe,
++ struct tuner_params *t_params,
++ int *frequency, u8 *config, u8 *cb)
+{
-+ int ret;
-+ int idx, reg, data;
-+ uint32_t regmap;
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ int i;
+
-+ 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;
++ for (i = 0; i < t_params->count; i++) {
++ if (*frequency > t_params->ranges[i].limit)
++ continue;
++ break;
+ }
-+ return ret;
++ if (i == t_params->count) {
++ 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;
++
++ 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;
+}
+
-+/*
-+ * 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)
++/* ---------------------------------------------------------------------- */
++
++static void simple_set_rf_input(struct dvb_frontend *fe,
++ u8 *config, u8 *cb, unsigned int rf)
+{
-+ int ret;
-+ int ridx;
-+ int cnt = ARRAY_SIZE(rxeq_init_vals);
++ struct tuner_simple_priv *priv = fe->tuner_priv;
+
-+ 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)
++ 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;
+ }
-+ 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)
++static int simple_std_setup(struct dvb_frontend *fe,
++ struct analog_parameters *params,
++ u8 *config, u8 *cb)
+{
-+ int ret = 0;
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ u8 tuneraddr;
++ int rc;
+
-+ ret = set_dds_vals(dd, dds_init_vals + DDS_3M);
++ /* tv norm specific stuff for multi-norm tuners */
++ switch (priv->type) {
++ 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;
++ else if (params->std & V4L2_STD_SECAM_LC)
++ *cb |= PHILIPS_MF_SET_STD_LC;
++ else /* V4L2_STD_B|V4L2_STD_GH */
++ *cb |= PHILIPS_MF_SET_STD_BG;
++ break;
+
-+ 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;
-+}
++ case TUNER_TEMIC_4046FM5:
++ *cb &= ~0x0f;
+
-+int ipath_sd7220_presets(struct ipath_devdata *dd)
-+{
-+ int ret = 0;
++ if (params->std & V4L2_STD_PAL_BG) {
++ *cb |= TEMIC_SET_PAL_BG;
+
-+ 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");
++ } else if (params->std & V4L2_STD_PAL_I) {
++ *cb |= TEMIC_SET_PAL_I;
+
-+ ret = ipath_internal_presets(dd);
-+return ret;
-+}
++ } else if (params->std & V4L2_STD_PAL_DK) {
++ *cb |= TEMIC_SET_PAL_DK;
+
-+static int ipath_sd_trimself(struct ipath_devdata *dd, int val)
-+{
-+ return ibsd_sto_noisy(dd, CMUCTRL5, val, 0xFF);
-+}
++ } else if (params->std & V4L2_STD_SECAM_L) {
++ *cb |= TEMIC_SET_PAL_L;
+
-+static int ipath_sd_early(struct ipath_devdata *dd)
-+{
-+ int ret = -1; /* Default failed */
-+ int chnl;
++ }
++ break;
+
-+ 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;
-+}
++ case TUNER_PHILIPS_FQ1216ME:
++ *cb &= ~0x0f;
+
-+#define BACTRL(chnl) EPB_LOC(chnl, 6, 0x0E)
-+#define LDOUTCTRL1(chnl) EPB_LOC(chnl, 7, 6)
-+#define RXHSSTATUS(chnl) EPB_LOC(chnl, 6, 0xF)
++ if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) {
++ *cb |= PHILIPS_SET_PAL_BGDK;
+
-+static int ipath_sd_dactrim(struct ipath_devdata *dd)
-+{
-+ int ret = -1; /* Default failed */
-+ int chnl;
++ } else if (params->std & V4L2_STD_PAL_I) {
++ *cb |= PHILIPS_SET_PAL_I;
+
-+ 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;
-+}
++ } else if (params->std & V4L2_STD_SECAM_L) {
++ *cb |= PHILIPS_SET_PAL_L;
+
-+#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;
++ }
++ break;
+
-+ 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);
++ 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;
++ if (!(params->std & V4L2_STD_ATSC))
++ *cb |= 2;
++ break;
++
++ case TUNER_MICROTUNE_4042FI5:
++ /* Set the charge pump for fast tuning */
++ *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 */
++ u8 buffer[4] = { 0x14, 0x00, 0x17, 0x00};
++ *cb &= ~0x40;
++ if (params->std & V4L2_STD_ATSC) {
++ *cb |= 0x40;
++ buffer[1] = 0x04;
++ }
++ /* set to the correct mode (analog or digital) */
++ tuneraddr = priv->i2c_props.addr;
++ priv->i2c_props.addr = 0x0a;
++ 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;
++ break;
+ }
-+ /* 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);
-+}
++ if (atv_input[priv->nr])
++ simple_set_rf_input(fe, config, cb, atv_input[priv->nr]);
+
-+/*
-+ * 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);
-+ }
++ return 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)
++static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer,
++ u16 div, u8 config, u8 cb)
+{
-+ struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
-+ struct ipath_relock *irp = &dd->ipath_relock_singleton;
-+ u64 val, ltstate;
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ int rc;
+
-+ 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;
-+ }
++ 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]);
+
-+ /*
-+ * 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);
++ 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;
+
-+ 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);
++ /* 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);
+ }
-+ /* 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);
++ /* 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;
+}
+
-+void ipath_set_relock_poll(struct ipath_devdata *dd, int ibup)
++static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)
+{
-+ struct ipath_relock *irp = &dd->ipath_relock_singleton;
++ struct tuner_simple_priv *priv = fe->tuner_priv;
+
-+ 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);
-+ }
++ 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;
+}
+
-diff --git a/drivers/infiniband/hw/ipath/ipath_sd7220_img.c b/drivers/infiniband/hw/ipath/ipath_sd7220_img.c
-new file mode 100644
-index 0000000..5ef59da
---- /dev/null
-+++ b/drivers/infiniband/hw/ipath/ipath_sd7220_img.c
-@@ -0,0 +1,1082 @@
-+/*
-+ * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved.
-+ *
-+ * This software is available to you under a choice of one of two
-+ * licenses. You may choose to be licensed under the terms of the GNU
-+ * General Public License (GPL) Version 2, available from the file
-+ * COPYING in the main directory of this source tree, or the
-+ * OpenIB.org BSD license below:
-+ *
-+ * Redistribution and use in source and binary forms, with or
-+ * without modification, are permitted provided that the following
-+ * conditions are met:
-+ *
-+ * - Redistributions of source code must retain the above
-+ * copyright notice, this list of conditions and the following
-+ * disclaimer.
-+ *
-+ * - Redistributions in binary form must reproduce the above
-+ * copyright notice, this list of conditions and the following
-+ * disclaimer in the documentation and/or other materials
-+ * provided with the distribution.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-+ * SOFTWARE.
-+ */
++/* ---------------------------------------------------------------------- */
+
-+/*
-+ * This file contains the memory image from the vendor, to be copied into
-+ * the IB SERDES of the IBA7220 during initialization.
-+ * The file also includes the two functions which use this image.
-+ */
-+#include <linux/pci.h>
-+#include <linux/delay.h>
++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;
+
-+#include "ipath_kernel.h"
-+#include "ipath_registers.h"
-+#include "ipath_7220.h"
++ tun = priv->tun;
+
-+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
-+};
++ /* 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)
++ */
+
-+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);
-+}
++ 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;
+
-+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.
-+ */
++ 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);
+
-+#include <linux/spinlock.h>
++ /* tv norm specific stuff for multi-norm tuners */
++ simple_std_setup(fe, params, &config, &cb);
+
-+#include "ipath_kernel.h"
-+#include "ipath_verbs.h"
-+#include "ipath_common.h"
++ if (t_params->cb_first_if_lower_freq && div < priv->last_div) {
++ buffer[0] = config;
++ buffer[1] = cb;
++ buffer[2] = (div>>8) & 0x7f;
++ buffer[3] = div & 0xff;
++ } else {
++ buffer[0] = (div>>8) & 0x7f;
++ buffer[1] = div & 0xff;
++ buffer[2] = config;
++ buffer[3] = cb;
++ }
++ priv->last_div = div;
++ 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));
+
-+#define SDMA_DESCQ_SZ PAGE_SIZE /* 256 entries per 4KB page */
++ tda9887_cfg.tuner = TUNER_TDA9887;
++ tda9887_cfg.priv = &config;
+
-+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);
++ if (params->std == V4L2_STD_SECAM_LC) {
++ if (t_params->port1_active ^ t_params->port1_invert_for_secam_lc)
++ config |= TDA9887_PORT1_ACTIVE;
++ if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc)
++ config |= TDA9887_PORT2_ACTIVE;
++ } else {
++ if (t_params->port1_active)
++ config |= TDA9887_PORT1_ACTIVE;
++ if (t_params->port2_active)
++ config |= TDA9887_PORT2_ACTIVE;
++ }
++ if (t_params->intercarrier_mode)
++ config |= TDA9887_INTERCARRIER;
++ if (is_secam_l) {
++ if (i == 0 && t_params->default_top_secam_low)
++ config |= TDA9887_TOP(t_params->default_top_secam_low);
++ else if (i == 1 && t_params->default_top_secam_mid)
++ 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 {
++ 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)
++ config |= TDA9887_TOP(t_params->default_top_mid);
++ else if (t_params->default_top_high)
++ config |= TDA9887_TOP(t_params->default_top_high);
++ }
++ if (t_params->default_pll_gating_18)
++ config |= TDA9887_GATING_18;
++ i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,
++ &tda9887_cfg);
+ }
++ 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);
++
++ simple_post_tune(fe, &buffer[0], div, config, cb);
++
++ return 0;
+}
+
-+static void vl15_watchdog_deq(struct ipath_devdata *dd)
++static int simple_set_radio_freq(struct dvb_frontend *fe,
++ struct analog_parameters *params)
+{
-+ /* 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);
++ struct tunertype *tun;
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ u8 buffer[4];
++ u16 div;
++ int rc, j;
++ struct tuner_params *t_params;
++ unsigned int freq = params->frequency;
++
++ tun = priv->tun;
++
++ for (j = tun->count-1; j > 0; j--)
++ if (tun->params[j].type == TUNER_PARAM_TYPE_RADIO)
++ break;
++ /* default t_params (j=0) will be used if desired type wasn't found */
++ t_params = &tun->params[j];
++
++ /* Select Radio 1st IF used */
++ switch (t_params->radio_if) {
++ case 0: /* 10.7 MHz */
++ freq += (unsigned int)(10.7*16000);
++ break;
++ case 1: /* 33.3 MHz */
++ freq += (unsigned int)(33.3*16000);
++ break;
++ case 2: /* 41.3 MHz */
++ freq += (unsigned int)(41.3*16000);
++ break;
++ default:
++ tuner_warn("Unsupported radio_if value %d\n",
++ t_params->radio_if);
++ return 0;
+ }
-+}
+
-+static void vl15_watchdog_timeout(unsigned long opaque)
-+{
-+ struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
++ /* Bandswitch byte */
++ simple_radio_bandswitch(fe, &buffer[0]);
+
-+ 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);
++ buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) |
++ TUNER_RATIO_SELECT_50; /* 50 kHz step */
++
++ /* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps
++ freq * (1 Mhz / 16000 V4L steps) * (20 PLL steps / 1 MHz) =
++ freq * (1/800) */
++ div = (freq + 400) / 800;
++
++ if (t_params->cb_first_if_lower_freq && div < priv->last_div) {
++ buffer[0] = buffer[2];
++ buffer[1] = buffer[3];
++ buffer[2] = (div>>8) & 0x7f;
++ buffer[3] = div & 0xff;
+ } else {
-+ ipath_dbg("vl15 watchdog timeout - "
-+ "condition already cleared\n");
++ buffer[0] = (div>>8) & 0x7f;
++ buffer[1] = div & 0xff;
+ }
-+}
+
-+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;
++ tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n",
++ buffer[0], buffer[1], buffer[2], buffer[3]);
++ priv->last_div = div;
+
-+ desc[0] = le64_to_cpu(descqp[0]);
-+ desc[1] = le64_to_cpu(descqp[1]);
++ if (t_params->has_tda9887) {
++ int config = 0;
++ struct v4l2_priv_tun_config tda9887_cfg;
+
-+ addr = (desc[1] << 32) | (desc[0] >> 32);
-+ len = (desc[0] >> 14) & (0x7ffULL << 2);
-+ dma_unmap_single(&dd->pcidev->dev, addr, len, DMA_TO_DEVICE);
++ tda9887_cfg.tuner = TUNER_TDA9887;
++ tda9887_cfg.priv = &config;
++
++ 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)
++ config |= TDA9887_PORT2_ACTIVE;
++ if (t_params->intercarrier_mode)
++ config |= TDA9887_INTERCARRIER;
++/* if (t_params->port1_set_for_fm_mono)
++ config &= ~TDA9887_PORT1_ACTIVE;*/
++ if (t_params->fm_gain_normal)
++ config |= TDA9887_GAIN_NORMAL;
++ if (t_params->radio_if == 2)
++ config |= TDA9887_RIF_41_3;
++ i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,
++ &tda9887_cfg);
++ }
++ 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;
+}
+
-+/*
-+ * ipath_sdma_lock should be locked before calling this.
-+ */
-+int ipath_sdma_make_progress(struct ipath_devdata *dd)
++static int simple_set_params(struct dvb_frontend *fe,
++ struct analog_parameters *params)
+{
-+ struct list_head *lp = NULL;
-+ struct ipath_sdma_txreq *txp = NULL;
-+ u16 dmahead;
-+ u16 start_idx = 0;
-+ int progress = 0;
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ int ret = -EINVAL;
+
-+ 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;
++ if (priv->i2c_props.adap == NULL)
++ return -EINVAL;
++
++ switch (params->mode) {
++ case V4L2_TUNER_RADIO:
++ ret = simple_set_radio_freq(fe, params);
++ priv->frequency = params->frequency * 125 / 2;
++ break;
++ case V4L2_TUNER_ANALOG_TV:
++ case V4L2_TUNER_DIGITAL_TV:
++ ret = simple_set_tv_freq(fe, params);
++ priv->frequency = params->frequency * 62500;
++ break;
+ }
++ priv->bandwidth = 0;
+
-+ /*
-+ * 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;
++ return ret;
++}
+
-+ 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;
-+ }
++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;
+
-+ /* 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;
++ 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;
+
-+ 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;
++ /* 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;
+ }
-+ }
-+ progress = 1;
++ simple_set_rf_input(fe, &buf[2], &buf[3], new_rf);
++ break;
+ }
++ default:
++ break;
++ }
++}
+
-+ if (progress)
-+ tasklet_hi_schedule(&dd->ipath_sdma_notify_task);
++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;
+
-+done:
-+ return progress;
++ 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 void ipath_sdma_notify(struct ipath_devdata *dd, struct list_head *list)
++static int simple_dvb_calc_regs(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *params,
++ u8 *buf, int buf_len)
+{
-+ struct ipath_sdma_txreq *txp, *txp_next;
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ u32 frequency;
+
-+ list_for_each_entry_safe(txp, txp_next, list, list) {
-+ list_del_init(&txp->list);
++ if (buf_len < 5)
++ return -EINVAL;
+
-+ if (txp->callback)
-+ (*txp->callback)(txp->callback_cookie,
-+ txp->callback_status);
-+ }
++ 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 void sdma_notify_taskbody(struct ipath_devdata *dd)
++static int simple_dvb_set_params(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *params)
+{
-+ unsigned long flags;
-+ struct list_head list;
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ u32 prev_freq, prev_bw;
++ int ret;
++ u8 buf[5];
+
-+ INIT_LIST_HEAD(&list);
++ if (priv->i2c_props.adap == NULL)
++ return -EINVAL;
+
-+ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++ prev_freq = priv->frequency;
++ prev_bw = priv->bandwidth;
+
-+ list_splice_init(&dd->ipath_sdma_notifylist, &list);
++ ret = simple_dvb_calc_regs(fe, params, buf, 5);
++ if (ret != 5)
++ goto fail;
+
-+ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++ /* put analog demod in standby when tuning digital */
++ if (fe->ops.analog_ops.standby)
++ fe->ops.analog_ops.standby(fe);
+
-+ ipath_sdma_notify(dd, &list);
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
+
-+ /*
-+ * 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);
++ /* 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 void sdma_notify_task(unsigned long opaque)
++static int simple_init(struct dvb_frontend *fe)
+{
-+ struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
++ struct tuner_simple_priv *priv = fe->tuner_priv;
+
-+ if (!test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
-+ sdma_notify_taskbody(dd);
++ 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 void dump_sdma_state(struct ipath_devdata *dd)
++static int simple_sleep(struct dvb_frontend *fe)
+{
-+ unsigned long reg;
++ struct tuner_simple_priv *priv = fe->tuner_priv;
+
-+ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmastatus);
-+ ipath_cdbg(VERBOSE, "kr_senddmastatus: 0x%016lx\n", reg);
++ if (priv->i2c_props.adap == NULL)
++ return -EINVAL;
+
-+ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendctrl);
-+ ipath_cdbg(VERBOSE, "kr_sendctrl: 0x%016lx\n", reg);
++ if (priv->tun->sleepdata) {
++ int ret;
+
-+ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmabufmask0);
-+ ipath_cdbg(VERBOSE, "kr_senddmabufmask0: 0x%016lx\n", reg);
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
+
-+ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmabufmask1);
-+ ipath_cdbg(VERBOSE, "kr_senddmabufmask1: 0x%016lx\n", reg);
++ ret = tuner_i2c_xfer_send(&priv->i2c_props,
++ priv->tun->sleepdata + 1,
++ priv->tun->sleepdata[0]);
++ if (ret != priv->tun->sleepdata[0])
++ return ret;
++ }
+
-+ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmabufmask2);
-+ ipath_cdbg(VERBOSE, "kr_senddmabufmask2: 0x%016lx\n", reg);
++ return 0;
++}
+
-+ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmatail);
-+ ipath_cdbg(VERBOSE, "kr_senddmatail: 0x%016lx\n", reg);
++static int simple_release(struct dvb_frontend *fe)
++{
++ struct tuner_simple_priv *priv = fe->tuner_priv;
+
-+ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmahead);
-+ ipath_cdbg(VERBOSE, "kr_senddmahead: 0x%016lx\n", reg);
++ 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;
+}
+
-+static void sdma_abort_task(unsigned long opaque)
++static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
-+ struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
-+ u64 status;
-+ unsigned long flags;
-+
-+ if (test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
-+ return;
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ *frequency = priv->frequency;
++ return 0;
++}
+
-+ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++static int simple_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
++{
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ *bandwidth = priv->bandwidth;
++ return 0;
++}
+
-+ status = dd->ipath_sdma_status & IPATH_SDMA_ABORT_MASK;
++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,
++};
+
-+ /* nothing to do */
-+ if (status == IPATH_SDMA_ABORT_NONE)
-+ goto unlock;
++struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
++ struct i2c_adapter *i2c_adap,
++ u8 i2c_addr,
++ unsigned int type)
++{
++ struct tuner_simple_priv *priv = NULL;
++ int instance;
+
-+ /* 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;
++ if (type >= tuner_count) {
++ printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n",
++ __func__, type, tuner_count-1);
++ return NULL;
+ }
+
-+ /* 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;
++ /* 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,
++ };
+
-+ hwstatus = ipath_read_kreg64(dd,
-+ dd->ipath_kregs->kr_senddmastatus);
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
+
-+ 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);
-+ }
++ if (1 != i2c_transfer(i2c_adap, &msg, 1))
++ tuner_warn("unable to probe %s, proceeding anyway.",
++ tuners[type].name);
+
-+ /* 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);
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 0);
++ }
+
-+ /* 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;
++ mutex_lock(&tuner_simple_list_mutex);
+
-+ /* Reset SendDmaLenGen */
-+ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmalengen,
-+ (u64) dd->ipath_sdma_descq_cnt | (1ULL << 18));
++ 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;
+
-+ /* done with sdma state for a bit */
-+ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++ priv->type = type;
++ priv->tun = &tuners[type];
++ priv->nr = simple_devcount++;
++ break;
++ default:
++ fe->tuner_priv = priv;
++ break;
++ }
+
-+ /*
-+ * 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);
++ mutex_unlock(&tuner_simple_list_mutex);
+
-+ /* make sure I see next message */
-+ dd->ipath_sdma_abort_jiffies = 0;
++ memcpy(&fe->ops.tuner_ops, &simple_tuner_ops,
++ sizeof(struct dvb_tuner_ops));
+
-+ goto done;
-+ }
++ tuner_info("type set to %d (%s)\n", type, priv->tun->name);
+
-+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;
++ 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]);
+ }
-+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;
++ 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");
++MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
++MODULE_LICENSE("GPL");
+
+/*
-+ * This is called from interrupt context.
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-basic-offset: 8
++ * End:
+ */
-+void ipath_sdma_intr(struct ipath_devdata *dd)
-+{
-+ unsigned long flags;
+diff --git a/drivers/media/common/tuners/tuner-simple.h b/drivers/media/common/tuners/tuner-simple.h
+new file mode 100644
+index 0000000..381fa5d
+--- /dev/null
++++ b/drivers/media/common/tuners/tuner-simple.h
+@@ -0,0 +1,39 @@
++/*
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
+
-+ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
+
-+ (void) ipath_sdma_make_progress(dd);
++ You 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.
++*/
+
-+ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
-+}
++#ifndef __TUNER_SIMPLE_H__
++#define __TUNER_SIMPLE_H__
+
-+static int alloc_sdma(struct ipath_devdata *dd)
++#include <linux/i2c.h>
++#include "dvb_frontend.h"
++
++#if defined(CONFIG_MEDIA_TUNER_SIMPLE) || (defined(CONFIG_MEDIA_TUNER_SIMPLE_MODULE) && defined(MODULE))
++extern struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
++ struct i2c_adapter *i2c_adap,
++ u8 i2c_addr,
++ unsigned int type);
++#else
++static inline struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
++ struct i2c_adapter *i2c_adap,
++ u8 i2c_addr,
++ unsigned int type)
+{
-+ int ret = 0;
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++ return NULL;
++}
++#endif
+
-+ /* 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);
++#endif /* __TUNER_SIMPLE_H__ */
+diff --git a/drivers/media/common/tuners/tuner-types.c b/drivers/media/common/tuners/tuner-types.c
+new file mode 100644
+index 0000000..10dddca
+--- /dev/null
++++ b/drivers/media/common/tuners/tuner-types.c
+@@ -0,0 +1,1652 @@
++/*
++ *
++ * i2c tv tuner chip device type database.
++ *
++ */
+
-+ if (!dd->ipath_sdma_descq) {
-+ ipath_dev_err(dd, "failed to allocate SendDMA descriptor "
-+ "FIFO memory\n");
-+ ret = -ENOMEM;
-+ goto done;
-+ }
++#include <linux/i2c.h>
++#include <media/tuner.h>
++#include <media/tuner-types.h>
+
-+ 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;
++/*
++ * The floats in the tuner struct are computed at compile time
++ * by gcc and cast back to integers. Thus we don't violate the
++ * "no float in kernel" rule.
++ *
++ * A tuner_range may be referenced by multiple tuner_params structs.
++ * There are many duplicates in here. Reusing tuner_range structs,
++ * rather than defining new ones for each tuner, will cut down on
++ * memory usage, and is preferred when possible.
++ *
++ * Each tuner_params array may contain one or more elements, one
++ * for each video standard.
++ *
++ * FIXME: tuner_params struct contains an element, tda988x. We must
++ * set this for all tuners that contain a tda988x chip, and then we
++ * can remove this setting from the various card structs.
++ *
++ * FIXME: Right now, all tuners are using the first tuner_params[]
++ * array element for analog mode. In the future, we will be merging
++ * similar tuner definitions together, such that each tuner definition
++ * will have a tuner_params struct for each available video standard.
++ * At that point, the tuner_params[] array element will be chosen
++ * based on the video standard in use.
++ */
+
-+ 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);
++/* The following was taken from dvb-pll.c: */
+
-+ goto done;
++/* 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 };
+
-+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;
-+}
++/* 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 };
+
-+int setup_sdma(struct ipath_devdata *dd)
-+{
-+ int ret = 0;
-+ unsigned i, n;
-+ u64 tmp64;
-+ u64 senddmabufmask[3] = { 0 };
-+ unsigned long flags;
++/* 0-9 */
++/* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */
+
-+ ret = alloc_sdma(dd);
-+ if (ret)
-+ goto done;
++static struct tuner_range tuner_temic_pal_ranges[] = {
++ { 16 * 140.25 /*MHz*/, 0x8e, 0x02, },
++ { 16 * 463.25 /*MHz*/, 0x8e, 0x04, },
++ { 16 * 999.99 , 0x8e, 0x01, },
++};
+
-+ if (!dd->ipath_sdma_descq) {
-+ ipath_dev_err(dd, "SendDMA memory not allocated\n");
-+ goto done;
-+ }
++static struct tuner_params tuner_temic_pal_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_temic_pal_ranges,
++ .count = ARRAY_SIZE(tuner_temic_pal_ranges),
++ },
++};
+
-+ 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;
++/* ------------ TUNER_PHILIPS_PAL_I - Philips PAL_I ------------ */
+
-+ /* 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);
++static struct tuner_range tuner_philips_pal_i_ranges[] = {
++ { 16 * 140.25 /*MHz*/, 0x8e, 0xa0, },
++ { 16 * 463.25 /*MHz*/, 0x8e, 0x90, },
++ { 16 * 999.99 , 0x8e, 0x30, },
++};
+
-+ /* 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]);
++static struct tuner_params tuner_philips_pal_i_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_philips_pal_i_ranges,
++ .count = ARRAY_SIZE(tuner_philips_pal_i_ranges),
++ },
++};
+
-+ INIT_LIST_HEAD(&dd->ipath_sdma_activelist);
-+ INIT_LIST_HEAD(&dd->ipath_sdma_notifylist);
++/* ------------ TUNER_PHILIPS_NTSC - Philips NTSC ------------ */
+
-+ 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);
++static struct tuner_range tuner_philips_ntsc_ranges[] = {
++ { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, },
++ { 16 * 451.25 /*MHz*/, 0x8e, 0x90, },
++ { 16 * 999.99 , 0x8e, 0x30, },
++};
+
-+ /*
-+ * 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);
++static struct tuner_params tuner_philips_ntsc_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_philips_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_philips_ntsc_ranges),
++ .cb_first_if_lower_freq = 1,
++ },
++};
+
-+done:
-+ return ret;
-+}
++/* ------------ TUNER_PHILIPS_SECAM - Philips SECAM ------------ */
+
-+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;
++static struct tuner_range tuner_philips_secam_ranges[] = {
++ { 16 * 168.25 /*MHz*/, 0x8e, 0xa7, },
++ { 16 * 447.25 /*MHz*/, 0x8e, 0x97, },
++ { 16 * 999.99 , 0x8e, 0x37, },
++};
+
-+ 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);
++static struct tuner_params tuner_philips_secam_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_SECAM,
++ .ranges = tuner_philips_secam_ranges,
++ .count = ARRAY_SIZE(tuner_philips_secam_ranges),
++ .cb_first_if_lower_freq = 1,
++ },
++};
+
-+ tasklet_kill(&dd->ipath_sdma_abort_task);
-+ tasklet_kill(&dd->ipath_sdma_notify_task);
++/* ------------ TUNER_PHILIPS_PAL - Philips PAL ------------ */
+
-+ /* 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);
++static struct tuner_range tuner_philips_pal_ranges[] = {
++ { 16 * 168.25 /*MHz*/, 0x8e, 0xa0, },
++ { 16 * 447.25 /*MHz*/, 0x8e, 0x90, },
++ { 16 * 999.99 , 0x8e, 0x30, },
++};
+
-+ 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);
++static struct tuner_params tuner_philips_pal_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_philips_pal_ranges,
++ .count = ARRAY_SIZE(tuner_philips_pal_ranges),
++ .cb_first_if_lower_freq = 1,
++ },
++};
+
-+ sdma_notify_taskbody(dd);
++/* ------------ TUNER_TEMIC_NTSC - TEMIC NTSC ------------ */
+
-+ del_timer_sync(&dd->ipath_sdma_vl15_timer);
++static struct tuner_range tuner_temic_ntsc_ranges[] = {
++ { 16 * 157.25 /*MHz*/, 0x8e, 0x02, },
++ { 16 * 463.25 /*MHz*/, 0x8e, 0x04, },
++ { 16 * 999.99 , 0x8e, 0x01, },
++};
+
-+ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++static struct tuner_params tuner_temic_ntsc_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_temic_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_temic_ntsc_ranges),
++ },
++};
+
-+ dd->ipath_sdma_abort_jiffies = 0;
++/* ------------ TUNER_TEMIC_PAL_I - TEMIC PAL_I ------------ */
+
-+ 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);
++static struct tuner_range tuner_temic_pal_i_ranges[] = {
++ { 16 * 170.00 /*MHz*/, 0x8e, 0x02, },
++ { 16 * 450.00 /*MHz*/, 0x8e, 0x04, },
++ { 16 * 999.99 , 0x8e, 0x01, },
++};
+
-+ 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;
-+ }
++static struct tuner_params tuner_temic_pal_i_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_temic_pal_i_ranges,
++ .count = ARRAY_SIZE(tuner_temic_pal_i_ranges),
++ },
++};
+
-+ 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;
-+ }
++/* ------------ TUNER_TEMIC_4036FY5_NTSC - TEMIC NTSC ------------ */
+
-+ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++static struct tuner_range tuner_temic_4036fy5_ntsc_ranges[] = {
++ { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, },
++ { 16 * 463.25 /*MHz*/, 0x8e, 0x90, },
++ { 16 * 999.99 , 0x8e, 0x30, },
++};
+
-+ if (sdma_head_dma)
-+ dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE,
-+ sdma_head_dma, sdma_head_phys);
++static struct tuner_params tuner_temic_4036fy5_ntsc_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_temic_4036fy5_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_ranges),
++ },
++};
+
-+ if (sdma_descq)
-+ dma_free_coherent(&dd->pcidev->dev, SDMA_DESCQ_SZ,
-+ sdma_descq, sdma_descq_phys);
-+}
++/* ------------ TUNER_ALPS_TSBH1_NTSC - TEMIC NTSC ------------ */
+
-+/*
-+ * [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;
++static struct tuner_range tuner_alps_tsb_1_ranges[] = {
++ { 16 * 137.25 /*MHz*/, 0x8e, 0x01, },
++ { 16 * 385.25 /*MHz*/, 0x8e, 0x02, },
++ { 16 * 999.99 , 0x8e, 0x08, },
++};
+
-+ if (!(dd->ipath_flags & IPATH_HAS_SEND_DMA))
-+ goto bail;
++static struct tuner_params tuner_alps_tsbh1_ntsc_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_alps_tsb_1_ranges,
++ .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges),
++ },
++};
+
-+ /*
-+ * 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);
++/* 10-19 */
++/* ------------ TUNER_ALPS_TSBE1_PAL - TEMIC PAL ------------ */
+
-+bail:
-+ return;
-+}
++static struct tuner_params tuner_alps_tsb_1_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_alps_tsb_1_ranges,
++ .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges),
++ },
++};
+
-+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;
-+}
++/* ------------ TUNER_ALPS_TSBB5_PAL_I - Alps PAL_I ------------ */
+
-+/*
-+ * 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().
++static struct tuner_range tuner_alps_tsb_5_pal_ranges[] = {
++ { 16 * 133.25 /*MHz*/, 0x8e, 0x01, },
++ { 16 * 351.25 /*MHz*/, 0x8e, 0x02, },
++ { 16 * 999.99 , 0x8e, 0x08, },
++};
++
++static struct tuner_params tuner_alps_tsbb5_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_alps_tsb_5_pal_ranges,
++ .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_ALPS_TSBE5_PAL - Alps PAL ------------ */
++
++static struct tuner_params tuner_alps_tsbe5_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_alps_tsb_5_pal_ranges,
++ .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_ALPS_TSBC5_PAL - Alps PAL ------------ */
++
++static struct tuner_params tuner_alps_tsbc5_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_alps_tsb_5_pal_ranges,
++ .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_TEMIC_4006FH5_PAL - TEMIC PAL ------------ */
++
++static struct tuner_range tuner_lg_pal_ranges[] = {
++ { 16 * 170.00 /*MHz*/, 0x8e, 0xa0, },
++ { 16 * 450.00 /*MHz*/, 0x8e, 0x90, },
++ { 16 * 999.99 , 0x8e, 0x30, },
++};
++
++static struct tuner_params tuner_temic_4006fh5_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_lg_pal_ranges,
++ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_ALPS_TSHC6_NTSC - Alps NTSC ------------ */
++
++static struct tuner_range tuner_alps_tshc6_ntsc_ranges[] = {
++ { 16 * 137.25 /*MHz*/, 0x8e, 0x14, },
++ { 16 * 385.25 /*MHz*/, 0x8e, 0x12, },
++ { 16 * 999.99 , 0x8e, 0x11, },
++};
++
++static struct tuner_params tuner_alps_tshc6_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_alps_tshc6_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_alps_tshc6_ntsc_ranges),
++ },
++};
++
++/* ------------ TUNER_TEMIC_PAL_DK - TEMIC PAL ------------ */
++
++static struct tuner_range tuner_temic_pal_dk_ranges[] = {
++ { 16 * 168.25 /*MHz*/, 0x8e, 0xa0, },
++ { 16 * 456.25 /*MHz*/, 0x8e, 0x90, },
++ { 16 * 999.99 , 0x8e, 0x30, },
++};
++
++static struct tuner_params tuner_temic_pal_dk_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_temic_pal_dk_ranges,
++ .count = ARRAY_SIZE(tuner_temic_pal_dk_ranges),
++ },
++};
++
++/* ------------ TUNER_PHILIPS_NTSC_M - Philips NTSC ------------ */
++
++static struct tuner_range tuner_philips_ntsc_m_ranges[] = {
++ { 16 * 160.00 /*MHz*/, 0x8e, 0xa0, },
++ { 16 * 454.00 /*MHz*/, 0x8e, 0x90, },
++ { 16 * 999.99 , 0x8e, 0x30, },
++};
++
++static struct tuner_params tuner_philips_ntsc_m_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_philips_ntsc_m_ranges,
++ .count = ARRAY_SIZE(tuner_philips_ntsc_m_ranges),
++ },
++};
++
++/* ------------ TUNER_TEMIC_4066FY5_PAL_I - TEMIC PAL_I ------------ */
++
++static struct tuner_range tuner_temic_40x6f_5_pal_ranges[] = {
++ { 16 * 169.00 /*MHz*/, 0x8e, 0xa0, },
++ { 16 * 454.00 /*MHz*/, 0x8e, 0x90, },
++ { 16 * 999.99 , 0x8e, 0x30, },
++};
++
++static struct tuner_params tuner_temic_4066fy5_pal_i_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_temic_40x6f_5_pal_ranges,
++ .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_TEMIC_4006FN5_MULTI_PAL - TEMIC PAL ------------ */
++
++static struct tuner_params tuner_temic_4006fn5_multi_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_temic_40x6f_5_pal_ranges,
++ .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
++ },
++};
++
++/* 20-29 */
++/* ------------ TUNER_TEMIC_4009FR5_PAL - TEMIC PAL ------------ */
++
++static struct tuner_range tuner_temic_4009f_5_pal_ranges[] = {
++ { 16 * 141.00 /*MHz*/, 0x8e, 0xa0, },
++ { 16 * 464.00 /*MHz*/, 0x8e, 0x90, },
++ { 16 * 999.99 , 0x8e, 0x30, },
++};
++
++static struct tuner_params tuner_temic_4009f_5_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_temic_4009f_5_pal_ranges,
++ .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_TEMIC_4039FR5_NTSC - TEMIC NTSC ------------ */
++
++static struct tuner_range tuner_temic_4x3x_f_5_ntsc_ranges[] = {
++ { 16 * 158.00 /*MHz*/, 0x8e, 0xa0, },
++ { 16 * 453.00 /*MHz*/, 0x8e, 0x90, },
++ { 16 * 999.99 , 0x8e, 0x30, },
++};
++
++static struct tuner_params tuner_temic_4039fr5_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_temic_4x3x_f_5_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_temic_4x3x_f_5_ntsc_ranges),
++ },
++};
++
++/* ------------ TUNER_TEMIC_4046FM5 - TEMIC PAL ------------ */
++
++static struct tuner_params tuner_temic_4046fm5_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_temic_40x6f_5_pal_ranges,
++ .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_PHILIPS_PAL_DK - Philips PAL ------------ */
++
++static struct tuner_params tuner_philips_pal_dk_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_lg_pal_ranges,
++ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_PHILIPS_FQ1216ME - Philips PAL ------------ */
++
++static struct tuner_params tuner_philips_fq1216me_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_lg_pal_ranges,
++ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
++ .has_tda9887 = 1,
++ .port1_active = 1,
++ .port2_active = 1,
++ .port2_invert_for_secam_lc = 1,
++ },
++};
++
++/* ------------ TUNER_LG_PAL_I_FM - LGINNOTEK PAL_I ------------ */
++
++static struct tuner_params tuner_lg_pal_i_fm_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_lg_pal_ranges,
++ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_LG_PAL_I - LGINNOTEK PAL_I ------------ */
++
++static struct tuner_params tuner_lg_pal_i_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_lg_pal_ranges,
++ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_LG_NTSC_FM - LGINNOTEK NTSC ------------ */
++
++static struct tuner_range tuner_lg_ntsc_fm_ranges[] = {
++ { 16 * 210.00 /*MHz*/, 0x8e, 0xa0, },
++ { 16 * 497.00 /*MHz*/, 0x8e, 0x90, },
++ { 16 * 999.99 , 0x8e, 0x30, },
++};
++
++static struct tuner_params tuner_lg_ntsc_fm_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_lg_ntsc_fm_ranges,
++ .count = ARRAY_SIZE(tuner_lg_ntsc_fm_ranges),
++ },
++};
++
++/* ------------ TUNER_LG_PAL_FM - LGINNOTEK PAL ------------ */
++
++static struct tuner_params tuner_lg_pal_fm_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_lg_pal_ranges,
++ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_LG_PAL - LGINNOTEK PAL ------------ */
++
++static struct tuner_params tuner_lg_pal_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_lg_pal_ranges,
++ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
++ },
++};
++
++/* 30-39 */
++/* ------------ TUNER_TEMIC_4009FN5_MULTI_PAL_FM - TEMIC PAL ------------ */
++
++static struct tuner_params tuner_temic_4009_fn5_multi_pal_fm_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_temic_4009f_5_pal_ranges,
++ .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_SHARP_2U5JF5540_NTSC - SHARP NTSC ------------ */
++
++static struct tuner_range tuner_sharp_2u5jf5540_ntsc_ranges[] = {
++ { 16 * 137.25 /*MHz*/, 0x8e, 0x01, },
++ { 16 * 317.25 /*MHz*/, 0x8e, 0x02, },
++ { 16 * 999.99 , 0x8e, 0x08, },
++};
++
++static struct tuner_params tuner_sharp_2u5jf5540_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_sharp_2u5jf5540_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_sharp_2u5jf5540_ntsc_ranges),
++ },
++};
++
++/* ------------ TUNER_Samsung_PAL_TCPM9091PD27 - Samsung PAL ------------ */
++
++static struct tuner_range tuner_samsung_pal_tcpm9091pd27_ranges[] = {
++ { 16 * 169 /*MHz*/, 0x8e, 0xa0, },
++ { 16 * 464 /*MHz*/, 0x8e, 0x90, },
++ { 16 * 999.99 , 0x8e, 0x30, },
++};
++
++static struct tuner_params tuner_samsung_pal_tcpm9091pd27_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_samsung_pal_tcpm9091pd27_ranges,
++ .count = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_ranges),
++ },
++};
++
++/* ------------ TUNER_TEMIC_4106FH5 - TEMIC PAL ------------ */
++
++static struct tuner_params tuner_temic_4106fh5_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_temic_4009f_5_pal_ranges,
++ .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_TEMIC_4012FY5 - TEMIC PAL ------------ */
++
++static struct tuner_params tuner_temic_4012fy5_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_temic_pal_ranges,
++ .count = ARRAY_SIZE(tuner_temic_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_TEMIC_4136FY5 - TEMIC NTSC ------------ */
++
++static struct tuner_params tuner_temic_4136_fy5_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_temic_4x3x_f_5_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_temic_4x3x_f_5_ntsc_ranges),
++ },
++};
++
++/* ------------ TUNER_LG_PAL_NEW_TAPC - LGINNOTEK PAL ------------ */
++
++static struct tuner_range tuner_lg_new_tapc_ranges[] = {
++ { 16 * 170.00 /*MHz*/, 0x8e, 0x01, },
++ { 16 * 450.00 /*MHz*/, 0x8e, 0x02, },
++ { 16 * 999.99 , 0x8e, 0x08, },
++};
++
++static struct tuner_params tuner_lg_pal_new_tapc_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_lg_new_tapc_ranges,
++ .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
++ },
++};
++
++/* ------------ TUNER_PHILIPS_FM1216ME_MK3 - Philips PAL ------------ */
++
++static struct tuner_range tuner_fm1216me_mk3_pal_ranges[] = {
++ { 16 * 158.00 /*MHz*/, 0x8e, 0x01, },
++ { 16 * 442.00 /*MHz*/, 0x8e, 0x02, },
++ { 16 * 999.99 , 0x8e, 0x04, },
++};
++
++static struct tuner_params tuner_fm1216me_mk3_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_fm1216me_mk3_pal_ranges,
++ .count = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges),
++ .cb_first_if_lower_freq = 1,
++ .has_tda9887 = 1,
++ .port1_active = 1,
++ .port2_active = 1,
++ .port2_invert_for_secam_lc = 1,
++ .port1_fm_high_sensitivity = 1,
++ .default_top_mid = -2,
++ .default_top_secam_mid = -2,
++ .default_top_secam_high = -2,
++ },
++};
++
++/* ------------ TUNER_LG_NTSC_NEW_TAPC - LGINNOTEK NTSC ------------ */
++
++static struct tuner_params tuner_lg_ntsc_new_tapc_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_lg_new_tapc_ranges,
++ .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
++ },
++};
++
++/* 40-49 */
++/* ------------ TUNER_HITACHI_NTSC - HITACHI NTSC ------------ */
++
++static struct tuner_params tuner_hitachi_ntsc_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_lg_new_tapc_ranges,
++ .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
++ },
++};
++
++/* ------------ TUNER_PHILIPS_PAL_MK - Philips PAL ------------ */
++
++static struct tuner_range tuner_philips_pal_mk_pal_ranges[] = {
++ { 16 * 140.25 /*MHz*/, 0x8e, 0x01, },
++ { 16 * 463.25 /*MHz*/, 0x8e, 0xc2, },
++ { 16 * 999.99 , 0x8e, 0xcf, },
++};
++
++static struct tuner_params tuner_philips_pal_mk_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_philips_pal_mk_pal_ranges,
++ .count = ARRAY_SIZE(tuner_philips_pal_mk_pal_ranges),
++ },
++};
++
++/* ---- TUNER_PHILIPS_FCV1236D - Philips FCV1236D (ATSC/NTSC) ---- */
++
++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_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,
++ },
++};
++
++/* ------------ TUNER_PHILIPS_FM1236_MK3 - Philips NTSC ------------ */
++
++static struct tuner_range tuner_fm1236_mk3_ntsc_ranges[] = {
++ { 16 * 160.00 /*MHz*/, 0x8e, 0x01, },
++ { 16 * 442.00 /*MHz*/, 0x8e, 0x02, },
++ { 16 * 999.99 , 0x8e, 0x04, },
++};
++
++static struct tuner_params tuner_fm1236_mk3_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_fm1236_mk3_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
++ .cb_first_if_lower_freq = 1,
++ .has_tda9887 = 1,
++ .port1_active = 1,
++ .port2_active = 1,
++ .port1_fm_high_sensitivity = 1,
++ },
++};
++
++/* ------------ TUNER_PHILIPS_4IN1 - Philips NTSC ------------ */
++
++static struct tuner_params tuner_philips_4in1_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_fm1236_mk3_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
++ },
++};
++
++/* ------------ TUNER_MICROTUNE_4049FM5 - Microtune PAL ------------ */
++
++static struct tuner_params tuner_microtune_4049_fm5_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_temic_4009f_5_pal_ranges,
++ .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
++ .has_tda9887 = 1,
++ .port1_invert_for_secam_lc = 1,
++ .default_pll_gating_18 = 1,
++ .fm_gain_normal=1,
++ .radio_if = 1, /* 33.3 MHz */
++ },
++};
++
++/* ------------ TUNER_PANASONIC_VP27 - Panasonic NTSC ------------ */
++
++static struct tuner_range tuner_panasonic_vp27_ntsc_ranges[] = {
++ { 16 * 160.00 /*MHz*/, 0xce, 0x01, },
++ { 16 * 454.00 /*MHz*/, 0xce, 0x02, },
++ { 16 * 999.99 , 0xce, 0x08, },
++};
++
++static struct tuner_params tuner_panasonic_vp27_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_panasonic_vp27_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_panasonic_vp27_ntsc_ranges),
++ .has_tda9887 = 1,
++ .intercarrier_mode = 1,
++ .default_top_low = -3,
++ .default_top_mid = -3,
++ .default_top_high = -3,
++ },
++};
++
++/* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */
++
++static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = {
++ { 16 * 161.25 /*MHz*/, 0x8e, 0xa0, },
++ { 16 * 463.25 /*MHz*/, 0x8e, 0x90, },
++ { 16 * 999.99 , 0x8e, 0x30, },
++};
++
++static struct tuner_params tuner_tnf_8831bgff_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_tnf_8831bgff_pal_ranges,
++ .count = ARRAY_SIZE(tuner_tnf_8831bgff_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_MICROTUNE_4042FI5 - Microtune NTSC ------------ */
++
++static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = {
++ { 16 * 162.00 /*MHz*/, 0x8e, 0xa2, },
++ { 16 * 457.00 /*MHz*/, 0x8e, 0x94, },
++ { 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 */
++/* ------------ TUNER_TCL_2002N - TCL NTSC ------------ */
++
++static struct tuner_range tuner_tcl_2002n_ntsc_ranges[] = {
++ { 16 * 172.00 /*MHz*/, 0x8e, 0x01, },
++ { 16 * 448.00 /*MHz*/, 0x8e, 0x02, },
++ { 16 * 999.99 , 0x8e, 0x08, },
++};
++
++static struct tuner_params tuner_tcl_2002n_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_tcl_2002n_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_tcl_2002n_ntsc_ranges),
++ .cb_first_if_lower_freq = 1,
++ },
++};
++
++/* ------------ TUNER_PHILIPS_FM1256_IH3 - Philips PAL ------------ */
++
++static struct tuner_params tuner_philips_fm1256_ih3_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_fm1236_mk3_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
++ .radio_if = 1, /* 33.3 MHz */
++ },
++};
++
++/* ------------ 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, },
++ { 16 * 999.99 , 0x8e, 0x3c, },
++};
++
++static struct tuner_params tuner_thomson_dtt7610_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .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 ------------ */
++
++static struct tuner_range tuner_philips_fq1286_ntsc_ranges[] = {
++ { 16 * 160.00 /*MHz*/, 0x8e, 0x41, },
++ { 16 * 454.00 /*MHz*/, 0x8e, 0x42, },
++ { 16 * 999.99 , 0x8e, 0x04, },
++};
++
++static struct tuner_params tuner_philips_fq1286_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_philips_fq1286_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_philips_fq1286_ntsc_ranges),
++ },
++};
++
++/* ------------ TUNER_TCL_2002MB - TCL PAL ------------ */
++
++static struct tuner_range tuner_tcl_2002mb_pal_ranges[] = {
++ { 16 * 170.00 /*MHz*/, 0xce, 0x01, },
++ { 16 * 450.00 /*MHz*/, 0xce, 0x02, },
++ { 16 * 999.99 , 0xce, 0x08, },
++};
++
++static struct tuner_params tuner_tcl_2002mb_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_tcl_2002mb_pal_ranges,
++ .count = ARRAY_SIZE(tuner_tcl_2002mb_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_PHILIPS_FQ1216AME_MK4 - Philips PAL ------------ */
++
++static struct tuner_range tuner_philips_fq12_6a___mk4_pal_ranges[] = {
++ { 16 * 160.00 /*MHz*/, 0xce, 0x01, },
++ { 16 * 442.00 /*MHz*/, 0xce, 0x02, },
++ { 16 * 999.99 , 0xce, 0x04, },
++};
++
++static struct tuner_params tuner_philips_fq1216ame_mk4_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_philips_fq12_6a___mk4_pal_ranges,
++ .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_pal_ranges),
++ .has_tda9887 = 1,
++ .port1_active = 1,
++ .port2_invert_for_secam_lc = 1,
++ .default_top_mid = -2,
++ .default_top_secam_low = -2,
++ .default_top_secam_mid = -2,
++ .default_top_secam_high = -2,
++ },
++};
++
++/* ------------ TUNER_PHILIPS_FQ1236A_MK4 - Philips NTSC ------------ */
++
++static struct tuner_params tuner_philips_fq1236a_mk4_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_fm1236_mk3_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
++ },
++};
++
++/* ------------ TUNER_YMEC_TVF_8531MF - Philips NTSC ------------ */
++
++static struct tuner_params tuner_ymec_tvf_8531mf_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_philips_ntsc_m_ranges,
++ .count = ARRAY_SIZE(tuner_philips_ntsc_m_ranges),
++ },
++};
++
++/* ------------ TUNER_YMEC_TVF_5533MF - Philips NTSC ------------ */
++
++static struct tuner_range tuner_ymec_tvf_5533mf_ntsc_ranges[] = {
++ { 16 * 160.00 /*MHz*/, 0x8e, 0x01, },
++ { 16 * 454.00 /*MHz*/, 0x8e, 0x02, },
++ { 16 * 999.99 , 0x8e, 0x04, },
++};
++
++static struct tuner_params tuner_ymec_tvf_5533mf_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_ymec_tvf_5533mf_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_ymec_tvf_5533mf_ntsc_ranges),
++ },
++};
++
++/* 60-69 */
++/* ------------ TUNER_THOMSON_DTT761X - THOMSON ATSC ------------ */
++/* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
++
++static struct tuner_range tuner_thomson_dtt761x_ntsc_ranges[] = {
++ { 16 * 145.25 /*MHz*/, 0x8e, 0x39, },
++ { 16 * 415.25 /*MHz*/, 0x8e, 0x3a, },
++ { 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[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_thomson_dtt761x_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_thomson_dtt761x_ntsc_ranges),
++ .has_tda9887 = 1,
++ .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 ------------ */
++
++static struct tuner_range tuner_tena_9533_di_pal_ranges[] = {
++ { 16 * 160.25 /*MHz*/, 0x8e, 0x01, },
++ { 16 * 464.25 /*MHz*/, 0x8e, 0x02, },
++ { 16 * 999.99 , 0x8e, 0x04, },
++};
++
++static struct tuner_params tuner_tena_9533_di_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_tena_9533_di_pal_ranges,
++ .count = ARRAY_SIZE(tuner_tena_9533_di_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_PHILIPS_FMD1216ME_MK3 - Philips PAL ------------ */
++
++static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = {
++ { 16 * 160.00 /*MHz*/, 0x86, 0x51, },
++ { 16 * 442.00 /*MHz*/, 0x86, 0x52, },
++ { 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[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_philips_fmd1216me_mk3_pal_ranges,
++ .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges),
++ .has_tda9887 = 1,
++ .port1_active = 1,
++ .port2_active = 1,
++ .port2_fm_high_sensitivity = 1,
++ .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*/
++ },
++};
++
++
++/* ------ TUNER_LG_TDVS_H06XF - LG INNOTEK / INFINEON ATSC ----- */
++
++static struct tuner_range tuner_tua6034_ntsc_ranges[] = {
++ { 16 * 165.00 /*MHz*/, 0x8e, 0x01 },
++ { 16 * 450.00 /*MHz*/, 0x8e, 0x02 },
++ { 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[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .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 ------------ */
++
++static struct tuner_range tuner_ymec_tvf66t5_b_dff_pal_ranges[] = {
++ { 16 * 160.25 /*MHz*/, 0x8e, 0x01, },
++ { 16 * 464.25 /*MHz*/, 0x8e, 0x02, },
++ { 16 * 999.99 , 0x8e, 0x08, },
++};
++
++static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_ymec_tvf66t5_b_dff_pal_ranges,
++ .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_pal_ranges),
++ },
++};
++
++/* ------------ TUNER_LG_NTSC_TALN_MINI - LGINNOTEK NTSC ------------ */
++
++static struct tuner_range tuner_lg_taln_ntsc_ranges[] = {
++ { 16 * 137.25 /*MHz*/, 0x8e, 0x01, },
++ { 16 * 373.25 /*MHz*/, 0x8e, 0x02, },
++ { 16 * 999.99 , 0x8e, 0x08, },
++};
++
++static struct tuner_range tuner_lg_taln_pal_secam_ranges[] = {
++ { 16 * 150.00 /*MHz*/, 0x8e, 0x01, },
++ { 16 * 425.00 /*MHz*/, 0x8e, 0x02, },
++ { 16 * 999.99 , 0x8e, 0x08, },
++};
++
++static struct tuner_params tuner_lg_taln_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_lg_taln_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_lg_taln_ntsc_ranges),
++ },{
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_lg_taln_pal_secam_ranges,
++ .count = ARRAY_SIZE(tuner_lg_taln_pal_secam_ranges),
++ },
++};
++
++/* ------------ TUNER_PHILIPS_TD1316 - Philips PAL ------------ */
++
++static struct tuner_range tuner_philips_td1316_pal_ranges[] = {
++ { 16 * 160.00 /*MHz*/, 0xc8, 0xa1, },
++ { 16 * 442.00 /*MHz*/, 0xc8, 0xa2, },
++ { 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 ------------ */
++
++static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = {
++ { 16 * 157.25 /*MHz*/, 0xce, 0x01, },
++ { 16 * 454.00 /*MHz*/, 0xce, 0x02, },
++ { 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[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .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--------- */
++/* This is known to work with Tenna TVF58t5-MFF and TVF5835 MFF
++ * but it is expected to work also with other Tenna/Ymec
++ * models based on TI SN 761677 chip on both PAL and NTSC
+ */
-+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;
++static struct tuner_range tuner_tnf_5335_d_if_pal_ranges[] = {
++ { 16 * 168.25 /*MHz*/, 0x8e, 0x01, },
++ { 16 * 471.25 /*MHz*/, 0x8e, 0x02, },
++ { 16 * 999.99 , 0x8e, 0x08, },
++};
+
-+ 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;
-+ }
++static struct tuner_range tuner_tnf_5335mf_ntsc_ranges[] = {
++ { 16 * 169.25 /*MHz*/, 0x8e, 0x01, },
++ { 16 * 469.25 /*MHz*/, 0x8e, 0x02, },
++ { 16 * 999.99 , 0x8e, 0x08, },
++};
+
-+ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++static struct tuner_params tuner_tnf_5335mf_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_tnf_5335mf_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_tnf_5335mf_ntsc_ranges),
++ },
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_tnf_5335_d_if_pal_ranges,
++ .count = ARRAY_SIZE(tuner_tnf_5335_d_if_pal_ranges),
++ },
++};
+
-+retry:
-+ if (unlikely(test_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status))) {
-+ ret = -EBUSY;
-+ goto unlock;
-+ }
++/* 70-79 */
++/* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */
+
-+ if (tx->txreq.sg_count > ipath_sdma_descq_freecnt(dd)) {
-+ if (ipath_sdma_make_progress(dd))
-+ goto retry;
-+ ret = -ENOBUFS;
-+ goto unlock;
-+ }
++/* '+ 4' turns on the Low Noise Amplifier */
++static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = {
++ { 16 * 130.00 /*MHz*/, 0xce, 0x01 + 4, },
++ { 16 * 364.50 /*MHz*/, 0xce, 0x02 + 4, },
++ { 16 * 999.99 , 0xce, 0x08 + 4, },
++};
+
-+ 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;
-+ }
++static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_NTSC,
++ .ranges = tuner_samsung_tcpn_2121p30a_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_ntsc_ranges),
++ },
++};
+
-+ dwoffset = tx->map_len >> 2;
-+ make_sdma_desc(dd, sdmadesc, (u64) addr, dwoffset, 0);
++/* ------------ TUNER_THOMSON_FE6600 - DViCO Hybrid PAL ------------ */
+
-+ /* SDmaFirstDesc */
-+ sdmadesc[0] |= 1ULL << 12;
-+ if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_USELARGEBUF)
-+ sdmadesc[0] |= 1ULL << 14; /* SDmaUseLargeBuf */
++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, },
++};
+
-+ /* 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]);
++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, },
++};
+
-+ if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_FREEDESC)
-+ tx->txreq.start_idx = tail;
++static struct tuner_params tuner_thomson_fe6600_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .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*/,
++ },
++};
+
-+ /* increment the tail */
-+ if (++tail == dd->ipath_sdma_descq_cnt) {
-+ tail = 0;
-+ descqp = &dd->ipath_sdma_descq[0].qw[0];
-+ ++dd->ipath_sdma_generation;
-+ }
++/* ------------ TUNER_SAMSUNG_TCPG_6121P30A - Samsung PAL ------------ */
+
-+ sge = &ss->sge;
-+ while (dwords) {
-+ u32 dw;
-+ u32 len;
++/* '+ 4' turns on the Low Noise Amplifier */
++static struct tuner_range tuner_samsung_tcpg_6121p30a_pal_ranges[] = {
++ { 16 * 146.25 /*MHz*/, 0xce, 0x01 + 4, },
++ { 16 * 428.50 /*MHz*/, 0xce, 0x02 + 4, },
++ { 16 * 999.99 , 0xce, 0x08 + 4, },
++};
+
-+ 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]);
++static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = {
++ {
++ .type = TUNER_PARAM_TYPE_PAL,
++ .ranges = tuner_samsung_tcpg_6121p30a_pal_ranges,
++ .count = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_pal_ranges),
++ .has_tda9887 = 1,
++ .port1_active = 1,
++ .port2_active = 1,
++ .port2_invert_for_secam_lc = 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;
-+ }
++struct tunertype tuners[] = {
++ /* 0-9 */
++ [TUNER_TEMIC_PAL] = { /* TEMIC PAL */
++ .name = "Temic PAL (4002 FH5)",
++ .params = tuner_temic_pal_params,
++ .count = ARRAY_SIZE(tuner_temic_pal_params),
++ },
++ [TUNER_PHILIPS_PAL_I] = { /* Philips PAL_I */
++ .name = "Philips PAL_I (FI1246 and compatibles)",
++ .params = tuner_philips_pal_i_params,
++ .count = ARRAY_SIZE(tuner_philips_pal_i_params),
++ },
++ [TUNER_PHILIPS_NTSC] = { /* Philips NTSC */
++ .name = "Philips NTSC (FI1236,FM1236 and compatibles)",
++ .params = tuner_philips_ntsc_params,
++ .count = ARRAY_SIZE(tuner_philips_ntsc_params),
++ },
++ [TUNER_PHILIPS_SECAM] = { /* Philips SECAM */
++ .name = "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)",
++ .params = tuner_philips_secam_params,
++ .count = ARRAY_SIZE(tuner_philips_secam_params),
++ },
++ [TUNER_ABSENT] = { /* Tuner Absent */
++ .name = "NoTuner",
++ },
++ [TUNER_PHILIPS_PAL] = { /* Philips PAL */
++ .name = "Philips PAL_BG (FI1216 and compatibles)",
++ .params = tuner_philips_pal_params,
++ .count = ARRAY_SIZE(tuner_philips_pal_params),
++ },
++ [TUNER_TEMIC_NTSC] = { /* TEMIC NTSC */
++ .name = "Temic NTSC (4032 FY5)",
++ .params = tuner_temic_ntsc_params,
++ .count = ARRAY_SIZE(tuner_temic_ntsc_params),
++ },
++ [TUNER_TEMIC_PAL_I] = { /* TEMIC PAL_I */
++ .name = "Temic PAL_I (4062 FY5)",
++ .params = tuner_temic_pal_i_params,
++ .count = ARRAY_SIZE(tuner_temic_pal_i_params),
++ },
++ [TUNER_TEMIC_4036FY5_NTSC] = { /* TEMIC NTSC */
++ .name = "Temic NTSC (4036 FY5)",
++ .params = tuner_temic_4036fy5_ntsc_params,
++ .count = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_params),
++ },
++ [TUNER_ALPS_TSBH1_NTSC] = { /* TEMIC NTSC */
++ .name = "Alps HSBH1",
++ .params = tuner_alps_tsbh1_ntsc_params,
++ .count = ARRAY_SIZE(tuner_alps_tsbh1_ntsc_params),
++ },
+
-+ 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);
-+ }
++ /* 10-19 */
++ [TUNER_ALPS_TSBE1_PAL] = { /* TEMIC PAL */
++ .name = "Alps TSBE1",
++ .params = tuner_alps_tsb_1_params,
++ .count = ARRAY_SIZE(tuner_alps_tsb_1_params),
++ },
++ [TUNER_ALPS_TSBB5_PAL_I] = { /* Alps PAL_I */
++ .name = "Alps TSBB5",
++ .params = tuner_alps_tsbb5_params,
++ .count = ARRAY_SIZE(tuner_alps_tsbb5_params),
++ },
++ [TUNER_ALPS_TSBE5_PAL] = { /* Alps PAL */
++ .name = "Alps TSBE5",
++ .params = tuner_alps_tsbe5_params,
++ .count = ARRAY_SIZE(tuner_alps_tsbe5_params),
++ },
++ [TUNER_ALPS_TSBC5_PAL] = { /* Alps PAL */
++ .name = "Alps TSBC5",
++ .params = tuner_alps_tsbc5_params,
++ .count = ARRAY_SIZE(tuner_alps_tsbc5_params),
++ },
++ [TUNER_TEMIC_4006FH5_PAL] = { /* TEMIC PAL */
++ .name = "Temic PAL_BG (4006FH5)",
++ .params = tuner_temic_4006fh5_params,
++ .count = ARRAY_SIZE(tuner_temic_4006fh5_params),
++ },
++ [TUNER_ALPS_TSHC6_NTSC] = { /* Alps NTSC */
++ .name = "Alps TSCH6",
++ .params = tuner_alps_tshc6_params,
++ .count = ARRAY_SIZE(tuner_alps_tshc6_params),
++ },
++ [TUNER_TEMIC_PAL_DK] = { /* TEMIC PAL */
++ .name = "Temic PAL_DK (4016 FY5)",
++ .params = tuner_temic_pal_dk_params,
++ .count = ARRAY_SIZE(tuner_temic_pal_dk_params),
++ },
++ [TUNER_PHILIPS_NTSC_M] = { /* Philips NTSC */
++ .name = "Philips NTSC_M (MK2)",
++ .params = tuner_philips_ntsc_m_params,
++ .count = ARRAY_SIZE(tuner_philips_ntsc_m_params),
++ },
++ [TUNER_TEMIC_4066FY5_PAL_I] = { /* TEMIC PAL_I */
++ .name = "Temic PAL_I (4066 FY5)",
++ .params = tuner_temic_4066fy5_pal_i_params,
++ .count = ARRAY_SIZE(tuner_temic_4066fy5_pal_i_params),
++ },
++ [TUNER_TEMIC_4006FN5_MULTI_PAL] = { /* TEMIC PAL */
++ .name = "Temic PAL* auto (4006 FN5)",
++ .params = tuner_temic_4006fn5_multi_params,
++ .count = ARRAY_SIZE(tuner_temic_4006fn5_multi_params),
++ },
+
-+ /* Commit writes to memory and advance the tail on the chip */
-+ wmb();
-+ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmatail, tail);
++ /* 20-29 */
++ [TUNER_TEMIC_4009FR5_PAL] = { /* TEMIC PAL */
++ .name = "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)",
++ .params = tuner_temic_4009f_5_params,
++ .count = ARRAY_SIZE(tuner_temic_4009f_5_params),
++ },
++ [TUNER_TEMIC_4039FR5_NTSC] = { /* TEMIC NTSC */
++ .name = "Temic NTSC (4039 FR5)",
++ .params = tuner_temic_4039fr5_params,
++ .count = ARRAY_SIZE(tuner_temic_4039fr5_params),
++ },
++ [TUNER_TEMIC_4046FM5] = { /* TEMIC PAL */
++ .name = "Temic PAL/SECAM multi (4046 FM5)",
++ .params = tuner_temic_4046fm5_params,
++ .count = ARRAY_SIZE(tuner_temic_4046fm5_params),
++ },
++ [TUNER_PHILIPS_PAL_DK] = { /* Philips PAL */
++ .name = "Philips PAL_DK (FI1256 and compatibles)",
++ .params = tuner_philips_pal_dk_params,
++ .count = ARRAY_SIZE(tuner_philips_pal_dk_params),
++ },
++ [TUNER_PHILIPS_FQ1216ME] = { /* Philips PAL */
++ .name = "Philips PAL/SECAM multi (FQ1216ME)",
++ .params = tuner_philips_fq1216me_params,
++ .count = ARRAY_SIZE(tuner_philips_fq1216me_params),
++ },
++ [TUNER_LG_PAL_I_FM] = { /* LGINNOTEK PAL_I */
++ .name = "LG PAL_I+FM (TAPC-I001D)",
++ .params = tuner_lg_pal_i_fm_params,
++ .count = ARRAY_SIZE(tuner_lg_pal_i_fm_params),
++ },
++ [TUNER_LG_PAL_I] = { /* LGINNOTEK PAL_I */
++ .name = "LG PAL_I (TAPC-I701D)",
++ .params = tuner_lg_pal_i_params,
++ .count = ARRAY_SIZE(tuner_lg_pal_i_params),
++ },
++ [TUNER_LG_NTSC_FM] = { /* LGINNOTEK NTSC */
++ .name = "LG NTSC+FM (TPI8NSR01F)",
++ .params = tuner_lg_ntsc_fm_params,
++ .count = ARRAY_SIZE(tuner_lg_ntsc_fm_params),
++ },
++ [TUNER_LG_PAL_FM] = { /* LGINNOTEK PAL */
++ .name = "LG PAL_BG+FM (TPI8PSB01D)",
++ .params = tuner_lg_pal_fm_params,
++ .count = ARRAY_SIZE(tuner_lg_pal_fm_params),
++ },
++ [TUNER_LG_PAL] = { /* LGINNOTEK PAL */
++ .name = "LG PAL_BG (TPI8PSB11D)",
++ .params = tuner_lg_pal_params,
++ .count = ARRAY_SIZE(tuner_lg_pal_params),
++ },
+
-+ 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);
++ /* 30-39 */
++ [TUNER_TEMIC_4009FN5_MULTI_PAL_FM] = { /* TEMIC PAL */
++ .name = "Temic PAL* auto + FM (4009 FN5)",
++ .params = tuner_temic_4009_fn5_multi_pal_fm_params,
++ .count = ARRAY_SIZE(tuner_temic_4009_fn5_multi_pal_fm_params),
++ },
++ [TUNER_SHARP_2U5JF5540_NTSC] = { /* SHARP NTSC */
++ .name = "SHARP NTSC_JP (2U5JF5540)",
++ .params = tuner_sharp_2u5jf5540_params,
++ .count = ARRAY_SIZE(tuner_sharp_2u5jf5540_params),
++ },
++ [TUNER_Samsung_PAL_TCPM9091PD27] = { /* Samsung PAL */
++ .name = "Samsung PAL TCPM9091PD27",
++ .params = tuner_samsung_pal_tcpm9091pd27_params,
++ .count = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_params),
++ },
++ [TUNER_MT2032] = { /* Microtune PAL|NTSC */
++ .name = "MT20xx universal",
++ /* see mt20xx.c for details */ },
++ [TUNER_TEMIC_4106FH5] = { /* TEMIC PAL */
++ .name = "Temic PAL_BG (4106 FH5)",
++ .params = tuner_temic_4106fh5_params,
++ .count = ARRAY_SIZE(tuner_temic_4106fh5_params),
++ },
++ [TUNER_TEMIC_4012FY5] = { /* TEMIC PAL */
++ .name = "Temic PAL_DK/SECAM_L (4012 FY5)",
++ .params = tuner_temic_4012fy5_params,
++ .count = ARRAY_SIZE(tuner_temic_4012fy5_params),
++ },
++ [TUNER_TEMIC_4136FY5] = { /* TEMIC NTSC */
++ .name = "Temic NTSC (4136 FY5)",
++ .params = tuner_temic_4136_fy5_params,
++ .count = ARRAY_SIZE(tuner_temic_4136_fy5_params),
++ },
++ [TUNER_LG_PAL_NEW_TAPC] = { /* LGINNOTEK PAL */
++ .name = "LG PAL (newer TAPC series)",
++ .params = tuner_lg_pal_new_tapc_params,
++ .count = ARRAY_SIZE(tuner_lg_pal_new_tapc_params),
++ },
++ [TUNER_PHILIPS_FM1216ME_MK3] = { /* Philips PAL */
++ .name = "Philips PAL/SECAM multi (FM1216ME MK3)",
++ .params = tuner_fm1216me_mk3_params,
++ .count = ARRAY_SIZE(tuner_fm1216me_mk3_params),
++ },
++ [TUNER_LG_NTSC_NEW_TAPC] = { /* LGINNOTEK NTSC */
++ .name = "LG NTSC (newer TAPC series)",
++ .params = tuner_lg_ntsc_new_tapc_params,
++ .count = ARRAY_SIZE(tuner_lg_ntsc_new_tapc_params),
++ },
+
-+unlock:
-+ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
-+fail:
-+ return ret;
-+}
-diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c
-index f772102..e3d80ca 100644
---- a/drivers/infiniband/hw/ipath/ipath_srq.c
-+++ b/drivers/infiniband/hw/ipath/ipath_srq.c
-@@ -1,5 +1,5 @@
- /*
-- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
-+ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
- * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
-@@ -245,7 +245,8 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
- sizeof(offset_addr));
- if (ret)
- goto bail_free;
-- udata->outbuf = (void __user *) offset_addr;
-+ udata->outbuf =
-+ (void __user *) (unsigned long) offset_addr;
- ret = ib_copy_to_udata(udata, &offset,
- sizeof(offset));
- if (ret)
-diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c
-index d2725cd..c8e3d65 100644
---- a/drivers/infiniband/hw/ipath/ipath_stats.c
-+++ b/drivers/infiniband/hw/ipath/ipath_stats.c
-@@ -1,5 +1,5 @@
- /*
-- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
-+ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
- * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
-@@ -136,6 +136,7 @@ static void ipath_qcheck(struct ipath_devdata *dd)
- struct ipath_portdata *pd = dd->ipath_pd[0];
- size_t blen = 0;
- char buf[128];
-+ u32 hdrqtail;
-
- *buf = 0;
- if (pd->port_hdrqfull != dd->ipath_p0_hdrqfull) {
-@@ -174,17 +175,18 @@ static void ipath_qcheck(struct ipath_devdata *dd)
- if (blen)
- ipath_dbg("%s\n", buf);
-
-- if (pd->port_head != (u32)
-- le64_to_cpu(*dd->ipath_hdrqtailptr)) {
-+ hdrqtail = ipath_get_hdrqtail(pd);
-+ if (pd->port_head != hdrqtail) {
- if (dd->ipath_lastport0rcv_cnt ==
- ipath_stats.sps_port0pkts) {
- ipath_cdbg(PKT, "missing rcv interrupts? "
-- "port0 hd=%llx tl=%x; port0pkts %llx\n",
-- (unsigned long long)
-- le64_to_cpu(*dd->ipath_hdrqtailptr),
-- pd->port_head,
-+ "port0 hd=%x tl=%x; port0pkts %llx; write"
-+ " hd (w/intr)\n",
-+ pd->port_head, hdrqtail,
- (unsigned long long)
- ipath_stats.sps_port0pkts);
-+ ipath_write_ureg(dd, ur_rcvhdrhead, hdrqtail |
-+ dd->ipath_rhdrhead_intr_off, pd->port_port);
- }
- dd->ipath_lastport0rcv_cnt = ipath_stats.sps_port0pkts;
- }
-@@ -290,11 +292,11 @@ void ipath_get_faststats(unsigned long opaque)
- && time_after(jiffies, dd->ipath_unmasktime)) {
- char ebuf[256];
- int iserr;
-- iserr = ipath_decode_err(ebuf, sizeof ebuf,
-- dd->ipath_maskederrs);
-+ iserr = ipath_decode_err(dd, ebuf, sizeof ebuf,
-+ dd->ipath_maskederrs);
- if (dd->ipath_maskederrs &
-- ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
-- INFINIPATH_E_PKTERRS ))
-+ ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
-+ INFINIPATH_E_PKTERRS))
- ipath_dev_err(dd, "Re-enabling masked errors "
- "(%s)\n", ebuf);
- else {
-@@ -306,17 +308,18 @@ void ipath_get_faststats(unsigned long opaque)
- * level.
- */
- if (iserr)
-- ipath_dbg("Re-enabling queue full errors (%s)\n",
-- ebuf);
-+ ipath_dbg(
-+ "Re-enabling queue full errors (%s)\n",
-+ ebuf);
- else
- ipath_cdbg(ERRPKT, "Re-enabling packet"
-- " problem interrupt (%s)\n", ebuf);
-+ " problem interrupt (%s)\n", ebuf);
- }
-
- /* re-enable masked errors */
- dd->ipath_errormask |= dd->ipath_maskederrs;
- ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
-- dd->ipath_errormask);
-+ dd->ipath_errormask);
- dd->ipath_maskederrs = 0;
- }
-
-diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c
-index 56dfc8a..a6c8efb 100644
---- a/drivers/infiniband/hw/ipath/ipath_sysfs.c
-+++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c
-@@ -1,5 +1,5 @@
- /*
-- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
-+ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
- * Copyright (c) 2006 PathScale, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
-@@ -34,6 +34,7 @@
- #include <linux/ctype.h>
-
- #include "ipath_kernel.h"
-+#include "ipath_verbs.h"
- #include "ipath_common.h"
-
- /**
-@@ -163,6 +164,15 @@ static ssize_t show_boardversion(struct device *dev,
- return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_boardversion);
- }
-
-+static ssize_t show_localbus_info(struct device *dev,
-+ struct device_attribute *attr,
-+ char *buf)
-+{
-+ struct ipath_devdata *dd = dev_get_drvdata(dev);
-+ /* The string printed here is already newline-terminated. */
-+ return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_lbus_info);
-+}
++ /* 40-49 */
++ [TUNER_HITACHI_NTSC] = { /* HITACHI NTSC */
++ .name = "HITACHI V7-J180AT",
++ .params = tuner_hitachi_ntsc_params,
++ .count = ARRAY_SIZE(tuner_hitachi_ntsc_params),
++ },
++ [TUNER_PHILIPS_PAL_MK] = { /* Philips PAL */
++ .name = "Philips PAL_MK (FI1216 MK)",
++ .params = tuner_philips_pal_mk_params,
++ .count = ARRAY_SIZE(tuner_philips_pal_mk_params),
++ },
++ [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)",
++ .params = tuner_fm1236_mk3_params,
++ .count = ARRAY_SIZE(tuner_fm1236_mk3_params),
++ },
++ [TUNER_PHILIPS_4IN1] = { /* Philips NTSC */
++ .name = "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)",
++ .params = tuner_philips_4in1_params,
++ .count = ARRAY_SIZE(tuner_philips_4in1_params),
++ },
++ [TUNER_MICROTUNE_4049FM5] = { /* Microtune PAL */
++ .name = "Microtune 4049 FM5",
++ .params = tuner_microtune_4049_fm5_params,
++ .count = ARRAY_SIZE(tuner_microtune_4049_fm5_params),
++ },
++ [TUNER_PANASONIC_VP27] = { /* Panasonic NTSC */
++ .name = "Panasonic VP27s/ENGE4324D",
++ .params = tuner_panasonic_vp27_params,
++ .count = ARRAY_SIZE(tuner_panasonic_vp27_params),
++ },
++ [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */
++ .name = "LG NTSC (TAPE series)",
++ .params = tuner_fm1236_mk3_params,
++ .count = ARRAY_SIZE(tuner_fm1236_mk3_params),
++ },
++ [TUNER_TNF_8831BGFF] = { /* Philips PAL */
++ .name = "Tenna TNF 8831 BGFF)",
++ .params = tuner_tnf_8831bgff_params,
++ .count = ARRAY_SIZE(tuner_tnf_8831bgff_params),
++ },
++ [TUNER_MICROTUNE_4042FI5] = { /* Microtune NTSC */
++ .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,
++ },
+
- 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;
- }
++ /* 50-59 */
++ [TUNER_TCL_2002N] = { /* TCL NTSC */
++ .name = "TCL 2002N",
++ .params = tuner_tcl_2002n_params,
++ .count = ARRAY_SIZE(tuner_tcl_2002n_params),
++ },
++ [TUNER_PHILIPS_FM1256_IH3] = { /* Philips PAL */
++ .name = "Philips PAL/SECAM_D (FM 1256 I-H3)",
++ .params = tuner_philips_fm1256_ih3_params,
++ .count = ARRAY_SIZE(tuner_philips_fm1256_ih3_params),
++ },
++ [TUNER_THOMSON_DTT7610] = { /* THOMSON ATSC */
++ .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",
++ .params = tuner_philips_fq1286_params,
++ .count = ARRAY_SIZE(tuner_philips_fq1286_params),
++ },
++ [TUNER_PHILIPS_TDA8290] = { /* Philips PAL|NTSC */
++ .name = "Philips/NXP TDA 8290/8295 + 8275/8275A/18271",
++ /* see tda8290.c for details */ },
++ [TUNER_TCL_2002MB] = { /* TCL PAL */
++ .name = "TCL 2002MB",
++ .params = tuner_tcl_2002mb_params,
++ .count = ARRAY_SIZE(tuner_tcl_2002mb_params),
++ },
++ [TUNER_PHILIPS_FQ1216AME_MK4] = { /* Philips PAL */
++ .name = "Philips PAL/SECAM multi (FQ1216AME MK4)",
++ .params = tuner_philips_fq1216ame_mk4_params,
++ .count = ARRAY_SIZE(tuner_philips_fq1216ame_mk4_params),
++ },
++ [TUNER_PHILIPS_FQ1236A_MK4] = { /* Philips NTSC */
++ .name = "Philips FQ1236A MK4",
++ .params = tuner_philips_fq1236a_mk4_params,
++ .count = ARRAY_SIZE(tuner_philips_fq1236a_mk4_params),
++ },
++ [TUNER_YMEC_TVF_8531MF] = { /* Philips NTSC */
++ .name = "Ymec TVision TVF-8531MF/8831MF/8731MF",
++ .params = tuner_ymec_tvf_8531mf_params,
++ .count = ARRAY_SIZE(tuner_ymec_tvf_8531mf_params),
++ },
++ [TUNER_YMEC_TVF_5533MF] = { /* Philips NTSC */
++ .name = "Ymec TVision TVF-5533MF",
++ .params = tuner_ymec_tvf_5533mf_params,
++ .count = ARRAY_SIZE(tuner_ymec_tvf_5533mf_params),
++ },
+
- /*
- * 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;
++ /* 60-69 */
++ [TUNER_THOMSON_DTT761X] = { /* THOMSON ATSC */
++ /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
++ .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",
++ .params = tuner_tena_9533_di_params,
++ .count = ARRAY_SIZE(tuner_tena_9533_di_params),
++ },
++ [TUNER_TEA5767] = { /* Philips RADIO */
++ .name = "Philips TEA5767HN FM Radio",
++ /* see tea5767.c for details */
++ },
++ [TUNER_PHILIPS_FMD1216ME_MK3] = { /* Philips PAL */
++ .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",
++ .params = tuner_ymec_tvf66t5_b_dff_params,
++ .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_params),
++ },
++ [TUNER_LG_TALN] = { /* LGINNOTEK NTSC / PAL / SECAM */
++ .name = "LG TALN series",
++ .params = tuner_lg_taln_params,
++ .count = ARRAY_SIZE(tuner_lg_taln_params),
++ },
++ [TUNER_PHILIPS_TD1316] = { /* Philips PAL */
++ .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",
++ .params = tuner_tnf_5335mf_params,
++ .count = ARRAY_SIZE(tuner_tnf_5335mf_params),
++ },
+
-+ 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;
-+ }
++ /* 70-79 */
++ [TUNER_SAMSUNG_TCPN_2121P30A] = { /* Samsung NTSC */
++ .name = "Samsung TCPN 2121P30A",
++ .params = tuner_samsung_tcpn_2121p30a_params,
++ .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_params),
++ },
++ [TUNER_XC2028] = { /* Xceive 2028 */
++ .name = "Xceive xc2028/xc3028 tuner",
++ /* see tuner-xc2028.c for details */
++ },
++ [TUNER_THOMSON_FE6600] = { /* Thomson PAL / DVB-T */
++ .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",
++ .params = tuner_samsung_tcpg_6121p30a_params,
++ .count = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_params),
++ },
++ [TUNER_TDA9887] = { /* Philips TDA 9887 IF PLL Demodulator.
++ This chip is part of some modern tuners */
++ .name = "Philips TDA988[5,6,7] IF PLL Demodulator",
++ /* see tda9887.c for details */
++ },
++ [TUNER_TEA5761] = { /* Philips RADIO */
++ .name = "Philips TEA5761 FM Radio",
++ /* see tea5767.c for details */
++ },
++ [TUNER_XC5000] = { /* Xceive 5000 */
++ .name = "Xceive 5000 tuner",
++ /* see xc5000.c for details */
++ },
++};
++EXPORT_SYMBOL(tuners);
+
-+bail:
-+ return ret;
-+}
++unsigned const int tuner_count = ARRAY_SIZE(tuners);
++EXPORT_SYMBOL(tuner_count);
+
-+/*
-+ * dump tempsense regs. in decimal, to ease shell-scripts.
++MODULE_DESCRIPTION("Simple tuner device type database");
++MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/common/tuners/tuner-xc2028-types.h b/drivers/media/common/tuners/tuner-xc2028-types.h
+new file mode 100644
+index 0000000..74dc46a
+--- /dev/null
++++ b/drivers/media/common/tuners/tuner-xc2028-types.h
+@@ -0,0 +1,141 @@
++/* tuner-xc2028_types
++ *
++ * This file includes internal tipes to be used inside tuner-xc2028.
++ * Shouldn't be included outside tuner-xc2028
++ *
++ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab at infradead.org)
++ * This code is placed under the terms of the GNU General Public License v2
+ */
-+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;
-+}
++/* xc3028 firmware types */
+
- 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
++/* BASE firmware should be loaded before any other firmware */
++#define BASE (1<<0)
++#define BASE_TYPES (BASE|F8MHZ|MTS|FM|INPUT1|INPUT2|INIT1)
++
++/* F8MHZ marks BASE firmwares for 8 MHz Bandwidth */
++#define F8MHZ (1<<1)
++
++/* Multichannel Television Sound (MTS)
++ Those firmwares are capable of using xc2038 DSP to decode audio and
++ produce a baseband audio output on some pins of the chip.
++ There are MTS firmwares for the most used video standards. It should be
++ required to use MTS firmwares, depending on the way audio is routed into
++ the bridge chip
++ */
++#define MTS (1<<2)
++
++/* FIXME: I have no idea what's the difference between
++ D2620 and D2633 firmwares
++ */
++#define D2620 (1<<3)
++#define D2633 (1<<4)
++
++/* DTV firmwares for 6, 7 and 8 MHz
++ DTV6 - 6MHz - ATSC/DVB-C/DVB-T/ISDB-T/DOCSIS
++ DTV8 - 8MHz - DVB-C/DVB-T
++ */
++#define DTV6 (1 << 5)
++#define QAM (1 << 6)
++#define DTV7 (1<<7)
++#define DTV78 (1<<8)
++#define DTV8 (1<<9)
++
++#define DTV_TYPES (D2620|D2633|DTV6|QAM|DTV7|DTV78|DTV8|ATSC)
++
++/* There's a FM | BASE firmware + FM specific firmware (std=0) */
++#define FM (1<<10)
++
++#define STD_SPECIFIC_TYPES (MTS|FM|LCD|NOGD)
++
++/* Applies only for FM firmware
++ Makes it use RF input 1 (pin #2) instead of input 2 (pin #4)
++ */
++#define INPUT1 (1<<11)
++
++
++/* 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)
++
++/* Old firmwares were broken into init0 and init1 */
++#define INIT1 (1<<14)
++
++/* SCODE firmware selects particular behaviours */
++#define MONO (1 << 15)
++#define ATSC (1 << 16)
++#define IF (1 << 17)
++#define LG60 (1 << 18)
++#define ATI638 (1 << 19)
++#define OREN538 (1 << 20)
++#define OREN36 (1 << 21)
++#define TOYOTA388 (1 << 22)
++#define TOYOTA794 (1 << 23)
++#define DIBCOM52 (1 << 24)
++#define ZARLINK456 (1 << 25)
++#define CHINA (1 << 26)
++#define F6MHZ (1 << 27)
++#define INPUT2 (1 << 28)
++#define SCODE (1 << 29)
++
++/* This flag identifies that the scode table has a new format */
++#define HAS_IF (1 << 30)
++
++/* There are different scode tables for MTS and non-MTS.
++ The MTS firmwares support mono only
++ */
++#define SCODE_TYPES (SCODE | MTS)
++
++
++/* 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)
++
++/* Audio types */
++
++#define V4L2_STD_A2_A (1LL<<32)
++#define V4L2_STD_A2_B (1LL<<33)
++#define V4L2_STD_NICAM_A (1LL<<34)
++#define V4L2_STD_NICAM_B (1LL<<35)
++#define V4L2_STD_AM (1LL<<36)
++#define V4L2_STD_BTSC (1LL<<37)
++#define V4L2_STD_EIAJ (1LL<<38)
++
++#define V4L2_STD_A2 (V4L2_STD_A2_A | V4L2_STD_A2_B)
++#define V4L2_STD_NICAM (V4L2_STD_NICAM_A | V4L2_STD_NICAM_B)
++
++/* To preserve backward compatibilty,
++ (std & V4L2_STD_AUDIO) = 0 means that ALL audio stds are supported
++ */
++
++#define V4L2_STD_AUDIO (V4L2_STD_A2 | \
++ V4L2_STD_NICAM | \
++ V4L2_STD_AM | \
++ V4L2_STD_BTSC | \
++ V4L2_STD_EIAJ)
++
++/* Used standards with audio restrictions */
++
++#define V4L2_STD_PAL_BG_A2_A (V4L2_STD_PAL_BG | V4L2_STD_A2_A)
++#define V4L2_STD_PAL_BG_A2_B (V4L2_STD_PAL_BG | V4L2_STD_A2_B)
++#define V4L2_STD_PAL_BG_NICAM_A (V4L2_STD_PAL_BG | V4L2_STD_NICAM_A)
++#define V4L2_STD_PAL_BG_NICAM_B (V4L2_STD_PAL_BG | V4L2_STD_NICAM_B)
++#define V4L2_STD_PAL_DK_A2 (V4L2_STD_PAL_DK | V4L2_STD_A2)
++#define V4L2_STD_PAL_DK_NICAM (V4L2_STD_PAL_DK | V4L2_STD_NICAM)
++#define V4L2_STD_SECAM_L_NICAM (V4L2_STD_SECAM_L | V4L2_STD_NICAM)
++#define V4L2_STD_SECAM_L_AM (V4L2_STD_SECAM_L | V4L2_STD_AM)
+diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c
new file mode 100644
-index 0000000..86e0169
+index 0000000..9e9003c
--- /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:
++++ b/drivers/media/common/tuners/tuner-xc2028.c
+@@ -0,0 +1,1227 @@
++/* tuner-xc2028
+ *
-+ * - Redistributions of source code must retain the above
-+ * copyright notice, this list of conditions and the following
-+ * disclaimer.
++ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab at infradead.org)
+ *
-+ * - 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.
++ * Copyright (c) 2007 Michel Ludwig (michel.ludwig at gmail.com)
++ * - frontend interface
+ *
-+ * 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 code is placed under the terms of the GNU General Public License v2
+ */
-+#include <linux/mm.h>
-+#include <linux/types.h>
-+#include <linux/device.h>
-+#include <linux/dmapool.h>
-+#include <linux/slab.h>
-+#include <linux/list.h>
-+#include <linux/highmem.h>
-+#include <linux/io.h>
-+#include <linux/uio.h>
-+#include <linux/rbtree.h>
-+#include <linux/spinlock.h>
++
++#include <linux/i2c.h>
++#include <asm/div64.h>
++#include <linux/firmware.h>
++#include <linux/videodev2.h>
+#include <linux/delay.h>
++#include <media/tuner.h>
++#include <linux/mutex.h>
++#include "tuner-i2c.h"
++#include "tuner-xc2028.h"
++#include "tuner-xc2028-types.h"
+
-+#include "ipath_kernel.h"
-+#include "ipath_user_sdma.h"
++#include <linux/dvb/frontend.h>
++#include "dvb_frontend.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 */
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
-+ 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 */
-+};
++static char audio_std[8];
++module_param_string(audio_std, audio_std, sizeof(audio_std), 0);
++MODULE_PARM_DESC(audio_std,
++ "Audio standard. XC3028 audio decoder explicitly "
++ "needs to know what audio\n"
++ "standard is needed for some video standards with audio A2 or NICAM.\n"
++ "The valid values are:\n"
++ "A2\n"
++ "A2/A\n"
++ "A2/B\n"
++ "NICAM\n"
++ "NICAM/A\n"
++ "NICAM/B\n");
+
-+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;
++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");
+
-+ /* headers with expected length are allocated from here... */
-+ char header_cache_name[64];
-+ struct dma_pool *header_cache;
++static LIST_HEAD(xc2028_list);
++static DEFINE_MUTEX(xc2028_list_mutex);
+
-+ /* packets are allocated from the slab cache... */
-+ char pkt_slab_name[64];
-+ struct kmem_cache *pkt_slab;
++/* struct for storing firmware table */
++struct firmware_description {
++ unsigned int type;
++ v4l2_std_id id;
++ __u16 int_freq;
++ unsigned char *ptr;
++ unsigned int size;
++};
++
++struct firmware_properties {
++ unsigned int type;
++ v4l2_std_id id;
++ v4l2_std_id std_req;
++ __u16 int_freq;
++ unsigned int scode_table;
++ int scode_nr;
++};
++
++struct xc2028_data {
++ struct list_head xc2028_list;
++ struct tuner_i2c_props i2c_props;
++ int (*tuner_callback) (void *dev,
++ int command, int arg);
++ void *video_dev;
++ int count;
++ __u32 frequency;
++
++ struct firmware_description *firm;
++ int firm_size;
++ __u16 firm_version;
+
-+ /* as packets go on the queued queue, they are counted... */
-+ u32 counter;
-+ u32 sent_counter;
++ __u16 hwmodel;
++ __u16 hwvers;
+
-+ /* dma page table */
-+ struct rb_root dma_pages_root;
++ struct xc2028_ctrl ctrl;
++
++ struct firmware_properties cur_fw;
+
-+ /* 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);
++#define i2c_send(priv, buf, size) ({ \
++ int _rc; \
++ _rc = tuner_i2c_xfer_send(&priv->i2c_props, buf, size); \
++ if (size != _rc) \
++ tuner_info("i2c output error: rc = %d (should be %d)\n",\
++ _rc, (int)size); \
++ _rc; \
++})
+
-+ if (!pq)
-+ goto done;
++#define i2c_rcv(priv, buf, size) ({ \
++ int _rc; \
++ _rc = tuner_i2c_xfer_recv(&priv->i2c_props, buf, size); \
++ if (size != _rc) \
++ tuner_err("i2c input error: rc = %d (should be %d)\n", \
++ _rc, (int)size); \
++ _rc; \
++})
+
-+ pq->counter = 0;
-+ pq->sent_counter = 0;
-+ INIT_LIST_HEAD(&pq->sent);
++#define i2c_send_recv(priv, obuf, osize, ibuf, isize) ({ \
++ int _rc; \
++ _rc = tuner_i2c_xfer_send_recv(&priv->i2c_props, obuf, osize, \
++ ibuf, isize); \
++ if (isize != _rc) \
++ tuner_err("i2c input error: rc = %d (should be %d)\n", \
++ _rc, (int)isize); \
++ _rc; \
++})
+
-+ mutex_init(&pq->lock);
++#define send_seq(priv, data...) ({ \
++ static u8 _val[] = data; \
++ int _rc; \
++ if (sizeof(_val) != \
++ (_rc = tuner_i2c_xfer_send(&priv->i2c_props, \
++ _val, sizeof(_val)))) { \
++ tuner_err("Error on line %d: %d\n", __LINE__, _rc); \
++ } else \
++ msleep(10); \
++ _rc; \
++})
+
-+ 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);
++static int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
++{
++ unsigned char buf[2];
++ unsigned char ibuf[2];
+
-+ if (!pq->pkt_slab)
-+ goto err_kfree;
++ tuner_dbg("%s %04x called\n", __func__, reg);
+
-+ 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;
++ buf[0] = reg >> 8;
++ buf[1] = (unsigned char) reg;
+
-+ pq->dma_pages_root = RB_ROOT;
++ if (i2c_send_recv(priv, buf, 2, ibuf, 2) != 2)
++ return -EIO;
+
-+ goto done;
++ *val = (ibuf[1]) | (ibuf[0] << 8);
++ return 0;
++}
+
-+err_slab:
-+ kmem_cache_destroy(pq->pkt_slab);
-+err_kfree:
-+ kfree(pq);
-+ pq = NULL;
++#define dump_firm_type(t) dump_firm_type_and_int_freq(t, 0)
++static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
++{
++ if (type & BASE)
++ printk("BASE ");
++ if (type & INIT1)
++ printk("INIT1 ");
++ if (type & F8MHZ)
++ printk("F8MHZ ");
++ if (type & MTS)
++ printk("MTS ");
++ if (type & D2620)
++ printk("D2620 ");
++ if (type & D2633)
++ printk("D2633 ");
++ if (type & DTV6)
++ printk("DTV6 ");
++ if (type & QAM)
++ printk("QAM ");
++ if (type & DTV7)
++ printk("DTV7 ");
++ if (type & DTV78)
++ printk("DTV78 ");
++ if (type & DTV8)
++ printk("DTV8 ");
++ if (type & FM)
++ printk("FM ");
++ if (type & INPUT1)
++ printk("INPUT1 ");
++ if (type & LCD)
++ printk("LCD ");
++ if (type & NOGD)
++ printk("NOGD ");
++ if (type & MONO)
++ printk("MONO ");
++ if (type & ATSC)
++ printk("ATSC ");
++ if (type & IF)
++ printk("IF ");
++ if (type & LG60)
++ printk("LG60 ");
++ if (type & ATI638)
++ printk("ATI638 ");
++ if (type & OREN538)
++ printk("OREN538 ");
++ if (type & OREN36)
++ printk("OREN36 ");
++ if (type & TOYOTA388)
++ printk("TOYOTA388 ");
++ if (type & TOYOTA794)
++ printk("TOYOTA794 ");
++ if (type & DIBCOM52)
++ printk("DIBCOM52 ");
++ if (type & ZARLINK456)
++ printk("ZARLINK456 ");
++ if (type & CHINA)
++ printk("CHINA ");
++ if (type & F6MHZ)
++ printk("F6MHZ ");
++ if (type & INPUT2)
++ printk("INPUT2 ");
++ if (type & SCODE)
++ printk("SCODE ");
++ if (type & HAS_IF)
++ printk("HAS_IF_%d ", int_freq);
++}
++
++static v4l2_std_id parse_audio_std_option(void)
++{
++ if (strcasecmp(audio_std, "A2") == 0)
++ return V4L2_STD_A2;
++ if (strcasecmp(audio_std, "A2/A") == 0)
++ return V4L2_STD_A2_A;
++ if (strcasecmp(audio_std, "A2/B") == 0)
++ return V4L2_STD_A2_B;
++ if (strcasecmp(audio_std, "NICAM") == 0)
++ return V4L2_STD_NICAM;
++ if (strcasecmp(audio_std, "NICAM/A") == 0)
++ return V4L2_STD_NICAM_A;
++ if (strcasecmp(audio_std, "NICAM/B") == 0)
++ return V4L2_STD_NICAM_B;
+
-+done:
-+ return pq;
++ return 0;
+}
+
-+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)
++static void free_firmware(struct xc2028_data *priv)
+{
-+ 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;
++ int i;
++ tuner_dbg("%s called\n", __func__);
++
++ if (!priv->firm)
++ return;
++
++ for (i = 0; i < priv->firm_size; i++)
++ kfree(priv->firm[i].ptr);
++
++ kfree(priv->firm);
++
++ priv->firm = NULL;
++ priv->firm_size = 0;
++
++ memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
+}
+
-+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)
++static int load_all_firmwares(struct dvb_frontend *fe)
+{
-+ pkt->naddr = 1;
-+ pkt->counter = counter;
-+ ipath_user_sdma_init_frag(pkt, 0, offset, len, 0, dma_mapped, page,
-+ kvaddr, dma_addr);
-+}
++ struct xc2028_data *priv = fe->tuner_priv;
++ const struct firmware *fw = NULL;
++ unsigned char *p, *endp;
++ int rc = 0;
++ int n, n_array;
++ char name[33];
++ char *fname;
+
-+/* 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;
++ tuner_dbg("%s called\n", __func__);
+
-+ if (!page) {
-+ ret = -ENOMEM;
-+ goto done;
++ if (!firmware_name[0])
++ fname = priv->ctrl.fname;
++ else
++ fname = firmware_name;
++
++ 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",
++ fname);
++ else
++ tuner_err("Error %d while requesting firmware %s \n",
++ rc, fname);
++
++ return rc;
+ }
++ p = fw->data;
++ endp = p + fw->size;
+
-+ mpage = kmap(page);
-+ mpage_save = mpage;
-+ for (i = 0; i < niov; i++) {
-+ int cfur;
++ if (fw->size < sizeof(name) - 1 + 2 + 2) {
++ tuner_err("Error: firmware file %s has invalid size!\n",
++ fname);
++ goto corrupt;
++ }
+
-+ cfur = copy_from_user(mpage,
-+ iov[i].iov_base, iov[i].iov_len);
-+ if (cfur) {
-+ ret = -EFAULT;
-+ goto free_unmap;
-+ }
++ memcpy(name, p, sizeof(name) - 1);
++ name[sizeof(name) - 1] = 0;
++ p += sizeof(name) - 1;
+
-+ mpage += iov[i].iov_len;
-+ len += iov[i].iov_len;
++ priv->firm_version = le16_to_cpu(*(__u16 *) p);
++ p += 2;
++
++ n_array = le16_to_cpu(*(__u16 *) p);
++ p += 2;
++
++ tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
++ n_array, fname, name,
++ priv->firm_version >> 8, priv->firm_version & 0xff);
++
++ priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
++ if (priv->firm == NULL) {
++ tuner_err("Not enough memory to load firmware file.\n");
++ rc = -ENOMEM;
++ goto err;
+ }
++ priv->firm_size = n_array;
+
-+ 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;
++ n = -1;
++ while (p < endp) {
++ __u32 type, size;
++ v4l2_std_id id;
++ __u16 int_freq = 0;
++
++ n++;
++ if (n >= n_array) {
++ tuner_err("More firmware images in file than "
++ "were expected!\n");
++ goto corrupt;
++ }
++
++ /* Checks if there's enough bytes to read */
++ if (p + sizeof(type) + sizeof(id) + sizeof(size) > endp) {
++ tuner_err("Firmware header is incomplete!\n");
++ goto corrupt;
++ }
++
++ type = le32_to_cpu(*(__u32 *) p);
++ p += sizeof(type);
++
++ id = le64_to_cpu(*(v4l2_std_id *) p);
++ p += sizeof(id);
++
++ if (type & HAS_IF) {
++ int_freq = le16_to_cpu(*(__u16 *) p);
++ p += sizeof(int_freq);
++ }
++
++ size = le32_to_cpu(*(__u32 *) p);
++ p += sizeof(size);
++
++ if ((!size) || (size + p > endp)) {
++ tuner_err("Firmware type ");
++ dump_firm_type(type);
++ printk("(%x), id %llx is corrupted "
++ "(size=%d, expected %d)\n",
++ type, (unsigned long long)id,
++ (unsigned)(endp - p), size);
++ goto corrupt;
++ }
++
++ priv->firm[n].ptr = kzalloc(size, GFP_KERNEL);
++ if (priv->firm[n].ptr == NULL) {
++ tuner_err("Not enough memory to load firmware file.\n");
++ rc = -ENOMEM;
++ goto err;
++ }
++ tuner_dbg("Reading firmware type ");
++ if (debug) {
++ dump_firm_type_and_int_freq(type, int_freq);
++ printk("(%x), id %llx, size=%d.\n",
++ type, (unsigned long long)id, size);
++ }
++
++ memcpy(priv->firm[n].ptr, p, size);
++ priv->firm[n].type = type;
++ priv->firm[n].id = id;
++ priv->firm[n].size = size;
++ priv->firm[n].int_freq = int_freq;
++
++ p += size;
+ }
+
-+ ipath_user_sdma_init_frag(pkt, 1, 0, len, 0, 1, page, mpage_save,
-+ dma_addr);
-+ pkt->naddr = 2;
++ if (n + 1 != priv->firm_size) {
++ tuner_err("Firmware file is incomplete!\n");
++ goto corrupt;
++ }
+
+ goto done;
+
-+free_unmap:
-+ kunmap(page);
-+ __free_page(page);
++corrupt:
++ rc = -EINVAL;
++ tuner_err("Error: firmware file is corrupted!\n");
++
++err:
++ tuner_info("Releasing partially loaded firmware file.\n");
++ free_firmware(priv);
++
+done:
-+ return ret;
++ release_firmware(fw);
++ if (rc == 0)
++ tuner_dbg("Firmware files loaded.\n");
++
++ return rc;
+}
+
-+/* how many pages in this iovec element? */
-+static int ipath_user_sdma_num_pages(const struct iovec *iov)
++static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
++ v4l2_std_id *id)
+{
-+ 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;
++ struct xc2028_data *priv = fe->tuner_priv;
++ int i, best_i = -1, best_nr_matches = 0;
++ unsigned int type_mask = 0;
+
-+ return 1 + ((epage - spage) >> PAGE_SHIFT);
++ tuner_dbg("%s called, want type=", __func__);
++ if (debug) {
++ dump_firm_type(type);
++ printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
++ }
++
++ if (!priv->firm) {
++ tuner_err("Error! firmware not loaded\n");
++ return -EINVAL;
++ }
++
++ if (((type & ~SCODE) == 0) && (*id == 0))
++ *id = V4L2_STD_PAL;
++
++ if (type & BASE)
++ type_mask = BASE_TYPES;
++ else if (type & SCODE) {
++ type &= SCODE_TYPES;
++ type_mask = SCODE_TYPES & ~HAS_IF;
++ } else if (type & DTV_TYPES)
++ type_mask = DTV_TYPES;
++ else if (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 & type_mask)) &&
++ (*id == priv->firm[i].id))
++ goto found;
++ }
++
++ /* Seek for generic video standard match */
++ for (i = 0; i < priv->firm_size; i++) {
++ v4l2_std_id match_mask;
++ int nr_matches;
++
++ if (type != (priv->firm[i].type & type_mask))
++ continue;
++
++ match_mask = *id & priv->firm[i].id;
++ if (!match_mask)
++ continue;
++
++ if ((*id & match_mask) == *id)
++ goto found; /* Supports all the requested standards */
++
++ nr_matches = hweight64(match_mask);
++ if (nr_matches > best_nr_matches) {
++ best_nr_matches = nr_matches;
++ best_i = i;
++ }
++ }
++
++ if (best_nr_matches > 0) {
++ tuner_dbg("Selecting best matching firmware (%d bits) for "
++ "type=", best_nr_matches);
++ dump_firm_type(type);
++ printk("(%x), id %016llx:\n", type, (unsigned long long)*id);
++ i = best_i;
++ goto found;
++ }
++
++ /*FIXME: Would make sense to seek for type "hint" match ? */
++
++ i = -ENOENT;
++ goto ret;
++
++found:
++ *id = priv->firm[i].id;
++
++ret:
++ tuner_dbg("%s firmware for type=", (i < 0) ? "Can't find" : "Found");
++ if (debug) {
++ dump_firm_type(type);
++ printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
++ }
++ return i;
+}
+
-+/* truncate length to page boundry */
-+static int ipath_user_sdma_page_length(unsigned long addr, unsigned long len)
++static int load_firmware(struct dvb_frontend *fe, unsigned int type,
++ v4l2_std_id *id)
+{
-+ const unsigned long offset = addr & ~PAGE_MASK;
++ struct xc2028_data *priv = fe->tuner_priv;
++ int pos, rc;
++ unsigned char *p, *endp, buf[priv->ctrl.max_len];
+
-+ return ((offset + len) > PAGE_SIZE) ? (PAGE_SIZE - offset) : len;
++ tuner_dbg("%s called\n", __func__);
++
++ pos = seek_firmware(fe, type, id);
++ if (pos < 0)
++ return pos;
++
++ tuner_info("Loading firmware for type=");
++ dump_firm_type(priv->firm[pos].type);
++ printk("(%x), id %016llx.\n", priv->firm[pos].type,
++ (unsigned long long)*id);
++
++ p = priv->firm[pos].ptr;
++ endp = p + priv->firm[pos].size;
++
++ while (p < endp) {
++ __u16 size;
++
++ /* Checks if there's enough bytes to read */
++ if (p + sizeof(size) > endp) {
++ tuner_err("Firmware chunk size is wrong\n");
++ return -EINVAL;
++ }
++
++ size = le16_to_cpu(*(__u16 *) p);
++ p += sizeof(size);
++
++ if (size == 0xffff)
++ return 0;
++
++ if (!size) {
++ /* Special callback command received */
++ rc = priv->tuner_callback(priv->video_dev,
++ XC2028_TUNER_RESET, 0);
++ if (rc < 0) {
++ tuner_err("Error at RESET code %d\n",
++ (*p) & 0x7f);
++ return -EINVAL;
++ }
++ continue;
++ }
++ if (size >= 0xff00) {
++ switch (size) {
++ case 0xff00:
++ rc = priv->tuner_callback(priv->video_dev,
++ XC2028_RESET_CLK, 0);
++ if (rc < 0) {
++ tuner_err("Error at RESET code %d\n",
++ (*p) & 0x7f);
++ return -EINVAL;
++ }
++ break;
++ default:
++ tuner_info("Invalid RESET code %d\n",
++ size & 0x7f);
++ return -EINVAL;
++
++ }
++ continue;
++ }
++
++ /* Checks for a sleep command */
++ if (size & 0x8000) {
++ msleep(size & 0x7fff);
++ continue;
++ }
++
++ if ((size + p > endp)) {
++ tuner_err("missing bytes: need %d, have %d\n",
++ size, (int)(endp - p));
++ return -EINVAL;
++ }
++
++ buf[0] = *p;
++ p++;
++ size--;
++
++ /* Sends message chunks */
++ while (size > 0) {
++ int len = (size < priv->ctrl.max_len - 1) ?
++ size : priv->ctrl.max_len - 1;
++
++ memcpy(buf + 1, p, len);
++
++ rc = i2c_send(priv, buf, len + 1);
++ if (rc < 0) {
++ tuner_err("%d returned from send\n", rc);
++ return -EINVAL;
++ }
++
++ p += len;
++ size -= len;
++ }
++ }
++ return 0;
+}
+
-+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)
++static int load_scode(struct dvb_frontend *fe, unsigned int type,
++ v4l2_std_id *id, __u16 int_freq, int scode)
+{
-+ const int i = frag;
++ struct xc2028_data *priv = fe->tuner_priv;
++ int pos, rc;
++ unsigned char *p;
+
-+ 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);
++ tuner_dbg("%s called\n", __func__);
+
-+ if (pkt->addr[i].kvaddr)
-+ kunmap(pkt->addr[i].page);
++ if (!int_freq) {
++ pos = seek_firmware(fe, type, id);
++ if (pos < 0)
++ return pos;
++ } else {
++ for (pos = 0; pos < priv->firm_size; pos++) {
++ if ((priv->firm[pos].int_freq == int_freq) &&
++ (priv->firm[pos].type & HAS_IF))
++ break;
++ }
++ if (pos == priv->firm_size)
++ return -ENOENT;
++ }
+
-+ 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);
++ p = priv->firm[pos].ptr;
++
++ if (priv->firm[pos].type & HAS_IF) {
++ if (priv->firm[pos].size != 12 * 16 || scode >= 16)
++ return -EINVAL;
++ p += 12 * scode;
++ } else {
++ /* 16 SCODE entries per file; each SCODE entry is 12 bytes and
++ * has a 2-byte size header in the firmware format. */
++ if (priv->firm[pos].size != 14 * 16 || scode >= 16 ||
++ le16_to_cpu(*(__u16 *)(p + 14 * scode)) != 12)
++ return -EINVAL;
++ p += 14 * scode + 2;
++ }
++
++ tuner_info("Loading SCODE for type=");
++ dump_firm_type_and_int_freq(priv->firm[pos].type,
++ priv->firm[pos].int_freq);
++ printk("(%x), id %016llx.\n", priv->firm[pos].type,
++ (unsigned long long)*id);
++
++ if (priv->firm_version < 0x0202)
++ rc = send_seq(priv, {0x20, 0x00, 0x00, 0x00});
++ else
++ rc = send_seq(priv, {0xa0, 0x00, 0x00, 0x00});
++ if (rc < 0)
++ return -EIO;
++
++ rc = i2c_send(priv, p, 12);
++ if (rc < 0)
++ return -EIO;
++
++ rc = send_seq(priv, {0x00, 0x8c});
++ if (rc < 0)
++ return -EIO;
++
++ return 0;
+}
+
-+/* 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)
++static int check_firmware(struct dvb_frontend *fe, unsigned int type,
++ v4l2_std_id std, __u16 int_freq)
+{
-+ struct page *pages[2];
-+ int j;
-+ int ret;
++ struct xc2028_data *priv = fe->tuner_priv;
++ struct firmware_properties new_fw;
++ int rc = 0, is_retry = 0;
++ u16 version, hwmodel;
++ v4l2_std_id std0;
+
-+ ret = get_user_pages(current, current->mm, addr,
-+ npages, 0, 1, pages, NULL);
++ tuner_dbg("%s called\n", __func__);
+
-+ if (ret != npages) {
-+ int i;
++ if (!priv->firm) {
++ if (!priv->ctrl.fname) {
++ tuner_info("xc2028/3028 firmware name not set!\n");
++ return -EINVAL;
++ }
+
-+ for (i = 0; i < ret; i++)
-+ put_page(pages[i]);
++ rc = load_all_firmwares(fe);
++ if (rc < 0)
++ return rc;
++ }
+
-+ ret = -ENOMEM;
-+ goto done;
++ if (priv->ctrl.mts && !(type & FM))
++ type |= MTS;
++
++retry:
++ new_fw.type = type;
++ new_fw.id = std;
++ new_fw.std_req = std;
++ new_fw.scode_table = SCODE | priv->ctrl.scode_table;
++ new_fw.scode_nr = 0;
++ new_fw.int_freq = int_freq;
++
++ tuner_dbg("checking firmware, user requested type=");
++ if (debug) {
++ dump_firm_type(new_fw.type);
++ printk("(%x), id %016llx, ", new_fw.type,
++ (unsigned long long)new_fw.std_req);
++ if (!int_freq) {
++ printk("scode_tbl ");
++ dump_firm_type(priv->ctrl.scode_table);
++ printk("(%x), ", priv->ctrl.scode_table);
++ } else
++ printk("int_freq %d, ", new_fw.int_freq);
++ printk("scode_nr %d\n", new_fw.scode_nr);
+ }
+
-+ 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;
++ /* No need to reload base firmware if it matches */
++ if (((BASE | new_fw.type) & BASE_TYPES) ==
++ (priv->cur_fw.type & BASE_TYPES)) {
++ tuner_dbg("BASE firmware not changed.\n");
++ goto skip_base;
++ }
+
-+ if (dma_mapping_error(dma_addr)) {
-+ ret = -ENOMEM;
-+ goto done;
-+ }
++ /* Updating BASE - forget about all currently loaded firmware */
++ memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
+
-+ ipath_user_sdma_init_frag(pkt, pkt->naddr, fofs, flen, 1, 1,
-+ pages[j], kmap(pages[j]),
-+ dma_addr);
++ /* Reset is needed before loading firmware */
++ rc = priv->tuner_callback(priv->video_dev,
++ XC2028_TUNER_RESET, 0);
++ if (rc < 0)
++ goto fail;
+
-+ pkt->naddr++;
-+ addr += flen;
-+ tlen -= flen;
++ /* BASE firmwares are all std0 */
++ std0 = 0;
++ rc = load_firmware(fe, BASE | new_fw.type, &std0);
++ if (rc < 0) {
++ tuner_err("Error %d while loading base firmware\n",
++ rc);
++ goto fail;
+ }
+
-+done:
-+ return ret;
++ /* Load INIT1, if needed */
++ tuner_dbg("Load init1 firmware, if exists\n");
++
++ rc = load_firmware(fe, BASE | INIT1 | new_fw.type, &std0);
++ if (rc == -ENOENT)
++ rc = load_firmware(fe, (BASE | INIT1 | new_fw.type) & ~F8MHZ,
++ &std0);
++ if (rc < 0 && rc != -ENOENT) {
++ tuner_err("Error %d while loading init1 firmware\n",
++ rc);
++ goto fail;
++ }
++
++skip_base:
++ /*
++ * No need to reload standard specific firmware if base firmware
++ * was not reloaded and requested video standards have not changed.
++ */
++ if (priv->cur_fw.type == (BASE | new_fw.type) &&
++ priv->cur_fw.std_req == std) {
++ tuner_dbg("Std-specific firmware already loaded.\n");
++ goto skip_std_specific;
++ }
++
++ /* Reloading std-specific firmware forces a SCODE update */
++ priv->cur_fw.scode_table = 0;
++
++ rc = load_firmware(fe, new_fw.type, &new_fw.id);
++ if (rc == -ENOENT)
++ rc = load_firmware(fe, new_fw.type & ~F8MHZ, &new_fw.id);
++
++ if (rc < 0)
++ goto fail;
++
++skip_std_specific:
++ if (priv->cur_fw.scode_table == new_fw.scode_table &&
++ priv->cur_fw.scode_nr == new_fw.scode_nr) {
++ tuner_dbg("SCODE firmware already loaded.\n");
++ goto check_device;
++ }
++
++ if (new_fw.type & FM)
++ goto check_device;
++
++ /* Load SCODE firmware, if exists */
++ tuner_dbg("Trying to load scode %d\n", new_fw.scode_nr);
++
++ rc = load_scode(fe, new_fw.type | new_fw.scode_table, &new_fw.id,
++ new_fw.int_freq, new_fw.scode_nr);
++
++check_device:
++ if (xc2028_get_reg(priv, 0x0004, &version) < 0 ||
++ xc2028_get_reg(priv, 0x0008, &hwmodel) < 0) {
++ tuner_err("Unable to read tuner registers.\n");
++ goto fail;
++ }
++
++ 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))) {
++ tuner_err("Incorrect readback of firmware version.\n");
++ goto fail;
++ }
++
++ /* Check that the tuner hardware model remains consistent over time. */
++ if (priv->hwmodel == 0 && (hwmodel == 2028 || hwmodel == 3028)) {
++ priv->hwmodel = hwmodel;
++ priv->hwvers = version & 0xff00;
++ } else if (priv->hwmodel == 0 || priv->hwmodel != hwmodel ||
++ priv->hwvers != (version & 0xff00)) {
++ tuner_err("Read invalid device hardware information - tuner "
++ "hung?\n");
++ goto fail;
++ }
++
++ memcpy(&priv->cur_fw, &new_fw, sizeof(priv->cur_fw));
++
++ /*
++ * By setting BASE in cur_fw.type only after successfully loading all
++ * firmwares, we can:
++ * 1. Identify that BASE firmware with type=0 has been loaded;
++ * 2. Tell whether BASE firmware was just changed the next time through.
++ */
++ priv->cur_fw.type |= BASE;
++
++ return 0;
++
++fail:
++ memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
++ if (!is_retry) {
++ msleep(50);
++ is_retry = 1;
++ tuner_dbg("Retrying firmware load\n");
++ goto retry;
++ }
++
++ if (rc == -ENOENT)
++ rc = -EINVAL;
++ return rc;
+}
+
-+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)
++static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
+{
-+ int ret = 0;
-+ unsigned long idx;
++ struct xc2028_data *priv = fe->tuner_priv;
++ u16 frq_lock, signal = 0;
++ int rc;
+
-+ 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;
++ tuner_dbg("%s called\n", __func__);
+
-+ ret = ipath_user_sdma_pin_pages(dd, pkt,
-+ addr, iov[idx].iov_len,
-+ npages);
-+ if (ret < 0)
-+ goto free_pkt;
++ mutex_lock(&priv->lock);
++
++ /* Sync Lock Indicator */
++ rc = xc2028_get_reg(priv, 0x0002, &frq_lock);
++ if (rc < 0)
++ goto ret;
++
++ /* 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)
++ 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;
++}
++
++#define DIV 15625
++
++static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
++ enum tuner_mode new_mode,
++ unsigned int type,
++ v4l2_std_id std,
++ u16 int_freq)
++{
++ struct xc2028_data *priv = fe->tuner_priv;
++ int rc = -EINVAL;
++ unsigned char buf[4];
++ u32 div, offset = 0;
++
++ tuner_dbg("%s called\n", __func__);
++
++ mutex_lock(&priv->lock);
++
++ tuner_dbg("should set frequency %d kHz\n", freq / 1000);
++
++ if (check_firmware(fe, type, std, int_freq) < 0)
++ goto ret;
++
++ /* On some cases xc2028 can disable video output, if
++ * very weak signals are received. By sending a soft
++ * reset, this is re-enabled. So, it is better to always
++ * send a soft reset before changing channels, to be sure
++ * that xc2028 will be in a safe state.
++ * Maybe this might also be needed for DTV.
++ */
++ if (new_mode == T_ANALOG_TV) {
++ rc = send_seq(priv, {0x00, 0x00});
++ } else if (priv->cur_fw.type & ATSC) {
++ offset = 1750000;
++ } else {
++ offset = 2750000;
++ /*
++ * We must adjust the offset by 500kHz in two cases in order
++ * to correctly center the IF output:
++ * 1) When the ZARLINK456 or DIBCOM52 tables were explicitly
++ * selected and a 7MHz channel is tuned;
++ * 2) When tuning a VHF channel with DTV78 firmware.
++ */
++ if (((priv->cur_fw.type & DTV7) &&
++ (priv->cur_fw.scode_table & (ZARLINK456 | DIBCOM52))) ||
++ ((priv->cur_fw.type & DTV78) && freq < 470000000))
++ offset -= 500000;
+ }
+
-+ goto done;
++ div = (freq - offset + DIV / 2) / DIV;
+
-+free_pkt:
-+ for (idx = 0; idx < pkt->naddr; idx++)
-+ ipath_user_sdma_free_pkt_frag(&dd->pcidev->dev, pq, pkt, idx);
++ /* CMD= Set frequency */
++ if (priv->firm_version < 0x0202)
++ rc = send_seq(priv, {0x00, 0x02, 0x00, 0x00});
++ else
++ rc = send_seq(priv, {0x80, 0x02, 0x00, 0x00});
++ if (rc < 0)
++ goto ret;
+
-+done:
-+ return 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);
++
++ buf[0] = 0xff & (div >> 24);
++ buf[1] = 0xff & (div >> 16);
++ buf[2] = 0xff & (div >> 8);
++ buf[3] = 0xff & (div);
++
++ rc = i2c_send(priv, buf, sizeof(buf));
++ if (rc < 0)
++ goto ret;
++ msleep(100);
++
++ priv->frequency = freq;
++
++ tuner_dbg("divisor= %02x %02x %02x %02x (freq=%d.%03d)\n",
++ buf[0], buf[1], buf[2], buf[3],
++ freq / 1000000, (freq % 1000000) / 1000);
++
++ rc = 0;
++
++ret:
++ mutex_unlock(&priv->lock);
++
++ return rc;
+}
+
-+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)
++static int xc2028_set_analog_freq(struct dvb_frontend *fe,
++ struct analog_parameters *p)
+{
-+ int ret = 0;
++ struct xc2028_data *priv = fe->tuner_priv;
++ unsigned int type=0;
+
-+ if (npages >= ARRAY_SIZE(pkt->addr))
-+ ret = ipath_user_sdma_coalesce(dd, pkt, iov, niov);
++ tuner_dbg("%s called\n", __func__);
++
++ if (p->mode == V4L2_TUNER_RADIO) {
++ type |= FM;
++ if (priv->ctrl.input1)
++ type |= INPUT1;
++ return generic_set_freq(fe, (625l * p->frequency) / 10,
++ T_ANALOG_TV, type, 0, 0);
++ }
++
++ /* if std is not defined, choose one */
++ if (!p->std)
++ p->std = V4L2_STD_MN;
++
++ /* PAL/M, PAL/N, PAL/Nc and NTSC variants should use 6MHz firmware */
++ if (!(p->std & V4L2_STD_MN))
++ type |= F8MHZ;
++
++ /* Add audio hack to std mask */
++ p->std |= parse_audio_std_option();
++
++ return generic_set_freq(fe, 62500l * p->frequency,
++ T_ANALOG_TV, type, p->std, 0);
++}
++
++static int xc2028_set_params(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *p)
++{
++ struct xc2028_data *priv = fe->tuner_priv;
++ unsigned int type=0;
++ fe_bandwidth_t bw = BANDWIDTH_8_MHZ;
++ u16 demod = 0;
++
++ tuner_dbg("%s called\n", __func__);
++
++ if (priv->ctrl.d2633)
++ type |= D2633;
+ else
-+ ret = ipath_user_sdma_pin_pkt(dd, pq, pkt, iov, niov);
++ type |= D2620;
+
-+ return ret;
++ switch(fe->ops.info.type) {
++ case FE_OFDM:
++ bw = p->u.ofdm.bandwidth;
++ break;
++ case FE_QAM:
++ tuner_info("WARN: There are some reports that "
++ "QAM 6 MHz doesn't work.\n"
++ "If this works for you, please report by "
++ "e-mail to: v4l-dvb-maintainer at linuxtv.org\n");
++ bw = BANDWIDTH_6_MHZ;
++ type |= QAM;
++ break;
++ case FE_ATSC:
++ bw = BANDWIDTH_6_MHZ;
++ /* The only ATSC firmware (at least on v2.7) is D2633,
++ so overrides ctrl->d2633 */
++ type |= ATSC| D2633;
++ type &= ~D2620;
++ break;
++ /* DVB-S is not supported */
++ default:
++ return -EINVAL;
++ }
++
++ switch (bw) {
++ case BANDWIDTH_8_MHZ:
++ if (p->frequency < 470000000)
++ priv->ctrl.vhfbw7 = 0;
++ else
++ priv->ctrl.uhfbw8 = 1;
++ type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV8;
++ type |= F8MHZ;
++ break;
++ case BANDWIDTH_7_MHZ:
++ if (p->frequency < 470000000)
++ priv->ctrl.vhfbw7 = 1;
++ else
++ priv->ctrl.uhfbw8 = 0;
++ type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV7;
++ type |= F8MHZ;
++ break;
++ case BANDWIDTH_6_MHZ:
++ type |= DTV6;
++ priv->ctrl.vhfbw7 = 0;
++ priv->ctrl.uhfbw8 = 0;
++ break;
++ default:
++ tuner_err("error: bandwidth not supported.\n");
++ };
++
++ /* All S-code tables need a 200kHz shift */
++ if (priv->ctrl.demod)
++ demod = priv->ctrl.demod + 200;
++
++ return generic_set_freq(fe, p->frequency,
++ T_DIGITAL_TV, type, 0, demod);
+}
+
-+/* 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)
++
++static int xc2028_dvb_release(struct dvb_frontend *fe)
+{
-+ struct ipath_user_sdma_pkt *pkt, *pkt_next;
++ struct xc2028_data *priv = fe->tuner_priv;
+
-+ list_for_each_entry_safe(pkt, pkt_next, list, list) {
-+ int i;
++ tuner_dbg("%s called\n", __func__);
+
-+ for (i = 0; i < pkt->naddr; i++)
-+ ipath_user_sdma_free_pkt_frag(dev, pq, pkt, i);
++ mutex_lock(&xc2028_list_mutex);
+
-+ kmem_cache_free(pq->pkt_slab, pkt);
++ priv->count--;
++
++ if (!priv->count) {
++ list_del(&priv->xc2028_list);
++
++ kfree(priv->ctrl.fname);
++
++ free_firmware(priv);
++ kfree(priv);
++ fe->tuner_priv = NULL;
+ }
++
++ mutex_unlock(&xc2028_list_mutex);
++
++ return 0;
+}
+
-+/*
-+ * 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)
++static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
-+ 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;
++ struct xc2028_data *priv = fe->tuner_priv;
+
-+ 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;
++ tuner_dbg("%s called\n", __func__);
+
-+ dma_mapped = 0;
-+ len = iov[idx].iov_len;
-+ nw = len >> 2;
-+ page = NULL;
++ *frequency = priv->frequency;
+
-+ pkt = kmem_cache_alloc(pq->pkt_slab, GFP_KERNEL);
-+ if (!pkt) {
-+ ret = -ENOMEM;
-+ goto free_list;
-+ }
++ return 0;
++}
+
-+ if (len < IPATH_USER_SDMA_MIN_HEADER_LENGTH ||
-+ len > PAGE_SIZE || len & 3 || addr & 3) {
-+ ret = -EINVAL;
-+ goto free_pkt;
-+ }
++static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
++{
++ struct xc2028_data *priv = fe->tuner_priv;
++ struct xc2028_ctrl *p = priv_cfg;
++ int rc = 0;
+
-+ if (len == IPATH_USER_SDMA_EXP_HEADER_LENGTH)
-+ pbc = dma_pool_alloc(pq->header_cache, GFP_KERNEL,
-+ &dma_addr);
-+ else
-+ pbc = NULL;
++ tuner_dbg("%s called\n", __func__);
+
-+ if (!pbc) {
-+ page = alloc_page(GFP_KERNEL);
-+ if (!page) {
-+ ret = -ENOMEM;
-+ goto free_pkt;
-+ }
-+ pbc = kmap(page);
-+ }
++ mutex_lock(&priv->lock);
+
-+ cfur = copy_from_user(pbc, iov[idx].iov_base, len);
-+ if (cfur) {
-+ ret = -EFAULT;
-+ goto free_pbc;
++ memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
++ 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);
+ }
+
-+ /*
-+ * 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;
++ priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL);
++ if (priv->ctrl.fname == NULL)
++ rc = -ENOMEM;
++ }
+
-+ /*
-+ * 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;
-+ }
++ mutex_unlock(&priv->lock);
+
++ return rc;
++}
+
-+ idx++;
-+ while (pktnwc < pktnw && idx < niov) {
-+ const size_t slen = iov[idx].iov_len;
-+ const unsigned long faddr =
-+ (unsigned long) iov[idx].iov_base;
++static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
++ .info = {
++ .name = "Xceive XC3028",
++ .frequency_min = 42000000,
++ .frequency_max = 864000000,
++ .frequency_step = 50000,
++ },
+
-+ if (slen & 3 || faddr & 3 || !slen ||
-+ slen > PAGE_SIZE) {
-+ ret = -EINVAL;
-+ goto free_pbc;
-+ }
++ .set_config = xc2028_set_config,
++ .set_analog_params = xc2028_set_analog_freq,
++ .release = xc2028_dvb_release,
++ .get_frequency = xc2028_get_frequency,
++ .get_rf_strength = xc2028_signal,
++ .set_params = xc2028_set_params,
++};
+
-+ npages++;
-+ if ((faddr & PAGE_MASK) !=
-+ ((faddr + slen - 1) & PAGE_MASK))
-+ npages++;
++struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
++ struct xc2028_config *cfg)
++{
++ struct xc2028_data *priv;
++ void *video_dev;
+
-+ pktnwc += slen >> 2;
-+ idx++;
-+ nfrags++;
-+ }
++ if (debug)
++ printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n");
+
-+ if (pktnwc != pktnw) {
-+ ret = -EINVAL;
-+ goto free_pbc;
-+ }
++ if (NULL == cfg)
++ return NULL;
+
-+ 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;
-+ }
++ if (!fe) {
++ printk(KERN_ERR "xc2028: No frontend!\n");
++ return NULL;
++ }
+
-+ dma_mapped = 1;
-+ }
++ video_dev = cfg->i2c_adap->algo_data;
+
-+ ipath_user_sdma_init_header(pkt, counter, 0, len, dma_mapped,
-+ page, pbc, dma_addr);
++ if (debug)
++ printk(KERN_DEBUG "xc2028: video_dev =%p\n", video_dev);
+
-+ if (nfrags) {
-+ ret = ipath_user_sdma_init_payload(dd, pq, pkt,
-+ iov + idx_save + 1,
-+ nfrags, npages);
-+ if (ret < 0)
-+ goto free_pbc_dma;
++ mutex_lock(&xc2028_list_mutex);
++
++ list_for_each_entry(priv, &xc2028_list, xc2028_list) {
++ if (&priv->i2c_props.adap->dev == &cfg->i2c_adap->dev) {
++ video_dev = NULL;
++ if (debug)
++ printk(KERN_DEBUG "xc2028: reusing device\n");
++
++ break;
+ }
++ }
+
-+ counter++;
-+ npkts++;
++ if (video_dev) {
++ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++ if (priv == NULL) {
++ mutex_unlock(&xc2028_list_mutex);
++ return NULL;
++ }
+
-+ list_add_tail(&pkt->list, list);
++ 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;
++
++ mutex_init(&priv->lock);
++
++ list_add_tail(&priv->xc2028_list, &xc2028_list);
+ }
+
-+ ret = idx;
-+ goto done;
++ fe->tuner_priv = priv;
++ priv->count++;
+
-+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;
++ 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));
++
++ tuner_info("type set to %s\n", "XCeive xc2028/xc3028 tuner");
++
++ if (cfg->ctrl)
++ xc2028_set_config(fe, cfg->ctrl);
++
++ mutex_unlock(&xc2028_list_mutex);
++
++ return fe;
+}
+
-+static void ipath_user_sdma_set_complete_counter(struct ipath_user_sdma_queue *pq,
-+ u32 c)
++EXPORT_SYMBOL(xc2028_attach);
++
++MODULE_DESCRIPTION("Xceive xc2028/xc3028 tuner driver");
++MODULE_AUTHOR("Michel Ludwig <michel.ludwig at gmail.com>");
++MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab at infradead.org>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/common/tuners/tuner-xc2028.h b/drivers/media/common/tuners/tuner-xc2028.h
+new file mode 100644
+index 0000000..216025c
+--- /dev/null
++++ b/drivers/media/common/tuners/tuner-xc2028.h
+@@ -0,0 +1,63 @@
++/* tuner-xc2028
++ *
++ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab at infradead.org)
++ * This code is placed under the terms of the GNU General Public License v2
++ */
++
++#ifndef __TUNER_XC2028_H__
++#define __TUNER_XC2028_H__
++
++#include "dvb_frontend.h"
++
++#define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw"
++
++/* Dmoduler IF (kHz) */
++#define XC3028_FE_DEFAULT 0 /* Don't load SCODE */
++#define XC3028_FE_LG60 6000
++#define XC3028_FE_ATI638 6380
++#define XC3028_FE_OREN538 5380
++#define XC3028_FE_OREN36 3600
++#define XC3028_FE_TOYOTA388 3880
++#define XC3028_FE_TOYOTA794 7940
++#define XC3028_FE_DIBCOM52 5200
++#define XC3028_FE_ZARLINK456 4560
++#define XC3028_FE_CHINA 5200
++
++struct xc2028_ctrl {
++ char *fname;
++ int max_len;
++ unsigned int scode_table;
++ unsigned int mts :1;
++ unsigned int d2633 :1;
++ unsigned int input1:1;
++ unsigned int vhfbw7:1;
++ unsigned int uhfbw8:1;
++ unsigned int demod;
++};
++
++struct xc2028_config {
++ struct i2c_adapter *i2c_adap;
++ u8 i2c_addr;
++ void *video_dev;
++ struct xc2028_ctrl *ctrl;
++ int (*callback) (void *dev, int command, int arg);
++};
++
++/* xc2028 commands for callback */
++#define XC2028_TUNER_RESET 0
++#define XC2028_RESET_CLK 1
++
++#if defined(CONFIG_MEDIA_TUNER_XC2028) || (defined(CONFIG_MEDIA_TUNER_XC2028_MODULE) && defined(MODULE))
++extern struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
++ struct xc2028_config *cfg);
++#else
++static inline struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
++ struct xc2028_config *cfg)
+{
-+ pq->sent_counter = c;
++ printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
++ __func__);
++ return NULL;
+}
++#endif
+
-+/* 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)
++#endif /* __TUNER_XC2028_H__ */
+diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c
+new file mode 100644
+index 0000000..43d35bd
+--- /dev/null
++++ b/drivers/media/common/tuners/xc5000.c
+@@ -0,0 +1,964 @@
++/*
++ * Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
++ *
++ * Copyright (c) 2007 Xceive Corporation
++ * Copyright (c) 2007 Steven Toth <stoth at hauppauge.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/videodev2.h>
++#include <linux/delay.h>
++#include <linux/dvb/frontend.h>
++#include <linux/i2c.h>
++
++#include "dvb_frontend.h"
++
++#include "xc5000.h"
++#include "xc5000_priv.h"
++
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
++
++#define dprintk(level,fmt, arg...) if (debug >= level) \
++ printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
++
++#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw"
++#define XC5000_DEFAULT_FIRMWARE_SIZE 12332
++
++/* Misc Defines */
++#define MAX_TV_STANDARD 23
++#define XC_MAX_I2C_WRITE_LENGTH 64
++
++/* Signal Types */
++#define XC_RF_MODE_AIR 0
++#define XC_RF_MODE_CABLE 1
++
++/* Result codes */
++#define XC_RESULT_SUCCESS 0
++#define XC_RESULT_RESET_FAILURE 1
++#define XC_RESULT_I2C_WRITE_FAILURE 2
++#define XC_RESULT_I2C_READ_FAILURE 3
++#define XC_RESULT_OUT_OF_RANGE 5
++
++/* Product id */
++#define XC_PRODUCT_ID_FW_NOT_LOADED 0x2000
++#define XC_PRODUCT_ID_FW_LOADED 0x1388
++
++/* Registers */
++#define XREG_INIT 0x00
++#define XREG_VIDEO_MODE 0x01
++#define XREG_AUDIO_MODE 0x02
++#define XREG_RF_FREQ 0x03
++#define XREG_D_CODE 0x04
++#define XREG_IF_OUT 0x05
++#define XREG_SEEK_MODE 0x07
++#define XREG_POWER_DOWN 0x0A
++#define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */
++#define XREG_SMOOTHEDCVBS 0x0E
++#define XREG_XTALFREQ 0x0F
++#define XREG_FINERFFREQ 0x10
++#define XREG_DDIMODE 0x11
++
++#define XREG_ADC_ENV 0x00
++#define XREG_QUALITY 0x01
++#define XREG_FRAME_LINES 0x02
++#define XREG_HSYNC_FREQ 0x03
++#define XREG_LOCK 0x04
++#define XREG_FREQ_ERROR 0x05
++#define XREG_SNR 0x06
++#define XREG_VERSION 0x07
++#define XREG_PRODUCT_ID 0x08
++#define XREG_BUSY 0x09
++
++/*
++ Basic firmware description. This will remain with
++ the driver for documentation purposes.
++
++ This represents an I2C firmware file encoded as a
++ string of unsigned char. Format is as follows:
++
++ char[0 ]=len0_MSB -> len = len_MSB * 256 + len_LSB
++ char[1 ]=len0_LSB -> length of first write transaction
++ char[2 ]=data0 -> first byte to be sent
++ char[3 ]=data1
++ char[4 ]=data2
++ char[ ]=...
++ char[M ]=dataN -> last byte to be sent
++ char[M+1]=len1_MSB -> len = len_MSB * 256 + len_LSB
++ char[M+2]=len1_LSB -> length of second write transaction
++ char[M+3]=data0
++ char[M+4]=data1
++ ...
++ etc.
++
++ The [len] value should be interpreted as follows:
++
++ len= len_MSB _ len_LSB
++ len=1111_1111_1111_1111 : End of I2C_SEQUENCE
++ len=0000_0000_0000_0000 : Reset command: Do hardware reset
++ len=0NNN_NNNN_NNNN_NNNN : Normal transaction: number of bytes = {1:32767)
++ len=1WWW_WWWW_WWWW_WWWW : Wait command: wait for {1:32767} ms
++
++ For the RESET and WAIT commands, the two following bytes will contain
++ immediately the length of the following transaction.
++
++*/
++typedef struct {
++ char *Name;
++ u16 AudioMode;
++ u16 VideoMode;
++} XC_TV_STANDARD;
++
++/* Tuner standards */
++#define MN_NTSC_PAL_BTSC 0
++#define MN_NTSC_PAL_A2 1
++#define MN_NTSC_PAL_EIAJ 2
++#define MN_NTSC_PAL_Mono 3
++#define BG_PAL_A2 4
++#define BG_PAL_NICAM 5
++#define BG_PAL_MONO 6
++#define I_PAL_NICAM 7
++#define I_PAL_NICAM_MONO 8
++#define DK_PAL_A2 9
++#define DK_PAL_NICAM 10
++#define DK_PAL_MONO 11
++#define DK_SECAM_A2DK1 12
++#define DK_SECAM_A2LDK3 13
++#define DK_SECAM_A2MONO 14
++#define L_SECAM_NICAM 15
++#define LC_SECAM_NICAM 16
++#define DTV6 17
++#define DTV8 18
++#define DTV7_8 19
++#define DTV7 20
++#define FM_Radio_INPUT2 21
++#define FM_Radio_INPUT1 22
++
++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},
++ {"M/N-NTSC/PAL-Mono", 0x0478, 0x8020},
++ {"B/G-PAL-A2", 0x0A00, 0x8049},
++ {"B/G-PAL-NICAM", 0x0C04, 0x8049},
++ {"B/G-PAL-MONO", 0x0878, 0x8059},
++ {"I-PAL-NICAM", 0x1080, 0x8009},
++ {"I-PAL-NICAM-MONO", 0x0E78, 0x8009},
++ {"D/K-PAL-A2", 0x1600, 0x8009},
++ {"D/K-PAL-NICAM", 0x0E80, 0x8009},
++ {"D/K-PAL-MONO", 0x1478, 0x8009},
++ {"D/K-SECAM-A2 DK1", 0x1200, 0x8009},
++ {"D/K-SECAM-A2 L/DK3",0x0E00, 0x8009},
++ {"D/K-SECAM-A2 MONO", 0x1478, 0x8009},
++ {"L-SECAM-NICAM", 0x8E82, 0x0009},
++ {"L'-SECAM-NICAM", 0x8E82, 0x4009},
++ {"DTV6", 0x00C0, 0x8002},
++ {"DTV8", 0x00C0, 0x800B},
++ {"DTV7/8", 0x00C0, 0x801B},
++ {"DTV7", 0x00C0, 0x8007},
++ {"FM Radio-INPUT2", 0x9802, 0x9002},
++ {"FM Radio-INPUT1", 0x0208, 0x9002}
++};
++
++static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len);
++static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len);
++static void xc5000_TunerReset(struct dvb_frontend *fe);
++
++static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
+{
-+ struct list_head free_list;
-+ struct ipath_user_sdma_pkt *pkt;
-+ struct ipath_user_sdma_pkt *pkt_prev;
-+ int ret = 0;
++ return xc5000_writeregs(priv, buf, len)
++ ? XC_RESULT_I2C_WRITE_FAILURE : XC_RESULT_SUCCESS;
++}
+
-+ INIT_LIST_HEAD(&free_list);
++static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
++{
++ return xc5000_readregs(priv, buf, len)
++ ? XC_RESULT_I2C_READ_FAILURE : XC_RESULT_SUCCESS;
++}
+
-+ list_for_each_entry_safe(pkt, pkt_prev, &pq->sent, list) {
-+ s64 descd = dd->ipath_sdma_descq_removed - pkt->added;
++static int xc_reset(struct dvb_frontend *fe)
++{
++ xc5000_TunerReset(fe);
++ return XC_RESULT_SUCCESS;
++}
+
-+ if (descd < 0)
-+ break;
++static void xc_wait(int wait_ms)
++{
++ msleep(wait_ms);
++}
+
-+ list_move_tail(&pkt->list, &free_list);
++static void xc5000_TunerReset(struct dvb_frontend *fe)
++{
++ struct xc5000_priv *priv = fe->tuner_priv;
++ int ret;
+
-+ /* one more packet cleaned */
-+ ret++;
-+ }
++ dprintk(1, "%s()\n", __func__);
+
-+ if (!list_empty(&free_list)) {
-+ u32 counter;
++ if (priv->cfg->tuner_callback) {
++ ret = priv->cfg->tuner_callback(priv->cfg->priv,
++ XC5000_TUNER_RESET, 0);
++ if (ret)
++ printk(KERN_ERR "xc5000: reset failed\n");
++ } else
++ printk(KERN_ERR "xc5000: no tuner reset callback function, fatal\n");
++}
+
-+ pkt = list_entry(free_list.prev,
-+ struct ipath_user_sdma_pkt, list);
-+ counter = pkt->counter;
++static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData)
++{
++ u8 buf[4];
++ int WatchDogTimer = 5;
++ int result;
+
-+ ipath_user_sdma_free_pkt_list(&dd->pcidev->dev, pq, &free_list);
-+ ipath_user_sdma_set_complete_counter(pq, counter);
++ buf[0] = (regAddr >> 8) & 0xFF;
++ buf[1] = regAddr & 0xFF;
++ buf[2] = (i2cData >> 8) & 0xFF;
++ buf[3] = i2cData & 0xFF;
++ result = xc_send_i2c_data(priv, buf, 4);
++ if (result == XC_RESULT_SUCCESS) {
++ /* wait for busy flag to clear */
++ while ((WatchDogTimer > 0) && (result == XC_RESULT_SUCCESS)) {
++ buf[0] = 0;
++ buf[1] = XREG_BUSY;
++
++ result = xc_send_i2c_data(priv, buf, 2);
++ if (result == XC_RESULT_SUCCESS) {
++ result = xc_read_i2c_data(priv, buf, 2);
++ if (result == XC_RESULT_SUCCESS) {
++ if ((buf[0] == 0) && (buf[1] == 0)) {
++ /* busy flag cleared */
++ break;
++ } else {
++ xc_wait(100); /* wait 5 ms */
++ WatchDogTimer--;
++ }
++ }
++ }
++ }
+ }
++ if (WatchDogTimer < 0)
++ result = XC_RESULT_I2C_WRITE_FAILURE;
+
-+ return ret;
++ return result;
+}
+
-+void ipath_user_sdma_queue_destroy(struct ipath_user_sdma_queue *pq)
++static int xc_read_reg(struct xc5000_priv *priv, u16 regAddr, u16 *i2cData)
+{
-+ if (!pq)
-+ return;
++ u8 buf[2];
++ int result;
+
-+ kmem_cache_destroy(pq->pkt_slab);
-+ dma_pool_destroy(pq->header_cache);
-+ kfree(pq);
++ buf[0] = (regAddr >> 8) & 0xFF;
++ buf[1] = regAddr & 0xFF;
++ result = xc_send_i2c_data(priv, buf, 2);
++ if (result != XC_RESULT_SUCCESS)
++ return result;
++
++ result = xc_read_i2c_data(priv, buf, 2);
++ if (result != XC_RESULT_SUCCESS)
++ return result;
++
++ *i2cData = buf[0] * 256 + buf[1];
++ return result;
+}
+
-+/* clean descriptor queue, returns > 0 if some elements cleaned */
-+static int ipath_user_sdma_hwqueue_clean(struct ipath_devdata *dd)
++static int xc_load_i2c_sequence(struct dvb_frontend *fe, u8 i2c_sequence[])
++{
++ struct xc5000_priv *priv = fe->tuner_priv;
++
++ int i, nbytes_to_send, result;
++ unsigned int len, pos, index;
++ u8 buf[XC_MAX_I2C_WRITE_LENGTH];
++
++ index=0;
++ while ((i2c_sequence[index]!=0xFF) || (i2c_sequence[index+1]!=0xFF)) {
++ len = i2c_sequence[index]* 256 + i2c_sequence[index+1];
++ if (len == 0x0000) {
++ /* RESET command */
++ result = xc_reset(fe);
++ index += 2;
++ if (result != XC_RESULT_SUCCESS)
++ return result;
++ } else if (len & 0x8000) {
++ /* WAIT command */
++ xc_wait(len & 0x7FFF);
++ index += 2;
++ } else {
++ /* Send i2c data whilst ensuring individual transactions
++ * do not exceed XC_MAX_I2C_WRITE_LENGTH bytes.
++ */
++ index += 2;
++ buf[0] = i2c_sequence[index];
++ buf[1] = i2c_sequence[index + 1];
++ pos = 2;
++ while (pos < len) {
++ if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2) {
++ nbytes_to_send = XC_MAX_I2C_WRITE_LENGTH;
++ } else {
++ nbytes_to_send = (len - pos + 2);
++ }
++ for (i=2; i<nbytes_to_send; i++) {
++ buf[i] = i2c_sequence[index + pos + i - 2];
++ }
++ result = xc_send_i2c_data(priv, buf, nbytes_to_send);
++
++ if (result != XC_RESULT_SUCCESS)
++ return result;
++
++ pos += nbytes_to_send - 2;
++ }
++ index += len;
++ }
++ }
++ return XC_RESULT_SUCCESS;
++}
++
++static int xc_initialize(struct xc5000_priv *priv)
++{
++ dprintk(1, "%s()\n", __func__);
++ return xc_write_reg(priv, XREG_INIT, 0);
++}
++
++static int xc_SetTVStandard(struct xc5000_priv *priv,
++ u16 VideoMode, u16 AudioMode)
+{
+ int ret;
-+ unsigned long flags;
++ dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode);
++ dprintk(1, "%s() Standard = %s\n",
++ __func__,
++ XC5000_Standard[priv->video_standard].Name);
+
-+ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
-+ ret = ipath_sdma_make_progress(dd);
-+ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++ ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode);
++ if (ret == XC_RESULT_SUCCESS)
++ ret = xc_write_reg(priv, XREG_AUDIO_MODE, AudioMode);
+
+ 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)
++static int xc_shutdown(struct xc5000_priv *priv)
+{
-+ int i;
++ return 0;
++ /* Fixme: cannot bring tuner back alive once shutdown
++ * without reloading the driver modules.
++ * return xc_write_reg(priv, XREG_POWER_DOWN, 0);
++ */
++}
+
-+ if (!pq)
-+ return;
++static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
++{
++ dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
++ rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
+
-+ 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 ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE))
++ {
++ rf_mode = XC_RF_MODE_CABLE;
++ printk(KERN_ERR
++ "%s(), Invalid mode, defaulting to CABLE",
++ __func__);
+ }
++ return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
++}
+
-+ if (!list_empty(&pq->sent)) {
-+ struct list_head free_list;
++static const struct dvb_tuner_ops xc5000_tuner_ops;
+
-+ 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 int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz)
++{
++ u16 freq_code;
++
++ 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))
++ return XC_RESULT_OUT_OF_RANGE;
++
++ freq_code = (u16)(freq_hz / 15625);
++
++ return xc_write_reg(priv, XREG_RF_FREQ, freq_code);
+}
+
-+static inline __le64 ipath_sdma_make_desc0(struct ipath_devdata *dd,
-+ u64 addr, u64 dwlen, u64 dwoffset)
++
++static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz)
+{
-+ 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));
++ u32 freq_code = (freq_khz * 1024)/1000;
++ dprintk(1, "%s(freq_khz = %d) freq_code = 0x%x\n",
++ __func__, freq_khz, freq_code);
++
++ return xc_write_reg(priv, XREG_IF_OUT, freq_code);
+}
+
-+static inline __le64 ipath_sdma_make_first_desc0(__le64 descq)
++
++static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope)
+{
-+ return descq | __constant_cpu_to_le64(1ULL << 12);
++ return xc_read_reg(priv, XREG_ADC_ENV, adc_envelope);
+}
+
-+static inline __le64 ipath_sdma_make_last_desc0(__le64 descq)
++static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz)
+{
-+ /* last */ /* dma head */
-+ return descq | __constant_cpu_to_le64(1ULL << 11 | 1ULL << 13);
++ int result;
++ u16 regData;
++ u32 tmp;
++
++ result = xc_read_reg(priv, XREG_FREQ_ERROR, ®Data);
++ if (result)
++ return result;
++
++ tmp = (u32)regData;
++ (*freq_error_hz) = (tmp * 15625) / 1000;
++ return result;
+}
+
-+static inline __le64 ipath_sdma_make_desc1(u64 addr)
++static int xc_get_lock_status(struct xc5000_priv *priv, u16 *lock_status)
+{
-+ /* SDmaPhyAddr[47:32] */
-+ return cpu_to_le64(addr >> 32);
++ return xc_read_reg(priv, XREG_LOCK, lock_status);
+}
+
-+static void ipath_user_sdma_send_frag(struct ipath_devdata *dd,
-+ struct ipath_user_sdma_pkt *pkt, int idx,
-+ unsigned ofs, u16 tail)
++static int xc_get_version(struct xc5000_priv *priv,
++ u8 *hw_majorversion, u8 *hw_minorversion,
++ u8 *fw_majorversion, u8 *fw_minorversion)
+{
-+ 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;
++ u16 data;
++ int result;
+
-+ descqp = &dd->ipath_sdma_descq[tail].qw[0];
++ result = xc_read_reg(priv, XREG_VERSION, &data);
++ if (result)
++ return result;
+
-+ 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);
++ (*hw_majorversion) = (data >> 12) & 0x0F;
++ (*hw_minorversion) = (data >> 8) & 0x0F;
++ (*fw_majorversion) = (data >> 4) & 0x0F;
++ (*fw_minorversion) = data & 0x0F;
+
-+ descqp[0] = descq0;
-+ descqp[1] = ipath_sdma_make_desc1(addr);
++ return 0;
+}
+
-+/* 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)
++static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz)
+{
-+ int ret = 0;
-+ unsigned long flags;
-+ u16 tail;
++ u16 regData;
++ int result;
+
-+ if (list_empty(pktlist))
-+ return 0;
++ result = xc_read_reg(priv, XREG_HSYNC_FREQ, ®Data);
++ if (result)
++ return result;
+
-+ if (unlikely(!(dd->ipath_flags & IPATH_LINKACTIVE)))
-+ return -ECOMM;
++ (*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100;
++ return result;
++}
+
-+ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++static int xc_get_frame_lines(struct xc5000_priv *priv, u16 *frame_lines)
++{
++ return xc_read_reg(priv, XREG_FRAME_LINES, frame_lines);
++}
+
-+ if (unlikely(dd->ipath_sdma_status & IPATH_SDMA_ABORT_MASK)) {
-+ ret = -ECOMM;
-+ goto unlock;
++static int xc_get_quality(struct xc5000_priv *priv, u16 *quality)
++{
++ return xc_read_reg(priv, XREG_QUALITY, quality);
++}
++
++static u16 WaitForLock(struct xc5000_priv *priv)
++{
++ u16 lockState = 0;
++ int watchDogCount = 40;
++
++ while ((lockState == 0) && (watchDogCount > 0)) {
++ xc_get_lock_status(priv, &lockState);
++ if (lockState != 1) {
++ xc_wait(5);
++ watchDogCount--;
++ }
+ }
++ return lockState;
++}
+
-+ 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;
++static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz)
++{
++ int found = 0;
+
-+ if (pkt->naddr > ipath_sdma_descq_freecnt(dd))
-+ goto unlock_check_tail;
++ dprintk(1, "%s(%u)\n", __func__, freq_hz);
+
-+ for (i = 0; i < pkt->naddr; i++) {
-+ ipath_user_sdma_send_frag(dd, pkt, i, ofs, tail);
-+ ofs += pkt->addr[i].length >> 2;
++ if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS)
++ return 0;
+
-+ if (++tail == dd->ipath_sdma_descq_cnt) {
-+ tail = 0;
-+ ++dd->ipath_sdma_generation;
-+ }
-+ }
++ if (WaitForLock(priv) == 1)
++ found = 1;
+
-+ if ((ofs<<2) > dd->ipath_ibmaxlen) {
-+ ipath_dbg("packet size %X > ibmax %X, fail\n",
-+ ofs<<2, dd->ipath_ibmaxlen);
-+ ret = -EMSGSIZE;
-+ goto unlock;
-+ }
++ return found;
++}
+
-+ /*
-+ * 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;
-+ }
-+ }
++static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
++{
++ u8 buf[2] = { reg >> 8, reg & 0xff };
++ u8 bval[2] = { 0, 0 };
++ struct i2c_msg msg[2] = {
++ { .addr = priv->cfg->i2c_address,
++ .flags = 0, .buf = &buf[0], .len = 2 },
++ { .addr = priv->cfg->i2c_address,
++ .flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
++ };
+
-+ dd->ipath_sdma_descq_added += pkt->naddr;
-+ pkt->added = dd->ipath_sdma_descq_added;
-+ list_move_tail(&pkt->list, &pq->sent);
-+ ret++;
++ if (i2c_transfer(priv->i2c, msg, 2) != 2) {
++ printk(KERN_WARNING "xc5000: I2C read failed\n");
++ return -EREMOTEIO;
+ }
+
-+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;
++ *val = (bval[0] << 8) | bval[1];
++ return 0;
++}
++
++static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len)
++{
++ struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
++ .flags = 0, .buf = buf, .len = len };
++
++ if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
++ printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n",
++ (int)len);
++ return -EREMOTEIO;
+ }
++ return 0;
++}
+
-+unlock:
-+ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len)
++{
++ struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
++ .flags = I2C_M_RD, .buf = buf, .len = len };
++
++ if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
++ printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n",(int)len);
++ return -EREMOTEIO;
++ }
++ return 0;
++}
++
++static int xc5000_fwupload(struct dvb_frontend* fe)
++{
++ struct xc5000_priv *priv = fe->tuner_priv;
++ const struct firmware *fw;
++ int ret;
++
++ /* request the firmware, this will block and timeout */
++ printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
++ XC5000_DEFAULT_FIRMWARE);
++
++ ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c->dev);
++ if (ret) {
++ printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
++ ret = XC_RESULT_RESET_FAILURE;
++ goto out;
++ } else {
++ printk(KERN_INFO "xc5000: firmware read %Zu bytes.\n",
++ fw->size);
++ ret = XC_RESULT_SUCCESS;
++ }
++
++ if (fw->size != XC5000_DEFAULT_FIRMWARE_SIZE) {
++ printk(KERN_ERR "xc5000: firmware incorrect size\n");
++ ret = XC_RESULT_RESET_FAILURE;
++ } else {
++ printk(KERN_INFO "xc5000: firmware upload\n");
++ ret = xc_load_i2c_sequence(fe, fw->data );
++ }
+
++out:
++ release_firmware(fw);
+ return ret;
+}
+
-+int ipath_user_sdma_writev(struct ipath_devdata *dd,
-+ struct ipath_user_sdma_queue *pq,
-+ const struct iovec *iov,
-+ unsigned long dim)
++static void xc_debug_dump(struct xc5000_priv *priv)
+{
-+ int ret = 0;
-+ struct list_head list;
-+ int npkts = 0;
++ u16 adc_envelope;
++ u32 freq_error_hz = 0;
++ u16 lock_status;
++ u32 hsync_freq_hz = 0;
++ u16 frame_lines;
++ u16 quality;
++ u8 hw_majorversion = 0, hw_minorversion = 0;
++ u8 fw_majorversion = 0, fw_minorversion = 0;
+
-+ INIT_LIST_HEAD(&list);
++ /* Wait for stats to stabilize.
++ * Frame Lines needs two frame times after initial lock
++ * before it is valid.
++ */
++ xc_wait(100);
+
-+ mutex_lock(&pq->lock);
++ xc_get_ADC_Envelope(priv, &adc_envelope);
++ dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope);
+
-+ if (dd->ipath_sdma_descq_added != dd->ipath_sdma_descq_removed) {
-+ ipath_user_sdma_hwqueue_clean(dd);
-+ ipath_user_sdma_queue_clean(dd, pq);
++ xc_get_frequency_error(priv, &freq_error_hz);
++ dprintk(1, "*** Frequency error = %d Hz\n", freq_error_hz);
++
++ xc_get_lock_status(priv, &lock_status);
++ dprintk(1, "*** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d\n",
++ lock_status);
++
++ xc_get_version(priv, &hw_majorversion, &hw_minorversion,
++ &fw_majorversion, &fw_minorversion);
++ dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x\n",
++ hw_majorversion, hw_minorversion,
++ fw_majorversion, fw_minorversion);
++
++ xc_get_hsync_freq(priv, &hsync_freq_hz);
++ dprintk(1, "*** Horizontal sync frequency = %d Hz\n", hsync_freq_hz);
++
++ xc_get_frame_lines(priv, &frame_lines);
++ dprintk(1, "*** Frame lines = %d\n", frame_lines);
++
++ xc_get_quality(priv, &quality);
++ dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
++}
++
++static int xc5000_set_params(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *params)
++{
++ struct xc5000_priv *priv = fe->tuner_priv;
++ int ret;
++
++ 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", __func__);
++ priv->rf_mode = XC_RF_MODE_AIR;
++ priv->freq_hz = params->frequency - 1750000;
++ priv->bandwidth = BANDWIDTH_6_MHZ;
++ priv->video_standard = DTV6;
++ break;
++ case QAM_64:
++ case QAM_256:
++ case QAM_AUTO:
++ 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;
++ priv->video_standard = DTV6;
++ break;
++ default:
++ return -EINVAL;
+ }
+
-+ while (dim) {
-+ const int mxp = 8;
++ dprintk(1, "%s() frequency=%d (compensated)\n",
++ __func__, priv->freq_hz);
+
-+ down_write(¤t->mm->mmap_sem);
-+ ret = ipath_user_sdma_queue_pkts(dd, pq, &list, iov, dim, mxp);
-+ up_write(¤t->mm->mmap_sem);
++ ret = xc_SetSignalSource(priv, priv->rf_mode);
++ if (ret != XC_RESULT_SUCCESS) {
++ printk(KERN_ERR
++ "xc5000: xc_SetSignalSource(%d) failed\n",
++ priv->rf_mode);
++ return -EREMOTEIO;
++ }
+
-+ if (ret <= 0)
-+ goto done_unlock;
-+ else {
-+ dim -= ret;
-+ iov += ret;
-+ }
++ ret = xc_SetTVStandard(priv,
++ XC5000_Standard[priv->video_standard].VideoMode,
++ XC5000_Standard[priv->video_standard].AudioMode);
++ if (ret != XC_RESULT_SUCCESS) {
++ printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
++ return -EREMOTEIO;
++ }
+
-+ /* 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 = xc_set_IF_frequency(priv, priv->cfg->if_khz);
++ if (ret != XC_RESULT_SUCCESS) {
++ printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n",
++ priv->cfg->if_khz);
++ return -EIO;
++ }
+
-+ ret = ipath_user_sdma_push_pkts(dd, pq, &list);
-+ if (ret < 0)
-+ goto done_unlock;
-+ else {
-+ npkts += ret;
-+ pq->counter += ret;
++ xc_tune_channel(priv, priv->freq_hz);
+
-+ if (!list_empty(&list))
-+ goto done_unlock;
-+ }
-+ }
++ if (debug)
++ xc_debug_dump(priv);
++
++ return 0;
++}
++
++static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
++
++static int xc5000_set_analog_params(struct dvb_frontend *fe,
++ struct analog_parameters *params)
++{
++ struct xc5000_priv *priv = fe->tuner_priv;
++ int ret;
++
++ if(priv->fwloaded == 0)
++ xc_load_fw_and_init_tuner(fe);
++
++ dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
++ __func__, params->frequency);
++
++ priv->rf_mode = XC_RF_MODE_CABLE; /* Fix me: it could be air. */
++
++ /* params->frequency is in units of 62.5khz */
++ priv->freq_hz = params->frequency * 62500;
++
++ /* FIX ME: Some video standards may have several possible audio
++ standards. We simply default to one of them here.
++ */
++ if(params->std & V4L2_STD_MN) {
++ /* default to BTSC audio standard */
++ priv->video_standard = MN_NTSC_PAL_BTSC;
++ goto tune_channel;
+ }
+
-+done_unlock:
-+ if (!list_empty(&list))
-+ ipath_user_sdma_free_pkt_list(&dd->pcidev->dev, pq, &list);
-+ mutex_unlock(&pq->lock);
++ if(params->std & V4L2_STD_PAL_BG) {
++ /* default to NICAM audio standard */
++ priv->video_standard = BG_PAL_NICAM;
++ goto tune_channel;
++ }
+
-+ return (ret < 0) ? ret : npkts;
++ if(params->std & V4L2_STD_PAL_I) {
++ /* default to NICAM audio standard */
++ priv->video_standard = I_PAL_NICAM;
++ goto tune_channel;
++ }
++
++ if(params->std & V4L2_STD_PAL_DK) {
++ /* default to NICAM audio standard */
++ priv->video_standard = DK_PAL_NICAM;
++ goto tune_channel;
++ }
++
++ if(params->std & V4L2_STD_SECAM_DK) {
++ /* default to A2 DK1 audio standard */
++ priv->video_standard = DK_SECAM_A2DK1;
++ goto tune_channel;
++ }
++
++ if(params->std & V4L2_STD_SECAM_L) {
++ priv->video_standard = L_SECAM_NICAM;
++ goto tune_channel;
++ }
++
++ if(params->std & V4L2_STD_SECAM_LC) {
++ priv->video_standard = LC_SECAM_NICAM;
++ goto tune_channel;
++ }
++
++tune_channel:
++ ret = xc_SetSignalSource(priv, priv->rf_mode);
++ if (ret != XC_RESULT_SUCCESS) {
++ printk(KERN_ERR
++ "xc5000: xc_SetSignalSource(%d) failed\n",
++ priv->rf_mode);
++ return -EREMOTEIO;
++ }
++
++ ret = xc_SetTVStandard(priv,
++ XC5000_Standard[priv->video_standard].VideoMode,
++ XC5000_Standard[priv->video_standard].AudioMode);
++ if (ret != XC_RESULT_SUCCESS) {
++ printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
++ return -EREMOTEIO;
++ }
++
++ xc_tune_channel(priv, priv->freq_hz);
++
++ if (debug)
++ xc_debug_dump(priv);
++
++ return 0;
+}
+
-+int ipath_user_sdma_make_progress(struct ipath_devdata *dd,
-+ struct ipath_user_sdma_queue *pq)
++static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
++{
++ struct xc5000_priv *priv = fe->tuner_priv;
++ dprintk(1, "%s()\n", __func__);
++ *freq = priv->freq_hz;
++ return 0;
++}
++
++static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
++{
++ struct xc5000_priv *priv = fe->tuner_priv;
++ dprintk(1, "%s()\n", __func__);
++
++ *bw = priv->bandwidth;
++ return 0;
++}
++
++static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
++{
++ struct xc5000_priv *priv = fe->tuner_priv;
++ u16 lock_status = 0;
++
++ xc_get_lock_status(priv, &lock_status);
++
++ dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status);
++
++ *status = lock_status;
++
++ return 0;
++}
++
++static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
+{
++ struct xc5000_priv *priv = fe->tuner_priv;
+ 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);
++ if (priv->fwloaded == 0) {
++ ret = xc5000_fwupload(fe);
++ if (ret != XC_RESULT_SUCCESS)
++ return ret;
++ priv->fwloaded = 1;
++ }
++
++ /* Start the tuner self-calibration process */
++ ret |= xc_initialize(priv);
++
++ /* Wait for calibration to complete.
++ * We could continue but XC5000 will clock stretch subsequent
++ * I2C transactions until calibration is complete. This way we
++ * don't have to rely on clock stretching working.
++ */
++ xc_wait( 100 );
++
++ /* Default to "CABLE" mode */
++ ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
+
+ return ret;
+}
+
-+u32 ipath_user_sdma_complete_counter(const struct ipath_user_sdma_queue *pq)
++static int xc5000_sleep(struct dvb_frontend *fe)
+{
-+ return pq->sent_counter;
++ struct xc5000_priv *priv = fe->tuner_priv;
++ int ret;
++
++ 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
++ * doing something right.
++ *
++ */
++
++ ret = xc_shutdown(priv);
++ if(ret != XC_RESULT_SUCCESS) {
++ printk(KERN_ERR
++ "xc5000: %s() unable to shutdown tuner\n",
++ __func__);
++ return -EREMOTEIO;
++ }
++ else {
++ /* priv->fwloaded = 0; */
++ return XC_RESULT_SUCCESS;
++ }
+}
+
-+u32 ipath_user_sdma_inflight_counter(struct ipath_user_sdma_queue *pq)
++static int xc5000_init(struct dvb_frontend *fe)
+{
-+ return pq->counter;
++ struct xc5000_priv *priv = fe->tuner_priv;
++ 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");
++ return -EREMOTEIO;
++ }
++
++ if (debug)
++ xc_debug_dump(priv);
++
++ return 0;
+}
+
-diff --git a/drivers/infiniband/hw/ipath/ipath_user_sdma.h b/drivers/infiniband/hw/ipath/ipath_user_sdma.h
++static int xc5000_release(struct dvb_frontend *fe)
++{
++ dprintk(1, "%s()\n", __func__);
++ kfree(fe->tuner_priv);
++ fe->tuner_priv = NULL;
++ return 0;
++}
++
++static const struct dvb_tuner_ops xc5000_tuner_ops = {
++ .info = {
++ .name = "Xceive XC5000",
++ .frequency_min = 1000000,
++ .frequency_max = 1023000000,
++ .frequency_step = 50000,
++ },
++
++ .release = xc5000_release,
++ .init = xc5000_init,
++ .sleep = xc5000_sleep,
++
++ .set_params = xc5000_set_params,
++ .set_analog_params = xc5000_set_analog_params,
++ .get_frequency = xc5000_get_frequency,
++ .get_bandwidth = xc5000_get_bandwidth,
++ .get_status = xc5000_get_status
++};
++
++struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe,
++ struct i2c_adapter *i2c,
++ struct xc5000_config *cfg)
++{
++ struct xc5000_priv *priv = NULL;
++ u16 id = 0;
++
++ dprintk(1, "%s()\n", __func__);
++
++ priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL);
++ if (priv == NULL)
++ return NULL;
++
++ priv->cfg = cfg;
++ priv->bandwidth = BANDWIDTH_6_MHZ;
++ priv->i2c = i2c;
++
++ /* Check if firmware has been loaded. It is possible that another
++ instance of the driver has loaded the firmware.
++ */
++ if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) {
++ kfree(priv);
++ return NULL;
++ }
++
++ switch(id) {
++ case XC_PRODUCT_ID_FW_LOADED:
++ printk(KERN_INFO
++ "xc5000: Successfully identified at address 0x%02x\n",
++ cfg->i2c_address);
++ printk(KERN_INFO
++ "xc5000: Firmware has been loaded previously\n");
++ priv->fwloaded = 1;
++ break;
++ case XC_PRODUCT_ID_FW_NOT_LOADED:
++ printk(KERN_INFO
++ "xc5000: Successfully identified at address 0x%02x\n",
++ cfg->i2c_address);
++ printk(KERN_INFO
++ "xc5000: Firmware has not been loaded previously\n");
++ priv->fwloaded = 0;
++ break;
++ default:
++ printk(KERN_ERR
++ "xc5000: Device not found at addr 0x%02x (0x%x)\n",
++ cfg->i2c_address, id);
++ kfree(priv);
++ return NULL;
++ }
++
++ memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops,
++ sizeof(struct dvb_tuner_ops));
++
++ fe->tuner_priv = priv;
++
++ return fe;
++}
++EXPORT_SYMBOL(xc5000_attach);
++
++MODULE_AUTHOR("Steven Toth");
++MODULE_DESCRIPTION("Xceive xc5000 silicon tuner driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/common/tuners/xc5000.h b/drivers/media/common/tuners/xc5000.h
new file mode 100644
-index 0000000..e70946c
+index 0000000..0ee80f9
--- /dev/null
-+++ b/drivers/infiniband/hw/ipath/ipath_user_sdma.h
-@@ -0,0 +1,54 @@
++++ b/drivers/media/common/tuners/xc5000.h
+@@ -0,0 +1,63 @@
+/*
-+ * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved.
++ * Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
+ *
-+ * 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:
++ * Copyright (c) 2007 Steven Toth <stoth at hauppauge.com>
+ *
-+ * Redistribution and use in source and binary forms, with or
-+ * without modification, are permitted provided that the following
-+ * conditions are met:
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
+ *
-+ * - Redistributions of source code must retain the above
-+ * copyright notice, this list of conditions and the following
-+ * disclaimer.
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
-+ * - 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.
++ * GNU General Public License for more details.
+ *
-+ * 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.
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
-+#include <linux/device.h>
+
-+struct ipath_user_sdma_queue;
++#ifndef __XC5000_H__
++#define __XC5000_H__
+
-+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);
++#include <linux/firmware.h>
+
-+int ipath_user_sdma_writev(struct ipath_devdata *dd,
-+ struct ipath_user_sdma_queue *pq,
-+ const struct iovec *iov,
-+ unsigned long dim);
++struct dvb_frontend;
++struct i2c_adapter;
+
-+int ipath_user_sdma_make_progress(struct ipath_devdata *dd,
-+ struct ipath_user_sdma_queue *pq);
++struct xc5000_config {
++ u8 i2c_address;
++ u32 if_khz;
++
++ /* For each bridge framework, when it attaches either analog or digital,
++ * it has to store a reference back to its _core equivalent structure,
++ * so that it can service the hardware by steering gpio's etc.
++ * Each bridge implementation is different so cast priv accordingly.
++ * The xc5000 driver cares not for this value, other than ensuring
++ * it's passed back to a bridge during tuner_callback().
++ */
++ void *priv;
++ int (*tuner_callback) (void *priv, int command, int arg);
++};
+
-+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);
++/* xc5000 callback command */
++#define XC5000_TUNER_RESET 0
+
-+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");
++#if defined(CONFIG_MEDIA_TUNER_XC5000) || \
++ (defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE))
++extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
++ struct i2c_adapter *i2c,
++ struct xc5000_config *cfg);
++#else
++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", __func__);
++ return NULL;
++}
++#endif // CONFIG_MEDIA_TUNER_XC5000
++
++#endif // __XC5000_H__
+diff --git a/drivers/media/common/tuners/xc5000_priv.h b/drivers/media/common/tuners/xc5000_priv.h
+new file mode 100644
+index 0000000..13b2d19
+--- /dev/null
++++ b/drivers/media/common/tuners/xc5000_priv.h
+@@ -0,0 +1,36 @@
++/*
++ * Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
++ *
++ * Copyright (c) 2007 Steven Toth <stoth at hauppauge.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef XC5000_PRIV_H
++#define XC5000_PRIV_H
++
++struct xc5000_priv {
++ struct xc5000_config *cfg;
++ struct i2c_adapter *i2c;
++
++ u32 freq_hz;
++ u32 bandwidth;
++ u8 video_standard;
++ u8 rf_mode;
++ u8 fwloaded;
++};
++
++#endif
+diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
+index 03ef88a..7b21b49 100644
+--- a/drivers/media/dvb/Kconfig
++++ b/drivers/media/dvb/Kconfig
+@@ -1,9 +1,7 @@
+ #
+-# Multimedia device configuration
++# DVB device configuration
+ #
- 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");
+-source "drivers/media/dvb/dvb-core/Kconfig"
+-
+ menuconfig DVB_CAPTURE_DRIVERS
+ bool "DVB/ATSC adapters"
+ depends on DVB_CORE
+diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
+index 3197aeb..73dc2ee 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 MEDIA_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..d9db066 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
- 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);
- }
++
+ 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
-+/*
-+ * 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 */
+ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
++EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+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;
+
-+ while (length) {
-+ u32 len = sge.length;
++ u8 no_base_addr;
++ flexcop_i2c_port_t port;
++};
+
-+ 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;
+ /* 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 ndesc;
-+}
+ return ret;
+ }
+
+ static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len, int retries)
+ {
+- int ret = flexcop_eeprom_request(fc,FC_READ,addr,buf,len,retries);
++ int ret = flexcop_eeprom_request(fc, FC_READ, addr, buf, len, retries);
+ if (ret == 0)
+ if (calc_lrc(buf, len - 1) != buf[len - 1])
+ ret = -EINVAL;
+diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+index 0378fd6..7b0ea3b 100644
+--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
++++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+@@ -5,6 +5,8 @@
+ *
+ * see flexcop.c for copyright information.
+ */
++#include <media/tuner.h>
+
-+/*
-+ * 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;
+ #include "flexcop.h"
+
+ #include "stv0299.h"
+@@ -15,6 +17,15 @@
+ #include "mt312.h"
+ #include "lgdt330x.h"
+ #include "dvb-pll.h"
++#include "tuner-simple.h"
+
-+ while (length) {
-+ u32 len = sge->length;
++#include "s5h1420.h"
++#include "itd1000.h"
+
-+ 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;
-+ }
-+}
++#include "cx24123.h"
++#include "cx24113.h"
+
- /**
- * 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);
++#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;
}
--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;
-+ }
-+}
+@@ -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,
+ };
+
+
-+/*
-+ * 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;
-+ }
-+}
++/* SkyStar2 rev2.7 (a/u) */
++static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
++ .demod_address = 0x53,
++ .invert = 1,
++ .repeated_start_workaround = 1,
++};
+
-+static inline struct ipath_verbs_txreq *get_txreq(struct ipath_ibdev *dev)
-+{
-+ struct ipath_verbs_txreq *tx = NULL;
-+ unsigned long flags;
++static struct itd1000_config skystar2_rev2_7_itd1000_config = {
++ .i2c_address = 0x61,
++};
+
-+ spin_lock_irqsave(&dev->pending_lock, flags);
-+ if (!list_empty(&dev->txreq_free)) {
-+ struct list_head *l = dev->txreq_free.next;
++/* SkyStar2 rev2.8 */
++static struct cx24123_config skystar2_rev2_8_cx24123_config = {
++ .demod_address = 0x55,
++ .dont_use_pll = 1,
++ .agc_callback = cx24113_agc_callback,
++};
+
-+ list_del(l);
-+ tx = list_entry(l, struct ipath_verbs_txreq, txreq.list);
-+ }
-+ spin_unlock_irqrestore(&dev->pending_lock, flags);
-+ return tx;
-+}
++static const struct cx24113_config skystar2_rev2_8_cx24113_config = {
++ .i2c_addr = 0x54,
++ .xtal_khz = 10111,
++};
+
-+static inline void put_txreq(struct ipath_ibdev *dev,
-+ struct ipath_verbs_txreq *tx)
-+{
-+ unsigned long flags;
+ /* 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;
+
-+ spin_lock_irqsave(&dev->pending_lock, flags);
-+ list_add(&tx->txreq.list, &dev->txreq_free);
-+ spin_unlock_irqrestore(&dev->pending_lock, flags);
-+}
++ /* 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;
+
-+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);
++ fc->fe_sleep = ops->sleep;
++ ops->sleep = flexcop_sleep;
+
-+ /* 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;
++ fc->dev_type = FC_SKY_REV27;
+
-+ ipath_send_complete(qp, tx->wqe, ibs);
++ /* 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 */
+
-+ if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_FREEBUF)
-+ kfree(tx->txreq.map_addr);
-+ put_txreq(dev, tx);
++ /* 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");
++ }
+
-+ if (atomic_dec_and_test(&qp->refcount))
-+ wake_up(&qp->wait);
-+}
++ fc->dev_type = FC_SKY_REV28;
+
-+/*
-+ * 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;
-+}
++ 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");
+
-+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;
++ /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an
++ * IR-receiver (PIC16F818) - but the card has no input for
++ * that ??? */
+
-+ 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;
++ 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;
+ }
+
-+ tx = get_txreq(dev);
-+ if (!tx) {
-+ ret = -EBUSY;
-+ goto bail;
+ /* 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;
+ }
+
-+ /*
-+ * 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;
++ 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;
+ }
+
-+ 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;
+ /* 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;
+ }
+
-+ /* 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;
+ /* 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;
+ }
-+ 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;
+ /* 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;
+
-+err_tx:
-+ if (atomic_dec_and_test(&qp->refcount))
-+ wake_up(&qp->wait);
-+ put_txreq(dev, tx);
-+bail:
-+ return ret;
-+}
++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 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)
+ static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100)
{
- struct ipath_devdata *dd = to_idev(qp->ibqp.device)->dd;
-+ u32 *hdr = (u32 *) ibhdr;
- u32 __iomem *piobuf;
- unsigned flush_wc;
-+ u32 control;
- int ret;
+ int i;
+@@ -38,30 +40,25 @@ static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r
+ return -EREMOTEIO;
+ }
-- piobuf = ipath_getpiobuf(dd, NULL);
-+ piobuf = ipath_getpiobuf(dd, plen, NULL);
- if (unlikely(piobuf == NULL)) {
- ret = -EBUSY;
- goto bail;
+-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;
}
- /*
-- * 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);
+ 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;
+
-+ /* VL15 packets bypass credit check */
-+ if ((be16_to_cpu(ibhdr->lrh[0]) >> 12) == 15)
-+ control |= 1ULL << 31;
++#ifdef DUMP_I2C_MESSAGES
++ int i;
++#endif
+
-+ /*
-+ * 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;
+ u16 bytes_to_transfer;
+ flexcop_ibi_value r100;
-- /* 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);
+@@ -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
-+ ret = ipath_verbs_send_pio(qp, hdr, hdrwords, ss, len,
-+ plen, dwords);
++ 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;
++ }
- 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;
+ 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;
- ret = 0;
+ 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
-@@ -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;
+ 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;
+- };
++ }
+
- /* 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;
++#ifdef DUMP_I2C_MESSAGES
++ printk("\n");
++#endif
-- /*
-- * 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,
+ 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;
- /* ib_create_ah() will initialize ah->ibah. */
- ah->attr = *ah_attr;
-+ ah->attr.static_rate = ipath_ib_rate_to_mult(ah_attr->static_rate);
+ /* 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;
- ret = &ah->ibah;
+- if (mutex_lock_interruptible(&fc->i2c_mutex))
++ if (mutex_lock_interruptible(&i2c->fc->i2c_mutex))
+ return -ERESTARTSYS;
-@@ -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);
+- /* 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);
+ }
- *ah_attr = ah->attr;
-+ ah_attr->static_rate = ipath_mult_to_ib_rate(ah->attr.static_rate);
+- if (ret < 0)
+- err("i2c master_xfer failed");
+- else
+- ret = num;
+-
+- mutex_unlock(&fc->i2c_mutex);
++ mutex_unlock(&i2c->fc->i2c_mutex);
- return 0;
++ if (ret == 0)
++ ret = num;
+ return ret;
}
-@@ -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)
+@@ -189,28 +213,68 @@ int flexcop_i2c_init(struct flexcop_device *fc)
- dev = &idev->ibdev;
+ mutex_init(&fc->i2c_mutex);
-+ 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;
+- 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;
+
- /* 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 */
++ 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;
- /* 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;
+- 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;
-+ for (i = 0; i < dd->ipath_sdma_descq_cnt; i++, tx++)
-+ list_add(&tx->txreq.list, &idev->txreq_free);
+- 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;
+
- /*
- * 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);
++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;
}
--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)
+ void flexcop_i2c_exit(struct flexcop_device *fc)
{
- struct ipath_ibdev *dev =
-- container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
-+ container_of(device, struct ipath_ibdev, ibdev.dev);
+- 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);
++ }
- return sprintf(buf, "%x\n", dev->dd->ipath_pcirev);
+ 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 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;
+ 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)
- ret = dev->dd->ipath_f_get_boardname(dev->dd, buf, 128);
-@@ -1835,10 +2197,11 @@ bail:
- return ret;
- }
+-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);
--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)
+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)
{
- 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;
+ u8 tmp1, tmp2;
-@@ -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];
+- dprintk("%s: mask = %x, addr = %x\n", __FUNCTION__, mask, addr);
++ dprintk("%s: mask = %x, addr = %x\n", __func__, mask, addr);
-@@ -1874,16 +2239,16 @@ static ssize_t show_stats(struct class_device *cdev, char *buf)
- return len;
+ 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
--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);
+ /* 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;
--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
- };
+ 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 ipath_verbs_register_sysfs(struct ib_device *dev)
-@@ -1892,8 +2257,8 @@ static int ipath_verbs_register_sysfs(struct ib_device *dev)
- int ret;
+-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);
+ }
- 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));
+ 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
-+struct ipath_pio_header {
-+ __le32 pbc[2];
-+ struct ipath_ib_header hdr;
-+} __attribute__ ((packed));
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
- /*
- * 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;
- };
+ /* global zero for ibi values */
+ flexcop_ibi_value ibi_zero;
- /*
-@@ -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;
- };
+@@ -66,8 +68,10 @@ static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-+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)
+ static int flexcop_dvb_init(struct flexcop_device *fc)
{
- 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);
+- 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;
-+unsigned ipath_ib_rate_to_mult(enum ib_rate rate);
++ /* 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;
+
- int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr,
- u32 hdrwords, struct ipath_sge_state *ss, u32 len);
+ /* 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");
--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);
+- if ((ret = flexcop_i2c_init(fc)))
+- goto error;
+-
+ if ((ret = flexcop_frontend_init(fc)))
+ goto error;
- 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);
- }
+diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
+index ea66617..d1239b8 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 MEDIA_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..d98f1d4 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
-+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;
+-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/common/tuners
+diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
+index 307ff35..a763756 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;
+@@ -1714,7 +1714,7 @@ static void dst_release(struct dvb_frontend *fe)
+ struct dst_state *state = fe->demodulator_priv;
+ if (state->dst_ca) {
+ dvb_unregister_device(state->dst_ca);
+-#ifdef CONFIG_DVB_CORE_ATTACH
++#ifdef CONFIG_MEDIA_ATTACH
+ symbol_put(dst_ca_attach);
+ #endif
+ }
+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, " ==================================================================================================");
- 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
+ // 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).");
- 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;
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define dprintk( args... ) \
+- do \
++ do { \
+ if (debug) printk(KERN_DEBUG args); \
+- while (0)
++ } while (0)
- 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;
+ #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;
+ }
-- 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;
+@@ -715,7 +719,10 @@ static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
+ {
+ int result;
- 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 ((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"
-- if (mlx4_buf_alloc(dev->dev, buf_size, PAGE_SIZE * 2, &cq->buf.buf)) {
-- err = -ENOMEM;
-- goto err_db;
-- }
+ 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/Kconfig b/drivers/media/dvb/dvb-core/Kconfig
+deleted file mode 100644
+index e3e6839..0000000
+--- a/drivers/media/dvb/dvb-core/Kconfig
++++ /dev/null
+@@ -1,34 +0,0 @@
+-config DVB_CORE
+- tristate "DVB for Linux"
+- depends on NET && INET
+- select CRC32
+- help
+- Support Digital Video Broadcasting hardware. Enable this if you
+- own a DVB adapter and want to use it or if you compile Linux for
+- a digital SetTopBox.
+-
+- DVB core utility functions for device handling, software fallbacks etc.
+- Say Y when you have a DVB card and want to use it. Say Y if your want
+- to build your drivers outside the kernel, but need the DVB core. All
+- in-kernel drivers will select this automatically if needed.
+-
+- API specs and user tools are available from <http://www.linuxtv.org/>.
+-
+- Please report problems regarding this driver to the LinuxDVB
+- mailing list.
+-
+- If unsure say N.
+-
+-config DVB_CORE_ATTACH
+- bool "Load and attach frontend modules as needed"
+- depends on DVB_CORE
+- depends on MODULES
+- help
+- Remove the static dependency of DVB card drivers on all
+- frontend modules for all possible card variants. Instead,
+- allow the card drivers to only load the frontend modules
+- they require. This saves several KBytes of memory.
-
-- 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;
+- Note: You will need module-init-tools v3.2 or later for this feature.
-
-- err = mlx4_buf_write_mtt(dev->dev, &cq->buf.mtt, &cq->buf.buf);
-- if (err)
-- goto err_mtt;
-+ goto err_db;
+- If unsure say Y.
+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 */
- uar = &dev->priv_uar;
- }
-@@ -187,12 +243,10 @@ err_dbmap:
- err_mtt:
- mlx4_mtt_cleanup(dev->dev, &cq->buf.mtt);
+ /* 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;
--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);
+- dprintk("function : %s\n", __FUNCTION__);
++ dprintk("function : %s\n", __func__);
- err_db:
- if (!context)
-@@ -204,6 +258,170 @@ err_cq:
- return ERR_PTR(err);
+ 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 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)
++static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev,
++ unsigned long size)
+{
-+ struct mlx4_ib_resize_cq ucmd;
-+ int err;
++ struct dvb_ringbuffer *buf = &dmxdev->dvr_buffer;
++ void *newmem;
++ void *oldmem;
+
-+ if (cq->resize_umem)
-+ return -EBUSY;
++ dprintk("function : %s\n", __func__);
+
-+ if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
-+ return -EFAULT;
++ if (buf->size == size)
++ return 0;
++ if (!size)
++ return -EINVAL;
+
-+ cq->resize_buf = kmalloc(sizeof *cq->resize_buf, GFP_ATOMIC);
-+ if (!cq->resize_buf)
++ newmem = vmalloc(size);
++ if (!newmem)
+ 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;
++ oldmem = buf->data;
+
-+ i = cq->mcq.cons_index;
-+ while (get_sw_cqe(cq, i & cq->ibcq.cqe))
-+ ++i;
++ spin_lock_irq(&dmxdev->lock);
++ buf->data = newmem;
++ buf->size = size;
+
-+ return i - cq->mcq.cons_index;
-+}
++ /* reset and not flush in case the buffer shrinks */
++ dvb_ringbuffer_reset(buf);
++ spin_unlock_irq(&dmxdev->lock);
+
-+static void mlx4_ib_cq_resize_copy_cqes(struct mlx4_ib_cq *cq)
-+{
-+ struct mlx4_cqe *cqe;
-+ int i;
++ vfree(oldmem);
+
-+ 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;
++ return 0;
+}
+
-+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;
+ 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;
+
-+err_buf:
-+ if (!ibcq->uobject)
-+ mlx4_ib_free_cq_buf(dev, &cq->resize_buf->buf,
-+ cq->resize_buf->cqe);
++ newmem = vmalloc(size);
++ if (!newmem)
++ return -ENOMEM;
+
-+ kfree(cq->resize_buf);
-+ cq->resize_buf = NULL;
++ oldmem = buf->data;
+
-+ if (cq->resize_umem) {
-+ ib_umem_release(cq->resize_umem);
-+ cq->resize_umem = NULL;
-+ }
+ spin_lock_irq(&dmxdevfilter->dev->lock);
+- mem = buf->data;
+- buf->data = NULL;
++ buf->data = newmem;
+ buf->size = size;
+- dvb_ringbuffer_flush(buf);
+
-+out:
-+ mutex_unlock(&cq->resize_mutex);
-+ return err;
-+}
++ /* 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);
+
- 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);
+ return 0;
+ }
+
+@@ -374,7 +411,8 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
+ return 0;
}
-@@ -297,6 +514,20 @@ static void mlx4_ib_handle_error_cqe(struct mlx4_err_cqe *cqe,
- wc->vendor_err = cqe->vendor_err_syndrome;
- }
+- 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;
+ }
-+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;
+@@ -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)
-+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;
- }
+ 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;
-+ /* 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;
+ 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;
}
- } 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);
+
+@@ -276,7 +276,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
+ msleep(1);
}
- 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;
+- dprintk("%s failed timeout:%lu\n", __FUNCTION__, jiffies - start);
++ dprintk("%s failed timeout:%lu\n", __func__, jiffies - start);
-- 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"
+ /* 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];
- #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"
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
- 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;
+ /* 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;
- props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
- 0xffffff;
-@@ -477,42 +481,51 @@ out:
- return err;
- }
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
--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);
- }
+ /* 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;
--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);
- }
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
--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)
+ /* 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)
{
-- 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);
- }
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
--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)
+ 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)
{
-- 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);
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
--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
- };
+ ca->wakeup = 1;
+ mb();
+@@ -964,7 +964,7 @@ static int dvb_ca_en50221_thread(void *data)
+ int pktcount;
+ void *rxbuf;
- 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;
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
- 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;
+ /* 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;
}
-@@ -675,18 +691,20 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
- }
+diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
+index 925cfa6..8cbdb21 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;
- 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;
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- 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;
+ 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;
-- 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;
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
-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;
- };
+ if (events->overflow) {
+ events->overflow = 0;
+@@ -237,7 +237,7 @@ static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepr
+ {
+ int q2;
-+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;
- };
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- struct mlx4_ib_mr {
-@@ -110,6 +118,10 @@ struct mlx4_ib_wq {
- unsigned tail;
- };
+ 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
-+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);
+ 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);
-+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 {
+ /* set the frontend itself */
+@@ -511,7 +511,7 @@ static int dvb_frontend_thread(void *data)
+ fe_status_t s;
+ struct dvb_frontend_parameters *params;
- 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)
- }
- }
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
--static int send_wqe_overhead(enum ib_qp_type type)
-+static int send_wqe_overhead(enum ib_qp_type type, u32 flags)
+ fepriv->check_wrapped = 0;
+ fepriv->quality = 0;
+@@ -597,7 +597,7 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
{
- /*
- * 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;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
-@@ -329,7 +331,7 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- 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);
+ 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;
- /*
- * 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,
- }
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- 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);
+ 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;
- 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;
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
-+ 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;
+ 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;
-+ /* 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,
- }
- }
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
-- 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:
- }
+ poll_wait (file, &fepriv->events.wait_queue, wait);
- 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;
- }
+@@ -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;
-- 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;
- }
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- 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);
+ 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);
+@@ -1189,7 +1189,7 @@ int dvb_unregister_frontend(struct dvb_frontend* fe)
}
+ EXPORT_SYMBOL(dvb_unregister_frontend);
-+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)
+-#ifdef CONFIG_DVB_CORE_ATTACH
++#ifdef CONFIG_MEDIA_ATTACH
+ void dvb_frontend_detach(struct dvb_frontend* fe)
{
-@@ -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;
+ void *ptr;
+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
- 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;
+ /* 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;
- 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;
+- 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__);
-@@ -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;
+ priv->secfeed=NULL;
+ priv->secfilter=NULL;
+ priv->tsfeed = NULL;
- 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;
+ 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)
+ }
- 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 (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);
+ }
- 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
- }
+ 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;
+ }
- err = mlx4_qp_query(dev->dev, &qp->mqp, &context);
-- if (err)
-- return -EINVAL;
-+ if (err) {
-+ err = -EINVAL;
-+ goto out;
-+ }
+- 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
- mlx4_state = be32_to_cpu(context.flags) >> 28;
+ /* 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;
+ }
-- 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:
+- 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;
- qp_init_attr->cap = qp_attr->cap;
+- 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);
+ }
-- return 0;
-+out:
-+ mutex_unlock(&qp->mutex);
-+ return err;
+ if (priv->secfilter) {
+- dprintk("%s: release secfilter\n", __FUNCTION__);
++ dprintk("%s: release secfilter\n", __func__);
+ priv->secfeed->release_filter(priv->secfeed,
+ priv->secfilter);
+ priv->secfilter=NULL;
+@@ -1082,7 +1082,7 @@ static int dvb_net_feed_stop(struct net_device *dev)
+ for (i=0; i<priv->multi_num; i++) {
+ if (priv->multi_secfilter[i]) {
+ dprintk("%s: release multi_filter[%d]\n",
+- __FUNCTION__, i);
++ __func__, i);
+ priv->secfeed->release_filter(priv->secfeed,
+ priv->multi_secfilter[i]);
+ priv->multi_secfilter[i] = NULL;
+@@ -1096,7 +1096,7 @@ static int dvb_net_feed_stop(struct net_device *dev)
+ } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
+ if (priv->tsfeed) {
+ if (priv->tsfeed->is_filtering) {
+- dprintk("%s: stop tsfeed\n", __FUNCTION__);
++ dprintk("%s: stop tsfeed\n", __func__);
+ priv->tsfeed->stop_filtering(priv->tsfeed);
+ }
+ priv->demux->release_ts_feed(priv->demux, priv->tsfeed);
+diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+index ac9d93c..872985b 100644
+--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
++++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+@@ -90,7 +90,11 @@ void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
+ rbuf->error = 0;
}
-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);
+-
++void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf)
++{
++ rbuf->pread = rbuf->pwrite = 0;
++ rbuf->error = 0;
++}
-+ /* 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) */
+ 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.
+ */
- /* 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;
+@@ -85,6 +86,13 @@ extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf);
+ extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf);
- cqe = next_cqe_sw(cq);
- if (!cqe)
-@@ -635,12 +637,14 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
- break;
- }
- entry->slid = be16_to_cpu(cqe->rlid);
-- entry->sl = be16_to_cpu(cqe->sl_g_mlpath) >> 12;
-+ entry->sl = cqe->sl_ipok >> 4;
- entry->src_qp = be32_to_cpu(cqe->rqpn) & 0xffffff;
-- entry->dlid_path_bits = be16_to_cpu(cqe->sl_g_mlpath) & 0x7f;
-+ entry->dlid_path_bits = cqe->g_mlpath & 0x7f;
- entry->pkey_index = be32_to_cpu(cqe->imm_etype_pkey_eec) >> 16;
-- entry->wc_flags |= be16_to_cpu(cqe->sl_g_mlpath) & 0x80 ?
-- IB_WC_GRH : 0;
-+ entry->wc_flags |= cqe->g_mlpath & 0x80 ? IB_WC_GRH : 0;
-+ checksum = (be32_to_cpu(cqe->rqpn) >> 24) |
-+ ((be32_to_cpu(cqe->my_ee) >> 16) & 0xff00);
-+ entry->csum_ok = (cqe->sl_ipok & 1 && checksum == 0xffff);
- }
- entry->status = IB_WC_SUCCESS;
-diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
-index 7bbdd1f..7bc32f8 100644
---- a/drivers/infiniband/hw/mthca/mthca_dev.h
-+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
-@@ -46,16 +46,15 @@
- #include <linux/timer.h>
- #include <linux/mutex.h>
- #include <linux/list.h>
--
--#include <asm/semaphore.h>
-+#include <linux/semaphore.h>
++/*
++** 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"
+ };
- #include "mthca_provider.h"
- #include "mthca_doorbell.h"
+-#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)
+ }
- #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)
+-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;
+ }
-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;
+@@ -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 inline struct mthca_eqe* next_eqe_sw(struct mthca_eq *eq)
-+static inline struct mthca_eqe *next_eqe_sw(struct mthca_eq *eq)
++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)
{
-- 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;
+ int num = 0;
-- 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;
+ 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++;
+ }
-+ 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;
+@@ -281,13 +287,28 @@ skip:
}
- static int mthca_init_tavor(struct mthca_dev *mdev)
+
+-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)
{
-+ 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;
+- int num;
++ int i, num;
-- 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;
+ 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..89d12dc 100644
+--- a/drivers/media/dvb/dvb-core/dvbdev.h
++++ b/drivers/media/dvb/dvb-core/dvbdev.h
+@@ -31,6 +31,10 @@
- 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;
+ #define DVB_MAJOR 212
-@@ -653,7 +660,7 @@ static int mthca_init_arbel(struct mthca_dev *mdev)
- profile.num_srq = dev_lim.max_srqs;
++#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
- 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;
++#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")
-- 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);
+ struct dvb_adapter {
+ int num;
+@@ -78,7 +87,9 @@ struct dvb_device {
+ };
- 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
- };
+-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);
--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,
- };
+ extern int dvb_register_device (struct dvb_adapter *adap,
+@@ -104,7 +115,7 @@ extern int dvb_usercopy(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg));
- 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;
- };
+ /** generic DVB attach function. */
+-#ifdef CONFIG_DVB_CORE_ATTACH
++#ifdef CONFIG_MEDIA_ATTACH
+ #define dvb_attach(FUNCTION, ARGS...) ({ \
+ void *__r = NULL; \
+ typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
+diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
+index d73934d..4c1cff9 100644
+--- a/drivers/media/dvb/dvb-usb/Kconfig
++++ b/drivers/media/dvb/dvb-usb/Kconfig
+@@ -25,7 +25,7 @@ config DVB_USB_A800
+ tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)"
+ depends on DVB_USB
+ select DVB_DIB3000MC
+- select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
++ select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ select DVB_PLL if !DVB_FE_CUSTOMISE
+ help
+ Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
+@@ -35,7 +35,7 @@ config DVB_USB_DIBUSB_MB
+ depends on DVB_USB
+ select DVB_PLL if !DVB_FE_CUSTOMISE
+ select DVB_DIB3000MB
+- select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
++ select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ help
+ Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
+ DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
+@@ -56,7 +56,7 @@ config DVB_USB_DIBUSB_MC
+ tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
+ depends on DVB_USB
+ select DVB_DIB3000MC
+- select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
++ select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ help
+ Support for USB2.0 DVB-T receivers based on reference designs made by
+ DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
+@@ -73,8 +73,8 @@ config DVB_USB_DIB0700
+ select DVB_DIB7000P
+ select DVB_DIB7000M
+ select DVB_DIB3000MC
+- select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+- select DVB_TUNER_MT2266 if !DVB_FE_CUSTOMISE
++ select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
++ select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE
+ select DVB_TUNER_DIB0070
+ help
+ Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
+@@ -93,7 +93,7 @@ config DVB_USB_UMT_010
+ depends on DVB_USB
+ select DVB_PLL if !DVB_FE_CUSTOMISE
+ select DVB_DIB3000MC
+- select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
++ select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ help
+ Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
--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);
+@@ -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 MEDIA_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
+@@ -117,7 +118,7 @@ config DVB_USB_M920X
+ tristate "Uli m920x DVB-T USB2.0 support"
+ depends on DVB_USB
+ select DVB_MT352 if !DVB_FE_CUSTOMISE
+- select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
++ select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+ help
+ Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
+ Currently, only devices with a product id of
+@@ -128,7 +129,7 @@ config DVB_USB_GL861
+ tristate "Genesys Logic GL861 USB2.0 support"
+ depends on DVB_USB
+ select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+- select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
++ select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+ help
+ Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0
+ receiver with USB ID 0db0:5581.
+@@ -137,7 +138,7 @@ config DVB_USB_AU6610
+ tristate "Alcor Micro AU6610 USB2.0 support"
+ depends on DVB_USB
+ select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+- select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
++ select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+ help
+ Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver.
- u8 status;
+@@ -189,7 +190,7 @@ config DVB_USB_NOVA_T_USB2
+ tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
+ depends on DVB_USB
+ select DVB_DIB3000MC
+- select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
++ select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ select DVB_PLL if !DVB_FE_CUSTOMISE
+ help
+ Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
+@@ -226,8 +227,8 @@ config DVB_USB_OPERA1
+ config DVB_USB_AF9005
+ tristate "Afatech AF9005 DVB-T USB1.1 support"
+ depends on DVB_USB && EXPERIMENTAL
+- select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+- select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
++ select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
++ select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+ help
+ Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver
+ and the TerraTec Cinergy T USB XE (Rev.1)
+diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
+index 60a9100..c6511a6 100644
+--- a/drivers/media/dvb/dvb-usb/Makefile
++++ b/drivers/media/dvb/dvb-usb/Makefile
+@@ -63,5 +63,5 @@ obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o
-@@ -540,6 +540,9 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
- struct mthca_qp *qp;
- int err;
+ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ # due to tuner-xc3028
+-EXTRA_CFLAGS += -Idrivers/media/video
++EXTRA_CFLAGS += -Idrivers/media/common/tuners
-+ if (init_attr->create_flags)
-+ return ERR_PTR(-EINVAL);
+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);
+
- 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);
- }
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define deb_rc(args...) dprintk(debug,0x01,args)
--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)
+ 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)
{
-- 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);
+- return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE,NULL);
++ return dvb_usb_device_init(intf, &a800_properties,
++ THIS_MODULE, NULL, adapter_nr);
}
--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)
- }
- }
+ /* 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.");
--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)
++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)
{
-- 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);
+- 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 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;
+ 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);
-+ mutex_lock(&qp->mutex);
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
- if (qp->state == IB_QPS_RESET) {
- qp_attr->qp_state = IB_QPS_RESET;
- goto done;
- }
+ 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;
- 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;
-+ }
+- 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);
- 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;
- }
+ if (alt == NULL) {
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
+index c583650..720fcd1 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.c
++++ b/drivers/media/dvb/dvb-usb/cxusb.c
+@@ -23,6 +23,8 @@
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
++#include <media/tuner.h>
++
+ #include "cxusb.h"
- qp_param = mailbox->buf;
- context = &qp_param->context;
- mthca_state = be32_to_cpu(context->flags) >> 28;
+ #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"
-- 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:
+ /* 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;
+ }
- qp_init_attr->cap = qp_attr->cap;
+@@ -477,8 +483,8 @@ static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
--out:
-+out_mailbox:
- mthca_free_mailbox(dev, mailbox);
-+
-+out:
-+ mutex_unlock(&qp->mutex);
- return err;
+ 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;
}
-@@ -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;
+@@ -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;
-@@ -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;
+ }
+@@ -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,
+ };
- wqe += sizeof (struct mthca_next_seg);
- size = sizeof (struct mthca_next_seg) / 16;
-diff --git a/drivers/infiniband/hw/mthca/mthca_wqe.h b/drivers/infiniband/hw/mthca/mthca_wqe.h
-index f6a66fe..b3551a8 100644
---- a/drivers/infiniband/hw/mthca/mthca_wqe.h
-+++ b/drivers/infiniband/hw/mthca/mthca_wqe.h
-@@ -38,14 +38,16 @@
- #include <linux/types.h>
+ 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;
+- }
- 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
+ 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;
};
- 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);
+@@ -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);
- 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);
+ 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[];
+
- 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();
- }
+ #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);
-@@ -751,13 +738,13 @@ static void __devexit nes_remove(struct pci_dev *pcidev)
+-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).");
- list_del(&nesdev->list);
- nes_destroy_cqp(nesdev);
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
-+ free_irq(pcidev->irq, nesdev);
- tasklet_kill(&nesdev->dpc_tasklet);
+ /* 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);
+ }
- /* Deallocate the Adapter Structure */
- nes_destroy_adapter(nesdev->nesadapter);
+-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;
-- free_irq(pcidev->irq, nesdev);
--
- if (nesdev->msi_enabled) {
- pci_disable_msi(pcidev);
- }
-diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h
-index a48b288..cdf2e9a 100644
---- a/drivers/infiniband/hw/nes/nes.h
-+++ b/drivers/infiniband/hw/nes/nes.h
-@@ -43,7 +43,6 @@
- #include <linux/dma-mapping.h>
- #include <linux/workqueue.h>
- #include <linux/slab.h>
--#include <asm/semaphore.h>
- #include <linux/version.h>
- #include <asm/io.h>
- #include <linux/crc32c.h>
-@@ -143,12 +142,12 @@
- #ifdef CONFIG_INFINIBAND_NES_DEBUG
- #define nes_debug(level, fmt, args...) \
- if (level & nes_debug_level) \
-- printk(KERN_ERR PFX "%s[%u]: " fmt, __FUNCTION__, __LINE__, ##args)
-+ printk(KERN_ERR PFX "%s[%u]: " fmt, __func__, __LINE__, ##args)
+ 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"
- #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__); \
+ 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;;
}
- #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;
++/* 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
- extern struct list_head nes_adapter_list;
--extern struct list_head nes_dev_list;
--
--extern struct nes_cm_core *g_cm_core;
+ static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
- 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;
++/* Number of keypresses to ignore before start repeating */
++#define RC_REPEAT_DELAY 2
++
+ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+ {
+ u8 key[4];
+@@ -314,18 +461,67 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+ err("RC Query Failed");
+ return -1;
+ }
++
++ /* losing half of KEY_0 events from Philipps rc5 remotes.. */
+ if (key[0]==0 && key[1]==0 && key[2]==0 && key[3]==0) return 0;
+- if (key[3-1]!=st->rc_toggle) {
++
++ /* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)key[3-2],(int)key[3-3],(int)key[3-1],(int)key[3]); */
++
++ dib0700_rc_setup(d); /* reset ir sensor data to prevent false events */
++
++ switch (dvb_usb_dib0700_ir_proto) {
++ case 0: {
++ /* NEC protocol sends repeat code as 0 0 0 FF */
++ if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
++ (key[3] == 0xFF)) {
++ st->rc_counter++;
++ if (st->rc_counter > RC_REPEAT_DELAY) {
++ *event = d->last_event;
++ *state = REMOTE_KEY_PRESSED;
++ st->rc_counter = RC_REPEAT_DELAY;
++ }
++ return 0;
++ }
+ for (i=0;i<d->props.rc_key_map_size; i++) {
+ if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) {
++ st->rc_counter = 0;
++ *event = keymap[i].event;
++ *state = REMOTE_KEY_PRESSED;
++ d->last_event = keymap[i].event;
++ return 0;
++ }
++ }
++ break;
++ }
++ default: {
++ /* RC-5 protocol changes toggle bit on new keypress */
++ for (i = 0; i < d->props.rc_key_map_size; i++) {
++ if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) {
++ if (d->last_event == keymap[i].event &&
++ key[3-1] == st->rc_toggle) {
++ st->rc_counter++;
++ /* prevents unwanted double hits */
++ if (st->rc_counter > RC_REPEAT_DELAY) {
++ *event = d->last_event;
++ *state = REMOTE_KEY_PRESSED;
++ st->rc_counter = RC_REPEAT_DELAY;
++ }
++
++ return 0;
++ }
++ st->rc_counter = 0;
+ *event = keymap[i].event;
+ *state = REMOTE_KEY_PRESSED;
+- st->rc_toggle=key[3-1];
++ st->rc_toggle = key[3-1];
++ d->last_event = keymap[i].event;
+ return 0;
+ }
+ }
+- err("Unknown remote controller key : %2X %2X",(int)key[3-2],(int)key[3-3]);
++ break;
+ }
++ }
++ err("Unknown remote controller key: %2X %2X %2X %2X", (int) key[3-2], (int) key[3-3], (int) key[3-1], (int) key[3]);
++ d->last_event = 0;
+ return 0;
+ }
--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;
+@@ -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);
--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 *);
+- dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, &dib7070p_dib7000p_config);
++ dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
++ &dib7070p_dib7000p_config);
- /* 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 *);
+- 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;
+ }
- /* 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 *);
+@@ -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) },
-
-+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
+- { 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);
--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));
+@@ -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[] = {
+ },
+ },
- nes_debug(NES_DBG_CM, "State : %u \n", core->state);
+- .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,
-@@ -395,7 +418,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
- }
+@@ -1090,7 +1305,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
+ },
+ },
- 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);
+- .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 },
++ },
+ },
- 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
+ .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 @@
*/
--int send_reset(struct nes_cm_node *cm_node)
-+static int send_reset(struct nes_cm_node *cm_node)
+ #include "dibusb.h"
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ static int dib3000mb_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
{
- 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)
+ 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)
{
- 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
+- 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 @@
*/
--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)
+ #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)
{
- int ret;
+- 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);
+ }
-@@ -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)
+ /* 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 sk_buff *skb, *new_skb;
+ 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 };
-@@ -820,7 +843,6 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
+ 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)
{
- unsigned long flags;
- u32 hashkey;
-- struct list_head *list_pos;
- struct list_head *hte;
- struct nes_cm_node *cm_node;
+ 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;
-@@ -835,8 +857,7 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
+ 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 *);
- /* 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)
+-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)
{
- unsigned long flags;
-- struct list_head *listen_list;
- struct nes_cm_listener *listen_node;
+- int ret;
++ int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
++ adap->dev->owner, &adap->dev->udev->dev,
++ adapter_nums);
- /* 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;
+- 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
-@@ -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)
+ /* 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;
}
-@@ -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)
+
+-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;
- struct sk_buff *skb;
-@@ -1761,7 +1777,7 @@ int mini_cm_reject(struct nes_cm_core *cm_core,
- /**
- * mini_cm_close
+
+@@ -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 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 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)
{
- int ret = 0;
+ 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;
-@@ -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)
+- 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)
{
- 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)
+@@ -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,
{
- int i;
+ struct gp8psk_fe_state *st = fe->demodulator_priv;
-@@ -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;
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
-- atomic_set(&cm_core->session_id, 0);
- atomic_set(&cm_core->events_posted, 0);
+ 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;
- /* 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);
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
-@@ -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)
+ /* 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)
{
- 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,try = 0;
+@@ -190,7 +192,8 @@ static int gp8psk_usb_probe(struct usb_interface *intf,
{
- int ret = 0;
+ 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);
-@@ -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);
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid);
-@@ -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)
+ 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)
{
- 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);
+- deb("%s\n",__FUNCTION__);
++ deb("%s\n",__func__);
- 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;
- }
+ 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)
-@@ -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)
+ static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
{
- u64 u64temp;
- struct nes_qp *nesqp;
-@@ -2864,7 +2879,7 @@ void cm_event_connected(struct nes_cm_event *event)
+- deb("%s\n",__FUNCTION__);
++ deb("%s\n",__func__);
- 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 );
+ 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)
-@@ -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)
+ static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
{
- 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);
+- deb("%s\n",__FUNCTION__);
++ deb("%s\n",__func__);
-@@ -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)
+ 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)
{
- 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)
+- 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)
{
- 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);
+- deb("%s\n",__FUNCTION__);
++ deb("%s\n",__func__);
- 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)
+ 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)
{
- 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 {
+- deb("%s\n",__FUNCTION__);
++ deb("%s\n",__func__);
- 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 {
+ 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
+ */
- /* per connection node and node state information */
- struct nes_cm_node {
-- u64 session_id;
- u32 hashkey;
+- 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;
+ }
- nes_addr_t loc_addr, rem_addr;
-@@ -327,7 +325,6 @@ struct nes_cm_event {
+- 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;
+ }
- struct nes_cm_core {
- enum nes_cm_node_state state;
-- atomic_t session_id;
+ /* 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;
+ }
- 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);
- };
+- 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);
--
--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);
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define deb_rc(args...) dprintk(debug,0x01,args)
+ #define deb_ee(args...) dprintk(debug,0x02,args)
- 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);
+@@ -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);
+ }
- 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);
+ /* 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);
--/* 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 @@
++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;
+ }
- #include "nes.h"
+- 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);
--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;
++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,
+ };
- #include "nes_cm.h"
+ static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap)
+@@ -176,17 +179,25 @@ static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap)
-+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);
+ /* DVB USB Driver stuff */
+ static struct dvb_usb_device_properties ttusb2_properties;
++static struct dvb_usb_device_properties ttusb2_properties_s2400;
- #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;
+ 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;
+ }
- 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;
+ 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);
- 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;
+@@ -242,6 +253,54 @@ static struct dvb_usb_device_properties ttusb2_properties = {
}
-- 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)
++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)
{
- 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)
+ 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)
{
- 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)
+- 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)
{
- u32 u32temp;
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ vp702x_fe_refresh_state(st);
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
-@@ -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)
+ 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)
{
- 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)
+- 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)
{
- 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)
+ 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)
{
- // 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)
+- 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)
{
- 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");
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
+ return 0;
+ }
- } 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)
+@@ -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,
--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)
+ static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
{
- struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq);
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
+ return 0;
+ }
-@@ -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)
+@@ -238,7 +238,7 @@ static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
- 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;
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ u8 ibuf[10];
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
--
--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)
+ st->tone_mode = tone;
- 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)
+@@ -263,7 +263,7 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
{
- 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;
- }
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ u8 ibuf[10];
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
--
--/**
-- * 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__);
+ st->voltage = voltage;
- return cqp_request;
+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);
}
-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);
+ 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);
+ }
- /**
- * 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;
+ static struct usb_device_id vp7045_usb_table [] = {
+diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
+index 9ad86ce..6d23846 100644
+--- a/drivers/media/dvb/frontends/Kconfig
++++ b/drivers/media/dvb/frontends/Kconfig
+@@ -15,22 +15,36 @@ config DVB_FE_CUSTOMISE
+ comment "DVB-S (satellite) frontends"
+ depends on DVB_CORE
- 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); */
+-config DVB_STV0299
+- tristate "ST STV0299 based"
++config DVB_CX24110
++ tristate "Conexant CX24110 based"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A DVB-S tuner module. Say Y when you want to support this frontend.
-- 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; */
+-config DVB_CX24110
+- tristate "Conexant CX24110 based"
++config DVB_CX24123
++ tristate "Conexant CX24123 based"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A DVB-S tuner module. Say Y when you want to support this frontend.
-+ if (init_attr->create_flags)
-+ return ERR_PTR(-EINVAL);
+-config DVB_CX24123
+- tristate "Conexant CX24123 based"
++config DVB_MT312
++ tristate "Zarlink VP310/MT312 based"
++ depends on DVB_CORE && I2C
++ default m if DVB_FE_CUSTOMISE
++ help
++ A DVB-S tuner module. Say Y when you want to support this frontend.
+
- 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);
++config DVB_S5H1420
++ tristate "Samsung S5H1420 based"
++ depends on DVB_CORE && I2C
++ default m if DVB_FE_CUSTOMISE
++ help
++ A DVB-S tuner module. Say Y when you want to support this frontend.
++
++config DVB_STV0299
++ tristate "ST STV0299 based"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+@@ -43,8 +57,8 @@ config DVB_TDA8083
+ help
+ A DVB-S tuner module. Say Y when you want to support this frontend.
- 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;
+-config DVB_MT312
+- tristate "Zarlink VP310/MT312 based"
++config DVB_TDA10086
++ tristate "Philips TDA10086 based"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+@@ -57,19 +71,26 @@ config DVB_VES1X93
+ help
+ A DVB-S tuner module. Say Y when you want to support this frontend.
- 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;
+-config DVB_S5H1420
+- tristate "Samsung S5H1420 based"
++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
+ help
+ A DVB-S tuner module. Say Y when you want to support this frontend.
- 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");
- }
+-config DVB_TDA10086
+- tristate "Philips TDA10086 based"
++config DVB_TDA826X
++ tristate "Philips TDA826X silicon tuner"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+- A DVB-S tuner module. Say Y when you want to support this frontend.
++ A DVB-S silicon tuner module. Say Y when you want to support this tuner.
++
++config DVB_TUA6100
++ tristate "Infineon TUA6100 PLL"
++ depends on DVB_CORE && I2C
++ default m if DVB_FE_CUSTOMISE
++ help
++ A DVB-S PLL chip.
+ comment "DVB-T (terrestrial) frontends"
+ depends on DVB_CORE
+@@ -188,6 +209,14 @@ config DVB_DIB7000P
+ A DVB-T tuner module. Designed for mobile usage. Say Y when you want
+ to support this frontend.
--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);
++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
--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
- };
+@@ -291,65 +320,32 @@ config DVB_S5H1409
+ 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
+-
+-config DVB_PLL
+- tristate "Generic I2C PLL based tuners"
++config DVB_AU8522
++ tristate "Auvitek AU8522 based"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+- This module drives a number of tuners based on PLL chips with a
+- common I2C interface. Say Y when you want to support these tuners.
+-
+-config DVB_TDA826X
+- tristate "Philips TDA826X silicon tuner"
+- depends on DVB_CORE && I2C
+- default m if DVB_FE_CUSTOMISE
+- help
+- A DVB-S silicon tuner module. Say Y when you want to support this tuner.
++ An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
++ to support this frontend.
-@@ -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;
+-config DVB_TDA827X
+- tristate "Philips TDA827X silicon tuner"
++config DVB_S5H1411
++ tristate "Samsung S5H1411 based"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+- A DVB-T silicon tuner module. Say Y when you want to support this tuner.
++ An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
++ to support this frontend.
-- 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;
+-config DVB_TDA18271
+- tristate "NXP TDA18271 silicon tuner"
+- depends on I2C
+- default m if DVB_FE_CUSTOMISE
+- help
+- A silicon tuner module. Say Y when you want to support this tuner.
++comment "Digital terrestrial only tuners/PLL"
++ depends on DVB_CORE
+
+-config DVB_TUNER_QT1010
+- tristate "Quantek QT1010 silicon tuner"
++config DVB_PLL
++ tristate "Generic I2C PLL based tuners"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+- A driver for the silicon tuner QT1010 from Quantek.
+-
+-config DVB_TUNER_MT2060
+- tristate "Microtune MT2060 silicon IF tuner"
+- depends on I2C
+- default m if DVB_FE_CUSTOMISE
+- help
+- A driver for the silicon IF tuner MT2060 from Microtune.
+-
+-config DVB_TUNER_MT2266
+- tristate "Microtune MT2266 silicon tuner"
+- depends on I2C
+- default m if DVB_FE_CUSTOMISE
+- help
+- A driver for the silicon baseband tuner MT2266 from Microtune.
+-
+-config DVB_TUNER_MT2131
+- tristate "Microtune MT2131 silicon tuner"
+- depends on I2C
+- default m if DVB_FE_CUSTOMISE
+- help
+- A driver for the silicon baseband tuner MT2131 from Microtune.
++ This module drives a number of tuners based on PLL chips with a
++ common I2C interface. Say Y when you want to support these tuners.
+
+ config DVB_TUNER_DIB0070
+ tristate "DiBcom DiB0070 silicon base-band tuner"
+@@ -360,16 +356,7 @@ config DVB_TUNER_DIB0070
+ This device is only used inside a SiP called togther with a
+ demodulator for now.
-- if (nesibdev == NULL)
-- return;
+-config DVB_TUNER_XC5000
+- tristate "Xceive XC5000 silicon tuner"
+- depends on I2C
+- default m if DVB_FE_CUSTOMISE
+- help
+- A driver for the silicon tuner XC5000 from Xceive.
+- This device is only used inside a SiP called togther with a
+- demodulator for now.
-
-- 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]);
- }
+-comment "Miscellaneous devices"
++comment "SEC control devices for DVB-S"
+ depends on DVB_CORE
- 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
+ config DVB_LNBP21
+@@ -379,18 +366,18 @@ config DVB_LNBP21
+ help
+ An SEC control chip.
-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,
+-config DVB_ISL6421
+- tristate "ISL6421 SEC controller"
++config DVB_ISL6405
++ tristate "ISL6405 SEC controller"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ An SEC control chip.
- IPOIB_MAX_BACKOFF_SECONDS = 16,
+-config DVB_TUA6100
+- tristate "TUA6100 PLL"
++config DVB_ISL6421
++ tristate "ISL6421 SEC controller"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+- A DVBS PLL chip.
++ An SEC control chip.
-@@ -241,6 +242,11 @@ struct ipoib_cm_dev_priv {
- int num_frags;
- };
+ endmenu
+diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
+index 16bd107..a89dc0f 100644
+--- a/drivers/media/dvb/frontends/Makefile
++++ b/drivers/media/dvb/frontends/Makefile
+@@ -3,9 +3,7 @@
+ #
-+struct ipoib_ethtool_st {
-+ u16 coalesce_usecs;
-+ u16 max_coalesced_frames;
+ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
+-EXTRA_CFLAGS += -Idrivers/media/video/
+-
+-tda18271-objs := tda18271-tables.o tda18271-common.o tda18271-fe.o
++EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+
+ obj-$(CONFIG_DVB_PLL) += dvb-pll.o
+ obj-$(CONFIG_DVB_STV0299) += stv0299.o
+@@ -38,16 +36,14 @@ 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
+-obj-$(CONFIG_DVB_TDA827X) += tda827x.o
+-obj-$(CONFIG_DVB_TDA18271) += tda18271.o
+-obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
+-obj-$(CONFIG_DVB_TUNER_MT2266) += mt2266.o
+ obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o
+-obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o
+ obj-$(CONFIG_DVB_TUA6100) += tua6100.o
+-obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131.o
+ obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
+-obj-$(CONFIG_DVB_TUNER_XC5000) += xc5000.o
++obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
++obj-$(CONFIG_DVB_AU8522) += au8522.o
++obj-$(CONFIG_DVB_TDA10048) += tda10048.o
++obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
+diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c
+new file mode 100644
+index 0000000..084a280
+--- /dev/null
++++ b/drivers/media/dvb/frontends/au8522.c
+@@ -0,0 +1,692 @@
++/*
++ Auvitek AU8522 QAM/8VSB demodulator driver
++
++ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include "dvb_frontend.h"
++#include "dvb-pll.h"
++#include "au8522.h"
++
++struct au8522_state {
++
++ struct i2c_adapter *i2c;
++
++ /* configuration settings */
++ const struct au8522_config *config;
++
++ struct dvb_frontend frontend;
++
++ u32 current_frequency;
++ fe_modulation_t current_modulation;
++
++};
++
++static int debug;
++
++#define dprintk(arg...) do { \
++ if (debug) \
++ printk(arg); \
++ } while (0)
++
++/* 16 bit registers, 8 bit values */
++static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
++{
++ int ret;
++ u8 buf [] = { reg >> 8, reg & 0xff, data };
++
++ struct i2c_msg msg = { .addr = state->config->demod_address,
++ .flags = 0, .buf = buf, .len = 3 };
++
++ ret = i2c_transfer(state->i2c, &msg, 1);
++
++ if (ret != 1)
++ printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
++ "ret == %i)\n", __func__, reg, data, ret);
++
++ return (ret != 1) ? -1 : 0;
++}
++
++static u8 au8522_readreg(struct au8522_state *state, u16 reg)
++{
++ int ret;
++ u8 b0 [] = { reg >> 8, reg & 0xff };
++ u8 b1 [] = { 0 };
++
++ struct i2c_msg msg [] = {
++ { .addr = state->config->demod_address, .flags = 0,
++ .buf = b0, .len = 2 },
++ { .addr = state->config->demod_address, .flags = I2C_M_RD,
++ .buf = b1, .len = 1 } };
++
++ ret = i2c_transfer(state->i2c, msg, 2);
++
++ if (ret != 2)
++ printk(KERN_ERR "%s: readreg error (ret == %i)\n",
++ __func__, ret);
++ return b1[0];
++}
++
++static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
++{
++ struct au8522_state *state = fe->demodulator_priv;
++
++ dprintk("%s(%d)\n", __func__, enable);
++
++ if (enable)
++ return au8522_writereg(state, 0x106, 1);
++ else
++ return au8522_writereg(state, 0x106, 0);
++}
++
++struct mse2snr_tab {
++ u16 val;
++ u16 data;
++};
++
++/* VSB SNR lookup table */
++static struct mse2snr_tab vsb_mse2snr_tab[] = {
++ { 0, 270 },
++ { 2, 250 },
++ { 3, 240 },
++ { 5, 230 },
++ { 7, 220 },
++ { 9, 210 },
++ { 12, 200 },
++ { 13, 195 },
++ { 15, 190 },
++ { 17, 185 },
++ { 19, 180 },
++ { 21, 175 },
++ { 24, 170 },
++ { 27, 165 },
++ { 31, 160 },
++ { 32, 158 },
++ { 33, 156 },
++ { 36, 152 },
++ { 37, 150 },
++ { 39, 148 },
++ { 40, 146 },
++ { 41, 144 },
++ { 43, 142 },
++ { 44, 140 },
++ { 48, 135 },
++ { 50, 130 },
++ { 43, 142 },
++ { 53, 125 },
++ { 56, 120 },
++ { 256, 115 },
++};
++
++/* QAM64 SNR lookup table */
++static struct mse2snr_tab qam64_mse2snr_tab[] = {
++ { 15, 0 },
++ { 16, 290 },
++ { 17, 288 },
++ { 18, 286 },
++ { 19, 284 },
++ { 20, 282 },
++ { 21, 281 },
++ { 22, 279 },
++ { 23, 277 },
++ { 24, 275 },
++ { 25, 273 },
++ { 26, 271 },
++ { 27, 269 },
++ { 28, 268 },
++ { 29, 266 },
++ { 30, 264 },
++ { 31, 262 },
++ { 32, 260 },
++ { 33, 259 },
++ { 34, 258 },
++ { 35, 256 },
++ { 36, 255 },
++ { 37, 254 },
++ { 38, 252 },
++ { 39, 251 },
++ { 40, 250 },
++ { 41, 249 },
++ { 42, 248 },
++ { 43, 246 },
++ { 44, 245 },
++ { 45, 244 },
++ { 46, 242 },
++ { 47, 241 },
++ { 48, 240 },
++ { 50, 239 },
++ { 51, 238 },
++ { 53, 237 },
++ { 54, 236 },
++ { 56, 235 },
++ { 57, 234 },
++ { 59, 233 },
++ { 60, 232 },
++ { 62, 231 },
++ { 63, 230 },
++ { 65, 229 },
++ { 67, 228 },
++ { 68, 227 },
++ { 70, 226 },
++ { 71, 225 },
++ { 73, 224 },
++ { 74, 223 },
++ { 76, 222 },
++ { 78, 221 },
++ { 80, 220 },
++ { 82, 219 },
++ { 85, 218 },
++ { 88, 217 },
++ { 90, 216 },
++ { 92, 215 },
++ { 93, 214 },
++ { 94, 212 },
++ { 95, 211 },
++ { 97, 210 },
++ { 99, 209 },
++ { 101, 208 },
++ { 102, 207 },
++ { 104, 206 },
++ { 107, 205 },
++ { 111, 204 },
++ { 114, 203 },
++ { 118, 202 },
++ { 122, 201 },
++ { 125, 200 },
++ { 128, 199 },
++ { 130, 198 },
++ { 132, 197 },
++ { 256, 190 },
++};
++
++/* QAM256 SNR lookup table */
++static struct mse2snr_tab qam256_mse2snr_tab[] = {
++ { 16, 0 },
++ { 17, 400 },
++ { 18, 398 },
++ { 19, 396 },
++ { 20, 394 },
++ { 21, 392 },
++ { 22, 390 },
++ { 23, 388 },
++ { 24, 386 },
++ { 25, 384 },
++ { 26, 382 },
++ { 27, 380 },
++ { 28, 379 },
++ { 29, 378 },
++ { 30, 377 },
++ { 31, 376 },
++ { 32, 375 },
++ { 33, 374 },
++ { 34, 373 },
++ { 35, 372 },
++ { 36, 371 },
++ { 37, 370 },
++ { 38, 362 },
++ { 39, 354 },
++ { 40, 346 },
++ { 41, 338 },
++ { 42, 330 },
++ { 43, 328 },
++ { 44, 326 },
++ { 45, 324 },
++ { 46, 322 },
++ { 47, 320 },
++ { 48, 319 },
++ { 49, 318 },
++ { 50, 317 },
++ { 51, 316 },
++ { 52, 315 },
++ { 53, 314 },
++ { 54, 313 },
++ { 55, 312 },
++ { 56, 311 },
++ { 57, 310 },
++ { 58, 308 },
++ { 59, 306 },
++ { 60, 304 },
++ { 61, 302 },
++ { 62, 300 },
++ { 63, 298 },
++ { 65, 295 },
++ { 68, 294 },
++ { 70, 293 },
++ { 73, 292 },
++ { 76, 291 },
++ { 78, 290 },
++ { 79, 289 },
++ { 81, 288 },
++ { 82, 287 },
++ { 83, 286 },
++ { 84, 285 },
++ { 85, 284 },
++ { 86, 283 },
++ { 88, 282 },
++ { 89, 281 },
++ { 256, 280 },
++};
++
++static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse,
++ u16 *snr)
++{
++ int i, ret = -EINVAL;
++ dprintk("%s()\n", __func__);
++
++ for (i = 0; i < sz; i++) {
++ if (mse < tab[i].val) {
++ *snr = tab[i].data;
++ ret = 0;
++ break;
++ }
++ }
++ dprintk("%s() snr=%d\n", __func__, *snr);
++ return ret;
++}
++
++/* VSB Modulation table */
++static struct {
++ u16 reg;
++ u16 data;
++} VSB_mod_tab[] = {
++ { 0x8090, 0x84 },
++ { 0x4092, 0x11 },
++ { 0x2005, 0x00 },
++ { 0x8091, 0x80 },
++ { 0x80a3, 0x0c },
++ { 0x80a4, 0xe8 },
++ { 0x8081, 0xc4 },
++ { 0x80a5, 0x40 },
++ { 0x80a7, 0x40 },
++ { 0x80a6, 0x67 },
++ { 0x8262, 0x20 },
++ { 0x821c, 0x30 },
++ { 0x80d8, 0x1a },
++ { 0x8227, 0xa0 },
++ { 0x8121, 0xff },
++ { 0x80a8, 0xf0 },
++ { 0x80a9, 0x05 },
++ { 0x80aa, 0x77 },
++ { 0x80ab, 0xf0 },
++ { 0x80ac, 0x05 },
++ { 0x80ad, 0x77 },
++ { 0x80ae, 0x41 },
++ { 0x80af, 0x66 },
++ { 0x821b, 0xcc },
++ { 0x821d, 0x80 },
++ { 0x80b5, 0xfb },
++ { 0x80b6, 0x8e },
++ { 0x80b7, 0x39 },
++ { 0x80a4, 0xe8 },
++ { 0x8231, 0x13 },
++};
++
++/* QAM Modulation table */
++static struct {
++ u16 reg;
++ u16 data;
++} QAM_mod_tab[] = {
++ { 0x80a3, 0x09 },
++ { 0x80a4, 0x00 },
++ { 0x8081, 0xc4 },
++ { 0x80a5, 0x40 },
++ { 0x80b5, 0xfb },
++ { 0x80b6, 0x8e },
++ { 0x80b7, 0x39 },
++ { 0x80aa, 0x77 },
++ { 0x80ad, 0x77 },
++ { 0x80a6, 0x67 },
++ { 0x8262, 0x20 },
++ { 0x821c, 0x30 },
++ { 0x80b8, 0x3e },
++ { 0x80b9, 0xf0 },
++ { 0x80ba, 0x01 },
++ { 0x80bb, 0x18 },
++ { 0x80bc, 0x50 },
++ { 0x80bd, 0x00 },
++ { 0x80be, 0xea },
++ { 0x80bf, 0xef },
++ { 0x80c0, 0xfc },
++ { 0x80c1, 0xbd },
++ { 0x80c2, 0x1f },
++ { 0x80c3, 0xfc },
++ { 0x80c4, 0xdd },
++ { 0x80c5, 0xaf },
++ { 0x80c6, 0x00 },
++ { 0x80c7, 0x38 },
++ { 0x80c8, 0x30 },
++ { 0x80c9, 0x05 },
++ { 0x80ca, 0x4a },
++ { 0x80cb, 0xd0 },
++ { 0x80cc, 0x01 },
++ { 0x80cd, 0xd9 },
++ { 0x80ce, 0x6f },
++ { 0x80cf, 0xf9 },
++ { 0x80d0, 0x70 },
++ { 0x80d1, 0xdf },
++ { 0x80d2, 0xf7 },
++ { 0x80d3, 0xc2 },
++ { 0x80d4, 0xdf },
++ { 0x80d5, 0x02 },
++ { 0x80d6, 0x9a },
++ { 0x80d7, 0xd0 },
++ { 0x8250, 0x0d },
++ { 0x8251, 0xcd },
++ { 0x8252, 0xe0 },
++ { 0x8253, 0x05 },
++ { 0x8254, 0xa7 },
++ { 0x8255, 0xff },
++ { 0x8256, 0xed },
++ { 0x8257, 0x5b },
++ { 0x8258, 0xae },
++ { 0x8259, 0xe6 },
++ { 0x825a, 0x3d },
++ { 0x825b, 0x0f },
++ { 0x825c, 0x0d },
++ { 0x825d, 0xea },
++ { 0x825e, 0xf2 },
++ { 0x825f, 0x51 },
++ { 0x8260, 0xf5 },
++ { 0x8261, 0x06 },
++ { 0x821a, 0x00 },
++ { 0x8546, 0x40 },
++ { 0x8210, 0x26 },
++ { 0x8211, 0xf6 },
++ { 0x8212, 0x84 },
++ { 0x8213, 0x02 },
++ { 0x8502, 0x01 },
++ { 0x8121, 0x04 },
++ { 0x8122, 0x04 },
++ { 0x852e, 0x10 },
++ { 0x80a4, 0xca },
++ { 0x80a7, 0x40 },
++ { 0x8526, 0x01 },
+};
+
- /*
- * 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);
++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;
+
- #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");
++ 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;
++ }
+
-+ dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO);
-+ priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;
++ 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);
+
- 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);
++ fe->ops.tuner_ops.get_status(fe, &tuner_status);
+
-+ 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;
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
++ if (tuner_status)
++ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
++ break;
++ }
+
- 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.
-+ */
++ dprintk("%s() status 0x%08x\n", __func__, *status);
+
-+#include <linux/kernel.h>
-+#include <linux/ethtool.h>
-+#include <linux/netdevice.h>
++ return 0;
++}
+
-+#include "ipoib.h"
++static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
++{
++ struct au8522_state *state = fe->demodulator_priv;
++ int ret = -EINVAL;
+
-+static void ipoib_get_drvinfo(struct net_device *netdev,
-+ struct ethtool_drvinfo *drvinfo)
++ 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)
+{
-+ strncpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver) - 1);
++ return au8522_read_snr(fe, signal_strength);
+}
+
-+static int ipoib_get_coalesce(struct net_device *dev,
-+ struct ethtool_coalesce *coal)
++static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
-+ struct ipoib_dev_priv *priv = netdev_priv(dev);
++ struct au8522_state *state = fe->demodulator_priv;
+
-+ 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;
++ if (state->current_modulation == VSB_8)
++ *ucblocks = au8522_readreg(state, 0x4087);
++ else
++ *ucblocks = au8522_readreg(state, 0x4543);
+
+ return 0;
+}
+
-+static int ipoib_set_coalesce(struct net_device *dev,
-+ struct ethtool_coalesce *coal)
++static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
-+ struct ipoib_dev_priv *priv = netdev_priv(dev);
-+ int ret;
++ return au8522_read_ucblocks(fe, ber);
++}
+
-+ /*
-+ * 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;
++static int au8522_get_frontend(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *p)
++{
++ struct au8522_state *state = fe->demodulator_priv;
+
-+ 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;
-+ }
++ p->frequency = state->current_frequency;
++ p->u.vsb.modulation = state->current_modulation;
+
-+ 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 int au8522_get_tune_settings(struct dvb_frontend *fe,
++ struct dvb_frontend_tune_settings *tune)
++{
++ tune->min_delay_ms = 1000;
+ 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,
-+};
++static void au8522_release(struct dvb_frontend *fe)
++{
++ struct au8522_state *state = fe->demodulator_priv;
++ kfree(state);
++}
+
-+void ipoib_set_ethtool_ops(struct net_device *dev)
++static struct dvb_frontend_ops au8522_ops;
++
++struct dvb_frontend *au8522_attach(const struct au8522_config *config,
++ struct i2c_adapter *i2c)
+{
-+ SET_ETHTOOL_OPS(dev, &ipoib_ethtool_ops);
++ 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;
+}
-diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
-index 08c4396..0205eb7 100644
---- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
-+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
-@@ -39,6 +39,8 @@
- #include <linux/dma-mapping.h>
-
- #include <rdma/ib_cache.h>
-+#include <linux/ip.h>
-+#include <linux/tcp.h>
-
- #include "ipoib.h"
-
-@@ -231,6 +233,10 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
- skb->dev = dev;
- /* XXX get correct PACKET_ type here */
- skb->pkt_type = PACKET_HOST;
++EXPORT_SYMBOL(au8522_attach);
+
-+ if (test_bit(IPOIB_FLAG_CSUM, &priv->flags) && likely(wc->csum_ok))
-+ skb->ip_summed = CHECKSUM_UNNECESSARY;
++static struct dvb_frontend_ops au8522_ops = {
+
- 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;
++ .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
++ },
+
-+ 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);
- }
++ .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,
++};
+
-+ if (off)
-+ ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE);
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
- 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;
++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
+
-+ 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;
++ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
+
- 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;
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the 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 (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;
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
+
- 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);
++ You 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.
+
- 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;
++#ifndef __AU8522_H__
++#define __AU8522_H__
+
-+ kfree(device_attr);
++#include <linux/dvb/frontend.h>
+
-+ 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;
-+ }
++struct au8522_config {
++ /* the demodulator's i2c address */
++ u8 demod_address;
+
- /*
- * 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;
++ /* Return lock status based on tuner lock, or demod lock */
++#define AU8522_TUNERLOCKING 0
++#define AU8522_DEMODLOCKING 1
++ u8 status_mode;
++};
+
- 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 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 */
+
- 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);
- }
++#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) {
- 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;
+ 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;
}
-- 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);
+@@ -110,7 +110,7 @@ static int bcm3510_readbytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 l
-@@ -1456,9 +1458,10 @@ static int srp_reset_host(struct scsi_cmnd *scmnd)
- return ret;
+ 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 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));
+ 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
+ };
- 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));
- }
+@@ -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;
--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));
+- 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 (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));
- }
+ 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 };
--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));
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- 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));
- }
+ ret = i2c_transfer (state->i2c, &msg, 1);
--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 (ret != 1)
+ printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+- __FUNCTION__, reg, data, ret);
++ __func__, reg, data, ret);
- 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));
+ 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 } };
--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));
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- 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]));
- }
+ ret = i2c_transfer (state->i2c, msg, 2);
--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)
+@@ -105,7 +105,7 @@ static int cx22700_set_inversion (struct cx22700_state* state, int inversion)
{
-- struct srp_target_port *target = host_to_target(class_to_shost(cdev));
-+ struct srp_target_port *target = host_to_target(class_to_shost(dev));
+ u8 val;
- 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]));
- }
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
--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));
+ 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;
- 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);
- }
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
--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));
+ 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;
- return sprintf(buf, "%d\n", target->srp_host->port);
- }
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
--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)
+ 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)
{
-- 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);
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
}
-
--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
+ #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;
};
-@@ -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;
+-static int debug = 0;
++static int debug;
+ #define dprintk if (debug) printk
- 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;
- }
+ /* Register values to initialise the demod */
+@@ -90,7 +90,7 @@ static int cx22702_writereg (struct cx22702_state* state, u8 reg, u8 data)
--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);
+ if (ret != 1)
+ printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+- __FUNCTION__, reg, data, ret);
++ __func__, reg, data, ret);
- complete(&host->released);
+ 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);
- static struct class srp_class = {
- .name = "infiniband_srp",
-- .release = srp_release_class_dev
-+ .dev_release = srp_release_dev
- };
+ if (ret != 2)
+- printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
++ printk("%s: readreg error (ret == %i)\n", __func__, ret);
- /*
-@@ -1835,11 +1846,12 @@ out:
- return ret;
+ return b1[0];
}
-
--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)
+@@ -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 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);
+ 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;
+ }
--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);
+@@ -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;
+ }
-- return sprintf(buf, "%s\n", host->dev->dev->name);
-+ return sprintf(buf, "%s\n", host->srp_dev->dev->name);
- }
+@@ -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);
--static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
-+static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
+ dprintk ("%s: status demod=0x%02x agc=0x%02x\n"
+- ,__FUNCTION__,reg0A,reg23);
++ ,__func__,reg0A,reg23);
--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)
+ 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)
{
-- 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);
+- 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)
--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;
+ 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;
+ }
- return host;
+@@ -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;
- err_class:
-- class_device_unregister(&host->class_dev);
-+ device_unregister(&host->dev);
+- 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;
- 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);
+- dprintk("%s: init chip\n", __FUNCTION__);
++ dprintk("%s: init chip\n", __func__);
- 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)
+ 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)
{
- int ret;
-
-+ if (srp_sg_tablesize > 255) {
-+ printk(KERN_WARNING PFX "Clamping srp_sg_tablesize to 255\n");
-+ srp_sg_tablesize = 255;
-+ }
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_CX24110
+diff --git a/drivers/media/dvb/frontends/cx24113.h b/drivers/media/dvb/frontends/cx24113.h
+new file mode 100644
+index 0000000..5ab3dd1
+--- /dev/null
++++ b/drivers/media/dvb/frontends/cx24113.h
+@@ -0,0 +1,48 @@
++/*
++ * Driver for Conexant CX24113/CX24128 Tuner (Satelite)
++ *
++ * Copyright (C) 2007-8 Patrick Boettcher <pb at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ */
+
- 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.
++#ifndef CX24113_H
++#define CX24113_H
+
- 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
++struct dvb_frontend;
+
-+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.
++struct cx24113_config {
++ u8 i2c_addr; /* 0x14 or 0x54 */
+
-+ To compile this driver as a module, choose M here: the
-+ module will be called zhenhua.
++ u32 xtal_khz;
++};
+
- 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 @@
++/* 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 @@
/*
-- * X-Box gamepad - v0.0.6
-+ * X-Box gamepad driver
- *
- * Copyright (c) 2002 Marko Friedemann <mfr at bmx-chemnitz.de>
- * 2004 Oliver Schwartz <Oliver.Schwartz at gmx.de>,
-@@ -68,6 +68,8 @@
- * - dance pads will map D-PAD to buttons, not axes
- * - pass the module paramater 'dpad_to_buttons' to force
- * the D-PAD to map to buttons if your pad is not detected
+- Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
+-
+- Copyright (C) 2005 Steven Toth <stoth at hauppauge.com>
+-
+- Support for KWorld DVB-S 100 by Vadim Catana <skystar at moldova.cc>
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2 of the License, or
+- (at your option) any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
+-
+- You should have received a copy of the GNU General Public License
+- along with this program; if not, write to the Free Software
+- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-*/
++ * Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
+ *
-+ * Later changes can be tracked in SCM.
- */
++ * Copyright (C) 2005 Steven Toth <stoth at hauppauge.com>
++ *
++ * Support for KWorld DVB-S 100 by Vadim Catana <skystar at moldova.cc>
++ *
++ * Support for CX24123/CX24113-NIM by Patrick Boettcher <pb at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
+ #include <linux/slab.h>
#include <linux/kernel.h>
-@@ -77,7 +79,6 @@
- #include <linux/module.h>
- #include <linux/usb/input.h>
-
--#define DRIVER_VERSION "v0.0.6"
- #define DRIVER_AUTHOR "Marko Friedemann <mfr at bmx-chemnitz.de>"
- #define DRIVER_DESC "X-Box pad driver"
-
-@@ -87,10 +88,12 @@
- but we map them to axes when possible to simplify things */
- #define MAP_DPAD_TO_BUTTONS 0
- #define MAP_DPAD_TO_AXES 1
--#define MAP_DPAD_UNKNOWN -1
-+#define MAP_DPAD_UNKNOWN 2
-
- #define XTYPE_XBOX 0
- #define XTYPE_XBOX360 1
-+#define XTYPE_XBOX360W 2
-+#define XTYPE_UNKNOWN 3
+@@ -32,9 +34,16 @@
- 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 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)
--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 */
- };
+ struct cx24123_state
+@@ -51,6 +60,10 @@ struct cx24123_state
+ u32 pllarg;
+ u32 FILTune;
-+/* original xbox controllers only */
-+static const signed short xpad_btn[] = {
-+ BTN_C, BTN_Z, /* "analog" buttons */
-+ -1 /* terminating entry */
-+};
++ struct i2c_adapter tuner_i2c_adapter;
+
- /* 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) }
++ u8 demod_rev;
+
- 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 */
- { }
+ /* 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 */
};
-@@ -188,10 +216,15 @@ struct usb_xpad {
- struct input_dev *dev; /* input device interface */
- struct usb_device *udev; /* usb device */
+-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;
-+ int pad_present;
-+
- struct urb *irq_in; /* urb for interrupt in report */
- unsigned char *idata; /* input data */
- dma_addr_t idata_dma;
+- 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); */
-+ 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)));
+ 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;
+ }
- /* 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)));
+ return 0;
+ }
- /* 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)));
+-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 }
+ };
- /* 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)));
+ ret = i2c_transfer(state->i2c, msg, 2);
- /* 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);
+ 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;
}
-+/*
-+ * 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]);
-+}
++#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 void xpad_irq_in(struct urb *urb)
+ static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
{
- struct usb_xpad *xpad = urb->context;
-- int retval;
-+ int retval, status;
+ u8 nom_reg = cx24123_readreg(state, 0x0e);
+@@ -274,17 +291,17 @@ static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_invers
-- switch (urb->status) {
-+ status = urb->status;
-+
-+ switch (status) {
- case 0:
- /* success */
+ 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;
-@@ -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;
+@@ -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;
}
-- 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;
+@@ -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));
-- 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;
- }
+- 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);
-@@ -399,6 +475,23 @@ exit:
- __FUNCTION__, retval);
+ return 0;
}
-+static void xpad_bulk_out(struct urb *urb)
++
++/*
++ * 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)
+{
-+ 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);
-+ }
++ 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 xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
+ static int cx24123_initfe(struct dvb_frontend* fe)
{
- 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;
+ struct cx24123_state *state = fe->demodulator_priv;
+ int i;
-@@ -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);
- }
+- dprintk("%s: init frontend\n",__FUNCTION__);
++ dprintk("init frontend\n");
-@@ -477,6 +571,9 @@ static int xpad_play_effect(struct input_dev *dev, void *data,
+ /* 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);
- static int xpad_init_ff(struct usb_xpad *xpad)
- {
-+ if (xpad->xtype != XTYPE_XBOX360)
-+ return 0;
++ if (state->config->dont_use_pll)
++ cx24123_repeater_mode(state, 1, 0);
+
- input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
+ return 0;
+ }
- 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)
+@@ -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 usb_xpad *xpad = input_get_drvdata(dev);
+ struct cx24123_state *state = fe->demodulator_priv;
+-
+ int sync = cx24123_readreg(state, 0x14);
+- int lock = cx24123_readreg(state, 0x20);
-+ /* URB was submitted in probe */
-+ if(xpad->xtype == XTYPE_XBOX360W)
-+ return 0;
+ *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;
++ }
+
- 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)
+ 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 usb_xpad *xpad = input_get_drvdata(dev);
+ struct cx24123_state *state = fe->demodulator_priv;
-- usb_kill_urb(xpad->irq_in);
-+ if(xpad->xtype != XTYPE_XBOX360W)
-+ usb_kill_urb(xpad->irq_in);
- xpad_stop_output(xpad);
- }
+@@ -813,23 +866,24 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
+ (cx24123_readreg(state, 0x1d) << 8 |
+ cx24123_readreg(state, 0x1e));
-@@ -632,7 +735,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
- goto fail1;
+- dprintk("%s: BER = %d\n",__FUNCTION__,*ber);
++ dprintk("BER = %d\n", *ber);
- xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN,
-- GFP_ATOMIC, &xpad->idata_dma);
-+ GFP_KERNEL, &xpad->idata_dma);
- if (!xpad->idata)
- goto fail1;
+ return 0;
+ }
-@@ -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);
+-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;
- /* 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;
+ *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);
- 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)
+-static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
++static int cx24123_read_snr(struct dvb_frontend *fe, u16 *snr)
{
- int result = usb_register(&xpad_driver);
- if (result == 0)
-- info(DRIVER_DESC ":" DRIVER_VERSION);
-+ info(DRIVER_DESC);
- return result;
+ 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;
}
-diff --git a/drivers/input/joystick/zhenhua.c b/drivers/input/joystick/zhenhua.c
-new file mode 100644
-index 0000000..b585312
---- /dev/null
-+++ b/drivers/input/joystick/zhenhua.c
-@@ -0,0 +1,243 @@
-+/*
-+ * derived from "twidjoy.c"
-+ *
-+ * Copyright (c) 2008 Martin Kebert
-+ * Copyright (c) 2001 Arndt Schoenewald
-+ * Copyright (c) 2000-2001 Vojtech Pavlik
-+ * Copyright (c) 2000 Mark Fletcher
-+ *
-+ */
-+
-+/*
-+ * Driver to use 4CH RC transmitter using Zhen Hua 5-byte protocol (Walkera Lama,
-+ * EasyCopter etc.) as a joystick under Linux.
-+ *
-+ * RC transmitters using Zhen Hua 5-byte protocol are cheap four channels
-+ * transmitters for control a RC planes or RC helicopters with possibility to
-+ * connect on a serial port.
-+ * Data coming from transmitter is in this order:
-+ * 1. byte = synchronisation byte
-+ * 2. byte = X axis
-+ * 3. byte = Y axis
-+ * 4. byte = RZ axis
-+ * 5. byte = Z axis
-+ * (and this is repeated)
-+ *
-+ * For questions or feedback regarding this driver module please contact:
-+ * Martin Kebert <gkmarty at gmail.com> - but I am not a C-programmer nor kernel
-+ * coder :-(
-+ */
-+
-+/*
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/input.h>
-+#include <linux/serio.h>
-+#include <linux/init.h>
-+
-+#define DRIVER_DESC "RC transmitter with 5-byte Zhen Hua protocol joystick driver"
-+
-+MODULE_DESCRIPTION(DRIVER_DESC);
-+MODULE_LICENSE("GPL");
-+
-+/*
-+ * Constants.
-+ */
-+
-+#define ZHENHUA_MAX_LENGTH 5
-+
-+/*
-+ * Zhen Hua data.
-+ */
-+
-+struct zhenhua {
-+ struct input_dev *dev;
-+ int idx;
-+ unsigned char data[ZHENHUA_MAX_LENGTH];
-+ char phys[32];
-+};
-+
-+
-+/* bits in all incoming bytes needs to be "reversed" */
-+static int zhenhua_bitreverse(int x)
-+{
-+ x = ((x & 0xaa) >> 1) | ((x & 0x55) << 1);
-+ x = ((x & 0xcc) >> 2) | ((x & 0x33) << 2);
-+ x = ((x & 0xf0) >> 4) | ((x & 0x0f) << 4);
-+ return x;
-+}
-+
-+/*
-+ * zhenhua_process_packet() decodes packets the driver receives from the
-+ * RC transmitter. It updates the data accordingly.
-+ */
-+
-+static void zhenhua_process_packet(struct zhenhua *zhenhua)
-+{
-+ struct input_dev *dev = zhenhua->dev;
-+ unsigned char *data = zhenhua->data;
-+
-+ input_report_abs(dev, ABS_Y, data[1]);
-+ input_report_abs(dev, ABS_X, data[2]);
-+ input_report_abs(dev, ABS_RZ, data[3]);
-+ input_report_abs(dev, ABS_Z, data[4]);
-+
-+ input_sync(dev);
-+}
-+
-+/*
-+ * zhenhua_interrupt() is called by the low level driver when characters
-+ * are ready for us. We then buffer them for further processing, or call the
-+ * packet processing routine.
-+ */
-+
-+static irqreturn_t zhenhua_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
-+{
-+ struct zhenhua *zhenhua = serio_get_drvdata(serio);
-+
-+ /* All Zhen Hua packets are 5 bytes. The fact that the first byte
-+ * is allways 0xf7 and all others are in range 0x32 - 0xc8 (50-200)
-+ * can be used to check and regain sync. */
-+
-+ if (data == 0xef)
-+ zhenhua->idx = 0; /* this byte starts a new packet */
-+ else if (zhenhua->idx == 0)
-+ return IRQ_HANDLED; /* wrong MSB -- ignore this byte */
-+
-+ if (zhenhua->idx < ZHENHUA_MAX_LENGTH)
-+ zhenhua->data[zhenhua->idx++] = zhenhua_bitreverse(data);
-+
-+ if (zhenhua->idx == ZHENHUA_MAX_LENGTH) {
-+ zhenhua_process_packet(zhenhua);
-+ zhenhua->idx = 0;
-+ }
-+
-+ return IRQ_HANDLED;
-+}
-+
-+/*
-+ * zhenhua_disconnect() is the opposite of zhenhua_connect()
-+ */
-+
-+static void zhenhua_disconnect(struct serio *serio)
-+{
-+ struct zhenhua *zhenhua = serio_get_drvdata(serio);
-+
-+ serio_close(serio);
-+ serio_set_drvdata(serio, NULL);
-+ input_unregister_device(zhenhua->dev);
-+ kfree(zhenhua);
-+}
-+
-+/*
-+ * zhenhua_connect() is the routine that is called when someone adds a
-+ * new serio device. It looks for the Twiddler, and if found, registers
-+ * it as an input device.
-+ */
-+
-+static int zhenhua_connect(struct serio *serio, struct serio_driver *drv)
-+{
-+ struct zhenhua *zhenhua;
-+ struct input_dev *input_dev;
-+ int err = -ENOMEM;
-+
-+ zhenhua = kzalloc(sizeof(struct zhenhua), GFP_KERNEL);
-+ input_dev = input_allocate_device();
-+ if (!zhenhua || !input_dev)
-+ goto fail1;
-+
-+ zhenhua->dev = input_dev;
-+ snprintf(zhenhua->phys, sizeof(zhenhua->phys), "%s/input0", serio->phys);
-+
-+ input_dev->name = "Zhen Hua 5-byte device";
-+ input_dev->phys = zhenhua->phys;
-+ input_dev->id.bustype = BUS_RS232;
-+ input_dev->id.vendor = SERIO_ZHENHUA;
-+ input_dev->id.product = 0x0001;
-+ input_dev->id.version = 0x0100;
-+ input_dev->dev.parent = &serio->dev;
-+
-+ input_dev->evbit[0] = BIT(EV_ABS);
-+ input_set_abs_params(input_dev, ABS_X, 50, 200, 0, 0);
-+ input_set_abs_params(input_dev, ABS_Y, 50, 200, 0, 0);
-+ input_set_abs_params(input_dev, ABS_Z, 50, 200, 0, 0);
-+ input_set_abs_params(input_dev, ABS_RZ, 50, 200, 0, 0);
-+
-+ serio_set_drvdata(serio, zhenhua);
-+
-+ err = serio_open(serio, drv);
-+ if (err)
-+ goto fail2;
-+
-+ err = input_register_device(zhenhua->dev);
-+ if (err)
-+ goto fail3;
-+
-+ return 0;
-+
-+ fail3: serio_close(serio);
-+ fail2: serio_set_drvdata(serio, NULL);
-+ fail1: input_free_device(input_dev);
-+ kfree(zhenhua);
-+ return err;
-+}
-+
-+/*
-+ * The serio driver structure.
-+ */
-+
-+static struct serio_device_id zhenhua_serio_ids[] = {
-+ {
-+ .type = SERIO_RS232,
-+ .proto = SERIO_ZHENHUA,
-+ .id = SERIO_ANY,
-+ .extra = SERIO_ANY,
-+ },
-+ { 0 }
-+};
-+
-+MODULE_DEVICE_TABLE(serio, zhenhua_serio_ids);
-+
-+static struct serio_driver zhenhua_drv = {
-+ .driver = {
-+ .name = "zhenhua",
-+ },
-+ .description = DRIVER_DESC,
-+ .id_table = zhenhua_serio_ids,
-+ .interrupt = zhenhua_interrupt,
-+ .connect = zhenhua_connect,
-+ .disconnect = zhenhua_disconnect,
-+};
-+
-+/*
-+ * The functions for inserting/removing us as a module.
-+ */
-+
-+static int __init zhenhua_init(void)
-+{
-+ return serio_register_driver(&zhenhua_drv);
-+}
-+
-+static void __exit zhenhua_exit(void)
-+{
-+ serio_unregister_driver(&zhenhua_drv);
-+}
+-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);
+
-+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.
++ 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...");
-+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.
+ /* 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);
+
-+ 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,
- },
- };
+@@ -872,14 +936,14 @@ static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
+ {
+ struct cx24123_state *state = fe->demodulator_priv;
-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)
+- dprintk("%s: get_frontend\n",__FUNCTION__);
++ dprintk("\n");
- bfin_write_KPAD_CTL(bfin_read_KPAD_CTL() | KPAD_EN);
+ 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)
-+ device_init_wakeup(&pdev->dev, 1);
-+
- printk(KERN_ERR DRV_NAME
- ": Blackfin BF54x Keypad registered IRQ %d\n", bf54x_kpad->irq);
+ 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;
+ }
-@@ -354,12 +356,40 @@ static int __devexit bfin_kpad_remove(struct platform_device *pdev)
- return 0;
+@@ -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);
}
-+#ifdef CONFIG_PM
-+static int bfin_kpad_suspend(struct platform_device *pdev, pm_message_t state)
++static int cx24123_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap,
++ struct i2c_msg msg[], int num)
+{
-+ struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
-+
-+ if (device_may_wakeup(&pdev->dev))
-+ enable_irq_wake(bf54x_kpad->irq);
-+
-+ return 0;
++ 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 int bfin_kpad_resume(struct platform_device *pdev)
++static u32 cx24123_tuner_i2c_func(struct i2c_adapter *adapter)
+{
-+ struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
++ return I2C_FUNC_I2C;
++}
+
-+ if (device_may_wakeup(&pdev->dev))
-+ disable_irq_wake(bf54x_kpad->irq);
++static struct i2c_algorithm cx24123_tuner_i2c_algo = {
++ .master_xfer = cx24123_tuner_i2c_tuner_xfer,
++ .functionality = cx24123_tuner_i2c_func,
++};
+
-+ return 0;
++struct i2c_adapter *
++ cx24123_get_tuner_i2c_adapter(struct dvb_frontend *fe)
++{
++ struct cx24123_state *state = fe->demodulator_priv;
++ return &state->tuner_i2c_adapter;
+}
-+#else
-+# define bfin_kpad_suspend NULL
-+# define bfin_kpad_resume NULL
-+#endif
++EXPORT_SYMBOL(cx24123_get_tuner_i2c_adapter);
+
- struct platform_driver bfin_kpad_device_driver = {
-- .probe = bfin_kpad_probe,
-- .remove = __devexit_p(bfin_kpad_remove),
- .driver = {
- .name = DRV_NAME,
-- }
-+ .owner = THIS_MODULE,
-+ },
-+ .probe = bfin_kpad_probe,
-+ .remove = __devexit_p(bfin_kpad_remove),
-+ .suspend = bfin_kpad_suspend,
-+ .resume = bfin_kpad_resume,
- };
-
- static int __init bfin_kpad_init(void)
-@@ -378,3 +408,4 @@ module_exit(bfin_kpad_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("Michael Hennerich <hennerich at blackfin.uclinux.org>");
- MODULE_DESCRIPTION("Keypad driver for BF54x Processors");
-+MODULE_ALIAS("platform:bf54x-keys");
-diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
-index 790fed3..29fbec6 100644
---- a/drivers/input/keyboard/corgikbd.c
-+++ b/drivers/input/keyboard/corgikbd.c
-@@ -23,6 +23,7 @@
- #include <asm/arch/corgi.h>
- #include <asm/arch/hardware.h>
- #include <asm/arch/pxa-regs.h>
-+#include <asm/arch/pxa2xx-gpio.h>
- #include <asm/hardware/scoop.h>
-
- #define KB_ROWS 8
-@@ -392,6 +393,7 @@ static struct platform_driver corgikbd_driver = {
- .resume = corgikbd_resume,
- .driver = {
- .name = "corgi-keyboard",
-+ .owner = THIS_MODULE,
- },
- };
+ static struct dvb_frontend_ops cx24123_ops;
-@@ -411,3 +413,4 @@ module_exit(corgikbd_exit);
- MODULE_AUTHOR("Richard Purdie <rpurdie at rpsys.net>");
- MODULE_DESCRIPTION("Corgi Keyboard Driver");
- MODULE_LICENSE("GPLv2");
-+MODULE_ALIAS("platform:corgi-keyboard");
-diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
-index 6a9ca4b..bbd00c3 100644
---- a/drivers/input/keyboard/gpio_keys.c
-+++ b/drivers/input/keyboard/gpio_keys.c
-@@ -43,10 +43,11 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
+ 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);
- input_event(input, type, button->code, !!state);
- input_sync(input);
-+ return IRQ_HANDLED;
- }
++ 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;
}
-- return IRQ_HANDLED;
-+ return IRQ_NONE;
- }
+ /* 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;
- 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,
+ /* 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;
}
- };
-
-@@ -232,3 +234,4 @@ module_exit(gpio_keys_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("Phil Blundell <pb at handhelds.org>");
- MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
-+MODULE_ALIAS("platform:gpio-keys");
-diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c
-index a23633a..9387da3 100644
---- a/drivers/input/keyboard/jornada680_kbd.c
-+++ b/drivers/input/keyboard/jornada680_kbd.c
-@@ -254,6 +254,7 @@ static int __devexit jornada680kbd_remove(struct platform_device *pdev)
- static struct platform_driver jornada680kbd_driver = {
- .driver = {
- .name = "jornada680_kbd",
-+ .owner = THIS_MODULE,
- },
- .probe = jornada680kbd_probe,
- .remove = __devexit_p(jornada680kbd_remove),
-@@ -275,3 +276,4 @@ module_exit(jornada680kbd_exit);
- MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson at gmail.com>");
- MODULE_DESCRIPTION("HP Jornada 620/660/680/690 Keyboard Driver");
- MODULE_LICENSE("GPLv2");
-+MODULE_ALIAS("platform:jornada680_kbd");
-diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c
-index 986f93c..a1164a0 100644
---- a/drivers/input/keyboard/jornada720_kbd.c
-+++ b/drivers/input/keyboard/jornada720_kbd.c
-@@ -162,9 +162,13 @@ static int __devexit jornada720_kbd_remove(struct platform_device *pdev)
- return 0;
- }
-+/* work with hotplug and coldplug */
-+MODULE_ALIAS("platform:jornada720_kbd");
+ /* create dvb_frontend */
+ memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+
- 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
++ /* 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;
- #define KB_DELAY 8
- #define SCAN_INTERVAL (HZ/10)
--#define LOCOMOKBD_PRESSED 1
+ 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).");
- struct locomokbd {
- unsigned char keycode[LOCOMOKBD_NUMKEYS];
- struct input_dev *input;
- char phys[32];
+-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");
-- struct locomo_dev *ldev;
- unsigned long base;
- spinlock_t lock;
+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
- struct timer_list timer;
-+ unsigned long suspend_jiffies;
-+ unsigned int count_cancel;
+ /* 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 *);
};
- /* 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)
+ #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)
{
-- 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);
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
}
-@@ -186,10 +206,11 @@ static irqreturn_t locomokbd_interrupt(int irq, void *dev_id)
- static void locomokbd_timer_callback(unsigned long data)
+ #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)
{
- struct locomokbd *locomokbd = (struct locomokbd *) data;
-+
- locomokbd_scankeyboard(locomokbd);
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
}
-
--static int locomokbd_probe(struct locomo_dev *dev)
-+static int __devinit locomokbd_probe(struct locomo_dev *dev)
+ #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)
{
- struct locomokbd *locomokbd;
- struct input_dev *input_dev;
-@@ -211,7 +232,6 @@ static int locomokbd_probe(struct locomo_dev *dev)
- goto err_free_mem;
- }
+- 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);
-- locomokbd->ldev = dev;
- locomo_set_drvdata(dev, locomokbd);
+ /* make this a config parameter */
+- dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO);
++ dib7000p_set_output_mode(state, state->cfg.output_mode);
+ return ret;
+ }
- 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;
+@@ -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;
-+ locomokbd->suspend_jiffies = jiffies;
++ /* 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;
+
- locomokbd->input = input_dev;
- strcpy(locomokbd->phys, "locomokbd/input0");
+ 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;
-@@ -233,9 +255,10 @@ static int locomokbd_probe(struct locomo_dev *dev)
- input_dev->id.version = 0x0100;
- input_dev->dev.parent = &dev->dev;
+ int (*agc_control) (struct dvb_frontend *, u8 before);
++
++ u8 output_mode;
+ };
-- 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);
+ #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 {
- memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode));
-@@ -268,7 +291,7 @@ static int locomokbd_probe(struct locomo_dev *dev)
- return err;
- }
+ static unsigned int dvb_pll_devcount;
--static int locomokbd_remove(struct locomo_dev *dev)
-+static int __devexit locomokbd_remove(struct locomo_dev *dev)
+-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)
{
- struct locomokbd *locomokbd = locomo_get_drvdata(dev);
+@@ -165,34 +131,6 @@ static struct dvb_pll_desc dvb_pll_lg_z201 = {
+ },
+ };
-@@ -292,7 +315,7 @@ static struct locomo_driver keyboard_driver = {
+-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 = {
},
- .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;
+-/* 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 = {
}
+ };
- 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,
+-/* 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 = {
},
};
-@@ -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;
- }
+-/*
+- * 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 = {
+ }
+ };
-+/* 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,
- },
+-/* 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,
};
-diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c
+ /* ----------------------------------------------------------- */
+@@ -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..8486abc
+index 0000000..33d33f4
--- /dev/null
-+++ b/drivers/input/keyboard/sh_keysc.c
-@@ -0,0 +1,280 @@
++++ b/drivers/media/dvb/frontends/isl6405.c
+@@ -0,0 +1,164 @@
+/*
-+ * SuperH KEYSC Keypad Driver
++ * isl6405.c - driver for dual lnb supply and control ic ISL6405
+ *
-+ * Copyright (C) 2008 Magnus Damm
++ * Copyright (C) 2008 Hartmut Hackmann
++ * Copyright (C) 2006 Oliver Endriss
+ *
-+ * 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
++ * as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
++ *
++ *
++ * the project's page is at http://www.linuxtv.org
+ */
-+
++#include <linux/delay.h>
++#include <linux/errno.h>
++#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/irq.h>
-+#include <linux/delay.h>
-+#include <linux/platform_device.h>
-+#include <linux/input.h>
-+#include <linux/io.h>
-+#include <asm/sh_keysc.h>
-+
-+#define KYCR1_OFFS 0x00
-+#define KYCR2_OFFS 0x04
-+#define KYINDR_OFFS 0x08
-+#define KYOUTDR_OFFS 0x0c
-+
-+#define KYCR2_IRQ_LEVEL 0x10
-+#define KYCR2_IRQ_DISABLED 0x00
++#include <linux/string.h>
++#include <linux/slab.h>
+
-+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 },
-+};
++#include "dvb_frontend.h"
++#include "isl6405.h"
+
-+struct sh_keysc_priv {
-+ void __iomem *iomem_base;
-+ unsigned long last_keys;
-+ struct input_dev *input;
-+ struct sh_keysc_info pdata;
++struct isl6405 {
++ u8 config;
++ u8 override_or;
++ u8 override_and;
++ struct i2c_adapter *i2c;
++ u8 i2c_addr;
+};
+
-+static irqreturn_t sh_keysc_isr(int irq, void *dev_id)
++static int isl6405_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
-+ 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;
-+ }
++ 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 (!(keys1 & mask)) {
-+ input_event(priv->input, EV_KEY, k, 0);
-+ priv->last_keys &= ~mask;
++ 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;
++ };
+ }
-+ input_sync(priv->input);
++ isl6405->config |= isl6405->override_or;
++ isl6405->config &= isl6405->override_and;
+
-+ return IRQ_HANDLED;
++ return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
-+#define res_size(res) ((res)->end - (res)->start + 1)
-+
-+static int __devinit sh_keysc_probe(struct platform_device *pdev)
++static int isl6405_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
-+ 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);
-+ }
++ 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) };
+
-+ error = input_register_device(input);
-+ if (error) {
-+ dev_err(&pdev->dev, "failed to register input device\n");
-+ goto err5;
++ 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;
+
-+ 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;
++ return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
-+static int __devexit sh_keysc_remove(struct platform_device *pdev)
++static void isl6405_release(struct dvb_frontend *fe)
+{
-+ struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
-+ struct resource *res;
-+
-+ iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS);
++ /* power off */
++ isl6405_set_voltage(fe, SEC_VOLTAGE_OFF);
+
-+ input_unregister_device(priv->input);
-+ free_irq(platform_get_irq(pdev, 0), pdev);
-+ iounmap(priv->iomem_base);
++ /* free */
++ kfree(fe->sec_priv);
++ fe->sec_priv = NULL;
++}
+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ release_mem_region(res->start, res_size(res));
++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;
+
-+ platform_set_drvdata(pdev, NULL);
-+ kfree(priv);
-+ return 0;
-+}
++ /* 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;
+
-+#define sh_keysc_suspend NULL
-+#define sh_keysc_resume NULL
++ /* bits which should be forced to '0' */
++ isl6405->override_and = ~override_clear;
+
-+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",
++ /* detect if it is present or not */
++ if (isl6405_set_voltage(fe, SEC_VOLTAGE_OFF)) {
++ kfree(isl6405);
++ fe->sec_priv = NULL;
++ return NULL;
+ }
-+};
+
-+static int __init sh_keysc_init(void)
-+{
-+ return platform_driver_register(&sh_keysc_device_driver);
-+}
++ /* install release callback */
++ fe->ops.release_sec = isl6405_release;
+
-+static void __exit sh_keysc_exit(void)
-+{
-+ platform_driver_unregister(&sh_keysc_device_driver);
-+}
++ /* override frontend ops */
++ fe->ops.set_voltage = isl6405_set_voltage;
++ fe->ops.enable_high_lnb_voltage = isl6405_enable_high_lnb_voltage;
+
-+module_init(sh_keysc_init);
-+module_exit(sh_keysc_exit);
++ return fe;
++}
++EXPORT_SYMBOL(isl6405_attach);
+
-+MODULE_AUTHOR("Magnus Damm");
-+MODULE_DESCRIPTION("SuperH KEYSC Keypad Driver");
++MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6405");
++MODULE_AUTHOR("Hartmut Hackmann & Oliver Endriss");
+MODULE_LICENSE("GPL");
-diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
-index 1d59a2d..61e401b 100644
---- a/drivers/input/keyboard/spitzkbd.c
-+++ b/drivers/input/keyboard/spitzkbd.c
-@@ -23,6 +23,7 @@
- #include <asm/arch/spitz.h>
- #include <asm/arch/hardware.h>
- #include <asm/arch/pxa-regs.h>
-+#include <asm/arch/pxa2xx-gpio.h>
-
- #define KB_ROWS 7
- #define KB_COLS 11
-@@ -494,3 +495,4 @@ module_exit(spitzkbd_exit);
- MODULE_AUTHOR("Richard Purdie <rpurdie at rpsys.net>");
- MODULE_DESCRIPTION("Spitz Keyboard Driver");
- MODULE_LICENSE("GPLv2");
-+MODULE_ALIAS("platform:spitz-keyboard");
-diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c
-index 3884d1e..94e444b 100644
---- a/drivers/input/keyboard/tosakbd.c
-+++ b/drivers/input/keyboard/tosakbd.c
-@@ -52,7 +52,7 @@ KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_
- struct tosakbd {
- unsigned int keycode[ARRAY_SIZE(tosakbd_keycode)];
- struct input_dev *input;
--
-+ int suspended;
- spinlock_t lock; /* protect kbd scanning */
- struct timer_list timer;
- };
-@@ -133,6 +133,9 @@ static void tosakbd_scankeyboard(struct platform_device *dev)
-
- spin_lock_irqsave(&tosakbd->lock, flags);
-
-+ if (tosakbd->suspended)
-+ goto out;
+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
++ */
+
- 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;
++#ifndef _ISL6405_H
++#define _ISL6405_H
+
- 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;
++#include <linux/dvb/frontend.h>
+
-+ 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);
++/* system register bits */
+
-+ tosakbd->suspended = 0;
- tosakbd_scankeyboard(dev);
-
- return 0;
-@@ -365,8 +380,8 @@ fail:
- return error;
- }
-
--static int __devexit tosakbd_remove(struct platform_device *dev) {
--
-+static int __devexit tosakbd_remove(struct platform_device *dev)
-+{
- int i;
- struct tosakbd *tosakbd = platform_get_drvdata(dev);
-
-@@ -394,6 +409,7 @@ static struct platform_driver tosakbd_driver = {
- .resume = tosakbd_resume,
- .driver = {
- .name = "tosa-keyboard",
-+ .owner = THIS_MODULE,
- },
- };
-
-@@ -413,3 +429,4 @@ module_exit(tosakbd_exit);
- MODULE_AUTHOR("Dirk Opfer <Dirk at Opfer-Online.de>");
- MODULE_DESCRIPTION("Tosa Keyboard Driver");
- MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:tosa-keyboard");
-diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
-index c5263d6..92b6834 100644
---- a/drivers/input/misc/Kconfig
-+++ b/drivers/input/misc/Kconfig
-@@ -15,6 +15,7 @@ if INPUT_MISC
- config INPUT_PCSPKR
- tristate "PC Speaker support"
- depends on ALPHA || X86 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES
-+ depends on SND_PCSP=n
- help
- Say Y here if you want the standard PC Speaker to be used for
- bells and whistles.
-diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c
-index 5511ef0..6a1f48b 100644
---- a/drivers/input/misc/cobalt_btns.c
-+++ b/drivers/input/misc/cobalt_btns.c
-@@ -148,6 +148,9 @@ static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
- return 0;
- }
-
-+/* work with hotplug and coldplug */
-+MODULE_ALIAS("platform:Cobalt buttons");
++/* this bit selects register (control) 1 or 2
++ note that the bit maps are different */
+
- 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");
++#define ISL6405_SR 0x80
+
- 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.
++/* 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
+
-+ To compile this driver as a module, choose M here: the module will
-+ be called at32psif.
++/* 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
+
- 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
++#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..41fda8c
+index 0000000..04c562c
--- /dev/null
-+++ b/drivers/input/serio/at32psif.c
-@@ -0,0 +1,375 @@
++++ b/drivers/media/dvb/frontends/itd1000.c
+@@ -0,0 +1,400 @@
+/*
-+ * Copyright (C) 2007 Atmel Corporation
++ * Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
+ *
-+ * Driver for the AT32AP700X PS/2 controller (PSIF).
++ * Copyright (c) 2007-8 Patrick Boettcher <pb at linuxtv.org>
+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published
-+ * by the Free Software Foundation.
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
-+#include <linux/kernel.h>
++
+#include <linux/module.h>
-+#include <linux/device.h>
-+#include <linux/init.h>
-+#include <linux/serio.h>
-+#include <linux/interrupt.h>
++#include <linux/moduleparam.h>
+#include <linux/delay.h>
-+#include <linux/err.h>
-+#include <linux/io.h>
-+#include <linux/clk.h>
-+#include <linux/platform_device.h>
-+
-+/* PSIF register offsets */
-+#define PSIF_CR 0x00
-+#define PSIF_RHR 0x04
-+#define PSIF_THR 0x08
-+#define PSIF_SR 0x10
-+#define PSIF_IER 0x14
-+#define PSIF_IDR 0x18
-+#define PSIF_IMR 0x1c
-+#define PSIF_PSR 0x24
++#include <linux/dvb/frontend.h>
++#include <linux/i2c.h>
+
-+/* 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
++#include "dvb_frontend.h"
+
-+/* 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
++#include "itd1000.h"
++#include "itd1000_priv.h"
+
-+/* Bitfields in prescale register. */
-+#define PSIF_PSR_PRSCV_OFFSET 0
-+#define PSIF_PSR_PRSCV_SIZE 12
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
-+/* Bitfields in receive hold register. */
-+#define PSIF_RHR_RXDATA_OFFSET 0
-+#define PSIF_RHR_RXDATA_SIZE 8
++#define deb(args...) do { \
++ if (debug) { \
++ printk(KERN_DEBUG "ITD1000: " args);\
++ printk("\n"); \
++ } \
++} while (0)
+
-+/* Bitfields in transmit hold register. */
-+#define PSIF_THR_TXDATA_OFFSET 0
-+#define PSIF_THR_TXDATA_SIZE 8
++#define warn(args...) do { \
++ printk(KERN_WARNING "ITD1000: " args); \
++ printk("\n"); \
++} while (0)
+
-+/* Bit manipulation macros */
-+#define PSIF_BIT(name) \
-+ (1 << PSIF_##name##_OFFSET)
++#define info(args...) do { \
++ printk(KERN_INFO "ITD1000: " args); \
++ printk("\n"); \
++} while (0)
+
-+#define PSIF_BF(name, value) \
-+ (((value) & ((1 << PSIF_##name##_SIZE) - 1)) \
-+ << PSIF_##name##_OFFSET)
++/* 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);
+
-+#define PSIF_BFEXT(name, value) \
-+ (((value) >> PSIF_##name##_OFFSET) \
-+ & ((1 << PSIF_##name##_SIZE) - 1))
++ /* deb("wr %02x: %02x", reg, v[0]); */
+
-+#define PSIF_BFINS(name, value, old) \
-+ (((old) & ~(((1 << PSIF_##name##_SIZE) - 1) \
-+ << PSIF_##name##_OFFSET)) \
-+ | PSIF_BF(name, value))
++ if (i2c_transfer(state->i2c, &msg, 1) != 1) {
++ printk(KERN_WARNING "itd1000 I2C write failed\n");
++ return -EREMOTEIO;
++ }
++ return 0;
++}
+
-+/* Register access macros */
-+#define psif_readl(port, reg) \
-+ __raw_readl((port)->regs + PSIF_##reg)
++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 },
++ };
+
-+#define psif_writel(port, reg, value) \
-+ __raw_writel((value), (port)->regs + PSIF_##reg)
++ /* ugly flexcop workaround */
++ itd1000_write_regs(state, (reg - 1) & 0xff, &state->shadow[(reg - 1) & 0xff], 1);
+
-+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;
-+};
++ if (i2c_transfer(state->i2c, msg, 2) != 2) {
++ warn("itd1000 I2C read failed");
++ return -EREMOTEIO;
++ }
++ return val;
++}
+
-+static irqreturn_t psif_interrupt(int irq, void *_ptr)
++static inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v)
+{
-+ struct psif *psif = _ptr;
-+ int retval = IRQ_NONE;
-+ unsigned int io_flags = 0;
-+ unsigned long status;
++ int ret = itd1000_write_regs(state, r, &v, 1);
++ state->shadow[r] = v;
++ return ret;
++}
+
-+ status = psif_readl(psif, SR);
+
-+ if (status & PSIF_BIT(RXRDY)) {
-+ unsigned char val = (unsigned char) psif_readl(psif, RHR);
++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 },
++};
+
-+ if (status & PSIF_BIT(PARITY))
-+ io_flags |= SERIO_PARITY;
-+ if (status & PSIF_BIT(OVRUN))
-+ dev_err(&psif->pdev->dev, "overrun read error\n");
++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;
+
-+ serio_interrupt(psif->io, val, io_flags);
++ deb("symbol_rate = %d", symbol_rate);
+
-+ retval = IRQ_HANDLED;
-+ }
++ /* not sure what is that ? - starting to download the table */
++ itd1000_write_reg(state, CON1, con1 | (1 << 1));
+
-+ return retval;
++ 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 int psif_write(struct serio *io, unsigned char val)
++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)
+{
-+ struct psif *psif = io->port_data;
-+ unsigned long flags;
-+ int timeout = 10;
-+ int retval = 0;
++ 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;
+
-+ spin_lock_irqsave(&psif->lock, flags);
++ /* reserved bit again (reset ?) */
++ itd1000_write_reg(state, GVBB_I2C, gvbb_i2c | (1 << 6));
+
-+ while (!(psif_readl(psif, SR) & PSIF_BIT(TXEMPTY)) && timeout--)
-+ msleep(10);
++ 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);
+
-+ if (timeout >= 0) {
-+ psif_writel(psif, THR, val);
-+ } else {
-+ dev_dbg(&psif->pdev->dev, "timeout writing to THR\n");
-+ retval = -EBUSY;
-+ }
++ adcout = itd1000_read_reg(state, PLLLOCK) & 0x0f;
+
-+ spin_unlock_irqrestore(&psif->lock, flags);
++ deb("VCO: %dkHz: %d -> ADCOUT: %d %02x", freq_khz, itd1000_vcorg[i].vcorg, adcout, vco_chp1_i2c);
+
-+ return retval;
++ 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;
++ }
++ }
+}
+
-+static int psif_open(struct serio *io)
-+{
-+ struct psif *psif = io->port_data;
-+ int retval;
-+
-+ retval = clk_enable(psif->pclk);
-+ if (retval)
-+ goto out;
++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 } }
++};
+
-+ 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;
-+}
++#define FREF 16
+
-+static void psif_close(struct serio *io)
++static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
+{
-+ struct psif *psif = io->port_data;
++ int i, j;
++ u32 plln, pllf;
++ u64 tmp;
+
-+ psif->open = 0;
++ plln = (freq_khz * 1000) / 2 / FREF;
+
-+ psif_writel(psif, IDR, ~0UL);
-+ psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS));
++ /* Compute the factional part times 1000 */
++ tmp = plln % 1000000;
++ plln /= 1000000;
+
-+ clk_disable(psif->pclk);
-+}
++ tmp *= 1048576;
++ do_div(tmp, 1000000);
++ pllf = (u32) tmp;
+
-+static void psif_set_prescaler(struct psif *psif)
-+{
-+ unsigned long prscv;
-+ unsigned long rate = clk_get_rate(psif->pclk);
++ 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);
+
-+ /* PRSCV = Pulse length (100 us) * PSIF module frequency. */
-+ prscv = 100 * (rate / 1000000UL);
++ 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);
+
-+ if (prscv > ((1<<PSIF_PSR_PRSCV_SIZE) - 1)) {
-+ prscv = (1<<PSIF_PSR_PRSCV_SIZE) - 1;
-+ dev_dbg(&psif->pdev->dev, "pclk too fast, "
-+ "prescaler set to max\n");
++ 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;
++ }
+ }
+
-+ clk_enable(psif->pclk);
-+ psif_writel(psif, PSR, prscv);
-+ clk_disable(psif->pclk);
++ itd1000_set_vco(state, freq_khz);
+}
+
-+static int __init psif_probe(struct platform_device *pdev)
++static int itd1000_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
-+ struct resource *regs;
-+ struct psif *psif;
-+ struct serio *io;
-+ struct clk *pclk;
-+ int irq;
-+ int ret;
++ struct itd1000_state *state = fe->tuner_priv;
++ u8 pllcon1;
+
-+ psif = kzalloc(sizeof(struct psif), GFP_KERNEL);
-+ if (!psif) {
-+ dev_dbg(&pdev->dev, "out of memory\n");
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+ psif->pdev = pdev;
++ itd1000_set_lo(state, p->frequency);
++ itd1000_set_lpf_bw(state, p->u.qpsk.symbol_rate);
+
-+ 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;
++ pllcon1 = itd1000_read_reg(state, PLLCON1) & 0x7f;
++ itd1000_write_reg(state, PLLCON1, pllcon1 | (1 << 7));
++ itd1000_write_reg(state, PLLCON1, pllcon1);
+
-+ 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;
-+ }
++ return 0;
++}
+
-+ 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;
-+ }
++static int itd1000_get_frequency(struct dvb_frontend *fe, u32 *frequency)
++{
++ struct itd1000_state *state = fe->tuner_priv;
++ *frequency = state->frequency;
++ return 0;
++}
+
-+ 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;
++static int itd1000_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
++{
++ return 0;
++}
+
-+ /* 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);
++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 },
++};
+
-+ 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;
++static u8 itd1000_reinit_tab[][2] = {
++ { VCO_CHP1_I2C, 0x8a },
++ { BW, 0x87 },
++ { GVBB_I2C, 0x03 },
++ { BBGVMIN, 0x03 },
++ { CON1, 0x2e },
++};
+
-+ 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);
++static int itd1000_init(struct dvb_frontend *fe)
++{
++ struct itd1000_state *state = fe->tuner_priv;
++ int i;
+
-+ spin_lock_init(&psif->lock);
-+ serio_register_port(psif->io);
-+ platform_set_drvdata(pdev, psif);
++ for (i = 0; i < ARRAY_SIZE(itd1000_init_tab); i++)
++ itd1000_write_reg(state, itd1000_init_tab[i][0], itd1000_init_tab[i][1]);
+
-+ dev_info(&pdev->dev, "Atmel AVR32 PSIF PS/2 driver on 0x%08x irq %d\n",
-+ (int)psif->regs, psif->irq);
++ 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;
++}
+
-+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 itd1000_sleep(struct dvb_frontend *fe)
++{
++ return 0;
+}
+
-+static int __exit psif_remove(struct platform_device *pdev)
++static int itd1000_release(struct dvb_frontend *fe)
+{
-+ struct psif *psif = platform_get_drvdata(pdev);
++ kfree(fe->tuner_priv);
++ fe->tuner_priv = NULL;
++ return 0;
++}
+
-+ psif_writel(psif, IDR, ~0UL);
-+ psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS));
++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 */
++ },
+
-+ serio_unregister_port(psif->io);
-+ iounmap(psif->regs);
-+ free_irq(psif->irq, psif);
-+ clk_put(psif->pclk);
-+ kfree(psif);
++ .release = itd1000_release,
+
-+ platform_set_drvdata(pdev, NULL);
++ .init = itd1000_init,
++ .sleep = itd1000_sleep,
+
-+ return 0;
-+}
++ .set_params = itd1000_set_parameters,
++ .get_frequency = itd1000_get_frequency,
++ .get_bandwidth = itd1000_get_bandwidth
++};
+
-+#ifdef CONFIG_PM
-+static int psif_suspend(struct platform_device *pdev, pm_message_t state)
++
++struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg)
+{
-+ struct psif *psif = platform_get_drvdata(pdev);
++ struct itd1000_state *state = NULL;
++ u8 i = 0;
+
-+ if (psif->open) {
-+ psif_writel(psif, CR, PSIF_BIT(CR_RXDIS) | PSIF_BIT(CR_TXDIS));
-+ clk_disable(psif->pclk);
++ 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);
+
-+ return 0;
-+}
++ memset(state->shadow, 0xff, sizeof(state->shadow));
++ for (i = 0x65; i < 0x9c; i++)
++ state->shadow[i] = itd1000_read_reg(state, i);
+
-+static int psif_resume(struct platform_device *pdev)
-+{
-+ struct psif *psif = platform_get_drvdata(pdev);
++ memcpy(&fe->ops.tuner_ops, &itd1000_tuner_ops, sizeof(struct dvb_tuner_ops));
+
-+ if (psif->open) {
-+ clk_enable(psif->pclk);
-+ psif_set_prescaler(psif);
-+ psif_writel(psif, CR, PSIF_BIT(CR_RXEN) | PSIF_BIT(CR_TXEN));
-+ }
++ fe->tuner_priv = state;
+
-+ return 0;
++ return fe;
+}
-+#else
-+#define psif_suspend NULL
-+#define psif_resume NULL
-+#endif
++EXPORT_SYMBOL(itd1000_attach);
+
-+static struct platform_driver psif_driver = {
-+ .remove = __exit_p(psif_remove),
-+ .driver = {
-+ .name = "atmel_psif",
-+ },
-+ .suspend = psif_suspend,
-+ .resume = psif_resume,
++MODULE_AUTHOR("Patrick Boettcher <pb at linuxtv.org>");
++MODULE_DESCRIPTION("Integrant ITD1000 driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/dvb/frontends/itd1000.h b/drivers/media/dvb/frontends/itd1000.h
+new file mode 100644
+index 0000000..5e18df0
+--- /dev/null
++++ b/drivers/media/dvb/frontends/itd1000.h
+@@ -0,0 +1,42 @@
++/*
++ * Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
++ *
++ * Copyright (c) 2007 Patrick Boettcher <pb at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ */
++
++#ifndef ITD1000_H
++#define ITD1000_H
++
++struct dvb_frontend;
++struct i2c_adapter;
++
++struct itd1000_config {
++ u8 i2c_address;
+};
+
-+static int __init psif_init(void)
++#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)
+{
-+ return platform_driver_probe(&psif_driver, psif_probe);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++ return NULL;
+}
++#endif
+
-+static void __exit psif_exit(void)
-+{
-+ platform_driver_unregister(&psif_driver);
-+}
++#endif
+diff --git a/drivers/media/dvb/frontends/itd1000_priv.h b/drivers/media/dvb/frontends/itd1000_priv.h
+new file mode 100644
+index 0000000..8cdc54e
+--- /dev/null
++++ b/drivers/media/dvb/frontends/itd1000_priv.h
+@@ -0,0 +1,88 @@
++/*
++ * Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
++ *
++ * Copyright (c) 2007 Patrick Boettcher <pb at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ */
+
-+module_init(psif_init);
-+module_exit(psif_exit);
++#ifndef ITD1000_PRIV_H
++#define ITD1000_PRIV_H
+
-+MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt at atmel.com>");
-+MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
-index c45ea74..f1fd3b6 100644
---- a/drivers/input/serio/hp_sdc_mlc.c
-+++ b/drivers/input/serio/hp_sdc_mlc.c
-@@ -40,7 +40,7 @@
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/string.h>
--#include <asm/semaphore.h>
-+#include <linux/semaphore.h>
++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)
- #define PREFIX "HP SDC MLC: "
+ if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1)
+ dprintk ("%s: write_reg error (reg == %02x) = %02x!\n",
+- __FUNCTION__, reg, ret);
++ __func__, reg, ret);
-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);
+ 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 */
-- 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));
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off).");
+ #define dprintk(args...) \
+@@ -88,7 +88,7 @@ static int i2c_write_demod_bytes (struct lgdt330x_state* state,
+
+ for (i=0; i<len-1; i+=2){
+ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+- printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err);
++ printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __func__, msg.buf[0], msg.buf[1], err);
+ if (err < 0)
+ return err;
+ else
+@@ -117,7 +117,7 @@ static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
+ int ret;
+ ret = i2c_transfer(state->i2c, msg, 2);
+ if (ret != 2) {
+- printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __FUNCTION__, state->config->demod_address, reg, ret);
++ printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __func__, state->config->demod_address, reg, ret);
+ } else {
+ ret = 0;
+ }
+@@ -256,7 +256,7 @@ static int lgdt330x_init(struct dvb_frontend* fe)
+ printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
+ err = -ENODEV;
+ }
+- dprintk("%s entered as %s\n", __FUNCTION__, chip_name);
++ dprintk("%s entered as %s\n", __func__, chip_name);
+ if (err < 0)
+ return err;
+ return lgdt330x_SwReset(state);
+@@ -334,7 +334,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
+ if (state->current_modulation != param->u.vsb.modulation) {
+ switch(param->u.vsb.modulation) {
+ case VSB_8:
+- dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
++ dprintk("%s: VSB_8 MODE\n", __func__);
+
+ /* Select VSB mode */
+ top_ctrl_cfg[1] = 0x03;
+@@ -350,7 +350,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
+ break;
+
+ case QAM_64:
+- dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
++ dprintk("%s: QAM_64 MODE\n", __func__);
+
+ /* Select QAM_64 mode */
+ top_ctrl_cfg[1] = 0x00;
+@@ -366,7 +366,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
+ break;
+
+ case QAM_256:
+- dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
++ dprintk("%s: QAM_256 MODE\n", __func__);
+
+ /* Select QAM_256 mode */
+ top_ctrl_cfg[1] = 0x01;
+@@ -381,7 +381,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
+ }
+ break;
+ default:
+- printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
++ printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __func__, param->u.vsb.modulation);
+ return -1;
+ }
+ /*
+@@ -431,7 +431,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
+
+ /* AGC status register */
+ i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
+- dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
++ dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]);
+ if ((buf[0] & 0x0c) == 0x8){
+ /* Test signal does not exist flag */
+ /* as well as the AGC lock flag. */
+@@ -445,7 +445,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ */
+ /* signal status */
+ i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
+- dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]);
++ dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __func__, buf[0], buf[1], buf[2]);
+
+
+ /* sync status */
+@@ -461,7 +461,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
+
+ /* Carrier Recovery Lock Status Register */
+ i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
+- dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
++ dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]);
+ switch (state->current_modulation) {
+ case QAM_256:
+ case QAM_64:
+@@ -474,7 +474,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ *status |= FE_HAS_CARRIER;
+ break;
+ default:
+- printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
++ printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__);
}
- 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);
+ return 0;
+@@ -493,7 +493,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ if (err < 0)
+ return err;
-- 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));
+- 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.c b/drivers/media/dvb/frontends/mt2060.c
+deleted file mode 100644
+index 1305b0e..0000000
+--- a/drivers/media/dvb/frontends/mt2060.c
++++ /dev/null
+@@ -1,369 +0,0 @@
+-/*
+- * Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
+- *
+- * Copyright (c) 2006 Olivier DANET <odanet at caramail.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- *
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+- */
+-
+-/* In that file, frequencies are expressed in kiloHertz to avoid 32 bits overflows */
+-
+-#include <linux/module.h>
+-#include <linux/delay.h>
+-#include <linux/dvb/frontend.h>
+-#include <linux/i2c.h>
+-
+-#include "dvb_frontend.h"
+-
+-#include "mt2060.h"
+-#include "mt2060_priv.h"
+-
+-static int debug;
+-module_param(debug, int, 0644);
+-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+-
+-#define dprintk(args...) do { if (debug) {printk(KERN_DEBUG "MT2060: " args); printk("\n"); }} while (0)
+-
+-// Reads a single register
+-static int mt2060_readreg(struct mt2060_priv *priv, u8 reg, u8 *val)
+-{
+- struct i2c_msg msg[2] = {
+- { .addr = priv->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 },
+- { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val, .len = 1 },
+- };
+-
+- if (i2c_transfer(priv->i2c, msg, 2) != 2) {
+- printk(KERN_WARNING "mt2060 I2C read failed\n");
+- return -EREMOTEIO;
+- }
+- return 0;
+-}
+-
+-// Writes a single register
+-static int mt2060_writereg(struct mt2060_priv *priv, u8 reg, u8 val)
+-{
+- u8 buf[2] = { reg, val };
+- struct i2c_msg msg = {
+- .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2
+- };
+-
+- if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+- printk(KERN_WARNING "mt2060 I2C write failed\n");
+- return -EREMOTEIO;
+- }
+- return 0;
+-}
+-
+-// Writes a set of consecutive registers
+-static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len)
+-{
+- struct i2c_msg msg = {
+- .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = len
+- };
+- if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+- printk(KERN_WARNING "mt2060 I2C write failed (len=%i)\n",(int)len);
+- return -EREMOTEIO;
+- }
+- return 0;
+-}
+-
+-// Initialisation sequences
+-// LNABAND=3, NUM1=0x3C, DIV1=0x74, NUM2=0x1080, DIV2=0x49
+-static u8 mt2060_config1[] = {
+- REG_LO1C1,
+- 0x3F, 0x74, 0x00, 0x08, 0x93
+-};
+-
+-// FMCG=2, GP2=0, GP1=0
+-static u8 mt2060_config2[] = {
+- REG_MISC_CTRL,
+- 0x20, 0x1E, 0x30, 0xff, 0x80, 0xff, 0x00, 0x2c, 0x42
+-};
+-
+-// VGAG=3, V1CSE=1
+-
+-#ifdef MT2060_SPURCHECK
+-/* The function below calculates the frequency offset between the output frequency if2
+- and the closer cross modulation subcarrier between lo1 and lo2 up to the tenth harmonic */
+-static int mt2060_spurcalc(u32 lo1,u32 lo2,u32 if2)
+-{
+- int I,J;
+- int dia,diamin,diff;
+- diamin=1000000;
+- for (I = 1; I < 10; I++) {
+- J = ((2*I*lo1)/lo2+1)/2;
+- diff = I*(int)lo1-J*(int)lo2;
+- if (diff < 0) diff=-diff;
+- dia = (diff-(int)if2);
+- if (dia < 0) dia=-dia;
+- if (diamin > dia) diamin=dia;
+- }
+- return diamin;
+-}
+-
+-#define BANDWIDTH 4000 // kHz
+-
+-/* Calculates the frequency offset to add to avoid spurs. Returns 0 if no offset is needed */
+-static int mt2060_spurcheck(u32 lo1,u32 lo2,u32 if2)
+-{
+- u32 Spur,Sp1,Sp2;
+- int I,J;
+- I=0;
+- J=1000;
+-
+- Spur=mt2060_spurcalc(lo1,lo2,if2);
+- if (Spur < BANDWIDTH) {
+- /* Potential spurs detected */
+- dprintk("Spurs before : f_lo1: %d f_lo2: %d (kHz)",
+- (int)lo1,(int)lo2);
+- I=1000;
+- Sp1 = mt2060_spurcalc(lo1+I,lo2+I,if2);
+- Sp2 = mt2060_spurcalc(lo1-I,lo2-I,if2);
+-
+- if (Sp1 < Sp2) {
+- J=-J; I=-I; Spur=Sp2;
+- } else
+- Spur=Sp1;
+-
+- while (Spur < BANDWIDTH) {
+- I += J;
+- Spur = mt2060_spurcalc(lo1+I,lo2+I,if2);
+- }
+- dprintk("Spurs after : f_lo1: %d f_lo2: %d (kHz)",
+- (int)(lo1+I),(int)(lo2+I));
+- }
+- return I;
+-}
+-#endif
+-
+-#define IF2 36150 // IF2 frequency = 36.150 MHz
+-#define FREF 16000 // Quartz oscillator 16 MHz
+-
+-static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+-{
+- struct mt2060_priv *priv;
+- int ret=0;
+- int i=0;
+- u32 freq;
+- u8 lnaband;
+- u32 f_lo1,f_lo2;
+- u32 div1,num1,div2,num2;
+- u8 b[8];
+- u32 if1;
+-
+- priv = fe->tuner_priv;
+-
+- if1 = priv->if1_freq;
+- b[0] = REG_LO1B1;
+- b[1] = 0xFF;
+-
+- mt2060_writeregs(priv,b,2);
+-
+- freq = params->frequency / 1000; // Hz -> kHz
+- priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+-
+- f_lo1 = freq + if1 * 1000;
+- f_lo1 = (f_lo1 / 250) * 250;
+- f_lo2 = f_lo1 - freq - IF2;
+- // From the Comtech datasheet, the step used is 50kHz. The tuner chip could be more precise
+- f_lo2 = ((f_lo2 + 25) / 50) * 50;
+- priv->frequency = (f_lo1 - f_lo2 - IF2) * 1000,
+-
+-#ifdef MT2060_SPURCHECK
+- // LO-related spurs detection and correction
+- num1 = mt2060_spurcheck(f_lo1,f_lo2,IF2);
+- f_lo1 += num1;
+- f_lo2 += num1;
+-#endif
+- //Frequency LO1 = 16MHz * (DIV1 + NUM1/64 )
+- num1 = f_lo1 / (FREF / 64);
+- div1 = num1 / 64;
+- num1 &= 0x3f;
+-
+- // Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 )
+- num2 = f_lo2 * 64 / (FREF / 128);
+- div2 = num2 / 8192;
+- num2 &= 0x1fff;
+-
+- if (freq <= 95000) lnaband = 0xB0; else
+- if (freq <= 180000) lnaband = 0xA0; else
+- if (freq <= 260000) lnaband = 0x90; else
+- if (freq <= 335000) lnaband = 0x80; else
+- if (freq <= 425000) lnaband = 0x70; else
+- if (freq <= 480000) lnaband = 0x60; else
+- if (freq <= 570000) lnaband = 0x50; else
+- if (freq <= 645000) lnaband = 0x40; else
+- if (freq <= 730000) lnaband = 0x30; else
+- if (freq <= 810000) lnaband = 0x20; else lnaband = 0x10;
+-
+- b[0] = REG_LO1C1;
+- b[1] = lnaband | ((num1 >>2) & 0x0F);
+- b[2] = div1;
+- b[3] = (num2 & 0x0F) | ((num1 & 3) << 4);
+- b[4] = num2 >> 4;
+- b[5] = ((num2 >>12) & 1) | (div2 << 1);
+-
+- dprintk("IF1: %dMHz",(int)if1);
+- dprintk("PLL freq=%dkHz f_lo1=%dkHz f_lo2=%dkHz",(int)freq,(int)f_lo1,(int)f_lo2);
+- dprintk("PLL div1=%d num1=%d div2=%d num2=%d",(int)div1,(int)num1,(int)div2,(int)num2);
+- dprintk("PLL [1..5]: %2x %2x %2x %2x %2x",(int)b[1],(int)b[2],(int)b[3],(int)b[4],(int)b[5]);
+-
+- mt2060_writeregs(priv,b,6);
+-
+- //Waits for pll lock or timeout
+- i = 0;
+- do {
+- mt2060_readreg(priv,REG_LO_STATUS,b);
+- if ((b[0] & 0x88)==0x88)
+- break;
+- msleep(4);
+- i++;
+- } while (i<10);
+-
+- return ret;
+-}
+-
+-static void mt2060_calibrate(struct mt2060_priv *priv)
+-{
+- u8 b = 0;
+- int i = 0;
+-
+- if (mt2060_writeregs(priv,mt2060_config1,sizeof(mt2060_config1)))
+- return;
+- if (mt2060_writeregs(priv,mt2060_config2,sizeof(mt2060_config2)))
+- return;
+-
+- /* initialize the clock output */
+- mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x30);
+-
+- do {
+- b |= (1 << 6); // FM1SS;
+- mt2060_writereg(priv, REG_LO2C1,b);
+- msleep(20);
+-
+- if (i == 0) {
+- b |= (1 << 7); // FM1CA;
+- mt2060_writereg(priv, REG_LO2C1,b);
+- b &= ~(1 << 7); // FM1CA;
+- msleep(20);
+- }
+-
+- b &= ~(1 << 6); // FM1SS
+- mt2060_writereg(priv, REG_LO2C1,b);
+-
+- msleep(20);
+- i++;
+- } while (i < 9);
+-
+- i = 0;
+- while (i++ < 10 && mt2060_readreg(priv, REG_MISC_STAT, &b) == 0 && (b & (1 << 6)) == 0)
+- msleep(20);
+-
+- if (i < 10) {
+- mt2060_readreg(priv, REG_FM_FREQ, &priv->fmfreq); // now find out, what is fmreq used for :)
+- dprintk("calibration was successful: %d", (int)priv->fmfreq);
+- } else
+- dprintk("FMCAL timed out");
+-}
+-
+-static int mt2060_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+-{
+- struct mt2060_priv *priv = fe->tuner_priv;
+- *frequency = priv->frequency;
+- return 0;
+-}
+-
+-static int mt2060_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+-{
+- struct mt2060_priv *priv = fe->tuner_priv;
+- *bandwidth = priv->bandwidth;
+- return 0;
+-}
+-
+-static int mt2060_init(struct dvb_frontend *fe)
+-{
+- struct mt2060_priv *priv = fe->tuner_priv;
+- return mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x33);
+-}
+-
+-static int mt2060_sleep(struct dvb_frontend *fe)
+-{
+- struct mt2060_priv *priv = fe->tuner_priv;
+- return mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x30);
+-}
+-
+-static int mt2060_release(struct dvb_frontend *fe)
+-{
+- kfree(fe->tuner_priv);
+- fe->tuner_priv = NULL;
+- return 0;
+-}
+-
+-static const struct dvb_tuner_ops mt2060_tuner_ops = {
+- .info = {
+- .name = "Microtune MT2060",
+- .frequency_min = 48000000,
+- .frequency_max = 860000000,
+- .frequency_step = 50000,
+- },
+-
+- .release = mt2060_release,
+-
+- .init = mt2060_init,
+- .sleep = mt2060_sleep,
+-
+- .set_params = mt2060_set_params,
+- .get_frequency = mt2060_get_frequency,
+- .get_bandwidth = mt2060_get_bandwidth
+-};
+-
+-/* This functions tries to identify a MT2060 tuner by reading the PART/REV register. This is hasty. */
+-struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
+-{
+- struct mt2060_priv *priv = NULL;
+- u8 id = 0;
+-
+- priv = kzalloc(sizeof(struct mt2060_priv), GFP_KERNEL);
+- if (priv == NULL)
+- return NULL;
+-
+- priv->cfg = cfg;
+- priv->i2c = i2c;
+- priv->if1_freq = if1;
+-
+- if (mt2060_readreg(priv,REG_PART_REV,&id) != 0) {
+- kfree(priv);
+- return NULL;
+- }
+-
+- if (id != PART_REV) {
+- kfree(priv);
+- return NULL;
+- }
+- printk(KERN_INFO "MT2060: successfully identified (IF1 = %d)\n", if1);
+- memcpy(&fe->ops.tuner_ops, &mt2060_tuner_ops, sizeof(struct dvb_tuner_ops));
+-
+- fe->tuner_priv = priv;
+-
+- mt2060_calibrate(priv);
+-
+- return fe;
+-}
+-EXPORT_SYMBOL(mt2060_attach);
+-
+-MODULE_AUTHOR("Olivier DANET");
+-MODULE_DESCRIPTION("Microtune MT2060 silicon tuner driver");
+-MODULE_LICENSE("GPL");
+diff --git a/drivers/media/dvb/frontends/mt2060.h b/drivers/media/dvb/frontends/mt2060.h
+deleted file mode 100644
+index 0a86eab..0000000
+--- a/drivers/media/dvb/frontends/mt2060.h
++++ /dev/null
+@@ -1,43 +0,0 @@
+-/*
+- * Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
+- *
+- * Copyright (c) 2006 Olivier DANET <odanet at caramail.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- *
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+- */
+-
+-#ifndef MT2060_H
+-#define MT2060_H
+-
+-struct dvb_frontend;
+-struct i2c_adapter;
+-
+-struct mt2060_config {
+- u8 i2c_address;
+- u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */
+-};
+-
+-#if defined(CONFIG_DVB_TUNER_MT2060) || (defined(CONFIG_DVB_TUNER_MT2060_MODULE) && defined(MODULE))
+-extern struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1);
+-#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__);
+- return NULL;
+-}
+-#endif // CONFIG_DVB_TUNER_MT2060
+-
+-#endif
+diff --git a/drivers/media/dvb/frontends/mt2060_priv.h b/drivers/media/dvb/frontends/mt2060_priv.h
+deleted file mode 100644
+index 5eaccde..0000000
+--- a/drivers/media/dvb/frontends/mt2060_priv.h
++++ /dev/null
+@@ -1,105 +0,0 @@
+-/*
+- * Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
+- *
+- * Copyright (c) 2006 Olivier DANET <odanet at caramail.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- *
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+- */
+-
+-#ifndef MT2060_PRIV_H
+-#define MT2060_PRIV_H
+-
+-// Uncomment the #define below to enable spurs checking. The results where quite unconvincing.
+-// #define MT2060_SPURCHECK
+-
+-/* This driver is based on the information available in the datasheet of the
+- "Comtech SDVBT-3K6M" tuner ( K1000737843.pdf ) which features the MT2060 register map :
+-
+- I2C Address : 0x60
+-
+- Reg.No | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | ( defaults )
+- --------------------------------------------------------------------------------
+- 00 | [ PART ] | [ REV ] | R = 0x63
+- 01 | [ LNABAND ] | [ NUM1(5:2) ] | RW = 0x3F
+- 02 | [ DIV1 ] | RW = 0x74
+- 03 | FM1CA | FM1SS | [ NUM1(1:0) ] | [ NUM2(3:0) ] | RW = 0x00
+- 04 | NUM2(11:4) ] | RW = 0x08
+- 05 | [ DIV2 ] |NUM2(12)| RW = 0x93
+- 06 | L1LK | [ TAD1 ] | L2LK | [ TAD2 ] | R
+- 07 | [ FMF ] | R
+- 08 | ? | FMCAL | ? | ? | ? | ? | ? | TEMP | R
+- 09 | 0 | 0 | [ FMGC ] | 0 | GP02 | GP01 | 0 | RW = 0x20
+- 0A | ??
+- 0B | 0 | 0 | 1 | 1 | 0 | 0 | [ VGAG ] | RW = 0x30
+- 0C | V1CSE | 1 | 1 | 1 | 1 | 1 | 1 | 1 | RW = 0xFF
+- 0D | 1 | 0 | [ V1CS ] | RW = 0xB0
+- 0E | ??
+- 0F | ??
+- 10 | ??
+- 11 | [ LOTO ] | 0 | 0 | 1 | 0 | RW = 0x42
+-
+- PART : Part code : 6 for MT2060
+- REV : Revision code : 3 for current revision
+- LNABAND : Input frequency range : ( See code for details )
+- NUM1 / DIV1 / NUM2 / DIV2 : Frequencies programming ( See code for details )
+- FM1CA : Calibration Start Bit
+- FM1SS : Calibration Single Step bit
+- L1LK : LO1 Lock Detect
+- TAD1 : Tune Line ADC ( ? )
+- L2LK : LO2 Lock Detect
+- TAD2 : Tune Line ADC ( ? )
+- FMF : Estimated first IF Center frequency Offset ( ? )
+- FM1CAL : Calibration done bit
+- TEMP : On chip temperature sensor
+- FMCG : Mixer 1 Cap Gain ( ? )
+- GP01 / GP02 : Programmable digital outputs. Unconnected pins ?
+- V1CSE : LO1 VCO Automatic Capacitor Select Enable ( ? )
+- V1CS : LO1 Capacitor Selection Value ( ? )
+- LOTO : LO Timeout ( ? )
+- VGAG : Tuner Output gain
+-*/
+-
+-#define I2C_ADDRESS 0x60
+-
+-#define REG_PART_REV 0
+-#define REG_LO1C1 1
+-#define REG_LO1C2 2
+-#define REG_LO2C1 3
+-#define REG_LO2C2 4
+-#define REG_LO2C3 5
+-#define REG_LO_STATUS 6
+-#define REG_FM_FREQ 7
+-#define REG_MISC_STAT 8
+-#define REG_MISC_CTRL 9
+-#define REG_RESERVED_A 0x0A
+-#define REG_VGAG 0x0B
+-#define REG_LO1B1 0x0C
+-#define REG_LO1B2 0x0D
+-#define REG_LOTO 0x11
+-
+-#define PART_REV 0x63 // The current driver works only with PART=6 and REV=3 chips
+-
+-struct mt2060_priv {
+- struct mt2060_config *cfg;
+- struct i2c_adapter *i2c;
+-
+- u32 frequency;
+- u32 bandwidth;
+- u16 if1_freq;
+- u8 fmfreq;
+-};
+-
+-#endif
+diff --git a/drivers/media/dvb/frontends/mt2131.c b/drivers/media/dvb/frontends/mt2131.c
+deleted file mode 100644
+index 13cf166..0000000
+--- a/drivers/media/dvb/frontends/mt2131.c
++++ /dev/null
+@@ -1,314 +0,0 @@
+-/*
+- * Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
+- *
+- * Copyright (c) 2006 Steven Toth <stoth at hauppauge.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- *
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/delay.h>
+-#include <linux/dvb/frontend.h>
+-#include <linux/i2c.h>
+-
+-#include "dvb_frontend.h"
+-
+-#include "mt2131.h"
+-#include "mt2131_priv.h"
+-
+-static int debug;
+-module_param(debug, int, 0644);
+-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+-
+-#define dprintk(level,fmt, arg...) if (debug >= level) \
+- printk(KERN_INFO "%s: " fmt, "mt2131", ## arg)
+-
+-static u8 mt2131_config1[] = {
+- 0x01,
+- 0x50, 0x00, 0x50, 0x80, 0x00, 0x49, 0xfa, 0x88,
+- 0x08, 0x77, 0x41, 0x04, 0x00, 0x00, 0x00, 0x32,
+- 0x7f, 0xda, 0x4c, 0x00, 0x10, 0xaa, 0x78, 0x80,
+- 0xff, 0x68, 0xa0, 0xff, 0xdd, 0x00, 0x00
+-};
+-
+-static u8 mt2131_config2[] = {
+- 0x10,
+- 0x7f, 0xc8, 0x0a, 0x5f, 0x00, 0x04
+-};
+-
+-static int mt2131_readreg(struct mt2131_priv *priv, u8 reg, u8 *val)
+-{
+- struct i2c_msg msg[2] = {
+- { .addr = priv->cfg->i2c_address, .flags = 0,
+- .buf = ®, .len = 1 },
+- { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD,
+- .buf = val, .len = 1 },
+- };
+-
+- if (i2c_transfer(priv->i2c, msg, 2) != 2) {
+- printk(KERN_WARNING "mt2131 I2C read failed\n");
+- return -EREMOTEIO;
+- }
+- return 0;
+-}
+-
+-static int mt2131_writereg(struct mt2131_priv *priv, u8 reg, u8 val)
+-{
+- u8 buf[2] = { reg, val };
+- struct i2c_msg msg = { .addr = priv->cfg->i2c_address, .flags = 0,
+- .buf = buf, .len = 2 };
+-
+- if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+- printk(KERN_WARNING "mt2131 I2C write failed\n");
+- return -EREMOTEIO;
+- }
+- return 0;
+-}
+-
+-static int mt2131_writeregs(struct mt2131_priv *priv,u8 *buf, u8 len)
+-{
+- struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
+- .flags = 0, .buf = buf, .len = len };
+-
+- if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+- printk(KERN_WARNING "mt2131 I2C write failed (len=%i)\n",
+- (int)len);
+- return -EREMOTEIO;
+- }
+- return 0;
+-}
+-
+-static int mt2131_set_params(struct dvb_frontend *fe,
+- struct dvb_frontend_parameters *params)
+-{
+- struct mt2131_priv *priv;
+- int ret=0, i;
+- u32 freq;
+- u8 if_band_center;
+- u32 f_lo1, f_lo2;
+- u32 div1, num1, div2, num2;
+- u8 b[8];
+- u8 lockval = 0;
+-
+- priv = fe->tuner_priv;
+- if (fe->ops.info.type == FE_OFDM)
+- priv->bandwidth = params->u.ofdm.bandwidth;
+- else
+- priv->bandwidth = 0;
+-
+- freq = params->frequency / 1000; // Hz -> kHz
+- dprintk(1, "%s() freq=%d\n", __FUNCTION__, freq);
+-
+- f_lo1 = freq + MT2131_IF1 * 1000;
+- f_lo1 = (f_lo1 / 250) * 250;
+- f_lo2 = f_lo1 - freq - MT2131_IF2;
+-
+- priv->frequency = (f_lo1 - f_lo2 - MT2131_IF2) * 1000;
+-
+- /* Frequency LO1 = 16MHz * (DIV1 + NUM1/8192 ) */
+- num1 = f_lo1 * 64 / (MT2131_FREF / 128);
+- div1 = num1 / 8192;
+- num1 &= 0x1fff;
+-
+- /* Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 ) */
+- num2 = f_lo2 * 64 / (MT2131_FREF / 128);
+- div2 = num2 / 8192;
+- num2 &= 0x1fff;
+-
+- if (freq <= 82500) if_band_center = 0x00; else
+- if (freq <= 137500) if_band_center = 0x01; else
+- if (freq <= 192500) if_band_center = 0x02; else
+- if (freq <= 247500) if_band_center = 0x03; else
+- if (freq <= 302500) if_band_center = 0x04; else
+- if (freq <= 357500) if_band_center = 0x05; else
+- if (freq <= 412500) if_band_center = 0x06; else
+- if (freq <= 467500) if_band_center = 0x07; else
+- if (freq <= 522500) if_band_center = 0x08; else
+- if (freq <= 577500) if_band_center = 0x09; else
+- if (freq <= 632500) if_band_center = 0x0A; else
+- if (freq <= 687500) if_band_center = 0x0B; else
+- if (freq <= 742500) if_band_center = 0x0C; else
+- if (freq <= 797500) if_band_center = 0x0D; else
+- if (freq <= 852500) if_band_center = 0x0E; else
+- if (freq <= 907500) if_band_center = 0x0F; else
+- if (freq <= 962500) if_band_center = 0x10; else
+- if (freq <= 1017500) if_band_center = 0x11; else
+- if (freq <= 1072500) if_band_center = 0x12; else if_band_center = 0x13;
+-
+- b[0] = 1;
+- b[1] = (num1 >> 5) & 0xFF;
+- b[2] = (num1 & 0x1F);
+- b[3] = div1;
+- b[4] = (num2 >> 5) & 0xFF;
+- b[5] = num2 & 0x1F;
+- b[6] = div2;
+-
+- dprintk(1, "IF1: %dMHz IF2: %dMHz\n", MT2131_IF1, MT2131_IF2);
+- dprintk(1, "PLL freq=%dkHz band=%d\n", (int)freq, (int)if_band_center);
+- dprintk(1, "PLL f_lo1=%dkHz f_lo2=%dkHz\n", (int)f_lo1, (int)f_lo2);
+- dprintk(1, "PLL div1=%d num1=%d div2=%d num2=%d\n",
+- (int)div1, (int)num1, (int)div2, (int)num2);
+- dprintk(1, "PLL [1..6]: %2x %2x %2x %2x %2x %2x\n",
+- (int)b[1], (int)b[2], (int)b[3], (int)b[4], (int)b[5],
+- (int)b[6]);
+-
+- ret = mt2131_writeregs(priv,b,7);
+- if (ret < 0)
+- return ret;
+-
+- mt2131_writereg(priv, 0x0b, if_band_center);
+-
+- /* Wait for lock */
+- i = 0;
+- do {
+- mt2131_readreg(priv, 0x08, &lockval);
+- if ((lockval & 0x88) == 0x88)
+- break;
+- msleep(4);
+- i++;
+- } while (i < 10);
+-
+- return ret;
+-}
+-
+-static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+-{
+- struct mt2131_priv *priv = fe->tuner_priv;
+- dprintk(1, "%s()\n", __FUNCTION__);
+- *frequency = priv->frequency;
+- return 0;
+-}
+-
+-static int mt2131_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+-{
+- struct mt2131_priv *priv = fe->tuner_priv;
+- dprintk(1, "%s()\n", __FUNCTION__);
+- *bandwidth = priv->bandwidth;
+- return 0;
+-}
+-
+-static int mt2131_get_status(struct dvb_frontend *fe, u32 *status)
+-{
+- struct mt2131_priv *priv = fe->tuner_priv;
+- u8 lock_status = 0;
+- u8 afc_status = 0;
+-
+- *status = 0;
+-
+- mt2131_readreg(priv, 0x08, &lock_status);
+- if ((lock_status & 0x88) == 0x88)
+- *status = TUNER_STATUS_LOCKED;
+-
+- mt2131_readreg(priv, 0x09, &afc_status);
+- dprintk(1, "%s() - LO Status = 0x%x, AFC Status = 0x%x\n",
+- __FUNCTION__, lock_status, afc_status);
+-
+- return 0;
+-}
+-
+-static int mt2131_init(struct dvb_frontend *fe)
+-{
+- struct mt2131_priv *priv = fe->tuner_priv;
+- int ret;
+- dprintk(1, "%s()\n", __FUNCTION__);
+-
+- if ((ret = mt2131_writeregs(priv, mt2131_config1,
+- sizeof(mt2131_config1))) < 0)
+- return ret;
+-
+- mt2131_writereg(priv, 0x0b, 0x09);
+- mt2131_writereg(priv, 0x15, 0x47);
+- mt2131_writereg(priv, 0x07, 0xf2);
+- mt2131_writereg(priv, 0x0b, 0x01);
+-
+- if ((ret = mt2131_writeregs(priv, mt2131_config2,
+- sizeof(mt2131_config2))) < 0)
+- return ret;
+-
+- return ret;
+-}
+-
+-static int mt2131_release(struct dvb_frontend *fe)
+-{
+- dprintk(1, "%s()\n", __FUNCTION__);
+- kfree(fe->tuner_priv);
+- fe->tuner_priv = NULL;
+- return 0;
+-}
+-
+-static const struct dvb_tuner_ops mt2131_tuner_ops = {
+- .info = {
+- .name = "Microtune MT2131",
+- .frequency_min = 48000000,
+- .frequency_max = 860000000,
+- .frequency_step = 50000,
+- },
+-
+- .release = mt2131_release,
+- .init = mt2131_init,
+-
+- .set_params = mt2131_set_params,
+- .get_frequency = mt2131_get_frequency,
+- .get_bandwidth = mt2131_get_bandwidth,
+- .get_status = mt2131_get_status
+-};
+-
+-struct dvb_frontend * mt2131_attach(struct dvb_frontend *fe,
+- struct i2c_adapter *i2c,
+- struct mt2131_config *cfg, u16 if1)
+-{
+- struct mt2131_priv *priv = NULL;
+- u8 id = 0;
+-
+- dprintk(1, "%s()\n", __FUNCTION__);
+-
+- priv = kzalloc(sizeof(struct mt2131_priv), GFP_KERNEL);
+- if (priv == NULL)
+- return NULL;
+-
+- priv->cfg = cfg;
+- priv->bandwidth = 6000000; /* 6MHz */
+- priv->i2c = i2c;
+-
+- if (mt2131_readreg(priv, 0, &id) != 0) {
+- kfree(priv);
+- return NULL;
+- }
+- if ( (id != 0x3E) && (id != 0x3F) ) {
+- printk(KERN_ERR "MT2131: Device not found at addr 0x%02x\n",
+- cfg->i2c_address);
+- kfree(priv);
+- return NULL;
+- }
+-
+- printk(KERN_INFO "MT2131: successfully identified at address 0x%02x\n",
+- cfg->i2c_address);
+- memcpy(&fe->ops.tuner_ops, &mt2131_tuner_ops,
+- sizeof(struct dvb_tuner_ops));
+-
+- fe->tuner_priv = priv;
+- return fe;
+-}
+-EXPORT_SYMBOL(mt2131_attach);
+-
+-MODULE_AUTHOR("Steven Toth");
+-MODULE_DESCRIPTION("Microtune MT2131 silicon tuner driver");
+-MODULE_LICENSE("GPL");
+-
+-/*
+- * Local variables:
+- * c-basic-offset: 8
+- */
+diff --git a/drivers/media/dvb/frontends/mt2131.h b/drivers/media/dvb/frontends/mt2131.h
+deleted file mode 100644
+index 1e4ffe7..0000000
+--- a/drivers/media/dvb/frontends/mt2131.h
++++ /dev/null
+@@ -1,54 +0,0 @@
+-/*
+- * Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
+- *
+- * Copyright (c) 2006 Steven Toth <stoth at hauppauge.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- *
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#ifndef __MT2131_H__
+-#define __MT2131_H__
+-
+-struct dvb_frontend;
+-struct i2c_adapter;
+-
+-struct mt2131_config {
+- u8 i2c_address;
+- u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */
+-};
+-
+-#if defined(CONFIG_DVB_TUNER_MT2131) || (defined(CONFIG_DVB_TUNER_MT2131_MODULE) && defined(MODULE))
+-extern struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
+- struct i2c_adapter *i2c,
+- struct mt2131_config *cfg,
+- u16 if1);
+-#else
+-static inline struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
+- struct i2c_adapter *i2c,
+- struct mt2131_config *cfg,
+- u16 if1)
+-{
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+- return NULL;
+-}
+-#endif /* CONFIG_DVB_TUNER_MT2131 */
+-
+-#endif /* __MT2131_H__ */
+-
+-/*
+- * Local variables:
+- * c-basic-offset: 8
+- */
+diff --git a/drivers/media/dvb/frontends/mt2131_priv.h b/drivers/media/dvb/frontends/mt2131_priv.h
+deleted file mode 100644
+index e930759..0000000
+--- a/drivers/media/dvb/frontends/mt2131_priv.h
++++ /dev/null
+@@ -1,49 +0,0 @@
+-/*
+- * Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
+- *
+- * Copyright (c) 2006 Steven Toth <stoth at hauppauge.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- *
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#ifndef __MT2131_PRIV_H__
+-#define __MT2131_PRIV_H__
+-
+-/* Regs */
+-#define MT2131_PWR 0x07
+-#define MT2131_UPC_1 0x0b
+-#define MT2131_AGC_RL 0x10
+-#define MT2131_MISC_2 0x15
+-
+-/* frequency values in KHz */
+-#define MT2131_IF1 1220
+-#define MT2131_IF2 44000
+-#define MT2131_FREF 16000
+-
+-struct mt2131_priv {
+- struct mt2131_config *cfg;
+- struct i2c_adapter *i2c;
+-
+- u32 frequency;
+- u32 bandwidth;
+-};
+-
+-#endif /* __MT2131_PRIV_H__ */
+-
+-/*
+- * Local variables:
+- * c-basic-offset: 8
+- */
+diff --git a/drivers/media/dvb/frontends/mt2266.c b/drivers/media/dvb/frontends/mt2266.c
+deleted file mode 100644
+index 54b18f9..0000000
+--- a/drivers/media/dvb/frontends/mt2266.c
++++ /dev/null
+@@ -1,351 +0,0 @@
+-/*
+- * Driver for Microtune MT2266 "Direct conversion low power broadband tuner"
+- *
+- * Copyright (c) 2007 Olivier DANET <odanet at caramail.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/delay.h>
+-#include <linux/dvb/frontend.h>
+-#include <linux/i2c.h>
+-
+-#include "dvb_frontend.h"
+-#include "mt2266.h"
+-
+-#define I2C_ADDRESS 0x60
+-
+-#define REG_PART_REV 0
+-#define REG_TUNE 1
+-#define REG_BAND 6
+-#define REG_BANDWIDTH 8
+-#define REG_LOCK 0x12
+-
+-#define PART_REV 0x85
+-
+-struct mt2266_priv {
+- struct mt2266_config *cfg;
+- struct i2c_adapter *i2c;
+-
+- u32 frequency;
+- u32 bandwidth;
+- u8 band;
+-};
+-
+-#define MT2266_VHF 1
+-#define MT2266_UHF 0
+-
+-/* Here, frequencies are expressed in kiloHertz to avoid 32 bits overflows */
+-
+-static int debug;
+-module_param(debug, int, 0644);
+-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+-
+-#define dprintk(args...) do { if (debug) {printk(KERN_DEBUG "MT2266: " args); printk("\n"); }} while (0)
+-
+-// Reads a single register
+-static int mt2266_readreg(struct mt2266_priv *priv, u8 reg, u8 *val)
+-{
+- struct i2c_msg msg[2] = {
+- { .addr = priv->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 },
+- { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val, .len = 1 },
+- };
+- if (i2c_transfer(priv->i2c, msg, 2) != 2) {
+- printk(KERN_WARNING "MT2266 I2C read failed\n");
+- return -EREMOTEIO;
+- }
+- return 0;
+-}
+-
+-// Writes a single register
+-static int mt2266_writereg(struct mt2266_priv *priv, u8 reg, u8 val)
+-{
+- u8 buf[2] = { reg, val };
+- struct i2c_msg msg = {
+- .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2
+- };
+- if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+- printk(KERN_WARNING "MT2266 I2C write failed\n");
+- return -EREMOTEIO;
+- }
+- return 0;
+-}
+-
+-// Writes a set of consecutive registers
+-static int mt2266_writeregs(struct mt2266_priv *priv,u8 *buf, u8 len)
+-{
+- struct i2c_msg msg = {
+- .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = len
+- };
+- if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+- printk(KERN_WARNING "MT2266 I2C write failed (len=%i)\n",(int)len);
+- return -EREMOTEIO;
+- }
+- return 0;
+-}
+-
+-// Initialisation sequences
+-static u8 mt2266_init1[] = { REG_TUNE, 0x00, 0x00, 0x28,
+- 0x00, 0x52, 0x99, 0x3f };
+-
+-static u8 mt2266_init2[] = {
+- 0x17, 0x6d, 0x71, 0x61, 0xc0, 0xbf, 0xff, 0xdc, 0x00, 0x0a, 0xd4,
+- 0x03, 0x64, 0x64, 0x64, 0x64, 0x22, 0xaa, 0xf2, 0x1e, 0x80, 0x14,
+- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7f, 0x5e, 0x3f, 0xff, 0xff,
+- 0xff, 0x00, 0x77, 0x0f, 0x2d
+-};
+-
+-static u8 mt2266_init_8mhz[] = { REG_BANDWIDTH, 0x22, 0x22, 0x22, 0x22,
+- 0x22, 0x22, 0x22, 0x22 };
+-
+-static u8 mt2266_init_7mhz[] = { REG_BANDWIDTH, 0x32, 0x32, 0x32, 0x32,
+- 0x32, 0x32, 0x32, 0x32 };
+-
+-static u8 mt2266_init_6mhz[] = { REG_BANDWIDTH, 0xa7, 0xa7, 0xa7, 0xa7,
+- 0xa7, 0xa7, 0xa7, 0xa7 };
+-
+-static u8 mt2266_uhf[] = { 0x1d, 0xdc, 0x00, 0x0a, 0xd4, 0x03, 0x64, 0x64,
+- 0x64, 0x64, 0x22, 0xaa, 0xf2, 0x1e, 0x80, 0x14 };
+-
+-static u8 mt2266_vhf[] = { 0x1d, 0xfe, 0x00, 0x00, 0xb4, 0x03, 0xa5, 0xa5,
+- 0xa5, 0xa5, 0x82, 0xaa, 0xf1, 0x17, 0x80, 0x1f };
+-
+-#define FREF 30000 // Quartz oscillator 30 MHz
+-
+-static int mt2266_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+-{
+- struct mt2266_priv *priv;
+- int ret=0;
+- u32 freq;
+- u32 tune;
+- u8 lnaband;
+- u8 b[10];
+- int i;
+- u8 band;
+-
+- priv = fe->tuner_priv;
+-
+- freq = params->frequency / 1000; // Hz -> kHz
+- if (freq < 470000 && freq > 230000)
+- return -EINVAL; /* Gap between VHF and UHF bands */
+- priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+- priv->frequency = freq * 1000;
+-
+- tune = 2 * freq * (8192/16) / (FREF/16);
+- band = (freq < 300000) ? MT2266_VHF : MT2266_UHF;
+- if (band == MT2266_VHF)
+- tune *= 2;
+-
+- switch (params->u.ofdm.bandwidth) {
+- case BANDWIDTH_6_MHZ:
+- mt2266_writeregs(priv, mt2266_init_6mhz,
+- sizeof(mt2266_init_6mhz));
+- break;
+- case BANDWIDTH_7_MHZ:
+- mt2266_writeregs(priv, mt2266_init_7mhz,
+- sizeof(mt2266_init_7mhz));
+- break;
+- case BANDWIDTH_8_MHZ:
+- default:
+- mt2266_writeregs(priv, mt2266_init_8mhz,
+- sizeof(mt2266_init_8mhz));
+- break;
+- }
+-
+- if (band == MT2266_VHF && priv->band == MT2266_UHF) {
+- dprintk("Switch from UHF to VHF");
+- mt2266_writereg(priv, 0x05, 0x04);
+- mt2266_writereg(priv, 0x19, 0x61);
+- mt2266_writeregs(priv, mt2266_vhf, sizeof(mt2266_vhf));
+- } else if (band == MT2266_UHF && priv->band == MT2266_VHF) {
+- dprintk("Switch from VHF to UHF");
+- mt2266_writereg(priv, 0x05, 0x52);
+- mt2266_writereg(priv, 0x19, 0x61);
+- mt2266_writeregs(priv, mt2266_uhf, sizeof(mt2266_uhf));
+- }
+- msleep(10);
+-
+- if (freq <= 495000)
+- lnaband = 0xEE;
+- else if (freq <= 525000)
+- lnaband = 0xDD;
+- else if (freq <= 550000)
+- lnaband = 0xCC;
+- else if (freq <= 580000)
+- lnaband = 0xBB;
+- else if (freq <= 605000)
+- lnaband = 0xAA;
+- else if (freq <= 630000)
+- lnaband = 0x99;
+- else if (freq <= 655000)
+- lnaband = 0x88;
+- else if (freq <= 685000)
+- lnaband = 0x77;
+- else if (freq <= 710000)
+- lnaband = 0x66;
+- else if (freq <= 735000)
+- lnaband = 0x55;
+- else if (freq <= 765000)
+- lnaband = 0x44;
+- else if (freq <= 802000)
+- lnaband = 0x33;
+- else if (freq <= 840000)
+- lnaband = 0x22;
+- else
+- lnaband = 0x11;
+-
+- b[0] = REG_TUNE;
+- b[1] = (tune >> 8) & 0x1F;
+- b[2] = tune & 0xFF;
+- b[3] = tune >> 13;
+- mt2266_writeregs(priv,b,4);
+-
+- dprintk("set_parms: tune=%d band=%d %s",
+- (int) tune, (int) lnaband,
+- (band == MT2266_UHF) ? "UHF" : "VHF");
+- dprintk("set_parms: [1..3]: %2x %2x %2x",
+- (int) b[1], (int) b[2], (int)b[3]);
+-
+- if (band == MT2266_UHF) {
+- b[0] = 0x05;
+- b[1] = (priv->band == MT2266_VHF) ? 0x52 : 0x62;
+- b[2] = lnaband;
+- mt2266_writeregs(priv, b, 3);
+- }
+-
+- /* Wait for pll lock or timeout */
+- i = 0;
+- do {
+- mt2266_readreg(priv,REG_LOCK,b);
+- if (b[0] & 0x40)
+- break;
+- msleep(10);
+- i++;
+- } while (i<10);
+- dprintk("Lock when i=%i",(int)i);
+-
+- if (band == MT2266_UHF && priv->band == MT2266_VHF)
+- mt2266_writereg(priv, 0x05, 0x62);
+-
+- priv->band = band;
+-
+- return ret;
+-}
+-
+-static void mt2266_calibrate(struct mt2266_priv *priv)
+-{
+- mt2266_writereg(priv, 0x11, 0x03);
+- mt2266_writereg(priv, 0x11, 0x01);
+- mt2266_writeregs(priv, mt2266_init1, sizeof(mt2266_init1));
+- mt2266_writeregs(priv, mt2266_init2, sizeof(mt2266_init2));
+- mt2266_writereg(priv, 0x33, 0x5e);
+- mt2266_writereg(priv, 0x10, 0x10);
+- mt2266_writereg(priv, 0x10, 0x00);
+- mt2266_writeregs(priv, mt2266_init_8mhz, sizeof(mt2266_init_8mhz));
+- msleep(25);
+- mt2266_writereg(priv, 0x17, 0x6d);
+- mt2266_writereg(priv, 0x1c, 0x00);
+- msleep(75);
+- mt2266_writereg(priv, 0x17, 0x6d);
+- mt2266_writereg(priv, 0x1c, 0xff);
+-}
+-
+-static int mt2266_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+-{
+- struct mt2266_priv *priv = fe->tuner_priv;
+- *frequency = priv->frequency;
+- return 0;
+-}
+-
+-static int mt2266_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+-{
+- struct mt2266_priv *priv = fe->tuner_priv;
+- *bandwidth = priv->bandwidth;
+- return 0;
+-}
+-
+-static int mt2266_init(struct dvb_frontend *fe)
+-{
+- int ret;
+- struct mt2266_priv *priv = fe->tuner_priv;
+- ret = mt2266_writereg(priv, 0x17, 0x6d);
+- if (ret < 0)
+- return ret;
+- ret = mt2266_writereg(priv, 0x1c, 0xff);
+- if (ret < 0)
+- return ret;
+- return 0;
+-}
+-
+-static int mt2266_sleep(struct dvb_frontend *fe)
+-{
+- struct mt2266_priv *priv = fe->tuner_priv;
+- mt2266_writereg(priv, 0x17, 0x6d);
+- mt2266_writereg(priv, 0x1c, 0x00);
+- return 0;
+-}
+-
+-static int mt2266_release(struct dvb_frontend *fe)
+-{
+- kfree(fe->tuner_priv);
+- fe->tuner_priv = NULL;
+- return 0;
+-}
+-
+-static const struct dvb_tuner_ops mt2266_tuner_ops = {
+- .info = {
+- .name = "Microtune MT2266",
+- .frequency_min = 174000000,
+- .frequency_max = 862000000,
+- .frequency_step = 50000,
+- },
+- .release = mt2266_release,
+- .init = mt2266_init,
+- .sleep = mt2266_sleep,
+- .set_params = mt2266_set_params,
+- .get_frequency = mt2266_get_frequency,
+- .get_bandwidth = mt2266_get_bandwidth
+-};
+-
+-struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg)
+-{
+- struct mt2266_priv *priv = NULL;
+- u8 id = 0;
+-
+- priv = kzalloc(sizeof(struct mt2266_priv), GFP_KERNEL);
+- if (priv == NULL)
+- return NULL;
+-
+- priv->cfg = cfg;
+- priv->i2c = i2c;
+- priv->band = MT2266_UHF;
+-
+- if (mt2266_readreg(priv, 0, &id)) {
+- kfree(priv);
+- return NULL;
+- }
+- if (id != PART_REV) {
+- kfree(priv);
+- return NULL;
+- }
+- printk(KERN_INFO "MT2266: successfully identified\n");
+- memcpy(&fe->ops.tuner_ops, &mt2266_tuner_ops, sizeof(struct dvb_tuner_ops));
+-
+- fe->tuner_priv = priv;
+- mt2266_calibrate(priv);
+- return fe;
+-}
+-EXPORT_SYMBOL(mt2266_attach);
+-
+-MODULE_AUTHOR("Olivier DANET");
+-MODULE_DESCRIPTION("Microtune MT2266 silicon tuner driver");
+-MODULE_LICENSE("GPL");
+diff --git a/drivers/media/dvb/frontends/mt2266.h b/drivers/media/dvb/frontends/mt2266.h
+deleted file mode 100644
+index f31dd61..0000000
+--- a/drivers/media/dvb/frontends/mt2266.h
++++ /dev/null
+@@ -1,37 +0,0 @@
+-/*
+- * Driver for Microtune MT2266 "Direct conversion low power broadband tuner"
+- *
+- * Copyright (c) 2007 Olivier DANET <odanet at caramail.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- */
+-
+-#ifndef MT2266_H
+-#define MT2266_H
+-
+-struct dvb_frontend;
+-struct i2c_adapter;
+-
+-struct mt2266_config {
+- u8 i2c_address;
+-};
+-
+-#if defined(CONFIG_DVB_TUNER_MT2266) || (defined(CONFIG_DVB_TUNER_MT2266_MODULE) && defined(MODULE))
+-extern struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg);
+-#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__);
+- return NULL;
+-}
+-#endif // CONFIG_DVB_TUNER_MT2266
+-
+-#endif
+diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
+index 1638301..081ca33 100644
+--- a/drivers/media/dvb/frontends/mt312.c
++++ b/drivers/media/dvb/frontends/mt312.c
+@@ -1,7 +1,8 @@
+ /*
+- Driver for Zarlink VP310/MT312 Satellite Channel Decoder
++ Driver for Zarlink VP310/MT312/ZL10313 Satellite Channel Decoder
+
+ Copyright (C) 2003 Andreas Oberritter <obi at linuxtv.org>
++ Copyright (C) 2008 Matthias Schwarzott <zzam at gentoo.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+@@ -43,7 +44,8 @@ struct mt312_state {
+ struct dvb_frontend frontend;
+
+ u8 id;
+- u8 frequency;
++ unsigned long xtal;
++ u8 freq_mult;
+ };
+
+ static int debug;
+@@ -53,12 +55,11 @@ static int debug;
+ printk(KERN_DEBUG "mt312: " args); \
+ } while (0)
+
+-#define MT312_SYS_CLK 90000000UL /* 90 MHz */
+-#define MT312_LPOWER_SYS_CLK 60000000UL /* 60 MHz */
+ #define MT312_PLL_CLK 10000000UL /* 10 MHz */
++#define MT312_PLL_CLK_10_111 10111000UL /* 10.111 MHz */
+
+ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
+- void *buf, const size_t count)
++ u8 *buf, const size_t count)
+ {
+ int ret;
+ struct i2c_msg msg[2];
+@@ -76,7 +77,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2) {
+- printk(KERN_ERR "%s: ret == %d\n", __FUNCTION__, ret);
++ printk(KERN_ERR "%s: ret == %d\n", __func__, ret);
+ return -EREMOTEIO;
+ }
+
+@@ -84,7 +85,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
+ int i;
+ dprintk("R(%d):", reg & 0x7f);
+ for (i = 0; i < count; i++)
+- printk(" %02x", ((const u8 *) buf)[i]);
++ printk(" %02x", buf[i]);
+ printk("\n");
+ }
+
+@@ -92,7 +93,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
+ }
+
+ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
+- const void *src, const size_t count)
++ const u8 *src, const size_t count)
+ {
+ int ret;
+ u8 buf[count + 1];
+@@ -102,7 +103,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
+ int i;
+ dprintk("W(%d):", reg & 0x7f);
+ for (i = 0; i < count; i++)
+- printk(" %02x", ((const u8 *) src)[i]);
++ printk(" %02x", src[i]);
+ printk("\n");
+ }
+
+@@ -117,7 +118,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
+ ret = i2c_transfer(state->i2c, &msg, 1);
+
+ if (ret != 1) {
+- dprintk("%s: ret == %d\n", __FUNCTION__, ret);
++ dprintk("%s: ret == %d\n", __func__, ret);
+ return -EREMOTEIO;
+ }
+
+@@ -209,7 +210,7 @@ static int mt312_get_symbol_rate(struct mt312_state *state, u32 *sr)
+ dprintk("sym_rat_op=%d dec_ratio=%d\n",
+ sym_rat_op, dec_ratio);
+ dprintk("*sr(manual) = %lu\n",
+- (((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) *
++ (((state->xtal * 8192) / (sym_rat_op + 8192)) *
+ 2) - dec_ratio);
+ }
+
+@@ -242,7 +243,7 @@ static int mt312_initfe(struct dvb_frontend *fe)
+
+ /* wake up */
+ ret = mt312_writereg(state, CONFIG,
+- (state->frequency == 60 ? 0x88 : 0x8c));
++ (state->freq_mult == 6 ? 0x88 : 0x8c));
+ if (ret < 0)
+ return ret;
+
+@@ -265,12 +266,37 @@ static int mt312_initfe(struct dvb_frontend *fe)
+ return ret;
+ }
+
++ switch (state->id) {
++ case ID_ZL10313:
++ /* enable ADC */
++ ret = mt312_writereg(state, GPP_CTRL, 0x80);
++ if (ret < 0)
++ return ret;
++
++ /* configure ZL10313 for optimal ADC performance */
++ buf[0] = 0x80;
++ buf[1] = 0xB0;
++ ret = mt312_write(state, HW_CTRL, buf, 2);
++ if (ret < 0)
++ return ret;
++
++ /* enable MPEG output and ADCs */
++ ret = mt312_writereg(state, HW_CTRL, 0x00);
++ if (ret < 0)
++ return ret;
++
++ ret = mt312_writereg(state, MPEG_CTRL, 0x00);
++ if (ret < 0)
++ return ret;
++
++ break;
++ }
++
+ /* SYS_CLK */
+- buf[0] = mt312_div((state->frequency == 60 ? MT312_LPOWER_SYS_CLK :
+- MT312_SYS_CLK) * 2, 1000000);
++ buf[0] = mt312_div(state->xtal * state->freq_mult * 2, 1000000);
+
+ /* DISEQC_RATIO */
+- buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4);
++ buf[1] = mt312_div(state->xtal, 22000 * 4);
+
+ ret = mt312_write(state, SYS_CLK, buf, sizeof(buf));
+ if (ret < 0)
+@@ -280,7 +306,17 @@ static int mt312_initfe(struct dvb_frontend *fe)
+ if (ret < 0)
+ return ret;
+
+- ret = mt312_writereg(state, OP_CTRL, 0x53);
++ /* different MOCLK polarity */
++ switch (state->id) {
++ case ID_ZL10313:
++ buf[0] = 0x33;
++ break;
++ default:
++ buf[0] = 0x53;
++ break;
++ }
++
++ ret = mt312_writereg(state, OP_CTRL, buf[0]);
+ if (ret < 0)
+ return ret;
+
+@@ -323,6 +359,9 @@ static int mt312_send_master_cmd(struct dvb_frontend *fe,
+ if (ret < 0)
+ return ret;
+
++ /* is there a better way to wait for message to be transmitted */
++ msleep(100);
++
+ /* set DISEQC_MODE[2:0] to zero if a return message is expected */
+ if (c->msg[0] & 0x02) {
+ ret = mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40));
+@@ -383,11 +422,16 @@ static int mt312_set_voltage(struct dvb_frontend *fe, const fe_sec_voltage_t v)
+ {
+ struct mt312_state *state = fe->demodulator_priv;
+ const u8 volt_tab[3] = { 0x00, 0x40, 0x00 };
++ u8 val;
+
+ if (v > SEC_VOLTAGE_OFF)
+ return -EINVAL;
+
+- return mt312_writereg(state, DISEQC_MODE, volt_tab[v]);
++ val = volt_tab[v];
++ if (state->config->voltage_inverted)
++ val ^= 0x40;
++
++ return mt312_writereg(state, DISEQC_MODE, val);
+ }
+
+ static int mt312_read_status(struct dvb_frontend *fe, fe_status_t *s)
+@@ -463,7 +507,7 @@ static int mt312_read_snr(struct dvb_frontend *fe, u16 *snr)
+ int ret;
+ u8 buf[2];
+
+- ret = mt312_read(state, M_SNR_H, &buf, sizeof(buf));
++ ret = mt312_read(state, M_SNR_H, buf, sizeof(buf));
+ if (ret < 0)
+ return ret;
+
+@@ -478,7 +522,7 @@ static int mt312_read_ucblocks(struct dvb_frontend *fe, u32 *ubc)
+ int ret;
+ u8 buf[2];
+
+- ret = mt312_read(state, RS_UBC_H, &buf, sizeof(buf));
++ ret = mt312_read(state, RS_UBC_H, buf, sizeof(buf));
+ if (ret < 0)
+ return ret;
+
+@@ -499,7 +543,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
+ { 0x00, 0x01, 0x02, 0x04, 0x3f, 0x08, 0x10, 0x20, 0x3f, 0x3f };
+ const u8 inv_tab[3] = { 0x00, 0x40, 0x80 };
+
+- dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency);
++ dprintk("%s: Freq %d\n", __func__, p->frequency);
+
+ if ((p->frequency < fe->ops.info.frequency_min)
+ || (p->frequency > fe->ops.info.frequency_max))
+@@ -532,17 +576,17 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
+ return ret;
+ if (p->u.qpsk.symbol_rate >= 30000000) {
+ /* Note that 30MS/s should use 90MHz */
+- if ((config_val & 0x0c) == 0x08) {
++ if (state->freq_mult == 6) {
+ /* We are running 60MHz */
+- state->frequency = 90;
++ state->freq_mult = 9;
+ ret = mt312_initfe(fe);
+ if (ret < 0)
+ return ret;
+ }
+ } else {
+- if ((config_val & 0x0c) == 0x0C) {
++ if (state->freq_mult == 9) {
+ /* We are running 90MHz */
+- state->frequency = 60;
++ state->freq_mult = 6;
+ ret = mt312_initfe(fe);
+ if (ret < 0)
+ return ret;
+@@ -551,6 +595,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
+ break;
+
+ case ID_MT312:
++ case ID_ZL10313:
+ break;
+
+ default:
+@@ -616,11 +661,29 @@ static int mt312_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+ {
+ struct mt312_state *state = fe->demodulator_priv;
+
+- if (enable) {
+- return mt312_writereg(state, GPP_CTRL, 0x40);
+- } else {
+- return mt312_writereg(state, GPP_CTRL, 0x00);
++ u8 val = 0x00;
++ int ret;
++
++ switch (state->id) {
++ case ID_ZL10313:
++ ret = mt312_readreg(state, GPP_CTRL, &val);
++ if (ret < 0)
++ goto error;
++
++ /* preserve this bit to not accidently shutdown ADC */
++ val &= 0x80;
++ break;
+ }
++
++ if (enable)
++ val |= 0x40;
++ else
++ val &= ~0x40;
++
++ ret = mt312_writereg(state, GPP_CTRL, val);
++
++error:
++ return ret;
+ }
+
+ static int mt312_sleep(struct dvb_frontend *fe)
+@@ -634,6 +697,18 @@ static int mt312_sleep(struct dvb_frontend *fe)
+ if (ret < 0)
+ return ret;
+
++ if (state->id == ID_ZL10313) {
++ /* reset ADC */
++ ret = mt312_writereg(state, GPP_CTRL, 0x00);
++ if (ret < 0)
++ return ret;
++
++ /* full shutdown of ADCs, mpeg bus tristated */
++ ret = mt312_writereg(state, HW_CTRL, 0x0d);
++ if (ret < 0)
++ return ret;
++ }
++
+ ret = mt312_readreg(state, CONFIG, &config);
+ if (ret < 0)
+ return ret;
+@@ -661,6 +736,7 @@ static void mt312_release(struct dvb_frontend *fe)
+ kfree(state);
+ }
+
++#define MT312_SYS_CLK 90000000UL /* 90 MHz */
+ static struct dvb_frontend_ops vp310_mt312_ops = {
+
+ .info = {
+@@ -668,8 +744,8 @@ static struct dvb_frontend_ops vp310_mt312_ops = {
+ .type = FE_QPSK,
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+- .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128,
+- .symbol_rate_min = MT312_SYS_CLK / 128,
++ .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, /* FIXME: adjust freq to real used xtal */
++ .symbol_rate_min = MT312_SYS_CLK / 128, /* FIXME as above */
+ .symbol_rate_max = MT312_SYS_CLK / 2,
+ .caps =
+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
+@@ -726,14 +802,21 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
+ switch (state->id) {
+ case ID_VP310:
+ strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S");
+- state->frequency = 90;
++ state->xtal = MT312_PLL_CLK;
++ state->freq_mult = 9;
+ break;
+ case ID_MT312:
+ strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S");
+- state->frequency = 60;
++ state->xtal = MT312_PLL_CLK;
++ state->freq_mult = 6;
++ break;
++ case ID_ZL10313:
++ strcpy(state->frontend.ops.info.name, "Zarlink ZL10313 DVB-S");
++ state->xtal = MT312_PLL_CLK_10_111;
++ state->freq_mult = 9;
+ break;
+ default:
+- printk(KERN_WARNING "Only Zarlink VP310/MT312"
++ printk(KERN_WARNING "Only Zarlink VP310/MT312/ZL10313"
+ " are supported chips.\n");
+ goto error;
}
+@@ -749,7 +832,7 @@ EXPORT_SYMBOL(vp310_mt312_attach);
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
- 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_DESCRIPTION("Zarlink VP310/MT312 DVB-S Demodulator driver");
++MODULE_DESCRIPTION("Zarlink VP310/MT312/ZL10313 DVB-S Demodulator driver");
+ MODULE_AUTHOR("Andreas Oberritter <obi at linuxtv.org>");
MODULE_LICENSE("GPL");
-+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/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;
};
-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.
+ #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 {
- 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.
+ enum mt312_model_id {
+ ID_VP310 = 1,
+- ID_MT312 = 3
++ ID_MT312 = 3,
++ ID_ZL10313 = 5,
+ };
- 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 @@
- */
+ #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)
- #define USB_VENDOR_ID_AIPTEK 0x08ca
-+#define USB_VENDOR_ID_KYE 0x0458
- #define USB_REQ_GET_REPORT 0x01
- #define USB_REQ_SET_REPORT 0x09
+ if (ret != 2) {
+ printk("%s: readreg error (reg=%d, ret==%i)\n",
+- __FUNCTION__, reg, ret);
++ __func__, reg, ret);
+ return ret;
+ }
-@@ -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)},
- {}
- };
+@@ -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)
-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];
- };
+ static u8 mt352_reset_attach [] = { RESET, 0xC0 };
-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));
+- dprintk("%s: hello\n",__FUNCTION__);
++ dprintk("%s: hello\n",__func__);
- 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)
+ 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)
{
- struct wacom *wacom = input_get_drvdata(dev);
+- 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
-+ 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;
+ 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)
-+ mutex_unlock(&wacom->lock);
+ 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
-@@ -135,7 +151,11 @@ static void wacom_close(struct input_dev *dev)
+ 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)
{
- struct wacom *wacom = input_get_drvdata(dev);
+ u8 attr, len2, buf;
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
-+ mutex_lock(&wacom->lock);
- usb_kill_urb(wacom->irq);
-+ wacom->open = 0;
-+ wacom->intf->needs_remote_wakeup = 0;
-+ mutex_unlock(&wacom->lock);
- }
+ /* 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__);
- 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
+ /* 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__);
- 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));
+ /* 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__);
-@@ -304,23 +326,57 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
+ 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__);
- static void wacom_disconnect(struct usb_interface *intf)
+ buf[0] = 0x00;
+ nxt200x_writebytes(state, 0x2b, buf, 1);
+@@ -328,7 +328,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
{
-- struct wacom *wacom = usb_get_intfdata (intf);
-+ struct wacom *wacom = usb_get_intfdata(intf);
+ u8 buf, count = 0;
- 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);
- }
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
- 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,
- };
+ dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[1], data[2], data[3], data[4]);
- 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.
+@@ -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__);
-+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 @@
+ 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;
- # Each configuration option enables a list of files.
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+ dprintk("Firmware is %zu bytes\n", fw->size);
-+wm97xx-ts-y := wm97xx-core.o
-+
- obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
- obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
- obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o
-@@ -19,3 +21,8 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
- obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
- obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
- obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
-+obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
-+wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
-+wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
-+wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
-+obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
-diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
-index 57a1c28..907a45f 100644
---- a/drivers/input/touchscreen/ads7846.c
-+++ b/drivers/input/touchscreen/ads7846.c
-@@ -28,13 +28,6 @@
- #include <linux/spi/ads7846.h>
- #include <asm/irq.h>
+ /* 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;
--#ifdef CONFIG_ARM
--#include <asm/mach-types.h>
--#ifdef CONFIG_ARCH_OMAP
--#include <asm/arch/gpio.h>
--#endif
--#endif
--
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+ dprintk("Firmware is %zu bytes\n", fw->size);
- /*
- * This code has been heavily tested on a Nokia 770, and lightly
-@@ -87,6 +80,7 @@ struct ads7846 {
- #endif
+ /* 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;
+ };
- 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");
+-static int debug = 0;
++static int debug;
+ #define dprintk if (debug) printk
- 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;
+ 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)); })
- if (!req)
-@@ -270,13 +260,13 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
+ /* 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 (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;
+ 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");
- kfree(req);
-- return status ? status : sample;
-+ return status;
- }
+ /* Calculate SNR using noise, c, and NTSC rejection correction */
+ state->snr = calculate_snr(noise, c) - usK;
+ *snr = (state->snr) >> 16;
- #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;
+- 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);
- /* external resistors may scale vAUX into 0..vREF */
-- retval *= vREF_mV;
-+ retval *= ts->vref_mv;
- retval = retval >> 12;
- return retval;
+ 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;
}
-@@ -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)
+ #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)
- ts->spi = spi;
- ts->input = input_dev;
-+ ts->vref_mv = pdata->vref_mv;
+ 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;
+ }
- hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- ts->timer.function = ads7846_timer;
-@@ -1174,31 +1165,6 @@ static struct spi_driver ads7846_driver = {
+ state->snr = calculate_snr(rec_buf[0], 89599047);
+ *snr = (state->snr) >> 16;
- static int __init ads7846_init(void)
+- 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)
{
-- /* grr, board-specific init should stay out of drivers!! */
+- 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.c b/drivers/media/dvb/frontends/qt1010.c
+deleted file mode 100644
+index 825aa14..0000000
+--- a/drivers/media/dvb/frontends/qt1010.c
++++ /dev/null
+@@ -1,485 +0,0 @@
+-/*
+- * Driver for Quantek QT1010 silicon tuner
+- *
+- * Copyright (C) 2006 Antti Palosaari <crope at iki.fi>
+- * Aapo Tahkola <aet at rasterburn.org>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-#include "qt1010.h"
+-#include "qt1010_priv.h"
-
--#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);
+-static int debug;
+-module_param(debug, int, 0644);
+-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+-
+-#define dprintk(args...) \
+- do { \
+- if (debug) printk(KERN_DEBUG "QT1010: " args); \
+- } while (0)
+-
+-/* read single register */
+-static int qt1010_readreg(struct qt1010_priv *priv, u8 reg, u8 *val)
+-{
+- struct i2c_msg msg[2] = {
+- { .addr = priv->cfg->i2c_address,
+- .flags = 0, .buf = ®, .len = 1 },
+- { .addr = priv->cfg->i2c_address,
+- .flags = I2C_M_RD, .buf = val, .len = 1 },
+- };
+-
+- if (i2c_transfer(priv->i2c, msg, 2) != 2) {
+- printk(KERN_WARNING "qt1010 I2C read failed\n");
+- return -EREMOTEIO;
- }
-- // also TI 1510 Innovator, bitbanging through FPGA
-- // also Nokia 770
-- // also Palm Tungsten T2
--#endif
+- return 0;
+-}
-
-- // 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)
+-/* write single register */
+-static int qt1010_writereg(struct qt1010_priv *priv, u8 reg, u8 val)
+-{
+- u8 buf[2] = { reg, val };
+- struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
+- .flags = 0, .buf = buf, .len = 2 };
-
-- // Atmel at91sam9261-EK uses ads7843
+- if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+- printk(KERN_WARNING "qt1010 I2C write failed\n");
+- return -EREMOTEIO;
+- }
+- return 0;
+-}
-
-- // also various AMD Au1x00 devel boards
+-/* dump all registers */
+-static void qt1010_dump_regs(struct qt1010_priv *priv)
+-{
+- char buf[52], buf2[4];
+- u8 reg, val;
-
- 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);
+- for (reg = 0; ; reg++) {
+- if (reg % 16 == 0) {
+- if (reg)
+- printk("%s\n", buf);
+- sprintf(buf, "%02x: ", reg);
+- }
+- if (qt1010_readreg(priv, reg, &val) == 0)
+- sprintf(buf2, "%02x ", val);
+- else
+- strcpy(buf2, "-- ");
+- strcat(buf, buf2);
+- if (reg == 0x2f)
+- break;
+- }
+- printk("%s\n", buf);
+-}
-
--#ifdef CONFIG_ARCH_OMAP
-- if (machine_is_omap_osk()) {
-- omap_free_gpio(4);
-- omap_free_gpio(6);
+-static int qt1010_set_params(struct dvb_frontend *fe,
+- struct dvb_frontend_parameters *params)
+-{
+- struct qt1010_priv *priv;
+- int err;
+- u32 freq, div, mod1, mod2;
+- u8 i, tmpval, reg05;
+- qt1010_i2c_oper_t rd[48] = {
+- { QT1010_WR, 0x01, 0x80 },
+- { QT1010_WR, 0x02, 0x3f },
+- { QT1010_WR, 0x05, 0xff }, /* 02 c write */
+- { QT1010_WR, 0x06, 0x44 },
+- { QT1010_WR, 0x07, 0xff }, /* 04 c write */
+- { QT1010_WR, 0x08, 0x08 },
+- { QT1010_WR, 0x09, 0xff }, /* 06 c write */
+- { QT1010_WR, 0x0a, 0xff }, /* 07 c write */
+- { QT1010_WR, 0x0b, 0xff }, /* 08 c write */
+- { QT1010_WR, 0x0c, 0xe1 },
+- { QT1010_WR, 0x1a, 0xff }, /* 10 c write */
+- { QT1010_WR, 0x1b, 0x00 },
+- { QT1010_WR, 0x1c, 0x89 },
+- { QT1010_WR, 0x11, 0xff }, /* 13 c write */
+- { QT1010_WR, 0x12, 0xff }, /* 14 c write */
+- { QT1010_WR, 0x22, 0xff }, /* 15 c write */
+- { QT1010_WR, 0x1e, 0x00 },
+- { QT1010_WR, 0x1e, 0xd0 },
+- { QT1010_RD, 0x22, 0xff }, /* 16 c read */
+- { QT1010_WR, 0x1e, 0x00 },
+- { QT1010_RD, 0x05, 0xff }, /* 20 c read */
+- { QT1010_RD, 0x22, 0xff }, /* 21 c read */
+- { QT1010_WR, 0x23, 0xd0 },
+- { QT1010_WR, 0x1e, 0x00 },
+- { QT1010_WR, 0x1e, 0xe0 },
+- { QT1010_RD, 0x23, 0xff }, /* 25 c read */
+- { QT1010_RD, 0x23, 0xff }, /* 26 c read */
+- { QT1010_WR, 0x1e, 0x00 },
+- { QT1010_WR, 0x24, 0xd0 },
+- { QT1010_WR, 0x1e, 0x00 },
+- { QT1010_WR, 0x1e, 0xf0 },
+- { QT1010_RD, 0x24, 0xff }, /* 31 c read */
+- { QT1010_WR, 0x1e, 0x00 },
+- { QT1010_WR, 0x14, 0x7f },
+- { QT1010_WR, 0x15, 0x7f },
+- { QT1010_WR, 0x05, 0xff }, /* 35 c write */
+- { QT1010_WR, 0x06, 0x00 },
+- { QT1010_WR, 0x15, 0x1f },
+- { QT1010_WR, 0x16, 0xff },
+- { QT1010_WR, 0x18, 0xff },
+- { QT1010_WR, 0x1f, 0xff }, /* 40 c write */
+- { QT1010_WR, 0x20, 0xff }, /* 41 c write */
+- { QT1010_WR, 0x21, 0x53 },
+- { QT1010_WR, 0x25, 0xff }, /* 43 c write */
+- { QT1010_WR, 0x26, 0x15 },
+- { QT1010_WR, 0x00, 0xff }, /* 45 c write */
+- { QT1010_WR, 0x02, 0x00 },
+- { QT1010_WR, 0x01, 0x00 }
+- };
+-
+-#define FREQ1 32000000 /* 32 MHz */
+-#define FREQ2 4000000 /* 4 MHz Quartz oscillator in the stick? */
+-
+- priv = fe->tuner_priv;
+- freq = params->frequency;
+- div = (freq + QT1010_OFFSET) / QT1010_STEP;
+- freq = (div * QT1010_STEP) - QT1010_OFFSET;
+- mod1 = (freq + QT1010_OFFSET) % FREQ1;
+- mod2 = (freq + QT1010_OFFSET) % FREQ2;
+- priv->bandwidth =
+- (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+- priv->frequency = freq;
+-
+- if (fe->ops.i2c_gate_ctrl)
+- fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+-
+- /* reg 05 base value */
+- if (freq < 290000000) reg05 = 0x14; /* 290 MHz */
+- else if (freq < 610000000) reg05 = 0x34; /* 610 MHz */
+- else if (freq < 802000000) reg05 = 0x54; /* 802 MHz */
+- else reg05 = 0x74;
+-
+- /* 0x5 */
+- rd[2].val = reg05;
+-
+- /* 07 - set frequency: 32 MHz scale */
+- rd[4].val = (freq + QT1010_OFFSET) / FREQ1;
+-
+- /* 09 - changes every 8/24 MHz */
+- if (mod1 < 8000000) rd[6].val = 0x1d;
+- else rd[6].val = 0x1c;
+-
+- /* 0a - set frequency: 4 MHz scale (max 28 MHz) */
+- if (mod1 < 1*FREQ2) rd[7].val = 0x09; /* +0 MHz */
+- else if (mod1 < 2*FREQ2) rd[7].val = 0x08; /* +4 MHz */
+- else if (mod1 < 3*FREQ2) rd[7].val = 0x0f; /* +8 MHz */
+- else if (mod1 < 4*FREQ2) rd[7].val = 0x0e; /* +12 MHz */
+- else if (mod1 < 5*FREQ2) rd[7].val = 0x0d; /* +16 MHz */
+- else if (mod1 < 6*FREQ2) rd[7].val = 0x0c; /* +20 MHz */
+- else if (mod1 < 7*FREQ2) rd[7].val = 0x0b; /* +24 MHz */
+- else rd[7].val = 0x0a; /* +28 MHz */
+-
+- /* 0b - changes every 2/2 MHz */
+- if (mod2 < 2000000) rd[8].val = 0x45;
+- else rd[8].val = 0x44;
+-
+- /* 1a - set frequency: 125 kHz scale (max 3875 kHz)*/
+- tmpval = 0x78; /* byte, overflows intentionally */
+- rd[10].val = tmpval-((mod2/QT1010_STEP)*0x08);
+-
+- /* 11 */
+- rd[13].val = 0xfd; /* TODO: correct value calculation */
+-
+- /* 12 */
+- rd[14].val = 0x91; /* TODO: correct value calculation */
+-
+- /* 22 */
+- if (freq < 450000000) rd[15].val = 0xd0; /* 450 MHz */
+- else if (freq < 482000000) rd[15].val = 0xd1; /* 482 MHz */
+- else if (freq < 514000000) rd[15].val = 0xd4; /* 514 MHz */
+- else if (freq < 546000000) rd[15].val = 0xd7; /* 546 MHz */
+- else if (freq < 610000000) rd[15].val = 0xda; /* 610 MHz */
+- else rd[15].val = 0xd0;
+-
+- /* 05 */
+- rd[35].val = (reg05 & 0xf0);
+-
+- /* 1f */
+- if (mod1 < 8000000) tmpval = 0x00;
+- else if (mod1 < 12000000) tmpval = 0x01;
+- else if (mod1 < 16000000) tmpval = 0x02;
+- else if (mod1 < 24000000) tmpval = 0x03;
+- else if (mod1 < 28000000) tmpval = 0x04;
+- else tmpval = 0x05;
+- rd[40].val = (priv->reg1f_init_val + 0x0e + tmpval);
+-
+- /* 20 */
+- if (mod1 < 8000000) tmpval = 0x00;
+- else if (mod1 < 12000000) tmpval = 0x01;
+- else if (mod1 < 20000000) tmpval = 0x02;
+- else if (mod1 < 24000000) tmpval = 0x03;
+- else if (mod1 < 28000000) tmpval = 0x04;
+- else tmpval = 0x05;
+- rd[41].val = (priv->reg20_init_val + 0x0d + tmpval);
+-
+- /* 25 */
+- rd[43].val = priv->reg25_init_val;
+-
+- /* 00 */
+- rd[45].val = 0x92; /* TODO: correct value calculation */
+-
+- dprintk("freq:%u 05:%02x 07:%02x 09:%02x 0a:%02x 0b:%02x " \
+- "1a:%02x 11:%02x 12:%02x 22:%02x 05:%02x 1f:%02x " \
+- "20:%02x 25:%02x 00:%02x", \
+- freq, rd[2].val, rd[4].val, rd[6].val, rd[7].val, rd[8].val, \
+- rd[10].val, rd[13].val, rd[14].val, rd[15].val, rd[35].val, \
+- rd[40].val, rd[41].val, rd[43].val, rd[45].val);
+-
+- for (i = 0; i < ARRAY_SIZE(rd); i++) {
+- if (rd[i].oper == QT1010_WR) {
+- err = qt1010_writereg(priv, rd[i].reg, rd[i].val);
+- } else { /* read is required to proper locking */
+- err = qt1010_readreg(priv, rd[i].reg, &tmpval);
+- }
+- if (err) return err;
+- }
+-
+- if (debug)
+- qt1010_dump_regs(priv);
+-
+- if (fe->ops.i2c_gate_ctrl)
+- fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+-
+- return 0;
+-}
+-
+-static int qt1010_init_meas1(struct qt1010_priv *priv,
+- u8 oper, u8 reg, u8 reg_init_val, u8 *retval)
+-{
+- u8 i, val1, val2;
+- int err;
+-
+- qt1010_i2c_oper_t i2c_data[] = {
+- { QT1010_WR, reg, reg_init_val },
+- { QT1010_WR, 0x1e, 0x00 },
+- { QT1010_WR, 0x1e, oper },
+- { QT1010_RD, reg, 0xff }
+- };
+-
+- for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
+- if (i2c_data[i].oper == QT1010_WR) {
+- err = qt1010_writereg(priv, i2c_data[i].reg,
+- i2c_data[i].val);
+- } else {
+- err = qt1010_readreg(priv, i2c_data[i].reg, &val2);
+- }
+- if (err) return err;
+- }
+-
+- do {
+- val1 = val2;
+- err = qt1010_readreg(priv, reg, &val2);
+- if (err) return err;
+- dprintk("compare reg:%02x %02x %02x", reg, val1, val2);
+- } while (val1 != val2);
+- *retval = val1;
+-
+- return qt1010_writereg(priv, 0x1e, 0x00);
+-}
+-
+-static u8 qt1010_init_meas2(struct qt1010_priv *priv,
+- u8 reg_init_val, u8 *retval)
+-{
+- u8 i, val;
+- int err;
+- qt1010_i2c_oper_t i2c_data[] = {
+- { QT1010_WR, 0x07, reg_init_val },
+- { QT1010_WR, 0x22, 0xd0 },
+- { QT1010_WR, 0x1e, 0x00 },
+- { QT1010_WR, 0x1e, 0xd0 },
+- { QT1010_RD, 0x22, 0xff },
+- { QT1010_WR, 0x1e, 0x00 },
+- { QT1010_WR, 0x22, 0xff }
+- };
+- for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
+- if (i2c_data[i].oper == QT1010_WR) {
+- err = qt1010_writereg(priv, i2c_data[i].reg,
+- i2c_data[i].val);
+- } else {
+- err = qt1010_readreg(priv, i2c_data[i].reg, &val);
+- }
+- if (err) return err;
+- }
+- *retval = val;
+- return 0;
+-}
+-
+-static int qt1010_init(struct dvb_frontend *fe)
+-{
+- struct qt1010_priv *priv = fe->tuner_priv;
+- struct dvb_frontend_parameters params;
+- int err = 0;
+- u8 i, tmpval, *valptr = NULL;
+-
+- qt1010_i2c_oper_t i2c_data[] = {
+- { QT1010_WR, 0x01, 0x80 },
+- { QT1010_WR, 0x0d, 0x84 },
+- { QT1010_WR, 0x0e, 0xb7 },
+- { QT1010_WR, 0x2a, 0x23 },
+- { QT1010_WR, 0x2c, 0xdc },
+- { QT1010_M1, 0x25, 0x40 }, /* get reg 25 init value */
+- { QT1010_M1, 0x81, 0xff }, /* get reg 25 init value */
+- { QT1010_WR, 0x2b, 0x70 },
+- { QT1010_WR, 0x2a, 0x23 },
+- { QT1010_M1, 0x26, 0x08 },
+- { QT1010_M1, 0x82, 0xff },
+- { QT1010_WR, 0x05, 0x14 },
+- { QT1010_WR, 0x06, 0x44 },
+- { QT1010_WR, 0x07, 0x28 },
+- { QT1010_WR, 0x08, 0x0b },
+- { QT1010_WR, 0x11, 0xfd },
+- { QT1010_M1, 0x22, 0x0d },
+- { QT1010_M1, 0xd0, 0xff },
+- { QT1010_WR, 0x06, 0x40 },
+- { QT1010_WR, 0x16, 0xf0 },
+- { QT1010_WR, 0x02, 0x38 },
+- { QT1010_WR, 0x03, 0x18 },
+- { QT1010_WR, 0x20, 0xe0 },
+- { QT1010_M1, 0x1f, 0x20 }, /* get reg 1f init value */
+- { QT1010_M1, 0x84, 0xff }, /* get reg 1f init value */
+- { QT1010_RD, 0x20, 0x20 }, /* get reg 20 init value */
+- { QT1010_WR, 0x03, 0x19 },
+- { QT1010_WR, 0x02, 0x3f },
+- { QT1010_WR, 0x21, 0x53 },
+- { QT1010_RD, 0x21, 0xff },
+- { QT1010_WR, 0x11, 0xfd },
+- { QT1010_WR, 0x05, 0x34 },
+- { QT1010_WR, 0x06, 0x44 },
+- { QT1010_WR, 0x08, 0x08 }
+- };
+-
+- if (fe->ops.i2c_gate_ctrl)
+- fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+-
+- for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
+- switch (i2c_data[i].oper) {
+- case QT1010_WR:
+- err = qt1010_writereg(priv, i2c_data[i].reg,
+- i2c_data[i].val);
+- break;
+- case QT1010_RD:
+- if (i2c_data[i].val == 0x20)
+- valptr = &priv->reg20_init_val;
+- else
+- valptr = &tmpval;
+- err = qt1010_readreg(priv, i2c_data[i].reg, valptr);
+- break;
+- case QT1010_M1:
+- if (i2c_data[i].val == 0x25)
+- valptr = &priv->reg25_init_val;
+- else if (i2c_data[i].val == 0x1f)
+- valptr = &priv->reg1f_init_val;
+- else
+- valptr = &tmpval;
+- err = qt1010_init_meas1(priv, i2c_data[i+1].reg,
+- i2c_data[i].reg,
+- i2c_data[i].val, valptr);
+- i++;
+- break;
+- }
+- if (err) return err;
+- }
+-
+- for (i = 0x31; i < 0x3a; i++) /* 0x31 - 0x39 */
+- if ((err = qt1010_init_meas2(priv, i, &tmpval)))
+- return err;
+-
+- params.frequency = 545000000; /* Sigmatek DVB-110 545000000 */
+- /* MSI Megasky 580 GL861 533000000 */
+- return qt1010_set_params(fe, ¶ms);
+-}
+-
+-static int qt1010_release(struct dvb_frontend *fe)
+-{
+- kfree(fe->tuner_priv);
+- fe->tuner_priv = NULL;
+- return 0;
+-}
+-
+-static int qt1010_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+-{
+- struct qt1010_priv *priv = fe->tuner_priv;
+- *frequency = priv->frequency;
+- return 0;
+-}
+-
+-static int qt1010_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+-{
+- struct qt1010_priv *priv = fe->tuner_priv;
+- *bandwidth = priv->bandwidth;
+- return 0;
+-}
+-
+-static const struct dvb_tuner_ops qt1010_tuner_ops = {
+- .info = {
+- .name = "Quantek QT1010",
+- .frequency_min = QT1010_MIN_FREQ,
+- .frequency_max = QT1010_MAX_FREQ,
+- .frequency_step = QT1010_STEP,
+- },
+-
+- .release = qt1010_release,
+- .init = qt1010_init,
+- /* TODO: implement sleep */
+-
+- .set_params = qt1010_set_params,
+- .get_frequency = qt1010_get_frequency,
+- .get_bandwidth = qt1010_get_bandwidth
+-};
+-
+-struct dvb_frontend * qt1010_attach(struct dvb_frontend *fe,
+- struct i2c_adapter *i2c,
+- struct qt1010_config *cfg)
+-{
+- struct qt1010_priv *priv = NULL;
+- u8 id;
+-
+- priv = kzalloc(sizeof(struct qt1010_priv), GFP_KERNEL);
+- if (priv == NULL)
+- return NULL;
+-
+- priv->cfg = cfg;
+- priv->i2c = i2c;
+-
+- if (fe->ops.i2c_gate_ctrl)
+- fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+-
+-
+- /* Try to detect tuner chip. Probably this is not correct register. */
+- if (qt1010_readreg(priv, 0x29, &id) != 0 || (id != 0x39)) {
+- kfree(priv);
+- return NULL;
- }
+-
+- if (fe->ops.i2c_gate_ctrl)
+- fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+-
+- printk(KERN_INFO "Quantek QT1010 successfully identified.\n");
+- memcpy(&fe->ops.tuner_ops, &qt1010_tuner_ops,
+- sizeof(struct dvb_tuner_ops));
+-
+- fe->tuner_priv = priv;
+- return fe;
+-}
+-EXPORT_SYMBOL(qt1010_attach);
+-
+-MODULE_DESCRIPTION("Quantek QT1010 silicon tuner driver");
+-MODULE_AUTHOR("Antti Palosaari <crope at iki.fi>");
+-MODULE_AUTHOR("Aapo Tahkola <aet at rasterburn.org>");
+-MODULE_VERSION("0.1");
+-MODULE_LICENSE("GPL");
+diff --git a/drivers/media/dvb/frontends/qt1010.h b/drivers/media/dvb/frontends/qt1010.h
+deleted file mode 100644
+index 3ab4aa0..0000000
+--- a/drivers/media/dvb/frontends/qt1010.h
++++ /dev/null
+@@ -1,53 +0,0 @@
+-/*
+- * Driver for Quantek QT1010 silicon tuner
+- *
+- * Copyright (C) 2006 Antti Palosaari <crope at iki.fi>
+- * Aapo Tahkola <aet at rasterburn.org>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#ifndef QT1010_H
+-#define QT1010_H
+-
+-#include "dvb_frontend.h"
+-
+-struct qt1010_config {
+- u8 i2c_address;
+-};
+-
+-/**
+- * Attach a qt1010 tuner to the supplied frontend structure.
+- *
+- * @param fe frontend to attach to
+- * @param i2c i2c adapter to use
+- * @param cfg tuner hw based configuration
+- * @return fe pointer on success, NULL on failure
+- */
+-#if defined(CONFIG_DVB_TUNER_QT1010) || (defined(CONFIG_DVB_TUNER_QT1010_MODULE) && defined(MODULE))
+-extern struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
+- struct i2c_adapter *i2c,
+- struct qt1010_config *cfg);
+-#else
+-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__);
+- return NULL;
+-}
+-#endif // CONFIG_DVB_TUNER_QT1010
+-
-#endif
+diff --git a/drivers/media/dvb/frontends/qt1010_priv.h b/drivers/media/dvb/frontends/qt1010_priv.h
+deleted file mode 100644
+index 090cf47..0000000
+--- a/drivers/media/dvb/frontends/qt1010_priv.h
++++ /dev/null
+@@ -1,105 +0,0 @@
+-/*
+- * Driver for Quantek QT1010 silicon tuner
+- *
+- * Copyright (C) 2006 Antti Palosaari <crope at iki.fi>
+- * Aapo Tahkola <aet at rasterburn.org>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#ifndef QT1010_PRIV_H
+-#define QT1010_PRIV_H
+-
+-/*
+-reg def meaning
+-=== === =======
+-00 00 ?
+-01 a0 ? operation start/stop; start=80, stop=00
+-02 00 ?
+-03 19 ?
+-04 00 ?
+-05 00 ? maybe band selection
+-06 00 ?
+-07 2b set frequency: 32 MHz scale, n*32 MHz
+-08 0b ?
+-09 10 ? changes every 8/24 MHz; values 1d/1c
+-0a 08 set frequency: 4 MHz scale, n*4 MHz
+-0b 41 ? changes every 2/2 MHz; values 45/45
+-0c e1 ?
+-0d 94 ?
+-0e b6 ?
+-0f 2c ?
+-10 10 ?
+-11 f1 ? maybe device specified adjustment
+-12 11 ? maybe device specified adjustment
+-13 3f ?
+-14 1f ?
+-15 3f ?
+-16 ff ?
+-17 ff ?
+-18 f7 ?
+-19 80 ?
+-1a d0 set frequency: 125 kHz scale, n*125 kHz
+-1b 00 ?
+-1c 89 ?
+-1d 00 ?
+-1e 00 ? looks like operation register; write cmd here, read result from 1f-26
+-1f 20 ? chip initialization
+-20 e0 ? chip initialization
+-21 20 ?
+-22 d0 ?
+-23 d0 ?
+-24 d0 ?
+-25 40 ? chip initialization
+-26 08 ?
+-27 29 ?
+-28 55 ?
+-29 39 ?
+-2a 13 ?
+-2b 01 ?
+-2c ea ?
+-2d 00 ?
+-2e 00 ? not used?
+-2f 00 ? not used?
+-*/
-
- }
- module_exit(ads7846_exit);
+-#define QT1010_STEP 125000 /* 125 kHz used by Windows drivers,
+- hw could be more precise but we don't
+- know how to use */
+-#define QT1010_MIN_FREQ 48000000 /* 48 MHz */
+-#define QT1010_MAX_FREQ 860000000 /* 860 MHz */
+-#define QT1010_OFFSET 1246000000 /* 1246 MHz */
+-
+-#define QT1010_WR 0
+-#define QT1010_RD 1
+-#define QT1010_M1 3
+-
+-typedef struct {
+- u8 oper, reg, val;
+-} qt1010_i2c_oper_t;
+-
+-struct qt1010_priv {
+- struct qt1010_config *cfg;
+- struct i2c_adapter *i2c;
+-
+- u8 reg1f_init_val;
+- u8 reg20_init_val;
+- u8 reg25_init_val;
+-
+- u32 frequency;
+- u32 bandwidth;
+-};
+-
+-#endif
+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;
+ };
-diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
-index 99d92f5..4e9d8ee 100644
---- a/drivers/input/touchscreen/corgi_ts.c
-+++ b/drivers/input/touchscreen/corgi_ts.c
-@@ -22,6 +22,7 @@
- #include <asm/arch/sharpsl.h>
- #include <asm/arch/hardware.h>
- #include <asm/arch/pxa-regs.h>
-+#include <asm/arch/pxa2xx-gpio.h>
+-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)
- #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,
- },
- };
+ 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);
-@@ -380,3 +382,4 @@ module_exit(corgits_exit);
- MODULE_AUTHOR("Richard Purdie <rpurdie at rpsys.net>");
- MODULE_DESCRIPTION("Corgi TouchScreen Driver");
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:corgi-ts");
-diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c
-index 42a1c9a..7422421 100644
---- a/drivers/input/touchscreen/jornada720_ts.c
-+++ b/drivers/input/touchscreen/jornada720_ts.c
-@@ -160,11 +160,15 @@ static int __devexit jornada720_ts_remove(struct platform_device *pdev)
- return 0;
+ 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);
-+/* 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,
- },
- };
+ 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];
+ }
-diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c
-new file mode 100644
-index 0000000..a79f029
---- /dev/null
-+++ b/drivers/input/touchscreen/mainstone-wm97xx.c
-@@ -0,0 +1,302 @@
-+/*
-+ * mainstone-wm97xx.c -- Mainstone Continuous Touch screen driver for
-+ * Wolfson WM97xx AC97 Codecs.
-+ *
-+ * Copyright 2004, 2007 Wolfson Microelectronics PLC.
-+ * Author: Liam Girdwood
-+ * liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
-+ * Parts Copyright : Ian Molton <spyro at f2s.com>
-+ * Andrew Zabolotny <zap at homelink.ru>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2 of the License, or (at your
-+ * option) any later version.
-+ *
-+ * Notes:
-+ * This is a wm97xx extended touch driver to capture touch
-+ * data in a continuous manner on the Intel XScale archictecture
-+ *
-+ * Features:
-+ * - codecs supported:- WM9705, WM9712, WM9713
-+ * - processors supported:- Intel XScale PXA25x, PXA26x, PXA27x
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/version.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/irq.h>
-+#include <linux/interrupt.h>
-+#include <linux/wm97xx.h>
-+#include <linux/io.h>
-+#include <asm/arch/pxa-regs.h>
-+
-+#define VERSION "0.13"
-+
-+struct continuous {
-+ u16 id; /* codec id */
-+ u8 code; /* continuous code */
-+ u8 reads; /* number of coord reads per read cycle */
-+ u32 speed; /* number of coords per second */
-+};
-+
-+#define WM_READS(sp) ((sp / HZ) + 1)
-+
-+static const struct continuous cinfo[] = {
-+ {WM9705_ID2, 0, WM_READS(94), 94},
-+ {WM9705_ID2, 1, WM_READS(188), 188},
-+ {WM9705_ID2, 2, WM_READS(375), 375},
-+ {WM9705_ID2, 3, WM_READS(750), 750},
-+ {WM9712_ID2, 0, WM_READS(94), 94},
-+ {WM9712_ID2, 1, WM_READS(188), 188},
-+ {WM9712_ID2, 2, WM_READS(375), 375},
-+ {WM9712_ID2, 3, WM_READS(750), 750},
-+ {WM9713_ID2, 0, WM_READS(94), 94},
-+ {WM9713_ID2, 1, WM_READS(120), 120},
-+ {WM9713_ID2, 2, WM_READS(154), 154},
-+ {WM9713_ID2, 3, WM_READS(188), 188},
-+};
-+
-+/* continuous speed index */
-+static int sp_idx;
-+static u16 last, tries;
-+
-+/*
-+ * Pen sampling frequency (Hz) in continuous mode.
-+ */
-+static int cont_rate = 200;
-+module_param(cont_rate, int, 0);
-+MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
-+
-+/*
-+ * Pen down detection.
-+ *
-+ * This driver can either poll or use an interrupt to indicate a pen down
-+ * event. If the irq request fails then it will fall back to polling mode.
-+ */
-+static int pen_int;
-+module_param(pen_int, int, 0);
-+MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)");
-+
-+/*
-+ * Pressure readback.
-+ *
-+ * Set to 1 to read back pen down pressure
-+ */
-+static int pressure;
-+module_param(pressure, int, 0);
-+MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
-+
-+/*
-+ * AC97 touch data slot.
-+ *
-+ * Touch screen readback data ac97 slot
-+ */
-+static int ac97_touch_slot = 5;
-+module_param(ac97_touch_slot, int, 0);
-+MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
-+
-+
-+/* flush AC97 slot 5 FIFO on pxa machines */
-+#ifdef CONFIG_PXA27x
-+static void wm97xx_acc_pen_up(struct wm97xx *wm)
-+{
-+ schedule_timeout_uninterruptible(1);
-+
-+ while (MISR & (1 << 2))
-+ MODR;
-+}
-+#else
-+static void wm97xx_acc_pen_up(struct wm97xx *wm)
-+{
-+ int count = 16;
-+ schedule_timeout_uninterruptible(1);
-+
-+ while (count < 16) {
-+ MODR;
-+ count--;
-+ }
-+}
-+#endif
-+
-+static int wm97xx_acc_pen_down(struct wm97xx *wm)
-+{
-+ u16 x, y, p = 0x100 | WM97XX_ADCSEL_PRES;
-+ int reads = 0;
-+
-+ /* When the AC97 queue has been drained we need to allow time
-+ * to buffer up samples otherwise we end up spinning polling
-+ * for samples. The controller can't have a suitably low
-+ * threashold set to use the notifications it gives.
-+ */
-+ schedule_timeout_uninterruptible(1);
-+
-+ if (tries > 5) {
-+ tries = 0;
-+ return RC_PENUP;
-+ }
-+
-+ x = MODR;
-+ if (x == last) {
-+ tries++;
-+ return RC_AGAIN;
-+ }
-+ last = x;
-+ do {
-+ if (reads)
-+ x = MODR;
-+ y = MODR;
-+ if (pressure)
-+ p = MODR;
-+
-+ /* are samples valid */
-+ if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X ||
-+ (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y ||
-+ (p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES)
-+ goto up;
-+
-+ /* coordinate is good */
-+ tries = 0;
-+ input_report_abs(wm->input_dev, ABS_X, x & 0xfff);
-+ input_report_abs(wm->input_dev, ABS_Y, y & 0xfff);
-+ input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff);
-+ input_sync(wm->input_dev);
-+ reads++;
-+ } while (reads < cinfo[sp_idx].reads);
-+up:
-+ return RC_PENDOWN | RC_AGAIN;
-+}
-+
-+static int wm97xx_acc_startup(struct wm97xx *wm)
-+{
-+ int idx = 0;
-+
-+ /* check we have a codec */
-+ if (wm->ac97 == NULL)
-+ return -ENODEV;
-+
-+ /* Go you big red fire engine */
-+ for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
-+ if (wm->id != cinfo[idx].id)
-+ continue;
-+ sp_idx = idx;
-+ if (cont_rate <= cinfo[idx].speed)
-+ break;
-+ }
-+ wm->acc_rate = cinfo[sp_idx].code;
-+ wm->acc_slot = ac97_touch_slot;
-+ dev_info(wm->dev,
-+ "mainstone accelerated touchscreen driver, %d samples/sec\n",
-+ cinfo[sp_idx].speed);
-+
-+ /* codec specific irq config */
-+ if (pen_int) {
-+ switch (wm->id) {
-+ case WM9705_ID2:
-+ wm->pen_irq = IRQ_GPIO(4);
-+ set_irq_type(IRQ_GPIO(4), IRQT_BOTHEDGE);
-+ break;
-+ case WM9712_ID2:
-+ case WM9713_ID2:
-+ /* enable pen down interrupt */
-+ /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */
-+ wm->pen_irq = MAINSTONE_AC97_IRQ;
-+ wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
-+ WM97XX_GPIO_POL_HIGH,
-+ WM97XX_GPIO_STICKY,
-+ WM97XX_GPIO_WAKE);
-+ wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT,
-+ WM97XX_GPIO_POL_HIGH,
-+ WM97XX_GPIO_NOTSTICKY,
-+ WM97XX_GPIO_NOWAKE);
-+ break;
-+ default:
-+ dev_err(wm->dev,
-+ "pen down irq not supported on this device\n");
-+ pen_int = 0;
-+ break;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static void wm97xx_acc_shutdown(struct wm97xx *wm)
-+{
-+ /* codec specific deconfig */
-+ if (pen_int) {
-+ switch (wm->id & 0xffff) {
-+ case WM9705_ID2:
-+ wm->pen_irq = 0;
-+ break;
-+ case WM9712_ID2:
-+ case WM9713_ID2:
-+ /* disable interrupt */
-+ wm->pen_irq = 0;
-+ break;
-+ }
-+ }
-+}
-+
-+static void wm97xx_irq_enable(struct wm97xx *wm, int enable)
-+{
-+ if (enable)
-+ enable_irq(wm->pen_irq);
-+ else
-+ disable_irq(wm->pen_irq);
-+}
-+
-+static struct wm97xx_mach_ops mainstone_mach_ops = {
-+ .acc_enabled = 1,
-+ .acc_pen_up = wm97xx_acc_pen_up,
-+ .acc_pen_down = wm97xx_acc_pen_down,
-+ .acc_startup = wm97xx_acc_startup,
-+ .acc_shutdown = wm97xx_acc_shutdown,
-+ .irq_enable = wm97xx_irq_enable,
-+ .irq_gpio = WM97XX_GPIO_2,
-+};
-+
-+static int mainstone_wm97xx_probe(struct platform_device *pdev)
-+{
-+ struct wm97xx *wm = platform_get_drvdata(pdev);
-+
-+ return wm97xx_register_mach_ops(wm, &mainstone_mach_ops);
-+}
-+
-+static int mainstone_wm97xx_remove(struct platform_device *pdev)
-+{
-+ struct wm97xx *wm = platform_get_drvdata(pdev);
-+
-+ wm97xx_unregister_mach_ops(wm);
-+ return 0;
-+}
-+
-+static struct platform_driver mainstone_wm97xx_driver = {
-+ .probe = mainstone_wm97xx_probe,
-+ .remove = mainstone_wm97xx_remove,
-+ .driver = {
-+ .name = "wm97xx-touch",
-+ },
-+};
-+
-+static int __init mainstone_wm97xx_init(void)
-+{
-+ return platform_driver_register(&mainstone_wm97xx_driver);
-+}
-+
-+static void __exit mainstone_wm97xx_exit(void)
-+{
-+ platform_driver_unregister(&mainstone_wm97xx_driver);
-+}
-+
-+module_init(mainstone_wm97xx_init);
-+module_exit(mainstone_wm97xx_exit);
-+
-+/* Module information */
-+MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
-+MODULE_DESCRIPTION("wm97xx continuous touch driver for mainstone");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
-index 607f993..bce018e 100644
---- a/drivers/input/touchscreen/ucb1400_ts.c
-+++ b/drivers/input/touchscreen/ucb1400_ts.c
-@@ -427,10 +427,6 @@ static int ucb1400_detect_irq(struct ucb1400 *ucb)
- unsigned long mask, timeout;
+@@ -340,7 +340,7 @@ static int s5h1409_softreset(struct dvb_frontend* fe)
+ {
+ struct s5h1409_state* state = fe->demodulator_priv;
- mask = probe_irq_on();
-- if (!mask) {
-- probe_irq_off(mask);
-- return -EBUSY;
-- }
+- dprintk("%s()\n", __FUNCTION__);
++ dprintk("%s()\n", __func__);
- /* 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)
+ 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 usb_device *dev = usbtouch->udev;
-- int ret;
-- unsigned char buf[2];
-+ int ret = -ENOMEM;
-+ unsigned char *buf;
+ struct s5h1409_state* state = fe->demodulator_priv;
-+ 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;
-+ }
+- dprintk("%s(%d KHz)\n", __FUNCTION__, KHz);
++ dprintk("%s(%d KHz)\n", __func__, KHz);
- /* 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;
-+ }
+ 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;
- /* 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;
- }
+- 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;
-diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c
-new file mode 100644
-index 0000000..978e1a1
---- /dev/null
-+++ b/drivers/input/touchscreen/wm9705.c
-@@ -0,0 +1,353 @@
-+/*
-+ * wm9705.c -- Codec driver for Wolfson WM9705 AC97 Codec.
-+ *
-+ * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
-+ * Author: Liam Girdwood
-+ * liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
-+ * Parts Copyright : Ian Molton <spyro at f2s.com>
-+ * Andrew Zabolotny <zap at homelink.ru>
-+ * Russell King <rmk at arm.linux.org.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2 of the License, or (at your
-+ * option) any later version.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/version.h>
-+#include <linux/kernel.h>
-+#include <linux/input.h>
-+#include <linux/delay.h>
-+#include <linux/bitops.h>
-+#include <linux/wm97xx.h>
-+
-+#define TS_NAME "wm97xx"
-+#define WM9705_VERSION "1.00"
-+#define DEFAULT_PRESSURE 0xb0c0
-+
-+/*
-+ * Module parameters
-+ */
-+
-+/*
-+ * Set current used for pressure measurement.
-+ *
-+ * Set pil = 2 to use 400uA
-+ * pil = 1 to use 200uA and
-+ * pil = 0 to disable pressure measurement.
-+ *
-+ * This is used to increase the range of values returned by the adc
-+ * when measureing touchpanel pressure.
-+ */
-+static int pil;
-+module_param(pil, int, 0);
-+MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
-+
-+/*
-+ * Set threshold for pressure measurement.
-+ *
-+ * Pen down pressure below threshold is ignored.
-+ */
-+static int pressure = DEFAULT_PRESSURE & 0xfff;
-+module_param(pressure, int, 0);
-+MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
-+
-+/*
-+ * Set adc sample delay.
-+ *
-+ * For accurate touchpanel measurements, some settling time may be
-+ * required between the switch matrix applying a voltage across the
-+ * touchpanel plate and the ADC sampling the signal.
-+ *
-+ * This delay can be set by setting delay = n, where n is the array
-+ * position of the delay in the array delay_table below.
-+ * Long delays > 1ms are supported for completeness, but are not
-+ * recommended.
-+ */
-+static int delay = 4;
-+module_param(delay, int, 0);
-+MODULE_PARM_DESC(delay, "Set adc sample delay.");
-+
-+/*
-+ * Pen detect comparator threshold.
-+ *
-+ * 0 to Vmid in 15 steps, 0 = use zero power comparator with Vmid threshold
-+ * i.e. 1 = Vmid/15 threshold
-+ * 15 = Vmid/1 threshold
-+ *
-+ * Adjust this value if you are having problems with pen detect not
-+ * detecting any down events.
-+ */
-+static int pdd = 8;
-+module_param(pdd, int, 0);
-+MODULE_PARM_DESC(pdd, "Set pen detect comparator threshold");
-+
-+/*
-+ * Set adc mask function.
-+ *
-+ * Sources of glitch noise, such as signals driving an LCD display, may feed
-+ * through to the touch screen plates and affect measurement accuracy. In
-+ * order to minimise this, a signal may be applied to the MASK pin to delay or
-+ * synchronise the sampling.
-+ *
-+ * 0 = No delay or sync
-+ * 1 = High on pin stops conversions
-+ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
-+ * 3 = Edge triggered, edge on pin starts conversion after delay param
-+ */
-+static int mask;
-+module_param(mask, int, 0);
-+MODULE_PARM_DESC(mask, "Set adc mask function.");
-+
-+/*
-+ * ADC sample delay times in uS
-+ */
-+static const int delay_table[] = {
-+ 21, /* 1 AC97 Link frames */
-+ 42, /* 2 */
-+ 84, /* 4 */
-+ 167, /* 8 */
-+ 333, /* 16 */
-+ 667, /* 32 */
-+ 1000, /* 48 */
-+ 1333, /* 64 */
-+ 2000, /* 96 */
-+ 2667, /* 128 */
-+ 3333, /* 160 */
-+ 4000, /* 192 */
-+ 4667, /* 224 */
-+ 5333, /* 256 */
-+ 6000, /* 288 */
-+ 0 /* No delay, switch matrix always on */
-+};
-+
-+/*
-+ * Delay after issuing a POLL command.
-+ *
-+ * The delay is 3 AC97 link frames + the touchpanel settling delay
-+ */
-+static inline void poll_delay(int d)
-+{
-+ udelay(3 * AC97_LINK_FRAME + delay_table[d]);
-+}
-+
-+/*
-+ * set up the physical settings of the WM9705
-+ */
-+static void wm9705_phy_init(struct wm97xx *wm)
-+{
-+ u16 dig1 = 0, dig2 = WM97XX_RPR;
-+
-+ /*
-+ * mute VIDEO and AUX as they share X and Y touchscreen
-+ * inputs on the WM9705
-+ */
-+ wm97xx_reg_write(wm, AC97_AUX, 0x8000);
-+ wm97xx_reg_write(wm, AC97_VIDEO, 0x8000);
-+
-+ /* touchpanel pressure current*/
-+ if (pil == 2) {
-+ dig2 |= WM9705_PIL;
-+ dev_dbg(wm->dev,
-+ "setting pressure measurement current to 400uA.");
-+ } else if (pil)
-+ dev_dbg(wm->dev,
-+ "setting pressure measurement current to 200uA.");
-+ if (!pil)
-+ pressure = 0;
-+
-+ /* polling mode sample settling delay */
-+ if (delay != 4) {
-+ if (delay < 0 || delay > 15) {
-+ dev_dbg(wm->dev, "supplied delay out of range.");
-+ delay = 4;
-+ }
-+ }
-+ dig1 &= 0xff0f;
-+ dig1 |= WM97XX_DELAY(delay);
-+ dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.",
-+ delay_table[delay]);
-+
-+ /* WM9705 pdd */
-+ dig2 |= (pdd & 0x000f);
-+ dev_dbg(wm->dev, "setting pdd to Vmid/%d", 1 - (pdd & 0x000f));
-+
-+ /* mask */
-+ dig2 |= ((mask & 0x3) << 4);
-+
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
-+}
-+
-+static void wm9705_dig_enable(struct wm97xx *wm, int enable)
-+{
-+ if (enable) {
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
-+ wm->dig[2] | WM97XX_PRP_DET_DIG);
-+ wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
-+ } else
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
-+ wm->dig[2] & ~WM97XX_PRP_DET_DIG);
-+}
-+
-+static void wm9705_aux_prepare(struct wm97xx *wm)
-+{
-+ memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
-+}
-+
-+static void wm9705_dig_restore(struct wm97xx *wm)
-+{
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
-+}
-+
-+static inline int is_pden(struct wm97xx *wm)
-+{
-+ return wm->dig[2] & WM9705_PDEN;
-+}
-+
-+/*
-+ * Read a sample from the WM9705 adc in polling mode.
-+ */
-+static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
-+{
-+ int timeout = 5 * delay;
-+
-+ if (!wm->pen_probably_down) {
-+ u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
-+ if (!(data & WM97XX_PEN_DOWN))
-+ return RC_PENUP;
-+ wm->pen_probably_down = 1;
-+ }
-+
-+ /* set up digitiser */
-+ if (adcsel & 0x8000)
-+ adcsel = ((adcsel & 0x7fff) + 3) << 12;
-+
-+ if (wm->mach_ops && wm->mach_ops->pre_sample)
-+ wm->mach_ops->pre_sample(adcsel);
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
-+ adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
-+
-+ /* wait 3 AC97 time slots + delay for conversion */
-+ poll_delay(delay);
-+
-+ /* wait for POLL to go low */
-+ while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
-+ && timeout) {
-+ udelay(AC97_LINK_FRAME);
-+ timeout--;
-+ }
-+
-+ if (timeout == 0) {
-+ /* If PDEN is set, we can get a timeout when pen goes up */
-+ if (is_pden(wm))
-+ wm->pen_probably_down = 0;
-+ else
-+ dev_dbg(wm->dev, "adc sample timeout");
-+ return RC_PENUP;
-+ }
-+
-+ *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
-+ if (wm->mach_ops && wm->mach_ops->post_sample)
-+ wm->mach_ops->post_sample(adcsel);
-+
-+ /* check we have correct sample */
-+ if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
-+ dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
-+ *sample & WM97XX_ADCSEL_MASK);
-+ return RC_PENUP;
-+ }
-+
-+ if (!(*sample & WM97XX_PEN_DOWN)) {
-+ wm->pen_probably_down = 0;
-+ return RC_PENUP;
-+ }
-+
-+ return RC_VALID;
-+}
-+
-+/*
-+ * Sample the WM9705 touchscreen in polling mode
-+ */
-+static int wm9705_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
-+{
-+ int rc;
-+
-+ rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X, &data->x);
-+ if (rc != RC_VALID)
-+ return rc;
-+ rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y);
-+ if (rc != RC_VALID)
-+ return rc;
-+ if (pil) {
-+ rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p);
-+ if (rc != RC_VALID)
-+ return rc;
-+ } else
-+ data->p = DEFAULT_PRESSURE;
-+
-+ return RC_VALID;
-+}
-+
-+/*
-+ * Enable WM9705 continuous mode, i.e. touch data is streamed across
-+ * an AC97 slot
-+ */
-+static int wm9705_acc_enable(struct wm97xx *wm, int enable)
-+{
-+ u16 dig1, dig2;
-+ int ret = 0;
-+
-+ dig1 = wm->dig[1];
-+ dig2 = wm->dig[2];
-+
-+ if (enable) {
-+ /* continous mode */
-+ if (wm->mach_ops->acc_startup &&
-+ (ret = wm->mach_ops->acc_startup(wm)) < 0)
-+ return ret;
-+ dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
-+ WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
-+ dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
-+ WM97XX_DELAY(delay) |
-+ WM97XX_SLT(wm->acc_slot) |
-+ WM97XX_RATE(wm->acc_rate);
-+ if (pil)
-+ dig1 |= WM97XX_ADCSEL_PRES;
-+ dig2 |= WM9705_PDEN;
-+ } else {
-+ dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
-+ dig2 &= ~WM9705_PDEN;
-+ if (wm->mach_ops->acc_shutdown)
-+ wm->mach_ops->acc_shutdown(wm);
-+ }
-+
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
-+
-+ return ret;
-+}
-+
-+struct wm97xx_codec_drv wm9705_codec = {
-+ .id = WM9705_ID2,
-+ .name = "wm9705",
-+ .poll_sample = wm9705_poll_sample,
-+ .poll_touch = wm9705_poll_touch,
-+ .acc_enable = wm9705_acc_enable,
-+ .phy_init = wm9705_phy_init,
-+ .dig_enable = wm9705_dig_enable,
-+ .dig_restore = wm9705_dig_restore,
-+ .aux_prepare = wm9705_aux_prepare,
-+};
-+EXPORT_SYMBOL_GPL(wm9705_codec);
-+
-+/* Module information */
-+MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
-+MODULE_DESCRIPTION("WM9705 Touch Screen Driver");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c
-new file mode 100644
-index 0000000..0b6e4cf
---- /dev/null
-+++ b/drivers/input/touchscreen/wm9712.c
-@@ -0,0 +1,462 @@
-+/*
-+ * wm9712.c -- Codec driver for Wolfson WM9712 AC97 Codecs.
-+ *
-+ * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
-+ * Author: Liam Girdwood
-+ * liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
-+ * Parts Copyright : Ian Molton <spyro at f2s.com>
-+ * Andrew Zabolotny <zap at homelink.ru>
-+ * Russell King <rmk at arm.linux.org.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2 of the License, or (at your
-+ * option) any later version.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/version.h>
-+#include <linux/kernel.h>
-+#include <linux/input.h>
-+#include <linux/delay.h>
-+#include <linux/bitops.h>
-+#include <linux/wm97xx.h>
-+
-+#define TS_NAME "wm97xx"
-+#define WM9712_VERSION "1.00"
-+#define DEFAULT_PRESSURE 0xb0c0
-+
-+/*
-+ * Module parameters
-+ */
-+
-+/*
-+ * Set internal pull up for pen detect.
-+ *
-+ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
-+ * i.e. pull up resistance = 64k Ohms / rpu.
-+ *
-+ * Adjust this value if you are having problems with pen detect not
-+ * detecting any down event.
-+ */
-+static int rpu = 8;
-+module_param(rpu, int, 0);
-+MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
-+
-+/*
-+ * Set current used for pressure measurement.
-+ *
-+ * Set pil = 2 to use 400uA
-+ * pil = 1 to use 200uA and
-+ * pil = 0 to disable pressure measurement.
-+ *
-+ * This is used to increase the range of values returned by the adc
-+ * when measureing touchpanel pressure.
-+ */
-+static int pil;
-+module_param(pil, int, 0);
-+MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
-+
-+/*
-+ * Set threshold for pressure measurement.
-+ *
-+ * Pen down pressure below threshold is ignored.
-+ */
-+static int pressure = DEFAULT_PRESSURE & 0xfff;
-+module_param(pressure, int, 0);
-+MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
-+
-+/*
-+ * Set adc sample delay.
-+ *
-+ * For accurate touchpanel measurements, some settling time may be
-+ * required between the switch matrix applying a voltage across the
-+ * touchpanel plate and the ADC sampling the signal.
-+ *
-+ * This delay can be set by setting delay = n, where n is the array
-+ * position of the delay in the array delay_table below.
-+ * Long delays > 1ms are supported for completeness, but are not
-+ * recommended.
-+ */
-+static int delay = 3;
-+module_param(delay, int, 0);
-+MODULE_PARM_DESC(delay, "Set adc sample delay.");
-+
-+/*
-+ * Set five_wire = 1 to use a 5 wire touchscreen.
-+ *
-+ * NOTE: Five wire mode does not allow for readback of pressure.
-+ */
-+static int five_wire;
-+module_param(five_wire, int, 0);
-+MODULE_PARM_DESC(five_wire, "Set to '1' to use 5-wire touchscreen.");
-+
-+/*
-+ * Set adc mask function.
-+ *
-+ * Sources of glitch noise, such as signals driving an LCD display, may feed
-+ * through to the touch screen plates and affect measurement accuracy. In
-+ * order to minimise this, a signal may be applied to the MASK pin to delay or
-+ * synchronise the sampling.
-+ *
-+ * 0 = No delay or sync
-+ * 1 = High on pin stops conversions
-+ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
-+ * 3 = Edge triggered, edge on pin starts conversion after delay param
-+ */
-+static int mask;
-+module_param(mask, int, 0);
-+MODULE_PARM_DESC(mask, "Set adc mask function.");
-+
-+/*
-+ * Coordinate Polling Enable.
-+ *
-+ * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
-+ * for every poll.
-+ */
-+static int coord;
-+module_param(coord, int, 0);
-+MODULE_PARM_DESC(coord, "Polling coordinate mode");
-+
-+/*
-+ * ADC sample delay times in uS
-+ */
-+static const int delay_table[] = {
-+ 21, /* 1 AC97 Link frames */
-+ 42, /* 2 */
-+ 84, /* 4 */
-+ 167, /* 8 */
-+ 333, /* 16 */
-+ 667, /* 32 */
-+ 1000, /* 48 */
-+ 1333, /* 64 */
-+ 2000, /* 96 */
-+ 2667, /* 128 */
-+ 3333, /* 160 */
-+ 4000, /* 192 */
-+ 4667, /* 224 */
-+ 5333, /* 256 */
-+ 6000, /* 288 */
-+ 0 /* No delay, switch matrix always on */
-+};
-+
-+/*
-+ * Delay after issuing a POLL command.
-+ *
-+ * The delay is 3 AC97 link frames + the touchpanel settling delay
-+ */
-+static inline void poll_delay(int d)
-+{
-+ udelay(3 * AC97_LINK_FRAME + delay_table[d]);
-+}
-+
-+/*
-+ * set up the physical settings of the WM9712
-+ */
-+static void wm9712_phy_init(struct wm97xx *wm)
-+{
-+ u16 dig1 = 0;
-+ u16 dig2 = WM97XX_RPR | WM9712_RPU(1);
-+
-+ /* WM9712 rpu */
-+ if (rpu) {
-+ dig2 &= 0xffc0;
-+ dig2 |= WM9712_RPU(rpu);
-+ dev_dbg(wm->dev, "setting pen detect pull-up to %d Ohms",
-+ 64000 / rpu);
-+ }
-+
-+ /* touchpanel pressure current*/
-+ if (pil == 2) {
-+ dig2 |= WM9712_PIL;
-+ dev_dbg(wm->dev,
-+ "setting pressure measurement current to 400uA.");
-+ } else if (pil)
-+ dev_dbg(wm->dev,
-+ "setting pressure measurement current to 200uA.");
-+ if (!pil)
-+ pressure = 0;
-+
-+ /* WM9712 five wire */
-+ if (five_wire) {
-+ dig2 |= WM9712_45W;
-+ dev_dbg(wm->dev, "setting 5-wire touchscreen mode.");
-+ }
-+
-+ /* polling mode sample settling delay */
-+ if (delay < 0 || delay > 15) {
-+ dev_dbg(wm->dev, "supplied delay out of range.");
-+ delay = 4;
-+ }
-+ dig1 &= 0xff0f;
-+ dig1 |= WM97XX_DELAY(delay);
-+ dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.",
-+ delay_table[delay]);
-+
-+ /* mask */
-+ dig2 |= ((mask & 0x3) << 6);
-+ if (mask) {
-+ u16 reg;
-+ /* Set GPIO4 as Mask Pin*/
-+ reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
-+ wm97xx_reg_write(wm, AC97_MISC_AFE, reg | WM97XX_GPIO_4);
-+ reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
-+ wm97xx_reg_write(wm, AC97_GPIO_CFG, reg | WM97XX_GPIO_4);
-+ }
-+
-+ /* wait - coord mode */
-+ if (coord)
-+ dig2 |= WM9712_WAIT;
-+
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
-+}
-+
-+static void wm9712_dig_enable(struct wm97xx *wm, int enable)
-+{
-+ u16 dig2 = wm->dig[2];
-+
-+ if (enable) {
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
-+ dig2 | WM97XX_PRP_DET_DIG);
-+ wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
-+ } else
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
-+ dig2 & ~WM97XX_PRP_DET_DIG);
-+}
-+
-+static void wm9712_aux_prepare(struct wm97xx *wm)
-+{
-+ memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
-+}
-+
-+static void wm9712_dig_restore(struct wm97xx *wm)
-+{
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
-+}
-+
-+static inline int is_pden(struct wm97xx *wm)
-+{
-+ return wm->dig[2] & WM9712_PDEN;
-+}
-+
-+/*
-+ * Read a sample from the WM9712 adc in polling mode.
-+ */
-+static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
-+{
-+ int timeout = 5 * delay;
-+
-+ if (!wm->pen_probably_down) {
-+ u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
-+ if (!(data & WM97XX_PEN_DOWN))
-+ return RC_PENUP;
-+ wm->pen_probably_down = 1;
-+ }
-+
-+ /* set up digitiser */
-+ if (adcsel & 0x8000)
-+ adcsel = ((adcsel & 0x7fff) + 3) << 12;
-+
-+ if (wm->mach_ops && wm->mach_ops->pre_sample)
-+ wm->mach_ops->pre_sample(adcsel);
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
-+ adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
-+
-+ /* wait 3 AC97 time slots + delay for conversion */
-+ poll_delay(delay);
-+
-+ /* wait for POLL to go low */
-+ while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
-+ && timeout) {
-+ udelay(AC97_LINK_FRAME);
-+ timeout--;
-+ }
-+
-+ if (timeout <= 0) {
-+ /* If PDEN is set, we can get a timeout when pen goes up */
-+ if (is_pden(wm))
-+ wm->pen_probably_down = 0;
-+ else
-+ dev_dbg(wm->dev, "adc sample timeout");
-+ return RC_PENUP;
-+ }
-+
-+ *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
-+ if (wm->mach_ops && wm->mach_ops->post_sample)
-+ wm->mach_ops->post_sample(adcsel);
-+
-+ /* check we have correct sample */
-+ if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
-+ dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
-+ *sample & WM97XX_ADCSEL_MASK);
-+ return RC_PENUP;
-+ }
-+
-+ if (!(*sample & WM97XX_PEN_DOWN)) {
-+ wm->pen_probably_down = 0;
-+ return RC_PENUP;
-+ }
-+
-+ return RC_VALID;
-+}
-+
+- 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 @@
+/*
-+ * 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;
++ Samsung S5H1411 VSB/QAM demodulator driver
+
-+ if (wm->mach_ops && wm->mach_ops->post_sample)
-+ wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
++ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
+
-+ /* 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;
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the 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 (!(data->x & WM97XX_PEN_DOWN) || !(data->y & WM97XX_PEN_DOWN)) {
-+ wm->pen_probably_down = 0;
-+ return RC_PENUP;
-+ }
-+ return RC_VALID;
-+err:
-+ return 0;
-+}
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
+
-+/*
-+ * Sample the WM9712 touchscreen in polling mode
-+ */
-+static int wm9712_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
-+{
-+ int rc;
++ You 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.
+
-+ 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;
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include "dvb_frontend.h"
++#include "dvb-pll.h"
++#include "s5h1411.h"
+
-+ 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;
-+}
++struct s5h1411_state {
+
-+/*
-+ * 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;
++ struct i2c_adapter *i2c;
+
-+ dig1 = wm->dig[1];
-+ dig2 = wm->dig[2];
++ /* configuration settings */
++ const struct s5h1411_config *config;
+
-+ 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);
-+ }
++ struct dvb_frontend frontend;
+
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
-+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
++ fe_modulation_t current_modulation;
+
-+ return 0;
-+}
++ u32 current_frequency;
++ int if_freq;
+
-+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,
++ u8 inversion;
+};
-+EXPORT_SYMBOL_GPL(wm9712_codec);
-+
-+/* Module information */
-+MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
-+MODULE_DESCRIPTION("WM9712 Touch Screen Driver");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c
-new file mode 100644
-index 0000000..01278bd
---- /dev/null
-+++ b/drivers/input/touchscreen/wm9713.c
-@@ -0,0 +1,460 @@
-+/*
-+ * wm9713.c -- Codec touch driver for Wolfson WM9713 AC97 Codec.
-+ *
-+ * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
-+ * Author: Liam Girdwood
-+ * liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
-+ * Parts Copyright : Ian Molton <spyro at f2s.com>
-+ * Andrew Zabolotny <zap at homelink.ru>
-+ * Russell King <rmk at arm.linux.org.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2 of the License, or (at your
-+ * option) any later version.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/version.h>
-+#include <linux/kernel.h>
-+#include <linux/input.h>
-+#include <linux/delay.h>
-+#include <linux/bitops.h>
-+#include <linux/wm97xx.h>
-+
-+#define TS_NAME "wm97xx"
-+#define WM9713_VERSION "1.00"
-+#define DEFAULT_PRESSURE 0xb0c0
-+
-+/*
-+ * Module parameters
-+ */
-+
-+/*
-+ * Set internal pull up for pen detect.
-+ *
-+ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
-+ * i.e. pull up resistance = 64k Ohms / rpu.
-+ *
-+ * Adjust this value if you are having problems with pen detect not
-+ * detecting any down event.
-+ */
-+static int rpu = 8;
-+module_param(rpu, int, 0);
-+MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
-+
-+/*
-+ * Set current used for pressure measurement.
-+ *
-+ * Set pil = 2 to use 400uA
-+ * pil = 1 to use 200uA and
-+ * pil = 0 to disable pressure measurement.
-+ *
-+ * This is used to increase the range of values returned by the adc
-+ * when measureing touchpanel pressure.
-+ */
-+static int pil;
-+module_param(pil, int, 0);
-+MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
+
-+/*
-+ * Set threshold for pressure measurement.
-+ *
-+ * Pen down pressure below threshold is ignored.
-+ */
-+static int pressure = DEFAULT_PRESSURE & 0xfff;
-+module_param(pressure, int, 0);
-+MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
++static int debug;
+
-+/*
-+ * 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.");
++#define dprintk(arg...) do { \
++ if (debug) \
++ printk(arg); \
++ } while (0)
+
-+/*
-+ * 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.");
++/* 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, },
++};
+
-+/*
-+ * 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");
++/* 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, },
++};
+
-+/*
-+ * 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 */
++/* 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, },
+};
+
-+/*
-+ * 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]);
-+}
++/* 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, },
++};
+
-+/*
-+ * set up the physical settings of the WM9713
-+ */
-+static void wm9713_phy_init(struct wm97xx *wm)
++/* 8 bit registers, 16 bit values */
++static int s5h1411_writereg(struct s5h1411_state *state,
++ u8 addr, u8 reg, u16 data)
+{
-+ 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;
++ int ret;
++ u8 buf [] = { reg, data >> 8, data & 0xff };
+
-+ /* 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);
++ struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
+
-+ /* mask */
-+ dig3 |= ((mask & 0x3) << 4);
-+ if (coord)
-+ dig3 |= WM9713_WAIT;
++ ret = i2c_transfer(state->i2c, &msg, 1);
+
-+ wm->misc = wm97xx_reg_read(wm, 0x5a);
++ if (ret != 1)
++ printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, "
++ "ret == %i)\n", __func__, addr, reg, data, ret);
+
-+ 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);
++ return (ret != 1) ? -1 : 0;
+}
+
-+static void wm9713_dig_enable(struct wm97xx *wm, int enable)
++static u16 s5h1411_readreg(struct s5h1411_state *state, u8 addr, u8 reg)
+{
-+ 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);
-+ }
-+}
++ int ret;
++ u8 b0 [] = { reg };
++ u8 b1 [] = { 0, 0 };
+
-+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]);
-+}
++ struct i2c_msg msg [] = {
++ { .addr = addr, .flags = 0, .buf = b0, .len = 1 },
++ { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 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);
-+}
++ ret = i2c_transfer(state->i2c, msg, 2);
+
-+static inline int is_pden(struct wm97xx *wm)
-+{
-+ return wm->dig[2] & WM9713_PDEN;
++ if (ret != 2)
++ printk(KERN_ERR "%s: readreg error (ret == %i)\n",
++ __func__, ret);
++ return (b1[0] << 8) | b1[1];
+}
+
-+/*
-+ * Read a sample from the WM9713 adc in polling mode.
-+ */
-+static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
++static int s5h1411_softreset(struct dvb_frontend *fe)
+{
-+ 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;
-+ }
++ struct s5h1411_state *state = fe->demodulator_priv;
+
-+ if (!(*sample & WM97XX_PEN_DOWN)) {
-+ wm->pen_probably_down = 0;
-+ return RC_PENUP;
-+ }
++ dprintk("%s()\n", __func__);
+
-+ return RC_VALID;
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 0);
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 1);
++ return 0;
+}
+
-+/*
-+ * Read a coordinate from the WM9713 adc in polling mode.
-+ */
-+static int wm9713_poll_coord(struct wm97xx *wm, struct wm97xx_data *data)
++static int s5h1411_set_if_freq(struct dvb_frontend *fe, int KHz)
+{
-+ 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);
++ struct s5h1411_state *state = fe->demodulator_priv;
+
-+ /* 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--;
-+ }
++ dprintk("%s(%d KHz)\n", __func__, KHz);
+
-+ 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;
++ 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;
+ }
+
-+ /* 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;
++ state->if_freq = KHz;
+
-+ 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)
++static int s5h1411_set_mpeg_timing(struct dvb_frontend *fe, int mode)
+{
-+ u16 dig1, dig2, dig3;
-+ int ret = 0;
-+
-+ dig1 = wm->dig[0];
-+ dig2 = wm->dig[1];
-+ dig3 = wm->dig[2];
++ struct s5h1411_state *state = fe->demodulator_priv;
++ u16 val;
+
-+ if (enable) {
-+ /* continous mode */
-+ if (wm->mach_ops->acc_startup &&
-+ (ret = wm->mach_ops->acc_startup(wm)) < 0)
-+ return ret;
++ dprintk("%s(%d)\n", __func__, mode);
+
-+ 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);
++ 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;
+ }
+
-+ wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
-+ wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
-+ wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
-+
-+ return ret;
-+}
-+
-+struct wm97xx_codec_drv wm9713_codec = {
-+ .id = WM9713_ID2,
-+ .name = "wm9713",
-+ .poll_sample = wm9713_poll_sample,
-+ .poll_touch = wm9713_poll_touch,
-+ .acc_enable = wm9713_acc_enable,
-+ .phy_init = wm9713_phy_init,
-+ .dig_enable = wm9713_dig_enable,
-+ .dig_restore = wm9713_dig_restore,
-+ .aux_prepare = wm9713_aux_prepare,
-+};
-+EXPORT_SYMBOL_GPL(wm9713_codec);
-+
-+/* Module information */
-+MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
-+MODULE_DESCRIPTION("WM9713 Touch Screen Driver");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
-new file mode 100644
-index 0000000..e9c7ea4
---- /dev/null
-+++ b/drivers/input/touchscreen/wm97xx-core.c
-@@ -0,0 +1,829 @@
-+/*
-+ * wm97xx-core.c -- Touch screen driver core for Wolfson WM9705, WM9712
-+ * and WM9713 AC97 Codecs.
-+ *
-+ * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
-+ * Author: Liam Girdwood
-+ * liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
-+ * Parts Copyright : Ian Molton <spyro at f2s.com>
-+ * Andrew Zabolotny <zap at homelink.ru>
-+ * Russell King <rmk at arm.linux.org.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2 of the License, or (at your
-+ * option) any later version.
-+ *
-+ * Notes:
-+ *
-+ * Features:
-+ * - supports WM9705, WM9712, WM9713
-+ * - polling mode
-+ * - continuous mode (arch-dependent)
-+ * - adjustable rpu/dpp settings
-+ * - adjustable pressure current
-+ * - adjustable sample settle delay
-+ * - 4 and 5 wire touchscreens (5 wire is WM9712 only)
-+ * - pen down detection
-+ * - battery monitor
-+ * - sample AUX adcs
-+ * - power management
-+ * - codec GPIO
-+ * - codec event notification
-+ * Todo
-+ * - Support for async sampling control for noisy LCDs.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/version.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/string.h>
-+#include <linux/proc_fs.h>
-+#include <linux/pm.h>
-+#include <linux/interrupt.h>
-+#include <linux/bitops.h>
-+#include <linux/workqueue.h>
-+#include <linux/wm97xx.h>
-+#include <linux/uaccess.h>
-+#include <linux/io.h>
-+
-+#define TS_NAME "wm97xx"
-+#define WM_CORE_VERSION "1.00"
-+#define DEFAULT_PRESSURE 0xb0c0
-+
-+
-+/*
-+ * Touchscreen absolute values
-+ *
-+ * These parameters are used to help the input layer discard out of
-+ * range readings and reduce jitter etc.
-+ *
-+ * o min, max:- indicate the min and max values your touch screen returns
-+ * o fuzz:- use a higher number to reduce jitter
-+ *
-+ * The default values correspond to Mainstone II in QVGA mode
-+ *
-+ * Please read
-+ * Documentation/input/input-programming.txt for more details.
-+ */
-+
-+static int abs_x[3] = {350, 3900, 5};
-+module_param_array(abs_x, int, NULL, 0);
-+MODULE_PARM_DESC(abs_x, "Touchscreen absolute X min, max, fuzz");
-+
-+static int abs_y[3] = {320, 3750, 40};
-+module_param_array(abs_y, int, NULL, 0);
-+MODULE_PARM_DESC(abs_y, "Touchscreen absolute Y min, max, fuzz");
-+
-+static int abs_p[3] = {0, 150, 4};
-+module_param_array(abs_p, int, NULL, 0);
-+MODULE_PARM_DESC(abs_p, "Touchscreen absolute Pressure min, max, fuzz");
-+
-+/*
-+ * wm97xx IO access, all IO locking done by AC97 layer
-+ */
-+int wm97xx_reg_read(struct wm97xx *wm, u16 reg)
-+{
-+ if (wm->ac97)
-+ return wm->ac97->bus->ops->read(wm->ac97, reg);
-+ else
-+ return -1;
++ /* Configure MPEG Signal Timing charactistics */
++ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbe, val);
+}
-+EXPORT_SYMBOL_GPL(wm97xx_reg_read);
+
-+void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val)
++static int s5h1411_set_spectralinversion(struct dvb_frontend *fe, int inversion)
+{
-+ /* cache digitiser registers */
-+ if (reg >= AC97_WM9713_DIG1 && reg <= AC97_WM9713_DIG3)
-+ wm->dig[(reg - AC97_WM9713_DIG1) >> 1] = val;
++ struct s5h1411_state *state = fe->demodulator_priv;
++ u16 val;
+
-+ /* cache gpio regs */
-+ if (reg >= AC97_GPIO_CFG && reg <= AC97_MISC_AFE)
-+ wm->gpio[(reg - AC97_GPIO_CFG) >> 1] = val;
++ dprintk("%s(%d)\n", __func__, inversion);
++ val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x24) & ~0x1000;
+
-+ /* wm9713 irq reg */
-+ if (reg == 0x5a)
-+ wm->misc = val;
++ if (inversion == 1)
++ val |= 0x1000; /* Inverted */
++ else
++ val |= 0x0000;
+
-+ if (wm->ac97)
-+ wm->ac97->bus->ops->write(wm->ac97, reg, val);
++ state->inversion = inversion;
++ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x24, 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)
++static int s5h1411_enable_modulation(struct dvb_frontend *fe,
++ fe_modulation_t m)
+{
-+ int power_adc = 0, auxval;
-+ u16 power = 0;
++ struct s5h1411_state *state = fe->demodulator_priv;
+
-+ /* get codec */
-+ mutex_lock(&wm->codec_mutex);
++ dprintk("%s(0x%08x)\n", __func__, m);
+
-+ /* 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);
++ 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;
+ }
+
-+ /* 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;
++ state->current_modulation = m;
++ s5h1411_softreset(fe);
+
-+ mutex_unlock(&wm->codec_mutex);
-+ return ret;
++ return 0;
+}
-+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)
++static int s5h1411_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
-+ u16 reg;
-+
-+ mutex_lock(&wm->codec_mutex);
-+ reg = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
++ struct s5h1411_state *state = fe->demodulator_priv;
+
-+ if (status & WM97XX_GPIO_HIGH)
-+ reg |= gpio;
-+ else
-+ reg &= ~gpio;
++ dprintk("%s(%d)\n", __func__, enable);
+
-+ if (wm->id == WM9712_ID2)
-+ wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1);
++ if (enable)
++ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
+ else
-+ wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg);
-+ mutex_unlock(&wm->codec_mutex);
++ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 0);
+}
-+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)
++static int s5h1411_set_gpio(struct dvb_frontend *fe, int enable)
+{
-+ 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);
++ struct s5h1411_state *state = fe->demodulator_priv;
++ u16 val;
+
-+ if (wake == WM97XX_GPIO_WAKE)
-+ reg |= gpio;
-+ else
-+ reg &= ~gpio;
++ dprintk("%s(%d)\n", __func__, enable);
+
-+ wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, reg);
-+ reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
++ val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xe0) & ~0x02;
+
-+ if (dir == WM97XX_GPIO_IN)
-+ reg |= gpio;
++ if (enable)
++ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0,
++ val | 0x02);
+ 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);
++ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0, val);
+}
-+EXPORT_SYMBOL_GPL(wm97xx_set_suspend_mode);
+
-+/*
-+ * Handle a pen down interrupt.
-+ */
-+static void wm97xx_pen_irq_worker(struct work_struct *work)
++static int s5h1411_sleep(struct dvb_frontend *fe, int enable)
+{
-+ 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);
-+ }
++ struct s5h1411_state *state = fe->demodulator_priv;
+
-+ /* 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);
-+ }
++ dprintk("%s(%d)\n", __func__, enable);
+
-+ /* Let ts_reader report the pen up for debounce. */
-+ if (!wm->pen_is_down && pen_was_down)
-+ wm->pen_is_down = 1;
++ if (enable)
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 1);
++ else {
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 0);
++ s5h1411_softreset(fe);
+ }
+
-+ if (!wm->pen_is_down && wm->mach_ops->acc_enabled)
-+ wm->mach_ops->acc_pen_up(wm);
-+
-+ wm->mach_ops->irq_enable(wm, 1);
++ return 0;
+}
+
-+/*
-+ * 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)
++static int s5h1411_register_reset(struct dvb_frontend *fe)
+{
-+ struct wm97xx *wm = dev_id;
++ struct s5h1411_state *state = fe->demodulator_priv;
+
-+ if (!work_pending(&wm->pen_event_work)) {
-+ wm->mach_ops->irq_enable(wm, 0);
-+ queue_work(wm->ts_workq, &wm->pen_event_work);
-+ }
++ dprintk("%s()\n", __func__);
+
-+ return IRQ_HANDLED;
++ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf3, 0);
+}
+
-+/*
-+ * initialise pen IRQ handler and workqueue
-+ */
-+static int wm97xx_init_pen_irq(struct wm97xx *wm)
++/* 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)
+{
-+ u16 reg;
-+
-+ /* If an interrupt is supplied an IRQ enable operation must also be
-+ * provided. */
-+ BUG_ON(!wm->mach_ops->irq_enable);
++ struct s5h1411_state *state = fe->demodulator_priv;
+
-+ 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;
-+ }
++ dprintk("%s(frequency=%d)\n", __func__, p->frequency);
+
-+ /* 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);
-+ }
++ s5h1411_softreset(fe);
+
-+ return 0;
-+}
++ state->current_frequency = p->frequency;
+
-+static int wm97xx_read_samples(struct wm97xx *wm)
-+{
-+ struct wm97xx_data data;
-+ int rc;
++ s5h1411_enable_modulation(fe, p->u.vsb.modulation);
+
-+ mutex_lock(&wm->codec_mutex);
++ /* Allow the demod to settle */
++ msleep(100);
+
-+ 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 (fe->ops.tuner_ops.set_params) {
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
+
-+ 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++;
-+ }
++ fe->ops.tuner_ops.set_params(fe, p);
+
-+ } 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;
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
-+ 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);
++ return 0;
+}
+
-+/**
-+ * 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)
++/* Reset the demod hardware and reset all of the configuration registers
++ to a default state. */
++static int s5h1411_init(struct dvb_frontend *fe)
+{
-+ struct wm97xx *wm = input_get_drvdata(idev);
++ struct s5h1411_state *state = fe->demodulator_priv;
++ int i;
+
-+ wm->ts_workq = create_singlethread_workqueue("kwm97xx");
-+ if (wm->ts_workq == NULL) {
-+ dev_err(wm->dev,
-+ "Failed to create workqueue\n");
-+ return -EINVAL;
-+ }
++ dprintk("%s()\n", __func__);
+
-+ /* start digitiser */
-+ if (wm->mach_ops && wm->mach_ops->acc_enabled)
-+ wm->codec->acc_enable(wm, 1);
-+ wm->codec->dig_enable(wm, 1);
++ s5h1411_sleep(fe, 0);
++ s5h1411_register_reset(fe);
+
-+ INIT_DELAYED_WORK(&wm->ts_reader, wm97xx_ts_reader);
-+ INIT_WORK(&wm->pen_event_work, wm97xx_pen_irq_worker);
++ for (i = 0; i < ARRAY_SIZE(init_tab); i++)
++ s5h1411_writereg(state, init_tab[i].addr,
++ init_tab[i].reg,
++ init_tab[i].data);
+
-+ 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;
++ /* The datasheet says that after initialisation, VSB is default */
++ state->current_modulation = VSB_8;
+
-+ wm->pen_is_down = 0;
-+ if (wm->pen_irq)
-+ wm97xx_init_pen_irq(wm);
++ if (state->config->output_mode == S5H1411_SERIAL_OUTPUT)
++ /* Serial */
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1101);
+ else
-+ dev_err(wm->dev, "No IRQ specified\n");
++ /* Parallel */
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1001);
+
-+ /* 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);
++ 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;
+}
+
-+/**
-+ * 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)
++static int s5h1411_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
-+ struct wm97xx *wm = input_get_drvdata(idev);
++ struct s5h1411_state *state = fe->demodulator_priv;
+ u16 reg;
++ u32 tuner_status = 0;
+
-+ 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);
++ *status = 0;
+
-+ dev_info(wm->dev, "detected a wm97%02x codec\n", wm->id & 0xff);
++ /* 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 (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;
++ 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;
-+#endif
-+#ifdef CONFIG_TOUCHSCREEN_WM9713
-+ case 0x13:
-+ wm->codec = &wm9713_codec;
++ 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;
-+#endif
+ default:
-+ dev_err(wm->dev, "Support for wm97%02x not compiled in.\n",
-+ wm->id & 0xff);
-+ ret = -ENODEV;
-+ goto alloc_err;
-+ }
-+
-+ wm->input_dev = input_allocate_device();
-+ if (wm->input_dev == NULL) {
-+ ret = -ENOMEM;
-+ goto alloc_err;
-+ }
-+
-+ /* set up touch configuration */
-+ wm->input_dev->name = "wm97xx touchscreen";
-+ wm->input_dev->open = wm97xx_ts_input_open;
-+ wm->input_dev->close = wm97xx_ts_input_close;
-+ set_bit(EV_ABS, wm->input_dev->evbit);
-+ set_bit(ABS_X, wm->input_dev->absbit);
-+ set_bit(ABS_Y, wm->input_dev->absbit);
-+ set_bit(ABS_PRESSURE, wm->input_dev->absbit);
-+ input_set_abs_params(wm->input_dev, ABS_X, abs_x[0], abs_x[1],
-+ abs_x[2], 0);
-+ input_set_abs_params(wm->input_dev, ABS_Y, abs_y[0], abs_y[1],
-+ abs_y[2], 0);
-+ input_set_abs_params(wm->input_dev, ABS_PRESSURE, abs_p[0], abs_p[1],
-+ abs_p[2], 0);
-+ input_set_drvdata(wm->input_dev, wm);
-+ wm->input_dev->dev.parent = dev;
-+ ret = input_register_device(wm->input_dev);
-+ if (ret < 0)
-+ goto dev_alloc_err;
-+
-+ /* set up physical characteristics */
-+ wm->codec->phy_init(wm);
-+
-+ /* load gpio cache */
-+ wm->gpio[0] = wm97xx_reg_read(wm, AC97_GPIO_CFG);
-+ wm->gpio[1] = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
-+ wm->gpio[2] = wm97xx_reg_read(wm, AC97_GPIO_STICKY);
-+ wm->gpio[3] = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP);
-+ wm->gpio[4] = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
-+ wm->gpio[5] = wm97xx_reg_read(wm, AC97_MISC_AFE);
-+
-+ /* register our battery device */
-+ wm->battery_dev = platform_device_alloc("wm97xx-battery", -1);
-+ if (!wm->battery_dev) {
-+ ret = -ENOMEM;
-+ goto batt_err;
-+ }
-+ platform_set_drvdata(wm->battery_dev, wm);
-+ wm->battery_dev->dev.parent = dev;
-+ ret = platform_device_add(wm->battery_dev);
-+ if (ret < 0)
-+ goto batt_reg_err;
-+
-+ /* register our extended touch device (for machine specific
-+ * extensions) */
-+ wm->touch_dev = platform_device_alloc("wm97xx-touch", -1);
-+ if (!wm->touch_dev) {
-+ ret = -ENOMEM;
-+ goto touch_err;
-+ }
-+ platform_set_drvdata(wm->touch_dev, wm);
-+ wm->touch_dev->dev.parent = dev;
-+ ret = platform_device_add(wm->touch_dev);
-+ if (ret < 0)
-+ goto touch_reg_err;
-+
-+ return ret;
-+
-+ touch_reg_err:
-+ platform_device_put(wm->touch_dev);
-+ touch_err:
-+ platform_device_unregister(wm->battery_dev);
-+ wm->battery_dev = NULL;
-+ batt_reg_err:
-+ platform_device_put(wm->battery_dev);
-+ batt_err:
-+ input_unregister_device(wm->input_dev);
-+ wm->input_dev = NULL;
-+ dev_alloc_err:
-+ input_free_device(wm->input_dev);
-+ alloc_err:
-+ kfree(wm);
-+
-+ return ret;
-+}
-+
-+static int wm97xx_remove(struct device *dev)
-+{
-+ struct wm97xx *wm = dev_get_drvdata(dev);
-+
-+ platform_device_unregister(wm->battery_dev);
-+ platform_device_unregister(wm->touch_dev);
-+ input_unregister_device(wm->input_dev);
-+ kfree(wm);
-+
-+ return 0;
-+}
-+
-+#ifdef CONFIG_PM
-+static int wm97xx_suspend(struct device *dev, pm_message_t state)
-+{
-+ struct wm97xx *wm = dev_get_drvdata(dev);
-+ u16 reg;
-+ int suspend_mode;
-+
-+ if (device_may_wakeup(&wm->input_dev->dev))
-+ suspend_mode = wm->suspend_mode;
-+ else
-+ suspend_mode = 0;
-+
-+ if (wm->input_dev->users)
-+ cancel_delayed_work_sync(&wm->ts_reader);
-+
-+ /* Power down the digitiser (bypassing the cache for resume) */
-+ reg = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER2);
-+ reg &= ~WM97XX_PRP_DET_DIG;
-+ if (wm->input_dev->users)
-+ reg |= suspend_mode;
-+ wm->ac97->bus->ops->write(wm->ac97, AC97_WM97XX_DIGITISER2, reg);
-+
-+ /* WM9713 has an additional power bit - turn it off if there
-+ * are no users or if suspend mode is zero. */
-+ if (wm->id == WM9713_ID2 &&
-+ (!wm->input_dev->users || !suspend_mode)) {
-+ reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) | 0x8000;
-+ wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
-+ }
-+
-+ return 0;
-+}
-+
-+static int wm97xx_resume(struct device *dev)
-+{
-+ struct wm97xx *wm = dev_get_drvdata(dev);
-+
-+ /* restore digitiser and gpios */
-+ if (wm->id == WM9713_ID2) {
-+ wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig[0]);
-+ wm97xx_reg_write(wm, 0x5a, wm->misc);
-+ if (wm->input_dev->users) {
-+ u16 reg;
-+ reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) & 0x7fff;
-+ wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
-+ }
-+ }
-+
-+ wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig[1]);
-+ wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2]);
-+
-+ wm97xx_reg_write(wm, AC97_GPIO_CFG, wm->gpio[0]);
-+ wm97xx_reg_write(wm, AC97_GPIO_POLARITY, wm->gpio[1]);
-+ wm97xx_reg_write(wm, AC97_GPIO_STICKY, wm->gpio[2]);
-+ wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, wm->gpio[3]);
-+ wm97xx_reg_write(wm, AC97_GPIO_STATUS, wm->gpio[4]);
-+ wm97xx_reg_write(wm, AC97_MISC_AFE, wm->gpio[5]);
-+
-+ if (wm->input_dev->users && !wm->pen_irq) {
-+ wm->ts_reader_interval = wm->ts_reader_min_interval;
-+ queue_delayed_work(wm->ts_workq, &wm->ts_reader,
-+ wm->ts_reader_interval);
-+ }
-+
-+ return 0;
-+}
-+
-+#else
-+#define wm97xx_suspend NULL
-+#define wm97xx_resume NULL
-+#endif
-+
-+/*
-+ * Machine specific operations
-+ */
-+int wm97xx_register_mach_ops(struct wm97xx *wm,
-+ struct wm97xx_mach_ops *mach_ops)
-+{
-+ mutex_lock(&wm->codec_mutex);
-+ if (wm->mach_ops) {
-+ mutex_unlock(&wm->codec_mutex);
+ return -EINVAL;
-+ }
-+ wm->mach_ops = mach_ops;
-+ mutex_unlock(&wm->codec_mutex);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(wm97xx_register_mach_ops);
-+
-+void wm97xx_unregister_mach_ops(struct wm97xx *wm)
-+{
-+ mutex_lock(&wm->codec_mutex);
-+ wm->mach_ops = NULL;
-+ mutex_unlock(&wm->codec_mutex);
-+}
-+EXPORT_SYMBOL_GPL(wm97xx_unregister_mach_ops);
-+
-+static struct device_driver wm97xx_driver = {
-+ .name = "ac97",
-+ .bus = &ac97_bus_type,
-+ .owner = THIS_MODULE,
-+ .probe = wm97xx_probe,
-+ .remove = wm97xx_remove,
-+ .suspend = wm97xx_suspend,
-+ .resume = wm97xx_resume,
-+};
-+
-+static int __init wm97xx_init(void)
-+{
-+ return driver_register(&wm97xx_driver);
-+}
-+
-+static void __exit wm97xx_exit(void)
-+{
-+ driver_unregister(&wm97xx_driver);
-+}
-+
-+module_init(wm97xx_init);
-+module_exit(wm97xx_exit);
-+
-+/* Module information */
-+MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
-+MODULE_DESCRIPTION("WM97xx Core - Touch Screen / AUX ADC / GPIO Driver");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c
-new file mode 100644
-index 0000000..0f47f46
---- /dev/null
-+++ b/drivers/input/xen-kbdfront.c
-@@ -0,0 +1,340 @@
-+/*
-+ * Xen para-virtual input device
-+ *
-+ * Copyright (C) 2005 Anthony Liguori <aliguori at us.ibm.com>
-+ * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru at redhat.com>
-+ *
-+ * Based on linux/drivers/input/mouse/sermouse.c
-+ *
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file COPYING in the main directory of this archive for
-+ * more details.
-+ */
++ }
+
-+/*
-+ * TODO:
-+ *
-+ * Switch to grant tables together with xen-fbfront.c.
-+ */
++ 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);
+
-+#include <linux/kernel.h>
-+#include <linux/errno.h>
-+#include <linux/module.h>
-+#include <linux/input.h>
-+#include <asm/xen/hypervisor.h>
-+#include <xen/events.h>
-+#include <xen/page.h>
-+#include <xen/interface/io/fbif.h>
-+#include <xen/interface/io/kbdif.h>
-+#include <xen/xenbus.h>
++ fe->ops.tuner_ops.get_status(fe, &tuner_status);
+
-+struct xenkbd_info {
-+ struct input_dev *kbd;
-+ struct input_dev *ptr;
-+ struct xenkbd_page *page;
-+ int irq;
-+ struct xenbus_device *xbdev;
-+ char phys[32];
-+};
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 0);
++ }
++ if (tuner_status)
++ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
++ break;
++ }
+
-+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 *);
++ dprintk("%s() status 0x%08x\n", __func__, *status);
+
-+/*
-+ * Note: if you need to send out events, see xenfb_do_update() for how
-+ * to do that.
-+ */
++ return 0;
++}
+
-+static irqreturn_t input_handler(int rq, void *dev_id)
++static int s5h1411_qam256_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
+{
-+ 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);
++ int i, ret = -EINVAL;
++ dprintk("%s()\n", __func__);
+
-+ 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);
++ 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;
+ }
-+ if (dev)
-+ input_sync(dev);
+ }
-+ mb(); /* ensure we got ring contents */
-+ page->in_cons = cons;
-+ notify_remote_via_irq(info->irq);
-+
-+ return IRQ_HANDLED;
++ return ret;
+}
+
-+static int __devinit xenkbd_probe(struct xenbus_device *dev,
-+ const struct xenbus_device_id *id)
++static int s5h1411_qam64_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
+{
-+ int ret, i;
-+ struct xenkbd_info *info;
-+ struct input_dev *kbd, *ptr;
++ int i, ret = -EINVAL;
++ dprintk("%s()\n", __func__);
+
-+ info = kzalloc(sizeof(*info), GFP_KERNEL);
-+ if (!info) {
-+ xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
-+ return -ENOMEM;
++ 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;
++ }
+ }
-+ 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;
++ return ret;
++}
+
-+ /* 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);
++static int s5h1411_vsb_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
++{
++ int i, ret = -EINVAL;
++ dprintk("%s()\n", __func__);
+
-+ ret = input_register_device(kbd);
-+ if (ret) {
-+ input_free_device(kbd);
-+ xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
-+ goto error;
++ 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;
++ }
+ }
-+ info->kbd = kbd;
++ dprintk("%s() snr=%d\n", __func__, *snr);
++ return ret;
++}
+
-+ /* 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);
++static int s5h1411_read_snr(struct dvb_frontend *fe, u16 *snr)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
++ u16 reg;
++ dprintk("%s()\n", __func__);
+
-+ ret = input_register_device(ptr);
-+ if (ret) {
-+ input_free_device(ptr);
-+ xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
-+ goto error;
++ 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;
+ }
-+ 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;
++ return -EINVAL;
+}
+
-+static int xenkbd_resume(struct xenbus_device *dev)
++static int s5h1411_read_signal_strength(struct dvb_frontend *fe,
++ u16 *signal_strength)
+{
-+ struct xenkbd_info *info = dev->dev.driver_data;
-+
-+ xenkbd_disconnect_backend(info);
-+ memset(info->page, 0, PAGE_SIZE);
-+ return xenkbd_connect_backend(dev, info);
++ return s5h1411_read_snr(fe, signal_strength);
+}
+
-+static int xenkbd_remove(struct xenbus_device *dev)
++static int s5h1411_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
-+ struct xenkbd_info *info = dev->dev.driver_data;
++ struct s5h1411_state *state = fe->demodulator_priv;
++
++ *ucblocks = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xc9);
+
-+ 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)
++static int s5h1411_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
-+ int ret, evtchn;
-+ struct xenbus_transaction xbt;
++ return s5h1411_read_ucblocks(fe, ber);
++}
+
-+ 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;
++static int s5h1411_get_frontend(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *p)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
+
-+ 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;
-+ }
++ p->frequency = state->current_frequency;
++ p->u.vsb.modulation = state->current_modulation;
+
-+ xenbus_switch_state(dev, XenbusStateInitialised);
+ return 0;
++}
+
-+ error_xenbus:
-+ xenbus_transaction_end(xbt, 1);
-+ xenbus_dev_fatal(dev, ret, "writing xenstore");
-+ return ret;
++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 xenkbd_disconnect_backend(struct xenkbd_info *info)
++static void s5h1411_release(struct dvb_frontend *fe)
+{
-+ if (info->irq >= 0)
-+ unbind_from_irqhandler(info->irq, info);
-+ info->irq = -1;
++ struct s5h1411_state *state = fe->demodulator_priv;
++ kfree(state);
+}
+
-+static void xenkbd_backend_changed(struct xenbus_device *dev,
-+ enum xenbus_state backend_state)
++static struct dvb_frontend_ops s5h1411_ops;
++
++struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
++ struct i2c_adapter *i2c)
+{
-+ struct xenkbd_info *info = dev->dev.driver_data;
-+ int ret, val;
++ struct s5h1411_state *state = NULL;
++ u16 reg;
+
-+ switch (backend_state) {
-+ case XenbusStateInitialising:
-+ case XenbusStateInitialised:
-+ case XenbusStateUnknown:
-+ case XenbusStateClosed:
-+ break;
++ /* allocate memory for the internal state */
++ state = kmalloc(sizeof(struct s5h1411_state), GFP_KERNEL);
++ if (state == NULL)
++ goto error;
+
-+ 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;
++ /* setup the state */
++ state->config = config;
++ state->i2c = i2c;
++ state->current_modulation = VSB_8;
++ state->inversion = state->config->inversion;
+
-+ 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;
++ /* check if the demod exists */
++ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x05);
++ if (reg != 0x0066)
++ goto error;
+
-+ case XenbusStateClosing:
-+ xenbus_frontend_closed(dev);
-+ break;
++ /* 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 xenbus_device_id xenkbd_ids[] = {
-+ { "vkbd" },
-+ { "" }
-+};
++static struct dvb_frontend_ops s5h1411_ops = {
+
-+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,
++ .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,
+};
+
-+static int __init xenkbd_init(void)
-+{
-+ if (!is_running_on_xen())
-+ return -ENODEV;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
-+ /* Nothing to do if running in dom0. */
-+ if (is_initial_xendomain())
-+ return -ENODEV;
++MODULE_DESCRIPTION("Samsung S5H1411 QAM-B/ATSC Demodulator driver");
++MODULE_AUTHOR("Steven Toth");
++MODULE_LICENSE("GPL");
+
-+ return xenbus_register_frontend(&xenkbd);
-+}
++/*
++ * 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
+
-+static void __exit xenkbd_cleanup(void)
++ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++#ifndef __S5H1411_H__
++#define __S5H1411_H__
++
++#include <linux/dvb/frontend.h>
++
++#define S5H1411_I2C_TOP_ADDR (0x32 >> 1)
++#define S5H1411_I2C_QAM_ADDR (0x34 >> 1)
++
++struct s5h1411_config {
++
++ /* serial/parallel output */
++#define S5H1411_PARALLEL_OUTPUT 0
++#define S5H1411_SERIAL_OUTPUT 1
++ u8 output_mode;
++
++ /* GPIO Setting */
++#define S5H1411_GPIO_OFF 0
++#define S5H1411_GPIO_ON 1
++ u8 gpio;
++
++ /* MPEG signal timing */
++#define S5H1411_MPEGTIMING_CONTINOUS_INVERTING_CLOCK 0
++#define S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK 1
++#define S5H1411_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK 2
++#define S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK 3
++ u16 mpeg_timing;
++
++ /* IF Freq for QAM and VSB in KHz */
++#define S5H1411_IF_2500 2500
++#define S5H1411_IF_3500 3500
++#define S5H1411_IF_4000 4000
++#define S5H1411_IF_5380 5380
++#define S5H1411_IF_44000 44000
++#define S5H1411_VSB_IF_DEFAULT S5H1411_IF_44000
++#define S5H1411_QAM_IF_DEFAULT S5H1411_IF_44000
++ u16 qam_if;
++ u16 vsb_if;
++
++ /* Spectral Inversion */
++#define S5H1411_INVERSION_OFF 0
++#define S5H1411_INVERSION_ON 1
++ u8 inversion;
++
++ /* Return lock status based on tuner lock, or demod lock */
++#define S5H1411_TUNERLOCKING 0
++#define S5H1411_DEMODLOCKING 1
++ u8 status_mode;
++};
++
++#if defined(CONFIG_DVB_S5H1411) || \
++ (defined(CONFIG_DVB_S5H1411_MODULE) && defined(MODULE))
++extern struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
++ struct i2c_adapter *i2c);
++#else
++static inline struct dvb_frontend *s5h1411_attach(
++ const struct s5h1411_config *config,
++ struct i2c_adapter *i2c)
+{
-+ xenbus_unregister_driver(&xenkbd);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++ return NULL;
+}
++#endif /* CONFIG_DVB_S5H1411 */
+
-+module_init(xenkbd_init);
-+module_exit(xenkbd_cleanup);
++#endif /* __S5H1411_H__ */
+
-+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[];
++/*
++ * Local variables:
++ * c-basic-offset: 8
++ */
+diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
+index 2c2c344..720ed9f 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
-
- 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 $";
+-Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
+-
+-This program is free software; you can redistribute it and/or modify
+-it under the terms of the GNU General Public License as published by
+-the Free Software Foundation; either version 2 of the License, or
+-(at your option) any later version.
+-
+-This program is distributed in the hope that it will be useful,
+-but WITHOUT ANY WARRANTY; without even the implied warranty of
+-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-
+-GNU General Public License for more details.
+-
+-You should have received a copy of the GNU General Public License
+-along with this program; if not, write to the Free Software
+-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-*/
++ * Driver for
++ * Samsung S5H1420 and
++ * PnpNetwork PN1010 QPSK Demodulator
++ *
++ * Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
++ * Copyright (C) 2005-8 Patrick Boettcher <pb at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
- #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);
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+@@ -29,23 +31,35 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ #include <linux/jiffies.h>
+ #include <asm/div64.h>
-- printk(KERN_INFO
-- "HiSax: %s config irq:%d cfg:0x%X\n",
-- CardType[cs->typ], cs->irq,
-+ printk(KERN_INFO "HiSax: AVM A1 config irq:%d cfg:0x%X\n",
-+ cs->irq,
- cs->hw.avm.cfg_reg);
- printk(KERN_INFO
- "HiSax: isac:0x%X/0x%X\n",
-diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
-index 3d1bdc8..9ca2ee5 100644
---- a/drivers/isdn/hisax/bkm_a4t.c
-+++ b/drivers/isdn/hisax/bkm_a4t.c
-@@ -20,8 +20,6 @@
- #include <linux/pci.h>
- #include "bkm_ax.h"
+-#include "dvb_frontend.h"
+-#include "s5h1420.h"
++#include <linux/i2c.h>
--extern const char *CardType[];
--
- static const char *bkm_a4t_revision = "$Revision: 1.22.2.4 $";
++#include "dvb_frontend.h"
++#include "s5h1420.h"
++#include "s5h1420_priv.h"
-@@ -284,15 +282,16 @@ static int __devinit a4t_cs_init(struct IsdnCard *card,
- I20_REGISTER_FILE *pI20_Regs;
+ #define TONE_FREQ 22000
- 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;
+ 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;
-- 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);
+ 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];
+ };
- 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);
- }
+ 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);
-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 */
+-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];
++}
--extern const char *CardType[];
--
- static const char sct_quadro_revision[] = "$Revision: 1.22.2.4 $";
+ 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;
- 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);
+- 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;
}
-@@ -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;
++ state->shadow[reg] = data;
-- 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;
+ return 0;
+ }
-- 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)
+-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)
{
- 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;
+ struct s5h1420_state* state = fe->demodulator_priv;
- 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);
- }
++ 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;
}
- #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)
- }
++ dprintk("leave %s\n", __func__);
+ return 0;
+ }
--static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs)
-+static void rs_interrupt_elsa(struct IsdnCardState *cs)
+@@ -113,6 +150,7 @@ static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
- int status, iir, msr;
- int pass_counter = 0;
-
- #ifdef SERIAL_DEBUG_INTR
-- printk("rs_interrupt_single(%d)...", irq);
-+ printk(KERN_DEBUG "rs_interrupt_single(%d)...", cs->irq);
- #endif
-
- do {
-diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
-index f66620a..0ea3b46 100644
---- a/drivers/isdn/hisax/gazel.c
-+++ b/drivers/isdn/hisax/gazel.c
-@@ -19,7 +19,6 @@
- #include "ipac.h"
- #include <linux/pci.h>
+ struct s5h1420_state* state = fe->demodulator_priv;
--extern const char *CardType[];
- static const char *gazel_revision = "$Revision: 2.19.2.4 $";
++ 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__);
- #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;
}
+@@ -137,6 +176,7 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
+ unsigned long timeout;
+ int result = 0;
-diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
-index fba8b62..f126566 100644
---- a/drivers/isdn/hisax/hfc_pci.c
-+++ b/drivers/isdn/hisax/hfc_pci.c
-@@ -22,8 +22,6 @@
- #include <linux/pci.h>
- #include <linux/interrupt.h>
-
--extern const char *CardType[];
--
- static const char *hfcpci_revision = "$Revision: 1.48.2.4 $";
-
- /* table entry in the PCI devices list */
-diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
-index 05482d2..f4a2138 100644
---- a/drivers/isdn/hisax/hfc_sx.c
-+++ b/drivers/isdn/hisax/hfc_sx.c
-@@ -18,8 +18,6 @@
- #include <linux/interrupt.h>
- #include <linux/isapnp.h>
++ dprintk("enter %s\n", __func__);
+ if (cmd->msg_len > 8)
+ return -EINVAL;
--extern const char *CardType[];
--
- static const char *hfcsx_revision = "$Revision: 1.12.2.5 $";
+@@ -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;
+ }
- /***************************************/
-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;
- };
+@@ -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;
-+typedef int (*hisax_setup_func_t)(struct IsdnCard *card);
++ dprintk("enter %s\n", __func__);
+
- extern void HiSax_closecard(int);
- extern int hisax_init_pcmcia(void *, int *, IsdnCard_t *);
-diff --git a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c
-index 55de069..ca41617 100644
---- a/drivers/isdn/hisax/isurf.c
-+++ b/drivers/isdn/hisax/isurf.c
-@@ -17,8 +17,6 @@
- #include "isdnl1.h"
- #include <linux/isapnp.h>
-
--extern const char *CardType[];
--
- static const char *ISurf_revision = "$Revision: 1.12.2.4 $";
+ if (status == NULL)
+ return -EINVAL;
- #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"
+@@ -297,13 +340,13 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
--extern const char *CardType[];
- static const char *ix1_revision = "$Revision: 2.12.2.4 $";
+ /* 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);
- #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);
- }
+ /* 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)
}
-- 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 @@
- *
- */
+ /* perform post lock setup */
+- if ((*status & FE_HAS_LOCK) && (!state->postlocked)) {
++ if ((*status & FE_HAS_LOCK) && !state->postlocked) {
--extern const char *CardType[];
+ /* calculate the data rate */
+ u32 tmp = s5h1420_getsymbolrate(state);
+- switch(s5h1420_readreg(state, 0x32) & 0x07) {
+- case 0:
+- tmp = (tmp * 2 * 1) / 2;
+- break;
-
- #define byteout(addr,val) outb(val,addr)
- #define bytein(addr) inb(addr)
-
-diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
-index bd99211..421b8e6 100644
---- a/drivers/isdn/hisax/niccy.c
-+++ b/drivers/isdn/hisax/niccy.c
-@@ -21,7 +21,6 @@
- #include <linux/pci.h>
- #include <linux/isapnp.h>
-
--extern const char *CardType[];
- static const char *niccy_revision = "$Revision: 1.21.2.4 $";
-
- #define byteout(addr,val) outb(val,addr)
-@@ -284,14 +283,14 @@ int __devinit setup_niccy(struct IsdnCard *card)
- cs->subtyp = NICCY_PNP;
- cs->irq = card->para[0];
- if (!request_region(cs->hw.niccy.isac, 2, "niccy data")) {
-- printk(KERN_WARNING "HiSax: %s data port %x-%x "
-- "already in use\n", CardType[card->typ],
-+ printk(KERN_WARNING "HiSax: NICCY data port %x-%x "
-+ "already in use\n",
- cs->hw.niccy.isac, cs->hw.niccy.isac + 1);
- return 0;
+- 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 (!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 (tmp == 0) {
+- printk("s5h1420: avoided division by 0\n");
++ printk(KERN_ERR "s5h1420: avoided division by 0\n");
+ tmp = 1;
}
- 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);
- }
+ tmp = state->fclk / tmp;
-- 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);
++
+ /* 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));
- 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"
+- /* DC freeze */
+- s5h1420_writereg(state, 0x1f, s5h1420_readreg(state, 0x1f) | 0x01);
++ /* kicker disable */
++ val = s5h1420_readreg(state, QPSK01) & 0x7f;
++ s5h1420_writereg(state, QPSK01, val);
--extern const char *CardType[];
- static const char *sportster_revision = "$Revision: 1.16.2.4 $";
+- /* 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);
++ }
- #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);
+ /* post-lock processing has been done! */
+ state->postlocked = 1;
}
-- printk(KERN_INFO "HiSax: %s config irq:%d cfg:0x%X\n",
-- CardType[cs->typ], cs->irq, cs->hw.spt.cfg_reg);
-+ printk(KERN_INFO "HiSax: USR Sportster config irq:%d cfg:0x%X\n",
-+ cs->irq, cs->hw.spt.cfg_reg);
- setup_isac(cs);
- cs->readisac = &ReadISAC;
- cs->writeisac = &WriteISAC;
-diff --git a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c
-index 0909662..b0ce4ae 100644
---- a/drivers/isdn/hisax/teleint.c
-+++ b/drivers/isdn/hisax/teleint.c
-@@ -16,8 +16,6 @@
- #include "hfc_2bs0.h"
- #include "isdnl1.h"
-
--extern const char *CardType[];
--
- static const char *TeleInt_revision = "$Revision: 1.16.2.5 $";
- #define byteout(addr,val) outb(val,addr)
-@@ -286,8 +284,7 @@ setup_TeleInt(struct IsdnCard *card)
- init_timer(&cs->hw.hfc.timer);
- if (!request_region(cs->hw.hfc.addr, 2, "TeleInt isdn")) {
- printk(KERN_WARNING
-- "HiSax: %s config port %x-%x already in use\n",
-- CardType[card->typ],
-+ "HiSax: TeleInt config port %x-%x already in use\n",
- cs->hw.hfc.addr,
- cs->hw.hfc.addr + 2);
- return (0);
-diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
-index 4393003..28b08de 100644
---- a/drivers/isdn/hisax/telespci.c
-+++ b/drivers/isdn/hisax/telespci.c
-@@ -19,7 +19,6 @@
- #include "isdnl1.h"
- #include <linux/pci.h>
++ dprintk("leave %s\n", __func__);
++
+ return 0;
+ }
--extern const char *CardType[];
- static const char *telespci_revision = "$Revision: 2.23.2.3 $";
+@@ -414,6 +462,7 @@ static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
- #define ZORAN_PO_RQ_PEN 0x02000000
-@@ -329,8 +328,8 @@ setup_telespci(struct IsdnCard *card)
- /* writel(0x00800000, cs->hw.teles0.membase + 0x200); */
+ 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;
- 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);
++ 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));
- 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
+- 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", (unsigned long long)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__);
+ }
--extern const char *CardType[];
+ static u32 s5h1420_getsymbolrate(struct s5h1420_state* state)
+ {
+- u64 val = 0;
+- int sampling = 2;
-
- 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.
+- if (s5h1420_readreg(state, 0x05) & 0x2)
+- sampling = 1;
-
- 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.
+- 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;
+ }
-+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.
+ static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset)
+ {
+ int val;
++ u8 v;
+
- 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
++ dprintk("enter %s\n", __func__);
- This module can drive the mail LED for the following notebooks:
+ /* 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));
-+ 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)
+- 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__);
+ }
-+ If your model is not listed here you can try the "nodetect"
-+ module paramter.
+ 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;
+
- To compile this driver as a module, choose M here: the
- module will be called leds-clevo-mail.
++ dprintk("enter %s\n", __func__);
-@@ -181,4 +183,11 @@ config LEDS_TRIGGER_HEARTBEAT
- load average.
- If unsure, say Y.
+- 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;
+- }
-+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
+ 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;
- # 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 @@
+ case FEC_2_3:
+- s5h1420_writereg(state, 0x30, 0x02);
+- s5h1420_writereg(state, 0x31, 0x11 | inversion);
++ vit08 = 0x02; vit09 = 0x11;
+ break;
- static struct class *leds_class;
+ case FEC_3_4:
+- s5h1420_writereg(state, 0x30, 0x04);
+- s5h1420_writereg(state, 0x31, 0x12 | inversion);
++ vit08 = 0x04; vit09 = 0x12;
+ break;
-+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;
+ case FEC_5_6:
+- s5h1420_writereg(state, 0x30, 0x08);
+- s5h1420_writereg(state, 0x31, 0x13 | inversion);
++ vit08 = 0x08; vit09 = 0x13;
+ break;
- /* no lock needed for this */
-+ led_update_brightness(led_cdev);
- sprintf(buf, "%u\n", led_cdev->brightness);
- ret = strlen(buf) + 1;
+ case FEC_6_7:
+- s5h1420_writereg(state, 0x30, 0x10);
+- s5h1420_writereg(state, 0x31, 0x14 | inversion);
++ vit08 = 0x10; vit09 = 0x14;
+ break;
-@@ -51,6 +58,9 @@ static ssize_t led_brightness_store(struct device *dev,
+ case FEC_7_8:
+- s5h1420_writereg(state, 0x30, 0x20);
+- s5h1420_writereg(state, 0x31, 0x15 | inversion);
++ vit08 = 0x20; vit09 = 0x15;
+ break;
- if (count == size) {
- ret = count;
-+
-+ if (state == LED_OFF)
-+ led_trigger_remove(led_cdev);
- led_set_brightness(led_cdev, state);
+ 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__);
+ }
-@@ -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);
+ 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;
+
- #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);
++ dprintk("enter %s\n", __func__);
- 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"
+ /* 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)) {
- DECLARE_RWSEM(leds_list_lock);
--LIST_HEAD(leds_list);
-+EXPORT_SYMBOL_GPL(leds_list_lock);
+ 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");
-+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);
+ /* first of all, software reset */
+ s5h1420_reset(state);
-+ /* Used by LED Class */
+ /* 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;
+
- 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;
++ /* 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));
-@@ -66,7 +66,7 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
-
- return -EINVAL;
- }
--
-+EXPORT_SYMBOL_GPL(led_trigger_store);
+- /* 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);
- 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);
+- /* 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 */
- /* 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)
+ /* 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);
}
- 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);
+@@ -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);
+
-+/* LED Trigger Interface */
+ 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;
+ }
- int led_trigger_register(struct led_trigger *trigger)
+@@ -717,11 +812,10 @@ static int s5h1420_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
{
-@@ -181,26 +177,7 @@ int led_trigger_register(struct led_trigger *trigger)
+ struct s5h1420_state* state = fe->demodulator_priv;
- return 0;
+- 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;
-
--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);
+- return s5h1420_writereg(state, 0x02, 0x12);
++ state->CON_1_val = 0x12;
++ return s5h1420_writereg(state, 0x02, state->CON_1_val);
+ }
- void led_trigger_unregister(struct led_trigger *trigger)
+ static void s5h1420_release(struct dvb_frontend* fe)
{
-@@ -221,6 +198,49 @@ void led_trigger_unregister(struct led_trigger *trigger)
- }
- up_read(&leds_list_lock);
+ struct s5h1420_state* state = fe->demodulator_priv;
++ i2c_del_adapter(&state->tuner_i2c_adapter);
+ kfree(state);
}
-+EXPORT_SYMBOL_GPL(led_trigger_unregister);
-+
-+/* Simple LED Tigger Interface */
+
+-static struct dvb_frontend_ops s5h1420_ops;
++static u32 s5h1420_tuner_i2c_func(struct i2c_adapter *adapter)
++{
++ return I2C_FUNC_I2C;
++}
+
-+void led_trigger_event(struct led_trigger *trigger,
-+ enum led_brightness brightness)
++static int s5h1420_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
-+ struct list_head *entry;
++ 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 */
+
-+ if (!trigger)
-+ return;
++ memset(m, 0, sizeof(struct i2c_msg) * (1 + num));
+
-+ read_lock(&trigger->leddev_list_lock);
-+ list_for_each(entry, &trigger->led_cdevs) {
-+ struct led_classdev *led_cdev;
++ 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);
+
-+ led_cdev = list_entry(entry, struct led_classdev, trig_list);
-+ led_set_brightness(led_cdev, brightness);
-+ }
-+ read_unlock(&trigger->leddev_list_lock);
++ return i2c_transfer(state->i2c, m, 1+num) == 1 + num ? num : -EIO;
+}
-+EXPORT_SYMBOL_GPL(led_trigger_event);
+
-+void led_trigger_register_simple(const char *name, struct led_trigger **tp)
-+{
-+ struct led_trigger *trigger;
-+ int err;
++static struct i2c_algorithm s5h1420_tuner_i2c_algo = {
++ .master_xfer = s5h1420_tuner_i2c_tuner_xfer,
++ .functionality = s5h1420_tuner_i2c_func,
++};
+
-+ trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
++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);
+
-+ 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);
++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;
+
-+ *tp = trigger;
-+}
-+EXPORT_SYMBOL_GPL(led_trigger_register_simple);
+ if (state == NULL)
+ goto error;
- 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);
+@@ -772,24 +901,42 @@ struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
+ state->symbol_rate = 0;
- 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
+ /* 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;
--MODULE_AUTHOR("Márton Németh <nm127 at freemail.hu>");
-+MODULE_AUTHOR("Márton Németh <nm127 at freemail.hu>");
- MODULE_DESCRIPTION("Clevo mail LED driver");
- MODULE_LICENSE("GPL");
++ 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;
-@@ -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,
+ error:
+ kfree(state);
+ return NULL;
}
++EXPORT_SYMBOL(s5h1420_attach);
- static int clevo_mail_led_blink(struct led_classdev *led_cdev,
-- unsigned long* delay_on,
-- unsigned long* delay_off)
-+ unsigned long *delay_on,
-+ unsigned long *delay_off)
- {
- int status = -EINVAL;
-
-diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c
-index 096881a..059aa29 100644
---- a/drivers/leds/leds-cobalt-qube.c
-+++ b/drivers/leds/leds-cobalt-qube.c
-@@ -18,7 +18,7 @@ static void __iomem *led_port;
- static u8 led_value;
-
- static void qube_front_led_set(struct led_classdev *led_cdev,
-- enum led_brightness brightness)
-+ enum led_brightness brightness)
- {
- if (brightness)
- led_value = LED_FRONT_LEFT | LED_FRONT_RIGHT;
-diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c
-index 6ebfff3..ff0e8c3 100644
---- a/drivers/leds/leds-cobalt-raq.c
-+++ b/drivers/leds/leds-cobalt-raq.c
-@@ -15,7 +15,7 @@
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #include <linux/init.h>
- #include <linux/io.h>
-@@ -33,7 +33,7 @@ static u8 led_value;
- static DEFINE_SPINLOCK(led_value_lock);
-
- static void raq_web_led_set(struct led_classdev *led_cdev,
-- enum led_brightness brightness)
-+ enum led_brightness brightness)
- {
- unsigned long flags;
+ static struct dvb_frontend_ops s5h1420_ops = {
-@@ -54,7 +54,7 @@ static struct led_classdev raq_web_led = {
+ .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,
};
- static void raq_power_off_led_set(struct led_classdev *led_cdev,
-- enum led_brightness brightness)
-+ enum led_brightness brightness)
- {
- unsigned long flags;
-
-diff --git a/drivers/leds/leds-corgi.c b/drivers/leds/leds-corgi.c
-index 29e931f..a709704 100644
---- a/drivers/leds/leds-corgi.c
-+++ b/drivers/leds/leds-corgi.c
-@@ -21,7 +21,8 @@
- #include <asm/arch/pxa-regs.h>
- #include <asm/hardware/scoop.h>
+-module_param(debug, int, 0644);
+-
+-MODULE_DESCRIPTION("Samsung S5H1420 DVB-S Demodulator driver");
+-MODULE_AUTHOR("Andrew de Quincey");
++MODULE_DESCRIPTION("Samsung S5H1420/PnpNetwork PN1010 DVB-S Demodulator driver");
++MODULE_AUTHOR("Andrew de Quincey, Patrick Boettcher");
+ MODULE_LICENSE("GPL");
+-
+-EXPORT_SYMBOL(s5h1420_attach);
+diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h
+index 1555870..4c913f1 100644
+--- a/drivers/media/dvb/frontends/s5h1420.h
++++ b/drivers/media/dvb/frontends/s5h1420.h
+@@ -1,25 +1,26 @@
+ /*
+- Driver for S5H1420 QPSK Demodulators
+-
+- Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2 of the License, or
+- (at your option) any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-
+- GNU General Public License for more details.
+-
+- You should have received a copy of the GNU General Public License
+- along with this program; if not, write to the Free Software
+- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-*/
+-
++ * Driver for
++ * Samsung S5H1420 and
++ * PnpNetwork PN1010 QPSK Demodulator
++ *
++ * Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
++ * Copyright (C) 2005-8 Patrick Boettcher <pb at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
+ #ifndef S5H1420_H
+ #define S5H1420_H
--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);
- }
+@@ -31,17 +32,26 @@ struct s5h1420_config
+ u8 demod_address;
--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)
+ /* 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 */
+ };
- static void __exit corgiled_exit(void)
+ #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)
{
-- platform_driver_unregister(&corgiled_driver);
-+ platform_driver_unregister(&corgiled_driver);
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
}
-
- module_init(corgiled_init);
-diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c
+ #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..a7421b8
+index 0000000..d9c58d2
--- /dev/null
-+++ b/drivers/leds/leds-fsg.c
-@@ -0,0 +1,261 @@
++++ b/drivers/media/dvb/frontends/s5h1420_priv.h
+@@ -0,0 +1,102 @@
+/*
-+ * LED Driver for the Freecom FSG-3
++ * Driver for
++ * Samsung S5H1420 and
++ * PnpNetwork PN1010 QPSK Demodulator
+ *
-+ * Copyright (c) 2008 Rod Whitby <rod at whitby.id.au>
++ * Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
++ * Copyright (C) 2005 Patrick Boettcher <pb at linuxtv.org>
+ *
-+ * Author: Rod Whitby <rod at whitby.id.au>
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 2 of the License, or (at your option)
++ * any later version.
+ *
-+ * Based on leds-spitz.c
-+ * Copyright 2005-2006 Openedhand Ltd.
-+ * Author: Richard Purdie <rpurdie at openedhand.com>
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
-+ * 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.
++ * GNU General Public License for more details.
+ *
++ * You 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 <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/platform_device.h>
-+#include <linux/leds.h>
-+#include <asm/arch/hardware.h>
-+#include <asm/io.h>
-+
-+static short __iomem *latch_address;
-+static unsigned short latch_value;
-+
-+
-+static void fsg_led_wlan_set(struct led_classdev *led_cdev,
-+ enum led_brightness value)
-+{
-+ if (value) {
-+ latch_value &= ~(1 << FSG_LED_WLAN_BIT);
-+ *latch_address = latch_value;
-+ } else {
-+ latch_value |= (1 << FSG_LED_WLAN_BIT);
-+ *latch_address = latch_value;
-+ }
-+}
-+
-+static void fsg_led_wan_set(struct led_classdev *led_cdev,
-+ enum led_brightness value)
-+{
-+ if (value) {
-+ latch_value &= ~(1 << FSG_LED_WAN_BIT);
-+ *latch_address = latch_value;
-+ } else {
-+ latch_value |= (1 << FSG_LED_WAN_BIT);
-+ *latch_address = latch_value;
-+ }
-+}
-+
-+static void fsg_led_sata_set(struct led_classdev *led_cdev,
-+ enum led_brightness value)
-+{
-+ if (value) {
-+ latch_value &= ~(1 << FSG_LED_SATA_BIT);
-+ *latch_address = latch_value;
-+ } else {
-+ latch_value |= (1 << FSG_LED_SATA_BIT);
-+ *latch_address = latch_value;
-+ }
-+}
-+
-+static void fsg_led_usb_set(struct led_classdev *led_cdev,
-+ enum led_brightness value)
-+{
-+ if (value) {
-+ latch_value &= ~(1 << FSG_LED_USB_BIT);
-+ *latch_address = latch_value;
-+ } else {
-+ latch_value |= (1 << FSG_LED_USB_BIT);
-+ *latch_address = latch_value;
-+ }
-+}
-+
-+static void fsg_led_sync_set(struct led_classdev *led_cdev,
-+ enum led_brightness value)
-+{
-+ if (value) {
-+ latch_value &= ~(1 << FSG_LED_SYNC_BIT);
-+ *latch_address = latch_value;
-+ } else {
-+ latch_value |= (1 << FSG_LED_SYNC_BIT);
-+ *latch_address = latch_value;
-+ }
-+}
-+
-+static void fsg_led_ring_set(struct led_classdev *led_cdev,
-+ enum led_brightness value)
-+{
-+ if (value) {
-+ latch_value &= ~(1 << FSG_LED_RING_BIT);
-+ *latch_address = latch_value;
-+ } else {
-+ latch_value |= (1 << FSG_LED_RING_BIT);
-+ *latch_address = latch_value;
-+ }
-+}
-+
-+
-+
-+static struct led_classdev fsg_wlan_led = {
-+ .name = "fsg:blue:wlan",
-+ .brightness_set = fsg_led_wlan_set,
-+};
-+
-+static struct led_classdev fsg_wan_led = {
-+ .name = "fsg:blue:wan",
-+ .brightness_set = fsg_led_wan_set,
-+};
-+
-+static struct led_classdev fsg_sata_led = {
-+ .name = "fsg:blue:sata",
-+ .brightness_set = fsg_led_sata_set,
-+};
-+
-+static struct led_classdev fsg_usb_led = {
-+ .name = "fsg:blue:usb",
-+ .brightness_set = fsg_led_usb_set,
-+};
++#include <asm/types.h>
+
-+static struct led_classdev fsg_sync_led = {
-+ .name = "fsg:blue:sync",
-+ .brightness_set = fsg_led_sync_set,
-+};
++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,
+
-+static struct led_classdev fsg_ring_led = {
-+ .name = "fsg:blue:ring",
-+ .brightness_set = fsg_led_ring_set,
++ 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,
+};
+
+
-+
-+#ifdef CONFIG_PM
-+static int fsg_led_suspend(struct platform_device *dev, pm_message_t state)
-+{
-+ led_classdev_suspend(&fsg_wlan_led);
-+ led_classdev_suspend(&fsg_wan_led);
-+ led_classdev_suspend(&fsg_sata_led);
-+ led_classdev_suspend(&fsg_usb_led);
-+ led_classdev_suspend(&fsg_sync_led);
-+ led_classdev_suspend(&fsg_ring_led);
-+ return 0;
-+}
-+
-+static int fsg_led_resume(struct platform_device *dev)
-+{
-+ led_classdev_resume(&fsg_wlan_led);
-+ led_classdev_resume(&fsg_wan_led);
-+ led_classdev_resume(&fsg_sata_led);
-+ led_classdev_resume(&fsg_usb_led);
-+ led_classdev_resume(&fsg_sync_led);
-+ led_classdev_resume(&fsg_ring_led);
-+ return 0;
-+}
-+#endif
-+
-+
-+static int fsg_led_probe(struct platform_device *pdev)
-+{
-+ int ret;
-+
-+ ret = led_classdev_register(&pdev->dev, &fsg_wlan_led);
-+ if (ret < 0)
-+ goto failwlan;
-+
-+ ret = led_classdev_register(&pdev->dev, &fsg_wan_led);
-+ if (ret < 0)
-+ goto failwan;
-+
-+ ret = led_classdev_register(&pdev->dev, &fsg_sata_led);
-+ if (ret < 0)
-+ goto failsata;
-+
-+ ret = led_classdev_register(&pdev->dev, &fsg_usb_led);
-+ if (ret < 0)
-+ goto failusb;
-+
-+ ret = led_classdev_register(&pdev->dev, &fsg_sync_led);
-+ if (ret < 0)
-+ goto failsync;
-+
-+ ret = led_classdev_register(&pdev->dev, &fsg_ring_led);
-+ if (ret < 0)
-+ goto failring;
-+
-+ /* Map the LED chip select address space */
-+ latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
-+ if (!latch_address) {
-+ ret = -ENOMEM;
-+ goto failremap;
-+ }
-+
-+ latch_value = 0xffff;
-+ *latch_address = latch_value;
-+
-+ return ret;
-+
-+ failremap:
-+ led_classdev_unregister(&fsg_ring_led);
-+ failring:
-+ led_classdev_unregister(&fsg_sync_led);
-+ failsync:
-+ led_classdev_unregister(&fsg_usb_led);
-+ failusb:
-+ led_classdev_unregister(&fsg_sata_led);
-+ failsata:
-+ led_classdev_unregister(&fsg_wan_led);
-+ failwan:
-+ led_classdev_unregister(&fsg_wlan_led);
-+ failwlan:
-+
-+ return ret;
-+}
-+
-+static int fsg_led_remove(struct platform_device *pdev)
-+{
-+ iounmap(latch_address);
-+
-+ led_classdev_unregister(&fsg_wlan_led);
-+ led_classdev_unregister(&fsg_wan_led);
-+ led_classdev_unregister(&fsg_sata_led);
-+ led_classdev_unregister(&fsg_usb_led);
-+ led_classdev_unregister(&fsg_sync_led);
-+ led_classdev_unregister(&fsg_ring_led);
-+
-+ return 0;
-+}
-+
-+
-+static struct platform_driver fsg_led_driver = {
-+ .probe = fsg_led_probe,
-+ .remove = fsg_led_remove,
-+#ifdef CONFIG_PM
-+ .suspend = fsg_led_suspend,
-+ .resume = fsg_led_resume,
+#endif
-+ .driver = {
-+ .name = "fsg-led",
-+ },
-+};
-+
-+
-+static int __init fsg_led_init(void)
-+{
-+ return platform_driver_register(&fsg_led_driver);
-+}
-+
-+static void __exit fsg_led_exit(void)
-+{
-+ platform_driver_unregister(&fsg_led_driver);
-+}
-+
-+
-+module_init(fsg_led_init);
-+module_exit(fsg_led_exit);
-+
-+MODULE_AUTHOR("Rod Whitby <rod at whitby.id.au>");
-+MODULE_DESCRIPTION("Freecom FSG-3 LED driver");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
-index 1aae8b3..b13bd29 100644
---- a/drivers/leds/leds-gpio.c
-+++ b/drivers/leds/leds-gpio.c
-@@ -24,6 +24,8 @@ struct gpio_led_data {
- u8 new_level;
- u8 can_sleep;
- u8 active_low;
-+ int (*platform_gpio_blink_set)(unsigned gpio,
-+ unsigned long *delay_on, unsigned long *delay_off);
- };
+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;
- 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);
- }
+ 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;
+ }
-+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;
+@@ -88,7 +88,7 @@ static int sp8870_readreg (struct sp8870_state* state, u16 reg)
+ ret = i2c_transfer (state->i2c, msg, 2);
-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;
+ if (ret != 2) {
+- dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
++ dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
+ return -1;
}
- }
-@@ -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;
- }
- }
+@@ -104,7 +104,7 @@ static int sp8870_firmware_upload (struct sp8870_state* state, const struct firm
+ int tx_len;
+ int err = 0;
-@@ -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);
+- 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;
}
- }
-diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c
-index 870f5a3..844d597 100644
---- a/drivers/leds/leds-hp6xx.c
-+++ b/drivers/leds/leds-hp6xx.c
-@@ -17,7 +17,8 @@
- #include <asm/hd64461.h>
- #include <asm/hp6xx.h>
+- dprintk ("%s: done!\n", __FUNCTION__);
++ dprintk ("%s: done!\n", __func__);
+ return 0;
+ };
--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;
+@@ -310,7 +310,7 @@ static int sp8870_init (struct dvb_frontend* fe)
+ if (state->initialised) return 0;
+ state->initialised = 1;
-@@ -28,7 +29,8 @@ static void hp6xxled_green_set(struct led_classdev *led_cdev, enum led_brightnes
- outb(v8 | PKDR_LED_GREEN, PKDR);
+- 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;
}
--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)
+-// 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)
{
- u16 v16;
+@@ -475,7 +475,7 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
+ int trials = 0;
+ int check_count = 0;
-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,
+- dprintk("%s: frequency = %i\n", __FUNCTION__, p->frequency);
++ dprintk("%s: frequency = %i\n", __func__, p->frequency);
- 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);
+ 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
+ }
-@@ -151,7 +151,7 @@ static int __init s3c24xx_led_init(void)
+ if (!valid) {
+- printk("%s: firmware crash!!!!!!\n", __FUNCTION__);
++ printk("%s: firmware crash!!!!!!\n", __func__);
+ return -EIO;
+ }
- static void __exit s3c24xx_led_exit(void)
+ 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)
{
-- platform_driver_unregister(&s3c24xx_led_driver);
-+ platform_driver_unregister(&s3c24xx_led_driver);
+- 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)
- module_init(s3c24xx_led_init);
-diff --git a/drivers/leds/leds-spitz.c b/drivers/leds/leds-spitz.c
-index 87007cc..e75e854 100644
---- a/drivers/leds/leds-spitz.c
-+++ b/drivers/leds/leds-spitz.c
-@@ -21,7 +21,8 @@
- #include <asm/arch/pxa-regs.h>
- #include <asm/arch/spitz.h>
+ 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;
+ }
--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);
- }
+@@ -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 }};
--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)
+ 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;
+ }
- static void __exit spitzled_exit(void)
+@@ -91,7 +91,7 @@ static int sp887x_readreg (struct sp887x_state* state, u16 reg)
+
+ static void sp887x_microcontroller_stop (struct sp887x_state* state)
{
-- platform_driver_unregister(&spitzled_driver);
-+ platform_driver_unregister(&spitzled_driver);
- }
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+ sp887x_writereg(state, 0xf08, 0x000);
+ sp887x_writereg(state, 0xf09, 0x000);
- module_init(spitzled_init);
-diff --git a/drivers/leds/leds-tosa.c b/drivers/leds/leds-tosa.c
-deleted file mode 100644
-index 7ebecc4..0000000
---- a/drivers/leds/leds-tosa.c
-+++ /dev/null
-@@ -1,132 +0,0 @@
--/*
-- * LED Triggers Core
-- *
-- * Copyright 2005 Dirk Opfer
-- *
-- * Author: Dirk Opfer <Dirk at Opfer-Online.de>
-- * based on spitz.c
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- *
-- */
--
--#include <linux/kernel.h>
--#include <linux/init.h>
--#include <linux/platform_device.h>
--#include <linux/leds.h>
--#include <asm/hardware/scoop.h>
--#include <asm/mach-types.h>
--#include <asm/arch/hardware.h>
--#include <asm/arch/pxa-regs.h>
--#include <asm/arch/tosa.h>
--
--static void tosaled_amber_set(struct led_classdev *led_cdev,
-- enum led_brightness value)
--{
-- if (value)
-- set_scoop_gpio(&tosascoop_jc_device.dev,
-- TOSA_SCOOP_JC_CHRG_ERR_LED);
-- else
-- reset_scoop_gpio(&tosascoop_jc_device.dev,
-- TOSA_SCOOP_JC_CHRG_ERR_LED);
--}
--
--static void tosaled_green_set(struct led_classdev *led_cdev,
-- enum led_brightness value)
--{
-- if (value)
-- set_scoop_gpio(&tosascoop_jc_device.dev,
-- TOSA_SCOOP_JC_NOTE_LED);
-- else
-- reset_scoop_gpio(&tosascoop_jc_device.dev,
-- TOSA_SCOOP_JC_NOTE_LED);
--}
--
--static struct led_classdev tosa_amber_led = {
-- .name = "tosa:amber:charge",
-- .default_trigger = "sharpsl-charge",
-- .brightness_set = tosaled_amber_set,
--};
--
--static struct led_classdev tosa_green_led = {
-- .name = "tosa:green:mail",
-- .default_trigger = "nand-disk",
-- .brightness_set = tosaled_green_set,
--};
--
--#ifdef CONFIG_PM
--static int tosaled_suspend(struct platform_device *dev, pm_message_t state)
--{
--#ifdef CONFIG_LEDS_TRIGGERS
-- if (tosa_amber_led.trigger && strcmp(tosa_amber_led.trigger->name,
-- "sharpsl-charge"))
--#endif
-- led_classdev_suspend(&tosa_amber_led);
-- led_classdev_suspend(&tosa_green_led);
-- return 0;
--}
--
--static int tosaled_resume(struct platform_device *dev)
--{
-- led_classdev_resume(&tosa_amber_led);
-- led_classdev_resume(&tosa_green_led);
-- return 0;
--}
--#else
--#define tosaled_suspend NULL
--#define tosaled_resume NULL
--#endif
--
--static int tosaled_probe(struct platform_device *pdev)
--{
-- int ret;
--
-- ret = led_classdev_register(&pdev->dev, &tosa_amber_led);
-- if (ret < 0)
-- return ret;
--
-- ret = led_classdev_register(&pdev->dev, &tosa_green_led);
-- if (ret < 0)
-- led_classdev_unregister(&tosa_amber_led);
--
-- return ret;
--}
--
--static int tosaled_remove(struct platform_device *pdev)
--{
-- led_classdev_unregister(&tosa_amber_led);
-- led_classdev_unregister(&tosa_green_led);
--
-- return 0;
--}
--
--static struct platform_driver tosaled_driver = {
-- .probe = tosaled_probe,
-- .remove = tosaled_remove,
-- .suspend = tosaled_suspend,
-- .resume = tosaled_resume,
-- .driver = {
-- .name = "tosa-led",
-- .owner = THIS_MODULE,
-- },
--};
--
--static int __init tosaled_init(void)
--{
-- return platform_driver_register(&tosaled_driver);
--}
--
--static void __exit tosaled_exit(void)
--{
-- platform_driver_unregister(&tosaled_driver);
--}
--
--module_init(tosaled_init);
--module_exit(tosaled_exit);
--
--MODULE_AUTHOR("Dirk Opfer <Dirk at Opfer-Online.de>");
--MODULE_DESCRIPTION("Tosa LED driver");
--MODULE_LICENSE("GPL");
--MODULE_ALIAS("platform:tosa-led");
-diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
-index 12b6fe9..5edbf52 100644
---- a/drivers/leds/leds.h
-+++ b/drivers/leds/leds.h
-@@ -27,6 +27,11 @@ static inline void led_set_brightness(struct led_classdev *led_cdev,
- led_cdev->brightness_set(led_cdev, value);
- }
+@@ -101,7 +101,7 @@ static void sp887x_microcontroller_stop (struct sp887x_state* state)
-+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;
+ 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);
-@@ -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
+@@ -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;
- ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
-diff --git a/drivers/leds/ledtrig-default-on.c b/drivers/leds/ledtrig-default-on.c
-new file mode 100644
-index 0000000..92995e4
---- /dev/null
-+++ b/drivers/leds/ledtrig-default-on.c
-@@ -0,0 +1,45 @@
-+/*
-+ * LED Kernel Default ON Trigger
-+ *
-+ * Copyright 2008 Nick Forbes <nick.forbes at incepta.com>
-+ *
-+ * Based on Richard Purdie's ledtrig-timer.c.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/leds.h>
-+#include "leds.h"
-+
-+static void defon_trig_activate(struct led_classdev *led_cdev)
-+{
-+ led_set_brightness(led_cdev, LED_FULL);
-+}
-+
-+static struct led_trigger defon_led_trigger = {
-+ .name = "default-on",
-+ .activate = defon_trig_activate,
-+};
-+
-+static int __init defon_trig_init(void)
-+{
-+ return led_trigger_register(&defon_led_trigger);
-+}
-+
-+static void __exit defon_trig_exit(void)
-+{
-+ led_trigger_unregister(&defon_led_trigger);
-+}
-+
-+module_init(defon_trig_init);
-+module_exit(defon_trig_exit);
-+
-+MODULE_AUTHOR("Nick Forbes <nick.forbes at incepta.com>");
-+MODULE_DESCRIPTION("Default-ON LED trigger");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/leds/ledtrig-ide-disk.c b/drivers/leds/ledtrig-ide-disk.c
-index 54b155c..883a577 100644
---- a/drivers/leds/ledtrig-ide-disk.c
-+++ b/drivers/leds/ledtrig-ide-disk.c
-@@ -38,7 +38,7 @@ static void ledtrig_ide_timerfunc(unsigned long data)
- if (ide_lastactivity != ide_activity) {
- ide_lastactivity = ide_activity;
- led_trigger_event(ledtrig_ide, LED_FULL);
-- mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
-+ mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
- } else {
- led_trigger_event(ledtrig_ide, LED_OFF);
- }
-diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c
-index 82c55d6..5c99f4f 100644
---- a/drivers/leds/ledtrig-timer.c
-+++ b/drivers/leds/ledtrig-timer.c
-@@ -25,6 +25,9 @@
- #include "leds.h"
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
- 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;
+ /* 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
- if (!timer_data->delay_on || !timer_data->delay_off) {
- led_set_brightness(led_cdev, LED_OFF);
- return;
- }
+ sp887x_microcontroller_stop (state);
-- 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;
- }
+- printk ("%s: firmware upload... ", __FUNCTION__);
++ printk ("%s: firmware upload... ", __func__);
- 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));
- }
+ /* 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
--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)
+ 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)
{
- 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;
+- 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)
--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;
- }
+ 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);
--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)
+ 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)
{
- 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;
+- 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)
--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;
+ 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);
-+ 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;
+ return (ret != 1) ? -EREMOTEIO : 0;
+ }
+@@ -113,7 +113,7 @@ static u8 stv0299_readreg (struct stv0299_state* state, u8 reg)
- init_timer(&timer_data->timer);
-diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
-index 2337e1a..005bd04 100644
---- a/drivers/lguest/lg.h
-+++ b/drivers/lguest/lg.h
-@@ -10,7 +10,6 @@
- #include <linux/wait.h>
- #include <linux/hrtimer.h>
- #include <linux/err.h>
--#include <asm/semaphore.h>
+ if (ret != 2)
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
+- __FUNCTION__, reg, ret);
++ __func__, reg, ret);
- #include <asm/lguest.h>
+ 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);
-diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
-index 2895810..2097820 100644
---- a/drivers/macintosh/adb.c
-+++ b/drivers/macintosh/adb.c
-@@ -37,9 +37,9 @@
- #include <linux/device.h>
- #include <linux/kthread.h>
- #include <linux/platform_device.h>
-+#include <linux/semaphore.h>
+ if (ret != 2)
+- dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
++ dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
- #include <asm/uaccess.h>
--#include <asm/semaphore.h>
- #ifdef CONFIG_PPC
- #include <asm/prom.h>
- #include <asm/machdep.h>
-diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
-index 8930230..cc9f275 100644
---- a/drivers/macintosh/mac_hid.c
-+++ b/drivers/macintosh/mac_hid.c
-@@ -103,6 +103,9 @@ int mac_hid_mouse_emulate_buttons(int caller, unsigned int keycode, int down)
- return 0;
+ return ret == 2 ? 0 : ret;
}
-+static struct lock_class_key emumousebtn_event_class;
-+static struct lock_class_key emumousebtn_mutex_class;
-+
- static int emumousebtn_input_register(void)
+ static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
{
- int ret;
-@@ -111,6 +114,9 @@ static int emumousebtn_input_register(void)
- if (!emumousebtn)
- return -ENOMEM;
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
-+ 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)
- }
+ 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;
- int media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base,
-- int irq, int index)
-+ int irq, ide_hwif_t *hwif)
+- 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)
{
- int i;
+ unsigned long start = jiffies;
-@@ -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];
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- if (bay->mdev && which_bay == bay->mdev->ofdev.node) {
-- int timeout = 5000;
-+ int timeout = 5000, index = hwif->index;
-
- down(&bay->lock);
+ 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;
-+ bay->cd_port = hwif;
- bay->cd_base = (void __iomem *) base;
- bay->cd_irq = irq;
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
-@@ -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;
+ while ((stv0299_readreg(state, 0x0a) & 3) != 2 ) {
+ if (jiffies - start > timeout) {
+- dprintk ("%s: timeout!!\n", __FUNCTION__);
++ dprintk ("%s: timeout!!\n", __func__);
+ return -ETIMEDOUT;
}
- 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,
- },
- };
+ msleep(10);
+@@ -245,7 +245,7 @@ static int stv0299_get_symbolrate (struct stv0299_state* state)
+ u8 sfr[3];
+ s8 rtf;
-@@ -711,3 +711,4 @@ module_exit(wf_pm112_exit);
- MODULE_AUTHOR("Paul Mackerras <paulus at samba.org>");
- MODULE_DESCRIPTION("Thermal control for PowerMac11,2");
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:windfarm");
-diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c
-index f24fa73..abbe206 100644
---- a/drivers/macintosh/windfarm_pm81.c
-+++ b/drivers/macintosh/windfarm_pm81.c
-@@ -770,7 +770,7 @@ static struct platform_driver wf_smu_driver = {
- .remove = __devexit_p(wf_smu_remove),
- .driver = {
- .name = "windfarm",
-- .bus = &platform_bus_type,
-+ .owner = THIS_MODULE,
- },
- };
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
-@@ -810,4 +810,4 @@ module_exit(wf_smu_exit);
- MODULE_AUTHOR("Benjamin Herrenschmidt <benh at kernel.crashing.org>");
- MODULE_DESCRIPTION("Thermal control logic for iMac G5");
- MODULE_LICENSE("GPL");
--
-+MODULE_ALIAS("platform:windfarm");
-diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c
-index 26eee69..764c525 100644
---- a/drivers/macintosh/windfarm_pm91.c
-+++ b/drivers/macintosh/windfarm_pm91.c
-@@ -702,7 +702,7 @@ static struct platform_driver wf_smu_driver = {
- .remove = __devexit_p(wf_smu_remove),
- .driver = {
- .name = "windfarm",
-- .bus = &platform_bus_type,
-+ .owner = THIS_MODULE,
- },
- };
+ 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;
-@@ -742,3 +742,4 @@ MODULE_AUTHOR("Benjamin Herrenschmidt <benh at kernel.crashing.org>");
- MODULE_DESCRIPTION("Thermal control logic for PowerMac9,1");
- MODULE_LICENSE("GPL");
+- 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);
-+MODULE_ALIAS("platform:windfarm");
-diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
-index f449d77..797918d 100644
---- a/drivers/macintosh/windfarm_smu_sat.c
-+++ b/drivers/macintosh/windfarm_smu_sat.c
-@@ -13,7 +13,7 @@
- #include <linux/init.h>
- #include <linux/wait.h>
- #include <linux/i2c.h>
--#include <asm/semaphore.h>
-+#include <linux/semaphore.h>
- #include <asm/prom.h>
- #include <asm/smu.h>
- #include <asm/pmac_low_i2c.h>
-diff --git a/drivers/md/Makefile b/drivers/md/Makefile
-index d9aa7ed..7be09ee 100644
---- a/drivers/md/Makefile
-+++ b/drivers/md/Makefile
-@@ -3,10 +3,10 @@
- #
+ srate += offset;
- 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
+@@ -276,7 +276,7 @@ static int stv0299_send_diseqc_msg (struct dvb_frontend* fe,
+ u8 val;
+ int i;
- 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 @@
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- #include "dm.h"
- #include "dm-snap.h"
--#include "dm-io.h"
--#include "kcopyd.h"
+ 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;
- #include <linux/mm.h>
- #include <linux/pagemap.h>
- #include <linux/vmalloc.h>
- #include <linux/slab.h>
-+#include <linux/dm-io.h>
-+#include <linux/dm-kcopyd.h>
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- #define DM_MSG_PREFIX "snapshots"
- #define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */
-@@ -131,7 +131,7 @@ struct pstore {
+ 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;
- static unsigned sectors_to_pages(unsigned sectors)
- {
-- return sectors / (PAGE_SIZE >> 9);
-+ return DIV_ROUND_UP(sectors, PAGE_SIZE >> 9);
- }
+- dprintk("%s: %s\n", __FUNCTION__,
++ dprintk("%s: %s\n", __func__,
+ voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
+ voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
- static int alloc_area(struct pstore *ps)
-@@ -159,7 +159,7 @@ static void free_area(struct pstore *ps)
+@@ -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);
}
- 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)
+ 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 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.
- */
+ struct stv0299_state* state = fe->demodulator_priv;
+ int i;
++ u8 reg;
++ u8 val;
--#include "dm-io.h"
-+#include "dm.h"
+ dprintk("stv0299: init chip\n");
- #include <linux/bio.h>
- #include <linux/mempool.h>
- #include <linux/module.h>
- #include <linux/sched.h>
- #include <linux/slab.h>
-+#include <linux/dm-io.h>
+- 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);
++ }
- struct dm_io_client {
- mempool_t *pool;
-@@ -20,7 +21,7 @@ struct dm_io_client {
+ 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);
- /* 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);
+- dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __FUNCTION__, sync);
++ dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync);
+ *status = 0;
+
+ if (signal > 10)
+@@ -499,7 +514,7 @@ static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+ s32 signal = 0xffff - ((stv0299_readreg (state, 0x18) << 8)
+ | stv0299_readreg (state, 0x19));
+
+- dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __FUNCTION__,
++ dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __func__,
+ stv0299_readreg (state, 0x18),
+ stv0299_readreg (state, 0x19), (int) signal);
+
+@@ -536,7 +551,7 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
+ struct stv0299_state* state = fe->demodulator_priv;
+ int invval = 0;
+
+- dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__);
++ dprintk ("%s : FE_SET_FRONTEND\n", __func__);
+
+ // set the inversion
+ if (p->inversion == INVERSION_OFF) invval = 0;
+diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h
+index 33df949..3282f43 100644
+--- a/drivers/media/dvb/frontends/stv0299.h
++++ b/drivers/media/dvb/frontends/stv0299.h
+@@ -48,10 +48,10 @@
+ #include <linux/dvb/frontend.h>
+ #include "dvb_frontend.h"
- if (atomic_dec_and_test(&io->count)) {
- if (io->sleeper)
- wake_up_process(io->sleeper);
+-#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
- else {
-- unsigned long r = io->error;
-+ unsigned long r = io->error_bits;
- io_notify_fn fn = io->callback;
- void *context = io->context;
+ #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;
-@@ -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,
- }
++ /* Turn-off OP0? */
++ u8 op0_off:1;
++
+ /* minimum delay before retuning */
+ int min_delay_ms;
- 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)
+@@ -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)
{
- int i;
-@@ -347,17 +348,17 @@ static void dispatch_io(int rw, unsigned int num_regions,
+- 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);
- 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;
- }
+ 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];
+ }
-- 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;
+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];
+ }
- if (error_bits)
-- *error_bits = io.error;
-+ *error_bits = io.error_bits;
+@@ -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 io.error ? -EIO : 0;
-+ return io.error_bits ? -EIO : 0;
+ return (ret != 1) ? -EREMOTEIO : 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)
+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)
{
- 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)
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
}
-
- /*
-- * 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)
+ #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)
{
- 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
+- 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..996802b
+index 0000000..090fb7d
--- /dev/null
-+++ b/drivers/md/dm-kcopyd.c
-@@ -0,0 +1,654 @@
++++ b/drivers/media/dvb/frontends/tda10048.c
+@@ -0,0 +1,841 @@
+/*
-+ * 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.
-+ */
++ NXP TDA10048HN DVB OFDM demodulator driver
+
-+#include <linux/types.h>
-+#include <asm/atomic.h>
-+#include <linux/blkdev.h>
-+#include <linux/fs.h>
++ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++#include <linux/kernel.h>
+#include <linux/init.h>
-+#include <linux/list.h>
-+#include <linux/mempool.h>
+#include <linux/module.h>
-+#include <linux/pagemap.h>
++#include <linux/string.h>
+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+#include <linux/workqueue.h>
-+#include <linux/mutex.h>
-+#include <linux/dm-kcopyd.h>
++#include <linux/delay.h>
++#include "dvb_frontend.h"
++#include "dvb_math.h"
++#include "tda10048.h"
+
-+#include "dm.h"
++#define TDA10048_DEFAULT_FIRMWARE "dvb-fe-tda10048-1.0.fw"
++#define TDA10048_DEFAULT_FIRMWARE_SIZE 24878
+
-+/*-----------------------------------------------------------------
-+ * 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;
++/* 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
+
-+ struct dm_io_client *io_client;
++static unsigned int debug;
+
-+ wait_queue_head_t destroyq;
-+ atomic_t nr_jobs;
++#define dprintk(level, fmt, arg...)\
++ do { if (debug >= level)\
++ printk(KERN_DEBUG "tda10048: " fmt, ## arg);\
++ } while (0)
+
-+ mempool_t *job_pool;
++struct tda10048_state {
+
-+ struct workqueue_struct *kcopyd_wq;
-+ struct work_struct kcopyd_work;
++ struct i2c_adapter *i2c;
+
-+/*
-+ * 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;
++ /* configuration settings */
++ const struct tda10048_config *config;
++ struct dvb_frontend frontend;
++
++ int fwloaded;
+};
+
-+static void wake(struct dm_kcopyd_client *kc)
-+{
-+ queue_work(kc->kcopyd_wq, &kc->kcopyd_work);
-+}
++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 struct page_list *alloc_pl(void)
++static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
+{
-+ struct page_list *pl;
++ int ret;
++ u8 buf [] = { reg, data };
++ struct i2c_msg msg = {
++ .addr = state->config->demod_address,
++ .flags = 0, .buf = buf, .len = 2 };
+
-+ pl = kmalloc(sizeof(*pl), GFP_KERNEL);
-+ if (!pl)
-+ return NULL;
++ dprintk(2, "%s(reg = 0x%02x, data = 0x%02x)\n", __func__, reg, data);
+
-+ pl->page = alloc_page(GFP_KERNEL);
-+ if (!pl->page) {
-+ kfree(pl);
-+ return NULL;
-+ }
++ ret = i2c_transfer(state->i2c, &msg, 1);
+
-+ return pl;
-+}
++ if (ret != 1)
++ printk("%s: writereg error (ret == %i)\n", __func__, ret);
+
-+static void free_pl(struct page_list *pl)
-+{
-+ __free_page(pl->page);
-+ kfree(pl);
++ return (ret != 1) ? -1 : 0;
+}
+
-+static int kcopyd_get_pages(struct dm_kcopyd_client *kc,
-+ unsigned int nr, struct page_list **pages)
++static u8 tda10048_readreg(struct tda10048_state *state, u8 reg)
+{
-+ struct page_list *pl;
-+
-+ spin_lock(&kc->lock);
-+ if (kc->nr_free_pages < nr) {
-+ spin_unlock(&kc->lock);
-+ return -ENOMEM;
-+ }
++ 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 } };
+
-+ kc->nr_free_pages -= nr;
-+ for (*pages = pl = kc->pages; --nr; pl = pl->next)
-+ ;
++ dprintk(2, "%s(reg = 0x%02x)\n", __func__, reg);
+
-+ kc->pages = pl->next;
-+ pl->next = NULL;
++ ret = i2c_transfer(state->i2c, msg, 2);
+
-+ spin_unlock(&kc->lock);
++ if (ret != 2)
++ printk(KERN_ERR "%s: readreg error (ret == %i)\n",
++ __func__, ret);
+
-+ return 0;
++ return b1[0];
+}
+
-+static void kcopyd_put_pages(struct dm_kcopyd_client *kc, struct page_list *pl)
++static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg,
++ u8 *data, u16 len)
+{
-+ struct page_list *cursor;
++ int ret = -EREMOTEIO;
++ struct i2c_msg msg;
++ u8 *buf;
+
-+ spin_lock(&kc->lock);
-+ for (cursor = pl; cursor->next; cursor = cursor->next)
-+ kc->nr_free_pages++;
++ dprintk(2, "%s(%d, ?, len = %d)\n", __func__, reg, len);
+
-+ kc->nr_free_pages++;
-+ cursor->next = kc->pages;
-+ kc->pages = pl;
-+ spin_unlock(&kc->lock);
-+}
++ buf = kmalloc(len + 1, GFP_KERNEL);
++ if (buf == NULL) {
++ ret = -ENOMEM;
++ goto error;
++ }
+
-+/*
-+ * These three functions resize the page pool.
-+ */
-+static void drop_pages(struct page_list *pl)
-+{
-+ struct page_list *next;
++ *buf = reg;
++ memcpy(buf + 1, data, len);
+
-+ while (pl) {
-+ next = pl->next;
-+ free_pl(pl);
-+ pl = next;
-+ }
-+}
++ msg.addr = state->config->demod_address;
++ msg.flags = 0;
++ msg.buf = buf;
++ msg.len = len + 1;
+
-+static int client_alloc_pages(struct dm_kcopyd_client *kc, unsigned int nr)
-+{
-+ unsigned int i;
-+ struct page_list *pl = NULL, *next;
++ dprintk(2, "%s(): write len = %d\n",
++ __func__, msg.len);
+
-+ for (i = 0; i < nr; i++) {
-+ next = alloc_pl();
-+ if (!next) {
-+ if (pl)
-+ drop_pages(pl);
-+ return -ENOMEM;
-+ }
-+ next->next = pl;
-+ pl = next;
++ ret = i2c_transfer(state->i2c, &msg, 1);
++ if (ret != 1) {
++ printk(KERN_ERR "%s(): writereg error err %i\n",
++ __func__, ret);
++ ret = -EREMOTEIO;
+ }
+
-+ kcopyd_put_pages(kc, pl);
-+ kc->nr_pages += nr;
-+ return 0;
++error:
++ kfree(buf);
++
++ return ret;
+}
+
-+static void client_free_pages(struct dm_kcopyd_client *kc)
++static int tda10048_firmware_upload(struct dvb_frontend *fe)
+{
-+ BUG_ON(kc->nr_free_pages != kc->nr_pages);
-+ drop_pages(kc->pages);
-+ kc->pages = NULL;
-+ kc->nr_free_pages = kc->nr_pages = 0;
-+}
++ struct tda10048_state *state = fe->demodulator_priv;
++ const struct firmware *fw;
++ int ret;
++ int pos = 0;
++ int cnt;
++ u8 wlen = state->config->fwbulkwritelen;
+
-+/*-----------------------------------------------------------------
-+ * 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;
++ if ((wlen != TDA10048_BULKWRITE_200) && (wlen != TDA10048_BULKWRITE_50))
++ wlen = TDA10048_BULKWRITE_200;
+
-+ /*
-+ * Error state of the job.
-+ */
-+ int read_err;
-+ unsigned long write_err;
++ /* request the firmware, this will block and timeout */
++ printk(KERN_INFO "%s: waiting for firmware upload (%s)...\n",
++ __func__,
++ TDA10048_DEFAULT_FIRMWARE);
+
-+ /*
-+ * Either READ or WRITE
-+ */
-+ int rw;
-+ struct dm_io_region source;
++ 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;
++ }
+
-+ /*
-+ * The destinations for the transfer.
-+ */
-+ unsigned int num_dests;
-+ struct dm_io_region dests[DM_KCOPYD_MAX_REGIONS];
++ 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__);
+
-+ sector_t offset;
-+ unsigned int nr_pages;
-+ struct page_list *pages;
++ /* 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);
+
-+ /*
-+ * 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;
++ /* Put the demod into host download mode */
++ tda10048_writereg(state, TDA10048_CONF_C4_1,
++ tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xf9);
+
-+ /*
-+ * 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;
-+};
++ /* Boot the DSP */
++ tda10048_writereg(state, TDA10048_CONF_C4_1,
++ tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x08);
+
-+/* FIXME: this should scale with the number of pages */
-+#define MIN_JOBS 512
++ /* Prepare for download */
++ tda10048_writereg(state, TDA10048_DSP_CODE_CPT, 0);
+
-+static struct kmem_cache *_job_cache;
++ /* Download the firmware payload */
++ while (pos < fw->size) {
+
-+int __init dm_kcopyd_init(void)
-+{
-+ _job_cache = KMEM_CACHE(kcopyd_job, 0);
-+ if (!_job_cache)
-+ return -ENOMEM;
++ if ((fw->size - pos) > wlen)
++ cnt = wlen;
++ else
++ cnt = fw->size - pos;
+
-+ return 0;
-+}
++ tda10048_writeregbulk(state, TDA10048_DSP_CODE_IN,
++ &fw->data[pos], cnt);
+
-+void dm_kcopyd_exit(void)
-+{
-+ kmem_cache_destroy(_job_cache);
-+ _job_cache = NULL;
-+}
++ pos += cnt;
++ }
+
-+/*
-+ * 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;
++ ret = -EIO;
++ /* Wait up to 250ms for the DSP to boot */
++ for (cnt = 0; cnt < 250 ; cnt += 10) {
+
-+ spin_lock_irqsave(&kc->job_lock, flags);
++ msleep(10);
+
-+ if (!list_empty(jobs)) {
-+ job = list_entry(jobs->next, struct kcopyd_job, list);
-+ list_del(&job->list);
++ if (tda10048_readreg(state, TDA10048_SYNC_STATUS)
++ & 0x40) {
++ ret = 0;
++ break;
++ }
++ }
+ }
-+ spin_unlock_irqrestore(&kc->job_lock, flags);
+
-+ return job;
-+}
++ release_firmware(fw);
+
-+static void push(struct list_head *jobs, struct kcopyd_job *job)
-+{
-+ unsigned long flags;
-+ struct dm_kcopyd_client *kc = job->kc;
++ if (ret == 0) {
++ printk(KERN_INFO "%s: firmware uploaded\n", __func__);
++ state->fwloaded = 1;
++ } else
++ printk(KERN_ERR "%s: firmware upload failed\n", __func__);
+
-+ spin_lock_irqsave(&kc->job_lock, flags);
-+ list_add_tail(&job->list, jobs);
-+ spin_unlock_irqrestore(&kc->job_lock, flags);
++ return ret;
+}
+
-+/*
-+ * 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)
++static int tda10048_set_inversion(struct dvb_frontend *fe, int inversion)
+{
-+ 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;
++ struct tda10048_state *state = fe->demodulator_priv;
+
-+ kcopyd_put_pages(kc, job->pages);
-+ mempool_free(job, kc->job_pool);
-+ fn(read_err, write_err, context);
++ dprintk(1, "%s(%d)\n", __func__, inversion);
+
-+ if (atomic_dec_and_test(&kc->nr_jobs))
-+ wake_up(&kc->destroyq);
++ 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;
+}
+
-+static void complete_io(unsigned long error, void *context)
++/* Retrieve the demod settings */
++static int tda10048_get_tps(struct tda10048_state *state,
++ struct dvb_ofdm_parameters *p)
+{
-+ struct kcopyd_job *job = (struct kcopyd_job *) context;
-+ struct dm_kcopyd_client *kc = job->kc;
++ u8 val;
+
-+ if (error) {
-+ if (job->rw == WRITE)
-+ job->write_err |= error;
-+ else
-+ job->read_err = 1;
++ /* Make sure the TPS regs are valid */
++ if (!(tda10048_readreg(state, TDA10048_AUTO) & 0x01))
++ return -EAGAIN;
+
-+ if (!test_bit(DM_KCOPYD_IGNORE_ERROR, &job->flags)) {
-+ push(&kc->complete_jobs, job);
-+ wake(kc);
-+ return;
-+ }
++ 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;
+ }
+
-+ if (job->rw == WRITE)
-+ push(&kc->complete_jobs, job);
++ 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;
++ }
+
-+ else {
-+ job->rw = WRITE;
-+ push(&kc->io_jobs, job);
++ 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;
+ }
+
-+ wake(kc);
++ return 0;
+}
+
-+/*
-+ * 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)
++static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
-+ 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,
-+ };
++ struct tda10048_state *state = fe->demodulator_priv;
++ dprintk(1, "%s(%d)\n", __func__, enable);
+
-+ if (job->rw == READ)
-+ r = dm_io(&io_req, 1, &job->source, NULL);
++ if (enable)
++ return tda10048_writereg(state, TDA10048_CONF_C4_1,
++ tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x02);
+ else
-+ r = dm_io(&io_req, job->num_dests, job->dests, NULL);
-+
-+ return r;
++ return tda10048_writereg(state, TDA10048_CONF_C4_1,
++ tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xfd);
+}
+
-+static int run_pages_job(struct kcopyd_job *job)
++static int tda10048_output_mode(struct dvb_frontend *fe, int serial)
+{
-+ int r;
++ struct tda10048_state *state = fe->demodulator_priv;
++ dprintk(1, "%s(%d)\n", __func__, serial);
+
-+ 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;
-+ }
++ /* Ensure pins are out of tri-state */
++ tda10048_writereg(state, TDA10048_CONF_TRISTATE1, 0x21);
++ tda10048_writereg(state, TDA10048_CONF_TRISTATE2, 0x00);
+
-+ if (r == -ENOMEM)
-+ /* can't complete now */
-+ return 1;
++ 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 r;
++ return 0;
+}
+
-+/*
-+ * 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 *))
++/* 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 kcopyd_job *job;
-+ int r, count = 0;
++ struct tda10048_state *state = fe->demodulator_priv;
+
-+ while ((job = pop(jobs, kc))) {
++ dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency);
+
-+ r = fn(job);
++ if (fe->ops.tuner_ops.set_params) {
+
-+ 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 (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
+
-+ if (r > 0) {
-+ /*
-+ * We couldn't service this job ATM, so
-+ * push this job back onto the list.
-+ */
-+ push(jobs, job);
-+ break;
-+ }
++ fe->ops.tuner_ops.set_params(fe, p);
+
-+ count++;
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
-+ return count;
++ /* Enable demod TPS auto detection and begin acquisition */
++ tda10048_writereg(state, TDA10048_AUTO, 0x57);
++
++ return 0;
+}
+
-+/*
-+ * kcopyd does this every time it's woken up.
-+ */
-+static void do_work(struct work_struct *work)
++/* Establish sane defaults and load firmware. */
++static int tda10048_init(struct dvb_frontend *fe)
+{
-+ struct dm_kcopyd_client *kc = container_of(work,
-+ struct dm_kcopyd_client, kcopyd_work);
++ struct tda10048_state *state = fe->demodulator_priv;
++ int ret = 0, i;
+
-+ /*
-+ * 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);
-+}
++ dprintk(1, "%s()\n", __func__);
+
-+/*
-+ * 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);
-+}
++ /* Apply register defaults */
++ for (i = 0; i < ARRAY_SIZE(init_tab); i++)
++ tda10048_writereg(state, init_tab[i].reg, init_tab[i].data);
+
-+#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;
++ if (state->fwloaded == 0)
++ ret = tda10048_firmware_upload(fe);
+
-+ mutex_lock(&job->lock);
++ /* Set either serial or parallel */
++ tda10048_output_mode(fe, state->config->output_mode);
+
-+ /* update the error */
-+ if (read_err)
-+ job->read_err = 1;
++ /* set inversion */
++ tda10048_set_inversion(fe, state->config->inversion);
+
-+ if (write_err)
-+ job->write_err |= write_err;
++ /* Ensure we leave the gate closed */
++ tda10048_i2c_gate_ctrl(fe, 0);
+
-+ /*
-+ * 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;
++ return ret;
++}
+
-+ job->progress += count;
-+ }
-+ }
-+ mutex_unlock(&job->lock);
++static int tda10048_read_status(struct dvb_frontend *fe, fe_status_t *status)
++{
++ struct tda10048_state *state = fe->demodulator_priv;
++ u8 reg;
+
-+ if (count) {
-+ int i;
-+ struct kcopyd_job *sub_job = mempool_alloc(job->kc->job_pool,
-+ GFP_NOIO);
++ *status = 0;
+
-+ *sub_job = *job;
-+ sub_job->source.sector += progress;
-+ sub_job->source.count = count;
++ reg = tda10048_readreg(state, TDA10048_SYNC_STATUS);
+
-+ for (i = 0; i < job->num_dests; i++) {
-+ sub_job->dests[i].sector += progress;
-+ sub_job->dests[i].count = count;
-+ }
++ dprintk(1, "%s() status =0x%02x\n", __func__, reg);
+
-+ sub_job->fn = segment_complete;
-+ sub_job->context = job;
-+ dispatch_job(sub_job);
++ if (reg & 0x02)
++ *status |= FE_HAS_CARRIER;
+
-+ } else if (atomic_dec_and_test(&job->sub_jobs)) {
++ if (reg & 0x04)
++ *status |= FE_HAS_SIGNAL;
+
-+ /*
-+ * 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);
++ if (reg & 0x08) {
++ *status |= FE_HAS_LOCK;
++ *status |= FE_HAS_VITERBI;
++ *status |= FE_HAS_SYNC;
+ }
++
++ return 0;
+}
+
-+/*
-+ * Create some little jobs that will do the move between
-+ * them.
-+ */
-+#define SPLIT_COUNT 8
-+static void split_job(struct kcopyd_job *job)
++static int tda10048_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
-+ int i;
++ struct tda10048_state *state = fe->demodulator_priv;
+
-+ atomic_set(&job->sub_jobs, SPLIT_COUNT);
-+ for (i = 0; i < SPLIT_COUNT; i++)
-+ segment_complete(0, 0u, job);
++ 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;
+}
+
-+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)
++static int tda10048_read_signal_strength(struct dvb_frontend *fe,
++ u16 *signal_strength)
+{
-+ struct kcopyd_job *job;
++ struct tda10048_state *state = fe->demodulator_priv;
++ u8 v;
+
-+ /*
-+ * Allocate a new job.
-+ */
-+ job = mempool_alloc(kc->job_pool, GFP_NOIO);
++ dprintk(1, "%s()\n", __func__);
+
-+ /*
-+ * set up for the read.
-+ */
-+ job->kc = kc;
-+ job->flags = flags;
-+ job->read_err = 0;
-+ job->write_err = 0;
-+ job->rw = READ;
++ *signal_strength = 65535;
+
-+ job->source = *from;
++ v = tda10048_readreg(state, TDA10048_NP_OUT);
++ if (v > 0)
++ *signal_strength -= (v << 8) | v;
+
-+ job->num_dests = num_dests;
-+ memcpy(&job->dests, dests, sizeof(*dests) * num_dests);
++ return 0;
++}
+
-+ job->offset = 0;
-+ job->nr_pages = 0;
-+ job->pages = NULL;
++/* 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 },
++};
+
-+ job->fn = fn;
-+ job->context = context;
++static int tda10048_read_snr(struct dvb_frontend *fe, u16 *snr)
++{
++ struct tda10048_state *state = fe->demodulator_priv;
++ u8 v;
++ int i, ret = -EINVAL;
+
-+ if (job->source.count < SUB_JOB_SIZE)
-+ dispatch_job(job);
++ dprintk(1, "%s()\n", __func__);
+
-+ else {
-+ mutex_init(&job->lock);
-+ job->progress = 0;
-+ split_job(job);
++ 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 0;
++ return ret;
+}
-+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)
++static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
-+ /* FIXME: finish */
-+ return -1;
++ 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;
+}
-+#endif /* 0 */
+
-+/*-----------------------------------------------------------------
-+ * Client setup
-+ *---------------------------------------------------------------*/
-+int dm_kcopyd_client_create(unsigned int nr_pages,
-+ struct dm_kcopyd_client **result)
++static int tda10048_get_frontend(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *p)
+{
-+ int r = -ENOMEM;
-+ struct dm_kcopyd_client *kc;
++ struct tda10048_state *state = fe->demodulator_priv;
+
-+ kc = kmalloc(sizeof(*kc), GFP_KERNEL);
-+ if (!kc)
-+ return -ENOMEM;
++ dprintk(1, "%s()\n", __func__);
+
-+ 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);
++ p->inversion = tda10048_readreg(state, TDA10048_CONF_C1_1)
++ & 0x20 ? INVERSION_ON : INVERSION_OFF;
+
-+ kc->job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache);
-+ if (!kc->job_pool)
-+ goto bad_slab;
++ return tda10048_get_tps(state, &p->u.ofdm);
++}
+
-+ INIT_WORK(&kc->kcopyd_work, do_work);
-+ kc->kcopyd_wq = create_singlethread_workqueue("kcopyd");
-+ if (!kc->kcopyd_wq)
-+ goto bad_workqueue;
++static int tda10048_get_tune_settings(struct dvb_frontend *fe,
++ struct dvb_frontend_tune_settings *tune)
++{
++ tune->min_delay_ms = 1000;
++ return 0;
++}
+
-+ kc->pages = NULL;
-+ kc->nr_pages = kc->nr_free_pages = 0;
-+ r = client_alloc_pages(kc, nr_pages);
-+ if (r)
-+ goto bad_client_pages;
++static void tda10048_release(struct dvb_frontend *fe)
++{
++ struct tda10048_state *state = fe->demodulator_priv;
++ dprintk(1, "%s()\n", __func__);
++ kfree(state);
++}
+
-+ 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;
-+ }
++static struct dvb_frontend_ops tda10048_ops;
+
-+ init_waitqueue_head(&kc->destroyq);
-+ atomic_set(&kc->nr_jobs, 0);
++struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
++ struct i2c_adapter *i2c)
++{
++ struct tda10048_state *state = NULL;
+
-+ *result = kc;
-+ return 0;
++ dprintk(1, "%s()\n", __func__);
+
-+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);
++ /* allocate memory for the internal state */
++ state = kmalloc(sizeof(struct tda10048_state), GFP_KERNEL);
++ if (state == NULL)
++ goto error;
+
-+ return r;
-+}
-+EXPORT_SYMBOL(dm_kcopyd_client_create);
++ /* setup the state */
++ state->config = config;
++ state->i2c = i2c;
++ state->fwloaded = 0;
+
-+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));
++ /* check if the demod is present */
++ if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048)
++ goto error;
+
-+ BUG_ON(!list_empty(&kc->complete_jobs));
-+ BUG_ON(!list_empty(&kc->io_jobs));
-+ BUG_ON(!list_empty(&kc->pages_jobs));
-+ destroy_workqueue(kc->kcopyd_wq);
-+ dm_io_client_destroy(kc->io_client);
-+ client_free_pages(kc);
-+ mempool_destroy(kc->job_pool);
-+ kfree(kc);
-+}
-+EXPORT_SYMBOL(dm_kcopyd_client_destroy);
-diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
-index 2a74b21..67a6f31 100644
---- a/drivers/md/dm-log.c
-+++ b/drivers/md/dm-log.c
-@@ -1,5 +1,6 @@
- /*
- * Copyright (C) 2003 Sistina Software
-+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
- *
- * This file is released under the LGPL.
- */
-@@ -8,64 +9,58 @@
- #include <linux/slab.h>
- #include <linux/module.h>
- #include <linux/vmalloc.h>
-+#include <linux/dm-io.h>
-+#include <linux/dm-dirty-log.h>
-
--#include "dm-log.h"
--#include "dm-io.h"
-+#include "dm.h"
-
--#define DM_MSG_PREFIX "mirror log"
-+#define DM_MSG_PREFIX "dirty region log"
-
--static LIST_HEAD(_log_types);
--static DEFINE_SPINLOCK(_lock);
-+struct dm_dirty_log_internal {
-+ struct dm_dirty_log_type *type;
-
--int dm_register_dirty_log_type(struct dirty_log_type *type)
--{
-- spin_lock(&_lock);
-- type->use_count = 0;
-- list_add(&type->list, &_log_types);
-- spin_unlock(&_lock);
-+ struct list_head list;
-+ long use;
-+};
-
-- return 0;
--}
-+static LIST_HEAD(_log_types);
-+static DEFINE_SPINLOCK(_lock);
-
--int dm_unregister_dirty_log_type(struct dirty_log_type *type)
-+static struct dm_dirty_log_internal *__find_dirty_log_type(const char *name)
- {
-- spin_lock(&_lock);
--
-- if (type->use_count)
-- DMWARN("Attempt to unregister a log type that is still in use");
-- else
-- list_del(&type->list);
-+ struct dm_dirty_log_internal *log_type;
-
-- spin_unlock(&_lock);
-+ list_for_each_entry(log_type, &_log_types, list)
-+ if (!strcmp(name, log_type->type->name))
-+ return log_type;
-
-- return 0;
-+ return NULL;
- }
-
--static struct dirty_log_type *_get_type(const char *type_name)
-+static struct dm_dirty_log_internal *_get_dirty_log_type(const char *name)
- {
-- struct dirty_log_type *type;
-+ struct dm_dirty_log_internal *log_type;
-
- spin_lock(&_lock);
-- list_for_each_entry (type, &_log_types, list)
-- if (!strcmp(type_name, type->name)) {
-- if (!type->use_count && !try_module_get(type->module)){
-- spin_unlock(&_lock);
-- return NULL;
-- }
-- type->use_count++;
-- spin_unlock(&_lock);
-- return type;
-- }
++ /* create dvb_frontend */
++ memcpy(&state->frontend.ops, &tda10048_ops,
++ sizeof(struct dvb_frontend_ops));
++ state->frontend.demodulator_priv = state;
+
-+ 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;
++ /* Leave the gate closed */
++ tda10048_i2c_gate_ctrl(&state->frontend, 0);
+
-+ 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;
++ return &state->frontend;
+
-+ 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;
++error:
++ kfree(state);
++ return NULL;
++}
++EXPORT_SYMBOL(tda10048_attach);
+
-+ if (!type)
-+ return;
++static struct dvb_frontend_ops tda10048_ops = {
+
- spin_lock(&_lock);
-- if (!--type->use_count)
-+ log_type = __find_dirty_log_type(type->name);
-+ if (!log_type)
-+ goto out;
++ .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
++ },
+
-+ if (!--log_type->use)
- module_put(type->module);
++ .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,
++};
+
-+ BUG_ON(log_type->use < 0);
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
-+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);
++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
+
-+ if (log_type)
-+ log_type->type = type;
++ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
+
-+ return log_type;
-+}
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
+
-+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;
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
+
-+ if (!log_type)
-+ return -ENOMEM;
++ You 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.
+
-+ 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);
++#ifndef TDA10048_H
++#define TDA10048_H
+
-+int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type)
-+{
-+ struct dm_dirty_log_internal *log_type;
++#include <linux/dvb/frontend.h>
++#include <linux/firmware.h>
+
-+ spin_lock(&_lock);
++struct tda10048_config {
+
-+ log_type = __find_dirty_log_type(type->name);
-+ if (!log_type) {
-+ spin_unlock(&_lock);
-+ return -EINVAL;
-+ }
++ /* the demodulator's i2c address */
++ u8 demod_address;
+
-+ if (log_type->use) {
-+ spin_unlock(&_lock);
-+ return -ETXTBSY;
-+ }
++ /* serial/parallel output */
++#define TDA10048_PARALLEL_OUTPUT 0
++#define TDA10048_SERIAL_OUTPUT 1
++ u8 output_mode;
+
-+ list_del(&log_type->list);
++#define TDA10048_BULKWRITE_200 200
++#define TDA10048_BULKWRITE_50 50
++ u8 fwbulkwritelen;
+
-+ spin_unlock(&_lock);
-+ kfree(log_type);
++ /* Spectral Inversion */
++#define TDA10048_INVERSION_OFF 0
++#define TDA10048_INVERSION_ON 1
++ u8 inversion;
++};
+
-+ return 0;
++#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;
+}
-+EXPORT_SYMBOL(dm_dirty_log_type_unregister);
++#endif /* CONFIG_DVB_TDA10048 */
+
-+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;
++#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 };
- 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
+- dprintk("%s: reg=0x%x, data=0x%x\n", __FUNCTION__, reg, data);
++ dprintk("%s: reg=0x%x, data=0x%x\n", __func__, reg, data);
- return log;
- }
-+EXPORT_SYMBOL(dm_dirty_log_create);
+ msg.addr = state->config->demod_address;
+ ret = i2c_transfer(state->i2c, &msg, 1);
--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);
+ 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;
}
-+EXPORT_SYMBOL(dm_dirty_log_destroy);
+@@ -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 }};
- /*-----------------------------------------------------------------
- * 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;
+- dprintk("%s: reg=0x%x\n", __FUNCTION__, reg);
++ dprintk("%s: reg=0x%x\n", __func__, reg);
-- struct io_region header_location;
-+ struct dm_io_region header_location;
- struct log_header *disk_header;
- };
+ msg[0].addr = state->config->demod_address;
+ msg[1].addr = state->config->demod_address;
+ ret = i2c_transfer(state->i2c, msg, 2);
-@@ -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;
+ 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];
}
-@@ -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)
+@@ -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)
{
-@@ -315,7 +387,7 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti,
- int r;
+ 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);
- if (argc < 1 || argc > 2) {
-- DMWARN("wrong number of arguments to mirror log");
-+ DMWARN("wrong number of arguments to dirty region log");
- return -EINVAL;
- }
+ // 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;
-@@ -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;
- }
+- dprintk("%s: reg=0x%x, len=0x%x\n", __FUNCTION__, reg, len);
++ dprintk("%s: reg=0x%x, len=0x%x\n", __func__, reg, len);
--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)
+ 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)
{
- return create_log_context(log, ti, argc, argv, NULL);
-@@ -447,7 +519,7 @@ static void destroy_log_context(struct log_c *lc)
- kfree(lc);
- }
+ int result;
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
--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;
+ 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)
-@@ -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)
+ static int tda1004x_disable_tuner_i2c(struct tda1004x_state *state)
{
- int r;
- struct dm_dev *dev;
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
- 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;
+ 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;
-@@ -485,7 +557,7 @@ static int disk_ctr(struct dirty_log *log, struct dm_target *ti,
- return 0;
- }
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
--static void disk_dtr(struct dirty_log *log)
-+static void disk_dtr(struct dm_dirty_log *log)
+ 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 log_c *lc = (struct log_c *) log->context;
+ struct tda1004x_state* state = fe->demodulator_priv;
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
-@@ -514,7 +586,7 @@ static void fail_log_device(struct log_c *lc)
- dm_table_event(lc->ti->table);
- }
+ 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;
--static int disk_resume(struct dirty_log *log)
-+static int disk_resume(struct dm_dirty_log *log)
+- 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
{
- 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);
+ 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
}
-@@ -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;
+ // success
+- dprintk("%s: fe_status=0x%x\n", __FUNCTION__, *fe_status);
++ dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
+ return 0;
}
--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;
+@@ -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;
}
--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);
- }
+@@ -1086,7 +1086,7 @@ static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
+ struct tda1004x_state* state = fe->demodulator_priv;
+ int tmp;
--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);
- }
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
--static int core_flush(struct dirty_log *log)
-+static int core_flush(struct dm_dirty_log *log)
- {
- /* no op */
+ // 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;
}
--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;
- }
+@@ -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;
--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);
+- dprintk("%s: ucblocks=0x%x\n", __FUNCTION__, *ucblocks);
++ dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks);
+ return 0;
}
--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);
- }
+@@ -1141,7 +1141,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber)
+ struct tda1004x_state* state = fe->demodulator_priv;
+ int tmp;
--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;
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
-@@ -654,7 +726,7 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region)
- return 1;
- }
+ // 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);
--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,
- }
+- dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber);
++ dprintk("%s: ber=0x%x\n", __func__, *ber);
+ return 0;
}
--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;
+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
-@@ -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" : "")
+ /* slave address and configuration of the tuner */
+ u8 tuner_address;
+- u8 tuner_config;
+ u8 antenna_switch;
--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)
+ /* 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)
{
- int sz = 0;
-@@ -700,7 +772,7 @@ static int core_status(struct dirty_log *log, status_type_t status,
- return sz;
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
}
-
--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)
+ static inline struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
+ struct i2c_adapter* i2c)
{
- int sz = 0;
-@@ -722,7 +794,7 @@ static int disk_status(struct dirty_log *log, status_type_t status,
- return sz;
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
}
-
--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,
+ #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 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");
+-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)
-- 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);
- }
+ if (ret != 1)
+ dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
+- __FUNCTION__, reg, data, ret);
++ __func__, reg, data, ret);
- return r;
+ 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);
--void dm_dirty_log_exit(void)
-+void __exit dm_dirty_log_exit(void)
+ 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,
{
-- dm_unregister_dirty_log_type(&_disk_type);
-- dm_unregister_dirty_log_type(&_core_type);
-+ dm_dirty_log_type_unregister(&_disk_type);
-+ dm_dirty_log_type_unregister(&_core_type);
- }
-
--EXPORT_SYMBOL(dm_register_dirty_log_type);
--EXPORT_SYMBOL(dm_unregister_dirty_log_type);
--EXPORT_SYMBOL(dm_create_dirty_log);
--EXPORT_SYMBOL(dm_destroy_dirty_log);
-+module_init(dm_dirty_log_init);
-+module_exit(dm_dirty_log_exit);
-+
-+MODULE_DESCRIPTION(DM_NAME " dirty region log");
-+MODULE_AUTHOR("Joe Thornber, Heinz Mauelshagen <dm-devel at redhat.com>");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/md/dm-log.h b/drivers/md/dm-log.h
-deleted file mode 100644
-index 3fae87e..0000000
---- a/drivers/md/dm-log.h
-+++ /dev/null
-@@ -1,131 +0,0 @@
--/*
-- * Copyright (C) 2003 Sistina Software
-- *
-- * This file is released under the LGPL.
-- */
--
--#ifndef DM_DIRTY_LOG
--#define DM_DIRTY_LOG
--
--#include "dm.h"
--
--typedef sector_t region_t;
--
--struct dirty_log_type;
--
--struct dirty_log {
-- struct dirty_log_type *type;
-- void *context;
--};
--
--struct dirty_log_type {
-- struct list_head list;
-- const char *name;
-- struct module *module;
-- unsigned int use_count;
--
-- int (*ctr)(struct dirty_log *log, struct dm_target *ti,
-- unsigned int argc, char **argv);
-- void (*dtr)(struct dirty_log *log);
--
-- /*
-- * There are times when we don't want the log to touch
-- * the disk.
-- */
-- int (*presuspend)(struct dirty_log *log);
-- int (*postsuspend)(struct dirty_log *log);
-- int (*resume)(struct dirty_log *log);
--
-- /*
-- * Retrieves the smallest size of region that the log can
-- * deal with.
-- */
-- uint32_t (*get_region_size)(struct dirty_log *log);
--
-- /*
-- * A predicate to say whether a region is clean or not.
-- * May block.
-- */
-- int (*is_clean)(struct dirty_log *log, region_t region);
--
-- /*
-- * Returns: 0, 1, -EWOULDBLOCK, < 0
-- *
-- * A predicate function to check the area given by
-- * [sector, sector + len) is in sync.
-- *
-- * If -EWOULDBLOCK is returned the state of the region is
-- * unknown, typically this will result in a read being
-- * passed to a daemon to deal with, since a daemon is
-- * allowed to block.
-- */
-- int (*in_sync)(struct dirty_log *log, region_t region, int can_block);
--
-- /*
-- * Flush the current log state (eg, to disk). This
-- * function may block.
-- */
-- int (*flush)(struct dirty_log *log);
--
-- /*
-- * Mark an area as clean or dirty. These functions may
-- * block, though for performance reasons blocking should
-- * be extremely rare (eg, allocating another chunk of
-- * memory for some reason).
-- */
-- void (*mark_region)(struct dirty_log *log, region_t region);
-- void (*clear_region)(struct dirty_log *log, region_t region);
--
-- /*
-- * Returns: <0 (error), 0 (no region), 1 (region)
-- *
-- * The mirrord will need perform recovery on regions of
-- * the mirror that are in the NOSYNC state. This
-- * function asks the log to tell the caller about the
-- * next region that this machine should recover.
-- *
-- * Do not confuse this function with 'in_sync()', one
-- * tells you if an area is synchronised, the other
-- * assigns recovery work.
-- */
-- int (*get_resync_work)(struct dirty_log *log, region_t *region);
--
-- /*
-- * This notifies the log that the resync status of a region
-- * has changed. It also clears the region from the recovering
-- * list (if present).
-- */
-- void (*set_region_sync)(struct dirty_log *log,
-- region_t region, int in_sync);
--
-- /*
-- * Returns the number of regions that are in sync.
-- */
-- region_t (*get_sync_count)(struct dirty_log *log);
--
-- /*
-- * Support function for mirror status requests.
-- */
-- int (*status)(struct dirty_log *log, status_type_t status_type,
-- char *result, unsigned int maxlen);
--};
--
--int dm_register_dirty_log_type(struct dirty_log_type *type);
--int dm_unregister_dirty_log_type(struct dirty_log_type *type);
--
--
--/*
-- * Make sure you use these two functions, rather than calling
-- * type->constructor/destructor() directly.
-- */
--struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *ti,
-- unsigned int argc, char **argv);
--void dm_destroy_dirty_log(struct dirty_log *log);
--
--/*
-- * init/exit functions.
-- */
--int dm_dirty_log_init(void);
--void dm_dirty_log_exit(void);
--
--#endif
-diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
-index 762cb08..ff05fe8 100644
---- a/drivers/md/dm-raid1.c
-+++ b/drivers/md/dm-raid1.c
-@@ -7,9 +7,6 @@
- #include "dm.h"
- #include "dm-bio-list.h"
- #include "dm-bio-record.h"
--#include "dm-io.h"
--#include "dm-log.h"
--#include "kcopyd.h"
-
- #include <linux/ctype.h>
- #include <linux/init.h>
-@@ -22,6 +19,9 @@
- #include <linux/workqueue.h>
- #include <linux/log2.h>
- #include <linux/hardirq.h>
-+#include <linux/dm-io.h>
-+#include <linux/dm-dirty-log.h>
-+#include <linux/dm-kcopyd.h>
+ int val;
- #define DM_MSG_PREFIX "raid1"
- #define DM_IO_PAGES 64
-@@ -74,7 +74,7 @@ struct region_hash {
- unsigned region_shift;
+- // read a byte and check
++ /* read a byte and check */
+ val = tda10086_read_byte(state, reg);
+ if (val < 0)
+ return val;
- /* holds persistent region state */
-- struct dirty_log *log;
-+ struct dm_dirty_log *log;
+- // mask if off
++ /* mask if off */
+ val = val & ~mask;
+ val |= data & 0xff;
- /* 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;
+- // write it out again
++ /* write it out again */
+ return tda10086_write_byte(state, reg, val);
+ }
- spinlock_t lock; /* protects the lists */
-@@ -154,6 +154,9 @@ struct mirror_set {
+@@ -108,62 +108,67 @@ static int tda10086_init(struct dvb_frontend* fe)
+ struct tda10086_state* state = fe->demodulator_priv;
+ u8 t22k_off = 0x80;
- struct workqueue_struct *kmirrord_wq;
- struct work_struct kmirrord_work;
-+ struct timer_list timer;
-+ unsigned long timer_pending;
-+
- struct work_struct trigger_event;
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- unsigned int nr_mirrors;
-@@ -178,13 +181,32 @@ static void wake(struct mirror_set *ms)
- queue_work(ms->kmirrord_wq, &ms->kmirrord_work);
- }
+ if (state->config->diseqc_tone)
+ t22k_off = 0;
+- // reset
++ /* reset */
+ tda10086_write_byte(state, 0x00, 0x00);
+ msleep(10);
-+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;
+- // 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 */
+
-+ ms->timer.expires = jiffies + HZ / 5;
-+ ms->timer.data = (unsigned long) ms;
-+ ms->timer.function = delayed_wake_fn;
-+ add_timer(&ms->timer);
-+}
++ /* 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 */
+
- /* 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);
- }
++ /* 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);
- 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);
+- // 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 */
- 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;
+- // 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);
-@@ -822,9 +842,9 @@ static int recover(struct mirror_set *ms, struct region *reg)
- }
+- // 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 */
- /* 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);
+- // setup carrier recovery
++ /* setup carrier recovery */
+ tda10086_write_byte(state, 0x3d, 0x80);
- 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;
+- // 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);
- /*
- * 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);
+ 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;
--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);
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
-- wake(ms);
-+ delayed_wake(ms);
- }
+ 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;
- 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);
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
-- 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);
- }
+ 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__);
-@@ -1303,7 +1308,7 @@ static void do_mirror(struct work_struct *work)
- static struct mirror_set *alloc_context(unsigned int nr_mirrors,
- uint32_t region_size,
- struct dm_target *ti,
-- struct dirty_log *dl)
-+ struct dm_dirty_log *dl)
- {
- size_t len;
- struct mirror_set *ms = NULL;
-@@ -1403,12 +1408,12 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
- /*
- * Create dirty log: log_type #log_params <log_params>
- */
--static struct dirty_log *create_dirty_log(struct dm_target *ti,
-+static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
- unsigned int argc, char **argv,
- unsigned int *args_used)
+ if (state->config->diseqc_tone)
+ t22k_off = 0;
+@@ -266,7 +271,7 @@ static int tda10086_set_inversion(struct tda10086_state *state,
{
- unsigned int param_count;
-- struct dirty_log *dl;
-+ struct dm_dirty_log *dl;
+ u8 invval = 0x80;
- 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;
- }
+- dprintk ("%s %i %i\n", __FUNCTION__, fe_params->inversion, state->config->invert);
++ dprintk ("%s %i %i\n", __func__, fe_params->inversion, state->config->invert);
-- 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,
+ 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;
- 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;
+- 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;
}
-@@ -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;
+- // calculate BDR
++ /* calculate BDR */
+ big = (1ULL<<21) * ((u64) symbol_rate/1000ULL) * (1ULL<<dfn);
+ big += ((SACLK/1000ULL)-1ULL);
+ do_div(big, (SACLK/1000ULL));
+ bdr = big & 0xfffff;
- 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;
+- // calculate BDRI
++ /* calculate BDRI */
+ tmp = (1<<dfn)*(symbol_rate/1000);
+ bdri = ((32 * (SACLK/1000)) + (tmp-1)) / tmp;
- 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;
- }
+@@ -366,7 +371,7 @@ static int tda10086_set_fec(struct tda10086_state *state,
+ {
+ u8 fecval;
-@@ -1516,13 +1521,13 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+- dprintk ("%s %i\n", __FUNCTION__, fe_params->u.qpsk.fec_inner);
++ dprintk ("%s %i\n", __func__, fe_params->u.qpsk.fec_inner);
- if (argc < nr_mirrors * 2) {
- ti->error = "Too few mirror arguments";
-- dm_destroy_dirty_log(dl);
-+ dm_dirty_log_destroy(dl);
- return -EINVAL;
- }
+ 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;
- 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;
- }
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
-@@ -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);
+- // modify parameters for tuning
++ /* modify parameters for tuning */
+ tda10086_write_byte(state, 0x02, 0x35);
+ state->has_lock = false;
- 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;
+- // 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);
}
-- 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;
+- // 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;
-@@ -1589,8 +1596,9 @@ static void mirror_dtr(struct dm_target *ti)
- {
- struct mirror_set *ms = (struct mirror_set *) ti->private;
+- // 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);
-+ 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;
+@@ -459,13 +464,13 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
+ int tmp;
+ u64 tmp64;
- atomic_set(&ms->suspend, 1);
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
-@@ -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;
+- // check for invalid symbol rate
++ /* check for invalid symbol rate */
+ if (fe_params->u.qpsk.symbol_rate < 500000)
+ return -EINVAL;
- 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;
+- // 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;
- 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];
+- // 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
+ }
+ }
- switch (type) {
-@@ -1864,15 +1872,9 @@ static int __init dm_mirror_init(void)
- {
- int r;
+- // 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;
-- 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();
-- }
+- // 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;
- 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();
- }
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- /* Module hooks */
-diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
-index 4dc8a43..1ba8a47 100644
---- a/drivers/md/dm-snap.c
-+++ b/drivers/md/dm-snap.c
-@@ -18,10 +18,10 @@
- #include <linux/slab.h>
- #include <linux/vmalloc.h>
- #include <linux/log2.h>
-+#include <linux/dm-kcopyd.h>
+ 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;
- #include "dm-snap.h"
- #include "dm-bio-list.h"
--#include "kcopyd.h"
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- #define DM_MSG_PREFIX "snapshots"
+ _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;
-@@ -36,9 +36,9 @@
- #define SNAPSHOT_COPY_PRIORITY 2
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- /*
-- * 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)
+ _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;
- 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;
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- /* 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;
- }
+- // read it
++ /* read it */
+ *ucblocks = tda10086_read_byte(state, 0x18) & 0x7f;
-- 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;
+- // reset counter
++ /* reset counter */
+ tda10086_write_byte(state, 0x18, 0x00);
+ tda10086_write_byte(state, 0x18, 0x80);
- bad6:
-- kcopyd_client_destroy(s->kcopyd_client);
-+ dm_kcopyd_client_destroy(s->kcopyd_client);
+@@ -620,9 +625,9 @@ static int tda10086_read_ber(struct dvb_frontend* fe, u32* ber)
+ {
+ struct tda10086_state* state = fe->demodulator_priv;
- bad5:
- s->store.destroy(&s->store);
-@@ -613,7 +613,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- static void __free_exceptions(struct dm_snapshot *s)
+- // 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)
{
-- 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)
+ struct tda10086_state* state = fe->demodulator_priv;
- s->valid = 0;
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
-- dm_table_event(s->table);
-+ dm_table_event(s->ti->table);
- }
+ tda10086_write_mask(state, 0x00, 0x08, 0x08);
- 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)
+@@ -646,7 +651,7 @@ static int tda10086_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
{
- 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);
- }
+ struct tda10086_state* state = fe->demodulator_priv;
-@@ -1060,7 +1060,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
- goto next_snapshot;
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- /* 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;
+ 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;
- /*
-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 {
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
- struct dm_snapshot {
- struct rw_semaphore lock;
-- struct dm_table *table;
-+ struct dm_target *ti;
+ /* allocate memory for the internal state */
+ state = kmalloc(sizeof(struct tda10086_state), GFP_KERNEL);
+diff --git a/drivers/media/dvb/frontends/tda10086.h b/drivers/media/dvb/frontends/tda10086.h
+index eeceaee..61148c5 100644
+--- a/drivers/media/dvb/frontends/tda10086.h
++++ b/drivers/media/dvb/frontends/tda10086.h
+@@ -26,6 +26,11 @@
+ #include <linux/dvb/frontend.h>
+ #include <linux/firmware.h>
- struct dm_dev *origin;
- struct dm_dev *cow;
-@@ -169,7 +169,7 @@ struct dm_snapshot {
- /* The on disk metadata handler */
- struct exception_store store;
++enum tda10086_xtal {
++ TDA10086_XTAL_16M,
++ TDA10086_XTAL_4M
++};
++
+ struct tda10086_config
+ {
+ /* the demodulator's i2c address */
+@@ -36,6 +41,9 @@ struct tda10086_config
-- struct kcopyd_client *kcopyd_client;
-+ struct dm_kcopyd_client *kcopyd_client;
+ /* do we need the diseqc signal with carrier? */
+ u8 diseqc_tone;
++
++ /* frequency of the reference xtal */
++ enum tda10086_xtal xtal_freq;
+ };
- /* 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;
+ #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 */
--int dm_create_error_table(struct dm_table **result, struct mapped_device *md)
+-#endif // TDA10086_H
++#endif /* TDA10086_H */
+diff --git a/drivers/media/dvb/frontends/tda18271-common.c b/drivers/media/dvb/frontends/tda18271-common.c
+deleted file mode 100644
+index bca5709..0000000
+--- a/drivers/media/dvb/frontends/tda18271-common.c
++++ /dev/null
+@@ -1,653 +0,0 @@
+-/*
+- tda18271-common.c - driver for the Philips / NXP TDA18271 silicon tuner
+-
+- Copyright (C) 2007, 2008 Michael Krufky <mkrufky at linuxtv.org>
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2 of the License, or
+- (at your option) any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
+-
+- You 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 "tda18271-priv.h"
+-
+-static int tda18271_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-- struct dm_table *t;
-- sector_t dev_size = 1;
-- int r;
+- struct tda18271_priv *priv = fe->tuner_priv;
+- enum tda18271_i2c_gate gate;
+- int ret = 0;
-
-- /*
-- * 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);
+- switch (priv->gate) {
+- case TDA18271_GATE_DIGITAL:
+- case TDA18271_GATE_ANALOG:
+- gate = priv->gate;
+- break;
+- case TDA18271_GATE_AUTO:
+- default:
+- switch (priv->mode) {
+- case TDA18271_DIGITAL:
+- gate = TDA18271_GATE_DIGITAL;
+- break;
+- case TDA18271_ANALOG:
+- default:
+- gate = TDA18271_GATE_ANALOG;
+- break;
+- }
- }
-
-- r = dm_table_create(&t, FMODE_READ, 1, md);
-- if (r)
-- return r;
+- switch (gate) {
+- case TDA18271_GATE_ANALOG:
+- if (fe->ops.analog_ops.i2c_gate_ctrl)
+- ret = fe->ops.analog_ops.i2c_gate_ctrl(fe, enable);
+- break;
+- case TDA18271_GATE_DIGITAL:
+- if (fe->ops.i2c_gate_ctrl)
+- ret = fe->ops.i2c_gate_ctrl(fe, enable);
+- break;
+- default:
+- ret = -EINVAL;
+- break;
+- }
-
-- r = dm_table_add_target(t, "error", 0, dev_size, NULL);
-- if (r)
-- goto out;
+- return ret;
+-};
-
-- r = dm_table_complete(t);
-- if (r)
-- goto out;
+-/*---------------------------------------------------------------------*/
-
-- *result = t;
+-static void tda18271_dump_regs(struct dvb_frontend *fe, int extended)
+-{
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
-
--out:
-- if (r)
-- dm_table_put(t);
+- tda_reg("=== TDA18271 REG DUMP ===\n");
+- tda_reg("ID_BYTE = 0x%02x\n", 0xff & regs[R_ID]);
+- tda_reg("THERMO_BYTE = 0x%02x\n", 0xff & regs[R_TM]);
+- tda_reg("POWER_LEVEL_BYTE = 0x%02x\n", 0xff & regs[R_PL]);
+- tda_reg("EASY_PROG_BYTE_1 = 0x%02x\n", 0xff & regs[R_EP1]);
+- tda_reg("EASY_PROG_BYTE_2 = 0x%02x\n", 0xff & regs[R_EP2]);
+- tda_reg("EASY_PROG_BYTE_3 = 0x%02x\n", 0xff & regs[R_EP3]);
+- tda_reg("EASY_PROG_BYTE_4 = 0x%02x\n", 0xff & regs[R_EP4]);
+- tda_reg("EASY_PROG_BYTE_5 = 0x%02x\n", 0xff & regs[R_EP5]);
+- tda_reg("CAL_POST_DIV_BYTE = 0x%02x\n", 0xff & regs[R_CPD]);
+- tda_reg("CAL_DIV_BYTE_1 = 0x%02x\n", 0xff & regs[R_CD1]);
+- tda_reg("CAL_DIV_BYTE_2 = 0x%02x\n", 0xff & regs[R_CD2]);
+- tda_reg("CAL_DIV_BYTE_3 = 0x%02x\n", 0xff & regs[R_CD3]);
+- tda_reg("MAIN_POST_DIV_BYTE = 0x%02x\n", 0xff & regs[R_MPD]);
+- tda_reg("MAIN_DIV_BYTE_1 = 0x%02x\n", 0xff & regs[R_MD1]);
+- tda_reg("MAIN_DIV_BYTE_2 = 0x%02x\n", 0xff & regs[R_MD2]);
+- tda_reg("MAIN_DIV_BYTE_3 = 0x%02x\n", 0xff & regs[R_MD3]);
-
-- return r;
+- /* only dump extended regs if DBG_ADV is set */
+- if (!(tda18271_debug & DBG_ADV))
+- return;
+-
+- /* W indicates write-only registers.
+- * Register dump for write-only registers shows last value written. */
+-
+- tda_reg("EXTENDED_BYTE_1 = 0x%02x\n", 0xff & regs[R_EB1]);
+- tda_reg("EXTENDED_BYTE_2 = 0x%02x\n", 0xff & regs[R_EB2]);
+- tda_reg("EXTENDED_BYTE_3 = 0x%02x\n", 0xff & regs[R_EB3]);
+- tda_reg("EXTENDED_BYTE_4 = 0x%02x\n", 0xff & regs[R_EB4]);
+- tda_reg("EXTENDED_BYTE_5 = 0x%02x\n", 0xff & regs[R_EB5]);
+- tda_reg("EXTENDED_BYTE_6 = 0x%02x\n", 0xff & regs[R_EB6]);
+- tda_reg("EXTENDED_BYTE_7 = 0x%02x\n", 0xff & regs[R_EB7]);
+- tda_reg("EXTENDED_BYTE_8 = 0x%02x\n", 0xff & regs[R_EB8]);
+- tda_reg("EXTENDED_BYTE_9 W = 0x%02x\n", 0xff & regs[R_EB9]);
+- tda_reg("EXTENDED_BYTE_10 = 0x%02x\n", 0xff & regs[R_EB10]);
+- tda_reg("EXTENDED_BYTE_11 = 0x%02x\n", 0xff & regs[R_EB11]);
+- tda_reg("EXTENDED_BYTE_12 = 0x%02x\n", 0xff & regs[R_EB12]);
+- tda_reg("EXTENDED_BYTE_13 = 0x%02x\n", 0xff & regs[R_EB13]);
+- tda_reg("EXTENDED_BYTE_14 = 0x%02x\n", 0xff & regs[R_EB14]);
+- tda_reg("EXTENDED_BYTE_15 = 0x%02x\n", 0xff & regs[R_EB15]);
+- tda_reg("EXTENDED_BYTE_16 W = 0x%02x\n", 0xff & regs[R_EB16]);
+- tda_reg("EXTENDED_BYTE_17 W = 0x%02x\n", 0xff & regs[R_EB17]);
+- tda_reg("EXTENDED_BYTE_18 = 0x%02x\n", 0xff & regs[R_EB18]);
+- tda_reg("EXTENDED_BYTE_19 W = 0x%02x\n", 0xff & regs[R_EB19]);
+- tda_reg("EXTENDED_BYTE_20 W = 0x%02x\n", 0xff & regs[R_EB20]);
+- tda_reg("EXTENDED_BYTE_21 = 0x%02x\n", 0xff & regs[R_EB21]);
+- tda_reg("EXTENDED_BYTE_22 = 0x%02x\n", 0xff & regs[R_EB22]);
+- tda_reg("EXTENDED_BYTE_23 = 0x%02x\n", 0xff & regs[R_EB23]);
-}
--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;
+-int tda18271_read_regs(struct dvb_frontend *fe)
+-{
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+- unsigned char buf = 0x00;
+- int ret;
+- struct i2c_msg msg[] = {
+- { .addr = priv->i2c_addr, .flags = 0,
+- .buf = &buf, .len = 1 },
+- { .addr = priv->i2c_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);
+-
+- tda18271_i2c_gate_ctrl(fe, 0);
+-
+- if (ret != 2)
+- tda_err("ERROR: i2c_transfer returned: %d\n", ret);
+-
+- if (tda18271_debug & DBG_REG)
+- tda18271_dump_regs(fe, 0);
+-
+- return (ret == 2 ? 0 : ret);
+-}
+-
+-int tda18271_read_extended(struct dvb_frontend *fe)
+-{
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+- unsigned char regdump[TDA18271_NUM_REGS];
+- unsigned char buf = 0x00;
+- int ret, i;
+- struct i2c_msg msg[] = {
+- { .addr = priv->i2c_addr, .flags = 0,
+- .buf = &buf, .len = 1 },
+- { .addr = priv->i2c_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);
+-
+- tda18271_i2c_gate_ctrl(fe, 0);
+-
+- if (ret != 2)
+- tda_err("ERROR: i2c_transfer returned: %d\n", ret);
+-
+- for (i = 0; i < TDA18271_NUM_REGS; i++) {
+- /* don't update write-only registers */
+- if ((i != R_EB9) &&
+- (i != R_EB16) &&
+- (i != R_EB17) &&
+- (i != R_EB19) &&
+- (i != R_EB20))
+- regs[i] = regdump[i];
- }
-
- if (m >= (1 << MINORBITS)) {
- idr_remove(&_minor_idr, m);
-@@ -991,7 +992,7 @@ static struct block_device_operations dm_blk_dops;
- static struct mapped_device *alloc_dev(int minor)
- {
- int r;
-- struct mapped_device *md = kmalloc(sizeof(*md), GFP_KERNEL);
-+ struct mapped_device *md = kzalloc(sizeof(*md), GFP_KERNEL);
- void *old_md;
-
- if (!md) {
-@@ -1004,13 +1005,12 @@ static struct mapped_device *alloc_dev(int minor)
-
- /* get a minor number for the dev */
- if (minor == DM_ANY_MINOR)
-- r = next_free_minor(md, &minor);
-+ r = next_free_minor(&minor);
- else
-- r = specific_minor(md, minor);
-+ r = specific_minor(minor);
- if (r < 0)
- goto bad_minor;
-
-- memset(md, 0, sizeof(*md));
- init_rwsem(&md->io_lock);
- mutex_init(&md->suspend_lock);
- spin_lock_init(&md->pushback_lock);
-diff --git a/drivers/md/dm.h b/drivers/md/dm.h
-index b4584a3..8c03b63 100644
---- a/drivers/md/dm.h
-+++ b/drivers/md/dm.h
-@@ -16,67 +16,6 @@
- #include <linux/blkdev.h>
- #include <linux/hdreg.h>
-
--#define DM_NAME "device-mapper"
-
--#define DMERR(f, arg...) \
-- printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
--#define DMERR_LIMIT(f, arg...) \
-- do { \
-- if (printk_ratelimit()) \
-- printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " \
-- f "\n", ## arg); \
-- } while (0)
+- if (tda18271_debug & DBG_REG)
+- tda18271_dump_regs(fe, 1);
-
--#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)
+- return (ret == 2 ? 0 : ret);
+-}
-
--#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)
+-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,
+- .buf = buf, .len = len + 1 };
+- int i, ret;
-
--#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
+- BUG_ON((len == 0) || (idx + len > sizeof(buf)));
-
--#define DMEMIT(x...) sz += ((sz >= maxlen) ? \
-- 0 : scnprintf(result + sz, maxlen - sz, x))
+- buf[0] = idx;
+- for (i = 1; i <= len; i++)
+- buf[i] = regs[idx - 1 + i];
-
--#define SECTOR_SHIFT 9
+- tda18271_i2c_gate_ctrl(fe, 1);
-
--/*
-- * Definitions of return values from target end_io function.
-- */
--#define DM_ENDIO_INCOMPLETE 1
--#define DM_ENDIO_REQUEUE 2
+- /* write registers */
+- ret = i2c_transfer(priv->i2c_adap, &msg, 1);
-
--/*
-- * 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
+- tda18271_i2c_gate_ctrl(fe, 0);
-
- /*
- * 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))
+- if (ret != 1)
+- tda_err("ERROR: i2c_transfer returned: %d\n", ret);
-
--#define dm_sector_div_up(n, sz) ( \
--{ \
-- sector_t _r = ((n) + (sz) - 1); \
-- sector_div(_r, (sz)); \
-- _r; \
--} \
--)
+- return (ret == 1 ? 0 : ret);
+-}
+-
+-/*---------------------------------------------------------------------*/
+-
+-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);
+-
+- /* initialize registers */
+- switch (priv->id) {
+- case TDA18271HDC1:
+- regs[R_ID] = 0x83;
+- break;
+- case TDA18271HDC2:
+- regs[R_ID] = 0x84;
+- break;
+- };
+-
+- regs[R_TM] = 0x08;
+- regs[R_PL] = 0x80;
+- regs[R_EP1] = 0xc6;
+- regs[R_EP2] = 0xdf;
+- regs[R_EP3] = 0x16;
+- regs[R_EP4] = 0x60;
+- regs[R_EP5] = 0x80;
+- regs[R_CPD] = 0x80;
+- regs[R_CD1] = 0x00;
+- regs[R_CD2] = 0x00;
+- regs[R_CD3] = 0x00;
+- regs[R_MPD] = 0x00;
+- regs[R_MD1] = 0x00;
+- regs[R_MD2] = 0x00;
+- regs[R_MD3] = 0x00;
+-
+- switch (priv->id) {
+- case TDA18271HDC1:
+- regs[R_EB1] = 0xff;
+- break;
+- case TDA18271HDC2:
+- regs[R_EB1] = 0xfc;
+- break;
+- };
+-
+- regs[R_EB2] = 0x01;
+- regs[R_EB3] = 0x84;
+- regs[R_EB4] = 0x41;
+- regs[R_EB5] = 0x01;
+- regs[R_EB6] = 0x84;
+- regs[R_EB7] = 0x40;
+- regs[R_EB8] = 0x07;
+- regs[R_EB9] = 0x00;
+- regs[R_EB10] = 0x00;
+- regs[R_EB11] = 0x96;
+-
+- switch (priv->id) {
+- case TDA18271HDC1:
+- regs[R_EB12] = 0x0f;
+- break;
+- case TDA18271HDC2:
+- regs[R_EB12] = 0x33;
+- break;
+- };
+-
+- regs[R_EB13] = 0xc1;
+- regs[R_EB14] = 0x00;
+- regs[R_EB15] = 0x8f;
+- regs[R_EB16] = 0x00;
+- regs[R_EB17] = 0x00;
+-
+- switch (priv->id) {
+- case TDA18271HDC1:
+- regs[R_EB18] = 0x00;
+- break;
+- case TDA18271HDC2:
+- regs[R_EB18] = 0x8c;
+- break;
+- };
+-
+- regs[R_EB19] = 0x00;
+- regs[R_EB20] = 0x20;
+-
+- switch (priv->id) {
+- case TDA18271HDC1:
+- regs[R_EB21] = 0x33;
+- break;
+- case TDA18271HDC2:
+- regs[R_EB21] = 0xb3;
+- break;
+- };
+-
+- regs[R_EB22] = 0x48;
+- regs[R_EB23] = 0xb0;
+-
+- tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
+-
+- /* setup agc1 gain */
+- regs[R_EB17] = 0x00;
+- tda18271_write_regs(fe, R_EB17, 1);
+- regs[R_EB17] = 0x03;
+- tda18271_write_regs(fe, R_EB17, 1);
+- regs[R_EB17] = 0x43;
+- tda18271_write_regs(fe, R_EB17, 1);
+- regs[R_EB17] = 0x4c;
+- tda18271_write_regs(fe, R_EB17, 1);
+-
+- /* setup agc2 gain */
+- if ((priv->id) == TDA18271HDC1) {
+- regs[R_EB20] = 0xa0;
+- tda18271_write_regs(fe, R_EB20, 1);
+- regs[R_EB20] = 0xa7;
+- tda18271_write_regs(fe, R_EB20, 1);
+- regs[R_EB20] = 0xe7;
+- tda18271_write_regs(fe, R_EB20, 1);
+- regs[R_EB20] = 0xec;
+- tda18271_write_regs(fe, R_EB20, 1);
+- }
+-
+- /* image rejection calibration */
+-
+- /* low-band */
+- regs[R_EP3] = 0x1f;
+- regs[R_EP4] = 0x66;
+- regs[R_EP5] = 0x81;
+- regs[R_CPD] = 0xcc;
+- regs[R_CD1] = 0x6c;
+- regs[R_CD2] = 0x00;
+- regs[R_CD3] = 0x00;
+- regs[R_MPD] = 0xcd;
+- regs[R_MD1] = 0x77;
+- 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;
+- };
+-
+- if ((priv->id) == TDA18271HDC2) {
+- /* main pll cp source on */
+- regs[R_EB4] = 0x61;
+- tda18271_write_regs(fe, R_EB4, 1);
+- msleep(1);
+-
+- /* main pll cp source off */
+- regs[R_EB4] = 0x41;
+- tda18271_write_regs(fe, R_EB4, 1);
+- }
+-
+- msleep(5); /* pll locking */
+-
+- /* launch detector */
+- tda18271_write_regs(fe, R_EP1, 1);
+- msleep(5); /* wanted low measurement */
+-
+- regs[R_EP5] = 0x85;
+- regs[R_CPD] = 0xcb;
+- regs[R_CD1] = 0x66;
+- regs[R_CD2] = 0x70;
+-
+- tda18271_write_regs(fe, R_EP3, 7);
+- msleep(5); /* pll locking */
+-
+- /* launch optimization algorithm */
+- tda18271_write_regs(fe, R_EP2, 1);
+- msleep(30); /* image low optimization completion */
+-
+- /* mid-band */
+- regs[R_EP5] = 0x82;
+- regs[R_CPD] = 0xa8;
+- regs[R_CD2] = 0x00;
+- regs[R_MPD] = 0xa9;
+- regs[R_MD1] = 0x73;
+- regs[R_MD2] = 0x1a;
+-
+- tda18271_write_regs(fe, R_EP3, 11);
+- msleep(5); /* pll locking */
+-
+- tda18271_write_regs(fe, R_EP1, 1);
+- msleep(5); /* wanted mid measurement */
+-
+- regs[R_EP5] = 0x86;
+- regs[R_CPD] = 0xa8;
+- regs[R_CD1] = 0x66;
+- regs[R_CD2] = 0xa0;
+-
+- tda18271_write_regs(fe, R_EP3, 7);
+- msleep(5); /* pll locking */
+-
+- /* launch optimization algorithm */
+- tda18271_write_regs(fe, R_EP2, 1);
+- msleep(30); /* image mid optimization completion */
+-
+- /* high-band */
+- regs[R_EP5] = 0x83;
+- regs[R_CPD] = 0x98;
+- regs[R_CD1] = 0x65;
+- regs[R_CD2] = 0x00;
+- regs[R_MPD] = 0x99;
+- regs[R_MD1] = 0x71;
+- regs[R_MD2] = 0xcd;
+-
+- tda18271_write_regs(fe, R_EP3, 11);
+- msleep(5); /* pll locking */
+-
+- /* launch detector */
+- tda18271_write_regs(fe, R_EP1, 1);
+- msleep(5); /* wanted high measurement */
+-
+- regs[R_EP5] = 0x87;
+- regs[R_CD1] = 0x65;
+- regs[R_CD2] = 0x50;
+-
+- tda18271_write_regs(fe, R_EP3, 7);
+- msleep(5); /* pll locking */
+-
+- /* launch optimization algorithm */
+- tda18271_write_regs(fe, R_EP2, 1);
+- msleep(30); /* image high optimization completion */
+-
+- /* return to normal mode */
+- regs[R_EP4] = 0x64;
+- tda18271_write_regs(fe, R_EP4, 1);
+-
+- /* synchronize */
+- tda18271_write_regs(fe, R_EP1, 1);
+-
+- return 0;
+-}
+-
+-/*---------------------------------------------------------------------*/
-
-/*
-- * ceiling(n / size) * size
+- * Standby modes, EP3 [7:5]
+- *
+- * | SM || SM_LT || SM_XT || mode description
+- * |=====\\=======\\=======\\===================================
+- * | 0 || 0 || 0 || normal mode
+- * |-----||-------||-------||-----------------------------------
+- * | || || || standby mode w/ slave tuner output
+- * | 1 || 0 || 0 || & loop thru & xtal oscillator on
+- * |-----||-------||-------||-----------------------------------
+- * | 1 || 1 || 0 || standby mode w/ xtal oscillator on
+- * |-----||-------||-------||-----------------------------------
+- * | 1 || 1 || 1 || power off
+- *
- */
--#define dm_round_up(n, sz) (dm_div_up((n), (sz)) * (sz))
-
--static inline sector_t to_sector(unsigned long n)
+-int tda18271_set_standby_mode(struct dvb_frontend *fe,
+- int sm, int sm_lt, int sm_xt)
-{
-- return (n >> 9);
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+-
+- tda_dbg("sm = %d, sm_lt = %d, sm_xt = %d\n", sm, sm_lt, sm_xt);
+-
+- regs[R_EP3] &= ~0xe0; /* clear sm, sm_lt, sm_xt */
+- regs[R_EP3] |= sm ? (1 << 7) : 0 |
+- sm_lt ? (1 << 6) : 0 |
+- sm_xt ? (1 << 5) : 0;
+-
+- tda18271_write_regs(fe, R_EP3, 1);
+-
+- return 0;
-}
-
--static inline unsigned long to_bytes(sector_t n)
+-/*---------------------------------------------------------------------*/
+-
+-int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq)
-{
-- return (n << 9);
+- /* sets main post divider & divider bytes, but does not write them */
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+- u8 d, pd;
+- u32 div;
+-
+- int ret = tda18271_lookup_pll_map(fe, MAIN_PLL, &freq, &pd, &d);
+- if (ret < 0)
+- goto fail;
+-
+- regs[R_MPD] = (0x77 & pd);
+-
+- switch (priv->mode) {
+- case TDA18271_ANALOG:
+- regs[R_MPD] &= ~0x08;
+- break;
+- case TDA18271_DIGITAL:
+- regs[R_MPD] |= 0x08;
+- break;
+- }
+-
+- div = ((d * (freq / 1000)) << 7) / 125;
+-
+- regs[R_MD1] = 0x7f & (div >> 16);
+- regs[R_MD2] = 0xff & (div >> 8);
+- regs[R_MD3] = 0xff & div;
+-fail:
+- return ret;
-}
-
- 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
+-int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq)
+-{
+- /* sets cal post divider & divider bytes, but does not write them */
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+- u8 d, pd;
+- u32 div;
+-
+- int ret = tda18271_lookup_pll_map(fe, CAL_PLL, &freq, &pd, &d);
+- if (ret < 0)
+- goto fail;
+-
+- regs[R_CPD] = pd;
+-
+- div = ((d * (freq / 1000)) << 7) / 125;
+-
+- regs[R_CD1] = 0x7f & (div >> 16);
+- regs[R_CD2] = 0xff & (div >> 8);
+- regs[R_CD3] = 0xff & div;
+-fail:
+- return ret;
+-}
+-
+-/*---------------------------------------------------------------------*/
+-
+-int tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq)
+-{
+- /* sets bp filter bits, but does not write them */
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+- u8 val;
+-
+- int ret = tda18271_lookup_map(fe, BP_FILTER, freq, &val);
+- if (ret < 0)
+- goto fail;
+-
+- regs[R_EP1] &= ~0x07; /* clear bp filter bits */
+- regs[R_EP1] |= (0x07 & val);
+-fail:
+- return ret;
+-}
+-
+-int tda18271_calc_km(struct dvb_frontend *fe, u32 *freq)
+-{
+- /* sets K & M bits, but does not write them */
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+- u8 val;
+-
+- int ret = tda18271_lookup_map(fe, RF_CAL_KMCO, freq, &val);
+- if (ret < 0)
+- goto fail;
+-
+- regs[R_EB13] &= ~0x7c; /* clear k & m bits */
+- regs[R_EB13] |= (0x7c & val);
+-fail:
+- return ret;
+-}
+-
+-int tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq)
+-{
+- /* sets rf band bits, but does not write them */
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+- u8 val;
+-
+- int ret = tda18271_lookup_map(fe, RF_BAND, freq, &val);
+- if (ret < 0)
+- goto fail;
+-
+- regs[R_EP2] &= ~0xe0; /* clear rf band bits */
+- regs[R_EP2] |= (0xe0 & (val << 5));
+-fail:
+- return ret;
+-}
+-
+-int tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq)
+-{
+- /* sets gain taper bits, but does not write them */
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+- u8 val;
+-
+- int ret = tda18271_lookup_map(fe, GAIN_TAPER, freq, &val);
+- if (ret < 0)
+- goto fail;
+-
+- regs[R_EP2] &= ~0x1f; /* clear gain taper bits */
+- regs[R_EP2] |= (0x1f & val);
+-fail:
+- return ret;
+-}
+-
+-int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq)
+-{
+- /* sets IR Meas bits, but does not write them */
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+- u8 val;
+-
+- int ret = tda18271_lookup_map(fe, IR_MEASURE, freq, &val);
+- if (ret < 0)
+- goto fail;
+-
+- regs[R_EP5] &= ~0x07;
+- regs[R_EP5] |= (0x07 & val);
+-fail:
+- return ret;
+-}
+-
+-int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq)
+-{
+- /* sets rf cal byte (RFC_Cprog), but does not write it */
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+- u8 val;
+-
+- tda18271_lookup_map(fe, RF_CAL, freq, &val);
+-
+- regs[R_EB14] = val;
+-
+- return 0;
+-}
+-
+-/*
+- * Overrides for Emacs so that we follow Linus's tabbing style.
+- * ---------------------------------------------------------------------------
+- * Local variables:
+- * c-basic-offset: 8
+- * End:
+- */
+diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c
deleted file mode 100644
-index e76b52a..0000000
---- a/drivers/md/kcopyd.c
+index dfe72aa..0000000
+--- a/drivers/media/dvb/frontends/tda18271-fe.c
+++ /dev/null
-@@ -1,708 +0,0 @@
+@@ -1,1225 +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.
-- */
+- tda18271-fe.c - driver for the Philips / NXP TDA18271 silicon tuner
-
--#include <asm/types.h>
--#include <asm/atomic.h>
+- Copyright (C) 2007, 2008 Michael Krufky <mkrufky at linuxtv.org>
-
--#include <linux/blkdev.h>
--#include <linux/fs.h>
--#include <linux/init.h>
--#include <linux/list.h>
--#include <linux/mempool.h>
--#include <linux/module.h>
--#include <linux/pagemap.h>
--#include <linux/slab.h>
--#include <linux/vmalloc.h>
--#include <linux/workqueue.h>
--#include <linux/mutex.h>
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the 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 "kcopyd.h"
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
-
--static struct workqueue_struct *_kcopyd_wq;
--static struct work_struct _kcopyd_work;
+- You 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.
+-*/
-
--static void wake(void)
+-#include <linux/delay.h>
+-#include <linux/videodev2.h>
+-#include "tda18271-priv.h"
+-
+-int tda18271_debug;
+-module_param_named(debug, tda18271_debug, int, 0644);
+-MODULE_PARM_DESC(debug, "set debug level "
+- "(info=1, map=2, reg=4, adv=8, cal=16 (or-able))");
+-
+-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 int tda18271_ir_cal_init(struct dvb_frontend *fe)
-{
-- queue_work(_kcopyd_wq, &_kcopyd_work);
+- 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;
+-}
+-
+-/* ------------------------------------------------------------------ */
+-
+-static int tda18271_channel_configuration(struct dvb_frontend *fe,
+- u32 ifc, u32 freq, u32 bw, u8 std,
+- int radio)
+-{
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+- u32 N;
+-
+- /* update TV broadcast parameters */
+-
+- /* set standard */
+- regs[R_EP3] &= ~0x1f; /* clear std bits */
+- regs[R_EP3] |= std;
+-
+- /* set cal mode to normal */
+- regs[R_EP4] &= ~0x03;
+-
+- /* update IF output level & IF notch frequency */
+- 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; /* IF level = 1 */
+- regs[R_MPD] |= 0x80; /* IF notch = 1 */
+- break;
+- }
+-
+- if (radio)
+- regs[R_EP4] |= 0x80;
+- else
+- regs[R_EP4] &= ~0x80;
+-
+- /* update RF_TOP / IF_TOP */
+- 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);
+-
+- /* --------------------------------------------------------------- */
+-
+- /* disable Power Level Indicator */
+- regs[R_EP1] |= 0x40;
+-
+- /* frequency dependent parameters */
+-
+- tda18271_calc_ir_measure(fe, &freq);
+-
+- tda18271_calc_bp_filter(fe, &freq);
+-
+- tda18271_calc_rf_band(fe, &freq);
+-
+- tda18271_calc_gain_taper(fe, &freq);
+-
+- /* --------------------------------------------------------------- */
+-
+- /* dual tuner and agc1 extra configuration */
+-
+- /* main vco when Master, cal vco when slave */
+- regs[R_EB1] |= 0x04; /* FIXME: assumes master */
+-
+- /* agc1 always active */
+- regs[R_EB1] &= ~0x02;
+-
+- /* agc1 has priority on agc2 */
+- regs[R_EB1] &= ~0x01;
+-
+- tda18271_write_regs(fe, R_EB1, 1);
+-
+- /* --------------------------------------------------------------- */
+-
+- N = freq + ifc;
+-
+- /* FIXME: assumes master */
+- tda18271_calc_main_pll(fe, N);
+- tda18271_write_regs(fe, R_MPD, 4);
+-
+- tda18271_write_regs(fe, R_TM, 7);
+-
+- /* main pll charge pump source */
+- regs[R_EB4] |= 0x20;
+- tda18271_write_regs(fe, R_EB4, 1);
+-
+- msleep(1);
+-
+- /* normal operation for the main pll */
+- regs[R_EB4] &= ~0x20;
+- tda18271_write_regs(fe, R_EB4, 1);
+-
+- msleep(5);
+-
+- return 0;
+-}
+-
+-static int tda18271_read_thermometer(struct dvb_frontend *fe)
+-{
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+- int tm;
+-
+- /* switch thermometer on */
+- regs[R_TM] |= 0x10;
+- tda18271_write_regs(fe, R_TM, 1);
+-
+- /* read thermometer info */
+- tda18271_read_regs(fe);
+-
+- if ((((regs[R_TM] & 0x0f) == 0x00) && ((regs[R_TM] & 0x20) == 0x20)) ||
+- (((regs[R_TM] & 0x0f) == 0x08) && ((regs[R_TM] & 0x20) == 0x00))) {
+-
+- if ((regs[R_TM] & 0x20) == 0x20)
+- regs[R_TM] &= ~0x20;
+- else
+- regs[R_TM] |= 0x20;
+-
+- tda18271_write_regs(fe, R_TM, 1);
+-
+- msleep(10); /* temperature sensing */
+-
+- /* read thermometer info */
+- tda18271_read_regs(fe);
+- }
+-
+- tm = tda18271_lookup_thermometer(fe);
+-
+- /* switch thermometer off */
+- regs[R_TM] &= ~0x10;
+- tda18271_write_regs(fe, R_TM, 1);
+-
+- /* set CAL mode to normal */
+- regs[R_EP4] &= ~0x03;
+- tda18271_write_regs(fe, R_EP4, 1);
+-
+- return tm;
+-}
+-
+-static int tda18271_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;
+- unsigned char *regs = priv->tda18271_regs;
+- int tm_current, rfcal_comp, approx, i;
+- u8 dc_over_dt, rf_tab;
+-
+- /* power up */
+- tda18271_set_standby_mode(fe, 0, 0, 0);
+-
+- /* read die current temperature */
+- tm_current = tda18271_read_thermometer(fe);
+-
+- /* frequency dependent parameters */
+-
+- tda18271_calc_rf_cal(fe, &freq);
+- rf_tab = regs[R_EB14];
+-
+- i = tda18271_lookup_rf_band(fe, &freq, NULL);
+- if (i < 0)
+- return -EINVAL;
+-
+- if ((0 == map[i].rf3) || (freq / 1000 < map[i].rf2)) {
+- approx = map[i].rf_a1 *
+- (freq / 1000 - map[i].rf1) + map[i].rf_b1 + rf_tab;
+- } else {
+- approx = map[i].rf_a2 *
+- (freq / 1000 - map[i].rf2) + map[i].rf_b2 + rf_tab;
+- }
+-
+- if (approx < 0)
+- approx = 0;
+- if (approx > 255)
+- approx = 255;
+-
+- tda18271_lookup_map(fe, RF_CAL_DC_OVER_DT, &freq, &dc_over_dt);
+-
+- /* calculate temperature compensation */
+- rfcal_comp = dc_over_dt * (tm_current - priv->tm_rfcal);
+-
+- regs[R_EB14] = approx + rfcal_comp;
+- tda18271_write_regs(fe, R_EB14, 1);
+-
+- return 0;
+-}
+-
+-static int tda18271_por(struct dvb_frontend *fe)
+-{
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+-
+- /* power up detector 1 */
+- regs[R_EB12] &= ~0x20;
+- tda18271_write_regs(fe, R_EB12, 1);
+-
+- regs[R_EB18] &= ~0x80; /* turn agc1 loop on */
+- regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */
+- tda18271_write_regs(fe, R_EB18, 1);
+-
+- regs[R_EB21] |= 0x03; /* set agc2_gain to -6 dB */
+-
+- /* POR mode */
+- tda18271_set_standby_mode(fe, 1, 0, 0);
+-
+- /* disable 1.5 MHz low pass filter */
+- regs[R_EB23] &= ~0x04; /* forcelp_fc2_en = 0 */
+- regs[R_EB23] &= ~0x02; /* XXX: lp_fc[2] = 0 */
+- tda18271_write_regs(fe, R_EB21, 3);
+-
+- return 0;
+-}
+-
+-static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq)
+-{
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+- u32 N;
+-
+- /* set CAL mode to normal */
+- regs[R_EP4] &= ~0x03;
+- tda18271_write_regs(fe, R_EP4, 1);
+-
+- /* switch off agc1 */
+- regs[R_EP3] |= 0x40; /* sm_lt = 1 */
+-
+- regs[R_EB18] |= 0x03; /* set agc1_gain to 15 dB */
+- tda18271_write_regs(fe, R_EB18, 1);
+-
+- /* frequency dependent parameters */
+-
+- tda18271_calc_bp_filter(fe, &freq);
+- tda18271_calc_gain_taper(fe, &freq);
+- tda18271_calc_rf_band(fe, &freq);
+- tda18271_calc_km(fe, &freq);
+-
+- tda18271_write_regs(fe, R_EP1, 3);
+- tda18271_write_regs(fe, R_EB13, 1);
+-
+- /* main pll charge pump source */
+- regs[R_EB4] |= 0x20;
+- tda18271_write_regs(fe, R_EB4, 1);
+-
+- /* cal pll charge pump source */
+- regs[R_EB7] |= 0x20;
+- tda18271_write_regs(fe, R_EB7, 1);
+-
+- /* force dcdc converter to 0 V */
+- regs[R_EB14] = 0x00;
+- tda18271_write_regs(fe, R_EB14, 1);
+-
+- /* disable plls lock */
+- regs[R_EB20] &= ~0x20;
+- tda18271_write_regs(fe, R_EB20, 1);
+-
+- /* set CAL mode to RF tracking filter calibration */
+- regs[R_EP4] |= 0x03;
+- tda18271_write_regs(fe, R_EP4, 2);
+-
+- /* --------------------------------------------------------------- */
+-
+- /* set the internal calibration signal */
+- N = freq;
+-
+- tda18271_calc_main_pll(fe, N);
+- tda18271_write_regs(fe, R_MPD, 4);
+-
+- /* downconvert internal calibration */
+- N += 1000000;
+-
+- tda18271_calc_main_pll(fe, N);
+- tda18271_write_regs(fe, R_MPD, 4);
+-
+- msleep(5);
+-
+- tda18271_write_regs(fe, R_EP2, 1);
+- tda18271_write_regs(fe, R_EP1, 1);
+- tda18271_write_regs(fe, R_EP2, 1);
+- tda18271_write_regs(fe, R_EP1, 1);
+-
+- /* --------------------------------------------------------------- */
+-
+- /* normal operation for the main pll */
+- regs[R_EB4] &= ~0x20;
+- tda18271_write_regs(fe, R_EB4, 1);
+-
+- /* normal operation for the cal pll */
+- regs[R_EB7] &= ~0x20;
+- tda18271_write_regs(fe, R_EB7, 1);
+-
+- msleep(5); /* plls locking */
+-
+- /* launch the rf tracking filters calibration */
+- regs[R_EB20] |= 0x20;
+- tda18271_write_regs(fe, R_EB20, 1);
+-
+- msleep(60); /* calibration */
+-
+- /* --------------------------------------------------------------- */
+-
+- /* set CAL mode to normal */
+- regs[R_EP4] &= ~0x03;
+-
+- /* switch on agc1 */
+- regs[R_EP3] &= ~0x40; /* sm_lt = 0 */
+-
+- regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */
+- tda18271_write_regs(fe, R_EB18, 1);
+-
+- tda18271_write_regs(fe, R_EP3, 2);
+-
+- /* synchronization */
+- tda18271_write_regs(fe, R_EP1, 1);
+-
+- /* get calibration result */
+- tda18271_read_extended(fe);
+-
+- return regs[R_EB14];
+-}
+-
+-static int tda18271_powerscan(struct dvb_frontend *fe,
+- u32 *freq_in, u32 *freq_out)
+-{
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+- int sgn, bcal, count, wait;
+- u8 cid_target;
+- u16 count_limit;
+- u32 freq;
+-
+- freq = *freq_in;
+-
+- tda18271_calc_rf_band(fe, &freq);
+- tda18271_calc_rf_cal(fe, &freq);
+- tda18271_calc_gain_taper(fe, &freq);
+- tda18271_lookup_cid_target(fe, &freq, &cid_target, &count_limit);
+-
+- tda18271_write_regs(fe, R_EP2, 1);
+- tda18271_write_regs(fe, R_EB14, 1);
+-
+- /* downconvert frequency */
+- freq += 1000000;
+-
+- tda18271_calc_main_pll(fe, freq);
+- tda18271_write_regs(fe, R_MPD, 4);
+-
+- msleep(5); /* pll locking */
+-
+- /* detection mode */
+- regs[R_EP4] &= ~0x03;
+- regs[R_EP4] |= 0x01;
+- tda18271_write_regs(fe, R_EP4, 1);
+-
+- /* launch power detection measurement */
+- tda18271_write_regs(fe, R_EP2, 1);
+-
+- /* read power detection info, stored in EB10 */
+- tda18271_read_extended(fe);
+-
+- /* algorithm initialization */
+- sgn = 1;
+- *freq_out = *freq_in;
+- bcal = 0;
+- count = 0;
+- wait = false;
+-
+- while ((regs[R_EB10] & 0x3f) < cid_target) {
+- /* downconvert updated freq to 1 MHz */
+- freq = *freq_in + (sgn * count) + 1000000;
+-
+- tda18271_calc_main_pll(fe, freq);
+- tda18271_write_regs(fe, R_MPD, 4);
+-
+- if (wait) {
+- msleep(5); /* pll locking */
+- wait = false;
+- } else
+- udelay(100); /* pll locking */
+-
+- /* launch power detection measurement */
+- tda18271_write_regs(fe, R_EP2, 1);
+-
+- /* read power detection info, stored in EB10 */
+- tda18271_read_extended(fe);
+-
+- count += 200;
+-
+- if (count < count_limit)
+- continue;
+-
+- if (sgn <= 0)
+- break;
+-
+- sgn = -1 * sgn;
+- count = 200;
+- wait = true;
+- }
+-
+- if ((regs[R_EB10] & 0x3f) >= cid_target) {
+- bcal = 1;
+- *freq_out = freq - 1000000;
+- } else
+- bcal = 0;
+-
+- tda_cal("bcal = %d, freq_in = %d, freq_out = %d (freq = %d)\n",
+- bcal, *freq_in, *freq_out, freq);
+-
+- return bcal;
+-}
+-
+-static int tda18271_powerscan_init(struct dvb_frontend *fe)
+-{
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+-
+- /* set standard to digital */
+- regs[R_EP3] &= ~0x1f; /* clear std bits */
+- regs[R_EP3] |= 0x12;
+-
+- /* set cal mode to normal */
+- regs[R_EP4] &= ~0x03;
+-
+- /* update IF output level & IF notch frequency */
+- regs[R_EP4] &= ~0x1c; /* clear if level bits */
+-
+- tda18271_write_regs(fe, R_EP3, 2);
+-
+- regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */
+- tda18271_write_regs(fe, R_EB18, 1);
+-
+- regs[R_EB21] &= ~0x03; /* set agc2_gain to -15 dB */
+-
+- /* 1.5 MHz low pass filter */
+- regs[R_EB23] |= 0x04; /* forcelp_fc2_en = 1 */
+- regs[R_EB23] |= 0x02; /* lp_fc[2] = 1 */
+-
+- tda18271_write_regs(fe, R_EB21, 3);
+-
+- return 0;
+-}
+-
+-static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq)
+-{
+- struct tda18271_priv *priv = fe->tuner_priv;
+- struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state;
+- unsigned char *regs = priv->tda18271_regs;
+- int bcal, rf, i;
+-#define RF1 0
+-#define RF2 1
+-#define RF3 2
+- u32 rf_default[3];
+- u32 rf_freq[3];
+- u8 prog_cal[3];
+- u8 prog_tab[3];
+-
+- i = tda18271_lookup_rf_band(fe, &freq, NULL);
+-
+- if (i < 0)
+- return i;
+-
+- rf_default[RF1] = 1000 * map[i].rf1_def;
+- rf_default[RF2] = 1000 * map[i].rf2_def;
+- rf_default[RF3] = 1000 * map[i].rf3_def;
+-
+- for (rf = RF1; rf <= RF3; rf++) {
+- if (0 == rf_default[rf])
+- return 0;
+- tda_cal("freq = %d, rf = %d\n", freq, rf);
+-
+- /* look for optimized calibration frequency */
+- bcal = tda18271_powerscan(fe, &rf_default[rf], &rf_freq[rf]);
+-
+- tda18271_calc_rf_cal(fe, &rf_freq[rf]);
+- prog_tab[rf] = regs[R_EB14];
+-
+- if (1 == bcal)
+- prog_cal[rf] = tda18271_calibrate_rf(fe, rf_freq[rf]);
+- else
+- prog_cal[rf] = prog_tab[rf];
+-
+- switch (rf) {
+- case RF1:
+- map[i].rf_a1 = 0;
+- map[i].rf_b1 = prog_cal[RF1] - prog_tab[RF1];
+- map[i].rf1 = rf_freq[RF1] / 1000;
+- break;
+- case RF2:
+- map[i].rf_a1 = (prog_cal[RF2] - prog_tab[RF2] -
+- prog_cal[RF1] + prog_tab[RF1]) /
+- ((rf_freq[RF2] - rf_freq[RF1]) / 1000);
+- map[i].rf2 = rf_freq[RF2] / 1000;
+- break;
+- case RF3:
+- map[i].rf_a2 = (prog_cal[RF3] - prog_tab[RF3] -
+- prog_cal[RF2] + prog_tab[RF2]) /
+- ((rf_freq[RF3] - rf_freq[RF2]) / 1000);
+- map[i].rf_b2 = prog_cal[RF2] - prog_tab[RF2];
+- map[i].rf3 = rf_freq[RF3] / 1000;
+- break;
+- default:
+- BUG();
+- }
+- }
+-
+- return 0;
+-}
+-
+-static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe)
+-{
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned int i;
+-
+- tda_info("tda18271: performing RF tracking filter calibration\n");
+-
+- /* wait for die temperature stabilization */
+- msleep(200);
+-
+- tda18271_powerscan_init(fe);
+-
+- /* rf band calibration */
+- for (i = 0; priv->rf_cal_state[i].rfmax != 0; i++)
+- tda18271_rf_tracking_filters_init(fe, 1000 *
+- priv->rf_cal_state[i].rfmax);
+-
+- priv->tm_rfcal = tda18271_read_thermometer(fe);
+-
+- return 0;
+-}
+-
+-/* ------------------------------------------------------------------ */
+-
+-static int tda18271_rf_cal_init(struct dvb_frontend *fe)
+-{
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+-
+- /* test RF_CAL_OK to see if we need init */
+- if ((regs[R_EP1] & 0x10) == 0)
+- priv->cal_initialized = false;
+-
+- if (priv->cal_initialized)
+- return 0;
+-
+- tda18271_calc_rf_filter_curve(fe);
+-
+- tda18271_por(fe);
+-
+- tda_info("tda18271: RF tracking filter calibration complete\n");
+-
+- priv->cal_initialized = true;
+-
+- 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;
-}
-
--/*-----------------------------------------------------------------
-- * Each kcopyd client has its own little pool of preallocated
-- * pages for kcopyd io.
-- *---------------------------------------------------------------*/
--struct kcopyd_client {
-- struct list_head list;
+-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)
+-{
+- 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);
+-
+- regs[R_EB4] &= 0x07;
+- regs[R_EB4] |= 0x60;
+- tda18271_write_regs(fe, R_EB4, 1);
+-
+- regs[R_EB7] = 0x60;
+- tda18271_write_regs(fe, R_EB7, 1);
+-
+- regs[R_EB14] = 0x00;
+- tda18271_write_regs(fe, R_EB14, 1);
+-
+- regs[R_EB20] = 0xcc;
+- tda18271_write_regs(fe, R_EB20, 1);
+-
+- /* set cal mode to RF tracking filter calibration */
+- regs[R_EP4] |= 0x03;
+-
+- /* calculate cal pll */
+-
+- switch (priv->mode) {
+- case TDA18271_ANALOG:
+- N = freq - 1250000;
+- break;
+- case TDA18271_DIGITAL:
+- N = freq + bw / 2;
+- break;
+- }
+-
+- tda18271_calc_cal_pll(fe, N);
+-
+- /* calculate main pll */
+-
+- switch (priv->mode) {
+- case TDA18271_ANALOG:
+- N = freq - 250000;
+- break;
+- case TDA18271_DIGITAL:
+- N = freq + bw / 2 + 1000000;
+- break;
+- }
+-
+- tda18271_calc_main_pll(fe, N);
+-
+- tda18271_write_regs(fe, R_EP3, 11);
+- msleep(5); /* RF tracking filter calibration initialization */
+-
+- /* search for K,M,CO for RF calibration */
+- tda18271_calc_km(fe, &freq);
+- tda18271_write_regs(fe, R_EB13, 1);
+-
+- /* search for rf band */
+- tda18271_calc_rf_band(fe, &freq);
+-
+- /* search for gain taper */
+- tda18271_calc_gain_taper(fe, &freq);
+-
+- tda18271_write_regs(fe, R_EP2, 1);
+- tda18271_write_regs(fe, R_EP1, 1);
+- tda18271_write_regs(fe, R_EP2, 1);
+- tda18271_write_regs(fe, R_EP1, 1);
-
-- spinlock_t lock;
-- struct page_list *pages;
-- unsigned int nr_pages;
-- unsigned int nr_free_pages;
+- regs[R_EB4] &= 0x07;
+- regs[R_EB4] |= 0x40;
+- tda18271_write_regs(fe, R_EB4, 1);
-
-- struct dm_io_client *io_client;
+- regs[R_EB7] = 0x40;
+- tda18271_write_regs(fe, R_EB7, 1);
+- msleep(10);
-
-- wait_queue_head_t destroyq;
-- atomic_t nr_jobs;
--};
+- regs[R_EB20] = 0xec;
+- tda18271_write_regs(fe, R_EB20, 1);
+- msleep(60); /* RF tracking filter calibration completion */
-
--static struct page_list *alloc_pl(void)
--{
-- struct page_list *pl;
+- regs[R_EP4] &= ~0x03; /* set cal mode to normal */
+- tda18271_write_regs(fe, R_EP4, 1);
-
-- pl = kmalloc(sizeof(*pl), GFP_KERNEL);
-- if (!pl)
-- return NULL;
+- tda18271_write_regs(fe, R_EP1, 1);
-
-- pl->page = alloc_page(GFP_KERNEL);
-- if (!pl->page) {
-- kfree(pl);
-- return NULL;
+- /* RF tracking filter correction for VHF_Low band */
+- if (0 == tda18271_calc_rf_cal(fe, &freq))
+- tda18271_write_regs(fe, R_EB14, 1);
+-
+- /* Channel Configuration */
+-
+- 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);
-
-- return pl;
--}
+- regs[R_EP1] |= 0x40; /* set dis power level on */
-
--static void free_pl(struct page_list *pl)
--{
-- __free_page(pl->page);
-- kfree(pl);
--}
+- /* set standard */
+- regs[R_EP3] &= ~0x1f; /* clear std bits */
-
--static int kcopyd_get_pages(struct kcopyd_client *kc,
-- unsigned int nr, struct page_list **pages)
--{
-- struct page_list *pl;
+- /* see table 22 */
+- regs[R_EP3] |= std;
-
-- spin_lock(&kc->lock);
-- if (kc->nr_free_pages < nr) {
-- spin_unlock(&kc->lock);
-- return -ENOMEM;
-- }
+- regs[R_EP4] &= ~0x03; /* set cal mode to normal */
-
-- kc->nr_free_pages -= nr;
-- for (*pages = pl = kc->pages; --nr; pl = pl->next)
-- ;
+- 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;
+- }
-
-- kc->pages = pl->next;
-- pl->next = NULL;
+- if (radio)
+- regs[R_EP4] |= 0x80;
+- else
+- regs[R_EP4] &= ~0x80;
-
-- spin_unlock(&kc->lock);
+- /* image rejection validity */
+- tda18271_calc_ir_measure(fe, &freq);
-
-- return 0;
--}
+- /* calculate MAIN PLL */
+- N = freq + ifc;
-
--static void kcopyd_put_pages(struct kcopyd_client *kc, struct page_list *pl)
--{
-- struct page_list *cursor;
+- tda18271_calc_main_pll(fe, N);
-
-- spin_lock(&kc->lock);
-- for (cursor = pl; cursor->next; cursor = cursor->next)
-- kc->nr_free_pages++;
+- tda18271_write_regs(fe, R_TM, 15);
+- msleep(5);
+- mutex_unlock(&priv->lock);
-
-- kc->nr_free_pages++;
-- cursor->next = kc->pages;
-- kc->pages = pl;
-- spin_unlock(&kc->lock);
+- return 0;
-}
-
--/*
-- * These three functions resize the page pool.
-- */
--static void drop_pages(struct page_list *pl)
+-static inline int tda18271_tune(struct dvb_frontend *fe,
+- u32 ifc, u32 freq, u32 bw, u8 std, int radio)
-{
-- struct page_list *next;
+- struct tda18271_priv *priv = fe->tuner_priv;
+- int ret = -EINVAL;
-
-- while (pl) {
-- next = pl->next;
-- free_pl(pl);
-- pl = next;
+- switch (priv->id) {
+- case TDA18271HDC1:
+- ret = tda18271c1_tune(fe, ifc, freq, bw, std, radio);
+- break;
+- case TDA18271HDC2:
+- ret = tda18271c2_tune(fe, ifc, freq, bw, std, radio);
+- break;
- }
+- return ret;
-}
-
--static int client_alloc_pages(struct kcopyd_client *kc, unsigned int nr)
+-/* ------------------------------------------------------------------ */
+-
+-static int tda18271_set_params(struct dvb_frontend *fe,
+- struct dvb_frontend_parameters *params)
-{
-- unsigned int i;
-- struct page_list *pl = NULL, *next;
+- struct tda18271_priv *priv = fe->tuner_priv;
+- struct tda18271_std_map *std_map = &priv->std;
+- int ret;
+- u8 std;
+- u16 sgIF;
+- u32 bw, freq = params->frequency;
-
-- for (i = 0; i < nr; i++) {
-- next = alloc_pl();
-- if (!next) {
-- if (pl)
-- drop_pages(pl);
-- return -ENOMEM;
+- priv->mode = TDA18271_DIGITAL;
+-
+- if (fe->ops.info.type == FE_ATSC) {
+- 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;
+- break;
+- case QAM_64:
+- case QAM_256:
+- std = std_map->qam_6.std_bits;
+- sgIF = std_map->qam_6.if_freq;
+- break;
+- default:
+- tda_warn("modulation not set!\n");
+- return -EINVAL;
- }
-- next->next = pl;
-- pl = next;
+-#if 0
+- /* userspace request is already center adjusted */
+- freq += 1750000; /* Adjust to center (+1.75MHZ) */
+-#endif
+- bw = 6000000;
+- } else if (fe->ops.info.type == FE_OFDM) {
+- 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;
+- break;
+- case BANDWIDTH_7_MHZ:
+- bw = 7000000;
+- std = std_map->dvbt_7.std_bits;
+- sgIF = std_map->dvbt_7.if_freq;
+- break;
+- case BANDWIDTH_8_MHZ:
+- bw = 8000000;
+- std = std_map->dvbt_8.std_bits;
+- sgIF = std_map->dvbt_8.if_freq;
+- break;
+- default:
+- tda_warn("bandwidth not set!\n");
+- return -EINVAL;
+- }
+- } else {
+- tda_warn("modulation type not supported!\n");
+- return -EINVAL;
- }
-
-- kcopyd_put_pages(kc, pl);
-- kc->nr_pages += nr;
-- return 0;
+- /* When tuning digital, the analog demod must be tri-stated */
+- if (fe->ops.analog_ops.standby)
+- fe->ops.analog_ops.standby(fe);
+-
+- ret = tda18271_tune(fe, sgIF * 1000, freq, bw, std, 0);
+-
+- if (ret < 0)
+- goto fail;
+-
+- priv->frequency = freq;
+- priv->bandwidth = (fe->ops.info.type == FE_OFDM) ?
+- params->u.ofdm.bandwidth : 0;
+-fail:
+- return ret;
-}
-
--static void client_free_pages(struct kcopyd_client *kc)
+-static int tda18271_set_analog_params(struct dvb_frontend *fe,
+- struct analog_parameters *params)
-{
-- BUG_ON(kc->nr_free_pages != kc->nr_pages);
-- drop_pages(kc->pages);
-- kc->pages = NULL;
-- kc->nr_free_pages = kc->nr_pages = 0;
--}
+- struct tda18271_priv *priv = fe->tuner_priv;
+- struct tda18271_std_map *std_map = &priv->std;
+- char *mode;
+- int ret, radio = 0;
+- u8 std;
+- u16 sgIF;
+- u32 freq = params->frequency * 62500;
-
--/*-----------------------------------------------------------------
-- * 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;
+- priv->mode = TDA18271_ANALOG;
-
-- /*
-- * Error state of the job.
-- */
-- int read_err;
-- unsigned long write_err;
+- 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;
+- mode = "fm";
+- } else if (params->std & V4L2_STD_MN) {
+- std = std_map->atv_mn.std_bits;
+- sgIF = std_map->atv_mn.if_freq;
+- mode = "MN";
+- } else if (params->std & V4L2_STD_B) {
+- std = std_map->atv_b.std_bits;
+- sgIF = std_map->atv_b.if_freq;
+- mode = "B";
+- } else if (params->std & V4L2_STD_GH) {
+- std = std_map->atv_gh.std_bits;
+- sgIF = std_map->atv_gh.if_freq;
+- mode = "GH";
+- } else if (params->std & V4L2_STD_PAL_I) {
+- std = std_map->atv_i.std_bits;
+- sgIF = std_map->atv_i.if_freq;
+- mode = "I";
+- } else if (params->std & V4L2_STD_DK) {
+- std = std_map->atv_dk.std_bits;
+- sgIF = std_map->atv_dk.if_freq;
+- mode = "DK";
+- } else if (params->std & V4L2_STD_SECAM_L) {
+- std = std_map->atv_l.std_bits;
+- sgIF = std_map->atv_l.if_freq;
+- mode = "L";
+- } else if (params->std & V4L2_STD_SECAM_LC) {
+- std = std_map->atv_lc.std_bits;
+- sgIF = std_map->atv_lc.if_freq;
+- mode = "L'";
+- } else {
+- std = std_map->atv_i.std_bits;
+- sgIF = std_map->atv_i.if_freq;
+- mode = "xx";
+- }
-
-- /*
-- * Either READ or WRITE
-- */
-- int rw;
-- struct io_region source;
+- tda_dbg("setting tda18271 to system %s\n", mode);
-
-- /*
-- * The destinations for the transfer.
-- */
-- unsigned int num_dests;
-- struct io_region dests[KCOPYD_MAX_REGIONS];
+- ret = tda18271_tune(fe, sgIF * 1000, freq, 0, std, radio);
-
-- sector_t offset;
-- unsigned int nr_pages;
-- struct page_list *pages;
+- if (ret < 0)
+- goto fail;
-
-- /*
-- * Set this to ensure you are notified when the job has
-- * completed. 'context' is for callback to use.
-- */
-- kcopyd_notify_fn fn;
-- void *context;
+- priv->frequency = freq;
+- priv->bandwidth = 0;
+-fail:
+- return ret;
+-}
-
-- /*
-- * 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;
--};
+-static int tda18271_sleep(struct dvb_frontend *fe)
+-{
+- struct tda18271_priv *priv = fe->tuner_priv;
-
--/* FIXME: this should scale with the number of pages */
--#define MIN_JOBS 512
+- mutex_lock(&priv->lock);
-
--static struct kmem_cache *_job_cache;
--static mempool_t *_job_pool;
+- /* standby mode w/ slave tuner output
+- * & loop thru & xtal oscillator on */
+- tda18271_set_standby_mode(fe, 1, 0, 0);
-
--/*
-- * 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);
+- mutex_unlock(&priv->lock);
-
--static LIST_HEAD(_complete_jobs);
--static LIST_HEAD(_io_jobs);
--static LIST_HEAD(_pages_jobs);
+- return 0;
+-}
-
--static int jobs_init(void)
+-static int tda18271_release(struct dvb_frontend *fe)
-{
-- _job_cache = KMEM_CACHE(kcopyd_job, 0);
-- if (!_job_cache)
-- return -ENOMEM;
+- struct tda18271_priv *priv = fe->tuner_priv;
-
-- _job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache);
-- if (!_job_pool) {
-- kmem_cache_destroy(_job_cache);
-- return -ENOMEM;
+- mutex_lock(&tda18271_list_mutex);
+-
+- priv->count--;
+-
+- 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;
-
- return 0;
-}
-
--static void jobs_exit(void)
+-static int tda18271_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-- 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;
+- struct tda18271_priv *priv = fe->tuner_priv;
+- *frequency = priv->frequency;
+- return 0;
-}
-
--/*
-- * Functions to push and pop a job onto the head of a given job
-- * list.
-- */
--static struct kcopyd_job *pop(struct list_head *jobs)
+-static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-- struct kcopyd_job *job = NULL;
-- unsigned long flags;
+- struct tda18271_priv *priv = fe->tuner_priv;
+- *bandwidth = priv->bandwidth;
+- return 0;
+-}
-
-- 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);
+-#define tda18271_update_std(std_cfg, name) do { \
+- if (map->std_cfg.if_freq + map->std_cfg.std_bits > 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)
-
-- return job;
--}
+-#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); \
+- } while (0)
-
--static void push(struct list_head *jobs, struct kcopyd_job *job)
+-static int tda18271_dump_std_map(struct dvb_frontend *fe)
-{
-- unsigned long flags;
+- struct tda18271_priv *priv = fe->tuner_priv;
+- struct tda18271_std_map *std = &priv->std;
-
-- spin_lock_irqsave(&_job_lock, flags);
-- list_add_tail(&job->list, jobs);
-- spin_unlock_irqrestore(&_job_lock, flags);
+- 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(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");
+-
+- return 0;
-}
-
--/*
-- * 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)
+-static int tda18271_update_std_map(struct dvb_frontend *fe,
+- struct tda18271_std_map *map)
-{
-- 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;
+- struct tda18271_priv *priv = fe->tuner_priv;
+- struct tda18271_std_map *std = &priv->std;
-
-- kcopyd_put_pages(kc, job->pages);
-- mempool_free(job, _job_pool);
-- fn(read_err, write_err, context);
+- if (!map)
+- return -EINVAL;
-
-- if (atomic_dec_and_test(&kc->nr_jobs))
-- wake_up(&kc->destroyq);
+- tda18271_update_std(fm_radio, "fm");
+- tda18271_update_std(atv_b, "atv b");
+- tda18271_update_std(atv_dk, "atv dk");
+- tda18271_update_std(atv_gh, "atv gh");
+- tda18271_update_std(atv_i, "atv i");
+- tda18271_update_std(atv_l, "atv l");
+- tda18271_update_std(atv_lc, "atv l'");
+- tda18271_update_std(atv_mn, "atv mn");
+- tda18271_update_std(atsc_6, "atsc 6");
+- tda18271_update_std(dvbt_6, "dvbt 6");
+- tda18271_update_std(dvbt_7, "dvbt 7");
+- tda18271_update_std(dvbt_8, "dvbt 8");
+- tda18271_update_std(qam_6, "qam 6");
+- tda18271_update_std(qam_8, "qam 8");
-
- return 0;
-}
-
--static void complete_io(unsigned long error, void *context)
+-static int tda18271_get_id(struct dvb_frontend *fe)
-{
-- struct kcopyd_job *job = (struct kcopyd_job *) context;
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+- char *name;
+- int ret = 0;
-
-- if (error) {
-- if (job->rw == WRITE)
-- job->write_err |= error;
-- else
-- job->read_err = 1;
+- mutex_lock(&priv->lock);
+- tda18271_read_regs(fe);
+- mutex_unlock(&priv->lock);
-
-- if (!test_bit(KCOPYD_IGNORE_ERROR, &job->flags)) {
-- push(&_complete_jobs, job);
-- wake();
-- return;
-- }
+- switch (regs[R_ID] & 0x7f) {
+- case 3:
+- name = "TDA18271HD/C1";
+- priv->id = TDA18271HDC1;
+- break;
+- case 4:
+- name = "TDA18271HD/C2";
+- priv->id = TDA18271HDC2;
+- break;
+- default:
+- name = "Unknown device";
+- ret = -EINVAL;
+- break;
- }
-
-- if (job->rw == WRITE)
-- push(&_complete_jobs, job);
--
-- else {
-- job->rw = WRITE;
-- push(&_io_jobs, job);
-- }
+- tda_info("%s detected @ %d-%04x%s\n", name,
+- i2c_adapter_id(priv->i2c_adap), priv->i2c_addr,
+- (0 == ret) ? "" : ", device not supported.");
-
-- wake();
+- return ret;
-}
-
--/*
-- * 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)
+-static struct dvb_tuner_ops tda18271_tuner_ops = {
+- .info = {
+- .name = "NXP TDA18271HD",
+- .frequency_min = 45000000,
+- .frequency_max = 864000000,
+- .frequency_step = 62500
+- },
+- .init = tda18271_init,
+- .sleep = tda18271_sleep,
+- .set_params = tda18271_set_params,
+- .set_analog_params = tda18271_set_analog_params,
+- .release = tda18271_release,
+- .get_frequency = tda18271_get_frequency,
+- .get_bandwidth = tda18271_get_bandwidth,
+-};
+-
+-struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
+- struct i2c_adapter *i2c,
+- struct tda18271_config *cfg)
-{
-- 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,
-- };
+- struct tda18271_priv *priv = NULL;
+- int state_found = 0;
-
-- 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);
+- mutex_lock(&tda18271_list_mutex);
-
-- return r;
--}
+- 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);
-
--static int run_pages_job(struct kcopyd_job *job)
--{
-- int r;
+- priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL);
+- if (priv == NULL) {
+- mutex_unlock(&tda18271_list_mutex);
+- return NULL;
+- }
-
-- 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;
+- priv->i2c_addr = addr;
+- priv->i2c_adap = i2c;
+- priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
+- priv->cal_initialized = false;
+- mutex_init(&priv->lock);
+- priv->count++;
+-
+- fe->tuner_priv = priv;
+-
+- list_add_tail(&priv->tda18271_list, &tda18271_list);
+-
+- if (tda18271_get_id(fe) < 0)
+- goto fail;
+-
+- if (tda18271_assign_map_layout(fe) < 0)
+- goto fail;
+-
+- mutex_lock(&priv->lock);
+- tda18271_init_regs(fe);
+-
+- if ((tda18271_cal_on_startup) && (priv->id == TDA18271HDC2))
+- tda18271_rf_cal_init(fe);
+-
+- mutex_unlock(&priv->lock);
- }
-
-- if (r == -ENOMEM)
-- /* can't complete now */
-- return 1;
+- /* override default std map with values in config struct */
+- if ((cfg) && (cfg->std_map))
+- tda18271_update_std_map(fe, cfg->std_map);
-
-- return r;
+- mutex_unlock(&tda18271_list_mutex);
+-
+- memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
+- sizeof(struct dvb_tuner_ops));
+-
+- if (tda18271_debug & DBG_MAP)
+- tda18271_dump_std_map(fe);
+-
+- return fe;
+-fail:
+- mutex_unlock(&tda18271_list_mutex);
+-
+- tda18271_release(fe);
+- return NULL;
-}
+-EXPORT_SYMBOL_GPL(tda18271_attach);
+-MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver");
+-MODULE_AUTHOR("Michael Krufky <mkrufky at linuxtv.org>");
+-MODULE_LICENSE("GPL");
+-MODULE_VERSION("0.2");
-
-/*
-- * Run through a list for as long as possible. Returns the count
-- * of successful jobs.
+- * Overrides for Emacs so that we follow Linus's tabbing style.
+- * ---------------------------------------------------------------------------
+- * Local variables:
+- * c-basic-offset: 8
+- * End:
- */
--static int process_jobs(struct list_head *jobs, int (*fn) (struct kcopyd_job *))
--{
-- struct kcopyd_job *job;
-- int r, count = 0;
+diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h
+deleted file mode 100644
+index 7b939a5..0000000
+--- a/drivers/media/dvb/frontends/tda18271-priv.h
++++ /dev/null
+@@ -1,212 +0,0 @@
+-/*
+- tda18271-priv.h - private header for the NXP TDA18271 silicon tuner
-
-- while ((job = pop(jobs))) {
+- Copyright (C) 2007, 2008 Michael Krufky <mkrufky at linuxtv.org>
-
-- r = fn(job);
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the 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 (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;
-- }
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
-
-- if (r > 0) {
-- /*
-- * We couldn't service this job ATM, so
-- * push this job back onto the list.
-- */
-- push(jobs, job);
-- break;
-- }
+- You 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.
+-*/
-
-- count++;
-- }
+-#ifndef __TDA18271_PRIV_H__
+-#define __TDA18271_PRIV_H__
-
-- return count;
--}
+-#include <linux/kernel.h>
+-#include <linux/types.h>
+-#include <linux/mutex.h>
+-#include "tda18271.h"
-
--/*
-- * 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);
--}
+-#define R_ID 0x00 /* ID byte */
+-#define R_TM 0x01 /* Thermo byte */
+-#define R_PL 0x02 /* Power level byte */
+-#define R_EP1 0x03 /* Easy Prog byte 1 */
+-#define R_EP2 0x04 /* Easy Prog byte 2 */
+-#define R_EP3 0x05 /* Easy Prog byte 3 */
+-#define R_EP4 0x06 /* Easy Prog byte 4 */
+-#define R_EP5 0x07 /* Easy Prog byte 5 */
+-#define R_CPD 0x08 /* Cal Post-Divider byte */
+-#define R_CD1 0x09 /* Cal Divider byte 1 */
+-#define R_CD2 0x0a /* Cal Divider byte 2 */
+-#define R_CD3 0x0b /* Cal Divider byte 3 */
+-#define R_MPD 0x0c /* Main Post-Divider byte */
+-#define R_MD1 0x0d /* Main Divider byte 1 */
+-#define R_MD2 0x0e /* Main Divider byte 2 */
+-#define R_MD3 0x0f /* Main Divider byte 3 */
+-#define R_EB1 0x10 /* Extended byte 1 */
+-#define R_EB2 0x11 /* Extended byte 2 */
+-#define R_EB3 0x12 /* Extended byte 3 */
+-#define R_EB4 0x13 /* Extended byte 4 */
+-#define R_EB5 0x14 /* Extended byte 5 */
+-#define R_EB6 0x15 /* Extended byte 6 */
+-#define R_EB7 0x16 /* Extended byte 7 */
+-#define R_EB8 0x17 /* Extended byte 8 */
+-#define R_EB9 0x18 /* Extended byte 9 */
+-#define R_EB10 0x19 /* Extended byte 10 */
+-#define R_EB11 0x1a /* Extended byte 11 */
+-#define R_EB12 0x1b /* Extended byte 12 */
+-#define R_EB13 0x1c /* Extended byte 13 */
+-#define R_EB14 0x1d /* Extended byte 14 */
+-#define R_EB15 0x1e /* Extended byte 15 */
+-#define R_EB16 0x1f /* Extended byte 16 */
+-#define R_EB17 0x20 /* Extended byte 17 */
+-#define R_EB18 0x21 /* Extended byte 18 */
+-#define R_EB19 0x22 /* Extended byte 19 */
+-#define R_EB20 0x23 /* Extended byte 20 */
+-#define R_EB21 0x24 /* Extended byte 21 */
+-#define R_EB22 0x25 /* Extended byte 22 */
+-#define R_EB23 0x26 /* Extended byte 23 */
+-
+-#define TDA18271_NUM_REGS 39
+-
+-/*---------------------------------------------------------------------*/
+-
+-struct tda18271_rf_tracking_filter_cal {
+- u32 rfmax;
+- u8 rfband;
+- u32 rf1_def;
+- u32 rf2_def;
+- u32 rf3_def;
+- u32 rf1;
+- u32 rf2;
+- u32 rf3;
+- int rf_a1;
+- int rf_b1;
+- int rf_a2;
+- int rf_b2;
+-};
+-
+-enum tda18271_mode {
+- TDA18271_ANALOG,
+- TDA18271_DIGITAL,
+-};
+-
+-struct tda18271_map_layout;
+-
+-enum tda18271_ver {
+- TDA18271HDC1,
+- TDA18271HDC2,
+-};
-
--/*
-- * 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();
--}
+-struct tda18271_priv {
+- u8 i2c_addr;
+- struct i2c_adapter *i2c_adap;
+- unsigned char tda18271_regs[TDA18271_NUM_REGS];
-
--#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;
+- struct list_head tda18271_list;
-
-- mutex_lock(&job->lock);
+- enum tda18271_mode mode;
+- enum tda18271_i2c_gate gate;
+- enum tda18271_ver id;
-
-- /* update the error */
-- if (read_err)
-- job->read_err = 1;
+- unsigned int count;
+- unsigned int tm_rfcal;
+- unsigned int cal_initialized:1;
-
-- if (write_err)
-- job->write_err |= write_err;
+- struct tda18271_map_layout *maps;
+- struct tda18271_std_map std;
+- struct tda18271_rf_tracking_filter_cal rf_cal_state[8];
-
-- /*
-- * 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;
+- struct mutex lock;
-
-- job->progress += count;
-- }
-- }
-- mutex_unlock(&job->lock);
+- u32 frequency;
+- u32 bandwidth;
+-};
-
-- 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;
+-extern int tda18271_debug;
-
-- for (i = 0; i < job->num_dests; i++) {
-- sub_job->dests[i].sector += progress;
-- sub_job->dests[i].count = count;
-- }
+-#define DBG_INFO 1
+-#define DBG_MAP 2
+-#define DBG_REG 4
+-#define DBG_ADV 8
+-#define DBG_CAL 16
-
-- sub_job->fn = segment_complete;
-- sub_job->context = job;
-- dispatch_job(sub_job);
+-#define tda_printk(kern, fmt, arg...) \
+- printk(kern "%s: " fmt, __FUNCTION__, ##arg)
-
-- } else if (atomic_dec_and_test(&job->sub_jobs)) {
+-#define dprintk(kern, lvl, fmt, arg...) do {\
+- if (tda18271_debug & lvl) \
+- tda_printk(kern, fmt, ##arg); } while (0)
+-
+-#define tda_info(fmt, arg...) printk(KERN_INFO fmt, ##arg)
+-#define tda_warn(fmt, arg...) tda_printk(KERN_WARNING, fmt, ##arg)
+-#define tda_err(fmt, arg...) tda_printk(KERN_ERR, fmt, ##arg)
+-#define tda_dbg(fmt, arg...) dprintk(KERN_DEBUG, DBG_INFO, fmt, ##arg)
+-#define tda_map(fmt, arg...) dprintk(KERN_DEBUG, DBG_MAP, fmt, ##arg)
+-#define tda_reg(fmt, arg...) dprintk(KERN_DEBUG, DBG_REG, fmt, ##arg)
+-#define tda_cal(fmt, arg...) dprintk(KERN_DEBUG, DBG_CAL, fmt, ##arg)
+-
+-/*---------------------------------------------------------------------*/
+-
+-enum tda18271_map_type {
+- /* tda18271_pll_map */
+- MAIN_PLL,
+- CAL_PLL,
+- /* tda18271_map */
+- RF_CAL,
+- RF_CAL_KMCO,
+- RF_CAL_DC_OVER_DT,
+- BP_FILTER,
+- RF_BAND,
+- GAIN_TAPER,
+- IR_MEASURE,
+-};
+-
+-extern int tda18271_lookup_pll_map(struct dvb_frontend *fe,
+- enum tda18271_map_type map_type,
+- u32 *freq, u8 *post_div, u8 *div);
+-extern int tda18271_lookup_map(struct dvb_frontend *fe,
+- enum tda18271_map_type map_type,
+- u32 *freq, u8 *val);
+-
+-extern int tda18271_lookup_thermometer(struct dvb_frontend *fe);
+-
+-extern int tda18271_lookup_rf_band(struct dvb_frontend *fe,
+- u32 *freq, u8 *rf_band);
+-
+-extern int tda18271_lookup_cid_target(struct dvb_frontend *fe,
+- u32 *freq, u8 *cid_target,
+- u16 *count_limit);
+-
+-extern int tda18271_assign_map_layout(struct dvb_frontend *fe);
+-
+-/*---------------------------------------------------------------------*/
+-
+-extern int tda18271_read_regs(struct dvb_frontend *fe);
+-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_set_standby_mode(struct dvb_frontend *fe,
+- int sm, int sm_lt, int sm_xt);
+-
+-extern int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq);
+-extern int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq);
+-
+-extern int tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq);
+-extern int tda18271_calc_km(struct dvb_frontend *fe, u32 *freq);
+-extern int tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq);
+-extern int tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq);
+-extern int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq);
+-extern int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq);
-
-- /*
-- * 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);
-- }
--}
+-#endif /* __TDA18271_PRIV_H__ */
-
-/*
-- * Create some little jobs that will do the move between
-- * them.
+- * Overrides for Emacs so that we follow Linus's tabbing style.
+- * ---------------------------------------------------------------------------
+- * Local variables:
+- * c-basic-offset: 8
+- * End:
- */
--#define SPLIT_COUNT 8
--static void split_job(struct kcopyd_job *job)
--{
-- int i;
+diff --git a/drivers/media/dvb/frontends/tda18271-tables.c b/drivers/media/dvb/frontends/tda18271-tables.c
+deleted file mode 100644
+index e94afcf..0000000
+--- a/drivers/media/dvb/frontends/tda18271-tables.c
++++ /dev/null
+@@ -1,1285 +0,0 @@
+-/*
+- tda18271-tables.c - driver for the Philips / NXP TDA18271 silicon tuner
-
-- atomic_set(&job->sub_jobs, SPLIT_COUNT);
-- for (i = 0; i < SPLIT_COUNT; i++)
-- segment_complete(0, 0u, job);
--}
+- Copyright (C) 2007, 2008 Michael Krufky <mkrufky at linuxtv.org>
-
--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)
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2 of the License, or
+- (at your option) any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
+-
+- You 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 "tda18271-priv.h"
+-
+-struct tda18271_pll_map {
+- u32 lomax;
+- u8 pd; /* post div */
+- u8 d; /* div */
+-};
+-
+-struct tda18271_map {
+- u32 rfmax;
+- u8 val;
+-};
+-
+-/*---------------------------------------------------------------------*/
+-
+-static struct tda18271_pll_map tda18271c1_main_pll[] = {
+- { .lomax = 32000, .pd = 0x5f, .d = 0xf0 },
+- { .lomax = 35000, .pd = 0x5e, .d = 0xe0 },
+- { .lomax = 37000, .pd = 0x5d, .d = 0xd0 },
+- { .lomax = 41000, .pd = 0x5c, .d = 0xc0 },
+- { .lomax = 44000, .pd = 0x5b, .d = 0xb0 },
+- { .lomax = 49000, .pd = 0x5a, .d = 0xa0 },
+- { .lomax = 54000, .pd = 0x59, .d = 0x90 },
+- { .lomax = 61000, .pd = 0x58, .d = 0x80 },
+- { .lomax = 65000, .pd = 0x4f, .d = 0x78 },
+- { .lomax = 70000, .pd = 0x4e, .d = 0x70 },
+- { .lomax = 75000, .pd = 0x4d, .d = 0x68 },
+- { .lomax = 82000, .pd = 0x4c, .d = 0x60 },
+- { .lomax = 89000, .pd = 0x4b, .d = 0x58 },
+- { .lomax = 98000, .pd = 0x4a, .d = 0x50 },
+- { .lomax = 109000, .pd = 0x49, .d = 0x48 },
+- { .lomax = 123000, .pd = 0x48, .d = 0x40 },
+- { .lomax = 131000, .pd = 0x3f, .d = 0x3c },
+- { .lomax = 141000, .pd = 0x3e, .d = 0x38 },
+- { .lomax = 151000, .pd = 0x3d, .d = 0x34 },
+- { .lomax = 164000, .pd = 0x3c, .d = 0x30 },
+- { .lomax = 179000, .pd = 0x3b, .d = 0x2c },
+- { .lomax = 197000, .pd = 0x3a, .d = 0x28 },
+- { .lomax = 219000, .pd = 0x39, .d = 0x24 },
+- { .lomax = 246000, .pd = 0x38, .d = 0x20 },
+- { .lomax = 263000, .pd = 0x2f, .d = 0x1e },
+- { .lomax = 282000, .pd = 0x2e, .d = 0x1c },
+- { .lomax = 303000, .pd = 0x2d, .d = 0x1a },
+- { .lomax = 329000, .pd = 0x2c, .d = 0x18 },
+- { .lomax = 359000, .pd = 0x2b, .d = 0x16 },
+- { .lomax = 395000, .pd = 0x2a, .d = 0x14 },
+- { .lomax = 438000, .pd = 0x29, .d = 0x12 },
+- { .lomax = 493000, .pd = 0x28, .d = 0x10 },
+- { .lomax = 526000, .pd = 0x1f, .d = 0x0f },
+- { .lomax = 564000, .pd = 0x1e, .d = 0x0e },
+- { .lomax = 607000, .pd = 0x1d, .d = 0x0d },
+- { .lomax = 658000, .pd = 0x1c, .d = 0x0c },
+- { .lomax = 718000, .pd = 0x1b, .d = 0x0b },
+- { .lomax = 790000, .pd = 0x1a, .d = 0x0a },
+- { .lomax = 877000, .pd = 0x19, .d = 0x09 },
+- { .lomax = 987000, .pd = 0x18, .d = 0x08 },
+- { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */
+-};
+-
+-static struct tda18271_pll_map tda18271c2_main_pll[] = {
+- { .lomax = 33125, .pd = 0x57, .d = 0xf0 },
+- { .lomax = 35500, .pd = 0x56, .d = 0xe0 },
+- { .lomax = 38188, .pd = 0x55, .d = 0xd0 },
+- { .lomax = 41375, .pd = 0x54, .d = 0xc0 },
+- { .lomax = 45125, .pd = 0x53, .d = 0xb0 },
+- { .lomax = 49688, .pd = 0x52, .d = 0xa0 },
+- { .lomax = 55188, .pd = 0x51, .d = 0x90 },
+- { .lomax = 62125, .pd = 0x50, .d = 0x80 },
+- { .lomax = 66250, .pd = 0x47, .d = 0x78 },
+- { .lomax = 71000, .pd = 0x46, .d = 0x70 },
+- { .lomax = 76375, .pd = 0x45, .d = 0x68 },
+- { .lomax = 82750, .pd = 0x44, .d = 0x60 },
+- { .lomax = 90250, .pd = 0x43, .d = 0x58 },
+- { .lomax = 99375, .pd = 0x42, .d = 0x50 },
+- { .lomax = 110375, .pd = 0x41, .d = 0x48 },
+- { .lomax = 124250, .pd = 0x40, .d = 0x40 },
+- { .lomax = 132500, .pd = 0x37, .d = 0x3c },
+- { .lomax = 142000, .pd = 0x36, .d = 0x38 },
+- { .lomax = 152750, .pd = 0x35, .d = 0x34 },
+- { .lomax = 165500, .pd = 0x34, .d = 0x30 },
+- { .lomax = 180500, .pd = 0x33, .d = 0x2c },
+- { .lomax = 198750, .pd = 0x32, .d = 0x28 },
+- { .lomax = 220750, .pd = 0x31, .d = 0x24 },
+- { .lomax = 248500, .pd = 0x30, .d = 0x20 },
+- { .lomax = 265000, .pd = 0x27, .d = 0x1e },
+- { .lomax = 284000, .pd = 0x26, .d = 0x1c },
+- { .lomax = 305500, .pd = 0x25, .d = 0x1a },
+- { .lomax = 331000, .pd = 0x24, .d = 0x18 },
+- { .lomax = 361000, .pd = 0x23, .d = 0x16 },
+- { .lomax = 397500, .pd = 0x22, .d = 0x14 },
+- { .lomax = 441500, .pd = 0x21, .d = 0x12 },
+- { .lomax = 497000, .pd = 0x20, .d = 0x10 },
+- { .lomax = 530000, .pd = 0x17, .d = 0x0f },
+- { .lomax = 568000, .pd = 0x16, .d = 0x0e },
+- { .lomax = 611000, .pd = 0x15, .d = 0x0d },
+- { .lomax = 662000, .pd = 0x14, .d = 0x0c },
+- { .lomax = 722000, .pd = 0x13, .d = 0x0b },
+- { .lomax = 795000, .pd = 0x12, .d = 0x0a },
+- { .lomax = 883000, .pd = 0x11, .d = 0x09 },
+- { .lomax = 994000, .pd = 0x10, .d = 0x08 },
+- { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */
+-};
+-
+-static struct tda18271_pll_map tda18271c1_cal_pll[] = {
+- { .lomax = 33000, .pd = 0xdd, .d = 0xd0 },
+- { .lomax = 36000, .pd = 0xdc, .d = 0xc0 },
+- { .lomax = 40000, .pd = 0xdb, .d = 0xb0 },
+- { .lomax = 44000, .pd = 0xda, .d = 0xa0 },
+- { .lomax = 49000, .pd = 0xd9, .d = 0x90 },
+- { .lomax = 55000, .pd = 0xd8, .d = 0x80 },
+- { .lomax = 63000, .pd = 0xd3, .d = 0x70 },
+- { .lomax = 67000, .pd = 0xcd, .d = 0x68 },
+- { .lomax = 73000, .pd = 0xcc, .d = 0x60 },
+- { .lomax = 80000, .pd = 0xcb, .d = 0x58 },
+- { .lomax = 88000, .pd = 0xca, .d = 0x50 },
+- { .lomax = 98000, .pd = 0xc9, .d = 0x48 },
+- { .lomax = 110000, .pd = 0xc8, .d = 0x40 },
+- { .lomax = 126000, .pd = 0xc3, .d = 0x38 },
+- { .lomax = 135000, .pd = 0xbd, .d = 0x34 },
+- { .lomax = 147000, .pd = 0xbc, .d = 0x30 },
+- { .lomax = 160000, .pd = 0xbb, .d = 0x2c },
+- { .lomax = 176000, .pd = 0xba, .d = 0x28 },
+- { .lomax = 196000, .pd = 0xb9, .d = 0x24 },
+- { .lomax = 220000, .pd = 0xb8, .d = 0x20 },
+- { .lomax = 252000, .pd = 0xb3, .d = 0x1c },
+- { .lomax = 271000, .pd = 0xad, .d = 0x1a },
+- { .lomax = 294000, .pd = 0xac, .d = 0x18 },
+- { .lomax = 321000, .pd = 0xab, .d = 0x16 },
+- { .lomax = 353000, .pd = 0xaa, .d = 0x14 },
+- { .lomax = 392000, .pd = 0xa9, .d = 0x12 },
+- { .lomax = 441000, .pd = 0xa8, .d = 0x10 },
+- { .lomax = 505000, .pd = 0xa3, .d = 0x0e },
+- { .lomax = 543000, .pd = 0x9d, .d = 0x0d },
+- { .lomax = 589000, .pd = 0x9c, .d = 0x0c },
+- { .lomax = 642000, .pd = 0x9b, .d = 0x0b },
+- { .lomax = 707000, .pd = 0x9a, .d = 0x0a },
+- { .lomax = 785000, .pd = 0x99, .d = 0x09 },
+- { .lomax = 883000, .pd = 0x98, .d = 0x08 },
+- { .lomax = 1010000, .pd = 0x93, .d = 0x07 },
+- { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */
+-};
+-
+-static struct tda18271_pll_map tda18271c2_cal_pll[] = {
+- { .lomax = 33813, .pd = 0xdd, .d = 0xd0 },
+- { .lomax = 36625, .pd = 0xdc, .d = 0xc0 },
+- { .lomax = 39938, .pd = 0xdb, .d = 0xb0 },
+- { .lomax = 43938, .pd = 0xda, .d = 0xa0 },
+- { .lomax = 48813, .pd = 0xd9, .d = 0x90 },
+- { .lomax = 54938, .pd = 0xd8, .d = 0x80 },
+- { .lomax = 62813, .pd = 0xd3, .d = 0x70 },
+- { .lomax = 67625, .pd = 0xcd, .d = 0x68 },
+- { .lomax = 73250, .pd = 0xcc, .d = 0x60 },
+- { .lomax = 79875, .pd = 0xcb, .d = 0x58 },
+- { .lomax = 87875, .pd = 0xca, .d = 0x50 },
+- { .lomax = 97625, .pd = 0xc9, .d = 0x48 },
+- { .lomax = 109875, .pd = 0xc8, .d = 0x40 },
+- { .lomax = 125625, .pd = 0xc3, .d = 0x38 },
+- { .lomax = 135250, .pd = 0xbd, .d = 0x34 },
+- { .lomax = 146500, .pd = 0xbc, .d = 0x30 },
+- { .lomax = 159750, .pd = 0xbb, .d = 0x2c },
+- { .lomax = 175750, .pd = 0xba, .d = 0x28 },
+- { .lomax = 195250, .pd = 0xb9, .d = 0x24 },
+- { .lomax = 219750, .pd = 0xb8, .d = 0x20 },
+- { .lomax = 251250, .pd = 0xb3, .d = 0x1c },
+- { .lomax = 270500, .pd = 0xad, .d = 0x1a },
+- { .lomax = 293000, .pd = 0xac, .d = 0x18 },
+- { .lomax = 319500, .pd = 0xab, .d = 0x16 },
+- { .lomax = 351500, .pd = 0xaa, .d = 0x14 },
+- { .lomax = 390500, .pd = 0xa9, .d = 0x12 },
+- { .lomax = 439500, .pd = 0xa8, .d = 0x10 },
+- { .lomax = 502500, .pd = 0xa3, .d = 0x0e },
+- { .lomax = 541000, .pd = 0x9d, .d = 0x0d },
+- { .lomax = 586000, .pd = 0x9c, .d = 0x0c },
+- { .lomax = 639000, .pd = 0x9b, .d = 0x0b },
+- { .lomax = 703000, .pd = 0x9a, .d = 0x0a },
+- { .lomax = 781000, .pd = 0x99, .d = 0x09 },
+- { .lomax = 879000, .pd = 0x98, .d = 0x08 },
+- { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */
+-};
+-
+-static struct tda18271_map tda18271_bp_filter[] = {
+- { .rfmax = 62000, .val = 0x00 },
+- { .rfmax = 84000, .val = 0x01 },
+- { .rfmax = 100000, .val = 0x02 },
+- { .rfmax = 140000, .val = 0x03 },
+- { .rfmax = 170000, .val = 0x04 },
+- { .rfmax = 180000, .val = 0x05 },
+- { .rfmax = 865000, .val = 0x06 },
+- { .rfmax = 0, .val = 0x00 }, /* end */
+-};
+-
+-static struct tda18271_map tda18271c1_km[] = {
+- { .rfmax = 61100, .val = 0x74 },
+- { .rfmax = 350000, .val = 0x40 },
+- { .rfmax = 720000, .val = 0x30 },
+- { .rfmax = 865000, .val = 0x40 },
+- { .rfmax = 0, .val = 0x00 }, /* end */
+-};
+-
+-static struct tda18271_map tda18271c2_km[] = {
+- { .rfmax = 47900, .val = 0x38 },
+- { .rfmax = 61100, .val = 0x44 },
+- { .rfmax = 350000, .val = 0x30 },
+- { .rfmax = 720000, .val = 0x24 },
+- { .rfmax = 865000, .val = 0x3c },
+- { .rfmax = 0, .val = 0x00 }, /* end */
+-};
+-
+-static struct tda18271_map tda18271_rf_band[] = {
+- { .rfmax = 47900, .val = 0x00 },
+- { .rfmax = 61100, .val = 0x01 },
+-/* { .rfmax = 152600, .val = 0x02 }, */
+- { .rfmax = 121200, .val = 0x02 },
+- { .rfmax = 164700, .val = 0x03 },
+- { .rfmax = 203500, .val = 0x04 },
+- { .rfmax = 457800, .val = 0x05 },
+- { .rfmax = 865000, .val = 0x06 },
+- { .rfmax = 0, .val = 0x00 }, /* end */
+-};
+-
+-static struct tda18271_map tda18271_gain_taper[] = {
+- { .rfmax = 45400, .val = 0x1f },
+- { .rfmax = 45800, .val = 0x1e },
+- { .rfmax = 46200, .val = 0x1d },
+- { .rfmax = 46700, .val = 0x1c },
+- { .rfmax = 47100, .val = 0x1b },
+- { .rfmax = 47500, .val = 0x1a },
+- { .rfmax = 47900, .val = 0x19 },
+- { .rfmax = 49600, .val = 0x17 },
+- { .rfmax = 51200, .val = 0x16 },
+- { .rfmax = 52900, .val = 0x15 },
+- { .rfmax = 54500, .val = 0x14 },
+- { .rfmax = 56200, .val = 0x13 },
+- { .rfmax = 57800, .val = 0x12 },
+- { .rfmax = 59500, .val = 0x11 },
+- { .rfmax = 61100, .val = 0x10 },
+- { .rfmax = 67600, .val = 0x0d },
+- { .rfmax = 74200, .val = 0x0c },
+- { .rfmax = 80700, .val = 0x0b },
+- { .rfmax = 87200, .val = 0x0a },
+- { .rfmax = 93800, .val = 0x09 },
+- { .rfmax = 100300, .val = 0x08 },
+- { .rfmax = 106900, .val = 0x07 },
+- { .rfmax = 113400, .val = 0x06 },
+- { .rfmax = 119900, .val = 0x05 },
+- { .rfmax = 126500, .val = 0x04 },
+- { .rfmax = 133000, .val = 0x03 },
+- { .rfmax = 139500, .val = 0x02 },
+- { .rfmax = 146100, .val = 0x01 },
+- { .rfmax = 152600, .val = 0x00 },
+- { .rfmax = 154300, .val = 0x1f },
+- { .rfmax = 156100, .val = 0x1e },
+- { .rfmax = 157800, .val = 0x1d },
+- { .rfmax = 159500, .val = 0x1c },
+- { .rfmax = 161200, .val = 0x1b },
+- { .rfmax = 163000, .val = 0x1a },
+- { .rfmax = 164700, .val = 0x19 },
+- { .rfmax = 170200, .val = 0x17 },
+- { .rfmax = 175800, .val = 0x16 },
+- { .rfmax = 181300, .val = 0x15 },
+- { .rfmax = 186900, .val = 0x14 },
+- { .rfmax = 192400, .val = 0x13 },
+- { .rfmax = 198000, .val = 0x12 },
+- { .rfmax = 203500, .val = 0x11 },
+- { .rfmax = 216200, .val = 0x14 },
+- { .rfmax = 228900, .val = 0x13 },
+- { .rfmax = 241600, .val = 0x12 },
+- { .rfmax = 254400, .val = 0x11 },
+- { .rfmax = 267100, .val = 0x10 },
+- { .rfmax = 279800, .val = 0x0f },
+- { .rfmax = 292500, .val = 0x0e },
+- { .rfmax = 305200, .val = 0x0d },
+- { .rfmax = 317900, .val = 0x0c },
+- { .rfmax = 330700, .val = 0x0b },
+- { .rfmax = 343400, .val = 0x0a },
+- { .rfmax = 356100, .val = 0x09 },
+- { .rfmax = 368800, .val = 0x08 },
+- { .rfmax = 381500, .val = 0x07 },
+- { .rfmax = 394200, .val = 0x06 },
+- { .rfmax = 406900, .val = 0x05 },
+- { .rfmax = 419700, .val = 0x04 },
+- { .rfmax = 432400, .val = 0x03 },
+- { .rfmax = 445100, .val = 0x02 },
+- { .rfmax = 457800, .val = 0x01 },
+- { .rfmax = 476300, .val = 0x19 },
+- { .rfmax = 494800, .val = 0x18 },
+- { .rfmax = 513300, .val = 0x17 },
+- { .rfmax = 531800, .val = 0x16 },
+- { .rfmax = 550300, .val = 0x15 },
+- { .rfmax = 568900, .val = 0x14 },
+- { .rfmax = 587400, .val = 0x13 },
+- { .rfmax = 605900, .val = 0x12 },
+- { .rfmax = 624400, .val = 0x11 },
+- { .rfmax = 642900, .val = 0x10 },
+- { .rfmax = 661400, .val = 0x0f },
+- { .rfmax = 679900, .val = 0x0e },
+- { .rfmax = 698400, .val = 0x0d },
+- { .rfmax = 716900, .val = 0x0c },
+- { .rfmax = 735400, .val = 0x0b },
+- { .rfmax = 753900, .val = 0x0a },
+- { .rfmax = 772500, .val = 0x09 },
+- { .rfmax = 791000, .val = 0x08 },
+- { .rfmax = 809500, .val = 0x07 },
+- { .rfmax = 828000, .val = 0x06 },
+- { .rfmax = 846500, .val = 0x05 },
+- { .rfmax = 865000, .val = 0x04 },
+- { .rfmax = 0, .val = 0x00 }, /* end */
+-};
+-
+-static struct tda18271_map tda18271c1_rf_cal[] = {
+- { .rfmax = 41000, .val = 0x1e },
+- { .rfmax = 43000, .val = 0x30 },
+- { .rfmax = 45000, .val = 0x43 },
+- { .rfmax = 46000, .val = 0x4d },
+- { .rfmax = 47000, .val = 0x54 },
+- { .rfmax = 47900, .val = 0x64 },
+- { .rfmax = 49100, .val = 0x20 },
+- { .rfmax = 50000, .val = 0x22 },
+- { .rfmax = 51000, .val = 0x2a },
+- { .rfmax = 53000, .val = 0x32 },
+- { .rfmax = 55000, .val = 0x35 },
+- { .rfmax = 56000, .val = 0x3c },
+- { .rfmax = 57000, .val = 0x3f },
+- { .rfmax = 58000, .val = 0x48 },
+- { .rfmax = 59000, .val = 0x4d },
+- { .rfmax = 60000, .val = 0x58 },
+- { .rfmax = 61100, .val = 0x5f },
+- { .rfmax = 0, .val = 0x00 }, /* end */
+-};
+-
+-static struct tda18271_map tda18271c2_rf_cal[] = {
+- { .rfmax = 41000, .val = 0x0f },
+- { .rfmax = 43000, .val = 0x1c },
+- { .rfmax = 45000, .val = 0x2f },
+- { .rfmax = 46000, .val = 0x39 },
+- { .rfmax = 47000, .val = 0x40 },
+- { .rfmax = 47900, .val = 0x50 },
+- { .rfmax = 49100, .val = 0x16 },
+- { .rfmax = 50000, .val = 0x18 },
+- { .rfmax = 51000, .val = 0x20 },
+- { .rfmax = 53000, .val = 0x28 },
+- { .rfmax = 55000, .val = 0x2b },
+- { .rfmax = 56000, .val = 0x32 },
+- { .rfmax = 57000, .val = 0x35 },
+- { .rfmax = 58000, .val = 0x3e },
+- { .rfmax = 59000, .val = 0x43 },
+- { .rfmax = 60000, .val = 0x4e },
+- { .rfmax = 61100, .val = 0x55 },
+- { .rfmax = 63000, .val = 0x0f },
+- { .rfmax = 64000, .val = 0x11 },
+- { .rfmax = 65000, .val = 0x12 },
+- { .rfmax = 66000, .val = 0x15 },
+- { .rfmax = 67000, .val = 0x16 },
+- { .rfmax = 68000, .val = 0x17 },
+- { .rfmax = 70000, .val = 0x19 },
+- { .rfmax = 71000, .val = 0x1c },
+- { .rfmax = 72000, .val = 0x1d },
+- { .rfmax = 73000, .val = 0x1f },
+- { .rfmax = 74000, .val = 0x20 },
+- { .rfmax = 75000, .val = 0x21 },
+- { .rfmax = 76000, .val = 0x24 },
+- { .rfmax = 77000, .val = 0x25 },
+- { .rfmax = 78000, .val = 0x27 },
+- { .rfmax = 80000, .val = 0x28 },
+- { .rfmax = 81000, .val = 0x29 },
+- { .rfmax = 82000, .val = 0x2d },
+- { .rfmax = 83000, .val = 0x2e },
+- { .rfmax = 84000, .val = 0x2f },
+- { .rfmax = 85000, .val = 0x31 },
+- { .rfmax = 86000, .val = 0x33 },
+- { .rfmax = 87000, .val = 0x34 },
+- { .rfmax = 88000, .val = 0x35 },
+- { .rfmax = 89000, .val = 0x37 },
+- { .rfmax = 90000, .val = 0x38 },
+- { .rfmax = 91000, .val = 0x39 },
+- { .rfmax = 93000, .val = 0x3c },
+- { .rfmax = 94000, .val = 0x3e },
+- { .rfmax = 95000, .val = 0x3f },
+- { .rfmax = 96000, .val = 0x40 },
+- { .rfmax = 97000, .val = 0x42 },
+- { .rfmax = 99000, .val = 0x45 },
+- { .rfmax = 100000, .val = 0x46 },
+- { .rfmax = 102000, .val = 0x48 },
+- { .rfmax = 103000, .val = 0x4a },
+- { .rfmax = 105000, .val = 0x4d },
+- { .rfmax = 106000, .val = 0x4e },
+- { .rfmax = 107000, .val = 0x50 },
+- { .rfmax = 108000, .val = 0x51 },
+- { .rfmax = 110000, .val = 0x54 },
+- { .rfmax = 111000, .val = 0x56 },
+- { .rfmax = 112000, .val = 0x57 },
+- { .rfmax = 113000, .val = 0x58 },
+- { .rfmax = 114000, .val = 0x59 },
+- { .rfmax = 115000, .val = 0x5c },
+- { .rfmax = 116000, .val = 0x5d },
+- { .rfmax = 117000, .val = 0x5f },
+- { .rfmax = 119000, .val = 0x60 },
+- { .rfmax = 120000, .val = 0x64 },
+- { .rfmax = 121000, .val = 0x65 },
+- { .rfmax = 122000, .val = 0x66 },
+- { .rfmax = 123000, .val = 0x68 },
+- { .rfmax = 124000, .val = 0x69 },
+- { .rfmax = 125000, .val = 0x6c },
+- { .rfmax = 126000, .val = 0x6d },
+- { .rfmax = 127000, .val = 0x6e },
+- { .rfmax = 128000, .val = 0x70 },
+- { .rfmax = 129000, .val = 0x71 },
+- { .rfmax = 130000, .val = 0x75 },
+- { .rfmax = 131000, .val = 0x77 },
+- { .rfmax = 132000, .val = 0x78 },
+- { .rfmax = 133000, .val = 0x7b },
+- { .rfmax = 134000, .val = 0x7e },
+- { .rfmax = 135000, .val = 0x81 },
+- { .rfmax = 136000, .val = 0x82 },
+- { .rfmax = 137000, .val = 0x87 },
+- { .rfmax = 138000, .val = 0x88 },
+- { .rfmax = 139000, .val = 0x8d },
+- { .rfmax = 140000, .val = 0x8e },
+- { .rfmax = 141000, .val = 0x91 },
+- { .rfmax = 142000, .val = 0x95 },
+- { .rfmax = 143000, .val = 0x9a },
+- { .rfmax = 144000, .val = 0x9d },
+- { .rfmax = 145000, .val = 0xa1 },
+- { .rfmax = 146000, .val = 0xa2 },
+- { .rfmax = 147000, .val = 0xa4 },
+- { .rfmax = 148000, .val = 0xa9 },
+- { .rfmax = 149000, .val = 0xae },
+- { .rfmax = 150000, .val = 0xb0 },
+- { .rfmax = 151000, .val = 0xb1 },
+- { .rfmax = 152000, .val = 0xb7 },
+- { .rfmax = 153000, .val = 0xbd },
+- { .rfmax = 154000, .val = 0x20 },
+- { .rfmax = 155000, .val = 0x22 },
+- { .rfmax = 156000, .val = 0x24 },
+- { .rfmax = 157000, .val = 0x25 },
+- { .rfmax = 158000, .val = 0x27 },
+- { .rfmax = 159000, .val = 0x29 },
+- { .rfmax = 160000, .val = 0x2c },
+- { .rfmax = 161000, .val = 0x2d },
+- { .rfmax = 163000, .val = 0x2e },
+- { .rfmax = 164000, .val = 0x2f },
+- { .rfmax = 165000, .val = 0x30 },
+- { .rfmax = 166000, .val = 0x11 },
+- { .rfmax = 167000, .val = 0x12 },
+- { .rfmax = 168000, .val = 0x13 },
+- { .rfmax = 169000, .val = 0x14 },
+- { .rfmax = 170000, .val = 0x15 },
+- { .rfmax = 172000, .val = 0x16 },
+- { .rfmax = 173000, .val = 0x17 },
+- { .rfmax = 174000, .val = 0x18 },
+- { .rfmax = 175000, .val = 0x1a },
+- { .rfmax = 176000, .val = 0x1b },
+- { .rfmax = 178000, .val = 0x1d },
+- { .rfmax = 179000, .val = 0x1e },
+- { .rfmax = 180000, .val = 0x1f },
+- { .rfmax = 181000, .val = 0x20 },
+- { .rfmax = 182000, .val = 0x21 },
+- { .rfmax = 183000, .val = 0x22 },
+- { .rfmax = 184000, .val = 0x24 },
+- { .rfmax = 185000, .val = 0x25 },
+- { .rfmax = 186000, .val = 0x26 },
+- { .rfmax = 187000, .val = 0x27 },
+- { .rfmax = 188000, .val = 0x29 },
+- { .rfmax = 189000, .val = 0x2a },
+- { .rfmax = 190000, .val = 0x2c },
+- { .rfmax = 191000, .val = 0x2d },
+- { .rfmax = 192000, .val = 0x2e },
+- { .rfmax = 193000, .val = 0x2f },
+- { .rfmax = 194000, .val = 0x30 },
+- { .rfmax = 195000, .val = 0x33 },
+- { .rfmax = 196000, .val = 0x35 },
+- { .rfmax = 198000, .val = 0x36 },
+- { .rfmax = 200000, .val = 0x38 },
+- { .rfmax = 201000, .val = 0x3c },
+- { .rfmax = 202000, .val = 0x3d },
+- { .rfmax = 203500, .val = 0x3e },
+- { .rfmax = 206000, .val = 0x0e },
+- { .rfmax = 208000, .val = 0x0f },
+- { .rfmax = 212000, .val = 0x10 },
+- { .rfmax = 216000, .val = 0x11 },
+- { .rfmax = 217000, .val = 0x12 },
+- { .rfmax = 218000, .val = 0x13 },
+- { .rfmax = 220000, .val = 0x14 },
+- { .rfmax = 222000, .val = 0x15 },
+- { .rfmax = 225000, .val = 0x16 },
+- { .rfmax = 228000, .val = 0x17 },
+- { .rfmax = 231000, .val = 0x18 },
+- { .rfmax = 234000, .val = 0x19 },
+- { .rfmax = 235000, .val = 0x1a },
+- { .rfmax = 236000, .val = 0x1b },
+- { .rfmax = 237000, .val = 0x1c },
+- { .rfmax = 240000, .val = 0x1d },
+- { .rfmax = 242000, .val = 0x1f },
+- { .rfmax = 247000, .val = 0x20 },
+- { .rfmax = 249000, .val = 0x21 },
+- { .rfmax = 252000, .val = 0x22 },
+- { .rfmax = 253000, .val = 0x23 },
+- { .rfmax = 254000, .val = 0x24 },
+- { .rfmax = 256000, .val = 0x25 },
+- { .rfmax = 259000, .val = 0x26 },
+- { .rfmax = 262000, .val = 0x27 },
+- { .rfmax = 264000, .val = 0x28 },
+- { .rfmax = 267000, .val = 0x29 },
+- { .rfmax = 269000, .val = 0x2a },
+- { .rfmax = 271000, .val = 0x2b },
+- { .rfmax = 273000, .val = 0x2c },
+- { .rfmax = 275000, .val = 0x2d },
+- { .rfmax = 277000, .val = 0x2e },
+- { .rfmax = 279000, .val = 0x2f },
+- { .rfmax = 282000, .val = 0x30 },
+- { .rfmax = 284000, .val = 0x31 },
+- { .rfmax = 286000, .val = 0x32 },
+- { .rfmax = 287000, .val = 0x33 },
+- { .rfmax = 290000, .val = 0x34 },
+- { .rfmax = 293000, .val = 0x35 },
+- { .rfmax = 295000, .val = 0x36 },
+- { .rfmax = 297000, .val = 0x37 },
+- { .rfmax = 300000, .val = 0x38 },
+- { .rfmax = 303000, .val = 0x39 },
+- { .rfmax = 305000, .val = 0x3a },
+- { .rfmax = 306000, .val = 0x3b },
+- { .rfmax = 307000, .val = 0x3c },
+- { .rfmax = 310000, .val = 0x3d },
+- { .rfmax = 312000, .val = 0x3e },
+- { .rfmax = 315000, .val = 0x3f },
+- { .rfmax = 318000, .val = 0x40 },
+- { .rfmax = 320000, .val = 0x41 },
+- { .rfmax = 323000, .val = 0x42 },
+- { .rfmax = 324000, .val = 0x43 },
+- { .rfmax = 325000, .val = 0x44 },
+- { .rfmax = 327000, .val = 0x45 },
+- { .rfmax = 331000, .val = 0x46 },
+- { .rfmax = 334000, .val = 0x47 },
+- { .rfmax = 337000, .val = 0x48 },
+- { .rfmax = 339000, .val = 0x49 },
+- { .rfmax = 340000, .val = 0x4a },
+- { .rfmax = 341000, .val = 0x4b },
+- { .rfmax = 343000, .val = 0x4c },
+- { .rfmax = 345000, .val = 0x4d },
+- { .rfmax = 349000, .val = 0x4e },
+- { .rfmax = 352000, .val = 0x4f },
+- { .rfmax = 353000, .val = 0x50 },
+- { .rfmax = 355000, .val = 0x51 },
+- { .rfmax = 357000, .val = 0x52 },
+- { .rfmax = 359000, .val = 0x53 },
+- { .rfmax = 361000, .val = 0x54 },
+- { .rfmax = 362000, .val = 0x55 },
+- { .rfmax = 364000, .val = 0x56 },
+- { .rfmax = 368000, .val = 0x57 },
+- { .rfmax = 370000, .val = 0x58 },
+- { .rfmax = 372000, .val = 0x59 },
+- { .rfmax = 375000, .val = 0x5a },
+- { .rfmax = 376000, .val = 0x5b },
+- { .rfmax = 377000, .val = 0x5c },
+- { .rfmax = 379000, .val = 0x5d },
+- { .rfmax = 382000, .val = 0x5e },
+- { .rfmax = 384000, .val = 0x5f },
+- { .rfmax = 385000, .val = 0x60 },
+- { .rfmax = 386000, .val = 0x61 },
+- { .rfmax = 388000, .val = 0x62 },
+- { .rfmax = 390000, .val = 0x63 },
+- { .rfmax = 393000, .val = 0x64 },
+- { .rfmax = 394000, .val = 0x65 },
+- { .rfmax = 396000, .val = 0x66 },
+- { .rfmax = 397000, .val = 0x67 },
+- { .rfmax = 398000, .val = 0x68 },
+- { .rfmax = 400000, .val = 0x69 },
+- { .rfmax = 402000, .val = 0x6a },
+- { .rfmax = 403000, .val = 0x6b },
+- { .rfmax = 407000, .val = 0x6c },
+- { .rfmax = 408000, .val = 0x6d },
+- { .rfmax = 409000, .val = 0x6e },
+- { .rfmax = 410000, .val = 0x6f },
+- { .rfmax = 411000, .val = 0x70 },
+- { .rfmax = 412000, .val = 0x71 },
+- { .rfmax = 413000, .val = 0x72 },
+- { .rfmax = 414000, .val = 0x73 },
+- { .rfmax = 417000, .val = 0x74 },
+- { .rfmax = 418000, .val = 0x75 },
+- { .rfmax = 420000, .val = 0x76 },
+- { .rfmax = 422000, .val = 0x77 },
+- { .rfmax = 423000, .val = 0x78 },
+- { .rfmax = 424000, .val = 0x79 },
+- { .rfmax = 427000, .val = 0x7a },
+- { .rfmax = 428000, .val = 0x7b },
+- { .rfmax = 429000, .val = 0x7d },
+- { .rfmax = 432000, .val = 0x7f },
+- { .rfmax = 434000, .val = 0x80 },
+- { .rfmax = 435000, .val = 0x81 },
+- { .rfmax = 436000, .val = 0x83 },
+- { .rfmax = 437000, .val = 0x84 },
+- { .rfmax = 438000, .val = 0x85 },
+- { .rfmax = 439000, .val = 0x86 },
+- { .rfmax = 440000, .val = 0x87 },
+- { .rfmax = 441000, .val = 0x88 },
+- { .rfmax = 442000, .val = 0x89 },
+- { .rfmax = 445000, .val = 0x8a },
+- { .rfmax = 446000, .val = 0x8b },
+- { .rfmax = 447000, .val = 0x8c },
+- { .rfmax = 448000, .val = 0x8e },
+- { .rfmax = 449000, .val = 0x8f },
+- { .rfmax = 450000, .val = 0x90 },
+- { .rfmax = 452000, .val = 0x91 },
+- { .rfmax = 453000, .val = 0x93 },
+- { .rfmax = 454000, .val = 0x94 },
+- { .rfmax = 456000, .val = 0x96 },
+- { .rfmax = 457000, .val = 0x98 },
+- { .rfmax = 461000, .val = 0x11 },
+- { .rfmax = 468000, .val = 0x12 },
+- { .rfmax = 472000, .val = 0x13 },
+- { .rfmax = 473000, .val = 0x14 },
+- { .rfmax = 474000, .val = 0x15 },
+- { .rfmax = 481000, .val = 0x16 },
+- { .rfmax = 486000, .val = 0x17 },
+- { .rfmax = 491000, .val = 0x18 },
+- { .rfmax = 498000, .val = 0x19 },
+- { .rfmax = 499000, .val = 0x1a },
+- { .rfmax = 501000, .val = 0x1b },
+- { .rfmax = 506000, .val = 0x1c },
+- { .rfmax = 511000, .val = 0x1d },
+- { .rfmax = 516000, .val = 0x1e },
+- { .rfmax = 520000, .val = 0x1f },
+- { .rfmax = 521000, .val = 0x20 },
+- { .rfmax = 525000, .val = 0x21 },
+- { .rfmax = 529000, .val = 0x22 },
+- { .rfmax = 533000, .val = 0x23 },
+- { .rfmax = 539000, .val = 0x24 },
+- { .rfmax = 541000, .val = 0x25 },
+- { .rfmax = 547000, .val = 0x26 },
+- { .rfmax = 549000, .val = 0x27 },
+- { .rfmax = 551000, .val = 0x28 },
+- { .rfmax = 556000, .val = 0x29 },
+- { .rfmax = 561000, .val = 0x2a },
+- { .rfmax = 563000, .val = 0x2b },
+- { .rfmax = 565000, .val = 0x2c },
+- { .rfmax = 569000, .val = 0x2d },
+- { .rfmax = 571000, .val = 0x2e },
+- { .rfmax = 577000, .val = 0x2f },
+- { .rfmax = 580000, .val = 0x30 },
+- { .rfmax = 582000, .val = 0x31 },
+- { .rfmax = 584000, .val = 0x32 },
+- { .rfmax = 588000, .val = 0x33 },
+- { .rfmax = 591000, .val = 0x34 },
+- { .rfmax = 596000, .val = 0x35 },
+- { .rfmax = 598000, .val = 0x36 },
+- { .rfmax = 603000, .val = 0x37 },
+- { .rfmax = 604000, .val = 0x38 },
+- { .rfmax = 606000, .val = 0x39 },
+- { .rfmax = 612000, .val = 0x3a },
+- { .rfmax = 615000, .val = 0x3b },
+- { .rfmax = 617000, .val = 0x3c },
+- { .rfmax = 621000, .val = 0x3d },
+- { .rfmax = 622000, .val = 0x3e },
+- { .rfmax = 625000, .val = 0x3f },
+- { .rfmax = 632000, .val = 0x40 },
+- { .rfmax = 633000, .val = 0x41 },
+- { .rfmax = 634000, .val = 0x42 },
+- { .rfmax = 642000, .val = 0x43 },
+- { .rfmax = 643000, .val = 0x44 },
+- { .rfmax = 647000, .val = 0x45 },
+- { .rfmax = 650000, .val = 0x46 },
+- { .rfmax = 652000, .val = 0x47 },
+- { .rfmax = 657000, .val = 0x48 },
+- { .rfmax = 661000, .val = 0x49 },
+- { .rfmax = 662000, .val = 0x4a },
+- { .rfmax = 665000, .val = 0x4b },
+- { .rfmax = 667000, .val = 0x4c },
+- { .rfmax = 670000, .val = 0x4d },
+- { .rfmax = 673000, .val = 0x4e },
+- { .rfmax = 676000, .val = 0x4f },
+- { .rfmax = 677000, .val = 0x50 },
+- { .rfmax = 681000, .val = 0x51 },
+- { .rfmax = 683000, .val = 0x52 },
+- { .rfmax = 686000, .val = 0x53 },
+- { .rfmax = 688000, .val = 0x54 },
+- { .rfmax = 689000, .val = 0x55 },
+- { .rfmax = 691000, .val = 0x56 },
+- { .rfmax = 695000, .val = 0x57 },
+- { .rfmax = 698000, .val = 0x58 },
+- { .rfmax = 703000, .val = 0x59 },
+- { .rfmax = 704000, .val = 0x5a },
+- { .rfmax = 705000, .val = 0x5b },
+- { .rfmax = 707000, .val = 0x5c },
+- { .rfmax = 710000, .val = 0x5d },
+- { .rfmax = 712000, .val = 0x5e },
+- { .rfmax = 717000, .val = 0x5f },
+- { .rfmax = 718000, .val = 0x60 },
+- { .rfmax = 721000, .val = 0x61 },
+- { .rfmax = 722000, .val = 0x62 },
+- { .rfmax = 723000, .val = 0x63 },
+- { .rfmax = 725000, .val = 0x64 },
+- { .rfmax = 727000, .val = 0x65 },
+- { .rfmax = 730000, .val = 0x66 },
+- { .rfmax = 732000, .val = 0x67 },
+- { .rfmax = 735000, .val = 0x68 },
+- { .rfmax = 740000, .val = 0x69 },
+- { .rfmax = 741000, .val = 0x6a },
+- { .rfmax = 742000, .val = 0x6b },
+- { .rfmax = 743000, .val = 0x6c },
+- { .rfmax = 745000, .val = 0x6d },
+- { .rfmax = 747000, .val = 0x6e },
+- { .rfmax = 748000, .val = 0x6f },
+- { .rfmax = 750000, .val = 0x70 },
+- { .rfmax = 752000, .val = 0x71 },
+- { .rfmax = 754000, .val = 0x72 },
+- { .rfmax = 757000, .val = 0x73 },
+- { .rfmax = 758000, .val = 0x74 },
+- { .rfmax = 760000, .val = 0x75 },
+- { .rfmax = 763000, .val = 0x76 },
+- { .rfmax = 764000, .val = 0x77 },
+- { .rfmax = 766000, .val = 0x78 },
+- { .rfmax = 767000, .val = 0x79 },
+- { .rfmax = 768000, .val = 0x7a },
+- { .rfmax = 773000, .val = 0x7b },
+- { .rfmax = 774000, .val = 0x7c },
+- { .rfmax = 776000, .val = 0x7d },
+- { .rfmax = 777000, .val = 0x7e },
+- { .rfmax = 778000, .val = 0x7f },
+- { .rfmax = 779000, .val = 0x80 },
+- { .rfmax = 781000, .val = 0x81 },
+- { .rfmax = 783000, .val = 0x82 },
+- { .rfmax = 784000, .val = 0x83 },
+- { .rfmax = 785000, .val = 0x84 },
+- { .rfmax = 786000, .val = 0x85 },
+- { .rfmax = 793000, .val = 0x86 },
+- { .rfmax = 794000, .val = 0x87 },
+- { .rfmax = 795000, .val = 0x88 },
+- { .rfmax = 797000, .val = 0x89 },
+- { .rfmax = 799000, .val = 0x8a },
+- { .rfmax = 801000, .val = 0x8b },
+- { .rfmax = 802000, .val = 0x8c },
+- { .rfmax = 803000, .val = 0x8d },
+- { .rfmax = 804000, .val = 0x8e },
+- { .rfmax = 810000, .val = 0x90 },
+- { .rfmax = 811000, .val = 0x91 },
+- { .rfmax = 812000, .val = 0x92 },
+- { .rfmax = 814000, .val = 0x93 },
+- { .rfmax = 816000, .val = 0x94 },
+- { .rfmax = 817000, .val = 0x96 },
+- { .rfmax = 818000, .val = 0x97 },
+- { .rfmax = 820000, .val = 0x98 },
+- { .rfmax = 821000, .val = 0x99 },
+- { .rfmax = 822000, .val = 0x9a },
+- { .rfmax = 828000, .val = 0x9b },
+- { .rfmax = 829000, .val = 0x9d },
+- { .rfmax = 830000, .val = 0x9f },
+- { .rfmax = 831000, .val = 0xa0 },
+- { .rfmax = 833000, .val = 0xa1 },
+- { .rfmax = 835000, .val = 0xa2 },
+- { .rfmax = 836000, .val = 0xa3 },
+- { .rfmax = 837000, .val = 0xa4 },
+- { .rfmax = 838000, .val = 0xa6 },
+- { .rfmax = 840000, .val = 0xa8 },
+- { .rfmax = 842000, .val = 0xa9 },
+- { .rfmax = 845000, .val = 0xaa },
+- { .rfmax = 846000, .val = 0xab },
+- { .rfmax = 847000, .val = 0xad },
+- { .rfmax = 848000, .val = 0xae },
+- { .rfmax = 852000, .val = 0xaf },
+- { .rfmax = 853000, .val = 0xb0 },
+- { .rfmax = 858000, .val = 0xb1 },
+- { .rfmax = 860000, .val = 0xb2 },
+- { .rfmax = 861000, .val = 0xb3 },
+- { .rfmax = 862000, .val = 0xb4 },
+- { .rfmax = 863000, .val = 0xb6 },
+- { .rfmax = 864000, .val = 0xb8 },
+- { .rfmax = 865000, .val = 0xb9 },
+- { .rfmax = 0, .val = 0x00 }, /* end */
+-};
+-
+-static struct tda18271_map tda18271_ir_measure[] = {
+- { .rfmax = 30000, .val = 4 },
+- { .rfmax = 200000, .val = 5 },
+- { .rfmax = 600000, .val = 6 },
+- { .rfmax = 865000, .val = 7 },
+- { .rfmax = 0, .val = 0 }, /* end */
+-};
+-
+-static struct tda18271_map tda18271_rf_cal_dc_over_dt[] = {
+- { .rfmax = 47900, .val = 0x00 },
+- { .rfmax = 55000, .val = 0x00 },
+- { .rfmax = 61100, .val = 0x0a },
+- { .rfmax = 64000, .val = 0x0a },
+- { .rfmax = 82000, .val = 0x14 },
+- { .rfmax = 84000, .val = 0x19 },
+- { .rfmax = 119000, .val = 0x1c },
+- { .rfmax = 124000, .val = 0x20 },
+- { .rfmax = 129000, .val = 0x2a },
+- { .rfmax = 134000, .val = 0x32 },
+- { .rfmax = 139000, .val = 0x39 },
+- { .rfmax = 144000, .val = 0x3e },
+- { .rfmax = 149000, .val = 0x3f },
+- { .rfmax = 152600, .val = 0x40 },
+- { .rfmax = 154000, .val = 0x40 },
+- { .rfmax = 164700, .val = 0x41 },
+- { .rfmax = 203500, .val = 0x32 },
+- { .rfmax = 353000, .val = 0x19 },
+- { .rfmax = 356000, .val = 0x1a },
+- { .rfmax = 359000, .val = 0x1b },
+- { .rfmax = 363000, .val = 0x1c },
+- { .rfmax = 366000, .val = 0x1d },
+- { .rfmax = 369000, .val = 0x1e },
+- { .rfmax = 373000, .val = 0x1f },
+- { .rfmax = 376000, .val = 0x20 },
+- { .rfmax = 379000, .val = 0x21 },
+- { .rfmax = 383000, .val = 0x22 },
+- { .rfmax = 386000, .val = 0x23 },
+- { .rfmax = 389000, .val = 0x24 },
+- { .rfmax = 393000, .val = 0x25 },
+- { .rfmax = 396000, .val = 0x26 },
+- { .rfmax = 399000, .val = 0x27 },
+- { .rfmax = 402000, .val = 0x28 },
+- { .rfmax = 404000, .val = 0x29 },
+- { .rfmax = 407000, .val = 0x2a },
+- { .rfmax = 409000, .val = 0x2b },
+- { .rfmax = 412000, .val = 0x2c },
+- { .rfmax = 414000, .val = 0x2d },
+- { .rfmax = 417000, .val = 0x2e },
+- { .rfmax = 419000, .val = 0x2f },
+- { .rfmax = 422000, .val = 0x30 },
+- { .rfmax = 424000, .val = 0x31 },
+- { .rfmax = 427000, .val = 0x32 },
+- { .rfmax = 429000, .val = 0x33 },
+- { .rfmax = 432000, .val = 0x34 },
+- { .rfmax = 434000, .val = 0x35 },
+- { .rfmax = 437000, .val = 0x36 },
+- { .rfmax = 439000, .val = 0x37 },
+- { .rfmax = 442000, .val = 0x38 },
+- { .rfmax = 444000, .val = 0x39 },
+- { .rfmax = 447000, .val = 0x3a },
+- { .rfmax = 449000, .val = 0x3b },
+- { .rfmax = 457800, .val = 0x3c },
+- { .rfmax = 465000, .val = 0x0f },
+- { .rfmax = 477000, .val = 0x12 },
+- { .rfmax = 483000, .val = 0x14 },
+- { .rfmax = 502000, .val = 0x19 },
+- { .rfmax = 508000, .val = 0x1b },
+- { .rfmax = 519000, .val = 0x1c },
+- { .rfmax = 522000, .val = 0x1d },
+- { .rfmax = 524000, .val = 0x1e },
+- { .rfmax = 534000, .val = 0x1f },
+- { .rfmax = 549000, .val = 0x20 },
+- { .rfmax = 554000, .val = 0x22 },
+- { .rfmax = 584000, .val = 0x24 },
+- { .rfmax = 589000, .val = 0x26 },
+- { .rfmax = 658000, .val = 0x27 },
+- { .rfmax = 664000, .val = 0x2c },
+- { .rfmax = 669000, .val = 0x2d },
+- { .rfmax = 699000, .val = 0x2e },
+- { .rfmax = 704000, .val = 0x30 },
+- { .rfmax = 709000, .val = 0x31 },
+- { .rfmax = 714000, .val = 0x32 },
+- { .rfmax = 724000, .val = 0x33 },
+- { .rfmax = 729000, .val = 0x36 },
+- { .rfmax = 739000, .val = 0x38 },
+- { .rfmax = 744000, .val = 0x39 },
+- { .rfmax = 749000, .val = 0x3b },
+- { .rfmax = 754000, .val = 0x3c },
+- { .rfmax = 759000, .val = 0x3d },
+- { .rfmax = 764000, .val = 0x3e },
+- { .rfmax = 769000, .val = 0x3f },
+- { .rfmax = 774000, .val = 0x40 },
+- { .rfmax = 779000, .val = 0x41 },
+- { .rfmax = 784000, .val = 0x43 },
+- { .rfmax = 789000, .val = 0x46 },
+- { .rfmax = 794000, .val = 0x48 },
+- { .rfmax = 799000, .val = 0x4b },
+- { .rfmax = 804000, .val = 0x4f },
+- { .rfmax = 809000, .val = 0x54 },
+- { .rfmax = 814000, .val = 0x59 },
+- { .rfmax = 819000, .val = 0x5d },
+- { .rfmax = 824000, .val = 0x61 },
+- { .rfmax = 829000, .val = 0x68 },
+- { .rfmax = 834000, .val = 0x6e },
+- { .rfmax = 839000, .val = 0x75 },
+- { .rfmax = 844000, .val = 0x7e },
+- { .rfmax = 849000, .val = 0x82 },
+- { .rfmax = 854000, .val = 0x84 },
+- { .rfmax = 859000, .val = 0x8f },
+- { .rfmax = 865000, .val = 0x9a },
+- { .rfmax = 0, .val = 0x00 }, /* end */
+-};
+-
+-/*---------------------------------------------------------------------*/
+-
+-struct tda18271_thermo_map {
+- u8 d;
+- u8 r0;
+- u8 r1;
+-};
+-
+-static struct tda18271_thermo_map tda18271_thermometer[] = {
+- { .d = 0x00, .r0 = 60, .r1 = 92 },
+- { .d = 0x01, .r0 = 62, .r1 = 94 },
+- { .d = 0x02, .r0 = 66, .r1 = 98 },
+- { .d = 0x03, .r0 = 64, .r1 = 96 },
+- { .d = 0x04, .r0 = 74, .r1 = 106 },
+- { .d = 0x05, .r0 = 72, .r1 = 104 },
+- { .d = 0x06, .r0 = 68, .r1 = 100 },
+- { .d = 0x07, .r0 = 70, .r1 = 102 },
+- { .d = 0x08, .r0 = 90, .r1 = 122 },
+- { .d = 0x09, .r0 = 88, .r1 = 120 },
+- { .d = 0x0a, .r0 = 84, .r1 = 116 },
+- { .d = 0x0b, .r0 = 86, .r1 = 118 },
+- { .d = 0x0c, .r0 = 76, .r1 = 108 },
+- { .d = 0x0d, .r0 = 78, .r1 = 110 },
+- { .d = 0x0e, .r0 = 82, .r1 = 114 },
+- { .d = 0x0f, .r0 = 80, .r1 = 112 },
+- { .d = 0x00, .r0 = 0, .r1 = 0 }, /* end */
+-};
+-
+-int tda18271_lookup_thermometer(struct dvb_frontend *fe)
-{
-- struct kcopyd_job *job;
+- struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+- int val, i = 0;
-
-- /*
-- * Allocate a new job.
-- */
-- job = mempool_alloc(_job_pool, GFP_NOIO);
+- while (tda18271_thermometer[i].d < (regs[R_TM] & 0x0f)) {
+- if (tda18271_thermometer[i + 1].d == 0)
+- break;
+- i++;
+- }
-
-- /*
-- * set up for the read.
-- */
-- job->kc = kc;
-- job->flags = flags;
-- job->read_err = 0;
-- job->write_err = 0;
-- job->rw = READ;
+- if ((regs[R_TM] & 0x20) == 0x20)
+- val = tda18271_thermometer[i].r1;
+- else
+- val = tda18271_thermometer[i].r0;
-
-- job->source = *from;
+- tda_map("(%d) tm = %d\n", i, val);
-
-- job->num_dests = num_dests;
-- memcpy(&job->dests, dests, sizeof(*dests) * num_dests);
+- return val;
+-}
-
-- job->offset = 0;
-- job->nr_pages = 0;
-- job->pages = NULL;
+-/*---------------------------------------------------------------------*/
-
-- job->fn = fn;
-- job->context = context;
+-struct tda18271_cid_target_map {
+- u32 rfmax;
+- u8 target;
+- u16 limit;
+-};
+-
+-static struct tda18271_cid_target_map tda18271_cid_target[] = {
+- { .rfmax = 46000, .target = 0x04, .limit = 1800 },
+- { .rfmax = 52200, .target = 0x0a, .limit = 1500 },
+- { .rfmax = 79100, .target = 0x01, .limit = 4000 },
+- { .rfmax = 136800, .target = 0x18, .limit = 4000 },
+- { .rfmax = 156700, .target = 0x18, .limit = 4000 },
+- { .rfmax = 156700, .target = 0x18, .limit = 4000 },
+- { .rfmax = 186250, .target = 0x0a, .limit = 4000 },
+- { .rfmax = 230000, .target = 0x0a, .limit = 4000 },
+- { .rfmax = 345000, .target = 0x18, .limit = 4000 },
+- { .rfmax = 426000, .target = 0x0e, .limit = 4000 },
+- { .rfmax = 489500, .target = 0x1e, .limit = 4000 },
+- { .rfmax = 697500, .target = 0x32, .limit = 4000 },
+- { .rfmax = 842000, .target = 0x3a, .limit = 4000 },
+- { .rfmax = 0, .target = 0x00, .limit = 0 }, /* end */
+-};
-
-- if (job->source.count < SUB_JOB_SIZE)
-- dispatch_job(job);
+-int tda18271_lookup_cid_target(struct dvb_frontend *fe,
+- u32 *freq, u8 *cid_target, u16 *count_limit)
+-{
+- int i = 0;
-
-- else {
-- mutex_init(&job->lock);
-- job->progress = 0;
-- split_job(job);
+- while ((tda18271_cid_target[i].rfmax * 1000) < *freq) {
+- if (tda18271_cid_target[i + 1].rfmax == 0)
+- break;
+- i++;
- }
+- *cid_target = tda18271_cid_target[i].target;
+- *count_limit = tda18271_cid_target[i].limit;
+-
+- tda_map("(%d) cid_target = %02x, count_limit = %d\n", i,
+- tda18271_cid_target[i].target, tda18271_cid_target[i].limit);
-
- 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 struct tda18271_rf_tracking_filter_cal tda18271_rf_band_template[] = {
+- { .rfmax = 47900, .rfband = 0x00,
+- .rf1_def = 46000, .rf2_def = 0, .rf3_def = 0 },
+- { .rfmax = 61100, .rfband = 0x01,
+- .rf1_def = 52200, .rf2_def = 0, .rf3_def = 0 },
+- { .rfmax = 152600, .rfband = 0x02,
+- .rf1_def = 70100, .rf2_def = 136800, .rf3_def = 0 },
+- { .rfmax = 164700, .rfband = 0x03,
+- .rf1_def = 156700, .rf2_def = 0, .rf3_def = 0 },
+- { .rfmax = 203500, .rfband = 0x04,
+- .rf1_def = 186250, .rf2_def = 0, .rf3_def = 0 },
+- { .rfmax = 457800, .rfband = 0x05,
+- .rf1_def = 230000, .rf2_def = 345000, .rf3_def = 426000 },
+- { .rfmax = 865000, .rfband = 0x06,
+- .rf1_def = 489500, .rf2_def = 697500, .rf3_def = 842000 },
+- { .rfmax = 0, .rfband = 0x00,
+- .rf1_def = 0, .rf2_def = 0, .rf3_def = 0 }, /* end */
+-};
-
--static void client_add(struct kcopyd_client *kc)
+-int tda18271_lookup_rf_band(struct dvb_frontend *fe, u32 *freq, u8 *rf_band)
-{
-- mutex_lock(&_client_lock);
-- list_add(&kc->list, &_clients);
-- mutex_unlock(&_client_lock);
--}
+- struct tda18271_priv *priv = fe->tuner_priv;
+- struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state;
+- int i = 0;
-
--static void client_del(struct kcopyd_client *kc)
--{
-- mutex_lock(&_client_lock);
-- list_del(&kc->list);
-- mutex_unlock(&_client_lock);
+- while ((map[i].rfmax * 1000) < *freq) {
+- if (tda18271_debug & DBG_ADV)
+- tda_map("(%d) rfmax = %d < freq = %d, "
+- "rf1_def = %d, rf2_def = %d, rf3_def = %d, "
+- "rf1 = %d, rf2 = %d, rf3 = %d, "
+- "rf_a1 = %d, rf_a2 = %d, "
+- "rf_b1 = %d, rf_b2 = %d\n",
+- i, map[i].rfmax * 1000, *freq,
+- map[i].rf1_def, map[i].rf2_def, map[i].rf3_def,
+- map[i].rf1, map[i].rf2, map[i].rf3,
+- map[i].rf_a1, map[i].rf_a2,
+- map[i].rf_b1, map[i].rf_b2);
+- if (map[i].rfmax == 0)
+- return -EINVAL;
+- i++;
+- }
+- if (rf_band)
+- *rf_band = map[i].rfband;
+-
+- tda_map("(%d) rf_band = %02x\n", i, map[i].rfband);
+-
+- return i;
-}
-
--static DEFINE_MUTEX(kcopyd_init_lock);
--static int kcopyd_clients = 0;
+-/*---------------------------------------------------------------------*/
-
--static int kcopyd_init(void)
+-struct tda18271_map_layout {
+- struct tda18271_pll_map *main_pll;
+- struct tda18271_pll_map *cal_pll;
+-
+- struct tda18271_map *rf_cal;
+- struct tda18271_map *rf_cal_kmco;
+- struct tda18271_map *rf_cal_dc_over_dt;
+-
+- struct tda18271_map *bp_filter;
+- struct tda18271_map *rf_band;
+- struct tda18271_map *gain_taper;
+- struct tda18271_map *ir_measure;
+-};
+-
+-/*---------------------------------------------------------------------*/
+-
+-int tda18271_lookup_pll_map(struct dvb_frontend *fe,
+- enum tda18271_map_type map_type,
+- u32 *freq, u8 *post_div, u8 *div)
-{
-- int r;
+- struct tda18271_priv *priv = fe->tuner_priv;
+- struct tda18271_pll_map *map = NULL;
+- unsigned int i = 0;
+- char *map_name;
+- int ret = 0;
-
-- mutex_lock(&kcopyd_init_lock);
+- BUG_ON(!priv->maps);
-
-- if (kcopyd_clients) {
-- /* Already initialized. */
-- kcopyd_clients++;
-- mutex_unlock(&kcopyd_init_lock);
-- return 0;
+- switch (map_type) {
+- case MAIN_PLL:
+- map = priv->maps->main_pll;
+- map_name = "main_pll";
+- break;
+- case CAL_PLL:
+- map = priv->maps->cal_pll;
+- map_name = "cal_pll";
+- break;
+- default:
+- /* we should never get here */
+- map_name = "undefined";
+- break;
- }
-
-- r = jobs_init();
-- if (r) {
-- mutex_unlock(&kcopyd_init_lock);
-- return r;
+- if (!map) {
+- tda_warn("%s map is not set!\n", map_name);
+- ret = -EINVAL;
+- goto fail;
- }
-
-- _kcopyd_wq = create_singlethread_workqueue("kcopyd");
-- if (!_kcopyd_wq) {
-- jobs_exit();
-- mutex_unlock(&kcopyd_init_lock);
-- return -ENOMEM;
+- while ((map[i].lomax * 1000) < *freq) {
+- if (map[i + 1].lomax == 0) {
+- tda_map("%s: frequency (%d) out of range\n",
+- map_name, *freq);
+- ret = -ERANGE;
+- break;
+- }
+- i++;
- }
+- *post_div = map[i].pd;
+- *div = map[i].d;
-
-- 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);
+- tda_map("(%d) %s: post div = 0x%02x, div = 0x%02x\n",
+- i, map_name, *post_div, *div);
+-fail:
+- return ret;
-}
-
--int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result)
+-int tda18271_lookup_map(struct dvb_frontend *fe,
+- enum tda18271_map_type map_type,
+- u32 *freq, u8 *val)
-{
-- int r = 0;
-- struct kcopyd_client *kc;
+- struct tda18271_priv *priv = fe->tuner_priv;
+- struct tda18271_map *map = NULL;
+- unsigned int i = 0;
+- char *map_name;
+- int ret = 0;
-
-- r = kcopyd_init();
-- if (r)
-- return r;
+- BUG_ON(!priv->maps);
-
-- kc = kmalloc(sizeof(*kc), GFP_KERNEL);
-- if (!kc) {
-- kcopyd_exit();
-- return -ENOMEM;
+- switch (map_type) {
+- case BP_FILTER:
+- map = priv->maps->bp_filter;
+- map_name = "bp_filter";
+- break;
+- case RF_CAL_KMCO:
+- map = priv->maps->rf_cal_kmco;
+- map_name = "km";
+- break;
+- case RF_BAND:
+- map = priv->maps->rf_band;
+- map_name = "rf_band";
+- break;
+- case GAIN_TAPER:
+- map = priv->maps->gain_taper;
+- map_name = "gain_taper";
+- break;
+- case RF_CAL:
+- map = priv->maps->rf_cal;
+- map_name = "rf_cal";
+- break;
+- case IR_MEASURE:
+- map = priv->maps->ir_measure;
+- map_name = "ir_measure";
+- break;
+- case RF_CAL_DC_OVER_DT:
+- map = priv->maps->rf_cal_dc_over_dt;
+- map_name = "rf_cal_dc_over_dt";
+- break;
+- default:
+- /* we should never get here */
+- map_name = "undefined";
+- break;
- }
-
-- 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;
+- if (!map) {
+- tda_warn("%s map is not set!\n", map_name);
+- ret = -EINVAL;
+- goto fail;
- }
-
-- 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;
+- while ((map[i].rfmax * 1000) < *freq) {
+- if (map[i + 1].rfmax == 0) {
+- tda_map("%s: frequency (%d) out of range\n",
+- map_name, *freq);
+- ret = -ERANGE;
+- break;
+- }
+- i++;
- }
+- *val = map[i].val;
-
-- init_waitqueue_head(&kc->destroyq);
-- atomic_set(&kc->nr_jobs, 0);
--
-- client_add(kc);
-- *result = kc;
-- return 0;
+- tda_map("(%d) %s: 0x%02x\n", i, map_name, *val);
+-fail:
+- return ret;
-}
-
--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();
--}
+-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 },
+-};
-
--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.
-- */
+-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 },
+-};
-
--#ifndef DM_KCOPYD_H
--#define DM_KCOPYD_H
+-/*---------------------------------------------------------------------*/
-
--#include "dm-io.h"
+-static struct tda18271_map_layout tda18271c1_map_layout = {
+- .main_pll = tda18271c1_main_pll,
+- .cal_pll = tda18271c1_cal_pll,
-
--/* FIXME: make this configurable */
--#define KCOPYD_MAX_REGIONS 8
+- .rf_cal = tda18271c1_rf_cal,
+- .rf_cal_kmco = tda18271c1_km,
-
--#define KCOPYD_IGNORE_ERROR 1
+- .bp_filter = tda18271_bp_filter,
+- .rf_band = tda18271_rf_band,
+- .gain_taper = tda18271_gain_taper,
+- .ir_measure = tda18271_ir_measure,
+-};
-
--/*
-- * 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);
+-static struct tda18271_map_layout tda18271c2_map_layout = {
+- .main_pll = tda18271c2_main_pll,
+- .cal_pll = tda18271c2_cal_pll,
+-
+- .rf_cal = tda18271c2_rf_cal,
+- .rf_cal_kmco = tda18271c2_km,
+-
+- .rf_cal_dc_over_dt = tda18271_rf_cal_dc_over_dt,
+-
+- .bp_filter = tda18271_bp_filter,
+- .rf_band = tda18271_rf_band,
+- .gain_taper = tda18271_gain_taper,
+- .ir_measure = tda18271_ir_measure,
+-};
+-
+-int tda18271_assign_map_layout(struct dvb_frontend *fe)
+-{
+- struct tda18271_priv *priv = fe->tuner_priv;
+- int ret = 0;
+-
+- switch (priv->id) {
+- case TDA18271HDC1:
+- priv->maps = &tda18271c1_map_layout;
+- memcpy(&priv->std, &tda18271c1_std_map,
+- sizeof(struct tda18271_std_map));
+- break;
+- case TDA18271HDC2:
+- priv->maps = &tda18271c2_map_layout;
+- memcpy(&priv->std, &tda18271c2_std_map,
+- sizeof(struct tda18271_std_map));
+- break;
+- default:
+- ret = -EINVAL;
+- break;
+- }
+- memcpy(priv->rf_cal_state, &tda18271_rf_band_template,
+- sizeof(tda18271_rf_band_template));
+-
+- return ret;
+-}
-
-/*
-- * 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
+- * Overrides for Emacs so that we follow Linus's tabbing style.
+- * ---------------------------------------------------------------------------
+- * Local variables:
+- * c-basic-offset: 8
+- * End:
- */
--typedef void (*kcopyd_notify_fn)(int read_err, unsigned long write_err,
-- void *context);
+diff --git a/drivers/media/dvb/frontends/tda18271.h b/drivers/media/dvb/frontends/tda18271.h
+deleted file mode 100644
+index 24b0e35..0000000
+--- a/drivers/media/dvb/frontends/tda18271.h
++++ /dev/null
+@@ -1,78 +0,0 @@
+-/*
+- tda18271.h - header for the Philips / NXP TDA18271 silicon tuner
-
--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);
+- Copyright (C) 2007, 2008 Michael Krufky <mkrufky at linuxtv.org>
-
--#endif
-diff --git a/drivers/md/md.c b/drivers/md/md.c
-index 61ccbd2..5ebfb4d 100644
---- a/drivers/md/md.c
-+++ b/drivers/md/md.c
-@@ -4152,7 +4152,7 @@ static int hot_remove_disk(mddev_t * mddev, dev_t dev)
-
- return 0;
- busy:
-- printk(KERN_WARNING "md: cannot remove active disk %s from %s ... \n",
-+ printk(KERN_WARNING "md: cannot remove active disk %s from %s ...\n",
- bdevname(rdev->bdev,b), mdname(mddev));
- return -EBUSY;
- }
-diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
-index 1195069..128bb9c 100644
---- a/drivers/media/Kconfig
-+++ b/drivers/media/Kconfig
-@@ -30,7 +30,7 @@ config VIDEO_V4L2_COMMON
- depends on (I2C || I2C=n) && VIDEO_DEV
- default (I2C || I2C=n) && VIDEO_DEV
-
--config VIDEO_V4L1
-+config VIDEO_ALLOW_V4L1
- bool "Enable Video For Linux API 1 (DEPRECATED)"
- depends on VIDEO_DEV && VIDEO_V4L2_COMMON
- default VIDEO_DEV && VIDEO_V4L2_COMMON
-@@ -59,10 +59,15 @@ config VIDEO_V4L1_COMPAT
- If you are unsure as to whether this is required, answer Y.
-
- config VIDEO_V4L2
-- bool
-+ tristate
- depends on VIDEO_DEV && VIDEO_V4L2_COMMON
- default VIDEO_DEV && VIDEO_V4L2_COMMON
-
-+config VIDEO_V4L1
-+ tristate
-+ depends on VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
-+ default VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
-+
- source "drivers/media/video/Kconfig"
-
- source "drivers/media/radio/Kconfig"
-@@ -155,7 +160,7 @@ config VIDEOBUF_GEN
- tristate
-
- config VIDEOBUF_DMA_SG
-- depends on PCI
-+ depends on HAS_DMA
- select VIDEOBUF_GEN
- tristate
-
-diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c
-index bb2a027..2665052 100644
---- a/drivers/media/common/ir-functions.c
-+++ b/drivers/media/common/ir-functions.c
-@@ -34,7 +34,7 @@ static int repeat = 1;
- module_param(repeat, int, 0444);
- MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)");
-
--static int debug = 0; /* debug level (0,1,2) */
-+static int debug; /* debug level (0,1,2) */
- module_param(debug, int, 0644);
-
- #define dprintk(level, fmt, arg...) if (debug >= level) \
-diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c
-index 2ab5a12..a348581 100644
---- a/drivers/media/common/ir-keymaps.c
-+++ b/drivers/media/common/ir-keymaps.c
-@@ -212,6 +212,51 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = {
-
- EXPORT_SYMBOL_GPL(ir_codes_pixelview);
-
-+/*
-+ Mauro Carvalho Chehab <mchehab at infradead.org>
-+ present on PV MPEG 8000GT
-+ */
-+IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE] = {
-+ [0x3c] = KEY_PAUSE, /* Timeshift */
-+ [0x12] = KEY_POWER,
-+
-+ [0x3d] = KEY_1,
-+ [0x38] = KEY_2,
-+ [0x18] = KEY_3,
-+ [0x35] = KEY_4,
-+ [0x39] = KEY_5,
-+ [0x15] = KEY_6,
-+ [0x36] = KEY_7,
-+ [0x3a] = KEY_8,
-+ [0x1e] = KEY_9,
-+ [0x3e] = KEY_0,
-+
-+ [0x1c] = KEY_AGAIN, /* LOOP */
-+ [0x3f] = KEY_MEDIA, /* Source */
-+ [0x1f] = KEY_LAST, /* +100 */
-+ [0x1b] = KEY_MUTE,
-+
-+ [0x17] = KEY_CHANNELDOWN,
-+ [0x16] = KEY_CHANNELUP,
-+ [0x10] = KEY_VOLUMEUP,
-+ [0x14] = KEY_VOLUMEDOWN,
-+ [0x13] = KEY_ZOOM,
-+
-+ [0x19] = KEY_SHUFFLE, /* SNAPSHOT */
-+ [0x1a] = KEY_SEARCH, /* scan */
-+
-+ [0x37] = KEY_REWIND, /* << */
-+ [0x32] = KEY_RECORD, /* o (red) */
-+ [0x33] = KEY_FORWARD, /* >> */
-+ [0x11] = KEY_STOP, /* square */
-+ [0x3b] = KEY_PLAY, /* > */
-+ [0x30] = KEY_PLAYPAUSE, /* || */
-+
-+ [0x31] = KEY_TV,
-+ [0x34] = KEY_RADIO,
-+};
-+EXPORT_SYMBOL_GPL(ir_codes_pixelview_new);
-+
- IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = {
- [ 0x00 ] = KEY_0,
- [ 0x01 ] = KEY_1,
-@@ -726,7 +771,11 @@ IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = {
- [ 0x12 ] = KEY_CHANNELUP, // Channel +
- [ 0x13 ] = KEY_CHANNELDOWN, // Channel -
- [ 0x06 ] = KEY_AGAIN, // Recall
-- [ 0x10 ] = KEY_ENTER, // Enter
-+ [ 0x10 ] = KEY_ENTER, // Enter
-+
-+ [ 0x19 ] = KEY_BACK, // Rewind ( <<< )
-+ [ 0x1f ] = KEY_FORWARD, // Forward ( >>> )
-+ [ 0x0a ] = KEY_ANGLE, // (no label, may be used as the PAUSE button)
- };
-
- EXPORT_SYMBOL_GPL(ir_codes_flyvideo);
-@@ -1157,7 +1206,8 @@ EXPORT_SYMBOL_GPL(ir_codes_purpletv);
-
- /* Mapping for the 28 key remote control as seen at
- http://www.sednacomputer.com/photo/cardbus-tv.jpg
-- Pavel Mihaylov <bin at bash.info> */
-+ Pavel Mihaylov <bin at bash.info>
-+ Also for the remote bundled with Kozumi KTV-01C card */
- IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = {
- [ 0x00 ] = KEY_0,
- [ 0x01 ] = KEY_1,
-@@ -1188,6 +1238,11 @@ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = {
- [ 0x1c ] = KEY_RADIO, /* FM Radio */
- [ 0x1d ] = KEY_RECORD,
- [ 0x1e ] = KEY_PAUSE,
-+ /* additional codes for Kozumi's remote */
-+ [0x14] = KEY_INFO, /* OSD */
-+ [0x16] = KEY_OK, /* OK */
-+ [0x17] = KEY_DIGITS, /* Plus */
-+ [0x1f] = KEY_PLAY, /* Play */
- };
-
- EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna);
-@@ -1988,6 +2043,76 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = {
-
- EXPORT_SYMBOL_GPL(ir_codes_behold);
-
-+/* Beholder Intl. Ltd. 2008
-+ * Dmitry Belimov d.belimov at google.com
-+ * Keytable is used by BeholdTV Columbus
-+ * The "ascii-art picture" below (in comments, first row
-+ * is the keycode in hex, and subsequent row(s) shows
-+ * the button labels (several variants when appropriate)
-+ * helps to descide which keycodes to assign to the buttons.
-+ */
-+IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = {
-+
-+ /* 0x13 0x11 0x1C 0x12 *
-+ * Mute Source TV/FM Power *
-+ * */
-+
-+ [0x13] = KEY_MUTE,
-+ [0x11] = KEY_PROPS,
-+ [0x1C] = KEY_TUNER, /* KEY_TV/KEY_RADIO */
-+ [0x12] = KEY_POWER,
-+
-+ /* 0x01 0x02 0x03 0x0D *
-+ * 1 2 3 Stereo *
-+ * *
-+ * 0x04 0x05 0x06 0x19 *
-+ * 4 5 6 Snapshot *
-+ * *
-+ * 0x07 0x08 0x09 0x10 *
-+ * 7 8 9 Zoom *
-+ * */
-+ [0x01] = KEY_1,
-+ [0x02] = KEY_2,
-+ [0x03] = KEY_3,
-+ [0x0D] = KEY_SETUP, /* Setup key */
-+ [0x04] = KEY_4,
-+ [0x05] = KEY_5,
-+ [0x06] = KEY_6,
-+ [0x19] = KEY_BOOKMARKS, /* Snapshot key */
-+ [0x07] = KEY_7,
-+ [0x08] = KEY_8,
-+ [0x09] = KEY_9,
-+ [0x10] = KEY_ZOOM,
-+
-+ /* 0x0A 0x00 0x0B 0x0C *
-+ * RECALL 0 ChannelUp VolumeUp *
-+ * */
-+ [0x0A] = KEY_AGAIN,
-+ [0x00] = KEY_0,
-+ [0x0B] = KEY_CHANNELUP,
-+ [0x0C] = KEY_VOLUMEUP,
-+
-+ /* 0x1B 0x1D 0x15 0x18 *
-+ * Timeshift Record ChannelDown VolumeDown *
-+ * */
-+
-+ [0x1B] = KEY_REWIND,
-+ [0x1D] = KEY_RECORD,
-+ [0x15] = KEY_CHANNELDOWN,
-+ [0x18] = KEY_VOLUMEDOWN,
-+
-+ /* 0x0E 0x1E 0x0F 0x1A *
-+ * Stop Pause Previouse Next *
-+ * */
-+
-+ [0x0E] = KEY_STOP,
-+ [0x1E] = KEY_PAUSE,
-+ [0x0F] = KEY_PREVIOUS,
-+ [0x1A] = KEY_NEXT,
-+
-+};
-+EXPORT_SYMBOL_GPL(ir_codes_behold_columbus);
-+
- /*
- * Remote control for the Genius TVGO A11MCE
- * Adrian Pardini <pardo.bsso at gmail.com>
-@@ -2033,3 +2158,46 @@ IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE] = {
- [0x50] = KEY_BLUE,
- };
- EXPORT_SYMBOL_GPL(ir_codes_genius_tvgo_a11mce);
-+
-+/*
-+ * Remote control for Powercolor Real Angel 330
-+ * Daniel Fraga <fragabr at gmail.com>
-+ */
-+IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = {
-+ [0x38] = KEY_SWITCHVIDEOMODE, /* switch inputs */
-+ [0x0c] = KEY_MEDIA, /* Turn ON/OFF App */
-+ [0x00] = KEY_0,
-+ [0x01] = KEY_1,
-+ [0x02] = KEY_2,
-+ [0x03] = KEY_3,
-+ [0x04] = KEY_4,
-+ [0x05] = KEY_5,
-+ [0x06] = KEY_6,
-+ [0x07] = KEY_7,
-+ [0x08] = KEY_8,
-+ [0x09] = KEY_9,
-+ [0x0a] = KEY_DIGITS, /* single, double, tripple digit */
-+ [0x29] = KEY_PREVIOUS, /* previous channel */
-+ [0x12] = KEY_BRIGHTNESSUP,
-+ [0x13] = KEY_BRIGHTNESSDOWN,
-+ [0x2b] = KEY_MODE, /* stereo/mono */
-+ [0x2c] = KEY_TEXT, /* teletext */
-+ [0x20] = KEY_UP, /* channel up */
-+ [0x21] = KEY_DOWN, /* channel down */
-+ [0x10] = KEY_RIGHT, /* volume up */
-+ [0x11] = KEY_LEFT, /* volume down */
-+ [0x0d] = KEY_MUTE,
-+ [0x1f] = KEY_RECORD,
-+ [0x17] = KEY_PLAY,
-+ [0x16] = KEY_PAUSE,
-+ [0x0b] = KEY_STOP,
-+ [0x27] = KEY_FASTFORWARD,
-+ [0x26] = KEY_REWIND,
-+ [0x1e] = KEY_SEARCH, /* autoscan */
-+ [0x0e] = KEY_SHUFFLE, /* snapshot */
-+ [0x2d] = KEY_SETUP,
-+ [0x0f] = KEY_SCREEN, /* full screen */
-+ [0x14] = KEY_RADIO, /* FM radio */
-+ [0x25] = KEY_POWER, /* power */
-+};
-+EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel);
-diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
-index 7707b8c..89c7660 100644
---- a/drivers/media/common/saa7146_core.c
-+++ b/drivers/media/common/saa7146_core.c
-@@ -74,7 +74,7 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
- if (err) {
- printk(KERN_ERR "%s: %s timed out while waiting for "
- "registers getting programmed\n",
-- dev->name, __FUNCTION__);
-+ dev->name, __func__);
- return -ETIMEDOUT;
- }
- msleep(1);
-@@ -89,7 +89,7 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
- saa7146_read(dev, MC2);
- if (err) {
- DEB_S(("%s: %s timed out while waiting for transfer "
-- "completion\n", dev->name, __FUNCTION__));
-+ "completion\n", dev->name, __func__));
- return -ETIMEDOUT;
- }
- msleep(1);
-@@ -111,7 +111,7 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
- if (!loops--) {
- printk(KERN_ERR "%s: %s timed out while waiting for "
- "registers getting programmed\n",
-- dev->name, __FUNCTION__);
-+ dev->name, __func__);
- return -ETIMEDOUT;
- }
- udelay(1);
-@@ -125,7 +125,7 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
- saa7146_read(dev, MC2);
- if (!loops--) {
- DEB_S(("%s: %s timed out while waiting for transfer "
-- "completion\n", dev->name, __FUNCTION__));
-+ "completion\n", dev->name, __func__));
- return -ETIMEDOUT;
- }
- udelay(5);
-diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
-index 7e7689a..35b01ec 100644
---- a/drivers/media/common/saa7146_i2c.c
-+++ b/drivers/media/common/saa7146_i2c.c
-@@ -203,7 +203,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
- return -ERESTARTSYS;
-
- printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n",
-- dev->name, __FUNCTION__);
-+ dev->name, __func__);
- return -EIO;
- }
- status = saa7146_read(dev, I2C_STATUS);
-@@ -221,7 +221,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
- }
- if (time_after(jiffies,timeout)) {
- printk(KERN_WARNING "%s %s: timed out waiting for MC2\n",
-- dev->name, __FUNCTION__);
-+ dev->name, __func__);
- return -EIO;
- }
- }
-@@ -238,7 +238,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
- * (no answer from nonexisistant device...)
- */
- printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n",
-- dev->name, __FUNCTION__);
-+ dev->name, __func__);
- return -EIO;
- }
- if (++trial < 50 && short_delay)
-diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c
-index bfbd5a8..74e2b56 100644
---- a/drivers/media/common/saa7146_vbi.c
-+++ b/drivers/media/common/saa7146_vbi.c
-@@ -407,8 +407,8 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
- fh->vbi_fmt.start[1] = 312;
- fh->vbi_fmt.count[1] = 16;
-
-- videobuf_queue_pci_init(&fh->vbi_q, &vbi_qops,
-- dev->pci, &dev->slock,
-+ videobuf_queue_sg_init(&fh->vbi_q, &vbi_qops,
-+ &dev->pci->dev, &dev->slock,
- V4L2_BUF_TYPE_VBI_CAPTURE,
- V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
- sizeof(struct saa7146_buf),
-diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
-index 66fdbd0..3cbc6eb 100644
---- a/drivers/media/common/saa7146_video.c
-+++ b/drivers/media/common/saa7146_video.c
-@@ -1410,8 +1410,8 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
- sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
- fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;
-
-- videobuf_queue_pci_init(&fh->video_q, &video_qops,
-- dev->pci, &dev->slock,
-+ videobuf_queue_sg_init(&fh->video_q, &video_qops,
-+ &dev->pci->dev, &dev->slock,
- V4L2_BUF_TYPE_VIDEO_CAPTURE,
- V4L2_FIELD_INTERLACED,
- sizeof(struct saa7146_buf),
-diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
-index 3197aeb..6ec5afb 100644
---- a/drivers/media/dvb/b2c2/Kconfig
-+++ b/drivers/media/dvb/b2c2/Kconfig
-@@ -9,6 +9,11 @@ config DVB_B2C2_FLEXCOP
- select DVB_STV0297 if !DVB_FE_CUSTOMISE
- select DVB_BCM3510 if !DVB_FE_CUSTOMISE
- select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-+ select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
-+ select DVB_S5H1420 if !DVB_FE_CUSTOMISE
-+ select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE
-+ select DVB_ISL6421 if !DVB_FE_CUSTOMISE
-+ select DVB_CX24123 if !DVB_FE_CUSTOMISE
- help
- Support for the digital TV receiver chip made by B2C2 Inc. included in
- Technisats PCI cards and USB boxes.
-diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile
-index e97ff60..870e284 100644
---- a/drivers/media/dvb/b2c2/Makefile
-+++ b/drivers/media/dvb/b2c2/Makefile
-@@ -2,6 +2,7 @@ b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \
- flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o
- obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
-
-+
- ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),)
- b2c2-flexcop-objs += flexcop-dma.o
- endif
-@@ -13,3 +14,4 @@ b2c2-flexcop-usb-objs = flexcop-usb.o
- obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
-
- EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
-+EXTRA_CFLAGS += -Idrivers/media/video/
-diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h
-index 5a6c4fe..8ce0633 100644
---- a/drivers/media/dvb/b2c2/flexcop-common.h
-+++ b/drivers/media/dvb/b2c2/flexcop-common.h
-@@ -44,6 +44,14 @@ struct flexcop_dma {
- u32 size; /* size of each address in bytes */
- };
-
-+struct flexcop_i2c_adapter {
-+ struct flexcop_device *fc;
-+ struct i2c_adapter i2c_adap;
-+
-+ u8 no_base_addr;
-+ flexcop_i2c_port_t port;
-+};
-+
- /* Control structure for data definitions that are common to
- * the B2C2-based PCI and USB devices.
- */
-@@ -72,7 +80,7 @@ struct flexcop_device {
- struct dmx_frontend mem_frontend;
- int (*fe_sleep) (struct dvb_frontend *);
-
-- struct i2c_adapter i2c_adap;
-+ struct flexcop_i2c_adapter fc_i2c_adap[3];
- struct mutex i2c_mutex;
- struct module *owner;
-
-@@ -87,7 +95,8 @@ struct flexcop_device {
- int (*write_ibi_reg) (struct flexcop_device *, flexcop_ibi_register, flexcop_ibi_value);
-
-
-- int (*i2c_request) (struct flexcop_device*, flexcop_access_op_t, flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
-+ int (*i2c_request) (struct flexcop_i2c_adapter*,
-+ flexcop_access_op_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
- int (*stream_control) (struct flexcop_device*, int);
-
- int (*get_mac_addr) (struct flexcop_device *fc, int extended);
-@@ -128,8 +137,8 @@ int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended);
- * one. We have it in flexcop-i2c.c, because it is going via the actual
- * I2C-channel of the flexcop.
- */
--int flexcop_i2c_request(struct flexcop_device*, flexcop_access_op_t,
-- flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
-+int flexcop_i2c_request(struct flexcop_i2c_adapter*, flexcop_access_op_t,
-+ u8 chipaddr, u8 addr, u8 *buf, u16 len);
-
- /* from flexcop-sram.c */
- int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target);
-diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c
-index 6f592bc..a91ed28 100644
---- a/drivers/media/dvb/b2c2/flexcop-dma.c
-+++ b/drivers/media/dvb/b2c2/flexcop-dma.c
-@@ -112,7 +112,7 @@ static int flexcop_dma_remap(struct flexcop_device *fc,
- {
- flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c;
- flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
-- deb_info("%s\n",__FUNCTION__);
-+ deb_info("%s\n",__func__);
- v.dma_0xc.remap_enable = onoff;
- fc->write_ibi_reg(fc,r,v);
- return 0;
-@@ -162,7 +162,7 @@ int flexcop_dma_config_timer(struct flexcop_device *fc,
-
- flexcop_dma_remap(fc,dma_idx,0);
-
-- deb_info("%s\n",__FUNCTION__);
-+ deb_info("%s\n",__func__);
- v.dma_0x4_write.dmatimer = cycles;
- fc->write_ibi_reg(fc,r,v);
- return 0;
-diff --git a/drivers/media/dvb/b2c2/flexcop-eeprom.c b/drivers/media/dvb/b2c2/flexcop-eeprom.c
-index bbcf070..8a8ae8a 100644
---- a/drivers/media/dvb/b2c2/flexcop-eeprom.c
-+++ b/drivers/media/dvb/b2c2/flexcop-eeprom.c
-@@ -114,15 +114,18 @@ static int flexcop_eeprom_request(struct flexcop_device *fc, flexcop_access_op_t
- {
- int i,ret = 0;
- u8 chipaddr = 0x50 | ((addr >> 8) & 3);
-- for (i = 0; i < retries; i++)
-- if ((ret = fc->i2c_request(fc,op,FC_I2C_PORT_EEPROM,chipaddr,addr & 0xff,buf,len)) == 0)
-+ for (i = 0; i < retries; i++) {
-+ ret = fc->i2c_request(&fc->fc_i2c_adap[1], op, chipaddr,
-+ addr & 0xff, buf, len);
-+ if (ret == 0)
- break;
-+ }
- return ret;
- }
-
- static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len, int retries)
- {
-- int ret = flexcop_eeprom_request(fc,FC_READ,addr,buf,len,retries);
-+ int ret = flexcop_eeprom_request(fc, FC_READ, addr, buf, len, retries);
- if (ret == 0)
- if (calc_lrc(buf, len - 1) != buf[len - 1])
- ret = -EINVAL;
-diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
-index 0378fd6..7b0ea3b 100644
---- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
-+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
-@@ -5,6 +5,8 @@
- *
- * see flexcop.c for copyright information.
- */
-+#include <media/tuner.h>
-+
- #include "flexcop.h"
-
- #include "stv0299.h"
-@@ -15,6 +17,15 @@
- #include "mt312.h"
- #include "lgdt330x.h"
- #include "dvb-pll.h"
-+#include "tuner-simple.h"
-+
-+#include "s5h1420.h"
-+#include "itd1000.h"
-+
-+#include "cx24123.h"
-+#include "cx24113.h"
-+
-+#include "isl6421.h"
-
- /* lnb control */
-
-@@ -180,13 +191,13 @@ static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dv
- buf[2] = 0x84; /* 0xC4 */
- buf[3] = 0x08;
-
-- if (params->frequency < 1500000) buf[3] |= 0x10;
-+ if (params->frequency < 1500000)
-+ buf[3] |= 0x10;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-- if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) {
-+ if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
- return -EIO;
-- }
- return 0;
- }
-
-@@ -241,7 +252,7 @@ static struct stv0299_config samsung_tbmu24112_config = {
- .mclk = 88000000UL,
- .invert = 0,
- .skip_reinit = 0,
-- .lock_output = STV0229_LOCKOUTPUT_LK,
-+ .lock_output = STV0299_LOCKOUTPUT_LK,
- .volt13_op0_op1 = STV0299_VOLT13_OP1,
- .min_delay_ms = 100,
- .set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
-@@ -337,7 +348,7 @@ static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe,
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-- if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
-+ if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
- return -EIO;
- return 0;
- }
-@@ -386,10 +397,11 @@ static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
- deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]);
-- ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_TUNER, 0x61, buf[0], &buf[1], 3);
-+ ret = fc->i2c_request(&fc->fc_i2c_adap[2],
-+ FC_WRITE, 0x61, buf[0], &buf[1], 3);
- deb_tuner("tuner write returned: %d\n",ret);
-
-- return 0;
-+ return ret;
- }
-
- static u8 alps_tdee4_stv0297_inittab[] = {
-@@ -472,56 +484,159 @@ static struct stv0297_config alps_tdee4_stv0297_config = {
- // .pll_set = alps_tdee4_stv0297_pll_set,
- };
-
-+
-+/* SkyStar2 rev2.7 (a/u) */
-+static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
-+ .demod_address = 0x53,
-+ .invert = 1,
-+ .repeated_start_workaround = 1,
-+};
-+
-+static struct itd1000_config skystar2_rev2_7_itd1000_config = {
-+ .i2c_address = 0x61,
-+};
-+
-+/* SkyStar2 rev2.8 */
-+static struct cx24123_config skystar2_rev2_8_cx24123_config = {
-+ .demod_address = 0x55,
-+ .dont_use_pll = 1,
-+ .agc_callback = cx24113_agc_callback,
-+};
-+
-+static const struct cx24113_config skystar2_rev2_8_cx24113_config = {
-+ .i2c_addr = 0x54,
-+ .xtal_khz = 10111,
-+};
-+
- /* try to figure out the frontend, each card/box can have on of the following list */
- int flexcop_frontend_init(struct flexcop_device *fc)
- {
- struct dvb_frontend_ops *ops;
-+ struct i2c_adapter *i2c = &fc->fc_i2c_adap[0].i2c_adap;
-+ struct i2c_adapter *i2c_tuner;
-+
-+ /* enable no_base_addr - no repeated start when reading */
-+ fc->fc_i2c_adap[0].no_base_addr = 1;
-+ fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config, i2c);
-+ if (fc->fe != NULL) {
-+ flexcop_ibi_value r108;
-+ i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe);
-+ ops = &fc->fe->ops;
-+
-+ fc->fe_sleep = ops->sleep;
-+ ops->sleep = flexcop_sleep;
-+
-+ fc->dev_type = FC_SKY_REV27;
-+
-+ /* enable no_base_addr - no repeated start when reading */
-+ fc->fc_i2c_adap[2].no_base_addr = 1;
-+ if (dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, 0x08, 1, 1) == NULL)
-+ err("ISL6421 could NOT be attached");
-+ else
-+ info("ISL6421 successfully attached");
-+
-+ /* the ITD1000 requires a lower i2c clock - it slows down the stuff for everyone - but is it a problem ? */
-+ r108.raw = 0x00000506;
-+ fc->write_ibi_reg(fc, tw_sm_c_108, r108);
-+ if (i2c_tuner) {
-+ if (dvb_attach(itd1000_attach, fc->fe, i2c_tuner, &skystar2_rev2_7_itd1000_config) == NULL)
-+ err("ITD1000 could NOT be attached");
-+ else
-+ info("ITD1000 successfully attached");
-+ }
-+ goto fe_found;
-+ }
-+ fc->fc_i2c_adap[0].no_base_addr = 0; /* for the next devices we need it again */
-+
-+ /* try the sky v2.8 (cx24123, isl6421) */
-+ fc->fe = dvb_attach(cx24123_attach,
-+ &skystar2_rev2_8_cx24123_config, i2c);
-+ if (fc->fe != NULL) {
-+ i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);
-+ if (i2c_tuner != NULL) {
-+ if (dvb_attach(cx24113_attach, fc->fe,
-+ &skystar2_rev2_8_cx24113_config,
-+ i2c_tuner) == NULL)
-+ err("CX24113 could NOT be attached");
-+ else
-+ info("CX24113 successfully attached");
-+ }
-+
-+ fc->dev_type = FC_SKY_REV28;
-+
-+ fc->fc_i2c_adap[2].no_base_addr = 1;
-+ if (dvb_attach(isl6421_attach, fc->fe,
-+ &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0) == NULL)
-+ err("ISL6421 could NOT be attached");
-+ else
-+ info("ISL6421 successfully attached");
-+
-+ /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an
-+ * IR-receiver (PIC16F818) - but the card has no input for
-+ * that ??? */
-+
-+ goto fe_found;
-+ }
-
- /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
-- if ((fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
-+ fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c);
-+ if (fc->fe != NULL) {
- ops = &fc->fe->ops;
-
- ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
-
- ops->set_voltage = flexcop_set_voltage;
-
-- fc->fe_sleep = ops->sleep;
-- ops->sleep = flexcop_sleep;
-+ fc->fe_sleep = ops->sleep;
-+ ops->sleep = flexcop_sleep;
-+
-+ fc->dev_type = FC_SKY;
-+ goto fe_found;
-+ }
-
-- fc->dev_type = FC_SKY;
-- info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
-- } else
- /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
-- if ((fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
-- fc->dev_type = FC_AIR_DVB;
-+ fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
-+ if (fc->fe != NULL) {
-+ fc->dev_type = FC_AIR_DVB;
- fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
-- info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
-- } else
-+ goto fe_found;
-+ }
-+
- /* try the air atsc 2nd generation (nxt2002) */
-- if ((fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
-- fc->dev_type = FC_AIR_ATSC2;
-+ fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c);
-+ if (fc->fe != NULL) {
-+ fc->dev_type = FC_AIR_ATSC2;
- dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, DVB_PLL_SAMSUNG_TBMV);
-- info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
-- } else
-- /* try the air atsc 3nd generation (lgdt3303) */
-- if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
-- fc->dev_type = FC_AIR_ATSC3;
-- dvb_attach(dvb_pll_attach, fc->fe, 0x61, &fc->i2c_adap, DVB_PLL_LG_TDVS_H06XF);
-- info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
-- } else
-+ goto fe_found;
-+ }
-+
-+ fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c);
-+ if (fc->fe != NULL) {
-+ fc->dev_type = FC_AIR_ATSC3;
-+ dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
-+ TUNER_LG_TDVS_H06XF);
-+ goto fe_found;
-+ }
-+
- /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
-- if ((fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
-- fc->dev_type = FC_AIR_ATSC1;
-- info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
-- } else
-+ fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
-+ if (fc->fe != NULL) {
-+ fc->dev_type = FC_AIR_ATSC1;
-+ goto fe_found;
-+ }
-+
- /* try the cable dvb (stv0297) */
-- if ((fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
-- fc->dev_type = FC_CABLE;
-+ fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c);
-+ if (fc->fe != NULL) {
-+ fc->dev_type = FC_CABLE;
- fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
-- info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
-- } else
-+ goto fe_found;
-+ }
-+
- /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
-- if ((fc->fe = dvb_attach(vp310_mt312_attach, &skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
-+ fc->fe = dvb_attach(vp310_mt312_attach,
-+ &skystar23_samsung_tbdu18132_config, i2c);
-+ if (fc->fe != NULL) {
- ops = &fc->fe->ops;
-
- ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
-@@ -535,19 +650,21 @@ int flexcop_frontend_init(struct flexcop_device *fc)
- ops->sleep = flexcop_sleep;
-
- fc->dev_type = FC_SKY_OLD;
-- info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address);
-+ goto fe_found;
- }
-
-- if (fc->fe == NULL) {
-- err("no frontend driver found for this B2C2/FlexCop adapter");
-- return -ENODEV;
-- } else {
-- if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
-- err("frontend registration failed!");
-- dvb_frontend_detach(fc->fe);
-- fc->fe = NULL;
-- return -EINVAL;
-- }
-+ err("no frontend driver found for this B2C2/FlexCop adapter");
-+ return -ENODEV;
-+
-+fe_found:
-+ info("found '%s' .", fc->fe->ops.info.name);
-+ if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
-+ err("frontend registration failed!");
-+ ops = &fc->fe->ops;
-+ if (ops->release != NULL)
-+ ops->release(fc->fe);
-+ fc->fe = NULL;
-+ return -EINVAL;
- }
- fc->init_state |= FC_STATE_FE_INIT;
- return 0;
-diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c
-index 6bf858a..55973ea 100644
---- a/drivers/media/dvb/b2c2/flexcop-i2c.c
-+++ b/drivers/media/dvb/b2c2/flexcop-i2c.c
-@@ -9,6 +9,8 @@
-
- #define FC_MAX_I2C_RETRIES 100000
-
-+/* #define DUMP_I2C_MESSAGES */
-+
- static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100)
- {
- int i;
-@@ -38,30 +40,25 @@ static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r
- return -EREMOTEIO;
- }
-
--static int flexcop_i2c_read4(struct flexcop_device *fc, flexcop_ibi_value r100, u8 *buf)
-+static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c,
-+ flexcop_ibi_value r100, u8 *buf)
- {
- flexcop_ibi_value r104;
- int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */
- ret;
-
-- if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
-- /* The Cablestar needs a different kind of i2c-transfer (does not
-- * support "Repeat Start"):
-- * wait for the ACK failure,
-- * and do a subsequent read with the Bit 30 enabled
-- */
-- r100.tw_sm_c_100.no_base_addr_ack_error = 1;
-- if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
-- deb_i2c("no_base_addr read failed. %d\n",ret);
-- return ret;
-- }
-+ r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr;
-+ ret = flexcop_i2c_operation(i2c->fc, &r100);
-+ if (ret != 0) {
-+ deb_i2c("read failed. %d\n", ret);
-+ return ret;
- }
-
- buf[0] = r100.tw_sm_c_100.data1_reg;
-
- if (len > 0) {
-- r104 = fc->read_ibi_reg(fc,tw_sm_c_104);
-- deb_i2c("read: r100: %08x, r104: %08x\n",r100.raw,r104.raw);
-+ r104 = i2c->fc->read_ibi_reg(i2c->fc, tw_sm_c_104);
-+ deb_i2c("read: r100: %08x, r104: %08x\n", r100.raw, r104.raw);
-
- /* there is at least one more byte, otherwise we wouldn't be here */
- buf[1] = r104.tw_sm_c_104.data2_reg;
-@@ -85,17 +82,22 @@ static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100,
- r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0;
- r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0;
-
-- deb_i2c("write: r100: %08x, r104: %08x\n",r100.raw,r104.raw);
-+ deb_i2c("write: r100: %08x, r104: %08x\n", r100.raw, r104.raw);
-
- /* write the additional i2c data before doing the actual i2c operation */
-- fc->write_ibi_reg(fc,tw_sm_c_104,r104);
-- return flexcop_i2c_operation(fc,&r100);
-+ fc->write_ibi_reg(fc, tw_sm_c_104, r104);
-+ return flexcop_i2c_operation(fc, &r100);
- }
-
--int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
-- flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len)
-+int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
-+ flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
- {
- int ret;
-+
-+#ifdef DUMP_I2C_MESSAGES
-+ int i;
-+#endif
-+
- u16 bytes_to_transfer;
- flexcop_ibi_value r100;
-
-@@ -103,7 +105,25 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
- r100.raw = 0;
- r100.tw_sm_c_100.chipaddr = chipaddr;
- r100.tw_sm_c_100.twoWS_rw = op;
-- r100.tw_sm_c_100.twoWS_port_reg = port;
-+ r100.tw_sm_c_100.twoWS_port_reg = i2c->port;
-+
-+#ifdef DUMP_I2C_MESSAGES
-+ printk(KERN_DEBUG "%d ", i2c->port);
-+ if (op == FC_READ)
-+ printk("rd(");
-+ else
-+ printk("wr(");
-+
-+ printk("%02x): %02x ", chipaddr, addr);
-+#endif
-+
-+ /* in that case addr is the only value ->
-+ * we write it twice as baseaddr and val0
-+ * BBTI is doing it like that for ISL6421 at least */
-+ if (i2c->no_base_addr && len == 0 && op == FC_WRITE) {
-+ buf = &addr;
-+ len = 1;
-+ }
-
- while (len != 0) {
- bytes_to_transfer = len > 4 ? 4 : len;
-@@ -112,9 +132,14 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
- r100.tw_sm_c_100.baseaddr = addr;
-
- if (op == FC_READ)
-- ret = flexcop_i2c_read4(fc, r100, buf);
-+ ret = flexcop_i2c_read4(i2c, r100, buf);
- else
-- ret = flexcop_i2c_write4(fc,r100, buf);
-+ ret = flexcop_i2c_write4(i2c->fc, r100, buf);
-+
-+#ifdef DUMP_I2C_MESSAGES
-+ for (i = 0; i < bytes_to_transfer; i++)
-+ printk("%02x ", buf[i]);
-+#endif
-
- if (ret < 0)
- return ret;
-@@ -122,7 +147,11 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
- buf += bytes_to_transfer;
- addr += bytes_to_transfer;
- len -= bytes_to_transfer;
-- };
-+ }
-+
-+#ifdef DUMP_I2C_MESSAGES
-+ printk("\n");
-+#endif
-
- return 0;
- }
-@@ -132,7 +161,7 @@ EXPORT_SYMBOL(flexcop_i2c_request);
- /* master xfer callback for demodulator */
- static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
- {
-- struct flexcop_device *fc = i2c_get_adapdata(i2c_adap);
-+ struct flexcop_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap);
- int i, ret = 0;
-
- /* Some drivers use 1 byte or 0 byte reads as probes, which this
-@@ -142,34 +171,29 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs
- if (num == 1 && msgs[0].flags == I2C_M_RD && msgs[0].len <= 1)
- return 1;
-
-- if (mutex_lock_interruptible(&fc->i2c_mutex))
-+ if (mutex_lock_interruptible(&i2c->fc->i2c_mutex))
- return -ERESTARTSYS;
-
-- /* reading */
-- if (num == 2 &&
-- msgs[0].flags == 0 &&
-- msgs[1].flags == I2C_M_RD &&
-- msgs[0].buf != NULL &&
-- msgs[1].buf != NULL) {
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2 of the License, or
+- (at your option) any later version.
-
-- ret = fc->i2c_request(fc, FC_READ, FC_I2C_PORT_DEMOD, msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len);
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
-
-- } 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;
- }
+- You 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.
+-*/
-
-- 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;
+-#ifndef __TDA18271_H__
+-#define __TDA18271_H__
-
-- 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));
+-#include <linux/i2c.h>
+-#include "dvb_frontend.h"
-
-- 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;
- }
+-struct tda18271_std_map_item {
+- u16 if_freq;
+- u8 std_bits;
+-};
+-
+-struct tda18271_std_map {
+- struct tda18271_std_map_item fm_radio;
+- struct tda18271_std_map_item atv_b;
+- struct tda18271_std_map_item atv_dk;
+- struct tda18271_std_map_item atv_gh;
+- struct tda18271_std_map_item atv_i;
+- struct tda18271_std_map_item atv_l;
+- struct tda18271_std_map_item atv_lc;
+- struct tda18271_std_map_item atv_mn;
+- struct tda18271_std_map_item atsc_6;
+- struct tda18271_std_map_item dvbt_6;
+- struct tda18271_std_map_item dvbt_7;
+- struct tda18271_std_map_item dvbt_8;
+- struct tda18271_std_map_item qam_6;
+- struct tda18271_std_map_item qam_8;
+-};
+-
+-enum tda18271_i2c_gate {
+- TDA18271_GATE_AUTO = 0,
+- TDA18271_GATE_ANALOG,
+- TDA18271_GATE_DIGITAL,
+-};
+-
+-struct tda18271_config {
+- /* override default if freq / std settings (optional) */
+- struct tda18271_std_map *std_map;
+-
+- /* use i2c gate provided by analog or digital demod */
+- enum tda18271_i2c_gate gate;
+-};
+-
+-#if defined(CONFIG_DVB_TDA18271) || (defined(CONFIG_DVB_TDA18271_MODULE) && defined(MODULE))
+-extern struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
+- struct i2c_adapter *i2c,
+- struct tda18271_config *cfg);
+-#else
+-static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe,
+- u8 addr,
+- struct i2c_adapter *i2c,
+- struct tda18271_config *cfg)
+-{
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+- return NULL;
+-}
+-#endif
+-
+-#endif /* __TDA18271_H__ */
+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)
- 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);
-+ }
+ if (ret != 1)
+ dprintk ("%s: writereg error (reg %02x, ret == %i)\n",
+- __FUNCTION__, reg, ret);
++ __func__, reg, ret);
- fc->init_state &= ~FC_STATE_I2C_INIT;
+ return (ret != 1) ? -1 : 0;
}
-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;
+@@ -83,7 +83,7 @@ static int tda8083_readregs (struct tda8083_state* state, u8 reg1, u8 *b, u8 len
-- ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
-+ ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
- }
+ if (ret != 2)
+ dprintk ("%s: readreg error (reg %02x, ret == %i)\n",
+- __FUNCTION__, reg1, ret);
++ __func__, reg1, ret);
- /* return value is never used? */
-@@ -257,7 +257,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
+ 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)
{
- 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);
+- 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 @@
-- dprintk("%s: sram size = 64K\n", __FUNCTION__);
-+ dprintk("%s: sram size = 64K\n", __func__);
+ #include "tda826x.h"
- return 64;
- }
-@@ -381,7 +381,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
- sram_init(adapter);
- write_reg_dw(adapter, 0x208, tmp);
+-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: sram size = 32K\n", __FUNCTION__);
-+ dprintk("%s: sram size = 32K\n", __func__);
+- dprintk("%s:\n", __FUNCTION__);
++ dprintk("%s:\n", __func__);
- return 32;
+ 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__);
}
-@@ -390,7 +390,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
- sram_init(adapter);
- write_reg_dw(adapter, 0x208, tmp);
+ 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: SRAM detection failed. Set to 32K \n", __FUNCTION__);
-+ dprintk("%s: SRAM detection failed. Set to 32K \n", __func__);
+- dprintk("%s:\n", __FUNCTION__);
++ dprintk("%s:\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
+ div = (params->frequency + (1000-1)) / 1000;
- /* 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;
++ /* 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__);
}
-- wValue = (func << 8 ) | (port << 4);
-+ wValue = (func << 8) | (i2c->port << 4);
- wIndex = (chipaddr << 8 ) | addr;
+ 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;
- 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);
- }
+- dprintk("%s:\n", __FUNCTION__);
++ dprintk("%s:\n", __func__);
--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 (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)
{
- 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);
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
}
-
- 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)
- {
+ #endif // CONFIG_DVB_TDA826X
+diff --git a/drivers/media/dvb/frontends/tda827x.c b/drivers/media/dvb/frontends/tda827x.c
+deleted file mode 100644
+index 229b119..0000000
+--- a/drivers/media/dvb/frontends/tda827x.c
++++ /dev/null
+@@ -1,849 +0,0 @@
+-/*
+- *
+- * (c) 2005 Hartmut Hackmann
+- * (c) 2007 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, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#include <linux/module.h>
+-#include <asm/types.h>
+-#include <linux/dvb/frontend.h>
+-#include <linux/videodev2.h>
+-
+-#include "tda827x.h"
+-
+-static int debug = 0;
+-module_param(debug, int, 0644);
+-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+-
+-#define dprintk(args...) \
+- do { \
+- if (debug) printk(KERN_DEBUG "tda827x: " args); \
+- } while (0)
+-
+-struct tda827x_priv {
+- int i2c_addr;
+- struct i2c_adapter *i2c_adap;
+- struct tda827x_config *cfg;
+-
+- unsigned int sgIF;
+- unsigned char lpsel;
+-
+- u32 frequency;
+- u32 bandwidth;
+-};
+-
+-static void tda827x_set_std(struct dvb_frontend *fe,
+- struct analog_parameters *params)
+-{
+- struct tda827x_priv *priv = fe->tuner_priv;
+- char *mode;
+-
+- priv->lpsel = 0;
+- if (params->std & V4L2_STD_MN) {
+- priv->sgIF = 92;
+- priv->lpsel = 1;
+- mode = "MN";
+- } else if (params->std & V4L2_STD_B) {
+- priv->sgIF = 108;
+- mode = "B";
+- } else if (params->std & V4L2_STD_GH) {
+- priv->sgIF = 124;
+- mode = "GH";
+- } else if (params->std & V4L2_STD_PAL_I) {
+- priv->sgIF = 124;
+- mode = "I";
+- } else if (params->std & V4L2_STD_DK) {
+- priv->sgIF = 124;
+- mode = "DK";
+- } else if (params->std & V4L2_STD_SECAM_L) {
+- priv->sgIF = 124;
+- mode = "L";
+- } else if (params->std & V4L2_STD_SECAM_LC) {
+- priv->sgIF = 20;
+- mode = "LC";
+- } else {
+- priv->sgIF = 124;
+- mode = "xx";
+- }
+-
+- if (params->mode == V4L2_TUNER_RADIO)
+- priv->sgIF = 88; /* if frequency is 5.5 MHz */
+-
+- dprintk("setting tda827x to system %s\n", mode);
+-}
+-
+-
+-/* ------------------------------------------------------------------ */
+-
+-struct tda827x_data {
+- u32 lomax;
+- u8 spd;
+- u8 bs;
+- u8 bp;
+- u8 cp;
+- u8 gc3;
+- u8 div1p5;
+-};
+-
+-static const struct tda827x_data tda827x_table[] = {
+- { .lomax = 62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
+- { .lomax = 66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
+- { .lomax = 76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
+- { .lomax = 84000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
+- { .lomax = 93000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
+- { .lomax = 98000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
+- { .lomax = 109000000, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
+- { .lomax = 123000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
+- { .lomax = 133000000, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
+- { .lomax = 151000000, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
+- { .lomax = 154000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
+- { .lomax = 181000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0},
+- { .lomax = 185000000, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
+- { .lomax = 217000000, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
+- { .lomax = 244000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
+- { .lomax = 265000000, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
+- { .lomax = 302000000, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
+- { .lomax = 324000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
+- { .lomax = 370000000, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
+- { .lomax = 454000000, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
+- { .lomax = 493000000, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
+- { .lomax = 530000000, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
+- { .lomax = 554000000, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
+- { .lomax = 604000000, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
+- { .lomax = 696000000, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
+- { .lomax = 740000000, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
+- { .lomax = 820000000, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
+- { .lomax = 865000000, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
+- { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0}
+-};
+-
+-static int tda827xo_set_params(struct dvb_frontend *fe,
+- struct dvb_frontend_parameters *params)
+-{
+- struct tda827x_priv *priv = fe->tuner_priv;
+- u8 buf[14];
+-
+- struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
+- .buf = buf, .len = sizeof(buf) };
+- int i, tuner_freq, if_freq;
+- u32 N;
+-
+- dprintk("%s:\n", __FUNCTION__);
+- switch (params->u.ofdm.bandwidth) {
+- case BANDWIDTH_6_MHZ:
+- if_freq = 4000000;
+- break;
+- case BANDWIDTH_7_MHZ:
+- if_freq = 4500000;
+- break;
+- default: /* 8 MHz or Auto */
+- if_freq = 5000000;
+- break;
+- }
+- tuner_freq = params->frequency + if_freq;
+-
+- i = 0;
+- while (tda827x_table[i].lomax < tuner_freq) {
+- if (tda827x_table[i + 1].lomax == 0)
+- break;
+- i++;
+- }
+-
+- N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2);
+- buf[0] = 0;
+- buf[1] = (N>>8) | 0x40;
+- buf[2] = N & 0xff;
+- buf[3] = 0;
+- buf[4] = 0x52;
+- buf[5] = (tda827x_table[i].spd << 6) + (tda827x_table[i].div1p5 << 5) +
+- (tda827x_table[i].bs << 3) +
+- tda827x_table[i].bp;
+- buf[6] = (tda827x_table[i].gc3 << 4) + 0x8f;
+- buf[7] = 0xbf;
+- buf[8] = 0x2a;
+- buf[9] = 0x05;
+- buf[10] = 0xff;
+- buf[11] = 0x00;
+- buf[12] = 0x00;
+- buf[13] = 0x40;
+-
+- msg.len = 14;
+- if (fe->ops.i2c_gate_ctrl)
+- 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);
+- return -EIO;
+- }
+- msleep(500);
+- /* correct CP value */
+- buf[0] = 0x30;
+- buf[1] = 0x50 + tda827x_table[i].cp;
+- msg.len = 2;
+-
+- if (fe->ops.i2c_gate_ctrl)
+- fe->ops.i2c_gate_ctrl(fe, 1);
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- priv->frequency = tuner_freq - if_freq; // FIXME
+- priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+-
+- return 0;
+-}
+-
+-static int tda827xo_sleep(struct dvb_frontend *fe)
+-{
+- struct tda827x_priv *priv = fe->tuner_priv;
+- static u8 buf[] = { 0x30, 0xd0 };
+- 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 (priv->cfg && priv->cfg->sleep)
+- priv->cfg->sleep(fe);
+-
+- return 0;
+-}
+-
+-/* ------------------------------------------------------------------ */
+-
+-static int tda827xo_set_analog_params(struct dvb_frontend *fe,
+- struct analog_parameters *params)
+-{
+- unsigned char tuner_reg[8];
+- unsigned char reg2[2];
+- u32 N;
+- int i;
+- struct tda827x_priv *priv = fe->tuner_priv;
+- struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0 };
+- unsigned int freq = params->frequency;
+-
+- tda827x_set_std(fe, params);
+-
+- if (params->mode == V4L2_TUNER_RADIO)
+- freq = freq / 1000;
+-
+- N = freq + priv->sgIF;
+-
+- i = 0;
+- while (tda827x_table[i].lomax < N * 62500) {
+- if (tda827x_table[i + 1].lomax == 0)
+- break;
+- i++;
+- }
+-
+- N = N << tda827x_table[i].spd;
+-
+- tuner_reg[0] = 0;
+- tuner_reg[1] = (unsigned char)(N>>8);
+- tuner_reg[2] = (unsigned char) N;
+- tuner_reg[3] = 0x40;
+- tuner_reg[4] = 0x52 + (priv->lpsel << 5);
+- tuner_reg[5] = (tda827x_table[i].spd << 6) +
+- (tda827x_table[i].div1p5 << 5) +
+- (tda827x_table[i].bs << 3) + tda827x_table[i].bp;
+- tuner_reg[6] = 0x8f + (tda827x_table[i].gc3 << 4);
+- tuner_reg[7] = 0x8f;
+-
+- msg.buf = tuner_reg;
+- msg.len = 8;
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- msg.buf = reg2;
+- msg.len = 2;
+- reg2[0] = 0x80;
+- reg2[1] = 0;
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- reg2[0] = 0x60;
+- reg2[1] = 0xbf;
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- reg2[0] = 0x30;
+- reg2[1] = tuner_reg[4] + 0x80;
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- msleep(1);
+- reg2[0] = 0x30;
+- reg2[1] = tuner_reg[4] + 4;
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- msleep(1);
+- reg2[0] = 0x30;
+- reg2[1] = tuner_reg[4];
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- msleep(550);
+- reg2[0] = 0x30;
+- reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_table[i].cp;
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- reg2[0] = 0x60;
+- reg2[1] = 0x3f;
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- reg2[0] = 0x80;
+- reg2[1] = 0x08; /* Vsync en */
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- priv->frequency = freq * 62500;
+-
+- return 0;
+-}
+-
+-static void tda827xo_agcf(struct dvb_frontend *fe)
+-{
+- struct tda827x_priv *priv = fe->tuner_priv;
+- unsigned char data[] = { 0x80, 0x0c };
+- struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
+- .buf = data, .len = 2};
+-
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-}
+-
+-/* ------------------------------------------------------------------ */
+-
+-struct tda827xa_data {
+- u32 lomax;
+- u8 svco;
+- u8 spd;
+- u8 scr;
+- u8 sbs;
+- u8 gc3;
+-};
+-
+-static const struct tda827xa_data tda827xa_dvbt[] = {
+- { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1},
+- { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
+- { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
+- { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
+- { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
+- { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
+- { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
+- { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
+- { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
+- { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
+- { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
+- { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
+- { .lomax = 290000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
+- { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
+- { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
+- { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
+- { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
+- { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
+- { .lomax = 550000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
+- { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
+- { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
+- { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
+- { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
+- { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
+- { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
+- { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
+- { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
+-};
+-
+-static struct tda827xa_data tda827xa_analog[] = {
+- { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3},
+- { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
+- { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
+- { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
+- { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
+- { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
+- { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
+- { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
+- { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
+- { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
+- { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3},
+- { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3},
+- { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
+- { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
+- { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
+- { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
+- { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
+- { .lomax = 554000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
+- { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
+- { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
+- { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
+- { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
+- { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
+- { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
+- { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
+- { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
+-};
+-
+-static int tda827xa_set_params(struct dvb_frontend *fe,
+- struct dvb_frontend_parameters *params)
+-{
+- struct tda827x_priv *priv = fe->tuner_priv;
+- u8 buf[11];
+-
+- struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
+- .buf = buf, .len = sizeof(buf) };
+-
+- 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);
+- msleep(20);
+-
+- switch (params->u.ofdm.bandwidth) {
+- case BANDWIDTH_6_MHZ:
+- if_freq = 4000000;
+- break;
+- case BANDWIDTH_7_MHZ:
+- if_freq = 4500000;
+- break;
+- default: /* 8 MHz or Auto */
+- if_freq = 5000000;
+- break;
+- }
+- tuner_freq = params->frequency + if_freq;
+-
+- i = 0;
+- while (tda827xa_dvbt[i].lomax < tuner_freq) {
+- if(tda827xa_dvbt[i + 1].lomax == 0)
+- break;
+- i++;
+- }
+-
+- N = ((tuner_freq + 31250) / 62500) << tda827xa_dvbt[i].spd;
+- buf[0] = 0; // subaddress
+- buf[1] = N >> 8;
+- buf[2] = N & 0xff;
+- buf[3] = 0;
+- buf[4] = 0x16;
+- buf[5] = (tda827xa_dvbt[i].spd << 5) + (tda827xa_dvbt[i].svco << 3) +
+- tda827xa_dvbt[i].sbs;
+- buf[6] = 0x4b + (tda827xa_dvbt[i].gc3 << 4);
+- buf[7] = 0x1c;
+- buf[8] = 0x06;
+- buf[9] = 0x24;
+- buf[10] = 0x00;
+- msg.len = 11;
+- if (fe->ops.i2c_gate_ctrl)
+- 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);
+- return -EIO;
+- }
+- buf[0] = 0x90;
+- buf[1] = 0xff;
+- buf[2] = 0x60;
+- buf[3] = 0x00;
+- buf[4] = 0x59; // lpsel, for 6MHz + 2
+- msg.len = 5;
+- if (fe->ops.i2c_gate_ctrl)
+- fe->ops.i2c_gate_ctrl(fe, 1);
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- buf[0] = 0xa0;
+- buf[1] = 0x40;
+- msg.len = 2;
+- if (fe->ops.i2c_gate_ctrl)
+- fe->ops.i2c_gate_ctrl(fe, 1);
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- msleep(11);
+- msg.flags = I2C_M_RD;
+- if (fe->ops.i2c_gate_ctrl)
+- fe->ops.i2c_gate_ctrl(fe, 1);
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+- msg.flags = 0;
+-
+- 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);
+- buf[0] = 0x60;
+- buf[1] = 0x0c;
+- if (fe->ops.i2c_gate_ctrl)
+- fe->ops.i2c_gate_ctrl(fe, 1);
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+- }
+-
+- buf[0] = 0xc0;
+- buf[1] = 0x99; // lpsel, for 6MHz + 2
+- if (fe->ops.i2c_gate_ctrl)
+- fe->ops.i2c_gate_ctrl(fe, 1);
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- buf[0] = 0x60;
+- buf[1] = 0x3c;
+- if (fe->ops.i2c_gate_ctrl)
+- fe->ops.i2c_gate_ctrl(fe, 1);
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- /* correct CP value */
+- buf[0] = 0x30;
+- buf[1] = 0x10 + tda827xa_dvbt[i].scr;
+- if (fe->ops.i2c_gate_ctrl)
+- fe->ops.i2c_gate_ctrl(fe, 1);
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- msleep(163);
+- buf[0] = 0xc0;
+- buf[1] = 0x39; // lpsel, for 6MHz + 2
+- if (fe->ops.i2c_gate_ctrl)
+- fe->ops.i2c_gate_ctrl(fe, 1);
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- msleep(3);
+- /* freeze AGC1 */
+- buf[0] = 0x50;
+- buf[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4);
+- if (fe->ops.i2c_gate_ctrl)
+- fe->ops.i2c_gate_ctrl(fe, 1);
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- priv->frequency = tuner_freq - if_freq; // FIXME
+- priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+-
+- 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)
+-{
+- unsigned char tuner_reg[11];
+- u32 N;
+- int i;
+- struct tda827x_priv *priv = fe->tuner_priv;
+- struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
+- .buf = tuner_reg, .len = sizeof(tuner_reg) };
+- unsigned int freq = params->frequency;
+-
+- tda827x_set_std(fe, params);
+-
+- tda827xa_lna_gain(fe, 1, params);
+- msleep(10);
+-
+- if (params->mode == V4L2_TUNER_RADIO)
+- freq = freq / 1000;
+-
+- N = freq + priv->sgIF;
+-
+- i = 0;
+- while (tda827xa_analog[i].lomax < N * 62500) {
+- if (tda827xa_analog[i + 1].lomax == 0)
+- break;
+- i++;
+- }
+-
+- N = N << tda827xa_analog[i].spd;
+-
+- tuner_reg[0] = 0;
+- tuner_reg[1] = (unsigned char)(N>>8);
+- tuner_reg[2] = (unsigned char) N;
+- tuner_reg[3] = 0;
+- tuner_reg[4] = 0x16;
+- tuner_reg[5] = (tda827xa_analog[i].spd << 5) +
+- (tda827xa_analog[i].svco << 3) +
+- tda827xa_analog[i].sbs;
+- tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4);
+- tuner_reg[7] = 0x1c;
+- tuner_reg[8] = 4;
+- tuner_reg[9] = 0x20;
+- tuner_reg[10] = 0x00;
+- msg.len = 11;
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- tuner_reg[0] = 0x90;
+- tuner_reg[1] = 0xff;
+- tuner_reg[2] = 0xe0;
+- tuner_reg[3] = 0;
+- tuner_reg[4] = 0x99 + (priv->lpsel << 1);
+- msg.len = 5;
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- tuner_reg[0] = 0xa0;
+- tuner_reg[1] = 0xc0;
+- msg.len = 2;
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- tuner_reg[0] = 0x30;
+- tuner_reg[1] = 0x10 + tda827xa_analog[i].scr;
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- msg.flags = I2C_M_RD;
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+- msg.flags = 0;
+- tuner_reg[1] >>= 4;
+- dprintk("AGC2 gain is: %d\n", tuner_reg[1]);
+- if (tuner_reg[1] < 1)
+- tda827xa_lna_gain(fe, 0, params);
+-
+- msleep(100);
+- tuner_reg[0] = 0x60;
+- tuner_reg[1] = 0x3c;
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- msleep(163);
+- tuner_reg[0] = 0x50;
+- tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4);
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- tuner_reg[0] = 0x80;
+- tuner_reg[1] = 0x28;
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- tuner_reg[0] = 0xb0;
+- tuner_reg[1] = 0x01;
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- tuner_reg[0] = 0xc0;
+- tuner_reg[1] = 0x19 + (priv->lpsel << 1);
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- priv->frequency = freq * 62500;
+-
+- return 0;
+-}
+-
+-static void tda827xa_agcf(struct dvb_frontend *fe)
+-{
+- struct tda827x_priv *priv = fe->tuner_priv;
+- unsigned char data[] = {0x80, 0x2c};
+- struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0,
+- .buf = data, .len = 2};
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-}
+-
+-/* ------------------------------------------------------------------ */
+-
+-static int tda827x_release(struct dvb_frontend *fe)
+-{
+- kfree(fe->tuner_priv);
+- fe->tuner_priv = NULL;
+- return 0;
+-}
+-
+-static int tda827x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+-{
+- struct tda827x_priv *priv = fe->tuner_priv;
+- *frequency = priv->frequency;
+- return 0;
+-}
+-
+-static int tda827x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+-{
+- struct tda827x_priv *priv = fe->tuner_priv;
+- *bandwidth = priv->bandwidth;
+- return 0;
+-}
+-
+-static int tda827x_init(struct dvb_frontend *fe)
+-{
+- struct tda827x_priv *priv = fe->tuner_priv;
+- dprintk("%s:\n", __FUNCTION__);
+- if (priv->cfg && priv->cfg->init)
+- priv->cfg->init(fe);
+-
+- return 0;
+-}
+-
+-static int tda827x_probe_version(struct dvb_frontend *fe);
+-
+-static int tda827x_initial_init(struct dvb_frontend *fe)
+-{
- 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");
-
+- ret = tda827x_probe_version(fe);
+- if (ret)
+- return ret;
+- return fe->ops.tuner_ops.init(fe);
+-}
-
-- if ((ret = flexcop_i2c_init(fc)))
-- goto error;
+-static int tda827x_initial_sleep(struct dvb_frontend *fe)
+-{
+- int ret;
+- ret = tda827x_probe_version(fe);
+- if (ret)
+- return ret;
+- return fe->ops.tuner_ops.sleep(fe);
+-}
-
- 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);
+-static struct dvb_tuner_ops tda827xo_tuner_ops = {
+- .info = {
+- .name = "Philips TDA827X",
+- .frequency_min = 55000000,
+- .frequency_max = 860000000,
+- .frequency_step = 250000
+- },
+- .release = tda827x_release,
+- .init = tda827x_initial_init,
+- .sleep = tda827x_initial_sleep,
+- .set_params = tda827xo_set_params,
+- .set_analog_params = tda827xo_set_analog_params,
+- .get_frequency = tda827x_get_frequency,
+- .get_bandwidth = tda827x_get_bandwidth,
+-};
+-
+-static struct dvb_tuner_ops tda827xa_tuner_ops = {
+- .info = {
+- .name = "Philips TDA827XA",
+- .frequency_min = 44000000,
+- .frequency_max = 906000000,
+- .frequency_step = 62500
+- },
+- .release = tda827x_release,
+- .init = tda827x_init,
+- .sleep = tda827xa_sleep,
+- .set_params = tda827xa_set_params,
+- .set_analog_params = tda827xa_set_analog_params,
+- .get_frequency = tda827x_get_frequency,
+- .get_bandwidth = tda827x_get_bandwidth,
+-};
+-
+-static int tda827x_probe_version(struct dvb_frontend *fe)
+-{ u8 data;
+- struct tda827x_priv *priv = fe->tuner_priv;
+- struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = I2C_M_RD,
+- .buf = &data, .len = 1 };
+- if (fe->ops.i2c_gate_ctrl)
+- 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);
+- return -EIO;
- }
-+ 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 ((data & 0x3c) == 0) {
+- dprintk("tda827x tuner found\n");
+- fe->ops.tuner_ops.init = tda827x_init;
+- fe->ops.tuner_ops.sleep = tda827xo_sleep;
+- if (priv->cfg)
+- priv->cfg->agcf = tda827xo_agcf;
+- } else {
+- dprintk("tda827xa tuner found\n");
+- memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops));
+- if (priv->cfg)
+- priv->cfg->agcf = tda827xa_agcf;
+- }
+- return 0;
+-}
-
-- 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);
+-struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr,
+- struct i2c_adapter *i2c,
+- struct tda827x_config *cfg)
+-{
+- struct tda827x_priv *priv = NULL;
+-
+- dprintk("%s:\n", __FUNCTION__);
+- priv = kzalloc(sizeof(struct tda827x_priv), GFP_KERNEL);
+- if (priv == NULL)
+- return NULL;
+-
+- priv->i2c_addr = addr;
+- priv->i2c_adap = i2c;
+- priv->cfg = cfg;
+- memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops));
+- fe->tuner_priv = priv;
+-
+- dprintk("type set to %s\n", fe->ops.tuner_ops.info.name);
+-
+- return fe;
+-}
+-EXPORT_SYMBOL_GPL(tda827x_attach);
+-
+-MODULE_DESCRIPTION("DVB TDA827x driver");
+-MODULE_AUTHOR("Hartmut Hackmann <hartmut.hackmann at t-online.de>");
+-MODULE_AUTHOR("Michael Krufky <mkrufky at linuxtv.org>");
+-MODULE_LICENSE("GPL");
+-
+-/*
+- * Overrides for Emacs so that we follow Linus's tabbing style.
+- * ---------------------------------------------------------------------------
+- * Local variables:
+- * c-basic-offset: 8
+- * End:
+- */
+diff --git a/drivers/media/dvb/frontends/tda827x.h b/drivers/media/dvb/frontends/tda827x.h
+deleted file mode 100644
+index 92eb65b..0000000
+--- a/drivers/media/dvb/frontends/tda827x.h
++++ /dev/null
+@@ -1,69 +0,0 @@
+- /*
+- DVB Driver for Philips tda827x / tda827xa Silicon tuners
+-
+- (c) 2005 Hartmut Hackmann
+- (c) 2007 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, or
+- (at your option) any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-
+- GNU General Public License for more details.
+-
+- You 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 __DVB_TDA827X_H__
+-#define __DVB_TDA827X_H__
+-
+-#include <linux/i2c.h>
+-#include "dvb_frontend.h"
+-
+-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;
+- int (*tuner_callback) (void *dev, int command, int arg);
+-
+- void (*agcf)(struct dvb_frontend *fe);
+-};
+-
+-
+-/**
+- * Attach a tda827x tuner to the supplied frontend structure.
+- *
+- * @param fe Frontend to attach to.
+- * @param addr i2c address of the tuner.
+- * @param i2c i2c adapter to use.
+- * @param cfg optional callback function pointers.
+- * @return FE pointer on success, NULL on failure.
+- */
+-#if defined(CONFIG_DVB_TDA827X) || (defined(CONFIG_DVB_TDA827X_MODULE) && defined(MODULE))
+-extern struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe, int addr,
+- struct i2c_adapter *i2c,
+- struct tda827x_config *cfg);
+-#else
+-static inline struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe,
+- int addr,
+- struct i2c_adapter *i2c,
+- struct tda827x_config *cfg)
+-{
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+- return NULL;
+-}
+-#endif // CONFIG_DVB_TDA827X
+-
+-#endif // __DVB_TDA827X_H__
+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__);
}
-
-- 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)
+ 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)
{
- 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;
+- 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)
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
+ 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)
- // 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__);
+ if (ret != 2)
+ printk("ves1820: %s(): readreg error (reg == 0x%02x, "
+- "ret == %i)\n", __FUNCTION__, reg, ret);
++ "ret == %i)\n", __func__, reg, ret);
- 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)
+ 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;
+ };
-- 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__);
+-static int debug = 0;
++static int debug;
+ #define dprintk if (debug) printk
- 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;
+ #define DEMOD_VES1893 0
+@@ -98,7 +98,7 @@ static int ves1x93_writereg (struct ves1x93_state* state, u8 reg, u8 data)
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;
+ 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;
}
-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;
+@@ -179,7 +179,7 @@ static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate)
+ u32 tmp;
+ u32 FIN;
-- dprintk ("%s\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
+- dprintk("%s: srate == %d\n", __FUNCTION__, (unsigned int) srate);
++ dprintk("%s: srate == %d\n", __func__, (unsigned int) srate);
- 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
- };
+ 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\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
+- dprintk("%s: init chip\n", __FUNCTION__);
++ dprintk("%s: init chip\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)
+ 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)
{
- 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;
+- 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
+deleted file mode 100644
+index f642ca2..0000000
+--- a/drivers/media/dvb/frontends/xc5000.c
++++ /dev/null
+@@ -1,964 +0,0 @@
+-/*
+- * Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
+- *
+- * Copyright (c) 2007 Xceive Corporation
+- * Copyright (c) 2007 Steven Toth <stoth at hauppauge.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- *
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/moduleparam.h>
+-#include <linux/videodev2.h>
+-#include <linux/delay.h>
+-#include <linux/dvb/frontend.h>
+-#include <linux/i2c.h>
+-
+-#include "dvb_frontend.h"
+-
+-#include "xc5000.h"
+-#include "xc5000_priv.h"
+-
+-static int debug;
+-module_param(debug, int, 0644);
+-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+-
+-#define dprintk(level,fmt, arg...) if (debug >= level) \
+- printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
+-
+-#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw"
+-#define XC5000_DEFAULT_FIRMWARE_SIZE 12332
+-
+-/* Misc Defines */
+-#define MAX_TV_STANDARD 23
+-#define XC_MAX_I2C_WRITE_LENGTH 64
+-
+-/* Signal Types */
+-#define XC_RF_MODE_AIR 0
+-#define XC_RF_MODE_CABLE 1
+-
+-/* Result codes */
+-#define XC_RESULT_SUCCESS 0
+-#define XC_RESULT_RESET_FAILURE 1
+-#define XC_RESULT_I2C_WRITE_FAILURE 2
+-#define XC_RESULT_I2C_READ_FAILURE 3
+-#define XC_RESULT_OUT_OF_RANGE 5
+-
+-/* Product id */
+-#define XC_PRODUCT_ID_FW_NOT_LOADED 0x2000
+-#define XC_PRODUCT_ID_FW_LOADED 0x1388
+-
+-/* Registers */
+-#define XREG_INIT 0x00
+-#define XREG_VIDEO_MODE 0x01
+-#define XREG_AUDIO_MODE 0x02
+-#define XREG_RF_FREQ 0x03
+-#define XREG_D_CODE 0x04
+-#define XREG_IF_OUT 0x05
+-#define XREG_SEEK_MODE 0x07
+-#define XREG_POWER_DOWN 0x0A
+-#define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */
+-#define XREG_SMOOTHEDCVBS 0x0E
+-#define XREG_XTALFREQ 0x0F
+-#define XREG_FINERFFREQ 0x10
+-#define XREG_DDIMODE 0x11
+-
+-#define XREG_ADC_ENV 0x00
+-#define XREG_QUALITY 0x01
+-#define XREG_FRAME_LINES 0x02
+-#define XREG_HSYNC_FREQ 0x03
+-#define XREG_LOCK 0x04
+-#define XREG_FREQ_ERROR 0x05
+-#define XREG_SNR 0x06
+-#define XREG_VERSION 0x07
+-#define XREG_PRODUCT_ID 0x08
+-#define XREG_BUSY 0x09
+-
+-/*
+- Basic firmware description. This will remain with
+- the driver for documentation purposes.
+-
+- This represents an I2C firmware file encoded as a
+- string of unsigned char. Format is as follows:
+-
+- char[0 ]=len0_MSB -> len = len_MSB * 256 + len_LSB
+- char[1 ]=len0_LSB -> length of first write transaction
+- char[2 ]=data0 -> first byte to be sent
+- char[3 ]=data1
+- char[4 ]=data2
+- char[ ]=...
+- char[M ]=dataN -> last byte to be sent
+- char[M+1]=len1_MSB -> len = len_MSB * 256 + len_LSB
+- char[M+2]=len1_LSB -> length of second write transaction
+- char[M+3]=data0
+- char[M+4]=data1
+- ...
+- etc.
+-
+- The [len] value should be interpreted as follows:
+-
+- len= len_MSB _ len_LSB
+- len=1111_1111_1111_1111 : End of I2C_SEQUENCE
+- len=0000_0000_0000_0000 : Reset command: Do hardware reset
+- len=0NNN_NNNN_NNNN_NNNN : Normal transaction: number of bytes = {1:32767)
+- len=1WWW_WWWW_WWWW_WWWW : Wait command: wait for {1:32767} ms
+-
+- For the RESET and WAIT commands, the two following bytes will contain
+- immediately the length of the following transaction.
+-
+-*/
+-typedef struct {
+- char *Name;
+- u16 AudioMode;
+- u16 VideoMode;
+-} XC_TV_STANDARD;
+-
+-/* Tuner standards */
+-#define MN_NTSC_PAL_BTSC 0
+-#define MN_NTSC_PAL_A2 1
+-#define MN_NTSC_PAL_EIAJ 2
+-#define MN_NTSC_PAL_Mono 3
+-#define BG_PAL_A2 4
+-#define BG_PAL_NICAM 5
+-#define BG_PAL_MONO 6
+-#define I_PAL_NICAM 7
+-#define I_PAL_NICAM_MONO 8
+-#define DK_PAL_A2 9
+-#define DK_PAL_NICAM 10
+-#define DK_PAL_MONO 11
+-#define DK_SECAM_A2DK1 12
+-#define DK_SECAM_A2LDK3 13
+-#define DK_SECAM_A2MONO 14
+-#define L_SECAM_NICAM 15
+-#define LC_SECAM_NICAM 16
+-#define DTV6 17
+-#define DTV8 18
+-#define DTV7_8 19
+-#define DTV7 20
+-#define FM_Radio_INPUT2 21
+-#define FM_Radio_INPUT1 22
+-
+-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},
+- {"M/N-NTSC/PAL-Mono", 0x0478, 0x8020},
+- {"B/G-PAL-A2", 0x0A00, 0x8049},
+- {"B/G-PAL-NICAM", 0x0C04, 0x8049},
+- {"B/G-PAL-MONO", 0x0878, 0x8059},
+- {"I-PAL-NICAM", 0x1080, 0x8009},
+- {"I-PAL-NICAM-MONO", 0x0E78, 0x8009},
+- {"D/K-PAL-A2", 0x1600, 0x8009},
+- {"D/K-PAL-NICAM", 0x0E80, 0x8009},
+- {"D/K-PAL-MONO", 0x1478, 0x8009},
+- {"D/K-SECAM-A2 DK1", 0x1200, 0x8009},
+- {"D/K-SECAM-A2 L/DK3",0x0E00, 0x8009},
+- {"D/K-SECAM-A2 MONO", 0x1478, 0x8009},
+- {"L-SECAM-NICAM", 0x8E82, 0x0009},
+- {"L'-SECAM-NICAM", 0x8E82, 0x4009},
+- {"DTV6", 0x00C0, 0x8002},
+- {"DTV8", 0x00C0, 0x800B},
+- {"DTV7/8", 0x00C0, 0x801B},
+- {"DTV7", 0x00C0, 0x8007},
+- {"FM Radio-INPUT2", 0x9802, 0x9002},
+- {"FM Radio-INPUT1", 0x0208, 0x9002}
+-};
+-
+-static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len);
+-static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len);
+-static void xc5000_TunerReset(struct dvb_frontend *fe);
+-
+-static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
+-{
+- return xc5000_writeregs(priv, buf, len)
+- ? XC_RESULT_I2C_WRITE_FAILURE : XC_RESULT_SUCCESS;
+-}
+-
+-static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
+-{
+- return xc5000_readregs(priv, buf, len)
+- ? XC_RESULT_I2C_READ_FAILURE : XC_RESULT_SUCCESS;
+-}
+-
+-static int xc_reset(struct dvb_frontend *fe)
+-{
+- xc5000_TunerReset(fe);
+- return XC_RESULT_SUCCESS;
+-}
+-
+-static void xc_wait(int wait_ms)
+-{
+- msleep(wait_ms);
+-}
+-
+-static void xc5000_TunerReset(struct dvb_frontend *fe)
+-{
+- struct xc5000_priv *priv = fe->tuner_priv;
+- int ret;
+-
+- dprintk(1, "%s()\n", __FUNCTION__);
+-
+- if (priv->cfg->tuner_callback) {
+- ret = priv->cfg->tuner_callback(priv->cfg->priv,
+- XC5000_TUNER_RESET, 0);
+- if (ret)
+- printk(KERN_ERR "xc5000: reset failed\n");
+- } else
+- printk(KERN_ERR "xc5000: no tuner reset callback function, fatal\n");
+-}
+-
+-static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData)
+-{
+- u8 buf[4];
+- int WatchDogTimer = 5;
+- int result;
+-
+- buf[0] = (regAddr >> 8) & 0xFF;
+- buf[1] = regAddr & 0xFF;
+- buf[2] = (i2cData >> 8) & 0xFF;
+- buf[3] = i2cData & 0xFF;
+- result = xc_send_i2c_data(priv, buf, 4);
+- if (result == XC_RESULT_SUCCESS) {
+- /* wait for busy flag to clear */
+- while ((WatchDogTimer > 0) && (result == XC_RESULT_SUCCESS)) {
+- buf[0] = 0;
+- buf[1] = XREG_BUSY;
+-
+- result = xc_send_i2c_data(priv, buf, 2);
+- if (result == XC_RESULT_SUCCESS) {
+- result = xc_read_i2c_data(priv, buf, 2);
+- if (result == XC_RESULT_SUCCESS) {
+- if ((buf[0] == 0) && (buf[1] == 0)) {
+- /* busy flag cleared */
+- break;
+- } else {
+- xc_wait(100); /* wait 5 ms */
+- WatchDogTimer--;
+- }
+- }
+- }
+- }
+- }
+- if (WatchDogTimer < 0)
+- result = XC_RESULT_I2C_WRITE_FAILURE;
+-
+- return result;
+-}
+-
+-static int xc_read_reg(struct xc5000_priv *priv, u16 regAddr, u16 *i2cData)
+-{
+- u8 buf[2];
+- int result;
+-
+- buf[0] = (regAddr >> 8) & 0xFF;
+- buf[1] = regAddr & 0xFF;
+- result = xc_send_i2c_data(priv, buf, 2);
+- if (result != XC_RESULT_SUCCESS)
+- return result;
+-
+- result = xc_read_i2c_data(priv, buf, 2);
+- if (result != XC_RESULT_SUCCESS)
+- return result;
+-
+- *i2cData = buf[0] * 256 + buf[1];
+- return result;
+-}
+-
+-static int xc_load_i2c_sequence(struct dvb_frontend *fe, u8 i2c_sequence[])
+-{
+- struct xc5000_priv *priv = fe->tuner_priv;
+-
+- int i, nbytes_to_send, result;
+- unsigned int len, pos, index;
+- u8 buf[XC_MAX_I2C_WRITE_LENGTH];
+-
+- index=0;
+- while ((i2c_sequence[index]!=0xFF) || (i2c_sequence[index+1]!=0xFF)) {
+- len = i2c_sequence[index]* 256 + i2c_sequence[index+1];
+- if (len == 0x0000) {
+- /* RESET command */
+- result = xc_reset(fe);
+- index += 2;
+- if (result != XC_RESULT_SUCCESS)
+- return result;
+- } else if (len & 0x8000) {
+- /* WAIT command */
+- xc_wait(len & 0x7FFF);
+- index += 2;
+- } else {
+- /* Send i2c data whilst ensuring individual transactions
+- * do not exceed XC_MAX_I2C_WRITE_LENGTH bytes.
+- */
+- index += 2;
+- buf[0] = i2c_sequence[index];
+- buf[1] = i2c_sequence[index + 1];
+- pos = 2;
+- while (pos < len) {
+- if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2) {
+- nbytes_to_send = XC_MAX_I2C_WRITE_LENGTH;
+- } else {
+- nbytes_to_send = (len - pos + 2);
+- }
+- for (i=2; i<nbytes_to_send; i++) {
+- buf[i] = i2c_sequence[index + pos + i - 2];
+- }
+- result = xc_send_i2c_data(priv, buf, nbytes_to_send);
+-
+- if (result != XC_RESULT_SUCCESS)
+- return result;
+-
+- pos += nbytes_to_send - 2;
+- }
+- index += len;
+- }
+- }
+- return XC_RESULT_SUCCESS;
+-}
+-
+-static int xc_initialize(struct xc5000_priv *priv)
+-{
+- dprintk(1, "%s()\n", __FUNCTION__);
+- return xc_write_reg(priv, XREG_INIT, 0);
+-}
+-
+-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() Standard = %s\n",
+- __FUNCTION__,
+- XC5000_Standard[priv->video_standard].Name);
+-
+- ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode);
+- if (ret == XC_RESULT_SUCCESS)
+- ret = xc_write_reg(priv, XREG_AUDIO_MODE, AudioMode);
+-
+- return ret;
+-}
+-
+-static int xc_shutdown(struct xc5000_priv *priv)
+-{
+- return 0;
+- /* Fixme: cannot bring tuner back alive once shutdown
+- * without reloading the driver modules.
+- * return xc_write_reg(priv, XREG_POWER_DOWN, 0);
+- */
+-}
+-
+-static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
+-{
+- dprintk(1, "%s(%d) Source = %s\n", __FUNCTION__, rf_mode,
+- rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
+-
+- if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE))
+- {
+- rf_mode = XC_RF_MODE_CABLE;
+- printk(KERN_ERR
+- "%s(), Invalid mode, defaulting to CABLE",
+- __FUNCTION__);
+- }
+- return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
+-}
+-
+-static const struct dvb_tuner_ops xc5000_tuner_ops;
+-
+-static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz)
+-{
+- u16 freq_code;
+-
+- dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz);
+-
+- if ((freq_hz > xc5000_tuner_ops.info.frequency_max) ||
+- (freq_hz < xc5000_tuner_ops.info.frequency_min))
+- return XC_RESULT_OUT_OF_RANGE;
+-
+- freq_code = (u16)(freq_hz / 15625);
+-
+- return xc_write_reg(priv, XREG_RF_FREQ, freq_code);
+-}
+-
+-
+-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);
+-
+- return xc_write_reg(priv, XREG_IF_OUT, freq_code);
+-}
+-
+-
+-static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope)
+-{
+- return xc_read_reg(priv, XREG_ADC_ENV, adc_envelope);
+-}
+-
+-static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz)
+-{
+- int result;
+- u16 regData;
+- u32 tmp;
+-
+- result = xc_read_reg(priv, XREG_FREQ_ERROR, ®Data);
+- if (result)
+- return result;
+-
+- tmp = (u32)regData;
+- (*freq_error_hz) = (tmp * 15625) / 1000;
+- return result;
+-}
+-
+-static int xc_get_lock_status(struct xc5000_priv *priv, u16 *lock_status)
+-{
+- return xc_read_reg(priv, XREG_LOCK, lock_status);
+-}
+-
+-static int xc_get_version(struct xc5000_priv *priv,
+- u8 *hw_majorversion, u8 *hw_minorversion,
+- u8 *fw_majorversion, u8 *fw_minorversion)
+-{
+- u16 data;
+- int result;
+-
+- result = xc_read_reg(priv, XREG_VERSION, &data);
+- if (result)
+- return result;
+-
+- (*hw_majorversion) = (data >> 12) & 0x0F;
+- (*hw_minorversion) = (data >> 8) & 0x0F;
+- (*fw_majorversion) = (data >> 4) & 0x0F;
+- (*fw_minorversion) = data & 0x0F;
+-
+- return 0;
+-}
+-
+-static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz)
+-{
+- u16 regData;
+- int result;
+-
+- result = xc_read_reg(priv, XREG_HSYNC_FREQ, ®Data);
+- if (result)
+- return result;
+-
+- (*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100;
+- return result;
+-}
+-
+-static int xc_get_frame_lines(struct xc5000_priv *priv, u16 *frame_lines)
+-{
+- return xc_read_reg(priv, XREG_FRAME_LINES, frame_lines);
+-}
+-
+-static int xc_get_quality(struct xc5000_priv *priv, u16 *quality)
+-{
+- return xc_read_reg(priv, XREG_QUALITY, quality);
+-}
+-
+-static u16 WaitForLock(struct xc5000_priv *priv)
+-{
+- u16 lockState = 0;
+- int watchDogCount = 40;
+-
+- while ((lockState == 0) && (watchDogCount > 0)) {
+- xc_get_lock_status(priv, &lockState);
+- if (lockState != 1) {
+- xc_wait(5);
+- watchDogCount--;
+- }
+- }
+- return lockState;
+-}
+-
+-static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz)
+-{
+- int found = 0;
+-
+- dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz);
+-
+- if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS)
+- return 0;
+-
+- if (WaitForLock(priv) == 1)
+- found = 1;
+-
+- return found;
+-}
+-
+-static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
+-{
+- u8 buf[2] = { reg >> 8, reg & 0xff };
+- u8 bval[2] = { 0, 0 };
+- struct i2c_msg msg[2] = {
+- { .addr = priv->cfg->i2c_address,
+- .flags = 0, .buf = &buf[0], .len = 2 },
+- { .addr = priv->cfg->i2c_address,
+- .flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
+- };
+-
+- if (i2c_transfer(priv->i2c, msg, 2) != 2) {
+- printk(KERN_WARNING "xc5000: I2C read failed\n");
+- return -EREMOTEIO;
+- }
+-
+- *val = (bval[0] << 8) | bval[1];
+- return 0;
+-}
+-
+-static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len)
+-{
+- struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
+- .flags = 0, .buf = buf, .len = len };
+-
+- if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+- printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n",
+- (int)len);
+- return -EREMOTEIO;
+- }
+- return 0;
+-}
+-
+-static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len)
+-{
+- struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
+- .flags = I2C_M_RD, .buf = buf, .len = len };
+-
+- if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+- printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n",(int)len);
+- return -EREMOTEIO;
+- }
+- return 0;
+-}
+-
+-static int xc5000_fwupload(struct dvb_frontend* fe)
+-{
+- struct xc5000_priv *priv = fe->tuner_priv;
+- const struct firmware *fw;
+- int ret;
+-
+- /* request the firmware, this will block and timeout */
+- printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
+- XC5000_DEFAULT_FIRMWARE);
+-
+- ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c->dev);
+- if (ret) {
+- printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
+- ret = XC_RESULT_RESET_FAILURE;
+- goto out;
+- } else {
+- printk(KERN_INFO "xc5000: firmware read %Zu bytes.\n",
+- fw->size);
+- ret = XC_RESULT_SUCCESS;
+- }
+-
+- if (fw->size != XC5000_DEFAULT_FIRMWARE_SIZE) {
+- printk(KERN_ERR "xc5000: firmware incorrect size\n");
+- ret = XC_RESULT_RESET_FAILURE;
+- } else {
+- printk(KERN_INFO "xc5000: firmware upload\n");
+- ret = xc_load_i2c_sequence(fe, fw->data );
+- }
+-
+-out:
+- release_firmware(fw);
+- return ret;
+-}
+-
+-static void xc_debug_dump(struct xc5000_priv *priv)
+-{
+- u16 adc_envelope;
+- u32 freq_error_hz = 0;
+- u16 lock_status;
+- u32 hsync_freq_hz = 0;
+- u16 frame_lines;
+- u16 quality;
+- u8 hw_majorversion = 0, hw_minorversion = 0;
+- u8 fw_majorversion = 0, fw_minorversion = 0;
+-
+- /* Wait for stats to stabilize.
+- * Frame Lines needs two frame times after initial lock
+- * before it is valid.
+- */
+- xc_wait(100);
+-
+- xc_get_ADC_Envelope(priv, &adc_envelope);
+- dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope);
+-
+- xc_get_frequency_error(priv, &freq_error_hz);
+- dprintk(1, "*** Frequency error = %d Hz\n", freq_error_hz);
+-
+- xc_get_lock_status(priv, &lock_status);
+- dprintk(1, "*** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d\n",
+- lock_status);
+-
+- xc_get_version(priv, &hw_majorversion, &hw_minorversion,
+- &fw_majorversion, &fw_minorversion);
+- dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x\n",
+- hw_majorversion, hw_minorversion,
+- fw_majorversion, fw_minorversion);
+-
+- xc_get_hsync_freq(priv, &hsync_freq_hz);
+- dprintk(1, "*** Horizontal sync frequency = %d Hz\n", hsync_freq_hz);
+-
+- xc_get_frame_lines(priv, &frame_lines);
+- dprintk(1, "*** Frame lines = %d\n", frame_lines);
+-
+- xc_get_quality(priv, &quality);
+- dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
+-}
+-
+-static int xc5000_set_params(struct dvb_frontend *fe,
+- struct dvb_frontend_parameters *params)
+-{
+- struct xc5000_priv *priv = fe->tuner_priv;
+- int ret;
+-
+- dprintk(1, "%s() frequency=%d (Hz)\n", __FUNCTION__, params->frequency);
+-
+- switch(params->u.vsb.modulation) {
+- case VSB_8:
+- case VSB_16:
+- dprintk(1, "%s() VSB modulation\n", __FUNCTION__);
+- priv->rf_mode = XC_RF_MODE_AIR;
+- priv->freq_hz = params->frequency - 1750000;
+- priv->bandwidth = BANDWIDTH_6_MHZ;
+- priv->video_standard = DTV6;
+- break;
+- case QAM_64:
+- case QAM_256:
+- case QAM_AUTO:
+- dprintk(1, "%s() QAM modulation\n", __FUNCTION__);
+- priv->rf_mode = XC_RF_MODE_CABLE;
+- priv->freq_hz = params->frequency - 1750000;
+- priv->bandwidth = BANDWIDTH_6_MHZ;
+- priv->video_standard = DTV6;
+- break;
+- default:
+- return -EINVAL;
+- }
+-
+- dprintk(1, "%s() frequency=%d (compensated)\n",
+- __FUNCTION__, priv->freq_hz);
+-
+- ret = xc_SetSignalSource(priv, priv->rf_mode);
+- if (ret != XC_RESULT_SUCCESS) {
+- printk(KERN_ERR
+- "xc5000: xc_SetSignalSource(%d) failed\n",
+- priv->rf_mode);
+- return -EREMOTEIO;
+- }
+-
+- ret = xc_SetTVStandard(priv,
+- XC5000_Standard[priv->video_standard].VideoMode,
+- XC5000_Standard[priv->video_standard].AudioMode);
+- if (ret != XC_RESULT_SUCCESS) {
+- printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
+- return -EREMOTEIO;
+- }
+-
+- ret = xc_set_IF_frequency(priv, priv->cfg->if_khz);
+- if (ret != XC_RESULT_SUCCESS) {
+- printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n",
+- priv->cfg->if_khz);
+- return -EIO;
+- }
+-
+- xc_tune_channel(priv, priv->freq_hz);
+-
+- if (debug)
+- xc_debug_dump(priv);
+-
+- return 0;
+-}
+-
+-static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
+-
+-static int xc5000_set_analog_params(struct dvb_frontend *fe,
+- struct analog_parameters *params)
+-{
+- struct xc5000_priv *priv = fe->tuner_priv;
+- int ret;
+-
+- if(priv->fwloaded == 0)
+- xc_load_fw_and_init_tuner(fe);
+-
+- dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
+- __FUNCTION__, params->frequency);
+-
+- priv->rf_mode = XC_RF_MODE_CABLE; /* Fix me: it could be air. */
+-
+- /* params->frequency is in units of 62.5khz */
+- priv->freq_hz = params->frequency * 62500;
+-
+- /* FIX ME: Some video standards may have several possible audio
+- standards. We simply default to one of them here.
+- */
+- if(params->std & V4L2_STD_MN) {
+- /* default to BTSC audio standard */
+- priv->video_standard = MN_NTSC_PAL_BTSC;
+- goto tune_channel;
+- }
+-
+- if(params->std & V4L2_STD_PAL_BG) {
+- /* default to NICAM audio standard */
+- priv->video_standard = BG_PAL_NICAM;
+- goto tune_channel;
+- }
+-
+- if(params->std & V4L2_STD_PAL_I) {
+- /* default to NICAM audio standard */
+- priv->video_standard = I_PAL_NICAM;
+- goto tune_channel;
+- }
+-
+- if(params->std & V4L2_STD_PAL_DK) {
+- /* default to NICAM audio standard */
+- priv->video_standard = DK_PAL_NICAM;
+- goto tune_channel;
+- }
+-
+- if(params->std & V4L2_STD_SECAM_DK) {
+- /* default to A2 DK1 audio standard */
+- priv->video_standard = DK_SECAM_A2DK1;
+- goto tune_channel;
+- }
+-
+- if(params->std & V4L2_STD_SECAM_L) {
+- priv->video_standard = L_SECAM_NICAM;
+- goto tune_channel;
+- }
+-
+- if(params->std & V4L2_STD_SECAM_LC) {
+- priv->video_standard = LC_SECAM_NICAM;
+- goto tune_channel;
+- }
+-
+-tune_channel:
+- ret = xc_SetSignalSource(priv, priv->rf_mode);
+- if (ret != XC_RESULT_SUCCESS) {
+- printk(KERN_ERR
+- "xc5000: xc_SetSignalSource(%d) failed\n",
+- priv->rf_mode);
+- return -EREMOTEIO;
+- }
+-
+- ret = xc_SetTVStandard(priv,
+- XC5000_Standard[priv->video_standard].VideoMode,
+- XC5000_Standard[priv->video_standard].AudioMode);
+- if (ret != XC_RESULT_SUCCESS) {
+- printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
+- return -EREMOTEIO;
+- }
+-
+- xc_tune_channel(priv, priv->freq_hz);
+-
+- if (debug)
+- xc_debug_dump(priv);
+-
+- return 0;
+-}
+-
+-static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
+-{
+- struct xc5000_priv *priv = fe->tuner_priv;
+- dprintk(1, "%s()\n", __FUNCTION__);
+- *freq = priv->freq_hz;
+- return 0;
+-}
+-
+-static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
+-{
+- struct xc5000_priv *priv = fe->tuner_priv;
+- dprintk(1, "%s()\n", __FUNCTION__);
+-
+- *bw = priv->bandwidth;
+- return 0;
+-}
+-
+-static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
+-{
+- struct xc5000_priv *priv = fe->tuner_priv;
+- u16 lock_status = 0;
+-
+- xc_get_lock_status(priv, &lock_status);
+-
+- dprintk(1, "%s() lock_status = 0x%08x\n", __FUNCTION__, lock_status);
+-
+- *status = lock_status;
+-
+- return 0;
+-}
+-
+-static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
+-{
+- struct xc5000_priv *priv = fe->tuner_priv;
+- int ret = 0;
+-
+- if (priv->fwloaded == 0) {
+- ret = xc5000_fwupload(fe);
+- if (ret != XC_RESULT_SUCCESS)
+- return ret;
+- priv->fwloaded = 1;
+- }
+-
+- /* Start the tuner self-calibration process */
+- ret |= xc_initialize(priv);
+-
+- /* Wait for calibration to complete.
+- * We could continue but XC5000 will clock stretch subsequent
+- * I2C transactions until calibration is complete. This way we
+- * don't have to rely on clock stretching working.
+- */
+- xc_wait( 100 );
+-
+- /* Default to "CABLE" mode */
+- ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
+-
+- return ret;
+-}
+-
+-static int xc5000_sleep(struct dvb_frontend *fe)
+-{
+- struct xc5000_priv *priv = fe->tuner_priv;
+- int ret;
+-
+- dprintk(1, "%s()\n", __FUNCTION__);
+-
+- /* On Pinnacle PCTV HD 800i, the tuner cannot be reinitialized
+- * once shutdown without reloading the driver. Maybe I am not
+- * doing something right.
+- *
+- */
+-
+- ret = xc_shutdown(priv);
+- if(ret != XC_RESULT_SUCCESS) {
+- printk(KERN_ERR
+- "xc5000: %s() unable to shutdown tuner\n",
+- __FUNCTION__);
+- return -EREMOTEIO;
+- }
+- else {
+- /* priv->fwloaded = 0; */
+- return XC_RESULT_SUCCESS;
+- }
+-}
+-
+-static int xc5000_init(struct dvb_frontend *fe)
+-{
+- struct xc5000_priv *priv = fe->tuner_priv;
+- dprintk(1, "%s()\n", __FUNCTION__);
+-
+- if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
+- printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
+- return -EREMOTEIO;
+- }
+-
+- if (debug)
+- xc_debug_dump(priv);
+-
+- return 0;
+-}
+-
+-static int xc5000_release(struct dvb_frontend *fe)
+-{
+- dprintk(1, "%s()\n", __FUNCTION__);
+- kfree(fe->tuner_priv);
+- fe->tuner_priv = NULL;
+- return 0;
+-}
+-
+-static const struct dvb_tuner_ops xc5000_tuner_ops = {
+- .info = {
+- .name = "Xceive XC5000",
+- .frequency_min = 1000000,
+- .frequency_max = 1023000000,
+- .frequency_step = 50000,
+- },
+-
+- .release = xc5000_release,
+- .init = xc5000_init,
+- .sleep = xc5000_sleep,
+-
+- .set_params = xc5000_set_params,
+- .set_analog_params = xc5000_set_analog_params,
+- .get_frequency = xc5000_get_frequency,
+- .get_bandwidth = xc5000_get_bandwidth,
+- .get_status = xc5000_get_status
+-};
+-
+-struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe,
+- struct i2c_adapter *i2c,
+- struct xc5000_config *cfg)
+-{
+- struct xc5000_priv *priv = NULL;
+- u16 id = 0;
+-
+- dprintk(1, "%s()\n", __FUNCTION__);
+-
+- priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL);
+- if (priv == NULL)
+- return NULL;
+-
+- priv->cfg = cfg;
+- priv->bandwidth = BANDWIDTH_6_MHZ;
+- priv->i2c = i2c;
+-
+- /* Check if firmware has been loaded. It is possible that another
+- instance of the driver has loaded the firmware.
+- */
+- if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) {
+- kfree(priv);
+- return NULL;
+- }
+-
+- switch(id) {
+- case XC_PRODUCT_ID_FW_LOADED:
+- printk(KERN_INFO
+- "xc5000: Successfully identified at address 0x%02x\n",
+- cfg->i2c_address);
+- printk(KERN_INFO
+- "xc5000: Firmware has been loaded previously\n");
+- priv->fwloaded = 1;
+- break;
+- case XC_PRODUCT_ID_FW_NOT_LOADED:
+- printk(KERN_INFO
+- "xc5000: Successfully identified at address 0x%02x\n",
+- cfg->i2c_address);
+- printk(KERN_INFO
+- "xc5000: Firmware has not been loaded previously\n");
+- priv->fwloaded = 0;
+- break;
+- default:
+- printk(KERN_ERR
+- "xc5000: Device not found at addr 0x%02x (0x%x)\n",
+- cfg->i2c_address, id);
+- kfree(priv);
+- return NULL;
+- }
+-
+- memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops,
+- sizeof(struct dvb_tuner_ops));
+-
+- fe->tuner_priv = priv;
+-
+- return fe;
+-}
+-EXPORT_SYMBOL(xc5000_attach);
+-
+-MODULE_AUTHOR("Steven Toth");
+-MODULE_DESCRIPTION("Xceive xc5000 silicon tuner driver");
+-MODULE_LICENSE("GPL");
+diff --git a/drivers/media/dvb/frontends/xc5000.h b/drivers/media/dvb/frontends/xc5000.h
+deleted file mode 100644
+index 32a5f1c..0000000
+--- a/drivers/media/dvb/frontends/xc5000.h
++++ /dev/null
+@@ -1,63 +0,0 @@
+-/*
+- * Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
+- *
+- * Copyright (c) 2007 Steven Toth <stoth at hauppauge.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- *
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#ifndef __XC5000_H__
+-#define __XC5000_H__
+-
+-#include <linux/firmware.h>
+-
+-struct dvb_frontend;
+-struct i2c_adapter;
+-
+-struct xc5000_config {
+- u8 i2c_address;
+- u32 if_khz;
+-
+- /* For each bridge framework, when it attaches either analog or digital,
+- * it has to store a reference back to its _core equivalent structure,
+- * so that it can service the hardware by steering gpio's etc.
+- * Each bridge implementation is different so cast priv accordingly.
+- * The xc5000 driver cares not for this value, other than ensuring
+- * it's passed back to a bridge during tuner_callback().
+- */
+- void *priv;
+- int (*tuner_callback) (void *priv, int command, int arg);
+-};
+-
+-/* xc5000 callback command */
+-#define XC5000_TUNER_RESET 0
+-
+-#if defined(CONFIG_DVB_TUNER_XC5000) || \
+- (defined(CONFIG_DVB_TUNER_XC5000_MODULE) && defined(MODULE))
+-extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
+- struct i2c_adapter *i2c,
+- struct xc5000_config *cfg);
+-#else
+-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__);
+- return NULL;
+-}
+-#endif // CONFIG_DVB_TUNER_XC5000
+-
+-#endif // __XC5000_H__
+diff --git a/drivers/media/dvb/frontends/xc5000_priv.h b/drivers/media/dvb/frontends/xc5000_priv.h
+deleted file mode 100644
+index 13b2d19..0000000
+--- a/drivers/media/dvb/frontends/xc5000_priv.h
++++ /dev/null
+@@ -1,36 +0,0 @@
+-/*
+- * Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
+- *
+- * Copyright (c) 2007 Steven Toth <stoth at hauppauge.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- *
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#ifndef XC5000_PRIV_H
+-#define XC5000_PRIV_H
+-
+-struct xc5000_priv {
+- struct xc5000_config *cfg;
+- struct i2c_adapter *i2c;
+-
+- u32 freq_hz;
+- u32 bandwidth;
+- u8 video_standard;
+- u8 rf_mode;
+- u8 fwloaded;
+-};
+-
+-#endif
+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)
- 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)
- }
+-static int debug_regs = 0;
++static int debug_regs;
- 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);
- }
+ 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)
- 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;
- }
+ if (ret != 2) {
+ printk("%s: readreg error (reg=%d, ret==%i)\n",
+- __FUNCTION__, reg, ret);
++ __func__, reg, ret);
+ return ret;
+ }
-- 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
+@@ -152,7 +152,7 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
+ *nominal_rate = value;
- /* 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: bw %d, adc_clock %d => 0x%x\n",
+- __FUNCTION__, bw, adc_clock, *nominal_rate);
++ __func__, bw, adc_clock, *nominal_rate);
+ }
-- 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;
+ 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\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);
- }
+ 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);
+ }
- if (priv->secfilter) {
-- dprintk("%s: release secfilter\n", __FUNCTION__);
-+ dprintk("%s: release secfilter\n", __func__);
- priv->secfeed->release_filter(priv->secfeed,
- priv->secfilter);
- priv->secfilter=NULL;
-@@ -1082,7 +1082,7 @@ static int dvb_net_feed_stop(struct net_device *dev)
- for (i=0; i<priv->multi_num; i++) {
- if (priv->multi_secfilter[i]) {
- dprintk("%s: release multi_filter[%d]\n",
-- __FUNCTION__, i);
-+ __func__, i);
- priv->secfeed->release_filter(priv->secfeed,
- priv->multi_secfilter[i]);
- priv->multi_secfilter[i] = NULL;
-@@ -1096,7 +1096,7 @@ static int dvb_net_feed_stop(struct net_device *dev)
- } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
- if (priv->tsfeed) {
- if (priv->tsfeed->is_filtering) {
-- dprintk("%s: stop tsfeed\n", __FUNCTION__);
-+ dprintk("%s: stop tsfeed\n", __func__);
- priv->tsfeed->stop_filtering(priv->tsfeed);
- }
- priv->demux->release_ts_feed(priv->demux, priv->tsfeed);
-diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
-index ac9d93c..872985b 100644
---- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
-+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
-@@ -90,7 +90,11 @@ void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
- rbuf->error = 0;
+ 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"
--
-+void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf)
-+{
-+ rbuf->pread = rbuf->pwrite = 0;
-+ rbuf->error = 0;
-+}
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define DRIVER_NAME "pluto2"
- 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.
- */
+ #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;
-@@ -85,6 +86,13 @@ extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf);
- extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf);
+ /* 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");
-+/*
-+** 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);
-+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
- /* 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"
- };
+ static void restart_feeds(struct av7110 *av7110);
--#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 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));
--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;
+ 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? */
}
-@@ -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);
+@@ -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;
}
-@@ -262,18 +261,25 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
- }
- EXPORT_SYMBOL(dvb_unregister_device);
+@@ -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,
-+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;
-+}
+ 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;
- static int dvbdev_get_free_adapter_num (void)
- {
- int num = 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;
- 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++;
- }
+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;
-@@ -281,13 +287,28 @@ skip:
- }
+ #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
--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;
+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;
- mutex_lock(&dvbdev_register_lock);
+ 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 ((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;
+ 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;
}
-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
+@@ -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)
-+#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
+ 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;
+ }
-+#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")
+@@ -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;
- struct dvb_adapter {
- int num;
-@@ -78,7 +87,9 @@ struct dvb_device {
- };
+ 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];
--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);
+ dprintk(16, "%s: code %08x -> addr %i data 0x%02x -> keycode %i\n",
+- __FUNCTION__, ircom, addr, data, keycode);
++ __func__, ircom, addr, data, keycode);
- 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)
+ /* check device address */
+ if (!(ir->device_mask & (1 << addr)))
+@@ -151,7 +151,7 @@ static void av7110_emit_key(unsigned long parm)
- 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);
- }
+ if (!keycode) {
+ printk ("%s: code %08x -> addr %i data 0x%02x -> unknown key!\n",
+- __FUNCTION__, ircom, addr, data);
++ __func__, ircom, addr, data);
+ return;
+ }
- /* 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.");
+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;
-+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);
- }
+- 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;
- 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);
+- 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);
-+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;
+ 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) {
-- 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);
+ 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)");
- if (alt == NULL) {
-diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
-index c583650..720fcd1 100644
---- a/drivers/media/dvb/dvb-usb/cxusb.c
-+++ b/drivers/media/dvb/dvb-usb/cxusb.c
-@@ -23,6 +23,8 @@
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-+#include <media/tuner.h>
-+
- #include "cxusb.h"
+-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");
- #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"
+@@ -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)");
- /* 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)
+ /****************************************************************************
+ * TT budget / WinTV Nova
+ ****************************************************************************/
+@@ -223,7 +225,7 @@ static void vpeirq(unsigned long data)
- 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;
+ 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;
}
-@@ -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,
- };
+@@ -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);
- 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;
+- 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;
- }
- 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).");
+ /* 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"
-+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 diseqc_method;
+ module_param(diseqc_method, int, 0444);
+@@ -257,11 +258,17 @@ static struct ves1820_config alps_tdbe2_config = {
--static int dib0700_rc_setup(struct dvb_usb_device *d)
-+int dib0700_rc_setup(struct dvb_usb_device *d)
+ static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
- 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;
+- 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;
- 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"
+ div = (36125000 + params->frequency) / 166666;
- 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;;
- }
+@@ -292,6 +299,12 @@ static struct l64781_config grundig_29504_401_config = {
+ .demod_address = 0x55,
+ };
-+/* 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 struct l64781_config grundig_29504_401_config_activy = {
++ .demod_address = 0x54,
+};
+
-+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 u8 tuner_address_grundig_29504_401_activy = 0x60;
+
-+static struct xc2028_ctrl stk7700ph_xc3028_ctrl = {
-+ .fname = XC2028_DEFAULT_FIRMWARE,
-+ .max_len = 64,
-+ .demod = XC3028_FE_DIBCOM52,
+ 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 xc2028_config stk7700ph_xc3028_config = {
-+ .i2c_addr = 0x61,
-+ .callback = stk7700ph_xc3028_callback,
-+ .ctrl = &stk7700ph_xc3028_ctrl,
++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 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)
++static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg)
+{
-+ 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;
++ u8 val;
++ struct i2c_msg msg[] = {
++ { .addr = adr, .flags = 0, .buf = ®, .len = 1 },
++ { .addr = adr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
++ };
+
-+ return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config)
-+ == NULL ? -ENODEV : 0;
++ return (i2c_transfer(i2c, msg, 2) != 2) ? -EIO : val;
+}
+
- #define DEFAULT_RC_INTERVAL 150
-
- static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
+ static u8 read_pwm(struct budget* budget)
+ {
+ u8 b = 0xff;
+@@ -369,6 +416,8 @@ static u8 read_pwm(struct budget* budget)
-+/* 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)
+ static void frontend_init(struct budget *budget)
{
- 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]); */
++ (void)alps_bsbe1_config; /* avoid warning */
+
-+ dib0700_rc_setup(d); /* reset ir sensor data to prevent false events */
+ 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);
+
-+ 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;
++ 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;
+ }
-+ return 0;
-+ }
- for (i=0;i<d->props.rc_key_map_size; i++) {
- if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) {
-+ st->rc_counter = 0;
-+ *event = keymap[i].event;
-+ *state = REMOTE_KEY_PRESSED;
-+ d->last_event = keymap[i].event;
-+ return 0;
++ } 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;
-+ }
-+ 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;
- }
+ 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 },
-+ }
+ 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)
}
- }, { 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 },
-+ },
- },
+ break;
- .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),
-+ },
-+ },
++ 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;
+
-+ .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"
+ 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);
-+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+ 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 @@
+
- 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;
+ #ifndef __BUDGET_DVB__
+ #define __BUDGET_DVB__
- 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"
+@@ -21,7 +22,7 @@ extern int budget_debug;
+ #endif
-+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-+
- /* USB Driver stuff */
- static struct dvb_usb_device_properties dibusb_mc_properties;
+ #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)
- 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);
- }
+ 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 }
+ };
- /* 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)
+- /* dprintk("%s\n", __FUNCTION__); */
++ /* dprintk("%s\n", __func__); */
- 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 };
+ ret = i2c_transfer(adapter, msg, 2);
- 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);
+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);
+
- 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);
+ #define dprintk(x...) do { if (debug) printk(KERN_DEBUG x); } while (0)
-- 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;
+ #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;
}
-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
-
+ 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);
- /* 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
+ 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;
+ }
- #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).");
+@@ -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);
--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 (err < rcv_len) {
+- dprintk("%s: i == %i\n", __FUNCTION__, i);
++ dprintk("%s: i == %i\n", __func__, i);
+ break;
}
- 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;
- }
+@@ -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);
+ }
--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;
+ 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;
-@@ -143,7 +143,7 @@ static int dvb_usb_init(struct dvb_usb_device *d)
- dvb_usb_device_power_ctrl(d, 1);
+- 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]);
- 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;
+@@ -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]);
}
-@@ -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);
+@@ -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);
+ }
- 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;
- };
+ 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);
+ }
--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 *);
+ 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
- /* 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);
+-static int numpkt = 0, numts, numstuff, numsec, numinvalid;
++static int numpkt, numts, numstuff, numsec, numinvalid;
+ static unsigned long lastj;
-+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;
+ 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;
+ }
-- 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);
+@@ -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 (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;
+ #if 0
+ printk("%s: status %d, errcount == %d, length == %i\n",
+- __FUNCTION__,
++ __func__,
+ urb->status, urb->error_count, urb->actual_length);
+ #endif
-- deb_fe("%s\n",__FUNCTION__);
-+ deb_fe("%s\n",__func__);
+@@ -833,7 +834,7 @@ static int ttusb_start_iso_xfer(struct ttusb *ttusb)
+ int i, j, err, buffer_offset = 0;
- 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;
+ if (ttusb->iso_streaming) {
+- printk("%s: iso xfer already running!\n", __FUNCTION__);
++ printk("%s: iso xfer already running!\n", __func__);
+ return 0;
+ }
-- deb_fe("%s\n",__FUNCTION__);
-+ deb_fe("%s\n",__func__);
+@@ -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;
+ }
- /* 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);
+-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;
-+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);
+- dprintk("%s: TTUSB DVB connected\n", __FUNCTION__);
++ dprintk("%s: TTUSB DVB connected\n", __func__);
-+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-+
- static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid);
+ udev = interface_to_usbdev(intf);
- 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__);
+@@ -1669,7 +1670,10 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
- 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)
+ mutex_unlock(&ttusb->semi2c);
- static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
- {
-- deb("%s\n",__FUNCTION__);
-+ deb("%s\n",__func__);
+- 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)
- 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)
+ kfree(ttusb);
- static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
- {
-- deb("%s\n",__FUNCTION__);
-+ deb("%s\n",__func__);
+- dprintk("%s: TTUSB DVB disconnected\n", __FUNCTION__);
++ dprintk("%s: TTUSB DVB disconnected\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 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)");
- static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
- {
-- deb("%s\n",__FUNCTION__);
-+ deb("%s\n",__func__);
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define dprintk if (debug) printk
- 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)
+ #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;
+ }
- static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
- {
-- deb("%s\n",__FUNCTION__);
-+ deb("%s\n",__func__);
+@@ -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);
+ }
- 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 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;
- static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
- {
-- deb("%s\n",__FUNCTION__);
-+ deb("%s\n",__func__);
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%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
- */
+ 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 ((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 ((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;
+ }
-- 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;
- }
+@@ -289,7 +291,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
+ memcpy(&b[4], params, param_length);
- /* 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 (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 ((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);
+ 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,
-+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-+
- #define deb_rc(args...) dprintk(debug,0x01,args)
- #define deb_ee(args...) dprintk(debug,0x02,args)
+ 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;
-@@ -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);
- }
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
- /* 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);
+ 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]);
-+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)
+- 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)
{
-@@ -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 (length < 8) {
+- printk("%s: packet too short - discarding\n", __FUNCTION__);
++ printk("%s: packet too short - discarding\n", __func__);
+ return;
}
-- 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);
+ if (length > 8 + MAX_PVA_LENGTH) {
+- printk("%s: packet too long - discarding\n", __FUNCTION__);
++ printk("%s: packet too long - discarding\n", __func__);
+ return;
+ }
-+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,
- };
+@@ -507,7 +509,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
+ break;
- static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap)
-@@ -176,17 +179,25 @@ static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap)
+ 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;
- /* DVB USB Driver stuff */
- static struct dvb_usb_device_properties ttusb2_properties;
-+static struct dvb_usb_device_properties ttusb2_properties_s2400;
+ if (dec->packet_length % 2) {
+- printk("%s: odd sized packet - discarding\n", __FUNCTION__);
++ printk("%s: odd sized packet - discarding\n", __func__);
+ return;
+ }
- 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;
- }
+@@ -554,7 +556,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
+ csum ^= ((dec->packet[i] << 8) + dec->packet[i + 1]);
- 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);
+ if (csum) {
+- printk("%s: checksum failed - discarding\n", __FUNCTION__);
++ printk("%s: checksum failed - discarding\n", __func__);
+ return;
+ }
-@@ -242,6 +253,54 @@ static struct dvb_usb_device_properties ttusb2_properties = {
+@@ -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);
}
- };
-+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 @@
+ 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,
- #include "mt352.h"
+ 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);
+ }
-+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)
+@@ -804,7 +806,7 @@ static void ttusb_dec_setup_urbs(struct ttusb_dec *dec)
{
- struct vp702x_fe_state *st = fe->demodulator_priv;
- vp702x_fe_refresh_state(st);
-- deb_fe("%s\n",__FUNCTION__);
-+ deb_fe("%s\n",__func__);
+ int i, j, buffer_offset = 0;
- 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)
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
- 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)
+ 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)
{
- 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;
- }
+ int i;
- static int vp702x_fe_sleep(struct dvb_frontend *fe)
- {
-- deb_fe("%s\n",__FUNCTION__);
-+ deb_fe("%s\n",__func__);
- return 0;
- }
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
- static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep)
+ if (mutex_lock_interruptible(&dec->iso_mutex))
+ return;
+@@ -889,7 +891,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
{
-- deb_fe("%s\n",__FUNCTION__);
-+ deb_fe("%s\n",__func__);
- return 0;
- }
+ int i, result;
-@@ -208,7 +208,7 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
- u8 cmd[8],ibuf[10];
- memset(cmd,0,8);
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
-- deb_fe("%s\n",__FUNCTION__);
-+ deb_fe("%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);
- if (m->msg_len > 4)
- return -EINVAL;
-@@ -230,7 +230,7 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
+ 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;
- 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;
- }
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
-@@ -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__);
+ dprintk(" ts_type:");
- st->tone_mode = tone;
+@@ -1012,7 +1014,7 @@ static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
+ unsigned long flags;
+ u8 x = 1;
-@@ -263,7 +263,7 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
+- 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 vp702x_fe_state *st = fe->demodulator_priv;
- u8 ibuf[10];
-- deb_fe("%s\n",__FUNCTION__);
-+ deb_fe("%s\n",__func__);
+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
- st->voltage = voltage;
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
-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);
+ if (!dvbdmx->dmx.frontend)
+ return -EINVAL;
+@@ -1113,7 +1115,7 @@ static int ttusb_dec_stop_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
-+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)
+ static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
{
-- return dvb_usb_device_init(intf,&vp702x_properties,THIS_MODULE,NULL);
-+ return dvb_usb_device_init(intf, &vp702x_properties,
-+ THIS_MODULE, NULL, adapter_nr);
- }
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
- 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)
+ switch (dvbdmxfeed->type) {
+ case DMX_TYPE_TS:
+@@ -1132,7 +1134,7 @@ static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec)
{
-- 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
+ int i;
-@@ -369,6 +393,11 @@ config DVB_TUNER_XC5000
- This device is only used inside a SiP called togther with a
- demodulator for now.
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
-+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
+ 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;
-@@ -379,6 +408,13 @@ config DVB_LNBP21
- help
- An SEC control chip.
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
-+config DVB_ISL6405
-+ tristate "ISL6405 SEC controller"
-+ depends on DVB_CORE && I2C
-+ default m if DVB_FE_CUSTOMISE
-+ help
-+ An SEC control chip.
-+
- config DVB_ISL6421
- tristate "ISL6421 SEC controller"
- depends on DVB_CORE && I2C
-diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
-index 16bd107..9747c73 100644
---- a/drivers/media/dvb/frontends/Makefile
-+++ b/drivers/media/dvb/frontends/Makefile
-@@ -38,6 +38,7 @@ obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
- obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
- obj-$(CONFIG_DVB_CX24123) += cx24123.o
- obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
-+obj-$(CONFIG_DVB_ISL6405) += isl6405.o
- obj-$(CONFIG_DVB_ISL6421) += isl6421.o
- obj-$(CONFIG_DVB_TDA10086) += tda10086.o
- obj-$(CONFIG_DVB_TDA826X) += tda826x.o
-@@ -51,3 +52,7 @@ obj-$(CONFIG_DVB_TUA6100) += tua6100.o
- obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131.o
- obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
- obj-$(CONFIG_DVB_TUNER_XC5000) += xc5000.o
-+obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
-+obj-$(CONFIG_DVB_AU8522) += au8522.o
-+obj-$(CONFIG_DVB_TDA10048) += tda10048.o
-+obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
-diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c
-new file mode 100644
-index 0000000..084a280
---- /dev/null
-+++ b/drivers/media/dvb/frontends/au8522.c
-@@ -0,0 +1,692 @@
-+/*
-+ Auvitek AU8522 QAM/8VSB demodulator driver
-+
-+ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+
-+*/
-+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/slab.h>
-+#include <linux/delay.h>
-+#include "dvb_frontend.h"
-+#include "dvb-pll.h"
-+#include "au8522.h"
-+
-+struct au8522_state {
-+
-+ struct i2c_adapter *i2c;
-+
-+ /* configuration settings */
-+ const struct au8522_config *config;
-+
-+ struct dvb_frontend frontend;
-+
-+ u32 current_frequency;
-+ fe_modulation_t current_modulation;
-+
-+};
-+
-+static int debug;
-+
-+#define dprintk(arg...) do { \
-+ if (debug) \
-+ printk(arg); \
-+ } while (0)
-+
-+/* 16 bit registers, 8 bit values */
-+static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
-+{
-+ int ret;
-+ u8 buf [] = { reg >> 8, reg & 0xff, data };
-+
-+ struct i2c_msg msg = { .addr = state->config->demod_address,
-+ .flags = 0, .buf = buf, .len = 3 };
-+
-+ ret = i2c_transfer(state->i2c, &msg, 1);
-+
-+ if (ret != 1)
-+ printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
-+ "ret == %i)\n", __func__, reg, data, ret);
-+
-+ return (ret != 1) ? -1 : 0;
-+}
-+
-+static u8 au8522_readreg(struct au8522_state *state, u16 reg)
-+{
-+ int ret;
-+ u8 b0 [] = { reg >> 8, reg & 0xff };
-+ u8 b1 [] = { 0 };
-+
-+ struct i2c_msg msg [] = {
-+ { .addr = state->config->demod_address, .flags = 0,
-+ .buf = b0, .len = 2 },
-+ { .addr = state->config->demod_address, .flags = I2C_M_RD,
-+ .buf = b1, .len = 1 } };
-+
-+ ret = i2c_transfer(state->i2c, msg, 2);
-+
-+ if (ret != 2)
-+ printk(KERN_ERR "%s: readreg error (ret == %i)\n",
-+ __func__, ret);
-+ return b1[0];
-+}
-+
-+static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-+{
-+ struct au8522_state *state = fe->demodulator_priv;
-+
-+ dprintk("%s(%d)\n", __func__, enable);
-+
-+ if (enable)
-+ return au8522_writereg(state, 0x106, 1);
-+ else
-+ return au8522_writereg(state, 0x106, 0);
-+}
-+
-+struct mse2snr_tab {
-+ u16 val;
-+ u16 data;
-+};
-+
-+/* VSB SNR lookup table */
-+static struct mse2snr_tab vsb_mse2snr_tab[] = {
-+ { 0, 270 },
-+ { 2, 250 },
-+ { 3, 240 },
-+ { 5, 230 },
-+ { 7, 220 },
-+ { 9, 210 },
-+ { 12, 200 },
-+ { 13, 195 },
-+ { 15, 190 },
-+ { 17, 185 },
-+ { 19, 180 },
-+ { 21, 175 },
-+ { 24, 170 },
-+ { 27, 165 },
-+ { 31, 160 },
-+ { 32, 158 },
-+ { 33, 156 },
-+ { 36, 152 },
-+ { 37, 150 },
-+ { 39, 148 },
-+ { 40, 146 },
-+ { 41, 144 },
-+ { 43, 142 },
-+ { 44, 140 },
-+ { 48, 135 },
-+ { 50, 130 },
-+ { 43, 142 },
-+ { 53, 125 },
-+ { 56, 120 },
-+ { 256, 115 },
-+};
-+
-+/* QAM64 SNR lookup table */
-+static struct mse2snr_tab qam64_mse2snr_tab[] = {
-+ { 15, 0 },
-+ { 16, 290 },
-+ { 17, 288 },
-+ { 18, 286 },
-+ { 19, 284 },
-+ { 20, 282 },
-+ { 21, 281 },
-+ { 22, 279 },
-+ { 23, 277 },
-+ { 24, 275 },
-+ { 25, 273 },
-+ { 26, 271 },
-+ { 27, 269 },
-+ { 28, 268 },
-+ { 29, 266 },
-+ { 30, 264 },
-+ { 31, 262 },
-+ { 32, 260 },
-+ { 33, 259 },
-+ { 34, 258 },
-+ { 35, 256 },
-+ { 36, 255 },
-+ { 37, 254 },
-+ { 38, 252 },
-+ { 39, 251 },
-+ { 40, 250 },
-+ { 41, 249 },
-+ { 42, 248 },
-+ { 43, 246 },
-+ { 44, 245 },
-+ { 45, 244 },
-+ { 46, 242 },
-+ { 47, 241 },
-+ { 48, 240 },
-+ { 50, 239 },
-+ { 51, 238 },
-+ { 53, 237 },
-+ { 54, 236 },
-+ { 56, 235 },
-+ { 57, 234 },
-+ { 59, 233 },
-+ { 60, 232 },
-+ { 62, 231 },
-+ { 63, 230 },
-+ { 65, 229 },
-+ { 67, 228 },
-+ { 68, 227 },
-+ { 70, 226 },
-+ { 71, 225 },
-+ { 73, 224 },
-+ { 74, 223 },
-+ { 76, 222 },
-+ { 78, 221 },
-+ { 80, 220 },
-+ { 82, 219 },
-+ { 85, 218 },
-+ { 88, 217 },
-+ { 90, 216 },
-+ { 92, 215 },
-+ { 93, 214 },
-+ { 94, 212 },
-+ { 95, 211 },
-+ { 97, 210 },
-+ { 99, 209 },
-+ { 101, 208 },
-+ { 102, 207 },
-+ { 104, 206 },
-+ { 107, 205 },
-+ { 111, 204 },
-+ { 114, 203 },
-+ { 118, 202 },
-+ { 122, 201 },
-+ { 125, 200 },
-+ { 128, 199 },
-+ { 130, 198 },
-+ { 132, 197 },
-+ { 256, 190 },
-+};
-+
-+/* QAM256 SNR lookup table */
-+static struct mse2snr_tab qam256_mse2snr_tab[] = {
-+ { 16, 0 },
-+ { 17, 400 },
-+ { 18, 398 },
-+ { 19, 396 },
-+ { 20, 394 },
-+ { 21, 392 },
-+ { 22, 390 },
-+ { 23, 388 },
-+ { 24, 386 },
-+ { 25, 384 },
-+ { 26, 382 },
-+ { 27, 380 },
-+ { 28, 379 },
-+ { 29, 378 },
-+ { 30, 377 },
-+ { 31, 376 },
-+ { 32, 375 },
-+ { 33, 374 },
-+ { 34, 373 },
-+ { 35, 372 },
-+ { 36, 371 },
-+ { 37, 370 },
-+ { 38, 362 },
-+ { 39, 354 },
-+ { 40, 346 },
-+ { 41, 338 },
-+ { 42, 330 },
-+ { 43, 328 },
-+ { 44, 326 },
-+ { 45, 324 },
-+ { 46, 322 },
-+ { 47, 320 },
-+ { 48, 319 },
-+ { 49, 318 },
-+ { 50, 317 },
-+ { 51, 316 },
-+ { 52, 315 },
-+ { 53, 314 },
-+ { 54, 313 },
-+ { 55, 312 },
-+ { 56, 311 },
-+ { 57, 310 },
-+ { 58, 308 },
-+ { 59, 306 },
-+ { 60, 304 },
-+ { 61, 302 },
-+ { 62, 300 },
-+ { 63, 298 },
-+ { 65, 295 },
-+ { 68, 294 },
-+ { 70, 293 },
-+ { 73, 292 },
-+ { 76, 291 },
-+ { 78, 290 },
-+ { 79, 289 },
-+ { 81, 288 },
-+ { 82, 287 },
-+ { 83, 286 },
-+ { 84, 285 },
-+ { 85, 284 },
-+ { 86, 283 },
-+ { 88, 282 },
-+ { 89, 281 },
-+ { 256, 280 },
-+};
-+
-+static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse,
-+ u16 *snr)
-+{
-+ int i, ret = -EINVAL;
-+ dprintk("%s()\n", __func__);
-+
-+ for (i = 0; i < sz; i++) {
-+ if (mse < tab[i].val) {
-+ *snr = tab[i].data;
-+ ret = 0;
-+ break;
-+ }
-+ }
-+ dprintk("%s() snr=%d\n", __func__, *snr);
-+ return ret;
-+}
-+
-+/* VSB Modulation table */
-+static struct {
-+ u16 reg;
-+ u16 data;
-+} VSB_mod_tab[] = {
-+ { 0x8090, 0x84 },
-+ { 0x4092, 0x11 },
-+ { 0x2005, 0x00 },
-+ { 0x8091, 0x80 },
-+ { 0x80a3, 0x0c },
-+ { 0x80a4, 0xe8 },
-+ { 0x8081, 0xc4 },
-+ { 0x80a5, 0x40 },
-+ { 0x80a7, 0x40 },
-+ { 0x80a6, 0x67 },
-+ { 0x8262, 0x20 },
-+ { 0x821c, 0x30 },
-+ { 0x80d8, 0x1a },
-+ { 0x8227, 0xa0 },
-+ { 0x8121, 0xff },
-+ { 0x80a8, 0xf0 },
-+ { 0x80a9, 0x05 },
-+ { 0x80aa, 0x77 },
-+ { 0x80ab, 0xf0 },
-+ { 0x80ac, 0x05 },
-+ { 0x80ad, 0x77 },
-+ { 0x80ae, 0x41 },
-+ { 0x80af, 0x66 },
-+ { 0x821b, 0xcc },
-+ { 0x821d, 0x80 },
-+ { 0x80b5, 0xfb },
-+ { 0x80b6, 0x8e },
-+ { 0x80b7, 0x39 },
-+ { 0x80a4, 0xe8 },
-+ { 0x8231, 0x13 },
-+};
-+
-+/* QAM Modulation table */
-+static struct {
-+ u16 reg;
-+ u16 data;
-+} QAM_mod_tab[] = {
-+ { 0x80a3, 0x09 },
-+ { 0x80a4, 0x00 },
-+ { 0x8081, 0xc4 },
-+ { 0x80a5, 0x40 },
-+ { 0x80b5, 0xfb },
-+ { 0x80b6, 0x8e },
-+ { 0x80b7, 0x39 },
-+ { 0x80aa, 0x77 },
-+ { 0x80ad, 0x77 },
-+ { 0x80a6, 0x67 },
-+ { 0x8262, 0x20 },
-+ { 0x821c, 0x30 },
-+ { 0x80b8, 0x3e },
-+ { 0x80b9, 0xf0 },
-+ { 0x80ba, 0x01 },
-+ { 0x80bb, 0x18 },
-+ { 0x80bc, 0x50 },
-+ { 0x80bd, 0x00 },
-+ { 0x80be, 0xea },
-+ { 0x80bf, 0xef },
-+ { 0x80c0, 0xfc },
-+ { 0x80c1, 0xbd },
-+ { 0x80c2, 0x1f },
-+ { 0x80c3, 0xfc },
-+ { 0x80c4, 0xdd },
-+ { 0x80c5, 0xaf },
-+ { 0x80c6, 0x00 },
-+ { 0x80c7, 0x38 },
-+ { 0x80c8, 0x30 },
-+ { 0x80c9, 0x05 },
-+ { 0x80ca, 0x4a },
-+ { 0x80cb, 0xd0 },
-+ { 0x80cc, 0x01 },
-+ { 0x80cd, 0xd9 },
-+ { 0x80ce, 0x6f },
-+ { 0x80cf, 0xf9 },
-+ { 0x80d0, 0x70 },
-+ { 0x80d1, 0xdf },
-+ { 0x80d2, 0xf7 },
-+ { 0x80d3, 0xc2 },
-+ { 0x80d4, 0xdf },
-+ { 0x80d5, 0x02 },
-+ { 0x80d6, 0x9a },
-+ { 0x80d7, 0xd0 },
-+ { 0x8250, 0x0d },
-+ { 0x8251, 0xcd },
-+ { 0x8252, 0xe0 },
-+ { 0x8253, 0x05 },
-+ { 0x8254, 0xa7 },
-+ { 0x8255, 0xff },
-+ { 0x8256, 0xed },
-+ { 0x8257, 0x5b },
-+ { 0x8258, 0xae },
-+ { 0x8259, 0xe6 },
-+ { 0x825a, 0x3d },
-+ { 0x825b, 0x0f },
-+ { 0x825c, 0x0d },
-+ { 0x825d, 0xea },
-+ { 0x825e, 0xf2 },
-+ { 0x825f, 0x51 },
-+ { 0x8260, 0xf5 },
-+ { 0x8261, 0x06 },
-+ { 0x821a, 0x00 },
-+ { 0x8546, 0x40 },
-+ { 0x8210, 0x26 },
-+ { 0x8211, 0xf6 },
-+ { 0x8212, 0x84 },
-+ { 0x8213, 0x02 },
-+ { 0x8502, 0x01 },
-+ { 0x8121, 0x04 },
-+ { 0x8122, 0x04 },
-+ { 0x852e, 0x10 },
-+ { 0x80a4, 0xca },
-+ { 0x80a7, 0x40 },
-+ { 0x8526, 0x01 },
-+};
-+
-+static int au8522_enable_modulation(struct dvb_frontend *fe,
-+ fe_modulation_t m)
-+{
-+ struct au8522_state *state = fe->demodulator_priv;
-+ int i;
-+
-+ dprintk("%s(0x%08x)\n", __func__, m);
-+
-+ switch (m) {
-+ case VSB_8:
-+ dprintk("%s() VSB_8\n", __func__);
-+ for (i = 0; i < ARRAY_SIZE(VSB_mod_tab); i++)
-+ au8522_writereg(state,
-+ VSB_mod_tab[i].reg,
-+ VSB_mod_tab[i].data);
-+ break;
-+ case QAM_64:
-+ case QAM_256:
-+ dprintk("%s() QAM 64/256\n", __func__);
-+ for (i = 0; i < ARRAY_SIZE(QAM_mod_tab); i++)
-+ au8522_writereg(state,
-+ QAM_mod_tab[i].reg,
-+ QAM_mod_tab[i].data);
-+ break;
-+ default:
-+ dprintk("%s() Invalid modulation\n", __func__);
-+ return -EINVAL;
-+ }
-+
-+ state->current_modulation = m;
-+
-+ return 0;
-+}
-+
-+/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-+static int au8522_set_frontend(struct dvb_frontend *fe,
-+ struct dvb_frontend_parameters *p)
-+{
-+ struct au8522_state *state = fe->demodulator_priv;
-+
-+ dprintk("%s(frequency=%d)\n", __func__, p->frequency);
-+
-+ state->current_frequency = p->frequency;
-+
-+ au8522_enable_modulation(fe, p->u.vsb.modulation);
-+
-+ /* Allow the demod to settle */
-+ msleep(100);
-+
-+ if (fe->ops.tuner_ops.set_params) {
-+ if (fe->ops.i2c_gate_ctrl)
-+ fe->ops.i2c_gate_ctrl(fe, 1);
-+ fe->ops.tuner_ops.set_params(fe, p);
-+ if (fe->ops.i2c_gate_ctrl)
-+ fe->ops.i2c_gate_ctrl(fe, 0);
-+ }
-+
-+ return 0;
-+}
-+
-+/* Reset the demod hardware and reset all of the configuration registers
-+ to a default state. */
-+static int au8522_init(struct dvb_frontend *fe)
-+{
-+ struct au8522_state *state = fe->demodulator_priv;
-+ dprintk("%s()\n", __func__);
-+
-+ au8522_writereg(state, 0xa4, 1 << 5);
-+
-+ au8522_i2c_gate_ctrl(fe, 1);
-+
-+ return 0;
-+}
-+
-+static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
-+{
-+ struct au8522_state *state = fe->demodulator_priv;
-+ u8 reg;
-+ u32 tuner_status = 0;
-+
-+ *status = 0;
-+
-+ if (state->current_modulation == VSB_8) {
-+ dprintk("%s() Checking VSB_8\n", __func__);
-+ reg = au8522_readreg(state, 0x4088);
-+ if (reg & 0x01)
-+ *status |= FE_HAS_VITERBI;
-+ if (reg & 0x02)
-+ *status |= FE_HAS_LOCK | FE_HAS_SYNC;
-+ } else {
-+ dprintk("%s() Checking QAM\n", __func__);
-+ reg = au8522_readreg(state, 0x4541);
-+ if (reg & 0x80)
-+ *status |= FE_HAS_VITERBI;
-+ if (reg & 0x20)
-+ *status |= FE_HAS_LOCK | FE_HAS_SYNC;
-+ }
-+
-+ switch (state->config->status_mode) {
-+ case AU8522_DEMODLOCKING:
-+ dprintk("%s() DEMODLOCKING\n", __func__);
-+ if (*status & FE_HAS_VITERBI)
-+ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
-+ break;
-+ case AU8522_TUNERLOCKING:
-+ /* Get the tuner status */
-+ dprintk("%s() TUNERLOCKING\n", __func__);
-+ if (fe->ops.tuner_ops.get_status) {
-+ if (fe->ops.i2c_gate_ctrl)
-+ fe->ops.i2c_gate_ctrl(fe, 1);
-+
-+ fe->ops.tuner_ops.get_status(fe, &tuner_status);
-+
-+ if (fe->ops.i2c_gate_ctrl)
-+ fe->ops.i2c_gate_ctrl(fe, 0);
-+ }
-+ if (tuner_status)
-+ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
-+ break;
-+ }
-+
-+ dprintk("%s() status 0x%08x\n", __func__, *status);
-+
-+ return 0;
-+}
-+
-+static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
-+{
-+ struct au8522_state *state = fe->demodulator_priv;
-+ int ret = -EINVAL;
-+
-+ dprintk("%s()\n", __func__);
-+
-+ if (state->current_modulation == QAM_256)
-+ ret = au8522_mse2snr_lookup(qam256_mse2snr_tab,
-+ ARRAY_SIZE(qam256_mse2snr_tab),
-+ au8522_readreg(state, 0x4522),
-+ snr);
-+ else if (state->current_modulation == QAM_64)
-+ ret = au8522_mse2snr_lookup(qam64_mse2snr_tab,
-+ ARRAY_SIZE(qam64_mse2snr_tab),
-+ au8522_readreg(state, 0x4522),
-+ snr);
-+ else /* VSB_8 */
-+ ret = au8522_mse2snr_lookup(vsb_mse2snr_tab,
-+ ARRAY_SIZE(vsb_mse2snr_tab),
-+ au8522_readreg(state, 0x4311),
-+ snr);
-+
-+ return ret;
-+}
-+
-+static int au8522_read_signal_strength(struct dvb_frontend *fe,
-+ u16 *signal_strength)
-+{
-+ return au8522_read_snr(fe, signal_strength);
-+}
-+
-+static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-+{
-+ struct au8522_state *state = fe->demodulator_priv;
-+
-+ if (state->current_modulation == VSB_8)
-+ *ucblocks = au8522_readreg(state, 0x4087);
-+ else
-+ *ucblocks = au8522_readreg(state, 0x4543);
-+
-+ return 0;
-+}
-+
-+static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber)
-+{
-+ return au8522_read_ucblocks(fe, ber);
-+}
-+
-+static int au8522_get_frontend(struct dvb_frontend *fe,
-+ struct dvb_frontend_parameters *p)
-+{
-+ struct au8522_state *state = fe->demodulator_priv;
-+
-+ p->frequency = state->current_frequency;
-+ p->u.vsb.modulation = state->current_modulation;
-+
-+ return 0;
-+}
-+
-+static int au8522_get_tune_settings(struct dvb_frontend *fe,
-+ struct dvb_frontend_tune_settings *tune)
-+{
-+ tune->min_delay_ms = 1000;
-+ return 0;
-+}
-+
-+static void au8522_release(struct dvb_frontend *fe)
-+{
-+ struct au8522_state *state = fe->demodulator_priv;
-+ kfree(state);
-+}
-+
-+static struct dvb_frontend_ops au8522_ops;
-+
-+struct dvb_frontend *au8522_attach(const struct au8522_config *config,
-+ struct i2c_adapter *i2c)
-+{
-+ struct au8522_state *state = NULL;
-+
-+ /* allocate memory for the internal state */
-+ state = kmalloc(sizeof(struct au8522_state), GFP_KERNEL);
-+ if (state == NULL)
-+ goto error;
-+
-+ /* setup the state */
-+ state->config = config;
-+ state->i2c = i2c;
-+ /* create dvb_frontend */
-+ memcpy(&state->frontend.ops, &au8522_ops,
-+ sizeof(struct dvb_frontend_ops));
-+ state->frontend.demodulator_priv = state;
-+
-+ if (au8522_init(&state->frontend) != 0) {
-+ printk(KERN_ERR "%s: Failed to initialize correctly\n",
-+ __func__);
-+ goto error;
-+ }
-+
-+ /* Note: Leaving the I2C gate open here. */
-+ au8522_i2c_gate_ctrl(&state->frontend, 1);
-+
-+ return &state->frontend;
-+
-+error:
-+ kfree(state);
-+ return NULL;
-+}
-+EXPORT_SYMBOL(au8522_attach);
-+
-+static struct dvb_frontend_ops au8522_ops = {
-+
-+ .info = {
-+ .name = "Auvitek AU8522 QAM/8VSB Frontend",
-+ .type = FE_ATSC,
-+ .frequency_min = 54000000,
-+ .frequency_max = 858000000,
-+ .frequency_stepsize = 62500,
-+ .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
-+ },
-+
-+ .init = au8522_init,
-+ .i2c_gate_ctrl = au8522_i2c_gate_ctrl,
-+ .set_frontend = au8522_set_frontend,
-+ .get_frontend = au8522_get_frontend,
-+ .get_tune_settings = au8522_get_tune_settings,
-+ .read_status = au8522_read_status,
-+ .read_ber = au8522_read_ber,
-+ .read_signal_strength = au8522_read_signal_strength,
-+ .read_snr = au8522_read_snr,
-+ .read_ucblocks = au8522_read_ucblocks,
-+ .release = au8522_release,
-+};
-+
-+module_param(debug, int, 0644);
-+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
-+
-+MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver");
-+MODULE_AUTHOR("Steven Toth");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/media/dvb/frontends/au8522.h b/drivers/media/dvb/frontends/au8522.h
-new file mode 100644
-index 0000000..d7affa3
---- /dev/null
-+++ b/drivers/media/dvb/frontends/au8522.h
-@@ -0,0 +1,56 @@
-+/*
-+ Auvitek AU8522 QAM/8VSB demodulator driver
-+
-+ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+
-+*/
-+
-+#ifndef __AU8522_H__
-+#define __AU8522_H__
-+
-+#include <linux/dvb/frontend.h>
-+
-+struct au8522_config {
-+ /* the demodulator's i2c address */
-+ u8 demod_address;
-+
-+ /* Return lock status based on tuner lock, or demod lock */
-+#define AU8522_TUNERLOCKING 0
-+#define AU8522_DEMODLOCKING 1
-+ u8 status_mode;
-+};
-+
-+#if defined(CONFIG_DVB_AU8522) || \
-+ (defined(CONFIG_DVB_AU8522_MODULE) && defined(MODULE))
-+extern struct dvb_frontend *au8522_attach(const struct au8522_config *config,
-+ struct i2c_adapter *i2c);
-+#else
-+static inline
-+struct dvb_frontend *au8522_attach(const struct au8522_config *config,
-+ struct i2c_adapter *i2c)
-+{
-+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-+ return NULL;
-+}
-+#endif /* CONFIG_DVB_AU8522 */
-+
-+#endif /* __AU8522_H__ */
-+
-+/*
-+ * Local variables:
-+ * c-basic-offset: 8
-+ */
-diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
-index a913f49..d268e65 100644
---- a/drivers/media/dvb/frontends/bcm3510.c
-+++ b/drivers/media/dvb/frontends/bcm3510.c
-@@ -91,7 +91,7 @@ static int bcm3510_writebytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8
- if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ dec->iso_buffer = pci_alloc_consistent(NULL,
+ ISO_FRAME_SIZE *
+@@ -1214,7 +1216,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
- 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;
- }
+ 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);
-@@ -110,7 +110,7 @@ static int bcm3510_readbytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 l
+@@ -1223,7 +1225,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
- 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)
+ static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
{
-- 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
- };
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
-@@ -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;
+ 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)
-- 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;
+ static int ttusb_dec_init_usb(struct ttusb_dec *dec)
+ {
+- 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/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 };
+ 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__);
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
- ret = i2c_transfer (state->i2c, &msg, 1);
+ 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;
+ }
- if (ret != 1)
- printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
-- __FUNCTION__, reg, data, ret);
-+ __func__, reg, data, ret);
+@@ -1294,7 +1296,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
- 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 } };
+ 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__);
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
- ret = i2c_transfer (state->i2c, msg, 2);
+ result = ttusb_dec_get_stb_state(dec, &mode, &model, &version);
-@@ -105,7 +105,7 @@ static int cx22700_set_inversion (struct cx22700_state* state, int inversion)
+@@ -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)
{
- u8 val;
+ int result;
-- dprintk ("%s\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
+- 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;
+ 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);
-- dprintk ("%s\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
+ return result;
+ }
+@@ -1454,7 +1458,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
+ dec->demux.write_to_decoder = NULL;
- 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;
+ 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);
-- dprintk ("%s\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
+ dvb_unregister_adapter(&dec->adapter);
+@@ -1468,7 +1472,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
- 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;
- };
+ if ((result = dvb_dmxdev_init(&dec->dmxdev, &dec->adapter)) < 0) {
+ printk("%s: dvb_dmxdev_init failed: error %d\n",
+- __FUNCTION__, result);
++ __func__, result);
--static int debug = 0;
-+static int debug;
- #define dprintk if (debug) printk
+ dvb_dmx_release(&dec->demux);
+ dvb_unregister_adapter(&dec->adapter);
+@@ -1480,7 +1484,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
- /* Register values to initialise the demod */
-@@ -90,7 +90,7 @@ static int cx22702_writereg (struct cx22702_state* state, u8 reg, u8 data)
+ 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);
- if (ret != 1)
- printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
-- __FUNCTION__, reg, data, ret);
-+ __func__, reg, data, ret);
+ dvb_dmxdev_release(&dec->dmxdev);
+@@ -1492,7 +1496,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
- 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 ((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);
- if (ret != 2)
-- printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
-+ printk("%s: readreg error (ret == %i)\n", __func__, ret);
+ dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
+@@ -1510,7 +1514,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
- 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)
+ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
{
- 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;
- }
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
-@@ -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;
- }
+ 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)
+ {
-@@ -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\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: status demod=0x%02x agc=0x%02x\n"
-- ,__FUNCTION__,reg0A,reg23);
-+ ,__func__,reg0A,reg23);
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
- 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)
+ dec->iso_stream_count = 0;
- 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;
- }
+@@ -1612,12 +1616,12 @@ static int ttusb_dec_probe(struct usb_interface *intf,
+ struct usb_device *udev;
+ struct ttusb_dec *dec;
-@@ -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("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
-- 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;
+ udev = interface_to_usbdev(intf);
-- dprintk("%s: init chip\n", __FUNCTION__);
-+ dprintk("%s: init chip\n", __func__);
+ 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;
+ }
- for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) {
- cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
-diff --git a/drivers/media/dvb/frontends/cx24110.h b/drivers/media/dvb/frontends/cx24110.h
-index 0ca3af4..1792adb 100644
---- a/drivers/media/dvb/frontends/cx24110.h
-+++ b/drivers/media/dvb/frontends/cx24110.h
-@@ -48,7 +48,7 @@ extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
- static inline struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
- struct i2c_adapter* i2c)
- {
-- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
-+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
- }
- #endif // CONFIG_DVB_CX24110
-diff --git a/drivers/media/dvb/frontends/cx24113.h b/drivers/media/dvb/frontends/cx24113.h
-new file mode 100644
-index 0000000..5ab3dd1
---- /dev/null
-+++ b/drivers/media/dvb/frontends/cx24113.h
-@@ -0,0 +1,48 @@
-+/*
-+ * Driver for Conexant CX24113/CX24128 Tuner (Satelite)
-+ *
-+ * Copyright (C) 2007-8 Patrick Boettcher <pb at linuxtv.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ *
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
-+ */
-+
-+#ifndef CX24113_H
-+#define CX24113_H
-+
-+struct dvb_frontend;
-+
-+struct cx24113_config {
-+ u8 i2c_addr; /* 0x14 or 0x54 */
-+
-+ u32 xtal_khz;
-+};
-+
-+/* TODO: #if defined(CONFIG_DVB_TUNER_CX24113) || \
-+ * (defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE)) */
-+
-+static inline struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
-+ const struct cx24113_config *config, struct i2c_adapter *i2c)
-+{
-+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-+ return NULL;
-+}
-+
-+static inline void cx24113_agc_callback(struct dvb_frontend *fe)
-+{
-+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-+}
-+
-+#endif /* CX24113_H */
-diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c
-index d74fdbd..7f68d78 100644
---- a/drivers/media/dvb/frontends/cx24123.c
-+++ b/drivers/media/dvb/frontends/cx24123.c
-@@ -1,24 +1,26 @@
- /*
-- Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
--
-- Copyright (C) 2005 Steven Toth <stoth at hauppauge.com>
--
-- Support for KWorld DVB-S 100 by Vadim Catana <skystar at moldova.cc>
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--*/
-+ * Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
-+ *
-+ * Copyright (C) 2005 Steven Toth <stoth at hauppauge.com>
-+ *
-+ * Support for KWorld DVB-S 100 by Vadim Catana <skystar at moldova.cc>
-+ *
-+ * Support for CX24123/CX24113-NIM by Patrick Boettcher <pb at linuxtv.org>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of
-+ * the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
+@@ -1692,7 +1696,7 @@ static void ttusb_dec_disconnect(struct usb_interface *intf)
+
+ usb_set_intfdata(intf, NULL);
- #include <linux/slab.h>
- #include <linux/kernel.h>
-@@ -32,9 +34,16 @@
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
- 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)
+ if (dec->active) {
+ ttusb_dec_exit_tasklet(dec);
+@@ -1749,7 +1753,7 @@ static int __init ttusb_dec_init(void)
+ int result;
- struct cx24123_state
-@@ -51,6 +60,10 @@ struct cx24123_state
- u32 pllarg;
- u32 FILTune;
+ 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;
-+ 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 */
+ 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,
};
--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;
+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,
+ };
-- 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); */
+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"
- 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;
- }
+ static char * text_buffer;
+-static int rds_users = 0;
++static int rds_users;
- 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 }
- };
+ static int rds_f_open(struct inode *in, struct file *fi)
+diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
+index f0a67e9..1ec18ed 100644
+--- a/drivers/media/radio/radio-aimslab.c
++++ b/drivers/media/radio/radio-aimslab.c
+@@ -36,7 +36,6 @@
+ #include <asm/uaccess.h> /* copy to/from user */
+ #include <linux/videodev2.h> /* kernel radio structs */
+ #include <media/v4l2-common.h>
+-#include <asm/semaphore.h> /* Lock for the I/O */
- ret = i2c_transfer(state->i2c, msg, 2);
+ #include <linux/version.h> /* for KERNEL_VERSION MACRO */
+ #define RADIO_VERSION KERNEL_VERSION(0,0,2)
+@@ -383,7 +382,9 @@ static const struct file_operations rtrack_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
- 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;
- }
+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,
+ };
-- 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); */
+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[] = {
-- return b1[0];
-+ return b;
- }
+ 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;
-+#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)
+@@ -563,7 +563,9 @@ static const struct file_operations cadet_fops = {
+ .read = cadet_read,
+ .ioctl = video_ioctl2,
+ .poll = cadet_poll,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
+index 99a3231..de49be9 100644
+--- a/drivers/media/radio/radio-gemtek-pci.c
++++ b/drivers/media/radio/radio-gemtek-pci.c
+@@ -368,7 +368,9 @@ static const struct file_operations gemtek_pci_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
+index 246422b..81f6aeb 100644
+--- a/drivers/media/radio/radio-gemtek.c
++++ b/drivers/media/radio/radio-gemtek.c
+@@ -397,7 +397,9 @@ static const struct file_operations gemtek_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek
+ };
+
+diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
+index bc51f4d..bddd3c4 100644
+--- a/drivers/media/radio/radio-maestro.c
++++ b/drivers/media/radio/radio-maestro.c
+@@ -100,7 +100,9 @@ static const struct file_operations maestro_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
+index 8e184cf..0133ecf 100644
+--- a/drivers/media/radio/radio-maxiradio.c
++++ b/drivers/media/radio/radio-maxiradio.c
+@@ -103,7 +103,9 @@ static const struct file_operations maxiradio_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
+index 82aedfc..0708021 100644
+--- a/drivers/media/radio/radio-rtrack2.c
++++ b/drivers/media/radio/radio-rtrack2.c
+@@ -288,7 +288,9 @@ static const struct file_operations rtrack2_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
+index 53e1148..66e052f 100644
+--- a/drivers/media/radio/radio-sf16fmi.c
++++ b/drivers/media/radio/radio-sf16fmi.c
+@@ -288,7 +288,9 @@ static const struct file_operations fmi_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
+index ebc5fbb..b0ccf7c 100644
+--- a/drivers/media/radio/radio-sf16fmr2.c
++++ b/drivers/media/radio/radio-sf16fmr2.c
+@@ -29,6 +29,8 @@ static struct mutex lock;
+ #include <linux/version.h> /* for KERNEL_VERSION MACRO */
+ #define RADIO_VERSION KERNEL_VERSION(0,0,2)
+
++#define AUD_VOL_INDEX 1
+
- static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
+ 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
{
- u8 nom_reg = cx24123_readreg(state, 0x0e);
-@@ -274,17 +291,17 @@ static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_invers
+ 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];
- 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 (dev->card_type != 11) return 1;
++ if (dev->card_type != 11)
++ return 1;
- 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;
+- 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);
-@@ -326,42 +343,42 @@ static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
+ 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;
- 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);
+ 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 FEC_AUTO:
-- dprintk("%s: set FEC to auto\n",__FUNCTION__);
-+ dprintk("set FEC to auto\n");
- cx24123_writereg(state, 0x0f, 0xfe);
+ 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:
-@@ -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 -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;
}
-@@ -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);
+diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c
+index 649f14d..77354ca 100644
+--- a/drivers/media/radio/radio-si470x.c
++++ b/drivers/media/radio/radio-si470x.c
+@@ -85,6 +85,7 @@
+ * Oliver Neukum <oliver at neukum.org>
+ * Version 1.0.7
+ * - usb autosuspend support
++ * - unplugging fixed
+ *
+ * ToDo:
+ * - add seeking support
+@@ -97,10 +98,10 @@
+ /* driver definitions */
+ #define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz at gmx.net>"
+ #define DRIVER_NAME "radio-si470x"
+-#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 6)
++#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 7)
+ #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
+ #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
+-#define DRIVER_VERSION "1.0.6"
++#define DRIVER_VERSION "1.0.7"
- /* 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;
- }
+ /* kernel includes */
+@@ -424,6 +425,7 @@ struct si470x_device {
-@@ -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));
+ /* driver management */
+ unsigned int users;
++ unsigned char disconnected;
-- 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);
+ /* Silabs internal registers (0..15) */
+ unsigned short registers[RADIO_REGISTER_NUM];
+@@ -440,6 +442,12 @@ struct si470x_device {
- return 0;
- }
-+
-+/*
-+ * 0x23:
-+ * [7:7] = BTI enabled
-+ * [6:6] = I2C repeater enabled
-+ * [5:5] = I2C repeater start
-+ * [0:0] = BTI start
+ /*
++ * Lock to prevent kfree of data before all users have releases the device.
+ */
++static DEFINE_MUTEX(open_close_lock);
+
-+/* 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;
++/*
+ * 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);
-- dprintk("%s: init frontend\n",__FUNCTION__);
-+ dprintk("init frontend\n");
++ if (radio->disconnected)
++ return;
+ if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
+ return;
- /* 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);
+@@ -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 (state->config->dont_use_pll)
-+ cx24123_repeater_mode(state, 1, 0);
-+
- return 0;
- }
+ if (!radio)
+ return -ENODEV;
-@@ -676,10 +720,10 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
++ 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);
- 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;
+@@ -1016,10 +1034,11 @@ static int si470x_fops_release(struct inode *inode, struct file *file)
-- dprintk("%s:\n",__FUNCTION__);
-+ dprintk("\n");
+ retval = si470x_stop(radio);
+ usb_autopm_put_interface(radio->intf);
+- return retval;
+ }
- /* 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;
+- return 0;
++done:
++ mutex_unlock(&open_close_lock);
++ return retval;
+ }
-- 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)
+@@ -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 cx24123_state *state = fe->demodulator_priv;
--
- int sync = cx24123_readreg(state, 0x14);
-- int lock = cx24123_readreg(state, 0x20);
+ struct si470x_device *radio = video_get_drvdata(video_devdata(file));
- *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 (radio->disconnected)
++ return -EIO;
+
- 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;
+ 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;
-@@ -813,23 +866,24 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
- (cx24123_readreg(state, 0x1d) << 8 |
- cx24123_readreg(state, 0x1e));
++ 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;
-- dprintk("%s: BER = %d\n",__FUNCTION__,*ber);
-+ dprintk("BER = %d\n", *ber);
++ if (radio->disconnected)
++ return -EIO;
+ if (tuner->index > 0)
+ return -EINVAL;
- return 0;
- }
+@@ -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;
--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)
++ 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 cx24123_state *state = fe->demodulator_priv;
+ struct si470x_device *radio = video_get_drvdata(video_devdata(file));
- *signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */
++ if (radio->disconnected)
++ return -EIO;
++
+ freq->type = V4L2_TUNER_RADIO;
+ freq->frequency = si470x_get_freq(radio);
-- dprintk("%s: Signal strength = %d\n",__FUNCTION__,*signal_strength);
-+ dprintk("Signal strength = %d\n", *signal_strength);
+@@ -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;
- return 0;
- }
++ if (radio->disconnected)
++ return -EIO;
+ if (freq->type != V4L2_TUNER_RADIO)
+ return -EINVAL;
--static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
-+static int cx24123_read_snr(struct dvb_frontend *fe, u16 *snr)
+@@ -1510,11 +1546,16 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
{
- 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);
+ struct si470x_device *radio = usb_get_intfdata(intf);
- return 0;
++ 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);
}
--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...");
+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,
+ };
- /* 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);
+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,
+ };
-+ if (state->config->agc_callback)
-+ state->config->agc_callback(fe);
-+
- return 0;
- }
+diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
+index 1366326..18f2abd 100644
+--- a/drivers/media/radio/radio-typhoon.c
++++ b/drivers/media/radio/radio-typhoon.c
+@@ -35,6 +35,7 @@
+ #include <linux/init.h> /* Initdata */
+ #include <linux/ioport.h> /* request_region */
+ #include <linux/proc_fs.h> /* radio card status report */
++#include <linux/seq_file.h>
+ #include <asm/io.h> /* outb, outb_p */
+ #include <asm/uaccess.h> /* copy to/from user */
+ #include <linux/videodev2.h> /* kernel radio structs */
+@@ -93,9 +94,6 @@ static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency);
+ static void typhoon_mute(struct typhoon_device *dev);
+ static void typhoon_unmute(struct typhoon_device *dev);
+ static int typhoon_setvol(struct typhoon_device *dev, int vol);
+-#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+-static int typhoon_get_info(char *buf, char **start, off_t offset, int len);
+-#endif
-@@ -872,14 +936,14 @@ static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
+ static void typhoon_setvol_generic(struct typhoon_device *dev, int vol)
{
- struct cx24123_state *state = fe->demodulator_priv;
-
-- dprintk("%s: get_frontend\n",__FUNCTION__);
-+ dprintk("\n");
+@@ -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,
+ };
- 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)
+@@ -366,30 +366,39 @@ static struct video_device typhoon_radio =
- 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;
- }
+ #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
-@@ -939,47 +1003,86 @@ static int cx24123_get_algo(struct dvb_frontend *fe)
- static void cx24123_release(struct dvb_frontend* fe)
+-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)
{
- struct cx24123_state* state = fe->demodulator_priv;
-- dprintk("%s\n",__FUNCTION__);
-+ dprintk("\n");
-+ i2c_del_adapter(&state->tuner_i2c_adapter);
- kfree(state);
+- 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 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)
++static int typhoon_proc_open(struct inode *inode, struct file *file)
+{
-+ return I2C_FUNC_I2C;
++ return single_open(file, typhoon_proc_show, NULL);
+}
+
-+static struct i2c_algorithm cx24123_tuner_i2c_algo = {
-+ .master_xfer = cx24123_tuner_i2c_tuner_xfer,
-+ .functionality = cx24123_tuner_i2c_func,
++static const struct file_operations typhoon_proc_fops = {
++ .owner = THIS_MODULE,
++ .open = typhoon_proc_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
+};
-+
-+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;
+ #endif /* CONFIG_RADIO_TYPHOON_PROC_FS */
- 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);
+ 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);
-+ 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;
- }
+ #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);
- /* 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;
+ #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
- /* 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;
- }
+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,
+ };
- /* create dvb_frontend */
- memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
- state->frontend.demodulator_priv = state;
+diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
+index 1832966..fe743aa 100644
+--- a/drivers/media/video/Kconfig
++++ b/drivers/media/video/Kconfig
+@@ -1,4 +1,50 @@
+ #
++# Generic video config states
++#
+
-+ /* create tuner i2c adapter */
-+ if (config->dont_use_pll)
-+ cx24123_repeater_mode(state, 1, 0);
++config VIDEO_V4L2
++ tristate
++ depends on VIDEO_DEV && VIDEO_V4L2_COMMON
++ default VIDEO_DEV && VIDEO_V4L2_COMMON
+
-+ 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;
-+ }
++config VIDEO_V4L1
++ tristate
++ depends on VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
++ default VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
+
- return &state->frontend;
++config VIDEOBUF_GEN
++ tristate
++
++config VIDEOBUF_DMA_SG
++ depends on HAS_DMA
++ select VIDEOBUF_GEN
++ tristate
++
++config VIDEOBUF_VMALLOC
++ select VIDEOBUF_GEN
++ tristate
++
++config VIDEOBUF_DVB
++ tristate
++ select VIDEOBUF_GEN
++ select VIDEOBUF_DMA_SG
++
++config VIDEO_BTCX
++ tristate
++
++config VIDEO_IR_I2C
++ tristate
++
++config VIDEO_IR
++ tristate
++ depends on INPUT
++ select VIDEO_IR_I2C if I2C
++
++config VIDEO_TVEEPROM
++ tristate
++ depends on I2C
++
++#
+ # Multimedia Video device configuration
+ #
- 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).");
+@@ -270,6 +316,15 @@ config VIDEO_SAA711X
+ To compile this driver as a module, choose M here: the
+ module will be called saa7115.
--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");
++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
+@@ -635,7 +690,7 @@ config VIDEO_MXB
+ tristate "Siemens-Nixdorf 'Multimedia eXtension Board'"
+ depends on PCI && VIDEO_V4L1 && I2C
+ select VIDEO_SAA7146_VV
+- select VIDEO_TUNER
++ select MEDIA_TUNER
+ select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
+ select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO
+ select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO
+@@ -689,8 +744,12 @@ source "drivers/media/video/cx88/Kconfig"
-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
+ source "drivers/media/video/cx23885/Kconfig"
- /* 0 = LNB voltage normal, 1 = LNB voltage inverted */
- int lnb_polarity;
++source "drivers/media/video/au0828/Kconfig"
+
-+ /* 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);
+ source "drivers/media/video/ivtv/Kconfig"
- /* make this a config parameter */
-- dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO);
-+ dib7000p_set_output_mode(state, state->cfg.output_mode);
- return ret;
- }
++source "drivers/media/video/cx18/Kconfig"
++
+ config VIDEO_M32R_AR
+ tristate "AR devices"
+ depends on M32R && VIDEO_V4L1
+@@ -836,4 +895,49 @@ config USB_STKWEBCAM
-@@ -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;
+ endif # V4L_USB_DRIVERS
-+ /* 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;
++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.
+
- 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);
++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.
+
-+ u8 output_mode;
- };
++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..a352c6e 100644
+--- a/drivers/media/video/Makefile
++++ b/drivers/media/video/Makefile
+@@ -4,7 +4,7 @@
- #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 {
+ 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
- static unsigned int dvb_pll_devcount;
+ msp3400-objs := msp3400-driver.o msp3400-kthreads.o
--static int debug = 0;
-+static int debug;
- module_param(debug, int, 0644);
- MODULE_PARM_DESC(debug, "enable verbose debug messages");
+@@ -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
+@@ -83,15 +84,7 @@ obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
+ obj-$(CONFIG_VIDEO_DPC) += dpc7146.o
+ obj-$(CONFIG_TUNER_3036) += tuner-3036.o
+
+-obj-$(CONFIG_VIDEO_TUNER) += tuner.o
+-
+-obj-$(CONFIG_TUNER_XC2028) += tuner-xc2028.o
+-obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o
+-obj-$(CONFIG_TUNER_MT20XX) += mt20xx.o
+-obj-$(CONFIG_TUNER_TDA8290) += tda8290.o
+-obj-$(CONFIG_TUNER_TEA5767) += tea5767.o
+-obj-$(CONFIG_TUNER_TEA5761) += tea5761.o
+-obj-$(CONFIG_TUNER_TDA9887) += tda9887.o
++obj-$(CONFIG_MEDIA_TUNER) += tuner.o
+
+ obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
+ obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
+@@ -131,9 +124,18 @@ obj-$(CONFIG_USB_VICAM) += usbvideo/
+ obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += usbvideo/
--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 */
+ obj-$(CONFIG_VIDEO_IVTV) += ivtv/
++obj-$(CONFIG_VIDEO_CX18) += cx18/
--/* 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 = {
- },
- };
+ obj-$(CONFIG_VIDEO_VIVI) += vivi.o
+ obj-$(CONFIG_VIDEO_CX23885) += cx23885/
--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 = {
- },
- };
++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
++EXTRA_CFLAGS += -Idrivers/media/common/tuners
+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 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 = {
- }
- };
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
--/* 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 = {
- },
- };
+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
--/*
-- * 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 int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
- 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,
+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,
};
- /* ----------------------------------------------------------- */
-@@ -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
+diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig
new file mode 100644
-index 0000000..33d33f4
+index 0000000..cab277f
--- /dev/null
-+++ b/drivers/media/dvb/frontends/isl6405.c
-@@ -0,0 +1,164 @@
++++ 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 MEDIA_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..cd2c582
+--- /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/common/tuners
++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 @@
+/*
-+ * isl6405.c - driver for dual lnb supply and control ic ISL6405
++ * Driver for the Auvitek USB bridge
++ *
++ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include "au0828.h"
++#include "au0828-cards.h"
++
++struct au0828_board au0828_boards[] = {
++ [AU0828_BOARD_UNKNOWN] = {
++ .name = "Unknown board",
++ },
++ [AU0828_BOARD_HAUPPAUGE_HVR850] = {
++ .name = "Hauppauge HVR850",
++ },
++ [AU0828_BOARD_HAUPPAUGE_HVR950Q] = {
++ .name = "Hauppauge HVR950Q",
++ },
++ [AU0828_BOARD_DVICO_FUSIONHDTV7] = {
++ .name = "DViCO FusionHDTV USB",
++ },
++};
++
++/* Tuner callback function for au0828 boards. Currently only needed
++ * for HVR1500Q, which has an xc5000 tuner.
++ */
++int au0828_tuner_callback(void *priv, int command, int arg)
++{
++ struct au0828_dev *dev = priv;
++
++ dprintk(1, "%s()\n", __func__);
++
++ switch (dev->board) {
++ case AU0828_BOARD_HAUPPAUGE_HVR850:
++ case AU0828_BOARD_HAUPPAUGE_HVR950Q:
++ case AU0828_BOARD_DVICO_FUSIONHDTV7:
++ if (command == 0) {
++ /* Tuner Reset Command from xc5000 */
++ /* Drive the tuner into reset and out */
++ au0828_clear(dev, REG_001, 2);
++ mdelay(200);
++ au0828_set(dev, REG_001, 2);
++ mdelay(50);
++ return 0;
++ } else {
++ printk(KERN_ERR
++ "%s(): Unknown command.\n", __func__);
++ return -EINVAL;
++ }
++ break;
++ }
++
++ return 0; /* Should never be here */
++}
++
++static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
++{
++ struct tveeprom tv;
++
++ tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data);
++
++ /* Make sure we support the board model */
++ switch (tv.model) {
++ case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */
++ case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */
++ break;
++ default:
++ printk(KERN_WARNING "%s: warning: "
++ "unknown hauppauge model #%d\n", __func__, tv.model);
++ break;
++ }
++
++ printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
++ __func__, tv.model);
++}
++
++void au0828_card_setup(struct au0828_dev *dev)
++{
++ static u8 eeprom[256];
++
++ dprintk(1, "%s()\n", __func__);
++
++ if (dev->i2c_rc == 0) {
++ dev->i2c_client.addr = 0xa0 >> 1;
++ tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom));
++ }
++
++ switch (dev->board) {
++ case AU0828_BOARD_HAUPPAUGE_HVR850:
++ case AU0828_BOARD_HAUPPAUGE_HVR950Q:
++ if (dev->i2c_rc == 0)
++ hauppauge_eeprom(dev, eeprom+0xa0);
++ break;
++ }
++}
++
++/*
++ * The bridge has between 8 and 12 gpios.
++ * Regs 1 and 0 deal with output enables.
++ * Regs 3 and 2 deal with direction.
++ */
++void au0828_gpio_setup(struct au0828_dev *dev)
++{
++ dprintk(1, "%s()\n", __func__);
++
++ switch (dev->board) {
++ case AU0828_BOARD_HAUPPAUGE_HVR850:
++ case AU0828_BOARD_HAUPPAUGE_HVR950Q:
++ /* GPIO's
++ * 4 - CS5340
++ * 5 - AU8522 Demodulator
++ * 6 - eeprom W/P
++ * 9 - XC5000 Tuner
++ */
++
++ /* Into reset */
++ au0828_write(dev, REG_003, 0x02);
++ au0828_write(dev, REG_002, 0x88 | 0x20);
++ au0828_write(dev, REG_001, 0x0);
++ au0828_write(dev, REG_000, 0x0);
++ msleep(100);
++
++ /* Out of reset */
++ au0828_write(dev, REG_003, 0x02);
++ au0828_write(dev, REG_001, 0x02);
++ au0828_write(dev, REG_002, 0x88 | 0x20);
++ au0828_write(dev, REG_000, 0x88 | 0x20 | 0x40);
++ msleep(250);
++ break;
++ case AU0828_BOARD_DVICO_FUSIONHDTV7:
++ /* GPIO's
++ * 6 - ?
++ * 8 - AU8522 Demodulator
++ * 9 - XC5000 Tuner
++ */
++
++ /* Into reset */
++ au0828_write(dev, REG_003, 0x02);
++ au0828_write(dev, REG_002, 0xa0);
++ au0828_write(dev, REG_001, 0x0);
++ au0828_write(dev, REG_000, 0x0);
++ msleep(100);
++
++ /* Out of reset */
++ au0828_write(dev, REG_003, 0x02);
++ au0828_write(dev, REG_002, 0xa0);
++ au0828_write(dev, REG_001, 0x02);
++ au0828_write(dev, REG_000, 0xa0);
++ msleep(250);
++ break;
++ }
++}
++
++/* table of devices that work with this driver */
++struct usb_device_id au0828_usb_id_table [] = {
++ { USB_DEVICE(0x2040, 0x7200),
++ .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
++ { USB_DEVICE(0x2040, 0x7240),
++ .driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 },
++ { USB_DEVICE(0x0fe9, 0xd620),
++ .driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 },
++ { },
++};
++
++MODULE_DEVICE_TABLE(usb, au0828_usb_id_table);
+diff --git a/drivers/media/video/au0828/au0828-cards.h b/drivers/media/video/au0828/au0828-cards.h
+new file mode 100644
+index 0000000..e26f54a
+--- /dev/null
++++ b/drivers/media/video/au0828/au0828-cards.h
+@@ -0,0 +1,25 @@
++/*
++ * Driver for the Auvitek USB bridge
++ *
++ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
+ *
-+ * 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 free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2
-+ * of the License, or (at your option) any later version.
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
++ * GNU General Public License for more details.
+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#define AU0828_BOARD_UNKNOWN 0
++#define AU0828_BOARD_HAUPPAUGE_HVR950Q 1
++#define AU0828_BOARD_HAUPPAUGE_HVR850 2
++#define AU0828_BOARD_DVICO_FUSIONHDTV7 3
+diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c
+new file mode 100644
+index 0000000..54bfc0f
+--- /dev/null
++++ b/drivers/media/video/au0828/au0828-core.c
+@@ -0,0 +1,256 @@
++/*
++ * Driver for the Auvitek USB bridge
+ *
++ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
+ *
-+ * You 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
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
++ * GNU General Public License for more details.
+ *
-+ * the project's page is at http://www.linuxtv.org
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
-+#include <linux/delay.h>
-+#include <linux/errno.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
++
+#include <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/slab.h>
++#include <linux/videodev2.h>
++#include <media/v4l2-common.h>
++#include <linux/mutex.h>
+
-+#include "dvb_frontend.h"
-+#include "isl6405.h"
++#include "au0828.h"
+
-+struct isl6405 {
-+ u8 config;
-+ u8 override_or;
-+ u8 override_and;
-+ struct i2c_adapter *i2c;
-+ u8 i2c_addr;
-+};
++/*
++ * 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");
+
-+static int isl6405_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
++#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)
+{
-+ 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) };
++ 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];
++}
+
-+ 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;
++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);
++}
+
-+ return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;
++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 isl6405_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
++static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
++ u16 index, unsigned char *cp, u16 size)
+{
-+ 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) };
++ 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);
++ }
+
-+ 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;
++ mutex_unlock(&dev->mutex);
++ return status;
++}
+
-+ return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;
++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 isl6405_release(struct dvb_frontend *fe)
++static void au0828_usb_disconnect(struct usb_interface *interface)
+{
-+ /* power off */
-+ isl6405_set_voltage(fe, SEC_VOLTAGE_OFF);
++ 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);
+
-+ /* 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)
++static int au0828_usb_probe(struct usb_interface *interface,
++ const struct usb_device_id *id)
+{
-+ struct isl6405 *isl6405 = kmalloc(sizeof(struct isl6405), GFP_KERNEL);
-+ if (!isl6405)
-+ return NULL;
++ int ifnum;
++ struct au0828_dev *dev;
++ struct usb_device *usbdev = interface_to_usbdev(interface);
+
-+ /* 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;
++ ifnum = interface->altsetting->desc.bInterfaceNumber;
+
-+ /* bits which should be forced to '1' */
-+ isl6405->override_or = override_set;
++ if (ifnum != 0)
++ return -ENODEV;
+
-+ /* bits which should be forced to '0' */
-+ isl6405->override_and = ~override_clear;
++ 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);
+
-+ /* detect if it is present or not */
-+ if (isl6405_set_voltage(fe, SEC_VOLTAGE_OFF)) {
-+ kfree(isl6405);
-+ fe->sec_priv = NULL;
-+ return NULL;
++ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
++ if (dev == NULL) {
++ printk(KERN_ERR "%s() Unable to allocate memory\n", __func__);
++ return -ENOMEM;
+ }
+
-+ /* install release callback */
-+ fe->ops.release_sec = isl6405_release;
++ mutex_init(&dev->mutex);
++ mutex_init(&dev->dvb.lock);
++ dev->usbdev = usbdev;
++ dev->board = id->driver_info;
+
-+ /* override frontend ops */
-+ fe->ops.set_voltage = isl6405_set_voltage;
-+ fe->ops.enable_high_lnb_voltage = isl6405_enable_high_lnb_voltage;
++ usb_set_intfdata(interface, dev);
+
-+ return fe;
++ /* 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;
+}
-+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
-+ */
++static struct usb_driver au0828_usb_driver = {
++ .name = DRIVER_NAME,
++ .probe = au0828_usb_probe,
++ .disconnect = au0828_usb_disconnect,
++ .id_table = au0828_usb_id_table,
++};
+
-+#ifndef _ISL6405_H
-+#define _ISL6405_H
++static int __init au0828_init(void)
++{
++ int ret;
+
-+#include <linux/dvb/frontend.h>
++ if (au0828_debug & 1)
++ printk(KERN_INFO "%s() Debugging is enabled\n", __func__);
+
-+/* system register bits */
++ if (au0828_debug & 2)
++ printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__);
+
-+/* this bit selects register (control) 1 or 2
-+ note that the bit maps are different */
++ if (au0828_debug & 4)
++ printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__);
+
-+#define ISL6405_SR 0x80
++ if (au0828_debug & 8)
++ printk(KERN_INFO "%s() Bridge Debugging is enabled\n",
++ __func__);
+
-+/* 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
++ printk(KERN_INFO "au0828 driver loaded\n");
+
-+/* 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
++ ret = usb_register(&au0828_usb_driver);
++ if (ret)
++ printk(KERN_ERR "usb_register failed, error = %d\n", ret);
+
-+#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)
++ return ret;
++}
++
++static void __exit au0828_exit(void)
+{
-+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-+ return NULL;
++ usb_deregister(&au0828_usb_driver);
+}
-+#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
++module_init(au0828_init);
++module_exit(au0828_exit);
++
++MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");
++MODULE_AUTHOR("Steven Toth <stoth at hauppauge.com>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c
new file mode 100644
-index 0000000..04c562c
+index 0000000..1371b4e
--- /dev/null
-+++ b/drivers/media/dvb/frontends/itd1000.c
-@@ -0,0 +1,400 @@
++++ b/drivers/media/video/au0828/au0828-dvb.c
+@@ -0,0 +1,373 @@
+/*
-+ * Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
++ * Driver for the Auvitek USB bridge
+ *
-+ * Copyright (c) 2007-8 Patrick Boettcher <pb at linuxtv.org>
++ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
@@ -379294,398 +544412,758 @@
+ *
+ * You 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.=
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/delay.h>
-+#include <linux/dvb/frontend.h>
-+#include <linux/i2c.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/suspend.h>
++#include <media/v4l2-common.h>
+
-+#include "dvb_frontend.h"
++#include "au0828.h"
++#include "au8522.h"
++#include "xc5000.h"
+
-+#include "itd1000.h"
-+#include "itd1000_priv.h"
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
-+static int debug;
-+module_param(debug, int, 0644);
-+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
++#define _AU0828_BULKPIPE 0x83
++#define _BULKPIPESIZE 0xe522
+
-+#define deb(args...) do { \
-+ if (debug) { \
-+ printk(KERN_DEBUG "ITD1000: " args);\
-+ printk("\n"); \
-+ } \
-+} while (0)
++static struct au8522_config hauppauge_hvr950q_config = {
++ .demod_address = 0x8e >> 1,
++ .status_mode = AU8522_DEMODLOCKING,
++};
+
-+#define warn(args...) do { \
-+ printk(KERN_WARNING "ITD1000: " args); \
-+ printk("\n"); \
-+} while (0)
++static struct xc5000_config hauppauge_hvr950q_tunerconfig = {
++ .i2c_address = 0x61,
++ .if_khz = 6000,
++ .tuner_callback = au0828_tuner_callback
++};
+
-+#define info(args...) do { \
-+ printk(KERN_INFO "ITD1000: " args); \
-+ printk("\n"); \
-+} while (0)
++/*-------------------------------------------------------------------*/
++static void urb_completion(struct urb *purb)
++{
++ u8 *ptr;
++ struct au0828_dev *dev = purb->context;
++ int ptype = usb_pipetype(purb->pipe);
+
-+/* 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)
++ 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)
+{
-+ 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);
++ int i;
+
-+ /* deb("wr %02x: %02x", reg, v[0]); */
++ dprintk(2, "%s()\n", __func__);
+
-+ if (i2c_transfer(state->i2c, &msg, 1) != 1) {
-+ printk(KERN_WARNING "itd1000 I2C write failed\n");
-+ return -EREMOTEIO;
++ 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 itd1000_read_reg(struct itd1000_state *state, u8 reg)
++static int start_urb_transfer(struct au0828_dev *dev)
+{
-+ 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 },
-+ };
++ struct urb *purb;
++ int i, ret = -ENOMEM;
+
-+ /* ugly flexcop workaround */
-+ itd1000_write_regs(state, (reg - 1) & 0xff, &state->shadow[(reg - 1) & 0xff], 1);
++ dprintk(2, "%s()\n", __func__);
+
-+ if (i2c_transfer(state->i2c, msg, 2) != 2) {
-+ warn("itd1000 I2C read failed");
-+ return -EREMOTEIO;
++ if (dev->urb_streaming) {
++ dprintk(2, "%s: iso xfer already running!\n", __func__);
++ return 0;
+ }
-+ return val;
++
++ 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] = NULL;
++ 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 inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v)
++static int au0828_dvb_start_feed(struct dvb_demux_feed *feed)
+{
-+ int ret = itd1000_write_regs(state, r, &v, 1);
-+ state->shadow[r] = v;
++ 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__);
+
-+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 },
-+};
++ 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);
++ }
+
-+static void itd1000_set_lpf_bw(struct itd1000_state *state, u32 symbol_rate)
++ return ret;
++}
++
++static int dvb_register(struct au0828_dev *dev)
+{
-+ 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;
++ struct au0828_dvb *dvb = &dev->dvb;
++ int result;
+
-+ deb("symbol_rate = %d", symbol_rate);
++ dprintk(1, "%s()\n", __func__);
+
-+ /* not sure what is that ? - starting to download the table */
-+ itd1000_write_reg(state, CON1, con1 | (1 << 1));
++ /* 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;
+
-+ 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;
-+ }
++ /* 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;
++ }
+
-+ itd1000_write_reg(state, CON1, con1 | (0 << 1));
-+}
++ /* 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;
++ }
+
-+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 },
-+};
++ 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;
++ }
+
-+static void itd1000_set_vco(struct itd1000_state *state, u32 freq_khz)
++ 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)
+{
-+ 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;
++ struct au0828_dvb *dvb = &dev->dvb;
+
-+ /* reserved bit again (reset ?) */
-+ itd1000_write_reg(state, GVBB_I2C, gvbb_i2c | (1 << 6));
++ dprintk(1, "%s()\n", __func__);
+
-+ 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);
++ if (dvb->frontend == NULL)
++ return;
+
-+ adcout = itd1000_read_reg(state, PLLLOCK) & 0x0f;
++ 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);
++}
+
-+ deb("VCO: %dkHz: %d -> ADCOUT: %d %02x", freq_khz, itd1000_vcorg[i].vcorg, adcout, vco_chp1_i2c);
++/* 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;
+
-+ 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;
++ dprintk(1, "%s()\n", __func__);
++
++ /* init frontend */
++ switch (dev->board) {
++ case AU0828_BOARD_HAUPPAUGE_HVR850:
++ case AU0828_BOARD_HAUPPAUGE_HVR950Q:
++ case AU0828_BOARD_DVICO_FUSIONHDTV7:
++ dvb->frontend = dvb_attach(au8522_attach,
++ &hauppauge_hvr950q_config,
++ &dev->i2c_adap);
++ if (dvb->frontend != NULL) {
++ hauppauge_hvr950q_tunerconfig.priv = dev;
++ dvb_attach(xc5000_attach, dvb->frontend,
++ &dev->i2c_adap,
++ &hauppauge_hvr950q_tunerconfig);
+ }
++ break;
++ default:
++ printk(KERN_WARNING "The frontend of your DVB/ATSC card "
++ "isn't supported yet\n");
++ break;
++ }
++ if (NULL == dvb->frontend) {
++ printk(KERN_ERR "%s() Frontend initialization failed\n",
++ __func__);
++ return -1;
++ }
++
++ /* Put the analog decoder in standby to keep it quiet */
++ au0828_call_i2c_clients(dev, TUNER_SET_STANDBY, NULL);
++
++ if (dvb->frontend->ops.analog_ops.standby)
++ dvb->frontend->ops.analog_ops.standby(dvb->frontend);
++
++ /* register everything */
++ ret = dvb_register(dev);
++ if (ret < 0) {
++ if (dvb->frontend->ops.release)
++ dvb->frontend->ops.release(dvb->frontend);
++ return ret;
+ }
++
++ return 0;
+}
+diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c
+new file mode 100644
+index 0000000..741a493
+--- /dev/null
++++ b/drivers/media/video/au0828/au0828-i2c.c
+@@ -0,0 +1,381 @@
++/*
++ * Driver for the Auvitek AU0828 USB bridge
++ *
++ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
+
-+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 } }
-+};
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/io.h>
+
++#include "au0828.h"
+
-+#define FREF 16
++#include <media/v4l2-common.h>
+
-+static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
++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)
+{
-+ int i, j;
-+ u32 plln, pllf;
-+ u64 tmp;
++ struct au0828_dev *dev = i2c_adap->algo_data;
++ return au0828_read(dev, REG_201) & 0x08 ? 0 : 1;
++}
+
-+ plln = (freq_khz * 1000) / 2 / FREF;
++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;
++}
+
-+ /* Compute the factional part times 1000 */
-+ tmp = plln % 1000000;
-+ plln /= 1000000;
++static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap)
++{
++ int count;
+
-+ tmp *= 1048576;
-+ do_div(tmp, 1000000);
-+ pllf = (u32) tmp;
++ for (count = 0; count < I2C_WAIT_RETRY; count++) {
++ if (!i2c_slave_did_read_ack(i2c_adap))
++ break;
++ udelay(I2C_WAIT_DELAY);
++ }
+
-+ 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);
++ if (I2C_WAIT_RETRY == count)
++ return 0;
+
-+ 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);
++ return 1;
++}
+
-+ 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]);
++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);
+ }
+
-+ itd1000_set_vco(state, freq_khz);
++ if (I2C_WAIT_RETRY == count)
++ return 0;
++
++ return 1;
+}
+
-+static int itd1000_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
++static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap)
+{
-+ struct itd1000_state *state = fe->tuner_priv;
-+ u8 pllcon1;
++ struct au0828_dev *dev = i2c_adap->algo_data;
++ return au0828_read(dev, REG_201) & 0x04 ? 1 : 0;
++}
+
-+ itd1000_set_lo(state, p->frequency);
-+ itd1000_set_lpf_bw(state, p->u.qpsk.symbol_rate);
++static int i2c_wait_write_done(struct i2c_adapter *i2c_adap)
++{
++ int count;
+
-+ pllcon1 = itd1000_read_reg(state, PLLCON1) & 0x7f;
-+ itd1000_write_reg(state, PLLCON1, pllcon1 | (1 << 7));
-+ itd1000_write_reg(state, PLLCON1, pllcon1);
++ for (count = 0; count < I2C_WAIT_RETRY; count++) {
++ if (i2c_is_write_done(i2c_adap))
++ break;
++ udelay(I2C_WAIT_DELAY);
++ }
+
-+ return 0;
++ if (I2C_WAIT_RETRY == count)
++ return 0;
++
++ return 1;
+}
+
-+static int itd1000_get_frequency(struct dvb_frontend *fe, u32 *frequency)
++static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
+{
-+ struct itd1000_state *state = fe->tuner_priv;
-+ *frequency = state->frequency;
-+ return 0;
++ struct au0828_dev *dev = i2c_adap->algo_data;
++ return au0828_read(dev, REG_201) & 0x10 ? 1 : 0;
+}
+
-+static int itd1000_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
++static int i2c_wait_done(struct i2c_adapter *i2c_adap)
+{
-+ return 0;
++ 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;
+}
+
-+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 },
-+};
++/* 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;
+
-+static u8 itd1000_reinit_tab[][2] = {
-+ { VCO_CHP1_I2C, 0x8a },
-+ { BW, 0x87 },
-+ { GVBB_I2C, 0x03 },
-+ { BBGVMIN, 0x03 },
-+ { CON1, 0x2e },
-+};
++ 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);
+
-+static int itd1000_init(struct dvb_frontend *fe)
++ 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 itd1000_state *state = fe->tuner_priv;
++ struct au0828_dev *dev = i2c_adap->algo_data;
+ 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]);
++ dprintk(4, "%s()\n", __func__);
+
-+ for (i = 0; i < ARRAY_SIZE(itd1000_reinit_tab); i++)
-+ itd1000_write_reg(state, itd1000_reinit_tab[i][0], itd1000_reinit_tab[i][1]);
++ au0828_write(dev, REG_2FF, 0x01);
++ au0828_write(dev, REG_202, 0x07);
+
-+ return 0;
++ /* 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 itd1000_sleep(struct dvb_frontend *fe)
++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 itd1000_release(struct dvb_frontend *fe)
++static int detach_inform(struct i2c_client *client)
+{
-+ kfree(fe->tuner_priv);
-+ fe->tuner_priv = NULL;
++ dprintk(1, "i2c detach [client=%s]\n", client->name);
++
+ 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 */
-+ },
++void au0828_call_i2c_clients(struct au0828_dev *dev,
++ unsigned int cmd, void *arg)
++{
++ if (dev->i2c_rc != 0)
++ return;
+
-+ .release = itd1000_release,
++ i2c_clients_command(&dev->i2c_adap, cmd, arg);
++}
+
-+ .init = itd1000_init,
-+ .sleep = itd1000_sleep,
++static u32 au0828_functionality(struct i2c_adapter *adap)
++{
++ return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
++}
+
-+ .set_params = itd1000_set_parameters,
-+ .get_frequency = itd1000_get_frequency,
-+ .get_bandwidth = itd1000_get_bandwidth
++static struct i2c_algorithm au0828_i2c_algo_template = {
++ .master_xfer = i2c_xfer,
++ .functionality = au0828_functionality,
+};
+
++/* ----------------------------------------------------------------------- */
+
-+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;
++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,
++};
+
-+ state = kzalloc(sizeof(struct itd1000_state), GFP_KERNEL);
-+ if (state == NULL)
-+ return NULL;
++static struct i2c_client au0828_i2c_client_template = {
++ .name = "au0828 internal",
++};
+
-+ state->cfg = cfg;
-+ state->i2c = i2c;
++static char *i2c_devs[128] = {
++ [0x8e >> 1] = "au8522",
++ [0xa0 >> 1] = "eeprom",
++ [0xc2 >> 1] = "tuner/xc5000",
++};
+
-+ i = itd1000_read_reg(state, 0);
-+ if (i != 0) {
-+ kfree(state);
-+ return NULL;
++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] : "???");
+ }
-+ 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);
++/* init + register i2c algo-bit adapter */
++int au0828_i2c_register(struct au0828_dev *dev)
++{
++ dprintk(1, "%s()\n", __func__);
+
-+ memcpy(&fe->ops.tuner_ops, &itd1000_tuner_ops, sizeof(struct dvb_tuner_ops));
++ 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));
+
-+ fe->tuner_priv = state;
++ dev->i2c_adap.dev.parent = &dev->usbdev->dev;
+
-+ return fe;
++ 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;
+}
-+EXPORT_SYMBOL(itd1000_attach);
+
-+MODULE_AUTHOR("Patrick Boettcher <pb at linuxtv.org>");
-+MODULE_DESCRIPTION("Integrant ITD1000 driver");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/media/dvb/frontends/itd1000.h b/drivers/media/dvb/frontends/itd1000.h
++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..5e18df0
+index 0000000..3982755
--- /dev/null
-+++ b/drivers/media/dvb/frontends/itd1000.h
-@@ -0,0 +1,42 @@
++++ b/drivers/media/video/au0828/au0828-reg.h
+@@ -0,0 +1,38 @@
+/*
-+ * Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
++ * Driver for the Auvitek USB bridge
+ *
-+ * Copyright (c) 2007 Patrick Boettcher <pb at linuxtv.org>
++ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
@@ -379700,40 +545178,36 @@
+ *
+ * You 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.=
++ * 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;
-+};
++/* 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
+
-+#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
++#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
+
-+#endif
-diff --git a/drivers/media/dvb/frontends/itd1000_priv.h b/drivers/media/dvb/frontends/itd1000_priv.h
++#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..8cdc54e
+index 0000000..7beb571
--- /dev/null
-+++ b/drivers/media/dvb/frontends/itd1000_priv.h
-@@ -0,0 +1,88 @@
++++ b/drivers/media/video/au0828/au0828.h
+@@ -0,0 +1,124 @@
+/*
-+ * Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
++ * Driver for the Auvitek AU0828 USB bridge
+ *
-+ * Copyright (c) 2007 Patrick Boettcher <pb at linuxtv.org>
++ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
@@ -379748,9947 +545222,6909 @@
+ *
+ * You 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.=
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
-+#ifndef ITD1000_PRIV_H
-+#define ITD1000_PRIV_H
-+
-+struct itd1000_state {
-+ struct itd1000_config *cfg;
-+ struct i2c_adapter *i2c;
-+
-+ u32 frequency; /* contains the value resulting from the LO-setting */
-+
-+ /* ugly workaround for flexcop's incapable i2c-controller
-+ * FIXME, if possible
-+ */
-+ u8 shadow[255];
-+};
-+
-+enum itd1000_register {
-+ VCO_CHP1 = 0x65,
-+ VCO_CHP2,
-+ PLLCON1,
-+ PLLNH,
-+ PLLNL,
-+ PLLFH,
-+ PLLFM,
-+ PLLFL,
-+ RESERVED_0X6D,
-+ PLLLOCK,
-+ VCO_CHP2_I2C,
-+ VCO_CHP1_I2C,
-+ BW,
-+ RESERVED_0X73 = 0x73,
-+ RESERVED_0X74,
-+ RESERVED_0X75,
-+ GVBB,
-+ GVRF,
-+ GVBB_I2C,
-+ EXTGVBBRF,
-+ DIVAGCCK,
-+ BBTR,
-+ RFTR,
-+ BBGVMIN,
-+ RESERVED_0X7E,
-+ RESERVED_0X85 = 0x85,
-+ RESERVED_0X86,
-+ CON1,
-+ RESERVED_0X88,
-+ RESERVED_0X89,
-+ RFST0,
-+ RFST1,
-+ RFST2,
-+ RFST3,
-+ RFST4,
-+ RFST5,
-+ RFST6,
-+ RFST7,
-+ RFST8,
-+ RFST9,
-+ RESERVED_0X94,
-+ RESERVED_0X95,
-+ RESERVED_0X96,
-+ RESERVED_0X97,
-+ RESERVED_0X98,
-+ RESERVED_0X99,
-+ RESERVED_0X9A,
-+ RESERVED_0X9B,
-+};
-+
-+#endif
-diff --git a/drivers/media/dvb/frontends/l64781.c b/drivers/media/dvb/frontends/l64781.c
-index 443d904..e1e70e9 100644
---- a/drivers/media/dvb/frontends/l64781.c
-+++ b/drivers/media/dvb/frontends/l64781.c
-@@ -57,7 +57,7 @@ static int l64781_writereg (struct l64781_state* state, u8 reg, u8 data)
-
- if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1)
- dprintk ("%s: write_reg error (reg == %02x) = %02x!\n",
-- __FUNCTION__, reg, ret);
-+ __func__, reg, ret);
-
- return (ret != 1) ? -1 : 0;
- }
-diff --git a/drivers/media/dvb/frontends/l64781.h b/drivers/media/dvb/frontends/l64781.h
-index cd15f76..1305a9e 100644
---- a/drivers/media/dvb/frontends/l64781.h
-+++ b/drivers/media/dvb/frontends/l64781.h
-@@ -38,7 +38,7 @@ extern struct dvb_frontend* l64781_attach(const struct l64781_config* config,
- static inline struct dvb_frontend* l64781_attach(const struct l64781_config* config,
- struct i2c_adapter* i2c)
- {
-- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
-+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
- }
- #endif // CONFIG_DVB_L64781
-diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
-index bdc9fa8..f0195c8 100644
---- a/drivers/media/dvb/frontends/lgdt330x.c
-+++ b/drivers/media/dvb/frontends/lgdt330x.c
-@@ -49,7 +49,7 @@
- /* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */
- /* #define USE_EQMSE */
-
--static int debug = 0;
-+static int debug;
- module_param(debug, int, 0644);
- MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off).");
- #define dprintk(args...) \
-@@ -88,7 +88,7 @@ static int i2c_write_demod_bytes (struct lgdt330x_state* state,
-
- for (i=0; i<len-1; i+=2){
- if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-- printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err);
-+ printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __func__, msg.buf[0], msg.buf[1], err);
- if (err < 0)
- return err;
- else
-@@ -117,7 +117,7 @@ static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
- int ret;
- ret = i2c_transfer(state->i2c, msg, 2);
- if (ret != 2) {
-- printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __FUNCTION__, state->config->demod_address, reg, ret);
-+ printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __func__, state->config->demod_address, reg, ret);
- } else {
- ret = 0;
- }
-@@ -256,7 +256,7 @@ static int lgdt330x_init(struct dvb_frontend* fe)
- printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
- err = -ENODEV;
- }
-- dprintk("%s entered as %s\n", __FUNCTION__, chip_name);
-+ dprintk("%s entered as %s\n", __func__, chip_name);
- if (err < 0)
- return err;
- return lgdt330x_SwReset(state);
-@@ -334,7 +334,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
- if (state->current_modulation != param->u.vsb.modulation) {
- switch(param->u.vsb.modulation) {
- case VSB_8:
-- dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
-+ dprintk("%s: VSB_8 MODE\n", __func__);
-
- /* Select VSB mode */
- top_ctrl_cfg[1] = 0x03;
-@@ -350,7 +350,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
- break;
-
- case QAM_64:
-- dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
-+ dprintk("%s: QAM_64 MODE\n", __func__);
-
- /* Select QAM_64 mode */
- top_ctrl_cfg[1] = 0x00;
-@@ -366,7 +366,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
- break;
-
- case QAM_256:
-- dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
-+ dprintk("%s: QAM_256 MODE\n", __func__);
-
- /* Select QAM_256 mode */
- top_ctrl_cfg[1] = 0x01;
-@@ -381,7 +381,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
- }
- break;
- default:
-- printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
-+ printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __func__, param->u.vsb.modulation);
- return -1;
- }
- /*
-@@ -431,7 +431,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
-
- /* AGC status register */
- i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
-- dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
-+ dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]);
- if ((buf[0] & 0x0c) == 0x8){
- /* Test signal does not exist flag */
- /* as well as the AGC lock flag. */
-@@ -445,7 +445,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
- */
- /* signal status */
- i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
-- dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]);
-+ dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __func__, buf[0], buf[1], buf[2]);
-
-
- /* sync status */
-@@ -461,7 +461,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
-
- /* Carrier Recovery Lock Status Register */
- i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
-- dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
-+ dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]);
- switch (state->current_modulation) {
- case QAM_256:
- case QAM_64:
-@@ -474,7 +474,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
- *status |= FE_HAS_CARRIER;
- break;
- default:
-- printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
-+ printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__);
- }
-
- return 0;
-@@ -493,7 +493,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
- if (err < 0)
- return err;
-
-- dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
-+ dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]);
- if ((buf[0] & 0x21) == 0x01){
- /* Test input signal does not exist flag */
- /* as well as the AGC lock flag. */
-@@ -502,7 +502,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
-
- /* Carrier Recovery Lock Status Register */
- i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
-- dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
-+ dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]);
- switch (state->current_modulation) {
- case QAM_256:
- case QAM_64:
-@@ -533,7 +533,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
- }
- break;
- default:
-- printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
-+ printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__);
- }
- return 0;
- }
-@@ -607,14 +607,14 @@ static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
- break;
- default:
- printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
-- __FUNCTION__);
-+ __func__);
- return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
- }
-
- state->snr = calculate_snr(noise, c);
- *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
-
-- dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
-+ dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
- state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
-
- return 0;
-@@ -651,14 +651,14 @@ static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
- break;
- default:
- printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
-- __FUNCTION__);
-+ __func__);
- return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
- }
-
- state->snr = calculate_snr(noise, c);
- *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
-
-- dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
-+ dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
- state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
-
- return 0;
-@@ -743,7 +743,7 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
-
- error:
- kfree(state);
-- dprintk("%s: ERROR\n",__FUNCTION__);
-+ dprintk("%s: ERROR\n",__func__);
- return NULL;
- }
-
-diff --git a/drivers/media/dvb/frontends/lgdt330x.h b/drivers/media/dvb/frontends/lgdt330x.h
-index 9950590..9012504 100644
---- a/drivers/media/dvb/frontends/lgdt330x.h
-+++ b/drivers/media/dvb/frontends/lgdt330x.h
-@@ -59,7 +59,7 @@ extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config
- static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
- struct i2c_adapter* i2c)
- {
-- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
-+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
- }
- #endif // CONFIG_DVB_LGDT330X
-diff --git a/drivers/media/dvb/frontends/lnbp21.h b/drivers/media/dvb/frontends/lnbp21.h
-index 68906ac..8fe094b 100644
---- a/drivers/media/dvb/frontends/lnbp21.h
-+++ b/drivers/media/dvb/frontends/lnbp21.h
-@@ -45,7 +45,7 @@ extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_ad
- #else
- static inline struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
- {
-- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
-+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
- }
- #endif // CONFIG_DVB_LNBP21
-diff --git a/drivers/media/dvb/frontends/mt2060.h b/drivers/media/dvb/frontends/mt2060.h
-index 0a86eab..acba005 100644
---- a/drivers/media/dvb/frontends/mt2060.h
-+++ b/drivers/media/dvb/frontends/mt2060.h
-@@ -35,7 +35,7 @@ extern struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_a
- #else
- static inline struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
- {
-- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
-+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
- }
- #endif // CONFIG_DVB_TUNER_MT2060
-diff --git a/drivers/media/dvb/frontends/mt2131.c b/drivers/media/dvb/frontends/mt2131.c
-index 13cf166..e254bcf 100644
---- a/drivers/media/dvb/frontends/mt2131.c
-+++ b/drivers/media/dvb/frontends/mt2131.c
-@@ -110,7 +110,7 @@ static int mt2131_set_params(struct dvb_frontend *fe,
- priv->bandwidth = 0;
-
- freq = params->frequency / 1000; // Hz -> kHz
-- dprintk(1, "%s() freq=%d\n", __FUNCTION__, freq);
-+ dprintk(1, "%s() freq=%d\n", __func__, freq);
-
- f_lo1 = freq + MT2131_IF1 * 1000;
- f_lo1 = (f_lo1 / 250) * 250;
-@@ -187,7 +187,7 @@ static int mt2131_set_params(struct dvb_frontend *fe,
- static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
- {
- struct mt2131_priv *priv = fe->tuner_priv;
-- dprintk(1, "%s()\n", __FUNCTION__);
-+ dprintk(1, "%s()\n", __func__);
- *frequency = priv->frequency;
- return 0;
- }
-@@ -195,7 +195,7 @@ static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
- static int mt2131_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
- {
- struct mt2131_priv *priv = fe->tuner_priv;
-- dprintk(1, "%s()\n", __FUNCTION__);
-+ dprintk(1, "%s()\n", __func__);
- *bandwidth = priv->bandwidth;
- return 0;
- }
-@@ -214,7 +214,7 @@ static int mt2131_get_status(struct dvb_frontend *fe, u32 *status)
-
- mt2131_readreg(priv, 0x09, &afc_status);
- dprintk(1, "%s() - LO Status = 0x%x, AFC Status = 0x%x\n",
-- __FUNCTION__, lock_status, afc_status);
-+ __func__, lock_status, afc_status);
-
- return 0;
- }
-@@ -223,7 +223,7 @@ static int mt2131_init(struct dvb_frontend *fe)
- {
- struct mt2131_priv *priv = fe->tuner_priv;
- int ret;
-- dprintk(1, "%s()\n", __FUNCTION__);
-+ dprintk(1, "%s()\n", __func__);
-
- if ((ret = mt2131_writeregs(priv, mt2131_config1,
- sizeof(mt2131_config1))) < 0)
-@@ -243,7 +243,7 @@ static int mt2131_init(struct dvb_frontend *fe)
-
- static int mt2131_release(struct dvb_frontend *fe)
- {
-- dprintk(1, "%s()\n", __FUNCTION__);
-+ dprintk(1, "%s()\n", __func__);
- kfree(fe->tuner_priv);
- fe->tuner_priv = NULL;
- return 0;
-@@ -273,7 +273,7 @@ struct dvb_frontend * mt2131_attach(struct dvb_frontend *fe,
- struct mt2131_priv *priv = NULL;
- u8 id = 0;
-
-- dprintk(1, "%s()\n", __FUNCTION__);
-+ dprintk(1, "%s()\n", __func__);
-
- priv = kzalloc(sizeof(struct mt2131_priv), GFP_KERNEL);
- if (priv == NULL)
-diff --git a/drivers/media/dvb/frontends/mt2131.h b/drivers/media/dvb/frontends/mt2131.h
-index 1e4ffe7..606d857 100644
---- a/drivers/media/dvb/frontends/mt2131.h
-+++ b/drivers/media/dvb/frontends/mt2131.h
-@@ -41,7 +41,7 @@ static inline struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
- struct mt2131_config *cfg,
- u16 if1)
- {
-- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
-+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
- }
- #endif /* CONFIG_DVB_TUNER_MT2131 */
-diff --git a/drivers/media/dvb/frontends/mt2266.h b/drivers/media/dvb/frontends/mt2266.h
-index f31dd61..c5113ef 100644
---- a/drivers/media/dvb/frontends/mt2266.h
-+++ b/drivers/media/dvb/frontends/mt2266.h
-@@ -29,7 +29,7 @@ extern struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_a
- #else
- static inline struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg)
- {
-- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
-+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
- }
- #endif // CONFIG_DVB_TUNER_MT2266
-diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
-index 1638301..081ca33 100644
---- a/drivers/media/dvb/frontends/mt312.c
-+++ b/drivers/media/dvb/frontends/mt312.c
-@@ -1,7 +1,8 @@
- /*
-- Driver for Zarlink VP310/MT312 Satellite Channel Decoder
-+ Driver for Zarlink VP310/MT312/ZL10313 Satellite Channel Decoder
-
- Copyright (C) 2003 Andreas Oberritter <obi at linuxtv.org>
-+ Copyright (C) 2008 Matthias Schwarzott <zzam at gentoo.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
-@@ -43,7 +44,8 @@ struct mt312_state {
- struct dvb_frontend frontend;
-
- u8 id;
-- u8 frequency;
-+ unsigned long xtal;
-+ u8 freq_mult;
- };
-
- static int debug;
-@@ -53,12 +55,11 @@ static int debug;
- printk(KERN_DEBUG "mt312: " args); \
- } while (0)
-
--#define MT312_SYS_CLK 90000000UL /* 90 MHz */
--#define MT312_LPOWER_SYS_CLK 60000000UL /* 60 MHz */
- #define MT312_PLL_CLK 10000000UL /* 10 MHz */
-+#define MT312_PLL_CLK_10_111 10111000UL /* 10.111 MHz */
-
- static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
-- void *buf, const size_t count)
-+ u8 *buf, const size_t count)
- {
- int ret;
- struct i2c_msg msg[2];
-@@ -76,7 +77,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
- ret = i2c_transfer(state->i2c, msg, 2);
-
- if (ret != 2) {
-- printk(KERN_ERR "%s: ret == %d\n", __FUNCTION__, ret);
-+ printk(KERN_ERR "%s: ret == %d\n", __func__, ret);
- return -EREMOTEIO;
- }
-
-@@ -84,7 +85,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
- int i;
- dprintk("R(%d):", reg & 0x7f);
- for (i = 0; i < count; i++)
-- printk(" %02x", ((const u8 *) buf)[i]);
-+ printk(" %02x", buf[i]);
- printk("\n");
- }
-
-@@ -92,7 +93,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
- }
-
- static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
-- const void *src, const size_t count)
-+ const u8 *src, const size_t count)
- {
- int ret;
- u8 buf[count + 1];
-@@ -102,7 +103,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
- int i;
- dprintk("W(%d):", reg & 0x7f);
- for (i = 0; i < count; i++)
-- printk(" %02x", ((const u8 *) src)[i]);
-+ printk(" %02x", src[i]);
- printk("\n");
- }
-
-@@ -117,7 +118,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
- ret = i2c_transfer(state->i2c, &msg, 1);
-
- if (ret != 1) {
-- dprintk("%s: ret == %d\n", __FUNCTION__, ret);
-+ dprintk("%s: ret == %d\n", __func__, ret);
- return -EREMOTEIO;
- }
-
-@@ -209,7 +210,7 @@ static int mt312_get_symbol_rate(struct mt312_state *state, u32 *sr)
- dprintk("sym_rat_op=%d dec_ratio=%d\n",
- sym_rat_op, dec_ratio);
- dprintk("*sr(manual) = %lu\n",
-- (((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) *
-+ (((state->xtal * 8192) / (sym_rat_op + 8192)) *
- 2) - dec_ratio);
- }
-
-@@ -242,7 +243,7 @@ static int mt312_initfe(struct dvb_frontend *fe)
-
- /* wake up */
- ret = mt312_writereg(state, CONFIG,
-- (state->frequency == 60 ? 0x88 : 0x8c));
-+ (state->freq_mult == 6 ? 0x88 : 0x8c));
- if (ret < 0)
- return ret;
-
-@@ -265,12 +266,37 @@ static int mt312_initfe(struct dvb_frontend *fe)
- return ret;
- }
-
-+ switch (state->id) {
-+ case ID_ZL10313:
-+ /* enable ADC */
-+ ret = mt312_writereg(state, GPP_CTRL, 0x80);
-+ if (ret < 0)
-+ return ret;
-+
-+ /* configure ZL10313 for optimal ADC performance */
-+ buf[0] = 0x80;
-+ buf[1] = 0xB0;
-+ ret = mt312_write(state, HW_CTRL, buf, 2);
-+ if (ret < 0)
-+ return ret;
-+
-+ /* enable MPEG output and ADCs */
-+ ret = mt312_writereg(state, HW_CTRL, 0x00);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = mt312_writereg(state, MPEG_CTRL, 0x00);
-+ if (ret < 0)
-+ return ret;
-+
-+ break;
-+ }
-+
- /* SYS_CLK */
-- buf[0] = mt312_div((state->frequency == 60 ? MT312_LPOWER_SYS_CLK :
-- MT312_SYS_CLK) * 2, 1000000);
-+ buf[0] = mt312_div(state->xtal * state->freq_mult * 2, 1000000);
-
- /* DISEQC_RATIO */
-- buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4);
-+ buf[1] = mt312_div(state->xtal, 22000 * 4);
-
- ret = mt312_write(state, SYS_CLK, buf, sizeof(buf));
- if (ret < 0)
-@@ -280,7 +306,17 @@ static int mt312_initfe(struct dvb_frontend *fe)
- if (ret < 0)
- return ret;
-
-- ret = mt312_writereg(state, OP_CTRL, 0x53);
-+ /* different MOCLK polarity */
-+ switch (state->id) {
-+ case ID_ZL10313:
-+ buf[0] = 0x33;
-+ break;
-+ default:
-+ buf[0] = 0x53;
-+ break;
-+ }
-+
-+ ret = mt312_writereg(state, OP_CTRL, buf[0]);
- if (ret < 0)
- return ret;
-
-@@ -323,6 +359,9 @@ static int mt312_send_master_cmd(struct dvb_frontend *fe,
- if (ret < 0)
- return ret;
-
-+ /* is there a better way to wait for message to be transmitted */
-+ msleep(100);
++#include <linux/usb.h>
++#include <linux/i2c.h>
++#include <linux/i2c-algo-bit.h>
++#include <media/tveeprom.h>
+
- /* 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;
++/* DVB */
++#include "demux.h"
++#include "dmxdev.h"
++#include "dvb_demux.h"
++#include "dvb_frontend.h"
++#include "dvb_net.h"
++#include "dvbdev.h"
+
-+ 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;
++#include "au0828-reg.h"
++#include "au0828-cards.h"
+
-+ switch (state->id) {
-+ case ID_ZL10313:
-+ ret = mt312_readreg(state, GPP_CTRL, &val);
-+ if (ret < 0)
-+ goto error;
++#define DRIVER_NAME "au0828"
++#define URB_COUNT 16
++#define URB_BUFSIZE (0xe522)
+
-+ /* preserve this bit to not accidently shutdown ADC */
-+ val &= 0x80;
-+ break;
- }
++struct au0828_board {
++ char *name;
++};
+
-+ if (enable)
-+ val |= 0x40;
-+ else
-+ val &= ~0x40;
++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;
++};
+
-+ ret = mt312_writereg(state, GPP_CTRL, val);
++struct au0828_dev {
++ struct mutex mutex;
++ struct usb_device *usbdev;
++ int board;
++ u8 ctrlmsg[64];
+
-+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;
++ /* I2C */
++ struct i2c_adapter i2c_adap;
++ struct i2c_algo_bit_data i2c_algo;
++ struct i2c_client i2c_client;
++ u32 i2c_rc;
+
-+ /* full shutdown of ADCs, mpeg bus tristated */
-+ ret = mt312_writereg(state, HW_CTRL, 0x0d);
-+ if (ret < 0)
-+ return ret;
-+ }
++ /* Digital */
++ struct au0828_dvb dvb;
+
- 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).");
++ /* 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
--MODULE_DESCRIPTION("Zarlink VP310/MT312 DVB-S Demodulator driver");
-+MODULE_DESCRIPTION("Zarlink VP310/MT312/ZL10313 DVB-S Demodulator driver");
- MODULE_AUTHOR("Andreas Oberritter <obi at linuxtv.org>");
- MODULE_LICENSE("GPL");
-diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h
-index f17cb93..de796ea 100644
---- a/drivers/media/dvb/frontends/mt312.h
-+++ b/drivers/media/dvb/frontends/mt312.h
-@@ -31,6 +31,9 @@
- struct mt312_config {
- /* the demodulator's i2c address */
- u8 demod_address;
-+
-+ /* inverted voltage setting */
-+ unsigned int voltage_inverted:1;
- };
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-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 {
+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
- 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)
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
- if (ret != 2) {
- printk("%s: readreg error (reg=%d, ret==%i)\n",
-- __FUNCTION__, reg, ret);
-+ __func__, reg, ret);
- return ret;
- }
+diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig
+index cfc822b..7431ef6 100644
+--- a/drivers/media/video/bt8xx/Kconfig
++++ b/drivers/media/video/bt8xx/Kconfig
+@@ -6,7 +6,7 @@ config VIDEO_BT848
+ select VIDEO_BTCX
+ select VIDEOBUF_DMA_SG
+ select VIDEO_IR
+- select VIDEO_TUNER
++ select MEDIA_TUNER
+ select VIDEO_TVEEPROM
+ select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
+ select VIDEO_TVAUDIO if VIDEO_HELPER_CHIPS_AUTO
+diff --git a/drivers/media/video/bt8xx/Makefile b/drivers/media/video/bt8xx/Makefile
+index 924d216..e415f6f 100644
+--- a/drivers/media/video/bt8xx/Makefile
++++ b/drivers/media/video/bt8xx/Makefile
+@@ -9,4 +9,5 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
+ obj-$(CONFIG_VIDEO_BT848) += bttv.o
-@@ -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)
+ EXTRA_CFLAGS += -Idrivers/media/video
++EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+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 u8 mt352_reset_attach [] = { RESET, 0xC0 };
++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" },
-- dprintk("%s: hello\n",__FUNCTION__);
-+ dprintk("%s: hello\n",__func__);
+ { 0, -1, NULL }
+ };
+@@ -576,6 +579,8 @@ struct tvcard bttv_tvcards[] = {
+ .needs_tvaudio = 1,
+ .pll = PLL_28,
+ .tuner_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
+ },
+ [BTTV_BOARD_WINVIEW_601] = {
+ .name = "Leadtek WinView 601",
+@@ -2322,7 +2327,7 @@ struct tvcard bttv_tvcards[] = {
+ .tuner = 0,
+ .svhs = 2,
+ .muxsel = { 2, 3, 1, 0 },
+- .tuner_type = TUNER_PHILIPS_ATSC,
++ .tuner_type = TUNER_PHILIPS_FCV1236D,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .has_dvb = 1,
+@@ -2961,7 +2966,7 @@ struct tvcard bttv_tvcards[] = {
+ [BTTV_BOARD_DVICO_FUSIONHDTV_2] = {
+ .name = "DViCO FusionHDTV 2",
+ .tuner = 0,
+- .tuner_type = TUNER_PHILIPS_ATSC, /* FCV1236D */
++ .tuner_type = TUNER_PHILIPS_FCV1236D,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .video_inputs = 3,
+@@ -2992,6 +2997,45 @@ struct tvcard bttv_tvcards[] = {
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ },
++ [BTTV_BOARD_GEOVISION_GV600] = {
++ /* emhn at usb.ve */
++ .name = "Geovision GV-600",
++ .video_inputs = 16,
++ .audio_inputs = 0,
++ .tuner = UNSET,
++ .svhs = UNSET,
++ .gpiomask = 0x0,
++ .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2 },
++ .muxsel_hook = geovision_muxsel,
++ .gpiomux = { 0 },
++ .no_msp34xx = 1,
++ .pll = PLL_28,
++ .tuner_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ },
++ [BTTV_BOARD_KOZUMI_KTV_01C] = {
++ /* Mauro Lacy <mauro at lacy.com.ar>
++ * Based on MagicTV and Conceptronic CONTVFMi */
++
++ .name = "Kozumi KTV-01C",
++ .video_inputs = 3,
++ .audio_inputs = 1,
++ .tuner = 0,
++ .svhs = 2,
++ .gpiomask = 0x008007,
++ .muxsel = { 2, 3, 1, 1 },
++ .gpiomux = { 0, 1, 2, 2 }, /* CONTVFMi */
++ .gpiomute = 3, /* CONTVFMi */
++ .needs_tvaudio = 0,
++ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* TCL MK3 */
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ .pll = PLL_28,
++ .has_radio = 1,
++ .has_remote = 1,
++ },
+ };
- 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;
+ 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 );
}
- #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)
++static void geovision_muxsel(struct bttv *btv, unsigned int input)
++{
++ unsigned int inmux = input % 16;
++ gpio_inout(0xf, 0xf);
++ gpio_bits(0xf, inmux);
++}
++
+ /* ----------------------------------------------------------------------- */
- 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
+ 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;
- 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
+- 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;
- 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__);
+- 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)
- /* 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
+ static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
{
- int i;
- u8 buf, len2, attr;
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
++ if (unlikely(a->index))
++ return -EINVAL;
++
+ strcpy(a->name, "audio");
+ return 0;
+ }
- /* 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)
+ static int bttv_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
{
- u8 buf, stopval, counter = 0;
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
++ if (unlikely(a->index))
++ return -EINVAL;
++
+ return 0;
+ }
- /* 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__);
+@@ -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);
- 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__);
+- 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;
- 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;
++ file->private_data = NULL;
++ kfree(fh);
++
+ btv->radio_user--;
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
+ 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;
- dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[1], data[2], data[3], data[4]);
+ strcpy(i->name, "Radio");
+- i->type = V4L2_INPUT_TYPE_TUNER;
++ i->type = V4L2_INPUT_TYPE_TUNER;
-@@ -387,7 +387,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
- static void nxt200x_agc_reset(struct nxt200x_state* state)
+ 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)
{
- 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;
+- if (a->index != 0)
++ if (unlikely(a->index))
+ return -EINVAL;
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
- dprintk("Firmware is %zu bytes\n", fw->size);
+- memset(a, 0, sizeof(*a));
+ strcpy(a->name, "Radio");
- /* 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)
+ 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)
{
-- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
-+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
++ if (unlikely(a->index))
++ return -EINVAL;
++
+ return 0;
}
- #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)
+ static int radio_s_input(struct file *filp, void *priv, unsigned int i)
{
-- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
-+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
++ if (unlikely(i))
++ return -EINVAL;
++
+ return 0;
}
- #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;
+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;
}
-- dprintk("%s: read_status %04x\n", __FUNCTION__, reg);
-+ dprintk("%s: read_status %04x\n", __func__, reg);
+ 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
- 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");
+ static unsigned int vbibufs = 4;
+-static unsigned int vbi_debug = 0;
++static unsigned int vbi_debug;
- /* Calculate SNR using noise, c, and NTSC rejection correction */
- state->snr = calculate_snr(noise, c) - usK;
- *snr = (state->snr) >> 16;
+ module_param(vbibufs, int, 0444);
+ module_param(vbi_debug, int, 0644);
+diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h
+index bf4c339..f239320 100644
+--- a/drivers/media/video/bt8xx/bttv.h
++++ b/drivers/media/video/bt8xx/bttv.h
+@@ -19,6 +19,7 @@
+ #include <media/ir-common.h>
+ #include <media/ir-kbd-i2c.h>
+ #include <media/i2c-addr.h>
++#include <media/tuner.h>
-- 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);
+ /* ---------------------------------------------------------- */
+ /* 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
- 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;
- }
+ /* more card-specific defines */
+diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h
+index 1305d31..27da7b4 100644
+--- a/drivers/media/video/bt8xx/bttvp.h
++++ b/drivers/media/video/bt8xx/bttvp.h
+@@ -42,7 +42,6 @@
- state->snr = calculate_snr(rec_buf[0], 89599047);
- *snr = (state->snr) >> 16;
+ #include <linux/device.h>
+ #include <media/videobuf-dma-sg.h>
+-#include <media/tuner.h>
+ #include <media/tveeprom.h>
+ #include <media/ir-common.h>
-- 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);
+@@ -82,8 +81,6 @@
+ /* Limits scaled width, which must be a multiple of 4. */
+ #define MAX_HACTIVE (0x3FF & -4)
+
+-#define clamp(x, low, high) min (max (low, x), high)
+-
+ #define BTTV_NORMS (\
+ V4L2_STD_PAL | V4L2_STD_PAL_N | \
+ V4L2_STD_PAL_Nc | V4L2_STD_SECAM | \
+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;
- 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;
+ 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=
--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];
- }
+ #define MAX_CAMS 4
+ static struct qcam_device *qcams[MAX_CAMS];
+-static unsigned int num_cams = 0;
++static unsigned int num_cams;
-@@ -340,7 +340,7 @@ static int s5h1409_softreset(struct dvb_frontend* fe)
+ static int init_bwqcam(struct parport *port)
{
- struct s5h1409_state* state = fe->demodulator_priv;
-
-- dprintk("%s()\n", __FUNCTION__);
-+ dprintk("%s()\n", __func__);
+diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
+index cf1546b..fe1e67b 100644
+--- a/drivers/media/video/c-qcam.c
++++ b/drivers/media/video/c-qcam.c
+@@ -36,6 +36,7 @@
+ #include <linux/videodev.h>
+ #include <media/v4l2-common.h>
+ #include <linux/mutex.h>
++#include <linux/jiffies.h>
- 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;
+ #include <asm/uaccess.h>
-- dprintk("%s(%d KHz)\n", __FUNCTION__, KHz);
-+ dprintk("%s(%d KHz)\n", __func__, KHz);
+@@ -69,7 +70,7 @@ struct qcam_device {
- 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;
+ 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;
-- dprintk("%s(%d)\n", __FUNCTION__, inverted);
-+ dprintk("%s(%d)\n", __func__, inverted);
+ 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;
- 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;
+- 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;
-- dprintk("%s(0x%08x)\n", __FUNCTION__, m);
-+ dprintk("%s(0x%08x)\n", __func__, m);
+@@ -120,7 +122,8 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
+ unsigned long oldjiffies = jiffies;
+ unsigned int i;
- 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;
- }
+- 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;
-@@ -426,7 +426,7 @@ static int s5h1409_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
- {
- struct s5h1409_state* state = fe->demodulator_priv;
+@@ -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)
+ }
-- dprintk("%s(%d)\n", __FUNCTION__, enable);
-+ dprintk("%s(%d)\n", __func__, enable);
+ static struct qcam_device *qcams[MAX_CAMS];
+-static unsigned int num_cams = 0;
++static unsigned int num_cams;
- if (enable)
- return s5h1409_writereg(state, 0xf3, 1);
-@@ -438,7 +438,7 @@ static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable)
+ static int init_cqcam(struct parport *port)
{
- struct s5h1409_state* state = fe->demodulator_priv;
-
-- dprintk("%s(%d)\n", __FUNCTION__, enable);
-+ dprintk("%s(%d)\n", __func__, enable);
+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");
+ */
- 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;
+ #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.");
-- dprintk("%s(%d)\n", __FUNCTION__, enable);
-+ dprintk("%s(%d)\n", __func__, enable);
+-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,
+ };
- 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;
+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)
-- dprintk("%s()\n", __FUNCTION__);
-+ dprintk("%s()\n", __func__);
+ #ifdef _CPIA_DEBUG_
+ #define ADBG(fmt,args...) printk(fmt, jiffies, ##args)
+-#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __FUNCTION__, __LINE__ , ##args)
++#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __func__, __LINE__ , ##args)
+ #else
+ #define DBG(fmn,args...) do {} while(0)
+ #endif
+diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c
+index a76bd78..c8b9fdb 100644
+--- a/drivers/media/video/cpia2/cpia2_core.c
++++ b/drivers/media/video/cpia2/cpia2_core.c
+@@ -34,7 +34,7 @@
+ #include <linux/slab.h>
+ #include <linux/vmalloc.h>
- 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;
+-//#define _CPIA2_DEBUG_
++/* #define _CPIA2_DEBUG_ */
-- dprintk("%s(frequency=%d)\n", __FUNCTION__, p->frequency);
-+ dprintk("%s(frequency=%d)\n", __func__, p->frequency);
+ #include "cpia2patch.h"
- s5h1409_softreset(fe);
+@@ -48,7 +48,7 @@ static const char *block_name[] = {
+ };
+ #endif
-@@ -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;
+-static unsigned int debugs_on = 0;//DEBUG_REG;
++static unsigned int debugs_on; /* default 0 - DEBUG_REG */
-- 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;
+ /******************************************************************************
+@@ -570,7 +570,7 @@ int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd)
+ block_name[block_index]);
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__);
+ default:
+- LOG("%s: invalid request mode\n",__FUNCTION__);
++ LOG("%s: invalid request mode\n",__func__);
+ return -EINVAL;
+ }
- 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)
+@@ -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,
}
-- dprintk("%s() status 0x%08x\n", __FUNCTION__, *status);
-+ dprintk("%s() status 0x%08x\n", __func__, *status);
+ if (!buf) {
+- ERR("%s: buffer NULL\n",__FUNCTION__);
++ ERR("%s: buffer NULL\n",__func__);
+ return -EINVAL;
+ }
- 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__);
+ if (!cam) {
+- ERR("%s: Internal error, camera_data NULL!\n",__FUNCTION__);
++ ERR("%s: Internal error, camera_data NULL!\n",__func__);
+ return -EINVAL;
+ }
- 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__);
+@@ -2370,7 +2370,7 @@ long cpia2_read(struct camera_data *cam,
+ return -ERESTARTSYS;
- 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__);
+ 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;
- 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;
- }
+ if(!cam) {
+- ERR("%s: Internal error, camera_data not found!\n",__FUNCTION__);
++ ERR("%s: Internal error, camera_data not found!\n",__func__);
+ return POLLERR;
}
-- 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)
+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)
{
- struct s5h1409_state* state = fe->demodulator_priv;
- u16 reg;
-- dprintk("%s()\n", __FUNCTION__);
-+ dprintk("%s()\n", __func__);
+- static int frame_count = 0;
++ static int frame_count;
- switch(state->current_modulation) {
- case QAM_64:
-@@ -812,7 +812,7 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
+ unsigned char *inbuff = cam->workbuff->data;
- if (s5h1409_init(&state->frontend) != 0) {
- printk(KERN_ERR "%s: Failed to initialize correctly\n",
-- __FUNCTION__);
-+ __func__);
- goto error;
- }
+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/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;
+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);
}
- #endif /* CONFIG_DVB_S5H1409 */
-diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb/frontends/s5h1411.c
+
+ static int cpia_usb_open(void *privdata)
+diff --git a/drivers/media/video/cs5345.c b/drivers/media/video/cs5345.c
+index fae469c..2a429f9 100644
+--- a/drivers/media/video/cs5345.c
++++ b/drivers/media/video/cs5345.c
+@@ -142,7 +142,8 @@ static int cs5345_command(struct i2c_client *client, unsigned cmd, void *arg)
+
+ /* ----------------------------------------------------------------------- */
+
+-static int cs5345_probe(struct i2c_client *client)
++static int cs5345_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ /* Check if the adapter supports the needed features */
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c
+index f41bfde..2dfd0af 100644
+--- a/drivers/media/video/cs53l32a.c
++++ b/drivers/media/video/cs53l32a.c
+@@ -135,7 +135,8 @@ static int cs53l32a_command(struct i2c_client *client, unsigned cmd, void *arg)
+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
+ */
+
+-static int cs53l32a_probe(struct i2c_client *client)
++static int cs53l32a_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ int i;
+
+diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig
new file mode 100644
-index 0000000..eb5bfc9
+index 0000000..acc4b47
--- /dev/null
-+++ b/drivers/media/dvb/frontends/s5h1411.c
-@@ -0,0 +1,888 @@
-+/*
-+ Samsung S5H1411 VSB/QAM demodulator driver
++++ b/drivers/media/video/cx18/Kconfig
+@@ -0,0 +1,20 @@
++config VIDEO_CX18
++ tristate "Conexant cx23418 MPEG encoder support"
++ depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL
++ select I2C_ALGOBIT
++ select FW_LOADER
++ select VIDEO_IR
++ select MEDIA_TUNER
++ select VIDEO_TVEEPROM
++ select VIDEO_CX2341X
++ select VIDEO_CS5345
++ select DVB_S5H1409
++ ---help---
++ This is a video4linux driver for Conexant cx23418 based
++ PCI combo video recorder devices.
+
-+ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
++ This is used in devices such as the Hauppauge HVR-1600
++ cards.
+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
++ To compile this driver as a module, choose M here: the
++ module will be called cx18.
+diff --git a/drivers/media/video/cx18/Makefile b/drivers/media/video/cx18/Makefile
+new file mode 100644
+index 0000000..b23d2e2
+--- /dev/null
++++ b/drivers/media/video/cx18/Makefile
+@@ -0,0 +1,11 @@
++cx18-objs := cx18-driver.o cx18-cards.o cx18-i2c.o cx18-firmware.o cx18-gpio.o \
++ cx18-queue.o cx18-streams.o cx18-fileops.o cx18-ioctl.o cx18-controls.o \
++ cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \
++ cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \
++ cx18-dvb.o
+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
++obj-$(CONFIG_VIDEO_CX18) += cx18.o
+
-+ You 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.
++EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
++EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
++EXTRA_CFLAGS += -Idrivers/media/common/tuners
+diff --git a/drivers/media/video/cx18/cx18-audio.c b/drivers/media/video/cx18/cx18-audio.c
+new file mode 100644
+index 0000000..1adc404
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-audio.c
+@@ -0,0 +1,73 @@
++/*
++ * cx18 audio-related functions
++ *
++ * Derived from ivtv-audio.c
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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 "cx18-driver.h"
++#include "cx18-i2c.h"
++#include "cx18-cards.h"
++#include "cx18-audio.h"
++
++/* Selects the audio input and output according to the current
++ settings. */
++int cx18_audio_set_io(struct cx18 *cx)
++{
++ struct v4l2_routing route;
++ u32 audio_input;
++ int mux_input;
++
++ /* Determine which input to use */
++ if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
++ audio_input = cx->card->radio_input.audio_input;
++ mux_input = cx->card->radio_input.muxer_input;
++ } else {
++ audio_input =
++ cx->card->audio_inputs[cx->audio_input].audio_input;
++ mux_input =
++ cx->card->audio_inputs[cx->audio_input].muxer_input;
++ }
+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/slab.h>
-+#include <linux/delay.h>
-+#include "dvb_frontend.h"
-+#include "dvb-pll.h"
-+#include "s5h1411.h"
++ /* handle muxer chips */
++ route.input = mux_input;
++ route.output = 0;
++ cx18_i2c_hw(cx, cx->card->hw_muxer, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+
-+struct s5h1411_state {
++ route.input = audio_input;
++ return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl,
++ VIDIOC_INT_S_AUDIO_ROUTING, &route);
++}
+
-+ struct i2c_adapter *i2c;
++void cx18_audio_set_route(struct cx18 *cx, struct v4l2_routing *route)
++{
++ cx18_i2c_hw(cx, cx->card->hw_audio_ctrl,
++ VIDIOC_INT_S_AUDIO_ROUTING, route);
++}
+
-+ /* configuration settings */
-+ const struct s5h1411_config *config;
++void cx18_audio_set_audio_clock_freq(struct cx18 *cx, u8 freq)
++{
++ static u32 freqs[3] = { 44100, 48000, 32000 };
+
-+ struct dvb_frontend frontend;
++ /* The audio clock of the digitizer must match the codec sample
++ rate otherwise you get some very strange effects. */
++ if (freq > 2)
++ return;
++ cx18_call_i2c_clients(cx, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freqs[freq]);
++}
+diff --git a/drivers/media/video/cx18/cx18-audio.h b/drivers/media/video/cx18/cx18-audio.h
+new file mode 100644
+index 0000000..cb569a6
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-audio.h
+@@ -0,0 +1,26 @@
++/*
++ * cx18 audio-related functions
++ *
++ * Derived from ivtv-audio.c
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
-+ fe_modulation_t current_modulation;
++int cx18_audio_set_io(struct cx18 *cx);
++void cx18_audio_set_route(struct cx18 *cx, struct v4l2_routing *route);
++void cx18_audio_set_audio_clock_freq(struct cx18 *cx, u8 freq);
+diff --git a/drivers/media/video/cx18/cx18-av-audio.c b/drivers/media/video/cx18/cx18-av-audio.c
+new file mode 100644
+index 0000000..2dc3a5d
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-av-audio.c
+@@ -0,0 +1,361 @@
++/*
++ * cx18 ADEC audio functions
++ *
++ * Derived from cx25840-audio.c
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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.
++ */
+
-+ u32 current_frequency;
-+ int if_freq;
++#include "cx18-driver.h"
+
-+ u8 inversion;
-+};
++static int set_audclk_freq(struct cx18 *cx, u32 freq)
++{
++ struct cx18_av_state *state = &cx->av_state;
+
-+static int debug;
++ if (freq != 32000 && freq != 44100 && freq != 48000)
++ return -EINVAL;
+
-+#define dprintk(arg...) do { \
-+ if (debug) \
-+ printk(arg); \
-+ } while (0)
++ /* common for all inputs and rates */
++ /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
++ cx18_av_write(cx, 0x127, 0x50);
+
-+/* 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, },
-+};
++ if (state->aud_input != CX18_AV_AUDIO_SERIAL) {
++ switch (freq) {
++ case 32000:
++ /* VID_PLL and AUX_PLL */
++ cx18_av_write4(cx, 0x108, 0x1006040f);
+
-+/* 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, },
-+};
++ /* AUX_PLL_FRAC */
++ cx18_av_write4(cx, 0x110, 0x01bb39ee);
+
-+/* 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, },
-+};
++ /* src3/4/6_ctl = 0x0801f77f */
++ cx18_av_write4(cx, 0x900, 0x0801f77f);
++ cx18_av_write4(cx, 0x904, 0x0801f77f);
++ cx18_av_write4(cx, 0x90c, 0x0801f77f);
++ break;
+
-+/* 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, },
-+};
++ case 44100:
++ /* VID_PLL and AUX_PLL */
++ cx18_av_write4(cx, 0x108, 0x1009040f);
+
-+/* 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 };
++ /* AUX_PLL_FRAC */
++ cx18_av_write4(cx, 0x110, 0x00ec6bd6);
+
-+ struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
++ /* src3/4/6_ctl = 0x08016d59 */
++ cx18_av_write4(cx, 0x900, 0x08016d59);
++ cx18_av_write4(cx, 0x904, 0x08016d59);
++ cx18_av_write4(cx, 0x90c, 0x08016d59);
++ break;
+
-+ ret = i2c_transfer(state->i2c, &msg, 1);
++ case 48000:
++ /* VID_PLL and AUX_PLL */
++ cx18_av_write4(cx, 0x108, 0x100a040f);
+
-+ if (ret != 1)
-+ printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, "
-+ "ret == %i)\n", __func__, addr, reg, data, ret);
++ /* AUX_PLL_FRAC */
++ cx18_av_write4(cx, 0x110, 0x0098d6e5);
+
-+ return (ret != 1) ? -1 : 0;
-+}
++ /* src3/4/6_ctl = 0x08014faa */
++ cx18_av_write4(cx, 0x900, 0x08014faa);
++ cx18_av_write4(cx, 0x904, 0x08014faa);
++ cx18_av_write4(cx, 0x90c, 0x08014faa);
++ break;
++ }
++ } else {
++ switch (freq) {
++ case 32000:
++ /* VID_PLL and AUX_PLL */
++ cx18_av_write4(cx, 0x108, 0x1e08040f);
+
-+static u16 s5h1411_readreg(struct s5h1411_state *state, u8 addr, u8 reg)
-+{
-+ int ret;
-+ u8 b0 [] = { reg };
-+ u8 b1 [] = { 0, 0 };
++ /* AUX_PLL_FRAC */
++ cx18_av_write4(cx, 0x110, 0x012a0869);
+
-+ struct i2c_msg msg [] = {
-+ { .addr = addr, .flags = 0, .buf = b0, .len = 1 },
-+ { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
++ /* src1_ctl = 0x08010000 */
++ cx18_av_write4(cx, 0x8f8, 0x08010000);
+
-+ ret = i2c_transfer(state->i2c, msg, 2);
++ /* src3/4/6_ctl = 0x08020000 */
++ cx18_av_write4(cx, 0x900, 0x08020000);
++ cx18_av_write4(cx, 0x904, 0x08020000);
++ cx18_av_write4(cx, 0x90c, 0x08020000);
+
-+ if (ret != 2)
-+ printk(KERN_ERR "%s: readreg error (ret == %i)\n",
-+ __func__, ret);
-+ return (b1[0] << 8) | b1[1];
-+}
++ /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
++ cx18_av_write(cx, 0x127, 0x54);
++ break;
+
-+static int s5h1411_softreset(struct dvb_frontend *fe)
-+{
-+ struct s5h1411_state *state = fe->demodulator_priv;
++ case 44100:
++ /* VID_PLL and AUX_PLL */
++ cx18_av_write4(cx, 0x108, 0x1809040f);
+
-+ dprintk("%s()\n", __func__);
++ /* AUX_PLL_FRAC */
++ cx18_av_write4(cx, 0x110, 0x00ec6bd6);
+
-+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 0);
-+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 1);
-+ return 0;
-+}
++ /* src1_ctl = 0x08010000 */
++ cx18_av_write4(cx, 0x8f8, 0x080160cd);
+
-+static int s5h1411_set_if_freq(struct dvb_frontend *fe, int KHz)
-+{
-+ struct s5h1411_state *state = fe->demodulator_priv;
++ /* src3/4/6_ctl = 0x08020000 */
++ cx18_av_write4(cx, 0x900, 0x08017385);
++ cx18_av_write4(cx, 0x904, 0x08017385);
++ cx18_av_write4(cx, 0x90c, 0x08017385);
++ break;
+
-+ dprintk("%s(%d KHz)\n", __func__, KHz);
++ case 48000:
++ /* VID_PLL and AUX_PLL */
++ cx18_av_write4(cx, 0x108, 0x180a040f);
+
-+ 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;
++ /* AUX_PLL_FRAC */
++ cx18_av_write4(cx, 0x110, 0x0098d6e5);
++
++ /* src1_ctl = 0x08010000 */
++ cx18_av_write4(cx, 0x8f8, 0x08018000);
++
++ /* src3/4/6_ctl = 0x08020000 */
++ cx18_av_write4(cx, 0x900, 0x08015555);
++ cx18_av_write4(cx, 0x904, 0x08015555);
++ cx18_av_write4(cx, 0x90c, 0x08015555);
++ break;
++ }
+ }
+
-+ state->if_freq = KHz;
++ state->audclk_freq = freq;
+
+ return 0;
+}
+
-+static int s5h1411_set_mpeg_timing(struct dvb_frontend *fe, int mode)
++void cx18_av_audio_set_path(struct cx18 *cx)
+{
-+ struct s5h1411_state *state = fe->demodulator_priv;
-+ u16 val;
++ struct cx18_av_state *state = &cx->av_state;
+
-+ dprintk("%s(%d)\n", __func__, mode);
++ /* stop microcontroller */
++ cx18_av_and_or(cx, 0x803, ~0x10, 0);
+
-+ 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;
++ /* assert soft reset */
++ cx18_av_and_or(cx, 0x810, ~0x1, 0x01);
++
++ /* Mute everything to prevent the PFFT! */
++ cx18_av_write(cx, 0x8d3, 0x1f);
++
++ if (state->aud_input == CX18_AV_AUDIO_SERIAL) {
++ /* Set Path1 to Serial Audio Input */
++ cx18_av_write4(cx, 0x8d0, 0x01011012);
++
++ /* The microcontroller should not be started for the
++ * non-tuner inputs: autodetection is specific for
++ * TV audio. */
++ } else {
++ /* Set Path1 to Analog Demod Main Channel */
++ cx18_av_write4(cx, 0x8d0, 0x1f063870);
+ }
+
-+ /* Configure MPEG Signal Timing charactistics */
-+ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbe, val);
++ set_audclk_freq(cx, state->audclk_freq);
++
++ /* deassert soft reset */
++ cx18_av_and_or(cx, 0x810, ~0x1, 0x00);
++
++ if (state->aud_input != CX18_AV_AUDIO_SERIAL) {
++ /* When the microcontroller detects the
++ * audio format, it will unmute the lines */
++ cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
++ }
+}
+
-+static int s5h1411_set_spectralinversion(struct dvb_frontend *fe, int inversion)
++static int get_volume(struct cx18 *cx)
+{
-+ struct s5h1411_state *state = fe->demodulator_priv;
-+ u16 val;
++ /* Volume runs +18dB to -96dB in 1/2dB steps
++ * change to fit the msp3400 -114dB to +12dB range */
+
-+ dprintk("%s(%d)\n", __func__, inversion);
-+ val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x24) & ~0x1000;
++ /* check PATH1_VOLUME */
++ int vol = 228 - cx18_av_read(cx, 0x8d4);
++ vol = (vol / 2) + 23;
++ return vol << 9;
++}
+
-+ if (inversion == 1)
-+ val |= 0x1000; /* Inverted */
++static void set_volume(struct cx18 *cx, int volume)
++{
++ /* First convert the volume to msp3400 values (0-127) */
++ int vol = volume >> 9;
++ /* now scale it up to cx18_av values
++ * -114dB to -96dB maps to 0
++ * this should be 19, but in my testing that was 4dB too loud */
++ if (vol <= 23)
++ vol = 0;
+ else
-+ val |= 0x0000;
++ vol -= 23;
+
-+ state->inversion = inversion;
-+ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x24, val);
++ /* PATH1_VOLUME */
++ cx18_av_write(cx, 0x8d4, 228 - (vol * 2));
+}
+
-+static int s5h1411_enable_modulation(struct dvb_frontend *fe,
-+ fe_modulation_t m)
++static int get_bass(struct cx18 *cx)
+{
-+ struct s5h1411_state *state = fe->demodulator_priv;
++ /* bass is 49 steps +12dB to -12dB */
+
-+ dprintk("%s(0x%08x)\n", __func__, m);
++ /* check PATH1_EQ_BASS_VOL */
++ int bass = cx18_av_read(cx, 0x8d9) & 0x3f;
++ bass = (((48 - bass) * 0xffff) + 47) / 48;
++ return bass;
++}
+
-+ 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;
-+ }
++static void set_bass(struct cx18 *cx, int bass)
++{
++ /* PATH1_EQ_BASS_VOL */
++ cx18_av_and_or(cx, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
++}
+
-+ state->current_modulation = m;
-+ s5h1411_softreset(fe);
++static int get_treble(struct cx18 *cx)
++{
++ /* treble is 49 steps +12dB to -12dB */
+
-+ return 0;
++ /* check PATH1_EQ_TREBLE_VOL */
++ int treble = cx18_av_read(cx, 0x8db) & 0x3f;
++ treble = (((48 - treble) * 0xffff) + 47) / 48;
++ return treble;
+}
+
-+static int s5h1411_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
++static void set_treble(struct cx18 *cx, int treble)
+{
-+ struct s5h1411_state *state = fe->demodulator_priv;
++ /* PATH1_EQ_TREBLE_VOL */
++ cx18_av_and_or(cx, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
++}
+
-+ dprintk("%s(%d)\n", __func__, enable);
++static int get_balance(struct cx18 *cx)
++{
++ /* balance is 7 bit, 0 to -96dB */
+
-+ if (enable)
-+ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
++ /* check PATH1_BAL_LEVEL */
++ int balance = cx18_av_read(cx, 0x8d5) & 0x7f;
++ /* check PATH1_BAL_LEFT */
++ if ((cx18_av_read(cx, 0x8d5) & 0x80) == 0)
++ balance = 0x80 - balance;
+ else
-+ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 0);
++ balance = 0x80 + balance;
++ return balance << 8;
+}
+
-+static int s5h1411_set_gpio(struct dvb_frontend *fe, int enable)
++static void set_balance(struct cx18 *cx, int balance)
+{
-+ struct s5h1411_state *state = fe->demodulator_priv;
-+ u16 val;
++ int bal = balance >> 8;
++ if (bal > 0x80) {
++ /* PATH1_BAL_LEFT */
++ cx18_av_and_or(cx, 0x8d5, 0x7f, 0x80);
++ /* PATH1_BAL_LEVEL */
++ cx18_av_and_or(cx, 0x8d5, ~0x7f, bal & 0x7f);
++ } else {
++ /* PATH1_BAL_LEFT */
++ cx18_av_and_or(cx, 0x8d5, 0x7f, 0x00);
++ /* PATH1_BAL_LEVEL */
++ cx18_av_and_or(cx, 0x8d5, ~0x7f, 0x80 - bal);
++ }
++}
+
-+ dprintk("%s(%d)\n", __func__, enable);
++static int get_mute(struct cx18 *cx)
++{
++ /* check SRC1_MUTE_EN */
++ return cx18_av_read(cx, 0x8d3) & 0x2 ? 1 : 0;
++}
+
-+ val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xe0) & ~0x02;
++static void set_mute(struct cx18 *cx, int mute)
++{
++ struct cx18_av_state *state = &cx->av_state;
+
-+ if (enable)
-+ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0,
-+ val | 0x02);
-+ else
-+ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0, val);
++ if (state->aud_input != CX18_AV_AUDIO_SERIAL) {
++ /* Must turn off microcontroller in order to mute sound.
++ * Not sure if this is the best method, but it does work.
++ * If the microcontroller is running, then it will undo any
++ * changes to the mute register. */
++ if (mute) {
++ /* disable microcontroller */
++ cx18_av_and_or(cx, 0x803, ~0x10, 0x00);
++ cx18_av_write(cx, 0x8d3, 0x1f);
++ } else {
++ /* enable microcontroller */
++ cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
++ }
++ } else {
++ /* SRC1_MUTE_EN */
++ cx18_av_and_or(cx, 0x8d3, ~0x2, mute ? 0x02 : 0x00);
++ }
+}
+
-+static int s5h1411_sleep(struct dvb_frontend *fe, int enable)
++int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg)
+{
-+ struct s5h1411_state *state = fe->demodulator_priv;
++ struct cx18_av_state *state = &cx->av_state;
++ struct v4l2_control *ctrl = arg;
++ int retval;
+
-+ dprintk("%s(%d)\n", __func__, enable);
++ switch (cmd) {
++ case VIDIOC_INT_AUDIO_CLOCK_FREQ:
++ if (state->aud_input != CX18_AV_AUDIO_SERIAL) {
++ cx18_av_and_or(cx, 0x803, ~0x10, 0);
++ cx18_av_write(cx, 0x8d3, 0x1f);
++ }
++ cx18_av_and_or(cx, 0x810, ~0x1, 1);
++ retval = set_audclk_freq(cx, *(u32 *)arg);
++ cx18_av_and_or(cx, 0x810, ~0x1, 0);
++ if (state->aud_input != CX18_AV_AUDIO_SERIAL)
++ cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
++ return retval;
+
-+ if (enable)
-+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 1);
-+ else {
-+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 0);
-+ s5h1411_softreset(fe);
++ case VIDIOC_G_CTRL:
++ switch (ctrl->id) {
++ case V4L2_CID_AUDIO_VOLUME:
++ ctrl->value = get_volume(cx);
++ break;
++ case V4L2_CID_AUDIO_BASS:
++ ctrl->value = get_bass(cx);
++ break;
++ case V4L2_CID_AUDIO_TREBLE:
++ ctrl->value = get_treble(cx);
++ break;
++ case V4L2_CID_AUDIO_BALANCE:
++ ctrl->value = get_balance(cx);
++ break;
++ case V4L2_CID_AUDIO_MUTE:
++ ctrl->value = get_mute(cx);
++ break;
++ default:
++ return -EINVAL;
++ }
++ break;
++
++ case VIDIOC_S_CTRL:
++ switch (ctrl->id) {
++ case V4L2_CID_AUDIO_VOLUME:
++ set_volume(cx, ctrl->value);
++ break;
++ case V4L2_CID_AUDIO_BASS:
++ set_bass(cx, ctrl->value);
++ break;
++ case V4L2_CID_AUDIO_TREBLE:
++ set_treble(cx, ctrl->value);
++ break;
++ case V4L2_CID_AUDIO_BALANCE:
++ set_balance(cx, ctrl->value);
++ break;
++ case V4L2_CID_AUDIO_MUTE:
++ set_mute(cx, ctrl->value);
++ break;
++ default:
++ return -EINVAL;
++ }
++ break;
++
++ default:
++ return -EINVAL;
+ }
+
+ return 0;
+}
+diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c
+new file mode 100644
+index 0000000..6686490
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-av-core.c
+@@ -0,0 +1,879 @@
++/*
++ * cx18 ADEC audio functions
++ *
++ * Derived from cx25840-core.c
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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.
++ */
+
-+static int s5h1411_register_reset(struct dvb_frontend *fe)
++#include "cx18-driver.h"
++
++int cx18_av_write(struct cx18 *cx, u16 addr, u8 value)
+{
-+ struct s5h1411_state *state = fe->demodulator_priv;
++ u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3));
++ u32 mask = 0xff;
++ int shift = (addr & 3) * 8;
+
-+ dprintk("%s()\n", __func__);
++ x = (x & ~(mask << shift)) | ((u32)value << shift);
++ writel(x, cx->reg_mem + 0xc40000 + (addr & ~3));
++ return 0;
++}
+
-+ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf3, 0);
++int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value)
++{
++ writel(value, cx->reg_mem + 0xc40000 + addr);
++ return 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)
++u8 cx18_av_read(struct cx18 *cx, u16 addr)
+{
-+ struct s5h1411_state *state = fe->demodulator_priv;
++ u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3));
++ int shift = (addr & 3) * 8;
+
-+ dprintk("%s(frequency=%d)\n", __func__, p->frequency);
++ return (x >> shift) & 0xff;
++}
+
-+ s5h1411_softreset(fe);
++u32 cx18_av_read4(struct cx18 *cx, u16 addr)
++{
++ return readl(cx->reg_mem + 0xc40000 + addr);
++}
+
-+ state->current_frequency = p->frequency;
++int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask,
++ u8 or_value)
++{
++ return cx18_av_write(cx, addr,
++ (cx18_av_read(cx, addr) & and_mask) |
++ or_value);
++}
+
-+ s5h1411_enable_modulation(fe, p->u.vsb.modulation);
++int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask,
++ u32 or_value)
++{
++ return cx18_av_write4(cx, addr,
++ (cx18_av_read4(cx, addr) & and_mask) |
++ or_value);
++}
+
-+ /* 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);
++static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
++ enum cx18_av_audio_input aud_input);
++static void log_audio_status(struct cx18 *cx);
++static void log_video_status(struct cx18 *cx);
+
-+ fe->ops.tuner_ops.set_params(fe, p);
++/* ----------------------------------------------------------------------- */
+
-+ if (fe->ops.i2c_gate_ctrl)
-+ fe->ops.i2c_gate_ctrl(fe, 0);
++static void cx18_av_initialize(struct cx18 *cx)
++{
++ u32 v;
++
++ cx18_av_loadfw(cx);
++ /* Stop 8051 code execution */
++ cx18_av_write4(cx, CXADEC_DL_CTL, 0x03000000);
++
++ /* initallize the PLL by toggling sleep bit */
++ v = cx18_av_read4(cx, CXADEC_HOST_REG1);
++ /* enable sleep mode */
++ cx18_av_write4(cx, CXADEC_HOST_REG1, v | 1);
++ /* disable sleep mode */
++ cx18_av_write4(cx, CXADEC_HOST_REG1, v & 0xfffe);
++
++ /* initialize DLLs */
++ v = cx18_av_read4(cx, CXADEC_DLL1_DIAG_CTRL) & 0xE1FFFEFF;
++ /* disable FLD */
++ cx18_av_write4(cx, CXADEC_DLL1_DIAG_CTRL, v);
++ /* enable FLD */
++ cx18_av_write4(cx, CXADEC_DLL1_DIAG_CTRL, v | 0x10000100);
++
++ v = cx18_av_read4(cx, CXADEC_DLL2_DIAG_CTRL) & 0xE1FFFEFF;
++ /* disable FLD */
++ cx18_av_write4(cx, CXADEC_DLL2_DIAG_CTRL, v);
++ /* enable FLD */
++ cx18_av_write4(cx, CXADEC_DLL2_DIAG_CTRL, v | 0x06000100);
++
++ /* set analog bias currents. Set Vreg to 1.20V. */
++ cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL1, 0x000A1802);
++
++ v = cx18_av_read4(cx, CXADEC_AFE_DIAG_CTRL3) | 1;
++ /* enable TUNE_FIL_RST */
++ cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL3, v);
++ /* disable TUNE_FIL_RST */
++ cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL3, v & 0xFFFFFFFE);
++
++ /* enable 656 output */
++ cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x040C00);
++
++ /* video output drive strength */
++ cx18_av_and_or4(cx, CXADEC_PIN_CTRL2, ~0, 0x2);
++
++ /* reset video */
++ cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0x8000);
++ cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0);
++
++ /* set video to auto-detect */
++ /* Clear bits 11-12 to enable slow locking mode. Set autodetect mode */
++ /* set the comb notch = 1 */
++ cx18_av_and_or4(cx, CXADEC_MODE_CTRL, 0xFFF7E7F0, 0x02040800);
++
++ /* Enable wtw_en in CRUSH_CTRL (Set bit 22) */
++ /* Enable maj_sel in CRUSH_CTRL (Set bit 20) */
++ cx18_av_and_or4(cx, CXADEC_CRUSH_CTRL, ~0, 0x00500000);
++
++ /* Set VGA_TRACK_RANGE to 0x20 */
++ cx18_av_and_or4(cx, CXADEC_DFE_CTRL2, 0xFFFF00FF, 0x00002000);
++
++ /* Enable VBI capture */
++ cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010253F);
++ /* cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010253E); */
++
++ /* Set the video input.
++ The setting in MODE_CTRL gets lost when we do the above setup */
++ /* EncSetSignalStd(dwDevNum, pEnc->dwSigStd); */
++ /* EncSetVideoInput(dwDevNum, pEnc->VidIndSelection); */
++
++ v = cx18_av_read4(cx, CXADEC_AFE_CTRL);
++ v &= 0xFFFBFFFF; /* turn OFF bit 18 for droop_comp_ch1 */
++ v &= 0xFFFF7FFF; /* turn OFF bit 9 for clamp_sel_ch1 */
++ v &= 0xFFFFFFFE; /* turn OFF bit 0 for 12db_ch1 */
++ /* v |= 0x00000001;*/ /* turn ON bit 0 for 12db_ch1 */
++ cx18_av_write4(cx, CXADEC_AFE_CTRL, v);
++
++/* if(dwEnable && dw3DCombAvailable) { */
++/* CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x7728021F); */
++/* } else { */
++/* CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x6628021F); */
++/* } */
++ cx18_av_write4(cx, CXADEC_SRC_COMB_CFG, 0x6628021F);
++}
++
++/* ----------------------------------------------------------------------- */
++
++static void input_change(struct cx18 *cx)
++{
++ struct cx18_av_state *state = &cx->av_state;
++ v4l2_std_id std = state->std;
++
++ /* Follow step 8c and 8d of section 3.16 in the cx18_av datasheet */
++ if (std & V4L2_STD_SECAM)
++ cx18_av_write(cx, 0x402, 0);
++ else {
++ cx18_av_write(cx, 0x402, 0x04);
++ cx18_av_write(cx, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11);
+ }
++ cx18_av_and_or(cx, 0x401, ~0x60, 0);
++ cx18_av_and_or(cx, 0x401, ~0x60, 0x60);
+
-+ return 0;
++ if (std & V4L2_STD_525_60) {
++ if (std == V4L2_STD_NTSC_M_JP) {
++ /* Japan uses EIAJ audio standard */
++ cx18_av_write(cx, 0x808, 0xf7);
++ } else if (std == V4L2_STD_NTSC_M_KR) {
++ /* South Korea uses A2 audio standard */
++ cx18_av_write(cx, 0x808, 0xf8);
++ } else {
++ /* Others use the BTSC audio standard */
++ cx18_av_write(cx, 0x808, 0xf6);
++ }
++ cx18_av_write(cx, 0x80b, 0x00);
++ } else if (std & V4L2_STD_PAL) {
++ /* Follow tuner change procedure for PAL */
++ cx18_av_write(cx, 0x808, 0xff);
++ cx18_av_write(cx, 0x80b, 0x03);
++ } else if (std & V4L2_STD_SECAM) {
++ /* Select autodetect for SECAM */
++ cx18_av_write(cx, 0x808, 0xff);
++ cx18_av_write(cx, 0x80b, 0x03);
++ }
++
++ if (cx18_av_read(cx, 0x803) & 0x10) {
++ /* restart audio decoder microcontroller */
++ cx18_av_and_or(cx, 0x803, ~0x10, 0x00);
++ cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
++ }
+}
+
-+/* Reset the demod hardware and reset all of the configuration registers
-+ to a default state. */
-+static int s5h1411_init(struct dvb_frontend *fe)
++static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
++ enum cx18_av_audio_input aud_input)
+{
-+ struct s5h1411_state *state = fe->demodulator_priv;
-+ int i;
++ struct cx18_av_state *state = &cx->av_state;
++ u8 is_composite = (vid_input >= CX18_AV_COMPOSITE1 &&
++ vid_input <= CX18_AV_COMPOSITE8);
++ u8 reg;
+
-+ dprintk("%s()\n", __func__);
++ CX18_DEBUG_INFO("decoder set video input %d, audio input %d\n",
++ vid_input, aud_input);
+
-+ s5h1411_sleep(fe, 0);
-+ s5h1411_register_reset(fe);
++ if (is_composite) {
++ reg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1);
++ } else {
++ int luma = vid_input & 0xf0;
++ int chroma = vid_input & 0xf00;
+
-+ for (i = 0; i < ARRAY_SIZE(init_tab); i++)
-+ s5h1411_writereg(state, init_tab[i].addr,
-+ init_tab[i].reg,
-+ init_tab[i].data);
++ if ((vid_input & ~0xff0) ||
++ luma < CX18_AV_SVIDEO_LUMA1 ||
++ luma > CX18_AV_SVIDEO_LUMA4 ||
++ chroma < CX18_AV_SVIDEO_CHROMA4 ||
++ chroma > CX18_AV_SVIDEO_CHROMA8) {
++ CX18_ERR("0x%04x is not a valid video input!\n",
++ vid_input);
++ return -EINVAL;
++ }
++ reg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4);
++ if (chroma >= CX18_AV_SVIDEO_CHROMA7) {
++ reg &= 0x3f;
++ reg |= (chroma - CX18_AV_SVIDEO_CHROMA7) >> 2;
++ } else {
++ reg &= 0xcf;
++ reg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4;
++ }
++ }
+
-+ /* The datasheet says that after initialisation, VSB is default */
-+ state->current_modulation = VSB_8;
++ switch (aud_input) {
++ case CX18_AV_AUDIO_SERIAL:
++ /* do nothing, use serial audio input */
++ break;
++ case CX18_AV_AUDIO4: reg &= ~0x30; break;
++ case CX18_AV_AUDIO5: reg &= ~0x30; reg |= 0x10; break;
++ case CX18_AV_AUDIO6: reg &= ~0x30; reg |= 0x20; break;
++ case CX18_AV_AUDIO7: reg &= ~0xc0; break;
++ case CX18_AV_AUDIO8: reg &= ~0xc0; reg |= 0x40; break;
+
-+ if (state->config->output_mode == S5H1411_SERIAL_OUTPUT)
-+ /* Serial */
-+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1101);
++ default:
++ CX18_ERR("0x%04x is not a valid audio input!\n", aud_input);
++ return -EINVAL;
++ }
++
++ cx18_av_write(cx, 0x103, reg);
++ /* Set INPUT_MODE to Composite (0) or S-Video (1) */
++ cx18_av_and_or(cx, 0x401, ~0x6, is_composite ? 0 : 0x02);
++ /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
++ cx18_av_and_or(cx, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
++ /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
++ if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30)
++ cx18_av_and_or(cx, 0x102, ~0x4, 4);
+ else
-+ /* Parallel */
-+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1001);
++ cx18_av_and_or(cx, 0x102, ~0x4, 0);
++ /*cx18_av_and_or4(cx, 0x104, ~0x001b4180, 0x00004180);*/
+
-+ 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);
++ state->vid_input = vid_input;
++ state->aud_input = aud_input;
++ cx18_av_audio_set_path(cx);
++ input_change(cx);
++ return 0;
++}
+
-+ /* Note: Leaving the I2C gate closed. */
-+ s5h1411_i2c_gate_ctrl(fe, 0);
++/* ----------------------------------------------------------------------- */
++
++static int set_v4lstd(struct cx18 *cx)
++{
++ struct cx18_av_state *state = &cx->av_state;
++ u8 fmt = 0; /* zero is autodetect */
++ u8 pal_m = 0;
++
++ /* First tests should be against specific std */
++ 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 (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;
++ }
++
++ CX18_DEBUG_INFO("changing video std to fmt %i\n", fmt);
+
++ /* Follow step 9 of section 3.16 in the cx18_av datasheet.
++ Without this PAL may display a vertical ghosting effect.
++ This happens for example with the Yuan MPC622. */
++ if (fmt >= 4 && fmt < 8) {
++ /* Set format to NTSC-M */
++ cx18_av_and_or(cx, 0x400, ~0xf, 1);
++ /* Turn off LCOMB */
++ cx18_av_and_or(cx, 0x47b, ~6, 0);
++ }
++ cx18_av_and_or(cx, 0x400, ~0xf, fmt);
++ cx18_av_and_or(cx, 0x403, ~0x3, pal_m);
++ cx18_av_vbi_setup(cx);
++ input_change(cx);
+ return 0;
+}
+
-+static int s5h1411_read_status(struct dvb_frontend *fe, fe_status_t *status)
++/* ----------------------------------------------------------------------- */
++
++static int set_v4lctrl(struct cx18 *cx, struct v4l2_control *ctrl)
+{
-+ struct s5h1411_state *state = fe->demodulator_priv;
-+ u16 reg;
-+ u32 tuner_status = 0;
++ switch (ctrl->id) {
++ case V4L2_CID_BRIGHTNESS:
++ if (ctrl->value < 0 || ctrl->value > 255) {
++ CX18_ERR("invalid brightness setting %d\n",
++ ctrl->value);
++ return -ERANGE;
++ }
+
-+ *status = 0;
++ cx18_av_write(cx, 0x414, ctrl->value - 128);
++ break;
+
-+ /* 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;
++ case V4L2_CID_CONTRAST:
++ if (ctrl->value < 0 || ctrl->value > 127) {
++ CX18_ERR("invalid contrast setting %d\n",
++ ctrl->value);
++ return -ERANGE;
++ }
+
-+ 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;
++ cx18_av_write(cx, 0x415, ctrl->value << 1);
+ 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;
++
++ case V4L2_CID_SATURATION:
++ if (ctrl->value < 0 || ctrl->value > 127) {
++ CX18_ERR("invalid saturation setting %d\n",
++ ctrl->value);
++ return -ERANGE;
++ }
++
++ cx18_av_write(cx, 0x420, ctrl->value << 1);
++ cx18_av_write(cx, 0x421, ctrl->value << 1);
++ break;
++
++ case V4L2_CID_HUE:
++ if (ctrl->value < -127 || ctrl->value > 127) {
++ CX18_ERR("invalid hue setting %d\n", ctrl->value);
++ return -ERANGE;
++ }
++
++ cx18_av_write(cx, 0x422, ctrl->value);
+ break;
++
++ case V4L2_CID_AUDIO_VOLUME:
++ case V4L2_CID_AUDIO_BASS:
++ case V4L2_CID_AUDIO_TREBLE:
++ case V4L2_CID_AUDIO_BALANCE:
++ case V4L2_CID_AUDIO_MUTE:
++ return cx18_av_audio(cx, VIDIOC_S_CTRL, ctrl);
++
+ default:
+ return -EINVAL;
+ }
+
-+ switch (state->config->status_mode) {
-+ case S5H1411_DEMODLOCKING:
-+ if (*status & FE_HAS_VITERBI)
-+ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
++ return 0;
++}
++
++static int get_v4lctrl(struct cx18 *cx, struct v4l2_control *ctrl)
++{
++ switch (ctrl->id) {
++ case V4L2_CID_BRIGHTNESS:
++ ctrl->value = (s8)cx18_av_read(cx, 0x414) + 128;
+ 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);
++ case V4L2_CID_CONTRAST:
++ ctrl->value = cx18_av_read(cx, 0x415) >> 1;
++ break;
++ case V4L2_CID_SATURATION:
++ ctrl->value = cx18_av_read(cx, 0x420) >> 1;
++ break;
++ case V4L2_CID_HUE:
++ ctrl->value = (s8)cx18_av_read(cx, 0x422);
++ break;
++ case V4L2_CID_AUDIO_VOLUME:
++ case V4L2_CID_AUDIO_BASS:
++ case V4L2_CID_AUDIO_TREBLE:
++ case V4L2_CID_AUDIO_BALANCE:
++ case V4L2_CID_AUDIO_MUTE:
++ return cx18_av_audio(cx, VIDIOC_G_CTRL, ctrl);
++ default:
++ return -EINVAL;
++ }
+
-+ fe->ops.tuner_ops.get_status(fe, &tuner_status);
++ return 0;
++}
+
-+ if (fe->ops.i2c_gate_ctrl)
-+ fe->ops.i2c_gate_ctrl(fe, 0);
-+ }
-+ if (tuner_status)
-+ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
-+ break;
++/* ----------------------------------------------------------------------- */
++
++static int get_v4lfmt(struct cx18 *cx, struct v4l2_format *fmt)
++{
++ switch (fmt->type) {
++ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
++ return cx18_av_vbi(cx, VIDIOC_G_FMT, fmt);
++ default:
++ return -EINVAL;
+ }
+
-+ dprintk("%s() status 0x%08x\n", __func__, *status);
-+
+ return 0;
+}
+
-+static int s5h1411_qam256_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
++static int set_v4lfmt(struct cx18 *cx, struct v4l2_format *fmt)
+{
-+ int i, ret = -EINVAL;
-+ dprintk("%s()\n", __func__);
++ struct cx18_av_state *state = &cx->av_state;
++ struct v4l2_pix_format *pix;
++ int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
++ int is_50Hz = !(state->std & V4L2_STD_525_60);
+
-+ 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;
++ switch (fmt->type) {
++ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
++ pix = &(fmt->fmt.pix);
++
++ Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4;
++ Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4;
++
++ Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4;
++ Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4;
++
++ Vlines = pix->height + (is_50Hz ? 4 : 7);
++
++ if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) ||
++ (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
++ CX18_ERR("%dx%d is not a valid size!\n",
++ pix->width, pix->height);
++ return -ERANGE;
+ }
-+ }
-+ return ret;
-+}
+
-+static int s5h1411_qam64_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
-+{
-+ int i, ret = -EINVAL;
-+ dprintk("%s()\n", __func__);
++ HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20);
++ VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
++ VSC &= 0x1fff;
++
++ if (pix->width >= 385)
++ filter = 0;
++ else if (pix->width > 192)
++ filter = 1;
++ else if (pix->width > 96)
++ filter = 2;
++ else
++ filter = 3;
+
-+ 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;
-+}
++ CX18_DEBUG_INFO("decoder set size %dx%d -> scale %ux%u\n",
++ pix->width, pix->height, HSC, VSC);
+
-+static int s5h1411_vsb_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
-+{
-+ int i, ret = -EINVAL;
-+ dprintk("%s()\n", __func__);
++ /* HSCALE=HSC */
++ cx18_av_write(cx, 0x418, HSC & 0xff);
++ cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff);
++ cx18_av_write(cx, 0x41a, HSC >> 16);
++ /* VSCALE=VSC */
++ cx18_av_write(cx, 0x41c, VSC & 0xff);
++ cx18_av_write(cx, 0x41d, VSC >> 8);
++ /* VS_INTRLACE=1 VFILT=filter */
++ cx18_av_write(cx, 0x41e, 0x8 | filter);
++ break;
+
-+ 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;
-+}
++ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
++ return cx18_av_vbi(cx, VIDIOC_S_FMT, fmt);
+
-+static int s5h1411_read_snr(struct dvb_frontend *fe, u16 *snr)
-+{
-+ struct s5h1411_state *state = fe->demodulator_priv;
-+ u16 reg;
-+ dprintk("%s()\n", __func__);
++ case V4L2_BUF_TYPE_VBI_CAPTURE:
++ return cx18_av_vbi(cx, VIDIOC_S_FMT, fmt);
+
-+ 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;
+ }
+
-+ return -EINVAL;
++ return 0;
+}
+
-+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)
++int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg)
+{
-+ struct s5h1411_state *state = fe->demodulator_priv;
++ struct cx18_av_state *state = &cx->av_state;
++ struct v4l2_tuner *vt = arg;
++ struct v4l2_routing *route = arg;
+
-+ *ucblocks = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xc9);
++ /* ignore these commands */
++ switch (cmd) {
++ case TUNER_SET_TYPE_ADDR:
++ return 0;
++ }
+
-+ return 0;
-+}
++ if (!state->is_initialized) {
++ CX18_DEBUG_INFO("cmd %08x triggered fw load\n", cmd);
++ /* initialize on first use */
++ state->is_initialized = 1;
++ cx18_av_initialize(cx);
++ }
+
-+static int s5h1411_read_ber(struct dvb_frontend *fe, u32 *ber)
-+{
-+ return s5h1411_read_ucblocks(fe, ber);
-+}
++ switch (cmd) {
++ case VIDIOC_INT_DECODE_VBI_LINE:
++ return cx18_av_vbi(cx, cmd, arg);
+
-+static int s5h1411_get_frontend(struct dvb_frontend *fe,
-+ struct dvb_frontend_parameters *p)
-+{
-+ struct s5h1411_state *state = fe->demodulator_priv;
++ case VIDIOC_INT_AUDIO_CLOCK_FREQ:
++ return cx18_av_audio(cx, cmd, arg);
+
-+ p->frequency = state->current_frequency;
-+ p->u.vsb.modulation = state->current_modulation;
++ case VIDIOC_STREAMON:
++ CX18_DEBUG_INFO("enable output\n");
++ cx18_av_write(cx, 0x115, 0x8c);
++ cx18_av_write(cx, 0x116, 0x07);
++ break;
+
-+ return 0;
-+}
++ case VIDIOC_STREAMOFF:
++ CX18_DEBUG_INFO("disable output\n");
++ cx18_av_write(cx, 0x115, 0x00);
++ cx18_av_write(cx, 0x116, 0x00);
++ break;
+
-+static int s5h1411_get_tune_settings(struct dvb_frontend *fe,
-+ struct dvb_frontend_tune_settings *tune)
-+{
-+ tune->min_delay_ms = 1000;
-+ return 0;
-+}
++ case VIDIOC_LOG_STATUS:
++ log_video_status(cx);
++ log_audio_status(cx);
++ break;
+
-+static void s5h1411_release(struct dvb_frontend *fe)
-+{
-+ struct s5h1411_state *state = fe->demodulator_priv;
-+ kfree(state);
-+}
++ case VIDIOC_G_CTRL:
++ return get_v4lctrl(cx, (struct v4l2_control *)arg);
+
-+static struct dvb_frontend_ops s5h1411_ops;
++ case VIDIOC_S_CTRL:
++ return set_v4lctrl(cx, (struct v4l2_control *)arg);
+
-+struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
-+ struct i2c_adapter *i2c)
-+{
-+ struct s5h1411_state *state = NULL;
-+ u16 reg;
++ case VIDIOC_QUERYCTRL:
++ {
++ struct v4l2_queryctrl *qc = arg;
+
-+ /* allocate memory for the internal state */
-+ state = kmalloc(sizeof(struct s5h1411_state), GFP_KERNEL);
-+ if (state == NULL)
-+ goto error;
++ switch (qc->id) {
++ case V4L2_CID_BRIGHTNESS:
++ case V4L2_CID_CONTRAST:
++ case V4L2_CID_SATURATION:
++ case V4L2_CID_HUE:
++ return v4l2_ctrl_query_fill_std(qc);
++ default:
++ break;
++ }
+
-+ /* setup the state */
-+ state->config = config;
-+ state->i2c = i2c;
-+ state->current_modulation = VSB_8;
-+ state->inversion = state->config->inversion;
++ switch (qc->id) {
++ case V4L2_CID_AUDIO_VOLUME:
++ case V4L2_CID_AUDIO_MUTE:
++ case V4L2_CID_AUDIO_BALANCE:
++ case V4L2_CID_AUDIO_BASS:
++ case V4L2_CID_AUDIO_TREBLE:
++ return v4l2_ctrl_query_fill_std(qc);
++ default:
++ return -EINVAL;
++ }
++ return -EINVAL;
++ }
+
-+ /* check if the demod exists */
-+ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x05);
-+ if (reg != 0x0066)
-+ goto error;
++ case VIDIOC_G_STD:
++ *(v4l2_std_id *)arg = state->std;
++ break;
+
-+ /* create dvb_frontend */
-+ memcpy(&state->frontend.ops, &s5h1411_ops,
-+ sizeof(struct dvb_frontend_ops));
++ case VIDIOC_S_STD:
++ if (state->radio == 0 && state->std == *(v4l2_std_id *)arg)
++ return 0;
++ state->radio = 0;
++ state->std = *(v4l2_std_id *)arg;
++ return set_v4lstd(cx);
+
-+ state->frontend.demodulator_priv = state;
++ case AUDC_SET_RADIO:
++ state->radio = 1;
++ break;
+
-+ if (s5h1411_init(&state->frontend) != 0) {
-+ printk(KERN_ERR "%s: Failed to initialize correctly\n",
-+ __func__);
-+ goto error;
-+ }
++ case VIDIOC_INT_G_VIDEO_ROUTING:
++ route->input = state->vid_input;
++ route->output = 0;
++ break;
+
-+ /* Note: Leaving the I2C gate open here. */
-+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
++ case VIDIOC_INT_S_VIDEO_ROUTING:
++ return set_input(cx, route->input, state->aud_input);
+
-+ return &state->frontend;
++ case VIDIOC_INT_G_AUDIO_ROUTING:
++ route->input = state->aud_input;
++ route->output = 0;
++ break;
+
-+error:
-+ kfree(state);
-+ return NULL;
-+}
-+EXPORT_SYMBOL(s5h1411_attach);
++ case VIDIOC_INT_S_AUDIO_ROUTING:
++ return set_input(cx, state->vid_input, route->input);
+
-+static struct dvb_frontend_ops s5h1411_ops = {
++ case VIDIOC_S_FREQUENCY:
++ input_change(cx);
++ break;
+
-+ .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
-+ },
++ case VIDIOC_G_TUNER:
++ {
++ u8 vpres = cx18_av_read(cx, 0x40e) & 0x20;
++ u8 mode;
++ int val = 0;
+
-+ .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,
-+};
++ if (state->radio)
++ break;
+
-+module_param(debug, int, 0644);
-+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
++ vt->signal = vpres ? 0xffff : 0x0;
+
-+MODULE_DESCRIPTION("Samsung S5H1411 QAM-B/ATSC Demodulator driver");
-+MODULE_AUTHOR("Steven Toth");
-+MODULE_LICENSE("GPL");
++ vt->capability |=
++ V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
++ V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
+
-+/*
-+ * 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
++ mode = cx18_av_read(cx, 0x804);
+
-+ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
++ /* get rxsubchans and audmode */
++ if ((mode & 0xf) == 1)
++ val |= V4L2_TUNER_SUB_STEREO;
++ else
++ val |= V4L2_TUNER_SUB_MONO;
+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the 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 (mode == 2 || mode == 4)
++ val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
++ if (mode & 0x10)
++ val |= V4L2_TUNER_SUB_SAP;
+
-+ You 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.
++ vt->rxsubchans = val;
++ vt->audmode = state->audmode;
++ break;
++ }
+
-+*/
++ case VIDIOC_S_TUNER:
++ if (state->radio)
++ break;
+
-+#ifndef __S5H1411_H__
-+#define __S5H1411_H__
++ switch (vt->audmode) {
++ case V4L2_TUNER_MODE_MONO:
++ /* mono -> mono
++ stereo -> mono
++ bilingual -> lang1 */
++ cx18_av_and_or(cx, 0x809, ~0xf, 0x00);
++ break;
++ case V4L2_TUNER_MODE_STEREO:
++ case V4L2_TUNER_MODE_LANG1:
++ /* mono -> mono
++ stereo -> stereo
++ bilingual -> lang1 */
++ cx18_av_and_or(cx, 0x809, ~0xf, 0x04);
++ break;
++ case V4L2_TUNER_MODE_LANG1_LANG2:
++ /* mono -> mono
++ stereo -> stereo
++ bilingual -> lang1/lang2 */
++ cx18_av_and_or(cx, 0x809, ~0xf, 0x07);
++ break;
++ case V4L2_TUNER_MODE_LANG2:
++ /* mono -> mono
++ stereo -> stereo
++ bilingual -> lang2 */
++ cx18_av_and_or(cx, 0x809, ~0xf, 0x01);
++ break;
++ default:
++ return -EINVAL;
++ }
++ state->audmode = vt->audmode;
++ break;
+
-+#include <linux/dvb/frontend.h>
++ case VIDIOC_G_FMT:
++ return get_v4lfmt(cx, (struct v4l2_format *)arg);
+
-+#define S5H1411_I2C_TOP_ADDR (0x32 >> 1)
-+#define S5H1411_I2C_QAM_ADDR (0x34 >> 1)
++ case VIDIOC_S_FMT:
++ return set_v4lfmt(cx, (struct v4l2_format *)arg);
+
-+struct s5h1411_config {
++ case VIDIOC_INT_RESET:
++ cx18_av_initialize(cx);
++ break;
+
-+ /* serial/parallel output */
-+#define S5H1411_PARALLEL_OUTPUT 0
-+#define S5H1411_SERIAL_OUTPUT 1
-+ u8 output_mode;
++ default:
++ return -EINVAL;
++ }
+
-+ /* GPIO Setting */
-+#define S5H1411_GPIO_OFF 0
-+#define S5H1411_GPIO_ON 1
-+ u8 gpio;
++ return 0;
++}
+
-+ /* 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;
++static void log_video_status(struct cx18 *cx)
++{
++ static const char *const fmt_strs[] = {
++ "0x0",
++ "NTSC-M", "NTSC-J", "NTSC-4.43",
++ "PAL-BDGHI", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60",
++ "0x9", "0xA", "0xB",
++ "SECAM",
++ "0xD", "0xE", "0xF"
++ };
+
-+ /* Return lock status based on tuner lock, or demod lock */
-+#define S5H1411_TUNERLOCKING 0
-+#define S5H1411_DEMODLOCKING 1
-+ u8 status_mode;
-+};
++ struct cx18_av_state *state = &cx->av_state;
++ u8 vidfmt_sel = cx18_av_read(cx, 0x400) & 0xf;
++ u8 gen_stat1 = cx18_av_read(cx, 0x40d);
++ u8 gen_stat2 = cx18_av_read(cx, 0x40e);
++ int vid_input = state->vid_input;
++
++ CX18_INFO("Video signal: %spresent\n",
++ (gen_stat2 & 0x20) ? "" : "not ");
++ CX18_INFO("Detected format: %s\n",
++ fmt_strs[gen_stat1 & 0xf]);
++
++ CX18_INFO("Specified standard: %s\n",
++ vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");
++
++ if (vid_input >= CX18_AV_COMPOSITE1 &&
++ vid_input <= CX18_AV_COMPOSITE8) {
++ CX18_INFO("Specified video input: Composite %d\n",
++ vid_input - CX18_AV_COMPOSITE1 + 1);
++ } else {
++ CX18_INFO("Specified video input: S-Video (Luma In%d, Chroma In%d)\n",
++ (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8);
++ }
+
-+#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;
++ CX18_INFO("Specified audioclock freq: %d Hz\n", state->audclk_freq);
+}
-+#endif /* CONFIG_DVB_S5H1411 */
+
-+#endif /* __S5H1411_H__ */
++/* ----------------------------------------------------------------------- */
++
++static void log_audio_status(struct cx18 *cx)
++{
++ struct cx18_av_state *state = &cx->av_state;
++ u8 download_ctl = cx18_av_read(cx, 0x803);
++ u8 mod_det_stat0 = cx18_av_read(cx, 0x805);
++ u8 mod_det_stat1 = cx18_av_read(cx, 0x804);
++ u8 audio_config = cx18_av_read(cx, 0x808);
++ u8 pref_mode = cx18_av_read(cx, 0x809);
++ u8 afc0 = cx18_av_read(cx, 0x80b);
++ u8 mute_ctl = cx18_av_read(cx, 0x8d3);
++ int aud_input = state->aud_input;
++ char *p;
++
++ switch (mod_det_stat0) {
++ case 0x00: p = "mono"; break;
++ case 0x01: p = "stereo"; break;
++ case 0x02: p = "dual"; break;
++ case 0x04: p = "tri"; break;
++ case 0x10: p = "mono with SAP"; break;
++ case 0x11: p = "stereo with SAP"; break;
++ case 0x12: p = "dual with SAP"; break;
++ case 0x14: p = "tri with SAP"; break;
++ case 0xfe: p = "forced mode"; break;
++ default: p = "not defined";
++ }
++ CX18_INFO("Detected audio mode: %s\n", p);
++
++ switch (mod_det_stat1) {
++ case 0x00: p = "BTSC"; break;
++ case 0x01: p = "EIAJ"; break;
++ case 0x02: p = "A2-M"; break;
++ case 0x03: p = "A2-BG"; break;
++ case 0x04: p = "A2-DK1"; break;
++ case 0x05: p = "A2-DK2"; break;
++ case 0x06: p = "A2-DK3"; break;
++ case 0x07: p = "A1 (6.0 MHz FM Mono)"; break;
++ case 0x08: p = "AM-L"; break;
++ case 0x09: p = "NICAM-BG"; break;
++ case 0x0a: p = "NICAM-DK"; break;
++ case 0x0b: p = "NICAM-I"; break;
++ case 0x0c: p = "NICAM-L"; break;
++ case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break;
++ case 0xff: p = "no detected audio standard"; break;
++ default: p = "not defined";
++ }
++ CX18_INFO("Detected audio standard: %s\n", p);
++ CX18_INFO("Audio muted: %s\n",
++ (mute_ctl & 0x2) ? "yes" : "no");
++ CX18_INFO("Audio microcontroller: %s\n",
++ (download_ctl & 0x10) ? "running" : "stopped");
++
++ switch (audio_config >> 4) {
++ case 0x00: p = "BTSC"; break;
++ case 0x01: p = "EIAJ"; break;
++ case 0x02: p = "A2-M"; break;
++ case 0x03: p = "A2-BG"; break;
++ case 0x04: p = "A2-DK1"; break;
++ case 0x05: p = "A2-DK2"; break;
++ case 0x06: p = "A2-DK3"; break;
++ case 0x07: p = "A1 (6.0 MHz FM Mono)"; break;
++ case 0x08: p = "AM-L"; break;
++ case 0x09: p = "NICAM-BG"; break;
++ case 0x0a: p = "NICAM-DK"; break;
++ case 0x0b: p = "NICAM-I"; break;
++ case 0x0c: p = "NICAM-L"; break;
++ case 0x0d: p = "FM radio"; break;
++ case 0x0f: p = "automatic detection"; break;
++ default: p = "undefined";
++ }
++ CX18_INFO("Configured audio standard: %s\n", p);
++
++ if ((audio_config >> 4) < 0xF) {
++ switch (audio_config & 0xF) {
++ case 0x00: p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)"; break;
++ case 0x01: p = "MONO2 (LANGUAGE B)"; break;
++ case 0x02: p = "MONO3 (STEREO forced MONO)"; break;
++ case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break;
++ case 0x04: p = "STEREO"; break;
++ case 0x05: p = "DUAL1 (AB)"; break;
++ case 0x06: p = "DUAL2 (AC) (FM)"; break;
++ case 0x07: p = "DUAL3 (BC) (FM)"; break;
++ case 0x08: p = "DUAL4 (AC) (AM)"; break;
++ case 0x09: p = "DUAL5 (BC) (AM)"; break;
++ case 0x0a: p = "SAP"; break;
++ default: p = "undefined";
++ }
++ CX18_INFO("Configured audio mode: %s\n", p);
++ } else {
++ switch (audio_config & 0xF) {
++ case 0x00: p = "BG"; break;
++ case 0x01: p = "DK1"; break;
++ case 0x02: p = "DK2"; break;
++ case 0x03: p = "DK3"; break;
++ case 0x04: p = "I"; break;
++ case 0x05: p = "L"; break;
++ case 0x06: p = "BTSC"; break;
++ case 0x07: p = "EIAJ"; break;
++ case 0x08: p = "A2-M"; break;
++ case 0x09: p = "FM Radio"; break;
++ case 0x0f: p = "automatic standard and mode detection"; break;
++ default: p = "undefined";
++ }
++ CX18_INFO("Configured audio system: %s\n", p);
++ }
++
++ if (aud_input)
++ CX18_INFO("Specified audio input: Tuner (In%d)\n",
++ aud_input);
++ else
++ CX18_INFO("Specified audio input: External\n");
+
++ switch (pref_mode & 0xf) {
++ case 0: p = "mono/language A"; break;
++ case 1: p = "language B"; break;
++ case 2: p = "language C"; break;
++ case 3: p = "analog fallback"; break;
++ case 4: p = "stereo"; break;
++ case 5: p = "language AC"; break;
++ case 6: p = "language BC"; break;
++ case 7: p = "language AB"; break;
++ default: p = "undefined";
++ }
++ CX18_INFO("Preferred audio mode: %s\n", p);
++
++ if ((audio_config & 0xf) == 0xf) {
++ switch ((afc0 >> 2) & 0x1) {
++ case 0: p = "system DK"; break;
++ case 1: p = "system L"; break;
++ }
++ CX18_INFO("Selected 65 MHz format: %s\n", p);
++
++ switch (afc0 & 0x3) {
++ case 0: p = "BTSC"; break;
++ case 1: p = "EIAJ"; break;
++ case 2: p = "A2-M"; break;
++ default: p = "undefined";
++ }
++ CX18_INFO("Selected 45 MHz format: %s\n", p);
++ }
++}
+diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h
+new file mode 100644
+index 0000000..786901d
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-av-core.h
+@@ -0,0 +1,318 @@
+/*
-+ * Local variables:
-+ * c-basic-offset: 8
-+ */
-diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
-index 2c2c344..281e1cb 100644
---- a/drivers/media/dvb/frontends/s5h1420.c
-+++ b/drivers/media/dvb/frontends/s5h1420.c
-@@ -1,24 +1,26 @@
- /*
--Driver for Samsung S5H1420 QPSK Demodulator
--
--Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
--
--This program is free software; you can redistribute it and/or modify
--it under the terms of the GNU General Public License as published by
--the Free Software Foundation; either version 2 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,
--but WITHOUT ANY WARRANTY; without even the implied warranty of
--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--
--GNU General Public License for more details.
--
--You should have received a copy of the GNU General Public License
--along with this program; if not, write to the Free Software
--Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
--*/
-+ * Driver for
-+ * Samsung S5H1420 and
-+ * PnpNetwork PN1010 QPSK Demodulator
++ * cx18 ADEC header
+ *
-+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
-+ * Copyright (C) 2005-8 Patrick Boettcher <pb at linuxtv.org>
++ * Derived from cx25840-core.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.
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
+ *
-+ * GNU General Public License for more details.
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
+ *
-+ * You 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.
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++ * 02110-1301, USA.
+ */
-
- #include <linux/kernel.h>
- #include <linux/module.h>
-@@ -29,23 +31,35 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- #include <linux/jiffies.h>
- #include <asm/div64.h>
-
--#include "dvb_frontend.h"
--#include "s5h1420.h"
-+#include <linux/i2c.h>
-
-
-+#include "dvb_frontend.h"
-+#include "s5h1420.h"
-+#include "s5h1420_priv.h"
-
- #define TONE_FREQ 22000
-
- struct s5h1420_state {
- struct i2c_adapter* i2c;
- const struct s5h1420_config* config;
-+
- struct dvb_frontend frontend;
-+ struct i2c_adapter tuner_i2c_adapter;
+
-+ u8 CON_1_val;
-
- u8 postlocked:1;
- u32 fclk;
- u32 tunedfreq;
- fe_code_rate_t fec_inner;
- u32 symbol_rate;
++#ifndef _CX18_AV_CORE_H_
++#define _CX18_AV_CORE_H_
+
-+ /* 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");
++struct cx18;
+
-+#define dprintk(x...) do { \
-+ if (debug) \
-+ printk(KERN_DEBUG "S5H1420: " x); \
-+} while (0)
++enum cx18_av_video_input {
++ /* Composite video inputs In1-In8 */
++ CX18_AV_COMPOSITE1 = 1,
++ CX18_AV_COMPOSITE2,
++ CX18_AV_COMPOSITE3,
++ CX18_AV_COMPOSITE4,
++ CX18_AV_COMPOSITE5,
++ CX18_AV_COMPOSITE6,
++ CX18_AV_COMPOSITE7,
++ CX18_AV_COMPOSITE8,
++
++ /* S-Video inputs consist of one luma input (In1-In4) ORed with one
++ chroma input (In5-In8) */
++ CX18_AV_SVIDEO_LUMA1 = 0x10,
++ CX18_AV_SVIDEO_LUMA2 = 0x20,
++ CX18_AV_SVIDEO_LUMA3 = 0x30,
++ CX18_AV_SVIDEO_LUMA4 = 0x40,
++ CX18_AV_SVIDEO_CHROMA4 = 0x400,
++ CX18_AV_SVIDEO_CHROMA5 = 0x500,
++ CX18_AV_SVIDEO_CHROMA6 = 0x600,
++ CX18_AV_SVIDEO_CHROMA7 = 0x700,
++ CX18_AV_SVIDEO_CHROMA8 = 0x800,
++
++ /* S-Video aliases for common luma/chroma combinations */
++ CX18_AV_SVIDEO1 = 0x510,
++ CX18_AV_SVIDEO2 = 0x620,
++ CX18_AV_SVIDEO3 = 0x730,
++ CX18_AV_SVIDEO4 = 0x840,
++};
++
++enum cx18_av_audio_input {
++ /* Audio inputs: serial or In4-In8 */
++ CX18_AV_AUDIO_SERIAL,
++ CX18_AV_AUDIO4 = 4,
++ CX18_AV_AUDIO5,
++ CX18_AV_AUDIO6,
++ CX18_AV_AUDIO7,
++ CX18_AV_AUDIO8,
++};
+
-+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 },
-+ };
++struct cx18_av_state {
++ int radio;
++ v4l2_std_id std;
++ enum cx18_av_video_input vid_input;
++ enum cx18_av_audio_input aud_input;
++ u32 audclk_freq;
++ int audmode;
++ int vbi_line_offset;
++ u32 id;
++ u32 rev;
++ int is_initialized;
++};
+
-+ 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;
-+ }
++/* Registers */
++#define CXADEC_CHIP_TYPE_TIGER 0x837
++#define CXADEC_CHIP_TYPE_MAKO 0x843
+
-+ /* dprintk("rd(%02x): %02x %02x\n", state->config->demod_address, reg, b[0]); */
++#define CXADEC_HOST_REG1 0x000
++#define CXADEC_HOST_REG2 0x001
+
-+ 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__);
++#define CXADEC_CHIP_CTRL 0x100
++#define CXADEC_AFE_CTRL 0x104
++#define CXADEC_PLL_CTRL1 0x108
++#define CXADEC_VID_PLL_FRAC 0x10C
++#define CXADEC_AUX_PLL_FRAC 0x110
++#define CXADEC_PIN_CTRL1 0x114
++#define CXADEC_PIN_CTRL2 0x118
++#define CXADEC_PIN_CFG1 0x11C
++#define CXADEC_PIN_CFG2 0x120
++
++#define CXADEC_PIN_CFG3 0x124
++#define CXADEC_I2S_MCLK 0x127
++
++#define CXADEC_AUD_LOCK1 0x128
++#define CXADEC_AUD_LOCK2 0x12C
++#define CXADEC_POWER_CTRL 0x130
++#define CXADEC_AFE_DIAG_CTRL1 0x134
++#define CXADEC_AFE_DIAG_CTRL2 0x138
++#define CXADEC_AFE_DIAG_CTRL3 0x13C
++#define CXADEC_PLL_DIAG_CTRL 0x140
++#define CXADEC_TEST_CTRL1 0x144
++#define CXADEC_TEST_CTRL2 0x148
++#define CXADEC_BIST_STAT 0x14C
++#define CXADEC_DLL1_DIAG_CTRL 0x158
++#define CXADEC_DLL2_DIAG_CTRL 0x15C
++
++/* IR registers */
++#define CXADEC_IR_CTRL_REG 0x200
++#define CXADEC_IR_TXCLK_REG 0x204
++#define CXADEC_IR_RXCLK_REG 0x208
++#define CXADEC_IR_CDUTY_REG 0x20C
++#define CXADEC_IR_STAT_REG 0x210
++#define CXADEC_IR_IRQEN_REG 0x214
++#define CXADEC_IR_FILTER_REG 0x218
++#define CXADEC_IR_FIFO_REG 0x21C
++
++/* Video Registers */
++#define CXADEC_MODE_CTRL 0x400
++#define CXADEC_OUT_CTRL1 0x404
++#define CXADEC_OUT_CTRL2 0x408
++#define CXADEC_GEN_STAT 0x40C
++#define CXADEC_INT_STAT_MASK 0x410
++#define CXADEC_LUMA_CTRL 0x414
++
++#define CXADEC_BRIGHTNESS_CTRL_BYTE 0x414
++#define CXADEC_CONTRAST_CTRL_BYTE 0x415
++#define CXADEC_LUMA_CTRL_BYTE_3 0x416
++
++#define CXADEC_HSCALE_CTRL 0x418
++#define CXADEC_VSCALE_CTRL 0x41C
++
++#define CXADEC_CHROMA_CTRL 0x420
++
++#define CXADEC_USAT_CTRL_BYTE 0x420
++#define CXADEC_VSAT_CTRL_BYTE 0x421
++#define CXADEC_HUE_CTRL_BYTE 0x422
++
++#define CXADEC_VBI_LINE_CTRL1 0x424
++#define CXADEC_VBI_LINE_CTRL2 0x428
++#define CXADEC_VBI_LINE_CTRL3 0x42C
++#define CXADEC_VBI_LINE_CTRL4 0x430
++#define CXADEC_VBI_LINE_CTRL5 0x434
++#define CXADEC_VBI_FC_CFG 0x438
++#define CXADEC_VBI_MISC_CFG1 0x43C
++#define CXADEC_VBI_MISC_CFG2 0x440
++#define CXADEC_VBI_PAY1 0x444
++#define CXADEC_VBI_PAY2 0x448
++#define CXADEC_VBI_CUST1_CFG1 0x44C
++#define CXADEC_VBI_CUST1_CFG2 0x450
++#define CXADEC_VBI_CUST1_CFG3 0x454
++#define CXADEC_VBI_CUST2_CFG1 0x458
++#define CXADEC_VBI_CUST2_CFG2 0x45C
++#define CXADEC_VBI_CUST2_CFG3 0x460
++#define CXADEC_VBI_CUST3_CFG1 0x464
++#define CXADEC_VBI_CUST3_CFG2 0x468
++#define CXADEC_VBI_CUST3_CFG3 0x46C
++#define CXADEC_HORIZ_TIM_CTRL 0x470
++#define CXADEC_VERT_TIM_CTRL 0x474
++#define CXADEC_SRC_COMB_CFG 0x478
++#define CXADEC_CHROMA_VBIOFF_CFG 0x47C
++#define CXADEC_FIELD_COUNT 0x480
++#define CXADEC_MISC_TIM_CTRL 0x484
++#define CXADEC_DFE_CTRL1 0x488
++#define CXADEC_DFE_CTRL2 0x48C
++#define CXADEC_DFE_CTRL3 0x490
++#define CXADEC_PLL_CTRL2 0x494
++#define CXADEC_HTL_CTRL 0x498
++#define CXADEC_COMB_CTRL 0x49C
++#define CXADEC_CRUSH_CTRL 0x4A0
++#define CXADEC_SOFT_RST_CTRL 0x4A4
++#define CXADEC_MV_DT_CTRL2 0x4A8
++#define CXADEC_MV_DT_CTRL3 0x4AC
++#define CXADEC_MISC_DIAG_CTRL 0x4B8
++
++#define CXADEC_DL_CTL 0x800
++#define CXADEC_DL_CTL_ADDRESS_LOW 0x800 /* Byte 1 in DL_CTL */
++#define CXADEC_DL_CTL_ADDRESS_HIGH 0x801 /* Byte 2 in DL_CTL */
++#define CXADEC_DL_CTL_DATA 0x802 /* Byte 3 in DL_CTL */
++#define CXADEC_DL_CTL_CONTROL 0x803 /* Byte 4 in DL_CTL */
++
++#define CXADEC_STD_DET_STATUS 0x804
++
++#define CXADEC_STD_DET_CTL 0x808
++#define CXADEC_STD_DET_CTL_AUD_CTL 0x808 /* Byte 1 in STD_DET_CTL */
++#define CXADEC_STD_DET_CTL_PREF_MODE 0x809 /* Byte 2 in STD_DET_CTL */
++
++#define CXADEC_DW8051_INT 0x80C
++#define CXADEC_GENERAL_CTL 0x810
++#define CXADEC_AAGC_CTL 0x814
++#define CXADEC_IF_SRC_CTL 0x818
++#define CXADEC_ANLOG_DEMOD_CTL 0x81C
++#define CXADEC_ROT_FREQ_CTL 0x820
++#define CXADEC_FM1_CTL 0x824
++#define CXADEC_PDF_CTL 0x828
++#define CXADEC_DFT1_CTL1 0x82C
++#define CXADEC_DFT1_CTL2 0x830
++#define CXADEC_DFT_STATUS 0x834
++#define CXADEC_DFT2_CTL1 0x838
++#define CXADEC_DFT2_CTL2 0x83C
++#define CXADEC_DFT2_STATUS 0x840
++#define CXADEC_DFT3_CTL1 0x844
++#define CXADEC_DFT3_CTL2 0x848
++#define CXADEC_DFT3_STATUS 0x84C
++#define CXADEC_DFT4_CTL1 0x850
++#define CXADEC_DFT4_CTL2 0x854
++#define CXADEC_DFT4_STATUS 0x858
++#define CXADEC_AM_MTS_DET 0x85C
++#define CXADEC_ANALOG_MUX_CTL 0x860
++#define CXADEC_DIG_PLL_CTL1 0x864
++#define CXADEC_DIG_PLL_CTL2 0x868
++#define CXADEC_DIG_PLL_CTL3 0x86C
++#define CXADEC_DIG_PLL_CTL4 0x870
++#define CXADEC_DIG_PLL_CTL5 0x874
++#define CXADEC_DEEMPH_GAIN_CTL 0x878
++#define CXADEC_DEEMPH_COEF1 0x87C
++#define CXADEC_DEEMPH_COEF2 0x880
++#define CXADEC_DBX1_CTL1 0x884
++#define CXADEC_DBX1_CTL2 0x888
++#define CXADEC_DBX1_STATUS 0x88C
++#define CXADEC_DBX2_CTL1 0x890
++#define CXADEC_DBX2_CTL2 0x894
++#define CXADEC_DBX2_STATUS 0x898
++#define CXADEC_AM_FM_DIFF 0x89C
++
++/* NICAM registers go here */
++#define CXADEC_NICAM_STATUS 0x8C8
++#define CXADEC_DEMATRIX_CTL 0x8CC
++
++#define CXADEC_PATH1_CTL1 0x8D0
++#define CXADEC_PATH1_VOL_CTL 0x8D4
++#define CXADEC_PATH1_EQ_CTL 0x8D8
++#define CXADEC_PATH1_SC_CTL 0x8DC
++
++#define CXADEC_PATH2_CTL1 0x8E0
++#define CXADEC_PATH2_VOL_CTL 0x8E4
++#define CXADEC_PATH2_EQ_CTL 0x8E8
++#define CXADEC_PATH2_SC_CTL 0x8EC
++
++#define CXADEC_SRC_CTL 0x8F0
++#define CXADEC_SRC_LF_COEF 0x8F4
++#define CXADEC_SRC1_CTL 0x8F8
++#define CXADEC_SRC2_CTL 0x8FC
++#define CXADEC_SRC3_CTL 0x900
++#define CXADEC_SRC4_CTL 0x904
++#define CXADEC_SRC5_CTL 0x908
++#define CXADEC_SRC6_CTL 0x90C
++
++#define CXADEC_BASEBAND_OUT_SEL 0x910
++#define CXADEC_I2S_IN_CTL 0x914
++#define CXADEC_I2S_OUT_CTL 0x918
++#define CXADEC_AC97_CTL 0x91C
++#define CXADEC_QAM_PDF 0x920
++#define CXADEC_QAM_CONST_DEC 0x924
++#define CXADEC_QAM_ROTATOR_FREQ 0x948
++
++/* Bit defintions / settings used in Mako Audio */
++#define CXADEC_PREF_MODE_MONO_LANGA 0
++#define CXADEC_PREF_MODE_MONO_LANGB 1
++#define CXADEC_PREF_MODE_MONO_LANGC 2
++#define CXADEC_PREF_MODE_FALLBACK 3
++#define CXADEC_PREF_MODE_STEREO 4
++#define CXADEC_PREF_MODE_DUAL_LANG_AC 5
++#define CXADEC_PREF_MODE_DUAL_LANG_BC 6
++#define CXADEC_PREF_MODE_DUAL_LANG_AB 7
++
++
++#define CXADEC_DETECT_STEREO 1
++#define CXADEC_DETECT_DUAL 2
++#define CXADEC_DETECT_TRI 4
++#define CXADEC_DETECT_SAP 0x10
++#define CXADEC_DETECT_NO_SIGNAL 0xFF
++
++#define CXADEC_SELECT_AUDIO_STANDARD_BG 0xF0 /* NICAM BG and A2 BG */
++#define CXADEC_SELECT_AUDIO_STANDARD_DK1 0xF1 /* NICAM DK and A2 DK */
++#define CXADEC_SELECT_AUDIO_STANDARD_DK2 0xF2
++#define CXADEC_SELECT_AUDIO_STANDARD_DK3 0xF3
++#define CXADEC_SELECT_AUDIO_STANDARD_I 0xF4 /* NICAM I and A1 */
++#define CXADEC_SELECT_AUDIO_STANDARD_L 0xF5 /* NICAM L and System L AM */
++#define CXADEC_SELECT_AUDIO_STANDARD_BTSC 0xF6
++#define CXADEC_SELECT_AUDIO_STANDARD_EIAJ 0xF7
++#define CXADEC_SELECT_AUDIO_STANDARD_A2_M 0xF8 /* A2 M */
++#define CXADEC_SELECT_AUDIO_STANDARD_FM 0xF9 /* FM radio */
++#define CXADEC_SELECT_AUDIO_STANDARD_AUTO 0xFF /* Auto detect */
+
- 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__);
++/* ----------------------------------------------------------------------- */
++/* cx18_av-core.c */
++int cx18_av_write(struct cx18 *cx, u16 addr, u8 value);
++int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value);
++u8 cx18_av_read(struct cx18 *cx, u16 addr);
++u32 cx18_av_read4(struct cx18 *cx, u16 addr);
++int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value);
++int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value);
++int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg);
+
- 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;
- }
++/* ----------------------------------------------------------------------- */
++/* cx18_av-firmware.c */
++int cx18_av_loadfw(struct cx18 *cx);
+
- 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;
-
++/* ----------------------------------------------------------------------- */
++/* cx18_av-audio.c */
++int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg);
++void cx18_av_audio_set_path(struct cx18 *cx);
+
- /* 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);
++/* ----------------------------------------------------------------------- */
++/* cx18_av-vbi.c */
++void cx18_av_vbi_setup(struct cx18 *cx);
++int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg);
+
-+ s5h1420_writereg(state, FEC01, 0x18);
-+ s5h1420_writereg(state, FEC01, 0x10);
-+ s5h1420_writereg(state, FEC01, val);
++#endif
+diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c
+new file mode 100644
+index 0000000..526e142
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-av-firmware.c
+@@ -0,0 +1,120 @@
++/*
++ * cx18 ADEC firmware functions
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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.
++ */
+
-+ /* 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 */
++#include "cx18-driver.h"
++#include <linux/firmware.h>
+
-+ 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__);
++#define FWFILE "v4l-cx23418-dig.fw"
+
- 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__);
++int cx18_av_loadfw(struct cx18 *cx)
++{
++ const struct firmware *fw = NULL;
++ u32 size;
++ u32 v;
++ u8 *ptr;
++ int i;
+
- 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);
++ if (request_firmware(&fw, FWFILE, &cx->dev->dev) != 0) {
++ CX18_ERR("unable to open firmware %s\n", FWFILE);
++ return -EINVAL;
++ }
+
-+ 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;
++ cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000);
++ cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6); /* Byte 0 */
+
-+ 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);
++ /* Reset the Mako core (Register is undocumented.) */
++ cx18_av_write4(cx, 0x8100, 0x00010000);
+
-+ 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;
++ /* Put the 8051 in reset and enable firmware upload */
++ cx18_av_write4(cx, CXADEC_DL_CTL, 0x0F000000);
+
-+ 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;
++ ptr = fw->data;
++ size = fw->size;
+
-+ 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;
++ for (i = 0; i < size; i++) {
++ u32 dl_control = 0x0F000000 | ((u32)ptr[i] << 16);
++ u32 value = 0;
++ int retries;
+
-+ /* 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);
++ for (retries = 0; retries < 5; retries++) {
++ cx18_av_write4(cx, CXADEC_DL_CTL, dl_control);
++ value = cx18_av_read4(cx, CXADEC_DL_CTL);
++ if ((value & 0x3F00) == (dl_control & 0x3F00))
++ break;
++ }
++ if (retries >= 5) {
++ CX18_ERR("unable to load firmware %s\n", FWFILE);
++ release_firmware(fw);
++ return -EIO;
++ }
++ }
+
-+ 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);
++ cx18_av_write4(cx, CXADEC_DL_CTL, 0x13000000 | fw->size);
+
-+ 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);
++ /* Output to the 416 */
++ cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x78000);
+
-+ s5h1420_writereg(state, Monitor12, 0x00); /* unfreeze DC compensation */
++ /* Audio input control 1 set to Sony mode */
++ /* Audio output input 2 is 0 for slave operation input */
++ /* 0xC4000914[5]: 0 = left sample on WS=0, 1 = left sample on WS=1 */
++ /* 0xC4000914[7]: 0 = Philips mode, 1 = Sony mode (1st SCK rising edge
++ after WS transition for first bit of audio word. */
++ cx18_av_write4(cx, CXADEC_I2S_IN_CTL, 0x000000A0);
++
++ /* Audio output control 1 is set to Sony mode */
++ /* Audio output control 2 is set to 1 for master mode */
++ /* 0xC4000918[5]: 0 = left sample on WS=0, 1 = left sample on WS=1 */
++ /* 0xC4000918[7]: 0 = Philips mode, 1 = Sony mode (1st SCK rising edge
++ after WS transition for first bit of audio word. */
++ /* 0xC4000918[8]: 0 = slave operation, 1 = master (SCK_OUT and WS_OUT
++ are generated) */
++ cx18_av_write4(cx, CXADEC_I2S_OUT_CTL, 0x000001A0);
++
++ /* set alt I2s master clock to /16 and enable alt divider i2s
++ passthrough */
++ cx18_av_write4(cx, CXADEC_PIN_CFG3, 0x5000B687);
++
++ cx18_av_write4(cx, CXADEC_STD_DET_CTL, 0x000000F6);
++ /* CxDevWrReg(CXADEC_STD_DET_CTL, 0x000000FF); */
++
++ /* Set bit 0 in register 0x9CC to signify that this is MiniMe. */
++ /* Register 0x09CC is defined by the Merlin firmware, and doesn't
++ have a name in the spec. */
++ cx18_av_write4(cx, 0x09CC, 1);
++
++#define CX18_AUDIO_ENABLE 0xc72014
++ v = read_reg(CX18_AUDIO_ENABLE);
++ /* If bit 11 is 1 */
++ if (v & 0x800)
++ write_reg(v & 0xFFFFFBFF, CX18_AUDIO_ENABLE); /* Clear bit 10 */
++
++ /* Enable WW auto audio standard detection */
++ v = cx18_av_read4(cx, CXADEC_STD_DET_CTL);
++ v |= 0xFF; /* Auto by default */
++ v |= 0x400; /* Stereo by default */
++ v |= 0x14000000;
++ cx18_av_write4(cx, CXADEC_STD_DET_CTL, v);
+
-+ 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 */
++ release_firmware(fw);
+
-+ 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);
++ CX18_INFO("loaded %s firmware (%d bytes)\n", FWFILE, size);
++ return 0;
++}
+diff --git a/drivers/media/video/cx18/cx18-av-vbi.c b/drivers/media/video/cx18/cx18-av-vbi.c
+new file mode 100644
+index 0000000..d09f1da
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-av-vbi.c
+@@ -0,0 +1,413 @@
++/*
++ * cx18 ADEC VBI functions
++ *
++ * Derived from cx25840-vbi.c
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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.
++ */
+
- 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;
-+}
++#include "cx18-driver.h"
+
-+static int s5h1420_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
++static int odd_parity(u8 c)
+{
-+ 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 */
++ c ^= (c >> 4);
++ c ^= (c >> 2);
++ c ^= (c >> 1);
++
++ return c & 1;
++}
++
++static int decode_vps(u8 *dst, u8 *p)
++{
++ static const u8 biphase_tbl[] = {
++ 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
++ 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
++ 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
++ 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
++ 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
++ 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
++ 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
++ 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
++ 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
++ 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
++ 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
++ 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
++ 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
++ 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
++ 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
++ 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
++ 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
++ 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
++ 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
++ 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
++ 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
++ 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
++ 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
++ 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
++ 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
++ 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
++ 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
++ 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
++ 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
++ 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
++ 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
++ 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
++ };
+
-+ memset(m, 0, sizeof(struct i2c_msg) * (1 + num));
++ u8 c, err = 0;
++ int i;
+
-+ 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);
++ for (i = 0; i < 2 * 13; i += 2) {
++ err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
++ c = (biphase_tbl[p[i + 1]] & 0xf) |
++ ((biphase_tbl[p[i]] & 0xf) << 4);
++ dst[i / 2] = c;
++ }
+
-+ return i2c_transfer(state->i2c, m, 1+num) == 1 + num ? num : -EIO;
++ return err & 0xf0;
+}
+
-+static struct i2c_algorithm s5h1420_tuner_i2c_algo = {
-+ .master_xfer = s5h1420_tuner_i2c_tuner_xfer,
-+ .functionality = s5h1420_tuner_i2c_func,
-+};
++void cx18_av_vbi_setup(struct cx18 *cx)
++{
++ struct cx18_av_state *state = &cx->av_state;
++ v4l2_std_id std = state->std;
++ int hblank, hactive, burst, vblank, vactive, sc;
++ int vblank656, src_decimation;
++ int luma_lpf, uv_lpf, comb;
++ u32 pll_int, pll_frac, pll_post;
++
++ /* datasheet startup, step 8d */
++ if (std & ~V4L2_STD_NTSC)
++ cx18_av_write(cx, 0x49f, 0x11);
++ else
++ cx18_av_write(cx, 0x49f, 0x14);
+
-+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;
++ if (std & V4L2_STD_625_50) {
++ hblank = 0x084;
++ hactive = 0x2d0;
++ burst = 0x5d;
++ vblank = 0x024;
++ vactive = 0x244;
++ vblank656 = 0x28;
++ src_decimation = 0x21f;
++
++ luma_lpf = 2;
++ if (std & V4L2_STD_SECAM) {
++ uv_lpf = 0;
++ comb = 0;
++ sc = 0x0a425f;
++ } else if (std == V4L2_STD_PAL_Nc) {
++ uv_lpf = 1;
++ comb = 0x20;
++ sc = 556453;
++ } else {
++ uv_lpf = 1;
++ comb = 0x20;
++ sc = 0x0a8263;
++ }
++ } else {
++ hactive = 720;
++ hblank = 122;
++ vactive = 487;
++ luma_lpf = 1;
++ uv_lpf = 1;
++
++ src_decimation = 0x21f;
++ if (std == V4L2_STD_PAL_60) {
++ vblank = 26;
++ vblank656 = 26;
++ burst = 0x5b;
++ luma_lpf = 2;
++ comb = 0x20;
++ sc = 0x0a8263;
++ } else if (std == V4L2_STD_PAL_M) {
++ vblank = 20;
++ vblank656 = 24;
++ burst = 0x61;
++ comb = 0x20;
++
++ sc = 555452;
++ } else {
++ vblank = 26;
++ vblank656 = 26;
++ burst = 0x5b;
++ comb = 0x66;
++ sc = 556063;
++ }
++ }
++
++ /* DEBUG: Displays configured PLL frequency */
++ pll_int = cx18_av_read(cx, 0x108);
++ pll_frac = cx18_av_read4(cx, 0x10c) & 0x1ffffff;
++ pll_post = cx18_av_read(cx, 0x109);
++ CX18_DEBUG_INFO("PLL regs = int: %u, frac: %u, post: %u\n",
++ pll_int, pll_frac, pll_post);
++
++ if (pll_post) {
++ int fin, fsc;
++ int pll = 28636363L * ((((u64)pll_int) << 25) + pll_frac);
++
++ pll >>= 25;
++ pll /= pll_post;
++ CX18_DEBUG_INFO("PLL = %d.%06d MHz\n",
++ pll / 1000000, pll % 1000000);
++ CX18_DEBUG_INFO("PLL/8 = %d.%06d MHz\n",
++ pll / 8000000, (pll / 8) % 1000000);
++
++ fin = ((u64)src_decimation * pll) >> 12;
++ CX18_DEBUG_INFO("ADC Sampling freq = %d.%06d MHz\n",
++ fin / 1000000, fin % 1000000);
++
++ fsc = (((u64)sc) * pll) >> 24L;
++ CX18_DEBUG_INFO("Chroma sub-carrier freq = %d.%06d MHz\n",
++ fsc / 1000000, fsc % 1000000);
++
++ CX18_DEBUG_INFO("hblank %i, hactive %i, "
++ "vblank %i , vactive %i, vblank656 %i, src_dec %i,"
++ "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x,"
++ " sc 0x%06x\n",
++ hblank, hactive, vblank, vactive, vblank656,
++ src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
++ }
++
++ /* Sets horizontal blanking delay and active lines */
++ cx18_av_write(cx, 0x470, hblank);
++ cx18_av_write(cx, 0x471, 0xff & (((hblank >> 8) & 0x3) |
++ (hactive << 4)));
++ cx18_av_write(cx, 0x472, hactive >> 4);
++
++ /* Sets burst gate delay */
++ cx18_av_write(cx, 0x473, burst);
++
++ /* Sets vertical blanking delay and active duration */
++ cx18_av_write(cx, 0x474, vblank);
++ cx18_av_write(cx, 0x475, 0xff & (((vblank >> 8) & 0x3) |
++ (vactive << 4)));
++ cx18_av_write(cx, 0x476, vactive >> 4);
++ cx18_av_write(cx, 0x477, vblank656);
++
++ /* Sets src decimation rate */
++ cx18_av_write(cx, 0x478, 0xff & src_decimation);
++ cx18_av_write(cx, 0x479, 0xff & (src_decimation >> 8));
++
++ /* Sets Luma and UV Low pass filters */
++ cx18_av_write(cx, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
++
++ /* Enables comb filters */
++ cx18_av_write(cx, 0x47b, comb);
++
++ /* Sets SC Step*/
++ cx18_av_write(cx, 0x47c, sc);
++ cx18_av_write(cx, 0x47d, 0xff & sc >> 8);
++ cx18_av_write(cx, 0x47e, 0xff & sc >> 16);
++
++ /* Sets VBI parameters */
++ if (std & V4L2_STD_625_50) {
++ cx18_av_write(cx, 0x47f, 0x01);
++ state->vbi_line_offset = 5;
++ } else {
++ cx18_av_write(cx, 0x47f, 0x00);
++ state->vbi_line_offset = 8;
++ }
+}
-+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)
++int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg)
+{
- /* 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;
++ struct cx18_av_state *state = &cx->av_state;
++ struct v4l2_format *fmt;
++ struct v4l2_sliced_vbi_format *svbi;
+
- 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));
++ switch (cmd) {
++ case VIDIOC_G_FMT:
++ {
++ static u16 lcr2vbi[] = {
++ 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
++ 0, V4L2_SLICED_WSS_625, 0, /* 4 */
++ V4L2_SLICED_CAPTION_525, /* 6 */
++ 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */
++ 0, 0, 0, 0
++ };
++ int is_pal = !(state->std & V4L2_STD_525_60);
++ int i;
+
-+ for (i = 0; i < 0x50; i++)
-+ state->shadow[i] = s5h1420_readreg(state, i);
++ fmt = arg;
++ if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
++ return -EINVAL;
++ svbi = &fmt->fmt.sliced;
++ memset(svbi, 0, sizeof(*svbi));
++ /* we're done if raw VBI is active */
++ if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
++ break;
+
- /* create dvb_frontend */
- memcpy(&state->frontend.ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops));
- state->frontend.demodulator_priv = state;
++ if (is_pal) {
++ for (i = 7; i <= 23; i++) {
++ u8 v = cx18_av_read(cx, 0x424 + i - 7);
++
++ svbi->service_lines[0][i] = lcr2vbi[v >> 4];
++ svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
++ svbi->service_set |= svbi->service_lines[0][i] |
++ svbi->service_lines[1][i];
++ }
++ } else {
++ for (i = 10; i <= 21; i++) {
++ u8 v = cx18_av_read(cx, 0x424 + i - 10);
+
-+ /* 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;
++ svbi->service_lines[0][i] = lcr2vbi[v >> 4];
++ svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
++ svbi->service_set |= svbi->service_lines[0][i] |
++ svbi->service_lines[1][i];
++ }
++ }
++ break;
+ }
+
- return &state->frontend;
-
- error:
- kfree(state);
- return NULL;
- }
-+EXPORT_SYMBOL(s5h1420_attach);
-
- static struct dvb_frontend_ops s5h1420_ops = {
-
- .info = {
-- .name = "Samsung S5H1420 DVB-S",
-+ .name = "Samsung S5H1420/PnpNetwork PN1010 DVB-S",
- .type = FE_QPSK,
- .frequency_min = 950000,
- .frequency_max = 2150000,
-@@ -826,10 +973,6 @@ static struct dvb_frontend_ops s5h1420_ops = {
- .set_voltage = s5h1420_set_voltage,
- };
-
--module_param(debug, int, 0644);
--
--MODULE_DESCRIPTION("Samsung S5H1420 DVB-S Demodulator driver");
--MODULE_AUTHOR("Andrew de Quincey");
-+MODULE_DESCRIPTION("Samsung S5H1420/PnpNetwork PN1010 DVB-S Demodulator driver");
-+MODULE_AUTHOR("Andrew de Quincey, Patrick Boettcher");
- MODULE_LICENSE("GPL");
--
--EXPORT_SYMBOL(s5h1420_attach);
-diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h
-index 1555870..4c913f1 100644
---- a/drivers/media/dvb/frontends/s5h1420.h
-+++ b/drivers/media/dvb/frontends/s5h1420.h
-@@ -1,25 +1,26 @@
- /*
-- Driver for S5H1420 QPSK Demodulators
--
-- Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
--*/
--
-+ * Driver for
-+ * Samsung S5H1420 and
-+ * PnpNetwork PN1010 QPSK Demodulator
-+ *
-+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
-+ * Copyright (C) 2005-8 Patrick Boettcher <pb at linuxtv.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ *
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
- #ifndef S5H1420_H
- #define S5H1420_H
-
-@@ -31,17 +32,26 @@ struct s5h1420_config
- u8 demod_address;
-
- /* does the inversion require inversion? */
-- u8 invert:1;
-+ u8 invert : 1;
++ case VIDIOC_S_FMT:
++ {
++ int is_pal = !(state->std & V4L2_STD_525_60);
++ int vbi_offset = is_pal ? 1 : 0;
++ int i, x;
++ u8 lcr[24];
+
-+ 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;
-+}
++ fmt = arg;
++ if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
++ return -EINVAL;
++ svbi = &fmt->fmt.sliced;
++ if (svbi->service_set == 0) {
++ /* raw VBI */
++ memset(svbi, 0, sizeof(*svbi));
+
-+static inline struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe)
- {
-- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
- return NULL;
- }
- #endif // CONFIG_DVB_S5H1420
-diff --git a/drivers/media/dvb/frontends/s5h1420_priv.h b/drivers/media/dvb/frontends/s5h1420_priv.h
-new file mode 100644
-index 0000000..d9c58d2
---- /dev/null
-+++ b/drivers/media/dvb/frontends/s5h1420_priv.h
-@@ -0,0 +1,102 @@
-+/*
-+ * Driver for
-+ * Samsung S5H1420 and
-+ * PnpNetwork PN1010 QPSK Demodulator
-+ *
-+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
-+ * Copyright (C) 2005 Patrick Boettcher <pb at linuxtv.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the Free
-+ * Software Foundation; either version 2 of the License, or (at your option)
-+ * any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the
-+ *
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc., 675 Mass
-+ * Ave, Cambridge, MA 02139, USA.
-+ */
-+#ifndef S5H1420_PRIV
-+#define S5H1420_PRIV
++ /* Setup VBI */
++ cx18_av_vbi_setup(cx);
+
-+#include <asm/types.h>
++ /* VBI Offset */
++ cx18_av_write(cx, 0x47f, vbi_offset);
++ cx18_av_write(cx, 0x404, 0x2e);
++ break;
++ }
+
-+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,
++ for (x = 0; x <= 23; x++)
++ lcr[x] = 0x00;
+
-+ 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,
-+};
++ /* Setup VBI */
++ cx18_av_vbi_setup(cx);
+
++ /* Sliced VBI */
++ cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */
++ cx18_av_write(cx, 0x406, 0x13);
++ cx18_av_write(cx, 0x47f, vbi_offset);
+
-+#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 (is_pal) {
++ for (i = 0; i <= 6; i++)
++ svbi->service_lines[0][i] =
++ svbi->service_lines[1][i] = 0;
++ } else {
++ for (i = 0; i <= 9; i++)
++ svbi->service_lines[0][i] =
++ svbi->service_lines[1][i] = 0;
++
++ for (i = 22; i <= 23; i++)
++ svbi->service_lines[0][i] =
++ svbi->service_lines[1][i] = 0;
++ }
+
-+ if (state->config->op0_off)
-+ reg0x0c &= ~0x10;
++ for (i = 7; i <= 23; i++) {
++ for (x = 0; x <= 1; x++) {
++ switch (svbi->service_lines[1-x][i]) {
++ case V4L2_SLICED_TELETEXT_B:
++ lcr[i] |= 1 << (4 * x);
++ break;
++ case V4L2_SLICED_WSS_625:
++ lcr[i] |= 4 << (4 * x);
++ break;
++ case V4L2_SLICED_CAPTION_525:
++ lcr[i] |= 6 << (4 * x);
++ break;
++ case V4L2_SLICED_VPS:
++ lcr[i] |= 9 << (4 * x);
++ break;
++ }
++ }
++ }
+
-+ stv0299_writeregI(state, 0x08, reg0x08);
-+ return stv0299_writeregI(state, 0x0c, reg0x0c);
- }
-
- static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long cmd)
-@@ -408,7 +414,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
-
- cmd = cmd << 1;
- if (debug_legacy_dish_switch)
-- printk ("%s switch command: 0x%04lx\n",__FUNCTION__, cmd);
-+ printk ("%s switch command: 0x%04lx\n",__func__, cmd);
-
- do_gettimeofday (&nexttime);
- if (debug_legacy_dish_switch)
-@@ -433,7 +439,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
- }
- if (debug_legacy_dish_switch) {
- printk ("%s(%d): switch delay (should be 32k followed by all 8k\n",
-- __FUNCTION__, fe->dvb->num);
-+ __func__, fe->dvb->num);
- for (i = 1; i < 10; i++)
- printk ("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
- }
-@@ -445,11 +451,20 @@ static int stv0299_init (struct dvb_frontend* fe)
- {
- struct stv0299_state* state = fe->demodulator_priv;
- int i;
-+ u8 reg;
-+ u8 val;
-
- dprintk("stv0299: init chip\n");
-
-- for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2)
-- stv0299_writeregI(state, state->config->inittab[i], state->config->inittab[i+1]);
-+ for (i = 0; ; i += 2) {
-+ reg = state->config->inittab[i];
-+ val = state->config->inittab[i+1];
-+ if (reg == 0xff && val == 0xff)
-+ break;
-+ if (reg == 0x0c && state->config->op0_off)
-+ val &= ~0x10;
-+ stv0299_writeregI(state, reg, val);
-+ }
-
- return 0;
- }
-@@ -461,7 +476,7 @@ static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status)
- u8 signal = 0xff - stv0299_readreg (state, 0x18);
- u8 sync = stv0299_readreg (state, 0x1b);
-
-- dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __FUNCTION__, sync);
-+ dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync);
- *status = 0;
-
- if (signal > 10)
-@@ -499,7 +514,7 @@ static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength)
- s32 signal = 0xffff - ((stv0299_readreg (state, 0x18) << 8)
- | stv0299_readreg (state, 0x19));
-
-- dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __FUNCTION__,
-+ dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __func__,
- stv0299_readreg (state, 0x18),
- stv0299_readreg (state, 0x19), (int) signal);
-
-@@ -536,7 +551,7 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
- struct stv0299_state* state = fe->demodulator_priv;
- int invval = 0;
-
-- dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__);
-+ dprintk ("%s : FE_SET_FRONTEND\n", __func__);
-
- // set the inversion
- if (p->inversion == INVERSION_OFF) invval = 0;
-diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h
-index 33df949..3282f43 100644
---- a/drivers/media/dvb/frontends/stv0299.h
-+++ b/drivers/media/dvb/frontends/stv0299.h
-@@ -48,10 +48,10 @@
- #include <linux/dvb/frontend.h>
- #include "dvb_frontend.h"
-
--#define STV0229_LOCKOUTPUT_0 0
--#define STV0229_LOCKOUTPUT_1 1
--#define STV0229_LOCKOUTPUT_CF 2
--#define STV0229_LOCKOUTPUT_LK 3
-+#define STV0299_LOCKOUTPUT_0 0
-+#define STV0299_LOCKOUTPUT_1 1
-+#define STV0299_LOCKOUTPUT_CF 2
-+#define STV0299_LOCKOUTPUT_LK 3
-
- #define STV0299_VOLT13_OP0 0
- #define STV0299_VOLT13_OP1 1
-@@ -82,6 +82,9 @@ struct stv0299_config
- /* Is 13v controlled by OP0 or OP1? */
- u8 volt13_op0_op1:1;
-
-+ /* Turn-off OP0? */
-+ u8 op0_off:1;
++ if (is_pal) {
++ for (x = 1, i = 0x424; i <= 0x434; i++, x++)
++ cx18_av_write(cx, i, lcr[6 + x]);
++ } else {
++ for (x = 1, i = 0x424; i <= 0x430; i++, x++)
++ cx18_av_write(cx, i, lcr[9 + x]);
++ for (i = 0x431; i <= 0x434; i++)
++ cx18_av_write(cx, i, 0);
++ }
+
- /* 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
++ cx18_av_write(cx, 0x43c, 0x16);
++ cx18_av_write(cx, 0x474, is_pal ? 0x2a : 0x22);
++ break;
++ }
++
++ case VIDIOC_INT_DECODE_VBI_LINE:
++ {
++ struct v4l2_decode_vbi_line *vbi = arg;
++ u8 *p = vbi->p;
++ int id1, id2, l, err = 0;
++
++ if (p[0] || p[1] != 0xff || p[2] != 0xff ||
++ (p[3] != 0x55 && p[3] != 0x91)) {
++ vbi->line = vbi->type = 0;
++ break;
++ }
++
++ p += 4;
++ id1 = p[-1];
++ id2 = p[0] & 0xf;
++ l = p[2] & 0x3f;
++ l += state->vbi_line_offset;
++ p += 4;
++
++ switch (id2) {
++ case 1:
++ id2 = V4L2_SLICED_TELETEXT_B;
++ break;
++ case 4:
++ id2 = V4L2_SLICED_WSS_625;
++ break;
++ case 6:
++ id2 = V4L2_SLICED_CAPTION_525;
++ err = !odd_parity(p[0]) || !odd_parity(p[1]);
++ break;
++ case 9:
++ id2 = V4L2_SLICED_VPS;
++ if (decode_vps(p, p) != 0)
++ err = 1;
++ break;
++ default:
++ id2 = 0;
++ err = 1;
++ break;
++ }
++
++ vbi->type = err ? 0 : id2;
++ vbi->line = err ? 0 : l;
++ vbi->is_second_field = err ? 0 : (id1 == 0x55);
++ vbi->p = p;
++ break;
++ }
++ }
++
++ return 0;
++}
+diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c
new file mode 100644
-index 0000000..090fb7d
+index 0000000..f5e3ba1
--- /dev/null
-+++ b/drivers/media/dvb/frontends/tda10048.c
-@@ -0,0 +1,841 @@
++++ b/drivers/media/video/cx18/cx18-cards.c
+@@ -0,0 +1,277 @@
+/*
-+ NXP TDA10048HN DVB OFDM demodulator driver
-+
-+ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
++ * cx18 functions to query card hardware
++ *
++ * Derived from ivtv-cards.c
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the 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 "cx18-driver.h"
++#include "cx18-cards.h"
++#include "cx18-i2c.h"
++#include <media/cs5345.h>
++
++/********************** card configuration *******************************/
++
++/* usual i2c tuner addresses to probe */
++static struct cx18_card_tuner_i2c cx18_i2c_std = {
++ .radio = { I2C_CLIENT_END },
++ .demod = { 0x43, I2C_CLIENT_END },
++ .tv = { 0x61, 0x60, I2C_CLIENT_END },
++};
++
++/* Please add new PCI IDs to: http://pci-ids.ucw.cz/iii
++ This keeps the PCI ID database up to date. Note that the entries
++ must be added under vendor 0x4444 (Conexant) as subsystem IDs.
++ New vendor IDs should still be added to the vendor ID list. */
++
++/* Hauppauge HVR-1600 cards */
++
++/* Note: for Hauppauge cards the tveeprom information is used instead
++ of PCI IDs */
++static const struct cx18_card cx18_card_hvr1600_esmt = {
++ .type = CX18_CARD_HVR_1600_ESMT,
++ .name = "Hauppauge HVR-1600",
++ .comment = "DVB & VBI are not yet supported\n",
++ .v4l2_capabilities = CX18_CAP_ENCODER,
++ .hw_audio_ctrl = CX18_HW_CX23418,
++ .hw_muxer = CX18_HW_CS5345,
++ .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | CX18_HW_CS5345,
++ .video_inputs = {
++ { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 },
++ { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 },
++ { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 },
++ { CX18_CARD_INPUT_SVIDEO2, 2, CX23418_SVIDEO2 },
++ { CX18_CARD_INPUT_COMPOSITE2, 2, CX23418_COMPOSITE4 },
++ },
++ .audio_inputs = {
++ { CX18_CARD_INPUT_AUD_TUNER,
++ CX23418_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
++ { CX18_CARD_INPUT_LINE_IN1,
++ CX23418_AUDIO_SERIAL, CS5345_IN_2 },
++ { CX18_CARD_INPUT_LINE_IN2,
++ CX23418_AUDIO_SERIAL, CS5345_IN_2 },
++ },
++ .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
++ CX23418_AUDIO_SERIAL, 0 },
++ .ddr = {
++ /* ESMT M13S128324A-5B memory */
++ .chip_config = 0x003,
++ .refresh = 0x30c,
++ .timing1 = 0x44220e82,
++ .timing2 = 0x08,
++ .tune_lane = 0,
++ .initial_emrs = 0,
++ },
++ .gpio_init.initial_value = 0x3001,
++ .gpio_init.direction = 0x3001,
++ .i2c = &cx18_i2c_std,
++};
++
++static const struct cx18_card cx18_card_hvr1600_samsung = {
++ .type = CX18_CARD_HVR_1600_SAMSUNG,
++ .name = "Hauppauge HVR-1600 (Preproduction)",
++ .comment = "DVB & VBI are not yet supported\n",
++ .v4l2_capabilities = CX18_CAP_ENCODER,
++ .hw_audio_ctrl = CX18_HW_CX23418,
++ .hw_muxer = CX18_HW_CS5345,
++ .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | CX18_HW_CS5345,
++ .video_inputs = {
++ { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 },
++ { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 },
++ { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 },
++ { CX18_CARD_INPUT_SVIDEO2, 2, CX23418_SVIDEO2 },
++ { CX18_CARD_INPUT_COMPOSITE2, 2, CX23418_COMPOSITE4 },
++ },
++ .audio_inputs = {
++ { CX18_CARD_INPUT_AUD_TUNER,
++ CX23418_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
++ { CX18_CARD_INPUT_LINE_IN1,
++ CX23418_AUDIO_SERIAL, CS5345_IN_2 },
++ { CX18_CARD_INPUT_LINE_IN2,
++ CX23418_AUDIO_SERIAL, CS5345_IN_2 },
++ },
++ .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
++ CX23418_AUDIO_SERIAL, 0 },
++ .ddr = {
++ /* Samsung K4D263238G-VC33 memory */
++ .chip_config = 0x003,
++ .refresh = 0x30c,
++ .timing1 = 0x23230b73,
++ .timing2 = 0x08,
++ .tune_lane = 0,
++ .initial_emrs = 2,
++ },
++ .gpio_init.initial_value = 0x3001,
++ .gpio_init.direction = 0x3001,
++ .i2c = &cx18_i2c_std,
++};
++
++/* ------------------------------------------------------------------------- */
++
++/* Compro VideoMate H900: not working at the moment! */
++
++static const struct cx18_card_pci_info cx18_pci_h900[] = {
++ { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_COMPRO, 0xe100 },
++ { 0, 0, 0 }
++};
++
++static const struct cx18_card cx18_card_h900 = {
++ .type = CX18_CARD_COMPRO_H900,
++ .name = "Compro VideoMate H900",
++ .comment = "Not yet supported!\n",
++ .v4l2_capabilities = 0,
++ .hw_audio_ctrl = CX18_HW_CX23418,
++ .hw_all = CX18_HW_TUNER,
++ .video_inputs = {
++ { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 },
++ { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 },
++ { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 },
++ },
++ .audio_inputs = {
++ { CX18_CARD_INPUT_AUD_TUNER,
++ CX23418_AUDIO8, 0 },
++ { CX18_CARD_INPUT_LINE_IN1,
++ CX23418_AUDIO_SERIAL, 0 },
++ },
++ .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
++ CX23418_AUDIO_SERIAL, 0 },
++ .tuners = {
++ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
++ },
++ .ddr = {
++ /* EtronTech EM6A9160TS-5G memory */
++ .chip_config = 0x50003,
++ .refresh = 0x753,
++ .timing1 = 0x24330e84,
++ .timing2 = 0x1f,
++ .tune_lane = 0,
++ .initial_emrs = 0,
++ },
++ .pci_list = cx18_pci_h900,
++ .i2c = &cx18_i2c_std,
++};
+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
++/* ------------------------------------------------------------------------- */
+
-+ You 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.
++/* Yuan MPC718: not working at the moment! */
+
-+*/
++static const struct cx18_card_pci_info cx18_pci_mpc718[] = {
++ { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_YUAN, 0x0718 },
++ { 0, 0, 0 }
++};
++
++static const struct cx18_card cx18_card_mpc718 = {
++ .type = CX18_CARD_YUAN_MPC718,
++ .name = "Yuan MPC718",
++ .comment = "Not yet supported!\n",
++ .v4l2_capabilities = 0,
++ .hw_audio_ctrl = CX18_HW_CX23418,
++ .hw_all = CX18_HW_TUNER,
++ .video_inputs = {
++ { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 },
++ { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 },
++ { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 },
++ },
++ .audio_inputs = {
++ { CX18_CARD_INPUT_AUD_TUNER,
++ CX23418_AUDIO8, 0 },
++ { CX18_CARD_INPUT_LINE_IN1,
++ CX23418_AUDIO_SERIAL, 0 },
++ },
++ .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
++ CX23418_AUDIO_SERIAL, 0 },
++ .tuners = {
++ /* XC3028 tuner */
++ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
++ },
++ /* tuner reset */
++ .gpio_init = { .direction = 0x1000, .initial_value = 0x1000 },
++ .ddr = {
++ /* Probably Samsung K4D263238G-VC33 memory */
++ .chip_config = 0x003,
++ .refresh = 0x30c,
++ .timing1 = 0x23230b73,
++ .timing2 = 0x08,
++ .tune_lane = 0,
++ .initial_emrs = 2,
++ },
++ .pci_list = cx18_pci_mpc718,
++ .i2c = &cx18_i2c_std,
++};
+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/slab.h>
-+#include <linux/delay.h>
-+#include "dvb_frontend.h"
-+#include "dvb_math.h"
-+#include "tda10048.h"
++static const struct cx18_card *cx18_card_list[] = {
++ &cx18_card_hvr1600_esmt,
++ &cx18_card_hvr1600_samsung,
++ &cx18_card_h900,
++ &cx18_card_mpc718,
++};
+
-+#define TDA10048_DEFAULT_FIRMWARE "dvb-fe-tda10048-1.0.fw"
-+#define TDA10048_DEFAULT_FIRMWARE_SIZE 24878
++const struct cx18_card *cx18_get_card(u16 index)
++{
++ if (index >= ARRAY_SIZE(cx18_card_list))
++ return NULL;
++ return cx18_card_list[index];
++}
+
-+/* 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
++int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input)
++{
++ const struct cx18_card_video_input *card_input =
++ cx->card->video_inputs + index;
++ static const char * const input_strs[] = {
++ "Tuner 1",
++ "S-Video 1",
++ "S-Video 2",
++ "Composite 1",
++ "Composite 2",
++ "Composite 3"
++ };
+
-+static unsigned int debug;
++ memset(input, 0, sizeof(*input));
++ if (index >= cx->nof_inputs)
++ return -EINVAL;
++ input->index = index;
++ strlcpy(input->name, input_strs[card_input->video_type - 1],
++ sizeof(input->name));
++ input->type = (card_input->video_type == CX18_CARD_INPUT_VID_TUNER ?
++ V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA);
++ input->audioset = (1 << cx->nof_audio_inputs) - 1;
++ input->std = (input->type == V4L2_INPUT_TYPE_TUNER) ?
++ cx->tuner_std : V4L2_STD_ALL;
++ return 0;
++}
+
-+#define dprintk(level, fmt, arg...)\
-+ do { if (debug >= level)\
-+ printk(KERN_DEBUG "tda10048: " fmt, ## arg);\
-+ } while (0)
++int cx18_get_audio_input(struct cx18 *cx, u16 index, struct v4l2_audio *audio)
++{
++ const struct cx18_card_audio_input *aud_input =
++ cx->card->audio_inputs + index;
++ static const char * const input_strs[] = {
++ "Tuner 1",
++ "Line In 1",
++ "Line In 2"
++ };
+
-+struct tda10048_state {
++ memset(audio, 0, sizeof(*audio));
++ if (index >= cx->nof_audio_inputs)
++ return -EINVAL;
++ strlcpy(audio->name, input_strs[aud_input->audio_type - 1],
++ sizeof(audio->name));
++ audio->index = index;
++ audio->capability = V4L2_AUDCAP_STEREO;
++ return 0;
++}
+diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h
+new file mode 100644
+index 0000000..bca249b
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-cards.h
+@@ -0,0 +1,170 @@
++/*
++ * cx18 functions to query card hardware
++ *
++ * Derived from ivtv-cards.c
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
-+ struct i2c_adapter *i2c;
++/* hardware flags */
++#define CX18_HW_TUNER (1 << 0)
++#define CX18_HW_TVEEPROM (1 << 1)
++#define CX18_HW_CS5345 (1 << 2)
++#define CX18_HW_GPIO (1 << 3)
++#define CX18_HW_CX23418 (1 << 4)
++#define CX18_HW_DVB (1 << 5)
++
++/* video inputs */
++#define CX18_CARD_INPUT_VID_TUNER 1
++#define CX18_CARD_INPUT_SVIDEO1 2
++#define CX18_CARD_INPUT_SVIDEO2 3
++#define CX18_CARD_INPUT_COMPOSITE1 4
++#define CX18_CARD_INPUT_COMPOSITE2 5
++#define CX18_CARD_INPUT_COMPOSITE3 6
++
++enum cx34180_video_input {
++ /* Composite video inputs In1-In8 */
++ CX23418_COMPOSITE1 = 1,
++ CX23418_COMPOSITE2,
++ CX23418_COMPOSITE3,
++ CX23418_COMPOSITE4,
++ CX23418_COMPOSITE5,
++ CX23418_COMPOSITE6,
++ CX23418_COMPOSITE7,
++ CX23418_COMPOSITE8,
++
++ /* S-Video inputs consist of one luma input (In1-In4) ORed with one
++ chroma input (In5-In8) */
++ CX23418_SVIDEO_LUMA1 = 0x10,
++ CX23418_SVIDEO_LUMA2 = 0x20,
++ CX23418_SVIDEO_LUMA3 = 0x30,
++ CX23418_SVIDEO_LUMA4 = 0x40,
++ CX23418_SVIDEO_CHROMA4 = 0x400,
++ CX23418_SVIDEO_CHROMA5 = 0x500,
++ CX23418_SVIDEO_CHROMA6 = 0x600,
++ CX23418_SVIDEO_CHROMA7 = 0x700,
++ CX23418_SVIDEO_CHROMA8 = 0x800,
++
++ /* S-Video aliases for common luma/chroma combinations */
++ CX23418_SVIDEO1 = 0x510,
++ CX23418_SVIDEO2 = 0x620,
++ CX23418_SVIDEO3 = 0x730,
++ CX23418_SVIDEO4 = 0x840,
++};
++
++/* audio inputs */
++#define CX18_CARD_INPUT_AUD_TUNER 1
++#define CX18_CARD_INPUT_LINE_IN1 2
++#define CX18_CARD_INPUT_LINE_IN2 3
++
++#define CX18_CARD_MAX_VIDEO_INPUTS 6
++#define CX18_CARD_MAX_AUDIO_INPUTS 3
++#define CX18_CARD_MAX_TUNERS 2
++
++enum cx23418_audio_input {
++ /* Audio inputs: serial or In4-In8 */
++ CX23418_AUDIO_SERIAL,
++ CX23418_AUDIO4 = 4,
++ CX23418_AUDIO5,
++ CX23418_AUDIO6,
++ CX23418_AUDIO7,
++ CX23418_AUDIO8,
++};
++
++/* V4L2 capability aliases */
++#define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \
++ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE)
++/* | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE) not yet */
++
++struct cx18_card_video_input {
++ u8 video_type; /* video input type */
++ u8 audio_index; /* index in cx18_card_audio_input array */
++ u16 video_input; /* hardware video input */
++};
++
++struct cx18_card_audio_input {
++ u8 audio_type; /* audio input type */
++ u32 audio_input; /* hardware audio input */
++ u16 muxer_input; /* hardware muxer input for boards with a
++ multiplexer chip */
++};
++
++struct cx18_card_pci_info {
++ u16 device;
++ u16 subsystem_vendor;
++ u16 subsystem_device;
++};
++
++/* GPIO definitions */
++
++/* The mask is the set of bits used by the operation */
++
++struct cx18_gpio_init { /* set initial GPIO DIR and OUT values */
++ u16 direction; /* DIR setting. Leave to 0 if no init is needed */
++ u16 initial_value;
++};
++
++struct cx18_card_tuner {
++ v4l2_std_id std; /* standard for which the tuner is suitable */
++ int tuner; /* tuner ID (from tuner.h) */
++};
++
++struct cx18_card_tuner_i2c {
++ unsigned short radio[2];/* radio tuner i2c address to probe */
++ unsigned short demod[2];/* demodulator i2c address to probe */
++ unsigned short tv[4]; /* tv tuner i2c addresses to probe */
++};
++
++struct cx18_ddr { /* DDR config data */
++ u32 chip_config;
++ u32 refresh;
++ u32 timing1;
++ u32 timing2;
++ u32 tune_lane;
++ u32 initial_emrs;
++};
+
-+ /* configuration settings */
-+ const struct tda10048_config *config;
-+ struct dvb_frontend frontend;
++/* for card information/parameters */
++struct cx18_card {
++ int type;
++ char *name;
++ char *comment;
++ u32 v4l2_capabilities;
++ u32 hw_audio_ctrl; /* hardware used for the V4L2 controls (only
++ 1 dev allowed) */
++ u32 hw_muxer; /* hardware used to multiplex audio input */
++ u32 hw_all; /* all hardware used by the board */
++ struct cx18_card_video_input video_inputs[CX18_CARD_MAX_VIDEO_INPUTS];
++ struct cx18_card_audio_input audio_inputs[CX18_CARD_MAX_AUDIO_INPUTS];
++ struct cx18_card_audio_input radio_input;
++
++ /* GPIO card-specific settings */
++ struct cx18_gpio_init gpio_init;
++
++ struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS];
++ struct cx18_card_tuner_i2c *i2c;
++
++ struct cx18_ddr ddr;
++
++ /* list of device and subsystem vendor/devices that
++ correspond to this card type. */
++ const struct cx18_card_pci_info *pci_list;
++};
++
++int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input);
++int cx18_get_audio_input(struct cx18 *cx, u16 index, struct v4l2_audio *input);
++const struct cx18_card *cx18_get_card(u16 index);
+diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c
+new file mode 100644
+index 0000000..2bdac5e
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-controls.c
+@@ -0,0 +1,306 @@
++/*
++ * cx18 ioctl control functions
++ *
++ * Derived from ivtv-controls.c
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
-+ int fwloaded;
++#include "cx18-driver.h"
++#include "cx18-av-core.h"
++#include "cx18-cards.h"
++#include "cx18-ioctl.h"
++#include "cx18-audio.h"
++#include "cx18-i2c.h"
++#include "cx18-mailbox.h"
++#include "cx18-controls.h"
++
++static const u32 user_ctrls[] = {
++ V4L2_CID_USER_CLASS,
++ V4L2_CID_BRIGHTNESS,
++ V4L2_CID_CONTRAST,
++ V4L2_CID_SATURATION,
++ V4L2_CID_HUE,
++ V4L2_CID_AUDIO_VOLUME,
++ V4L2_CID_AUDIO_BALANCE,
++ V4L2_CID_AUDIO_BASS,
++ V4L2_CID_AUDIO_TREBLE,
++ V4L2_CID_AUDIO_MUTE,
++ V4L2_CID_AUDIO_LOUDNESS,
++ 0
+};
+
-+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 const u32 *ctrl_classes[] = {
++ user_ctrls,
++ cx2341x_mpeg_ctrls,
++ NULL
+};
+
-+static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
++static int cx18_queryctrl(struct cx18 *cx, struct v4l2_queryctrl *qctrl)
+{
-+ int ret;
-+ u8 buf [] = { reg, data };
-+ struct i2c_msg msg = {
-+ .addr = state->config->demod_address,
-+ .flags = 0, .buf = buf, .len = 2 };
++ const char *name;
+
-+ dprintk(2, "%s(reg = 0x%02x, data = 0x%02x)\n", __func__, reg, data);
++ CX18_DEBUG_IOCTL("VIDIOC_QUERYCTRL(%08x)\n", qctrl->id);
+
-+ ret = i2c_transfer(state->i2c, &msg, 1);
++ qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
++ if (qctrl->id == 0)
++ return -EINVAL;
+
-+ if (ret != 1)
-+ printk("%s: writereg error (ret == %i)\n", __func__, ret);
++ switch (qctrl->id) {
++ /* Standard V4L2 controls */
++ case V4L2_CID_BRIGHTNESS:
++ case V4L2_CID_HUE:
++ case V4L2_CID_SATURATION:
++ case V4L2_CID_CONTRAST:
++ if (cx18_av_cmd(cx, VIDIOC_QUERYCTRL, qctrl))
++ qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
++ return 0;
+
-+ return (ret != 1) ? -1 : 0;
++ case V4L2_CID_AUDIO_VOLUME:
++ case V4L2_CID_AUDIO_MUTE:
++ case V4L2_CID_AUDIO_BALANCE:
++ case V4L2_CID_AUDIO_BASS:
++ case V4L2_CID_AUDIO_TREBLE:
++ case V4L2_CID_AUDIO_LOUDNESS:
++ if (cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_QUERYCTRL, qctrl))
++ qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
++ return 0;
++
++ default:
++ if (cx2341x_ctrl_query(&cx->params, qctrl))
++ qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
++ return 0;
++ }
++ strncpy(qctrl->name, name, sizeof(qctrl->name) - 1);
++ qctrl->name[sizeof(qctrl->name) - 1] = 0;
++ return 0;
+}
+
-+static u8 tda10048_readreg(struct tda10048_state *state, u8 reg)
++static int cx18_querymenu(struct cx18 *cx, struct v4l2_querymenu *qmenu)
+{
-+ 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 } };
++ struct v4l2_queryctrl qctrl;
+
-+ dprintk(2, "%s(reg = 0x%02x)\n", __func__, reg);
++ qctrl.id = qmenu->id;
++ cx18_queryctrl(cx, &qctrl);
++ return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(qmenu->id));
++}
+
-+ ret = i2c_transfer(state->i2c, msg, 2);
++static int cx18_s_ctrl(struct cx18 *cx, struct v4l2_control *vctrl)
++{
++ s32 v = vctrl->value;
+
-+ if (ret != 2)
-+ printk(KERN_ERR "%s: readreg error (ret == %i)\n",
-+ __func__, ret);
++ CX18_DEBUG_IOCTL("VIDIOC_S_CTRL(%08x, %x)\n", vctrl->id, v);
+
-+ return b1[0];
++ switch (vctrl->id) {
++ /* Standard V4L2 controls */
++ case V4L2_CID_BRIGHTNESS:
++ case V4L2_CID_HUE:
++ case V4L2_CID_SATURATION:
++ case V4L2_CID_CONTRAST:
++ return cx18_av_cmd(cx, VIDIOC_S_CTRL, vctrl);
++
++ case V4L2_CID_AUDIO_VOLUME:
++ case V4L2_CID_AUDIO_MUTE:
++ case V4L2_CID_AUDIO_BALANCE:
++ case V4L2_CID_AUDIO_BASS:
++ case V4L2_CID_AUDIO_TREBLE:
++ case V4L2_CID_AUDIO_LOUDNESS:
++ return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_S_CTRL, vctrl);
++
++ default:
++ CX18_DEBUG_IOCTL("invalid control %x\n", vctrl->id);
++ return -EINVAL;
++ }
++ return 0;
+}
+
-+static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg,
-+ u8 *data, u16 len)
++static int cx18_g_ctrl(struct cx18 *cx, struct v4l2_control *vctrl)
+{
-+ int ret = -EREMOTEIO;
-+ struct i2c_msg msg;
-+ u8 *buf;
++ CX18_DEBUG_IOCTL("VIDIOC_G_CTRL(%08x)\n", vctrl->id);
+
-+ dprintk(2, "%s(%d, ?, len = %d)\n", __func__, reg, len);
++ switch (vctrl->id) {
++ /* Standard V4L2 controls */
++ case V4L2_CID_BRIGHTNESS:
++ case V4L2_CID_HUE:
++ case V4L2_CID_SATURATION:
++ case V4L2_CID_CONTRAST:
++ return cx18_av_cmd(cx, VIDIOC_G_CTRL, vctrl);
+
-+ buf = kmalloc(len + 1, GFP_KERNEL);
-+ if (buf == NULL) {
-+ ret = -ENOMEM;
-+ goto error;
++ case V4L2_CID_AUDIO_VOLUME:
++ case V4L2_CID_AUDIO_MUTE:
++ case V4L2_CID_AUDIO_BALANCE:
++ case V4L2_CID_AUDIO_BASS:
++ case V4L2_CID_AUDIO_TREBLE:
++ case V4L2_CID_AUDIO_LOUDNESS:
++ return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_G_CTRL, vctrl);
++ default:
++ CX18_DEBUG_IOCTL("invalid control %x\n", vctrl->id);
++ return -EINVAL;
+ }
++ return 0;
++}
+
-+ *buf = reg;
-+ memcpy(buf + 1, data, len);
-+
-+ msg.addr = state->config->demod_address;
-+ msg.flags = 0;
-+ msg.buf = buf;
-+ msg.len = len + 1;
++static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt)
++{
++ if (!(cx->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE))
++ return -EINVAL;
++ if (atomic_read(&cx->capturing) > 0)
++ return -EBUSY;
+
-+ dprintk(2, "%s(): write len = %d\n",
-+ __func__, msg.len);
++ /* First try to allocate sliced VBI buffers if needed. */
++ if (fmt && cx->vbi.sliced_mpeg_data[0] == NULL) {
++ int i;
+
-+ ret = i2c_transfer(state->i2c, &msg, 1);
-+ if (ret != 1) {
-+ printk(KERN_ERR "%s(): writereg error err %i\n",
-+ __func__, ret);
-+ ret = -EREMOTEIO;
++ for (i = 0; i < CX18_VBI_FRAMES; i++) {
++ /* Yuck, hardcoded. Needs to be a define */
++ cx->vbi.sliced_mpeg_data[i] = kmalloc(2049, GFP_KERNEL);
++ if (cx->vbi.sliced_mpeg_data[i] == NULL) {
++ while (--i >= 0) {
++ kfree(cx->vbi.sliced_mpeg_data[i]);
++ cx->vbi.sliced_mpeg_data[i] = NULL;
++ }
++ return -ENOMEM;
++ }
++ }
+ }
+
-+error:
-+ kfree(buf);
++ cx->vbi.insert_mpeg = fmt;
+
-+ return ret;
++ if (cx->vbi.insert_mpeg == 0)
++ return 0;
++ /* Need sliced data for mpeg insertion */
++ if (cx18_get_service_set(cx->vbi.sliced_in) == 0) {
++ if (cx->is_60hz)
++ cx->vbi.sliced_in->service_set = V4L2_SLICED_CAPTION_525;
++ else
++ cx->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625;
++ cx18_expand_service_set(cx->vbi.sliced_in, cx->is_50hz);
++ }
++ return 0;
+}
+
-+static int tda10048_firmware_upload(struct dvb_frontend *fe)
++int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg)
+{
-+ struct tda10048_state *state = fe->demodulator_priv;
-+ const struct firmware *fw;
-+ int ret;
-+ int pos = 0;
-+ int cnt;
-+ u8 wlen = state->config->fwbulkwritelen;
++ struct v4l2_control ctrl;
+
-+ if ((wlen != TDA10048_BULKWRITE_200) && (wlen != TDA10048_BULKWRITE_50))
-+ wlen = TDA10048_BULKWRITE_200;
++ switch (cmd) {
++ case VIDIOC_QUERYMENU:
++ CX18_DEBUG_IOCTL("VIDIOC_QUERYMENU\n");
++ return cx18_querymenu(cx, arg);
+
-+ /* request the firmware, this will block and timeout */
-+ printk(KERN_INFO "%s: waiting for firmware upload (%s)...\n",
-+ __func__,
-+ TDA10048_DEFAULT_FIRMWARE);
++ case VIDIOC_QUERYCTRL:
++ return cx18_queryctrl(cx, arg);
+
-+ 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;
-+ }
++ case VIDIOC_S_CTRL:
++ return cx18_s_ctrl(cx, arg);
+
-+ 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__);
++ case VIDIOC_G_CTRL:
++ return cx18_g_ctrl(cx, arg);
+
-+ /* 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);
++ case VIDIOC_S_EXT_CTRLS:
++ {
++ struct v4l2_ext_controls *c = arg;
+
-+ /* Put the demod into host download mode */
-+ tda10048_writereg(state, TDA10048_CONF_C4_1,
-+ tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xf9);
++ if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
++ int i;
++ int err = 0;
+
-+ /* Boot the DSP */
-+ tda10048_writereg(state, TDA10048_CONF_C4_1,
-+ tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x08);
++ for (i = 0; i < c->count; i++) {
++ ctrl.id = c->controls[i].id;
++ ctrl.value = c->controls[i].value;
++ err = cx18_s_ctrl(cx, &ctrl);
++ c->controls[i].value = ctrl.value;
++ if (err) {
++ c->error_idx = i;
++ break;
++ }
++ }
++ return err;
++ }
++ CX18_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n");
++ if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
++ struct cx2341x_mpeg_params p = cx->params;
++ int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->capturing), arg, cmd);
+
-+ /* Prepare for download */
-+ tda10048_writereg(state, TDA10048_DSP_CODE_CPT, 0);
++ if (err)
++ return err;
+
-+ /* Download the firmware payload */
-+ while (pos < fw->size) {
++ if (p.video_encoding != cx->params.video_encoding) {
++ int is_mpeg1 = p.video_encoding ==
++ V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
++ struct v4l2_format fmt;
++
++ /* fix videodecoder resolution */
++ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ fmt.fmt.pix.width = cx->params.width / (is_mpeg1 ? 2 : 1);
++ fmt.fmt.pix.height = cx->params.height;
++ cx18_av_cmd(cx, VIDIOC_S_FMT, &fmt);
++ }
++ err = cx2341x_update(cx, cx18_api_func, &cx->params, &p);
++ if (!err && cx->params.stream_vbi_fmt != p.stream_vbi_fmt)
++ err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt);
++ cx->params = p;
++ cx->dualwatch_stereo_mode = p.audio_properties & 0x0300;
++ cx18_audio_set_audio_clock_freq(cx, p.audio_properties & 0x03);
++ return err;
++ }
++ return -EINVAL;
++ }
+
-+ if ((fw->size - pos) > wlen)
-+ cnt = wlen;
-+ else
-+ cnt = fw->size - pos;
++ case VIDIOC_G_EXT_CTRLS:
++ {
++ struct v4l2_ext_controls *c = arg;
+
-+ tda10048_writeregbulk(state, TDA10048_DSP_CODE_IN,
-+ &fw->data[pos], cnt);
++ if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
++ int i;
++ int err = 0;
+
-+ pos += cnt;
++ for (i = 0; i < c->count; i++) {
++ ctrl.id = c->controls[i].id;
++ ctrl.value = c->controls[i].value;
++ err = cx18_g_ctrl(cx, &ctrl);
++ c->controls[i].value = ctrl.value;
++ if (err) {
++ c->error_idx = i;
++ break;
++ }
++ }
++ return err;
+ }
++ CX18_DEBUG_IOCTL("VIDIOC_G_EXT_CTRLS\n");
++ if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
++ return cx2341x_ext_ctrls(&cx->params, 0, arg, cmd);
++ return -EINVAL;
++ }
+
-+ ret = -EIO;
-+ /* Wait up to 250ms for the DSP to boot */
-+ for (cnt = 0; cnt < 250 ; cnt += 10) {
++ case VIDIOC_TRY_EXT_CTRLS:
++ {
++ struct v4l2_ext_controls *c = arg;
+
-+ msleep(10);
++ CX18_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n");
++ if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
++ return cx2341x_ext_ctrls(&cx->params,
++ atomic_read(&cx->capturing), arg, cmd);
++ return -EINVAL;
++ }
+
-+ if (tda10048_readreg(state, TDA10048_SYNC_STATUS)
-+ & 0x40) {
-+ ret = 0;
-+ break;
-+ }
-+ }
++ default:
++ return -EINVAL;
+ }
++ return 0;
++}
+diff --git a/drivers/media/video/cx18/cx18-controls.h b/drivers/media/video/cx18/cx18-controls.h
+new file mode 100644
+index 0000000..6e985cf
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-controls.h
+@@ -0,0 +1,24 @@
++/*
++ * cx18 ioctl control functions
++ *
++ * Derived from ivtv-controls.h
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
+
-+ release_firmware(fw);
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the 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 (ret == 0) {
-+ printk(KERN_INFO "%s: firmware uploaded\n", __func__);
-+ state->fwloaded = 1;
-+ } else
-+ printk(KERN_ERR "%s: firmware upload failed\n", __func__);
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
+
-+ return ret;
++ * You 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
++ */
++
++int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg);
+diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
+new file mode 100644
+index 0000000..8f5ed9b
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-driver.c
+@@ -0,0 +1,971 @@
++/*
++ * cx18 driver initialization and card probing
++ *
++ * Derived from ivtv-driver.c
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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 "cx18-driver.h"
++#include "cx18-version.h"
++#include "cx18-cards.h"
++#include "cx18-i2c.h"
++#include "cx18-irq.h"
++#include "cx18-gpio.h"
++#include "cx18-firmware.h"
++#include "cx18-streams.h"
++#include "cx18-av-core.h"
++#include "cx18-scb.h"
++#include "cx18-mailbox.h"
++#include "cx18-ioctl.h"
++#include "tuner-xc2028.h"
++
++#include <media/tveeprom.h>
++
++
++/* var to keep track of the number of array elements in use */
++int cx18_cards_active;
++
++/* If you have already X v4l cards, then set this to X. This way
++ the device numbers stay matched. Example: you have a WinTV card
++ without radio and a Compro H900 with. Normally this would give a
++ video1 device together with a radio0 device for the Compro. By
++ setting this to 1 you ensure that radio0 is now also radio1. */
++int cx18_first_minor;
++
++/* Master variable for all cx18 info */
++struct cx18 *cx18_cards[CX18_MAX_CARDS];
++
++/* Protects cx18_cards_active */
++DEFINE_SPINLOCK(cx18_cards_lock);
++
++/* add your revision and whatnot here */
++static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
++ {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418,
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
++ {0,}
++};
++
++MODULE_DEVICE_TABLE(pci, cx18_pci_tbl);
++
++/* Parameter declarations */
++static int cardtype[CX18_MAX_CARDS];
++static int tuner[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
++ -1, -1, -1, -1, -1, -1, -1, -1,
++ -1, -1, -1, -1, -1, -1, -1, -1,
++ -1, -1, -1, -1, -1, -1, -1, -1 };
++static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
++ -1, -1, -1, -1, -1, -1, -1, -1,
++ -1, -1, -1, -1, -1, -1, -1, -1,
++ -1, -1, -1, -1, -1, -1, -1, -1 };
++
++static int cardtype_c = 1;
++static int tuner_c = 1;
++static int radio_c = 1;
++static char pal[] = "--";
++static char secam[] = "--";
++static char ntsc[] = "-";
++
++/* Buffers */
++static int enc_mpg_buffers = CX18_DEFAULT_ENC_MPG_BUFFERS;
++static int enc_ts_buffers = CX18_DEFAULT_ENC_TS_BUFFERS;
++static int enc_yuv_buffers = CX18_DEFAULT_ENC_YUV_BUFFERS;
++static int enc_vbi_buffers = CX18_DEFAULT_ENC_VBI_BUFFERS;
++static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS;
++
++static int cx18_pci_latency = 1;
++
++int cx18_debug;
++
++module_param_array(tuner, int, &tuner_c, 0644);
++module_param_array(radio, bool, &radio_c, 0644);
++module_param_array(cardtype, int, &cardtype_c, 0644);
++module_param_string(pal, pal, sizeof(pal), 0644);
++module_param_string(secam, secam, sizeof(secam), 0644);
++module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
++module_param_named(debug, cx18_debug, int, 0644);
++module_param(cx18_pci_latency, int, 0644);
++module_param(cx18_first_minor, int, 0644);
++
++module_param(enc_mpg_buffers, int, 0644);
++module_param(enc_ts_buffers, int, 0644);
++module_param(enc_yuv_buffers, int, 0644);
++module_param(enc_vbi_buffers, int, 0644);
++module_param(enc_pcm_buffers, int, 0644);
++
++MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
++ "\t\t\tsee tuner.h for values");
++MODULE_PARM_DESC(radio,
++ "Enable or disable the radio. Use only if autodetection\n"
++ "\t\t\tfails. 0 = disable, 1 = enable");
++MODULE_PARM_DESC(cardtype,
++ "Only use this option if your card is not detected properly.\n"
++ "\t\tSpecify card type:\n"
++ "\t\t\t 1 = Hauppauge HVR 1600 (ESMT memory)\n"
++ "\t\t\t 2 = Hauppauge HVR 1600 (Samsung memory)\n"
++ "\t\t\t 3 = Compro VideoMate H900\n"
++ "\t\t\t 4 = Yuan MPC718\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(debug,
++ "Debug level (bitmask). Default: 0\n"
++ "\t\t\t 1/0x0001: warning\n"
++ "\t\t\t 2/0x0002: info\n"
++ "\t\t\t 4/0x0004: mailbox\n"
++ "\t\t\t 8/0x0008: dma\n"
++ "\t\t\t 16/0x0010: ioctl\n"
++ "\t\t\t 32/0x0020: file\n"
++ "\t\t\t 64/0x0040: i2c\n"
++ "\t\t\t128/0x0080: irq\n"
++ "\t\t\t256/0x0100: high volume\n");
++MODULE_PARM_DESC(cx18_pci_latency,
++ "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n"
++ "\t\t\tDefault: Yes");
++MODULE_PARM_DESC(enc_mpg_buffers,
++ "Encoder MPG Buffers (in MB)\n"
++ "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS));
++MODULE_PARM_DESC(enc_ts_buffers,
++ "Encoder TS Buffers (in MB)\n"
++ "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFFERS));
++MODULE_PARM_DESC(enc_yuv_buffers,
++ "Encoder YUV Buffers (in MB)\n"
++ "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS));
++MODULE_PARM_DESC(enc_vbi_buffers,
++ "Encoder VBI Buffers (in MB)\n"
++ "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_VBI_BUFFERS));
++MODULE_PARM_DESC(enc_pcm_buffers,
++ "Encoder PCM buffers (in MB)\n"
++ "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS));
++
++MODULE_PARM_DESC(cx18_first_minor, "Set minor assigned to first card");
++
++MODULE_AUTHOR("Hans Verkuil");
++MODULE_DESCRIPTION("CX23418 driver");
++MODULE_SUPPORTED_DEVICE("CX23418 MPEG2 encoder");
++MODULE_LICENSE("GPL");
++
++MODULE_VERSION(CX18_VERSION);
++
++int cx18_waitq(wait_queue_head_t *waitq)
++{
++ DEFINE_WAIT(wait);
++
++ prepare_to_wait(waitq, &wait, TASK_INTERRUPTIBLE);
++ schedule();
++ finish_wait(waitq, &wait);
++ return signal_pending(current) ? -EINTR : 0;
+}
+
-+static int tda10048_set_inversion(struct dvb_frontend *fe, int inversion)
++/* Generic utility functions */
++int cx18_msleep_timeout(unsigned int msecs, int intr)
+{
-+ struct tda10048_state *state = fe->demodulator_priv;
++ int timeout = msecs_to_jiffies(msecs);
++ int sig;
+
-+ dprintk(1, "%s(%d)\n", __func__, inversion);
++ do {
++ set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
++ timeout = schedule_timeout(timeout);
++ sig = intr ? signal_pending(current) : 0;
++ } while (!sig && timeout);
++ return sig;
++}
+
-+ 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);
++/* Release ioremapped memory */
++static void cx18_iounmap(struct cx18 *cx)
++{
++ if (cx == NULL)
++ return;
+
-+ return 0;
++ /* Release io memory */
++ if (cx->enc_mem != NULL) {
++ CX18_DEBUG_INFO("releasing enc_mem\n");
++ iounmap(cx->enc_mem);
++ cx->enc_mem = NULL;
++ }
+}
+
-+/* Retrieve the demod settings */
-+static int tda10048_get_tps(struct tda10048_state *state,
-+ struct dvb_ofdm_parameters *p)
++/* Hauppauge card? get values from tveeprom */
++void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv)
+{
-+ u8 val;
++ u8 eedata[256];
+
-+ /* Make sure the TPS regs are valid */
-+ if (!(tda10048_readreg(state, TDA10048_AUTO) & 0x01))
-+ return -EAGAIN;
++ cx->i2c_client[0].addr = 0xA0 >> 1;
++ tveeprom_read(&cx->i2c_client[0], eedata, sizeof(eedata));
++ tveeprom_hauppauge_analog(&cx->i2c_client[0], tv, eedata);
++}
+
-+ 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;
++static void cx18_process_eeprom(struct cx18 *cx)
++{
++ struct tveeprom tv;
++
++ cx18_read_eeprom(cx, &tv);
++
++ /* Many thanks to Steven Toth from Hauppauge for providing the
++ model numbers */
++ switch (tv.model) {
++ case 74000 ... 74099:
++ cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
++ break;
++ case 74700 ... 74799:
++ cx->card = cx18_get_card(CX18_CARD_HVR_1600_SAMSUNG);
++ break;
++ case 0:
++ CX18_ERR("Invalid EEPROM\n");
++ return;
++ default:
++ CX18_ERR("Unknown model %d, defaulting to HVR-1600\n", tv.model);
++ cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
++ 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;
++
++ cx->v4l2_cap = cx->card->v4l2_capabilities;
++ cx->card_name = cx->card->name;
++ cx->card_i2c = cx->card->i2c;
++
++ CX18_INFO("Autodetected %s\n", cx->card_name);
++
++ if (tv.tuner_type == TUNER_ABSENT)
++ CX18_ERR("tveeprom cannot autodetect tuner!");
++
++ if (cx->options.tuner == -1)
++ cx->options.tuner = tv.tuner_type;
++ if (cx->options.radio == -1)
++ cx->options.radio = (tv.has_radio != 0);
++
++ if (cx->std != 0)
++ /* user specified tuner standard */
++ return;
++
++ /* autodetect tuner standard */
++ if (tv.tuner_formats & V4L2_STD_PAL) {
++ CX18_DEBUG_INFO("PAL tuner detected\n");
++ cx->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
++ } else if (tv.tuner_formats & V4L2_STD_NTSC) {
++ CX18_DEBUG_INFO("NTSC tuner detected\n");
++ cx->std |= V4L2_STD_NTSC_M;
++ } else if (tv.tuner_formats & V4L2_STD_SECAM) {
++ CX18_DEBUG_INFO("SECAM tuner detected\n");
++ cx->std |= V4L2_STD_SECAM_L;
++ } else {
++ CX18_INFO("No tuner detected, default to NTSC-M\n");
++ cx->std |= V4L2_STD_NTSC_M;
+ }
++}
+
-+ 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;
++static v4l2_std_id cx18_parse_std(struct cx18 *cx)
++{
++ switch (pal[0]) {
++ case '6':
++ 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;
++ case 'n':
++ case 'N':
++ if (pal[1] == 'c' || pal[1] == 'C')
++ return V4L2_STD_PAL_Nc;
++ return V4L2_STD_PAL_N;
++ case 'i':
++ case 'I':
++ return V4L2_STD_PAL_I;
++ case 'd':
++ case 'D':
++ case 'k':
++ case 'K':
++ return V4L2_STD_PAL_DK;
++ case 'M':
++ case 'm':
++ return V4L2_STD_PAL_M;
++ case '-':
++ break;
++ default:
++ CX18_WARN("pal= argument not recognised\n");
++ return 0;
+ }
+
-+ 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 (secam[0]) {
++ case 'b':
++ case 'B':
++ case 'g':
++ case 'G':
++ case 'h':
++ case 'H':
++ return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
++ case 'd':
++ case 'D':
++ case 'k':
++ case 'K':
++ return V4L2_STD_SECAM_DK;
++ case 'l':
++ case 'L':
++ if (secam[1] == 'C' || secam[1] == 'c')
++ return V4L2_STD_SECAM_LC;
++ return V4L2_STD_SECAM_L;
++ case '-':
++ break;
++ default:
++ CX18_WARN("secam= argument not recognised\n");
++ return 0;
+ }
-+ switch (val & 0x02) {
-+ case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break;
-+ case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break;
++
++ switch (ntsc[0]) {
++ case 'm':
++ case 'M':
++ return V4L2_STD_NTSC_M;
++ case 'j':
++ case 'J':
++ return V4L2_STD_NTSC_M_JP;
++ case 'k':
++ case 'K':
++ return V4L2_STD_NTSC_M_KR;
++ case '-':
++ break;
++ default:
++ CX18_WARN("ntsc= argument not recognised\n");
++ return 0;
+ }
+
++ /* no match found */
+ return 0;
+}
+
-+static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
++static void cx18_process_options(struct cx18 *cx)
+{
-+ struct tda10048_state *state = fe->demodulator_priv;
-+ dprintk(1, "%s(%d)\n", __func__, enable);
++ int i, j;
+
-+ 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);
-+}
++ cx->options.megabytes[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers;
++ cx->options.megabytes[CX18_ENC_STREAM_TYPE_TS] = enc_ts_buffers;
++ cx->options.megabytes[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers;
++ cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers;
++ cx->options.megabytes[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers;
++ cx->options.cardtype = cardtype[cx->num];
++ cx->options.tuner = tuner[cx->num];
++ cx->options.radio = radio[cx->num];
++
++ cx->std = cx18_parse_std(cx);
++ if (cx->options.cardtype == -1) {
++ CX18_INFO("Ignore card\n");
++ return;
++ }
++ cx->card = cx18_get_card(cx->options.cardtype - 1);
++ if (cx->card)
++ CX18_INFO("User specified %s card\n", cx->card->name);
++ else if (cx->options.cardtype != 0)
++ CX18_ERR("Unknown user specified type, trying to autodetect card\n");
++ if (cx->card == NULL) {
++ if (cx->dev->subsystem_vendor == CX18_PCI_ID_HAUPPAUGE) {
++ cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
++ CX18_INFO("Autodetected Hauppauge card\n");
++ }
++ }
++ if (cx->card == NULL) {
++ for (i = 0; (cx->card = cx18_get_card(i)); i++) {
++ if (cx->card->pci_list == NULL)
++ continue;
++ for (j = 0; cx->card->pci_list[j].device; j++) {
++ if (cx->dev->device !=
++ cx->card->pci_list[j].device)
++ continue;
++ if (cx->dev->subsystem_vendor !=
++ cx->card->pci_list[j].subsystem_vendor)
++ continue;
++ if (cx->dev->subsystem_device !=
++ cx->card->pci_list[j].subsystem_device)
++ continue;
++ CX18_INFO("Autodetected %s card\n", cx->card->name);
++ goto done;
++ }
++ }
++ }
++done:
+
-+static int tda10048_output_mode(struct dvb_frontend *fe, int serial)
++ if (cx->card == NULL) {
++ cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
++ CX18_ERR("Unknown card: vendor/device: %04x/%04x\n",
++ cx->dev->vendor, cx->dev->device);
++ CX18_ERR(" subsystem vendor/device: %04x/%04x\n",
++ cx->dev->subsystem_vendor, cx->dev->subsystem_device);
++ CX18_ERR("Defaulting to %s card\n", cx->card->name);
++ CX18_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n");
++ CX18_ERR("card you have to the ivtv-devel mailinglist (www.ivtvdriver.org)\n");
++ CX18_ERR("Prefix your subject line with [UNKNOWN CX18 CARD].\n");
++ }
++ cx->v4l2_cap = cx->card->v4l2_capabilities;
++ cx->card_name = cx->card->name;
++ cx->card_i2c = cx->card->i2c;
++}
++
++/* Precondition: the cx18 structure has been memset to 0. Only
++ the dev and num fields have been filled in.
++ No assumptions on the card type may be made here (see cx18_init_struct2
++ for that).
++ */
++static int __devinit cx18_init_struct1(struct cx18 *cx)
++{
++ cx->base_addr = pci_resource_start(cx->dev, 0);
++
++ mutex_init(&cx->serialize_lock);
++ mutex_init(&cx->i2c_bus_lock[0]);
++ mutex_init(&cx->i2c_bus_lock[1]);
++
++ spin_lock_init(&cx->lock);
++ spin_lock_init(&cx->dma_reg_lock);
++
++ /* start counting open_id at 1 */
++ cx->open_id = 1;
++
++ /* Initial settings */
++ cx2341x_fill_defaults(&cx->params);
++ cx->temporal_strength = cx->params.video_temporal_filter;
++ cx->spatial_strength = cx->params.video_spatial_filter;
++ cx->filter_mode = cx->params.video_spatial_filter_mode |
++ (cx->params.video_temporal_filter_mode << 1) |
++ (cx->params.video_median_filter_type << 2);
++ cx->params.port = CX2341X_PORT_MEMORY;
++ cx->params.capabilities = CX2341X_CAP_HAS_SLICED_VBI;
++ init_waitqueue_head(&cx->cap_w);
++ init_waitqueue_head(&cx->mb_apu_waitq);
++ init_waitqueue_head(&cx->mb_cpu_waitq);
++ init_waitqueue_head(&cx->mb_epu_waitq);
++ init_waitqueue_head(&cx->mb_hpu_waitq);
++ init_waitqueue_head(&cx->dma_waitq);
++
++ /* VBI */
++ cx->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
++ cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced;
++ cx->vbi.raw_size = 1456;
++ cx->vbi.raw_decoder_line_size = 1456;
++ cx->vbi.raw_decoder_sav_odd_field = 0x20;
++ cx->vbi.raw_decoder_sav_even_field = 0x60;
++ cx->vbi.sliced_decoder_line_size = 272;
++ cx->vbi.sliced_decoder_sav_odd_field = 0xB0;
++ cx->vbi.sliced_decoder_sav_even_field = 0xF0;
++ return 0;
++}
++
++/* Second initialization part. Here the card type has been
++ autodetected. */
++static void __devinit cx18_init_struct2(struct cx18 *cx)
+{
-+ struct tda10048_state *state = fe->demodulator_priv;
-+ dprintk(1, "%s(%d)\n", __func__, serial);
++ int i;
+
-+ /* Ensure pins are out of tri-state */
-+ tda10048_writereg(state, TDA10048_CONF_TRISTATE1, 0x21);
-+ tda10048_writereg(state, TDA10048_CONF_TRISTATE2, 0x00);
++ for (i = 0; i < CX18_CARD_MAX_VIDEO_INPUTS; i++)
++ if (cx->card->video_inputs[i].video_type == 0)
++ break;
++ cx->nof_inputs = i;
++ for (i = 0; i < CX18_CARD_MAX_AUDIO_INPUTS; i++)
++ if (cx->card->audio_inputs[i].audio_type == 0)
++ break;
++ cx->nof_audio_inputs = i;
+
-+ 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);
++ /* Find tuner input */
++ for (i = 0; i < cx->nof_inputs; i++) {
++ if (cx->card->video_inputs[i].video_type ==
++ CX18_CARD_INPUT_VID_TUNER)
++ break;
+ }
-+
-+ return 0;
++ if (i == cx->nof_inputs)
++ i = 0;
++ cx->active_input = i;
++ cx->audio_input = cx->card->video_inputs[i].audio_index;
++ cx->av_state.vid_input = CX18_AV_COMPOSITE7;
++ cx->av_state.aud_input = CX18_AV_AUDIO8;
++ cx->av_state.audclk_freq = 48000;
++ cx->av_state.audmode = V4L2_TUNER_MODE_LANG1;
++ cx->av_state.vbi_line_offset = 8;
+}
+
-+/* 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)
++static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev,
++ const struct pci_device_id *pci_id)
+{
-+ struct tda10048_state *state = fe->demodulator_priv;
++ u16 cmd;
++ unsigned char pci_latency;
+
-+ dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency);
++ CX18_DEBUG_INFO("Enabling pci device\n");
+
-+ if (fe->ops.tuner_ops.set_params) {
++ if (pci_enable_device(dev)) {
++ CX18_ERR("Can't enable device %d!\n", cx->num);
++ return -EIO;
++ }
++ if (pci_set_dma_mask(dev, 0xffffffff)) {
++ CX18_ERR("No suitable DMA available on card %d.\n", cx->num);
++ return -EIO;
++ }
++ if (!request_mem_region(cx->base_addr, CX18_MEM_SIZE, "cx18 encoder")) {
++ CX18_ERR("Cannot request encoder memory region on card %d.\n", cx->num);
++ return -EIO;
++ }
+
-+ if (fe->ops.i2c_gate_ctrl)
-+ fe->ops.i2c_gate_ctrl(fe, 1);
++ /* Check for bus mastering */
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
+
-+ fe->ops.tuner_ops.set_params(fe, p);
++ pci_read_config_byte(dev, PCI_CLASS_REVISION, &cx->card_rev);
++ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
+
-+ if (fe->ops.i2c_gate_ctrl)
-+ fe->ops.i2c_gate_ctrl(fe, 0);
++ if (pci_latency < 64 && cx18_pci_latency) {
++ CX18_INFO("Unreasonably low latency timer, "
++ "setting to 64 (was %d)\n", pci_latency);
++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
++ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
+ }
++ /* This config space value relates to DMA latencies. The
++ default value 0x8080 is too low however and will lead
++ to DMA errors. 0xffff is the max value which solves
++ these problems. */
++ pci_write_config_dword(dev, 0x40, 0xffff);
+
-+ /* Enable demod TPS auto detection and begin acquisition */
-+ tda10048_writereg(state, TDA10048_AUTO, 0x57);
++ CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, "
++ "irq: %d, latency: %d, memory: 0x%lx\n",
++ cx->dev->device, cx->card_rev, dev->bus->number,
++ PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
++ cx->dev->irq, pci_latency, (unsigned long)cx->base_addr);
+
+ return 0;
+}
+
-+/* Establish sane defaults and load firmware. */
-+static int tda10048_init(struct dvb_frontend *fe)
++static u32 cx18_request_module(struct cx18 *cx, u32 hw,
++ const char *name, u32 id)
+{
-+ 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 ((hw & id) == 0)
++ return hw;
++ if (request_module(name) != 0) {
++ CX18_ERR("Failed to load module %s\n", name);
++ return hw & ~id;
++ }
++ CX18_DEBUG_INFO("Loaded module %s\n", name);
++ return hw;
++}
+
-+ if (state->fwloaded == 0)
-+ ret = tda10048_firmware_upload(fe);
++static void cx18_load_and_init_modules(struct cx18 *cx)
++{
++ u32 hw = cx->card->hw_all;
++ int i;
+
-+ /* Set either serial or parallel */
-+ tda10048_output_mode(fe, state->config->output_mode);
++ /* load modules */
++#ifndef CONFIG_MEDIA_TUNER
++ hw = cx18_request_module(cx, hw, "tuner", CX18_HW_TUNER);
++#endif
++#ifndef CONFIG_VIDEO_CS5345
++ hw = cx18_request_module(cx, hw, "cs5345", CX18_HW_CS5345);
++#endif
+
-+ /* set inversion */
-+ tda10048_set_inversion(fe, state->config->inversion);
++ /* check which i2c devices are actually found */
++ for (i = 0; i < 32; i++) {
++ u32 device = 1 << i;
+
-+ /* Ensure we leave the gate closed */
-+ tda10048_i2c_gate_ctrl(fe, 0);
++ if (!(device & hw))
++ continue;
++ if (device == CX18_HW_GPIO || device == CX18_HW_TVEEPROM ||
++ device == CX18_HW_CX23418 || device == CX18_HW_DVB) {
++ /* These 'devices' do not use i2c probing */
++ cx->hw_flags |= device;
++ continue;
++ }
++ cx18_i2c_register(cx, i);
++ if (cx18_i2c_hw_addr(cx, device) > 0)
++ cx->hw_flags |= device;
++ }
+
-+ return ret;
++ hw = cx->hw_flags;
+}
+
-+static int tda10048_read_status(struct dvb_frontend *fe, fe_status_t *status)
++static int __devinit cx18_probe(struct pci_dev *dev,
++ const struct pci_device_id *pci_id)
+{
-+ struct tda10048_state *state = fe->demodulator_priv;
-+ u8 reg;
++ int retval = 0;
++ int vbi_buf_size;
++ u32 devtype;
++ struct cx18 *cx;
++
++ spin_lock(&cx18_cards_lock);
++
++ /* Make sure we've got a place for this card */
++ if (cx18_cards_active == CX18_MAX_CARDS) {
++ printk(KERN_ERR "cx18: Maximum number of cards detected (%d).\n",
++ cx18_cards_active);
++ spin_unlock(&cx18_cards_lock);
++ return -ENOMEM;
++ }
+
-+ *status = 0;
++ cx = kzalloc(sizeof(struct cx18), GFP_ATOMIC);
++ if (cx == 0) {
++ spin_unlock(&cx18_cards_lock);
++ return -ENOMEM;
++ }
++ cx18_cards[cx18_cards_active] = cx;
++ cx->dev = dev;
++ cx->num = cx18_cards_active++;
++ snprintf(cx->name, sizeof(cx->name) - 1, "cx18-%d", cx->num);
++ CX18_INFO("Initializing card #%d\n", cx->num);
++
++ spin_unlock(&cx18_cards_lock);
++
++ cx18_process_options(cx);
++ if (cx->options.cardtype == -1) {
++ retval = -ENODEV;
++ goto err;
++ }
++ if (cx18_init_struct1(cx)) {
++ retval = -ENOMEM;
++ goto err;
++ }
+
-+ reg = tda10048_readreg(state, TDA10048_SYNC_STATUS);
++ CX18_DEBUG_INFO("base addr: 0x%08x\n", cx->base_addr);
+
-+ dprintk(1, "%s() status =0x%02x\n", __func__, reg);
++ /* PCI Device Setup */
++ retval = cx18_setup_pci(cx, dev, pci_id);
++ if (retval != 0) {
++ if (retval == -EIO)
++ goto free_workqueue;
++ else if (retval == -ENXIO)
++ goto free_mem;
++ }
++ /* save cx in the pci struct for later use */
++ pci_set_drvdata(dev, cx);
++
++ /* map io memory */
++ CX18_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n",
++ cx->base_addr + CX18_MEM_OFFSET, CX18_MEM_SIZE);
++ cx->enc_mem = ioremap_nocache(cx->base_addr + CX18_MEM_OFFSET,
++ CX18_MEM_SIZE);
++ if (!cx->enc_mem) {
++ CX18_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n");
++ CX18_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n");
++ retval = -ENOMEM;
++ goto free_mem;
++ }
++ cx->reg_mem = cx->enc_mem + CX18_REG_OFFSET;
++ devtype = read_reg(0xC72028);
++ switch (devtype & 0xff000000) {
++ case 0xff000000:
++ CX18_INFO("cx23418 revision %08x (A)\n", devtype);
++ break;
++ case 0x01000000:
++ CX18_INFO("cx23418 revision %08x (B)\n", devtype);
++ break;
++ default:
++ CX18_INFO("cx23418 revision %08x (Unknown)\n", devtype);
++ break;
++ }
+
-+ if (reg & 0x02)
-+ *status |= FE_HAS_CARRIER;
++ cx18_init_power(cx, 1);
++ cx18_init_memory(cx);
+
-+ if (reg & 0x04)
-+ *status |= FE_HAS_SIGNAL;
++ cx->scb = (struct cx18_scb *)(cx->enc_mem + SCB_OFFSET);
++ cx18_init_scb(cx);
+
-+ if (reg & 0x08) {
-+ *status |= FE_HAS_LOCK;
-+ *status |= FE_HAS_VITERBI;
-+ *status |= FE_HAS_SYNC;
++ cx18_gpio_init(cx);
++
++ /* active i2c */
++ CX18_DEBUG_INFO("activating i2c...\n");
++ if (init_cx18_i2c(cx)) {
++ CX18_ERR("Could not initialize i2c\n");
++ goto free_map;
+ }
+
-+ return 0;
-+}
++ CX18_DEBUG_INFO("Active card count: %d.\n", cx18_cards_active);
+
-+static int tda10048_read_ber(struct dvb_frontend *fe, u32 *ber)
-+{
-+ struct tda10048_state *state = fe->demodulator_priv;
++ if (cx->card->hw_all & CX18_HW_TVEEPROM) {
++ /* Based on the model number the cardtype may be changed.
++ The PCI IDs are not always reliable. */
++ cx18_process_eeprom(cx);
++ }
++ if (cx->card->comment)
++ CX18_INFO("%s", cx->card->comment);
++ if (cx->card->v4l2_capabilities == 0) {
++ retval = -ENODEV;
++ goto free_i2c;
++ }
++ cx18_init_memory(cx);
+
-+ dprintk(1, "%s()\n", __func__);
++ /* Register IRQ */
++ retval = request_irq(cx->dev->irq, cx18_irq_handler,
++ IRQF_SHARED | IRQF_DISABLED, cx->name, (void *)cx);
++ if (retval) {
++ CX18_ERR("Failed to register irq %d\n", retval);
++ goto free_i2c;
++ }
+
-+ /* TODO: A reset may be required here */
-+ *ber = tda10048_readreg(state, TDA10048_CBER_MSB) << 8 |
-+ tda10048_readreg(state, TDA10048_CBER_LSB);
++ if (cx->std == 0)
++ cx->std = V4L2_STD_NTSC_M;
+
-+ return 0;
-+}
++ if (cx->options.tuner == -1) {
++ int i;
+
-+static int tda10048_read_signal_strength(struct dvb_frontend *fe,
-+ u16 *signal_strength)
-+{
-+ struct tda10048_state *state = fe->demodulator_priv;
-+ u8 v;
++ for (i = 0; i < CX18_CARD_MAX_TUNERS; i++) {
++ if ((cx->std & cx->card->tuners[i].std) == 0)
++ continue;
++ cx->options.tuner = cx->card->tuners[i].tuner;
++ break;
++ }
++ }
++ /* if no tuner was found, then pick the first tuner in the card list */
++ if (cx->options.tuner == -1 && cx->card->tuners[0].std) {
++ cx->std = cx->card->tuners[0].std;
++ cx->options.tuner = cx->card->tuners[0].tuner;
++ }
++ if (cx->options.radio == -1)
++ cx->options.radio = (cx->card->radio_input.audio_type != 0);
+
-+ dprintk(1, "%s()\n", __func__);
++ /* The card is now fully identified, continue with card-specific
++ initialization. */
++ cx18_init_struct2(cx);
+
-+ *signal_strength = 65535;
++ cx18_load_and_init_modules(cx);
+
-+ v = tda10048_readreg(state, TDA10048_NP_OUT);
-+ if (v > 0)
-+ *signal_strength -= (v << 8) | v;
++ if (cx->std & V4L2_STD_525_60) {
++ cx->is_60hz = 1;
++ cx->is_out_60hz = 1;
++ } else {
++ cx->is_50hz = 1;
++ cx->is_out_50hz = 1;
++ }
++ cx->params.video_gop_size = cx->is_60hz ? 15 : 12;
+
-+ return 0;
-+}
++ cx->stream_buf_size[CX18_ENC_STREAM_TYPE_MPG] = 0x08000;
++ cx->stream_buf_size[CX18_ENC_STREAM_TYPE_TS] = 0x08000;
++ cx->stream_buf_size[CX18_ENC_STREAM_TYPE_PCM] = 0x01200;
++ cx->stream_buf_size[CX18_ENC_STREAM_TYPE_YUV] = 0x20000;
++ vbi_buf_size = cx->vbi.raw_size * (cx->is_60hz ? 24 : 36) / 2;
++ cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_buf_size;
+
-+/* 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 },
-+};
++ if (cx->options.radio > 0)
++ cx->v4l2_cap |= V4L2_CAP_RADIO;
+
-+static int tda10048_read_snr(struct dvb_frontend *fe, u16 *snr)
-+{
-+ struct tda10048_state *state = fe->demodulator_priv;
-+ u8 v;
-+ int i, ret = -EINVAL;
++ retval = cx18_streams_setup(cx);
++ if (retval) {
++ CX18_ERR("Error %d setting up streams\n", retval);
++ goto free_irq;
++ }
++ retval = cx18_streams_register(cx);
++ if (retval) {
++ CX18_ERR("Error %d registering devices\n", retval);
++ goto free_streams;
++ }
+
-+ dprintk(1, "%s()\n", __func__);
++ if (cx->options.tuner > -1) {
++ struct tuner_setup setup;
+
-+ 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;
++ setup.addr = ADDR_UNSET;
++ setup.type = cx->options.tuner;
++ setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */
++ setup.tuner_callback = (setup.type == TUNER_XC2028) ?
++ cx18_reset_tuner_gpio : NULL;
++ cx18_call_i2c_clients(cx, TUNER_SET_TYPE_ADDR, &setup);
++ if (setup.type == TUNER_XC2028) {
++ static struct xc2028_ctrl ctrl = {
++ .fname = XC2028_DEFAULT_FIRMWARE,
++ .max_len = 64,
++ };
++ struct v4l2_priv_tun_config cfg = {
++ .tuner = cx->options.tuner,
++ .priv = &ctrl,
++ };
++ cx18_call_i2c_clients(cx, TUNER_SET_CONFIG, &cfg);
+ }
+ }
+
-+ return ret;
++ /* The tuner is fixed to the standard. The other inputs (e.g. S-Video)
++ are not. */
++ cx->tuner_std = cx->std;
++
++ cx18_init_on_first_open(cx);
++
++ CX18_INFO("Initialized card #%d: %s\n", cx->num, cx->card_name);
++
++ return 0;
++
++free_streams:
++ cx18_streams_cleanup(cx);
++free_irq:
++ free_irq(cx->dev->irq, (void *)cx);
++free_i2c:
++ exit_cx18_i2c(cx);
++free_map:
++ cx18_iounmap(cx);
++free_mem:
++ release_mem_region(cx->base_addr, CX18_MEM_SIZE);
++free_workqueue:
++err:
++ if (retval == 0)
++ retval = -ENODEV;
++ CX18_ERR("Error %d on initialization\n", retval);
++
++ kfree(cx18_cards[cx18_cards_active]);
++ cx18_cards[cx18_cards_active] = NULL;
++ return retval;
+}
+
-+static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
++int cx18_init_on_first_open(struct cx18 *cx)
+{
-+ struct tda10048_state *state = fe->demodulator_priv;
++ int video_input;
++ int fw_retry_count = 3;
++ struct v4l2_frequency vf;
+
-+ dprintk(1, "%s()\n", __func__);
++ if (test_bit(CX18_F_I_FAILED, &cx->i_flags))
++ return -ENXIO;
+
-+ *ucblocks = tda10048_readreg(state, TDA10048_UNCOR_CPT_MSB) << 8 |
-+ tda10048_readreg(state, TDA10048_UNCOR_CPT_LSB);
++ if (test_and_set_bit(CX18_F_I_INITED, &cx->i_flags))
++ return 0;
++
++ while (--fw_retry_count > 0) {
++ /* load firmware */
++ if (cx18_firmware_init(cx) == 0)
++ break;
++ if (fw_retry_count > 1)
++ CX18_WARN("Retry loading firmware\n");
++ }
++
++ if (fw_retry_count == 0) {
++ set_bit(CX18_F_I_FAILED, &cx->i_flags);
++ return -ENXIO;
++ }
++ set_bit(CX18_F_I_LOADED_FW, &cx->i_flags);
++
++ /* Init the firmware twice to work around a silicon bug
++ * transport related. */
++
++ fw_retry_count = 3;
++ while (--fw_retry_count > 0) {
++ /* load firmware */
++ if (cx18_firmware_init(cx) == 0)
++ break;
++ if (fw_retry_count > 1)
++ CX18_WARN("Retry loading firmware\n");
++ }
++
++ if (fw_retry_count == 0) {
++ set_bit(CX18_F_I_FAILED, &cx->i_flags);
++ return -ENXIO;
++ }
+
++ vf.tuner = 0;
++ vf.type = V4L2_TUNER_ANALOG_TV;
++ vf.frequency = 6400; /* the tuner 'baseline' frequency */
++
++ /* Set initial frequency. For PAL/SECAM broadcasts no
++ 'default' channel exists AFAIK. */
++ if (cx->std == V4L2_STD_NTSC_M_JP)
++ vf.frequency = 1460; /* ch. 1 91250*16/1000 */
++ else if (cx->std & V4L2_STD_NTSC_M)
++ vf.frequency = 1076; /* ch. 4 67250*16/1000 */
++
++ video_input = cx->active_input;
++ cx->active_input++; /* Force update of input */
++ cx18_v4l2_ioctls(cx, NULL, VIDIOC_S_INPUT, &video_input);
++
++ /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
++ in one place. */
++ cx->std++; /* Force full standard initialization */
++ cx18_v4l2_ioctls(cx, NULL, VIDIOC_S_STD, &cx->tuner_std);
++ cx18_v4l2_ioctls(cx, NULL, VIDIOC_S_FREQUENCY, &vf);
+ return 0;
+}
+
-+static int tda10048_get_frontend(struct dvb_frontend *fe,
-+ struct dvb_frontend_parameters *p)
++static void cx18_remove(struct pci_dev *pci_dev)
+{
-+ struct tda10048_state *state = fe->demodulator_priv;
++ struct cx18 *cx = pci_get_drvdata(pci_dev);
+
-+ dprintk(1, "%s()\n", __func__);
++ CX18_DEBUG_INFO("Removing Card #%d\n", cx->num);
+
-+ p->inversion = tda10048_readreg(state, TDA10048_CONF_C1_1)
-+ & 0x20 ? INVERSION_ON : INVERSION_OFF;
++ /* Stop all captures */
++ CX18_DEBUG_INFO("Stopping all streams\n");
++ if (atomic_read(&cx->capturing) > 0)
++ cx18_stop_all_captures(cx);
+
-+ return tda10048_get_tps(state, &p->u.ofdm);
++ /* Interrupts */
++ sw1_irq_disable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
++ sw2_irq_disable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
++
++ cx18_halt_firmware(cx);
++
++ cx18_streams_cleanup(cx);
++
++ exit_cx18_i2c(cx);
++
++ free_irq(cx->dev->irq, (void *)cx);
++
++ if (cx->dev)
++ cx18_iounmap(cx);
++
++ release_mem_region(cx->base_addr, CX18_MEM_SIZE);
++
++ pci_disable_device(cx->dev);
++
++ CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num);
+}
+
-+static int tda10048_get_tune_settings(struct dvb_frontend *fe,
-+ struct dvb_frontend_tune_settings *tune)
++/* define a pci_driver for card detection */
++static struct pci_driver cx18_pci_driver = {
++ .name = "cx18",
++ .id_table = cx18_pci_tbl,
++ .probe = cx18_probe,
++ .remove = cx18_remove,
++};
++
++static int module_start(void)
+{
-+ tune->min_delay_ms = 1000;
++ printk(KERN_INFO "cx18: Start initialization, version %s\n", CX18_VERSION);
++
++ memset(cx18_cards, 0, sizeof(cx18_cards));
++
++ /* Validate parameters */
++ if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) {
++ printk(KERN_ERR "cx18: Exiting, ivtv_first_minor must be between 0 and %d\n",
++ CX18_MAX_CARDS - 1);
++ return -1;
++ }
++
++ if (cx18_debug < 0 || cx18_debug > 511) {
++ cx18_debug = 0;
++ printk(KERN_INFO "cx18: Debug value must be >= 0 and <= 511!\n");
++ }
++
++ if (pci_register_driver(&cx18_pci_driver)) {
++ printk(KERN_ERR "cx18: Error detecting PCI card\n");
++ return -ENODEV;
++ }
++ printk(KERN_INFO "cx18: End initialization\n");
+ return 0;
+}
+
-+static void tda10048_release(struct dvb_frontend *fe)
++static void module_cleanup(void)
+{
-+ struct tda10048_state *state = fe->demodulator_priv;
-+ dprintk(1, "%s()\n", __func__);
-+ kfree(state);
++ int i;
++
++ pci_unregister_driver(&cx18_pci_driver);
++
++ for (i = 0; i < cx18_cards_active; i++) {
++ if (cx18_cards[i] == NULL)
++ continue;
++ kfree(cx18_cards[i]);
++ }
+}
+
-+static struct dvb_frontend_ops tda10048_ops;
++module_init(module_start);
++module_exit(module_cleanup);
+diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
+new file mode 100644
+index 0000000..2ee9391
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-driver.h
+@@ -0,0 +1,500 @@
++/*
++ * cx18 driver internal defines and structures
++ *
++ * Derived from ivtv-driver.h
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
-+struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
-+ struct i2c_adapter *i2c)
-+{
-+ struct tda10048_state *state = NULL;
++#ifndef CX18_DRIVER_H
++#define CX18_DRIVER_H
+
-+ dprintk(1, "%s()\n", __func__);
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/pci.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/i2c.h>
++#include <linux/i2c-algo-bit.h>
++#include <linux/list.h>
++#include <linux/unistd.h>
++#include <linux/byteorder/swab.h>
++#include <linux/pagemap.h>
++#include <linux/workqueue.h>
++#include <linux/mutex.h>
+
-+ /* allocate memory for the internal state */
-+ state = kmalloc(sizeof(struct tda10048_state), GFP_KERNEL);
-+ if (state == NULL)
-+ goto error;
++#include <linux/dvb/video.h>
++#include <linux/dvb/audio.h>
++#include <media/v4l2-common.h>
++#include <media/tuner.h>
++#include "cx18-mailbox.h"
++#include "cx18-av-core.h"
++#include "cx23418.h"
+
-+ /* setup the state */
-+ state->config = config;
-+ state->i2c = i2c;
-+ state->fwloaded = 0;
++/* DVB */
++#include "demux.h"
++#include "dmxdev.h"
++#include "dvb_demux.h"
++#include "dvb_frontend.h"
++#include "dvb_net.h"
++#include "dvbdev.h"
+
-+ /* check if the demod is present */
-+ if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048)
-+ goto error;
++#ifndef CONFIG_PCI
++# error "This driver requires kernel PCI support."
++#endif
+
-+ /* create dvb_frontend */
-+ memcpy(&state->frontend.ops, &tda10048_ops,
-+ sizeof(struct dvb_frontend_ops));
-+ state->frontend.demodulator_priv = state;
++#define CX18_MEM_OFFSET 0x00000000
++#define CX18_MEM_SIZE 0x04000000
++#define CX18_REG_OFFSET 0x02000000
++
++/* Maximum cx18 driver instances. */
++#define CX18_MAX_CARDS 32
++
++/* Supported cards */
++#define CX18_CARD_HVR_1600_ESMT 0 /* Hauppauge HVR 1600 (ESMT memory) */
++#define CX18_CARD_HVR_1600_SAMSUNG 1 /* Hauppauge HVR 1600 (Samsung memory) */
++#define CX18_CARD_COMPRO_H900 2 /* Compro VideoMate H900 */
++#define CX18_CARD_YUAN_MPC718 3 /* Yuan MPC718 */
++#define CX18_CARD_LAST 3
++
++#define CX18_ENC_STREAM_TYPE_MPG 0
++#define CX18_ENC_STREAM_TYPE_TS 1
++#define CX18_ENC_STREAM_TYPE_YUV 2
++#define CX18_ENC_STREAM_TYPE_VBI 3
++#define CX18_ENC_STREAM_TYPE_PCM 4
++#define CX18_ENC_STREAM_TYPE_IDX 5
++#define CX18_ENC_STREAM_TYPE_RAD 6
++#define CX18_MAX_STREAMS 7
++
++/* system vendor and device IDs */
++#define PCI_VENDOR_ID_CX 0x14f1
++#define PCI_DEVICE_ID_CX23418 0x5b7a
++
++/* subsystem vendor ID */
++#define CX18_PCI_ID_HAUPPAUGE 0x0070
++#define CX18_PCI_ID_COMPRO 0x185b
++#define CX18_PCI_ID_YUAN 0x12ab
++
++/* ======================================================================== */
++/* ========================== START USER SETTABLE DMA VARIABLES =========== */
++/* ======================================================================== */
++
++/* DMA Buffers, Default size in MB allocated */
++#define CX18_DEFAULT_ENC_TS_BUFFERS 1
++#define CX18_DEFAULT_ENC_MPG_BUFFERS 2
++#define CX18_DEFAULT_ENC_IDX_BUFFERS 1
++#define CX18_DEFAULT_ENC_YUV_BUFFERS 2
++#define CX18_DEFAULT_ENC_VBI_BUFFERS 1
++#define CX18_DEFAULT_ENC_PCM_BUFFERS 1
++
++/* i2c stuff */
++#define I2C_CLIENTS_MAX 16
++
++/* debugging */
++
++/* Flag to turn on high volume debugging */
++#define CX18_DBGFLG_WARN (1 << 0)
++#define CX18_DBGFLG_INFO (1 << 1)
++#define CX18_DBGFLG_API (1 << 2)
++#define CX18_DBGFLG_DMA (1 << 3)
++#define CX18_DBGFLG_IOCTL (1 << 4)
++#define CX18_DBGFLG_FILE (1 << 5)
++#define CX18_DBGFLG_I2C (1 << 6)
++#define CX18_DBGFLG_IRQ (1 << 7)
++/* Flag to turn on high volume debugging */
++#define CX18_DBGFLG_HIGHVOL (1 << 8)
++
++/* NOTE: extra space before comma in 'cx->num , ## args' is required for
++ gcc-2.95, otherwise it won't compile. */
++#define CX18_DEBUG(x, type, fmt, args...) \
++ do { \
++ if ((x) & cx18_debug) \
++ printk(KERN_INFO "cx18-%d " type ": " fmt, cx->num , ## args); \
++ } while (0)
++#define CX18_DEBUG_WARN(fmt, args...) CX18_DEBUG(CX18_DBGFLG_WARN, "warning", fmt , ## args)
++#define CX18_DEBUG_INFO(fmt, args...) CX18_DEBUG(CX18_DBGFLG_INFO, "info", fmt , ## args)
++#define CX18_DEBUG_API(fmt, args...) CX18_DEBUG(CX18_DBGFLG_API, "api", fmt , ## args)
++#define CX18_DEBUG_DMA(fmt, args...) CX18_DEBUG(CX18_DBGFLG_DMA, "dma", fmt , ## args)
++#define CX18_DEBUG_IOCTL(fmt, args...) CX18_DEBUG(CX18_DBGFLG_IOCTL, "ioctl", fmt , ## args)
++#define CX18_DEBUG_FILE(fmt, args...) CX18_DEBUG(CX18_DBGFLG_FILE, "file", fmt , ## args)
++#define CX18_DEBUG_I2C(fmt, args...) CX18_DEBUG(CX18_DBGFLG_I2C, "i2c", fmt , ## args)
++#define CX18_DEBUG_IRQ(fmt, args...) CX18_DEBUG(CX18_DBGFLG_IRQ, "irq", fmt , ## args)
+
-+ /* Leave the gate closed */
-+ tda10048_i2c_gate_ctrl(&state->frontend, 0);
++#define CX18_DEBUG_HIGH_VOL(x, type, fmt, args...) \
++ do { \
++ if (((x) & cx18_debug) && (cx18_debug & CX18_DBGFLG_HIGHVOL)) \
++ printk(KERN_INFO "cx18%d " type ": " fmt, cx->num , ## args); \
++ } while (0)
++#define CX18_DEBUG_HI_WARN(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_WARN, "warning", fmt , ## args)
++#define CX18_DEBUG_HI_INFO(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_INFO, "info", fmt , ## args)
++#define CX18_DEBUG_HI_API(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_API, "api", fmt , ## args)
++#define CX18_DEBUG_HI_DMA(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_DMA, "dma", fmt , ## args)
++#define CX18_DEBUG_HI_IOCTL(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_IOCTL, "ioctl", fmt , ## args)
++#define CX18_DEBUG_HI_FILE(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_FILE, "file", fmt , ## args)
++#define CX18_DEBUG_HI_I2C(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_I2C, "i2c", fmt , ## args)
++#define CX18_DEBUG_HI_IRQ(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_IRQ, "irq", fmt , ## args)
++
++/* Standard kernel messages */
++#define CX18_ERR(fmt, args...) printk(KERN_ERR "cx18-%d: " fmt, cx->num , ## args)
++#define CX18_WARN(fmt, args...) printk(KERN_WARNING "cx18-%d: " fmt, cx->num , ## args)
++#define CX18_INFO(fmt, args...) printk(KERN_INFO "cx18-%d: " fmt, cx->num , ## args)
++
++/* Values for CX18_API_DEC_PLAYBACK_SPEED mpeg_frame_type_mask parameter: */
++#define MPEG_FRAME_TYPE_IFRAME 1
++#define MPEG_FRAME_TYPE_IFRAME_PFRAME 3
++#define MPEG_FRAME_TYPE_ALL 7
++
++#define CX18_MAX_PGM_INDEX (400)
++
++extern int cx18_debug;
++
++
++struct cx18_options {
++ int megabytes[CX18_MAX_STREAMS]; /* Size in megabytes of each stream */
++ int cardtype; /* force card type on load */
++ int tuner; /* set tuner on load */
++ int radio; /* enable/disable radio */
++};
++
++/* per-buffer bit flags */
++#define CX18_F_B_NEED_BUF_SWAP 0 /* this buffer should be byte swapped */
++
++/* per-stream, s_flags */
++#define CX18_F_S_CLAIMED 3 /* this stream is claimed */
++#define CX18_F_S_STREAMING 4 /* the fw is decoding/encoding this stream */
++#define CX18_F_S_INTERNAL_USE 5 /* this stream is used internally (sliced VBI processing) */
++#define CX18_F_S_STREAMOFF 7 /* signal end of stream EOS */
++#define CX18_F_S_APPL_IO 8 /* this stream is used read/written by an application */
++
++/* per-cx18, i_flags */
++#define CX18_F_I_LOADED_FW 0 /* Loaded the firmware the first time */
++#define CX18_F_I_EOS 4 /* End of encoder stream reached */
++#define CX18_F_I_RADIO_USER 5 /* The radio tuner is selected */
++#define CX18_F_I_ENC_PAUSED 13 /* the encoder is paused */
++#define CX18_F_I_INITED 21 /* set after first open */
++#define CX18_F_I_FAILED 22 /* set if first open failed */
++
++/* These are the VBI types as they appear in the embedded VBI private packets. */
++#define CX18_SLICED_TYPE_TELETEXT_B (1)
++#define CX18_SLICED_TYPE_CAPTION_525 (4)
++#define CX18_SLICED_TYPE_WSS_625 (5)
++#define CX18_SLICED_TYPE_VPS (7)
+
-+ return &state->frontend;
++struct cx18_buffer {
++ struct list_head list;
++ dma_addr_t dma_handle;
++ u32 id;
++ unsigned long b_flags;
++ char *buf;
+
-+error:
-+ kfree(state);
-+ return NULL;
-+}
-+EXPORT_SYMBOL(tda10048_attach);
++ u32 bytesused;
++ u32 readpos;
++};
+
-+static struct dvb_frontend_ops tda10048_ops = {
++struct cx18_queue {
++ struct list_head list;
++ u32 buffers;
++ u32 length;
++ u32 bytesused;
++};
+
-+ .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
-+ },
++struct cx18_dvb {
++ struct dmx_frontend hw_frontend;
++ struct dmx_frontend mem_frontend;
++ struct dmxdev dmxdev;
++ struct dvb_adapter dvb_adapter;
++ struct dvb_demux demux;
++ struct dvb_frontend *fe;
++ struct dvb_net dvbnet;
++ int enabled;
++ int feeding;
++
++ struct mutex feedlock;
+
-+ .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");
++struct cx18; /* forward reference */
++struct cx18_scb; /* forward reference */
+
-+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
++struct cx18_stream {
++ /* These first four fields are always set, even if the stream
++ is not actually created. */
++ struct video_device *v4l2dev; /* NULL when stream not created */
++ struct cx18 *cx; /* for ease of use */
++ const char *name; /* name of the stream */
++ int type; /* stream type */
++ u32 handle; /* task handle */
++ unsigned mdl_offset;
++
++ u32 id;
++ spinlock_t qlock; /* locks access to the queues */
++ unsigned long s_flags; /* status flags, see above */
++ int dma; /* can be PCI_DMA_TODEVICE,
++ PCI_DMA_FROMDEVICE or
++ PCI_DMA_NONE */
++ u64 dma_pts;
++ wait_queue_head_t waitq;
++
++ /* Buffer Stats */
++ u32 buffers;
++ u32 buf_size;
++ u32 buffers_stolen;
++
++ /* Buffer Queues */
++ struct cx18_queue q_free; /* free buffers */
++ struct cx18_queue q_full; /* full buffers */
++ struct cx18_queue q_io; /* waiting for I/O */
+
-+ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
++ /* DVB / Digital Transport */
++ struct cx18_dvb dvb;
++};
+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
++struct cx18_open_id {
++ u32 open_id;
++ int type;
++ enum v4l2_priority prio;
++ struct cx18 *cx;
++};
+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
++/* forward declaration of struct defined in cx18-cards.h */
++struct cx18_card;
+
-+ You 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 CX18_VBI_FRAMES 32
++
++/* VBI data */
++struct vbi_info {
++ u32 enc_size;
++ u32 frame;
++ u8 cc_data_odd[256];
++ u8 cc_data_even[256];
++ int cc_pos;
++ u8 cc_no_update;
++ u8 vps[5];
++ u8 vps_found;
++ int wss;
++ u8 wss_found;
++ u8 wss_no_update;
++ u32 raw_decoder_line_size;
++ u8 raw_decoder_sav_odd_field;
++ u8 raw_decoder_sav_even_field;
++ u32 sliced_decoder_line_size;
++ u8 sliced_decoder_sav_odd_field;
++ u8 sliced_decoder_sav_even_field;
++ struct v4l2_format in;
++ /* convenience pointer to sliced struct in vbi_in union */
++ struct v4l2_sliced_vbi_format *sliced_in;
++ u32 service_set_in;
++ int insert_mpeg;
++
++ /* Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines.
++ One for /dev/vbi0 and one for /dev/vbi8 */
++ struct v4l2_sliced_vbi_data sliced_data[36];
++
++ /* Buffer for VBI data inserted into MPEG stream.
++ The first byte is a dummy byte that's never used.
++ The next 16 bytes contain the MPEG header for the VBI data,
++ the remainder is the actual VBI data.
++ The max size accepted by the MPEG VBI reinsertion turns out
++ to be 1552 bytes, which happens to be 4 + (1 + 42) * (2 * 18) bytes,
++ where 4 is a four byte header, 42 is the max sliced VBI payload, 1 is
++ a single line header byte and 2 * 18 is the number of VBI lines per frame.
++
++ However, it seems that the data must be 1K aligned, so we have to
++ pad the data until the 1 or 2 K boundary.
++
++ This pointer array will allocate 2049 bytes to store each VBI frame. */
++ u8 *sliced_mpeg_data[CX18_VBI_FRAMES];
++ u32 sliced_mpeg_size[CX18_VBI_FRAMES];
++ struct cx18_buffer sliced_mpeg_buf;
++ u32 inserted_frame;
++
++ u32 start[2], count;
++ u32 raw_size;
++ u32 sliced_size;
++};
++
++/* Per cx23418, per I2C bus private algo callback data */
++struct cx18_i2c_algo_callback_data {
++ struct cx18 *cx;
++ int bus_index; /* 0 or 1 for the cx23418's 1st or 2nd I2C bus */
++};
++
++/* Struct to hold info about cx18 cards */
++struct cx18 {
++ int num; /* board number, -1 during init! */
++ char name[8]; /* board name for printk and interrupts (e.g. 'cx180') */
++ struct pci_dev *dev; /* PCI device */
++ const struct cx18_card *card; /* card information */
++ const char *card_name; /* full name of the card */
++ const struct cx18_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */
++ u8 is_50hz;
++ u8 is_60hz;
++ u8 is_out_50hz;
++ u8 is_out_60hz;
++ u8 nof_inputs; /* number of video inputs */
++ u8 nof_audio_inputs; /* number of audio inputs */
++ u16 buffer_id; /* buffer ID counter */
++ u32 v4l2_cap; /* V4L2 capabilities of card */
++ u32 hw_flags; /* Hardware description of the board */
++ unsigned mdl_offset;
++ struct cx18_scb *scb; /* pointer to SCB */
++
++ struct cx18_av_state av_state;
++
++ /* codec settings */
++ struct cx2341x_mpeg_params params;
++ u32 filter_mode;
++ u32 temporal_strength;
++ u32 spatial_strength;
++
++ /* dualwatch */
++ unsigned long dualwatch_jiffies;
++ u16 dualwatch_stereo_mode;
++
++ /* Digitizer type */
++ int digitizer; /* 0x00EF = saa7114 0x00FO = saa7115 0x0106 = mic */
++
++ struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */
++ struct cx18_options options; /* User options */
++ int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */
++ struct cx18_stream streams[CX18_MAX_STREAMS]; /* Stream data */
++ unsigned long i_flags; /* global cx18 flags */
++ atomic_t capturing; /* count number of active capture streams */
++ spinlock_t lock; /* lock access to this struct */
++ int search_pack_header;
++
++ spinlock_t dma_reg_lock; /* lock access to DMA engine registers */
++
++ int open_id; /* incremented each time an open occurs, used as
++ unique ID. Starts at 1, so 0 can be used as
++ uninitialized value in the stream->id. */
++
++ u32 base_addr;
++ struct v4l2_prio_state prio;
++
++ u8 card_rev;
++ void __iomem *enc_mem, *reg_mem;
++
++ struct vbi_info vbi;
++
++ u32 pgm_info_offset;
++ u32 pgm_info_num;
++ u32 pgm_info_write_idx;
++ u32 pgm_info_read_idx;
++ struct v4l2_enc_idx_entry pgm_info[CX18_MAX_PGM_INDEX];
++
++ u64 mpg_data_received;
++ u64 vbi_data_inserted;
++
++ wait_queue_head_t mb_apu_waitq;
++ wait_queue_head_t mb_cpu_waitq;
++ wait_queue_head_t mb_epu_waitq;
++ wait_queue_head_t mb_hpu_waitq;
++ wait_queue_head_t cap_w;
++ /* when the current DMA is finished this queue is woken up */
++ wait_queue_head_t dma_waitq;
++
++ /* i2c */
++ struct i2c_adapter i2c_adap[2];
++ struct i2c_algo_bit_data i2c_algo[2];
++ struct cx18_i2c_algo_callback_data i2c_algo_cb_data[2];
++ struct i2c_client i2c_client[2];
++ struct mutex i2c_bus_lock[2];
++ struct i2c_client *i2c_clients[I2C_CLIENTS_MAX];
++
++ /* v4l2 and User settings */
++
++ /* codec settings */
++ u32 audio_input;
++ u32 active_input;
++ u32 active_output;
++ v4l2_std_id std;
++ v4l2_std_id tuner_std; /* The norm of the tuner (fixed) */
++};
+
-+#ifndef TDA10048_H
-+#define TDA10048_H
++/* Globals */
++extern struct cx18 *cx18_cards[];
++extern int cx18_cards_active;
++extern int cx18_first_minor;
++extern spinlock_t cx18_cards_lock;
++
++/*==============Prototypes==================*/
++
++/* Return non-zero if a signal is pending */
++int cx18_msleep_timeout(unsigned int msecs, int intr);
++
++/* Wait on queue, returns -EINTR if interrupted */
++int cx18_waitq(wait_queue_head_t *waitq);
++
++/* Read Hauppauge eeprom */
++struct tveeprom; /* forward reference */
++void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv);
++
++/* First-open initialization: load firmware, etc. */
++int cx18_init_on_first_open(struct cx18 *cx);
++
++/* This is a PCI post thing, where if the pci register is not read, then
++ the write doesn't always take effect right away. By reading back the
++ register any pending PCI writes will be performed (in order), and so
++ you can be sure that the writes are guaranteed to be done.
++
++ Rarely needed, only in some timing sensitive cases.
++ Apparently if this is not done some motherboards seem
++ to kill the firmware and get into the broken state until computer is
++ rebooted. */
++#define write_sync(val, reg) \
++ do { writel(val, reg); readl(reg); } while (0)
++
++#define read_reg(reg) readl(cx->reg_mem + (reg))
++#define write_reg(val, reg) writel(val, cx->reg_mem + (reg))
++#define write_reg_sync(val, reg) \
++ do { write_reg(val, reg); read_reg(reg); } while (0)
++
++#define read_enc(addr) readl(cx->enc_mem + (u32)(addr))
++#define write_enc(val, addr) writel(val, cx->enc_mem + (u32)(addr))
++#define write_enc_sync(val, addr) \
++ do { write_enc(val, addr); read_enc(addr); } while (0)
++
++#define sw1_irq_enable(val) do { \
++ write_reg(val, SW1_INT_STATUS); \
++ write_reg(read_reg(SW1_INT_ENABLE_PCI) | (val), SW1_INT_ENABLE_PCI); \
++} while (0)
+
-+#include <linux/dvb/frontend.h>
-+#include <linux/firmware.h>
++#define sw1_irq_disable(val) \
++ write_reg(read_reg(SW1_INT_ENABLE_PCI) & ~(val), SW1_INT_ENABLE_PCI);
+
-+struct tda10048_config {
++#define sw2_irq_enable(val) do { \
++ write_reg(val, SW2_INT_STATUS); \
++ write_reg(read_reg(SW2_INT_ENABLE_PCI) | (val), SW2_INT_ENABLE_PCI); \
++} while (0)
+
-+ /* the demodulator's i2c address */
-+ u8 demod_address;
++#define sw2_irq_disable(val) \
++ write_reg(read_reg(SW2_INT_ENABLE_PCI) & ~(val), SW2_INT_ENABLE_PCI);
+
-+ /* serial/parallel output */
-+#define TDA10048_PARALLEL_OUTPUT 0
-+#define TDA10048_SERIAL_OUTPUT 1
-+ u8 output_mode;
++#define setup_page(addr) do { \
++ u32 val = read_reg(0xD000F8) & ~0x1f00; \
++ write_reg(val | (((addr) >> 17) & 0x1f00), 0xD000F8); \
++} while (0)
+
-+#define TDA10048_BULKWRITE_200 200
-+#define TDA10048_BULKWRITE_50 50
-+ u8 fwbulkwritelen;
++#endif /* CX18_DRIVER_H */
+diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c
+new file mode 100644
+index 0000000..65efe69
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-dvb.c
+@@ -0,0 +1,288 @@
++/*
++ * cx18 functions for DVB support
++ *
++ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
+
-+ /* Spectral Inversion */
-+#define TDA10048_INVERSION_OFF 0
-+#define TDA10048_INVERSION_ON 1
-+ u8 inversion;
++#include "cx18-version.h"
++#include "cx18-dvb.h"
++#include "cx18-streams.h"
++#include "cx18-cards.h"
++#include "s5h1409.h"
++
++/* Wait until the MXL500X driver is merged */
++#ifdef HAVE_MXL500X
++#include "mxl500x.h"
++#endif
++
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
++#define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000
++
++#ifdef HAVE_MXL500X
++static struct mxl500x_config hauppauge_hvr1600_tuner = {
++ .delsys = MXL500x_MODE_ATSC,
++ .octf = MXL500x_OCTF_CH,
++ .xtal_freq = 16000000,
++ .iflo_freq = 5380000,
++ .ref_freq = 322800000,
++ .rssi_ena = MXL_RSSI_ENABLE,
++ .addr = 0xC6 >> 1,
+};
+
-+#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)
++static struct s5h1409_config hauppauge_hvr1600_config = {
++ .demod_address = 0x32 >> 1,
++ .output_mode = S5H1409_SERIAL_OUTPUT,
++ .gpio = S5H1409_GPIO_ON,
++ .qam_if = 44000,
++ .inversion = S5H1409_INVERSION_OFF,
++ .status_mode = S5H1409_DEMODLOCKING,
++ .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
++
++};
++#endif
++
++static int dvb_register(struct cx18_stream *stream);
++
++/* Kernel DVB framework calls this when the feed needs to start.
++ * The CX18 framework should enable the transport DMA handling
++ * and queue processing.
++ */
++static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
+{
-+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-+ return NULL;
-+}
-+#endif /* CONFIG_DVB_TDA10048 */
++ struct dvb_demux *demux = feed->demux;
++ struct cx18_stream *stream = (struct cx18_stream *) demux->priv;
++ struct cx18 *cx = stream->cx;
++ int ret = -EINVAL;
++ u32 v;
+
-+#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 */
++ CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n",
++ feed->pid, feed->index);
++ switch (cx->card->type) {
++ case CX18_CARD_HVR_1600_ESMT:
++ case CX18_CARD_HVR_1600_SAMSUNG:
++ v = read_reg(CX18_REG_DMUX_NUM_PORT_0_CONTROL);
++ v |= 0x00400000; /* Serial Mode */
++ v |= 0x00002000; /* Data Length - Byte */
++ v |= 0x00010000; /* Error - Polarity */
++ v |= 0x00020000; /* Error - Passthru */
++ v |= 0x000c0000; /* Error - Ignore */
++ write_reg(v, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
++ break;
+
-+ /* 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 */
++ default:
++ /* Assumption - Parallel transport - Signalling
++ * undefined or default.
++ */
++ break;
+ }
-+ tda10086_write_mask(state, 0x55, 0x20, 0x00); /* powerup PLL */
+
-+ /* setup TS interface */
- tda10086_write_byte(state, 0x11, 0x81);
- tda10086_write_byte(state, 0x12, 0x81);
-- tda10086_write_byte(state, 0x19, 0x40); // parallel mode A + MSBFIRST
-- tda10086_write_byte(state, 0x56, 0x80); // powerdown WPLL - unused in the mode we use
-- tda10086_write_byte(state, 0x57, 0x08); // bypass WPLL - unused in the mode we use
-+ tda10086_write_byte(state, 0x19, 0x40); /* parallel mode A + MSBFIRST */
-+ tda10086_write_byte(state, 0x56, 0x80); /* powerdown WPLL - unused in the mode we use */
-+ tda10086_write_byte(state, 0x57, 0x08); /* bypass WPLL - unused in the mode we use */
- tda10086_write_byte(state, 0x10, 0x2a);
-
-- // setup ADC
-- tda10086_write_byte(state, 0x58, 0x61); // ADC setup
-- tda10086_write_mask(state, 0x58, 0x01, 0x00); // powerup ADC
-+ /* setup ADC */
-+ tda10086_write_byte(state, 0x58, 0x61); /* ADC setup */
-+ tda10086_write_mask(state, 0x58, 0x01, 0x00); /* powerup ADC */
-
-- // setup AGC
-+ /* setup AGC */
- tda10086_write_byte(state, 0x05, 0x0B);
- tda10086_write_byte(state, 0x37, 0x63);
-- tda10086_write_byte(state, 0x3f, 0x0a); // NOTE: flydvb varies it
-+ tda10086_write_byte(state, 0x3f, 0x0a); /* NOTE: flydvb varies it */
- tda10086_write_byte(state, 0x40, 0x64);
- tda10086_write_byte(state, 0x41, 0x4f);
- tda10086_write_byte(state, 0x42, 0x43);
-
-- // setup viterbi
-- tda10086_write_byte(state, 0x1a, 0x11); // VBER 10^6, DVB, QPSK
-+ /* setup viterbi */
-+ tda10086_write_byte(state, 0x1a, 0x11); /* VBER 10^6, DVB, QPSK */
-
-- // setup carrier recovery
-+ /* setup carrier recovery */
- tda10086_write_byte(state, 0x3d, 0x80);
-
-- // setup SEC
-- tda10086_write_byte(state, 0x36, t22k_off); // all SEC off, 22k tone
-- tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000))); // } tone frequency
-- tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8); // }
-+ /* setup SEC */
-+ tda10086_write_byte(state, 0x36, t22k_off); /* all SEC off, 22k tone */
-+ tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000)));
-+ tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8);
-
- return 0;
- }
-@@ -173,7 +178,7 @@ static void tda10086_diseqc_wait(struct tda10086_state *state)
- unsigned long timeout = jiffies + msecs_to_jiffies(200);
- while (!(tda10086_read_byte(state, 0x50) & 0x01)) {
- if(time_after(jiffies, timeout)) {
-- printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__);
-+ printk("%s: diseqc queue not ready, command may be lost.\n", __func__);
- break;
- }
- msleep(10);
-@@ -185,7 +190,7 @@ static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
- struct tda10086_state* state = fe->demodulator_priv;
- u8 t22k_off = 0x80;
-
-- dprintk ("%s\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
-
- if (state->config->diseqc_tone)
- t22k_off = 0;
-@@ -211,7 +216,7 @@ static int tda10086_send_master_cmd (struct dvb_frontend* fe,
- u8 oldval;
- u8 t22k_off = 0x80;
-
-- dprintk ("%s\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
-
- if (state->config->diseqc_tone)
- t22k_off = 0;
-@@ -239,7 +244,7 @@ static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minic
- u8 oldval = tda10086_read_byte(state, 0x36);
- u8 t22k_off = 0x80;
-
-- dprintk ("%s\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
-
- if (state->config->diseqc_tone)
- t22k_off = 0;
-@@ -266,7 +271,7 @@ static int tda10086_set_inversion(struct tda10086_state *state,
- {
- u8 invval = 0x80;
-
-- dprintk ("%s %i %i\n", __FUNCTION__, fe_params->inversion, state->config->invert);
-+ dprintk ("%s %i %i\n", __func__, fe_params->inversion, state->config->invert);
-
- switch(fe_params->inversion) {
- case INVERSION_OFF:
-@@ -300,9 +305,9 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state,
- u32 bdri;
- u32 symbol_rate = fe_params->u.qpsk.symbol_rate;
-
-- dprintk ("%s %i\n", __FUNCTION__, symbol_rate);
-+ dprintk ("%s %i\n", __func__, symbol_rate);
-
-- // setup the decimation and anti-aliasing filters..
-+ /* setup the decimation and anti-aliasing filters.. */
- if (symbol_rate < (u32) (SACLK * 0.0137)) {
- dfn=4;
- afs=1;
-@@ -339,13 +344,13 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state,
- byp=1;
- }
-
-- // calculate BDR
-+ /* calculate BDR */
- big = (1ULL<<21) * ((u64) symbol_rate/1000ULL) * (1ULL<<dfn);
- big += ((SACLK/1000ULL)-1ULL);
- do_div(big, (SACLK/1000ULL));
- bdr = big & 0xfffff;
-
-- // calculate BDRI
-+ /* calculate BDRI */
- tmp = (1<<dfn)*(symbol_rate/1000);
- bdri = ((32 * (SACLK/1000)) + (tmp-1)) / tmp;
-
-@@ -366,7 +371,7 @@ static int tda10086_set_fec(struct tda10086_state *state,
- {
- u8 fecval;
-
-- dprintk ("%s %i\n", __FUNCTION__, fe_params->u.qpsk.fec_inner);
-+ dprintk ("%s %i\n", __func__, fe_params->u.qpsk.fec_inner);
-
- switch(fe_params->u.qpsk.fec_inner) {
- case FEC_1_2:
-@@ -412,13 +417,13 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
- u32 freq = 0;
- int freqoff;
-
-- dprintk ("%s\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
-
-- // modify parameters for tuning
-+ /* modify parameters for tuning */
- tda10086_write_byte(state, 0x02, 0x35);
- state->has_lock = false;
-
-- // set params
-+ /* set params */
- if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, fe_params);
- if (fe->ops.i2c_gate_ctrl)
-@@ -430,7 +435,7 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
- fe->ops.i2c_gate_ctrl(fe, 0);
- }
-
-- // calcluate the frequency offset (in *Hz* not kHz)
-+ /* calcluate the frequency offset (in *Hz* not kHz) */
- freqoff = fe_params->frequency - freq;
- freqoff = ((1<<16) * freqoff) / (SACLK/1000);
- tda10086_write_byte(state, 0x3d, 0x80 | ((freqoff >> 8) & 0x7f));
-@@ -443,7 +448,7 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
- if ((ret = tda10086_set_fec(state, fe_params)) < 0)
- return ret;
-
-- // soft reset + disable TS output until lock
-+ /* soft reset + disable TS output until lock */
- tda10086_write_mask(state, 0x10, 0x40, 0x40);
- tda10086_write_mask(state, 0x00, 0x01, 0x00);
-
-@@ -459,13 +464,13 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
- int tmp;
- u64 tmp64;
-
-- dprintk ("%s\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
-
-- // check for invalid symbol rate
-+ /* check for invalid symbol rate */
- if (fe_params->u.qpsk.symbol_rate < 500000)
- return -EINVAL;
-
-- // calculate the updated frequency (note: we convert from Hz->kHz)
-+ /* calculate the updated frequency (note: we convert from Hz->kHz) */
- tmp64 = tda10086_read_byte(state, 0x52);
- tmp64 |= (tda10086_read_byte(state, 0x51) << 8);
- if (tmp64 & 0x8000)
-@@ -474,7 +479,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
- do_div(tmp64, (1ULL<<15) * (1ULL<<1));
- fe_params->frequency = (int) state->frequency + (int) tmp64;
-
-- // the inversion
-+ /* the inversion */
- val = tda10086_read_byte(state, 0x0c);
- if (val & 0x80) {
- switch(val & 0x40) {
-@@ -505,7 +510,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
- }
- }
-
-- // calculate the updated symbol rate
-+ /* calculate the updated symbol rate */
- tmp = tda10086_read_byte(state, 0x1d);
- if (tmp & 0x80)
- tmp |= 0xffffff00;
-@@ -513,7 +518,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
- tmp = ((state->symbol_rate/1000) * tmp) / (1000000/1000);
- fe_params->u.qpsk.symbol_rate = state->symbol_rate + tmp;
-
-- // the FEC
-+ /* the FEC */
- val = (tda10086_read_byte(state, 0x0d) & 0x70) >> 4;
- switch(val) {
- case 0x00:
-@@ -550,7 +555,7 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
- struct tda10086_state* state = fe->demodulator_priv;
- u8 val;
-
-- dprintk ("%s\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
-
- val = tda10086_read_byte(state, 0x0e);
- *fe_status = 0;
-@@ -566,7 +571,7 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
- *fe_status |= FE_HAS_LOCK;
- if (!state->has_lock) {
- state->has_lock = true;
-- // modify parameters for stable reception
-+ /* modify parameters for stable reception */
- tda10086_write_byte(state, 0x02, 0x00);
- }
- }
-@@ -579,7 +584,7 @@ static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
- struct tda10086_state* state = fe->demodulator_priv;
- u8 _str;
-
-- dprintk ("%s\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
-
- _str = 0xff - tda10086_read_byte(state, 0x43);
- *signal = (_str << 8) | _str;
-@@ -592,7 +597,7 @@ static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr)
- struct tda10086_state* state = fe->demodulator_priv;
- u8 _snr;
-
-- dprintk ("%s\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
-
- _snr = 0xff - tda10086_read_byte(state, 0x1c);
- *snr = (_snr << 8) | _snr;
-@@ -604,12 +609,12 @@ static int tda10086_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
- {
- struct tda10086_state* state = fe->demodulator_priv;
-
-- dprintk ("%s\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
-
-- // read it
-+ /* read it */
- *ucblocks = tda10086_read_byte(state, 0x18) & 0x7f;
-
-- // reset counter
-+ /* reset counter */
- tda10086_write_byte(state, 0x18, 0x00);
- tda10086_write_byte(state, 0x18, 0x80);
-
-@@ -620,9 +625,9 @@ static int tda10086_read_ber(struct dvb_frontend* fe, u32* ber)
- {
- struct tda10086_state* state = fe->demodulator_priv;
-
-- dprintk ("%s\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
-
-- // read it
-+ /* read it */
- *ber = 0;
- *ber |= tda10086_read_byte(state, 0x15);
- *ber |= tda10086_read_byte(state, 0x16) << 8;
-@@ -635,7 +640,7 @@ static int tda10086_sleep(struct dvb_frontend* fe)
- {
- struct tda10086_state* state = fe->demodulator_priv;
-
-- dprintk ("%s\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
-
- tda10086_write_mask(state, 0x00, 0x08, 0x08);
-
-@@ -646,7 +651,7 @@ static int tda10086_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
- {
- struct tda10086_state* state = fe->demodulator_priv;
-
-- dprintk ("%s\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
-
- if (enable) {
- tda10086_write_mask(state, 0x00, 0x10, 0x10);
-@@ -737,7 +742,7 @@ struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
- {
- struct tda10086_state *state;
-
-- dprintk ("%s\n", __FUNCTION__);
-+ dprintk ("%s\n", __func__);
-
- /* allocate memory for the internal state */
- state = kmalloc(sizeof(struct tda10086_state), GFP_KERNEL);
-diff --git a/drivers/media/dvb/frontends/tda10086.h b/drivers/media/dvb/frontends/tda10086.h
-index eeceaee..61148c5 100644
---- a/drivers/media/dvb/frontends/tda10086.h
-+++ b/drivers/media/dvb/frontends/tda10086.h
-@@ -26,6 +26,11 @@
- #include <linux/dvb/frontend.h>
- #include <linux/firmware.h>
-
-+enum tda10086_xtal {
-+ TDA10086_XTAL_16M,
-+ TDA10086_XTAL_4M
-+};
++ if (!demux->dmx.frontend)
++ return -EINVAL;
+
- 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;
++ if (stream) {
++ mutex_lock(&stream->dvb.feedlock);
++ if (stream->dvb.feeding++ == 0) {
++ CX18_DEBUG_INFO("Starting Transport DMA\n");
++ ret = cx18_start_v4l2_encode_stream(stream);
++ } else
++ ret = 0;
++ mutex_unlock(&stream->dvb.feedlock);
++ }
+
-+ /* 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)
++ return ret;
++}
++
++/* Kernel DVB framework calls this when the feed needs to stop. */
++static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed)
++{
++ struct dvb_demux *demux = feed->demux;
++ struct cx18_stream *stream = (struct cx18_stream *)demux->priv;
++ struct cx18 *cx = stream->cx;
++ int ret = -EINVAL;
++
++ CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n",
++ feed->pid, feed->index);
++
++ if (stream) {
++ mutex_lock(&stream->dvb.feedlock);
++ if (--stream->dvb.feeding == 0) {
++ CX18_DEBUG_INFO("Stopping Transport DMA\n");
++ ret = cx18_stop_v4l2_encode_stream(stream, 0);
++ } else
++ ret = 0;
++ mutex_unlock(&stream->dvb.feedlock);
++ }
++
++ return ret;
++}
++
++int cx18_dvb_register(struct cx18_stream *stream)
+{
-+ struct tda18271_priv *priv = fe->tuner_priv;
-+ unsigned char *regs = priv->tda18271_regs;
++ struct cx18 *cx = stream->cx;
++ struct cx18_dvb *dvb = &stream->dvb;
++ struct dvb_adapter *dvb_adapter;
++ struct dvb_demux *dvbdemux;
++ struct dmx_demux *dmx;
++ int ret;
+
-+ int r_cp = (pll == TDA18271_CAL_PLL) ? R_EB7 : R_EB4;
++ if (!dvb)
++ return -EINVAL;
+
-+ regs[r_cp] &= ~0x20;
-+ regs[r_cp] |= ((force & 1) << 5);
-+ tda18271_write_regs(fe, r_cp, 1);
++ ret = dvb_register_adapter(&dvb->dvb_adapter,
++ CX18_DRIVER_NAME,
++ THIS_MODULE, &cx->dev->dev, adapter_nr);
++ if (ret < 0)
++ goto err_out;
+
-+ return 0;
++ dvb_adapter = &dvb->dvb_adapter;
++
++ dvbdemux = &dvb->demux;
++
++ dvbdemux->priv = (void *)stream;
++
++ dvbdemux->filternum = 256;
++ dvbdemux->feednum = 256;
++ dvbdemux->start_feed = cx18_dvb_start_feed;
++ dvbdemux->stop_feed = cx18_dvb_stop_feed;
++ dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
++ DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
++ ret = dvb_dmx_init(dvbdemux);
++ if (ret < 0)
++ goto err_dvb_unregister_adapter;
++
++ dmx = &dvbdemux->dmx;
++
++ dvb->hw_frontend.source = DMX_FRONTEND_0;
++ dvb->mem_frontend.source = DMX_MEMORY_FE;
++ dvb->dmxdev.filternum = 256;
++ dvb->dmxdev.demux = dmx;
++
++ ret = dvb_dmxdev_init(&dvb->dmxdev, dvb_adapter);
++ if (ret < 0)
++ goto err_dvb_dmx_release;
++
++ ret = dmx->add_frontend(dmx, &dvb->hw_frontend);
++ if (ret < 0)
++ goto err_dvb_dmxdev_release;
++
++ ret = dmx->add_frontend(dmx, &dvb->mem_frontend);
++ if (ret < 0)
++ goto err_remove_hw_frontend;
++
++ ret = dmx->connect_frontend(dmx, &dvb->hw_frontend);
++ if (ret < 0)
++ goto err_remove_mem_frontend;
++
++ ret = dvb_register(stream);
++ if (ret < 0)
++ goto err_disconnect_frontend;
++
++ dvb_net_init(dvb_adapter, &dvb->dvbnet, dmx);
++
++ CX18_INFO("DVB Frontend registered\n");
++ mutex_init(&dvb->feedlock);
++ dvb->enabled = 1;
++ return ret;
++
++err_disconnect_frontend:
++ dmx->disconnect_frontend(dmx);
++err_remove_mem_frontend:
++ dmx->remove_frontend(dmx, &dvb->mem_frontend);
++err_remove_hw_frontend:
++ dmx->remove_frontend(dmx, &dvb->hw_frontend);
++err_dvb_dmxdev_release:
++ dvb_dmxdev_release(&dvb->dmxdev);
++err_dvb_dmx_release:
++ dvb_dmx_release(dvbdemux);
++err_dvb_unregister_adapter:
++ dvb_unregister_adapter(dvb_adapter);
++err_out:
++ return ret;
+}
+
- 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;
++void cx18_dvb_unregister(struct cx18_stream *stream)
++{
++ struct cx18 *cx = stream->cx;
++ struct cx18_dvb *dvb = &stream->dvb;
++ struct dvb_adapter *dvb_adapter;
++ struct dvb_demux *dvbdemux;
++ struct dmx_demux *dmx;
++
++ CX18_INFO("unregister DVB\n");
++
++ dvb_adapter = &dvb->dvb_adapter;
++ dvbdemux = &dvb->demux;
++ dmx = &dvbdemux->dmx;
++
++ dmx->close(dmx);
++ dvb_net_release(&dvb->dvbnet);
++ dmx->remove_frontend(dmx, &dvb->mem_frontend);
++ dmx->remove_frontend(dmx, &dvb->hw_frontend);
++ dvb_dmxdev_release(&dvb->dmxdev);
++ dvb_dmx_release(dvbdemux);
++ dvb_unregister_frontend(dvb->fe);
++ dvb_frontend_detach(dvb->fe);
++ dvb_unregister_adapter(dvb_adapter);
++}
+
-+ /* 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 */
++/* 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.
++ */
++static int dvb_register(struct cx18_stream *stream)
++{
++ struct cx18_dvb *dvb = &stream->dvb;
++ struct cx18 *cx = stream->cx;
++ int ret = 0;
++
++ switch (cx->card->type) {
++/* Wait until the MXL500X driver is merged */
++#ifdef HAVE_MXL500X
++ case CX18_CARD_HVR_1600_ESMT:
++ case CX18_CARD_HVR_1600_SAMSUNG:
++ dvb->fe = dvb_attach(s5h1409_attach,
++ &hauppauge_hvr1600_config,
++ &cx->i2c_adap[0]);
++ if (dvb->fe != NULL) {
++ dvb_attach(mxl500x_attach, dvb->fe,
++ &hauppauge_hvr1600_tuner,
++ &cx->i2c_adap[0]);
++ ret = 0;
++ }
+ break;
-+ case TDA18271_SLAVE:
-+ regs[R_EB1] &= ~0x04; /* cal vco */
++#endif
++ default:
++ /* No Digital Tv Support */
+ 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;
++ if (dvb->fe == NULL) {
++ CX18_ERR("frontend initialization failed\n");
++ return -1;
+ }
-
- 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)
-+/* ------------------------------------------------------------------ */
++ ret = dvb_register_frontend(&dvb->dvb_adapter, dvb->fe);
++ if (ret < 0) {
++ if (dvb->fe->ops.release)
++ dvb->fe->ops.release(dvb->fe);
++ return ret;
++ }
+
-+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;
++ return ret;
+}
-
-- 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 */
+diff --git a/drivers/media/video/cx18/cx18-dvb.h b/drivers/media/video/cx18/cx18-dvb.h
+new file mode 100644
+index 0000000..d6a6ccd
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-dvb.h
+@@ -0,0 +1,25 @@
++/*
++ * cx18 functions for DVB support
++ *
++ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include "cx18-driver.h"
++
++int cx18_dvb_register(struct cx18_stream *stream);
++void cx18_dvb_unregister(struct cx18_stream *stream);
+diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
+new file mode 100644
+index 0000000..6930306
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-fileops.c
+@@ -0,0 +1,711 @@
++/*
++ * cx18 file operation functions
++ *
++ * Derived from ivtv-fileops.c
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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 "cx18-driver.h"
++#include "cx18-fileops.h"
++#include "cx18-i2c.h"
++#include "cx18-queue.h"
++#include "cx18-vbi.h"
++#include "cx18-audio.h"
++#include "cx18-mailbox.h"
++#include "cx18-scb.h"
++#include "cx18-streams.h"
++#include "cx18-controls.h"
++#include "cx18-ioctl.h"
++#include "cx18-cards.h"
++
++/* This function tries to claim the stream for a specific file descriptor.
++ If no one else is using this stream then the stream is claimed and
++ associated VBI streams are also automatically claimed.
++ Possible error returns: -EBUSY if someone else has claimed
++ the stream or 0 on success. */
++int cx18_claim_stream(struct cx18_open_id *id, int type)
++{
++ struct cx18 *cx = id->cx;
++ struct cx18_stream *s = &cx->streams[type];
++ struct cx18_stream *s_vbi;
++ int vbi_type;
++
++ if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
++ /* someone already claimed this stream */
++ if (s->id == id->open_id) {
++ /* yes, this file descriptor did. So that's OK. */
++ return 0;
++ }
++ if (s->id == -1 && type == CX18_ENC_STREAM_TYPE_VBI) {
++ /* VBI is handled already internally, now also assign
++ the file descriptor to this stream for external
++ reading of the stream. */
++ s->id = id->open_id;
++ CX18_DEBUG_INFO("Start Read VBI\n");
++ return 0;
++ }
++ /* someone else is using this stream already */
++ CX18_DEBUG_INFO("Stream %d is busy\n", type);
++ return -EBUSY;
++ }
++ s->id = id->open_id;
++
++ /* CX18_DEC_STREAM_TYPE_MPG needs to claim CX18_DEC_STREAM_TYPE_VBI,
++ CX18_ENC_STREAM_TYPE_MPG needs to claim CX18_ENC_STREAM_TYPE_VBI
++ (provided VBI insertion is on and sliced VBI is selected), for all
++ other streams we're done */
++ if (type == CX18_ENC_STREAM_TYPE_MPG &&
++ cx->vbi.insert_mpeg && cx->vbi.sliced_in->service_set) {
++ vbi_type = CX18_ENC_STREAM_TYPE_VBI;
++ } else {
++ return 0;
++ }
++ s_vbi = &cx->streams[vbi_type];
++
++ set_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags);
++
++ /* mark that it is used internally */
++ set_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags);
+ 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);
++/* This function releases a previously claimed stream. It will take into
++ account associated VBI streams. */
++void cx18_release_stream(struct cx18_stream *s)
++{
++ struct cx18 *cx = s->cx;
++ struct cx18_stream *s_vbi;
+
-+ tda18271_init(fe);
++ s->id = -1;
++ if (s->type == CX18_ENC_STREAM_TYPE_VBI &&
++ test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) {
++ /* this stream is still in use internally */
++ return;
++ }
++ if (!test_and_clear_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
++ CX18_DEBUG_WARN("Release stream %s not in use!\n", s->name);
++ return;
++ }
+
-+ 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);
++ cx18_flush_queues(s);
+
-+ mutex_unlock(&priv->lock);
++ /* CX18_ENC_STREAM_TYPE_MPG needs to release CX18_ENC_STREAM_TYPE_VBI,
++ for all other streams we're done */
++ if (s->type == CX18_ENC_STREAM_TYPE_MPG)
++ s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
++ else
++ return;
+
-+ 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;
++ /* clear internal use flag */
++ if (!test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags)) {
++ /* was already cleared */
++ return;
++ }
++ if (s_vbi->id != -1) {
++ /* VBI stream still claimed by a file descriptor */
++ return;
++ }
++ clear_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags);
++ cx18_flush_queues(s_vbi);
++}
+
-+ /* allow dvb driver to override i2c gate setting */
-+ if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG))
-+ priv->gate = cfg->gate;
-+ break;
- }
-
- /* override default std map with values in config struct */
-@@ -1200,7 +1128,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
- memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
- sizeof(struct dvb_tuner_ops));
-
-- if (tda18271_debug & DBG_MAP)
-+ if (tda18271_debug & (DBG_MAP | DBG_ADV))
- tda18271_dump_std_map(fe);
-
- return fe;
-@@ -1214,7 +1142,7 @@ EXPORT_SYMBOL_GPL(tda18271_attach);
- MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver");
- MODULE_AUTHOR("Michael Krufky <mkrufky at linuxtv.org>");
- MODULE_LICENSE("GPL");
--MODULE_VERSION("0.2");
-+MODULE_VERSION("0.3");
-
- /*
- * Overrides for Emacs so that we follow Linus's tabbing style.
-diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h
-index 7b939a5..2bc5eb3 100644
---- a/drivers/media/dvb/frontends/tda18271-priv.h
-+++ b/drivers/media/dvb/frontends/tda18271-priv.h
-@@ -24,6 +24,7 @@
- #include <linux/kernel.h>
- #include <linux/types.h>
- #include <linux/mutex.h>
-+#include "tuner-i2c.h"
- #include "tda18271.h"
-
- #define R_ID 0x00 /* ID byte */
-@@ -85,6 +86,11 @@ struct tda18271_rf_tracking_filter_cal {
- int rf_b2;
- };
-
-+enum tda18271_pll {
-+ TDA18271_MAIN_PLL,
-+ TDA18271_CAL_PLL,
-+};
++static void cx18_dualwatch(struct cx18 *cx)
++{
++ struct v4l2_tuner vt;
++ u16 new_bitmap;
++ u16 new_stereo_mode;
++ const u16 stereo_mask = 0x0300;
++ const u16 dual = 0x0200;
++
++ new_stereo_mode = cx->params.audio_properties & stereo_mask;
++ memset(&vt, 0, sizeof(vt));
++ cx18_call_i2c_clients(cx, VIDIOC_G_TUNER, &vt);
++ if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 &&
++ (vt.rxsubchans & V4L2_TUNER_SUB_LANG2))
++ new_stereo_mode = dual;
+
- 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;
++ if (new_stereo_mode == cx->dualwatch_stereo_mode)
++ return;
+
-+ /* 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,
-+};
++ new_bitmap = new_stereo_mode | (cx->params.audio_properties & ~stereo_mask);
+
- 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;
++ CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. new audio_bitmask=0x%ux\n",
++ cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap);
+
- /* use i2c gate provided by analog or digital demod */
- enum tda18271_i2c_gate gate;
++ if (cx18_vapi(cx, CX18_CPU_SET_AUDIO_PARAMETERS, 2,
++ cx18_find_handle(cx), new_bitmap) == 0) {
++ cx->dualwatch_stereo_mode = new_stereo_mode;
++ return;
++ }
++ CX18_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
++}
+
-+ /* 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)
++static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, int *err)
+{
-+ 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) };
++ struct cx18 *cx = s->cx;
++ struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
++ struct cx18_buffer *buf;
++ DEFINE_WAIT(wait);
+
-+ dprintk("%s:\n", __func__);
-+ if (fe->ops.i2c_gate_ctrl)
-+ fe->ops.i2c_gate_ctrl(fe, 1);
++ *err = 0;
++ while (1) {
++ if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
+
-+ i2c_transfer(priv->i2c_adap, &msg, 1);
++ if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) {
++ cx->dualwatch_jiffies = jiffies;
++ cx18_dualwatch(cx);
++ }
++ if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
++ !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
++ while ((buf = cx18_dequeue(s_vbi, &s_vbi->q_full))) {
++ /* byteswap and process VBI data */
++/* cx18_process_vbi_data(cx, buf, s_vbi->dma_pts, s_vbi->type); */
++ cx18_enqueue(s_vbi, buf, &s_vbi->q_free);
++ }
++ }
++ buf = &cx->vbi.sliced_mpeg_buf;
++ if (buf->readpos != buf->bytesused)
++ return buf;
++ }
+
-+ if (fe->ops.i2c_gate_ctrl)
-+ fe->ops.i2c_gate_ctrl(fe, 0);
++ /* do we have leftover data? */
++ buf = cx18_dequeue(s, &s->q_io);
++ if (buf)
++ return buf;
+
-+ if (priv->cfg && priv->cfg->sleep)
-+ priv->cfg->sleep(fe);
++ /* do we have new data? */
++ buf = cx18_dequeue(s, &s->q_full);
++ if (buf) {
++ if (!test_and_clear_bit(CX18_F_B_NEED_BUF_SWAP,
++ &buf->b_flags))
++ return buf;
++ if (s->type == CX18_ENC_STREAM_TYPE_MPG)
++ /* byteswap MPG data */
++ cx18_buf_swap(buf);
++ else {
++ /* byteswap and process VBI data */
++ cx18_process_vbi_data(cx, buf,
++ s->dma_pts, s->type);
++ }
++ return buf;
++ }
+
-+ return 0;
++ /* return if end of stream */
++ if (!test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
++ CX18_DEBUG_INFO("EOS %s\n", s->name);
++ return NULL;
++ }
++
++ /* return if file was opened with O_NONBLOCK */
++ if (non_block) {
++ *err = -EAGAIN;
++ return NULL;
++ }
++
++ /* wait for more data to arrive */
++ prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
++ /* New buffers might have become available before we were added
++ to the waitqueue */
++ if (!s->q_full.buffers)
++ schedule();
++ finish_wait(&s->waitq, &wait);
++ if (signal_pending(current)) {
++ /* return if a signal was received */
++ CX18_DEBUG_INFO("User stopped %s\n", s->name);
++ *err = -EINTR;
++ return NULL;
++ }
++ }
+}
+
-+static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
-+ struct analog_parameters *params)
++static void cx18_setup_sliced_vbi_buf(struct cx18 *cx)
+{
-+ 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) };
++ int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
+
-+ 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;
++ cx->vbi.sliced_mpeg_buf.buf = cx->vbi.sliced_mpeg_data[idx];
++ cx->vbi.sliced_mpeg_buf.bytesused = cx->vbi.sliced_mpeg_size[idx];
++ cx->vbi.sliced_mpeg_buf.readpos = 0;
++}
++
++static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
++ struct cx18_buffer *buf, char __user *ubuf, size_t ucount)
++{
++ struct cx18 *cx = s->cx;
++ size_t len = buf->bytesused - buf->readpos;
++
++ if (len > ucount)
++ len = ucount;
++ if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG &&
++ cx->vbi.sliced_in->service_set && buf != &cx->vbi.sliced_mpeg_buf) {
++ const char *start = buf->buf + buf->readpos;
++ const char *p = start + 1;
++ const u8 *q;
++ u8 ch = cx->search_pack_header ? 0xba : 0xe0;
++ int stuffing, i;
++
++ while (start + len > p) {
++ q = memchr(p, 0, start + len - p);
++ if (q == NULL)
++ break;
++ p = q + 1;
++ if ((char *)q + 15 >= buf->buf + buf->bytesused ||
++ q[1] != 0 || q[2] != 1 || q[3] != ch)
++ continue;
++ if (!cx->search_pack_header) {
++ if ((q[6] & 0xc0) != 0x80)
++ continue;
++ if (((q[7] & 0xc0) == 0x80 &&
++ (q[9] & 0xf0) == 0x20) ||
++ ((q[7] & 0xc0) == 0xc0 &&
++ (q[9] & 0xf0) == 0x30)) {
++ ch = 0xba;
++ cx->search_pack_header = 1;
++ p = q + 9;
++ }
++ continue;
++ }
++ stuffing = q[13] & 7;
++ /* all stuffing bytes must be 0xff */
++ for (i = 0; i < stuffing; i++)
++ if (q[14 + i] != 0xff)
++ break;
++ if (i == stuffing &&
++ (q[4] & 0xc4) == 0x44 &&
++ (q[12] & 3) == 3 &&
++ q[14 + stuffing] == 0 &&
++ q[15 + stuffing] == 0 &&
++ q[16 + stuffing] == 1) {
++ cx->search_pack_header = 0;
++ len = (char *)q - start;
++ cx18_setup_sliced_vbi_buf(cx);
++ break;
++ }
+ }
-+ 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;
+ }
++ if (copy_to_user(ubuf, (u8 *)buf->buf + buf->readpos, len)) {
++ CX18_DEBUG_WARN("copy %zd bytes to user failed for %s\n",
++ len, s->name);
++ return -EFAULT;
++ }
++ buf->readpos += len;
++ if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
++ buf != &cx->vbi.sliced_mpeg_buf)
++ cx->mpg_data_received += len;
++ return len;
+}
+
- 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__);
++static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
++ size_t tot_count, int non_block)
++{
++ struct cx18 *cx = s->cx;
++ size_t tot_written = 0;
++ int single_frame = 0;
++
++ if (atomic_read(&cx->capturing) == 0 && s->id == -1) {
++ /* shouldn't happen */
++ CX18_DEBUG_WARN("Stream %s not initialized before read\n",
++ s->name);
++ return -EIO;
++ }
+
-+ 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);
++ /* Each VBI buffer is one frame, the v4l2 API says that for VBI the
++ frames should arrive one-by-one, so make sure we never output more
++ than one VBI frame at a time */
++ if (s->type == CX18_ENC_STREAM_TYPE_VBI &&
++ cx->vbi.sliced_in->service_set)
++ single_frame = 1;
+
- #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);
++ for (;;) {
++ struct cx18_buffer *buf;
++ int rc;
+
- 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);
++ buf = cx18_get_buffer(s, non_block, &rc);
++ /* if there is no data available... */
++ if (buf == NULL) {
++ /* if we got data, then return that regardless */
++ if (tot_written)
++ break;
++ /* EOS condition */
++ if (rc == 0) {
++ clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
++ clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
++ cx18_release_stream(s);
++ }
++ /* set errno */
++ return rc;
++ }
+
- /****************************************************************************
- * 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) };
++ rc = cx18_copy_buf_to_user(s, buf, ubuf + tot_written,
++ tot_count - tot_written);
++
++ if (buf != &cx->vbi.sliced_mpeg_buf) {
++ if (buf->readpos == buf->bytesused) {
++ cx18_buf_sync_for_device(s, buf);
++ cx18_enqueue(s, buf, &s->q_free);
++ cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5,
++ s->handle,
++ (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
++ 1, buf->id, s->buf_size);
++ } else
++ cx18_enqueue(s, buf, &s->q_io);
++ } else if (buf->readpos == buf->bytesused) {
++ int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
++
++ cx->vbi.sliced_mpeg_size[idx] = 0;
++ cx->vbi.inserted_frame++;
++ cx->vbi_data_inserted += buf->bytesused;
++ }
++ if (rc < 0)
++ return rc;
++ tot_written += rc;
++
++ if (tot_written == tot_count || single_frame)
++ break;
++ }
++ return tot_written;
++}
++
++static ssize_t cx18_read_pos(struct cx18_stream *s, char __user *ubuf,
++ size_t count, loff_t *pos, int non_block)
++{
++ ssize_t rc = count ? cx18_read(s, ubuf, count, non_block) : 0;
++ struct cx18 *cx = s->cx;
+
-+ 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,
-+};
++ CX18_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc);
++ if (rc > 0)
++ pos += rc;
++ return rc;
++}
+
-+static u8 tuner_address_grundig_29504_401_activy = 0x60;
++int cx18_start_capture(struct cx18_open_id *id)
++{
++ struct cx18 *cx = id->cx;
++ struct cx18_stream *s = &cx->streams[id->type];
++ struct cx18_stream *s_vbi;
+
- 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,
-+};
++ if (s->type == CX18_ENC_STREAM_TYPE_RAD) {
++ /* you cannot read from these stream types. */
++ return -EPERM;
++ }
+
-+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,
-+};
++ /* Try to claim this stream. */
++ if (cx18_claim_stream(id, s->type))
++ return -EBUSY;
+
++ /* If capture is already in progress, then we also have to
++ do nothing extra. */
++ if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) ||
++ test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) {
++ set_bit(CX18_F_S_APPL_IO, &s->s_flags);
++ return 0;
++ }
+
-+static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg)
++ /* Start VBI capture if required */
++ s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
++ if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
++ test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
++ !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
++ /* Note: the CX18_ENC_STREAM_TYPE_VBI is claimed
++ automatically when the MPG stream is claimed.
++ We only need to start the VBI capturing. */
++ if (cx18_start_v4l2_encode_stream(s_vbi)) {
++ CX18_DEBUG_WARN("VBI capture start failed\n");
++
++ /* Failure, clean up and return an error */
++ clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
++ clear_bit(CX18_F_S_STREAMING, &s->s_flags);
++ /* also releases the associated VBI stream */
++ cx18_release_stream(s);
++ return -EIO;
++ }
++ CX18_DEBUG_INFO("VBI insertion started\n");
++ }
++
++ /* Tell the card to start capturing */
++ if (!cx18_start_v4l2_encode_stream(s)) {
++ /* We're done */
++ set_bit(CX18_F_S_APPL_IO, &s->s_flags);
++ /* Resume a possibly paused encoder */
++ if (test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
++ cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, s->handle);
++ return 0;
++ }
++
++ /* failure, clean up */
++ CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
++
++ /* Note: the CX18_ENC_STREAM_TYPE_VBI is released
++ automatically when the MPG stream is released.
++ We only need to stop the VBI capturing. */
++ if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
++ test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
++ cx18_stop_v4l2_encode_stream(s_vbi, 0);
++ clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
++ }
++ clear_bit(CX18_F_S_STREAMING, &s->s_flags);
++ cx18_release_stream(s);
++ return -EIO;
++}
++
++ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
++ loff_t *pos)
+{
-+ u8 val;
-+ struct i2c_msg msg[] = {
-+ { .addr = adr, .flags = 0, .buf = ®, .len = 1 },
-+ { .addr = adr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
-+ };
++ struct cx18_open_id *id = filp->private_data;
++ struct cx18 *cx = id->cx;
++ struct cx18_stream *s = &cx->streams[id->type];
++ int rc;
+
-+ return (i2c_transfer(i2c, msg, 2) != 2) ? -EIO : val;
++ CX18_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
++
++ mutex_lock(&cx->serialize_lock);
++ rc = cx18_start_capture(id);
++ mutex_unlock(&cx->serialize_lock);
++ if (rc)
++ return rc;
++ return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
+}
+
- 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 */
++unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
++{
++ struct cx18_open_id *id = filp->private_data;
++ struct cx18 *cx = id->cx;
++ struct cx18_stream *s = &cx->streams[id->type];
++ int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+
- 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);
++ /* Start a capture if there is none */
++ if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
++ int rc;
+
-+ 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;
++ mutex_lock(&cx->serialize_lock);
++ rc = cx18_start_capture(id);
++ mutex_unlock(&cx->serialize_lock);
++ if (rc) {
++ CX18_DEBUG_INFO("Could not start capture for %s (%d)\n",
++ s->name, rc);
++ return POLLERR;
+ }
-+ break;
++ CX18_DEBUG_FILE("Encoder poll started capture\n");
++ }
+
- 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 @@
++ /* add stream's waitq to the poll list */
++ CX18_DEBUG_HI_FILE("Encoder poll\n");
++ poll_wait(filp, &s->waitq, wait);
+
- #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);
++ if (s->q_full.length || s->q_io.length)
++ return POLLIN | POLLRDNORM;
++ if (eof)
++ return POLLHUP;
++ return 0;
++}
+
- #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);
++void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
++{
++ struct cx18 *cx = id->cx;
++ struct cx18_stream *s = &cx->streams[id->type];
+
- #define dprintk if (debug) printk
-
- #define DRIVER_NAME "TechnoTrend/Hauppauge DEC USB"
-@@ -217,11 +219,11 @@ static void ttusb_dec_handle_irq( struct urb *urb)
- case -ETIME:
- /* this urb is dead, cleanup */
- dprintk("%s:urb shutting down with status: %d\n",
-- __FUNCTION__, urb->status);
-+ __func__, urb->status);
- return;
- default:
- dprintk("%s:nonzero status received: %d\n",
-- __FUNCTION__,urb->status);
-+ __func__,urb->status);
- goto exit;
- }
-
-@@ -235,7 +237,7 @@ static void ttusb_dec_handle_irq( struct urb *urb)
- * keyrepeat signal is recieved for lets say 200ms.
- * this should/could be added later ...
- * for now lets report each signal as a key down and up*/
-- dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]);
-+ dprintk("%s:rc signal:%d\n", __func__, buffer[4]);
- input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1);
- input_sync(dec->rc_input_dev);
- input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0);
-@@ -245,7 +247,7 @@ static void ttusb_dec_handle_irq( struct urb *urb)
- exit: retval = usb_submit_urb(urb, GFP_ATOMIC);
- if(retval)
- printk("%s - usb_commit_urb failed with result: %d\n",
-- __FUNCTION__, retval);
-+ __func__, retval);
- }
-
- static u16 crc16(u16 crc, const u8 *buf, size_t len)
-@@ -268,7 +270,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
- int result, actual_len, i;
- u8 *b;
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- b = kmalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL);
- if (!b)
-@@ -276,7 +278,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
-
- if ((result = mutex_lock_interruptible(&dec->usb_mutex))) {
- kfree(b);
-- printk("%s: Failed to lock usb mutex.\n", __FUNCTION__);
-+ printk("%s: Failed to lock usb mutex.\n", __func__);
- return result;
- }
-
-@@ -289,7 +291,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
- memcpy(&b[4], params, param_length);
-
- if (debug) {
-- printk("%s: command: ", __FUNCTION__);
-+ printk("%s: command: ", __func__);
- for (i = 0; i < param_length + 4; i++)
- printk("0x%02X ", b[i]);
- printk("\n");
-@@ -300,7 +302,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
-
- if (result) {
- printk("%s: command bulk message failed: error %d\n",
-- __FUNCTION__, result);
-+ __func__, result);
- mutex_unlock(&dec->usb_mutex);
- kfree(b);
- return result;
-@@ -311,13 +313,13 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
-
- if (result) {
- printk("%s: result bulk message failed: error %d\n",
-- __FUNCTION__, result);
-+ __func__, result);
- mutex_unlock(&dec->usb_mutex);
- kfree(b);
- return result;
- } else {
- if (debug) {
-- printk("%s: result: ", __FUNCTION__);
-+ printk("%s: result: ", __func__);
- for (i = 0; i < actual_len; i++)
- printk("0x%02X ", b[i]);
- printk("\n");
-@@ -343,7 +345,7 @@ static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode,
- int result;
- unsigned int tmp;
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c);
- if (result)
-@@ -400,7 +402,7 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec)
- u16 audio = htons(dec->pid[DMX_PES_AUDIO]);
- u16 video = htons(dec->pid[DMX_PES_VIDEO]);
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- memcpy(&b[0], &pcr, 2);
- memcpy(&b[2], &audio, 2);
-@@ -419,12 +421,12 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec)
- static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
- {
- if (length < 8) {
-- printk("%s: packet too short - discarding\n", __FUNCTION__);
-+ printk("%s: packet too short - discarding\n", __func__);
- return;
- }
-
- if (length > 8 + MAX_PVA_LENGTH) {
-- printk("%s: packet too long - discarding\n", __FUNCTION__);
-+ printk("%s: packet too long - discarding\n", __func__);
- return;
- }
-
-@@ -507,7 +509,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
- break;
-
- default:
-- printk("%s: unknown PVA type: %02x.\n", __FUNCTION__,
-+ printk("%s: unknown PVA type: %02x.\n", __func__,
- pva[2]);
- break;
- }
-@@ -546,7 +548,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
- u16 packet_id;
-
- if (dec->packet_length % 2) {
-- printk("%s: odd sized packet - discarding\n", __FUNCTION__);
-+ printk("%s: odd sized packet - discarding\n", __func__);
- return;
- }
-
-@@ -554,7 +556,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
- csum ^= ((dec->packet[i] << 8) + dec->packet[i + 1]);
-
- if (csum) {
-- printk("%s: checksum failed - discarding\n", __FUNCTION__);
-+ printk("%s: checksum failed - discarding\n", __func__);
- return;
- }
-
-@@ -563,7 +565,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
-
- if ((packet_id != dec->next_packet_id) && dec->next_packet_id) {
- printk("%s: warning: lost packets between %u and %u\n",
-- __FUNCTION__, dec->next_packet_id - 1, packet_id);
-+ __func__, dec->next_packet_id - 1, packet_id);
- }
-
- if (packet_id == 0xffff)
-@@ -652,7 +654,7 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
- dec->packet_state = 7;
- } else {
- printk("%s: unknown packet type: "
-- "%02x%02x\n", __FUNCTION__,
-+ "%02x%02x\n", __func__,
- dec->packet[0], dec->packet[1]);
- dec->packet_state = 0;
- }
-@@ -724,7 +726,7 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
-
- default:
- printk("%s: illegal packet state encountered.\n",
-- __FUNCTION__);
-+ __func__);
- dec->packet_state = 0;
- }
- }
-@@ -792,7 +794,7 @@ static void ttusb_dec_process_urb(struct urb *urb)
- } else {
- /* -ENOENT is expected when unlinking urbs */
- if (urb->status != -ENOENT)
-- dprintk("%s: urb error: %d\n", __FUNCTION__,
-+ dprintk("%s: urb error: %d\n", __func__,
- urb->status);
- }
-
-@@ -804,7 +806,7 @@ static void ttusb_dec_setup_urbs(struct ttusb_dec *dec)
- {
- int i, j, buffer_offset = 0;
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- for (i = 0; i < ISO_BUF_COUNT; i++) {
- int frame_offset = 0;
-@@ -834,7 +836,7 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec)
- {
- int i;
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- if (mutex_lock_interruptible(&dec->iso_mutex))
- return;
-@@ -889,7 +891,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
- {
- int i, result;
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- if (mutex_lock_interruptible(&dec->iso_mutex))
- return -EAGAIN;
-@@ -905,7 +907,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
- if ((result = usb_submit_urb(dec->iso_urb[i],
- GFP_ATOMIC))) {
- printk("%s: failed urb submission %d: "
-- "error %d\n", __FUNCTION__, i, result);
-+ "error %d\n", __func__, i, result);
-
- while (i) {
- usb_kill_urb(dec->iso_urb[i - 1]);
-@@ -932,7 +934,7 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
- u8 b0[] = { 0x05 };
- int result = 0;
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- dprintk(" ts_type:");
-
-@@ -1012,7 +1014,7 @@ static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
- unsigned long flags;
- u8 x = 1;
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- pid = htons(dvbdmxfeed->pid);
- memcpy(&b0[0], &pid, 2);
-@@ -1052,7 +1054,7 @@ static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed)
- {
- struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- if (!dvbdmx->dmx.frontend)
- return -EINVAL;
-@@ -1113,7 +1115,7 @@ static int ttusb_dec_stop_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
-
- static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
- {
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- switch (dvbdmxfeed->type) {
- case DMX_TYPE_TS:
-@@ -1132,7 +1134,7 @@ static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec)
- {
- int i;
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- for (i = 0; i < ISO_BUF_COUNT; i++)
- usb_free_urb(dec->iso_urb[i]);
-@@ -1147,7 +1149,7 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
- {
- int i;
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- dec->iso_buffer = pci_alloc_consistent(NULL,
- ISO_FRAME_SIZE *
-@@ -1214,7 +1216,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
-
- dec->rc_input_dev = input_dev;
- if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
-- printk("%s: usb_submit_urb failed\n",__FUNCTION__);
-+ printk("%s: usb_submit_urb failed\n",__func__);
- /* enable irq pipe */
- ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL);
-
-@@ -1223,7 +1225,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
-
- static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
- {
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- dec->v_pes[0] = 0x00;
- dec->v_pes[1] = 0x00;
-@@ -1233,7 +1235,7 @@ static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
-
- static int ttusb_dec_init_usb(struct ttusb_dec *dec)
- {
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- mutex_init(&dec->usb_mutex);
- mutex_init(&dec->iso_mutex);
-@@ -1281,11 +1283,11 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
- u32 crc32_csum, crc32_check, tmp;
- const struct firmware *fw_entry = NULL;
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- if (request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev)) {
- printk(KERN_ERR "%s: Firmware (%s) unavailable.\n",
-- __FUNCTION__, dec->firmware_name);
-+ __func__, dec->firmware_name);
- return 1;
- }
-
-@@ -1294,7 +1296,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
-
- if (firmware_size < 60) {
- printk("%s: firmware size too small for DSP code (%zu < 60).\n",
-- __FUNCTION__, firmware_size);
-+ __func__, firmware_size);
- release_firmware(fw_entry);
- return -1;
- }
-@@ -1308,7 +1310,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
- if (crc32_csum != crc32_check) {
- printk("%s: crc32 check of DSP code failed (calculated "
- "0x%08x != 0x%08x in file), file invalid.\n",
-- __FUNCTION__, crc32_csum, crc32_check);
-+ __func__, crc32_csum, crc32_check);
- release_firmware(fw_entry);
- return -1;
- }
-@@ -1376,7 +1378,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
- int result;
- unsigned int mode, model, version;
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- result = ttusb_dec_get_stb_state(dec, &mode, &model, &version);
-
-@@ -1415,7 +1417,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
- default:
- printk(KERN_ERR "%s: unknown model returned "
- "by firmware (%08x) - please report\n",
-- __FUNCTION__, model);
-+ __func__, model);
- return -1;
- break;
- }
-@@ -1434,12 +1436,14 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
- {
- int result;
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- if ((result = dvb_register_adapter(&dec->adapter,
-- dec->model_name, THIS_MODULE, &dec->udev->dev)) < 0) {
-+ dec->model_name, THIS_MODULE,
-+ &dec->udev->dev,
-+ adapter_nr)) < 0) {
- printk("%s: dvb_register_adapter failed: error %d\n",
-- __FUNCTION__, result);
-+ __func__, result);
-
- return result;
- }
-@@ -1454,7 +1458,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
- dec->demux.write_to_decoder = NULL;
-
- if ((result = dvb_dmx_init(&dec->demux)) < 0) {
-- printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
-+ printk("%s: dvb_dmx_init failed: error %d\n", __func__,
- result);
-
- dvb_unregister_adapter(&dec->adapter);
-@@ -1468,7 +1472,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
-
- if ((result = dvb_dmxdev_init(&dec->dmxdev, &dec->adapter)) < 0) {
- printk("%s: dvb_dmxdev_init failed: error %d\n",
-- __FUNCTION__, result);
-+ __func__, result);
-
- dvb_dmx_release(&dec->demux);
- dvb_unregister_adapter(&dec->adapter);
-@@ -1480,7 +1484,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
-
- if ((result = dec->demux.dmx.add_frontend(&dec->demux.dmx,
- &dec->frontend)) < 0) {
-- printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
-+ printk("%s: dvb_dmx_init failed: error %d\n", __func__,
- result);
-
- dvb_dmxdev_release(&dec->dmxdev);
-@@ -1492,7 +1496,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
-
- if ((result = dec->demux.dmx.connect_frontend(&dec->demux.dmx,
- &dec->frontend)) < 0) {
-- printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
-+ printk("%s: dvb_dmx_init failed: error %d\n", __func__,
- result);
-
- dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
-@@ -1510,7 +1514,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
-
- static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
- {
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- dvb_net_release(&dec->dvb_net);
- dec->demux.dmx.close(&dec->demux.dmx);
-@@ -1528,7 +1532,7 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
- static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
- {
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
- /* we have to check whether the irq URB is already submitted.
- * As the irq is submitted after the interface is changed,
- * this is the best method i figured out.
-@@ -1552,7 +1556,7 @@ static void ttusb_dec_exit_usb(struct ttusb_dec *dec)
- {
- int i;
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- dec->iso_stream_count = 0;
-
-@@ -1612,12 +1616,12 @@ static int ttusb_dec_probe(struct usb_interface *intf,
- struct usb_device *udev;
- struct ttusb_dec *dec;
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- udev = interface_to_usbdev(intf);
-
- if (!(dec = kzalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {
-- printk("%s: couldn't allocate memory.\n", __FUNCTION__);
-+ printk("%s: couldn't allocate memory.\n", __func__);
- return -ENOMEM;
- }
-
-@@ -1692,7 +1696,7 @@ static void ttusb_dec_disconnect(struct usb_interface *intf)
-
- usb_set_intfdata(intf, NULL);
-
-- dprintk("%s\n", __FUNCTION__);
-+ dprintk("%s\n", __func__);
-
- if (dec->active) {
- ttusb_dec_exit_tasklet(dec);
-@@ -1749,7 +1753,7 @@ static int __init ttusb_dec_init(void)
- int result;
-
- if ((result = usb_register(&ttusb_dec_driver)) < 0) {
-- printk("%s: initialisation failed: error %d.\n", __FUNCTION__,
-+ printk("%s: initialisation failed: error %d.\n", __func__,
- result);
- return result;
- }
-diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
-index a6fb1d6..eb5eaec 100644
---- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
-+++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
-@@ -53,7 +53,7 @@ static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
- return ret;
-
- if(len != 4) {
-- printk(KERN_ERR "%s: unexpected reply\n", __FUNCTION__);
-+ printk(KERN_ERR "%s: unexpected reply\n", __func__);
- return -EIO;
- }
-
-@@ -70,7 +70,7 @@ static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
- break;
- default:
- pr_info("%s: returned unknown value: %d\n",
-- __FUNCTION__, result[3]);
-+ __func__, result[3]);
- return -EIO;
- }
-
-diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
-index 36c0e36..4e3f83e 100644
---- a/drivers/media/radio/dsbr100.c
-+++ b/drivers/media/radio/dsbr100.c
-@@ -438,7 +438,9 @@ static const struct file_operations usb_dsbr100_fops = {
- .open = usb_dsbr100_open,
- .release = usb_dsbr100_close,
- .ioctl = video_ioctl2,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .llseek = no_llseek,
- };
-
-diff --git a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c
-index 3ae56fe..09fe6f1 100644
---- a/drivers/media/radio/miropcm20-radio.c
-+++ b/drivers/media/radio/miropcm20-radio.c
-@@ -221,7 +221,9 @@ static const struct file_operations pcm20_fops = {
- .open = video_exclusive_open,
- .release = video_exclusive_release,
- .ioctl = pcm20_ioctl,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .llseek = no_llseek,
- };
-
-diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c
-index aed1147..06dfed9 100644
---- a/drivers/media/radio/miropcm20-rds.c
-+++ b/drivers/media/radio/miropcm20-rds.c
-@@ -19,7 +19,7 @@
- #include "miropcm20-rds-core.h"
-
- static char * text_buffer;
--static int rds_users = 0;
-+static int rds_users;
-
-
- static int rds_f_open(struct inode *in, struct file *fi)
-diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
-index f0a67e9..1ec18ed 100644
---- a/drivers/media/radio/radio-aimslab.c
-+++ b/drivers/media/radio/radio-aimslab.c
-@@ -36,7 +36,6 @@
- #include <asm/uaccess.h> /* copy to/from user */
- #include <linux/videodev2.h> /* kernel radio structs */
- #include <media/v4l2-common.h>
--#include <asm/semaphore.h> /* Lock for the I/O */
-
- #include <linux/version.h> /* for KERNEL_VERSION MACRO */
- #define RADIO_VERSION KERNEL_VERSION(0,0,2)
-@@ -383,7 +382,9 @@ static const struct file_operations rtrack_fops = {
- .open = video_exclusive_open,
- .release = video_exclusive_release,
- .ioctl = video_ioctl2,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .llseek = no_llseek,
- };
-
-diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
-index 9b1f7a9..46cdb54 100644
---- a/drivers/media/radio/radio-aztech.c
-+++ b/drivers/media/radio/radio-aztech.c
-@@ -346,7 +346,9 @@ static const struct file_operations aztech_fops = {
- .open = video_exclusive_open,
- .release = video_exclusive_release,
- .ioctl = video_ioctl2,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .llseek = no_llseek,
- };
-
-diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
-index 57b9e3a..b14db53 100644
---- a/drivers/media/radio/radio-cadet.c
-+++ b/drivers/media/radio/radio-cadet.c
-@@ -69,13 +69,13 @@ static struct v4l2_queryctrl radio_qctrl[] = {
-
- static int io=-1; /* default to isapnp activation */
- static int radio_nr = -1;
--static int users=0;
--static int curtuner=0;
--static int tunestat=0;
--static int sigstrength=0;
-+static int users;
-+static int curtuner;
-+static int tunestat;
-+static int sigstrength;
- static wait_queue_head_t read_queue;
- static struct timer_list readtimer;
--static __u8 rdsin=0,rdsout=0,rdsstat=0;
-+static __u8 rdsin, rdsout, rdsstat;
- static unsigned char rdsbuf[RDS_BUFFER];
- static spinlock_t cadet_io_lock;
-
-@@ -563,7 +563,9 @@ static const struct file_operations cadet_fops = {
- .read = cadet_read,
- .ioctl = video_ioctl2,
- .poll = cadet_poll,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .llseek = no_llseek,
- };
-
-diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
-index 99a3231..de49be9 100644
---- a/drivers/media/radio/radio-gemtek-pci.c
-+++ b/drivers/media/radio/radio-gemtek-pci.c
-@@ -368,7 +368,9 @@ static const struct file_operations gemtek_pci_fops = {
- .open = video_exclusive_open,
- .release = video_exclusive_release,
- .ioctl = video_ioctl2,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .llseek = no_llseek,
- };
-
-diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
-index 246422b..81f6aeb 100644
---- a/drivers/media/radio/radio-gemtek.c
-+++ b/drivers/media/radio/radio-gemtek.c
-@@ -397,7 +397,9 @@ static const struct file_operations gemtek_fops = {
- .open = video_exclusive_open,
- .release = video_exclusive_release,
- .ioctl = video_ioctl2,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .llseek = no_llseek
- };
-
-diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
-index bc51f4d..bddd3c4 100644
---- a/drivers/media/radio/radio-maestro.c
-+++ b/drivers/media/radio/radio-maestro.c
-@@ -100,7 +100,9 @@ static const struct file_operations maestro_fops = {
- .open = video_exclusive_open,
- .release = video_exclusive_release,
- .ioctl = video_ioctl2,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .llseek = no_llseek,
- };
-
-diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
-index 8e184cf..0133ecf 100644
---- a/drivers/media/radio/radio-maxiradio.c
-+++ b/drivers/media/radio/radio-maxiradio.c
-@@ -103,7 +103,9 @@ static const struct file_operations maxiradio_fops = {
- .open = video_exclusive_open,
- .release = video_exclusive_release,
- .ioctl = video_ioctl2,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .llseek = no_llseek,
- };
-
-diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
-index 82aedfc..0708021 100644
---- a/drivers/media/radio/radio-rtrack2.c
-+++ b/drivers/media/radio/radio-rtrack2.c
-@@ -288,7 +288,9 @@ static const struct file_operations rtrack2_fops = {
- .open = video_exclusive_open,
- .release = video_exclusive_release,
- .ioctl = video_ioctl2,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .llseek = no_llseek,
- };
-
-diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
-index 53e1148..66e052f 100644
---- a/drivers/media/radio/radio-sf16fmi.c
-+++ b/drivers/media/radio/radio-sf16fmi.c
-@@ -288,7 +288,9 @@ static const struct file_operations fmi_fops = {
- .open = video_exclusive_open,
- .release = video_exclusive_release,
- .ioctl = video_ioctl2,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .llseek = no_llseek,
- };
-
-diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
-index ebc5fbb..b0ccf7c 100644
---- a/drivers/media/radio/radio-sf16fmr2.c
-+++ b/drivers/media/radio/radio-sf16fmr2.c
-@@ -29,6 +29,8 @@ static struct mutex lock;
- #include <linux/version.h> /* for KERNEL_VERSION MACRO */
- #define RADIO_VERSION KERNEL_VERSION(0,0,2)
-
-+#define AUD_VOL_INDEX 1
++ CX18_DEBUG_IOCTL("close() of %s\n", s->name);
+
- 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;
++ /* 'Unclaim' this stream */
++
++ /* Stop capturing */
++ if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
++ struct cx18_stream *s_vbi =
++ &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
++
++ CX18_DEBUG_INFO("close stopping capture\n");
++ /* Special case: a running VBI capture for VBI insertion
++ in the mpeg stream. Need to stop that too. */
++ if (id->type == CX18_ENC_STREAM_TYPE_MPG &&
++ test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
++ !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
++ CX18_DEBUG_INFO("close stopping embedded VBI capture\n");
++ cx18_stop_v4l2_encode_stream(s_vbi, 0);
++ }
++ if (id->type == CX18_ENC_STREAM_TYPE_VBI &&
++ test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags))
++ /* Also used internally, don't stop capturing */
++ s->id = -1;
+ else
-+ fmr2->curvol = ctrl->value;
++ cx18_stop_v4l2_encode_stream(s, gop_end);
++ }
++ if (!gop_end) {
++ clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
++ clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
++ cx18_release_stream(s);
++ }
++}
+
- 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));
++int cx18_v4l2_close(struct inode *inode, struct file *filp)
++{
++ struct cx18_open_id *id = filp->private_data;
++ struct cx18 *cx = id->cx;
++ struct cx18_stream *s = &cx->streams[id->type];
+
-+ /* Only card_type == 11 implements volume */
-+ if (fmr2_unit.card_type != 11)
-+ radio_qctrl[AUD_VOL_INDEX].maximum = 1;
++ CX18_DEBUG_IOCTL("close() of %s\n", s->name);
+
- return 0;
- }
-
-diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c
-index 649f14d..77354ca 100644
---- a/drivers/media/radio/radio-si470x.c
-+++ b/drivers/media/radio/radio-si470x.c
-@@ -85,6 +85,7 @@
- * Oliver Neukum <oliver at neukum.org>
- * Version 1.0.7
- * - usb autosuspend support
-+ * - unplugging fixed
- *
- * ToDo:
- * - add seeking support
-@@ -97,10 +98,10 @@
- /* driver definitions */
- #define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz at gmx.net>"
- #define DRIVER_NAME "radio-si470x"
--#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 6)
-+#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 7)
- #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
- #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
--#define DRIVER_VERSION "1.0.6"
-+#define DRIVER_VERSION "1.0.7"
-
-
- /* kernel includes */
-@@ -424,6 +425,7 @@ struct si470x_device {
-
- /* driver management */
- unsigned int users;
-+ unsigned char disconnected;
-
- /* Silabs internal registers (0..15) */
- unsigned short registers[RADIO_REGISTER_NUM];
-@@ -440,6 +442,12 @@ struct si470x_device {
-
-
- /*
-+ * Lock to prevent kfree of data before all users have releases the device.
-+ */
-+static DEFINE_MUTEX(open_close_lock);
++ v4l2_prio_close(&cx->prio, &id->prio);
+
++ /* Easy case first: this stream was never claimed by us */
++ if (s->id != id->open_id) {
++ kfree(id);
++ return 0;
++ }
+
-+/*
- * 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;
-+ }
++ /* 'Unclaim' this stream */
+
- /* 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;
++ /* Stop radio */
++ mutex_lock(&cx->serialize_lock);
++ if (id->type == CX18_ENC_STREAM_TYPE_RAD) {
++ /* Closing radio device, return to TV mode */
++ cx18_mute(cx);
++ /* Mark that the radio is no longer in use */
++ clear_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
++ /* Switch tuner to TV */
++ cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std);
++ /* Select correct audio input (i.e. TV tuner or Line in) */
++ cx18_audio_set_io(cx);
++ if (atomic_read(&cx->capturing) > 0) {
++ /* Undo video mute */
++ cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
++ cx->params.video_mute |
++ (cx->params.video_mute_yuv << 8));
++ }
++ /* Done! Unmute and continue. */
++ cx18_unmute(cx);
++ cx18_release_stream(s);
++ } else {
++ cx18_stop_capture(id, 0);
++ }
++ kfree(id);
++ mutex_unlock(&cx->serialize_lock);
++ return 0;
++}
+
- 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;
++static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
++{
++ struct cx18 *cx = s->cx;
++ struct cx18_open_id *item;
+
- 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;
++ CX18_DEBUG_FILE("open %s\n", s->name);
+
- freq->type = V4L2_TUNER_RADIO;
- freq->frequency = si470x_get_freq(radio);
-
-@@ -1340,6 +1374,8 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv,
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
- int retval;
-
-+ if (radio->disconnected)
-+ return -EIO;
- if (freq->type != V4L2_TUNER_RADIO)
- return -EINVAL;
-
-@@ -1510,11 +1546,16 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
- {
- struct si470x_device *radio = usb_get_intfdata(intf);
-
-+ mutex_lock(&open_close_lock);
-+ radio->disconnected = 1;
- cancel_delayed_work_sync(&radio->work);
- usb_set_intfdata(intf, NULL);
-- video_unregister_device(radio->videodev);
-- kfree(radio->buffer);
-- kfree(radio);
-+ if (radio->users == 0) {
-+ video_unregister_device(radio->videodev);
-+ kfree(radio->buffer);
-+ kfree(radio);
-+ }
-+ mutex_unlock(&open_close_lock);
- }
-
-
-diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
-index 535ffe8..acc3208 100644
---- a/drivers/media/radio/radio-terratec.c
-+++ b/drivers/media/radio/radio-terratec.c
-@@ -360,7 +360,9 @@ static const struct file_operations terratec_fops = {
- .open = video_exclusive_open,
- .release = video_exclusive_release,
- .ioctl = video_ioctl2,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .llseek = no_llseek,
- };
-
-diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
-index c11981f..4ebdfba 100644
---- a/drivers/media/radio/radio-trust.c
-+++ b/drivers/media/radio/radio-trust.c
-@@ -340,7 +340,9 @@ static const struct file_operations trust_fops = {
- .open = video_exclusive_open,
- .release = video_exclusive_release,
- .ioctl = video_ioctl2,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .llseek = no_llseek,
- };
-
-diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
-index 1366326..18f2abd 100644
---- a/drivers/media/radio/radio-typhoon.c
-+++ b/drivers/media/radio/radio-typhoon.c
-@@ -35,6 +35,7 @@
- #include <linux/init.h> /* Initdata */
- #include <linux/ioport.h> /* request_region */
- #include <linux/proc_fs.h> /* radio card status report */
-+#include <linux/seq_file.h>
- #include <asm/io.h> /* outb, outb_p */
- #include <asm/uaccess.h> /* copy to/from user */
- #include <linux/videodev2.h> /* kernel radio structs */
-@@ -93,9 +94,6 @@ static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency);
- static void typhoon_mute(struct typhoon_device *dev);
- static void typhoon_unmute(struct typhoon_device *dev);
- static int typhoon_setvol(struct typhoon_device *dev, int vol);
--#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
--static int typhoon_get_info(char *buf, char **start, off_t offset, int len);
--#endif
-
- static void typhoon_setvol_generic(struct typhoon_device *dev, int vol)
- {
-@@ -340,7 +338,9 @@ static const struct file_operations typhoon_fops = {
- .open = video_exclusive_open,
- .release = video_exclusive_release,
- .ioctl = video_ioctl2,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .llseek = no_llseek,
- };
-
-@@ -366,30 +366,39 @@ static struct video_device typhoon_radio =
-
- #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
-
--static int typhoon_get_info(char *buf, char **start, off_t offset, int len)
-+static int typhoon_proc_show(struct seq_file *m, void *v)
- {
-- char *out = buf;
--
- #ifdef MODULE
- #define MODULEPROCSTRING "Driver loaded as a module"
- #else
- #define MODULEPROCSTRING "Driver compiled into kernel"
- #endif
-
-- /* output must be kept under PAGE_SIZE */
-- out += sprintf(out, BANNER);
-- out += sprintf(out, "Load type: " MODULEPROCSTRING "\n\n");
-- out += sprintf(out, "frequency = %lu kHz\n",
-+ seq_puts(m, BANNER);
-+ seq_puts(m, "Load type: " MODULEPROCSTRING "\n\n");
-+ seq_printf(m, "frequency = %lu kHz\n",
- typhoon_unit.curfreq >> 4);
-- out += sprintf(out, "volume = %d\n", typhoon_unit.curvol);
-- out += sprintf(out, "mute = %s\n", typhoon_unit.muted ?
-+ seq_printf(m, "volume = %d\n", typhoon_unit.curvol);
-+ seq_printf(m, "mute = %s\n", typhoon_unit.muted ?
- "on" : "off");
-- out += sprintf(out, "iobase = 0x%x\n", typhoon_unit.iobase);
-- out += sprintf(out, "mute frequency = %lu kHz\n",
-+ seq_printf(m, "iobase = 0x%x\n", typhoon_unit.iobase);
-+ seq_printf(m, "mute frequency = %lu kHz\n",
- typhoon_unit.mutefreq >> 4);
-- return out - buf;
++ /* Allocate memory */
++ item = kmalloc(sizeof(struct cx18_open_id), GFP_KERNEL);
++ if (NULL == item) {
++ CX18_DEBUG_WARN("nomem on v4l2 open\n");
++ return -ENOMEM;
++ }
++ item->cx = cx;
++ item->type = s->type;
++ v4l2_prio_open(&cx->prio, &item->prio);
++
++ item->open_id = cx->open_id++;
++ filp->private_data = item;
++
++ if (item->type == CX18_ENC_STREAM_TYPE_RAD) {
++ /* Try to claim this stream */
++ if (cx18_claim_stream(item, item->type)) {
++ /* No, it's already in use */
++ kfree(item);
++ return -EBUSY;
++ }
++
++ if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
++ if (atomic_read(&cx->capturing) > 0) {
++ /* switching to radio while capture is
++ in progress is not polite */
++ cx18_release_stream(s);
++ kfree(item);
++ return -EBUSY;
++ }
++ }
++
++ /* Mark that the radio is being used. */
++ set_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
++ /* We have the radio */
++ cx18_mute(cx);
++ /* Switch tuner to radio */
++ cx18_call_i2c_clients(cx, AUDC_SET_RADIO, NULL);
++ /* Select the correct audio input (i.e. radio tuner) */
++ cx18_audio_set_io(cx);
++ /* Done! Unmute and continue. */
++ cx18_unmute(cx);
++ }
+ return 0;
- }
-
-+static int typhoon_proc_open(struct inode *inode, struct file *file)
++}
++
++int cx18_v4l2_open(struct inode *inode, struct file *filp)
+{
-+ return single_open(file, typhoon_proc_show, NULL);
++ int res, x, y = 0;
++ struct cx18 *cx = NULL;
++ struct cx18_stream *s = NULL;
++ int minor = iminor(inode);
++
++ /* Find which card this open was on */
++ spin_lock(&cx18_cards_lock);
++ for (x = 0; cx == NULL && x < cx18_cards_active; x++) {
++ /* find out which stream this open was on */
++ for (y = 0; y < CX18_MAX_STREAMS; y++) {
++ s = &cx18_cards[x]->streams[y];
++ if (s->v4l2dev && s->v4l2dev->minor == minor) {
++ cx = cx18_cards[x];
++ break;
++ }
++ }
++ }
++ spin_unlock(&cx18_cards_lock);
++
++ if (cx == NULL) {
++ /* Couldn't find a device registered
++ on that minor, shouldn't happen! */
++ printk(KERN_WARNING "No cx18 device found on minor %d\n",
++ minor);
++ return -ENXIO;
++ }
++
++ mutex_lock(&cx->serialize_lock);
++ if (cx18_init_on_first_open(cx)) {
++ CX18_ERR("Failed to initialize on minor %d\n", minor);
++ mutex_unlock(&cx->serialize_lock);
++ return -ENXIO;
++ }
++ res = cx18_serialized_open(s, filp);
++ mutex_unlock(&cx->serialize_lock);
++ return res;
+}
+
-+static const struct file_operations typhoon_proc_fops = {
-+ .owner = THIS_MODULE,
-+ .open = typhoon_proc_open,
-+ .read = seq_read,
-+ .llseek = seq_lseek,
-+ .release = single_release,
++void cx18_mute(struct cx18 *cx)
++{
++ if (atomic_read(&cx->capturing))
++ cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
++ cx18_find_handle(cx), 1);
++ CX18_DEBUG_INFO("Mute\n");
++}
++
++void cx18_unmute(struct cx18 *cx)
++{
++ if (atomic_read(&cx->capturing)) {
++ cx18_msleep_timeout(100, 0);
++ cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2,
++ cx18_find_handle(cx), 12);
++ cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
++ cx18_find_handle(cx), 0);
++ }
++ CX18_DEBUG_INFO("Unmute\n");
++}
+diff --git a/drivers/media/video/cx18/cx18-fileops.h b/drivers/media/video/cx18/cx18-fileops.h
+new file mode 100644
+index 0000000..16cdafb
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-fileops.h
+@@ -0,0 +1,45 @@
++/*
++ * cx18 file operation functions
++ *
++ * Derived from ivtv-fileops.h
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
++
++/* Testing/Debugging */
++int cx18_v4l2_open(struct inode *inode, struct file *filp);
++ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
++ loff_t *pos);
++ssize_t cx18_v4l2_write(struct file *filp, const char __user *buf, size_t count,
++ loff_t *pos);
++int cx18_v4l2_close(struct inode *inode, struct file *filp);
++unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait);
++int cx18_start_capture(struct cx18_open_id *id);
++void cx18_stop_capture(struct cx18_open_id *id, int gop_end);
++void cx18_mute(struct cx18 *cx);
++void cx18_unmute(struct cx18 *cx);
++
++/* Utilities */
++
++/* Try to claim a stream for the filehandle. Return 0 on success,
++ -EBUSY if stream already claimed. Once a stream is claimed, it
++ remains claimed until the associated filehandle is closed. */
++int cx18_claim_stream(struct cx18_open_id *id, int type);
++
++/* Release a previously claimed stream. */
++void cx18_release_stream(struct cx18_stream *s);
+diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c
+new file mode 100644
+index 0000000..2694ce3
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-firmware.c
+@@ -0,0 +1,373 @@
++/*
++ * cx18 firmware functions
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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 "cx18-driver.h"
++#include "cx18-scb.h"
++#include "cx18-irq.h"
++#include "cx18-firmware.h"
++#include "cx18-cards.h"
++#include <linux/firmware.h>
++
++#define CX18_PROC_SOFT_RESET 0xc70010
++#define CX18_DDR_SOFT_RESET 0xc70014
++#define CX18_CLOCK_SELECT1 0xc71000
++#define CX18_CLOCK_SELECT2 0xc71004
++#define CX18_HALF_CLOCK_SELECT1 0xc71008
++#define CX18_HALF_CLOCK_SELECT2 0xc7100C
++#define CX18_CLOCK_POLARITY1 0xc71010
++#define CX18_CLOCK_POLARITY2 0xc71014
++#define CX18_ADD_DELAY_ENABLE1 0xc71018
++#define CX18_ADD_DELAY_ENABLE2 0xc7101C
++#define CX18_CLOCK_ENABLE1 0xc71020
++#define CX18_CLOCK_ENABLE2 0xc71024
++
++#define CX18_REG_BUS_TIMEOUT_EN 0xc72024
++
++#define CX18_AUDIO_ENABLE 0xc72014
++#define CX18_REG_BUS_TIMEOUT_EN 0xc72024
++
++#define CX18_FAST_CLOCK_PLL_INT 0xc78000
++#define CX18_FAST_CLOCK_PLL_FRAC 0xc78004
++#define CX18_FAST_CLOCK_PLL_POST 0xc78008
++#define CX18_FAST_CLOCK_PLL_PRESCALE 0xc7800C
++#define CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH 0xc78010
++
++#define CX18_SLOW_CLOCK_PLL_INT 0xc78014
++#define CX18_SLOW_CLOCK_PLL_FRAC 0xc78018
++#define CX18_SLOW_CLOCK_PLL_POST 0xc7801C
++#define CX18_MPEG_CLOCK_PLL_INT 0xc78040
++#define CX18_MPEG_CLOCK_PLL_FRAC 0xc78044
++#define CX18_MPEG_CLOCK_PLL_POST 0xc78048
++#define CX18_PLL_POWER_DOWN 0xc78088
++#define CX18_SW1_INT_STATUS 0xc73104
++#define CX18_SW1_INT_ENABLE_PCI 0xc7311C
++#define CX18_SW2_INT_SET 0xc73140
++#define CX18_SW2_INT_STATUS 0xc73144
++#define CX18_ADEC_CONTROL 0xc78120
++
++#define CX18_DDR_REQUEST_ENABLE 0xc80000
++#define CX18_DDR_CHIP_CONFIG 0xc80004
++#define CX18_DDR_REFRESH 0xc80008
++#define CX18_DDR_TIMING1 0xc8000C
++#define CX18_DDR_TIMING2 0xc80010
++#define CX18_DDR_POWER_REG 0xc8001C
++
++#define CX18_DDR_TUNE_LANE 0xc80048
++#define CX18_DDR_INITIAL_EMRS 0xc80054
++#define CX18_DDR_MB_PER_ROW_7 0xc8009C
++#define CX18_DDR_BASE_63_ADDR 0xc804FC
++
++#define CX18_WMB_CLIENT02 0xc90108
++#define CX18_WMB_CLIENT05 0xc90114
++#define CX18_WMB_CLIENT06 0xc90118
++#define CX18_WMB_CLIENT07 0xc9011C
++#define CX18_WMB_CLIENT08 0xc90120
++#define CX18_WMB_CLIENT09 0xc90124
++#define CX18_WMB_CLIENT10 0xc90128
++#define CX18_WMB_CLIENT11 0xc9012C
++#define CX18_WMB_CLIENT12 0xc90130
++#define CX18_WMB_CLIENT13 0xc90134
++#define CX18_WMB_CLIENT14 0xc90138
++
++#define CX18_DSP0_INTERRUPT_MASK 0xd0004C
++
++/* Encoder/decoder firmware sizes */
++#define CX18_FW_CPU_SIZE (174716)
++#define CX18_FW_APU_SIZE (141200)
++
++#define APU_ROM_SYNC1 0x6D676553 /* "mgeS" */
++#define APU_ROM_SYNC2 0x72646548 /* "rdeH" */
++
++struct cx18_apu_rom_seghdr {
++ u32 sync1;
++ u32 sync2;
++ u32 addr;
++ u32 size;
+};
- #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.
++static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx, long size)
++{
++ const struct firmware *fw = NULL;
++ int retries = 3;
++ int i, j;
++ u32 __iomem *dst = (u32 __iomem *)mem;
++ const u32 *src;
+
- 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"
++retry:
++ if (!retries || request_firmware(&fw, fn, &cx->dev->dev)) {
++ CX18_ERR("Unable to open firmware %s (must be %ld bytes)\n",
++ fn, size);
++ CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n");
++ return -ENOMEM;
++ }
+
- 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.
++ src = (const u32 *)fw->data;
+
-+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.
++ if (fw->size != size) {
++ /* Due to race conditions in firmware loading (esp. with
++ udev <0.95) the wrong file was sometimes loaded. So we check
++ filesizes to see if at least the right-sized file was
++ loaded. If not, then we retry. */
++ CX18_INFO("retry: file loaded was not %s (expected size %ld, got %zd)\n",
++ fn, size, fw->size);
++ release_firmware(fw);
++ retries--;
++ goto retry;
++ }
++ for (i = 0; i < fw->size; i += 4096) {
++ setup_page(i);
++ for (j = i; j < fw->size && j < i + 4096; j += 4) {
++ /* no need for endianness conversion on the ppc */
++ __raw_writel(*src, dst);
++ if (__raw_readl(dst) != *src) {
++ CX18_ERR("Mismatch at offset %x\n", i);
++ release_firmware(fw);
++ return -EIO;
++ }
++ dst++;
++ src++;
++ }
++ }
++ if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
++ CX18_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size);
++ release_firmware(fw);
++ return size;
++}
+
-+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
++static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx, long size)
++{
++ const struct firmware *fw = NULL;
++ int retries = 3;
++ int i, j;
++ const u32 *src;
++ struct cx18_apu_rom_seghdr seghdr;
++ const u8 *vers;
++ u32 offset = 0;
++ u32 apu_version = 0;
++ int sz;
+
-+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
++retry:
++ if (!retries || request_firmware(&fw, fn, &cx->dev->dev)) {
++ CX18_ERR("unable to open firmware %s (must be %ld bytes)\n",
++ fn, size);
++ CX18_ERR("did you put the firmware in the hotplug firmware directory?\n");
++ return -ENOMEM;
++ }
+
-+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
++ src = (const u32 *)fw->data;
++ vers = fw->data + sizeof(seghdr);
++ sz = fw->size;
++
++ if (fw->size != size) {
++ /* Due to race conditions in firmware loading (esp. with
++ udev <0.95) the wrong file was sometimes loaded. So we check
++ filesizes to see if at least the right-sized file was
++ loaded. If not, then we retry. */
++ CX18_INFO("retry: file loaded was not %s (expected size %ld, got %zd)\n",
++ fn, size, fw->size);
++ release_firmware(fw);
++ retries--;
++ goto retry;
++ }
++ apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32];
++ while (offset + sizeof(seghdr) < size) {
++ /* TODO: byteswapping */
++ memcpy(&seghdr, src + offset / 4, sizeof(seghdr));
++ offset += sizeof(seghdr);
++ if (seghdr.sync1 != APU_ROM_SYNC1 ||
++ seghdr.sync2 != APU_ROM_SYNC2) {
++ offset += seghdr.size;
++ continue;
++ }
++ CX18_DEBUG_INFO("load segment %x-%x\n", seghdr.addr,
++ seghdr.addr + seghdr.size - 1);
++ if (offset + seghdr.size > sz)
++ break;
++ for (i = 0; i < seghdr.size; i += 4096) {
++ setup_page(offset + i);
++ for (j = i; j < seghdr.size && j < i + 4096; j += 4) {
++ /* no need for endianness conversion on the ppc */
++ __raw_writel(src[(offset + j) / 4], dst + seghdr.addr + j);
++ if (__raw_readl(dst + seghdr.addr + j) != src[(offset + j) / 4]) {
++ CX18_ERR("Mismatch at offset %x\n", offset + j);
++ release_firmware(fw);
++ return -EIO;
++ }
++ }
++ }
++ offset += seghdr.size;
++ }
++ if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
++ CX18_INFO("loaded %s firmware V%08x (%zd bytes)\n",
++ fn, apu_version, fw->size);
++ release_firmware(fw);
++ /* Clear bit0 for APU to start from 0 */
++ write_reg(read_reg(0xc72030) & ~1, 0xc72030);
++ return size;
++}
+
-+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
++void cx18_halt_firmware(struct cx18 *cx)
++{
++ CX18_DEBUG_INFO("Preparing for firmware halt.\n");
++ write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
++ write_reg(0x00020002, CX18_ADEC_CONTROL);
++}
+
- 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
++void cx18_init_power(struct cx18 *cx, int lowpwr)
++{
++ /* power-down Spare and AOM PLLs */
++ /* power-up fast, slow and mpeg PLLs */
++ write_reg(0x00000008, CX18_PLL_POWER_DOWN);
+
-+obj-$(CONFIG_VIDEO_AU0828) += au0828/
++ /* ADEC out of sleep */
++ write_reg(0x00020000, CX18_ADEC_CONTROL);
+
- 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
++ /* The fast clock is at 200/245 MHz */
++ write_reg(lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
++ write_reg(lowpwr ? 0x1EFBF37 : 0x038E3D7, CX18_FAST_CLOCK_PLL_FRAC);
++
++ write_reg(2, CX18_FAST_CLOCK_PLL_POST);
++ write_reg(1, CX18_FAST_CLOCK_PLL_PRESCALE);
++ write_reg(4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH);
++
++ /* set slow clock to 125/120 MHz */
++ write_reg(lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT);
++ write_reg(lowpwr ? 0xEBAF05 : 0x18618A8, CX18_SLOW_CLOCK_PLL_FRAC);
++ write_reg(4, CX18_SLOW_CLOCK_PLL_POST);
++
++ /* mpeg clock pll 54MHz */
++ write_reg(0xF, CX18_MPEG_CLOCK_PLL_INT);
++ write_reg(0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC);
++ write_reg(8, CX18_MPEG_CLOCK_PLL_POST);
++
++ /* Defaults */
++ /* APU = SC or SC/2 = 125/62.5 */
++ /* EPU = SC = 125 */
++ /* DDR = FC = 180 */
++ /* ENC = SC = 125 */
++ /* AI1 = SC = 125 */
++ /* VIM2 = disabled */
++ /* PCI = FC/2 = 90 */
++ /* AI2 = disabled */
++ /* DEMUX = disabled */
++ /* AO = SC/2 = 62.5 */
++ /* SER = 54MHz */
++ /* VFC = disabled */
++ /* USB = disabled */
++
++ write_reg(lowpwr ? 0xFFFF0020 : 0x00060004, CX18_CLOCK_SELECT1);
++ write_reg(lowpwr ? 0xFFFF0004 : 0x00060006, CX18_CLOCK_SELECT2);
++
++ write_reg(0xFFFF0002, CX18_HALF_CLOCK_SELECT1);
++ write_reg(0xFFFF0104, CX18_HALF_CLOCK_SELECT2);
++
++ write_reg(0xFFFF9026, CX18_CLOCK_ENABLE1);
++ write_reg(0xFFFF3105, CX18_CLOCK_ENABLE2);
++}
++
++void cx18_init_memory(struct cx18 *cx)
++{
++ cx18_msleep_timeout(10, 0);
++ write_reg(0x10000, CX18_DDR_SOFT_RESET);
++ cx18_msleep_timeout(10, 0);
++
++ write_reg(cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
++
++ cx18_msleep_timeout(10, 0);
++
++ write_reg(cx->card->ddr.refresh, CX18_DDR_REFRESH);
++ write_reg(cx->card->ddr.timing1, CX18_DDR_TIMING1);
++ write_reg(cx->card->ddr.timing2, CX18_DDR_TIMING2);
++
++ cx18_msleep_timeout(10, 0);
++
++ /* Initialize DQS pad time */
++ write_reg(cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE);
++ write_reg(cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS);
++
++ cx18_msleep_timeout(10, 0);
++
++ write_reg(0x20000, CX18_DDR_SOFT_RESET);
++ cx18_msleep_timeout(10, 0);
++
++ /* use power-down mode when idle */
++ write_reg(0x00000010, CX18_DDR_POWER_REG);
++
++ write_reg(0x10001, CX18_REG_BUS_TIMEOUT_EN);
++
++ write_reg(0x48, CX18_DDR_MB_PER_ROW_7);
++ write_reg(0xE0000, CX18_DDR_BASE_63_ADDR);
++
++ write_reg(0x00000101, CX18_WMB_CLIENT02); /* AO */
++ write_reg(0x00000101, CX18_WMB_CLIENT09); /* AI2 */
++ write_reg(0x00000101, CX18_WMB_CLIENT05); /* VIM1 */
++ write_reg(0x00000101, CX18_WMB_CLIENT06); /* AI1 */
++ write_reg(0x00000101, CX18_WMB_CLIENT07); /* 3D comb */
++ write_reg(0x00000101, CX18_WMB_CLIENT10); /* ME */
++ write_reg(0x00000101, CX18_WMB_CLIENT12); /* ENC */
++ write_reg(0x00000101, CX18_WMB_CLIENT13); /* PK */
++ write_reg(0x00000101, CX18_WMB_CLIENT11); /* RC */
++ write_reg(0x00000101, CX18_WMB_CLIENT14); /* AVO */
++}
++
++int cx18_firmware_init(struct cx18 *cx)
++{
++ /* Allow chip to control CLKRUN */
++ write_reg(0x5, CX18_DSP0_INTERRUPT_MASK);
++
++ write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
++
++ cx18_msleep_timeout(1, 0);
++
++ sw1_irq_enable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
++ sw2_irq_enable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
++
++ /* Only if the processor is not running */
++ if (read_reg(CX18_PROC_SOFT_RESET) & 8) {
++ int sz = load_apu_fw_direct("v4l-cx23418-apu.fw",
++ cx->enc_mem, cx, CX18_FW_APU_SIZE);
++
++ sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw",
++ cx->enc_mem, cx, CX18_FW_CPU_SIZE);
++
++ if (sz > 0) {
++ int retries = 0;
++
++ /* start the CPU */
++ write_reg(0x00080000, CX18_PROC_SOFT_RESET);
++ while (retries++ < 50) { /* Loop for max 500mS */
++ if ((read_reg(CX18_PROC_SOFT_RESET) & 1) == 0)
++ break;
++ cx18_msleep_timeout(10, 0);
++ }
++ cx18_msleep_timeout(200, 0);
++ if (retries == 51) {
++ CX18_ERR("Could not start the CPU\n");
++ return -EIO;
++ }
++ }
++ if (sz <= 0)
++ return -EIO;
++ }
++ /* initialize GPIO */
++ write_reg(0x14001400, 0xC78110);
++ return 0;
++}
+diff --git a/drivers/media/video/cx18/cx18-firmware.h b/drivers/media/video/cx18/cx18-firmware.h
new file mode 100644
-index 0000000..4170826
+index 0000000..38d4c05
--- /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.
++++ b/drivers/media/video/cx18/cx18-firmware.h
+@@ -0,0 +1,25 @@
++/*
++ * cx18 firmware functions
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
-+ 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
++int cx18_firmware_init(struct cx18 *cx);
++void cx18_halt_firmware(struct cx18 *cx);
++void cx18_init_memory(struct cx18 *cx);
++void cx18_init_power(struct cx18 *cx, int lowpwr);
+diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c
new file mode 100644
-index 0000000..9f4f572
+index 0000000..19253e6
--- /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
++++ b/drivers/media/video/cx18/cx18-gpio.c
+@@ -0,0 +1,74 @@
++/*
++ * cx18 gpio functions
++ *
++ * Derived from ivtv-gpio.c
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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 "cx18-driver.h"
++#include "cx18-cards.h"
++#include "cx18-gpio.h"
++#include "tuner-xc2028.h"
++
++/********************* GPIO stuffs *********************/
++
++/* GPIO registers */
++#define CX18_REG_GPIO_IN 0xc72010
++#define CX18_REG_GPIO_OUT1 0xc78100
++#define CX18_REG_GPIO_DIR1 0xc78108
++#define CX18_REG_GPIO_OUT2 0xc78104
++#define CX18_REG_GPIO_DIR2 0xc7810c
++
++/*
++ * HVR-1600 GPIO pins, courtesy of Hauppauge:
++ *
++ * gpio0: zilog ir process reset pin
++ * gpio1: zilog programming pin (you should never use this)
++ * gpio12: cx24227 reset pin
++ * gpio13: cs5345 reset pin
++*/
++
++void cx18_gpio_init(struct cx18 *cx)
++{
++ if (cx->card->gpio_init.direction == 0)
++ return;
+
-+obj-$(CONFIG_VIDEO_AU0828) += au0828.o
++ CX18_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n",
++ read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_OUT1));
+
-+EXTRA_CFLAGS += -Idrivers/media/video
-+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
++ /* init output data then direction */
++ write_reg(cx->card->gpio_init.direction << 16, CX18_REG_GPIO_DIR1);
++ write_reg(0, CX18_REG_GPIO_DIR2);
++ write_reg((cx->card->gpio_init.direction << 16) |
++ cx->card->gpio_init.initial_value, CX18_REG_GPIO_OUT1);
++ write_reg(0, CX18_REG_GPIO_OUT2);
++}
+
-+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
++/* Xceive tuner reset function */
++int cx18_reset_tuner_gpio(void *dev, int cmd, int value)
++{
++ struct i2c_algo_bit_data *algo = dev;
++ struct cx18 *cx = algo->data;
++/* int curdir, curout;*/
++
++ if (cmd != XC2028_TUNER_RESET)
++ return 0;
++ CX18_DEBUG_INFO("Resetting tuner\n");
++ return 0;
++}
+diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/video/cx18/cx18-gpio.h
new file mode 100644
-index 0000000..a2a6983
+index 0000000..41bac88
--- /dev/null
-+++ b/drivers/media/video/au0828/au0828-cards.c
-@@ -0,0 +1,181 @@
++++ b/drivers/media/video/cx18/cx18-gpio.h
+@@ -0,0 +1,24 @@
+/*
-+ * Driver for the Auvitek USB bridge
++ * cx18 gpio functions
+ *
-+ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ * Derived from ivtv-gpio.h
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
@@ -389698,184 +552134,464 @@
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
++
++void cx18_gpio_init(struct cx18 *cx);
++int cx18_reset_tuner_gpio(void *dev, int cmd, int value);
+diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c
+new file mode 100644
+index 0000000..18c88d1
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-i2c.c
+@@ -0,0 +1,431 @@
++/*
++ * cx18 I2C functions
++ *
++ * Derived from ivtv-i2c.c
+ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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.
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ * 02111-1307 USA
+ */
+
-+#include "au0828.h"
-+#include "au0828-cards.h"
++#include "cx18-driver.h"
++#include "cx18-cards.h"
++#include "cx18-gpio.h"
++#include "cx18-av-core.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",
-+ },
++#include <media/ir-kbd-i2c.h>
++
++#define CX18_REG_I2C_1_WR 0xf15000
++#define CX18_REG_I2C_1_RD 0xf15008
++#define CX18_REG_I2C_2_WR 0xf25100
++#define CX18_REG_I2C_2_RD 0xf25108
++
++#define SETSCL_BIT 0x0001
++#define SETSDL_BIT 0x0002
++#define GETSCL_BIT 0x0004
++#define GETSDL_BIT 0x0008
++
++#ifndef I2C_ADAP_CLASS_TV_ANALOG
++#define I2C_ADAP_CLASS_TV_ANALOG I2C_CLASS_TV_ANALOG
++#endif
++
++#define CX18_CS5345_I2C_ADDR 0x4c
++
++/* This array should match the CX18_HW_ defines */
++static const u8 hw_driverids[] = {
++ I2C_DRIVERID_TUNER,
++ I2C_DRIVERID_TVEEPROM,
++ I2C_DRIVERID_CS5345,
++ 0, /* CX18_HW_GPIO dummy driver ID */
++ 0 /* CX18_HW_CX23418 dummy driver ID */
+};
+
-+/* 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)
++/* This array should match the CX18_HW_ defines */
++static const u8 hw_addrs[] = {
++ 0,
++ 0,
++ CX18_CS5345_I2C_ADDR,
++ 0, /* CX18_HW_GPIO dummy driver ID */
++ 0, /* CX18_HW_CX23418 dummy driver ID */
++};
++
++/* This array should match the CX18_HW_ defines */
++/* This might well become a card-specific array */
++static const u8 hw_bus[] = {
++ 0,
++ 0,
++ 0,
++ 0, /* CX18_HW_GPIO dummy driver ID */
++ 0, /* CX18_HW_CX23418 dummy driver ID */
++};
++
++/* This array should match the CX18_HW_ defines */
++static const char * const hw_drivernames[] = {
++ "tuner",
++ "tveeprom",
++ "cs5345",
++ "gpio",
++ "cx23418",
++};
++
++int cx18_i2c_register(struct cx18 *cx, unsigned idx)
+{
-+ struct au0828_dev *dev = priv;
++ struct i2c_board_info info;
++ struct i2c_client *c;
++ u8 id, bus;
++ int i;
+
-+ dprintk(1, "%s()\n", __func__);
++ CX18_DEBUG_I2C("i2c client register\n");
++ if (idx >= ARRAY_SIZE(hw_driverids) || hw_driverids[idx] == 0)
++ return -1;
++ id = hw_driverids[idx];
++ bus = hw_bus[idx];
++ memset(&info, 0, sizeof(info));
++ strlcpy(info.driver_name, hw_drivernames[idx],
++ sizeof(info.driver_name));
++ info.addr = hw_addrs[idx];
++ for (i = 0; i < I2C_CLIENTS_MAX; i++)
++ if (cx->i2c_clients[i] == NULL)
++ break;
+
-+ 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;
++ if (i == I2C_CLIENTS_MAX) {
++ CX18_ERR("insufficient room for new I2C client!\n");
++ return -ENOMEM;
+ }
+
-+ return 0; /* Should never be here */
++ if (id != I2C_DRIVERID_TUNER) {
++ c = i2c_new_device(&cx->i2c_adap[bus], &info);
++ if (c->driver == NULL)
++ i2c_unregister_device(c);
++ else
++ cx->i2c_clients[i] = c;
++ return cx->i2c_clients[i] ? 0 : -ENODEV;
++ }
++
++ /* special tuner handling */
++ c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->radio);
++ if (c && c->driver == NULL)
++ i2c_unregister_device(c);
++ else if (c)
++ cx->i2c_clients[i++] = c;
++ c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->demod);
++ if (c && c->driver == NULL)
++ i2c_unregister_device(c);
++ else if (c)
++ cx->i2c_clients[i++] = c;
++ c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->tv);
++ if (c && c->driver == NULL)
++ i2c_unregister_device(c);
++ else if (c)
++ cx->i2c_clients[i++] = c;
++ return 0;
+}
+
-+static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
++static int attach_inform(struct i2c_client *client)
+{
-+ struct tveeprom tv;
++ return 0;
++}
+
-+ tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data);
++static int detach_inform(struct i2c_client *client)
++{
++ int i;
++ struct cx18 *cx = (struct cx18 *)i2c_get_adapdata(client->adapter);
+
-+ /* 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;
++ CX18_DEBUG_I2C("i2c client detach\n");
++ for (i = 0; i < I2C_CLIENTS_MAX; i++) {
++ if (cx->i2c_clients[i] == client) {
++ cx->i2c_clients[i] = NULL;
++ break;
++ }
+ }
++ CX18_DEBUG_I2C("i2c detach [client=%s,%s]\n",
++ client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed");
+
-+ printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
-+ __func__, tv.model);
++ return 0;
+}
+
-+void au0828_card_setup(struct au0828_dev *dev)
++static void cx18_setscl(void *data, int state)
+{
-+ static u8 eeprom[256];
++ struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
++ int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
++ u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
++ u32 r = read_reg(addr);
+
-+ dprintk(1, "%s()\n", __func__);
++ if (state)
++ write_reg_sync(r | SETSCL_BIT, addr);
++ else
++ write_reg_sync(r & ~SETSCL_BIT, addr);
++}
+
-+ if (dev->i2c_rc == 0) {
-+ dev->i2c_client.addr = 0xa0 >> 1;
-+ tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom));
++static void cx18_setsda(void *data, int state)
++{
++ struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
++ int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
++ u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
++ u32 r = read_reg(addr);
++
++ if (state)
++ write_reg_sync(r | SETSDL_BIT, addr);
++ else
++ write_reg_sync(r & ~SETSDL_BIT, addr);
++}
++
++static int cx18_getscl(void *data)
++{
++ struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
++ int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
++ u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
++
++ return read_reg(addr) & GETSCL_BIT;
++}
++
++static int cx18_getsda(void *data)
++{
++ struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
++ int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
++ u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
++
++ return read_reg(addr) & GETSDL_BIT;
++}
++
++/* template for i2c-bit-algo */
++static struct i2c_adapter cx18_i2c_adap_template = {
++ .name = "cx18 i2c driver",
++ .id = I2C_HW_B_CX2341X,
++ .algo = NULL, /* set by i2c-algo-bit */
++ .algo_data = NULL, /* filled from template */
++ .client_register = attach_inform,
++ .client_unregister = detach_inform,
++ .owner = THIS_MODULE,
++};
++
++#define CX18_SCL_PERIOD (10) /* usecs. 10 usec is period for a 100 KHz clock */
++#define CX18_ALGO_BIT_TIMEOUT (2) /* seconds */
++
++static struct i2c_algo_bit_data cx18_i2c_algo_template = {
++ .setsda = cx18_setsda,
++ .setscl = cx18_setscl,
++ .getsda = cx18_getsda,
++ .getscl = cx18_getscl,
++ .udelay = CX18_SCL_PERIOD/2, /* 1/2 clock period in usec*/
++ .timeout = CX18_ALGO_BIT_TIMEOUT*HZ /* jiffies */
++};
++
++static struct i2c_client cx18_i2c_client_template = {
++ .name = "cx18 internal",
++};
++
++int cx18_call_i2c_client(struct cx18 *cx, int addr, unsigned cmd, void *arg)
++{
++ struct i2c_client *client;
++ int retval;
++ int i;
++
++ CX18_DEBUG_I2C("call_i2c_client addr=%02x\n", addr);
++ for (i = 0; i < I2C_CLIENTS_MAX; i++) {
++ client = cx->i2c_clients[i];
++ if (client == NULL || client->driver == NULL ||
++ client->driver->command == NULL)
++ continue;
++ if (addr == client->addr) {
++ retval = client->driver->command(client, cmd, arg);
++ return retval;
++ }
+ }
++ if (cmd != VIDIOC_G_CHIP_IDENT)
++ CX18_ERR("i2c addr 0x%02x not found for cmd 0x%x!\n",
++ addr, cmd);
++ return -ENODEV;
++}
+
-+ switch (dev->board) {
-+ case AU0828_BOARD_HAUPPAUGE_HVR850:
-+ case AU0828_BOARD_HAUPPAUGE_HVR950Q:
-+ if (dev->i2c_rc == 0)
-+ hauppauge_eeprom(dev, eeprom+0xa0);
-+ break;
++/* Find the i2c device based on the driver ID and return
++ its i2c address or -ENODEV if no matching device was found. */
++static int cx18_i2c_id_addr(struct cx18 *cx, u32 id)
++{
++ struct i2c_client *client;
++ int retval = -ENODEV;
++ int i;
++
++ for (i = 0; i < I2C_CLIENTS_MAX; i++) {
++ client = cx->i2c_clients[i];
++ if (client == NULL || client->driver == NULL)
++ continue;
++ if (id == client->driver->id) {
++ retval = client->addr;
++ break;
++ }
+ }
++ return retval;
+}
+
-+/*
-+ * 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)
++/* Find the i2c device name matching the DRIVERID */
++static const char *cx18_i2c_id_name(u32 id)
+{
-+ dprintk(1, "%s()\n", __func__);
++ int i;
+
-+ 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
-+ */
++ for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
++ if (hw_driverids[i] == id)
++ return hw_drivernames[i];
++ return "unknown device";
++}
+
-+ /* 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);
++/* Find the i2c device name matching the CX18_HW_ flag */
++static const char *cx18_i2c_hw_name(u32 hw)
++{
++ int i;
+
-+ /* 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
-+ */
++ for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
++ if (1 << i == hw)
++ return hw_drivernames[i];
++ return "unknown device";
++}
+
-+ /* 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);
++/* Find the i2c device matching the CX18_HW_ flag and return
++ its i2c address or -ENODEV if no matching device was found. */
++int cx18_i2c_hw_addr(struct cx18 *cx, u32 hw)
++{
++ int i;
+
-+ /* 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;
++ for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
++ if (1 << i == hw)
++ return cx18_i2c_id_addr(cx, hw_driverids[i]);
++ return -ENODEV;
++}
++
++/* Calls i2c device based on CX18_HW_ flag. If hw == 0, then do nothing.
++ If hw == CX18_HW_GPIO then call the gpio handler. */
++int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg)
++{
++ int addr;
++
++ if (hw == CX18_HW_GPIO || hw == 0)
++ return 0;
++ if (hw == CX18_HW_CX23418)
++ return cx18_av_cmd(cx, cmd, arg);
++
++ addr = cx18_i2c_hw_addr(cx, hw);
++ if (addr < 0) {
++ CX18_ERR("i2c hardware 0x%08x (%s) not found for cmd 0x%x!\n",
++ hw, cx18_i2c_hw_name(hw), cmd);
++ return addr;
+ }
++ return cx18_call_i2c_client(cx, addr, cmd, arg);
+}
+
-+/* 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 },
-+ { },
-+};
++/* Calls i2c device based on I2C driver ID. */
++int cx18_i2c_id(struct cx18 *cx, u32 id, unsigned int cmd, void *arg)
++{
++ int addr;
+
-+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
++ addr = cx18_i2c_id_addr(cx, id);
++ if (addr < 0) {
++ if (cmd != VIDIOC_G_CHIP_IDENT)
++ CX18_ERR("i2c ID 0x%08x (%s) not found for cmd 0x%x!\n",
++ id, cx18_i2c_id_name(id), cmd);
++ return addr;
++ }
++ return cx18_call_i2c_client(cx, addr, cmd, arg);
++}
++
++/* broadcast cmd for all I2C clients and for the gpio subsystem */
++void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg)
++{
++ if (cx->i2c_adap[0].algo == NULL || cx->i2c_adap[1].algo == NULL) {
++ CX18_ERR("adapter is not set\n");
++ return;
++ }
++ cx18_av_cmd(cx, cmd, arg);
++ i2c_clients_command(&cx->i2c_adap[0], cmd, arg);
++ i2c_clients_command(&cx->i2c_adap[1], cmd, arg);
++}
++
++/* init + register i2c algo-bit adapter */
++int init_cx18_i2c(struct cx18 *cx)
++{
++ int i;
++ CX18_DEBUG_I2C("i2c init\n");
++
++ for (i = 0; i < 2; i++) {
++ memcpy(&cx->i2c_adap[i], &cx18_i2c_adap_template,
++ sizeof(struct i2c_adapter));
++ memcpy(&cx->i2c_algo[i], &cx18_i2c_algo_template,
++ sizeof(struct i2c_algo_bit_data));
++ cx->i2c_algo_cb_data[i].cx = cx;
++ cx->i2c_algo_cb_data[i].bus_index = i;
++ cx->i2c_algo[i].data = &cx->i2c_algo_cb_data[i];
++ cx->i2c_adap[i].algo_data = &cx->i2c_algo[i];
++
++ sprintf(cx->i2c_adap[i].name + strlen(cx->i2c_adap[i].name),
++ " #%d-%d", cx->num, i);
++ i2c_set_adapdata(&cx->i2c_adap[i], cx);
++
++ memcpy(&cx->i2c_client[i], &cx18_i2c_client_template,
++ sizeof(struct i2c_client));
++ sprintf(cx->i2c_client[i].name +
++ strlen(cx->i2c_client[i].name), "%d", i);
++ cx->i2c_client[i].adapter = &cx->i2c_adap[i];
++ cx->i2c_adap[i].dev.parent = &cx->dev->dev;
++ }
++
++ if (read_reg(CX18_REG_I2C_2_WR) != 0x0003c02f) {
++ /* Reset/Unreset I2C hardware block */
++ write_reg(0x10000000, 0xc71004); /* Clock select 220MHz */
++ write_reg_sync(0x10001000, 0xc71024); /* Clock Enable */
++ }
++ /* courtesy of Steven Toth <stoth at hauppauge.com> */
++ write_reg_sync(0x00c00000, 0xc7001c);
++ mdelay(10);
++ write_reg_sync(0x00c000c0, 0xc7001c);
++ mdelay(10);
++ write_reg_sync(0x00c00000, 0xc7001c);
++
++ write_reg_sync(0x00c00000, 0xc730c8); /* Set to edge-triggered intrs. */
++ write_reg_sync(0x00c00000, 0xc730c4); /* Clear any stale intrs */
++
++ /* Hw I2C1 Clock Freq ~100kHz */
++ write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_1_WR);
++ cx18_setscl(&cx->i2c_algo_cb_data[0], 1);
++ cx18_setsda(&cx->i2c_algo_cb_data[0], 1);
++
++ /* Hw I2C2 Clock Freq ~100kHz */
++ write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_2_WR);
++ cx18_setscl(&cx->i2c_algo_cb_data[1], 1);
++ cx18_setsda(&cx->i2c_algo_cb_data[1], 1);
++
++ return i2c_bit_add_bus(&cx->i2c_adap[0]) ||
++ i2c_bit_add_bus(&cx->i2c_adap[1]);
++}
++
++void exit_cx18_i2c(struct cx18 *cx)
++{
++ int i;
++ CX18_DEBUG_I2C("i2c exit\n");
++ write_reg(read_reg(CX18_REG_I2C_1_WR) | 4, CX18_REG_I2C_1_WR);
++ write_reg(read_reg(CX18_REG_I2C_2_WR) | 4, CX18_REG_I2C_2_WR);
++
++ for (i = 0; i < 2; i++) {
++ i2c_del_adapter(&cx->i2c_adap[i]);
++ }
++}
++
++/*
++ Hauppauge HVR1600 should have:
++ 32 cx24227
++ 98 unknown
++ a0 eeprom
++ c2 tuner
++ e? zilog ir
++ */
+diff --git a/drivers/media/video/cx18/cx18-i2c.h b/drivers/media/video/cx18/cx18-i2c.h
new file mode 100644
-index 0000000..e26f54a
+index 0000000..113c3f9
--- /dev/null
-+++ b/drivers/media/video/au0828/au0828-cards.h
-@@ -0,0 +1,25 @@
++++ b/drivers/media/video/cx18/cx18-i2c.h
+@@ -0,0 +1,33 @@
+/*
-+ * Driver for the Auvitek USB bridge
++ * cx18 I2C functions
+ *
-+ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ * Derived from ivtv-i2c.h
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
@@ -389885,28 +552601,36 @@
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ *
+ * GNU General Public License for more details.
+ *
+ * You 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.
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ * 02111-1307 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
++int cx18_i2c_hw_addr(struct cx18 *cx, u32 hw);
++int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg);
++int cx18_i2c_id(struct cx18 *cx, u32 id, unsigned int cmd, void *arg);
++int cx18_call_i2c_client(struct cx18 *cx, int addr, unsigned cmd, void *arg);
++void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg);
++int cx18_i2c_register(struct cx18 *cx, unsigned idx);
++
++/* init + register i2c algo-bit adapter */
++int init_cx18_i2c(struct cx18 *cx);
++void exit_cx18_i2c(struct cx18 *cx);
+diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
new file mode 100644
-index 0000000..54bfc0f
+index 0000000..dbdcb86
--- /dev/null
-+++ b/drivers/media/video/au0828/au0828-core.c
-@@ -0,0 +1,256 @@
++++ b/drivers/media/video/cx18/cx18-ioctl.c
+@@ -0,0 +1,851 @@
+/*
-+ * Driver for the Auvitek USB bridge
++ * cx18 ioctl system call
+ *
-+ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ * Derived from ivtv-ioctl.c
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
@@ -389916,259 +552640,854 @@
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ *
+ * GNU General Public License for more details.
+ *
+ * You 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.
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ * 02111-1307 USA
+ */
+
-+#include <linux/module.h>
-+#include <linux/videodev2.h>
-+#include <media/v4l2-common.h>
-+#include <linux/mutex.h>
-+
-+#include "au0828.h"
++#include "cx18-driver.h"
++#include "cx18-version.h"
++#include "cx18-mailbox.h"
++#include "cx18-i2c.h"
++#include "cx18-queue.h"
++#include "cx18-fileops.h"
++#include "cx18-vbi.h"
++#include "cx18-audio.h"
++#include "cx18-video.h"
++#include "cx18-streams.h"
++#include "cx18-ioctl.h"
++#include "cx18-gpio.h"
++#include "cx18-controls.h"
++#include "cx18-cards.h"
++#include "cx18-av-core.h"
++#include <media/tveeprom.h>
++#include <media/v4l2-chip-ident.h>
++#include <linux/i2c-id.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");
++u16 cx18_service2vbi(int type)
++{
++ switch (type) {
++ case V4L2_SLICED_TELETEXT_B:
++ return CX18_SLICED_TYPE_TELETEXT_B;
++ case V4L2_SLICED_CAPTION_525:
++ return CX18_SLICED_TYPE_CAPTION_525;
++ case V4L2_SLICED_WSS_625:
++ return CX18_SLICED_TYPE_WSS_625;
++ case V4L2_SLICED_VPS:
++ return CX18_SLICED_TYPE_VPS;
++ default:
++ return 0;
++ }
++}
+
-+#define _AU0828_BULKPIPE 0x03
-+#define _BULKPIPESIZE 0xffff
++static int valid_service_line(int field, int line, int is_pal)
++{
++ return (is_pal && line >= 6 && (line != 23 || field == 0)) ||
++ (!is_pal && line >= 10 && line < 22);
++}
+
-+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);
++static u16 select_service_from_set(int field, int line, u16 set, int is_pal)
++{
++ u16 valid_set = (is_pal ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525);
++ int i;
+
-+/* USB Direction */
-+#define CMD_REQUEST_IN 0x00
-+#define CMD_REQUEST_OUT 0x01
++ set = set & valid_set;
++ if (set == 0 || !valid_service_line(field, line, is_pal))
++ return 0;
++ if (!is_pal) {
++ if (line == 21 && (set & V4L2_SLICED_CAPTION_525))
++ return V4L2_SLICED_CAPTION_525;
++ } else {
++ if (line == 16 && field == 0 && (set & V4L2_SLICED_VPS))
++ return V4L2_SLICED_VPS;
++ if (line == 23 && field == 0 && (set & V4L2_SLICED_WSS_625))
++ return V4L2_SLICED_WSS_625;
++ if (line == 23)
++ return 0;
++ }
++ for (i = 0; i < 32; i++) {
++ if ((1 << i) & set)
++ return 1 << i;
++ }
++ return 0;
++}
+
-+u32 au0828_readreg(struct au0828_dev *dev, u16 reg)
++void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
+{
-+ 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];
++ u16 set = fmt->service_set;
++ int f, l;
++
++ fmt->service_set = 0;
++ for (f = 0; f < 2; f++) {
++ for (l = 0; l < 24; l++)
++ fmt->service_lines[f][l] = select_service_from_set(f, l, set, is_pal);
++ }
+}
+
-+u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val)
++static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
+{
-+ dprintk(8, "%s(0x%x, 0x%x)\n", __func__, reg, val);
-+ return send_control_msg(dev, CMD_REQUEST_OUT, val, reg,
-+ dev->ctrlmsg, 0);
++ int f, l;
++ u16 set = 0;
++
++ for (f = 0; f < 2; f++) {
++ for (l = 0; l < 24; l++) {
++ fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal);
++ set |= fmt->service_lines[f][l];
++ }
++ }
++ return set != 0;
+}
+
-+static void cmd_msg_dump(struct au0828_dev *dev)
++u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt)
+{
-+ int i;
++ int f, l;
++ u16 set = 0;
+
-+ 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]);
++ for (f = 0; f < 2; f++) {
++ for (l = 0; l < 24; l++)
++ set |= fmt->service_lines[f][l];
++ }
++ return set;
+}
+
-+static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
-+ u16 index, unsigned char *cp, u16 size)
++static const struct {
++ v4l2_std_id std;
++ char *name;
++} enum_stds[] = {
++ { V4L2_STD_PAL_BG | V4L2_STD_PAL_H, "PAL-BGH" },
++ { V4L2_STD_PAL_DK, "PAL-DK" },
++ { V4L2_STD_PAL_I, "PAL-I" },
++ { V4L2_STD_PAL_M, "PAL-M" },
++ { V4L2_STD_PAL_N, "PAL-N" },
++ { V4L2_STD_PAL_Nc, "PAL-Nc" },
++ { V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H, "SECAM-BGH" },
++ { V4L2_STD_SECAM_DK, "SECAM-DK" },
++ { V4L2_STD_SECAM_L, "SECAM-L" },
++ { V4L2_STD_SECAM_LC, "SECAM-L'" },
++ { V4L2_STD_NTSC_M, "NTSC-M" },
++ { V4L2_STD_NTSC_M_JP, "NTSC-J" },
++ { V4L2_STD_NTSC_M_KR, "NTSC-K" },
++};
++
++static const struct v4l2_standard cx18_std_60hz = {
++ .frameperiod = {.numerator = 1001, .denominator = 30000},
++ .framelines = 525,
++};
++
++static const struct v4l2_standard cx18_std_50hz = {
++ .frameperiod = { .numerator = 1, .denominator = 25 },
++ .framelines = 625,
++};
++
++static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
+{
-+ int status = -ENODEV;
-+ mutex_lock(&dev->mutex);
-+ if (dev->usbdev) {
++ struct v4l2_register *regs = arg;
++ unsigned long flags;
+
-+ /* 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);
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++ if (regs->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE)
++ return -EINVAL;
+
-+ status = min(status, 0);
++ spin_lock_irqsave(&cx18_cards_lock, flags);
++ if (cmd == VIDIOC_DBG_G_REGISTER)
++ regs->val = read_enc(regs->reg);
++ else
++ write_enc(regs->val, regs->reg);
++ spin_unlock_irqrestore(&cx18_cards_lock, flags);
++ return 0;
++}
+
-+ if (status < 0) {
-+ printk(KERN_ERR "%s() Failed sending control message, error %d.\n",
-+ __func__, status);
++static int cx18_get_fmt(struct cx18 *cx, int streamtype, struct v4l2_format *fmt)
++{
++ switch (fmt->type) {
++ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
++ fmt->fmt.pix.width = cx->params.width;
++ fmt->fmt.pix.height = cx->params.height;
++ fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
++ fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
++ if (streamtype == CX18_ENC_STREAM_TYPE_YUV) {
++ fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12;
++ /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
++ fmt->fmt.pix.sizeimage =
++ fmt->fmt.pix.height * fmt->fmt.pix.width +
++ fmt->fmt.pix.height * (fmt->fmt.pix.width / 2);
++ } else {
++ fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
++ fmt->fmt.pix.sizeimage = 128 * 1024;
+ }
++ break;
++
++ case V4L2_BUF_TYPE_VBI_CAPTURE:
++ fmt->fmt.vbi.sampling_rate = 27000000;
++ fmt->fmt.vbi.offset = 248;
++ fmt->fmt.vbi.samples_per_line = cx->vbi.raw_decoder_line_size - 4;
++ fmt->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
++ fmt->fmt.vbi.start[0] = cx->vbi.start[0];
++ fmt->fmt.vbi.start[1] = cx->vbi.start[1];
++ fmt->fmt.vbi.count[0] = fmt->fmt.vbi.count[1] = cx->vbi.count;
++ break;
++
++ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
++ {
++ struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
++
++ vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
++ memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));
++ memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));
+
++ cx18_av_cmd(cx, VIDIOC_G_FMT, fmt);
++ vbifmt->service_set = cx18_get_service_set(vbifmt);
++ break;
+ }
-+ mutex_unlock(&dev->mutex);
-+ return status;
++ default:
++ return -EINVAL;
++ }
++ return 0;
+}
+
-+static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
-+ u16 index, unsigned char *cp, u16 size)
++static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype,
++ struct v4l2_format *fmt, int set_fmt)
+{
-+ int status = -ENODEV;
-+ mutex_lock(&dev->mutex);
-+ if (dev->usbdev) {
++ struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
++ u16 set;
+
-+ memset(dev->ctrlmsg, 0, sizeof(dev->ctrlmsg));
++ /* set window size */
++ if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
++ int w = fmt->fmt.pix.width;
++ int h = fmt->fmt.pix.height;
++
++ if (w > 720)
++ w = 720;
++ else if (w < 1)
++ w = 1;
++ if (h > (cx->is_50hz ? 576 : 480))
++ h = (cx->is_50hz ? 576 : 480);
++ else if (h < 2)
++ h = 2;
++ cx18_get_fmt(cx, streamtype, fmt);
++ fmt->fmt.pix.width = w;
++ fmt->fmt.pix.height = h;
+
-+ /* 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);
++ if (!set_fmt || (cx->params.width == w && cx->params.height == h))
++ return 0;
++ if (atomic_read(&cx->capturing) > 0)
++ return -EBUSY;
+
-+ status = min(status, 0);
++ cx->params.width = w;
++ cx->params.height = h;
++ if (w != 720 || h != (cx->is_50hz ? 576 : 480))
++ cx->params.video_temporal_filter = 0;
++ else
++ cx->params.video_temporal_filter = 8;
++ cx18_av_cmd(cx, VIDIOC_S_FMT, fmt);
++ return cx18_get_fmt(cx, streamtype, fmt);
++ }
+
-+ if (status < 0) {
-+ printk(KERN_ERR "%s() Failed receiving control message, error %d.\n",
-+ __func__, status);
-+ } else
-+ cmd_msg_dump(dev);
++ /* set raw VBI format */
++ if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
++ if (set_fmt && streamtype == CX18_ENC_STREAM_TYPE_VBI &&
++ cx->vbi.sliced_in->service_set &&
++ atomic_read(&cx->capturing) > 0)
++ return -EBUSY;
++ if (set_fmt) {
++ cx->vbi.sliced_in->service_set = 0;
++ cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in);
++ }
++ return cx18_get_fmt(cx, streamtype, fmt);
+ }
-+ mutex_unlock(&dev->mutex);
-+ return status;
-+}
+
-+static void au0828_usb_disconnect(struct usb_interface *interface)
-+{
-+ struct au0828_dev *dev = usb_get_intfdata(interface);
++ /* any else but sliced VBI capture is an error */
++ if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
++ return -EINVAL;
+
-+ dprintk(1, "%s()\n", __func__);
++ /* TODO: implement sliced VBI, for now silently return 0 */
++ return 0;
+
-+ /* Digital TV */
-+ au0828_dvb_unregister(dev);
++ /* set sliced VBI capture format */
++ vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
++ memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));
+
-+ /* I2C */
-+ au0828_i2c_unregister(dev);
++ if (vbifmt->service_set)
++ cx18_expand_service_set(vbifmt, cx->is_50hz);
++ set = check_service_set(vbifmt, cx->is_50hz);
++ vbifmt->service_set = cx18_get_service_set(vbifmt);
+
-+ usb_set_intfdata(interface, NULL);
++ if (!set_fmt)
++ return 0;
++ if (set == 0)
++ return -EINVAL;
++ if (atomic_read(&cx->capturing) > 0 && cx->vbi.sliced_in->service_set == 0)
++ return -EBUSY;
++ cx18_av_cmd(cx, VIDIOC_S_FMT, fmt);
++ memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in));
++ return 0;
++}
+
-+ mutex_lock(&dev->mutex);
-+ dev->usbdev = NULL;
-+ mutex_unlock(&dev->mutex);
++static int cx18_debug_ioctls(struct file *filp, unsigned int cmd, void *arg)
++{
++ struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data;
++ struct cx18 *cx = id->cx;
++ struct v4l2_register *reg = arg;
+
-+ kfree(dev);
++ switch (cmd) {
++ /* ioctls to allow direct access to the encoder registers for testing */
++ case VIDIOC_DBG_G_REGISTER:
++ if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
++ return cx18_cxc(cx, cmd, arg);
++ if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
++ return cx18_i2c_id(cx, reg->match_chip, cmd, arg);
++ return cx18_call_i2c_client(cx, reg->match_chip, cmd, arg);
++
++ case VIDIOC_DBG_S_REGISTER:
++ if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
++ return cx18_cxc(cx, cmd, arg);
++ if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
++ return cx18_i2c_id(cx, reg->match_chip, cmd, arg);
++ return cx18_call_i2c_client(cx, reg->match_chip, cmd, arg);
++
++ case VIDIOC_G_CHIP_IDENT: {
++ struct v4l2_chip_ident *chip = arg;
++
++ chip->ident = V4L2_IDENT_NONE;
++ chip->revision = 0;
++ if (reg->match_type == V4L2_CHIP_MATCH_HOST) {
++ if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) {
++ struct v4l2_chip_ident *chip = arg;
++
++ chip->ident = V4L2_IDENT_CX23418;
++ }
++ return 0;
++ }
++ if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
++ return cx18_i2c_id(cx, reg->match_chip, cmd, arg);
++ if (reg->match_type == V4L2_CHIP_MATCH_I2C_ADDR)
++ return cx18_call_i2c_client(cx, reg->match_chip, cmd, arg);
++ return -EINVAL;
++ }
++
++ case VIDIOC_INT_S_AUDIO_ROUTING: {
++ struct v4l2_routing *route = arg;
++
++ cx18_audio_set_route(cx, route);
++ break;
++ }
+
++ default:
++ return -EINVAL;
++ }
++ return 0;
+}
+
-+static int au0828_usb_probe(struct usb_interface *interface,
-+ const struct usb_device_id *id)
++int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg)
+{
-+ int ifnum;
-+ struct au0828_dev *dev;
-+ struct usb_device *usbdev = interface_to_usbdev(interface);
++ struct cx18_open_id *id = NULL;
+
-+ ifnum = interface->altsetting->desc.bInterfaceNumber;
++ if (filp)
++ id = (struct cx18_open_id *)filp->private_data;
+
-+ if (ifnum != 0)
-+ return -ENODEV;
++ switch (cmd) {
++ case VIDIOC_G_PRIORITY:
++ {
++ enum v4l2_priority *p = arg;
+
-+ 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);
++ *p = v4l2_prio_max(&cx->prio);
++ break;
++ }
+
-+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-+ if (dev == NULL) {
-+ printk(KERN_ERR "%s() Unable to allocate memory\n", __func__);
-+ return -ENOMEM;
++ case VIDIOC_S_PRIORITY:
++ {
++ enum v4l2_priority *prio = arg;
++
++ return v4l2_prio_change(&cx->prio, &id->prio, *prio);
+ }
+
-+ mutex_init(&dev->mutex);
-+ mutex_init(&dev->dvb.lock);
-+ dev->usbdev = usbdev;
-+ dev->board = id->driver_info;
++ case VIDIOC_QUERYCAP:{
++ struct v4l2_capability *vcap = arg;
+
-+ usb_set_intfdata(interface, dev);
++ memset(vcap, 0, sizeof(*vcap));
++ strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
++ strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
++ strlcpy(vcap->bus_info, pci_name(cx->dev), sizeof(vcap->bus_info));
++ vcap->version = CX18_DRIVER_VERSION; /* version */
++ vcap->capabilities = cx->v4l2_cap; /* capabilities */
+
-+ /* Power Up the bridge */
-+ au0828_write(dev, REG_600, 1 << 4);
++ /* reserved.. must set to 0! */
++ vcap->reserved[0] = vcap->reserved[1] =
++ vcap->reserved[2] = vcap->reserved[3] = 0;
++ break;
++ }
+
-+ /* Bring up the GPIO's and supporting devices */
-+ au0828_gpio_setup(dev);
++ case VIDIOC_ENUMAUDIO:{
++ struct v4l2_audio *vin = arg;
+
-+ /* I2C */
-+ au0828_i2c_register(dev);
++ return cx18_get_audio_input(cx, vin->index, vin);
++ }
+
-+ /* Setup */
-+ au0828_card_setup(dev);
++ case VIDIOC_G_AUDIO:{
++ struct v4l2_audio *vin = arg;
+
-+ /* Digital TV */
-+ au0828_dvb_register(dev);
++ vin->index = cx->audio_input;
++ return cx18_get_audio_input(cx, vin->index, vin);
++ }
+
-+ printk(KERN_INFO "Registered device AU0828 [%s]\n",
-+ au0828_boards[dev->board].name == NULL ? "Unset" :
-+ au0828_boards[dev->board].name);
++ case VIDIOC_S_AUDIO:{
++ struct v4l2_audio *vout = arg;
+
-+ return 0;
-+}
++ if (vout->index >= cx->nof_audio_inputs)
++ return -EINVAL;
++ cx->audio_input = vout->index;
++ cx18_audio_set_io(cx);
++ break;
++ }
+
-+static struct usb_driver au0828_usb_driver = {
-+ .name = DRIVER_NAME,
-+ .probe = au0828_usb_probe,
-+ .disconnect = au0828_usb_disconnect,
-+ .id_table = au0828_usb_id_table,
-+};
++ case VIDIOC_ENUMINPUT:{
++ struct v4l2_input *vin = arg;
+
-+static int __init au0828_init(void)
-+{
-+ int ret;
++ /* set it to defaults from our table */
++ return cx18_get_input(cx, vin->index, vin);
++ }
+
-+ if (au0828_debug & 1)
-+ printk(KERN_INFO "%s() Debugging is enabled\n", __func__);
++ case VIDIOC_TRY_FMT:
++ case VIDIOC_S_FMT: {
++ struct v4l2_format *fmt = arg;
+
-+ if (au0828_debug & 2)
-+ printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__);
++ return cx18_try_or_set_fmt(cx, id->type, fmt, cmd == VIDIOC_S_FMT);
++ }
+
-+ if (au0828_debug & 4)
-+ printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__);
++ case VIDIOC_G_FMT: {
++ struct v4l2_format *fmt = arg;
++ int type = fmt->type;
+
-+ if (au0828_debug & 8)
-+ printk(KERN_INFO "%s() Bridge Debugging is enabled\n",
-+ __func__);
++ memset(fmt, 0, sizeof(*fmt));
++ fmt->type = type;
++ return cx18_get_fmt(cx, id->type, fmt);
++ }
+
-+ printk(KERN_INFO "au0828 driver loaded\n");
++ case VIDIOC_CROPCAP: {
++ struct v4l2_cropcap *cropcap = arg;
+
-+ ret = usb_register(&au0828_usb_driver);
-+ if (ret)
-+ printk(KERN_ERR "usb_register failed, error = %d\n", ret);
++ if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++ cropcap->bounds.top = cropcap->bounds.left = 0;
++ cropcap->bounds.width = 720;
++ cropcap->bounds.height = cx->is_50hz ? 576 : 480;
++ cropcap->pixelaspect.numerator = cx->is_50hz ? 59 : 10;
++ cropcap->pixelaspect.denominator = cx->is_50hz ? 54 : 11;
++ cropcap->defrect = cropcap->bounds;
++ return 0;
++ }
+
-+ return ret;
++ case VIDIOC_S_CROP: {
++ struct v4l2_crop *crop = arg;
++
++ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++ return cx18_av_cmd(cx, VIDIOC_S_CROP, arg);
++ }
++
++ case VIDIOC_G_CROP: {
++ struct v4l2_crop *crop = arg;
++
++ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++ return cx18_av_cmd(cx, VIDIOC_G_CROP, arg);
++ }
++
++ case VIDIOC_ENUM_FMT: {
++ static struct v4l2_fmtdesc formats[] = {
++ { 0, 0, 0,
++ "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12,
++ { 0, 0, 0, 0 }
++ },
++ { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
++ "MPEG", V4L2_PIX_FMT_MPEG,
++ { 0, 0, 0, 0 }
++ }
++ };
++ struct v4l2_fmtdesc *fmt = arg;
++ enum v4l2_buf_type type = fmt->type;
++
++ switch (type) {
++ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
++ break;
++ default:
++ return -EINVAL;
++ }
++ if (fmt->index > 1)
++ return -EINVAL;
++ *fmt = formats[fmt->index];
++ fmt->type = type;
++ return 0;
++ }
++
++ case VIDIOC_G_INPUT:{
++ *(int *)arg = cx->active_input;
++ break;
++ }
++
++ case VIDIOC_S_INPUT:{
++ int inp = *(int *)arg;
++
++ if (inp < 0 || inp >= cx->nof_inputs)
++ return -EINVAL;
++
++ if (inp == cx->active_input) {
++ CX18_DEBUG_INFO("Input unchanged\n");
++ break;
++ }
++ CX18_DEBUG_INFO("Changing input from %d to %d\n",
++ cx->active_input, inp);
++
++ cx->active_input = inp;
++ /* Set the audio input to whatever is appropriate for the
++ input type. */
++ cx->audio_input = cx->card->video_inputs[inp].audio_index;
++
++ /* prevent others from messing with the streams until
++ we're finished changing inputs. */
++ cx18_mute(cx);
++ cx18_video_set_io(cx);
++ cx18_audio_set_io(cx);
++ cx18_unmute(cx);
++ break;
++ }
++
++ case VIDIOC_G_FREQUENCY:{
++ struct v4l2_frequency *vf = arg;
++
++ if (vf->tuner != 0)
++ return -EINVAL;
++ cx18_call_i2c_clients(cx, cmd, arg);
++ break;
++ }
++
++ case VIDIOC_S_FREQUENCY:{
++ struct v4l2_frequency vf = *(struct v4l2_frequency *)arg;
++
++ if (vf.tuner != 0)
++ return -EINVAL;
++
++ cx18_mute(cx);
++ CX18_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf.frequency);
++ cx18_call_i2c_clients(cx, cmd, &vf);
++ cx18_unmute(cx);
++ break;
++ }
++
++ case VIDIOC_ENUMSTD:{
++ struct v4l2_standard *vs = arg;
++ int idx = vs->index;
++
++ if (idx < 0 || idx >= ARRAY_SIZE(enum_stds))
++ return -EINVAL;
++
++ *vs = (enum_stds[idx].std & V4L2_STD_525_60) ?
++ cx18_std_60hz : cx18_std_50hz;
++ vs->index = idx;
++ vs->id = enum_stds[idx].std;
++ strlcpy(vs->name, enum_stds[idx].name, sizeof(vs->name));
++ break;
++ }
++
++ case VIDIOC_G_STD:{
++ *(v4l2_std_id *) arg = cx->std;
++ break;
++ }
++
++ case VIDIOC_S_STD: {
++ v4l2_std_id std = *(v4l2_std_id *) arg;
++
++ if ((std & V4L2_STD_ALL) == 0)
++ return -EINVAL;
++
++ if (std == cx->std)
++ break;
++
++ if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ||
++ atomic_read(&cx->capturing) > 0) {
++ /* Switching standard would turn off the radio or mess
++ with already running streams, prevent that by
++ returning EBUSY. */
++ return -EBUSY;
++ }
++
++ cx->std = std;
++ cx->is_60hz = (std & V4L2_STD_525_60) ? 1 : 0;
++ cx->params.is_50hz = cx->is_50hz = !cx->is_60hz;
++ cx->params.width = 720;
++ cx->params.height = cx->is_50hz ? 576 : 480;
++ cx->vbi.count = cx->is_50hz ? 18 : 12;
++ cx->vbi.start[0] = cx->is_50hz ? 6 : 10;
++ cx->vbi.start[1] = cx->is_50hz ? 318 : 273;
++ cx->vbi.sliced_decoder_line_size = cx->is_60hz ? 272 : 284;
++ CX18_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)cx->std);
++
++ /* Tuner */
++ cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std);
++ break;
++ }
++
++ case VIDIOC_S_TUNER: { /* Setting tuner can only set audio mode */
++ struct v4l2_tuner *vt = arg;
++
++ if (vt->index != 0)
++ return -EINVAL;
++
++ cx18_call_i2c_clients(cx, VIDIOC_S_TUNER, vt);
++ break;
++ }
++
++ case VIDIOC_G_TUNER: {
++ struct v4l2_tuner *vt = arg;
++
++ if (vt->index != 0)
++ return -EINVAL;
++
++ memset(vt, 0, sizeof(*vt));
++ cx18_call_i2c_clients(cx, VIDIOC_G_TUNER, vt);
++
++ if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
++ strlcpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name));
++ vt->type = V4L2_TUNER_RADIO;
++ } else {
++ strlcpy(vt->name, "cx18 TV Tuner", sizeof(vt->name));
++ vt->type = V4L2_TUNER_ANALOG_TV;
++ }
++ break;
++ }
++
++ case VIDIOC_G_SLICED_VBI_CAP: {
++ struct v4l2_sliced_vbi_cap *cap = arg;
++ int set = cx->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
++ int f, l;
++ enum v4l2_buf_type type = cap->type;
++
++ memset(cap, 0, sizeof(*cap));
++ cap->type = type;
++ if (type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
++ for (f = 0; f < 2; f++) {
++ for (l = 0; l < 24; l++) {
++ if (valid_service_line(f, l, cx->is_50hz))
++ cap->service_lines[f][l] = set;
++ }
++ }
++ return 0;
++ }
++ return -EINVAL;
++ }
++
++ case VIDIOC_ENCODER_CMD:
++ case VIDIOC_TRY_ENCODER_CMD: {
++ struct v4l2_encoder_cmd *enc = arg;
++ int try = cmd == VIDIOC_TRY_ENCODER_CMD;
++
++ memset(&enc->raw, 0, sizeof(enc->raw));
++ switch (enc->cmd) {
++ case V4L2_ENC_CMD_START:
++ enc->flags = 0;
++ if (try)
++ return 0;
++ return cx18_start_capture(id);
++
++ case V4L2_ENC_CMD_STOP:
++ enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
++ if (try)
++ return 0;
++ cx18_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
++ return 0;
++
++ case V4L2_ENC_CMD_PAUSE:
++ enc->flags = 0;
++ if (try)
++ return 0;
++ if (!atomic_read(&cx->capturing))
++ return -EPERM;
++ if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
++ return 0;
++ cx18_mute(cx);
++ cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, cx18_find_handle(cx));
++ break;
++
++ case V4L2_ENC_CMD_RESUME:
++ enc->flags = 0;
++ if (try)
++ return 0;
++ if (!atomic_read(&cx->capturing))
++ return -EPERM;
++ if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
++ return 0;
++ cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, cx18_find_handle(cx));
++ cx18_unmute(cx);
++ break;
++ default:
++ return -EINVAL;
++ }
++ break;
++ }
++
++ case VIDIOC_LOG_STATUS:
++ {
++ struct v4l2_input vidin;
++ struct v4l2_audio audin;
++ int i;
++
++ CX18_INFO("================= START STATUS CARD #%d =================\n", cx->num);
++ if (cx->hw_flags & CX18_HW_TVEEPROM) {
++ struct tveeprom tv;
++
++ cx18_read_eeprom(cx, &tv);
++ }
++ cx18_call_i2c_clients(cx, VIDIOC_LOG_STATUS, NULL);
++ cx18_get_input(cx, cx->active_input, &vidin);
++ cx18_get_audio_input(cx, cx->audio_input, &audin);
++ CX18_INFO("Video Input: %s\n", vidin.name);
++ CX18_INFO("Audio Input: %s\n", audin.name);
++ CX18_INFO("Tuner: %s\n",
++ test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ?
++ "Radio" : "TV");
++ cx2341x_log_status(&cx->params, cx->name);
++ CX18_INFO("Status flags: 0x%08lx\n", cx->i_flags);
++ for (i = 0; i < CX18_MAX_STREAMS; i++) {
++ struct cx18_stream *s = &cx->streams[i];
++
++ if (s->v4l2dev == NULL || s->buffers == 0)
++ continue;
++ CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n",
++ s->name, s->s_flags,
++ (s->buffers - s->q_free.buffers) * 100 / s->buffers,
++ (s->buffers * s->buf_size) / 1024, s->buffers);
++ }
++ CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
++ (long long)cx->mpg_data_received,
++ (long long)cx->vbi_data_inserted);
++ CX18_INFO("================== END STATUS CARD #%d ==================\n", cx->num);
++ break;
++ }
++
++ default:
++ return -EINVAL;
++ }
++ return 0;
+}
+
-+static void __exit au0828_exit(void)
++static int cx18_v4l2_do_ioctl(struct inode *inode, struct file *filp,
++ unsigned int cmd, void *arg)
+{
-+ usb_deregister(&au0828_usb_driver);
++ struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data;
++ struct cx18 *cx = id->cx;
++ int ret;
++
++ /* check priority */
++ switch (cmd) {
++ case VIDIOC_S_CTRL:
++ case VIDIOC_S_STD:
++ case VIDIOC_S_INPUT:
++ case VIDIOC_S_TUNER:
++ case VIDIOC_S_FREQUENCY:
++ case VIDIOC_S_FMT:
++ case VIDIOC_S_CROP:
++ case VIDIOC_S_EXT_CTRLS:
++ ret = v4l2_prio_check(&cx->prio, &id->prio);
++ if (ret)
++ return ret;
++ }
++
++ switch (cmd) {
++ case VIDIOC_DBG_G_REGISTER:
++ case VIDIOC_DBG_S_REGISTER:
++ case VIDIOC_G_CHIP_IDENT:
++ case VIDIOC_INT_S_AUDIO_ROUTING:
++ case VIDIOC_INT_RESET:
++ if (cx18_debug & CX18_DBGFLG_IOCTL) {
++ printk(KERN_INFO "cx18%d ioctl: ", cx->num);
++ v4l_printk_ioctl(cmd);
++ }
++ return cx18_debug_ioctls(filp, cmd, arg);
++
++ case VIDIOC_G_PRIORITY:
++ case VIDIOC_S_PRIORITY:
++ case VIDIOC_QUERYCAP:
++ case VIDIOC_ENUMINPUT:
++ case VIDIOC_G_INPUT:
++ case VIDIOC_S_INPUT:
++ case VIDIOC_G_FMT:
++ case VIDIOC_S_FMT:
++ case VIDIOC_TRY_FMT:
++ case VIDIOC_ENUM_FMT:
++ case VIDIOC_CROPCAP:
++ case VIDIOC_G_CROP:
++ case VIDIOC_S_CROP:
++ case VIDIOC_G_FREQUENCY:
++ case VIDIOC_S_FREQUENCY:
++ case VIDIOC_ENUMSTD:
++ case VIDIOC_G_STD:
++ case VIDIOC_S_STD:
++ case VIDIOC_S_TUNER:
++ case VIDIOC_G_TUNER:
++ case VIDIOC_ENUMAUDIO:
++ case VIDIOC_S_AUDIO:
++ case VIDIOC_G_AUDIO:
++ case VIDIOC_G_SLICED_VBI_CAP:
++ case VIDIOC_LOG_STATUS:
++ case VIDIOC_G_ENC_INDEX:
++ case VIDIOC_ENCODER_CMD:
++ case VIDIOC_TRY_ENCODER_CMD:
++ if (cx18_debug & CX18_DBGFLG_IOCTL) {
++ printk(KERN_INFO "cx18%d ioctl: ", cx->num);
++ v4l_printk_ioctl(cmd);
++ }
++ return cx18_v4l2_ioctls(cx, filp, cmd, arg);
++
++ case VIDIOC_QUERYMENU:
++ case VIDIOC_QUERYCTRL:
++ case VIDIOC_S_CTRL:
++ case VIDIOC_G_CTRL:
++ case VIDIOC_S_EXT_CTRLS:
++ case VIDIOC_G_EXT_CTRLS:
++ case VIDIOC_TRY_EXT_CTRLS:
++ if (cx18_debug & CX18_DBGFLG_IOCTL) {
++ printk(KERN_INFO "cx18%d ioctl: ", cx->num);
++ v4l_printk_ioctl(cmd);
++ }
++ return cx18_control_ioctls(cx, cmd, arg);
++
++ case 0x00005401: /* Handle isatty() calls */
++ return -EINVAL;
++ default:
++ return v4l_compat_translate_ioctl(inode, filp, cmd, arg,
++ cx18_v4l2_do_ioctl);
++ }
++ return 0;
+}
+
-+module_init(au0828_init);
-+module_exit(au0828_exit);
++int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
++ unsigned long arg)
++{
++ struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data;
++ struct cx18 *cx = id->cx;
++ int res;
+
-+MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");
-+MODULE_AUTHOR("Steven Toth <stoth at hauppauge.com>");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c
++ mutex_lock(&cx->serialize_lock);
++ res = video_usercopy(inode, filp, cmd, arg, cx18_v4l2_do_ioctl);
++ mutex_unlock(&cx->serialize_lock);
++ return res;
++}
+diff --git a/drivers/media/video/cx18/cx18-ioctl.h b/drivers/media/video/cx18/cx18-ioctl.h
new file mode 100644
-index 0000000..5040d7f
+index 0000000..9f4c7eb
--- /dev/null
-+++ b/drivers/media/video/au0828/au0828-dvb.c
-@@ -0,0 +1,373 @@
++++ b/drivers/media/video/cx18/cx18-ioctl.h
+@@ -0,0 +1,30 @@
+/*
-+ * Driver for the Auvitek USB bridge
++ * cx18 ioctl system call
+ *
-+ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ * Derived from ivtv-ioctl.h
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
@@ -390178,376 +553497,637 @@
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ *
+ * GNU General Public License for more details.
+ *
+ * You 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.
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ * 02111-1307 USA
+ */
+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/device.h>
-+#include <linux/suspend.h>
-+#include <media/v4l2-common.h>
-+
-+#include "au0828.h"
-+#include "au8522.h"
-+#include "xc5000.h"
-+
-+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-+
-+#define _AU0828_BULKPIPE 0x83
-+#define _BULKPIPESIZE 0xe522
-+
-+static struct au8522_config hauppauge_hvr950q_config = {
-+ .demod_address = 0x8e >> 1,
-+ .status_mode = AU8522_DEMODLOCKING,
-+};
-+
-+static struct xc5000_config hauppauge_hvr950q_tunerconfig = {
-+ .i2c_address = 0x61,
-+ .if_khz = 6000,
-+ .tuner_callback = au0828_tuner_callback
-+};
-+
-+/*-------------------------------------------------------------------*/
-+static void urb_completion(struct urb *purb)
-+{
-+ u8 *ptr;
-+ struct au0828_dev *dev = purb->context;
-+ int ptype = usb_pipetype(purb->pipe);
-+
-+ dprintk(2, "%s()\n", __func__);
-+
-+ if (!dev)
-+ return;
++u16 cx18_service2vbi(int type);
++void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal);
++u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt);
++int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
++ unsigned long arg);
++int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd,
++ void *arg);
+diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c
+new file mode 100644
+index 0000000..6e14f8b
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-irq.c
+@@ -0,0 +1,179 @@
++/*
++ * cx18 interrupt handling
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
-+ if (dev->urb_streaming == 0)
-+ return;
++#include "cx18-driver.h"
++#include "cx18-firmware.h"
++#include "cx18-fileops.h"
++#include "cx18-queue.h"
++#include "cx18-irq.h"
++#include "cx18-ioctl.h"
++#include "cx18-mailbox.h"
++#include "cx18-vbi.h"
++#include "cx18-scb.h"
++
++#define DMA_MAGIC_COOKIE 0x000001fe
++
++static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
++{
++ u32 handle = mb->args[0];
++ struct cx18_stream *s = NULL;
++ struct cx18_buffer *buf;
++ u32 off;
++ int i;
++ int id;
+
-+ if (ptype != PIPE_BULK) {
-+ printk(KERN_ERR "%s() Unsupported URB type %d\n",
-+ __func__, ptype);
++ for (i = 0; i < CX18_MAX_STREAMS; i++) {
++ s = &cx->streams[i];
++ if ((handle == s->handle) && (s->dvb.enabled))
++ break;
++ if (s->v4l2dev && handle == s->handle)
++ break;
++ }
++ if (i == CX18_MAX_STREAMS) {
++ CX18_WARN("DMA done for unknown handle %d for stream %s\n",
++ handle, s->name);
++ mb->error = CXERR_NOT_OPEN;
++ mb->cmd = 0;
++ cx18_mb_ack(cx, mb);
+ 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);
++ off = mb->args[1];
++ if (mb->args[2] != 1)
++ CX18_WARN("Ack struct = %d for %s\n",
++ mb->args[2], s->name);
++ id = read_enc(off);
++ buf = cx18_queue_find_buf(s, id, read_enc(off + 4));
++ CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id);
++ if (buf) {
++ cx18_buf_sync_for_cpu(s, buf);
++ if (s->type == CX18_ENC_STREAM_TYPE_TS && s->dvb.enabled) {
++ /* process the buffer here */
++ CX18_DEBUG_HI_DMA("TS recv and sent bytesused=%d\n",
++ buf->bytesused);
++
++ dvb_dmx_swfilter(&s->dvb.demux, buf->buf,
++ buf->bytesused);
++
++ cx18_buf_sync_for_device(s, buf);
++ cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
++ (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
++ 1, buf->id, s->buf_size);
++ } else
++ set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags);
++ } else {
++ CX18_WARN("Could not find buf %d for stream %s\n",
++ read_enc(off), s->name);
++ }
++ mb->error = 0;
++ mb->cmd = 0;
++ cx18_mb_ack(cx, mb);
++ wake_up(&cx->dma_waitq);
++ if (s->id != -1)
++ wake_up(&s->waitq);
++}
+
-+ /* Clean the buffer before we requeue */
-+ memset(purb->transfer_buffer, 0, URB_BUFSIZE);
++static void epu_debug(struct cx18 *cx, struct cx18_mailbox *mb)
++{
++ char str[256] = { 0 };
++ char *p;
+
-+ /* Requeue URB */
-+ usb_submit_urb(purb, GFP_ATOMIC);
++ if (mb->args[1]) {
++ setup_page(mb->args[1]);
++ memcpy_fromio(str, cx->enc_mem + mb->args[1], 252);
++ str[252] = 0;
++ }
++ cx18_mb_ack(cx, mb);
++ CX18_DEBUG_INFO("%x %s\n", mb->args[0], str);
++ p = strchr(str, '.');
++ if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags) && p && p > str)
++ CX18_INFO("FW version: %s\n", p - 1);
+}
+
-+static int stop_urb_transfer(struct au0828_dev *dev)
++static void hpu_cmd(struct cx18 *cx, u32 sw1)
+{
-+ int i;
++ struct cx18_mailbox mb;
+
-+ dprintk(2, "%s()\n", __func__);
++ if (sw1 & IRQ_CPU_TO_EPU) {
++ memcpy_fromio(&mb, &cx->scb->cpu2epu_mb, sizeof(mb));
++ mb.error = 0;
+
-+ 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]);
++ switch (mb.cmd) {
++ case CX18_EPU_DMA_DONE:
++ epu_dma_done(cx, &mb);
++ break;
++ case CX18_EPU_DEBUG:
++ epu_debug(cx, &mb);
++ break;
++ default:
++ CX18_WARN("Unexpected mailbox command %08x\n", mb.cmd);
++ break;
++ }
+ }
-+
-+ dev->urb_streaming = 0;
-+
-+ return 0;
++ if (sw1 & (IRQ_APU_TO_EPU | IRQ_HPU_TO_EPU))
++ CX18_WARN("Unexpected interrupt %08x\n", sw1);
+}
+
-+static int start_urb_transfer(struct au0828_dev *dev)
++irqreturn_t cx18_irq_handler(int irq, void *dev_id)
+{
-+ struct urb *purb;
-+ int i, ret = -ENOMEM;
++ struct cx18 *cx = (struct cx18 *)dev_id;
++ u32 sw1, sw1_mask;
++ u32 sw2, sw2_mask;
++ u32 hw2, hw2_mask;
+
-+ dprintk(2, "%s()\n", __func__);
++ spin_lock(&cx->dma_reg_lock);
+
-+ if (dev->urb_streaming) {
-+ dprintk(2, "%s: iso xfer already running!\n", __func__);
-+ return 0;
++ hw2_mask = read_reg(HW2_INT_MASK5_PCI);
++ hw2 = read_reg(HW2_INT_CLR_STATUS) & hw2_mask;
++ sw2_mask = read_reg(SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK;
++ sw2 = read_reg(SW2_INT_STATUS) & sw2_mask;
++ sw1_mask = read_reg(SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU;
++ sw1 = read_reg(SW1_INT_STATUS) & sw1_mask;
++
++ write_reg(sw2&sw2_mask, SW2_INT_STATUS);
++ write_reg(sw1&sw1_mask, SW1_INT_STATUS);
++ write_reg(hw2&hw2_mask, HW2_INT_CLR_STATUS);
++
++ if (sw1 || sw2 || hw2)
++ CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2);
++
++ /* To do: interrupt-based I2C handling
++ if (hw2 & 0x00c00000) {
+ }
++ */
+
-+ for (i = 0; i < URB_COUNT; i++) {
++ if (sw2) {
++ if (sw2 & (cx->scb->cpu2hpu_irq_ack | cx->scb->cpu2epu_irq_ack))
++ wake_up(&cx->mb_cpu_waitq);
++ if (sw2 & (cx->scb->apu2hpu_irq_ack | cx->scb->apu2epu_irq_ack))
++ wake_up(&cx->mb_apu_waitq);
++ if (sw2 & cx->scb->epu2hpu_irq_ack)
++ wake_up(&cx->mb_epu_waitq);
++ if (sw2 & cx->scb->hpu2epu_irq_ack)
++ wake_up(&cx->mb_hpu_waitq);
++ }
++
++ if (sw1)
++ hpu_cmd(cx, sw1);
++ spin_unlock(&cx->dma_reg_lock);
+
-+ dev->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
-+ if (!dev->urbs[i])
-+ goto err;
++ return (hw2 | sw1 | sw2) ? IRQ_HANDLED : IRQ_NONE;
++}
+diff --git a/drivers/media/video/cx18/cx18-irq.h b/drivers/media/video/cx18/cx18-irq.h
+new file mode 100644
+index 0000000..379f704
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-irq.h
+@@ -0,0 +1,37 @@
++/*
++ * cx18 interrupt handling
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
-+ purb = dev->urbs[i];
++#define HW2_I2C1_INT (1 << 22)
++#define HW2_I2C2_INT (1 << 23)
++#define HW2_INT_CLR_STATUS 0xc730c4
++#define HW2_INT_MASK5_PCI 0xc730e4
++#define SW1_INT_SET 0xc73100
++#define SW1_INT_STATUS 0xc73104
++#define SW1_INT_ENABLE_PCI 0xc7311c
++#define SW2_INT_SET 0xc73140
++#define SW2_INT_STATUS 0xc73144
++#define SW2_INT_ENABLE_PCI 0xc7315c
++
++irqreturn_t cx18_irq_handler(int irq, void *dev_id);
++
++void cx18_irq_work_handler(struct work_struct *work);
++void cx18_dma_stream_dec_prepare(struct cx18_stream *s, u32 offset, int lock);
++void cx18_unfinished_dma(unsigned long arg);
+diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
+new file mode 100644
+index 0000000..0c5f328
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-mailbox.c
+@@ -0,0 +1,372 @@
++/*
++ * cx18 mailbox functions
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
-+ purb->transfer_buffer = kzalloc(URB_BUFSIZE, GFP_KERNEL);
-+ if (!purb->transfer_buffer) {
-+ usb_free_urb(purb);
-+ dev->urbs[i] = 0;
-+ goto err;
-+ }
++#include <stdarg.h>
+
-+ purb->status = -EINPROGRESS;
-+ usb_fill_bulk_urb(purb,
-+ dev->usbdev,
-+ usb_rcvbulkpipe(dev->usbdev, _AU0828_BULKPIPE),
-+ purb->transfer_buffer,
-+ URB_BUFSIZE,
-+ urb_completion,
-+ dev);
++#include "cx18-driver.h"
++#include "cx18-scb.h"
++#include "cx18-irq.h"
++#include "cx18-mailbox.h"
+
-+ }
++#define API_FAST (1 << 2) /* Short timeout */
++#define API_SLOW (1 << 3) /* Additional 300ms timeout */
+
-+ 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;
-+ }
-+ }
++#define APU 0
++#define CPU 1
++#define EPU 2
++#define HPU 3
+
-+ dev->urb_streaming = 1;
-+ ret = 0;
++struct cx18_api_info {
++ u32 cmd;
++ u8 flags; /* Flags, see above */
++ u8 rpu; /* Processing unit */
++ const char *name; /* The name of the command */
++};
++
++#define API_ENTRY(rpu, x, f) { (x), (f), (rpu), #x }
++
++static const struct cx18_api_info api_info[] = {
++ /* MPEG encoder API */
++ API_ENTRY(CPU, CX18_CPU_SET_CHANNEL_TYPE, 0),
++ API_ENTRY(CPU, CX18_EPU_DEBUG, 0),
++ API_ENTRY(CPU, CX18_CREATE_TASK, 0),
++ API_ENTRY(CPU, CX18_DESTROY_TASK, 0),
++ API_ENTRY(CPU, CX18_CPU_CAPTURE_START, API_SLOW),
++ API_ENTRY(CPU, CX18_CPU_CAPTURE_STOP, API_SLOW),
++ API_ENTRY(CPU, CX18_CPU_CAPTURE_PAUSE, 0),
++ API_ENTRY(CPU, CX18_CPU_CAPTURE_RESUME, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_CHANNEL_TYPE, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_STREAM_OUTPUT_TYPE, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_VIDEO_IN, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_VIDEO_RATE, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_VIDEO_RESOLUTION, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_FILTER_PARAM, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_SPATIAL_FILTER_TYPE, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_MEDIAN_CORING, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_INDEXTABLE, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_AUDIO_PARAMETERS, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_VIDEO_MUTE, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_AUDIO_MUTE, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_MISC_PARAMETERS, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_RAW_VBI_PARAM, API_SLOW),
++ API_ENTRY(CPU, CX18_CPU_SET_CAPTURE_LINE_NO, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_COPYRIGHT, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_AUDIO_PID, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_VIDEO_PID, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_VER_CROP_LINE, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_GOP_STRUCTURE, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_SCENE_CHANGE_DETECTION, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_ASPECT_RATIO, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_SKIP_INPUT_FRAME, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_SLICED_VBI_PARAM, 0),
++ API_ENTRY(CPU, CX18_CPU_SET_USERDATA_PLACE_HOLDER, 0),
++ API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS, 0),
++ API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0),
++ API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST),
++ API_ENTRY(0, 0, 0),
++};
+
-+err:
-+ return ret;
++static const struct cx18_api_info *find_api_info(u32 cmd)
++{
++ int i;
++
++ for (i = 0; api_info[i].cmd; i++)
++ if (api_info[i].cmd == cmd)
++ return &api_info[i];
++ return NULL;
+}
+
-+static int au0828_dvb_start_feed(struct dvb_demux_feed *feed)
++static struct cx18_mailbox *cx18_mb_is_complete(struct cx18 *cx, int rpu,
++ u32 *state, u32 *irq, u32 *req)
+{
-+ struct dvb_demux *demux = feed->demux;
-+ struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
-+ struct au0828_dvb *dvb = &dev->dvb;
-+ int ret = 0;
++ struct cx18_mailbox *mb = NULL;
++ int wait_count = 0;
++ u32 ack;
+
-+ dprintk(1, "%s()\n", __func__);
++ switch (rpu) {
++ case APU:
++ mb = &cx->scb->epu2apu_mb;
++ *state = readl(&cx->scb->apu_state);
++ *irq = readl(&cx->scb->epu2apu_irq);
++ break;
+
-+ if (!demux->dmx.frontend)
-+ return -EINVAL;
++ case CPU:
++ mb = &cx->scb->epu2cpu_mb;
++ *state = readl(&cx->scb->cpu_state);
++ *irq = readl(&cx->scb->epu2cpu_irq);
++ break;
+
-+ 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);
++ case HPU:
++ mb = &cx->scb->epu2hpu_mb;
++ *state = readl(&cx->scb->hpu_state);
++ *irq = readl(&cx->scb->epu2hpu_irq);
++ break;
+ }
+
-+ return ret;
++ if (mb == NULL)
++ return mb;
++
++ do {
++ *req = readl(&mb->request);
++ ack = readl(&mb->ack);
++ wait_count++;
++ } while (*req != ack && wait_count < 600);
++
++ if (*req == ack) {
++ (*req)++;
++ if (*req == 0 || *req == 0xffffffff)
++ *req = 1;
++ return mb;
++ }
++ return NULL;
+}
+
-+static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
++long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb)
+{
-+ struct dvb_demux *demux = feed->demux;
-+ struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
-+ struct au0828_dvb *dvb = &dev->dvb;
-+ int ret = 0;
++ const struct cx18_api_info *info = find_api_info(mb->cmd);
++ struct cx18_mailbox *ack_mb;
++ u32 ack_irq;
++ u8 rpu = CPU;
+
-+ dprintk(1, "%s()\n", __func__);
++ if (info == NULL && mb->cmd) {
++ CX18_WARN("Cannot ack unknown command %x\n", mb->cmd);
++ return -EINVAL;
++ }
++ if (info)
++ rpu = info->rpu;
+
-+ 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);
++ switch (rpu) {
++ case HPU:
++ ack_irq = IRQ_EPU_TO_HPU_ACK;
++ ack_mb = &cx->scb->hpu2epu_mb;
++ break;
++ case APU:
++ ack_irq = IRQ_EPU_TO_APU_ACK;
++ ack_mb = &cx->scb->apu2epu_mb;
++ break;
++ case CPU:
++ ack_irq = IRQ_EPU_TO_CPU_ACK;
++ ack_mb = &cx->scb->cpu2epu_mb;
++ break;
++ default:
++ CX18_WARN("Unknown RPU for command %x\n", mb->cmd);
++ return -EINVAL;
+ }
+
-+ return ret;
++ setup_page(SCB_OFFSET);
++ write_sync(mb->request, &ack_mb->ack);
++ write_reg(ack_irq, SW2_INT_SET);
++ return 0;
+}
+
-+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;
-+ }
++static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
++{
++ const struct cx18_api_info *info = find_api_info(cmd);
++ u32 state = 0, irq = 0, req, oldreq, err;
++ struct cx18_mailbox *mb;
++ wait_queue_head_t *waitq;
++ int timeout = 100;
++ int cnt = 0;
++ int sig = 0;
++ int i;
+
-+ /* 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;
++ if (info == NULL) {
++ CX18_WARN("unknown cmd %x\n", cmd);
++ return -EINVAL;
+ }
+
-+ 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;
-+ }
++ if (cmd == CX18_CPU_DE_SET_MDL)
++ CX18_DEBUG_HI_API("%s\n", info->name);
++ else
++ CX18_DEBUG_API("%s\n", info->name);
++ setup_page(SCB_OFFSET);
++ mb = cx18_mb_is_complete(cx, info->rpu, &state, &irq, &req);
+
-+ 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;
++ if (mb == NULL) {
++ CX18_ERR("mb %s busy\n", info->name);
++ return -EBUSY;
+ }
+
-+ 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;
++ oldreq = req - 1;
++ writel(cmd, &mb->cmd);
++ for (i = 0; i < args; i++)
++ writel(data[i], &mb->args[i]);
++ writel(0, &mb->error);
++ writel(req, &mb->request);
++
++ switch (info->rpu) {
++ case APU: waitq = &cx->mb_apu_waitq; break;
++ case CPU: waitq = &cx->mb_cpu_waitq; break;
++ case EPU: waitq = &cx->mb_epu_waitq; break;
++ case HPU: waitq = &cx->mb_hpu_waitq; break;
++ default: return -EINVAL;
++ }
++ if (info->flags & API_FAST)
++ timeout /= 2;
++ write_reg(irq, SW1_INT_SET);
++
++ while (!sig && readl(&mb->ack) != readl(&mb->request) && cnt < 660) {
++ if (cnt > 200 && !in_atomic())
++ sig = cx18_msleep_timeout(10, 1);
++ cnt++;
+ }
-+
-+ 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;
++ if (sig)
++ return -EINTR;
++ if (cnt == 660) {
++ writel(oldreq, &mb->request);
++ CX18_ERR("mb %s failed\n", info->name);
++ return -EINVAL;
+ }
-+
-+ /* 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;
++ for (i = 0; i < MAX_MB_ARGUMENTS; i++)
++ data[i] = readl(&mb->args[i]);
++ err = readl(&mb->error);
++ if (!in_atomic() && (info->flags & API_SLOW))
++ cx18_msleep_timeout(300, 0);
++ if (err)
++ CX18_DEBUG_API("mailbox error %08x for command %s\n", err,
++ info->name);
++ return err ? -EIO : 0;
+}
+
-+void au0828_dvb_unregister(struct au0828_dev *dev)
++int cx18_api(struct cx18 *cx, u32 cmd, int args, u32 data[])
+{
-+ struct au0828_dvb *dvb = &dev->dvb;
++ int res = cx18_api_call(cx, cmd, args, data);
+
-+ dprintk(1, "%s()\n", __func__);
++ /* Allow a single retry, probably already too late though.
++ If there is no free mailbox then that is usually an indication
++ of a more serious problem. */
++ return (res == -EBUSY) ? cx18_api_call(cx, cmd, args, data) : res;
++}
+
-+ if (dvb->frontend == NULL)
-+ return;
++static int cx18_set_filter_param(struct cx18_stream *s)
++{
++ struct cx18 *cx = s->cx;
++ u32 mode;
++ int ret;
+
-+ 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);
++ mode = (cx->filter_mode & 1) ? 2 : (cx->spatial_strength ? 1 : 0);
++ ret = cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
++ s->handle, 1, mode, cx->spatial_strength);
++ mode = (cx->filter_mode & 2) ? 2 : (cx->temporal_strength ? 1 : 0);
++ ret = ret ? ret : cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
++ s->handle, 0, mode, cx->temporal_strength);
++ ret = ret ? ret : cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
++ s->handle, 2, cx->filter_mode >> 2, 0);
++ return ret;
+}
+
-+/* 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)
++int cx18_api_func(void *priv, u32 cmd, int in, int out,
++ u32 data[CX2341X_MBOX_MAX_DATA])
+{
-+ struct au0828_dvb *dvb = &dev->dvb;
-+ int ret;
++ struct cx18 *cx = priv;
++ struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];
+
-+ dprintk(1, "%s()\n", __func__);
++ switch (cmd) {
++ case CX2341X_ENC_SET_OUTPUT_PORT:
++ return 0;
++ case CX2341X_ENC_SET_FRAME_RATE:
++ return cx18_vapi(cx, CX18_CPU_SET_VIDEO_IN, 6,
++ s->handle, 0, 0, 0, 0, data[0]);
++ case CX2341X_ENC_SET_FRAME_SIZE:
++ return cx18_vapi(cx, CX18_CPU_SET_VIDEO_RESOLUTION, 3,
++ s->handle, data[1], data[0]);
++ case CX2341X_ENC_SET_STREAM_TYPE:
++ return cx18_vapi(cx, CX18_CPU_SET_STREAM_OUTPUT_TYPE, 2,
++ s->handle, data[0]);
++ case CX2341X_ENC_SET_ASPECT_RATIO:
++ return cx18_vapi(cx, CX18_CPU_SET_ASPECT_RATIO, 2,
++ s->handle, data[0]);
+
-+ /* 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;
++ case CX2341X_ENC_SET_GOP_PROPERTIES:
++ return cx18_vapi(cx, CX18_CPU_SET_GOP_STRUCTURE, 3,
++ s->handle, data[0], data[1]);
++ case CX2341X_ENC_SET_GOP_CLOSURE:
++ return 0;
++ case CX2341X_ENC_SET_AUDIO_PROPERTIES:
++ return cx18_vapi(cx, CX18_CPU_SET_AUDIO_PARAMETERS, 2,
++ s->handle, data[0]);
++ case CX2341X_ENC_MUTE_AUDIO:
++ return cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
++ s->handle, data[0]);
++ case CX2341X_ENC_SET_BIT_RATE:
++ return cx18_vapi(cx, CX18_CPU_SET_VIDEO_RATE, 5,
++ s->handle, data[0], data[1], data[2], data[3]);
++ case CX2341X_ENC_MUTE_VIDEO:
++ return cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2,
++ s->handle, data[0]);
++ case CX2341X_ENC_SET_FRAME_DROP_RATE:
++ return cx18_vapi(cx, CX18_CPU_SET_SKIP_INPUT_FRAME, 2,
++ s->handle, data[0]);
++ case CX2341X_ENC_MISC:
++ return cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 4,
++ s->handle, data[0], data[1], data[2]);
++ case CX2341X_ENC_SET_DNR_FILTER_MODE:
++ cx->filter_mode = (data[0] & 3) | (data[1] << 2);
++ return cx18_set_filter_param(s);
++ case CX2341X_ENC_SET_DNR_FILTER_PROPS:
++ cx->spatial_strength = data[0];
++ cx->temporal_strength = data[1];
++ return cx18_set_filter_param(s);
++ case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
++ return cx18_vapi(cx, CX18_CPU_SET_SPATIAL_FILTER_TYPE, 3,
++ s->handle, data[0], data[1]);
++ case CX2341X_ENC_SET_CORING_LEVELS:
++ return cx18_vapi(cx, CX18_CPU_SET_MEDIAN_CORING, 5,
++ s->handle, data[0], data[1], data[2], data[3]);
+ }
++ CX18_WARN("Unknown cmd %x\n", cmd);
++ return 0;
++}
+
-+ /* Put the analog decoder in standby to keep it quiet */
-+ au0828_call_i2c_clients(dev, TUNER_SET_STANDBY, NULL);
++int cx18_vapi_result(struct cx18 *cx, u32 data[MAX_MB_ARGUMENTS],
++ u32 cmd, int args, ...)
++{
++ va_list ap;
++ int i;
+
-+ if (dvb->frontend->ops.analog_ops.standby)
-+ dvb->frontend->ops.analog_ops.standby(dvb->frontend);
++ va_start(ap, args);
++ for (i = 0; i < args; i++)
++ data[i] = va_arg(ap, u32);
++ va_end(ap);
++ return cx18_api(cx, cmd, args, data);
++}
+
-+ /* register everything */
-+ ret = dvb_register(dev);
-+ if (ret < 0) {
-+ if (dvb->frontend->ops.release)
-+ dvb->frontend->ops.release(dvb->frontend);
-+ return ret;
-+ }
++int cx18_vapi(struct cx18 *cx, u32 cmd, int args, ...)
++{
++ u32 data[MAX_MB_ARGUMENTS];
++ va_list ap;
++ int i;
+
-+ return 0;
++ if (cx == NULL) {
++ CX18_ERR("cx == NULL (cmd=%x)\n", cmd);
++ return 0;
++ }
++ if (args > MAX_MB_ARGUMENTS) {
++ CX18_ERR("args too big (cmd=%x)\n", cmd);
++ args = MAX_MB_ARGUMENTS;
++ }
++ va_start(ap, args);
++ for (i = 0; i < args; i++)
++ data[i] = va_arg(ap, u32);
++ va_end(ap);
++ return cx18_api(cx, cmd, args, data);
+}
-diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c
+diff --git a/drivers/media/video/cx18/cx18-mailbox.h b/drivers/media/video/cx18/cx18-mailbox.h
new file mode 100644
-index 0000000..741a493
+index 0000000..d995641
--- /dev/null
-+++ b/drivers/media/video/au0828/au0828-i2c.c
-@@ -0,0 +1,381 @@
++++ b/drivers/media/video/cx18/cx18-mailbox.h
+@@ -0,0 +1,73 @@
+/*
-+ * Driver for the Auvitek AU0828 USB bridge
++ * cx18 mailbox functions
+ *
-+ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
@@ -390557,384 +554137,1421 @@
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ *
+ * GNU General Public License for more details.
+ *
+ * You 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.
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ * 02111-1307 USA
+ */
+
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/io.h>
++#ifndef _CX18_MAILBOX_H_
++#define _CX18_MAILBOX_H_
+
-+#include "au0828.h"
++/* mailbox max args */
++#define MAX_MB_ARGUMENTS 6
++/* compatibility, should be same as the define in cx2341x.h */
++#define CX2341X_MBOX_MAX_DATA 16
++
++#define MB_RESERVED_HANDLE_0 0
++#define MB_RESERVED_HANDLE_1 0xFFFFFFFF
++
++struct cx18;
++
++/* The cx18_mailbox struct is the mailbox structure which is used for passing
++ messages between processors */
++struct cx18_mailbox {
++ /* The sender sets a handle in 'request' after he fills the command. The
++ 'request' should be different than 'ack'. The sender, also, generates
++ an interrupt on XPU2YPU_irq where XPU is the sender and YPU is the
++ receiver. */
++ u32 request;
++ /* The receiver detects a new command when 'req' is different than 'ack'.
++ He sets 'ack' to the same value as 'req' to clear the command. He, also,
++ generates an interrupt on YPU2XPU_irq where XPU is the sender and YPU
++ is the receiver. */
++ u32 ack;
++ u32 reserved[6];
++ /* 'cmd' identifies the command. The list of these commands are in
++ cx23418.h */
++ u32 cmd;
++ /* Each command can have up to 6 arguments */
++ u32 args[MAX_MB_ARGUMENTS];
++ /* The return code can be one of the codes in the file cx23418.h. If the
++ command is completed successfuly, the error will be ERR_SYS_SUCCESS.
++ If it is pending, the code is ERR_SYS_PENDING. If it failed, the error
++ code would indicate the task from which the error originated and will
++ be one of the errors in cx23418.h. In that case, the following
++ applies ((error & 0xff) != 0).
++ If the command is pending, the return will be passed in a MB from the
++ receiver to the sender. 'req' will be returned in args[0] */
++ u32 error;
++};
++
++int cx18_api(struct cx18 *cx, u32 cmd, int args, u32 data[]);
++int cx18_vapi_result(struct cx18 *cx, u32 data[MAX_MB_ARGUMENTS], u32 cmd,
++ int args, ...);
++int cx18_vapi(struct cx18 *cx, u32 cmd, int args, ...);
++int cx18_api_func(void *priv, u32 cmd, int in, int out,
++ u32 data[CX2341X_MBOX_MAX_DATA]);
++long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb);
+
-+#include <media/v4l2-common.h>
++#endif
+diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c
+new file mode 100644
+index 0000000..65af1bb
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-queue.c
+@@ -0,0 +1,282 @@
++/*
++ * cx18 buffer queues
++ *
++ * Derived from ivtv-queue.c
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
-+static int i2c_scan;
-+module_param(i2c_scan, int, 0444);
-+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
++#include "cx18-driver.h"
++#include "cx18-streams.h"
++#include "cx18-queue.h"
++#include "cx18-scb.h"
+
-+#define I2C_WAIT_DELAY 512
-+#define I2C_WAIT_RETRY 64
++int cx18_buf_copy_from_user(struct cx18_stream *s, struct cx18_buffer *buf,
++ const char __user *src, int copybytes)
++{
++ if (s->buf_size - buf->bytesused < copybytes)
++ copybytes = s->buf_size - buf->bytesused;
++ if (copy_from_user(buf->buf + buf->bytesused, src, copybytes))
++ return -EFAULT;
++ buf->bytesused += copybytes;
++ return copybytes;
++}
+
-+static inline int i2c_slave_did_write_ack(struct i2c_adapter *i2c_adap)
++void cx18_buf_swap(struct cx18_buffer *buf)
+{
-+ struct au0828_dev *dev = i2c_adap->algo_data;
-+ return au0828_read(dev, REG_201) & 0x08 ? 0 : 1;
++ int i;
++
++ for (i = 0; i < buf->bytesused; i += 4)
++ swab32s((u32 *)(buf->buf + i));
+}
+
-+static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap)
++void cx18_queue_init(struct cx18_queue *q)
+{
-+ struct au0828_dev *dev = i2c_adap->algo_data;
-+ return au0828_read(dev, REG_201) & 0x02 ? 0 : 1;
++ INIT_LIST_HEAD(&q->list);
++ q->buffers = 0;
++ q->length = 0;
++ q->bytesused = 0;
+}
+
-+static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap)
++void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf,
++ struct cx18_queue *q)
+{
-+ int count;
++ unsigned long flags = 0;
+
-+ for (count = 0; count < I2C_WAIT_RETRY; count++) {
-+ if (!i2c_slave_did_read_ack(i2c_adap))
-+ break;
-+ udelay(I2C_WAIT_DELAY);
-+ }
++ /* clear the buffer if it is going to be enqueued to the free queue */
++ if (q == &s->q_free) {
++ buf->bytesused = 0;
++ buf->readpos = 0;
++ buf->b_flags = 0;
++ }
++ spin_lock_irqsave(&s->qlock, flags);
++ list_add_tail(&buf->list, &q->list);
++ q->buffers++;
++ q->length += s->buf_size;
++ q->bytesused += buf->bytesused - buf->readpos;
++ spin_unlock_irqrestore(&s->qlock, flags);
++}
+
-+ if (I2C_WAIT_RETRY == count)
-+ return 0;
++struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q)
++{
++ struct cx18_buffer *buf = NULL;
++ unsigned long flags = 0;
+
-+ return 1;
++ spin_lock_irqsave(&s->qlock, flags);
++ if (!list_empty(&q->list)) {
++ buf = list_entry(q->list.next, struct cx18_buffer, list);
++ list_del_init(q->list.next);
++ q->buffers--;
++ q->length -= s->buf_size;
++ q->bytesused -= buf->bytesused - buf->readpos;
++ }
++ spin_unlock_irqrestore(&s->qlock, flags);
++ return buf;
+}
+
-+static inline int i2c_is_read_busy(struct i2c_adapter *i2c_adap)
++struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
++ u32 bytesused)
+{
-+ struct au0828_dev *dev = i2c_adap->algo_data;
-+ return au0828_read(dev, REG_201) & 0x01 ? 0 : 1;
++ struct cx18 *cx = s->cx;
++ struct list_head *p;
++
++ list_for_each(p, &s->q_free.list) {
++ struct cx18_buffer *buf =
++ list_entry(p, struct cx18_buffer, list);
++
++ if (buf->id != id)
++ continue;
++ buf->bytesused = bytesused;
++ /* the transport buffers are handled differently,
++ so there is no need to move them to the full queue */
++ if (s->type == CX18_ENC_STREAM_TYPE_TS)
++ return buf;
++ s->q_free.buffers--;
++ s->q_free.length -= s->buf_size;
++ s->q_full.buffers++;
++ s->q_full.length += s->buf_size;
++ s->q_full.bytesused += buf->bytesused;
++ list_move_tail(&buf->list, &s->q_full.list);
++ return buf;
++ }
++ CX18_ERR("Cannot find buffer %d for stream %s\n", id, s->name);
++ return NULL;
+}
+
-+static int i2c_wait_read_done(struct i2c_adapter *i2c_adap)
++static void cx18_queue_move_buf(struct cx18_stream *s, struct cx18_queue *from,
++ struct cx18_queue *to, int clear, int full)
+{
-+ int count;
++ struct cx18_buffer *buf =
++ list_entry(from->list.next, struct cx18_buffer, list);
+
-+ for (count = 0; count < I2C_WAIT_RETRY; count++) {
-+ if (!i2c_is_read_busy(i2c_adap))
-+ break;
-+ udelay(I2C_WAIT_DELAY);
++ list_move_tail(from->list.next, &to->list);
++ from->buffers--;
++ from->length -= s->buf_size;
++ from->bytesused -= buf->bytesused - buf->readpos;
++ /* special handling for q_free */
++ if (clear)
++ buf->bytesused = buf->readpos = buf->b_flags = 0;
++ else if (full) {
++ /* special handling for stolen buffers, assume
++ all bytes are used. */
++ buf->bytesused = s->buf_size;
++ buf->readpos = buf->b_flags = 0;
++ }
++ to->buffers++;
++ to->length += s->buf_size;
++ to->bytesused += buf->bytesused - buf->readpos;
++}
++
++/* Move 'needed_bytes' worth of buffers from queue 'from' into queue 'to'.
++ If 'needed_bytes' == 0, then move all buffers from 'from' into 'to'.
++ If 'steal' != NULL, then buffers may also taken from that queue if
++ needed.
++
++ The buffer is automatically cleared if it goes to the free queue. It is
++ also cleared if buffers need to be taken from the 'steal' queue and
++ the 'from' queue is the free queue.
++
++ When 'from' is q_free, then needed_bytes is compared to the total
++ available buffer length, otherwise needed_bytes is compared to the
++ bytesused value. For the 'steal' queue the total available buffer
++ length is always used.
++
++ -ENOMEM is returned if the buffers could not be obtained, 0 if all
++ buffers where obtained from the 'from' list and if non-zero then
++ the number of stolen buffers is returned. */
++int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from,
++ struct cx18_queue *steal, struct cx18_queue *to, int needed_bytes)
++{
++ unsigned long flags;
++ int rc = 0;
++ int from_free = from == &s->q_free;
++ int to_free = to == &s->q_free;
++ int bytes_available;
++
++ spin_lock_irqsave(&s->qlock, flags);
++ if (needed_bytes == 0) {
++ from_free = 1;
++ needed_bytes = from->length;
+ }
+
-+ if (I2C_WAIT_RETRY == count)
-+ return 0;
++ bytes_available = from_free ? from->length : from->bytesused;
++ bytes_available += steal ? steal->length : 0;
+
-+ return 1;
++ if (bytes_available < needed_bytes) {
++ spin_unlock_irqrestore(&s->qlock, flags);
++ return -ENOMEM;
++ }
++ if (from_free) {
++ u32 old_length = to->length;
++
++ while (to->length - old_length < needed_bytes) {
++ if (list_empty(&from->list))
++ from = steal;
++ if (from == steal)
++ rc++; /* keep track of 'stolen' buffers */
++ cx18_queue_move_buf(s, from, to, 1, 0);
++ }
++ } else {
++ u32 old_bytesused = to->bytesused;
++
++ while (to->bytesused - old_bytesused < needed_bytes) {
++ if (list_empty(&from->list))
++ from = steal;
++ if (from == steal)
++ rc++; /* keep track of 'stolen' buffers */
++ cx18_queue_move_buf(s, from, to, to_free, rc);
++ }
++ }
++ spin_unlock_irqrestore(&s->qlock, flags);
++ return rc;
+}
+
-+static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap)
++void cx18_flush_queues(struct cx18_stream *s)
+{
-+ struct au0828_dev *dev = i2c_adap->algo_data;
-+ return au0828_read(dev, REG_201) & 0x04 ? 1 : 0;
++ cx18_queue_move(s, &s->q_io, NULL, &s->q_free, 0);
++ cx18_queue_move(s, &s->q_full, NULL, &s->q_free, 0);
+}
+
-+static int i2c_wait_write_done(struct i2c_adapter *i2c_adap)
++int cx18_stream_alloc(struct cx18_stream *s)
+{
-+ int count;
++ struct cx18 *cx = s->cx;
++ int i;
+
-+ for (count = 0; count < I2C_WAIT_RETRY; count++) {
-+ if (i2c_is_write_done(i2c_adap))
-+ break;
-+ udelay(I2C_WAIT_DELAY);
++ if (s->buffers == 0)
++ return 0;
++
++ CX18_DEBUG_INFO("Allocate %s stream: %d x %d buffers (%dkB total)\n",
++ s->name, s->buffers, s->buf_size,
++ s->buffers * s->buf_size / 1024);
++
++ if (((char *)&cx->scb->cpu_mdl[cx->mdl_offset + s->buffers] -
++ (char *)cx->scb) > SCB_RESERVED_SIZE) {
++ unsigned bufsz = (((char *)cx->scb) + SCB_RESERVED_SIZE -
++ ((char *)cx->scb->cpu_mdl));
++
++ CX18_ERR("Too many buffers, cannot fit in SCB area\n");
++ CX18_ERR("Max buffers = %zd\n",
++ bufsz / sizeof(struct cx18_mdl));
++ return -ENOMEM;
+ }
+
-+ if (I2C_WAIT_RETRY == count)
-+ return 0;
++ s->mdl_offset = cx->mdl_offset;
+
-+ return 1;
-+}
++ /* allocate stream buffers. Initially all buffers are in q_free. */
++ for (i = 0; i < s->buffers; i++) {
++ struct cx18_buffer *buf =
++ kzalloc(sizeof(struct cx18_buffer), GFP_KERNEL);
+
-+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;
++ if (buf == NULL)
++ break;
++ buf->buf = kmalloc(s->buf_size, GFP_KERNEL);
++ if (buf->buf == NULL) {
++ kfree(buf);
++ break;
++ }
++ buf->id = cx->buffer_id++;
++ INIT_LIST_HEAD(&buf->list);
++ buf->dma_handle = pci_map_single(s->cx->dev,
++ buf->buf, s->buf_size, s->dma);
++ cx18_buf_sync_for_cpu(s, buf);
++ cx18_enqueue(s, buf, &s->q_free);
++ }
++ if (i == s->buffers) {
++ cx->mdl_offset += s->buffers;
++ return 0;
++ }
++ CX18_ERR("Couldn't allocate buffers for %s stream\n", s->name);
++ cx18_stream_free(s);
++ return -ENOMEM;
+}
+
-+static int i2c_wait_done(struct i2c_adapter *i2c_adap)
++void cx18_stream_free(struct cx18_stream *s)
+{
-+ int count;
++ struct cx18_buffer *buf;
+
-+ for (count = 0; count < I2C_WAIT_RETRY; count++) {
-+ if (!i2c_is_busy(i2c_adap))
-+ break;
-+ udelay(I2C_WAIT_DELAY);
++ /* move all buffers to q_free */
++ cx18_flush_queues(s);
++
++ /* empty q_free */
++ while ((buf = cx18_dequeue(s, &s->q_free))) {
++ pci_unmap_single(s->cx->dev, buf->dma_handle,
++ s->buf_size, s->dma);
++ kfree(buf->buf);
++ kfree(buf);
+ }
++}
+diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h
+new file mode 100644
+index 0000000..f86c8a6
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-queue.h
+@@ -0,0 +1,59 @@
++/*
++ * cx18 buffer queues
++ *
++ * Derived from ivtv-queue.h
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
-+ if (I2C_WAIT_RETRY == count)
-+ return 0;
++#define CX18_DMA_UNMAPPED ((u32) -1)
+
-+ return 1;
-+}
++/* cx18_buffer utility functions */
+
-+/* FIXME: Implement join handling correctly */
-+static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
-+ const struct i2c_msg *msg, int joined_rlen)
++static inline void cx18_buf_sync_for_cpu(struct cx18_stream *s,
++ struct cx18_buffer *buf)
+{
-+ int i, strobe = 0;
-+ struct au0828_dev *dev = i2c_adap->algo_data;
++ pci_dma_sync_single_for_cpu(s->cx->dev, buf->dma_handle,
++ s->buf_size, s->dma);
++}
+
-+ dprintk(4, "%s()\n", __func__);
++static inline void cx18_buf_sync_for_device(struct cx18_stream *s,
++ struct cx18_buffer *buf)
++{
++ pci_dma_sync_single_for_device(s->cx->dev, buf->dma_handle,
++ s->buf_size, s->dma);
++}
+
-+ au0828_write(dev, REG_2FF, 0x01);
-+ au0828_write(dev, REG_202, 0x07);
++int cx18_buf_copy_from_user(struct cx18_stream *s, struct cx18_buffer *buf,
++ const char __user *src, int copybytes);
++void cx18_buf_swap(struct cx18_buffer *buf);
+
-+ /* Hardware needs 8 bit addresses */
-+ au0828_write(dev, REG_203, msg->addr << 1);
++/* cx18_queue utility functions */
++void cx18_queue_init(struct cx18_queue *q);
++void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf,
++ struct cx18_queue *q);
++struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q);
++int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from,
++ struct cx18_queue *steal, struct cx18_queue *to, int needed_bytes);
++struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
++ u32 bytesused);
++void cx18_flush_queues(struct cx18_stream *s);
+
-+ dprintk(4, "SEND: %02x\n", msg->addr);
++/* cx18_stream utility functions */
++int cx18_stream_alloc(struct cx18_stream *s);
++void cx18_stream_free(struct cx18_stream *s);
+diff --git a/drivers/media/video/cx18/cx18-scb.c b/drivers/media/video/cx18/cx18-scb.c
+new file mode 100644
+index 0000000..30bc803
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-scb.c
+@@ -0,0 +1,121 @@
++/*
++ * cx18 System Control Block initialization
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
-+ for (i = 0; i < msg->len;) {
++#include "cx18-driver.h"
++#include "cx18-scb.h"
+
-+ dprintk(4, " %02x\n", msg->buf[i]);
++void cx18_init_scb(struct cx18 *cx)
++{
++ setup_page(SCB_OFFSET);
++ memset_io(cx->scb, 0, 0x10000);
++
++ writel(IRQ_APU_TO_CPU, &cx->scb->apu2cpu_irq);
++ writel(IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack);
++ writel(IRQ_HPU_TO_CPU, &cx->scb->hpu2cpu_irq);
++ writel(IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack);
++ writel(IRQ_PPU_TO_CPU, &cx->scb->ppu2cpu_irq);
++ writel(IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack);
++ writel(IRQ_EPU_TO_CPU, &cx->scb->epu2cpu_irq);
++ writel(IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack);
++
++ writel(IRQ_CPU_TO_APU, &cx->scb->cpu2apu_irq);
++ writel(IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack);
++ writel(IRQ_HPU_TO_APU, &cx->scb->hpu2apu_irq);
++ writel(IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack);
++ writel(IRQ_PPU_TO_APU, &cx->scb->ppu2apu_irq);
++ writel(IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack);
++ writel(IRQ_EPU_TO_APU, &cx->scb->epu2apu_irq);
++ writel(IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack);
++
++ writel(IRQ_CPU_TO_HPU, &cx->scb->cpu2hpu_irq);
++ writel(IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack);
++ writel(IRQ_APU_TO_HPU, &cx->scb->apu2hpu_irq);
++ writel(IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack);
++ writel(IRQ_PPU_TO_HPU, &cx->scb->ppu2hpu_irq);
++ writel(IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack);
++ writel(IRQ_EPU_TO_HPU, &cx->scb->epu2hpu_irq);
++ writel(IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack);
++
++ writel(IRQ_CPU_TO_PPU, &cx->scb->cpu2ppu_irq);
++ writel(IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack);
++ writel(IRQ_APU_TO_PPU, &cx->scb->apu2ppu_irq);
++ writel(IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack);
++ writel(IRQ_HPU_TO_PPU, &cx->scb->hpu2ppu_irq);
++ writel(IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack);
++ writel(IRQ_EPU_TO_PPU, &cx->scb->epu2ppu_irq);
++ writel(IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack);
++
++ writel(IRQ_CPU_TO_EPU, &cx->scb->cpu2epu_irq);
++ writel(IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack);
++ writel(IRQ_APU_TO_EPU, &cx->scb->apu2epu_irq);
++ writel(IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack);
++ writel(IRQ_HPU_TO_EPU, &cx->scb->hpu2epu_irq);
++ writel(IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack);
++ writel(IRQ_PPU_TO_EPU, &cx->scb->ppu2epu_irq);
++ writel(IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack);
++
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb),
++ &cx->scb->apu2cpu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb),
++ &cx->scb->hpu2cpu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb),
++ &cx->scb->ppu2cpu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb),
++ &cx->scb->epu2cpu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb),
++ &cx->scb->cpu2apu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb),
++ &cx->scb->hpu2apu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb),
++ &cx->scb->ppu2apu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb),
++ &cx->scb->epu2apu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb),
++ &cx->scb->cpu2hpu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb),
++ &cx->scb->apu2hpu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb),
++ &cx->scb->ppu2hpu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb),
++ &cx->scb->epu2hpu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb),
++ &cx->scb->cpu2ppu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb),
++ &cx->scb->apu2ppu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb),
++ &cx->scb->hpu2ppu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb),
++ &cx->scb->epu2ppu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb),
++ &cx->scb->cpu2epu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb),
++ &cx->scb->apu2epu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb),
++ &cx->scb->hpu2epu_mb_offset);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb),
++ &cx->scb->ppu2epu_mb_offset);
+
-+ au0828_write(dev, REG_205, msg->buf[i]);
++ writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu_state),
++ &cx->scb->ipc_offset);
+
-+ strobe++;
-+ i++;
++ writel(1, &cx->scb->hpu_state);
++ writel(1, &cx->scb->epu_state);
++}
+diff --git a/drivers/media/video/cx18/cx18-scb.h b/drivers/media/video/cx18/cx18-scb.h
+new file mode 100644
+index 0000000..86b4cb1
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-scb.h
+@@ -0,0 +1,285 @@
++/*
++ * cx18 System Control Block initialization
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
-+ if ((strobe >= 4) || (i >= msg->len)) {
++#ifndef CX18_SCB_H
++#define CX18_SCB_H
+
-+ /* Strobe the byte into the bus */
-+ if (i < msg->len)
-+ au0828_write(dev, REG_200, 0x41);
-+ else
-+ au0828_write(dev, REG_200, 0x01);
++#include "cx18-mailbox.h"
+
-+ /* Reset strobe trigger */
-+ strobe = 0;
++/* NOTE: All ACK interrupts are in the SW2 register. All non-ACK interrupts
++ are in the SW1 register. */
++
++#define IRQ_APU_TO_CPU 0x00000001
++#define IRQ_CPU_TO_APU_ACK 0x00000001
++#define IRQ_HPU_TO_CPU 0x00000002
++#define IRQ_CPU_TO_HPU_ACK 0x00000002
++#define IRQ_PPU_TO_CPU 0x00000004
++#define IRQ_CPU_TO_PPU_ACK 0x00000004
++#define IRQ_EPU_TO_CPU 0x00000008
++#define IRQ_CPU_TO_EPU_ACK 0x00000008
++
++#define IRQ_CPU_TO_APU 0x00000010
++#define IRQ_APU_TO_CPU_ACK 0x00000010
++#define IRQ_HPU_TO_APU 0x00000020
++#define IRQ_APU_TO_HPU_ACK 0x00000020
++#define IRQ_PPU_TO_APU 0x00000040
++#define IRQ_APU_TO_PPU_ACK 0x00000040
++#define IRQ_EPU_TO_APU 0x00000080
++#define IRQ_APU_TO_EPU_ACK 0x00000080
++
++#define IRQ_CPU_TO_HPU 0x00000100
++#define IRQ_HPU_TO_CPU_ACK 0x00000100
++#define IRQ_APU_TO_HPU 0x00000200
++#define IRQ_HPU_TO_APU_ACK 0x00000200
++#define IRQ_PPU_TO_HPU 0x00000400
++#define IRQ_HPU_TO_PPU_ACK 0x00000400
++#define IRQ_EPU_TO_HPU 0x00000800
++#define IRQ_HPU_TO_EPU_ACK 0x00000800
++
++#define IRQ_CPU_TO_PPU 0x00001000
++#define IRQ_PPU_TO_CPU_ACK 0x00001000
++#define IRQ_APU_TO_PPU 0x00002000
++#define IRQ_PPU_TO_APU_ACK 0x00002000
++#define IRQ_HPU_TO_PPU 0x00004000
++#define IRQ_PPU_TO_HPU_ACK 0x00004000
++#define IRQ_EPU_TO_PPU 0x00008000
++#define IRQ_PPU_TO_EPU_ACK 0x00008000
++
++#define IRQ_CPU_TO_EPU 0x00010000
++#define IRQ_EPU_TO_CPU_ACK 0x00010000
++#define IRQ_APU_TO_EPU 0x00020000
++#define IRQ_EPU_TO_APU_ACK 0x00020000
++#define IRQ_HPU_TO_EPU 0x00040000
++#define IRQ_EPU_TO_HPU_ACK 0x00040000
++#define IRQ_PPU_TO_EPU 0x00080000
++#define IRQ_EPU_TO_PPU_ACK 0x00080000
++
++#define SCB_OFFSET 0xDC0000
++
++/* If Firmware uses fixed memory map, it shall not allocate the area
++ between SCB_OFFSET and SCB_OFFSET+SCB_RESERVED_SIZE-1 inclusive */
++#define SCB_RESERVED_SIZE 0x10000
++
++
++/* This structure is used by EPU to provide memory descriptors in its memory */
++struct cx18_mdl {
++ u32 paddr; /* Physical address of a buffer segment */
++ u32 length; /* Length of the buffer segment */
++};
++
++/* This structure is used by CPU to provide completed buffers information */
++struct cx18_mdl_ack {
++ u32 id; /* ID of a completed MDL */
++ u32 data_used; /* Total data filled in the MDL for buffer 'id' */
++};
++
++struct cx18_scb {
++ /* These fields form the System Control Block which is used at boot time
++ for localizing the IPC data as well as the code positions for all
++ processors. The offsets are from the start of this struct. */
++
++ /* Offset where to find the Inter-Processor Communication data */
++ u32 ipc_offset;
++ u32 reserved01[7];
++ /* Offset where to find the start of the CPU code */
++ u32 cpu_code_offset;
++ u32 reserved02[3];
++ /* Offset where to find the start of the APU code */
++ u32 apu_code_offset;
++ u32 reserved03[3];
++ /* Offset where to find the start of the HPU code */
++ u32 hpu_code_offset;
++ u32 reserved04[3];
++ /* Offset where to find the start of the PPU code */
++ u32 ppu_code_offset;
++ u32 reserved05[3];
++
++ /* These fields form Inter-Processor Communication data which is used
++ by all processors to locate the information needed for communicating
++ with other processors */
++
++ /* Fields for CPU: */
++
++ /* bit 0: 1/0 processor ready/not ready. Set other bits to 0. */
++ u32 cpu_state;
++ u32 reserved1[7];
++ /* Offset to the mailbox used for sending commands from APU to CPU */
++ u32 apu2cpu_mb_offset;
++ /* Value to write to register SW1 register set (0xC7003100) after the
++ command is ready */
++ u32 apu2cpu_irq;
++ /* Value to write to register SW2 register set (0xC7003140) after the
++ command is cleared */
++ u32 apu2cpu_irq_ack;
++ u32 reserved2[13];
++
++ u32 hpu2cpu_mb_offset;
++ u32 hpu2cpu_irq;
++ u32 hpu2cpu_irq_ack;
++ u32 reserved3[13];
++
++ u32 ppu2cpu_mb_offset;
++ u32 ppu2cpu_irq;
++ u32 ppu2cpu_irq_ack;
++ u32 reserved4[13];
++
++ u32 epu2cpu_mb_offset;
++ u32 epu2cpu_irq;
++ u32 epu2cpu_irq_ack;
++ u32 reserved5[13];
++ u32 reserved6[8];
++
++ /* Fields for APU: */
++
++ u32 apu_state;
++ u32 reserved11[7];
++ u32 cpu2apu_mb_offset;
++ u32 cpu2apu_irq;
++ u32 cpu2apu_irq_ack;
++ u32 reserved12[13];
++
++ u32 hpu2apu_mb_offset;
++ u32 hpu2apu_irq;
++ u32 hpu2apu_irq_ack;
++ u32 reserved13[13];
++
++ u32 ppu2apu_mb_offset;
++ u32 ppu2apu_irq;
++ u32 ppu2apu_irq_ack;
++ u32 reserved14[13];
++
++ u32 epu2apu_mb_offset;
++ u32 epu2apu_irq;
++ u32 epu2apu_irq_ack;
++ u32 reserved15[13];
++ u32 reserved16[8];
++
++ /* Fields for HPU: */
++
++ u32 hpu_state;
++ u32 reserved21[7];
++ u32 cpu2hpu_mb_offset;
++ u32 cpu2hpu_irq;
++ u32 cpu2hpu_irq_ack;
++ u32 reserved22[13];
++
++ u32 apu2hpu_mb_offset;
++ u32 apu2hpu_irq;
++ u32 apu2hpu_irq_ack;
++ u32 reserved23[13];
++
++ u32 ppu2hpu_mb_offset;
++ u32 ppu2hpu_irq;
++ u32 ppu2hpu_irq_ack;
++ u32 reserved24[13];
++
++ u32 epu2hpu_mb_offset;
++ u32 epu2hpu_irq;
++ u32 epu2hpu_irq_ack;
++ u32 reserved25[13];
++ u32 reserved26[8];
++
++ /* Fields for PPU: */
++
++ u32 ppu_state;
++ u32 reserved31[7];
++ u32 cpu2ppu_mb_offset;
++ u32 cpu2ppu_irq;
++ u32 cpu2ppu_irq_ack;
++ u32 reserved32[13];
++
++ u32 apu2ppu_mb_offset;
++ u32 apu2ppu_irq;
++ u32 apu2ppu_irq_ack;
++ u32 reserved33[13];
++
++ u32 hpu2ppu_mb_offset;
++ u32 hpu2ppu_irq;
++ u32 hpu2ppu_irq_ack;
++ u32 reserved34[13];
++
++ u32 epu2ppu_mb_offset;
++ u32 epu2ppu_irq;
++ u32 epu2ppu_irq_ack;
++ u32 reserved35[13];
++ u32 reserved36[8];
++
++ /* Fields for EPU: */
++
++ u32 epu_state;
++ u32 reserved41[7];
++ u32 cpu2epu_mb_offset;
++ u32 cpu2epu_irq;
++ u32 cpu2epu_irq_ack;
++ u32 reserved42[13];
++
++ u32 apu2epu_mb_offset;
++ u32 apu2epu_irq;
++ u32 apu2epu_irq_ack;
++ u32 reserved43[13];
++
++ u32 hpu2epu_mb_offset;
++ u32 hpu2epu_irq;
++ u32 hpu2epu_irq_ack;
++ u32 reserved44[13];
++
++ u32 ppu2epu_mb_offset;
++ u32 ppu2epu_irq;
++ u32 ppu2epu_irq_ack;
++ u32 reserved45[13];
++ u32 reserved46[8];
++
++ u32 semaphores[8]; /* Semaphores */
++
++ u32 reserved50[32]; /* Reserved for future use */
++
++ struct cx18_mailbox apu2cpu_mb;
++ struct cx18_mailbox hpu2cpu_mb;
++ struct cx18_mailbox ppu2cpu_mb;
++ struct cx18_mailbox epu2cpu_mb;
++
++ struct cx18_mailbox cpu2apu_mb;
++ struct cx18_mailbox hpu2apu_mb;
++ struct cx18_mailbox ppu2apu_mb;
++ struct cx18_mailbox epu2apu_mb;
++
++ struct cx18_mailbox cpu2hpu_mb;
++ struct cx18_mailbox apu2hpu_mb;
++ struct cx18_mailbox ppu2hpu_mb;
++ struct cx18_mailbox epu2hpu_mb;
++
++ struct cx18_mailbox cpu2ppu_mb;
++ struct cx18_mailbox apu2ppu_mb;
++ struct cx18_mailbox hpu2ppu_mb;
++ struct cx18_mailbox epu2ppu_mb;
++
++ struct cx18_mailbox cpu2epu_mb;
++ struct cx18_mailbox apu2epu_mb;
++ struct cx18_mailbox hpu2epu_mb;
++ struct cx18_mailbox ppu2epu_mb;
+
-+ if (!i2c_wait_write_done(i2c_adap))
-+ return -EIO;
++ struct cx18_mdl_ack cpu_mdl_ack[CX18_MAX_STREAMS][2];
++ struct cx18_mdl cpu_mdl[1];
++};
+
-+ }
++void cx18_init_scb(struct cx18 *cx);
+
-+ }
-+ if (!i2c_wait_done(i2c_adap))
-+ return -EIO;
++#endif
+diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
+new file mode 100644
+index 0000000..afb141b
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-streams.c
+@@ -0,0 +1,566 @@
++/*
++ * cx18 init/start/stop/exit stream functions
++ *
++ * Derived from ivtv-streams.c
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
-+ dprintk(4, "\n");
++#include "cx18-driver.h"
++#include "cx18-fileops.h"
++#include "cx18-mailbox.h"
++#include "cx18-i2c.h"
++#include "cx18-queue.h"
++#include "cx18-ioctl.h"
++#include "cx18-streams.h"
++#include "cx18-cards.h"
++#include "cx18-scb.h"
++#include "cx18-av-core.h"
++#include "cx18-dvb.h"
++
++#define CX18_DSP0_INTERRUPT_MASK 0xd0004C
++
++static struct file_operations cx18_v4l2_enc_fops = {
++ .owner = THIS_MODULE,
++ .read = cx18_v4l2_read,
++ .open = cx18_v4l2_open,
++ .ioctl = cx18_v4l2_ioctl,
++ .release = cx18_v4l2_close,
++ .poll = cx18_v4l2_enc_poll,
++};
++
++/* offset from 0 to register ts v4l2 minors on */
++#define CX18_V4L2_ENC_TS_OFFSET 16
++/* offset from 0 to register pcm v4l2 minors on */
++#define CX18_V4L2_ENC_PCM_OFFSET 24
++/* offset from 0 to register yuv v4l2 minors on */
++#define CX18_V4L2_ENC_YUV_OFFSET 32
+
-+ return msg->len;
-+}
++static struct {
++ const char *name;
++ int vfl_type;
++ int minor_offset;
++ int dma;
++ enum v4l2_buf_type buf_type;
++ struct file_operations *fops;
++} cx18_stream_info[] = {
++ { /* CX18_ENC_STREAM_TYPE_MPG */
++ "encoder MPEG",
++ VFL_TYPE_GRABBER, 0,
++ PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ &cx18_v4l2_enc_fops
++ },
++ { /* CX18_ENC_STREAM_TYPE_TS */
++ "TS",
++ VFL_TYPE_GRABBER, -1,
++ PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ &cx18_v4l2_enc_fops
++ },
++ { /* CX18_ENC_STREAM_TYPE_YUV */
++ "encoder YUV",
++ VFL_TYPE_GRABBER, CX18_V4L2_ENC_YUV_OFFSET,
++ PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ &cx18_v4l2_enc_fops
++ },
++ { /* CX18_ENC_STREAM_TYPE_VBI */
++ "encoder VBI",
++ VFL_TYPE_VBI, 0,
++ PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VBI_CAPTURE,
++ &cx18_v4l2_enc_fops
++ },
++ { /* CX18_ENC_STREAM_TYPE_PCM */
++ "encoder PCM audio",
++ VFL_TYPE_GRABBER, CX18_V4L2_ENC_PCM_OFFSET,
++ PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_PRIVATE,
++ &cx18_v4l2_enc_fops
++ },
++ { /* CX18_ENC_STREAM_TYPE_IDX */
++ "encoder IDX",
++ VFL_TYPE_GRABBER, -1,
++ PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ &cx18_v4l2_enc_fops
++ },
++ { /* CX18_ENC_STREAM_TYPE_RAD */
++ "encoder radio",
++ VFL_TYPE_RADIO, 0,
++ PCI_DMA_NONE, V4L2_BUF_TYPE_PRIVATE,
++ &cx18_v4l2_enc_fops
++ },
++};
+
-+/* FIXME: Implement join handling correctly */
-+static int i2c_readbytes(struct i2c_adapter *i2c_adap,
-+ const struct i2c_msg *msg, int joined)
++static void cx18_stream_init(struct cx18 *cx, int type)
+{
-+ struct au0828_dev *dev = i2c_adap->algo_data;
-+ int i;
++ struct cx18_stream *s = &cx->streams[type];
++ struct video_device *dev = s->v4l2dev;
++ u32 max_size = cx->options.megabytes[type] * 1024 * 1024;
++
++ /* we need to keep v4l2dev, so restore it afterwards */
++ memset(s, 0, sizeof(*s));
++ s->v4l2dev = dev;
++
++ /* initialize cx18_stream fields */
++ s->cx = cx;
++ s->type = type;
++ s->name = cx18_stream_info[type].name;
++ s->handle = 0xffffffff;
++
++ s->dma = cx18_stream_info[type].dma;
++ s->buf_size = cx->stream_buf_size[type];
++ if (s->buf_size)
++ s->buffers = max_size / s->buf_size;
++ if (s->buffers > 63) {
++ /* Each stream has a maximum of 63 buffers,
++ ensure we do not exceed that. */
++ s->buffers = 63;
++ s->buf_size = (max_size / s->buffers) & ~0xfff;
++ }
++ spin_lock_init(&s->qlock);
++ init_waitqueue_head(&s->waitq);
++ s->id = -1;
++ cx18_queue_init(&s->q_free);
++ cx18_queue_init(&s->q_full);
++ cx18_queue_init(&s->q_io);
++}
++
++static int cx18_prep_dev(struct cx18 *cx, int type)
++{
++ struct cx18_stream *s = &cx->streams[type];
++ u32 cap = cx->v4l2_cap;
++ int minor_offset = cx18_stream_info[type].minor_offset;
++ int minor;
++
++ /* These four fields are always initialized. If v4l2dev == NULL, then
++ this stream is not in use. In that case no other fields but these
++ four can be used. */
++ s->v4l2dev = NULL;
++ s->cx = cx;
++ s->type = type;
++ s->name = cx18_stream_info[type].name;
+
-+ dprintk(4, "%s()\n", __func__);
++ /* Check whether the radio is supported */
++ if (type == CX18_ENC_STREAM_TYPE_RAD && !(cap & V4L2_CAP_RADIO))
++ return 0;
+
-+ au0828_write(dev, REG_2FF, 0x01);
-+ au0828_write(dev, REG_202, 0x07);
++ /* Check whether VBI is supported */
++ if (type == CX18_ENC_STREAM_TYPE_VBI &&
++ !(cap & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)))
++ return 0;
+
-+ /* Hardware needs 8 bit addresses */
-+ au0828_write(dev, REG_203, msg->addr << 1);
++ /* card number + user defined offset + device offset */
++ minor = cx->num + cx18_first_minor + minor_offset;
+
-+ dprintk(4, " RECV:\n");
++ /* User explicitly selected 0 buffers for these streams, so don't
++ create them. */
++ if (cx18_stream_info[type].dma != PCI_DMA_NONE &&
++ cx->options.megabytes[type] == 0) {
++ CX18_INFO("Disabled %s device\n", cx18_stream_info[type].name);
++ return 0;
++ }
+
-+ /* Deal with i2c_scan */
-+ if (msg->len == 0) {
-+ au0828_write(dev, REG_200, 0x20);
-+ if (i2c_wait_read_ack(i2c_adap))
-+ return -EIO;
++ cx18_stream_init(cx, type);
++
++ if (minor_offset == -1)
+ return 0;
++
++ /* allocate and initialize the v4l2 video device structure */
++ s->v4l2dev = video_device_alloc();
++ if (s->v4l2dev == NULL) {
++ CX18_ERR("Couldn't allocate v4l2 video_device for %s\n",
++ s->name);
++ return -ENOMEM;
+ }
+
-+ for (i = 0; i < msg->len;) {
++ s->v4l2dev->type =
++ VID_TYPE_CAPTURE | VID_TYPE_TUNER | VID_TYPE_TELETEXT |
++ VID_TYPE_CLIPPING | VID_TYPE_SCALES | VID_TYPE_MPEG_ENCODER;
++ snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18%d %s",
++ cx->num, s->name);
+
-+ i++;
++ s->v4l2dev->minor = minor;
++ s->v4l2dev->dev = &cx->dev->dev;
++ s->v4l2dev->fops = cx18_stream_info[type].fops;
++ s->v4l2dev->release = video_device_release;
+
-+ if (i < msg->len)
-+ au0828_write(dev, REG_200, 0x60);
-+ else
-+ au0828_write(dev, REG_200, 0x20);
++ return 0;
++}
+
-+ if (!i2c_wait_read_done(i2c_adap))
-+ return -EIO;
++/* Initialize v4l2 variables and register v4l2 devices */
++int cx18_streams_setup(struct cx18 *cx)
++{
++ int type;
+
-+ msg->buf[i-1] = au0828_read(dev, REG_209) & 0xff;
++ /* Setup V4L2 Devices */
++ for (type = 0; type < CX18_MAX_STREAMS; type++) {
++ /* Prepare device */
++ if (cx18_prep_dev(cx, type))
++ break;
+
-+ dprintk(4, " %02x\n", msg->buf[i-1]);
++ /* Allocate Stream */
++ if (cx18_stream_alloc(&cx->streams[type]))
++ break;
+ }
-+ if (!i2c_wait_done(i2c_adap))
-+ return -EIO;
-+
-+ dprintk(4, "\n");
++ if (type == CX18_MAX_STREAMS)
++ return 0;
+
-+ return msg->len;
++ /* One or more streams could not be initialized. Clean 'em all up. */
++ cx18_streams_cleanup(cx);
++ return -ENOMEM;
+}
+
-+static int i2c_xfer(struct i2c_adapter *i2c_adap,
-+ struct i2c_msg *msgs, int num)
++static int cx18_reg_dev(struct cx18 *cx, int type)
+{
-+ int i, retval = 0;
++ struct cx18_stream *s = &cx->streams[type];
++ int vfl_type = cx18_stream_info[type].vfl_type;
++ int minor;
++
++ /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something?
++ * We need a VFL_TYPE_TS defined.
++ */
++ if (strcmp("TS", s->name) == 0) {
++ /* just return if no DVB is supported */
++ if ((cx->card->hw_all & CX18_HW_DVB) == 0)
++ return 0;
++ if (cx18_dvb_register(s) < 0) {
++ CX18_ERR("DVB failed to register\n");
++ return -EINVAL;
++ }
++ }
+
-+ dprintk(4, "%s(num = %d)\n", __func__, num);
++ if (s->v4l2dev == NULL)
++ return 0;
+
-+ 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;
++ minor = s->v4l2dev->minor;
++
++ /* Register device. First try the desired minor, then any free one. */
++ if (video_register_device(s->v4l2dev, vfl_type, minor) &&
++ video_register_device(s->v4l2dev, vfl_type, -1)) {
++ CX18_ERR("Couldn't register v4l2 device for %s minor %d\n",
++ s->name, minor);
++ video_device_release(s->v4l2dev);
++ s->v4l2dev = NULL;
++ return -ENOMEM;
+ }
-+ return num;
++ minor = s->v4l2dev->minor;
+
-+err:
-+ return retval;
++ switch (vfl_type) {
++ case VFL_TYPE_GRABBER:
++ CX18_INFO("Registered device video%d for %s (%d MB)\n",
++ minor, s->name, cx->options.megabytes[type]);
++ break;
++
++ case VFL_TYPE_RADIO:
++ CX18_INFO("Registered device radio%d for %s\n",
++ minor - MINOR_VFL_TYPE_RADIO_MIN, s->name);
++ break;
++
++ case VFL_TYPE_VBI:
++ if (cx->options.megabytes[type])
++ CX18_INFO("Registered device vbi%d for %s (%d MB)\n",
++ minor - MINOR_VFL_TYPE_VBI_MIN,
++ s->name, cx->options.megabytes[type]);
++ else
++ CX18_INFO("Registered device vbi%d for %s\n",
++ minor - MINOR_VFL_TYPE_VBI_MIN, s->name);
++ break;
++ }
++
++ return 0;
+}
+
-+static int attach_inform(struct i2c_client *client)
++/* Register v4l2 devices */
++int cx18_streams_register(struct cx18 *cx)
+{
-+ dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
-+ client->driver->driver.name, client->addr, client->name);
++ int type;
++ int err = 0;
+
-+ if (!client->driver->command)
++ /* Register V4L2 devices */
++ for (type = 0; type < CX18_MAX_STREAMS; type++)
++ err |= cx18_reg_dev(cx, type);
++
++ if (err == 0)
+ return 0;
+
-+ return 0;
++ /* One or more streams could not be initialized. Clean 'em all up. */
++ cx18_streams_cleanup(cx);
++ return -ENOMEM;
+}
+
-+static int detach_inform(struct i2c_client *client)
++/* Unregister v4l2 devices */
++void cx18_streams_cleanup(struct cx18 *cx)
+{
-+ dprintk(1, "i2c detach [client=%s]\n", client->name);
++ struct video_device *vdev;
++ int type;
+
-+ return 0;
++ /* Teardown all streams */
++ for (type = 0; type < CX18_MAX_STREAMS; type++) {
++ if (cx->streams[type].dvb.enabled)
++ cx18_dvb_unregister(&cx->streams[type]);
++
++ vdev = cx->streams[type].v4l2dev;
++
++ cx->streams[type].v4l2dev = NULL;
++ if (vdev == NULL)
++ continue;
++
++ cx18_stream_free(&cx->streams[type]);
++
++ /* Unregister device */
++ video_unregister_device(vdev);
++ }
+}
+
-+void au0828_call_i2c_clients(struct au0828_dev *dev,
-+ unsigned int cmd, void *arg)
++static void cx18_vbi_setup(struct cx18_stream *s)
+{
-+ if (dev->i2c_rc != 0)
-+ return;
++ struct cx18 *cx = s->cx;
++ int raw = cx->vbi.sliced_in->service_set == 0;
++ u32 data[CX2341X_MBOX_MAX_DATA];
++ int lines;
+
-+ i2c_clients_command(&dev->i2c_adap, cmd, arg);
++ if (cx->is_60hz) {
++ cx->vbi.count = 12;
++ cx->vbi.start[0] = 10;
++ cx->vbi.start[1] = 273;
++ } else { /* PAL/SECAM */
++ cx->vbi.count = 18;
++ cx->vbi.start[0] = 6;
++ cx->vbi.start[1] = 318;
++ }
++
++ /* setup VBI registers */
++ cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in);
++
++ /* determine number of lines and total number of VBI bytes.
++ A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1
++ The '- 1' byte is probably an unused U or V byte. Or something...
++ A sliced line takes 51 bytes: 4 byte frame header, 4 byte internal
++ header, 42 data bytes + checksum (to be confirmed) */
++ if (raw) {
++ lines = cx->vbi.count * 2;
++ } else {
++ lines = cx->is_60hz ? 24 : 38;
++ if (cx->is_60hz)
++ lines += 2;
++ }
++
++ cx->vbi.enc_size = lines *
++ (raw ? cx->vbi.raw_size : cx->vbi.sliced_size);
++
++ data[0] = s->handle;
++ /* Lines per field */
++ data[1] = (lines / 2) | ((lines / 2) << 16);
++ /* bytes per line */
++ data[2] = (raw ? cx->vbi.raw_size : cx->vbi.sliced_size);
++ /* Every X number of frames a VBI interrupt arrives
++ (frames as in 25 or 30 fps) */
++ data[3] = 1;
++ /* Setup VBI for the cx25840 digitizer */
++ if (raw) {
++ data[4] = 0x20602060;
++ data[5] = 0x30703070;
++ } else {
++ data[4] = 0xB0F0B0F0;
++ data[5] = 0xA0E0A0E0;
++ }
++
++ CX18_DEBUG_INFO("Setup VBI h: %d lines %x bpl %d fr %d %x %x\n",
++ data[0], data[1], data[2], data[3], data[4], data[5]);
++
++ if (s->type == CX18_ENC_STREAM_TYPE_VBI)
++ cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data);
+}
+
-+static u32 au0828_functionality(struct i2c_adapter *adap)
++int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
+{
-+ return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
-+}
++ u32 data[MAX_MB_ARGUMENTS];
++ struct cx18 *cx = s->cx;
++ struct list_head *p;
++ int ts = 0;
++ int captype = 0;
+
-+static struct i2c_algorithm au0828_i2c_algo_template = {
-+ .master_xfer = i2c_xfer,
-+ .functionality = au0828_functionality,
-+};
++ if (s->v4l2dev == NULL && s->dvb.enabled == 0)
++ return -EINVAL;
+
-+/* ----------------------------------------------------------------------- */
++ CX18_DEBUG_INFO("Start encoder stream %s\n", s->name);
+
-+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,
-+};
++ switch (s->type) {
++ case CX18_ENC_STREAM_TYPE_MPG:
++ captype = CAPTURE_CHANNEL_TYPE_MPEG;
++ cx->mpg_data_received = cx->vbi_data_inserted = 0;
++ cx->dualwatch_jiffies = jiffies;
++ cx->dualwatch_stereo_mode = cx->params.audio_properties & 0x300;
++ cx->search_pack_header = 0;
++ break;
++
++ case CX18_ENC_STREAM_TYPE_TS:
++ captype = CAPTURE_CHANNEL_TYPE_TS;
++ ts = 1;
++ break;
++ case CX18_ENC_STREAM_TYPE_YUV:
++ captype = CAPTURE_CHANNEL_TYPE_YUV;
++ break;
++ case CX18_ENC_STREAM_TYPE_PCM:
++ captype = CAPTURE_CHANNEL_TYPE_PCM;
++ break;
++ case CX18_ENC_STREAM_TYPE_VBI:
++ captype = cx->vbi.sliced_in->service_set ?
++ CAPTURE_CHANNEL_TYPE_SLICED_VBI : CAPTURE_CHANNEL_TYPE_VBI;
++ cx->vbi.frame = 0;
++ cx->vbi.inserted_frame = 0;
++ memset(cx->vbi.sliced_mpeg_size,
++ 0, sizeof(cx->vbi.sliced_mpeg_size));
++ break;
++ default:
++ return -EINVAL;
++ }
++ s->buffers_stolen = 0;
+
-+static struct i2c_client au0828_i2c_client_template = {
-+ .name = "au0828 internal",
-+};
++ /* mute/unmute video */
++ cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2,
++ s->handle, !!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags));
+
-+static char *i2c_devs[128] = {
-+ [0x8e >> 1] = "au8522",
-+ [0xa0 >> 1] = "eeprom",
-+ [0xc2 >> 1] = "tuner/xc5000",
-+};
++ /* Clear Streamoff flags in case left from last capture */
++ clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+
-+static void do_i2c_scan(char *name, struct i2c_client *c)
++ cx18_vapi_result(cx, data, CX18_CREATE_TASK, 1, CPU_CMD_MASK_CAPTURE);
++ s->handle = data[0];
++ cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype);
++
++ if (atomic_read(&cx->capturing) == 0 && !ts) {
++ /* Stuff from Windows, we don't know what it is */
++ cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0);
++ cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1);
++ cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 8, 0);
++ cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 4, 1);
++ cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, s->handle, 12);
++
++ cx18_vapi(cx, CX18_CPU_SET_CAPTURE_LINE_NO, 3,
++ s->handle, cx->digitizer, cx->digitizer);
++
++ /* Setup VBI */
++ if (cx->v4l2_cap & V4L2_CAP_VBI_CAPTURE)
++ cx18_vbi_setup(s);
++
++ /* assign program index info.
++ Mask 7: select I/P/B, Num_req: 400 max */
++ cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 1, 0);
++
++ /* Setup API for Stream */
++ cx2341x_update(cx, cx18_api_func, NULL, &cx->params);
++ }
++
++ if (atomic_read(&cx->capturing) == 0) {
++ clear_bit(CX18_F_I_EOS, &cx->i_flags);
++ write_reg(7, CX18_DSP0_INTERRUPT_MASK);
++ }
++
++ cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle,
++ (void *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem,
++ (void *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem);
++
++ list_for_each(p, &s->q_free.list) {
++ struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list);
++
++ writel(buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr);
++ writel(s->buf_size, &cx->scb->cpu_mdl[buf->id].length);
++ cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
++ (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, 1,
++ buf->id, s->buf_size);
++ }
++ /* begin_capture */
++ if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) {
++ CX18_DEBUG_WARN("Error starting capture!\n");
++ cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
++ return -EINVAL;
++ }
++
++ /* you're live! sit back and await interrupts :) */
++ atomic_inc(&cx->capturing);
++ return 0;
++}
++
++void cx18_stop_all_captures(struct cx18 *cx)
+{
-+ unsigned char buf;
-+ int i, rc;
++ int i;
+
-+ for (i = 0; i < 128; i++) {
-+ c->addr = i;
-+ rc = i2c_master_recv(c, &buf, 0);
-+ if (rc < 0)
++ for (i = CX18_MAX_STREAMS - 1; i >= 0; i--) {
++ struct cx18_stream *s = &cx->streams[i];
++
++ if (s->v4l2dev == NULL && s->dvb.enabled == 0)
+ continue;
-+ printk(KERN_INFO "%s: i2c scan: found device @ 0x%x [%s]\n",
-+ name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
++ if (test_bit(CX18_F_S_STREAMING, &s->s_flags))
++ cx18_stop_v4l2_encode_stream(s, 0);
+ }
+}
+
-+/* init + register i2c algo-bit adapter */
-+int au0828_i2c_register(struct au0828_dev *dev)
++int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
+{
-+ dprintk(1, "%s()\n", __func__);
++ struct cx18 *cx = s->cx;
++ unsigned long then;
+
-+ 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));
++ if (s->v4l2dev == NULL && s->dvb.enabled == 0)
++ return -EINVAL;
+
-+ dev->i2c_adap.dev.parent = &dev->usbdev->dev;
++ /* This function assumes that you are allowed to stop the capture
++ and that we are actually capturing */
+
-+ strlcpy(dev->i2c_adap.name, DRIVER_NAME,
-+ sizeof(dev->i2c_adap.name));
++ CX18_DEBUG_INFO("Stop Capture\n");
+
-+ dev->i2c_algo.data = dev;
-+ dev->i2c_adap.algo_data = dev;
-+ i2c_set_adapdata(&dev->i2c_adap, dev);
-+ i2c_add_adapter(&dev->i2c_adap);
++ if (atomic_read(&cx->capturing) == 0)
++ return 0;
+
-+ dev->i2c_client.adapter = &dev->i2c_adap;
++ if (s->type == CX18_ENC_STREAM_TYPE_MPG)
++ cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, !gop_end);
++ else
++ cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle);
+
-+ 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);
++ then = jiffies;
+
-+ return dev->i2c_rc;
++ if (s->type == CX18_ENC_STREAM_TYPE_MPG && gop_end) {
++ CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n");
++ }
++
++ atomic_dec(&cx->capturing);
++
++ /* Clear capture and no-read bits */
++ clear_bit(CX18_F_S_STREAMING, &s->s_flags);
++
++ cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
++ s->handle = 0xffffffff;
++
++ if (atomic_read(&cx->capturing) > 0)
++ return 0;
++
++ write_reg(5, CX18_DSP0_INTERRUPT_MASK);
++ wake_up(&s->waitq);
++
++ return 0;
+}
+
-+int au0828_i2c_unregister(struct au0828_dev *dev)
++u32 cx18_find_handle(struct cx18 *cx)
+{
-+ i2c_del_adapter(&dev->i2c_adap);
++ int i;
++
++ /* find first available handle to be used for global settings */
++ for (i = 0; i < CX18_MAX_STREAMS; i++) {
++ struct cx18_stream *s = &cx->streams[i];
++
++ if (s->v4l2dev && s->handle)
++ return s->handle;
++ }
+ return 0;
+}
-+
-diff --git a/drivers/media/video/au0828/au0828-reg.h b/drivers/media/video/au0828/au0828-reg.h
+diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h
new file mode 100644
-index 0000000..3982755
+index 0000000..8c7ba7d
--- /dev/null
-+++ b/drivers/media/video/au0828/au0828-reg.h
-@@ -0,0 +1,38 @@
++++ b/drivers/media/video/cx18/cx18-streams.h
+@@ -0,0 +1,33 @@
+/*
-+ * Driver for the Auvitek USB bridge
++ * cx18 init/start/stop/exit stream functions
+ *
-+ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ * Derived from ivtv-streams.h
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
@@ -390944,41 +555561,36 @@
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ *
+ * GNU General Public License for more details.
+ *
+ * You 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.
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ * 02111-1307 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
++u32 cx18_find_handle(struct cx18 *cx);
++int cx18_streams_setup(struct cx18 *cx);
++int cx18_streams_register(struct cx18 *cx);
++void cx18_streams_cleanup(struct cx18 *cx);
+
-+#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
++/* Capture related */
++int cx18_start_v4l2_encode_stream(struct cx18_stream *s);
++int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end);
+
-+#define REG_600 0x600
-diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h
++void cx18_stop_all_captures(struct cx18 *cx);
+diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c
new file mode 100644
-index 0000000..7beb571
+index 0000000..22e76ee
--- /dev/null
-+++ b/drivers/media/video/au0828/au0828.h
-@@ -0,0 +1,124 @@
++++ b/drivers/media/video/cx18/cx18-vbi.c
+@@ -0,0 +1,208 @@
+/*
-+ * Driver for the Auvitek AU0828 USB bridge
++ * cx18 Vertical Blank Interval support functions
+ *
-+ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ * Derived from ivtv-vbi.c
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
@@ -390988,730 +555600,860 @@
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ *
+ * GNU General Public License for more details.
+ *
+ * You 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.
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ * 02111-1307 USA
+ */
+
-+#include <linux/usb.h>
-+#include <linux/i2c.h>
-+#include <linux/i2c-algo-bit.h>
-+#include <media/tveeprom.h>
++#include "cx18-driver.h"
++#include "cx18-vbi.h"
++#include "cx18-ioctl.h"
++#include "cx18-queue.h"
++#include "cx18-av-core.h"
+
-+/* DVB */
-+#include "demux.h"
-+#include "dmxdev.h"
-+#include "dvb_demux.h"
-+#include "dvb_frontend.h"
-+#include "dvb_net.h"
-+#include "dvbdev.h"
++static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp)
++{
++ int line = 0;
++ int i;
++ u32 linemask[2] = { 0, 0 };
++ unsigned short size;
++ static const u8 mpeg_hdr_data[] = {
++ 0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66,
++ 0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff,
++ 0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80,
++ 0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff
++ };
++ const int sd = sizeof(mpeg_hdr_data); /* start of vbi data */
++ int idx = cx->vbi.frame % CX18_VBI_FRAMES;
++ u8 *dst = &cx->vbi.sliced_mpeg_data[idx][0];
++
++ for (i = 0; i < lines; i++) {
++ struct v4l2_sliced_vbi_data *sdata = cx->vbi.sliced_data + i;
++ int f, l;
+
-+#include "au0828-reg.h"
-+#include "au0828-cards.h"
++ if (sdata->id == 0)
++ continue;
+
-+#define DRIVER_NAME "au0828"
-+#define URB_COUNT 16
-+#define URB_BUFSIZE (0xe522)
++ l = sdata->line - 6;
++ f = sdata->field;
++ if (f)
++ l += 18;
++ if (l < 32)
++ linemask[0] |= (1 << l);
++ else
++ linemask[1] |= (1 << (l - 32));
++ dst[sd + 12 + line * 43] = cx18_service2vbi(sdata->id);
++ memcpy(dst + sd + 12 + line * 43 + 1, sdata->data, 42);
++ line++;
++ }
++ memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data));
++ if (line == 36) {
++ /* All lines are used, so there is no space for the linemask
++ (the max size of the VBI data is 36 * 43 + 4 bytes).
++ So in this case we use the magic number 'ITV0'. */
++ memcpy(dst + sd, "ITV0", 4);
++ memcpy(dst + sd + 4, dst + sd + 12, line * 43);
++ size = 4 + ((43 * line + 3) & ~3);
++ } else {
++ memcpy(dst + sd, "cx0", 4);
++ memcpy(dst + sd + 4, &linemask[0], 8);
++ size = 12 + ((43 * line + 3) & ~3);
++ }
++ dst[4+16] = (size + 10) >> 8;
++ dst[5+16] = (size + 10) & 0xff;
++ dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6);
++ dst[10+16] = (pts_stamp >> 22) & 0xff;
++ dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff);
++ dst[12+16] = (pts_stamp >> 7) & 0xff;
++ dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1);
++ cx->vbi.sliced_mpeg_size[idx] = sd + size;
++}
++
++/* Compress raw VBI format, removes leading SAV codes and surplus space
++ after the field.
++ Returns new compressed size. */
++static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size)
++{
++ u32 line_size = cx->vbi.raw_decoder_line_size;
++ u32 lines = cx->vbi.count;
++ u8 sav1 = cx->vbi.raw_decoder_sav_odd_field;
++ u8 sav2 = cx->vbi.raw_decoder_sav_even_field;
++ u8 *q = buf;
++ u8 *p;
++ int i;
+
-+struct au0828_board {
-+ char *name;
-+};
++ for (i = 0; i < lines; i++) {
++ p = buf + i * line_size;
+
-+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;
-+};
++ /* Look for SAV code */
++ if (p[0] != 0xff || p[1] || p[2] ||
++ (p[3] != sav1 && p[3] != sav2))
++ break;
++ memcpy(q, p + 4, line_size - 4);
++ q += line_size - 4;
++ }
++ return lines * (line_size - 4);
++}
+
-+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;
++/* Compressed VBI format, all found sliced blocks put next to one another
++ Returns new compressed size */
++static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf,
++ u32 size, u8 sav)
++{
++ u32 line_size = cx->vbi.sliced_decoder_line_size;
++ struct v4l2_decode_vbi_line vbi;
++ int i;
+
-+ /* Digital */
-+ struct au0828_dvb dvb;
++ /* find the first valid line */
++ for (i = 0; i < size; i++, buf++) {
++ if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav)
++ break;
++ }
+
-+ /* USB / URB Related */
-+ int urb_streaming;
-+ struct urb *urbs[URB_COUNT];
++ size -= i;
++ if (size < line_size)
++ return line;
++ for (i = 0; i < size / line_size; i++) {
++ u8 *p = buf + i * line_size;
+
-+};
++ /* Look for SAV code */
++ if (p[0] != 0xff || p[1] || p[2] || p[3] != sav)
++ continue;
++ vbi.p = p + 4;
++ cx18_av_cmd(cx, VIDIOC_INT_DECODE_VBI_LINE, &vbi);
++ if (vbi.type) {
++ cx->vbi.sliced_data[line].id = vbi.type;
++ cx->vbi.sliced_data[line].field = vbi.is_second_field;
++ cx->vbi.sliced_data[line].line = vbi.line;
++ memcpy(cx->vbi.sliced_data[line].data, vbi.p, 42);
++ line++;
++ }
++ }
++ return line;
++}
+
-+struct au0828_buff {
-+ struct au0828_dev *dev;
-+ struct urb *purb;
-+ struct list_head buff_list;
-+};
++void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf,
++ u64 pts_stamp, int streamtype)
++{
++ u8 *p = (u8 *) buf->buf;
++ u32 size = buf->bytesused;
++ int lines;
+
-+/* ----------------------------------------------------------- */
-+#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)))
++ if (streamtype != CX18_ENC_STREAM_TYPE_VBI)
++ return;
+
-+#define au0828_set(dev, reg, bit) au0828_andor(dev, (reg), (bit), (bit))
-+#define au0828_clear(dev, reg, bit) au0828_andor(dev, (reg), (bit), 0)
++ /* Raw VBI data */
++ if (cx->vbi.sliced_in->service_set == 0) {
++ u8 type;
++
++ cx18_buf_swap(buf);
++
++ type = p[3];
++
++ size = buf->bytesused = compress_raw_buf(cx, p, size);
++
++ /* second field of the frame? */
++ if (type == cx->vbi.raw_decoder_sav_even_field) {
++ /* Dirty hack needed for backwards
++ compatibility of old VBI software. */
++ p += size - 4;
++ memcpy(p, &cx->vbi.frame, 4);
++ cx->vbi.frame++;
++ }
++ return;
++ }
+
-+/* ----------------------------------------------------------- */
-+/* 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;
++ /* Sliced VBI data with data insertion */
++ cx18_buf_swap(buf);
+
-+/* ----------------------------------------------------------- */
-+/* 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);
++ /* first field */
++ lines = compress_sliced_buf(cx, 0, p, size / 2,
++ cx->vbi.sliced_decoder_sav_odd_field);
++ /* second field */
++ /* experimentation shows that the second half does not always
++ begin at the exact address. So start a bit earlier
++ (hence 32). */
++ lines = compress_sliced_buf(cx, lines, p + size / 2 - 32,
++ size / 2 + 32, cx->vbi.sliced_decoder_sav_even_field);
++ /* always return at least one empty line */
++ if (lines == 0) {
++ cx->vbi.sliced_data[0].id = 0;
++ cx->vbi.sliced_data[0].line = 0;
++ cx->vbi.sliced_data[0].field = 0;
++ lines = 1;
++ }
++ buf->bytesused = size = lines * sizeof(cx->vbi.sliced_data[0]);
++ memcpy(p, &cx->vbi.sliced_data[0], size);
++
++ if (cx->vbi.insert_mpeg)
++ copy_vbi_data(cx, lines, pts_stamp);
++ cx->vbi.frame++;
++}
+diff --git a/drivers/media/video/cx18/cx18-vbi.h b/drivers/media/video/cx18/cx18-vbi.h
+new file mode 100644
+index 0000000..c56ff7d
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-vbi.h
+@@ -0,0 +1,26 @@
++/*
++ * cx18 Vertical Blank Interval support functions
++ *
++ * Derived from ivtv-vbi.h
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
-+/* ----------------------------------------------------------- */
-+/* 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);
++void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf,
++ u64 pts_stamp, int streamtype);
++int cx18_used_line(struct cx18 *cx, int line, int field);
+diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h
+new file mode 100644
+index 0000000..d5c7a6f
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-version.h
+@@ -0,0 +1,34 @@
++/*
++ * cx18 driver version information
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
-+/* ----------------------------------------------------------- */
-+/* au0828-dvb.c */
-+extern int au0828_dvb_register(struct au0828_dev *dev);
-+extern void au0828_dvb_unregister(struct au0828_dev *dev);
++#ifndef CX18_VERSION_H
++#define CX18_VERSION_H
+
-+#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);
++#define CX18_DRIVER_NAME "cx18"
++#define CX18_DRIVER_VERSION_MAJOR 1
++#define CX18_DRIVER_VERSION_MINOR 0
++#define CX18_DRIVER_VERSION_PATCHLEVEL 0
+
- static int terratec_active_radio_upgrade(struct bttv *btv);
- static int tea5757_read(struct bttv *btv);
- static int tea5757_write(struct bttv *btv, int value);
-@@ -301,6 +303,7 @@ static struct CARD {
- { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" },
- { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini "},
- { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2, "DViCO FusionHDTV 2" },
-+ { 0x763c008a, BTTV_BOARD_GEOVISION_GV600, "GeoVision GV-600" },
-
- { 0, -1, NULL }
- };
-@@ -576,6 +579,8 @@ struct tvcard bttv_tvcards[] = {
- .needs_tvaudio = 1,
- .pll = PLL_28,
- .tuner_type = UNSET,
-+ .tuner_addr = ADDR_UNSET,
-+ .radio_addr = ADDR_UNSET,
- },
- [BTTV_BOARD_WINVIEW_601] = {
- .name = "Leadtek WinView 601",
-@@ -2322,7 +2327,7 @@ struct tvcard bttv_tvcards[] = {
- .tuner = 0,
- .svhs = 2,
- .muxsel = { 2, 3, 1, 0 },
-- .tuner_type = TUNER_PHILIPS_ATSC,
-+ .tuner_type = TUNER_PHILIPS_FCV1236D,
- .tuner_addr = ADDR_UNSET,
- .radio_addr = ADDR_UNSET,
- .has_dvb = 1,
-@@ -2961,7 +2966,7 @@ struct tvcard bttv_tvcards[] = {
- [BTTV_BOARD_DVICO_FUSIONHDTV_2] = {
- .name = "DViCO FusionHDTV 2",
- .tuner = 0,
-- .tuner_type = TUNER_PHILIPS_ATSC, /* FCV1236D */
-+ .tuner_type = TUNER_PHILIPS_FCV1236D,
- .tuner_addr = ADDR_UNSET,
- .radio_addr = ADDR_UNSET,
- .video_inputs = 3,
-@@ -2992,6 +2997,45 @@ struct tvcard bttv_tvcards[] = {
- .tuner_addr = ADDR_UNSET,
- .radio_addr = ADDR_UNSET,
- },
-+ [BTTV_BOARD_GEOVISION_GV600] = {
-+ /* emhn at usb.ve */
-+ .name = "Geovision GV-600",
-+ .video_inputs = 16,
-+ .audio_inputs = 0,
-+ .tuner = UNSET,
-+ .svhs = UNSET,
-+ .gpiomask = 0x0,
-+ .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2,
-+ 2, 2, 2, 2, 2, 2, 2, 2 },
-+ .muxsel_hook = geovision_muxsel,
-+ .gpiomux = { 0 },
-+ .no_msp34xx = 1,
-+ .pll = PLL_28,
-+ .tuner_type = UNSET,
-+ .tuner_addr = ADDR_UNSET,
-+ .radio_addr = ADDR_UNSET,
-+ },
-+ [BTTV_BOARD_KOZUMI_KTV_01C] = {
-+ /* Mauro Lacy <mauro at lacy.com.ar>
-+ * Based on MagicTV and Conceptronic CONTVFMi */
++#define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL)
++#define CX18_DRIVER_VERSION KERNEL_VERSION(CX18_DRIVER_VERSION_MAJOR, \
++ CX18_DRIVER_VERSION_MINOR, CX18_DRIVER_VERSION_PATCHLEVEL)
+
-+ .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)
++#endif
+diff --git a/drivers/media/video/cx18/cx18-video.c b/drivers/media/video/cx18/cx18-video.c
+new file mode 100644
+index 0000000..2e5c419
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-video.c
+@@ -0,0 +1,45 @@
++/*
++ * cx18 video interface functions
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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 "cx18-driver.h"
++#include "cx18-video.h"
++#include "cx18-av-core.h"
++#include "cx18-cards.h"
++
++void cx18_video_set_io(struct cx18 *cx)
+{
-+ unsigned int inmux = input % 16;
-+ gpio_inout(0xf, 0xf);
-+ gpio_bits(0xf, inmux);
++ struct v4l2_routing route;
++ int inp = cx->active_input;
++ u32 type;
++
++ route.input = cx->card->video_inputs[inp].video_input;
++ route.output = 0;
++ cx18_av_cmd(cx, VIDIOC_INT_S_VIDEO_ROUTING, &route);
++
++ type = cx->card->video_inputs[inp].video_type;
++
++ if (type == CX18_CARD_INPUT_VID_TUNER)
++ route.input = 0; /* Tuner */
++ else if (type < CX18_CARD_INPUT_COMPOSITE1)
++ route.input = 2; /* S-Video */
++ else
++ route.input = 1; /* Composite */
+}
+diff --git a/drivers/media/video/cx18/cx18-video.h b/drivers/media/video/cx18/cx18-video.h
+new file mode 100644
+index 0000000..529006a
+--- /dev/null
++++ b/drivers/media/video/cx18/cx18-video.h
+@@ -0,0 +1,22 @@
++/*
++ * cx18 video interface functions
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
++
++void cx18_video_set_io(struct cx18 *cx);
+diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h
+new file mode 100644
+index 0000000..33f78da
+--- /dev/null
++++ b/drivers/media/video/cx18/cx23418.h
+@@ -0,0 +1,458 @@
++/*
++ * cx18 header containing common defines.
++ *
++ * Copyright (C) 2007 Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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
++ */
+
- /* ----------------------------------------------------------------------- */
-
- 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;
++#ifndef CX23418_H
++#define CX23418_H
+
- 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;
++#include <media/cx2341x.h>
+
- 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);
++#define MGR_CMD_MASK 0x40000000
++/* The MSB of the command code indicates that this is the completion of a
++ command */
++#define MGR_CMD_MASK_ACK (MGR_CMD_MASK | 0x80000000)
++
++/* Description: This command creates a new instance of a certain task
++ IN[0] - Task ID. This is one of the XPU_CMD_MASK_YYY where XPU is
++ the processor on which the task YYY will be created
++ OUT[0] - Task handle. This handle is passed along with commands to
++ dispatch to the right instance of the task
++ ReturnCode - One of the ERR_SYS_... */
++#define CX18_CREATE_TASK (MGR_CMD_MASK | 0x0001)
++
++/* Description: This command destroys an instance of a task
++ IN[0] - Task handle. Hanlde of the task to destroy
++ ReturnCode - One of the ERR_SYS_... */
++#define CX18_DESTROY_TASK (MGR_CMD_MASK | 0x0002)
++
++/* All commands for CPU have the following mask set */
++#define CPU_CMD_MASK 0x20000000
++#define CPU_CMD_MASK_ACK (CPU_CMD_MASK | 0x80000000)
++#define CPU_CMD_MASK_CAPTURE (CPU_CMD_MASK | 0x00020000)
++#define CPU_CMD_MASK_TS (CPU_CMD_MASK | 0x00040000)
++
++#define EPU_CMD_MASK 0x02000000
++#define EPU_CMD_MASK_DEBUG (EPU_CMD_MASK | 0x000000)
++#define EPU_CMD_MASK_DE (EPU_CMD_MASK | 0x040000)
++
++/* Description: This command indicates that a Memory Descriptor List has been
++ filled with the requested channel type
++ IN[0] - Task handle. Handle of the task
++ IN[1] - Offset of the MDL_ACK from the beginning of the local DDR.
++ IN[2] - Number of CNXT_MDL_ACK structures in the array pointed to by IN[1]
++ ReturnCode - One of the ERR_DE_... */
++#define CX18_EPU_DMA_DONE (EPU_CMD_MASK_DE | 0x0001)
++
++/* Something interesting happened
++ IN[0] - A value to log
++ IN[1] - An offset of a string in the MiniMe memory;
++ 0/zero/NULL means "I have nothing to say" */
++#define CX18_EPU_DEBUG (EPU_CMD_MASK_DEBUG | 0x0003)
++
++/* Description: This command starts streaming with the set channel type
++ IN[0] - Task handle. Handle of the task to start
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_CAPTURE_START (CPU_CMD_MASK_CAPTURE | 0x0002)
++
++/* Description: This command stops streaming with the set channel type
++ IN[0] - Task handle. Handle of the task to stop
++ IN[1] - 0 = stop at end of GOP, 1 = stop at end of frame (MPEG only)
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_CAPTURE_STOP (CPU_CMD_MASK_CAPTURE | 0x0003)
++
++/* Description: This command pauses streaming with the set channel type
++ IN[0] - Task handle. Handle of the task to pause
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_CAPTURE_PAUSE (CPU_CMD_MASK_CAPTURE | 0x0007)
++
++/* Description: This command resumes streaming with the set channel type
++ IN[0] - Task handle. Handle of the task to resume
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_CAPTURE_RESUME (CPU_CMD_MASK_CAPTURE | 0x0008)
++
++#define CAPTURE_CHANNEL_TYPE_NONE 0
++#define CAPTURE_CHANNEL_TYPE_MPEG 1
++#define CAPTURE_CHANNEL_TYPE_INDEX 2
++#define CAPTURE_CHANNEL_TYPE_YUV 3
++#define CAPTURE_CHANNEL_TYPE_PCM 4
++#define CAPTURE_CHANNEL_TYPE_VBI 5
++#define CAPTURE_CHANNEL_TYPE_SLICED_VBI 6
++#define CAPTURE_CHANNEL_TYPE_TS 7
++#define CAPTURE_CHANNEL_TYPE_MAX 15
++
++/* Description: This command sets the channel type. This can only be done
++ when stopped.
++ IN[0] - Task handle. Handle of the task to start
++ IN[1] - Channel Type. See Below.
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_CHANNEL_TYPE (CPU_CMD_MASK_CAPTURE + 1)
++
++/* Description: Set stream output type
++ IN[0] - task handle. Handle of the task to start
++ IN[1] - type
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_STREAM_OUTPUT_TYPE (CPU_CMD_MASK_CAPTURE | 0x0012)
++
++/* Description: Set video input resolution and frame rate
++ IN[0] - task handle
++ IN[1] - reserved
++ IN[2] - reserved
++ IN[3] - reserved
++ IN[4] - reserved
++ IN[5] - frame rate, 0 - 29.97f/s, 1 - 25f/s
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_VIDEO_IN (CPU_CMD_MASK_CAPTURE | 0x0004)
++
++/* Description: Set video frame rate
++ IN[0] - task handle. Handle of the task to start
++ IN[1] - video bit rate mode
++ IN[2] - video average rate
++ IN[3] - video peak rate
++ IN[4] - system mux rate
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_VIDEO_RATE (CPU_CMD_MASK_CAPTURE | 0x0005)
++
++/* Description: Set video output resolution
++ IN[0] - task handle
++ IN[1] - horizontal size
++ IN[2] - vertical size
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_VIDEO_RESOLUTION (CPU_CMD_MASK_CAPTURE | 0x0006)
++
++/* Description: This command set filter parameters
++ IN[0] - Task handle. Handle of the task
++ IN[1] - type, 0 - temporal, 1 - spatial, 2 - median
++ IN[2] - mode, temporal/spatial: 0 - disable, 1 - static, 2 - dynamic
++ median: 0 = disable, 1 = horizontal, 2 = vertical,
++ 3 = horizontal/vertical, 4 = diagonal
++ IN[3] - strength, temporal 0 - 31, spatial 0 - 15
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_FILTER_PARAM (CPU_CMD_MASK_CAPTURE | 0x0009)
++
++/* Description: This command set spatial filter type
++ IN[0] - Task handle.
++ IN[1] - luma type: 0 = disable, 1 = 1D horizontal only, 2 = 1D vertical only,
++ 3 = 2D H/V separable, 4 = 2D symmetric non-separable
++ IN[2] - chroma type: 0 - diable, 1 = 1D horizontal
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_SPATIAL_FILTER_TYPE (CPU_CMD_MASK_CAPTURE | 0x000C)
++
++/* Description: This command set coring levels for median filter
++ IN[0] - Task handle.
++ IN[1] - luma_high
++ IN[2] - luma_low
++ IN[3] - chroma_high
++ IN[4] - chroma_low
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_MEDIAN_CORING (CPU_CMD_MASK_CAPTURE | 0x000E)
++
++/* Description: This command set the picture type mask for index file
++ IN[0] - 0 = disable index file output
++ 1 = output I picture
++ 2 = P picture
++ 4 = B picture
++ other = illegal */
++#define CX18_CPU_SET_INDEXTABLE (CPU_CMD_MASK_CAPTURE | 0x0010)
++
++/* Description: Set audio parameters
++ IN[0] - task handle. Handle of the task to start
++ IN[1] - audio parameter
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_AUDIO_PARAMETERS (CPU_CMD_MASK_CAPTURE | 0x0011)
++
++/* Description: Set video mute
++ IN[0] - task handle. Handle of the task to start
++ IN[1] - bit31-24: muteYvalue
++ bit23-16: muteUvalue
++ bit15-8: muteVvalue
++ bit0: 1:mute, 0: unmute
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_VIDEO_MUTE (CPU_CMD_MASK_CAPTURE | 0x0013)
++
++/* Description: Set audio mute
++ IN[0] - task handle. Handle of the task to start
++ IN[1] - mute/unmute
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_AUDIO_MUTE (CPU_CMD_MASK_CAPTURE | 0x0014)
++
++/* Description: Set stream output type
++ IN[0] - task handle. Handle of the task to start
++ IN[1] - subType
++ SET_INITIAL_SCR 1
++ SET_QUALITY_MODE 2
++ SET_VIM_PROTECT_MODE 3
++ SET_PTS_CORRECTION 4
++ SET_USB_FLUSH_MODE 5
++ SET_MERAQPAR_ENABLE 6
++ SET_NAV_PACK_INSERTION 7
++ SET_SCENE_CHANGE_ENABLE 8
++ IN[2] - parameter 1
++ IN[3] - parameter 2
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_MISC_PARAMETERS (CPU_CMD_MASK_CAPTURE | 0x0015)
++
++/* Description: Set raw VBI parameters
++ IN[0] - Task handle
++ IN[1] - No. of input lines per field:
++ bit[15:0]: field 1,
++ bit[31:16]: field 2
++ IN[2] - No. of input bytes per line
++ IN[3] - No. of output frames per transfer
++ IN[4] - start code
++ IN[5] - stop code
++ ReturnCode */
++#define CX18_CPU_SET_RAW_VBI_PARAM (CPU_CMD_MASK_CAPTURE | 0x0016)
++
++/* Description: Set capture line No.
++ IN[0] - task handle. Handle of the task to start
++ IN[1] - height1
++ IN[2] - height2
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_CAPTURE_LINE_NO (CPU_CMD_MASK_CAPTURE | 0x0017)
++
++/* Description: Set copyright
++ IN[0] - task handle. Handle of the task to start
++ IN[1] - copyright
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_COPYRIGHT (CPU_CMD_MASK_CAPTURE | 0x0018)
++
++/* Description: Set audio PID
++ IN[0] - task handle. Handle of the task to start
++ IN[1] - PID
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_AUDIO_PID (CPU_CMD_MASK_CAPTURE | 0x0019)
++
++/* Description: Set video PID
++ IN[0] - task handle. Handle of the task to start
++ IN[1] - PID
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_VIDEO_PID (CPU_CMD_MASK_CAPTURE | 0x001A)
++
++/* Description: Set Vertical Crop Line
++ IN[0] - task handle. Handle of the task to start
++ IN[1] - Line
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_VER_CROP_LINE (CPU_CMD_MASK_CAPTURE | 0x001B)
++
++/* Description: Set COP structure
++ IN[0] - task handle. Handle of the task to start
++ IN[1] - M
++ IN[2] - N
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_GOP_STRUCTURE (CPU_CMD_MASK_CAPTURE | 0x001C)
++
++/* Description: Set Scene Change Detection
++ IN[0] - task handle. Handle of the task to start
++ IN[1] - scene change
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_SCENE_CHANGE_DETECTION (CPU_CMD_MASK_CAPTURE | 0x001D)
++
++/* Description: Set Aspect Ratio
++ IN[0] - task handle. Handle of the task to start
++ IN[1] - AspectRatio
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_ASPECT_RATIO (CPU_CMD_MASK_CAPTURE | 0x001E)
++
++/* Description: Set Skip Input Frame
++ IN[0] - task handle. Handle of the task to start
++ IN[1] - skip input frames
++ ReturnCode - One of the ERR_CAPTURE_... */
++#define CX18_CPU_SET_SKIP_INPUT_FRAME (CPU_CMD_MASK_CAPTURE | 0x001F)
++
++/* Description: Set sliced VBI parameters -
++ Note This API will only apply to MPEG and Sliced VBI Channels
++ IN[0] - Task handle
++ IN[1] - output type, 0 - CC, 1 - Moji, 2 - Teletext
++ IN[2] - start / stop line
++ bit[15:0] start line number
++ bit[31:16] stop line number
++ IN[3] - number of output frames per interrupt
++ IN[4] - VBI insertion mode
++ bit 0: output user data, 1 - enable
++ bit 1: output private stream, 1 - enable
++ bit 2: mux option, 0 - in GOP, 1 - in picture
++ bit[7:0] private stream ID
++ IN[5] - insertion period while mux option is in picture
++ ReturnCode - VBI data offset */
++#define CX18_CPU_SET_SLICED_VBI_PARAM (CPU_CMD_MASK_CAPTURE | 0x0020)
++
++/* Description: Set the user data place holder
++ IN[0] - type of data (0 for user)
++ IN[1] - Stuffing period
++ IN[2] - ID data size in word (less than 10)
++ IN[3] - Pointer to ID buffer */
++#define CX18_CPU_SET_USERDATA_PLACE_HOLDER (CPU_CMD_MASK_CAPTURE | 0x0021)
++
++
++/* Description:
++ In[0] Task Handle
++ return parameter:
++ Out[0] Reserved
++ Out[1] Video PTS bit[32:2] of last output video frame.
++ Out[2] Video PTS bit[ 1:0] of last output video frame.
++ Out[3] Hardware Video PTS counter bit[31:0],
++ these bits get incremented on every 90kHz clock tick.
++ Out[4] Hardware Video PTS counter bit32,
++ these bits get incremented on every 90kHz clock tick.
++ ReturnCode */
++#define CX18_CPU_GET_ENC_PTS (CPU_CMD_MASK_CAPTURE | 0x0022)
++
++/* Below is the list of commands related to the data exchange */
++#define CPU_CMD_MASK_DE (CPU_CMD_MASK | 0x040000)
++
++/* Description: This command provides the physical base address of the local
++ DDR as viewed by EPU
++ IN[0] - Physical offset where EPU has the local DDR mapped
++ ReturnCode - One of the ERR_DE_... */
++#define CPU_CMD_DE_SetBase (CPU_CMD_MASK_DE | 0x0001)
++
++/* Description: This command provides the offsets in the device memory where
++ the 2 cx18_mdl_ack blocks reside
++ IN[0] - Task handle. Handle of the task to start
++ IN[1] - Offset of the first cx18_mdl_ack from the beginning of the
++ local DDR.
++ IN[2] - Offset of the second cx18_mdl_ack from the beginning of the
++ local DDR.
++ ReturnCode - One of the ERR_DE_... */
++#define CX18_CPU_DE_SET_MDL_ACK (CPU_CMD_MASK_DE | 0x0002)
++
++/* Description: This command provides the offset to a Memory Descriptor List
++ IN[0] - Task handle. Handle of the task to start
++ IN[1] - Offset of the MDL from the beginning of the local DDR.
++ IN[2] - Number of cx18_mdl structures in the array pointed to by IN[1]
++ IN[3] - Buffer ID
++ IN[4] - Total buffer length
++ ReturnCode - One of the ERR_DE_... */
++#define CX18_CPU_DE_SET_MDL (CPU_CMD_MASK_DE | 0x0005)
++
++/* Description: This command requests return of all current Memory
++ Descriptor Lists to the driver
++ IN[0] - Task handle. Handle of the task to start
++ ReturnCode - One of the ERR_DE_... */
++/* #define CX18_CPU_DE_ReleaseMDL (CPU_CMD_MASK_DE | 0x0006) */
++
++/* Description: This command signals the cpu that the dat buffer has been
++ consumed and ready for re-use.
++ IN[0] - Task handle. Handle of the task
++ IN[1] - Offset of the data block from the beginning of the local DDR.
++ IN[2] - Number of bytes in the data block
++ ReturnCode - One of the ERR_DE_... */
++/* #define CX18_CPU_DE_RELEASE_BUFFER (CPU_CMD_MASK_DE | 0x0007) */
++
++/* No Error / Success */
++#define CNXT_OK 0x000000
++
++/* Received unknown command */
++#define CXERR_UNK_CMD 0x000001
++
++/* First parameter in the command is invalid */
++#define CXERR_INVALID_PARAM1 0x000002
++
++/* Second parameter in the command is invalid */
++#define CXERR_INVALID_PARAM2 0x000003
++
++/* Device interface is not open/found */
++#define CXERR_DEV_NOT_FOUND 0x000004
++
++/* Requested function is not implemented/available */
++#define CXERR_NOTSUPPORTED 0x000005
++
++/* Invalid pointer is provided */
++#define CXERR_BADPTR 0x000006
++
++/* Unable to allocate memory */
++#define CXERR_NOMEM 0x000007
++
++/* Object/Link not found */
++#define CXERR_LINK 0x000008
++
++/* Device busy, command cannot be executed */
++#define CXERR_BUSY 0x000009
++
++/* File/device/handle is not open. */
++#define CXERR_NOT_OPEN 0x00000A
++
++/* Value is out of range */
++#define CXERR_OUTOFRANGE 0x00000B
++
++/* Buffer overflow */
++#define CXERR_OVERFLOW 0x00000C
++
++/* Version mismatch */
++#define CXERR_BADVER 0x00000D
++
++/* Operation timed out */
++#define CXERR_TIMEOUT 0x00000E
++
++/* Operation aborted */
++#define CXERR_ABORT 0x00000F
++
++/* Specified I2C device not found for read/write */
++#define CXERR_I2CDEV_NOTFOUND 0x000010
++
++/* Error in I2C data xfer (but I2C device is present) */
++#define CXERR_I2CDEV_XFERERR 0x000011
++
++/* Chanel changing component not ready */
++#define CXERR_CHANNELNOTREADY 0x000012
++
++/* PPU (Presensation/Decoder) mail box is corrupted */
++#define CXERR_PPU_MB_CORRUPT 0x000013
++
++/* CPU (Capture/Encoder) mail box is corrupted */
++#define CXERR_CPU_MB_CORRUPT 0x000014
++
++/* APU (Audio) mail box is corrupted */
++#define CXERR_APU_MB_CORRUPT 0x000015
++
++/* Unable to open file for reading */
++#define CXERR_FILE_OPEN_READ 0x000016
++
++/* Unable to open file for writing */
++#define CXERR_FILE_OPEN_WRITE 0x000017
++
++/* Unable to find the I2C section specified */
++#define CXERR_I2C_BADSECTION 0x000018
++
++/* Error in I2C data xfer (but I2C device is present) */
++#define CXERR_I2CDEV_DATALOW 0x000019
++
++/* Error in I2C data xfer (but I2C device is present) */
++#define CXERR_I2CDEV_CLOCKLOW 0x00001A
++
++/* No Interrupt received from HW (for I2C access) */
++#define CXERR_NO_HW_I2C_INTR 0x00001B
++
++/* RPU is not ready to accept commands! */
++#define CXERR_RPU_NOT_READY 0x00001C
++
++/* RPU is not ready to accept commands! */
++#define CXERR_RPU_NO_ACK 0x00001D
++
++/* The are no buffers ready. Try again soon! */
++#define CXERR_NODATA_AGAIN 0x00001E
+
- 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;
++/* The stream is stopping. Function not alllowed now! */
++#define CXERR_STOPPING_STATUS 0x00001F
+
- return 0;
- }
-
- static int radio_s_input(struct file *filp, void *priv, unsigned int i)
- {
-+ if (unlikely(i))
-+ return -EINVAL;
++/* Trying to access hardware when the power is turned OFF */
++#define CXERR_DEVPOWER_OFF 0x000020
+
- return 0;
- }
-
-diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c
-index fc9ecb2..a38af98 100644
---- a/drivers/media/video/bt8xx/bttv-input.c
-+++ b/drivers/media/video/bt8xx/bttv-input.c
-@@ -278,6 +278,12 @@ int bttv_input_init(struct bttv *btv)
- ir->mask_keyup = 0x004000;
- ir->polling = 50; /* ms */
- break;
-+ case BTTV_BOARD_KOZUMI_KTV_01C:
-+ ir_codes = ir_codes_pctv_sedna;
-+ ir->mask_keycode = 0x001f00;
-+ ir->mask_keyup = 0x006000;
-+ ir->polling = 50; /* ms */
-+ break;
- }
- if (NULL == ir_codes) {
- dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type);
-diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
-index 75fa82c..bfdbc46 100644
---- a/drivers/media/video/bt8xx/bttv-vbi.c
-+++ b/drivers/media/video/bt8xx/bttv-vbi.c
-@@ -54,7 +54,7 @@
- #define VBI_DEFLINES 16
-
- static unsigned int vbibufs = 4;
--static unsigned int vbi_debug = 0;
-+static unsigned int vbi_debug;
-
- module_param(vbibufs, int, 0444);
- module_param(vbi_debug, int, 0644);
-diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h
-index bf4c339..f239320 100644
---- a/drivers/media/video/bt8xx/bttv.h
-+++ b/drivers/media/video/bt8xx/bttv.h
-@@ -19,6 +19,7 @@
- #include <media/ir-common.h>
- #include <media/ir-kbd-i2c.h>
- #include <media/i2c-addr.h>
-+#include <media/tuner.h>
-
- /* ---------------------------------------------------------- */
- /* exported by bttv-cards.c */
-@@ -173,6 +174,8 @@
- #define BTTV_BOARD_VOODOOTV_200 0x93
- #define BTTV_BOARD_DVICO_FUSIONHDTV_2 0x94
- #define BTTV_BOARD_TYPHOON_TVTUNERPCI 0x95
-+#define BTTV_BOARD_GEOVISION_GV600 0x96
-+#define BTTV_BOARD_KOZUMI_KTV_01C 0x97
-
-
- /* more card-specific defines */
-diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h
-index 1305d31..03816b7 100644
---- a/drivers/media/video/bt8xx/bttvp.h
-+++ b/drivers/media/video/bt8xx/bttvp.h
-@@ -42,7 +42,6 @@
-
- #include <linux/device.h>
- #include <media/videobuf-dma-sg.h>
--#include <media/tuner.h>
- #include <media/tveeprom.h>
- #include <media/ir-common.h>
-
-diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
-index 0322653..b364ada 100644
---- a/drivers/media/video/bw-qcam.c
-+++ b/drivers/media/video/bw-qcam.c
-@@ -523,7 +523,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
- int ret=1;
- unsigned int hi, lo;
- unsigned int hi2, lo2;
-- static int state = 0;
-+ static int state;
-
- if (buffer == NULL)
- {
-@@ -898,7 +898,9 @@ static const struct file_operations qcam_fops = {
- .open = video_exclusive_open,
- .release = video_exclusive_release,
- .ioctl = qcam_ioctl,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .read = qcam_read,
- .llseek = no_llseek,
- };
-@@ -912,7 +914,7 @@ static struct video_device qcam_template=
-
- #define MAX_CAMS 4
- static struct qcam_device *qcams[MAX_CAMS];
--static unsigned int num_cams = 0;
-+static unsigned int num_cams;
-
- static int init_bwqcam(struct parport *port)
- {
-diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
-index cf1546b..fe1e67b 100644
---- a/drivers/media/video/c-qcam.c
-+++ b/drivers/media/video/c-qcam.c
-@@ -36,6 +36,7 @@
- #include <linux/videodev.h>
- #include <media/v4l2-common.h>
- #include <linux/mutex.h>
-+#include <linux/jiffies.h>
-
- #include <asm/uaccess.h>
-
-@@ -69,7 +70,7 @@ struct qcam_device {
-
- static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
- static int probe = 2;
--static int force_rgb = 0;
-+static int force_rgb;
- static int video_nr = -1;
-
- static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i)
-@@ -95,7 +96,8 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam,
- unsigned long oldjiffies = jiffies;
- unsigned int i;
-
-- for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); )
-+ for (oldjiffies = jiffies;
-+ time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); )
- if (qcam_ready1(qcam) == value)
- return 0;
-
-@@ -120,7 +122,8 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
- unsigned long oldjiffies = jiffies;
- unsigned int i;
-
-- for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); )
-+ for (oldjiffies = jiffies;
-+ time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); )
- if (qcam_ready2(qcam) == value)
- return 0;
-
-@@ -689,7 +692,9 @@ static const struct file_operations qcam_fops = {
- .open = video_exclusive_open,
- .release = video_exclusive_release,
- .ioctl = qcam_ioctl,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .read = qcam_read,
- .llseek = no_llseek,
- };
-@@ -741,7 +746,7 @@ static struct qcam_device *qcam_init(struct parport *port)
- }
-
- static struct qcam_device *qcams[MAX_CAMS];
--static unsigned int num_cams = 0;
-+static unsigned int num_cams;
-
- static int init_cqcam(struct parport *port)
- {
-diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
-index 7ae499c..5195b1f 100644
---- a/drivers/media/video/cafe_ccic.c
-+++ b/drivers/media/video/cafe_ccic.c
-@@ -65,7 +65,7 @@ MODULE_SUPPORTED_DEVICE("Video");
- */
-
- #define MAX_DMA_BUFS 3
--static int alloc_bufs_at_read = 0;
-+static int alloc_bufs_at_read;
- module_param(alloc_bufs_at_read, bool, 0444);
- MODULE_PARM_DESC(alloc_bufs_at_read,
- "Non-zero value causes DMA buffers to be allocated when the "
-@@ -99,7 +99,7 @@ MODULE_PARM_DESC(max_buffers,
- "will be allowed to allocate. These buffers are big and live "
- "in vmalloc space.");
-
--static int flip = 0;
-+static int flip;
- module_param(flip, bool, 0444);
- MODULE_PARM_DESC(flip,
- "If set, the sensor will be instructed to flip the image "
-diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
-index 7c630f5..2a81376 100644
---- a/drivers/media/video/cpia.c
-+++ b/drivers/media/video/cpia.c
-@@ -3792,7 +3792,9 @@ static const struct file_operations cpia_fops = {
- .read = cpia_read,
- .mmap = cpia_mmap,
- .ioctl = cpia_ioctl,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .llseek = no_llseek,
- };
-
-diff --git a/drivers/media/video/cpia.h b/drivers/media/video/cpia.h
-index 78392fb..5096058 100644
---- a/drivers/media/video/cpia.h
-+++ b/drivers/media/video/cpia.h
-@@ -412,11 +412,11 @@ void cpia_unregister_camera(struct cam_data *cam);
- /* ErrorCode */
- #define ERROR_FLICKER_BELOW_MIN_EXP 0x01 /*flicker exposure got below minimum exposure */
- #define ALOG(fmt,args...) printk(fmt, ##args)
--#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __FUNCTION__ , __LINE__ , ##args)
-+#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __func__ , __LINE__ , ##args)
-
- #ifdef _CPIA_DEBUG_
- #define ADBG(fmt,args...) printk(fmt, jiffies, ##args)
--#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __FUNCTION__, __LINE__ , ##args)
-+#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __func__, __LINE__ , ##args)
- #else
- #define DBG(fmn,args...) do {} while(0)
- #endif
-diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c
-index a76bd78..c8b9fdb 100644
---- a/drivers/media/video/cpia2/cpia2_core.c
-+++ b/drivers/media/video/cpia2/cpia2_core.c
-@@ -34,7 +34,7 @@
- #include <linux/slab.h>
- #include <linux/vmalloc.h>
-
--//#define _CPIA2_DEBUG_
-+/* #define _CPIA2_DEBUG_ */
-
- #include "cpia2patch.h"
-
-@@ -48,7 +48,7 @@ static const char *block_name[] = {
- };
- #endif
-
--static unsigned int debugs_on = 0;//DEBUG_REG;
-+static unsigned int debugs_on; /* default 0 - DEBUG_REG */
-
-
- /******************************************************************************
-@@ -570,7 +570,7 @@ int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd)
- block_name[block_index]);
- break;
- default:
-- LOG("%s: invalid request mode\n",__FUNCTION__);
-+ LOG("%s: invalid request mode\n",__func__);
- return -EINVAL;
- }
-
-@@ -952,7 +952,7 @@ static int set_default_user_mode(struct camera_data *cam)
- frame_rate = CPIA2_VP_FRAMERATE_30;
- break;
- default:
-- LOG("%s: Invalid sensor flag value 0x%0X\n",__FUNCTION__,
-+ LOG("%s: Invalid sensor flag value 0x%0X\n",__func__,
- cam->params.version.sensor_flags);
- return -EINVAL;
- }
-@@ -2356,12 +2356,12 @@ long cpia2_read(struct camera_data *cam,
- }
-
- if (!buf) {
-- ERR("%s: buffer NULL\n",__FUNCTION__);
-+ ERR("%s: buffer NULL\n",__func__);
- return -EINVAL;
- }
-
- if (!cam) {
-- ERR("%s: Internal error, camera_data NULL!\n",__FUNCTION__);
-+ ERR("%s: Internal error, camera_data NULL!\n",__func__);
- return -EINVAL;
- }
-
-@@ -2370,7 +2370,7 @@ long cpia2_read(struct camera_data *cam,
- return -ERESTARTSYS;
-
- if (!cam->present) {
-- LOG("%s: camera removed\n",__FUNCTION__);
-+ LOG("%s: camera removed\n",__func__);
- mutex_unlock(&cam->busy_lock);
- return 0; /* EOF */
- }
-@@ -2434,7 +2434,7 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp,
- unsigned int status=0;
-
- if(!cam) {
-- ERR("%s: Internal error, camera_data not found!\n",__FUNCTION__);
-+ ERR("%s: Internal error, camera_data not found!\n",__func__);
- return POLLERR;
- }
-
-diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c
-index d8e9298..a457474 100644
---- a/drivers/media/video/cpia2/cpia2_usb.c
-+++ b/drivers/media/video/cpia2/cpia2_usb.c
-@@ -84,7 +84,7 @@ static struct usb_driver cpia2_driver = {
- *****************************************************************************/
- static void process_frame(struct camera_data *cam)
- {
-- static int frame_count = 0;
-+ static int frame_count;
-
- unsigned char *inbuff = cam->workbuff->data;
-
-diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
-index e378abe..7ce2789 100644
---- a/drivers/media/video/cpia2/cpia2_v4l.c
-+++ b/drivers/media/video/cpia2/cpia2_v4l.c
-@@ -1927,7 +1927,9 @@ static const struct file_operations fops_template = {
- .poll = cpia2_v4l_poll,
- .ioctl = cpia2_ioctl,
- .llseek = no_llseek,
-+#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-+#endif
- .mmap = cpia2_mmap,
- };
-
-diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
-index 9da4726..ef1f893 100644
---- a/drivers/media/video/cpia_usb.c
-+++ b/drivers/media/video/cpia_usb.c
-@@ -170,7 +170,7 @@ static void cpia_usb_complete(struct urb *urb)
- /* resubmit */
- urb->dev = ucpia->dev;
- if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0)
-- printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __FUNCTION__, i);
-+ printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __func__, i);
- }
-
- static int cpia_usb_open(void *privdata)
++#endif /* CX23418_H */
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig
-index 1fd326f..ca5fbce 100644
+index 1fd326f..cadf936 100644
--- a/drivers/media/video/cx23885/Kconfig
+++ b/drivers/media/video/cx23885/Kconfig
-@@ -8,6 +8,7 @@ config VIDEO_CX23885
+@@ -4,18 +4,20 @@ config VIDEO_CX23885
+ select I2C_ALGOBIT
+ select FW_LOADER
+ select VIDEO_BTCX
+- select VIDEO_TUNER
++ select MEDIA_TUNER
select VIDEO_TVEEPROM
select VIDEO_IR
select VIDEOBUF_DVB
+- select DVB_TUNER_MT2131 if !DVB_FE_CUSTOMISE
+ select VIDEO_CX25840
- select DVB_TUNER_MT2131 if !DVB_FE_CUSTOMISE
++ select MEDIA_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_PLL if !DVB_FE_CUSTOMISE
+- select TUNER_XC2028 if !DVB_FE_CUSTOMIZE
+- select TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
+- select DVB_TDA18271 if !DVB_FE_CUSTOMIZE
+- select DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
++ select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE
++ select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
++ select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE
++ select MEDIA_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
+index 32c90be..29c23b4 100644
--- a/drivers/media/video/cx23885/Makefile
+++ b/drivers/media/video/cx23885/Makefile
-@@ -1,4 +1,4 @@
+@@ -1,8 +1,9 @@
-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
+ EXTRA_CFLAGS += -Idrivers/media/video
++EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+ EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+
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
@@ -395039,7 +559781,7 @@
/* ----------------------------------------------------------- */
/* tv norms */
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
-index 756a1ee..7fde678 100644
+index 756a1ee..8882381 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)
@@ -395183,7 +559925,17 @@
case AUDC_SET_RADIO:
state->radio = 1;
-@@ -1291,6 +1268,12 @@ static int cx25840_probe(struct i2c_client *client)
+@@ -1232,7 +1209,8 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
+
+ /* ----------------------------------------------------------------------- */
+
+-static int cx25840_probe(struct i2c_client *client)
++static int cx25840_probe(struct i2c_client *client,
++ const struct i2c_device_id *did)
+ {
+ struct cx25840_state *state;
+ u32 id;
+@@ -1291,6 +1269,12 @@ static int cx25840_probe(struct i2c_client *client)
state->id = id;
state->rev = device_id;
@@ -395285,18 +560037,38 @@
int i, x;
u8 lcr[24];
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
-index 49d3813..27635cd 100644
+index 49d3813..b0d7d6a 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
+@@ -5,7 +5,7 @@ config VIDEO_CX88
+ select FW_LOADER
+ select VIDEO_BTCX
+ select VIDEOBUF_DMA_SG
+- select VIDEO_TUNER
++ select MEDIA_TUNER
+ select VIDEO_TVEEPROM
+ select VIDEO_IR
+ select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO
@@ -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 MEDIA_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/Makefile b/drivers/media/video/cx88/Makefile
+index 532cee3..6ec30f2 100644
+--- a/drivers/media/video/cx88/Makefile
++++ b/drivers/media/video/cx88/Makefile
+@@ -10,5 +10,6 @@ obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
+ obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
+
+ EXTRA_CFLAGS += -Idrivers/media/video
++EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+ EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
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
@@ -395451,10 +560223,10 @@
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
+index 8c9a8ad..aeba26d 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;
+@@ -44,9 +44,22 @@ static unsigned int latency = UNSET;
module_param(latency,int,0444);
MODULE_PARM_DESC(latency,"pci latency timer");
@@ -395471,7 +560243,13 @@
/* ------------------------------------------------------------------ */
/* board config info */
-@@ -1354,6 +1364,10 @@ static const struct cx88_board cx88_boards[] = {
++/* If radio_type !=UNSET, radio_addr should be specified
++ */
++
+ static const struct cx88_board cx88_boards[] = {
+ [CX88_BOARD_UNKNOWN] = {
+ .name = "UNKNOWN/GENERIC",
+@@ -1354,6 +1367,10 @@ static const struct cx88_board cx88_boards[] = {
}},
/* fixme: Add radio support */
.mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
@@ -395482,7 +560260,7 @@
},
[CX88_BOARD_ADSTECH_PTV_390] = {
.name = "ADS Tech Instant Video PCI",
-@@ -1401,6 +1415,246 @@ static const struct cx88_board cx88_boards[] = {
+@@ -1401,6 +1418,246 @@ static const struct cx88_board cx88_boards[] = {
}},
.mpeg = CX88_MPEG_DVB,
},
@@ -395729,7 +560507,7 @@
};
/* ------------------------------------------------------------------ */
-@@ -1605,7 +1859,11 @@ static const struct cx88_subid cx88_subids[] = {
+@@ -1605,7 +1862,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 */
@@ -395742,7 +560520,7 @@
.subvendor = 0x17de,
.subdevice = 0x0840,
.card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
-@@ -1714,6 +1972,38 @@ static const struct cx88_subid cx88_subids[] = {
+@@ -1714,6 +1975,38 @@ static const struct cx88_subid cx88_subids[] = {
.subvendor = 0x11bd,
.subdevice = 0x0051,
.card = CX88_BOARD_PINNACLE_PCTV_HD_800i,
@@ -395781,7 +560559,7 @@
},
};
-@@ -1731,17 +2021,16 @@ static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
+@@ -1731,17 +2024,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) {
@@ -395803,7 +560581,7 @@
}
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)
+@@ -1785,13 +2077,12 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
/* known */
break;
default:
@@ -395820,7 +560598,7 @@
}
/* ----------------------------------------------------------------------- */
-@@ -1837,8 +2125,7 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
+@@ -1837,8 +2128,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;
@@ -395830,7 +560608,7 @@
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)
+@@ -1846,6 +2136,75 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
CX88_RADIO : 0;
}
@@ -395906,7 +560684,7 @@
/* ----------------------------------------------------------------------- */
/* some DViCO specific stuff */
-@@ -1874,32 +2230,85 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
+@@ -1874,32 +2233,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) {
@@ -396000,7 +560778,7 @@
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)
+@@ -1908,6 +2320,36 @@ int cx88_tuner_callback(void *priv, int command, int arg)
}
return 0; /* Should never be here */
}
@@ -396037,7 +560815,7 @@
EXPORT_SYMBOL(cx88_tuner_callback);
/* ----------------------------------------------------------------------- */
-@@ -1918,23 +2357,25 @@ static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
+@@ -1918,23 +2360,25 @@ static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
if (0 == pci->subsystem_vendor &&
0 == pci->subsystem_device) {
@@ -396068,7 +560846,7 @@
core->name, i, cx88_boards[i].name);
}
-@@ -1951,9 +2392,57 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
+@@ -1951,31 +2395,85 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */
udelay(1000);
break;
@@ -396086,9 +560864,9 @@
+ /* Enable the xc5000 tuner */
+ cx_set(MO_GP0_IO, 0x00001010);
+ break;
- }
- }
-
++ }
++}
++
+/*
+ * Sets board-dependent xc3028 configuration
+ */
@@ -396119,14 +560897,53 @@
+ 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)
++ struct tuner_setup tun_setup;
++ unsigned int mode_mask = T_RADIO |
++ T_ANALOG_TV |
++ T_DIGITAL_TV;
++
++ memset(&tun_setup, 0, sizeof(tun_setup));
+
+ if (0 == core->i2c_rc) {
+ core->i2c_client.addr = 0xa0 >> 1;
+- tveeprom_read(&core->i2c_client,eeprom,sizeof(eeprom));
++ tveeprom_read(&core->i2c_client, eeprom, sizeof(eeprom));
+ }
+
+ switch (core->boardnr) {
+ case CX88_BOARD_HAUPPAUGE:
+ case CX88_BOARD_HAUPPAUGE_ROSLYN:
+ if (0 == core->i2c_rc)
+- hauppauge_eeprom(core,eeprom+8);
++ hauppauge_eeprom(core, eeprom+8);
+ break;
+ case CX88_BOARD_GDI:
+ if (0 == core->i2c_rc)
+- gdi_eeprom(core,eeprom);
++ gdi_eeprom(core, eeprom);
+ break;
+ case CX88_BOARD_WINFAST2000XP_EXPERT:
+ if (0 == core->i2c_rc)
+- leadtek_eeprom(core,eeprom);
++ leadtek_eeprom(core, eeprom);
+ break;
+ case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+ case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+@@ -1985,12 +2483,19 @@ static void cx88_card_setup(struct cx88_core *core)
+ case CX88_BOARD_HAUPPAUGE_HVR3000:
+ case CX88_BOARD_HAUPPAUGE_HVR1300:
+ if (0 == core->i2c_rc)
+- hauppauge_eeprom(core,eeprom);
++ hauppauge_eeprom(core, eeprom);
+ break;
+ case CX88_BOARD_KWORLD_DVBS_100:
cx_write(MO_GP0_IO, 0x000007f8);
cx_write(MO_GP1_IO, 0x00000001);
break;
@@ -396140,7 +560957,7 @@
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)
+@@ -2038,10 +2543,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))
@@ -396153,11 +560970,41 @@
}
break;
case CX88_BOARD_MSI_TVANYWHERE_MASTER:
-@@ -2062,6 +2556,22 @@ static void cx88_card_setup(struct cx88_core *core)
+@@ -2061,7 +2564,53 @@ static void cx88_card_setup(struct cx88_core *core)
+
cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg);
}
++ } /*end switch() */
++
++
++ /* Setup tuners */
++ if ((core->board.radio_type != UNSET)) {
++ tun_setup.mode_mask = T_RADIO;
++ tun_setup.type = core->board.radio_type;
++ tun_setup.addr = core->board.radio_addr;
++ tun_setup.tuner_callback = cx88_tuner_callback;
++ cx88_call_i2c_clients(core, TUNER_SET_TYPE_ADDR, &tun_setup);
++ mode_mask &= ~T_RADIO;
}
+
++ if (core->board.tuner_type != TUNER_ABSENT) {
++ tun_setup.mode_mask = mode_mask;
++ tun_setup.type = core->board.tuner_type;
++ tun_setup.addr = core->board.tuner_addr;
++ tun_setup.tuner_callback = cx88_tuner_callback;
++
++ cx88_call_i2c_clients(core, TUNER_SET_TYPE_ADDR, &tun_setup);
++ }
++
++ if (core->board.tda9887_conf) {
++ struct v4l2_priv_tun_config tda9887_cfg;
++
++ tda9887_cfg.tuner = TUNER_TDA9887;
++ tda9887_cfg.priv = &core->board.tda9887_conf;
++
++ cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tda9887_cfg);
++ }
++
+ if (core->board.tuner_type == TUNER_XC2028) {
+ struct v4l2_priv_tun_config xc2028_cfg;
+ struct xc2028_ctrl ctl;
@@ -396173,10 +561020,11 @@
+ ctl.fname);
+ cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg);
+ }
++ cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);
}
/* ------------------------------------------------------------------ */
-@@ -2178,9 +2688,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
+@@ -2178,9 +2727,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board));
@@ -396188,7 +561036,7 @@
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)
+@@ -2189,8 +2737,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];
@@ -396199,7 +561047,13 @@
/* init hardware */
cx88_reset(core);
-@@ -2207,12 +2716,3 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
+@@ -2201,18 +2749,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
+ if (TUNER_ABSENT != core->board.tuner_type)
+ request_module("tuner");
+
+- cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);
+ cx88_card_setup(core);
+ cx88_ir_init(core, pci);
return core;
}
@@ -396738,7 +561592,7 @@
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
+index 566b26a..cb6a096 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -35,11 +35,11 @@
@@ -396755,6 +561609,49 @@
module_param(i2c_scan, int, 0444);
MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
+@@ -99,42 +99,11 @@ static int cx8800_bit_getsda(void *data)
+
+ static int attach_inform(struct i2c_client *client)
+ {
+- struct tuner_setup tun_setup;
+ struct cx88_core *core = i2c_get_adapdata(client->adapter);
+
+ 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;
+-
+- if (core->board.radio_type != UNSET) {
+- if ((core->board.radio_addr==ADDR_UNSET)||(core->board.radio_addr==client->addr)) {
+- tun_setup.mode_mask = T_RADIO;
+- tun_setup.type = core->board.radio_type;
+- tun_setup.addr = core->board.radio_addr;
+- tun_setup.tuner_callback = cx88_tuner_callback;
+- client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup);
+- }
+- }
+- if (core->board.tuner_type != UNSET) {
+- if ((core->board.tuner_addr==ADDR_UNSET)||(core->board.tuner_addr==client->addr)) {
+-
+- tun_setup.mode_mask = T_ANALOG_TV;
+- tun_setup.type = core->board.tuner_type;
+- tun_setup.addr = core->board.tuner_addr;
+- tun_setup.tuner_callback = cx88_tuner_callback;
+- client->driver->command (client,TUNER_SET_TYPE_ADDR, &tun_setup);
+- }
+- }
+-
+- if (core->board.tda9887_conf) {
+- struct v4l2_priv_tun_config tda9887_cfg;
+
+- tda9887_cfg.tuner = TUNER_TDA9887;
+- tda9887_cfg.priv = &core->board.tda9887_conf;
+-
+- client->driver->command(client, TUNER_SET_CONFIG, &tda9887_cfg);
+- }
+ return 0;
+ }
+
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
@@ -397206,23 +562103,6 @@
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
@@ -397277,7 +562157,7 @@
#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
+index 0f7a0bd..c7c2896 100644
--- a/drivers/media/video/em28xx/Kconfig
+++ b/drivers/media/video/em28xx/Kconfig
@@ -1,11 +1,13 @@
@@ -397285,7 +562165,8 @@
- 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_TUNER
++ select MEDIA_TUNER
select VIDEO_TVEEPROM
select VIDEO_IR
+ select VIDEOBUF_VMALLOC
@@ -397310,17 +562191,20 @@
+ 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
+index 0924550..8137a8c 100644
--- a/drivers/media/video/em28xx/Makefile
+++ b/drivers/media/video/em28xx/Makefile
-@@ -5,6 +5,7 @@ em28xx-alsa-objs := em28xx-audio.o
+@@ -5,8 +5,10 @@ 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/common/tuners
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+ EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+
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
@@ -401770,10 +566654,17 @@
}
}
diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig
-index 270906f..b617170 100644
+index 270906f..eec115b 100644
--- a/drivers/media/video/ivtv/Kconfig
+++ b/drivers/media/video/ivtv/Kconfig
-@@ -10,6 +10,7 @@ config VIDEO_IVTV
+@@ -4,12 +4,13 @@ config VIDEO_IVTV
+ select I2C_ALGOBIT
+ select FW_LOADER
+ select VIDEO_IR
+- select VIDEO_TUNER
++ select MEDIA_TUNER
+ select VIDEO_TVEEPROM
+ select VIDEO_CX2341X
select VIDEO_CX25840
select VIDEO_MSP3400
select VIDEO_SAA711X
@@ -401781,30 +566672,326 @@
select VIDEO_SAA7127
select VIDEO_TVAUDIO
select VIDEO_CS53L32A
+diff --git a/drivers/media/video/ivtv/Makefile b/drivers/media/video/ivtv/Makefile
+index a038901..26ce0d6 100644
+--- a/drivers/media/video/ivtv/Makefile
++++ b/drivers/media/video/ivtv/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_VIDEO_IVTV) += ivtv.o
+ obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o
+
+ EXTRA_CFLAGS += -Idrivers/media/video
++EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+ EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+
diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c
-index f23c6b8..e908649 100644
+index f23c6b8..4fb8fae 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 = {
+@@ -40,6 +40,8 @@
+ #define MSP_MONO MSP_INPUT(MSP_IN_MONO, MSP_IN_TUNER1, \
+ MSP_DSP_IN_SCART, MSP_DSP_IN_SCART)
+
++#define V4L2_STD_NOT_MN (V4L2_STD_PAL|V4L2_STD_SECAM)
++
+ /* usual i2c tuner addresses to probe */
+ static struct ivtv_card_tuner_i2c ivtv_i2c_std = {
+ .radio = { I2C_CLIENT_END },
+@@ -298,7 +300,7 @@ static const struct ivtv_card ivtv_card_mpg600 = {
+ .gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 },
+ .tuners = {
+ /* The PAL tuner is confirmed */
+- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FQ1216ME },
++ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FQ1216ME },
+ { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
+ },
+ .pci_list = ivtv_pci_mpg600,
+@@ -339,7 +341,7 @@ static const struct ivtv_card ivtv_card_mpg160 = {
+ .lang1 = 0x0004, .lang2 = 0x0000, .both = 0x0008 },
+ .gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 },
+ .tuners = {
+- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FQ1216ME },
++ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FQ1216ME },
+ { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
+ },
+ .pci_list = ivtv_pci_mpg160,
+@@ -375,7 +377,7 @@ static const struct ivtv_card ivtv_card_pg600 = {
+ { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL },
+ },
+ .tuners = {
+- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FQ1216ME },
++ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FQ1216ME },
+ { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
+ },
+ .pci_list = ivtv_pci_pg600,
+@@ -416,11 +418,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 },
+- { .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_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_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,
+@@ -491,7 +492,7 @@ static const struct ivtv_card ivtv_card_tg5000tv = {
+ .gpio_video_input = { .mask = 0x0030, .tuner = 0x0000,
+ .composite = 0x0010, .svideo = 0x0020 },
+ .tuners = {
+- { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FQ1286 },
++ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
+ },
+ .pci_list = ivtv_pci_tg5000tv,
+ .i2c = &ivtv_i2c_std,
+@@ -522,7 +523,7 @@ static const struct ivtv_card ivtv_card_va2000 = {
+ { IVTV_CARD_INPUT_AUD_TUNER, MSP_TUNER },
+ },
+ .tuners = {
+- { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FQ1286 },
++ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
+ },
+ .pci_list = ivtv_pci_va2000,
+ .i2c = &ivtv_i2c_std,
+@@ -566,7 +567,7 @@ static const struct ivtv_card ivtv_card_cx23416gyc = {
+ .gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000,
+ .f44100 = 0x4000, .f48000 = 0x8000 },
+ .tuners = {
+- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
++ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+ { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+ },
+ .pci_list = ivtv_pci_cx23416gyc,
+@@ -598,7 +599,7 @@ static const struct ivtv_card ivtv_card_cx23416gyc_nogr = {
+ .gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000,
+ .f44100 = 0x4000, .f48000 = 0x8000 },
+ .tuners = {
+- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
++ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+ { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+ },
+ .i2c = &ivtv_i2c_std,
+@@ -628,7 +629,7 @@ static const struct ivtv_card ivtv_card_cx23416gyc_nogrycs = {
+ .gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000,
+ .f44100 = 0x4000, .f48000 = 0x8000 },
+ .tuners = {
+- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
++ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+ { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+ },
+ .i2c = &ivtv_i2c_std,
+@@ -668,7 +669,7 @@ static const struct ivtv_card ivtv_card_gv_mvprx = {
+ .gpio_audio_input = { .mask = 0xffff, .tuner = 0x0200, .linein = 0x0300 },
+ .tuners = {
+ /* This card has the Panasonic VP27 tuner */
+- { .std = V4L2_STD_525_60, .tuner = TUNER_PANASONIC_VP27 },
++ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 },
+ },
+ .pci_list = ivtv_pci_gv_mvprx,
+ .i2c = &ivtv_i2c_std,
+@@ -705,7 +706,7 @@ static const struct ivtv_card ivtv_card_gv_mvprx2e = {
+ .gpio_audio_input = { .mask = 0xffff, .tuner = 0x0200, .linein = 0x0300 },
+ .tuners = {
+ /* This card has the Panasonic VP27 tuner */
+- { .std = V4L2_STD_525_60, .tuner = TUNER_PANASONIC_VP27 },
++ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 },
+ },
+ .pci_list = ivtv_pci_gv_mvprx2e,
+ .i2c = &ivtv_i2c_std,
+@@ -740,7 +741,7 @@ static const struct ivtv_card ivtv_card_gotview_pci_dvd = {
+ .gpio_init = { .direction = 0xf000, .initial_value = 0xA000 },
+ .tuners = {
+ /* This card has a Philips FQ1216ME MK3 tuner */
+- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
++ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+ },
+ .pci_list = ivtv_pci_gotview_pci_dvd,
+ .i2c = &ivtv_i2c_std,
+@@ -779,7 +780,7 @@ static const struct ivtv_card ivtv_card_gotview_pci_dvd2 = {
+ .gpio_audio_input = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 },
+ .tuners = {
+ /* This card has a Philips FQ1216ME MK5 tuner */
+- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
++ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+ },
+ .pci_list = ivtv_pci_gotview_pci_dvd2,
+ .i2c = &ivtv_i2c_std,
+@@ -857,7 +858,7 @@ static const struct ivtv_card ivtv_card_dctmvtvp1 = {
+ .gpio_video_input = { .mask = 0x0030, .tuner = 0x0000,
+ .composite = 0x0010, .svideo = 0x0020},
+ .tuners = {
+- { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FQ1286 },
++ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
+ },
+ .pci_list = ivtv_pci_dctmvtvp1,
+ .i2c = &ivtv_i2c_std,
+@@ -876,6 +877,7 @@ static const struct ivtv_card_pci_info ivtv_pci_pg600v2[] = {
+ static const struct ivtv_card ivtv_card_pg600v2 = {
+ .type = IVTV_CARD_PG600V2,
+ .name = "Yuan PG600-2, GotView PCI DVD Lite",
++ .comment = "only Composite and S-Video inputs are supported, not the tuner\n",
+ .v4l2_capabilities = IVTV_CAP_ENCODER,
+ .hw_video = IVTV_HW_CX25840,
+ .hw_audio = IVTV_HW_CX25840,
+@@ -922,6 +924,7 @@ static const struct ivtv_card ivtv_card_club3d = {
+ },
+ .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
+ .gpio_init = { .direction = 0x1000, .initial_value = 0x1000 }, /* tuner reset */
++ .xceive_pin = 12,
+ .tuners = {
+ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+ },
+@@ -945,15 +948,22 @@ static const struct ivtv_card ivtv_card_avertv_mce116 = {
+ .hw_video = IVTV_HW_CX25840,
+ .hw_audio = IVTV_HW_CX25840,
+ .hw_audio_ctrl = IVTV_HW_CX25840,
+- .hw_all = IVTV_HW_CX25840 | IVTV_HW_WM8739,
++ .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739,
+ .video_inputs = {
+- { IVTV_CARD_INPUT_SVIDEO1, 0, CX25840_SVIDEO3 },
+- { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 },
++ { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 },
++ { IVTV_CARD_INPUT_SVIDEO1, 1, CX25840_SVIDEO3 },
++ { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+ },
+ .audio_inputs = {
++ { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
+ { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 },
+ },
+- .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 }, /* enable line-in */
++ /* enable line-in */
++ .gpio_init = { .direction = 0xe400, .initial_value = 0x4400 },
++ .xceive_pin = 10,
++ .tuners = {
++ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
++ },
+ .pci_list = ivtv_pci_avertv_mce116,
+ .i2c = &ivtv_i2c_std,
+ };
+@@ -991,7 +1001,7 @@ static const struct ivtv_card ivtv_card_aver_pvr150 = {
+ .gpio_audio_input = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 },
+ .tuners = {
+ /* This card has a Partsnic PTI-5NF05 tuner */
+- { .std = V4L2_STD_525_60, .tuner = TUNER_TCL_2002N },
++ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_TCL_2002N },
+ },
+ .pci_list = ivtv_pci_aver_pvr150,
+ .i2c = &ivtv_i2c_radio,
+@@ -1059,12 +1069,48 @@ static const struct ivtv_card ivtv_card_asus_falcon2 = {
+ },
+ .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, M52790_IN_TUNER },
+ .tuners = {
+- { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FM1236_MK3 },
++ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+ },
+ .pci_list = ivtv_pci_asus_falcon2,
+ .i2c = &ivtv_i2c_std,
+ };
+
++/* ------------------------------------------------------------------------- */
++
++/* AVerMedia M104 miniPCI card */
++
++static const struct ivtv_card_pci_info ivtv_pci_aver_m104[] = {
++ { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc136 },
++ { 0, 0, 0 }
++};
++
++static const struct ivtv_card ivtv_card_aver_m104 = {
++ .type = IVTV_CARD_AVER_M104,
++ .name = "AVerMedia M104",
++ .comment = "Not yet supported!\n",
++ .v4l2_capabilities = 0, /*IVTV_CAP_ENCODER,*/
++ .hw_video = IVTV_HW_CX25840,
++ .hw_audio = IVTV_HW_CX25840,
++ .hw_audio_ctrl = IVTV_HW_CX25840,
++ .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739,
++ .video_inputs = {
++ { IVTV_CARD_INPUT_SVIDEO1, 0, CX25840_SVIDEO3 },
++ { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 },
++ },
++ .audio_inputs = {
++ { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 },
++ },
++ .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 },
++ /* enable line-in + reset tuner */
++ .gpio_init = { .direction = 0xe400, .initial_value = 0x4000 },
++ .xceive_pin = 10,
++ .tuners = {
++ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
++ },
++ .pci_list = ivtv_pci_aver_m104,
++ .i2c = &ivtv_i2c_std,
++};
++
+ static const struct ivtv_card *ivtv_card_list[] = {
+ &ivtv_card_pvr250,
+ &ivtv_card_pvr350,
+@@ -1090,6 +1136,7 @@ static const struct ivtv_card *ivtv_card_list[] = {
+ &ivtv_card_asus_falcon2,
+ &ivtv_card_aver_pvr150,
+ &ivtv_card_aver_ezmaker,
++ &ivtv_card_aver_m104,
+
+ /* Variations of standard cards but with the same PCI IDs.
+ These cards must come last in this list. */
+@@ -1121,7 +1168,8 @@ int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input)
+ if (index >= itv->nof_inputs)
+ return -EINVAL;
+ input->index = index;
+- strcpy(input->name, input_strs[card_input->video_type - 1]);
++ strlcpy(input->name, input_strs[card_input->video_type - 1],
++ sizeof(input->name));
+ input->type = (card_input->video_type == IVTV_CARD_INPUT_VID_TUNER ?
+ V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA);
+ input->audioset = (1 << itv->nof_audio_inputs) - 1;
+@@ -1138,7 +1186,7 @@ int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output)
+ if (index >= itv->card->nof_outputs)
+ return -EINVAL;
+ output->index = index;
+- strcpy(output->name, card_output->name);
++ strlcpy(output->name, card_output->name, sizeof(output->name));
+ output->type = V4L2_OUTPUT_TYPE_ANALOG;
+ output->audioset = 1;
+ output->std = V4L2_STD_ALL;
+@@ -1157,7 +1205,8 @@ int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *audio)
+ memset(audio, 0, sizeof(*audio));
+ if (index >= itv->nof_audio_inputs)
+ return -EINVAL;
+- strcpy(audio->name, input_strs[aud_input->audio_type - 1]);
++ strlcpy(audio->name, input_strs[aud_input->audio_type - 1],
++ sizeof(audio->name));
+ audio->index = index;
+ audio->capability = V4L2_AUDCAP_STEREO;
+ return 0;
+@@ -1168,6 +1217,6 @@ int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *aud
+ memset(aud_output, 0, sizeof(*aud_output));
+ if (itv->card->video_outputs == NULL || index != 0)
+ return -EINVAL;
+- strcpy(aud_output->name, "A/V Audio Out");
++ strlcpy(aud_output->name, "A/V Audio Out", sizeof(aud_output->name));
+ return 0;
+ }
diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h
-index 191aafd..9186fa2 100644
+index 191aafd..748485d 100644
--- a/drivers/media/video/ivtv/ivtv-cards.h
+++ b/drivers/media/video/ivtv/ivtv-cards.h
-@@ -119,7 +119,7 @@
+@@ -48,7 +48,8 @@
+ #define IVTV_CARD_ASUS_FALCON2 21 /* ASUS Falcon2 */
+ #define IVTV_CARD_AVER_PVR150PLUS 22 /* AVerMedia PVR-150 Plus */
+ #define IVTV_CARD_AVER_EZMAKER 23 /* AVerMedia EZMaker PCI Deluxe */
+-#define IVTV_CARD_LAST 23
++#define IVTV_CARD_AVER_M104 24 /* AverMedia M104 miniPCI card */
++#define IVTV_CARD_LAST 24
+
+ /* Variants of existing cards but with the same PCI IDs. The driver
+ detects these based on other device information.
+@@ -119,7 +120,7 @@
#define IVTV_CARD_MAX_VIDEO_INPUTS 6
#define IVTV_CARD_MAX_AUDIO_INPUTS 3
@@ -401813,8 +567000,24 @@
/* SAA71XX HW inputs */
#define IVTV_SAA71XX_COMPOSITE0 0
+@@ -244,6 +245,7 @@ struct ivtv_card_tuner_i2c {
+ struct ivtv_card {
+ int type;
+ char *name;
++ char *comment;
+ u32 v4l2_capabilities;
+ u32 hw_video; /* hardware used to process video */
+ u32 hw_audio; /* hardware used to process audio */
+@@ -256,6 +258,7 @@ struct ivtv_card {
+ int nof_outputs;
+ const struct ivtv_card_output *video_outputs;
+ u8 gr_config; /* config byte for the ghost reduction device */
++ u8 xceive_pin; /* XCeive tuner GPIO reset pin */
+
+ /* GPIO card-specific settings */
+ struct ivtv_gpio_init gpio_init;
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
-index 948ca35..065df53 100644
+index 948ca35..ed020f7 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,
@@ -401851,8 +567054,11 @@
module_param(newi2c, int, 0644);
MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
-@@ -190,9 +192,14 @@ MODULE_PARM_DESC(cardtype,
+@@ -188,11 +190,17 @@ MODULE_PARM_DESC(cardtype,
+ "\t\t\t22 = ASUS Falcon2\n"
+ "\t\t\t23 = AverMedia PVR-150 Plus\n"
"\t\t\t24 = AverMedia EZMaker PCI Deluxe\n"
++ "\t\t\t25 = AverMedia M104 (not yet working)\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");
@@ -401869,7 +567075,7 @@
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)
+@@ -490,30 +498,35 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv)
{
switch (pal[0]) {
case '6':
@@ -401907,7 +567113,7 @@
return V4L2_STD_PAL_M;
case '-':
break;
-@@ -529,14 +541,17 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv)
+@@ -529,14 +542,17 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv)
case 'G':
case 'h':
case 'H':
@@ -401925,7 +567131,7 @@
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)
+@@ -550,12 +566,15 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv)
switch (ntsc[0]) {
case 'm':
case 'M':
@@ -401941,7 +567147,7 @@
return V4L2_STD_NTSC_M_KR;
case '-':
break;
-@@ -584,8 +602,13 @@ static void ivtv_process_options(struct ivtv *itv)
+@@ -584,8 +603,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;
@@ -401956,7 +567162,7 @@
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)
+@@ -711,6 +735,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;
@@ -401964,7 +567170,16 @@
return 0;
}
-@@ -859,7 +883,9 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
+@@ -847,7 +872,7 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
+ unsigned i;
+
+ /* load modules */
+-#ifndef CONFIG_VIDEO_TUNER
++#ifndef CONFIG_MEDIA_TUNER
+ hw = ivtv_request_module(itv, hw, "tuner", IVTV_HW_TUNER);
+ #endif
+ #ifndef CONFIG_VIDEO_CX25840
+@@ -859,7 +884,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
@@ -401974,6 +567189,110 @@
#ifndef CONFIG_VIDEO_UPD64031A
hw = ivtv_request_module(itv, hw, "upd64031a", IVTV_HW_UPD64031A);
#endif
+@@ -1022,7 +1049,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
+ IVTV_ENCODER_SIZE);
+ if (!itv->enc_mem) {
+ IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n");
+- IVTV_ERR("or disabling CONFIG_HIMEM4G into the kernel would help\n");
++ IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n");
+ retval = -ENOMEM;
+ goto free_mem;
+ }
+@@ -1034,7 +1061,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
+ IVTV_DECODER_SIZE);
+ if (!itv->dec_mem) {
+ IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n");
+- IVTV_ERR("or disabling CONFIG_HIMEM4G into the kernel would help\n");
++ IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n");
+ retval = -ENOMEM;
+ goto free_mem;
+ }
+@@ -1050,7 +1077,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
+ ioremap_nocache(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
+ if (!itv->reg_mem) {
+ IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n");
+- IVTV_ERR("or disabling CONFIG_HIMEM4G into the kernel would help\n");
++ IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n");
+ retval = -ENOMEM;
+ goto free_io;
+ }
+@@ -1071,6 +1098,13 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
+ The PCI IDs are not always reliable. */
+ ivtv_process_eeprom(itv);
+ }
++ if (itv->card->comment)
++ IVTV_INFO("%s", itv->card->comment);
++ if (itv->card->v4l2_capabilities == 0) {
++ /* card was detected but is not supported */
++ retval = -ENODEV;
++ goto free_i2c;
++ }
+
+ if (itv->std == 0) {
+ itv->std = V4L2_STD_NTSC_M;
+@@ -1169,13 +1203,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
+ ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std);
+ }
+
+- retval = ivtv_streams_setup(itv);
+- if (retval) {
+- IVTV_ERR("Error %d setting up streams\n", retval);
+- goto free_i2c;
+- }
+-
+- IVTV_DEBUG_IRQ("Masking interrupts\n");
+ /* clear interrupt mask, effectively disabling interrupts */
+ ivtv_set_irq_mask(itv, 0xffffffff);
+
+@@ -1184,32 +1211,38 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
+ IRQF_SHARED | IRQF_DISABLED, itv->name, (void *)itv);
+ if (retval) {
+ IVTV_ERR("Failed to register irq %d\n", retval);
+- goto free_streams;
++ goto free_i2c;
++ }
++
++ retval = ivtv_streams_setup(itv);
++ if (retval) {
++ IVTV_ERR("Error %d setting up streams\n", retval);
++ goto free_irq;
+ }
+ retval = ivtv_streams_register(itv);
+ if (retval) {
+ IVTV_ERR("Error %d registering devices\n", retval);
+- goto free_irq;
++ goto free_streams;
+ }
+ IVTV_INFO("Initialized card #%d: %s\n", itv->num, itv->card_name);
+ return 0;
+
+- free_irq:
+- free_irq(itv->dev->irq, (void *)itv);
+- free_streams:
++free_streams:
+ ivtv_streams_cleanup(itv);
+- free_i2c:
++free_irq:
++ free_irq(itv->dev->irq, (void *)itv);
++free_i2c:
+ exit_ivtv_i2c(itv);
+- free_io:
++free_io:
+ ivtv_iounmap(itv);
+- free_mem:
++free_mem:
+ release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
+ release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
+ if (itv->has_cx23415)
+ release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
+- free_workqueue:
++free_workqueue:
+ destroy_workqueue(itv->irq_work_queues);
+- err:
++err:
+ if (retval == 0)
+ retval = -ENODEV;
+ IVTV_ERR("Error %d on initialization\n", retval);
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
@@ -401988,7 +567307,7 @@
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
+index 6fb96f1..2b74b0a 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,
@@ -402002,20 +567321,61 @@
itv->dualwatch_jiffies = jiffies;
ivtv_dualwatch(itv);
}
-@@ -753,7 +755,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
+@@ -753,8 +755,10 @@ 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)
++ if (s->q_full.length || s->q_io.length)
return POLLIN | POLLRDNORM;
++ if (eof)
++ return POLLHUP;
return 0;
}
+
+diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c
+index 688cd38..d8ac09f 100644
+--- a/drivers/media/video/ivtv/ivtv-gpio.c
++++ b/drivers/media/video/ivtv/ivtv-gpio.c
+@@ -128,20 +128,17 @@ int ivtv_reset_tuner_gpio(void *dev, int cmd, int value)
+ {
+ struct i2c_algo_bit_data *algo = dev;
+ struct ivtv *itv = algo->data;
+- int curdir, curout;
++ u32 curout;
+
+ if (cmd != XC2028_TUNER_RESET)
+ return 0;
+ IVTV_DEBUG_INFO("Resetting tuner\n");
+ curout = read_reg(IVTV_REG_GPIO_OUT);
+- curdir = read_reg(IVTV_REG_GPIO_DIR);
+- curdir |= (1 << 12); /* GPIO bit 12 */
+-
+- curout &= ~(1 << 12);
++ curout &= ~(1 << itv->card->xceive_pin);
+ write_reg(curout, IVTV_REG_GPIO_OUT);
+ schedule_timeout_interruptible(msecs_to_jiffies(1));
+
+- curout |= (1 << 12);
++ curout |= 1 << itv->card->xceive_pin;
+ write_reg(curout, IVTV_REG_GPIO_OUT);
+ schedule_timeout_interruptible(msecs_to_jiffies(1));
+ return 0;
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
-index fa5ab1e..9824eaf 100644
+index fa5ab1e..771adf4 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)
+@@ -167,7 +167,8 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
+ return -1;
+ id = hw_driverids[idx];
+ memset(&info, 0, sizeof(info));
+- strcpy(info.driver_name, hw_drivernames[idx]);
++ strlcpy(info.driver_name, hw_drivernames[idx],
++ sizeof(info.driver_name));
+ info.addr = hw_addrs[idx];
+ for (i = 0; itv->i2c_clients[i] && i < I2C_CLIENTS_MAX; i++) {}
+
+@@ -177,10 +178,16 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
}
if (id != I2C_DRIVERID_TUNER) {
@@ -402036,10 +567396,52 @@
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
+index edef2a5..d508b5d 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)
+@@ -243,20 +243,31 @@ static int ivtv_validate_speed(int cur_speed, int new_speed)
+ int fact = new_speed < 0 ? -1 : 1;
+ int s;
+
+- if (new_speed < 0) new_speed = -new_speed;
+- if (cur_speed < 0) cur_speed = -cur_speed;
++ if (cur_speed == 0)
++ cur_speed = 1000;
++ if (new_speed < 0)
++ new_speed = -new_speed;
++ if (cur_speed < 0)
++ cur_speed = -cur_speed;
+
+ if (cur_speed <= new_speed) {
+- if (new_speed > 1500) return fact * 2000;
+- if (new_speed > 1000) return fact * 1500;
++ if (new_speed > 1500)
++ return fact * 2000;
++ if (new_speed > 1000)
++ return fact * 1500;
+ }
+ else {
+- if (new_speed >= 2000) return fact * 2000;
+- if (new_speed >= 1500) return fact * 1500;
+- if (new_speed >= 1000) return fact * 1000;
+- }
+- if (new_speed == 0) return 1000;
+- if (new_speed == 1 || new_speed == 1000) return fact * new_speed;
++ if (new_speed >= 2000)
++ return fact * 2000;
++ if (new_speed >= 1500)
++ return fact * 1500;
++ if (new_speed >= 1000)
++ return fact * 1000;
++ }
++ if (new_speed == 0)
++ return 1000;
++ if (new_speed == 1 || new_speed == 1000)
++ return fact * new_speed;
+
+ s = new_speed;
+ new_speed = 1000 / new_speed;
+@@ -712,6 +723,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;
@@ -402047,17 +567449,20 @@
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
+@@ -740,9 +752,9 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ struct v4l2_capability *vcap = arg;
memset(vcap, 0, sizeof(*vcap));
- strcpy(vcap->driver, IVTV_DRIVER_NAME); /* driver name */
+- 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... */
+- strcpy(vcap->bus_info, pci_name(itv->dev)); /* bus info... */
++ strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
++ strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
++ strlcpy(vcap->bus_info, pci_name(itv->dev), sizeof(vcap->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
+
+@@ -827,8 +839,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
case VIDIOC_CROPCAP: {
struct v4l2_cropcap *cropcap = arg;
@@ -402067,7 +567472,7 @@
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
+@@ -837,8 +848,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) {
@@ -402084,7 +567489,7 @@
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
+@@ -856,7 +873,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) {
@@ -402093,7 +567498,7 @@
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
+@@ -867,9 +884,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
}
return -EINVAL;
}
@@ -402104,7 +567509,7 @@
}
case VIDIOC_G_CROP: {
-@@ -878,14 +883,12 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+@@ -878,14 +893,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)
@@ -402121,7 +567526,16 @@
}
case VIDIOC_ENUM_FMT: {
-@@ -1070,11 +1073,10 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+@@ -1015,7 +1028,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ ivtv_std_60hz : ivtv_std_50hz;
+ vs->index = idx;
+ vs->id = enum_stds[idx].std;
+- strcpy(vs->name, enum_stds[idx].name);
++ strlcpy(vs->name, enum_stds[idx].name, sizeof(vs->name));
+ break;
+ }
+
+@@ -1070,11 +1083,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);
@@ -402136,7 +567550,20 @@
}
}
break;
-@@ -1272,6 +1274,8 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+@@ -1100,10 +1112,10 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, vt);
+
+ if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
+- strcpy(vt->name, "ivtv Radio Tuner");
++ strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
+ vt->type = V4L2_TUNER_RADIO;
+ } else {
+- strcpy(vt->name, "ivtv TV Tuner");
++ strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
+ vt->type = V4L2_TUNER_ANALOG_TV;
+ }
+ break;
+@@ -1272,6 +1284,8 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
else
fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
}
@@ -402145,7 +567572,7 @@
break;
}
-@@ -1285,6 +1289,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+@@ -1285,6 +1299,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);
@@ -402153,7 +567580,7 @@
break;
}
-@@ -1628,6 +1633,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
+@@ -1628,6 +1643,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);
@@ -402161,7 +567588,7 @@
}
return ivtv_debug_ioctls(filp, cmd, arg);
-@@ -1671,6 +1677,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
+@@ -1671,6 +1687,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);
@@ -402169,7 +567596,7 @@
}
return ivtv_v4l2_ioctls(itv, filp, cmd, arg);
-@@ -1684,6 +1691,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
+@@ -1684,6 +1701,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);
@@ -402178,14 +567605,14 @@
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
+index 65604dd..d8ba3a4 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);
++ itv->dma_timer.expires = jiffies + msecs_to_jiffies(300);
+ add_timer(&itv->dma_timer);
}
@@ -402194,7 +567621,7 @@
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);
++ itv->dma_timer.expires = jiffies + msecs_to_jiffies(300);
+ add_timer(&itv->dma_timer);
}
@@ -402343,8 +567770,21 @@
schedule_timeout(msecs_to_jiffies(10));
}
+diff --git a/drivers/media/video/ivtv/ivtv-version.h b/drivers/media/video/ivtv/ivtv-version.h
+index 0f1d4cc..02c5ab0 100644
+--- a/drivers/media/video/ivtv/ivtv-version.h
++++ b/drivers/media/video/ivtv/ivtv-version.h
+@@ -23,7 +23,7 @@
+ #define IVTV_DRIVER_NAME "ivtv"
+ #define IVTV_DRIVER_VERSION_MAJOR 1
+ #define IVTV_DRIVER_VERSION_MINOR 2
+-#define IVTV_DRIVER_VERSION_PATCHLEVEL 0
++#define IVTV_DRIVER_VERSION_PATCHLEVEL 1
+
+ #define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL)
+ #define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL)
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c
-index 8518348..393d917 100644
+index 8518348..62f70bd 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)
@@ -402427,6 +567867,44 @@
{
DEFINE_WAIT(wait);
int rc = 0;
+@@ -1094,8 +1098,8 @@ void ivtv_yuv_setup_stream_frame(struct ivtv *itv)
+ ivtv_yuv_next_free(itv);
+
+ /* Copy V4L2 parameters to an ivtv_dma_frame struct... */
+- dma_args.y_source = 0L;
+- dma_args.uv_source = 0L;
++ dma_args.y_source = NULL;
++ dma_args.uv_source = NULL;
+ dma_args.src.left = 0;
+ dma_args.src.top = 0;
+ dma_args.src.width = yi->v4l2_src_w;
+diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c
+index 3b23fc0..df789f6 100644
+--- a/drivers/media/video/ivtv/ivtvfb.c
++++ b/drivers/media/video/ivtv/ivtvfb.c
+@@ -532,7 +532,7 @@ static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
+
+ IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+- strcpy(fix->id, "cx23415 TV out");
++ strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id));
+ fix->smem_start = oi->video_pbase;
+ fix->smem_len = oi->video_buffer_size;
+ fix->type = FB_TYPE_PACKED_PIXELS;
+diff --git a/drivers/media/video/m52790.c b/drivers/media/video/m52790.c
+index d4bf14c..5b9dfa2 100644
+--- a/drivers/media/video/m52790.c
++++ b/drivers/media/video/m52790.c
+@@ -126,7 +126,8 @@ static int m52790_command(struct i2c_client *client, unsigned int cmd,
+
+ /* i2c implementation */
+
+-static int m52790_probe(struct i2c_client *client)
++static int m52790_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct m52790_state *state;
+
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index 3d51fa0..e7ccbc8 100644
--- a/drivers/media/video/meye.c
@@ -403926,7 +569404,7 @@
#ifdef CONFIG_PM
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
-index 7a11f31..b73c740 100644
+index 7a11f31..e627316 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)
@@ -403947,6 +569425,15 @@
case VIDIOCGAUDIO:
{
struct video_audio *va = arg;
+@@ -805,7 +805,7 @@ static int msp_resume(struct i2c_client *client)
+
+ /* ----------------------------------------------------------------------- */
+
+-static int msp_probe(struct i2c_client *client)
++static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
+ {
+ struct msp_state *state;
+ int (*thread_func)(void *data) = NULL;
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
@@ -403985,59 +569472,731 @@
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
+deleted file mode 100644
+index 74fd6a0..0000000
--- a/drivers/media/video/mt20xx.c
-+++ b/drivers/media/video/mt20xx.c
-@@ -10,12 +10,10 @@
- #include "tuner-i2c.h"
- #include "mt20xx.h"
-
++++ /dev/null
+@@ -1,671 +0,0 @@
+-/*
+- * i2c tv tuner chip device driver
+- * controls microtune tuners, mt2032 + mt2050 at the moment.
+- *
+- * This "mt20xx" module was split apart from the original "tuner" module.
+- */
+-#include <linux/delay.h>
+-#include <linux/i2c.h>
+-#include <linux/videodev.h>
+-#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");
-
+-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 optimize_vco = 1;
+-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 */
-
+-module_param(radio_antenna, int, 0644);
+-
+-/* ---------------------------------------------------------------------- */
+-
+-#define MT2032 0x04
+-#define MT2030 0x06
+-#define MT2040 0x07
+-#define MT2050 0x42
+-
+-static char *microtune_part[] = {
+- [ MT2030 ] = "MT2030",
+- [ MT2032 ] = "MT2032",
+- [ MT2040 ] = "MT2040",
+- [ MT2050 ] = "MT2050",
+-};
+-
+-struct microtune_priv {
+- struct tuner_i2c_props i2c_props;
+-
+- unsigned int xogc;
+- //unsigned int radio_if2;
+-
+- u32 frequency;
+-};
+-
+-static int microtune_release(struct dvb_frontend *fe)
+-{
+- kfree(fe->tuner_priv);
+- fe->tuner_priv = NULL;
+-
+- return 0;
+-}
+-
+-static int microtune_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+-{
+- struct microtune_priv *priv = fe->tuner_priv;
+- *frequency = priv->frequency;
+- return 0;
+-}
+-
+-// IsSpurInBand()?
+-static int mt2032_spurcheck(struct dvb_frontend *fe,
+- int f1, int f2, int spectrum_from,int spectrum_to)
+-{
+- struct microtune_priv *priv = fe->tuner_priv;
+- int n1=1,n2,f;
+-
+- f1=f1/1000; //scale to kHz to avoid 32bit overflows
+- f2=f2/1000;
+- spectrum_from/=1000;
+- spectrum_to/=1000;
+-
+- tuner_dbg("spurcheck f1=%d f2=%d from=%d to=%d\n",
+- f1,f2,spectrum_from,spectrum_to);
+-
+- do {
+- n2=-n1;
+- f=n1*(f1-f2);
+- do {
+- n2--;
+- f=f-f2;
+- tuner_dbg("spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f);
+-
+- if( (f>spectrum_from) && (f<spectrum_to))
+- tuner_dbg("mt2032 spurcheck triggered: %d\n",n1);
+- } while ( (f>(f2-spectrum_to)) || (n2>-5));
+- n1++;
+- } while (n1<5);
+-
+- return 1;
+-}
+-
+-static int mt2032_compute_freq(struct dvb_frontend *fe,
+- unsigned int rfin,
+- unsigned int if1, unsigned int if2,
+- unsigned int spectrum_from,
+- unsigned int spectrum_to,
+- unsigned char *buf,
+- int *ret_sel,
+- unsigned int xogc) //all in Hz
+-{
+- struct microtune_priv *priv = fe->tuner_priv;
+- unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1,
+- desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq;
+-
+- fref= 5250 *1000; //5.25MHz
+- desired_lo1=rfin+if1;
+-
+- lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000);
+- lo1n=lo1/8;
+- lo1a=lo1-(lo1n*8);
+-
+- s=rfin/1000/1000+1090;
+-
+- if(optimize_vco) {
+- if(s>1890) sel=0;
+- else if(s>1720) sel=1;
+- else if(s>1530) sel=2;
+- else if(s>1370) sel=3;
+- else sel=4; // >1090
+- }
+- else {
+- if(s>1790) sel=0; // <1958
+- else if(s>1617) sel=1;
+- else if(s>1449) sel=2;
+- else if(s>1291) sel=3;
+- else sel=4; // >1090
+- }
+- *ret_sel=sel;
+-
+- lo1freq=(lo1a+8*lo1n)*fref;
+-
+- tuner_dbg("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n",
+- rfin,lo1,lo1n,lo1a,sel,lo1freq);
+-
+- desired_lo2=lo1freq-rfin-if2;
+- lo2=(desired_lo2)/fref;
+- lo2n=lo2/8;
+- lo2a=lo2-(lo2n*8);
+- lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith
+- lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000;
+-
+- tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n",
+- rfin,lo2,lo2n,lo2a,lo2num,lo2freq);
+-
+- if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) {
+- tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n",
+- lo1a, lo1n, lo2a,lo2n);
+- return(-1);
+- }
+-
+- mt2032_spurcheck(fe, lo1freq, desired_lo2, spectrum_from, spectrum_to);
+- // should recalculate lo1 (one step up/down)
+-
+- // set up MT2032 register map for transfer over i2c
+- buf[0]=lo1n-1;
+- buf[1]=lo1a | (sel<<4);
+- buf[2]=0x86; // LOGC
+- buf[3]=0x0f; //reserved
+- buf[4]=0x1f;
+- buf[5]=(lo2n-1) | (lo2a<<5);
+- if(rfin >400*1000*1000)
+- buf[6]=0xe4;
+- else
+- buf[6]=0xf4; // set PKEN per rev 1.2
+- buf[7]=8+xogc;
+- buf[8]=0xc3; //reserved
+- buf[9]=0x4e; //reserved
+- buf[10]=0xec; //reserved
+- buf[11]=(lo2num&0xff);
+- buf[12]=(lo2num>>8) |0x80; // Lo2RST
+-
+- return 0;
+-}
+-
+-static int mt2032_check_lo_lock(struct dvb_frontend *fe)
+-{
+- struct microtune_priv *priv = fe->tuner_priv;
+- int try,lock=0;
+- unsigned char buf[2];
+-
+- for(try=0;try<10;try++) {
+- buf[0]=0x0e;
+- tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
+- tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
+- tuner_dbg("mt2032 Reg.E=0x%02x\n",buf[0]);
+- lock=buf[0] &0x06;
+-
+- if (lock==6)
+- break;
+-
+- tuner_dbg("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]);
+- udelay(1000);
+- }
+- return lock;
+-}
+-
+-static int mt2032_optimize_vco(struct dvb_frontend *fe,int sel,int lock)
+-{
+- struct microtune_priv *priv = fe->tuner_priv;
+- unsigned char buf[2];
+- int tad1;
+-
+- buf[0]=0x0f;
+- tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
+- tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
+- tuner_dbg("mt2032 Reg.F=0x%02x\n",buf[0]);
+- tad1=buf[0]&0x07;
+-
+- if(tad1 ==0) return lock;
+- if(tad1 ==1) return lock;
+-
+- if(tad1==2) {
+- if(sel==0)
+- return lock;
+- else sel--;
+- }
+- else {
+- if(sel<4)
+- sel++;
+- else
+- return lock;
+- }
+-
+- tuner_dbg("mt2032 optimize_vco: sel=%d\n",sel);
+-
+- buf[0]=0x0f;
+- buf[1]=sel;
+- tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
+- lock=mt2032_check_lo_lock(fe);
+- return lock;
+-}
+-
+-
+-static void mt2032_set_if_freq(struct dvb_frontend *fe, unsigned int rfin,
+- unsigned int if1, unsigned int if2,
+- unsigned int from, unsigned int to)
+-{
+- unsigned char buf[21];
+- int lint_try,ret,sel,lock=0;
+- struct microtune_priv *priv = fe->tuner_priv;
+-
+- tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n",
+- rfin,if1,if2,from,to);
+-
+- buf[0]=0;
+- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
+- tuner_i2c_xfer_recv(&priv->i2c_props,buf,21);
+-
+- buf[0]=0;
+- ret=mt2032_compute_freq(fe,rfin,if1,if2,from,to,&buf[1],&sel,priv->xogc);
+- if (ret<0)
+- return;
+-
+- // send only the relevant registers per Rev. 1.2
+- buf[0]=0;
+- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,4);
+- buf[5]=5;
+- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,4);
+- buf[11]=11;
+- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+11,3);
+- if(ret!=3)
+- tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret);
+-
+- // wait for PLLs to lock (per manual), retry LINT if not.
+- for(lint_try=0; lint_try<2; lint_try++) {
+- lock=mt2032_check_lo_lock(fe);
+-
+- if(optimize_vco)
+- lock=mt2032_optimize_vco(fe,sel,lock);
+- if(lock==6) break;
+-
+- tuner_dbg("mt2032: re-init PLLs by LINT\n");
+- buf[0]=7;
+- buf[1]=0x80 +8+priv->xogc; // set LINT to re-init PLLs
+- tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
+- mdelay(10);
+- buf[1]=8+priv->xogc;
+- tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
+- }
+-
+- if (lock!=6)
+- tuner_warn("MT2032 Fatal Error: PLLs didn't lock.\n");
+-
+- buf[0]=2;
+- buf[1]=0x20; // LOGC for optimal phase noise
+- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
+- if (ret!=2)
+- tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
+-}
+-
+-
+-static int mt2032_set_tv_freq(struct dvb_frontend *fe,
+- struct analog_parameters *params)
+-{
+- int if2,from,to;
+-
+- // signal bandwidth and picture carrier
+- if (params->std & V4L2_STD_525_60) {
+- // NTSC
+- from = 40750*1000;
+- to = 46750*1000;
+- if2 = 45750*1000;
+- } else {
+- // PAL
+- from = 32900*1000;
+- to = 39900*1000;
+- if2 = 38900*1000;
+- }
+-
+- mt2032_set_if_freq(fe, params->frequency*62500,
+- 1090*1000*1000, if2, from, to);
+-
+- return 0;
+-}
+-
+-static int mt2032_set_radio_freq(struct dvb_frontend *fe,
+- struct analog_parameters *params)
+-{
+- struct microtune_priv *priv = fe->tuner_priv;
+- int if2;
+-
+- if (params->std & V4L2_STD_525_60) {
+- tuner_dbg("pinnacle ntsc\n");
+- if2 = 41300 * 1000;
+- } else {
+- tuner_dbg("pinnacle pal\n");
+- if2 = 33300 * 1000;
+- }
+-
+- // per Manual for FM tuning: first if center freq. 1085 MHz
+- mt2032_set_if_freq(fe, params->frequency * 125 / 2,
+- 1085*1000*1000,if2,if2,if2);
+-
+- return 0;
+-}
+-
+-static int mt2032_set_params(struct dvb_frontend *fe,
+- struct analog_parameters *params)
+-{
+- struct microtune_priv *priv = fe->tuner_priv;
+- int ret = -EINVAL;
+-
+- switch (params->mode) {
+- case V4L2_TUNER_RADIO:
+- ret = mt2032_set_radio_freq(fe, params);
+- priv->frequency = params->frequency * 125 / 2;
+- break;
+- case V4L2_TUNER_ANALOG_TV:
+- case V4L2_TUNER_DIGITAL_TV:
+- ret = mt2032_set_tv_freq(fe, params);
+- priv->frequency = params->frequency * 62500;
+- break;
+- }
+-
+- return ret;
+-}
+-
+-static struct dvb_tuner_ops mt2032_tuner_ops = {
+- .set_analog_params = mt2032_set_params,
+- .release = microtune_release,
+- .get_frequency = microtune_get_frequency,
+-};
+-
+-// Initialization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
+-static int mt2032_init(struct dvb_frontend *fe)
+-{
+- struct microtune_priv *priv = fe->tuner_priv;
+- unsigned char buf[21];
+- int ret,xogc,xok=0;
+-
+- // Initialize Registers per spec.
+- buf[1]=2; // Index to register 2
+- buf[2]=0xff;
+- buf[3]=0x0f;
+- buf[4]=0x1f;
+- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+1,4);
+-
+- buf[5]=6; // Index register 6
+- buf[6]=0xe4;
+- buf[7]=0x8f;
+- buf[8]=0xc3;
+- buf[9]=0x4e;
+- buf[10]=0xec;
+- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,6);
+-
+- buf[12]=13; // Index register 13
+- buf[13]=0x32;
+- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+12,2);
+-
+- // Adjust XOGC (register 7), wait for XOK
+- xogc=7;
+- do {
+- tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
+- mdelay(10);
+- buf[0]=0x0e;
+- tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
+- tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
+- xok=buf[0]&0x01;
+- tuner_dbg("mt2032: xok = 0x%02x\n",xok);
+- if (xok == 1) break;
+-
+- xogc--;
+- tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
+- if (xogc == 3) {
+- xogc=4; // min. 4 per spec
+- break;
+- }
+- buf[0]=0x07;
+- buf[1]=0x88 + xogc;
+- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
+- if (ret!=2)
+- tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
+- } while (xok != 1 );
+- priv->xogc=xogc;
+-
+- memcpy(&fe->ops.tuner_ops, &mt2032_tuner_ops, sizeof(struct dvb_tuner_ops));
+-
+- return(1);
+-}
+-
+-static void mt2050_set_antenna(struct dvb_frontend *fe, unsigned char antenna)
+-{
+- struct microtune_priv *priv = fe->tuner_priv;
+- unsigned char buf[2];
+- int ret;
+-
+- buf[0] = 6;
+- buf[1] = antenna ? 0x11 : 0x10;
+- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
+- tuner_dbg("mt2050: enabled antenna connector %d\n", antenna);
+-}
+-
+-static void mt2050_set_if_freq(struct dvb_frontend *fe,unsigned int freq, unsigned int if2)
+-{
+- struct microtune_priv *priv = fe->tuner_priv;
+- unsigned int if1=1218*1000*1000;
+- unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b;
+- int ret;
+- unsigned char buf[6];
+-
+- tuner_dbg("mt2050_set_if_freq freq=%d if1=%d if2=%d\n",
+- freq,if1,if2);
+-
+- f_lo1=freq+if1;
+- f_lo1=(f_lo1/1000000)*1000000;
+-
+- f_lo2=f_lo1-freq-if2;
+- f_lo2=(f_lo2/50000)*50000;
+-
+- lo1=f_lo1/4000000;
+- lo2=f_lo2/4000000;
+-
+- f_lo1_modulo= f_lo1-(lo1*4000000);
+- f_lo2_modulo= f_lo2-(lo2*4000000);
+-
+- num1=4*f_lo1_modulo/4000000;
+- num2=4096*(f_lo2_modulo/1000)/4000;
+-
+- // todo spurchecks
+-
+- div1a=(lo1/12)-1;
+- div1b=lo1-(div1a+1)*12;
+-
+- div2a=(lo2/8)-1;
+- div2b=lo2-(div2a+1)*8;
+-
+- if (debug > 1) {
+- tuner_dbg("lo1 lo2 = %d %d\n", lo1, lo2);
+- tuner_dbg("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n",
+- num1,num2,div1a,div1b,div2a,div2b);
+- }
+-
+- buf[0]=1;
+- buf[1]= 4*div1b + num1;
+- if(freq<275*1000*1000) buf[1] = buf[1]|0x80;
+-
+- buf[2]=div1a;
+- buf[3]=32*div2b + num2/256;
+- buf[4]=num2-(num2/256)*256;
+- buf[5]=div2a;
+- if(num2!=0) buf[5]=buf[5]|0x40;
+-
+- if (debug > 1) {
+- int i;
+- tuner_dbg("bufs is: ");
+- for(i=0;i<6;i++)
+- printk("%x ",buf[i]);
+- printk("\n");
+- }
+-
+- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,6);
+- if (ret!=6)
+- tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret);
+-}
+-
+-static int mt2050_set_tv_freq(struct dvb_frontend *fe,
+- struct analog_parameters *params)
+-{
+- unsigned int if2;
+-
+- if (params->std & V4L2_STD_525_60) {
+- // NTSC
+- if2 = 45750*1000;
+- } else {
+- // PAL
+- if2 = 38900*1000;
+- }
+- if (V4L2_TUNER_DIGITAL_TV == params->mode) {
+- // DVB (pinnacle 300i)
+- if2 = 36150*1000;
+- }
+- mt2050_set_if_freq(fe, params->frequency*62500, if2);
+- mt2050_set_antenna(fe, tv_antenna);
+-
+- return 0;
+-}
+-
+-static int mt2050_set_radio_freq(struct dvb_frontend *fe,
+- struct analog_parameters *params)
+-{
+- struct microtune_priv *priv = fe->tuner_priv;
+- int if2;
+-
+- if (params->std & V4L2_STD_525_60) {
+- tuner_dbg("pinnacle ntsc\n");
+- if2 = 41300 * 1000;
+- } else {
+- tuner_dbg("pinnacle pal\n");
+- if2 = 33300 * 1000;
+- }
+-
+- mt2050_set_if_freq(fe, params->frequency * 125 / 2, if2);
+- mt2050_set_antenna(fe, radio_antenna);
+-
+- return 0;
+-}
+-
+-static int mt2050_set_params(struct dvb_frontend *fe,
+- struct analog_parameters *params)
+-{
+- struct microtune_priv *priv = fe->tuner_priv;
+- int ret = -EINVAL;
+-
+- switch (params->mode) {
+- case V4L2_TUNER_RADIO:
+- ret = mt2050_set_radio_freq(fe, params);
+- priv->frequency = params->frequency * 125 / 2;
+- break;
+- case V4L2_TUNER_ANALOG_TV:
+- case V4L2_TUNER_DIGITAL_TV:
+- ret = mt2050_set_tv_freq(fe, params);
+- priv->frequency = params->frequency * 62500;
+- break;
+- }
+-
+- return ret;
+-}
+-
+-static struct dvb_tuner_ops mt2050_tuner_ops = {
+- .set_analog_params = mt2050_set_params,
+- .release = microtune_release,
+- .get_frequency = microtune_get_frequency,
+-};
+-
+-static int mt2050_init(struct dvb_frontend *fe)
+-{
+- struct microtune_priv *priv = fe->tuner_priv;
+- unsigned char buf[2];
+- int ret;
+-
+- buf[0]=6;
+- buf[1]=0x10;
+- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // power
+-
+- buf[0]=0x0f;
+- buf[1]=0x0f;
+- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // m1lo
+-
+- buf[0]=0x0d;
+- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
+- tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
+-
+- tuner_dbg("mt2050: sro is %x\n",buf[0]);
+-
+- memcpy(&fe->ops.tuner_ops, &mt2050_tuner_ops, sizeof(struct dvb_tuner_ops));
+-
+- return 0;
+-}
+-
+-struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
+- struct i2c_adapter* i2c_adap,
+- u8 i2c_addr)
+-{
+- struct microtune_priv *priv = NULL;
+- char *name;
+- unsigned char buf[21];
+- int company_code;
+-
+- priv = kzalloc(sizeof(struct microtune_priv), GFP_KERNEL);
+- if (priv == NULL)
+- return NULL;
+- fe->tuner_priv = priv;
+-
+- priv->i2c_props.addr = i2c_addr;
+- priv->i2c_props.adap = i2c_adap;
+-
+- //priv->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */
+-
+- memset(buf,0,sizeof(buf));
+-
+- name = "unknown";
+-
+- tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
+- tuner_i2c_xfer_recv(&priv->i2c_props,buf,21);
+- if (debug) {
+- int i;
+- tuner_dbg("MT20xx hexdump:");
+- for(i=0;i<21;i++) {
+- printk(" %02x",buf[i]);
+- if(((i+1)%8)==0) printk(" ");
+- }
+- printk("\n");
+- }
+- company_code = buf[0x11] << 8 | buf[0x12];
+- tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n",
+- company_code,buf[0x13],buf[0x14]);
+-
+-
+- if (buf[0x13] < ARRAY_SIZE(microtune_part) &&
+- NULL != microtune_part[buf[0x13]])
+- name = microtune_part[buf[0x13]];
+- switch (buf[0x13]) {
+- case MT2032:
+- mt2032_init(fe);
+- break;
+- case MT2050:
+- mt2050_init(fe);
+- break;
+- default:
+- tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n",
+- name);
+- return NULL;
+- }
+-
+- strlcpy(fe->ops.tuner_ops.info.name, name,
+- sizeof(fe->ops.tuner_ops.info.name));
+- tuner_info("microtune %s found, OK\n",name);
+- return fe;
+-}
+-
+-EXPORT_SYMBOL_GPL(microtune_attach);
+-
+-MODULE_DESCRIPTION("Microtune tuner driver");
+-MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
+-MODULE_LICENSE("GPL");
+-
+-/*
+- * Overrides for Emacs so that we follow Linus's tabbing style.
+- * ---------------------------------------------------------------------------
+- * Local variables:
+- * c-basic-offset: 8
+- * End:
+- */
diff --git a/drivers/media/video/mt20xx.h b/drivers/media/video/mt20xx.h
-index 5e9c825..aa848e1 100644
+deleted file mode 100644
+index 5e9c825..0000000
--- 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)
- {
++++ /dev/null
+@@ -1,37 +0,0 @@
+-/*
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2 of the License, or
+- (at your option) any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
+-
+- You 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 __MT20XX_H__
+-#define __MT20XX_H__
+-
+-#include <linux/i2c.h>
+-#include "dvb_frontend.h"
+-
+-#if defined(CONFIG_TUNER_MT20XX) || (defined(CONFIG_TUNER_MT20XX_MODULE) && defined(MODULE))
+-extern struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
+- struct i2c_adapter* i2c_adap,
+- u8 i2c_addr);
+-#else
+-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
+- return NULL;
+-}
+-#endif
+-
+-#endif /* __MT20XX_H__ */
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
new file mode 100644
-index 0000000..3fb5f63
+index 0000000..179e470
--- /dev/null
+++ b/drivers/media/video/mt9m001.c
-@@ -0,0 +1,722 @@
+@@ -0,0 +1,730 @@
+/*
+ * Driver for MT9M001 CMOS Image Sensor from Micron
+ *
@@ -404412,7 +570571,7 @@
+}
+#endif
+
-+const struct v4l2_queryctrl mt9m001_controls[] = {
++static const struct v4l2_queryctrl mt9m001_controls[] = {
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -404660,7 +570819,8 @@
+ soc_camera_video_stop(&mt9m001->icd);
+}
+
-+static int mt9m001_probe(struct i2c_client *client)
++static int mt9m001_probe(struct i2c_client *client,
++ const struct i2c_device_id *did)
+{
+ struct mt9m001 *mt9m001;
+ struct soc_camera_device *icd;
@@ -404736,12 +570896,19 @@
+ return 0;
+}
+
++static const struct i2c_device_id mt9m001_id[] = {
++ { "mt9m001", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, mt9m001_id);
++
+static struct i2c_driver mt9m001_i2c_driver = {
+ .driver = {
+ .name = "mt9m001",
+ },
+ .probe = mt9m001_probe,
+ .remove = mt9m001_remove,
++ .id_table = mt9m001_id,
+};
+
+static int __init mt9m001_mod_init(void)
@@ -404762,10 +570929,10 @@
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
new file mode 100644
-index 0000000..d4b9e27
+index 0000000..d1391ac
--- /dev/null
+++ b/drivers/media/video/mt9v022.c
-@@ -0,0 +1,844 @@
+@@ -0,0 +1,852 @@
+/*
+ * Driver for MT9V022 CMOS Image Sensor from Micron
+ *
@@ -405220,7 +571387,7 @@
+}
+#endif
+
-+const struct v4l2_queryctrl mt9v022_controls[] = {
++static const struct v4l2_queryctrl mt9v022_controls[] = {
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -405513,7 +571680,8 @@
+ soc_camera_video_stop(&mt9v022->icd);
+}
+
-+static int mt9v022_probe(struct i2c_client *client)
++static int mt9v022_probe(struct i2c_client *client,
++ const struct i2c_device_id *did)
+{
+ struct mt9v022 *mt9v022;
+ struct soc_camera_device *icd;
@@ -405586,12 +571754,19 @@
+ return 0;
+}
+
++static const struct i2c_device_id mt9v022_id[] = {
++ { "mt9v022", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, mt9v022_id);
++
+static struct i2c_driver mt9v022_i2c_driver = {
+ .driver = {
+ .name = "mt9v022",
+ },
+ .probe = mt9v022_probe,
+ .remove = mt9v022_remove,
++ .id_table = mt9v022_id,
+};
+
+static int __init mt9v022_mod_init(void)
@@ -405723,43 +571898,88 @@
.llseek = no_llseek,
};
diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig
-index 6fc1b8b..158b3d0 100644
+index 6fc1b8b..9620c67 100644
--- a/drivers/media/video/pvrusb2/Kconfig
+++ b/drivers/media/video/pvrusb2/Kconfig
-@@ -58,6 +58,31 @@ config VIDEO_PVRUSB2_SYSFS
+@@ -1,14 +1,15 @@
+ config VIDEO_PVRUSB2
+ tristate "Hauppauge WinTV-PVR USB2 support"
+- depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
++ depends on VIDEO_V4L2 && I2C
+ select FW_LOADER
+- select VIDEO_TUNER
++ select MEDIA_TUNER
+ select VIDEO_TVEEPROM
+ select VIDEO_CX2341X
+ select VIDEO_SAA711X
+ select VIDEO_CX25840
+ select VIDEO_MSP3400
+ select VIDEO_WM8775
++ select VIDEO_CS53L32A
+ ---help---
+ This is a video4linux driver for Conexant 23416 based
+ usb2 personal video recorder devices.
+@@ -16,32 +17,6 @@ config VIDEO_PVRUSB2
+ To compile this driver as a module, choose M here: the
+ module will be called pvrusb2
+
+-config VIDEO_PVRUSB2_ONAIR_CREATOR
+- bool "pvrusb2 driver support for OnAir Creator model"
+- depends on VIDEO_PVRUSB2 && EXPERIMENTAL
+- select VIDEO_SAA711X
+- select VIDEO_CS53L32A
+- ---help---
+-
+- This option enables support for the OnAir Creator USB tuner
+- device. This is a hybrid device, however currently only
+- analog mode is supported.
+-
+- If you are in doubt, say Y.
+-
+-config VIDEO_PVRUSB2_ONAIR_USB2
+- bool "pvrusb2 driver support for OnAir USB2 model"
+- depends on VIDEO_PVRUSB2 && EXPERIMENTAL
+- select VIDEO_SAA711X
+- select VIDEO_CS53L32A
+- ---help---
+-
+- This option enables support for the OnAir USB2 tuner device
+- (also known as the Sasem tuner). This is a hybrid device,
+- however currently only analog mode is supported.
+-
+- If you are in doubt, say Y.
+-
+ config VIDEO_PVRUSB2_SYSFS
+ bool "pvrusb2 sysfs support (EXPERIMENTAL)"
+ default y
+@@ -58,6 +33,25 @@ config VIDEO_PVRUSB2_SYSFS
Note: This feature is experimental and subject to change.
+config VIDEO_PVRUSB2_DVB
-+ bool "pvrusb2 DVB support (EXPERIMENTAL)"
-+ default n
++ bool "pvrusb2 ATSC/DVB support (EXPERIMENTAL)"
++ default y
+ 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
++ select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE
++ select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
++ select MEDIA_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.
++ This option enables a DVB interface for the pvrusb2 driver.
++ If your device does not support digital television, this
++ feature will have no affect on the driver's operation.
+
-+ Note: This feature is very experimental and might break
++ If you are in doubt, say Y.
+
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
+index 47284e5..4fda2de 100644
--- a/drivers/media/video/pvrusb2/Makefile
+++ b/drivers/media/video/pvrusb2/Makefile
@@ -1,5 +1,6 @@
@@ -405769,7 +571989,7 @@
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 \
+@@ -9,6 +10,12 @@ 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 \
@@ -405779,10 +571999,24 @@
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
+
+EXTRA_CFLAGS += -Idrivers/media/video
++EXTRA_CFLAGS += -Idrivers/media/common/tuners
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c
+index 9a7c8e9..8d859cc 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-audio.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-audio.c
+@@ -75,7 +75,7 @@ static void set_stereo(struct pvr2_msp3400_handler *ctxt)
+ pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo");
+
+ if ((sid < ARRAY_SIZE(routing_schemes)) &&
+- ((sp = routing_schemes + sid) != 0) &&
++ ((sp = routing_schemes + sid) != NULL) &&
+ (hdw->input_val >= 0) &&
+ (hdw->input_val < sp->cnt)) {
+ route.input = sp->def[hdw->input_val];
diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c
-index 9d94aed..b5db6a5 100644
+index 9d94aed..73dcb1c 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-context.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-context.c
@@ -23,40 +23,193 @@
@@ -405978,7 +572212,7 @@
+int pvr2_context_global_init(void)
+{
+ pvr2_context_thread_ptr = kthread_run(pvr2_context_thread_func,
-+ 0,
++ NULL,
+ "pvrusb2-context");
+ return (pvr2_context_thread_ptr ? 0 : -ENOMEM);
+}
@@ -406300,7 +572534,7 @@
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
+index ffdc45c..29d5059 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[] = {
@@ -406314,8 +572548,17 @@
.vid = CX25840_COMPOSITE1,
.aud = CX25840_AUDIO_SERIAL,
},
+@@ -121,7 +123,7 @@ static void set_input(struct pvr2_v4l_cx2584x *ctxt)
+ memset(&route,0,sizeof(route));
+
+ if ((sid < ARRAY_SIZE(routing_schemes)) &&
+- ((sp = routing_schemes + sid) != 0) &&
++ ((sp = routing_schemes + sid) != NULL) &&
+ (hdw->input_val >= 0) &&
+ (hdw->input_val < sp->cnt)) {
+ vid_input = sp->def[hdw->input_val].vid;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debug.h b/drivers/media/video/pvrusb2/pvrusb2-debug.h
-index fca49d8..11537dd 100644
+index fca49d8..707d2d9 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;
@@ -406327,6 +572570,14 @@
#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 */
+@@ -54,6 +54,7 @@ extern int pvrusb2_debug;
+ #define PVR2_TRACE_DATA_FLOW (1 << 25) /* Track data flow */
+ #define PVR2_TRACE_DEBUGIFC (1 << 26) /* Debug interface actions */
+ #define PVR2_TRACE_GPIO (1 << 27) /* GPIO state bit changes */
++#define PVR2_TRACE_DVB_FEED (1 << 28) /* DVB transport feed debug */
+
+
+ #endif /* __PVRUSB2_HDW_INTERNAL_H */
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
@@ -406377,7 +572628,7 @@
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
+index fe9991c..5bf6d8f 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.
@@ -406441,7 +572692,7 @@
};
-@@ -105,6 +124,30 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = {
+@@ -105,15 +124,70 @@ 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,
@@ -406472,7 +572723,9 @@
.signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW,
};
-@@ -114,6 +157,38 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = {
+
+
+-#ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_CREATOR
/*------------------------------------------------------------------------*/
/* OnAir Creator */
@@ -406511,7 +572764,7 @@
static const char *pvr2_client_onair_creator[] = {
"saa7115",
"tuner",
-@@ -126,7 +201,16 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = {
+@@ -126,16 +200,54 @@ 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,
@@ -406520,15 +572773,17 @@
+ .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 = {
+
+-#ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_USB2
/*------------------------------------------------------------------------*/
/* OnAir USB 2.0 */
@@ -406566,7 +572821,7 @@
static const char *pvr2_client_onair_usb2[] = {
"saa7115",
"tuner",
-@@ -147,8 +262,17 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = {
+@@ -147,16 +259,68 @@ 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),
@@ -406577,15 +572832,16 @@
+ .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 */
@@ -406636,7 +572892,7 @@
static const char *pvr2_client_73xxx[] = {
"cx25840",
"tuner",
-@@ -167,7 +335,7 @@ static const char *pvr2_fw1_names_73xxx[] = {
+@@ -167,7 +331,7 @@ static const char *pvr2_fw1_names_73xxx[] = {
};
static const struct pvr2_device_desc pvr2_device_73xxx = {
@@ -406645,7 +572901,7 @@
.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 = {
+@@ -175,15 +339,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,
@@ -406663,7 +572919,7 @@
#endif
};
-@@ -192,6 +359,80 @@ static const struct pvr2_device_desc pvr2_device_73xxx = {
+@@ -192,6 +355,80 @@ static const struct pvr2_device_desc pvr2_device_73xxx = {
/*------------------------------------------------------------------------*/
/* Hauppauge PVR-USB2 Model 75xxx */
@@ -406744,7 +573000,7 @@
static const char *pvr2_client_75xxx[] = {
"cx25840",
"tuner",
-@@ -201,17 +442,46 @@ static const char *pvr2_fw1_names_75xxx[] = {
+@@ -201,17 +438,46 @@ static const char *pvr2_fw1_names_75xxx[] = {
"v4l-pvrusb2-73xxx-01.fw",
};
@@ -406754,18 +573010,18 @@
+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,
++ .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,
++ .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+ .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
- .default_std_mask = V4L2_STD_NTSC_M,
++ .default_std_mask = V4L2_STD_NTSC_M,
+ .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+ .dvb_props = &pvr2_750xx_dvb_props,
@@ -406775,18 +573031,18 @@
+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,
+ .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,
+ .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+ .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
-+ .default_std_mask = V4L2_STD_NTSC_M,
+ .default_std_mask = V4L2_STD_NTSC_M,
+ .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+ .dvb_props = &pvr2_751xx_dvb_props,
@@ -406794,16 +573050,20 @@
};
-@@ -225,6 +495,8 @@ struct usb_device_id pvr2_device_table[] = {
+@@ -225,20 +491,18 @@ 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},
+-#ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_CREATOR
+ { 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[] = {
+-#endif
+-#ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_USB2
+ { USB_DEVICE(0x11ba, 0x1001),
+ .driver_info = (kernel_ulong_t)&pvr2_device_onair_usb2},
+-#endif
{ USB_DEVICE(0x2040, 0x7300),
.driver_info = (kernel_ulong_t)&pvr2_device_73xxx},
{ USB_DEVICE(0x2040, 0x7500),
@@ -406941,10 +573201,10 @@
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
+index 0000000..6ec4bf8
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c
-@@ -0,0 +1,425 @@
+@@ -0,0 +1,433 @@
+/*
+ * pvrusb2-dvb.c - linux-dvb api interface to the pvrusb2 driver.
+ *
@@ -406968,6 +573228,7 @@
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include "dvbdev.h"
++#include "pvrusb2-debug.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-io.h"
@@ -406982,7 +573243,7 @@
+ struct pvr2_buffer *bp;
+ struct pvr2_stream *stream;
+
-+ printk(KERN_DEBUG "dvb thread started\n");
++ pvr2_trace(PVR2_TRACE_DVB_FEED, "dvb feed thread started");
+ set_freezable();
+
+ stream = adap->channel.stream->stream;
@@ -407029,7 +573290,7 @@
+ /* 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");
++ pvr2_trace(PVR2_TRACE_DVB_FEED, "dvb feed thread stopped");
+
+ return 0;
+}
@@ -407077,7 +573338,7 @@
+ 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->buffer_storage[idx] = NULL;
+ }
+ adap->stream_run = 0;
+ }
@@ -407089,7 +573350,7 @@
+ unsigned int idx;
+ int ret;
+ struct pvr2_buffer *bp;
-+ struct pvr2_stream *stream = 0;
++ struct pvr2_stream *stream = NULL;
+
+ if (adap->stream_run) return -EIO;
+
@@ -407121,7 +573382,7 @@
+ ret = pvr2_hdw_set_streaming(adap->channel.hdw, 1);
+ if (ret < 0) return ret;
+
-+ while ((bp = pvr2_stream_get_idle_buffer(stream)) != 0) {
++ while ((bp = pvr2_stream_get_idle_buffer(stream)) != NULL) {
+ ret = pvr2_buffer_queue(bp);
+ if (ret < 0) return ret;
+ }
@@ -407157,7 +573418,8 @@
+ do {
+ if (onoff) {
+ if (!adap->feedcount) {
-+ printk(KERN_DEBUG "start feeding\n");
++ pvr2_trace(PVR2_TRACE_DVB_FEED,
++ "start feeding demux");
+ ret = pvr2_dvb_stream_start(adap);
+ if (ret < 0) break;
+ }
@@ -407165,7 +573427,8 @@
+ } else if (adap->feedcount > 0) {
+ (adap->feedcount)--;
+ if (!adap->feedcount) {
-+ printk(KERN_DEBUG "stop feeding\n");
++ pvr2_trace(PVR2_TRACE_DVB_FEED,
++ "stop feeding demux");
+ pvr2_dvb_stream_end(adap);
+ }
+ }
@@ -407177,15 +573440,13 @@
+
+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);
++ pvr2_trace(PVR2_TRACE_DVB_FEED, "start pid: 0x%04x", dvbdmxfeed->pid);
+ 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);
++ pvr2_trace(PVR2_TRACE_DVB_FEED, "stop pid: 0x%04x", dvbdmxfeed->pid);
+ return pvr2_dvb_ctrl_feed(dvbdmxfeed, 0);
+}
+
@@ -407206,7 +573467,8 @@
+ &adap->channel.hdw->usb_dev->dev,
+ adapter_nr);
+ if (ret < 0) {
-+ err("dvb_register_adapter failed: error %d", ret);
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++ "dvb_register_adapter failed: error %d", ret);
+ goto err;
+ }
+ adap->dvb_adap.priv = adap;
@@ -407223,7 +573485,8 @@
+
+ ret = dvb_dmx_init(&adap->demux);
+ if (ret < 0) {
-+ err("dvb_dmx_init failed: error %d", ret);
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++ "dvb_dmx_init failed: error %d", ret);
+ goto err_dmx;
+ }
+
@@ -407233,7 +573496,8 @@
+
+ ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap);
+ if (ret < 0) {
-+ err("dvb_dmxdev_init failed: error %d", ret);
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++ "dvb_dmxdev_init failed: error %d", ret);
+ goto err_dmx_dev;
+ }
+
@@ -407251,7 +573515,7 @@
+
+static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap)
+{
-+ printk(KERN_DEBUG "unregistering DVB devices\n");
++ pvr2_trace(PVR2_TRACE_INFO, "unregistering DVB devices");
+ dvb_net_release(&adap->dvb_net);
+ adap->demux.dmx.close(&adap->demux.dmx);
+ dvb_dmxdev_release(&adap->dmxdev);
@@ -407267,7 +573531,7 @@
+ int ret = 0;
+
+ if (dvb_props == NULL) {
-+ err("fe_props not defined!");
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS, "fe_props not defined!");
+ return -EINVAL;
+ }
+
@@ -407275,13 +573539,15 @@
+ &adap->channel,
+ (1 << PVR2_CVAL_INPUT_DTV));
+ if (ret) {
-+ err("failed to grab control of dtv input (code=%d)",
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++ "failed to grab control of dtv input (code=%d)",
+ ret);
+ return ret;
+ }
+
+ if (dvb_props->frontend_attach == NULL) {
-+ err("frontend_attach not defined!");
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++ "frontend_attach not defined!");
+ ret = -EINVAL;
+ goto done;
+ }
@@ -407289,7 +573555,8 @@
+ if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) {
+
+ if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
-+ err("frontend registration failed!");
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++ "frontend registration failed!");
+ dvb_frontend_detach(adap->fe);
+ adap->fe = NULL;
+ ret = -ENODEV;
@@ -407306,7 +573573,8 @@
+ adap->fe->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
+
+ } else {
-+ err("no frontend was attached!");
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++ "no frontend was attached!");
+ ret = -ENODEV;
+ return ret;
+ }
@@ -409361,7 +575629,7 @@
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
+index 8f0587e..e9b5d4e 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 {
@@ -409649,10 +575917,23 @@
+ fail:
+ pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
+ pvr2_v4l2_destroy_no_lock(vp);
-+ return 0;
++ return NULL;
}
/*
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
+index 7c47345..2433a31 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
+@@ -81,7 +81,7 @@ static void set_input(struct pvr2_v4l_decoder *ctxt)
+ pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_input(%d)",hdw->input_val);
+
+ if ((sid < ARRAY_SIZE(routing_schemes)) &&
+- ((sp = routing_schemes + sid) != 0) &&
++ ((sp = routing_schemes + sid) != NULL) &&
+ (hdw->input_val >= 0) &&
+ (hdw->input_val < sp->cnt)) {
+ route.input = sp->def[hdw->input_val];
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
@@ -411017,7 +577298,7 @@
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
+index 41e5e51..e684108 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, "
@@ -411038,6 +577319,16 @@
reg |= 0x20;
} else if (std == V4L2_STD_PAL_60) {
reg |= 0x10;
+@@ -1450,7 +1450,8 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
+
+ /* ----------------------------------------------------------------------- */
+
+-static int saa7115_probe(struct i2c_client *client)
++static int saa7115_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct saa711x_state *state;
+ int i;
diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c
index 80bf911..cedb988 100644
--- a/drivers/media/video/saa711x.c
@@ -411051,18 +577342,55 @@
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/saa7127.c b/drivers/media/video/saa7127.c
+index 06c88db..e750cd6 100644
+--- a/drivers/media/video/saa7127.c
++++ b/drivers/media/video/saa7127.c
+@@ -661,7 +661,8 @@ static int saa7127_command(struct i2c_client *client,
+
+ /* ----------------------------------------------------------------------- */
+
+-static int saa7127_probe(struct i2c_client *client)
++static int saa7127_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct saa7127_state *state;
+ struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 }; /* set to disabled */
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
-index 96bc3b1..e086f14 100644
+index 96bc3b1..40e4c3b 100644
--- a/drivers/media/video/saa7134/Kconfig
+++ b/drivers/media/video/saa7134/Kconfig
-@@ -37,6 +37,7 @@ config VIDEO_SAA7134_DVB
+@@ -3,7 +3,7 @@ config VIDEO_SAA7134
+ depends on VIDEO_DEV && PCI && I2C && INPUT
+ select VIDEOBUF_DMA_SG
+ select VIDEO_IR
+- select VIDEO_TUNER
++ select MEDIA_TUNER
+ select VIDEO_TVEEPROM
+ select CRC32
+ ---help---
+@@ -35,8 +35,9 @@ config VIDEO_SAA7134_DVB
+ select DVB_NXT200X if !DVB_FE_CUSTOMISE
+ select DVB_TDA10086 if !DVB_FE_CUSTOMISE
select DVB_TDA826X if !DVB_FE_CUSTOMISE
- select DVB_TDA827X if !DVB_FE_CUSTOMISE
+- select DVB_TDA827X if !DVB_FE_CUSTOMISE
++ select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE
select DVB_ISL6421 if !DVB_FE_CUSTOMISE
-+ select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
++ select MEDIA_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/Makefile b/drivers/media/video/saa7134/Makefile
+index 9aff937..3dbaa19 100644
+--- a/drivers/media/video/saa7134/Makefile
++++ b/drivers/media/video/saa7134/Makefile
+@@ -11,5 +11,6 @@ obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o
+ obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
+
+ EXTRA_CFLAGS += -Idrivers/media/video
++EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+ EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
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
@@ -411131,7 +577459,7 @@
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
+index 6f57442..b111903 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -22,11 +22,15 @@
@@ -411150,7 +577478,17 @@
/* commly used strings */
static char name_mute[] = "mute";
-@@ -1046,7 +1050,7 @@ struct saa7134_board saa7134_boards[] = {
+@@ -43,6 +47,9 @@ static char name_svideo[] = "S-Video";
+ /* ------------------------------------------------------------------ */
+ /* board config info */
+
++/* If radio_type !=UNSET, radio_addr should be specified
++ */
++
+ struct saa7134_board saa7134_boards[] = {
+ [SAA7134_BOARD_UNKNOWN] = {
+ .name = "UNKNOWN/GENERIC",
+@@ -1046,7 +1053,7 @@ struct saa7134_board saa7134_boards[] = {
},
[SAA7134_BOARD_MANLI_MTV002] = {
/* Ognjen Nastic <ognjen at logosoft.ba> */
@@ -411159,7 +577497,7 @@
.audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_PAL,
.radio_type = UNSET,
-@@ -1073,7 +1077,7 @@ struct saa7134_board saa7134_boards[] = {
+@@ -1073,7 +1080,7 @@ struct saa7134_board saa7134_boards[] = {
},
[SAA7134_BOARD_MANLI_MTV001] = {
/* Ognjen Nastic <ognjen at logosoft.ba> UNTESTED */
@@ -411168,7 +577506,7 @@
.audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_PAL,
.radio_type = UNSET,
-@@ -2195,6 +2199,8 @@ struct saa7134_board saa7134_boards[] = {
+@@ -2195,6 +2202,8 @@ struct saa7134_board saa7134_boards[] = {
},
[SAA7134_BOARD_BEHOLD_409FM] = {
/* <http://tuner.beholder.ru>, Sergey <skiv at orel.ru> */
@@ -411177,7 +577515,7 @@
.name = "Beholder BeholdTV 409 FM",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
-@@ -2202,6 +2208,7 @@ struct saa7134_board saa7134_boards[] = {
+@@ -2202,6 +2211,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
@@ -411185,7 +577523,7 @@
.inputs = {{
.name = name_tv,
.vmux = 3,
-@@ -2908,15 +2915,13 @@ struct saa7134_board saa7134_boards[] = {
+@@ -2908,15 +2918,13 @@ struct saa7134_board saa7134_boards[] = {
}},
},
[SAA7134_BOARD_MD7134_BRIDGE_2] = {
@@ -411203,7 +577541,16 @@
},
[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[] = {
+@@ -3082,7 +3090,7 @@ struct saa7134_board saa7134_boards[] = {
+ .tuner_type = TUNER_PHILIPS_TD1316, /* untested */
+ .radio_type = TUNER_TEA5767, /* untested */
+ .tuner_addr = ADDR_UNSET,
+- .radio_addr = ADDR_UNSET,
++ .radio_addr = 0x60,
+ .tda9887_conf = TDA9887_PRESENT,
+ .mpeg = SAA7134_MPEG_DVB,
+ .inputs = {{
+@@ -3330,7 +3338,7 @@ struct saa7134_board saa7134_boards[] = {
/* Juan Pablo Sormani <sorman at gmail.com> */
.name = "Encore ENLTV-FM",
.audio_clock = 0x00200000,
@@ -411212,7 +577559,7 @@
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
-@@ -3575,12 +3580,15 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3575,12 +3583,15 @@ struct saa7134_board saa7134_boards[] = {
}},
},
[SAA7134_BOARD_BEHOLD_401] = {
@@ -411228,7 +577575,7 @@
.inputs = {{
.name = name_svideo,
.vmux = 8,
-@@ -3601,12 +3609,15 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3601,12 +3612,15 @@ struct saa7134_board saa7134_boards[] = {
},
},
[SAA7134_BOARD_BEHOLD_403] = {
@@ -411244,7 +577591,7 @@
.inputs = {{
.name = name_svideo,
.vmux = 8,
-@@ -3623,12 +3634,15 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3623,12 +3637,15 @@ struct saa7134_board saa7134_boards[] = {
}},
},
[SAA7134_BOARD_BEHOLD_403FM] = {
@@ -411260,7 +577607,7 @@
.inputs = {{
.name = name_svideo,
.vmux = 8,
-@@ -3649,6 +3663,8 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3649,6 +3666,8 @@ struct saa7134_board saa7134_boards[] = {
},
},
[SAA7134_BOARD_BEHOLD_405] = {
@@ -411269,7 +577616,7 @@
.name = "Beholder BeholdTV 405",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
-@@ -3656,6 +3672,7 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3656,6 +3675,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
@@ -411277,7 +577624,7 @@
.inputs = {{
.name = name_svideo,
.vmux = 8,
-@@ -3673,6 +3690,8 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3673,6 +3693,8 @@ struct saa7134_board saa7134_boards[] = {
},
[SAA7134_BOARD_BEHOLD_405FM] = {
/* Sergey <skiv at orel.ru> */
@@ -411286,7 +577633,7 @@
.name = "Beholder BeholdTV 405 FM",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
-@@ -3680,6 +3699,7 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3680,6 +3702,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
@@ -411294,7 +577641,7 @@
.inputs = {{
.name = name_svideo,
.vmux = 8,
-@@ -3700,6 +3720,8 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3700,6 +3723,8 @@ struct saa7134_board saa7134_boards[] = {
},
},
[SAA7134_BOARD_BEHOLD_407] = {
@@ -411303,7 +577650,7 @@
.name = "Beholder BeholdTV 407",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
-@@ -3707,7 +3729,7 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3707,7 +3732,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
@@ -411312,7 +577659,7 @@
.inputs = {{
.name = name_svideo,
.vmux = 8,
-@@ -3727,6 +3749,8 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3727,6 +3752,8 @@ struct saa7134_board saa7134_boards[] = {
}},
},
[SAA7134_BOARD_BEHOLD_407FM] = {
@@ -411321,7 +577668,7 @@
.name = "Beholder BeholdTV 407 FM",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
-@@ -3734,7 +3758,7 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3734,7 +3761,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
@@ -411330,7 +577677,7 @@
.inputs = {{
.name = name_svideo,
.vmux = 8,
-@@ -3759,6 +3783,8 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3759,6 +3786,8 @@ struct saa7134_board saa7134_boards[] = {
},
},
[SAA7134_BOARD_BEHOLD_409] = {
@@ -411339,7 +577686,7 @@
.name = "Beholder BeholdTV 409",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
-@@ -3766,6 +3792,7 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3766,6 +3795,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
@@ -411347,7 +577694,7 @@
.inputs = {{
.name = name_tv,
.vmux = 3,
-@@ -3782,6 +3809,8 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3782,6 +3812,8 @@ struct saa7134_board saa7134_boards[] = {
}},
},
[SAA7134_BOARD_BEHOLD_505FM] = {
@@ -411356,7 +577703,7 @@
.name = "Beholder BeholdTV 505 FM/RDS",
.audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
-@@ -3789,6 +3818,7 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3789,6 +3821,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
@@ -411364,7 +577711,7 @@
.inputs = {{
.name = name_tv,
.vmux = 3,
-@@ -3813,6 +3843,8 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3813,6 +3846,8 @@ struct saa7134_board saa7134_boards[] = {
},
},
[SAA7134_BOARD_BEHOLD_507_9FM] = {
@@ -411373,7 +577720,7 @@
.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[] = {
+@@ -3820,6 +3855,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
@@ -411381,7 +577728,7 @@
.inputs = {{
.name = name_tv,
.vmux = 3,
-@@ -3840,6 +3873,8 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3840,6 +3876,8 @@ struct saa7134_board saa7134_boards[] = {
},
},
[SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = {
@@ -411390,7 +577737,7 @@
.name = "Beholder BeholdTV Columbus TVFM",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_ALPS_TSBE5_PAL,
-@@ -3847,23 +3882,28 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3847,23 +3885,28 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
@@ -411422,7 +577769,7 @@
},
},
[SAA7134_BOARD_BEHOLD_607_9FM] = {
-@@ -3992,6 +4032,221 @@ struct saa7134_board saa7134_boards[] = {
+@@ -3992,6 +4035,251 @@ struct saa7134_board saa7134_boards[] = {
.gpio = 0x6000,
},
},
@@ -411641,10 +577988,40 @@
+ .amux = LINE1,
+ } },
+ },
++ [SAA7134_BOARD_BEHOLD_H6] = {
++ /* Igor Kuznetsov <igk at igk.ru> */
++ .name = "Beholder BeholdTV H6",
++ .audio_clock = 0x00187de7,
++ .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
++ .radio_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ .tda9887_conf = TDA9887_PRESENT,
++ .inputs = {{
++ .name = name_tv,
++ .vmux = 3,
++ .amux = TV,
++ .tv = 1,
++ }, {
++ .name = name_comp1,
++ .vmux = 1,
++ .amux = LINE1,
++ }, {
++ .name = name_svideo,
++ .vmux = 8,
++ .amux = LINE1,
++ } },
++ .radio = {
++ .name = name_radio,
++ .amux = LINE2,
++ },
++ /* no DVB support for now */
++ /* .mpeg = SAA7134_MPEG_DVB, */
++ },
};
const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
-@@ -4224,6 +4479,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
+@@ -4224,6 +4512,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
.driver_data = SAA7134_BOARD_MD2819,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
@@ -411663,7 +578040,20 @@
.device = PCI_DEVICE_ID_PHILIPS_SAA7130,
.subvendor = 0x1461, /* Avermedia Technologies Inc */
.subdevice = 0x2115,
-@@ -4942,7 +5209,43 @@ struct pci_device_id saa7134_pci_tbl[] = {
+@@ -4930,6 +5230,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
+ .subvendor = 0x5ace,
+ .subdevice = 0x6193,
+ .driver_data = SAA7134_BOARD_BEHOLD_M6,
++ }, {
++ .vendor = PCI_VENDOR_ID_PHILIPS,
++ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
++ .subvendor = 0x5ace,
++ .subdevice = 0x6191,
++ .driver_data = SAA7134_BOARD_BEHOLD_M6,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+@@ -4942,7 +5248,49 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subvendor = 0x1822, /*Twinhan Technology Co. Ltd*/
.subdevice = 0x0022,
.driver_data = SAA7134_BOARD_TWINHAN_DTV_DVB_3056,
@@ -411704,10 +578094,16 @@
+ .subdevice = 0xc900,
+ .driver_data = SAA7134_BOARD_VIDEOMATE_T750,
+ }, {
++ .vendor = PCI_VENDOR_ID_PHILIPS,
++ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
++ .subvendor = 0x5ace,
++ .subdevice = 0x6290,
++ .driver_data = SAA7134_BOARD_BEHOLD_H6,
++ }, {
/* --- 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)
+@@ -4998,6 +5346,77 @@ static void board_flyvideo(struct saa7134_dev *dev)
dev->name, dev->name, dev->name);
}
@@ -411785,7 +578181,7 @@
/* ----------------------------------------------------------- */
static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data)
-@@ -5067,6 +5441,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
+@@ -5067,6 +5486,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:
@@ -411793,7 +578189,7 @@
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)
+@@ -5133,11 +5553,29 @@ int saa7134_board_init1(struct saa7134_dev *dev)
saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08000000, 0x00000000);
break;
case SAA7134_BOARD_AVERMEDIA_CARDBUS:
@@ -411825,7 +578221,7 @@
break;
case SAA7134_BOARD_RTD_VFG7350:
-@@ -5160,7 +5553,6 @@ int saa7134_board_init1(struct saa7134_dev *dev)
+@@ -5160,7 +5598,6 @@ int saa7134_board_init1(struct saa7134_dev *dev)
dev->has_remote = SAA7134_REMOTE_I2C;
break;
case SAA7134_BOARD_AVERMEDIA_A169_B:
@@ -411833,7 +578229,7 @@
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)
+@@ -5172,24 +5609,100 @@ 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;
@@ -411849,43 +578245,139 @@
}
return 0;
}
-@@ -5200,11 +5601,16 @@ int saa7134_board_init2(struct saa7134_dev *dev)
+
++static void saa7134_tuner_setup(struct saa7134_dev *dev)
++{
++ struct tuner_setup tun_setup;
++ unsigned int mode_mask = T_RADIO |
++ T_ANALOG_TV |
++ T_DIGITAL_TV;
++
++ memset(&tun_setup, 0, sizeof(tun_setup));
++ tun_setup.tuner_callback = saa7134_tuner_callback;
++
++ if (saa7134_boards[dev->board].radio_type != UNSET) {
++ tun_setup.type = saa7134_boards[dev->board].radio_type;
++ tun_setup.addr = saa7134_boards[dev->board].radio_addr;
++
++ tun_setup.mode_mask = T_RADIO;
++
++ saa7134_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
++ mode_mask &= ~T_RADIO;
++ }
++
++ if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type != UNSET)) {
++ tun_setup.type = dev->tuner_type;
++ tun_setup.addr = dev->tuner_addr;
++ tun_setup.config = saa7134_boards[dev->board].tuner_config;
++ tun_setup.tuner_callback = saa7134_tuner_callback;
++
++ tun_setup.mode_mask = mode_mask;
++
++ saa7134_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
++ }
++
++ if (dev->tda9887_conf) {
++ struct v4l2_priv_tun_config tda9887_cfg;
++
++ tda9887_cfg.tuner = TUNER_TDA9887;
++ tda9887_cfg.priv = &dev->tda9887_conf;
++
++ saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG,
++ &tda9887_cfg);
++ }
++
++ 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);
++ }
++}
++
+ /* stuff which needs working i2c */
+ int saa7134_board_init2(struct saa7134_dev *dev)
+ {
+ unsigned char buf;
+ int board;
+- struct tuner_setup tun_setup;
+- tun_setup.config = 0;
+- tun_setup.tuner_callback = saa7134_tuner_callback;
++
++ dev->tuner_type = saa7134_boards[dev->board].tuner_type;
++ dev->tuner_addr = saa7134_boards[dev->board].tuner_addr;
+
+ switch (dev->board) {
+ case SAA7134_BOARD_BMK_MPEX_NOTUNER:
+ case SAA7134_BOARD_BMK_MPEX_TUNER:
+ dev->i2c_client.addr = 0x60;
+- board = (i2c_master_recv(&dev->i2c_client,&buf,0) < 0)
++ board = (i2c_master_recv(&dev->i2c_client, &buf, 0) < 0)
+ ? SAA7134_BOARD_BMK_MPEX_NOTUNER
+ : SAA7134_BOARD_BMK_MPEX_TUNER;
+ if (board == dev->board)
+@@ -5199,16 +5712,9 @@ int saa7134_board_init2(struct saa7134_dev *dev)
+ saa7134_boards[dev->board].name);
dev->tuner_type = saa7134_boards[dev->board].tuner_type;
- if (TUNER_ABSENT != dev->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);
+- {
++ {
+ u8 subaddr;
+ u8 data[3];
+ int ret, tuner_t;
+@@ -5261,67 +5767,56 @@ int saa7134_board_init2(struct saa7134_dev *dev)
}
+ printk(KERN_INFO "%s Tuner type is %d\n", dev->name, dev->tuner_type);
+- if (dev->tuner_type == TUNER_PHILIPS_FMD1216ME_MK3) {
+- struct v4l2_priv_tun_config tda9887_cfg;
+-
+- tda9887_cfg.tuner = TUNER_TDA9887;
+- tda9887_cfg.priv = &dev->tda9887_conf;
+-
+- dev->tda9887_conf = TDA9887_PRESENT |
+- TDA9887_PORT1_ACTIVE |
+- TDA9887_PORT2_ACTIVE;
+-
+- saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG,
+- &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;
-
+- 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 */
@@ -411897,21 +578389,143 @@
+ }
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)
+ * the channel decoder. We have to make it transparent to find it
+ */
+- {
+ u8 data[] = { 0x07, 0x02};
+ struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
+
+- tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
+- tun_setup.type = dev->tuner_type;
+- tun_setup.addr = dev->tuner_addr;
+-
+- saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup);
+- }
+ break;
++ }
+ case SAA7134_BOARD_PHILIPS_TIGER:
+ case SAA7134_BOARD_PHILIPS_TIGER_S:
+- {
++ {
+ u8 data[] = { 0x3c, 0x33, 0x60};
+ struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+- if(dev->autodetected && (dev->eedata[0x49] == 0x50)) {
++ if (dev->autodetected && (dev->eedata[0x49] == 0x50)) {
+ dev->board = SAA7134_BOARD_PHILIPS_TIGER_S;
+ printk(KERN_INFO "%s: Reconfigured board as %s\n",
+ dev->name, saa7134_boards[dev->board].name);
+ }
+- if(dev->board == SAA7134_BOARD_PHILIPS_TIGER_S) {
+- tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
+- tun_setup.type = TUNER_PHILIPS_TDA8290;
+- tun_setup.addr = 0x4b;
+- tun_setup.config = 2;
++ if (dev->board == SAA7134_BOARD_PHILIPS_TIGER_S) {
++ dev->tuner_type = TUNER_PHILIPS_TDA8290;
++
++ saa7134_tuner_setup(dev);
+
+- saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup);
+ data[2] = 0x68;
++ i2c_transfer(&dev->i2c_adap, &msg, 1);
++
++ /* Tuner setup is handled before I2C transfer.
++ Due to that, there's no need to do it later
++ */
++ return 0;
+ }
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
+- }
+ break;
++ }
+ case SAA7134_BOARD_HAUPPAUGE_HVR1110:
+ hauppauge_eeprom(dev, dev->eedata+0x80);
+ /* break intentionally omitted */
+@@ -5333,52 +5828,56 @@ 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)
+- {
+ u8 data[] = { 0x3c, 0x33, 0x60};
+ struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
+- }
+ break;
++ }
+ case SAA7134_BOARD_FLYDVB_TRIO:
+- {
++ {
+ u8 data[] = { 0x3c, 0x33, 0x62};
+ struct i2c_msg msg = {.addr=0x09, .flags=0, .buf=data, .len = sizeof(data)};
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
+- }
+ break;
++ }
+ case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
+ case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
++ {
+ /* initialize analog mode */
+- {
+ u8 data[] = { 0x3c, 0x33, 0x6a};
+ struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
+- }
+ break;
++ }
+ case SAA7134_BOARD_CINERGY_HT_PCMCIA:
+ case SAA7134_BOARD_CINERGY_HT_PCI:
++ {
+ /* initialize analog mode */
+- {
+ u8 data[] = { 0x3c, 0x33, 0x68};
+ struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
+- }
+ break;
++ }
+ case SAA7134_BOARD_KWORLD_ATSC110:
+- {
+- /* enable tuner */
+- int i;
+- static const u8 buffer [] = { 0x10,0x12,0x13,0x04,0x16,0x00,0x14,0x04,0x017,0x00 };
+- dev->i2c_client.addr = 0x0a;
+- for (i = 0; i < 5; i++)
+- if (2 != i2c_master_send(&dev->i2c_client,&buffer[i*2],2))
+- printk(KERN_WARNING "%s: Unable to enable tuner(%i).\n",
+- dev->name, i);
+- }
++ {
++ /* enable tuner */
++ int i;
++ static const u8 buffer [] = { 0x10, 0x12, 0x13, 0x04, 0x16,
++ 0x00, 0x14, 0x04, 0x17, 0x00 };
++ dev->i2c_client.addr = 0x0a;
++ for (i = 0; i < 5; i++)
++ if (2 != i2c_master_send(&dev->i2c_client,
++ &buffer[i*2], 2))
++ printk(KERN_WARNING
++ "%s: Unable to enable tuner(%i).\n",
++ dev->name, i);
+ break;
++ }
+ case SAA7134_BOARD_VIDEOMATE_DVBT_200:
+ case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
+ /* The T200 and the T200A share the same pci id. Consequently,
+@@ -5402,13 +5901,23 @@ 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;
+
@@ -411922,34 +578536,11 @@
+ tea5767_cfg.tuner = TUNER_TEA5767;
+ tea5767_cfg.priv = &ctl;
+ saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tea5767_cfg);
-+ }
+ break;
}
++ } /* switch() */
+
-+ 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);
-+ }
++ saa7134_tuner_setup(dev);
+
return 0;
}
@@ -412879,7 +579470,7 @@
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
+index d3322c3..d8af386 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -33,11 +33,11 @@
@@ -412905,8 +579496,64 @@
return true;
default:
return false;
+@@ -322,8 +324,6 @@ static u32 functionality(struct i2c_adapter *adap)
+ static int attach_inform(struct i2c_client *client)
+ {
+ struct saa7134_dev *dev = client->adapter->algo_data;
+- int tuner = dev->tuner_type;
+- struct tuner_setup tun_setup;
+
+ d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
+ client->driver->driver.name, client->addr, client->name);
+@@ -344,46 +344,6 @@ static int attach_inform(struct i2c_client *client)
+ }
+ }
+
+- if (!client->driver->command)
+- return 0;
+-
+- if (saa7134_boards[dev->board].radio_type != UNSET) {
+-
+- tun_setup.type = saa7134_boards[dev->board].radio_type;
+- tun_setup.addr = saa7134_boards[dev->board].radio_addr;
+-
+- if ((tun_setup.addr == ADDR_UNSET) || (tun_setup.addr == client->addr)) {
+- tun_setup.mode_mask = T_RADIO;
+-
+- client->driver->command(client, TUNER_SET_TYPE_ADDR, &tun_setup);
+- }
+- }
+-
+- if (tuner != UNSET) {
+- tun_setup.type = tuner;
+- tun_setup.addr = saa7134_boards[dev->board].tuner_addr;
+- tun_setup.config = saa7134_boards[dev->board].tuner_config;
+- tun_setup.tuner_callback = saa7134_tuner_callback;
+-
+- if ((tun_setup.addr == ADDR_UNSET)||(tun_setup.addr == client->addr)) {
+-
+- tun_setup.mode_mask = T_ANALOG_TV;
+-
+- client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_setup);
+- }
+-
+- if (tuner == TUNER_TDA9887) {
+- struct v4l2_priv_tun_config tda9887_cfg;
+-
+- tda9887_cfg.tuner = TUNER_TDA9887;
+- tda9887_cfg.priv = &dev->tda9887_conf;
+-
+- client->driver->command(client, TUNER_SET_CONFIG,
+- &tda9887_cfg);
+- }
+- }
+-
+-
+ return 0;
+ }
+
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
-index b418881..767ff30 100644
+index b418881..919632b 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -27,15 +27,15 @@
@@ -412955,6 +579602,14 @@
mask_keyup = 0x004000;
polling = 50; // ms
break;
+@@ -520,6 +531,7 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
+ break;
+ case SAA7134_BOARD_BEHOLD_607_9FM:
+ case SAA7134_BOARD_BEHOLD_M6:
++ case SAA7134_BOARD_BEHOLD_H6:
+ snprintf(ir->c.name, sizeof(ir->c.name), "BeholdTV");
+ ir->get_key = get_key_beholdm6xx;
+ ir->ir_codes = ir_codes_behold;
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
@@ -413098,10 +579753,10 @@
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
+index f940d02..34ff0d4 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
-@@ -253,7 +253,17 @@ struct saa7134_format {
+@@ -253,7 +253,18 @@ struct saa7134_format {
#define SAA7134_BOARD_BEHOLD_607_9FM 129
#define SAA7134_BOARD_BEHOLD_M6 130
#define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131
@@ -413116,11 +579771,12 @@
+#define SAA7134_BOARD_VIDEOMATE_T750 139
+#define SAA7134_BOARD_AVERMEDIA_A700_PRO 140
+#define SAA7134_BOARD_AVERMEDIA_A700_HYBRID 141
++#define SAA7134_BOARD_BEHOLD_H6 142
+
#define SAA7134_MAXBOARDS 8
#define SAA7134_INPUT_MAX 8
-@@ -380,9 +390,7 @@ struct saa7134_fh {
+@@ -380,9 +391,7 @@ struct saa7134_fh {
unsigned int radio;
enum v4l2_buf_type type;
unsigned int resources;
@@ -413130,7 +579786,7 @@
/* video overlay */
struct v4l2_window win;
-@@ -454,9 +462,7 @@ struct saa7134_dev {
+@@ -454,9 +463,7 @@ struct saa7134_dev {
struct list_head devlist;
struct mutex lock;
spinlock_t slock;
@@ -413140,7 +579796,7 @@
/* workstruct for loading modules */
struct work_struct request_module_wk;
-@@ -556,7 +562,9 @@ struct saa7134_dev {
+@@ -556,7 +563,9 @@ struct saa7134_dev {
#if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
/* SAA7134_MPEG_DVB only */
struct videobuf_dvb dvb;
@@ -413151,7 +579807,7 @@
#endif
};
-@@ -594,7 +602,6 @@ extern int saa7134_no_overlay;
+@@ -594,7 +603,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);
@@ -413159,7 +579815,7 @@
#define SAA7134_PGTABLE_SIZE 4096
-@@ -631,6 +638,7 @@ extern struct pci_device_id __devinitdata saa7134_pci_tbl[];
+@@ -631,6 +639,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);
@@ -413169,10 +579825,10 @@
/* ----------------------------------------------------------- */
diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c
new file mode 100644
-index 0000000..53c5edb
+index 0000000..72c4081
--- /dev/null
+++ b/drivers/media/video/saa717x.c
-@@ -0,0 +1,1516 @@
+@@ -0,0 +1,1517 @@
+/*
+ * saa717x - Philips SAA717xHL video decoder driver
+ *
@@ -414593,7 +581249,8 @@
+/* i2c implementation */
+
+/* ----------------------------------------------------------------------- */
-+static int saa717x_probe(struct i2c_client *client)
++static int saa717x_probe(struct i2c_client *client,
++ const struct i2c_device_id *did)
+{
+ struct saa717x_state *decoder;
+ u8 id = 0;
@@ -415993,10 +582650,20 @@
};
static struct video_device stv680_template = {
diff --git a/drivers/media/video/tcm825x.c b/drivers/media/video/tcm825x.c
-index fb895f6..6943b44 100644
+index fb895f6..e57a646 100644
--- a/drivers/media/video/tcm825x.c
+++ b/drivers/media/video/tcm825x.c
-@@ -906,7 +906,7 @@ static int __init tcm825x_init(void)
+@@ -840,7 +840,8 @@ static struct v4l2_int_device tcm825x_int_device = {
+ },
+ };
+
+-static int tcm825x_probe(struct i2c_client *client)
++static int tcm825x_probe(struct i2c_client *client,
++ const struct i2c_device_id *did)
+ {
+ struct tcm825x_sensor *sensor = &tcm825x;
+ int rval;
+@@ -906,7 +907,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",
@@ -416006,114 +582673,880 @@
return rval;
}
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c
-index 55bc89a..0ebb5b5 100644
+deleted file mode 100644
+index 55bc89a..0000000
--- 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");
-
++++ /dev/null
+@@ -1,806 +0,0 @@
+-/*
+-
+- i2c tv tuner chip device driver
+- controls the philips tda8290+75 tuner chip combo.
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2 of the License, or
+- (at your option) any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
+-
+- You 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.
+-
+- This "tda8290" module was split apart from the original "tuner" module.
+-*/
+-
+-#include <linux/i2c.h>
+-#include <linux/delay.h>
+-#include <linux/videodev.h>
+-#include "tuner-i2c.h"
+-#include "tda8290.h"
+-#include "tda827x.h"
+-#include "tda18271.h"
+-
+-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)
+-/* ---------------------------------------------------------------------- */
+-
+-struct tda8290_priv {
+- struct tuner_i2c_props i2c_props;
+-
+- unsigned char tda8290_easy_mode;
+-
+- unsigned char tda827x_addr;
+-
+- unsigned char ver;
+-#define TDA8290 1
+-#define TDA8295 2
+-#define TDA8275 4
+-#define TDA8275A 8
+-#define TDA18271 16
+-
+- struct tda827x_config cfg;
+-};
+-
+-/*---------------------------------------------------------------------*/
+-
+-static int tda8290_i2c_bridge(struct dvb_frontend *fe, int close)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+-
+- unsigned char enable[2] = { 0x21, 0xC0 };
+- unsigned char disable[2] = { 0x21, 0x00 };
+- unsigned char *msg;
+-
+- if (close) {
+- msg = enable;
+- tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
+- /* let the bridge stabilize */
+- msleep(20);
+- } else {
+- msg = disable;
+- tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
+- }
+-
+- return 0;
+-}
+-
+-static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+-
+- unsigned char enable[2] = { 0x45, 0xc1 };
+- unsigned char disable[2] = { 0x46, 0x00 };
+- unsigned char buf[3] = { 0x45, 0x01, 0x00 };
+- unsigned char *msg;
+-
+- if (close) {
+- msg = enable;
+- tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
+- /* let the bridge stabilize */
+- msleep(20);
+- } else {
+- msg = disable;
+- tuner_i2c_xfer_send(&priv->i2c_props, msg, 1);
+- tuner_i2c_xfer_recv(&priv->i2c_props, &msg[1], 1);
+-
+- buf[2] = msg[1];
+- buf[2] &= ~0x04;
+- tuner_i2c_xfer_send(&priv->i2c_props, buf, 3);
+- msleep(5);
+-
+- msg[1] |= 0x04;
+- tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
+- }
+-
+- return 0;
+-}
+-
+-/*---------------------------------------------------------------------*/
+-
+-static void set_audio(struct dvb_frontend *fe,
+- struct analog_parameters *params)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+- char* mode;
+-
+- if (params->std & V4L2_STD_MN) {
+- priv->tda8290_easy_mode = 0x01;
+- mode = "MN";
+- } else if (params->std & V4L2_STD_B) {
+- priv->tda8290_easy_mode = 0x02;
+- mode = "B";
+- } else if (params->std & V4L2_STD_GH) {
+- priv->tda8290_easy_mode = 0x04;
+- mode = "GH";
+- } else if (params->std & V4L2_STD_PAL_I) {
+- priv->tda8290_easy_mode = 0x08;
+- mode = "I";
+- } else if (params->std & V4L2_STD_DK) {
+- priv->tda8290_easy_mode = 0x10;
+- mode = "DK";
+- } else if (params->std & V4L2_STD_SECAM_L) {
+- priv->tda8290_easy_mode = 0x20;
+- mode = "L";
+- } else if (params->std & V4L2_STD_SECAM_LC) {
+- priv->tda8290_easy_mode = 0x40;
+- mode = "LC";
+- } else {
+- priv->tda8290_easy_mode = 0x10;
+- mode = "xx";
+- }
+-
+- tuner_dbg("setting tda829x to system %s\n", mode);
+-}
+-
+-static void tda8290_set_params(struct dvb_frontend *fe,
+- struct analog_parameters *params)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+-
+- unsigned char soft_reset[] = { 0x00, 0x00 };
+- unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode };
+- unsigned char expert_mode[] = { 0x01, 0x80 };
+- unsigned char agc_out_on[] = { 0x02, 0x00 };
+- unsigned char gainset_off[] = { 0x28, 0x14 };
+- unsigned char if_agc_spd[] = { 0x0f, 0x88 };
+- unsigned char adc_head_6[] = { 0x05, 0x04 };
+- unsigned char adc_head_9[] = { 0x05, 0x02 };
+- unsigned char adc_head_12[] = { 0x05, 0x01 };
+- unsigned char pll_bw_nom[] = { 0x0d, 0x47 };
+- unsigned char pll_bw_low[] = { 0x0d, 0x27 };
+- unsigned char gainset_2[] = { 0x28, 0x64 };
+- unsigned char agc_rst_on[] = { 0x0e, 0x0b };
+- unsigned char agc_rst_off[] = { 0x0e, 0x09 };
+- unsigned char if_agc_set[] = { 0x0f, 0x81 };
+- unsigned char addr_adc_sat = 0x1a;
+- unsigned char addr_agc_stat = 0x1d;
+- unsigned char addr_pll_stat = 0x1b;
+- unsigned char adc_sat, agc_stat,
+- pll_stat;
+- int i;
+-
+- 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_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);
+- msleep(1);
+-
+- expert_mode[1] = priv->tda8290_easy_mode + 0x80;
+- tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2);
+- tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2);
+- tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2);
+- if (priv->tda8290_easy_mode & 0x60)
+- tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2);
+- else
+- tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2);
+- tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2);
+-
+- tda8290_i2c_bridge(fe, 1);
+-
+- if (fe->ops.tuner_ops.set_analog_params)
+- fe->ops.tuner_ops.set_analog_params(fe, params);
+-
+- for (i = 0; i < 3; i++) {
+- tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
+- tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
+- if (pll_stat & 0x80) {
+- tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1);
+- tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1);
+- tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
+- tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
+- tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat);
+- break;
+- } else {
+- tuner_dbg("tda8290 not locked, no signal?\n");
+- msleep(100);
+- }
+- }
+- /* adjust headroom resp. gain */
+- if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat < 20))) {
+- tuner_dbg("adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d\n",
+- agc_stat, adc_sat, pll_stat & 0x80);
+- tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2);
+- msleep(100);
+- tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
+- tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
+- tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
+- tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
+- if ((agc_stat > 115) || !(pll_stat & 0x80)) {
+- tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n",
+- agc_stat, pll_stat & 0x80);
+- if (priv->cfg.agcf)
+- priv->cfg.agcf(fe);
+- msleep(100);
+- tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
+- tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
+- tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
+- tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
+- if((agc_stat > 115) || !(pll_stat & 0x80)) {
+- tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat);
+- tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2);
+- tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_low, 2);
+- msleep(100);
+- }
+- }
+- }
+-
+- /* l/ l' deadlock? */
+- if(priv->tda8290_easy_mode & 0x60) {
+- tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1);
+- tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1);
+- tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
+- tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
+- if ((adc_sat > 20) || !(pll_stat & 0x80)) {
+- tuner_dbg("trying to resolve SECAM L deadlock\n");
+- tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2);
+- msleep(40);
+- tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_off, 2);
+- }
+- }
+-
+- tda8290_i2c_bridge(fe, 0);
+- tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2);
+-}
+-
+-/*---------------------------------------------------------------------*/
+-
+-static void tda8295_power(struct dvb_frontend *fe, int enable)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+- unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */
+-
+- tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
+- tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
+-
+- if (enable)
+- buf[1] = 0x01;
+- else
+- buf[1] = 0x03;
+-
+- tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
+-}
+-
+-static void tda8295_set_easy_mode(struct dvb_frontend *fe, int enable)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+- unsigned char buf[] = { 0x01, 0x00 };
+-
+- tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
+- tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
+-
+- if (enable)
+- buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */
+- else
+- buf[1] = 0x00; /* reset active bit */
+-
+- tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
+-}
+-
+-static void tda8295_set_video_std(struct dvb_frontend *fe)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+- unsigned char buf[] = { 0x00, priv->tda8290_easy_mode };
+-
+- tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
+-
+- tda8295_set_easy_mode(fe, 1);
+- msleep(20);
+- tda8295_set_easy_mode(fe, 0);
+-}
+-
+-/*---------------------------------------------------------------------*/
+-
+-static void tda8295_agc1_out(struct dvb_frontend *fe, int enable)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+- unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */
+-
+- tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
+- tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
+-
+- if (enable)
+- buf[1] &= ~0x40;
+- else
+- buf[1] |= 0x40;
+-
+- tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
+-}
+-
+-static void tda8295_agc2_out(struct dvb_frontend *fe, int enable)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+- unsigned char set_gpio_cf[] = { 0x44, 0x00 };
+- unsigned char set_gpio_val[] = { 0x46, 0x00 };
+-
+- tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_cf[0], 1);
+- tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_cf[1], 1);
+- tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_val[0], 1);
+- tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_val[1], 1);
+-
+- set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */
+-
+- if (enable) {
+- set_gpio_cf[1] |= 0x01; /* config GPIO_0 as Open Drain Out */
+- set_gpio_val[1] &= 0xfe; /* set GPIO_0 pin low */
+- }
+- tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_cf, 2);
+- tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2);
+-}
+-
+-static int tda8295_has_signal(struct dvb_frontend *fe)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+-
+- unsigned char hvpll_stat = 0x26;
+- unsigned char ret;
+-
+- tuner_i2c_xfer_send(&priv->i2c_props, &hvpll_stat, 1);
+- tuner_i2c_xfer_recv(&priv->i2c_props, &ret, 1);
+- return (ret & 0x01) ? 65535 : 0;
+-}
+-
+-/*---------------------------------------------------------------------*/
+-
+-static void tda8295_set_params(struct dvb_frontend *fe,
+- struct analog_parameters *params)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+-
+- unsigned char blanking_mode[] = { 0x1d, 0x00 };
+-
+- 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 };
-
+-
+- tda8295_power(fe, 1);
+- tda8295_agc1_out(fe, 1);
+-
+- tuner_i2c_xfer_send(&priv->i2c_props, &blanking_mode[0], 1);
+- tuner_i2c_xfer_recv(&priv->i2c_props, &blanking_mode[1], 1);
+-
+- tda8295_set_video_std(fe);
+-
+- blanking_mode[1] = 0x03;
+- tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2);
+- msleep(20);
+-
+- tda8295_i2c_bridge(fe, 1);
+-
+- if (fe->ops.tuner_ops.set_analog_params)
+- fe->ops.tuner_ops.set_analog_params(fe, params);
+-
+- if (priv->cfg.agcf)
+- priv->cfg.agcf(fe);
+-
+- if (tda8295_has_signal(fe))
+- tuner_dbg("tda8295 is locked\n");
+- else
+- tuner_dbg("tda8295 not locked, no signal?\n");
+-
+- tda8295_i2c_bridge(fe, 0);
+-}
+-
+-/*---------------------------------------------------------------------*/
+-
+-static int tda8290_has_signal(struct dvb_frontend *fe)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+-
+- unsigned char i2c_get_afc[1] = { 0x1B };
+- unsigned char afc = 0;
+-
+- tuner_i2c_xfer_send(&priv->i2c_props, i2c_get_afc, ARRAY_SIZE(i2c_get_afc));
+- tuner_i2c_xfer_recv(&priv->i2c_props, &afc, 1);
+- return (afc & 0x80)? 65535:0;
+-}
+-
+-/*---------------------------------------------------------------------*/
+-
+-static void tda8290_standby(struct dvb_frontend *fe)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+-
+- unsigned char cb1[] = { 0x30, 0xD0 };
+- unsigned char tda8290_standby[] = { 0x00, 0x02 };
+- unsigned char tda8290_agc_tri[] = { 0x02, 0x20 };
+- struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2};
+-
+- tda8290_i2c_bridge(fe, 1);
+- if (priv->ver & TDA8275A)
+- cb1[1] = 0x90;
+- i2c_transfer(priv->i2c_props.adap, &msg, 1);
+- tda8290_i2c_bridge(fe, 0);
+- tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2);
+- tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2);
+-}
+-
+-static void tda8295_standby(struct dvb_frontend *fe)
+-{
+- tda8295_agc1_out(fe, 0); /* Put AGC in tri-state */
+-
+- tda8295_power(fe, 0);
+-}
+-
+-static void tda8290_init_if(struct dvb_frontend *fe)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+-
+- unsigned char set_VS[] = { 0x30, 0x6F };
+- 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;
-
+- tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2);
+- else
+- tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2);
+- tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2);
+-}
+-
+-static void tda8295_init_if(struct dvb_frontend *fe)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+-
+- static unsigned char set_adc_ctl[] = { 0x33, 0x14 };
+- static unsigned char set_adc_ctl2[] = { 0x34, 0x00 };
+- static unsigned char set_pll_reg6[] = { 0x3e, 0x63 };
+- static unsigned char set_pll_reg0[] = { 0x38, 0x23 };
+- static unsigned char set_pll_reg7[] = { 0x3f, 0x01 };
+- static unsigned char set_pll_reg10[] = { 0x42, 0x61 };
+- static unsigned char set_gpio_reg0[] = { 0x44, 0x0b };
+-
+- tda8295_power(fe, 1);
+-
+- tda8295_set_easy_mode(fe, 0);
+- tda8295_set_video_std(fe);
+-
+- tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl, 2);
+- tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl2, 2);
+- tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg6, 2);
+- tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg0, 2);
+- tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg7, 2);
+- tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg10, 2);
+- tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_reg0, 2);
+-
+- tda8295_agc1_out(fe, 0);
+- tda8295_agc2_out(fe, 0);
+-}
+-
+-static void tda8290_init_tuner(struct dvb_frontend *fe)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+- unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf,
+- 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 };
+- unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b,
+- 0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b };
+- struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0,
+- .buf=tda8275_init, .len = 14};
+- if (priv->ver & TDA8275A)
+- msg.buf = tda8275a_init;
+-
+- tda8290_i2c_bridge(fe, 1);
+- i2c_transfer(priv->i2c_props.adap, &msg, 1);
+- tda8290_i2c_bridge(fe, 0);
+-}
+-
+-/*---------------------------------------------------------------------*/
+-
+-static void tda829x_release(struct dvb_frontend *fe)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+-
+- /* only try to release the tuner if we've
+- * attached it from within this module */
+- if (priv->ver & (TDA18271 | TDA8275 | TDA8275A))
+- if (fe->ops.tuner_ops.release)
+- fe->ops.tuner_ops.release(fe);
+-
+- kfree(fe->analog_demod_priv);
+- fe->analog_demod_priv = NULL;
+-}
+-
+-static struct tda18271_config tda829x_tda18271_config = {
+- .gate = TDA18271_GATE_ANALOG,
+-};
+-
+-static int tda829x_find_tuner(struct dvb_frontend *fe)
+-{
+- struct tda8290_priv *priv = fe->analog_demod_priv;
+- struct analog_demod_ops *analog_ops = &fe->ops.analog_ops;
+- int i, ret, tuners_found;
+- u32 tuner_addrs;
+- u8 data;
+- struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 };
+-
+- if (NULL == analog_ops->i2c_gate_ctrl)
+- return -EINVAL;
+-
+- analog_ops->i2c_gate_ctrl(fe, 1);
+-
+- /* probe for tuner chip */
+- tuners_found = 0;
+- tuner_addrs = 0;
+- for (i = 0x60; i <= 0x63; i++) {
+- msg.addr = i;
+- ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
+- if (ret == 1) {
+- tuners_found++;
+- tuner_addrs = (tuner_addrs << 8) + i;
+- }
+- }
+- /* if there is more than one tuner, we expect the right one is
+- behind the bridge and we choose the highest address that doesn't
+- give a response now
+- */
+-
+- analog_ops->i2c_gate_ctrl(fe, 0);
+-
+- if (tuners_found > 1)
+- for (i = 0; i < tuners_found; i++) {
+- msg.addr = tuner_addrs & 0xff;
+- ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
+- if (ret == 1)
+- tuner_addrs = tuner_addrs >> 8;
+- else
+- break;
+- }
+-
+- if (tuner_addrs == 0) {
+- tuner_addrs = 0x60;
+- tuner_info("could not clearly identify tuner address, "
+- "defaulting to %x\n", tuner_addrs);
+- } else {
+- tuner_addrs = tuner_addrs & 0xff;
+- tuner_info("setting tuner address to %x\n", tuner_addrs);
+- }
+- priv->tda827x_addr = tuner_addrs;
+- msg.addr = tuner_addrs;
+-
+- analog_ops->i2c_gate_ctrl(fe, 1);
+- ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
+-
+- if (ret != 1) {
+- tuner_warn("tuner access failed!\n");
+- return -EREMOTEIO;
+- }
+-
+- if ((data == 0x83) || (data == 0x84)) {
+- priv->ver |= TDA18271;
+- tda18271_attach(fe, priv->tda827x_addr,
+- priv->i2c_props.adap,
+- &tda829x_tda18271_config);
+- } else {
+- if ((data & 0x3c) == 0)
+- priv->ver |= TDA8275;
+- 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",
+- }
+- if (fe->ops.tuner_ops.init)
+- fe->ops.tuner_ops.init(fe);
+-
+- if (fe->ops.tuner_ops.sleep)
+- fe->ops.tuner_ops.sleep(fe);
+-
+- analog_ops->i2c_gate_ctrl(fe, 0);
+-
+- return 0;
+-}
+-
+-static int tda8290_probe(struct tuner_i2c_props *i2c_props)
+-{
+-#define TDA8290_ID 0x89
+- unsigned char tda8290_id[] = { 0x1f, 0x00 };
+-
+- /* detect tda8290 */
+- tuner_i2c_xfer_send(i2c_props, &tda8290_id[0], 1);
+- tuner_i2c_xfer_recv(i2c_props, &tda8290_id[1], 1);
+-
+- 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",
+- i2c_props->addr);
+- return 0;
+- }
+-
+- return -ENODEV;
+-}
+-
+-static int tda8295_probe(struct tuner_i2c_props *i2c_props)
+-{
+-#define TDA8295_ID 0x8a
+- unsigned char tda8295_id[] = { 0x2f, 0x00 };
+-
+- /* detect tda8295 */
+- tuner_i2c_xfer_send(i2c_props, &tda8295_id[0], 1);
+- tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1);
+-
+- 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;
+- i2c_props->addr);
+- return 0;
+- }
+-
+- return -ENODEV;
+-}
+-
+-static struct analog_demod_ops tda8290_ops = {
+- .set_params = tda8290_set_params,
+- .has_signal = tda8290_has_signal,
+- .standby = tda8290_standby,
+- .release = tda829x_release,
+- .i2c_gate_ctrl = tda8290_i2c_bridge,
+-};
+-
+-static struct analog_demod_ops tda8295_ops = {
+- .set_params = tda8295_set_params,
+- .has_signal = tda8295_has_signal,
+- .standby = tda8295_standby,
+- .release = tda829x_release,
+- .i2c_gate_ctrl = tda8295_i2c_bridge,
+-};
+-
+-struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
+- struct i2c_adapter *i2c_adap, u8 i2c_addr,
+- struct tda829x_config *cfg)
+-{
+- struct tda8290_priv *priv = NULL;
+- char *name;
+-
+- priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL);
+- if (priv == NULL)
+- return NULL;
+- fe->analog_demod_priv = priv;
+-
+- priv->i2c_props.addr = i2c_addr;
+- priv->i2c_props.adap = i2c_adap;
+- if (cfg) {
+- priv->cfg.config = cfg->lna_cfg;
+- priv->cfg.tuner_callback = cfg->tuner_callback;
+- }
+-
+- if (tda8290_probe(&priv->i2c_props) == 0) {
+- priv->ver = TDA8290;
+- memcpy(&fe->ops.analog_ops, &tda8290_ops,
+- sizeof(struct analog_demod_ops));
+- }
+-
+- if (tda8295_probe(&priv->i2c_props) == 0) {
+- priv->ver = TDA8295;
+- memcpy(&fe->ops.analog_ops, &tda8295_ops,
+- sizeof(struct analog_demod_ops));
+- }
+-
+- if ((!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) &&
+- (tda829x_find_tuner(fe) < 0))
+- goto fail;
+-
+- switch (priv->ver) {
+- case TDA8290:
+- name = "tda8290";
+- break;
+- case TDA8295:
+- name = "tda8295";
+- break;
+- case TDA8290 | TDA8275:
+- name = "tda8290+75";
+- break;
+- case TDA8295 | TDA8275:
+- name = "tda8295+75";
+- break;
+- case TDA8290 | TDA8275A:
+- name = "tda8290+75a";
+- break;
+- case TDA8295 | TDA8275A:
+- name = "tda8295+75a";
+- break;
+- case TDA8290 | TDA18271:
+- name = "tda8290+18271";
+- break;
+- case TDA8295 | TDA18271:
+- name = "tda8295+18271";
+- break;
+- default:
+- goto fail;
+- }
+- tuner_info("type set to %s\n", name);
+-
+- fe->ops.analog_ops.info.name = name;
+-
+- if (priv->ver & TDA8290) {
+- tda8290_init_tuner(fe);
+- tda8290_init_if(fe);
+- } else if (priv->ver & TDA8295)
+- tda8295_init_if(fe);
+-
+- return fe;
+-
+-fail:
+- tda829x_release(fe);
+- return NULL;
+-}
+-EXPORT_SYMBOL_GPL(tda829x_attach);
+-
+-int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
+-{
+- struct tuner_i2c_props i2c_props = {
+- .adap = i2c_adap,
+- .addr = i2c_addr,
+- };
+-
+- unsigned char soft_reset[] = { 0x00, 0x00 };
+- unsigned char easy_mode_b[] = { 0x01, 0x02 };
+- unsigned char easy_mode_g[] = { 0x01, 0x04 };
+- unsigned char restore_9886[] = { 0x00, 0xd6, 0x30 };
+- unsigned char addr_dto_lsb = 0x07;
+- unsigned char data;
+-#define PROBE_BUFFER_SIZE 8
+- unsigned char buf[PROBE_BUFFER_SIZE];
+- int i;
+-
+- /* rule out tda9887, which would return the same byte repeatedly */
+- tuner_i2c_xfer_send(&i2c_props, soft_reset, 1);
+- tuner_i2c_xfer_recv(&i2c_props, buf, PROBE_BUFFER_SIZE);
+- for (i = 1; i < PROBE_BUFFER_SIZE; i++) {
+- if (buf[i] != buf[0])
+- break;
+- }
+-
+- /* all bytes are equal, not a tda829x - probably a tda9887 */
+- if (i == PROBE_BUFFER_SIZE)
+- return -ENODEV;
+-
+- if ((tda8290_probe(&i2c_props) == 0) ||
+- (tda8295_probe(&i2c_props) == 0))
+- return 0;
+-
+- /* fall back to old probing method */
+- tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2);
+- tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
+- tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1);
+- tuner_i2c_xfer_recv(&i2c_props, &data, 1);
+- if (data == 0) {
+- tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2);
+- tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
+- tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1);
+- tuner_i2c_xfer_recv(&i2c_props, &data, 1);
+- if (data == 0x7b) {
+- return 0;
+- }
+- }
+- tuner_i2c_xfer_send(&i2c_props, restore_9886, 3);
+- return -ENODEV;
+-}
+-EXPORT_SYMBOL_GPL(tda829x_probe);
+-
+-MODULE_DESCRIPTION("Philips/NXP TDA8290/TDA8295 analog IF demodulator driver");
+-MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky");
+-MODULE_LICENSE("GPL");
+-
+-/*
+- * Overrides for Emacs so that we follow Linus's tabbing style.
+- * ---------------------------------------------------------------------------
+- * Local variables:
+- * c-basic-offset: 8
+- * End:
+- */
diff --git a/drivers/media/video/tda8290.h b/drivers/media/video/tda8290.h
-index dc8ef31..d3bbf27 100644
+deleted file mode 100644
+index dc8ef31..0000000
--- a/drivers/media/video/tda8290.h
-+++ b/drivers/media/video/tda8290.h
-@@ -21,7 +21,7 @@
- #include "dvb_frontend.h"
-
- struct tda829x_config {
++++ /dev/null
+@@ -1,57 +0,0 @@
+-/*
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2 of the License, or
+- (at your option) any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
+-
+- You 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 __TDA8290_H__
+-#define __TDA8290_H__
+-
+-#include <linux/i2c.h>
+-#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)
- {
+- int (*tuner_callback) (void *dev, int command, int arg);
+-
+- unsigned int probe_tuner:1;
+-#define TDA829X_PROBE_TUNER 0
+-#define TDA829X_DONT_PROBE 1
+-};
+-
+-#if defined(CONFIG_TUNER_TDA8290) || (defined(CONFIG_TUNER_TDA8290_MODULE) && defined(MODULE))
+-extern int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr);
+-
+-extern struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
+- struct i2c_adapter *i2c_adap,
+- u8 i2c_addr,
+- struct tda829x_config *cfg);
+-#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",
+- return -EINVAL;
+-}
+-
+-static inline struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
+- struct i2c_adapter *i2c_adap,
+- u8 i2c_addr,
+- struct tda829x_config *cfg)
+-{
+- printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
- __FUNCTION__);
-+ __func__);
- return NULL;
- }
- #endif
+- return NULL;
+-}
+-#endif
+-
+-#endif /* __TDA8290_H__ */
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
index bdca5d2..0cee002 100644
--- a/drivers/media/video/tda9840.c
@@ -416133,287 +583566,1686 @@
#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
+deleted file mode 100644
+index 106c93b..0000000
--- 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");
-
++++ /dev/null
+@@ -1,695 +0,0 @@
+-#include <linux/module.h>
+-#include <linux/kernel.h>
+-#include <linux/i2c.h>
+-#include <linux/types.h>
+-#include <linux/init.h>
+-#include <linux/errno.h>
+-#include <linux/slab.h>
+-#include <linux/delay.h>
+-#include <linux/videodev.h>
+-#include <media/v4l2-common.h>
+-#include <media/tuner.h>
+-#include "tuner-i2c.h"
+-#include "tda9887.h"
+-
+-
+-/* Chips:
+- TDA9885 (PAL, NTSC)
+- TDA9886 (PAL, SECAM, NTSC)
+- TDA9887 (PAL, SECAM, NTSC, FM Radio)
+-
+- Used as part of several tuners
+-*/
+-
+-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)
- {
+-
+-struct tda9887_priv {
+- struct tuner_i2c_props i2c_props;
+-
+- unsigned char data[4];
+- unsigned int config;
+- unsigned int mode;
+- unsigned int audmode;
+- v4l2_std_id std;
+-};
+-
+-/* ---------------------------------------------------------------------- */
+-
+-#define UNSET (-1U)
+-
+-struct tvnorm {
+- v4l2_std_id std;
+- char *name;
+- unsigned char b;
+- unsigned char c;
+- unsigned char e;
+-};
+-
+-/* ---------------------------------------------------------------------- */
+-
+-//
+-// TDA defines
+-//
+-
+-//// first reg (b)
+-#define cVideoTrapBypassOFF 0x00 // bit b0
+-#define cVideoTrapBypassON 0x01 // bit b0
+-
+-#define cAutoMuteFmInactive 0x00 // bit b1
+-#define cAutoMuteFmActive 0x02 // bit b1
+-
+-#define cIntercarrier 0x00 // bit b2
+-#define cQSS 0x04 // bit b2
+-
+-#define cPositiveAmTV 0x00 // bit b3:4
+-#define cFmRadio 0x08 // bit b3:4
+-#define cNegativeFmTV 0x10 // bit b3:4
+-
+-
+-#define cForcedMuteAudioON 0x20 // bit b5
+-#define cForcedMuteAudioOFF 0x00 // bit b5
+-
+-#define cOutputPort1Active 0x00 // bit b6
+-#define cOutputPort1Inactive 0x40 // bit b6
+-
+-#define cOutputPort2Active 0x00 // bit b7
+-#define cOutputPort2Inactive 0x80 // bit b7
+-
+-
+-//// second reg (c)
+-#define cDeemphasisOFF 0x00 // bit c5
+-#define cDeemphasisON 0x20 // bit c5
+-
+-#define cDeemphasis75 0x00 // bit c6
+-#define cDeemphasis50 0x40 // bit c6
+-
+-#define cAudioGain0 0x00 // bit c7
+-#define cAudioGain6 0x80 // bit c7
+-
+-#define cTopMask 0x1f // bit c0:4
+-#define cTopDefault 0x10 // bit c0:4
+-
+-//// third reg (e)
+-#define cAudioIF_4_5 0x00 // bit e0:1
+-#define cAudioIF_5_5 0x01 // bit e0:1
+-#define cAudioIF_6_0 0x02 // bit e0:1
+-#define cAudioIF_6_5 0x03 // bit e0:1
+-
+-
+-#define cVideoIFMask 0x1c // bit e2:4
+-/* Video IF selection in TV Mode (bit B3=0) */
+-#define cVideoIF_58_75 0x00 // bit e2:4
+-#define cVideoIF_45_75 0x04 // bit e2:4
+-#define cVideoIF_38_90 0x08 // bit e2:4
+-#define cVideoIF_38_00 0x0C // bit e2:4
+-#define cVideoIF_33_90 0x10 // bit e2:4
+-#define cVideoIF_33_40 0x14 // bit e2:4
+-#define cRadioIF_45_75 0x18 // bit e2:4
+-#define cRadioIF_38_90 0x1C // bit e2:4
+-
+-/* IF1 selection in Radio Mode (bit B3=1) */
+-#define cRadioIF_33_30 0x00 // bit e2,4 (also 0x10,0x14)
+-#define cRadioIF_41_30 0x04 // bit e2,4
+-
+-/* Output of AFC pin in radio mode when bit E7=1 */
+-#define cRadioAGC_SIF 0x00 // bit e3
+-#define cRadioAGC_FM 0x08 // bit e3
+-
+-#define cTunerGainNormal 0x00 // bit e5
+-#define cTunerGainLow 0x20 // bit e5
+-
+-#define cGating_18 0x00 // bit e6
+-#define cGating_36 0x40 // bit e6
+-
+-#define cAgcOutON 0x80 // bit e7
+-#define cAgcOutOFF 0x00 // bit e7
+-
+-/* ---------------------------------------------------------------------- */
+-
+-static struct tvnorm tvnorms[] = {
+- {
+- .std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N,
+- .name = "PAL-BGHN",
+- .b = ( cNegativeFmTV |
+- cQSS ),
+- .c = ( cDeemphasisON |
+- cDeemphasis50 |
+- cTopDefault),
+- .e = ( cGating_36 |
+- cAudioIF_5_5 |
+- cVideoIF_38_90 ),
+- },{
+- .std = V4L2_STD_PAL_I,
+- .name = "PAL-I",
+- .b = ( cNegativeFmTV |
+- cQSS ),
+- .c = ( cDeemphasisON |
+- cDeemphasis50 |
+- cTopDefault),
+- .e = ( cGating_36 |
+- cAudioIF_6_0 |
+- cVideoIF_38_90 ),
+- },{
+- .std = V4L2_STD_PAL_DK,
+- .name = "PAL-DK",
+- .b = ( cNegativeFmTV |
+- cQSS ),
+- .c = ( cDeemphasisON |
+- cDeemphasis50 |
+- cTopDefault),
+- .e = ( cGating_36 |
+- cAudioIF_6_5 |
+- cVideoIF_38_90 ),
+- },{
+- .std = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc,
+- .name = "PAL-M/Nc",
+- .b = ( cNegativeFmTV |
+- cQSS ),
+- .c = ( cDeemphasisON |
+- cDeemphasis75 |
+- cTopDefault),
+- .e = ( cGating_36 |
+- cAudioIF_4_5 |
+- cVideoIF_45_75 ),
+- },{
+- .std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
+- .name = "SECAM-BGH",
+- .b = ( cPositiveAmTV |
+- cQSS ),
+- .c = ( cTopDefault),
+- .e = ( cGating_36 |
+- cAudioIF_5_5 |
+- cVideoIF_38_90 ),
+- },{
+- .std = V4L2_STD_SECAM_L,
+- .name = "SECAM-L",
+- .b = ( cPositiveAmTV |
+- cQSS ),
+- .c = ( cTopDefault),
+- .e = ( cGating_36 |
+- cAudioIF_6_5 |
+- cVideoIF_38_90 ),
+- },{
+- .std = V4L2_STD_SECAM_LC,
+- .name = "SECAM-L'",
+- .b = ( cOutputPort2Inactive |
+- cPositiveAmTV |
+- cQSS ),
+- .c = ( cTopDefault),
+- .e = ( cGating_36 |
+- cAudioIF_6_5 |
+- cVideoIF_33_90 ),
+- },{
+- .std = V4L2_STD_SECAM_DK,
+- .name = "SECAM-DK",
+- .b = ( cNegativeFmTV |
+- cQSS ),
+- .c = ( cDeemphasisON |
+- cDeemphasis50 |
+- cTopDefault),
+- .e = ( cGating_36 |
+- cAudioIF_6_5 |
+- cVideoIF_38_90 ),
+- },{
+- .std = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
+- .name = "NTSC-M",
+- .b = ( cNegativeFmTV |
+- cQSS ),
+- .c = ( cDeemphasisON |
+- cDeemphasis75 |
+- cTopDefault),
+- .e = ( cGating_36 |
+- cAudioIF_4_5 |
+- cVideoIF_45_75 ),
+- },{
+- .std = V4L2_STD_NTSC_M_JP,
+- .name = "NTSC-M-JP",
+- .b = ( cNegativeFmTV |
+- cQSS ),
+- .c = ( cDeemphasisON |
+- cDeemphasis50 |
+- cTopDefault),
+- .e = ( cGating_36 |
+- cAudioIF_4_5 |
+- cVideoIF_58_75 ),
+- }
+-};
+-
+-static struct tvnorm radio_stereo = {
+- .name = "Radio Stereo",
+- .b = ( cFmRadio |
+- cQSS ),
+- .c = ( cDeemphasisOFF |
+- cAudioGain6 |
+- cTopDefault),
+- .e = ( cTunerGainLow |
+- cAudioIF_5_5 |
+- cRadioIF_38_90 ),
+-};
+-
+-static struct tvnorm radio_mono = {
+- .name = "Radio Mono",
+- .b = ( cFmRadio |
+- cQSS ),
+- .c = ( cDeemphasisON |
+- cDeemphasis75 |
+- cTopDefault),
+- .e = ( cTunerGainLow |
+- cAudioIF_5_5 |
+- cRadioIF_38_90 ),
+-};
+-
+-/* ---------------------------------------------------------------------- */
+-
+-static void dump_read_message(struct dvb_frontend *fe, unsigned char *buf)
+-{
+- struct tda9887_priv *priv = fe->analog_demod_priv;
+-
+- static char *afc[16] = {
+- "- 12.5 kHz",
+- "- 37.5 kHz",
+- "- 62.5 kHz",
+- "- 87.5 kHz",
+- "-112.5 kHz",
+- "-137.5 kHz",
+- "-162.5 kHz",
+- "-187.5 kHz [min]",
+- "+187.5 kHz [max]",
+- "+162.5 kHz",
+- "+137.5 kHz",
+- "+112.5 kHz",
+- "+ 87.5 kHz",
+- "+ 62.5 kHz",
+- "+ 37.5 kHz",
+- "+ 12.5 kHz",
+- };
+- tuner_info("read: 0x%2x\n", buf[0]);
+- tuner_info(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no");
+- tuner_info(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]);
+- tuner_info(" fmif level : %s\n", (buf[0] & 0x20) ? "high" : "low");
+- tuner_info(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out");
+- tuner_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low");
+-}
+-
+-static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf)
+-{
+- struct tda9887_priv *priv = fe->analog_demod_priv;
+-
+- static char *sound[4] = {
+- "AM/TV",
+- "FM/radio",
+- "FM/TV",
+- "FM/radio"
+- };
+- static char *adjust[32] = {
+- "-16", "-15", "-14", "-13", "-12", "-11", "-10", "-9",
+- "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1",
+- "0", "+1", "+2", "+3", "+4", "+5", "+6", "+7",
+- "+8", "+9", "+10", "+11", "+12", "+13", "+14", "+15"
+- };
+- static char *deemph[4] = {
+- "no", "no", "75", "50"
+- };
+- static char *carrier[4] = {
+- "4.5 MHz",
+- "5.5 MHz",
+- "6.0 MHz",
+- "6.5 MHz / AM"
+- };
+- static char *vif[8] = {
+- "58.75 MHz",
+- "45.75 MHz",
+- "38.9 MHz",
+- "38.0 MHz",
+- "33.9 MHz",
+- "33.4 MHz",
+- "45.75 MHz + pin13",
+- "38.9 MHz + pin13",
+- };
+- static char *rif[4] = {
+- "44 MHz",
+- "52 MHz",
+- "52 MHz",
+- "44 MHz",
+- };
+-
+- tuner_info("write: byte B 0x%02x\n", buf[1]);
+- tuner_info(" B0 video mode : %s\n",
+- (buf[1] & 0x01) ? "video trap" : "sound trap");
+- tuner_info(" B1 auto mute fm : %s\n",
+- (buf[1] & 0x02) ? "yes" : "no");
+- tuner_info(" B2 carrier mode : %s\n",
+- (buf[1] & 0x04) ? "QSS" : "Intercarrier");
+- tuner_info(" B3-4 tv sound/radio : %s\n",
+- sound[(buf[1] & 0x18) >> 3]);
+- tuner_info(" B5 force mute audio: %s\n",
+- (buf[1] & 0x20) ? "yes" : "no");
+- tuner_info(" B6 output port 1 : %s\n",
+- (buf[1] & 0x40) ? "high (inactive)" : "low (active)");
+- tuner_info(" B7 output port 2 : %s\n",
+- (buf[1] & 0x80) ? "high (inactive)" : "low (active)");
+-
+- tuner_info("write: byte C 0x%02x\n", buf[2]);
+- tuner_info(" C0-4 top adjustment : %s dB\n",
+- adjust[buf[2] & 0x1f]);
+- tuner_info(" C5-6 de-emphasis : %s\n",
+- deemph[(buf[2] & 0x60) >> 5]);
+- tuner_info(" C7 audio gain : %s\n",
+- (buf[2] & 0x80) ? "-6" : "0");
+-
+- tuner_info("write: byte E 0x%02x\n", buf[3]);
+- tuner_info(" E0-1 sound carrier : %s\n",
+- carrier[(buf[3] & 0x03)]);
+- tuner_info(" E6 l pll gating : %s\n",
+- (buf[3] & 0x40) ? "36" : "13");
+-
+- if (buf[1] & 0x08) {
+- /* radio */
+- tuner_info(" E2-4 video if : %s\n",
+- rif[(buf[3] & 0x0c) >> 2]);
+- tuner_info(" E7 vif agc output : %s\n",
+- (buf[3] & 0x80)
+- ? ((buf[3] & 0x10) ? "fm-agc radio" :
+- "sif-agc radio")
+- : "fm radio carrier afc");
+- } else {
+- /* video */
+- tuner_info(" E2-4 video if : %s\n",
+- vif[(buf[3] & 0x1c) >> 2]);
+- tuner_info(" E5 tuner gain : %s\n",
+- (buf[3] & 0x80)
+- ? ((buf[3] & 0x20) ? "external" : "normal")
+- : ((buf[3] & 0x20) ? "minimum" : "normal"));
+- tuner_info(" E7 vif agc output : %s\n",
+- (buf[3] & 0x80) ? ((buf[3] & 0x20)
+- ? "pin3 port, pin22 vif agc out"
+- : "pin22 port, pin3 vif acg ext in")
+- : "pin3+pin22 port");
+- }
+- tuner_info("--\n");
+-}
+-
+-/* ---------------------------------------------------------------------- */
+-
+-static int tda9887_set_tvnorm(struct dvb_frontend *fe)
+-{
+- struct tda9887_priv *priv = fe->analog_demod_priv;
+- struct tvnorm *norm = NULL;
+- char *buf = priv->data;
+- int i;
+-
+- if (priv->mode == V4L2_TUNER_RADIO) {
+- if (priv->audmode == V4L2_TUNER_MODE_MONO)
+- norm = &radio_mono;
+- else
+- norm = &radio_stereo;
+- } else {
+- for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
+- if (tvnorms[i].std & priv->std) {
+- norm = tvnorms+i;
+- break;
+- }
+- }
+- }
+- if (NULL == norm) {
+- tuner_dbg("Unsupported tvnorm entry - audio muted\n");
+- return -1;
+- }
+-
+- tuner_dbg("configure for: %s\n", norm->name);
+- buf[1] = norm->b;
+- buf[2] = norm->c;
+- buf[3] = norm->e;
+- return 0;
+-}
+-
+-static unsigned int port1 = UNSET;
+-static unsigned int port2 = UNSET;
+-static unsigned int qss = UNSET;
+-static unsigned int adjust = UNSET;
+-
+-module_param(port1, int, 0644);
+-module_param(port2, int, 0644);
+-module_param(qss, int, 0644);
+-module_param(adjust, int, 0644);
+-
+-static int tda9887_set_insmod(struct dvb_frontend *fe)
+-{
+- struct tda9887_priv *priv = fe->analog_demod_priv;
+- char *buf = priv->data;
+-
+- if (UNSET != port1) {
+- if (port1)
+- buf[1] |= cOutputPort1Inactive;
+- else
+- buf[1] &= ~cOutputPort1Inactive;
+- }
+- if (UNSET != port2) {
+- if (port2)
+- buf[1] |= cOutputPort2Inactive;
+- else
+- buf[1] &= ~cOutputPort2Inactive;
+- }
+-
+- if (UNSET != qss) {
+- if (qss)
+- buf[1] |= cQSS;
+- else
+- buf[1] &= ~cQSS;
+- }
+-
+- if (adjust >= 0x00 && adjust < 0x20) {
+- buf[2] &= ~cTopMask;
+- buf[2] |= adjust;
+- }
+- return 0;
+-}
+-
+-static int tda9887_do_config(struct dvb_frontend *fe)
+-{
+- struct tda9887_priv *priv = fe->analog_demod_priv;
+- char *buf = priv->data;
+-
+- if (priv->config & TDA9887_PORT1_ACTIVE)
+- buf[1] &= ~cOutputPort1Inactive;
+- if (priv->config & TDA9887_PORT1_INACTIVE)
+- buf[1] |= cOutputPort1Inactive;
+- if (priv->config & TDA9887_PORT2_ACTIVE)
+- buf[1] &= ~cOutputPort2Inactive;
+- if (priv->config & TDA9887_PORT2_INACTIVE)
+- buf[1] |= cOutputPort2Inactive;
+-
+- if (priv->config & TDA9887_QSS)
+- buf[1] |= cQSS;
+- if (priv->config & TDA9887_INTERCARRIER)
+- buf[1] &= ~cQSS;
+-
+- if (priv->config & TDA9887_AUTOMUTE)
+- buf[1] |= cAutoMuteFmActive;
+- if (priv->config & TDA9887_DEEMPHASIS_MASK) {
+- buf[2] &= ~0x60;
+- switch (priv->config & TDA9887_DEEMPHASIS_MASK) {
+- case TDA9887_DEEMPHASIS_NONE:
+- buf[2] |= cDeemphasisOFF;
+- break;
+- case TDA9887_DEEMPHASIS_50:
+- buf[2] |= cDeemphasisON | cDeemphasis50;
+- break;
+- case TDA9887_DEEMPHASIS_75:
+- buf[2] |= cDeemphasisON | cDeemphasis75;
+- break;
+- }
+- }
+- if (priv->config & TDA9887_TOP_SET) {
+- buf[2] &= ~cTopMask;
+- buf[2] |= (priv->config >> 8) & cTopMask;
+- }
+- if ((priv->config & TDA9887_INTERCARRIER_NTSC) &&
+- (priv->std & V4L2_STD_NTSC))
+- buf[1] &= ~cQSS;
+- if (priv->config & TDA9887_GATING_18)
+- buf[3] &= ~cGating_36;
+-
+- if (priv->mode == V4L2_TUNER_RADIO) {
+- if (priv->config & TDA9887_RIF_41_3) {
+- buf[3] &= ~cVideoIFMask;
+- buf[3] |= cRadioIF_41_30;
+- }
+- if (priv->config & TDA9887_GAIN_NORMAL)
+- buf[3] &= ~cTunerGainLow;
+- }
+-
+- return 0;
+-}
+-
+-/* ---------------------------------------------------------------------- */
+-
+-static int tda9887_status(struct dvb_frontend *fe)
+-{
+- struct tda9887_priv *priv = fe->analog_demod_priv;
+- unsigned char buf[1];
+- int rc;
+-
+- memset(buf,0,sizeof(buf));
+- if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,buf,1)))
+- tuner_info("i2c i/o error: rc == %d (should be 1)\n", rc);
+- dump_read_message(fe, buf);
+- return 0;
+-}
+-
+-static void tda9887_configure(struct dvb_frontend *fe)
+-{
+- struct tda9887_priv *priv = fe->analog_demod_priv;
+- int rc;
+-
+- memset(priv->data,0,sizeof(priv->data));
+- tda9887_set_tvnorm(fe);
+-
+- /* A note on the port settings:
+- These settings tend to depend on the specifics of the board.
+- By default they are set to inactive (bit value 1) by this driver,
+- overwriting any changes made by the tvnorm. This means that it
+- is the responsibility of the module using the tda9887 to set
+- these values in case of changes in the tvnorm.
+- In many cases port 2 should be made active (0) when selecting
+- SECAM-L, and port 2 should remain inactive (1) for SECAM-L'.
+-
+- For the other standards the tda9887 application note says that
+- the ports should be set to active (0), but, again, that may
+- differ depending on the precise hardware configuration.
+- */
+- priv->data[1] |= cOutputPort1Inactive;
+- priv->data[1] |= cOutputPort2Inactive;
+-
+- tda9887_do_config(fe);
+- tda9887_set_insmod(fe);
+-
+- if (priv->mode == T_STANDBY)
+- priv->data[1] |= cForcedMuteAudioON;
+-
+- tuner_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
+- priv->data[1], priv->data[2], priv->data[3]);
+- if (debug > 1)
+- dump_write_message(fe, priv->data);
+-
+- if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4)))
+- tuner_info("i2c i/o error: rc == %d (should be 4)\n", rc);
+-
+- if (debug > 2) {
+- msleep_interruptible(1000);
+- tda9887_status(fe);
+- }
+-}
+-
+-/* ---------------------------------------------------------------------- */
+-
+-static void tda9887_tuner_status(struct dvb_frontend *fe)
+-{
+- struct tda9887_priv *priv = fe->analog_demod_priv;
+- tuner_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n",
+- priv->data[1], priv->data[2], priv->data[3]);
+-}
+-
+-static int tda9887_get_afc(struct dvb_frontend *fe)
+-{
+- struct tda9887_priv *priv = fe->analog_demod_priv;
+- static int AFC_BITS_2_kHz[] = {
+- -12500, -37500, -62500, -97500,
+- -112500, -137500, -162500, -187500,
+- 187500, 162500, 137500, 112500,
+- 97500 , 62500, 37500 , 12500
+- };
+- int afc=0;
+- __u8 reg = 0;
+-
+- if (1 == tuner_i2c_xfer_recv(&priv->i2c_props,®,1))
+- afc = AFC_BITS_2_kHz[(reg>>1)&0x0f];
+-
+- return afc;
+-}
+-
+-static void tda9887_standby(struct dvb_frontend *fe)
+-{
+- struct tda9887_priv *priv = fe->analog_demod_priv;
+-
+- priv->mode = T_STANDBY;
+-
+- tda9887_configure(fe);
+-}
+-
+-static void tda9887_set_params(struct dvb_frontend *fe,
+- struct analog_parameters *params)
+-{
+- struct tda9887_priv *priv = fe->analog_demod_priv;
+-
+- priv->mode = params->mode;
+- priv->audmode = params->audmode;
+- priv->std = params->std;
+- tda9887_configure(fe);
+-}
+-
+-static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg)
+-{
+- struct tda9887_priv *priv = fe->analog_demod_priv;
+-
+- priv->config = *(unsigned int *)priv_cfg;
+- tda9887_configure(fe);
+-
+- return 0;
+-}
+-
+-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;
-
+- fe->analog_demod_priv = NULL;
+-}
+-
+-static struct analog_demod_ops tda9887_ops = {
+- .info = {
+- .name = "tda9887",
+- },
+- .set_params = tda9887_set_params,
+- .standby = tda9887_standby,
+- .tuner_status = tda9887_tuner_status,
+- .get_afc = tda9887_get_afc,
+- .release = tda9887_release,
+- .set_config = tda9887_set_config,
+-};
+-
+-struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
+- struct i2c_adapter *i2c_adap,
+- u8 i2c_addr)
+-{
+- struct tda9887_priv *priv = NULL;
+-
- 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));
+-
+- memcpy(&fe->ops.analog_ops, &tda9887_ops,
+- sizeof(struct analog_demod_ops));
+-
+- return fe;
+-}
+-EXPORT_SYMBOL_GPL(tda9887_attach);
+-
+-MODULE_LICENSE("GPL");
+-
+-/*
+- * Overrides for Emacs so that we follow Linus's tabbing style.
+- * ---------------------------------------------------------------------------
+- * Local variables:
+- * c-basic-offset: 8
+- * End:
+- */
diff --git a/drivers/media/video/tda9887.h b/drivers/media/video/tda9887.h
-index 8f873a8..be49dcb 100644
+deleted file mode 100644
+index 8f873a8..0000000
--- 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)
- {
++++ /dev/null
+@@ -1,38 +0,0 @@
+-/*
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2 of the License, or
+- (at your option) any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
+-
+- You 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 __TDA9887_H__
+-#define __TDA9887_H__
+-
+-#include <linux/i2c.h>
+-#include "dvb_frontend.h"
+-
+-/* ------------------------------------------------------------------------ */
+-#if defined(CONFIG_TUNER_TDA9887) || (defined(CONFIG_TUNER_TDA9887_MODULE) && defined(MODULE))
+-extern struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
+- struct i2c_adapter *i2c_adap,
+- u8 i2c_addr);
+-#else
+-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
+- return NULL;
+-}
+-#endif
+-
+-#endif /* __TDA9887_H__ */
diff --git a/drivers/media/video/tea5761.c b/drivers/media/video/tea5761.c
-index 5326eec..b93cdef 100644
+deleted file mode 100644
+index 5326eec..0000000
--- a/drivers/media/video/tea5761.c
-+++ b/drivers/media/video/tea5761.c
-@@ -14,12 +14,10 @@
- #include "tuner-i2c.h"
- #include "tea5761.h"
-
++++ /dev/null
+@@ -1,320 +0,0 @@
+-/*
+- * For Philips TEA5761 FM Chip
+- * I2C address is allways 0x20 (0x10 at 7-bit mode).
+- *
+- * Copyright (c) 2005-2007 Mauro Carvalho Chehab (mchehab at infradead.org)
+- * This code is placed under the terms of the GNUv2 General Public License
+- *
+- */
+-
+-#include <linux/i2c.h>
+-#include <linux/delay.h>
+-#include <linux/videodev.h>
+-#include <media/tuner.h>
+-#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");
-
+-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));
+-struct tea5761_priv {
+- struct tuner_i2c_props i2c_props;
+-
+- u32 frequency;
+-};
+-
+-/*****************************************************************************/
+-
+-/***************************
+- * TEA5761HN I2C registers *
+- ***************************/
+-
+-/* INTREG - Read: bytes 0 and 1 / Write: byte 0 */
+-
+- /* first byte for reading */
+-#define TEA5761_INTREG_IFFLAG 0x10
+-#define TEA5761_INTREG_LEVFLAG 0x8
+-#define TEA5761_INTREG_FRRFLAG 0x2
+-#define TEA5761_INTREG_BLFLAG 0x1
+-
+- /* second byte for reading / byte for writing */
+-#define TEA5761_INTREG_IFMSK 0x10
+-#define TEA5761_INTREG_LEVMSK 0x8
+-#define TEA5761_INTREG_FRMSK 0x2
+-#define TEA5761_INTREG_BLMSK 0x1
+-
+-/* FRQSET - Read: bytes 2 and 3 / Write: byte 1 and 2 */
+-
+- /* First byte */
+-#define TEA5761_FRQSET_SEARCH_UP 0x80 /* 1=Station search from botton to up */
+-#define TEA5761_FRQSET_SEARCH_MODE 0x40 /* 1=Search mode */
+-
+- /* Bits 0-5 for divider MSB */
+-
+- /* Second byte */
+- /* Bits 0-7 for divider LSB */
+-
+-/* TNCTRL - Read: bytes 4 and 5 / Write: Bytes 3 and 4 */
+-
+- /* first byte */
+-
+-#define TEA5761_TNCTRL_PUPD_0 0x40 /* Power UP/Power Down MSB */
+-#define TEA5761_TNCTRL_BLIM 0X20 /* 1= Japan Frequencies, 0= European frequencies */
+-#define TEA5761_TNCTRL_SWPM 0x10 /* 1= software port is FRRFLAG */
+-#define TEA5761_TNCTRL_IFCTC 0x08 /* 1= IF count time 15.02 ms, 0= IF count time 2.02 ms */
+-#define TEA5761_TNCTRL_AFM 0x04
+-#define TEA5761_TNCTRL_SMUTE 0x02 /* 1= Soft mute */
+-#define TEA5761_TNCTRL_SNC 0x01
+-
+- /* second byte */
+-
+-#define TEA5761_TNCTRL_MU 0x80 /* 1=Hard mute */
+-#define TEA5761_TNCTRL_SSL_1 0x40
+-#define TEA5761_TNCTRL_SSL_0 0x20
+-#define TEA5761_TNCTRL_HLSI 0x10
+-#define TEA5761_TNCTRL_MST 0x08 /* 1 = mono */
+-#define TEA5761_TNCTRL_SWP 0x04
+-#define TEA5761_TNCTRL_DTC 0x02 /* 1 = deemphasis 50 us, 0 = deemphasis 75 us */
+-#define TEA5761_TNCTRL_AHLSI 0x01
+-
+-/* FRQCHECK - Read: bytes 6 and 7 */
+- /* First byte */
+-
+- /* Bits 0-5 for divider MSB */
+-
+- /* Second byte */
+- /* Bits 0-7 for divider LSB */
+-
+-/* TUNCHECK - Read: bytes 8 and 9 */
+-
+- /* First byte */
+-#define TEA5761_TUNCHECK_IF_MASK 0x7e /* IF count */
+-#define TEA5761_TUNCHECK_TUNTO 0x01
+-
+- /* Second byte */
+-#define TEA5761_TUNCHECK_LEV_MASK 0xf0 /* Level Count */
+-#define TEA5761_TUNCHECK_LD 0x08
+-#define TEA5761_TUNCHECK_STEREO 0x04
+-
+-/* TESTREG - Read: bytes 10 and 11 / Write: bytes 5 and 6 */
+-
+- /* All zero = no test mode */
+-
+-/* MANID - Read: bytes 12 and 13 */
+-
+- /* First byte - should be 0x10 */
+-#define TEA5767_MANID_VERSION_MASK 0xf0 /* Version = 1 */
+-#define TEA5767_MANID_ID_MSB_MASK 0x0f /* Manufacurer ID - should be 0 */
+-
+- /* Second byte - Should be 0x2b */
+-
+-#define TEA5767_MANID_ID_LSB_MASK 0xfe /* Manufacturer ID - should be 0x15 */
+-#define TEA5767_MANID_IDAV 0x01 /* 1 = Chip has ID, 0 = Chip has no ID */
+-
+-/* Chip ID - Read: bytes 14 and 15 */
+-
+- /* First byte - should be 0x57 */
+-
+- /* Second byte - should be 0x61 */
+-
+-/*****************************************************************************/
+-
+-#define FREQ_OFFSET 0 /* for TEA5767, it is 700 to give the right freq */
+-static void tea5761_status_dump(unsigned char *buffer)
+-{
+- unsigned int div, frq;
+-
+- div = ((buffer[2] & 0x3f) << 8) | buffer[3];
+-
+- frq = 1000 * (div * 32768 / 1000 + FREQ_OFFSET + 225) / 4; /* Freq in KHz */
+-
+- printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n",
+- frq / 1000, frq % 1000, div);
+-}
+-
+-/* Freq should be specifyed at 62.5 Hz */
+-static int set_radio_freq(struct dvb_frontend *fe,
+- struct analog_parameters *params)
+-{
+- struct tea5761_priv *priv = fe->tuner_priv;
+- unsigned int frq = params->frequency;
+- unsigned char buffer[7] = {0, 0, 0, 0, 0, 0, 0 };
+- unsigned div;
+- int rc;
+-
+- tuner_dbg("radio freq counter %d\n", frq);
+-
+- if (params->mode == T_STANDBY) {
+- tuner_dbg("TEA5761 set to standby mode\n");
+- buffer[5] |= TEA5761_TNCTRL_MU;
+- } else {
+- buffer[4] |= TEA5761_TNCTRL_PUPD_0;
+- }
+-
+-
+- if (params->audmode == V4L2_TUNER_MODE_MONO) {
+- tuner_dbg("TEA5761 set to mono\n");
+- buffer[5] |= TEA5761_TNCTRL_MST;
+- } else {
+- tuner_dbg("TEA5761 set to stereo\n");
+- }
+-
+- div = (1000 * (frq * 4 / 16 + 700 + 225) ) >> 15;
+- buffer[1] = (div >> 8) & 0x3f;
+- buffer[2] = div & 0xff;
+-
+- if (debug)
+- tea5761_status_dump(buffer);
+-
+- if (7 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 7)))
+- tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
+-
+- priv->frequency = frq * 125 / 2;
+-
+- return 0;
+-}
+-
+-static int tea5761_read_status(struct dvb_frontend *fe, char *buffer)
+-{
+- struct tea5761_priv *priv = fe->tuner_priv;
+- int rc;
+-
+- memset(buffer, 0, 16);
+- if (16 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 16))) {
+- tuner_warn("i2c i/o error: rc == %d (should be 16)\n", rc);
+- return -EREMOTEIO;
+- }
+-
+- return 0;
+-}
+-
+-static inline int tea5761_signal(struct dvb_frontend *fe, const char *buffer)
+-{
+- struct tea5761_priv *priv = fe->tuner_priv;
+-
+- int signal = ((buffer[9] & TEA5761_TUNCHECK_LEV_MASK) << (13 - 4));
+-
+- tuner_dbg("Signal strength: %d\n", signal);
+-
+- return signal;
+-}
+-
+-static inline int tea5761_stereo(struct dvb_frontend *fe, const char *buffer)
+-{
+- struct tea5761_priv *priv = fe->tuner_priv;
+-
+- int stereo = buffer[9] & TEA5761_TUNCHECK_STEREO;
+-
+- tuner_dbg("Radio ST GET = %02x\n", stereo);
+-
+- return (stereo ? V4L2_TUNER_SUB_STEREO : 0);
+-}
+-
+-static int tea5761_get_status(struct dvb_frontend *fe, u32 *status)
+-{
+- unsigned char buffer[16];
+-
+- *status = 0;
+-
+- if (0 == tea5761_read_status(fe, buffer)) {
+- if (tea5761_signal(fe, buffer))
+- *status = TUNER_STATUS_LOCKED;
+- if (tea5761_stereo(fe, buffer))
+- *status |= TUNER_STATUS_STEREO;
+- }
+-
+- return 0;
+-}
+-
+-static int tea5761_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
+-{
+- unsigned char buffer[16];
+-
+- *strength = 0;
+-
+- if (0 == tea5761_read_status(fe, buffer))
+- *strength = tea5761_signal(fe, buffer);
+-
+- return 0;
+-}
+-
+-int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
+-{
+- unsigned char buffer[16];
+- int rc;
+- struct tuner_i2c_props i2c = { .adap = i2c_adap, .addr = 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;
+- }
+-
+- 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");
+- return 0;
+-}
+-
+-static int tea5761_release(struct dvb_frontend *fe)
+-{
+- kfree(fe->tuner_priv);
+- fe->tuner_priv = NULL;
+-
+- return 0;
+-}
+-
+-static int tea5761_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+-{
+- struct tea5761_priv *priv = fe->tuner_priv;
+- *frequency = priv->frequency;
+- return 0;
+-}
+-
+-static struct dvb_tuner_ops tea5761_tuner_ops = {
+- .info = {
+- .name = "tea5761", // Philips TEA5761HN FM Radio
+- },
+- .set_analog_params = set_radio_freq,
+- .release = tea5761_release,
+- .get_frequency = tea5761_get_frequency,
+- .get_status = tea5761_get_status,
+- .get_rf_strength = tea5761_get_rf_strength,
+-};
+-
+-struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
+- struct i2c_adapter* i2c_adap,
+- u8 i2c_addr)
+-{
+- struct tea5761_priv *priv = NULL;
+-
+- if (tea5761_autodetection(i2c_adap, i2c_addr) == EINVAL)
+- return NULL;
+-
+- priv = kzalloc(sizeof(struct tea5761_priv), GFP_KERNEL);
+- if (priv == NULL)
+- return NULL;
+- fe->tuner_priv = priv;
+-
+- priv->i2c_props.addr = i2c_addr;
+- priv->i2c_props.adap = i2c_adap;
+-
+- memcpy(&fe->ops.tuner_ops, &tea5761_tuner_ops,
+- sizeof(struct dvb_tuner_ops));
+-
+- tuner_info("type set to %s\n", "Philips TEA5761HN FM Radio");
+-
+- return fe;
+-}
+-
+-
+-EXPORT_SYMBOL_GPL(tea5761_attach);
+-EXPORT_SYMBOL_GPL(tea5761_autodetection);
+-
+-MODULE_DESCRIPTION("Philips TEA5761 FM tuner driver");
+-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab at infradead.org>");
+-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/tea5761.h b/drivers/media/video/tea5761.h
-index 73a03b4..8eb6272 100644
+deleted file mode 100644
+index 73a03b4..0000000
--- 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",
++++ /dev/null
+@@ -1,47 +0,0 @@
+-/*
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2 of the License, or
+- (at your option) any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
+-
+- You 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 __TEA5761_H__
+-#define __TEA5761_H__
+-
+-#include <linux/i2c.h>
+-#include "dvb_frontend.h"
+-
+-#if defined(CONFIG_TUNER_TEA5761) || (defined(CONFIG_TUNER_TEA5761_MODULE) && defined(MODULE))
+-extern int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr);
+-
+-extern struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
+- struct i2c_adapter* i2c_adap,
+- u8 i2c_addr);
+-#else
+-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)
- {
+- return -EINVAL;
+-}
+-
+-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
+- return NULL;
+-}
+-#endif
+-
+-#endif /* __TEA5761_H__ */
diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c
-index e1b48d8..f6e7d7a 100644
+deleted file mode 100644
+index e1b48d8..0000000
--- a/drivers/media/video/tea5767.c
-+++ b/drivers/media/video/tea5767.c
-@@ -16,12 +16,10 @@
- #include "tuner-i2c.h"
- #include "tea5767.h"
-
++++ /dev/null
+@@ -1,479 +0,0 @@
+-/*
+- * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview
+- * I2C address is allways 0xC0.
+- *
+- *
+- * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab at infradead.org)
+- * This code is placed under the terms of the GNU General Public License
+- *
+- * tea5767 autodetection thanks to Torsten Seeboth and Atsushi Nakagawa
+- * from their contributions on DScaler.
+- */
+-
+-#include <linux/i2c.h>
+-#include <linux/delay.h>
+-#include <linux/videodev.h>
+-#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");
-
+-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])
+-/*****************************************************************************/
+-
+-struct tea5767_priv {
+- struct tuner_i2c_props i2c_props;
+- u32 frequency;
+- struct tea5767_ctrl ctrl;
+-};
+-
+-/*****************************************************************************/
+-
+-/******************************
+- * Write mode register values *
+- ******************************/
+-
+-/* First register */
+-#define TEA5767_MUTE 0x80 /* Mutes output */
+-#define TEA5767_SEARCH 0x40 /* Activates station search */
+-/* Bits 0-5 for divider MSB */
+-
+-/* Second register */
+-/* Bits 0-7 for divider LSB */
+-
+-/* Third register */
+-
+-/* Station search from botton to up */
+-#define TEA5767_SEARCH_UP 0x80
+-
+-/* Searches with ADC output = 10 */
+-#define TEA5767_SRCH_HIGH_LVL 0x60
+-
+-/* Searches with ADC output = 10 */
+-#define TEA5767_SRCH_MID_LVL 0x40
+-
+-/* Searches with ADC output = 5 */
+-#define TEA5767_SRCH_LOW_LVL 0x20
+-
+-/* if on, div=4*(Frf+Fif)/Fref otherwise, div=4*(Frf-Fif)/Freq) */
+-#define TEA5767_HIGH_LO_INJECT 0x10
+-
+-/* Disable stereo */
+-#define TEA5767_MONO 0x08
+-
+-/* Disable right channel and turns to mono */
+-#define TEA5767_MUTE_RIGHT 0x04
+-
+-/* Disable left channel and turns to mono */
+-#define TEA5767_MUTE_LEFT 0x02
+-
+-#define TEA5767_PORT1_HIGH 0x01
+-
+-/* Fourth register */
+-#define TEA5767_PORT2_HIGH 0x80
+-/* Chips stops working. Only I2C bus remains on */
+-#define TEA5767_STDBY 0x40
+-
+-/* Japan freq (76-108 MHz. If disabled, 87.5-108 MHz */
+-#define TEA5767_JAPAN_BAND 0x20
+-
+-/* Unselected means 32.768 KHz freq as reference. Otherwise Xtal at 13 MHz */
+-#define TEA5767_XTAL_32768 0x10
+-
+-/* Cuts weak signals */
+-#define TEA5767_SOFT_MUTE 0x08
+-
+-/* Activates high cut control */
+-#define TEA5767_HIGH_CUT_CTRL 0x04
+-
+-/* Activates stereo noise control */
+-#define TEA5767_ST_NOISE_CTL 0x02
+-
+-/* If activate PORT 1 indicates SEARCH or else it is used as PORT1 */
+-#define TEA5767_SRCH_IND 0x01
+-
+-/* Fifth register */
+-
+-/* By activating, it will use Xtal at 13 MHz as reference for divider */
+-#define TEA5767_PLLREF_ENABLE 0x80
+-
+-/* By activating, deemphasis=50, or else, deemphasis of 50us */
+-#define TEA5767_DEEMPH_75 0X40
+-
+-/*****************************
+- * Read mode register values *
+- *****************************/
+-
+-/* First register */
+-#define TEA5767_READY_FLAG_MASK 0x80
+-#define TEA5767_BAND_LIMIT_MASK 0X40
+-/* Bits 0-5 for divider MSB after search or preset */
+-
+-/* Second register */
+-/* Bits 0-7 for divider LSB after search or preset */
+-
+-/* Third register */
+-#define TEA5767_STEREO_MASK 0x80
+-#define TEA5767_IF_CNTR_MASK 0x7f
+-
+-/* Fourth register */
+-#define TEA5767_ADC_LEVEL_MASK 0xf0
+-
+-/* should be 0 */
+-#define TEA5767_CHIP_ID_MASK 0x0f
+-
+-/* Fifth register */
+-/* Reserved for future extensions */
+-#define TEA5767_RESERVED_MASK 0xff
+-
+-/*****************************************************************************/
+-
+-static void tea5767_status_dump(struct tea5767_priv *priv,
+- unsigned char *buffer)
+-{
+- unsigned int div, frq;
+-
+- if (TEA5767_READY_FLAG_MASK & buffer[0])
- printk(PREFIX "Ready Flag ON\n");
-+ tuner_info("Ready Flag ON\n");
- else
+- else
- printk(PREFIX "Ready Flag OFF\n");
-+ tuner_info("Ready Flag OFF\n");
-
- if (TEA5767_BAND_LIMIT_MASK & buffer[0])
+-
+- if (TEA5767_BAND_LIMIT_MASK & buffer[0])
- printk(PREFIX "Tuner at band limit\n");
-+ tuner_info("Tuner at band limit\n");
- else
+- 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;
-
+-
+- div = ((buffer[0] & 0x3f) << 8) | buffer[1];
+-
+- switch (priv->ctrl.xtal_freq) {
+- case TEA5767_HIGH_LO_13MHz:
+- frq = (div * 50000 - 700000 - 225000) / 4; /* Freq in KHz */
+- break;
+- case TEA5767_LOW_LO_13MHz:
+- frq = (div * 50000 + 700000 + 225000) / 4; /* Freq in KHz */
+- break;
+- case TEA5767_LOW_LO_32768:
+- frq = (div * 32768 + 700000 + 225000) / 4; /* Freq in KHz */
+- break;
+- case TEA5767_HIGH_LO_32768:
+- default:
+- frq = (div * 32768 - 700000 - 225000) / 4; /* Freq in KHz */
+- break;
+- }
+- 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])
+-
+- if (TEA5767_STEREO_MASK & buffer[2])
- printk(PREFIX "Stereo\n");
-+ tuner_info("Stereo\n");
- else
+- 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;
- }
-
+-}
+-
+-/* Freq should be specifyed at 62.5 Hz */
+-static int set_radio_freq(struct dvb_frontend *fe,
+- struct analog_parameters *params)
+-{
+- struct tea5767_priv *priv = fe->tuner_priv;
+- unsigned int frq = params->frequency;
+- unsigned char buffer[5];
+- unsigned div;
+- int rc;
+-
+- tuner_dbg("radio freq = %d.%03d MHz\n", frq/16000,(frq/16)%1000);
+-
+- buffer[2] = 0;
+-
+- if (priv->ctrl.port1)
+- buffer[2] |= TEA5767_PORT1_HIGH;
+-
+- if (params->audmode == V4L2_TUNER_MODE_MONO) {
+- tuner_dbg("TEA5767 set to mono\n");
+- buffer[2] |= TEA5767_MONO;
+- } else {
+- tuner_dbg("TEA5767 set to stereo\n");
+- }
+-
+-
+- buffer[3] = 0;
+-
+- if (priv->ctrl.port2)
+- buffer[3] |= TEA5767_PORT2_HIGH;
+-
+- if (priv->ctrl.high_cut)
+- buffer[3] |= TEA5767_HIGH_CUT_CTRL;
+-
+- if (priv->ctrl.st_noise)
+- buffer[3] |= TEA5767_ST_NOISE_CTL;
+-
+- if (priv->ctrl.soft_mute)
+- buffer[3] |= TEA5767_SOFT_MUTE;
+-
+- if (priv->ctrl.japan_band)
+- buffer[3] |= TEA5767_JAPAN_BAND;
+-
+- buffer[4] = 0;
+-
+- if (priv->ctrl.deemph_75)
+- buffer[4] |= TEA5767_DEEMPH_75;
+-
+- if (priv->ctrl.pllref)
+- buffer[4] |= TEA5767_PLLREF_ENABLE;
+-
+-
+- /* Rounds freq to next decimal value - for 62.5 KHz step */
+- /* frq = 20*(frq/16)+radio_frq[frq%16]; */
+-
+- switch (priv->ctrl.xtal_freq) {
+- case TEA5767_HIGH_LO_13MHz:
+- tuner_dbg("radio HIGH LO inject xtal @ 13 MHz\n");
+- buffer[2] |= TEA5767_HIGH_LO_INJECT;
+- div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000;
+- break;
+- case TEA5767_LOW_LO_13MHz:
+- tuner_dbg("radio LOW LO inject xtal @ 13 MHz\n");
+-
+- div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000;
+- break;
+- case TEA5767_LOW_LO_32768:
+- tuner_dbg("radio LOW LO inject xtal @ 32,768 MHz\n");
+- buffer[3] |= TEA5767_XTAL_32768;
+- /* const 700=4000*175 Khz - to adjust freq to right value */
+- div = ((frq * (4000 / 16) - 700000 - 225000) + 16384) >> 15;
+- break;
+- case TEA5767_HIGH_LO_32768:
+- default:
+- tuner_dbg("radio HIGH LO inject xtal @ 32,768 MHz\n");
+-
+- buffer[2] |= TEA5767_HIGH_LO_INJECT;
+- buffer[3] |= TEA5767_XTAL_32768;
+- div = ((frq * (4000 / 16) + 700000 + 225000) + 16384) >> 15;
+- break;
+- }
+- buffer[0] = (div >> 8) & 0x3f;
+- buffer[1] = div & 0xff;
+-
+- if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5)))
+- tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
+-
+- if (debug) {
+- if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5)))
+- tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
+- else
+- tea5767_status_dump(priv, buffer);
+- }
+-
+- priv->frequency = frq * 125 / 2;
+-
+- return 0;
+-}
+-
+-static int tea5767_read_status(struct dvb_frontend *fe, char *buffer)
+-{
+- struct tea5767_priv *priv = fe->tuner_priv;
+- int rc;
+-
+- memset(buffer, 0, 5);
+- if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5))) {
+- tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
+- return -EREMOTEIO;
+- }
+-
+- return 0;
+-}
+-
+-static inline int tea5767_signal(struct dvb_frontend *fe, const char *buffer)
+-{
+- struct tea5767_priv *priv = fe->tuner_priv;
+-
+- int signal = ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << 8);
+-
+- tuner_dbg("Signal strength: %d\n", signal);
+-
+- return signal;
+-}
+-
+-static inline int tea5767_stereo(struct dvb_frontend *fe, const char *buffer)
+-{
+- struct tea5767_priv *priv = fe->tuner_priv;
+-
+- int stereo = buffer[2] & TEA5767_STEREO_MASK;
+-
+- tuner_dbg("Radio ST GET = %02x\n", stereo);
+-
+- return (stereo ? V4L2_TUNER_SUB_STEREO : 0);
+-}
+-
+-static int tea5767_get_status(struct dvb_frontend *fe, u32 *status)
+-{
+- unsigned char buffer[5];
+-
+- *status = 0;
+-
+- if (0 == tea5767_read_status(fe, buffer)) {
+- if (tea5767_signal(fe, buffer))
+- *status = TUNER_STATUS_LOCKED;
+- if (tea5767_stereo(fe, buffer))
+- *status |= TUNER_STATUS_STEREO;
+- }
+-
+- return 0;
+-}
+-
+-static int tea5767_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
+-{
+- unsigned char buffer[5];
+-
+- *strength = 0;
+-
+- if (0 == tea5767_read_status(fe, buffer))
+- *strength = tea5767_signal(fe, buffer);
+-
+- return 0;
+-}
+-
+-static int tea5767_standby(struct dvb_frontend *fe)
+-{
+- unsigned char buffer[5];
+- struct tea5767_priv *priv = fe->tuner_priv;
+- unsigned div, rc;
+-
+- div = (87500 * 4 + 700 + 225 + 25) / 50; /* Set frequency to 87.5 MHz */
+- buffer[0] = (div >> 8) & 0x3f;
+- buffer[1] = div & 0xff;
+- buffer[2] = TEA5767_PORT1_HIGH;
+- buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL |
+- TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND | TEA5767_STDBY;
+- buffer[4] = 0;
+-
+- if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5)))
+- tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
+-
+- return 0;
+-}
+-
+-int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
+-{
+- struct tuner_i2c_props i2c = { .adap = i2c_adap, .addr = i2c_addr };
+- unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+- int rc;
+-
+- if ((rc = tuner_i2c_xfer_recv(&i2c, buffer, 7))< 5) {
+- printk(KERN_WARNING "It is not a TEA5767. Received %i bytes.\n", rc);
+- return EINVAL;
+- }
+-
+- /* If all bytes are the same then it's a TV tuner and not a tea5767 */
+- if (buffer[0] == buffer[1] && buffer[0] == buffer[2] &&
+- buffer[0] == buffer[3] && buffer[0] == buffer[4]) {
+- printk(KERN_WARNING "All bytes are equal. It is not a TEA5767\n");
+- return EINVAL;
+- }
+-
+- /* Status bytes:
+- * Byte 4: bit 3:1 : CI (Chip Identification) == 0
+- * bit 0 : internally set to 0
+- * Byte 5: bit 7:0 : == 0
+- */
+- if (((buffer[3] & 0x0f) != 0x00) || (buffer[4] != 0x00)) {
+- printk(KERN_WARNING "Chip ID is not zero. It is not a TEA5767\n");
+- 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;
+-
+- return 0;
+-}
+-
+-static int tea5767_release(struct dvb_frontend *fe)
+-{
+- kfree(fe->tuner_priv);
+- fe->tuner_priv = NULL;
+-
+- return 0;
+-}
+-
+-static int tea5767_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+-{
+- struct tea5767_priv *priv = fe->tuner_priv;
+- *frequency = priv->frequency;
+-
+- return 0;
+-}
+-
+-static int tea5767_set_config (struct dvb_frontend *fe, void *priv_cfg)
+-{
+- struct tea5767_priv *priv = fe->tuner_priv;
+-
+- memcpy(&priv->ctrl, priv_cfg, sizeof(priv->ctrl));
+-
+- return 0;
+-}
+-
+-static struct dvb_tuner_ops tea5767_tuner_ops = {
+- .info = {
+- .name = "tea5767", // Philips TEA5767HN FM Radio
+- },
+-
+- .set_analog_params = set_radio_freq,
+- .set_config = tea5767_set_config,
+- .sleep = tea5767_standby,
+- .release = tea5767_release,
+- .get_frequency = tea5767_get_frequency,
+- .get_status = tea5767_get_status,
+- .get_rf_strength = tea5767_get_rf_strength,
+-};
+-
+-struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
+- struct i2c_adapter* i2c_adap,
+- u8 i2c_addr)
+-{
+- struct tea5767_priv *priv = NULL;
+-
+- priv = kzalloc(sizeof(struct tea5767_priv), GFP_KERNEL);
+- if (priv == NULL)
+- return NULL;
+- fe->tuner_priv = priv;
+-
+- priv->i2c_props.addr = i2c_addr;
+- priv->i2c_props.adap = i2c_adap;
+- priv->ctrl.xtal_freq = TEA5767_HIGH_LO_32768;
+- priv->ctrl.port1 = 1;
+- priv->ctrl.port2 = 1;
+- priv->ctrl.high_cut = 1;
+- priv->ctrl.st_noise = 1;
+- priv->ctrl.japan_band = 1;
+-
+- memcpy(&fe->ops.tuner_ops, &tea5767_tuner_ops,
+- sizeof(struct dvb_tuner_ops));
+-
+- tuner_info("type set to %s\n", "Philips TEA5767HN FM Radio");
+-
+- return fe;
+-}
+-
+-EXPORT_SYMBOL_GPL(tea5767_attach);
+-EXPORT_SYMBOL_GPL(tea5767_autodetection);
+-
+-MODULE_DESCRIPTION("Philips TEA5767 FM tuner driver");
+-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab at infradead.org>");
+-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/tea5767.h b/drivers/media/video/tea5767.h
-index a44451f..7b547c0 100644
+deleted file mode 100644
+index a44451f..0000000
--- 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",
++++ /dev/null
+@@ -1,66 +0,0 @@
+-/*
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2 of the License, or
+- (at your option) any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
+-
+- You 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 __TEA5767_H__
+-#define __TEA5767_H__
+-
+-#include <linux/i2c.h>
+-#include "dvb_frontend.h"
+-
+-enum tea5767_xtal {
+- TEA5767_LOW_LO_32768 = 0,
+- TEA5767_HIGH_LO_32768 = 1,
+- TEA5767_LOW_LO_13MHz = 2,
+- TEA5767_HIGH_LO_13MHz = 3,
+-};
+-
+-struct tea5767_ctrl {
+- unsigned int port1:1;
+- unsigned int port2:1;
+- unsigned int high_cut:1;
+- unsigned int st_noise:1;
+- unsigned int soft_mute:1;
+- unsigned int japan_band:1;
+- unsigned int deemph_75:1;
+- unsigned int pllref:1;
+- enum tea5767_xtal xtal_freq;
+-};
+-
+-#if defined(CONFIG_TUNER_TEA5767) || (defined(CONFIG_TUNER_TEA5767_MODULE) && defined(MODULE))
+-extern int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr);
+-
+-extern struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
+- struct i2c_adapter* i2c_adap,
+- u8 i2c_addr);
+-#else
+-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)
- {
+- return -EINVAL;
+-}
+-
+-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
+- return NULL;
+-}
+-#endif
+-
+-#endif /* __TEA5767_H__ */
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
index df2fad9..9513d86 100644
--- a/drivers/media/video/tea6415c.c
@@ -416450,11 +585282,81 @@
/* 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/tlv320aic23b.c b/drivers/media/video/tlv320aic23b.c
+index dc7b9c2..f1db542 100644
+--- a/drivers/media/video/tlv320aic23b.c
++++ b/drivers/media/video/tlv320aic23b.c
+@@ -125,7 +125,8 @@ static int tlv320aic23b_command(struct i2c_client *client,
+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
+ */
+
+-static int tlv320aic23b_probe(struct i2c_client *client)
++static int tlv320aic23b_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct tlv320aic23b_state *state;
+
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
-index 78a09a2..2b72e10 100644
+index 78a09a2..6bf104e 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
-@@ -68,9 +68,9 @@ static unsigned short normal_i2c[] = {
+@@ -33,6 +33,46 @@
+
+ #define PREFIX t->i2c->driver->driver.name
+
++/** This macro allows us to probe dynamically, avoiding static links */
++#ifdef CONFIG_MEDIA_ATTACH
++#define tuner_symbol_probe(FUNCTION, ARGS...) ({ \
++ int __r = -EINVAL; \
++ typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
++ if (__a) { \
++ __r = (int) __a(ARGS); \
++ } else { \
++ printk(KERN_ERR "TUNER: Unable to find " \
++ "symbol "#FUNCTION"()\n"); \
++ } \
++ symbol_put(FUNCTION); \
++ __r; \
++})
++
++static void tuner_detach(struct dvb_frontend *fe)
++{
++ if (fe->ops.tuner_ops.release) {
++ fe->ops.tuner_ops.release(fe);
++ symbol_put_addr(fe->ops.tuner_ops.release);
++ }
++ if (fe->ops.analog_ops.release) {
++ fe->ops.analog_ops.release(fe);
++ symbol_put_addr(fe->ops.analog_ops.release);
++ }
++}
++#else
++#define tuner_symbol_probe(FUNCTION, ARGS...) ({ \
++ FUNCTION(ARGS); \
++})
++
++static void tuner_detach(struct dvb_frontend *fe)
++{
++ if (fe->ops.tuner_ops.release)
++ fe->ops.tuner_ops.release(fe);
++ if (fe->ops.analog_ops.release)
++ fe->ops.analog_ops.release(fe);
++}
++#endif
++
+ struct tuner {
+ /* device */
+ struct dvb_frontend fe;
+@@ -56,7 +96,7 @@ struct tuner {
+
+ /* standard i2c insmod options */
+ static unsigned short normal_i2c[] = {
+-#if defined(CONFIG_TUNER_TEA5761) || (defined(CONFIG_TUNER_TEA5761_MODULE) && defined(MODULE))
++#if defined(CONFIG_MEDIA_TUNER_TEA5761) || (defined(CONFIG_MEDIA_TUNER_TEA5761_MODULE) && defined(MODULE))
+ 0x10,
+ #endif
+ 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */
+@@ -68,9 +108,9 @@ static unsigned short normal_i2c[] = {
I2C_CLIENT_INSMOD;
/* insmod options used at init time => read/only */
@@ -416467,7 +585369,38 @@
/* insmod options used at runtime => read/write */
static int tuner_debug;
-@@ -313,24 +313,14 @@ static void tuner_i2c_address_check(struct tuner *t)
+@@ -139,22 +179,6 @@ static void fe_set_params(struct dvb_frontend *fe,
+ fe_tuner_ops->set_analog_params(fe, params);
+ }
+
+-static void fe_release(struct dvb_frontend *fe)
+-{
+- if (fe->ops.tuner_ops.release)
+- fe->ops.tuner_ops.release(fe);
+-
+- /* DO NOT kfree(fe->analog_demod_priv)
+- *
+- * If we are in this function, analog_demod_priv contains a pointer
+- * to struct tuner *t. This will be kfree'd in tuner_detach().
+- *
+- * Otherwise, fe->ops.analog_demod_ops->release will
+- * handle the cleanup for analog demodulator modules.
+- */
+- fe->analog_demod_priv = NULL;
+-}
+-
+ static void fe_standby(struct dvb_frontend *fe)
+ {
+ struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
+@@ -191,7 +215,6 @@ static void tuner_status(struct dvb_frontend *fe);
+ static struct analog_demod_ops tuner_core_ops = {
+ .set_params = fe_set_params,
+ .standby = fe_standby,
+- .release = fe_release,
+ .has_signal = fe_has_signal,
+ .set_config = fe_set_config,
+ .tuner_status = tuner_status
+@@ -313,27 +336,18 @@ static void tuner_i2c_address_check(struct tuner *t)
tuner_warn("output to v4l-dvb-maintainer at linuxtv.org\n");
tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n");
tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n",
@@ -416493,8 +585426,13 @@
+ .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,
+- tda829x_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
++ dvb_attach(tda829x_attach,
++ &t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
+ }
+
+ static struct xc5000_config xc5000_cfg;
+@@ -352,11 +366,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
return;
}
@@ -416506,7 +585444,24 @@
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,
+@@ -371,12 +380,13 @@ static void set_type(struct i2c_client *c, unsigned int type,
+ }
+
+ /* discard private data, in case set_type() was previously called */
+- if (analog_ops->release)
+- analog_ops->release(&t->fe);
++ tuner_detach(&t->fe);
++ t->fe.analog_demod_priv = NULL;
+
+ switch (t->type) {
+ case TUNER_MT2032:
+- microtune_attach(&t->fe, t->i2c->adapter, t->i2c->addr);
++ dvb_attach(microtune_attach,
++ &t->fe, t->i2c->adapter, t->i2c->addr);
+ break;
+ case TUNER_PHILIPS_TDA8290:
+ {
+@@ -384,19 +394,15 @@ static void set_type(struct i2c_client *c, unsigned int type,
break;
}
case TUNER_TEA5767:
@@ -416515,7 +585470,8 @@
- t->mode_mask = T_UNINITIALIZED;
- return;
- }
-+ if (!tea5767_attach(&t->fe, t->i2c->adapter, t->i2c->addr))
++ if (!dvb_attach(tea5767_attach, &t->fe,
++ t->i2c->adapter, t->i2c->addr))
+ goto attach_failed;
t->mode_mask = T_RADIO;
break;
@@ -416525,29 +585481,31 @@
- t->mode_mask = T_UNINITIALIZED;
- return;
- }
-+ if (!tea5761_attach(&t->fe, t->i2c->adapter, t->i2c->addr))
++ if (!dvb_attach(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,
+@@ -409,64 +415,70 @@ 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))
++ if (!dvb_attach(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[1] = 0xdc;
buffer[2] = 0x86;
buffer[3] = 0xa4;
- i2c_master_send(c,buffer,4);
+- i2c_master_send(c,buffer,4);
- attach_simple_tuner(t);
-+ if (!simple_tuner_attach(&t->fe, t->i2c->adapter,
-+ t->i2c->addr, t->type))
++ i2c_master_send(c, buffer, 4);
++ if (!dvb_attach(simple_tuner_attach, &t->fe,
++ t->i2c->adapter, t->i2c->addr, t->type))
+ goto attach_failed;
break;
case TUNER_XC2028:
@@ -416563,12 +585521,14 @@
- t->mode_mask = T_UNINITIALIZED;
- return;
- }
-+ if (!xc2028_attach(&t->fe, &cfg))
++ if (!dvb_attach(xc2028_attach, &t->fe, &cfg))
+ goto attach_failed;
break;
}
case TUNER_TDA9887:
- tda9887_attach(&t->fe, t->i2c->adapter, t->i2c->addr);
+- tda9887_attach(&t->fe, t->i2c->adapter, t->i2c->addr);
++ dvb_attach(tda9887_attach,
++ &t->fe, t->i2c->adapter, t->i2c->addr);
break;
case TUNER_XC5000:
+ {
@@ -416585,7 +585545,8 @@
- }
- {
- struct dvb_tuner_ops *xc_tuner_ops;
-+ if (!xc5000_attach(&t->fe, t->i2c->adapter, &xc5000_cfg))
++ if (!dvb_attach(xc5000_attach,
++ &t->fe, t->i2c->adapter, &xc5000_cfg))
+ goto attach_failed;
+
xc_tuner_ops = &t->fe.ops.tuner_ops;
@@ -416597,14 +585558,27 @@
+ }
default:
- attach_simple_tuner(t);
-+ if (!simple_tuner_attach(&t->fe, t->i2c->adapter,
-+ t->i2c->addr, t->type))
++ if (!dvb_attach(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 ((NULL == analog_ops->set_params) &&
+ (fe_tuner_ops->set_analog_params)) {
++
+ strlcpy(t->i2c->name, fe_tuner_ops->info.name,
+ sizeof(t->i2c->name));
+
+ t->fe.analog_demod_priv = t;
+ memcpy(analog_ops, &tuner_core_ops,
+ sizeof(struct analog_demod_ops));
++
+ } else {
+ strlcpy(t->i2c->name, analog_ops->info.name,
+ sizeof(t->i2c->name));
+@@ -477,11 +489,27 @@ static void set_type(struct i2c_client *c, unsigned int type,
if (t->mode_mask == T_UNINITIALIZED)
t->mode_mask = new_mode_mask;
@@ -416633,7 +585607,7 @@
}
/*
-@@ -496,14 +493,16 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
+@@ -496,14 +524,16 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
{
struct tuner *t = i2c_get_clientdata(c);
@@ -416653,7 +585627,30 @@
}
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)
+@@ -646,8 +676,8 @@ static void tuner_status(struct dvb_frontend *fe)
+ {
+ struct tuner *t = fe->analog_demod_priv;
+ unsigned long freq, freq_fraction;
+- struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
+- struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
++ struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
++ struct analog_demod_ops *analog_ops = &fe->ops.analog_ops;
+ const char *p;
+
+ switch (t->mode) {
+@@ -731,8 +761,10 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
+ struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
+ struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
+
+- if (tuner_debug>1)
++ if (tuner_debug > 1) {
+ v4l_i2c_print_ioctl(client,cmd);
++ printk("\n");
++ }
+
+ switch (cmd) {
+ /* --- configuration --- */
+@@ -759,7 +791,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (analog_ops->standby)
analog_ops->standby(&t->fe);
break;
@@ -416662,18 +585659,29 @@
case VIDIOCSAUDIO:
if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
return 0;
-@@ -1112,8 +1111,8 @@ static int tuner_probe(struct i2c_client *client)
+@@ -1074,7 +1106,8 @@ static void tuner_lookup(struct i2c_adapter *adap,
+ /* During client attach, set_type is called by adapter's attach_inform callback.
+ set_type must then be completed by tuner_probe.
+ */
+-static int tuner_probe(struct i2c_client *client)
++static int tuner_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct tuner *t;
+ struct tuner *radio;
+@@ -1112,8 +1145,9 @@ 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) {
++ if (tuner_symbol_probe(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)
+@@ -1125,15 +1159,15 @@ static int tuner_probe(struct i2c_client *client)
goto register_client;
}
@@ -416682,229 +585690,261 @@
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;
- };
+ case 0x4b:
+ /* If chip is not tda8290, don't register.
+ since it can be tda9887*/
+- if (tda829x_probe(t->i2c->adapter,
+- t->i2c->addr) == 0) {
++ if (tuner_symbol_probe(tda829x_probe, t->i2c->adapter,
++ t->i2c->addr) == 0) {
+ tuner_dbg("tda829x detected\n");
+ } else {
+ /* Default is being tda9887 */
+@@ -1145,7 +1179,8 @@ static int tuner_probe(struct i2c_client *client)
+ }
+ break;
+ case 0x60:
+- if (tea5767_autodetection(t->i2c->adapter, t->i2c->addr)
++ if (tuner_symbol_probe(tea5767_autodetection,
++ t->i2c->adapter, t->i2c->addr)
+ != EINVAL) {
+ t->type = TUNER_TEA5767;
+ t->mode_mask = T_RADIO;
+@@ -1234,10 +1269,9 @@ static int tuner_legacy_probe(struct i2c_adapter *adap)
+ static int tuner_remove(struct i2c_client *client)
+ {
+ struct tuner *t = i2c_get_clientdata(client);
+- struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
- 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;
- }
+- if (analog_ops->release)
+- analog_ops->release(&t->fe);
++ tuner_detach(&t->fe);
++ t->fe.analog_demod_priv = NULL;
+ list_del(&t->list);
+ kfree(t);
+diff --git a/drivers/media/video/tuner-i2c.h b/drivers/media/video/tuner-i2c.h
+deleted file mode 100644
+index de52e8f..0000000
+--- a/drivers/media/video/tuner-i2c.h
++++ /dev/null
+@@ -1,87 +0,0 @@
+-/*
+- tuner-i2c.h - i2c interface for different tuners
+-
+- Copyright (C) 2007 Michael Krufky (mkrufky at linuxtv.org)
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2 of the License, or
+- (at your option) any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
+-
+- You 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 __TUNER_I2C_H__
+-#define __TUNER_I2C_H__
+-
+-#include <linux/i2c.h>
+-
+-struct tuner_i2c_props {
+- u8 addr;
+- struct i2c_adapter *adap;
+-};
+-
+-static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, char *buf, int len)
+-{
+- struct i2c_msg msg = { .addr = props->addr, .flags = 0,
+- .buf = buf, .len = len };
+- int ret = i2c_transfer(props->adap, &msg, 1);
+-
+- return (ret == 1) ? len : ret;
+-}
+-
+-static inline int tuner_i2c_xfer_recv(struct tuner_i2c_props *props, char *buf, int len)
+-{
+- struct i2c_msg msg = { .addr = props->addr, .flags = I2C_M_RD,
+- .buf = buf, .len = len };
+- int ret = i2c_transfer(props->adap, &msg, 1);
+-
+- return (ret == 1) ? len : ret;
+-}
+-
+-static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props,
+- char *obuf, int olen,
+- char *ibuf, int ilen)
+-{
+- struct i2c_msg msg[2] = { { .addr = props->addr, .flags = 0,
+- .buf = obuf, .len = olen },
+- { .addr = props->addr, .flags = I2C_M_RD,
+- .buf = ibuf, .len = ilen } };
+- int ret = i2c_transfer(props->adap, msg, 2);
+-
+- 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)
-
+- } 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)
-
+- } 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)
-
+- } 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)) \
+- 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__ */
+- } while (0)
+-
+-#endif /* __TUNER_I2C_H__ */
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
-index c1db576..be8d903 100644
+deleted file mode 100644
+index c1db576..0000000
--- 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"
-
++++ /dev/null
+@@ -1,652 +0,0 @@
+-/*
+- * i2c tv tuner chip device driver
+- * controls all those simple 4-control-bytes style tuners.
+- *
+- * This "tuner-simple" module was split apart from the original "tuner" module.
+- */
+-#include <linux/delay.h>
+-#include <linux/i2c.h>
+-#include <linux/videodev.h>
+-#include <media/tuner.h>
+-#include <media/v4l2-common.h>
+-#include <media/tuner-types.h>
+-#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");
-
+-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_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
+-
+-/* ---------------------------------------------------------------------- */
+-
+-/* tv standard selection for Temic 4046 FM5
+- this value takes the low bits of control byte 2
+- from datasheet Rev.01, Feb.00
+- standard BG I L L2 D
+- picture IF 38.9 38.9 38.9 33.95 38.9
+- sound 1 33.4 32.9 32.4 40.45 32.4
+- sound 2 33.16
+- NICAM 33.05 32.348 33.05 33.05
+- */
+-#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;
-
+-#define TEMIC_SET_PAL_BG 0x0c
+-
+-/* tv tuner system standard selection for Philips FQ1216ME
+- this value takes the low bits of control byte 2
+- from datasheet "1999 Nov 16" (supersedes "1999 Mar 23")
+- standard BG DK I L L`
+- picture carrier 38.90 38.90 38.90 38.90 33.95
+- colour 34.47 34.47 34.47 34.47 38.38
+- sound 1 33.40 32.40 32.90 32.40 40.45
+- sound 2 33.16 - - - -
+- NICAM 33.05 33.05 32.35 33.05 39.80
+- */
+-#define PHILIPS_SET_PAL_I 0x01 /* Bit 2 always zero !*/
+-#define PHILIPS_SET_PAL_BGDK 0x09
+-#define PHILIPS_SET_PAL_L2 0x0a
+-#define PHILIPS_SET_PAL_L 0x0b
+-
+-/* system switching for Philips FI1216MF MK2
+- from datasheet "1996 Jul 09",
+- standard BG L L'
+- picture carrier 38.90 38.90 33.95
+- colour 34.47 34.37 38.38
+- sound 1 33.40 32.40 40.45
+- sound 2 33.16 - -
+- NICAM 33.05 33.05 39.80
+- */
+-#define PHILIPS_MF_SET_STD_BG 0x01 /* Bit 2 must be zero, Bit 3 is system output */
+-#define PHILIPS_MF_SET_STD_L 0x03 /* Used on Secam France */
+-#define PHILIPS_MF_SET_STD_LC 0x02 /* Used on SECAM L' */
+-
+-/* Control byte */
+-
+-#define TUNER_RATIO_MASK 0x06 /* Bit cb1:cb2 */
+-#define TUNER_RATIO_SELECT_50 0x00
+-#define TUNER_RATIO_SELECT_32 0x02
+-#define TUNER_RATIO_SELECT_166 0x04
+-#define TUNER_RATIO_SELECT_62 0x06
+-
+-#define TUNER_CHARGE_PUMP 0x40 /* Bit cb6 */
+-
+-/* Status byte */
+-
+-#define TUNER_POR 0x80
+-#define TUNER_FL 0x40
+-#define TUNER_MODE 0x38
+-#define TUNER_AFC 0x07
+-#define TUNER_SIGNAL 0x07
+-#define TUNER_STEREO 0x10
+-
+-#define TUNER_PLL_LOCKED 0x40
+-#define TUNER_STEREO_MK3 0x04
+-
+-struct tuner_simple_priv {
+- u16 last_div;
+- struct tuner_i2c_props i2c_props;
+-
+- unsigned int type;
+- struct tunertype *tun;
+-
+- u32 frequency;
+-};
+-
+-/* ---------------------------------------------------------------------- */
+-
+-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) {
+- return 0;
+-
+- return byte;
+-}
+-
+-static inline int tuner_signal(const int status)
+-{
+- return (status & TUNER_SIGNAL) << 13;
+-}
+-
+-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:
@@ -416912,52 +585952,54 @@
- 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;
+- }
+-}
+-
+-static inline int tuner_islocked(const int status)
+-{
+- return (status & TUNER_FL);
+-}
+-
+-static inline int tuner_afcstatus(const int status)
+-{
+- return (status & TUNER_AFC) - 2;
+-}
+-
+-
+-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;
+-
+- *status = 0;
+-
+- if (tuner_islocked(tuner_status))
+- *status = TUNER_STATUS_LOCKED;
+- if (tuner_stereo(priv->type, tuner_status))
+- *status |= TUNER_STATUS_STEREO;
+-
+- tuner_dbg("AFC Status: %d\n", tuner_afcstatus(tuner_status));
+-
+- return 0;
+-}
+-
+-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)
-
- /* ---------------------------------------------------------------------- */
-
+-
+- *strength = signal;
+-
+- tuner_dbg("Signal strength: %d\n", signal);
+-
+- return 0;
+-}
+-
+-/* ---------------------------------------------------------------------- */
+-
-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;
@@ -416966,32 +586008,9 @@
- 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
@@ -417003,13 +586022,7 @@
- 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;
@@ -417024,10 +586037,7 @@
- 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;
@@ -417038,428 +586048,181 @@
- 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++) {
+-
+- 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) {
+- 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) {
+-
+- /* 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 ??? */
+- /* 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)
+- 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 */
+- else /* V4L2_STD_B|V4L2_STD_GH */
- cb |= PHILIPS_MF_SET_STD_BG;
-+ *cb |= PHILIPS_MF_SET_STD_BG;
- break;
-
- case TUNER_TEMIC_4046FM5:
+- break;
+-
+- case TUNER_TEMIC_4046FM5:
- cb &= ~0x0f;
-+ *cb &= ~0x0f;
-
- if (params->std & V4L2_STD_PAL_BG) {
+-
+- 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) {
+-
+- } 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) {
+-
+- } 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) {
+-
+- } else if (params->std & V4L2_STD_SECAM_L) {
- cb |= TEMIC_SET_PAL_L;
-+ *cb |= TEMIC_SET_PAL_L;
-
- }
- break;
-
- case TUNER_PHILIPS_FQ1216ME:
+-
+- }
+- break;
+-
+- case TUNER_PHILIPS_FQ1216ME:
- cb &= ~0x0f;
-+ *cb &= ~0x0f;
-
- if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) {
+-
+- 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) {
+-
+- } 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) {
+-
+- } else if (params->std & V4L2_STD_SECAM_L) {
- cb |= PHILIPS_SET_PAL_L;
-+ *cb |= PHILIPS_SET_PAL_L;
-
- }
- break;
-
+-
+- }
+- 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 */
+- /* 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))
+- if (!(params->std & V4L2_STD_ATSC))
- cb |= 2;
- /* FIXME: input */
-+ *cb |= 2;
- break;
-
- case TUNER_MICROTUNE_4042FI5:
- /* Set the charge pump for fast tuning */
+- 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 */
+- 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) {
+- 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;
+- 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;
+- 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;
+- break;
+- }
+-
+- if (t_params->cb_first_if_lower_freq && div < priv->last_div) {
+- buffer[0] = config;
+- buffer[1] = cb;
+- buffer[2] = (div>>8) & 0x7f;
+- buffer[3] = div & 0xff;
+- } else {
+- buffer[0] = (div>>8) & 0x7f;
+- buffer[1] = div & 0xff;
+- buffer[2] = config;
+- buffer[3] = cb;
+- }
+- priv->last_div = div;
+- 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;
+-
+- tda9887_cfg.tuner = TUNER_TDA9887;
+- tda9887_cfg.priv = &config;
+-
+- if (params->std == V4L2_STD_SECAM_LC) {
+- if (t_params->port1_active ^ t_params->port1_invert_for_secam_lc)
+- 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);
+- if (t_params->port1_active)
+- config |= TDA9887_PORT1_ACTIVE;
+- if (t_params->port2_active)
+- config |= TDA9887_PORT2_ACTIVE;
+- }
+- if (t_params->intercarrier_mode)
+- config |= TDA9887_INTERCARRIER;
+- if (is_secam_l) {
+- if (i == 0 && t_params->default_top_secam_low)
+- config |= TDA9887_TOP(t_params->default_top_secam_low);
+- else if (i == 1 && t_params->default_top_secam_mid)
+- 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",
+- 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)
+- config |= TDA9887_TOP(t_params->default_top_mid);
+- else if (t_params->default_top_high)
+- config |= TDA9887_TOP(t_params->default_top_high);
+- }
+- if (t_params->default_pll_gating_18)
+- config |= TDA9887_GATING_18;
+- i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,
+- &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)))
@@ -417482,8 +586245,7 @@
- // 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))
@@ -417496,10 +586258,7 @@
- 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;
@@ -417508,27 +586267,51 @@
- 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:
+- return 0;
+-}
+-
+-static int simple_set_radio_freq(struct dvb_frontend *fe,
+- struct analog_parameters *params)
+-{
+- struct tunertype *tun;
+- struct tuner_simple_priv *priv = fe->tuner_priv;
+- u8 buffer[4];
+- u16 div;
+- int rc, j;
+- struct tuner_params *t_params;
+- unsigned int freq = params->frequency;
+-
+- tun = priv->tun;
+-
+- for (j = tun->count-1; j > 0; j--)
+- if (tun->params[j].type == TUNER_PARAM_TYPE_RADIO)
+- break;
+- /* default t_params (j=0) will be used if desired type wasn't found */
+- t_params = &tun->params[j];
+-
+- /* Select Radio 1st IF used */
+- switch (t_params->radio_if) {
+- case 0: /* 10.7 MHz */
+- freq += (unsigned int)(10.7*16000);
+- break;
+- case 1: /* 33.3 MHz */
+- freq += (unsigned int)(33.3*16000);
+- break;
+- case 2: /* 41.3 MHz */
+- 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 */
+- return 0;
+- }
+-
+- /* Bandswitch byte */
- switch (priv->type) {
- case TUNER_TENA_9533_DI:
- case TUNER_YMEC_TVF_5533MF:
@@ -417555,407 +586338,170 @@
- 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[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) |
+- TUNER_RATIO_SELECT_50; /* 50 kHz step */
+-
+- /* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps
+- freq * (1 Mhz / 16000 V4L steps) * (20 PLL steps / 1 MHz) =
+- freq * (1/800) */
+- div = (freq + 400) / 800;
+-
+- if (t_params->cb_first_if_lower_freq && div < priv->last_div) {
+- buffer[0] = buffer[2];
+- buffer[1] = buffer[3];
+- buffer[2] = (div>>8) & 0x7f;
+- buffer[3] = div & 0xff;
+- } else {
+- buffer[0] = (div>>8) & 0x7f;
+- buffer[1] = div & 0xff;
+- }
+-
+- 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;
-
+- priv->last_div = div;
+-
+- if (t_params->has_tda9887) {
+- int config = 0;
+- struct v4l2_priv_tun_config tda9887_cfg;
+-
+- 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;
+- 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,
+- config |= TDA9887_PORT2_ACTIVE;
+- if (t_params->intercarrier_mode)
+- config |= TDA9887_INTERCARRIER;
+-/* if (t_params->port1_set_for_fm_mono)
+- config &= ~TDA9887_PORT1_ACTIVE;*/
+- if (t_params->fm_gain_normal)
+- config |= TDA9887_GAIN_NORMAL;
+- 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)
- {
+-
+- return 0;
+-}
+-
+-static int simple_set_params(struct dvb_frontend *fe,
+- struct analog_parameters *params)
+-{
+- struct tuner_simple_priv *priv = fe->tuner_priv;
+- int ret = -EINVAL;
+-
+- switch (params->mode) {
+- case V4L2_TUNER_RADIO:
+- ret = simple_set_radio_freq(fe, params);
+- priv->frequency = params->frequency * 125 / 2;
+- break;
+- case V4L2_TUNER_ANALOG_TV:
+- case V4L2_TUNER_DIGITAL_TV:
+- ret = simple_set_tv_freq(fe, params);
+- priv->frequency = params->frequency * 62500;
+- break;
+- }
+-
+- return ret;
+-}
+-
+-
+-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,
+- fe->tuner_priv = NULL;
+-
+- return 0;
+-}
+-
+-static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+-{
+- struct tuner_simple_priv *priv = fe->tuner_priv;
+- *frequency = priv->frequency;
+- return 0;
+-}
+-
+-static struct dvb_tuner_ops simple_tuner_ops = {
+- .set_analog_params = simple_set_params,
+- .release = simple_release,
+- .get_frequency = simple_get_frequency,
+- .get_status = simple_get_status,
+- .get_rf_strength = simple_get_rf_strength,
+-};
+-
+-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;
-
+-{
+- struct tuner_simple_priv *priv = NULL;
+-
- 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;
+- 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");
+-
+-
+-EXPORT_SYMBOL_GPL(simple_tuner_attach);
+-
+-MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver");
+-MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
+-MODULE_LICENSE("GPL");
+-
+-/*
+- * Overrides for Emacs so that we follow Linus's tabbing style.
+- * ---------------------------------------------------------------------------
+- * Local variables:
+- * c-basic-offset: 8
+- * End:
+- */
diff --git a/drivers/media/video/tuner-simple.h b/drivers/media/video/tuner-simple.h
-index 9089939..e46cf01 100644
+deleted file mode 100644
+index 9089939..0000000
--- a/drivers/media/video/tuner-simple.h
-+++ b/drivers/media/video/tuner-simple.h
-@@ -20,25 +20,18 @@
- #include <linux/i2c.h>
- #include "dvb_frontend.h"
-
++++ /dev/null
+@@ -1,46 +0,0 @@
+-/*
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2 of the License, or
+- (at your option) any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
+-
+- You 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 __TUNER_SIMPLE_H__
+-#define __TUNER_SIMPLE_H__
+-
+-#include <linux/i2c.h>
+-#include "dvb_frontend.h"
+-
-struct simple_tuner_config
-{
- /* chip type */
@@ -417963,760 +586509,2695 @@
- 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,
+-#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,
+-#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
+- return NULL;
+-}
+-#endif
+-
+-#endif /* __TUNER_SIMPLE_H__ */
diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c
-index 883047f..10dddca 100644
+deleted file mode 100644
+index 883047f..0000000
--- 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[] = {
- },
- };
-
++++ /dev/null
+@@ -1,1484 +0,0 @@
+-/*
+- *
+- * i2c tv tuner chip device type database.
+- *
+- */
+-
+-#include <linux/i2c.h>
+-#include <media/tuner.h>
+-#include <media/tuner-types.h>
+-
+-/* ---------------------------------------------------------------------- */
+-
+-/*
+- * The floats in the tuner struct are computed at compile time
+- * by gcc and cast back to integers. Thus we don't violate the
+- * "no float in kernel" rule.
+- *
+- * A tuner_range may be referenced by multiple tuner_params structs.
+- * There are many duplicates in here. Reusing tuner_range structs,
+- * rather than defining new ones for each tuner, will cut down on
+- * memory usage, and is preferred when possible.
+- *
+- * Each tuner_params array may contain one or more elements, one
+- * for each video standard.
+- *
+- * FIXME: tuner_params struct contains an element, tda988x. We must
+- * set this for all tuners that contain a tda988x chip, and then we
+- * can remove this setting from the various card structs.
+- *
+- * FIXME: Right now, all tuners are using the first tuner_params[]
+- * array element for analog mode. In the future, we will be merging
+- * similar tuner definitions together, such that each tuner definition
+- * will have a tuner_params struct for each available video standard.
+- * At that point, the tuner_params[] array element will be chosen
+- * based on the video standard in use.
+- */
+-
+-/* 0-9 */
+-/* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */
+-
+-static struct tuner_range tuner_temic_pal_ranges[] = {
+- { 16 * 140.25 /*MHz*/, 0x8e, 0x02, },
+- { 16 * 463.25 /*MHz*/, 0x8e, 0x04, },
+- { 16 * 999.99 , 0x8e, 0x01, },
+-};
+-
+-static struct tuner_params tuner_temic_pal_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_temic_pal_ranges,
+- .count = ARRAY_SIZE(tuner_temic_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_PAL_I - Philips PAL_I ------------ */
+-
+-static struct tuner_range tuner_philips_pal_i_ranges[] = {
+- { 16 * 140.25 /*MHz*/, 0x8e, 0xa0, },
+- { 16 * 463.25 /*MHz*/, 0x8e, 0x90, },
+- { 16 * 999.99 , 0x8e, 0x30, },
+-};
+-
+-static struct tuner_params tuner_philips_pal_i_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_philips_pal_i_ranges,
+- .count = ARRAY_SIZE(tuner_philips_pal_i_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_NTSC - Philips NTSC ------------ */
+-
+-static struct tuner_range tuner_philips_ntsc_ranges[] = {
+- { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, },
+- { 16 * 451.25 /*MHz*/, 0x8e, 0x90, },
+- { 16 * 999.99 , 0x8e, 0x30, },
+-};
+-
+-static struct tuner_params tuner_philips_ntsc_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_philips_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_philips_ntsc_ranges),
+- .cb_first_if_lower_freq = 1,
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_SECAM - Philips SECAM ------------ */
+-
+-static struct tuner_range tuner_philips_secam_ranges[] = {
+- { 16 * 168.25 /*MHz*/, 0x8e, 0xa7, },
+- { 16 * 447.25 /*MHz*/, 0x8e, 0x97, },
+- { 16 * 999.99 , 0x8e, 0x37, },
+-};
+-
+-static struct tuner_params tuner_philips_secam_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_SECAM,
+- .ranges = tuner_philips_secam_ranges,
+- .count = ARRAY_SIZE(tuner_philips_secam_ranges),
+- .cb_first_if_lower_freq = 1,
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_PAL - Philips PAL ------------ */
+-
+-static struct tuner_range tuner_philips_pal_ranges[] = {
+- { 16 * 168.25 /*MHz*/, 0x8e, 0xa0, },
+- { 16 * 447.25 /*MHz*/, 0x8e, 0x90, },
+- { 16 * 999.99 , 0x8e, 0x30, },
+-};
+-
+-static struct tuner_params tuner_philips_pal_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_philips_pal_ranges,
+- .count = ARRAY_SIZE(tuner_philips_pal_ranges),
+- .cb_first_if_lower_freq = 1,
+- },
+-};
+-
+-/* ------------ TUNER_TEMIC_NTSC - TEMIC NTSC ------------ */
+-
+-static struct tuner_range tuner_temic_ntsc_ranges[] = {
+- { 16 * 157.25 /*MHz*/, 0x8e, 0x02, },
+- { 16 * 463.25 /*MHz*/, 0x8e, 0x04, },
+- { 16 * 999.99 , 0x8e, 0x01, },
+-};
+-
+-static struct tuner_params tuner_temic_ntsc_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_temic_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_temic_ntsc_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_TEMIC_PAL_I - TEMIC PAL_I ------------ */
+-
+-static struct tuner_range tuner_temic_pal_i_ranges[] = {
+- { 16 * 170.00 /*MHz*/, 0x8e, 0x02, },
+- { 16 * 450.00 /*MHz*/, 0x8e, 0x04, },
+- { 16 * 999.99 , 0x8e, 0x01, },
+-};
+-
+-static struct tuner_params tuner_temic_pal_i_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_temic_pal_i_ranges,
+- .count = ARRAY_SIZE(tuner_temic_pal_i_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_TEMIC_4036FY5_NTSC - TEMIC NTSC ------------ */
+-
+-static struct tuner_range tuner_temic_4036fy5_ntsc_ranges[] = {
+- { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, },
+- { 16 * 463.25 /*MHz*/, 0x8e, 0x90, },
+- { 16 * 999.99 , 0x8e, 0x30, },
+-};
+-
+-static struct tuner_params tuner_temic_4036fy5_ntsc_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_temic_4036fy5_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_ALPS_TSBH1_NTSC - TEMIC NTSC ------------ */
+-
+-static struct tuner_range tuner_alps_tsb_1_ranges[] = {
+- { 16 * 137.25 /*MHz*/, 0x8e, 0x01, },
+- { 16 * 385.25 /*MHz*/, 0x8e, 0x02, },
+- { 16 * 999.99 , 0x8e, 0x08, },
+-};
+-
+-static struct tuner_params tuner_alps_tsbh1_ntsc_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_alps_tsb_1_ranges,
+- .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges),
+- },
+-};
+-
+-/* 10-19 */
+-/* ------------ TUNER_ALPS_TSBE1_PAL - TEMIC PAL ------------ */
+-
+-static struct tuner_params tuner_alps_tsb_1_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_alps_tsb_1_ranges,
+- .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_ALPS_TSBB5_PAL_I - Alps PAL_I ------------ */
+-
+-static struct tuner_range tuner_alps_tsb_5_pal_ranges[] = {
+- { 16 * 133.25 /*MHz*/, 0x8e, 0x01, },
+- { 16 * 351.25 /*MHz*/, 0x8e, 0x02, },
+- { 16 * 999.99 , 0x8e, 0x08, },
+-};
+-
+-static struct tuner_params tuner_alps_tsbb5_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_alps_tsb_5_pal_ranges,
+- .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_ALPS_TSBE5_PAL - Alps PAL ------------ */
+-
+-static struct tuner_params tuner_alps_tsbe5_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_alps_tsb_5_pal_ranges,
+- .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_ALPS_TSBC5_PAL - Alps PAL ------------ */
+-
+-static struct tuner_params tuner_alps_tsbc5_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_alps_tsb_5_pal_ranges,
+- .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_TEMIC_4006FH5_PAL - TEMIC PAL ------------ */
+-
+-static struct tuner_range tuner_lg_pal_ranges[] = {
+- { 16 * 170.00 /*MHz*/, 0x8e, 0xa0, },
+- { 16 * 450.00 /*MHz*/, 0x8e, 0x90, },
+- { 16 * 999.99 , 0x8e, 0x30, },
+-};
+-
+-static struct tuner_params tuner_temic_4006fh5_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_lg_pal_ranges,
+- .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_ALPS_TSHC6_NTSC - Alps NTSC ------------ */
+-
+-static struct tuner_range tuner_alps_tshc6_ntsc_ranges[] = {
+- { 16 * 137.25 /*MHz*/, 0x8e, 0x14, },
+- { 16 * 385.25 /*MHz*/, 0x8e, 0x12, },
+- { 16 * 999.99 , 0x8e, 0x11, },
+-};
+-
+-static struct tuner_params tuner_alps_tshc6_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_alps_tshc6_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_alps_tshc6_ntsc_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_TEMIC_PAL_DK - TEMIC PAL ------------ */
+-
+-static struct tuner_range tuner_temic_pal_dk_ranges[] = {
+- { 16 * 168.25 /*MHz*/, 0x8e, 0xa0, },
+- { 16 * 456.25 /*MHz*/, 0x8e, 0x90, },
+- { 16 * 999.99 , 0x8e, 0x30, },
+-};
+-
+-static struct tuner_params tuner_temic_pal_dk_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_temic_pal_dk_ranges,
+- .count = ARRAY_SIZE(tuner_temic_pal_dk_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_NTSC_M - Philips NTSC ------------ */
+-
+-static struct tuner_range tuner_philips_ntsc_m_ranges[] = {
+- { 16 * 160.00 /*MHz*/, 0x8e, 0xa0, },
+- { 16 * 454.00 /*MHz*/, 0x8e, 0x90, },
+- { 16 * 999.99 , 0x8e, 0x30, },
+-};
+-
+-static struct tuner_params tuner_philips_ntsc_m_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_philips_ntsc_m_ranges,
+- .count = ARRAY_SIZE(tuner_philips_ntsc_m_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_TEMIC_4066FY5_PAL_I - TEMIC PAL_I ------------ */
+-
+-static struct tuner_range tuner_temic_40x6f_5_pal_ranges[] = {
+- { 16 * 169.00 /*MHz*/, 0x8e, 0xa0, },
+- { 16 * 454.00 /*MHz*/, 0x8e, 0x90, },
+- { 16 * 999.99 , 0x8e, 0x30, },
+-};
+-
+-static struct tuner_params tuner_temic_4066fy5_pal_i_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_temic_40x6f_5_pal_ranges,
+- .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_TEMIC_4006FN5_MULTI_PAL - TEMIC PAL ------------ */
+-
+-static struct tuner_params tuner_temic_4006fn5_multi_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_temic_40x6f_5_pal_ranges,
+- .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
+- },
+-};
+-
+-/* 20-29 */
+-/* ------------ TUNER_TEMIC_4009FR5_PAL - TEMIC PAL ------------ */
+-
+-static struct tuner_range tuner_temic_4009f_5_pal_ranges[] = {
+- { 16 * 141.00 /*MHz*/, 0x8e, 0xa0, },
+- { 16 * 464.00 /*MHz*/, 0x8e, 0x90, },
+- { 16 * 999.99 , 0x8e, 0x30, },
+-};
+-
+-static struct tuner_params tuner_temic_4009f_5_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_temic_4009f_5_pal_ranges,
+- .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_TEMIC_4039FR5_NTSC - TEMIC NTSC ------------ */
+-
+-static struct tuner_range tuner_temic_4x3x_f_5_ntsc_ranges[] = {
+- { 16 * 158.00 /*MHz*/, 0x8e, 0xa0, },
+- { 16 * 453.00 /*MHz*/, 0x8e, 0x90, },
+- { 16 * 999.99 , 0x8e, 0x30, },
+-};
+-
+-static struct tuner_params tuner_temic_4039fr5_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_temic_4x3x_f_5_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_temic_4x3x_f_5_ntsc_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_TEMIC_4046FM5 - TEMIC PAL ------------ */
+-
+-static struct tuner_params tuner_temic_4046fm5_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_temic_40x6f_5_pal_ranges,
+- .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_PAL_DK - Philips PAL ------------ */
+-
+-static struct tuner_params tuner_philips_pal_dk_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_lg_pal_ranges,
+- .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_FQ1216ME - Philips PAL ------------ */
+-
+-static struct tuner_params tuner_philips_fq1216me_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_lg_pal_ranges,
+- .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+- .has_tda9887 = 1,
+- .port1_active = 1,
+- .port2_active = 1,
+- .port2_invert_for_secam_lc = 1,
+- },
+-};
+-
+-/* ------------ TUNER_LG_PAL_I_FM - LGINNOTEK PAL_I ------------ */
+-
+-static struct tuner_params tuner_lg_pal_i_fm_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_lg_pal_ranges,
+- .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_LG_PAL_I - LGINNOTEK PAL_I ------------ */
+-
+-static struct tuner_params tuner_lg_pal_i_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_lg_pal_ranges,
+- .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_LG_NTSC_FM - LGINNOTEK NTSC ------------ */
+-
+-static struct tuner_range tuner_lg_ntsc_fm_ranges[] = {
+- { 16 * 210.00 /*MHz*/, 0x8e, 0xa0, },
+- { 16 * 497.00 /*MHz*/, 0x8e, 0x90, },
+- { 16 * 999.99 , 0x8e, 0x30, },
+-};
+-
+-static struct tuner_params tuner_lg_ntsc_fm_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_lg_ntsc_fm_ranges,
+- .count = ARRAY_SIZE(tuner_lg_ntsc_fm_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_LG_PAL_FM - LGINNOTEK PAL ------------ */
+-
+-static struct tuner_params tuner_lg_pal_fm_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_lg_pal_ranges,
+- .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_LG_PAL - LGINNOTEK PAL ------------ */
+-
+-static struct tuner_params tuner_lg_pal_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_lg_pal_ranges,
+- .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+- },
+-};
+-
+-/* 30-39 */
+-/* ------------ TUNER_TEMIC_4009FN5_MULTI_PAL_FM - TEMIC PAL ------------ */
+-
+-static struct tuner_params tuner_temic_4009_fn5_multi_pal_fm_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_temic_4009f_5_pal_ranges,
+- .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_SHARP_2U5JF5540_NTSC - SHARP NTSC ------------ */
+-
+-static struct tuner_range tuner_sharp_2u5jf5540_ntsc_ranges[] = {
+- { 16 * 137.25 /*MHz*/, 0x8e, 0x01, },
+- { 16 * 317.25 /*MHz*/, 0x8e, 0x02, },
+- { 16 * 999.99 , 0x8e, 0x08, },
+-};
+-
+-static struct tuner_params tuner_sharp_2u5jf5540_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_sharp_2u5jf5540_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_sharp_2u5jf5540_ntsc_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_Samsung_PAL_TCPM9091PD27 - Samsung PAL ------------ */
+-
+-static struct tuner_range tuner_samsung_pal_tcpm9091pd27_ranges[] = {
+- { 16 * 169 /*MHz*/, 0x8e, 0xa0, },
+- { 16 * 464 /*MHz*/, 0x8e, 0x90, },
+- { 16 * 999.99 , 0x8e, 0x30, },
+-};
+-
+-static struct tuner_params tuner_samsung_pal_tcpm9091pd27_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_samsung_pal_tcpm9091pd27_ranges,
+- .count = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_TEMIC_4106FH5 - TEMIC PAL ------------ */
+-
+-static struct tuner_params tuner_temic_4106fh5_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_temic_4009f_5_pal_ranges,
+- .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_TEMIC_4012FY5 - TEMIC PAL ------------ */
+-
+-static struct tuner_params tuner_temic_4012fy5_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_temic_pal_ranges,
+- .count = ARRAY_SIZE(tuner_temic_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_TEMIC_4136FY5 - TEMIC NTSC ------------ */
+-
+-static struct tuner_params tuner_temic_4136_fy5_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_temic_4x3x_f_5_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_temic_4x3x_f_5_ntsc_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_LG_PAL_NEW_TAPC - LGINNOTEK PAL ------------ */
+-
+-static struct tuner_range tuner_lg_new_tapc_ranges[] = {
+- { 16 * 170.00 /*MHz*/, 0x8e, 0x01, },
+- { 16 * 450.00 /*MHz*/, 0x8e, 0x02, },
+- { 16 * 999.99 , 0x8e, 0x08, },
+-};
+-
+-static struct tuner_params tuner_lg_pal_new_tapc_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_lg_new_tapc_ranges,
+- .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_FM1216ME_MK3 - Philips PAL ------------ */
+-
+-static struct tuner_range tuner_fm1216me_mk3_pal_ranges[] = {
+- { 16 * 158.00 /*MHz*/, 0x8e, 0x01, },
+- { 16 * 442.00 /*MHz*/, 0x8e, 0x02, },
+- { 16 * 999.99 , 0x8e, 0x04, },
+-};
+-
+-static struct tuner_params tuner_fm1216me_mk3_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_fm1216me_mk3_pal_ranges,
+- .count = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges),
+- .cb_first_if_lower_freq = 1,
+- .has_tda9887 = 1,
+- .port1_active = 1,
+- .port2_active = 1,
+- .port2_invert_for_secam_lc = 1,
+- .port1_fm_high_sensitivity = 1,
+- .default_top_mid = -2,
+- .default_top_secam_mid = -2,
+- .default_top_secam_high = -2,
+- },
+-};
+-
+-/* ------------ TUNER_LG_NTSC_NEW_TAPC - LGINNOTEK NTSC ------------ */
+-
+-static struct tuner_params tuner_lg_ntsc_new_tapc_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_lg_new_tapc_ranges,
+- .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
+- },
+-};
+-
+-/* 40-49 */
+-/* ------------ TUNER_HITACHI_NTSC - HITACHI NTSC ------------ */
+-
+-static struct tuner_params tuner_hitachi_ntsc_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_lg_new_tapc_ranges,
+- .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_PAL_MK - Philips PAL ------------ */
+-
+-static struct tuner_range tuner_philips_pal_mk_pal_ranges[] = {
+- { 16 * 140.25 /*MHz*/, 0x8e, 0x01, },
+- { 16 * 463.25 /*MHz*/, 0x8e, 0xc2, },
+- { 16 * 999.99 , 0x8e, 0xcf, },
+-};
+-
+-static struct tuner_params tuner_philips_pal_mk_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_philips_pal_mk_pal_ranges,
+- .count = ARRAY_SIZE(tuner_philips_pal_mk_pal_ranges),
+- },
+-};
+-
-/* ---- 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,
+- { 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 ------------ */
-
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_FM1236_MK3 - Philips NTSC ------------ */
+-
+-static struct tuner_range tuner_fm1236_mk3_ntsc_ranges[] = {
+- { 16 * 160.00 /*MHz*/, 0x8e, 0x01, },
+- { 16 * 442.00 /*MHz*/, 0x8e, 0x02, },
+- { 16 * 999.99 , 0x8e, 0x04, },
+-};
+-
+-static struct tuner_params tuner_fm1236_mk3_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_fm1236_mk3_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
+- .cb_first_if_lower_freq = 1,
+- .has_tda9887 = 1,
+- .port1_active = 1,
+- .port2_active = 1,
+- .port1_fm_high_sensitivity = 1,
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_4IN1 - Philips NTSC ------------ */
+-
+-static struct tuner_params tuner_philips_4in1_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_fm1236_mk3_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_MICROTUNE_4049FM5 - Microtune PAL ------------ */
+-
+-static struct tuner_params tuner_microtune_4049_fm5_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_temic_4009f_5_pal_ranges,
+- .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
+- .has_tda9887 = 1,
+- .port1_invert_for_secam_lc = 1,
+- .default_pll_gating_18 = 1,
+- .fm_gain_normal=1,
+- .radio_if = 1, /* 33.3 MHz */
+- },
+-};
+-
+-/* ------------ TUNER_PANASONIC_VP27 - Panasonic NTSC ------------ */
+-
+-static struct tuner_range tuner_panasonic_vp27_ntsc_ranges[] = {
+- { 16 * 160.00 /*MHz*/, 0xce, 0x01, },
+- { 16 * 454.00 /*MHz*/, 0xce, 0x02, },
+- { 16 * 999.99 , 0xce, 0x08, },
+-};
+-
+-static struct tuner_params tuner_panasonic_vp27_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_panasonic_vp27_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_panasonic_vp27_ntsc_ranges),
+- .has_tda9887 = 1,
+- .intercarrier_mode = 1,
+- .default_top_low = -3,
+- .default_top_mid = -3,
+- .default_top_high = -3,
+- },
+-};
+-
+-/* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */
+-
+-static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = {
+- { 16 * 161.25 /*MHz*/, 0x8e, 0xa0, },
+- { 16 * 463.25 /*MHz*/, 0x8e, 0x90, },
+- { 16 * 999.99 , 0x8e, 0x30, },
+-};
+-
+-static struct tuner_params tuner_tnf_8831bgff_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_tnf_8831bgff_pal_ranges,
+- .count = ARRAY_SIZE(tuner_tnf_8831bgff_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_MICROTUNE_4042FI5 - Microtune NTSC ------------ */
+-
+-static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = {
+- { 16 * 162.00 /*MHz*/, 0x8e, 0xa2, },
+- { 16 * 457.00 /*MHz*/, 0x8e, 0x94, },
+- { 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),
+- },
+-};
+-
+-/* 50-59 */
+-/* ------------ TUNER_TCL_2002N - TCL NTSC ------------ */
+-
+-static struct tuner_range tuner_tcl_2002n_ntsc_ranges[] = {
+- { 16 * 172.00 /*MHz*/, 0x8e, 0x01, },
+- { 16 * 448.00 /*MHz*/, 0x8e, 0x02, },
+- { 16 * 999.99 , 0x8e, 0x08, },
+-};
+-
+-static struct tuner_params tuner_tcl_2002n_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_tcl_2002n_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_tcl_2002n_ntsc_ranges),
+- .cb_first_if_lower_freq = 1,
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_FM1256_IH3 - Philips PAL ------------ */
+-
+-static struct tuner_params tuner_philips_fm1256_ih3_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_fm1236_mk3_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
+- .radio_if = 1, /* 33.3 MHz */
+- },
+-};
+-
+-/* ------------ TUNER_THOMSON_DTT7610 - THOMSON ATSC ------------ */
+-
+-static struct tuner_range tuner_thomson_dtt7610_ntsc_ranges[] = {
+- { 16 * 157.25 /*MHz*/, 0x8e, 0x39, },
+- { 16 * 454.00 /*MHz*/, 0x8e, 0x3a, },
+- { 16 * 999.99 , 0x8e, 0x3c, },
+-};
+-
+-static struct tuner_params tuner_thomson_dtt7610_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_thomson_dtt7610_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_FQ1286 - Philips NTSC ------------ */
+-
+-static struct tuner_range tuner_philips_fq1286_ntsc_ranges[] = {
+- { 16 * 160.00 /*MHz*/, 0x8e, 0x41, },
+- { 16 * 454.00 /*MHz*/, 0x8e, 0x42, },
+- { 16 * 999.99 , 0x8e, 0x04, },
+-};
+-
+-static struct tuner_params tuner_philips_fq1286_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_philips_fq1286_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_philips_fq1286_ntsc_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_TCL_2002MB - TCL PAL ------------ */
+-
+-static struct tuner_range tuner_tcl_2002mb_pal_ranges[] = {
+- { 16 * 170.00 /*MHz*/, 0xce, 0x01, },
+- { 16 * 450.00 /*MHz*/, 0xce, 0x02, },
+- { 16 * 999.99 , 0xce, 0x08, },
+-};
+-
+-static struct tuner_params tuner_tcl_2002mb_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_tcl_2002mb_pal_ranges,
+- .count = ARRAY_SIZE(tuner_tcl_2002mb_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_FQ1216AME_MK4 - Philips PAL ------------ */
+-
+-static struct tuner_range tuner_philips_fq12_6a___mk4_pal_ranges[] = {
+- { 16 * 160.00 /*MHz*/, 0xce, 0x01, },
+- { 16 * 442.00 /*MHz*/, 0xce, 0x02, },
+- { 16 * 999.99 , 0xce, 0x04, },
+-};
+-
+-static struct tuner_params tuner_philips_fq1216ame_mk4_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_philips_fq12_6a___mk4_pal_ranges,
+- .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_pal_ranges),
+- .has_tda9887 = 1,
+- .port1_active = 1,
+- .port2_invert_for_secam_lc = 1,
+- .default_top_mid = -2,
+- .default_top_secam_low = -2,
+- .default_top_secam_mid = -2,
+- .default_top_secam_high = -2,
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_FQ1236A_MK4 - Philips NTSC ------------ */
+-
+-static struct tuner_params tuner_philips_fq1236a_mk4_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_fm1236_mk3_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_YMEC_TVF_8531MF - Philips NTSC ------------ */
+-
+-static struct tuner_params tuner_ymec_tvf_8531mf_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_philips_ntsc_m_ranges,
+- .count = ARRAY_SIZE(tuner_philips_ntsc_m_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_YMEC_TVF_5533MF - Philips NTSC ------------ */
+-
+-static struct tuner_range tuner_ymec_tvf_5533mf_ntsc_ranges[] = {
+- { 16 * 160.00 /*MHz*/, 0x8e, 0x01, },
+- { 16 * 454.00 /*MHz*/, 0x8e, 0x02, },
+- { 16 * 999.99 , 0x8e, 0x04, },
+-};
+-
+-static struct tuner_params tuner_ymec_tvf_5533mf_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_ymec_tvf_5533mf_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_ymec_tvf_5533mf_ntsc_ranges),
+- },
+-};
+-
+-/* 60-69 */
+-/* ------------ TUNER_THOMSON_DTT761X - THOMSON ATSC ------------ */
+-/* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
+-
+-static struct tuner_range tuner_thomson_dtt761x_ntsc_ranges[] = {
+- { 16 * 145.25 /*MHz*/, 0x8e, 0x39, },
+- { 16 * 415.25 /*MHz*/, 0x8e, 0x3a, },
+- { 16 * 999.99 , 0x8e, 0x3c, },
+-};
+-
+-
+-static struct tuner_params tuner_thomson_dtt761x_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_thomson_dtt761x_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_thomson_dtt761x_ntsc_ranges),
+- .has_tda9887 = 1,
+- .fm_gain_normal = 1,
+- .radio_if = 2, /* 41.3 MHz */
+- },
+-};
+-
+-/* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */
+-
+-static struct tuner_range tuner_tena_9533_di_pal_ranges[] = {
+- { 16 * 160.25 /*MHz*/, 0x8e, 0x01, },
+- { 16 * 464.25 /*MHz*/, 0x8e, 0x02, },
+- { 16 * 999.99 , 0x8e, 0x04, },
+-};
+-
+-static struct tuner_params tuner_tena_9533_di_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_tena_9533_di_pal_ranges,
+- .count = ARRAY_SIZE(tuner_tena_9533_di_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_FMD1216ME_MK3 - Philips PAL ------------ */
+-
+-static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = {
+- { 16 * 160.00 /*MHz*/, 0x86, 0x51, },
+- { 16 * 442.00 /*MHz*/, 0x86, 0x52, },
+- { 16 * 999.99 , 0x86, 0x54, },
+-};
+-
+-
+-static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_philips_fmd1216me_mk3_pal_ranges,
+- .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges),
+- .has_tda9887 = 1,
+- .port1_active = 1,
+- .port2_active = 1,
+- .port2_fm_high_sensitivity = 1,
+- .port2_invert_for_secam_lc = 1,
+- .port1_set_for_fm_mono = 1,
+- },
+-};
+-
+-
+-/* ------ TUNER_LG_TDVS_H06XF - LG INNOTEK / INFINEON ATSC ----- */
+-
+-static struct tuner_range tuner_tua6034_ntsc_ranges[] = {
+- { 16 * 165.00 /*MHz*/, 0x8e, 0x01 },
+- { 16 * 450.00 /*MHz*/, 0x8e, 0x02 },
+- { 16 * 999.99 , 0x8e, 0x04 },
+-};
+-
+-
+-static struct tuner_params tuner_lg_tdvs_h06xf_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_tua6034_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_tua6034_ntsc_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */
+-
+-static struct tuner_range tuner_ymec_tvf66t5_b_dff_pal_ranges[] = {
+- { 16 * 160.25 /*MHz*/, 0x8e, 0x01, },
+- { 16 * 464.25 /*MHz*/, 0x8e, 0x02, },
+- { 16 * 999.99 , 0x8e, 0x08, },
+-};
+-
+-static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_ymec_tvf66t5_b_dff_pal_ranges,
+- .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_pal_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_LG_NTSC_TALN_MINI - LGINNOTEK NTSC ------------ */
+-
+-static struct tuner_range tuner_lg_taln_ntsc_ranges[] = {
+- { 16 * 137.25 /*MHz*/, 0x8e, 0x01, },
+- { 16 * 373.25 /*MHz*/, 0x8e, 0x02, },
+- { 16 * 999.99 , 0x8e, 0x08, },
+-};
+-
+-static struct tuner_range tuner_lg_taln_pal_secam_ranges[] = {
+- { 16 * 150.00 /*MHz*/, 0x8e, 0x01, },
+- { 16 * 425.00 /*MHz*/, 0x8e, 0x02, },
+- { 16 * 999.99 , 0x8e, 0x08, },
+-};
+-
+-static struct tuner_params tuner_lg_taln_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_lg_taln_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_lg_taln_ntsc_ranges),
+- },{
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_lg_taln_pal_secam_ranges,
+- .count = ARRAY_SIZE(tuner_lg_taln_pal_secam_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_TD1316 - Philips PAL ------------ */
+-
+-static struct tuner_range tuner_philips_td1316_pal_ranges[] = {
+- { 16 * 160.00 /*MHz*/, 0xc8, 0xa1, },
+- { 16 * 442.00 /*MHz*/, 0xc8, 0xa2, },
+- { 16 * 999.99 , 0xc8, 0xa4, },
+-};
+-
+-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),
+- },
+-};
+-
+-/* ------------ TUNER_PHILIPS_TUV1236D - Philips ATSC ------------ */
+-
+-static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = {
+- { 16 * 157.25 /*MHz*/, 0xce, 0x01, },
+- { 16 * 454.00 /*MHz*/, 0xce, 0x02, },
+- { 16 * 999.99 , 0xce, 0x04, },
+-};
+-
+-
+-static struct tuner_params tuner_tuv1236d_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_tuv1236d_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_tuv1236d_ntsc_ranges),
+- },
+-};
+-
+-/* ------------ TUNER_TNF_xxx5 - Texas Instruments--------- */
+-/* This is known to work with Tenna TVF58t5-MFF and TVF5835 MFF
+- * but it is expected to work also with other Tenna/Ymec
+- * models based on TI SN 761677 chip on both PAL and NTSC
+- */
+-
+-static struct tuner_range tuner_tnf_5335_d_if_pal_ranges[] = {
+- { 16 * 168.25 /*MHz*/, 0x8e, 0x01, },
+- { 16 * 471.25 /*MHz*/, 0x8e, 0x02, },
+- { 16 * 999.99 , 0x8e, 0x08, },
+-};
+-
+-static struct tuner_range tuner_tnf_5335mf_ntsc_ranges[] = {
+- { 16 * 169.25 /*MHz*/, 0x8e, 0x01, },
+- { 16 * 469.25 /*MHz*/, 0x8e, 0x02, },
+- { 16 * 999.99 , 0x8e, 0x08, },
+-};
+-
+-static struct tuner_params tuner_tnf_5335mf_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_tnf_5335mf_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_tnf_5335mf_ntsc_ranges),
+- },
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_tnf_5335_d_if_pal_ranges,
+- .count = ARRAY_SIZE(tuner_tnf_5335_d_if_pal_ranges),
+- },
+-};
+-
+-/* 70-79 */
+-/* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */
+-
+-/* '+ 4' turns on the Low Noise Amplifier */
+-static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = {
+- { 16 * 130.00 /*MHz*/, 0xce, 0x01 + 4, },
+- { 16 * 364.50 /*MHz*/, 0xce, 0x02 + 4, },
+- { 16 * 999.99 , 0xce, 0x08 + 4, },
+-};
+-
+-static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_samsung_tcpn_2121p30a_ntsc_ranges,
+- .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_ntsc_ranges),
+- },
+-};
+-
+-/* ------------ 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,
+- { 16 * 160.00 /*MHz*/, 0xfe, 0x11, },
+- { 16 * 442.00 /*MHz*/, 0xf6, 0x12, },
+- { 16 * 999.99 , 0xf6, 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_SAMSUNG_TCPG_6121P30A - Samsung PAL ------------ */
+-
+-/* '+ 4' turns on the Low Noise Amplifier */
+-static struct tuner_range tuner_samsung_tcpg_6121p30a_pal_ranges[] = {
+- { 16 * 146.25 /*MHz*/, 0xce, 0x01 + 4, },
+- { 16 * 428.50 /*MHz*/, 0xce, 0x02 + 4, },
+- { 16 * 999.99 , 0xce, 0x08 + 4, },
+-};
+-
+-static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = {
+- {
+- .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_samsung_tcpg_6121p30a_pal_ranges,
+- .count = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_pal_ranges),
+- .has_tda9887 = 1,
+- .port1_active = 1,
+- .port2_active = 1,
+- .port2_invert_for_secam_lc = 1,
+- },
+-};
+-
+-/* --------------------------------------------------------------------- */
+-
+-struct tunertype tuners[] = {
+- /* 0-9 */
+- [TUNER_TEMIC_PAL] = { /* TEMIC PAL */
+- .name = "Temic PAL (4002 FH5)",
+- .params = tuner_temic_pal_params,
+- .count = ARRAY_SIZE(tuner_temic_pal_params),
+- },
+- [TUNER_PHILIPS_PAL_I] = { /* Philips PAL_I */
+- .name = "Philips PAL_I (FI1246 and compatibles)",
+- .params = tuner_philips_pal_i_params,
+- .count = ARRAY_SIZE(tuner_philips_pal_i_params),
+- },
+- [TUNER_PHILIPS_NTSC] = { /* Philips NTSC */
+- .name = "Philips NTSC (FI1236,FM1236 and compatibles)",
+- .params = tuner_philips_ntsc_params,
+- .count = ARRAY_SIZE(tuner_philips_ntsc_params),
+- },
+- [TUNER_PHILIPS_SECAM] = { /* Philips SECAM */
+- .name = "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)",
+- .params = tuner_philips_secam_params,
+- .count = ARRAY_SIZE(tuner_philips_secam_params),
+- },
+- [TUNER_ABSENT] = { /* Tuner Absent */
+- .name = "NoTuner",
+- },
+- [TUNER_PHILIPS_PAL] = { /* Philips PAL */
+- .name = "Philips PAL_BG (FI1216 and compatibles)",
+- .params = tuner_philips_pal_params,
+- .count = ARRAY_SIZE(tuner_philips_pal_params),
+- },
+- [TUNER_TEMIC_NTSC] = { /* TEMIC NTSC */
+- .name = "Temic NTSC (4032 FY5)",
+- .params = tuner_temic_ntsc_params,
+- .count = ARRAY_SIZE(tuner_temic_ntsc_params),
+- },
+- [TUNER_TEMIC_PAL_I] = { /* TEMIC PAL_I */
+- .name = "Temic PAL_I (4062 FY5)",
+- .params = tuner_temic_pal_i_params,
+- .count = ARRAY_SIZE(tuner_temic_pal_i_params),
+- },
+- [TUNER_TEMIC_4036FY5_NTSC] = { /* TEMIC NTSC */
+- .name = "Temic NTSC (4036 FY5)",
+- .params = tuner_temic_4036fy5_ntsc_params,
+- .count = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_params),
+- },
+- [TUNER_ALPS_TSBH1_NTSC] = { /* TEMIC NTSC */
+- .name = "Alps HSBH1",
+- .params = tuner_alps_tsbh1_ntsc_params,
+- .count = ARRAY_SIZE(tuner_alps_tsbh1_ntsc_params),
+- },
+-
+- /* 10-19 */
+- [TUNER_ALPS_TSBE1_PAL] = { /* TEMIC PAL */
+- .name = "Alps TSBE1",
+- .params = tuner_alps_tsb_1_params,
+- .count = ARRAY_SIZE(tuner_alps_tsb_1_params),
+- },
+- [TUNER_ALPS_TSBB5_PAL_I] = { /* Alps PAL_I */
+- .name = "Alps TSBB5",
+- .params = tuner_alps_tsbb5_params,
+- .count = ARRAY_SIZE(tuner_alps_tsbb5_params),
+- },
+- [TUNER_ALPS_TSBE5_PAL] = { /* Alps PAL */
+- .name = "Alps TSBE5",
+- .params = tuner_alps_tsbe5_params,
+- .count = ARRAY_SIZE(tuner_alps_tsbe5_params),
+- },
+- [TUNER_ALPS_TSBC5_PAL] = { /* Alps PAL */
+- .name = "Alps TSBC5",
+- .params = tuner_alps_tsbc5_params,
+- .count = ARRAY_SIZE(tuner_alps_tsbc5_params),
+- },
+- [TUNER_TEMIC_4006FH5_PAL] = { /* TEMIC PAL */
+- .name = "Temic PAL_BG (4006FH5)",
+- .params = tuner_temic_4006fh5_params,
+- .count = ARRAY_SIZE(tuner_temic_4006fh5_params),
+- },
+- [TUNER_ALPS_TSHC6_NTSC] = { /* Alps NTSC */
+- .name = "Alps TSCH6",
+- .params = tuner_alps_tshc6_params,
+- .count = ARRAY_SIZE(tuner_alps_tshc6_params),
+- },
+- [TUNER_TEMIC_PAL_DK] = { /* TEMIC PAL */
+- .name = "Temic PAL_DK (4016 FY5)",
+- .params = tuner_temic_pal_dk_params,
+- .count = ARRAY_SIZE(tuner_temic_pal_dk_params),
+- },
+- [TUNER_PHILIPS_NTSC_M] = { /* Philips NTSC */
+- .name = "Philips NTSC_M (MK2)",
+- .params = tuner_philips_ntsc_m_params,
+- .count = ARRAY_SIZE(tuner_philips_ntsc_m_params),
+- },
+- [TUNER_TEMIC_4066FY5_PAL_I] = { /* TEMIC PAL_I */
+- .name = "Temic PAL_I (4066 FY5)",
+- .params = tuner_temic_4066fy5_pal_i_params,
+- .count = ARRAY_SIZE(tuner_temic_4066fy5_pal_i_params),
+- },
+- [TUNER_TEMIC_4006FN5_MULTI_PAL] = { /* TEMIC PAL */
+- .name = "Temic PAL* auto (4006 FN5)",
+- .params = tuner_temic_4006fn5_multi_params,
+- .count = ARRAY_SIZE(tuner_temic_4006fn5_multi_params),
+- },
+-
+- /* 20-29 */
+- [TUNER_TEMIC_4009FR5_PAL] = { /* TEMIC PAL */
+- .name = "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)",
+- .params = tuner_temic_4009f_5_params,
+- .count = ARRAY_SIZE(tuner_temic_4009f_5_params),
+- },
+- [TUNER_TEMIC_4039FR5_NTSC] = { /* TEMIC NTSC */
+- .name = "Temic NTSC (4039 FR5)",
+- .params = tuner_temic_4039fr5_params,
+- .count = ARRAY_SIZE(tuner_temic_4039fr5_params),
+- },
+- [TUNER_TEMIC_4046FM5] = { /* TEMIC PAL */
+- .name = "Temic PAL/SECAM multi (4046 FM5)",
+- .params = tuner_temic_4046fm5_params,
+- .count = ARRAY_SIZE(tuner_temic_4046fm5_params),
+- },
+- [TUNER_PHILIPS_PAL_DK] = { /* Philips PAL */
+- .name = "Philips PAL_DK (FI1256 and compatibles)",
+- .params = tuner_philips_pal_dk_params,
+- .count = ARRAY_SIZE(tuner_philips_pal_dk_params),
+- },
+- [TUNER_PHILIPS_FQ1216ME] = { /* Philips PAL */
+- .name = "Philips PAL/SECAM multi (FQ1216ME)",
+- .params = tuner_philips_fq1216me_params,
+- .count = ARRAY_SIZE(tuner_philips_fq1216me_params),
+- },
+- [TUNER_LG_PAL_I_FM] = { /* LGINNOTEK PAL_I */
+- .name = "LG PAL_I+FM (TAPC-I001D)",
+- .params = tuner_lg_pal_i_fm_params,
+- .count = ARRAY_SIZE(tuner_lg_pal_i_fm_params),
+- },
+- [TUNER_LG_PAL_I] = { /* LGINNOTEK PAL_I */
+- .name = "LG PAL_I (TAPC-I701D)",
+- .params = tuner_lg_pal_i_params,
+- .count = ARRAY_SIZE(tuner_lg_pal_i_params),
+- },
+- [TUNER_LG_NTSC_FM] = { /* LGINNOTEK NTSC */
+- .name = "LG NTSC+FM (TPI8NSR01F)",
+- .params = tuner_lg_ntsc_fm_params,
+- .count = ARRAY_SIZE(tuner_lg_ntsc_fm_params),
+- },
+- [TUNER_LG_PAL_FM] = { /* LGINNOTEK PAL */
+- .name = "LG PAL_BG+FM (TPI8PSB01D)",
+- .params = tuner_lg_pal_fm_params,
+- .count = ARRAY_SIZE(tuner_lg_pal_fm_params),
+- },
+- [TUNER_LG_PAL] = { /* LGINNOTEK PAL */
+- .name = "LG PAL_BG (TPI8PSB11D)",
+- .params = tuner_lg_pal_params,
+- .count = ARRAY_SIZE(tuner_lg_pal_params),
+- },
+-
+- /* 30-39 */
+- [TUNER_TEMIC_4009FN5_MULTI_PAL_FM] = { /* TEMIC PAL */
+- .name = "Temic PAL* auto + FM (4009 FN5)",
+- .params = tuner_temic_4009_fn5_multi_pal_fm_params,
+- .count = ARRAY_SIZE(tuner_temic_4009_fn5_multi_pal_fm_params),
+- },
+- [TUNER_SHARP_2U5JF5540_NTSC] = { /* SHARP NTSC */
+- .name = "SHARP NTSC_JP (2U5JF5540)",
+- .params = tuner_sharp_2u5jf5540_params,
+- .count = ARRAY_SIZE(tuner_sharp_2u5jf5540_params),
+- },
+- [TUNER_Samsung_PAL_TCPM9091PD27] = { /* Samsung PAL */
+- .name = "Samsung PAL TCPM9091PD27",
+- .params = tuner_samsung_pal_tcpm9091pd27_params,
+- .count = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_params),
+- },
+- [TUNER_MT2032] = { /* Microtune PAL|NTSC */
+- .name = "MT20xx universal",
+- /* see mt20xx.c for details */ },
+- [TUNER_TEMIC_4106FH5] = { /* TEMIC PAL */
+- .name = "Temic PAL_BG (4106 FH5)",
+- .params = tuner_temic_4106fh5_params,
+- .count = ARRAY_SIZE(tuner_temic_4106fh5_params),
+- },
+- [TUNER_TEMIC_4012FY5] = { /* TEMIC PAL */
+- .name = "Temic PAL_DK/SECAM_L (4012 FY5)",
+- .params = tuner_temic_4012fy5_params,
+- .count = ARRAY_SIZE(tuner_temic_4012fy5_params),
+- },
+- [TUNER_TEMIC_4136FY5] = { /* TEMIC NTSC */
+- .name = "Temic NTSC (4136 FY5)",
+- .params = tuner_temic_4136_fy5_params,
+- .count = ARRAY_SIZE(tuner_temic_4136_fy5_params),
+- },
+- [TUNER_LG_PAL_NEW_TAPC] = { /* LGINNOTEK PAL */
+- .name = "LG PAL (newer TAPC series)",
+- .params = tuner_lg_pal_new_tapc_params,
+- .count = ARRAY_SIZE(tuner_lg_pal_new_tapc_params),
+- },
+- [TUNER_PHILIPS_FM1216ME_MK3] = { /* Philips PAL */
+- .name = "Philips PAL/SECAM multi (FM1216ME MK3)",
+- .params = tuner_fm1216me_mk3_params,
+- .count = ARRAY_SIZE(tuner_fm1216me_mk3_params),
+- },
+- [TUNER_LG_NTSC_NEW_TAPC] = { /* LGINNOTEK NTSC */
+- .name = "LG NTSC (newer TAPC series)",
+- .params = tuner_lg_ntsc_new_tapc_params,
+- .count = ARRAY_SIZE(tuner_lg_ntsc_new_tapc_params),
+- },
+-
+- /* 40-49 */
+- [TUNER_HITACHI_NTSC] = { /* HITACHI NTSC */
+- .name = "HITACHI V7-J180AT",
+- .params = tuner_hitachi_ntsc_params,
+- .count = ARRAY_SIZE(tuner_hitachi_ntsc_params),
+- },
+- [TUNER_PHILIPS_PAL_MK] = { /* Philips PAL */
+- .name = "Philips PAL_MK (FI1216 MK)",
+- .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");
+- .name = "Philips FCV1236D ATSC/NTSC dual in",
+- .params = tuner_philips_fcv1236d_params,
+- .count = ARRAY_SIZE(tuner_philips_fcv1236d_params),
+- },
+- [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */
+- .name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)",
+- .params = tuner_fm1236_mk3_params,
+- .count = ARRAY_SIZE(tuner_fm1236_mk3_params),
+- },
+- [TUNER_PHILIPS_4IN1] = { /* Philips NTSC */
+- .name = "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)",
+- .params = tuner_philips_4in1_params,
+- .count = ARRAY_SIZE(tuner_philips_4in1_params),
+- },
+- [TUNER_MICROTUNE_4049FM5] = { /* Microtune PAL */
+- .name = "Microtune 4049 FM5",
+- .params = tuner_microtune_4049_fm5_params,
+- .count = ARRAY_SIZE(tuner_microtune_4049_fm5_params),
+- },
+- [TUNER_PANASONIC_VP27] = { /* Panasonic NTSC */
+- .name = "Panasonic VP27s/ENGE4324D",
+- .params = tuner_panasonic_vp27_params,
+- .count = ARRAY_SIZE(tuner_panasonic_vp27_params),
+- },
+- [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */
+- .name = "LG NTSC (TAPE series)",
+- .params = tuner_fm1236_mk3_params,
+- .count = ARRAY_SIZE(tuner_fm1236_mk3_params),
+- },
+- [TUNER_TNF_8831BGFF] = { /* Philips PAL */
+- .name = "Tenna TNF 8831 BGFF)",
+- .params = tuner_tnf_8831bgff_params,
+- .count = ARRAY_SIZE(tuner_tnf_8831bgff_params),
+- },
+- [TUNER_MICROTUNE_4042FI5] = { /* Microtune NTSC */
+- .name = "Microtune 4042 FI5 ATSC/NTSC dual in",
+- .params = tuner_microtune_4042fi5_params,
+- .count = ARRAY_SIZE(tuner_microtune_4042fi5_params),
+- },
+-
+- /* 50-59 */
+- [TUNER_TCL_2002N] = { /* TCL NTSC */
+- .name = "TCL 2002N",
+- .params = tuner_tcl_2002n_params,
+- .count = ARRAY_SIZE(tuner_tcl_2002n_params),
+- },
+- [TUNER_PHILIPS_FM1256_IH3] = { /* Philips PAL */
+- .name = "Philips PAL/SECAM_D (FM 1256 I-H3)",
+- .params = tuner_philips_fm1256_ih3_params,
+- .count = ARRAY_SIZE(tuner_philips_fm1256_ih3_params),
+- },
+- [TUNER_THOMSON_DTT7610] = { /* THOMSON ATSC */
+- .name = "Thomson DTT 7610 (ATSC/NTSC)",
+- .params = tuner_thomson_dtt7610_params,
+- .count = ARRAY_SIZE(tuner_thomson_dtt7610_params),
+- },
+- [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */
+- .name = "Philips FQ1286",
+- .params = tuner_philips_fq1286_params,
+- .count = ARRAY_SIZE(tuner_philips_fq1286_params),
+- },
+- [TUNER_PHILIPS_TDA8290] = { /* Philips PAL|NTSC */
+- .name = "Philips/NXP TDA 8290/8295 + 8275/8275A/18271",
+- /* see tda8290.c for details */ },
+- [TUNER_TCL_2002MB] = { /* TCL PAL */
+- .name = "TCL 2002MB",
+- .params = tuner_tcl_2002mb_params,
+- .count = ARRAY_SIZE(tuner_tcl_2002mb_params),
+- },
+- [TUNER_PHILIPS_FQ1216AME_MK4] = { /* Philips PAL */
+- .name = "Philips PAL/SECAM multi (FQ1216AME MK4)",
+- .params = tuner_philips_fq1216ame_mk4_params,
+- .count = ARRAY_SIZE(tuner_philips_fq1216ame_mk4_params),
+- },
+- [TUNER_PHILIPS_FQ1236A_MK4] = { /* Philips NTSC */
+- .name = "Philips FQ1236A MK4",
+- .params = tuner_philips_fq1236a_mk4_params,
+- .count = ARRAY_SIZE(tuner_philips_fq1236a_mk4_params),
+- },
+- [TUNER_YMEC_TVF_8531MF] = { /* Philips NTSC */
+- .name = "Ymec TVision TVF-8531MF/8831MF/8731MF",
+- .params = tuner_ymec_tvf_8531mf_params,
+- .count = ARRAY_SIZE(tuner_ymec_tvf_8531mf_params),
+- },
+- [TUNER_YMEC_TVF_5533MF] = { /* Philips NTSC */
+- .name = "Ymec TVision TVF-5533MF",
+- .params = tuner_ymec_tvf_5533mf_params,
+- .count = ARRAY_SIZE(tuner_ymec_tvf_5533mf_params),
+- },
+-
+- /* 60-69 */
+- [TUNER_THOMSON_DTT761X] = { /* THOMSON ATSC */
+- /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
+- .name = "Thomson DTT 761X (ATSC/NTSC)",
+- .params = tuner_thomson_dtt761x_params,
+- .count = ARRAY_SIZE(tuner_thomson_dtt761x_params),
+- },
+- [TUNER_TENA_9533_DI] = { /* Philips PAL */
+- .name = "Tena TNF9533-D/IF/TNF9533-B/DF",
+- .params = tuner_tena_9533_di_params,
+- .count = ARRAY_SIZE(tuner_tena_9533_di_params),
+- },
+- [TUNER_TEA5767] = { /* Philips RADIO */
+- .name = "Philips TEA5767HN FM Radio",
+- /* see tea5767.c for details */
+- },
+- [TUNER_PHILIPS_FMD1216ME_MK3] = { /* Philips PAL */
+- .name = "Philips FMD1216ME MK3 Hybrid Tuner",
+- .params = tuner_philips_fmd1216me_mk3_params,
+- .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params),
+- },
+- [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),
+- },
+- [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */
+- .name = "Ymec TVF66T5-B/DFF",
+- .params = tuner_ymec_tvf66t5_b_dff_params,
+- .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_params),
+- },
+- [TUNER_LG_TALN] = { /* LGINNOTEK NTSC / PAL / SECAM */
+- .name = "LG TALN series",
+- .params = tuner_lg_taln_params,
+- .count = ARRAY_SIZE(tuner_lg_taln_params),
+- },
+- [TUNER_PHILIPS_TD1316] = { /* Philips PAL */
+- .name = "Philips TD1316 Hybrid Tuner",
+- .params = tuner_philips_td1316_params,
+- .count = ARRAY_SIZE(tuner_philips_td1316_params),
+- },
+- [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */
+- .name = "Philips TUV1236D ATSC/NTSC dual in",
+- .params = tuner_tuv1236d_params,
+- .count = ARRAY_SIZE(tuner_tuv1236d_params),
+- },
+- [TUNER_TNF_5335MF] = { /* Tenna PAL/NTSC */
+- .name = "Tena TNF 5335 and similar models",
+- .params = tuner_tnf_5335mf_params,
+- .count = ARRAY_SIZE(tuner_tnf_5335mf_params),
+- },
+-
+- /* 70-79 */
+- [TUNER_SAMSUNG_TCPN_2121P30A] = { /* Samsung NTSC */
+- .name = "Samsung TCPN 2121P30A",
+- .params = tuner_samsung_tcpn_2121p30a_params,
+- .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_params),
+- },
+- [TUNER_XC2028] = { /* Xceive 2028 */
+- .name = "Xceive xc2028/xc3028 tuner",
+- /* see tuner-xc2028.c for details */
+- },
+- [TUNER_THOMSON_FE6600] = { /* Thomson PAL / DVB-T */
+- .name = "Thomson FE6600",
+- .params = tuner_thomson_fe6600_params,
+- .count = ARRAY_SIZE(tuner_thomson_fe6600_params),
+- },
+- [TUNER_SAMSUNG_TCPG_6121P30A] = { /* Samsung PAL */
+- .name = "Samsung TCPG 6121P30A",
+- .params = tuner_samsung_tcpg_6121p30a_params,
+- .count = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_params),
+- },
+- [TUNER_TDA9887] = { /* Philips TDA 9887 IF PLL Demodulator.
+- This chip is part of some modern tuners */
+- .name = "Philips TDA988[5,6,7] IF PLL Demodulator",
+- /* see tda9887.c for details */
+- },
+- [TUNER_TEA5761] = { /* Philips RADIO */
+- .name = "Philips TEA5761 FM Radio",
+- /* see tea5767.c for details */
+- },
+- [TUNER_XC5000] = { /* Xceive 5000 */
+- .name = "Xceive 5000 tuner",
+- /* see xc5000.c for details */
+- },
+-};
+-
+-unsigned const int tuner_count = ARRAY_SIZE(tuners);
diff --git a/drivers/media/video/tuner-xc2028-types.h b/drivers/media/video/tuner-xc2028-types.h
-index d0057fb..74dc46a 100644
+deleted file mode 100644
+index d0057fb..0000000
--- a/drivers/media/video/tuner-xc2028-types.h
-+++ b/drivers/media/video/tuner-xc2028-types.h
-@@ -1,6 +1,9 @@
- /* tuner-xc2028_types
- *
++++ /dev/null
+@@ -1,128 +0,0 @@
+-/* tuner-xc2028_types
+- *
- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab at infradead.org)
-+ * This file includes internal tipes to be used inside tuner-xc2028.
-+ * Shouldn't be included outside tuner-xc2028
-+ *
-+ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab at infradead.org)
- * This code is placed under the terms of the GNU General Public License v2
- */
-
-@@ -54,11 +57,13 @@
- /* LCD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
- and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
- There are variants both with and without NOGD
-+ Those firmwares produce better result with LCD displays
- */
- #define LCD (1<<12)
-
- /* NOGD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
- and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
-+ The NOGD firmwares don't have group delay compensation filter
- */
- #define NOGD (1<<13)
-
-@@ -85,11 +90,19 @@
- /* This flag identifies that the scode table has a new format */
- #define HAS_IF (1 << 30)
-
+- * This code is placed under the terms of the GNU General Public License v2
+- */
+-
+-/* xc3028 firmware types */
+-
+-/* BASE firmware should be loaded before any other firmware */
+-#define BASE (1<<0)
+-#define BASE_TYPES (BASE|F8MHZ|MTS|FM|INPUT1|INPUT2|INIT1)
+-
+-/* F8MHZ marks BASE firmwares for 8 MHz Bandwidth */
+-#define F8MHZ (1<<1)
+-
+-/* Multichannel Television Sound (MTS)
+- Those firmwares are capable of using xc2038 DSP to decode audio and
+- produce a baseband audio output on some pins of the chip.
+- There are MTS firmwares for the most used video standards. It should be
+- required to use MTS firmwares, depending on the way audio is routed into
+- the bridge chip
+- */
+-#define MTS (1<<2)
+-
+-/* FIXME: I have no idea what's the difference between
+- D2620 and D2633 firmwares
+- */
+-#define D2620 (1<<3)
+-#define D2633 (1<<4)
+-
+-/* DTV firmwares for 6, 7 and 8 MHz
+- DTV6 - 6MHz - ATSC/DVB-C/DVB-T/ISDB-T/DOCSIS
+- DTV8 - 8MHz - DVB-C/DVB-T
+- */
+-#define DTV6 (1 << 5)
+-#define QAM (1 << 6)
+-#define DTV7 (1<<7)
+-#define DTV78 (1<<8)
+-#define DTV8 (1<<9)
+-
+-#define DTV_TYPES (D2620|D2633|DTV6|QAM|DTV7|DTV78|DTV8|ATSC)
+-
+-/* There's a FM | BASE firmware + FM specific firmware (std=0) */
+-#define FM (1<<10)
+-
+-#define STD_SPECIFIC_TYPES (MTS|FM|LCD|NOGD)
+-
+-/* Applies only for FM firmware
+- Makes it use RF input 1 (pin #2) instead of input 2 (pin #4)
+- */
+-#define INPUT1 (1<<11)
+-
+-
+-/* 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
+- */
+-#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)
+- */
+-#define NOGD (1<<13)
+-
+-/* Old firmwares were broken into init0 and init1 */
+-#define INIT1 (1<<14)
+-
+-/* SCODE firmware selects particular behaviours */
+-#define MONO (1 << 15)
+-#define ATSC (1 << 16)
+-#define IF (1 << 17)
+-#define LG60 (1 << 18)
+-#define ATI638 (1 << 19)
+-#define OREN538 (1 << 20)
+-#define OREN36 (1 << 21)
+-#define TOYOTA388 (1 << 22)
+-#define TOYOTA794 (1 << 23)
+-#define DIBCOM52 (1 << 24)
+-#define ZARLINK456 (1 << 25)
+-#define CHINA (1 << 26)
+-#define F6MHZ (1 << 27)
+-#define INPUT2 (1 << 28)
+-#define SCODE (1 << 29)
+-
+-/* 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)
-
+-
+-#define V4L2_STD_SECAM_K3 (0x04000000)
+-
+-/* Audio types */
+-
+-#define V4L2_STD_A2_A (1LL<<32)
+-#define V4L2_STD_A2_B (1LL<<33)
+-#define V4L2_STD_NICAM_A (1LL<<34)
+-#define V4L2_STD_NICAM_B (1LL<<35)
+-#define V4L2_STD_AM (1LL<<36)
+-#define V4L2_STD_BTSC (1LL<<37)
+-#define V4L2_STD_EIAJ (1LL<<38)
+-
+-#define V4L2_STD_A2 (V4L2_STD_A2_A | V4L2_STD_A2_B)
+-#define V4L2_STD_NICAM (V4L2_STD_NICAM_A | V4L2_STD_NICAM_B)
+-
+-/* To preserve backward compatibilty,
+- (std & V4L2_STD_AUDIO) = 0 means that ALL audio stds are supported
+- */
+-
+-#define V4L2_STD_AUDIO (V4L2_STD_A2 | \
+- V4L2_STD_NICAM | \
+- V4L2_STD_AM | \
+- V4L2_STD_BTSC | \
+- V4L2_STD_EIAJ)
+-
+-/* Used standards with audio restrictions */
+-
+-#define V4L2_STD_PAL_BG_A2_A (V4L2_STD_PAL_BG | V4L2_STD_A2_A)
+-#define V4L2_STD_PAL_BG_A2_B (V4L2_STD_PAL_BG | V4L2_STD_A2_B)
+-#define V4L2_STD_PAL_BG_NICAM_A (V4L2_STD_PAL_BG | V4L2_STD_NICAM_A)
+-#define V4L2_STD_PAL_BG_NICAM_B (V4L2_STD_PAL_BG | V4L2_STD_NICAM_B)
+-#define V4L2_STD_PAL_DK_A2 (V4L2_STD_PAL_DK | V4L2_STD_A2)
+-#define V4L2_STD_PAL_DK_NICAM (V4L2_STD_PAL_DK | V4L2_STD_NICAM)
+-#define V4L2_STD_SECAM_L_NICAM (V4L2_STD_SECAM_L | V4L2_STD_NICAM)
+-#define V4L2_STD_SECAM_L_AM (V4L2_STD_SECAM_L | V4L2_STD_AM)
diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
-index 50cf876..9e9003c 100644
+deleted file mode 100644
+index 50cf876..0000000
--- a/drivers/media/video/tuner-xc2028.c
-+++ b/drivers/media/video/tuner-xc2028.c
-@@ -1,6 +1,6 @@
- /* tuner-xc2028
- *
++++ /dev/null
+@@ -1,1216 +0,0 @@
+-/* tuner-xc2028
+- *
- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab at infradead.org)
-+ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab at infradead.org)
- *
- * Copyright (c) 2007 Michel Ludwig (michel.ludwig at gmail.com)
- * - frontend interface
-@@ -23,8 +23,6 @@
- #include "dvb_frontend.h"
-
-
+- *
+- * Copyright (c) 2007 Michel Ludwig (michel.ludwig at gmail.com)
+- * - frontend interface
+- *
+- * This code is placed under the terms of the GNU General Public License v2
+- */
+-
+-#include <linux/i2c.h>
+-#include <asm/div64.h>
+-#include <linux/firmware.h>
+-#include <linux/videodev2.h>
+-#include <linux/delay.h>
+-#include <media/tuner.h>
+-#include <linux/mutex.h>
+-#include "tuner-i2c.h"
+-#include "tuner-xc2028.h"
+-#include "tuner-xc2028-types.h"
+-
+-#include <linux/dvb/frontend.h>
+-#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 int debug;
+-module_param(debug, int, 0644);
+-MODULE_PARM_DESC(debug, "enable verbose debug messages");
+-
+-static char audio_std[8];
+-module_param_string(audio_std, audio_std, sizeof(audio_std), 0);
+-MODULE_PARM_DESC(audio_std,
+- "Audio standard. XC3028 audio decoder explicitly "
+- "needs to know what audio\n"
+- "standard is needed for some video standards with audio A2 or NICAM.\n"
+- "The valid values are:\n"
+- "A2\n"
+- "A2/A\n"
+- "A2/B\n"
+- "NICAM\n"
+- "NICAM/A\n"
+- "NICAM/B\n");
+-
+-static LIST_HEAD(xc2028_list);
+-static DEFINE_MUTEX(xc2028_list_mutex);
+-
+-/* struct for storing firmware table */
+-struct firmware_description {
+- unsigned int type;
+- v4l2_std_id id;
+- __u16 int_freq;
+- unsigned char *ptr;
+- unsigned int size;
+-};
+-
+-struct firmware_properties {
+- unsigned int type;
+- v4l2_std_id id;
+- v4l2_std_id std_req;
+- __u16 int_freq;
+- unsigned int scode_table;
+- int scode_nr;
+-};
+-
+-struct xc2028_data {
+- struct list_head xc2028_list;
+- struct tuner_i2c_props i2c_props;
+- int (*tuner_callback) (void *dev,
+- int command, int arg);
+- void *video_dev;
+- int count;
+- __u32 frequency;
+-
+- struct firmware_description *firm;
+- int firm_size;
+- __u16 firm_version;
+-
+- __u16 hwmodel;
+- __u16 hwvers;
+-
+- struct xc2028_ctrl ctrl;
+-
+- struct firmware_properties cur_fw;
+-
+- struct mutex lock;
+-};
+-
+-#define i2c_send(priv, buf, size) ({ \
+- int _rc; \
+- _rc = tuner_i2c_xfer_send(&priv->i2c_props, buf, size); \
+- if (size != _rc) \
+- tuner_info("i2c output error: rc = %d (should be %d)\n",\
+- _rc, (int)size); \
+- _rc; \
+-})
+-
+-#define i2c_rcv(priv, buf, size) ({ \
+- int _rc; \
+- _rc = tuner_i2c_xfer_recv(&priv->i2c_props, buf, size); \
+- if (size != _rc) \
+- tuner_err("i2c input error: rc = %d (should be %d)\n", \
+- _rc, (int)size); \
+- _rc; \
+-})
+-
+-#define i2c_send_recv(priv, obuf, osize, ibuf, isize) ({ \
+- int _rc; \
+- _rc = tuner_i2c_xfer_send_recv(&priv->i2c_props, obuf, osize, \
+- ibuf, isize); \
+- if (isize != _rc) \
+- tuner_err("i2c input error: rc = %d (should be %d)\n", \
+- _rc, (int)isize); \
+- _rc; \
+-})
+-
+-#define send_seq(priv, data...) ({ \
+- static u8 _val[] = data; \
+- int _rc; \
+- if (sizeof(_val) != \
+- (_rc = tuner_i2c_xfer_send(&priv->i2c_props, \
+- _val, sizeof(_val)))) { \
+- tuner_err("Error on line %d: %d\n", __LINE__, _rc); \
+- } else \
+- msleep(10); \
+- _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];
-
+-{
+- 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)
+-
+- buf[0] = reg >> 8;
+- buf[1] = (unsigned char) reg;
+-
+- if (i2c_send_recv(priv, buf, 2, ibuf, 2) != 2)
+- return -EIO;
+-
+- *val = (ibuf[1]) | (ibuf[0] << 8);
+- return 0;
+-}
+-
+-#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__);
-
+-{
+- if (type & BASE)
+- printk("BASE ");
+- if (type & INIT1)
+- printk("INIT1 ");
+- if (type & F8MHZ)
+- printk("F8MHZ ");
+- if (type & MTS)
+- printk("MTS ");
+- if (type & D2620)
+- printk("D2620 ");
+- if (type & D2633)
+- printk("D2633 ");
+- if (type & DTV6)
+- printk("DTV6 ");
+- if (type & QAM)
+- printk("QAM ");
+- if (type & DTV7)
+- printk("DTV7 ");
+- if (type & DTV78)
+- printk("DTV78 ");
+- if (type & DTV8)
+- printk("DTV8 ");
+- if (type & FM)
+- printk("FM ");
+- if (type & INPUT1)
+- printk("INPUT1 ");
+- if (type & LCD)
+- printk("LCD ");
+- if (type & NOGD)
+- printk("NOGD ");
+- if (type & MONO)
+- printk("MONO ");
+- if (type & ATSC)
+- printk("ATSC ");
+- if (type & IF)
+- printk("IF ");
+- if (type & LG60)
+- printk("LG60 ");
+- if (type & ATI638)
+- printk("ATI638 ");
+- if (type & OREN538)
+- printk("OREN538 ");
+- if (type & OREN36)
+- printk("OREN36 ");
+- if (type & TOYOTA388)
+- printk("TOYOTA388 ");
+- if (type & TOYOTA794)
+- printk("TOYOTA794 ");
+- if (type & DIBCOM52)
+- printk("DIBCOM52 ");
+- if (type & ZARLINK456)
+- printk("ZARLINK456 ");
+- if (type & CHINA)
+- printk("CHINA ");
+- if (type & F6MHZ)
+- printk("F6MHZ ");
+- if (type & INPUT2)
+- printk("INPUT2 ");
+- if (type & SCODE)
+- printk("SCODE ");
+- if (type & HAS_IF)
+- printk("HAS_IF_%d ", int_freq);
+-}
+-
+-static v4l2_std_id parse_audio_std_option(void)
+-{
+- if (strcasecmp(audio_std, "A2") == 0)
+- return V4L2_STD_A2;
+- if (strcasecmp(audio_std, "A2/A") == 0)
+- return V4L2_STD_A2_A;
+- if (strcasecmp(audio_std, "A2/B") == 0)
+- return V4L2_STD_A2_B;
+- if (strcasecmp(audio_std, "NICAM") == 0)
+- return V4L2_STD_NICAM;
+- if (strcasecmp(audio_std, "NICAM/A") == 0)
+- return V4L2_STD_NICAM_A;
+- if (strcasecmp(audio_std, "NICAM/B") == 0)
+- return V4L2_STD_NICAM_B;
+-
+- return 0;
+-}
+-
+-static void free_firmware(struct xc2028_data *priv)
+-{
+- int i;
+-
+- if (!priv->firm)
+- return;
+-
+- for (i = 0; i < priv->firm_size; i++)
+- kfree(priv->firm[i].ptr);
+-
+- kfree(priv->firm);
+-
+- priv->firm = NULL;
+- priv->firm_size = 0;
+-
+- memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
+-}
+-
+-static int load_all_firmwares(struct dvb_frontend *fe)
+-{
+- struct xc2028_data *priv = fe->tuner_priv;
+- const struct firmware *fw = NULL;
+- unsigned char *p, *endp;
+- int rc = 0;
+- int n, n_array;
+- char name[33];
+-
- 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",
+- 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",
+- 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",
+-
+- return rc;
+- }
+- p = fw->data;
+- endp = p + fw->size;
+-
+- 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",
+- goto corrupt;
+- }
+-
+- memcpy(name, p, sizeof(name) - 1);
+- name[sizeof(name) - 1] = 0;
+- p += sizeof(name) - 1;
+-
+- priv->firm_version = le16_to_cpu(*(__u16 *) p);
+- p += 2;
+-
+- n_array = le16_to_cpu(*(__u16 *) p);
+- 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;
+- priv->firm_version >> 8, priv->firm_version & 0xff);
+-
+- priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
+- if (priv->firm == NULL) {
+- tuner_err("Not enough memory to load firmware file.\n");
+- rc = -ENOMEM;
+- goto err;
+- }
+- priv->firm_size = n_array;
+-
+- n = -1;
+- while (p < endp) {
+- __u32 type, size;
+- v4l2_std_id id;
+- __u16 int_freq = 0;
+-
+- n++;
+- if (n >= n_array) {
+- tuner_err("More firmware images in file than "
+- "were expected!\n");
+- goto corrupt;
+- }
+-
+- /* Checks if there's enough bytes to read */
+- if (p + sizeof(type) + sizeof(id) + sizeof(size) > endp) {
+- tuner_err("Firmware header is incomplete!\n");
+- goto corrupt;
+- }
+-
+- type = le32_to_cpu(*(__u32 *) p);
+- p += sizeof(type);
+-
+- id = le64_to_cpu(*(v4l2_std_id *) p);
+- p += sizeof(id);
+-
+- if (type & HAS_IF) {
+- int_freq = le16_to_cpu(*(__u16 *) p);
+- p += sizeof(int_freq);
+- }
+-
+- size = le32_to_cpu(*(__u32 *) p);
+- p += sizeof(size);
+-
+- if ((!size) || (size + p > endp)) {
+- tuner_err("Firmware type ");
+- dump_firm_type(type);
+- printk("(%x), id %llx is corrupted "
+- "(size=%d, expected %d)\n",
+- type, (unsigned long long)id,
+- (unsigned)(endp - p), size);
+- goto corrupt;
+- }
+-
+- priv->firm[n].ptr = kzalloc(size, GFP_KERNEL);
+- if (priv->firm[n].ptr == NULL) {
+- tuner_err("Not enough memory to load firmware file.\n");
+- rc = -ENOMEM;
+- goto err;
+- }
+- tuner_dbg("Reading firmware type ");
+- if (debug) {
+- dump_firm_type_and_int_freq(type, int_freq);
+- printk("(%x), id %llx, size=%d.\n",
+- type, (unsigned long long)id, size);
+- }
+-
+- memcpy(priv->firm[n].ptr, p, size);
+- priv->firm[n].type = type;
+- priv->firm[n].id = id;
+- priv->firm[n].size = size;
+- priv->firm[n].int_freq = int_freq;
+-
+- p += size;
+- }
+-
+- if (n + 1 != priv->firm_size) {
+- tuner_err("Firmware file is incomplete!\n");
+- goto corrupt;
+- }
+-
+- goto done;
+-
+-corrupt:
+- rc = -EINVAL;
+- tuner_err("Error: firmware file is corrupted!\n");
+-
+-err:
+- tuner_info("Releasing partially loaded firmware file.\n");
+- free_firmware(priv);
+-
+-done:
+- release_firmware(fw);
+- if (rc == 0)
+- tuner_dbg("Firmware files loaded.\n");
+-
+- return rc;
+-}
+-
+-static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
+- v4l2_std_id *id)
+-{
+- 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)
+- if (debug) {
+- dump_firm_type(type);
+- printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
+- }
+-
+- if (!priv->firm) {
+- tuner_err("Error! firmware not loaded\n");
+- return -EINVAL;
+- }
+-
+- if (((type & ~SCODE) == 0) && (*id == 0))
+- *id = V4L2_STD_PAL;
+-
+- if (type & BASE)
- type &= BASE_TYPES;
-+ type_mask = BASE_TYPES;
- else if (type & SCODE) {
- type &= SCODE_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)
+- } else if (type & DTV_TYPES)
- type &= DTV_TYPES;
-+ type_mask = DTV_TYPES;
- else if (type & STD_SPECIFIC_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++) {
+-
+- /* 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;
-
+- (*id == priv->firm[i].id))
+- goto found;
+- }
+-
+- /* Seek for generic video standard match */
+- for (i = 0; i < priv->firm_size; i++) {
+- 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];
-
+- continue;
+-
+- match_mask = *id & priv->firm[i].id;
+- if (!match_mask)
+- continue;
+-
+- if ((*id & match_mask) == *id)
+- goto found; /* Supports all the requested standards */
+-
+- nr_matches = hweight64(match_mask);
+- if (nr_matches > best_nr_matches) {
+- best_nr_matches = nr_matches;
+- best_i = i;
+- }
+- }
+-
+- if (best_nr_matches > 0) {
+- tuner_dbg("Selecting best matching firmware (%d bits) for "
+- "type=", best_nr_matches);
+- dump_firm_type(type);
+- printk("(%x), id %016llx:\n", type, (unsigned long long)*id);
+- i = best_i;
+- goto found;
+- }
+-
+- /*FIXME: Would make sense to seek for type "hint" match ? */
+-
+- i = -ENOENT;
+- goto ret;
+-
+-found:
+- *id = priv->firm[i].id;
+-
+-ret:
+- tuner_dbg("%s firmware for type=", (i < 0) ? "Can't find" : "Found");
+- if (debug) {
+- dump_firm_type(type);
+- printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
+- }
+- return i;
+-}
+-
+-static int load_firmware(struct dvb_frontend *fe, unsigned int type,
+- v4l2_std_id *id)
+-{
+- struct xc2028_data *priv = fe->tuner_priv;
+- 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;
-
+-
+- pos = seek_firmware(fe, type, id);
+- if (pos < 0)
+- return pos;
+-
+- tuner_info("Loading firmware for type=");
+- dump_firm_type(priv->firm[pos].type);
+- printk("(%x), id %016llx.\n", priv->firm[pos].type,
+- (unsigned long long)*id);
+-
+- p = priv->firm[pos].ptr;
+- endp = p + priv->firm[pos].size;
+-
+- while (p < endp) {
+- __u16 size;
+-
+- /* Checks if there's enough bytes to read */
+- if (p + sizeof(size) > endp) {
+- tuner_err("Firmware chunk size is wrong\n");
+- return -EINVAL;
+- }
+-
+- size = le16_to_cpu(*(__u16 *) p);
+- p += sizeof(size);
+-
+- if (size == 0xffff)
+- return 0;
+-
+- if (!size) {
+- /* Special callback command received */
+- rc = priv->tuner_callback(priv->video_dev,
+- XC2028_TUNER_RESET, 0);
+- if (rc < 0) {
+- tuner_err("Error at RESET code %d\n",
+- (*p) & 0x7f);
+- return -EINVAL;
+- }
+- continue;
+- }
+- if (size >= 0xff00) {
+- switch (size) {
+- case 0xff00:
+- rc = priv->tuner_callback(priv->video_dev,
+- XC2028_RESET_CLK, 0);
+- if (rc < 0) {
+- tuner_err("Error at RESET code %d\n",
+- (*p) & 0x7f);
+- return -EINVAL;
+- }
+- break;
+- default:
+- tuner_info("Invalid RESET code %d\n",
+- size & 0x7f);
+- return -EINVAL;
+-
+- }
+- continue;
+- }
+-
+- /* Checks for a sleep command */
+- if (size & 0x8000) {
+- msleep(size & 0x7fff);
+- continue;
+- }
+-
+- if ((size + p > endp)) {
+- tuner_err("missing bytes: need %d, have %d\n",
+- size, (int)(endp - p));
+- return -EINVAL;
+- }
+-
+- buf[0] = *p;
+- p++;
+- size--;
+-
+- /* Sends message chunks */
+- while (size > 0) {
+- int len = (size < priv->ctrl.max_len - 1) ?
+- size : priv->ctrl.max_len - 1;
+-
+- memcpy(buf + 1, p, len);
+-
+- rc = i2c_send(priv, buf, len + 1);
+- if (rc < 0) {
+- tuner_err("%d returned from send\n", rc);
+- return -EINVAL;
+- }
+-
+- p += len;
+- size -= len;
+- }
+- }
+- return 0;
+-}
+-
+-static int load_scode(struct dvb_frontend *fe, unsigned int type,
+- v4l2_std_id *id, __u16 int_freq, int scode)
+-{
+- struct xc2028_data *priv = fe->tuner_priv;
+- 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;
-
+-
+- if (!int_freq) {
+- pos = seek_firmware(fe, type, id);
+- if (pos < 0)
+- return pos;
+- } else {
+- for (pos = 0; pos < priv->firm_size; pos++) {
+- if ((priv->firm[pos].int_freq == int_freq) &&
+- (priv->firm[pos].type & HAS_IF))
+- break;
+- }
+- if (pos == priv->firm_size)
+- return -ENOENT;
+- }
+-
+- p = priv->firm[pos].ptr;
+-
+- if (priv->firm[pos].type & HAS_IF) {
+- if (priv->firm[pos].size != 12 * 16 || scode >= 16)
+- return -EINVAL;
+- p += 12 * scode;
+- } else {
+- /* 16 SCODE entries per file; each SCODE entry is 12 bytes and
+- * has a 2-byte size header in the firmware format. */
+- if (priv->firm[pos].size != 14 * 16 || scode >= 16 ||
+- le16_to_cpu(*(__u16 *)(p + 14 * scode)) != 12)
+- return -EINVAL;
+- p += 14 * scode + 2;
+- }
+-
+- tuner_info("Loading SCODE for type=");
+- dump_firm_type_and_int_freq(priv->firm[pos].type,
+- priv->firm[pos].int_freq);
+- printk("(%x), id %016llx.\n", priv->firm[pos].type,
+- (unsigned long long)*id);
+-
+- if (priv->firm_version < 0x0202)
+- rc = send_seq(priv, {0x20, 0x00, 0x00, 0x00});
+- else
+- rc = send_seq(priv, {0xa0, 0x00, 0x00, 0x00});
+- if (rc < 0)
+- return -EIO;
+-
+- rc = i2c_send(priv, p, 12);
+- if (rc < 0)
+- return -EIO;
+-
+- rc = send_seq(priv, {0x00, 0x8c});
+- if (rc < 0)
+- return -EIO;
+-
+- return 0;
+-}
+-
+-static int check_firmware(struct dvb_frontend *fe, unsigned int type,
+- v4l2_std_id std, __u16 int_freq)
+-{
+- struct xc2028_data *priv = fe->tuner_priv;
+- struct firmware_properties new_fw;
+- int rc = 0, is_retry = 0;
+- 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;
- }
-
+-
+- if (!priv->firm) {
+- if (!priv->ctrl.fname) {
+- tuner_info("xc2028/3028 firmware name not set!\n");
+- return -EINVAL;
+- }
+-
+- rc = load_all_firmwares(fe);
+- if (rc < 0)
+- return rc;
+- }
+-
+- if (priv->ctrl.mts && !(type & FM))
+- type |= MTS;
+-
+-retry:
+- new_fw.type = type;
+- new_fw.id = std;
+- new_fw.std_req = std;
+- new_fw.scode_table = SCODE | priv->ctrl.scode_table;
+- new_fw.scode_nr = 0;
+- new_fw.int_freq = int_freq;
+-
+- tuner_dbg("checking firmware, user requested type=");
+- if (debug) {
+- dump_firm_type(new_fw.type);
+- printk("(%x), id %016llx, ", new_fw.type,
+- (unsigned long long)new_fw.std_req);
+- if (!int_freq) {
+- printk("scode_tbl ");
+- dump_firm_type(priv->ctrl.scode_table);
+- printk("(%x), ", priv->ctrl.scode_table);
+- } else
+- printk("int_freq %d, ", new_fw.int_freq);
+- printk("scode_nr %d\n", new_fw.scode_nr);
+- }
+-
+- /* No need to reload base firmware if it matches */
+- if (((BASE | new_fw.type) & BASE_TYPES) ==
+- (priv->cur_fw.type & BASE_TYPES)) {
+- tuner_dbg("BASE firmware not changed.\n");
+- goto skip_base;
+- }
+-
+- /* Updating BASE - forget about all currently loaded firmware */
+- memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
+-
+- /* Reset is needed before loading firmware */
+- rc = priv->tuner_callback(priv->video_dev,
+- XC2028_TUNER_RESET, 0);
+- if (rc < 0)
+- goto fail;
+-
+- /* BASE firmwares are all std0 */
+- std0 = 0;
+- rc = load_firmware(fe, BASE | new_fw.type, &std0);
+- if (rc < 0) {
+- tuner_err("Error %d while loading base firmware\n",
+- rc);
+- goto fail;
+- }
+-
+- /* Load INIT1, if needed */
+- tuner_dbg("Load init1 firmware, if exists\n");
+-
+- rc = load_firmware(fe, BASE | INIT1 | new_fw.type, &std0);
+- if (rc == -ENOENT)
+- rc = load_firmware(fe, (BASE | INIT1 | new_fw.type) & ~F8MHZ,
+- &std0);
+- if (rc < 0 && rc != -ENOENT) {
+- tuner_err("Error %d while loading init1 firmware\n",
+- rc);
+- goto fail;
+- }
+-
+-skip_base:
+- /*
+- * No need to reload standard specific firmware if base firmware
+- * was not reloaded and requested video standards have not changed.
+- */
+- if (priv->cur_fw.type == (BASE | new_fw.type) &&
+- priv->cur_fw.std_req == std) {
+- tuner_dbg("Std-specific firmware already loaded.\n");
+- goto skip_std_specific;
+- }
+-
+- /* Reloading std-specific firmware forces a SCODE update */
+- priv->cur_fw.scode_table = 0;
+-
+- rc = load_firmware(fe, new_fw.type, &new_fw.id);
+- if (rc == -ENOENT)
+- rc = load_firmware(fe, new_fw.type & ~F8MHZ, &new_fw.id);
+-
+- if (rc < 0)
+- goto fail;
+-
+-skip_std_specific:
+- if (priv->cur_fw.scode_table == new_fw.scode_table &&
+- priv->cur_fw.scode_nr == new_fw.scode_nr) {
+- tuner_dbg("SCODE firmware already loaded.\n");
+- goto check_device;
+- }
+-
+- if (new_fw.type & FM)
+- goto check_device;
+-
+- /* Load SCODE firmware, if exists */
+- tuner_dbg("Trying to load scode %d\n", new_fw.scode_nr);
+-
+- rc = load_scode(fe, new_fw.type | new_fw.scode_table, &new_fw.id,
+- new_fw.int_freq, new_fw.scode_nr);
+-
+-check_device:
+- if (xc2028_get_reg(priv, 0x0004, &version) < 0 ||
+- xc2028_get_reg(priv, 0x0008, &hwmodel) < 0) {
+- tuner_err("Unable to read tuner registers.\n");
+- 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;
-
+-
+- /* Check firmware version against what we downloaded. */
+- if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) {
+- tuner_err("Incorrect readback of firmware version.\n");
+- goto fail;
+- }
+-
+- /* Check that the tuner hardware model remains consistent over time. */
+- if (priv->hwmodel == 0 && (hwmodel == 2028 || hwmodel == 3028)) {
+- priv->hwmodel = hwmodel;
+- priv->hwvers = version & 0xff00;
+- } else if (priv->hwmodel == 0 || priv->hwmodel != hwmodel ||
+- priv->hwvers != (version & 0xff00)) {
+- tuner_err("Read invalid device hardware information - tuner "
+- "hung?\n");
+- goto fail;
+- }
+-
+- memcpy(&priv->cur_fw, &new_fw, sizeof(priv->cur_fw));
+-
+- /*
+- * By setting BASE in cur_fw.type only after successfully loading all
+- * firmwares, we can:
+- * 1. Identify that BASE firmware with type=0 has been loaded;
+- * 2. Tell whether BASE firmware was just changed the next time through.
+- */
+- priv->cur_fw.type |= BASE;
+-
+- return 0;
+-
+-fail:
+- memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
+- if (!is_retry) {
+- msleep(50);
+- is_retry = 1;
+- tuner_dbg("Retrying firmware load\n");
+- goto retry;
+- }
+-
+- if (rc == -ENOENT)
+- rc = -EINVAL;
+- return rc;
+-}
+-
+-static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
+-{
+- struct xc2028_data *priv = fe->tuner_priv;
+- 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);
+-
+- 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;
-
+- 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)
+-
+- /* 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;
-
+-
+-ret:
+- mutex_unlock(&priv->lock);
+-
+- *strength = signal;
+-
+- return rc;
+-}
+-
+-#define DIV 15625
+-
+-static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
+- enum tuner_mode new_mode,
+- unsigned int type,
+- v4l2_std_id std,
+- u16 int_freq)
+-{
+- struct xc2028_data *priv = fe->tuner_priv;
+- int rc = -EINVAL;
+- 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;
-
+-
+- mutex_lock(&priv->lock);
+-
+- tuner_dbg("should set frequency %d kHz\n", freq / 1000);
+-
+- if (check_firmware(fe, type, std, int_freq) < 0)
+- goto ret;
+-
+- /* On some cases xc2028 can disable video output, if
+- * very weak signals are received. By sending a soft
+- * reset, this is re-enabled. So, it is better to always
+- * send a soft reset before changing channels, to be sure
+- * that xc2028 will be in a safe state.
+- * Maybe this might also be needed for DTV.
+- */
+- if (new_mode == T_ANALOG_TV) {
+- rc = send_seq(priv, {0x00, 0x00});
+- } else if (priv->cur_fw.type & ATSC) {
+- offset = 1750000;
+- } else {
+- offset = 2750000;
+- /*
+- * We must adjust the offset by 500kHz in two cases in order
+- * to correctly center the IF output:
+- * 1) When the ZARLINK456 or DIBCOM52 tables were explicitly
+- * selected and a 7MHz channel is tuned;
+- * 2) When tuning a VHF channel with DTV78 firmware.
+- */
+- if (((priv->cur_fw.type & DTV7) &&
+- (priv->cur_fw.scode_table & (ZARLINK456 | DIBCOM52))) ||
+- ((priv->cur_fw.type & DTV78) && freq < 470000000))
+- offset -= 500000;
+- }
+-
+- div = (freq - offset + DIV / 2) / DIV;
+-
+- /* CMD= Set frequency */
+- if (priv->firm_version < 0x0202)
+- rc = send_seq(priv, {0x00, 0x02, 0x00, 0x00});
+- else
+- rc = send_seq(priv, {0x80, 0x02, 0x00, 0x00});
+- 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;
-
+-
+- msleep(10);
+-
+- buf[0] = 0xff & (div >> 24);
+- buf[1] = 0xff & (div >> 16);
+- buf[2] = 0xff & (div >> 8);
+- buf[3] = 0xff & (div);
+-
+- rc = i2c_send(priv, buf, sizeof(buf));
+- if (rc < 0)
+- goto ret;
+- msleep(100);
+-
+- priv->frequency = freq;
+-
+- tuner_dbg("divisor= %02x %02x %02x %02x (freq=%d.%03d)\n",
+- buf[0], buf[1], buf[2], buf[3],
+- freq / 1000000, (freq % 1000000) / 1000);
+-
+- rc = 0;
+-
+-ret:
+- mutex_unlock(&priv->lock);
+-
+- return rc;
+-}
+-
+-static int xc2028_set_analog_freq(struct dvb_frontend *fe,
+- struct analog_parameters *p)
+-{
+- 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;
-
+-
+- if (p->mode == V4L2_TUNER_RADIO) {
+- type |= FM;
+- if (priv->ctrl.input1)
+- type |= INPUT1;
+- return generic_set_freq(fe, (625l * p->frequency) / 10,
+- T_ANALOG_TV, type, 0, 0);
+- }
+-
+- /* if std is not defined, choose one */
+- if (!p->std)
+- p->std = V4L2_STD_MN;
+-
+- /* PAL/M, PAL/N, PAL/Nc and NTSC variants should use 6MHz firmware */
+- if (!(p->std & V4L2_STD_MN))
+- type |= F8MHZ;
+-
+- /* Add audio hack to std mask */
+- p->std |= parse_audio_std_option();
+-
+- return generic_set_freq(fe, 62500l * p->frequency,
+- T_ANALOG_TV, type, p->std, 0);
+-}
+-
+-static int xc2028_set_params(struct dvb_frontend *fe,
+- struct dvb_frontend_parameters *p)
+-{
+- struct xc2028_data *priv = fe->tuner_priv;
+- unsigned int type=0;
+- 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);
- }
-
+-
+- if (priv->ctrl.d2633)
+- type |= D2633;
+- else
+- type |= D2620;
+-
+- switch(fe->ops.info.type) {
+- case FE_OFDM:
+- bw = p->u.ofdm.bandwidth;
+- break;
+- case FE_QAM:
+- tuner_info("WARN: There are some reports that "
+- "QAM 6 MHz doesn't work.\n"
+- "If this works for you, please report by "
+- "e-mail to: v4l-dvb-maintainer at linuxtv.org\n");
+- bw = BANDWIDTH_6_MHZ;
+- type |= QAM;
+- break;
+- case FE_ATSC:
+- bw = BANDWIDTH_6_MHZ;
+- /* The only ATSC firmware (at least on v2.7) is D2633,
+- so overrides ctrl->d2633 */
+- type |= ATSC| D2633;
+- type &= ~D2620;
+- break;
+- /* DVB-S is not supported */
+- default:
+- return -EINVAL;
+- }
+-
+- switch (bw) {
+- case BANDWIDTH_8_MHZ:
+- if (p->frequency < 470000000)
+- priv->ctrl.vhfbw7 = 0;
+- else
+- priv->ctrl.uhfbw8 = 1;
+- type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV8;
+- type |= F8MHZ;
+- break;
+- case BANDWIDTH_7_MHZ:
+- if (p->frequency < 470000000)
+- priv->ctrl.vhfbw7 = 1;
+- else
+- priv->ctrl.uhfbw8 = 0;
+- type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV7;
+- type |= F8MHZ;
+- break;
+- case BANDWIDTH_6_MHZ:
+- type |= DTV6;
+- priv->ctrl.vhfbw7 = 0;
+- priv->ctrl.uhfbw8 = 0;
+- break;
+- default:
+- tuner_err("error: bandwidth not supported.\n");
+- };
+-
+- /* All S-code tables need a 200kHz shift */
+- if (priv->ctrl.demod)
+- demod = priv->ctrl.demod + 200;
+-
+- return generic_set_freq(fe, p->frequency,
+- T_DIGITAL_TV, type, 0, demod);
+-}
+-
-static int xc2028_sleep(struct dvb_frontend *fe)
-{
- struct xc2028_data *priv = fe->tuner_priv;
@@ -418738,154 +589219,230 @@
- return rc;
-}
-
-
- static int xc2028_dvb_release(struct dvb_frontend *fe)
- {
- struct xc2028_data *priv = fe->tuner_priv;
-
+-
+-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;
-
+-
+- mutex_lock(&xc2028_list_mutex);
+-
+- priv->count--;
+-
+- if (!priv->count) {
+- list_del(&priv->xc2028_list);
+-
+- kfree(priv->ctrl.fname);
+-
+- free_firmware(priv);
+- kfree(priv);
+- fe->tuner_priv = NULL;
+- }
+-
+- mutex_unlock(&xc2028_list_mutex);
+-
+- return 0;
+-}
+-
+-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;
-
+-
+- *frequency = priv->frequency;
+-
+- return 0;
+-}
+-
+-static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
+-{
+- struct xc2028_data *priv = fe->tuner_priv;
+- 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);
-
+-
+- mutex_lock(&priv->lock);
+-
- kfree(priv->ctrl.fname);
- free_firmware(priv);
-
- memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
+- 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 (p->fname) {
+- 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,
+- mutex_unlock(&priv->lock);
+-
+- return rc;
+-}
+-
+-static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
+- .info = {
+- .name = "Xceive XC3028",
+- .frequency_min = 42000000,
+- .frequency_max = 864000000,
+- .frequency_step = 50000,
+- },
+-
+- .set_config = xc2028_set_config,
+- .set_analog_params = xc2028_set_analog_freq,
+- .release = xc2028_dvb_release,
+- .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)
+-};
+-
+-struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
+- struct xc2028_config *cfg)
+-{
+- struct xc2028_data *priv;
+- 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) {
+- return NULL;
+-
+- if (!fe) {
- printk(KERN_ERR PREFIX ": No frontend!\n");
-+ printk(KERN_ERR "xc2028: No frontend!\n");
- return NULL;
- }
-
+- 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) {
+-
+- 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));
-
+- video_dev = NULL;
+- break;
+- }
+- }
+-
+- if (video_dev) {
+- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+- if (priv == NULL) {
+- mutex_unlock(&xc2028_list_mutex);
+- return NULL;
+- }
+-
+- priv->i2c_props.addr = cfg->i2c_addr;
+- priv->i2c_props.adap = cfg->i2c_adap;
+- priv->video_dev = video_dev;
+- priv->tuner_callback = cfg->callback;
+- priv->ctrl.max_len = 13;
+-
+- mutex_init(&priv->lock);
+-
+- list_add_tail(&priv->xc2028_list, &xc2028_list);
+- }
+-
+- fe->tuner_priv = priv;
+- priv->count++;
+-
+- memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops,
+- sizeof(xc2028_dvb_tuner_ops));
+-
+- tuner_info("type set to %s\n", "XCeive xc2028/xc3028 tuner");
+-
+- if (cfg->ctrl)
+- xc2028_set_config(fe, cfg->ctrl);
+-
+- mutex_unlock(&xc2028_list_mutex);
+-
+- return fe;
+-}
+-
+-EXPORT_SYMBOL(xc2028_attach);
+-
+-MODULE_DESCRIPTION("Xceive xc2028/xc3028 tuner driver");
+-MODULE_AUTHOR("Michel Ludwig <michel.ludwig at gmail.com>");
+-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab at infradead.org>");
+-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/tuner-xc2028.h b/drivers/media/video/tuner-xc2028.h
-index 3eb8420..fc2f132 100644
+deleted file mode 100644
+index 3eb8420..0000000
--- a/drivers/media/video/tuner-xc2028.h
-+++ b/drivers/media/video/tuner-xc2028.h
-@@ -1,6 +1,6 @@
- /* tuner-xc2028
- *
++++ /dev/null
+@@ -1,63 +0,0 @@
+-/* tuner-xc2028
+- *
- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab at infradead.org)
-+ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab at infradead.org)
- * This code is placed under the terms of the GNU General Public License v2
- */
-
-@@ -12,7 +12,7 @@
- #define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw"
-
- /* Dmoduler IF (kHz) */
+- * This code is placed under the terms of the GNU General Public License v2
+- */
+-
+-#ifndef __TUNER_XC2028_H__
+-#define __TUNER_XC2028_H__
+-
+-#include "dvb_frontend.h"
+-
+-#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",
+-#define XC3028_FE_LG60 6000
+-#define XC3028_FE_ATI638 6380
+-#define XC3028_FE_OREN538 5380
+-#define XC3028_FE_OREN36 3600
+-#define XC3028_FE_TOYOTA388 3880
+-#define XC3028_FE_TOYOTA794 7940
+-#define XC3028_FE_DIBCOM52 5200
+-#define XC3028_FE_ZARLINK456 4560
+-#define XC3028_FE_CHINA 5200
+-
+-struct xc2028_ctrl {
+- char *fname;
+- int max_len;
+- unsigned int scode_table;
+- unsigned int mts :1;
+- unsigned int d2633 :1;
+- unsigned int input1:1;
+- unsigned int vhfbw7:1;
+- unsigned int uhfbw8:1;
+- unsigned int demod;
+-};
+-
+-struct xc2028_config {
+- struct i2c_adapter *i2c_adap;
+- u8 i2c_addr;
+- void *video_dev;
+- struct xc2028_ctrl *ctrl;
+- int (*callback) (void *dev, int command, int arg);
+-};
+-
+-/* xc2028 commands for callback */
+-#define XC2028_TUNER_RESET 0
+-#define XC2028_RESET_CLK 1
+-
+-#if defined(CONFIG_TUNER_XC2028) || (defined(CONFIG_TUNER_XC2028_MODULE) && defined(MODULE))
+-extern struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
+- struct xc2028_config *cfg);
+-#else
+-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
+- return NULL;
+-}
+-#endif
+-
+-#endif /* __TUNER_XC2028_H__ */
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
-index 01ebcec..f29a2cd 100644
+index 01ebcec..6f9945b 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -38,7 +38,7 @@
@@ -418912,6 +589469,15 @@
module_param(tda8425, int, 0444);
module_param(tda9840, int, 0444);
+@@ -1461,7 +1461,7 @@ static struct CHIPDESC chiplist[] = {
+ /* ---------------------------------------------------------------------- */
+ /* i2c registration */
+
+-static int chip_probe(struct i2c_client *client)
++static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id)
+ {
+ struct CHIPSTATE *chip;
+ struct CHIPDESC *desc;
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index dc0da44..3cf8a8e 100644
--- a/drivers/media/video/tveeprom.c
@@ -419039,6 +589605,34 @@
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
+diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c
+index bd20139..93bfd19 100644
+--- a/drivers/media/video/upd64031a.c
++++ b/drivers/media/video/upd64031a.c
+@@ -195,7 +195,8 @@ static int upd64031a_command(struct i2c_client *client, unsigned cmd, void *arg)
+
+ /* i2c implementation */
+
+-static int upd64031a_probe(struct i2c_client *client)
++static int upd64031a_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct upd64031a_state *state;
+ int i;
+diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c
+index 2d9a88f..9ab712a 100644
+--- a/drivers/media/video/upd64083.c
++++ b/drivers/media/video/upd64083.c
+@@ -172,7 +172,8 @@ static int upd64083_command(struct i2c_client *client, unsigned cmd, void *arg)
+
+ /* i2c implementation */
+
+-static int upd64083_probe(struct i2c_client *client)
++static int upd64083_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct upd64083_state *state;
+ int i;
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
@@ -419754,7 +590348,7 @@
}
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
+index da1ba02..17f542d 100644
--- a/drivers/media/video/usbvideo/vicam.c
+++ b/drivers/media/video/usbvideo/vicam.c
@@ -48,7 +48,7 @@
@@ -419766,7 +590360,20 @@
#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 = {
+@@ -70,12 +70,6 @@
+
+ #define VICAM_HEADER_SIZE 64
+
+-#define clamp( x, l, h ) max_t( __typeof__( x ), \
+- ( l ), \
+- min_t( __typeof__( x ), \
+- ( h ), \
+- ( x ) ) )
+-
+ /* Not sure what all the bytes in these char
+ * arrays do, but they're necessary to make
+ * the camera work.
+@@ -1066,7 +1060,9 @@ static const struct file_operations vicam_fops = {
.read = vicam_read,
.mmap = vicam_mmap,
.ioctl = vicam_ioctl,
@@ -419776,6 +590383,28 @@
.llseek = no_llseek,
};
+diff --git a/drivers/media/video/usbvision/Kconfig b/drivers/media/video/usbvision/Kconfig
+index fc24ef0..74e1d30 100644
+--- a/drivers/media/video/usbvision/Kconfig
++++ b/drivers/media/video/usbvision/Kconfig
+@@ -1,7 +1,7 @@
+ config VIDEO_USBVISION
+ tristate "USB video devices based on Nogatech NT1003/1004/1005"
+ depends on I2C && VIDEO_V4L2
+- select VIDEO_TUNER
++ select MEDIA_TUNER
+ select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
+ ---help---
+ There are more than 50 different USB video devices based on
+diff --git a/drivers/media/video/usbvision/Makefile b/drivers/media/video/usbvision/Makefile
+index 9ac92a8..3387187 100644
+--- a/drivers/media/video/usbvision/Makefile
++++ b/drivers/media/video/usbvision/Makefile
+@@ -3,3 +3,4 @@ usbvision-objs := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-
+ obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o
+
+ EXTRA_CFLAGS += -Idrivers/media/video
++EXTRA_CFLAGS += -Idrivers/media/common/tuners
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
@@ -422081,8 +592710,38 @@
EXPORT_SYMBOL(v4l_compat_translate_ioctl);
/*
+diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
+index 34deb68..e9dd996 100644
+--- a/drivers/media/video/v4l2-common.c
++++ b/drivers/media/video/v4l2-common.c
+@@ -710,13 +710,14 @@ EXPORT_SYMBOL(v4l2_chip_ident_i2c_client);
+ /* Helper function for I2C legacy drivers */
+
+ int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver,
+- const char *name, int (*probe)(struct i2c_client *))
++ const char *name,
++ int (*probe)(struct i2c_client *, const struct i2c_device_id *))
+ {
+ struct i2c_client *client;
+ int err;
+
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+- if (client == 0)
++ if (!client)
+ return -ENOMEM;
+
+ client->addr = address;
+@@ -724,7 +725,7 @@ int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver
+ client->driver = driver;
+ strlcpy(client->name, name, sizeof(client->name));
+
+- err = probe(client);
++ err = probe(client, NULL);
+ if (err == 0) {
+ i2c_attach_client(client);
+ } else {
diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c
-index eab79ff..fc51e49 100644
+index eab79ff..982f446 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)
@@ -422133,7 +592792,7 @@
}
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,
+@@ -98,29 +91,25 @@ 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);
@@ -422157,7 +592816,10 @@
+void *videobuf_queue_to_vmalloc (struct videobuf_queue *q,
+ struct videobuf_buffer *buf)
+{
-+ return CALL(q, vmalloc, buf);
++ if (q->int_ops->vmalloc)
++ return q->int_ops->vmalloc(buf);
++ else
++ return NULL;
+}
+EXPORT_SYMBOL_GPL(videobuf_queue_to_vmalloc);
+
@@ -422171,7 +592833,7 @@
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,
+@@ -144,10 +133,14 @@ void videobuf_queue_core_init(struct videobuf_queue *q,
BUG_ON(!q->ops->buf_queue);
BUG_ON(!q->ops->buf_release);
@@ -422186,7 +592848,7 @@
INIT_LIST_HEAD(&q->stream);
}
-@@ -195,19 +185,22 @@ void videobuf_queue_cancel(struct videobuf_queue *q)
+@@ -195,19 +188,22 @@ void videobuf_queue_cancel(struct videobuf_queue *q)
unsigned long flags = 0;
int i;
@@ -422213,7 +592875,7 @@
/* free all buffers + clear queue */
for (i = 0; i < VIDEO_MAX_FRAME; i++) {
-@@ -563,14 +556,13 @@ int videobuf_qbuf(struct videobuf_queue *q,
+@@ -563,14 +559,13 @@ int videobuf_qbuf(struct videobuf_queue *q,
list_add_tail(&buf->stream, &q->stream);
if (q->streaming) {
@@ -422231,7 +592893,7 @@
done:
mutex_unlock(&q->vb_lock);
-@@ -581,35 +573,88 @@ int videobuf_qbuf(struct videobuf_queue *q,
+@@ -581,35 +576,88 @@ int videobuf_qbuf(struct videobuf_queue *q,
return retval;
}
@@ -422337,7 +592999,7 @@
switch (buf->state) {
case VIDEOBUF_ERROR:
dprintk(1, "dqbuf: state is error\n");
-@@ -650,14 +695,13 @@ int videobuf_streamon(struct videobuf_queue *q)
+@@ -650,14 +698,13 @@ int videobuf_streamon(struct videobuf_queue *q)
if (q->streaming)
goto done;
q->streaming = 1;
@@ -422355,7 +593017,7 @@
done:
mutex_unlock(&q->vb_lock);
return retval;
-@@ -670,7 +714,6 @@ static int __videobuf_streamoff(struct videobuf_queue *q)
+@@ -670,7 +717,6 @@ static int __videobuf_streamoff(struct videobuf_queue *q)
return -EINVAL;
videobuf_queue_cancel(q);
@@ -422363,7 +593025,7 @@
return 0;
}
-@@ -712,11 +755,9 @@ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q,
+@@ -712,11 +758,9 @@ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q,
goto done;
/* start capture & wait */
@@ -422377,7 +593039,7 @@
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,
+@@ -740,14 +784,13 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
{
enum v4l2_field field;
unsigned long flags = 0;
@@ -422393,7 +593055,7 @@
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,
+@@ -778,12 +821,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
q->read_buf = NULL;
goto done;
}
@@ -422409,7 +593071,7 @@
q->read_off = 0;
}
-@@ -849,12 +888,10 @@ static int __videobuf_read_start(struct videobuf_queue *q)
+@@ -849,12 +891,10 @@ static int __videobuf_read_start(struct videobuf_queue *q)
return err;
list_add_tail(&q->bufs[i]->stream, &q->stream);
}
@@ -422424,7 +593086,7 @@
q->reading = 1;
return 0;
}
-@@ -863,7 +900,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q)
+@@ -863,7 +903,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q)
{
int i;
@@ -422432,7 +593094,7 @@
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)
+@@ -874,7 +913,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q)
q->bufs[i] = NULL;
}
q->read_buf = NULL;
@@ -422440,7 +593102,7 @@
}
-@@ -919,7 +954,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
+@@ -919,7 +957,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
@@ -422449,7 +593111,7 @@
mutex_lock(&q->vb_lock);
retval = -EBUSY;
if (q->streaming)
-@@ -968,11 +1003,9 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
+@@ -968,11 +1006,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);
@@ -423616,9 +594278,18 @@
}
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
-index 5bb7529..d545c98 100644
+index 5bb7529..01ea99c 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
+@@ -13,7 +13,7 @@
+ /*
+ * TODO:
+ * - remove "mark pages reserved-hacks" from memory allocation code
+- * and implement nopage()
++ * and implement fault()
+ * - check decimation, calculating and reporting image size when
+ * using decimation
+ * - implement read(), user mode buffers and overlay (?)
@@ -333,7 +333,7 @@ struct vino_settings {
*
* Use non-zero value to enable conversion.
@@ -424258,6 +594929,20 @@
vfd = video_device_alloc();
if (NULL == vfd)
+diff --git a/drivers/media/video/vp27smpx.c b/drivers/media/video/vp27smpx.c
+index 282c814..fac0deb 100644
+--- a/drivers/media/video/vp27smpx.c
++++ b/drivers/media/video/vp27smpx.c
+@@ -121,7 +121,8 @@ static int vp27smpx_command(struct i2c_client *client, unsigned cmd, void *arg)
+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
+ */
+
+-static int vp27smpx_probe(struct i2c_client *client)
++static int vp27smpx_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct vp27smpx_state *state;
+
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index a913385..3529302 100644
--- a/drivers/media/video/vpx3220.c
@@ -424361,6 +595046,34 @@
#undef PDBGG
#define PDBGG(fmt, args...) do {;} while(0); /* nothing: it's a placeholder */
+diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c
+index 31795b4..0f8ed84 100644
+--- a/drivers/media/video/wm8739.c
++++ b/drivers/media/video/wm8739.c
+@@ -261,7 +261,8 @@ static int wm8739_command(struct i2c_client *client, unsigned cmd, void *arg)
+
+ /* i2c implementation */
+
+-static int wm8739_probe(struct i2c_client *client)
++static int wm8739_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct wm8739_state *state;
+
+diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c
+index 869f9e7..67a409e 100644
+--- a/drivers/media/video/wm8775.c
++++ b/drivers/media/video/wm8775.c
+@@ -159,7 +159,8 @@ static int wm8775_command(struct i2c_client *client, unsigned cmd, void *arg)
+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
+ */
+
+-static int wm8775_probe(struct i2c_client *client)
++static int wm8775_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct wm8775_state *state;
+
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
@@ -424663,6 +595376,31 @@
.fops = &zoran_fops,
.release = &zoran_vdev_release,
.minor = -1
+diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran_procfs.c
+index 328ed6e..870bc5a 100644
+--- a/drivers/media/video/zoran_procfs.c
++++ b/drivers/media/video/zoran_procfs.c
+@@ -180,6 +180,7 @@ static ssize_t zoran_write(struct file *file, const char __user *buffer,
+ }
+
+ static const struct file_operations zoran_operations = {
++ .owner = THIS_MODULE,
+ .open = zoran_open,
+ .read = seq_read,
+ .write = zoran_write,
+@@ -195,10 +196,8 @@ zoran_proc_init (struct zoran *zr)
+ char name[8];
+
+ snprintf(name, 7, "zoran%d", zr->id);
+- if ((zr->zoran_proc = create_proc_entry(name, 0, NULL))) {
+- zr->zoran_proc->data = zr;
+- zr->zoran_proc->owner = THIS_MODULE;
+- zr->zoran_proc->proc_fops = &zoran_operations;
++ zr->zoran_proc = proc_create_data(name, 0, NULL, &zoran_operations, zr);
++ if (zr->zoran_proc != NULL) {
+ dprintk(2,
+ KERN_INFO
+ "%s: procfs entry /proc/%s allocated. data=%p\n",
diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zr36016.c
index dd08455..00d132b 100644
--- a/drivers/media/video/zr36016.c
@@ -425404,6 +596142,39 @@
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/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
+index a953148..81483de 100644
+--- a/drivers/message/i2o/i2o_block.c
++++ b/drivers/message/i2o/i2o_block.c
+@@ -371,7 +371,7 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req)
+ /* connect the i2o_block_request to the request */
+ if (!req->special) {
+ ireq = i2o_block_request_alloc();
+- if (unlikely(IS_ERR(ireq))) {
++ if (IS_ERR(ireq)) {
+ osm_debug("unable to allocate i2o_block_request!\n");
+ return BLKPREP_DEFER;
+ }
+diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
+index 6fdd072..54a3016 100644
+--- a/drivers/message/i2o/i2o_proc.c
++++ b/drivers/message/i2o/i2o_proc.c
+@@ -1893,13 +1893,11 @@ static int i2o_proc_create_entries(struct proc_dir_entry *dir,
+ struct proc_dir_entry *tmp;
+
+ while (i2o_pe->name) {
+- tmp = create_proc_entry(i2o_pe->name, i2o_pe->mode, dir);
++ tmp = proc_create_data(i2o_pe->name, i2o_pe->mode, dir,
++ i2o_pe->fops, data);
+ if (!tmp)
+ return -1;
+
+- tmp->data = data;
+- tmp->proc_fops = i2o_pe->fops;
+-
+ i2o_pe++;
+ }
+
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 0c886c8..2566479 100644
--- a/drivers/mfd/Kconfig
@@ -425445,6 +596216,37 @@
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/asic3.c b/drivers/mfd/asic3.c
+index f6f2d96..ef8a492 100644
+--- a/drivers/mfd/asic3.c
++++ b/drivers/mfd/asic3.c
+@@ -132,7 +132,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc)
+
+ if (iter >= MAX_ASIC_ISR_LOOPS)
+ printk(KERN_ERR "%s: interrupt processing overrun\n",
+- __FUNCTION__);
++ __func__);
+ }
+
+ static inline int asic3_irq_to_bank(struct asic3 *asic, int irq)
+@@ -409,7 +409,7 @@ int asic3_gpio_get_value(struct asic3 *asic, unsigned gpio)
+ return asic3_get_gpio_d(asic, Status) & mask;
+ default:
+ printk(KERN_ERR "%s: invalid GPIO value 0x%x",
+- __FUNCTION__, gpio);
++ __func__, gpio);
+ return -EINVAL;
+ }
+ }
+@@ -437,7 +437,7 @@ void asic3_gpio_set_value(struct asic3 *asic, unsigned gpio, int val)
+ return;
+ default:
+ printk(KERN_ERR "%s: invalid GPIO value 0x%x",
+- __FUNCTION__, gpio);
++ __func__, gpio);
+ return;
+ }
+ }
diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c
new file mode 100644
index 0000000..8872cc0
@@ -425893,10 +596695,10 @@
+MODULE_AUTHOR("Kevin O'Connor <kevin at koconnor.net>");
diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c
new file mode 100644
-index 0000000..4edc120
+index 0000000..633cbba
--- /dev/null
+++ b/drivers/mfd/htc-pasic3.c
-@@ -0,0 +1,262 @@
+@@ -0,0 +1,263 @@
+/*
+ * Core driver for HTC PASIC3 LED/DS1WM chip.
+ *
@@ -426031,8 +596833,9 @@
+ .disable = ds1wm_disable,
+};
+
-+static int ds1wm_device_add(struct device *pasic3_dev, int bus_shift)
++static int ds1wm_device_add(struct platform_device *pasic3_pdev, int bus_shift)
+{
++ struct device *pasic3_dev = &pasic3_pdev->dev;
+ struct pasic3_data *asic = pasic3_dev->driver_data;
+ struct platform_device *pdev;
+ int ret;
@@ -426043,8 +596846,8 @@
+ return -ENOMEM;
+ }
+
-+ ret = platform_device_add_resources(pdev, pdev->resource,
-+ pdev->num_resources);
++ ret = platform_device_add_resources(pdev, pasic3_pdev->resource,
++ pasic3_pdev->num_resources);
+ if (ret < 0) {
+ dev_dbg(pasic3_dev, "failed to add DS1WM resources\n");
+ goto exit_pdev_put;
@@ -426106,7 +596909,7 @@
+ return -ENOMEM;
+ }
+
-+ ret = ds1wm_device_add(dev, asic->bus_shift);
++ ret = ds1wm_device_add(pdev, asic->bus_shift);
+ if (ret < 0)
+ dev_warn(dev, "failed to register DS1WM\n");
+
@@ -426159,8 +596962,178 @@
+MODULE_AUTHOR("Philipp Zabel <philipp.zabel at gmail.com>");
+MODULE_DESCRIPTION("Core driver for HTC PASIC3");
+MODULE_LICENSE("GPL");
+diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
+index 13bac53..2fe6473 100644
+--- a/drivers/mfd/sm501.c
++++ b/drivers/mfd/sm501.c
+@@ -22,6 +22,7 @@
+
+ #include <linux/sm501.h>
+ #include <linux/sm501-regs.h>
++#include <linux/serial_8250.h>
+
+ #include <asm/io.h>
+
+@@ -348,11 +349,11 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
+ mode &= 3; /* get current power mode */
+
+ if (unit >= ARRAY_SIZE(sm->unit_power)) {
+- dev_err(dev, "%s: bad unit %d\n", __FUNCTION__, unit);
++ dev_err(dev, "%s: bad unit %d\n", __func__, unit);
+ goto already;
+ }
+
+- dev_dbg(sm->dev, "%s: unit %d, cur %d, to %d\n", __FUNCTION__, unit,
++ dev_dbg(sm->dev, "%s: unit %d, cur %d, to %d\n", __func__, unit,
+ sm->unit_power[unit], to);
+
+ if (to == 0 && sm->unit_power[unit] == 0) {
+@@ -723,13 +724,14 @@ static void sm501_device_release(struct device *dev)
+ */
+
+ static struct platform_device *
+-sm501_create_subdev(struct sm501_devdata *sm,
+- char *name, unsigned int res_count)
++sm501_create_subdev(struct sm501_devdata *sm, char *name,
++ unsigned int res_count, unsigned int platform_data_size)
+ {
+ struct sm501_device *smdev;
+
+ smdev = kzalloc(sizeof(struct sm501_device) +
+- sizeof(struct resource) * res_count, GFP_KERNEL);
++ (sizeof(struct resource) * res_count) +
++ platform_data_size, GFP_KERNEL);
+ if (!smdev)
+ return NULL;
+
+@@ -737,11 +739,15 @@ sm501_create_subdev(struct sm501_devdata *sm,
+
+ smdev->pdev.name = name;
+ smdev->pdev.id = sm->pdev_id;
+- smdev->pdev.resource = (struct resource *)(smdev+1);
+- smdev->pdev.num_resources = res_count;
+-
+ smdev->pdev.dev.parent = sm->dev;
+
++ if (res_count) {
++ smdev->pdev.resource = (struct resource *)(smdev+1);
++ smdev->pdev.num_resources = res_count;
++ }
++ if (platform_data_size)
++ smdev->pdev.dev.platform_data = (void *)(smdev+1);
++
+ return &smdev->pdev;
+ }
+
+@@ -829,7 +835,7 @@ static int sm501_register_usbhost(struct sm501_devdata *sm,
+ {
+ struct platform_device *pdev;
+
+- pdev = sm501_create_subdev(sm, "sm501-usb", 3);
++ pdev = sm501_create_subdev(sm, "sm501-usb", 3, 0);
+ if (!pdev)
+ return -ENOMEM;
+
+@@ -840,12 +846,55 @@ static int sm501_register_usbhost(struct sm501_devdata *sm,
+ return sm501_register_device(sm, pdev);
+ }
+
++static void sm501_setup_uart_data(struct sm501_devdata *sm,
++ struct plat_serial8250_port *uart_data,
++ unsigned int offset)
++{
++ uart_data->membase = sm->regs + offset;
++ uart_data->mapbase = sm->io_res->start + offset;
++ uart_data->iotype = UPIO_MEM;
++ uart_data->irq = sm->irq;
++ uart_data->flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
++ uart_data->regshift = 2;
++ uart_data->uartclk = (9600 * 16);
++}
++
++static int sm501_register_uart(struct sm501_devdata *sm, int devices)
++{
++ struct platform_device *pdev;
++ struct plat_serial8250_port *uart_data;
++
++ pdev = sm501_create_subdev(sm, "serial8250", 0,
++ sizeof(struct plat_serial8250_port) * 3);
++ if (!pdev)
++ return -ENOMEM;
++
++ uart_data = pdev->dev.platform_data;
++
++ if (devices & SM501_USE_UART0) {
++ sm501_setup_uart_data(sm, uart_data++, 0x30000);
++ sm501_unit_power(sm->dev, SM501_GATE_UART0, 1);
++ sm501_modify_reg(sm->dev, SM501_IRQ_MASK, 1 << 12, 0);
++ sm501_modify_reg(sm->dev, SM501_GPIO63_32_CONTROL, 0x01e0, 0);
++ }
++ if (devices & SM501_USE_UART1) {
++ sm501_setup_uart_data(sm, uart_data++, 0x30020);
++ sm501_unit_power(sm->dev, SM501_GATE_UART1, 1);
++ sm501_modify_reg(sm->dev, SM501_IRQ_MASK, 1 << 13, 0);
++ sm501_modify_reg(sm->dev, SM501_GPIO63_32_CONTROL, 0x1e00, 0);
++ }
++
++ pdev->id = PLAT8250_DEV_SM501;
++
++ return sm501_register_device(sm, pdev);
++}
++
+ static int sm501_register_display(struct sm501_devdata *sm,
+ resource_size_t *mem_avail)
+ {
+ struct platform_device *pdev;
+
+- pdev = sm501_create_subdev(sm, "sm501-fb", 4);
++ pdev = sm501_create_subdev(sm, "sm501-fb", 4, 0);
+ if (!pdev)
+ return -ENOMEM;
+
+@@ -963,6 +1012,7 @@ static unsigned int sm501_mem_local[] = {
+
+ static int sm501_init_dev(struct sm501_devdata *sm)
+ {
++ struct sm501_initdata *idata;
+ resource_size_t mem_avail;
+ unsigned long dramctrl;
+ unsigned long devid;
+@@ -980,6 +1030,9 @@ static int sm501_init_dev(struct sm501_devdata *sm)
+ return -EINVAL;
+ }
+
++ /* disable irqs */
++ writel(0, sm->regs + SM501_IRQ_MASK);
++
+ dramctrl = readl(sm->regs + SM501_DRAM_CONTROL);
+ mem_avail = sm501_mem_local[(dramctrl >> 13) & 0x7];
+
+@@ -998,15 +1051,14 @@ static int sm501_init_dev(struct sm501_devdata *sm)
+
+ /* check to see if we have some device initialisation */
+
+- if (sm->platdata) {
+- struct sm501_platdata *pdata = sm->platdata;
++ idata = sm->platdata ? sm->platdata->init : NULL;
++ if (idata) {
++ sm501_init_regs(sm, idata);
+
+- if (pdata->init) {
+- sm501_init_regs(sm, sm->platdata->init);
+-
+- if (pdata->init->devices & SM501_USE_USB_HOST)
+- sm501_register_usbhost(sm, &mem_avail);
+- }
++ if (idata->devices & SM501_USE_USB_HOST)
++ sm501_register_usbhost(sm, &mem_avail);
++ if (idata->devices & (SM501_USE_UART0 | SM501_USE_UART1))
++ sm501_register_uart(sm, idata->devices);
+ }
+
+ ret = sm501_check_clocks(sm);
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
-index fdbaa77..5e85948 100644
+index fdbaa77..ad34e2d 100644
--- a/drivers/mfd/ucb1x00-ts.c
+++ b/drivers/mfd/ucb1x00-ts.c
@@ -32,7 +32,6 @@
@@ -426171,8 +597144,36 @@
#include <asm/arch/collie.h>
#include <asm/mach-types.h>
+@@ -205,8 +204,7 @@ static inline int ucb1x00_ts_pen_down(struct ucb1x00_ts *ts)
+ static int ucb1x00_thread(void *_ts)
+ {
+ struct ucb1x00_ts *ts = _ts;
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
++ DECLARE_WAITQUEUE(wait, current);
+ int valid = 0;
+
+ set_freezable();
+@@ -235,7 +233,7 @@ static int ucb1x00_thread(void *_ts)
+
+
+ if (ucb1x00_ts_pen_down(ts)) {
+- set_task_state(tsk, TASK_INTERRUPTIBLE);
++ set_current_state(TASK_INTERRUPTIBLE);
+
+ ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, machine_is_collie() ? UCB_RISING : UCB_FALLING);
+ ucb1x00_disable(ts->ucb);
+@@ -263,7 +261,7 @@ static int ucb1x00_thread(void *_ts)
+ valid = 1;
+ }
+
+- set_task_state(tsk, TASK_INTERRUPTIBLE);
++ set_current_state(TASK_INTERRUPTIBLE);
+ timeout = HZ / 100;
+ }
+
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
-index 962817e..297a48f 100644
+index 962817e..636af28 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -22,6 +22,39 @@ config ATMEL_PWM
@@ -426215,7 +597216,66 @@
config IBM_ASM
tristate "Device driver for IBM RSA service processor"
depends on X86 && PCI && INPUT && EXPERIMENTAL
-@@ -327,4 +360,16 @@ config ENCLOSURE_SERVICES
+@@ -107,6 +140,7 @@ config ACER_WMI
+ depends on EXPERIMENTAL
+ depends on ACPI
+ depends on LEDS_CLASS
++ depends on NEW_LEDS
+ depends on BACKLIGHT_CLASS_DEVICE
+ depends on SERIO_I8042
+ select ACPI_WMI
+@@ -127,6 +161,7 @@ config ASUS_LAPTOP
+ depends on ACPI
+ depends on EXPERIMENTAL && !ACPI_ASUS
+ depends on LEDS_CLASS
++ depends on NEW_LEDS
+ depends on BACKLIGHT_CLASS_DEVICE
+ ---help---
+ This is the new Linux driver for Asus laptops. It may also support some
+@@ -208,10 +243,13 @@ config SONYPI_COMPAT
+ config THINKPAD_ACPI
+ tristate "ThinkPad ACPI Laptop Extras"
+ depends on X86 && ACPI
++ select BACKLIGHT_LCD_SUPPORT
+ select BACKLIGHT_CLASS_DEVICE
+ select HWMON
+ select NVRAM
+- depends on INPUT
++ select INPUT
++ select NEW_LEDS
++ select LEDS_CLASS
+ ---help---
+ This is a driver for the IBM and Lenovo ThinkPad laptops. It adds
+ support for Fn-Fx key combinations, Bluetooth control, video
+@@ -311,6 +349,7 @@ config ATMEL_SSC
+ config INTEL_MENLOW
+ tristate "Thermal Management driver for Intel menlow platform"
+ depends on ACPI_THERMAL
++ select THERMAL
+ depends on X86
+ ---help---
+ ACPI thermal management enhancement driver on
+@@ -318,6 +357,19 @@ config INTEL_MENLOW
+
+ If unsure, say N.
+
++config EEEPC_LAPTOP
++ tristate "Eee PC Hotkey Driver (EXPERIMENTAL)"
++ depends on X86
++ depends on ACPI
++ depends on BACKLIGHT_CLASS_DEVICE
++ depends on HWMON
++ depends on EXPERIMENTAL
++ ---help---
++ This driver supports the Fn-Fx keys on Eee PC laptops.
++ It also adds the ability to switch camera/wlan on/off.
++
++ If you have an Eee PC laptop, say Y or M here.
++
+ config ENCLOSURE_SERVICES
+ tristate "Enclosure Services"
+ default n
+@@ -327,4 +379,16 @@ config ENCLOSURE_SERVICES
driver (SCSI/ATA) which supports enclosures
or a SCSI enclosure device (SES) to use these services.
@@ -426233,18 +597293,23 @@
+
endif # MISC_DEVICES
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
-index 3b12f5d..5914da4 100644
+index 3b12f5d..1952875 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
+@@ -7,9 +7,11 @@ obj-$(CONFIG_IBM_ASM) += ibmasm/
+ obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/
+ obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
+ obj-$(CONFIG_ACER_WMI) += acer-wmi.o
+-obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
++obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
++obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-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
+@@ -22,3 +24,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
@@ -426417,11 +597482,691 @@
+ return platform_driver_probe(&tc_driver, tc_probe);
+}
+arch_initcall(tc_init);
+diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c
+new file mode 100644
+index 0000000..6d72760
+--- /dev/null
++++ b/drivers/misc/eeepc-laptop.c
+@@ -0,0 +1,666 @@
++/*
++ * eepc-laptop.c - Asus Eee PC extras
++ *
++ * Based on asus_acpi.c as patched for the Eee PC by Asus:
++ * ftp://ftp.asus.com/pub/ASUS/EeePC/701/ASUS_ACPI_071126.rar
++ * Based on eee.c from eeepc-linux
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/platform_device.h>
++#include <linux/backlight.h>
++#include <linux/fb.h>
++#include <linux/hwmon.h>
++#include <linux/hwmon-sysfs.h>
++#include <acpi/acpi_drivers.h>
++#include <acpi/acpi_bus.h>
++#include <linux/uaccess.h>
++
++#define EEEPC_LAPTOP_VERSION "0.1"
++
++#define EEEPC_HOTK_NAME "Eee PC Hotkey Driver"
++#define EEEPC_HOTK_FILE "eeepc"
++#define EEEPC_HOTK_CLASS "hotkey"
++#define EEEPC_HOTK_DEVICE_NAME "Hotkey"
++#define EEEPC_HOTK_HID "ASUS010"
++
++#define EEEPC_LOG EEEPC_HOTK_FILE ": "
++#define EEEPC_ERR KERN_ERR EEEPC_LOG
++#define EEEPC_WARNING KERN_WARNING EEEPC_LOG
++#define EEEPC_NOTICE KERN_NOTICE EEEPC_LOG
++#define EEEPC_INFO KERN_INFO EEEPC_LOG
++
++/*
++ * Definitions for Asus EeePC
++ */
++#define NOTIFY_WLAN_ON 0x10
++#define NOTIFY_BRN_MIN 0x20
++#define NOTIFY_BRN_MAX 0x2f
++
++enum {
++ DISABLE_ASL_WLAN = 0x0001,
++ DISABLE_ASL_BLUETOOTH = 0x0002,
++ DISABLE_ASL_IRDA = 0x0004,
++ DISABLE_ASL_CAMERA = 0x0008,
++ DISABLE_ASL_TV = 0x0010,
++ DISABLE_ASL_GPS = 0x0020,
++ DISABLE_ASL_DISPLAYSWITCH = 0x0040,
++ DISABLE_ASL_MODEM = 0x0080,
++ DISABLE_ASL_CARDREADER = 0x0100
++};
++
++enum {
++ CM_ASL_WLAN = 0,
++ CM_ASL_BLUETOOTH,
++ CM_ASL_IRDA,
++ CM_ASL_1394,
++ CM_ASL_CAMERA,
++ CM_ASL_TV,
++ CM_ASL_GPS,
++ CM_ASL_DVDROM,
++ CM_ASL_DISPLAYSWITCH,
++ CM_ASL_PANELBRIGHT,
++ CM_ASL_BIOSFLASH,
++ CM_ASL_ACPIFLASH,
++ CM_ASL_CPUFV,
++ CM_ASL_CPUTEMPERATURE,
++ CM_ASL_FANCPU,
++ CM_ASL_FANCHASSIS,
++ CM_ASL_USBPORT1,
++ CM_ASL_USBPORT2,
++ CM_ASL_USBPORT3,
++ CM_ASL_MODEM,
++ CM_ASL_CARDREADER,
++ CM_ASL_LID
++};
++
++const char *cm_getv[] = {
++ "WLDG", NULL, NULL, NULL,
++ "CAMG", NULL, NULL, NULL,
++ NULL, "PBLG", NULL, NULL,
++ "CFVG", NULL, NULL, NULL,
++ "USBG", NULL, NULL, "MODG",
++ "CRDG", "LIDG"
++};
++
++const char *cm_setv[] = {
++ "WLDS", NULL, NULL, NULL,
++ "CAMS", NULL, NULL, NULL,
++ "SDSP", "PBLS", "HDPS", NULL,
++ "CFVS", NULL, NULL, NULL,
++ "USBG", NULL, NULL, "MODS",
++ "CRDS", NULL
++};
++
++#define EEEPC_EC "\\_SB.PCI0.SBRG.EC0."
++
++#define EEEPC_EC_FAN_PWM EEEPC_EC "SC02" /* Fan PWM duty cycle (%) */
++#define EEEPC_EC_SC02 0x63
++#define EEEPC_EC_FAN_HRPM EEEPC_EC "SC05" /* High byte, fan speed (RPM) */
++#define EEEPC_EC_FAN_LRPM EEEPC_EC "SC06" /* Low byte, fan speed (RPM) */
++#define EEEPC_EC_FAN_CTRL EEEPC_EC "SFB3" /* Byte containing SF25 */
++#define EEEPC_EC_SFB3 0xD3
++
++/*
++ * This is the main structure, we can use it to store useful information
++ * about the hotk device
++ */
++struct eeepc_hotk {
++ struct acpi_device *device; /* the device we are in */
++ acpi_handle handle; /* the handle of the hotk device */
++ u32 cm_supported; /* the control methods supported
++ by this BIOS */
++ uint init_flag; /* Init flags */
++ u16 event_count[128]; /* count for each event */
++};
++
++/* The actual device the driver binds to */
++static struct eeepc_hotk *ehotk;
++
++/* Platform device/driver */
++static struct platform_driver platform_driver = {
++ .driver = {
++ .name = EEEPC_HOTK_FILE,
++ .owner = THIS_MODULE,
++ }
++};
++
++static struct platform_device *platform_device;
++
++/*
++ * The hotkey driver declaration
++ */
++static int eeepc_hotk_add(struct acpi_device *device);
++static int eeepc_hotk_remove(struct acpi_device *device, int type);
++
++static const struct acpi_device_id eeepc_device_ids[] = {
++ {EEEPC_HOTK_HID, 0},
++ {"", 0},
++};
++MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
++
++static struct acpi_driver eeepc_hotk_driver = {
++ .name = EEEPC_HOTK_NAME,
++ .class = EEEPC_HOTK_CLASS,
++ .ids = eeepc_device_ids,
++ .ops = {
++ .add = eeepc_hotk_add,
++ .remove = eeepc_hotk_remove,
++ },
++};
++
++/* The backlight device /sys/class/backlight */
++static struct backlight_device *eeepc_backlight_device;
++
++/* The hwmon device */
++static struct device *eeepc_hwmon_device;
++
++/*
++ * The backlight class declaration
++ */
++static int read_brightness(struct backlight_device *bd);
++static int update_bl_status(struct backlight_device *bd);
++static struct backlight_ops eeepcbl_ops = {
++ .get_brightness = read_brightness,
++ .update_status = update_bl_status,
++};
++
++MODULE_AUTHOR("Corentin Chary, Eric Cooper");
++MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
++MODULE_LICENSE("GPL");
++
++/*
++ * ACPI Helpers
++ */
++static int write_acpi_int(acpi_handle handle, const char *method, int val,
++ struct acpi_buffer *output)
++{
++ struct acpi_object_list params;
++ union acpi_object in_obj;
++ acpi_status status;
++
++ params.count = 1;
++ params.pointer = &in_obj;
++ in_obj.type = ACPI_TYPE_INTEGER;
++ in_obj.integer.value = val;
++
++ status = acpi_evaluate_object(handle, (char *)method, ¶ms, output);
++ return (status == AE_OK ? 0 : -1);
++}
++
++static int read_acpi_int(acpi_handle handle, const char *method, int *val)
++{
++ acpi_status status;
++ ulong result;
++
++ status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
++ if (ACPI_FAILURE(status)) {
++ *val = -1;
++ return -1;
++ } else {
++ *val = result;
++ return 0;
++ }
++}
++
++static int set_acpi(int cm, int value)
++{
++ if (ehotk->cm_supported & (0x1 << cm)) {
++ const char *method = cm_setv[cm];
++ if (method == NULL)
++ return -ENODEV;
++ if (write_acpi_int(ehotk->handle, method, value, NULL))
++ printk(EEEPC_WARNING "Error writing %s\n", method);
++ }
++ return 0;
++}
++
++static int get_acpi(int cm)
++{
++ int value = -1;
++ if ((ehotk->cm_supported & (0x1 << cm))) {
++ const char *method = cm_getv[cm];
++ if (method == NULL)
++ return -ENODEV;
++ if (read_acpi_int(ehotk->handle, method, &value))
++ printk(EEEPC_WARNING "Error reading %s\n", method);
++ }
++ return value;
++}
++
++/*
++ * Backlight
++ */
++static int read_brightness(struct backlight_device *bd)
++{
++ return get_acpi(CM_ASL_PANELBRIGHT);
++}
++
++static int set_brightness(struct backlight_device *bd, int value)
++{
++ value = max(0, min(15, value));
++ return set_acpi(CM_ASL_PANELBRIGHT, value);
++}
++
++static int update_bl_status(struct backlight_device *bd)
++{
++ return set_brightness(bd, bd->props.brightness);
++}
++
++/*
++ * Sys helpers
++ */
++static int parse_arg(const char *buf, unsigned long count, int *val)
++{
++ if (!count)
++ return 0;
++ if (sscanf(buf, "%i", val) != 1)
++ return -EINVAL;
++ return count;
++}
++
++static ssize_t store_sys_acpi(int cm, const char *buf, size_t count)
++{
++ int rv, value;
++
++ rv = parse_arg(buf, count, &value);
++ if (rv > 0)
++ set_acpi(cm, value);
++ return rv;
++}
++
++static ssize_t show_sys_acpi(int cm, char *buf)
++{
++ return sprintf(buf, "%d\n", get_acpi(cm));
++}
++
++#define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \
++ static ssize_t show_##_name(struct device *dev, \
++ struct device_attribute *attr, \
++ char *buf) \
++ { \
++ return show_sys_acpi(_cm, buf); \
++ } \
++ static ssize_t store_##_name(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
++ { \
++ return store_sys_acpi(_cm, buf, count); \
++ } \
++ static struct device_attribute dev_attr_##_name = { \
++ .attr = { \
++ .name = __stringify(_name), \
++ .mode = 0644 }, \
++ .show = show_##_name, \
++ .store = store_##_name, \
++ }
++
++EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
++EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
++EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
++EEEPC_CREATE_DEVICE_ATTR(wlan, CM_ASL_WLAN);
++
++static struct attribute *platform_attributes[] = {
++ &dev_attr_camera.attr,
++ &dev_attr_cardr.attr,
++ &dev_attr_disp.attr,
++ &dev_attr_wlan.attr,
++ NULL
++};
++
++static struct attribute_group platform_attribute_group = {
++ .attrs = platform_attributes
++};
++
++/*
++ * Hotkey functions
++ */
++static int eeepc_hotk_check(void)
++{
++ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
++ int result;
++
++ result = acpi_bus_get_status(ehotk->device);
++ if (result)
++ return result;
++ if (ehotk->device->status.present) {
++ if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag,
++ &buffer)) {
++ printk(EEEPC_ERR "Hotkey initialization failed\n");
++ return -ENODEV;
++ } else {
++ printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n",
++ ehotk->init_flag);
++ }
++ /* get control methods supported */
++ if (read_acpi_int(ehotk->handle, "CMSG"
++ , &ehotk->cm_supported)) {
++ printk(EEEPC_ERR
++ "Get control methods supported failed\n");
++ return -ENODEV;
++ } else {
++ printk(EEEPC_INFO
++ "Get control methods supported: 0x%x\n",
++ ehotk->cm_supported);
++ }
++ } else {
++ printk(EEEPC_ERR "Hotkey device not present, aborting\n");
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static void notify_wlan(u32 *event)
++{
++ /* if DISABLE_ASL_WLAN is set, the notify code for fn+f2
++ will always be 0x10 */
++ if (ehotk->cm_supported & (0x1 << CM_ASL_WLAN)) {
++ const char *method = cm_getv[CM_ASL_WLAN];
++ int value;
++ if (read_acpi_int(ehotk->handle, method, &value))
++ printk(EEEPC_WARNING "Error reading %s\n",
++ method);
++ else if (value == 1)
++ *event = 0x11;
++ }
++}
++
++static void notify_brn(void)
++{
++ struct backlight_device *bd = eeepc_backlight_device;
++ bd->props.brightness = read_brightness(bd);
++}
++
++static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
++{
++ if (!ehotk)
++ return;
++ if (event == NOTIFY_WLAN_ON && (DISABLE_ASL_WLAN & ehotk->init_flag))
++ notify_wlan(&event);
++ if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
++ notify_brn();
++ acpi_bus_generate_proc_event(ehotk->device, event,
++ ehotk->event_count[event % 128]++);
++}
++
++static int eeepc_hotk_add(struct acpi_device *device)
++{
++ acpi_status status = AE_OK;
++ int result;
++
++ if (!device)
++ return -EINVAL;
++ printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n");
++ ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
++ if (!ehotk)
++ return -ENOMEM;
++ ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
++ ehotk->handle = device->handle;
++ strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);
++ strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS);
++ acpi_driver_data(device) = ehotk;
++ ehotk->device = device;
++ result = eeepc_hotk_check();
++ if (result)
++ goto end;
++ status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
++ eeepc_hotk_notify, ehotk);
++ if (ACPI_FAILURE(status))
++ printk(EEEPC_ERR "Error installing notify handler\n");
++ end:
++ if (result) {
++ kfree(ehotk);
++ ehotk = NULL;
++ }
++ return result;
++}
++
++static int eeepc_hotk_remove(struct acpi_device *device, int type)
++{
++ acpi_status status = 0;
++
++ if (!device || !acpi_driver_data(device))
++ return -EINVAL;
++ status = acpi_remove_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
++ eeepc_hotk_notify);
++ if (ACPI_FAILURE(status))
++ printk(EEEPC_ERR "Error removing notify handler\n");
++ kfree(ehotk);
++ return 0;
++}
++
++/*
++ * Hwmon
++ */
++static int eeepc_get_fan_pwm(void)
++{
++ int value = 0;
++
++ read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value);
++ return (value);
++}
++
++static void eeepc_set_fan_pwm(int value)
++{
++ value = SENSORS_LIMIT(value, 0, 100);
++ ec_write(EEEPC_EC_SC02, value);
++}
++
++static int eeepc_get_fan_rpm(void)
++{
++ int high = 0;
++ int low = 0;
++
++ read_acpi_int(NULL, EEEPC_EC_FAN_HRPM, &high);
++ read_acpi_int(NULL, EEEPC_EC_FAN_LRPM, &low);
++ return (high << 8 | low);
++}
++
++static int eeepc_get_fan_ctrl(void)
++{
++ int value = 0;
++
++ read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
++ return ((value & 0x02 ? 1 : 0));
++}
++
++static void eeepc_set_fan_ctrl(int manual)
++{
++ int value = 0;
++
++ read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
++ if (manual)
++ value |= 0x02;
++ else
++ value &= ~0x02;
++ ec_write(EEEPC_EC_SFB3, value);
++}
++
++static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
++{
++ int rv, value;
++
++ rv = parse_arg(buf, count, &value);
++ if (rv > 0)
++ set(value);
++ return rv;
++}
++
++static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
++{
++ return sprintf(buf, "%d\n", get());
++}
++
++#define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \
++ static ssize_t show_##_name(struct device *dev, \
++ struct device_attribute *attr, \
++ char *buf) \
++ { \
++ return show_sys_hwmon(_set, buf); \
++ } \
++ static ssize_t store_##_name(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
++ { \
++ return store_sys_hwmon(_get, buf, count); \
++ } \
++ static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0);
++
++EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL);
++EEEPC_CREATE_SENSOR_ATTR(fan1_pwm, S_IRUGO | S_IWUSR,
++ eeepc_get_fan_pwm, eeepc_set_fan_pwm);
++EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
++ eeepc_get_fan_ctrl, eeepc_set_fan_ctrl);
++
++static struct attribute *hwmon_attributes[] = {
++ &sensor_dev_attr_fan1_pwm.dev_attr.attr,
++ &sensor_dev_attr_fan1_input.dev_attr.attr,
++ &sensor_dev_attr_pwm1_enable.dev_attr.attr,
++ NULL
++};
++
++static struct attribute_group hwmon_attribute_group = {
++ .attrs = hwmon_attributes
++};
++
++/*
++ * exit/init
++ */
++static void eeepc_backlight_exit(void)
++{
++ if (eeepc_backlight_device)
++ backlight_device_unregister(eeepc_backlight_device);
++ eeepc_backlight_device = NULL;
++}
++
++static void eeepc_hwmon_exit(void)
++{
++ struct device *hwmon;
++
++ hwmon = eeepc_hwmon_device;
++ if (!hwmon)
++ return ;
++ hwmon_device_unregister(hwmon);
++ sysfs_remove_group(&hwmon->kobj,
++ &hwmon_attribute_group);
++ eeepc_hwmon_device = NULL;
++}
++
++static void __exit eeepc_laptop_exit(void)
++{
++ eeepc_backlight_exit();
++ eeepc_hwmon_exit();
++ acpi_bus_unregister_driver(&eeepc_hotk_driver);
++ sysfs_remove_group(&platform_device->dev.kobj,
++ &platform_attribute_group);
++ platform_device_unregister(platform_device);
++ platform_driver_unregister(&platform_driver);
++}
++
++static int eeepc_backlight_init(struct device *dev)
++{
++ struct backlight_device *bd;
++
++ bd = backlight_device_register(EEEPC_HOTK_FILE, dev,
++ NULL, &eeepcbl_ops);
++ if (IS_ERR(bd)) {
++ printk(EEEPC_ERR
++ "Could not register eeepc backlight device\n");
++ eeepc_backlight_device = NULL;
++ return PTR_ERR(bd);
++ }
++ eeepc_backlight_device = bd;
++ bd->props.max_brightness = 15;
++ bd->props.brightness = read_brightness(NULL);
++ bd->props.power = FB_BLANK_UNBLANK;
++ backlight_update_status(bd);
++ return 0;
++}
++
++static int eeepc_hwmon_init(struct device *dev)
++{
++ struct device *hwmon;
++ int result;
++
++ hwmon = hwmon_device_register(dev);
++ if (IS_ERR(hwmon)) {
++ printk(EEEPC_ERR
++ "Could not register eeepc hwmon device\n");
++ eeepc_hwmon_device = NULL;
++ return PTR_ERR(hwmon);
++ }
++ eeepc_hwmon_device = hwmon;
++ result = sysfs_create_group(&hwmon->kobj,
++ &hwmon_attribute_group);
++ if (result)
++ eeepc_hwmon_exit();
++ return result;
++}
++
++static int __init eeepc_laptop_init(void)
++{
++ struct device *dev;
++ int result;
++
++ if (acpi_disabled)
++ return -ENODEV;
++ result = acpi_bus_register_driver(&eeepc_hotk_driver);
++ if (result < 0)
++ return result;
++ if (!ehotk) {
++ acpi_bus_unregister_driver(&eeepc_hotk_driver);
++ return -ENODEV;
++ }
++ dev = acpi_get_physical_device(ehotk->device->handle);
++ result = eeepc_backlight_init(dev);
++ if (result)
++ goto fail_backlight;
++ result = eeepc_hwmon_init(dev);
++ if (result)
++ goto fail_hwmon;
++ /* Register platform stuff */
++ result = platform_driver_register(&platform_driver);
++ if (result)
++ goto fail_platform_driver;
++ platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1);
++ if (!platform_device) {
++ result = -ENOMEM;
++ goto fail_platform_device1;
++ }
++ result = platform_device_add(platform_device);
++ if (result)
++ goto fail_platform_device2;
++ result = sysfs_create_group(&platform_device->dev.kobj,
++ &platform_attribute_group);
++ if (result)
++ goto fail_sysfs;
++ return 0;
++fail_sysfs:
++ platform_device_del(platform_device);
++fail_platform_device2:
++ platform_device_put(platform_device);
++fail_platform_device1:
++ platform_driver_unregister(&platform_driver);
++fail_platform_driver:
++ eeepc_hwmon_exit();
++fail_hwmon:
++ eeepc_backlight_exit();
++fail_backlight:
++ return result;
++}
++
++module_init(eeepc_laptop_init);
++module_exit(eeepc_laptop_exit);
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
-index 6fcb0e9..fafb57f 100644
+index 6fcb0e9..0736cff 100644
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
-@@ -40,16 +40,16 @@ static struct class enclosure_component_class;
+@@ -31,7 +31,6 @@
+ static LIST_HEAD(container_list);
+ static DEFINE_MUTEX(container_list_lock);
+ static struct class enclosure_class;
+-static struct class enclosure_component_class;
+
+ /**
+ * enclosure_find - find an enclosure given a device
+@@ -40,16 +39,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
@@ -426442,7 +598187,7 @@
mutex_unlock(&container_list_lock);
return edev;
}
-@@ -117,11 +117,11 @@ enclosure_register(struct device *dev, const char *name, int components,
+@@ -117,11 +116,11 @@ enclosure_register(struct device *dev, const char *name, int components,
edev->components = components;
@@ -426458,7 +598203,7 @@
if (err)
goto err;
-@@ -135,7 +135,7 @@ enclosure_register(struct device *dev, const char *name, int components,
+@@ -135,7 +134,7 @@ enclosure_register(struct device *dev, const char *name, int components,
return edev;
err:
@@ -426467,7 +598212,7 @@
kfree(edev);
return ERR_PTR(err);
}
-@@ -158,27 +158,28 @@ void enclosure_unregister(struct enclosure_device *edev)
+@@ -158,29 +157,69 @@ void enclosure_unregister(struct enclosure_device *edev)
for (i = 0; i < edev->components; i++)
if (edev->component[i].number != -1)
@@ -426482,6 +598227,40 @@
EXPORT_SYMBOL_GPL(enclosure_unregister);
-static void enclosure_release(struct class_device *cdev)
++#define ENCLOSURE_NAME_SIZE 64
++
++static void enclosure_link_name(struct enclosure_component *cdev, char *name)
++{
++ strcpy(name, "enclosure_device:");
++ strcat(name, cdev->cdev.bus_id);
++}
++
++static void enclosure_remove_links(struct enclosure_component *cdev)
++{
++ char name[ENCLOSURE_NAME_SIZE];
++
++ enclosure_link_name(cdev, name);
++ sysfs_remove_link(&cdev->dev->kobj, name);
++ sysfs_remove_link(&cdev->cdev.kobj, "device");
++}
++
++static int enclosure_add_links(struct enclosure_component *cdev)
++{
++ int error;
++ char name[ENCLOSURE_NAME_SIZE];
++
++ error = sysfs_create_link(&cdev->cdev.kobj, &cdev->dev->kobj, "device");
++ if (error)
++ return error;
++
++ enclosure_link_name(cdev, name);
++ error = sysfs_create_link(&cdev->dev->kobj, &cdev->cdev.kobj, name);
++ if (error)
++ sysfs_remove_link(&cdev->cdev.kobj, "device");
++
++ return error;
++}
++
+static void enclosure_release(struct device *cdev)
{
struct enclosure_device *edev = to_enclosure_device(cdev);
@@ -426495,16 +598274,22 @@
+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);
++ if (cdev->dev) {
++ enclosure_remove_links(cdev);
+ put_device(cdev->dev);
+- class_device_put(cdev->parent);
++ }
+ put_device(dev->parent);
}
++static struct attribute_group *enclosure_groups[];
++
/**
-@@ -201,7 +202,7 @@ enclosure_component_register(struct enclosure_device *edev,
+ * enclosure_component_register - add a particular component to an enclosure
+ * @edev: the enclosure to add the component
+@@ -201,7 +240,7 @@ enclosure_component_register(struct enclosure_device *edev,
const char *name)
{
struct enclosure_component *ecomp;
@@ -426513,13 +598298,13 @@
int err;
if (number >= edev->components)
-@@ -215,14 +216,14 @@ enclosure_component_register(struct enclosure_device *edev,
+@@ -215,14 +254,16 @@ enclosure_component_register(struct enclosure_device *edev,
ecomp->type = type;
ecomp->number = number;
cdev = &ecomp->cdev;
- cdev->parent = class_device_get(&edev->cdev);
+- cdev->class = &enclosure_component_class;
+ 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);
@@ -426528,11 +598313,14 @@
+ snprintf(cdev->bus_id, BUS_ID_SIZE, "%u", number);
- err = class_device_register(cdev);
++ cdev->release = enclosure_component_release;
++ cdev->groups = enclosure_groups;
++
+ err = device_register(cdev);
if (err)
ERR_PTR(err);
-@@ -247,18 +248,17 @@ EXPORT_SYMBOL_GPL(enclosure_component_register);
+@@ -247,18 +288,19 @@ EXPORT_SYMBOL_GPL(enclosure_component_register);
int enclosure_add_device(struct enclosure_device *edev, int component,
struct device *dev)
{
@@ -426546,17 +598334,18 @@
+ cdev = &edev->component[component];
- class_device_del(cdev);
-- if (cdev->dev)
+ if (cdev->dev)
- put_device(cdev->dev);
-+ device_del(&cdev->cdev);
++ enclosure_remove_links(cdev);
++
+ put_device(cdev->dev);
cdev->dev = get_device(dev);
- return class_device_add(cdev);
-+ return device_add(&cdev->cdev);
++ return enclosure_add_links(cdev);
}
EXPORT_SYMBOL_GPL(enclosure_add_device);
-@@ -272,18 +272,17 @@ EXPORT_SYMBOL_GPL(enclosure_add_device);
+@@ -272,18 +314,17 @@ EXPORT_SYMBOL_GPL(enclosure_add_device);
*/
int enclosure_remove_device(struct enclosure_device *edev, int component)
{
@@ -426580,7 +598369,7 @@
}
EXPORT_SYMBOL_GPL(enclosure_remove_device);
-@@ -291,14 +290,16 @@ EXPORT_SYMBOL_GPL(enclosure_remove_device);
+@@ -291,14 +332,16 @@ EXPORT_SYMBOL_GPL(enclosure_remove_device);
* sysfs pieces below
*/
@@ -426599,7 +598388,7 @@
__ATTR(components, S_IRUGO, enclosure_show_components, NULL),
__ATTR_NULL
};
-@@ -306,8 +307,8 @@ static struct class_device_attribute enclosure_attrs[] = {
+@@ -306,8 +349,8 @@ static struct class_device_attribute enclosure_attrs[] = {
static struct class enclosure_class = {
.name = "enclosure",
.owner = THIS_MODULE,
@@ -426610,7 +598399,7 @@
};
static const char *const enclosure_status [] = {
-@@ -326,7 +327,8 @@ static const char *const enclosure_type [] = {
+@@ -326,7 +369,8 @@ static const char *const enclosure_type [] = {
[ENCLOSURE_COMPONENT_ARRAY_DEVICE] = "array device",
};
@@ -426620,7 +598409,7 @@
{
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)
+@@ -336,8 +380,9 @@ static ssize_t get_component_fault(struct class_device *cdev, char *buf)
return snprintf(buf, 40, "%d\n", ecomp->fault);
}
@@ -426632,7 +598421,7 @@
{
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,
+@@ -348,7 +393,8 @@ static ssize_t set_component_fault(struct class_device *cdev, const char *buf,
return count;
}
@@ -426642,7 +598431,7 @@
{
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)
+@@ -358,8 +404,9 @@ static ssize_t get_component_status(struct class_device *cdev, char *buf)
return snprintf(buf, 40, "%s\n", enclosure_status[ecomp->status]);
}
@@ -426654,7 +598443,7 @@
{
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,
+@@ -380,7 +427,8 @@ static ssize_t set_component_status(struct class_device *cdev, const char *buf,
return -EINVAL;
}
@@ -426664,7 +598453,7 @@
{
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)
+@@ -390,8 +438,9 @@ static ssize_t get_component_active(struct class_device *cdev, char *buf)
return snprintf(buf, 40, "%d\n", ecomp->active);
}
@@ -426676,7 +598465,7 @@
{
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,
+@@ -402,7 +451,8 @@ static ssize_t set_component_active(struct class_device *cdev, const char *buf,
return count;
}
@@ -426686,7 +598475,7 @@
{
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)
+@@ -412,8 +462,9 @@ static ssize_t get_component_locate(struct class_device *cdev, char *buf)
return snprintf(buf, 40, "%d\n", ecomp->locate);
}
@@ -426698,7 +598487,7 @@
{
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,
+@@ -424,7 +475,8 @@ static ssize_t set_component_locate(struct class_device *cdev, const char *buf,
return count;
}
@@ -426708,31 +598497,229 @@
{
struct enclosure_component *ecomp = to_enclosure_component(cdev);
-@@ -432,7 +442,7 @@ static ssize_t get_component_type(struct class_device *cdev, char *buf)
+@@ -432,24 +484,32 @@ 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,
+- __ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault,
+- set_component_fault),
+- __ATTR(status, S_IRUGO | S_IWUSR, get_component_status,
+- set_component_status),
+- __ATTR(active, S_IRUGO | S_IWUSR, get_component_active,
+- set_component_active),
+- __ATTR(locate, S_IRUGO | S_IWUSR, get_component_locate,
+- set_component_locate),
+- __ATTR(type, S_IRUGO, get_component_type, NULL),
+- __ATTR_NULL
++static DEVICE_ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault,
++ set_component_fault);
++static DEVICE_ATTR(status, S_IRUGO | S_IWUSR, get_component_status,
++ set_component_status);
++static DEVICE_ATTR(active, S_IRUGO | S_IWUSR, get_component_active,
++ set_component_active);
++static DEVICE_ATTR(locate, S_IRUGO | S_IWUSR, get_component_locate,
++ set_component_locate);
++static DEVICE_ATTR(type, S_IRUGO, get_component_type, NULL);
++
++static struct attribute *enclosure_component_attrs[] = {
++ &dev_attr_fault.attr,
++ &dev_attr_status.attr,
++ &dev_attr_active.attr,
++ &dev_attr_locate.attr,
++ &dev_attr_type.attr,
++ NULL
+ };
+
+-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 struct attribute_group enclosure_group = {
++ .attrs = enclosure_component_attrs,
++};
++
++static struct attribute_group *enclosure_groups[] = {
++ &enclosure_group,
++ NULL
};
static int __init enclosure_init(void)
+@@ -459,20 +519,12 @@ static int __init enclosure_init(void)
+ err = class_register(&enclosure_class);
+ if (err)
+ return err;
+- err = class_register(&enclosure_component_class);
+- if (err)
+- goto err_out;
+
+ return 0;
+- err_out:
+- class_unregister(&enclosure_class);
+-
+- return err;
+ }
+
+ static void __exit enclosure_exit(void)
+ {
+- class_unregister(&enclosure_component_class);
+ class_unregister(&enclosure_class);
+ }
+
+diff --git a/drivers/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c
+index 302e924..ff51ab6 100644
+--- a/drivers/misc/hdpuftrs/hdpu_cpustate.c
++++ b/drivers/misc/hdpuftrs/hdpu_cpustate.c
+@@ -210,13 +210,10 @@ static int hdpu_cpustate_probe(struct platform_device *pdev)
+ return ret;
+ }
+
+- proc_de = create_proc_entry("sky_cpustate", 0666, &proc_root);
++ proc_de = proc_create("sky_cpustate", 0666, NULL, &proc_cpustate);
+ if (!proc_de) {
+ printk(KERN_WARNING "sky_cpustate: "
+ "Unable to create proc entry\n");
+- } else {
+- proc_de->proc_fops = &proc_cpustate;
+- proc_de->owner = THIS_MODULE;
+ }
+
+ printk(KERN_INFO "Sky CPU State Driver v" SKY_CPUSTATE_VERSION "\n");
+diff --git a/drivers/misc/hdpuftrs/hdpu_nexus.c b/drivers/misc/hdpuftrs/hdpu_nexus.c
+index 2fa36f7..08e26be 100644
+--- a/drivers/misc/hdpuftrs/hdpu_nexus.c
++++ b/drivers/misc/hdpuftrs/hdpu_nexus.c
+@@ -102,22 +102,17 @@ static int hdpu_nexus_probe(struct platform_device *pdev)
+ printk(KERN_ERR "sky_nexus: Could not map slot id\n");
+ }
+
+- hdpu_slot_id = create_proc_entry("sky_slot_id", 0666, &proc_root);
++ hdpu_slot_id = proc_create("sky_slot_id", 0666, NULL, &proc_slot_id);
+ if (!hdpu_slot_id) {
+ printk(KERN_WARNING "sky_nexus: "
+ "Unable to create proc dir entry: sky_slot_id\n");
+- } else {
+- hdpu_slot_id->proc_fops = &proc_slot_id;
+- hdpu_slot_id->owner = THIS_MODULE;
+ }
+
+- hdpu_chassis_id = create_proc_entry("sky_chassis_id", 0666, &proc_root);
+- if (!hdpu_chassis_id) {
++ hdpu_chassis_id = proc_create("sky_chassis_id", 0666, NULL,
++ &proc_chassis_id);
++ if (!hdpu_chassis_id)
+ printk(KERN_WARNING "sky_nexus: "
+ "Unable to create proc dir entry: sky_chassis_id\n");
+- } else {
+- hdpu_chassis_id->proc_fops = &proc_chassis_id;
+- hdpu_chassis_id->owner = THIS_MODULE;
+ }
+
+ return 0;
+@@ -128,8 +123,8 @@ static int hdpu_nexus_remove(struct platform_device *pdev)
+ slot_id = -1;
+ chassis_id = -1;
+
+- remove_proc_entry("sky_slot_id", &proc_root);
+- remove_proc_entry("sky_chassis_id", &proc_root);
++ remove_proc_entry("sky_slot_id", NULL);
++ remove_proc_entry("sky_chassis_id", NULL);
+
+ hdpu_slot_id = 0;
+ hdpu_chassis_id = 0;
+diff --git a/drivers/misc/ibmasm/command.c b/drivers/misc/ibmasm/command.c
+index 1a0e797..276d3fb 100644
+--- a/drivers/misc/ibmasm/command.c
++++ b/drivers/misc/ibmasm/command.c
+@@ -96,7 +96,7 @@ static inline void do_exec_command(struct service_processor *sp)
+ {
+ char tsbuf[32];
+
+- dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
++ dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
+
+ if (ibmasm_send_i2o_message(sp)) {
+ sp->current_command->status = IBMASM_CMD_FAILED;
+@@ -119,7 +119,7 @@ void ibmasm_exec_command(struct service_processor *sp, struct command *cmd)
+ unsigned long flags;
+ char tsbuf[32];
+
+- dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
++ dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
+
+ spin_lock_irqsave(&sp->lock, flags);
+
+@@ -139,7 +139,7 @@ static void exec_next_command(struct service_processor *sp)
+ unsigned long flags;
+ char tsbuf[32];
+
+- dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
++ dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
+
+ spin_lock_irqsave(&sp->lock, flags);
+ sp->current_command = dequeue_command(sp);
+diff --git a/drivers/misc/ibmasm/heartbeat.c b/drivers/misc/ibmasm/heartbeat.c
+index 3036e78..1bc4306 100644
+--- a/drivers/misc/ibmasm/heartbeat.c
++++ b/drivers/misc/ibmasm/heartbeat.c
+@@ -75,9 +75,9 @@ void ibmasm_heartbeat_exit(struct service_processor *sp)
+ {
+ char tsbuf[32];
+
+- dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
++ dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
+ ibmasm_wait_for_response(sp->heartbeat, IBMASM_CMD_TIMEOUT_NORMAL);
+- dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
++ dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
+ suspend_heartbeats = 1;
+ command_put(sp->heartbeat);
+ }
+@@ -88,7 +88,7 @@ void ibmasm_receive_heartbeat(struct service_processor *sp, void *message, size
+ struct dot_command_header *header = (struct dot_command_header *)cmd->buffer;
+ char tsbuf[32];
+
+- dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
++ dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
+ if (suspend_heartbeats)
+ return;
+
diff --git a/drivers/misc/intel_menlow.c b/drivers/misc/intel_menlow.c
-index de16e88..0c0bb30 100644
+index de16e88..80a1363 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)
+@@ -175,19 +175,17 @@ static int intel_menlow_memory_add(struct acpi_device *device)
+ goto end;
+ }
+
+- if (cdev) {
+- acpi_driver_data(device) = cdev;
+- result = sysfs_create_link(&device->dev.kobj,
+- &cdev->device.kobj, "thermal_cooling");
+- if (result)
+- goto unregister;
+-
+- result = sysfs_create_link(&cdev->device.kobj,
+- &device->dev.kobj, "device");
+- if (result) {
+- sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
+- goto unregister;
+- }
++ acpi_driver_data(device) = cdev;
++ result = sysfs_create_link(&device->dev.kobj,
++ &cdev->device.kobj, "thermal_cooling");
++ if (result)
++ goto unregister;
++
++ result = sysfs_create_link(&cdev->device.kobj,
++ &device->dev.kobj, "device");
++ if (result) {
++ sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
++ goto unregister;
+ }
+
+ end:
+@@ -213,7 +211,7 @@ static int intel_menlow_memory_remove(struct acpi_device *device, int type)
return 0;
}
@@ -426741,9 +598728,103 @@
{"INT0002", 0},
{"", 0},
};
+diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c
+index 05172d2..6f76573 100644
+--- a/drivers/misc/ioc4.c
++++ b/drivers/misc/ioc4.c
+@@ -75,7 +75,7 @@ ioc4_register_submodule(struct ioc4_submodule *is)
+ printk(KERN_WARNING
+ "%s: IOC4 submodule %s probe failed "
+ "for pci_dev %s",
+- __FUNCTION__, module_name(is->is_owner),
++ __func__, module_name(is->is_owner),
+ pci_name(idd->idd_pdev));
+ }
+ }
+@@ -102,7 +102,7 @@ ioc4_unregister_submodule(struct ioc4_submodule *is)
+ printk(KERN_WARNING
+ "%s: IOC4 submodule %s remove failed "
+ "for pci_dev %s.\n",
+- __FUNCTION__, module_name(is->is_owner),
++ __func__, module_name(is->is_owner),
+ pci_name(idd->idd_pdev));
+ }
+ }
+@@ -282,7 +282,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+ if ((ret = pci_enable_device(pdev))) {
+ printk(KERN_WARNING
+ "%s: Failed to enable IOC4 device for pci_dev %s.\n",
+- __FUNCTION__, pci_name(pdev));
++ __func__, pci_name(pdev));
+ goto out;
+ }
+ pci_set_master(pdev);
+@@ -292,7 +292,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+ if (!idd) {
+ printk(KERN_WARNING
+ "%s: Failed to allocate IOC4 data for pci_dev %s.\n",
+- __FUNCTION__, pci_name(pdev));
++ __func__, pci_name(pdev));
+ ret = -ENODEV;
+ goto out_idd;
+ }
+@@ -307,7 +307,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+ printk(KERN_WARNING
+ "%s: Unable to find IOC4 misc resource "
+ "for pci_dev %s.\n",
+- __FUNCTION__, pci_name(idd->idd_pdev));
++ __func__, pci_name(idd->idd_pdev));
+ ret = -ENODEV;
+ goto out_pci;
+ }
+@@ -316,7 +316,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+ printk(KERN_WARNING
+ "%s: Unable to request IOC4 misc region "
+ "for pci_dev %s.\n",
+- __FUNCTION__, pci_name(idd->idd_pdev));
++ __func__, pci_name(idd->idd_pdev));
+ ret = -ENODEV;
+ goto out_pci;
+ }
+@@ -326,7 +326,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+ printk(KERN_WARNING
+ "%s: Unable to remap IOC4 misc region "
+ "for pci_dev %s.\n",
+- __FUNCTION__, pci_name(idd->idd_pdev));
++ __func__, pci_name(idd->idd_pdev));
+ ret = -ENODEV;
+ goto out_misc_region;
+ }
+@@ -372,7 +372,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+ printk(KERN_WARNING
+ "%s: IOC4 submodule 0x%s probe failed "
+ "for pci_dev %s.\n",
+- __FUNCTION__, module_name(is->is_owner),
++ __func__, module_name(is->is_owner),
+ pci_name(idd->idd_pdev));
+ }
+ }
+@@ -406,7 +406,7 @@ ioc4_remove(struct pci_dev *pdev)
+ printk(KERN_WARNING
+ "%s: IOC4 submodule 0x%s remove failed "
+ "for pci_dev %s.\n",
+- __FUNCTION__, module_name(is->is_owner),
++ __func__, module_name(is->is_owner),
+ pci_name(idd->idd_pdev));
+ }
+ }
+@@ -418,7 +418,7 @@ ioc4_remove(struct pci_dev *pdev)
+ printk(KERN_WARNING
+ "%s: Unable to get IOC4 misc mapping for pci_dev %s. "
+ "Device removal may be incomplete.\n",
+- __FUNCTION__, pci_name(idd->idd_pdev));
++ __func__, pci_name(idd->idd_pdev));
+ }
+ release_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
+
diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c
new file mode 100644
-index 0000000..6d6286c
+index 0000000..30a1af8
--- /dev/null
+++ b/drivers/misc/kgdbts.c
@@ -0,0 +1,1090 @@
@@ -426881,7 +598962,7 @@
+static int final_ack;
+static int hw_break_val;
+static int hw_break_val2;
-+#if defined(CONFIG_ARM) || defined(CONFIG_MIPS)
++#if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_SPARC)
+static int arch_needs_sstep_emulation = 1;
+#else
+static int arch_needs_sstep_emulation;
@@ -427837,6 +599918,109 @@
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Wind River Systems, Inc.");
+
+diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
+index 7fa61e9..71d1c84 100644
+--- a/drivers/misc/phantom.c
++++ b/drivers/misc/phantom.c
+@@ -12,6 +12,7 @@
+ * or alternatively, you might use OpenHaptics provided by Sensable.
+ */
+
++#include <linux/compat.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/device.h>
+@@ -91,11 +92,8 @@ static long phantom_ioctl(struct file *file, unsigned int cmd,
+ unsigned long flags;
+ unsigned int i;
+
+- if (_IOC_TYPE(cmd) != PH_IOC_MAGIC ||
+- _IOC_NR(cmd) > PH_IOC_MAXNR)
+- return -ENOTTY;
+-
+ switch (cmd) {
++ case PHN_SETREG:
+ case PHN_SET_REG:
+ if (copy_from_user(&r, argp, sizeof(r)))
+ return -EFAULT;
+@@ -126,6 +124,7 @@ static long phantom_ioctl(struct file *file, unsigned int cmd,
+ phantom_status(dev, dev->status & ~PHB_RUNNING);
+ spin_unlock_irqrestore(&dev->regs_lock, flags);
+ break;
++ case PHN_SETREGS:
+ case PHN_SET_REGS:
+ if (copy_from_user(&rs, argp, sizeof(rs)))
+ return -EFAULT;
+@@ -143,6 +142,7 @@ static long phantom_ioctl(struct file *file, unsigned int cmd,
+ }
+ spin_unlock_irqrestore(&dev->regs_lock, flags);
+ break;
++ case PHN_GETREG:
+ case PHN_GET_REG:
+ if (copy_from_user(&r, argp, sizeof(r)))
+ return -EFAULT;
+@@ -155,6 +155,7 @@ static long phantom_ioctl(struct file *file, unsigned int cmd,
+ if (copy_to_user(argp, &r, sizeof(r)))
+ return -EFAULT;
+ break;
++ case PHN_GETREGS:
+ case PHN_GET_REGS: {
+ u32 m;
+
+@@ -168,6 +169,7 @@ static long phantom_ioctl(struct file *file, unsigned int cmd,
+ for (i = 0; i < m; i++)
+ if (rs.mask & BIT(i))
+ rs.values[i] = ioread32(dev->iaddr + i);
++ atomic_set(&dev->counter, 0);
+ spin_unlock_irqrestore(&dev->regs_lock, flags);
+
+ if (copy_to_user(argp, &rs, sizeof(rs)))
+@@ -191,6 +193,20 @@ static long phantom_ioctl(struct file *file, unsigned int cmd,
+ return 0;
+ }
+
++#ifdef CONFIG_COMPAT
++static long phantom_compat_ioctl(struct file *filp, unsigned int cmd,
++ unsigned long arg)
++{
++ if (_IOC_NR(cmd) <= 3 && _IOC_SIZE(cmd) == sizeof(compat_uptr_t)) {
++ cmd &= ~(_IOC_SIZEMASK << _IOC_SIZESHIFT);
++ cmd |= sizeof(void *) << _IOC_SIZESHIFT;
++ }
++ return phantom_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
++}
++#else
++#define phantom_compat_ioctl NULL
++#endif
++
+ static int phantom_open(struct inode *inode, struct file *file)
+ {
+ struct phantom_device *dev = container_of(inode->i_cdev,
+@@ -239,11 +255,12 @@ static unsigned int phantom_poll(struct file *file, poll_table *wait)
+
+ pr_debug("phantom_poll: %d\n", atomic_read(&dev->counter));
+ poll_wait(file, &dev->wait, wait);
+- if (atomic_read(&dev->counter)) {
++
++ if (!(dev->status & PHB_RUNNING))
++ mask = POLLERR;
++ else if (atomic_read(&dev->counter))
+ mask = POLLIN | POLLRDNORM;
+- atomic_dec(&dev->counter);
+- } else if ((dev->status & PHB_RUNNING) == 0)
+- mask = POLLIN | POLLRDNORM | POLLERR;
++
+ pr_debug("phantom_poll end: %x/%d\n", mask, atomic_read(&dev->counter));
+
+ return mask;
+@@ -253,6 +270,7 @@ static struct file_operations phantom_file_ops = {
+ .open = phantom_open,
+ .release = phantom_release,
+ .unlocked_ioctl = phantom_ioctl,
++ .compat_ioctl = phantom_compat_ioctl,
+ .poll = phantom_poll,
+ };
+
diff --git a/drivers/misc/sgi-xp/Makefile b/drivers/misc/sgi-xp/Makefile
new file mode 100644
index 0000000..b6e40a7
@@ -433422,7 +605606,7 @@
+ "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
+index 0000000..acd3fd4
--- /dev/null
+++ b/drivers/misc/sgi-xp/xpc_partition.c
@@ -0,0 +1,1174 @@
@@ -433639,7 +605823,7 @@
+ */
+ amos_page = xpc_vars->amos_page;
+ if (amos_page == NULL) {
-+ amos_page = (AMO_t *)TO_AMO(uncached_alloc_page(0));
++ amos_page = (AMO_t *)TO_AMO(uncached_alloc_page(0, 1));
+ if (amos_page == NULL) {
+ dev_err(xpc_part, "can't allocate page of AMOs\n");
+ return NULL;
@@ -433658,7 +605842,7 @@
+ dev_err(xpc_part, "can't change memory "
+ "protections\n");
+ uncached_free_page(__IA64_UNCACHED_OFFSET |
-+ TO_PHYS((u64)amos_page));
++ TO_PHYS((u64)amos_page), 1);
+ return NULL;
+ }
+ }
@@ -435275,14 +607459,1171 @@
+
+ unregister_netdev(xpnet_device);
+
-+ free_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/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
+index 02ff3d1..00e48e2 100644
+--- a/drivers/misc/sony-laptop.c
++++ b/drivers/misc/sony-laptop.c
+@@ -961,7 +961,7 @@ static int sony_nc_resume(struct acpi_device *device)
+ ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset,
+ item->value, NULL);
+ if (ret < 0) {
+- printk("%s: %d\n", __FUNCTION__, ret);
++ printk("%s: %d\n", __func__, ret);
+ break;
+ }
+ }
+@@ -1453,7 +1453,7 @@ static struct sonypi_eventtypes type4_events[] = {
+ udelay(1); \
+ if (!n) \
+ dprintk("command failed at %s : %s (line %d)\n", \
+- __FILE__, __FUNCTION__, __LINE__); \
++ __FILE__, __func__, __LINE__); \
+ }
+
+ static u8 sony_pic_call1(u8 dev)
+diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
+index 6cb7812..3f28f6e 100644
+--- a/drivers/misc/thinkpad_acpi.c
++++ b/drivers/misc/thinkpad_acpi.c
+@@ -21,7 +21,7 @@
+ * 02110-1301, USA.
+ */
+
+-#define TPACPI_VERSION "0.19"
++#define TPACPI_VERSION "0.20"
+ #define TPACPI_SYSFS_VERSION 0x020200
+
+ /*
+@@ -67,6 +67,7 @@
+ #include <linux/hwmon.h>
+ #include <linux/hwmon-sysfs.h>
+ #include <linux/input.h>
++#include <linux/leds.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/dmi.h>
+@@ -85,6 +86,8 @@
+ #define TP_CMOS_VOLUME_MUTE 2
+ #define TP_CMOS_BRIGHTNESS_UP 4
+ #define TP_CMOS_BRIGHTNESS_DOWN 5
++#define TP_CMOS_THINKLIGHT_ON 12
++#define TP_CMOS_THINKLIGHT_OFF 13
+
+ /* NVRAM Addresses */
+ enum tp_nvram_addr {
+@@ -133,8 +136,12 @@ enum {
+ #define TPACPI_PROC_DIR "ibm"
+ #define TPACPI_ACPI_EVENT_PREFIX "ibm"
+ #define TPACPI_DRVR_NAME TPACPI_FILE
++#define TPACPI_DRVR_SHORTNAME "tpacpi"
+ #define TPACPI_HWMON_DRVR_NAME TPACPI_NAME "_hwmon"
+
++#define TPACPI_NVRAM_KTHREAD_NAME "ktpacpi_nvramd"
++#define TPACPI_WORKQUEUE_NAME "ktpacpid"
++
+ #define TPACPI_MAX_ACPI_ARGS 3
+
+ /* Debugging */
+@@ -225,6 +232,7 @@ static struct {
+ u32 light:1;
+ u32 light_status:1;
+ u32 bright_16levels:1;
++ u32 bright_acpimode:1;
+ u32 wan:1;
+ u32 fan_ctrl_status_undef:1;
+ u32 input_device_registered:1;
+@@ -236,6 +244,11 @@ static struct {
+ u32 hotkey_poll_active:1;
+ } tp_features;
+
++static struct {
++ u16 hotkey_mask_ff:1;
++ u16 bright_cmos_ec_unsync:1;
++} tp_warned;
++
+ struct thinkpad_id_data {
+ unsigned int vendor; /* ThinkPad vendor:
+ * PCI_VENDOR_ID_IBM/PCI_VENDOR_ID_LENOVO */
+@@ -246,7 +259,8 @@ struct thinkpad_id_data {
+ u16 bios_model; /* Big Endian, TP-1Y = 0x5931, 0 = unknown */
+ u16 ec_model;
+
+- char *model_str;
++ char *model_str; /* ThinkPad T43 */
++ char *nummodel_str; /* 9384A9C for a 9384-A9C model */
+ };
+ static struct thinkpad_id_data thinkpad_id;
+
+@@ -259,6 +273,16 @@ static enum {
+ static int experimental;
+ static u32 dbg_level;
+
++static struct workqueue_struct *tpacpi_wq;
++
++/* Special LED class that can defer work */
++struct tpacpi_led_classdev {
++ struct led_classdev led_classdev;
++ struct work_struct work;
++ enum led_brightness new_brightness;
++ unsigned int led;
++};
++
+ /****************************************************************************
+ ****************************************************************************
+ *
+@@ -807,6 +831,80 @@ static int parse_strtoul(const char *buf,
+ return 0;
+ }
+
++static int __init tpacpi_query_bcl_levels(acpi_handle handle)
++{
++ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
++ union acpi_object *obj;
++ int rc;
++
++ if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) {
++ obj = (union acpi_object *)buffer.pointer;
++ if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
++ printk(TPACPI_ERR "Unknown _BCL data, "
++ "please report this to %s\n", TPACPI_MAIL);
++ rc = 0;
++ } else {
++ rc = obj->package.count;
++ }
++ } else {
++ return 0;
++ }
++
++ kfree(buffer.pointer);
++ return rc;
++}
++
++static acpi_status __init tpacpi_acpi_walk_find_bcl(acpi_handle handle,
++ u32 lvl, void *context, void **rv)
++{
++ char name[ACPI_PATH_SEGMENT_LENGTH];
++ struct acpi_buffer buffer = { sizeof(name), &name };
++
++ if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) &&
++ !strncmp("_BCL", name, sizeof(name) - 1)) {
++ BUG_ON(!rv || !*rv);
++ **(int **)rv = tpacpi_query_bcl_levels(handle);
++ return AE_CTRL_TERMINATE;
++ } else {
++ return AE_OK;
++ }
++}
++
++/*
++ * Returns 0 (no ACPI _BCL or _BCL invalid), or size of brightness map
++ */
++static int __init tpacpi_check_std_acpi_brightness_support(void)
++{
++ int status;
++ int bcl_levels = 0;
++ void *bcl_ptr = &bcl_levels;
++
++ if (!vid_handle) {
++ TPACPI_ACPIHANDLE_INIT(vid);
++ }
++ if (!vid_handle)
++ return 0;
++
++ /*
++ * Search for a _BCL method, and execute it. This is safe on all
++ * ThinkPads, and as a side-effect, _BCL will place a Lenovo Vista
++ * BIOS in ACPI backlight control mode. We do NOT have to care
++ * about calling the _BCL method in an enabled video device, any
++ * will do for our purposes.
++ */
++
++ status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3,
++ tpacpi_acpi_walk_find_bcl, NULL,
++ &bcl_ptr);
++
++ if (ACPI_SUCCESS(status) && bcl_levels > 2) {
++ tp_features.bright_acpimode = 1;
++ return (bcl_levels - 2);
++ }
++
++ return 0;
++}
++
+ /*************************************************************************
+ * thinkpad-acpi driver attributes
+ */
+@@ -909,12 +1007,14 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm)
+ thinkpad_id.ec_version_str : "unknown");
+
+ if (thinkpad_id.vendor && thinkpad_id.model_str)
+- printk(TPACPI_INFO "%s %s\n",
++ printk(TPACPI_INFO "%s %s, model %s\n",
+ (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ?
+ "IBM" : ((thinkpad_id.vendor ==
+ PCI_VENDOR_ID_LENOVO) ?
+ "Lenovo" : "Unknown vendor"),
+- thinkpad_id.model_str);
++ thinkpad_id.model_str,
++ (thinkpad_id.nummodel_str) ?
++ thinkpad_id.nummodel_str : "unknown");
+
+ return 0;
+ }
+@@ -1107,6 +1207,19 @@ static int hotkey_mask_set(u32 mask)
+ int rc = 0;
+
+ if (tp_features.hotkey_mask) {
++ if (!tp_warned.hotkey_mask_ff &&
++ (mask == 0xffff || mask == 0xffffff ||
++ mask == 0xffffffff)) {
++ tp_warned.hotkey_mask_ff = 1;
++ printk(TPACPI_NOTICE
++ "setting the hotkey mask to 0x%08x is likely "
++ "not the best way to go about it\n", mask);
++ printk(TPACPI_NOTICE
++ "please consider using the driver defaults, "
++ "and refer to up-to-date thinkpad-acpi "
++ "documentation\n");
++ }
++
+ HOTKEY_CONFIG_CRITICAL_START
+ for (i = 0; i < 32; i++) {
+ u32 m = 1 << i;
+@@ -1427,8 +1540,7 @@ static void hotkey_poll_setup(int may_warn)
+ (tpacpi_inputdev->users > 0 || hotkey_report_mode < 2)) {
+ if (!tpacpi_hotkey_task) {
+ tpacpi_hotkey_task = kthread_run(hotkey_kthread,
+- NULL,
+- TPACPI_FILE "d");
++ NULL, TPACPI_NVRAM_KTHREAD_NAME);
+ if (IS_ERR(tpacpi_hotkey_task)) {
+ tpacpi_hotkey_task = NULL;
+ printk(TPACPI_ERR
+@@ -1887,6 +1999,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
+ KEY_UNKNOWN, /* 0x0D: FN+INSERT */
+ KEY_UNKNOWN, /* 0x0E: FN+DELETE */
+
++ /* These either have to go through ACPI video, or
++ * act like in the IBM ThinkPads, so don't ever
++ * enable them by default */
+ KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */
+ KEY_RESERVED, /* 0x10: FN+END (brightness down) */
+
+@@ -2091,6 +2206,32 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
+ set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit);
+ }
+
++ /* Do not issue duplicate brightness change events to
++ * userspace */
++ if (!tp_features.bright_acpimode)
++ /* update bright_acpimode... */
++ tpacpi_check_std_acpi_brightness_support();
++
++ if (tp_features.bright_acpimode) {
++ printk(TPACPI_INFO
++ "This ThinkPad has standard ACPI backlight "
++ "brightness control, supported by the ACPI "
++ "video driver\n");
++ printk(TPACPI_NOTICE
++ "Disabling thinkpad-acpi brightness events "
++ "by default...\n");
++
++ /* The hotkey_reserved_mask change below is not
++ * necessary while the keys are at KEY_RESERVED in the
++ * default map, but better safe than sorry, leave it
++ * here as a marker of what we have to do, especially
++ * when we finally become able to set this at runtime
++ * on response to X.org requests */
++ hotkey_reserved_mask |=
++ (1 << TP_ACPI_HOTKEYSCAN_FNHOME)
++ | (1 << TP_ACPI_HOTKEYSCAN_FNEND);
++ }
++
+ dbg_printk(TPACPI_DBG_INIT,
+ "enabling hot key handling\n");
+ res = hotkey_status_set(1);
+@@ -3110,13 +3251,82 @@ static struct ibm_struct video_driver_data = {
+ TPACPI_HANDLE(lght, root, "\\LGHT"); /* A21e, A2xm/p, T20-22, X20-21 */
+ TPACPI_HANDLE(ledb, ec, "LEDB"); /* G4x */
+
++static int light_get_status(void)
++{
++ int status = 0;
++
++ if (tp_features.light_status) {
++ if (!acpi_evalf(ec_handle, &status, "KBLT", "d"))
++ return -EIO;
++ return (!!status);
++ }
++
++ return -ENXIO;
++}
++
++static int light_set_status(int status)
++{
++ int rc;
++
++ if (tp_features.light) {
++ if (cmos_handle) {
++ rc = acpi_evalf(cmos_handle, NULL, NULL, "vd",
++ (status)?
++ TP_CMOS_THINKLIGHT_ON :
++ TP_CMOS_THINKLIGHT_OFF);
++ } else {
++ rc = acpi_evalf(lght_handle, NULL, NULL, "vd",
++ (status)? 1 : 0);
++ }
++ return (rc)? 0 : -EIO;
++ }
++
++ return -ENXIO;
++}
++
++static void light_set_status_worker(struct work_struct *work)
++{
++ struct tpacpi_led_classdev *data =
++ container_of(work, struct tpacpi_led_classdev, work);
++
++ if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING))
++ light_set_status((data->new_brightness != LED_OFF));
++}
++
++static void light_sysfs_set(struct led_classdev *led_cdev,
++ enum led_brightness brightness)
++{
++ struct tpacpi_led_classdev *data =
++ container_of(led_cdev,
++ struct tpacpi_led_classdev,
++ led_classdev);
++ data->new_brightness = brightness;
++ queue_work(tpacpi_wq, &data->work);
++}
++
++static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev)
++{
++ return (light_get_status() == 1)? LED_FULL : LED_OFF;
++}
++
++static struct tpacpi_led_classdev tpacpi_led_thinklight = {
++ .led_classdev = {
++ .name = "tpacpi::thinklight",
++ .brightness_set = &light_sysfs_set,
++ .brightness_get = &light_sysfs_get,
++ }
++};
++
+ static int __init light_init(struct ibm_init_struct *iibm)
+ {
++ int rc = 0;
++
+ vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n");
+
+ TPACPI_ACPIHANDLE_INIT(ledb);
+ TPACPI_ACPIHANDLE_INIT(lght);
+ TPACPI_ACPIHANDLE_INIT(cmos);
++ INIT_WORK(&tpacpi_led_thinklight.work, light_set_status_worker);
+
+ /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */
+ tp_features.light = (cmos_handle || lght_handle) && !ledb_handle;
+@@ -3130,13 +3340,31 @@ static int __init light_init(struct ibm_init_struct *iibm)
+ vdbg_printk(TPACPI_DBG_INIT, "light is %s\n",
+ str_supported(tp_features.light));
+
+- return (tp_features.light)? 0 : 1;
++ if (tp_features.light) {
++ rc = led_classdev_register(&tpacpi_pdev->dev,
++ &tpacpi_led_thinklight.led_classdev);
++ }
++
++ if (rc < 0) {
++ tp_features.light = 0;
++ tp_features.light_status = 0;
++ } else {
++ rc = (tp_features.light)? 0 : 1;
++ }
++ return rc;
++}
++
++static void light_exit(void)
++{
++ led_classdev_unregister(&tpacpi_led_thinklight.led_classdev);
++ if (work_pending(&tpacpi_led_thinklight.work))
++ flush_workqueue(tpacpi_wq);
+ }
+
+ static int light_read(char *p)
+ {
+ int len = 0;
+- int status = 0;
++ int status;
+
+ if (!tp_features.light) {
+ len += sprintf(p + len, "status:\t\tnot supported\n");
+@@ -3144,8 +3372,9 @@ static int light_read(char *p)
+ len += sprintf(p + len, "status:\t\tunknown\n");
+ len += sprintf(p + len, "commands:\ton, off\n");
+ } else {
+- if (!acpi_evalf(ec_handle, &status, "KBLT", "d"))
+- return -EIO;
++ status = light_get_status();
++ if (status < 0)
++ return status;
+ len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0));
+ len += sprintf(p + len, "commands:\ton, off\n");
+ }
+@@ -3155,37 +3384,29 @@ static int light_read(char *p)
+
+ static int light_write(char *buf)
+ {
+- int cmos_cmd, lght_cmd;
+ char *cmd;
+- int success;
++ int newstatus = 0;
+
+ if (!tp_features.light)
+ return -ENODEV;
+
+ while ((cmd = next_cmd(&buf))) {
+ if (strlencmp(cmd, "on") == 0) {
+- cmos_cmd = 0x0c;
+- lght_cmd = 1;
++ newstatus = 1;
+ } else if (strlencmp(cmd, "off") == 0) {
+- cmos_cmd = 0x0d;
+- lght_cmd = 0;
++ newstatus = 0;
+ } else
+ return -EINVAL;
+-
+- success = cmos_handle ?
+- acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd) :
+- acpi_evalf(lght_handle, NULL, NULL, "vd", lght_cmd);
+- if (!success)
+- return -EIO;
+ }
+
+- return 0;
++ return light_set_status(newstatus);
+ }
+
+ static struct ibm_struct light_driver_data = {
+ .name = "light",
+ .read = light_read,
+ .write = light_write,
++ .exit = light_exit,
+ };
+
+ /*************************************************************************
+@@ -3583,6 +3804,12 @@ enum { /* For TPACPI_LED_OLD */
+ TPACPI_LED_EC_HLMS = 0x0e, /* EC reg to select led to command */
+ };
+
++enum led_status_t {
++ TPACPI_LED_OFF = 0,
++ TPACPI_LED_ON,
++ TPACPI_LED_BLINK,
++};
++
+ static enum led_access_mode led_supported;
+
+ TPACPI_HANDLE(led, ec, "SLED", /* 570 */
+@@ -3591,8 +3818,174 @@ TPACPI_HANDLE(led, ec, "SLED", /* 570 */
+ "LED", /* all others */
+ ); /* R30, R31 */
+
++#define TPACPI_LED_NUMLEDS 8
++static struct tpacpi_led_classdev *tpacpi_leds;
++static enum led_status_t tpacpi_led_state_cache[TPACPI_LED_NUMLEDS];
++static const char const *tpacpi_led_names[TPACPI_LED_NUMLEDS] = {
++ /* there's a limit of 19 chars + NULL before 2.6.26 */
++ "tpacpi::power",
++ "tpacpi:orange:batt",
++ "tpacpi:green:batt",
++ "tpacpi::dock_active",
++ "tpacpi::bay_active",
++ "tpacpi::dock_batt",
++ "tpacpi::unknown_led",
++ "tpacpi::standby",
++};
++
++static int led_get_status(unsigned int led)
++{
++ int status;
++ enum led_status_t led_s;
++
++ switch (led_supported) {
++ case TPACPI_LED_570:
++ if (!acpi_evalf(ec_handle,
++ &status, "GLED", "dd", 1 << led))
++ return -EIO;
++ led_s = (status == 0)?
++ TPACPI_LED_OFF :
++ ((status == 1)?
++ TPACPI_LED_ON :
++ TPACPI_LED_BLINK);
++ tpacpi_led_state_cache[led] = led_s;
++ return led_s;
++ default:
++ return -ENXIO;
++ }
++
++ /* not reached */
++}
++
++static int led_set_status(unsigned int led, enum led_status_t ledstatus)
++{
++ /* off, on, blink. Index is led_status_t */
++ static const int const led_sled_arg1[] = { 0, 1, 3 };
++ static const int const led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */
++ static const int const led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */
++ static const int const led_led_arg1[] = { 0, 0x80, 0xc0 };
++
++ int rc = 0;
++
++ switch (led_supported) {
++ case TPACPI_LED_570:
++ /* 570 */
++ led = 1 << led;
++ if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
++ led, led_sled_arg1[ledstatus]))
++ rc = -EIO;
++ break;
++ case TPACPI_LED_OLD:
++ /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
++ led = 1 << led;
++ rc = ec_write(TPACPI_LED_EC_HLMS, led);
++ if (rc >= 0)
++ rc = ec_write(TPACPI_LED_EC_HLBL,
++ led * led_exp_hlbl[ledstatus]);
++ if (rc >= 0)
++ rc = ec_write(TPACPI_LED_EC_HLCL,
++ led * led_exp_hlcl[ledstatus]);
++ break;
++ case TPACPI_LED_NEW:
++ /* all others */
++ if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
++ led, led_led_arg1[ledstatus]))
++ rc = -EIO;
++ break;
++ default:
++ rc = -ENXIO;
++ }
++
++ if (!rc)
++ tpacpi_led_state_cache[led] = ledstatus;
++
++ return rc;
++}
++
++static void led_sysfs_set_status(unsigned int led,
++ enum led_brightness brightness)
++{
++ led_set_status(led,
++ (brightness == LED_OFF) ?
++ TPACPI_LED_OFF :
++ (tpacpi_led_state_cache[led] == TPACPI_LED_BLINK) ?
++ TPACPI_LED_BLINK : TPACPI_LED_ON);
++}
++
++static void led_set_status_worker(struct work_struct *work)
++{
++ struct tpacpi_led_classdev *data =
++ container_of(work, struct tpacpi_led_classdev, work);
++
++ if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING))
++ led_sysfs_set_status(data->led, data->new_brightness);
++}
++
++static void led_sysfs_set(struct led_classdev *led_cdev,
++ enum led_brightness brightness)
++{
++ struct tpacpi_led_classdev *data = container_of(led_cdev,
++ struct tpacpi_led_classdev, led_classdev);
++
++ data->new_brightness = brightness;
++ queue_work(tpacpi_wq, &data->work);
++}
++
++static int led_sysfs_blink_set(struct led_classdev *led_cdev,
++ unsigned long *delay_on, unsigned long *delay_off)
++{
++ struct tpacpi_led_classdev *data = container_of(led_cdev,
++ struct tpacpi_led_classdev, led_classdev);
++
++ /* Can we choose the flash rate? */
++ if (*delay_on == 0 && *delay_off == 0) {
++ /* yes. set them to the hardware blink rate (1 Hz) */
++ *delay_on = 500; /* ms */
++ *delay_off = 500; /* ms */
++ } else if ((*delay_on != 500) || (*delay_off != 500))
++ return -EINVAL;
++
++ data->new_brightness = TPACPI_LED_BLINK;
++ queue_work(tpacpi_wq, &data->work);
++
++ return 0;
++}
++
++static enum led_brightness led_sysfs_get(struct led_classdev *led_cdev)
++{
++ int rc;
++
++ struct tpacpi_led_classdev *data = container_of(led_cdev,
++ struct tpacpi_led_classdev, led_classdev);
++
++ rc = led_get_status(data->led);
++
++ if (rc == TPACPI_LED_OFF || rc < 0)
++ rc = LED_OFF; /* no error handling in led class :( */
++ else
++ rc = LED_FULL;
++
++ return rc;
++}
++
++static void led_exit(void)
++{
++ unsigned int i;
++
++ for (i = 0; i < TPACPI_LED_NUMLEDS; i++) {
++ if (tpacpi_leds[i].led_classdev.name)
++ led_classdev_unregister(&tpacpi_leds[i].led_classdev);
++ }
++
++ kfree(tpacpi_leds);
++ tpacpi_leds = NULL;
++}
++
+ static int __init led_init(struct ibm_init_struct *iibm)
+ {
++ unsigned int i;
++ int rc;
++
+ vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n");
+
+ TPACPI_ACPIHANDLE_INIT(led);
+@@ -3613,10 +4006,41 @@ static int __init led_init(struct ibm_init_struct *iibm)
+ vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n",
+ str_supported(led_supported), led_supported);
+
++ tpacpi_leds = kzalloc(sizeof(*tpacpi_leds) * TPACPI_LED_NUMLEDS,
++ GFP_KERNEL);
++ if (!tpacpi_leds) {
++ printk(TPACPI_ERR "Out of memory for LED data\n");
++ return -ENOMEM;
++ }
++
++ for (i = 0; i < TPACPI_LED_NUMLEDS; i++) {
++ tpacpi_leds[i].led = i;
++
++ tpacpi_leds[i].led_classdev.brightness_set = &led_sysfs_set;
++ tpacpi_leds[i].led_classdev.blink_set = &led_sysfs_blink_set;
++ if (led_supported == TPACPI_LED_570)
++ tpacpi_leds[i].led_classdev.brightness_get =
++ &led_sysfs_get;
++
++ tpacpi_leds[i].led_classdev.name = tpacpi_led_names[i];
++
++ INIT_WORK(&tpacpi_leds[i].work, led_set_status_worker);
++
++ rc = led_classdev_register(&tpacpi_pdev->dev,
++ &tpacpi_leds[i].led_classdev);
++ if (rc < 0) {
++ tpacpi_leds[i].led_classdev.name = NULL;
++ led_exit();
++ return rc;
++ }
++ }
++
+ return (led_supported != TPACPI_LED_NONE)? 0 : 1;
+ }
+
+-#define led_status(s) ((s) == 0 ? "off" : ((s) == 1 ? "on" : "blinking"))
++#define str_led_status(s) \
++ ((s) == TPACPI_LED_OFF ? "off" : \
++ ((s) == TPACPI_LED_ON ? "on" : "blinking"))
+
+ static int led_read(char *p)
+ {
+@@ -3632,11 +4056,11 @@ static int led_read(char *p)
+ /* 570 */
+ int i, status;
+ for (i = 0; i < 8; i++) {
+- if (!acpi_evalf(ec_handle,
+- &status, "GLED", "dd", 1 << i))
++ status = led_get_status(i);
++ if (status < 0)
+ return -EIO;
+ len += sprintf(p + len, "%d:\t\t%s\n",
+- i, led_status(status));
++ i, str_led_status(status));
+ }
+ }
+
+@@ -3646,16 +4070,11 @@ static int led_read(char *p)
+ return len;
+ }
+
+-/* off, on, blink */
+-static const int led_sled_arg1[] = { 0, 1, 3 };
+-static const int led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */
+-static const int led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */
+-static const int led_led_arg1[] = { 0, 0x80, 0xc0 };
+-
+ static int led_write(char *buf)
+ {
+ char *cmd;
+- int led, ind, ret;
++ int led, rc;
++ enum led_status_t s;
+
+ if (!led_supported)
+ return -ENODEV;
+@@ -3665,38 +4084,18 @@ static int led_write(char *buf)
+ return -EINVAL;
+
+ if (strstr(cmd, "off")) {
+- ind = 0;
++ s = TPACPI_LED_OFF;
+ } else if (strstr(cmd, "on")) {
+- ind = 1;
++ s = TPACPI_LED_ON;
+ } else if (strstr(cmd, "blink")) {
+- ind = 2;
+- } else
+- return -EINVAL;
+-
+- if (led_supported == TPACPI_LED_570) {
+- /* 570 */
+- led = 1 << led;
+- if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
+- led, led_sled_arg1[ind]))
+- return -EIO;
+- } else if (led_supported == TPACPI_LED_OLD) {
+- /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
+- led = 1 << led;
+- ret = ec_write(TPACPI_LED_EC_HLMS, led);
+- if (ret >= 0)
+- ret = ec_write(TPACPI_LED_EC_HLBL,
+- led * led_exp_hlbl[ind]);
+- if (ret >= 0)
+- ret = ec_write(TPACPI_LED_EC_HLCL,
+- led * led_exp_hlcl[ind]);
+- if (ret < 0)
+- return ret;
++ s = TPACPI_LED_BLINK;
+ } else {
+- /* all others */
+- if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
+- led, led_led_arg1[ind]))
+- return -EIO;
++ return -EINVAL;
+ }
++
++ rc = led_set_status(led, s);
++ if (rc < 0)
++ return rc;
+ }
+
+ return 0;
+@@ -3706,6 +4105,7 @@ static struct ibm_struct led_driver_data = {
+ .name = "led",
+ .read = led_read,
+ .write = led_write,
++ .exit = led_exit,
+ };
+
+ /*************************************************************************
+@@ -4170,8 +4570,16 @@ static struct ibm_struct ecdump_driver_data = {
+
+ #define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen"
+
++enum {
++ TP_EC_BACKLIGHT = 0x31,
++
++ /* TP_EC_BACKLIGHT bitmasks */
++ TP_EC_BACKLIGHT_LVLMSK = 0x1F,
++ TP_EC_BACKLIGHT_CMDMSK = 0xE0,
++ TP_EC_BACKLIGHT_MAPSW = 0x20,
++};
++
+ static struct backlight_device *ibm_backlight_device;
+-static int brightness_offset = 0x31;
+ static int brightness_mode;
+ static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */
+
+@@ -4180,16 +4588,24 @@ static struct mutex brightness_mutex;
+ /*
+ * ThinkPads can read brightness from two places: EC 0x31, or
+ * CMOS NVRAM byte 0x5E, bits 0-3.
++ *
++ * EC 0x31 has the following layout
++ * Bit 7: unknown function
++ * Bit 6: unknown function
++ * Bit 5: Z: honour scale changes, NZ: ignore scale changes
++ * Bit 4: must be set to zero to avoid problems
++ * Bit 3-0: backlight brightness level
++ *
++ * brightness_get_raw returns status data in the EC 0x31 layout
+ */
+-static int brightness_get(struct backlight_device *bd)
++static int brightness_get_raw(int *status)
+ {
+ u8 lec = 0, lcmos = 0, level = 0;
+
+ if (brightness_mode & 1) {
+- if (!acpi_ec_read(brightness_offset, &lec))
++ if (!acpi_ec_read(TP_EC_BACKLIGHT, &lec))
+ return -EIO;
+- lec &= (tp_features.bright_16levels)? 0x0f : 0x07;
+- level = lec;
++ level = lec & TP_EC_BACKLIGHT_LVLMSK;
+ };
+ if (brightness_mode & 2) {
+ lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS)
+@@ -4199,16 +4615,27 @@ static int brightness_get(struct backlight_device *bd)
+ level = lcmos;
+ }
+
+- if (brightness_mode == 3 && lec != lcmos) {
+- printk(TPACPI_ERR
+- "CMOS NVRAM (%u) and EC (%u) do not agree "
+- "on display brightness level\n",
+- (unsigned int) lcmos,
+- (unsigned int) lec);
+- return -EIO;
++ if (brightness_mode == 3) {
++ *status = lec; /* Prefer EC, CMOS is just a backing store */
++ lec &= TP_EC_BACKLIGHT_LVLMSK;
++ if (lec == lcmos)
++ tp_warned.bright_cmos_ec_unsync = 0;
++ else {
++ if (!tp_warned.bright_cmos_ec_unsync) {
++ printk(TPACPI_ERR
++ "CMOS NVRAM (%u) and EC (%u) do not "
++ "agree on display brightness level\n",
++ (unsigned int) lcmos,
++ (unsigned int) lec);
++ tp_warned.bright_cmos_ec_unsync = 1;
++ }
++ return -EIO;
++ }
++ } else {
++ *status = level;
+ }
+
+- return level;
++ return 0;
+ }
+
+ /* May return EINTR which can always be mapped to ERESTARTSYS */
+@@ -4216,19 +4643,22 @@ static int brightness_set(int value)
+ {
+ int cmos_cmd, inc, i, res;
+ int current_value;
++ int command_bits;
+
+- if (value > ((tp_features.bright_16levels)? 15 : 7))
++ if (value > ((tp_features.bright_16levels)? 15 : 7) ||
++ value < 0)
+ return -EINVAL;
+
+ res = mutex_lock_interruptible(&brightness_mutex);
+ if (res < 0)
+ return res;
+
+- current_value = brightness_get(NULL);
+- if (current_value < 0) {
+- res = current_value;
++ res = brightness_get_raw(¤t_value);
++ if (res < 0)
+ goto errout;
+- }
++
++ command_bits = current_value & TP_EC_BACKLIGHT_CMDMSK;
++ current_value &= TP_EC_BACKLIGHT_LVLMSK;
+
+ cmos_cmd = value > current_value ?
+ TP_CMOS_BRIGHTNESS_UP :
+@@ -4243,7 +4673,8 @@ static int brightness_set(int value)
+ goto errout;
+ }
+ if ((brightness_mode & 1) &&
+- !acpi_ec_write(brightness_offset, i + inc)) {
++ !acpi_ec_write(TP_EC_BACKLIGHT,
++ (i + inc) | command_bits)) {
+ res = -EIO;
+ goto errout;;
+ }
+@@ -4266,106 +4697,23 @@ static int brightness_update_status(struct backlight_device *bd)
+ bd->props.brightness : 0);
+ }
+
+-static struct backlight_ops ibm_backlight_data = {
+- .get_brightness = brightness_get,
+- .update_status = brightness_update_status,
+-};
+-
+-/* --------------------------------------------------------------------- */
+-
+-static int __init tpacpi_query_bcll_levels(acpi_handle handle)
+-{
+- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+- union acpi_object *obj;
+- int rc;
+-
+- if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) {
+- obj = (union acpi_object *)buffer.pointer;
+- if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
+- printk(TPACPI_ERR "Unknown BCLL data, "
+- "please report this to %s\n", TPACPI_MAIL);
+- rc = 0;
+- } else {
+- rc = obj->package.count;
+- }
+- } else {
+- return 0;
+- }
+-
+- kfree(buffer.pointer);
+- return rc;
+-}
+-
+-static acpi_status __init brightness_find_bcll(acpi_handle handle, u32 lvl,
+- void *context, void **rv)
+-{
+- char name[ACPI_PATH_SEGMENT_LENGTH];
+- struct acpi_buffer buffer = { sizeof(name), &name };
+-
+- if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) &&
+- !strncmp("BCLL", name, sizeof(name) - 1)) {
+- if (tpacpi_query_bcll_levels(handle) == 16) {
+- *rv = handle;
+- return AE_CTRL_TERMINATE;
+- } else {
+- return AE_OK;
+- }
+- } else {
+- return AE_OK;
+- }
+-}
+-
+-static int __init brightness_check_levels(void)
++static int brightness_get(struct backlight_device *bd)
+ {
+- int status;
+- void *found_node = NULL;
++ int status, res;
+
+- if (!vid_handle) {
+- TPACPI_ACPIHANDLE_INIT(vid);
+- }
+- if (!vid_handle)
+- return 0;
+-
+- /* Search for a BCLL package with 16 levels */
+- status = acpi_walk_namespace(ACPI_TYPE_PACKAGE, vid_handle, 3,
+- brightness_find_bcll, NULL,
+- &found_node);
+-
+- return (ACPI_SUCCESS(status) && found_node != NULL);
+-}
+-
+-static acpi_status __init brightness_find_bcl(acpi_handle handle, u32 lvl,
+- void *context, void **rv)
+-{
+- char name[ACPI_PATH_SEGMENT_LENGTH];
+- struct acpi_buffer buffer = { sizeof(name), &name };
++ res = brightness_get_raw(&status);
++ if (res < 0)
++ return 0; /* FIXME: teach backlight about error handling */
+
+- if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) &&
+- !strncmp("_BCL", name, sizeof(name) - 1)) {
+- *rv = handle;
+- return AE_CTRL_TERMINATE;
+- } else {
+- return AE_OK;
+- }
++ return status & TP_EC_BACKLIGHT_LVLMSK;
+ }
+
+-static int __init brightness_check_std_acpi_support(void)
+-{
+- int status;
+- void *found_node = NULL;
+-
+- if (!vid_handle) {
+- TPACPI_ACPIHANDLE_INIT(vid);
+- }
+- if (!vid_handle)
+- return 0;
+-
+- /* Search for a _BCL method, but don't execute it */
+- status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3,
+- brightness_find_bcl, NULL, &found_node);
++static struct backlight_ops ibm_backlight_data = {
++ .get_brightness = brightness_get,
++ .update_status = brightness_update_status,
++};
+
+- return (ACPI_SUCCESS(status) && found_node != NULL);
+-}
++/* --------------------------------------------------------------------- */
+
+ static int __init brightness_init(struct ibm_init_struct *iibm)
+ {
+@@ -4375,13 +4723,19 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
+
+ mutex_init(&brightness_mutex);
+
+- if (!brightness_enable) {
+- dbg_printk(TPACPI_DBG_INIT,
+- "brightness support disabled by "
+- "module parameter\n");
+- return 1;
+- } else if (brightness_enable > 1) {
+- if (brightness_check_std_acpi_support()) {
++ /*
++ * We always attempt to detect acpi support, so as to switch
++ * Lenovo Vista BIOS to ACPI brightness mode even if we are not
++ * going to publish a backlight interface
++ */
++ b = tpacpi_check_std_acpi_brightness_support();
++ if (b > 0) {
++ if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) {
++ printk(TPACPI_NOTICE
++ "Lenovo BIOS switched to ACPI backlight "
++ "control mode\n");
++ }
++ if (brightness_enable > 1) {
+ printk(TPACPI_NOTICE
+ "standard ACPI backlight interface "
+ "available, not loading native one...\n");
+@@ -4389,6 +4743,22 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
+ }
+ }
+
++ if (!brightness_enable) {
++ dbg_printk(TPACPI_DBG_INIT,
++ "brightness support disabled by "
++ "module parameter\n");
++ return 1;
++ }
++
++ if (b > 16) {
++ printk(TPACPI_ERR
++ "Unsupported brightness interface, "
++ "please contact %s\n", TPACPI_MAIL);
++ return 1;
++ }
++ if (b == 16)
++ tp_features.bright_16levels = 1;
++
+ if (!brightness_mode) {
+ if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO)
+ brightness_mode = 2;
+@@ -4402,12 +4772,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
+ if (brightness_mode > 3)
+ return -EINVAL;
+
+- tp_features.bright_16levels =
+- thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO &&
+- brightness_check_levels();
+-
+- b = brightness_get(NULL);
+- if (b < 0)
++ if (brightness_get_raw(&b) < 0)
+ return 1;
+
+ if (tp_features.bright_16levels)
+@@ -4425,7 +4790,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
+
+ ibm_backlight_device->props.max_brightness =
+ (tp_features.bright_16levels)? 15 : 7;
+- ibm_backlight_device->props.brightness = b;
++ ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
+ backlight_update_status(ibm_backlight_device);
+
+ return 0;
+@@ -5046,11 +5411,11 @@ static void fan_watchdog_reset(void)
+ if (fan_watchdog_maxinterval > 0 &&
+ tpacpi_lifecycle != TPACPI_LIFE_EXITING) {
+ fan_watchdog_active = 1;
+- if (!schedule_delayed_work(&fan_watchdog_task,
++ if (!queue_delayed_work(tpacpi_wq, &fan_watchdog_task,
+ msecs_to_jiffies(fan_watchdog_maxinterval
+ * 1000))) {
+ printk(TPACPI_ERR
+- "failed to schedule the fan watchdog, "
++ "failed to queue the fan watchdog, "
+ "watchdog will not trigger\n");
+ }
+ } else
+@@ -5420,7 +5785,7 @@ static void fan_exit(void)
+ &driver_attr_fan_watchdog);
+
+ cancel_delayed_work(&fan_watchdog_task);
+- flush_scheduled_work();
++ flush_workqueue(tpacpi_wq);
+ }
+
+ static int fan_read(char *p)
+@@ -5826,10 +6191,13 @@ static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp)
+
+ tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION),
+ GFP_KERNEL);
+- if (strnicmp(tp->model_str, "ThinkPad", 8) != 0) {
++ if (tp->model_str && strnicmp(tp->model_str, "ThinkPad", 8) != 0) {
+ kfree(tp->model_str);
+ tp->model_str = NULL;
+ }
++
++ tp->nummodel_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_NAME),
++ GFP_KERNEL);
+ }
+
+ static int __init probe_for_thinkpad(void)
+@@ -6071,6 +6439,9 @@ static void thinkpad_acpi_module_exit(void)
+ if (proc_dir)
+ remove_proc_entry(TPACPI_PROC_DIR, acpi_root_dir);
+
++ if (tpacpi_wq)
++ destroy_workqueue(tpacpi_wq);
++
+ kfree(thinkpad_id.bios_version_str);
+ kfree(thinkpad_id.ec_version_str);
+ kfree(thinkpad_id.model_str);
+@@ -6101,6 +6472,12 @@ static int __init thinkpad_acpi_module_init(void)
+ TPACPI_ACPIHANDLE_INIT(ecrd);
+ TPACPI_ACPIHANDLE_INIT(ecwr);
+
++ tpacpi_wq = create_singlethread_workqueue(TPACPI_WORKQUEUE_NAME);
++ if (!tpacpi_wq) {
++ thinkpad_acpi_module_exit();
++ return -ENOMEM;
++ }
+
-+module_exit(xpnet_exit);
+ proc_dir = proc_mkdir(TPACPI_PROC_DIR, acpi_root_dir);
+ if (!proc_dir) {
+ printk(TPACPI_ERR
+@@ -6223,6 +6600,8 @@ static int __init thinkpad_acpi_module_init(void)
+ /* Please remove this in year 2009 */
+ MODULE_ALIAS("ibm_acpi");
+
++MODULE_ALIAS(TPACPI_DRVR_SHORTNAME);
+
-+MODULE_AUTHOR("Silicon Graphics, Inc.");
-+MODULE_DESCRIPTION("Cross Partition Network adapter (XPNET)");
-+MODULE_LICENSE("GPL");
+ /*
+ * DMI matching for module autoloading
+ *
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index b966674..01ced4c 100644
--- a/drivers/mmc/core/core.c
@@ -435444,6 +608785,43 @@
int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
{
+diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
+index 365024b..3550858 100644
+--- a/drivers/mmc/host/mmc_spi.c
++++ b/drivers/mmc/host/mmc_spi.c
+@@ -340,7 +340,7 @@ checkstatus:
+
+ /* SPI R3, R4, or R7 == R1 + 4 bytes */
+ case MMC_RSP_SPI_R3:
+- cmd->resp[1] = be32_to_cpu(get_unaligned((u32 *)cp));
++ cmd->resp[1] = get_unaligned_be32(cp);
+ break;
+
+ /* SPI R1 == just one status byte */
+diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
+index 95244a7..626ac08 100644
+--- a/drivers/mmc/host/mmci.c
++++ b/drivers/mmc/host/mmci.c
+@@ -213,9 +213,10 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema
+ void __iomem *base = host->base;
+ char *ptr = buffer;
+ u32 status;
++ int host_remain = host->size;
+
+ do {
+- int count = host->size - (readl(base + MMCIFIFOCNT) << 2);
++ int count = host_remain - (readl(base + MMCIFIFOCNT) << 2);
+
+ if (count > remain)
+ count = remain;
+@@ -227,6 +228,7 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema
+
+ ptr += count;
+ remain -= count;
++ host_remain -= count;
+
+ if (remain == 0)
+ break;
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 90c358b..14759e9 100644
--- a/drivers/mmc/host/omap.c
@@ -438481,7 +611859,7 @@
+#endif
+
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
-index 894c0b2..f0b10ca 100644
+index 894c0b2..3eb2643 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -47,6 +47,7 @@ struct platram_info {
@@ -438520,7 +611898,7 @@
+ /* probe for the right mtd map driver
+ * supplied by the platform_data struct */
+
-+ if (pdata->map_probes != 0) {
++ if (pdata->map_probes) {
+ const char **map_probes = pdata->map_probes;
+
+ for ( ; !info->mtd && *map_probes; map_probes++)
@@ -442448,8 +615826,124 @@
/* Lowest number PEBs reserved for bad PEB handling */
#define MIN_RESEVED_PEBS 2
+diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c
+index 9c65734..fdfb2b2 100644
+--- a/drivers/net/3c505.c
++++ b/drivers/net/3c505.c
+@@ -670,7 +670,7 @@ static irqreturn_t elp_interrupt(int irq, void *dev_id)
+ memcpy(adapter->current_dma.target, adapter->dma_buffer, adapter->current_dma.length);
+ }
+ skb->protocol = eth_type_trans(skb,dev);
+- adapter->stats.rx_bytes += skb->len;
++ dev->stats.rx_bytes += skb->len;
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+ }
+@@ -773,12 +773,12 @@ static irqreturn_t elp_interrupt(int irq, void *dev_id)
+ * received board statistics
+ */
+ case CMD_NETWORK_STATISTICS_RESPONSE:
+- adapter->stats.rx_packets += adapter->irx_pcb.data.netstat.tot_recv;
+- adapter->stats.tx_packets += adapter->irx_pcb.data.netstat.tot_xmit;
+- adapter->stats.rx_crc_errors += adapter->irx_pcb.data.netstat.err_CRC;
+- adapter->stats.rx_frame_errors += adapter->irx_pcb.data.netstat.err_align;
+- adapter->stats.rx_fifo_errors += adapter->irx_pcb.data.netstat.err_ovrrun;
+- adapter->stats.rx_over_errors += adapter->irx_pcb.data.netstat.err_res;
++ dev->stats.rx_packets += adapter->irx_pcb.data.netstat.tot_recv;
++ dev->stats.tx_packets += adapter->irx_pcb.data.netstat.tot_xmit;
++ dev->stats.rx_crc_errors += adapter->irx_pcb.data.netstat.err_CRC;
++ dev->stats.rx_frame_errors += adapter->irx_pcb.data.netstat.err_align;
++ dev->stats.rx_fifo_errors += adapter->irx_pcb.data.netstat.err_ovrrun;
++ dev->stats.rx_over_errors += adapter->irx_pcb.data.netstat.err_res;
+ adapter->got[CMD_NETWORK_STATISTICS] = 1;
+ if (elp_debug >= 3)
+ printk(KERN_DEBUG "%s: interrupt - statistics response received\n", dev->name);
+@@ -794,11 +794,11 @@ static irqreturn_t elp_interrupt(int irq, void *dev_id)
+ break;
+ switch (adapter->irx_pcb.data.xmit_resp.c_stat) {
+ case 0xffff:
+- adapter->stats.tx_aborted_errors++;
++ dev->stats.tx_aborted_errors++;
+ printk(KERN_INFO "%s: transmit timed out, network cable problem?\n", dev->name);
+ break;
+ case 0xfffe:
+- adapter->stats.tx_fifo_errors++;
++ dev->stats.tx_fifo_errors++;
+ printk(KERN_INFO "%s: transmit timed out, FIFO underrun\n", dev->name);
+ break;
+ }
+@@ -986,7 +986,7 @@ static bool send_packet(struct net_device *dev, struct sk_buff *skb)
+ return false;
+ }
+
+- adapter->stats.tx_bytes += nlen;
++ dev->stats.tx_bytes += nlen;
+
+ /*
+ * send the adapter a transmit packet command. Ignore segment and offset
+@@ -1041,7 +1041,6 @@ static bool send_packet(struct net_device *dev, struct sk_buff *skb)
+
+ static void elp_timeout(struct net_device *dev)
+ {
+- elp_device *adapter = dev->priv;
+ int stat;
+
+ stat = inb_status(dev->base_addr);
+@@ -1049,7 +1048,7 @@ static void elp_timeout(struct net_device *dev)
+ if (elp_debug >= 1)
+ printk(KERN_DEBUG "%s: status %#02x\n", dev->name, stat);
+ dev->trans_start = jiffies;
+- adapter->stats.tx_dropped++;
++ dev->stats.tx_dropped++;
+ netif_wake_queue(dev);
+ }
+
+@@ -1113,7 +1112,7 @@ static struct net_device_stats *elp_get_stats(struct net_device *dev)
+ /* If the device is closed, just return the latest stats we have,
+ - we cannot ask from the adapter without interrupts */
+ if (!netif_running(dev))
+- return &adapter->stats;
++ return &dev->stats;
+
+ /* send a get statistics command to the board */
+ adapter->tx_pcb.command = CMD_NETWORK_STATISTICS;
+@@ -1126,12 +1125,12 @@ static struct net_device_stats *elp_get_stats(struct net_device *dev)
+ while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && time_before(jiffies, timeout));
+ if (time_after_eq(jiffies, timeout)) {
+ TIMEOUT_MSG(__LINE__);
+- return &adapter->stats;
++ return &dev->stats;
+ }
+ }
+
+ /* statistics are now up to date */
+- return &adapter->stats;
++ return &dev->stats;
+ }
+
+
+@@ -1571,7 +1570,6 @@ static int __init elplus_setup(struct net_device *dev)
+ dev->set_multicast_list = elp_set_mc_list; /* local */
+ dev->ethtool_ops = &netdev_ethtool_ops; /* local */
+
+- memset(&(adapter->stats), 0, sizeof(struct net_device_stats));
+ dev->mem_start = dev->mem_end = 0;
+
+ err = register_netdev(dev);
+diff --git a/drivers/net/3c505.h b/drivers/net/3c505.h
+index 1910cb1..04df2a9 100644
+--- a/drivers/net/3c505.h
++++ b/drivers/net/3c505.h
+@@ -264,7 +264,6 @@ typedef struct {
+ pcb_struct rx_pcb; /* PCB for foreground receiving */
+ pcb_struct itx_pcb; /* PCB for background sending */
+ pcb_struct irx_pcb; /* PCB for background receiving */
+- struct net_device_stats stats;
+
+ void *dma_buffer;
+
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
-index 8fafac9..54dac06 100644
+index 8fafac9..e6c545f 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -54,25 +54,24 @@
@@ -442513,14 +616007,14 @@
#define EL3_IO_EXTENT 16
-@@ -168,23 +164,31 @@ enum RxFilter {
+@@ -168,23 +164,30 @@ 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_stats stats;
- struct net_device *next_dev;
spinlock_t lock;
/* skb send-queue */
@@ -442554,7 +616048,7 @@
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);
+@@ -199,7 +202,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;
@@ -442563,7 +616057,7 @@
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 *);
+@@ -209,13 +212,272 @@ static int el3_resume(struct device *);
/* generic device remove for all device types */
@@ -442838,7 +616332,7 @@
#ifdef CONFIG_EISA
static struct eisa_device_id el3_eisa_ids[] = {
{ "TCM5092" },
-@@ -230,13 +493,14 @@ static int el3_eisa_probe (struct device *device);
+@@ -230,13 +492,14 @@ static int el3_eisa_probe (struct device *device);
static struct eisa_driver el3_eisa_driver = {
.id_table = el3_eisa_ids,
.driver = {
@@ -442854,7 +616348,7 @@
#endif
#ifdef CONFIG_MCA
-@@ -271,45 +535,9 @@ static struct mca_driver el3_mca_driver = {
+@@ -271,45 +534,9 @@ static struct mca_driver el3_mca_driver = {
.resume = el3_resume,
},
};
@@ -442901,7 +616395,7 @@
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)
+@@ -360,231 +587,11 @@ static int __init el3_common_init(struct net_device *dev)
static void el3_common_remove (struct net_device *dev)
{
@@ -443133,7 +616627,7 @@
#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)
+@@ -596,7 +603,6 @@ static int __init el3_mca_probe(struct device *device)
* redone for multi-card detection by ZP Gu (zpg at castle.net)
* now works as a module */
@@ -443141,7 +616635,7 @@
short i;
int ioaddr, irq, if_port;
u16 phys_addr[3];
-@@ -613,7 +620,7 @@ static int __init el3_mca_probe(struct device *device)
+@@ -613,7 +619,7 @@ static int __init el3_mca_probe(struct device *device)
irq = pos5 & 0x0f;
@@ -443150,7 +616644,7 @@
el3_mca_adapter_names[mdev->index], slot + 1);
/* claim the slot */
-@@ -626,7 +633,7 @@ static int __init el3_mca_probe(struct device *device)
+@@ -626,7 +632,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) {
@@ -443159,7 +616653,7 @@
}
EL3WINDOW(0);
for (i = 0; i < 3; i++) {
-@@ -641,13 +648,7 @@ static int __init el3_mca_probe(struct device *device)
+@@ -641,13 +647,7 @@ static int __init el3_mca_probe(struct device *device)
netdev_boot_setup_check(dev);
@@ -443174,7 +616668,7 @@
device->driver_data = dev;
err = el3_common_init(dev);
-@@ -657,7 +658,7 @@ static int __init el3_mca_probe(struct device *device)
+@@ -657,7 +657,7 @@ static int __init el3_mca_probe(struct device *device)
return -ENOMEM;
}
@@ -443183,7 +616677,7 @@
return 0;
}
-@@ -666,7 +667,6 @@ static int __init el3_mca_probe(struct device *device)
+@@ -666,7 +666,6 @@ static int __init el3_mca_probe(struct device *device)
#ifdef CONFIG_EISA
static int __init el3_eisa_probe (struct device *device)
{
@@ -443191,7 +616685,7 @@
short i;
int ioaddr, irq, if_port;
u16 phys_addr[3];
-@@ -678,7 +678,7 @@ static int __init el3_eisa_probe (struct device *device)
+@@ -678,7 +677,7 @@ static int __init el3_eisa_probe (struct device *device)
edev = to_eisa_device (device);
ioaddr = edev->base_addr;
@@ -443200,7 +616694,7 @@
return -EBUSY;
/* Change the register set to the configuration window 0. */
-@@ -700,13 +700,7 @@ static int __init el3_eisa_probe (struct device *device)
+@@ -700,13 +699,7 @@ static int __init el3_eisa_probe (struct device *device)
netdev_boot_setup_check(dev);
@@ -443215,7 +616709,7 @@
eisa_set_drvdata (edev, dev);
err = el3_common_init(dev);
-@@ -716,12 +710,11 @@ static int __init el3_eisa_probe (struct device *device)
+@@ -716,12 +709,11 @@ static int __init el3_eisa_probe (struct device *device)
return err;
}
@@ -443229,7 +616723,7 @@
/* 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)
+@@ -734,7 +726,6 @@ static int __devexit el3_device_remove (struct device *device)
el3_common_remove (dev);
return 0;
}
@@ -443237,7 +616731,7 @@
/* 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)
+@@ -749,7 +740,7 @@ static ushort read_eeprom(int ioaddr, int index)
}
/* Read a word from the EEPROM when in the ISA ID probe state. */
@@ -443246,7 +616740,7 @@
{
int bit, word = 0;
-@@ -765,7 +757,7 @@ static ushort __init id_read_eeprom(int index)
+@@ -765,7 +756,7 @@ static ushort __init id_read_eeprom(int index)
word = (word << 1) + (inb(id_port) & 0x01);
if (el3_debug > 3)
@@ -443255,7 +616749,7 @@
return word;
}
-@@ -787,13 +779,13 @@ el3_open(struct net_device *dev)
+@@ -787,13 +778,13 @@ el3_open(struct net_device *dev)
EL3WINDOW(0);
if (el3_debug > 3)
@@ -443271,7 +616765,11 @@
dev->name, dev->irq, inw(ioaddr + EL3_STATUS));
return 0;
-@@ -806,7 +798,7 @@ el3_tx_timeout (struct net_device *dev)
+@@ -802,15 +793,14 @@ el3_open(struct net_device *dev)
+ static void
+ el3_tx_timeout (struct net_device *dev)
+ {
+- struct el3_private *lp = netdev_priv(dev);
int ioaddr = dev->base_addr;
/* Transmitter timeout, serious problems. */
@@ -443280,8 +616778,17 @@
"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;
+- lp->stats.tx_errors++;
++ dev->stats.tx_errors++;
+ dev->trans_start = jiffies;
+ /* Issue TX_RESET and TX_START commands. */
+ outw(TxReset, ioaddr + EL3_CMD);
+@@ -828,10 +818,10 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+
+ netif_stop_queue (dev);
+
+- lp->stats.tx_bytes += skb->len;
++ dev->stats.tx_bytes += skb->len;
if (el3_debug > 4) {
- printk("%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
@@ -443289,7 +616796,7 @@
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)
+@@ -840,7 +830,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. */
@@ -443298,7 +616805,16 @@
" 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)
+@@ -889,7 +879,7 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ int i = 4;
+
+ while (--i > 0 && (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
+- if (tx_status & 0x38) lp->stats.tx_aborted_errors++;
++ if (tx_status & 0x38) dev->stats.tx_aborted_errors++;
+ if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
+ if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
+ outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
+@@ -914,7 +904,7 @@ el3_interrupt(int irq, void *dev_id)
if (el3_debug > 4) {
status = inw(ioaddr + EL3_STATUS);
@@ -443307,7 +616823,7 @@
}
while ((status = inw(ioaddr + EL3_STATUS)) &
-@@ -925,7 +917,7 @@ el3_interrupt(int irq, void *dev_id)
+@@ -925,7 +915,7 @@ el3_interrupt(int irq, void *dev_id)
if (status & TxAvailable) {
if (el3_debug > 5)
@@ -443316,7 +616832,21 @@
/* 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)
+@@ -939,12 +929,11 @@ el3_interrupt(int irq, void *dev_id)
+ outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
+ }
+ if (status & TxComplete) { /* Really Tx error. */
+- struct el3_private *lp = netdev_priv(dev);
+ short tx_status;
+ int i = 4;
+
+ while (--i>0 && (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
+- if (tx_status & 0x38) lp->stats.tx_aborted_errors++;
++ if (tx_status & 0x38) dev->stats.tx_aborted_errors++;
+ if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
+ if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
+ outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
+@@ -964,7 +953,7 @@ el3_interrupt(int irq, void *dev_id)
}
if (--i < 0) {
@@ -443325,7 +616855,7 @@
dev->name, status);
/* Clear all interrupts. */
outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
-@@ -975,7 +967,7 @@ el3_interrupt(int irq, void *dev_id)
+@@ -975,7 +964,7 @@ el3_interrupt(int irq, void *dev_id)
}
if (el3_debug > 4) {
@@ -443334,7 +616864,96 @@
inw(ioaddr + EL3_STATUS));
}
spin_unlock(&lp->lock);
-@@ -1450,7 +1442,7 @@ el3_up(struct net_device *dev)
+@@ -1010,7 +999,7 @@ el3_get_stats(struct net_device *dev)
+ spin_lock_irqsave(&lp->lock, flags);
+ update_stats(dev);
+ spin_unlock_irqrestore(&lp->lock, flags);
+- return &lp->stats;
++ return &dev->stats;
+ }
+
+ /* Update statistics. We change to register window 6, so this should be run
+@@ -1020,7 +1009,6 @@ el3_get_stats(struct net_device *dev)
+ */
+ static void update_stats(struct net_device *dev)
+ {
+- struct el3_private *lp = netdev_priv(dev);
+ int ioaddr = dev->base_addr;
+
+ if (el3_debug > 5)
+@@ -1029,13 +1017,13 @@ static void update_stats(struct net_device *dev)
+ outw(StatsDisable, ioaddr + EL3_CMD);
+ /* Switch to the stats window, and read everything. */
+ EL3WINDOW(6);
+- lp->stats.tx_carrier_errors += inb(ioaddr + 0);
+- lp->stats.tx_heartbeat_errors += inb(ioaddr + 1);
++ dev->stats.tx_carrier_errors += inb(ioaddr + 0);
++ dev->stats.tx_heartbeat_errors += inb(ioaddr + 1);
+ /* Multiple collisions. */ inb(ioaddr + 2);
+- lp->stats.collisions += inb(ioaddr + 3);
+- lp->stats.tx_window_errors += inb(ioaddr + 4);
+- lp->stats.rx_fifo_errors += inb(ioaddr + 5);
+- lp->stats.tx_packets += inb(ioaddr + 6);
++ dev->stats.collisions += inb(ioaddr + 3);
++ dev->stats.tx_window_errors += inb(ioaddr + 4);
++ dev->stats.rx_fifo_errors += inb(ioaddr + 5);
++ dev->stats.tx_packets += inb(ioaddr + 6);
+ /* Rx packets */ inb(ioaddr + 7);
+ /* Tx deferrals */ inb(ioaddr + 8);
+ inw(ioaddr + 10); /* Total Rx and Tx octets. */
+@@ -1050,7 +1038,6 @@ static void update_stats(struct net_device *dev)
+ static int
+ el3_rx(struct net_device *dev)
+ {
+- struct el3_private *lp = netdev_priv(dev);
+ int ioaddr = dev->base_addr;
+ short rx_status;
+
+@@ -1062,21 +1049,21 @@ el3_rx(struct net_device *dev)
+ short error = rx_status & 0x3800;
+
+ outw(RxDiscard, ioaddr + EL3_CMD);
+- lp->stats.rx_errors++;
++ dev->stats.rx_errors++;
+ switch (error) {
+- case 0x0000: lp->stats.rx_over_errors++; break;
+- case 0x0800: lp->stats.rx_length_errors++; break;
+- case 0x1000: lp->stats.rx_frame_errors++; break;
+- case 0x1800: lp->stats.rx_length_errors++; break;
+- case 0x2000: lp->stats.rx_frame_errors++; break;
+- case 0x2800: lp->stats.rx_crc_errors++; break;
++ case 0x0000: dev->stats.rx_over_errors++; break;
++ case 0x0800: dev->stats.rx_length_errors++; break;
++ case 0x1000: dev->stats.rx_frame_errors++; break;
++ case 0x1800: dev->stats.rx_length_errors++; break;
++ case 0x2000: dev->stats.rx_frame_errors++; break;
++ case 0x2800: dev->stats.rx_crc_errors++; break;
+ }
+ } else {
+ short pkt_len = rx_status & 0x7ff;
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(pkt_len+5);
+- lp->stats.rx_bytes += pkt_len;
++ dev->stats.rx_bytes += pkt_len;
+ if (el3_debug > 4)
+ printk("Receiving packet size %d status %4.4x.\n",
+ pkt_len, rx_status);
+@@ -1091,11 +1078,11 @@ el3_rx(struct net_device *dev)
+ skb->protocol = eth_type_trans(skb,dev);
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+- lp->stats.rx_packets++;
++ dev->stats.rx_packets++;
+ continue;
+ }
+ outw(RxDiscard, ioaddr + EL3_CMD);
+- lp->stats.rx_dropped++;
++ dev->stats.rx_dropped++;
+ if (el3_debug)
+ printk("%s: Couldn't allocate a sk_buff of size %d.\n",
+ dev->name, pkt_len);
+@@ -1450,7 +1437,7 @@ el3_up(struct net_device *dev)
}
/* Power Management support functions */
@@ -443343,7 +616962,7 @@
static int
el3_suspend(struct device *pdev, pm_message_t state)
-@@ -1500,79 +1492,102 @@ el3_resume(struct device *pdev)
+@@ -1500,79 +1487,102 @@ el3_resume(struct device *pdev)
return 0;
}
@@ -443485,6 +617104,178 @@
module_init (el3_init_module);
module_exit (el3_cleanup_module);
-
+diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
+index 6ab84b6..105a8c7 100644
+--- a/drivers/net/3c515.c
++++ b/drivers/net/3c515.c
+@@ -310,7 +310,6 @@ struct corkscrew_private {
+ struct sk_buff *tx_skbuff[TX_RING_SIZE];
+ unsigned int cur_rx, cur_tx; /* The next free ring entry */
+ unsigned int dirty_rx, dirty_tx;/* The ring entries to be free()ed. */
+- struct net_device_stats stats;
+ struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */
+ struct timer_list timer; /* Media selection timer. */
+ int capabilities ; /* Adapter capabilities word. */
+@@ -983,8 +982,8 @@ static void corkscrew_timeout(struct net_device *dev)
+ break;
+ outw(TxEnable, ioaddr + EL3_CMD);
+ dev->trans_start = jiffies;
+- vp->stats.tx_errors++;
+- vp->stats.tx_dropped++;
++ dev->stats.tx_errors++;
++ dev->stats.tx_dropped++;
+ netif_wake_queue(dev);
+ }
+
+@@ -1050,7 +1049,7 @@ static int corkscrew_start_xmit(struct sk_buff *skb,
+ }
+ /* Put out the doubleword header... */
+ outl(skb->len, ioaddr + TX_FIFO);
+- vp->stats.tx_bytes += skb->len;
++ dev->stats.tx_bytes += skb->len;
+ #ifdef VORTEX_BUS_MASTER
+ if (vp->bus_master) {
+ /* Set the bus-master controller to transfer the packet. */
+@@ -1094,9 +1093,9 @@ static int corkscrew_start_xmit(struct sk_buff *skb,
+ printk("%s: Tx error, status %2.2x.\n",
+ dev->name, tx_status);
+ if (tx_status & 0x04)
+- vp->stats.tx_fifo_errors++;
++ dev->stats.tx_fifo_errors++;
+ if (tx_status & 0x38)
+- vp->stats.tx_aborted_errors++;
++ dev->stats.tx_aborted_errors++;
+ if (tx_status & 0x30) {
+ int j;
+ outw(TxReset, ioaddr + EL3_CMD);
+@@ -1257,7 +1256,6 @@ static irqreturn_t corkscrew_interrupt(int irq, void *dev_id)
+
+ static int corkscrew_rx(struct net_device *dev)
+ {
+- struct corkscrew_private *vp = netdev_priv(dev);
+ int ioaddr = dev->base_addr;
+ int i;
+ short rx_status;
+@@ -1271,17 +1269,17 @@ static int corkscrew_rx(struct net_device *dev)
+ if (corkscrew_debug > 2)
+ printk(" Rx error: status %2.2x.\n",
+ rx_error);
+- vp->stats.rx_errors++;
++ dev->stats.rx_errors++;
+ if (rx_error & 0x01)
+- vp->stats.rx_over_errors++;
++ dev->stats.rx_over_errors++;
+ if (rx_error & 0x02)
+- vp->stats.rx_length_errors++;
++ dev->stats.rx_length_errors++;
+ if (rx_error & 0x04)
+- vp->stats.rx_frame_errors++;
++ dev->stats.rx_frame_errors++;
+ if (rx_error & 0x08)
+- vp->stats.rx_crc_errors++;
++ dev->stats.rx_crc_errors++;
+ if (rx_error & 0x10)
+- vp->stats.rx_length_errors++;
++ dev->stats.rx_length_errors++;
+ } else {
+ /* The packet length: up to 4.5K!. */
+ short pkt_len = rx_status & 0x1fff;
+@@ -1301,8 +1299,8 @@ static int corkscrew_rx(struct net_device *dev)
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+- vp->stats.rx_packets++;
+- vp->stats.rx_bytes += pkt_len;
++ dev->stats.rx_packets++;
++ dev->stats.rx_bytes += pkt_len;
+ /* Wait a limited time to go to next packet. */
+ for (i = 200; i >= 0; i--)
+ if (! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+@@ -1312,7 +1310,7 @@ static int corkscrew_rx(struct net_device *dev)
+ printk("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, pkt_len);
+ }
+ outw(RxDiscard, ioaddr + EL3_CMD);
+- vp->stats.rx_dropped++;
++ dev->stats.rx_dropped++;
+ /* Wait a limited time to skip this packet. */
+ for (i = 200; i >= 0; i--)
+ if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
+@@ -1337,23 +1335,23 @@ static int boomerang_rx(struct net_device *dev)
+ if (corkscrew_debug > 2)
+ printk(" Rx error: status %2.2x.\n",
+ rx_error);
+- vp->stats.rx_errors++;
++ dev->stats.rx_errors++;
+ if (rx_error & 0x01)
+- vp->stats.rx_over_errors++;
++ dev->stats.rx_over_errors++;
+ if (rx_error & 0x02)
+- vp->stats.rx_length_errors++;
++ dev->stats.rx_length_errors++;
+ if (rx_error & 0x04)
+- vp->stats.rx_frame_errors++;
++ dev->stats.rx_frame_errors++;
+ if (rx_error & 0x08)
+- vp->stats.rx_crc_errors++;
++ dev->stats.rx_crc_errors++;
+ if (rx_error & 0x10)
+- vp->stats.rx_length_errors++;
++ dev->stats.rx_length_errors++;
+ } else {
+ /* The packet length: up to 4.5K!. */
+ short pkt_len = rx_status & 0x1fff;
+ struct sk_buff *skb;
+
+- vp->stats.rx_bytes += pkt_len;
++ dev->stats.rx_bytes += pkt_len;
+ if (corkscrew_debug > 4)
+ printk("Receiving packet size %d status %4.4x.\n",
+ pkt_len, rx_status);
+@@ -1388,7 +1386,7 @@ static int boomerang_rx(struct net_device *dev)
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+- vp->stats.rx_packets++;
++ dev->stats.rx_packets++;
+ }
+ entry = (++vp->cur_rx) % RX_RING_SIZE;
+ }
+@@ -1475,7 +1473,7 @@ static struct net_device_stats *corkscrew_get_stats(struct net_device *dev)
+ update_stats(dev->base_addr, dev);
+ spin_unlock_irqrestore(&vp->lock, flags);
+ }
+- return &vp->stats;
++ return &dev->stats;
+ }
+
+ /* Update statistics.
+@@ -1487,19 +1485,17 @@ static struct net_device_stats *corkscrew_get_stats(struct net_device *dev)
+ */
+ static void update_stats(int ioaddr, struct net_device *dev)
+ {
+- struct corkscrew_private *vp = netdev_priv(dev);
+-
+ /* Unlike the 3c5x9 we need not turn off stats updates while reading. */
+ /* Switch to the stats window, and read everything. */
+ EL3WINDOW(6);
+- vp->stats.tx_carrier_errors += inb(ioaddr + 0);
+- vp->stats.tx_heartbeat_errors += inb(ioaddr + 1);
++ dev->stats.tx_carrier_errors += inb(ioaddr + 0);
++ dev->stats.tx_heartbeat_errors += inb(ioaddr + 1);
+ /* Multiple collisions. */ inb(ioaddr + 2);
+- vp->stats.collisions += inb(ioaddr + 3);
+- vp->stats.tx_window_errors += inb(ioaddr + 4);
+- vp->stats.rx_fifo_errors += inb(ioaddr + 5);
+- vp->stats.tx_packets += inb(ioaddr + 6);
+- vp->stats.tx_packets += (inb(ioaddr + 9) & 0x30) << 4;
++ dev->stats.collisions += inb(ioaddr + 3);
++ dev->stats.tx_window_errors += inb(ioaddr + 4);
++ dev->stats.rx_fifo_errors += inb(ioaddr + 5);
++ dev->stats.tx_packets += inb(ioaddr + 6);
++ dev->stats.tx_packets += (inb(ioaddr + 9) & 0x30) << 4;
+ /* Rx packets */ inb(ioaddr + 7);
+ /* Must read to clear */
+ /* Tx deferrals */ inb(ioaddr + 8);
diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c
index b72b89d..fae295b 100644
--- a/drivers/net/3c527.c
@@ -443558,7 +617349,7 @@
#endif /* MODULE */
MODULE_LICENSE("GPL");
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
-index 3a0b20a..0697aa8 100644
+index 3a0b20a..af46341 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -467,6 +467,13 @@ config SNI_82596
@@ -443567,7 +617358,7 @@
+config KORINA
+ tristate "Korina (IDT RC32434) Ethernet support"
-+ depends on NET_ETHERNET && MIKROTIK_RB500
++ depends on NET_ETHERNET && MIKROTIK_RB532
+ help
+ If you have a Mikrotik RouterBoard 500 or IDT RC32434
+ based system say Y. Otherwise say N.
@@ -443593,6 +617384,15 @@
config EEPRO100
tristate "EtherExpressPro/100 support (eepro100, original Becker driver)"
+@@ -2004,7 +2011,7 @@ config E1000_DISABLE_PACKET_SPLIT
+
+ config E1000E
+ tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"
+- depends on PCI
++ depends on PCI && (!SPARC32 || BROKEN)
+ ---help---
+ This driver supports the PCI-Express Intel(R) PRO/1000 gigabit
+ ethernet family of adapters. For PCI or PCI-X e1000 adapters,
@@ -2220,93 +2227,6 @@ config SKY2_DEBUG
If unsure, say N.
@@ -443704,8 +617504,16 @@
select MII
help
This driver supports the gigabit ethernet MACs in the
+@@ -2672,6 +2593,7 @@ config BNX2X
+ To compile this driver as a module, choose M here: the module
+ will be called bnx2x. This is recommended.
+
++source "drivers/net/sfc/Kconfig"
+
+ endif # NETDEV_10000
+
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
-index 3b1ea32..2f1f3f2 100644
+index 3b1ea32..dcbfe84 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -15,7 +15,7 @@ obj-$(CONFIG_CHELSIO_T3) += cxgb3/
@@ -443743,6 +617551,12 @@
obj-$(CONFIG_MLX4_CORE) += mlx4/
obj-$(CONFIG_ENC28J60) += enc28j60.o
+@@ -252,3 +253,5 @@ obj-$(CONFIG_FS_ENET) += fs_enet/
+ obj-$(CONFIG_NETXEN_NIC) += netxen/
+ obj-$(CONFIG_NIU) += niu.o
+ obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
++obj-$(CONFIG_SFC) += sfc/
++
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index c59c806..bdc4c0b 100644
--- a/drivers/net/arcnet/arcnet.c
@@ -443789,6 +617603,54 @@
+module_init(com20020_module_init);
+module_exit(com20020_module_exit);
#endif /* MODULE */
+diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
+index f9cc2b6..8eda6ee 100644
+--- a/drivers/net/arm/Kconfig
++++ b/drivers/net/arm/Kconfig
+@@ -47,3 +47,11 @@ config EP93XX_ETH
+ help
+ This is a driver for the ethernet hardware included in EP93xx CPUs.
+ Say Y if you are building a kernel for EP93xx based devices.
++
++config IXP4XX_ETH
++ tristate "Intel IXP4xx Ethernet support"
++ depends on ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR
++ select MII
++ help
++ Say Y here if you want to use built-in Ethernet ports
++ on IXP4xx processor.
+diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile
+index a4c8682..7c812ac 100644
+--- a/drivers/net/arm/Makefile
++++ b/drivers/net/arm/Makefile
+@@ -9,3 +9,4 @@ obj-$(CONFIG_ARM_ETHER3) += ether3.o
+ obj-$(CONFIG_ARM_ETHER1) += ether1.o
+ obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o
+ obj-$(CONFIG_EP93XX_ETH) += ep93xx_eth.o
++obj-$(CONFIG_IXP4XX_ETH) += ixp4xx_eth.o
+diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
+index ba6bd03..a637910 100644
+--- a/drivers/net/arm/am79c961a.c
++++ b/drivers/net/arm/am79c961a.c
+@@ -693,11 +693,15 @@ static int __init am79c961_probe(struct platform_device *pdev)
+ * done by the ether bootp loader.
+ */
+ dev->base_addr = res->start;
+- dev->irq = platform_get_irq(pdev, 0);
++ ret = platform_get_irq(pdev, 0);
+
+- ret = -ENODEV;
+- if (dev->irq < 0)
++ if (ret < 0) {
++ ret = -ENODEV;
+ goto nodev;
++ }
++ dev->irq = ret;
++
++ ret = -ENODEV;
+ if (!request_region(dev->base_addr, 0x18, dev->name))
+ goto nodev;
+
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
@@ -443826,6 +617688,1277 @@
module_exit(ep93xx_eth_cleanup_module);
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ep93xx-eth");
+diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c
+new file mode 100644
+index 0000000..c617b64
+--- /dev/null
++++ b/drivers/net/arm/ixp4xx_eth.c
+@@ -0,0 +1,1265 @@
++/*
++ * Intel IXP4xx Ethernet driver for Linux
++ *
++ * Copyright (C) 2007 Krzysztof Halasa <khc at pm.waw.pl>
++ *
++ * 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.
++ *
++ * Ethernet port config (0x00 is not present on IXP42X):
++ *
++ * logical port 0x00 0x10 0x20
++ * NPE 0 (NPE-A) 1 (NPE-B) 2 (NPE-C)
++ * physical PortId 2 0 1
++ * TX queue 23 24 25
++ * RX-free queue 26 27 28
++ * TX-done queue is always 31, per-port RX and TX-ready queues are configurable
++ *
++ *
++ * Queue entries:
++ * bits 0 -> 1 - NPE ID (RX and TX-done)
++ * bits 0 -> 2 - priority (TX, per 802.1D)
++ * bits 3 -> 4 - port ID (user-set?)
++ * bits 5 -> 31 - physical descriptor address
++ */
++
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/dmapool.h>
++#include <linux/etherdevice.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/mii.h>
++#include <linux/platform_device.h>
++#include <asm/arch/npe.h>
++#include <asm/arch/qmgr.h>
++
++#define DEBUG_QUEUES 0
++#define DEBUG_DESC 0
++#define DEBUG_RX 0
++#define DEBUG_TX 0
++#define DEBUG_PKT_BYTES 0
++#define DEBUG_MDIO 0
++#define DEBUG_CLOSE 0
++
++#define DRV_NAME "ixp4xx_eth"
++
++#define MAX_NPES 3
++
++#define RX_DESCS 64 /* also length of all RX queues */
++#define TX_DESCS 16 /* also length of all TX queues */
++#define TXDONE_QUEUE_LEN 64 /* dwords */
++
++#define POOL_ALLOC_SIZE (sizeof(struct desc) * (RX_DESCS + TX_DESCS))
++#define REGS_SIZE 0x1000
++#define MAX_MRU 1536 /* 0x600 */
++#define RX_BUFF_SIZE ALIGN((NET_IP_ALIGN) + MAX_MRU, 4)
++
++#define NAPI_WEIGHT 16
++#define MDIO_INTERVAL (3 * HZ)
++#define MAX_MDIO_RETRIES 100 /* microseconds, typically 30 cycles */
++#define MAX_MII_RESET_RETRIES 100 /* mdio_read() cycles, typically 4 */
++#define MAX_CLOSE_WAIT 1000 /* microseconds, typically 2-3 cycles */
++
++#define NPE_ID(port_id) ((port_id) >> 4)
++#define PHYSICAL_ID(port_id) ((NPE_ID(port_id) + 2) % 3)
++#define TX_QUEUE(port_id) (NPE_ID(port_id) + 23)
++#define RXFREE_QUEUE(port_id) (NPE_ID(port_id) + 26)
++#define TXDONE_QUEUE 31
++
++/* TX Control Registers */
++#define TX_CNTRL0_TX_EN 0x01
++#define TX_CNTRL0_HALFDUPLEX 0x02
++#define TX_CNTRL0_RETRY 0x04
++#define TX_CNTRL0_PAD_EN 0x08
++#define TX_CNTRL0_APPEND_FCS 0x10
++#define TX_CNTRL0_2DEFER 0x20
++#define TX_CNTRL0_RMII 0x40 /* reduced MII */
++#define TX_CNTRL1_RETRIES 0x0F /* 4 bits */
++
++/* RX Control Registers */
++#define RX_CNTRL0_RX_EN 0x01
++#define RX_CNTRL0_PADSTRIP_EN 0x02
++#define RX_CNTRL0_SEND_FCS 0x04
++#define RX_CNTRL0_PAUSE_EN 0x08
++#define RX_CNTRL0_LOOP_EN 0x10
++#define RX_CNTRL0_ADDR_FLTR_EN 0x20
++#define RX_CNTRL0_RX_RUNT_EN 0x40
++#define RX_CNTRL0_BCAST_DIS 0x80
++#define RX_CNTRL1_DEFER_EN 0x01
++
++/* Core Control Register */
++#define CORE_RESET 0x01
++#define CORE_RX_FIFO_FLUSH 0x02
++#define CORE_TX_FIFO_FLUSH 0x04
++#define CORE_SEND_JAM 0x08
++#define CORE_MDC_EN 0x10 /* MDIO using NPE-B ETH-0 only */
++
++#define DEFAULT_TX_CNTRL0 (TX_CNTRL0_TX_EN | TX_CNTRL0_RETRY | \
++ TX_CNTRL0_PAD_EN | TX_CNTRL0_APPEND_FCS | \
++ TX_CNTRL0_2DEFER)
++#define DEFAULT_RX_CNTRL0 RX_CNTRL0_RX_EN
++#define DEFAULT_CORE_CNTRL CORE_MDC_EN
++
++
++/* NPE message codes */
++#define NPE_GETSTATUS 0x00
++#define NPE_EDB_SETPORTADDRESS 0x01
++#define NPE_EDB_GETMACADDRESSDATABASE 0x02
++#define NPE_EDB_SETMACADDRESSSDATABASE 0x03
++#define NPE_GETSTATS 0x04
++#define NPE_RESETSTATS 0x05
++#define NPE_SETMAXFRAMELENGTHS 0x06
++#define NPE_VLAN_SETRXTAGMODE 0x07
++#define NPE_VLAN_SETDEFAULTRXVID 0x08
++#define NPE_VLAN_SETPORTVLANTABLEENTRY 0x09
++#define NPE_VLAN_SETPORTVLANTABLERANGE 0x0A
++#define NPE_VLAN_SETRXQOSENTRY 0x0B
++#define NPE_VLAN_SETPORTIDEXTRACTIONMODE 0x0C
++#define NPE_STP_SETBLOCKINGSTATE 0x0D
++#define NPE_FW_SETFIREWALLMODE 0x0E
++#define NPE_PC_SETFRAMECONTROLDURATIONID 0x0F
++#define NPE_PC_SETAPMACTABLE 0x11
++#define NPE_SETLOOPBACK_MODE 0x12
++#define NPE_PC_SETBSSIDTABLE 0x13
++#define NPE_ADDRESS_FILTER_CONFIG 0x14
++#define NPE_APPENDFCSCONFIG 0x15
++#define NPE_NOTIFY_MAC_RECOVERY_DONE 0x16
++#define NPE_MAC_RECOVERY_START 0x17
++
++
++#ifdef __ARMEB__
++typedef struct sk_buff buffer_t;
++#define free_buffer dev_kfree_skb
++#define free_buffer_irq dev_kfree_skb_irq
++#else
++typedef void buffer_t;
++#define free_buffer kfree
++#define free_buffer_irq kfree
++#endif
++
++struct eth_regs {
++ u32 tx_control[2], __res1[2]; /* 000 */
++ u32 rx_control[2], __res2[2]; /* 010 */
++ u32 random_seed, __res3[3]; /* 020 */
++ u32 partial_empty_threshold, __res4; /* 030 */
++ u32 partial_full_threshold, __res5; /* 038 */
++ u32 tx_start_bytes, __res6[3]; /* 040 */
++ u32 tx_deferral, rx_deferral, __res7[2];/* 050 */
++ u32 tx_2part_deferral[2], __res8[2]; /* 060 */
++ u32 slot_time, __res9[3]; /* 070 */
++ u32 mdio_command[4]; /* 080 */
++ u32 mdio_status[4]; /* 090 */
++ u32 mcast_mask[6], __res10[2]; /* 0A0 */
++ u32 mcast_addr[6], __res11[2]; /* 0C0 */
++ u32 int_clock_threshold, __res12[3]; /* 0E0 */
++ u32 hw_addr[6], __res13[61]; /* 0F0 */
++ u32 core_control; /* 1FC */
++};
++
++struct port {
++ struct resource *mem_res;
++ struct eth_regs __iomem *regs;
++ struct npe *npe;
++ struct net_device *netdev;
++ struct napi_struct napi;
++ struct net_device_stats stat;
++ struct mii_if_info mii;
++ struct delayed_work mdio_thread;
++ struct eth_plat_info *plat;
++ buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS];
++ struct desc *desc_tab; /* coherent */
++ u32 desc_tab_phys;
++ int id; /* logical port ID */
++ u16 mii_bmcr;
++};
++
++/* NPE message structure */
++struct msg {
++#ifdef __ARMEB__
++ u8 cmd, eth_id, byte2, byte3;
++ u8 byte4, byte5, byte6, byte7;
++#else
++ u8 byte3, byte2, eth_id, cmd;
++ u8 byte7, byte6, byte5, byte4;
++#endif
++};
++
++/* Ethernet packet descriptor */
++struct desc {
++ u32 next; /* pointer to next buffer, unused */
++
++#ifdef __ARMEB__
++ u16 buf_len; /* buffer length */
++ u16 pkt_len; /* packet length */
++ u32 data; /* pointer to data buffer in RAM */
++ u8 dest_id;
++ u8 src_id;
++ u16 flags;
++ u8 qos;
++ u8 padlen;
++ u16 vlan_tci;
++#else
++ u16 pkt_len; /* packet length */
++ u16 buf_len; /* buffer length */
++ u32 data; /* pointer to data buffer in RAM */
++ u16 flags;
++ u8 src_id;
++ u8 dest_id;
++ u16 vlan_tci;
++ u8 padlen;
++ u8 qos;
++#endif
++
++#ifdef __ARMEB__
++ u8 dst_mac_0, dst_mac_1, dst_mac_2, dst_mac_3;
++ u8 dst_mac_4, dst_mac_5, src_mac_0, src_mac_1;
++ u8 src_mac_2, src_mac_3, src_mac_4, src_mac_5;
++#else
++ u8 dst_mac_3, dst_mac_2, dst_mac_1, dst_mac_0;
++ u8 src_mac_1, src_mac_0, dst_mac_5, dst_mac_4;
++ u8 src_mac_5, src_mac_4, src_mac_3, src_mac_2;
++#endif
++};
++
++
++#define rx_desc_phys(port, n) ((port)->desc_tab_phys + \
++ (n) * sizeof(struct desc))
++#define rx_desc_ptr(port, n) (&(port)->desc_tab[n])
++
++#define tx_desc_phys(port, n) ((port)->desc_tab_phys + \
++ ((n) + RX_DESCS) * sizeof(struct desc))
++#define tx_desc_ptr(port, n) (&(port)->desc_tab[(n) + RX_DESCS])
++
++#ifndef __ARMEB__
++static inline void memcpy_swab32(u32 *dest, u32 *src, int cnt)
++{
++ int i;
++ for (i = 0; i < cnt; i++)
++ dest[i] = swab32(src[i]);
++}
++#endif
++
++static spinlock_t mdio_lock;
++static struct eth_regs __iomem *mdio_regs; /* mdio command and status only */
++static int ports_open;
++static struct port *npe_port_tab[MAX_NPES];
++static struct dma_pool *dma_pool;
++
++
++static u16 mdio_cmd(struct net_device *dev, int phy_id, int location,
++ int write, u16 cmd)
++{
++ int cycles = 0;
++
++ if (__raw_readl(&mdio_regs->mdio_command[3]) & 0x80) {
++ printk(KERN_ERR "%s: MII not ready to transmit\n", dev->name);
++ return 0;
++ }
++
++ if (write) {
++ __raw_writel(cmd & 0xFF, &mdio_regs->mdio_command[0]);
++ __raw_writel(cmd >> 8, &mdio_regs->mdio_command[1]);
++ }
++ __raw_writel(((phy_id << 5) | location) & 0xFF,
++ &mdio_regs->mdio_command[2]);
++ __raw_writel((phy_id >> 3) | (write << 2) | 0x80 /* GO */,
++ &mdio_regs->mdio_command[3]);
++
++ while ((cycles < MAX_MDIO_RETRIES) &&
++ (__raw_readl(&mdio_regs->mdio_command[3]) & 0x80)) {
++ udelay(1);
++ cycles++;
++ }
++
++ if (cycles == MAX_MDIO_RETRIES) {
++ printk(KERN_ERR "%s: MII write failed\n", dev->name);
++ return 0;
++ }
++
++#if DEBUG_MDIO
++ printk(KERN_DEBUG "%s: mdio_cmd() took %i cycles\n", dev->name,
++ cycles);
++#endif
++
++ if (write)
++ return 0;
++
++ if (__raw_readl(&mdio_regs->mdio_status[3]) & 0x80) {
++ printk(KERN_ERR "%s: MII read failed\n", dev->name);
++ return 0;
++ }
++
++ return (__raw_readl(&mdio_regs->mdio_status[0]) & 0xFF) |
++ (__raw_readl(&mdio_regs->mdio_status[1]) << 8);
++}
++
++static int mdio_read(struct net_device *dev, int phy_id, int location)
++{
++ unsigned long flags;
++ u16 val;
++
++ spin_lock_irqsave(&mdio_lock, flags);
++ val = mdio_cmd(dev, phy_id, location, 0, 0);
++ spin_unlock_irqrestore(&mdio_lock, flags);
++ return val;
++}
++
++static void mdio_write(struct net_device *dev, int phy_id, int location,
++ int val)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&mdio_lock, flags);
++ mdio_cmd(dev, phy_id, location, 1, val);
++ spin_unlock_irqrestore(&mdio_lock, flags);
++}
++
++static void phy_reset(struct net_device *dev, int phy_id)
++{
++ struct port *port = netdev_priv(dev);
++ int cycles = 0;
++
++ mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr | BMCR_RESET);
++
++ while (cycles < MAX_MII_RESET_RETRIES) {
++ if (!(mdio_read(dev, phy_id, MII_BMCR) & BMCR_RESET)) {
++#if DEBUG_MDIO
++ printk(KERN_DEBUG "%s: phy_reset() took %i cycles\n",
++ dev->name, cycles);
++#endif
++ return;
++ }
++ udelay(1);
++ cycles++;
++ }
++
++ printk(KERN_ERR "%s: MII reset failed\n", dev->name);
++}
++
++static void eth_set_duplex(struct port *port)
++{
++ if (port->mii.full_duplex)
++ __raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX,
++ &port->regs->tx_control[0]);
++ else
++ __raw_writel(DEFAULT_TX_CNTRL0 | TX_CNTRL0_HALFDUPLEX,
++ &port->regs->tx_control[0]);
++}
++
++
++static void phy_check_media(struct port *port, int init)
++{
++ if (mii_check_media(&port->mii, 1, init))
++ eth_set_duplex(port);
++ if (port->mii.force_media) { /* mii_check_media() doesn't work */
++ struct net_device *dev = port->netdev;
++ int cur_link = mii_link_ok(&port->mii);
++ int prev_link = netif_carrier_ok(dev);
++
++ if (!prev_link && cur_link) {
++ printk(KERN_INFO "%s: link up\n", dev->name);
++ netif_carrier_on(dev);
++ } else if (prev_link && !cur_link) {
++ printk(KERN_INFO "%s: link down\n", dev->name);
++ netif_carrier_off(dev);
++ }
++ }
++}
++
++
++static void mdio_thread(struct work_struct *work)
++{
++ struct port *port = container_of(work, struct port, mdio_thread.work);
++
++ phy_check_media(port, 0);
++ schedule_delayed_work(&port->mdio_thread, MDIO_INTERVAL);
++}
++
++
++static inline void debug_pkt(struct net_device *dev, const char *func,
++ u8 *data, int len)
++{
++#if DEBUG_PKT_BYTES
++ int i;
++
++ printk(KERN_DEBUG "%s: %s(%i) ", dev->name, func, len);
++ for (i = 0; i < len; i++) {
++ if (i >= DEBUG_PKT_BYTES)
++ break;
++ printk("%s%02X",
++ ((i == 6) || (i == 12) || (i >= 14)) ? " " : "",
++ data[i]);
++ }
++ printk("\n");
++#endif
++}
++
++
++static inline void debug_desc(u32 phys, struct desc *desc)
++{
++#if DEBUG_DESC
++ printk(KERN_DEBUG "%X: %X %3X %3X %08X %2X < %2X %4X %X"
++ " %X %X %02X%02X%02X%02X%02X%02X < %02X%02X%02X%02X%02X%02X\n",
++ phys, desc->next, desc->buf_len, desc->pkt_len,
++ desc->data, desc->dest_id, desc->src_id, desc->flags,
++ desc->qos, desc->padlen, desc->vlan_tci,
++ desc->dst_mac_0, desc->dst_mac_1, desc->dst_mac_2,
++ desc->dst_mac_3, desc->dst_mac_4, desc->dst_mac_5,
++ desc->src_mac_0, desc->src_mac_1, desc->src_mac_2,
++ desc->src_mac_3, desc->src_mac_4, desc->src_mac_5);
++#endif
++}
++
++static inline void debug_queue(unsigned int queue, int is_get, u32 phys)
++{
++#if DEBUG_QUEUES
++ static struct {
++ int queue;
++ char *name;
++ } names[] = {
++ { TX_QUEUE(0x10), "TX#0 " },
++ { TX_QUEUE(0x20), "TX#1 " },
++ { TX_QUEUE(0x00), "TX#2 " },
++ { RXFREE_QUEUE(0x10), "RX-free#0 " },
++ { RXFREE_QUEUE(0x20), "RX-free#1 " },
++ { RXFREE_QUEUE(0x00), "RX-free#2 " },
++ { TXDONE_QUEUE, "TX-done " },
++ };
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(names); i++)
++ if (names[i].queue == queue)
++ break;
++
++ printk(KERN_DEBUG "Queue %i %s%s %X\n", queue,
++ i < ARRAY_SIZE(names) ? names[i].name : "",
++ is_get ? "->" : "<-", phys);
++#endif
++}
++
++static inline u32 queue_get_entry(unsigned int queue)
++{
++ u32 phys = qmgr_get_entry(queue);
++ debug_queue(queue, 1, phys);
++ return phys;
++}
++
++static inline int queue_get_desc(unsigned int queue, struct port *port,
++ int is_tx)
++{
++ u32 phys, tab_phys, n_desc;
++ struct desc *tab;
++
++ if (!(phys = queue_get_entry(queue)))
++ return -1;
++
++ phys &= ~0x1F; /* mask out non-address bits */
++ tab_phys = is_tx ? tx_desc_phys(port, 0) : rx_desc_phys(port, 0);
++ tab = is_tx ? tx_desc_ptr(port, 0) : rx_desc_ptr(port, 0);
++ n_desc = (phys - tab_phys) / sizeof(struct desc);
++ BUG_ON(n_desc >= (is_tx ? TX_DESCS : RX_DESCS));
++ debug_desc(phys, &tab[n_desc]);
++ BUG_ON(tab[n_desc].next);
++ return n_desc;
++}
++
++static inline void queue_put_desc(unsigned int queue, u32 phys,
++ struct desc *desc)
++{
++ debug_queue(queue, 0, phys);
++ debug_desc(phys, desc);
++ BUG_ON(phys & 0x1F);
++ qmgr_put_entry(queue, phys);
++ BUG_ON(qmgr_stat_overflow(queue));
++}
++
++
++static inline void dma_unmap_tx(struct port *port, struct desc *desc)
++{
++#ifdef __ARMEB__
++ dma_unmap_single(&port->netdev->dev, desc->data,
++ desc->buf_len, DMA_TO_DEVICE);
++#else
++ dma_unmap_single(&port->netdev->dev, desc->data & ~3,
++ ALIGN((desc->data & 3) + desc->buf_len, 4),
++ DMA_TO_DEVICE);
++#endif
++}
++
++
++static void eth_rx_irq(void *pdev)
++{
++ struct net_device *dev = pdev;
++ struct port *port = netdev_priv(dev);
++
++#if DEBUG_RX
++ printk(KERN_DEBUG "%s: eth_rx_irq\n", dev->name);
++#endif
++ qmgr_disable_irq(port->plat->rxq);
++ netif_rx_schedule(dev, &port->napi);
++}
++
++static int eth_poll(struct napi_struct *napi, int budget)
++{
++ struct port *port = container_of(napi, struct port, napi);
++ struct net_device *dev = port->netdev;
++ unsigned int rxq = port->plat->rxq, rxfreeq = RXFREE_QUEUE(port->id);
++ int received = 0;
++
++#if DEBUG_RX
++ printk(KERN_DEBUG "%s: eth_poll\n", dev->name);
++#endif
++
++ while (received < budget) {
++ struct sk_buff *skb;
++ struct desc *desc;
++ int n;
++#ifdef __ARMEB__
++ struct sk_buff *temp;
++ u32 phys;
++#endif
++
++ if ((n = queue_get_desc(rxq, port, 0)) < 0) {
++ received = 0; /* No packet received */
++#if DEBUG_RX
++ printk(KERN_DEBUG "%s: eth_poll netif_rx_complete\n",
++ dev->name);
++#endif
++ netif_rx_complete(dev, napi);
++ qmgr_enable_irq(rxq);
++ if (!qmgr_stat_empty(rxq) &&
++ netif_rx_reschedule(dev, napi)) {
++#if DEBUG_RX
++ printk(KERN_DEBUG "%s: eth_poll"
++ " netif_rx_reschedule successed\n",
++ dev->name);
++#endif
++ qmgr_disable_irq(rxq);
++ continue;
++ }
++#if DEBUG_RX
++ printk(KERN_DEBUG "%s: eth_poll all done\n",
++ dev->name);
++#endif
++ return 0; /* all work done */
++ }
++
++ desc = rx_desc_ptr(port, n);
++
++#ifdef __ARMEB__
++ if ((skb = netdev_alloc_skb(dev, RX_BUFF_SIZE))) {
++ phys = dma_map_single(&dev->dev, skb->data,
++ RX_BUFF_SIZE, DMA_FROM_DEVICE);
++ if (dma_mapping_error(phys)) {
++ dev_kfree_skb(skb);
++ skb = NULL;
++ }
++ }
++#else
++ skb = netdev_alloc_skb(dev,
++ ALIGN(NET_IP_ALIGN + desc->pkt_len, 4));
++#endif
++
++ if (!skb) {
++ port->stat.rx_dropped++;
++ /* put the desc back on RX-ready queue */
++ desc->buf_len = MAX_MRU;
++ desc->pkt_len = 0;
++ queue_put_desc(rxfreeq, rx_desc_phys(port, n), desc);
++ continue;
++ }
++
++ /* process received frame */
++#ifdef __ARMEB__
++ temp = skb;
++ skb = port->rx_buff_tab[n];
++ dma_unmap_single(&dev->dev, desc->data - NET_IP_ALIGN,
++ RX_BUFF_SIZE, DMA_FROM_DEVICE);
++#else
++ dma_sync_single(&dev->dev, desc->data - NET_IP_ALIGN,
++ RX_BUFF_SIZE, DMA_FROM_DEVICE);
++ memcpy_swab32((u32 *)skb->data, (u32 *)port->rx_buff_tab[n],
++ ALIGN(NET_IP_ALIGN + desc->pkt_len, 4) / 4);
++#endif
++ skb_reserve(skb, NET_IP_ALIGN);
++ skb_put(skb, desc->pkt_len);
++
++ debug_pkt(dev, "eth_poll", skb->data, skb->len);
++
++ skb->protocol = eth_type_trans(skb, dev);
++ dev->last_rx = jiffies;
++ port->stat.rx_packets++;
++ port->stat.rx_bytes += skb->len;
++ netif_receive_skb(skb);
++
++ /* put the new buffer on RX-free queue */
++#ifdef __ARMEB__
++ port->rx_buff_tab[n] = temp;
++ desc->data = phys + NET_IP_ALIGN;
++#endif
++ desc->buf_len = MAX_MRU;
++ desc->pkt_len = 0;
++ queue_put_desc(rxfreeq, rx_desc_phys(port, n), desc);
++ received++;
++ }
++
++#if DEBUG_RX
++ printk(KERN_DEBUG "eth_poll(): end, not all work done\n");
++#endif
++ return received; /* not all work done */
++}
++
++
++static void eth_txdone_irq(void *unused)
++{
++ u32 phys;
++
++#if DEBUG_TX
++ printk(KERN_DEBUG DRV_NAME ": eth_txdone_irq\n");
++#endif
++ while ((phys = queue_get_entry(TXDONE_QUEUE)) != 0) {
++ u32 npe_id, n_desc;
++ struct port *port;
++ struct desc *desc;
++ int start;
++
++ npe_id = phys & 3;
++ BUG_ON(npe_id >= MAX_NPES);
++ port = npe_port_tab[npe_id];
++ BUG_ON(!port);
++ phys &= ~0x1F; /* mask out non-address bits */
++ n_desc = (phys - tx_desc_phys(port, 0)) / sizeof(struct desc);
++ BUG_ON(n_desc >= TX_DESCS);
++ desc = tx_desc_ptr(port, n_desc);
++ debug_desc(phys, desc);
++
++ if (port->tx_buff_tab[n_desc]) { /* not the draining packet */
++ port->stat.tx_packets++;
++ port->stat.tx_bytes += desc->pkt_len;
++
++ dma_unmap_tx(port, desc);
++#if DEBUG_TX
++ printk(KERN_DEBUG "%s: eth_txdone_irq free %p\n",
++ port->netdev->name, port->tx_buff_tab[n_desc]);
++#endif
++ free_buffer_irq(port->tx_buff_tab[n_desc]);
++ port->tx_buff_tab[n_desc] = NULL;
++ }
++
++ start = qmgr_stat_empty(port->plat->txreadyq);
++ queue_put_desc(port->plat->txreadyq, phys, desc);
++ if (start) {
++#if DEBUG_TX
++ printk(KERN_DEBUG "%s: eth_txdone_irq xmit ready\n",
++ port->netdev->name);
++#endif
++ netif_wake_queue(port->netdev);
++ }
++ }
++}
++
++static int eth_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ struct port *port = netdev_priv(dev);
++ unsigned int txreadyq = port->plat->txreadyq;
++ int len, offset, bytes, n;
++ void *mem;
++ u32 phys;
++ struct desc *desc;
++
++#if DEBUG_TX
++ printk(KERN_DEBUG "%s: eth_xmit\n", dev->name);
++#endif
++
++ if (unlikely(skb->len > MAX_MRU)) {
++ dev_kfree_skb(skb);
++ port->stat.tx_errors++;
++ return NETDEV_TX_OK;
++ }
++
++ debug_pkt(dev, "eth_xmit", skb->data, skb->len);
++
++ len = skb->len;
++#ifdef __ARMEB__
++ offset = 0; /* no need to keep alignment */
++ bytes = len;
++ mem = skb->data;
++#else
++ offset = (int)skb->data & 3; /* keep 32-bit alignment */
++ bytes = ALIGN(offset + len, 4);
++ if (!(mem = kmalloc(bytes, GFP_ATOMIC))) {
++ dev_kfree_skb(skb);
++ port->stat.tx_dropped++;
++ return NETDEV_TX_OK;
++ }
++ memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4);
++ dev_kfree_skb(skb);
++#endif
++
++ phys = dma_map_single(&dev->dev, mem, bytes, DMA_TO_DEVICE);
++ if (dma_mapping_error(phys)) {
++#ifdef __ARMEB__
++ dev_kfree_skb(skb);
++#else
++ kfree(mem);
++#endif
++ port->stat.tx_dropped++;
++ return NETDEV_TX_OK;
++ }
++
++ n = queue_get_desc(txreadyq, port, 1);
++ BUG_ON(n < 0);
++ desc = tx_desc_ptr(port, n);
++
++#ifdef __ARMEB__
++ port->tx_buff_tab[n] = skb;
++#else
++ port->tx_buff_tab[n] = mem;
++#endif
++ desc->data = phys + offset;
++ desc->buf_len = desc->pkt_len = len;
++
++ /* NPE firmware pads short frames with zeros internally */
++ wmb();
++ queue_put_desc(TX_QUEUE(port->id), tx_desc_phys(port, n), desc);
++ dev->trans_start = jiffies;
++
++ if (qmgr_stat_empty(txreadyq)) {
++#if DEBUG_TX
++ printk(KERN_DEBUG "%s: eth_xmit queue full\n", dev->name);
++#endif
++ netif_stop_queue(dev);
++ /* we could miss TX ready interrupt */
++ if (!qmgr_stat_empty(txreadyq)) {
++#if DEBUG_TX
++ printk(KERN_DEBUG "%s: eth_xmit ready again\n",
++ dev->name);
++#endif
++ netif_wake_queue(dev);
++ }
++ }
++
++#if DEBUG_TX
++ printk(KERN_DEBUG "%s: eth_xmit end\n", dev->name);
++#endif
++ return NETDEV_TX_OK;
++}
++
++
++static struct net_device_stats *eth_stats(struct net_device *dev)
++{
++ struct port *port = netdev_priv(dev);
++ return &port->stat;
++}
++
++static void eth_set_mcast_list(struct net_device *dev)
++{
++ struct port *port = netdev_priv(dev);
++ struct dev_mc_list *mclist = dev->mc_list;
++ u8 diffs[ETH_ALEN], *addr;
++ int cnt = dev->mc_count, i;
++
++ if ((dev->flags & IFF_PROMISC) || !mclist || !cnt) {
++ __raw_writel(DEFAULT_RX_CNTRL0 & ~RX_CNTRL0_ADDR_FLTR_EN,
++ &port->regs->rx_control[0]);
++ return;
++ }
++
++ memset(diffs, 0, ETH_ALEN);
++ addr = mclist->dmi_addr; /* first MAC address */
++
++ while (--cnt && (mclist = mclist->next))
++ for (i = 0; i < ETH_ALEN; i++)
++ diffs[i] |= addr[i] ^ mclist->dmi_addr[i];
++
++ for (i = 0; i < ETH_ALEN; i++) {
++ __raw_writel(addr[i], &port->regs->mcast_addr[i]);
++ __raw_writel(~diffs[i], &port->regs->mcast_mask[i]);
++ }
++
++ __raw_writel(DEFAULT_RX_CNTRL0 | RX_CNTRL0_ADDR_FLTR_EN,
++ &port->regs->rx_control[0]);
++}
++
++
++static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
++{
++ struct port *port = netdev_priv(dev);
++ unsigned int duplex_chg;
++ int err;
++
++ if (!netif_running(dev))
++ return -EINVAL;
++ err = generic_mii_ioctl(&port->mii, if_mii(req), cmd, &duplex_chg);
++ if (duplex_chg)
++ eth_set_duplex(port);
++ return err;
++}
++
++
++static int request_queues(struct port *port)
++{
++ int err;
++
++ err = qmgr_request_queue(RXFREE_QUEUE(port->id), RX_DESCS, 0, 0);
++ if (err)
++ return err;
++
++ err = qmgr_request_queue(port->plat->rxq, RX_DESCS, 0, 0);
++ if (err)
++ goto rel_rxfree;
++
++ err = qmgr_request_queue(TX_QUEUE(port->id), TX_DESCS, 0, 0);
++ if (err)
++ goto rel_rx;
++
++ err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0);
++ if (err)
++ goto rel_tx;
++
++ /* TX-done queue handles skbs sent out by the NPEs */
++ if (!ports_open) {
++ err = qmgr_request_queue(TXDONE_QUEUE, TXDONE_QUEUE_LEN, 0, 0);
++ if (err)
++ goto rel_txready;
++ }
++ return 0;
++
++rel_txready:
++ qmgr_release_queue(port->plat->txreadyq);
++rel_tx:
++ qmgr_release_queue(TX_QUEUE(port->id));
++rel_rx:
++ qmgr_release_queue(port->plat->rxq);
++rel_rxfree:
++ qmgr_release_queue(RXFREE_QUEUE(port->id));
++ printk(KERN_DEBUG "%s: unable to request hardware queues\n",
++ port->netdev->name);
++ return err;
++}
++
++static void release_queues(struct port *port)
++{
++ qmgr_release_queue(RXFREE_QUEUE(port->id));
++ qmgr_release_queue(port->plat->rxq);
++ qmgr_release_queue(TX_QUEUE(port->id));
++ qmgr_release_queue(port->plat->txreadyq);
++
++ if (!ports_open)
++ qmgr_release_queue(TXDONE_QUEUE);
++}
++
++static int init_queues(struct port *port)
++{
++ int i;
++
++ if (!ports_open)
++ if (!(dma_pool = dma_pool_create(DRV_NAME, NULL,
++ POOL_ALLOC_SIZE, 32, 0)))
++ return -ENOMEM;
++
++ if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL,
++ &port->desc_tab_phys)))
++ return -ENOMEM;
++ memset(port->desc_tab, 0, POOL_ALLOC_SIZE);
++ memset(port->rx_buff_tab, 0, sizeof(port->rx_buff_tab)); /* tables */
++ memset(port->tx_buff_tab, 0, sizeof(port->tx_buff_tab));
++
++ /* Setup RX buffers */
++ for (i = 0; i < RX_DESCS; i++) {
++ struct desc *desc = rx_desc_ptr(port, i);
++ buffer_t *buff; /* skb or kmalloc()ated memory */
++ void *data;
++#ifdef __ARMEB__
++ if (!(buff = netdev_alloc_skb(port->netdev, RX_BUFF_SIZE)))
++ return -ENOMEM;
++ data = buff->data;
++#else
++ if (!(buff = kmalloc(RX_BUFF_SIZE, GFP_KERNEL)))
++ return -ENOMEM;
++ data = buff;
++#endif
++ desc->buf_len = MAX_MRU;
++ desc->data = dma_map_single(&port->netdev->dev, data,
++ RX_BUFF_SIZE, DMA_FROM_DEVICE);
++ if (dma_mapping_error(desc->data)) {
++ free_buffer(buff);
++ return -EIO;
++ }
++ desc->data += NET_IP_ALIGN;
++ port->rx_buff_tab[i] = buff;
++ }
++
++ return 0;
++}
++
++static void destroy_queues(struct port *port)
++{
++ int i;
++
++ if (port->desc_tab) {
++ for (i = 0; i < RX_DESCS; i++) {
++ struct desc *desc = rx_desc_ptr(port, i);
++ buffer_t *buff = port->rx_buff_tab[i];
++ if (buff) {
++ dma_unmap_single(&port->netdev->dev,
++ desc->data - NET_IP_ALIGN,
++ RX_BUFF_SIZE, DMA_FROM_DEVICE);
++ free_buffer(buff);
++ }
++ }
++ for (i = 0; i < TX_DESCS; i++) {
++ struct desc *desc = tx_desc_ptr(port, i);
++ buffer_t *buff = port->tx_buff_tab[i];
++ if (buff) {
++ dma_unmap_tx(port, desc);
++ free_buffer(buff);
++ }
++ }
++ dma_pool_free(dma_pool, port->desc_tab, port->desc_tab_phys);
++ port->desc_tab = NULL;
++ }
++
++ if (!ports_open && dma_pool) {
++ dma_pool_destroy(dma_pool);
++ dma_pool = NULL;
++ }
++}
++
++static int eth_open(struct net_device *dev)
++{
++ struct port *port = netdev_priv(dev);
++ struct npe *npe = port->npe;
++ struct msg msg;
++ int i, err;
++
++ if (!npe_running(npe)) {
++ err = npe_load_firmware(npe, npe_name(npe), &dev->dev);
++ if (err)
++ return err;
++
++ if (npe_recv_message(npe, &msg, "ETH_GET_STATUS")) {
++ printk(KERN_ERR "%s: %s not responding\n", dev->name,
++ npe_name(npe));
++ return -EIO;
++ }
++ }
++
++ mdio_write(dev, port->plat->phy, MII_BMCR, port->mii_bmcr);
++
++ memset(&msg, 0, sizeof(msg));
++ msg.cmd = NPE_VLAN_SETRXQOSENTRY;
++ msg.eth_id = port->id;
++ msg.byte5 = port->plat->rxq | 0x80;
++ msg.byte7 = port->plat->rxq << 4;
++ for (i = 0; i < 8; i++) {
++ msg.byte3 = i;
++ if (npe_send_recv_message(port->npe, &msg, "ETH_SET_RXQ"))
++ return -EIO;
++ }
++
++ msg.cmd = NPE_EDB_SETPORTADDRESS;
++ msg.eth_id = PHYSICAL_ID(port->id);
++ msg.byte2 = dev->dev_addr[0];
++ msg.byte3 = dev->dev_addr[1];
++ msg.byte4 = dev->dev_addr[2];
++ msg.byte5 = dev->dev_addr[3];
++ msg.byte6 = dev->dev_addr[4];
++ msg.byte7 = dev->dev_addr[5];
++ if (npe_send_recv_message(port->npe, &msg, "ETH_SET_MAC"))
++ return -EIO;
++
++ memset(&msg, 0, sizeof(msg));
++ msg.cmd = NPE_FW_SETFIREWALLMODE;
++ msg.eth_id = port->id;
++ if (npe_send_recv_message(port->npe, &msg, "ETH_SET_FIREWALL_MODE"))
++ return -EIO;
++
++ if ((err = request_queues(port)) != 0)
++ return err;
++
++ if ((err = init_queues(port)) != 0) {
++ destroy_queues(port);
++ release_queues(port);
++ return err;
++ }
++
++ for (i = 0; i < ETH_ALEN; i++)
++ __raw_writel(dev->dev_addr[i], &port->regs->hw_addr[i]);
++ __raw_writel(0x08, &port->regs->random_seed);
++ __raw_writel(0x12, &port->regs->partial_empty_threshold);
++ __raw_writel(0x30, &port->regs->partial_full_threshold);
++ __raw_writel(0x08, &port->regs->tx_start_bytes);
++ __raw_writel(0x15, &port->regs->tx_deferral);
++ __raw_writel(0x08, &port->regs->tx_2part_deferral[0]);
++ __raw_writel(0x07, &port->regs->tx_2part_deferral[1]);
++ __raw_writel(0x80, &port->regs->slot_time);
++ __raw_writel(0x01, &port->regs->int_clock_threshold);
++
++ /* Populate queues with buffers, no failure after this point */
++ for (i = 0; i < TX_DESCS; i++)
++ queue_put_desc(port->plat->txreadyq,
++ tx_desc_phys(port, i), tx_desc_ptr(port, i));
++
++ for (i = 0; i < RX_DESCS; i++)
++ queue_put_desc(RXFREE_QUEUE(port->id),
++ rx_desc_phys(port, i), rx_desc_ptr(port, i));
++
++ __raw_writel(TX_CNTRL1_RETRIES, &port->regs->tx_control[1]);
++ __raw_writel(DEFAULT_TX_CNTRL0, &port->regs->tx_control[0]);
++ __raw_writel(0, &port->regs->rx_control[1]);
++ __raw_writel(DEFAULT_RX_CNTRL0, &port->regs->rx_control[0]);
++
++ napi_enable(&port->napi);
++ phy_check_media(port, 1);
++ eth_set_mcast_list(dev);
++ netif_start_queue(dev);
++ schedule_delayed_work(&port->mdio_thread, MDIO_INTERVAL);
++
++ qmgr_set_irq(port->plat->rxq, QUEUE_IRQ_SRC_NOT_EMPTY,
++ eth_rx_irq, dev);
++ if (!ports_open) {
++ qmgr_set_irq(TXDONE_QUEUE, QUEUE_IRQ_SRC_NOT_EMPTY,
++ eth_txdone_irq, NULL);
++ qmgr_enable_irq(TXDONE_QUEUE);
++ }
++ ports_open++;
++ /* we may already have RX data, enables IRQ */
++ netif_rx_schedule(dev, &port->napi);
++ return 0;
++}
++
++static int eth_close(struct net_device *dev)
++{
++ struct port *port = netdev_priv(dev);
++ struct msg msg;
++ int buffs = RX_DESCS; /* allocated RX buffers */
++ int i;
++
++ ports_open--;
++ qmgr_disable_irq(port->plat->rxq);
++ napi_disable(&port->napi);
++ netif_stop_queue(dev);
++
++ while (queue_get_desc(RXFREE_QUEUE(port->id), port, 0) >= 0)
++ buffs--;
++
++ memset(&msg, 0, sizeof(msg));
++ msg.cmd = NPE_SETLOOPBACK_MODE;
++ msg.eth_id = port->id;
++ msg.byte3 = 1;
++ if (npe_send_recv_message(port->npe, &msg, "ETH_ENABLE_LOOPBACK"))
++ printk(KERN_CRIT "%s: unable to enable loopback\n", dev->name);
++
++ i = 0;
++ do { /* drain RX buffers */
++ while (queue_get_desc(port->plat->rxq, port, 0) >= 0)
++ buffs--;
++ if (!buffs)
++ break;
++ if (qmgr_stat_empty(TX_QUEUE(port->id))) {
++ /* we have to inject some packet */
++ struct desc *desc;
++ u32 phys;
++ int n = queue_get_desc(port->plat->txreadyq, port, 1);
++ BUG_ON(n < 0);
++ desc = tx_desc_ptr(port, n);
++ phys = tx_desc_phys(port, n);
++ desc->buf_len = desc->pkt_len = 1;
++ wmb();
++ queue_put_desc(TX_QUEUE(port->id), phys, desc);
++ }
++ udelay(1);
++ } while (++i < MAX_CLOSE_WAIT);
++
++ if (buffs)
++ printk(KERN_CRIT "%s: unable to drain RX queue, %i buffer(s)"
++ " left in NPE\n", dev->name, buffs);
++#if DEBUG_CLOSE
++ if (!buffs)
++ printk(KERN_DEBUG "Draining RX queue took %i cycles\n", i);
++#endif
++
++ buffs = TX_DESCS;
++ while (queue_get_desc(TX_QUEUE(port->id), port, 1) >= 0)
++ buffs--; /* cancel TX */
++
++ i = 0;
++ do {
++ while (queue_get_desc(port->plat->txreadyq, port, 1) >= 0)
++ buffs--;
++ if (!buffs)
++ break;
++ } while (++i < MAX_CLOSE_WAIT);
++
++ if (buffs)
++ printk(KERN_CRIT "%s: unable to drain TX queue, %i buffer(s) "
++ "left in NPE\n", dev->name, buffs);
++#if DEBUG_CLOSE
++ if (!buffs)
++ printk(KERN_DEBUG "Draining TX queues took %i cycles\n", i);
++#endif
++
++ msg.byte3 = 0;
++ if (npe_send_recv_message(port->npe, &msg, "ETH_DISABLE_LOOPBACK"))
++ printk(KERN_CRIT "%s: unable to disable loopback\n",
++ dev->name);
++
++ port->mii_bmcr = mdio_read(dev, port->plat->phy, MII_BMCR) &
++ ~(BMCR_RESET | BMCR_PDOWN); /* may have been altered */
++ mdio_write(dev, port->plat->phy, MII_BMCR,
++ port->mii_bmcr | BMCR_PDOWN);
++
++ if (!ports_open)
++ qmgr_disable_irq(TXDONE_QUEUE);
++ cancel_rearming_delayed_work(&port->mdio_thread);
++ destroy_queues(port);
++ release_queues(port);
++ return 0;
++}
++
++static int __devinit eth_init_one(struct platform_device *pdev)
++{
++ struct port *port;
++ struct net_device *dev;
++ struct eth_plat_info *plat = pdev->dev.platform_data;
++ u32 regs_phys;
++ int err;
++
++ if (!(dev = alloc_etherdev(sizeof(struct port))))
++ return -ENOMEM;
++
++ SET_NETDEV_DEV(dev, &pdev->dev);
++ port = netdev_priv(dev);
++ port->netdev = dev;
++ port->id = pdev->id;
++
++ switch (port->id) {
++ case IXP4XX_ETH_NPEA:
++ port->regs = (struct eth_regs __iomem *)IXP4XX_EthA_BASE_VIRT;
++ regs_phys = IXP4XX_EthA_BASE_PHYS;
++ break;
++ case IXP4XX_ETH_NPEB:
++ port->regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
++ regs_phys = IXP4XX_EthB_BASE_PHYS;
++ break;
++ case IXP4XX_ETH_NPEC:
++ port->regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT;
++ regs_phys = IXP4XX_EthC_BASE_PHYS;
++ break;
++ default:
++ err = -ENOSYS;
++ goto err_free;
++ }
++
++ dev->open = eth_open;
++ dev->hard_start_xmit = eth_xmit;
++ dev->stop = eth_close;
++ dev->get_stats = eth_stats;
++ dev->do_ioctl = eth_ioctl;
++ dev->set_multicast_list = eth_set_mcast_list;
++ dev->tx_queue_len = 100;
++
++ netif_napi_add(dev, &port->napi, eth_poll, NAPI_WEIGHT);
++
++ if (!(port->npe = npe_request(NPE_ID(port->id)))) {
++ err = -EIO;
++ goto err_free;
++ }
++
++ if (register_netdev(dev)) {
++ err = -EIO;
++ goto err_npe_rel;
++ }
++
++ port->mem_res = request_mem_region(regs_phys, REGS_SIZE, dev->name);
++ if (!port->mem_res) {
++ err = -EBUSY;
++ goto err_unreg;
++ }
++
++ port->plat = plat;
++ npe_port_tab[NPE_ID(port->id)] = port;
++ memcpy(dev->dev_addr, plat->hwaddr, ETH_ALEN);
++
++ platform_set_drvdata(pdev, dev);
++
++ __raw_writel(DEFAULT_CORE_CNTRL | CORE_RESET,
++ &port->regs->core_control);
++ udelay(50);
++ __raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control);
++ udelay(50);
++
++ port->mii.dev = dev;
++ port->mii.mdio_read = mdio_read;
++ port->mii.mdio_write = mdio_write;
++ port->mii.phy_id = plat->phy;
++ port->mii.phy_id_mask = 0x1F;
++ port->mii.reg_num_mask = 0x1F;
++
++ printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy,
++ npe_name(port->npe));
++
++ phy_reset(dev, plat->phy);
++ port->mii_bmcr = mdio_read(dev, plat->phy, MII_BMCR) &
++ ~(BMCR_RESET | BMCR_PDOWN);
++ mdio_write(dev, plat->phy, MII_BMCR, port->mii_bmcr | BMCR_PDOWN);
++
++ INIT_DELAYED_WORK(&port->mdio_thread, mdio_thread);
++ return 0;
++
++err_unreg:
++ unregister_netdev(dev);
++err_npe_rel:
++ npe_release(port->npe);
++err_free:
++ free_netdev(dev);
++ return err;
++}
++
++static int __devexit eth_remove_one(struct platform_device *pdev)
++{
++ struct net_device *dev = platform_get_drvdata(pdev);
++ struct port *port = netdev_priv(dev);
++
++ unregister_netdev(dev);
++ npe_port_tab[NPE_ID(port->id)] = NULL;
++ platform_set_drvdata(pdev, NULL);
++ npe_release(port->npe);
++ release_resource(port->mem_res);
++ free_netdev(dev);
++ return 0;
++}
++
++static struct platform_driver drv = {
++ .driver.name = DRV_NAME,
++ .probe = eth_init_one,
++ .remove = eth_remove_one,
++};
++
++static int __init eth_init_module(void)
++{
++ if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEB_ETH0))
++ return -ENOSYS;
++
++ /* All MII PHY accesses use NPE-B Ethernet registers */
++ spin_lock_init(&mdio_lock);
++ mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
++ __raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control);
++
++ return platform_driver_register(&drv);
++}
++
++static void __exit eth_cleanup_module(void)
++{
++ platform_driver_unregister(&drv);
++}
++
++MODULE_AUTHOR("Krzysztof Halasa");
++MODULE_DESCRIPTION("Intel IXP4xx Ethernet driver");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:ixp4xx_eth");
++module_init(eth_init_module);
++module_exit(eth_cleanup_module);
diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
index 24d81f9..7e874d4 100644
--- a/drivers/net/at1700.c
@@ -449096,634 +624229,3301 @@
+ * 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
++ * NEEDS TESTING:
++ * VLAN
++ * multicast
++ * promiscuous mode
++ * interrupt coalescing
++ * SMP torture testing
++ */
++
++#include <asm/atomic.h>
++#include <asm/byteorder.h>
++
++#include <linux/compiler.h>
++#include <linux/crc32.h>
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/etherdevice.h>
++#include <linux/hardirq.h>
++#include <linux/if_ether.h>
++#include <linux/if_vlan.h>
++#include <linux/in.h>
++#include <linux/interrupt.h>
++#include <linux/ip.h>
++#include <linux/irqflags.h>
++#include <linux/irqreturn.h>
++#include <linux/jiffies.h>
++#include <linux/mii.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/net.h>
++#include <linux/netdevice.h>
++#include <linux/pci.h>
++#include <linux/pci_ids.h>
++#include <linux/pm.h>
++#include <linux/skbuff.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++#include <linux/tcp.h>
++#include <linux/timer.h>
++#include <linux/types.h>
++#include <linux/workqueue.h>
++
++#include <net/checksum.h>
++
++#include "atl1.h"
++
++/* Temporary hack for merging atl1 and atl2 */
++#include "atlx.c"
++
++/*
++ * This is the only thing that needs to be changed to adjust the
++ * maximum number of ports that the driver can manage.
++ */
++#define ATL1_MAX_NIC 4
++
++#define OPTION_UNSET -1
++#define OPTION_DISABLED 0
++#define OPTION_ENABLED 1
++
++#define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET }
++
++/*
++ * Interrupt Moderate Timer in units of 2 us
++ *
++ * Valid Range: 10-65535
++ *
++ * Default Value: 100 (200us)
++ */
++static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
++static int num_int_mod_timer;
++module_param_array_named(int_mod_timer, int_mod_timer, int,
++ &num_int_mod_timer, 0);
++MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer");
++
++#define DEFAULT_INT_MOD_CNT 100 /* 200us */
++#define MAX_INT_MOD_CNT 65000
++#define MIN_INT_MOD_CNT 50
++
++struct atl1_option {
++ enum { enable_option, range_option, list_option } type;
++ char *name;
++ char *err;
++ int def;
++ union {
++ struct { /* range_option info */
++ int min;
++ int max;
++ } r;
++ struct { /* list_option info */
++ int nr;
++ struct atl1_opt_list {
++ int i;
++ char *str;
++ } *p;
++ } l;
++ } arg;
++};
++
++static int __devinit atl1_validate_option(int *value, struct atl1_option *opt,
++ struct pci_dev *pdev)
++{
++ if (*value == OPTION_UNSET) {
++ *value = opt->def;
++ return 0;
++ }
++
++ switch (opt->type) {
++ case enable_option:
++ switch (*value) {
++ case OPTION_ENABLED:
++ dev_info(&pdev->dev, "%s enabled\n", opt->name);
++ return 0;
++ case OPTION_DISABLED:
++ dev_info(&pdev->dev, "%s disabled\n", opt->name);
++ return 0;
++ }
++ break;
++ case range_option:
++ if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
++ dev_info(&pdev->dev, "%s set to %i\n", opt->name,
++ *value);
++ return 0;
++ }
++ break;
++ case list_option:{
++ int i;
++ struct atl1_opt_list *ent;
++
++ for (i = 0; i < opt->arg.l.nr; i++) {
++ ent = &opt->arg.l.p[i];
++ if (*value == ent->i) {
++ if (ent->str[0] != '\0')
++ dev_info(&pdev->dev, "%s\n",
++ ent->str);
++ return 0;
++ }
++ }
++ }
++ break;
++
++ default:
++ break;
++ }
++
++ dev_info(&pdev->dev, "invalid %s specified (%i) %s\n",
++ opt->name, *value, opt->err);
++ *value = opt->def;
++ return -1;
++}
++
++/*
++ * atl1_check_options - Range Checking for Command Line Parameters
++ * @adapter: board private structure
++ *
++ * This routine checks all command line parameters for valid user
++ * input. If an invalid value is given, or if no user specified
++ * value exists, a default value is used. The final value is stored
++ * in a variable in the adapter structure.
++ */
++void __devinit atl1_check_options(struct atl1_adapter *adapter)
++{
++ struct pci_dev *pdev = adapter->pdev;
++ int bd = adapter->bd_number;
++ if (bd >= ATL1_MAX_NIC) {
++ dev_notice(&pdev->dev, "no configuration for board#%i\n", bd);
++ dev_notice(&pdev->dev, "using defaults for all values\n");
++ }
++ { /* Interrupt Moderate Timer */
++ struct atl1_option opt = {
++ .type = range_option,
++ .name = "Interrupt Moderator Timer",
++ .err = "using default of "
++ __MODULE_STRING(DEFAULT_INT_MOD_CNT),
++ .def = DEFAULT_INT_MOD_CNT,
++ .arg = {.r = {.min = MIN_INT_MOD_CNT,
++ .max = MAX_INT_MOD_CNT} }
++ };
++ int val;
++ if (num_int_mod_timer > bd) {
++ val = int_mod_timer[bd];
++ atl1_validate_option(&val, &opt, pdev);
++ adapter->imt = (u16) val;
++ } else
++ adapter->imt = (u16) (opt.def);
++ }
++}
++
++/*
++ * atl1_pci_tbl - PCI Device ID Table
++ */
++static const struct pci_device_id atl1_pci_tbl[] = {
++ {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)},
++ /* required last entry */
++ {0,}
++};
++MODULE_DEVICE_TABLE(pci, atl1_pci_tbl);
++
++static const u32 atl1_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
++ NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP;
++
++static int debug = -1;
++module_param(debug, int, 0);
++MODULE_PARM_DESC(debug, "Message level (0=none,...,16=all)");
++
++/*
++ * Reset the transmit and receive units; mask and clear all interrupts.
++ * hw - Struct containing variables accessed by shared code
++ * return : 0 or idle status (if error)
++ */
++static s32 atl1_reset_hw(struct atl1_hw *hw)
++{
++ struct pci_dev *pdev = hw->back->pdev;
++ struct atl1_adapter *adapter = hw->back;
++ u32 icr;
++ int i;
++
++ /*
++ * Clear Interrupt mask to stop board from generating
++ * interrupts & Clear any pending interrupt events
++ */
++ /*
++ * iowrite32(0, hw->hw_addr + REG_IMR);
++ * iowrite32(0xffffffff, hw->hw_addr + REG_ISR);
++ */
++
++ /*
++ * Issue Soft Reset to the MAC. This will reset the chip's
++ * transmit, receive, DMA. It will not effect
++ * the current PCI configuration. The global reset bit is self-
++ * clearing, and should clear within a microsecond.
++ */
++ iowrite32(MASTER_CTRL_SOFT_RST, hw->hw_addr + REG_MASTER_CTRL);
++ ioread32(hw->hw_addr + REG_MASTER_CTRL);
++
++ iowrite16(1, hw->hw_addr + REG_PHY_ENABLE);
++ ioread16(hw->hw_addr + REG_PHY_ENABLE);
++
++ /* delay about 1ms */
++ msleep(1);
++
++ /* Wait at least 10ms for All module to be Idle */
++ for (i = 0; i < 10; i++) {
++ icr = ioread32(hw->hw_addr + REG_IDLE_STATUS);
++ if (!icr)
++ break;
++ /* delay 1 ms */
++ msleep(1);
++ /* FIXME: still the right way to do this? */
++ cpu_relax();
++ }
++
++ if (icr) {
++ if (netif_msg_hw(adapter))
++ dev_dbg(&pdev->dev, "ICR = 0x%x\n", icr);
++ return icr;
++ }
++
++ return 0;
++}
++
++/* function about EEPROM
++ *
++ * check_eeprom_exist
++ * return 0 if eeprom exist
++ */
++static int atl1_check_eeprom_exist(struct atl1_hw *hw)
++{
++ u32 value;
++ value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
++ if (value & SPI_FLASH_CTRL_EN_VPD) {
++ value &= ~SPI_FLASH_CTRL_EN_VPD;
++ iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
++ }
++
++ value = ioread16(hw->hw_addr + REG_PCIE_CAP_LIST);
++ return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
++}
++
++static bool atl1_read_eeprom(struct atl1_hw *hw, u32 offset, u32 *p_value)
++{
++ int i;
++ u32 control;
++
++ if (offset & 3)
++ /* address do not align */
++ return false;
++
++ iowrite32(0, hw->hw_addr + REG_VPD_DATA);
++ control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
++ iowrite32(control, hw->hw_addr + REG_VPD_CAP);
++ ioread32(hw->hw_addr + REG_VPD_CAP);
++
++ for (i = 0; i < 10; i++) {
++ msleep(2);
++ control = ioread32(hw->hw_addr + REG_VPD_CAP);
++ if (control & VPD_CAP_VPD_FLAG)
++ break;
++ }
++ if (control & VPD_CAP_VPD_FLAG) {
++ *p_value = ioread32(hw->hw_addr + REG_VPD_DATA);
++ return true;
++ }
++ /* timeout */
++ return false;
++}
++
++/*
++ * Reads the value from a PHY register
++ * hw - Struct containing variables accessed by shared code
++ * reg_addr - address of the PHY register to read
++ */
++s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data)
++{
++ u32 val;
++ int i;
++
++ val = ((u32) (reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
++ MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | MDIO_CLK_25_4 <<
++ MDIO_CLK_SEL_SHIFT;
++ iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
++ ioread32(hw->hw_addr + REG_MDIO_CTRL);
++
++ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
++ udelay(2);
++ val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
++ if (!(val & (MDIO_START | MDIO_BUSY)))
++ break;
++ }
++ if (!(val & (MDIO_START | MDIO_BUSY))) {
++ *phy_data = (u16) val;
++ return 0;
++ }
++ return ATLX_ERR_PHY;
++}
++
++#define CUSTOM_SPI_CS_SETUP 2
++#define CUSTOM_SPI_CLK_HI 2
++#define CUSTOM_SPI_CLK_LO 2
++#define CUSTOM_SPI_CS_HOLD 2
++#define CUSTOM_SPI_CS_HI 3
++
++static bool atl1_spi_read(struct atl1_hw *hw, u32 addr, u32 *buf)
++{
++ int i;
++ u32 value;
++
++ iowrite32(0, hw->hw_addr + REG_SPI_DATA);
++ iowrite32(addr, hw->hw_addr + REG_SPI_ADDR);
++
++ value = SPI_FLASH_CTRL_WAIT_READY |
++ (CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) <<
++ SPI_FLASH_CTRL_CS_SETUP_SHIFT | (CUSTOM_SPI_CLK_HI &
++ SPI_FLASH_CTRL_CLK_HI_MASK) <<
++ SPI_FLASH_CTRL_CLK_HI_SHIFT | (CUSTOM_SPI_CLK_LO &
++ SPI_FLASH_CTRL_CLK_LO_MASK) <<
++ SPI_FLASH_CTRL_CLK_LO_SHIFT | (CUSTOM_SPI_CS_HOLD &
++ SPI_FLASH_CTRL_CS_HOLD_MASK) <<
++ SPI_FLASH_CTRL_CS_HOLD_SHIFT | (CUSTOM_SPI_CS_HI &
++ SPI_FLASH_CTRL_CS_HI_MASK) <<
++ SPI_FLASH_CTRL_CS_HI_SHIFT | (1 & SPI_FLASH_CTRL_INS_MASK) <<
++ SPI_FLASH_CTRL_INS_SHIFT;
++
++ iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
++
++ value |= SPI_FLASH_CTRL_START;
++ iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
++ ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
++
++ for (i = 0; i < 10; i++) {
++ msleep(1);
++ value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
++ if (!(value & SPI_FLASH_CTRL_START))
++ break;
++ }
++
++ if (value & SPI_FLASH_CTRL_START)
++ return false;
++
++ *buf = ioread32(hw->hw_addr + REG_SPI_DATA);
++
++ return true;
++}
++
++/*
++ * get_permanent_address
++ * return 0 if get valid mac address,
++ */
++static int atl1_get_permanent_address(struct atl1_hw *hw)
++{
++ u32 addr[2];
++ u32 i, control;
++ u16 reg;
++ u8 eth_addr[ETH_ALEN];
++ bool key_valid;
++
++ if (is_valid_ether_addr(hw->perm_mac_addr))
++ return 0;
++
++ /* init */
++ addr[0] = addr[1] = 0;
++
++ if (!atl1_check_eeprom_exist(hw)) {
++ reg = 0;
++ key_valid = false;
++ /* Read out all EEPROM content */
++ i = 0;
++ while (1) {
++ if (atl1_read_eeprom(hw, i + 0x100, &control)) {
++ if (key_valid) {
++ if (reg == REG_MAC_STA_ADDR)
++ addr[0] = control;
++ else if (reg == (REG_MAC_STA_ADDR + 4))
++ addr[1] = control;
++ key_valid = false;
++ } else if ((control & 0xff) == 0x5A) {
++ key_valid = true;
++ reg = (u16) (control >> 16);
++ } else
++ break;
++ } else
++ /* read error */
++ break;
++ i += 4;
++ }
++
++ *(u32 *) ð_addr[2] = swab32(addr[0]);
++ *(u16 *) ð_addr[0] = swab16(*(u16 *) &addr[1]);
++ if (is_valid_ether_addr(eth_addr)) {
++ memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
++ return 0;
++ }
++ return 1;
++ }
++
++ /* see if SPI FLAGS exist ? */
++ addr[0] = addr[1] = 0;
++ reg = 0;
++ key_valid = false;
++ i = 0;
++ while (1) {
++ if (atl1_spi_read(hw, i + 0x1f000, &control)) {
++ if (key_valid) {
++ if (reg == REG_MAC_STA_ADDR)
++ addr[0] = control;
++ else if (reg == (REG_MAC_STA_ADDR + 4))
++ addr[1] = control;
++ key_valid = false;
++ } else if ((control & 0xff) == 0x5A) {
++ key_valid = true;
++ reg = (u16) (control >> 16);
++ } else
++ /* data end */
++ break;
++ } else
++ /* read error */
++ break;
++ i += 4;
++ }
++
++ *(u32 *) ð_addr[2] = swab32(addr[0]);
++ *(u16 *) ð_addr[0] = swab16(*(u16 *) &addr[1]);
++ if (is_valid_ether_addr(eth_addr)) {
++ memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
++ return 0;
++ }
++
++ /*
++ * On some motherboards, the MAC address is written by the
++ * BIOS directly to the MAC register during POST, and is
++ * not stored in eeprom. If all else thus far has failed
++ * to fetch the permanent MAC address, try reading it directly.
++ */
++ addr[0] = ioread32(hw->hw_addr + REG_MAC_STA_ADDR);
++ addr[1] = ioread16(hw->hw_addr + (REG_MAC_STA_ADDR + 4));
++ *(u32 *) ð_addr[2] = swab32(addr[0]);
++ *(u16 *) ð_addr[0] = swab16(*(u16 *) &addr[1]);
++ if (is_valid_ether_addr(eth_addr)) {
++ memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
++ return 0;
++ }
++
++ return 1;
++}
++
++/*
++ * Reads the adapter's MAC address from the EEPROM
++ * hw - Struct containing variables accessed by shared code
++ */
++s32 atl1_read_mac_addr(struct atl1_hw *hw)
++{
++ u16 i;
++
++ if (atl1_get_permanent_address(hw))
++ random_ether_addr(hw->perm_mac_addr);
++
++ for (i = 0; i < ETH_ALEN; i++)
++ hw->mac_addr[i] = hw->perm_mac_addr[i];
++ return 0;
++}
++
++/*
++ * Hashes an address to determine its location in the multicast table
++ * hw - Struct containing variables accessed by shared code
++ * mc_addr - the multicast address to hash
++ *
++ * atl1_hash_mc_addr
++ * purpose
++ * set hash value for a multicast address
++ * hash calcu processing :
++ * 1. calcu 32bit CRC for multicast address
++ * 2. reverse crc with MSB to LSB
++ */
++u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr)
++{
++ u32 crc32, value = 0;
++ int i;
++
++ crc32 = ether_crc_le(6, mc_addr);
++ for (i = 0; i < 32; i++)
++ value |= (((crc32 >> i) & 1) << (31 - i));
++
++ return value;
++}
++
++/*
++ * Sets the bit in the multicast table corresponding to the hash value.
++ * hw - Struct containing variables accessed by shared code
++ * hash_value - Multicast address hash value
++ */
++void atl1_hash_set(struct atl1_hw *hw, u32 hash_value)
++{
++ u32 hash_bit, hash_reg;
++ u32 mta;
++
++ /*
++ * The HASH Table is a register array of 2 32-bit registers.
++ * It is treated like an array of 64 bits. We want to set
++ * bit BitArray[hash_value]. So we figure out what register
++ * the bit is in, read it, OR in the new bit, then write
++ * back the new value. The register is determined by the
++ * upper 7 bits of the hash value and the bit within that
++ * register are determined by the lower 5 bits of the value.
++ */
++ hash_reg = (hash_value >> 31) & 0x1;
++ hash_bit = (hash_value >> 26) & 0x1F;
++ mta = ioread32((hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
++ mta |= (1 << hash_bit);
++ iowrite32(mta, (hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
++}
++
++/*
++ * Writes a value to a PHY register
++ * hw - Struct containing variables accessed by shared code
++ * reg_addr - address of the PHY register to write
++ * data - data to write to the PHY
++ */
++static s32 atl1_write_phy_reg(struct atl1_hw *hw, u32 reg_addr, u16 phy_data)
++{
++ int i;
++ u32 val;
++
++ val = ((u32) (phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
++ (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
++ MDIO_SUP_PREAMBLE |
++ MDIO_START | MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
++ iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
++ ioread32(hw->hw_addr + REG_MDIO_CTRL);
++
++ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
++ udelay(2);
++ val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
++ if (!(val & (MDIO_START | MDIO_BUSY)))
++ break;
++ }
++
++ if (!(val & (MDIO_START | MDIO_BUSY)))
++ return 0;
++
++ return ATLX_ERR_PHY;
++}
++
++/*
++ * Make L001's PHY out of Power Saving State (bug)
++ * hw - Struct containing variables accessed by shared code
++ * when power on, L001's PHY always on Power saving State
++ * (Gigabit Link forbidden)
++ */
++static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw)
++{
++ s32 ret;
++ ret = atl1_write_phy_reg(hw, 29, 0x0029);
++ if (ret)
++ return ret;
++ return atl1_write_phy_reg(hw, 30, 0);
++}
++
++/*
++ *TODO: do something or get rid of this
++ */
++#ifdef CONFIG_PM
++static s32 atl1_phy_enter_power_saving(struct atl1_hw *hw)
++{
++/* s32 ret_val;
++ * u16 phy_data;
++ */
++
++/*
++ ret_val = atl1_write_phy_reg(hw, ...);
++ ret_val = atl1_write_phy_reg(hw, ...);
++ ....
++*/
++ return 0;
++}
++#endif
++
++/*
++ * Resets the PHY and make all config validate
++ * hw - Struct containing variables accessed by shared code
++ *
++ * Sets bit 15 and 12 of the MII Control regiser (for F001 bug)
++ */
++static s32 atl1_phy_reset(struct atl1_hw *hw)
++{
++ struct pci_dev *pdev = hw->back->pdev;
++ struct atl1_adapter *adapter = hw->back;
++ s32 ret_val;
++ u16 phy_data;
++
++ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
++ hw->media_type == MEDIA_TYPE_1000M_FULL)
++ phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
++ else {
++ switch (hw->media_type) {
++ case MEDIA_TYPE_100M_FULL:
++ phy_data =
++ MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
++ MII_CR_RESET;
++ break;
++ case MEDIA_TYPE_100M_HALF:
++ phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
++ break;
++ case MEDIA_TYPE_10M_FULL:
++ phy_data =
++ MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
++ break;
++ default:
++ /* MEDIA_TYPE_10M_HALF: */
++ phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
++ break;
++ }
++ }
++
++ ret_val = atl1_write_phy_reg(hw, MII_BMCR, phy_data);
++ if (ret_val) {
++ u32 val;
++ int i;
++ /* pcie serdes link may be down! */
++ if (netif_msg_hw(adapter))
++ dev_dbg(&pdev->dev, "pcie phy link down\n");
++
++ for (i = 0; i < 25; i++) {
++ msleep(1);
++ val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
++ if (!(val & (MDIO_START | MDIO_BUSY)))
++ break;
++ }
++
++ if ((val & (MDIO_START | MDIO_BUSY)) != 0) {
++ if (netif_msg_hw(adapter))
++ dev_warn(&pdev->dev,
++ "pcie link down at least 25ms\n");
++ return ret_val;
++ }
++ }
++ return 0;
++}
++
++/*
++ * Configures PHY autoneg and flow control advertisement settings
++ * hw - Struct containing variables accessed by shared code
++ */
++static s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw)
++{
++ s32 ret_val;
++ s16 mii_autoneg_adv_reg;
++ s16 mii_1000t_ctrl_reg;
++
++ /* Read the MII Auto-Neg Advertisement Register (Address 4). */
++ mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
++
++ /* Read the MII 1000Base-T Control Register (Address 9). */
++ mii_1000t_ctrl_reg = MII_ATLX_CR_1000T_DEFAULT_CAP_MASK;
++
++ /*
++ * First we clear all the 10/100 mb speed bits in the Auto-Neg
++ * Advertisement Register (Address 4) and the 1000 mb speed bits in
++ * the 1000Base-T Control Register (Address 9).
++ */
++ mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
++ mii_1000t_ctrl_reg &= ~MII_ATLX_CR_1000T_SPEED_MASK;
++
++ /*
++ * Need to parse media_type and set up
++ * the appropriate PHY registers.
++ */
++ switch (hw->media_type) {
++ case MEDIA_TYPE_AUTO_SENSOR:
++ mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS |
++ MII_AR_10T_FD_CAPS |
++ MII_AR_100TX_HD_CAPS |
++ MII_AR_100TX_FD_CAPS);
++ mii_1000t_ctrl_reg |= MII_ATLX_CR_1000T_FD_CAPS;
++ break;
++
++ case MEDIA_TYPE_1000M_FULL:
++ mii_1000t_ctrl_reg |= MII_ATLX_CR_1000T_FD_CAPS;
++ break;
++
++ case MEDIA_TYPE_100M_FULL:
++ mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;
++ break;
++
++ case MEDIA_TYPE_100M_HALF:
++ mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;
++ break;
++
++ case MEDIA_TYPE_10M_FULL:
++ mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;
++ break;
++
++ default:
++ mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;
++ break;
++ }
++
++ /* flow control fixed to enable all */
++ mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
++
++ hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
++ hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
++
++ ret_val = atl1_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
++ if (ret_val)
++ return ret_val;
++
++ ret_val = atl1_write_phy_reg(hw, MII_ATLX_CR, mii_1000t_ctrl_reg);
++ if (ret_val)
++ return ret_val;
++
++ return 0;
++}
++
++/*
++ * Configures link settings.
++ * hw - Struct containing variables accessed by shared code
++ * Assumes the hardware has previously been reset and the
++ * transmitter and receiver are not enabled.
++ */
++static s32 atl1_setup_link(struct atl1_hw *hw)
++{
++ struct pci_dev *pdev = hw->back->pdev;
++ struct atl1_adapter *adapter = hw->back;
++ s32 ret_val;
++
++ /*
++ * Options:
++ * PHY will advertise value(s) parsed from
++ * autoneg_advertised and fc
++ * no matter what autoneg is , We will not wait link result.
++ */
++ ret_val = atl1_phy_setup_autoneg_adv(hw);
++ if (ret_val) {
++ if (netif_msg_link(adapter))
++ dev_dbg(&pdev->dev,
++ "error setting up autonegotiation\n");
++ return ret_val;
++ }
++ /* SW.Reset , En-Auto-Neg if needed */
++ ret_val = atl1_phy_reset(hw);
++ if (ret_val) {
++ if (netif_msg_link(adapter))
++ dev_dbg(&pdev->dev, "error resetting phy\n");
++ return ret_val;
++ }
++ hw->phy_configured = true;
++ return ret_val;
++}
++
++static void atl1_init_flash_opcode(struct atl1_hw *hw)
++{
++ if (hw->flash_vendor >= ARRAY_SIZE(flash_table))
++ /* Atmel */
++ hw->flash_vendor = 0;
++
++ /* Init OP table */
++ iowrite8(flash_table[hw->flash_vendor].cmd_program,
++ hw->hw_addr + REG_SPI_FLASH_OP_PROGRAM);
++ iowrite8(flash_table[hw->flash_vendor].cmd_sector_erase,
++ hw->hw_addr + REG_SPI_FLASH_OP_SC_ERASE);
++ iowrite8(flash_table[hw->flash_vendor].cmd_chip_erase,
++ hw->hw_addr + REG_SPI_FLASH_OP_CHIP_ERASE);
++ iowrite8(flash_table[hw->flash_vendor].cmd_rdid,
++ hw->hw_addr + REG_SPI_FLASH_OP_RDID);
++ iowrite8(flash_table[hw->flash_vendor].cmd_wren,
++ hw->hw_addr + REG_SPI_FLASH_OP_WREN);
++ iowrite8(flash_table[hw->flash_vendor].cmd_rdsr,
++ hw->hw_addr + REG_SPI_FLASH_OP_RDSR);
++ iowrite8(flash_table[hw->flash_vendor].cmd_wrsr,
++ hw->hw_addr + REG_SPI_FLASH_OP_WRSR);
++ iowrite8(flash_table[hw->flash_vendor].cmd_read,
++ hw->hw_addr + REG_SPI_FLASH_OP_READ);
++}
++
++/*
++ * Performs basic configuration of the adapter.
++ * hw - Struct containing variables accessed by shared code
++ * Assumes that the controller has previously been reset and is in a
++ * post-reset uninitialized state. Initializes multicast table,
++ * and Calls routines to setup link
++ * Leaves the transmit and receive units disabled and uninitialized.
++ */
++static s32 atl1_init_hw(struct atl1_hw *hw)
++{
++ u32 ret_val = 0;
++
++ /* Zero out the Multicast HASH table */
++ iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
++ /* clear the old settings from the multicast hash table */
++ iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
++
++ atl1_init_flash_opcode(hw);
++
++ if (!hw->phy_configured) {
++ /* enable GPHY LinkChange Interrrupt */
++ ret_val = atl1_write_phy_reg(hw, 18, 0xC00);
++ if (ret_val)
++ return ret_val;
++ /* make PHY out of power-saving state */
++ ret_val = atl1_phy_leave_power_saving(hw);
++ if (ret_val)
++ return ret_val;
++ /* Call a subroutine to configure the link */
++ ret_val = atl1_setup_link(hw);
++ }
++ return ret_val;
++}
++
++/*
++ * Detects the current speed and duplex settings of the hardware.
++ * hw - Struct containing variables accessed by shared code
++ * speed - Speed of the connection
++ * duplex - Duplex setting of the connection
++ */
++static s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex)
++{
++ struct pci_dev *pdev = hw->back->pdev;
++ struct atl1_adapter *adapter = hw->back;
++ s32 ret_val;
++ u16 phy_data;
++
++ /* ; --- Read PHY Specific Status Register (17) */
++ ret_val = atl1_read_phy_reg(hw, MII_ATLX_PSSR, &phy_data);
++ if (ret_val)
++ return ret_val;
++
++ if (!(phy_data & MII_ATLX_PSSR_SPD_DPLX_RESOLVED))
++ return ATLX_ERR_PHY_RES;
++
++ switch (phy_data & MII_ATLX_PSSR_SPEED) {
++ case MII_ATLX_PSSR_1000MBS:
++ *speed = SPEED_1000;
++ break;
++ case MII_ATLX_PSSR_100MBS:
++ *speed = SPEED_100;
++ break;
++ case MII_ATLX_PSSR_10MBS:
++ *speed = SPEED_10;
++ break;
++ default:
++ if (netif_msg_hw(adapter))
++ dev_dbg(&pdev->dev, "error getting speed\n");
++ return ATLX_ERR_PHY_SPEED;
++ break;
++ }
++ if (phy_data & MII_ATLX_PSSR_DPLX)
++ *duplex = FULL_DUPLEX;
++ else
++ *duplex = HALF_DUPLEX;
++
++ return 0;
++}
++
++void atl1_set_mac_addr(struct atl1_hw *hw)
++{
++ u32 value;
++ /*
++ * 00-0B-6A-F6-00-DC
++ * 0: 6AF600DC 1: 000B
++ * low dword
++ */
++ value = (((u32) hw->mac_addr[2]) << 24) |
++ (((u32) hw->mac_addr[3]) << 16) |
++ (((u32) hw->mac_addr[4]) << 8) | (((u32) hw->mac_addr[5]));
++ iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
++ /* high dword */
++ value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
++ iowrite32(value, (hw->hw_addr + REG_MAC_STA_ADDR) + (1 << 2));
++}
++
++/*
++ * atl1_sw_init - Initialize general software structures (struct atl1_adapter)
++ * @adapter: board private structure to initialize
++ *
++ * atl1_sw_init initializes the Adapter private data structure.
++ * Fields are initialized based on PCI device information and
++ * OS network device settings (MTU size).
++ */
++static int __devinit atl1_sw_init(struct atl1_adapter *adapter)
++{
++ struct atl1_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++
++ hw->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
++ hw->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
++
++ adapter->wol = 0;
++ adapter->rx_buffer_len = (hw->max_frame_size + 7) & ~7;
++ adapter->ict = 50000; /* 100ms */
++ adapter->link_speed = SPEED_0; /* hardware init */
++ adapter->link_duplex = FULL_DUPLEX;
++
++ hw->phy_configured = false;
++ hw->preamble_len = 7;
++ hw->ipgt = 0x60;
++ hw->min_ifg = 0x50;
++ hw->ipgr1 = 0x40;
++ hw->ipgr2 = 0x60;
++ hw->max_retry = 0xf;
++ hw->lcol = 0x37;
++ hw->jam_ipg = 7;
++ hw->rfd_burst = 8;
++ hw->rrd_burst = 8;
++ hw->rfd_fetch_gap = 1;
++ hw->rx_jumbo_th = adapter->rx_buffer_len / 8;
++ hw->rx_jumbo_lkah = 1;
++ hw->rrd_ret_timer = 16;
++ hw->tpd_burst = 4;
++ hw->tpd_fetch_th = 16;
++ hw->txf_burst = 0x100;
++ hw->tx_jumbo_task_th = (hw->max_frame_size + 7) >> 3;
++ hw->tpd_fetch_gap = 1;
++ hw->rcb_value = atl1_rcb_64;
++ hw->dma_ord = atl1_dma_ord_enh;
++ hw->dmar_block = atl1_dma_req_256;
++ hw->dmaw_block = atl1_dma_req_256;
++ hw->cmb_rrd = 4;
++ hw->cmb_tpd = 4;
++ hw->cmb_rx_timer = 1; /* about 2us */
++ hw->cmb_tx_timer = 1; /* about 2us */
++ hw->smb_timer = 100000; /* about 200ms */
++
++ spin_lock_init(&adapter->lock);
++ spin_lock_init(&adapter->mb_lock);
++
++ return 0;
++}
++
++static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ u16 result;
++
++ atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
++
++ return result;
++}
++
++static void mdio_write(struct net_device *netdev, int phy_id, int reg_num,
++ int val)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++
++ atl1_write_phy_reg(&adapter->hw, reg_num, val);
++}
++
++/*
++ * atl1_mii_ioctl -
++ * @netdev:
++ * @ifreq:
++ * @cmd:
++ */
++static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ unsigned long flags;
++ int retval;
++
++ if (!netif_running(netdev))
++ return -EINVAL;
++
++ spin_lock_irqsave(&adapter->lock, flags);
++ retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
++ spin_unlock_irqrestore(&adapter->lock, flags);
++
++ return retval;
++}
++
++/*
++ * atl1_setup_mem_resources - allocate Tx / RX descriptor resources
++ * @adapter: board private structure
++ *
++ * Return 0 on success, negative on failure
++ */
++static s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
++{
++ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
++ struct atl1_ring_header *ring_header = &adapter->ring_header;
++ struct pci_dev *pdev = adapter->pdev;
++ int size;
++ u8 offset = 0;
++
++ size = sizeof(struct atl1_buffer) * (tpd_ring->count + rfd_ring->count);
++ tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
++ if (unlikely(!tpd_ring->buffer_info)) {
++ if (netif_msg_drv(adapter))
++ dev_err(&pdev->dev, "kzalloc failed , size = D%d\n",
++ size);
++ goto err_nomem;
++ }
++ rfd_ring->buffer_info =
++ (struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count);
++
++ /*
++ * real ring DMA buffer
++ * each ring/block may need up to 8 bytes for alignment, hence the
++ * additional 40 bytes tacked onto the end.
++ */
++ ring_header->size = size =
++ sizeof(struct tx_packet_desc) * tpd_ring->count
++ + sizeof(struct rx_free_desc) * rfd_ring->count
++ + sizeof(struct rx_return_desc) * rrd_ring->count
++ + sizeof(struct coals_msg_block)
++ + sizeof(struct stats_msg_block)
++ + 40;
++
++ ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
++ &ring_header->dma);
++ if (unlikely(!ring_header->desc)) {
++ if (netif_msg_drv(adapter))
++ dev_err(&pdev->dev, "pci_alloc_consistent failed\n");
++ goto err_nomem;
++ }
++
++ memset(ring_header->desc, 0, ring_header->size);
++
++ /* init TPD ring */
++ tpd_ring->dma = ring_header->dma;
++ offset = (tpd_ring->dma & 0x7) ? (8 - (ring_header->dma & 0x7)) : 0;
++ tpd_ring->dma += offset;
++ tpd_ring->desc = (u8 *) ring_header->desc + offset;
++ tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count;
++
++ /* init RFD ring */
++ rfd_ring->dma = tpd_ring->dma + tpd_ring->size;
++ offset = (rfd_ring->dma & 0x7) ? (8 - (rfd_ring->dma & 0x7)) : 0;
++ rfd_ring->dma += offset;
++ rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset);
++ rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count;
++
++
++ /* init RRD ring */
++ rrd_ring->dma = rfd_ring->dma + rfd_ring->size;
++ offset = (rrd_ring->dma & 0x7) ? (8 - (rrd_ring->dma & 0x7)) : 0;
++ rrd_ring->dma += offset;
++ rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset);
++ rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count;
++
++
++ /* init CMB */
++ adapter->cmb.dma = rrd_ring->dma + rrd_ring->size;
++ offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0;
++ adapter->cmb.dma += offset;
++ adapter->cmb.cmb = (struct coals_msg_block *)
++ ((u8 *) rrd_ring->desc + (rrd_ring->size + offset));
++
++ /* init SMB */
++ adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block);
++ offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0;
++ adapter->smb.dma += offset;
++ adapter->smb.smb = (struct stats_msg_block *)
++ ((u8 *) adapter->cmb.cmb +
++ (sizeof(struct coals_msg_block) + offset));
++
++ return 0;
++
++err_nomem:
++ kfree(tpd_ring->buffer_info);
++ return -ENOMEM;
++}
++
++static void atl1_init_ring_ptrs(struct atl1_adapter *adapter)
++{
++ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
++
++ atomic_set(&tpd_ring->next_to_use, 0);
++ atomic_set(&tpd_ring->next_to_clean, 0);
++
++ rfd_ring->next_to_clean = 0;
++ atomic_set(&rfd_ring->next_to_use, 0);
++
++ rrd_ring->next_to_use = 0;
++ atomic_set(&rrd_ring->next_to_clean, 0);
++}
++
++/*
++ * atl1_clean_rx_ring - Free RFD Buffers
++ * @adapter: board private structure
++ */
++static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
++{
++ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
++ struct atl1_buffer *buffer_info;
++ struct pci_dev *pdev = adapter->pdev;
++ unsigned long size;
++ unsigned int i;
++
++ /* Free all the Rx ring sk_buffs */
++ for (i = 0; i < rfd_ring->count; i++) {
++ buffer_info = &rfd_ring->buffer_info[i];
++ if (buffer_info->dma) {
++ pci_unmap_page(pdev, buffer_info->dma,
++ buffer_info->length, PCI_DMA_FROMDEVICE);
++ buffer_info->dma = 0;
++ }
++ if (buffer_info->skb) {
++ dev_kfree_skb(buffer_info->skb);
++ buffer_info->skb = NULL;
++ }
++ }
++
++ size = sizeof(struct atl1_buffer) * rfd_ring->count;
++ memset(rfd_ring->buffer_info, 0, size);
++
++ /* Zero out the descriptor ring */
++ memset(rfd_ring->desc, 0, rfd_ring->size);
++
++ rfd_ring->next_to_clean = 0;
++ atomic_set(&rfd_ring->next_to_use, 0);
++
++ rrd_ring->next_to_use = 0;
++ atomic_set(&rrd_ring->next_to_clean, 0);
++}
++
++/*
++ * atl1_clean_tx_ring - Free Tx Buffers
++ * @adapter: board private structure
++ */
++static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
++{
++ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++ struct atl1_buffer *buffer_info;
++ struct pci_dev *pdev = adapter->pdev;
++ unsigned long size;
++ unsigned int i;
++
++ /* Free all the Tx ring sk_buffs */
++ for (i = 0; i < tpd_ring->count; i++) {
++ buffer_info = &tpd_ring->buffer_info[i];
++ if (buffer_info->dma) {
++ pci_unmap_page(pdev, buffer_info->dma,
++ buffer_info->length, PCI_DMA_TODEVICE);
++ buffer_info->dma = 0;
++ }
++ }
++
++ for (i = 0; i < tpd_ring->count; i++) {
++ buffer_info = &tpd_ring->buffer_info[i];
++ if (buffer_info->skb) {
++ dev_kfree_skb_any(buffer_info->skb);
++ buffer_info->skb = NULL;
++ }
++ }
++
++ size = sizeof(struct atl1_buffer) * tpd_ring->count;
++ memset(tpd_ring->buffer_info, 0, size);
++
++ /* Zero out the descriptor ring */
++ memset(tpd_ring->desc, 0, tpd_ring->size);
++
++ atomic_set(&tpd_ring->next_to_use, 0);
++ atomic_set(&tpd_ring->next_to_clean, 0);
++}
++
++/*
++ * atl1_free_ring_resources - Free Tx / RX descriptor Resources
++ * @adapter: board private structure
++ *
++ * Free all transmit software resources
++ */
++static void atl1_free_ring_resources(struct atl1_adapter *adapter)
++{
++ struct pci_dev *pdev = adapter->pdev;
++ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
++ struct atl1_ring_header *ring_header = &adapter->ring_header;
++
++ atl1_clean_tx_ring(adapter);
++ atl1_clean_rx_ring(adapter);
++
++ kfree(tpd_ring->buffer_info);
++ pci_free_consistent(pdev, ring_header->size, ring_header->desc,
++ ring_header->dma);
++
++ tpd_ring->buffer_info = NULL;
++ tpd_ring->desc = NULL;
++ tpd_ring->dma = 0;
++
++ rfd_ring->buffer_info = NULL;
++ rfd_ring->desc = NULL;
++ rfd_ring->dma = 0;
++
++ rrd_ring->desc = NULL;
++ rrd_ring->dma = 0;
++}
++
++static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
++{
++ u32 value;
++ struct atl1_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ /* Config MAC CTRL Register */
++ value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
++ /* duplex */
++ if (FULL_DUPLEX == adapter->link_duplex)
++ value |= MAC_CTRL_DUPLX;
++ /* speed */
++ value |= ((u32) ((SPEED_1000 == adapter->link_speed) ?
++ MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
++ MAC_CTRL_SPEED_SHIFT);
++ /* flow control */
++ value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
++ /* PAD & CRC */
++ value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
++ /* preamble length */
++ value |= (((u32) adapter->hw.preamble_len
++ & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
++ /* vlan */
++ if (adapter->vlgrp)
++ value |= MAC_CTRL_RMV_VLAN;
++ /* rx checksum
++ if (adapter->rx_csum)
++ value |= MAC_CTRL_RX_CHKSUM_EN;
++ */
++ /* filter mode */
++ value |= MAC_CTRL_BC_EN;
++ if (netdev->flags & IFF_PROMISC)
++ value |= MAC_CTRL_PROMIS_EN;
++ else if (netdev->flags & IFF_ALLMULTI)
++ value |= MAC_CTRL_MC_ALL_EN;
++ /* value |= MAC_CTRL_LOOPBACK; */
++ iowrite32(value, hw->hw_addr + REG_MAC_CTRL);
++}
++
++static u32 atl1_check_link(struct atl1_adapter *adapter)
++{
++ struct atl1_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ u32 ret_val;
++ u16 speed, duplex, phy_data;
++ int reconfig = 0;
++
++ /* MII_BMSR must read twice */
++ atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
++ atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
++ if (!(phy_data & BMSR_LSTATUS)) {
++ /* link down */
++ if (netif_carrier_ok(netdev)) {
++ /* old link state: Up */
++ if (netif_msg_link(adapter))
++ dev_info(&adapter->pdev->dev, "link is down\n");
++ adapter->link_speed = SPEED_0;
++ netif_carrier_off(netdev);
++ netif_stop_queue(netdev);
++ }
++ return 0;
++ }
++
++ /* Link Up */
++ ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
++ if (ret_val)
++ return ret_val;
++
++ switch (hw->media_type) {
++ case MEDIA_TYPE_1000M_FULL:
++ if (speed != SPEED_1000 || duplex != FULL_DUPLEX)
++ reconfig = 1;
++ break;
++ case MEDIA_TYPE_100M_FULL:
++ if (speed != SPEED_100 || duplex != FULL_DUPLEX)
++ reconfig = 1;
++ break;
++ case MEDIA_TYPE_100M_HALF:
++ if (speed != SPEED_100 || duplex != HALF_DUPLEX)
++ reconfig = 1;
++ break;
++ case MEDIA_TYPE_10M_FULL:
++ if (speed != SPEED_10 || duplex != FULL_DUPLEX)
++ reconfig = 1;
++ break;
++ case MEDIA_TYPE_10M_HALF:
++ if (speed != SPEED_10 || duplex != HALF_DUPLEX)
++ reconfig = 1;
++ break;
++ }
++
++ /* link result is our setting */
++ if (!reconfig) {
++ if (adapter->link_speed != speed
++ || adapter->link_duplex != duplex) {
++ adapter->link_speed = speed;
++ adapter->link_duplex = duplex;
++ atl1_setup_mac_ctrl(adapter);
++ if (netif_msg_link(adapter))
++ dev_info(&adapter->pdev->dev,
++ "%s link is up %d Mbps %s\n",
++ netdev->name, adapter->link_speed,
++ adapter->link_duplex == FULL_DUPLEX ?
++ "full duplex" : "half duplex");
++ }
++ if (!netif_carrier_ok(netdev)) {
++ /* Link down -> Up */
++ netif_carrier_on(netdev);
++ netif_wake_queue(netdev);
++ }
++ return 0;
++ }
++
++ /* change original link status */
++ if (netif_carrier_ok(netdev)) {
++ adapter->link_speed = SPEED_0;
++ netif_carrier_off(netdev);
++ netif_stop_queue(netdev);
++ }
++
++ if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR &&
++ hw->media_type != MEDIA_TYPE_1000M_FULL) {
++ switch (hw->media_type) {
++ case MEDIA_TYPE_100M_FULL:
++ phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
++ MII_CR_RESET;
++ break;
++ case MEDIA_TYPE_100M_HALF:
++ phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
++ break;
++ case MEDIA_TYPE_10M_FULL:
++ phy_data =
++ MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
++ break;
++ default:
++ /* MEDIA_TYPE_10M_HALF: */
++ phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
++ break;
++ }
++ atl1_write_phy_reg(hw, MII_BMCR, phy_data);
++ return 0;
++ }
++
++ /* auto-neg, insert timer to re-config phy */
++ if (!adapter->phy_timer_pending) {
++ adapter->phy_timer_pending = true;
++ mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ);
++ }
++
++ return 0;
++}
++
++static void set_flow_ctrl_old(struct atl1_adapter *adapter)
++{
++ u32 hi, lo, value;
++
++ /* RFD Flow Control */
++ value = adapter->rfd_ring.count;
++ hi = value / 16;
++ if (hi < 2)
++ hi = 2;
++ lo = value * 7 / 8;
++
++ value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
++ ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
++ iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
++
++ /* RRD Flow Control */
++ value = adapter->rrd_ring.count;
++ lo = value / 16;
++ hi = value * 7 / 8;
++ if (lo < 2)
++ lo = 2;
++ value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
++ ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
++ iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
++}
++
++static void set_flow_ctrl_new(struct atl1_hw *hw)
++{
++ u32 hi, lo, value;
++
++ /* RXF Flow Control */
++ value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN);
++ lo = value / 16;
++ if (lo < 192)
++ lo = 192;
++ hi = value * 7 / 8;
++ if (hi < lo)
++ hi = lo + 16;
++ value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
++ ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
++ iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
++
++ /* RRD Flow Control */
++ value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN);
++ lo = value / 8;
++ hi = value * 7 / 8;
++ if (lo < 2)
++ lo = 2;
++ if (hi < lo)
++ hi = lo + 3;
++ value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
++ ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
++ iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
++}
++
++/*
++ * atl1_configure - Configure Transmit&Receive Unit after Reset
++ * @adapter: board private structure
++ *
++ * Configure the Tx /Rx unit of the MAC after a reset.
+ */
++static u32 atl1_configure(struct atl1_adapter *adapter)
++{
++ struct atl1_hw *hw = &adapter->hw;
++ u32 value;
+
-+#include <asm/atomic.h>
-+#include <asm/byteorder.h>
++ /* clear interrupt status */
++ iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);
+
-+#include <linux/compiler.h>
-+#include <linux/crc32.h>
-+#include <linux/delay.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/etherdevice.h>
-+#include <linux/hardirq.h>
-+#include <linux/if_ether.h>
-+#include <linux/if_vlan.h>
-+#include <linux/in.h>
-+#include <linux/interrupt.h>
-+#include <linux/ip.h>
-+#include <linux/irqflags.h>
-+#include <linux/irqreturn.h>
-+#include <linux/jiffies.h>
-+#include <linux/mii.h>
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/net.h>
-+#include <linux/netdevice.h>
-+#include <linux/pci.h>
-+#include <linux/pci_ids.h>
-+#include <linux/pm.h>
-+#include <linux/skbuff.h>
-+#include <linux/slab.h>
-+#include <linux/spinlock.h>
-+#include <linux/string.h>
-+#include <linux/tcp.h>
-+#include <linux/timer.h>
-+#include <linux/types.h>
-+#include <linux/workqueue.h>
++ /* 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));
+
-+#include <net/checksum.h>
++ /* tx / rx ring */
+
-+#include "atl1.h"
++ /* 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);
+
-+/* Temporary hack for merging atl1 and atl2 */
-+#include "atlx.c"
++ /* 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);
+
-+/*
-+ * 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
++ /* Load Ptr */
++ iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
+
-+#define OPTION_UNSET -1
-+#define OPTION_DISABLED 0
-+#define OPTION_ENABLED 1
++ /* 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);
+
-+#define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET }
++ /* 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);
+
-+/*
-+ * 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");
++ /* 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);
+
-+#define DEFAULT_INT_MOD_CNT 100 /* 200us */
-+#define MAX_INT_MOD_CNT 65000
-+#define MIN_INT_MOD_CNT 50
++ /* 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);
+
-+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;
-+};
++ /* set Interrupt Clear Timer */
++ iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);
+
-+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;
-+ }
++ /* set max frame size hw will accept */
++ iowrite32(hw->max_frame_size, hw->hw_addr + REG_MTU);
+
-+ 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;
++ /* 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);
+
-+ 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;
-+ }
-+ }
-+ }
++ /* 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;
+ }
+
-+ dev_info(&pdev->dev, "invalid %s specified (%i) %s\n",
-+ opt->name, *value, opt->err);
-+ *value = opt->def;
-+ return -1;
++ /* 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_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.
++ * atl1_pcie_patch - Patch for PCIE module
+ */
-+void __devinit atl1_check_options(struct atl1_adapter *adapter)
++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;
-+ 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");
++
++ 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;
++ }
+ }
-+ { /* 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);
++
++ /* 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_pci_tbl - PCI Device ID Table
++ * atl1_alloc_rx_buffers - Replace used receive buffers
++ * @adapter: address of board private structure
+ */
-+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 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;
+
-+static const u32 atl1_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
-+ NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP;
++ 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];
+
-+static int debug = -1;
-+module_param(debug, int, 0);
-+MODULE_PARM_DESC(debug, "Message level (0=none,...,16=all)");
++ while (!buffer_info->alloced && !next_info->alloced) {
++ if (buffer_info->skb) {
++ buffer_info->alloced = 1;
++ goto next;
++ }
+
-+/*
-+ * 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)
++ 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)
+{
-+ struct pci_dev *pdev = hw->back->pdev;
-+ struct atl1_adapter *adapter = hw->back;
-+ u32 icr;
-+ int i;
++ 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;
+
-+ /*
-+ * 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);
-+ */
++ count = 0;
+
-+ /*
-+ * 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);
++ rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean);
+
-+ iowrite16(1, hw->hw_addr + REG_PHY_ENABLE);
-+ ioread16(hw->hw_addr + REG_PHY_ENABLE);
++ 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);
++ }
+
-+ /* delay about 1ms */
-+ msleep(1);
++ /* 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 */
+
-+ /* 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();
-+ }
++ }
++rrd_ok:
++ /* clean alloc flag for bad rrd */
++ atl1_clean_alloc_flag(adapter, rrd, 0);
+
-+ if (icr) {
-+ if (netif_msg_hw(adapter))
-+ dev_dbg(&pdev->dev, "ICR = 0x%x\n", icr);
-+ return icr;
++ 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;
+ }
+
-+ return 0;
++ 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);
++ }
+}
+
-+/* function about EEPROM
-+ *
-+ * check_eeprom_exist
-+ * return 0 if eeprom exist
-+ */
-+static int atl1_check_eeprom_exist(struct atl1_hw *hw)
++static void atl1_intr_tx(struct atl1_adapter *adapter)
+{
-+ 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);
++ 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);
+
-+ value = ioread16(hw->hw_addr + REG_PCIE_CAP_LIST);
-+ return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
++ if (netif_queue_stopped(adapter->netdev)
++ && netif_carrier_ok(adapter->netdev))
++ netif_wake_queue(adapter->netdev);
+}
+
-+static bool atl1_read_eeprom(struct atl1_hw *hw, u32 offset, u32 *p_value)
++static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring)
+{
-+ int i;
-+ u32 control;
++ 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);
++}
+
-+ if (offset & 3)
-+ /* address do not align */
-+ return false;
++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;
+
-+ 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);
++ 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;
++ }
+
-+ for (i = 0; i < 10; i++) {
-+ msleep(2);
-+ control = ioread32(hw->hw_addr + REG_VPD_CAP);
-+ if (control & VPD_CAP_VPD_FLAG)
-+ break;
++ 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;
++ }
+ }
-+ if (control & VPD_CAP_VPD_FLAG) {
-+ *p_value = ioread32(hw->hw_addr + REG_VPD_DATA);
++ 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;
+ }
-+ /* timeout */
-+ return false;
++ return 0;
+}
+
-+/*
-+ * 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)
++static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
++ struct tx_packet_desc *ptpd)
+{
-+ u32 val;
-+ int i;
++ /* 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;
+
-+ 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);
++ 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;
+
-+ 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;
++ 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;
+ }
-+ if (!(val & (MDIO_START | MDIO_BUSY))) {
-+ *phy_data = (u16) val;
-+ return 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;
++ }
+ }
-+ return ATLX_ERR_PHY;
++
++ /* last tpd's buffer-info */
++ buffer_info->skb = skb;
+}
+
-+#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 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);
+
-+static bool atl1_spi_read(struct atl1_hw *hw, u32 addr, u32 *buf)
++ 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)
+{
-+ int i;
-+ u32 value;
++ 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;
+
-+ iowrite32(0, hw->hw_addr + REG_SPI_DATA);
-+ iowrite32(addr, hw->hw_addr + REG_SPI_ADDR);
++ len -= skb->data_len;
+
-+ 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;
++ if (unlikely(skb->len <= 0)) {
++ dev_kfree_skb_any(skb);
++ return NETDEV_TX_OK;
++ }
+
-+ iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
++ 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;
++ }
+
-+ value |= SPI_FLASH_CTRL_START;
-+ iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
-+ ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
++ 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;
++ }
++ }
+
-+ 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 (!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 (value & SPI_FLASH_CTRL_START)
-+ return false;
++ 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;
++ }
+
-+ *buf = ioread32(hw->hw_addr + REG_SPI_DATA);
++ ptpd = ATL1_TPD_DESC(tpd_ring,
++ (u16) atomic_read(&tpd_ring->next_to_use));
++ memset(ptpd, 0, sizeof(struct tx_packet_desc));
+
-+ return true;
++ 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;
+}
+
+/*
-+ * get_permanent_address
-+ * return 0 if get valid mac address,
++ * atl1_intr - Interrupt Handler
++ * @irq: interrupt number
++ * @data: pointer to a network interface device structure
++ * @pt_regs: CPU registers structure
+ */
-+static int atl1_get_permanent_address(struct atl1_hw *hw)
++static irqreturn_t atl1_intr(int irq, void *data)
+{
-+ u32 addr[2];
-+ u32 i, control;
-+ u16 reg;
-+ u8 eth_addr[ETH_ALEN];
-+ bool key_valid;
++ struct atl1_adapter *adapter = netdev_priv(data);
++ u32 status;
++ int max_ints = 10;
+
-+ if (is_valid_ether_addr(hw->perm_mac_addr))
-+ return 0;
++ status = adapter->cmb.cmb->int_stats;
++ if (!status)
++ return IRQ_NONE;
+
-+ /* init */
-+ addr[0] = addr[1] = 0;
++ do {
++ /* clear CMB interrupt status at once */
++ adapter->cmb.cmb->int_stats = 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;
++ 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;
++ }
+ }
+
-+ *(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;
++ /* 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;
+ }
-+ 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 */
++ /* 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;
-+ i += 4;
++
++ } while ((status = adapter->cmb.cmb->int_stats));
++
++ /* re-enable Interrupt */
++ iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
++ return IRQ_HANDLED;
++}
++
++/*
++ * atl1_watchdog - Timer Call-back
++ * @data: pointer to netdev cast into an unsigned long
++ */
++static void atl1_watchdog(unsigned long data)
++{
++ struct atl1_adapter *adapter = (struct atl1_adapter *)data;
++
++ /* Reset the timer */
++ mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
++}
++
++/*
++ * atl1_phy_config - Timer Call-back
++ * @data: pointer to netdev cast into an unsigned long
++ */
++static void atl1_phy_config(unsigned long data)
++{
++ struct atl1_adapter *adapter = (struct atl1_adapter *)data;
++ struct atl1_hw *hw = &adapter->hw;
++ unsigned long flags;
++
++ spin_lock_irqsave(&adapter->lock, flags);
++ adapter->phy_timer_pending = false;
++ atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
++ atl1_write_phy_reg(hw, MII_ATLX_CR, hw->mii_1000t_ctrl_reg);
++ atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
++ spin_unlock_irqrestore(&adapter->lock, flags);
++}
++
++/*
++ * Orphaned vendor comment left intact here:
++ * <vendor comment>
++ * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
++ * will assert. We do soft reset <0x1400=1> according
++ * with the SPEC. BUT, it seemes that PCIE or DMA
++ * state-machine will not be reset. DMAR_TO_INT will
++ * assert again and again.
++ * </vendor comment>
++ */
++
++static int atl1_reset(struct atl1_adapter *adapter)
++{
++ int ret;
++ ret = atl1_reset_hw(&adapter->hw);
++ if (ret)
++ return ret;
++ return atl1_init_hw(&adapter->hw);
++}
++
++static s32 atl1_up(struct atl1_adapter *adapter)
++{
++ struct net_device *netdev = adapter->netdev;
++ int err;
++ int irq_flags = IRQF_SAMPLE_RANDOM;
++
++ /* hardware has been reset, we need to reload some things */
++ atlx_set_multi(netdev);
++ atl1_init_ring_ptrs(adapter);
++ atlx_restore_vlan(adapter);
++ err = atl1_alloc_rx_buffers(adapter);
++ if (unlikely(!err))
++ /* no RX BUFFER allocated */
++ return -ENOMEM;
++
++ if (unlikely(atl1_configure(adapter))) {
++ err = -EIO;
++ goto err_up;
+ }
+
-+ *(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;
++ 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;
+ }
+
-+ /*
-+ * 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;
++ 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;
+ }
+
-+ return 1;
++ 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;
+}
+
+/*
-+ * Reads the adapter's MAC address from the EEPROM
-+ * hw - Struct containing variables accessed by shared code
++ * 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.
+ */
-+s32 atl1_read_mac_addr(struct atl1_hw *hw)
++static int atl1_open(struct net_device *netdev)
+{
-+ u16 i;
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ int err;
+
-+ if (atl1_get_permanent_address(hw))
-+ random_ether_addr(hw->perm_mac_addr);
++ /* allocate transmit descriptors */
++ err = atl1_setup_ring_resources(adapter);
++ if (err)
++ return err;
++
++ err = atl1_up(adapter);
++ if (err)
++ goto err_up;
+
-+ for (i = 0; i < ETH_ALEN; i++)
-+ hw->mac_addr[i] = hw->perm_mac_addr[i];
+ return 0;
++
++err_up:
++ atl1_reset(adapter);
++ return err;
+}
+
+/*
-+ * 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_close - Disables a network interface
++ * @netdev: network interface device structure
+ *
-+ * 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
++ * 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.
+ */
-+u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr)
++static int atl1_close(struct net_device *netdev)
+{
-+ u32 crc32, value = 0;
-+ int i;
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ atl1_down(adapter);
++ atl1_free_ring_resources(adapter);
++ return 0;
++}
+
-+ crc32 = ether_crc_le(6, mc_addr);
-+ for (i = 0; i < 32; i++)
-+ value |= (((crc32 >> i) & 1) << (31 - i));
++#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;
+
-+ return value;
++ 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
+
+/*
-+ * 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
++ * 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.
+ */
-+void atl1_hash_set(struct atl1_hw *hw, u32 hash_value)
++static int __devinit atl1_probe(struct pci_dev *pdev,
++ const struct pci_device_id *ent)
+{
-+ u32 hash_bit, hash_reg;
-+ u32 mta;
++ 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 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.
++ * 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.
+ */
-+ 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));
++ 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;
+}
+
+/*
-+ * 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
++ * 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 s32 atl1_write_phy_reg(struct atl1_hw *hw, u32 reg_addr, u16 phy_data)
++static void __devexit atl1_remove(struct pci_dev *pdev)
+{
-+ int i;
-+ u32 val;
++ struct net_device *netdev = pci_get_drvdata(pdev);
++ struct atl1_adapter *adapter;
++ /* Device not available. Return. */
++ if (!netdev)
++ return;
+
-+ 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);
++ adapter = netdev_priv(netdev);
+
-+ 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;
++ /*
++ * 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);
+ }
+
-+ if (!(val & (MDIO_START | MDIO_BUSY)))
-+ return 0;
++ 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;
++ }
+
-+ 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)
++static int atl1_get_sset_count(struct net_device *netdev, int sset)
+{
-+ s32 ret;
-+ ret = atl1_write_phy_reg(hw, 29, 0x0029);
-+ if (ret)
-+ return ret;
-+ return atl1_write_phy_reg(hw, 30, 0);
++ switch (sset) {
++ case ETH_SS_STATS:
++ return ARRAY_SIZE(atl1_gstrings_stats);
++ default:
++ return -EOPNOTSUPP;
++ }
+}
+
-+/*
-+ *TODO: do something or get rid of this
-+ */
-+#ifdef CONFIG_PM
-+static s32 atl1_phy_enter_power_saving(struct atl1_hw *hw)
++static int atl1_get_settings(struct net_device *netdev,
++ struct ethtool_cmd *ecmd)
+{
-+/* s32 ret_val;
-+ * u16 phy_data;
-+ */
++ 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;
+
-+/*
-+ 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)
++static int atl1_set_settings(struct net_device *netdev,
++ struct ethtool_cmd *ecmd)
+{
-+ struct pci_dev *pdev = hw->back->pdev;
-+ struct atl1_adapter *adapter = hw->back;
-+ s32 ret_val;
++ 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;
@@ -449747,33679 +627547,46989 @@
+ break;
+ }
+ }
++ atl1_write_phy_reg(hw, MII_BMCR, phy_data);
++exit_sset:
++ if (ret_val)
++ hw->media_type = old_media_type;
+
-+ 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");
++ 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;
++}
+
-+ for (i = 0; i < 25; i++) {
-+ msleep(1);
-+ val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
-+ if (!(val & (MDIO_START | MDIO_BUSY)))
-+ break;
-+ }
++static void atl1_get_drvinfo(struct net_device *netdev,
++ struct ethtool_drvinfo *drvinfo)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
+
-+ 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;
-+ }
-+ }
++ 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;
+}
+
-+/*
-+ * 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)
++static u32 atl1_get_msglevel(struct net_device *netdev)
+{
-+ s32 ret_val;
-+ s16 mii_autoneg_adv_reg;
-+ s16 mii_1000t_ctrl_reg;
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ return adapter->msg_enable;
++}
+
-+ /* Read the MII Auto-Neg Advertisement Register (Address 4). */
-+ mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
++static void atl1_set_msglevel(struct net_device *netdev, u32 value)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ adapter->msg_enable = value;
++}
+
-+ /* Read the MII 1000Base-T Control Register (Address 9). */
-+ mii_1000t_ctrl_reg = MII_ATLX_CR_1000T_DEFAULT_CAP_MASK;
++static int atl1_get_regs_len(struct net_device *netdev)
++{
++ return ATL1_REG_COUNT * sizeof(u32);
++}
+
-+ /*
-+ * 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;
++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;
+
-+ /*
-+ * 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;
++ 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)));
++ }
++ }
++}
+
-+ case MEDIA_TYPE_1000M_FULL:
-+ mii_1000t_ctrl_reg |= MII_ATLX_CR_1000T_FD_CAPS;
-+ break;
++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;
+
-+ case MEDIA_TYPE_100M_FULL:
-+ mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;
-+ break;
++ 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;
++}
+
-+ case MEDIA_TYPE_100M_HALF:
-+ mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;
-+ break;
++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;
+
-+ case MEDIA_TYPE_10M_FULL:
-+ mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;
-+ break;
++ 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;
+
-+ default:
-+ mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;
-+ break;
-+ }
++ tpd_old = adapter->tpd_ring;
++ rfd_old = adapter->rfd_ring;
++ rrd_old = adapter->rrd_ring;
++ rhdr_old = adapter->ring_header;
+
-+ /* flow control fixed to enable all */
-+ mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
++ if (netif_running(adapter->netdev))
++ atl1_down(adapter);
+
-+ hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
-+ hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
++ 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;
+
-+ ret_val = atl1_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
-+ if (ret_val)
-+ return ret_val;
++ 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;
+
-+ ret_val = atl1_write_phy_reg(hw, MII_ATLX_CR, mii_1000t_ctrl_reg);
-+ if (ret_val)
-+ return ret_val;
++ 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;
+
-+ return 0;
-+}
++ /*
++ * save the new, restore the old in order to free it,
++ * then restore the new back again
++ */
+
-+/*
-+ * 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;
++ 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;
+
-+ /*
-+ * 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;
++ err = atl1_up(adapter);
++ if (err)
++ return err;
+ }
-+ hw->phy_configured = true;
-+ return ret_val;
++ 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_init_flash_opcode(struct atl1_hw *hw)
++static void atl1_get_pauseparam(struct net_device *netdev,
++ struct ethtool_pauseparam *epause)
+{
-+ if (hw->flash_vendor >= ARRAY_SIZE(flash_table))
-+ /* Atmel */
-+ hw->flash_vendor = 0;
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ struct atl1_hw *hw = &adapter->hw;
+
-+ /* 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);
++ 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;
+}
+
-+/*
-+ * 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)
++static int atl1_set_pauseparam(struct net_device *netdev,
++ struct ethtool_pauseparam *epause)
+{
-+ u32 ret_val = 0;
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ struct atl1_hw *hw = &adapter->hw;
+
-+ /* 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));
++ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
++ hw->media_type == MEDIA_TYPE_1000M_FULL) {
++ epause->autoneg = AUTONEG_ENABLE;
++ } else {
++ epause->autoneg = AUTONEG_DISABLE;
++ }
+
-+ atl1_init_flash_opcode(hw);
++ epause->rx_pause = 1;
++ epause->tx_pause = 1;
+
-+ 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;
++ return 0;
+}
+
-+/*
-+ * Detects the current speed and duplex settings of the hardware.
-+ * hw - Struct containing variables accessed by shared code
-+ * speed - Speed of the connection
-+ * duplex - Duplex setting of the connection
-+ */
-+static s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex)
++/* FIXME: is this right? -- CHS */
++static u32 atl1_get_rx_csum(struct net_device *netdev)
+{
-+ 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;
++ return 1;
++}
+
-+ if (!(phy_data & MII_ATLX_PSSR_SPD_DPLX_RESOLVED))
-+ return ATLX_ERR_PHY_RES;
++static void atl1_get_strings(struct net_device *netdev, u32 stringset,
++ u8 *data)
++{
++ u8 *p = data;
++ int i;
+
-+ 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;
++ 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;
+ }
-+ 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)
++static int atl1_nway_reset(struct net_device *netdev)
+{
-+ 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));
++ 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 @@
+/*
-+ * atl1_sw_init - Initialize general software structures (struct atl1_adapter)
-+ * @adapter: board private structure to initialize
++ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
++ * Copyright(c) 2006 - 2007 Chris Snook <csnook at redhat.com>
++ * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
+ *
-+ * atl1_sw_init initializes the Adapter private data structure.
-+ * Fields are initialized based on PCI device information and
-+ * OS network device settings (MTU size).
++ * 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.
+ */
-+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;
++#ifndef ATL1_H
++#define ATL1_H
+
-+ 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;
++#include <linux/compiler.h>
++#include <linux/ethtool.h>
++#include <linux/if_vlan.h>
++#include <linux/mii.h>
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/spinlock.h>
++#include <linux/timer.h>
++#include <linux/types.h>
++#include <linux/workqueue.h>
+
-+ 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 */
++#include "atlx.h"
+
-+ spin_lock_init(&adapter->lock);
-+ spin_lock_init(&adapter->mb_lock);
++#define ATLX_DRIVER_NAME "atl1"
+
-+ return 0;
-+}
++MODULE_DESCRIPTION("Atheros L1 Gigabit Ethernet Driver");
+
-+static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
-+{
-+ struct atl1_adapter *adapter = netdev_priv(netdev);
-+ u16 result;
++#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
+
-+ atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
++struct atl1_adapter;
++struct atl1_hw;
+
-+ return result;
-+}
++/* 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);
+
-+static void mdio_write(struct net_device *netdev, int phy_id, int reg_num,
-+ int val)
-+{
-+ struct atl1_adapter *adapter = netdev_priv(netdev);
++extern const struct ethtool_ops atl1_ethtool_ops;
+
-+ atl1_write_phy_reg(&adapter->hw, reg_num, val);
-+}
++/* hardware definitions specific to L1 */
+
-+/*
-+ * 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;
++/* 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
+
-+ if (!netif_running(netdev))
-+ return -EINVAL;
++/* MDIO Control Register */
++#define MDIO_WAIT_TIMES 30
+
-+ spin_lock_irqsave(&adapter->lock, flags);
-+ retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
-+ spin_unlock_irqrestore(&adapter->lock, flags);
++/* 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
+
-+ return retval;
-+}
++/* 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
+
-+/*
-+ * 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;
++/* 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
+
-+ 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);
++/* 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
+
-+ /*
-+ * 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;
++/* Load Ptr Register */
++#define REG_LOAD_PTR 0x1534
+
-+ 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;
-+ }
++/* 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
+
-+ memset(ring_header->desc, 0, ring_header->size);
++/* 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
+
-+ /* 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;
++/* 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
+
-+ /* 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;
++/* 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
+
-+ /* 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;
++/* 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
+
-+ /* 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));
++/* 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
+
-+ /* 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));
++/* 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
+
-+ return 0;
++/* 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
+
-+err_nomem:
-+ kfree(tpd_ring->buffer_info);
-+ return -ENOMEM;
-+}
++/* 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
+
-+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;
++/* Number of packet received since last CMB write */
++#define REG_CMB_RX_PKT_CNT 0x15DC
+
-+ atomic_set(&tpd_ring->next_to_use, 0);
-+ atomic_set(&tpd_ring->next_to_clean, 0);
++/* Number of packet transmitted since last CMB write */
++#define REG_CMB_TX_PKT_CNT 0x15E0
+
-+ rfd_ring->next_to_clean = 0;
-+ atomic_set(&rfd_ring->next_to_use, 0);
++/* SMB auto DMA timer register */
++#define REG_SMB_TIMER 0x15E4
+
-+ rrd_ring->next_to_use = 0;
-+ atomic_set(&rrd_ring->next_to_clean, 0);
-+}
++/* 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
+
-+/*
-+ * 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;
++/* 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
+
-+ /* 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;
-+ }
-+ }
++/* 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)
+
-+ size = sizeof(struct atl1_buffer) * rfd_ring->count;
-+ memset(rfd_ring->buffer_info, 0, size);
++/* 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)
+
-+ /* Zero out the descriptor ring */
-+ memset(rfd_ring->desc, 0, rfd_ring->size);
++#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
+
-+ rfd_ring->next_to_clean = 0;
-+ atomic_set(&rfd_ring->next_to_use, 0);
++#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F /* All but 1000-Half */
+
-+ rrd_ring->next_to_use = 0;
-+ atomic_set(&rrd_ring->next_to_clean, 0);
-+}
++#define MAX_JUMBO_FRAME_SIZE 10240
+
-+/*
-+ * 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;
++#define ATL1_EEDUMP_LEN 48
+
-+ /* 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;
-+ }
-+ }
++/* 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 */
+
-+ 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;
-+ }
-+ }
++ /* 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. */
++};
+
-+ size = sizeof(struct atl1_buffer) * tpd_ring->count;
-+ memset(tpd_ring->buffer_info, 0, size);
++/* 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. */
++};
+
-+ /* Zero out the descriptor ring */
-+ memset(tpd_ring->desc, 0, tpd_ring->size);
++/* 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;
+
-+ atomic_set(&tpd_ring->next_to_use, 0);
-+ atomic_set(&tpd_ring->next_to_clean, 0);
-+}
++ 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));
+
+/*
-+ * atl1_free_ring_resources - Free Tx / RX descriptor Resources
-+ * @adapter: board private structure
++ * The L1 transmit packet descriptor is comprised of four 32-bit words.
+ *
-+ * Free all transmit software resources
++ * 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-+
+ */
-+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);
++/* 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
+
-+ kfree(tpd_ring->buffer_info);
-+ pci_free_consistent(pdev, ring_header->size, ring_header->desc,
-+ ring_header->dma);
++/* 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_ring->buffer_info = NULL;
-+ tpd_ring->desc = NULL;
-+ tpd_ring->dma = 0;
++/* 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
+
-+ rfd_ring->buffer_info = NULL;
-+ rfd_ring->desc = NULL;
-+ rfd_ring->dma = 0;
++/* 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
+
-+ rrd_ring->desc = NULL;
-+ rrd_ring->dma = 0;
-+}
++struct tx_packet_desc {
++ __le64 buffer_addr;
++ __le32 word2;
++ __le32 word3;
++};
+
-+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);
-+}
++/* DMA Order Settings */
++enum atl1_dma_order {
++ atl1_dma_ord_in = 1,
++ atl1_dma_ord_enh = 2,
++ atl1_dma_ord_out = 4
++};
+
-+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;
++enum atl1_dma_rcb {
++ atl1_rcb_64 = 0,
++ atl1_rcb_128 = 1
++};
+
-+ /* 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;
-+ }
++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
++};
+
-+ /* Link Up */
-+ ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
-+ if (ret_val)
-+ return ret_val;
++#define ATL1_MAX_INTR 3
++#define ATL1_MAX_TX_BUF_LEN 0x3000 /* 12288 bytes */
+
-+ 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;
-+ }
++#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
+
-+ /* 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;
-+ }
++#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)
+
-+ /* change original link status */
-+ if (netif_carrier_ok(netdev)) {
-+ adapter->link_speed = SPEED_0;
-+ netif_carrier_off(netdev);
-+ netif_stop_queue(netdev);
-+ }
++/*
++ * 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 */
++};
+
-+ 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;
-+ }
++/*
++ * 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;
++};
+
-+ /* 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);
-+ }
++/* 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;
++};
+
-+ return 0;
-+}
++/* 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;
++};
+
-+static void set_flow_ctrl_old(struct atl1_adapter *adapter)
-+{
-+ u32 hi, lo, value;
++/* 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;
++};
+
-+ /* RFD Flow Control */
-+ value = adapter->rfd_ring.count;
-+ hi = value / 16;
-+ if (hi < 2)
-+ hi = 2;
-+ lo = value * 7 / 8;
++/* coalescing message block (cmb) */
++struct atl1_cmb {
++ struct coals_msg_block *cmb;
++ dma_addr_t dma;
++};
+
-+ 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);
++/* statistics message block (smb) */
++struct atl1_smb {
++ struct stats_msg_block *smb;
++ dma_addr_t dma;
++};
+
-+ /* 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);
-+}
++/* 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;
++};
+
-+static void set_flow_ctrl_new(struct atl1_hw *hw)
-+{
-+ u32 hi, lo, value;
++/* 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 */
+
-+ /* 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);
++ u16 cmb_tpd;
++ u16 cmb_rrd;
++ u16 cmb_rx_timer;
++ u16 cmb_tx_timer;
++ u32 smb_timer;
++ u16 media_type;
++ u16 autoneg_advertised;
+
-+ /* 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);
-+}
++ u16 mii_autoneg_adv_reg;
++ u16 mii_1000t_ctrl_reg;
+
-+/*
-+ * 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;
++ u32 max_frame_size;
++ u32 min_frame_size;
+
-+ /* clear interrupt status */
-+ iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);
++ u16 dev_rev;
+
-+ /* 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));
++ /* spi flash */
++ u8 flash_vendor;
+
-+ /* tx / rx ring */
++ u8 mac_addr[ETH_ALEN];
++ u8 perm_mac_addr[ETH_ALEN];
+
-+ /* 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);
++ bool phy_configured;
++};
+
-+ /* 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);
++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;
+
-+ /* Load Ptr */
-+ iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
++ /* all descriptor rings' memory */
++ struct atl1_ring_header ring_header;
+
-+ /* 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);
++ /* TX */
++ struct atl1_tpd_ring tpd_ring;
++ spinlock_t mb_lock;
+
-+ /* 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);
++ /* 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 */
+
-+ /* 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);
++ u32 bd_number; /* board number */
++ bool pci_using_64;
++ struct atl1_hw hw;
++ struct atl1_smb smb;
++ struct atl1_cmb cmb;
++};
+
-+ /* 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);
++#endif /* ATL1_H */
+diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c
+new file mode 100644
+index 0000000..f06b854
+--- /dev/null
++++ b/drivers/net/atlx/atlx.c
+@@ -0,0 +1,256 @@
++/* atlx.c -- common functions for Attansic network drivers
++ *
++ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
++ * Copyright(c) 2006 - 2007 Chris Snook <csnook at redhat.com>
++ * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
++ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
++ *
++ * Derived from Intel e1000 driver
++ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 2 of the License, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 59
++ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
+
-+ /* set Interrupt Clear Timer */
-+ iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);
++/* Including this file like a header is a temporary hack, I promise. -- CHS */
++#ifndef ATLX_C
++#define ATLX_C
+
-+ /* set max frame size hw will accept */
-+ iowrite32(hw->max_frame_size, hw->hw_addr + REG_MTU);
++#include <linux/device.h>
++#include <linux/errno.h>
++#include <linux/etherdevice.h>
++#include <linux/if.h>
++#include <linux/netdevice.h>
++#include <linux/socket.h>
++#include <linux/sockios.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/workqueue.h>
+
-+ /* 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);
++#include "atlx.h"
+
-+ /* Flow Control */
-+ switch (hw->dev_rev) {
-+ case 0x8001:
-+ case 0x9001:
-+ case 0x9002:
-+ case 0x9003:
-+ set_flow_ctrl_old(adapter);
-+ break;
++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:
-+ set_flow_ctrl_new(hw);
-+ break;
++ return -EOPNOTSUPP;
+ }
++}
+
-+ /* 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);
++/*
++ * 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;
+
-+ /* 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);
++ if (netif_running(netdev))
++ return -EBUSY;
+
-+ /* 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);
++ if (!is_valid_ether_addr(addr->sa_data))
++ return -EADDRNOTAVAIL;
+
-+ /* 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);
++ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
++ memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+
-+ /* 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);
++ atlx_set_mac_addr(&adapter->hw);
++ return 0;
++}
+
-+ /* --- enable CMB / SMB */
-+ value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN;
-+ iowrite32(value, hw->hw_addr + REG_CSMB_CTRL);
++static void atlx_check_for_link(struct atlx_adapter *adapter)
++{
++ struct net_device *netdev = adapter->netdev;
++ u16 phy_data = 0;
+
-+ value = ioread32(adapter->hw.hw_addr + REG_ISR);
-+ if (unlikely((value & ISR_PHY_LINKDOWN) != 0))
-+ value = 1; /* config failed */
-+ else
-+ value = 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);
+
-+ /* clear all interrupt status */
-+ iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR);
-+ iowrite32(0, adapter->hw.hw_addr + REG_ISR);
-+ return value;
++ /* 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_pcie_patch - Patch for PCIE module
++ * 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 atl1_pcie_patch(struct atl1_adapter *adapter)
++static void atlx_set_multi(struct net_device *netdev)
+{
-+ u32 value;
++ struct atlx_adapter *adapter = netdev_priv(netdev);
++ struct atlx_hw *hw = &adapter->hw;
++ struct dev_mc_list *mc_ptr;
++ u32 rctl;
++ u32 hash_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);
++ /* 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);
++ }
+}
+
+/*
-+ * 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
++ * atlx_irq_enable - Enable default interrupt generation settings
++ * @adapter: board private structure
+ */
-+static void atl1_via_workaround(struct atl1_adapter *adapter)
++static void atlx_irq_enable(struct atlx_adapter *adapter)
+{
-+ unsigned long value;
++ iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
++ ioread32(adapter->hw.hw_addr + REG_IMR);
++}
+
-+ 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);
++/*
++ * 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 atl1_inc_smb(struct atl1_adapter *adapter)
++static void atlx_clear_phy_int(struct atlx_adapter *adapter)
+{
-+ struct stats_msg_block *smb = adapter->smb.smb;
++ u16 phy_data;
++ unsigned long flags;
+
-+ /* 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);
++ spin_lock_irqsave(&adapter->lock, flags);
++ atlx_read_phy_reg(&adapter->hw, 19, &phy_data);
++ spin_unlock_irqrestore(&adapter->lock, flags);
++}
+
-+ /* 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);
++/*
++ * 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;
++}
+
-+ 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;
++/*
++ * 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);
++}
+
-+ /* 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;
++/*
++ * 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->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 = container_of(work, struct atlx_adapter, link_chg_task);
+
-+ 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;
++ spin_lock_irqsave(&adapter->lock, flags);
++ atlx_check_link(adapter);
++ spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
-+static void atl1_update_mailbox(struct atl1_adapter *adapter)
++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 tpd_next_to_use;
-+ u32 rfd_next_to_use;
-+ u32 rrd_next_to_clean;
-+ u32 value;
-+
-+ spin_lock_irqsave(&adapter->mb_lock, flags);
++ u32 ctrl;
+
-+ 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);
++ spin_lock_irqsave(&adapter->lock, flags);
++ /* atlx_irq_disable(adapter); FIXME: confirm/remove */
++ adapter->vlgrp = grp;
+
-+ 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);
++ 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);
++ }
+
-+ spin_unlock_irqrestore(&adapter->mb_lock, flags);
++ /* atlx_irq_enable(adapter); FIXME */
++ spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
-+static void atl1_clean_alloc_flag(struct atl1_adapter *adapter,
-+ struct rx_return_desc *rrd, u16 offset)
++static void atlx_restore_vlan(struct atlx_adapter *adapter)
+{
-+ 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;
-+ }
-+ }
++ atlx_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+}
+
-+static void atl1_update_rfd_index(struct atl1_adapter *adapter,
-+ struct rx_return_desc *rrd)
-+{
-+ u16 num_buf;
++#endif /* ATLX_C */
+diff --git a/drivers/net/atlx/atlx.h b/drivers/net/atlx/atlx.h
+new file mode 100644
+index 0000000..3be7c09
+--- /dev/null
++++ b/drivers/net/atlx/atlx.h
+@@ -0,0 +1,506 @@
++/* atlx_hw.h -- common hardware definitions for Attansic network drivers
++ *
++ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
++ * Copyright(c) 2006 - 2007 Chris Snook <csnook at redhat.com>
++ * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
++ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
++ *
++ * Derived from Intel e1000 driver
++ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 2 of the License, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 59
++ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
+
-+ 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);
-+}
++#ifndef ATLX_H
++#define ATLX_H
+
-+static void atl1_rx_checksum(struct atl1_adapter *adapter,
-+ struct rx_return_desc *rrd, struct sk_buff *skb)
-+{
-+ struct pci_dev *pdev = adapter->pdev;
++#include <linux/module.h>
++#include <linux/types.h>
+
-+ skb->ip_summed = CHECKSUM_NONE;
++#define ATLX_DRIVER_VERSION "2.1.1"
++MODULE_AUTHOR("Xiong Huang <xiong.huang at atheros.com>, \
++ Chris Snook <csnook at redhat.com>, Jay Cliburn <jcliburn at gmail.com>");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(ATLX_DRIVER_VERSION);
+
-+ 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;
-+ }
-+ }
++#define ATLX_ERR_PHY 2
++#define ATLX_ERR_PHY_SPEED 7
++#define ATLX_ERR_PHY_RES 8
+
-+ /* not IPv4 */
-+ if (!(rrd->pkt_flg & PACKET_FLAG_IPV4))
-+ /* checksum is invalid, but it's not an IPv4 pkt, so ok */
-+ return;
++#define SPEED_0 0xffff
++#define SPEED_10 10
++#define SPEED_100 100
++#define SPEED_1000 1000
++#define HALF_DUPLEX 1
++#define FULL_DUPLEX 2
+
-+ /* 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;
-+ }
++#define MEDIA_TYPE_AUTO_SENSOR 0
+
-+ /* 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;
-+}
++/* register definitions */
++#define REG_PM_CTRLSTAT 0x44
+
-+/*
-+ * 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;
++#define REG_PCIE_CAP_LIST 0x58
+
-+ 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];
++#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
+
-+ while (!buffer_info->alloced && !next_info->alloced) {
-+ if (buffer_info->skb) {
-+ buffer_info->alloced = 1;
-+ goto next;
-+ }
++#define REG_VPD_DATA 0x70
+
-+ rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use);
++#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
+
-+ skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
-+ if (unlikely(!skb)) {
-+ /* Better luck next round */
-+ adapter->net_stats.rx_dropped++;
-+ break;
-+ }
++#define REG_SPI_ADDR 0x204
+
-+ /*
-+ * 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);
++#define REG_SPI_DATA 0x208
+
-+ 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;
++#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
+
-+next:
-+ rfd_next_to_use = next_next;
-+ if (unlikely(++next_next == rfd_ring->count))
-+ next_next = 0;
++#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
+
-+ buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
-+ next_info = &rfd_ring->buffer_info[next_next];
-+ num_alloc++;
-+ }
++#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
+
-+ 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;
-+}
++#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
+
-+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;
++#define REG_PCIE_PHYMISC 0x1000
++#define PCIE_PHYMISC_FORCE_RCV_DET 0x4
+
-+ count = 0;
++#define REG_PCIE_DLL_TX_CTRL1 0x1104
++#define PCIE_DLL_TX_CTRL1_SEL_NOR_CLK 0x400
++#define PCIE_DLL_TX_CTRL1_DEF 0x568
+
-+ rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean);
++#define REG_LTSSM_TEST_MODE 0x12FC
++#define LTSSM_TEST_MODE_DEF 0x6500
+
-+ 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);
-+ }
++/* 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
+
-+ /* 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);
++/* Timer Initial Value Register */
++#define REG_MANUAL_TIMER_INIT 0x1404
+
-+ /* 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 */
++/* IRQ Moderator Timer Initial Value Register */
++#define REG_IRQ_MODU_TIMER_INIT 0x1408
+
-+ break;
-+ }
-+rrd_ok:
-+ /* clean alloc flag for bad rrd */
-+ atl1_clean_alloc_flag(adapter, rrd, 0);
++#define REG_PHY_ENABLE 0x140C
+
-+ buffer_info = &rfd_ring->buffer_info[rrd->buf_indx];
-+ if (++rfd_ring->next_to_clean == rfd_ring->count)
-+ rfd_ring->next_to_clean = 0;
++/* IRQ Anti-Lost Timer Initial Value Register */
++#define REG_CMBDISDMA_TIMER 0x140E
+
-+ /* update rrd next to clean */
-+ if (++rrd_next_to_clean == rrd_ring->count)
-+ rrd_next_to_clean = 0;
-+ count++;
++/* Block IDLE Status Register */
++#define REG_IDLE_STATUS 0x1410
+
-+ 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;
-+ }
-+ }
++/* 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
+
-+ /* 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);
++/* MII PHY Status Register */
++#define REG_PHY_STATUS 0x1418
+
-+ skb_put(skb, length - ETH_FCS_LEN);
++/* 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
+
-+ /* Receive Checksum Offload */
-+ atl1_rx_checksum(adapter, rrd, skb);
-+ skb->protocol = eth_type_trans(skb, adapter->netdev);
++/* SerDes Lock Detect Control and Status Register */
++#define REG_SERDES_LOCK 0x1424
++#define SERDES_LOCK_DETECT 1
++#define SERDES_LOCK_DETECT_EN 2
+
-+ 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);
++/* 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
+
-+ /* let protocol layer free skb */
-+ buffer_info->skb = NULL;
-+ buffer_info->alloced = 0;
-+ rrd->xsz.valid = 0;
++/* 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
+
-+ adapter->netdev->last_rx = jiffies;
-+ }
++/* MAC STATION ADDRESS */
++#define REG_MAC_STA_ADDR 0x1488
+
-+ atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean);
++/* Hash table for multicast address */
++#define REG_RX_HASH_TABLE 0x1490
+
-+ atl1_alloc_rx_buffers(adapter);
++/* 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
+
-+ /* update mailbox ? */
-+ if (count) {
-+ u32 tpd_next_to_use;
-+ u32 rfd_next_to_use;
++/* Maximum Frame Length Control Register */
++#define REG_MTU 0x149C
+
-+ spin_lock(&adapter->mb_lock);
++/* 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
+
-+ 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);
-+ }
-+}
++/* Internal SRAM Partition Register, high 32 bits */
++#define REG_SRAM_RFD_ADDR 0x1500
+
-+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;
++/* Descriptor Control register, high 32 bits */
++#define REG_DESC_BASE_ADDR_HI 0x1540
+
-+ 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);
++/* 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
+
-+ while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
-+ struct tx_packet_desc *tpd;
++/* Interrupt Mask Register */
++#define REG_IMR 0x1604
+
-+ 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;
-+ }
++#define REG_RFD_RRD_IDX 0x1800
++#define REG_TPD_IDX 0x1804
+
-+ if (buffer_info->skb) {
-+ dev_kfree_skb_irq(buffer_info->skb);
-+ buffer_info->skb = NULL;
-+ }
++/* MII definitions */
+
-+ 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);
++/* 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
+
-+ if (netif_queue_stopped(adapter->netdev)
-+ && netif_carrier_ok(adapter->netdev))
-+ netif_wake_queue(adapter->netdev);
++/* PHY Control Register */
++#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100,
++ * 00=10
++ */
++#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
++#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
++#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
++#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
++#define MII_CR_POWER_DOWN 0x0800 /* Power down */
++#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
++#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100,
++ * 00=10
++ */
++#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
++#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
++#define MII_CR_SPEED_MASK 0x2040
++#define MII_CR_SPEED_1000 0x0040
++#define MII_CR_SPEED_100 0x2000
++#define MII_CR_SPEED_10 0x0000
++
++/* PHY Status Register */
++#define MII_SR_EXTENDED_CAPS 0x0001 /* Ext register capabilities */
++#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
++#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
++#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */
++#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */
++#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
++#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
++#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext stat info in Reg 0x0F */
++#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */
++#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */
++#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */
++#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */
++#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */
++#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
++#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
++
++/* Link partner ability register */
++#define MII_LPA_SLCT 0x001f /* Same as advertise selector */
++#define MII_LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
++#define MII_LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
++#define MII_LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
++#define MII_LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
++#define MII_LPA_100BASE4 0x0200 /* 100BASE-T4 */
++#define MII_LPA_PAUSE 0x0400 /* PAUSE */
++#define MII_LPA_ASYPAUSE 0x0800 /* Asymmetrical PAUSE */
++#define MII_LPA_RFAULT 0x2000 /* Link partner faulted */
++#define MII_LPA_LPACK 0x4000 /* Link partner acked us */
++#define MII_LPA_NPAGE 0x8000 /* Next page bit */
++
++/* Autoneg Advertisement Register */
++#define MII_AR_SELECTOR_FIELD 0x0001 /* IEEE 802.3 CSMA/CD */
++#define MII_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
++#define MII_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
++#define MII_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
++#define MII_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
++#define MII_AR_100T4_CAPS 0x0200 /* 100T4 Capable */
++#define MII_AR_PAUSE 0x0400 /* Pause operation desired */
++#define MII_AR_ASM_DIR 0x0800 /* Asymmetric Pause Dir bit */
++#define MII_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */
++#define MII_AR_NEXT_PAGE 0x8000 /* Next Page ability support */
++#define MII_AR_SPEED_MASK 0x01E0
++#define MII_AR_DEFAULT_CAP_MASK 0x0DE0
++
++/* 1000BASE-T Control Register */
++#define MII_ATLX_CR_1000T_HD_CAPS 0x0100 /* Adv 1000T HD cap */
++#define MII_ATLX_CR_1000T_FD_CAPS 0x0200 /* Adv 1000T FD cap */
++#define MII_ATLX_CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device,
++ * 0=DTE device */
++#define MII_ATLX_CR_1000T_MS_VALUE 0x0800 /* 1=Config PHY as Master,
++ * 0=Configure PHY as Slave */
++#define MII_ATLX_CR_1000T_MS_ENABLE 0x1000 /* 1=Man Master/Slave config,
++ * 0=Auto Master/Slave config
++ */
++#define MII_ATLX_CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
++#define MII_ATLX_CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */
++#define MII_ATLX_CR_1000T_TEST_MODE_2 0x4000 /* Master Xmit Jitter test */
++#define MII_ATLX_CR_1000T_TEST_MODE_3 0x6000 /* Slave Xmit Jitter test */
++#define MII_ATLX_CR_1000T_TEST_MODE_4 0x8000 /* Xmitter Distortion test */
++#define MII_ATLX_CR_1000T_SPEED_MASK 0x0300
++#define MII_ATLX_CR_1000T_DEFAULT_CAP_MASK 0x0300
++
++/* 1000BASE-T Status Register */
++#define MII_ATLX_SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */
++#define MII_ATLX_SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */
++#define MII_ATLX_SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
++#define MII_ATLX_SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */
++#define MII_ATLX_SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master
++ * 0=Slave
++ */
++#define MII_ATLX_SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config
++ * fault */
++#define MII_ATLX_SR_1000T_REMOTE_RX_STATUS_SHIFT 12
++#define MII_ATLX_SR_1000T_LOCAL_RX_STATUS_SHIFT 13
++
++/* Extended Status Register */
++#define MII_ATLX_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */
++#define MII_ATLX_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */
++#define MII_ATLX_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */
++#define MII_ATLX_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */
++
++/* ATLX PHY Specific Control Register */
++#define MII_ATLX_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Func disabled */
++#define MII_ATLX_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enbld */
++#define MII_ATLX_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */
++#define MII_ATLX_PSCR_MAC_POWERDOWN 0x0008
++#define MII_ATLX_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low
++ * 0=CLK125 toggling
++ */
++#define MII_ATLX_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5,
++ * Manual MDI configuration
++ */
++#define MII_ATLX_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */
++#define MII_ATLX_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover
++ * 100BASE-TX/10BASE-T: MDI
++ * Mode */
++#define MII_ATLX_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled
++ * all speeds.
++ */
++#define MII_ATLX_PSCR_10BT_EXT_DIST_ENABLE 0x0080 /* 1=Enable Extended
++ * 10BASE-T distance
++ * (Lower 10BASE-T RX
++ * Threshold)
++ * 0=Normal 10BASE-T RX
++ * Threshold
++ */
++#define MII_ATLX_PSCR_MII_5BIT_ENABLE 0x0100 /* 1=5-Bit interface in
++ * 100BASE-TX
++ * 0=MII interface in
++ * 100BASE-TX
++ */
++#define MII_ATLX_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler dsbl */
++#define MII_ATLX_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */
++#define MII_ATLX_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
++#define MII_ATLX_PSCR_POLARITY_REVERSAL_SHIFT 1
++#define MII_ATLX_PSCR_AUTO_X_MODE_SHIFT 5
++#define MII_ATLX_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7
++
++/* ATLX PHY Specific Status Register */
++#define MII_ATLX_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */
++#define MII_ATLX_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */
++#define MII_ATLX_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */
++#define MII_ATLX_PSSR_10MBS 0x0000 /* 00=10Mbs */
++#define MII_ATLX_PSSR_100MBS 0x4000 /* 01=100Mbs */
++#define MII_ATLX_PSSR_1000MBS 0x8000 /* 10=1000Mbs */
++
++/* PCI Command Register Bit Definitions */
++#define PCI_REG_COMMAND 0x04 /* PCI Command Register */
++#define CMD_IO_SPACE 0x0001
++#define CMD_MEMORY_SPACE 0x0002
++#define CMD_BUS_MASTER 0x0004
++
++/* Wake Up Filter Control */
++#define ATLX_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
++#define ATLX_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
++#define ATLX_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
++#define ATLX_WUFC_MC 0x00000008 /* Multicast Wakeup Enable */
++#define ATLX_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
++
++#define ADVERTISE_10_HALF 0x0001
++#define ADVERTISE_10_FULL 0x0002
++#define ADVERTISE_100_HALF 0x0004
++#define ADVERTISE_100_FULL 0x0008
++#define ADVERTISE_1000_HALF 0x0010
++#define ADVERTISE_1000_FULL 0x0020
++#define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds */
++#define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds */
++
++#define PHY_AUTO_NEG_TIME 45 /* 4.5 Seconds */
++#define PHY_FORCE_TIME 20 /* 2.0 Seconds */
++
++/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA */
++#define EEPROM_SUM 0xBABA
++#define NODE_ADDRESS_SIZE 6
++
++struct atlx_spi_flash_dev {
++ const char *manu_name; /* manufacturer id */
++ /* op-code */
++ u8 cmd_wrsr;
++ u8 cmd_read;
++ u8 cmd_program;
++ u8 cmd_wren;
++ u8 cmd_wrdi;
++ u8 cmd_rdsr;
++ u8 cmd_rdid;
++ u8 cmd_sector_erase;
++ u8 cmd_chip_erase;
++};
++
++#endif /* ATLX_H */
+diff --git a/drivers/net/atp.c b/drivers/net/atp.c
+index 62f09e5..3d44333 100644
+--- a/drivers/net/atp.c
++++ b/drivers/net/atp.c
+@@ -378,8 +378,8 @@ static void __init get_node_ID(struct net_device *dev)
+ sa_offset = 15;
+
+ for (i = 0; i < 3; i++)
+- ((u16 *)dev->dev_addr)[i] =
+- be16_to_cpu(eeprom_op(ioaddr, EE_READ(sa_offset + i)));
++ ((__be16 *)dev->dev_addr)[i] =
++ cpu_to_be16(eeprom_op(ioaddr, EE_READ(sa_offset + i)));
+
+ write_reg(ioaddr, CMR2, CMR2_NULL);
+ }
+diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
+index 504b7ce..3634b5f 100644
+--- a/drivers/net/au1000_eth.c
++++ b/drivers/net/au1000_eth.c
+@@ -701,7 +701,7 @@ static struct net_device * au1000_probe(int port_num)
+ aup->mii_bus.write = mdiobus_write;
+ aup->mii_bus.reset = mdiobus_reset;
+ aup->mii_bus.name = "au1000_eth_mii";
+- aup->mii_bus.id = aup->mac_id;
++ snprintf(aup->mii_bus.id, MII_BUS_ID_SIZE, "%x", aup->mac_id);
+ aup->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+ for(i = 0; i < PHY_MAX_ADDR; ++i)
+ aup->mii_bus.irq[i] = PHY_POLL;
+@@ -709,11 +709,11 @@ static struct net_device * au1000_probe(int port_num)
+ /* if known, set corresponding PHY IRQs */
+ #if defined(AU1XXX_PHY_STATIC_CONFIG)
+ # if defined(AU1XXX_PHY0_IRQ)
+- if (AU1XXX_PHY0_BUSID == aup->mii_bus.id)
++ if (AU1XXX_PHY0_BUSID == aup->mac_id)
+ aup->mii_bus.irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ;
+ # endif
+ # if defined(AU1XXX_PHY1_IRQ)
+- if (AU1XXX_PHY1_BUSID == aup->mii_bus.id)
++ if (AU1XXX_PHY1_BUSID == aup->mac_id)
+ aup->mii_bus.irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ;
+ # endif
+ #endif
+diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
+index 194949a..0b4adf4 100644
+--- a/drivers/net/ax88796.c
++++ b/drivers/net/ax88796.c
+@@ -1005,3 +1005,4 @@ module_exit(axdrv_exit);
+ MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");
+ MODULE_AUTHOR("Ben Dooks, <ben at simtec.co.uk>");
+ MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:ax88796");
+diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
+index 26b2dd5..89c0018 100644
+--- a/drivers/net/bfin_mac.c
++++ b/drivers/net/bfin_mac.c
+@@ -27,6 +27,7 @@
+ #include <linux/phy.h>
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
++#include <linux/ethtool.h>
+ #include <linux/skbuff.h>
+ #include <linux/platform_device.h>
+
+@@ -42,11 +43,12 @@
+ #define DRV_NAME "bfin_mac"
+ #define DRV_VERSION "1.1"
+ #define DRV_AUTHOR "Bryan Wu, Luke Yang"
+-#define DRV_DESC "Blackfin BF53[67] BF527 on-chip Ethernet MAC driver"
++#define DRV_DESC "Blackfin on-chip Ethernet MAC driver"
+
+ 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)
+@@ -72,8 +74,14 @@ static struct net_dma_desc_tx *current_tx_ptr;
+ static struct net_dma_desc_tx *tx_desc;
+ static struct net_dma_desc_rx *rx_desc;
+
+-static void bf537mac_disable(void);
+-static void bf537mac_enable(void);
++#if defined(CONFIG_BFIN_MAC_RMII)
++static u16 pin_req[] = P_RMII0;
++#else
++static u16 pin_req[] = P_MII0;
++#endif
++
++static void bfin_mac_disable(void);
++static void bfin_mac_enable(void);
+
+ static void desc_list_free(void)
+ {
+@@ -242,27 +250,6 @@ init_error:
+
+ /*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/
+
+-/* Set FER regs to MUX in Ethernet pins */
+-static int setup_pin_mux(int action)
+-{
+-#if defined(CONFIG_BFIN_MAC_RMII)
+- u16 pin_req[] = P_RMII0;
+-#else
+- u16 pin_req[] = P_MII0;
+-#endif
+-
+- if (action) {
+- if (peripheral_request_list(pin_req, DRV_NAME)) {
+- printk(KERN_ERR DRV_NAME
+- ": Requesting Peripherals failed\n");
+- return -EFAULT;
+- }
+- } else
+- peripheral_free_list(pin_req);
+-
+- return 0;
+-}
+-
+ /*
+ * MII operations
+ */
+@@ -321,9 +308,9 @@ static int mdiobus_reset(struct mii_bus *bus)
+ return 0;
+ }
+
+-static void bf537_adjust_link(struct net_device *dev)
++static void bfin_mac_adjust_link(struct net_device *dev)
+ {
+- struct bf537mac_local *lp = netdev_priv(dev);
++ struct bfin_mac_local *lp = netdev_priv(dev);
+ struct phy_device *phydev = lp->phydev;
+ unsigned long flags;
+ int new_state = 0;
+@@ -394,7 +381,7 @@ static void bf537_adjust_link(struct net_device *dev)
+
+ static int mii_probe(struct net_device *dev)
+ {
+- struct bf537mac_local *lp = netdev_priv(dev);
++ struct bfin_mac_local *lp = netdev_priv(dev);
+ struct phy_device *phydev = NULL;
+ unsigned short sysctl;
+ int i;
+@@ -430,10 +417,10 @@ static int mii_probe(struct net_device *dev)
+ }
+
+ #if defined(CONFIG_BFIN_MAC_RMII)
+- phydev = phy_connect(dev, phydev->dev.bus_id, &bf537_adjust_link, 0,
++ phydev = phy_connect(dev, phydev->dev.bus_id, &bfin_mac_adjust_link, 0,
+ PHY_INTERFACE_MODE_RMII);
+ #else
+- phydev = phy_connect(dev, phydev->dev.bus_id, &bf537_adjust_link, 0,
++ phydev = phy_connect(dev, phydev->dev.bus_id, &bfin_mac_adjust_link, 0,
+ PHY_INTERFACE_MODE_MII);
+ #endif
+
+@@ -468,6 +455,51 @@ static int mii_probe(struct net_device *dev)
+ return 0;
+ }
+
++/*
++ * Ethtool support
++ */
++
++static int
++bfin_mac_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++ struct bfin_mac_local *lp = netdev_priv(dev);
++
++ if (lp->phydev)
++ return phy_ethtool_gset(lp->phydev, cmd);
++
++ return -EINVAL;
+}
+
-+static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring)
++static int
++bfin_mac_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
-+ 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);
++ struct bfin_mac_local *lp = netdev_priv(dev);
++
++ if (!capable(CAP_NET_ADMIN))
++ return -EPERM;
++
++ if (lp->phydev)
++ return phy_ethtool_sset(lp->phydev, cmd);
++
++ return -EINVAL;
+}
+
-+static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
-+ struct tx_packet_desc *ptpd)
++static void bfin_mac_ethtool_getdrvinfo(struct net_device *dev,
++ struct ethtool_drvinfo *info)
+{
-+ /* spinlock held */
-+ u8 hdr_len, ip_off;
-+ u32 real_len;
-+ int err;
++ strcpy(info->driver, DRV_NAME);
++ strcpy(info->version, DRV_VERSION);
++ strcpy(info->fw_version, "N/A");
++ strcpy(info->bus_info, dev->dev.bus_id);
++}
+
-+ 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;
-+ }
++static struct ethtool_ops bfin_mac_ethtool_ops = {
++ .get_settings = bfin_mac_ethtool_getsettings,
++ .set_settings = bfin_mac_ethtool_setsettings,
++ .get_link = ethtool_op_get_link,
++ .get_drvinfo = bfin_mac_ethtool_getdrvinfo,
++};
+
-+ if (skb->protocol == ntohs(ETH_P_IP)) {
-+ struct iphdr *iph = ip_hdr(skb);
+ /**************************************************************************/
+ void setup_system_regs(struct net_device *dev)
+ {
+@@ -510,7 +542,7 @@ static void setup_mac_addr(u8 *mac_addr)
+ bfin_write_EMAC_ADDRHI(addr_hi);
+ }
+
+-static int bf537mac_set_mac_address(struct net_device *dev, void *p)
++static int bfin_mac_set_mac_address(struct net_device *dev, void *p)
+ {
+ struct sockaddr *addr = p;
+ if (netif_running(dev))
+@@ -572,7 +604,7 @@ adjust_head:
+
+ }
+
+-static int bf537mac_hard_start_xmit(struct sk_buff *skb,
++static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+ {
+ unsigned int data;
+@@ -630,7 +662,7 @@ out:
+ return 0;
+ }
+
+-static void bf537mac_rx(struct net_device *dev)
++static void bfin_mac_rx(struct net_device *dev)
+ {
+ struct sk_buff *skb, *new_skb;
+ unsigned short len;
+@@ -679,7 +711,7 @@ out:
+ }
+
+ /* interrupt routine to handle rx and error signal */
+-static irqreturn_t bf537mac_interrupt(int irq, void *dev_id)
++static irqreturn_t bfin_mac_interrupt(int irq, void *dev_id)
+ {
+ struct net_device *dev = dev_id;
+ int number = 0;
+@@ -699,21 +731,21 @@ get_one_packet:
+ }
+
+ real_rx:
+- bf537mac_rx(dev);
++ bfin_mac_rx(dev);
+ number++;
+ goto get_one_packet;
+ }
+
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+-static void bf537mac_poll(struct net_device *dev)
++static void bfin_mac_poll(struct net_device *dev)
+ {
+ disable_irq(IRQ_MAC_RX);
+- bf537mac_interrupt(IRQ_MAC_RX, dev);
++ bfin_mac_interrupt(IRQ_MAC_RX, dev);
+ enable_irq(IRQ_MAC_RX);
+ }
+ #endif /* CONFIG_NET_POLL_CONTROLLER */
+
+-static void bf537mac_disable(void)
++static void bfin_mac_disable(void)
+ {
+ unsigned int opmode;
+
+@@ -727,7 +759,7 @@ static void bf537mac_disable(void)
+ /*
+ * Enable Interrupts, Receive, and Transmit
+ */
+-static void bf537mac_enable(void)
++static void bfin_mac_enable(void)
+ {
+ u32 opmode;
+
+@@ -765,23 +797,23 @@ static void bf537mac_enable(void)
+ }
+
+ /* Our watchdog timed out. Called by the networking layer */
+-static void bf537mac_timeout(struct net_device *dev)
++static void bfin_mac_timeout(struct net_device *dev)
+ {
+ pr_debug("%s: %s\n", dev->name, __FUNCTION__);
+
+- bf537mac_disable();
++ bfin_mac_disable();
+
+ /* reset tx queue */
+ tx_list_tail = tx_list_head->next;
+
+- bf537mac_enable();
++ bfin_mac_enable();
+
+ /* We can accept TX packets again */
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+ }
+
+-static void bf537mac_multicast_hash(struct net_device *dev)
++static void bfin_mac_multicast_hash(struct net_device *dev)
+ {
+ u32 emac_hashhi, emac_hashlo;
+ struct dev_mc_list *dmi = dev->mc_list;
+@@ -820,7 +852,7 @@ static void bf537mac_multicast_hash(struct net_device *dev)
+ * promiscuous mode (for TCPDUMP and cousins) or accept
+ * a select set of multicast packets
+ */
+-static void bf537mac_set_multicast_list(struct net_device *dev)
++static void bfin_mac_set_multicast_list(struct net_device *dev)
+ {
+ u32 sysctl;
+
+@@ -839,7 +871,7 @@ static void bf537mac_set_multicast_list(struct net_device *dev)
+ sysctl = bfin_read_EMAC_OPMODE();
+ sysctl |= HM;
+ bfin_write_EMAC_OPMODE(sysctl);
+- bf537mac_multicast_hash(dev);
++ bfin_mac_multicast_hash(dev);
+ } else {
+ /* clear promisc or multicast mode */
+ sysctl = bfin_read_EMAC_OPMODE();
+@@ -851,7 +883,7 @@ static void bf537mac_set_multicast_list(struct net_device *dev)
+ /*
+ * this puts the device in an inactive state
+ */
+-static void bf537mac_shutdown(struct net_device *dev)
++static void bfin_mac_shutdown(struct net_device *dev)
+ {
+ /* Turn off the EMAC */
+ bfin_write_EMAC_OPMODE(0x00000000);
+@@ -865,9 +897,9 @@ static void bf537mac_shutdown(struct net_device *dev)
+ *
+ * Set up everything, reset the card, etc..
+ */
+-static int bf537mac_open(struct net_device *dev)
++static int bfin_mac_open(struct net_device *dev)
+ {
+- struct bf537mac_local *lp = netdev_priv(dev);
++ struct bfin_mac_local *lp = netdev_priv(dev);
+ int retval;
+ pr_debug("%s: %s\n", dev->name, __FUNCTION__);
+
+@@ -890,8 +922,8 @@ static int bf537mac_open(struct net_device *dev)
+ phy_start(lp->phydev);
+ phy_write(lp->phydev, MII_BMCR, BMCR_RESET);
+ setup_system_regs(dev);
+- bf537mac_disable();
+- bf537mac_enable();
++ bfin_mac_disable();
++ bfin_mac_enable();
+ pr_debug("hardware init finished\n");
+ netif_start_queue(dev);
+ netif_carrier_on(dev);
+@@ -905,9 +937,9 @@ static int bf537mac_open(struct net_device *dev)
+ * and not talk to the outside world. Caused by
+ * an 'ifconfig ethX down'
+ */
+-static int bf537mac_close(struct net_device *dev)
++static int bfin_mac_close(struct net_device *dev)
+ {
+- struct bf537mac_local *lp = netdev_priv(dev);
++ struct bfin_mac_local *lp = netdev_priv(dev);
+ pr_debug("%s: %s\n", dev->name, __FUNCTION__);
+
+ netif_stop_queue(dev);
+@@ -917,7 +949,7 @@ static int bf537mac_close(struct net_device *dev)
+ phy_write(lp->phydev, MII_BMCR, BMCR_PDOWN);
+
+ /* clear everything */
+- bf537mac_shutdown(dev);
++ bfin_mac_shutdown(dev);
+
+ /* free the rx/tx buffers */
+ desc_list_free();
+@@ -925,135 +957,148 @@ static int bf537mac_close(struct net_device *dev)
+ return 0;
+ }
+
+-static int __init bf537mac_probe(struct net_device *dev)
++static int __init bfin_mac_probe(struct platform_device *pdev)
+ {
+- struct bf537mac_local *lp = netdev_priv(dev);
+- int retval;
+- int i;
++ struct net_device *ndev;
++ struct bfin_mac_local *lp;
++ int rc, i;
+
-+ 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;
-+ }
++ ndev = alloc_etherdev(sizeof(struct bfin_mac_local));
++ if (!ndev) {
++ dev_err(&pdev->dev, "Cannot allocate net device!\n");
++ return -ENOMEM;
++ }
+
-+ 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;
++ SET_NETDEV_DEV(ndev, &pdev->dev);
++ platform_set_drvdata(pdev, ndev);
++ lp = netdev_priv(ndev);
+
+ /* Grab the MAC address in the MAC */
+- *(__le32 *) (&(dev->dev_addr[0])) = cpu_to_le32(bfin_read_EMAC_ADDRLO());
+- *(__le16 *) (&(dev->dev_addr[4])) = cpu_to_le16((u16) bfin_read_EMAC_ADDRHI());
++ *(__le32 *) (&(ndev->dev_addr[0])) = cpu_to_le32(bfin_read_EMAC_ADDRLO());
++ *(__le16 *) (&(ndev->dev_addr[4])) = cpu_to_le16((u16) bfin_read_EMAC_ADDRHI());
+
+ /* probe mac */
+ /*todo: how to proble? which is revision_register */
+ bfin_write_EMAC_ADDRLO(0x12345678);
+ if (bfin_read_EMAC_ADDRLO() != 0x12345678) {
+- pr_debug("can't detect bf537 mac!\n");
+- retval = -ENODEV;
+- goto err_out;
++ dev_err(&pdev->dev, "Cannot detect Blackfin on-chip ethernet MAC controller!\n");
++ rc = -ENODEV;
++ goto out_err_probe_mac;
+ }
+
+ /* set the GPIO pins to Ethernet mode */
+- retval = setup_pin_mux(1);
+- if (retval)
+- return retval;
+-
+- /*Is it valid? (Did bootloader initialize it?) */
+- if (!is_valid_ether_addr(dev->dev_addr)) {
+- /* Grab the MAC from the board somehow - this is done in the
+- arch/blackfin/mach-bf537/boards/eth_mac.c */
+- bfin_get_ether_addr(dev->dev_addr);
++ rc = peripheral_request_list(pin_req, DRV_NAME);
++ if (rc) {
++ dev_err(&pdev->dev, "Requesting peripherals failed!\n");
++ rc = -EFAULT;
++ goto out_err_setup_pin_mux;
+ }
+
++ /*
++ * Is it valid? (Did bootloader initialize it?)
++ * Grab the MAC from the board somehow
++ * this is done in the arch/blackfin/mach-bfxxx/boards/eth_mac.c
++ */
++ if (!is_valid_ether_addr(ndev->dev_addr))
++ bfin_get_ether_addr(ndev->dev_addr);
+
-+ 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;
-+ }
+ /* If still not valid, get a random one */
+- if (!is_valid_ether_addr(dev->dev_addr)) {
+- random_ether_addr(dev->dev_addr);
+- }
++ if (!is_valid_ether_addr(ndev->dev_addr))
++ random_ether_addr(ndev->dev_addr);
+
+- setup_mac_addr(dev->dev_addr);
++ setup_mac_addr(ndev->dev_addr);
+
+ /* MDIO bus initial */
+- lp->mii_bus.priv = dev;
++ lp->mii_bus.priv = ndev;
+ lp->mii_bus.read = mdiobus_read;
+ 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;
+
+- mdiobus_register(&lp->mii_bus);
++ rc = mdiobus_register(&lp->mii_bus);
++ if (rc) {
++ dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
++ goto out_err_mdiobus_register;
+ }
+
+- retval = mii_probe(dev);
+- if (retval)
+- return retval;
++ rc = mii_probe(ndev);
++ if (rc) {
++ dev_err(&pdev->dev, "MII Probe failed!\n");
++ goto out_err_mii_probe;
++ }
+
+ /* Fill in the fields of the device structure with ethernet values. */
+- ether_setup(dev);
+-
+- dev->open = bf537mac_open;
+- dev->stop = bf537mac_close;
+- dev->hard_start_xmit = bf537mac_hard_start_xmit;
+- dev->set_mac_address = bf537mac_set_mac_address;
+- dev->tx_timeout = bf537mac_timeout;
+- dev->set_multicast_list = bf537mac_set_multicast_list;
++ ether_setup(ndev);
++
++ ndev->open = bfin_mac_open;
++ ndev->stop = bfin_mac_close;
++ ndev->hard_start_xmit = bfin_mac_hard_start_xmit;
++ ndev->set_mac_address = bfin_mac_set_mac_address;
++ ndev->tx_timeout = bfin_mac_timeout;
++ ndev->set_multicast_list = bfin_mac_set_multicast_list;
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+- dev->poll_controller = bf537mac_poll;
++ ndev->poll_controller = bfin_mac_poll;
+ #endif
++ ndev->ethtool_ops = &bfin_mac_ethtool_ops;
+
+ spin_lock_init(&lp->lock);
+
+ /* now, enable interrupts */
+ /* register irq handler */
+- if (request_irq
+- (IRQ_MAC_RX, bf537mac_interrupt, IRQF_DISABLED | IRQF_SHARED,
+- "EMAC_RX", dev)) {
+- printk(KERN_WARNING DRV_NAME
+- ": Unable to attach BlackFin MAC RX interrupt\n");
+- return -EBUSY;
+- }
+-
+-
+- retval = register_netdev(dev);
+- if (retval == 0) {
+- /* now, print out the card info, in a short format.. */
+- printk(KERN_INFO "%s: Version %s, %s\n",
+- DRV_NAME, DRV_VERSION, DRV_DESC);
++ rc = request_irq(IRQ_MAC_RX, bfin_mac_interrupt,
++ IRQF_DISABLED | IRQF_SHARED, "EMAC_RX", ndev);
++ if (rc) {
++ dev_err(&pdev->dev, "Cannot request Blackfin MAC RX IRQ!\n");
++ rc = -EBUSY;
++ goto out_err_request_irq;
+ }
+
+-err_out:
+- return retval;
+-}
+-
+-static int bfin_mac_probe(struct platform_device *pdev)
+-{
+- struct net_device *ndev;
+-
+- ndev = alloc_etherdev(sizeof(struct bf537mac_local));
+- if (!ndev) {
+- printk(KERN_WARNING DRV_NAME ": could not allocate device\n");
+- return -ENOMEM;
++ rc = register_netdev(ndev);
++ if (rc) {
++ dev_err(&pdev->dev, "Cannot register net device!\n");
++ goto out_err_reg_ndev;
+ }
+
+- SET_NETDEV_DEV(ndev, &pdev->dev);
++ /* now, print out the card info, in a short format.. */
++ dev_info(&pdev->dev, "%s, Version %s\n", DRV_DESC, DRV_VERSION);
+
+- platform_set_drvdata(pdev, ndev);
++ return 0;
+
+- if (bf537mac_probe(ndev) != 0) {
+- platform_set_drvdata(pdev, NULL);
+- free_netdev(ndev);
+- printk(KERN_WARNING DRV_NAME ": not found\n");
+- return -ENODEV;
+- }
++out_err_reg_ndev:
++ free_irq(IRQ_MAC_RX, ndev);
++out_err_request_irq:
++out_err_mii_probe:
++ mdiobus_unregister(&lp->mii_bus);
++out_err_mdiobus_register:
++ peripheral_free_list(pin_req);
++out_err_setup_pin_mux:
++out_err_probe_mac:
++ platform_set_drvdata(pdev, NULL);
++ free_netdev(ndev);
+
+- return 0;
++ return rc;
+ }
+
+ static int bfin_mac_remove(struct platform_device *pdev)
+ {
+ struct net_device *ndev = platform_get_drvdata(pdev);
++ struct bfin_mac_local *lp = netdev_priv(ndev);
+
+ platform_set_drvdata(pdev, NULL);
+
++ mdiobus_unregister(&lp->mii_bus);
++
+ unregister_netdev(ndev);
+
+ free_irq(IRQ_MAC_RX, ndev);
+
+ free_netdev(ndev);
+
+- setup_pin_mux(0);
++ peripheral_free_list(pin_req);
+
+ return 0;
+ }
+@@ -1064,7 +1109,7 @@ static int bfin_mac_suspend(struct platform_device *pdev, pm_message_t mesg)
+ struct net_device *net_dev = platform_get_drvdata(pdev);
+
+ if (netif_running(net_dev))
+- bf537mac_close(net_dev);
++ bfin_mac_close(net_dev);
+
+ return 0;
+ }
+@@ -1074,7 +1119,7 @@ static int bfin_mac_resume(struct platform_device *pdev)
+ struct net_device *net_dev = platform_get_drvdata(pdev);
+
+ if (netif_running(net_dev))
+- bf537mac_open(net_dev);
++ bfin_mac_open(net_dev);
+
+ return 0;
+ }
+@@ -1089,8 +1134,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 +1152,4 @@ static void __exit bfin_mac_cleanup(void)
+ }
+
+ module_exit(bfin_mac_cleanup);
++
+diff --git a/drivers/net/bfin_mac.h b/drivers/net/bfin_mac.h
+index f774d5a..beff510 100644
+--- a/drivers/net/bfin_mac.h
++++ b/drivers/net/bfin_mac.h
+@@ -49,7 +49,7 @@ struct net_dma_desc_tx {
+ struct status_area_tx status;
+ };
+
+-struct bf537mac_local {
++struct bfin_mac_local {
+ /*
+ * these are things that the kernel wants me to keep, so users
+ * can find out semi-useless statistics of how well the card is
+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..6425603 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;
+@@ -3287,17 +3282,14 @@ static int bond_create_proc_entry(struct bonding *bond)
+ struct net_device *bond_dev = bond->dev;
+
+ if (bond_proc_dir) {
+- bond->proc_entry = create_proc_entry(bond_dev->name,
+- S_IRUGO,
+- bond_proc_dir);
++ bond->proc_entry = proc_create_data(bond_dev->name,
++ S_IRUGO, bond_proc_dir,
++ &bond_info_fops, bond);
+ if (bond->proc_entry == NULL) {
+ printk(KERN_WARNING DRV_NAME
+ ": Warning: Cannot create /proc/net/%s/%s\n",
+ DRV_NAME, bond_dev->name);
+ } else {
+- bond->proc_entry->data = bond;
+- bond->proc_entry->proc_fops = &bond_info_fops;
+- bond->proc_entry->owner = THIS_MODULE;
+ memcpy(bond->proc_file_name, bond_dev->name, IFNAMSIZ);
+ }
+ }
+@@ -3473,7 +3465,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 +3503,9 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event,
+ struct bonding *bond, *bond_next;
+ struct vlan_entry *vlan, *vlan_next;
+
++ if (dev_net(ifa->ifa_dev->dev) != &init_net)
++ return NOTIFY_DONE;
++
+ list_for_each_entry_safe(bond, bond_next, &bond_dev_list, bond_list) {
+ if (bond->dev == event_dev) {
+ switch (event) {
+diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
+index 14299f8..93e1363 100644
+--- a/drivers/net/cassini.c
++++ b/drivers/net/cassini.c
+@@ -532,8 +532,7 @@ static void cas_spare_free(struct cas *cp)
+ /* free spare buffers */
+ INIT_LIST_HEAD(&list);
+ spin_lock(&cp->rx_spare_lock);
+- list_splice(&cp->rx_spare_list, &list);
+- INIT_LIST_HEAD(&cp->rx_spare_list);
++ list_splice_init(&cp->rx_spare_list, &list);
+ spin_unlock(&cp->rx_spare_lock);
+ list_for_each_safe(elem, tmp, &list) {
+ cas_page_free(cp, list_entry(elem, cas_page_t, list));
+@@ -546,13 +545,11 @@ static void cas_spare_free(struct cas *cp)
+ * lock than used everywhere else to manipulate this list.
+ */
+ spin_lock(&cp->rx_inuse_lock);
+- list_splice(&cp->rx_inuse_list, &list);
+- INIT_LIST_HEAD(&cp->rx_inuse_list);
++ list_splice_init(&cp->rx_inuse_list, &list);
+ spin_unlock(&cp->rx_inuse_lock);
+ #else
+ spin_lock(&cp->rx_spare_lock);
+- list_splice(&cp->rx_inuse_list, &list);
+- INIT_LIST_HEAD(&cp->rx_inuse_list);
++ list_splice_init(&cp->rx_inuse_list, &list);
+ spin_unlock(&cp->rx_spare_lock);
+ #endif
+ list_for_each_safe(elem, tmp, &list) {
+@@ -573,8 +570,7 @@ static void cas_spare_recover(struct cas *cp, const gfp_t flags)
+ /* make a local copy of the list */
+ INIT_LIST_HEAD(&list);
+ spin_lock(&cp->rx_inuse_lock);
+- list_splice(&cp->rx_inuse_list, &list);
+- INIT_LIST_HEAD(&cp->rx_inuse_list);
++ list_splice_init(&cp->rx_inuse_list, &list);
+ spin_unlock(&cp->rx_inuse_lock);
+
+ list_for_each_safe(elem, tmp, &list) {
+diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
+index c85194f..2b5740b 100644
+--- a/drivers/net/cpmac.c
++++ b/drivers/net/cpmac.c
+@@ -42,6 +42,7 @@
+ MODULE_AUTHOR("Eugene Konev <ejka at imfi.kspu.ru>");
+ MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:cpmac");
+
+ static int debug_level = 8;
+ static int dumb_switch;
+@@ -987,7 +988,7 @@ static int external_switch;
+ static int __devinit cpmac_probe(struct platform_device *pdev)
+ {
+ int rc, phy_id, i;
+- int mdio_bus_id = cpmac_mii.id;
++ char *mdio_bus_id = "0";
+ struct resource *mem;
+ struct cpmac_priv *priv;
+ struct net_device *dev;
+@@ -1008,8 +1009,6 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
+ if (external_switch || dumb_switch) {
+ struct fixed_phy_status status = {};
+
+- mdio_bus_id = 0;
+-
+ /*
+ * FIXME: this should be in the platform code!
+ * Since there is not platform code at all (that is,
+@@ -1105,6 +1104,7 @@ static int __devexit cpmac_remove(struct platform_device *pdev)
+
+ static struct platform_driver cpmac_driver = {
+ .driver.name = "cpmac",
++ .driver.owner = THIS_MODULE,
+ .probe = cpmac_probe,
+ .remove = __devexit_p(cpmac_remove),
+ };
+@@ -1143,6 +1143,7 @@ int __devinit cpmac_init(void)
+ }
+
+ cpmac_mii.phy_mask = ~(mask | 0x80000000);
++ snprintf(cpmac_mii.id, MII_BUS_ID_SIZE, "0");
+
+ res = mdiobus_register(&cpmac_mii);
+ if (res)
+diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
+index eb305a0..4fdb13f 100644
+--- a/drivers/net/cxgb3/adapter.h
++++ b/drivers/net/cxgb3/adapter.h
+@@ -43,7 +43,6 @@
+ #include <linux/mutex.h>
+ #include <linux/bitops.h>
+ #include "t3cdev.h"
+-#include <asm/semaphore.h>
+ #include <asm/io.h>
+
+ struct vlan_group;
+diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
+index fd2e05b..05e5f59 100644
+--- a/drivers/net/cxgb3/cxgb3_main.c
++++ b/drivers/net/cxgb3/cxgb3_main.c
+@@ -1014,8 +1014,8 @@ static int offload_open(struct net_device *dev)
+ adapter->port[0]->mtu : 0xffff);
+ init_smt(adapter);
+
+- /* Never mind if the next step fails */
+- sysfs_create_group(&tdev->lldev->dev.kobj, &offload_attr_group);
++ if (sysfs_create_group(&tdev->lldev->dev.kobj, &offload_attr_group))
++ dev_dbg(&dev->dev, "cannot create sysfs group\n");
+
+ /* Call back all registered clients */
+ cxgb3_add_clients(tdev);
+diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
+index 901c824..ff9c013 100644
+--- a/drivers/net/cxgb3/cxgb3_offload.c
++++ b/drivers/net/cxgb3/cxgb3_offload.c
+@@ -833,10 +833,26 @@ static int do_trace(struct t3cdev *dev, struct sk_buff *skb)
+ return 0;
+ }
+
++/*
++ * That skb would better have come from process_responses() where we abuse
++ * ->priority and ->csum to carry our data. NB: if we get to per-arch
++ * ->csum, the things might get really interesting here.
++ */
++
++static inline u32 get_hwtid(struct sk_buff *skb)
++{
++ return ntohl((__force __be32)skb->priority) >> 8 & 0xfffff;
++}
++
++static inline u32 get_opcode(struct sk_buff *skb)
++{
++ return G_OPCODE(ntohl((__force __be32)skb->csum));
++}
++
+ static int do_term(struct t3cdev *dev, struct sk_buff *skb)
+ {
+- unsigned int hwtid = ntohl(skb->priority) >> 8 & 0xfffff;
+- unsigned int opcode = G_OPCODE(ntohl(skb->csum));
++ unsigned int hwtid = get_hwtid(skb);
++ unsigned int opcode = get_opcode(skb);
+ struct t3c_tid_entry *t3c_tid;
+
+ t3c_tid = lookup_tid(&(T3C_DATA(dev))->tid_maps, hwtid);
+@@ -914,7 +930,7 @@ int process_rx(struct t3cdev *dev, struct sk_buff **skbs, int n)
+ {
+ while (n--) {
+ struct sk_buff *skb = *skbs++;
+- unsigned int opcode = G_OPCODE(ntohl(skb->csum));
++ unsigned int opcode = get_opcode(skb);
+ int ret = cpl_handlers[opcode] (dev, skb);
+
+ #if VALIDATE_TID
+diff --git a/drivers/net/cxgb3/l2t.c b/drivers/net/cxgb3/l2t.c
+index 865faee..f510140 100644
+--- a/drivers/net/cxgb3/l2t.c
++++ b/drivers/net/cxgb3/l2t.c
+@@ -407,7 +407,7 @@ found:
+ } else if (neigh->nud_state & (NUD_CONNECTED|NUD_STALE))
+ setup_l2e_send_pending(dev, NULL, e);
+ } else {
+- e->state = neigh_is_connected(neigh) ?
++ e->state = neigh->nud_state & NUD_CONNECTED ?
+ L2T_STATE_VALID : L2T_STATE_STALE;
+ if (memcmp(e->dmac, neigh->ha, 6))
+ setup_l2e_send_pending(dev, NULL, e);
+diff --git a/drivers/net/cxgb3/t3cdev.h b/drivers/net/cxgb3/t3cdev.h
+index 77fcc1a..a18c8a1 100644
+--- a/drivers/net/cxgb3/t3cdev.h
++++ b/drivers/net/cxgb3/t3cdev.h
+@@ -34,7 +34,6 @@
+
+ #include <linux/list.h>
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+ #include <linux/netdevice.h>
+ #include <linux/proc_fs.h>
+ #include <linux/skbuff.h>
+diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h
+index 229303f..a0177fc 100644
+--- a/drivers/net/cxgb3/version.h
++++ b/drivers/net/cxgb3/version.h
+@@ -38,7 +38,7 @@
+ #define DRV_VERSION "1.0-ko"
+
+ /* Firmware version */
+-#define FW_VERSION_MAJOR 5
++#define FW_VERSION_MAJOR 6
+ #define FW_VERSION_MINOR 0
+ #define FW_VERSION_MICRO 0
+ #endif /* __CHELSIO_VERSION_H */
+diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
+index ddc30c4..c062aac 100644
+--- a/drivers/net/defxx.c
++++ b/drivers/net/defxx.c
+@@ -971,7 +971,8 @@ static int __devinit dfx_driver_init(struct net_device *dev,
+ int alloc_size; /* total buffer size needed */
+ char *top_v, *curr_v; /* virtual addrs into memory block */
+ dma_addr_t top_p, curr_p; /* physical addrs into memory block */
+- u32 data, le32; /* host data register value */
++ u32 data; /* host data register value */
++ __le32 le32;
+ char *board_name = NULL;
+
+ DBG_printk("In dfx_driver_init...\n");
+diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
+index d63cc93..e6fe261 100644
+--- a/drivers/net/dm9000.c
++++ b/drivers/net/dm9000.c
+@@ -1418,3 +1418,4 @@ module_exit(dm9000_cleanup);
+ MODULE_AUTHOR("Sascha Hauer, Ben Dooks");
+ MODULE_DESCRIPTION("Davicom DM9000 network driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:dm9000");
+diff --git a/drivers/net/e100.c b/drivers/net/e100.c
+index 2d139ec..f3cba5e 100644
+--- a/drivers/net/e100.c
++++ b/drivers/net/e100.c
+@@ -1802,7 +1802,7 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
+ * it is protected by the before last buffer's el bit being set */
+ if (rx->prev->skb) {
+ struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data;
+- put_unaligned(cpu_to_le32(rx->dma_addr), &prev_rfd->link);
++ put_unaligned_le32(rx->dma_addr, &prev_rfd->link);
+ }
+
+ return 0;
+diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
+index 3b84028..31feae1 100644
+--- a/drivers/net/e1000/e1000.h
++++ b/drivers/net/e1000/e1000.h
+@@ -161,13 +161,13 @@ struct e1000_buffer {
+ struct sk_buff *skb;
+ dma_addr_t dma;
+ unsigned long time_stamp;
+- uint16_t length;
+- uint16_t next_to_watch;
++ u16 length;
++ u16 next_to_watch;
+ };
+
+
+ struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; };
+-struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; };
++struct e1000_ps_page_dma { u64 ps_page_dma[PS_PAGE_BUFFERS]; };
+
+ struct e1000_tx_ring {
+ /* pointer to the descriptor ring memory */
+@@ -186,9 +186,9 @@ struct e1000_tx_ring {
+ struct e1000_buffer *buffer_info;
+
+ spinlock_t tx_lock;
+- uint16_t tdh;
+- uint16_t tdt;
+- boolean_t last_tx_tso;
++ u16 tdh;
++ u16 tdt;
++ bool last_tx_tso;
+ };
+
+ struct e1000_rx_ring {
+@@ -213,8 +213,8 @@ struct e1000_rx_ring {
+ /* cpu for rx queue */
+ int cpu;
+
+- uint16_t rdh;
+- uint16_t rdt;
++ u16 rdh;
++ u16 rdt;
+ };
+
+ #define E1000_DESC_UNUSED(R) \
+@@ -237,31 +237,30 @@ struct e1000_adapter {
+ struct timer_list watchdog_timer;
+ struct timer_list phy_info_timer;
+ struct vlan_group *vlgrp;
+- uint16_t mng_vlan_id;
+- uint32_t bd_number;
+- uint32_t rx_buffer_len;
+- uint32_t wol;
+- uint32_t smartspeed;
+- uint32_t en_mng_pt;
+- uint16_t link_speed;
+- uint16_t link_duplex;
++ u16 mng_vlan_id;
++ u32 bd_number;
++ u32 rx_buffer_len;
++ u32 wol;
++ u32 smartspeed;
++ u32 en_mng_pt;
++ u16 link_speed;
++ u16 link_duplex;
+ spinlock_t stats_lock;
+ #ifdef CONFIG_E1000_NAPI
+ spinlock_t tx_queue_lock;
+ #endif
+- atomic_t irq_sem;
+ unsigned int total_tx_bytes;
+ unsigned int total_tx_packets;
+ unsigned int total_rx_bytes;
+ unsigned int total_rx_packets;
+ /* Interrupt Throttle Rate */
+- uint32_t itr;
+- uint32_t itr_setting;
+- uint16_t tx_itr;
+- uint16_t rx_itr;
++ u32 itr;
++ u32 itr_setting;
++ u16 tx_itr;
++ u16 rx_itr;
+
+ struct work_struct reset_task;
+- uint8_t fc_autoneg;
++ u8 fc_autoneg;
+
+ struct timer_list blink_timer;
+ unsigned long led_status;
+@@ -270,30 +269,30 @@ struct e1000_adapter {
+ struct e1000_tx_ring *tx_ring; /* One per active queue */
+ unsigned int restart_queue;
+ unsigned long tx_queue_len;
+- uint32_t txd_cmd;
+- uint32_t tx_int_delay;
+- uint32_t tx_abs_int_delay;
+- uint32_t gotcl;
+- uint64_t gotcl_old;
+- uint64_t tpt_old;
+- uint64_t colc_old;
+- uint32_t tx_timeout_count;
+- uint32_t tx_fifo_head;
+- uint32_t tx_head_addr;
+- uint32_t tx_fifo_size;
+- uint8_t tx_timeout_factor;
++ u32 txd_cmd;
++ u32 tx_int_delay;
++ u32 tx_abs_int_delay;
++ u32 gotcl;
++ u64 gotcl_old;
++ u64 tpt_old;
++ u64 colc_old;
++ u32 tx_timeout_count;
++ u32 tx_fifo_head;
++ u32 tx_head_addr;
++ u32 tx_fifo_size;
++ u8 tx_timeout_factor;
+ atomic_t tx_fifo_stall;
+- boolean_t pcix_82544;
+- boolean_t detect_tx_hung;
++ bool pcix_82544;
++ bool detect_tx_hung;
+
+ /* RX */
+ #ifdef CONFIG_E1000_NAPI
+- boolean_t (*clean_rx) (struct e1000_adapter *adapter,
+- struct e1000_rx_ring *rx_ring,
+- int *work_done, int work_to_do);
++ bool (*clean_rx) (struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring,
++ int *work_done, int work_to_do);
+ #else
+- boolean_t (*clean_rx) (struct e1000_adapter *adapter,
+- struct e1000_rx_ring *rx_ring);
++ bool (*clean_rx) (struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring);
+ #endif
+ void (*alloc_rx_buf) (struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+@@ -306,17 +305,17 @@ struct e1000_adapter {
+ int num_tx_queues;
+ int num_rx_queues;
+
+- uint64_t hw_csum_err;
+- uint64_t hw_csum_good;
+- uint64_t rx_hdr_split;
+- uint32_t alloc_rx_buff_failed;
+- uint32_t rx_int_delay;
+- uint32_t rx_abs_int_delay;
+- boolean_t rx_csum;
++ u64 hw_csum_err;
++ u64 hw_csum_good;
++ u64 rx_hdr_split;
++ u32 alloc_rx_buff_failed;
++ u32 rx_int_delay;
++ u32 rx_abs_int_delay;
++ bool rx_csum;
+ unsigned int rx_ps_pages;
+- uint32_t gorcl;
+- uint64_t gorcl_old;
+- uint16_t rx_ps_bsize0;
++ u32 gorcl;
++ u64 gorcl_old;
++ u16 rx_ps_bsize0;
+
+
+ /* OS defined structs */
+@@ -330,19 +329,19 @@ struct e1000_adapter {
+ struct e1000_phy_info phy_info;
+ struct e1000_phy_stats phy_stats;
+
+- uint32_t test_icr;
++ u32 test_icr;
+ struct e1000_tx_ring test_tx_ring;
+ struct e1000_rx_ring test_rx_ring;
+
+ int msg_enable;
+- boolean_t have_msi;
++ bool have_msi;
+
+ /* to not mess up cache alignment, always add to the bottom */
+- boolean_t tso_force;
+- boolean_t smart_power_down; /* phy smart power down */
+- boolean_t quad_port_a;
++ bool tso_force;
++ bool smart_power_down; /* phy smart power down */
++ bool quad_port_a;
+ unsigned long flags;
+- uint32_t eeprom_wol;
++ u32 eeprom_wol;
+ };
+
+ enum e1000_state_t {
+diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
+index 85e66f4..701531e 100644
+--- a/drivers/net/e1000/e1000_ethtool.c
++++ b/drivers/net/e1000/e1000_ethtool.c
+@@ -36,7 +36,7 @@ extern int e1000_up(struct e1000_adapter *adapter);
+ extern void e1000_down(struct e1000_adapter *adapter);
+ extern void e1000_reinit_locked(struct e1000_adapter *adapter);
+ extern void e1000_reset(struct e1000_adapter *adapter);
+-extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
++extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx);
+ extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+ extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+ extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+@@ -289,7 +289,7 @@ e1000_set_pauseparam(struct net_device *netdev,
+ return retval;
+ }
+
+-static uint32_t
++static u32
+ e1000_get_rx_csum(struct net_device *netdev)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+@@ -297,7 +297,7 @@ e1000_get_rx_csum(struct net_device *netdev)
+ }
+
+ static int
+-e1000_set_rx_csum(struct net_device *netdev, uint32_t data)
++e1000_set_rx_csum(struct net_device *netdev, u32 data)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ adapter->rx_csum = data;
+@@ -309,14 +309,14 @@ e1000_set_rx_csum(struct net_device *netdev, uint32_t data)
+ return 0;
+ }
+
+-static uint32_t
++static u32
+ e1000_get_tx_csum(struct net_device *netdev)
+ {
+ return (netdev->features & NETIF_F_HW_CSUM) != 0;
+ }
+
+ static int
+-e1000_set_tx_csum(struct net_device *netdev, uint32_t data)
++e1000_set_tx_csum(struct net_device *netdev, u32 data)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+
+@@ -335,7 +335,7 @@ e1000_set_tx_csum(struct net_device *netdev, uint32_t data)
+ }
+
+ static int
+-e1000_set_tso(struct net_device *netdev, uint32_t data)
++e1000_set_tso(struct net_device *netdev, u32 data)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ if ((adapter->hw.mac_type < e1000_82544) ||
+@@ -353,11 +353,11 @@ e1000_set_tso(struct net_device *netdev, uint32_t data)
+ netdev->features &= ~NETIF_F_TSO6;
+
+ DPRINTK(PROBE, INFO, "TSO is %s\n", data ? "Enabled" : "Disabled");
+- adapter->tso_force = TRUE;
++ adapter->tso_force = true;
+ return 0;
+ }
+
+-static uint32_t
++static u32
+ e1000_get_msglevel(struct net_device *netdev)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+@@ -365,7 +365,7 @@ e1000_get_msglevel(struct net_device *netdev)
+ }
+
+ static void
+-e1000_set_msglevel(struct net_device *netdev, uint32_t data)
++e1000_set_msglevel(struct net_device *netdev, u32 data)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ adapter->msg_enable = data;
+@@ -375,7 +375,7 @@ static int
+ e1000_get_regs_len(struct net_device *netdev)
+ {
+ #define E1000_REGS_LEN 32
+- return E1000_REGS_LEN * sizeof(uint32_t);
++ return E1000_REGS_LEN * sizeof(u32);
+ }
+
+ static void
+@@ -384,10 +384,10 @@ e1000_get_regs(struct net_device *netdev,
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+- uint32_t *regs_buff = p;
+- uint16_t phy_data;
++ u32 *regs_buff = p;
++ u16 phy_data;
+
+- memset(p, 0, E1000_REGS_LEN * sizeof(uint32_t));
++ memset(p, 0, E1000_REGS_LEN * sizeof(u32));
+
+ regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
+
+@@ -412,44 +412,44 @@ e1000_get_regs(struct net_device *netdev,
+ IGP01E1000_PHY_AGC_A);
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_A &
+ IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+- regs_buff[13] = (uint32_t)phy_data; /* cable length */
++ regs_buff[13] = (u32)phy_data; /* cable length */
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+ IGP01E1000_PHY_AGC_B);
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_B &
+ IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+- regs_buff[14] = (uint32_t)phy_data; /* cable length */
++ regs_buff[14] = (u32)phy_data; /* cable length */
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+ IGP01E1000_PHY_AGC_C);
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_C &
+ IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+- regs_buff[15] = (uint32_t)phy_data; /* cable length */
++ regs_buff[15] = (u32)phy_data; /* cable length */
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+ IGP01E1000_PHY_AGC_D);
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_D &
+ IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+- regs_buff[16] = (uint32_t)phy_data; /* cable length */
++ regs_buff[16] = (u32)phy_data; /* cable length */
+ regs_buff[17] = 0; /* extended 10bt distance (not needed) */
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0);
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS &
+ IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+- regs_buff[18] = (uint32_t)phy_data; /* cable polarity */
++ regs_buff[18] = (u32)phy_data; /* cable polarity */
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+ IGP01E1000_PHY_PCS_INIT_REG);
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG &
+ IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+- regs_buff[19] = (uint32_t)phy_data; /* cable polarity */
++ regs_buff[19] = (u32)phy_data; /* cable polarity */
+ regs_buff[20] = 0; /* polarity correction enabled (always) */
+ regs_buff[22] = 0; /* phy receive errors (unavailable) */
+ regs_buff[23] = regs_buff[18]; /* mdix mode */
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0);
+ } else {
+ e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+- regs_buff[13] = (uint32_t)phy_data; /* cable length */
++ regs_buff[13] = (u32)phy_data; /* cable length */
+ regs_buff[14] = 0; /* Dummy (to align w/ IGP phy reg dump) */
+ regs_buff[15] = 0; /* Dummy (to align w/ IGP phy reg dump) */
+ regs_buff[16] = 0; /* Dummy (to align w/ IGP phy reg dump) */
+ e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+- regs_buff[17] = (uint32_t)phy_data; /* extended 10bt distance */
++ regs_buff[17] = (u32)phy_data; /* extended 10bt distance */
+ regs_buff[18] = regs_buff[13]; /* cable polarity */
+ regs_buff[19] = 0; /* Dummy (to align w/ IGP phy reg dump) */
+ regs_buff[20] = regs_buff[17]; /* polarity correction */
+@@ -459,7 +459,7 @@ e1000_get_regs(struct net_device *netdev,
+ }
+ regs_buff[21] = adapter->phy_stats.idle_errors; /* phy idle errors */
+ e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
+- regs_buff[24] = (uint32_t)phy_data; /* phy local receiver status */
++ regs_buff[24] = (u32)phy_data; /* phy local receiver status */
+ regs_buff[25] = regs_buff[24]; /* phy remote receiver status */
+ if (hw->mac_type >= e1000_82540 &&
+ hw->mac_type < e1000_82571 &&
+@@ -477,14 +477,14 @@ e1000_get_eeprom_len(struct net_device *netdev)
+
+ static int
+ e1000_get_eeprom(struct net_device *netdev,
+- struct ethtool_eeprom *eeprom, uint8_t *bytes)
++ struct ethtool_eeprom *eeprom, u8 *bytes)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+- uint16_t *eeprom_buff;
++ u16 *eeprom_buff;
+ int first_word, last_word;
+ int ret_val = 0;
+- uint16_t i;
++ u16 i;
+
+ if (eeprom->len == 0)
+ return -EINVAL;
+@@ -494,7 +494,7 @@ e1000_get_eeprom(struct net_device *netdev,
+ first_word = eeprom->offset >> 1;
+ last_word = (eeprom->offset + eeprom->len - 1) >> 1;
+
+- eeprom_buff = kmalloc(sizeof(uint16_t) *
++ eeprom_buff = kmalloc(sizeof(u16) *
+ (last_word - first_word + 1), GFP_KERNEL);
+ if (!eeprom_buff)
+ return -ENOMEM;
+@@ -514,7 +514,7 @@ e1000_get_eeprom(struct net_device *netdev,
+ for (i = 0; i < last_word - first_word + 1; i++)
+ le16_to_cpus(&eeprom_buff[i]);
+
+- memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset & 1),
++ memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1),
+ eeprom->len);
+ kfree(eeprom_buff);
+
+@@ -523,14 +523,14 @@ e1000_get_eeprom(struct net_device *netdev,
+
+ static int
+ e1000_set_eeprom(struct net_device *netdev,
+- struct ethtool_eeprom *eeprom, uint8_t *bytes)
++ struct ethtool_eeprom *eeprom, u8 *bytes)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+- uint16_t *eeprom_buff;
++ u16 *eeprom_buff;
+ void *ptr;
+ int max_len, first_word, last_word, ret_val = 0;
+- uint16_t i;
++ u16 i;
+
+ if (eeprom->len == 0)
+ return -EOPNOTSUPP;
+@@ -590,7 +590,7 @@ e1000_get_drvinfo(struct net_device *netdev,
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ char firmware_version[32];
+- uint16_t eeprom_data;
++ u16 eeprom_data;
+
+ strncpy(drvinfo->driver, e1000_driver_name, 32);
+ strncpy(drvinfo->version, e1000_driver_version, 32);
+@@ -674,13 +674,13 @@ e1000_set_ringparam(struct net_device *netdev,
+ adapter->tx_ring = txdr;
+ adapter->rx_ring = rxdr;
+
+- rxdr->count = max(ring->rx_pending,(uint32_t)E1000_MIN_RXD);
+- rxdr->count = min(rxdr->count,(uint32_t)(mac_type < e1000_82544 ?
++ rxdr->count = max(ring->rx_pending,(u32)E1000_MIN_RXD);
++ rxdr->count = min(rxdr->count,(u32)(mac_type < e1000_82544 ?
+ E1000_MAX_RXD : E1000_MAX_82544_RXD));
+ rxdr->count = ALIGN(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE);
+
+- txdr->count = max(ring->tx_pending,(uint32_t)E1000_MIN_TXD);
+- txdr->count = min(txdr->count,(uint32_t)(mac_type < e1000_82544 ?
++ txdr->count = max(ring->tx_pending,(u32)E1000_MIN_TXD);
++ txdr->count = min(txdr->count,(u32)(mac_type < e1000_82544 ?
+ E1000_MAX_TXD : E1000_MAX_82544_TXD));
+ txdr->count = ALIGN(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE);
+
+@@ -728,13 +728,13 @@ err_setup:
+ return err;
+ }
+
+-static bool reg_pattern_test(struct e1000_adapter *adapter, uint64_t *data,
+- int reg, uint32_t mask, uint32_t write)
++static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data,
++ int reg, u32 mask, u32 write)
+ {
+- static const uint32_t test[] =
++ static const u32 test[] =
+ {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
+- uint8_t __iomem *address = adapter->hw.hw_addr + reg;
+- uint32_t read;
++ u8 __iomem *address = adapter->hw.hw_addr + reg;
++ u32 read;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(test); i++) {
+@@ -751,11 +751,11 @@ static bool reg_pattern_test(struct e1000_adapter *adapter, uint64_t *data,
+ return false;
+ }
+
+-static bool reg_set_and_check(struct e1000_adapter *adapter, uint64_t *data,
+- int reg, uint32_t mask, uint32_t write)
++static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
++ int reg, u32 mask, u32 write)
+ {
+- uint8_t __iomem *address = adapter->hw.hw_addr + reg;
+- uint32_t read;
++ u8 __iomem *address = adapter->hw.hw_addr + reg;
++ u32 read;
+
+ writel(write & mask, address);
+ read = readl(address);
+@@ -788,10 +788,10 @@ static bool reg_set_and_check(struct e1000_adapter *adapter, uint64_t *data,
+ } while (0)
+
+ static int
+-e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
++e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
+ {
+- uint32_t value, before, after;
+- uint32_t i, toggle;
++ u32 value, before, after;
++ u32 i, toggle;
+
+ /* The status register is Read Only, so a write should fail.
+ * Some bits that get toggled are ignored.
+@@ -884,11 +884,11 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
+ }
+
+ static int
+-e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data)
++e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
+ {
+- uint16_t temp;
+- uint16_t checksum = 0;
+- uint16_t i;
++ u16 temp;
++ u16 checksum = 0;
++ u16 i;
+
+ *data = 0;
+ /* Read and add up the contents of the EEPROM */
+@@ -901,7 +901,7 @@ e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data)
+ }
+
+ /* If Checksum is not Correct return error else test passed */
+- if ((checksum != (uint16_t) EEPROM_SUM) && !(*data))
++ if ((checksum != (u16) EEPROM_SUM) && !(*data))
+ *data = 2;
+
+ return *data;
+@@ -919,11 +919,12 @@ e1000_test_intr(int irq, void *data)
+ }
+
+ static int
+-e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
++e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
+ {
+ struct net_device *netdev = adapter->netdev;
+- uint32_t mask, i=0, shared_int = TRUE;
+- uint32_t irq = adapter->pdev->irq;
++ u32 mask, i = 0;
++ bool shared_int = true;
++ u32 irq = adapter->pdev->irq;
+
+ *data = 0;
+
+@@ -931,7 +932,7 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
+ /* Hook up test interrupt handler just for this test */
+ if (!request_irq(irq, &e1000_test_intr, IRQF_PROBE_SHARED, netdev->name,
+ netdev))
+- shared_int = FALSE;
++ shared_int = false;
+ else if (request_irq(irq, &e1000_test_intr, IRQF_SHARED,
+ netdev->name, netdev)) {
+ *data = 1;
+@@ -1069,7 +1070,7 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+ struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
+ struct pci_dev *pdev = adapter->pdev;
+- uint32_t rctl;
++ u32 rctl;
+ int i, ret_val;
+
+ /* Setup Tx descriptor ring and Tx buffers */
+@@ -1095,8 +1096,8 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ txdr->next_to_use = txdr->next_to_clean = 0;
+
+ E1000_WRITE_REG(&adapter->hw, TDBAL,
+- ((uint64_t) txdr->dma & 0x00000000FFFFFFFF));
+- E1000_WRITE_REG(&adapter->hw, TDBAH, ((uint64_t) txdr->dma >> 32));
++ ((u64) txdr->dma & 0x00000000FFFFFFFF));
++ E1000_WRITE_REG(&adapter->hw, TDBAH, ((u64) txdr->dma >> 32));
+ E1000_WRITE_REG(&adapter->hw, TDLEN,
+ txdr->count * sizeof(struct e1000_tx_desc));
+ E1000_WRITE_REG(&adapter->hw, TDH, 0);
+@@ -1152,8 +1153,8 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
+ E1000_WRITE_REG(&adapter->hw, RDBAL,
+- ((uint64_t) rxdr->dma & 0xFFFFFFFF));
+- E1000_WRITE_REG(&adapter->hw, RDBAH, ((uint64_t) rxdr->dma >> 32));
++ ((u64) rxdr->dma & 0xFFFFFFFF));
++ E1000_WRITE_REG(&adapter->hw, RDBAH, ((u64) rxdr->dma >> 32));
+ E1000_WRITE_REG(&adapter->hw, RDLEN, rxdr->size);
+ E1000_WRITE_REG(&adapter->hw, RDH, 0);
+ E1000_WRITE_REG(&adapter->hw, RDT, 0);
+@@ -1201,7 +1202,7 @@ e1000_phy_disable_receiver(struct e1000_adapter *adapter)
+ static void
+ e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter)
+ {
+- uint16_t phy_reg;
++ u16 phy_reg;
+
+ /* Because we reset the PHY above, we need to re-force TX_CLK in the
+ * Extended PHY Specific Control Register to 25MHz clock. This
+@@ -1225,8 +1226,8 @@ e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter)
+ static int
+ e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
+ {
+- uint32_t ctrl_reg;
+- uint16_t phy_reg;
++ u32 ctrl_reg;
++ u16 phy_reg;
+
+ /* Setup the Device Control Register for PHY loopback test. */
+
+@@ -1292,10 +1293,10 @@ e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
+ static int
+ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+ {
+- uint32_t ctrl_reg = 0;
+- uint32_t stat_reg = 0;
++ u32 ctrl_reg = 0;
++ u32 stat_reg = 0;
+
+- adapter->hw.autoneg = FALSE;
++ adapter->hw.autoneg = false;
+
+ if (adapter->hw.phy_type == e1000_phy_m88) {
+ /* Auto-MDI/MDIX Off */
+@@ -1362,8 +1363,8 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+ static int
+ e1000_set_phy_loopback(struct e1000_adapter *adapter)
+ {
+- uint16_t phy_reg = 0;
+- uint16_t count = 0;
++ u16 phy_reg = 0;
++ u16 count = 0;
+
+ switch (adapter->hw.mac_type) {
+ case e1000_82543:
+@@ -1415,7 +1416,7 @@ static int
+ e1000_setup_loopback_test(struct e1000_adapter *adapter)
+ {
+ struct e1000_hw *hw = &adapter->hw;
+- uint32_t rctl;
++ u32 rctl;
+
+ if (hw->media_type == e1000_media_type_fiber ||
+ hw->media_type == e1000_media_type_internal_serdes) {
+@@ -1450,8 +1451,8 @@ static void
+ e1000_loopback_cleanup(struct e1000_adapter *adapter)
+ {
+ struct e1000_hw *hw = &adapter->hw;
+- uint32_t rctl;
+- uint16_t phy_reg;
++ u32 rctl;
++ u16 phy_reg;
+
+ rctl = E1000_READ_REG(hw, RCTL);
+ rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
+@@ -1473,7 +1474,7 @@ e1000_loopback_cleanup(struct e1000_adapter *adapter)
+ case e1000_82545_rev_3:
+ case e1000_82546_rev_3:
+ default:
+- hw->autoneg = TRUE;
++ hw->autoneg = true;
+ if (hw->phy_type == e1000_phy_gg82563)
+ e1000_write_phy_reg(hw,
+ GG82563_PHY_KMRN_MODE_CTRL,
+@@ -1577,7 +1578,7 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
+ }
+
+ static int
+-e1000_loopback_test(struct e1000_adapter *adapter, uint64_t *data)
++e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
+ {
+ /* PHY loopback cannot be performed if SoL/IDER
+ * sessions are active */
+@@ -1602,18 +1603,18 @@ out:
+ }
+
+ static int
+-e1000_link_test(struct e1000_adapter *adapter, uint64_t *data)
++e1000_link_test(struct e1000_adapter *adapter, u64 *data)
+ {
+ *data = 0;
+ if (adapter->hw.media_type == e1000_media_type_internal_serdes) {
+ int i = 0;
+- adapter->hw.serdes_link_down = TRUE;
++ adapter->hw.serdes_link_down = true;
+
+ /* On some blade server designs, link establishment
+ * could take as long as 2-3 minutes */
+ do {
+ e1000_check_for_link(&adapter->hw);
+- if (adapter->hw.serdes_link_down == FALSE)
++ if (!adapter->hw.serdes_link_down)
+ return *data;
+ msleep(20);
+ } while (i++ < 3750);
+@@ -1646,19 +1647,19 @@ e1000_get_sset_count(struct net_device *netdev, int sset)
+
+ static void
+ e1000_diag_test(struct net_device *netdev,
+- struct ethtool_test *eth_test, uint64_t *data)
++ struct ethtool_test *eth_test, u64 *data)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+- boolean_t if_running = netif_running(netdev);
++ bool if_running = netif_running(netdev);
+
+ set_bit(__E1000_TESTING, &adapter->flags);
+ if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
+ /* Offline tests */
+
+ /* save speed, duplex, autoneg settings */
+- uint16_t autoneg_advertised = adapter->hw.autoneg_advertised;
+- uint8_t forced_speed_duplex = adapter->hw.forced_speed_duplex;
+- uint8_t autoneg = adapter->hw.autoneg;
++ u16 autoneg_advertised = adapter->hw.autoneg_advertised;
++ u8 forced_speed_duplex = adapter->hw.forced_speed_duplex;
++ u8 autoneg = adapter->hw.autoneg;
+
+ DPRINTK(HW, INFO, "offline testing starting\n");
+
+@@ -1876,7 +1877,7 @@ e1000_led_blink_callback(unsigned long data)
+ }
+
+ static int
+-e1000_phys_id(struct net_device *netdev, uint32_t data)
++e1000_phys_id(struct net_device *netdev, u32 data)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+
+@@ -1926,7 +1927,7 @@ e1000_nway_reset(struct net_device *netdev)
+
+ static void
+ e1000_get_ethtool_stats(struct net_device *netdev,
+- struct ethtool_stats *stats, uint64_t *data)
++ struct ethtool_stats *stats, u64 *data)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ int i;
+@@ -1935,15 +1936,15 @@ e1000_get_ethtool_stats(struct net_device *netdev,
+ for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
+ char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;
+ data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
+- sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
++ sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+ }
+ /* BUG_ON(i != E1000_STATS_LEN); */
+ }
+
+ static void
+-e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
++e1000_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
+ {
+- uint8_t *p = data;
++ u8 *p = data;
+ int i;
+
+ switch (stringset) {
+diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
+index 7c6888c..9a4b6cb 100644
+--- a/drivers/net/e1000/e1000_hw.c
++++ b/drivers/net/e1000/e1000_hw.c
+@@ -33,106 +33,107 @@
+
+ #include "e1000_hw.h"
+
+-static int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask);
+-static void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask);
+-static int32_t e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *data);
+-static int32_t e1000_write_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data);
+-static int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
++static s32 e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask);
++static void e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask);
++static s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 reg_addr, u16 *data);
++static s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 reg_addr, u16 data);
++static s32 e1000_get_software_semaphore(struct e1000_hw *hw);
+ static void e1000_release_software_semaphore(struct e1000_hw *hw);
+
+-static uint8_t e1000_arc_subsystem_valid(struct e1000_hw *hw);
+-static int32_t e1000_check_downshift(struct e1000_hw *hw);
+-static int32_t e1000_check_polarity(struct e1000_hw *hw, e1000_rev_polarity *polarity);
++static u8 e1000_arc_subsystem_valid(struct e1000_hw *hw);
++static s32 e1000_check_downshift(struct e1000_hw *hw);
++static s32 e1000_check_polarity(struct e1000_hw *hw, e1000_rev_polarity *polarity);
+ static void e1000_clear_hw_cntrs(struct e1000_hw *hw);
+ static void e1000_clear_vfta(struct e1000_hw *hw);
+-static int32_t e1000_commit_shadow_ram(struct e1000_hw *hw);
+-static int32_t e1000_config_dsp_after_link_change(struct e1000_hw *hw, boolean_t link_up);
+-static int32_t e1000_config_fc_after_link_up(struct e1000_hw *hw);
+-static int32_t e1000_detect_gig_phy(struct e1000_hw *hw);
+-static int32_t e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank);
+-static int32_t e1000_get_auto_rd_done(struct e1000_hw *hw);
+-static int32_t e1000_get_cable_length(struct e1000_hw *hw, uint16_t *min_length, uint16_t *max_length);
+-static int32_t e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw);
+-static int32_t e1000_get_phy_cfg_done(struct e1000_hw *hw);
+-static int32_t e1000_get_software_flag(struct e1000_hw *hw);
+-static int32_t e1000_ich8_cycle_init(struct e1000_hw *hw);
+-static int32_t e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout);
+-static int32_t e1000_id_led_init(struct e1000_hw *hw);
+-static int32_t e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw, uint32_t cnf_base_addr, uint32_t cnf_size);
+-static int32_t e1000_init_lcd_from_nvm(struct e1000_hw *hw);
++static s32 e1000_commit_shadow_ram(struct e1000_hw *hw);
++static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw,
++ bool link_up);
++static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw);
++static s32 e1000_detect_gig_phy(struct e1000_hw *hw);
++static s32 e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank);
++static s32 e1000_get_auto_rd_done(struct e1000_hw *hw);
++static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length, u16 *max_length);
++static s32 e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw);
++static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw);
++static s32 e1000_get_software_flag(struct e1000_hw *hw);
++static s32 e1000_ich8_cycle_init(struct e1000_hw *hw);
++static s32 e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout);
++static s32 e1000_id_led_init(struct e1000_hw *hw);
++static s32 e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw, u32 cnf_base_addr, u32 cnf_size);
++static s32 e1000_init_lcd_from_nvm(struct e1000_hw *hw);
+ static void e1000_init_rx_addrs(struct e1000_hw *hw);
+ static void e1000_initialize_hardware_bits(struct e1000_hw *hw);
+-static boolean_t e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw);
+-static int32_t e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
+-static int32_t e1000_mng_enable_host_if(struct e1000_hw *hw);
+-static int32_t e1000_mng_host_if_write(struct e1000_hw *hw, uint8_t *buffer, uint16_t length, uint16_t offset, uint8_t *sum);
+-static int32_t e1000_mng_write_cmd_header(struct e1000_hw* hw, struct e1000_host_mng_command_header* hdr);
+-static int32_t e1000_mng_write_commit(struct e1000_hw *hw);
+-static int32_t e1000_phy_ife_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
+-static int32_t e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
+-static int32_t e1000_read_eeprom_eerd(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
+-static int32_t e1000_write_eeprom_eewr(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
+-static int32_t e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd);
+-static int32_t e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
++static bool e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw);
++static s32 e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
++static s32 e1000_mng_enable_host_if(struct e1000_hw *hw);
++static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length, u16 offset, u8 *sum);
++static s32 e1000_mng_write_cmd_header(struct e1000_hw* hw, struct e1000_host_mng_command_header* hdr);
++static s32 e1000_mng_write_commit(struct e1000_hw *hw);
++static s32 e1000_phy_ife_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
++static s32 e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
++static s32 e1000_read_eeprom_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
++static s32 e1000_write_eeprom_eewr(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
++static s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd);
++static s32 e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
+ static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw);
+-static int32_t e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t *data);
+-static int32_t e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte);
+-static int32_t e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte);
+-static int32_t e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data);
+-static int32_t e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size, uint16_t *data);
+-static int32_t e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size, uint16_t data);
+-static int32_t e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
+-static int32_t e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
++static s32 e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8 *data);
++static s32 e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte);
++static s32 e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte);
++static s32 e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data);
++static s32 e1000_read_ich8_data(struct e1000_hw *hw, u32 index, u32 size, u16 *data);
++static s32 e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size, u16 data);
++static s32 e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
++static s32 e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+ static void e1000_release_software_flag(struct e1000_hw *hw);
+-static int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active);
+-static int32_t e1000_set_d0_lplu_state(struct e1000_hw *hw, boolean_t active);
+-static int32_t e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop);
++static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
++static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
++static s32 e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop);
+ static void e1000_set_pci_express_master_disable(struct e1000_hw *hw);
+-static int32_t e1000_wait_autoneg(struct e1000_hw *hw);
+-static void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value);
+-static int32_t e1000_set_phy_type(struct e1000_hw *hw);
++static s32 e1000_wait_autoneg(struct e1000_hw *hw);
++static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value);
++static s32 e1000_set_phy_type(struct e1000_hw *hw);
+ static void e1000_phy_init_script(struct e1000_hw *hw);
+-static int32_t e1000_setup_copper_link(struct e1000_hw *hw);
+-static int32_t e1000_setup_fiber_serdes_link(struct e1000_hw *hw);
+-static int32_t e1000_adjust_serdes_amplitude(struct e1000_hw *hw);
+-static int32_t e1000_phy_force_speed_duplex(struct e1000_hw *hw);
+-static int32_t e1000_config_mac_to_phy(struct e1000_hw *hw);
+-static void e1000_raise_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl);
+-static void e1000_lower_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl);
+-static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data,
+- uint16_t count);
+-static uint16_t e1000_shift_in_mdi_bits(struct e1000_hw *hw);
+-static int32_t e1000_phy_reset_dsp(struct e1000_hw *hw);
+-static int32_t e1000_write_eeprom_spi(struct e1000_hw *hw, uint16_t offset,
+- uint16_t words, uint16_t *data);
+-static int32_t e1000_write_eeprom_microwire(struct e1000_hw *hw,
+- uint16_t offset, uint16_t words,
+- uint16_t *data);
+-static int32_t e1000_spi_eeprom_ready(struct e1000_hw *hw);
+-static void e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t *eecd);
+-static void e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t *eecd);
+-static void e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data,
+- uint16_t count);
+-static int32_t e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+- uint16_t phy_data);
+-static int32_t e1000_read_phy_reg_ex(struct e1000_hw *hw,uint32_t reg_addr,
+- uint16_t *phy_data);
+-static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw, uint16_t count);
+-static int32_t e1000_acquire_eeprom(struct e1000_hw *hw);
++static s32 e1000_setup_copper_link(struct e1000_hw *hw);
++static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw);
++static s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw);
++static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw);
++static s32 e1000_config_mac_to_phy(struct e1000_hw *hw);
++static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
++static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
++static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data,
++ u16 count);
++static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw);
++static s32 e1000_phy_reset_dsp(struct e1000_hw *hw);
++static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset,
++ u16 words, u16 *data);
++static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw,
++ u16 offset, u16 words,
++ u16 *data);
++static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw);
++static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd);
++static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd);
++static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data,
++ u16 count);
++static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
++ u16 phy_data);
++static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw,u32 reg_addr,
++ u16 *phy_data);
++static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count);
++static s32 e1000_acquire_eeprom(struct e1000_hw *hw);
+ static void e1000_release_eeprom(struct e1000_hw *hw);
+ static void e1000_standby_eeprom(struct e1000_hw *hw);
+-static int32_t e1000_set_vco_speed(struct e1000_hw *hw);
+-static int32_t e1000_polarity_reversal_workaround(struct e1000_hw *hw);
+-static int32_t e1000_set_phy_mode(struct e1000_hw *hw);
+-static int32_t e1000_host_if_read_cookie(struct e1000_hw *hw, uint8_t *buffer);
+-static uint8_t e1000_calculate_mng_checksum(char *buffer, uint32_t length);
+-static int32_t e1000_configure_kmrn_for_10_100(struct e1000_hw *hw,
+- uint16_t duplex);
+-static int32_t e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
++static s32 e1000_set_vco_speed(struct e1000_hw *hw);
++static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw);
++static s32 e1000_set_phy_mode(struct e1000_hw *hw);
++static s32 e1000_host_if_read_cookie(struct e1000_hw *hw, u8 *buffer);
++static u8 e1000_calculate_mng_checksum(char *buffer, u32 length);
++static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw,
++ u16 duplex);
++static s32 e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
+
+ /* IGP cable length table */
+ static const
+-uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
++u16 e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
+ { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25,
+ 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40,
+@@ -143,7 +144,7 @@ uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
+ 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120};
+
+ static const
+-uint16_t e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
++u16 e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
+ { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
+ 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41,
+ 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61,
+@@ -158,7 +159,7 @@ uint16_t e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_set_phy_type(struct e1000_hw *hw)
+ {
+ DEBUGFUNC("e1000_set_phy_type");
+@@ -212,8 +213,8 @@ e1000_set_phy_type(struct e1000_hw *hw)
+ static void
+ e1000_phy_init_script(struct e1000_hw *hw)
+ {
+- uint32_t ret_val;
+- uint16_t phy_saved_data;
++ u32 ret_val;
++ u16 phy_saved_data;
+
+ DEBUGFUNC("e1000_phy_init_script");
+
+@@ -271,7 +272,7 @@ e1000_phy_init_script(struct e1000_hw *hw)
+ e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
+
+ if (hw->mac_type == e1000_82547) {
+- uint16_t fused, fine, coarse;
++ u16 fused, fine, coarse;
+
+ /* Move to analog registers page */
+ e1000_read_phy_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused);
+@@ -305,7 +306,7 @@ e1000_phy_init_script(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_set_mac_type(struct e1000_hw *hw)
+ {
+ DEBUGFUNC("e1000_set_mac_type");
+@@ -425,22 +426,22 @@ e1000_set_mac_type(struct e1000_hw *hw)
+
+ switch (hw->mac_type) {
+ case e1000_ich8lan:
+- hw->swfwhw_semaphore_present = TRUE;
+- hw->asf_firmware_present = TRUE;
++ hw->swfwhw_semaphore_present = true;
++ hw->asf_firmware_present = true;
+ break;
+ case e1000_80003es2lan:
+- hw->swfw_sync_present = TRUE;
++ hw->swfw_sync_present = true;
+ /* fall through */
+ case e1000_82571:
+ case e1000_82572:
+ case e1000_82573:
+- hw->eeprom_semaphore_present = TRUE;
++ hw->eeprom_semaphore_present = true;
+ /* fall through */
+ case e1000_82541:
+ case e1000_82547:
+ case e1000_82541_rev_2:
+ case e1000_82547_rev_2:
+- hw->asf_firmware_present = TRUE;
++ hw->asf_firmware_present = true;
+ break;
+ default:
+ break;
+@@ -450,20 +451,20 @@ e1000_set_mac_type(struct e1000_hw *hw)
+ * FD mode
+ */
+ if (hw->mac_type == e1000_82543)
+- hw->bad_tx_carr_stats_fd = TRUE;
++ hw->bad_tx_carr_stats_fd = true;
+
+ /* capable of receiving management packets to the host */
+ if (hw->mac_type >= e1000_82571)
+- hw->has_manc2h = TRUE;
++ hw->has_manc2h = true;
+
+ /* In rare occasions, ESB2 systems would end up started without
+ * the RX unit being turned on.
+ */
+ if (hw->mac_type == e1000_80003es2lan)
+- hw->rx_needs_kicking = TRUE;
++ hw->rx_needs_kicking = true;
+
+ if (hw->mac_type > e1000_82544)
+- hw->has_smbus = TRUE;
++ hw->has_smbus = true;
+
+ return E1000_SUCCESS;
+ }
+@@ -476,13 +477,13 @@ e1000_set_mac_type(struct e1000_hw *hw)
+ void
+ e1000_set_media_type(struct e1000_hw *hw)
+ {
+- uint32_t status;
++ u32 status;
+
+ DEBUGFUNC("e1000_set_media_type");
+
+ if (hw->mac_type != e1000_82543) {
+ /* tbi_compatibility is only valid on 82543 */
+- hw->tbi_compatibility_en = FALSE;
++ hw->tbi_compatibility_en = false;
+ }
+
+ switch (hw->device_id) {
+@@ -513,7 +514,7 @@ e1000_set_media_type(struct e1000_hw *hw)
+ if (status & E1000_STATUS_TBIMODE) {
+ hw->media_type = e1000_media_type_fiber;
+ /* tbi_compatibility not valid on fiber */
+- hw->tbi_compatibility_en = FALSE;
++ hw->tbi_compatibility_en = false;
+ } else {
+ hw->media_type = e1000_media_type_copper;
+ }
+@@ -527,17 +528,17 @@ e1000_set_media_type(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_reset_hw(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
+- uint32_t ctrl_ext;
+- uint32_t icr;
+- uint32_t manc;
+- uint32_t led_ctrl;
+- uint32_t timeout;
+- uint32_t extcnf_ctrl;
+- int32_t ret_val;
++ u32 ctrl;
++ u32 ctrl_ext;
++ u32 icr;
++ u32 manc;
++ u32 led_ctrl;
++ u32 timeout;
++ u32 extcnf_ctrl;
++ s32 ret_val;
+
+ DEBUGFUNC("e1000_reset_hw");
+
+@@ -569,7 +570,7 @@ e1000_reset_hw(struct e1000_hw *hw)
+ E1000_WRITE_FLUSH(hw);
+
+ /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
+- hw->tbi_compatibility_on = FALSE;
++ hw->tbi_compatibility_on = false;
+
+ /* Delay to allow any outstanding PCI transactions to complete before
+ * resetting the device
+@@ -682,7 +683,7 @@ e1000_reset_hw(struct e1000_hw *hw)
+ msleep(20);
+ break;
+ case e1000_82573:
+- if (e1000_is_onboard_nvm_eeprom(hw) == FALSE) {
++ if (!e1000_is_onboard_nvm_eeprom(hw)) {
+ udelay(10);
+ ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext |= E1000_CTRL_EXT_EE_RST;
+@@ -729,7 +730,7 @@ e1000_reset_hw(struct e1000_hw *hw)
+ }
+
+ if (hw->mac_type == e1000_ich8lan) {
+- uint32_t kab = E1000_READ_REG(hw, KABGTXD);
++ u32 kab = E1000_READ_REG(hw, KABGTXD);
+ kab |= E1000_KABGTXD_BGSQLBIAS;
+ E1000_WRITE_REG(hw, KABGTXD, kab);
+ }
+@@ -751,10 +752,10 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
+ {
+ if ((hw->mac_type >= e1000_82571) && (!hw->initialize_hw_bits_disable)) {
+ /* Settings common to all PCI-express silicon */
+- uint32_t reg_ctrl, reg_ctrl_ext;
+- uint32_t reg_tarc0, reg_tarc1;
+- uint32_t reg_tctl;
+- uint32_t reg_txdctl, reg_txdctl1;
++ u32 reg_ctrl, reg_ctrl_ext;
++ u32 reg_tarc0, reg_tarc1;
++ u32 reg_tctl;
++ u32 reg_txdctl, reg_txdctl1;
+
+ /* link autonegotiation/sync workarounds */
+ reg_tarc0 = E1000_READ_REG(hw, TARC0);
+@@ -865,15 +866,15 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
+ * configuration and flow control settings. Clears all on-chip counters. Leaves
+ * the transmit and receive units disabled and uninitialized.
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_init_hw(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
+- uint32_t i;
+- int32_t ret_val;
+- uint32_t mta_size;
+- uint32_t reg_data;
+- uint32_t ctrl_ext;
++ u32 ctrl;
++ u32 i;
++ s32 ret_val;
++ u32 mta_size;
++ u32 reg_data;
++ u32 ctrl_ext;
+
+ DEBUGFUNC("e1000_init_hw");
+
+@@ -1019,7 +1020,7 @@ e1000_init_hw(struct e1000_hw *hw)
+
+
+ if (hw->mac_type == e1000_82573) {
+- uint32_t gcr = E1000_READ_REG(hw, GCR);
++ u32 gcr = E1000_READ_REG(hw, GCR);
+ gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
+ E1000_WRITE_REG(hw, GCR, gcr);
+ }
+@@ -1053,11 +1054,11 @@ e1000_init_hw(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code.
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
+ {
+- uint16_t eeprom_data;
+- int32_t ret_val;
++ u16 eeprom_data;
++ s32 ret_val;
+
+ DEBUGFUNC("e1000_adjust_serdes_amplitude");
+
+@@ -1099,12 +1100,12 @@ e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
+ * established. Assumes the hardware has previously been reset and the
+ * transmitter and receiver are not enabled.
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_setup_link(struct e1000_hw *hw)
+ {
+- uint32_t ctrl_ext;
+- int32_t ret_val;
+- uint16_t eeprom_data;
++ u32 ctrl_ext;
++ s32 ret_val;
++ u16 eeprom_data;
+
+ DEBUGFUNC("e1000_setup_link");
+
+@@ -1232,15 +1233,15 @@ e1000_setup_link(struct e1000_hw *hw)
+ * link. Assumes the hardware has been previously reset and the transmitter
+ * and receiver are not enabled.
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
+- uint32_t status;
+- uint32_t txcw = 0;
+- uint32_t i;
+- uint32_t signal = 0;
+- int32_t ret_val;
++ u32 ctrl;
++ u32 status;
++ u32 txcw = 0;
++ u32 i;
++ u32 signal = 0;
++ s32 ret_val;
+
+ DEBUGFUNC("e1000_setup_fiber_serdes_link");
+
+@@ -1379,12 +1380,12 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_preconfig(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
+- int32_t ret_val;
+- uint16_t phy_data;
++ u32 ctrl;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_copper_link_preconfig");
+
+@@ -1428,7 +1429,7 @@ e1000_copper_link_preconfig(struct e1000_hw *hw)
+ if (hw->mac_type <= e1000_82543 ||
+ hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||
+ hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2)
+- hw->phy_reset_disable = FALSE;
++ hw->phy_reset_disable = false;
+
+ return E1000_SUCCESS;
+ }
+@@ -1439,12 +1440,12 @@ e1000_copper_link_preconfig(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *********************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_igp_setup(struct e1000_hw *hw)
+ {
+- uint32_t led_ctrl;
+- int32_t ret_val;
+- uint16_t phy_data;
++ u32 led_ctrl;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_copper_link_igp_setup");
+
+@@ -1470,7 +1471,7 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
+ /* The NVM settings will configure LPLU in D3 for IGP2 and IGP3 PHYs */
+ if (hw->phy_type == e1000_phy_igp) {
+ /* disable lplu d3 during driver init */
+- ret_val = e1000_set_d3_lplu_state(hw, FALSE);
++ ret_val = e1000_set_d3_lplu_state(hw, false);
+ if (ret_val) {
+ DEBUGOUT("Error Disabling LPLU D3\n");
+ return ret_val;
+@@ -1478,7 +1479,7 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
+ }
+
+ /* disable lplu d0 during driver init */
+- ret_val = e1000_set_d0_lplu_state(hw, FALSE);
++ ret_val = e1000_set_d0_lplu_state(hw, false);
+ if (ret_val) {
+ DEBUGOUT("Error Disabling LPLU D0\n");
+ return ret_val;
+@@ -1586,12 +1587,12 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *********************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_ggp_setup(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
+- uint32_t reg_data;
++ s32 ret_val;
++ u16 phy_data;
++ u32 reg_data;
+
+ DEBUGFUNC("e1000_copper_link_ggp_setup");
+
+@@ -1691,7 +1692,7 @@ e1000_copper_link_ggp_setup(struct e1000_hw *hw)
+ * firmware will have already initialized them. We only initialize
+ * them if the HW is not in IAMT mode.
+ */
+- if (e1000_check_mng_mode(hw) == FALSE) {
++ if (!e1000_check_mng_mode(hw)) {
+ /* Enable Electrical Idle on the PHY */
+ phy_data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
+ ret_val = e1000_write_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
+@@ -1734,11 +1735,11 @@ e1000_copper_link_ggp_setup(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *********************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_mgp_setup(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_copper_link_mgp_setup");
+
+@@ -1838,11 +1839,11 @@ e1000_copper_link_mgp_setup(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *********************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_autoneg(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_copper_link_autoneg");
+
+@@ -1892,7 +1893,7 @@ e1000_copper_link_autoneg(struct e1000_hw *hw)
+ }
+ }
+
+- hw->get_link_status = TRUE;
++ hw->get_link_status = true;
+
+ return E1000_SUCCESS;
+ }
+@@ -1909,10 +1910,10 @@ e1000_copper_link_autoneg(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_postconfig(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
++ s32 ret_val;
+ DEBUGFUNC("e1000_copper_link_postconfig");
+
+ if (hw->mac_type >= e1000_82544) {
+@@ -1932,7 +1933,7 @@ e1000_copper_link_postconfig(struct e1000_hw *hw)
+
+ /* Config DSP to improve Giga link quality */
+ if (hw->phy_type == e1000_phy_igp) {
+- ret_val = e1000_config_dsp_after_link_change(hw, TRUE);
++ ret_val = e1000_config_dsp_after_link_change(hw, true);
+ if (ret_val) {
+ DEBUGOUT("Error Configuring DSP after link up\n");
+ return ret_val;
+@@ -1947,13 +1948,13 @@ e1000_copper_link_postconfig(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_setup_copper_link(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t i;
+- uint16_t phy_data;
+- uint16_t reg_data;
++ s32 ret_val;
++ u16 i;
++ u16 phy_data;
++ u16 reg_data;
+
+ DEBUGFUNC("e1000_setup_copper_link");
+
+@@ -2061,12 +2062,12 @@ e1000_setup_copper_link(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
+-e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, uint16_t duplex)
++static s32
++e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex)
+ {
+- int32_t ret_val = E1000_SUCCESS;
+- uint32_t tipg;
+- uint16_t reg_data;
++ s32 ret_val = E1000_SUCCESS;
++ u32 tipg;
++ u16 reg_data;
+
+ DEBUGFUNC("e1000_configure_kmrn_for_10_100");
+
+@@ -2097,12 +2098,12 @@ e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, uint16_t duplex)
+ return ret_val;
+ }
+
+-static int32_t
++static s32
+ e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
+ {
+- int32_t ret_val = E1000_SUCCESS;
+- uint16_t reg_data;
+- uint32_t tipg;
++ s32 ret_val = E1000_SUCCESS;
++ u16 reg_data;
++ u32 tipg;
+
+ DEBUGFUNC("e1000_configure_kmrn_for_1000");
+
+@@ -2134,12 +2135,12 @@ e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-int32_t
++s32
+ e1000_phy_setup_autoneg(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t mii_autoneg_adv_reg;
+- uint16_t mii_1000t_ctrl_reg;
++ s32 ret_val;
++ u16 mii_autoneg_adv_reg;
++ u16 mii_1000t_ctrl_reg;
+
+ DEBUGFUNC("e1000_phy_setup_autoneg");
+
+@@ -2283,15 +2284,15 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
+- int32_t ret_val;
+- uint16_t mii_ctrl_reg;
+- uint16_t mii_status_reg;
+- uint16_t phy_data;
+- uint16_t i;
++ u32 ctrl;
++ s32 ret_val;
++ u16 mii_ctrl_reg;
++ u16 mii_status_reg;
++ u16 phy_data;
++ u16 i;
+
+ DEBUGFUNC("e1000_phy_force_speed_duplex");
+
+@@ -2537,7 +2538,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
+ void
+ e1000_config_collision_dist(struct e1000_hw *hw)
+ {
+- uint32_t tctl, coll_dist;
++ u32 tctl, coll_dist;
+
+ DEBUGFUNC("e1000_config_collision_dist");
+
+@@ -2564,12 +2565,12 @@ e1000_config_collision_dist(struct e1000_hw *hw)
+ * The contents of the PHY register containing the needed information need to
+ * be passed in.
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_config_mac_to_phy(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
+- int32_t ret_val;
+- uint16_t phy_data;
++ u32 ctrl;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_config_mac_to_phy");
+
+@@ -2623,10 +2624,10 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
+ * by the PHY rather than the MAC. Software must also configure these
+ * bits when link is forced on a fiber connection.
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_force_mac_fc(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
++ u32 ctrl;
+
+ DEBUGFUNC("e1000_force_mac_fc");
+
+@@ -2690,15 +2691,15 @@ e1000_force_mac_fc(struct e1000_hw *hw)
+ * based on the flow control negotiated by the PHY. In TBI mode, the TFCE
+ * and RFCE bits will be automaticaly set to the negotiated flow control mode.
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_config_fc_after_link_up(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t mii_status_reg;
+- uint16_t mii_nway_adv_reg;
+- uint16_t mii_nway_lp_ability_reg;
+- uint16_t speed;
+- uint16_t duplex;
++ s32 ret_val;
++ u16 mii_status_reg;
++ u16 mii_nway_adv_reg;
++ u16 mii_nway_lp_ability_reg;
++ u16 speed;
++ u16 duplex;
+
+ DEBUGFUNC("e1000_config_fc_after_link_up");
+
+@@ -2895,17 +2896,17 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
+ *
+ * Called by any function that needs to check the link status of the adapter.
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_check_for_link(struct e1000_hw *hw)
+ {
+- uint32_t rxcw = 0;
+- uint32_t ctrl;
+- uint32_t status;
+- uint32_t rctl;
+- uint32_t icr;
+- uint32_t signal = 0;
+- int32_t ret_val;
+- uint16_t phy_data;
++ u32 rxcw = 0;
++ u32 ctrl;
++ u32 status;
++ u32 rctl;
++ u32 icr;
++ u32 signal = 0;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_check_for_link");
+
+@@ -2923,7 +2924,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+ if (hw->media_type == e1000_media_type_fiber) {
+ signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
+ if (status & E1000_STATUS_LU)
+- hw->get_link_status = FALSE;
++ hw->get_link_status = false;
+ }
+ }
+
+@@ -2947,7 +2948,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+ return ret_val;
+
+ if (phy_data & MII_SR_LINK_STATUS) {
+- hw->get_link_status = FALSE;
++ hw->get_link_status = false;
+ /* Check if there was DownShift, must be checked immediately after
+ * link-up */
+ e1000_check_downshift(hw);
+@@ -2973,7 +2974,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+
+ } else {
+ /* No link detected */
+- e1000_config_dsp_after_link_change(hw, FALSE);
++ e1000_config_dsp_after_link_change(hw, false);
+ return 0;
+ }
+
+@@ -2983,7 +2984,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+ if (!hw->autoneg) return -E1000_ERR_CONFIG;
+
+ /* optimize the dsp settings for the igp phy */
+- e1000_config_dsp_after_link_change(hw, TRUE);
++ e1000_config_dsp_after_link_change(hw, true);
+
+ /* We have a M88E1000 PHY and Auto-Neg is enabled. If we
+ * have Si on board that is 82544 or newer, Auto
+@@ -3021,7 +3022,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+ * at gigabit speed, we turn on TBI compatibility.
+ */
+ if (hw->tbi_compatibility_en) {
+- uint16_t speed, duplex;
++ u16 speed, duplex;
+ ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
+ if (ret_val) {
+ DEBUGOUT("Error getting link speed and duplex\n");
+@@ -3036,7 +3037,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+ rctl = E1000_READ_REG(hw, RCTL);
+ rctl &= ~E1000_RCTL_SBP;
+ E1000_WRITE_REG(hw, RCTL, rctl);
+- hw->tbi_compatibility_on = FALSE;
++ hw->tbi_compatibility_on = false;
+ }
+ } else {
+ /* If TBI compatibility is was previously off, turn it on. For
+@@ -3045,7 +3046,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+ * will look like CRC errors to to the hardware.
+ */
+ if (!hw->tbi_compatibility_on) {
+- hw->tbi_compatibility_on = TRUE;
++ hw->tbi_compatibility_on = true;
+ rctl = E1000_READ_REG(hw, RCTL);
+ rctl |= E1000_RCTL_SBP;
+ E1000_WRITE_REG(hw, RCTL, rctl);
+@@ -3098,7 +3099,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+ E1000_WRITE_REG(hw, TXCW, hw->txcw);
+ E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU));
+
+- hw->serdes_link_down = FALSE;
++ hw->serdes_link_down = false;
+ }
+ /* If we force link for non-auto-negotiation switch, check link status
+ * based on MAC synchronization for internal serdes media type.
+@@ -3109,11 +3110,11 @@ e1000_check_for_link(struct e1000_hw *hw)
+ udelay(10);
+ if (E1000_RXCW_SYNCH & E1000_READ_REG(hw, RXCW)) {
+ if (!(rxcw & E1000_RXCW_IV)) {
+- hw->serdes_link_down = FALSE;
++ hw->serdes_link_down = false;
+ DEBUGOUT("SERDES: Link is up.\n");
+ }
+ } else {
+- hw->serdes_link_down = TRUE;
++ hw->serdes_link_down = true;
+ DEBUGOUT("SERDES: Link is down.\n");
+ }
+ }
+@@ -3131,14 +3132,14 @@ e1000_check_for_link(struct e1000_hw *hw)
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_get_speed_and_duplex(struct e1000_hw *hw,
+- uint16_t *speed,
+- uint16_t *duplex)
++ u16 *speed,
++ u16 *duplex)
+ {
+- uint32_t status;
+- int32_t ret_val;
+- uint16_t phy_data;
++ u32 status;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_get_speed_and_duplex");
+
+@@ -3213,12 +3214,12 @@ e1000_get_speed_and_duplex(struct e1000_hw *hw,
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_wait_autoneg(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t i;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 i;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_wait_autoneg");
+ DEBUGOUT("Waiting for Auto-Neg to complete.\n");
+@@ -3250,7 +3251,7 @@ e1000_wait_autoneg(struct e1000_hw *hw)
+ ******************************************************************************/
+ static void
+ e1000_raise_mdi_clk(struct e1000_hw *hw,
+- uint32_t *ctrl)
++ u32 *ctrl)
+ {
+ /* Raise the clock input to the Management Data Clock (by setting the MDC
+ * bit), and then delay 10 microseconds.
+@@ -3268,7 +3269,7 @@ e1000_raise_mdi_clk(struct e1000_hw *hw,
+ ******************************************************************************/
+ static void
+ e1000_lower_mdi_clk(struct e1000_hw *hw,
+- uint32_t *ctrl)
++ u32 *ctrl)
+ {
+ /* Lower the clock input to the Management Data Clock (by clearing the MDC
+ * bit), and then delay 10 microseconds.
+@@ -3289,11 +3290,11 @@ e1000_lower_mdi_clk(struct e1000_hw *hw,
+ ******************************************************************************/
+ static void
+ e1000_shift_out_mdi_bits(struct e1000_hw *hw,
+- uint32_t data,
+- uint16_t count)
++ u32 data,
++ u16 count)
+ {
+- uint32_t ctrl;
+- uint32_t mask;
++ u32 ctrl;
++ u32 mask;
+
+ /* We need to shift "count" number of bits out to the PHY. So, the value
+ * in the "data" parameter will be shifted out to the PHY one bit at a
+@@ -3337,12 +3338,12 @@ e1000_shift_out_mdi_bits(struct e1000_hw *hw,
+ *
+ * Bits are shifted in in MSB to LSB order.
+ ******************************************************************************/
+-static uint16_t
++static u16
+ e1000_shift_in_mdi_bits(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
+- uint16_t data = 0;
+- uint8_t i;
++ u32 ctrl;
++ u16 data = 0;
++ u8 i;
+
+ /* In order to read a register from the PHY, we need to shift in a total
+ * of 18 bits from the PHY. The first two bit (turnaround) times are used
+@@ -3383,13 +3384,13 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw)
+ return data;
+ }
+
+-static int32_t
+-e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
++static s32
++e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask)
+ {
+- uint32_t swfw_sync = 0;
+- uint32_t swmask = mask;
+- uint32_t fwmask = mask << 16;
+- int32_t timeout = 200;
++ u32 swfw_sync = 0;
++ u32 swmask = mask;
++ u32 fwmask = mask << 16;
++ s32 timeout = 200;
+
+ DEBUGFUNC("e1000_swfw_sync_acquire");
+
+@@ -3428,10 +3429,10 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
+ }
+
+ static void
+-e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask)
++e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask)
+ {
+- uint32_t swfw_sync;
+- uint32_t swmask = mask;
++ u32 swfw_sync;
++ u32 swmask = mask;
+
+ DEBUGFUNC("e1000_swfw_sync_release");
+
+@@ -3463,13 +3464,13 @@ e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask)
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ ******************************************************************************/
+-int32_t
++s32
+ e1000_read_phy_reg(struct e1000_hw *hw,
+- uint32_t reg_addr,
+- uint16_t *phy_data)
++ u32 reg_addr,
++ u16 *phy_data)
+ {
+- uint32_t ret_val;
+- uint16_t swfw;
++ u32 ret_val;
++ u16 swfw;
+
+ DEBUGFUNC("e1000_read_phy_reg");
+
+@@ -3487,7 +3488,7 @@ e1000_read_phy_reg(struct e1000_hw *hw,
+ hw->phy_type == e1000_phy_igp_2) &&
+ (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
+ ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
+- (uint16_t)reg_addr);
++ (u16)reg_addr);
+ if (ret_val) {
+ e1000_swfw_sync_release(hw, swfw);
+ return ret_val;
+@@ -3498,14 +3499,14 @@ e1000_read_phy_reg(struct e1000_hw *hw,
+ /* Select Configuration Page */
+ if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
+ ret_val = e1000_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT,
+- (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
++ (u16)((u16)reg_addr >> GG82563_PAGE_SHIFT));
+ } else {
+ /* Use Alternative Page Select register to access
+ * registers 30 and 31
+ */
+ ret_val = e1000_write_phy_reg_ex(hw,
+ GG82563_PHY_PAGE_SELECT_ALT,
+- (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
++ (u16)((u16)reg_addr >> GG82563_PAGE_SHIFT));
+ }
+
+ if (ret_val) {
+@@ -3522,13 +3523,13 @@ e1000_read_phy_reg(struct e1000_hw *hw,
+ return ret_val;
+ }
+
+-static int32_t
+-e1000_read_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+- uint16_t *phy_data)
++static s32
++e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
++ u16 *phy_data)
+ {
+- uint32_t i;
+- uint32_t mdic = 0;
+- const uint32_t phy_addr = 1;
++ u32 i;
++ u32 mdic = 0;
++ const u32 phy_addr = 1;
+
+ DEBUGFUNC("e1000_read_phy_reg_ex");
+
+@@ -3562,7 +3563,7 @@ e1000_read_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+ DEBUGOUT("MDI Error\n");
+ return -E1000_ERR_PHY;
+ }
+- *phy_data = (uint16_t) mdic;
++ *phy_data = (u16) mdic;
+ } else {
+ /* We must first send a preamble through the MDIO pin to signal the
+ * beginning of an MII instruction. This is done by sending 32
+@@ -3602,12 +3603,12 @@ e1000_read_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ ******************************************************************************/
+-int32_t
+-e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr,
+- uint16_t phy_data)
++s32
++e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr,
++ u16 phy_data)
+ {
+- uint32_t ret_val;
+- uint16_t swfw;
++ u32 ret_val;
++ u16 swfw;
+
+ DEBUGFUNC("e1000_write_phy_reg");
+
+@@ -3625,7 +3626,7 @@ e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr,
+ hw->phy_type == e1000_phy_igp_2) &&
+ (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
+ ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
+- (uint16_t)reg_addr);
++ (u16)reg_addr);
+ if (ret_val) {
+ e1000_swfw_sync_release(hw, swfw);
+ return ret_val;
+@@ -3636,14 +3637,14 @@ e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr,
+ /* Select Configuration Page */
+ if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
+ ret_val = e1000_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT,
+- (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
++ (u16)((u16)reg_addr >> GG82563_PAGE_SHIFT));
+ } else {
+ /* Use Alternative Page Select register to access
+ * registers 30 and 31
+ */
+ ret_val = e1000_write_phy_reg_ex(hw,
+ GG82563_PHY_PAGE_SELECT_ALT,
+- (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
++ (u16)((u16)reg_addr >> GG82563_PAGE_SHIFT));
+ }
+
+ if (ret_val) {
+@@ -3660,13 +3661,13 @@ e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr,
+ return ret_val;
+ }
+
+-static int32_t
+-e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+- uint16_t phy_data)
++static s32
++e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
++ u16 phy_data)
+ {
+- uint32_t i;
+- uint32_t mdic = 0;
+- const uint32_t phy_addr = 1;
++ u32 i;
++ u32 mdic = 0;
++ const u32 phy_addr = 1;
+
+ DEBUGFUNC("e1000_write_phy_reg_ex");
+
+@@ -3680,7 +3681,7 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+ * for the PHY register in the MDI Control register. The MAC will take
+ * care of interfacing with the PHY to send the desired data.
+ */
+- mdic = (((uint32_t) phy_data) |
++ mdic = (((u32) phy_data) |
+ (reg_addr << E1000_MDIC_REG_SHIFT) |
+ (phy_addr << E1000_MDIC_PHY_SHIFT) |
+ (E1000_MDIC_OP_WRITE));
+@@ -3714,7 +3715,7 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+ mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) |
+ (PHY_OP_WRITE << 12) | (PHY_SOF << 14));
+ mdic <<= 16;
+- mdic |= (uint32_t) phy_data;
++ mdic |= (u32) phy_data;
+
+ e1000_shift_out_mdi_bits(hw, mdic, 32);
+ }
+@@ -3722,13 +3723,13 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+ return E1000_SUCCESS;
+ }
+
+-static int32_t
++static s32
+ e1000_read_kmrn_reg(struct e1000_hw *hw,
+- uint32_t reg_addr,
+- uint16_t *data)
++ u32 reg_addr,
++ u16 *data)
+ {
+- uint32_t reg_val;
+- uint16_t swfw;
++ u32 reg_val;
++ u16 swfw;
+ DEBUGFUNC("e1000_read_kmrn_reg");
+
+ if ((hw->mac_type == e1000_80003es2lan) &&
+@@ -3749,19 +3750,19 @@ e1000_read_kmrn_reg(struct e1000_hw *hw,
+
+ /* Read the data returned */
+ reg_val = E1000_READ_REG(hw, KUMCTRLSTA);
+- *data = (uint16_t)reg_val;
++ *data = (u16)reg_val;
+
+ e1000_swfw_sync_release(hw, swfw);
+ return E1000_SUCCESS;
+ }
+
+-static int32_t
++static s32
+ e1000_write_kmrn_reg(struct e1000_hw *hw,
+- uint32_t reg_addr,
+- uint16_t data)
++ u32 reg_addr,
++ u16 data)
+ {
+- uint32_t reg_val;
+- uint16_t swfw;
++ u32 reg_val;
++ u16 swfw;
+ DEBUGFUNC("e1000_write_kmrn_reg");
+
+ if ((hw->mac_type == e1000_80003es2lan) &&
+@@ -3787,13 +3788,13 @@ e1000_write_kmrn_reg(struct e1000_hw *hw,
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-int32_t
++s32
+ e1000_phy_hw_reset(struct e1000_hw *hw)
+ {
+- uint32_t ctrl, ctrl_ext;
+- uint32_t led_ctrl;
+- int32_t ret_val;
+- uint16_t swfw;
++ u32 ctrl, ctrl_ext;
++ u32 led_ctrl;
++ s32 ret_val;
++ u16 swfw;
+
+ DEBUGFUNC("e1000_phy_hw_reset");
+
+@@ -3881,11 +3882,11 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
+ *
+ * Sets bit 15 of the MII Control register
+ ******************************************************************************/
+-int32_t
++s32
+ e1000_phy_reset(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_phy_reset");
+
+@@ -3936,9 +3937,9 @@ e1000_phy_reset(struct e1000_hw *hw)
+ void
+ e1000_phy_powerdown_workaround(struct e1000_hw *hw)
+ {
+- int32_t reg;
+- uint16_t phy_data;
+- int32_t retry = 0;
++ s32 reg;
++ u16 phy_data;
++ s32 retry = 0;
+
+ DEBUGFUNC("e1000_phy_powerdown_workaround");
+
+@@ -3986,13 +3987,13 @@ e1000_phy_powerdown_workaround(struct e1000_hw *hw)
+ *
+ * hw - struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- int32_t reg;
+- int32_t cnt;
+- uint16_t phy_data;
++ s32 ret_val;
++ s32 reg;
++ s32 cnt;
++ u16 phy_data;
+
+ if (hw->kmrn_lock_loss_workaround_disabled)
+ return E1000_SUCCESS;
+@@ -4039,12 +4040,12 @@ e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_detect_gig_phy(struct e1000_hw *hw)
+ {
+- int32_t phy_init_status, ret_val;
+- uint16_t phy_id_high, phy_id_low;
+- boolean_t match = FALSE;
++ s32 phy_init_status, ret_val;
++ u16 phy_id_high, phy_id_low;
++ bool match = false;
+
+ DEBUGFUNC("e1000_detect_gig_phy");
+
+@@ -4075,46 +4076,46 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+
+- hw->phy_id = (uint32_t) (phy_id_high << 16);
++ hw->phy_id = (u32) (phy_id_high << 16);
+ udelay(20);
+ ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low);
+ if (ret_val)
+ return ret_val;
+
+- hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK);
+- hw->phy_revision = (uint32_t) phy_id_low & ~PHY_REVISION_MASK;
++ hw->phy_id |= (u32) (phy_id_low & PHY_REVISION_MASK);
++ hw->phy_revision = (u32) phy_id_low & ~PHY_REVISION_MASK;
+
+ switch (hw->mac_type) {
+ case e1000_82543:
+- if (hw->phy_id == M88E1000_E_PHY_ID) match = TRUE;
++ if (hw->phy_id == M88E1000_E_PHY_ID) match = true;
+ break;
+ case e1000_82544:
+- if (hw->phy_id == M88E1000_I_PHY_ID) match = TRUE;
++ if (hw->phy_id == M88E1000_I_PHY_ID) match = true;
+ break;
+ case e1000_82540:
+ case e1000_82545:
+ case e1000_82545_rev_3:
+ case e1000_82546:
+ case e1000_82546_rev_3:
+- if (hw->phy_id == M88E1011_I_PHY_ID) match = TRUE;
++ if (hw->phy_id == M88E1011_I_PHY_ID) match = true;
+ break;
+ case e1000_82541:
+ case e1000_82541_rev_2:
+ case e1000_82547:
+ case e1000_82547_rev_2:
+- if (hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE;
++ if (hw->phy_id == IGP01E1000_I_PHY_ID) match = true;
+ break;
+ case e1000_82573:
+- if (hw->phy_id == M88E1111_I_PHY_ID) match = TRUE;
++ if (hw->phy_id == M88E1111_I_PHY_ID) match = true;
+ break;
+ case e1000_80003es2lan:
+- if (hw->phy_id == GG82563_E_PHY_ID) match = TRUE;
++ if (hw->phy_id == GG82563_E_PHY_ID) match = true;
+ break;
+ case e1000_ich8lan:
+- if (hw->phy_id == IGP03E1000_E_PHY_ID) match = TRUE;
+- if (hw->phy_id == IFE_E_PHY_ID) match = TRUE;
+- if (hw->phy_id == IFE_PLUS_E_PHY_ID) match = TRUE;
+- if (hw->phy_id == IFE_C_E_PHY_ID) match = TRUE;
++ if (hw->phy_id == IGP03E1000_E_PHY_ID) match = true;
++ if (hw->phy_id == IFE_E_PHY_ID) match = true;
++ if (hw->phy_id == IFE_PLUS_E_PHY_ID) match = true;
++ if (hw->phy_id == IFE_C_E_PHY_ID) match = true;
+ break;
+ default:
+ DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
+@@ -4135,10 +4136,10 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_phy_reset_dsp(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
++ s32 ret_val;
+ DEBUGFUNC("e1000_phy_reset_dsp");
+
+ do {
+@@ -4162,12 +4163,12 @@ e1000_phy_reset_dsp(struct e1000_hw *hw)
+ * hw - Struct containing variables accessed by shared code
+ * phy_info - PHY information structure
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_phy_igp_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info)
+ {
+- int32_t ret_val;
+- uint16_t phy_data, min_length, max_length, average;
++ s32 ret_val;
++ u16 phy_data, min_length, max_length, average;
+ e1000_rev_polarity polarity;
+
+ DEBUGFUNC("e1000_phy_igp_get_info");
+@@ -4239,12 +4240,12 @@ e1000_phy_igp_get_info(struct e1000_hw *hw,
+ * hw - Struct containing variables accessed by shared code
+ * phy_info - PHY information structure
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_phy_ife_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 phy_data;
+ e1000_rev_polarity polarity;
+
+ DEBUGFUNC("e1000_phy_ife_get_info");
+@@ -4289,12 +4290,12 @@ e1000_phy_ife_get_info(struct e1000_hw *hw,
+ * hw - Struct containing variables accessed by shared code
+ * phy_info - PHY information structure
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_phy_m88_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 phy_data;
+ e1000_rev_polarity polarity;
+
+ DEBUGFUNC("e1000_phy_m88_get_info");
+@@ -4368,12 +4369,12 @@ e1000_phy_m88_get_info(struct e1000_hw *hw,
+ * hw - Struct containing variables accessed by shared code
+ * phy_info - PHY information structure
+ ******************************************************************************/
+-int32_t
++s32
+ e1000_phy_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_phy_get_info");
+
+@@ -4414,7 +4415,7 @@ e1000_phy_get_info(struct e1000_hw *hw,
+ return e1000_phy_m88_get_info(hw, phy_info);
+ }
+
+-int32_t
++s32
+ e1000_validate_mdi_setting(struct e1000_hw *hw)
+ {
+ DEBUGFUNC("e1000_validate_mdi_settings");
+@@ -4435,13 +4436,13 @@ e1000_validate_mdi_setting(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_init_eeprom_params(struct e1000_hw *hw)
+ {
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+- uint32_t eecd = E1000_READ_REG(hw, EECD);
+- int32_t ret_val = E1000_SUCCESS;
+- uint16_t eeprom_size;
++ u32 eecd = E1000_READ_REG(hw, EECD);
++ s32 ret_val = E1000_SUCCESS;
++ u16 eeprom_size;
+
+ DEBUGFUNC("e1000_init_eeprom_params");
+
+@@ -4455,8 +4456,8 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+ eeprom->opcode_bits = 3;
+ eeprom->address_bits = 6;
+ eeprom->delay_usec = 50;
+- eeprom->use_eerd = FALSE;
+- eeprom->use_eewr = FALSE;
++ eeprom->use_eerd = false;
++ eeprom->use_eewr = false;
+ break;
+ case e1000_82540:
+ case e1000_82545:
+@@ -4473,8 +4474,8 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+ eeprom->word_size = 64;
+ eeprom->address_bits = 6;
+ }
+- eeprom->use_eerd = FALSE;
+- eeprom->use_eewr = FALSE;
++ eeprom->use_eerd = false;
++ eeprom->use_eewr = false;
+ break;
+ case e1000_82541:
+ case e1000_82541_rev_2:
+@@ -4503,8 +4504,8 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+ eeprom->address_bits = 6;
+ }
+ }
+- eeprom->use_eerd = FALSE;
+- eeprom->use_eewr = FALSE;
++ eeprom->use_eerd = false;
++ eeprom->use_eewr = false;
+ break;
+ case e1000_82571:
+ case e1000_82572:
+@@ -4518,8 +4519,8 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+ eeprom->page_size = 8;
+ eeprom->address_bits = 8;
+ }
+- eeprom->use_eerd = FALSE;
+- eeprom->use_eewr = FALSE;
++ eeprom->use_eerd = false;
++ eeprom->use_eewr = false;
+ break;
+ case e1000_82573:
+ eeprom->type = e1000_eeprom_spi;
+@@ -4532,9 +4533,9 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+ eeprom->page_size = 8;
+ eeprom->address_bits = 8;
+ }
+- eeprom->use_eerd = TRUE;
+- eeprom->use_eewr = TRUE;
+- if (e1000_is_onboard_nvm_eeprom(hw) == FALSE) {
++ eeprom->use_eerd = true;
++ eeprom->use_eewr = true;
++ if (!e1000_is_onboard_nvm_eeprom(hw)) {
+ eeprom->type = e1000_eeprom_flash;
+ eeprom->word_size = 2048;
+
+@@ -4555,24 +4556,24 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+ eeprom->page_size = 8;
+ eeprom->address_bits = 8;
+ }
+- eeprom->use_eerd = TRUE;
+- eeprom->use_eewr = FALSE;
++ eeprom->use_eerd = true;
++ eeprom->use_eewr = false;
+ break;
+ case e1000_ich8lan:
+ {
+- int32_t i = 0;
+- uint32_t flash_size = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_GFPREG);
++ s32 i = 0;
++ u32 flash_size = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_GFPREG);
+
+ eeprom->type = e1000_eeprom_ich8;
+- eeprom->use_eerd = FALSE;
+- eeprom->use_eewr = FALSE;
++ eeprom->use_eerd = false;
++ eeprom->use_eewr = false;
+ eeprom->word_size = E1000_SHADOW_RAM_WORDS;
+
+ /* Zero the shadow RAM structure. But don't load it from NVM
+ * so as to save time for driver init */
+ if (hw->eeprom_shadow_ram != NULL) {
+ for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
+- hw->eeprom_shadow_ram[i].modified = FALSE;
++ hw->eeprom_shadow_ram[i].modified = false;
+ hw->eeprom_shadow_ram[i].eeprom_word = 0xFFFF;
+ }
+ }
+@@ -4585,7 +4586,7 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+
+ hw->flash_bank_size *= ICH_FLASH_SECTOR_SIZE;
+
+- hw->flash_bank_size /= 2 * sizeof(uint16_t);
++ hw->flash_bank_size /= 2 * sizeof(u16);
+
+ break;
+ }
+@@ -4610,7 +4611,7 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+ if (eeprom_size)
+ eeprom_size++;
+ } else {
+- eeprom_size = (uint16_t)((eecd & E1000_EECD_SIZE_EX_MASK) >>
++ eeprom_size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
+ E1000_EECD_SIZE_EX_SHIFT);
+ }
+
+@@ -4627,7 +4628,7 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+ *****************************************************************************/
+ static void
+ e1000_raise_ee_clk(struct e1000_hw *hw,
+- uint32_t *eecd)
++ u32 *eecd)
+ {
+ /* Raise the clock input to the EEPROM (by setting the SK bit), and then
+ * wait <delay> microseconds.
+@@ -4646,7 +4647,7 @@ e1000_raise_ee_clk(struct e1000_hw *hw,
+ *****************************************************************************/
+ static void
+ e1000_lower_ee_clk(struct e1000_hw *hw,
+- uint32_t *eecd)
++ u32 *eecd)
+ {
+ /* Lower the clock input to the EEPROM (by clearing the SK bit), and then
+ * wait 50 microseconds.
+@@ -4666,12 +4667,12 @@ e1000_lower_ee_clk(struct e1000_hw *hw,
+ *****************************************************************************/
+ static void
+ e1000_shift_out_ee_bits(struct e1000_hw *hw,
+- uint16_t data,
+- uint16_t count)
++ u16 data,
++ u16 count)
+ {
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+- uint32_t eecd;
+- uint32_t mask;
++ u32 eecd;
++ u32 mask;
+
+ /* We need to shift "count" bits out to the EEPROM. So, value in the
+ * "data" parameter will be shifted out to the EEPROM one bit at a time.
+@@ -4717,13 +4718,13 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw,
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-static uint16_t
++static u16
+ e1000_shift_in_ee_bits(struct e1000_hw *hw,
+- uint16_t count)
++ u16 count)
+ {
+- uint32_t eecd;
+- uint32_t i;
+- uint16_t data;
++ u32 eecd;
++ u32 i;
++ u16 data;
+
+ /* In order to read a register from the EEPROM, we need to shift 'count'
+ * bits in from the EEPROM. Bits are "shifted in" by raising the clock
+@@ -4761,11 +4762,11 @@ e1000_shift_in_ee_bits(struct e1000_hw *hw,
+ * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
+ * function should be called before issuing a command to the EEPROM.
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_acquire_eeprom(struct e1000_hw *hw)
+ {
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+- uint32_t eecd, i=0;
++ u32 eecd, i=0;
+
+ DEBUGFUNC("e1000_acquire_eeprom");
+
+@@ -4824,7 +4825,7 @@ static void
+ e1000_standby_eeprom(struct e1000_hw *hw)
+ {
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+- uint32_t eecd;
++ u32 eecd;
+
+ eecd = E1000_READ_REG(hw, EECD);
+
+@@ -4872,7 +4873,7 @@ e1000_standby_eeprom(struct e1000_hw *hw)
+ static void
+ e1000_release_eeprom(struct e1000_hw *hw)
+ {
+- uint32_t eecd;
++ u32 eecd;
+
+ DEBUGFUNC("e1000_release_eeprom");
+
+@@ -4920,11 +4921,11 @@ e1000_release_eeprom(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_spi_eeprom_ready(struct e1000_hw *hw)
+ {
+- uint16_t retry_count = 0;
+- uint8_t spi_stat_reg;
++ u16 retry_count = 0;
++ u8 spi_stat_reg;
+
+ DEBUGFUNC("e1000_spi_eeprom_ready");
+
+@@ -4937,7 +4938,7 @@ e1000_spi_eeprom_ready(struct e1000_hw *hw)
+ do {
+ e1000_shift_out_ee_bits(hw, EEPROM_RDSR_OPCODE_SPI,
+ hw->eeprom.opcode_bits);
+- spi_stat_reg = (uint8_t)e1000_shift_in_ee_bits(hw, 8);
++ spi_stat_reg = (u8)e1000_shift_in_ee_bits(hw, 8);
+ if (!(spi_stat_reg & EEPROM_STATUS_RDY_SPI))
+ break;
+
+@@ -4966,14 +4967,14 @@ e1000_spi_eeprom_ready(struct e1000_hw *hw)
+ * data - word read from the EEPROM
+ * words - number of words to read
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_read_eeprom(struct e1000_hw *hw,
+- uint16_t offset,
+- uint16_t words,
+- uint16_t *data)
++ u16 offset,
++ u16 words,
++ u16 *data)
+ {
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+- uint32_t i = 0;
++ u32 i = 0;
+
+ DEBUGFUNC("e1000_read_eeprom");
+
+@@ -4994,15 +4995,14 @@ e1000_read_eeprom(struct e1000_hw *hw,
+ * directly. In this case, we need to acquire the EEPROM so that
+ * FW or other port software does not interrupt.
+ */
+- if (e1000_is_onboard_nvm_eeprom(hw) == TRUE &&
+- hw->eeprom.use_eerd == FALSE) {
++ if (e1000_is_onboard_nvm_eeprom(hw) && !hw->eeprom.use_eerd) {
+ /* Prepare the EEPROM for bit-bang reading */
+ if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
+ return -E1000_ERR_EEPROM;
+ }
+
+ /* Eerd register EEPROM access requires no eeprom aquire/release */
+- if (eeprom->use_eerd == TRUE)
++ if (eeprom->use_eerd)
+ return e1000_read_eeprom_eerd(hw, offset, words, data);
+
+ /* ICH EEPROM access is done via the ICH flash controller */
+@@ -5012,8 +5012,8 @@ e1000_read_eeprom(struct e1000_hw *hw,
+ /* Set up the SPI or Microwire EEPROM for bit-bang reading. We have
+ * acquired the EEPROM at this point, so any returns should relase it */
+ if (eeprom->type == e1000_eeprom_spi) {
+- uint16_t word_in;
+- uint8_t read_opcode = EEPROM_READ_OPCODE_SPI;
++ u16 word_in;
++ u8 read_opcode = EEPROM_READ_OPCODE_SPI;
+
+ if (e1000_spi_eeprom_ready(hw)) {
+ e1000_release_eeprom(hw);
+@@ -5028,7 +5028,7 @@ e1000_read_eeprom(struct e1000_hw *hw,
+
+ /* Send the READ command (opcode + addr) */
+ e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits);
+- e1000_shift_out_ee_bits(hw, (uint16_t)(offset*2), eeprom->address_bits);
++ e1000_shift_out_ee_bits(hw, (u16)(offset*2), eeprom->address_bits);
+
+ /* Read the data. The address of the eeprom internally increments with
+ * each byte (spi) being read, saving on the overhead of eeprom setup
+@@ -5044,7 +5044,7 @@ e1000_read_eeprom(struct e1000_hw *hw,
+ /* Send the READ command (opcode + addr) */
+ e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE_MICROWIRE,
+ eeprom->opcode_bits);
+- e1000_shift_out_ee_bits(hw, (uint16_t)(offset + i),
++ e1000_shift_out_ee_bits(hw, (u16)(offset + i),
+ eeprom->address_bits);
+
+ /* Read the data. For microwire, each word requires the overhead
+@@ -5068,14 +5068,14 @@ e1000_read_eeprom(struct e1000_hw *hw,
+ * data - word read from the EEPROM
+ * words - number of words to read
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_read_eeprom_eerd(struct e1000_hw *hw,
+- uint16_t offset,
+- uint16_t words,
+- uint16_t *data)
++ u16 offset,
++ u16 words,
++ u16 *data)
+ {
+- uint32_t i, eerd = 0;
+- int32_t error = 0;
++ u32 i, eerd = 0;
++ s32 error = 0;
+
+ for (i = 0; i < words; i++) {
+ eerd = ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) +
+@@ -5102,15 +5102,15 @@ e1000_read_eeprom_eerd(struct e1000_hw *hw,
+ * data - word read from the EEPROM
+ * words - number of words to read
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_write_eeprom_eewr(struct e1000_hw *hw,
+- uint16_t offset,
+- uint16_t words,
+- uint16_t *data)
++ u16 offset,
++ u16 words,
++ u16 *data)
+ {
+- uint32_t register_value = 0;
+- uint32_t i = 0;
+- int32_t error = 0;
++ u32 register_value = 0;
++ u32 i = 0;
++ s32 error = 0;
+
+ if (e1000_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM))
+ return -E1000_ERR_SWFW_SYNC;
+@@ -5143,12 +5143,12 @@ e1000_write_eeprom_eewr(struct e1000_hw *hw,
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
+ {
+- uint32_t attempts = 100000;
+- uint32_t i, reg = 0;
+- int32_t done = E1000_ERR_EEPROM;
++ u32 attempts = 100000;
++ u32 i, reg = 0;
++ s32 done = E1000_ERR_EEPROM;
+
+ for (i = 0; i < attempts; i++) {
+ if (eerd == E1000_EEPROM_POLL_READ)
+@@ -5171,15 +5171,15 @@ e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ****************************************************************************/
+-static boolean_t
++static bool
+ e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
+ {
+- uint32_t eecd = 0;
++ u32 eecd = 0;
+
+ DEBUGFUNC("e1000_is_onboard_nvm_eeprom");
+
+ if (hw->mac_type == e1000_ich8lan)
+- return FALSE;
++ return false;
+
+ if (hw->mac_type == e1000_82573) {
+ eecd = E1000_READ_REG(hw, EECD);
+@@ -5189,10 +5189,10 @@ e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
+
+ /* If both bits are set, device is Flash type */
+ if (eecd == 0x03) {
+- return FALSE;
++ return false;
+ }
+ }
+- return TRUE;
++ return true;
+ }
+
+ /******************************************************************************
+@@ -5204,16 +5204,15 @@ e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
+ * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
+ * valid.
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_validate_eeprom_checksum(struct e1000_hw *hw)
+ {
+- uint16_t checksum = 0;
+- uint16_t i, eeprom_data;
++ u16 checksum = 0;
++ u16 i, eeprom_data;
+
+ DEBUGFUNC("e1000_validate_eeprom_checksum");
+
+- if ((hw->mac_type == e1000_82573) &&
+- (e1000_is_onboard_nvm_eeprom(hw) == FALSE)) {
++ if ((hw->mac_type == e1000_82573) && !e1000_is_onboard_nvm_eeprom(hw)) {
+ /* Check bit 4 of word 10h. If it is 0, firmware is done updating
+ * 10h-12h. Checksum may need to be fixed. */
+ e1000_read_eeprom(hw, 0x10, 1, &eeprom_data);
+@@ -5253,7 +5252,7 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw)
+ checksum += eeprom_data;
+ }
+
+- if (checksum == (uint16_t) EEPROM_SUM)
++ if (checksum == (u16) EEPROM_SUM)
+ return E1000_SUCCESS;
+ else {
+ DEBUGOUT("EEPROM Checksum Invalid\n");
+@@ -5269,12 +5268,12 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw)
+ * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
+ * Writes the difference to word offset 63 of the EEPROM.
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_update_eeprom_checksum(struct e1000_hw *hw)
+ {
+- uint32_t ctrl_ext;
+- uint16_t checksum = 0;
+- uint16_t i, eeprom_data;
++ u32 ctrl_ext;
++ u16 checksum = 0;
++ u16 i, eeprom_data;
+
+ DEBUGFUNC("e1000_update_eeprom_checksum");
+
+@@ -5285,7 +5284,7 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw)
+ }
+ checksum += eeprom_data;
+ }
+- checksum = (uint16_t) EEPROM_SUM - checksum;
++ checksum = (u16) EEPROM_SUM - checksum;
+ if (e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
+ DEBUGOUT("EEPROM Write Error\n");
+ return -E1000_ERR_EEPROM;
+@@ -5314,14 +5313,14 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw)
+ * If e1000_update_eeprom_checksum is not called after this function, the
+ * EEPROM will most likely contain an invalid checksum.
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_write_eeprom(struct e1000_hw *hw,
+- uint16_t offset,
+- uint16_t words,
+- uint16_t *data)
++ u16 offset,
++ u16 words,
++ u16 *data)
+ {
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+- int32_t status = 0;
++ s32 status = 0;
+
+ DEBUGFUNC("e1000_write_eeprom");
+
+@@ -5339,7 +5338,7 @@ e1000_write_eeprom(struct e1000_hw *hw,
+ }
+
+ /* 82573 writes only through eewr */
+- if (eeprom->use_eewr == TRUE)
++ if (eeprom->use_eewr)
+ return e1000_write_eeprom_eewr(hw, offset, words, data);
+
+ if (eeprom->type == e1000_eeprom_ich8)
+@@ -5371,19 +5370,19 @@ e1000_write_eeprom(struct e1000_hw *hw,
+ * data - pointer to array of 8 bit words to be written to the EEPROM
+ *
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_write_eeprom_spi(struct e1000_hw *hw,
+- uint16_t offset,
+- uint16_t words,
+- uint16_t *data)
++ u16 offset,
++ u16 words,
++ u16 *data)
+ {
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+- uint16_t widx = 0;
++ u16 widx = 0;
+
+ DEBUGFUNC("e1000_write_eeprom_spi");
+
+ while (widx < words) {
+- uint8_t write_opcode = EEPROM_WRITE_OPCODE_SPI;
++ u8 write_opcode = EEPROM_WRITE_OPCODE_SPI;
+
+ if (e1000_spi_eeprom_ready(hw)) return -E1000_ERR_EEPROM;
+
+@@ -5402,14 +5401,14 @@ e1000_write_eeprom_spi(struct e1000_hw *hw,
+ /* Send the Write command (8-bit opcode + addr) */
+ e1000_shift_out_ee_bits(hw, write_opcode, eeprom->opcode_bits);
+
+- e1000_shift_out_ee_bits(hw, (uint16_t)((offset + widx)*2),
++ e1000_shift_out_ee_bits(hw, (u16)((offset + widx)*2),
+ eeprom->address_bits);
+
+ /* Send the data */
+
+ /* Loop to allow for up to whole page write (32 bytes) of eeprom */
+ while (widx < words) {
+- uint16_t word_out = data[widx];
++ u16 word_out = data[widx];
+ word_out = (word_out >> 8) | (word_out << 8);
+ e1000_shift_out_ee_bits(hw, word_out, 16);
+ widx++;
+@@ -5437,16 +5436,16 @@ e1000_write_eeprom_spi(struct e1000_hw *hw,
+ * data - pointer to array of 16 bit words to be written to the EEPROM
+ *
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_write_eeprom_microwire(struct e1000_hw *hw,
+- uint16_t offset,
+- uint16_t words,
+- uint16_t *data)
++ u16 offset,
++ u16 words,
++ u16 *data)
+ {
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+- uint32_t eecd;
+- uint16_t words_written = 0;
+- uint16_t i = 0;
++ u32 eecd;
++ u16 words_written = 0;
++ u16 i = 0;
+
+ DEBUGFUNC("e1000_write_eeprom_microwire");
+
+@@ -5457,9 +5456,9 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw,
+ * EEPROM into write/erase mode.
+ */
+ e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE_MICROWIRE,
+- (uint16_t)(eeprom->opcode_bits + 2));
++ (u16)(eeprom->opcode_bits + 2));
+
+- e1000_shift_out_ee_bits(hw, 0, (uint16_t)(eeprom->address_bits - 2));
++ e1000_shift_out_ee_bits(hw, 0, (u16)(eeprom->address_bits - 2));
+
+ /* Prepare the EEPROM */
+ e1000_standby_eeprom(hw);
+@@ -5469,7 +5468,7 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw,
+ e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE_MICROWIRE,
+ eeprom->opcode_bits);
+
+- e1000_shift_out_ee_bits(hw, (uint16_t)(offset + words_written),
++ e1000_shift_out_ee_bits(hw, (u16)(offset + words_written),
+ eeprom->address_bits);
+
+ /* Send the data */
+@@ -5507,9 +5506,9 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw,
+ * EEPROM out of write/erase mode.
+ */
+ e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE_MICROWIRE,
+- (uint16_t)(eeprom->opcode_bits + 2));
++ (u16)(eeprom->opcode_bits + 2));
+
+- e1000_shift_out_ee_bits(hw, 0, (uint16_t)(eeprom->address_bits - 2));
++ e1000_shift_out_ee_bits(hw, 0, (u16)(eeprom->address_bits - 2));
+
+ return E1000_SUCCESS;
+ }
+@@ -5524,19 +5523,19 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw,
+ * data - word read from the EEPROM
+ * words - number of words to read
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_commit_shadow_ram(struct e1000_hw *hw)
+ {
+- uint32_t attempts = 100000;
+- uint32_t eecd = 0;
+- uint32_t flop = 0;
+- uint32_t i = 0;
+- int32_t error = E1000_SUCCESS;
+- uint32_t old_bank_offset = 0;
+- uint32_t new_bank_offset = 0;
+- uint8_t low_byte = 0;
+- uint8_t high_byte = 0;
+- boolean_t sector_write_failed = FALSE;
++ u32 attempts = 100000;
++ u32 eecd = 0;
++ u32 flop = 0;
++ u32 i = 0;
++ s32 error = E1000_SUCCESS;
++ u32 old_bank_offset = 0;
++ u32 new_bank_offset = 0;
++ u8 low_byte = 0;
++ u8 high_byte = 0;
++ bool sector_write_failed = false;
+
+ if (hw->mac_type == e1000_82573) {
+ /* The flop register will be used to determine if flash type is STM */
+@@ -5588,24 +5587,24 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+ e1000_erase_ich8_4k_segment(hw, 0);
+ }
+
+- sector_write_failed = FALSE;
++ sector_write_failed = false;
+ /* Loop for every byte in the shadow RAM,
+ * which is in units of words. */
+ for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
+ /* Determine whether to write the value stored
+ * in the other NVM bank or a modified value stored
+ * in the shadow RAM */
+- if (hw->eeprom_shadow_ram[i].modified == TRUE) {
+- low_byte = (uint8_t)hw->eeprom_shadow_ram[i].eeprom_word;
++ if (hw->eeprom_shadow_ram[i].modified) {
++ low_byte = (u8)hw->eeprom_shadow_ram[i].eeprom_word;
+ udelay(100);
+ error = e1000_verify_write_ich8_byte(hw,
+ (i << 1) + new_bank_offset, low_byte);
+
+ if (error != E1000_SUCCESS)
+- sector_write_failed = TRUE;
++ sector_write_failed = true;
+ else {
+ high_byte =
+- (uint8_t)(hw->eeprom_shadow_ram[i].eeprom_word >> 8);
++ (u8)(hw->eeprom_shadow_ram[i].eeprom_word >> 8);
+ udelay(100);
+ }
+ } else {
+@@ -5616,7 +5615,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+ (i << 1) + new_bank_offset, low_byte);
+
+ if (error != E1000_SUCCESS)
+- sector_write_failed = TRUE;
++ sector_write_failed = true;
+ else {
+ e1000_read_ich8_byte(hw, (i << 1) + old_bank_offset + 1,
+ &high_byte);
+@@ -5624,10 +5623,10 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+ }
+ }
+
+- /* If the write of the low byte was successful, go ahread and
++ /* If the write of the low byte was successful, go ahead and
+ * write the high byte while checking to make sure that if it
+ * is the signature byte, then it is handled properly */
+- if (sector_write_failed == FALSE) {
++ if (!sector_write_failed) {
+ /* If the word is 0x13, then make sure the signature bits
+ * (15:14) are 11b until the commit has completed.
+ * This will allow us to write 10b which indicates the
+@@ -5640,7 +5639,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+ error = e1000_verify_write_ich8_byte(hw,
+ (i << 1) + new_bank_offset + 1, high_byte);
+ if (error != E1000_SUCCESS)
+- sector_write_failed = TRUE;
++ sector_write_failed = true;
+
+ } else {
+ /* If the write failed then break from the loop and
+@@ -5651,7 +5650,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+
+ /* Don't bother writing the segment valid bits if sector
+ * programming failed. */
+- if (sector_write_failed == FALSE) {
++ if (!sector_write_failed) {
+ /* Finally validate the new segment by setting bit 15:14
+ * to 10b in word 0x13 , this can be done without an
+ * erase as well since these bits are 11 to start with
+@@ -5673,7 +5672,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+
+ /* Clear the now not used entry in the cache */
+ for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
+- hw->eeprom_shadow_ram[i].modified = FALSE;
++ hw->eeprom_shadow_ram[i].modified = false;
+ hw->eeprom_shadow_ram[i].eeprom_word = 0xFFFF;
+ }
+ }
+@@ -5688,11 +5687,11 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_read_mac_addr(struct e1000_hw * hw)
+ {
+- uint16_t offset;
+- uint16_t eeprom_data, i;
++ u16 offset;
++ u16 eeprom_data, i;
+
+ DEBUGFUNC("e1000_read_mac_addr");
+
+@@ -5702,8 +5701,8 @@ e1000_read_mac_addr(struct e1000_hw * hw)
+ DEBUGOUT("EEPROM Read Error\n");
+ return -E1000_ERR_EEPROM;
+ }
+- hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF);
+- hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8);
++ hw->perm_mac_addr[i] = (u8) (eeprom_data & 0x00FF);
++ hw->perm_mac_addr[i+1] = (u8) (eeprom_data >> 8);
+ }
+
+ switch (hw->mac_type) {
+@@ -5735,8 +5734,8 @@ e1000_read_mac_addr(struct e1000_hw * hw)
+ static void
+ e1000_init_rx_addrs(struct e1000_hw *hw)
+ {
+- uint32_t i;
+- uint32_t rar_num;
++ u32 i;
++ u32 rar_num;
+
+ DEBUGFUNC("e1000_init_rx_addrs");
+
+@@ -5750,7 +5749,7 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
+ /* Reserve a spot for the Locally Administered Address to work around
+ * an 82571 issue in which a reset on one port will reload the MAC on
+ * the other port. */
+- if ((hw->mac_type == e1000_82571) && (hw->laa_is_present == TRUE))
++ if ((hw->mac_type == e1000_82571) && (hw->laa_is_present))
+ rar_num -= 1;
+ if (hw->mac_type == e1000_ich8lan)
+ rar_num = E1000_RAR_ENTRIES_ICH8LAN;
+@@ -5771,11 +5770,11 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
+ * hw - Struct containing variables accessed by shared code
+ * mc_addr - the multicast address to hash
+ *****************************************************************************/
+-uint32_t
++u32
+ e1000_hash_mc_addr(struct e1000_hw *hw,
+- uint8_t *mc_addr)
++ u8 *mc_addr)
+ {
+- uint32_t hash_value = 0;
++ u32 hash_value = 0;
+
+ /* The portion of the address that is used for the hash table is
+ * determined by the mc_filter_type setting.
+@@ -5788,37 +5787,37 @@ e1000_hash_mc_addr(struct e1000_hw *hw,
+ case 0:
+ if (hw->mac_type == e1000_ich8lan) {
+ /* [47:38] i.e. 0x158 for above example address */
+- hash_value = ((mc_addr[4] >> 6) | (((uint16_t) mc_addr[5]) << 2));
++ hash_value = ((mc_addr[4] >> 6) | (((u16) mc_addr[5]) << 2));
+ } else {
+ /* [47:36] i.e. 0x563 for above example address */
+- hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));
++ hash_value = ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
+ }
+ break;
+ case 1:
+ if (hw->mac_type == e1000_ich8lan) {
+ /* [46:37] i.e. 0x2B1 for above example address */
+- hash_value = ((mc_addr[4] >> 5) | (((uint16_t) mc_addr[5]) << 3));
++ hash_value = ((mc_addr[4] >> 5) | (((u16) mc_addr[5]) << 3));
+ } else {
+ /* [46:35] i.e. 0xAC6 for above example address */
+- hash_value = ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5));
++ hash_value = ((mc_addr[4] >> 3) | (((u16) mc_addr[5]) << 5));
+ }
+ break;
+ case 2:
+ if (hw->mac_type == e1000_ich8lan) {
+ /*[45:36] i.e. 0x163 for above example address */
+- hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));
++ hash_value = ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
+ } else {
+ /* [45:34] i.e. 0x5D8 for above example address */
+- hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
++ hash_value = ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
+ }
+ break;
+ case 3:
+ if (hw->mac_type == e1000_ich8lan) {
+ /* [43:34] i.e. 0x18D for above example address */
+- hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
++ hash_value = ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
+ } else {
+ /* [43:32] i.e. 0x634 for above example address */
+- hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8));
++ hash_value = ((mc_addr[4]) | (((u16) mc_addr[5]) << 8));
+ }
+ break;
+ }
+@@ -5838,11 +5837,11 @@ e1000_hash_mc_addr(struct e1000_hw *hw,
+ *****************************************************************************/
+ void
+ e1000_mta_set(struct e1000_hw *hw,
+- uint32_t hash_value)
++ u32 hash_value)
+ {
+- uint32_t hash_bit, hash_reg;
+- uint32_t mta;
+- uint32_t temp;
++ u32 hash_bit, hash_reg;
++ u32 mta;
++ u32 temp;
+
+ /* The MTA is a register array of 128 32-bit registers.
+ * It is treated like an array of 4096 bits. We want to set
+@@ -5887,18 +5886,18 @@ e1000_mta_set(struct e1000_hw *hw,
+ *****************************************************************************/
+ void
+ e1000_rar_set(struct e1000_hw *hw,
+- uint8_t *addr,
+- uint32_t index)
++ u8 *addr,
++ u32 index)
+ {
+- uint32_t rar_low, rar_high;
++ u32 rar_low, rar_high;
+
+ /* HW expects these in little endian so we reverse the byte order
+ * from network order (big endian) to little endian
+ */
+- rar_low = ((uint32_t) addr[0] |
+- ((uint32_t) addr[1] << 8) |
+- ((uint32_t) addr[2] << 16) | ((uint32_t) addr[3] << 24));
+- rar_high = ((uint32_t) addr[4] | ((uint32_t) addr[5] << 8));
++ rar_low = ((u32) addr[0] |
++ ((u32) addr[1] << 8) |
++ ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
++ rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
+
+ /* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx
+ * unit hang.
+@@ -5922,7 +5921,7 @@ e1000_rar_set(struct e1000_hw *hw,
+ case e1000_82571:
+ case e1000_82572:
+ case e1000_80003es2lan:
+- if (hw->leave_av_bit_off == TRUE)
++ if (hw->leave_av_bit_off)
+ break;
+ default:
+ /* Indicate to hardware the Address is Valid. */
+@@ -5945,10 +5944,10 @@ e1000_rar_set(struct e1000_hw *hw,
+ *****************************************************************************/
+ void
+ e1000_write_vfta(struct e1000_hw *hw,
+- uint32_t offset,
+- uint32_t value)
++ u32 offset,
++ u32 value)
+ {
+- uint32_t temp;
++ u32 temp;
+
+ if (hw->mac_type == e1000_ich8lan)
+ return;
+@@ -5973,10 +5972,10 @@ e1000_write_vfta(struct e1000_hw *hw,
+ static void
+ e1000_clear_vfta(struct e1000_hw *hw)
+ {
+- uint32_t offset;
+- uint32_t vfta_value = 0;
+- uint32_t vfta_offset = 0;
+- uint32_t vfta_bit_in_reg = 0;
++ u32 offset;
++ u32 vfta_value = 0;
++ u32 vfta_offset = 0;
++ u32 vfta_bit_in_reg = 0;
+
+ if (hw->mac_type == e1000_ich8lan)
+ return;
+@@ -6004,15 +6003,15 @@ e1000_clear_vfta(struct e1000_hw *hw)
+ }
+ }
+
+-static int32_t
++static s32
+ e1000_id_led_init(struct e1000_hw * hw)
+ {
+- uint32_t ledctl;
+- const uint32_t ledctl_mask = 0x000000FF;
+- const uint32_t ledctl_on = E1000_LEDCTL_MODE_LED_ON;
+- const uint32_t ledctl_off = E1000_LEDCTL_MODE_LED_OFF;
+- uint16_t eeprom_data, i, temp;
+- const uint16_t led_mask = 0x0F;
++ u32 ledctl;
++ const u32 ledctl_mask = 0x000000FF;
++ const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON;
++ const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF;
++ u16 eeprom_data, i, temp;
++ const u16 led_mask = 0x0F;
+
+ DEBUGFUNC("e1000_id_led_init");
+
+@@ -6087,11 +6086,11 @@ e1000_id_led_init(struct e1000_hw * hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_setup_led(struct e1000_hw *hw)
+ {
+- uint32_t ledctl;
+- int32_t ret_val = E1000_SUCCESS;
++ u32 ledctl;
++ s32 ret_val = E1000_SUCCESS;
+
+ DEBUGFUNC("e1000_setup_led");
+
+@@ -6112,7 +6111,7 @@ e1000_setup_led(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
+- (uint16_t)(hw->phy_spd_default &
++ (u16)(hw->phy_spd_default &
+ ~IGP01E1000_GMII_SPD));
+ if (ret_val)
+ return ret_val;
+@@ -6146,11 +6145,11 @@ e1000_setup_led(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_blink_led_start(struct e1000_hw *hw)
+ {
+- int16_t i;
+- uint32_t ledctl_blink = 0;
++ s16 i;
++ u32 ledctl_blink = 0;
+
+ DEBUGFUNC("e1000_id_led_blink_on");
+
+@@ -6181,10 +6180,10 @@ e1000_blink_led_start(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_cleanup_led(struct e1000_hw *hw)
+ {
+- int32_t ret_val = E1000_SUCCESS;
++ s32 ret_val = E1000_SUCCESS;
+
+ DEBUGFUNC("e1000_cleanup_led");
+
+@@ -6223,10 +6222,10 @@ e1000_cleanup_led(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_led_on(struct e1000_hw *hw)
+ {
+- uint32_t ctrl = E1000_READ_REG(hw, CTRL);
++ u32 ctrl = E1000_READ_REG(hw, CTRL);
+
+ DEBUGFUNC("e1000_led_on");
+
+@@ -6274,10 +6273,10 @@ e1000_led_on(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_led_off(struct e1000_hw *hw)
+ {
+- uint32_t ctrl = E1000_READ_REG(hw, CTRL);
++ u32 ctrl = E1000_READ_REG(hw, CTRL);
+
+ DEBUGFUNC("e1000_led_off");
+
+@@ -6328,7 +6327,7 @@ e1000_led_off(struct e1000_hw *hw)
+ static void
+ e1000_clear_hw_cntrs(struct e1000_hw *hw)
+ {
+- volatile uint32_t temp;
++ volatile u32 temp;
+
+ temp = E1000_READ_REG(hw, CRCERRS);
+ temp = E1000_READ_REG(hw, SYMERRS);
+@@ -6425,7 +6424,7 @@ e1000_clear_hw_cntrs(struct e1000_hw *hw)
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Call this after e1000_init_hw. You may override the IFS defaults by setting
+- * hw->ifs_params_forced to TRUE. However, you must initialize hw->
++ * hw->ifs_params_forced to true. However, you must initialize hw->
+ * current_ifs_val, ifs_min_val, ifs_max_val, ifs_step_size, and ifs_ratio
+ * before calling this function.
+ *****************************************************************************/
+@@ -6442,7 +6441,7 @@ e1000_reset_adaptive(struct e1000_hw *hw)
+ hw->ifs_step_size = IFS_STEP;
+ hw->ifs_ratio = IFS_RATIO;
+ }
+- hw->in_ifs_mode = FALSE;
++ hw->in_ifs_mode = false;
+ E1000_WRITE_REG(hw, AIT, 0);
+ } else {
+ DEBUGOUT("Not in Adaptive IFS mode!\n");
+@@ -6465,7 +6464,7 @@ e1000_update_adaptive(struct e1000_hw *hw)
+ if (hw->adaptive_ifs) {
+ if ((hw->collision_delta * hw->ifs_ratio) > hw->tx_packet_delta) {
+ if (hw->tx_packet_delta > MIN_NUM_XMITS) {
+- hw->in_ifs_mode = TRUE;
++ hw->in_ifs_mode = true;
+ if (hw->current_ifs_val < hw->ifs_max_val) {
+ if (hw->current_ifs_val == 0)
+ hw->current_ifs_val = hw->ifs_min_val;
+@@ -6477,7 +6476,7 @@ e1000_update_adaptive(struct e1000_hw *hw)
+ } else {
+ if (hw->in_ifs_mode && (hw->tx_packet_delta <= MIN_NUM_XMITS)) {
+ hw->current_ifs_val = 0;
+- hw->in_ifs_mode = FALSE;
++ hw->in_ifs_mode = false;
+ E1000_WRITE_REG(hw, AIT, 0);
+ }
+ }
+@@ -6496,10 +6495,10 @@ e1000_update_adaptive(struct e1000_hw *hw)
+ void
+ e1000_tbi_adjust_stats(struct e1000_hw *hw,
+ struct e1000_hw_stats *stats,
+- uint32_t frame_len,
+- uint8_t *mac_addr)
++ u32 frame_len,
++ u8 *mac_addr)
+ {
+- uint64_t carry_bit;
++ u64 carry_bit;
+
+ /* First adjust the frame length. */
+ frame_len--;
+@@ -6528,7 +6527,7 @@ e1000_tbi_adjust_stats(struct e1000_hw *hw,
+ * since the test for a multicast frame will test positive on
+ * a broadcast frame.
+ */
+- if ((mac_addr[0] == (uint8_t) 0xff) && (mac_addr[1] == (uint8_t) 0xff))
++ if ((mac_addr[0] == (u8) 0xff) && (mac_addr[1] == (u8) 0xff))
+ /* Broadcast packet */
+ stats->bprc++;
+ else if (*mac_addr & 0x01)
+@@ -6574,9 +6573,9 @@ e1000_tbi_adjust_stats(struct e1000_hw *hw,
+ void
+ e1000_get_bus_info(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t pci_ex_link_status;
+- uint32_t status;
++ s32 ret_val;
++ u16 pci_ex_link_status;
++ u32 status;
+
+ switch (hw->mac_type) {
+ case e1000_82542_rev2_0:
+@@ -6648,8 +6647,8 @@ e1000_get_bus_info(struct e1000_hw *hw)
+ *****************************************************************************/
+ static void
+ e1000_write_reg_io(struct e1000_hw *hw,
+- uint32_t offset,
+- uint32_t value)
++ u32 offset,
++ u32 value)
+ {
+ unsigned long io_addr = hw->io_base;
+ unsigned long io_data = hw->io_base + 4;
+@@ -6673,15 +6672,15 @@ e1000_write_reg_io(struct e1000_hw *hw,
+ * register to the minimum and maximum range.
+ * For IGP phy's, the function calculates the range by the AGC registers.
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_get_cable_length(struct e1000_hw *hw,
+- uint16_t *min_length,
+- uint16_t *max_length)
++ u16 *min_length,
++ u16 *max_length)
+ {
+- int32_t ret_val;
+- uint16_t agc_value = 0;
+- uint16_t i, phy_data;
+- uint16_t cable_length;
++ s32 ret_val;
++ u16 agc_value = 0;
++ u16 i, phy_data;
++ u16 cable_length;
+
+ DEBUGFUNC("e1000_get_cable_length");
+
+@@ -6752,9 +6751,9 @@ e1000_get_cable_length(struct e1000_hw *hw,
+ break;
+ }
+ } else if (hw->phy_type == e1000_phy_igp) { /* For IGP PHY */
+- uint16_t cur_agc_value;
+- uint16_t min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
+- uint16_t agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
++ u16 cur_agc_value;
++ u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
++ u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
+ {IGP01E1000_PHY_AGC_A,
+ IGP01E1000_PHY_AGC_B,
+ IGP01E1000_PHY_AGC_C,
+@@ -6800,9 +6799,9 @@ e1000_get_cable_length(struct e1000_hw *hw,
+ IGP01E1000_AGC_RANGE;
+ } else if (hw->phy_type == e1000_phy_igp_2 ||
+ hw->phy_type == e1000_phy_igp_3) {
+- uint16_t cur_agc_index, max_agc_index = 0;
+- uint16_t min_agc_index = IGP02E1000_AGC_LENGTH_TABLE_SIZE - 1;
+- uint16_t agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
++ u16 cur_agc_index, max_agc_index = 0;
++ u16 min_agc_index = IGP02E1000_AGC_LENGTH_TABLE_SIZE - 1;
++ u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
+ {IGP02E1000_PHY_AGC_A,
+ IGP02E1000_PHY_AGC_B,
+ IGP02E1000_PHY_AGC_C,
+@@ -6864,12 +6863,12 @@ e1000_get_cable_length(struct e1000_hw *hw,
+ * return 0. If the link speed is 1000 Mbps the polarity status is in the
+ * IGP01E1000_PHY_PCS_INIT_REG.
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_check_polarity(struct e1000_hw *hw,
+ e1000_rev_polarity *polarity)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_check_polarity");
+
+@@ -6940,11 +6939,11 @@ e1000_check_polarity(struct e1000_hw *hw,
+ * Link Health register. In IGP this bit is latched high, so the driver must
+ * read it immediately after link is established.
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_check_downshift(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_check_downshift");
+
+@@ -6968,7 +6967,7 @@ e1000_check_downshift(struct e1000_hw *hw)
+ M88E1000_PSSR_DOWNSHIFT_SHIFT;
+ } else if (hw->phy_type == e1000_phy_ife) {
+ /* e1000_phy_ife supports 10/100 speed only */
+- hw->speed_downgraded = FALSE;
++ hw->speed_downgraded = false;
+ }
+
+ return E1000_SUCCESS;
+@@ -6986,18 +6985,18 @@ e1000_check_downshift(struct e1000_hw *hw)
+ *
+ ****************************************************************************/
+
+-static int32_t
++static s32
+ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
+- boolean_t link_up)
++ bool link_up)
+ {
+- int32_t ret_val;
+- uint16_t phy_data, phy_saved_data, speed, duplex, i;
+- uint16_t dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
++ s32 ret_val;
++ u16 phy_data, phy_saved_data, speed, duplex, i;
++ u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
+ {IGP01E1000_PHY_AGC_PARAM_A,
+ IGP01E1000_PHY_AGC_PARAM_B,
+ IGP01E1000_PHY_AGC_PARAM_C,
+ IGP01E1000_PHY_AGC_PARAM_D};
+- uint16_t min_length, max_length;
++ u16 min_length, max_length;
+
+ DEBUGFUNC("e1000_config_dsp_after_link_change");
+
+@@ -7039,8 +7038,8 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
+ if ((hw->ffe_config_state == e1000_ffe_config_enabled) &&
+ (min_length < e1000_igp_cable_length_50)) {
+
+- uint16_t ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
+- uint32_t idle_errs = 0;
++ u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
++ u32 idle_errs = 0;
+
+ /* clear previous idle error counts */
+ ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS,
+@@ -7174,11 +7173,11 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
+ *
+ * hw - Struct containing variables accessed by shared code
+ ****************************************************************************/
+-static int32_t
++static s32
+ e1000_set_phy_mode(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t eeprom_data;
++ s32 ret_val;
++ u16 eeprom_data;
+
+ DEBUGFUNC("e1000_set_phy_mode");
+
+@@ -7198,7 +7197,7 @@ e1000_set_phy_mode(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+
+- hw->phy_reset_disable = FALSE;
++ hw->phy_reset_disable = false;
+ }
+ }
+
+@@ -7219,13 +7218,13 @@ e1000_set_phy_mode(struct e1000_hw *hw)
+ *
+ ****************************************************************************/
+
+-static int32_t
++static s32
+ e1000_set_d3_lplu_state(struct e1000_hw *hw,
+- boolean_t active)
++ bool active)
+ {
+- uint32_t phy_ctrl = 0;
+- int32_t ret_val;
+- uint16_t phy_data;
++ u32 phy_ctrl = 0;
++ s32 ret_val;
++ u16 phy_data;
+ DEBUGFUNC("e1000_set_d3_lplu_state");
+
+ if (hw->phy_type != e1000_phy_igp && hw->phy_type != e1000_phy_igp_2
+@@ -7349,13 +7348,13 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw,
+ *
+ ****************************************************************************/
+
+-static int32_t
++static s32
+ e1000_set_d0_lplu_state(struct e1000_hw *hw,
+- boolean_t active)
++ bool active)
+ {
+- uint32_t phy_ctrl = 0;
+- int32_t ret_val;
+- uint16_t phy_data;
++ u32 phy_ctrl = 0;
++ s32 ret_val;
++ u16 phy_data;
+ DEBUGFUNC("e1000_set_d0_lplu_state");
+
+ if (hw->mac_type <= e1000_82547_rev_2)
+@@ -7440,12 +7439,12 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw,
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_set_vco_speed(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t default_page = 0;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 default_page = 0;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_set_vco_speed");
+
+@@ -7504,18 +7503,18 @@ e1000_set_vco_speed(struct e1000_hw *hw)
+ *
+ * returns: - E1000_SUCCESS .
+ ****************************************************************************/
+-static int32_t
+-e1000_host_if_read_cookie(struct e1000_hw * hw, uint8_t *buffer)
++static s32
++e1000_host_if_read_cookie(struct e1000_hw * hw, u8 *buffer)
+ {
+- uint8_t i;
+- uint32_t offset = E1000_MNG_DHCP_COOKIE_OFFSET;
+- uint8_t length = E1000_MNG_DHCP_COOKIE_LENGTH;
++ u8 i;
++ u32 offset = E1000_MNG_DHCP_COOKIE_OFFSET;
++ u8 length = E1000_MNG_DHCP_COOKIE_LENGTH;
+
+ length = (length >> 2);
+ offset = (offset >> 2);
+
+ for (i = 0; i < length; i++) {
+- *((uint32_t *) buffer + i) =
++ *((u32 *) buffer + i) =
+ E1000_READ_REG_ARRAY_DWORD(hw, HOST_IF, offset + i);
+ }
+ return E1000_SUCCESS;
+@@ -7531,11 +7530,11 @@ e1000_host_if_read_cookie(struct e1000_hw * hw, uint8_t *buffer)
+ * timeout
+ * - E1000_SUCCESS for success.
+ ****************************************************************************/
+-static int32_t
++static s32
+ e1000_mng_enable_host_if(struct e1000_hw * hw)
+ {
+- uint32_t hicr;
+- uint8_t i;
++ u32 hicr;
++ u8 i;
+
+ /* Check that the host interface is enabled. */
+ hicr = E1000_READ_REG(hw, HICR);
+@@ -7565,14 +7564,14 @@ e1000_mng_enable_host_if(struct e1000_hw * hw)
+ *
+ * returns - E1000_SUCCESS for success.
+ ****************************************************************************/
+-static int32_t
+-e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
+- uint16_t length, uint16_t offset, uint8_t *sum)
++static s32
++e1000_mng_host_if_write(struct e1000_hw * hw, u8 *buffer,
++ u16 length, u16 offset, u8 *sum)
+ {
+- uint8_t *tmp;
+- uint8_t *bufptr = buffer;
+- uint32_t data = 0;
+- uint16_t remaining, i, j, prev_bytes;
++ u8 *tmp;
++ u8 *bufptr = buffer;
++ u32 data = 0;
++ u16 remaining, i, j, prev_bytes;
+
+ /* sum = only sum of the data and it is not checksum */
+
+@@ -7580,14 +7579,14 @@ e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
+ return -E1000_ERR_PARAM;
+ }
+
+- tmp = (uint8_t *)&data;
++ tmp = (u8 *)&data;
+ prev_bytes = offset & 0x3;
+ offset &= 0xFFFC;
+ offset >>= 2;
+
+ if (prev_bytes) {
+ data = E1000_READ_REG_ARRAY_DWORD(hw, HOST_IF, offset);
+- for (j = prev_bytes; j < sizeof(uint32_t); j++) {
++ for (j = prev_bytes; j < sizeof(u32); j++) {
+ *(tmp + j) = *bufptr++;
+ *sum += *(tmp + j);
+ }
+@@ -7605,7 +7604,7 @@ e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
+ /* The device driver writes the relevant command block into the
+ * ram area. */
+ for (i = 0; i < length; i++) {
+- for (j = 0; j < sizeof(uint32_t); j++) {
++ for (j = 0; j < sizeof(u32); j++) {
+ *(tmp + j) = *bufptr++;
+ *sum += *(tmp + j);
+ }
+@@ -7613,7 +7612,7 @@ e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
+ E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, offset + i, data);
+ }
+ if (remaining) {
+- for (j = 0; j < sizeof(uint32_t); j++) {
++ for (j = 0; j < sizeof(u32); j++) {
+ if (j < remaining)
+ *(tmp + j) = *bufptr++;
+ else
+@@ -7633,23 +7632,23 @@ e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
+ *
+ * returns - E1000_SUCCESS for success.
+ ****************************************************************************/
+-static int32_t
++static s32
+ e1000_mng_write_cmd_header(struct e1000_hw * hw,
+ struct e1000_host_mng_command_header * hdr)
+ {
+- uint16_t i;
+- uint8_t sum;
+- uint8_t *buffer;
++ u16 i;
++ u8 sum;
++ u8 *buffer;
+
+ /* Write the whole command header structure which includes sum of
+ * the buffer */
+
+- uint16_t length = sizeof(struct e1000_host_mng_command_header);
++ u16 length = sizeof(struct e1000_host_mng_command_header);
+
+ sum = hdr->checksum;
+ hdr->checksum = 0;
+
+- buffer = (uint8_t *) hdr;
++ buffer = (u8 *) hdr;
+ i = length;
+ while (i--)
+ sum += buffer[i];
+@@ -7659,7 +7658,7 @@ e1000_mng_write_cmd_header(struct e1000_hw * hw,
+ length >>= 2;
+ /* The device driver writes the relevant command block into the ram area. */
+ for (i = 0; i < length; i++) {
+- E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((uint32_t *) hdr + i));
++ E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((u32 *) hdr + i));
+ E1000_WRITE_FLUSH(hw);
+ }
+
+@@ -7673,10 +7672,10 @@ e1000_mng_write_cmd_header(struct e1000_hw * hw,
+ *
+ * returns - E1000_SUCCESS for success.
+ ****************************************************************************/
+-static int32_t
++static s32
+ e1000_mng_write_commit(struct e1000_hw * hw)
+ {
+- uint32_t hicr;
++ u32 hicr;
+
+ hicr = E1000_READ_REG(hw, HICR);
+ /* Setting this bit tells the ARC that a new command is pending. */
+@@ -7689,35 +7688,35 @@ e1000_mng_write_commit(struct e1000_hw * hw)
+ /*****************************************************************************
+ * This function checks the mode of the firmware.
+ *
+- * returns - TRUE when the mode is IAMT or FALSE.
++ * returns - true when the mode is IAMT or false.
+ ****************************************************************************/
+-boolean_t
++bool
+ e1000_check_mng_mode(struct e1000_hw *hw)
+ {
+- uint32_t fwsm;
++ u32 fwsm;
+
+ fwsm = E1000_READ_REG(hw, FWSM);
+
+ if (hw->mac_type == e1000_ich8lan) {
+ if ((fwsm & E1000_FWSM_MODE_MASK) ==
+ (E1000_MNG_ICH_IAMT_MODE << E1000_FWSM_MODE_SHIFT))
+- return TRUE;
++ return true;
+ } else if ((fwsm & E1000_FWSM_MODE_MASK) ==
+ (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT))
+- return TRUE;
++ return true;
+
+- return FALSE;
++ return false;
+ }
+
+
+ /*****************************************************************************
+ * This function writes the dhcp info .
+ ****************************************************************************/
+-int32_t
+-e1000_mng_write_dhcp_info(struct e1000_hw * hw, uint8_t *buffer,
+- uint16_t length)
++s32
++e1000_mng_write_dhcp_info(struct e1000_hw * hw, u8 *buffer,
++ u16 length)
+ {
+- int32_t ret_val;
++ s32 ret_val;
+ struct e1000_host_mng_command_header hdr;
+
+ hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
+@@ -7745,11 +7744,11 @@ e1000_mng_write_dhcp_info(struct e1000_hw * hw, uint8_t *buffer,
+ *
+ * returns - checksum of buffer contents.
+ ****************************************************************************/
+-static uint8_t
+-e1000_calculate_mng_checksum(char *buffer, uint32_t length)
++static u8
++e1000_calculate_mng_checksum(char *buffer, u32 length)
+ {
+- uint8_t sum = 0;
+- uint32_t i;
++ u8 sum = 0;
++ u32 i;
+
+ if (!buffer)
+ return 0;
+@@ -7757,23 +7756,23 @@ e1000_calculate_mng_checksum(char *buffer, uint32_t length)
+ for (i=0; i < length; i++)
+ sum += buffer[i];
+
+- return (uint8_t) (0 - sum);
++ return (u8) (0 - sum);
+ }
+
+ /*****************************************************************************
+ * This function checks whether tx pkt filtering needs to be enabled or not.
+ *
+- * returns - TRUE for packet filtering or FALSE.
++ * returns - true for packet filtering or false.
+ ****************************************************************************/
+-boolean_t
++bool
+ e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
+ {
+ /* called in init as well as watchdog timer functions */
+
+- int32_t ret_val, checksum;
+- boolean_t tx_filter = FALSE;
++ s32 ret_val, checksum;
++ bool tx_filter = false;
+ struct e1000_host_mng_dhcp_cookie *hdr = &(hw->mng_cookie);
+- uint8_t *buffer = (uint8_t *) &(hw->mng_cookie);
++ u8 *buffer = (u8 *) &(hw->mng_cookie);
+
+ if (e1000_check_mng_mode(hw)) {
+ ret_val = e1000_mng_enable_host_if(hw);
+@@ -7787,11 +7786,11 @@ e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
+ E1000_MNG_DHCP_COOKIE_LENGTH)) {
+ if (hdr->status &
+ E1000_MNG_DHCP_COOKIE_STATUS_PARSING_SUPPORT)
+- tx_filter = TRUE;
++ tx_filter = true;
+ } else
+- tx_filter = TRUE;
++ tx_filter = true;
+ } else
+- tx_filter = TRUE;
++ tx_filter = true;
+ }
+ }
+
+@@ -7804,41 +7803,41 @@ e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+- * returns: - TRUE/FALSE
++ * returns: - true/false
+ *
+ *****************************************************************************/
+-uint32_t
++u32
+ e1000_enable_mng_pass_thru(struct e1000_hw *hw)
+ {
+- uint32_t manc;
+- uint32_t fwsm, factps;
++ u32 manc;
++ u32 fwsm, factps;
+
+ if (hw->asf_firmware_present) {
+ manc = E1000_READ_REG(hw, MANC);
+
+ if (!(manc & E1000_MANC_RCV_TCO_EN) ||
+ !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
+- return FALSE;
+- if (e1000_arc_subsystem_valid(hw) == TRUE) {
++ return false;
++ if (e1000_arc_subsystem_valid(hw)) {
+ fwsm = E1000_READ_REG(hw, FWSM);
+ factps = E1000_READ_REG(hw, FACTPS);
+
+ if ((((fwsm & E1000_FWSM_MODE_MASK) >> E1000_FWSM_MODE_SHIFT) ==
+ e1000_mng_mode_pt) && !(factps & E1000_FACTPS_MNGCG))
+- return TRUE;
++ return true;
+ } else
+ if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN))
+- return TRUE;
++ return true;
+ }
+- return FALSE;
++ return false;
+ }
+
+-static int32_t
++static s32
+ e1000_polarity_reversal_workaround(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t mii_status_reg;
+- uint16_t i;
++ s32 ret_val;
++ u16 mii_status_reg;
++ u16 i;
+
+ /* Polarity reversal workaround for forced 10F/10H links. */
+
+@@ -7930,7 +7929,7 @@ e1000_polarity_reversal_workaround(struct e1000_hw *hw)
+ static void
+ e1000_set_pci_express_master_disable(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
++ u32 ctrl;
+
+ DEBUGFUNC("e1000_set_pci_express_master_disable");
+
+@@ -7953,10 +7952,10 @@ e1000_set_pci_express_master_disable(struct e1000_hw *hw)
+ * E1000_SUCCESS master requests disabled.
+ *
+ ******************************************************************************/
+-int32_t
++s32
+ e1000_disable_pciex_master(struct e1000_hw *hw)
+ {
+- int32_t timeout = MASTER_DISABLE_TIMEOUT; /* 80ms */
++ s32 timeout = MASTER_DISABLE_TIMEOUT; /* 80ms */
+
+ DEBUGFUNC("e1000_disable_pciex_master");
+
+@@ -7991,10 +7990,10 @@ e1000_disable_pciex_master(struct e1000_hw *hw)
+ * E1000_SUCCESS at any other case.
+ *
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_get_auto_rd_done(struct e1000_hw *hw)
+ {
+- int32_t timeout = AUTO_READ_DONE_TIMEOUT;
++ s32 timeout = AUTO_READ_DONE_TIMEOUT;
+
+ DEBUGFUNC("e1000_get_auto_rd_done");
+
+@@ -8039,11 +8038,11 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
+ * E1000_SUCCESS at any other case.
+ *
+ ***************************************************************************/
+-static int32_t
++static s32
+ e1000_get_phy_cfg_done(struct e1000_hw *hw)
+ {
+- int32_t timeout = PHY_CFG_TIMEOUT;
+- uint32_t cfg_mask = E1000_EEPROM_CFG_DONE;
++ s32 timeout = PHY_CFG_TIMEOUT;
++ u32 cfg_mask = E1000_EEPROM_CFG_DONE;
+
+ DEBUGFUNC("e1000_get_phy_cfg_done");
+
+@@ -8086,11 +8085,11 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
+ * E1000_SUCCESS at any other case.
+ *
+ ***************************************************************************/
+-static int32_t
++static s32
+ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
+ {
+- int32_t timeout;
+- uint32_t swsm;
++ s32 timeout;
++ u32 swsm;
+
+ DEBUGFUNC("e1000_get_hw_eeprom_semaphore");
+
+@@ -8139,7 +8138,7 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
+ static void
+ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
+ {
+- uint32_t swsm;
++ u32 swsm;
+
+ DEBUGFUNC("e1000_put_hw_eeprom_semaphore");
+
+@@ -8165,11 +8164,11 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
+ * E1000_SUCCESS at any other case.
+ *
+ ***************************************************************************/
+-static int32_t
++static s32
+ e1000_get_software_semaphore(struct e1000_hw *hw)
+ {
+- int32_t timeout = hw->eeprom.word_size + 1;
+- uint32_t swsm;
++ s32 timeout = hw->eeprom.word_size + 1;
++ u32 swsm;
+
+ DEBUGFUNC("e1000_get_software_semaphore");
+
+@@ -8204,7 +8203,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
+ static void
+ e1000_release_software_semaphore(struct e1000_hw *hw)
+ {
+- uint32_t swsm;
++ u32 swsm;
+
+ DEBUGFUNC("e1000_release_software_semaphore");
+
+@@ -8229,11 +8228,11 @@ e1000_release_software_semaphore(struct e1000_hw *hw)
+ * E1000_SUCCESS
+ *
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_check_phy_reset_block(struct e1000_hw *hw)
+ {
+- uint32_t manc = 0;
+- uint32_t fwsm = 0;
++ u32 manc = 0;
++ u32 fwsm = 0;
+
+ if (hw->mac_type == e1000_ich8lan) {
+ fwsm = E1000_READ_REG(hw, FWSM);
+@@ -8247,10 +8246,10 @@ e1000_check_phy_reset_block(struct e1000_hw *hw)
+ E1000_BLK_PHY_RESET : E1000_SUCCESS;
+ }
+
+-static uint8_t
++static u8
+ e1000_arc_subsystem_valid(struct e1000_hw *hw)
+ {
+- uint32_t fwsm;
++ u32 fwsm;
+
+ /* On 8257x silicon, registers in the range of 0x8800 - 0x8FFC
+ * may not be provided a DMA clock when no manageability features are
+@@ -8264,14 +8263,14 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
+ case e1000_80003es2lan:
+ fwsm = E1000_READ_REG(hw, FWSM);
+ if ((fwsm & E1000_FWSM_MODE_MASK) != 0)
+- return TRUE;
++ return true;
+ break;
+ case e1000_ich8lan:
+- return TRUE;
++ return true;
+ default:
+ break;
+ }
+- return FALSE;
++ return false;
+ }
+
+
+@@ -8284,10 +8283,10 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
+ * returns: E1000_SUCCESS
+ *
+ *****************************************************************************/
+-static int32_t
+-e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop)
++static s32
++e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop)
+ {
+- uint32_t gcr_reg = 0;
++ u32 gcr_reg = 0;
+
+ DEBUGFUNC("e1000_set_pci_ex_no_snoop");
+
+@@ -8304,7 +8303,7 @@ e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop)
+ E1000_WRITE_REG(hw, GCR, gcr_reg);
+ }
+ if (hw->mac_type == e1000_ich8lan) {
+- uint32_t ctrl_ext;
++ u32 ctrl_ext;
+
+ E1000_WRITE_REG(hw, GCR, PCI_EX_82566_SNOOP_ALL);
+
+@@ -8325,11 +8324,11 @@ e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop)
+ * hw: Struct containing variables accessed by shared code
+ *
+ ***************************************************************************/
+-static int32_t
++static s32
+ e1000_get_software_flag(struct e1000_hw *hw)
+ {
+- int32_t timeout = PHY_CFG_TIMEOUT;
+- uint32_t extcnf_ctrl;
++ s32 timeout = PHY_CFG_TIMEOUT;
++ u32 extcnf_ctrl;
+
+ DEBUGFUNC("e1000_get_software_flag");
+
+@@ -8367,7 +8366,7 @@ e1000_get_software_flag(struct e1000_hw *hw)
+ static void
+ e1000_release_software_flag(struct e1000_hw *hw)
+ {
+- uint32_t extcnf_ctrl;
++ u32 extcnf_ctrl;
+
+ DEBUGFUNC("e1000_release_software_flag");
+
+@@ -8389,16 +8388,16 @@ e1000_release_software_flag(struct e1000_hw *hw)
+ * data - word read from the EEPROM
+ * words - number of words to read
+ *****************************************************************************/
+-static int32_t
+-e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+- uint16_t *data)
++static s32
++e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
++ u16 *data)
+ {
+- int32_t error = E1000_SUCCESS;
+- uint32_t flash_bank = 0;
+- uint32_t act_offset = 0;
+- uint32_t bank_offset = 0;
+- uint16_t word = 0;
+- uint16_t i = 0;
++ s32 error = E1000_SUCCESS;
++ u32 flash_bank = 0;
++ u32 act_offset = 0;
++ u32 bank_offset = 0;
++ u16 word = 0;
++ u16 i = 0;
+
+ /* We need to know which is the valid flash bank. In the event
+ * that we didn't allocate eeprom_shadow_ram, we may not be
+@@ -8417,7 +8416,7 @@ e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+
+ for (i = 0; i < words; i++) {
+ if (hw->eeprom_shadow_ram != NULL &&
+- hw->eeprom_shadow_ram[offset+i].modified == TRUE) {
++ hw->eeprom_shadow_ram[offset+i].modified) {
+ data[i] = hw->eeprom_shadow_ram[offset+i].eeprom_word;
+ } else {
+ /* The NVM part needs a byte offset, hence * 2 */
+@@ -8445,12 +8444,12 @@ e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+ * words - number of words to write
+ * data - words to write to the EEPROM
+ *****************************************************************************/
+-static int32_t
+-e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+- uint16_t *data)
++static s32
++e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
++ u16 *data)
+ {
+- uint32_t i = 0;
+- int32_t error = E1000_SUCCESS;
++ u32 i = 0;
++ s32 error = E1000_SUCCESS;
+
+ error = e1000_get_software_flag(hw);
+ if (error != E1000_SUCCESS)
+@@ -8466,7 +8465,7 @@ e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+ if (hw->eeprom_shadow_ram != NULL) {
+ for (i = 0; i < words; i++) {
+ if ((offset + i) < E1000_SHADOW_RAM_WORDS) {
+- hw->eeprom_shadow_ram[offset+i].modified = TRUE;
++ hw->eeprom_shadow_ram[offset+i].modified = true;
+ hw->eeprom_shadow_ram[offset+i].eeprom_word = data[i];
+ } else {
+ error = -E1000_ERR_EEPROM;
+@@ -8492,12 +8491,12 @@ e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+ *
+ * hw - The pointer to the hw structure
+ ****************************************************************************/
+-static int32_t
++static s32
+ e1000_ich8_cycle_init(struct e1000_hw *hw)
+ {
+ union ich8_hws_flash_status hsfsts;
+- int32_t error = E1000_ERR_EEPROM;
+- int32_t i = 0;
++ s32 error = E1000_ERR_EEPROM;
++ s32 i = 0;
+
+ DEBUGFUNC("e1000_ich8_cycle_init");
+
+@@ -8559,13 +8558,13 @@ e1000_ich8_cycle_init(struct e1000_hw *hw)
+ *
+ * hw - The pointer to the hw structure
+ ****************************************************************************/
+-static int32_t
+-e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout)
++static s32
++e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout)
+ {
+ union ich8_hws_flash_ctrl hsflctl;
+ union ich8_hws_flash_status hsfsts;
+- int32_t error = E1000_ERR_EEPROM;
+- uint32_t i = 0;
++ s32 error = E1000_ERR_EEPROM;
++ u32 i = 0;
+
+ /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
+ hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
+@@ -8594,16 +8593,16 @@ e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout)
+ * size - Size of data to read, 1=byte 2=word
+ * data - Pointer to the word to store the value read.
+ *****************************************************************************/
+-static int32_t
+-e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
+- uint32_t size, uint16_t* data)
++static s32
++e1000_read_ich8_data(struct e1000_hw *hw, u32 index,
++ u32 size, u16* data)
+ {
+ union ich8_hws_flash_status hsfsts;
+ union ich8_hws_flash_ctrl hsflctl;
+- uint32_t flash_linear_address;
+- uint32_t flash_data = 0;
+- int32_t error = -E1000_ERR_EEPROM;
+- int32_t count = 0;
++ u32 flash_linear_address;
++ u32 flash_data = 0;
++ s32 error = -E1000_ERR_EEPROM;
++ s32 count = 0;
+
+ DEBUGFUNC("e1000_read_ich8_data");
+
+@@ -8641,9 +8640,9 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
+ if (error == E1000_SUCCESS) {
+ flash_data = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_FDATA0);
+ if (size == 1) {
+- *data = (uint8_t)(flash_data & 0x000000FF);
++ *data = (u8)(flash_data & 0x000000FF);
+ } else if (size == 2) {
+- *data = (uint16_t)(flash_data & 0x0000FFFF);
++ *data = (u16)(flash_data & 0x0000FFFF);
+ }
+ break;
+ } else {
+@@ -8673,16 +8672,16 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
+ * size - Size of data to read, 1=byte 2=word
+ * data - The byte(s) to write to the NVM.
+ *****************************************************************************/
+-static int32_t
+-e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
+- uint16_t data)
++static s32
++e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
++ u16 data)
+ {
+ union ich8_hws_flash_status hsfsts;
+ union ich8_hws_flash_ctrl hsflctl;
+- uint32_t flash_linear_address;
+- uint32_t flash_data = 0;
+- int32_t error = -E1000_ERR_EEPROM;
+- int32_t count = 0;
++ u32 flash_linear_address;
++ u32 flash_data = 0;
++ s32 error = -E1000_ERR_EEPROM;
++ s32 count = 0;
+
+ DEBUGFUNC("e1000_write_ich8_data");
+
+@@ -8711,9 +8710,9 @@ e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
+ E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_address);
+
+ if (size == 1)
+- flash_data = (uint32_t)data & 0x00FF;
++ flash_data = (u32)data & 0x00FF;
+ else
+- flash_data = (uint32_t)data;
++ flash_data = (u32)data;
+
+ E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data);
+
+@@ -8748,15 +8747,15 @@ e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
+ * index - The index of the byte to read.
+ * data - Pointer to a byte to store the value read.
+ *****************************************************************************/
+-static int32_t
+-e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t* data)
++static s32
++e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8* data)
+ {
+- int32_t status = E1000_SUCCESS;
+- uint16_t word = 0;
++ s32 status = E1000_SUCCESS;
++ u16 word = 0;
+
+ status = e1000_read_ich8_data(hw, index, 1, &word);
+ if (status == E1000_SUCCESS) {
+- *data = (uint8_t)word;
++ *data = (u8)word;
+ }
+
+ return status;
+@@ -8771,11 +8770,11 @@ e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t* data)
+ * index - The index of the byte to write.
+ * byte - The byte to write to the NVM.
+ *****************************************************************************/
+-static int32_t
+-e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte)
++static s32
++e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte)
+ {
+- int32_t error = E1000_SUCCESS;
+- int32_t program_retries = 0;
++ s32 error = E1000_SUCCESS;
++ s32 program_retries = 0;
+
+ DEBUGOUT2("Byte := %2.2X Offset := %d\n", byte, index);
+
+@@ -8804,11 +8803,11 @@ e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte)
+ * index - The index of the byte to read.
+ * data - The byte to write to the NVM.
+ *****************************************************************************/
+-static int32_t
+-e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t data)
++static s32
++e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 data)
+ {
+- int32_t status = E1000_SUCCESS;
+- uint16_t word = (uint16_t)data;
++ s32 status = E1000_SUCCESS;
++ u16 word = (u16)data;
+
+ status = e1000_write_ich8_data(hw, index, 1, word);
+
+@@ -8822,10 +8821,10 @@ e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t data)
+ * index - The starting byte index of the word to read.
+ * data - Pointer to a word to store the value read.
+ *****************************************************************************/
+-static int32_t
+-e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data)
++static s32
++e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data)
+ {
+- int32_t status = E1000_SUCCESS;
++ s32 status = E1000_SUCCESS;
+ status = e1000_read_ich8_data(hw, index, 2, data);
+ return status;
+ }
+@@ -8841,19 +8840,19 @@ e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data)
+ * amount of NVM used in each bank is a *minimum* of 4 KBytes, but in fact the
+ * bank size may be 4, 8 or 64 KBytes
+ *****************************************************************************/
+-static int32_t
+-e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank)
++static s32
++e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank)
+ {
+ union ich8_hws_flash_status hsfsts;
+ union ich8_hws_flash_ctrl hsflctl;
+- uint32_t flash_linear_address;
+- int32_t count = 0;
+- int32_t error = E1000_ERR_EEPROM;
+- int32_t iteration;
+- int32_t sub_sector_size = 0;
+- int32_t bank_size;
+- int32_t j = 0;
+- int32_t error_flag = 0;
++ u32 flash_linear_address;
++ s32 count = 0;
++ s32 error = E1000_ERR_EEPROM;
++ s32 iteration;
++ s32 sub_sector_size = 0;
++ s32 bank_size;
++ s32 j = 0;
++ s32 error_flag = 0;
+
+ hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
+
+@@ -8931,16 +8930,16 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank)
+ return error;
+ }
+
+-static int32_t
++static s32
+ e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
+- uint32_t cnf_base_addr, uint32_t cnf_size)
++ u32 cnf_base_addr, u32 cnf_size)
+ {
+- uint32_t ret_val = E1000_SUCCESS;
+- uint16_t word_addr, reg_data, reg_addr;
+- uint16_t i;
++ u32 ret_val = E1000_SUCCESS;
++ u16 word_addr, reg_data, reg_addr;
++ u16 i;
+
+ /* cnf_base_addr is in DWORD */
+- word_addr = (uint16_t)(cnf_base_addr << 1);
++ word_addr = (u16)(cnf_base_addr << 1);
+
+ /* cnf_size is returned in size of dwords */
+ for (i = 0; i < cnf_size; i++) {
+@@ -8956,7 +8955,7 @@ e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
+ if (ret_val != E1000_SUCCESS)
+ return ret_val;
+
+- ret_val = e1000_write_phy_reg_ex(hw, (uint32_t)reg_addr, reg_data);
++ ret_val = e1000_write_phy_reg_ex(hw, (u32)reg_addr, reg_data);
+
+ e1000_release_software_flag(hw);
+ }
+@@ -8973,10 +8972,10 @@ e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
+ *
+ * hw: Struct containing variables accessed by shared code
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_init_lcd_from_nvm(struct e1000_hw *hw)
+ {
+- uint32_t reg_data, cnf_base_addr, cnf_size, ret_val, loop;
++ u32 reg_data, cnf_base_addr, cnf_size, ret_val, loop;
+
+ if (hw->phy_type != e1000_phy_igp_3)
+ return E1000_SUCCESS;
+diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
+index a6c3c34..99fce2c 100644
+--- a/drivers/net/e1000/e1000_hw.h
++++ b/drivers/net/e1000/e1000_hw.h
+@@ -100,8 +100,8 @@ typedef enum {
+ } e1000_fc_type;
+
+ struct e1000_shadow_ram {
+- uint16_t eeprom_word;
+- boolean_t modified;
++ u16 eeprom_word;
++ bool modified;
+ };
+
+ /* PCI bus types */
+@@ -263,19 +263,19 @@ struct e1000_phy_info {
+ };
+
+ struct e1000_phy_stats {
+- uint32_t idle_errors;
+- uint32_t receive_errors;
++ u32 idle_errors;
++ u32 receive_errors;
+ };
+
+ struct e1000_eeprom_info {
+ e1000_eeprom_type type;
+- uint16_t word_size;
+- uint16_t opcode_bits;
+- uint16_t address_bits;
+- uint16_t delay_usec;
+- uint16_t page_size;
+- boolean_t use_eerd;
+- boolean_t use_eewr;
++ u16 word_size;
++ u16 opcode_bits;
++ u16 address_bits;
++ u16 delay_usec;
++ u16 page_size;
++ bool use_eerd;
++ bool use_eewr;
+ };
+
+ /* Flex ASF Information */
+@@ -308,34 +308,34 @@ typedef enum {
+
+ /* Function prototypes */
+ /* Initialization */
+-int32_t e1000_reset_hw(struct e1000_hw *hw);
+-int32_t e1000_init_hw(struct e1000_hw *hw);
+-int32_t e1000_set_mac_type(struct e1000_hw *hw);
++s32 e1000_reset_hw(struct e1000_hw *hw);
++s32 e1000_init_hw(struct e1000_hw *hw);
++s32 e1000_set_mac_type(struct e1000_hw *hw);
+ void e1000_set_media_type(struct e1000_hw *hw);
+
+ /* Link Configuration */
+-int32_t e1000_setup_link(struct e1000_hw *hw);
+-int32_t e1000_phy_setup_autoneg(struct e1000_hw *hw);
++s32 e1000_setup_link(struct e1000_hw *hw);
++s32 e1000_phy_setup_autoneg(struct e1000_hw *hw);
+ void e1000_config_collision_dist(struct e1000_hw *hw);
+-int32_t e1000_check_for_link(struct e1000_hw *hw);
+-int32_t e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t *speed, uint16_t *duplex);
+-int32_t e1000_force_mac_fc(struct e1000_hw *hw);
++s32 e1000_check_for_link(struct e1000_hw *hw);
++s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex);
++s32 e1000_force_mac_fc(struct e1000_hw *hw);
+
+ /* PHY */
+-int32_t e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy_data);
+-int32_t e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data);
+-int32_t e1000_phy_hw_reset(struct e1000_hw *hw);
+-int32_t e1000_phy_reset(struct e1000_hw *hw);
+-int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
+-int32_t e1000_validate_mdi_setting(struct e1000_hw *hw);
++s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data);
++s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 data);
++s32 e1000_phy_hw_reset(struct e1000_hw *hw);
++s32 e1000_phy_reset(struct e1000_hw *hw);
++s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
++s32 e1000_validate_mdi_setting(struct e1000_hw *hw);
+
+ void e1000_phy_powerdown_workaround(struct e1000_hw *hw);
+
+ /* EEPROM Functions */
+-int32_t e1000_init_eeprom_params(struct e1000_hw *hw);
++s32 e1000_init_eeprom_params(struct e1000_hw *hw);
+
+ /* MNG HOST IF functions */
+-uint32_t e1000_enable_mng_pass_thru(struct e1000_hw *hw);
++u32 e1000_enable_mng_pass_thru(struct e1000_hw *hw);
+
+ #define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64
+ #define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 /* Host Interface data length */
+@@ -354,80 +354,80 @@ uint32_t e1000_enable_mng_pass_thru(struct e1000_hw *hw);
+ #define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F
+
+ struct e1000_host_mng_command_header {
+- uint8_t command_id;
+- uint8_t checksum;
+- uint16_t reserved1;
+- uint16_t reserved2;
+- uint16_t command_length;
++ u8 command_id;
++ u8 checksum;
++ u16 reserved1;
++ u16 reserved2;
++ u16 command_length;
+ };
+
+ struct e1000_host_mng_command_info {
+ struct e1000_host_mng_command_header command_header; /* Command Head/Command Result Head has 4 bytes */
+- uint8_t command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; /* Command data can length 0..0x658*/
++ u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; /* Command data can length 0..0x658*/
+ };
+ #ifdef __BIG_ENDIAN
+ struct e1000_host_mng_dhcp_cookie{
+- uint32_t signature;
+- uint16_t vlan_id;
+- uint8_t reserved0;
+- uint8_t status;
+- uint32_t reserved1;
+- uint8_t checksum;
+- uint8_t reserved3;
+- uint16_t reserved2;
++ u32 signature;
++ u16 vlan_id;
++ u8 reserved0;
++ u8 status;
++ u32 reserved1;
++ u8 checksum;
++ u8 reserved3;
++ u16 reserved2;
+ };
+ #else
+ struct e1000_host_mng_dhcp_cookie{
+- uint32_t signature;
+- uint8_t status;
+- uint8_t reserved0;
+- uint16_t vlan_id;
+- uint32_t reserved1;
+- uint16_t reserved2;
+- uint8_t reserved3;
+- uint8_t checksum;
++ u32 signature;
++ u8 status;
++ u8 reserved0;
++ u16 vlan_id;
++ u32 reserved1;
++ u16 reserved2;
++ u8 reserved3;
++ u8 checksum;
+ };
+ #endif
+
+-int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer,
+- uint16_t length);
+-boolean_t e1000_check_mng_mode(struct e1000_hw *hw);
+-boolean_t e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
+-int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
+-int32_t e1000_validate_eeprom_checksum(struct e1000_hw *hw);
+-int32_t e1000_update_eeprom_checksum(struct e1000_hw *hw);
+-int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
+-int32_t e1000_read_mac_addr(struct e1000_hw * hw);
++s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer,
++ u16 length);
++bool e1000_check_mng_mode(struct e1000_hw *hw);
++bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
++s32 e1000_read_eeprom(struct e1000_hw *hw, u16 reg, u16 words, u16 *data);
++s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw);
++s32 e1000_update_eeprom_checksum(struct e1000_hw *hw);
++s32 e1000_write_eeprom(struct e1000_hw *hw, u16 reg, u16 words, u16 *data);
++s32 e1000_read_mac_addr(struct e1000_hw * hw);
+
+ /* Filters (multicast, vlan, receive) */
+-uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, uint8_t * mc_addr);
+-void e1000_mta_set(struct e1000_hw *hw, uint32_t hash_value);
+-void e1000_rar_set(struct e1000_hw *hw, uint8_t * mc_addr, uint32_t rar_index);
+-void e1000_write_vfta(struct e1000_hw *hw, uint32_t offset, uint32_t value);
++u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 * mc_addr);
++void e1000_mta_set(struct e1000_hw *hw, u32 hash_value);
++void e1000_rar_set(struct e1000_hw *hw, u8 * mc_addr, u32 rar_index);
++void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value);
+
+ /* LED functions */
+-int32_t e1000_setup_led(struct e1000_hw *hw);
+-int32_t e1000_cleanup_led(struct e1000_hw *hw);
+-int32_t e1000_led_on(struct e1000_hw *hw);
+-int32_t e1000_led_off(struct e1000_hw *hw);
+-int32_t e1000_blink_led_start(struct e1000_hw *hw);
++s32 e1000_setup_led(struct e1000_hw *hw);
++s32 e1000_cleanup_led(struct e1000_hw *hw);
++s32 e1000_led_on(struct e1000_hw *hw);
++s32 e1000_led_off(struct e1000_hw *hw);
++s32 e1000_blink_led_start(struct e1000_hw *hw);
+
+ /* Adaptive IFS Functions */
+
+ /* Everything else */
+ void e1000_reset_adaptive(struct e1000_hw *hw);
+ void e1000_update_adaptive(struct e1000_hw *hw);
+-void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats, uint32_t frame_len, uint8_t * mac_addr);
++void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats, u32 frame_len, u8 * mac_addr);
+ void e1000_get_bus_info(struct e1000_hw *hw);
+ void e1000_pci_set_mwi(struct e1000_hw *hw);
+ void e1000_pci_clear_mwi(struct e1000_hw *hw);
+-int32_t e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value);
++s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
+ void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc);
+ int e1000_pcix_get_mmrbc(struct e1000_hw *hw);
+ /* Port I/O is only supported on 82544 and newer */
+-void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value);
+-int32_t e1000_disable_pciex_master(struct e1000_hw *hw);
+-int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
++void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value);
++s32 e1000_disable_pciex_master(struct e1000_hw *hw);
++s32 e1000_check_phy_reset_block(struct e1000_hw *hw);
+
+
+ #define E1000_READ_REG_IO(a, reg) \
+@@ -596,8 +596,8 @@ struct e1000_rx_desc {
+ __le64 buffer_addr; /* Address of the descriptor's data buffer */
+ __le16 length; /* Length of data DMAed into data buffer */
+ __le16 csum; /* Packet checksum */
+- uint8_t status; /* Descriptor status */
+- uint8_t errors; /* Descriptor Errors */
++ u8 status; /* Descriptor status */
++ u8 errors; /* Descriptor Errors */
+ __le16 special;
+ };
+
+@@ -718,15 +718,15 @@ struct e1000_tx_desc {
+ __le32 data;
+ struct {
+ __le16 length; /* Data buffer length */
+- uint8_t cso; /* Checksum offset */
+- uint8_t cmd; /* Descriptor control */
++ u8 cso; /* Checksum offset */
++ u8 cmd; /* Descriptor control */
+ } flags;
+ } lower;
+ union {
+ __le32 data;
+ struct {
+- uint8_t status; /* Descriptor status */
+- uint8_t css; /* Checksum start */
++ u8 status; /* Descriptor status */
++ u8 css; /* Checksum start */
+ __le16 special;
+ } fields;
+ } upper;
+@@ -759,16 +759,16 @@ struct e1000_context_desc {
+ union {
+ __le32 ip_config;
+ struct {
+- uint8_t ipcss; /* IP checksum start */
+- uint8_t ipcso; /* IP checksum offset */
++ u8 ipcss; /* IP checksum start */
++ u8 ipcso; /* IP checksum offset */
+ __le16 ipcse; /* IP checksum end */
+ } ip_fields;
+ } lower_setup;
+ union {
+ __le32 tcp_config;
+ struct {
+- uint8_t tucss; /* TCP checksum start */
+- uint8_t tucso; /* TCP checksum offset */
++ u8 tucss; /* TCP checksum start */
++ u8 tucso; /* TCP checksum offset */
+ __le16 tucse; /* TCP checksum end */
+ } tcp_fields;
+ } upper_setup;
+@@ -776,8 +776,8 @@ struct e1000_context_desc {
+ union {
+ __le32 data;
+ struct {
+- uint8_t status; /* Descriptor status */
+- uint8_t hdr_len; /* Header length */
++ u8 status; /* Descriptor status */
++ u8 hdr_len; /* Header length */
+ __le16 mss; /* Maximum segment size */
+ } fields;
+ } tcp_seg_setup;
+@@ -790,15 +790,15 @@ struct e1000_data_desc {
+ __le32 data;
+ struct {
+ __le16 length; /* Data buffer length */
+- uint8_t typ_len_ext; /* */
+- uint8_t cmd; /* */
++ u8 typ_len_ext; /* */
++ u8 cmd; /* */
+ } flags;
+ } lower;
+ union {
+ __le32 data;
+ struct {
+- uint8_t status; /* Descriptor status */
+- uint8_t popts; /* Packet Options */
++ u8 status; /* Descriptor status */
++ u8 popts; /* Packet Options */
+ __le16 special; /* */
+ } fields;
+ } upper;
+@@ -825,8 +825,8 @@ struct e1000_rar {
+
+ /* IPv4 Address Table Entry */
+ struct e1000_ipv4_at_entry {
+- volatile uint32_t ipv4_addr; /* IP Address (RW) */
+- volatile uint32_t reserved;
++ volatile u32 ipv4_addr; /* IP Address (RW) */
++ volatile u32 reserved;
+ };
+
+ /* Four wakeup IP addresses are supported */
+@@ -837,25 +837,25 @@ struct e1000_ipv4_at_entry {
+
+ /* IPv6 Address Table Entry */
+ struct e1000_ipv6_at_entry {
+- volatile uint8_t ipv6_addr[16];
++ volatile u8 ipv6_addr[16];
+ };
+
+ /* Flexible Filter Length Table Entry */
+ struct e1000_fflt_entry {
+- volatile uint32_t length; /* Flexible Filter Length (RW) */
+- volatile uint32_t reserved;
++ volatile u32 length; /* Flexible Filter Length (RW) */
++ volatile u32 reserved;
+ };
+
+ /* Flexible Filter Mask Table Entry */
+ struct e1000_ffmt_entry {
+- volatile uint32_t mask; /* Flexible Filter Mask (RW) */
+- volatile uint32_t reserved;
++ volatile u32 mask; /* Flexible Filter Mask (RW) */
++ volatile u32 reserved;
+ };
+
+ /* Flexible Filter Value Table Entry */
+ struct e1000_ffvt_entry {
+- volatile uint32_t value; /* Flexible Filter Value (RW) */
+- volatile uint32_t reserved;
++ volatile u32 value; /* Flexible Filter Value (RW) */
++ volatile u32 reserved;
+ };
+
+ /* Four Flexible Filters are supported */
+@@ -1309,89 +1309,89 @@ struct e1000_ffvt_entry {
+
+ /* Statistics counters collected by the MAC */
+ struct e1000_hw_stats {
+- uint64_t crcerrs;
+- uint64_t algnerrc;
+- uint64_t symerrs;
+- uint64_t rxerrc;
+- uint64_t txerrc;
+- uint64_t mpc;
+- uint64_t scc;
+- uint64_t ecol;
+- uint64_t mcc;
+- uint64_t latecol;
+- uint64_t colc;
+- uint64_t dc;
+- uint64_t tncrs;
+- uint64_t sec;
+- uint64_t cexterr;
+- uint64_t rlec;
+- uint64_t xonrxc;
+- uint64_t xontxc;
+- uint64_t xoffrxc;
+- uint64_t xofftxc;
+- uint64_t fcruc;
+- uint64_t prc64;
+- uint64_t prc127;
+- uint64_t prc255;
+- uint64_t prc511;
+- uint64_t prc1023;
+- uint64_t prc1522;
+- uint64_t gprc;
+- uint64_t bprc;
+- uint64_t mprc;
+- uint64_t gptc;
+- uint64_t gorcl;
+- uint64_t gorch;
+- uint64_t gotcl;
+- uint64_t gotch;
+- uint64_t rnbc;
+- uint64_t ruc;
+- uint64_t rfc;
+- uint64_t roc;
+- uint64_t rlerrc;
+- uint64_t rjc;
+- uint64_t mgprc;
+- uint64_t mgpdc;
+- uint64_t mgptc;
+- uint64_t torl;
+- uint64_t torh;
+- uint64_t totl;
+- uint64_t toth;
+- uint64_t tpr;
+- uint64_t tpt;
+- uint64_t ptc64;
+- uint64_t ptc127;
+- uint64_t ptc255;
+- uint64_t ptc511;
+- uint64_t ptc1023;
+- uint64_t ptc1522;
+- uint64_t mptc;
+- uint64_t bptc;
+- uint64_t tsctc;
+- uint64_t tsctfc;
+- uint64_t iac;
+- uint64_t icrxptc;
+- uint64_t icrxatc;
+- uint64_t ictxptc;
+- uint64_t ictxatc;
+- uint64_t ictxqec;
+- uint64_t ictxqmtc;
+- uint64_t icrxdmtc;
+- uint64_t icrxoc;
++ u64 crcerrs;
++ u64 algnerrc;
++ u64 symerrs;
++ u64 rxerrc;
++ u64 txerrc;
++ u64 mpc;
++ u64 scc;
++ u64 ecol;
++ u64 mcc;
++ u64 latecol;
++ u64 colc;
++ u64 dc;
++ u64 tncrs;
++ u64 sec;
++ u64 cexterr;
++ u64 rlec;
++ u64 xonrxc;
++ u64 xontxc;
++ u64 xoffrxc;
++ u64 xofftxc;
++ u64 fcruc;
++ u64 prc64;
++ u64 prc127;
++ u64 prc255;
++ u64 prc511;
++ u64 prc1023;
++ u64 prc1522;
++ u64 gprc;
++ u64 bprc;
++ u64 mprc;
++ u64 gptc;
++ u64 gorcl;
++ u64 gorch;
++ u64 gotcl;
++ u64 gotch;
++ u64 rnbc;
++ u64 ruc;
++ u64 rfc;
++ u64 roc;
++ u64 rlerrc;
++ u64 rjc;
++ u64 mgprc;
++ u64 mgpdc;
++ u64 mgptc;
++ u64 torl;
++ u64 torh;
++ u64 totl;
++ u64 toth;
++ u64 tpr;
++ u64 tpt;
++ u64 ptc64;
++ u64 ptc127;
++ u64 ptc255;
++ u64 ptc511;
++ u64 ptc1023;
++ u64 ptc1522;
++ u64 mptc;
++ u64 bptc;
++ u64 tsctc;
++ u64 tsctfc;
++ u64 iac;
++ u64 icrxptc;
++ u64 icrxatc;
++ u64 ictxptc;
++ u64 ictxatc;
++ u64 ictxqec;
++ u64 ictxqmtc;
++ u64 icrxdmtc;
++ u64 icrxoc;
+ };
+
+ /* Structure containing variables used by the shared code (e1000_hw.c) */
+ struct e1000_hw {
+- uint8_t __iomem *hw_addr;
+- uint8_t __iomem *flash_address;
++ u8 __iomem *hw_addr;
++ u8 __iomem *flash_address;
+ e1000_mac_type mac_type;
+ e1000_phy_type phy_type;
+- uint32_t phy_init_script;
++ u32 phy_init_script;
+ e1000_media_type media_type;
+ void *back;
+ struct e1000_shadow_ram *eeprom_shadow_ram;
+- uint32_t flash_bank_size;
+- uint32_t flash_base_addr;
++ u32 flash_bank_size;
++ u32 flash_base_addr;
+ e1000_fc_type fc;
+ e1000_bus_speed bus_speed;
+ e1000_bus_width bus_width;
+@@ -1400,75 +1400,75 @@ struct e1000_hw {
+ e1000_ms_type master_slave;
+ e1000_ms_type original_master_slave;
+ e1000_ffe_config ffe_config_state;
+- uint32_t asf_firmware_present;
+- uint32_t eeprom_semaphore_present;
+- uint32_t swfw_sync_present;
+- uint32_t swfwhw_semaphore_present;
++ u32 asf_firmware_present;
++ u32 eeprom_semaphore_present;
++ u32 swfw_sync_present;
++ u32 swfwhw_semaphore_present;
+ unsigned long io_base;
+- uint32_t phy_id;
+- uint32_t phy_revision;
+- uint32_t phy_addr;
+- uint32_t original_fc;
+- uint32_t txcw;
+- uint32_t autoneg_failed;
+- uint32_t max_frame_size;
+- uint32_t min_frame_size;
+- uint32_t mc_filter_type;
+- uint32_t num_mc_addrs;
+- uint32_t collision_delta;
+- uint32_t tx_packet_delta;
+- uint32_t ledctl_default;
+- uint32_t ledctl_mode1;
+- uint32_t ledctl_mode2;
+- boolean_t tx_pkt_filtering;
++ u32 phy_id;
++ u32 phy_revision;
++ u32 phy_addr;
++ u32 original_fc;
++ u32 txcw;
++ u32 autoneg_failed;
++ u32 max_frame_size;
++ u32 min_frame_size;
++ u32 mc_filter_type;
++ u32 num_mc_addrs;
++ u32 collision_delta;
++ u32 tx_packet_delta;
++ u32 ledctl_default;
++ u32 ledctl_mode1;
++ u32 ledctl_mode2;
++ bool tx_pkt_filtering;
+ struct e1000_host_mng_dhcp_cookie mng_cookie;
+- uint16_t phy_spd_default;
+- uint16_t autoneg_advertised;
+- uint16_t pci_cmd_word;
+- uint16_t fc_high_water;
+- uint16_t fc_low_water;
+- uint16_t fc_pause_time;
+- uint16_t current_ifs_val;
+- uint16_t ifs_min_val;
+- uint16_t ifs_max_val;
+- uint16_t ifs_step_size;
+- uint16_t ifs_ratio;
+- uint16_t device_id;
+- uint16_t vendor_id;
+- uint16_t subsystem_id;
+- uint16_t subsystem_vendor_id;
+- uint8_t revision_id;
+- uint8_t autoneg;
+- uint8_t mdix;
+- uint8_t forced_speed_duplex;
+- uint8_t wait_autoneg_complete;
+- uint8_t dma_fairness;
+- uint8_t mac_addr[NODE_ADDRESS_SIZE];
+- uint8_t perm_mac_addr[NODE_ADDRESS_SIZE];
+- boolean_t disable_polarity_correction;
+- boolean_t speed_downgraded;
++ u16 phy_spd_default;
++ u16 autoneg_advertised;
++ u16 pci_cmd_word;
++ u16 fc_high_water;
++ u16 fc_low_water;
++ u16 fc_pause_time;
++ u16 current_ifs_val;
++ u16 ifs_min_val;
++ u16 ifs_max_val;
++ u16 ifs_step_size;
++ u16 ifs_ratio;
++ u16 device_id;
++ u16 vendor_id;
++ u16 subsystem_id;
++ u16 subsystem_vendor_id;
++ u8 revision_id;
++ u8 autoneg;
++ u8 mdix;
++ u8 forced_speed_duplex;
++ u8 wait_autoneg_complete;
++ u8 dma_fairness;
++ u8 mac_addr[NODE_ADDRESS_SIZE];
++ u8 perm_mac_addr[NODE_ADDRESS_SIZE];
++ bool disable_polarity_correction;
++ bool speed_downgraded;
+ e1000_smart_speed smart_speed;
+ e1000_dsp_config dsp_config_state;
+- boolean_t get_link_status;
+- boolean_t serdes_link_down;
+- boolean_t tbi_compatibility_en;
+- boolean_t tbi_compatibility_on;
+- boolean_t laa_is_present;
+- boolean_t phy_reset_disable;
+- boolean_t initialize_hw_bits_disable;
+- boolean_t fc_send_xon;
+- boolean_t fc_strict_ieee;
+- boolean_t report_tx_early;
+- boolean_t adaptive_ifs;
+- boolean_t ifs_params_forced;
+- boolean_t in_ifs_mode;
+- boolean_t mng_reg_access_disabled;
+- boolean_t leave_av_bit_off;
+- boolean_t kmrn_lock_loss_workaround_disabled;
+- boolean_t bad_tx_carr_stats_fd;
+- boolean_t has_manc2h;
+- boolean_t rx_needs_kicking;
+- boolean_t has_smbus;
++ bool get_link_status;
++ bool serdes_link_down;
++ bool tbi_compatibility_en;
++ bool tbi_compatibility_on;
++ bool laa_is_present;
++ bool phy_reset_disable;
++ bool initialize_hw_bits_disable;
++ bool fc_send_xon;
++ bool fc_strict_ieee;
++ bool report_tx_early;
++ bool adaptive_ifs;
++ bool ifs_params_forced;
++ bool in_ifs_mode;
++ bool mng_reg_access_disabled;
++ bool leave_av_bit_off;
++ bool kmrn_lock_loss_workaround_disabled;
++ bool bad_tx_carr_stats_fd;
++ bool has_manc2h;
++ bool rx_needs_kicking;
++ bool has_smbus;
+ };
+
+
+@@ -2165,14 +2165,14 @@ typedef enum {
+ #define E1000_HI_COMMAND_TIMEOUT 500 /* Time in ms to process HI command */
+
+ struct e1000_host_command_header {
+- uint8_t command_id;
+- uint8_t command_length;
+- uint8_t command_options; /* I/F bits for command, status for return */
+- uint8_t checksum;
++ u8 command_id;
++ u8 command_length;
++ u8 command_options; /* I/F bits for command, status for return */
++ u8 checksum;
+ };
+ struct e1000_host_command_info {
+ struct e1000_host_command_header command_header; /* Command Head/Command Result Head has 4 bytes */
+- uint8_t command_data[E1000_HI_MAX_DATA_LENGTH]; /* Command data can length 0..252 */
++ u8 command_data[E1000_HI_MAX_DATA_LENGTH]; /* Command data can length 0..252 */
+ };
+
+ /* Host SMB register #0 */
+@@ -2495,7 +2495,7 @@ struct e1000_host_command_info {
+ /* Number of milliseconds we wait for PHY configuration done after MAC reset */
+ #define PHY_CFG_TIMEOUT 100
+
+-#define E1000_TX_BUFFER_SIZE ((uint32_t)1514)
++#define E1000_TX_BUFFER_SIZE ((u32)1514)
+
+ /* The carrier extension symbol, as received by the NIC. */
+ #define CARRIER_EXTENSION 0x0F
+@@ -2518,11 +2518,11 @@ struct e1000_host_command_info {
+ * Typical use:
+ * ...
+ * if (TBI_ACCEPT) {
+- * accept_frame = TRUE;
++ * accept_frame = true;
+ * e1000_tbi_adjust_stats(adapter, MacAddress);
+ * frame_length--;
+ * } else {
+- * accept_frame = FALSE;
++ * accept_frame = false;
+ * }
+ * ...
+ */
+@@ -3312,68 +3312,68 @@ struct e1000_host_command_info {
+ /* Offset 04h HSFSTS */
+ union ich8_hws_flash_status {
+ struct ich8_hsfsts {
+-#ifdef E1000_BIG_ENDIAN
+- uint16_t reserved2 :6;
+- uint16_t fldesvalid :1;
+- uint16_t flockdn :1;
+- uint16_t flcdone :1;
+- uint16_t flcerr :1;
+- uint16_t dael :1;
+- uint16_t berasesz :2;
+- uint16_t flcinprog :1;
+- uint16_t reserved1 :2;
++#ifdef __BIG_ENDIAN
++ u16 reserved2 :6;
++ u16 fldesvalid :1;
++ u16 flockdn :1;
++ u16 flcdone :1;
++ u16 flcerr :1;
++ u16 dael :1;
++ u16 berasesz :2;
++ u16 flcinprog :1;
++ u16 reserved1 :2;
+ #else
+- uint16_t flcdone :1; /* bit 0 Flash Cycle Done */
+- uint16_t flcerr :1; /* bit 1 Flash Cycle Error */
+- uint16_t dael :1; /* bit 2 Direct Access error Log */
+- uint16_t berasesz :2; /* bit 4:3 Block/Sector Erase Size */
+- uint16_t flcinprog :1; /* bit 5 flash SPI cycle in Progress */
+- uint16_t reserved1 :2; /* bit 13:6 Reserved */
+- uint16_t reserved2 :6; /* bit 13:6 Reserved */
+- uint16_t fldesvalid :1; /* bit 14 Flash Descriptor Valid */
+- uint16_t flockdn :1; /* bit 15 Flash Configuration Lock-Down */
++ u16 flcdone :1; /* bit 0 Flash Cycle Done */
++ u16 flcerr :1; /* bit 1 Flash Cycle Error */
++ u16 dael :1; /* bit 2 Direct Access error Log */
++ u16 berasesz :2; /* bit 4:3 Block/Sector Erase Size */
++ u16 flcinprog :1; /* bit 5 flash SPI cycle in Progress */
++ u16 reserved1 :2; /* bit 13:6 Reserved */
++ u16 reserved2 :6; /* bit 13:6 Reserved */
++ u16 fldesvalid :1; /* bit 14 Flash Descriptor Valid */
++ u16 flockdn :1; /* bit 15 Flash Configuration Lock-Down */
+ #endif
+ } hsf_status;
+- uint16_t regval;
++ u16 regval;
+ };
+
+ /* ICH8 GbE Flash Hardware Sequencing Flash control Register bit breakdown */
+ /* Offset 06h FLCTL */
+ union ich8_hws_flash_ctrl {
+ struct ich8_hsflctl {
+-#ifdef E1000_BIG_ENDIAN
+- uint16_t fldbcount :2;
+- uint16_t flockdn :6;
+- uint16_t flcgo :1;
+- uint16_t flcycle :2;
+- uint16_t reserved :5;
++#ifdef __BIG_ENDIAN
++ u16 fldbcount :2;
++ u16 flockdn :6;
++ u16 flcgo :1;
++ u16 flcycle :2;
++ u16 reserved :5;
+ #else
+- uint16_t flcgo :1; /* 0 Flash Cycle Go */
+- uint16_t flcycle :2; /* 2:1 Flash Cycle */
+- uint16_t reserved :5; /* 7:3 Reserved */
+- uint16_t fldbcount :2; /* 9:8 Flash Data Byte Count */
+- uint16_t flockdn :6; /* 15:10 Reserved */
++ u16 flcgo :1; /* 0 Flash Cycle Go */
++ u16 flcycle :2; /* 2:1 Flash Cycle */
++ u16 reserved :5; /* 7:3 Reserved */
++ u16 fldbcount :2; /* 9:8 Flash Data Byte Count */
++ u16 flockdn :6; /* 15:10 Reserved */
+ #endif
+ } hsf_ctrl;
+- uint16_t regval;
++ u16 regval;
+ };
+
+ /* ICH8 Flash Region Access Permissions */
+ union ich8_hws_flash_regacc {
+ struct ich8_flracc {
+-#ifdef E1000_BIG_ENDIAN
+- uint32_t gmwag :8;
+- uint32_t gmrag :8;
+- uint32_t grwa :8;
+- uint32_t grra :8;
++#ifdef __BIG_ENDIAN
++ u32 gmwag :8;
++ u32 gmrag :8;
++ u32 grwa :8;
++ u32 grra :8;
+ #else
+- uint32_t grra :8; /* 0:7 GbE region Read Access */
+- uint32_t grwa :8; /* 8:15 GbE region Write Access */
+- uint32_t gmrag :8; /* 23:16 GbE Master Read Access Grant */
+- uint32_t gmwag :8; /* 31:24 GbE Master Write Access Grant */
++ u32 grra :8; /* 0:7 GbE region Read Access */
++ u32 grwa :8; /* 8:15 GbE region Write Access */
++ u32 gmrag :8; /* 23:16 GbE Master Read Access Grant */
++ u32 gmwag :8; /* 31:24 GbE Master Write Access Grant */
+ #endif
+ } hsf_flregacc;
+- uint16_t regval;
++ u16 regval;
+ };
+
+ /* Miscellaneous PHY bit definitions. */
+diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
+index 0991648..59579b1 100644
+--- a/drivers/net/e1000/e1000_main.c
++++ b/drivers/net/e1000/e1000_main.c
+@@ -127,7 +127,7 @@ int e1000_up(struct e1000_adapter *adapter);
+ void e1000_down(struct e1000_adapter *adapter);
+ void e1000_reinit_locked(struct e1000_adapter *adapter);
+ void e1000_reset(struct e1000_adapter *adapter);
+-int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
++int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx);
+ int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+ int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+ void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
+@@ -169,21 +169,21 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
+ static int e1000_set_mac(struct net_device *netdev, void *p);
+ static irqreturn_t e1000_intr(int irq, void *data);
+ static irqreturn_t e1000_intr_msi(int irq, void *data);
+-static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter,
+- struct e1000_tx_ring *tx_ring);
++static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
++ struct e1000_tx_ring *tx_ring);
+ #ifdef CONFIG_E1000_NAPI
+ static int e1000_clean(struct napi_struct *napi, int budget);
+-static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
+- struct e1000_rx_ring *rx_ring,
+- int *work_done, int work_to_do);
+-static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+- struct e1000_rx_ring *rx_ring,
+- int *work_done, int work_to_do);
++static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring,
++ int *work_done, int work_to_do);
++static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring,
++ int *work_done, int work_to_do);
+ #else
+-static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
+- struct e1000_rx_ring *rx_ring);
+-static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+- struct e1000_rx_ring *rx_ring);
++static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring);
++static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring);
+ #endif
+ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+@@ -203,8 +203,8 @@ static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
+ struct sk_buff *skb);
+
+ static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
+-static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
+-static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
++static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
++static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
+ static void e1000_restore_vlan(struct e1000_adapter *adapter);
+
+ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
+@@ -347,7 +347,6 @@ static void e1000_free_irq(struct e1000_adapter *adapter)
+ static void
+ e1000_irq_disable(struct e1000_adapter *adapter)
+ {
+- atomic_inc(&adapter->irq_sem);
+ E1000_WRITE_REG(&adapter->hw, IMC, ~0);
+ E1000_WRITE_FLUSH(&adapter->hw);
+ synchronize_irq(adapter->pdev->irq);
+@@ -361,18 +360,16 @@ e1000_irq_disable(struct e1000_adapter *adapter)
+ static void
+ e1000_irq_enable(struct e1000_adapter *adapter)
+ {
+- if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
+- E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
+- E1000_WRITE_FLUSH(&adapter->hw);
+- }
++ E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
++ E1000_WRITE_FLUSH(&adapter->hw);
+ }
+
+ static void
+ e1000_update_mng_vlan(struct e1000_adapter *adapter)
+ {
+ struct net_device *netdev = adapter->netdev;
+- uint16_t vid = adapter->hw.mng_cookie.vlan_id;
+- uint16_t old_vid = adapter->mng_vlan_id;
++ u16 vid = adapter->hw.mng_cookie.vlan_id;
++ u16 old_vid = adapter->mng_vlan_id;
+ if (adapter->vlgrp) {
+ if (!vlan_group_get_device(adapter->vlgrp, vid)) {
+ if (adapter->hw.mng_cookie.status &
+@@ -382,7 +379,7 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter)
+ } else
+ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
+
+- if ((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) &&
++ if ((old_vid != (u16)E1000_MNG_VLAN_NONE) &&
+ (vid != old_vid) &&
+ !vlan_group_get_device(adapter->vlgrp, old_vid))
+ e1000_vlan_rx_kill_vid(netdev, old_vid);
+@@ -405,8 +402,8 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter)
+ static void
+ e1000_release_hw_control(struct e1000_adapter *adapter)
+ {
+- uint32_t ctrl_ext;
+- uint32_t swsm;
++ u32 ctrl_ext;
++ u32 swsm;
+
+ /* Let firmware taken over control of h/w */
+ switch (adapter->hw.mac_type) {
+@@ -442,8 +439,8 @@ e1000_release_hw_control(struct e1000_adapter *adapter)
+ static void
+ e1000_get_hw_control(struct e1000_adapter *adapter)
+ {
+- uint32_t ctrl_ext;
+- uint32_t swsm;
++ u32 ctrl_ext;
++ u32 swsm;
+
+ /* Let firmware know the driver has taken over */
+ switch (adapter->hw.mac_type) {
+@@ -469,7 +466,7 @@ static void
+ e1000_init_manageability(struct e1000_adapter *adapter)
+ {
+ if (adapter->en_mng_pt) {
+- uint32_t manc = E1000_READ_REG(&adapter->hw, MANC);
++ u32 manc = E1000_READ_REG(&adapter->hw, MANC);
+
+ /* disable hardware interception of ARP */
+ manc &= ~(E1000_MANC_ARP_EN);
+@@ -478,7 +475,7 @@ e1000_init_manageability(struct e1000_adapter *adapter)
+ /* this will probably generate destination unreachable messages
+ * from the host OS, but the packets will be handled on SMBUS */
+ if (adapter->hw.has_manc2h) {
+- uint32_t manc2h = E1000_READ_REG(&adapter->hw, MANC2H);
++ u32 manc2h = E1000_READ_REG(&adapter->hw, MANC2H);
+
+ manc |= E1000_MANC_EN_MNG2HOST;
+ #define E1000_MNG2HOST_PORT_623 (1 << 5)
+@@ -496,7 +493,7 @@ static void
+ e1000_release_manageability(struct e1000_adapter *adapter)
+ {
+ if (adapter->en_mng_pt) {
+- uint32_t manc = E1000_READ_REG(&adapter->hw, MANC);
++ u32 manc = E1000_READ_REG(&adapter->hw, MANC);
+
+ /* re-enable hardware interception of ARP */
+ manc |= E1000_MANC_ARP_EN;
+@@ -569,7 +566,7 @@ int e1000_up(struct e1000_adapter *adapter)
+
+ void e1000_power_up_phy(struct e1000_adapter *adapter)
+ {
+- uint16_t mii_reg = 0;
++ u16 mii_reg = 0;
+
+ /* Just clear the power down bit to wake the phy back up */
+ if (adapter->hw.media_type == e1000_media_type_copper) {
+@@ -584,13 +581,13 @@ void e1000_power_up_phy(struct e1000_adapter *adapter)
+ static void e1000_power_down_phy(struct e1000_adapter *adapter)
+ {
+ /* Power down the PHY so no link is implied when interface is down *
+- * The PHY cannot be powered down if any of the following is TRUE *
++ * The PHY cannot be powered down if any of the following is true *
+ * (a) WoL is enabled
+ * (b) AMT is active
+ * (c) SoL/IDER session is active */
+ if (!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
+ adapter->hw.media_type == e1000_media_type_copper) {
+- uint16_t mii_reg = 0;
++ u16 mii_reg = 0;
+
+ switch (adapter->hw.mac_type) {
+ case e1000_82540:
+@@ -638,7 +635,6 @@ e1000_down(struct e1000_adapter *adapter)
+
+ #ifdef CONFIG_E1000_NAPI
+ napi_disable(&adapter->napi);
+- atomic_set(&adapter->irq_sem, 0);
+ #endif
+ e1000_irq_disable(adapter);
+
+@@ -671,9 +667,9 @@ e1000_reinit_locked(struct e1000_adapter *adapter)
+ void
+ e1000_reset(struct e1000_adapter *adapter)
+ {
+- uint32_t pba = 0, tx_space, min_tx_space, min_rx_space;
+- uint16_t fc_high_water_mark = E1000_FC_HIGH_DIFF;
+- boolean_t legacy_pba_adjust = FALSE;
++ u32 pba = 0, tx_space, min_tx_space, min_rx_space;
++ u16 fc_high_water_mark = E1000_FC_HIGH_DIFF;
++ bool legacy_pba_adjust = false;
+
+ /* Repartition Pba for greater than 9k mtu
+ * To take effect CTRL.RST is required.
+@@ -687,7 +683,7 @@ e1000_reset(struct e1000_adapter *adapter)
+ case e1000_82540:
+ case e1000_82541:
+ case e1000_82541_rev_2:
+- legacy_pba_adjust = TRUE;
++ legacy_pba_adjust = true;
+ pba = E1000_PBA_48K;
+ break;
+ case e1000_82545:
+@@ -698,7 +694,7 @@ e1000_reset(struct e1000_adapter *adapter)
+ break;
+ case e1000_82547:
+ case e1000_82547_rev_2:
+- legacy_pba_adjust = TRUE;
++ legacy_pba_adjust = true;
+ pba = E1000_PBA_30K;
+ break;
+ case e1000_82571:
+@@ -716,7 +712,7 @@ e1000_reset(struct e1000_adapter *adapter)
+ break;
+ }
+
+- if (legacy_pba_adjust == TRUE) {
++ if (legacy_pba_adjust) {
+ if (adapter->netdev->mtu > E1000_RXBUFFER_8192)
+ pba -= 8; /* allocate more FIFO for Tx */
+
+@@ -819,7 +815,7 @@ e1000_reset(struct e1000_adapter *adapter)
+ adapter->hw.mac_type <= e1000_82547_rev_2 &&
+ adapter->hw.autoneg == 1 &&
+ adapter->hw.autoneg_advertised == ADVERTISE_1000_FULL) {
+- uint32_t ctrl = E1000_READ_REG(&adapter->hw, CTRL);
++ u32 ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+ /* clear phy power management bit if we are in gig only mode,
+ * which if enabled will attempt negotiation to 100Mb, which
+ * can cause a loss of link at power off or driver unload */
+@@ -836,7 +832,7 @@ e1000_reset(struct e1000_adapter *adapter)
+ if (!adapter->smart_power_down &&
+ (adapter->hw.mac_type == e1000_82571 ||
+ adapter->hw.mac_type == e1000_82572)) {
+- uint16_t phy_data = 0;
++ u16 phy_data = 0;
+ /* speed up time to link by disabling smart power down, ignore
+ * the return value of this function because there is nothing
+ * different we would do if it failed */
+@@ -930,8 +926,8 @@ e1000_probe(struct pci_dev *pdev,
+ static int cards_found = 0;
+ static int global_quad_port_a = 0; /* global ksp3 port a indication */
+ int i, err, pci_using_dac;
+- uint16_t eeprom_data = 0;
+- uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
++ u16 eeprom_data = 0;
++ u16 eeprom_apme_mask = E1000_EEPROM_APME;
+ DECLARE_MAC_BUF(mac);
+
+ if ((err = pci_enable_device(pdev)))
+@@ -1366,15 +1362,15 @@ e1000_sw_init(struct e1000_adapter *adapter)
+
+ e1000_set_media_type(hw);
+
+- hw->wait_autoneg_complete = FALSE;
+- hw->tbi_compatibility_en = TRUE;
+- hw->adaptive_ifs = TRUE;
++ hw->wait_autoneg_complete = false;
++ hw->tbi_compatibility_en = true;
++ hw->adaptive_ifs = true;
+
+ /* Copper options */
+
+ if (hw->media_type == e1000_media_type_copper) {
+ hw->mdix = AUTO_ALL_MODES;
+- hw->disable_polarity_correction = FALSE;
++ hw->disable_polarity_correction = false;
+ hw->master_slave = E1000_MASTER_SLAVE;
+ }
+
+@@ -1396,7 +1392,6 @@ e1000_sw_init(struct e1000_adapter *adapter)
+ #endif
+
+ /* Explicitly disable IRQ since the NIC can be in any state. */
+- atomic_set(&adapter->irq_sem, 0);
+ e1000_irq_disable(adapter);
+
+ spin_lock_init(&adapter->stats_lock);
+@@ -1576,7 +1571,7 @@ e1000_close(struct net_device *netdev)
+ * @start: address of beginning of memory
+ * @len: length of memory
+ **/
+-static boolean_t
++static bool
+ e1000_check_64k_bound(struct e1000_adapter *adapter,
+ void *start, unsigned long len)
+ {
+@@ -1587,10 +1582,10 @@ e1000_check_64k_bound(struct e1000_adapter *adapter,
+ * write location to cross 64k boundary due to errata 23 */
+ if (adapter->hw.mac_type == e1000_82545 ||
+ adapter->hw.mac_type == e1000_82546) {
+- return ((begin ^ (end - 1)) >> 16) != 0 ? FALSE : TRUE;
++ return ((begin ^ (end - 1)) >> 16) != 0 ? false : true;
+ }
+
+- return TRUE;
++ return true;
+ }
+
+ /**
+@@ -1707,10 +1702,10 @@ e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
+ static void
+ e1000_configure_tx(struct e1000_adapter *adapter)
+ {
+- uint64_t tdba;
++ u64 tdba;
+ struct e1000_hw *hw = &adapter->hw;
+- uint32_t tdlen, tctl, tipg, tarc;
+- uint32_t ipgr1, ipgr2;
++ u32 tdlen, tctl, tipg, tarc;
++ u32 ipgr1, ipgr2;
+
+ /* Setup the HW Tx Head and Tail descriptor pointers */
+
+@@ -1952,10 +1947,10 @@ e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
+ static void
+ e1000_setup_rctl(struct e1000_adapter *adapter)
+ {
+- uint32_t rctl, rfctl;
+- uint32_t psrctl = 0;
++ u32 rctl, rfctl;
++ u32 psrctl = 0;
+ #ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
+- uint32_t pages = 0;
++ u32 pages = 0;
+ #endif
+
+ rctl = E1000_READ_REG(&adapter->hw, RCTL);
+@@ -2070,9 +2065,9 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
+ static void
+ e1000_configure_rx(struct e1000_adapter *adapter)
+ {
+- uint64_t rdba;
++ u64 rdba;
+ struct e1000_hw *hw = &adapter->hw;
+- uint32_t rdlen, rctl, rxcsum, ctrl_ext;
++ u32 rdlen, rctl, rxcsum, ctrl_ext;
+
+ if (adapter->rx_ps_pages) {
+ /* this is a 32 byte descriptor */
+@@ -2133,7 +2128,7 @@ e1000_configure_rx(struct e1000_adapter *adapter)
+ /* Enable 82543 Receive Checksum Offload for TCP and UDP */
+ if (hw->mac_type >= e1000_82543) {
+ rxcsum = E1000_READ_REG(hw, RXCSUM);
+- if (adapter->rx_csum == TRUE) {
++ if (adapter->rx_csum) {
+ rxcsum |= E1000_RXCSUM_TUOFL;
+
+ /* Enable 82571 IPv4 payload checksum for UDP fragments
+@@ -2392,7 +2387,7 @@ static void
+ e1000_enter_82542_rst(struct e1000_adapter *adapter)
+ {
+ struct net_device *netdev = adapter->netdev;
+- uint32_t rctl;
++ u32 rctl;
+
+ e1000_pci_clear_mwi(&adapter->hw);
+
+@@ -2410,7 +2405,7 @@ static void
+ e1000_leave_82542_rst(struct e1000_adapter *adapter)
+ {
+ struct net_device *netdev = adapter->netdev;
+- uint32_t rctl;
++ u32 rctl;
+
+ rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ rctl &= ~E1000_RCTL_RST;
+@@ -2495,8 +2490,8 @@ e1000_set_rx_mode(struct net_device *netdev)
+ struct e1000_hw *hw = &adapter->hw;
+ struct dev_addr_list *uc_ptr;
+ struct dev_addr_list *mc_ptr;
+- uint32_t rctl;
+- uint32_t hash_value;
++ u32 rctl;
++ u32 hash_value;
+ int i, rar_entries = E1000_RAR_ENTRIES;
+ int mta_reg_count = (hw->mac_type == e1000_ich8lan) ?
+ E1000_NUM_MTA_REGISTERS_ICH8LAN :
+@@ -2600,7 +2595,7 @@ e1000_82547_tx_fifo_stall(unsigned long data)
+ {
+ struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+ struct net_device *netdev = adapter->netdev;
+- uint32_t tctl;
++ u32 tctl;
+
+ if (atomic_read(&adapter->tx_fifo_stall)) {
+ if ((E1000_READ_REG(&adapter->hw, TDT) ==
+@@ -2642,8 +2637,8 @@ e1000_watchdog(unsigned long data)
+ struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+ struct net_device *netdev = adapter->netdev;
+ struct e1000_tx_ring *txdr = adapter->tx_ring;
+- uint32_t link, tctl;
+- int32_t ret_val;
++ u32 link, tctl;
++ s32 ret_val;
+
+ ret_val = e1000_check_for_link(&adapter->hw);
+ if ((ret_val == E1000_ERR_PHY) &&
+@@ -2668,8 +2663,8 @@ e1000_watchdog(unsigned long data)
+
+ if (link) {
+ if (!netif_carrier_ok(netdev)) {
+- uint32_t ctrl;
+- boolean_t txb2b = 1;
++ u32 ctrl;
++ bool txb2b = true;
+ e1000_get_speed_and_duplex(&adapter->hw,
+ &adapter->link_speed,
+ &adapter->link_duplex);
+@@ -2691,12 +2686,12 @@ e1000_watchdog(unsigned long data)
+ adapter->tx_timeout_factor = 1;
+ switch (adapter->link_speed) {
+ case SPEED_10:
+- txb2b = 0;
++ txb2b = false;
+ netdev->tx_queue_len = 10;
+ adapter->tx_timeout_factor = 8;
+ break;
+ case SPEED_100:
+- txb2b = 0;
++ txb2b = false;
+ netdev->tx_queue_len = 100;
+ /* maybe add some timeout factor ? */
+ break;
+@@ -2704,8 +2699,8 @@ e1000_watchdog(unsigned long data)
+
+ if ((adapter->hw.mac_type == e1000_82571 ||
+ adapter->hw.mac_type == e1000_82572) &&
+- txb2b == 0) {
+- uint32_t tarc0;
++ !txb2b) {
++ u32 tarc0;
+ tarc0 = E1000_READ_REG(&adapter->hw, TARC0);
+ tarc0 &= ~(1 << 21);
+ E1000_WRITE_REG(&adapter->hw, TARC0, tarc0);
+@@ -2747,7 +2742,7 @@ e1000_watchdog(unsigned long data)
+ /* make sure the receive unit is started */
+ if (adapter->hw.rx_needs_kicking) {
+ struct e1000_hw *hw = &adapter->hw;
+- uint32_t rctl = E1000_READ_REG(hw, RCTL);
++ u32 rctl = E1000_READ_REG(hw, RCTL);
+ E1000_WRITE_REG(hw, RCTL, rctl | E1000_RCTL_EN);
+ }
+ }
+@@ -2802,7 +2797,7 @@ e1000_watchdog(unsigned long data)
+ E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0);
+
+ /* Force detection of hung controller every watchdog period */
+- adapter->detect_tx_hung = TRUE;
++ adapter->detect_tx_hung = true;
+
+ /* With 82571 controllers, LAA may be overwritten due to controller
+ * reset from the other port. Set the appropriate LAA in RAR[0] */
+@@ -2837,7 +2832,7 @@ enum latency_range {
+ * @bytes: the number of bytes during this measurement interval
+ **/
+ static unsigned int e1000_update_itr(struct e1000_adapter *adapter,
+- uint16_t itr_setting,
++ u16 itr_setting,
+ int packets,
+ int bytes)
+ {
+@@ -2889,8 +2884,8 @@ update_itr_done:
+ static void e1000_set_itr(struct e1000_adapter *adapter)
+ {
+ struct e1000_hw *hw = &adapter->hw;
+- uint16_t current_itr;
+- uint32_t new_itr = adapter->itr;
++ u16 current_itr;
++ u32 new_itr = adapter->itr;
+
+ if (unlikely(hw->mac_type < e1000_82540))
+ return;
+@@ -2964,9 +2959,9 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ struct e1000_context_desc *context_desc;
+ struct e1000_buffer *buffer_info;
+ unsigned int i;
+- uint32_t cmd_length = 0;
+- uint16_t ipcse = 0, tucse, mss;
+- uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
++ u32 cmd_length = 0;
++ u16 ipcse = 0, tucse, mss;
++ u8 ipcss, ipcso, tucss, tucso, hdr_len;
+ int err;
+
+ if (skb_is_gso(skb)) {
+@@ -3025,19 +3020,19 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ if (++i == tx_ring->count) i = 0;
+ tx_ring->next_to_use = i;
+
+- return TRUE;
++ return true;
+ }
+- return FALSE;
+ return false;
-+}
-+
-+static 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;
+ }
+
+-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 0;
-+}
-+
-+static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
-+ struct tx_packet_desc *ptpd)
-+{
-+ /* spinlock held */
-+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-+ struct atl1_buffer *buffer_info;
-+ u16 buf_len = skb->len;
-+ struct page *page;
-+ unsigned long offset;
-+ unsigned int nr_frags;
-+ unsigned int f;
-+ int retval;
-+ u16 next_to_use;
-+ u16 data_len;
-+ u8 hdr_len;
-+
-+ buf_len -= skb->data_len;
-+ nr_frags = skb_shinfo(skb)->nr_frags;
-+ next_to_use = atomic_read(&tpd_ring->next_to_use);
-+ buffer_info = &tpd_ring->buffer_info[next_to_use];
-+ if (unlikely(buffer_info->skb))
-+ BUG();
-+ /* put skb in last TPD */
-+ buffer_info->skb = NULL;
-+
-+ retval = (ptpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK;
-+ if (retval) {
-+ /* TSO */
-+ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-+ buffer_info->length = hdr_len;
-+ page = virt_to_page(skb->data);
-+ offset = (unsigned long)skb->data & ~PAGE_MASK;
-+ buffer_info->dma = pci_map_page(adapter->pdev, page,
-+ offset, hdr_len,
-+ PCI_DMA_TODEVICE);
-+
-+ if (++next_to_use == tpd_ring->count)
-+ next_to_use = 0;
-+
-+ if (buf_len > hdr_len) {
-+ int i, nseg;
-+
-+ data_len = buf_len - hdr_len;
-+ nseg = (data_len + ATL1_MAX_TX_BUF_LEN - 1) /
-+ ATL1_MAX_TX_BUF_LEN;
-+ for (i = 0; i < nseg; i++) {
-+ buffer_info =
-+ &tpd_ring->buffer_info[next_to_use];
-+ buffer_info->skb = NULL;
-+ buffer_info->length =
-+ (ATL1_MAX_TX_BUF_LEN >=
-+ data_len) ? ATL1_MAX_TX_BUF_LEN : data_len;
-+ data_len -= buffer_info->length;
-+ page = virt_to_page(skb->data +
-+ (hdr_len + i * ATL1_MAX_TX_BUF_LEN));
-+ offset = (unsigned long)(skb->data +
-+ (hdr_len + i * ATL1_MAX_TX_BUF_LEN)) &
-+ ~PAGE_MASK;
-+ buffer_info->dma = pci_map_page(adapter->pdev,
-+ page, offset, buffer_info->length,
-+ PCI_DMA_TODEVICE);
-+ if (++next_to_use == tpd_ring->count)
-+ next_to_use = 0;
-+ }
-+ }
-+ } else {
-+ /* not TSO */
-+ buffer_info->length = buf_len;
-+ page = virt_to_page(skb->data);
-+ offset = (unsigned long)skb->data & ~PAGE_MASK;
-+ buffer_info->dma = pci_map_page(adapter->pdev, page,
-+ offset, buf_len, PCI_DMA_TODEVICE);
-+ if (++next_to_use == tpd_ring->count)
-+ next_to_use = 0;
-+ }
-+
-+ for (f = 0; f < nr_frags; f++) {
-+ struct skb_frag_struct *frag;
-+ u16 i, nseg;
-+
-+ frag = &skb_shinfo(skb)->frags[f];
-+ buf_len = frag->size;
-+
-+ nseg = (buf_len + ATL1_MAX_TX_BUF_LEN - 1) /
-+ ATL1_MAX_TX_BUF_LEN;
-+ for (i = 0; i < nseg; i++) {
-+ buffer_info = &tpd_ring->buffer_info[next_to_use];
-+ if (unlikely(buffer_info->skb))
-+ BUG();
-+ buffer_info->skb = NULL;
-+ buffer_info->length = (buf_len > ATL1_MAX_TX_BUF_LEN) ?
-+ ATL1_MAX_TX_BUF_LEN : buf_len;
-+ buf_len -= buffer_info->length;
-+ buffer_info->dma = pci_map_page(adapter->pdev,
-+ frag->page,
-+ frag->page_offset + (i * ATL1_MAX_TX_BUF_LEN),
-+ buffer_info->length, PCI_DMA_TODEVICE);
-+
-+ if (++next_to_use == tpd_ring->count)
-+ next_to_use = 0;
-+ }
-+ }
-+
-+ /* last tpd's buffer-info */
-+ buffer_info->skb = skb;
-+}
-+
-+static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count,
-+ struct tx_packet_desc *ptpd)
-+{
-+ /* spinlock held */
-+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-+ struct atl1_buffer *buffer_info;
-+ struct tx_packet_desc *tpd;
-+ u16 j;
-+ u32 val;
-+ u16 next_to_use = (u16) atomic_read(&tpd_ring->next_to_use);
-+
-+ for (j = 0; j < count; j++) {
-+ buffer_info = &tpd_ring->buffer_info[next_to_use];
-+ tpd = ATL1_TPD_DESC(&adapter->tpd_ring, next_to_use);
-+ if (tpd != ptpd)
-+ memcpy(tpd, ptpd, sizeof(struct tx_packet_desc));
-+ tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
-+ tpd->word2 = (cpu_to_le16(buffer_info->length) &
-+ TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT;
-+
-+ /*
-+ * if this is the first packet in a TSO chain, set
-+ * TPD_HDRFLAG, otherwise, clear it.
-+ */
-+ val = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) &
-+ TPD_SEGMENT_EN_MASK;
-+ if (val) {
-+ if (!j)
-+ tpd->word3 |= 1 << TPD_HDRFLAG_SHIFT;
-+ else
-+ tpd->word3 &= ~(1 << TPD_HDRFLAG_SHIFT);
-+ }
-+
-+ if (j == (count - 1))
-+ tpd->word3 |= 1 << TPD_EOP_SHIFT;
-+
-+ if (++next_to_use == tpd_ring->count)
-+ next_to_use = 0;
-+ }
-+ /*
-+ * Force memory writes to complete before letting h/w
-+ * know there are new descriptors to fetch. (Only
-+ * applicable for weak-ordered memory model archs,
-+ * such as IA-64).
-+ */
-+ wmb();
-+
-+ atomic_set(&tpd_ring->next_to_use, next_to_use);
-+}
-+
-+static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
-+{
-+ struct atl1_adapter *adapter = netdev_priv(netdev);
-+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-+ int len = skb->len;
-+ int tso;
-+ int count = 1;
-+ int ret_val;
-+ struct tx_packet_desc *ptpd;
-+ u16 frag_size;
-+ u16 vlan_tag;
-+ unsigned long flags;
-+ unsigned int nr_frags = 0;
-+ unsigned int mss = 0;
-+ unsigned int f;
-+ unsigned int proto_hdr_len;
-+
-+ len -= skb->data_len;
-+
-+ if (unlikely(skb->len <= 0)) {
-+ dev_kfree_skb_any(skb);
-+ return NETDEV_TX_OK;
-+ }
-+
-+ nr_frags = skb_shinfo(skb)->nr_frags;
-+ for (f = 0; f < nr_frags; f++) {
-+ frag_size = skb_shinfo(skb)->frags[f].size;
-+ if (frag_size)
-+ count += (frag_size + ATL1_MAX_TX_BUF_LEN - 1) /
-+ ATL1_MAX_TX_BUF_LEN;
-+ }
-+
-+ mss = skb_shinfo(skb)->gso_size;
-+ if (mss) {
-+ if (skb->protocol == ntohs(ETH_P_IP)) {
-+ proto_hdr_len = (skb_transport_offset(skb) +
-+ tcp_hdrlen(skb));
-+ if (unlikely(proto_hdr_len > len)) {
-+ dev_kfree_skb_any(skb);
-+ return NETDEV_TX_OK;
-+ }
-+ /* need additional TPD ? */
-+ if (proto_hdr_len != len)
-+ count += (len - proto_hdr_len +
-+ ATL1_MAX_TX_BUF_LEN - 1) /
-+ ATL1_MAX_TX_BUF_LEN;
-+ }
-+ }
-+
-+ if (!spin_trylock_irqsave(&adapter->lock, flags)) {
-+ /* Can't get lock - tell upper layer to requeue */
-+ if (netif_msg_tx_queued(adapter))
-+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-+ "tx locked\n");
-+ return NETDEV_TX_LOCKED;
-+ }
-+
-+ if (atl1_tpd_avail(&adapter->tpd_ring) < count) {
-+ /* not enough descriptors */
-+ netif_stop_queue(netdev);
-+ spin_unlock_irqrestore(&adapter->lock, flags);
-+ if (netif_msg_tx_queued(adapter))
-+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-+ "tx busy\n");
-+ return NETDEV_TX_BUSY;
-+ }
-+
-+ ptpd = ATL1_TPD_DESC(tpd_ring,
-+ (u16) atomic_read(&tpd_ring->next_to_use));
-+ memset(ptpd, 0, sizeof(struct tx_packet_desc));
-+
-+ if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
-+ vlan_tag = vlan_tx_tag_get(skb);
-+ vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) |
-+ ((vlan_tag >> 9) & 0x8);
-+ ptpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT;
-+ ptpd->word3 |= (vlan_tag & TPD_VL_TAGGED_MASK) <<
-+ TPD_VL_TAGGED_SHIFT;
-+ }
-+
-+ tso = atl1_tso(adapter, skb, ptpd);
-+ if (tso < 0) {
-+ spin_unlock_irqrestore(&adapter->lock, flags);
-+ dev_kfree_skb_any(skb);
-+ return NETDEV_TX_OK;
-+ }
-+
-+ if (!tso) {
-+ ret_val = atl1_tx_csum(adapter, skb, ptpd);
-+ if (ret_val < 0) {
-+ spin_unlock_irqrestore(&adapter->lock, flags);
-+ dev_kfree_skb_any(skb);
-+ return NETDEV_TX_OK;
-+ }
-+ }
-+
-+ atl1_tx_map(adapter, skb, ptpd);
-+ atl1_tx_queue(adapter, count, ptpd);
-+ atl1_update_mailbox(adapter);
-+ spin_unlock_irqrestore(&adapter->lock, flags);
-+ netdev->trans_start = jiffies;
-+ return NETDEV_TX_OK;
-+}
-+
-+/*
-+ * atl1_intr - Interrupt Handler
-+ * @irq: interrupt number
-+ * @data: pointer to a network interface device structure
-+ * @pt_regs: CPU registers structure
-+ */
-+static irqreturn_t atl1_intr(int irq, void *data)
-+{
-+ struct atl1_adapter *adapter = netdev_priv(data);
-+ u32 status;
-+ int max_ints = 10;
-+
-+ status = adapter->cmb.cmb->int_stats;
-+ if (!status)
-+ return IRQ_NONE;
-+
-+ do {
-+ /* clear CMB interrupt status at once */
-+ adapter->cmb.cmb->int_stats = 0;
-+
-+ if (status & ISR_GPHY) /* clear phy status */
-+ atlx_clear_phy_int(adapter);
-+
-+ /* clear ISR status, and Enable CMB DMA/Disable Interrupt */
-+ iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
-+
-+ /* check if SMB intr */
-+ if (status & ISR_SMB)
-+ atl1_inc_smb(adapter);
-+
-+ /* check if PCIE PHY Link down */
-+ if (status & ISR_PHY_LINKDOWN) {
-+ if (netif_msg_intr(adapter))
-+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-+ "pcie phy link down %x\n", status);
-+ if (netif_running(adapter->netdev)) { /* reset MAC */
-+ iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-+ schedule_work(&adapter->pcie_dma_to_rst_task);
-+ return IRQ_HANDLED;
-+ }
-+ }
-+
-+ /* check if DMA read/write error ? */
-+ if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
-+ if (netif_msg_intr(adapter))
-+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-+ "pcie DMA r/w error (status = 0x%x)\n",
-+ status);
-+ iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-+ schedule_work(&adapter->pcie_dma_to_rst_task);
-+ return IRQ_HANDLED;
-+ }
-+
-+ /* link event */
-+ if (status & ISR_GPHY) {
-+ adapter->soft_stats.tx_carrier_errors++;
-+ atl1_check_for_link(adapter);
-+ }
-+
-+ /* transmit event */
-+ if (status & ISR_CMB_TX)
-+ atl1_intr_tx(adapter);
-+
-+ /* rx exception */
-+ if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
-+ ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
-+ ISR_HOST_RRD_OV | ISR_CMB_RX))) {
-+ if (status & (ISR_RXF_OV | ISR_RFD_UNRUN |
-+ ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
-+ ISR_HOST_RRD_OV))
-+ if (netif_msg_intr(adapter))
-+ dev_printk(KERN_DEBUG,
-+ &adapter->pdev->dev,
-+ "rx exception, ISR = 0x%x\n",
-+ status);
-+ atl1_intr_rx(adapter);
-+ }
-+
-+ if (--max_ints < 0)
-+ break;
-+
-+ } while ((status = adapter->cmb.cmb->int_stats));
-+
-+ /* re-enable Interrupt */
-+ iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
-+ return IRQ_HANDLED;
-+}
-+
-+/*
-+ * atl1_watchdog - Timer Call-back
-+ * @data: pointer to netdev cast into an unsigned long
-+ */
-+static void atl1_watchdog(unsigned long data)
-+{
-+ struct atl1_adapter *adapter = (struct atl1_adapter *)data;
-+
-+ /* Reset the timer */
-+ mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
-+}
-+
-+/*
-+ * atl1_phy_config - Timer Call-back
-+ * @data: pointer to netdev cast into an unsigned long
-+ */
-+static void atl1_phy_config(unsigned long data)
-+{
-+ struct atl1_adapter *adapter = (struct atl1_adapter *)data;
-+ struct atl1_hw *hw = &adapter->hw;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&adapter->lock, flags);
-+ adapter->phy_timer_pending = false;
-+ atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
-+ atl1_write_phy_reg(hw, MII_ATLX_CR, hw->mii_1000t_ctrl_reg);
-+ atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
-+ spin_unlock_irqrestore(&adapter->lock, flags);
-+}
-+
-+/*
-+ * Orphaned vendor comment left intact here:
-+ * <vendor comment>
-+ * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
-+ * will assert. We do soft reset <0x1400=1> according
-+ * with the SPEC. BUT, it seemes that PCIE or DMA
-+ * state-machine will not be reset. DMAR_TO_INT will
-+ * assert again and again.
-+ * </vendor comment>
-+ */
-+
-+static int atl1_reset(struct atl1_adapter *adapter)
-+{
-+ int ret;
-+ ret = atl1_reset_hw(&adapter->hw);
-+ if (ret)
-+ return ret;
-+ return atl1_init_hw(&adapter->hw);
-+}
-+
-+static s32 atl1_up(struct atl1_adapter *adapter)
-+{
-+ struct net_device *netdev = adapter->netdev;
-+ int err;
-+ int irq_flags = IRQF_SAMPLE_RANDOM;
-+
-+ /* hardware has been reset, we need to reload some things */
-+ atlx_set_multi(netdev);
-+ atl1_init_ring_ptrs(adapter);
-+ atlx_restore_vlan(adapter);
-+ err = atl1_alloc_rx_buffers(adapter);
-+ if (unlikely(!err))
-+ /* no RX BUFFER allocated */
-+ return -ENOMEM;
-+
-+ if (unlikely(atl1_configure(adapter))) {
-+ err = -EIO;
-+ goto err_up;
-+ }
-+
-+ err = pci_enable_msi(adapter->pdev);
-+ if (err) {
-+ if (netif_msg_ifup(adapter))
-+ dev_info(&adapter->pdev->dev,
-+ "Unable to enable MSI: %d\n", err);
-+ irq_flags |= IRQF_SHARED;
-+ }
-+
-+ err = request_irq(adapter->pdev->irq, &atl1_intr, irq_flags,
-+ netdev->name, netdev);
-+ if (unlikely(err))
-+ goto err_up;
-+
-+ mod_timer(&adapter->watchdog_timer, jiffies);
-+ atlx_irq_enable(adapter);
-+ atl1_check_link(adapter);
-+ return 0;
-+
-+err_up:
-+ pci_disable_msi(adapter->pdev);
-+ /* free rx_buffers */
-+ atl1_clean_rx_ring(adapter);
-+ return err;
-+}
-+
-+static void atl1_down(struct atl1_adapter *adapter)
-+{
-+ struct net_device *netdev = adapter->netdev;
-+
-+ del_timer_sync(&adapter->watchdog_timer);
-+ del_timer_sync(&adapter->phy_config_timer);
-+ adapter->phy_timer_pending = false;
-+
-+ atlx_irq_disable(adapter);
-+ free_irq(adapter->pdev->irq, netdev);
-+ pci_disable_msi(adapter->pdev);
-+ atl1_reset_hw(&adapter->hw);
-+ adapter->cmb.cmb->int_stats = 0;
-+
-+ adapter->link_speed = SPEED_0;
-+ adapter->link_duplex = -1;
-+ netif_carrier_off(netdev);
-+ netif_stop_queue(netdev);
-+
-+ atl1_clean_tx_ring(adapter);
-+ atl1_clean_rx_ring(adapter);
-+}
-+
-+static void atl1_tx_timeout_task(struct work_struct *work)
-+{
-+ struct atl1_adapter *adapter =
-+ container_of(work, struct atl1_adapter, tx_timeout_task);
-+ struct net_device *netdev = adapter->netdev;
-+
-+ netif_device_detach(netdev);
-+ atl1_down(adapter);
-+ atl1_up(adapter);
-+ netif_device_attach(netdev);
-+}
-+
-+/*
-+ * atl1_change_mtu - Change the Maximum Transfer Unit
-+ * @netdev: network interface device structure
-+ * @new_mtu: new value for maximum frame size
-+ *
-+ * Returns 0 on success, negative on failure
-+ */
-+static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
-+{
-+ struct atl1_adapter *adapter = netdev_priv(netdev);
-+ int old_mtu = netdev->mtu;
-+ int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
-+
-+ if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
-+ (max_frame > MAX_JUMBO_FRAME_SIZE)) {
-+ if (netif_msg_link(adapter))
-+ dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
-+ return -EINVAL;
-+ }
-+
-+ adapter->hw.max_frame_size = max_frame;
-+ adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
-+ adapter->rx_buffer_len = (max_frame + 7) & ~7;
-+ adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
-+
-+ netdev->mtu = new_mtu;
-+ if ((old_mtu != new_mtu) && netif_running(netdev)) {
-+ atl1_down(adapter);
-+ atl1_up(adapter);
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * atl1_open - Called when a network interface is made active
-+ * @netdev: network interface device structure
-+ *
-+ * Returns 0 on success, negative value on failure
-+ *
-+ * The open entry point is called when a network interface is made
-+ * active by the system (IFF_UP). At this point all resources needed
-+ * for transmit and receive operations are allocated, the interrupt
-+ * handler is registered with the OS, the watchdog timer is started,
-+ * and the stack is notified that the interface is ready.
-+ */
-+static int atl1_open(struct net_device *netdev)
-+{
-+ struct atl1_adapter *adapter = netdev_priv(netdev);
-+ int err;
-+
-+ /* allocate transmit descriptors */
-+ err = atl1_setup_ring_resources(adapter);
-+ if (err)
-+ return err;
-+
-+ err = atl1_up(adapter);
-+ if (err)
-+ goto err_up;
-+
-+ return 0;
-+
-+err_up:
-+ atl1_reset(adapter);
-+ return err;
-+}
-+
-+/*
-+ * atl1_close - Disables a network interface
-+ * @netdev: network interface device structure
-+ *
-+ * Returns 0, this is not allowed to fail
-+ *
-+ * The close entry point is called when an interface is de-activated
-+ * by the OS. The hardware is still under the drivers control, but
-+ * needs to be disabled. A global MAC reset is issued to stop the
-+ * hardware, and all transmit and receive resources are freed.
-+ */
-+static int atl1_close(struct net_device *netdev)
-+{
-+ struct atl1_adapter *adapter = netdev_priv(netdev);
-+ atl1_down(adapter);
-+ atl1_free_ring_resources(adapter);
-+ return 0;
-+}
+ }
+
+- 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);
+
-+#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;
++ /* 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;
-+
-+ 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);
+ #ifdef CONFIG_PM
+ int retval = 0;
+ #endif
+@@ -5238,7 +5227,7 @@ e1000_resume(struct pci_dev *pdev)
+ {
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+- uint32_t err;
+ u32 err;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
+index 10af742..365626d 100644
+--- a/drivers/net/e1000/e1000_osdep.h
++++ b/drivers/net/e1000/e1000_osdep.h
+@@ -41,13 +41,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/sched.h>
+
+-typedef enum {
+-#undef FALSE
+- FALSE = 0,
+-#undef TRUE
+- TRUE = 1
+-} boolean_t;
+-
+ #ifdef DBG
+ #define DEBUGOUT(S) printk(KERN_DEBUG S "\n")
+ #define DEBUGOUT1(S, A...) printk(KERN_DEBUG S "\n", A)
+diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
+index 7fe2031..462351c 100644
+--- a/drivers/net/e1000e/82571.c
++++ b/drivers/net/e1000e/82571.c
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+
+ Intel PRO/1000 Linux driver
+- Copyright(c) 1999 - 2007 Intel Corporation.
++ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+@@ -29,6 +29,9 @@
+ /*
+ * 82571EB Gigabit Ethernet Controller
+ * 82571EB Gigabit Ethernet Controller (Fiber)
++ * 82571EB Dual Port Gigabit Mezzanine Adapter
++ * 82571EB Quad Port Gigabit Mezzanine Adapter
++ * 82571PT Gigabit PT Quad Port Server ExpressModule
+ * 82572EI Gigabit Ethernet Controller (Copper)
+ * 82572EI Gigabit Ethernet Controller (Fiber)
+ * 82572EI Gigabit Ethernet Controller
+@@ -72,7 +75,7 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val;
+
+- if (hw->media_type != e1000_media_type_copper) {
++ if (hw->phy.media_type != e1000_media_type_copper) {
+ phy->type = e1000_phy_none;
+ return 0;
+ }
+@@ -150,7 +153,8 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
+ if (((eecd >> 15) & 0x3) == 0x3) {
+ nvm->type = e1000_nvm_flash_hw;
+ nvm->word_size = 2048;
+- /* Autonomous Flash update bit must be cleared due
++ /*
++ * Autonomous Flash update bit must be cleared due
+ * to Flash update issue.
+ */
+ eecd &= ~E1000_EECD_AUPDEN;
+@@ -159,13 +163,18 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
+ }
+ /* Fall Through */
+ default:
+- nvm->type = e1000_nvm_eeprom_spi;
++ nvm->type = e1000_nvm_eeprom_spi;
+ size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
+ E1000_EECD_SIZE_EX_SHIFT);
+- /* Added to a constant, "size" becomes the left-shift value
++ /*
++ * Added to a constant, "size" becomes the left-shift value
+ * for setting word_size.
+ */
+ size += NVM_WORD_SIZE_BASE_SHIFT;
+
-+ 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;
-+
++ /* 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. */
+ /*
-+ * 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.
++ * If our nvm is an EEPROM, then we're done
++ * otherwise, commit the checksum to the flash NVM.
+ */
-+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-+ if (err) {
-+ dev_err(&pdev->dev, "no usable DMA configuration\n");
-+ goto err_dma;
-+ }
+ 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. */
+ /*
-+ * Mark all PCI regions associated with PCI device
-+ * pdev as being reserved by owner atl1_driver_name
++ * A check for invalid values: offset too large, too many words,
++ * and not enough words.
+ */
-+ err = pci_request_regions(pdev, ATLX_DRIVER_NAME);
-+ if (err)
-+ goto err_request_regions;
-+
+ 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
+ /*
-+ * 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;
-+
++ * 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. */
+ /*
-+ * patch for some L1 of old version,
-+ * the final version of L1 may not need these
-+ * patches
++ * Must acquire the MDIO ownership before MAC reset.
++ * Ownership defaults to firmware after a reset.
+ */
-+ /* atl1_pcie_patch(adapter); */
-+
-+ /* really reset GPHY core */
-+ iowrite16(0, adapter->hw.hw_addr + REG_PHY_ENABLE);
-+
+ 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.
+ /*
-+ * 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);
-+
++ * 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
+ /*
-+ * 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++) {
++ * 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
+ /*
-+ * 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;
-+
++ * 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
+ /*
-+ * 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 @@
++ * 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
+/*
-+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
-+ * Copyright(c) 2006 - 2007 Chris Snook <csnook at redhat.com>
-+ * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
-+ *
-+ * Derived from Intel e1000 driver
-+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the Free
-+ * Software Foundation; either version 2 of the License, or (at your option)
-+ * any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc., 59
-+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ */
-+
-+#ifndef ATL1_H
-+#define ATL1_H
-+
-+#include <linux/compiler.h>
-+#include <linux/ethtool.h>
-+#include <linux/if_vlan.h>
-+#include <linux/mii.h>
-+#include <linux/module.h>
-+#include <linux/skbuff.h>
-+#include <linux/spinlock.h>
-+#include <linux/timer.h>
-+#include <linux/types.h>
-+#include <linux/workqueue.h>
-+
-+#include "atlx.h"
-+
-+#define ATLX_DRIVER_NAME "atl1"
-+
-+MODULE_DESCRIPTION("Atheros L1 Gigabit Ethernet Driver");
-+
-+#define atlx_adapter atl1_adapter
-+#define atlx_check_for_link atl1_check_for_link
-+#define atlx_check_link atl1_check_link
-+#define atlx_hash_mc_addr atl1_hash_mc_addr
-+#define atlx_hash_set atl1_hash_set
-+#define atlx_hw atl1_hw
-+#define atlx_mii_ioctl atl1_mii_ioctl
-+#define atlx_read_phy_reg atl1_read_phy_reg
-+#define atlx_set_mac atl1_set_mac
-+#define atlx_set_mac_addr atl1_set_mac_addr
-+
-+struct atl1_adapter;
-+struct atl1_hw;
-+
-+/* function prototypes needed by multiple files */
-+u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr);
-+void atl1_hash_set(struct atl1_hw *hw, u32 hash_value);
-+s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data);
-+void atl1_set_mac_addr(struct atl1_hw *hw);
-+static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
-+ int cmd);
-+static u32 atl1_check_link(struct atl1_adapter *adapter);
-+
-+extern const struct ethtool_ops atl1_ethtool_ops;
-+
-+/* hardware definitions specific to L1 */
-+
-+/* Block IDLE Status Register */
-+#define IDLE_STATUS_RXMAC 0x1
-+#define IDLE_STATUS_TXMAC 0x2
-+#define IDLE_STATUS_RXQ 0x4
-+#define IDLE_STATUS_TXQ 0x8
-+#define IDLE_STATUS_DMAR 0x10
-+#define IDLE_STATUS_DMAW 0x20
-+#define IDLE_STATUS_SMB 0x40
-+#define IDLE_STATUS_CMB 0x80
-+
-+/* MDIO Control Register */
-+#define MDIO_WAIT_TIMES 30
-+
-+/* MAC Control Register */
-+#define MAC_CTRL_TX_PAUSE 0x10000
-+#define MAC_CTRL_SCNT 0x20000
-+#define MAC_CTRL_SRST_TX 0x40000
-+#define MAC_CTRL_TX_SIMURST 0x80000
-+#define MAC_CTRL_SPEED_SHIFT 20
-+#define MAC_CTRL_SPEED_MASK 0x300000
-+#define MAC_CTRL_SPEED_1000 0x2
-+#define MAC_CTRL_SPEED_10_100 0x1
-+#define MAC_CTRL_DBG_TX_BKPRESURE 0x400000
-+#define MAC_CTRL_TX_HUGE 0x800000
-+#define MAC_CTRL_RX_CHKSUM_EN 0x1000000
-+#define MAC_CTRL_DBG 0x8000000
-+
-+/* Wake-On-Lan control register */
-+#define WOL_CLK_SWITCH_EN 0x8000
-+#define WOL_PT5_EN 0x200000
-+#define WOL_PT6_EN 0x400000
-+#define WOL_PT5_MATCH 0x8000000
-+#define WOL_PT6_MATCH 0x10000000
-+
-+/* WOL Length ( 2 DWORD ) */
-+#define REG_WOL_PATTERN_LEN 0x14A4
-+#define WOL_PT_LEN_MASK 0x7F
-+#define WOL_PT0_LEN_SHIFT 0
-+#define WOL_PT1_LEN_SHIFT 8
-+#define WOL_PT2_LEN_SHIFT 16
-+#define WOL_PT3_LEN_SHIFT 24
-+#define WOL_PT4_LEN_SHIFT 0
-+#define WOL_PT5_LEN_SHIFT 8
-+#define WOL_PT6_LEN_SHIFT 16
-+
-+/* Internal SRAM Partition Registers, low 32 bits */
-+#define REG_SRAM_RFD_LEN 0x1504
-+#define REG_SRAM_RRD_ADDR 0x1508
-+#define REG_SRAM_RRD_LEN 0x150C
-+#define REG_SRAM_TPD_ADDR 0x1510
-+#define REG_SRAM_TPD_LEN 0x1514
-+#define REG_SRAM_TRD_ADDR 0x1518
-+#define REG_SRAM_TRD_LEN 0x151C
-+#define REG_SRAM_RXF_ADDR 0x1520
-+#define REG_SRAM_RXF_LEN 0x1524
-+#define REG_SRAM_TXF_ADDR 0x1528
-+#define REG_SRAM_TXF_LEN 0x152C
-+#define REG_SRAM_TCPH_PATH_ADDR 0x1530
-+#define SRAM_TCPH_ADDR_MASK 0xFFF
-+#define SRAM_TCPH_ADDR_SHIFT 0
-+#define SRAM_PATH_ADDR_MASK 0xFFF
-+#define SRAM_PATH_ADDR_SHIFT 16
-+
-+/* Load Ptr Register */
-+#define REG_LOAD_PTR 0x1534
-+
-+/* Descriptor Control registers, low 32 bits */
-+#define REG_DESC_RFD_ADDR_LO 0x1544
-+#define REG_DESC_RRD_ADDR_LO 0x1548
-+#define REG_DESC_TPD_ADDR_LO 0x154C
-+#define REG_DESC_CMB_ADDR_LO 0x1550
-+#define REG_DESC_SMB_ADDR_LO 0x1554
-+#define REG_DESC_RFD_RRD_RING_SIZE 0x1558
-+#define DESC_RFD_RING_SIZE_MASK 0x7FF
-+#define DESC_RFD_RING_SIZE_SHIFT 0
-+#define DESC_RRD_RING_SIZE_MASK 0x7FF
-+#define DESC_RRD_RING_SIZE_SHIFT 16
-+#define REG_DESC_TPD_RING_SIZE 0x155C
-+#define DESC_TPD_RING_SIZE_MASK 0x3FF
-+#define DESC_TPD_RING_SIZE_SHIFT 0
-+
-+/* TXQ Control Register */
-+#define REG_TXQ_CTRL 0x1580
-+#define TXQ_CTRL_TPD_BURST_NUM_SHIFT 0
-+#define TXQ_CTRL_TPD_BURST_NUM_MASK 0x1F
-+#define TXQ_CTRL_EN 0x20
-+#define TXQ_CTRL_ENH_MODE 0x40
-+#define TXQ_CTRL_TPD_FETCH_TH_SHIFT 8
-+#define TXQ_CTRL_TPD_FETCH_TH_MASK 0x3F
-+#define TXQ_CTRL_TXF_BURST_NUM_SHIFT 16
-+#define TXQ_CTRL_TXF_BURST_NUM_MASK 0xFFFF
-+
-+/* Jumbo packet Threshold for task offload */
-+#define REG_TX_JUMBO_TASK_TH_TPD_IPG 0x1584
-+#define TX_JUMBO_TASK_TH_MASK 0x7FF
-+#define TX_JUMBO_TASK_TH_SHIFT 0
-+#define TX_TPD_MIN_IPG_MASK 0x1F
-+#define TX_TPD_MIN_IPG_SHIFT 16
-+
-+/* RXQ Control Register */
-+#define REG_RXQ_CTRL 0x15A0
-+#define RXQ_CTRL_RFD_BURST_NUM_SHIFT 0
-+#define RXQ_CTRL_RFD_BURST_NUM_MASK 0xFF
-+#define RXQ_CTRL_RRD_BURST_THRESH_SHIFT 8
-+#define RXQ_CTRL_RRD_BURST_THRESH_MASK 0xFF
-+#define RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT 16
-+#define RXQ_CTRL_RFD_PREF_MIN_IPG_MASK 0x1F
-+#define RXQ_CTRL_CUT_THRU_EN 0x40000000
-+#define RXQ_CTRL_EN 0x80000000
-+
-+/* Rx jumbo packet threshold and rrd retirement timer */
-+#define REG_RXQ_JMBOSZ_RRDTIM 0x15A4
-+#define RXQ_JMBOSZ_TH_MASK 0x7FF
-+#define RXQ_JMBOSZ_TH_SHIFT 0
-+#define RXQ_JMBO_LKAH_MASK 0xF
-+#define RXQ_JMBO_LKAH_SHIFT 11
-+#define RXQ_RRD_TIMER_MASK 0xFFFF
-+#define RXQ_RRD_TIMER_SHIFT 16
-+
-+/* RFD flow control register */
-+#define REG_RXQ_RXF_PAUSE_THRESH 0x15A8
-+#define RXQ_RXF_PAUSE_TH_HI_SHIFT 16
-+#define RXQ_RXF_PAUSE_TH_HI_MASK 0xFFF
-+#define RXQ_RXF_PAUSE_TH_LO_SHIFT 0
-+#define RXQ_RXF_PAUSE_TH_LO_MASK 0xFFF
-+
-+/* RRD flow control register */
-+#define REG_RXQ_RRD_PAUSE_THRESH 0x15AC
-+#define RXQ_RRD_PAUSE_TH_HI_SHIFT 0
-+#define RXQ_RRD_PAUSE_TH_HI_MASK 0xFFF
-+#define RXQ_RRD_PAUSE_TH_LO_SHIFT 16
-+#define RXQ_RRD_PAUSE_TH_LO_MASK 0xFFF
-+
-+/* DMA Engine Control Register */
-+#define REG_DMA_CTRL 0x15C0
-+#define DMA_CTRL_DMAR_IN_ORDER 0x1
-+#define DMA_CTRL_DMAR_ENH_ORDER 0x2
-+#define DMA_CTRL_DMAR_OUT_ORDER 0x4
-+#define DMA_CTRL_RCB_VALUE 0x8
-+#define DMA_CTRL_DMAR_BURST_LEN_SHIFT 4
-+#define DMA_CTRL_DMAR_BURST_LEN_MASK 7
-+#define DMA_CTRL_DMAW_BURST_LEN_SHIFT 7
-+#define DMA_CTRL_DMAW_BURST_LEN_MASK 7
-+#define DMA_CTRL_DMAR_EN 0x400
-+#define DMA_CTRL_DMAW_EN 0x800
-+
-+/* CMB/SMB Control Register */
-+#define REG_CSMB_CTRL 0x15D0
-+#define CSMB_CTRL_CMB_NOW 1
-+#define CSMB_CTRL_SMB_NOW 2
-+#define CSMB_CTRL_CMB_EN 4
-+#define CSMB_CTRL_SMB_EN 8
-+
-+/* CMB DMA Write Threshold Register */
-+#define REG_CMB_WRITE_TH 0x15D4
-+#define CMB_RRD_TH_SHIFT 0
-+#define CMB_RRD_TH_MASK 0x7FF
-+#define CMB_TPD_TH_SHIFT 16
-+#define CMB_TPD_TH_MASK 0x7FF
-+
-+/* RX/TX count-down timer to trigger CMB-write. 2us resolution. */
-+#define REG_CMB_WRITE_TIMER 0x15D8
-+#define CMB_RX_TM_SHIFT 0
-+#define CMB_RX_TM_MASK 0xFFFF
-+#define CMB_TX_TM_SHIFT 16
-+#define CMB_TX_TM_MASK 0xFFFF
-+
-+/* Number of packet received since last CMB write */
-+#define REG_CMB_RX_PKT_CNT 0x15DC
-+
-+/* Number of packet transmitted since last CMB write */
-+#define REG_CMB_TX_PKT_CNT 0x15E0
-+
-+/* SMB auto DMA timer register */
-+#define REG_SMB_TIMER 0x15E4
-+
-+/* Mailbox Register */
-+#define REG_MAILBOX 0x15F0
-+#define MB_RFD_PROD_INDX_SHIFT 0
-+#define MB_RFD_PROD_INDX_MASK 0x7FF
-+#define MB_RRD_CONS_INDX_SHIFT 11
-+#define MB_RRD_CONS_INDX_MASK 0x7FF
-+#define MB_TPD_PROD_INDX_SHIFT 22
-+#define MB_TPD_PROD_INDX_MASK 0x3FF
-+
-+/* Interrupt Status Register */
-+#define ISR_SMB 0x1
-+#define ISR_TIMER 0x2
-+#define ISR_MANUAL 0x4
-+#define ISR_RXF_OV 0x8
-+#define ISR_RFD_UNRUN 0x10
-+#define ISR_RRD_OV 0x20
-+#define ISR_TXF_UNRUN 0x40
-+#define ISR_LINK 0x80
-+#define ISR_HOST_RFD_UNRUN 0x100
-+#define ISR_HOST_RRD_OV 0x200
-+#define ISR_DMAR_TO_RST 0x400
-+#define ISR_DMAW_TO_RST 0x800
-+#define ISR_GPHY 0x1000
-+#define ISR_RX_PKT 0x10000
-+#define ISR_TX_PKT 0x20000
-+#define ISR_TX_DMA 0x40000
-+#define ISR_RX_DMA 0x80000
-+#define ISR_CMB_RX 0x100000
-+#define ISR_CMB_TX 0x200000
-+#define ISR_MAC_RX 0x400000
-+#define ISR_MAC_TX 0x800000
-+#define ISR_DIS_SMB 0x20000000
-+#define ISR_DIS_DMA 0x40000000
-+
-+/* Normal Interrupt mask */
-+#define IMR_NORMAL_MASK (\
-+ ISR_SMB |\
-+ ISR_GPHY |\
-+ ISR_PHY_LINKDOWN|\
-+ ISR_DMAR_TO_RST |\
-+ ISR_DMAW_TO_RST |\
-+ ISR_CMB_TX |\
-+ ISR_CMB_RX)
-+
-+/* Debug Interrupt Mask (enable all interrupt) */
-+#define IMR_DEBUG_MASK (\
-+ ISR_SMB |\
-+ ISR_TIMER |\
-+ ISR_MANUAL |\
-+ ISR_RXF_OV |\
-+ ISR_RFD_UNRUN |\
-+ ISR_RRD_OV |\
-+ ISR_TXF_UNRUN |\
-+ ISR_LINK |\
-+ ISR_CMB_TX |\
-+ ISR_CMB_RX |\
-+ ISR_RX_PKT |\
-+ ISR_TX_PKT |\
-+ ISR_MAC_RX |\
-+ ISR_MAC_TX)
-+
-+#define MEDIA_TYPE_1000M_FULL 1
-+#define MEDIA_TYPE_100M_FULL 2
-+#define MEDIA_TYPE_100M_HALF 3
-+#define MEDIA_TYPE_10M_FULL 4
-+#define MEDIA_TYPE_10M_HALF 5
-+
-+#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F /* All but 1000-Half */
-+
-+#define MAX_JUMBO_FRAME_SIZE 10240
-+
-+#define ATL1_EEDUMP_LEN 48
-+
-+/* Statistics counters collected by the MAC */
-+struct stats_msg_block {
-+ /* rx */
-+ u32 rx_ok; /* good RX packets */
-+ u32 rx_bcast; /* good RX broadcast packets */
-+ u32 rx_mcast; /* good RX multicast packets */
-+ u32 rx_pause; /* RX pause frames */
-+ u32 rx_ctrl; /* RX control packets other than pause frames */
-+ u32 rx_fcs_err; /* RX packets with bad FCS */
-+ u32 rx_len_err; /* RX packets with length != actual size */
-+ u32 rx_byte_cnt; /* good bytes received. FCS is NOT included */
-+ u32 rx_runt; /* RX packets < 64 bytes with good FCS */
-+ u32 rx_frag; /* RX packets < 64 bytes with bad FCS */
-+ u32 rx_sz_64; /* 64 byte RX packets */
-+ u32 rx_sz_65_127;
-+ u32 rx_sz_128_255;
-+ u32 rx_sz_256_511;
-+ u32 rx_sz_512_1023;
-+ u32 rx_sz_1024_1518;
-+ u32 rx_sz_1519_max; /* 1519 byte to MTU RX packets */
-+ u32 rx_sz_ov; /* truncated RX packets > MTU */
-+ u32 rx_rxf_ov; /* frames dropped due to RX FIFO overflow */
-+ u32 rx_rrd_ov; /* frames dropped due to RRD overflow */
-+ u32 rx_align_err; /* alignment errors */
-+ u32 rx_bcast_byte_cnt; /* RX broadcast bytes, excluding FCS */
-+ u32 rx_mcast_byte_cnt; /* RX multicast bytes, excluding FCS */
-+ u32 rx_err_addr; /* packets dropped due to address filtering */
-+
-+ /* tx */
-+ u32 tx_ok; /* good TX packets */
-+ u32 tx_bcast; /* good TX broadcast packets */
-+ u32 tx_mcast; /* good TX multicast packets */
-+ u32 tx_pause; /* TX pause frames */
-+ u32 tx_exc_defer; /* TX packets deferred excessively */
-+ u32 tx_ctrl; /* TX control frames, excluding pause frames */
-+ u32 tx_defer; /* TX packets deferred */
-+ u32 tx_byte_cnt; /* bytes transmitted, FCS is NOT included */
-+ u32 tx_sz_64; /* 64 byte TX packets */
-+ u32 tx_sz_65_127;
-+ u32 tx_sz_128_255;
-+ u32 tx_sz_256_511;
-+ u32 tx_sz_512_1023;
-+ u32 tx_sz_1024_1518;
-+ u32 tx_sz_1519_max; /* 1519 byte to MTU TX packets */
-+ u32 tx_1_col; /* packets TX after a single collision */
-+ u32 tx_2_col; /* packets TX after multiple collisions */
-+ u32 tx_late_col; /* TX packets with late collisions */
-+ u32 tx_abort_col; /* TX packets aborted w/excessive collisions */
-+ u32 tx_underrun; /* TX packets aborted due to TX FIFO underrun
-+ * or TRD FIFO underrun */
-+ u32 tx_rd_eop; /* reads beyond the EOP into the next frame
-+ * when TRD was not written timely */
-+ u32 tx_len_err; /* TX packets where length != actual size */
-+ u32 tx_trunc; /* TX packets truncated due to size > MTU */
-+ u32 tx_bcast_byte; /* broadcast bytes transmitted, excluding FCS */
-+ u32 tx_mcast_byte; /* multicast bytes transmitted, excluding FCS */
-+ u32 smb_updated; /* 1: SMB Updated. This is used by software to
-+ * indicate the statistics update. Software
-+ * should clear this bit after retrieving the
-+ * statistics information. */
-+};
-+
-+/* Coalescing Message Block */
-+struct coals_msg_block {
-+ u32 int_stats; /* interrupt status */
-+ u16 rrd_prod_idx; /* TRD Producer Index. */
-+ u16 rfd_cons_idx; /* RFD Consumer Index. */
-+ u16 update; /* Selene sets this bit every time it DMAs the
-+ * CMB to host memory. Software should clear
-+ * this bit when CMB info is processed. */
-+ u16 tpd_cons_idx; /* TPD Consumer Index. */
-+};
-+
-+/* RRD descriptor */
-+struct rx_return_desc {
-+ u8 num_buf; /* Number of RFD buffers used by the received packet */
-+ u8 resved;
-+ u16 buf_indx; /* RFD Index of the first buffer */
-+ union {
-+ u32 valid;
-+ struct {
-+ u16 rx_chksum;
-+ u16 pkt_size;
-+ } xsum_sz;
-+ } xsz;
-+
-+ u16 pkt_flg; /* Packet flags */
-+ u16 err_flg; /* Error flags */
-+ u16 resved2;
-+ u16 vlan_tag; /* VLAN TAG */
-+};
-+
-+#define PACKET_FLAG_ETH_TYPE 0x0080
-+#define PACKET_FLAG_VLAN_INS 0x0100
-+#define PACKET_FLAG_ERR 0x0200
-+#define PACKET_FLAG_IPV4 0x0400
-+#define PACKET_FLAG_UDP 0x0800
-+#define PACKET_FLAG_TCP 0x1000
-+#define PACKET_FLAG_BCAST 0x2000
-+#define PACKET_FLAG_MCAST 0x4000
-+#define PACKET_FLAG_PAUSE 0x8000
-+
-+#define ERR_FLAG_CRC 0x0001
-+#define ERR_FLAG_CODE 0x0002
-+#define ERR_FLAG_DRIBBLE 0x0004
-+#define ERR_FLAG_RUNT 0x0008
-+#define ERR_FLAG_OV 0x0010
-+#define ERR_FLAG_TRUNC 0x0020
-+#define ERR_FLAG_IP_CHKSUM 0x0040
-+#define ERR_FLAG_L4_CHKSUM 0x0080
-+#define ERR_FLAG_LEN 0x0100
-+#define ERR_FLAG_DES_ADDR 0x0200
-+
-+/* RFD descriptor */
-+struct rx_free_desc {
-+ __le64 buffer_addr; /* Address of the descriptor's data buffer */
-+ __le16 buf_len; /* Size of the receive buffer in host memory */
-+ u16 coalese; /* Update consumer index to host after the
-+ * reception of this frame */
-+ /* __attribute__ ((packed)) is required */
-+} __attribute__ ((packed));
-+
++ * 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
+/*
-+ * 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-+
++ * 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
+ */
-+
-+/* 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)
-+
++#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 */
+/*
-+ * 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
++ * Number of times we will attempt to autonegotiate before downshifting if we
++ * are the master
+ */
-+struct atl1_ring_header {
-+ void *desc; /* virtual address */
-+ dma_addr_t dma; /* physical address*/
-+ unsigned int size; /* length in bytes */
-+};
-+
+ #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 */
+/*
-+ * atl1_buffer is wrapper around a pointer to a socket buffer
-+ * so a DMA handle can be stored along with the skb
++ * Number of times we will attempt to autonegotiate before downshifting if we
++ * are the slave
+ */
-+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;
-+};
+ #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
+
-+/* 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;
++#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 */
+};
+
-+/* 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;
-+
+ /* 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;
+
-+ u16 dev_rev;
-+
-+ /* spi flash */
-+ u8 flash_vendor;
-+
-+ u8 mac_addr[ETH_ALEN];
-+ u8 perm_mac_addr[ETH_ALEN];
-+
-+ bool phy_configured;
-+};
-+
-+struct atl1_adapter {
-+ struct net_device *netdev;
-+ struct pci_dev *pdev;
-+ struct net_device_stats net_stats;
-+ struct atl1_sft_stats soft_stats;
-+ struct vlan_group *vlgrp;
-+ u32 rx_buffer_len;
-+ u32 wol;
-+ u16 link_speed;
-+ u16 link_duplex;
-+ spinlock_t lock;
-+ struct work_struct tx_timeout_task;
-+ struct work_struct link_chg_task;
-+ struct work_struct pcie_dma_to_rst_task;
-+ struct timer_list watchdog_timer;
-+ struct timer_list phy_config_timer;
-+ bool phy_timer_pending;
-+
-+ /* all descriptor rings' memory */
-+ struct atl1_ring_header ring_header;
-+
-+ /* TX */
-+ struct atl1_tpd_ring tpd_ring;
-+ spinlock_t mb_lock;
-+
-+ /* RX */
-+ struct atl1_rfd_ring rfd_ring;
-+ struct atl1_rrd_ring rrd_ring;
-+ u64 hw_csum_err;
-+ u64 hw_csum_good;
-+ u32 msg_enable;
-+ u16 imt; /* interrupt moderator timer (2us resolution) */
-+ u16 ict; /* interrupt clear timer (2us resolution */
-+ struct mii_if_info mii; /* MII interface info */
-+
-+ u32 bd_number; /* board number */
-+ bool pci_using_64;
-+ struct atl1_hw hw;
-+ struct atl1_smb smb;
-+ struct atl1_cmb cmb;
-+};
-+
-+#endif /* ATL1_H */
-diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c
-new file mode 100644
-index 0000000..f06b854
---- /dev/null
-+++ b/drivers/net/atlx/atlx.c
-@@ -0,0 +1,256 @@
-+/* atlx.c -- common functions for Attansic network drivers
-+ *
-+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
-+ * Copyright(c) 2006 - 2007 Chris Snook <csnook at redhat.com>
-+ * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
-+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
-+ *
-+ * Derived from Intel e1000 driver
-+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the Free
-+ * Software Foundation; either version 2 of the License, or (at your option)
-+ * any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc., 59
-+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ */
-+
-+/* Including this file like a header is a temporary hack, I promise. -- CHS */
-+#ifndef ATLX_C
-+#define ATLX_C
-+
-+#include <linux/device.h>
-+#include <linux/errno.h>
-+#include <linux/etherdevice.h>
-+#include <linux/if.h>
-+#include <linux/netdevice.h>
-+#include <linux/socket.h>
-+#include <linux/sockios.h>
-+#include <linux/spinlock.h>
-+#include <linux/string.h>
-+#include <linux/types.h>
-+#include <linux/workqueue.h>
-+
-+#include "atlx.h"
-+
-+static struct atlx_spi_flash_dev flash_table[] = {
-+/* MFR_NAME WRSR READ PRGM WREN WRDI RDSR RDID SEC_ERS CHIP_ERS */
-+ {"Atmel", 0x00, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52, 0x62},
-+ {"SST", 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20, 0x60},
-+ {"ST", 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xAB, 0xD8, 0xC7},
-+};
-+
-+static int atlx_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-+{
-+ switch (cmd) {
-+ case SIOCGMIIPHY:
-+ case SIOCGMIIREG:
-+ case SIOCSMIIREG:
-+ return atlx_mii_ioctl(netdev, ifr, cmd);
-+ default:
-+ return -EOPNOTSUPP;
-+ }
-+}
+ 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
+/*
-+ * 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;
-+}
++ * 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;
+
-+static void atlx_check_for_link(struct atlx_adapter *adapter)
-+{
-+ struct net_device *netdev = adapter->netdev;
-+ u16 phy_data = 0;
++ /* 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;
+
-+ 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);
+ 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;
+
-+ /* 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);
-+ }
+ /* 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;
+ }
-+ 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);
+
+ 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;
+ }
-+}
-+
-+/*
-+ * 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);
-+}
+
+- /* 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;
+
-+/*
-+ * 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);
-+}
+ /* 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;
+
-+static void atlx_clear_phy_int(struct atlx_adapter *adapter)
-+{
-+ u16 phy_data;
-+ unsigned long flags;
+ 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;
+
-+ spin_lock_irqsave(&adapter->lock, flags);
-+ atlx_read_phy_reg(&adapter->hw, 19, &phy_data);
-+ spin_unlock_irqrestore(&adapter->lock, flags);
-+}
++ 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;
+
-+/*
-+ * 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;
-+}
++ 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;
+
-+/*
-+ * 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);
-+}
++ 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 */
+
-+/*
-+ * atlx_link_chg_task - deal with link change event Out of interrupt context
-+ */
-+static void atlx_link_chg_task(struct work_struct *work)
++ 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 atlx_adapter *adapter;
-+ unsigned long flags;
++ struct e1000_adapter *adapter = netdev_priv(netdev);
+
-+ adapter = container_of(work, struct atlx_adapter, link_chg_task);
++ if (adapter->itr_setting <= 3)
++ ec->rx_coalesce_usecs = adapter->itr_setting;
++ else
++ ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting;
+
-+ spin_lock_irqsave(&adapter->lock, flags);
-+ atlx_check_link(adapter);
-+ spin_unlock_irqrestore(&adapter->lock, flags);
++ return 0;
+}
+
-+static void atlx_vlan_rx_register(struct net_device *netdev,
-+ struct vlan_group *grp)
++static int e1000_set_coalesce(struct net_device *netdev,
++ struct ethtool_coalesce *ec)
+{
-+ struct atlx_adapter *adapter = netdev_priv(netdev);
-+ unsigned long flags;
-+ u32 ctrl;
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
+
-+ spin_lock_irqsave(&adapter->lock, flags);
-+ /* atlx_irq_disable(adapter); FIXME: confirm/remove */
-+ adapter->vlgrp = grp;
++ 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 (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);
++ if (ec->rx_coalesce_usecs <= 3) {
++ adapter->itr = 20000;
++ adapter->itr_setting = ec->rx_coalesce_usecs;
+ } 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);
++ adapter->itr = (1000000 / ec->rx_coalesce_usecs);
++ adapter->itr_setting = adapter->itr & ~3;
+ }
+
-+ /* atlx_irq_enable(adapter); FIXME */
-+ spin_unlock_irqrestore(&adapter->lock, flags);
-+}
++ if (adapter->itr_setting != 0)
++ ew32(ITR, 1000000000 / (adapter->itr * 256));
++ else
++ ew32(ITR, 0);
+
-+static void atlx_restore_vlan(struct atlx_adapter *adapter)
-+{
-+ atlx_vlan_rx_register(adapter->netdev, adapter->vlgrp);
++ return 0;
+}
+
-+#endif /* ATLX_C */
-diff --git a/drivers/net/atlx/atlx.h b/drivers/net/atlx/atlx.h
-new file mode 100644
-index 0000000..3be7c09
---- /dev/null
-+++ b/drivers/net/atlx/atlx.h
-@@ -0,0 +1,506 @@
-+/* atlx_hw.h -- common hardware definitions for Attansic network drivers
-+ *
-+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
-+ * Copyright(c) 2006 - 2007 Chris Snook <csnook at redhat.com>
-+ * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
-+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
-+ *
-+ * Derived from Intel e1000 driver
-+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the Free
-+ * Software Foundation; either version 2 of the License, or (at your option)
-+ * any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc., 59
-+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ */
-+
-+#ifndef ATLX_H
-+#define ATLX_H
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+
-+#define ATLX_DRIVER_VERSION "2.1.1"
-+MODULE_AUTHOR("Xiong Huang <xiong.huang at atheros.com>, \
-+ Chris Snook <csnook at redhat.com>, Jay Cliburn <jcliburn at gmail.com>");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION(ATLX_DRIVER_VERSION);
-+
-+#define ATLX_ERR_PHY 2
-+#define ATLX_ERR_PHY_SPEED 7
-+#define ATLX_ERR_PHY_RES 8
-+
-+#define SPEED_0 0xffff
-+#define SPEED_10 10
-+#define SPEED_100 100
-+#define SPEED_1000 1000
-+#define HALF_DUPLEX 1
-+#define FULL_DUPLEX 2
-+
-+#define MEDIA_TYPE_AUTO_SENSOR 0
-+
-+/* register definitions */
-+#define REG_PM_CTRLSTAT 0x44
-+
-+#define REG_PCIE_CAP_LIST 0x58
-+
-+#define REG_VPD_CAP 0x6C
-+#define VPD_CAP_ID_MASK 0xFF
-+#define VPD_CAP_ID_SHIFT 0
-+#define VPD_CAP_NEXT_PTR_MASK 0xFF
-+#define VPD_CAP_NEXT_PTR_SHIFT 8
-+#define VPD_CAP_VPD_ADDR_MASK 0x7FFF
-+#define VPD_CAP_VPD_ADDR_SHIFT 16
-+#define VPD_CAP_VPD_FLAG 0x80000000
-+
-+#define REG_VPD_DATA 0x70
-+
-+#define REG_SPI_FLASH_CTRL 0x200
-+#define SPI_FLASH_CTRL_STS_NON_RDY 0x1
-+#define SPI_FLASH_CTRL_STS_WEN 0x2
-+#define SPI_FLASH_CTRL_STS_WPEN 0x80
-+#define SPI_FLASH_CTRL_DEV_STS_MASK 0xFF
-+#define SPI_FLASH_CTRL_DEV_STS_SHIFT 0
-+#define SPI_FLASH_CTRL_INS_MASK 0x7
-+#define SPI_FLASH_CTRL_INS_SHIFT 8
-+#define SPI_FLASH_CTRL_START 0x800
-+#define SPI_FLASH_CTRL_EN_VPD 0x2000
-+#define SPI_FLASH_CTRL_LDSTART 0x8000
-+#define SPI_FLASH_CTRL_CS_HI_MASK 0x3
-+#define SPI_FLASH_CTRL_CS_HI_SHIFT 16
-+#define SPI_FLASH_CTRL_CS_HOLD_MASK 0x3
-+#define SPI_FLASH_CTRL_CS_HOLD_SHIFT 18
-+#define SPI_FLASH_CTRL_CLK_LO_MASK 0x3
-+#define SPI_FLASH_CTRL_CLK_LO_SHIFT 20
-+#define SPI_FLASH_CTRL_CLK_HI_MASK 0x3
-+#define SPI_FLASH_CTRL_CLK_HI_SHIFT 22
-+#define SPI_FLASH_CTRL_CS_SETUP_MASK 0x3
-+#define SPI_FLASH_CTRL_CS_SETUP_SHIFT 24
-+#define SPI_FLASH_CTRL_EROM_PGSZ_MASK 0x3
-+#define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT 26
-+#define SPI_FLASH_CTRL_WAIT_READY 0x10000000
-+
-+#define REG_SPI_ADDR 0x204
-+
-+#define REG_SPI_DATA 0x208
-+
-+#define REG_SPI_FLASH_CONFIG 0x20C
-+#define SPI_FLASH_CONFIG_LD_ADDR_MASK 0xFFFFFF
-+#define SPI_FLASH_CONFIG_LD_ADDR_SHIFT 0
-+#define SPI_FLASH_CONFIG_VPD_ADDR_MASK 0x3
-+#define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT 24
-+#define SPI_FLASH_CONFIG_LD_EXIST 0x4000000
-+
-+#define REG_SPI_FLASH_OP_PROGRAM 0x210
-+#define REG_SPI_FLASH_OP_SC_ERASE 0x211
-+#define REG_SPI_FLASH_OP_CHIP_ERASE 0x212
-+#define REG_SPI_FLASH_OP_RDID 0x213
-+#define REG_SPI_FLASH_OP_WREN 0x214
-+#define REG_SPI_FLASH_OP_RDSR 0x215
-+#define REG_SPI_FLASH_OP_WRSR 0x216
-+#define REG_SPI_FLASH_OP_READ 0x217
-+
-+#define REG_TWSI_CTRL 0x218
-+#define TWSI_CTRL_LD_OFFSET_MASK 0xFF
-+#define TWSI_CTRL_LD_OFFSET_SHIFT 0
-+#define TWSI_CTRL_LD_SLV_ADDR_MASK 0x7
-+#define TWSI_CTRL_LD_SLV_ADDR_SHIFT 8
-+#define TWSI_CTRL_SW_LDSTART 0x800
-+#define TWSI_CTRL_HW_LDSTART 0x1000
-+#define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x7F
-+#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT 15
-+#define TWSI_CTRL_LD_EXIST 0x400000
-+#define TWSI_CTRL_READ_FREQ_SEL_MASK 0x3
-+#define TWSI_CTRL_READ_FREQ_SEL_SHIFT 23
-+#define TWSI_CTRL_FREQ_SEL_100K 0
-+#define TWSI_CTRL_FREQ_SEL_200K 1
-+#define TWSI_CTRL_FREQ_SEL_300K 2
-+#define TWSI_CTRL_FREQ_SEL_400K 3
-+#define TWSI_CTRL_SMB_SLV_ADDR /* FIXME: define or remove */
-+#define TWSI_CTRL_WRITE_FREQ_SEL_MASK 0x3
-+#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT 24
-+
-+#define REG_PCIE_DEV_MISC_CTRL 0x21C
-+#define PCIE_DEV_MISC_CTRL_EXT_PIPE 0x2
-+#define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS 0x1
-+#define PCIE_DEV_MISC_CTRL_SPIROM_EXIST 0x4
-+#define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN 0x8
-+#define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN 0x10
-+
-+#define REG_PCIE_PHYMISC 0x1000
-+#define PCIE_PHYMISC_FORCE_RCV_DET 0x4
-+
-+#define REG_PCIE_DLL_TX_CTRL1 0x1104
-+#define PCIE_DLL_TX_CTRL1_SEL_NOR_CLK 0x400
-+#define PCIE_DLL_TX_CTRL1_DEF 0x568
-+
-+#define REG_LTSSM_TEST_MODE 0x12FC
-+#define LTSSM_TEST_MODE_DEF 0x6500
-+
-+/* Master Control Register */
-+#define REG_MASTER_CTRL 0x1400
-+#define MASTER_CTRL_SOFT_RST 0x1
-+#define MASTER_CTRL_MTIMER_EN 0x2
-+#define MASTER_CTRL_ITIMER_EN 0x4
-+#define MASTER_CTRL_MANUAL_INT 0x8
-+#define MASTER_CTRL_REV_NUM_SHIFT 16
-+#define MASTER_CTRL_REV_NUM_MASK 0xFF
-+#define MASTER_CTRL_DEV_ID_SHIFT 24
-+#define MASTER_CTRL_DEV_ID_MASK 0xFF
-+
-+/* Timer Initial Value Register */
-+#define REG_MANUAL_TIMER_INIT 0x1404
-+
-+/* IRQ Moderator Timer Initial Value Register */
-+#define REG_IRQ_MODU_TIMER_INIT 0x1408
-+
-+#define REG_PHY_ENABLE 0x140C
-+
-+/* IRQ Anti-Lost Timer Initial Value Register */
-+#define REG_CMBDISDMA_TIMER 0x140E
-+
-+/* Block IDLE Status Register */
-+#define REG_IDLE_STATUS 0x1410
-+
-+/* MDIO Control Register */
-+#define REG_MDIO_CTRL 0x1414
-+#define MDIO_DATA_MASK 0xFFFF
-+#define MDIO_DATA_SHIFT 0
-+#define MDIO_REG_ADDR_MASK 0x1F
-+#define MDIO_REG_ADDR_SHIFT 16
-+#define MDIO_RW 0x200000
-+#define MDIO_SUP_PREAMBLE 0x400000
-+#define MDIO_START 0x800000
-+#define MDIO_CLK_SEL_SHIFT 24
-+#define MDIO_CLK_25_4 0
-+#define MDIO_CLK_25_6 2
-+#define MDIO_CLK_25_8 3
-+#define MDIO_CLK_25_10 4
-+#define MDIO_CLK_25_14 5
-+#define MDIO_CLK_25_20 6
-+#define MDIO_CLK_25_28 7
-+#define MDIO_BUSY 0x8000000
-+
-+/* MII PHY Status Register */
-+#define REG_PHY_STATUS 0x1418
-+
-+/* BIST Control and Status Register0 (for the Packet Memory) */
-+#define REG_BIST0_CTRL 0x141C
-+#define BIST0_NOW 0x1
-+#define BIST0_SRAM_FAIL 0x2
-+#define BIST0_FUSE_FLAG 0x4
-+#define REG_BIST1_CTRL 0x1420
-+#define BIST1_NOW 0x1
-+#define BIST1_SRAM_FAIL 0x2
-+#define BIST1_FUSE_FLAG 0x4
-+
-+/* SerDes Lock Detect Control and Status Register */
-+#define REG_SERDES_LOCK 0x1424
-+#define SERDES_LOCK_DETECT 1
-+#define SERDES_LOCK_DETECT_EN 2
-+
-+/* MAC Control Register */
-+#define REG_MAC_CTRL 0x1480
-+#define MAC_CTRL_TX_EN 1
-+#define MAC_CTRL_RX_EN 2
-+#define MAC_CTRL_TX_FLOW 4
-+#define MAC_CTRL_RX_FLOW 8
-+#define MAC_CTRL_LOOPBACK 0x10
-+#define MAC_CTRL_DUPLX 0x20
-+#define MAC_CTRL_ADD_CRC 0x40
-+#define MAC_CTRL_PAD 0x80
-+#define MAC_CTRL_LENCHK 0x100
-+#define MAC_CTRL_HUGE_EN 0x200
-+#define MAC_CTRL_PRMLEN_SHIFT 10
-+#define MAC_CTRL_PRMLEN_MASK 0xF
-+#define MAC_CTRL_RMV_VLAN 0x4000
-+#define MAC_CTRL_PROMIS_EN 0x8000
-+#define MAC_CTRL_MC_ALL_EN 0x2000000
-+#define MAC_CTRL_BC_EN 0x4000000
-+
-+/* MAC IPG/IFG Control Register */
-+#define REG_MAC_IPG_IFG 0x1484
-+#define MAC_IPG_IFG_IPGT_SHIFT 0
-+#define MAC_IPG_IFG_IPGT_MASK 0x7F
-+#define MAC_IPG_IFG_MIFG_SHIFT 8
-+#define MAC_IPG_IFG_MIFG_MASK 0xFF
-+#define MAC_IPG_IFG_IPGR1_SHIFT 16
-+#define MAC_IPG_IFG_IPGR1_MASK 0x7F
-+#define MAC_IPG_IFG_IPGR2_SHIFT 24
-+#define MAC_IPG_IFG_IPGR2_MASK 0x7F
-+
-+/* MAC STATION ADDRESS */
-+#define REG_MAC_STA_ADDR 0x1488
-+
-+/* Hash table for multicast address */
-+#define REG_RX_HASH_TABLE 0x1490
-+
-+/* MAC Half-Duplex Control Register */
-+#define REG_MAC_HALF_DUPLX_CTRL 0x1498
-+#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT 0
-+#define MAC_HALF_DUPLX_CTRL_LCOL_MASK 0x3FF
-+#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12
-+#define MAC_HALF_DUPLX_CTRL_RETRY_MASK 0xF
-+#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN 0x10000
-+#define MAC_HALF_DUPLX_CTRL_NO_BACK_C 0x20000
-+#define MAC_HALF_DUPLX_CTRL_NO_BACK_P 0x40000
-+#define MAC_HALF_DUPLX_CTRL_ABEBE 0x80000
-+#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT 20
-+#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK 0xF
-+#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24
-+#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK 0xF
-+
-+/* Maximum Frame Length Control Register */
-+#define REG_MTU 0x149C
-+
-+/* Wake-On-Lan control register */
-+#define REG_WOL_CTRL 0x14A0
-+#define WOL_PATTERN_EN 0x1
-+#define WOL_PATTERN_PME_EN 0x2
-+#define WOL_MAGIC_EN 0x4
-+#define WOL_MAGIC_PME_EN 0x8
-+#define WOL_LINK_CHG_EN 0x10
-+#define WOL_LINK_CHG_PME_EN 0x20
-+#define WOL_PATTERN_ST 0x100
-+#define WOL_MAGIC_ST 0x200
-+#define WOL_LINKCHG_ST 0x400
-+#define WOL_PT0_EN 0x10000
-+#define WOL_PT1_EN 0x20000
-+#define WOL_PT2_EN 0x40000
-+#define WOL_PT3_EN 0x80000
-+#define WOL_PT4_EN 0x100000
-+#define WOL_PT0_MATCH 0x1000000
-+#define WOL_PT1_MATCH 0x2000000
-+#define WOL_PT2_MATCH 0x4000000
-+#define WOL_PT3_MATCH 0x8000000
-+#define WOL_PT4_MATCH 0x10000000
-+
-+/* Internal SRAM Partition Register, high 32 bits */
-+#define REG_SRAM_RFD_ADDR 0x1500
-+
-+/* Descriptor Control register, high 32 bits */
-+#define REG_DESC_BASE_ADDR_HI 0x1540
-+
-+/* Interrupt Status Register */
-+#define REG_ISR 0x1600
-+#define ISR_UR_DETECTED 0x1000000
-+#define ISR_FERR_DETECTED 0x2000000
-+#define ISR_NFERR_DETECTED 0x4000000
-+#define ISR_CERR_DETECTED 0x8000000
-+#define ISR_PHY_LINKDOWN 0x10000000
-+#define ISR_DIS_INT 0x80000000
-+
-+/* Interrupt Mask Register */
-+#define REG_IMR 0x1604
-+
-+#define REG_RFD_RRD_IDX 0x1800
-+#define REG_TPD_IDX 0x1804
-+
-+/* MII definitions */
-+
-+/* PHY Common Register */
-+#define MII_ATLX_CR 0x09
-+#define MII_ATLX_SR 0x0A
-+#define MII_ATLX_ESR 0x0F
-+#define MII_ATLX_PSCR 0x10
-+#define MII_ATLX_PSSR 0x11
-+
-+/* PHY Control Register */
-+#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100,
-+ * 00=10
-+ */
-+#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
-+#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
-+#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
-+#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
-+#define MII_CR_POWER_DOWN 0x0800 /* Power down */
-+#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
-+#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100,
-+ * 00=10
-+ */
-+#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
-+#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
-+#define MII_CR_SPEED_MASK 0x2040
-+#define MII_CR_SPEED_1000 0x0040
-+#define MII_CR_SPEED_100 0x2000
-+#define MII_CR_SPEED_10 0x0000
-+
-+/* PHY Status Register */
-+#define MII_SR_EXTENDED_CAPS 0x0001 /* Ext register capabilities */
-+#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
-+#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
-+#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */
-+#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */
-+#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
-+#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
-+#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext stat info in Reg 0x0F */
-+#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */
-+#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */
-+#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */
-+#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */
-+#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */
-+#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
-+#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
-+
-+/* Link partner ability register */
-+#define MII_LPA_SLCT 0x001f /* Same as advertise selector */
-+#define MII_LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
-+#define MII_LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
-+#define MII_LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
-+#define MII_LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
-+#define MII_LPA_100BASE4 0x0200 /* 100BASE-T4 */
-+#define MII_LPA_PAUSE 0x0400 /* PAUSE */
-+#define MII_LPA_ASYPAUSE 0x0800 /* Asymmetrical PAUSE */
-+#define MII_LPA_RFAULT 0x2000 /* Link partner faulted */
-+#define MII_LPA_LPACK 0x4000 /* Link partner acked us */
-+#define MII_LPA_NPAGE 0x8000 /* Next page bit */
-+
-+/* Autoneg Advertisement Register */
-+#define MII_AR_SELECTOR_FIELD 0x0001 /* IEEE 802.3 CSMA/CD */
-+#define MII_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
-+#define MII_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
-+#define MII_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
-+#define MII_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
-+#define MII_AR_100T4_CAPS 0x0200 /* 100T4 Capable */
-+#define MII_AR_PAUSE 0x0400 /* Pause operation desired */
-+#define MII_AR_ASM_DIR 0x0800 /* Asymmetric Pause Dir bit */
-+#define MII_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */
-+#define MII_AR_NEXT_PAGE 0x8000 /* Next Page ability support */
-+#define MII_AR_SPEED_MASK 0x01E0
-+#define MII_AR_DEFAULT_CAP_MASK 0x0DE0
-+
-+/* 1000BASE-T Control Register */
-+#define MII_ATLX_CR_1000T_HD_CAPS 0x0100 /* Adv 1000T HD cap */
-+#define MII_ATLX_CR_1000T_FD_CAPS 0x0200 /* Adv 1000T FD cap */
-+#define MII_ATLX_CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device,
-+ * 0=DTE device */
-+#define MII_ATLX_CR_1000T_MS_VALUE 0x0800 /* 1=Config PHY as Master,
-+ * 0=Configure PHY as Slave */
-+#define MII_ATLX_CR_1000T_MS_ENABLE 0x1000 /* 1=Man Master/Slave config,
-+ * 0=Auto Master/Slave config
-+ */
-+#define MII_ATLX_CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
-+#define MII_ATLX_CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */
-+#define MII_ATLX_CR_1000T_TEST_MODE_2 0x4000 /* Master Xmit Jitter test */
-+#define MII_ATLX_CR_1000T_TEST_MODE_3 0x6000 /* Slave Xmit Jitter test */
-+#define MII_ATLX_CR_1000T_TEST_MODE_4 0x8000 /* Xmitter Distortion test */
-+#define MII_ATLX_CR_1000T_SPEED_MASK 0x0300
-+#define MII_ATLX_CR_1000T_DEFAULT_CAP_MASK 0x0300
-+
-+/* 1000BASE-T Status Register */
-+#define MII_ATLX_SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */
-+#define MII_ATLX_SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */
-+#define MII_ATLX_SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
-+#define MII_ATLX_SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */
-+#define MII_ATLX_SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master
-+ * 0=Slave
-+ */
-+#define MII_ATLX_SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config
-+ * fault */
-+#define MII_ATLX_SR_1000T_REMOTE_RX_STATUS_SHIFT 12
-+#define MII_ATLX_SR_1000T_LOCAL_RX_STATUS_SHIFT 13
-+
-+/* Extended Status Register */
-+#define MII_ATLX_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */
-+#define MII_ATLX_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */
-+#define MII_ATLX_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */
-+#define MII_ATLX_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */
-+
-+/* ATLX PHY Specific Control Register */
-+#define MII_ATLX_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Func disabled */
-+#define MII_ATLX_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enbld */
-+#define MII_ATLX_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */
-+#define MII_ATLX_PSCR_MAC_POWERDOWN 0x0008
-+#define MII_ATLX_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low
-+ * 0=CLK125 toggling
-+ */
-+#define MII_ATLX_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5,
-+ * Manual MDI configuration
-+ */
-+#define MII_ATLX_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */
-+#define MII_ATLX_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover
-+ * 100BASE-TX/10BASE-T: MDI
-+ * Mode */
-+#define MII_ATLX_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled
-+ * all speeds.
-+ */
-+#define MII_ATLX_PSCR_10BT_EXT_DIST_ENABLE 0x0080 /* 1=Enable Extended
-+ * 10BASE-T distance
-+ * (Lower 10BASE-T RX
-+ * Threshold)
-+ * 0=Normal 10BASE-T RX
-+ * Threshold
-+ */
-+#define MII_ATLX_PSCR_MII_5BIT_ENABLE 0x0100 /* 1=5-Bit interface in
-+ * 100BASE-TX
-+ * 0=MII interface in
-+ * 100BASE-TX
-+ */
-+#define MII_ATLX_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler dsbl */
-+#define MII_ATLX_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */
-+#define MII_ATLX_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
-+#define MII_ATLX_PSCR_POLARITY_REVERSAL_SHIFT 1
-+#define MII_ATLX_PSCR_AUTO_X_MODE_SHIFT 5
-+#define MII_ATLX_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7
-+
-+/* ATLX PHY Specific Status Register */
-+#define MII_ATLX_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */
-+#define MII_ATLX_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */
-+#define MII_ATLX_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */
-+#define MII_ATLX_PSSR_10MBS 0x0000 /* 00=10Mbs */
-+#define MII_ATLX_PSSR_100MBS 0x4000 /* 01=100Mbs */
-+#define MII_ATLX_PSSR_1000MBS 0x8000 /* 10=1000Mbs */
-+
-+/* PCI Command Register Bit Definitions */
-+#define PCI_REG_COMMAND 0x04 /* PCI Command Register */
-+#define CMD_IO_SPACE 0x0001
-+#define CMD_MEMORY_SPACE 0x0002
-+#define CMD_BUS_MASTER 0x0004
-+
-+/* Wake Up Filter Control */
-+#define ATLX_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
-+#define ATLX_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
-+#define ATLX_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
-+#define ATLX_WUFC_MC 0x00000008 /* Multicast Wakeup Enable */
-+#define ATLX_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
-+
-+#define ADVERTISE_10_HALF 0x0001
-+#define ADVERTISE_10_FULL 0x0002
-+#define ADVERTISE_100_HALF 0x0004
-+#define ADVERTISE_100_FULL 0x0008
-+#define ADVERTISE_1000_HALF 0x0010
-+#define ADVERTISE_1000_FULL 0x0020
-+#define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds */
-+#define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds */
-+
-+#define PHY_AUTO_NEG_TIME 45 /* 4.5 Seconds */
-+#define PHY_FORCE_TIME 20 /* 2.0 Seconds */
-+
-+/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA */
-+#define EEPROM_SUM 0xBABA
-+#define NODE_ADDRESS_SIZE 6
+ 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;
+
-+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;
+ 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;
+};
+
-+#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;
+ 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;
- 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)));
+ 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;
+ };
- write_reg(ioaddr, CMR2, CMR2_NULL);
- }
-diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
-index 504b7ce..3634b5f 100644
---- a/drivers/net/au1000_eth.c
-+++ b/drivers/net/au1000_eth.c
-@@ -701,7 +701,7 @@ static struct net_device * au1000_probe(int port_num)
- aup->mii_bus.write = mdiobus_write;
- aup->mii_bus.reset = mdiobus_reset;
- aup->mii_bus.name = "au1000_eth_mii";
-- aup->mii_bus.id = aup->mac_id;
-+ snprintf(aup->mii_bus.id, MII_BUS_ID_SIZE, "%x", aup->mac_id);
- aup->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
- for(i = 0; i < PHY_MAX_ADDR; ++i)
- aup->mii_bus.irq[i] = PHY_POLL;
-@@ -709,11 +709,11 @@ static struct net_device * au1000_probe(int port_num)
- /* if known, set corresponding PHY IRQs */
- #if defined(AU1XXX_PHY_STATIC_CONFIG)
- # if defined(AU1XXX_PHY0_IRQ)
-- if (AU1XXX_PHY0_BUSID == aup->mii_bus.id)
-+ if (AU1XXX_PHY0_BUSID == aup->mac_id)
- aup->mii_bus.irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ;
- # endif
- # if defined(AU1XXX_PHY1_IRQ)
-- if (AU1XXX_PHY1_BUSID == aup->mii_bus.id)
-+ if (AU1XXX_PHY1_BUSID == aup->mac_id)
- aup->mii_bus.irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ;
- # endif
- #endif
-diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
-index 194949a..0b4adf4 100644
---- a/drivers/net/ax88796.c
-+++ b/drivers/net/ax88796.c
-@@ -1005,3 +1005,4 @@ module_exit(axdrv_exit);
- MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");
- MODULE_AUTHOR("Ben Dooks, <ben at simtec.co.uk>");
- MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:ax88796");
-diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
-index 26b2dd5..4fec858 100644
---- a/drivers/net/bfin_mac.c
-+++ b/drivers/net/bfin_mac.c
-@@ -47,6 +47,7 @@
- MODULE_AUTHOR(DRV_AUTHOR);
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION(DRV_DESC);
-+MODULE_ALIAS("platform:bfin_mac");
+ #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 @@
+ /*******************************************************************************
- #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,
-+ },
- };
+ Intel PRO/1000 Linux driver
+- Copyright(c) 1999 - 2007 Intel Corporation.
++ Copyright(c) 1999 - 2008 Intel Corporation.
- static int __init bfin_mac_init(void)
-@@ -1106,3 +1108,4 @@ static void __exit bfin_mac_cleanup(void)
+ 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;
}
- 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;
+-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)
-- if (dev->nd_net != &init_net)
-+ if (dev_net(dev) != &init_net)
- goto out;
+ udelay(1);
- 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 (phy->wait_for_link) {
++ if (phy->autoneg_wait_to_complete) {
+ hw_dbg(hw, "Waiting for forced speed/duplex link on IFE phy.\n");
-- if (bond_dev->nd_net != &init_net)
-+ if (dev_net(bond_dev) != &init_net)
- goto out;
+ 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;
- 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;
+- /* 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 (dev->nd_net != &init_net)
-+ if (dev_net(dev) != &init_net)
- goto out;
+- /* 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);
- 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;
+- /* 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;
-- /* 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;
+- /* Configure LCD from extended configuration
+- * region. */
++ /* Configure LCD from extended configuration region. */
- arp = arp_hdr(skb);
-@@ -3068,8 +3065,6 @@ out:
+ /* 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;
- #ifdef CONFIG_PROC_FS
+- /* 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);
--#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;
+- /* 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);
-- if (event_dev->nd_net != &init_net)
-+ if (dev_net(event_dev) != &init_net)
- return NOTIFY_DONE;
+- /* 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;
- 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;
+ 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;
-+ 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.
+ 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)
*/
- spin_lock(&cp->rx_inuse_lock);
-- list_splice(&cp->rx_inuse_list, &list);
-- INIT_LIST_HEAD(&cp->rx_inuse_list);
-+ list_splice_init(&cp->rx_inuse_list, &list);
- spin_unlock(&cp->rx_inuse_lock);
- #else
- spin_lock(&cp->rx_spare_lock);
-- list_splice(&cp->rx_inuse_list, &list);
-- INIT_LIST_HEAD(&cp->rx_inuse_list);
-+ list_splice_init(&cp->rx_inuse_list, &list);
- spin_unlock(&cp->rx_spare_lock);
- #endif
- list_for_each_safe(elem, tmp, &list) {
-@@ -573,8 +570,7 @@ static void cas_spare_recover(struct cas *cp, const gfp_t flags)
- /* make a local copy of the list */
- INIT_LIST_HEAD(&list);
- spin_lock(&cp->rx_inuse_lock);
-- list_splice(&cp->rx_inuse_list, &list);
-- INIT_LIST_HEAD(&cp->rx_inuse_list);
-+ list_splice_init(&cp->rx_inuse_list, &list);
- spin_unlock(&cp->rx_inuse_lock);
- list_for_each_safe(elem, tmp, &list) {
-diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
-index c85194f..2b5740b 100644
---- a/drivers/net/cpmac.c
-+++ b/drivers/net/cpmac.c
-@@ -42,6 +42,7 @@
- MODULE_AUTHOR("Eugene Konev <ejka at imfi.kspu.ru>");
- MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)");
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:cpmac");
+ 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);
- 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)
+- /* 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)
{
- 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 = {};
+- 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);
-- 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)
+ /* unable to acquire PCS lock */
+@@ -1970,7 +2021,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
+ }
- 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)
- }
+ /**
+- * 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);
- cpmac_mii.phy_mask = ~(mask | 0x80000000);
-+ snprintf(cpmac_mii.id, MII_BUS_ID_SIZE, "0");
+- /* 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);
- res = mdiobus_register(&cpmac_mii);
- if (res)
-diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
-index eb305a0..4fdb13f 100644
---- a/drivers/net/cxgb3/adapter.h
-+++ b/drivers/net/cxgb3/adapter.h
-@@ -43,7 +43,6 @@
- #include <linux/mutex.h>
- #include <linux/bitops.h>
- #include "t3cdev.h"
--#include <asm/semaphore.h>
- #include <asm/io.h>
+@@ -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 @@
+ /*******************************************************************************
- 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);
+ Intel PRO/1000 Linux driver
+- Copyright(c) 1999 - 2007 Intel Corporation.
++ Copyright(c) 1999 - 2008 Intel Corporation.
-- /* 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");
+ 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 {
- /* 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;
- }
+ #define E1000_FACTPS_MNGCG 0x20000000
-+/*
-+ * 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)
+-#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)
{
-- 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;
+ u32 rar_low, rar_high;
- 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)
+- /* 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)
{
- 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);
+ u32 hash_bit, hash_reg, mta;
- #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 @@
+- /* 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;
- #include <linux/list.h>
- #include <asm/atomic.h>
--#include <asm/semaphore.h>
- #include <linux/netdevice.h>
- #include <linux/proc_fs.h>
- #include <linux/skbuff.h>
-diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
-index ddc30c4..c062aac 100644
---- a/drivers/net/defxx.c
-+++ b/drivers/net/defxx.c
-@@ -971,7 +971,8 @@ static int __devinit dfx_driver_init(struct net_device *dev,
- int alloc_size; /* total buffer size needed */
- char *top_v, *curr_v; /* virtual addrs into memory block */
- dma_addr_t top_p, curr_p; /* physical addrs into memory block */
-- u32 data, le32; /* host data register value */
-+ u32 data; /* host data register value */
-+ __le32 le32;
- char *board_name = NULL;
+- /* 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++;
- 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;
- };
+- /* 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;
- 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]; };
+- /* 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;
- struct e1000_tx_ring {
- /* pointer to the descriptor ring memory */
-@@ -186,9 +186,9 @@ struct e1000_tx_ring {
- struct e1000_buffer *buffer_info;
+- /* 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;
- spinlock_t tx_lock;
-- uint16_t tdh;
-- uint16_t tdt;
-- boolean_t last_tx_tso;
-+ u16 tdh;
-+ u16 tdt;
-+ bool last_tx_tso;
- };
+- /* 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)
- struct e1000_rx_ring {
-@@ -213,8 +213,8 @@ struct e1000_rx_ring {
- /* cpu for rx queue */
- int cpu;
+ mac->get_link_status = 0;
-- uint16_t rdh;
-- uint16_t rdt;
-+ u16 rdh;
-+ u16 rdt;
- };
+- /* 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);
- #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;
+- /* 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;
+ }
- struct work_struct reset_task;
-- uint8_t fc_autoneg;
-+ u8 fc_autoneg;
+- /* 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);
- 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;
+- /* 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);
- /* 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;
+- /* 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);
-- 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;
+- /* 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;
- /* OS defined structs */
-@@ -330,19 +329,19 @@ struct e1000_adapter {
- struct e1000_phy_info phy_info;
- struct e1000_phy_stats phy_stats;
+- /* 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)
+ }
-- uint32_t test_icr;
-+ u32 test_icr;
- struct e1000_tx_ring test_tx_ring;
- struct e1000_rx_ring test_rx_ring;
+ 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;
- int msg_enable;
-- boolean_t have_msi;
-+ bool have_msi;
+ return 0;
+ }
+@@ -630,7 +648,8 @@ s32 e1000e_setup_link(struct e1000_hw *hw)
+ struct e1000_mac_info *mac = &hw->mac;
+ s32 ret_val;
- /* 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;
- };
+- /* 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;
+ }
- 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;
- }
+- /* 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;
--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)
- }
+- 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);
- 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;
- }
+ /* Call the necessary media_type subroutine to configure the link. */
+ ret_val = mac->ops.setup_physical_interface(hw);
+ if (ret_val)
+ return ret_val;
--static uint32_t
-+static u32
- e1000_get_tx_csum(struct net_device *netdev)
- {
- return (netdev->features & NETIF_F_HW_CSUM) != 0;
- }
+- /* 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);
- 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);
+- ew32(FCTTV, mac->fc_pause_time);
++ ew32(FCTTV, hw->fc.pause_time);
-@@ -335,7 +335,7 @@ e1000_set_tx_csum(struct net_device *netdev, uint32_t data)
+ 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;
- 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;
+- /* 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;
- DPRINTK(PROBE, INFO, "TSO is %s\n", data ? "Enabled" : "Disabled");
-- adapter->tso_force = TRUE;
-+ adapter->tso_force = true;
- return 0;
- }
+- /* 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;
--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)
- }
+- /* 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);
- 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)
+- /* 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)
{
- #define E1000_REGS_LEN 32
-- return E1000_REGS_LEN * sizeof(uint32_t);
-+ return E1000_REGS_LEN * sizeof(u32);
- }
+- struct e1000_mac_info *mac = &hw->mac;
+ u32 fcrtl = 0, fcrth = 0;
- static void
-@@ -384,10 +384,10 @@ e1000_get_regs(struct net_device *netdev,
+- /* 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_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;
+- struct e1000_mac_info *mac = &hw->mac;
+ u32 ctrl;
-- memset(p, 0, E1000_REGS_LEN * sizeof(uint32_t));
-+ memset(p, 0, E1000_REGS_LEN * sizeof(u32));
+ ctrl = er32(CTRL);
- regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
+- /* 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);
-@@ -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);
+- 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 {
- 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,
+- if (hw->media_type == e1000_media_type_copper)
++ if (hw->phy.media_type == e1000_media_type_copper)
+ ret_val = e1000e_force_mac_fc(hw);
}
- 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;
+@@ -988,13 +1019,15 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ return ret_val;
+ }
- 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;
+- /* 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;
+ }
-- 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]);
+- /* 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;
-- memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset & 1),
-+ memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1),
- eeprom->len);
- kfree(eeprom_buff);
+- /* 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");
+ }
-@@ -523,14 +523,14 @@ e1000_get_eeprom(struct net_device *netdev,
+- /* 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)
+ }
- static int
- e1000_set_eeprom(struct net_device *netdev,
-- struct ethtool_eeprom *eeprom, uint8_t *bytes)
-+ struct ethtool_eeprom *eeprom, u8 *bytes)
+ 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)
{
- 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;
+ u32 ctrl;
- if (eeprom->len == 0)
- return -EOPNOTSUPP;
-@@ -590,7 +590,7 @@ e1000_get_drvinfo(struct net_device *netdev,
+- 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)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
- char firmware_version[32];
-- uint16_t eeprom_data;
-+ u16 eeprom_data;
+ u32 ctrl;
- 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;
+- 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;
-- 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);
+- /* 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)
+ }
-- 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);
+ /**
+- * 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;
-@@ -728,13 +728,13 @@ err_setup:
- return err;
- }
+- /* 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;
--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;
+- data[i] = (er32(EERD) >>
+- E1000_NVM_RW_REG_DATA);
++ data[i] = (er32(EERD) >> E1000_NVM_RW_REG_DATA);
+ }
- 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;
- }
+ 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;
--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;
+- /* 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)
- 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)
+ e1000_standby_nvm(hw);
- 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;
+- /* 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;
- /* 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)
- }
+@@ -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);
- 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;
+ /* 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)
+ }
- *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 (mac_addr_offset)
+- hw->dev_spec.e82571.alt_mac_addr_is_present = 1;
++ hw->dev_spec.e82571.alt_mac_addr_is_present = 1;
}
- /* 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)
+ for (i = 0; i < ETH_ALEN; i += 2) {
+@@ -2244,7 +2236,7 @@ bool e1000e_check_mng_mode(struct e1000_hw *hw)
}
- 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;
+ /**
+- * 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;
+ }
- /* 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;
+- /* 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;
- 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;
+- /* 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;
+ }
- /* 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)
+-s32 e1000e_read_part_num(struct e1000_hw *hw, u32 *part_num)
++s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num)
{
-- uint32_t ctrl_reg;
-- uint16_t phy_reg;
-+ u32 ctrl_reg;
-+ u16 phy_reg;
-
- /* Setup the Device Control Register for PHY loopback test. */
+ 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);
-@@ -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;
+ 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;
-- adapter->hw.autoneg = FALSE;
-+ adapter->hw.autoneg = false;
+ 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 @@
+ /*******************************************************************************
- 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;
+ Intel PRO/1000 Linux driver
+- Copyright(c) 1999 - 2007 Intel Corporation.
++ Copyright(c) 1999 - 2008 Intel Corporation.
- 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;
+ 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 @@
- 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;
+ #include "e1000.h"
- 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)
- }
+-#define DRV_VERSION "0.2.0"
++#define DRV_VERSION "0.2.1"
+ char e1000e_driver_name[] = "e1000e";
+ const char e1000e_driver_version[] = DRV_VERSION;
- 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:
+@@ -82,7 +82,7 @@ static int e1000_desc_unused(struct e1000_ring *ring)
}
- 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;
+ /**
+- * 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;
+ }
- /* 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)
+- /* 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);
- 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);
+- /* 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;
+ }
- set_bit(__E1000_TESTING, &adapter->flags);
- if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
- /* Offline tests */
+- /* 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);
- /* 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;
+- /* 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++;
- DPRINTK(HW, INFO, "offline testing starting\n");
+- /* 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);
-@@ -1876,7 +1877,7 @@ e1000_led_blink_callback(unsigned long data)
+- 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;
}
- 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)
+@@ -581,22 +591,23 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
+ }
- 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;
+ 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);
+ }
}
- /* BUG_ON(i != E1000_STATS_LEN); */
+ 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;
}
- 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;
+@@ -677,21 +688,28 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ skb_put(skb, length);
- 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 @@
+ {
+- /* 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]);
- #include "e1000_hw.h"
+- /* 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;
--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);
+ ps_page = &buffer_info->ps_pages[0];
--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);
+- /* 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);
+ }
- /* 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};
+ return IRQ_HANDLED;
+@@ -890,26 +911,31 @@ static irqreturn_t e1000_intr(int irq, void *data)
+ if (!icr)
+ return IRQ_NONE; /* Not our interrupt */
- 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)
+- /* 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)
{
- 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)
+ 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)
{
-- uint32_t ret_val;
-- uint16_t phy_saved_data;
-+ u32 ret_val;
-+ u16 phy_saved_data;
+ struct e1000_hw *hw = &adapter->hw;
- DEBUGFUNC("e1000_phy_init_script");
+- if (atomic_dec_and_test(&adapter->irq_sem)) {
+- ew32(IMS, IMS_ENABLE_MASK);
+- e1e_flush();
+- }
++ ew32(IMS, IMS_ENABLE_MASK);
++ e1e_flush();
+ }
-@@ -271,7 +272,7 @@ e1000_phy_init_script(struct e1000_hw *hw)
- e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
+ /**
+@@ -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);
+ }
+ }
- if (hw->mac_type == e1000_82547) {
-- uint16_t fused, fine, coarse;
-+ u16 fused, fine, coarse;
+@@ -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);
+ }
+ }
- /* 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)
+@@ -1353,9 +1373,11 @@ static void e1000_set_itr(struct e1000_adapter *adapter)
- 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;
+ 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:
- /* capable of receiving management packets to the host */
- if (hw->mac_type >= e1000_82571)
-- hw->has_manc2h = TRUE;
-+ hw->has_manc2h = true;
+ /**
+ * 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;
- /* 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;
+- /* 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;
- if (hw->mac_type > e1000_82544)
-- hw->has_smbus = TRUE;
-+ hw->has_smbus = true;
+- 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);
- 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;
+ 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;
- DEBUGFUNC("e1000_set_media_type");
+- e1000_irq_disable(adapter);
++ if (!test_bit(__E1000_DOWN, &adapter->state))
++ e1000_irq_disable(adapter);
+ adapter->vlgrp = grp;
- if (hw->mac_type != e1000_82543) {
- /* tbi_compatibility is only valid on 82543 */
-- hw->tbi_compatibility_en = FALSE;
-+ hw->tbi_compatibility_en = false;
- }
+ if (grp) {
+@@ -1517,7 +1545,8 @@ static void e1000_vlan_rx_register(struct net_device *netdev,
+ }
+ }
- 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;
+- e1000_irq_enable(adapter);
++ if (!test_bit(__E1000_DOWN, &adapter->state))
++ e1000_irq_enable(adapter);
+ }
- DEBUGFUNC("e1000_reset_hw");
+ static void e1000_restore_vlan(struct e1000_adapter *adapter)
+@@ -1546,9 +1575,11 @@ static void e1000_init_manageability(struct e1000_adapter *adapter)
-@@ -569,7 +570,7 @@ e1000_reset_hw(struct e1000_hw *hw)
- E1000_WRITE_FLUSH(hw);
+ manc = er32(MANC);
- /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
-- hw->tbi_compatibility_on = FALSE;
-+ hw->tbi_compatibility_on = false;
+- /* 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)
- /* 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)
- }
+ /* 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);
- 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;
+ /* Program the Transmit Control Register */
+@@ -1608,22 +1639,24 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
+ (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
- /* 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;
+ 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);
+ }
- DEBUGFUNC("e1000_init_hw");
+ /* 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);
+ }
-@@ -1019,7 +1020,7 @@ e1000_init_hw(struct e1000_hw *hw)
+ 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)
+ }
- 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;
+ ew32(RCTL, rctl);
++ /* just started the receive unit, no need to restart */
++ adapter->flags &= ~FLAG_RX_RESTART_NOW;
+ }
- DEBUGFUNC("e1000_adjust_serdes_amplitude");
+ /**
+@@ -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));
-@@ -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;
+ 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();
- DEBUGFUNC("e1000_setup_link");
+- /* 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;
-@@ -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;
+- /* 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);
- DEBUGFUNC("e1000_setup_fiber_serdes_link");
+- /* 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)
+ }
-@@ -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)
+ /**
+- * 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)
{
-- uint32_t ctrl;
-- int32_t ret_val;
-- uint16_t phy_data;
-+ u32 ctrl;
-+ s32 ret_val;
-+ u16 phy_data;
+- 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);
+ }
- DEBUGFUNC("e1000_copper_link_preconfig");
+@@ -1923,7 +1965,7 @@ static void e1000_set_multi(struct net_device *netdev)
+ mc_ptr = mc_ptr->next;
+ }
-@@ -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;
+- 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);
+ }
+ }
- return E1000_SUCCESS;
+ /**
+- * 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));
}
-@@ -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");
+ /**
+@@ -1967,9 +2007,11 @@ void e1000e_power_up_phy(struct e1000_adapter *adapter)
+ u16 mii_reg = 0;
-@@ -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)
- }
+ /* 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;
- /* 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;
+ /* non-copper PHY? */
+- if (adapter->hw.media_type != e1000_media_type_copper)
++ if (adapter->hw.phy.media_type != e1000_media_type_copper)
+ return;
- DEBUGFUNC("e1000_copper_link_ggp_setup");
+ /* 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;
-@@ -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)
+ /* 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)
{
-- int32_t ret_val;
-- uint16_t phy_data;
-+ s32 ret_val;
-+ u16 phy_data;
+ 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;
- DEBUGFUNC("e1000_copper_link_mgp_setup");
+- ew32(PBA, adapter->pba);
++ /* reset Packet Buffer Allocation to default */
++ ew32(PBA, pba);
-@@ -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;
+- 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;
- DEBUGFUNC("e1000_copper_link_autoneg");
+- /* 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;
-@@ -1892,7 +1893,7 @@ e1000_copper_link_autoneg(struct e1000_hw *hw)
- }
- }
+- /* 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)
+ }
-- 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");
+- /* 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));
- if (hw->mac_type >= e1000_82544) {
-@@ -1932,7 +1933,7 @@ e1000_copper_link_postconfig(struct e1000_hw *hw)
+- 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;
- /* 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;
+ 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;
- DEBUGFUNC("e1000_setup_copper_link");
+ /* Allow time for pending master requests to run */
+ mac->ops.reset_hw(hw);
+@@ -2115,9 +2170,11 @@ void e1000e_reset(struct e1000_adapter *adapter)
-@@ -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)
+ 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)
{
-- int32_t ret_val = E1000_SUCCESS;
-- uint32_t tipg;
-- uint16_t reg_data;
-+ s32 ret_val = E1000_SUCCESS;
-+ u32 tipg;
-+ u16 reg_data;
+- struct e1000_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
- DEBUGFUNC("e1000_configure_kmrn_for_10_100");
+ 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;
-@@ -2097,12 +2098,12 @@ e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, uint16_t duplex)
- return ret_val;
+ 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;
}
--static int32_t
-+static s32
- e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
+-/* 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)
{
-- int32_t ret_val = E1000_SUCCESS;
-- uint16_t reg_data;
-- uint32_t tipg;
-+ s32 ret_val = E1000_SUCCESS;
-+ u16 reg_data;
-+ u32 tipg;
+ struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+@@ -2430,63 +2498,35 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
- DEBUGFUNC("e1000_configure_kmrn_for_1000");
+ spin_lock_irqsave(&adapter->stats_lock, irq_flags);
-@@ -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;
+- /* 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
+ */
- DEBUGFUNC("e1000_phy_setup_autoneg");
+ 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);
-@@ -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;
+- 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);
+- }
- DEBUGFUNC("e1000_phy_force_speed_duplex");
+ 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);
-@@ -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;
+- 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;
- DEBUGFUNC("e1000_config_collision_dist");
+ /* Rx Errors */
-@@ -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;
+- /* 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 */
- DEBUGFUNC("e1000_config_mac_to_phy");
+ /* 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);
+ }
-@@ -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)
++/**
++ * 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)
{
-- uint32_t ctrl;
-+ u32 ctrl;
+- struct net_device *netdev = adapter->netdev;
+ struct e1000_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
+ u32 ctrl = er32(CTRL);
- DEBUGFUNC("e1000_force_mac_fc");
+ ndev_info(netdev,
+@@ -2579,6 +2656,62 @@ static void e1000_print_link_info(struct e1000_adapter *adapter)
+ ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None" )));
+ }
-@@ -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)
++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)
{
-- 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;
+ 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;
- DEBUGFUNC("e1000_config_fc_after_link_up");
+- 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");
+ }
-@@ -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;
+ if ((e1000e_enable_tx_pkt_filtering(hw)) &&
+ (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id))
+ e1000_update_mng_vlan(adapter);
- DEBUGFUNC("e1000_check_for_link");
+- 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;
+ }
-@@ -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;
- }
- }
+- /* 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);
+ }
-@@ -2947,7 +2948,7 @@ e1000_check_for_link(struct e1000_hw *hw)
- return ret_val;
+- /* 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)
+ }
+ }
- 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)
+- /* 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;
- } else {
- /* No link detected */
-- e1000_config_dsp_after_link_change(hw, FALSE);
-+ e1000_config_dsp_after_link_change(hw, false);
- return 0;
- }
+- 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;
-@@ -2983,7 +2984,7 @@ e1000_check_for_link(struct e1000_hw *hw)
- if (!hw->autoneg) return -E1000_ERR_CONFIG;
+ e1000e_update_adaptive(&adapter->hw);
- /* optimize the dsp settings for the igp phy */
-- e1000_config_dsp_after_link_change(hw, TRUE);
-+ e1000_config_dsp_after_link_change(hw, true);
+@@ -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);
+ }
+ }
- /* 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));
+- /* Cause software interrupt to ensure rx ring is cleaned */
++ /* Cause software interrupt to ensure Rx ring is cleaned */
+ ew32(ICS, E1000_ICS_RXDMT0);
-- 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;
+ /* Force detection of hung controller every watchdog period */
+ adapter->detect_tx_hung = 1;
- DEBUGFUNC("e1000_get_speed_and_duplex");
+- /* 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);
-@@ -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;
+@@ -3032,16 +3156,20 @@ static void e1000_tx_queue(struct e1000_adapter *adapter,
- 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;
+ tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
- /* 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;
+- /* 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();
- /* 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;
+ 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();
}
--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;
+@@ -3089,13 +3217,17 @@ static int __e1000_maybe_stop_tx(struct net_device *netdev, int size)
+ struct e1000_adapter *adapter = netdev_priv(netdev);
- DEBUGFUNC("e1000_swfw_sync_acquire");
+ 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();
-@@ -3428,10 +3429,10 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
- }
+- /* 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;
- 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;
+@@ -3142,21 +3274,29 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ }
- DEBUGFUNC("e1000_swfw_sync_release");
+ 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;
-@@ -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;
+- /* 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;
- DEBUGFUNC("e1000_read_phy_reg");
+@@ -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;
-@@ -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));
- }
+- /* 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;
- if (ret_val) {
-@@ -3522,13 +3523,13 @@ e1000_read_phy_reg(struct e1000_hw *hw,
- return ret_val;
- }
+- /* 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;
--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;
+@@ -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);
- DEBUGFUNC("e1000_read_phy_reg_ex");
+- /* 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
++ */
-@@ -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)
+ 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,
{
-- uint32_t ret_val;
-- uint16_t swfw;
-+ u32 ret_val;
-+ u16 swfw;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct mii_ioctl_data *data = if_mii(ifr);
+- unsigned long irq_flags;
- DEBUGFUNC("e1000_write_phy_reg");
+- if (adapter->hw.media_type != e1000_media_type_copper)
++ if (adapter->hw.phy.media_type != e1000_media_type_copper)
+ return -EOPNOTSUPP;
-@@ -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));
- }
+ 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 (ret_val) {
-@@ -3660,13 +3661,13 @@ e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr,
- return ret_val;
- }
+- 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);
--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;
+- /* 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);
- DEBUGFUNC("e1000_write_phy_reg_ex");
+ pci_disable_device(pdev);
+@@ -3552,9 +3727,11 @@ static int e1000_resume(struct pci_dev *pdev)
-@@ -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;
+ 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);
- 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;
- }
+@@ -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);
--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");
+ 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)
- if ((hw->mac_type == e1000_80003es2lan) &&
-@@ -3749,19 +3750,19 @@ e1000_read_kmrn_reg(struct e1000_hw *hw,
+ netif_device_attach(netdev);
- /* Read the data returned */
- reg_val = E1000_READ_REG(hw, KUMCTRLSTA);
-- *data = (uint16_t)reg_val;
-+ *data = (u16)reg_val;
+- /* 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;
- e1000_swfw_sync_release(hw, swfw);
- return E1000_SUCCESS;
+ /* 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));
}
--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");
+ /**
+@@ -3754,6 +3934,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
+ goto err_pci_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;
+ pci_set_master(pdev);
++ pci_save_state(pdev);
- DEBUGFUNC("e1000_phy_hw_reset");
+ 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));
-@@ -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;
+- err = ei->get_invariants(adapter);
++ err = ei->get_variants(adapter);
+ if (err)
+ goto err_hw_init;
- DEBUGFUNC("e1000_phy_reset");
+ hw->mac.ops.get_bus_info(&adapter->hw);
-@@ -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;
+- adapter->hw.phy.wait_for_link = 0;
++ adapter->hw.phy.autoneg_wait_to_complete = 0;
- DEBUGFUNC("e1000_phy_powerdown_workaround");
+ /* 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;
-@@ -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;
+- /* 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 (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;
+ if (e1000e_enable_mng_pass_thru(&adapter->hw))
+ adapter->flags |= FLAG_MNG_PT_ENABLED;
- DEBUGFUNC("e1000_detect_gig_phy");
+- /* 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);
-@@ -4075,46 +4076,46 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
- if (ret_val)
- return ret_val;
+ /*
+@@ -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;
-- 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;
+ /* 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);
-- 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;
+- /* 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);
- 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");
+- /* 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);
- 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;
+ flush_scheduled_work();
- 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;
+- /* 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);
- 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;
+ 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);
- 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;
+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 @@
+ /*******************************************************************************
- DEBUGFUNC("e1000_phy_get_info");
+ Intel PRO/1000 Linux driver
+- Copyright(c) 1999 - 2007 Intel Corporation.
++ Copyright(c) 1999 - 2008 Intel Corporation.
-@@ -4414,7 +4415,7 @@ e1000_phy_get_info(struct e1000_hw *hw,
- return e1000_phy_m88_get_info(hw, phy_info);
- }
+ 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 @@
--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;
+ #include "e1000.h"
- DEBUGFUNC("e1000_init_eeprom_params");
+-/* 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.
+ */
-@@ -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;
+@@ -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");
-@@ -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);
+-/* 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);
- 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)
+-/* 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
- hw->flash_bank_size *= ICH_FLASH_SECTOR_SIZE;
+-/* 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
-- hw->flash_bank_size /= 2 * sizeof(uint16_t);
-+ hw->flash_bank_size /= 2 * sizeof(u16);
+-/* 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
- 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);
- }
+-/* 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
-@@ -4627,7 +4628,7 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
- *****************************************************************************/
- static void
- e1000_raise_ee_clk(struct e1000_hw *hw,
-- uint32_t *eecd)
-+ u32 *eecd)
- {
- /* Raise the clock input to the EEPROM (by setting the SK bit), and then
- * wait <delay> microseconds.
-@@ -4646,7 +4647,7 @@ e1000_raise_ee_clk(struct e1000_hw *hw,
- *****************************************************************************/
- static void
- e1000_lower_ee_clk(struct e1000_hw *hw,
-- uint32_t *eecd)
-+ u32 *eecd)
- {
- /* Lower the clock input to the EEPROM (by clearing the SK bit), and then
- * wait 50 microseconds.
-@@ -4666,12 +4667,12 @@ e1000_lower_ee_clk(struct e1000_hw *hw,
- *****************************************************************************/
- static void
- e1000_shift_out_ee_bits(struct e1000_hw *hw,
-- uint16_t data,
-- uint16_t count)
-+ u16 data,
-+ u16 count)
- {
- struct e1000_eeprom_info *eeprom = &hw->eeprom;
-- uint32_t eecd;
-- uint32_t mask;
-+ u32 eecd;
-+ u32 mask;
+-/* 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
- /* 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,
+-/* Enable Smart Power Down of the PHY
++/*
++ * Enable Smart Power Down of the PHY
*
- * 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;
+ * Valid Range: 0, 1
+ *
+@@ -115,7 +123,8 @@ E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
+ */
+ E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
- /* 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;
+-/* 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 @@
+ /*******************************************************************************
- DEBUGFUNC("e1000_acquire_eeprom");
+ Intel PRO/1000 Linux driver
+- Copyright(c) 1999 - 2007 Intel Corporation.
++ Copyright(c) 1999 - 2008 Intel Corporation.
-@@ -4824,7 +4825,7 @@ static void
- e1000_standby_eeprom(struct e1000_hw *hw)
+ 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_eeprom_info *eeprom = &hw->eeprom;
-- uint32_t eecd;
-+ u32 eecd;
+ 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;
+ }
- eecd = E1000_READ_REG(hw, EECD);
+- /* 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)
-@@ -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;
+ ew32(MDIC, mdic);
- DEBUGFUNC("e1000_release_eeprom");
+- /* 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)
+ }
-@@ -4920,11 +4921,11 @@ e1000_release_eeprom(struct e1000_hw *hw)
+ /**
+- * 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
*
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
--static int32_t
-+static s32
- e1000_spi_eeprom_ready(struct e1000_hw *hw)
+ * 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)
{
-- uint16_t retry_count = 0;
-- uint8_t spi_stat_reg;
-+ u16 retry_count = 0;
-+ u8 spi_stat_reg;
-
- DEBUGFUNC("e1000_spi_eeprom_ready");
+ 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;
+ }
-@@ -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;
+- /* 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)
-@@ -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;
+ ew32(MDIC, mdic);
- DEBUGFUNC("e1000_read_eeprom");
+- /* 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;
++ }
-@@ -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;
- }
+ 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;
- /* 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);
+- 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);
- /* 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;
+ hw->phy.ops.release_phy(hw);
- if (e1000_spi_eeprom_ready(hw)) {
- e1000_release_eeprom(hw);
-@@ -5028,7 +5028,7 @@ e1000_read_eeprom(struct e1000_hw *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;
- /* 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);
+- 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);
- /* 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);
+ hw->phy.ops.release_phy(hw);
- /* 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;
+@@ -280,18 +292,17 @@ s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
+ return ret_val;
- 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 (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;
+ }
+ }
- 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;
+- 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);
- 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;
+ hw->phy.ops.release_phy(hw);
- DEBUGFUNC("e1000_is_onboard_nvm_eeprom");
+@@ -316,18 +327,17 @@ s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
+ return ret_val;
- if (hw->mac_type == e1000_ich8lan)
-- return FALSE;
-+ return false;
+ 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;
+ }
+ }
- 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)
+- 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);
- /* If both bits are set, device is Flash type */
- if (eecd == 0x03) {
-- return FALSE;
-+ return false;
- }
- }
-- return TRUE;
-+ return true;
- }
+ hw->phy.ops.release_phy(hw);
- /******************************************************************************
-@@ -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;
+@@ -409,14 +419,17 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
+ s32 ret_val;
+ u16 phy_data;
- DEBUGFUNC("e1000_validate_eeprom_checksum");
+- /* 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;
-- 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;
- }
+- 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;
-- 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;
+- /* 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;
+ }
- DEBUGFUNC("e1000_update_eeprom_checksum");
+- /* 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;
-@@ -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;
+- 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;
+ }
- DEBUGFUNC("e1000_write_eeprom");
+- /* 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);
-@@ -5339,7 +5338,7 @@ e1000_write_eeprom(struct e1000_hw *hw,
- }
+ /* 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)
- /* 82573 writes only through eewr */
-- if (eeprom->use_eewr == TRUE)
-+ if (eeprom->use_eewr)
- return e1000_write_eeprom_eewr(hw, offset, words, data);
+ /* 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;
- 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;
+ data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+- data);
++ data);
+ if (ret_val)
+ return ret_val;
- DEBUGFUNC("e1000_write_eeprom_spi");
+@@ -630,14 +650,16 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
+ return ret_val;
+ }
- while (widx < words) {
-- uint8_t write_opcode = EEPROM_WRITE_OPCODE_SPI;
-+ u8 write_opcode = EEPROM_WRITE_OPCODE_SPI;
+- /* 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.
+ */
- if (e1000_spi_eeprom_ready(hw)) return -E1000_ERR_EEPROM;
+- /* 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;
+ }
-@@ -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);
+- /* 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;
-- e1000_shift_out_ee_bits(hw, (uint16_t)((offset + widx)*2),
-+ e1000_shift_out_ee_bits(hw, (u16)((offset + widx)*2),
- eeprom->address_bits);
+- /* Perform some bounds checking on the autoneg advertisement
++ /*
++ * Perform some bounds checking on the autoneg advertisement
+ * parameter.
+ */
+ phy->autoneg_advertised &= phy->autoneg_mask;
- /* Send the data */
+- /* 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");
- /* 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;
+- /* 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;
- DEBUGFUNC("e1000_write_eeprom_microwire");
+- /* 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;
-@@ -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));
+ 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)
+ }
+ }
-- 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));
+- /* 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;
- /* 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);
+- /* 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)
-- e1000_shift_out_ee_bits(hw, (uint16_t)(offset + words_written),
-+ e1000_shift_out_ee_bits(hw, (u16)(offset + words_written),
- eeprom->address_bits);
+ udelay(1);
- /* 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));
+- if (phy->wait_for_link) {
++ if (phy->autoneg_wait_to_complete) {
+ hw_dbg(hw, "Waiting for forced speed/duplex link on IGP phy.\n");
-- 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));
+ 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;
- 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;
+- /* 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)
- 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);
- }
+ udelay(1);
-- 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 (phy->wait_for_link) {
++ if (phy->autoneg_wait_to_complete) {
+ hw_dbg(hw, "Waiting for forced speed/duplex link on M88 phy.\n");
- 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);
+ 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 (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 (!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;
-- /* 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;
+- /* 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;
- } else {
- /* If the write failed then break from the loop and
-@@ -5651,7 +5650,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+- /* 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;
- /* 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)
+ /* Turn off flow control when forcing speed/duplex */
+- mac->fc = e1000_fc_none;
++ hw->fc.type = e1000_fc_none;
- /* 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;
+ /* 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)
- DEBUGFUNC("e1000_read_mac_addr");
+ 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;
-@@ -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);
- }
+ 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;
- 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;
+ 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;
- DEBUGFUNC("e1000_init_rx_addrs");
+- /* 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)
+ }
-@@ -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;
+ /**
+- * 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);
+ }
- /* 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;
+- /* 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;
- /* 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;
+ 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;
- /* 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));
+- /* 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;
- /* 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;
+@@ -1466,7 +1515,7 @@ s32 e1000e_get_phy_info_m88(struct e1000_hw *hw)
+ u16 phy_data;
+ bool link;
- 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->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/eepro.c b/drivers/net/eepro.c
+index 83bda6c..56f5049 100644
+--- a/drivers/net/eepro.c
++++ b/drivers/net/eepro.c
+@@ -633,7 +633,7 @@ static void __init printEEPROMInfo(struct net_device *dev)
+ printk(KERN_DEBUG " PC: %d\n", GetBit(Word,ee_PC));
+ printk(KERN_DEBUG " TPE/AUI: %d\n", GetBit(Word,ee_TPE_AUI));
+ printk(KERN_DEBUG " Jabber: %d\n", GetBit(Word,ee_Jabber));
+- printk(KERN_DEBUG " AutoPort: %d\n", GetBit(!Word,ee_Jabber));
++ printk(KERN_DEBUG " AutoPort: %d\n", !GetBit(Word,ee_AutoPort));
+ printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex));
+ }
- if (hw->mac_type == e1000_ich8lan)
- return;
-@@ -6004,15 +6003,15 @@ e1000_clear_vfta(struct e1000_hw *hw)
- }
- }
+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;
+ };
--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;
+ 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;
+ };
- DEBUGFUNC("e1000_id_led_init");
+ #define EHEA_PORT_UP 1
+@@ -453,7 +453,7 @@ struct ehea_port {
+ struct vlan_group *vgrp;
+ struct ehea_eq *qp_eq;
+ struct work_struct reset_task;
+- struct semaphore port_lock;
++ struct mutex port_lock;
+ char int_aff_name[EHEA_IRQ_NAME_SIZE];
+ int allmulti; /* Indicates IFF_ALLMULTI state */
+ int promisc; /* Indicates IFF_PROMISC state */
+diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
+index f460b62..f9bc21c 100644
+--- a/drivers/net/ehea/ehea_main.c
++++ b/drivers/net/ehea/ehea_main.c
+@@ -36,6 +36,7 @@
+ #include <linux/notifier.h>
+ #include <linux/reboot.h>
+ #include <asm/kexec.h>
++#include <linux/mutex.h>
-@@ -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;
+ #include <net/ip.h>
- DEBUGFUNC("e1000_setup_led");
+@@ -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;
-@@ -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;
+@@ -1761,7 +1762,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa)
- DEBUGFUNC("e1000_id_led_blink_on");
+ memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len);
-@@ -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;
+- down(&ehea_bcmc_regs.lock);
++ mutex_lock(&ehea_bcmc_regs.lock);
- DEBUGFUNC("e1000_cleanup_led");
+ /* 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)
-@@ -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);
+ 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);
- DEBUGFUNC("e1000_led_on");
+- down(&ehea_bcmc_regs.lock);
++ mutex_lock(&ehea_bcmc_regs.lock);
-@@ -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);
+ 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;
+ }
- DEBUGFUNC("e1000_led_off");
+@@ -2455,7 +2456,7 @@ static int ehea_up(struct net_device *dev)
+ if (port->state == EHEA_PORT_UP)
+ return 0;
-@@ -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;
+- down(&ehea_fw_handles.lock);
++ mutex_lock(&ehea_fw_handles.lock);
- 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;
+ 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)
+ }
+ }
- /* 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;
+- down(&ehea_bcmc_regs.lock);
++ mutex_lock(&ehea_bcmc_regs.lock);
- 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;
+ 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);
- DEBUGFUNC("e1000_get_cable_length");
+ ehea_update_bcmc_registrations();
+- up(&ehea_bcmc_regs.lock);
++ mutex_unlock(&ehea_bcmc_regs.lock);
-@@ -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;
+ ehea_update_firmware_handles();
+- up(&ehea_fw_handles.lock);
++ mutex_unlock(&ehea_fw_handles.lock);
- DEBUGFUNC("e1000_check_polarity");
+ return ret;
+ }
+@@ -2545,7 +2546,7 @@ static int ehea_open(struct net_device *dev)
+ int ret;
+ struct ehea_port *port = netdev_priv(dev);
-@@ -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;
+- down(&port->port_lock);
++ mutex_lock(&port->port_lock);
- DEBUGFUNC("e1000_check_downshift");
+ 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);
+ }
-@@ -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;
- }
+- up(&port->port_lock);
++ mutex_unlock(&port->port_lock);
- return E1000_SUCCESS;
-@@ -6986,18 +6985,18 @@ e1000_check_downshift(struct e1000_hw *hw)
- *
- ****************************************************************************/
+ return ret;
+ }
+@@ -2569,18 +2570,18 @@ static int ehea_down(struct net_device *dev)
+ if (port->state == EHEA_PORT_DOWN)
+ return 0;
--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;
+- 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);
- DEBUGFUNC("e1000_config_dsp_after_link_change");
+ ehea_free_interrupts(dev);
-@@ -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)) {
+- down(&ehea_fw_handles.lock);
+-
+ port->state = EHEA_PORT_DOWN;
-- 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;
+ ehea_update_bcmc_registrations();
+- up(&ehea_bcmc_regs.lock);
++ mutex_unlock(&ehea_bcmc_regs.lock);
- /* 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;
+ ret = ehea_clean_all_portres(port);
+ if (ret)
+@@ -2588,7 +2589,7 @@ static int ehea_down(struct net_device *dev)
+ dev->name, ret);
- DEBUGFUNC("e1000_set_phy_mode");
+ ehea_update_firmware_handles();
+- up(&ehea_fw_handles.lock);
++ mutex_unlock(&ehea_fw_handles.lock);
-@@ -7198,7 +7197,7 @@ e1000_set_phy_mode(struct e1000_hw *hw)
- if (ret_val)
- return ret_val;
+ return ret;
+ }
+@@ -2602,15 +2603,15 @@ static int ehea_stop(struct net_device *dev)
+ ehea_info("disabling port %s", dev->name);
-- hw->phy_reset_disable = FALSE;
-+ hw->phy_reset_disable = false;
- }
- }
+ 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;
+ }
-@@ -7219,13 +7218,13 @@ e1000_set_phy_mode(struct e1000_hw *hw)
- *
- ****************************************************************************/
+-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)
+ }
+ }
--static int32_t
-+static s32
- e1000_set_d3_lplu_state(struct e1000_hw *hw,
-- boolean_t active)
-+ bool active)
+-void ehea_flush_sq(struct ehea_port *port)
++static void ehea_flush_sq(struct ehea_port *port)
{
-- 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");
+ int i;
- 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,
- *
- ****************************************************************************/
+@@ -2820,7 +2821,7 @@ static void ehea_reset_port(struct work_struct *work)
+ struct net_device *dev = port->netdev;
--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");
+ port->resets++;
+- down(&port->port_lock);
++ mutex_lock(&port->port_lock);
+ netif_stop_queue(dev);
- 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;
+ port_napi_disable(port);
+@@ -2840,7 +2841,7 @@ static void ehea_reset_port(struct work_struct *work)
- DEBUGFUNC("e1000_set_vco_speed");
+ netif_wake_queue(dev);
+ out:
+- up(&port->port_lock);
++ mutex_unlock(&port->port_lock);
+ return;
+ }
-@@ -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;
+@@ -2849,7 +2850,7 @@ static void ehea_rereg_mrs(struct work_struct *work)
+ int ret, i;
+ struct ehea_adapter *adapter;
- length = (length >> 2);
- offset = (offset >> 2);
+- down(&dlpar_mem_lock);
++ mutex_lock(&dlpar_mem_lock);
+ ehea_info("LPAR memory enlarged - re-initializing driver");
- 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;
+ 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;
- /* 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;
+- if (port) {
+- struct net_device *dev = port->netdev;
++ if (!port)
++ continue;
- /* sum = only sum of the data and it is not checksum */
+- 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);
+ }
+ }
-@@ -7580,14 +7579,14 @@ e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
- return -E1000_ERR_PARAM;
- }
+@@ -2912,17 +2915,17 @@ static void ehea_rereg_mrs(struct work_struct *work)
+ struct net_device *dev = port->netdev;
-- tmp = (uint8_t *)&data;
-+ tmp = (u8 *)&data;
- prev_bytes = offset & 0x3;
- offset &= 0xFFFC;
- offset >>= 2;
+ 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,
- 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;
+ port = netdev_priv(dev);
- /* Write the whole command header structure which includes sum of
- * the buffer */
+- sema_init(&port->port_lock, 1);
++ mutex_init(&port->port_lock);
+ port->state = EHEA_PORT_DOWN;
+ port->sig_comp_iv = sq_entries / 10;
-- uint16_t length = sizeof(struct e1000_host_mng_command_header);
-+ u16 length = sizeof(struct e1000_host_mng_command_header);
+@@ -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);
- sum = hdr->checksum;
- hdr->checksum = 0;
+ adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
+ if (!adapter) {
+@@ -3446,7 +3449,7 @@ out_free_ad:
-- 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);
- }
+ out:
+ ehea_update_firmware_handles();
+- up(&ehea_fw_handles.lock);
++ mutex_unlock(&ehea_fw_handles.lock);
+ return ret;
+ }
-@@ -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;
+@@ -3465,7 +3468,7 @@ static int __devexit ehea_remove(struct of_device *dev)
- 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;
+ flush_scheduled_work();
- fwsm = E1000_READ_REG(hw, FWSM);
+- down(&ehea_fw_handles.lock);
++ mutex_lock(&ehea_fw_handles.lock);
- 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;
+ 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);
-- return FALSE;
-+ return false;
+ 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);
- /*****************************************************************************
- * 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;
+ ret = check_module_parm();
+ if (ret)
+diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
+index fe59c27..d21b7ab 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];
- 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;
+- 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);
- 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];
+ priv->link = PHY_DOWN;
+@@ -491,20 +491,23 @@ static irqreturn_t mpc52xx_fec_interrupt(int irq, void *dev_id)
-- return (uint8_t) (0 - sum);
-+ return (u8) (0 - sum);
- }
+ out_be32(&fec->ievent, ievent); /* clear pending events */
- /*****************************************************************************
- * 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 */
+- if (ievent & ~(FEC_IEVENT_RFIFO_ERROR | FEC_IEVENT_XFIFO_ERROR)) {
+- if (ievent & ~FEC_IEVENT_TFINT)
+- dev_dbg(&dev->dev, "ievent: %08x\n", ievent);
++ /* on fifo error, soft-reset fec */
++ if (ievent & (FEC_IEVENT_RFIFO_ERROR | FEC_IEVENT_XFIFO_ERROR)) {
++
++ if (net_ratelimit() && (ievent & FEC_IEVENT_RFIFO_ERROR))
++ dev_warn(&dev->dev, "FEC_IEVENT_RFIFO_ERROR\n");
++ if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR))
++ dev_warn(&dev->dev, "FEC_IEVENT_XFIFO_ERROR\n");
++
++ mpc52xx_fec_reset(dev);
++
++ netif_wake_queue(dev);
+ return IRQ_HANDLED;
+ }
-- 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 (net_ratelimit() && (ievent & FEC_IEVENT_RFIFO_ERROR))
+- dev_warn(&dev->dev, "FEC_IEVENT_RFIFO_ERROR\n");
+- if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR))
+- dev_warn(&dev->dev, "FEC_IEVENT_XFIFO_ERROR\n");
++ if (ievent & ~FEC_IEVENT_TFINT)
++ dev_dbg(&dev->dev, "ievent: %08x\n", ievent);
- 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;
- }
- }
+- mpc52xx_fec_reset(dev);
+-
+- netif_wake_queue(dev);
+ return IRQ_HANDLED;
+ }
-@@ -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
+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
*
- *****************************************************************************/
--uint32_t
-+u32
- e1000_enable_mng_pass_thru(struct e1000_hw *hw)
- {
-- uint32_t manc;
-- uint32_t fwsm, factps;
-+ u32 manc;
-+ u32 fwsm, factps;
+- * 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"
- if (hw->asf_firmware_present) {
- manc = E1000_READ_REG(hw, MANC);
+@@ -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 */
- 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);
+ enum {
+ NvRegIrqStatus = 0x000,
+@@ -263,11 +175,13 @@ enum {
+ NvRegReceiverStatus = 0x98,
+ #define NVREG_RCVSTAT_BUSY 0x01
- 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;
- }
+- 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
--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;
+ NvRegTxDeferral = 0xA0,
+ #define NVREG_TX_DEFERRAL_DEFAULT 0x15050f
+@@ -290,6 +204,11 @@ enum {
- /* Polarity reversal workaround for forced 10F/10H links. */
+ 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
-@@ -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;
+ NvRegTxRingPhysAddr = 0x100,
+ NvRegRxRingPhysAddr = 0x104,
+@@ -441,6 +360,7 @@ union ring_type {
- DEBUGFUNC("e1000_set_pci_express_master_disable");
+ #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 {
-@@ -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 */
+ #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
- DEBUGFUNC("e1000_disable_pciex_master");
+ /* 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
-@@ -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;
+ #define PHY_GIGABIT 0x0100
- DEBUGFUNC("e1000_get_auto_rd_done");
+@@ -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;
-@@ -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)
++/*
++ * 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)
{
-- 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;
+ 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;
+ }
- DEBUGFUNC("e1000_get_phy_cfg_done");
++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);
-@@ -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)
+- 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)
{
-- int32_t timeout;
-- uint32_t swsm;
-+ s32 timeout;
-+ u32 swsm;
+ struct fe_priv *np = get_nvpriv(dev);
- DEBUGFUNC("e1000_get_hw_eeprom_semaphore");
+- 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;
++ }
++ }
+ }
+ }
-@@ -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;
+@@ -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;
++ }
++ }
+ }
+ }
- DEBUGFUNC("e1000_put_hw_eeprom_semaphore");
+@@ -1435,6 +1462,18 @@ static void nv_stop_tx(struct net_device *dev)
+ base + NvRegTransmitPoll);
+ }
-@@ -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)
++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)
{
-- 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");
+ 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];
-@@ -8204,7 +8203,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
- static void
- e1000_release_software_semaphore(struct e1000_hw *hw)
+ 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)
{
-- uint32_t swsm;
-+ u32 swsm;
+ 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;
- DEBUGFUNC("e1000_release_software_semaphore");
+ 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)
-@@ -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;
+ 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;
- 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;
+ 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 uint8_t
-+static u8
- e1000_arc_subsystem_valid(struct e1000_hw *hw)
+-static void drain_ring(struct net_device *dev)
++static void nv_drain_rxtx(struct net_device *dev)
{
-- 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;
+ 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;
-@@ -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;
+@@ -2260,7 +2426,7 @@ static void nv_tx_timeout(struct net_device *dev)
+ }
+ printk(KERN_INFO "%s: Dumping tx ring\n", dev->name);
+ for (i=0;i<np->tx_ring_size;i+= 4) {
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++ if (!nv_optimized(np)) {
+ printk(KERN_INFO "%03x: %08x %08x // %08x %08x // %08x %08x // %08x %08x\n",
+ i,
+ le32_to_cpu(np->tx_ring.orig[i].buf),
+@@ -2296,7 +2462,7 @@ static void nv_tx_timeout(struct net_device *dev)
+ nv_stop_tx(dev);
- DEBUGFUNC("e1000_set_pci_ex_no_snoop");
+ /* 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);
-@@ -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;
+ /* 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:
+ }
- E1000_WRITE_REG(hw, GCR, PCI_EX_82566_SNOOP_ALL);
+ 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);
+ }
-@@ -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;
+ 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;
- DEBUGFUNC("e1000_get_software_flag");
+- 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);
-@@ -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;
+ /* 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);
- DEBUGFUNC("e1000_release_software_flag");
+ 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);
-@@ -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;
+ if (!np->in_shutdown)
+- mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL);
++ mod_timer(&np->stats_poll,
++ round_jiffies(jiffies + STATS_INTERVAL));
+ }
- /* 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,
+ 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)
+ }
- 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;
+ if (netif_running(dev)) {
+- nv_start_rx(dev);
+- nv_start_tx(dev);
++ nv_start_rxtx(dev);
+ nv_enable_irq(dev);
+ }
- 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;
+@@ -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)
+ }
- DEBUGFUNC("e1000_ich8_cycle_init");
+ 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
+ }
-@@ -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;
+ /* 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);
- /* 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;
+ /* 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*
+ }
- DEBUGFUNC("e1000_read_ich8_data");
+ 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);
-@@ -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;
+ /* restart rx engine */
+- nv_start_rx(dev);
+- nv_start_tx(dev);
++ nv_start_rxtx(dev);
- DEBUGFUNC("e1000_write_ich8_data");
+ /* 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);
-@@ -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 (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);
- if (size == 1)
-- flash_data = (uint32_t)data & 0x00FF;
-+ flash_data = (u32)data & 0x00FF;
- else
-- flash_data = (uint32_t)data;
-+ flash_data = (u32)data;
+ /* 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);
- E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data);
+@@ -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);
-@@ -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;
+ 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;
- status = e1000_read_ich8_data(hw, index, 1, &word);
- if (status == E1000_SUCCESS) {
-- *data = (uint8_t)word;
-+ *data = (u8)word;
- }
+ dprintk(KERN_DEBUG "nv_open: begin\n");
- 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;
+@@ -4986,8 +5133,20 @@ static int nv_open(struct net_device *dev)
+ writel(np->rx_buf_sz, base + NvRegOffloadConfig);
- DEBUGOUT2("Byte := %2.2X Offset := %d\n", byte, index);
+ 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)
-@@ -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;
+ /* 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));
- status = e1000_write_ich8_data(hw, index, 1, word);
+ spin_unlock_irq(&np->lock);
-@@ -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;
+ return 0;
+ out_drain:
+- drain_ring(dev);
++ nv_drain_rxtx(dev);
+ return ret;
}
-@@ -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);
+@@ -5093,8 +5252,7 @@ static int nv_close(struct net_device *dev)
-@@ -8931,16 +8930,16 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank)
- return error;
- }
+ 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);
--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;
+ /* disable interrupts on the nic or we will lock up */
+@@ -5107,7 +5265,7 @@ static int nv_close(struct net_device *dev)
- /* cnf_base_addr is in DWORD */
-- word_addr = (uint16_t)(cnf_base_addr << 1);
-+ word_addr = (u16)(cnf_base_addr << 1);
+ nv_free_irq(dev);
- /* 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;
+- drain_ring(dev);
++ nv_drain_rxtx(dev);
-- 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);
+ 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
- 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;
+ /* copy of driver data */
+ np->driver_data = id->driver_data;
++ /* copy of device id */
++ np->device_id = id->device;
- 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;
+ /* 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;
- struct e1000_shadow_ram {
-- uint16_t eeprom_word;
-- boolean_t modified;
-+ u16 eeprom_word;
-+ bool modified;
- };
+- 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
- /* PCI bus types */
-@@ -263,19 +263,19 @@ struct e1000_phy_info {
- };
+ 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;
+ }
- struct e1000_phy_stats {
-- uint32_t idle_errors;
-- uint32_t receive_errors;
-+ u32 idle_errors;
-+ u32 receive_errors;
- };
++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);
- 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;
++ /* 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.");
- /* Flex ASF Information */
-@@ -308,34 +308,34 @@ typedef enum {
+ MODULE_AUTHOR("Manfred Spraul <manfred at colorfullife.com>");
+ MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver");
+diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
+index 940e204..67b4b07 100644
+--- a/drivers/net/fs_enet/fs_enet-main.c
++++ b/drivers/net/fs_enet/fs_enet-main.c
+@@ -1178,7 +1178,7 @@ static int __devinit find_phy(struct device_node *np,
- /* 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);
+ 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;
+ }
- /* 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);
+@@ -1202,7 +1202,7 @@ static int __devinit find_phy(struct device_node *np,
+ if (!data || len != 4)
+ goto out_put_mdio;
- /* 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);
+- snprintf(fpi->bus_id, 16, PHY_ID_FMT, res.start, *data);
++ snprintf(fpi->bus_id, 16, "%x:%02x", res.start, *data);
- void e1000_phy_powerdown_workaround(struct e1000_hw *hw);
+ 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);
- /* EEPROM Functions */
--int32_t e1000_init_eeprom_params(struct e1000_hw *hw);
-+s32 e1000_init_eeprom_params(struct e1000_hw *hw);
+ 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;
- /* 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);
+ new_bus->name = "BB MII Bus",
+- new_bus->id = pdev->id;
++ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
- #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
+ 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;
- 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;
- };
+- new_bus->id = res.start;
++ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start);
- 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
+ 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);
--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);
+ pdata = (struct fs_mii_fec_platform_info *)pdev->dev.platform_data;
- /* 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);
+diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
+index 718cf77..587afe7 100644
+--- a/drivers/net/gianfar.c
++++ b/drivers/net/gianfar.c
+@@ -98,7 +98,6 @@
+ #include "gianfar_mii.h"
- /* 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);
+ #define TX_TIMEOUT (1*HZ)
+-#define SKB_ALLOC_TIMEOUT 1000000
+ #undef BRIEF_GFAR_ERRORS
+ #undef VERBOSE_GFAR_ERRORS
- /* Adaptive IFS Functions */
+@@ -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);
+@@ -130,8 +131,6 @@ static void free_skb_resources(struct gfar_private *priv);
+ static void gfar_set_multi(struct net_device *dev);
+ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
+ static void gfar_configure_serdes(struct net_device *dev);
+-extern int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id, int regnum, u16 value);
+-extern int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum);
+ #ifdef CONFIG_GFAR_NAPI
+ static int gfar_poll(struct napi_struct *napi, int budget);
+ #endif
+@@ -476,24 +475,30 @@ static int init_phy(struct net_device *dev)
+ return 0;
+ }
- /* 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);
++/*
++ * Initialize TBI PHY interface for communicating with the
++ * SERDES lynx PHY on the chip. We communicate with this PHY
++ * through the MDIO bus on each controller, treating it as a
++ * "normal" PHY at the address found in the TBIPA register. We assume
++ * that the TBIPA register is valid. Either the MDIO bus code will set
++ * it to a value that doesn't conflict with other PHYs on the bus, or the
++ * value doesn't matter, as there are no other PHYs on the bus.
++ */
+ static void gfar_configure_serdes(struct net_device *dev)
+ {
+ struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_mii __iomem *regs =
+ (void __iomem *)&priv->regs->gfar_mii_regs;
++ int tbipa = gfar_read(&priv->regs->tbipa);
+- /* Initialise TBI i/f to communicate with serdes (lynx phy) */
++ /* Single clk mode, mii mode off(for serdes communication) */
++ gfar_local_mdio_write(regs, tbipa, MII_TBICON, TBICON_CLK_SELECT);
- #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;
- };
+- /* Single clk mode, mii mode off(for aerdes communication) */
+- gfar_local_mdio_write(regs, TBIPA_VALUE, MII_TBICON, TBICON_CLK_SELECT);
+-
+- /* Supported pause and full-duplex, no half-duplex */
+- gfar_local_mdio_write(regs, TBIPA_VALUE, MII_ADVERTISE,
++ gfar_local_mdio_write(regs, tbipa, MII_ADVERTISE,
+ ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE |
+ ADVERTISE_1000XPSE_ASYM);
-@@ -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 {
+- /* ANEG enable, restart ANEG, full duplex mode, speed[1] set */
+- gfar_local_mdio_write(regs, TBIPA_VALUE, MII_BMCR, BMCR_ANENABLE |
++ gfar_local_mdio_write(regs, tbipa, MII_BMCR, BMCR_ANENABLE |
+ BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000);
+ }
- /* 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;
- };
+@@ -540,9 +545,6 @@ static void init_registers(struct net_device *dev)
- /* Four wakeup IP addresses are supported */
-@@ -837,25 +837,25 @@ struct e1000_ipv4_at_entry {
+ /* Initialize the Minimum Frame Length Register */
+ gfar_write(&priv->regs->minflr, MINFLR_INIT_SETTINGS);
+-
+- /* Assign the TBI an address which won't conflict with the PHYs */
+- gfar_write(&priv->regs->tbipa, TBIPA_VALUE);
+ }
- /* 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;
- };
+@@ -783,14 +785,21 @@ int startup_gfar(struct net_device *dev)
- /* 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;
- };
+ rxbdp = priv->rx_bd_base;
+ for (i = 0; i < priv->rx_ring_size; i++) {
+- struct sk_buff *skb = NULL;
++ struct sk_buff *skb;
- /* 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;
- };
+- rxbdp->status = 0;
++ skb = gfar_new_skb(dev);
- /* Four Flexible Filters are supported */
-@@ -1309,89 +1309,89 @@ struct e1000_ffvt_entry {
+- skb = gfar_new_skb(dev, rxbdp);
++ if (!skb) {
++ printk(KERN_ERR "%s: Can't allocate RX buffers\n",
++ dev->name);
++
++ goto err_rxalloc_fail;
++ }
- /* 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;
- };
+ priv->rx_skbuff[i] = skb;
- /* 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;
- };
++ gfar_new_rxbdp(dev, rxbdp, skb);
++
+ rxbdp++;
+ }
+@@ -916,6 +925,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 +1195,7 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
+ int frame_size = new_mtu + ETH_HLEN;
-@@ -2165,14 +2165,14 @@ typedef enum {
- #define E1000_HI_COMMAND_TIMEOUT 500 /* Time in ms to process HI command */
+ if (priv->vlan_enable)
+- frame_size += VLAN_ETH_HLEN;
++ frame_size += VLAN_HLEN;
- 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 */
- };
+ if (gfar_uses_fcb(priv))
+ frame_size += GMAC_FCB_LEN;
+@@ -1250,17 +1260,12 @@ static void gfar_timeout(struct net_device *dev)
+ }
- /* 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
+ /* 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;
--#define E1000_TX_BUFFER_SIZE ((uint32_t)1514)
-+#define E1000_TX_BUFFER_SIZE ((u32)1514)
+- /* 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 +1274,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id)
+ if ((bdp == priv->cur_tx) && (netif_queue_stopped(dev) == 0))
+ break;
- /* 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;
- };
+- dev->stats.tx_packets++;
++ howmany++;
- /* 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;
- };
+ /* Deferred means some collisions occurred during transmit, */
+ /* but we eventually sent the packet. */
+@@ -1278,11 +1283,15 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id)
- /* 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;
- };
+ /* 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);
- /* 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);
++ /* 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 +1306,69 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id)
+ netif_wake_queue(dev);
+ } /* while ((bdp->status & TXBD_READY) == 0) */
- 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);
++ 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);
++ }
- 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);
+ spin_unlock(&priv->txlock);
+
+ return IRQ_HANDLED;
}
- static void
- e1000_update_mng_vlan(struct e1000_adapter *adapter)
+-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)
{
- 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;
+ unsigned int alignamount;
+ struct gfar_private *priv = netdev_priv(dev);
+ struct sk_buff *skb = NULL;
+- unsigned int timeout = SKB_ALLOC_TIMEOUT;
-- 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;
+ /* 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);
- /* 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;
+- if (NULL == skb)
++ if (!skb)
+ return NULL;
- /* 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);
+ alignamount = RXBUF_ALIGNMENT -
+@@ -1332,15 +1379,6 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
+ */
+ skb_reserve(skb, alignamount);
- /* 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);
+- 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;
+ }
- 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);
+@@ -1392,15 +1430,15 @@ irqreturn_t gfar_receive(int irq, void *dev_id)
+ unsigned long flags;
+ #endif
- /* re-enable hardware interception of ARP */
- manc |= E1000_MANC_ARP_EN;
-@@ -569,7 +566,7 @@ int e1000_up(struct e1000_adapter *adapter)
+- /* 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);
- void e1000_power_up_phy(struct e1000_adapter *adapter)
- {
-- uint16_t mii_reg = 0;
-+ u16 mii_reg = 0;
+ __netif_rx_schedule(dev, &priv->napi);
+@@ -1411,17 +1449,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);
- /* 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;
+ spin_lock_irqsave(&priv->rxlock, flags);
+ gfar_clean_rx_ring(dev, priv->rx_ring_size);
- switch (adapter->hw.mac_type) {
- case e1000_82540:
-@@ -638,7 +635,6 @@ e1000_down(struct e1000_adapter *adapter)
+ /* 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);
++ }
- #ifdef CONFIG_E1000_NAPI
- napi_disable(&adapter->napi);
-- atomic_set(&adapter->irq_sem, 0);
+ spin_unlock_irqrestore(&priv->rxlock, flags);
#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;
+@@ -1523,12 +1564,31 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
+ bdp = priv->cur_rx;
- /* 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;
- }
+ 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 (legacy_pba_adjust == TRUE) {
-+ if (legacy_pba_adjust) {
- if (adapter->netdev->mtu > E1000_RXBUFFER_8192)
- pba -= 8; /* allocate more FIFO for Tx */
+- 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 +1599,14 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
+ gfar_process_frame(dev, skb, pkt_len);
-@@ -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);
+ 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;
+ }
- if ((err = pci_enable_device(pdev)))
-@@ -1366,15 +1362,15 @@ e1000_sw_init(struct e1000_adapter *adapter)
+ dev->last_rx = jiffies;
- e1000_set_media_type(hw);
+- /* Clear the status flags for this buffer */
+- bdp->status &= ~RXBD_STATS;
++ priv->rx_skbuff[priv->skb_currx] = newskb;
-- 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;
+- /* 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);
- /* Copper options */
+ /* Update to the next pointer */
+ if (bdp->status & RXBD_WRAP)
+@@ -1565,9 +1616,8 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
- 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;
+ /* 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);
}
-@@ -1396,7 +1392,6 @@ e1000_sw_init(struct e1000_adapter *adapter)
- #endif
+ /* Update the current rxbd pointer to be the next one */
+@@ -1582,6 +1632,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);
++ }
- /* Explicitly disable IRQ since the NIC can be in any state. */
-- atomic_set(&adapter->irq_sem, 0);
- e1000_irq_disable(adapter);
+ howmany = gfar_clean_rx_ring(dev, budget);
- 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;
+@@ -1595,11 +1652,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 TRUE;
-+ return true;
+ return howmany;
+@@ -1975,12 +2032,16 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
+ return IRQ_HANDLED;
}
- /**
-@@ -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;
++/* 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,
+ },
+ };
- /* Setup the HW Tx Head and Tail descriptor pointers */
+diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
+index 46cd773..fd487be 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
-@@ -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
+ /* The number of Exact Match registers */
+@@ -124,13 +124,19 @@ extern const char gfar_driver_version[];
- 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;
+ #define DEFAULT_TX_COALESCE 1
+ #define DEFAULT_TXCOUNT 16
+-#define DEFAULT_TXTIME 4
++#define DEFAULT_TXTIME 21
- 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;
++#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 */
- /* 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;
+-#define TBIPA_VALUE 0x1f
+ #define MIIMCFG_INIT_VALUE 0x00000007
+ #define MIIMCFG_RESET 0x80000000
+ #define MIIMIND_BUSY 0x00000001
+@@ -242,6 +248,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 +276,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)
- e1000_pci_clear_mwi(&adapter->hw);
+ /* Fifo management */
+ #define FIFO_TX_THR_MASK 0x01ff
+@@ -340,6 +348,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)
-@@ -2410,7 +2405,7 @@ static void
- e1000_leave_82542_rst(struct e1000_adapter *adapter)
+ /* 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..ebcfb27 100644
+--- a/drivers/net/gianfar_mii.c
++++ b/drivers/net/gianfar_mii.c
+@@ -78,7 +78,6 @@ int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id,
+ * same as system mdio bus, used for controlling the external PHYs, for eg.
+ */
+ int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum)
+-
{
- struct net_device *netdev = adapter->netdev;
-- uint32_t rctl;
-+ u32 rctl;
+ u16 value;
- 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)
+@@ -122,7 +121,7 @@ int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+ }
+
+ /* Reset the MIIM registers, and wait for the bus to free */
+-int gfar_mdio_reset(struct mii_bus *bus)
++static int gfar_mdio_reset(struct mii_bus *bus)
{
- struct e1000_adapter *adapter = (struct e1000_adapter *) data;
- struct net_device *netdev = adapter->netdev;
-- uint32_t tctl;
-+ u32 tctl;
+ struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
+ unsigned int timeout = PHY_INIT_TIMEOUT;
+@@ -152,14 +151,15 @@ int gfar_mdio_reset(struct mii_bus *bus)
+ }
- 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)
+-int gfar_mdio_probe(struct device *dev)
++static int gfar_mdio_probe(struct device *dev)
+ {
+ struct platform_device *pdev = to_platform_device(dev);
+ struct gianfar_mdio_data *pdata;
+ struct gfar_mii __iomem *regs;
++ struct gfar __iomem *enet_regs;
+ struct mii_bus *new_bus;
+ struct resource *r;
+- int err = 0;
++ int i, err = 0;
- 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 (NULL == dev)
+ return -EINVAL;
+@@ -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);
- 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);
+ pdata = (struct gianfar_mdio_data *)pdev->dev.platform_data;
- /* Force detection of hung controller every watchdog period */
-- adapter->detect_tx_hung = TRUE;
-+ adapter->detect_tx_hung = true;
+@@ -199,6 +199,34 @@ int gfar_mdio_probe(struct device *dev)
+ new_bus->dev = dev;
+ dev_set_drvdata(dev, new_bus);
+
++ /*
++ * This is mildly evil, but so is our hardware for doing this.
++ * Also, we have to cast back to struct gfar_mii because of
++ * definition weirdness done in gianfar.h.
++ */
++ enet_regs = (struct gfar __iomem *)
++ ((char *)regs - offsetof(struct gfar, gfar_mii_regs));
++
++ /* Scan the bus, looking for an empty spot for TBIPA */
++ gfar_write(&enet_regs->tbipa, 0);
++ for (i = PHY_MAX_ADDR; i > 0; i--) {
++ u32 phy_id;
++ int r;
++
++ r = get_phy_id(new_bus, i, &phy_id);
++ if (r)
++ return r;
++
++ if (phy_id == 0xffffffff)
++ break;
++ }
++
++ /* The bus is full. We don't support using 31 PHYs, sorry */
++ if (i == 0)
++ return -EBUSY;
++
++ gfar_write(&enet_regs->tbipa, i);
++
+ err = mdiobus_register(new_bus);
- /* 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 (0 != err) {
+@@ -218,7 +246,7 @@ reg_map_fail:
+ }
- 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;
+-int gfar_mdio_remove(struct device *dev)
++static int gfar_mdio_remove(struct device *dev)
+ {
+ struct mii_bus *bus = dev_get_drvdata(dev);
+
+diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h
+index b373091..2af28b1 100644
+--- a/drivers/net/gianfar_mii.h
++++ b/drivers/net/gianfar_mii.h
+@@ -41,6 +41,9 @@ struct gfar_mii {
+
+ int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum);
+ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
++int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id,
++ int regnum, u16 value);
++int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum);
+ int __init gfar_mdio_init(void);
+ void gfar_mdio_exit(void);
+ #endif /* GIANFAR_PHY_H */
+diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
+index b53f6b6..e5c2380 100644
+--- a/drivers/net/hamachi.c
++++ b/drivers/net/hamachi.c
+@@ -1508,7 +1508,7 @@ static int hamachi_rx(struct net_device *dev)
+ hmp->rx_buf_sz,
+ PCI_DMA_FROMDEVICE);
+ buf_addr = (u8 *) hmp->rx_skbuff[entry]->data;
+- frame_status = le32_to_cpu(get_unaligned((__le32*)&(buf_addr[data_size - 12])));
++ frame_status = get_unaligned_le32(&(buf_addr[data_size - 12]));
+ if (hamachi_debug > 4)
+ printk(KERN_DEBUG " hamachi_rx() status was %8.8x.\n",
+ frame_status);
+diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
+index 0a9b751..9d57212 100644
+--- a/drivers/net/hamradio/6pack.c
++++ b/drivers/net/hamradio/6pack.c
+@@ -33,7 +33,7 @@
+ #include <linux/init.h>
+ #include <linux/ip.h>
+ #include <linux/tcp.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <asm/atomic.h>
+
+ #define SIXPACK_VERSION "Revision: 0.3.0"
+@@ -148,13 +148,13 @@ static void sp_xmit_on_air(unsigned long channel)
-- return TRUE;
-+ return true;
+ if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistence)) {
+ sp->led_state = 0x70;
+- sp->tty->driver->write(sp->tty, &sp->led_state, 1);
++ sp->tty->ops->write(sp->tty, &sp->led_state, 1);
+ sp->tx_enable = 1;
+- actual = sp->tty->driver->write(sp->tty, sp->xbuff, sp->status2);
++ actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2);
+ sp->xleft -= actual;
+ sp->xhead += actual;
+ sp->led_state = 0x60;
+- sp->tty->driver->write(sp->tty, &sp->led_state, 1);
++ sp->tty->ops->write(sp->tty, &sp->led_state, 1);
+ sp->status2 = 0;
+ } else
+ mod_timer(&sp->tx_t, jiffies + ((when + 1) * HZ) / 100);
+@@ -220,13 +220,13 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
+ */
+ if (sp->duplex == 1) {
+ sp->led_state = 0x70;
+- sp->tty->driver->write(sp->tty, &sp->led_state, 1);
++ sp->tty->ops->write(sp->tty, &sp->led_state, 1);
+ sp->tx_enable = 1;
+- actual = sp->tty->driver->write(sp->tty, sp->xbuff, count);
++ actual = sp->tty->ops->write(sp->tty, sp->xbuff, count);
+ sp->xleft = count - actual;
+ sp->xhead = sp->xbuff + actual;
+ sp->led_state = 0x60;
+- sp->tty->driver->write(sp->tty, &sp->led_state, 1);
++ sp->tty->ops->write(sp->tty, &sp->led_state, 1);
+ } else {
+ sp->xleft = count;
+ sp->xhead = sp->xbuff;
+@@ -444,7 +444,7 @@ static void sixpack_write_wakeup(struct tty_struct *tty)
}
-- return FALSE;
-+ return false;
+
+ if (sp->tx_enable) {
+- actual = tty->driver->write(tty, sp->xhead, sp->xleft);
++ actual = tty->ops->write(tty, sp->xhead, sp->xleft);
+ sp->xleft -= actual;
+ sp->xhead += actual;
+ }
+@@ -491,9 +491,7 @@ static void sixpack_receive_buf(struct tty_struct *tty,
+ sixpack_decode(sp, buf, count1);
+
+ sp_put(sp);
+- if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
+- && tty->driver->unthrottle)
+- tty->driver->unthrottle(tty);
++ tty_unthrottle(tty);
}
--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;
+ /*
+@@ -554,8 +552,8 @@ static void resync_tnc(unsigned long channel)
+ /* resync the TNC */
- 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;
+ sp->led_state = 0x60;
+- sp->tty->driver->write(sp->tty, &sp->led_state, 1);
+- sp->tty->driver->write(sp->tty, &resync_cmd, 1);
++ sp->tty->ops->write(sp->tty, &sp->led_state, 1);
++ sp->tty->ops->write(sp->tty, &resync_cmd, 1);
-- return TRUE;
-+ return true;
- }
-- return FALSE;
-+ return false;
- }
+ /* Start resync timer again -- the TNC might be still absent */
+@@ -573,7 +571,7 @@ static inline int tnc_init(struct sixpack *sp)
- #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;
+ tnc_set_sync_state(sp, TNC_UNSYNC_STARTUP);
- 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;
+- sp->tty->driver->write(sp->tty, &inbyte, 1);
++ sp->tty->ops->write(sp->tty, &inbyte, 1);
- skb_fifo_len = ALIGN(skb_fifo_len, E1000_FIFO_HDR);
+ del_timer(&sp->resync_t);
+ sp->resync_t.data = (unsigned long) sp;
+@@ -601,6 +599,8 @@ static int sixpack_open(struct tty_struct *tty)
-@@ -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;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
++ if (tty->ops->write == NULL)
++ return -EOPNOTSUPP;
- return e1000_mng_write_dhcp_info(hw,
-- (uint8_t *)udp + 8,
-+ (u8 *)udp + 8,
- length);
- }
+ dev = alloc_netdev(sizeof(struct sixpack), "sp%d", sp_setup);
+ if (!dev) {
+@@ -914,9 +914,9 @@ static void decode_prio_command(struct sixpack *sp, unsigned char cmd)
+ } else { /* output watchdog char if idle */
+ if ((sp->status2 != 0) && (sp->duplex == 1)) {
+ sp->led_state = 0x70;
+- sp->tty->driver->write(sp->tty, &sp->led_state, 1);
++ sp->tty->ops->write(sp->tty, &sp->led_state, 1);
+ sp->tx_enable = 1;
+- actual = sp->tty->driver->write(sp->tty, sp->xbuff, sp->status2);
++ actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2);
+ sp->xleft -= actual;
+ sp->xhead += actual;
+ sp->led_state = 0x60;
+@@ -926,7 +926,7 @@ static void decode_prio_command(struct sixpack *sp, unsigned char cmd)
+ }
+
+ /* needed to trigger the TNC watchdog */
+- sp->tty->driver->write(sp->tty, &sp->led_state, 1);
++ sp->tty->ops->write(sp->tty, &sp->led_state, 1);
+
+ /* if the state byte has been received, the TNC is present,
+ so the resync timer can be reset. */
+@@ -956,12 +956,12 @@ static void decode_std_command(struct sixpack *sp, unsigned char cmd)
+ if ((sp->status & SIXP_RX_DCD_MASK) ==
+ SIXP_RX_DCD_MASK) {
+ sp->led_state = 0x68;
+- sp->tty->driver->write(sp->tty, &sp->led_state, 1);
++ sp->tty->ops->write(sp->tty, &sp->led_state, 1);
}
-@@ -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;
+ } else {
+ sp->led_state = 0x60;
+ /* fill trailing bytes with zeroes */
+- sp->tty->driver->write(sp->tty, &sp->led_state, 1);
++ sp->tty->ops->write(sp->tty, &sp->led_state, 1);
+ rest = sp->rx_count;
+ if (rest != 0)
+ for (i = rest; i <= 3; i++)
+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;
-@@ -3562,7 +3557,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
+- 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 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;
+ struct net_device *dev = (struct net_device *)ptr;
- 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;
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
- #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
+ 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);
+ }
+ }
-@@ -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 */
+diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
+index 30c9b3b..6516603 100644
+--- a/drivers/net/hamradio/mkiss.c
++++ b/drivers/net/hamradio/mkiss.c
+@@ -516,7 +516,7 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
+ spin_unlock_bh(&ax->buflock);
+
+ set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
+- actual = ax->tty->driver->write(ax->tty, ax->xbuff, count);
++ actual = ax->tty->ops->write(ax->tty, ax->xbuff, count);
+ ax->stats.tx_packets++;
+ ax->stats.tx_bytes += actual;
+
+@@ -546,7 +546,7 @@ static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
+ }
+
+ printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name,
+- (ax->tty->driver->chars_in_buffer(ax->tty) || ax->xleft) ?
++ (ax->tty->ops->chars_in_buffer(ax->tty) || ax->xleft) ?
+ "bad line quality" : "driver error");
--#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;
+ ax->xleft = 0;
+@@ -736,6 +736,8 @@ static int mkiss_open(struct tty_struct *tty)
-- /* 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 (!capable(CAP_NET_ADMIN))
+ return -EPERM;
++ if (tty->ops->write == NULL)
++ return -EOPNOTSUPP;
- 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);
+ dev = alloc_netdev(sizeof(struct mkiss), "ax%d", ax_setup);
+ if (!dev) {
+@@ -754,8 +756,7 @@ static int mkiss_open(struct tty_struct *tty)
+ tty->disc_data = ax;
+ tty->receive_room = 65535;
+
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ tty_driver_flush_buffer(tty);
+
+ /* Restore default settings */
+ dev->type = ARPHRD_AX25;
+@@ -935,9 +936,7 @@ static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,
}
-@@ -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
- **/
+ mkiss_put(ax);
+- if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
+- && tty->driver->unthrottle)
+- tty->driver->unthrottle(tty);
++ tty_unthrottle(tty);
+ }
--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;
+ /*
+@@ -962,7 +961,7 @@ static void mkiss_write_wakeup(struct tty_struct *tty)
+ goto out;
+ }
- 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);
+- actual = tty->driver->write(tty, ax->xhead, ax->xleft);
++ actual = tty->ops->write(tty, ax->xhead, ax->xleft);
+ ax->xleft -= actual;
+ ax->xhead += actual;
- 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,
+diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
+index 378a239..5d2108c 100644
+--- a/drivers/net/ibm_newemac/core.c
++++ b/drivers/net/ibm_newemac/core.c
+@@ -43,6 +43,8 @@
+ #include <asm/io.h>
+ #include <asm/dma.h>
+ #include <asm/uaccess.h>
++#include <asm/dcr.h>
++#include <asm/dcr-regs.h>
- 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)
+ #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)
{
-- 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;
+- 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);
+ }
- /* 82543 or newer only */
-@@ -4200,7 +4185,7 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
- * @adapter: board private structure
- **/
++/* 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;
--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;
+ 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);
- i = rx_ring->next_to_clean;
-@@ -4247,7 +4232,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ /* 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);
- next_buffer = &rx_ring->buffer_info[i];
+ /* 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);
-- 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,
+ /* 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);
- /* 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);
+ /* 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)
- skb->protocol = eth_type_trans(skb, netdev);
-@@ -4373,7 +4358,7 @@ next_desc:
- * @adapter: board private structure
- **/
+ 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);
--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;
+@@ -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;
+ }
- i = rx_ring->next_to_clean;
-@@ -4420,7 +4405,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+-static struct notifier_block emac_of_bus_notifier = {
++static struct notifier_block emac_of_bus_notifier __devinitdata = {
+ .notifier_call = emac_of_bus_notify
+ };
- next_buffer = &rx_ring->buffer_info[i];
+@@ -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;
-- 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)
++ /* 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)
{
-- uint16_t phy_status;
-- uint16_t phy_ctrl;
-+ u16 phy_status;
-+ u16 phy_ctrl;
+ unsigned long flags;
- 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;
+@@ -136,6 +136,14 @@ void mal_enable_rx_channel(struct mal_instance *mal, int channel)
+ {
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);
- }
++ /*
++ * 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);
--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)
+ 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)
{
- struct e1000_adapter *adapter = hw->back;
-- uint16_t cap_offset;
-+ u16 cap_offset;
++ /*
++ * 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));
- 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)
+ 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
--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)
+-void __devexit rgmii_detach(struct of_device *ofdev, int input)
++void rgmii_detach(struct of_device *ofdev, int input)
{
- outl(value, port);
+ 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;
}
-@@ -4999,9 +4984,10 @@ static void
- e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+
+-void __devexit tah_detach(struct of_device *ofdev, int channel)
++void tah_detach(struct of_device *ofdev, int channel)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
-- uint32_t ctrl, rctl;
-+ u32 ctrl, rctl;
+ struct tah_instance *dev = dev_get_drvdata(&ofdev->dev);
-- e1000_irq_disable(adapter);
-+ if (!test_bit(__E1000_DOWN, &adapter->flags))
-+ e1000_irq_disable(adapter);
- adapter->vlgrp = grp;
+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);
+ }
- 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)
- }
- }
+-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);
-- e1000_irq_enable(adapter);
-+ if (!test_bit(__E1000_DOWN, &adapter->flags))
-+ e1000_irq_enable(adapter);
+diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
+index 57772be..0052780 100644
+--- a/drivers/net/ibmveth.c
++++ b/drivers/net/ibmveth.c
+@@ -49,7 +49,6 @@
+ #include <linux/in.h>
+ #include <linux/ip.h>
+ #include <net/net_namespace.h>
+-#include <asm/semaphore.h>
+ #include <asm/hvcall.h>
+ #include <asm/atomic.h>
+ #include <asm/vio.h>
+@@ -1259,26 +1258,7 @@ static void ibmveth_proc_unregister_driver(void)
+ remove_proc_entry(IBMVETH_PROC_DIR, init_net.proc_net);
}
- static void
--e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
-+e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+-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 e1000_adapter *adapter = netdev_priv(netdev);
-- uint32_t vfta, index;
-+ u32 vfta, index;
+ 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)
- 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)
+ 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 void
--e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
-+e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+ static int ibmveth_proc_open(struct inode *inode, struct file *file)
{
- 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);
+- 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);
+ }
- 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);
+ 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,
+ };
- 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)
+ static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter)
+@@ -1339,13 +1302,10 @@ static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter)
+ if (ibmveth_proc_dir) {
+ char u_addr[10];
+ sprintf(u_addr, "%x", adapter->vdev->unit_address);
+- entry = create_proc_entry(u_addr, S_IFREG, ibmveth_proc_dir);
+- if (!entry) {
++ entry = proc_create_data(u_addr, S_IFREG, ibmveth_proc_dir,
++ &ibmveth_proc_fops, adapter);
++ if (!entry)
+ ibmveth_error_printk("Cannot create adapter proc entry");
+- } else {
+- entry->data = (void *) adapter;
+- entry->proc_fops = &ibmveth_proc_fops;
+- }
+ }
+ return;
}
+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;
- 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;
+ pci_set_master(pdev);
++ pci_save_state(pdev);
-@@ -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;
+ 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_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
-diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
-index 10af742..365626d 100644
---- a/drivers/net/e1000/e1000_osdep.h
-+++ b/drivers/net/e1000/e1000_osdep.h
-@@ -41,13 +41,6 @@
- #include <linux/interrupt.h>
- #include <linux/sched.h>
+ 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,
+ },
+ };
--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 @@
- /*******************************************************************************
+@@ -2256,6 +2257,7 @@ static void FIR2SIR(int iobase)
+ MODULE_AUTHOR("Benjamin Kong <benjamin_kong at ali.com.tw>");
+ MODULE_DESCRIPTION("ALi FIR Controller Driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:" ALI_IRCC_DRIVER_NAME);
- 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;
+ module_param_array(io, int, NULL, 0);
+diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
+index fc753d7..e6f40b7 100644
+--- a/drivers/net/irda/irtty-sir.c
++++ b/drivers/net/irda/irtty-sir.c
+@@ -64,7 +64,7 @@ static int irtty_chars_in_buffer(struct sir_dev *dev)
+ IRDA_ASSERT(priv != NULL, return -1;);
+ IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
+
+- return priv->tty->driver->chars_in_buffer(priv->tty);
++ return tty_chars_in_buffer(priv->tty);
+ }
+
+ /* Wait (sleep) until underlaying hardware finished transmission
+@@ -93,10 +93,8 @@ static void irtty_wait_until_sent(struct sir_dev *dev)
+ IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;);
-- 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;
+ tty = priv->tty;
+- if (tty->driver->wait_until_sent) {
+- lock_kernel();
+- tty->driver->wait_until_sent(tty, msecs_to_jiffies(100));
+- unlock_kernel();
++ if (tty->ops->wait_until_sent) {
++ tty->ops->wait_until_sent(tty, msecs_to_jiffies(100));
}
+ else {
+ msleep(USBSERIAL_TX_DONE_DELAY);
+@@ -125,48 +123,14 @@ static int irtty_change_speed(struct sir_dev *dev, unsigned speed)
-@@ -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;
+ tty = priv->tty;
+
+- lock_kernel();
++ mutex_lock(&tty->termios_mutex);
+ old_termios = *(tty->termios);
+ cflag = tty->termios->c_cflag;
+-
+- cflag &= ~CBAUD;
+-
+- IRDA_DEBUG(2, "%s(), Setting speed to %d\n", __FUNCTION__, speed);
+-
+- switch (speed) {
+- case 1200:
+- cflag |= B1200;
+- break;
+- case 2400:
+- cflag |= B2400;
+- break;
+- case 4800:
+- cflag |= B4800;
+- break;
+- case 19200:
+- cflag |= B19200;
+- break;
+- case 38400:
+- cflag |= B38400;
+- break;
+- case 57600:
+- cflag |= B57600;
+- break;
+- case 115200:
+- cflag |= B115200;
+- break;
+- case 9600:
+- default:
+- cflag |= B9600;
+- break;
+- }
+-
+- tty->termios->c_cflag = cflag;
+- if (tty->driver->set_termios)
+- tty->driver->set_termios(tty, &old_termios);
+- unlock_kernel();
+-
++ tty_encode_baud_rate(tty, speed, speed);
++ if (tty->ops->set_termios)
++ tty->ops->set_termios(tty, &old_termios);
+ priv->io.speed = speed;
++ mutex_unlock(&tty->termios_mutex);
- /* 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;
}
+@@ -202,8 +166,8 @@ static int irtty_set_dtr_rts(struct sir_dev *dev, int dtr, int rts)
+ * This function is not yet defined for all tty driver, so
+ * let's be careful... Jean II
+ */
+- IRDA_ASSERT(priv->tty->driver->tiocmset != NULL, return -1;);
+- priv->tty->driver->tiocmset(priv->tty, NULL, set, clear);
++ IRDA_ASSERT(priv->tty->ops->tiocmset != NULL, return -1;);
++ priv->tty->ops->tiocmset(priv->tty, NULL, set, clear);
--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;
+ return 0;
+ }
+@@ -225,17 +189,13 @@ static int irtty_do_write(struct sir_dev *dev, const unsigned char *ptr, size_t
+ IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
-- /* 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;
+ tty = priv->tty;
+- if (!tty->driver->write)
++ if (!tty->ops->write)
+ return 0;
+ tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+- if (tty->driver->write_room) {
+- writelen = tty->driver->write_room(tty);
+- if (writelen > len)
+- writelen = len;
+- }
+- else
++ writelen = tty_write_room(tty);
++ if (writelen > len)
+ writelen = len;
+- return tty->driver->write(tty, ptr, writelen);
++ return tty->ops->write(tty, ptr, writelen);
+ }
-@@ -496,7 +512,8 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
+ /* ------------------------------------------------------- */
+@@ -321,7 +281,7 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
+ struct ktermios old_termios;
+ int cflag;
- /* 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;
+- lock_kernel();
++ mutex_lock(&tty->termios_mutex);
+ old_termios = *(tty->termios);
+ cflag = tty->termios->c_cflag;
+
+@@ -331,9 +291,9 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
+ cflag |= CREAD;
-- /* 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;
+ tty->termios->c_cflag = cflag;
+- if (tty->driver->set_termios)
+- tty->driver->set_termios(tty, &old_termios);
+- unlock_kernel();
++ if (tty->ops->set_termios)
++ tty->ops->set_termios(tty, &old_termios);
++ mutex_unlock(&tty->termios_mutex);
+ }
+
+ /*****************************************************************/
+@@ -359,8 +319,8 @@ static int irtty_start_dev(struct sir_dev *dev)
+
+ tty = priv->tty;
+
+- if (tty->driver->start)
+- tty->driver->start(tty);
++ if (tty->ops->start)
++ tty->ops->start(tty);
+ /* Make sure we can receive more data */
+ irtty_stop_receiver(tty, FALSE);
+
+@@ -388,8 +348,8 @@ static int irtty_stop_dev(struct sir_dev *dev)
+
+ /* Make sure we don't receive more data */
+ irtty_stop_receiver(tty, TRUE);
+- if (tty->driver->stop)
+- tty->driver->stop(tty);
++ if (tty->ops->stop)
++ tty->ops->stop(tty);
+
+ mutex_unlock(&irtty_mutex);
+
+@@ -483,11 +443,10 @@ static int irtty_open(struct tty_struct *tty)
+
+ /* stop the underlying driver */
+ irtty_stop_receiver(tty, TRUE);
+- if (tty->driver->stop)
+- tty->driver->stop(tty);
++ if (tty->ops->stop)
++ tty->ops->stop(tty);
+
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ tty_driver_flush_buffer(tty);
+
+ /* apply mtt override */
+ sir_tty_drv.qos_mtt_bits = qos_mtt_bits;
+@@ -564,8 +523,8 @@ static void irtty_close(struct tty_struct *tty)
+ /* Stop tty */
+ irtty_stop_receiver(tty, TRUE);
+ tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+- if (tty->driver->stop)
+- tty->driver->stop(tty);
++ if (tty->ops->stop)
++ tty->ops->stop(tty);
- 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;
+ kfree(priv);
- 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;
+diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c
+index 93916cf..ad92d3f 100644
+--- a/drivers/net/irda/mcs7780.c
++++ b/drivers/net/irda/mcs7780.c
+@@ -464,7 +464,7 @@ static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len)
+ }
-- /* 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)
+ fcs = ~(crc32_le(~0, buf, new_len));
+- if(fcs != le32_to_cpu(get_unaligned((__le32 *)(buf+new_len)))) {
++ if(fcs != get_unaligned_le32(buf + new_len)) {
+ IRDA_ERROR("crc error calc 0x%x len %d\n", fcs, new_len);
+ mcs->stats.rx_errors++;
+ mcs->stats.rx_crc_errors++;
+diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
+index 8c09344..d5c2d27 100644
+--- a/drivers/net/irda/pxaficp_ir.c
++++ b/drivers/net/irda/pxaficp_ir.c
+@@ -36,6 +36,7 @@
+ #include <asm/hardware.h>
+ #include <asm/arch/irda.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
- msleep(10);
+ #ifdef CONFIG_MACH_MAINSTONE
+ #include <asm/arch/mainstone.h>
+@@ -831,6 +832,11 @@ static int pxa_irda_probe(struct platform_device *pdev)
+ if (err)
+ goto err_mem_5;
-- /* 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;
++ 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);
-- /* 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);
+ 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);
- /* 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);
+ 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,
+ },
+ };
- /* 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);
+@@ -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/irda/stir4200.c b/drivers/net/irda/stir4200.c
+index e59c485..0519637 100644
+--- a/drivers/net/irda/stir4200.c
++++ b/drivers/net/irda/stir4200.c
+@@ -329,7 +329,7 @@ static void fir_eof(struct stir_cb *stir)
+ }
+
+ fcs = ~(crc32_le(~0, rx_buff->data, len));
+- if (fcs != le32_to_cpu(get_unaligned((__le32 *)(rx_buff->data+len)))) {
++ if (fcs != get_unaligned_le32(rx_buff->data + len)) {
+ pr_debug("crc error calc 0x%x len %d\n", fcs, len);
+ stir->stats.rx_errors++;
+ stir->stats.rx_crc_errors++;
+diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
+index acd082a..d15e00b 100644
+--- a/drivers/net/irda/vlsi_ir.c
++++ b/drivers/net/irda/vlsi_ir.c
+@@ -1674,13 +1674,12 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ if (vlsi_proc_root != NULL) {
+ struct proc_dir_entry *ent;
+
+- ent = create_proc_entry(ndev->name, S_IFREG|S_IRUGO, vlsi_proc_root);
++ ent = proc_create_data(ndev->name, S_IFREG|S_IRUGO,
++ vlsi_proc_root, VLSI_PROC_FOPS, ndev);
+ if (!ent) {
+ IRDA_WARNING("%s: failed to create proc entry\n",
+ __FUNCTION__);
+ } else {
+- ent->data = ndev;
+- ent->proc_fops = VLSI_PROC_FOPS;
+ ent->size = 0;
+ }
+ idev->proc_entry = ent;
+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)
- /* ...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);
- }
+ 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 };
-- /* 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;
+ 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;
+ };
- /* Transmit Descriptor Control 0 */
-- reg = er32(TXDCTL);
-+ reg = er32(TXDCTL(0));
- reg |= (1 << 22);
-- ew32(TXDCTL, reg);
-+ ew32(TXDCTL(0), reg);
+ 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;
- /* Transmit Descriptor Control 1 */
-- reg = er32(TXDCTL1);
-+ reg = er32(TXDCTL(1));
- reg |= (1 << 22);
-- ew32(TXDCTL1, reg);
-+ ew32(TXDCTL(1), reg);
+ 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;
- /* 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);
+ /* 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;
- /* 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)
+ /* 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
+ };
- 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)
- }
+ /* 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[];
- /**
-- * 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--;
++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);
-- 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);
- }
+ 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);
- /**
-@@ -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)
+-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)
{
-- /* 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;
+ /* 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;
- 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)
+ /* 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;
- /* 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;
+ /* 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;
-- /* 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;
+ eecd_reg = IXGB_READ_REG(hw, EECD);
- 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 @@
- /*******************************************************************************
+@@ -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;
- Intel PRO/1000 Linux driver
-- Copyright(c) 1999 - 2007 Intel Corporation.
-+ Copyright(c) 1999 - 2008 Intel Corporation.
+ eecd_reg = IXGB_READ_REG(hw, EECD);
- 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
+@@ -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;
- /* 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 */
+ eecd_reg = IXGB_READ_REG(hw, EECD);
--/* 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
+@@ -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;
- /* 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 */
+ eecd_reg = IXGB_READ_REG(hw, EECD);
--/* 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,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;
-@@ -279,7 +282,7 @@
- #define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */
+ /* 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);
- /* 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
+ if(eecd_reg & IXGB_EECD_DO)
+- return (TRUE);
++ return (true);
- /* 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 */
+ udelay(50);
+ }
+ ASSERT(0);
+- return (FALSE);
++ return (false);
+ }
- #define E1000_PBS_16K E1000_PBA_16K
+ /******************************************************************************
+@@ -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;
-@@ -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 */
+ for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++)
+ checksum += ixgb_read_eeprom(hw, i);
--/* 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 */
+- if(checksum == (uint16_t) EEPROM_SUM)
+- return (TRUE);
++ if(checksum == (u16) EEPROM_SUM)
++ return (true);
+ else
+- return (FALSE);
++ return (false);
+ }
- /* 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 */
+ /******************************************************************************
+@@ -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;
- /* 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
+ for(i = 0; i < EEPROM_CHECKSUM_REG; i++)
+ checksum += ixgb_read_eeprom(hw, i);
- /* 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) */
+- checksum = (uint16_t) EEPROM_SUM - checksum;
++ checksum = (u16) EEPROM_SUM - checksum;
- /* 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 */
+ 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;
- /* 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
+@@ -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;
- /* 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 */
+ /* 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;
- /* 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 */
+ DEBUGFUNC("ixgb_get_eeprom_data");
+@@ -473,27 +473,27 @@ ixgb_get_eeprom_data(struct ixgb_hw *hw)
- #define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7
+ 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);
+ }
--/* 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
+- 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);
+ }
--/* 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 @@
- /*******************************************************************************
+ 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);
+ }
- Intel PRO/1000 Linux driver
-- Copyright(c) 1999 - 2007 Intel Corporation.
-+ Copyright(c) 1999 - 2008 Intel Corporation.
+- return(TRUE);
++ return(true);
+ }
- 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)
+ /******************************************************************************
+@@ -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)
+ {
--/* 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
+ 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]);
+ }
- #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 */
+@@ -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;
- /* 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;
- };
+ DEBUGFUNC("ixgb_get_ee_mac_addr");
-+/* 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 {
+- 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));
- spinlock_t tx_queue_lock; /* prevent concurrent tail updates */
+@@ -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;
-- /* this is still needed for 82571 and above */
-- atomic_t irq_sem;
--
- /* track device up/down/testing state */
- unsigned long state;
+- 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));
-@@ -180,7 +192,7 @@ struct e1000_adapter {
- u16 rx_itr;
+ 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 @@
- /*
-- * 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;
+ /* 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;
+ };
-- /* 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;
+ /* EEPROM Functions */
+-uint16_t ixgb_read_eeprom(struct ixgb_hw *hw, uint16_t reg);
++u16 ixgb_read_eeprom(struct ixgb_hw *hw, u16 reg);
- /*
-- * 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;
+-boolean_t ixgb_validate_eeprom_checksum(struct ixgb_hw *hw);
++bool ixgb_validate_eeprom_checksum(struct ixgb_hw *hw);
-- /* 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;
+ void ixgb_update_eeprom_checksum(struct ixgb_hw *hw);
- unsigned int rx_ps_pages;
- u16 rx_ps_bsize0;
-+ u32 max_frame_size;
-+ u32 min_frame_size;
+-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);
- /* 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;
+ #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 @@
-+ /* 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;
+ #include <asm/uaccess.h>
-- u8 fc_autoneg;
-+ bool fc_autoneg;
+-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
- unsigned long led_status;
+ 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;
-@@ -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)
+ 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;
+ }
- #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;
+-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)
+ }
--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);
+ 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);
- extern s32 e1000e_commit_phy(struct e1000_hw *hw);
+ adapter->rx_csum = data;
-@@ -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);
+ 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 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 @@
- /*******************************************************************************
+ 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)
+ }
- Intel PRO/1000 Linux driver
-- Copyright(c) 1999 - 2007 Intel Corporation.
-+ Copyright(c) 1999 - 2008 Intel Corporation.
+ 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;
+ }
- 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
+-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)
+ }
- #define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS 0x0008
- #define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS 0x0800
-@@ -48,6 +49,7 @@
+ 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;
+ }
- #define E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004
- #define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT 0x0000
-+#define E1000_KMRNCTRLSTA_OPMODE_E_IDLE 0x2000
+@@ -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;
- #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
+ /* 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 */
-+/* 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 */
+- regs->len = (reg - reg_start) * sizeof(uint32_t);
++ regs->len = (reg - reg_start) * sizeof(u32);
+ }
--/* 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;
+ static int
+@@ -416,7 +407,7 @@ ixgb_get_eeprom_len(struct net_device *netdev)
-- 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;
+ 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));
}
-- nvm->type = e1000_nvm_eeprom_spi;
-+ nvm->type = e1000_nvm_eeprom_spi;
+- memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset & 1),
++ memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1),
+ eeprom->len);
+ kfree(eeprom_buff);
- size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
- E1000_EECD_SIZE_EX_SHIFT);
+@@ -464,14 +455,14 @@ geeprom_error:
-- /* 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;
+ 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;
- 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;
- }
+ if(eeprom->len == 0)
+ return -EINVAL;
+@@ -570,14 +561,14 @@ ixgb_set_ringparam(struct net_device *netdev,
+ return -EINVAL;
-@@ -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;
+ if(netif_running(adapter->netdev))
+- ixgb_down(adapter,TRUE);
++ ixgb_down(adapter, true);
- /* 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;
+- 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 s32 e1000_get_invariants_80003es2lan(struct e1000_adapter *adapter)
-+static s32 e1000_get_variants_80003es2lan(struct e1000_adapter *adapter)
+ static int
+-ixgb_phys_id(struct net_device *netdev, uint32_t data)
++ixgb_phys_id(struct net_device *netdev, u32 data)
{
- struct e1000_hw *hw = &adapter->hw;
- s32 rc;
-@@ -265,6 +275,7 @@ static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw)
- u16 mask;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
- mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
-+ mask |= E1000_SWFW_CSR_SM;
+@@ -669,7 +660,7 @@ ixgb_get_sset_count(struct net_device *netdev, int sset)
- return e1000_acquire_swfw_sync_80003es2lan(hw, mask);
+ 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;
+ }
}
-@@ -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);
- }
+ 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;
-@@ -344,8 +357,10 @@ static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
- if (!(swfw_sync & (fwmask | swmask)))
- break;
+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 @@
-- /* 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;
+ /* Local function prototypes */
-+ 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;
-+ }
+-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);
- 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;
-+ }
+-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);
-- /* 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);
+ static void ixgb_get_bus_info(struct ixgb_hw *hw);
- /* ...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);
+-static boolean_t ixgb_link_reset(struct ixgb_hw *hw);
++static bool ixgb_link_reset(struct ixgb_hw *hw);
- if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
- ret_val = -E1000_ERR_PHY;
-+ e1000_release_phy_80003es2lan(hw);
- return ret_val;
- }
+ static void ixgb_optics_reset(struct ixgb_hw *hw);
- udelay(200);
+@@ -55,18 +55,18 @@ static void ixgb_clear_vfta(struct ixgb_hw *hw);
-- 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);
+ static void ixgb_init_rx_addrs(struct ixgb_hw *hw);
- udelay(200);
-+ e1000_release_phy_80003es2lan(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);
- return ret_val;
- }
-@@ -458,40 +483,51 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
- u32 page_select;
- u16 temp;
+-static boolean_t ixgb_setup_fc(struct ixgb_hw *hw);
++static bool ixgb_setup_fc(struct ixgb_hw *hw);
-+ 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;
-+ }
+-static boolean_t mac_addr_valid(uint8_t *mac_addr);
++static bool mac_addr_valid(u8 *mac_addr);
- 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;
-+ }
+-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");
-- /* 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...
+@@ -127,13 +127,13 @@ ixgb_adapter_stop(struct ixgb_hw *hw)
*/
- udelay(200);
+ if(hw->adapter_stopped) {
+ DEBUGOUT("Exiting because the adapter is already stopped!!!\n");
+- return FALSE;
++ return false;
+ }
- /* ...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);
+ /* Set the Adapter Stopped flag so other driver functions stop
+ * touching the Hardware.
+ */
+- hw->adapter_stopped = TRUE;
++ hw->adapter_stopped = true;
-- if (((u16)offset >> GG82563_PAGE_SHIFT) != temp)
-+ if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
-+ e1000_release_phy_80003es2lan(hw);
- return -E1000_ERR_PHY;
-+ }
+ /* 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;
- udelay(200);
+ 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;
-- 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);
+ DEBUGFUNC("ixgb_init_hw");
- udelay(200);
-+ e1000_release_phy_80003es2lan(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);
- return ret_val;
- }
-@@ -554,7 +590,8 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
- u16 phy_data;
- bool link;
+- if (ixgb_get_eeprom_data(hw) == FALSE) {
+- return(FALSE);
+- }
++ if (!ixgb_get_eeprom_data(hw))
++ return false;
-- /* 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.
+ /* 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)
*/
- 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)
+ if (!mac_addr_valid(hw->curr_mac_addr)) {
+ DEBUGOUT("MAC address invalid after ixgb_init_rx_addrs\n");
+- return(FALSE);
++ return(false);
+ }
- udelay(1);
+ /* tell the routines in this file they can access hardware again */
+- hw->adapter_stopped = FALSE;
++ hw->adapter_stopped = false;
-- 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");
+ /* 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;
-@@ -593,7 +630,8 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
- return ret_val;
+ DEBUGFUNC("ixgb_init_rx_addrs");
- 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;
+@@ -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 */
-- /* 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;
+ DEBUGFUNC("ixgb_mc_addr_list_update");
-- /* 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,
+@@ -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)
{
- s32 ret_val;
+- uint32_t hash_value = 0;
++ u32 hash_value = 0;
-- 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;
+ DEBUGFUNC("ixgb_hash_mc_addr");
-- /* 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);
+@@ -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;
- /* 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);
+ /* 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;
- /* ...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);
+ DEBUGFUNC("ixgb_rar_set");
- /* 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);
+ /* 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));
-- /* 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;
+- rar_high = ((uint32_t) addr[4] |
+- ((uint32_t)addr[5] << 8) |
++ rar_high = ((u32) addr[4] |
++ ((u32)addr[5] << 8) |
+ IXGB_RAH_AV);
- /* Transmit Descriptor Control 0 */
-- reg = er32(TXDCTL);
-+ reg = er32(TXDCTL(0));
- reg |= (1 << 22);
-- ew32(TXDCTL, reg);
-+ ew32(TXDCTL(0), reg);
+ 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;
- /* Transmit Descriptor Control 1 */
-- reg = er32(TXDCTL1);
-+ reg = er32(TXDCTL(1));
- reg |= (1 << 22);
-- ew32(TXDCTL1, reg);
-+ ew32(TXDCTL(1), reg);
+ 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
+ *****************************************************************************/
- /* 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);
+-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;
- /* 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);
- }
+ DEBUGFUNC("ixgb_setup_fc");
- /**
-@@ -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;
+@@ -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;
-- 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;
+ 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);
+ }
-@@ -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;
+ /******************************************************************************
+@@ -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;
-- 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;
+ ASSERT(reg_address <= IXGB_MAX_PHY_REG_ADDRESS);
+ ASSERT(phy_address <= IXGB_MAX_PHY_ADDRESS);
+ ASSERT(device_type <= IXGB_MAX_PHY_DEV_TYPE);
-- /* 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;
- }
+ /* 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);
-- /* 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;
- }
+ /* 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;
-- /* 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;
+ DEBUGFUNC("ixgb_check_for_link");
-+ 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;
+@@ -950,7 +949,7 @@ ixgb_check_for_link(struct ixgb_hw *hw)
-- /* 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;
+ 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;
-- 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));
+ 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;
- 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;
- }
+ DEBUGFUNC("ixgb_clear_hw_cntrs");
-- /* 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);
+@@ -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);
-- /* 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;
+ /* 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);
-@@ -1053,12 +1119,12 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
+ /* 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)
{
- s32 ret_val;
- u32 tipg;
-- u16 reg_data;
-+ u32 i = 0;
-+ u16 reg_data, reg_data2;
+- uint32_t status_reg;
++ u32 status_reg;
- 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;
+ status_reg = IXGB_READ_REG(hw, STATUS);
-@@ -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);
+@@ -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");
-- 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));
+ /* 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;
- 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)
+ 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)
{
- s32 ret_val;
-- u16 reg_data;
-+ u16 reg_data, reg_data2;
- u32 tipg;
-+ u32 i = 0;
+ if (hw->phy_type == ixgb_phy_type_txn17401) {
+- uint16_t mdio_reg;
++ u16 mdio_reg;
- 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;
+ 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;
+ };
-@@ -1108,9 +1181,16 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
- tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN;
- ew32(TIPG, tipg);
+@@ -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;
+ };
-- 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));
+@@ -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 */
- 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 @@
- /*******************************************************************************
+ 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;
+ };
- Intel PRO/1000 Linux driver
-- Copyright(c) 1999 - 2007 Intel Corporation.
-+ Copyright(c) 1999 - 2008 Intel Corporation.
+@@ -637,33 +637,33 @@ struct ixgb_context_desc {
- 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)"
+ /* 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];
};
--#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;
+ /*
+ * 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))
-- if (hw->media_type == e1000_media_type_copper) {
-+ if (hw->phy.media_type == e1000_media_type_copper) {
+ /*
+ * 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)))
- ecmd->supported = (SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
-@@ -165,7 +165,7 @@ static int e1000_get_settings(struct net_device *netdev,
- ecmd->duplex = -1;
- }
+ /* 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 */
+ };
-- 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;
+@@ -685,139 +685,139 @@ struct ixgb_bus {
+ };
- /* 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;
+ 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;
+ };
-- /* 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,
+ /* 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;
+ };
- 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);
+ /* 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);
-- 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);
+ extern void ixgb_rar_set(struct ixgb_hw *hw,
+- uint8_t *addr,
+- uint32_t index);
++ u8 *addr,
++ u32 index);
- 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;
+ /* 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);
- 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));
- }
+ /* Vfta functions */
+ extern void ixgb_write_vfta(struct ixgb_hw *hw,
+- uint32_t offset,
+- uint32_t value);
++ u32 offset,
++ u32 value);
-@@ -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);
+ /* 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);
-- /* 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);
+ /* 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);
-- /* 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));
+ #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);
+ }
- 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;
+ int
+@@ -274,7 +271,7 @@ ixgb_up(struct ixgb_adapter *adapter)
-- /* 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;
- }
+ 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);
--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;
+ if(!(ctrl0 & IXGB_CTRL0_JFE)) {
+ ctrl0 |= IXGB_CTRL0_JFE;
+@@ -283,26 +280,30 @@ ixgb_up(struct ixgb_adapter *adapter)
}
}
-- return false;
-+ return 0;
+
+- 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;
}
- static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
- int reg, u32 mask, u32 write)
+ void
+-ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
++ixgb_down(struct ixgb_adapter *adapter, bool kill_watchdog)
{
-- 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)
+ 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
-
--#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)
++ /* waiting for NAPI to complete can re-enable interrupts */
+ ixgb_irq_disable(adapter);
+ free_irq(adapter->pdev->irq, netdev);
--#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)
+@@ -589,9 +590,9 @@ ixgb_sw_init(struct ixgb_adapter *adapter)
+ /* enable flow control to be programmed */
+ hw->fc.send_xon = 1;
- 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;
+- atomic_set(&adapter->irq_sem, 1);
+ spin_lock_init(&adapter->tx_lock);
-- /* 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;
++ set_bit(__IXGB_DOWN, &adapter->flags);
+ return 0;
+ }
- 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)
- }
- }
+@@ -656,7 +657,7 @@ ixgb_close(struct net_device *netdev)
+ {
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
-- /* 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)
- }
+- ixgb_down(adapter, TRUE);
++ ixgb_down(adapter, true);
- 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;
+ 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;
-@@ -1033,13 +1047,13 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
- if (!tx_ring->count)
- tx_ring->count = E1000_DEFAULT_TXD;
+ /* 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;
-- 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);
+ rctl = IXGB_READ_REG(&adapter->hw, RCTL);
- 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;
+@@ -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;
-- 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);
+ /* make sure receives are disabled while setting up the descriptors */
- 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;
- }
+@@ -881,7 +882,7 @@ ixgb_configure_rx(struct ixgb_adapter *adapter)
+ IXGB_WRITE_REG(hw, RXDCTL, rxdctl);
-@@ -1099,13 +1108,13 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
- if (!rx_ring->count)
- rx_ring->count = E1000_DEFAULT_RXD;
+ /* 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;
-- 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);
+ /* 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];
- 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;
+ IXGB_WRITE_REG(hw, RCTL, rctl);
+@@ -1164,7 +1165,7 @@ ixgb_watchdog(unsigned long data)
}
-- 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;
+ /* Force detection of hung controller every watchdog period */
+- adapter->detect_tx_hung = TRUE;
++ adapter->detect_tx_hung = true;
-- adapter->hw.mac.autoneg = 0;
-+ hw->mac.autoneg = 0;
+ /* 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 (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);
+ if (likely(skb_is_gso(skb))) {
+@@ -1243,12 +1244,12 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
+ return 0;
+ }
- ctrl_reg = er32(CTRL);
+-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 (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);
+ 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;
-@@ -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);
+- return TRUE;
++ return true;
+ }
- /* 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 */
+- 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 ((adapter->hw.mac.type == e1000_ich8lan) ||
-+ (adapter->hw.mac.type == e1000_ich9lan))
-+ ctrl_reg |= E1000_CTRL_SLU; /* Set Link Up */
+ if(skb->len <= 0) {
+ dev_kfree_skb_any(skb);
+ return 0;
}
-- 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)
+ #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);
- ew32(CTRL, ctrl_reg);
+ adapter->tx_timeout_count++;
+- ixgb_down(adapter, TRUE);
++ ixgb_down(adapter, true);
+ ixgb_up(adapter);
+ }
-- /* 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);
+@@ -1595,7 +1600,7 @@ ixgb_change_mtu(struct net_device *netdev, int new_mtu)
+ netdev->mtu = new_mtu;
- udelay(500);
-@@ -1244,8 +1264,10 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter)
+ if ((old_max_frame != max_frame) && netif_running(netdev)) {
+- ixgb_down(adapter, TRUE);
++ ixgb_down(adapter, true);
+ ixgb_up(adapter);
+ }
- /* special requirements for 82571/82572 fiber adapters */
+@@ -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 */
-- /* 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);
+- 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);
-@@ -1263,8 +1285,10 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter)
- ew32(CTRL, ctrl);
+ #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
+ **/
-- /* 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);
+-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;
-- /* 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;
+ 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)
- /* 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));
+ while(eop_desc->status & IXGB_TX_DESC_STATUS_DD) {
- return 0;
- }
-@@ -1312,8 +1338,8 @@ static int e1000_setup_loopback_test(struct e1000_adapter *adapter)
- struct e1000_hw *hw = &adapter->hw;
- u32 rctl;
+- for(cleaned = FALSE; !cleaned; ) {
++ for (cleaned = false; !cleaned; ) {
+ tx_desc = IXGB_TX_DESC(*tx_ring, i);
+ buffer_info = &tx_ring->buffer_info[i];
-- 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);
- }
+@@ -1839,7 +1843,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
-@@ -1347,18 +1373,17 @@ static void e1000_loopback_cleanup(struct e1000_adapter *adapter)
+ ixgb_unmap_and_free_tx_resource(adapter, buffer_info);
- 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)
+- *(uint32_t *)&(tx_desc->status) = 0;
++ *(u32 *)&(tx_desc->status) = 0;
- ew32(RDT, rx_ring->count - 1);
+ 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
+ **/
-- /* 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 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;
- 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;
+ 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);
- *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;
+- cleaned = TRUE;
++ cleaned = true;
-- /* 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,
+ 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;
- ndev_info(netdev, "offline testing starting\n");
+ 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);
+ }
-- /* 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;
+- ixgb_irq_enable(adapter);
++ /* don't enable interrupts unless we are UP */
++ if (adapter->netdev->flags & IFF_UP)
++ ixgb_irq_enable(adapter);
+ }
-@@ -1596,9 +1629,9 @@ static void e1000_diag_test(struct net_device *netdev,
- adapter->hw.mac.autoneg = autoneg;
+ 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;
- /* 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;
+ /* add VID to filter table */
- 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;
+@@ -2211,18 +2217,20 @@ ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
}
-+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)
+ 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 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,
- };
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+- uint32_t vfta, index;
++ u32 vfta, index;
- 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 @@
- /*******************************************************************************
+ ixgb_irq_disable(adapter);
- Intel PRO/1000 Linux driver
-- Copyright(c) 1999 - 2007 Intel Corporation.
-+ Copyright(c) 1999 - 2008 Intel Corporation.
+ vlan_group_set_device(adapter->vlgrp, vid, NULL);
- 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 */
+- ixgb_irq_enable(adapter);
++ /* don't enable interrupts unless we are UP */
++ if (adapter->netdev->flags & IFF_UP)
++ ixgb_irq_enable(adapter);
- /* 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
+- /* remove VID from filter table*/
++ /* remove VID from filter table */
- #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
+ 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);
-@@ -400,7 +402,7 @@ enum e1000_rev_polarity{
- e1000_rev_polarity_undefined = 0xFF
- };
+ 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);
--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];
+ if(netif_running(netdev))
+- ixgb_down(adapter, TRUE);
++ ixgb_down(adapter, true);
- enum e1000_mac_type type;
-- enum e1000_fc_mode fc;
-- enum e1000_fc_mode original_fc;
+ pci_disable_device(pdev);
- 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;
+diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h
+index 9e04a6b..4be1b27 100644
+--- a/drivers/net/ixgb/ixgb_osdep.h
++++ b/drivers/net/ixgb/ixgb_osdep.h
+@@ -39,13 +39,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/sched.h>
-@@ -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;
+-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"
- u8 forced_speed_duplex;
++#ifdef CONFIG_DCA
++#include <linux/dca.h>
++#endif
-@@ -780,6 +770,8 @@ struct e1000_phy_info {
- u32 reset_delay_us; /* in usec */
- u32 revision;
+ #define IXGBE_ERR(args...) printk(KERN_ERR "ixgbe: " args)
-+ 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;
+@@ -120,7 +123,6 @@ struct ixgbe_queue_stats {
};
- struct e1000_nvm_info {
-@@ -817,6 +809,16 @@ struct e1000_bus_info {
- u16 func;
- };
+ 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;
-+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;
-+};
++ 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 */
+
- 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;
++#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 */
- 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;
+ u32 eims_value;
+ u16 itr_register;
+@@ -146,6 +162,33 @@ struct ixgbe_ring {
+ u16 work_limit; /* max work per interrupt */
};
- #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 @@
- /*******************************************************************************
++#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 {
- Intel PRO/1000 Linux driver
-- Copyright(c) 1999 - 2007 Intel Corporation.
-+ Copyright(c) 1999 - 2008 Intel Corporation.
+ #define IXGBE_MAX_JUMBO_FRAME_SIZE 16128
- 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;
++#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;
-- /* 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)
+ /* 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;
- gfpreg = er32flash(ICH_FLASH_GFPREG);
+ u64 rx_hdr_split;
+ u32 alloc_rx_page_failed;
+ u32 alloc_rx_buff_failed;
-- /* 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.
++ /* Some features need tri-state capability,
++ * thus the additional *_CAPABLE flags.
+ */
- 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;
+ 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)
-- /* 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;
+ /* 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;
- /* Set media type function pointer */
-- hw->media_type = e1000_media_type_copper;
-+ hw->phy.media_type = e1000_media_type_copper;
+ 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)
- /* Set mta register count */
- mac->mta_reg_count = 32;
-@@ -313,7 +316,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
+ 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;
}
-
--static s32 e1000_get_invariants_ich8lan(struct e1000_adapter *adapter)
-+static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
+@@ -873,13 +886,13 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
{
- struct e1000_hw *hw = &adapter->hw;
- s32 rc;
-@@ -450,7 +453,7 @@ static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw)
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
- udelay(1);
+- 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 (phy->wait_for_link) {
-+ if (phy->autoneg_wait_to_complete) {
- hw_dbg(hw, "Waiting for forced speed/duplex link on IFE phy.\n");
+- 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;
- 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;
+@@ -893,22 +906,26 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
-- /* 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 ((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;
-- /* 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.
+ /* convert to rate of irq's per second */
+- if (ec->rx_coalesce_usecs == 0)
+- adapter->rx_eitr = 0;
++ if (ec->rx_coalesce_usecs < IXGBE_MIN_ITR_USECS)
++ adapter->rx_eitr = ec->rx_coalesce_usecs;
+ else
+ adapter->rx_eitr = (1000000 / ec->rx_coalesce_usecs);
+
+- if (ec->tx_coalesce_usecs == 0)
+- adapter->tx_eitr = 0;
++ if (ec->tx_coalesce_usecs < IXGBE_MIN_ITR_USECS)
++ adapter->tx_eitr = ec->rx_coalesce_usecs;
+ else
+ adapter->tx_eitr = (1000000 / ec->tx_coalesce_usecs);
+
+diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
+index c2095ce..7b85922 100644
+--- a/drivers/net/ixgbe/ixgbe_main.c
++++ b/drivers/net/ixgbe/ixgbe_main.c
+@@ -48,7 +48,7 @@ char ixgbe_driver_name[] = "ixgbe";
+ static const char ixgbe_driver_string[] =
+ "Intel(R) 10 Gigabit PCI Express Network Driver";
+
+-#define DRV_VERSION "1.1.18"
++#define DRV_VERSION "1.3.18-k2"
+ const char ixgbe_driver_version[] = DRV_VERSION;
+ static const char ixgbe_copyright[] =
+ "Copyright (c) 1999-2007 Intel Corporation.";
+@@ -80,6 +80,16 @@ static struct pci_device_id ixgbe_pci_tbl[] = {
+ };
+ MODULE_DEVICE_TABLE(pci, ixgbe_pci_tbl);
+
++#ifdef CONFIG_DCA
++static int ixgbe_notify_dca(struct notifier_block *, unsigned long event,
++ void *p);
++static struct notifier_block dca_notifier = {
++ .notifier_call = ixgbe_notify_dca,
++ .next = NULL,
++ .priority = 0
++};
++#endif
++
+ MODULE_AUTHOR("Intel Corporation, <linux.nics at intel.com>");
+ MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver");
+ MODULE_LICENSE("GPL");
+@@ -256,26 +266,125 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter,
+ * sees the new next_to_clean.
*/
-@@ -536,8 +541,10 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
- data &= ~E1000_STATUS_LAN_INIT_DONE;
- ew32(STATUS, data);
+ 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
+ }
-- /* 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;
+ 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
-- /* Configure LCD from extended configuration
-- * region. */
-+ /* Configure LCD from extended configuration region. */
+ if (total_tx_packets >= tx_ring->work_limit)
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->eims_value);
- /* 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;
++ 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;
+ }
-- /* 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);
++#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;
-- /* 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);
++ 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;
+ }
-- /* 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;
+-#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;
- 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;
+- 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;
- 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;
+- 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));
+ }
- 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;
+- 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;
+ }
- 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);
+ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
+@@ -614,153 +895,302 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
-- /* 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);
+ 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;
- /* 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;
+- 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);
++ }
- 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 IRQ_HANDLED;
+ }
- return 0;
-@@ -944,7 +950,8 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
++/**
++ * 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);
- ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
+- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rxr->eims_value);
+- netif_rx_schedule(adapter->netdev, &adapter->napi);
+ return IRQ_HANDLED;
+ }
-- /* 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)
- */
++/**
++ * 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;
- 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);
+- /* 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
-- /* 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)
+ ixgbe_clean_rx_irq(adapter, rxr, &work_done, budget);
- ret_val = e1000e_update_nvm_checksum_generic(hw);
- if (ret_val)
-- return ret_val;;
-+ return ret_val;
+- /* 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);
+ }
- if (nvm->type != e1000_nvm_flash_sw)
-- return ret_val;;
-+ return ret_val;
+ return work_done;
+ }
- ret_val = e1000_acquire_swflag_ich8lan(hw);
- if (ret_val)
-- return ret_val;;
-+ return ret_val;
++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;
-- /* We're writing to the opposite bank so if we're on bank 1,
+- /* +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;
+ /*
-+ * 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
++ * The ideal configuration...
++ * We have enough vectors to map one per queue.
+ */
- 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 (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);
-- /* 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;
+- 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);
-@@ -1230,18 +1252,22 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
- break;
- }
+- err = pci_enable_msix(adapter->pdev, adapter->msix_entries,
+- max_msix_count);
+- if (err)
+ goto out;
++ }
-- /* Don't bother writing the segment valid bits if sector
-- * programming failed. */
+- 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;
+ /*
-+ * Don't bother writing the segment valid bits if sector
-+ * programming failed.
++ * 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.
+ */
- if (ret_val) {
- hw_dbg(hw, "Flash commit failed.\n");
- e1000_release_swflag_ich8lan(hw);
- return ret_val;
++ /* 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++;
}
-- /* 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;
+- 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++;
}
-- /* 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);
+- 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;
+ }
-- /* 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;
+- /* FIXME: implement netif_napi_remove() instead */
+- adapter->napi.poll = ixgbe_clean_rxonly;
+- adapter->flags |= IXGBE_FLAG_MSIX_ENABLED;
+ return 0;
-- /* 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);
+-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;
+ }
-- /* 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;
++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;
-- /* 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)
+- eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
- ret_val = e1000e_get_bus_info_pcie(hw);
++ /* 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 */
-- /* 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;
+@@ -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);
+ }
-- /* 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);
+ return IRQ_HANDLED;
+ }
-- /* 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);
++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;
- 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);
+- /* 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);
+ }
- /* 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);
+- err = request_irq(adapter->pdev->irq, handler, flags,
+- netdev->name, netdev);
+ if (err)
+ DPRINTK(PROBE, ERR, "request_irq failed, Error %d\n", err);
-- /* 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);
+-request_done:
+ return err;
+ }
-- /* 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);
+@@ -841,28 +1274,22 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
+ struct net_device *netdev = adapter->netdev;
- /* Transmit Descriptor Control 0 */
-- reg = er32(TXDCTL);
-+ reg = er32(TXDCTL(0));
- reg |= (1 << 22);
-- ew32(TXDCTL, reg);
-+ ew32(TXDCTL(0), reg);
+ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+- int i;
++ int i, q_vectors;
- /* Transmit Descriptor Control 1 */
-- reg = er32(TXDCTL1);
-+ reg = er32(TXDCTL(1));
- reg |= (1 << 22);
-- ew32(TXDCTL1, reg);
-+ ew32(TXDCTL(1), reg);
+- 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;
+- }
- /* 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);
+- 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);
+ }
+ }
- /* 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);
+@@ -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);
++ }
+ }
- /* Device Status */
- if (hw->mac.type == e1000_ich8lan) {
-@@ -1807,29 +1852,29 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
+ /**
+@@ -883,12 +1316,9 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
**/
- static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
+ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
{
-- 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);
+- 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);
}
-@@ -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.
+@@ -898,20 +1328,18 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
**/
-@@ -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);
+ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
+ {
+- int i;
+ struct ixgbe_hw *hw = &adapter->hw;
-- /* 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);
+- 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));
- /* unable to acquire PCS lock */
-@@ -1970,7 +2021,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
+ 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");
}
/**
-- * 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);
+@@ -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;
-- /* 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
+ /* 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.
+ */
- if (hw->mac.type == e1000_ich8lan)
- e1000e_gig_downshift_workaround_ich8lan(hw);
++ 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);
+ }
-@@ -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 @@
- /*******************************************************************************
+ #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;
- Intel PRO/1000 Linux driver
-- Copyright(c) 1999 - 2007 Intel Corporation.
-+ Copyright(c) 1999 - 2008 Intel Corporation.
+ /* 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)
- 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 {
+ 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);
- #define E1000_FACTPS_MNGCG 0x20000000
+ 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);
+ }
--#define E1000_IAMT_SIGNATURE 0x544D4149 /* Intel(R) Active Management
-- * Technology signature */
-+/* Intel(R) Active Management Technology signature */
-+#define E1000_IAMT_SIGNATURE 0x544D4149
+- 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);
+ }
- /**
- * 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;
+ /* 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]);
-- /* 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;
+ 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);
++ }
-- /* 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;
+- /* 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);
+ }
-- /* 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++;
+ static void ixgbe_vlan_rx_register(struct net_device *netdev,
+@@ -1219,6 +1636,42 @@ static void ixgbe_set_multi(struct net_device *netdev)
-- /* 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)
++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)
{
- u32 hash_value;
- u32 i;
+ 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;
-- /* 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;
+ ixgbe_get_hw_control(adapter);
-- /* 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;
+- 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);
+ }
-- /* 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)
+- 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);
++ }
- mac->get_link_status = 0;
++ 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)
+ }
-- /* 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);
+ 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);
+ }
-- /* 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;
+ 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);
-- /* 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);
+ 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);
-- /* 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);
+ /* 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;
-- /* 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);
+ 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 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)
+ 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,
+ }
- 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)
+ /**
+- * 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 s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
+-static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter)
++static void ixgbe_clean_all_rx_rings(struct ixgbe_adapter *adapter)
{
-- struct e1000_mac_info *mac = &hw->mac;
- s32 ret_val;
- u16 nvm_data;
+ int i;
-- /* 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)
- }
+- 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]);
+ }
- 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;
+ /**
+- * 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;
- return 0;
+- 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]);
}
-@@ -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;
- }
+ 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);
-- /* 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;
+- napi_disable(&adapter->napi);
+-
+ ixgbe_irq_disable(adapter);
-- 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);
++ ixgbe_napi_disable_all(adapter);
+ del_timer_sync(&adapter->watchdog_timer);
- /* Call the necessary media_type subroutine to configure the link. */
- ret_val = mac->ops.setup_physical_interface(hw);
- if (ret_val)
- return ret_val;
+ netif_carrier_off(netdev);
+@@ -1547,27 +2014,37 @@ static void ixgbe_shutdown(struct pci_dev *pdev)
+ }
-- /* 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);
+ /**
+- * 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;
-- ew32(FCTTV, mac->fc_pause_time);
-+ ew32(FCTTV, hw->fc.pause_time);
+- /* 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);
- 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;
+ if (tx_cleaned)
+ work_done = budget;
-- /* 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 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);
+ }
-- /* 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;
++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;
-- /* 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);
+ 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 these adapters, the SW defineable pin 1 is set when the optics
++ 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;
++
+ /*
-+ * 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,
++ * 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;
++
+ /*
-+ * 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;
++ * 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);
}
- 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)
++ 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 e1000_mac_info *mac = &hw->mac;
- u32 ctrl;
+ 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;
- ctrl = er32(CTRL);
+ /* default flow control settings */
+ hw->fc.original_type = ixgbe_fc_full;
+ hw->fc.type = ixgbe_fc_full;
-- /* 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);
++ /* 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;
+ }
-- 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;
+- /* 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;
-- /* 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);
+- 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;
}
-@@ -988,13 +1019,15 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
- return ret_val;
+- 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);
-- /* 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;
- }
+- 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);
-- /* 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;
+ rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
+@@ -1763,7 +2513,6 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
-- /* 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");
- }
+ rxdr->next_to_clean = 0;
+ rxdr->next_to_use = 0;
+- rxdr->adapter = adapter;
-- /* 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)
- }
+ return 0;
+ }
+@@ -1841,8 +2590,7 @@ static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter)
+ }
- if (duplex == HALF_DUPLEX)
-- mac->fc = e1000_fc_none;
-+ hw->fc.type = e1000_fc_none;
+ /**
+- * 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)
+ }
-- /* 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;
+ /**
+- * 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;
-- 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;
++ 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;
-- 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)
+ if (netif_running(netdev))
+@@ -1935,23 +2685,16 @@ static int ixgbe_open(struct net_device *netdev)
{
- u32 ctrl;
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ int err;
+- u32 num_rx_queues = adapter->num_rx_queues;
-- 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;
+ /* disallow open during test */
+ if (test_bit(__IXGBE_TESTING, &adapter->state))
+ return -EBUSY;
-- /* 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)
- }
+-try_intr_reinit:
+ /* allocate transmit descriptors */
+ err = ixgbe_setup_all_tx_resources(adapter);
+ if (err)
+ goto err_setup_tx;
- /**
-- * 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;
+- if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
+- num_rx_queues = 1;
+- adapter->num_rx_queues = num_rx_queues;
- }
-
-- e1000_standby_nvm(hw);
--
-- if ((nvm->address_bits == 8) && (offset >= 128))
-- read_opcode |= NVM_A8_OPCODE_SPI;
+ /* 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;
-
-- /* 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);
+- /* Reset the hardware, and start over. */
+- ixgbe_reset(adapter);
-
-- /* 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);
+- goto try_intr_reinit;
- }
-
-- 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;
+ 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
-- /* 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;
+ adapter->hw.mac.ops.check_link(&adapter->hw, &(link_speed), &link_up);
-- data[i] = (er32(EERD) >>
-- E1000_NVM_RW_REG_DATA);
-+ data[i] = (er32(EERD) >> E1000_NVM_RW_REG_DATA);
+@@ -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,
}
- 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;
+ pci_set_master(pdev);
++ pci_save_state(pdev);
-- /* 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)
++#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,
- e1000_standby_nvm(hw);
+ /* Setup hw api */
+ memcpy(&hw->mac.ops, ii->mac_ops, sizeof(hw->mac.ops));
++ hw->mac.type = ii->mac;
-- /* 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;
+ 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;
-@@ -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);
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ netdev->features |= NETIF_F_MULTI_QUEUE;
++#endif
- /* 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)
- }
+ /* 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;
- if (mac_addr_offset)
-- hw->dev_spec.e82571.alt_mac_addr_is_present = 1;
-+ hw->dev_spec.e82571.alt_mac_addr_is_present = 1;
+- /* 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);
- for (i = 0; i < ETH_ALEN; i += 2) {
-@@ -2244,7 +2236,7 @@ bool e1000e_check_mng_mode(struct e1000_hw *hw)
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
+@@ -2975,6 +3788,10 @@ static int __init ixgbe_init_module(void)
+
+ printk(KERN_INFO "%s: %s\n", ixgbe_driver_name, ixgbe_copyright);
+
++#ifdef CONFIG_DCA
++ dca_register_notify(&dca_notifier);
++
++#endif
+ ret = pci_register_driver(&ixgbe_driver);
+ return ret;
+ }
+@@ -2988,8 +3805,25 @@ module_init(ixgbe_init_module);
+ **/
+ static void __exit ixgbe_exit_module(void)
+ {
++#ifdef CONFIG_DCA
++ dca_unregister_notify(&dca_notifier);
++#endif
+ pci_unregister_driver(&ixgbe_driver);
}
++
++#ifdef CONFIG_DCA
++static int ixgbe_notify_dca(struct notifier_block *nb, unsigned long event,
++ void *p)
++{
++ int ret_val;
++
++ ret_val = driver_for_each_device(&ixgbe_driver.driver, NULL, &event,
++ __ixgbe_notify_dca);
++
++ return ret_val ? NOTIFY_BAD : NOTIFY_DONE;
++}
++#endif /* CONFIG_DCA */
++
+ module_exit(ixgbe_exit_module);
+
+ /* ixgbe_main.c */
+diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c
+index 5c154fe..0794482 100644
+--- a/drivers/net/jazzsonic.c
++++ b/drivers/net/jazzsonic.c
+@@ -249,6 +249,7 @@ out:
+ MODULE_DESCRIPTION("Jazz SONIC ethernet driver");
+ module_param(sonic_debug, int, 0);
+ MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)");
++MODULE_ALIAS("platform:jazzsonic");
+
+ #include "sonic.c"
+
+@@ -271,6 +272,7 @@ static struct platform_driver jazz_sonic_driver = {
+ .remove = __devexit_p(jazz_sonic_device_remove),
+ .driver = {
+ .name = jazz_sonic_string,
++ .owner = THIS_MODULE,
+ },
+ };
+
+diff --git a/drivers/net/korina.c b/drivers/net/korina.c
+new file mode 100644
+index 0000000..e185763
+--- /dev/null
++++ b/drivers/net/korina.c
+@@ -0,0 +1,1230 @@
++/*
++ * Driver for the IDT RC32434 (Korina) on-chip ethernet controller.
++ *
++ * Copyright 2004 IDT Inc. (rischelp at idt.com)
++ * Copyright 2006 Felix Fietkau <nbd at openwrt.org>
++ * Copyright 2008 Florian Fainelli <florian at openwrt.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Writing to a DMA status register:
++ *
++ * When writing to the status register, you should mask the bit you have
++ * been testing the status register with. Both Tx and Rx DMA registers
++ * should stick to this procedure.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/moduleparam.h>
++#include <linux/sched.h>
++#include <linux/ctype.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/in.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++#include <linux/errno.h>
++#include <linux/platform_device.h>
++#include <linux/mii.h>
++#include <linux/ethtool.h>
++#include <linux/crc32.h>
++
++#include <asm/bootinfo.h>
++#include <asm/system.h>
++#include <asm/bitops.h>
++#include <asm/pgtable.h>
++#include <asm/segment.h>
++#include <asm/io.h>
++#include <asm/dma.h>
++
++#include <asm/mach-rc32434/rb.h>
++#include <asm/mach-rc32434/rc32434.h>
++#include <asm/mach-rc32434/eth.h>
++#include <asm/mach-rc32434/dma_v.h>
++
++#define DRV_NAME "korina"
++#define DRV_VERSION "0.10"
++#define DRV_RELDATE "04Mar2008"
++
++#define STATION_ADDRESS_HIGH(dev) (((dev)->dev_addr[0] << 8) | \
++ ((dev)->dev_addr[1]))
++#define STATION_ADDRESS_LOW(dev) (((dev)->dev_addr[2] << 24) | \
++ ((dev)->dev_addr[3] << 16) | \
++ ((dev)->dev_addr[4] << 8) | \
++ ((dev)->dev_addr[5]))
++
++#define MII_CLOCK 1250000 /* no more than 2.5MHz */
++
++/* the following must be powers of two */
++#define KORINA_NUM_RDS 64 /* number of receive descriptors */
++#define KORINA_NUM_TDS 64 /* number of transmit descriptors */
++
++#define KORINA_RBSIZE 536 /* size of one resource buffer = Ether MTU */
++#define KORINA_RDS_MASK (KORINA_NUM_RDS - 1)
++#define KORINA_TDS_MASK (KORINA_NUM_TDS - 1)
++#define RD_RING_SIZE (KORINA_NUM_RDS * sizeof(struct dma_desc))
++#define TD_RING_SIZE (KORINA_NUM_TDS * sizeof(struct dma_desc))
++
++#define TX_TIMEOUT (6000 * HZ / 1000)
++
++enum chain_status { desc_filled, desc_empty };
++#define IS_DMA_FINISHED(X) (((X) & (DMA_DESC_FINI)) != 0)
++#define IS_DMA_DONE(X) (((X) & (DMA_DESC_DONE)) != 0)
++#define RCVPKT_LENGTH(X) (((X) & ETH_RX_LEN) >> ETH_RX_LEN_BIT)
++
++/* Information that need to be kept for each board. */
++struct korina_private {
++ struct eth_regs *eth_regs;
++ struct dma_reg *rx_dma_regs;
++ struct dma_reg *tx_dma_regs;
++ struct dma_desc *td_ring; /* transmit descriptor ring */
++ struct dma_desc *rd_ring; /* receive descriptor ring */
++
++ struct sk_buff *tx_skb[KORINA_NUM_TDS];
++ struct sk_buff *rx_skb[KORINA_NUM_RDS];
++
++ int rx_next_done;
++ int rx_chain_head;
++ int rx_chain_tail;
++ enum chain_status rx_chain_status;
++
++ int tx_next_done;
++ int tx_chain_head;
++ int tx_chain_tail;
++ enum chain_status tx_chain_status;
++ int tx_count;
++ int tx_full;
++
++ int rx_irq;
++ int tx_irq;
++ int ovr_irq;
++ int und_irq;
++
++ spinlock_t lock; /* NIC xmit lock */
++
++ int dma_halt_cnt;
++ int dma_run_cnt;
++ struct napi_struct napi;
++ struct mii_if_info mii_if;
++ struct net_device *dev;
++ int phy_addr;
++};
++
++extern unsigned int idt_cpu_freq;
++
++static inline void korina_start_dma(struct dma_reg *ch, u32 dma_addr)
++{
++ writel(0, &ch->dmandptr);
++ writel(dma_addr, &ch->dmadptr);
++}
++
++static inline void korina_abort_dma(struct net_device *dev,
++ struct dma_reg *ch)
++{
++ if (readl(&ch->dmac) & DMA_CHAN_RUN_BIT) {
++ writel(0x10, &ch->dmac);
++
++ while (!(readl(&ch->dmas) & DMA_STAT_HALT))
++ dev->trans_start = jiffies;
++
++ writel(0, &ch->dmas);
++ }
++
++ writel(0, &ch->dmadptr);
++ writel(0, &ch->dmandptr);
++}
++
++static inline void korina_chain_dma(struct dma_reg *ch, u32 dma_addr)
++{
++ writel(dma_addr, &ch->dmandptr);
++}
++
++static void korina_abort_tx(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++
++ korina_abort_dma(dev, lp->tx_dma_regs);
++}
++
++static void korina_abort_rx(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++
++ korina_abort_dma(dev, lp->rx_dma_regs);
++}
++
++static void korina_start_rx(struct korina_private *lp,
++ struct dma_desc *rd)
++{
++ korina_start_dma(lp->rx_dma_regs, CPHYSADDR(rd));
++}
++
++static void korina_chain_rx(struct korina_private *lp,
++ struct dma_desc *rd)
++{
++ korina_chain_dma(lp->rx_dma_regs, CPHYSADDR(rd));
++}
++
++/* transmit packet */
++static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ unsigned long flags;
++ u32 length;
++ u32 chain_index;
++ struct dma_desc *td;
++
++ spin_lock_irqsave(&lp->lock, flags);
++
++ td = &lp->td_ring[lp->tx_chain_tail];
++
++ /* stop queue when full, drop pkts if queue already full */
++ if (lp->tx_count >= (KORINA_NUM_TDS - 2)) {
++ lp->tx_full = 1;
++
++ if (lp->tx_count == (KORINA_NUM_TDS - 2))
++ netif_stop_queue(dev);
++ else {
++ dev->stats.tx_dropped++;
++ dev_kfree_skb_any(skb);
++ spin_unlock_irqrestore(&lp->lock, flags);
++
++ return NETDEV_TX_BUSY;
++ }
++ }
++
++ lp->tx_count++;
++
++ lp->tx_skb[lp->tx_chain_tail] = skb;
++
++ length = skb->len;
++ dma_cache_wback((u32)skb->data, skb->len);
++
++ /* Setup the transmit descriptor. */
++ dma_cache_inv((u32) td, sizeof(*td));
++ td->ca = CPHYSADDR(skb->data);
++ chain_index = (lp->tx_chain_tail - 1) &
++ KORINA_TDS_MASK;
++
++ if (readl(&(lp->tx_dma_regs->dmandptr)) == 0) {
++ if (lp->tx_chain_status == desc_empty) {
++ /* Update tail */
++ td->control = DMA_COUNT(length) |
++ DMA_DESC_COF | DMA_DESC_IOF;
++ /* Move tail */
++ lp->tx_chain_tail = chain_index;
++ /* Write to NDPTR */
++ writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
++ &lp->tx_dma_regs->dmandptr);
++ /* Move head to tail */
++ lp->tx_chain_head = lp->tx_chain_tail;
++ } else {
++ /* Update tail */
++ td->control = DMA_COUNT(length) |
++ DMA_DESC_COF | DMA_DESC_IOF;
++ /* Link to prev */
++ lp->td_ring[chain_index].control &=
++ ~DMA_DESC_COF;
++ /* Link to prev */
++ lp->td_ring[chain_index].link = CPHYSADDR(td);
++ /* Move tail */
++ lp->tx_chain_tail = chain_index;
++ /* Write to NDPTR */
++ writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
++ &(lp->tx_dma_regs->dmandptr));
++ /* Move head to tail */
++ lp->tx_chain_head = lp->tx_chain_tail;
++ lp->tx_chain_status = desc_empty;
++ }
++ } else {
++ if (lp->tx_chain_status == desc_empty) {
++ /* Update tail */
++ td->control = DMA_COUNT(length) |
++ DMA_DESC_COF | DMA_DESC_IOF;
++ /* Move tail */
++ lp->tx_chain_tail = chain_index;
++ lp->tx_chain_status = desc_filled;
++ netif_stop_queue(dev);
++ } else {
++ /* Update tail */
++ td->control = DMA_COUNT(length) |
++ DMA_DESC_COF | DMA_DESC_IOF;
++ lp->td_ring[chain_index].control &=
++ ~DMA_DESC_COF;
++ lp->td_ring[chain_index].link = CPHYSADDR(td);
++ lp->tx_chain_tail = chain_index;
++ }
++ }
++ dma_cache_wback((u32) td, sizeof(*td));
++
++ dev->trans_start = jiffies;
++ spin_unlock_irqrestore(&lp->lock, flags);
++
++ return NETDEV_TX_OK;
++}
++
++static int mdio_read(struct net_device *dev, int mii_id, int reg)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ int ret;
++
++ mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8);
++
++ writel(0, &lp->eth_regs->miimcfg);
++ writel(0, &lp->eth_regs->miimcmd);
++ writel(mii_id | reg, &lp->eth_regs->miimaddr);
++ writel(ETH_MII_CMD_SCN, &lp->eth_regs->miimcmd);
++
++ ret = (int)(readl(&lp->eth_regs->miimrdd));
++ return ret;
++}
++
++static void mdio_write(struct net_device *dev, int mii_id, int reg, int val)
++{
++ struct korina_private *lp = netdev_priv(dev);
++
++ mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8);
++
++ writel(0, &lp->eth_regs->miimcfg);
++ writel(1, &lp->eth_regs->miimcmd);
++ writel(mii_id | reg, &lp->eth_regs->miimaddr);
++ writel(ETH_MII_CMD_SCN, &lp->eth_regs->miimcmd);
++ writel(val, &lp->eth_regs->miimwtd);
++}
++
++/* Ethernet Rx DMA interrupt */
++static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id)
++{
++ struct net_device *dev = dev_id;
++ struct korina_private *lp = netdev_priv(dev);
++ u32 dmas, dmasm;
++ irqreturn_t retval;
++
++ dmas = readl(&lp->rx_dma_regs->dmas);
++ if (dmas & (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)) {
++ netif_rx_schedule_prep(dev, &lp->napi);
++
++ dmasm = readl(&lp->rx_dma_regs->dmasm);
++ writel(dmasm | (DMA_STAT_DONE |
++ DMA_STAT_HALT | DMA_STAT_ERR),
++ &lp->rx_dma_regs->dmasm);
++
++ if (dmas & DMA_STAT_ERR)
++ printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name);
++
++ retval = IRQ_HANDLED;
++ } else
++ retval = IRQ_NONE;
++
++ return retval;
++}
++
++static int korina_rx(struct net_device *dev, int limit)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ struct dma_desc *rd = &lp->rd_ring[lp->rx_next_done];
++ struct sk_buff *skb, *skb_new;
++ u8 *pkt_buf;
++ u32 devcs, pkt_len, dmas, rx_free_desc;
++ int count;
++
++ dma_cache_inv((u32)rd, sizeof(*rd));
++
++ for (count = 0; count < limit; count++) {
++
++ devcs = rd->devcs;
++
++ /* Update statistics counters */
++ if (devcs & ETH_RX_CRC)
++ dev->stats.rx_crc_errors++;
++ if (devcs & ETH_RX_LOR)
++ dev->stats.rx_length_errors++;
++ if (devcs & ETH_RX_LE)
++ dev->stats.rx_length_errors++;
++ if (devcs & ETH_RX_OVR)
++ dev->stats.rx_over_errors++;
++ if (devcs & ETH_RX_CV)
++ dev->stats.rx_frame_errors++;
++ if (devcs & ETH_RX_CES)
++ dev->stats.rx_length_errors++;
++ if (devcs & ETH_RX_MP)
++ dev->stats.multicast++;
++
++ if ((devcs & ETH_RX_LD) != ETH_RX_LD) {
++ /* check that this is a whole packet
++ * WARNING: DMA_FD bit incorrectly set
++ * in Rc32434 (errata ref #077) */
++ dev->stats.rx_errors++;
++ dev->stats.rx_dropped++;
++ }
++
++ while ((rx_free_desc = KORINA_RBSIZE - (u32)DMA_COUNT(rd->control)) != 0) {
++ /* init the var. used for the later
++ * operations within the while loop */
++ skb_new = NULL;
++ pkt_len = RCVPKT_LENGTH(devcs);
++ skb = lp->rx_skb[lp->rx_next_done];
++
++ if ((devcs & ETH_RX_ROK)) {
++ /* must be the (first and) last
++ * descriptor then */
++ pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data;
++
++ /* invalidate the cache */
++ dma_cache_inv((unsigned long)pkt_buf, pkt_len - 4);
++
++ /* Malloc up new buffer. */
++ skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2);
++
++ if (!skb_new)
++ break;
++ /* Do not count the CRC */
++ skb_put(skb, pkt_len - 4);
++ skb->protocol = eth_type_trans(skb, dev);
++
++ /* Pass the packet to upper layers */
++ netif_receive_skb(skb);
++ dev->last_rx = jiffies;
++ dev->stats.rx_packets++;
++ dev->stats.rx_bytes += pkt_len;
++
++ /* Update the mcast stats */
++ if (devcs & ETH_RX_MP)
++ dev->stats.multicast++;
++
++ lp->rx_skb[lp->rx_next_done] = skb_new;
++ }
++
++ rd->devcs = 0;
++
++ /* Restore descriptor's curr_addr */
++ if (skb_new)
++ rd->ca = CPHYSADDR(skb_new->data);
++ else
++ rd->ca = CPHYSADDR(skb->data);
++
++ rd->control = DMA_COUNT(KORINA_RBSIZE) |
++ DMA_DESC_COD | DMA_DESC_IOD;
++ lp->rd_ring[(lp->rx_next_done - 1) &
++ KORINA_RDS_MASK].control &=
++ ~DMA_DESC_COD;
++
++ lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK;
++ dma_cache_wback((u32)rd, sizeof(*rd));
++ rd = &lp->rd_ring[lp->rx_next_done];
++ writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas);
++ }
++ }
++
++ dmas = readl(&lp->rx_dma_regs->dmas);
++
++ if (dmas & DMA_STAT_HALT) {
++ writel(~(DMA_STAT_HALT | DMA_STAT_ERR),
++ &lp->rx_dma_regs->dmas);
++
++ lp->dma_halt_cnt++;
++ rd->devcs = 0;
++ skb = lp->rx_skb[lp->rx_next_done];
++ rd->ca = CPHYSADDR(skb->data);
++ dma_cache_wback((u32)rd, sizeof(*rd));
++ korina_chain_rx(lp, rd);
++ }
++
++ return count;
++}
++
++static int korina_poll(struct napi_struct *napi, int budget)
++{
++ struct korina_private *lp =
++ container_of(napi, struct korina_private, napi);
++ struct net_device *dev = lp->dev;
++ int work_done;
++
++ work_done = korina_rx(dev, budget);
++ if (work_done < budget) {
++ netif_rx_complete(dev, napi);
++
++ writel(readl(&lp->rx_dma_regs->dmasm) &
++ ~(DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR),
++ &lp->rx_dma_regs->dmasm);
++ }
++ return work_done;
++}
++
++/*
++ * Set or clear the multicast filter for this adaptor.
++ */
++static void korina_multicast_list(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ unsigned long flags;
++ struct dev_mc_list *dmi = dev->mc_list;
++ u32 recognise = ETH_ARC_AB; /* always accept broadcasts */
++ int i;
++
++ /* Set promiscuous mode */
++ if (dev->flags & IFF_PROMISC)
++ recognise |= ETH_ARC_PRO;
++
++ else if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 4))
++ /* All multicast and broadcast */
++ recognise |= ETH_ARC_AM;
++
++ /* Build the hash table */
++ if (dev->mc_count > 4) {
++ u16 hash_table[4];
++ u32 crc;
++
++ for (i = 0; i < 4; i++)
++ hash_table[i] = 0;
++
++ for (i = 0; i < dev->mc_count; i++) {
++ char *addrs = dmi->dmi_addr;
++
++ dmi = dmi->next;
++
++ if (!(*addrs & 1))
++ continue;
++
++ crc = ether_crc_le(6, addrs);
++ crc >>= 26;
++ hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
++ }
++ /* Accept filtered multicast */
++ recognise |= ETH_ARC_AFM;
++
++ /* Fill the MAC hash tables with their values */
++ writel((u32)(hash_table[1] << 16 | hash_table[0]),
++ &lp->eth_regs->ethhash0);
++ writel((u32)(hash_table[3] << 16 | hash_table[2]),
++ &lp->eth_regs->ethhash1);
++ }
++
++ spin_lock_irqsave(&lp->lock, flags);
++ writel(recognise, &lp->eth_regs->etharc);
++ spin_unlock_irqrestore(&lp->lock, flags);
++}
++
++static void korina_tx(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ struct dma_desc *td = &lp->td_ring[lp->tx_next_done];
++ u32 devcs;
++ u32 dmas;
++
++ spin_lock(&lp->lock);
++
++ /* Process all desc that are done */
++ while (IS_DMA_FINISHED(td->control)) {
++ if (lp->tx_full == 1) {
++ netif_wake_queue(dev);
++ lp->tx_full = 0;
++ }
++
++ devcs = lp->td_ring[lp->tx_next_done].devcs;
++ if ((devcs & (ETH_TX_FD | ETH_TX_LD)) !=
++ (ETH_TX_FD | ETH_TX_LD)) {
++ dev->stats.tx_errors++;
++ dev->stats.tx_dropped++;
++
++ /* Should never happen */
++ printk(KERN_ERR DRV_NAME "%s: split tx ignored\n",
++ dev->name);
++ } else if (devcs & ETH_TX_TOK) {
++ dev->stats.tx_packets++;
++ dev->stats.tx_bytes +=
++ lp->tx_skb[lp->tx_next_done]->len;
++ } else {
++ dev->stats.tx_errors++;
++ dev->stats.tx_dropped++;
++
++ /* Underflow */
++ if (devcs & ETH_TX_UND)
++ dev->stats.tx_fifo_errors++;
++
++ /* Oversized frame */
++ if (devcs & ETH_TX_OF)
++ dev->stats.tx_aborted_errors++;
++
++ /* Excessive deferrals */
++ if (devcs & ETH_TX_ED)
++ dev->stats.tx_carrier_errors++;
++
++ /* Collisions: medium busy */
++ if (devcs & ETH_TX_EC)
++ dev->stats.collisions++;
++
++ /* Late collision */
++ if (devcs & ETH_TX_LC)
++ dev->stats.tx_window_errors++;
++ }
++
++ /* We must always free the original skb */
++ if (lp->tx_skb[lp->tx_next_done]) {
++ dev_kfree_skb_any(lp->tx_skb[lp->tx_next_done]);
++ lp->tx_skb[lp->tx_next_done] = NULL;
++ }
++
++ lp->td_ring[lp->tx_next_done].control = DMA_DESC_IOF;
++ lp->td_ring[lp->tx_next_done].devcs = ETH_TX_FD | ETH_TX_LD;
++ lp->td_ring[lp->tx_next_done].link = 0;
++ lp->td_ring[lp->tx_next_done].ca = 0;
++ lp->tx_count--;
++
++ /* Go on to next transmission */
++ lp->tx_next_done = (lp->tx_next_done + 1) & KORINA_TDS_MASK;
++ td = &lp->td_ring[lp->tx_next_done];
++
++ }
++
++ /* Clear the DMA status register */
++ dmas = readl(&lp->tx_dma_regs->dmas);
++ writel(~dmas, &lp->tx_dma_regs->dmas);
++
++ writel(readl(&lp->tx_dma_regs->dmasm) &
++ ~(DMA_STAT_FINI | DMA_STAT_ERR),
++ &lp->tx_dma_regs->dmasm);
++
++ spin_unlock(&lp->lock);
++}
++
++static irqreturn_t
++korina_tx_dma_interrupt(int irq, void *dev_id)
++{
++ struct net_device *dev = dev_id;
++ struct korina_private *lp = netdev_priv(dev);
++ u32 dmas, dmasm;
++ irqreturn_t retval;
++
++ dmas = readl(&lp->tx_dma_regs->dmas);
++
++ if (dmas & (DMA_STAT_FINI | DMA_STAT_ERR)) {
++ korina_tx(dev);
++
++ dmasm = readl(&lp->tx_dma_regs->dmasm);
++ writel(dmasm | (DMA_STAT_FINI | DMA_STAT_ERR),
++ &lp->tx_dma_regs->dmasm);
++
++ if (lp->tx_chain_status == desc_filled &&
++ (readl(&(lp->tx_dma_regs->dmandptr)) == 0)) {
++ writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
++ &(lp->tx_dma_regs->dmandptr));
++ lp->tx_chain_status = desc_empty;
++ lp->tx_chain_head = lp->tx_chain_tail;
++ dev->trans_start = jiffies;
++ }
++ if (dmas & DMA_STAT_ERR)
++ printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name);
++
++ retval = IRQ_HANDLED;
++ } else
++ retval = IRQ_NONE;
++
++ return retval;
++}
++
++
++static void korina_check_media(struct net_device *dev, unsigned int init_media)
++{
++ struct korina_private *lp = netdev_priv(dev);
++
++ mii_check_media(&lp->mii_if, 0, init_media);
++
++ if (lp->mii_if.full_duplex)
++ writel(readl(&lp->eth_regs->ethmac2) | ETH_MAC2_FD,
++ &lp->eth_regs->ethmac2);
++ else
++ writel(readl(&lp->eth_regs->ethmac2) & ~ETH_MAC2_FD,
++ &lp->eth_regs->ethmac2);
++}
++
++static void korina_set_carrier(struct mii_if_info *mii)
++{
++ if (mii->force_media) {
++ /* autoneg is off: Link is always assumed to be up */
++ if (!netif_carrier_ok(mii->dev))
++ netif_carrier_on(mii->dev);
++ } else /* Let MMI library update carrier status */
++ korina_check_media(mii->dev, 0);
++}
++
++static int korina_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ struct mii_ioctl_data *data = if_mii(rq);
++ int rc;
++
++ if (!netif_running(dev))
++ return -EINVAL;
++ spin_lock_irq(&lp->lock);
++ rc = generic_mii_ioctl(&lp->mii_if, data, cmd, NULL);
++ spin_unlock_irq(&lp->lock);
++ korina_set_carrier(&lp->mii_if);
++
++ return rc;
++}
++
++/* ethtool helpers */
++static void netdev_get_drvinfo(struct net_device *dev,
++ struct ethtool_drvinfo *info)
++{
++ struct korina_private *lp = netdev_priv(dev);
++
++ strcpy(info->driver, DRV_NAME);
++ strcpy(info->version, DRV_VERSION);
++ strcpy(info->bus_info, lp->dev->name);
++}
++
++static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ int rc;
++
++ spin_lock_irq(&lp->lock);
++ rc = mii_ethtool_gset(&lp->mii_if, cmd);
++ spin_unlock_irq(&lp->lock);
++
++ return rc;
++}
++
++static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ int rc;
++
++ spin_lock_irq(&lp->lock);
++ rc = mii_ethtool_sset(&lp->mii_if, cmd);
++ spin_unlock_irq(&lp->lock);
++ korina_set_carrier(&lp->mii_if);
++
++ return rc;
++}
++
++static u32 netdev_get_link(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++
++ return mii_link_ok(&lp->mii_if);
++}
++
++static struct ethtool_ops netdev_ethtool_ops = {
++ .get_drvinfo = netdev_get_drvinfo,
++ .get_settings = netdev_get_settings,
++ .set_settings = netdev_set_settings,
++ .get_link = netdev_get_link,
++};
++
++static void korina_alloc_ring(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ int i;
++
++ /* Initialize the transmit descriptors */
++ for (i = 0; i < KORINA_NUM_TDS; i++) {
++ lp->td_ring[i].control = DMA_DESC_IOF;
++ lp->td_ring[i].devcs = ETH_TX_FD | ETH_TX_LD;
++ lp->td_ring[i].ca = 0;
++ lp->td_ring[i].link = 0;
++ }
++ lp->tx_next_done = lp->tx_chain_head = lp->tx_chain_tail =
++ lp->tx_full = lp->tx_count = 0;
++ lp->tx_chain_status = desc_empty;
++
++ /* Initialize the receive descriptors */
++ for (i = 0; i < KORINA_NUM_RDS; i++) {
++ struct sk_buff *skb = lp->rx_skb[i];
++
++ skb = dev_alloc_skb(KORINA_RBSIZE + 2);
++ if (!skb)
++ break;
++ skb_reserve(skb, 2);
++ lp->rx_skb[i] = skb;
++ lp->rd_ring[i].control = DMA_DESC_IOD |
++ DMA_COUNT(KORINA_RBSIZE);
++ lp->rd_ring[i].devcs = 0;
++ lp->rd_ring[i].ca = CPHYSADDR(skb->data);
++ lp->rd_ring[i].link = CPHYSADDR(&lp->rd_ring[i+1]);
++ }
++
++ /* loop back */
++ lp->rd_ring[i].link = CPHYSADDR(&lp->rd_ring[0]);
++ lp->rx_next_done = 0;
++
++ lp->rd_ring[i].control |= DMA_DESC_COD;
++ lp->rx_chain_head = 0;
++ lp->rx_chain_tail = 0;
++ lp->rx_chain_status = desc_empty;
++}
++
++static void korina_free_ring(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ int i;
++
++ for (i = 0; i < KORINA_NUM_RDS; i++) {
++ lp->rd_ring[i].control = 0;
++ if (lp->rx_skb[i])
++ dev_kfree_skb_any(lp->rx_skb[i]);
++ lp->rx_skb[i] = NULL;
++ }
++
++ for (i = 0; i < KORINA_NUM_TDS; i++) {
++ lp->td_ring[i].control = 0;
++ if (lp->tx_skb[i])
++ dev_kfree_skb_any(lp->tx_skb[i]);
++ lp->tx_skb[i] = NULL;
++ }
++}
++
++/*
++ * Initialize the RC32434 ethernet controller.
++ */
++static int korina_init(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++
++ /* Disable DMA */
++ korina_abort_tx(dev);
++ korina_abort_rx(dev);
++
++ /* reset ethernet logic */
++ writel(0, &lp->eth_regs->ethintfc);
++ while ((readl(&lp->eth_regs->ethintfc) & ETH_INT_FC_RIP))
++ dev->trans_start = jiffies;
++
++ /* Enable Ethernet Interface */
++ writel(ETH_INT_FC_EN, &lp->eth_regs->ethintfc);
++
++ /* Allocate rings */
++ korina_alloc_ring(dev);
++
++ writel(0, &lp->rx_dma_regs->dmas);
++ /* Start Rx DMA */
++ korina_start_rx(lp, &lp->rd_ring[0]);
++
++ writel(readl(&lp->tx_dma_regs->dmasm) &
++ ~(DMA_STAT_FINI | DMA_STAT_ERR),
++ &lp->tx_dma_regs->dmasm);
++ writel(readl(&lp->rx_dma_regs->dmasm) &
++ ~(DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR),
++ &lp->rx_dma_regs->dmasm);
++
++ /* Accept only packets destined for this Ethernet device address */
++ writel(ETH_ARC_AB, &lp->eth_regs->etharc);
++
++ /* Set all Ether station address registers to their initial values */
++ writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal0);
++ writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah0);
++
++ writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal1);
++ writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah1);
++
++ writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal2);
++ writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah2);
++
++ writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal3);
++ writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah3);
++
++
++ /* Frame Length Checking, Pad Enable, CRC Enable, Full Duplex set */
++ writel(ETH_MAC2_PE | ETH_MAC2_CEN | ETH_MAC2_FD,
++ &lp->eth_regs->ethmac2);
++
++ /* Back to back inter-packet-gap */
++ writel(0x15, &lp->eth_regs->ethipgt);
++ /* Non - Back to back inter-packet-gap */
++ writel(0x12, &lp->eth_regs->ethipgr);
++
++ /* Management Clock Prescaler Divisor
++ * Clock independent setting */
++ writel(((idt_cpu_freq) / MII_CLOCK + 1) & ~1,
++ &lp->eth_regs->ethmcp);
++
++ /* don't transmit until fifo contains 48b */
++ writel(48, &lp->eth_regs->ethfifott);
++
++ writel(ETH_MAC1_RE, &lp->eth_regs->ethmac1);
++
++ napi_enable(&lp->napi);
++ netif_start_queue(dev);
++
++ return 0;
++}
++
++/*
++ * Restart the RC32434 ethernet controller.
++ * FIXME: check the return status where we call it
++ */
++static int korina_restart(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ int ret;
++
++ /*
++ * Disable interrupts
++ */
++ disable_irq(lp->rx_irq);
++ disable_irq(lp->tx_irq);
++ disable_irq(lp->ovr_irq);
++ disable_irq(lp->und_irq);
++
++ writel(readl(&lp->tx_dma_regs->dmasm) |
++ DMA_STAT_FINI | DMA_STAT_ERR,
++ &lp->tx_dma_regs->dmasm);
++ writel(readl(&lp->rx_dma_regs->dmasm) |
++ DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR,
++ &lp->rx_dma_regs->dmasm);
++
++ korina_free_ring(dev);
++
++ ret = korina_init(dev);
++ if (ret < 0) {
++ printk(KERN_ERR DRV_NAME "%s: cannot restart device\n",
++ dev->name);
++ return ret;
++ }
++ korina_multicast_list(dev);
++
++ enable_irq(lp->und_irq);
++ enable_irq(lp->ovr_irq);
++ enable_irq(lp->tx_irq);
++ enable_irq(lp->rx_irq);
++
++ return ret;
++}
++
++static void korina_clear_and_restart(struct net_device *dev, u32 value)
++{
++ struct korina_private *lp = netdev_priv(dev);
++
++ netif_stop_queue(dev);
++ writel(value, &lp->eth_regs->ethintfc);
++ korina_restart(dev);
++}
++
++/* Ethernet Tx Underflow interrupt */
++static irqreturn_t korina_und_interrupt(int irq, void *dev_id)
++{
++ struct net_device *dev = dev_id;
++ struct korina_private *lp = netdev_priv(dev);
++ unsigned int und;
++
++ spin_lock(&lp->lock);
++
++ und = readl(&lp->eth_regs->ethintfc);
++
++ if (und & ETH_INT_FC_UND)
++ korina_clear_and_restart(dev, und & ~ETH_INT_FC_UND);
++
++ spin_unlock(&lp->lock);
++
++ return IRQ_HANDLED;
++}
++
++static void korina_tx_timeout(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ unsigned long flags;
++
++ spin_lock_irqsave(&lp->lock, flags);
++ korina_restart(dev);
++ spin_unlock_irqrestore(&lp->lock, flags);
++}
++
++/* Ethernet Rx Overflow interrupt */
++static irqreturn_t
++korina_ovr_interrupt(int irq, void *dev_id)
++{
++ struct net_device *dev = dev_id;
++ struct korina_private *lp = netdev_priv(dev);
++ unsigned int ovr;
++
++ spin_lock(&lp->lock);
++ ovr = readl(&lp->eth_regs->ethintfc);
++
++ if (ovr & ETH_INT_FC_OVR)
++ korina_clear_and_restart(dev, ovr & ~ETH_INT_FC_OVR);
++
++ spin_unlock(&lp->lock);
++
++ return IRQ_HANDLED;
++}
++
++#ifdef CONFIG_NET_POLL_CONTROLLER
++static void korina_poll_controller(struct net_device *dev)
++{
++ disable_irq(dev->irq);
++ korina_tx_dma_interrupt(dev->irq, dev);
++ enable_irq(dev->irq);
++}
++#endif
++
++static int korina_open(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ int ret;
++
++ /* Initialize */
++ ret = korina_init(dev);
++ if (ret < 0) {
++ printk(KERN_ERR DRV_NAME "%s: cannot open device\n", dev->name);
++ goto out;
++ }
++
++ /* Install the interrupt handler
++ * that handles the Done Finished
++ * Ovr and Und Events */
++ ret = request_irq(lp->rx_irq, &korina_rx_dma_interrupt,
++ IRQF_SHARED | IRQF_DISABLED, "Korina ethernet Rx", dev);
++ if (ret < 0) {
++ printk(KERN_ERR DRV_NAME "%s: unable to get Rx DMA IRQ %d\n",
++ dev->name, lp->rx_irq);
++ goto err_release;
++ }
++ ret = request_irq(lp->tx_irq, &korina_tx_dma_interrupt,
++ IRQF_SHARED | IRQF_DISABLED, "Korina ethernet Tx", dev);
++ if (ret < 0) {
++ printk(KERN_ERR DRV_NAME "%s: unable to get Tx DMA IRQ %d\n",
++ dev->name, lp->tx_irq);
++ goto err_free_rx_irq;
++ }
++
++ /* Install handler for overrun error. */
++ ret = request_irq(lp->ovr_irq, &korina_ovr_interrupt,
++ IRQF_SHARED | IRQF_DISABLED, "Ethernet Overflow", dev);
++ if (ret < 0) {
++ printk(KERN_ERR DRV_NAME"%s: unable to get OVR IRQ %d\n",
++ dev->name, lp->ovr_irq);
++ goto err_free_tx_irq;
++ }
++
++ /* Install handler for underflow error. */
++ ret = request_irq(lp->und_irq, &korina_und_interrupt,
++ IRQF_SHARED | IRQF_DISABLED, "Ethernet Underflow", dev);
++ if (ret < 0) {
++ printk(KERN_ERR DRV_NAME "%s: unable to get UND IRQ %d\n",
++ dev->name, lp->und_irq);
++ goto err_free_ovr_irq;
++ }
++out:
++ return ret;
++
++err_free_ovr_irq:
++ free_irq(lp->ovr_irq, dev);
++err_free_tx_irq:
++ free_irq(lp->tx_irq, dev);
++err_free_rx_irq:
++ free_irq(lp->rx_irq, dev);
++err_release:
++ korina_free_ring(dev);
++ goto out;
++}
++
++static int korina_close(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ u32 tmp;
++
++ /* Disable interrupts */
++ disable_irq(lp->rx_irq);
++ disable_irq(lp->tx_irq);
++ disable_irq(lp->ovr_irq);
++ disable_irq(lp->und_irq);
++
++ korina_abort_tx(dev);
++ tmp = readl(&lp->tx_dma_regs->dmasm);
++ tmp = tmp | DMA_STAT_FINI | DMA_STAT_ERR;
++ writel(tmp, &lp->tx_dma_regs->dmasm);
++
++ korina_abort_rx(dev);
++ tmp = readl(&lp->rx_dma_regs->dmasm);
++ tmp = tmp | DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR;
++ writel(tmp, &lp->rx_dma_regs->dmasm);
++
++ korina_free_ring(dev);
++
++ free_irq(lp->rx_irq, dev);
++ free_irq(lp->tx_irq, dev);
++ free_irq(lp->ovr_irq, dev);
++ free_irq(lp->und_irq, dev);
++
++ return 0;
++}
++
++static int korina_probe(struct platform_device *pdev)
++{
++ struct korina_device *bif = platform_get_drvdata(pdev);
++ struct korina_private *lp;
++ struct net_device *dev;
++ struct resource *r;
++ int rc;
++
++ dev = alloc_etherdev(sizeof(struct korina_private));
++ if (!dev) {
++ printk(KERN_ERR DRV_NAME ": alloc_etherdev failed\n");
++ return -ENOMEM;
++ }
++ SET_NETDEV_DEV(dev, &pdev->dev);
++ platform_set_drvdata(pdev, dev);
++ lp = netdev_priv(dev);
++
++ bif->dev = dev;
++ memcpy(dev->dev_addr, bif->mac, 6);
++
++ lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx");
++ lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx");
++ lp->ovr_irq = platform_get_irq_byname(pdev, "korina_ovr");
++ lp->und_irq = platform_get_irq_byname(pdev, "korina_und");
++
++ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_regs");
++ dev->base_addr = r->start;
++ lp->eth_regs = ioremap_nocache(r->start, r->end - r->start);
++ if (!lp->eth_regs) {
++ printk(KERN_ERR DRV_NAME "cannot remap registers\n");
++ rc = -ENXIO;
++ goto probe_err_out;
++ }
++
++ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_rx");
++ lp->rx_dma_regs = ioremap_nocache(r->start, r->end - r->start);
++ if (!lp->rx_dma_regs) {
++ printk(KERN_ERR DRV_NAME "cannot remap Rx DMA registers\n");
++ rc = -ENXIO;
++ goto probe_err_dma_rx;
++ }
++
++ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_tx");
++ lp->tx_dma_regs = ioremap_nocache(r->start, r->end - r->start);
++ if (!lp->tx_dma_regs) {
++ printk(KERN_ERR DRV_NAME "cannot remap Tx DMA registers\n");
++ rc = -ENXIO;
++ goto probe_err_dma_tx;
++ }
++
++ lp->td_ring = kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL);
++ if (!lp->td_ring) {
++ printk(KERN_ERR DRV_NAME "cannot allocate descriptors\n");
++ rc = -ENXIO;
++ goto probe_err_td_ring;
++ }
++
++ dma_cache_inv((unsigned long)(lp->td_ring),
++ TD_RING_SIZE + RD_RING_SIZE);
++
++ /* now convert TD_RING pointer to KSEG1 */
++ lp->td_ring = (struct dma_desc *)KSEG1ADDR(lp->td_ring);
++ lp->rd_ring = &lp->td_ring[KORINA_NUM_TDS];
++
++ spin_lock_init(&lp->lock);
++ /* just use the rx dma irq */
++ dev->irq = lp->rx_irq;
++ lp->dev = dev;
++
++ dev->open = korina_open;
++ dev->stop = korina_close;
++ dev->hard_start_xmit = korina_send_packet;
++ dev->set_multicast_list = &korina_multicast_list;
++ dev->ethtool_ops = &netdev_ethtool_ops;
++ dev->tx_timeout = korina_tx_timeout;
++ dev->watchdog_timeo = TX_TIMEOUT;
++ dev->do_ioctl = &korina_ioctl;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ dev->poll_controller = korina_poll_controller;
++#endif
++ netif_napi_add(dev, &lp->napi, korina_poll, 64);
++
++ lp->phy_addr = (((lp->rx_irq == 0x2c? 1:0) << 8) | 0x05);
++ lp->mii_if.dev = dev;
++ lp->mii_if.mdio_read = mdio_read;
++ lp->mii_if.mdio_write = mdio_write;
++ lp->mii_if.phy_id = lp->phy_addr;
++ lp->mii_if.phy_id_mask = 0x1f;
++ lp->mii_if.reg_num_mask = 0x1f;
++
++ rc = register_netdev(dev);
++ if (rc < 0) {
++ printk(KERN_ERR DRV_NAME
++ ": cannot register net device %d\n", rc);
++ goto probe_err_register;
++ }
++out:
++ return rc;
++
++probe_err_register:
++ kfree(lp->td_ring);
++probe_err_td_ring:
++ iounmap(lp->tx_dma_regs);
++probe_err_dma_tx:
++ iounmap(lp->rx_dma_regs);
++probe_err_dma_rx:
++ iounmap(lp->eth_regs);
++probe_err_out:
++ free_netdev(dev);
++ goto out;
++}
++
++static int korina_remove(struct platform_device *pdev)
++{
++ struct korina_device *bif = platform_get_drvdata(pdev);
++ struct korina_private *lp = netdev_priv(bif->dev);
++
++ iounmap(lp->eth_regs);
++ iounmap(lp->rx_dma_regs);
++ iounmap(lp->tx_dma_regs);
++
++ platform_set_drvdata(pdev, NULL);
++ unregister_netdev(bif->dev);
++ free_netdev(bif->dev);
++
++ return 0;
++}
++
++static struct platform_driver korina_driver = {
++ .driver.name = "korina",
++ .probe = korina_probe,
++ .remove = korina_remove,
++};
++
++static int __init korina_init_module(void)
++{
++ return platform_driver_register(&korina_driver);
++}
++
++static void korina_cleanup_module(void)
++{
++ return platform_driver_unregister(&korina_driver);
++}
++
++module_init(korina_init_module);
++module_exit(korina_cleanup_module);
++
++MODULE_AUTHOR("Philip Rischel <rischelp at idt.com>");
++MODULE_AUTHOR("Felix Fietkau <nbd at openwrt.org>");
++MODULE_AUTHOR("Florian Fainelli <florian at openwrt.org>");
++MODULE_DESCRIPTION("IDT RC32434 (Korina) Ethernet driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
+index f2a6e71..41b774b 100644
+--- a/drivers/net/loopback.c
++++ b/drivers/net/loopback.c
+@@ -258,7 +258,7 @@ static __net_init int loopback_net_init(struct net *net)
+ if (!dev)
+ goto out;
- /**
-- * 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;
- }
+- 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,
+ },
+ };
-- /* 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;
+@@ -1300,3 +1301,4 @@ module_exit(macb_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Atmel MACB Ethernet driver");
+ MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen at atmel.com>");
++MODULE_ALIAS("platform:macb");
+diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
+index f651a81..2056cfc 100644
+--- a/drivers/net/macvlan.c
++++ b/drivers/net/macvlan.c
+@@ -402,7 +402,7 @@ static int macvlan_newlink(struct net_device *dev,
+ if (!tb[IFLA_LINK])
+ return -EINVAL;
-- /* 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;
- }
+- 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;
--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;
+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,
}
-- *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;
+@@ -855,3 +856,4 @@ module_exit(meth_exit_module);
+ MODULE_AUTHOR("Ilya Volynets <ilya at theIlya.com>");
+ MODULE_DESCRIPTION("SGI O2 Builtin Fast Ethernet driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:meth");
+diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c
+index 75ef9d0..f9d6b4d 100644
+--- a/drivers/net/mlx4/alloc.c
++++ b/drivers/net/mlx4/alloc.c
+@@ -196,3 +196,160 @@ void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf)
}
-- *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 @@
- /*******************************************************************************
+ EXPORT_SYMBOL_GPL(mlx4_buf_free);
++
++static struct mlx4_db_pgdir *mlx4_alloc_db_pgdir(struct device *dma_device)
++{
++ struct mlx4_db_pgdir *pgdir;
++
++ pgdir = kzalloc(sizeof *pgdir, GFP_KERNEL);
++ if (!pgdir)
++ return NULL;
++
++ bitmap_fill(pgdir->order1, MLX4_DB_PER_PAGE / 2);
++ pgdir->bits[0] = pgdir->order0;
++ pgdir->bits[1] = pgdir->order1;
++ pgdir->db_page = dma_alloc_coherent(dma_device, PAGE_SIZE,
++ &pgdir->db_dma, GFP_KERNEL);
++ if (!pgdir->db_page) {
++ kfree(pgdir);
++ return NULL;
++ }
++
++ return pgdir;
++}
++
++static int mlx4_alloc_db_from_pgdir(struct mlx4_db_pgdir *pgdir,
++ struct mlx4_db *db, int order)
++{
++ int o;
++ int i;
++
++ for (o = order; o <= 1; ++o) {
++ i = find_first_bit(pgdir->bits[o], MLX4_DB_PER_PAGE >> o);
++ if (i < MLX4_DB_PER_PAGE >> o)
++ goto found;
++ }
++
++ return -ENOMEM;
++
++found:
++ clear_bit(i, pgdir->bits[o]);
++
++ i <<= o;
++
++ if (o > order)
++ set_bit(i ^ 1, pgdir->bits[order]);
++
++ db->u.pgdir = pgdir;
++ db->index = i;
++ db->db = pgdir->db_page + db->index;
++ db->dma = pgdir->db_dma + db->index * 4;
++ db->order = order;
++
++ return 0;
++}
++
++int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, int order)
++{
++ struct mlx4_priv *priv = mlx4_priv(dev);
++ struct mlx4_db_pgdir *pgdir;
++ int ret = 0;
++
++ mutex_lock(&priv->pgdir_mutex);
++
++ list_for_each_entry(pgdir, &priv->pgdir_list, list)
++ if (!mlx4_alloc_db_from_pgdir(pgdir, db, order))
++ goto out;
++
++ pgdir = mlx4_alloc_db_pgdir(&(dev->pdev->dev));
++ if (!pgdir) {
++ ret = -ENOMEM;
++ goto out;
++ }
++
++ list_add(&pgdir->list, &priv->pgdir_list);
++
++ /* This should never fail -- we just allocated an empty page: */
++ WARN_ON(mlx4_alloc_db_from_pgdir(pgdir, db, order));
++
++out:
++ mutex_unlock(&priv->pgdir_mutex);
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(mlx4_db_alloc);
++
++void mlx4_db_free(struct mlx4_dev *dev, struct mlx4_db *db)
++{
++ struct mlx4_priv *priv = mlx4_priv(dev);
++ int o;
++ int i;
++
++ mutex_lock(&priv->pgdir_mutex);
++
++ o = db->order;
++ i = db->index;
++
++ if (db->order == 0 && test_bit(i ^ 1, db->u.pgdir->order0)) {
++ clear_bit(i ^ 1, db->u.pgdir->order0);
++ ++o;
++ }
++ i >>= o;
++ set_bit(i, db->u.pgdir->bits[o]);
++
++ if (bitmap_full(db->u.pgdir->order1, MLX4_DB_PER_PAGE / 2)) {
++ dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
++ db->u.pgdir->db_page, db->u.pgdir->db_dma);
++ list_del(&db->u.pgdir->list);
++ kfree(db->u.pgdir);
++ }
++
++ mutex_unlock(&priv->pgdir_mutex);
++}
++EXPORT_SYMBOL_GPL(mlx4_db_free);
++
++int mlx4_alloc_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres,
++ int size, int max_direct)
++{
++ int err;
++
++ err = mlx4_db_alloc(dev, &wqres->db, 1);
++ if (err)
++ return err;
++
++ *wqres->db.db = 0;
++
++ err = mlx4_buf_alloc(dev, size, max_direct, &wqres->buf);
++ if (err)
++ goto err_db;
++
++ err = mlx4_mtt_init(dev, wqres->buf.npages, wqres->buf.page_shift,
++ &wqres->mtt);
++ if (err)
++ goto err_buf;
++
++ err = mlx4_buf_write_mtt(dev, &wqres->mtt, &wqres->buf);
++ if (err)
++ goto err_mtt;
++
++ return 0;
++
++err_mtt:
++ mlx4_mtt_cleanup(dev, &wqres->mtt);
++err_buf:
++ mlx4_buf_free(dev, size, &wqres->buf);
++err_db:
++ mlx4_db_free(dev, &wqres->db);
++
++ return err;
++}
++EXPORT_SYMBOL_GPL(mlx4_alloc_hwq_res);
++
++void mlx4_free_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres,
++ int size)
++{
++ mlx4_mtt_cleanup(dev, &wqres->mtt);
++ mlx4_buf_free(dev, size, &wqres->buf);
++ mlx4_db_free(dev, &wqres->db);
++}
++EXPORT_SYMBOL_GPL(mlx4_free_hwq_res);
+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);
- Intel PRO/1000 Linux driver
-- Copyright(c) 1999 - 2007 Intel Corporation.
-+ Copyright(c) 1999 - 2008 Intel Corporation.
+- mlx4_dispatch_event(dev, MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR, 0, 0);
++ mlx4_dispatch_event(dev, MLX4_DEV_EVENT_CATASTROPHIC_ERROR, 0);
- 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 @@
+ 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;
+ };
- #include "e1000.h"
+-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..95e87a2 100644
+--- a/drivers/net/mlx4/cq.c
++++ b/drivers/net/mlx4/cq.c
+@@ -38,6 +38,7 @@
+ #include <linux/hardirq.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;
+ #include <linux/mlx4/cmd.h>
++#include <linux/mlx4/cq.h>
-@@ -82,7 +82,7 @@ static int e1000_desc_unused(struct e1000_ring *ring)
- }
+ #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;
+ };
- /**
-- * 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;
- }
+@@ -121,6 +120,13 @@ static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
+ MLX4_CMD_TIME_CLASS_A);
+ }
-- /* 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);
++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,8 +135,61 @@ static int mlx4_HW2SW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
+ MLX4_CMD_TIME_CLASS_A);
+ }
-- /* 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,
++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, 0);
++
++ 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)
++ struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq,
++ int collapsed)
+ {
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_cq_table *cq_table = &priv->cq_table;
+@@ -166,6 +225,7 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
+ cq_context = mailbox->buf;
+ memset(cq_context, 0, sizeof *cq_context);
+
++ cq_context->flags = cpu_to_be32(!!collapsed << 18);
+ cq_context->logsize_usrpage = cpu_to_be32((ilog2(nent) << 24) | uar->index);
+ cq_context->comp_eqn = priv->eq_table.eq[MLX4_EQ_COMP].eqn;
+ cq_context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
+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;
- }
-- /* 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);
+ 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;
-- /* 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++;
+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);
-- /* 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);
+ dump_dev_cap_flags(dev, dev_cap->flags);
-- 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;
- }
+@@ -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);
-@@ -581,22 +591,23 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
- }
++ /* 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 */
- 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;
- }
+ 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;
+ };
-@@ -677,21 +688,28 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
- skb_put(skb, length);
+ 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.
+ */
- {
-- /* 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]);
+-#include <linux/mlx4/driver.h>
+-
+ #include "mlx4.h"
-- /* 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;
+ struct mlx4_device_context {
+@@ -113,8 +111,7 @@ void mlx4_unregister_interface(struct mlx4_interface *intf)
+ }
+ EXPORT_SYMBOL_GPL(mlx4_unregister_interface);
- ps_page = &buffer_info->ps_pages[0];
+-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,
-- /* 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);
+ 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);
-- 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;
+ spin_unlock_irqrestore(&priv->ctx_lock, flags);
}
+diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
+index 08bfc13..a6aa49f 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";
-@@ -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);
+ 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;
-- /* 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 0;
+ }
+@@ -735,8 +736,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
}
- 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);
+ /*
+- * 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) {
+@@ -798,6 +798,9 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ INIT_LIST_HEAD(&priv->ctx_list);
+ spin_lock_init(&priv->ctx_lock);
-- /* 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;
++ INIT_LIST_HEAD(&priv->pgdir_list);
++ mutex_init(&priv->pgdir_mutex);
++
+ /*
+ * Now reset the HCA before we touch the PCI capabilities or
+ * attempt a firmware command, since a boot ROM may have left
+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])
}
- /* 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);
- }
- }
+ index += dev->caps.num_mgms;
-@@ -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);
+- 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;
-@@ -1353,9 +1373,11 @@ static void e1000_set_itr(struct e1000_adapter *adapter)
+- 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;
++ }
- 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:
+ if (prev == -1) {
+ /* Remove entry from MGM */
+diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
+index 53a1cdd..a4023c2 100644
+--- a/drivers/net/mlx4/mlx4.h
++++ b/drivers/net/mlx4/mlx4.h
+@@ -42,6 +42,7 @@
+ #include <linux/timer.h>
- /**
- * 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;
+ #include <linux/mlx4/device.h>
++#include <linux/mlx4/driver.h>
+ #include <linux/mlx4/doorbell.h>
-- /* 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;
+ #define DRV_NAME "mlx4_core"
+@@ -256,6 +257,9 @@ struct mlx4_priv {
+ struct list_head ctx_list;
+ spinlock_t ctx_lock;
-- 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);
++ struct list_head pgdir_list;
++ struct mutex pgdir_mutex;
+
-+ 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;
+ struct mlx4_fw fw;
+ struct mlx4_cmd cmd;
-- e1000_irq_disable(adapter);
-+ if (!test_bit(__E1000_DOWN, &adapter->state))
-+ e1000_irq_disable(adapter);
- adapter->vlgrp = grp;
+@@ -313,8 +317,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);
- if (grp) {
-@@ -1517,7 +1545,8 @@ static void e1000_vlan_rx_register(struct net_device *netdev,
- }
- }
+ struct mlx4_dev_cap;
+ struct mlx4_init_hca_param;
+diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c
+index 79b317b..cb46446 100644
+--- a/drivers/net/mlx4/mr.c
++++ b/drivers/net/mlx4/mr.c
+@@ -607,15 +607,9 @@ EXPORT_SYMBOL_GPL(mlx4_fmr_enable);
+ void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr,
+ u32 *lkey, u32 *rkey)
+ {
+- u32 key;
+-
+ if (!fmr->maps)
+ return;
-- e1000_irq_enable(adapter);
-+ if (!test_bit(__E1000_DOWN, &adapter->state))
-+ e1000_irq_enable(adapter);
- }
+- key = key_to_hw_index(fmr->mr.key);
+- key &= dev->caps.num_mpts - 1;
+- *lkey = *rkey = fmr->mr.key = hw_index_to_key(key);
+-
+ fmr->maps = 0;
+
+ *(u8 *) fmr->mpt = MLX4_MPT_STATUS_SW;
+diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c
+index fa24e65..ee5484c 100644
+--- a/drivers/net/mlx4/qp.c
++++ b/drivers/net/mlx4/qp.c
+@@ -299,3 +299,34 @@ int mlx4_qp_query(struct mlx4_dev *dev, struct mlx4_qp *qp,
+ }
+ EXPORT_SYMBOL_GPL(mlx4_qp_query);
+
++int mlx4_qp_to_ready(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
++ struct mlx4_qp_context *context,
++ struct mlx4_qp *qp, enum mlx4_qp_state *qp_state)
++{
++ int err;
++ int i;
++ enum mlx4_qp_state states[] = {
++ MLX4_QP_STATE_RST,
++ MLX4_QP_STATE_INIT,
++ MLX4_QP_STATE_RTR,
++ MLX4_QP_STATE_RTS
++ };
++
++ for (i = 0; i < ARRAY_SIZE(states) - 1; i++) {
++ context->flags &= cpu_to_be32(~(0xf << 28));
++ context->flags |= cpu_to_be32(states[i + 1] << 28);
++ err = mlx4_qp_modify(dev, mtt, states[i], states[i + 1],
++ context, 0, 0, qp);
++ if (err) {
++ mlx4_err(dev, "Failed to bring QP to state: "
++ "%d with error: %d\n",
++ states[i + 1], err);
++ return err;
++ }
++
++ *qp_state = states[i + 1];
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(mlx4_qp_to_ready);
+diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
+index 771139e..381b36e 100644
+--- a/drivers/net/mv643xx_eth.c
++++ b/drivers/net/mv643xx_eth.c
+@@ -3,7 +3,8 @@
+ * Copyright (C) 2002 Matthew Dharm <mdharm at momenco.com>
+ *
+ * Based on the 64360 driver from:
+- * Copyright (C) 2002 rabeeh at galileo.co.il
++ * Copyright (C) 2002 Rabeeh Khoury <rabeeh at galileo.co.il>
++ * Rabeeh Khoury <rabeeh at marvell.com>
+ *
+ * Copyright (C) 2003 PMC-Sierra, Inc.,
+ * written by Manish Lachwani
+@@ -16,6 +17,9 @@
+ * Copyright (C) 2004 Steven J. Hill <sjhill1 at rockwellcollins.com>
+ * <sjhill at realitydiluted.com>
+ *
++ * Copyright (C) 2007-2008 Marvell Semiconductor
++ * Lennert Buytenhek <buytenh at marvell.com>
++ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+@@ -63,20 +67,6 @@
+ #define MV643XX_TX_FAST_REFILL
+ #undef MV643XX_COAL
- static void e1000_restore_vlan(struct e1000_adapter *adapter)
-@@ -1546,9 +1575,11 @@ static void e1000_init_manageability(struct e1000_adapter *adapter)
+-/*
+- * 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;
- manc = er32(MANC);
+-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 {
-- /* 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)
+ /* 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);
- /* 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);
+-static void ethernet_phy_reset(unsigned int eth_port_num);
++static void ethernet_phy_reset(struct mv643xx_private *mp);
- /* Program the Transmit Control Register */
-@@ -1608,22 +1639,24 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
- (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
+-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);
- 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);
- }
+-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);
- /* 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);
- }
+-static void eth_clear_mib_counters(unsigned int eth_port_num);
++static void eth_clear_mib_counters(struct mv643xx_private *mp);
- 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);
+ 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);
-@@ -1761,6 +1796,8 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
- }
+-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);
- ew32(RCTL, rctl);
-+ /* just started the receive unit, no need to restart */
-+ adapter->flags &= ~FLAG_RX_RESTART_NOW;
+-static inline u32 mv_read(int offset)
++static inline u32 rdl(struct mv643xx_private *mp, int offset)
+ {
+ return readl(mv643xx_eth_base + offset);
}
- /**
-@@ -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;
+-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;
-- /* 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)
+ 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);
}
- 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)
+ 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)
{
-- 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);
+ 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);
}
-@@ -1923,7 +1965,7 @@ static void e1000_set_multi(struct net_device *netdev)
- mc_ptr = mc_ptr->next;
- }
+ /*
+@@ -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;
-- 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);
- }
- }
+- 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);
- /**
-- * 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));
+ 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;
- /**
-@@ -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)
+ if (!netif_running(dev))
return;
- /* non-copper PHY? */
-- if (adapter->hw.media_type != e1000_media_type_copper)
-+ if (adapter->hw.phy.media_type != e1000_media_type_copper)
- return;
+ netif_stop_queue(dev);
- /* 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;
+- eth_port_reset(mp->port_num);
++ eth_port_reset(mp);
+ eth_port_start(dev);
- /* 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.
+ 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
*/
- void e1000e_reset(struct e1000_adapter *adapter)
+-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 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;
+ 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;
-- ew32(PBA, adapter->pba);
-+ /* reset Packet Buffer Allocation to default */
-+ ew32(PBA, pba);
+- o_pscr = mv_read(PORT_SERIAL_CONTROL_REG(port_num));
++ o_pscr = rdl(mp, PORT_SERIAL_CONTROL_REG(port_num));
+ n_pscr = o_pscr;
-- 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;
+ /* clear speed, duplex and rx buffer size fields */
+@@ -1031,16 +1014,16 @@ static void mv643xx_eth_update_pscr(struct net_device *dev,
-- /* 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 (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);
-- /* 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)
+ 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);
+ }
-- /* 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);
+@@ -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);
- napi_disable(&adapter->napi);
-- atomic_set(&adapter->irq_sem, 0);
- e1000_irq_disable(adapter);
+ /* wait for previous write to complete */
+- mv_read(INTERRUPT_MASK_REG(port_num));
++ rdl(mp, INTERRUPT_MASK_REG(port_num));
- 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)
+ 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)
{
-- 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);
++ unsigned int port_num = mp->port_num;
+ unsigned int coal = ((t_clk / 1000000) * delay) / 64;
-- /* 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;
- }
+ /* 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));
--/* 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)
+ 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)
{
- struct e1000_adapter *adapter = (struct e1000_adapter *) data;
-@@ -2430,63 +2498,35 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
+- 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;
+ }
- spin_lock_irqsave(&adapter->stats_lock, irq_flags);
+@@ -1327,16 +1311,15 @@ static int mv643xx_eth_open(struct net_device *dev)
+ int err;
-- /* 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
- */
+ /* 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));
- 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);
+ 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;
+ }
-- 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);
-- }
+@@ -1430,17 +1413,17 @@ static int mv643xx_eth_open(struct net_device *dev)
- 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);
+ #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
-- 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;
+ 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);
- /* Rx Errors */
+ /* 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);
-- /* 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 */
+ /* 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);
- /* 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);
- }
+ return 0;
-+/**
-+ * 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);
+@@ -1459,7 +1442,7 @@ static void mv643xx_eth_free_tx_rings(struct net_device *dev)
+ struct mv643xx_private *mp = netdev_priv(dev);
- ndev_info(netdev,
-@@ -2579,6 +2656,62 @@ static void e1000_print_link_info(struct e1000_adapter *adapter)
- ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None" )));
- }
+ /* Stop Tx Queues */
+- mv643xx_eth_port_disable_tx(mp->port_num);
++ mv643xx_eth_port_disable_tx(mp);
-+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)
+ /* 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 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)
- }
- }
+ struct mv643xx_private *mp = netdev_priv(dev);
+- unsigned int port_num = mp->port_num;
+ int curr;
-- /* 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;
+ /* Stop RX Queues */
+- mv643xx_eth_port_disable_rx(port_num);
++ mv643xx_eth_port_disable_rx(mp);
-- 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;
+ /* 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;
- e1000e_update_adaptive(&adapter->hw);
+ /* 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));
-@@ -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);
- }
- }
+ #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);
-- /* Cause software interrupt to ensure rx ring is cleaned */
-+ /* Cause software interrupt to ensure Rx ring is cleaned */
- ew32(ICS, E1000_ICS_RXDMT0);
+- eth_port_reset(mp->port_num);
++ eth_port_reset(mp);
- /* Force detection of hung controller every watchdog period */
- adapter->detect_tx_hung = 1;
+ 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
-- /* 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);
+ 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);
-@@ -3032,16 +3156,20 @@ static void e1000_tx_queue(struct e1000_adapter *adapter,
+ 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);
+ }
- tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
+ return work_done;
+@@ -1723,7 +1705,7 @@ static void eth_tx_submit_descs_for_skb(struct mv643xx_private *mp,
-- /* 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).
-+ */
+ /* 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);
- 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();
+ 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;
-@@ -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;
+ 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);
-@@ -3142,21 +3274,29 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ 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;
}
- 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;
+- 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)
-- /* 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;
+ spin_unlock_irqrestore(&mp->lock, flags);
-- /* 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;
+- return 0; /* success */
++ return NETDEV_TX_OK;
+ }
-@@ -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);
+ #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;
-- /* 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
-+ */
+- 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));
- 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;
+ mv643xx_eth_int_handler(netdev->irq, netdev);
- 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;
+- mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
++ wrl(mp, INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
+ }
+ #endif
-- if (adapter->hw.media_type != e1000_media_type_copper)
-+ if (adapter->hw.phy.media_type != e1000_media_type_copper)
- return -EOPNOTSUPP;
+@@ -1900,7 +1880,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
+ port_num = mp->port_num = pd->port_number;
- 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);
+ /* 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;
-- 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);
+@@ -1908,7 +1888,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
+ memcpy(dev->dev_addr, pd->mac_addr, 6);
-- /* 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);
+ if (pd->phy_addr || pd->force_phy_addr)
+- ethernet_phy_set(port_num, pd->phy_addr);
++ ethernet_phy_set(mp, pd->phy_addr);
- pci_disable_device(pdev);
-@@ -3552,9 +3727,11 @@ static int e1000_resume(struct pci_dev *pdev)
+ 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;
- netif_device_attach(netdev);
+- 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;
+ }
-- /* 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);
+- 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)
-@@ -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);
+ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
+ {
++ static int mv643xx_version_printed = 0;
+ struct resource *res;
- 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)
+- 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");
- netif_device_attach(netdev);
+ 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;
-- /* 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;
+ /* 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));
- /* 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));
+- eth_port_reset(port_num);
++ eth_port_reset(mp);
}
- /**
-@@ -3754,6 +3934,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
- goto err_pci_reg;
+ 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,
+ },
+ };
- pci_set_master(pdev);
-+ pci_save_state(pdev);
+@@ -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,
+ },
+ };
- 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));
+@@ -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);
-- err = ei->get_invariants(adapter);
-+ err = ei->get_variants(adapter);
- if (err)
- goto err_hw_init;
+ /*
+ * 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.
+ */
- hw->mac.ops.get_bus_info(&adapter->hw);
+-/* 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);
-- adapter->hw.phy.wait_for_link = 0;
-+ adapter->hw.phy.autoneg_wait_to_complete = 0;
+ /*
+ * 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;
- /* 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;
+- eth_port_reset(mp->port_num);
++ eth_port_reset(mp);
-- /* 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;
+- eth_port_init_mac_tables(mp->port_num);
++ eth_port_init_mac_tables(mp);
+ }
- if (e1000e_enable_mng_pass_thru(&adapter->hw))
- adapter->flags |= FLAG_MNG_PT_ENABLED;
+ /*
+@@ -2306,28 +2287,28 @@ static void eth_port_start(struct net_device *dev)
-- /* 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);
+ /* 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));
- /*
-@@ -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;
+ /* 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));
- /* 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);
+ /* 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);
-- /* 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);
+ /* Assign port configuration and command. */
+- mv_write(PORT_CONFIG_REG(port_num),
++ wrl(mp, PORT_CONFIG_REG(port_num),
+ PORT_CONFIG_DEFAULT_VALUE);
-- /* 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);
+- mv_write(PORT_CONFIG_EXTEND_REG(port_num),
++ wrl(mp, PORT_CONFIG_EXTEND_REG(port_num),
+ PORT_CONFIG_EXTEND_DEFAULT_VALUE);
- flush_scheduled_work();
+- pscr = mv_read(PORT_SERIAL_CONTROL_REG(port_num));
++ pscr = rdl(mp, PORT_SERIAL_CONTROL_REG(port_num));
-- /* 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);
+ 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);
- 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);
+ 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;
-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 @@
- /*******************************************************************************
+- mv_write(PORT_SERIAL_CONTROL_REG(port_num), pscr);
++ wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), pscr);
- Intel PRO/1000 Linux driver
-- Copyright(c) 1999 - 2007 Intel Corporation.
-+ Copyright(c) 1999 - 2008 Intel Corporation.
+ pscr |= SERIAL_PORT_ENABLE;
+- mv_write(PORT_SERIAL_CONTROL_REG(port_num), pscr);
++ wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), pscr);
- 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 @@
+ /* Assign port SDMA configuration */
+- mv_write(SDMA_CONFIG_REG(port_num),
++ wrl(mp, SDMA_CONFIG_REG(port_num),
+ PORT_SDMA_CONFIG_DEFAULT_VALUE);
- #include "e1000.h"
+ /* Enable port Rx. */
+- mv643xx_eth_port_enable_rx(port_num, ETH_RX_QUEUES_ENABLED);
++ mv643xx_eth_port_enable_rx(mp, ETH_RX_QUEUES_ENABLED);
--/* 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.
- */
+ /* Disable port bandwidth limits by clearing MTU register */
+- mv_write(MAXIMUM_TRANSMIT_UNIT(port_num), 0);
++ wrl(mp, MAXIMUM_TRANSMIT_UNIT(port_num), 0);
-@@ -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");
+ /* 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);
+ }
--/* 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).
+ /*
+ * eth_port_uc_addr_set - Write a MAC address into the port's hw registers
*/
-@@ -60,8 +62,9 @@ MODULE_PARM_DESC(copybreak,
- MODULE_PARM_DESC(X, desc);
+-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);
--/* 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
+ /* 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);
+ }
--/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
-+/*
-+ * Transmit Absolute Interrupt Delay in units of 1.024 microseconds
- *
- * Valid Range: 0-65535
+ /*
+ * eth_port_uc_addr_get - Read the MAC address from the port's hw registers
*/
-@@ -79,8 +83,9 @@ E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
- #define MAX_TXABSDELAY 0xFFFF
- #define MIN_TXABSDELAY 0
+-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;
--/* 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
+- 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));
--/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
-+/*
-+ * Receive Absolute Interrupt Delay in units of 1.024 microseconds
- *
- * Valid Range: 0-65535
+ 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;
*/
-@@ -98,7 +104,8 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
- #define MAX_RXABSDELAY 0xFFFF
- #define MIN_RXABSDELAY 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 */
--/* 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
+ /* 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);
+ }
--/* 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");
+ /*
+@@ -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.
*/
- E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
+-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)
--/* 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 @@
- /*******************************************************************************
+ 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;
+ }
- Intel PRO/1000 Linux driver
-- Copyright(c) 1999 - 2007 Intel Corporation.
-+ Copyright(c) 1999 - 2008 Intel Corporation.
+@@ -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);
- 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)
+- 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);
}
- /**
-- * 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;
- }
+ /*
+@@ -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 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.
+ /* 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)
*/
-@@ -144,8 +145,12 @@ static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+ 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);
- ew32(MDIC, mdic);
+ /* 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);
+ }
-- /* 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)
+@@ -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);
}
- /**
-- * 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
+ /*
+@@ -2594,7 +2580,7 @@ static void eth_port_set_multicast_list(struct net_device *dev)
+ * Other Multicast) and set each entry to 0.
*
- * 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)
+ * 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)
{
- 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)
++ unsigned int port_num = mp->port_num;
+ int table_index;
- ew32(MDIC, mdic);
+ /* 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);
-- /* 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;
+ 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);
}
-+ if (mdic & E1000_MDIC_ERROR) {
-+ hw_dbg(hw, "MDI Error\n");
-+ return -E1000_ERR_PHY;
-+ }
+ }
- return 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);
}
-@@ -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);
+ 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);
+ }
- hw->phy.ops.release_phy(hw);
+ 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;
-@@ -252,9 +265,8 @@ s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
- if (ret_val)
- return ret_val;
+- 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);
-- 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);
+- 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 */
- hw->phy.ops.release_phy(hw);
+ 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;
+ }
-@@ -280,18 +292,17 @@ s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
- return ret_val;
+@@ -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;
- 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;
- }
- }
+- reg_data = mv_read(PHY_ADDR_REG);
++ reg_data = rdl(mp, PHY_ADDR_REG);
-- 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);
+- return ((reg_data >> (5 * eth_port_num)) & 0x1f);
++ return ((reg_data >> (5 * mp->port_num)) & 0x1f);
+ }
- hw->phy.ops.release_phy(hw);
+ /*
+@@ -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;
-@@ -316,18 +327,17 @@ s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
- return ret_val;
+- 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);
+ }
- 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;
- }
- }
+ /*
+@@ -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;
-- 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);
+ /* 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);
- hw->phy.ops.release_phy(hw);
+ /* 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);
+ }
-@@ -409,14 +419,17 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
- s32 ret_val;
- u16 phy_data;
+-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);
+ }
-- /* 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;
+-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);
+ }
-- 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;
+-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;
-- /* 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;
- }
+ /* 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));
-- /* 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;
+ /* 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);
-- 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 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;
+ }
-- /* 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);
+-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;
- /* 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)
+ /* 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));
- /* 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;
+ /* 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);
+ }
- data &= ~IGP01E1000_PSCFR_SMART_SPEED;
- ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-- data);
-+ data);
- if (ret_val)
- return ret_val;
+@@ -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;
-@@ -630,14 +650,16 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
- return ret_val;
- }
+- 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);
-- /* 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.
- */
+ /* Clear all MIB counters */
+- eth_clear_mib_counters(port_num);
++ eth_clear_mib_counters(mp);
-- /* 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;
- }
+ /* 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);
+ }
-- /* 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)
+
+@@ -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)
{
-@@ -766,12 +793,14 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
- s32 ret_val;
- u16 phy_ctrl;
+- int phy_addr = ethernet_phy_get(port_num);
++ int phy_addr = ethernet_phy_get(mp);
+ unsigned long flags;
+ int i;
-- /* Perform some bounds checking on the autoneg advertisement
-+ /*
-+ * Perform some bounds checking on the autoneg advertisement
- * parameter.
- */
- phy->autoneg_advertised &= phy->autoneg_mask;
+@@ -2923,27 +2914,27 @@ static void eth_port_read_smi_reg(unsigned int port_num,
+ spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
-- /* 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)
+ /* 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);
}
- 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;
+- mv_write(SMI_REG,
++ wrl(mp, SMI_REG,
+ (phy_addr << 16) | (phy_reg << 21) | ETH_SMI_OPCODE_READ);
- 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)
+ /* 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);
}
-- /* 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)
+- *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;
- udelay(1);
+- phy_addr = ethernet_phy_get(eth_port_num);
++ phy_addr = ethernet_phy_get(mp);
-- if (phy->wait_for_link) {
-+ if (phy->autoneg_wait_to_complete) {
- hw_dbg(hw, "Waiting for forced speed/duplex link on IGP phy.\n");
+ /* the SMI register is a shared resource */
+ spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
- 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;
+ /* 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);
+ }
-- /* 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)
+- 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;
- udelay(1);
+- eth_port_read_smi_reg(mp->port_num, location, &val);
++ eth_port_read_smi_reg(mp, location, &val);
+ return val;
+ }
-- if (phy->wait_for_link) {
-+ if (phy->autoneg_wait_to_complete) {
- hw_dbg(hw, "Waiting for forced speed/duplex link on M88 phy.\n");
+ 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);
+ }
- 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;
+ /*
+@@ -3156,7 +3146,7 @@ struct mv643xx_stats {
+ int stat_offset;
+ };
- 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;
+-#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)
-- /* 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;
+ static const struct mv643xx_stats mv643xx_gstrings_stats[] = {
+diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
+index cead81e..ef63c8d 100644
+--- a/drivers/net/myri10ge/myri10ge.c
++++ b/drivers/net/myri10ge/myri10ge.c
+@@ -2437,7 +2437,7 @@ static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev)
+ int status;
-- /* 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;
+ segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO6);
+- if (unlikely(IS_ERR(segs)))
++ if (IS_ERR(segs))
+ goto drop;
- /* Turn off flow control when forcing speed/duplex */
-- mac->fc = e1000_fc_none;
-+ hw->fc.type = e1000_fc_none;
+ while (segs) {
+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;
+ };
- /* 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)
+ /* 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 (!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;
+ 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);
- 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;
+ 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 @@
- 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;
+ #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;
-- /* 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)
- }
+ /*
+ * 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);
- /**
-- * 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);
- }
+ /* Functions from netxen_nic_isr.c */
+-int netxen_nic_link_ok(struct netxen_adapter *adapter);
+ void netxen_initialize_adapter_sw(struct netxen_adapter *adapter);
+ void netxen_initialize_adapter_hw(struct netxen_adapter *adapter);
+ void *netxen_alloc(struct pci_dev *pdev, size_t sz, dma_addr_t * ptr,
+diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
+index 160f605..24d027e 100644
+--- a/drivers/net/netxen/netxen_nic_hdr.h
++++ b/drivers/net/netxen/netxen_nic_hdr.h
+@@ -34,7 +34,6 @@
+ #include <linux/kernel.h>
+ #include <linux/version.h>
-- /* 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;
+-#include <asm/semaphore.h>
+ #include <linux/spinlock.h>
+ #include <asm/irq.h>
+ #include <linux/init.h>
+diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
+index 05748ca..af73564 100644
+--- a/drivers/net/netxen/netxen_nic_hw.c
++++ b/drivers/net/netxen/netxen_nic_hw.c
+@@ -1132,8 +1132,8 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
+ u32 fw_minor = 0;
+ u32 fw_build = 0;
+ char brd_name[NETXEN_MAX_SHORT_NAME];
+- struct netxen_new_user_info user_info;
+- int i, addr = NETXEN_USER_START;
++ char serial_num[32];
++ int i, addr;
+ __le32 *ptr32;
- 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;
+ 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);
-- /* 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;
+ 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);
-@@ -1466,7 +1515,7 @@ s32 e1000e_get_phy_info_m88(struct e1000_hw *hw)
- u16 phy_data;
- bool link;
+ 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 (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;
- };
++#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)
- 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;
- };
+ return 0;
+ }
++#endif /* 0 */
- #define EHEA_PORT_UP 1
-@@ -453,7 +453,7 @@ struct ehea_port {
- struct vlan_group *vgrp;
- struct ehea_eq *qp_eq;
- struct work_struct reset_task;
-- struct semaphore port_lock;
-+ struct mutex port_lock;
- char int_aff_name[EHEA_IRQ_NAME_SIZE];
- int allmulti; /* Indicates IFF_ALLMULTI state */
- int promisc; /* Indicates IFF_PROMISC state */
-diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
-index f460b62..f9bc21c 100644
---- a/drivers/net/ehea/ehea_main.c
-+++ b/drivers/net/ehea/ehea_main.c
-@@ -36,6 +36,7 @@
- #include <linux/notifier.h>
- #include <linux/reboot.h>
- #include <asm/kexec.h>
-+#include <linux/mutex.h>
+ 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 = {
- #include <net/ip.h>
+ MODULE_DEVICE_TABLE(pci, netxen_pci_tbl);
-@@ -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;
+-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);
-@@ -1761,7 +1762,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa)
+ 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); }
- memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len);
+-#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))
-- down(&ehea_bcmc_regs.lock);
-+ mutex_lock(&ehea_bcmc_regs.lock);
+ /******************* how to calculate the buffers *****************************
- /* 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)
+@@ -179,34 +179,35 @@ static void ni52_timeout(struct net_device *dev);
- 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);
+ /* 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);
-- down(&ehea_bcmc_regs.lock);
-+ mutex_lock(&ehea_bcmc_regs.lock);
+ 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;
+ };
- if (dev->flags & IFF_ALLMULTI) {
- ehea_allmulti(dev, 1);
-@@ -1972,7 +1973,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
+@@ -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)
}
- 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;
+-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 */
+ }
-- down(&ehea_fw_handles.lock);
-+ mutex_lock(&ehea_fw_handles.lock);
++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;
- 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)
- }
- }
+- 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;
-- down(&ehea_bcmc_regs.lock);
-+ mutex_lock(&ehea_bcmc_regs.lock);
+- 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;
+ }
- 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);
+ /******************************************************************
+@@ -346,13 +359,6 @@ static void alloc586(struct net_device *dev)
+ ni_reset586();
+ mdelay(32);
- ehea_update_bcmc_registrations();
-- up(&ehea_bcmc_regs.lock);
-+ mutex_unlock(&ehea_bcmc_regs.lock);
+- 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));
- ehea_update_firmware_handles();
-- up(&ehea_fw_handles.lock);
-+ mutex_unlock(&ehea_fw_handles.lock);
+@@ -371,7 +377,7 @@ static void alloc586(struct net_device *dev)
- return ret;
+ p->reset = 0;
+
+- memset_io((char *)p->scb, 0, sizeof(struct scb_struct));
++ memset_io(p->scb, 0, sizeof(struct scb_struct));
}
-@@ -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);
+ /* 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 (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);
- }
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
-- up(&port->port_lock);
-+ mutex_unlock(&port->port_lock);
++ 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;
- return ret;
- }
-@@ -2569,18 +2570,18 @@ static int ehea_down(struct net_device *dev)
- if (port->state == EHEA_PORT_DOWN)
- return 0;
+ dev->base_addr = ioaddr;
+ dev->irq = irq;
+ dev->mem_start = memstart;
+ dev->mem_end = memend;
-- down(&ehea_bcmc_regs.lock);
-+ mutex_lock(&ehea_fw_handles.lock);
++ spin_lock_init(&priv->spinlock);
+
-+ mutex_lock(&ehea_bcmc_regs.lock);
- ehea_drop_multicast_list(dev);
- ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
+ if (!request_region(ioaddr, NI52_TOTAL_SIZE, DRV_NAME))
+ return -EBUSY;
- ehea_free_interrupts(dev);
+@@ -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
-- down(&ehea_fw_handles.lock);
+- memset((char *)dev->priv, 0, sizeof(struct priv));
-
- 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);
+- ((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);
- return ret;
- }
-@@ -2602,15 +2603,15 @@ static int ehea_stop(struct net_device *dev)
- ehea_info("disabling port %s", dev->name);
+ /* 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;
- 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;
- }
+ 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:
--void ehea_purge_sq(struct ehea_qp *orig_qp)
-+static void ehea_purge_sq(struct ehea_qp *orig_qp)
+ static int init586(struct net_device *dev)
{
- 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 *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;
--void ehea_flush_sq(struct ehea_port *port)
-+static void ehea_flush_sq(struct ehea_port *port)
- {
- int i;
+- ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct));
++ ptr = p->scb + 1;
-@@ -2820,7 +2821,7 @@ static void ehea_reset_port(struct work_struct *work)
- struct net_device *dev = port->netdev;
+- 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);
- port->resets++;
-- down(&port->port_lock);
-+ mutex_lock(&port->port_lock);
- netif_stop_queue(dev);
+ 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
+ */
- port_napi_disable(port);
-@@ -2840,7 +2841,7 @@ static void ehea_reset_port(struct work_struct *work)
+- ias_cmd = (struct iasetup_cmd_struct *)ptr;
++ ias_cmd = ptr;
- netif_wake_queue(dev);
- out:
-- up(&port->port_lock);
-+ mutex_unlock(&port->port_lock);
- return;
- }
+ writew(0, &ias_cmd->cmd_status);
+ writew(CMD_IASETUP | CMD_LAST, &ias_cmd->cmd_cmd);
+ writew(0xffff, &ias_cmd->cmd_link);
-@@ -2849,7 +2850,7 @@ static void ehea_rereg_mrs(struct work_struct *work)
- int ret, i;
- struct ehea_adapter *adapter;
+- memcpy_toio((char *)&ias_cmd->iaddr, (char *)dev->dev_addr, ETH_ALEN);
++ memcpy_toio(&ias_cmd->iaddr, (char *)dev->dev_addr, ETH_ALEN);
-- down(&dlpar_mem_lock);
-+ mutex_lock(&dlpar_mem_lock);
- ehea_info("LPAR memory enlarged - re-initializing driver");
+ writew(make16(ias_cmd), &p->scb->cbl_offset);
- 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;
+@@ -663,7 +671,7 @@ static int init586(struct net_device *dev)
+ * TDR, wire check .. e.g. no resistor e.t.c
+ */
-- if (port) {
-- struct net_device *dev = port->netdev;
-+ if (!port)
-+ continue;
+- tdr_cmd = (struct tdr_cmd_struct *)ptr;
++ tdr_cmd = ptr;
-- 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);
- }
- }
+ 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);
-@@ -2912,17 +2915,17 @@ static void ehea_rereg_mrs(struct work_struct *work)
- struct net_device *dev = port->netdev;
+ 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);
- 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,
+ 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
- port = netdev_priv(dev);
+- ptr = alloc_rfa(dev, (void *)ptr); /* init receive-frame-area */
++ ptr = alloc_rfa(dev, ptr); /* init receive-frame-area */
-- sema_init(&port->port_lock, 1);
-+ mutex_init(&port->port_lock);
- port->state = EHEA_PORT_DOWN;
- port->sig_comp_iv = sq_entries / 10;
+ /*
+ * 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).
+ */
-@@ -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);
+-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;
- adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
- if (!adapter) {
-@@ -3446,7 +3449,7 @@ out_free_ad:
+- memset_io((char *) rfd, 0,
++ memset_io(rfd, 0,
+ sizeof(struct rfd_struct) * (p->num_recv_buffs + rfdadd));
+ p->rfd_first = rfd;
- out:
- ehea_update_firmware_handles();
-- up(&ehea_fw_handles.lock);
-+ mutex_unlock(&ehea_fw_handles.lock);
- return ret;
- }
+@@ -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);
-@@ -3465,7 +3468,7 @@ static int __devexit ehea_remove(struct of_device *dev)
+- ptr = (void *) (rfd + (p->num_recv_buffs + rfdadd));
++ ptr = rfd + (p->num_recv_buffs + rfdadd);
- flush_scheduled_work();
+- rbd = (struct rbd_struct *) ptr;
+- ptr = (void *) (rbd + p->num_recv_buffs);
++ rbd = ptr;
++ ptr = rbd + p->num_recv_buffs;
-- down(&ehea_fw_handles.lock);
-+ mutex_lock(&ehea_fw_handles.lock);
+ /* 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));
- 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);
+ 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)
- ehea_update_firmware_handles();
-- up(&ehea_fw_handles.lock);
-+ mutex_unlock(&ehea_fw_handles.lock);
+ /* 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;
- 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));
+ if (debuglevel > 0)
+ printk("R");
-- 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);
+ 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);
- 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];
+ 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. */
-- 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);
+- 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 */
- 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;
- }
+- 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));
-- 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"
+@@ -1178,12 +1186,11 @@ static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev)
-@@ -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 */
+ netif_stop_queue(dev);
- enum {
- NvRegIrqStatus = 0x000,
-@@ -263,11 +175,13 @@ enum {
- NvRegReceiverStatus = 0x98,
- #define NVREG_RCVSTAT_BUSY 0x01
+- 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);
+ }
-- 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
+@@ -1191,14 +1198,14 @@ static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev)
+ # ifdef NO_NOPCOMMANDS
- NvRegTxDeferral = 0xA0,
- #define NVREG_TX_DEFERRAL_DEFAULT 0x15050f
-@@ -290,6 +204,11 @@ enum {
+ #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)
- 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
+ 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 */
+ };
- NvRegTxRingPhysAddr = 0x100,
- NvRegRxRingPhysAddr = 0x104,
-@@ -441,6 +360,7 @@ union ring_type {
+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 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 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"
- #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
+ 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)
- /* 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
++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)
+ }
- #define PHY_GIGABIT 0x0100
+ 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;
+ }
-@@ -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;
+@@ -706,6 +713,251 @@ static int serdes_init_1g(struct niu *np)
+ return 0;
+ }
-+/*
-+ * 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 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;
+
- static inline struct fe_priv *get_nvpriv(struct net_device *dev)
++ 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)
{
- 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;
+ int err, limit;
+@@ -751,6 +1003,28 @@ static int bcm8704_user_dev3_readback(struct niu *np, int reg)
+ return 0;
}
-+static bool nv_optimized(struct fe_priv *np)
++static int bcm8706_init_user_dev3(struct niu *np)
+{
-+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-+ return false;
-+ return true;
++ 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 reg_delay(struct net_device *dev, int offset, u32 mask, u32 target,
- int delay, int delaymax, const char *msg)
+ static int bcm8704_init_user_dev3(struct niu *np)
{
-@@ -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);
+ int err;
+@@ -880,33 +1154,11 @@ static int xcvr_init_10g_mrvl88x2011(struct niu *np)
+ MRVL88X2011_10G_PMD_TX_DIS, MRVL88X2011_ENA_PMDTX);
+ }
-- 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)
+-static int xcvr_init_10g_bcm8704(struct niu *np)
++
++static int xcvr_diag_bcm870x(struct niu *np)
{
- 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;
-+ }
-+ }
- }
- }
+- 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;
-@@ -1435,6 +1462,18 @@ static void nv_stop_tx(struct net_device *dev)
- base + NvRegTransmitPoll);
+ #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 void nv_start_rxtx(struct net_device *dev)
++static int xcvr_10g_set_lb_bcm870x(struct niu *np)
+{
-+ nv_start_rx(dev);
-+ nv_start_tx(dev);
++ 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 void nv_stop_rxtx(struct net_device *dev)
++static int xcvr_init_10g_bcm8706(struct niu *np)
+{
-+ nv_stop_rx(dev);
-+ nv_stop_tx(dev);
++ 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 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;
++static int xcvr_init_10g_bcm8704(struct niu *np)
++{
++ int err;
+
- 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)
++ err = bcm8704_reset(np);
++ if (err)
++ return err;
+
-+ 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;
++ err = bcm8704_init_user_dev3(np);
++ if (err)
++ return err;
+
- 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)
++ err = xcvr_10g_set_lb_bcm870x(np);
++ if (err)
++ return err;
+
-+ 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)
++ err = xcvr_diag_bcm870x(np);
++ if (err)
++ return err;
+
-+ 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;
++ 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;
+ }
- 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 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 void drain_ring(struct net_device *dev)
-+static void nv_drain_rxtx(struct net_device *dev)
++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)
{
- 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));
+ int err, link_up;
+@@ -1317,6 +1768,82 @@ static int link_status_10g(struct niu *np, int *link_up_p)
+ return err;
}
-+static void nv_legacybackoff_reseed(struct net_device *dev)
++static int niu_10g_phy_present(struct niu *np)
+{
-+ u8 __iomem *base = get_hwbase(dev);
-+ u32 reg;
-+ u32 low;
-+ int tx_status = 0;
++ u64 sig, mask, val;
+
-+ reg = readl(base + NvRegSlotTime) & ~NVREG_SLOTTIME_MASK;
-+ get_random_bytes(&low, sizeof(low));
-+ reg |= low & NVREG_SLOTTIME_MASK;
++ 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;
+
-+ /* 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);
++ 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;
+}
+
-+/* Gear Backoff Seeds */
-+#define BACKOFF_SEEDSET_ROWS 8
-+#define BACKOFF_SEEDSET_LFSRS 15
+ 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);
+
-+/* 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}};
++ /* Initialize all 4 lanes of the SERDES. */
++ for (i = 0; i < 4; i++) {
++ u32 rxtx_ctrl, glue0;
+
-+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}};
++ err = esr_read_rxtx_ctrl(np, i, &rxtx_ctrl);
++ if (err)
++ return err;
++ err = esr_read_glue0(np, i, &glue0);
++ if (err)
++ return err;
+
-+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;
++ rxtx_ctrl &= ~(ESR_RXTX_CTRL_VMUXLO);
++ rxtx_ctrl |= (ESR_RXTX_CTRL_ENSTRETCH |
++ (2 << ESR_RXTX_CTRL_VMUXLO_SHIFT));
+
-+ /* 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;
++ 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));
+
-+ get_random_bytes(&miniseed2, sizeof(miniseed2));
-+ miniseed2 &= 0x0fff;
-+ if (miniseed2 == 0)
-+ miniseed2 = 0xabc;
-+ miniseed2_reversed =
-+ ((miniseed2 & 0xF00) >> 8) |
-+ (miniseed2 & 0x0F0) |
-+ ((miniseed2 & 0x00F) << 8);
++ err = esr_write_rxtx_ctrl(np, i, rxtx_ctrl);
++ if (err)
++ return err;
++ err = esr_write_glue0(np, i, glue0);
++ if (err)
++ return err;
++ }
+
-+ 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);
++ 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;
+
-+ /* 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;
++ 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;
+
-+ /* 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);
++ default:
++ return -EINVAL;
++ }
+
-+ /* 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);
++ 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;
+}
+
- /*
- * 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);
-+ }
+ 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;
+
- dev_kfree_skb_any(np->get_tx_ctx->skb);
- np->get_tx_ctx->skb = NULL;
-
-@@ -2260,7 +2426,7 @@ static void nv_tx_timeout(struct net_device *dev)
- }
- printk(KERN_INFO "%s: Dumping tx ring\n", dev->name);
- for (i=0;i<np->tx_ring_size;i+= 4) {
-- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-+ if (!nv_optimized(np)) {
- printk(KERN_INFO "%03x: %08x %08x // %08x %08x // %08x %08x // %08x %08x\n",
- i,
- le32_to_cpu(np->tx_ring.orig[i].buf),
-@@ -2296,7 +2462,7 @@ static void nv_tx_timeout(struct net_device *dev)
- nv_stop_tx(dev);
-
- /* 2) check that the packets were not sent already: */
-- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-+ if (!nv_optimized(np))
- nv_tx_done(dev);
- else
- nv_tx_done_optimized(dev, np->tx_ring_size);
-@@ -2663,12 +2829,10 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
- netif_tx_lock_bh(dev);
- spin_lock(&np->lock);
- /* stop engines */
-- nv_stop_rx(dev);
-- nv_stop_tx(dev);
-+ nv_stop_rxtx(dev);
- nv_txrx_reset(dev);
- /* drain rx queue */
-- nv_drain_rx(dev);
-- nv_drain_tx(dev);
-+ nv_drain_rxtx(dev);
- /* reinit driver view of the rx queue */
- set_bufsize(dev);
- if (nv_init_ring(dev)) {
-@@ -2685,8 +2849,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
- pci_push(base);
-
- /* restart rx engine */
-- nv_start_rx(dev);
-- nv_start_tx(dev);
-+ nv_start_rxtx(dev);
- spin_unlock(&np->lock);
- netif_tx_unlock_bh(dev);
- nv_enable_irq(dev);
-@@ -2973,15 +3136,14 @@ set_speed:
- }
++ 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;
- 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);
- }
+ default:
+@@ -4139,6 +4862,12 @@ static void niu_init_xif_xmac(struct niu *np)
+ struct niu_link_config *lp = &np->link_config;
+ u64 val;
- 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->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;
-- 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;
+@@ -4155,7 +4884,8 @@ static void niu_init_xif_xmac(struct niu *np)
+ val &= ~XMAC_CONFIG_LFS_DISABLE;
} 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);
+ 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
- nv_nic_irq(0, dev);
-@@ -3860,7 +4019,8 @@ static void nv_do_stats_poll(unsigned long data)
- nv_get_hw_stats(dev);
+ val &= ~XMAC_CONFIG_1G_PCS_BYPASS;
+@@ -4224,16 +4954,26 @@ static void niu_init_xif(struct niu *np)
- if (!np->in_shutdown)
-- mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL);
-+ mod_timer(&np->stats_poll,
-+ round_jiffies(jiffies + STATS_INTERVAL));
+ 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 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);
-+ }
+ 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);
+ }
- 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
+ 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;
- /* copy of driver data */
- np->driver_data = id->driver_data;
-+ /* copy of device id */
-+ np->device_id = id->device;
+- 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)
- /* 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;
+ 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;
-- 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
+@@ -4273,8 +5017,18 @@ static int niu_init_pcs(struct niu *np)
+ (void) nr64_xpcs(XPCS_SYMERR_CNT23);
+ break;
- 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;
++ 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;
- }
- if (i == 33) {
-@@ -5561,6 +5730,28 @@ out:
- return err;
+@@ -6254,6 +7008,37 @@ static int __devinit niu_phy_type_prop_decode(struct niu *np,
+ return 0;
}
-+static void nv_restore_phy(struct net_device *dev)
++/* 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)
+{
-+ struct fe_priv *np = netdev_priv(dev);
-+ u16 phy_reserved, mii_control;
++ return !strncmp(np->vpd.board_model, model, strlen(model));
++}
+
-+ 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);
++static int niu_pci_vpd_get_nports(struct niu *np)
++{
++ int ports = 0;
+
-+ /* 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);
++ 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 __devexit nv_remove(struct pci_dev *pci_dev)
+ static void __devinit niu_pci_vpd_validate(struct niu *np)
{
- 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);
+ struct net_device *dev = np->dev;
+@@ -6268,7 +7053,22 @@ static void __devinit niu_pci_vpd_validate(struct niu *np)
+ return;
+ }
-+ /* restore any phy related changes */
-+ nv_restore_phy(dev);
+- 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;
+
- /* free all structures */
- free_rings(dev);
- iounmap(get_hwbase(dev));
-@@ -5716,83 +5910,83 @@ static struct pci_device_id pci_tbl[] = {
- },
- { /* MCP65 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_NEED_TX_LIMIT,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
- },
- { /* MCP65 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
- },
- { /* MCP65 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
- },
- { /* MCP65 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
- },
- { /* MCP67 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
- },
- { /* MCP67 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
- },
- { /* MCP67 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
- },
- { /* MCP67 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
- },
- { /* MCP73 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_28),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
- },
- { /* MCP73 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_29),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
- },
- { /* MCP73 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_30),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
- },
- { /* MCP73 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_31),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
- },
- { /* MCP77 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_32),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
- },
- { /* MCP77 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_33),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
- },
- { /* MCP77 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_34),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
- },
- { /* MCP77 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
- },
- { /* MCP79 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
- },
- { /* MCP79 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
- },
- { /* MCP79 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
- },
- { /* MCP79 Ethernet Controller */
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39),
-- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
-+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
- },
- {0,},
- };
-@@ -5828,6 +6022,8 @@ module_param(msix, int, 0);
- MODULE_PARM_DESC(msix, "MSIX interrupts are enabled by setting to 1 and disabled by setting to 0.");
- module_param(dma_64bit, int, 0);
- MODULE_PARM_DESC(dma_64bit, "High DMA is enabled by setting to 1 and disabled by setting to 0.");
-+module_param(phy_cross, int, 0);
-+MODULE_PARM_DESC(phy_cross, "Phy crossover detection for Realtek 8201 phy is enabled by setting to 1 and disabled by setting to 0.");
-
- MODULE_AUTHOR("Manfred Spraul <manfred at colorfullife.com>");
- MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver");
-diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
-index 940e204..67b4b07 100644
---- a/drivers/net/fs_enet/fs_enet-main.c
-+++ b/drivers/net/fs_enet/fs_enet-main.c
-@@ -1178,7 +1178,7 @@ static int __devinit find_phy(struct device_node *np,
++ if (!parent->num_ports)
++ return -ENODEV;
++ }
+ }
+ }
- 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);
+@@ -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;
-@@ -1202,7 +1202,7 @@ static int __devinit find_phy(struct device_node *np,
- if (!data || len != 4)
- goto out_put_mdio;
+- 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;
-- snprintf(fpi->bus_id, 16, PHY_ID_FMT, res.start, *data);
-+ snprintf(fpi->bus_id, 16, "%x:%02x", res.start, *data);
+- 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);
- 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);
+- 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;
- 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;
+- /* 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;
- new_bus->name = "BB MII Bus",
-- new_bus->id = pdev->id;
-+ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+- 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;
- 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;
+- 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;
-- new_bus->id = res.start;
-+ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+- 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;
++ }
+ }
- 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);
+ parent->port_phy = val;
+@@ -7189,15 +8014,16 @@ static int __devinit niu_get_invariants(struct niu *np)
- pdata = (struct fs_mii_fec_platform_info *)pdev->dev.platform_data;
+ have_props = !err;
-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"
+- err = niu_get_and_validate_port(np);
+- if (err)
+- return err;
+-
+ err = niu_init_mac_ipp_pcs_base(np);
+ if (err)
+ return err;
- #define TX_TIMEOUT (1*HZ)
--#define SKB_ALLOC_TIMEOUT 1000000
- #undef BRIEF_GFAR_ERRORS
- #undef VERBOSE_GFAR_ERRORS
+- 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;
-@@ -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)
+@@ -7209,10 +8035,17 @@ static int __devinit niu_get_invariants(struct niu *np)
+ niu_pci_vpd_fetch(np, offset);
+ nw64(ESPC_PIO_EN, 0);
- rxbdp = priv->rx_bd_base;
- for (i = 0; i < priv->rx_ring_size; i++) {
-- struct sk_buff *skb = NULL;
-+ struct sk_buff *skb;
+- 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;
++ }
-- rxbdp->status = 0;
-+ skb = gfar_new_skb(dev);
+ 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));
-- skb = gfar_new_skb(dev, rxbdp);
-+ if (!skb) {
-+ printk(KERN_ERR "%s: Can't allocate RX buffers\n",
-+ dev->name);
-+
-+ goto err_rxalloc_fail;
-+ }
+- 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);
++ }
+ }
- priv->rx_skbuff[i] = skb;
+ 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 {
-+ gfar_new_rxbdp(dev, rxbdp, skb);
+ #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"
+
- rxbdp++;
- }
+ #define NIU_VPD_MIN_MAJOR 3
+ #define NIU_VPD_MIN_MINOR 4
-@@ -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;
+@@ -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
- if (priv->vlan_enable)
-- frame_size += VLAN_ETH_HLEN;
-+ frame_size += VLAN_HLEN;
+ u8 num_ports;
- if (gfar_uses_fcb(priv))
- frame_size += GMAC_FCB_LEN;
-@@ -1250,17 +1259,12 @@ static void gfar_timeout(struct net_device *dev)
- }
+@@ -3198,10 +3209,13 @@ struct niu {
+ struct niu_parent *parent;
- /* 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;
+ 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
+ */
-- /* 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;
+-/* Must be a power of two */
+-#define RX_RING_SIZE 2048
+-#define TX_RING_SIZE 4096
+-
+ #define LRO_MAX_AGGR 64
-- dev->stats.tx_packets++;
-+ howmany++;
+ #define PE_MIN_MTU 64
+-#define PE_MAX_MTU 1500
++#define PE_MAX_MTU 9000
+ #define PE_DEF_MTU ETH_DATA_LEN
- /* 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)
+ #define DEFAULT_MSG_ENABLE \
+@@ -76,16 +71,6 @@
+ NETIF_MSG_RX_ERR | \
+ NETIF_MSG_TX_ERR)
- /* 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);
+-#define TX_DESC(tx, num) ((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)])
+-#define TX_DESC_INFO(tx, num) ((tx)->ring_info[(num) & (TX_RING_SIZE-1)])
+-#define RX_DESC(rx, num) ((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])
+-#define RX_DESC_INFO(rx, num) ((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
+-#define RX_BUFF(rx, num) ((rx)->buffers[(num) & (RX_RING_SIZE-1)])
+-
+-#define RING_USED(ring) (((ring)->next_to_fill - (ring)->next_to_clean) \
+- & ((ring)->size - 1))
+-#define RING_AVAIL(ring) ((ring->size) - RING_USED(ring))
+-
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR ("Olof Johansson <olof at lixom.net>");
+ MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver");
+@@ -94,6 +79,8 @@ static int debug = -1; /* -1 == use DEFAULT_MSG_ENABLE as value */
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "PA Semi MAC bitmapped debugging message enable value");
-+ /* Clean BD length for empty detection */
-+ bdp->length = 0;
++extern const struct ethtool_ops pasemi_mac_ethtool_ops;
+
- /* 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) */
+ 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;
+ }
-+ dev->stats.tx_packets += howmany;
++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;
+
-+ return howmany;
-+}
++ ring = pasemi_dma_alloc_chan(TXCHAN, sizeof(struct pasemi_mac_csring),
++ offsetof(struct pasemi_mac_csring, chan));
+
-+/* 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);
++ if (!ring) {
++ dev_err(&mac->pdev->dev, "Can't allocate checksum channel\n");
++ goto out_chan;
++ }
+
-+ /* Clear IEVENT */
-+ gfar_write(&priv->regs->ievent, IEVENT_TX_MASK);
++ chno = ring->chan.chno;
+
-+ /* Lock priv */
-+ spin_lock(&priv->txlock);
++ ring->size = CS_RING_SIZE;
++ ring->next_to_fill = 0;
+
-+ gfar_clean_tx_ring(dev);
++ /* Allocate descriptors */
++ if (pasemi_dma_alloc_ring(&ring->chan, CS_RING_SIZE))
++ goto out_ring_desc;
+
- /* 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;
++ 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);
+
-+ bdp->bufPtr = dma_map_single(&dev->dev, skb->data,
-+ priv->rx_buffer_size, DMA_FROM_DEVICE);
++ write_dma_reg(PAS_DMA_TXCHAN_BASEU(chno), val);
+
-+ flags = RXBD_EMPTY | RXBD_INTERRUPT;
++ 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;
+
-+ if (bdp == priv->rx_bd_base + priv->rx_ring_size - 1)
-+ flags |= RXBD_WRAP;
++ pasemi_dma_clear_flag(ring->events[0]);
++ pasemi_dma_clear_flag(ring->events[1]);
+
-+ eieio();
++ ring->fun = pasemi_dma_alloc_fun();
++ if (ring->fun < 0)
++ goto out_fun;
+
-+ *status_len = (u32)flags << 16;
-+}
++ 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;
+
-+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);
++ write_dma_reg(PAS_DMA_TXCHAN_CFG(chno), cfg);
+
- 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();
++ /* 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);
+
-+ /* Add another skb for the future */
-+ newskb = gfar_new_skb(dev);
++ return ring;
+
- 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);
++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:
+
-+ if (unlikely(!newskb))
-+ newskb = skb;
++ return NULL;
++}
+
-+ if (skb) {
-+ dma_unmap_single(&priv->dev->dev,
-+ bdp->bufPtr,
-+ priv->rx_buffer_size,
-+ DMA_FROM_DEVICE);
++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;
+
-+ 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;
++ for (i = 0; i < MAX_CS; i++)
++ if (mac->cs[i])
++ mac->num_cs++;
++}
+
-+ /* 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);
-+ }
++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);
- howmany = gfar_clean_rx_ring(dev, budget);
+ 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;
-@@ -1595,11 +1651,11 @@ static int gfar_poll(struct napi_struct *napi, int budget)
+- 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);
- /* 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);
++ /* 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;
+ }
- }
-
- 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
++ skb = TX_DESC_INFO(txring, i+1).skb;
++ nr_frags = TX_DESC_INFO(txring, i).dma;
+
-+/* Non NAPI Case */
-+#ifndef CONFIG_GFAR_NAPI
- #define DEFAULT_RX_COALESCE 1
- #define DEFAULT_RXCOUNT 16
--#define DEFAULT_RXTIME 4
-+#else
-+#define DEFAULT_RX_COALESCE 0
-+#define DEFAULT_RXCOUNT 0
-+#endif /* CONFIG_GFAR_NAPI */
-
- #define TBIPA_VALUE 0x1f
- #define MIIMCFG_INIT_VALUE 0x00000007
-@@ -242,6 +249,7 @@ extern const char gfar_driver_version[];
- #define IEVENT_PERR 0x00000001
- #define IEVENT_RX_MASK (IEVENT_RXB0 | IEVENT_RXF0)
- #define IEVENT_TX_MASK (IEVENT_TXB | IEVENT_TXF)
-+#define IEVENT_RTX_MASK (IEVENT_RX_MASK | IEVENT_TX_MASK)
- #define IEVENT_ERR_MASK \
- (IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \
- IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \
-@@ -269,11 +277,12 @@ extern const char gfar_driver_version[];
- #define IMASK_FIQ 0x00000004
- #define IMASK_DPE 0x00000002
- #define IMASK_PERR 0x00000001
--#define IMASK_RX_DISABLED ~(IMASK_RXFEN0 | IMASK_BSY)
- #define IMASK_DEFAULT (IMASK_TXEEN | IMASK_TXFEN | IMASK_TXBEN | \
- IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \
- IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \
- | IMASK_PERR)
-+#define IMASK_RTX_DISABLED ((~(IMASK_RXFEN0 | IMASK_TXFEN | IMASK_BSY)) \
-+ & IMASK_DEFAULT)
-
- /* Fifo management */
- #define FIFO_TX_THR_MASK 0x01ff
-@@ -340,6 +349,9 @@ extern const char gfar_driver_version[];
- #define RXBD_OVERRUN 0x0002
- #define RXBD_TRUNCATED 0x0001
- #define RXBD_STATS 0x01ff
-+#define RXBD_ERR (RXBD_LARGE | RXBD_SHORT | RXBD_NONOCTET \
-+ | RXBD_CRCERR | RXBD_OVERRUN \
-+ | RXBD_TRUNCATED)
-
- /* Rx FCB status field bits */
- #define RXFCB_VLN 0x8000
-diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
-index 2432762..b889892 100644
---- a/drivers/net/gianfar_mii.c
-+++ b/drivers/net/gianfar_mii.c
-@@ -173,7 +173,7 @@ int gfar_mdio_probe(struct device *dev)
- new_bus->read = &gfar_mdio_read,
- new_bus->write = &gfar_mdio_write,
- new_bus->reset = &gfar_mdio_reset,
-- new_bus->id = pdev->id;
-+ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
-
- pdata = (struct gianfar_mdio_data *)pdev->dev.platform_data;
-
-diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
-index 0a9b751..1da55dd 100644
---- a/drivers/net/hamradio/6pack.c
-+++ b/drivers/net/hamradio/6pack.c
-@@ -33,7 +33,7 @@
- #include <linux/init.h>
- #include <linux/ip.h>
- #include <linux/tcp.h>
--#include <asm/semaphore.h>
-+#include <linux/semaphore.h>
- #include <asm/atomic.h>
+ 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;
- #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;
+ 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);
-- if (dev->nd_net != &init_net)
-+ if (dev_net(dev) != &init_net)
- goto drop;
+ of_node_put(phy_dn);
- 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
+@@ -1041,13 +1134,7 @@ static int pasemi_mac_open(struct net_device *dev)
{
- struct net_device *dev = (struct net_device *)ptr;
-
-- if (dev->nd_net != &init_net)
-+ if (dev_net(dev) != &init_net)
- return NOTIFY_DONE;
+ 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;
- 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);
- }
- }
+ 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;
-diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
-index 378a239..5d2108c 100644
---- a/drivers/net/ibm_newemac/core.c
-+++ b/drivers/net/ibm_newemac/core.c
-@@ -43,6 +43,8 @@
- #include <asm/io.h>
- #include <asm/dma.h>
- #include <asm/uaccess.h>
-+#include <asm/dcr.h>
-+#include <asm/dcr-regs.h>
++ /* 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;
- #include "core.h"
+ 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);
-@@ -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);
++ 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;
}
-+/* 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)
++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)
+{
-+#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
-+}
++ 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;
+
-+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
++ 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;
+}
+
- /* 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);
+ 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);
- /* 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);
+- 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);
- /* 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);
+- 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;
- /* 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);
+ nfrags = skb_shinfo(skb)->nr_frags;
- /* 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;
+@@ -1350,24 +1535,46 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
}
-@@ -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;
- }
+- 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);
++ }
++ }
--static struct notifier_block emac_of_bus_notifier = {
-+static struct notifier_block emac_of_bus_notifier __devinitdata = {
- .notifier_call = emac_of_bus_notify
- };
+- txring = tx_ring(mac);
++ mactx = dflags | XCT_MACTX_LLEN(skb->len);
-@@ -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;
+ spin_lock_irqsave(&txring->lock, flags);
-+ /* 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
+- 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
*/
-@@ -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)
+- 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;
}
- /* 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;
++ /* 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;
+ }
- /* 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
++#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
-+ * Set if we need phy clock workaround for 440ep or 440gr
++ * 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.
+ */
-+#define EMAC_FTR_440EP_PHY_CLK_FIX 0x00000100
++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;
++ }
+ }
- /* Right now, we don't quite handle the always/possible masks on the
-@@ -312,8 +320,8 @@ enum {
+ /* 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;
- 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,
- };
++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);
+ }
- 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;
+- return 0;
++ return ret;
}
--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;
+ 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);
-@@ -136,6 +136,14 @@ void mal_enable_rx_channel(struct mal_instance *mal, int channel)
- {
- unsigned long flags;
+ dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG |
+- NETIF_F_HIGHDMA;
++ NETIF_F_HIGHDMA | NETIF_F_GSO;
-+ /*
-+ * 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);
+ 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
- MAL_DBG(mal, "enable_rx(%d)" NL, channel);
-@@ -148,6 +156,14 @@ void mal_enable_rx_channel(struct mal_instance *mal, int channel)
+ dev->change_mtu = pasemi_mac_change_mtu;
++ dev->ethtool_ops = &pasemi_mac_ethtool_ops;
- 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));
+ if (err)
+ goto out;
+diff --git a/drivers/net/pasemi_mac.h b/drivers/net/pasemi_mac.h
+index 99e7b93..1a115ec 100644
+--- a/drivers/net/pasemi_mac.h
++++ b/drivers/net/pasemi_mac.h
+@@ -26,7 +26,14 @@
+ #include <linux/spinlock.h>
+ #include <linux/phy.h>
- 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);
- }
++/* 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
--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;
- }
+ 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 */
+ };
--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);
++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;
-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);
- }
+ 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;
--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);
+ u8 mac_addr[6];
-diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
-index 57772be..ce4fc2e 100644
---- a/drivers/net/ibmveth.c
-+++ b/drivers/net/ibmveth.c
-@@ -49,7 +49,6 @@
- #include <linux/in.h>
- #include <linux/ip.h>
- #include <net/net_namespace.h>
--#include <asm/semaphore.h>
- #include <asm/hvcall.h>
- #include <asm/atomic.h>
- #include <asm/vio.h>
-@@ -1259,26 +1258,7 @@ static void ibmveth_proc_unregister_driver(void)
- remove_proc_entry(IBMVETH_PROC_DIR, init_net.proc_net);
- }
+@@ -74,6 +92,7 @@ struct pasemi_mac {
--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)
+ 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;
+ };
- 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,
--};
++#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))
- 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);
- }
+ /* PCI register offsets and formats */
- 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,
+@@ -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,
};
- 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;
+@@ -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)
- pci_set_master(pdev);
-+ pci_save_state(pdev);
++#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)
- 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);
++
+ #endif /* PASEMI_MAC_H */
+diff --git a/drivers/net/pasemi_mac_ethtool.c b/drivers/net/pasemi_mac_ethtool.c
+new file mode 100644
+index 0000000..5e8df3a
+--- /dev/null
++++ b/drivers/net/pasemi_mac_ethtool.c
+@@ -0,0 +1,159 @@
++/*
++ * Copyright (C) 2006-2008 PA Semi, Inc
++ *
++ * Ethtool hooks for the PA Semi PWRficient onchip 1G/10G Ethernet MACs
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++
++#include <linux/netdevice.h>
++#include <linux/ethtool.h>
++#include <linux/pci.h>
++#include <linux/inet_lro.h>
++
++#include <asm/pasemi_dma.h>
++#include "pasemi_mac.h"
++
++static struct {
++ const char str[ETH_GSTRING_LEN];
++} ethtool_stats_keys[] = {
++ { "rx-drops" },
++ { "rx-bytes" },
++ { "rx-packets" },
++ { "rx-broadcast-packets" },
++ { "rx-multicast-packets" },
++ { "rx-crc-errors" },
++ { "rx-undersize-errors" },
++ { "rx-oversize-errors" },
++ { "rx-short-fragment-errors" },
++ { "rx-jabber-errors" },
++ { "rx-64-byte-packets" },
++ { "rx-65-127-byte-packets" },
++ { "rx-128-255-byte-packets" },
++ { "rx-256-511-byte-packets" },
++ { "rx-512-1023-byte-packets" },
++ { "rx-1024-1518-byte-packets" },
++ { "rx-pause-frames" },
++ { "tx-bytes" },
++ { "tx-packets" },
++ { "tx-broadcast-packets" },
++ { "tx-multicast-packets" },
++ { "tx-collisions" },
++ { "tx-late-collisions" },
++ { "tx-excessive-collisions" },
++ { "tx-crc-errors" },
++ { "tx-undersize-errors" },
++ { "tx-oversize-errors" },
++ { "tx-64-byte-packets" },
++ { "tx-65-127-byte-packets" },
++ { "tx-128-255-byte-packets" },
++ { "tx-256-511-byte-packets" },
++ { "tx-512-1023-byte-packets" },
++ { "tx-1024-1518-byte-packets" },
++};
++
++static int
++pasemi_mac_ethtool_get_settings(struct net_device *netdev,
++ struct ethtool_cmd *cmd)
++{
++ struct pasemi_mac *mac = netdev_priv(netdev);
++ struct phy_device *phydev = mac->phydev;
++
++ return phy_ethtool_gset(phydev, cmd);
++}
++
++static void
++pasemi_mac_ethtool_get_drvinfo(struct net_device *netdev,
++ struct ethtool_drvinfo *drvinfo)
++{
++ struct pasemi_mac *mac;
++ mac = netdev_priv(netdev);
++
++ /* clear and fill out info */
++ memset(drvinfo, 0, sizeof(struct ethtool_drvinfo));
++ strncpy(drvinfo->driver, "pasemi_mac", 12);
++ strcpy(drvinfo->version, "N/A");
++ strcpy(drvinfo->fw_version, "N/A");
++ strncpy(drvinfo->bus_info, pci_name(mac->pdev), 32);
++}
++
++static u32
++pasemi_mac_ethtool_get_msglevel(struct net_device *netdev)
++{
++ struct pasemi_mac *mac = netdev_priv(netdev);
++ return mac->msg_enable;
++}
++
++static void
++pasemi_mac_ethtool_set_msglevel(struct net_device *netdev,
++ u32 level)
++{
++ struct pasemi_mac *mac = netdev_priv(netdev);
++ mac->msg_enable = level;
++}
++
++
++static void
++pasemi_mac_ethtool_get_ringparam(struct net_device *netdev,
++ struct ethtool_ringparam *ering)
++{
++ struct pasemi_mac *mac = netdev->priv;
++
++ ering->tx_max_pending = TX_RING_SIZE/2;
++ ering->tx_pending = RING_USED(mac->tx)/2;
++ ering->rx_max_pending = RX_RING_SIZE/4;
++ ering->rx_pending = RING_USED(mac->rx)/4;
++}
++
++static int pasemi_mac_get_sset_count(struct net_device *netdev, int sset)
++{
++ switch (sset) {
++ case ETH_SS_STATS:
++ return ARRAY_SIZE(ethtool_stats_keys);
++ default:
++ return -EOPNOTSUPP;
++ }
++}
++
++static void pasemi_mac_get_ethtool_stats(struct net_device *netdev,
++ struct ethtool_stats *stats, u64 *data)
++{
++ struct pasemi_mac *mac = netdev->priv;
++ int i;
++
++ data[0] = pasemi_read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if))
++ >> PAS_DMA_RXINT_RCMDSTA_DROPS_S;
++ for (i = 0; i < 32; i++)
++ data[1+i] = pasemi_read_mac_reg(mac->dma_if, PAS_MAC_RMON(i));
++}
++
++static void pasemi_mac_get_strings(struct net_device *netdev, u32 stringset,
++ u8 *data)
++{
++ memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys));
++}
++
++const struct ethtool_ops pasemi_mac_ethtool_ops = {
++ .get_settings = pasemi_mac_ethtool_get_settings,
++ .get_drvinfo = pasemi_mac_ethtool_get_drvinfo,
++ .get_msglevel = pasemi_mac_ethtool_get_msglevel,
++ .set_msglevel = pasemi_mac_ethtool_set_msglevel,
++ .get_link = ethtool_op_get_link,
++ .get_ringparam = pasemi_mac_ethtool_get_ringparam,
++ .get_strings = pasemi_mac_get_strings,
++ .get_sset_count = pasemi_mac_get_sset_count,
++ .get_ethtool_stats = pasemi_mac_get_ethtool_stats,
++};
++
+diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
+index 3ac8529..6bf9e76 100644
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -48,7 +48,7 @@ config VITESSE_PHY
+ config SMSC_PHY
+ tristate "Drivers for SMSC PHYs"
+ ---help---
+- Currently supports the LAN83C185 PHY
++ Currently supports the LAN83C185, LAN8187 and LAN8700 PHYs
- 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,
- },
+ config BROADCOM_PHY
+ tristate "Drivers for Broadcom PHYs"
+diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
+index 5b80358..60c5cfe 100644
+--- a/drivers/net/phy/broadcom.c
++++ b/drivers/net/phy/broadcom.c
+@@ -99,6 +99,41 @@ static int bcm54xx_config_intr(struct phy_device *phydev)
+ return err;
+ }
+
++static int bcm5481_config_aneg(struct phy_device *phydev)
++{
++ int ret;
++
++ /* Aneg firsly. */
++ ret = genphy_config_aneg(phydev);
++
++ /* Then we can set up the delay. */
++ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
++ u16 reg;
++
++ /*
++ * There is no BCM5481 specification available, so down
++ * here is everything we know about "register 0x18". This
++ * at least helps BCM5481 to successfuly receive packets
++ * on MPC8360E-RDK board. Peter Barada <peterb at logicpd.com>
++ * says: "This sets delay between the RXD and RXC signals
++ * instead of using trace lengths to achieve timing".
++ */
++
++ /* Set RDX clk delay. */
++ reg = 0x7 | (0x7 << 12);
++ phy_write(phydev, 0x18, reg);
++
++ reg = phy_read(phydev, 0x18);
++ /* Set RDX-RXC skew. */
++ reg |= (1 << 8);
++ /* Write bits 14:0. */
++ reg |= (1 << 15);
++ phy_write(phydev, 0x18, reg);
++ }
++
++ return ret;
++}
++
+ static struct phy_driver bcm5411_driver = {
+ .phy_id = 0x00206070,
+ .phy_id_mask = 0xfffffff0,
+@@ -141,8 +176,36 @@ static struct phy_driver bcm5461_driver = {
+ .driver = { .owner = THIS_MODULE },
};
-@@ -2256,6 +2257,7 @@ static void FIR2SIR(int iobase)
- MODULE_AUTHOR("Benjamin Kong <benjamin_kong at ali.com.tw>");
- MODULE_DESCRIPTION("ALi FIR Controller Driver");
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:" ALI_IRCC_DRIVER_NAME);
++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;
+ }
- module_param_array(io, int, NULL, 0);
-diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
-index 8c09344..d5c2d27 100644
---- a/drivers/net/irda/pxaficp_ir.c
-+++ b/drivers/net/irda/pxaficp_ir.c
-@@ -36,6 +36,7 @@
- #include <asm/hardware.h>
- #include <asm/arch/irda.h>
- #include <asm/arch/pxa-regs.h>
-+#include <asm/arch/pxa2xx-gpio.h>
+- 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)
- #ifdef CONFIG_MACH_MAINSTONE
- #include <asm/arch/mainstone.h>
-@@ -831,6 +832,11 @@ static int pxa_irda_probe(struct platform_device *pdev)
- if (err)
- goto err_mem_5;
+ phydev->bus = bus;
-+ if (si->pdata->startup)
-+ err = si->pdata->startup(si->dev);
-+ if (err)
-+ goto err_startup;
++ /* Run all of the fixups for this PHY */
++ phy_scan_fixups(phydev);
+
- 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);
+ err = device_register(&phydev->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);
+ 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;
- 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,
- },
- };
+ default:
+diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
+index f4c4fd8..ac3c01d 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));
+ }
-@@ -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 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);
- static int veth_allocate_events(HvLpIndex rlp, int number)
+ /**
+- * 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)
{
-- struct veth_allocation vc = { COMPLETION_INITIALIZER(vc.c), 0 };
-+ struct veth_allocation vc =
-+ { COMPLETION_INITIALIZER_ONSTACK(vc.c), 0 };
+ int phy_reg;
+- u32 phy_id;
+- struct phy_device *dev = NULL;
- 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;
- };
+ /* Grab the bits from PHYIR1, and put them
+ * in the upper half */
+ phy_reg = bus->read(bus, addr, MII_PHYSID1);
- 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;
+ if (phy_reg < 0)
+- return ERR_PTR(phy_reg);
++ return -EIO;
- 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;
+- phy_id = (phy_reg & 0xffff) << 16;
++ *phy_id = (phy_reg & 0xffff) << 16;
- /* 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;
+ /* Grab the bits from PHYIR2, and put them in the lower half */
+ phy_reg = bus->read(bus, addr, MII_PHYSID2);
- /* 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;
-+};
+ if (phy_reg < 0)
+- return ERR_PTR(phy_reg);
++ return -EIO;
+
-+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);
++ *phy_id |= (phy_reg & 0xffff);
+
++ return 0;
++}
+
- #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);
++/**
++ * 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;
- static void ixgb_cleanup_eeprom(struct ixgb_hw *hw);
+- phy_id |= (phy_reg & 0xffff);
++ r = get_phy_id(bus, addr, &phy_id);
++ if (r)
++ return ERR_PTR(r);
-@@ -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)
+ /* If the phy_id is all Fs, there is no device there */
+ if (0xffffffff == phy_id)
+@@ -146,7 +256,7 @@ void phy_prepare_link(struct phy_device *phydev,
+ /**
+ * phy_connect - connect an ethernet device to a PHY device
+ * @dev: the network device to connect
+- * @phy_id: the PHY device to connect
++ * @bus_id: the id string of the PHY device to connect
+ * @handler: callback function for state change notifications
+ * @flags: PHY device's dev_flags
+ * @interface: PHY device's interface
+@@ -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)
{
-- uint32_t eecd_reg;
-- uint32_t mask;
-+ u32 eecd_reg;
-+ u32 mask;
+ struct phy_device *phydev;
- /* 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,
+- 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
*
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
--static uint16_t
-+static u16
- ixgb_shift_in_bits(struct ixgb_hw *hw)
+@@ -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)
{
-- uint32_t eecd_reg;
-- uint32_t i;
-- uint16_t data;
-+ u32 eecd_reg;
-+ u32 i;
-+ u16 data;
+ struct bus_type *bus = &mdio_bus_type;
+ struct phy_device *phydev;
+@@ -226,12 +336,12 @@ struct phy_device *phy_attach(struct net_device *dev,
- /* 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;
+ /* 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);
- eecd_reg = IXGB_READ_REG(hw, EECD);
+ 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);
+ }
-@@ -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;
+@@ -251,7 +361,7 @@ struct phy_device *phy_attach(struct net_device *dev,
- eecd_reg = IXGB_READ_REG(hw, EECD);
+ if (phydev->attached_dev) {
+ printk(KERN_ERR "%s: %s already attached\n",
+- dev->name, phy_id);
++ dev->name, bus_id);
+ return ERR_PTR(-EBUSY);
+ }
-@@ -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;
+@@ -267,6 +377,11 @@ struct phy_device *phy_attach(struct net_device *dev,
+ if (phydev->drv->config_init) {
+ int err;
- eecd_reg = IXGB_READ_REG(hw, EECD);
++ err = phy_scan_fixups(phydev);
++
++ if (err < 0)
++ return ERR_PTR(err);
++
+ err = phydev->drv->config_init(phydev);
-@@ -259,7 +259,7 @@ ixgb_clock_eeprom(struct ixgb_hw *hw)
- static void
- ixgb_cleanup_eeprom(struct ixgb_hw *hw)
+ if (err < 0)
+@@ -375,6 +490,7 @@ EXPORT_SYMBOL(genphy_config_advert);
+ */
+ int genphy_setup_forced(struct phy_device *phydev)
{
-- uint32_t eecd_reg;
-+ u32 eecd_reg;
-
- eecd_reg = IXGB_READ_REG(hw, EECD);
++ int err;
+ int ctl = 0;
-@@ -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;
+ 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);
- /* 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 (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;
- if(eecd_reg & IXGB_EECD_DO)
-- return (TRUE);
-+ return (true);
+ /* 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);
- udelay(50);
- }
- ASSERT(0);
-- return (FALSE);
-+ return (false);
+- return ctl;
++ return err;
}
- /******************************************************************************
-@@ -319,22 +319,22 @@ ixgb_wait_eeprom_command(struct ixgb_hw *hw)
- * valid.
+
+diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
+index b1d8ed4..73baa7a 100644
+--- a/drivers/net/phy/smsc.c
++++ b/drivers/net/phy/smsc.c
+@@ -12,6 +12,8 @@
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*
- * 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)
++ * Support added for SMSC LAN8187 and LAN8700 by steve.glendinning at smsc.com
++ *
+ */
+
+ #include <linux/kernel.h>
+@@ -38,7 +40,7 @@
+ (MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4)
+
+
+-static int lan83c185_config_intr(struct phy_device *phydev)
++static int smsc_phy_config_intr(struct phy_device *phydev)
{
-- uint16_t checksum = 0;
-- uint16_t i;
-+ u16 checksum = 0;
-+ u16 i;
+ int rc = phy_write (phydev, MII_LAN83C185_IM,
+ ((PHY_INTERRUPT_ENABLED == phydev->interrupts)
+@@ -48,16 +50,16 @@ static int lan83c185_config_intr(struct phy_device *phydev)
+ return rc < 0 ? rc : 0;
+ }
- for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++)
- checksum += ixgb_read_eeprom(hw, i);
+-static int lan83c185_ack_interrupt(struct phy_device *phydev)
++static int smsc_phy_ack_interrupt(struct phy_device *phydev)
+ {
+ int rc = phy_read (phydev, MII_LAN83C185_ISF);
-- if(checksum == (uint16_t) EEPROM_SUM)
-- return (TRUE);
-+ if(checksum == (u16) EEPROM_SUM)
-+ return (true);
- else
-- return (FALSE);
-+ return (false);
+ return rc < 0 ? rc : 0;
}
- /******************************************************************************
-@@ -348,13 +348,13 @@ ixgb_validate_eeprom_checksum(struct ixgb_hw *hw)
- void
- ixgb_update_eeprom_checksum(struct ixgb_hw *hw)
+-static int lan83c185_config_init(struct phy_device *phydev)
++static int smsc_phy_config_init(struct phy_device *phydev)
{
-- uint16_t checksum = 0;
-- uint16_t i;
-+ u16 checksum = 0;
-+ u16 i;
+- return lan83c185_ack_interrupt (phydev);
++ return smsc_phy_ack_interrupt (phydev);
+ }
- 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;
+@@ -73,22 +75,87 @@ static struct phy_driver lan83c185_driver = {
+ /* basic functions */
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+- .config_init = lan83c185_config_init,
++ .config_init = smsc_phy_config_init,
- 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;
+ /* IRQ related */
+- .ack_interrupt = lan83c185_ack_interrupt,
+- .config_intr = lan83c185_config_intr,
++ .ack_interrupt = smsc_phy_ack_interrupt,
++ .config_intr = smsc_phy_config_intr,
++
++ .driver = { .owner = THIS_MODULE, }
++};
++
++static struct phy_driver lan8187_driver = {
++ .phy_id = 0x0007c0b0, /* OUI=0x00800f, Model#=0x0b */
++ .phy_id_mask = 0xfffffff0,
++ .name = "SMSC LAN8187",
++
++ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
++ | SUPPORTED_Asym_Pause),
++ .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
++
++ /* basic functions */
++ .config_aneg = genphy_config_aneg,
++ .read_status = genphy_read_status,
++ .config_init = smsc_phy_config_init,
++
++ /* IRQ related */
++ .ack_interrupt = smsc_phy_ack_interrupt,
++ .config_intr = smsc_phy_config_intr,
++
++ .driver = { .owner = THIS_MODULE, }
++};
++
++static struct phy_driver lan8700_driver = {
++ .phy_id = 0x0007c0c0, /* OUI=0x00800f, Model#=0x0c */
++ .phy_id_mask = 0xfffffff0,
++ .name = "SMSC LAN8700",
++
++ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
++ | SUPPORTED_Asym_Pause),
++ .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
++
++ /* basic functions */
++ .config_aneg = genphy_config_aneg,
++ .read_status = genphy_read_status,
++ .config_init = smsc_phy_config_init,
++
++ /* IRQ related */
++ .ack_interrupt = smsc_phy_ack_interrupt,
++ .config_intr = smsc_phy_config_intr,
-@@ -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;
+ .driver = { .owner = THIS_MODULE, }
+ };
- /* 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)
+ static int __init smsc_init(void)
{
-- uint16_t i;
-- uint16_t checksum = 0;
-+ u16 i;
-+ u16 checksum = 0;
- struct ixgb_ee_map_type *ee_map;
+- return phy_driver_register (&lan83c185_driver);
++ int ret;
++
++ ret = phy_driver_register (&lan83c185_driver);
++ if (ret)
++ goto err1;
++
++ ret = phy_driver_register (&lan8187_driver);
++ if (ret)
++ goto err2;
++
++ ret = phy_driver_register (&lan8700_driver);
++ if (ret)
++ goto err3;
++
++ return 0;
++
++err3:
++ phy_driver_unregister (&lan8187_driver);
++err2:
++ phy_driver_unregister (&lan83c185_driver);
++err1:
++ return ret;
+ }
- DEBUGFUNC("ixgb_get_eeprom_data");
-@@ -473,27 +473,27 @@ ixgb_get_eeprom_data(struct ixgb_hw *hw)
+ static void __exit smsc_exit(void)
+ {
++ phy_driver_unregister (&lan8700_driver);
++ phy_driver_unregister (&lan8187_driver);
+ phy_driver_unregister (&lan83c185_driver);
+ }
- 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);
- }
+diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
+index f023d5b..f1a52de 100644
+--- a/drivers/net/ppp_async.c
++++ b/drivers/net/ppp_async.c
+@@ -158,6 +158,9 @@ ppp_asynctty_open(struct tty_struct *tty)
+ struct asyncppp *ap;
+ int err;
-- 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 (tty->ops->write == NULL)
++ return -EOPNOTSUPP;
++
+ err = -ENOMEM;
+ ap = kzalloc(sizeof(*ap), GFP_KERNEL);
+ if (!ap)
+@@ -358,9 +361,7 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
+ if (!skb_queue_empty(&ap->rqueue))
+ tasklet_schedule(&ap->tsk);
+ ap_put(ap);
+- if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
+- && tty->driver->unthrottle)
+- tty->driver->unthrottle(tty);
++ tty_unthrottle(tty);
+ }
- 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);
- }
+ static void
+@@ -676,7 +677,7 @@ ppp_async_push(struct asyncppp *ap)
+ if (!tty_stuffed && ap->optr < ap->olim) {
+ avail = ap->olim - ap->optr;
+ set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+- sent = tty->driver->write(tty, ap->optr, avail);
++ sent = tty->ops->write(tty, ap->optr, avail);
+ if (sent < 0)
+ goto flush; /* error, e.g. loss of CD */
+ ap->optr += sent;
+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)
-- return(TRUE);
-+ return(true);
+ outf:
+ kfree_skb(skb);
+- ++ppp->stats.tx_dropped;
++ ++ppp->dev->stats.tx_dropped;
+ return 0;
}
- /******************************************************************************
-@@ -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)
+-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)
{
- 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);
+@@ -1095,8 +1086,8 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
+ #endif /* CONFIG_PPP_FILTER */
}
-@@ -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]);
- }
+- ++ppp->stats.tx_packets;
+- ppp->stats.tx_bytes += skb->len - 2;
++ ++ppp->dev->stats.tx_packets;
++ ppp->dev->stats.tx_bytes += skb->len - 2;
-@@ -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;
+ 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;
+ }
- DEBUGFUNC("ixgb_get_ee_mac_addr");
+ /*
+@@ -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 (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));
+ 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;
-@@ -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)
+ 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)
{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+- ++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;
+ }
-- 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));
+- ++ppp->stats.rx_packets;
+- ppp->stats.rx_bytes += skb->len - 2;
++ ++ppp->dev->stats.rx_packets;
++ ppp->dev->stats.rx_bytes += skb->len - 2;
- 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 @@
+ 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);
+ }
- /* 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;
- };
+@@ -2377,12 +2368,12 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st)
+ struct slcompress *vj = ppp->vj;
- /* EEPROM Functions */
--uint16_t ixgb_read_eeprom(struct ixgb_hw *hw, uint16_t reg);
-+u16 ixgb_read_eeprom(struct ixgb_hw *hw, u16 reg);
+ 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;
--boolean_t ixgb_validate_eeprom_checksum(struct ixgb_hw *hw);
-+bool ixgb_validate_eeprom_checksum(struct ixgb_hw *hw);
+ dev->hard_start_xmit = ppp_start_xmit;
+- dev->get_stats = ppp_net_stats;
+ dev->do_ioctl = ppp_net_ioctl;
- void ixgb_update_eeprom_checksum(struct ixgb_hw *hw);
+ ret = -EEXIST;
+diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
+index 0d80fa5..b8f0369 100644
+--- a/drivers/net/ppp_synctty.c
++++ b/drivers/net/ppp_synctty.c
+@@ -207,6 +207,9 @@ ppp_sync_open(struct tty_struct *tty)
+ struct syncppp *ap;
+ int err;
--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);
++ if (tty->ops->write == NULL)
++ return -EOPNOTSUPP;
++
+ ap = kzalloc(sizeof(*ap), GFP_KERNEL);
+ err = -ENOMEM;
+ if (!ap)
+@@ -398,9 +401,7 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
+ if (!skb_queue_empty(&ap->rqueue))
+ tasklet_schedule(&ap->tsk);
+ sp_put(ap);
+- if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
+- && tty->driver->unthrottle)
+- tty->driver->unthrottle(tty);
++ tty_unthrottle(tty);
+ }
- #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 @@
+ static void
+@@ -653,7 +654,7 @@ ppp_sync_push(struct syncppp *ap)
+ tty_stuffed = 0;
+ if (!tty_stuffed && ap->tpkt) {
+ set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+- sent = tty->driver->write(tty, ap->tpkt->data, ap->tpkt->len);
++ sent = tty->ops->write(tty, ap->tpkt->data, ap->tpkt->len);
+ if (sent < 0)
+ goto flush; /* error, e.g. loss of CD */
+ if (sent < ap->tpkt->len) {
+diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
+index ac0ac98..58a26a4 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;
- #include <asm/uaccess.h>
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
--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
+ /* 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;
- 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 (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto drop;
- 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;
- }
+ 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;
--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)
- }
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto abort;
- static int
--ixgb_set_rx_csum(struct net_device *netdev, uint32_t data)
-+ixgb_set_rx_csum(struct net_device *netdev, u32 data)
+ if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
+@@ -1052,11 +1052,9 @@ static int __init pppoe_proc_init(void)
{
- struct ixgb_adapter *adapter = netdev_priv(netdev);
-
- adapter->rx_csum = data;
+ struct proc_dir_entry *p;
- 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)
+- p = create_proc_entry("pppoe", S_IRUGO, init_net.proc_net);
++ p = proc_net_fops_create(&init_net, "pppoe", S_IRUGO, &pppoe_seq_fops);
+ if (!p)
+ return -ENOMEM;
+-
+- p->proc_fops = &pppoe_seq_fops;
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)
- }
+ #else /* CONFIG_PROC_FS */
+diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
+index 3d10ca0..244d783 100644
+--- a/drivers/net/pppol2tp.c
++++ b/drivers/net/pppol2tp.c
+@@ -2469,12 +2469,12 @@ static int __init pppol2tp_init(void)
+ goto out_unregister_pppol2tp_proto;
- 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)
+ #ifdef CONFIG_PROC_FS
+- pppol2tp_proc = create_proc_entry("pppol2tp", 0, init_net.proc_net);
++ pppol2tp_proc = proc_net_fops_create(&init_net, "pppol2tp", 0,
++ &pppol2tp_proc_fops);
+ if (!pppol2tp_proc) {
+ err = -ENOMEM;
+ goto out_unregister_pppox_proto;
+ }
+- pppol2tp_proc->proc_fops = &pppol2tp_proc_fops;
+ #endif /* CONFIG_PROC_FS */
+ printk(KERN_INFO "PPPoL2TP kernel driver, %s\n",
+ PPPOL2TP_DRV_VERSION);
+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 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;
- }
++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,
+ };
-@@ -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;
+ /**
+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
+ };
- /* 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 */
++/* 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)
-- regs->len = (reg - reg_start) * sizeof(uint32_t);
-+ regs->len = (reg - reg_start) * sizeof(u32);
+ 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,
- static int
-@@ -416,7 +407,7 @@ ixgb_get_eeprom_len(struct net_device *netdev)
+ if (seg_cnt == 1) {
+ /* Terminate the last segment. */
+- oal_entry->len =
+- cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
++ oal_entry->len |= cpu_to_le32(OAL_LAST_ENTRY);
+ } else {
+ oal = tx_cb->oal;
+ for (completed_segs=0; completed_segs<frag_cnt; completed_segs++,seg++) {
+@@ -2530,8 +2529,7 @@ static int ql_send_map(struct ql3_adapter *qdev,
+ frag->size);
+ }
+ /* Terminate the last segment. */
+- oal_entry->len =
+- cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
++ oal_entry->len |= cpu_to_le32(OAL_LAST_ENTRY);
+ }
- 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));
+ return NETDEV_TX_OK;
+diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
+index 3acfeea..6572425 100644
+--- a/drivers/net/r8169.c
++++ b/drivers/net/r8169.c
+@@ -1617,6 +1617,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ SET_NETDEV_DEV(dev, &pdev->dev);
+ tp = netdev_priv(dev);
+ tp->dev = dev;
++ tp->pci_dev = pdev;
+ tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
+
+ /* enable device (incl. PCI PM wakeup and hotplug setup) */
+@@ -1705,18 +1706,18 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+
+ rtl8169_print_mac_version(tp);
+
+- for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) {
++ for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) {
+ if (tp->mac_version == rtl_chip_info[i].mac_version)
+ break;
+ }
+- if (i < 0) {
++ if (i == ARRAY_SIZE(rtl_chip_info)) {
+ /* Unknown chip: assume array element #0, original RTL-8169 */
+ if (netif_msg_probe(tp)) {
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "unknown chip version, assuming %s\n",
+ rtl_chip_info[0].name);
+ }
+- i++;
++ i = 0;
}
+ tp->chipset = i;
-- memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset & 1),
-+ memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1),
- eeprom->len);
- kfree(eeprom_buff);
+@@ -1777,7 +1778,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ #endif
-@@ -464,14 +455,14 @@ geeprom_error:
+ tp->intr_mask = 0xffff;
+- tp->pci_dev = pdev;
+ tp->mmio_addr = ioaddr;
+ tp->align = cfg->align;
+ tp->hw_start = cfg->hw_start;
+diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
+index e7fd08a..2b8fd68 100644
+--- a/drivers/net/rionet.c
++++ b/drivers/net/rionet.c
+@@ -77,7 +77,7 @@ static int rionet_capable = 1;
+ * could be made into a hash table to save memory depending
+ * on system trade-offs.
+ */
+-static struct rio_dev *rionet_active[RIO_MAX_ROUTE_ENTRIES];
++static struct rio_dev **rionet_active;
+
+ #define is_rionet_capable(pef, src_ops, dst_ops) \
+ ((pef & RIO_PEF_INB_MBOX) && \
+@@ -195,7 +195,8 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+ }
+
+ if (eth->h_dest[0] & 0x01) {
+- for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++)
++ for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size);
++ i++)
+ if (rionet_active[i])
+ rionet_queue_tx_msg(skb, ndev,
+ rionet_active[i]);
+@@ -385,6 +386,8 @@ static void rionet_remove(struct rio_dev *rdev)
+ struct net_device *ndev = NULL;
+ struct rionet_peer *peer, *tmp;
+
++ free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ?
++ __ilog2(sizeof(void *)) + 4 : 0);
+ unregister_netdev(ndev);
+ kfree(ndev);
- 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;
+@@ -443,6 +446,15 @@ static int rionet_setup_netdev(struct rio_mport *mport)
+ goto out;
+ }
- if(eeprom->len == 0)
- return -EINVAL;
-@@ -570,14 +561,14 @@ ixgb_set_ringparam(struct net_device *netdev,
- return -EINVAL;
++ rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL,
++ mport->sys_size ? __ilog2(sizeof(void *)) + 4 : 0);
++ if (!rionet_active) {
++ rc = -ENOMEM;
++ goto out;
++ }
++ memset((void *)rionet_active, 0, sizeof(void *) *
++ RIO_MAX_ROUTE_ENTRIES(mport->sys_size));
++
+ /* Set up private area */
+ rnet = (struct rionet_private *)ndev->priv;
+ rnet->mport = mport;
+diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
+index c082cf0..523478e 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'
+ ************************************************************************/
- if(netif_running(adapter->netdev))
-- ixgb_down(adapter,TRUE);
-+ ixgb_down(adapter, true);
+ #include <linux/module.h>
+@@ -84,7 +86,7 @@
+ #include "s2io.h"
+ #include "s2io-regs.h"
-- 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);
+-#define DRV_VERSION "2.0.26.20"
++#define DRV_VERSION "2.0.26.23"
-- 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);
+ /* S2io Driver name & version. */
+ static char s2io_driver_name[] = "Neterion";
+@@ -115,20 +117,6 @@ static inline int RXD_IS_UP2DT(struct RxD_t *rxdp)
- if(netif_running(adapter->netdev)) {
-@@ -633,7 +624,7 @@ ixgb_led_blink_callback(unsigned long data)
- }
+ #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 int
--ixgb_phys_id(struct net_device *netdev, uint32_t data)
-+ixgb_phys_id(struct net_device *netdev, u32 data)
+ static inline int is_s2io_card_up(const struct s2io_nic * sp)
{
- struct ixgb_adapter *adapter = netdev_priv(netdev);
-
-@@ -669,7 +660,7 @@ ixgb_get_sset_count(struct net_device *netdev, int sset)
+@@ -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;
- 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;
- }
- }
++/* 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);
- 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 @@
+ /* 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)
- /* Local function prototypes */
++/* 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;
--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);
+ for (j = 0; j < page_num; j++) {
+ int k = 0;
+@@ -704,6 +809,7 @@ static int init_shared_mem(struct s2io_nic *nic)
+ config->rx_cfg[i].num_rxd - 1;
+ mac_control->rings[i].nic = nic;
+ mac_control->rings[i].ring_no = i;
++ mac_control->rings[i].lro = lro_enable;
+
+ blk_cnt = config->rx_cfg[i].num_rxd /
+ (rxd_count[nic->rxd_mode] + 1);
+@@ -1455,113 +1561,112 @@ static int init_nic(struct s2io_nic *nic)
+ writeq(val64, &bar0->tx_fifo_partition_0);
--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);
+ /* Filling the Rx round robin registers as per the
+- * number of Rings and steering based on QoS.
+- */
++ * number of Rings and steering based on QoS with
++ * equal priority.
++ */
+ switch (config->rx_ring_num) {
+ case 1:
++ val64 = 0x0;
++ writeq(val64, &bar0->rx_w_round_robin_0);
++ writeq(val64, &bar0->rx_w_round_robin_1);
++ writeq(val64, &bar0->rx_w_round_robin_2);
++ writeq(val64, &bar0->rx_w_round_robin_3);
++ writeq(val64, &bar0->rx_w_round_robin_4);
++
+ val64 = 0x8080808080808080ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 2:
+- val64 = 0x0000010000010000ULL;
++ val64 = 0x0001000100010001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+- val64 = 0x0100000100000100ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+- val64 = 0x0001000001000001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+- val64 = 0x0000010000010000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+- val64 = 0x0100000000000000ULL;
++ val64 = 0x0001000100000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
- static void ixgb_get_bus_info(struct ixgb_hw *hw);
+ val64 = 0x8080808040404040ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 3:
+- val64 = 0x0001000102000001ULL;
++ val64 = 0x0001020001020001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+- val64 = 0x0001020000010001ULL;
++ val64 = 0x0200010200010200ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+- val64 = 0x0200000100010200ULL;
++ val64 = 0x0102000102000102ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+- val64 = 0x0001000102000001ULL;
++ val64 = 0x0001020001020001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+- val64 = 0x0001020000000000ULL;
++ val64 = 0x0200010200000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
--static boolean_t ixgb_link_reset(struct ixgb_hw *hw);
-+static bool ixgb_link_reset(struct ixgb_hw *hw);
+ val64 = 0x8080804040402020ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 4:
+- val64 = 0x0001020300010200ULL;
++ val64 = 0x0001020300010203ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+- val64 = 0x0100000102030001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+- val64 = 0x0200010000010203ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+- val64 = 0x0001020001000001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+- val64 = 0x0203000100000000ULL;
++ val64 = 0x0001020300000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
- static void ixgb_optics_reset(struct ixgb_hw *hw);
+ val64 = 0x8080404020201010ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 5:
+- val64 = 0x0001000203000102ULL;
++ val64 = 0x0001020304000102ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+- val64 = 0x0001020001030004ULL;
++ val64 = 0x0304000102030400ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+- val64 = 0x0001000203000102ULL;
++ val64 = 0x0102030400010203ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+- val64 = 0x0001020001030004ULL;
++ val64 = 0x0400010203040001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+- val64 = 0x0001000000000000ULL;
++ val64 = 0x0203040000000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
-@@ -55,18 +55,18 @@ static void ixgb_clear_vfta(struct ixgb_hw *hw);
+ val64 = 0x8080404020201008ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 6:
+- val64 = 0x0001020304000102ULL;
++ val64 = 0x0001020304050001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+- val64 = 0x0304050001020001ULL;
++ val64 = 0x0203040500010203ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+- val64 = 0x0203000100000102ULL;
++ val64 = 0x0405000102030405ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+- val64 = 0x0304000102030405ULL;
++ val64 = 0x0001020304050001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+- val64 = 0x0001000200000000ULL;
++ val64 = 0x0203040500000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
- static void ixgb_init_rx_addrs(struct ixgb_hw *hw);
+ val64 = 0x8080404020100804ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 7:
+- val64 = 0x0001020001020300ULL;
++ val64 = 0x0001020304050600ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+- val64 = 0x0102030400010203ULL;
++ val64 = 0x0102030405060001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+- val64 = 0x0405060001020001ULL;
++ val64 = 0x0203040506000102ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+- val64 = 0x0304050000010200ULL;
++ val64 = 0x0304050600010203ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+- val64 = 0x0102030000000000ULL;
++ val64 = 0x0405060000000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
--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);
+ val64 = 0x8080402010080402ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 8:
+- val64 = 0x0001020300040105ULL;
++ val64 = 0x0001020304050607ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+- val64 = 0x0200030106000204ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+- val64 = 0x0103000502010007ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+- val64 = 0x0304010002060500ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+- val64 = 0x0103020400000000ULL;
++ val64 = 0x0001020300000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
--static boolean_t ixgb_setup_fc(struct ixgb_hw *hw);
-+static bool ixgb_setup_fc(struct ixgb_hw *hw);
+ val64 = 0x8040201008040201ULL;
+@@ -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);
+@@ -2394,8 +2499,7 @@ static void stop_nic(struct s2io_nic *nic)
--static boolean_t mac_addr_valid(uint8_t *mac_addr);
-+static bool mac_addr_valid(u8 *mac_addr);
+ /**
+ * fill_rx_buffers - Allocates the Rx side skbs
+- * @nic: device private variable
+- * @ring_no: ring number
++ * @ring_info: per ring structure
+ * Description:
+ * The function allocates Rx side skbs and puts the physical
+ * address of these buffers into the RxD buffer pointers, so that the NIC
+@@ -2413,112 +2517,94 @@ static void stop_nic(struct s2io_nic *nic)
+ * SUCCESS on success or an appropriate -ve value on failure.
+ */
--static uint32_t ixgb_mac_reset(struct ixgb_hw *hw)
-+static u32 ixgb_mac_reset(struct ixgb_hw *hw)
+-static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
++static int fill_rx_buffers(struct ring_info *ring)
{
-- uint32_t ctrl_reg;
-+ u32 ctrl_reg;
+- struct net_device *dev = nic->dev;
+ struct sk_buff *skb;
+ struct RxD_t *rxdp;
+- int off, off1, size, block_no, block_no1;
++ int off, size, block_no, block_no1;
+ u32 alloc_tab = 0;
+ u32 alloc_cnt;
+- struct mac_info *mac_control;
+- 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;
++ int rxd_index = 0;
+ struct RxD1 *rxdp1;
+ struct RxD3 *rxdp3;
+- struct swStat *stats = &nic->mac_control.stats_info->sw_stat;
++ struct swStat *stats = &ring->nic->mac_control.stats_info->sw_stat;
+
+- mac_control = &nic->mac_control;
+- config = &nic->config;
+- alloc_cnt = mac_control->rings[ring_no].pkt_cnt -
+- atomic_read(&nic->rx_bufs_left[ring_no]);
++ alloc_cnt = ring->pkt_cnt - ring->rx_bufs_left;
+
+- block_no1 = mac_control->rings[ring_no].rx_curr_get_info.block_index;
+- off1 = mac_control->rings[ring_no].rx_curr_get_info.offset;
++ block_no1 = ring->rx_curr_get_info.block_index;
+ while (alloc_tab < alloc_cnt) {
+- block_no = mac_control->rings[ring_no].rx_curr_put_info.
+- block_index;
+- off = mac_control->rings[ring_no].rx_curr_put_info.offset;
++ block_no = ring->rx_curr_put_info.block_index;
+
+- rxdp = mac_control->rings[ring_no].
+- rx_blocks[block_no].rxds[off].virt_addr;
++ off = ring->rx_curr_put_info.offset;
+
+- if ((block_no == block_no1) && (off == off1) &&
+- (rxdp->Host_Control)) {
++ rxdp = ring->rx_blocks[block_no].rxds[off].virt_addr;
++
++ rxd_index = off + 1;
++ if (block_no)
++ rxd_index += (block_no * ring->rxd_count);
++
++ if ((block_no == block_no1) &&
++ (off == ring->rx_curr_get_info.offset) &&
++ (rxdp->Host_Control)) {
+ DBG_PRINT(INTR_DBG, "%s: Get and Put",
+- dev->name);
++ ring->dev->name);
+ DBG_PRINT(INTR_DBG, " info equated\n");
+ goto end;
+ }
+- if (off && (off == rxd_count[nic->rxd_mode])) {
+- mac_control->rings[ring_no].rx_curr_put_info.
+- block_index++;
+- if (mac_control->rings[ring_no].rx_curr_put_info.
+- block_index == mac_control->rings[ring_no].
+- block_count)
+- mac_control->rings[ring_no].rx_curr_put_info.
+- block_index = 0;
+- block_no = mac_control->rings[ring_no].
+- rx_curr_put_info.block_index;
+- if (off == rxd_count[nic->rxd_mode])
+- off = 0;
+- mac_control->rings[ring_no].rx_curr_put_info.
+- offset = off;
+- rxdp = mac_control->rings[ring_no].
+- rx_blocks[block_no].block_virt_addr;
++ if (off && (off == ring->rxd_count)) {
++ ring->rx_curr_put_info.block_index++;
++ if (ring->rx_curr_put_info.block_index ==
++ ring->block_count)
++ ring->rx_curr_put_info.block_index = 0;
++ block_no = ring->rx_curr_put_info.block_index;
++ off = 0;
++ ring->rx_curr_put_info.offset = off;
++ rxdp = ring->rx_blocks[block_no].block_virt_addr;
+ 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;
++ ring->dev->name, rxdp);
++
+ }
++
+ if ((rxdp->Control_1 & RXD_OWN_XENA) &&
+- ((nic->rxd_mode == RXD_MODE_3B) &&
++ ((ring->rxd_mode == RXD_MODE_3B) &&
+ (rxdp->Control_2 & s2BIT(0)))) {
+- mac_control->rings[ring_no].rx_curr_put_info.
+- offset = off;
++ ring->rx_curr_put_info.offset = off;
+ goto end;
+ }
+ /* calculate size of skb based on ring mode */
+- size = dev->mtu + HEADER_ETHERNET_II_802_3_SIZE +
++ size = ring->mtu + HEADER_ETHERNET_II_802_3_SIZE +
+ HEADER_802_2_SIZE + HEADER_SNAP_SIZE;
+- if (nic->rxd_mode == RXD_MODE_1)
++ if (ring->rxd_mode == RXD_MODE_1)
+ size += NET_IP_ALIGN;
+ else
+- size = dev->mtu + ALIGN_SIZE + BUF0_LEN + 4;
++ size = ring->mtu + ALIGN_SIZE + BUF0_LEN + 4;
- 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;
+ /* allocate skb */
+ skb = dev_alloc_skb(size);
+ if(!skb) {
+- DBG_PRINT(INFO_DBG, "%s: Out of ", dev->name);
++ DBG_PRINT(INFO_DBG, "%s: Out of ", ring->dev->name);
+ DBG_PRINT(INFO_DBG, "memory to allocate SKBs\n");
+ if (first_rxdp) {
+ wmb();
+ first_rxdp->Control_1 |= RXD_OWN_XENA;
+ }
+- nic->mac_control.stats_info->sw_stat. \
+- mem_alloc_fail_cnt++;
++ stats->mem_alloc_fail_cnt++;
++
+ return -ENOMEM ;
+ }
+- nic->mac_control.stats_info->sw_stat.mem_allocated
+- += skb->truesize;
+- if (nic->rxd_mode == RXD_MODE_1) {
++ stats->mem_allocated += skb->truesize;
++
++ if (ring->rxd_mode == RXD_MODE_1) {
+ /* 1 buffer mode - normal operation mode */
+ rxdp1 = (struct RxD1*)rxdp;
+ memset(rxdp, 0, sizeof(struct RxD1));
+ skb_reserve(skb, NET_IP_ALIGN);
+ rxdp1->Buffer0_ptr = pci_map_single
+- (nic->pdev, skb->data, size - NET_IP_ALIGN,
++ (ring->pdev, skb->data, size - NET_IP_ALIGN,
+ PCI_DMA_FROMDEVICE);
+ if( (rxdp1->Buffer0_ptr == 0) ||
+ (rxdp1->Buffer0_ptr ==
+@@ -2527,8 +2613,8 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
+
+ rxdp->Control_2 =
+ SET_BUFFER0_SIZE_1(size - NET_IP_ALIGN);
+-
+- } else if (nic->rxd_mode == RXD_MODE_3B) {
++ rxdp->Host_Control = (unsigned long) (skb);
++ } else if (ring->rxd_mode == RXD_MODE_3B) {
+ /*
+ * 2 buffer mode -
+ * 2 buffer mode provides 128
+@@ -2544,7 +2630,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
+ rxdp3->Buffer0_ptr = Buffer0_ptr;
+ rxdp3->Buffer1_ptr = Buffer1_ptr;
+
+- ba = &mac_control->rings[ring_no].ba[block_no][off];
++ ba = &ring->ba[block_no][off];
+ skb_reserve(skb, BUF0_LEN);
+ tmp = (u64)(unsigned long) skb->data;
+ tmp += ALIGN_SIZE;
+@@ -2554,10 +2640,10 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
+
+ if (!(rxdp3->Buffer0_ptr))
+ rxdp3->Buffer0_ptr =
+- pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN,
+- PCI_DMA_FROMDEVICE);
++ pci_map_single(ring->pdev, ba->ba_0,
++ BUF0_LEN, PCI_DMA_FROMDEVICE);
+ else
+- pci_dma_sync_single_for_device(nic->pdev,
++ pci_dma_sync_single_for_device(ring->pdev,
+ (dma_addr_t) rxdp3->Buffer0_ptr,
+ BUF0_LEN, PCI_DMA_FROMDEVICE);
+ if( (rxdp3->Buffer0_ptr == 0) ||
+@@ -2565,7 +2651,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
+ goto pci_map_failed;
+
+ rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN);
+- if (nic->rxd_mode == RXD_MODE_3B) {
++ if (ring->rxd_mode == RXD_MODE_3B) {
+ /* Two buffer mode */
- DEBUGFUNC("ixgb_adapter_stop");
+ /*
+@@ -2573,39 +2659,42 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
+ * L4 payload
+ */
+ rxdp3->Buffer2_ptr = pci_map_single
+- (nic->pdev, skb->data, dev->mtu + 4,
++ (ring->pdev, skb->data, ring->mtu + 4,
+ PCI_DMA_FROMDEVICE);
+
+ if( (rxdp3->Buffer2_ptr == 0) ||
+ (rxdp3->Buffer2_ptr == DMA_ERROR_CODE))
+ goto pci_map_failed;
+
+- rxdp3->Buffer1_ptr =
+- pci_map_single(nic->pdev,
++ if (!rxdp3->Buffer1_ptr)
++ rxdp3->Buffer1_ptr =
++ pci_map_single(ring->pdev,
+ ba->ba_1, BUF1_LEN,
+ PCI_DMA_FROMDEVICE);
++
+ if( (rxdp3->Buffer1_ptr == 0) ||
+ (rxdp3->Buffer1_ptr == DMA_ERROR_CODE)) {
+ pci_unmap_single
+- (nic->pdev,
+- (dma_addr_t)rxdp3->Buffer2_ptr,
+- dev->mtu + 4,
++ (ring->pdev,
++ (dma_addr_t)(unsigned long)
++ skb->data,
++ ring->mtu + 4,
+ PCI_DMA_FROMDEVICE);
+ goto pci_map_failed;
+ }
+ rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1);
+ rxdp->Control_2 |= SET_BUFFER2_SIZE_3
+- (dev->mtu + 4);
++ (ring->mtu + 4);
+ }
+ rxdp->Control_2 |= s2BIT(0);
++ rxdp->Host_Control = (unsigned long) (skb);
+ }
+- rxdp->Host_Control = (unsigned long) (skb);
+ if (alloc_tab & ((1 << rxsync_frequency) - 1))
+ rxdp->Control_1 |= RXD_OWN_XENA;
+ off++;
+- if (off == (rxd_count[nic->rxd_mode] + 1))
++ if (off == (ring->rxd_count + 1))
+ off = 0;
+- mac_control->rings[ring_no].rx_curr_put_info.offset = off;
++ ring->rx_curr_put_info.offset = off;
+
+ rxdp->Control_2 |= SET_RXD_MARKER;
+ if (!(alloc_tab & ((1 << rxsync_frequency) - 1))) {
+@@ -2615,7 +2704,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
+ }
+ first_rxdp = rxdp;
+ }
+- atomic_inc(&nic->rx_bufs_left[ring_no]);
++ ring->rx_bufs_left += 1;
+ alloc_tab++;
+ }
-@@ -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;
+@@ -2687,7 +2776,7 @@ static void free_rxd_blk(struct s2io_nic *sp, int ring_no, int blk)
+ }
+ sp->mac_control.stats_info->sw_stat.mem_freed += skb->truesize;
+ dev_kfree_skb(skb);
+- atomic_dec(&sp->rx_bufs_left[ring_no]);
++ mac_control->rings[ring_no].rx_bufs_left -= 1;
}
+ }
- /* Set the Adapter Stopped flag so other driver functions stop
- * touching the Hardware.
- */
-- hw->adapter_stopped = TRUE;
-+ hw->adapter_stopped = true;
+@@ -2718,7 +2807,7 @@ static void free_rx_buffers(struct s2io_nic *sp)
+ mac_control->rings[i].rx_curr_get_info.block_index = 0;
+ mac_control->rings[i].rx_curr_put_info.offset = 0;
+ mac_control->rings[i].rx_curr_get_info.offset = 0;
+- atomic_set(&sp->rx_bufs_left[i], 0);
++ mac_control->rings[i].rx_bufs_left = 0;
+ DBG_PRINT(INIT_DBG, "%s:Freed 0x%x Rx Buffers on ring%d\n",
+ dev->name, buf_cnt, i);
+ }
+@@ -2768,7 +2857,7 @@ static int s2io_poll(struct napi_struct *napi, int budget)
+ netif_rx_complete(dev, napi);
+
+ for (i = 0; i < config->rx_ring_num; i++) {
+- if (fill_rx_buffers(nic, i) == -ENOMEM) {
++ if (fill_rx_buffers(&mac_control->rings[i]) == -ENOMEM) {
+ DBG_PRINT(INFO_DBG, "%s:Out of memory", dev->name);
+ DBG_PRINT(INFO_DBG, " in Rx Poll!!\n");
+ break;
+@@ -2781,7 +2870,7 @@ static int s2io_poll(struct napi_struct *napi, int budget)
- /* 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;
+ no_rx:
+ for (i = 0; i < config->rx_ring_num; i++) {
+- if (fill_rx_buffers(nic, i) == -ENOMEM) {
++ if (fill_rx_buffers(&mac_control->rings[i]) == -ENOMEM) {
+ DBG_PRINT(INFO_DBG, "%s:Out of memory", dev->name);
+ DBG_PRINT(INFO_DBG, " in Rx Poll!!\n");
+ break;
+@@ -2832,7 +2921,7 @@ static void s2io_netpoll(struct net_device *dev)
+ rx_intr_handler(&mac_control->rings[i]);
- 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)
+ for (i = 0; i < config->rx_ring_num; i++) {
+- if (fill_rx_buffers(nic, i) == -ENOMEM) {
++ if (fill_rx_buffers(&mac_control->rings[i]) == -ENOMEM) {
+ DBG_PRINT(INFO_DBG, "%s:Out of memory", dev->name);
+ DBG_PRINT(INFO_DBG, " in Rx Netpoll!!\n");
+ break;
+@@ -2857,9 +2946,7 @@ static void s2io_netpoll(struct net_device *dev)
+ */
+ static void rx_intr_handler(struct ring_info *ring_data)
{
-- 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);
+- 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 +2955,11 @@ static void rx_intr_handler(struct ring_info *ring_data)
+ struct RxD1* rxdp1;
+ struct RxD3* rxdp3;
-- if (ixgb_get_eeprom_data(hw) == FALSE) {
-- return(FALSE);
-- }
-+ if (!ixgb_get_eeprom_data(hw))
-+ return false;
+- 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;
- /* 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);
+ while (RXD_IS_UP2DT(rxdp)) {
+ /*
+@@ -2889,34 +2968,34 @@ static void rx_intr_handler(struct ring_info *ring_data)
+ */
+ if ((get_block == put_block) &&
+ (get_info.offset + 1) == put_info.offset) {
+- DBG_PRINT(INTR_DBG, "%s: Ring Full\n",dev->name);
++ DBG_PRINT(INTR_DBG, "%s: Ring Full\n",
++ ring_data->dev->name);
+ break;
+ }
+ skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control);
+ if (skb == NULL) {
+ DBG_PRINT(ERR_DBG, "%s: The skb is ",
+- dev->name);
++ ring_data->dev->name);
+ DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
+- spin_unlock(&nic->rx_lock);
+ return;
+ }
+- if (nic->rxd_mode == RXD_MODE_1) {
++ if (ring_data->rxd_mode == RXD_MODE_1) {
+ rxdp1 = (struct RxD1*)rxdp;
+- pci_unmap_single(nic->pdev, (dma_addr_t)
++ pci_unmap_single(ring_data->pdev, (dma_addr_t)
+ rxdp1->Buffer0_ptr,
+- dev->mtu +
++ ring_data->mtu +
+ HEADER_ETHERNET_II_802_3_SIZE +
+ HEADER_802_2_SIZE +
+ HEADER_SNAP_SIZE,
+ PCI_DMA_FROMDEVICE);
+- } else if (nic->rxd_mode == RXD_MODE_3B) {
++ } else if (ring_data->rxd_mode == RXD_MODE_3B) {
+ rxdp3 = (struct RxD3*)rxdp;
+- pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t)
++ pci_dma_sync_single_for_cpu(ring_data->pdev, (dma_addr_t)
+ rxdp3->Buffer0_ptr,
+ BUF0_LEN, PCI_DMA_FROMDEVICE);
+- pci_unmap_single(nic->pdev, (dma_addr_t)
++ pci_unmap_single(ring_data->pdev, (dma_addr_t)
+ rxdp3->Buffer2_ptr,
+- dev->mtu + 4,
++ ring_data->mtu + 4,
+ PCI_DMA_FROMDEVICE);
+ }
+ prefetch(skb->data);
+@@ -2925,7 +3004,7 @@ static void rx_intr_handler(struct ring_info *ring_data)
+ ring_data->rx_curr_get_info.offset = get_info.offset;
+ rxdp = ring_data->rx_blocks[get_block].
+ rxds[get_info.offset].virt_addr;
+- if (get_info.offset == rxd_count[nic->rxd_mode]) {
++ if (get_info.offset == rxd_count[ring_data->rxd_mode]) {
+ get_info.offset = 0;
+ ring_data->rx_curr_get_info.offset = get_info.offset;
+ get_block++;
+@@ -2935,26 +3014,26 @@ static void rx_intr_handler(struct ring_info *ring_data)
+ rxdp = ring_data->rx_blocks[get_block].block_virt_addr;
+ }
+
+- nic->pkts_to_process -= 1;
+- if ((napi) && (!nic->pkts_to_process))
+- break;
++ if(ring_data->nic->config.napi){
++ ring_data->nic->pkts_to_process -= 1;
++ if (!ring_data->nic->pkts_to_process)
++ break;
++ }
+ pkt_cnt++;
+ if ((indicate_max_pkts) && (pkt_cnt > indicate_max_pkts))
+ break;
}
+- if (nic->lro) {
++ if (ring_data->lro) {
+ /* Clear all LRO sessions before exiting */
+ for (i=0; i<MAX_LRO_SESSIONS; i++) {
+- struct lro *lro = &nic->lro0_n[i];
++ struct lro *lro = &ring_data->lro0_n[i];
+ if (lro->in_use) {
+- update_L3L4_header(nic, lro);
+- queue_rx_frame(lro->parent);
++ update_L3L4_header(ring_data->nic, lro);
++ queue_rx_frame(lro->parent, lro->vlan_tag);
+ clear_lro_session(lro);
+ }
+ }
+ }
+-
+- spin_unlock(&nic->rx_lock);
+ }
- /* 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)
+ /**
+@@ -2972,10 +3051,10 @@ static void rx_intr_handler(struct ring_info *ring_data)
+ static void tx_intr_handler(struct fifo_info *fifo_data)
{
-- uint32_t i;
-+ u32 i;
-
- DEBUGFUNC("ixgb_init_rx_addrs");
+ 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;
-@@ -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 */
+@@ -3036,6 +3115,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
+ DBG_PRINT(ERR_DBG, "in Tx Free Intr\n");
+ return;
+ }
++ pkt_cnt++;
- DEBUGFUNC("ixgb_mc_addr_list_update");
+ /* Updating the statistics block */
+ nic->stats.tx_bytes += skb->len;
+@@ -3051,8 +3131,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
+ get_info.offset;
+ }
-@@ -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;
+- if (netif_queue_stopped(dev))
+- netif_wake_queue(dev);
++ s2io_wake_tx_queue(fifo_data, pkt_cnt, nic->config.multiq);
- DEBUGFUNC("ixgb_hash_mc_addr");
+ spin_unlock_irqrestore(&fifo_data->tx_lock, flags);
+ }
+@@ -3933,8 +4012,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;
-@@ -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;
+ hw_init_failed:
+@@ -3979,8 +4057,7 @@ static int s2io_close(struct net_device *dev)
+ if (!is_s2io_card_up(sp))
+ return 0;
- /* 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;
+- 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 +4065,6 @@ static int s2io_close(struct net_device *dev)
+ do_s2io_delete_unicast_mc(sp, tmp64);
+ }
- DEBUGFUNC("ixgb_rar_set");
+- /* Reset card, kill tasklet and free Tx and Rx buffers. */
+ s2io_card_down(sp);
- /* 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));
+ return 0;
+@@ -4016,11 +4092,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;
-- rar_high = ((uint32_t) addr[4] |
-- ((uint32_t)addr[5] << 8) |
-+ rar_high = ((u32) addr[4] |
-+ ((u32)addr[5] << 8) |
- IXGB_RAH_AV);
+ mac_control = &sp->mac_control;
+@@ -4042,15 +4119,67 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+ }
- 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;
+ 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;
++ }
+ }
- 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
- *****************************************************************************/
+- 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 +4189,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 +4208,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 +4226,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 +4298,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 +4310,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);
+@@ -4195,31 +4327,11 @@ s2io_alarm_handle(unsigned long data)
+ mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
+ }
--static boolean_t
-+static bool
- ixgb_setup_fc(struct ixgb_hw *hw)
+-static int s2io_chk_rx_buffers(struct s2io_nic *sp, int rng_n)
++static int s2io_chk_rx_buffers(struct ring_info *ring)
{
-- 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");
+- 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(ring) == -ENOMEM) {
++ DBG_PRINT(INFO_DBG, "%s:Out of memory", ring->dev->name);
++ DBG_PRINT(INFO_DBG, " in Rx Intr!!\n");
+ }
+ return 0;
+ }
+@@ -4233,7 +4345,7 @@ static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id)
+ return IRQ_HANDLED;
-@@ -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;
+ rx_intr_handler(ring);
+- s2io_chk_rx_buffers(sp, ring->ring_no);
++ s2io_chk_rx_buffers(ring);
- 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);
+ return IRQ_HANDLED;
}
+@@ -4590,7 +4702,7 @@ static void s2io_handle_errors(void * dev_id)
+ return;
- /******************************************************************************
-@@ -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);
+ reset:
+- netif_stop_queue(dev);
++ s2io_stop_all_tx_queue(sp);
+ schedule_work(&sp->rst_timer_task);
+ sw_stat->soft_reset_cnt++;
+ return;
+@@ -4691,7 +4803,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
+ */
+ if (!config->napi) {
+ for (i = 0; i < config->rx_ring_num; i++)
+- s2io_chk_rx_buffers(sp, i);
++ s2io_chk_rx_buffers(&mac_control->rings[i]);
+ }
+ writeq(sp->general_int_mask, &bar0->general_int_mask);
+ readl(&bar0->general_int_status);
+@@ -4748,6 +4860,7 @@ static struct net_device_stats *s2io_get_stats(struct net_device *dev)
+ struct s2io_nic *sp = dev->priv;
+ struct mac_info *mac_control;
+ struct config_param *config;
++ int i;
- /* 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;
+ mac_control = &sp->mac_control;
+@@ -4767,6 +4880,13 @@ static struct net_device_stats *s2io_get_stats(struct net_device *dev)
+ sp->stats.rx_length_errors =
+ le64_to_cpu(mac_control->stats_info->rmac_long_frms);
- DEBUGFUNC("ixgb_check_for_link");
++ /* collect per-ring rx_packets and rx_bytes */
++ sp->stats.rx_packets = sp->stats.rx_bytes = 0;
++ for (i = 0; i < config->rx_ring_num; i++) {
++ sp->stats.rx_packets += mac_control->rings[i].rx_packets;
++ sp->stats.rx_bytes += mac_control->rings[i].rx_bytes;
++ }
++
+ return (&sp->stats);
+ }
-@@ -950,7 +949,7 @@ ixgb_check_for_link(struct ixgb_hw *hw)
+@@ -6577,16 +6697,15 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
- 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;
+ 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 +6717,6 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
+ }
- 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;
+ /**
+- * 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 +6770,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);
+ }
}
- 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)
+ val64 = readq(&bar0->adapter_control);
+@@ -6921,11 +6997,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 +7015,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 +7065,6 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
{
-- volatile uint32_t temp_reg;
-+ volatile u32 temp_reg;
+ 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 +7089,6 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
- DEBUGFUNC("ixgb_clear_hw_cntrs");
+ s2io_rem_isr(sp);
-@@ -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);
+- /* 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 +7123,7 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
+ free_tx_buffers(sp);
- /* 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);
+ /* Free all Rx buffers */
+- spin_lock_irqsave(&sp->rx_lock, flags);
+ free_rx_buffers(sp);
+- spin_unlock_irqrestore(&sp->rx_lock, flags);
- /* 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;
+ clear_bit(__S2IO_STATE_LINK_TASK, &(sp->state));
+ }
+@@ -7089,7 +7159,9 @@ static int s2io_card_up(struct s2io_nic * sp)
+ config = &sp->config;
- status_reg = IXGB_READ_REG(hw, STATUS);
+ for (i = 0; i < config->rx_ring_num; i++) {
+- if ((ret = fill_rx_buffers(sp, i))) {
++ mac_control->rings[i].mtu = dev->mtu;
++ ret = fill_rx_buffers(&mac_control->rings[i]);
++ if (ret) {
+ DBG_PRINT(ERR_DBG, "%s: Out of memory in Open\n",
+ dev->name);
+ s2io_reset(sp);
+@@ -7097,7 +7169,7 @@ static int s2io_card_up(struct s2io_nic * sp)
+ return -ENOMEM;
+ }
+ DBG_PRINT(INFO_DBG, "Buf in ring:%d is %d:\n", i,
+- atomic_read(&sp->rx_bufs_left[i]));
++ mac_control->rings[i].rx_bufs_left);
+ }
-@@ -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");
+ /* Initialise napi */
+@@ -7142,9 +7214,6 @@ static int s2io_card_up(struct s2io_nic * sp)
- /* 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;
+ 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 +7253,7 @@ static void s2io_restart_nic(struct work_struct *work)
+ DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
+ dev->name);
}
- /* 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;
+- 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:
+@@ -7235,7 +7304,7 @@ static void s2io_tx_watchdog(struct net_device *dev)
+ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
+ {
+ struct s2io_nic *sp = ring_data->nic;
+- struct net_device *dev = (struct net_device *) sp->dev;
++ struct net_device *dev = (struct net_device *) ring_data->dev;
+ struct sk_buff *skb = (struct sk_buff *)
+ ((unsigned long) rxdp->Host_Control);
+ int ring_no = ring_data->ring_no;
+@@ -7312,19 +7381,19 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
+ sp->mac_control.stats_info->sw_stat.mem_freed
+ += skb->truesize;
+ dev_kfree_skb(skb);
+- atomic_dec(&sp->rx_bufs_left[ring_no]);
++ ring_data->rx_bufs_left -= 1;
+ rxdp->Host_Control = 0;
+ return 0;
+ }
}
- return (is_valid);
+
+ /* Updating statistics */
+- sp->stats.rx_packets++;
++ ring_data->rx_packets++;
+ rxdp->Host_Control = 0;
+ if (sp->rxd_mode == RXD_MODE_1) {
+ int len = RXD_GET_BUFFER0_SIZE_1(rxdp->Control_2);
+
+- sp->stats.rx_bytes += len;
++ ring_data->rx_bytes += len;
+ skb_put(skb, len);
+
+ } else if (sp->rxd_mode == RXD_MODE_3B) {
+@@ -7335,13 +7404,13 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
+ unsigned char *buff = skb_push(skb, buf0_len);
+
+ struct buffAdd *ba = &ring_data->ba[get_block][get_off];
+- sp->stats.rx_bytes += buf0_len + buf2_len;
++ ring_data->rx_bytes += buf0_len + buf2_len;
+ memcpy(buff, ba->ba_0, buf0_len);
+ skb_put(skb, buf2_len);
+ }
+
+- if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && ((!sp->lro) ||
+- (sp->lro && (!(rxdp->Control_1 & RXD_FRAME_IP_FRAG)))) &&
++ if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && ((!ring_data->lro) ||
++ (ring_data->lro && (!(rxdp->Control_1 & RXD_FRAME_IP_FRAG)))) &&
+ (sp->rx_csum)) {
+ l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1);
+ l4_csum = RXD_GET_L4_CKSUM(rxdp->Control_1);
+@@ -7352,14 +7421,14 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
+ * a flag in the RxD.
+ */
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+- if (sp->lro) {
++ if (ring_data->lro) {
+ u32 tcp_len;
+ u8 *tcp;
+ int ret = 0;
+
+- ret = s2io_club_tcp_session(skb->data, &tcp,
+- &tcp_len, &lro,
+- rxdp, sp);
++ ret = s2io_club_tcp_session(ring_data,
++ skb->data, &tcp, &tcp_len, &lro,
++ rxdp, sp);
+ switch (ret) {
+ case 3: /* Begin anew */
+ lro->parent = skb;
+@@ -7374,7 +7443,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 +7455,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,34 +7482,15 @@ 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]);
++ sp->mac_control.rings[ring_no].rx_bufs_left -= 1;
+ return SUCCESS;
}
-@@ -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);
+@@ -7463,6 +7515,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 +7528,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,26 +7565,56 @@ static void s2io_init_pci(struct s2io_nic * sp)
+ pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
+ }
- } while (!link_status && --lrst_retries);
-@@ -1225,7 +1224,7 @@ static void
- ixgb_optics_reset(struct ixgb_hw *hw)
+-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 (hw->phy_type == ixgb_phy_type_txn17401) {
-- uint16_t mdio_reg;
-+ u16 mdio_reg;
+ 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");
+ }
- 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;
- };
+- if ( rx_ring_num > 8) {
+- DBG_PRINT(ERR_DBG, "s2io: Requested number of Rx rings not "
++#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 > MAX_RX_RINGS) {
++ DBG_PRINT(ERR_DBG, "s2io: Requested number of rx rings not "
+ "supported\n");
+- DBG_PRINT(ERR_DBG, "s2io: Default to 8 Rx rings\n");
+- rx_ring_num = 8;
++ DBG_PRINT(ERR_DBG, "s2io: Default to %d rx rings\n",
++ MAX_RX_RINGS);
++ rx_ring_num = MAX_RX_RINGS;
+ }
++
+ if (*dev_intr_type != INTA)
+ napi = 0;
-@@ -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;
- };
+@@ -7616,9 +7700,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);
-@@ -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 */
+- if ((ret = s2io_verify_parm(pdev, &dev_intr_type)))
++ ret = s2io_verify_parm(pdev, &dev_intr_type, &dev_multiq);
++ if (ret)
+ return ret;
- 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;
- };
+ if ((ret = pci_enable_device(pdev))) {
+@@ -7649,7 +7735,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 +7788,45 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ config = &sp->config;
-@@ -637,33 +637,33 @@ struct ixgb_context_desc {
+ config->napi = napi;
++ config->tx_steering_type = tx_steering_type;
- /* 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];
- };
+ /* 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;
+ }
- /*
- * 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))
+ /* 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];
++
- /*
- * 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)))
+ config->tx_intr_type = TXD_INT_TYPE_UTILZ;
+ for (i = 0; i < config->tx_fifo_num; i++) {
+@@ -7724,10 +7842,15 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
- /* 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 */
- };
+ /* Rx side parameters. */
+ config->rx_ring_num = rx_ring_num;
+- for (i = 0; i < MAX_RX_RINGS; i++) {
++ for (i = 0; i < config->rx_ring_num; i++) {
+ config->rx_cfg[i].num_rxd = rx_ring_sz[i] *
+ (rxd_count[sp->rxd_mode] + 1);
+ config->rx_cfg[i].ring_priority = i;
++ mac_control->rings[i].rx_bufs_left = 0;
++ mac_control->rings[i].rxd_mode = sp->rxd_mode;
++ mac_control->rings[i].rxd_count = rxd_count[sp->rxd_mode];
++ mac_control->rings[i].pdev = sp->pdev;
++ mac_control->rings[i].dev = sp->dev;
+ }
+
+ for (i = 0; i < rx_ring_num; i++) {
+@@ -7742,10 +7865,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ mac_control->mc_pause_threshold_q4q7 = mc_pause_threshold_q4q7;
+
+
+- /* Initialize Ring buffer parameters. */
+- for (i = 0; i < config->rx_ring_num; i++)
+- atomic_set(&sp->rx_bufs_left[i], 0);
+-
+ /* initialize the shared memory used by the NIC and the host */
+ if (init_shared_mem(sp)) {
+ DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n",
+@@ -7793,6 +7912,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;
-@@ -685,139 +685,139 @@ struct ixgb_bus {
- };
+ /*
+ * will use eth_mac_addr() for dev->set_mac_address
+@@ -7813,7 +7933,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 +8019,15 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ s2io_reset(sp);
- 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;
- };
+ /*
+- * Initialize the tasklet status and link state flags
++ * Initialize link state flags
+ * and the card state parameter
+ */
+- sp->tasklet_status = 0;
+ sp->state = 0;
- /* 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;
- };
+ /* Initialize spinlocks */
+ for (i = 0; i < sp->config.tx_fifo_num; i++)
+ spin_lock_init(&mac_control->fifos[i].tx_lock);
- /* 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);
+- 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 +8080,13 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
- extern void ixgb_rar_set(struct ixgb_hw *hw,
-- uint8_t *addr,
-- uint32_t index);
-+ u8 *addr,
-+ u32 index);
+ 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);
++
++ DBG_PRINT(ERR_DBG, "%s: Using %d Rx ring(s)\n", dev->name,
++ sp->config.rx_ring_num);
++
+ switch(sp->config.intr_type) {
+ case INTA:
+ DBG_PRINT(ERR_DBG, "%s: Interrupt type INTA\n", dev->name);
+@@ -7970,6 +8095,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 +8212,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 +8224,20 @@ static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip,
+ return -1;
+ }
- /* 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);
+- /* 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;
+ }
- /* Vfta functions */
- extern void ixgb_write_vfta(struct ixgb_hw *hw,
-- uint32_t offset,
-- uint32_t value);
-+ u32 offset,
-+ u32 value);
+ *ip = (struct iphdr *)((u8 *)buffer + ip_off);
+@@ -8114,7 +8264,7 @@ static inline int get_l4_pyld_length(struct iphdr *ip, struct tcphdr *tcp)
+ }
- /* 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);
+ 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 +8275,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.
+@@ -8250,25 +8401,27 @@ static int verify_l3_l4_lro_capable(struct lro *l_lro, struct iphdr *ip,
+ }
- /* 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);
+ static int
+-s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,
+- struct RxD_t *rxdp, struct s2io_nic *sp)
++s2io_club_tcp_session(struct ring_info *ring_data, u8 *buffer, u8 **tcp,
++ u32 *tcp_len, struct lro **lro, struct RxD_t *rxdp,
++ struct s2io_nic *sp)
+ {
+ 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;
+- }
- #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 */
++ vlan_tag = RXD_GET_VLAN_TAG(rxdp->Control_2);
+ tcph = (struct tcphdr *)*tcp;
+ *tcp_len = get_l4_pyld_length(ip, tcph);
+ for (i=0; i<MAX_LRO_SESSIONS; i++) {
+- struct lro *l_lro = &sp->lro0_n[i];
++ struct lro *l_lro = &ring_data->lro0_n[i];
+ if (l_lro->in_use) {
+ if (check_for_socket_match(l_lro, ip, tcph))
+ continue;
+@@ -8306,7 +8459,7 @@ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,
+ }
- 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);
+ for (i=0; i<MAX_LRO_SESSIONS; i++) {
+- struct lro *l_lro = &sp->lro0_n[i];
++ struct lro *l_lro = &ring_data->lro0_n[i];
+ if (!(l_lro->in_use)) {
+ *lro = l_lro;
+ ret = 3; /* Begin anew */
+@@ -8324,7 +8477,8 @@ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,
- #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);
+ switch (ret) {
+ case 3:
+- initiate_new_session(*lro, buffer, ip, tcph, *tcp_len);
++ initiate_new_session(*lro, buffer, ip, tcph, *tcp_len,
++ vlan_tag);
+ break;
+ case 2:
+ update_L3L4_header(sp, *lro);
+@@ -8352,15 +8506,25 @@ static void clear_lro_session(struct lro *lro)
+ memset(lro, 0, lro_struct_size);
+ }
- #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)
+-static void queue_rx_frame(struct sk_buff *skb)
++static void queue_rx_frame(struct sk_buff *skb, u16 vlan_tag)
{
-- 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);
- }
+ struct net_device *dev = skb->dev;
++ struct s2io_nic *sp = dev->priv;
- int
-@@ -274,7 +271,7 @@ ixgb_up(struct ixgb_adapter *adapter)
+ 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);
++ }
+ }
- 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);
+ 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..0709eba 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
- if(!(ctrl0 & IXGB_CTRL0_JFE)) {
- ctrl0 |= IXGB_CTRL0_JFE;
-@@ -283,26 +280,30 @@ ixgb_up(struct ixgb_adapter *adapter)
- }
- }
+-#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
++
-- mod_timer(&adapter->watchdog_timer, jiffies);
-+ clear_bit(__IXGB_DOWN, &adapter->flags);
+ #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},
+ };
- #ifdef CONFIG_IXGB_NAPI
- napi_enable(&adapter->napi);
- #endif
- ixgb_irq_enable(adapter);
++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 */
-+ mod_timer(&adapter->watchdog_timer, jiffies);
++ /* 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;
+
- return 0;
- }
+ 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;
+ };
- 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;
+ /* 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)
+@@ -665,11 +678,53 @@ struct rx_block_info {
+ struct rxd_info *rxds;
+ };
-+ /* prevent the interrupt handler from restarting watchdog */
-+ set_bit(__IXGB_DOWN, &adapter->flags);
++/* Data structure to represent a LRO session */
++struct lro {
++ struct sk_buff *parent;
++ struct sk_buff *last_frag;
++ u8 *l2h;
++ struct iphdr *iph;
++ struct tcphdr *tcph;
++ u32 tcp_next_seq;
++ __be32 tcp_ack;
++ int total_len;
++ int frags_len;
++ int sg_num;
++ int in_use;
++ __be16 window;
++ u16 vlan_tag;
++ u32 cur_tsval;
++ __be32 cur_tsecr;
++ u8 saw_ts;
++} ____cacheline_aligned;
+
- #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);
+ /* Ring specific structure */
+ struct ring_info {
+ /* The ring number */
+ int ring_no;
+
++ /* per-ring buffer counter */
++ u32 rx_bufs_left;
++
++ #define MAX_LRO_SESSIONS 32
++ struct lro lro0_n[MAX_LRO_SESSIONS];
++ u8 lro;
++
++ /* copy of sp->rxd_mode flag */
++ int rxd_mode;
++
++ /* Number of rxds per block for the rxd_mode */
++ int rxd_count;
++
++ /* copy of sp pointer */
++ struct s2io_nic *nic;
++
++ /* copy of sp->dev pointer */
++ struct net_device *dev;
++
++ /* copy of sp->pdev pointer */
++ struct pci_dev *pdev;
++
+ /*
+ * Place holders for the virtual and physical addresses of
+ * all the Rx Blocks
+@@ -690,13 +745,16 @@ struct ring_info {
+ */
+ struct rx_curr_get_info rx_curr_get_info;
-@@ -589,9 +590,9 @@ ixgb_sw_init(struct ixgb_adapter *adapter)
- /* enable flow control to be programmed */
- hw->fc.send_xon = 1;
+- /* Index to the absolute position of the put pointer of Rx ring */
+- int put_pos;
+-
++ /* interface MTU value */
++ unsigned mtu;
++
+ /* Buffer Address store. */
+ struct buffAdd **ba;
+- struct s2io_nic *nic;
+-};
++
++ /* per-Ring statistics */
++ unsigned long rx_packets;
++ unsigned long rx_bytes;
++} ____cacheline_aligned;
-- atomic_set(&adapter->irq_sem, 1);
- spin_lock_init(&adapter->tx_lock);
+ /* Fifo specific structure */
+ struct fifo_info {
+@@ -720,6 +778,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;
-+ set_bit(__IXGB_DOWN, &adapter->flags);
- return 0;
- }
+ /* Per fifo lock */
+ spinlock_t tx_lock;
+@@ -794,25 +861,6 @@ struct msix_info_st {
+ u64 data;
+ };
-@@ -656,7 +657,7 @@ ixgb_close(struct net_device *netdev)
+-/* Data structure to represent a LRO session */
+-struct lro {
+- struct sk_buff *parent;
+- struct sk_buff *last_frag;
+- u8 *l2h;
+- struct iphdr *iph;
+- struct tcphdr *tcph;
+- u32 tcp_next_seq;
+- __be32 tcp_ack;
+- int total_len;
+- int frags_len;
+- int sg_num;
+- int in_use;
+- __be16 window;
+- u32 cur_tsval;
+- __be32 cur_tsecr;
+- u8 saw_ts;
+-};
+-
+ /* These flags represent the devices temporary state */
+ enum s2io_device_state_t
{
- struct ixgb_adapter *adapter = netdev_priv(netdev);
+@@ -845,8 +893,6 @@ struct s2io_nic {
+ int device_enabled_once;
-- ixgb_down(adapter, TRUE);
-+ ixgb_down(adapter, true);
+ char name[60];
+- struct tasklet_struct task;
+- volatile unsigned long tasklet_status;
- 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;
+ /* Timer that handles I/O errors/exceptions */
+ struct timer_list alarm_timer;
+@@ -854,10 +900,6 @@ struct s2io_nic {
+ /* Space to back up the PCI config space */
+ u32 config_space[256 / sizeof(u32)];
- /* 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;
+- atomic_t rx_bufs_left[MAX_RX_RINGS];
+-
+- spinlock_t put_lock;
+-
+ #define PROMISC 1
+ #define ALL_MULTI 2
- rctl = IXGB_READ_REG(&adapter->hw, RCTL);
+@@ -885,6 +927,27 @@ struct s2io_nic {
+ */
+ int rx_csum;
-@@ -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;
++ /* 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.
+ */
+@@ -913,14 +976,11 @@ struct s2io_nic {
+ #define XFRAME_II_DEVICE 2
+ u8 device_type;
+
+-#define MAX_LRO_SESSIONS 32
+- struct lro lro0_n[MAX_LRO_SESSIONS];
+ unsigned long clubbed_frms_cnt;
+ unsigned long sending_both;
+ 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 +1110,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);
+@@ -1083,11 +1142,11 @@ static int do_s2io_add_mc(struct s2io_nic *sp, u8 *addr);
+ static int do_s2io_add_mac(struct s2io_nic *sp, u64 addr, int offset);
+ static int do_s2io_delete_unicast_mc(struct s2io_nic *sp, u64 addr);
- /* make sure receives are disabled while setting up the descriptors */
+-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 int s2io_club_tcp_session(struct ring_info *ring_data, 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);
-@@ -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;
+ /* 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[]);
- /* 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];
+ /* 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);
- IXGB_WRITE_REG(hw, RCTL, rctl);
-@@ -1164,7 +1165,7 @@ ixgb_watchdog(unsigned long data)
- }
+ /* 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[]);
- /* Force detection of hung controller every watchdog period */
-- adapter->detect_tx_hung = TRUE;
-+ adapter->detect_tx_hung = true;
+ /* 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);
- /* 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;
+ 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;
- if (likely(skb_is_gso(skb))) {
-@@ -1243,12 +1244,12 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
- return 0;
+ /* 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)
}
--static boolean_t
-+static bool
- ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
+ /* 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[])
{
- struct ixgb_context_desc *context_desc;
- unsigned int i;
-- uint8_t css, cso;
-+ u8 css, cso;
+ unsigned char a;
+@@ -354,7 +354,7 @@ card_send_command(const int ioaddr[], const char* name,
+ static const int Sb1000TimeOutJiffies = 7 * HZ;
- 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;
+ /* 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)
+ }
-- return TRUE;
-+ return true;
- }
+ /* 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)
+ }
-- return FALSE;
-+ return false;
+ /* 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,
}
- #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;
+ /* 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[])
+ }
- 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;
+ /* 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};
-+ if (test_bit(__IXGB_DOWN, &adapter->flags)) {
-+ dev_kfree_skb(skb);
-+ return NETDEV_TX_OK;
-+ }
+ 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};
+
- 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);
+ unsigned char st[7];
+ int port, status;
+- const unsigned char Command0[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00};
- adapter->tx_timeout_count++;
-- ixgb_down(adapter, TRUE);
-+ ixgb_down(adapter, true);
- ixgb_up(adapter);
+ port = ioaddr[1] + 6;
+ outb(0x4, port);
+@@ -479,12 +480,13 @@ sb1000_reset(const int ioaddr[], const char* name)
}
-@@ -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);
- }
+ /* 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};
-@@ -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 */
+ /* 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};
-- 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);
+ return card_send_command(ioaddr, name, Command0, st);
+ }
- #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.
- */
+-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};
-- 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
- **/
+ if ((status = card_send_command(ioaddr, name, Command0, st)))
+ return status;
+ return card_send_command(ioaddr, name, Command1, st);
+ }
--static boolean_t
-+static bool
- ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
+-static inline int
++static int
+ sb1000_activate(const int ioaddr[], const char* name)
{
- 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)
++ 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};
- while(eop_desc->status & IXGB_TX_DESC_STATUS_DD) {
+ 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};
-- for(cleaned = FALSE; !cleaned; ) {
-+ for (cleaned = false; !cleaned; ) {
- tx_desc = IXGB_TX_DESC(*tx_ring, i);
- buffer_info = &tx_ring->buffer_info[i];
+ 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};
-@@ -1839,7 +1843,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
+ 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};
- ixgb_unmap_and_free_tx_resource(adapter, buffer_info);
+ 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};
-- *(uint32_t *)&(tx_desc->status) = 0;
-+ *(u32 *)&(tx_desc->status) = 0;
+ 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[])
+ }
- 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;
+-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)
+ {
- 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);
+@@ -888,14 +897,15 @@ dropped_frame:
+ return -1;
+ }
-- cleaned = TRUE;
-+ cleaned = true;
+-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;
- 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)
+ 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)
{
- struct ixgb_adapter *adapter = netdev_priv(netdev);
-- uint32_t ctrl, rctl;
-+ u32 ctrl, rctl;
++ 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);
- 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);
- }
+- 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;
-- ixgb_irq_enable(adapter);
-+ /* don't enable interrupts unless we are UP */
-+ if (adapter->netdev->flags & IFF_UP)
-+ ixgb_irq_enable(adapter);
- }
+ 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));
- 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;
+ 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 {
- /* add VID to filter table */
+ /* for dev->get_stats */
+ long rx_value;
+- struct net_device_stats stats;
+ };
-@@ -2211,18 +2217,20 @@ ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
+ /* 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++;
- 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;
+ 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;
+ }
- ixgb_irq_disable(adapter);
+ if (tx_status & (TxOutOfWindow | TxAborted)) {
+- priv->stats.tx_errors++;
++ dev->stats.tx_errors++;
- vlan_group_set_device(adapter->vlgrp, vid, NULL);
+ if (tx_status & TxAborted)
+- priv->stats.tx_aborted_errors++;
++ dev->stats.tx_aborted_errors++;
-- ixgb_irq_enable(adapter);
-+ /* don't enable interrupts unless we are UP */
-+ if (adapter->netdev->flags & IFF_UP)
-+ ixgb_irq_enable(adapter);
+ if (tx_status & TxCarrierLost)
+- priv->stats.tx_carrier_errors++;
++ dev->stats.tx_carrier_errors++;
-- /* remove VID from filter table*/
-+ /* remove VID from filter table */
+ if (tx_status & TxOutOfWindow)
+- priv->stats.tx_window_errors++;
++ dev->stats.tx_window_errors++;
+ }
- 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 (tx_status & TxUnderrun)
+- priv->stats.tx_fifo_errors++;
++ dev->stats.tx_fifo_errors++;
+ }
- 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 (priv->tx_tail != old_tx_tail)
+@@ -704,27 +703,29 @@ static void _sc92031_tx_tasklet(struct net_device *dev)
+ netif_wake_queue(dev);
+ }
- if(netif_running(netdev))
-- ixgb_down(adapter, TRUE);
-+ ixgb_down(adapter, true);
+-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++;
+ }
- pci_disable_device(pdev);
+ if (!(rx_status & RxStatesOK)) {
+- priv->stats.rx_errors++;
++ dev->stats.rx_errors++;
-diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h
-index 9e04a6b..4be1b27 100644
---- a/drivers/net/ixgb/ixgb_osdep.h
-+++ b/drivers/net/ixgb/ixgb_osdep.h
-@@ -39,13 +39,6 @@
- #include <linux/interrupt.h>
- #include <linux/sched.h>
+ if (rx_status & (RxHugeFrame | RxSmallFrame))
+- priv->stats.rx_length_errors++;
++ dev->stats.rx_length_errors++;
--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"
+ if (rx_status & RxBadAlign)
+- priv->stats.rx_frame_errors++;
++ dev->stats.rx_frame_errors++;
-+#ifdef CONFIG_DCA
-+#include <linux/dca.h>
-+#endif
+ 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++;
++ }
+ }
- #define IXGBE_ERR(args...) printk(KERN_ERR "ixgbe: " args)
+ 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;
+ }
-@@ -120,7 +123,6 @@ struct ixgbe_queue_stats {
- };
+@@ -795,7 +796,7 @@ static void _sc92031_rx_tasklet(struct net_device *dev)
- 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;
+ rx_len -= rx_size_align + 4;
-+ 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;
+- 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);
-+ unsigned int total_bytes;
-+ unsigned int total_packets;
+- priv->stats.rx_bytes += pkt_size;
+- priv->stats.rx_packets++;
++ dev->stats.rx_bytes += pkt_size;
++ dev->stats.rx_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 */
+ if (rx_status & Rx_Multicast)
+- priv->stats.multicast++;
++ dev->stats.multicast++;
- u32 eims_value;
- u16 itr_register;
-@@ -146,6 +162,33 @@ struct ixgbe_ring {
- u16 work_limit; /* max work per interrupt */
- };
+ 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)
-+#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 {
+ 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++;
+ }
+ }
- #define IXGBE_MAX_JUMBO_FRAME_SIZE 16128
+@@ -866,11 +865,11 @@ static void sc92031_tasklet(unsigned long data)
+ _sc92031_rx_tasklet(dev);
-+#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;
+ if (intr_status & RxOverflow)
+- priv->stats.rx_errors++;
++ dev->stats.rx_errors++;
- /* 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;
+ if (intr_status & TimeOut) {
+- priv->stats.rx_errors++;
+- priv->stats.rx_length_errors++;
++ dev->stats.rx_errors++;
++ dev->stats.rx_length_errors++;
+ }
- u64 rx_hdr_split;
- u32 alloc_rx_page_failed;
- u32 alloc_rx_buff_failed;
+ if (intr_status & (LinkFail | LinkOK))
+@@ -936,38 +935,36 @@ static struct net_device_stats *sc92031_get_stats(struct net_device *dev)
-+ /* 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)
+ 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;
- /* 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;
+ spin_unlock_bh(&priv->lock);
+ }
- 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)
+- return &priv->stats;
++ return &dev->stats;
+ }
- static int ixgbe_set_tso(struct net_device *netdev, u32 data)
+ 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;
-
- 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);
+ unsigned len;
+ unsigned entry;
+ u32 tx_status;
-- 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 (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;
+ }
-- 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;
+ spin_lock(&priv->lock);
-@@ -893,22 +906,26 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
- struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ if (unlikely(!netif_carrier_ok(dev))) {
+- err = -ENOLINK;
+- priv->stats.tx_dropped++;
++ dev->stats.tx_dropped++;
+ goto out_unlock;
+ }
- 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;
+@@ -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);
- /* 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);
+ len = skb->len;
+- if (unlikely(len < ETH_ZLEN)) {
+- memset(priv->tx_bufs + entry * TX_BUF_SIZE + len,
+- 0, ETH_ZLEN - len);
+- len = ETH_ZLEN;
+- }
-- 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);
+ wmb();
-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";
+@@ -1009,7 +1001,7 @@ out_unlock:
+ out:
+ dev_kfree_skb(skb);
--#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);
+- return err;
++ return NETDEV_TX_OK;
+ }
-+#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
+ static int sc92031_open(struct net_device *dev)
+diff --git a/drivers/net/sfc/Kconfig b/drivers/net/sfc/Kconfig
+new file mode 100644
+index 0000000..dbad95c
+--- /dev/null
++++ b/drivers/net/sfc/Kconfig
+@@ -0,0 +1,12 @@
++config SFC
++ tristate "Solarflare Solarstorm SFC4000 support"
++ depends on PCI && INET
++ select MII
++ select INET_LRO
++ select CRC32
++ help
++ This driver supports 10-gigabit Ethernet cards based on
++ the Solarflare Communications Solarstorm SFC4000 controller.
+
- MODULE_AUTHOR("Intel Corporation, <linux.nics at intel.com>");
- MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver");
- MODULE_LICENSE("GPL");
-@@ -256,26 +266,125 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter,
- * sees the new next_to_clean.
- */
- smp_mb();
-+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
-+ if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) &&
-+ !test_bit(__IXGBE_DOWN, &adapter->state)) {
-+ netif_wake_subqueue(netdev, tx_ring->queue_index);
-+ adapter->restart_queue++;
-+ }
++ To compile this driver as a module, choose M here. The module
++ will be called sfc.
+diff --git a/drivers/net/sfc/Makefile b/drivers/net/sfc/Makefile
+new file mode 100644
+index 0000000..0f02344
+--- /dev/null
++++ b/drivers/net/sfc/Makefile
+@@ -0,0 +1,5 @@
++sfc-y += efx.o falcon.o tx.o rx.o falcon_xmac.o \
++ i2c-direct.o ethtool.o xfp_phy.o mdio_10g.o \
++ tenxpress.o boards.o sfe4001.o
++
++obj-$(CONFIG_SFC) += sfc.o
+diff --git a/drivers/net/sfc/bitfield.h b/drivers/net/sfc/bitfield.h
+new file mode 100644
+index 0000000..2806201
+--- /dev/null
++++ b/drivers/net/sfc/bitfield.h
+@@ -0,0 +1,508 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005-2006 Fen Systems Ltd.
++ * Copyright 2006-2008 Solarflare Communications 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, incorporated herein by reference.
++ */
++
++#ifndef EFX_BITFIELD_H
++#define EFX_BITFIELD_H
++
++/*
++ * Efx bitfield access
++ *
++ * Efx NICs make extensive use of bitfields up to 128 bits
++ * wide. Since there is no native 128-bit datatype on most systems,
++ * and since 64-bit datatypes are inefficient on 32-bit systems and
++ * vice versa, we wrap accesses in a way that uses the most efficient
++ * datatype.
++ *
++ * The NICs are PCI devices and therefore little-endian. Since most
++ * of the quantities that we deal with are DMAed to/from host memory,
++ * we define our datatypes (efx_oword_t, efx_qword_t and
++ * efx_dword_t) to be little-endian.
++ */
++
++/* Lowest bit numbers and widths */
++#define EFX_DUMMY_FIELD_LBN 0
++#define EFX_DUMMY_FIELD_WIDTH 0
++#define EFX_DWORD_0_LBN 0
++#define EFX_DWORD_0_WIDTH 32
++#define EFX_DWORD_1_LBN 32
++#define EFX_DWORD_1_WIDTH 32
++#define EFX_DWORD_2_LBN 64
++#define EFX_DWORD_2_WIDTH 32
++#define EFX_DWORD_3_LBN 96
++#define EFX_DWORD_3_WIDTH 32
++
++/* Specified attribute (e.g. LBN) of the specified field */
++#define EFX_VAL(field, attribute) field ## _ ## attribute
++/* Low bit number of the specified field */
++#define EFX_LOW_BIT(field) EFX_VAL(field, LBN)
++/* Bit width of the specified field */
++#define EFX_WIDTH(field) EFX_VAL(field, WIDTH)
++/* High bit number of the specified field */
++#define EFX_HIGH_BIT(field) (EFX_LOW_BIT(field) + EFX_WIDTH(field) - 1)
++/* Mask equal in width to the specified field.
++ *
++ * For example, a field with width 5 would have a mask of 0x1f.
++ *
++ * The maximum width mask that can be generated is 64 bits.
++ */
++#define EFX_MASK64(field) \
++ (EFX_WIDTH(field) == 64 ? ~((u64) 0) : \
++ (((((u64) 1) << EFX_WIDTH(field))) - 1))
++
++/* Mask equal in width to the specified field.
++ *
++ * For example, a field with width 5 would have a mask of 0x1f.
++ *
++ * The maximum width mask that can be generated is 32 bits. Use
++ * EFX_MASK64 for higher width fields.
++ */
++#define EFX_MASK32(field) \
++ (EFX_WIDTH(field) == 32 ? ~((u32) 0) : \
++ (((((u32) 1) << EFX_WIDTH(field))) - 1))
++
++/* A doubleword (i.e. 4 byte) datatype - little-endian in HW */
++typedef union efx_dword {
++ __le32 u32[1];
++} efx_dword_t;
++
++/* A quadword (i.e. 8 byte) datatype - little-endian in HW */
++typedef union efx_qword {
++ __le64 u64[1];
++ __le32 u32[2];
++ efx_dword_t dword[2];
++} efx_qword_t;
++
++/* An octword (eight-word, i.e. 16 byte) datatype - little-endian in HW */
++typedef union efx_oword {
++ __le64 u64[2];
++ efx_qword_t qword[2];
++ __le32 u32[4];
++ efx_dword_t dword[4];
++} efx_oword_t;
++
++/* Format string and value expanders for printk */
++#define EFX_DWORD_FMT "%08x"
++#define EFX_QWORD_FMT "%08x:%08x"
++#define EFX_OWORD_FMT "%08x:%08x:%08x:%08x"
++#define EFX_DWORD_VAL(dword) \
++ ((unsigned int) le32_to_cpu((dword).u32[0]))
++#define EFX_QWORD_VAL(qword) \
++ ((unsigned int) le32_to_cpu((qword).u32[1])), \
++ ((unsigned int) le32_to_cpu((qword).u32[0]))
++#define EFX_OWORD_VAL(oword) \
++ ((unsigned int) le32_to_cpu((oword).u32[3])), \
++ ((unsigned int) le32_to_cpu((oword).u32[2])), \
++ ((unsigned int) le32_to_cpu((oword).u32[1])), \
++ ((unsigned int) le32_to_cpu((oword).u32[0]))
++
++/*
++ * Extract bit field portion [low,high) from the native-endian element
++ * which contains bits [min,max).
++ *
++ * For example, suppose "element" represents the high 32 bits of a
++ * 64-bit value, and we wish to extract the bits belonging to the bit
++ * field occupying bits 28-45 of this 64-bit value.
++ *
++ * Then EFX_EXTRACT ( element, 32, 63, 28, 45 ) would give
++ *
++ * ( element ) << 4
++ *
++ * The result will contain the relevant bits filled in in the range
++ * [0,high-low), with garbage in bits [high-low+1,...).
++ */
++#define EFX_EXTRACT_NATIVE(native_element, min, max, low, high) \
++ (((low > max) || (high < min)) ? 0 : \
++ ((low > min) ? \
++ ((native_element) >> (low - min)) : \
++ ((native_element) << (min - low))))
++
++/*
++ * Extract bit field portion [low,high) from the 64-bit little-endian
++ * element which contains bits [min,max)
++ */
++#define EFX_EXTRACT64(element, min, max, low, high) \
++ EFX_EXTRACT_NATIVE(le64_to_cpu(element), min, max, low, high)
++
++/*
++ * Extract bit field portion [low,high) from the 32-bit little-endian
++ * element which contains bits [min,max)
++ */
++#define EFX_EXTRACT32(element, min, max, low, high) \
++ EFX_EXTRACT_NATIVE(le32_to_cpu(element), min, max, low, high)
++
++#define EFX_EXTRACT_OWORD64(oword, low, high) \
++ (EFX_EXTRACT64((oword).u64[0], 0, 63, low, high) | \
++ EFX_EXTRACT64((oword).u64[1], 64, 127, low, high))
++
++#define EFX_EXTRACT_QWORD64(qword, low, high) \
++ EFX_EXTRACT64((qword).u64[0], 0, 63, low, high)
++
++#define EFX_EXTRACT_OWORD32(oword, low, high) \
++ (EFX_EXTRACT32((oword).u32[0], 0, 31, low, high) | \
++ EFX_EXTRACT32((oword).u32[1], 32, 63, low, high) | \
++ EFX_EXTRACT32((oword).u32[2], 64, 95, low, high) | \
++ EFX_EXTRACT32((oword).u32[3], 96, 127, low, high))
++
++#define EFX_EXTRACT_QWORD32(qword, low, high) \
++ (EFX_EXTRACT32((qword).u32[0], 0, 31, low, high) | \
++ EFX_EXTRACT32((qword).u32[1], 32, 63, low, high))
++
++#define EFX_EXTRACT_DWORD(dword, low, high) \
++ EFX_EXTRACT32((dword).u32[0], 0, 31, low, high)
++
++#define EFX_OWORD_FIELD64(oword, field) \
++ (EFX_EXTRACT_OWORD64(oword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
++ & EFX_MASK64(field))
++
++#define EFX_QWORD_FIELD64(qword, field) \
++ (EFX_EXTRACT_QWORD64(qword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
++ & EFX_MASK64(field))
++
++#define EFX_OWORD_FIELD32(oword, field) \
++ (EFX_EXTRACT_OWORD32(oword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
++ & EFX_MASK32(field))
++
++#define EFX_QWORD_FIELD32(qword, field) \
++ (EFX_EXTRACT_QWORD32(qword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
++ & EFX_MASK32(field))
++
++#define EFX_DWORD_FIELD(dword, field) \
++ (EFX_EXTRACT_DWORD(dword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
++ & EFX_MASK32(field))
++
++#define EFX_OWORD_IS_ZERO64(oword) \
++ (((oword).u64[0] | (oword).u64[1]) == (__force __le64) 0)
++
++#define EFX_QWORD_IS_ZERO64(qword) \
++ (((qword).u64[0]) == (__force __le64) 0)
++
++#define EFX_OWORD_IS_ZERO32(oword) \
++ (((oword).u32[0] | (oword).u32[1] | (oword).u32[2] | (oword).u32[3]) \
++ == (__force __le32) 0)
++
++#define EFX_QWORD_IS_ZERO32(qword) \
++ (((qword).u32[0] | (qword).u32[1]) == (__force __le32) 0)
++
++#define EFX_DWORD_IS_ZERO(dword) \
++ (((dword).u32[0]) == (__force __le32) 0)
++
++#define EFX_OWORD_IS_ALL_ONES64(oword) \
++ (((oword).u64[0] & (oword).u64[1]) == ~((__force __le64) 0))
++
++#define EFX_QWORD_IS_ALL_ONES64(qword) \
++ ((qword).u64[0] == ~((__force __le64) 0))
++
++#define EFX_OWORD_IS_ALL_ONES32(oword) \
++ (((oword).u32[0] & (oword).u32[1] & (oword).u32[2] & (oword).u32[3]) \
++ == ~((__force __le32) 0))
++
++#define EFX_QWORD_IS_ALL_ONES32(qword) \
++ (((qword).u32[0] & (qword).u32[1]) == ~((__force __le32) 0))
++
++#define EFX_DWORD_IS_ALL_ONES(dword) \
++ ((dword).u32[0] == ~((__force __le32) 0))
++
++#if BITS_PER_LONG == 64
++#define EFX_OWORD_FIELD EFX_OWORD_FIELD64
++#define EFX_QWORD_FIELD EFX_QWORD_FIELD64
++#define EFX_OWORD_IS_ZERO EFX_OWORD_IS_ZERO64
++#define EFX_QWORD_IS_ZERO EFX_QWORD_IS_ZERO64
++#define EFX_OWORD_IS_ALL_ONES EFX_OWORD_IS_ALL_ONES64
++#define EFX_QWORD_IS_ALL_ONES EFX_QWORD_IS_ALL_ONES64
+#else
- if (netif_queue_stopped(netdev) &&
- !test_bit(__IXGBE_DOWN, &adapter->state)) {
- netif_wake_queue(netdev);
- adapter->restart_queue++;
- }
++#define EFX_OWORD_FIELD EFX_OWORD_FIELD32
++#define EFX_QWORD_FIELD EFX_QWORD_FIELD32
++#define EFX_OWORD_IS_ZERO EFX_OWORD_IS_ZERO32
++#define EFX_QWORD_IS_ZERO EFX_QWORD_IS_ZERO32
++#define EFX_OWORD_IS_ALL_ONES EFX_OWORD_IS_ALL_ONES32
++#define EFX_QWORD_IS_ALL_ONES EFX_QWORD_IS_ALL_ONES32
++#endif
++
++/*
++ * Construct bit field portion
++ *
++ * Creates the portion of the bit field [low,high) that lies within
++ * the range [min,max).
++ */
++#define EFX_INSERT_NATIVE64(min, max, low, high, value) \
++ (((low > max) || (high < min)) ? 0 : \
++ ((low > min) ? \
++ (((u64) (value)) << (low - min)) : \
++ (((u64) (value)) >> (min - low))))
++
++#define EFX_INSERT_NATIVE32(min, max, low, high, value) \
++ (((low > max) || (high < min)) ? 0 : \
++ ((low > min) ? \
++ (((u32) (value)) << (low - min)) : \
++ (((u32) (value)) >> (min - low))))
++
++#define EFX_INSERT_NATIVE(min, max, low, high, value) \
++ ((((max - min) >= 32) || ((high - low) >= 32)) ? \
++ EFX_INSERT_NATIVE64(min, max, low, high, value) : \
++ EFX_INSERT_NATIVE32(min, max, low, high, value))
++
++/*
++ * Construct bit field portion
++ *
++ * Creates the portion of the named bit field that lies within the
++ * range [min,max).
++ */
++#define EFX_INSERT_FIELD_NATIVE(min, max, field, value) \
++ EFX_INSERT_NATIVE(min, max, EFX_LOW_BIT(field), \
++ EFX_HIGH_BIT(field), value)
++
++/*
++ * Construct bit field
++ *
++ * Creates the portion of the named bit fields that lie within the
++ * range [min,max).
++ */
++#define EFX_INSERT_FIELDS_NATIVE(min, max, \
++ field1, value1, \
++ field2, value2, \
++ field3, value3, \
++ field4, value4, \
++ field5, value5, \
++ field6, value6, \
++ field7, value7, \
++ field8, value8, \
++ field9, value9, \
++ field10, value10) \
++ (EFX_INSERT_FIELD_NATIVE((min), (max), field1, (value1)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field2, (value2)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field3, (value3)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field4, (value4)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field5, (value5)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field6, (value6)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field7, (value7)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field8, (value8)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field9, (value9)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field10, (value10)))
++
++#define EFX_INSERT_FIELDS64(...) \
++ cpu_to_le64(EFX_INSERT_FIELDS_NATIVE(__VA_ARGS__))
++
++#define EFX_INSERT_FIELDS32(...) \
++ cpu_to_le32(EFX_INSERT_FIELDS_NATIVE(__VA_ARGS__))
++
++#define EFX_POPULATE_OWORD64(oword, ...) do { \
++ (oword).u64[0] = EFX_INSERT_FIELDS64(0, 63, __VA_ARGS__); \
++ (oword).u64[1] = EFX_INSERT_FIELDS64(64, 127, __VA_ARGS__); \
++ } while (0)
++
++#define EFX_POPULATE_QWORD64(qword, ...) do { \
++ (qword).u64[0] = EFX_INSERT_FIELDS64(0, 63, __VA_ARGS__); \
++ } while (0)
++
++#define EFX_POPULATE_OWORD32(oword, ...) do { \
++ (oword).u32[0] = EFX_INSERT_FIELDS32(0, 31, __VA_ARGS__); \
++ (oword).u32[1] = EFX_INSERT_FIELDS32(32, 63, __VA_ARGS__); \
++ (oword).u32[2] = EFX_INSERT_FIELDS32(64, 95, __VA_ARGS__); \
++ (oword).u32[3] = EFX_INSERT_FIELDS32(96, 127, __VA_ARGS__); \
++ } while (0)
++
++#define EFX_POPULATE_QWORD32(qword, ...) do { \
++ (qword).u32[0] = EFX_INSERT_FIELDS32(0, 31, __VA_ARGS__); \
++ (qword).u32[1] = EFX_INSERT_FIELDS32(32, 63, __VA_ARGS__); \
++ } while (0)
++
++#define EFX_POPULATE_DWORD(dword, ...) do { \
++ (dword).u32[0] = EFX_INSERT_FIELDS32(0, 31, __VA_ARGS__); \
++ } while (0)
++
++#if BITS_PER_LONG == 64
++#define EFX_POPULATE_OWORD EFX_POPULATE_OWORD64
++#define EFX_POPULATE_QWORD EFX_POPULATE_QWORD64
++#else
++#define EFX_POPULATE_OWORD EFX_POPULATE_OWORD32
++#define EFX_POPULATE_QWORD EFX_POPULATE_QWORD32
+#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);
++
++/* Populate an octword field with various numbers of arguments */
++#define EFX_POPULATE_OWORD_10 EFX_POPULATE_OWORD
++#define EFX_POPULATE_OWORD_9(oword, ...) \
++ EFX_POPULATE_OWORD_10(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_OWORD_8(oword, ...) \
++ EFX_POPULATE_OWORD_9(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_OWORD_7(oword, ...) \
++ EFX_POPULATE_OWORD_8(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_OWORD_6(oword, ...) \
++ EFX_POPULATE_OWORD_7(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_OWORD_5(oword, ...) \
++ EFX_POPULATE_OWORD_6(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_OWORD_4(oword, ...) \
++ EFX_POPULATE_OWORD_5(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_OWORD_3(oword, ...) \
++ EFX_POPULATE_OWORD_4(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_OWORD_2(oword, ...) \
++ EFX_POPULATE_OWORD_3(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_OWORD_1(oword, ...) \
++ EFX_POPULATE_OWORD_2(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_ZERO_OWORD(oword) \
++ EFX_POPULATE_OWORD_1(oword, EFX_DUMMY_FIELD, 0)
++#define EFX_SET_OWORD(oword) \
++ EFX_POPULATE_OWORD_4(oword, \
++ EFX_DWORD_0, 0xffffffff, \
++ EFX_DWORD_1, 0xffffffff, \
++ EFX_DWORD_2, 0xffffffff, \
++ EFX_DWORD_3, 0xffffffff)
++
++/* Populate a quadword field with various numbers of arguments */
++#define EFX_POPULATE_QWORD_10 EFX_POPULATE_QWORD
++#define EFX_POPULATE_QWORD_9(qword, ...) \
++ EFX_POPULATE_QWORD_10(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_QWORD_8(qword, ...) \
++ EFX_POPULATE_QWORD_9(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_QWORD_7(qword, ...) \
++ EFX_POPULATE_QWORD_8(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_QWORD_6(qword, ...) \
++ EFX_POPULATE_QWORD_7(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_QWORD_5(qword, ...) \
++ EFX_POPULATE_QWORD_6(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_QWORD_4(qword, ...) \
++ EFX_POPULATE_QWORD_5(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_QWORD_3(qword, ...) \
++ EFX_POPULATE_QWORD_4(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_QWORD_2(qword, ...) \
++ EFX_POPULATE_QWORD_3(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_QWORD_1(qword, ...) \
++ EFX_POPULATE_QWORD_2(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_ZERO_QWORD(qword) \
++ EFX_POPULATE_QWORD_1(qword, EFX_DUMMY_FIELD, 0)
++#define EFX_SET_QWORD(qword) \
++ EFX_POPULATE_QWORD_2(qword, \
++ EFX_DWORD_0, 0xffffffff, \
++ EFX_DWORD_1, 0xffffffff)
++
++/* Populate a dword field with various numbers of arguments */
++#define EFX_POPULATE_DWORD_10 EFX_POPULATE_DWORD
++#define EFX_POPULATE_DWORD_9(dword, ...) \
++ EFX_POPULATE_DWORD_10(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_DWORD_8(dword, ...) \
++ EFX_POPULATE_DWORD_9(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_DWORD_7(dword, ...) \
++ EFX_POPULATE_DWORD_8(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_DWORD_6(dword, ...) \
++ EFX_POPULATE_DWORD_7(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_DWORD_5(dword, ...) \
++ EFX_POPULATE_DWORD_6(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_DWORD_4(dword, ...) \
++ EFX_POPULATE_DWORD_5(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_DWORD_3(dword, ...) \
++ EFX_POPULATE_DWORD_4(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_DWORD_2(dword, ...) \
++ EFX_POPULATE_DWORD_3(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_DWORD_1(dword, ...) \
++ EFX_POPULATE_DWORD_2(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_ZERO_DWORD(dword) \
++ EFX_POPULATE_DWORD_1(dword, EFX_DUMMY_FIELD, 0)
++#define EFX_SET_DWORD(dword) \
++ EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0, 0xffffffff)
++
++/*
++ * Modify a named field within an already-populated structure. Used
++ * for read-modify-write operations.
++ *
++ */
++
++#define EFX_INVERT_OWORD(oword) do { \
++ (oword).u64[0] = ~((oword).u64[0]); \
++ (oword).u64[1] = ~((oword).u64[1]); \
++ } while (0)
++
++#define EFX_INSERT_FIELD64(...) \
++ cpu_to_le64(EFX_INSERT_FIELD_NATIVE(__VA_ARGS__))
++
++#define EFX_INSERT_FIELD32(...) \
++ cpu_to_le32(EFX_INSERT_FIELD_NATIVE(__VA_ARGS__))
++
++#define EFX_INPLACE_MASK64(min, max, field) \
++ EFX_INSERT_FIELD64(min, max, field, EFX_MASK64(field))
++
++#define EFX_INPLACE_MASK32(min, max, field) \
++ EFX_INSERT_FIELD32(min, max, field, EFX_MASK32(field))
++
++#define EFX_SET_OWORD_FIELD64(oword, field, value) do { \
++ (oword).u64[0] = (((oword).u64[0] \
++ & ~EFX_INPLACE_MASK64(0, 63, field)) \
++ | EFX_INSERT_FIELD64(0, 63, field, value)); \
++ (oword).u64[1] = (((oword).u64[1] \
++ & ~EFX_INPLACE_MASK64(64, 127, field)) \
++ | EFX_INSERT_FIELD64(64, 127, field, value)); \
++ } while (0)
++
++#define EFX_SET_QWORD_FIELD64(qword, field, value) do { \
++ (qword).u64[0] = (((qword).u64[0] \
++ & ~EFX_INPLACE_MASK64(0, 63, field)) \
++ | EFX_INSERT_FIELD64(0, 63, field, value)); \
++ } while (0)
++
++#define EFX_SET_OWORD_FIELD32(oword, field, value) do { \
++ (oword).u32[0] = (((oword).u32[0] \
++ & ~EFX_INPLACE_MASK32(0, 31, field)) \
++ | EFX_INSERT_FIELD32(0, 31, field, value)); \
++ (oword).u32[1] = (((oword).u32[1] \
++ & ~EFX_INPLACE_MASK32(32, 63, field)) \
++ | EFX_INSERT_FIELD32(32, 63, field, value)); \
++ (oword).u32[2] = (((oword).u32[2] \
++ & ~EFX_INPLACE_MASK32(64, 95, field)) \
++ | EFX_INSERT_FIELD32(64, 95, field, value)); \
++ (oword).u32[3] = (((oword).u32[3] \
++ & ~EFX_INPLACE_MASK32(96, 127, field)) \
++ | EFX_INSERT_FIELD32(96, 127, field, value)); \
++ } while (0)
++
++#define EFX_SET_QWORD_FIELD32(qword, field, value) do { \
++ (qword).u32[0] = (((qword).u32[0] \
++ & ~EFX_INPLACE_MASK32(0, 31, field)) \
++ | EFX_INSERT_FIELD32(0, 31, field, value)); \
++ (qword).u32[1] = (((qword).u32[1] \
++ & ~EFX_INPLACE_MASK32(32, 63, field)) \
++ | EFX_INSERT_FIELD32(32, 63, field, value)); \
++ } while (0)
++
++#define EFX_SET_DWORD_FIELD(dword, field, value) do { \
++ (dword).u32[0] = (((dword).u32[0] \
++ & ~EFX_INPLACE_MASK32(0, 31, field)) \
++ | EFX_INSERT_FIELD32(0, 31, field, value)); \
++ } while (0)
++
++#if BITS_PER_LONG == 64
++#define EFX_SET_OWORD_FIELD EFX_SET_OWORD_FIELD64
++#define EFX_SET_QWORD_FIELD EFX_SET_QWORD_FIELD64
+#else
- netif_stop_queue(netdev);
++#define EFX_SET_OWORD_FIELD EFX_SET_OWORD_FIELD32
++#define EFX_SET_QWORD_FIELD EFX_SET_QWORD_FIELD32
+#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;
++#define EFX_SET_OWORD_FIELD_VER(efx, oword, field, value) do { \
++ if (FALCON_REV(efx) >= FALCON_REV_B0) { \
++ EFX_SET_OWORD_FIELD((oword), field##_B0, (value)); \
++ } else { \
++ EFX_SET_OWORD_FIELD((oword), field##_A1, (value)); \
++ } \
++} while (0)
++
++#define EFX_QWORD_FIELD_VER(efx, qword, field) \
++ (FALCON_REV(efx) >= FALCON_REV_B0 ? \
++ EFX_QWORD_FIELD((qword), field##_B0) : \
++ EFX_QWORD_FIELD((qword), field##_A1))
++
++/* Used to avoid compiler warnings about shift range exceeding width
++ * of the data types when dma_addr_t is only 32 bits wide.
++ */
++#define DMA_ADDR_T_WIDTH (8 * sizeof(dma_addr_t))
++#define EFX_DMA_TYPE_WIDTH(width) \
++ (((width) < DMA_ADDR_T_WIDTH) ? (width) : DMA_ADDR_T_WIDTH)
++#define EFX_DMA_MAX_MASK ((DMA_ADDR_T_WIDTH == 64) ? \
++ ~((u64) 0) : ~((u32) 0))
++#define EFX_DMA_MASK(mask) ((mask) & EFX_DMA_MAX_MASK)
++
++#endif /* EFX_BITFIELD_H */
+diff --git a/drivers/net/sfc/boards.c b/drivers/net/sfc/boards.c
+new file mode 100644
+index 0000000..eecaa6d
+--- /dev/null
++++ b/drivers/net/sfc/boards.c
+@@ -0,0 +1,167 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2007 Solarflare Communications 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, incorporated herein by reference.
++ */
++
++#include "net_driver.h"
++#include "phy.h"
++#include "boards.h"
++#include "efx.h"
++
++/* Macros for unpacking the board revision */
++/* The revision info is in host byte order. */
++#define BOARD_TYPE(_rev) (_rev >> 8)
++#define BOARD_MAJOR(_rev) ((_rev >> 4) & 0xf)
++#define BOARD_MINOR(_rev) (_rev & 0xf)
++
++/* Blink support. If the PHY has no auto-blink mode so we hang it off a timer */
++#define BLINK_INTERVAL (HZ/2)
++
++static void blink_led_timer(unsigned long context)
++{
++ struct efx_nic *efx = (struct efx_nic *)context;
++ struct efx_blinker *bl = &efx->board_info.blinker;
++ efx->board_info.set_fault_led(efx, bl->state);
++ bl->state = !bl->state;
++ if (bl->resubmit) {
++ bl->timer.expires = jiffies + BLINK_INTERVAL;
++ add_timer(&bl->timer);
+ }
-+ put_cpu();
+}
+
-+static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
-+ struct ixgbe_ring *txr)
++static void board_blink(struct efx_nic *efx, int blink)
+{
-+ u32 txctrl;
-+ int cpu = get_cpu();
-+ int q = txr - adapter->tx_ring;
++ struct efx_blinker *blinker = &efx->board_info.blinker;
+
-+ 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;
++ /* The rtnl mutex serialises all ethtool ioctls, so
++ * nothing special needs doing here. */
++ if (blink) {
++ blinker->resubmit = 1;
++ blinker->state = 0;
++ setup_timer(&blinker->timer, blink_led_timer,
++ (unsigned long)efx);
++ blinker->timer.expires = jiffies + BLINK_INTERVAL;
++ add_timer(&blinker->timer);
++ } else {
++ blinker->resubmit = 0;
++ if (blinker->timer.function)
++ del_timer_sync(&blinker->timer);
++ efx->board_info.set_fault_led(efx, 0);
+ }
-+ put_cpu();
+}
+
-+static void ixgbe_setup_dca(struct ixgbe_adapter *adapter)
++/*****************************************************************************
++ * Support for the SFE4002
++ *
++ */
++/****************************************************************************/
++/* LED allocations. Note that on rev A0 boards the schematic and the reality
++ * differ: red and green are swapped. Below is the fixed (A1) layout (there
++ * are only 3 A0 boards in existence, so no real reason to make this
++ * conditional).
++ */
++#define SFE4002_FAULT_LED (2) /* Red */
++#define SFE4002_RX_LED (0) /* Green */
++#define SFE4002_TX_LED (1) /* Amber */
++
++static int sfe4002_init_leds(struct efx_nic *efx)
+{
-+ int i;
++ /* Set the TX and RX LEDs to reflect status and activity, and the
++ * fault LED off */
++ xfp_set_led(efx, SFE4002_TX_LED,
++ QUAKE_LED_TXLINK | QUAKE_LED_LINK_ACTSTAT);
++ xfp_set_led(efx, SFE4002_RX_LED,
++ QUAKE_LED_RXLINK | QUAKE_LED_LINK_ACTSTAT);
++ xfp_set_led(efx, SFE4002_FAULT_LED, QUAKE_LED_OFF);
++ efx->board_info.blinker.led_num = SFE4002_FAULT_LED;
++ return 0;
++}
+
-+ if (!(adapter->flags & IXGBE_FLAG_DCA_ENABLED))
-+ return;
++static void sfe4002_fault_led(struct efx_nic *efx, int state)
++{
++ xfp_set_led(efx, SFE4002_FAULT_LED, state ? QUAKE_LED_ON :
++ QUAKE_LED_OFF);
++}
+
-+ 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 sfe4002_init(struct efx_nic *efx)
++{
++ efx->board_info.init_leds = sfe4002_init_leds;
++ efx->board_info.set_fault_led = sfe4002_fault_led;
++ efx->board_info.blink = board_blink;
++ return 0;
+}
+
-+static int __ixgbe_notify_dca(struct device *dev, void *data)
++/* This will get expanded as board-specific details get moved out of the
++ * PHY drivers. */
++struct efx_board_data {
++ const char *ref_model;
++ const char *gen_type;
++ int (*init) (struct efx_nic *nic);
++};
++
++static int dummy_init(struct efx_nic *nic)
+{
-+ struct net_device *netdev = dev_get_drvdata(dev);
-+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
-+ unsigned long event = *(unsigned long *)data;
++ return 0;
++}
+
-+ 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);
++static struct efx_board_data board_data[] = {
++ [EFX_BOARD_INVALID] =
++ {NULL, NULL, dummy_init},
++ [EFX_BOARD_SFE4001] =
++ {"SFE4001", "10GBASE-T adapter", sfe4001_poweron},
++ [EFX_BOARD_SFE4002] =
++ {"SFE4002", "XFP adapter", sfe4002_init},
++};
++
++int efx_set_board_info(struct efx_nic *efx, u16 revision_info)
++{
++ int rc = 0;
++ struct efx_board_data *data;
++
++ if (BOARD_TYPE(revision_info) >= EFX_BOARD_MAX) {
++ EFX_ERR(efx, "squashing unknown board type %d\n",
++ BOARD_TYPE(revision_info));
++ revision_info = 0;
++ }
++
++ if (BOARD_TYPE(revision_info) == 0) {
++ efx->board_info.major = 0;
++ efx->board_info.minor = 0;
++ /* For early boards that don't have revision info. there is
++ * only 1 board for each PHY type, so we can work it out, with
++ * the exception of the PHY-less boards. */
++ switch (efx->phy_type) {
++ case PHY_TYPE_10XPRESS:
++ efx->board_info.type = EFX_BOARD_SFE4001;
++ break;
++ case PHY_TYPE_XFP:
++ efx->board_info.type = EFX_BOARD_SFE4002;
++ break;
++ default:
++ efx->board_info.type = 0;
+ 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;
-+ }
++ } else {
++ efx->board_info.type = BOARD_TYPE(revision_info);
++ efx->board_info.major = BOARD_MAJOR(revision_info);
++ efx->board_info.minor = BOARD_MINOR(revision_info);
++ }
++
++ data = &board_data[efx->board_info.type];
++
++ /* Report the board model number or generic type for recognisable
++ * boards. */
++ if (efx->board_info.type != 0)
++ EFX_INFO(efx, "board is %s rev %c%d\n",
++ (efx->pci_dev->subsystem_vendor == EFX_VENDID_SFC)
++ ? data->ref_model : data->gen_type,
++ 'A' + efx->board_info.major, efx->board_info.minor);
+
-+ return 0;
++ efx->board_info.init = data->init;
++
++ return rc;
+}
+diff --git a/drivers/net/sfc/boards.h b/drivers/net/sfc/boards.h
+new file mode 100644
+index 0000000..f56341d
+--- /dev/null
++++ b/drivers/net/sfc/boards.h
+@@ -0,0 +1,26 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2007 Solarflare Communications 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, incorporated herein by reference.
++ */
+
-+#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;
++#ifndef EFX_BOARDS_H
++#define EFX_BOARDS_H
+
- 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);
++/* Board IDs (must fit in 8 bits) */
++enum efx_board_type {
++ EFX_BOARD_INVALID = 0,
++ EFX_BOARD_SFE4001 = 1, /* SFE4001 (10GBASE-T) */
++ EFX_BOARD_SFE4002 = 2,
++ /* Insert new types before here */
++ EFX_BOARD_MAX
++};
+
-+ 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);
++extern int efx_set_board_info(struct efx_nic *efx, u16 revision_info);
++extern int sfe4001_poweron(struct efx_nic *efx);
++extern void sfe4001_poweroff(struct efx_nic *efx);
+
-+ 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);
-+ }
++#endif
+diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
+new file mode 100644
+index 0000000..59edcf7
+--- /dev/null
++++ b/drivers/net/sfc/efx.c
+@@ -0,0 +1,2208 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005-2006 Fen Systems Ltd.
++ * Copyright 2005-2008 Solarflare Communications 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, incorporated herein by reference.
++ */
+
-+ /* 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;
++#include <linux/module.h>
++#include <linux/pci.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++#include <linux/notifier.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/in.h>
++#include <linux/crc32.h>
++#include <linux/ethtool.h>
++#include "net_driver.h"
++#include "gmii.h"
++#include "ethtool.h"
++#include "tx.h"
++#include "rx.h"
++#include "efx.h"
++#include "mdio_10g.h"
++#include "falcon.h"
++#include "workarounds.h"
++#include "mac.h"
++
++#define EFX_MAX_MTU (9 * 1024)
++
++/* RX slow fill workqueue. If memory allocation fails in the fast path,
++ * a work item is pushed onto this work queue to retry the allocation later,
++ * to avoid the NIC being starved of RX buffers. Since this is a per cpu
++ * workqueue, there is nothing to be gained in making it per NIC
++ */
++static struct workqueue_struct *refill_workqueue;
+
-+ 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);
++/**************************************************************************
++ *
++ * Configurable values
++ *
++ *************************************************************************/
+
-+ /* 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);
-+}
++/*
++ * Enable large receive offload (LRO) aka soft segment reassembly (SSR)
++ *
++ * This sets the default for new devices. It can be controlled later
++ * using ethtool.
++ */
++static int lro = 1;
++module_param(lro, int, 0644);
++MODULE_PARM_DESC(lro, "Large receive offload acceleration");
+
-+enum latency_range {
-+ lowest_latency = 0,
-+ low_latency = 1,
-+ bulk_latency = 2,
-+ latency_invalid = 255
-+};
++/*
++ * Use separate channels for TX and RX events
++ *
++ * Set this to 1 to use separate channels for TX and RX. It allows us to
++ * apply a higher level of interrupt moderation to TX events.
++ *
++ * This is forced to 0 for MSI interrupt mode as the interrupt vector
++ * is not written
++ */
++static unsigned int separate_tx_and_rx_channels = 1;
+
-+/**
-+ * 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
++/* This is the weight assigned to each of the (per-channel) virtual
++ * NAPI devices.
++ */
++static int napi_weight = 64;
++
++/* This is the time (in jiffies) between invocations of the hardware
++ * monitor, which checks for known hardware bugs and resets the
++ * hardware and driver as necessary.
++ */
++unsigned int efx_monitor_interval = 1 * HZ;
++
++/* This controls whether or not the hardware monitor will trigger a
++ * reset when it detects an error condition.
++ */
++static unsigned int monitor_reset = 1;
++
++/* This controls whether or not the driver will initialise devices
++ * with invalid MAC addresses stored in the EEPROM or flash. If true,
++ * such devices will be initialised with a random locally-generated
++ * MAC address. This allows for loading the sfc_mtd driver to
++ * reprogram the flash, even if the flash contents (including the MAC
++ * address) have previously been erased.
++ */
++static unsigned int allow_bad_hwaddr;
++
++/* Initial interrupt moderation settings. They can be modified after
++ * module load with ethtool.
+ *
-+ * 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)
++ * The default for RX should strike a balance between increasing the
++ * round-trip latency and reducing overhead.
++ */
++static unsigned int rx_irq_mod_usec = 60;
++
++/* Initial interrupt moderation settings. They can be modified after
++ * module load with ethtool.
++ *
++ * This default is chosen to ensure that a 10G link does not go idle
++ * while a TX queue is stopped after it has become full. A queue is
++ * restarted when it drops below half full. The time this takes (assuming
++ * worst case 3 descriptors per packet and 1024 descriptors) is
++ * 512 / 3 * 1.2 = 205 usec.
++ */
++static unsigned int tx_irq_mod_usec = 150;
++
++/* This is the first interrupt mode to try out of:
++ * 0 => MSI-X
++ * 1 => MSI
++ * 2 => legacy
++ */
++static unsigned int interrupt_mode;
++
++/* This is the requested number of CPUs to use for Receive-Side Scaling (RSS),
++ * i.e. the number of CPUs among which we may distribute simultaneous
++ * interrupt handling.
++ *
++ * Cards without MSI-X will only target one CPU via legacy or MSI interrupt.
++ * The default (0) means to assign an interrupt to each package (level II cache)
++ */
++static unsigned int rss_cpus;
++module_param(rss_cpus, uint, 0444);
++MODULE_PARM_DESC(rss_cpus, "Number of CPUs to use for Receive-Side Scaling");
++
++/**************************************************************************
++ *
++ * Utility functions and prototypes
++ *
++ *************************************************************************/
++static void efx_remove_channel(struct efx_channel *channel);
++static void efx_remove_port(struct efx_nic *efx);
++static void efx_fini_napi(struct efx_nic *efx);
++static void efx_fini_channels(struct efx_nic *efx);
++
++#define EFX_ASSERT_RESET_SERIALISED(efx) \
++ do { \
++ if ((efx->state == STATE_RUNNING) || \
++ (efx->state == STATE_RESETTING)) \
++ ASSERT_RTNL(); \
++ } while (0)
++
++/**************************************************************************
++ *
++ * Event queue processing
++ *
++ *************************************************************************/
++
++/* Process channel's event queue
++ *
++ * This function is responsible for processing the event queue of a
++ * single channel. The caller must guarantee that this function will
++ * never be concurrently called more than once on the same channel,
++ * though different channels may be being processed concurrently.
++ */
++static inline int efx_process_channel(struct efx_channel *channel, int rx_quota)
+{
-+ unsigned int retval = itr_setting;
-+ u32 timepassed_us;
-+ u64 bytes_perint;
++ int rxdmaqs;
++ struct efx_rx_queue *rx_queue;
+
-+ if (packets == 0)
-+ goto update_itr_done;
++ if (unlikely(channel->efx->reset_pending != RESET_TYPE_NONE ||
++ !channel->enabled))
++ return rx_quota;
+
++ rxdmaqs = falcon_process_eventq(channel, &rx_quota);
+
-+ /* 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 */
++ /* Deliver last RX packet. */
++ if (channel->rx_pkt) {
++ __efx_rx_packet(channel, channel->rx_pkt,
++ channel->rx_pkt_csummed);
++ channel->rx_pkt = NULL;
++ }
+
-+ 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;
++ efx_flush_lro(channel);
++ efx_rx_strategy(channel);
++
++ /* Refill descriptor rings as necessary */
++ rx_queue = &channel->efx->rx_queue[0];
++ while (rxdmaqs) {
++ if (rxdmaqs & 0x01)
++ efx_fast_push_rx_descriptors(rx_queue);
++ rx_queue++;
++ rxdmaqs >>= 1;
+ }
+
-+update_itr_done:
-+ return retval;
++ return rx_quota;
+}
+
-+static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
++/* Mark channel as finished processing
++ *
++ * Note that since we will not receive further interrupts for this
++ * channel before we finish processing and call the eventq_read_ack()
++ * method, there is no need to use the interrupt hold-off timers.
++ */
++static inline void efx_channel_processed(struct efx_channel *channel)
+{
-+ 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;
++ /* Write to EVQ_RPTR_REG. If a new event arrived in a race
++ * with finishing processing, a new interrupt will be raised.
++ */
++ channel->work_pending = 0;
++ smp_wmb(); /* Ensure channel updated before any new interrupt. */
++ falcon_eventq_read_ack(channel);
++}
+
-+ 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);
-+ }
++/* NAPI poll handler
++ *
++ * NAPI guarantees serialisation of polls of the same device, which
++ * provides the guarantee required by efx_process_channel().
++ */
++static int efx_poll(struct napi_struct *napi, int budget)
++{
++ struct efx_channel *channel =
++ container_of(napi, struct efx_channel, napi_str);
++ struct net_device *napi_dev = channel->napi_dev;
++ int unused;
++ int rx_packets;
+
-+ 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);
-+ }
++ EFX_TRACE(channel->efx, "channel %d NAPI poll executing on CPU %d\n",
++ channel->channel, raw_smp_processor_id());
+
-+ current_itr = max(q_vector->rx_eitr, q_vector->tx_eitr);
++ unused = efx_process_channel(channel, budget);
++ rx_packets = (budget - unused);
+
-+ 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 (rx_packets < budget) {
++ /* There is no race here; although napi_disable() will
++ * only wait for netif_rx_complete(), this isn't a problem
++ * since efx_channel_processed() will have no effect if
++ * interrupts have already been disabled.
++ */
++ netif_rx_complete(napi_dev, napi);
++ efx_channel_processed(channel);
+ }
+
-+ 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 rx_packets;
++}
+
-+ 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;
++/* Process the eventq of the specified channel immediately on this CPU
++ *
++ * Disable hardware generated interrupts, wait for any existing
++ * processing to finish, then directly poll (and ack ) the eventq.
++ * Finally reenable NAPI and interrupts.
++ *
++ * Since we are touching interrupts the caller should hold the suspend lock
++ */
++void efx_process_channel_now(struct efx_channel *channel)
++{
++ struct efx_nic *efx = channel->efx;
+
-+ 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;
++ BUG_ON(!channel->used_flags);
++ BUG_ON(!channel->enabled);
+
-+ r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
-+ if (!q_vector->rxr_count)
-+ return IRQ_HANDLED;
++ /* Disable interrupts and wait for ISRs to complete */
++ falcon_disable_interrupts(efx);
++ if (efx->legacy_irq)
++ synchronize_irq(efx->legacy_irq);
++ if (channel->has_interrupt && channel->irq)
++ synchronize_irq(channel->irq);
+
-+ 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);
++ /* Wait for any NAPI processing to complete */
++ napi_disable(&channel->napi_str);
+
-+ return IRQ_HANDLED;
++ /* Poll the channel */
++ (void) efx_process_channel(channel, efx->type->evq_size);
++
++ /* Ack the eventq. This may cause an interrupt to be generated
++ * when they are reenabled */
++ efx_channel_processed(channel);
++
++ napi_enable(&channel->napi_str);
++ falcon_enable_interrupts(efx);
+}
+
-+static irqreturn_t ixgbe_msix_clean_many(int irq, void *data)
++/* Create event queue
++ * Event queue memory allocations are done only once. If the channel
++ * is reset, the memory buffer will be reused; this guards against
++ * errors during channel reset and also simplifies interrupt handling.
++ */
++static int efx_probe_eventq(struct efx_channel *channel)
+{
-+ 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)
++ EFX_LOG(channel->efx, "chan %d create event queue\n", channel->channel);
++
++ return falcon_probe_eventq(channel);
++}
++
++/* Prepare channel's event queue */
++static int efx_init_eventq(struct efx_channel *channel)
+{
-+ 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;
++ EFX_LOG(channel->efx, "chan %d init event queue\n", channel->channel);
++
++ channel->eventq_read_ptr = 0;
++
++ return falcon_init_eventq(channel);
+}
+
-+static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
-+ int r_idx)
++static void efx_fini_eventq(struct efx_channel *channel)
+{
-+ 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;
++ EFX_LOG(channel->efx, "chan %d fini event queue\n", channel->channel);
++
++ falcon_fini_eventq(channel);
+}
+
- /**
-- * 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)
++static void efx_remove_eventq(struct efx_channel *channel)
+{
-+ 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;
++ EFX_LOG(channel->efx, "chan %d remove event queue\n", channel->channel);
+
-+ /* 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;
++ falcon_remove_eventq(channel);
++}
++
++/**************************************************************************
++ *
++ * Channel handling
++ *
++ *************************************************************************/
++
++/* Setup per-NIC RX buffer parameters.
++ * Calculate the rx buffer allocation parameters required to support
++ * the current MTU, including padding for header alignment and overruns.
++ */
++static void efx_calc_rx_buffer_params(struct efx_nic *efx)
++{
++ unsigned int order, len;
++
++ len = (max(EFX_PAGE_IP_ALIGN, NET_IP_ALIGN) +
++ EFX_MAX_FRAME_LEN(efx->net_dev->mtu) +
++ efx->type->rx_buffer_padding);
++
++ /* Calculate page-order */
++ for (order = 0; ((1u << order) * PAGE_SIZE) < len; ++order)
++ ;
++
++ efx->rx_buffer_len = len;
++ efx->rx_buffer_order = order;
++}
++
++static int efx_probe_channel(struct efx_channel *channel)
++{
++ struct efx_tx_queue *tx_queue;
++ struct efx_rx_queue *rx_queue;
++ int rc;
++
++ EFX_LOG(channel->efx, "creating channel %d\n", channel->channel);
++
++ rc = efx_probe_eventq(channel);
++ if (rc)
++ goto fail1;
++
++ efx_for_each_channel_tx_queue(tx_queue, channel) {
++ rc = efx_probe_tx_queue(tx_queue);
++ if (rc)
++ goto fail2;
+ }
-
-- 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--;
++
++ efx_for_each_channel_rx_queue(rx_queue, channel) {
++ rc = efx_probe_rx_queue(rx_queue);
++ if (rc)
++ goto fail3;
++ }
++
++ channel->n_rx_frm_trunc = 0;
++
++ return 0;
++
++ fail3:
++ efx_for_each_channel_rx_queue(rx_queue, channel)
++ efx_remove_rx_queue(rx_queue);
++ fail2:
++ efx_for_each_channel_tx_queue(tx_queue, channel)
++ efx_remove_tx_queue(tx_queue);
++ fail1:
++ return rc;
++}
++
++
++/* Channels are shutdown and reinitialised whilst the NIC is running
++ * to propagate configuration changes (mtu, checksum offload), or
++ * to clear hardware error conditions
++ */
++static int efx_init_channels(struct efx_nic *efx)
++{
++ struct efx_tx_queue *tx_queue;
++ struct efx_rx_queue *rx_queue;
++ struct efx_channel *channel;
++ int rc = 0;
++
++ efx_calc_rx_buffer_params(efx);
++
++ /* Initialise the channels */
++ efx_for_each_channel(channel, efx) {
++ EFX_LOG(channel->efx, "init chan %d\n", channel->channel);
++
++ rc = efx_init_eventq(channel);
++ if (rc)
++ goto err;
++
++ efx_for_each_channel_tx_queue(tx_queue, channel) {
++ rc = efx_init_tx_queue(tx_queue);
++ if (rc)
++ goto err;
+ }
++
++ /* The rx buffer allocation strategy is MTU dependent */
++ efx_rx_strategy(channel);
++
++ efx_for_each_channel_rx_queue(rx_queue, channel) {
++ rc = efx_init_rx_queue(rx_queue);
++ if (rc)
++ goto err;
++ }
++
++ WARN_ON(channel->rx_pkt != NULL);
++ efx_rx_strategy(channel);
+ }
-+ 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;
++
++ return 0;
++
++ err:
++ EFX_ERR(efx, "failed to initialise channel %d\n",
++ channel ? channel->channel : -1);
++ efx_fini_channels(efx);
++ return rc;
+}
+
-+/**
-+ * ixgbe_request_msix_irqs - Initialize MSI-X interrupts
-+ * @adapter: board private structure
++/* This enables event queue processing and packet transmission.
+ *
-+ * ixgbe_request_msix_irqs allocates MSI-X vectors and requests
-+ * interrupts from the kernel.
-+ **/
-+static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
++ * Note that this function is not allowed to fail, since that would
++ * introduce too much complexity into the suspend/resume path.
++ */
++static void efx_start_channel(struct efx_channel *channel)
+{
-+ struct net_device *netdev = adapter->netdev;
-+ irqreturn_t (*handler)(int, void *);
-+ int i, vector, q_vectors, err;
++ struct efx_rx_queue *rx_queue;
+
-+ /* Decrement for Other and TCP Timer vectors */
-+ q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
++ EFX_LOG(channel->efx, "starting chan %d\n", channel->channel);
+
-+ /* Map the Tx/Rx rings to the vectors we were allotted. */
-+ err = ixgbe_map_rings_to_vectors(adapter, q_vectors);
-+ if (err)
-+ goto out;
++ if (!(channel->efx->net_dev->flags & IFF_UP))
++ netif_napi_add(channel->napi_dev, &channel->napi_str,
++ efx_poll, napi_weight);
+
-+#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)
++ channel->work_pending = 0;
++ channel->enabled = 1;
++ smp_wmb(); /* ensure channel updated before first interrupt */
++
++ napi_enable(&channel->napi_str);
++
++ /* Load up RX descriptors */
++ efx_for_each_channel_rx_queue(rx_queue, channel)
++ efx_fast_push_rx_descriptors(rx_queue);
++}
++
++/* This disables event queue processing and packet transmission.
++ * This function does not guarantee that all queue processing
++ * (e.g. RX refill) is complete.
++ */
++static void efx_stop_channel(struct efx_channel *channel)
+{
-+ 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];
++ struct efx_rx_queue *rx_queue;
+
-+ 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);
++ if (!channel->enabled)
++ return;
+
-+ current_itr = max(q_vector->rx_eitr, q_vector->tx_eitr);
++ EFX_LOG(channel->efx, "stop chan %d\n", channel->channel);
+
-+ 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;
++ channel->enabled = 0;
++ napi_disable(&channel->napi_str);
++
++ /* Ensure that any worker threads have exited or will be no-ops */
++ efx_for_each_channel_rx_queue(rx_queue, channel) {
++ spin_lock_bh(&rx_queue->add_lock);
++ spin_unlock_bh(&rx_queue->add_lock);
+ }
++}
+
-+ 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);
++static void efx_fini_channels(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++ struct efx_tx_queue *tx_queue;
++ struct efx_rx_queue *rx_queue;
++
++ EFX_ASSERT_RESET_SERIALISED(efx);
++ BUG_ON(efx->port_enabled);
++
++ efx_for_each_channel(channel, efx) {
++ EFX_LOG(channel->efx, "shut down chan %d\n", channel->channel);
++
++ efx_for_each_channel_rx_queue(rx_queue, channel)
++ efx_fini_rx_queue(rx_queue);
++ efx_for_each_channel_tx_queue(tx_queue, channel)
++ efx_fini_tx_queue(tx_queue);
+ }
+
-+ return;
++ /* Do the event queues last so that we can handle flush events
++ * for all DMA queues. */
++ efx_for_each_channel(channel, efx) {
++ EFX_LOG(channel->efx, "shut down evq %d\n", channel->channel);
++
++ efx_fini_eventq(channel);
++ }
+}
+
-+static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter);
++static void efx_remove_channel(struct efx_channel *channel)
++{
++ struct efx_tx_queue *tx_queue;
++ struct efx_rx_queue *rx_queue;
+
- /**
-- * 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);
++ EFX_LOG(channel->efx, "destroy chan %d\n", channel->channel);
+
++ efx_for_each_channel_rx_queue(rx_queue, channel)
++ efx_remove_rx_queue(rx_queue);
++ efx_for_each_channel_tx_queue(tx_queue, channel)
++ efx_remove_tx_queue(tx_queue);
++ efx_remove_eventq(channel);
+
-+ 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)
++ channel->used_flags = 0;
++}
++
++void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay)
+{
-+ int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
++ queue_delayed_work(refill_workqueue, &rx_queue->work, delay);
++}
+
-+ 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;
++/**************************************************************************
++ *
++ * Port handling
++ *
++ **************************************************************************/
++
++/* This ensures that the kernel is kept informed (via
++ * netif_carrier_on/off) of the link status, and also maintains the
++ * link status's stop on the port's TX queue.
++ */
++static void efx_link_status_changed(struct efx_nic *efx)
++{
++ int carrier_ok;
++
++ /* SFC Bug 5356: A net_dev notifier is registered, so we must ensure
++ * that no events are triggered between unregister_netdev() and the
++ * driver unloading. A more general condition is that NETDEV_CHANGE
++ * can only be generated between NETDEV_UP and NETDEV_DOWN */
++ if (!netif_running(efx->net_dev))
++ return;
++
++ carrier_ok = netif_carrier_ok(efx->net_dev) ? 1 : 0;
++ if (efx->link_up != carrier_ok) {
++ efx->n_link_state_changes++;
++
++ if (efx->link_up)
++ netif_carrier_on(efx->net_dev);
++ else
++ netif_carrier_off(efx->net_dev);
++ }
++
++ /* Status message for kernel log */
++ if (efx->link_up) {
++ struct mii_if_info *gmii = &efx->mii;
++ unsigned adv, lpa;
++ /* NONE here means direct XAUI from the controller, with no
++ * MDIO-attached device we can query. */
++ if (efx->phy_type != PHY_TYPE_NONE) {
++ adv = gmii_advertised(gmii);
++ lpa = gmii_lpa(gmii);
++ } else {
++ lpa = GM_LPA_10000 | LPA_DUPLEX;
++ adv = lpa;
++ }
++ EFX_INFO(efx, "link up at %dMbps %s-duplex "
++ "(adv %04x lpa %04x) (MTU %d)%s\n",
++ (efx->link_options & GM_LPA_10000 ? 10000 :
++ (efx->link_options & GM_LPA_1000 ? 1000 :
++ (efx->link_options & GM_LPA_100 ? 100 :
++ 10))),
++ (efx->link_options & GM_LPA_DUPLEX ?
++ "full" : "half"),
++ adv, lpa,
++ efx->net_dev->mtu,
++ (efx->promiscuous ? " [PROMISC]" : ""));
++ } else {
++ EFX_INFO(efx, "link down\n");
+ }
++
+}
+
- /**
- * 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);
++/* This call reinitialises the MAC to pick up new PHY settings. The
++ * caller must hold the mac_lock */
++static void __efx_reconfigure_port(struct efx_nic *efx)
++{
++ WARN_ON(!mutex_is_locked(&efx->mac_lock));
++
++ EFX_LOG(efx, "reconfiguring MAC from PHY settings on CPU %d\n",
++ raw_smp_processor_id());
++
++ falcon_reconfigure_xmac(efx);
++
++ /* Inform kernel of loss/gain of carrier */
++ efx_link_status_changed(efx);
++}
++
++/* Reinitialise the MAC to pick up new PHY settings, even if the port is
++ * disabled. */
++void efx_reconfigure_port(struct efx_nic *efx)
++{
++ EFX_ASSERT_RESET_SERIALISED(efx);
++
++ mutex_lock(&efx->mac_lock);
++ __efx_reconfigure_port(efx);
++ mutex_unlock(&efx->mac_lock);
++}
++
++/* Asynchronous efx_reconfigure_port work item. To speed up efx_flush_all()
++ * we don't efx_reconfigure_port() if the port is disabled. Care is taken
++ * in efx_stop_all() and efx_start_port() to prevent PHY events being lost */
++static void efx_reconfigure_work(struct work_struct *data)
++{
++ struct efx_nic *efx = container_of(data, struct efx_nic,
++ reconfigure_work);
++
++ mutex_lock(&efx->mac_lock);
++ if (efx->port_enabled)
++ __efx_reconfigure_port(efx);
++ mutex_unlock(&efx->mac_lock);
++}
++
++static int efx_probe_port(struct efx_nic *efx)
++{
++ int rc;
++
++ EFX_LOG(efx, "create port\n");
++
++ /* Connect up MAC/PHY operations table and read MAC address */
++ rc = falcon_probe_port(efx);
++ if (rc)
++ goto err;
++
++ /* Sanity check MAC address */
++ if (is_valid_ether_addr(efx->mac_address)) {
++ memcpy(efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN);
+ } 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;
++ DECLARE_MAC_BUF(mac);
+
-+ 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]));
++ EFX_ERR(efx, "invalid MAC address %s\n",
++ print_mac(mac, efx->mac_address));
++ if (!allow_bad_hwaddr) {
++ rc = -EINVAL;
++ goto err;
+ }
++ random_ether_addr(efx->net_dev->dev_addr);
++ EFX_INFO(efx, "using locally-generated MAC %s\n",
++ print_mac(mac, efx->net_dev->dev_addr));
++ }
+
-+ 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);
++ return 0;
++
++ err:
++ efx_remove_port(efx);
++ return rc;
++}
++
++static int efx_init_port(struct efx_nic *efx)
++{
++ int rc;
++
++ EFX_LOG(efx, "init port\n");
++
++ /* Initialise the MAC and PHY */
++ rc = falcon_init_xmac(efx);
++ if (rc)
++ return rc;
++
++ efx->port_initialized = 1;
++
++ /* Reconfigure port to program MAC registers */
++ falcon_reconfigure_xmac(efx);
++
++ return 0;
++}
++
++/* Allow efx_reconfigure_port() to be scheduled, and close the window
++ * between efx_stop_port and efx_flush_all whereby a previously scheduled
++ * efx_reconfigure_port() may have been cancelled */
++static void efx_start_port(struct efx_nic *efx)
++{
++ EFX_LOG(efx, "start port\n");
++ BUG_ON(efx->port_enabled);
++
++ mutex_lock(&efx->mac_lock);
++ efx->port_enabled = 1;
++ __efx_reconfigure_port(efx);
++ mutex_unlock(&efx->mac_lock);
++}
++
++/* Prevent efx_reconfigure_work and efx_monitor() from executing, and
++ * efx_set_multicast_list() from scheduling efx_reconfigure_work.
++ * efx_reconfigure_work can still be scheduled via NAPI processing
++ * until efx_flush_all() is called */
++static void efx_stop_port(struct efx_nic *efx)
++{
++ EFX_LOG(efx, "stop port\n");
++
++ mutex_lock(&efx->mac_lock);
++ efx->port_enabled = 0;
++ mutex_unlock(&efx->mac_lock);
++
++ /* Serialise against efx_set_multicast_list() */
++ if (NET_DEV_REGISTERED(efx)) {
++ netif_tx_lock_bh(efx->net_dev);
++ netif_tx_unlock_bh(efx->net_dev);
+ }
- }
-
- /**
-@@ -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);
++static void efx_fini_port(struct efx_nic *efx)
++{
++ EFX_LOG(efx, "shut down port\n");
+
-+ 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.
++ if (!efx->port_initialized)
++ return;
++
++ falcon_fini_xmac(efx);
++ efx->port_initialized = 0;
++
++ efx->link_up = 0;
++ efx_link_status_changed(efx);
++}
++
++static void efx_remove_port(struct efx_nic *efx)
++{
++ EFX_LOG(efx, "destroying port\n");
++
++ falcon_remove_port(efx);
++}
++
++/**************************************************************************
++ *
++ * NIC handling
++ *
++ **************************************************************************/
++
++/* This configures the PCI device to enable I/O and DMA. */
++static int efx_init_io(struct efx_nic *efx)
++{
++ struct pci_dev *pci_dev = efx->pci_dev;
++ dma_addr_t dma_mask = efx->type->max_dma_mask;
++ int rc;
++
++ EFX_LOG(efx, "initialising I/O\n");
++
++ rc = pci_enable_device(pci_dev);
++ if (rc) {
++ EFX_ERR(efx, "failed to enable PCI device\n");
++ goto fail1;
++ }
++
++ pci_set_master(pci_dev);
++
++ /* Set the PCI DMA mask. Try all possibilities from our
++ * genuine mask down to 32 bits, because some architectures
++ * (e.g. x86_64 with iommu_sac_force set) will allow 40 bit
++ * masks event though they reject 46 bit masks.
++ */
++ while (dma_mask > 0x7fffffffUL) {
++ if (pci_dma_supported(pci_dev, dma_mask) &&
++ ((rc = pci_set_dma_mask(pci_dev, dma_mask)) == 0))
++ break;
++ dma_mask >>= 1;
++ }
++ if (rc) {
++ EFX_ERR(efx, "could not find a suitable DMA mask\n");
++ goto fail2;
++ }
++ EFX_LOG(efx, "using DMA mask %llx\n", (unsigned long long) dma_mask);
++ rc = pci_set_consistent_dma_mask(pci_dev, dma_mask);
++ if (rc) {
++ /* pci_set_consistent_dma_mask() is not *allowed* to
++ * fail with a mask that pci_set_dma_mask() accepted,
++ * but just in case...
+ */
-+ 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);
++ EFX_ERR(efx, "failed to set consistent DMA mask\n");
++ goto fail2;
+ }
-
-- /* 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;
++ efx->membase_phys = pci_resource_start(efx->pci_dev,
++ efx->type->mem_bar);
++ rc = pci_request_region(pci_dev, efx->type->mem_bar, "sfc");
++ if (rc) {
++ EFX_ERR(efx, "request for memory BAR failed\n");
++ rc = -EIO;
++ goto fail3;
+ }
++ efx->membase = ioremap_nocache(efx->membase_phys,
++ efx->type->mem_map_size);
++ if (!efx->membase) {
++ EFX_ERR(efx, "could not map memory BAR %d at %lx+%x\n",
++ efx->type->mem_bar, efx->membase_phys,
++ efx->type->mem_map_size);
++ rc = -ENOMEM;
++ goto fail4;
++ }
++ EFX_LOG(efx, "memory BAR %u at %lx+%x (virtual %p)\n",
++ efx->type->mem_bar, efx->membase_phys, efx->type->mem_map_size,
++ efx->membase);
+
-+ 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)
++ return 0;
++
++ fail4:
++ release_mem_region(efx->membase_phys, efx->type->mem_map_size);
++ fail3:
++ efx->membase_phys = 0UL;
++ fail2:
++ pci_disable_device(efx->pci_dev);
++ fail1:
++ return rc;
++}
++
++static void efx_fini_io(struct efx_nic *efx)
+{
-+ int q_idx;
-+ struct ixgbe_q_vector *q_vector;
-+ int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
++ EFX_LOG(efx, "shutting down I/O\n");
+
-+ /* legacy and MSI only use one vector */
-+ if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
-+ q_vectors = 1;
++ if (efx->membase) {
++ iounmap(efx->membase);
++ efx->membase = NULL;
++ }
+
-+ 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);
++ if (efx->membase_phys) {
++ pci_release_region(efx->pci_dev, efx->type->mem_bar);
++ efx->membase_phys = 0UL;
+ }
++
++ pci_disable_device(efx->pci_dev);
+}
+
-+static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter)
++/* Probe the number and type of interrupts we are able to obtain. */
++static void efx_probe_interrupts(struct efx_nic *efx)
+{
-+ int q_idx;
-+ struct ixgbe_q_vector *q_vector;
-+ int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
++ int max_channel = efx->type->phys_addr_channels - 1;
++ struct msix_entry xentries[EFX_MAX_CHANNELS];
++ int rc, i;
+
-+ /* legacy and MSI only use one vector */
-+ if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
-+ q_vectors = 1;
++ if (efx->interrupt_mode == EFX_INT_MODE_MSIX) {
++ BUG_ON(!pci_find_capability(efx->pci_dev, PCI_CAP_ID_MSIX));
+
-+ 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);
++ efx->rss_queues = rss_cpus ? rss_cpus : num_online_cpus();
++ efx->rss_queues = min(efx->rss_queues, max_channel + 1);
++ efx->rss_queues = min(efx->rss_queues, EFX_MAX_CHANNELS);
++
++ /* Request maximum number of MSI interrupts, and fill out
++ * the channel interrupt information the allowed allocation */
++ for (i = 0; i < efx->rss_queues; i++)
++ xentries[i].entry = i;
++ rc = pci_enable_msix(efx->pci_dev, xentries, efx->rss_queues);
++ if (rc > 0) {
++ EFX_BUG_ON_PARANOID(rc >= efx->rss_queues);
++ efx->rss_queues = rc;
++ rc = pci_enable_msix(efx->pci_dev, xentries,
++ efx->rss_queues);
++ }
++
++ if (rc == 0) {
++ for (i = 0; i < efx->rss_queues; i++) {
++ efx->channel[i].has_interrupt = 1;
++ efx->channel[i].irq = xentries[i].vector;
++ }
++ } else {
++ /* Fall back to single channel MSI */
++ efx->interrupt_mode = EFX_INT_MODE_MSI;
++ EFX_ERR(efx, "could not enable MSI-X\n");
++ }
++ }
++
++ /* Try single interrupt MSI */
++ if (efx->interrupt_mode == EFX_INT_MODE_MSI) {
++ efx->rss_queues = 1;
++ rc = pci_enable_msi(efx->pci_dev);
++ if (rc == 0) {
++ efx->channel[0].irq = efx->pci_dev->irq;
++ efx->channel[0].has_interrupt = 1;
++ } else {
++ EFX_ERR(efx, "could not enable MSI\n");
++ efx->interrupt_mode = EFX_INT_MODE_LEGACY;
++ }
++ }
++
++ /* Assume legacy interrupts */
++ if (efx->interrupt_mode == EFX_INT_MODE_LEGACY) {
++ efx->rss_queues = 1;
++ /* Every channel is interruptible */
++ for (i = 0; i < EFX_MAX_CHANNELS; i++)
++ efx->channel[i].has_interrupt = 1;
++ efx->legacy_irq = efx->pci_dev->irq;
+ }
+}
+
- 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);
++static void efx_remove_interrupts(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++
++ /* Remove MSI/MSI-X interrupts */
++ efx_for_each_channel_with_interrupt(channel, efx)
++ channel->irq = 0;
++ pci_disable_msi(efx->pci_dev);
++ pci_disable_msix(efx->pci_dev);
++
++ /* Remove legacy interrupt */
++ efx->legacy_irq = 0;
++}
++
++/* Select number of used resources
++ * Should be called after probe_interrupts()
++ */
++static void efx_select_used(struct efx_nic *efx)
++{
++ struct efx_tx_queue *tx_queue;
++ struct efx_rx_queue *rx_queue;
++ int i;
++
++ /* TX queues. One per port per channel with TX capability
++ * (more than one per port won't work on Linux, due to out
++ * of order issues... but will be fine on Solaris)
++ */
++ tx_queue = &efx->tx_queue[0];
++
++ /* Perform this for each channel with TX capabilities.
++ * At the moment, we only support a single TX queue
++ */
++ tx_queue->used = 1;
++ if ((!EFX_INT_MODE_USE_MSI(efx)) && separate_tx_and_rx_channels)
++ tx_queue->channel = &efx->channel[1];
++ else
++ tx_queue->channel = &efx->channel[0];
++ tx_queue->channel->used_flags |= EFX_USED_BY_TX;
++ tx_queue++;
++
++ /* RX queues. Each has a dedicated channel. */
++ for (i = 0; i < EFX_MAX_RX_QUEUES; i++) {
++ rx_queue = &efx->rx_queue[i];
++
++ if (i < efx->rss_queues) {
++ rx_queue->used = 1;
++ /* If we allow multiple RX queues per channel
++ * we need to decide that here
++ */
++ rx_queue->channel = &efx->channel[rx_queue->queue];
++ rx_queue->channel->used_flags |= EFX_USED_BY_RX;
++ rx_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);
++static int efx_probe_nic(struct efx_nic *efx)
++{
++ int rc;
+
- 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
++ EFX_LOG(efx, "creating NIC\n");
++
++ /* Carry out hardware-type specific initialisation */
++ rc = falcon_probe_nic(efx);
++ if (rc)
++ return rc;
++
++ /* Determine the number of channels and RX queues by trying to hook
++ * in MSI-X interrupts. */
++ efx_probe_interrupts(efx);
++
++ /* Determine number of RX queues and TX queues */
++ efx_select_used(efx);
++
++ /* Initialise the interrupt moderation settings */
++ efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec);
++
++ return 0;
++}
++
++static void efx_remove_nic(struct efx_nic *efx)
++{
++ EFX_LOG(efx, "destroying NIC\n");
++
++ efx_remove_interrupts(efx);
++ falcon_remove_nic(efx);
++}
++
++/**************************************************************************
+ *
-+ * 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);
++ * NIC startup/shutdown
++ *
++ *************************************************************************/
++
++static int efx_probe_all(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++ int rc;
++
++ /* Create NIC */
++ rc = efx_probe_nic(efx);
++ if (rc) {
++ EFX_ERR(efx, "failed to create NIC\n");
++ goto fail1;
+ }
-+#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)
++ /* Create port */
++ rc = efx_probe_port(efx);
++ if (rc) {
++ EFX_ERR(efx, "failed to create port\n");
++ goto fail2;
++ }
++
++ /* Create channels */
++ efx_for_each_channel(channel, efx) {
++ rc = efx_probe_channel(channel);
++ if (rc) {
++ EFX_ERR(efx, "failed to create channel %d\n",
++ channel->channel);
++ goto fail3;
++ }
++ }
++
++ return 0;
++
++ fail3:
++ efx_for_each_channel(channel, efx)
++ efx_remove_channel(channel);
++ efx_remove_port(efx);
++ fail2:
++ efx_remove_nic(efx);
++ fail1:
++ return rc;
++}
++
++/* Called after previous invocation(s) of efx_stop_all, restarts the
++ * port, kernel transmit queue, NAPI processing and hardware interrupts,
++ * and ensures that the port is scheduled to be reconfigured.
++ * This function is safe to call multiple times when the NIC is in any
++ * state. */
++static void efx_start_all(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++
++ EFX_ASSERT_RESET_SERIALISED(efx);
++
++ /* Check that it is appropriate to restart the interface. All
++ * of these flags are safe to read under just the rtnl lock */
++ if (efx->port_enabled)
++ return;
++ if ((efx->state != STATE_RUNNING) && (efx->state != STATE_INIT))
++ return;
++ if (NET_DEV_REGISTERED(efx) && !netif_running(efx->net_dev))
++ return;
++
++ /* Mark the port as enabled so port reconfigurations can start, then
++ * restart the transmit interface early so the watchdog timer stops */
++ efx_start_port(efx);
++ efx_wake_queue(efx);
++
++ efx_for_each_channel(channel, efx)
++ efx_start_channel(channel);
++
++ falcon_enable_interrupts(efx);
++
++ /* Start hardware monitor if we're in RUNNING */
++ if (efx->state == STATE_RUNNING)
++ queue_delayed_work(efx->workqueue, &efx->monitor_work,
++ efx_monitor_interval);
++}
++
++/* Flush all delayed work. Should only be called when no more delayed work
++ * will be scheduled. This doesn't flush pending online resets (efx_reset),
++ * since we're holding the rtnl_lock at this point. */
++static void efx_flush_all(struct efx_nic *efx)
+{
-+ int err, vector_threshold;
++ struct efx_rx_queue *rx_queue;
+
-+ /* 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;
++ /* Make sure the hardware monitor is stopped */
++ cancel_delayed_work_sync(&efx->monitor_work);
+
-+ /* 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;
++ /* Ensure that all RX slow refills are complete. */
++ efx_for_each_rx_queue(rx_queue, efx) {
++ cancel_delayed_work_sync(&rx_queue->work);
+ }
+
-+ 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;
++ /* Stop scheduled port reconfigurations */
++ cancel_work_sync(&efx->reconfigure_work);
++
++}
++
++/* Quiesce hardware and software without bringing the link down.
++ * Safe to call multiple times, when the nic and interface is in any
++ * state. The caller is guaranteed to subsequently be in a position
++ * to modify any hardware and software state they see fit without
++ * taking locks. */
++static void efx_stop_all(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++
++ EFX_ASSERT_RESET_SERIALISED(efx);
++
++ /* port_enabled can be read safely under the rtnl lock */
++ if (!efx->port_enabled)
++ return;
++
++ /* Disable interrupts and wait for ISR to complete */
++ falcon_disable_interrupts(efx);
++ if (efx->legacy_irq)
++ synchronize_irq(efx->legacy_irq);
++ efx_for_each_channel_with_interrupt(channel, efx)
++ if (channel->irq)
++ synchronize_irq(channel->irq);
++
++ /* Stop all NAPI processing and synchronous rx refills */
++ efx_for_each_channel(channel, efx)
++ efx_stop_channel(channel);
++
++ /* Stop all asynchronous port reconfigurations. Since all
++ * event processing has already been stopped, there is no
++ * window to loose phy events */
++ efx_stop_port(efx);
++
++ /* Flush reconfigure_work, refill_workqueue, monitor_work */
++ efx_flush_all(efx);
++
++ /* Isolate the MAC from the TX and RX engines, so that queue
++ * flushes will complete in a timely fashion. */
++ falcon_deconfigure_mac_wrapper(efx);
++ falcon_drain_tx_fifo(efx);
++
++ /* Stop the kernel transmit interface late, so the watchdog
++ * timer isn't ticking over the flush */
++ efx_stop_queue(efx);
++ if (NET_DEV_REGISTERED(efx)) {
++ netif_tx_lock_bh(efx->net_dev);
++ netif_tx_unlock_bh(efx->net_dev);
+ }
+}
+
-+static void __devinit ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
++static void efx_remove_all(struct efx_nic *efx)
+{
-+ int nrq, ntq;
-+ int feature_mask = 0, rss_i, rss_m;
++ struct efx_channel *channel;
+
-+ /* 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;
++ efx_for_each_channel(channel, efx)
++ efx_remove_channel(channel);
++ efx_remove_port(efx);
++ efx_remove_nic(efx);
++}
+
-+ 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;
-+ }
++/* A convinience function to safely flush all the queues */
++int efx_flush_queues(struct efx_nic *efx)
++{
++ int rc;
+
-+ 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;
++ EFX_ASSERT_RESET_SERIALISED(efx);
++
++ efx_stop_all(efx);
++
++ efx_fini_channels(efx);
++ rc = efx_init_channels(efx);
++ if (rc) {
++ efx_schedule_reset(efx, RESET_TYPE_DISABLE);
++ return rc;
+ }
+
-+ adapter->num_rx_queues = nrq;
-+ adapter->num_tx_queues = ntq;
++ efx_start_all(efx);
++
++ return 0;
+}
+
-+/**
-+ * 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)
++ * Interrupt moderation
++ *
++ **************************************************************************/
++
++/* Set interrupt moderation parameters */
++void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs)
+{
-+ /* 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;
++ struct efx_tx_queue *tx_queue;
++ struct efx_rx_queue *rx_queue;
+
-+ /* 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;
++ EFX_ASSERT_RESET_SERIALISED(efx);
++
++ efx_for_each_tx_queue(tx_queue, efx)
++ tx_queue->channel->irq_moderation = tx_usecs;
++
++ efx_for_each_rx_queue(rx_queue, efx)
++ rx_queue->channel->irq_moderation = rx_usecs;
++}
++
++/**************************************************************************
++ *
++ * Hardware monitor
++ *
++ **************************************************************************/
++
++/* Run periodically off the general workqueue. Serialised against
++ * efx_reconfigure_port via the mac_lock */
++static void efx_monitor(struct work_struct *data)
++{
++ struct efx_nic *efx = container_of(data, struct efx_nic,
++ monitor_work.work);
++ int rc = 0;
++
++ EFX_TRACE(efx, "hardware monitor executing on CPU %d\n",
++ raw_smp_processor_id());
++
++
++ /* If the mac_lock is already held then it is likely a port
++ * reconfiguration is already in place, which will likely do
++ * most of the work of check_hw() anyway. */
++ if (!mutex_trylock(&efx->mac_lock)) {
++ queue_delayed_work(efx->workqueue, &efx->monitor_work,
++ efx_monitor_interval);
++ return;
++ }
++
++ if (efx->port_enabled)
++ rc = falcon_check_xmac(efx);
++ mutex_unlock(&efx->mac_lock);
++
++ if (rc) {
++ if (monitor_reset) {
++ EFX_ERR(efx, "hardware monitor detected a fault: "
++ "triggering reset\n");
++ efx_schedule_reset(efx, RESET_TYPE_MONITOR);
++ } else {
++ EFX_ERR(efx, "hardware monitor detected a fault, "
++ "skipping reset\n");
+ }
-+ break;
-+ default:
-+ break;
+ }
++
++ queue_delayed_work(efx->workqueue, &efx->monitor_work,
++ efx_monitor_interval);
+}
+
- /**
- * 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;
++/**************************************************************************
++ *
++ * ioctls
++ *
++ *************************************************************************/
++
++/* Net device ioctl
++ * Context: process, rtnl_lock() held.
++ */
++static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
++{
++ struct efx_nic *efx = net_dev->priv;
++
++ EFX_ASSERT_RESET_SERIALISED(efx);
++
++ return generic_mii_ioctl(&efx->mii, if_mii(ifr), cmd, NULL);
++}
++
++/**************************************************************************
++ *
++ * NAPI interface
++ *
++ **************************************************************************/
++
++static int efx_init_napi(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++ int rc;
++
++ efx_for_each_channel(channel, efx) {
++ channel->napi_dev = efx->net_dev;
++ rc = efx_lro_init(&channel->lro_mgr, efx);
++ if (rc)
++ goto err;
+ }
- 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;
++ return 0;
++ err:
++ efx_fini_napi(efx);
++ return rc;
++}
++
++static void efx_fini_napi(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++
++ efx_for_each_channel(channel, efx) {
++ efx_lro_fini(&channel->lro_mgr);
++ channel->napi_dev = NULL;
+ }
++}
+
-+ ixgbe_cache_ring_register(adapter);
++/**************************************************************************
++ *
++ * Kernel netpoll interface
++ *
++ *************************************************************************/
+
-+ return 0;
++#ifdef CONFIG_NET_POLL_CONTROLLER
+
-+err_rx_ring_allocation:
-+ kfree(adapter->tx_ring);
-+err_tx_ring_allocation:
-+ return -ENOMEM;
++/* Although in the common case interrupts will be disabled, this is not
++ * guaranteed. However, all our work happens inside the NAPI callback,
++ * so no locking is required.
++ */
++static void efx_netpoll(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++ struct efx_channel *channel;
++
++ efx_for_each_channel_with_interrupt(channel, efx)
++ efx_schedule_channel(channel);
+}
+
-+/**
-+ * ixgbe_set_interrupt_capability - set MSI-X or MSI if supported
-+ * @adapter: board private structure to initialize
++#endif
++
++/**************************************************************************
+ *
-+ * 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)
++ * Kernel net device interface
++ *
++ *************************************************************************/
++
++/* Context: process, rtnl_lock() held. */
++static int efx_net_open(struct net_device *net_dev)
+{
-+ int err = 0;
-+ int vector, v_budget;
++ struct efx_nic *efx = net_dev->priv;
++ EFX_ASSERT_RESET_SERIALISED(efx);
+
-+ /*
-+ * 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;
++ EFX_LOG(efx, "opening device %s on CPU %d\n", net_dev->name,
++ raw_smp_processor_id());
+
-+ /*
-+ * 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);
++ efx_start_all(efx);
++ return 0;
++}
+
-+ /* 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;
-+ }
++/* Context: process, rtnl_lock() held.
++ * Note that the kernel will ignore our return code; this method
++ * should really be a void.
++ */
++static int efx_net_stop(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++ int rc;
+
-+ goto try_msi;
++ EFX_LOG(efx, "closing %s on CPU %d\n", net_dev->name,
++ raw_smp_processor_id());
++
++ /* Stop the device and flush all the channels */
++ efx_stop_all(efx);
++ efx_fini_channels(efx);
++ rc = efx_init_channels(efx);
++ if (rc)
++ efx_schedule_reset(efx, RESET_TYPE_DISABLE);
++
++ return 0;
++}
++
++/* Context: process, dev_base_lock held, non-blocking. */
++static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++ struct efx_mac_stats *mac_stats = &efx->mac_stats;
++ struct net_device_stats *stats = &net_dev->stats;
++
++ if (!spin_trylock(&efx->stats_lock))
++ return stats;
++ if (efx->state == STATE_RUNNING) {
++ falcon_update_stats_xmac(efx);
++ falcon_update_nic_stats(efx);
+ }
++ spin_unlock(&efx->stats_lock);
+
-+ for (vector = 0; vector < v_budget; vector++)
-+ adapter->msix_entries[vector].entry = vector;
++ stats->rx_packets = mac_stats->rx_packets;
++ stats->tx_packets = mac_stats->tx_packets;
++ stats->rx_bytes = mac_stats->rx_bytes;
++ stats->tx_bytes = mac_stats->tx_bytes;
++ stats->multicast = mac_stats->rx_multicast;
++ stats->collisions = mac_stats->tx_collision;
++ stats->rx_length_errors = (mac_stats->rx_gtjumbo +
++ mac_stats->rx_length_error);
++ stats->rx_over_errors = efx->n_rx_nodesc_drop_cnt;
++ stats->rx_crc_errors = mac_stats->rx_bad;
++ stats->rx_frame_errors = mac_stats->rx_align_error;
++ stats->rx_fifo_errors = mac_stats->rx_overflow;
++ stats->rx_missed_errors = mac_stats->rx_missed;
++ stats->tx_window_errors = mac_stats->tx_late_collision;
+
-+ ixgbe_acquire_msix_vectors(adapter, v_budget);
++ stats->rx_errors = (stats->rx_length_errors +
++ stats->rx_over_errors +
++ stats->rx_crc_errors +
++ stats->rx_frame_errors +
++ stats->rx_fifo_errors +
++ stats->rx_missed_errors +
++ mac_stats->rx_symbol_error);
++ stats->tx_errors = (stats->tx_window_errors +
++ mac_stats->tx_bad);
+
-+ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
-+ goto out;
++ return stats;
++}
+
-+try_msi:
-+ err = pci_enable_msi(adapter->pdev);
-+ if (!err) {
-+ adapter->flags |= IXGBE_FLAG_MSI_ENABLED;
++/* Context: netif_tx_lock held, BHs disabled. */
++static void efx_watchdog(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++
++ EFX_ERR(efx, "TX stuck with stop_count=%d port_enabled=%d: %s\n",
++ atomic_read(&efx->netif_stop_count), efx->port_enabled,
++ monitor_reset ? "resetting channels" : "skipping reset");
++
++ if (monitor_reset)
++ efx_schedule_reset(efx, RESET_TYPE_MONITOR);
++}
++
++
++/* Context: process, rtnl_lock() held. */
++static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
++{
++ struct efx_nic *efx = net_dev->priv;
++ int rc = 0;
++
++ EFX_ASSERT_RESET_SERIALISED(efx);
++
++ if (new_mtu > EFX_MAX_MTU)
++ return -EINVAL;
++
++ efx_stop_all(efx);
++
++ EFX_LOG(efx, "changing MTU to %d\n", new_mtu);
++
++ efx_fini_channels(efx);
++ net_dev->mtu = new_mtu;
++ rc = efx_init_channels(efx);
++ if (rc)
++ goto fail;
++
++ efx_start_all(efx);
++ return rc;
++
++ fail:
++ efx_schedule_reset(efx, RESET_TYPE_DISABLE);
++ return rc;
++}
++
++static int efx_set_mac_address(struct net_device *net_dev, void *data)
++{
++ struct efx_nic *efx = net_dev->priv;
++ struct sockaddr *addr = data;
++ char *new_addr = addr->sa_data;
++
++ EFX_ASSERT_RESET_SERIALISED(efx);
++
++ if (!is_valid_ether_addr(new_addr)) {
++ DECLARE_MAC_BUF(mac);
++ EFX_ERR(efx, "invalid ethernet MAC address requested: %s\n",
++ print_mac(mac, new_addr));
++ return -EINVAL;
++ }
++
++ memcpy(net_dev->dev_addr, new_addr, net_dev->addr_len);
++
++ /* Reconfigure the MAC */
++ efx_reconfigure_port(efx);
++
++ return 0;
++}
++
++/* Context: netif_tx_lock held, BHs disabled. */
++static void efx_set_multicast_list(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++ struct dev_mc_list *mc_list = net_dev->mc_list;
++ union efx_multicast_hash *mc_hash = &efx->multicast_hash;
++ int promiscuous;
++ u32 crc;
++ int bit;
++ int i;
++
++ /* Set per-MAC promiscuity flag and reconfigure MAC if necessary */
++ promiscuous = (net_dev->flags & IFF_PROMISC) ? 1 : 0;
++ if (efx->promiscuous != promiscuous) {
++ efx->promiscuous = promiscuous;
++ /* Close the window between efx_stop_port() and efx_flush_all()
++ * by only queuing work when the port is enabled. */
++ if (efx->port_enabled)
++ queue_work(efx->workqueue, &efx->reconfigure_work);
++ }
++
++ /* Build multicast hash table */
++ if (promiscuous || (net_dev->flags & IFF_ALLMULTI)) {
++ memset(mc_hash, 0xff, sizeof(*mc_hash));
+ } else {
-+ DPRINTK(HW, DEBUG, "Unable to allocate MSI interrupt, "
-+ "falling back to legacy. Error: %d\n", err);
-+ /* reset err */
-+ err = 0;
++ memset(mc_hash, 0x00, sizeof(*mc_hash));
++ for (i = 0; i < net_dev->mc_count; i++) {
++ crc = ether_crc_le(ETH_ALEN, mc_list->dmi_addr);
++ bit = crc & (EFX_MCAST_HASH_ENTRIES - 1);
++ set_bit_le(bit, mc_hash->byte);
++ mc_list = mc_list->next;
++ }
+ }
+
-+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
++ /* Create and activate new global multicast hash table */
++ falcon_set_multicast_hash(efx);
++}
+
-+ return err;
++static int efx_netdev_event(struct notifier_block *this,
++ unsigned long event, void *ptr)
++{
++ struct net_device *net_dev = (struct net_device *)ptr;
++
++ if (net_dev->open == efx_net_open && event == NETDEV_CHANGENAME) {
++ struct efx_nic *efx = net_dev->priv;
++
++ strcpy(efx->name, net_dev->name);
++ }
++
++ return NOTIFY_DONE;
+}
+
-+static void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter)
++static struct notifier_block efx_netdev_notifier = {
++ .notifier_call = efx_netdev_event,
++};
++
++static int efx_register_netdev(struct efx_nic *efx)
+{
-+ 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;
++ struct net_device *net_dev = efx->net_dev;
++ int rc;
++
++ net_dev->watchdog_timeo = 5 * HZ;
++ net_dev->irq = efx->pci_dev->irq;
++ net_dev->open = efx_net_open;
++ net_dev->stop = efx_net_stop;
++ net_dev->get_stats = efx_net_stats;
++ net_dev->tx_timeout = &efx_watchdog;
++ net_dev->hard_start_xmit = efx_hard_start_xmit;
++ net_dev->do_ioctl = efx_ioctl;
++ net_dev->change_mtu = efx_change_mtu;
++ net_dev->set_mac_address = efx_set_mac_address;
++ net_dev->set_multicast_list = efx_set_multicast_list;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ net_dev->poll_controller = efx_netpoll;
++#endif
++ SET_NETDEV_DEV(net_dev, &efx->pci_dev->dev);
++ SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops);
++
++ /* Always start with carrier off; PHY events will detect the link */
++ netif_carrier_off(efx->net_dev);
++
++ /* Clear MAC statistics */
++ falcon_update_stats_xmac(efx);
++ memset(&efx->mac_stats, 0, sizeof(efx->mac_stats));
++
++ rc = register_netdev(net_dev);
++ if (rc) {
++ EFX_ERR(efx, "could not register net dev\n");
++ return rc;
++ }
++ strcpy(efx->name, net_dev->name);
++
++ return 0;
+}
+
-+/**
-+ * 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)
++static void efx_unregister_netdev(struct efx_nic *efx)
+{
-+ int err;
++ struct efx_tx_queue *tx_queue;
+
-+ /* Number of supported queues */
-+ ixgbe_set_num_queues(adapter);
++ if (!efx->net_dev)
++ return;
+
-+ err = ixgbe_alloc_queues(adapter);
-+ if (err) {
-+ DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n");
-+ goto err_alloc_queues;
++ BUG_ON(efx->net_dev->priv != efx);
++
++ /* Free up any skbs still remaining. This has to happen before
++ * we try to unregister the netdev as running their destructors
++ * may be needed to get the device ref. count to 0. */
++ efx_for_each_tx_queue(tx_queue, efx)
++ efx_release_tx_buffers(tx_queue);
++
++ if (NET_DEV_REGISTERED(efx)) {
++ strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
++ unregister_netdev(efx->net_dev);
+ }
++}
+
-+ err = ixgbe_set_interrupt_capability(adapter);
-+ if (err) {
-+ DPRINTK(PROBE, ERR, "Unable to setup interrupt capabilities\n");
-+ goto err_set_interrupt;
++/**************************************************************************
++ *
++ * Device reset and suspend
++ *
++ **************************************************************************/
++
++/* The final hardware and software finalisation before reset. */
++static int efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
++{
++ int rc;
++
++ EFX_ASSERT_RESET_SERIALISED(efx);
++
++ rc = falcon_xmac_get_settings(efx, ecmd);
++ if (rc) {
++ EFX_ERR(efx, "could not back up PHY settings\n");
++ goto fail;
+ }
+
-+ 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);
++ efx_fini_channels(efx);
++ return 0;
+
-+ set_bit(__IXGBE_DOWN, &adapter->state);
-
- return 0;
++ fail:
++ return rc;
++}
+
-+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;
++/* The first part of software initialisation after a hardware reset
++ * This function does not handle serialisation with the kernel, it
++ * assumes the caller has done this */
++static int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd)
++{
++ int rc;
+
-+ /* 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;
++ rc = efx_init_channels(efx);
++ if (rc)
++ goto fail1;
+
-+ /* 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));
++ /* Restore MAC and PHY settings. */
++ rc = falcon_xmac_set_settings(efx, ecmd);
++ if (rc) {
++ EFX_ERR(efx, "could not restore PHY settings\n");
++ goto fail2;
+ }
- }
-
- 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
++
++ return 0;
++
++ fail2:
++ efx_fini_channels(efx);
++ fail1:
++ return rc;
++}
++
++/* Reset the NIC as transparently as possible. Do not reset the PHY
++ * Note that the reset may fail, in which case the card will be left
++ * in a most-probably-unusable state.
++ *
++ * This function will sleep. You cannot reset from within an atomic
++ * state; use efx_schedule_reset() instead.
++ *
++ * Grabs the rtnl_lock.
+ */
-+static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter)
++static int efx_reset(struct efx_nic *efx)
+{
-+ int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
-+ int (*poll)(struct napi_struct *, int);
++ struct ethtool_cmd ecmd;
++ enum reset_type method = efx->reset_pending;
++ int rc;
+
-+ 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;
++ /* Serialise with kernel interfaces */
++ rtnl_lock();
++
++ /* If we're not RUNNING then don't reset. Leave the reset_pending
++ * flag set so that efx_pci_probe_main will be retried */
++ if (efx->state != STATE_RUNNING) {
++ EFX_INFO(efx, "scheduled reset quenched. NIC not RUNNING\n");
++ goto unlock_rtnl;
+ }
+
-+ 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);
++ efx->state = STATE_RESETTING;
++ EFX_INFO(efx, "resetting (%d)\n", method);
++
++ /* The net_dev->get_stats handler is quite slow, and will fail
++ * if a fetch is pending over reset. Serialise against it. */
++ spin_lock(&efx->stats_lock);
++ spin_unlock(&efx->stats_lock);
++
++ efx_stop_all(efx);
++ mutex_lock(&efx->mac_lock);
++
++ rc = efx_reset_down(efx, &ecmd);
++ if (rc)
++ goto fail1;
++
++ rc = falcon_reset_hw(efx, method);
++ if (rc) {
++ EFX_ERR(efx, "failed to reset hardware\n");
++ goto fail2;
+ }
-+}
+
-+/**
- * 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
++ /* Allow resets to be rescheduled. */
++ efx->reset_pending = RESET_TYPE_NONE;
+
-+ 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);
++ /* Reinitialise bus-mastering, which may have been turned off before
++ * the reset was scheduled. This is still appropriate, even in the
++ * RESET_TYPE_DISABLE since this driver generally assumes the hardware
++ * can respond to requests. */
++ pci_set_master(efx->pci_dev);
++
++ /* Reinitialise device. This is appropriate in the RESET_TYPE_DISABLE
++ * case so the driver can talk to external SRAM */
++ rc = falcon_init_nic(efx);
++ if (rc) {
++ EFX_ERR(efx, "failed to initialise NIC\n");
++ goto fail3;
+ }
-+#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);
++
++ /* Leave device stopped if necessary */
++ if (method == RESET_TYPE_DISABLE) {
++ /* Reinitialise the device anyway so the driver unload sequence
++ * can talk to the external SRAM */
++ (void) falcon_init_nic(efx);
++ rc = -EIO;
++ goto fail4;
+ }
+
-+#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);
++ rc = efx_reset_up(efx, &ecmd);
++ if (rc)
++ goto fail5;
+
- 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);
++ mutex_unlock(&efx->mac_lock);
++ EFX_LOG(efx, "reset complete\n");
+
-+#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);
- }
++ efx->state = STATE_RUNNING;
++ efx_start_all(efx);
+
-+#ifdef CONFIG_DCA
-+static int ixgbe_notify_dca(struct notifier_block *nb, unsigned long event,
-+ void *p)
++ unlock_rtnl:
++ rtnl_unlock();
++ return 0;
++
++ fail5:
++ fail4:
++ fail3:
++ fail2:
++ fail1:
++ EFX_ERR(efx, "has been disabled\n");
++ efx->state = STATE_DISABLED;
++
++ mutex_unlock(&efx->mac_lock);
++ rtnl_unlock();
++ efx_unregister_netdev(efx);
++ efx_fini_port(efx);
++ return rc;
++}
++
++/* The worker thread exists so that code that cannot sleep can
++ * schedule a reset for later.
++ */
++static void efx_reset_work(struct work_struct *data)
+{
-+ int ret_val;
++ struct efx_nic *nic = container_of(data, struct efx_nic, reset_work);
+
-+ ret_val = driver_for_each_device(&ixgbe_driver.driver, NULL, &event,
-+ __ixgbe_notify_dca);
++ efx_reset(nic);
++}
+
-+ return ret_val ? NOTIFY_BAD : NOTIFY_DONE;
++void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
++{
++ enum reset_type method;
++
++ if (efx->reset_pending != RESET_TYPE_NONE) {
++ EFX_INFO(efx, "quenching already scheduled reset\n");
++ return;
++ }
++
++ switch (type) {
++ case RESET_TYPE_INVISIBLE:
++ case RESET_TYPE_ALL:
++ case RESET_TYPE_WORLD:
++ case RESET_TYPE_DISABLE:
++ method = type;
++ break;
++ case RESET_TYPE_RX_RECOVERY:
++ case RESET_TYPE_RX_DESC_FETCH:
++ case RESET_TYPE_TX_DESC_FETCH:
++ case RESET_TYPE_TX_SKIP:
++ method = RESET_TYPE_INVISIBLE;
++ break;
++ default:
++ method = RESET_TYPE_ALL;
++ break;
++ }
++
++ if (method != type)
++ EFX_LOG(efx, "scheduling reset (%d:%d)\n", type, method);
++ else
++ EFX_LOG(efx, "scheduling reset (%d)\n", method);
++
++ efx->reset_pending = method;
++
++ queue_work(efx->workqueue, &efx->reset_work);
+}
-+#endif /* CONFIG_DCA */
+
- module_exit(ixgbe_exit_module);
-
- /* ixgbe_main.c */
-diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c
-index 5c154fe..0794482 100644
---- a/drivers/net/jazzsonic.c
-+++ b/drivers/net/jazzsonic.c
-@@ -249,6 +249,7 @@ out:
- MODULE_DESCRIPTION("Jazz SONIC ethernet driver");
- module_param(sonic_debug, int, 0);
- MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)");
-+MODULE_ALIAS("platform:jazzsonic");
-
- #include "sonic.c"
-
-@@ -271,6 +272,7 @@ static struct platform_driver jazz_sonic_driver = {
- .remove = __devexit_p(jazz_sonic_device_remove),
- .driver = {
- .name = jazz_sonic_string,
-+ .owner = THIS_MODULE,
- },
- };
-
-diff --git a/drivers/net/korina.c b/drivers/net/korina.c
-new file mode 100644
-index 0000000..e185763
---- /dev/null
-+++ b/drivers/net/korina.c
-@@ -0,0 +1,1230 @@
-+/*
-+ * Driver for the IDT RC32434 (Korina) on-chip ethernet controller.
++/**************************************************************************
+ *
-+ * Copyright 2004 IDT Inc. (rischelp at idt.com)
-+ * Copyright 2006 Felix Fietkau <nbd at openwrt.org>
-+ * Copyright 2008 Florian Fainelli <florian at openwrt.org>
++ * List of NICs we support
+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2 of the License, or (at your
-+ * option) any later version.
++ **************************************************************************/
++
++/* PCI device ID table */
++static struct pci_device_id efx_pci_table[] __devinitdata = {
++ {PCI_DEVICE(EFX_VENDID_SFC, FALCON_A_P_DEVID),
++ .driver_data = (unsigned long) &falcon_a_nic_type},
++ {PCI_DEVICE(EFX_VENDID_SFC, FALCON_B_P_DEVID),
++ .driver_data = (unsigned long) &falcon_b_nic_type},
++ {0} /* end of list */
++};
++
++/**************************************************************************
+ *
-+ * 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.
++ * Dummy PHY/MAC/Board operations
+ *
-+ * You 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.
++ * Can be used where the MAC does not implement this operation
++ * Needed so all function pointers are valid and do not have to be tested
++ * before use
+ *
-+ * Writing to a DMA status register:
++ **************************************************************************/
++int efx_port_dummy_op_int(struct efx_nic *efx)
++{
++ return 0;
++}
++void efx_port_dummy_op_void(struct efx_nic *efx) {}
++void efx_port_dummy_op_blink(struct efx_nic *efx, int blink) {}
++
++static struct efx_phy_operations efx_dummy_phy_operations = {
++ .init = efx_port_dummy_op_int,
++ .reconfigure = efx_port_dummy_op_void,
++ .check_hw = efx_port_dummy_op_int,
++ .fini = efx_port_dummy_op_void,
++ .clear_interrupt = efx_port_dummy_op_void,
++ .reset_xaui = efx_port_dummy_op_void,
++};
++
++/* Dummy board operations */
++static int efx_nic_dummy_op_int(struct efx_nic *nic)
++{
++ return 0;
++}
++
++static struct efx_board efx_dummy_board_info = {
++ .init = efx_nic_dummy_op_int,
++ .init_leds = efx_port_dummy_op_int,
++ .set_fault_led = efx_port_dummy_op_blink,
++};
++
++/**************************************************************************
+ *
-+ * 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.
++ * Data housekeeping
++ *
++ **************************************************************************/
++
++/* This zeroes out and then fills in the invariants in a struct
++ * efx_nic (including all sub-structures).
+ */
++static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
++ struct pci_dev *pci_dev, struct net_device *net_dev)
++{
++ struct efx_channel *channel;
++ struct efx_tx_queue *tx_queue;
++ struct efx_rx_queue *rx_queue;
++ int i, rc;
+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/moduleparam.h>
-+#include <linux/sched.h>
-+#include <linux/ctype.h>
-+#include <linux/types.h>
-+#include <linux/interrupt.h>
-+#include <linux/init.h>
-+#include <linux/ioport.h>
-+#include <linux/in.h>
-+#include <linux/slab.h>
-+#include <linux/string.h>
-+#include <linux/delay.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/skbuff.h>
-+#include <linux/errno.h>
-+#include <linux/platform_device.h>
-+#include <linux/mii.h>
-+#include <linux/ethtool.h>
-+#include <linux/crc32.h>
++ /* Initialise common structures */
++ memset(efx, 0, sizeof(*efx));
++ spin_lock_init(&efx->biu_lock);
++ spin_lock_init(&efx->phy_lock);
++ INIT_WORK(&efx->reset_work, efx_reset_work);
++ INIT_DELAYED_WORK(&efx->monitor_work, efx_monitor);
++ efx->pci_dev = pci_dev;
++ efx->state = STATE_INIT;
++ efx->reset_pending = RESET_TYPE_NONE;
++ strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name));
++ efx->board_info = efx_dummy_board_info;
++
++ efx->net_dev = net_dev;
++ efx->rx_checksum_enabled = 1;
++ spin_lock_init(&efx->netif_stop_lock);
++ spin_lock_init(&efx->stats_lock);
++ mutex_init(&efx->mac_lock);
++ efx->phy_op = &efx_dummy_phy_operations;
++ efx->mii.dev = net_dev;
++ INIT_WORK(&efx->reconfigure_work, efx_reconfigure_work);
++ atomic_set(&efx->netif_stop_count, 1);
++
++ for (i = 0; i < EFX_MAX_CHANNELS; i++) {
++ channel = &efx->channel[i];
++ channel->efx = efx;
++ channel->channel = i;
++ channel->evqnum = i;
++ channel->work_pending = 0;
++ }
++ for (i = 0; i < EFX_MAX_TX_QUEUES; i++) {
++ tx_queue = &efx->tx_queue[i];
++ tx_queue->efx = efx;
++ tx_queue->queue = i;
++ tx_queue->buffer = NULL;
++ tx_queue->channel = &efx->channel[0]; /* for safety */
++ }
++ for (i = 0; i < EFX_MAX_RX_QUEUES; i++) {
++ rx_queue = &efx->rx_queue[i];
++ rx_queue->efx = efx;
++ rx_queue->queue = i;
++ rx_queue->channel = &efx->channel[0]; /* for safety */
++ rx_queue->buffer = NULL;
++ spin_lock_init(&rx_queue->add_lock);
++ INIT_DELAYED_WORK(&rx_queue->work, efx_rx_work);
++ }
++
++ efx->type = type;
++
++ /* Sanity-check NIC type */
++ EFX_BUG_ON_PARANOID(efx->type->txd_ring_mask &
++ (efx->type->txd_ring_mask + 1));
++ EFX_BUG_ON_PARANOID(efx->type->rxd_ring_mask &
++ (efx->type->rxd_ring_mask + 1));
++ EFX_BUG_ON_PARANOID(efx->type->evq_size &
++ (efx->type->evq_size - 1));
++ /* As close as we can get to guaranteeing that we don't overflow */
++ EFX_BUG_ON_PARANOID(efx->type->evq_size <
++ (efx->type->txd_ring_mask + 1 +
++ efx->type->rxd_ring_mask + 1));
++ EFX_BUG_ON_PARANOID(efx->type->phys_addr_channels > EFX_MAX_CHANNELS);
++
++ /* Higher numbered interrupt modes are less capable! */
++ efx->interrupt_mode = max(efx->type->max_interrupt_mode,
++ interrupt_mode);
+
-+#include <asm/bootinfo.h>
-+#include <asm/system.h>
-+#include <asm/bitops.h>
-+#include <asm/pgtable.h>
-+#include <asm/segment.h>
-+#include <asm/io.h>
-+#include <asm/dma.h>
++ efx->workqueue = create_singlethread_workqueue("sfc_work");
++ if (!efx->workqueue) {
++ rc = -ENOMEM;
++ goto fail1;
++ }
+
-+#include <asm/mach-rc32434/rb.h>
-+#include <asm/mach-rc32434/rc32434.h>
-+#include <asm/mach-rc32434/eth.h>
-+#include <asm/mach-rc32434/dma_v.h>
++ return 0;
+
-+#define DRV_NAME "korina"
-+#define DRV_VERSION "0.10"
-+#define DRV_RELDATE "04Mar2008"
++ fail1:
++ return rc;
++}
+
-+#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]))
++static void efx_fini_struct(struct efx_nic *efx)
++{
++ if (efx->workqueue) {
++ destroy_workqueue(efx->workqueue);
++ efx->workqueue = NULL;
++ }
++}
+
-+#define MII_CLOCK 1250000 /* no more than 2.5MHz */
++/**************************************************************************
++ *
++ * PCI interface
++ *
++ **************************************************************************/
+
-+/* 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 */
++/* Main body of final NIC shutdown code
++ * This is called only at module unload (or hotplug removal).
++ */
++static void efx_pci_remove_main(struct efx_nic *efx)
++{
++ EFX_ASSERT_RESET_SERIALISED(efx);
+
-+#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))
++ /* Skip everything if we never obtained a valid membase */
++ if (!efx->membase)
++ return;
+
-+#define TX_TIMEOUT (6000 * HZ / 1000)
++ efx_fini_channels(efx);
++ efx_fini_port(efx);
+
-+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)
++ /* Shutdown the board, then the NIC and board state */
++ falcon_fini_interrupt(efx);
+
-+/* 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 */
++ efx_fini_napi(efx);
++ efx_remove_all(efx);
++}
+
-+ struct sk_buff *tx_skb[KORINA_NUM_TDS];
-+ struct sk_buff *rx_skb[KORINA_NUM_RDS];
++/* Final NIC shutdown
++ * This is called only at module unload (or hotplug removal).
++ */
++static void efx_pci_remove(struct pci_dev *pci_dev)
++{
++ struct efx_nic *efx;
++
++ efx = pci_get_drvdata(pci_dev);
++ if (!efx)
++ return;
++
++ /* Mark the NIC as fini, then stop the interface */
++ rtnl_lock();
++ efx->state = STATE_FINI;
++ dev_close(efx->net_dev);
++
++ /* Allow any queued efx_resets() to complete */
++ rtnl_unlock();
++
++ if (efx->membase == NULL)
++ goto out;
++
++ efx_unregister_netdev(efx);
++
++ /* Wait for any scheduled resets to complete. No more will be
++ * scheduled from this point because efx_stop_all() has been
++ * called, we are no longer registered with driverlink, and
++ * the net_device's have been removed. */
++ flush_workqueue(efx->workqueue);
++
++ efx_pci_remove_main(efx);
++
++out:
++ efx_fini_io(efx);
++ EFX_LOG(efx, "shutdown successful\n");
++
++ pci_set_drvdata(pci_dev, NULL);
++ efx_fini_struct(efx);
++ free_netdev(efx->net_dev);
++};
++
++/* Main body of NIC initialisation
++ * This is called at module load (or hotplug insertion, theoretically).
++ */
++static int efx_pci_probe_main(struct efx_nic *efx)
++{
++ int rc;
++
++ /* Do start-of-day initialisation */
++ rc = efx_probe_all(efx);
++ if (rc)
++ goto fail1;
++
++ rc = efx_init_napi(efx);
++ if (rc)
++ goto fail2;
++
++ /* Initialise the board */
++ rc = efx->board_info.init(efx);
++ if (rc) {
++ EFX_ERR(efx, "failed to initialise board\n");
++ goto fail3;
++ }
++
++ rc = falcon_init_nic(efx);
++ if (rc) {
++ EFX_ERR(efx, "failed to initialise NIC\n");
++ goto fail4;
++ }
++
++ rc = efx_init_port(efx);
++ if (rc) {
++ EFX_ERR(efx, "failed to initialise port\n");
++ goto fail5;
++ }
++
++ rc = efx_init_channels(efx);
++ if (rc)
++ goto fail6;
++
++ rc = falcon_init_interrupt(efx);
++ if (rc)
++ goto fail7;
++
++ return 0;
++
++ fail7:
++ efx_fini_channels(efx);
++ fail6:
++ efx_fini_port(efx);
++ fail5:
++ fail4:
++ fail3:
++ efx_fini_napi(efx);
++ fail2:
++ efx_remove_all(efx);
++ fail1:
++ return rc;
++}
++
++/* NIC initialisation
++ *
++ * This is called at module load (or hotplug insertion,
++ * theoretically). It sets up PCI mappings, tests and resets the NIC,
++ * sets up and registers the network devices with the kernel and hooks
++ * the interrupt service routine. It does not prepare the device for
++ * transmission; this is left to the first time one of the network
++ * interfaces is brought up (i.e. efx_net_open).
++ */
++static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
++ const struct pci_device_id *entry)
++{
++ struct efx_nic_type *type = (struct efx_nic_type *) entry->driver_data;
++ struct net_device *net_dev;
++ struct efx_nic *efx;
++ int i, rc;
++
++ /* Allocate and initialise a struct net_device and struct efx_nic */
++ net_dev = alloc_etherdev(sizeof(*efx));
++ if (!net_dev)
++ return -ENOMEM;
++ net_dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA;
++ if (lro)
++ net_dev->features |= NETIF_F_LRO;
++ efx = net_dev->priv;
++ pci_set_drvdata(pci_dev, efx);
++ rc = efx_init_struct(efx, type, pci_dev, net_dev);
++ if (rc)
++ goto fail1;
++
++ EFX_INFO(efx, "Solarflare Communications NIC detected\n");
++
++ /* Set up basic I/O (BAR mappings etc) */
++ rc = efx_init_io(efx);
++ if (rc)
++ goto fail2;
++
++ /* No serialisation is required with the reset path because
++ * we're in STATE_INIT. */
++ for (i = 0; i < 5; i++) {
++ rc = efx_pci_probe_main(efx);
++ if (rc == 0)
++ break;
++
++ /* Serialise against efx_reset(). No more resets will be
++ * scheduled since efx_stop_all() has been called, and we
++ * have not and never have been registered with either
++ * the rtnetlink or driverlink layers. */
++ cancel_work_sync(&efx->reset_work);
++
++ /* Retry if a recoverably reset event has been scheduled */
++ if ((efx->reset_pending != RESET_TYPE_INVISIBLE) &&
++ (efx->reset_pending != RESET_TYPE_ALL))
++ goto fail3;
++
++ efx->reset_pending = RESET_TYPE_NONE;
++ }
++
++ if (rc) {
++ EFX_ERR(efx, "Could not reset NIC\n");
++ goto fail4;
++ }
+
-+ int rx_next_done;
-+ int rx_chain_head;
-+ int rx_chain_tail;
-+ enum chain_status rx_chain_status;
++ /* Switch to the running state before we expose the device to
++ * the OS. This is to ensure that the initial gathering of
++ * MAC stats succeeds. */
++ rtnl_lock();
++ efx->state = STATE_RUNNING;
++ rtnl_unlock();
+
-+ int tx_next_done;
-+ int tx_chain_head;
-+ int tx_chain_tail;
-+ enum chain_status tx_chain_status;
-+ int tx_count;
-+ int tx_full;
++ rc = efx_register_netdev(efx);
++ if (rc)
++ goto fail5;
+
-+ int rx_irq;
-+ int tx_irq;
-+ int ovr_irq;
-+ int und_irq;
++ EFX_LOG(efx, "initialisation successful\n");
+
-+ spinlock_t lock; /* NIC xmit lock */
++ return 0;
+
-+ 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;
++ fail5:
++ efx_pci_remove_main(efx);
++ fail4:
++ fail3:
++ efx_fini_io(efx);
++ fail2:
++ efx_fini_struct(efx);
++ fail1:
++ EFX_LOG(efx, "initialisation failed. rc=%d\n", rc);
++ free_netdev(net_dev);
++ return rc;
++}
++
++static struct pci_driver efx_pci_driver = {
++ .name = EFX_DRIVER_NAME,
++ .id_table = efx_pci_table,
++ .probe = efx_pci_probe,
++ .remove = efx_pci_remove,
+};
+
-+extern unsigned int idt_cpu_freq;
++/**************************************************************************
++ *
++ * Kernel module interface
++ *
++ *************************************************************************/
+
-+static inline void korina_start_dma(struct dma_reg *ch, u32 dma_addr)
-+{
-+ writel(0, &ch->dmandptr);
-+ writel(dma_addr, &ch->dmadptr);
-+}
++module_param(interrupt_mode, uint, 0444);
++MODULE_PARM_DESC(interrupt_mode,
++ "Interrupt mode (0=>MSIX 1=>MSI 2=>legacy)");
+
-+static inline void korina_abort_dma(struct net_device *dev,
-+ struct dma_reg *ch)
++static int __init efx_init_module(void)
+{
-+ if (readl(&ch->dmac) & DMA_CHAN_RUN_BIT) {
-+ writel(0x10, &ch->dmac);
++ int rc;
+
-+ while (!(readl(&ch->dmas) & DMA_STAT_HALT))
-+ dev->trans_start = jiffies;
++ printk(KERN_INFO "Solarflare NET driver v" EFX_DRIVER_VERSION "\n");
+
-+ writel(0, &ch->dmas);
-+ }
++ rc = register_netdevice_notifier(&efx_netdev_notifier);
++ if (rc)
++ goto err_notifier;
+
-+ writel(0, &ch->dmadptr);
-+ writel(0, &ch->dmandptr);
-+}
++ refill_workqueue = create_workqueue("sfc_refill");
++ if (!refill_workqueue) {
++ rc = -ENOMEM;
++ goto err_refill;
++ }
+
-+static inline void korina_chain_dma(struct dma_reg *ch, u32 dma_addr)
-+{
-+ writel(dma_addr, &ch->dmandptr);
-+}
++ rc = pci_register_driver(&efx_pci_driver);
++ if (rc < 0)
++ goto err_pci;
+
-+static void korina_abort_tx(struct net_device *dev)
-+{
-+ struct korina_private *lp = netdev_priv(dev);
++ return 0;
+
-+ korina_abort_dma(dev, lp->tx_dma_regs);
++ err_pci:
++ destroy_workqueue(refill_workqueue);
++ err_refill:
++ unregister_netdevice_notifier(&efx_netdev_notifier);
++ err_notifier:
++ return rc;
+}
+
-+static void korina_abort_rx(struct net_device *dev)
++static void __exit efx_exit_module(void)
+{
-+ struct korina_private *lp = netdev_priv(dev);
++ printk(KERN_INFO "Solarflare NET driver unloading\n");
+
-+ korina_abort_dma(dev, lp->rx_dma_regs);
-+}
++ pci_unregister_driver(&efx_pci_driver);
++ destroy_workqueue(refill_workqueue);
++ unregister_netdevice_notifier(&efx_netdev_notifier);
+
-+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));
-+}
++module_init(efx_init_module);
++module_exit(efx_exit_module);
+
-+/* 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;
++MODULE_AUTHOR("Michael Brown <mbrown at fensystems.co.uk> and "
++ "Solarflare Communications");
++MODULE_DESCRIPTION("Solarflare Communications network driver");
++MODULE_LICENSE("GPL");
++MODULE_DEVICE_TABLE(pci, efx_pci_table);
+diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
+new file mode 100644
+index 0000000..3b2f69f
+--- /dev/null
++++ b/drivers/net/sfc/efx.h
+@@ -0,0 +1,67 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005-2006 Fen Systems Ltd.
++ * Copyright 2006-2008 Solarflare Communications 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, incorporated herein by reference.
++ */
+
-+ spin_lock_irqsave(&lp->lock, flags);
++#ifndef EFX_EFX_H
++#define EFX_EFX_H
+
-+ td = &lp->td_ring[lp->tx_chain_tail];
++#include "net_driver.h"
+
-+ /* stop queue when full, drop pkts if queue already full */
-+ if (lp->tx_count >= (KORINA_NUM_TDS - 2)) {
-+ lp->tx_full = 1;
++/* PCI IDs */
++#define EFX_VENDID_SFC 0x1924
++#define FALCON_A_P_DEVID 0x0703
++#define FALCON_A_S_DEVID 0x6703
++#define FALCON_B_P_DEVID 0x0710
+
-+ 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);
++/* TX */
++extern int efx_xmit(struct efx_nic *efx,
++ struct efx_tx_queue *tx_queue, struct sk_buff *skb);
++extern void efx_stop_queue(struct efx_nic *efx);
++extern void efx_wake_queue(struct efx_nic *efx);
+
-+ return NETDEV_TX_BUSY;
-+ }
-+ }
++/* RX */
++extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
++extern void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
++ unsigned int len, int checksummed, int discard);
++extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay);
+
-+ lp->tx_count++;
++/* Channels */
++extern void efx_process_channel_now(struct efx_channel *channel);
++extern int efx_flush_queues(struct efx_nic *efx);
+
-+ lp->tx_skb[lp->tx_chain_tail] = skb;
++/* Ports */
++extern void efx_reconfigure_port(struct efx_nic *efx);
+
-+ length = skb->len;
-+ dma_cache_wback((u32)skb->data, skb->len);
++/* Global */
++extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
++extern void efx_suspend(struct efx_nic *efx);
++extern void efx_resume(struct efx_nic *efx);
++extern void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs,
++ int rx_usecs);
++extern int efx_request_power(struct efx_nic *efx, int mw, const char *name);
++extern void efx_hex_dump(const u8 *, unsigned int, const char *);
+
-+ /* 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;
++/* Dummy PHY ops for PHY drivers */
++extern int efx_port_dummy_op_int(struct efx_nic *efx);
++extern void efx_port_dummy_op_void(struct efx_nic *efx);
++extern void efx_port_dummy_op_blink(struct efx_nic *efx, int blink);
+
-+ 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);
++extern unsigned int efx_monitor_interval;
+
-+ return NETDEV_TX_OK;
++static inline void efx_schedule_channel(struct efx_channel *channel)
++{
++ EFX_TRACE(channel->efx, "channel %d scheduling NAPI poll on CPU%d\n",
++ channel->channel, raw_smp_processor_id());
++ channel->work_pending = 1;
++
++ netif_rx_schedule(channel->napi_dev, &channel->napi_str);
+}
+
-+static int mdio_read(struct net_device *dev, int mii_id, int reg)
-+{
-+ struct korina_private *lp = netdev_priv(dev);
-+ int ret;
++#endif /* EFX_EFX_H */
+diff --git a/drivers/net/sfc/enum.h b/drivers/net/sfc/enum.h
+new file mode 100644
+index 0000000..43663a4
+--- /dev/null
++++ b/drivers/net/sfc/enum.h
+@@ -0,0 +1,50 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2007 Solarflare Communications 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, incorporated herein by reference.
++ */
+
-+ mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8);
++#ifndef EFX_ENUM_H
++#define EFX_ENUM_H
+
-+ 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;
-+}
++/**
++ * enum reset_type - reset types
++ *
++ * %RESET_TYPE_INVSIBLE, %RESET_TYPE_ALL, %RESET_TYPE_WORLD and
++ * %RESET_TYPE_DISABLE specify the method/scope of the reset. The
++ * other valuesspecify reasons, which efx_schedule_reset() will choose
++ * a method for.
++ *
++ * @RESET_TYPE_INVISIBLE: don't reset the PHYs or interrupts
++ * @RESET_TYPE_ALL: reset everything but PCI core blocks
++ * @RESET_TYPE_WORLD: reset everything, save & restore PCI config
++ * @RESET_TYPE_DISABLE: disable NIC
++ * @RESET_TYPE_MONITOR: reset due to hardware monitor
++ * @RESET_TYPE_INT_ERROR: reset due to internal error
++ * @RESET_TYPE_RX_RECOVERY: reset to recover from RX datapath errors
++ * @RESET_TYPE_RX_DESC_FETCH: pcie error during rx descriptor fetch
++ * @RESET_TYPE_TX_DESC_FETCH: pcie error during tx descriptor fetch
++ * @RESET_TYPE_TX_SKIP: hardware completed empty tx descriptors
++ */
++enum reset_type {
++ RESET_TYPE_NONE = -1,
++ RESET_TYPE_INVISIBLE = 0,
++ RESET_TYPE_ALL = 1,
++ RESET_TYPE_WORLD = 2,
++ RESET_TYPE_DISABLE = 3,
++ RESET_TYPE_MAX_METHOD,
++ RESET_TYPE_MONITOR,
++ RESET_TYPE_INT_ERROR,
++ RESET_TYPE_RX_RECOVERY,
++ RESET_TYPE_RX_DESC_FETCH,
++ RESET_TYPE_TX_DESC_FETCH,
++ RESET_TYPE_TX_SKIP,
++ RESET_TYPE_MAX,
++};
+
-+static void mdio_write(struct net_device *dev, int mii_id, int reg, int val)
-+{
-+ struct korina_private *lp = netdev_priv(dev);
++#endif /* EFX_ENUM_H */
+diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
+new file mode 100644
+index 0000000..ad541ba
+--- /dev/null
++++ b/drivers/net/sfc/ethtool.c
+@@ -0,0 +1,460 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005-2006 Fen Systems Ltd.
++ * Copyright 2006-2008 Solarflare Communications 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, incorporated herein by reference.
++ */
+
-+ mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8);
++#include <linux/netdevice.h>
++#include <linux/ethtool.h>
++#include <linux/rtnetlink.h>
++#include "net_driver.h"
++#include "efx.h"
++#include "ethtool.h"
++#include "falcon.h"
++#include "gmii.h"
++#include "mac.h"
+
-+ 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);
++static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable);
++
++struct ethtool_string {
++ char name[ETH_GSTRING_LEN];
++};
++
++struct efx_ethtool_stat {
++ const char *name;
++ enum {
++ EFX_ETHTOOL_STAT_SOURCE_mac_stats,
++ EFX_ETHTOOL_STAT_SOURCE_nic,
++ EFX_ETHTOOL_STAT_SOURCE_channel
++ } source;
++ unsigned offset;
++ u64(*get_stat) (void *field); /* Reader function */
++};
++
++/* Initialiser for a struct #efx_ethtool_stat with type-checking */
++#define EFX_ETHTOOL_STAT(stat_name, source_name, field, field_type, \
++ get_stat_function) { \
++ .name = #stat_name, \
++ .source = EFX_ETHTOOL_STAT_SOURCE_##source_name, \
++ .offset = ((((field_type *) 0) == \
++ &((struct efx_##source_name *)0)->field) ? \
++ offsetof(struct efx_##source_name, field) : \
++ offsetof(struct efx_##source_name, field)), \
++ .get_stat = get_stat_function, \
++}
++
++static u64 efx_get_uint_stat(void *field)
++{
++ return *(unsigned int *)field;
++}
++
++static u64 efx_get_ulong_stat(void *field)
++{
++ return *(unsigned long *)field;
++}
++
++static u64 efx_get_u64_stat(void *field)
++{
++ return *(u64 *) field;
++}
++
++static u64 efx_get_atomic_stat(void *field)
++{
++ return atomic_read((atomic_t *) field);
++}
++
++#define EFX_ETHTOOL_ULONG_MAC_STAT(field) \
++ EFX_ETHTOOL_STAT(field, mac_stats, field, \
++ unsigned long, efx_get_ulong_stat)
++
++#define EFX_ETHTOOL_U64_MAC_STAT(field) \
++ EFX_ETHTOOL_STAT(field, mac_stats, field, \
++ u64, efx_get_u64_stat)
++
++#define EFX_ETHTOOL_UINT_NIC_STAT(name) \
++ EFX_ETHTOOL_STAT(name, nic, n_##name, \
++ unsigned int, efx_get_uint_stat)
++
++#define EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(field) \
++ EFX_ETHTOOL_STAT(field, nic, field, \
++ atomic_t, efx_get_atomic_stat)
++
++#define EFX_ETHTOOL_UINT_CHANNEL_STAT(field) \
++ EFX_ETHTOOL_STAT(field, channel, n_##field, \
++ unsigned int, efx_get_uint_stat)
++
++static struct efx_ethtool_stat efx_ethtool_stats[] = {
++ EFX_ETHTOOL_U64_MAC_STAT(tx_bytes),
++ EFX_ETHTOOL_U64_MAC_STAT(tx_good_bytes),
++ EFX_ETHTOOL_U64_MAC_STAT(tx_bad_bytes),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_packets),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_bad),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_pause),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_control),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_unicast),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_multicast),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_broadcast),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_lt64),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_64),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_65_to_127),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_128_to_255),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_256_to_511),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_512_to_1023),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_1024_to_15xx),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_15xx_to_jumbo),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_gtjumbo),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_collision),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_single_collision),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_multiple_collision),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_excessive_collision),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_deferred),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_late_collision),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_excessive_deferred),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_non_tcpudp),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_mac_src_error),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_ip_src_error),
++ EFX_ETHTOOL_U64_MAC_STAT(rx_bytes),
++ EFX_ETHTOOL_U64_MAC_STAT(rx_good_bytes),
++ EFX_ETHTOOL_U64_MAC_STAT(rx_bad_bytes),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_packets),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_good),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_pause),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_control),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_unicast),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_multicast),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_broadcast),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_lt64),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_64),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_65_to_127),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_128_to_255),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_256_to_511),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_512_to_1023),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_1024_to_15xx),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_15xx_to_jumbo),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_gtjumbo),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_lt64),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_64_to_15xx),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_15xx_to_jumbo),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_gtjumbo),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_overflow),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_missed),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_false_carrier),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_symbol_error),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_align_error),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_length_error),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_internal_error),
++ EFX_ETHTOOL_UINT_NIC_STAT(rx_nodesc_drop_cnt),
++ EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset),
++ EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc),
++ EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err),
++ EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tcp_udp_chksum_err),
++ EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc),
++};
++
++/* Number of ethtool statistics */
++#define EFX_ETHTOOL_NUM_STATS ARRAY_SIZE(efx_ethtool_stats)
++
++/**************************************************************************
++ *
++ * Ethtool operations
++ *
++ **************************************************************************
++ */
++
++/* Identify device by flashing LEDs */
++static int efx_ethtool_phys_id(struct net_device *net_dev, u32 seconds)
++{
++ struct efx_nic *efx = net_dev->priv;
++
++ efx->board_info.blink(efx, 1);
++ schedule_timeout_interruptible(seconds * HZ);
++ efx->board_info.blink(efx, 0);
++ return 0;
+}
+
-+/* Ethernet Rx DMA interrupt */
-+static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id)
++/* This must be called with rtnl_lock held. */
++int efx_ethtool_get_settings(struct net_device *net_dev,
++ struct ethtool_cmd *ecmd)
+{
-+ struct net_device *dev = dev_id;
-+ struct korina_private *lp = netdev_priv(dev);
-+ u32 dmas, dmasm;
-+ irqreturn_t retval;
++ struct efx_nic *efx = net_dev->priv;
++ int rc;
+
-+ 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);
++ mutex_lock(&efx->mac_lock);
++ rc = falcon_xmac_get_settings(efx, ecmd);
++ mutex_unlock(&efx->mac_lock);
+
-+ dmasm = readl(&lp->rx_dma_regs->dmasm);
-+ writel(dmasm | (DMA_STAT_DONE |
-+ DMA_STAT_HALT | DMA_STAT_ERR),
-+ &lp->rx_dma_regs->dmasm);
++ return rc;
++}
+
-+ if (dmas & DMA_STAT_ERR)
-+ printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name);
++/* This must be called with rtnl_lock held. */
++int efx_ethtool_set_settings(struct net_device *net_dev,
++ struct ethtool_cmd *ecmd)
++{
++ struct efx_nic *efx = net_dev->priv;
++ int rc;
+
-+ retval = IRQ_HANDLED;
-+ } else
-+ retval = IRQ_NONE;
++ mutex_lock(&efx->mac_lock);
++ rc = falcon_xmac_set_settings(efx, ecmd);
++ mutex_unlock(&efx->mac_lock);
++ if (!rc)
++ efx_reconfigure_port(efx);
+
-+ return retval;
++ return rc;
+}
+
-+static int korina_rx(struct net_device *dev, int limit)
++static void efx_ethtool_get_drvinfo(struct net_device *net_dev,
++ struct ethtool_drvinfo *info)
+{
-+ 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;
++ struct efx_nic *efx = net_dev->priv;
+
-+ dma_cache_inv((u32)rd, sizeof(*rd));
++ strlcpy(info->driver, EFX_DRIVER_NAME, sizeof(info->driver));
++ strlcpy(info->version, EFX_DRIVER_VERSION, sizeof(info->version));
++ strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
++}
+
-+ for (count = 0; count < limit; count++) {
++static int efx_ethtool_get_stats_count(struct net_device *net_dev)
++{
++ return EFX_ETHTOOL_NUM_STATS;
++}
+
-+ devcs = rd->devcs;
++static void efx_ethtool_get_strings(struct net_device *net_dev,
++ u32 string_set, u8 *strings)
++{
++ struct ethtool_string *ethtool_strings =
++ (struct ethtool_string *)strings;
++ int i;
+
-+ /* 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 (string_set == ETH_SS_STATS)
++ for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++)
++ strncpy(ethtool_strings[i].name,
++ efx_ethtool_stats[i].name,
++ sizeof(ethtool_strings[i].name));
++}
+
-+ 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++;
-+ }
++static void efx_ethtool_get_stats(struct net_device *net_dev,
++ struct ethtool_stats *stats,
++ u64 *data)
++{
++ struct efx_nic *efx = net_dev->priv;
++ struct efx_mac_stats *mac_stats = &efx->mac_stats;
++ struct efx_ethtool_stat *stat;
++ struct efx_channel *channel;
++ int i;
+
-+ 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];
++ EFX_BUG_ON_PARANOID(stats->n_stats != EFX_ETHTOOL_NUM_STATS);
+
-+ if ((devcs & ETH_RX_ROK)) {
-+ /* must be the (first and) last
-+ * descriptor then */
-+ pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data;
++ /* Update MAC and NIC statistics */
++ net_dev->get_stats(net_dev);
+
-+ /* invalidate the cache */
-+ dma_cache_inv((unsigned long)pkt_buf, pkt_len - 4);
++ /* Fill detailed statistics buffer */
++ for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) {
++ stat = &efx_ethtool_stats[i];
++ switch (stat->source) {
++ case EFX_ETHTOOL_STAT_SOURCE_mac_stats:
++ data[i] = stat->get_stat((void *)mac_stats +
++ stat->offset);
++ break;
++ case EFX_ETHTOOL_STAT_SOURCE_nic:
++ data[i] = stat->get_stat((void *)efx + stat->offset);
++ break;
++ case EFX_ETHTOOL_STAT_SOURCE_channel:
++ data[i] = 0;
++ efx_for_each_channel(channel, efx)
++ data[i] += stat->get_stat((void *)channel +
++ stat->offset);
++ break;
++ }
++ }
++}
+
-+ /* Malloc up new buffer. */
-+ skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2);
++static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable)
++{
++ struct efx_nic *efx = net_dev->priv;
++ int rc;
+
-+ if (!skb_new)
-+ break;
-+ /* Do not count the CRC */
-+ skb_put(skb, pkt_len - 4);
-+ skb->protocol = eth_type_trans(skb, dev);
++ rc = ethtool_op_set_tx_csum(net_dev, enable);
++ if (rc)
++ return rc;
+
-+ /* Pass the packet to upper layers */
-+ netif_receive_skb(skb);
-+ dev->last_rx = jiffies;
-+ dev->stats.rx_packets++;
-+ dev->stats.rx_bytes += pkt_len;
++ efx_flush_queues(efx);
+
-+ /* Update the mcast stats */
-+ if (devcs & ETH_RX_MP)
-+ dev->stats.multicast++;
++ return 0;
++}
+
-+ lp->rx_skb[lp->rx_next_done] = skb_new;
-+ }
++static int efx_ethtool_set_rx_csum(struct net_device *net_dev, u32 enable)
++{
++ struct efx_nic *efx = net_dev->priv;
+
-+ rd->devcs = 0;
++ /* No way to stop the hardware doing the checks; we just
++ * ignore the result.
++ */
++ efx->rx_checksum_enabled = (enable ? 1 : 0);
+
-+ /* Restore descriptor's curr_addr */
-+ if (skb_new)
-+ rd->ca = CPHYSADDR(skb_new->data);
-+ else
-+ rd->ca = CPHYSADDR(skb->data);
++ return 0;
++}
+
-+ 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;
++static u32 efx_ethtool_get_rx_csum(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
+
-+ 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);
-+ }
-+ }
++ return efx->rx_checksum_enabled;
++}
+
-+ dmas = readl(&lp->rx_dma_regs->dmas);
++/* Restart autonegotiation */
++static int efx_ethtool_nway_reset(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
+
-+ if (dmas & DMA_STAT_HALT) {
-+ writel(~(DMA_STAT_HALT | DMA_STAT_ERR),
-+ &lp->rx_dma_regs->dmas);
++ return mii_nway_restart(&efx->mii);
++}
+
-+ 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);
-+ }
++static u32 efx_ethtool_get_link(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
+
-+ return count;
++ return efx->link_up;
+}
+
-+static int korina_poll(struct napi_struct *napi, int budget)
++static int efx_ethtool_get_coalesce(struct net_device *net_dev,
++ struct ethtool_coalesce *coalesce)
+{
-+ struct korina_private *lp =
-+ container_of(napi, struct korina_private, napi);
-+ struct net_device *dev = lp->dev;
-+ int work_done;
++ struct efx_nic *efx = net_dev->priv;
++ struct efx_tx_queue *tx_queue;
++ struct efx_rx_queue *rx_queue;
++ struct efx_channel *channel;
+
-+ work_done = korina_rx(dev, budget);
-+ if (work_done < budget) {
-+ netif_rx_complete(dev, napi);
++ memset(coalesce, 0, sizeof(*coalesce));
+
-+ writel(readl(&lp->rx_dma_regs->dmasm) &
-+ ~(DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR),
-+ &lp->rx_dma_regs->dmasm);
++ /* Find lowest IRQ moderation across all used TX queues */
++ coalesce->tx_coalesce_usecs_irq = ~((u32) 0);
++ efx_for_each_tx_queue(tx_queue, efx) {
++ channel = tx_queue->channel;
++ if (channel->irq_moderation < coalesce->tx_coalesce_usecs_irq) {
++ if (channel->used_flags != EFX_USED_BY_RX_TX)
++ coalesce->tx_coalesce_usecs_irq =
++ channel->irq_moderation;
++ else
++ coalesce->tx_coalesce_usecs_irq = 0;
++ }
+ }
-+ return work_done;
++
++ /* Find lowest IRQ moderation across all used RX queues */
++ coalesce->rx_coalesce_usecs_irq = ~((u32) 0);
++ efx_for_each_rx_queue(rx_queue, efx) {
++ channel = rx_queue->channel;
++ if (channel->irq_moderation < coalesce->rx_coalesce_usecs_irq)
++ coalesce->rx_coalesce_usecs_irq =
++ channel->irq_moderation;
++ }
++
++ return 0;
+}
+
-+/*
-+ * Set or clear the multicast filter for this adaptor.
++/* Set coalescing parameters
++ * The difficulties occur for shared channels
+ */
-+static void korina_multicast_list(struct net_device *dev)
++static int efx_ethtool_set_coalesce(struct net_device *net_dev,
++ struct ethtool_coalesce *coalesce)
+{
-+ 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;
++ struct efx_nic *efx = net_dev->priv;
++ struct efx_channel *channel;
++ struct efx_tx_queue *tx_queue;
++ unsigned tx_usecs, rx_usecs;
+
-+ /* Set promiscuous mode */
-+ if (dev->flags & IFF_PROMISC)
-+ recognise |= ETH_ARC_PRO;
++ if (coalesce->use_adaptive_rx_coalesce ||
++ coalesce->use_adaptive_tx_coalesce)
++ return -EOPNOTSUPP;
+
-+ else if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 4))
-+ /* All multicast and broadcast */
-+ recognise |= ETH_ARC_AM;
++ if (coalesce->rx_coalesce_usecs || coalesce->tx_coalesce_usecs) {
++ EFX_ERR(efx, "invalid coalescing setting. "
++ "Only rx/tx_coalesce_usecs_irq are supported\n");
++ return -EOPNOTSUPP;
++ }
+
-+ /* Build the hash table */
-+ if (dev->mc_count > 4) {
-+ u16 hash_table[4];
-+ u32 crc;
++ rx_usecs = coalesce->rx_coalesce_usecs_irq;
++ tx_usecs = coalesce->tx_coalesce_usecs_irq;
+
-+ for (i = 0; i < 4; i++)
-+ hash_table[i] = 0;
++ /* If the channel is shared only allow RX parameters to be set */
++ efx_for_each_tx_queue(tx_queue, efx) {
++ if ((tx_queue->channel->used_flags == EFX_USED_BY_RX_TX) &&
++ tx_usecs) {
++ EFX_ERR(efx, "Channel is shared. "
++ "Only RX coalescing may be set\n");
++ return -EOPNOTSUPP;
++ }
++ }
+
-+ for (i = 0; i < dev->mc_count; i++) {
-+ char *addrs = dmi->dmi_addr;
++ efx_init_irq_moderation(efx, tx_usecs, rx_usecs);
+
-+ dmi = dmi->next;
++ /* Reset channel to pick up new moderation value. Note that
++ * this may change the value of the irq_moderation field
++ * (e.g. to allow for hardware timer granularity).
++ */
++ efx_for_each_channel(channel, efx)
++ falcon_set_int_moderation(channel);
+
-+ if (!(*addrs & 1))
-+ continue;
++ return 0;
++}
+
-+ crc = ether_crc_le(6, addrs);
-+ crc >>= 26;
-+ hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
-+ }
-+ /* Accept filtered multicast */
-+ recognise |= ETH_ARC_AFM;
++static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
++ struct ethtool_pauseparam *pause)
++{
++ struct efx_nic *efx = net_dev->priv;
++ enum efx_fc_type flow_control = efx->flow_control;
++ int rc;
+
-+ /* 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);
-+ }
++ flow_control &= ~(EFX_FC_RX | EFX_FC_TX | EFX_FC_AUTO);
++ flow_control |= pause->rx_pause ? EFX_FC_RX : 0;
++ flow_control |= pause->tx_pause ? EFX_FC_TX : 0;
++ flow_control |= pause->autoneg ? EFX_FC_AUTO : 0;
++
++ /* Try to push the pause parameters */
++ mutex_lock(&efx->mac_lock);
++ rc = falcon_xmac_set_pause(efx, flow_control);
++ mutex_unlock(&efx->mac_lock);
+
-+ spin_lock_irqsave(&lp->lock, flags);
-+ writel(recognise, &lp->eth_regs->etharc);
-+ spin_unlock_irqrestore(&lp->lock, flags);
++ if (!rc)
++ efx_reconfigure_port(efx);
++
++ return rc;
+}
+
-+static void korina_tx(struct net_device *dev)
++static void efx_ethtool_get_pauseparam(struct net_device *net_dev,
++ struct ethtool_pauseparam *pause)
+{
-+ struct korina_private *lp = netdev_priv(dev);
-+ struct dma_desc *td = &lp->td_ring[lp->tx_next_done];
-+ u32 devcs;
-+ u32 dmas;
++ struct efx_nic *efx = net_dev->priv;
+
-+ spin_lock(&lp->lock);
++ pause->rx_pause = (efx->flow_control & EFX_FC_RX) ? 1 : 0;
++ pause->tx_pause = (efx->flow_control & EFX_FC_TX) ? 1 : 0;
++ pause->autoneg = (efx->flow_control & EFX_FC_AUTO) ? 1 : 0;
++}
+
-+ /* 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++;
++struct ethtool_ops efx_ethtool_ops = {
++ .get_settings = efx_ethtool_get_settings,
++ .set_settings = efx_ethtool_set_settings,
++ .get_drvinfo = efx_ethtool_get_drvinfo,
++ .nway_reset = efx_ethtool_nway_reset,
++ .get_link = efx_ethtool_get_link,
++ .get_coalesce = efx_ethtool_get_coalesce,
++ .set_coalesce = efx_ethtool_set_coalesce,
++ .get_pauseparam = efx_ethtool_get_pauseparam,
++ .set_pauseparam = efx_ethtool_set_pauseparam,
++ .get_rx_csum = efx_ethtool_get_rx_csum,
++ .set_rx_csum = efx_ethtool_set_rx_csum,
++ .get_tx_csum = ethtool_op_get_tx_csum,
++ .set_tx_csum = efx_ethtool_set_tx_csum,
++ .get_sg = ethtool_op_get_sg,
++ .set_sg = ethtool_op_set_sg,
++ .get_flags = ethtool_op_get_flags,
++ .set_flags = ethtool_op_set_flags,
++ .get_strings = efx_ethtool_get_strings,
++ .phys_id = efx_ethtool_phys_id,
++ .get_stats_count = efx_ethtool_get_stats_count,
++ .get_ethtool_stats = efx_ethtool_get_stats,
++};
+diff --git a/drivers/net/sfc/ethtool.h b/drivers/net/sfc/ethtool.h
+new file mode 100644
+index 0000000..3628e43
+--- /dev/null
++++ b/drivers/net/sfc/ethtool.h
+@@ -0,0 +1,27 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005 Fen Systems Ltd.
++ * Copyright 2006 Solarflare Communications 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, incorporated herein by reference.
++ */
+
-+ /* 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++;
++#ifndef EFX_ETHTOOL_H
++#define EFX_ETHTOOL_H
+
-+ /* Underflow */
-+ if (devcs & ETH_TX_UND)
-+ dev->stats.tx_fifo_errors++;
++#include "net_driver.h"
+
-+ /* Oversized frame */
-+ if (devcs & ETH_TX_OF)
-+ dev->stats.tx_aborted_errors++;
++/*
++ * Ethtool support
++ */
+
-+ /* Excessive deferrals */
-+ if (devcs & ETH_TX_ED)
-+ dev->stats.tx_carrier_errors++;
++extern int efx_ethtool_get_settings(struct net_device *net_dev,
++ struct ethtool_cmd *ecmd);
++extern int efx_ethtool_set_settings(struct net_device *net_dev,
++ struct ethtool_cmd *ecmd);
+
-+ /* Collisions: medium busy */
-+ if (devcs & ETH_TX_EC)
-+ dev->stats.collisions++;
++extern struct ethtool_ops efx_ethtool_ops;
+
-+ /* Late collision */
-+ if (devcs & ETH_TX_LC)
-+ dev->stats.tx_window_errors++;
-+ }
++#endif /* EFX_ETHTOOL_H */
+diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
+new file mode 100644
+index 0000000..46db549
+--- /dev/null
++++ b/drivers/net/sfc/falcon.c
+@@ -0,0 +1,2722 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005-2006 Fen Systems Ltd.
++ * Copyright 2006-2008 Solarflare Communications 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, incorporated herein by reference.
++ */
+
-+ /* 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;
-+ }
++#include <linux/bitops.h>
++#include <linux/delay.h>
++#include <linux/pci.h>
++#include <linux/module.h>
++#include <linux/seq_file.h>
++#include "net_driver.h"
++#include "bitfield.h"
++#include "efx.h"
++#include "mac.h"
++#include "gmii.h"
++#include "spi.h"
++#include "falcon.h"
++#include "falcon_hwdefs.h"
++#include "falcon_io.h"
++#include "mdio_10g.h"
++#include "phy.h"
++#include "boards.h"
++#include "workarounds.h"
++
++/* Falcon hardware control.
++ * Falcon is the internal codename for the SFC4000 controller that is
++ * present in SFE400X evaluation boards
++ */
+
-+ 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--;
++/**
++ * struct falcon_nic_data - Falcon NIC state
++ * @next_buffer_table: First available buffer table id
++ * @pci_dev2: The secondary PCI device if present
++ */
++struct falcon_nic_data {
++ unsigned next_buffer_table;
++ struct pci_dev *pci_dev2;
++};
+
-+ /* 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];
++/**************************************************************************
++ *
++ * Configurable values
++ *
++ **************************************************************************
++ */
+
-+ }
++static int disable_dma_stats;
+
-+ /* Clear the DMA status register */
-+ dmas = readl(&lp->tx_dma_regs->dmas);
-+ writel(~dmas, &lp->tx_dma_regs->dmas);
++/* This is set to 16 for a good reason. In summary, if larger than
++ * 16, the descriptor cache holds more than a default socket
++ * buffer's worth of packets (for UDP we can only have at most one
++ * socket buffer's worth outstanding). This combined with the fact
++ * that we only get 1 TX event per descriptor cache means the NIC
++ * goes idle.
++ */
++#define TX_DC_ENTRIES 16
++#define TX_DC_ENTRIES_ORDER 0
++#define TX_DC_BASE 0x130000
+
-+ writel(readl(&lp->tx_dma_regs->dmasm) &
-+ ~(DMA_STAT_FINI | DMA_STAT_ERR),
-+ &lp->tx_dma_regs->dmasm);
++#define RX_DC_ENTRIES 64
++#define RX_DC_ENTRIES_ORDER 2
++#define RX_DC_BASE 0x100000
+
-+ spin_unlock(&lp->lock);
-+}
++/* RX FIFO XOFF watermark
++ *
++ * When the amount of the RX FIFO increases used increases past this
++ * watermark send XOFF. Only used if RX flow control is enabled (ethtool -A)
++ * This also has an effect on RX/TX arbitration
++ */
++static int rx_xoff_thresh_bytes = -1;
++module_param(rx_xoff_thresh_bytes, int, 0644);
++MODULE_PARM_DESC(rx_xoff_thresh_bytes, "RX fifo XOFF threshold");
+
-+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;
++/* RX FIFO XON watermark
++ *
++ * When the amount of the RX FIFO used decreases below this
++ * watermark send XON. Only used if TX flow control is enabled (ethtool -A)
++ * This also has an effect on RX/TX arbitration
++ */
++static int rx_xon_thresh_bytes = -1;
++module_param(rx_xon_thresh_bytes, int, 0644);
++MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold");
+
-+ dmas = readl(&lp->tx_dma_regs->dmas);
++/* TX descriptor ring size - min 512 max 4k */
++#define FALCON_TXD_RING_ORDER TX_DESCQ_SIZE_1K
++#define FALCON_TXD_RING_SIZE 1024
++#define FALCON_TXD_RING_MASK (FALCON_TXD_RING_SIZE - 1)
+
-+ if (dmas & (DMA_STAT_FINI | DMA_STAT_ERR)) {
-+ korina_tx(dev);
++/* RX descriptor ring size - min 512 max 4k */
++#define FALCON_RXD_RING_ORDER RX_DESCQ_SIZE_1K
++#define FALCON_RXD_RING_SIZE 1024
++#define FALCON_RXD_RING_MASK (FALCON_RXD_RING_SIZE - 1)
+
-+ dmasm = readl(&lp->tx_dma_regs->dmasm);
-+ writel(dmasm | (DMA_STAT_FINI | DMA_STAT_ERR),
-+ &lp->tx_dma_regs->dmasm);
++/* Event queue size - max 32k */
++#define FALCON_EVQ_ORDER EVQ_SIZE_4K
++#define FALCON_EVQ_SIZE 4096
++#define FALCON_EVQ_MASK (FALCON_EVQ_SIZE - 1)
+
-+ 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);
++/* Max number of internal errors. After this resets will not be performed */
++#define FALCON_MAX_INT_ERRORS 4
+
-+ retval = IRQ_HANDLED;
-+ } else
-+ retval = IRQ_NONE;
++/* Maximum period that we wait for flush events. If the flush event
++ * doesn't arrive in this period of time then we check if the queue
++ * was disabled anyway. */
++#define FALCON_FLUSH_TIMEOUT 10 /* 10ms */
+
-+ return retval;
-+}
++/**************************************************************************
++ *
++ * Falcon constants
++ *
++ **************************************************************************
++ */
+
++/* DMA address mask (up to 46-bit, avoiding compiler warnings)
++ *
++ * Note that it is possible to have a platform with 64-bit longs and
++ * 32-bit DMA addresses, or vice versa. EFX_DMA_MASK takes care of the
++ * platform DMA mask.
++ */
++#if BITS_PER_LONG == 64
++#define FALCON_DMA_MASK EFX_DMA_MASK(0x00003fffffffffffUL)
++#else
++#define FALCON_DMA_MASK EFX_DMA_MASK(0x00003fffffffffffULL)
++#endif
+
-+static void korina_check_media(struct net_device *dev, unsigned int init_media)
-+{
-+ struct korina_private *lp = netdev_priv(dev);
++/* TX DMA length mask (13-bit) */
++#define FALCON_TX_DMA_MASK (4096 - 1)
+
-+ mii_check_media(&lp->mii_if, 0, init_media);
++/* Size and alignment of special buffers (4KB) */
++#define FALCON_BUF_SIZE 4096
+
-+ 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);
-+}
++/* Dummy SRAM size code */
++#define SRM_NB_BSZ_ONCHIP_ONLY (-1)
+
-+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);
-+}
++/* Be nice if these (or equiv.) were in linux/pci_regs.h, but they're not. */
++#define PCI_EXP_DEVCAP_PWR_VAL_LBN 18
++#define PCI_EXP_DEVCAP_PWR_SCL_LBN 26
++#define PCI_EXP_DEVCTL_PAYLOAD_LBN 5
++#define PCI_EXP_LNKSTA_LNK_WID 0x3f0
++#define PCI_EXP_LNKSTA_LNK_WID_LBN 4
+
-+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;
++#define FALCON_IS_DUAL_FUNC(efx) \
++ (FALCON_REV(efx) < FALCON_REV_B0)
+
-+ 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);
++/**************************************************************************
++ *
++ * Falcon hardware access
++ *
++ **************************************************************************/
+
-+ return rc;
++/* Read the current event from the event queue */
++static inline efx_qword_t *falcon_event(struct efx_channel *channel,
++ unsigned int index)
++{
++ return (((efx_qword_t *) (channel->eventq.addr)) + index);
+}
+
-+/* ethtool helpers */
-+static void netdev_get_drvinfo(struct net_device *dev,
-+ struct ethtool_drvinfo *info)
++/* See if an event is present
++ *
++ * We check both the high and low dword of the event for all ones. We
++ * wrote all ones when we cleared the event, and no valid event can
++ * have all ones in either its high or low dwords. This approach is
++ * robust against reordering.
++ *
++ * Note that using a single 64-bit comparison is incorrect; even
++ * though the CPU read will be atomic, the DMA write may not be.
++ */
++static inline int falcon_event_present(efx_qword_t *event)
+{
-+ struct korina_private *lp = netdev_priv(dev);
-+
-+ strcpy(info->driver, DRV_NAME);
-+ strcpy(info->version, DRV_VERSION);
-+ strcpy(info->bus_info, lp->dev->name);
++ return (!(EFX_DWORD_IS_ALL_ONES(event->dword[0]) |
++ EFX_DWORD_IS_ALL_ONES(event->dword[1])));
+}
+
-+static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++/**************************************************************************
++ *
++ * I2C bus - this is a bit-bashing interface using GPIO pins
++ * Note that it uses the output enables to tristate the outputs
++ * SDA is the data pin and SCL is the clock
++ *
++ **************************************************************************
++ */
++static void falcon_setsdascl(struct efx_i2c_interface *i2c)
+{
-+ 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);
++ efx_oword_t reg;
+
-+ return rc;
++ falcon_read(i2c->efx, ®, GPIO_CTL_REG_KER);
++ EFX_SET_OWORD_FIELD(reg, GPIO0_OEN, (i2c->scl ? 0 : 1));
++ EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, (i2c->sda ? 0 : 1));
++ falcon_write(i2c->efx, ®, GPIO_CTL_REG_KER);
+}
+
-+static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++static int falcon_getsda(struct efx_i2c_interface *i2c)
+{
-+ 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);
++ efx_oword_t reg;
+
-+ return rc;
++ falcon_read(i2c->efx, ®, GPIO_CTL_REG_KER);
++ return EFX_OWORD_FIELD(reg, GPIO3_IN);
+}
+
-+static u32 netdev_get_link(struct net_device *dev)
++static int falcon_getscl(struct efx_i2c_interface *i2c)
+{
-+ struct korina_private *lp = netdev_priv(dev);
++ efx_oword_t reg;
+
-+ return mii_link_ok(&lp->mii_if);
++ falcon_read(i2c->efx, ®, GPIO_CTL_REG_KER);
++ return EFX_DWORD_FIELD(reg, GPIO0_IN);
+}
+
-+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 struct efx_i2c_bit_operations falcon_i2c_bit_operations = {
++ .setsda = falcon_setsdascl,
++ .setscl = falcon_setsdascl,
++ .getsda = falcon_getsda,
++ .getscl = falcon_getscl,
++ .udelay = 100,
++ .mdelay = 10,
+};
+
-+static void korina_alloc_ring(struct net_device *dev)
++/**************************************************************************
++ *
++ * Falcon special buffer handling
++ * Special buffers are used for event queues and the TX and RX
++ * descriptor rings.
++ *
++ *************************************************************************/
++
++/*
++ * Initialise a Falcon special buffer
++ *
++ * This will define a buffer (previously allocated via
++ * falcon_alloc_special_buffer()) in Falcon's buffer table, allowing
++ * it to be used for event queues, descriptor rings etc.
++ */
++static int
++falcon_init_special_buffer(struct efx_nic *efx,
++ struct efx_special_buffer *buffer)
+{
-+ struct korina_private *lp = netdev_priv(dev);
++ efx_qword_t buf_desc;
++ int index;
++ dma_addr_t dma_addr;
+ 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];
++ EFX_BUG_ON_PARANOID(!buffer->addr);
+
-+ 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]);
++ /* Write buffer descriptors to NIC */
++ for (i = 0; i < buffer->entries; i++) {
++ index = buffer->index + i;
++ dma_addr = buffer->dma_addr + (i * 4096);
++ EFX_LOG(efx, "mapping special buffer %d at %llx\n",
++ index, (unsigned long long)dma_addr);
++ EFX_POPULATE_QWORD_4(buf_desc,
++ IP_DAT_BUF_SIZE, IP_DAT_BUF_SIZE_4K,
++ BUF_ADR_REGION, 0,
++ BUF_ADR_FBUF, (dma_addr >> 12),
++ BUF_OWNER_ID_FBUF, 0);
++ falcon_write_sram(efx, &buf_desc, index);
+ }
+
-+ /* 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;
++ return 0;
+}
+
-+static void korina_free_ring(struct net_device *dev)
++/* Unmaps a buffer from Falcon and clears the buffer table entries */
++static void
++falcon_fini_special_buffer(struct efx_nic *efx,
++ struct efx_special_buffer *buffer)
+{
-+ struct korina_private *lp = netdev_priv(dev);
-+ int i;
++ efx_oword_t buf_tbl_upd;
++ unsigned int start = buffer->index;
++ unsigned int end = (buffer->index + buffer->entries - 1);
+
-+ 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;
-+ }
++ if (!buffer->entries)
++ return;
+
-+ 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;
-+ }
++ EFX_LOG(efx, "unmapping special buffers %d-%d\n",
++ buffer->index, buffer->index + buffer->entries - 1);
++
++ EFX_POPULATE_OWORD_4(buf_tbl_upd,
++ BUF_UPD_CMD, 0,
++ BUF_CLR_CMD, 1,
++ BUF_CLR_END_ID, end,
++ BUF_CLR_START_ID, start);
++ falcon_write(efx, &buf_tbl_upd, BUF_TBL_UPD_REG_KER);
+}
+
+/*
-+ * Initialize the RC32434 ethernet controller.
++ * Allocate a new Falcon special buffer
++ *
++ * This allocates memory for a new buffer, clears it and allocates a
++ * new buffer ID range. It does not write into Falcon's buffer table.
++ *
++ * This call will allocate 4KB buffers, since Falcon can't use 8KB
++ * buffers for event queues and descriptor rings.
+ */
-+static int korina_init(struct net_device *dev)
++static int falcon_alloc_special_buffer(struct efx_nic *efx,
++ struct efx_special_buffer *buffer,
++ unsigned int len)
+{
-+ 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);
++ struct falcon_nic_data *nic_data = efx->nic_data;
+
-+ writel(0, &lp->rx_dma_regs->dmas);
-+ /* Start Rx DMA */
-+ korina_start_rx(lp, &lp->rd_ring[0]);
++ len = ALIGN(len, FALCON_BUF_SIZE);
+
-+ 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);
++ buffer->addr = pci_alloc_consistent(efx->pci_dev, len,
++ &buffer->dma_addr);
++ if (!buffer->addr)
++ return -ENOMEM;
++ buffer->len = len;
++ buffer->entries = len / FALCON_BUF_SIZE;
++ BUG_ON(buffer->dma_addr & (FALCON_BUF_SIZE - 1));
+
-+ /* Accept only packets destined for this Ethernet device address */
-+ writel(ETH_ARC_AB, &lp->eth_regs->etharc);
++ /* All zeros is a potentially valid event so memset to 0xff */
++ memset(buffer->addr, 0xff, len);
+
-+ /* 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);
++ /* Select new buffer ID */
++ buffer->index = nic_data->next_buffer_table;
++ nic_data->next_buffer_table += buffer->entries;
+
-+ writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal1);
-+ writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah1);
++ EFX_LOG(efx, "allocating special buffers %d-%d at %llx+%x "
++ "(virt %p phys %lx)\n", buffer->index,
++ buffer->index + buffer->entries - 1,
++ (unsigned long long)buffer->dma_addr, len,
++ buffer->addr, virt_to_phys(buffer->addr));
+
-+ writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal2);
-+ writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah2);
++ return 0;
++}
+
-+ writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal3);
-+ writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah3);
++static void falcon_free_special_buffer(struct efx_nic *efx,
++ struct efx_special_buffer *buffer)
++{
++ if (!buffer->addr)
++ return;
+
++ EFX_LOG(efx, "deallocating special buffers %d-%d at %llx+%x "
++ "(virt %p phys %lx)\n", buffer->index,
++ buffer->index + buffer->entries - 1,
++ (unsigned long long)buffer->dma_addr, buffer->len,
++ buffer->addr, virt_to_phys(buffer->addr));
++
++ pci_free_consistent(efx->pci_dev, buffer->len, buffer->addr,
++ buffer->dma_addr);
++ buffer->addr = NULL;
++ buffer->entries = 0;
++}
+
-+ /* Frame Length Checking, Pad Enable, CRC Enable, Full Duplex set */
-+ writel(ETH_MAC2_PE | ETH_MAC2_CEN | ETH_MAC2_FD,
-+ &lp->eth_regs->ethmac2);
++/**************************************************************************
++ *
++ * Falcon generic buffer handling
++ * These buffers are used for interrupt status and MAC stats
++ *
++ **************************************************************************/
+
-+ /* 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);
++static int falcon_alloc_buffer(struct efx_nic *efx,
++ struct efx_buffer *buffer, unsigned int len)
++{
++ buffer->addr = pci_alloc_consistent(efx->pci_dev, len,
++ &buffer->dma_addr);
++ if (!buffer->addr)
++ return -ENOMEM;
++ buffer->len = len;
++ memset(buffer->addr, 0, len);
++ return 0;
++}
+
-+ /* Management Clock Prescaler Divisor
-+ * Clock independent setting */
-+ writel(((idt_cpu_freq) / MII_CLOCK + 1) & ~1,
-+ &lp->eth_regs->ethmcp);
++static void falcon_free_buffer(struct efx_nic *efx, struct efx_buffer *buffer)
++{
++ if (buffer->addr) {
++ pci_free_consistent(efx->pci_dev, buffer->len,
++ buffer->addr, buffer->dma_addr);
++ buffer->addr = NULL;
++ }
++}
+
-+ /* don't transmit until fifo contains 48b */
-+ writel(48, &lp->eth_regs->ethfifott);
++/**************************************************************************
++ *
++ * Falcon TX path
++ *
++ **************************************************************************/
+
-+ writel(ETH_MAC1_RE, &lp->eth_regs->ethmac1);
++/* Returns a pointer to the specified transmit descriptor in the TX
++ * descriptor queue belonging to the specified channel.
++ */
++static inline efx_qword_t *falcon_tx_desc(struct efx_tx_queue *tx_queue,
++ unsigned int index)
++{
++ return (((efx_qword_t *) (tx_queue->txd.addr)) + index);
++}
+
-+ napi_enable(&lp->napi);
-+ netif_start_queue(dev);
++/* This writes to the TX_DESC_WPTR; write pointer for TX descriptor ring */
++static inline void falcon_notify_tx_desc(struct efx_tx_queue *tx_queue)
++{
++ unsigned write_ptr;
++ efx_dword_t reg;
+
-+ return 0;
++ write_ptr = tx_queue->write_count & FALCON_TXD_RING_MASK;
++ EFX_POPULATE_DWORD_1(reg, TX_DESC_WPTR_DWORD, write_ptr);
++ falcon_writel_page(tx_queue->efx, ®,
++ TX_DESC_UPD_REG_KER_DWORD, tx_queue->queue);
+}
+
-+/*
-+ * Restart the RC32434 ethernet controller.
-+ * FIXME: check the return status where we call it
++
++/* For each entry inserted into the software descriptor ring, create a
++ * descriptor in the hardware TX descriptor ring (in host memory), and
++ * write a doorbell.
+ */
-+static int korina_restart(struct net_device *dev)
++void falcon_push_buffers(struct efx_tx_queue *tx_queue)
+{
-+ 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);
++ struct efx_tx_buffer *buffer;
++ efx_qword_t *txd;
++ unsigned write_ptr;
+
-+ 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);
++ BUG_ON(tx_queue->write_count == tx_queue->insert_count);
+
-+ korina_free_ring(dev);
++ do {
++ write_ptr = tx_queue->write_count & FALCON_TXD_RING_MASK;
++ buffer = &tx_queue->buffer[write_ptr];
++ txd = falcon_tx_desc(tx_queue, write_ptr);
++ ++tx_queue->write_count;
+
-+ 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);
++ /* Create TX descriptor ring entry */
++ EFX_POPULATE_QWORD_5(*txd,
++ TX_KER_PORT, 0,
++ TX_KER_CONT, buffer->continuation,
++ TX_KER_BYTE_CNT, buffer->len,
++ TX_KER_BUF_REGION, 0,
++ TX_KER_BUF_ADR, buffer->dma_addr);
++ } while (tx_queue->write_count != tx_queue->insert_count);
+
-+ enable_irq(lp->und_irq);
-+ enable_irq(lp->ovr_irq);
-+ enable_irq(lp->tx_irq);
-+ enable_irq(lp->rx_irq);
++ wmb(); /* Ensure descriptors are written before they are fetched */
++ falcon_notify_tx_desc(tx_queue);
++}
+
-+ return ret;
++/* Allocate hardware resources for a TX queue */
++int falcon_probe_tx(struct efx_tx_queue *tx_queue)
++{
++ struct efx_nic *efx = tx_queue->efx;
++ return falcon_alloc_special_buffer(efx, &tx_queue->txd,
++ FALCON_TXD_RING_SIZE *
++ sizeof(efx_qword_t));
+}
+
-+static void korina_clear_and_restart(struct net_device *dev, u32 value)
++int falcon_init_tx(struct efx_tx_queue *tx_queue)
+{
-+ struct korina_private *lp = netdev_priv(dev);
++ efx_oword_t tx_desc_ptr;
++ struct efx_nic *efx = tx_queue->efx;
++ int rc;
+
-+ netif_stop_queue(dev);
-+ writel(value, &lp->eth_regs->ethintfc);
-+ korina_restart(dev);
++ /* Pin TX descriptor ring */
++ rc = falcon_init_special_buffer(efx, &tx_queue->txd);
++ if (rc)
++ return rc;
++
++ /* Push TX descriptor ring to card */
++ EFX_POPULATE_OWORD_10(tx_desc_ptr,
++ TX_DESCQ_EN, 1,
++ TX_ISCSI_DDIG_EN, 0,
++ TX_ISCSI_HDIG_EN, 0,
++ TX_DESCQ_BUF_BASE_ID, tx_queue->txd.index,
++ TX_DESCQ_EVQ_ID, tx_queue->channel->evqnum,
++ TX_DESCQ_OWNER_ID, 0,
++ TX_DESCQ_LABEL, tx_queue->queue,
++ TX_DESCQ_SIZE, FALCON_TXD_RING_ORDER,
++ TX_DESCQ_TYPE, 0,
++ TX_NON_IP_DROP_DIS_B0, 1);
++
++ if (FALCON_REV(efx) >= FALCON_REV_B0) {
++ int csum = !(efx->net_dev->features & NETIF_F_IP_CSUM);
++ EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_IP_CHKSM_DIS_B0, csum);
++ EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_TCP_CHKSM_DIS_B0, csum);
++ }
++
++ falcon_write_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base,
++ tx_queue->queue);
++
++ if (FALCON_REV(efx) < FALCON_REV_B0) {
++ efx_oword_t reg;
++
++ BUG_ON(tx_queue->queue >= 128); /* HW limit */
++
++ falcon_read(efx, ®, TX_CHKSM_CFG_REG_KER_A1);
++ if (efx->net_dev->features & NETIF_F_IP_CSUM)
++ clear_bit_le(tx_queue->queue, (void *)®);
++ else
++ set_bit_le(tx_queue->queue, (void *)®);
++ falcon_write(efx, ®, TX_CHKSM_CFG_REG_KER_A1);
++ }
++
++ return 0;
+}
+
-+/* Ethernet Tx Underflow interrupt */
-+static irqreturn_t korina_und_interrupt(int irq, void *dev_id)
++static int falcon_flush_tx_queue(struct efx_tx_queue *tx_queue)
+{
-+ struct net_device *dev = dev_id;
-+ struct korina_private *lp = netdev_priv(dev);
-+ unsigned int und;
++ struct efx_nic *efx = tx_queue->efx;
++ struct efx_channel *channel = &efx->channel[0];
++ efx_oword_t tx_flush_descq;
++ unsigned int read_ptr, i;
+
-+ spin_lock(&lp->lock);
++ /* Post a flush command */
++ EFX_POPULATE_OWORD_2(tx_flush_descq,
++ TX_FLUSH_DESCQ_CMD, 1,
++ TX_FLUSH_DESCQ, tx_queue->queue);
++ falcon_write(efx, &tx_flush_descq, TX_FLUSH_DESCQ_REG_KER);
++ msleep(FALCON_FLUSH_TIMEOUT);
+
-+ und = readl(&lp->eth_regs->ethintfc);
++ if (EFX_WORKAROUND_7803(efx))
++ return 0;
+
-+ if (und & ETH_INT_FC_UND)
-+ korina_clear_and_restart(dev, und & ~ETH_INT_FC_UND);
++ /* Look for a flush completed event */
++ read_ptr = channel->eventq_read_ptr;
++ for (i = 0; i < FALCON_EVQ_SIZE; ++i) {
++ efx_qword_t *event = falcon_event(channel, read_ptr);
++ int ev_code, ev_sub_code, ev_queue;
++ if (!falcon_event_present(event))
++ break;
+
-+ spin_unlock(&lp->lock);
++ ev_code = EFX_QWORD_FIELD(*event, EV_CODE);
++ ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE);
++ ev_queue = EFX_QWORD_FIELD(*event, DRIVER_EV_TX_DESCQ_ID);
++ if ((ev_sub_code == TX_DESCQ_FLS_DONE_EV_DECODE) &&
++ (ev_queue == tx_queue->queue)) {
++ EFX_LOG(efx, "tx queue %d flush command succesful\n",
++ tx_queue->queue);
++ return 0;
++ }
+
-+ return IRQ_HANDLED;
++ read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK;
++ }
++
++ if (EFX_WORKAROUND_11557(efx)) {
++ efx_oword_t reg;
++ int enabled;
++
++ falcon_read_table(efx, ®, efx->type->txd_ptr_tbl_base,
++ tx_queue->queue);
++ enabled = EFX_OWORD_FIELD(reg, TX_DESCQ_EN);
++ if (!enabled) {
++ EFX_LOG(efx, "tx queue %d disabled without a "
++ "flush event seen\n", tx_queue->queue);
++ return 0;
++ }
++ }
++
++ EFX_ERR(efx, "tx queue %d flush command timed out\n", tx_queue->queue);
++ return -ETIMEDOUT;
+}
+
-+static void korina_tx_timeout(struct net_device *dev)
++void falcon_fini_tx(struct efx_tx_queue *tx_queue)
+{
-+ struct korina_private *lp = netdev_priv(dev);
-+ unsigned long flags;
++ struct efx_nic *efx = tx_queue->efx;
++ efx_oword_t tx_desc_ptr;
+
-+ spin_lock_irqsave(&lp->lock, flags);
-+ korina_restart(dev);
-+ spin_unlock_irqrestore(&lp->lock, flags);
++ /* Stop the hardware using the queue */
++ if (falcon_flush_tx_queue(tx_queue))
++ EFX_ERR(efx, "failed to flush tx queue %d\n", tx_queue->queue);
++
++ /* Remove TX descriptor ring from card */
++ EFX_ZERO_OWORD(tx_desc_ptr);
++ falcon_write_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base,
++ tx_queue->queue);
++
++ /* Unpin TX descriptor ring */
++ falcon_fini_special_buffer(efx, &tx_queue->txd);
+}
+
-+/* Ethernet Rx Overflow interrupt */
-+static irqreturn_t
-+korina_ovr_interrupt(int irq, void *dev_id)
++/* Free buffers backing TX queue */
++void falcon_remove_tx(struct efx_tx_queue *tx_queue)
+{
-+ struct net_device *dev = dev_id;
-+ struct korina_private *lp = netdev_priv(dev);
-+ unsigned int ovr;
++ falcon_free_special_buffer(tx_queue->efx, &tx_queue->txd);
++}
+
-+ spin_lock(&lp->lock);
-+ ovr = readl(&lp->eth_regs->ethintfc);
++/**************************************************************************
++ *
++ * Falcon RX path
++ *
++ **************************************************************************/
+
-+ if (ovr & ETH_INT_FC_OVR)
-+ korina_clear_and_restart(dev, ovr & ~ETH_INT_FC_OVR);
++/* Returns a pointer to the specified descriptor in the RX descriptor queue */
++static inline efx_qword_t *falcon_rx_desc(struct efx_rx_queue *rx_queue,
++ unsigned int index)
++{
++ return (((efx_qword_t *) (rx_queue->rxd.addr)) + index);
++}
+
-+ spin_unlock(&lp->lock);
++/* This creates an entry in the RX descriptor queue */
++static inline void falcon_build_rx_desc(struct efx_rx_queue *rx_queue,
++ unsigned index)
++{
++ struct efx_rx_buffer *rx_buf;
++ efx_qword_t *rxd;
+
-+ return IRQ_HANDLED;
++ rxd = falcon_rx_desc(rx_queue, index);
++ rx_buf = efx_rx_buffer(rx_queue, index);
++ EFX_POPULATE_QWORD_3(*rxd,
++ RX_KER_BUF_SIZE,
++ rx_buf->len -
++ rx_queue->efx->type->rx_buffer_padding,
++ RX_KER_BUF_REGION, 0,
++ RX_KER_BUF_ADR, rx_buf->dma_addr);
+}
+
-+#ifdef CONFIG_NET_POLL_CONTROLLER
-+static void korina_poll_controller(struct net_device *dev)
++/* This writes to the RX_DESC_WPTR register for the specified receive
++ * descriptor ring.
++ */
++void falcon_notify_rx_desc(struct efx_rx_queue *rx_queue)
+{
-+ disable_irq(dev->irq);
-+ korina_tx_dma_interrupt(dev->irq, dev);
-+ enable_irq(dev->irq);
++ efx_dword_t reg;
++ unsigned write_ptr;
++
++ while (rx_queue->notified_count != rx_queue->added_count) {
++ falcon_build_rx_desc(rx_queue,
++ rx_queue->notified_count &
++ FALCON_RXD_RING_MASK);
++ ++rx_queue->notified_count;
++ }
++
++ wmb();
++ write_ptr = rx_queue->added_count & FALCON_RXD_RING_MASK;
++ EFX_POPULATE_DWORD_1(reg, RX_DESC_WPTR_DWORD, write_ptr);
++ falcon_writel_page(rx_queue->efx, ®,
++ RX_DESC_UPD_REG_KER_DWORD, rx_queue->queue);
+}
-+#endif
+
-+static int korina_open(struct net_device *dev)
++int falcon_probe_rx(struct efx_rx_queue *rx_queue)
+{
-+ struct korina_private *lp = netdev_priv(dev);
-+ int ret;
++ struct efx_nic *efx = rx_queue->efx;
++ return falcon_alloc_special_buffer(efx, &rx_queue->rxd,
++ FALCON_RXD_RING_SIZE *
++ sizeof(efx_qword_t));
++}
+
-+ /* Initialize */
-+ ret = korina_init(dev);
-+ if (ret < 0) {
-+ printk(KERN_ERR DRV_NAME "%s: cannot open device\n", dev->name);
-+ goto out;
-+ }
++int falcon_init_rx(struct efx_rx_queue *rx_queue)
++{
++ efx_oword_t rx_desc_ptr;
++ struct efx_nic *efx = rx_queue->efx;
++ int rc;
++ int is_b0 = FALCON_REV(efx) >= FALCON_REV_B0;
++ int iscsi_digest_en = is_b0;
+
-+ /* 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;
-+ }
++ EFX_LOG(efx, "RX queue %d ring in special buffers %d-%d\n",
++ rx_queue->queue, rx_queue->rxd.index,
++ rx_queue->rxd.index + rx_queue->rxd.entries - 1);
+
-+ /* 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;
++ /* Pin RX descriptor ring */
++ rc = falcon_init_special_buffer(efx, &rx_queue->rxd);
++ if (rc)
++ return rc;
++
++ /* Push RX descriptor ring to card */
++ EFX_POPULATE_OWORD_10(rx_desc_ptr,
++ RX_ISCSI_DDIG_EN, iscsi_digest_en,
++ RX_ISCSI_HDIG_EN, iscsi_digest_en,
++ RX_DESCQ_BUF_BASE_ID, rx_queue->rxd.index,
++ RX_DESCQ_EVQ_ID, rx_queue->channel->evqnum,
++ RX_DESCQ_OWNER_ID, 0,
++ RX_DESCQ_LABEL, rx_queue->queue,
++ RX_DESCQ_SIZE, FALCON_RXD_RING_ORDER,
++ RX_DESCQ_TYPE, 0 /* kernel queue */ ,
++ /* For >=B0 this is scatter so disable */
++ RX_DESCQ_JUMBO, !is_b0,
++ RX_DESCQ_EN, 1);
++ falcon_write_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
++ rx_queue->queue);
++ return 0;
++}
++
++static int falcon_flush_rx_queue(struct efx_rx_queue *rx_queue)
++{
++ struct efx_nic *efx = rx_queue->efx;
++ struct efx_channel *channel = &efx->channel[0];
++ unsigned int read_ptr, i;
++ efx_oword_t rx_flush_descq;
++
++ /* Post a flush command */
++ EFX_POPULATE_OWORD_2(rx_flush_descq,
++ RX_FLUSH_DESCQ_CMD, 1,
++ RX_FLUSH_DESCQ, rx_queue->queue);
++ falcon_write(efx, &rx_flush_descq, RX_FLUSH_DESCQ_REG_KER);
++ msleep(FALCON_FLUSH_TIMEOUT);
++
++ if (EFX_WORKAROUND_7803(efx))
++ return 0;
++
++ /* Look for a flush completed event */
++ read_ptr = channel->eventq_read_ptr;
++ for (i = 0; i < FALCON_EVQ_SIZE; ++i) {
++ efx_qword_t *event = falcon_event(channel, read_ptr);
++ int ev_code, ev_sub_code, ev_queue, ev_failed;
++ if (!falcon_event_present(event))
++ break;
++
++ ev_code = EFX_QWORD_FIELD(*event, EV_CODE);
++ ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE);
++ ev_queue = EFX_QWORD_FIELD(*event, DRIVER_EV_RX_DESCQ_ID);
++ ev_failed = EFX_QWORD_FIELD(*event, DRIVER_EV_RX_FLUSH_FAIL);
++
++ if ((ev_sub_code == RX_DESCQ_FLS_DONE_EV_DECODE) &&
++ (ev_queue == rx_queue->queue)) {
++ if (ev_failed) {
++ EFX_INFO(efx, "rx queue %d flush command "
++ "failed\n", rx_queue->queue);
++ return -EAGAIN;
++ } else {
++ EFX_LOG(efx, "rx queue %d flush command "
++ "succesful\n", rx_queue->queue);
++ return 0;
++ }
++ }
++
++ read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK;
+ }
+
-+ /* 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;
++ if (EFX_WORKAROUND_11557(efx)) {
++ efx_oword_t reg;
++ int enabled;
++
++ falcon_read_table(efx, ®, efx->type->rxd_ptr_tbl_base,
++ rx_queue->queue);
++ enabled = EFX_OWORD_FIELD(reg, RX_DESCQ_EN);
++ if (!enabled) {
++ EFX_LOG(efx, "rx queue %d disabled without a "
++ "flush event seen\n", rx_queue->queue);
++ return 0;
++ }
+ }
-+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;
++ EFX_ERR(efx, "rx queue %d flush command timed out\n", rx_queue->queue);
++ return -ETIMEDOUT;
+}
+
-+static int korina_close(struct net_device *dev)
++void falcon_fini_rx(struct efx_rx_queue *rx_queue)
+{
-+ struct korina_private *lp = netdev_priv(dev);
-+ u32 tmp;
++ efx_oword_t rx_desc_ptr;
++ struct efx_nic *efx = rx_queue->efx;
++ int i, rc;
+
-+ /* Disable interrupts */
-+ disable_irq(lp->rx_irq);
-+ disable_irq(lp->tx_irq);
-+ disable_irq(lp->ovr_irq);
-+ disable_irq(lp->und_irq);
++ /* Try and flush the rx queue. This may need to be repeated */
++ for (i = 0; i < 5; i++) {
++ rc = falcon_flush_rx_queue(rx_queue);
++ if (rc == -EAGAIN)
++ continue;
++ break;
++ }
++ if (rc)
++ EFX_ERR(efx, "failed to flush rx queue %d\n", rx_queue->queue);
+
-+ 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);
++ /* Remove RX descriptor ring from card */
++ EFX_ZERO_OWORD(rx_desc_ptr);
++ falcon_write_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
++ rx_queue->queue);
+
-+ 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);
++ /* Unpin RX descriptor ring */
++ falcon_fini_special_buffer(efx, &rx_queue->rxd);
++}
+
-+ korina_free_ring(dev);
++/* Free buffers backing RX queue */
++void falcon_remove_rx(struct efx_rx_queue *rx_queue)
++{
++ falcon_free_special_buffer(rx_queue->efx, &rx_queue->rxd);
++}
+
-+ free_irq(lp->rx_irq, dev);
-+ free_irq(lp->tx_irq, dev);
-+ free_irq(lp->ovr_irq, dev);
-+ free_irq(lp->und_irq, dev);
++/**************************************************************************
++ *
++ * Falcon event queue processing
++ * Event queues are processed by per-channel tasklets.
++ *
++ **************************************************************************/
+
-+ return 0;
++/* Update a channel's event queue's read pointer (RPTR) register
++ *
++ * This writes the EVQ_RPTR_REG register for the specified channel's
++ * event queue.
++ *
++ * Note that EVQ_RPTR_REG contains the index of the "last read" event,
++ * whereas channel->eventq_read_ptr contains the index of the "next to
++ * read" event.
++ */
++void falcon_eventq_read_ack(struct efx_channel *channel)
++{
++ efx_dword_t reg;
++ struct efx_nic *efx = channel->efx;
++
++ EFX_POPULATE_DWORD_1(reg, EVQ_RPTR_DWORD, channel->eventq_read_ptr);
++ falcon_writel_table(efx, ®, efx->type->evq_rptr_tbl_base,
++ channel->evqnum);
+}
+
-+static int korina_probe(struct platform_device *pdev)
++/* Use HW to insert a SW defined event */
++void falcon_generate_event(struct efx_channel *channel, efx_qword_t *event)
+{
-+ struct korina_device *bif = platform_get_drvdata(pdev);
-+ struct korina_private *lp;
-+ struct net_device *dev;
-+ struct resource *r;
-+ int rc;
++ efx_oword_t drv_ev_reg;
+
-+ 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);
++ EFX_POPULATE_OWORD_2(drv_ev_reg,
++ DRV_EV_QID, channel->evqnum,
++ DRV_EV_DATA,
++ EFX_QWORD_FIELD64(*event, WHOLE_EVENT));
++ falcon_write(channel->efx, &drv_ev_reg, DRV_EV_REG_KER);
++}
+
-+ bif->dev = dev;
-+ memcpy(dev->dev_addr, bif->mac, 6);
++/* Handle a transmit completion event
++ *
++ * Falcon batches TX completion events; the message we receive is of
++ * the form "complete all TX events up to this index".
++ */
++static inline void falcon_handle_tx_event(struct efx_channel *channel,
++ efx_qword_t *event)
++{
++ unsigned int tx_ev_desc_ptr;
++ unsigned int tx_ev_q_label;
++ struct efx_tx_queue *tx_queue;
++ struct efx_nic *efx = channel->efx;
+
-+ 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");
++ if (likely(EFX_QWORD_FIELD(*event, TX_EV_COMP))) {
++ /* Transmit completion */
++ tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, TX_EV_DESC_PTR);
++ tx_ev_q_label = EFX_QWORD_FIELD(*event, TX_EV_Q_LABEL);
++ tx_queue = &efx->tx_queue[tx_ev_q_label];
++ efx_xmit_done(tx_queue, tx_ev_desc_ptr);
++ } else if (EFX_QWORD_FIELD(*event, TX_EV_WQ_FF_FULL)) {
++ /* Rewrite the FIFO write pointer */
++ tx_ev_q_label = EFX_QWORD_FIELD(*event, TX_EV_Q_LABEL);
++ tx_queue = &efx->tx_queue[tx_ev_q_label];
+
-+ 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;
++ if (NET_DEV_REGISTERED(efx))
++ netif_tx_lock(efx->net_dev);
++ falcon_notify_tx_desc(tx_queue);
++ if (NET_DEV_REGISTERED(efx))
++ netif_tx_unlock(efx->net_dev);
++ } else if (EFX_QWORD_FIELD(*event, TX_EV_PKT_ERR) &&
++ EFX_WORKAROUND_10727(efx)) {
++ efx_schedule_reset(efx, RESET_TYPE_TX_DESC_FETCH);
++ } else {
++ EFX_ERR(efx, "channel %d unexpected TX event "
++ EFX_QWORD_FMT"\n", channel->channel,
++ EFX_QWORD_VAL(*event));
+ }
++}
+
-+ 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;
-+ }
++/* Check received packet's destination MAC address. */
++static int check_dest_mac(struct efx_rx_queue *rx_queue,
++ const efx_qword_t *event)
++{
++ struct efx_rx_buffer *rx_buf;
++ struct efx_nic *efx = rx_queue->efx;
++ int rx_ev_desc_ptr;
++ struct ethhdr *eh;
+
-+ 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;
-+ }
++ if (efx->promiscuous)
++ return 1;
+
-+ 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;
-+ }
++ rx_ev_desc_ptr = EFX_QWORD_FIELD(*event, RX_EV_DESC_PTR);
++ rx_buf = efx_rx_buffer(rx_queue, rx_ev_desc_ptr);
++ eh = (struct ethhdr *)rx_buf->data;
++ if (memcmp(eh->h_dest, efx->net_dev->dev_addr, ETH_ALEN))
++ return 0;
++ return 1;
++}
+
-+ dma_cache_inv((unsigned long)(lp->td_ring),
-+ TD_RING_SIZE + RD_RING_SIZE);
++/* Detect errors included in the rx_evt_pkt_ok bit. */
++static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
++ const efx_qword_t *event,
++ unsigned *rx_ev_pkt_ok,
++ int *discard, int byte_count)
++{
++ struct efx_nic *efx = rx_queue->efx;
++ unsigned rx_ev_buf_owner_id_err, rx_ev_ip_hdr_chksum_err;
++ unsigned rx_ev_tcp_udp_chksum_err, rx_ev_eth_crc_err;
++ unsigned rx_ev_frm_trunc, rx_ev_drib_nib, rx_ev_tobe_disc;
++ unsigned rx_ev_pkt_type, rx_ev_other_err, rx_ev_pause_frm;
++ unsigned rx_ev_ip_frag_err, rx_ev_hdr_type, rx_ev_mcast_pkt;
++ int snap, non_ip;
++
++ rx_ev_hdr_type = EFX_QWORD_FIELD(*event, RX_EV_HDR_TYPE);
++ rx_ev_mcast_pkt = EFX_QWORD_FIELD(*event, RX_EV_MCAST_PKT);
++ rx_ev_tobe_disc = EFX_QWORD_FIELD(*event, RX_EV_TOBE_DISC);
++ rx_ev_pkt_type = EFX_QWORD_FIELD(*event, RX_EV_PKT_TYPE);
++ rx_ev_buf_owner_id_err = EFX_QWORD_FIELD(*event,
++ RX_EV_BUF_OWNER_ID_ERR);
++ rx_ev_ip_frag_err = EFX_QWORD_FIELD(*event, RX_EV_IF_FRAG_ERR);
++ rx_ev_ip_hdr_chksum_err = EFX_QWORD_FIELD(*event,
++ RX_EV_IP_HDR_CHKSUM_ERR);
++ rx_ev_tcp_udp_chksum_err = EFX_QWORD_FIELD(*event,
++ RX_EV_TCP_UDP_CHKSUM_ERR);
++ rx_ev_eth_crc_err = EFX_QWORD_FIELD(*event, RX_EV_ETH_CRC_ERR);
++ rx_ev_frm_trunc = EFX_QWORD_FIELD(*event, RX_EV_FRM_TRUNC);
++ rx_ev_drib_nib = ((FALCON_REV(efx) >= FALCON_REV_B0) ?
++ 0 : EFX_QWORD_FIELD(*event, RX_EV_DRIB_NIB));
++ rx_ev_pause_frm = EFX_QWORD_FIELD(*event, RX_EV_PAUSE_FRM_ERR);
++
++ /* Every error apart from tobe_disc and pause_frm */
++ rx_ev_other_err = (rx_ev_drib_nib | rx_ev_tcp_udp_chksum_err |
++ rx_ev_buf_owner_id_err | rx_ev_eth_crc_err |
++ rx_ev_frm_trunc | rx_ev_ip_hdr_chksum_err);
++
++ snap = (rx_ev_pkt_type == RX_EV_PKT_TYPE_LLC_DECODE) ||
++ (rx_ev_pkt_type == RX_EV_PKT_TYPE_VLAN_LLC_DECODE);
++ non_ip = (rx_ev_hdr_type == RX_EV_HDR_TYPE_NON_IP_DECODE);
++
++ /* SFC bug 5475/8970: The Falcon XMAC incorrectly calculates the
++ * length field of an LLC frame, which sets TOBE_DISC. We could set
++ * PASS_LEN_ERR, but we want the MAC to filter out short frames (to
++ * protect the RX block).
++ *
++ * bug5475 - LLC/SNAP: Falcon identifies SNAP packets.
++ * bug8970 - LLC/noSNAP: Falcon does not provide an LLC flag.
++ * LLC can't encapsulate IP, so by definition
++ * these packets are NON_IP.
++ *
++ * Unicast mismatch will also cause TOBE_DISC, so the driver needs
++ * to check this.
++ */
++ if (EFX_WORKAROUND_5475(efx) && rx_ev_tobe_disc && (snap || non_ip)) {
++ /* If all the other flags are zero then we can state the
++ * entire packet is ok, which will flag to the kernel not
++ * to recalculate checksums.
++ */
++ if (!(non_ip | rx_ev_other_err | rx_ev_pause_frm))
++ *rx_ev_pkt_ok = 1;
+
-+ /* 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];
++ rx_ev_tobe_disc = 0;
+
-+ spin_lock_init(&lp->lock);
-+ /* just use the rx dma irq */
-+ dev->irq = lp->rx_irq;
-+ lp->dev = dev;
++ /* TOBE_DISC is set for unicast mismatch. But given that
++ * we can't trust TOBE_DISC here, we must validate the dest
++ * MAC address ourselves.
++ */
++ if (!rx_ev_mcast_pkt && !check_dest_mac(rx_queue, event))
++ rx_ev_tobe_disc = 1;
++ }
+
-+ 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);
++ /* Count errors that are not in MAC stats. */
++ if (rx_ev_frm_trunc)
++ ++rx_queue->channel->n_rx_frm_trunc;
++ else if (rx_ev_tobe_disc)
++ ++rx_queue->channel->n_rx_tobe_disc;
++ else if (rx_ev_ip_hdr_chksum_err)
++ ++rx_queue->channel->n_rx_ip_hdr_chksum_err;
++ else if (rx_ev_tcp_udp_chksum_err)
++ ++rx_queue->channel->n_rx_tcp_udp_chksum_err;
++ if (rx_ev_ip_frag_err)
++ ++rx_queue->channel->n_rx_ip_frag_err;
++
++ /* The frame must be discarded if any of these are true. */
++ *discard = (rx_ev_eth_crc_err | rx_ev_frm_trunc | rx_ev_drib_nib |
++ rx_ev_tobe_disc | rx_ev_pause_frm);
++
++ /* TOBE_DISC is expected on unicast mismatches; don't print out an
++ * error message. FRM_TRUNC indicates RXDP dropped the packet due
++ * to a FIFO overflow.
++ */
++#ifdef EFX_ENABLE_DEBUG
++ if (rx_ev_other_err) {
++ EFX_INFO_RL(efx, " RX queue %d unexpected RX event "
++ EFX_QWORD_FMT "%s%s%s%s%s%s%s%s%s\n",
++ rx_queue->queue, EFX_QWORD_VAL(*event),
++ rx_ev_buf_owner_id_err ? " [OWNER_ID_ERR]" : "",
++ rx_ev_ip_hdr_chksum_err ?
++ " [IP_HDR_CHKSUM_ERR]" : "",
++ rx_ev_tcp_udp_chksum_err ?
++ " [TCP_UDP_CHKSUM_ERR]" : "",
++ rx_ev_eth_crc_err ? " [ETH_CRC_ERR]" : "",
++ rx_ev_frm_trunc ? " [FRM_TRUNC]" : "",
++ rx_ev_drib_nib ? " [DRIB_NIB]" : "",
++ rx_ev_tobe_disc ? " [TOBE_DISC]" : "",
++ rx_ev_pause_frm ? " [PAUSE]" : "",
++ snap ? " [SNAP/LLC]" : "");
++ }
++#endif
++
++ if (unlikely(rx_ev_eth_crc_err && EFX_WORKAROUND_10750(efx) &&
++ efx->phy_type == PHY_TYPE_10XPRESS))
++ tenxpress_crc_err(efx);
++}
++
++/* Handle receive events that are not in-order. */
++static void falcon_handle_rx_bad_index(struct efx_rx_queue *rx_queue,
++ unsigned index)
++{
++ struct efx_nic *efx = rx_queue->efx;
++ unsigned expected, dropped;
++
++ expected = rx_queue->removed_count & FALCON_RXD_RING_MASK;
++ dropped = ((index + FALCON_RXD_RING_SIZE - expected) &
++ FALCON_RXD_RING_MASK);
++ EFX_INFO(efx, "dropped %d events (index=%d expected=%d)\n",
++ dropped, index, expected);
++
++ efx_schedule_reset(efx, EFX_WORKAROUND_5676(efx) ?
++ RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
++}
++
++/* Handle a packet received event
++ *
++ * Falcon silicon gives a "discard" flag if it's a unicast packet with the
++ * wrong destination address
++ * Also "is multicast" and "matches multicast filter" flags can be used to
++ * discard non-matching multicast packets.
++ */
++static inline int falcon_handle_rx_event(struct efx_channel *channel,
++ const efx_qword_t *event)
++{
++ unsigned int rx_ev_q_label, rx_ev_desc_ptr, rx_ev_byte_cnt;
++ unsigned int rx_ev_pkt_ok, rx_ev_hdr_type, rx_ev_mcast_pkt;
++ unsigned expected_ptr;
++ int discard = 0, checksummed;
++ struct efx_rx_queue *rx_queue;
++ struct efx_nic *efx = channel->efx;
++
++ /* Basic packet information */
++ rx_ev_byte_cnt = EFX_QWORD_FIELD(*event, RX_EV_BYTE_CNT);
++ rx_ev_pkt_ok = EFX_QWORD_FIELD(*event, RX_EV_PKT_OK);
++ rx_ev_hdr_type = EFX_QWORD_FIELD(*event, RX_EV_HDR_TYPE);
++ WARN_ON(EFX_QWORD_FIELD(*event, RX_EV_JUMBO_CONT));
++ WARN_ON(EFX_QWORD_FIELD(*event, RX_EV_SOP) != 1);
++
++ rx_ev_q_label = EFX_QWORD_FIELD(*event, RX_EV_Q_LABEL);
++ rx_queue = &efx->rx_queue[rx_ev_q_label];
++
++ rx_ev_desc_ptr = EFX_QWORD_FIELD(*event, RX_EV_DESC_PTR);
++ expected_ptr = rx_queue->removed_count & FALCON_RXD_RING_MASK;
++ if (unlikely(rx_ev_desc_ptr != expected_ptr)) {
++ falcon_handle_rx_bad_index(rx_queue, rx_ev_desc_ptr);
++ return rx_ev_q_label;
++ }
++
++ if (likely(rx_ev_pkt_ok)) {
++ /* If packet is marked as OK and packet type is TCP/IPv4 or
++ * UDP/IPv4, then we can rely on the hardware checksum.
++ */
++ checksummed = RX_EV_HDR_TYPE_HAS_CHECKSUMS(rx_ev_hdr_type);
++ } else {
++ falcon_handle_rx_not_ok(rx_queue, event, &rx_ev_pkt_ok,
++ &discard, rx_ev_byte_cnt);
++ checksummed = 0;
++ }
+
-+ 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;
++ /* Detect multicast packets that didn't match the filter */
++ rx_ev_mcast_pkt = EFX_QWORD_FIELD(*event, RX_EV_MCAST_PKT);
++ if (rx_ev_mcast_pkt) {
++ unsigned int rx_ev_mcast_hash_match =
++ EFX_QWORD_FIELD(*event, RX_EV_MCAST_HASH_MATCH);
+
-+ rc = register_netdev(dev);
-+ if (rc < 0) {
-+ printk(KERN_ERR DRV_NAME
-+ ": cannot register net device %d\n", rc);
-+ goto probe_err_register;
++ if (unlikely(!rx_ev_mcast_hash_match))
++ discard = 1;
+ }
-+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;
++ /* Handle received packet */
++ efx_rx_packet(rx_queue, rx_ev_desc_ptr, rx_ev_byte_cnt,
++ checksummed, discard);
++
++ return rx_ev_q_label;
+}
+
-+static int korina_remove(struct platform_device *pdev)
++/* Global events are basically PHY events */
++static void falcon_handle_global_event(struct efx_channel *channel,
++ efx_qword_t *event)
+{
-+ struct korina_device *bif = platform_get_drvdata(pdev);
-+ struct korina_private *lp = netdev_priv(bif->dev);
++ struct efx_nic *efx = channel->efx;
++ int is_phy_event = 0, handled = 0;
+
-+ iounmap(lp->eth_regs);
-+ iounmap(lp->rx_dma_regs);
-+ iounmap(lp->tx_dma_regs);
++ /* Check for interrupt on either port. Some boards have a
++ * single PHY wired to the interrupt line for port 1. */
++ if (EFX_QWORD_FIELD(*event, G_PHY0_INTR) ||
++ EFX_QWORD_FIELD(*event, G_PHY1_INTR) ||
++ EFX_QWORD_FIELD(*event, XG_PHY_INTR))
++ is_phy_event = 1;
+
-+ platform_set_drvdata(pdev, NULL);
-+ unregister_netdev(bif->dev);
-+ free_netdev(bif->dev);
++ if ((FALCON_REV(efx) >= FALCON_REV_B0) &&
++ EFX_OWORD_FIELD(*event, XG_MNT_INTR_B0))
++ is_phy_event = 1;
+
-+ return 0;
-+}
++ if (is_phy_event) {
++ efx->phy_op->clear_interrupt(efx);
++ queue_work(efx->workqueue, &efx->reconfigure_work);
++ handled = 1;
++ }
+
-+static struct platform_driver korina_driver = {
-+ .driver.name = "korina",
-+ .probe = korina_probe,
-+ .remove = korina_remove,
-+};
++ if (EFX_QWORD_FIELD_VER(efx, *event, RX_RECOVERY)) {
++ EFX_ERR(efx, "channel %d seen global RX_RESET "
++ "event. Resetting.\n", channel->channel);
++
++ atomic_inc(&efx->rx_reset);
++ efx_schedule_reset(efx, EFX_WORKAROUND_6555(efx) ?
++ RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
++ handled = 1;
++ }
+
-+static int __init korina_init_module(void)
-+{
-+ return platform_driver_register(&korina_driver);
++ if (!handled)
++ EFX_ERR(efx, "channel %d unknown global event "
++ EFX_QWORD_FMT "\n", channel->channel,
++ EFX_QWORD_VAL(*event));
++}
++
++static void falcon_handle_driver_event(struct efx_channel *channel,
++ efx_qword_t *event)
++{
++ struct efx_nic *efx = channel->efx;
++ unsigned int ev_sub_code;
++ unsigned int ev_sub_data;
++
++ ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE);
++ ev_sub_data = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_DATA);
++
++ switch (ev_sub_code) {
++ case TX_DESCQ_FLS_DONE_EV_DECODE:
++ EFX_TRACE(efx, "channel %d TXQ %d flushed\n",
++ channel->channel, ev_sub_data);
++ break;
++ case RX_DESCQ_FLS_DONE_EV_DECODE:
++ EFX_TRACE(efx, "channel %d RXQ %d flushed\n",
++ channel->channel, ev_sub_data);
++ break;
++ case EVQ_INIT_DONE_EV_DECODE:
++ EFX_LOG(efx, "channel %d EVQ %d initialised\n",
++ channel->channel, ev_sub_data);
++ break;
++ case SRM_UPD_DONE_EV_DECODE:
++ EFX_TRACE(efx, "channel %d SRAM update done\n",
++ channel->channel);
++ break;
++ case WAKE_UP_EV_DECODE:
++ EFX_TRACE(efx, "channel %d RXQ %d wakeup event\n",
++ channel->channel, ev_sub_data);
++ break;
++ case TIMER_EV_DECODE:
++ EFX_TRACE(efx, "channel %d RX queue %d timer expired\n",
++ channel->channel, ev_sub_data);
++ break;
++ case RX_RECOVERY_EV_DECODE:
++ EFX_ERR(efx, "channel %d seen DRIVER RX_RESET event. "
++ "Resetting.\n", channel->channel);
++ efx_schedule_reset(efx,
++ EFX_WORKAROUND_6555(efx) ?
++ RESET_TYPE_RX_RECOVERY :
++ RESET_TYPE_DISABLE);
++ break;
++ case RX_DSC_ERROR_EV_DECODE:
++ EFX_ERR(efx, "RX DMA Q %d reports descriptor fetch error."
++ " RX Q %d is disabled.\n", ev_sub_data, ev_sub_data);
++ efx_schedule_reset(efx, RESET_TYPE_RX_DESC_FETCH);
++ break;
++ case TX_DSC_ERROR_EV_DECODE:
++ EFX_ERR(efx, "TX DMA Q %d reports descriptor fetch error."
++ " TX Q %d is disabled.\n", ev_sub_data, ev_sub_data);
++ efx_schedule_reset(efx, RESET_TYPE_TX_DESC_FETCH);
++ break;
++ default:
++ EFX_TRACE(efx, "channel %d unknown driver event code %d "
++ "data %04x\n", channel->channel, ev_sub_code,
++ ev_sub_data);
++ break;
++ }
+}
+
-+static void korina_cleanup_module(void)
++int falcon_process_eventq(struct efx_channel *channel, int *rx_quota)
+{
-+ return platform_driver_unregister(&korina_driver);
-+}
++ unsigned int read_ptr;
++ efx_qword_t event, *p_event;
++ int ev_code;
++ int rxq;
++ int rxdmaqs = 0;
+
-+module_init(korina_init_module);
-+module_exit(korina_cleanup_module);
++ read_ptr = channel->eventq_read_ptr;
+
-+MODULE_AUTHOR("Philip Rischel <rischelp at idt.com>");
-+MODULE_AUTHOR("Felix Fietkau <nbd at openwrt.org>");
-+MODULE_AUTHOR("Florian Fainelli <florian at openwrt.org>");
-+MODULE_DESCRIPTION("IDT RC32434 (Korina) Ethernet driver");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
-index f2a6e71..41b774b 100644
---- a/drivers/net/loopback.c
-+++ b/drivers/net/loopback.c
-@@ -258,7 +258,7 @@ static __net_init int loopback_net_init(struct net *net)
- if (!dev)
- goto out;
-
-- dev->nd_net = net;
-+ dev_net_set(dev, net);
- err = register_netdev(dev);
- if (err)
- goto out_free_netdev;
-diff --git a/drivers/net/macb.c b/drivers/net/macb.c
-index 489c7c3..92dccd4 100644
---- a/drivers/net/macb.c
-+++ b/drivers/net/macb.c
-@@ -246,7 +246,7 @@ static int macb_mii_init(struct macb *bp)
- bp->mii_bus.read = &macb_mdio_read;
- bp->mii_bus.write = &macb_mdio_write;
- bp->mii_bus.reset = &macb_mdio_reset;
-- bp->mii_bus.id = bp->pdev->id;
-+ snprintf(bp->mii_bus.id, MII_BUS_ID_SIZE, "%x", bp->pdev->id);
- bp->mii_bus.priv = bp;
- bp->mii_bus.dev = &bp->dev->dev;
- pdata = bp->pdev->dev.platform_data;
-@@ -1281,6 +1281,7 @@ static struct platform_driver macb_driver = {
- .remove = __exit_p(macb_remove),
- .driver = {
- .name = "macb",
-+ .owner = THIS_MODULE,
- },
- };
-
-@@ -1300,3 +1301,4 @@ module_exit(macb_exit);
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("Atmel MACB Ethernet driver");
- MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen at atmel.com>");
-+MODULE_ALIAS("platform:macb");
-diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
-index f651a81..2056cfc 100644
---- a/drivers/net/macvlan.c
-+++ b/drivers/net/macvlan.c
-@@ -402,7 +402,7 @@ static int macvlan_newlink(struct net_device *dev,
- if (!tb[IFLA_LINK])
- return -EINVAL;
-
-- lowerdev = __dev_get_by_index(dev->nd_net, nla_get_u32(tb[IFLA_LINK]));
-+ lowerdev = __dev_get_by_index(dev_net(dev), nla_get_u32(tb[IFLA_LINK]));
- if (lowerdev == NULL)
- return -ENODEV;
-
-diff --git a/drivers/net/meth.c b/drivers/net/meth.c
-index cdaa8fc..0b32648 100644
---- a/drivers/net/meth.c
-+++ b/drivers/net/meth.c
-@@ -830,6 +830,7 @@ static struct platform_driver meth_driver = {
- .remove = __devexit_p(meth_remove),
- .driver = {
- .name = "meth",
-+ .owner = THIS_MODULE,
- }
- };
-
-@@ -855,3 +856,4 @@ module_exit(meth_exit_module);
- MODULE_AUTHOR("Ilya Volynets <ilya at theIlya.com>");
- MODULE_DESCRIPTION("SGI O2 Builtin Fast Ethernet driver");
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:meth");
-diff --git a/drivers/net/mlx4/catas.c b/drivers/net/mlx4/catas.c
-index 6b32ec9..aa95287 100644
---- a/drivers/net/mlx4/catas.c
-+++ b/drivers/net/mlx4/catas.c
-@@ -69,7 +69,7 @@ static void poll_catas(unsigned long dev_ptr)
- if (readl(priv->catas_err.map)) {
- dump_err_buf(dev);
-
-- mlx4_dispatch_event(dev, MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR, 0, 0);
-+ mlx4_dispatch_event(dev, MLX4_DEV_EVENT_CATASTROPHIC_ERROR, 0);
-
- if (internal_err_reset) {
- spin_lock(&catas_lock);
-diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
-index db49051..70dff94 100644
---- a/drivers/net/mlx4/cmd.c
-+++ b/drivers/net/mlx4/cmd.c
-@@ -106,7 +106,8 @@ struct mlx4_cmd_context {
- u16 token;
- };
-
--static int mlx4_status_to_errno(u8 status) {
-+static int mlx4_status_to_errno(u8 status)
-+{
- static const int trans_table[] = {
- [CMD_STAT_INTERNAL_ERR] = -EIO,
- [CMD_STAT_BAD_OP] = -EPERM,
-diff --git a/drivers/net/mlx4/cq.c b/drivers/net/mlx4/cq.c
-index d4441fe..caa5bcf 100644
---- a/drivers/net/mlx4/cq.c
-+++ b/drivers/net/mlx4/cq.c
-@@ -38,6 +38,7 @@
- #include <linux/hardirq.h>
-
- #include <linux/mlx4/cmd.h>
-+#include <linux/mlx4/cq.h>
-
- #include "mlx4.h"
- #include "icm.h"
-@@ -47,21 +48,19 @@ struct mlx4_cq_context {
- u16 reserved1[3];
- __be16 page_offset;
- __be32 logsize_usrpage;
-- u8 reserved2;
-- u8 cq_period;
-- u8 reserved3;
-- u8 cq_max_count;
-- u8 reserved4[3];
-+ __be16 cq_period;
-+ __be16 cq_max_count;
-+ u8 reserved2[3];
- u8 comp_eqn;
- u8 log_page_size;
-- u8 reserved5[2];
-+ u8 reserved3[2];
- u8 mtt_base_addr_h;
- __be32 mtt_base_addr_l;
- __be32 last_notified_index;
- __be32 solicit_producer_index;
- __be32 consumer_index;
- __be32 producer_index;
-- u32 reserved6[2];
-+ u32 reserved4[2];
- __be64 db_rec_addr;
- };
-
-@@ -121,6 +120,13 @@ static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
- MLX4_CMD_TIME_CLASS_A);
- }
-
-+static int mlx4_MODIFY_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
-+ int cq_num, u32 opmod)
-+{
-+ return mlx4_cmd(dev, mailbox->dma, cq_num, opmod, MLX4_CMD_MODIFY_CQ,
-+ MLX4_CMD_TIME_CLASS_A);
-+}
++ do {
++ p_event = falcon_event(channel, read_ptr);
++ event = *p_event;
+
- 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;
++ if (!falcon_event_present(&event))
++ /* End of events */
++ break;
+
-+ mailbox = mlx4_alloc_cmd_mailbox(dev);
-+ if (IS_ERR(mailbox))
-+ return PTR_ERR(mailbox);
++ EFX_TRACE(channel->efx, "channel %d event is "EFX_QWORD_FMT"\n",
++ channel->channel, EFX_QWORD_VAL(event));
+
-+ cq_context = mailbox->buf;
-+ memset(cq_context, 0, sizeof *cq_context);
++ /* Clear this event by marking it all ones */
++ EFX_SET_QWORD(*p_event);
+
-+ cq_context->cq_max_count = cpu_to_be16(count);
-+ cq_context->cq_period = cpu_to_be16(period);
++ ev_code = EFX_QWORD_FIELD(event, EV_CODE);
+
-+ err = mlx4_MODIFY_CQ(dev, mailbox, cq->cqn, 1);
++ switch (ev_code) {
++ case RX_IP_EV_DECODE:
++ rxq = falcon_handle_rx_event(channel, &event);
++ rxdmaqs |= (1 << rxq);
++ (*rx_quota)--;
++ break;
++ case TX_IP_EV_DECODE:
++ falcon_handle_tx_event(channel, &event);
++ break;
++ case DRV_GEN_EV_DECODE:
++ channel->eventq_magic
++ = EFX_QWORD_FIELD(event, EVQ_MAGIC);
++ EFX_LOG(channel->efx, "channel %d received generated "
++ "event "EFX_QWORD_FMT"\n", channel->channel,
++ EFX_QWORD_VAL(event));
++ break;
++ case GLOBAL_EV_DECODE:
++ falcon_handle_global_event(channel, &event);
++ break;
++ case DRIVER_EV_DECODE:
++ falcon_handle_driver_event(channel, &event);
++ break;
++ default:
++ EFX_ERR(channel->efx, "channel %d unknown event type %d"
++ " (data " EFX_QWORD_FMT ")\n", channel->channel,
++ ev_code, EFX_QWORD_VAL(event));
++ }
+
-+ mlx4_free_cmd_mailbox(dev, mailbox);
-+ return err;
++ /* Increment read pointer */
++ read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK;
++
++ } while (*rx_quota);
++
++ channel->eventq_read_ptr = read_ptr;
++ return rxdmaqs;
+}
-+EXPORT_SYMBOL_GPL(mlx4_cq_modify);
+
-+int mlx4_cq_resize(struct mlx4_dev *dev, struct mlx4_cq *cq,
-+ int entries, struct mlx4_mtt *mtt)
++void falcon_set_int_moderation(struct efx_channel *channel)
+{
-+ 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);
++ efx_dword_t timer_cmd;
++ struct efx_nic *efx = channel->efx;
+
-+ cq_context = mailbox->buf;
-+ memset(cq_context, 0, sizeof *cq_context);
++ /* Set timer register */
++ if (channel->irq_moderation) {
++ /* Round to resolution supported by hardware. The value we
++ * program is based at 0. So actual interrupt moderation
++ * achieved is ((x + 1) * res).
++ */
++ unsigned int res = 5;
++ channel->irq_moderation -= (channel->irq_moderation % res);
++ if (channel->irq_moderation < res)
++ channel->irq_moderation = res;
++ EFX_POPULATE_DWORD_2(timer_cmd,
++ TIMER_MODE, TIMER_MODE_INT_HLDOFF,
++ TIMER_VAL,
++ (channel->irq_moderation / res) - 1);
++ } else {
++ EFX_POPULATE_DWORD_2(timer_cmd,
++ TIMER_MODE, TIMER_MODE_DIS,
++ TIMER_VAL, 0);
++ }
++ falcon_writel_page_locked(efx, &timer_cmd, TIMER_CMD_REG_KER,
++ channel->evqnum);
+
-+ 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);
++/* Allocate buffer table entries for event queue */
++int falcon_probe_eventq(struct efx_channel *channel)
++{
++ struct efx_nic *efx = channel->efx;
++ unsigned int evq_size;
+
-+ mlx4_free_cmd_mailbox(dev, mailbox);
-+ return err;
++ evq_size = FALCON_EVQ_SIZE * sizeof(efx_qword_t);
++ return falcon_alloc_special_buffer(efx, &channel->eventq, evq_size);
+}
-+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;
++int falcon_init_eventq(struct efx_channel *channel)
++{
++ efx_oword_t evq_ptr;
++ struct efx_nic *efx = channel->efx;
++ int rc;
+
- 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);
++ EFX_LOG(efx, "channel %d event queue in special buffers %d-%d\n",
++ channel->channel, channel->eventq.index,
++ channel->eventq.index + channel->eventq.entries - 1);
+
- /* QPC/EEC/CQC/EQC/RDMARC attributes */
-
- MLX4_PUT(inbox, param->qpc_base, INIT_HCA_QPC_BASE_OFFSET);
-diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
-index e16dec8..306cb9b 100644
---- a/drivers/net/mlx4/fw.h
-+++ b/drivers/net/mlx4/fw.h
-@@ -96,6 +96,7 @@ struct mlx4_dev_cap {
- u8 bmme_flags;
- u32 reserved_lkey;
- u64 max_icm_sz;
-+ int max_gso_sz;
- };
-
- struct mlx4_adapter {
-diff --git a/drivers/net/mlx4/intf.c b/drivers/net/mlx4/intf.c
-index be5d9e9..4a6c4d5 100644
---- a/drivers/net/mlx4/intf.c
-+++ b/drivers/net/mlx4/intf.c
-@@ -30,8 +30,6 @@
- * SOFTWARE.
- */
-
--#include <linux/mlx4/driver.h>
--
- #include "mlx4.h"
-
- struct mlx4_device_context {
-@@ -113,8 +111,7 @@ void mlx4_unregister_interface(struct mlx4_interface *intf)
- }
- EXPORT_SYMBOL_GPL(mlx4_unregister_interface);
-
--void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_event type,
-- int subtype, int port)
-+void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, int port)
- {
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_device_context *dev_ctx;
-@@ -124,8 +121,7 @@ void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_event type,
-
- list_for_each_entry(dev_ctx, &priv->ctx_list, list)
- if (dev_ctx->intf->event)
-- dev_ctx->intf->event(dev, dev_ctx->context, type,
-- subtype, port);
-+ dev_ctx->intf->event(dev, dev_ctx->context, type, port);
-
- spin_unlock_irqrestore(&priv->ctx_lock, flags);
- }
-diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
-index 08bfc13..49a4aca 100644
---- a/drivers/net/mlx4/main.c
-+++ b/drivers/net/mlx4/main.c
-@@ -76,7 +76,7 @@ static char mlx4_version[] __devinitdata =
- DRV_VERSION " (" DRV_RELDATE ")\n";
-
- static struct mlx4_profile default_profile = {
-- .num_qp = 1 << 16,
-+ .num_qp = 1 << 17,
- .num_srq = 1 << 16,
- .rdmarc_per_qp = 1 << 4,
- .num_cq = 1 << 16,
-@@ -159,6 +159,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
- dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1);
- dev->caps.flags = dev_cap->flags;
- dev->caps.stat_rate_support = dev_cap->stat_rate_support;
-+ dev->caps.max_gso_sz = dev_cap->max_gso_sz;
-
- return 0;
- }
-@@ -735,8 +736,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
- }
-
- /*
-- * Check for BARs. We expect 0: 1MB, 2: 8MB, 4: DDR (may not
-- * be present)
-+ * Check for BARs. We expect 0: 1MB
- */
- if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||
- pci_resource_len(pdev, 0) != 1 << 20) {
-diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c
-index a99e772..57f7f1f 100644
---- a/drivers/net/mlx4/mcg.c
-+++ b/drivers/net/mlx4/mcg.c
-@@ -190,10 +190,6 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
- }
- index += dev->caps.num_mgms;
-
-- err = mlx4_READ_MCG(dev, index, mailbox);
-- if (err)
-- goto out;
--
- memset(mgm, 0, sizeof *mgm);
- memcpy(mgm->gid, gid, 16);
- }
-@@ -301,12 +297,10 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
- mgm->qp[loc] = mgm->qp[i - 1];
- mgm->qp[i - 1] = 0;
-
-- err = mlx4_WRITE_MCG(dev, index, mailbox);
-- if (err)
-- goto out;
--
-- if (i != 1)
-+ if (i != 1) {
-+ err = mlx4_WRITE_MCG(dev, index, mailbox);
- goto out;
-+ }
-
- if (prev == -1) {
- /* Remove entry from MGM */
-diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
-index 53a1cdd..7333681 100644
---- a/drivers/net/mlx4/mlx4.h
-+++ b/drivers/net/mlx4/mlx4.h
-@@ -42,6 +42,7 @@
- #include <linux/timer.h>
-
- #include <linux/mlx4/device.h>
-+#include <linux/mlx4/driver.h>
- #include <linux/mlx4/doorbell.h>
-
- #define DRV_NAME "mlx4_core"
-@@ -313,8 +314,7 @@ void mlx4_catas_cleanup(void);
- int mlx4_restart_one(struct pci_dev *pdev);
- int mlx4_register_device(struct mlx4_dev *dev);
- void mlx4_unregister_device(struct mlx4_dev *dev);
--void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_event type,
-- int subtype, int port);
-+void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, int port);
-
- struct mlx4_dev_cap;
- struct mlx4_init_hca_param;
-diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
-index 771139e..381b36e 100644
---- a/drivers/net/mv643xx_eth.c
-+++ b/drivers/net/mv643xx_eth.c
-@@ -3,7 +3,8 @@
- * Copyright (C) 2002 Matthew Dharm <mdharm at momenco.com>
- *
- * Based on the 64360 driver from:
-- * Copyright (C) 2002 rabeeh at galileo.co.il
-+ * Copyright (C) 2002 Rabeeh Khoury <rabeeh at galileo.co.il>
-+ * Rabeeh Khoury <rabeeh at marvell.com>
- *
- * Copyright (C) 2003 PMC-Sierra, Inc.,
- * written by Manish Lachwani
-@@ -16,6 +17,9 @@
- * Copyright (C) 2004 Steven J. Hill <sjhill1 at rockwellcollins.com>
- * <sjhill at realitydiluted.com>
- *
-+ * Copyright (C) 2007-2008 Marvell Semiconductor
-+ * Lennert Buytenhek <buytenh at marvell.com>
-+ *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
-@@ -63,20 +67,6 @@
- #define MV643XX_TX_FAST_REFILL
- #undef MV643XX_COAL
-
--/*
-- * Number of RX / TX descriptors on RX / TX rings.
-- * Note that allocating RX descriptors is done by allocating the RX
-- * ring AND a preallocated RX buffers (skb's) for each descriptor.
-- * The TX descriptors only allocates the TX descriptors ring,
-- * with no pre allocated TX buffers (skb's are allocated by higher layers.
-- */
--
--/* Default TX ring size is 1000 descriptors */
--#define MV643XX_DEFAULT_TX_QUEUE_SIZE 1000
--
--/* Default RX ring size is 400 descriptors */
--#define MV643XX_DEFAULT_RX_QUEUE_SIZE 400
--
- #define MV643XX_TX_COAL 100
- #ifdef MV643XX_COAL
- #define MV643XX_RX_COAL 100
-@@ -434,14 +424,6 @@ typedef enum _eth_func_ret_status {
- ETH_QUEUE_LAST_RESOURCE /* Ring resources about to exhaust. */
- } ETH_FUNC_RET_STATUS;
-
--typedef enum _eth_target {
-- ETH_TARGET_DRAM,
-- ETH_TARGET_DEVICE,
-- ETH_TARGET_CBS,
-- ETH_TARGET_PCI0,
-- ETH_TARGET_PCI1
--} ETH_TARGET;
--
- /* These are for big-endian machines. Little endian needs different
- * definitions.
- */
-@@ -586,43 +568,44 @@ struct mv643xx_private {
-
- /* Static function declarations */
- static void eth_port_init(struct mv643xx_private *mp);
--static void eth_port_reset(unsigned int eth_port_num);
-+static void eth_port_reset(struct mv643xx_private *mp);
- static void eth_port_start(struct net_device *dev);
-
--static void ethernet_phy_reset(unsigned int eth_port_num);
-+static void ethernet_phy_reset(struct mv643xx_private *mp);
-
--static void eth_port_write_smi_reg(unsigned int eth_port_num,
-+static void eth_port_write_smi_reg(struct mv643xx_private *mp,
- unsigned int phy_reg, unsigned int value);
-
--static void eth_port_read_smi_reg(unsigned int eth_port_num,
-+static void eth_port_read_smi_reg(struct mv643xx_private *mp,
- unsigned int phy_reg, unsigned int *value);
-
--static void eth_clear_mib_counters(unsigned int eth_port_num);
-+static void eth_clear_mib_counters(struct mv643xx_private *mp);
-
- static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
- struct pkt_info *p_pkt_info);
- static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
- struct pkt_info *p_pkt_info);
-
--static void eth_port_uc_addr_get(unsigned int port_num, unsigned char *p_addr);
--static void eth_port_uc_addr_set(unsigned int port_num, unsigned char *p_addr);
-+static void eth_port_uc_addr_get(struct mv643xx_private *mp,
-+ unsigned char *p_addr);
-+static void eth_port_uc_addr_set(struct mv643xx_private *mp,
-+ unsigned char *p_addr);
- static void eth_port_set_multicast_list(struct net_device *);
--static void mv643xx_eth_port_enable_tx(unsigned int port_num,
-+static void mv643xx_eth_port_enable_tx(struct mv643xx_private *mp,
- unsigned int queues);
--static void mv643xx_eth_port_enable_rx(unsigned int port_num,
-+static void mv643xx_eth_port_enable_rx(struct mv643xx_private *mp,
- unsigned int queues);
--static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num);
--static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num);
-+static unsigned int mv643xx_eth_port_disable_tx(struct mv643xx_private *mp);
-+static unsigned int mv643xx_eth_port_disable_rx(struct mv643xx_private *mp);
- static int mv643xx_eth_open(struct net_device *);
- static int mv643xx_eth_stop(struct net_device *);
--static int mv643xx_eth_change_mtu(struct net_device *, int);
--static void eth_port_init_mac_tables(unsigned int eth_port_num);
-+static void eth_port_init_mac_tables(struct mv643xx_private *mp);
- #ifdef MV643XX_NAPI
- static int mv643xx_poll(struct napi_struct *napi, int budget);
- #endif
--static int ethernet_phy_get(unsigned int eth_port_num);
--static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr);
--static int ethernet_phy_detect(unsigned int eth_port_num);
-+static int ethernet_phy_get(struct mv643xx_private *mp);
-+static void ethernet_phy_set(struct mv643xx_private *mp, int phy_addr);
-+static int ethernet_phy_detect(struct mv643xx_private *mp);
- static int mv643xx_mdio_read(struct net_device *dev, int phy_id, int location);
- static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, int val);
- static int mv643xx_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-@@ -636,12 +619,12 @@ static void __iomem *mv643xx_eth_base;
- /* used to protect SMI_REG, which is shared across ports */
- static DEFINE_SPINLOCK(mv643xx_eth_phy_lock);
-
--static inline u32 mv_read(int offset)
-+static inline u32 rdl(struct mv643xx_private *mp, int offset)
- {
- return readl(mv643xx_eth_base + offset);
- }
-
--static inline void mv_write(int offset, u32 data)
-+static inline void wrl(struct mv643xx_private *mp, int offset, u32 data)
- {
- writel(data, mv643xx_eth_base + offset);
- }
-@@ -659,18 +642,19 @@ static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
- return -EINVAL;
-
- dev->mtu = new_mtu;
-+ if (!netif_running(dev))
-+ return 0;
++ /* Pin event queue buffer */
++ rc = falcon_init_special_buffer(efx, &channel->eventq);
++ if (rc)
++ return rc;
+
- /*
-- * 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;
++ /* Fill event queue with all ones (i.e. empty events) */
++ memset(channel->eventq.addr, 0xff, channel->eventq.len);
+
- /* 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);
++ /* Push event queue to card */
++ EFX_POPULATE_OWORD_3(evq_ptr,
++ EVQ_EN, 1,
++ EVQ_SIZE, FALCON_EVQ_ORDER,
++ EVQ_BUF_BASE_ID, channel->eventq.index);
++ falcon_write_table(efx, &evq_ptr, efx->type->evq_ptr_tbl_base,
++ channel->evqnum);
+
- 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);
++ falcon_set_int_moderation(channel);
++
++ return 0;
++}
++
++void falcon_fini_eventq(struct efx_channel *channel)
++{
++ efx_oword_t eventq_ptr;
++ struct efx_nic *efx = channel->efx;
+
-+ 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;
++ /* Remove event queue from card */
++ EFX_ZERO_OWORD(eventq_ptr);
++ falcon_write_table(efx, &eventq_ptr, efx->type->evq_ptr_tbl_base,
++ channel->evqnum);
++
++ /* Unpin event queue */
++ falcon_fini_special_buffer(efx, &channel->eventq);
++}
++
++/* Free buffers backing event queue */
++void falcon_remove_eventq(struct efx_channel *channel)
++{
++ falcon_free_special_buffer(channel->efx, &channel->eventq);
++}
++
++
++/* Generates a test event on the event queue. A subsequent call to
++ * process_eventq() should pick up the event and place the value of
++ * "magic" into channel->eventq_magic;
++ */
++void falcon_generate_test_event(struct efx_channel *channel, unsigned int magic)
++{
++ efx_qword_t test_event;
++
++ EFX_POPULATE_QWORD_2(test_event,
++ EV_CODE, DRV_GEN_EV_DECODE,
++ EVQ_MAGIC, magic);
++ falcon_generate_event(channel, &test_event);
++}
++
++
++/**************************************************************************
++ *
++ * Falcon hardware interrupts
++ * The hardware interrupt handler does very little work; all the event
++ * queue processing is carried out by per-channel tasklets.
++ *
++ **************************************************************************/
++
++/* Enable/disable/generate Falcon interrupts */
++static inline void falcon_interrupts(struct efx_nic *efx, int enabled,
++ int force)
++{
++ efx_oword_t int_en_reg_ker;
++
++ EFX_POPULATE_OWORD_2(int_en_reg_ker,
++ KER_INT_KER, force,
++ DRV_INT_EN_KER, enabled);
++ falcon_write(efx, &int_en_reg_ker, INT_EN_REG_KER);
++}
++
++void falcon_enable_interrupts(struct efx_nic *efx)
++{
++ efx_oword_t int_adr_reg_ker;
++ struct efx_channel *channel;
++
++ EFX_ZERO_OWORD(*((efx_oword_t *) efx->irq_status.addr));
++ wmb(); /* Ensure interrupt vector is clear before interrupts enabled */
++
++ /* Program address */
++ EFX_POPULATE_OWORD_2(int_adr_reg_ker,
++ NORM_INT_VEC_DIS_KER, EFX_INT_MODE_USE_MSI(efx),
++ INT_ADR_KER, efx->irq_status.dma_addr);
++ falcon_write(efx, &int_adr_reg_ker, INT_ADR_REG_KER);
++
++ /* Enable interrupts */
++ falcon_interrupts(efx, 1, 0);
++
++ /* Force processing of all the channels to get the EVQ RPTRs up to
++ date */
++ efx_for_each_channel_with_interrupt(channel, efx)
++ efx_schedule_channel(channel);
++}
++
++void falcon_disable_interrupts(struct efx_nic *efx)
++{
++ /* Disable interrupts */
++ falcon_interrupts(efx, 0, 0);
++}
++
++/* Generate a Falcon test interrupt
++ * Interrupt must already have been enabled, otherwise nasty things
++ * may happen.
++ */
++void falcon_generate_interrupt(struct efx_nic *efx)
++{
++ falcon_interrupts(efx, 1, 1);
++}
++
++/* Acknowledge a legacy interrupt from Falcon
++ *
++ * This acknowledges a legacy (not MSI) interrupt via INT_ACK_KER_REG.
++ *
++ * Due to SFC bug 3706 (silicon revision <=A1) reads can be duplicated in the
++ * BIU. Interrupt acknowledge is read sensitive so must write instead
++ * (then read to ensure the BIU collector is flushed)
++ *
++ * NB most hardware supports MSI interrupts
++ */
++static inline void falcon_irq_ack_a1(struct efx_nic *efx)
++{
++ efx_dword_t reg;
++
++ EFX_POPULATE_DWORD_1(reg, INT_ACK_DUMMY_DATA, 0xb7eb7e);
++ falcon_writel(efx, ®, INT_ACK_REG_KER_A1);
++ falcon_readl(efx, ®, WORK_AROUND_BROKEN_PCI_READS_REG_KER_A1);
++}
++
++/* Process a fatal interrupt
++ * Disable bus mastering ASAP and schedule a reset
++ */
++static irqreturn_t falcon_fatal_interrupt(struct efx_nic *efx)
++{
++ struct falcon_nic_data *nic_data = efx->nic_data;
++ efx_oword_t *int_ker = (efx_oword_t *) efx->irq_status.addr;
++ efx_oword_t fatal_intr;
++ int error, mem_perr;
++ static int n_int_errors;
++
++ falcon_read(efx, &fatal_intr, FATAL_INTR_REG_KER);
++ error = EFX_OWORD_FIELD(fatal_intr, INT_KER_ERROR);
++
++ EFX_ERR(efx, "SYSTEM ERROR " EFX_OWORD_FMT " status "
++ EFX_OWORD_FMT ": %s\n", EFX_OWORD_VAL(*int_ker),
++ EFX_OWORD_VAL(fatal_intr),
++ error ? "disabling bus mastering" : "no recognised error");
++ if (error == 0)
++ goto out;
++
++ /* If this is a memory parity error dump which blocks are offending */
++ mem_perr = EFX_OWORD_FIELD(fatal_intr, MEM_PERR_INT_KER);
++ if (mem_perr) {
++ efx_oword_t reg;
++ falcon_read(efx, ®, MEM_STAT_REG_KER);
++ EFX_ERR(efx, "SYSTEM ERROR: memory parity error "
++ EFX_OWORD_FMT "\n", EFX_OWORD_VAL(reg));
++ }
++
++ /* Disable DMA bus mastering on both devices */
++ pci_disable_device(efx->pci_dev);
++ if (FALCON_IS_DUAL_FUNC(efx))
++ pci_disable_device(nic_data->pci_dev2);
++
++ if (++n_int_errors < FALCON_MAX_INT_ERRORS) {
++ EFX_ERR(efx, "SYSTEM ERROR - reset scheduled\n");
++ efx_schedule_reset(efx, RESET_TYPE_INT_ERROR);
++ } else {
++ EFX_ERR(efx, "SYSTEM ERROR - max number of errors seen."
++ "NIC will be disabled\n");
++ efx_schedule_reset(efx, RESET_TYPE_DISABLE);
+ }
++out:
++ return IRQ_HANDLED;
++}
+
-+ spin_lock_irqsave(&mp->lock, flags);
-
- if (mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB) {
- printk(KERN_ERR "%s: transmit with queue full\n", dev->name);
- netif_stop_queue(dev);
-- return 1;
-- }
--
-- if (has_tiny_unaligned_frags(skb)) {
-- if (__skb_linearize(skb)) {
-- stats->tx_dropped++;
-- printk(KERN_DEBUG "%s: failed to linearize tiny "
-- "unaligned fragment\n", dev->name);
-- return 1;
-- }
-+ spin_unlock_irqrestore(&mp->lock, flags);
-+ return NETDEV_TX_BUSY;
- }
-
-- spin_lock_irqsave(&mp->lock, flags);
--
- eth_tx_submit_descs_for_skb(mp, skb);
- stats->tx_bytes += skb->len;
- stats->tx_packets++;
-@@ -1768,7 +1748,7 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
-
- spin_unlock_irqrestore(&mp->lock, flags);
-
-- return 0; /* success */
-+ return NETDEV_TX_OK;
- }
-
- #ifdef CONFIG_NET_POLL_CONTROLLER
-@@ -1777,13 +1757,13 @@ static void mv643xx_netpoll(struct net_device *netdev)
- struct mv643xx_private *mp = netdev_priv(netdev);
- int port_num = mp->port_num;
-
-- mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
-+ wrl(mp, INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
- /* wait for previous write to complete */
-- mv_read(INTERRUPT_MASK_REG(port_num));
-+ rdl(mp, INTERRUPT_MASK_REG(port_num));
-
- mv643xx_eth_int_handler(netdev->irq, netdev);
-
-- mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
-+ wrl(mp, INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
- }
- #endif
-
-@@ -1900,7 +1880,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
- port_num = mp->port_num = pd->port_number;
-
- /* set default config values */
-- eth_port_uc_addr_get(port_num, dev->dev_addr);
-+ eth_port_uc_addr_get(mp, dev->dev_addr);
- mp->rx_ring_size = PORT_DEFAULT_RECEIVE_QUEUE_SIZE;
- mp->tx_ring_size = PORT_DEFAULT_TRANSMIT_QUEUE_SIZE;
-
-@@ -1908,7 +1888,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
- memcpy(dev->dev_addr, pd->mac_addr, 6);
-
- if (pd->phy_addr || pd->force_phy_addr)
-- ethernet_phy_set(port_num, pd->phy_addr);
-+ ethernet_phy_set(mp, pd->phy_addr);
-
- if (pd->rx_queue_size)
- mp->rx_ring_size = pd->rx_queue_size;
-@@ -1933,19 +1913,18 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
- mp->mii.dev = dev;
- mp->mii.mdio_read = mv643xx_mdio_read;
- mp->mii.mdio_write = mv643xx_mdio_write;
-- mp->mii.phy_id = ethernet_phy_get(port_num);
-+ mp->mii.phy_id = ethernet_phy_get(mp);
- mp->mii.phy_id_mask = 0x3f;
- mp->mii.reg_num_mask = 0x1f;
-
-- err = ethernet_phy_detect(port_num);
-+ err = ethernet_phy_detect(mp);
- if (err) {
-- pr_debug("MV643xx ethernet port %d: "
-- "No PHY detected at addr %d\n",
-- port_num, ethernet_phy_get(port_num));
-+ pr_debug("%s: No PHY detected at addr %d\n",
-+ dev->name, ethernet_phy_get(mp));
- goto out;
- }
-
-- ethernet_phy_reset(port_num);
-+ ethernet_phy_reset(mp);
- mp->mii.supports_gmii = mii_check_gmii_support(&mp->mii);
- mv643xx_init_ethtool_cmd(dev, mp->mii.phy_id, speed, duplex, &cmd);
- mv643xx_eth_update_pscr(dev, &cmd);
-@@ -2006,9 +1985,11 @@ static int mv643xx_eth_remove(struct platform_device *pdev)
-
- static int mv643xx_eth_shared_probe(struct platform_device *pdev)
- {
-+ static int mv643xx_version_printed = 0;
- struct resource *res;
-
-- printk(KERN_NOTICE "MV-643xx 10/100/1000 Ethernet Driver\n");
-+ if (!mv643xx_version_printed++)
-+ printk(KERN_NOTICE "MV-643xx 10/100/1000 Ethernet Driver\n");
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL)
-@@ -2037,10 +2018,10 @@ static void mv643xx_eth_shutdown(struct platform_device *pdev)
- unsigned int port_num = mp->port_num;
-
- /* Mask all interrupts on ethernet port */
-- mv_write(INTERRUPT_MASK_REG(port_num), 0);
-- mv_read (INTERRUPT_MASK_REG(port_num));
-+ wrl(mp, INTERRUPT_MASK_REG(port_num), 0);
-+ rdl(mp, INTERRUPT_MASK_REG(port_num));
-
-- eth_port_reset(port_num);
-+ eth_port_reset(mp);
- }
-
- static struct platform_driver mv643xx_eth_driver = {
-@@ -2049,6 +2030,7 @@ static struct platform_driver mv643xx_eth_driver = {
- .shutdown = mv643xx_eth_shutdown,
- .driver = {
- .name = MV643XX_ETH_NAME,
-+ .owner = THIS_MODULE,
- },
- };
-
-@@ -2057,6 +2039,7 @@ static struct platform_driver mv643xx_eth_shared_driver = {
- .remove = mv643xx_eth_shared_remove,
- .driver = {
- .name = MV643XX_ETH_SHARED_NAME,
-+ .owner = THIS_MODULE,
- },
- };
-
-@@ -2104,7 +2087,8 @@ MODULE_LICENSE("GPL");
- MODULE_AUTHOR( "Rabeeh Khoury, Assaf Hoffman, Matthew Dharm, Manish Lachwani"
- " and Dale Farnsworth");
- MODULE_DESCRIPTION("Ethernet driver for Marvell MV643XX");
--MODULE_ALIAS("platform:mv643xx_eth");
-+MODULE_ALIAS("platform:" MV643XX_ETH_NAME);
-+MODULE_ALIAS("platform:" MV643XX_ETH_SHARED_NAME);
-
- /*
- * The second part is the low level driver of the gigE ethernet ports.
-@@ -2229,12 +2213,9 @@ MODULE_ALIAS("platform:mv643xx_eth");
- * return_info Tx/Rx user resource return information.
- */
-
--/* PHY routines */
--static int ethernet_phy_get(unsigned int eth_port_num);
--static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr);
--
- /* Ethernet Port routines */
--static void eth_port_set_filter_table_entry(int table, unsigned char entry);
-+static void eth_port_set_filter_table_entry(struct mv643xx_private *mp,
-+ int table, unsigned char entry);
-
- /*
- * eth_port_init - Initialize the Ethernet port driver
-@@ -2264,9 +2245,9 @@ static void eth_port_init(struct mv643xx_private *mp)
- {
- mp->rx_resource_err = 0;
-
-- eth_port_reset(mp->port_num);
-+ eth_port_reset(mp);
-
-- eth_port_init_mac_tables(mp->port_num);
-+ eth_port_init_mac_tables(mp);
- }
-
- /*
-@@ -2306,28 +2287,28 @@ static void eth_port_start(struct net_device *dev)
-
- /* Assignment of Tx CTRP of given queue */
- tx_curr_desc = mp->tx_curr_desc_q;
-- mv_write(TX_CURRENT_QUEUE_DESC_PTR_0(port_num),
-+ wrl(mp, TX_CURRENT_QUEUE_DESC_PTR_0(port_num),
- (u32)((struct eth_tx_desc *)mp->tx_desc_dma + tx_curr_desc));
-
- /* Assignment of Rx CRDP of given queue */
- rx_curr_desc = mp->rx_curr_desc_q;
-- mv_write(RX_CURRENT_QUEUE_DESC_PTR_0(port_num),
-+ wrl(mp, RX_CURRENT_QUEUE_DESC_PTR_0(port_num),
- (u32)((struct eth_rx_desc *)mp->rx_desc_dma + rx_curr_desc));
-
- /* Add the assigned Ethernet address to the port's address table */
-- eth_port_uc_addr_set(port_num, dev->dev_addr);
-+ eth_port_uc_addr_set(mp, dev->dev_addr);
-
- /* Assign port configuration and command. */
-- mv_write(PORT_CONFIG_REG(port_num),
-+ wrl(mp, PORT_CONFIG_REG(port_num),
- PORT_CONFIG_DEFAULT_VALUE);
-
-- mv_write(PORT_CONFIG_EXTEND_REG(port_num),
-+ wrl(mp, PORT_CONFIG_EXTEND_REG(port_num),
- PORT_CONFIG_EXTEND_DEFAULT_VALUE);
-
-- pscr = mv_read(PORT_SERIAL_CONTROL_REG(port_num));
-+ pscr = rdl(mp, PORT_SERIAL_CONTROL_REG(port_num));
-
- pscr &= ~(SERIAL_PORT_ENABLE | FORCE_LINK_PASS);
-- mv_write(PORT_SERIAL_CONTROL_REG(port_num), pscr);
-+ wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), pscr);
-
- pscr |= DISABLE_AUTO_NEG_FOR_FLOW_CTRL |
- DISABLE_AUTO_NEG_SPEED_GMII |
-@@ -2335,32 +2316,34 @@ static void eth_port_start(struct net_device *dev)
- DO_NOT_FORCE_LINK_FAIL |
- SERIAL_PORT_CONTROL_RESERVED;
-
-- mv_write(PORT_SERIAL_CONTROL_REG(port_num), pscr);
-+ wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), pscr);
-
- pscr |= SERIAL_PORT_ENABLE;
-- mv_write(PORT_SERIAL_CONTROL_REG(port_num), pscr);
-+ wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), pscr);
-
- /* Assign port SDMA configuration */
-- mv_write(SDMA_CONFIG_REG(port_num),
-+ wrl(mp, SDMA_CONFIG_REG(port_num),
- PORT_SDMA_CONFIG_DEFAULT_VALUE);
-
- /* Enable port Rx. */
-- mv643xx_eth_port_enable_rx(port_num, ETH_RX_QUEUES_ENABLED);
-+ mv643xx_eth_port_enable_rx(mp, ETH_RX_QUEUES_ENABLED);
-
- /* Disable port bandwidth limits by clearing MTU register */
-- mv_write(MAXIMUM_TRANSMIT_UNIT(port_num), 0);
-+ wrl(mp, MAXIMUM_TRANSMIT_UNIT(port_num), 0);
-
- /* save phy settings across reset */
- mv643xx_get_settings(dev, ðtool_cmd);
-- ethernet_phy_reset(mp->port_num);
-+ ethernet_phy_reset(mp);
- mv643xx_set_settings(dev, ðtool_cmd);
- }
-
- /*
- * eth_port_uc_addr_set - Write a MAC address into the port's hw registers
- */
--static void eth_port_uc_addr_set(unsigned int port_num, unsigned char *p_addr)
-+static void eth_port_uc_addr_set(struct mv643xx_private *mp,
-+ unsigned char *p_addr)
- {
-+ unsigned int port_num = mp->port_num;
- unsigned int mac_h;
- unsigned int mac_l;
- int table;
-@@ -2369,24 +2352,26 @@ static void eth_port_uc_addr_set(unsigned int port_num, unsigned char *p_addr)
- mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) | (p_addr[2] << 8) |
- (p_addr[3] << 0);
-
-- mv_write(MAC_ADDR_LOW(port_num), mac_l);
-- mv_write(MAC_ADDR_HIGH(port_num), mac_h);
-+ wrl(mp, MAC_ADDR_LOW(port_num), mac_l);
-+ wrl(mp, MAC_ADDR_HIGH(port_num), mac_h);
-
- /* Accept frames with this address */
- table = DA_FILTER_UNICAST_TABLE_BASE(port_num);
-- eth_port_set_filter_table_entry(table, p_addr[5] & 0x0f);
-+ eth_port_set_filter_table_entry(mp, table, p_addr[5] & 0x0f);
- }
-
- /*
- * eth_port_uc_addr_get - Read the MAC address from the port's hw registers
- */
--static void eth_port_uc_addr_get(unsigned int port_num, unsigned char *p_addr)
-+static void eth_port_uc_addr_get(struct mv643xx_private *mp,
-+ unsigned char *p_addr)
- {
-+ unsigned int port_num = mp->port_num;
- unsigned int mac_h;
- unsigned int mac_l;
-
-- mac_h = mv_read(MAC_ADDR_HIGH(port_num));
-- mac_l = mv_read(MAC_ADDR_LOW(port_num));
-+ mac_h = rdl(mp, MAC_ADDR_HIGH(port_num));
-+ mac_l = rdl(mp, MAC_ADDR_LOW(port_num));
-
- p_addr[0] = (mac_h >> 24) & 0xff;
- p_addr[1] = (mac_h >> 16) & 0xff;
-@@ -2405,7 +2390,8 @@ static void eth_port_uc_addr_get(unsigned int port_num, unsigned char *p_addr)
- * 3-1 Queue (ETH_Q0=0)
- * 7-4 Reserved = 0;
- */
--static void eth_port_set_filter_table_entry(int table, unsigned char entry)
-+static void eth_port_set_filter_table_entry(struct mv643xx_private *mp,
-+ int table, unsigned char entry)
- {
- unsigned int table_reg;
- unsigned int tbl_offset;
-@@ -2415,9 +2401,9 @@ static void eth_port_set_filter_table_entry(int table, unsigned char entry)
- reg_offset = entry % 4; /* Entry offset within the register */
-
- /* Set "accepts frame bit" at specified table entry */
-- table_reg = mv_read(table + tbl_offset);
-+ table_reg = rdl(mp, table + tbl_offset);
- table_reg |= 0x01 << (8 * reg_offset);
-- mv_write(table + tbl_offset, table_reg);
-+ wrl(mp, table + tbl_offset, table_reg);
- }
-
- /*
-@@ -2434,8 +2420,9 @@ static void eth_port_set_filter_table_entry(int table, unsigned char entry)
- * In either case, eth_port_set_filter_table_entry() is then called
- * to set to set the actual table entry.
- */
--static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr)
-+static void eth_port_mc_addr(struct mv643xx_private *mp, unsigned char *p_addr)
- {
-+ unsigned int port_num = mp->port_num;
- unsigned int mac_h;
- unsigned int mac_l;
- unsigned char crc_result = 0;
-@@ -2446,9 +2433,8 @@ static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr)
-
- if ((p_addr[0] == 0x01) && (p_addr[1] == 0x00) &&
- (p_addr[2] == 0x5E) && (p_addr[3] == 0x00) && (p_addr[4] == 0x00)) {
-- table = DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
-- (eth_port_num);
-- eth_port_set_filter_table_entry(table, p_addr[5]);
-+ table = DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port_num);
-+ eth_port_set_filter_table_entry(mp, table, p_addr[5]);
- return;
- }
-
-@@ -2520,8 +2506,8 @@ static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr)
- for (i = 0; i < 8; i++)
- crc_result = crc_result | (crc[i] << i);
-
-- table = DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num);
-- eth_port_set_filter_table_entry(table, crc_result);
-+ table = DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port_num);
-+ eth_port_set_filter_table_entry(mp, table, crc_result);
- }
-
- /*
-@@ -2550,7 +2536,7 @@ static void eth_port_set_multicast_list(struct net_device *dev)
- * 3-1 Queue ETH_Q0=0
- * 7-4 Reserved = 0;
- */
-- mv_write(DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
-+ wrl(mp, DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
-
- /* Set all entries in DA filter other multicast
- * table (Ex_dFOMT)
-@@ -2560,7 +2546,7 @@ static void eth_port_set_multicast_list(struct net_device *dev)
- * 3-1 Queue ETH_Q0=0
- * 7-4 Reserved = 0;
- */
-- mv_write(DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
-+ wrl(mp, DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
- }
- return;
- }
-@@ -2570,11 +2556,11 @@ static void eth_port_set_multicast_list(struct net_device *dev)
- */
- for (table_index = 0; table_index <= 0xFC; table_index += 4) {
- /* Clear DA filter special multicast table (Ex_dFSMT) */
-- mv_write(DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
-+ wrl(mp, DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
- (eth_port_num) + table_index, 0);
-
- /* Clear DA filter other multicast table (Ex_dFOMT) */
-- mv_write(DA_FILTER_OTHER_MULTICAST_TABLE_BASE
-+ wrl(mp, DA_FILTER_OTHER_MULTICAST_TABLE_BASE
- (eth_port_num) + table_index, 0);
- }
-
-@@ -2583,7 +2569,7 @@ static void eth_port_set_multicast_list(struct net_device *dev)
- (i < 256) && (mc_list != NULL) && (i < dev->mc_count);
- i++, mc_list = mc_list->next)
- if (mc_list->dmi_addrlen == 6)
-- eth_port_mc_addr(eth_port_num, mc_list->dmi_addr);
-+ eth_port_mc_addr(mp, mc_list->dmi_addr);
- }
-
- /*
-@@ -2594,7 +2580,7 @@ static void eth_port_set_multicast_list(struct net_device *dev)
- * Other Multicast) and set each entry to 0.
- *
- * INPUT:
-- * unsigned int eth_port_num Ethernet Port number.
-+ * struct mv643xx_private *mp Ethernet Port.
- *
- * OUTPUT:
- * Multicast and Unicast packets are rejected.
-@@ -2602,22 +2588,23 @@ static void eth_port_set_multicast_list(struct net_device *dev)
- * RETURN:
- * None.
- */
--static void eth_port_init_mac_tables(unsigned int eth_port_num)
-+static void eth_port_init_mac_tables(struct mv643xx_private *mp)
- {
-+ unsigned int port_num = mp->port_num;
- int table_index;
-
- /* Clear DA filter unicast table (Ex_dFUT) */
- for (table_index = 0; table_index <= 0xC; table_index += 4)
-- mv_write(DA_FILTER_UNICAST_TABLE_BASE
-- (eth_port_num) + table_index, 0);
-+ wrl(mp, DA_FILTER_UNICAST_TABLE_BASE(port_num) +
-+ table_index, 0);
-
- for (table_index = 0; table_index <= 0xFC; table_index += 4) {
- /* Clear DA filter special multicast table (Ex_dFSMT) */
-- mv_write(DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
-- (eth_port_num) + table_index, 0);
-+ wrl(mp, DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port_num) +
-+ table_index, 0);
- /* Clear DA filter other multicast table (Ex_dFOMT) */
-- mv_write(DA_FILTER_OTHER_MULTICAST_TABLE_BASE
-- (eth_port_num) + table_index, 0);
-+ wrl(mp, DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port_num) +
-+ table_index, 0);
- }
- }
-
-@@ -2629,7 +2616,7 @@ static void eth_port_init_mac_tables(unsigned int eth_port_num)
- * A read from the MIB counter will reset the counter.
- *
- * INPUT:
-- * unsigned int eth_port_num Ethernet Port number.
-+ * struct mv643xx_private *mp Ethernet Port.
- *
- * OUTPUT:
- * After reading all MIB counters, the counters resets.
-@@ -2638,19 +2625,20 @@ static void eth_port_init_mac_tables(unsigned int eth_port_num)
- * MIB counter value.
- *
- */
--static void eth_clear_mib_counters(unsigned int eth_port_num)
-+static void eth_clear_mib_counters(struct mv643xx_private *mp)
- {
-+ unsigned int port_num = mp->port_num;
- int i;
-
- /* Perform dummy reads from MIB counters */
- for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION;
- i += 4)
-- mv_read(MIB_COUNTERS_BASE(eth_port_num) + i);
-+ rdl(mp, MIB_COUNTERS_BASE(port_num) + i);
- }
-
- static inline u32 read_mib(struct mv643xx_private *mp, int offset)
- {
-- return mv_read(MIB_COUNTERS_BASE(mp->port_num) + offset);
-+ return rdl(mp, MIB_COUNTERS_BASE(mp->port_num) + offset);
- }
-
- static void eth_update_mib_counters(struct mv643xx_private *mp)
-@@ -2686,7 +2674,7 @@ static void eth_update_mib_counters(struct mv643xx_private *mp)
- * the specified port.
- *
- * INPUT:
-- * unsigned int eth_port_num Ethernet Port number.
-+ * struct mv643xx_private *mp Ethernet Port.
- *
- * OUTPUT:
- * None
-@@ -2696,22 +2684,22 @@ static void eth_update_mib_counters(struct mv643xx_private *mp)
- * -ENODEV on failure
- *
- */
--static int ethernet_phy_detect(unsigned int port_num)
-+static int ethernet_phy_detect(struct mv643xx_private *mp)
- {
- unsigned int phy_reg_data0;
- int auto_neg;
-
-- eth_port_read_smi_reg(port_num, 0, &phy_reg_data0);
-+ eth_port_read_smi_reg(mp, 0, &phy_reg_data0);
- auto_neg = phy_reg_data0 & 0x1000;
- phy_reg_data0 ^= 0x1000; /* invert auto_neg */
-- eth_port_write_smi_reg(port_num, 0, phy_reg_data0);
-+ eth_port_write_smi_reg(mp, 0, phy_reg_data0);
-
-- eth_port_read_smi_reg(port_num, 0, &phy_reg_data0);
-+ eth_port_read_smi_reg(mp, 0, &phy_reg_data0);
- if ((phy_reg_data0 & 0x1000) == auto_neg)
- return -ENODEV; /* change didn't take */
-
- phy_reg_data0 ^= 0x1000;
-- eth_port_write_smi_reg(port_num, 0, phy_reg_data0);
-+ eth_port_write_smi_reg(mp, 0, phy_reg_data0);
- return 0;
- }
-
-@@ -2722,7 +2710,7 @@ static int ethernet_phy_detect(unsigned int port_num)
- * This routine returns the given ethernet port PHY address.
- *
- * INPUT:
-- * unsigned int eth_port_num Ethernet Port number.
-+ * struct mv643xx_private *mp Ethernet Port.
- *
- * OUTPUT:
- * None.
-@@ -2731,13 +2719,13 @@ static int ethernet_phy_detect(unsigned int port_num)
- * PHY address.
- *
- */
--static int ethernet_phy_get(unsigned int eth_port_num)
-+static int ethernet_phy_get(struct mv643xx_private *mp)
- {
- unsigned int reg_data;
-
-- reg_data = mv_read(PHY_ADDR_REG);
-+ reg_data = rdl(mp, PHY_ADDR_REG);
-
-- return ((reg_data >> (5 * eth_port_num)) & 0x1f);
-+ return ((reg_data >> (5 * mp->port_num)) & 0x1f);
- }
-
- /*
-@@ -2747,7 +2735,7 @@ static int ethernet_phy_get(unsigned int eth_port_num)
- * This routine sets the given ethernet port PHY address.
- *
- * INPUT:
-- * unsigned int eth_port_num Ethernet Port number.
-+ * struct mv643xx_private *mp Ethernet Port.
- * int phy_addr PHY address.
- *
- * OUTPUT:
-@@ -2757,15 +2745,15 @@ static int ethernet_phy_get(unsigned int eth_port_num)
- * None.
- *
- */
--static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr)
-+static void ethernet_phy_set(struct mv643xx_private *mp, int phy_addr)
- {
- u32 reg_data;
-- int addr_shift = 5 * eth_port_num;
-+ int addr_shift = 5 * mp->port_num;
-
-- reg_data = mv_read(PHY_ADDR_REG);
-+ reg_data = rdl(mp, PHY_ADDR_REG);
- reg_data &= ~(0x1f << addr_shift);
- reg_data |= (phy_addr & 0x1f) << addr_shift;
-- mv_write(PHY_ADDR_REG, reg_data);
-+ wrl(mp, PHY_ADDR_REG, reg_data);
- }
-
- /*
-@@ -2775,7 +2763,7 @@ static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr)
- * This routine utilizes the SMI interface to reset the ethernet port PHY.
- *
- * INPUT:
-- * unsigned int eth_port_num Ethernet Port number.
-+ * struct mv643xx_private *mp Ethernet Port.
- *
- * OUTPUT:
- * The PHY is reset.
-@@ -2784,51 +2772,52 @@ static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr)
- * None.
- *
- */
--static void ethernet_phy_reset(unsigned int eth_port_num)
-+static void ethernet_phy_reset(struct mv643xx_private *mp)
- {
- unsigned int phy_reg_data;
-
- /* Reset the PHY */
-- eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data);
-+ eth_port_read_smi_reg(mp, 0, &phy_reg_data);
- phy_reg_data |= 0x8000; /* Set bit 15 to reset the PHY */
-- eth_port_write_smi_reg(eth_port_num, 0, phy_reg_data);
-+ eth_port_write_smi_reg(mp, 0, phy_reg_data);
-
- /* wait for PHY to come out of reset */
- do {
- udelay(1);
-- eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data);
-+ eth_port_read_smi_reg(mp, 0, &phy_reg_data);
- } while (phy_reg_data & 0x8000);
- }
-
--static void mv643xx_eth_port_enable_tx(unsigned int port_num,
-+static void mv643xx_eth_port_enable_tx(struct mv643xx_private *mp,
- unsigned int queues)
- {
-- mv_write(TRANSMIT_QUEUE_COMMAND_REG(port_num), queues);
-+ wrl(mp, TRANSMIT_QUEUE_COMMAND_REG(mp->port_num), queues);
- }
-
--static void mv643xx_eth_port_enable_rx(unsigned int port_num,
-+static void mv643xx_eth_port_enable_rx(struct mv643xx_private *mp,
- unsigned int queues)
- {
-- mv_write(RECEIVE_QUEUE_COMMAND_REG(port_num), queues);
-+ wrl(mp, RECEIVE_QUEUE_COMMAND_REG(mp->port_num), queues);
- }
-
--static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num)
-+static unsigned int mv643xx_eth_port_disable_tx(struct mv643xx_private *mp)
- {
-+ unsigned int port_num = mp->port_num;
- u32 queues;
-
- /* Stop Tx port activity. Check port Tx activity. */
-- queues = mv_read(TRANSMIT_QUEUE_COMMAND_REG(port_num)) & 0xFF;
-+ queues = rdl(mp, TRANSMIT_QUEUE_COMMAND_REG(port_num)) & 0xFF;
- if (queues) {
- /* Issue stop command for active queues only */
-- mv_write(TRANSMIT_QUEUE_COMMAND_REG(port_num), (queues << 8));
-+ wrl(mp, TRANSMIT_QUEUE_COMMAND_REG(port_num), (queues << 8));
-
- /* Wait for all Tx activity to terminate. */
- /* Check port cause register that all Tx queues are stopped */
-- while (mv_read(TRANSMIT_QUEUE_COMMAND_REG(port_num)) & 0xFF)
-+ while (rdl(mp, TRANSMIT_QUEUE_COMMAND_REG(port_num)) & 0xFF)
- udelay(PHY_WAIT_MICRO_SECONDS);
-
- /* Wait for Tx FIFO to empty */
-- while (mv_read(PORT_STATUS_REG(port_num)) &
-+ while (rdl(mp, PORT_STATUS_REG(port_num)) &
- ETH_PORT_TX_FIFO_EMPTY)
- udelay(PHY_WAIT_MICRO_SECONDS);
- }
-@@ -2836,19 +2825,20 @@ static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num)
- return queues;
- }
-
--static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num)
-+static unsigned int mv643xx_eth_port_disable_rx(struct mv643xx_private *mp)
- {
-+ unsigned int port_num = mp->port_num;
- u32 queues;
-
- /* Stop Rx port activity. Check port Rx activity. */
-- queues = mv_read(RECEIVE_QUEUE_COMMAND_REG(port_num)) & 0xFF;
-+ queues = rdl(mp, RECEIVE_QUEUE_COMMAND_REG(port_num)) & 0xFF;
- if (queues) {
- /* Issue stop command for active queues only */
-- mv_write(RECEIVE_QUEUE_COMMAND_REG(port_num), (queues << 8));
-+ wrl(mp, RECEIVE_QUEUE_COMMAND_REG(port_num), (queues << 8));
-
- /* Wait for all Rx activity to terminate. */
- /* Check port cause register that all Rx queues are stopped */
-- while (mv_read(RECEIVE_QUEUE_COMMAND_REG(port_num)) & 0xFF)
-+ while (rdl(mp, RECEIVE_QUEUE_COMMAND_REG(port_num)) & 0xFF)
- udelay(PHY_WAIT_MICRO_SECONDS);
- }
-
-@@ -2864,7 +2854,7 @@ static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num)
- * idle state after this command is performed and the port is disabled.
- *
- * INPUT:
-- * unsigned int eth_port_num Ethernet Port number.
-+ * struct mv643xx_private *mp Ethernet Port.
- *
- * OUTPUT:
- * Channel activity is halted.
-@@ -2873,22 +2863,23 @@ static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num)
- * None.
- *
- */
--static void eth_port_reset(unsigned int port_num)
-+static void eth_port_reset(struct mv643xx_private *mp)
- {
-+ unsigned int port_num = mp->port_num;
- unsigned int reg_data;
-
-- mv643xx_eth_port_disable_tx(port_num);
-- mv643xx_eth_port_disable_rx(port_num);
-+ mv643xx_eth_port_disable_tx(mp);
-+ mv643xx_eth_port_disable_rx(mp);
-
- /* Clear all MIB counters */
-- eth_clear_mib_counters(port_num);
-+ eth_clear_mib_counters(mp);
-
- /* Reset the Enable bit in the Configuration Register */
-- reg_data = mv_read(PORT_SERIAL_CONTROL_REG(port_num));
-+ reg_data = rdl(mp, PORT_SERIAL_CONTROL_REG(port_num));
- reg_data &= ~(SERIAL_PORT_ENABLE |
- DO_NOT_FORCE_LINK_FAIL |
- FORCE_LINK_PASS);
-- mv_write(PORT_SERIAL_CONTROL_REG(port_num), reg_data);
-+ wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), reg_data);
- }
-
-
-@@ -2900,7 +2891,7 @@ static void eth_port_reset(unsigned int port_num)
- * order to perform PHY register read.
- *
- * INPUT:
-- * unsigned int port_num Ethernet Port number.
-+ * struct mv643xx_private *mp Ethernet Port.
- * unsigned int phy_reg PHY register address offset.
- * unsigned int *value Register value buffer.
- *
-@@ -2912,10 +2903,10 @@ static void eth_port_reset(unsigned int port_num)
- * true otherwise.
- *
- */
--static void eth_port_read_smi_reg(unsigned int port_num,
-+static void eth_port_read_smi_reg(struct mv643xx_private *mp,
- unsigned int phy_reg, unsigned int *value)
- {
-- int phy_addr = ethernet_phy_get(port_num);
-+ int phy_addr = ethernet_phy_get(mp);
- unsigned long flags;
- int i;
-
-@@ -2923,27 +2914,27 @@ static void eth_port_read_smi_reg(unsigned int port_num,
- spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
-
- /* wait for the SMI register to become available */
-- for (i = 0; mv_read(SMI_REG) & ETH_SMI_BUSY; i++) {
-+ for (i = 0; rdl(mp, SMI_REG) & ETH_SMI_BUSY; i++) {
- if (i == PHY_WAIT_ITERATIONS) {
-- printk("mv643xx PHY busy timeout, port %d\n", port_num);
-+ printk("%s: PHY busy timeout\n", mp->dev->name);
- goto out;
- }
- udelay(PHY_WAIT_MICRO_SECONDS);
- }
-
-- mv_write(SMI_REG,
-+ wrl(mp, SMI_REG,
- (phy_addr << 16) | (phy_reg << 21) | ETH_SMI_OPCODE_READ);
-
- /* now wait for the data to be valid */
-- for (i = 0; !(mv_read(SMI_REG) & ETH_SMI_READ_VALID); i++) {
-+ for (i = 0; !(rdl(mp, SMI_REG) & ETH_SMI_READ_VALID); i++) {
- if (i == PHY_WAIT_ITERATIONS) {
-- printk("mv643xx PHY read timeout, port %d\n", port_num);
-+ printk("%s: PHY read timeout\n", mp->dev->name);
- goto out;
- }
- udelay(PHY_WAIT_MICRO_SECONDS);
- }
-
-- *value = mv_read(SMI_REG) & 0xffff;
-+ *value = rdl(mp, SMI_REG) & 0xffff;
- out:
- spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags);
- }
-@@ -2956,7 +2947,7 @@ out:
- * order to perform writes to PHY registers.
- *
- * INPUT:
-- * unsigned int eth_port_num Ethernet Port number.
-+ * struct mv643xx_private *mp Ethernet Port.
- * unsigned int phy_reg PHY register address offset.
- * unsigned int value Register value.
- *
-@@ -2968,29 +2959,28 @@ out:
- * true otherwise.
- *
- */
--static void eth_port_write_smi_reg(unsigned int eth_port_num,
-+static void eth_port_write_smi_reg(struct mv643xx_private *mp,
- unsigned int phy_reg, unsigned int value)
- {
- int phy_addr;
- int i;
- unsigned long flags;
-
-- phy_addr = ethernet_phy_get(eth_port_num);
-+ phy_addr = ethernet_phy_get(mp);
-
- /* the SMI register is a shared resource */
- spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
-
- /* wait for the SMI register to become available */
-- for (i = 0; mv_read(SMI_REG) & ETH_SMI_BUSY; i++) {
-+ for (i = 0; rdl(mp, SMI_REG) & ETH_SMI_BUSY; i++) {
- if (i == PHY_WAIT_ITERATIONS) {
-- printk("mv643xx PHY busy timeout, port %d\n",
-- eth_port_num);
-+ printk("%s: PHY busy timeout\n", mp->dev->name);
- goto out;
- }
- udelay(PHY_WAIT_MICRO_SECONDS);
- }
-
-- mv_write(SMI_REG, (phy_addr << 16) | (phy_reg << 21) |
-+ wrl(mp, SMI_REG, (phy_addr << 16) | (phy_reg << 21) |
- ETH_SMI_OPCODE_WRITE | (value & 0xffff));
- out:
- spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags);
-@@ -3001,17 +2991,17 @@ out:
- */
- static int mv643xx_mdio_read(struct net_device *dev, int phy_id, int location)
- {
-- int val;
- struct mv643xx_private *mp = netdev_priv(dev);
-+ int val;
-
-- eth_port_read_smi_reg(mp->port_num, location, &val);
-+ eth_port_read_smi_reg(mp, location, &val);
- return val;
- }
-
- static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, int val)
- {
- struct mv643xx_private *mp = netdev_priv(dev);
-- eth_port_write_smi_reg(mp->port_num, location, val);
-+ eth_port_write_smi_reg(mp, location, val);
- }
-
- /*
-@@ -3156,7 +3146,7 @@ struct mv643xx_stats {
- int stat_offset;
- };
-
--#define MV643XX_STAT(m) sizeof(((struct mv643xx_private *)0)->m), \
-+#define MV643XX_STAT(m) FIELD_SIZEOF(struct mv643xx_private, m), \
- offsetof(struct mv643xx_private, m)
-
- static const struct mv643xx_stats mv643xx_gstrings_stats[] = {
-diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
-index 385f69c..46119bb 100644
---- a/drivers/net/natsemi.c
-+++ b/drivers/net/natsemi.c
-@@ -511,10 +511,10 @@ enum PhyCtrl_bits {
- /* Note that using only 32 bit fields simplifies conversion to big-endian
- architectures. */
- struct netdev_desc {
-- u32 next_desc;
-- s32 cmd_status;
-- u32 addr;
-- u32 software_use;
-+ __le32 next_desc;
-+ __le32 cmd_status;
-+ __le32 addr;
-+ __le32 software_use;
- };
-
- /* Bits in network_desc.status */
-@@ -786,7 +786,8 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
- struct netdev_private *np;
- int i, option, irq, chip_idx = ent->driver_data;
- static int find_cnt = -1;
-- unsigned long iostart, iosize;
-+ resource_size_t iostart;
-+ unsigned long iosize;
- void __iomem *ioaddr;
- const int pcibar = 1; /* PCI base address register */
- int prev_eedata;
-@@ -946,10 +947,11 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
- goto err_create_file;
-
- if (netif_msg_drv(np)) {
-- printk(KERN_INFO "natsemi %s: %s at %#08lx "
-+ printk(KERN_INFO "natsemi %s: %s at %#08llx "
- "(%s), %s, IRQ %d",
-- dev->name, natsemi_pci_info[chip_idx].name, iostart,
-- pci_name(np->pci_dev), print_mac(mac, dev->dev_addr), irq);
-+ dev->name, natsemi_pci_info[chip_idx].name,
-+ (unsigned long long)iostart, pci_name(np->pci_dev),
-+ print_mac(mac, dev->dev_addr), irq);
- if (dev->if_port == PORT_TP)
- printk(", port TP.\n");
- else if (np->ignore_phy)
-@@ -2018,7 +2020,7 @@ static void drain_rx(struct net_device *dev)
- /* Free all the skbuffs in the Rx queue. */
- for (i = 0; i < RX_RING_SIZE; i++) {
- np->rx_ring[i].cmd_status = 0;
-- np->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */
-+ np->rx_ring[i].addr = cpu_to_le32(0xBADF00D0); /* An invalid address. */
- if (np->rx_skbuff[i]) {
- pci_unmap_single(np->pci_dev,
- np->rx_dma[i], buflen,
-diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
-index 78d34af..dc442e3 100644
---- a/drivers/net/netx-eth.c
-+++ b/drivers/net/netx-eth.c
-@@ -502,4 +502,4 @@ module_exit(netx_eth_cleanup);
-
- MODULE_AUTHOR("Sascha Hauer, Pengutronix");
- MODULE_LICENSE("GPL");
--
-+MODULE_ALIAS("platform:" CARDNAME);
-diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
-index 7f20a03..8cb29f5 100644
---- a/drivers/net/netxen/netxen_nic.h
-+++ b/drivers/net/netxen/netxen_nic.h
-@@ -95,23 +95,6 @@
-
- #define ADDR_IN_WINDOW1(off) \
- ((off > NETXEN_CRB_PCIX_HOST2) && (off < NETXEN_CRB_MAX)) ? 1 : 0
--/*
-- * In netxen_nic_down(), we must wait for any pending callback requests into
-- * netxen_watchdog_task() to complete; eg otherwise the watchdog_timer could be
-- * reenabled right after it is deleted in netxen_nic_down(). FLUSH_SCHEDULED_WORK()
-- * does this synchronization.
-- *
-- * Normally, schedule_work()/flush_scheduled_work() could have worked, but
-- * netxen_nic_close() is invoked with kernel rtnl lock held. netif_carrier_off()
-- * call in netxen_nic_close() triggers a schedule_work(&linkwatch_work), and a
-- * subsequent call to flush_scheduled_work() in netxen_nic_down() would cause
-- * linkwatch_event() to be executed which also attempts to acquire the rtnl
-- * lock thus causing a deadlock.
-- */
--
--#define SCHEDULE_WORK(tp) queue_work(netxen_workq, tp)
--#define FLUSH_SCHEDULED_WORK() flush_workqueue(netxen_workq)
--extern struct workqueue_struct *netxen_workq;
-
- /*
- * normalize a 64MB crb address to 32MB PCI window
-@@ -1050,7 +1033,6 @@ void netxen_halt_pegs(struct netxen_adapter *adapter);
- int netxen_rom_se(struct netxen_adapter *adapter, int addr);
-
- /* Functions from netxen_nic_isr.c */
--int netxen_nic_link_ok(struct netxen_adapter *adapter);
- void netxen_initialize_adapter_sw(struct netxen_adapter *adapter);
- void netxen_initialize_adapter_hw(struct netxen_adapter *adapter);
- void *netxen_alloc(struct pci_dev *pdev, size_t sz, dma_addr_t * ptr,
-diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
-index 160f605..24d027e 100644
---- a/drivers/net/netxen/netxen_nic_hdr.h
-+++ b/drivers/net/netxen/netxen_nic_hdr.h
-@@ -34,7 +34,6 @@
- #include <linux/kernel.h>
- #include <linux/version.h>
-
--#include <asm/semaphore.h>
- #include <linux/spinlock.h>
- #include <asm/irq.h>
- #include <linux/init.h>
-diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
-index 05748ca..af73564 100644
---- a/drivers/net/netxen/netxen_nic_hw.c
-+++ b/drivers/net/netxen/netxen_nic_hw.c
-@@ -1132,8 +1132,8 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
- u32 fw_minor = 0;
- u32 fw_build = 0;
- char brd_name[NETXEN_MAX_SHORT_NAME];
-- struct netxen_new_user_info user_info;
-- int i, addr = NETXEN_USER_START;
-+ char serial_num[32];
-+ int i, addr;
- __le32 *ptr32;
-
- struct netxen_board_info *board_info = &(adapter->ahw.boardcfg);
-@@ -1150,10 +1150,10 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
- valid = 0;
- }
- if (valid) {
-- ptr32 = (u32 *) & user_info;
-- for (i = 0;
-- i < sizeof(struct netxen_new_user_info) / sizeof(u32);
-- i++) {
-+ ptr32 = (u32 *)&serial_num;
-+ addr = NETXEN_USER_START +
-+ offsetof(struct netxen_new_user_info, serial_num);
-+ for (i = 0; i < 8; i++) {
- if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) {
- printk("%s: ERROR reading %s board userarea.\n",
- netxen_nic_driver_name,
-@@ -1163,10 +1163,11 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
- ptr32++;
- addr += sizeof(u32);
- }
++/* Handle a legacy interrupt from Falcon
++ * Acknowledges the interrupt and schedule event queue processing.
++ */
++static irqreturn_t falcon_legacy_interrupt_b0(int irq, void *dev_id)
++{
++ struct efx_nic *efx = (struct efx_nic *)dev_id;
++ efx_oword_t *int_ker = (efx_oword_t *) efx->irq_status.addr;
++ struct efx_channel *channel;
++ efx_dword_t reg;
++ u32 queues;
++ int syserr;
++
++ /* Read the ISR which also ACKs the interrupts */
++ falcon_readl(efx, ®, INT_ISR0_B0);
++ queues = EFX_EXTRACT_DWORD(reg, 0, 31);
++
++ /* Check to see if we have a serious error condition */
++ syserr = EFX_OWORD_FIELD(*int_ker, FATAL_INT);
++ if (unlikely(syserr))
++ return falcon_fatal_interrupt(efx);
+
- 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.
++ if (queues == 0)
++ return IRQ_NONE;
++
++ efx->last_irq_cpu = raw_smp_processor_id();
++ EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_DWORD_FMT "\n",
++ irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg));
++
++ /* Schedule processing of any interrupting queues */
++ channel = &efx->channel[0];
++ while (queues) {
++ if (queues & 0x01)
++ efx_schedule_channel(channel);
++ channel++;
++ queues >>= 1;
++ }
++
++ return IRQ_HANDLED;
++}
++
++
++static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
++{
++ struct efx_nic *efx = (struct efx_nic *)dev_id;
++ efx_oword_t *int_ker = (efx_oword_t *) efx->irq_status.addr;
++ struct efx_channel *channel;
++ int syserr;
++ int queues;
++
++ /* Check to see if this is our interrupt. If it isn't, we
++ * exit without having touched the hardware.
++ */
++ if (unlikely(EFX_OWORD_IS_ZERO(*int_ker))) {
++ EFX_TRACE(efx, "IRQ %d on CPU %d not for me\n", irq,
++ raw_smp_processor_id());
++ return IRQ_NONE;
++ }
++ efx->last_irq_cpu = raw_smp_processor_id();
++ EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n",
++ irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker));
++
++ /* Check to see if we have a serious error condition */
++ syserr = EFX_OWORD_FIELD(*int_ker, FATAL_INT);
++ if (unlikely(syserr))
++ return falcon_fatal_interrupt(efx);
++
++ /* Determine interrupting queues, clear interrupt status
++ * register and acknowledge the device interrupt.
++ */
++ BUILD_BUG_ON(INT_EVQS_WIDTH > EFX_MAX_CHANNELS);
++ queues = EFX_OWORD_FIELD(*int_ker, INT_EVQS);
++ EFX_ZERO_OWORD(*int_ker);
++ wmb(); /* Ensure the vector is cleared before interrupt ack */
++ falcon_irq_ack_a1(efx);
++
++ /* Schedule processing of any interrupting queues */
++ channel = &efx->channel[0];
++ while (queues) {
++ if (queues & 0x01)
++ efx_schedule_channel(channel);
++ channel++;
++ queues >>= 1;
++ }
++
++ return IRQ_HANDLED;
++}
++
++/* Handle an MSI interrupt from Falcon
+ *
-+ * 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.
++ * Handle an MSI hardware interrupt. This routine schedules event
++ * queue processing. No interrupt acknowledgement cycle is necessary.
++ * Also, we never need to check that the interrupt is for us, since
++ * MSI interrupts cannot be shared.
++ */
++static irqreturn_t falcon_msi_interrupt(int irq, void *dev_id)
++{
++ struct efx_channel *channel = (struct efx_channel *)dev_id;
++ struct efx_nic *efx = channel->efx;
++ efx_oword_t *int_ker = (efx_oword_t *) efx->irq_status.addr;
++ int syserr;
++
++ efx->last_irq_cpu = raw_smp_processor_id();
++ EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n",
++ irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker));
++
++ /* Check to see if we have a serious error condition */
++ syserr = EFX_OWORD_FIELD(*int_ker, FATAL_INT);
++ if (unlikely(syserr))
++ return falcon_fatal_interrupt(efx);
++
++ /* Schedule processing of the channel */
++ efx_schedule_channel(channel);
++
++ return IRQ_HANDLED;
++}
++
++
++/* Setup RSS indirection table.
++ * This maps from the hash value of the packet to RXQ
+ */
++static void falcon_setup_rss_indir_table(struct efx_nic *efx)
++{
++ int i = 0;
++ unsigned long offset;
++ efx_dword_t dword;
+
-+static struct workqueue_struct *netxen_workq;
-+#define SCHEDULE_WORK(tp) queue_work(netxen_workq, tp)
-+#define FLUSH_SCHEDULED_WORK() flush_workqueue(netxen_workq)
++ if (FALCON_REV(efx) < FALCON_REV_B0)
++ return;
+
- 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)
++ for (offset = RX_RSS_INDIR_TBL_B0;
++ offset < RX_RSS_INDIR_TBL_B0 + 0x800;
++ offset += 0x10) {
++ EFX_POPULATE_DWORD_1(dword, RX_RSS_INDIR_ENT_B0,
++ i % efx->rss_queues);
++ falcon_writel(efx, &dword, offset);
++ i++;
++ }
++}
++
++/* Hook interrupt handler(s)
++ * Try MSI and then legacy interrupts.
++ */
++int falcon_init_interrupt(struct efx_nic *efx)
+{
-+ struct iscp_struct __iomem *iscp = addr;
-+ struct priv *p = dev->priv;
-+ memset_io(iscp, 0, sizeof(struct iscp_struct));
++ struct efx_channel *channel;
++ int rc;
+
-+ writel(make24(iscp), &p->scp->iscp);
-+ writeb(1, &iscp->busy);
++ if (!EFX_INT_MODE_USE_MSI(efx)) {
++ irq_handler_t handler;
++ if (FALCON_REV(efx) >= FALCON_REV_B0)
++ handler = falcon_legacy_interrupt_b0;
++ else
++ handler = falcon_legacy_interrupt_a1;
+
-+ ni_reset586();
-+ ni_attn586();
-+ mdelay(32); /* wait a while... */
-+ /* i82586 clears 'busy' after successful init */
-+ if (readb(&iscp->busy))
++ rc = request_irq(efx->legacy_irq, handler, IRQF_SHARED,
++ efx->name, efx);
++ if (rc) {
++ EFX_ERR(efx, "failed to hook legacy IRQ %d\n",
++ efx->pci_dev->irq);
++ goto fail1;
++ }
+ return 0;
-+ return 1;
++ }
++
++ /* Hook MSI or MSI-X interrupt */
++ efx_for_each_channel_with_interrupt(channel, efx) {
++ rc = request_irq(channel->irq, falcon_msi_interrupt,
++ IRQF_PROBE_SHARED, /* Not shared */
++ efx->name, channel);
++ if (rc) {
++ EFX_ERR(efx, "failed to hook IRQ %d\n", channel->irq);
++ goto fail2;
++ }
++ }
++
++ return 0;
++
++ fail2:
++ efx_for_each_channel_with_interrupt(channel, efx)
++ free_irq(channel->irq, channel);
++ fail1:
++ return rc;
+}
+
- /**********************************************
- * 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)
++void falcon_fini_interrupt(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++ efx_oword_t reg;
++
++ /* Disable MSI/MSI-X interrupts */
++ efx_for_each_channel_with_interrupt(channel, efx)
++ if (channel->irq)
++ free_irq(channel->irq, channel);
++
++ /* ACK legacy interrupt */
++ if (FALCON_REV(efx) >= FALCON_REV_B0)
++ falcon_read(efx, ®, INT_ISR0_B0);
++ else
++ falcon_irq_ack_a1(efx);
++
++ /* Disable legacy interrupt */
++ if (efx->legacy_irq)
++ free_irq(efx->legacy_irq, efx);
++}
++
++/**************************************************************************
++ *
++ * EEPROM/flash
++ *
++ **************************************************************************
++ */
++
++#define FALCON_SPI_MAX_LEN sizeof(efx_oword_t)
++
++/* Wait for SPI command completion */
++static int falcon_spi_wait(struct efx_nic *efx)
++{
++ efx_oword_t reg;
++ int cmd_en, timer_active;
++ int count;
++
++ count = 0;
++ do {
++ falcon_read(efx, ®, EE_SPI_HCMD_REG_KER);
++ cmd_en = EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN);
++ timer_active = EFX_OWORD_FIELD(reg, EE_WR_TIMER_ACTIVE);
++ if (!cmd_en && !timer_active)
++ return 0;
++ udelay(10);
++ } while (++count < 10000); /* wait upto 100msec */
++ EFX_ERR(efx, "timed out waiting for SPI\n");
++ return -ETIMEDOUT;
++}
++
++static int
++falcon_spi_read(struct efx_nic *efx, int device_id, unsigned int command,
++ unsigned int address, unsigned int addr_len,
++ void *data, unsigned int len)
++{
++ efx_oword_t reg;
++ int rc;
++
++ BUG_ON(len > FALCON_SPI_MAX_LEN);
++
++ /* Check SPI not currently being accessed */
++ rc = falcon_spi_wait(efx);
++ if (rc)
++ return rc;
++
++ /* Program address register */
++ EFX_POPULATE_OWORD_1(reg, EE_SPI_HADR_ADR, address);
++ falcon_write(efx, ®, EE_SPI_HADR_REG_KER);
++
++ /* Issue read command */
++ EFX_POPULATE_OWORD_7(reg,
++ EE_SPI_HCMD_CMD_EN, 1,
++ EE_SPI_HCMD_SF_SEL, device_id,
++ EE_SPI_HCMD_DABCNT, len,
++ EE_SPI_HCMD_READ, EE_SPI_READ,
++ EE_SPI_HCMD_DUBCNT, 0,
++ EE_SPI_HCMD_ADBCNT, addr_len,
++ EE_SPI_HCMD_ENC, command);
++ falcon_write(efx, ®, EE_SPI_HCMD_REG_KER);
++
++ /* Wait for read to complete */
++ rc = falcon_spi_wait(efx);
++ if (rc)
++ return rc;
++
++ /* Read data */
++ falcon_read(efx, ®, EE_SPI_HDATA_REG_KER);
++ memcpy(data, ®, len);
++ return 0;
++}
++
++/**************************************************************************
++ *
++ * MAC wrapper
++ *
++ **************************************************************************
++ */
++void falcon_drain_tx_fifo(struct efx_nic *efx)
++{
++ efx_oword_t temp;
++ int count;
++
++ if (FALCON_REV(efx) < FALCON_REV_B0)
++ return;
++
++ falcon_read(efx, &temp, MAC0_CTRL_REG_KER);
++ /* There is no point in draining more than once */
++ if (EFX_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0))
++ return;
++
++ /* MAC stats will fail whilst the TX fifo is draining. Serialise
++ * the drain sequence with the statistics fetch */
++ spin_lock(&efx->stats_lock);
++
++ EFX_SET_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0, 1);
++ falcon_write(efx, &temp, MAC0_CTRL_REG_KER);
++
++ /* Reset the MAC and EM block. */
++ falcon_read(efx, &temp, GLB_CTL_REG_KER);
++ EFX_SET_OWORD_FIELD(temp, RST_XGTX, 1);
++ EFX_SET_OWORD_FIELD(temp, RST_XGRX, 1);
++ EFX_SET_OWORD_FIELD(temp, RST_EM, 1);
++ falcon_write(efx, &temp, GLB_CTL_REG_KER);
++
++ count = 0;
++ while (1) {
++ falcon_read(efx, &temp, GLB_CTL_REG_KER);
++ if (!EFX_OWORD_FIELD(temp, RST_XGTX) &&
++ !EFX_OWORD_FIELD(temp, RST_XGRX) &&
++ !EFX_OWORD_FIELD(temp, RST_EM)) {
++ EFX_LOG(efx, "Completed MAC reset after %d loops\n",
++ count);
++ break;
++ }
++ if (count > 20) {
++ EFX_ERR(efx, "MAC reset failed\n");
++ break;
++ }
++ count++;
++ udelay(10);
++ }
++
++ spin_unlock(&efx->stats_lock);
++
++ /* If we've reset the EM block and the link is up, then
++ * we'll have to kick the XAUI link so the PHY can recover */
++ if (efx->link_up && EFX_WORKAROUND_5147(efx))
++ falcon_reset_xaui(efx);
++}
++
++void falcon_deconfigure_mac_wrapper(struct efx_nic *efx)
++{
++ efx_oword_t temp;
++
++ if (FALCON_REV(efx) < FALCON_REV_B0)
++ return;
++
++ /* Isolate the MAC -> RX */
++ falcon_read(efx, &temp, RX_CFG_REG_KER);
++ EFX_SET_OWORD_FIELD(temp, RX_INGR_EN_B0, 0);
++ falcon_write(efx, &temp, RX_CFG_REG_KER);
++
++ if (!efx->link_up)
++ falcon_drain_tx_fifo(efx);
++}
++
++void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
++{
++ efx_oword_t reg;
++ int link_speed;
++ unsigned int tx_fc;
++
++ if (efx->link_options & GM_LPA_10000)
++ link_speed = 0x3;
++ else if (efx->link_options & GM_LPA_1000)
++ link_speed = 0x2;
++ else if (efx->link_options & GM_LPA_100)
++ link_speed = 0x1;
++ else
++ link_speed = 0x0;
++ /* MAC_LINK_STATUS controls MAC backpressure but doesn't work
++ * as advertised. Disable to ensure packets are not
++ * indefinitely held and TX queue can be flushed at any point
++ * while the link is down. */
++ EFX_POPULATE_OWORD_5(reg,
++ MAC_XOFF_VAL, 0xffff /* max pause time */,
++ MAC_BCAD_ACPT, 1,
++ MAC_UC_PROM, efx->promiscuous,
++ MAC_LINK_STATUS, 1, /* always set */
++ MAC_SPEED, link_speed);
++ /* On B0, MAC backpressure can be disabled and packets get
++ * discarded. */
++ if (FALCON_REV(efx) >= FALCON_REV_B0) {
++ EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0,
++ !efx->link_up);
++ }
++
++ falcon_write(efx, ®, MAC0_CTRL_REG_KER);
++
++ /* Restore the multicast hash registers. */
++ falcon_set_multicast_hash(efx);
++
++ /* Transmission of pause frames when RX crosses the threshold is
++ * covered by RX_XOFF_MAC_EN and XM_TX_CFG_REG:XM_FCNTL.
++ * Action on receipt of pause frames is controller by XM_DIS_FCNTL */
++ tx_fc = (efx->flow_control & EFX_FC_TX) ? 1 : 0;
++ falcon_read(efx, ®, RX_CFG_REG_KER);
++ EFX_SET_OWORD_FIELD_VER(efx, reg, RX_XOFF_MAC_EN, tx_fc);
++
++ /* Unisolate the MAC -> RX */
++ if (FALCON_REV(efx) >= FALCON_REV_B0)
++ EFX_SET_OWORD_FIELD(reg, RX_INGR_EN_B0, 1);
++ falcon_write(efx, ®, RX_CFG_REG_KER);
++}
++
++int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset)
++{
++ efx_oword_t reg;
++ u32 *dma_done;
++ int i;
++
++ if (disable_dma_stats)
+ 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);
++ /* Statistics fetch will fail if the MAC is in TX drain */
++ if (FALCON_REV(efx) >= FALCON_REV_B0) {
++ efx_oword_t temp;
++ falcon_read(efx, &temp, MAC0_CTRL_REG_KER);
++ if (EFX_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0))
++ return 0;
++ }
++
++ dma_done = (efx->stats_buffer.addr + done_offset);
++ *dma_done = FALCON_STATS_NOT_DONE;
++ wmb(); /* ensure done flag is clear */
++
++ /* Initiate DMA transfer of stats */
++ EFX_POPULATE_OWORD_2(reg,
++ MAC_STAT_DMA_CMD, 1,
++ MAC_STAT_DMA_ADR,
++ efx->stats_buffer.dma_addr);
++ falcon_write(efx, ®, MAC0_STAT_DMA_REG_KER);
++
++ /* Wait for transfer to complete */
++ for (i = 0; i < 400; i++) {
++ if (*(volatile u32 *)dma_done == FALCON_STATS_DONE)
++ return 0;
++ udelay(10);
++ }
++
++ EFX_ERR(efx, "timed out waiting for statistics\n");
++ return -ETIMEDOUT;
++}
++
++/**************************************************************************
++ *
++ * PHY access via GMII
++ *
++ **************************************************************************
++ */
++
++/* Use the top bit of the MII PHY id to indicate the PHY type
++ * (1G/10G), with the remaining bits as the actual PHY id.
++ *
++ * This allows us to avoid leaking information from the mii_if_info
++ * structure into other data structures.
++ */
++#define FALCON_PHY_ID_ID_WIDTH EFX_WIDTH(MD_PRT_DEV_ADR)
++#define FALCON_PHY_ID_ID_MASK ((1 << FALCON_PHY_ID_ID_WIDTH) - 1)
++#define FALCON_PHY_ID_WIDTH (FALCON_PHY_ID_ID_WIDTH + 1)
++#define FALCON_PHY_ID_MASK ((1 << FALCON_PHY_ID_WIDTH) - 1)
++#define FALCON_PHY_ID_10G (1 << (FALCON_PHY_ID_WIDTH - 1))
++
++
++/* Packing the clause 45 port and device fields into a single value */
++#define MD_PRT_ADR_COMP_LBN (MD_PRT_ADR_LBN - MD_DEV_ADR_LBN)
++#define MD_PRT_ADR_COMP_WIDTH MD_PRT_ADR_WIDTH
++#define MD_DEV_ADR_COMP_LBN 0
++#define MD_DEV_ADR_COMP_WIDTH MD_DEV_ADR_WIDTH
++
++
++/* Wait for GMII access to complete */
++static int falcon_gmii_wait(struct efx_nic *efx)
++{
++ efx_dword_t md_stat;
++ int count;
++
++ for (count = 0; count < 1000; count++) { /* wait upto 10ms */
++ falcon_readl(efx, &md_stat, MD_STAT_REG_KER);
++ if (EFX_DWORD_FIELD(md_stat, MD_BSY) == 0) {
++ if (EFX_DWORD_FIELD(md_stat, MD_LNFL) != 0 ||
++ EFX_DWORD_FIELD(md_stat, MD_BSERR) != 0) {
++ EFX_ERR(efx, "error from GMII access "
++ EFX_DWORD_FMT"\n",
++ EFX_DWORD_VAL(md_stat));
++ return -EIO;
++ }
++ return 0;
++ }
++ udelay(10);
++ }
++ EFX_ERR(efx, "timed out waiting for GMII\n");
++ return -ETIMEDOUT;
++}
++
++/* Writes a GMII register of a PHY connected to Falcon using MDIO. */
++static void falcon_mdio_write(struct net_device *net_dev, int phy_id,
++ int addr, int value)
++{
++ struct efx_nic *efx = (struct efx_nic *)net_dev->priv;
++ unsigned int phy_id2 = phy_id & FALCON_PHY_ID_ID_MASK;
++ efx_oword_t reg;
++
++ /* The 'generic' prt/dev packing in mdio_10g.h is conveniently
++ * chosen so that the only current user, Falcon, can take the
++ * packed value and use them directly.
++ * Fail to build if this assumption is broken.
++ */
++ BUILD_BUG_ON(FALCON_PHY_ID_10G != MDIO45_XPRT_ID_IS10G);
++ BUILD_BUG_ON(FALCON_PHY_ID_ID_WIDTH != MDIO45_PRT_DEV_WIDTH);
++ BUILD_BUG_ON(MD_PRT_ADR_COMP_LBN != MDIO45_PRT_ID_COMP_LBN);
++ BUILD_BUG_ON(MD_DEV_ADR_COMP_LBN != MDIO45_DEV_ID_COMP_LBN);
++
++ if (phy_id2 == PHY_ADDR_INVALID)
++ return;
++
++ /* See falcon_mdio_read for an explanation. */
++ if (!(phy_id & FALCON_PHY_ID_10G)) {
++ int mmd = ffs(efx->phy_op->mmds) - 1;
++ EFX_TRACE(efx, "Fixing erroneous clause22 write\n");
++ phy_id2 = mdio_clause45_pack(phy_id2, mmd)
++ & FALCON_PHY_ID_ID_MASK;
++ }
++
++ EFX_REGDUMP(efx, "writing GMII %d register %02x with %04x\n", phy_id,
++ addr, value);
++
++ spin_lock_bh(&efx->phy_lock);
++
++ /* Check MII not currently being accessed */
++ if (falcon_gmii_wait(efx) != 0)
++ goto out;
++
++ /* Write the address/ID register */
++ EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr);
++ falcon_write(efx, ®, MD_PHY_ADR_REG_KER);
++
++ EFX_POPULATE_OWORD_1(reg, MD_PRT_DEV_ADR, phy_id2);
++ falcon_write(efx, ®, MD_ID_REG_KER);
++
++ /* Write data */
++ EFX_POPULATE_OWORD_1(reg, MD_TXD, value);
++ falcon_write(efx, ®, MD_TXD_REG_KER);
++
++ EFX_POPULATE_OWORD_2(reg,
++ MD_WRC, 1,
++ MD_GC, 0);
++ falcon_write(efx, ®, MD_CS_REG_KER);
++
++ /* Wait for data to be written */
++ if (falcon_gmii_wait(efx) != 0) {
++ /* Abort the write operation */
++ EFX_POPULATE_OWORD_2(reg,
++ MD_WRC, 0,
++ MD_GC, 1);
++ falcon_write(efx, ®, MD_CS_REG_KER);
++ udelay(10);
++ }
++
++ out:
++ spin_unlock_bh(&efx->phy_lock);
++}
++
++/* Reads a GMII register from a PHY connected to Falcon. If no value
++ * could be read, -1 will be returned. */
++static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr)
++{
++ struct efx_nic *efx = (struct efx_nic *)net_dev->priv;
++ unsigned int phy_addr = phy_id & FALCON_PHY_ID_ID_MASK;
++ efx_oword_t reg;
++ int value = -1;
++
++ if (phy_addr == PHY_ADDR_INVALID)
++ return -1;
++
++ /* Our PHY code knows whether it needs to talk clause 22(1G) or 45(10G)
++ * but the generic Linux code does not make any distinction or have
++ * any state for this.
++ * We spot the case where someone tried to talk 22 to a 45 PHY and
++ * redirect the request to the lowest numbered MMD as a clause45
++ * request. This is enough to allow simple queries like id and link
++ * state to succeed. TODO: We may need to do more in future.
++ */
++ if (!(phy_id & FALCON_PHY_ID_10G)) {
++ int mmd = ffs(efx->phy_op->mmds) - 1;
++ EFX_TRACE(efx, "Fixing erroneous clause22 read\n");
++ phy_addr = mdio_clause45_pack(phy_addr, mmd)
++ & FALCON_PHY_ID_ID_MASK;
++ }
++
++ spin_lock_bh(&efx->phy_lock);
++
++ /* Check MII not currently being accessed */
++ if (falcon_gmii_wait(efx) != 0)
++ goto out;
++
++ EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr);
++ falcon_write(efx, ®, MD_PHY_ADR_REG_KER);
++
++ EFX_POPULATE_OWORD_1(reg, MD_PRT_DEV_ADR, phy_addr);
++ falcon_write(efx, ®, MD_ID_REG_KER);
++
++ /* Request data to be read */
++ EFX_POPULATE_OWORD_2(reg, MD_RDC, 1, MD_GC, 0);
++ falcon_write(efx, ®, MD_CS_REG_KER);
++
++ /* Wait for data to become available */
++ value = falcon_gmii_wait(efx);
++ if (value == 0) {
++ falcon_read(efx, ®, MD_RXD_REG_KER);
++ value = EFX_OWORD_FIELD(reg, MD_RXD);
++ EFX_REGDUMP(efx, "read from GMII %d register %02x, got %04x\n",
++ phy_id, addr, value);
++ } else {
++ /* Abort the read operation */
++ EFX_POPULATE_OWORD_2(reg,
++ MD_RIC, 0,
++ MD_GC, 1);
++ falcon_write(efx, ®, MD_CS_REG_KER);
++
++ EFX_LOG(efx, "read from GMII 0x%x register %02x, got "
++ "error %d\n", phy_id, addr, value);
++ }
++
++ out:
++ spin_unlock_bh(&efx->phy_lock);
++
++ return value;
++}
++
++static void falcon_init_mdio(struct mii_if_info *gmii)
++{
++ gmii->mdio_read = falcon_mdio_read;
++ gmii->mdio_write = falcon_mdio_write;
++ gmii->phy_id_mask = FALCON_PHY_ID_MASK;
++ gmii->reg_num_mask = ((1 << EFX_WIDTH(MD_PHY_ADR)) - 1);
++}
++
++static int falcon_probe_phy(struct efx_nic *efx)
++{
++ switch (efx->phy_type) {
++ case PHY_TYPE_10XPRESS:
++ efx->phy_op = &falcon_tenxpress_phy_ops;
++ break;
++ case PHY_TYPE_XFP:
++ efx->phy_op = &falcon_xfp_phy_ops;
++ break;
++ default:
++ EFX_ERR(efx, "Unknown PHY type %d\n",
++ efx->phy_type);
++ return -1;
++ }
+ 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);
++/* This call is responsible for hooking in the MAC and PHY operations */
++int falcon_probe_port(struct efx_nic *efx)
++{
++ int rc;
+
- 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);
++ /* Hook in PHY operations table */
++ rc = falcon_probe_phy(efx);
++ if (rc)
++ return rc;
++
++ /* Set up GMII structure for PHY */
++ efx->mii.supports_gmii = 1;
++ falcon_init_mdio(&efx->mii);
++
++ /* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */
++ if (FALCON_REV(efx) >= FALCON_REV_B0)
++ efx->flow_control = EFX_FC_RX | EFX_FC_TX;
++ else
++ efx->flow_control = EFX_FC_RX;
++
++ /* Allocate buffer for stats */
++ rc = falcon_alloc_buffer(efx, &efx->stats_buffer,
++ FALCON_MAC_STATS_SIZE);
++ if (rc)
++ return rc;
++ EFX_LOG(efx, "stats buffer at %llx (virt %p phys %lx)\n",
++ (unsigned long long)efx->stats_buffer.dma_addr,
++ efx->stats_buffer.addr,
++ virt_to_phys(efx->stats_buffer.addr));
++
++ return 0;
++}
++
++void falcon_remove_port(struct efx_nic *efx)
++{
++ falcon_free_buffer(efx, &efx->stats_buffer);
++}
++
++/**************************************************************************
++ *
++ * Multicast filtering
++ *
++ **************************************************************************
++ */
++
++void falcon_set_multicast_hash(struct efx_nic *efx)
++{
++ union efx_multicast_hash *mc_hash = &efx->multicast_hash;
++
++ /* Broadcast packets go through the multicast hash filter.
++ * ether_crc_le() of the broadcast address is 0xbe2612ff
++ * so we always add bit 0xff to the mask.
++ */
++ set_bit_le(0xff, mc_hash->byte);
++
++ falcon_write(efx, &mc_hash->oword[0], MAC_MCAST_HASH_REG0_KER);
++ falcon_write(efx, &mc_hash->oword[1], MAC_MCAST_HASH_REG1_KER);
++}
++
++/**************************************************************************
++ *
++ * Device reset
++ *
++ **************************************************************************
++ */
++
++/* Resets NIC to known state. This routine must be called in process
++ * context and is allowed to sleep. */
++int falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
++{
++ struct falcon_nic_data *nic_data = efx->nic_data;
++ efx_oword_t glb_ctl_reg_ker;
++ int rc;
++
++ EFX_LOG(efx, "performing hardware reset (%d)\n", method);
++
++ /* Initiate device reset */
++ if (method == RESET_TYPE_WORLD) {
++ rc = pci_save_state(efx->pci_dev);
++ if (rc) {
++ EFX_ERR(efx, "failed to backup PCI state of primary "
++ "function prior to hardware reset\n");
++ goto fail1;
++ }
++ if (FALCON_IS_DUAL_FUNC(efx)) {
++ rc = pci_save_state(nic_data->pci_dev2);
++ if (rc) {
++ EFX_ERR(efx, "failed to backup PCI state of "
++ "secondary function prior to "
++ "hardware reset\n");
++ goto fail2;
++ }
++ }
++
++ EFX_POPULATE_OWORD_2(glb_ctl_reg_ker,
++ EXT_PHY_RST_DUR, 0x7,
++ SWRST, 1);
++ } else {
++ int reset_phy = (method == RESET_TYPE_INVISIBLE ?
++ EXCLUDE_FROM_RESET : 0);
++
++ EFX_POPULATE_OWORD_7(glb_ctl_reg_ker,
++ EXT_PHY_RST_CTL, reset_phy,
++ PCIE_CORE_RST_CTL, EXCLUDE_FROM_RESET,
++ PCIE_NSTCK_RST_CTL, EXCLUDE_FROM_RESET,
++ PCIE_SD_RST_CTL, EXCLUDE_FROM_RESET,
++ EE_RST_CTL, EXCLUDE_FROM_RESET,
++ EXT_PHY_RST_DUR, 0x7 /* 10ms */,
++ SWRST, 1);
++ }
++ falcon_write(efx, &glb_ctl_reg_ker, GLB_CTL_REG_KER);
++
++ EFX_LOG(efx, "waiting for hardware reset\n");
++ schedule_timeout_uninterruptible(HZ / 20);
++
++ /* Restore PCI configuration if needed */
++ if (method == RESET_TYPE_WORLD) {
++ if (FALCON_IS_DUAL_FUNC(efx)) {
++ rc = pci_restore_state(nic_data->pci_dev2);
++ if (rc) {
++ EFX_ERR(efx, "failed to restore PCI config for "
++ "the secondary function\n");
++ goto fail3;
++ }
++ }
++ rc = pci_restore_state(efx->pci_dev);
++ if (rc) {
++ EFX_ERR(efx, "failed to restore PCI config for the "
++ "primary function\n");
++ goto fail4;
++ }
++ EFX_LOG(efx, "successfully restored PCI config\n");
++ }
++
++ /* Assert that reset complete */
++ falcon_read(efx, &glb_ctl_reg_ker, GLB_CTL_REG_KER);
++ if (EFX_OWORD_FIELD(glb_ctl_reg_ker, SWRST) != 0) {
++ rc = -ETIMEDOUT;
++ EFX_ERR(efx, "timed out waiting for hardware reset\n");
++ goto fail5;
++ }
++ EFX_LOG(efx, "hardware reset complete\n");
++
++ return 0;
++
++ /* pci_save_state() and pci_restore_state() MUST be called in pairs */
++fail2:
++fail3:
++ pci_restore_state(efx->pci_dev);
++fail1:
++fail4:
++fail5:
++ return rc;
++}
++
++/* Zeroes out the SRAM contents. This routine must be called in
++ * process context and is allowed to sleep.
++ */
++static int falcon_reset_sram(struct efx_nic *efx)
++{
++ efx_oword_t srm_cfg_reg_ker, gpio_cfg_reg_ker;
++ int count;
++
++ /* Set the SRAM wake/sleep GPIO appropriately. */
++ falcon_read(efx, &gpio_cfg_reg_ker, GPIO_CTL_REG_KER);
++ EFX_SET_OWORD_FIELD(gpio_cfg_reg_ker, GPIO1_OEN, 1);
++ EFX_SET_OWORD_FIELD(gpio_cfg_reg_ker, GPIO1_OUT, 1);
++ falcon_write(efx, &gpio_cfg_reg_ker, GPIO_CTL_REG_KER);
++
++ /* Initiate SRAM reset */
++ EFX_POPULATE_OWORD_2(srm_cfg_reg_ker,
++ SRAM_OOB_BT_INIT_EN, 1,
++ SRM_NUM_BANKS_AND_BANK_SIZE, 0);
++ falcon_write(efx, &srm_cfg_reg_ker, SRM_CFG_REG_KER);
++
++ /* Wait for SRAM reset to complete */
++ count = 0;
++ do {
++ EFX_LOG(efx, "waiting for SRAM reset (attempt %d)...\n", count);
++
++ /* SRAM reset is slow; expect around 16ms */
++ schedule_timeout_uninterruptible(HZ / 50);
++
++ /* Check for reset complete */
++ falcon_read(efx, &srm_cfg_reg_ker, SRM_CFG_REG_KER);
++ if (!EFX_OWORD_FIELD(srm_cfg_reg_ker, SRAM_OOB_BT_INIT_EN)) {
++ EFX_LOG(efx, "SRAM reset complete\n");
+
- 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)
++ } while (++count < 20); /* wait upto 0.4 sec */
++
++ EFX_ERR(efx, "timed out waiting for SRAM reset\n");
++ return -ETIMEDOUT;
++}
++
++/* Extract non-volatile configuration */
++static int falcon_probe_nvconfig(struct efx_nic *efx)
+{
-+ 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;
++ struct falcon_nvconfig *nvconfig;
++ efx_oword_t nic_stat;
++ int device_id;
++ unsigned addr_len;
++ size_t offset, len;
++ int magic_num, struct_ver, board_rev;
++ int rc;
+
-+ 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;
++ /* Find the boot device. */
++ falcon_read(efx, &nic_stat, NIC_STAT_REG);
++ if (EFX_OWORD_FIELD(nic_stat, SF_PRST)) {
++ device_id = EE_SPI_FLASH;
++ addr_len = 3;
++ } else if (EFX_OWORD_FIELD(nic_stat, EE_PRST)) {
++ device_id = EE_SPI_EEPROM;
++ addr_len = 2;
++ } else {
++ return -ENODEV;
++ }
++
++ nvconfig = kmalloc(sizeof(*nvconfig), GFP_KERNEL);
++
++ /* Read the whole configuration structure into memory. */
++ for (offset = 0; offset < sizeof(*nvconfig); offset += len) {
++ len = min(sizeof(*nvconfig) - offset,
++ (size_t) FALCON_SPI_MAX_LEN);
++ rc = falcon_spi_read(efx, device_id, SPI_READ,
++ NVCONFIG_BASE + offset, addr_len,
++ (char *)nvconfig + offset, len);
++ if (rc)
++ goto out;
++ }
++
++ /* Read the MAC addresses */
++ memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN);
++
++ /* Read the board configuration. */
++ magic_num = le16_to_cpu(nvconfig->board_magic_num);
++ struct_ver = le16_to_cpu(nvconfig->board_struct_ver);
++
++ if (magic_num != NVCONFIG_BOARD_MAGIC_NUM || struct_ver < 2) {
++ EFX_ERR(efx, "Non volatile memory bad magic=%x ver=%x "
++ "therefore using defaults\n", magic_num, struct_ver);
++ efx->phy_type = PHY_TYPE_NONE;
++ efx->mii.phy_id = PHY_ADDR_INVALID;
++ board_rev = 0;
++ } else {
++ struct falcon_nvconfig_board_v2 *v2 = &nvconfig->board_v2;
++
++ efx->phy_type = v2->port0_phy_type;
++ efx->mii.phy_id = v2->port0_phy_addr;
++ board_rev = le16_to_cpu(v2->board_revision);
++ }
++
++ EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mii.phy_id);
++
++ efx_set_board_info(efx, board_rev);
++
++ out:
++ kfree(nvconfig);
++ return rc;
++}
++
++/* Probe the NIC variant (revision, ASIC vs FPGA, function count, port
++ * count, port speed). Set workaround and feature flags accordingly.
++ */
++static int falcon_probe_nic_variant(struct efx_nic *efx)
++{
++ efx_oword_t altera_build;
++
++ falcon_read(efx, &altera_build, ALTERA_BUILD_REG_KER);
++ if (EFX_OWORD_FIELD(altera_build, VER_ALL)) {
++ EFX_ERR(efx, "Falcon FPGA not supported\n");
++ return -ENODEV;
++ }
++
++ switch (FALCON_REV(efx)) {
++ case FALCON_REV_A0:
++ case 0xff:
++ EFX_ERR(efx, "Falcon rev A0 not supported\n");
++ return -ENODEV;
++
++ case FALCON_REV_A1:{
++ efx_oword_t nic_stat;
++
++ falcon_read(efx, &nic_stat, NIC_STAT_REG);
++
++ if (EFX_OWORD_FIELD(nic_stat, STRAP_PCIE) == 0) {
++ EFX_ERR(efx, "Falcon rev A1 PCI-X not supported\n");
++ return -ENODEV;
++ }
++ if (!EFX_OWORD_FIELD(nic_stat, STRAP_10G)) {
++ EFX_ERR(efx, "1G mode not supported\n");
++ return -ENODEV;
++ }
+ 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;
++ }
++
++ case FALCON_REV_B0:
+ break;
+
+ default:
-+ return -EINVAL;
++ EFX_ERR(efx, "Unknown Falcon rev %d\n", FALCON_REV(efx));
++ return -ENODEV;
+ }
-+ 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));
++ return 0;
++}
++
++int falcon_probe_nic(struct efx_nic *efx)
++{
++ struct falcon_nic_data *nic_data;
++ int rc;
++
++ /* Initialise I2C interface state */
++ efx->i2c.efx = efx;
++ efx->i2c.op = &falcon_i2c_bit_operations;
++ efx->i2c.sda = 1;
++ efx->i2c.scl = 1;
++
++ /* Allocate storage for hardware specific data */
++ nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL);
++ efx->nic_data = (void *) nic_data;
++
++ /* Determine number of ports etc. */
++ rc = falcon_probe_nic_variant(efx);
++ if (rc)
++ goto fail1;
++
++ /* Probe secondary function if expected */
++ if (FALCON_IS_DUAL_FUNC(efx)) {
++ struct pci_dev *dev = pci_dev_get(efx->pci_dev);
++
++ while ((dev = pci_get_device(EFX_VENDID_SFC, FALCON_A_S_DEVID,
++ dev))) {
++ if (dev->bus == efx->pci_dev->bus &&
++ dev->devfn == efx->pci_dev->devfn + 1) {
++ nic_data->pci_dev2 = dev;
++ break;
++ }
++ }
++ if (!nic_data->pci_dev2) {
++ EFX_ERR(efx, "failed to find secondary function\n");
++ rc = -ENODEV;
++ goto fail2;
++ }
+ }
+
-+ 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);
++ /* Now we can reset the NIC */
++ rc = falcon_reset_hw(efx, RESET_TYPE_ALL);
++ if (rc) {
++ EFX_ERR(efx, "failed to reset NIC\n");
++ goto fail3;
++ }
+
-+ /* Initialize all 4 lanes of the SERDES. */
-+ for (i = 0; i < 4; i++) {
-+ u32 rxtx_ctrl, glue0;
++ /* Allocate memory for INT_KER */
++ rc = falcon_alloc_buffer(efx, &efx->irq_status, sizeof(efx_oword_t));
++ if (rc)
++ goto fail4;
++ BUG_ON(efx->irq_status.dma_addr & 0x0f);
+
-+ err = esr_read_rxtx_ctrl(np, i, &rxtx_ctrl);
-+ if (err)
-+ return err;
-+ err = esr_read_glue0(np, i, &glue0);
-+ if (err)
-+ return err;
++ EFX_LOG(efx, "INT_KER at %llx (virt %p phys %lx)\n",
++ (unsigned long long)efx->irq_status.dma_addr,
++ efx->irq_status.addr, virt_to_phys(efx->irq_status.addr));
+
-+ rxtx_ctrl &= ~(ESR_RXTX_CTRL_VMUXLO);
-+ rxtx_ctrl |= (ESR_RXTX_CTRL_ENSTRETCH |
-+ (2 << ESR_RXTX_CTRL_VMUXLO_SHIFT));
++ /* Read in the non-volatile configuration */
++ rc = falcon_probe_nvconfig(efx);
++ if (rc)
++ goto fail5;
+
-+ 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));
++ return 0;
+
-+ err = esr_write_rxtx_ctrl(np, i, rxtx_ctrl);
-+ if (err)
-+ return err;
-+ err = esr_write_glue0(np, i, glue0);
-+ if (err)
-+ return err;
-+ }
++ fail5:
++ falcon_free_buffer(efx, &efx->irq_status);
++ fail4:
++ /* fall-thru */
++ fail3:
++ if (nic_data->pci_dev2) {
++ pci_dev_put(nic_data->pci_dev2);
++ nic_data->pci_dev2 = NULL;
++ }
++ fail2:
++ /* fall-thru */
++ fail1:
++ kfree(efx->nic_data);
++ return rc;
++}
+
++/* This call performs hardware-specific global initialisation, such as
++ * defining the descriptor cache sizes and number of RSS channels.
++ * It does not set up any buffers, descriptor rings or event queues.
++ */
++int falcon_init_nic(struct efx_nic *efx)
++{
++ struct falcon_nic_data *data;
++ efx_oword_t temp;
++ unsigned thresh;
++ int rc;
+
-+ sig = nr64(ESR_INT_SIGNALS);
-+ switch (np->port) {
-+ case 0:
-+ val = (ESR_INT_SRDY0_P0 | ESR_INT_DET0_P0);
-+ mask = val;
-+ break;
++ data = (struct falcon_nic_data *)efx->nic_data;
+
-+ case 1:
-+ val = (ESR_INT_SRDY0_P1 | ESR_INT_DET0_P1);
-+ mask = val;
-+ break;
++ /* Set up the address region register. This is only needed
++ * for the B0 FPGA, but since we are just pushing in the
++ * reset defaults this may as well be unconditional. */
++ EFX_POPULATE_OWORD_4(temp, ADR_REGION0, 0,
++ ADR_REGION1, (1 << 16),
++ ADR_REGION2, (2 << 16),
++ ADR_REGION3, (3 << 16));
++ falcon_write(efx, &temp, ADR_REGION_REG_KER);
++
++ /* Use on-chip SRAM */
++ falcon_read(efx, &temp, NIC_STAT_REG);
++ EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, 1);
++ falcon_write(efx, &temp, NIC_STAT_REG);
++
++ /* Set buffer table mode */
++ EFX_POPULATE_OWORD_1(temp, BUF_TBL_MODE, BUF_TBL_MODE_FULL);
++ falcon_write(efx, &temp, BUF_TBL_CFG_REG_KER);
+
-+ default:
-+ return -EINVAL;
++ rc = falcon_reset_sram(efx);
++ if (rc)
++ return rc;
++
++ /* Set positions of descriptor caches in SRAM. */
++ EFX_POPULATE_OWORD_1(temp, SRM_TX_DC_BASE_ADR, TX_DC_BASE / 8);
++ falcon_write(efx, &temp, SRM_TX_DC_CFG_REG_KER);
++ EFX_POPULATE_OWORD_1(temp, SRM_RX_DC_BASE_ADR, RX_DC_BASE / 8);
++ falcon_write(efx, &temp, SRM_RX_DC_CFG_REG_KER);
++
++ /* Set TX descriptor cache size. */
++ BUILD_BUG_ON(TX_DC_ENTRIES != (16 << TX_DC_ENTRIES_ORDER));
++ EFX_POPULATE_OWORD_1(temp, TX_DC_SIZE, TX_DC_ENTRIES_ORDER);
++ falcon_write(efx, &temp, TX_DC_CFG_REG_KER);
++
++ /* Set RX descriptor cache size. Set low watermark to size-8, as
++ * this allows most efficient prefetching.
++ */
++ BUILD_BUG_ON(RX_DC_ENTRIES != (16 << RX_DC_ENTRIES_ORDER));
++ EFX_POPULATE_OWORD_1(temp, RX_DC_SIZE, RX_DC_ENTRIES_ORDER);
++ falcon_write(efx, &temp, RX_DC_CFG_REG_KER);
++ EFX_POPULATE_OWORD_1(temp, RX_DC_PF_LWM, RX_DC_ENTRIES - 8);
++ falcon_write(efx, &temp, RX_DC_PF_WM_REG_KER);
++
++ /* Clear the parity enables on the TX data fifos as
++ * they produce false parity errors because of timing issues
++ */
++ if (EFX_WORKAROUND_5129(efx)) {
++ falcon_read(efx, &temp, SPARE_REG_KER);
++ EFX_SET_OWORD_FIELD(temp, MEM_PERR_EN_TX_DATA, 0);
++ falcon_write(efx, &temp, SPARE_REG_KER);
++ }
++
++ /* Enable all the genuinely fatal interrupts. (They are still
++ * masked by the overall interrupt mask, controlled by
++ * falcon_interrupts()).
++ *
++ * Note: All other fatal interrupts are enabled
++ */
++ EFX_POPULATE_OWORD_3(temp,
++ ILL_ADR_INT_KER_EN, 1,
++ RBUF_OWN_INT_KER_EN, 1,
++ TBUF_OWN_INT_KER_EN, 1);
++ EFX_INVERT_OWORD(temp);
++ falcon_write(efx, &temp, FATAL_INTR_REG_KER);
++
++ /* Set number of RSS queues for receive path. */
++ falcon_read(efx, &temp, RX_FILTER_CTL_REG);
++ if (FALCON_REV(efx) >= FALCON_REV_B0)
++ EFX_SET_OWORD_FIELD(temp, NUM_KER, 0);
++ else
++ EFX_SET_OWORD_FIELD(temp, NUM_KER, efx->rss_queues - 1);
++ if (EFX_WORKAROUND_7244(efx)) {
++ EFX_SET_OWORD_FIELD(temp, UDP_FULL_SRCH_LIMIT, 8);
++ EFX_SET_OWORD_FIELD(temp, UDP_WILD_SRCH_LIMIT, 8);
++ EFX_SET_OWORD_FIELD(temp, TCP_FULL_SRCH_LIMIT, 8);
++ EFX_SET_OWORD_FIELD(temp, TCP_WILD_SRCH_LIMIT, 8);
+ }
++ falcon_write(efx, &temp, RX_FILTER_CTL_REG);
+
-+ 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;
++ falcon_setup_rss_indir_table(efx);
++
++ /* Setup RX. Wait for descriptor is broken and must
++ * be disabled. RXDP recovery shouldn't be needed, but is.
++ */
++ falcon_read(efx, &temp, RX_SELF_RST_REG_KER);
++ EFX_SET_OWORD_FIELD(temp, RX_NODESC_WAIT_DIS, 1);
++ EFX_SET_OWORD_FIELD(temp, RX_RECOVERY_EN, 1);
++ if (EFX_WORKAROUND_5583(efx))
++ EFX_SET_OWORD_FIELD(temp, RX_ISCSI_DIS, 1);
++ falcon_write(efx, &temp, RX_SELF_RST_REG_KER);
++
++ /* Disable the ugly timer-based TX DMA backoff and allow TX DMA to be
++ * controlled by the RX FIFO fill level. Set arbitration to one pkt/Q.
++ */
++ falcon_read(efx, &temp, TX_CFG2_REG_KER);
++ EFX_SET_OWORD_FIELD(temp, TX_RX_SPACER, 0xfe);
++ EFX_SET_OWORD_FIELD(temp, TX_RX_SPACER_EN, 1);
++ EFX_SET_OWORD_FIELD(temp, TX_ONE_PKT_PER_Q, 1);
++ EFX_SET_OWORD_FIELD(temp, TX_CSR_PUSH_EN, 0);
++ EFX_SET_OWORD_FIELD(temp, TX_DIS_NON_IP_EV, 1);
++ /* Enable SW_EV to inherit in char driver - assume harmless here */
++ EFX_SET_OWORD_FIELD(temp, TX_SW_EV_EN, 1);
++ /* Prefetch threshold 2 => fetch when descriptor cache half empty */
++ EFX_SET_OWORD_FIELD(temp, TX_PREF_THRESHOLD, 2);
++ /* Squash TX of packets of 16 bytes or less */
++ if (FALCON_REV(efx) >= FALCON_REV_B0 && EFX_WORKAROUND_9141(efx))
++ EFX_SET_OWORD_FIELD(temp, TX_FLUSH_MIN_LEN_EN_B0, 1);
++ falcon_write(efx, &temp, TX_CFG2_REG_KER);
++
++ /* Do not enable TX_NO_EOP_DISC_EN, since it limits packets to 16
++ * descriptors (which is bad).
++ */
++ falcon_read(efx, &temp, TX_CFG_REG_KER);
++ EFX_SET_OWORD_FIELD(temp, TX_NO_EOP_DISC_EN, 0);
++ falcon_write(efx, &temp, TX_CFG_REG_KER);
++
++ /* RX config */
++ falcon_read(efx, &temp, RX_CFG_REG_KER);
++ EFX_SET_OWORD_FIELD_VER(efx, temp, RX_DESC_PUSH_EN, 0);
++ if (EFX_WORKAROUND_7575(efx))
++ EFX_SET_OWORD_FIELD_VER(efx, temp, RX_USR_BUF_SIZE,
++ (3 * 4096) / 32);
++ if (FALCON_REV(efx) >= FALCON_REV_B0)
++ EFX_SET_OWORD_FIELD(temp, RX_INGR_EN_B0, 1);
++
++ /* RX FIFO flow control thresholds */
++ thresh = ((rx_xon_thresh_bytes >= 0) ?
++ rx_xon_thresh_bytes : efx->type->rx_xon_thresh);
++ EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XON_MAC_TH, thresh / 256);
++ thresh = ((rx_xoff_thresh_bytes >= 0) ?
++ rx_xoff_thresh_bytes : efx->type->rx_xoff_thresh);
++ EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XOFF_MAC_TH, thresh / 256);
++ /* RX control FIFO thresholds [32 entries] */
++ EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XON_TX_TH, 25);
++ EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XOFF_TX_TH, 20);
++ falcon_write(efx, &temp, RX_CFG_REG_KER);
++
++ /* Set destination of both TX and RX Flush events */
++ if (FALCON_REV(efx) >= FALCON_REV_B0) {
++ EFX_POPULATE_OWORD_1(temp, FLS_EVQ_ID, 0);
++ falcon_write(efx, &temp, DP_CTRL_REG);
+ }
+
+ return 0;
+}
+
-+static int link_status_1g_serdes(struct niu *np, int *link_up_p)
++void falcon_remove_nic(struct efx_nic *efx)
++{
++ struct falcon_nic_data *nic_data = efx->nic_data;
++
++ falcon_free_buffer(efx, &efx->irq_status);
++
++ (void) falcon_reset_hw(efx, RESET_TYPE_ALL);
++
++ /* Release the second function after the reset */
++ if (nic_data->pci_dev2) {
++ pci_dev_put(nic_data->pci_dev2);
++ nic_data->pci_dev2 = NULL;
++ }
++
++ /* Tear down the private nic state */
++ kfree(efx->nic_data);
++ efx->nic_data = NULL;
++}
++
++void falcon_update_nic_stats(struct efx_nic *efx)
++{
++ efx_oword_t cnt;
++
++ falcon_read(efx, &cnt, RX_NODESC_DROP_REG_KER);
++ efx->n_rx_nodesc_drop_cnt += EFX_OWORD_FIELD(cnt, RX_NODESC_DROP_CNT);
++}
++
++/**************************************************************************
++ *
++ * Revision-dependent attributes used by efx.c
++ *
++ **************************************************************************
++ */
++
++struct efx_nic_type falcon_a_nic_type = {
++ .mem_bar = 2,
++ .mem_map_size = 0x20000,
++ .txd_ptr_tbl_base = TX_DESC_PTR_TBL_KER_A1,
++ .rxd_ptr_tbl_base = RX_DESC_PTR_TBL_KER_A1,
++ .buf_tbl_base = BUF_TBL_KER_A1,
++ .evq_ptr_tbl_base = EVQ_PTR_TBL_KER_A1,
++ .evq_rptr_tbl_base = EVQ_RPTR_REG_KER_A1,
++ .txd_ring_mask = FALCON_TXD_RING_MASK,
++ .rxd_ring_mask = FALCON_RXD_RING_MASK,
++ .evq_size = FALCON_EVQ_SIZE,
++ .max_dma_mask = FALCON_DMA_MASK,
++ .tx_dma_mask = FALCON_TX_DMA_MASK,
++ .bug5391_mask = 0xf,
++ .rx_xoff_thresh = 2048,
++ .rx_xon_thresh = 512,
++ .rx_buffer_padding = 0x24,
++ .max_interrupt_mode = EFX_INT_MODE_MSI,
++ .phys_addr_channels = 4,
++};
++
++struct efx_nic_type falcon_b_nic_type = {
++ .mem_bar = 2,
++ /* Map everything up to and including the RSS indirection
++ * table. Don't map MSI-X table, MSI-X PBA since Linux
++ * requires that they not be mapped. */
++ .mem_map_size = RX_RSS_INDIR_TBL_B0 + 0x800,
++ .txd_ptr_tbl_base = TX_DESC_PTR_TBL_KER_B0,
++ .rxd_ptr_tbl_base = RX_DESC_PTR_TBL_KER_B0,
++ .buf_tbl_base = BUF_TBL_KER_B0,
++ .evq_ptr_tbl_base = EVQ_PTR_TBL_KER_B0,
++ .evq_rptr_tbl_base = EVQ_RPTR_REG_KER_B0,
++ .txd_ring_mask = FALCON_TXD_RING_MASK,
++ .rxd_ring_mask = FALCON_RXD_RING_MASK,
++ .evq_size = FALCON_EVQ_SIZE,
++ .max_dma_mask = FALCON_DMA_MASK,
++ .tx_dma_mask = FALCON_TX_DMA_MASK,
++ .bug5391_mask = 0,
++ .rx_xoff_thresh = 54272, /* ~80Kb - 3*max MTU */
++ .rx_xon_thresh = 27648, /* ~3*max MTU */
++ .rx_buffer_padding = 0,
++ .max_interrupt_mode = EFX_INT_MODE_MSIX,
++ .phys_addr_channels = 32, /* Hardware limit is 64, but the legacy
++ * interrupt handler only supports 32
++ * channels */
++};
++
+diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h
+new file mode 100644
+index 0000000..6117403
+--- /dev/null
++++ b/drivers/net/sfc/falcon.h
+@@ -0,0 +1,130 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005-2006 Fen Systems Ltd.
++ * Copyright 2006-2008 Solarflare Communications 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, incorporated herein by reference.
++ */
++
++#ifndef EFX_FALCON_H
++#define EFX_FALCON_H
++
++#include "net_driver.h"
++
++/*
++ * Falcon hardware control
++ */
++
++enum falcon_revision {
++ FALCON_REV_A0 = 0,
++ FALCON_REV_A1 = 1,
++ FALCON_REV_B0 = 2,
++};
++
++#define FALCON_REV(efx) ((efx)->pci_dev->revision)
++
++extern struct efx_nic_type falcon_a_nic_type;
++extern struct efx_nic_type falcon_b_nic_type;
++
++/**************************************************************************
++ *
++ * Externs
++ *
++ **************************************************************************
++ */
++
++/* TX data path */
++extern int falcon_probe_tx(struct efx_tx_queue *tx_queue);
++extern int falcon_init_tx(struct efx_tx_queue *tx_queue);
++extern void falcon_fini_tx(struct efx_tx_queue *tx_queue);
++extern void falcon_remove_tx(struct efx_tx_queue *tx_queue);
++extern void falcon_push_buffers(struct efx_tx_queue *tx_queue);
++
++/* RX data path */
++extern int falcon_probe_rx(struct efx_rx_queue *rx_queue);
++extern int falcon_init_rx(struct efx_rx_queue *rx_queue);
++extern void falcon_fini_rx(struct efx_rx_queue *rx_queue);
++extern void falcon_remove_rx(struct efx_rx_queue *rx_queue);
++extern void falcon_notify_rx_desc(struct efx_rx_queue *rx_queue);
++
++/* Event data path */
++extern int falcon_probe_eventq(struct efx_channel *channel);
++extern int falcon_init_eventq(struct efx_channel *channel);
++extern void falcon_fini_eventq(struct efx_channel *channel);
++extern void falcon_remove_eventq(struct efx_channel *channel);
++extern int falcon_process_eventq(struct efx_channel *channel, int *rx_quota);
++extern void falcon_eventq_read_ack(struct efx_channel *channel);
++
++/* Ports */
++extern int falcon_probe_port(struct efx_nic *efx);
++extern void falcon_remove_port(struct efx_nic *efx);
++
++/* MAC/PHY */
++extern int falcon_xaui_link_ok(struct efx_nic *efx);
++extern int falcon_dma_stats(struct efx_nic *efx,
++ unsigned int done_offset);
++extern void falcon_drain_tx_fifo(struct efx_nic *efx);
++extern void falcon_deconfigure_mac_wrapper(struct efx_nic *efx);
++extern void falcon_reconfigure_mac_wrapper(struct efx_nic *efx);
++
++/* Interrupts and test events */
++extern int falcon_init_interrupt(struct efx_nic *efx);
++extern void falcon_enable_interrupts(struct efx_nic *efx);
++extern void falcon_generate_test_event(struct efx_channel *channel,
++ unsigned int magic);
++extern void falcon_generate_interrupt(struct efx_nic *efx);
++extern void falcon_set_int_moderation(struct efx_channel *channel);
++extern void falcon_disable_interrupts(struct efx_nic *efx);
++extern void falcon_fini_interrupt(struct efx_nic *efx);
++
++/* Global Resources */
++extern int falcon_probe_nic(struct efx_nic *efx);
++extern int falcon_probe_resources(struct efx_nic *efx);
++extern int falcon_init_nic(struct efx_nic *efx);
++extern int falcon_reset_hw(struct efx_nic *efx, enum reset_type method);
++extern void falcon_remove_resources(struct efx_nic *efx);
++extern void falcon_remove_nic(struct efx_nic *efx);
++extern void falcon_update_nic_stats(struct efx_nic *efx);
++extern void falcon_set_multicast_hash(struct efx_nic *efx);
++extern int falcon_reset_xaui(struct efx_nic *efx);
++
++/**************************************************************************
++ *
++ * Falcon MAC stats
++ *
++ **************************************************************************
++ */
++
++#define FALCON_STAT_OFFSET(falcon_stat) EFX_VAL(falcon_stat, offset)
++#define FALCON_STAT_WIDTH(falcon_stat) EFX_VAL(falcon_stat, WIDTH)
++
++/* Retrieve statistic from statistics block */
++#define FALCON_STAT(efx, falcon_stat, efx_stat) do { \
++ if (FALCON_STAT_WIDTH(falcon_stat) == 16) \
++ (efx)->mac_stats.efx_stat += le16_to_cpu( \
++ *((__force __le16 *) \
++ (efx->stats_buffer.addr + \
++ FALCON_STAT_OFFSET(falcon_stat)))); \
++ else if (FALCON_STAT_WIDTH(falcon_stat) == 32) \
++ (efx)->mac_stats.efx_stat += le32_to_cpu( \
++ *((__force __le32 *) \
++ (efx->stats_buffer.addr + \
++ FALCON_STAT_OFFSET(falcon_stat)))); \
++ else \
++ (efx)->mac_stats.efx_stat += le64_to_cpu( \
++ *((__force __le64 *) \
++ (efx->stats_buffer.addr + \
++ FALCON_STAT_OFFSET(falcon_stat)))); \
++ } while (0)
++
++#define FALCON_MAC_STATS_SIZE 0x100
++
++#define MAC_DATA_LBN 0
++#define MAC_DATA_WIDTH 32
++
++extern void falcon_generate_event(struct efx_channel *channel,
++ efx_qword_t *event);
++
++#endif /* EFX_FALCON_H */
+diff --git a/drivers/net/sfc/falcon_hwdefs.h b/drivers/net/sfc/falcon_hwdefs.h
+new file mode 100644
+index 0000000..0485a63
+--- /dev/null
++++ b/drivers/net/sfc/falcon_hwdefs.h
+@@ -0,0 +1,1135 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005-2006 Fen Systems Ltd.
++ * Copyright 2006-2008 Solarflare Communications 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, incorporated herein by reference.
++ */
++
++#ifndef EFX_FALCON_HWDEFS_H
++#define EFX_FALCON_HWDEFS_H
++
++/*
++ * Falcon hardware value definitions.
++ * Falcon is the internal codename for the SFC4000 controller that is
++ * present in SFE400X evaluation boards
++ */
++
++/**************************************************************************
++ *
++ * Falcon registers
++ *
++ **************************************************************************
++ */
++
++/* Address region register */
++#define ADR_REGION_REG_KER 0x00
++#define ADR_REGION0_LBN 0
++#define ADR_REGION0_WIDTH 18
++#define ADR_REGION1_LBN 32
++#define ADR_REGION1_WIDTH 18
++#define ADR_REGION2_LBN 64
++#define ADR_REGION2_WIDTH 18
++#define ADR_REGION3_LBN 96
++#define ADR_REGION3_WIDTH 18
++
++/* Interrupt enable register */
++#define INT_EN_REG_KER 0x0010
++#define KER_INT_KER_LBN 3
++#define KER_INT_KER_WIDTH 1
++#define DRV_INT_EN_KER_LBN 0
++#define DRV_INT_EN_KER_WIDTH 1
++
++/* Interrupt status address register */
++#define INT_ADR_REG_KER 0x0030
++#define NORM_INT_VEC_DIS_KER_LBN 64
++#define NORM_INT_VEC_DIS_KER_WIDTH 1
++#define INT_ADR_KER_LBN 0
++#define INT_ADR_KER_WIDTH EFX_DMA_TYPE_WIDTH(64) /* not 46 for this one */
++
++/* Interrupt status register (B0 only) */
++#define INT_ISR0_B0 0x90
++#define INT_ISR1_B0 0xA0
++
++/* Interrupt acknowledge register (A0/A1 only) */
++#define INT_ACK_REG_KER_A1 0x0050
++#define INT_ACK_DUMMY_DATA_LBN 0
++#define INT_ACK_DUMMY_DATA_WIDTH 32
++
++/* Interrupt acknowledge work-around register (A0/A1 only )*/
++#define WORK_AROUND_BROKEN_PCI_READS_REG_KER_A1 0x0070
++
++/* SPI host command register */
++#define EE_SPI_HCMD_REG_KER 0x0100
++#define EE_SPI_HCMD_CMD_EN_LBN 31
++#define EE_SPI_HCMD_CMD_EN_WIDTH 1
++#define EE_WR_TIMER_ACTIVE_LBN 28
++#define EE_WR_TIMER_ACTIVE_WIDTH 1
++#define EE_SPI_HCMD_SF_SEL_LBN 24
++#define EE_SPI_HCMD_SF_SEL_WIDTH 1
++#define EE_SPI_EEPROM 0
++#define EE_SPI_FLASH 1
++#define EE_SPI_HCMD_DABCNT_LBN 16
++#define EE_SPI_HCMD_DABCNT_WIDTH 5
++#define EE_SPI_HCMD_READ_LBN 15
++#define EE_SPI_HCMD_READ_WIDTH 1
++#define EE_SPI_READ 1
++#define EE_SPI_WRITE 0
++#define EE_SPI_HCMD_DUBCNT_LBN 12
++#define EE_SPI_HCMD_DUBCNT_WIDTH 2
++#define EE_SPI_HCMD_ADBCNT_LBN 8
++#define EE_SPI_HCMD_ADBCNT_WIDTH 2
++#define EE_SPI_HCMD_ENC_LBN 0
++#define EE_SPI_HCMD_ENC_WIDTH 8
++
++/* SPI host address register */
++#define EE_SPI_HADR_REG_KER 0x0110
++#define EE_SPI_HADR_ADR_LBN 0
++#define EE_SPI_HADR_ADR_WIDTH 24
++
++/* SPI host data register */
++#define EE_SPI_HDATA_REG_KER 0x0120
++
++/* PCIE CORE ACCESS REG */
++#define PCIE_CORE_ADDR_PCIE_DEVICE_CTRL_STAT 0x68
++#define PCIE_CORE_ADDR_PCIE_LINK_CTRL_STAT 0x70
++#define PCIE_CORE_ADDR_ACK_RPL_TIMER 0x700
++#define PCIE_CORE_ADDR_ACK_FREQ 0x70C
++
++/* NIC status register */
++#define NIC_STAT_REG 0x0200
++#define ONCHIP_SRAM_LBN 16
++#define ONCHIP_SRAM_WIDTH 1
++#define SF_PRST_LBN 9
++#define SF_PRST_WIDTH 1
++#define EE_PRST_LBN 8
++#define EE_PRST_WIDTH 1
++/* See pic_mode_t for decoding of this field */
++/* These bit definitions are extrapolated from the list of numerical
++ * values for STRAP_PINS.
++ */
++#define STRAP_10G_LBN 2
++#define STRAP_10G_WIDTH 1
++#define STRAP_PCIE_LBN 0
++#define STRAP_PCIE_WIDTH 1
++
++/* GPIO control register */
++#define GPIO_CTL_REG_KER 0x0210
++#define GPIO_OUTPUTS_LBN (16)
++#define GPIO_OUTPUTS_WIDTH (4)
++#define GPIO_INPUTS_LBN (8)
++#define GPIO_DIRECTION_LBN (24)
++#define GPIO_DIRECTION_WIDTH (4)
++#define GPIO_DIRECTION_OUT (1)
++#define GPIO_SRAM_SLEEP (1 << 1)
++
++#define GPIO3_OEN_LBN (GPIO_DIRECTION_LBN + 3)
++#define GPIO3_OEN_WIDTH 1
++#define GPIO2_OEN_LBN (GPIO_DIRECTION_LBN + 2)
++#define GPIO2_OEN_WIDTH 1
++#define GPIO1_OEN_LBN (GPIO_DIRECTION_LBN + 1)
++#define GPIO1_OEN_WIDTH 1
++#define GPIO0_OEN_LBN (GPIO_DIRECTION_LBN + 0)
++#define GPIO0_OEN_WIDTH 1
++
++#define GPIO3_OUT_LBN (GPIO_OUTPUTS_LBN + 3)
++#define GPIO3_OUT_WIDTH 1
++#define GPIO2_OUT_LBN (GPIO_OUTPUTS_LBN + 2)
++#define GPIO2_OUT_WIDTH 1
++#define GPIO1_OUT_LBN (GPIO_OUTPUTS_LBN + 1)
++#define GPIO1_OUT_WIDTH 1
++#define GPIO0_OUT_LBN (GPIO_OUTPUTS_LBN + 0)
++#define GPIO0_OUT_WIDTH 1
++
++#define GPIO3_IN_LBN (GPIO_INPUTS_LBN + 3)
++#define GPIO3_IN_WIDTH 1
++#define GPIO2_IN_WIDTH 1
++#define GPIO1_IN_WIDTH 1
++#define GPIO0_IN_LBN (GPIO_INPUTS_LBN + 0)
++#define GPIO0_IN_WIDTH 1
++
++/* Global control register */
++#define GLB_CTL_REG_KER 0x0220
++#define EXT_PHY_RST_CTL_LBN 63
++#define EXT_PHY_RST_CTL_WIDTH 1
++#define PCIE_SD_RST_CTL_LBN 61
++#define PCIE_SD_RST_CTL_WIDTH 1
++
++#define PCIE_NSTCK_RST_CTL_LBN 58
++#define PCIE_NSTCK_RST_CTL_WIDTH 1
++#define PCIE_CORE_RST_CTL_LBN 57
++#define PCIE_CORE_RST_CTL_WIDTH 1
++#define EE_RST_CTL_LBN 49
++#define EE_RST_CTL_WIDTH 1
++#define RST_XGRX_LBN 24
++#define RST_XGRX_WIDTH 1
++#define RST_XGTX_LBN 23
++#define RST_XGTX_WIDTH 1
++#define RST_EM_LBN 22
++#define RST_EM_WIDTH 1
++#define EXT_PHY_RST_DUR_LBN 1
++#define EXT_PHY_RST_DUR_WIDTH 3
++#define SWRST_LBN 0
++#define SWRST_WIDTH 1
++#define INCLUDE_IN_RESET 0
++#define EXCLUDE_FROM_RESET 1
++
++/* Fatal interrupt register */
++#define FATAL_INTR_REG_KER 0x0230
++#define RBUF_OWN_INT_KER_EN_LBN 39
++#define RBUF_OWN_INT_KER_EN_WIDTH 1
++#define TBUF_OWN_INT_KER_EN_LBN 38
++#define TBUF_OWN_INT_KER_EN_WIDTH 1
++#define ILL_ADR_INT_KER_EN_LBN 33
++#define ILL_ADR_INT_KER_EN_WIDTH 1
++#define MEM_PERR_INT_KER_LBN 8
++#define MEM_PERR_INT_KER_WIDTH 1
++#define INT_KER_ERROR_LBN 0
++#define INT_KER_ERROR_WIDTH 12
++
++#define DP_CTRL_REG 0x250
++#define FLS_EVQ_ID_LBN 0
++#define FLS_EVQ_ID_WIDTH 11
++
++#define MEM_STAT_REG_KER 0x260
++
++/* Debug probe register */
++#define DEBUG_BLK_SEL_MISC 7
++#define DEBUG_BLK_SEL_SERDES 6
++#define DEBUG_BLK_SEL_EM 5
++#define DEBUG_BLK_SEL_SR 4
++#define DEBUG_BLK_SEL_EV 3
++#define DEBUG_BLK_SEL_RX 2
++#define DEBUG_BLK_SEL_TX 1
++#define DEBUG_BLK_SEL_BIU 0
++
++/* FPGA build version */
++#define ALTERA_BUILD_REG_KER 0x0300
++#define VER_ALL_LBN 0
++#define VER_ALL_WIDTH 32
++
++/* Spare EEPROM bits register (flash 0x390) */
++#define SPARE_REG_KER 0x310
++#define MEM_PERR_EN_TX_DATA_LBN 72
++#define MEM_PERR_EN_TX_DATA_WIDTH 2
++
++/* Timer table for kernel access */
++#define TIMER_CMD_REG_KER 0x420
++#define TIMER_MODE_LBN 12
++#define TIMER_MODE_WIDTH 2
++#define TIMER_MODE_DIS 0
++#define TIMER_MODE_INT_HLDOFF 2
++#define TIMER_VAL_LBN 0
++#define TIMER_VAL_WIDTH 12
++
++/* Driver generated event register */
++#define DRV_EV_REG_KER 0x440
++#define DRV_EV_QID_LBN 64
++#define DRV_EV_QID_WIDTH 12
++#define DRV_EV_DATA_LBN 0
++#define DRV_EV_DATA_WIDTH 64
++
++/* Buffer table configuration register */
++#define BUF_TBL_CFG_REG_KER 0x600
++#define BUF_TBL_MODE_LBN 3
++#define BUF_TBL_MODE_WIDTH 1
++#define BUF_TBL_MODE_HALF 0
++#define BUF_TBL_MODE_FULL 1
++
++/* SRAM receive descriptor cache configuration register */
++#define SRM_RX_DC_CFG_REG_KER 0x610
++#define SRM_RX_DC_BASE_ADR_LBN 0
++#define SRM_RX_DC_BASE_ADR_WIDTH 21
++
++/* SRAM transmit descriptor cache configuration register */
++#define SRM_TX_DC_CFG_REG_KER 0x620
++#define SRM_TX_DC_BASE_ADR_LBN 0
++#define SRM_TX_DC_BASE_ADR_WIDTH 21
++
++/* SRAM configuration register */
++#define SRM_CFG_REG_KER 0x630
++#define SRAM_OOB_BT_INIT_EN_LBN 3
++#define SRAM_OOB_BT_INIT_EN_WIDTH 1
++#define SRM_NUM_BANKS_AND_BANK_SIZE_LBN 0
++#define SRM_NUM_BANKS_AND_BANK_SIZE_WIDTH 3
++#define SRM_NB_BSZ_1BANKS_2M 0
++#define SRM_NB_BSZ_1BANKS_4M 1
++#define SRM_NB_BSZ_1BANKS_8M 2
++#define SRM_NB_BSZ_DEFAULT 3 /* char driver will set the default */
++#define SRM_NB_BSZ_2BANKS_4M 4
++#define SRM_NB_BSZ_2BANKS_8M 5
++#define SRM_NB_BSZ_2BANKS_16M 6
++#define SRM_NB_BSZ_RESERVED 7
++
++/* Special buffer table update register */
++#define BUF_TBL_UPD_REG_KER 0x0650
++#define BUF_UPD_CMD_LBN 63
++#define BUF_UPD_CMD_WIDTH 1
++#define BUF_CLR_CMD_LBN 62
++#define BUF_CLR_CMD_WIDTH 1
++#define BUF_CLR_END_ID_LBN 32
++#define BUF_CLR_END_ID_WIDTH 20
++#define BUF_CLR_START_ID_LBN 0
++#define BUF_CLR_START_ID_WIDTH 20
++
++/* Receive configuration register */
++#define RX_CFG_REG_KER 0x800
++
++/* B0 */
++#define RX_INGR_EN_B0_LBN 47
++#define RX_INGR_EN_B0_WIDTH 1
++#define RX_DESC_PUSH_EN_B0_LBN 43
++#define RX_DESC_PUSH_EN_B0_WIDTH 1
++#define RX_XON_TX_TH_B0_LBN 33
++#define RX_XON_TX_TH_B0_WIDTH 5
++#define RX_XOFF_TX_TH_B0_LBN 28
++#define RX_XOFF_TX_TH_B0_WIDTH 5
++#define RX_USR_BUF_SIZE_B0_LBN 19
++#define RX_USR_BUF_SIZE_B0_WIDTH 9
++#define RX_XON_MAC_TH_B0_LBN 10
++#define RX_XON_MAC_TH_B0_WIDTH 9
++#define RX_XOFF_MAC_TH_B0_LBN 1
++#define RX_XOFF_MAC_TH_B0_WIDTH 9
++#define RX_XOFF_MAC_EN_B0_LBN 0
++#define RX_XOFF_MAC_EN_B0_WIDTH 1
++
++/* A1 */
++#define RX_DESC_PUSH_EN_A1_LBN 35
++#define RX_DESC_PUSH_EN_A1_WIDTH 1
++#define RX_XON_TX_TH_A1_LBN 25
++#define RX_XON_TX_TH_A1_WIDTH 5
++#define RX_XOFF_TX_TH_A1_LBN 20
++#define RX_XOFF_TX_TH_A1_WIDTH 5
++#define RX_USR_BUF_SIZE_A1_LBN 11
++#define RX_USR_BUF_SIZE_A1_WIDTH 9
++#define RX_XON_MAC_TH_A1_LBN 6
++#define RX_XON_MAC_TH_A1_WIDTH 5
++#define RX_XOFF_MAC_TH_A1_LBN 1
++#define RX_XOFF_MAC_TH_A1_WIDTH 5
++#define RX_XOFF_MAC_EN_A1_LBN 0
++#define RX_XOFF_MAC_EN_A1_WIDTH 1
++
++/* Receive filter control register */
++#define RX_FILTER_CTL_REG 0x810
++#define UDP_FULL_SRCH_LIMIT_LBN 32
++#define UDP_FULL_SRCH_LIMIT_WIDTH 8
++#define NUM_KER_LBN 24
++#define NUM_KER_WIDTH 2
++#define UDP_WILD_SRCH_LIMIT_LBN 16
++#define UDP_WILD_SRCH_LIMIT_WIDTH 8
++#define TCP_WILD_SRCH_LIMIT_LBN 8
++#define TCP_WILD_SRCH_LIMIT_WIDTH 8
++#define TCP_FULL_SRCH_LIMIT_LBN 0
++#define TCP_FULL_SRCH_LIMIT_WIDTH 8
++
++/* RX queue flush register */
++#define RX_FLUSH_DESCQ_REG_KER 0x0820
++#define RX_FLUSH_DESCQ_CMD_LBN 24
++#define RX_FLUSH_DESCQ_CMD_WIDTH 1
++#define RX_FLUSH_DESCQ_LBN 0
++#define RX_FLUSH_DESCQ_WIDTH 12
++
++/* Receive descriptor update register */
++#define RX_DESC_UPD_REG_KER_DWORD (0x830 + 12)
++#define RX_DESC_WPTR_DWORD_LBN 0
++#define RX_DESC_WPTR_DWORD_WIDTH 12
++
++/* Receive descriptor cache configuration register */
++#define RX_DC_CFG_REG_KER 0x840
++#define RX_DC_SIZE_LBN 0
++#define RX_DC_SIZE_WIDTH 2
++
++#define RX_DC_PF_WM_REG_KER 0x850
++#define RX_DC_PF_LWM_LBN 0
++#define RX_DC_PF_LWM_WIDTH 6
++
++/* RX no descriptor drop counter */
++#define RX_NODESC_DROP_REG_KER 0x880
++#define RX_NODESC_DROP_CNT_LBN 0
++#define RX_NODESC_DROP_CNT_WIDTH 16
++
++/* RX black magic register */
++#define RX_SELF_RST_REG_KER 0x890
++#define RX_ISCSI_DIS_LBN 17
++#define RX_ISCSI_DIS_WIDTH 1
++#define RX_NODESC_WAIT_DIS_LBN 9
++#define RX_NODESC_WAIT_DIS_WIDTH 1
++#define RX_RECOVERY_EN_LBN 8
++#define RX_RECOVERY_EN_WIDTH 1
++
++/* TX queue flush register */
++#define TX_FLUSH_DESCQ_REG_KER 0x0a00
++#define TX_FLUSH_DESCQ_CMD_LBN 12
++#define TX_FLUSH_DESCQ_CMD_WIDTH 1
++#define TX_FLUSH_DESCQ_LBN 0
++#define TX_FLUSH_DESCQ_WIDTH 12
++
++/* Transmit descriptor update register */
++#define TX_DESC_UPD_REG_KER_DWORD (0xa10 + 12)
++#define TX_DESC_WPTR_DWORD_LBN 0
++#define TX_DESC_WPTR_DWORD_WIDTH 12
++
++/* Transmit descriptor cache configuration register */
++#define TX_DC_CFG_REG_KER 0xa20
++#define TX_DC_SIZE_LBN 0
++#define TX_DC_SIZE_WIDTH 2
++
++/* Transmit checksum configuration register (A0/A1 only) */
++#define TX_CHKSM_CFG_REG_KER_A1 0xa30
++
++/* Transmit configuration register */
++#define TX_CFG_REG_KER 0xa50
++#define TX_NO_EOP_DISC_EN_LBN 5
++#define TX_NO_EOP_DISC_EN_WIDTH 1
++
++/* Transmit configuration register 2 */
++#define TX_CFG2_REG_KER 0xa80
++#define TX_CSR_PUSH_EN_LBN 89
++#define TX_CSR_PUSH_EN_WIDTH 1
++#define TX_RX_SPACER_LBN 64
++#define TX_RX_SPACER_WIDTH 8
++#define TX_SW_EV_EN_LBN 59
++#define TX_SW_EV_EN_WIDTH 1
++#define TX_RX_SPACER_EN_LBN 57
++#define TX_RX_SPACER_EN_WIDTH 1
++#define TX_PREF_THRESHOLD_LBN 19
++#define TX_PREF_THRESHOLD_WIDTH 2
++#define TX_ONE_PKT_PER_Q_LBN 18
++#define TX_ONE_PKT_PER_Q_WIDTH 1
++#define TX_DIS_NON_IP_EV_LBN 17
++#define TX_DIS_NON_IP_EV_WIDTH 1
++#define TX_FLUSH_MIN_LEN_EN_B0_LBN 7
++#define TX_FLUSH_MIN_LEN_EN_B0_WIDTH 1
++
++/* PHY management transmit data register */
++#define MD_TXD_REG_KER 0xc00
++#define MD_TXD_LBN 0
++#define MD_TXD_WIDTH 16
++
++/* PHY management receive data register */
++#define MD_RXD_REG_KER 0xc10
++#define MD_RXD_LBN 0
++#define MD_RXD_WIDTH 16
++
++/* PHY management configuration & status register */
++#define MD_CS_REG_KER 0xc20
++#define MD_GC_LBN 4
++#define MD_GC_WIDTH 1
++#define MD_RIC_LBN 2
++#define MD_RIC_WIDTH 1
++#define MD_RDC_LBN 1
++#define MD_RDC_WIDTH 1
++#define MD_WRC_LBN 0
++#define MD_WRC_WIDTH 1
++
++/* PHY management PHY address register */
++#define MD_PHY_ADR_REG_KER 0xc30
++#define MD_PHY_ADR_LBN 0
++#define MD_PHY_ADR_WIDTH 16
++
++/* PHY management ID register */
++#define MD_ID_REG_KER 0xc40
++#define MD_PRT_ADR_LBN 11
++#define MD_PRT_ADR_WIDTH 5
++#define MD_DEV_ADR_LBN 6
++#define MD_DEV_ADR_WIDTH 5
++/* Used for writing both at once */
++#define MD_PRT_DEV_ADR_LBN 6
++#define MD_PRT_DEV_ADR_WIDTH 10
++
++/* PHY management status & mask register (DWORD read only) */
++#define MD_STAT_REG_KER 0xc50
++#define MD_BSERR_LBN 2
++#define MD_BSERR_WIDTH 1
++#define MD_LNFL_LBN 1
++#define MD_LNFL_WIDTH 1
++#define MD_BSY_LBN 0
++#define MD_BSY_WIDTH 1
++
++/* Port 0 and 1 MAC stats registers */
++#define MAC0_STAT_DMA_REG_KER 0xc60
++#define MAC_STAT_DMA_CMD_LBN 48
++#define MAC_STAT_DMA_CMD_WIDTH 1
++#define MAC_STAT_DMA_ADR_LBN 0
++#define MAC_STAT_DMA_ADR_WIDTH EFX_DMA_TYPE_WIDTH(46)
++
++/* Port 0 and 1 MAC control registers */
++#define MAC0_CTRL_REG_KER 0xc80
++#define MAC_XOFF_VAL_LBN 16
++#define MAC_XOFF_VAL_WIDTH 16
++#define TXFIFO_DRAIN_EN_B0_LBN 7
++#define TXFIFO_DRAIN_EN_B0_WIDTH 1
++#define MAC_BCAD_ACPT_LBN 4
++#define MAC_BCAD_ACPT_WIDTH 1
++#define MAC_UC_PROM_LBN 3
++#define MAC_UC_PROM_WIDTH 1
++#define MAC_LINK_STATUS_LBN 2
++#define MAC_LINK_STATUS_WIDTH 1
++#define MAC_SPEED_LBN 0
++#define MAC_SPEED_WIDTH 2
++
++/* 10G XAUI XGXS default values */
++#define XX_TXDRV_DEQ_DEFAULT 0xe /* deq=.6 */
++#define XX_TXDRV_DTX_DEFAULT 0x5 /* 1.25 */
++#define XX_SD_CTL_DRV_DEFAULT 0 /* 20mA */
++
++/* Multicast address hash table */
++#define MAC_MCAST_HASH_REG0_KER 0xca0
++#define MAC_MCAST_HASH_REG1_KER 0xcb0
++
++/* GMAC registers */
++#define FALCON_GMAC_REGBANK 0xe00
++#define FALCON_GMAC_REGBANK_SIZE 0x200
++#define FALCON_GMAC_REG_SIZE 0x10
++
++/* XMAC registers */
++#define FALCON_XMAC_REGBANK 0x1200
++#define FALCON_XMAC_REGBANK_SIZE 0x200
++#define FALCON_XMAC_REG_SIZE 0x10
++
++/* XGMAC address register low */
++#define XM_ADR_LO_REG_MAC 0x00
++#define XM_ADR_3_LBN 24
++#define XM_ADR_3_WIDTH 8
++#define XM_ADR_2_LBN 16
++#define XM_ADR_2_WIDTH 8
++#define XM_ADR_1_LBN 8
++#define XM_ADR_1_WIDTH 8
++#define XM_ADR_0_LBN 0
++#define XM_ADR_0_WIDTH 8
++
++/* XGMAC address register high */
++#define XM_ADR_HI_REG_MAC 0x01
++#define XM_ADR_5_LBN 8
++#define XM_ADR_5_WIDTH 8
++#define XM_ADR_4_LBN 0
++#define XM_ADR_4_WIDTH 8
++
++/* XGMAC global configuration */
++#define XM_GLB_CFG_REG_MAC 0x02
++#define XM_RX_STAT_EN_LBN 11
++#define XM_RX_STAT_EN_WIDTH 1
++#define XM_TX_STAT_EN_LBN 10
++#define XM_TX_STAT_EN_WIDTH 1
++#define XM_RX_JUMBO_MODE_LBN 6
++#define XM_RX_JUMBO_MODE_WIDTH 1
++#define XM_INTCLR_MODE_LBN 3
++#define XM_INTCLR_MODE_WIDTH 1
++#define XM_CORE_RST_LBN 0
++#define XM_CORE_RST_WIDTH 1
++
++/* XGMAC transmit configuration */
++#define XM_TX_CFG_REG_MAC 0x03
++#define XM_IPG_LBN 16
++#define XM_IPG_WIDTH 4
++#define XM_FCNTL_LBN 10
++#define XM_FCNTL_WIDTH 1
++#define XM_TXCRC_LBN 8
++#define XM_TXCRC_WIDTH 1
++#define XM_AUTO_PAD_LBN 5
++#define XM_AUTO_PAD_WIDTH 1
++#define XM_TX_PRMBL_LBN 2
++#define XM_TX_PRMBL_WIDTH 1
++#define XM_TXEN_LBN 1
++#define XM_TXEN_WIDTH 1
++
++/* XGMAC receive configuration */
++#define XM_RX_CFG_REG_MAC 0x04
++#define XM_PASS_CRC_ERR_LBN 25
++#define XM_PASS_CRC_ERR_WIDTH 1
++#define XM_ACPT_ALL_MCAST_LBN 11
++#define XM_ACPT_ALL_MCAST_WIDTH 1
++#define XM_ACPT_ALL_UCAST_LBN 9
++#define XM_ACPT_ALL_UCAST_WIDTH 1
++#define XM_AUTO_DEPAD_LBN 8
++#define XM_AUTO_DEPAD_WIDTH 1
++#define XM_RXEN_LBN 1
++#define XM_RXEN_WIDTH 1
++
++/* XGMAC management interrupt mask register */
++#define XM_MGT_INT_MSK_REG_MAC_B0 0x5
++#define XM_MSK_PRMBLE_ERR_LBN 2
++#define XM_MSK_PRMBLE_ERR_WIDTH 1
++#define XM_MSK_RMTFLT_LBN 1
++#define XM_MSK_RMTFLT_WIDTH 1
++#define XM_MSK_LCLFLT_LBN 0
++#define XM_MSK_LCLFLT_WIDTH 1
++
++/* XGMAC flow control register */
++#define XM_FC_REG_MAC 0x7
++#define XM_PAUSE_TIME_LBN 16
++#define XM_PAUSE_TIME_WIDTH 16
++#define XM_DIS_FCNTL_LBN 0
++#define XM_DIS_FCNTL_WIDTH 1
++
++/* XGMAC pause time count register */
++#define XM_PAUSE_TIME_REG_MAC 0x9
++
++/* XGMAC transmit parameter register */
++#define XM_TX_PARAM_REG_MAC 0x0d
++#define XM_TX_JUMBO_MODE_LBN 31
++#define XM_TX_JUMBO_MODE_WIDTH 1
++#define XM_MAX_TX_FRM_SIZE_LBN 16
++#define XM_MAX_TX_FRM_SIZE_WIDTH 14
++
++/* XGMAC receive parameter register */
++#define XM_RX_PARAM_REG_MAC 0x0e
++#define XM_MAX_RX_FRM_SIZE_LBN 0
++#define XM_MAX_RX_FRM_SIZE_WIDTH 14
++
++/* XGMAC management interrupt status register */
++#define XM_MGT_INT_REG_MAC_B0 0x0f
++#define XM_PRMBLE_ERR 2
++#define XM_PRMBLE_WIDTH 1
++#define XM_RMTFLT_LBN 1
++#define XM_RMTFLT_WIDTH 1
++#define XM_LCLFLT_LBN 0
++#define XM_LCLFLT_WIDTH 1
++
++/* XGXS/XAUI powerdown/reset register */
++#define XX_PWR_RST_REG_MAC 0x10
++
++#define XX_PWRDND_EN_LBN 15
++#define XX_PWRDND_EN_WIDTH 1
++#define XX_PWRDNC_EN_LBN 14
++#define XX_PWRDNC_EN_WIDTH 1
++#define XX_PWRDNB_EN_LBN 13
++#define XX_PWRDNB_EN_WIDTH 1
++#define XX_PWRDNA_EN_LBN 12
++#define XX_PWRDNA_EN_WIDTH 1
++#define XX_RSTPLLCD_EN_LBN 9
++#define XX_RSTPLLCD_EN_WIDTH 1
++#define XX_RSTPLLAB_EN_LBN 8
++#define XX_RSTPLLAB_EN_WIDTH 1
++#define XX_RESETD_EN_LBN 7
++#define XX_RESETD_EN_WIDTH 1
++#define XX_RESETC_EN_LBN 6
++#define XX_RESETC_EN_WIDTH 1
++#define XX_RESETB_EN_LBN 5
++#define XX_RESETB_EN_WIDTH 1
++#define XX_RESETA_EN_LBN 4
++#define XX_RESETA_EN_WIDTH 1
++#define XX_RSTXGXSRX_EN_LBN 2
++#define XX_RSTXGXSRX_EN_WIDTH 1
++#define XX_RSTXGXSTX_EN_LBN 1
++#define XX_RSTXGXSTX_EN_WIDTH 1
++#define XX_RST_XX_EN_LBN 0
++#define XX_RST_XX_EN_WIDTH 1
++
++/* XGXS/XAUI powerdown/reset control register */
++#define XX_SD_CTL_REG_MAC 0x11
++#define XX_HIDRVD_LBN 15
++#define XX_HIDRVD_WIDTH 1
++#define XX_LODRVD_LBN 14
++#define XX_LODRVD_WIDTH 1
++#define XX_HIDRVC_LBN 13
++#define XX_HIDRVC_WIDTH 1
++#define XX_LODRVC_LBN 12
++#define XX_LODRVC_WIDTH 1
++#define XX_HIDRVB_LBN 11
++#define XX_HIDRVB_WIDTH 1
++#define XX_LODRVB_LBN 10
++#define XX_LODRVB_WIDTH 1
++#define XX_HIDRVA_LBN 9
++#define XX_HIDRVA_WIDTH 1
++#define XX_LODRVA_LBN 8
++#define XX_LODRVA_WIDTH 1
++
++#define XX_TXDRV_CTL_REG_MAC 0x12
++#define XX_DEQD_LBN 28
++#define XX_DEQD_WIDTH 4
++#define XX_DEQC_LBN 24
++#define XX_DEQC_WIDTH 4
++#define XX_DEQB_LBN 20
++#define XX_DEQB_WIDTH 4
++#define XX_DEQA_LBN 16
++#define XX_DEQA_WIDTH 4
++#define XX_DTXD_LBN 12
++#define XX_DTXD_WIDTH 4
++#define XX_DTXC_LBN 8
++#define XX_DTXC_WIDTH 4
++#define XX_DTXB_LBN 4
++#define XX_DTXB_WIDTH 4
++#define XX_DTXA_LBN 0
++#define XX_DTXA_WIDTH 4
++
++/* XAUI XGXS core status register */
++#define XX_FORCE_SIG_DECODE_FORCED 0xff
++#define XX_CORE_STAT_REG_MAC 0x16
++#define XX_ALIGN_DONE_LBN 20
++#define XX_ALIGN_DONE_WIDTH 1
++#define XX_SYNC_STAT_LBN 16
++#define XX_SYNC_STAT_WIDTH 4
++#define XX_SYNC_STAT_DECODE_SYNCED 0xf
++#define XX_COMMA_DET_LBN 12
++#define XX_COMMA_DET_WIDTH 4
++#define XX_COMMA_DET_DECODE_DETECTED 0xf
++#define XX_COMMA_DET_RESET 0xf
++#define XX_CHARERR_LBN 4
++#define XX_CHARERR_WIDTH 4
++#define XX_CHARERR_RESET 0xf
++#define XX_DISPERR_LBN 0
++#define XX_DISPERR_WIDTH 4
++#define XX_DISPERR_RESET 0xf
++
++/* Receive filter table */
++#define RX_FILTER_TBL0 0xF00000
++
++/* Receive descriptor pointer table */
++#define RX_DESC_PTR_TBL_KER_A1 0x11800
++#define RX_DESC_PTR_TBL_KER_B0 0xF40000
++#define RX_DESC_PTR_TBL_KER_P0 0x900
++#define RX_ISCSI_DDIG_EN_LBN 88
++#define RX_ISCSI_DDIG_EN_WIDTH 1
++#define RX_ISCSI_HDIG_EN_LBN 87
++#define RX_ISCSI_HDIG_EN_WIDTH 1
++#define RX_DESCQ_BUF_BASE_ID_LBN 36
++#define RX_DESCQ_BUF_BASE_ID_WIDTH 20
++#define RX_DESCQ_EVQ_ID_LBN 24
++#define RX_DESCQ_EVQ_ID_WIDTH 12
++#define RX_DESCQ_OWNER_ID_LBN 10
++#define RX_DESCQ_OWNER_ID_WIDTH 14
++#define RX_DESCQ_LABEL_LBN 5
++#define RX_DESCQ_LABEL_WIDTH 5
++#define RX_DESCQ_SIZE_LBN 3
++#define RX_DESCQ_SIZE_WIDTH 2
++#define RX_DESCQ_SIZE_4K 3
++#define RX_DESCQ_SIZE_2K 2
++#define RX_DESCQ_SIZE_1K 1
++#define RX_DESCQ_SIZE_512 0
++#define RX_DESCQ_TYPE_LBN 2
++#define RX_DESCQ_TYPE_WIDTH 1
++#define RX_DESCQ_JUMBO_LBN 1
++#define RX_DESCQ_JUMBO_WIDTH 1
++#define RX_DESCQ_EN_LBN 0
++#define RX_DESCQ_EN_WIDTH 1
++
++/* Transmit descriptor pointer table */
++#define TX_DESC_PTR_TBL_KER_A1 0x11900
++#define TX_DESC_PTR_TBL_KER_B0 0xF50000
++#define TX_DESC_PTR_TBL_KER_P0 0xa40
++#define TX_NON_IP_DROP_DIS_B0_LBN 91
++#define TX_NON_IP_DROP_DIS_B0_WIDTH 1
++#define TX_IP_CHKSM_DIS_B0_LBN 90
++#define TX_IP_CHKSM_DIS_B0_WIDTH 1
++#define TX_TCP_CHKSM_DIS_B0_LBN 89
++#define TX_TCP_CHKSM_DIS_B0_WIDTH 1
++#define TX_DESCQ_EN_LBN 88
++#define TX_DESCQ_EN_WIDTH 1
++#define TX_ISCSI_DDIG_EN_LBN 87
++#define TX_ISCSI_DDIG_EN_WIDTH 1
++#define TX_ISCSI_HDIG_EN_LBN 86
++#define TX_ISCSI_HDIG_EN_WIDTH 1
++#define TX_DESCQ_BUF_BASE_ID_LBN 36
++#define TX_DESCQ_BUF_BASE_ID_WIDTH 20
++#define TX_DESCQ_EVQ_ID_LBN 24
++#define TX_DESCQ_EVQ_ID_WIDTH 12
++#define TX_DESCQ_OWNER_ID_LBN 10
++#define TX_DESCQ_OWNER_ID_WIDTH 14
++#define TX_DESCQ_LABEL_LBN 5
++#define TX_DESCQ_LABEL_WIDTH 5
++#define TX_DESCQ_SIZE_LBN 3
++#define TX_DESCQ_SIZE_WIDTH 2
++#define TX_DESCQ_SIZE_4K 3
++#define TX_DESCQ_SIZE_2K 2
++#define TX_DESCQ_SIZE_1K 1
++#define TX_DESCQ_SIZE_512 0
++#define TX_DESCQ_TYPE_LBN 1
++#define TX_DESCQ_TYPE_WIDTH 2
++
++/* Event queue pointer */
++#define EVQ_PTR_TBL_KER_A1 0x11a00
++#define EVQ_PTR_TBL_KER_B0 0xf60000
++#define EVQ_PTR_TBL_KER_P0 0x500
++#define EVQ_EN_LBN 23
++#define EVQ_EN_WIDTH 1
++#define EVQ_SIZE_LBN 20
++#define EVQ_SIZE_WIDTH 3
++#define EVQ_SIZE_32K 6
++#define EVQ_SIZE_16K 5
++#define EVQ_SIZE_8K 4
++#define EVQ_SIZE_4K 3
++#define EVQ_SIZE_2K 2
++#define EVQ_SIZE_1K 1
++#define EVQ_SIZE_512 0
++#define EVQ_BUF_BASE_ID_LBN 0
++#define EVQ_BUF_BASE_ID_WIDTH 20
++
++/* Event queue read pointer */
++#define EVQ_RPTR_REG_KER_A1 0x11b00
++#define EVQ_RPTR_REG_KER_B0 0xfa0000
++#define EVQ_RPTR_REG_KER_DWORD (EVQ_RPTR_REG_KER + 0)
++#define EVQ_RPTR_DWORD_LBN 0
++#define EVQ_RPTR_DWORD_WIDTH 14
++
++/* RSS indirection table */
++#define RX_RSS_INDIR_TBL_B0 0xFB0000
++#define RX_RSS_INDIR_ENT_B0_LBN 0
++#define RX_RSS_INDIR_ENT_B0_WIDTH 6
++
++/* Special buffer descriptors (full-mode) */
++#define BUF_FULL_TBL_KER_A1 0x8000
++#define BUF_FULL_TBL_KER_B0 0x800000
++#define IP_DAT_BUF_SIZE_LBN 50
++#define IP_DAT_BUF_SIZE_WIDTH 1
++#define IP_DAT_BUF_SIZE_8K 1
++#define IP_DAT_BUF_SIZE_4K 0
++#define BUF_ADR_REGION_LBN 48
++#define BUF_ADR_REGION_WIDTH 2
++#define BUF_ADR_FBUF_LBN 14
++#define BUF_ADR_FBUF_WIDTH 34
++#define BUF_OWNER_ID_FBUF_LBN 0
++#define BUF_OWNER_ID_FBUF_WIDTH 14
++
++/* Transmit descriptor */
++#define TX_KER_PORT_LBN 63
++#define TX_KER_PORT_WIDTH 1
++#define TX_KER_CONT_LBN 62
++#define TX_KER_CONT_WIDTH 1
++#define TX_KER_BYTE_CNT_LBN 48
++#define TX_KER_BYTE_CNT_WIDTH 14
++#define TX_KER_BUF_REGION_LBN 46
++#define TX_KER_BUF_REGION_WIDTH 2
++#define TX_KER_BUF_REGION0_DECODE 0
++#define TX_KER_BUF_REGION1_DECODE 1
++#define TX_KER_BUF_REGION2_DECODE 2
++#define TX_KER_BUF_REGION3_DECODE 3
++#define TX_KER_BUF_ADR_LBN 0
++#define TX_KER_BUF_ADR_WIDTH EFX_DMA_TYPE_WIDTH(46)
++
++/* Receive descriptor */
++#define RX_KER_BUF_SIZE_LBN 48
++#define RX_KER_BUF_SIZE_WIDTH 14
++#define RX_KER_BUF_REGION_LBN 46
++#define RX_KER_BUF_REGION_WIDTH 2
++#define RX_KER_BUF_REGION0_DECODE 0
++#define RX_KER_BUF_REGION1_DECODE 1
++#define RX_KER_BUF_REGION2_DECODE 2
++#define RX_KER_BUF_REGION3_DECODE 3
++#define RX_KER_BUF_ADR_LBN 0
++#define RX_KER_BUF_ADR_WIDTH EFX_DMA_TYPE_WIDTH(46)
++
++/**************************************************************************
++ *
++ * Falcon events
++ *
++ **************************************************************************
++ */
++
++/* Event queue entries */
++#define EV_CODE_LBN 60
++#define EV_CODE_WIDTH 4
++#define RX_IP_EV_DECODE 0
++#define TX_IP_EV_DECODE 2
++#define DRIVER_EV_DECODE 5
++#define GLOBAL_EV_DECODE 6
++#define DRV_GEN_EV_DECODE 7
++#define WHOLE_EVENT_LBN 0
++#define WHOLE_EVENT_WIDTH 64
++
++/* Receive events */
++#define RX_EV_PKT_OK_LBN 56
++#define RX_EV_PKT_OK_WIDTH 1
++#define RX_EV_PAUSE_FRM_ERR_LBN 55
++#define RX_EV_PAUSE_FRM_ERR_WIDTH 1
++#define RX_EV_BUF_OWNER_ID_ERR_LBN 54
++#define RX_EV_BUF_OWNER_ID_ERR_WIDTH 1
++#define RX_EV_IF_FRAG_ERR_LBN 53
++#define RX_EV_IF_FRAG_ERR_WIDTH 1
++#define RX_EV_IP_HDR_CHKSUM_ERR_LBN 52
++#define RX_EV_IP_HDR_CHKSUM_ERR_WIDTH 1
++#define RX_EV_TCP_UDP_CHKSUM_ERR_LBN 51
++#define RX_EV_TCP_UDP_CHKSUM_ERR_WIDTH 1
++#define RX_EV_ETH_CRC_ERR_LBN 50
++#define RX_EV_ETH_CRC_ERR_WIDTH 1
++#define RX_EV_FRM_TRUNC_LBN 49
++#define RX_EV_FRM_TRUNC_WIDTH 1
++#define RX_EV_DRIB_NIB_LBN 48
++#define RX_EV_DRIB_NIB_WIDTH 1
++#define RX_EV_TOBE_DISC_LBN 47
++#define RX_EV_TOBE_DISC_WIDTH 1
++#define RX_EV_PKT_TYPE_LBN 44
++#define RX_EV_PKT_TYPE_WIDTH 3
++#define RX_EV_PKT_TYPE_ETH_DECODE 0
++#define RX_EV_PKT_TYPE_LLC_DECODE 1
++#define RX_EV_PKT_TYPE_JUMBO_DECODE 2
++#define RX_EV_PKT_TYPE_VLAN_DECODE 3
++#define RX_EV_PKT_TYPE_VLAN_LLC_DECODE 4
++#define RX_EV_PKT_TYPE_VLAN_JUMBO_DECODE 5
++#define RX_EV_HDR_TYPE_LBN 42
++#define RX_EV_HDR_TYPE_WIDTH 2
++#define RX_EV_HDR_TYPE_TCP_IPV4_DECODE 0
++#define RX_EV_HDR_TYPE_UDP_IPV4_DECODE 1
++#define RX_EV_HDR_TYPE_OTHER_IP_DECODE 2
++#define RX_EV_HDR_TYPE_NON_IP_DECODE 3
++#define RX_EV_HDR_TYPE_HAS_CHECKSUMS(hdr_type) \
++ ((hdr_type) <= RX_EV_HDR_TYPE_UDP_IPV4_DECODE)
++#define RX_EV_MCAST_HASH_MATCH_LBN 40
++#define RX_EV_MCAST_HASH_MATCH_WIDTH 1
++#define RX_EV_MCAST_PKT_LBN 39
++#define RX_EV_MCAST_PKT_WIDTH 1
++#define RX_EV_Q_LABEL_LBN 32
++#define RX_EV_Q_LABEL_WIDTH 5
++#define RX_EV_JUMBO_CONT_LBN 31
++#define RX_EV_JUMBO_CONT_WIDTH 1
++#define RX_EV_BYTE_CNT_LBN 16
++#define RX_EV_BYTE_CNT_WIDTH 14
++#define RX_EV_SOP_LBN 15
++#define RX_EV_SOP_WIDTH 1
++#define RX_EV_DESC_PTR_LBN 0
++#define RX_EV_DESC_PTR_WIDTH 12
++
++/* Transmit events */
++#define TX_EV_PKT_ERR_LBN 38
++#define TX_EV_PKT_ERR_WIDTH 1
++#define TX_EV_Q_LABEL_LBN 32
++#define TX_EV_Q_LABEL_WIDTH 5
++#define TX_EV_WQ_FF_FULL_LBN 15
++#define TX_EV_WQ_FF_FULL_WIDTH 1
++#define TX_EV_COMP_LBN 12
++#define TX_EV_COMP_WIDTH 1
++#define TX_EV_DESC_PTR_LBN 0
++#define TX_EV_DESC_PTR_WIDTH 12
++
++/* Driver events */
++#define DRIVER_EV_SUB_CODE_LBN 56
++#define DRIVER_EV_SUB_CODE_WIDTH 4
++#define DRIVER_EV_SUB_DATA_LBN 0
++#define DRIVER_EV_SUB_DATA_WIDTH 14
++#define TX_DESCQ_FLS_DONE_EV_DECODE 0
++#define RX_DESCQ_FLS_DONE_EV_DECODE 1
++#define EVQ_INIT_DONE_EV_DECODE 2
++#define EVQ_NOT_EN_EV_DECODE 3
++#define RX_DESCQ_FLSFF_OVFL_EV_DECODE 4
++#define SRM_UPD_DONE_EV_DECODE 5
++#define WAKE_UP_EV_DECODE 6
++#define TX_PKT_NON_TCP_UDP_DECODE 9
++#define TIMER_EV_DECODE 10
++#define RX_RECOVERY_EV_DECODE 11
++#define RX_DSC_ERROR_EV_DECODE 14
++#define TX_DSC_ERROR_EV_DECODE 15
++#define DRIVER_EV_TX_DESCQ_ID_LBN 0
++#define DRIVER_EV_TX_DESCQ_ID_WIDTH 12
++#define DRIVER_EV_RX_FLUSH_FAIL_LBN 12
++#define DRIVER_EV_RX_FLUSH_FAIL_WIDTH 1
++#define DRIVER_EV_RX_DESCQ_ID_LBN 0
++#define DRIVER_EV_RX_DESCQ_ID_WIDTH 12
++#define SRM_CLR_EV_DECODE 0
++#define SRM_UPD_EV_DECODE 1
++#define SRM_ILLCLR_EV_DECODE 2
++
++/* Global events */
++#define RX_RECOVERY_B0_LBN 12
++#define RX_RECOVERY_B0_WIDTH 1
++#define XG_MNT_INTR_B0_LBN 11
++#define XG_MNT_INTR_B0_WIDTH 1
++#define RX_RECOVERY_A1_LBN 11
++#define RX_RECOVERY_A1_WIDTH 1
++#define XG_PHY_INTR_LBN 9
++#define XG_PHY_INTR_WIDTH 1
++#define G_PHY1_INTR_LBN 8
++#define G_PHY1_INTR_WIDTH 1
++#define G_PHY0_INTR_LBN 7
++#define G_PHY0_INTR_WIDTH 1
++
++/* Driver-generated test events */
++#define EVQ_MAGIC_LBN 0
++#define EVQ_MAGIC_WIDTH 32
++
++/**************************************************************************
++ *
++ * Falcon MAC stats
++ *
++ **************************************************************************
++ *
++ */
++#define GRxGoodOct_offset 0x0
++#define GRxBadOct_offset 0x8
++#define GRxMissPkt_offset 0x10
++#define GRxFalseCRS_offset 0x14
++#define GRxPausePkt_offset 0x18
++#define GRxBadPkt_offset 0x1C
++#define GRxUcastPkt_offset 0x20
++#define GRxMcastPkt_offset 0x24
++#define GRxBcastPkt_offset 0x28
++#define GRxGoodLt64Pkt_offset 0x2C
++#define GRxBadLt64Pkt_offset 0x30
++#define GRx64Pkt_offset 0x34
++#define GRx65to127Pkt_offset 0x38
++#define GRx128to255Pkt_offset 0x3C
++#define GRx256to511Pkt_offset 0x40
++#define GRx512to1023Pkt_offset 0x44
++#define GRx1024to15xxPkt_offset 0x48
++#define GRx15xxtoJumboPkt_offset 0x4C
++#define GRxGtJumboPkt_offset 0x50
++#define GRxFcsErr64to15xxPkt_offset 0x54
++#define GRxFcsErr15xxtoJumboPkt_offset 0x58
++#define GRxFcsErrGtJumboPkt_offset 0x5C
++#define GTxGoodBadOct_offset 0x80
++#define GTxGoodOct_offset 0x88
++#define GTxSglColPkt_offset 0x90
++#define GTxMultColPkt_offset 0x94
++#define GTxExColPkt_offset 0x98
++#define GTxDefPkt_offset 0x9C
++#define GTxLateCol_offset 0xA0
++#define GTxExDefPkt_offset 0xA4
++#define GTxPausePkt_offset 0xA8
++#define GTxBadPkt_offset 0xAC
++#define GTxUcastPkt_offset 0xB0
++#define GTxMcastPkt_offset 0xB4
++#define GTxBcastPkt_offset 0xB8
++#define GTxLt64Pkt_offset 0xBC
++#define GTx64Pkt_offset 0xC0
++#define GTx65to127Pkt_offset 0xC4
++#define GTx128to255Pkt_offset 0xC8
++#define GTx256to511Pkt_offset 0xCC
++#define GTx512to1023Pkt_offset 0xD0
++#define GTx1024to15xxPkt_offset 0xD4
++#define GTx15xxtoJumboPkt_offset 0xD8
++#define GTxGtJumboPkt_offset 0xDC
++#define GTxNonTcpUdpPkt_offset 0xE0
++#define GTxMacSrcErrPkt_offset 0xE4
++#define GTxIpSrcErrPkt_offset 0xE8
++#define GDmaDone_offset 0xEC
++
++#define XgRxOctets_offset 0x0
++#define XgRxOctets_WIDTH 48
++#define XgRxOctetsOK_offset 0x8
++#define XgRxOctetsOK_WIDTH 48
++#define XgRxPkts_offset 0x10
++#define XgRxPkts_WIDTH 32
++#define XgRxPktsOK_offset 0x14
++#define XgRxPktsOK_WIDTH 32
++#define XgRxBroadcastPkts_offset 0x18
++#define XgRxBroadcastPkts_WIDTH 32
++#define XgRxMulticastPkts_offset 0x1C
++#define XgRxMulticastPkts_WIDTH 32
++#define XgRxUnicastPkts_offset 0x20
++#define XgRxUnicastPkts_WIDTH 32
++#define XgRxUndersizePkts_offset 0x24
++#define XgRxUndersizePkts_WIDTH 32
++#define XgRxOversizePkts_offset 0x28
++#define XgRxOversizePkts_WIDTH 32
++#define XgRxJabberPkts_offset 0x2C
++#define XgRxJabberPkts_WIDTH 32
++#define XgRxUndersizeFCSerrorPkts_offset 0x30
++#define XgRxUndersizeFCSerrorPkts_WIDTH 32
++#define XgRxDropEvents_offset 0x34
++#define XgRxDropEvents_WIDTH 32
++#define XgRxFCSerrorPkts_offset 0x38
++#define XgRxFCSerrorPkts_WIDTH 32
++#define XgRxAlignError_offset 0x3C
++#define XgRxAlignError_WIDTH 32
++#define XgRxSymbolError_offset 0x40
++#define XgRxSymbolError_WIDTH 32
++#define XgRxInternalMACError_offset 0x44
++#define XgRxInternalMACError_WIDTH 32
++#define XgRxControlPkts_offset 0x48
++#define XgRxControlPkts_WIDTH 32
++#define XgRxPausePkts_offset 0x4C
++#define XgRxPausePkts_WIDTH 32
++#define XgRxPkts64Octets_offset 0x50
++#define XgRxPkts64Octets_WIDTH 32
++#define XgRxPkts65to127Octets_offset 0x54
++#define XgRxPkts65to127Octets_WIDTH 32
++#define XgRxPkts128to255Octets_offset 0x58
++#define XgRxPkts128to255Octets_WIDTH 32
++#define XgRxPkts256to511Octets_offset 0x5C
++#define XgRxPkts256to511Octets_WIDTH 32
++#define XgRxPkts512to1023Octets_offset 0x60
++#define XgRxPkts512to1023Octets_WIDTH 32
++#define XgRxPkts1024to15xxOctets_offset 0x64
++#define XgRxPkts1024to15xxOctets_WIDTH 32
++#define XgRxPkts15xxtoMaxOctets_offset 0x68
++#define XgRxPkts15xxtoMaxOctets_WIDTH 32
++#define XgRxLengthError_offset 0x6C
++#define XgRxLengthError_WIDTH 32
++#define XgTxPkts_offset 0x80
++#define XgTxPkts_WIDTH 32
++#define XgTxOctets_offset 0x88
++#define XgTxOctets_WIDTH 48
++#define XgTxMulticastPkts_offset 0x90
++#define XgTxMulticastPkts_WIDTH 32
++#define XgTxBroadcastPkts_offset 0x94
++#define XgTxBroadcastPkts_WIDTH 32
++#define XgTxUnicastPkts_offset 0x98
++#define XgTxUnicastPkts_WIDTH 32
++#define XgTxControlPkts_offset 0x9C
++#define XgTxControlPkts_WIDTH 32
++#define XgTxPausePkts_offset 0xA0
++#define XgTxPausePkts_WIDTH 32
++#define XgTxPkts64Octets_offset 0xA4
++#define XgTxPkts64Octets_WIDTH 32
++#define XgTxPkts65to127Octets_offset 0xA8
++#define XgTxPkts65to127Octets_WIDTH 32
++#define XgTxPkts128to255Octets_offset 0xAC
++#define XgTxPkts128to255Octets_WIDTH 32
++#define XgTxPkts256to511Octets_offset 0xB0
++#define XgTxPkts256to511Octets_WIDTH 32
++#define XgTxPkts512to1023Octets_offset 0xB4
++#define XgTxPkts512to1023Octets_WIDTH 32
++#define XgTxPkts1024to15xxOctets_offset 0xB8
++#define XgTxPkts1024to15xxOctets_WIDTH 32
++#define XgTxPkts1519toMaxOctets_offset 0xBC
++#define XgTxPkts1519toMaxOctets_WIDTH 32
++#define XgTxUndersizePkts_offset 0xC0
++#define XgTxUndersizePkts_WIDTH 32
++#define XgTxOversizePkts_offset 0xC4
++#define XgTxOversizePkts_WIDTH 32
++#define XgTxNonTcpUdpPkt_offset 0xC8
++#define XgTxNonTcpUdpPkt_WIDTH 16
++#define XgTxMacSrcErrPkt_offset 0xCC
++#define XgTxMacSrcErrPkt_WIDTH 16
++#define XgTxIpSrcErrPkt_offset 0xD0
++#define XgTxIpSrcErrPkt_WIDTH 16
++#define XgDmaDone_offset 0xD4
++
++#define FALCON_STATS_NOT_DONE 0x00000000
++#define FALCON_STATS_DONE 0xffffffff
++
++/* Interrupt status register bits */
++#define FATAL_INT_LBN 64
++#define FATAL_INT_WIDTH 1
++#define INT_EVQS_LBN 40
++#define INT_EVQS_WIDTH 4
++
++/**************************************************************************
++ *
++ * Falcon non-volatile configuration
++ *
++ **************************************************************************
++ */
++
++/* Board configuration v2 (v1 is obsolete; later versions are compatible) */
++struct falcon_nvconfig_board_v2 {
++ __le16 nports;
++ u8 port0_phy_addr;
++ u8 port0_phy_type;
++ u8 port1_phy_addr;
++ u8 port1_phy_type;
++ __le16 asic_sub_revision;
++ __le16 board_revision;
++} __attribute__ ((packed));
++
++#define NVCONFIG_BASE 0x300
++#define NVCONFIG_BOARD_MAGIC_NUM 0xFA1C
++struct falcon_nvconfig {
++ efx_oword_t ee_vpd_cfg_reg; /* 0x300 */
++ u8 mac_address[2][8]; /* 0x310 */
++ efx_oword_t pcie_sd_ctl0123_reg; /* 0x320 */
++ efx_oword_t pcie_sd_ctl45_reg; /* 0x330 */
++ efx_oword_t pcie_pcs_ctl_stat_reg; /* 0x340 */
++ efx_oword_t hw_init_reg; /* 0x350 */
++ efx_oword_t nic_stat_reg; /* 0x360 */
++ efx_oword_t glb_ctl_reg; /* 0x370 */
++ efx_oword_t srm_cfg_reg; /* 0x380 */
++ efx_oword_t spare_reg; /* 0x390 */
++ __le16 board_magic_num; /* 0x3A0 */
++ __le16 board_struct_ver;
++ __le16 board_checksum;
++ struct falcon_nvconfig_board_v2 board_v2;
++} __attribute__ ((packed));
++
++#endif /* EFX_FALCON_HWDEFS_H */
+diff --git a/drivers/net/sfc/falcon_io.h b/drivers/net/sfc/falcon_io.h
+new file mode 100644
+index 0000000..ea08184
+--- /dev/null
++++ b/drivers/net/sfc/falcon_io.h
+@@ -0,0 +1,243 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005-2006 Fen Systems Ltd.
++ * Copyright 2006-2008 Solarflare Communications 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, incorporated herein by reference.
++ */
++
++#ifndef EFX_FALCON_IO_H
++#define EFX_FALCON_IO_H
++
++#include <linux/io.h>
++#include <linux/spinlock.h>
++#include "net_driver.h"
++
++/**************************************************************************
++ *
++ * Falcon hardware access
++ *
++ **************************************************************************
++ *
++ * Notes on locking strategy:
++ *
++ * Most Falcon registers require 16-byte (or 8-byte, for SRAM
++ * registers) atomic writes which necessitates locking.
++ * Under normal operation few writes to the Falcon BAR are made and these
++ * registers (EVQ_RPTR_REG, RX_DESC_UPD_REG and TX_DESC_UPD_REG) are special
++ * cased to allow 4-byte (hence lockless) accesses.
++ *
++ * It *is* safe to write to these 4-byte registers in the middle of an
++ * access to an 8-byte or 16-byte register. We therefore use a
++ * spinlock to protect accesses to the larger registers, but no locks
++ * for the 4-byte registers.
++ *
++ * A write barrier is needed to ensure that DW3 is written after DW0/1/2
++ * due to the way the 16byte registers are "collected" in the Falcon BIU
++ *
++ * We also lock when carrying out reads, to ensure consistency of the
++ * data (made possible since the BIU reads all 128 bits into a cache).
++ * Reads are very rare, so this isn't a significant performance
++ * impact. (Most data transferred from NIC to host is DMAed directly
++ * into host memory).
++ *
++ * I/O BAR access uses locks for both reads and writes (but is only provided
++ * for testing purposes).
++ */
++
++/* Special buffer descriptors (Falcon SRAM) */
++#define BUF_TBL_KER_A1 0x18000
++#define BUF_TBL_KER_B0 0x800000
++
++
++#if BITS_PER_LONG == 64
++#define FALCON_USE_QWORD_IO 1
++#endif
++
++#define _falcon_writeq(efx, value, reg) \
++ __raw_writeq((__force u64) (value), (efx)->membase + (reg))
++#define _falcon_writel(efx, value, reg) \
++ __raw_writel((__force u32) (value), (efx)->membase + (reg))
++#define _falcon_readq(efx, reg) \
++ ((__force __le64) __raw_readq((efx)->membase + (reg)))
++#define _falcon_readl(efx, reg) \
++ ((__force __le32) __raw_readl((efx)->membase + (reg)))
++
++/* Writes to a normal 16-byte Falcon register, locking as appropriate. */
++static inline void falcon_write(struct efx_nic *efx, efx_oword_t *value,
++ unsigned int reg)
+{
-+ 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;
++ EFX_REGDUMP(efx, "writing register %x with " EFX_OWORD_FMT "\n", reg,
++ EFX_OWORD_VAL(*value));
+
-+ spin_lock_irqsave(&np->lock, flags);
++ spin_lock_irqsave(&efx->biu_lock, flags);
++#ifdef FALCON_USE_QWORD_IO
++ _falcon_writeq(efx, value->u64[0], reg + 0);
++ wmb();
++ _falcon_writeq(efx, value->u64[1], reg + 8);
++#else
++ _falcon_writel(efx, value->u32[0], reg + 0);
++ _falcon_writel(efx, value->u32[1], reg + 4);
++ _falcon_writel(efx, value->u32[2], reg + 8);
++ wmb();
++ _falcon_writel(efx, value->u32[3], reg + 12);
++#endif
++ mmiowb();
++ spin_unlock_irqrestore(&efx->biu_lock, flags);
++}
+
-+ val = nr64_pcs(PCS_MII_STAT);
++/* Writes to an 8-byte Falcon SRAM register, locking as appropriate. */
++static inline void falcon_write_sram(struct efx_nic *efx, efx_qword_t *value,
++ unsigned int index)
++{
++ unsigned int reg = efx->type->buf_tbl_base + (index * sizeof(*value));
++ unsigned long flags;
+
-+ if (val & PCS_MII_STAT_LINK_STATUS) {
-+ link_up = 1;
-+ current_speed = SPEED_1000;
-+ current_duplex = DUPLEX_FULL;
-+ }
++ EFX_REGDUMP(efx, "writing SRAM register %x with " EFX_QWORD_FMT "\n",
++ reg, EFX_QWORD_VAL(*value));
+
-+ lp->active_speed = current_speed;
-+ lp->active_duplex = current_duplex;
-+ spin_unlock_irqrestore(&np->lock, flags);
++ spin_lock_irqsave(&efx->biu_lock, flags);
++#ifdef FALCON_USE_QWORD_IO
++ _falcon_writeq(efx, value->u64[0], reg + 0);
++#else
++ _falcon_writel(efx, value->u32[0], reg + 0);
++ wmb();
++ _falcon_writel(efx, value->u32[1], reg + 4);
++#endif
++ mmiowb();
++ spin_unlock_irqrestore(&efx->biu_lock, flags);
++}
+
-+ *link_up_p = link_up;
-+ return 0;
++/* Write dword to Falcon register that allows partial writes
++ *
++ * Some Falcon registers (EVQ_RPTR_REG, RX_DESC_UPD_REG and
++ * TX_DESC_UPD_REG) can be written to as a single dword. This allows
++ * for lockless writes.
++ */
++static inline void falcon_writel(struct efx_nic *efx, efx_dword_t *value,
++ unsigned int reg)
++{
++ EFX_REGDUMP(efx, "writing partial register %x with "EFX_DWORD_FMT"\n",
++ reg, EFX_DWORD_VAL(*value));
++
++ /* No lock required */
++ _falcon_writel(efx, value->u32[0], reg);
+}
+
++/* Read from a Falcon register
++ *
++ * This reads an entire 16-byte Falcon register in one go, locking as
++ * appropriate. It is essential to read the first dword first, as this
++ * prompts Falcon to load the current value into the shadow register.
++ */
++static inline void falcon_read(struct efx_nic *efx, efx_oword_t *value,
++ unsigned int reg)
++{
++ unsigned long flags;
+
-+static int link_status_10g_serdes(struct niu *np, int *link_up_p)
++ spin_lock_irqsave(&efx->biu_lock, flags);
++ value->u32[0] = _falcon_readl(efx, reg + 0);
++ rmb();
++ value->u32[1] = _falcon_readl(efx, reg + 4);
++ value->u32[2] = _falcon_readl(efx, reg + 8);
++ value->u32[3] = _falcon_readl(efx, reg + 12);
++ spin_unlock_irqrestore(&efx->biu_lock, flags);
++
++ EFX_REGDUMP(efx, "read from register %x, got " EFX_OWORD_FMT "\n", reg,
++ EFX_OWORD_VAL(*value));
++}
++
++/* This reads an 8-byte Falcon SRAM entry in one go. */
++static inline void falcon_read_sram(struct efx_nic *efx, efx_qword_t *value,
++ unsigned int index)
+{
++ unsigned int reg = efx->type->buf_tbl_base + (index * sizeof(*value));
+ 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);
++ spin_lock_irqsave(&efx->biu_lock, flags);
++#ifdef FALCON_USE_QWORD_IO
++ value->u64[0] = _falcon_readq(efx, reg + 0);
++#else
++ value->u32[0] = _falcon_readl(efx, reg + 0);
++ rmb();
++ value->u32[1] = _falcon_readl(efx, reg + 4);
++#endif
++ spin_unlock_irqrestore(&efx->biu_lock, flags);
+
-+ current_speed = SPEED_INVALID;
-+ current_duplex = DUPLEX_INVALID;
-+ spin_lock_irqsave(&np->lock, flags);
++ EFX_REGDUMP(efx, "read from SRAM register %x, got "EFX_QWORD_FMT"\n",
++ reg, EFX_QWORD_VAL(*value));
++}
+
-+ val = nr64_xpcs(XPCS_STATUS(0));
-+ val2 = nr64_mac(XMAC_INTER2);
-+ if (val2 & 0x01000000)
-+ link_ok = 0;
++/* Read dword from Falcon register that allows partial writes (sic) */
++static inline void falcon_readl(struct efx_nic *efx, efx_dword_t *value,
++ unsigned int reg)
++{
++ value->u32[0] = _falcon_readl(efx, reg);
++ EFX_REGDUMP(efx, "read from register %x, got "EFX_DWORD_FMT"\n",
++ reg, EFX_DWORD_VAL(*value));
++}
+
-+ 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;
++/* Write to a register forming part of a table */
++static inline void falcon_write_table(struct efx_nic *efx, efx_oword_t *value,
++ unsigned int reg, unsigned int index)
++{
++ falcon_write(efx, value, reg + index * sizeof(efx_oword_t));
+}
+
++/* Read to a register forming part of a table */
++static inline void falcon_read_table(struct efx_nic *efx, efx_oword_t *value,
++ unsigned int reg, unsigned int index)
++{
++ falcon_read(efx, value, reg + index * sizeof(efx_oword_t));
++}
+
-+static int link_status_1g_rgmii(struct niu *np, int *link_up_p)
++/* Write to a dword register forming part of a table */
++static inline void falcon_writel_table(struct efx_nic *efx, efx_dword_t *value,
++ unsigned int reg, unsigned int index)
++{
++ falcon_writel(efx, value, reg + index * sizeof(efx_oword_t));
++}
++
++/* Page-mapped register block size */
++#define FALCON_PAGE_BLOCK_SIZE 0x2000
++
++/* Calculate offset to page-mapped register block */
++#define FALCON_PAGED_REG(page, reg) \
++ ((page) * FALCON_PAGE_BLOCK_SIZE + (reg))
++
++/* As for falcon_write(), but for a page-mapped register. */
++static inline void falcon_write_page(struct efx_nic *efx, efx_oword_t *value,
++ unsigned int reg, unsigned int page)
++{
++ falcon_write(efx, value, FALCON_PAGED_REG(page, reg));
++}
++
++/* As for falcon_writel(), but for a page-mapped register. */
++static inline void falcon_writel_page(struct efx_nic *efx, efx_dword_t *value,
++ unsigned int reg, unsigned int page)
++{
++ falcon_writel(efx, value, FALCON_PAGED_REG(page, reg));
++}
++
++/* Write dword to Falcon page-mapped register with an extra lock.
++ *
++ * As for falcon_writel_page(), but for a register that suffers from
++ * SFC bug 3181. Take out a lock so the BIU collector cannot be
++ * confused. */
++static inline void falcon_writel_page_locked(struct efx_nic *efx,
++ efx_dword_t *value,
++ unsigned int reg,
++ unsigned int page)
+{
-+ 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(&efx->biu_lock, flags);
++ falcon_writel(efx, value, FALCON_PAGED_REG(page, reg));
++ spin_unlock_irqrestore(&efx->biu_lock, flags);
++}
+
-+ spin_lock_irqsave(&np->lock, flags);
++#endif /* EFX_FALCON_IO_H */
+diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c
+new file mode 100644
+index 0000000..aa7521b
+--- /dev/null
++++ b/drivers/net/sfc/falcon_xmac.c
+@@ -0,0 +1,585 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005-2006 Fen Systems Ltd.
++ * Copyright 2006-2008 Solarflare Communications 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, incorporated herein by reference.
++ */
+
-+ err = -EINVAL;
++#include <linux/delay.h>
++#include "net_driver.h"
++#include "efx.h"
++#include "falcon.h"
++#include "falcon_hwdefs.h"
++#include "falcon_io.h"
++#include "mac.h"
++#include "gmii.h"
++#include "mdio_10g.h"
++#include "phy.h"
++#include "boards.h"
++#include "workarounds.h"
+
-+ err = mii_read(np, np->phy_addr, MII_BMSR);
-+ if (err < 0)
-+ goto out;
++/**************************************************************************
++ *
++ * MAC register access
++ *
++ **************************************************************************/
+
-+ bmsr = err;
-+ if (bmsr & BMSR_LSTATUS) {
-+ u16 adv, lpa, common, estat;
++/* Offset of an XMAC register within Falcon */
++#define FALCON_XMAC_REG(mac_reg) \
++ (FALCON_XMAC_REGBANK + ((mac_reg) * FALCON_XMAC_REG_SIZE))
+
-+ err = mii_read(np, np->phy_addr, MII_ADVERTISE);
-+ if (err < 0)
-+ goto out;
-+ adv = err;
++void falcon_xmac_writel(struct efx_nic *efx,
++ efx_dword_t *value, unsigned int mac_reg)
++{
++ efx_oword_t temp;
+
-+ err = mii_read(np, np->phy_addr, MII_LPA);
-+ if (err < 0)
-+ goto out;
-+ lpa = err;
++ EFX_POPULATE_OWORD_1(temp, MAC_DATA, EFX_DWORD_FIELD(*value, MAC_DATA));
++ falcon_write(efx, &temp, FALCON_XMAC_REG(mac_reg));
++}
+
-+ common = adv & lpa;
++void falcon_xmac_readl(struct efx_nic *efx,
++ efx_dword_t *value, unsigned int mac_reg)
++{
++ efx_oword_t temp;
+
-+ 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;
++ falcon_read(efx, &temp, FALCON_XMAC_REG(mac_reg));
++ EFX_POPULATE_DWORD_1(*value, MAC_DATA, EFX_OWORD_FIELD(temp, MAC_DATA));
++}
+
-+ }
-+ lp->active_speed = current_speed;
-+ lp->active_duplex = current_duplex;
-+ err = 0;
++/**************************************************************************
++ *
++ * MAC operations
++ *
++ *************************************************************************/
++static int falcon_reset_xmac(struct efx_nic *efx)
++{
++ efx_dword_t reg;
++ int count;
+
-+out:
-+ spin_unlock_irqrestore(&np->lock, flags);
++ EFX_POPULATE_DWORD_1(reg, XM_CORE_RST, 1);
++ falcon_xmac_writel(efx, ®, XM_GLB_CFG_REG_MAC);
+
-+ *link_up_p = link_up;
-+ return err;
++ for (count = 0; count < 10000; count++) { /* wait upto 100ms */
++ falcon_xmac_readl(efx, ®, XM_GLB_CFG_REG_MAC);
++ if (EFX_DWORD_FIELD(reg, XM_CORE_RST) == 0)
++ return 0;
++ udelay(10);
++ }
++
++ EFX_ERR(efx, "timed out waiting for XMAC core reset\n");
++ return -ETIMEDOUT;
+}
+
++/* Configure the XAUI driver that is an output from Falcon */
++static void falcon_setup_xaui(struct efx_nic *efx)
++{
++ efx_dword_t sdctl, txdrv;
+
- 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)
++ /* Move the XAUI into low power, unless there is no PHY, in
++ * which case the XAUI will have to drive a cable. */
++ if (efx->phy_type == PHY_TYPE_NONE)
++ return;
++
++ falcon_xmac_readl(efx, &sdctl, XX_SD_CTL_REG_MAC);
++ EFX_SET_DWORD_FIELD(sdctl, XX_HIDRVD, XX_SD_CTL_DRV_DEFAULT);
++ EFX_SET_DWORD_FIELD(sdctl, XX_LODRVD, XX_SD_CTL_DRV_DEFAULT);
++ EFX_SET_DWORD_FIELD(sdctl, XX_HIDRVC, XX_SD_CTL_DRV_DEFAULT);
++ EFX_SET_DWORD_FIELD(sdctl, XX_LODRVC, XX_SD_CTL_DRV_DEFAULT);
++ EFX_SET_DWORD_FIELD(sdctl, XX_HIDRVB, XX_SD_CTL_DRV_DEFAULT);
++ EFX_SET_DWORD_FIELD(sdctl, XX_LODRVB, XX_SD_CTL_DRV_DEFAULT);
++ EFX_SET_DWORD_FIELD(sdctl, XX_HIDRVA, XX_SD_CTL_DRV_DEFAULT);
++ EFX_SET_DWORD_FIELD(sdctl, XX_LODRVA, XX_SD_CTL_DRV_DEFAULT);
++ falcon_xmac_writel(efx, &sdctl, XX_SD_CTL_REG_MAC);
++
++ EFX_POPULATE_DWORD_8(txdrv,
++ XX_DEQD, XX_TXDRV_DEQ_DEFAULT,
++ XX_DEQC, XX_TXDRV_DEQ_DEFAULT,
++ XX_DEQB, XX_TXDRV_DEQ_DEFAULT,
++ XX_DEQA, XX_TXDRV_DEQ_DEFAULT,
++ XX_DTXD, XX_TXDRV_DTX_DEFAULT,
++ XX_DTXC, XX_TXDRV_DTX_DEFAULT,
++ XX_DTXB, XX_TXDRV_DTX_DEFAULT,
++ XX_DTXA, XX_TXDRV_DTX_DEFAULT);
++ falcon_xmac_writel(efx, &txdrv, XX_TXDRV_CTL_REG_MAC);
++}
++
++static void falcon_hold_xaui_in_rst(struct efx_nic *efx)
++{
++ efx_dword_t reg;
++
++ EFX_ZERO_DWORD(reg);
++ EFX_SET_DWORD_FIELD(reg, XX_PWRDNA_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_PWRDNB_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_PWRDNC_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_PWRDND_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_RSTPLLAB_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_RSTPLLCD_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_RESETA_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_RESETB_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_RESETC_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_RESETD_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSRX_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSTX_EN, 1);
++ falcon_xmac_writel(efx, ®, XX_PWR_RST_REG_MAC);
++ udelay(10);
++}
++
++static int _falcon_reset_xaui_a(struct efx_nic *efx)
+{
-+ int err;
++ efx_dword_t reg;
+
++ falcon_hold_xaui_in_rst(efx);
++ falcon_xmac_readl(efx, ®, XX_PWR_RST_REG_MAC);
+
-+ 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;
++ /* Follow the RAMBUS XAUI data reset sequencing
++ * Channels A and B first: power down, reset PLL, reset, clear
++ */
++ EFX_SET_DWORD_FIELD(reg, XX_PWRDNA_EN, 0);
++ EFX_SET_DWORD_FIELD(reg, XX_PWRDNB_EN, 0);
++ falcon_xmac_writel(efx, ®, XX_PWR_RST_REG_MAC);
++ udelay(10);
+
-+ mdelay(1000);
++ EFX_SET_DWORD_FIELD(reg, XX_RSTPLLAB_EN, 0);
++ falcon_xmac_writel(efx, ®, XX_PWR_RST_REG_MAC);
++ udelay(10);
++
++ EFX_SET_DWORD_FIELD(reg, XX_RESETA_EN, 0);
++ EFX_SET_DWORD_FIELD(reg, XX_RESETB_EN, 0);
++ falcon_xmac_writel(efx, ®, XX_PWR_RST_REG_MAC);
++ udelay(10);
++
++ /* Channels C and D: power down, reset PLL, reset, clear */
++ EFX_SET_DWORD_FIELD(reg, XX_PWRDNC_EN, 0);
++ EFX_SET_DWORD_FIELD(reg, XX_PWRDND_EN, 0);
++ falcon_xmac_writel(efx, ®, XX_PWR_RST_REG_MAC);
++ udelay(10);
++
++ EFX_SET_DWORD_FIELD(reg, XX_RSTPLLCD_EN, 0);
++ falcon_xmac_writel(efx, ®, XX_PWR_RST_REG_MAC);
++ udelay(10);
++
++ EFX_SET_DWORD_FIELD(reg, XX_RESETC_EN, 0);
++ EFX_SET_DWORD_FIELD(reg, XX_RESETD_EN, 0);
++ falcon_xmac_writel(efx, ®, XX_PWR_RST_REG_MAC);
++ udelay(10);
++
++ /* Setup XAUI */
++ falcon_setup_xaui(efx);
++ udelay(10);
++
++ /* Take XGXS out of reset */
++ EFX_ZERO_DWORD(reg);
++ falcon_xmac_writel(efx, ®, XX_PWR_RST_REG_MAC);
++ udelay(10);
+
+ 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 _falcon_reset_xaui_b(struct efx_nic *efx)
++{
++ efx_dword_t reg;
++ int count;
+
-+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)
++ EFX_POPULATE_DWORD_1(reg, XX_RST_XX_EN, 1);
++ falcon_xmac_writel(efx, ®, XX_PWR_RST_REG_MAC);
++
++ /* Give some time for the link to establish */
++ for (count = 0; count < 1000; count++) { /* wait upto 10ms */
++ falcon_xmac_readl(efx, ®, XX_PWR_RST_REG_MAC);
++ if (EFX_DWORD_FIELD(reg, XX_RST_XX_EN) == 0) {
++ falcon_setup_xaui(efx);
++ return 0;
++ }
++ udelay(10);
++ }
++ EFX_ERR(efx, "timed out waiting for XAUI/XGXS reset\n");
++ return -ETIMEDOUT;
++}
++
++int falcon_reset_xaui(struct efx_nic *efx)
+{
-+ struct niu_link_config *lp = &np->link_config;
-+ int err;
++ int rc;
+
-+ err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
-+ MII_BMCR);
-+ if (err < 0)
-+ return err;
++ if (EFX_WORKAROUND_9388(efx)) {
++ falcon_hold_xaui_in_rst(efx);
++ efx->phy_op->reset_xaui(efx);
++ rc = _falcon_reset_xaui_a(efx);
++ } else {
++ rc = _falcon_reset_xaui_b(efx);
++ }
++ return rc;
++}
+
-+ err &= ~BMCR_LOOPBACK;
++static int falcon_xgmii_status(struct efx_nic *efx)
++{
++ efx_dword_t reg;
+
-+ if (lp->loopback_mode == LOOPBACK_MAC)
-+ err |= BMCR_LOOPBACK;
++ if (FALCON_REV(efx) < FALCON_REV_B0)
++ return 1;
+
-+ err = mdio_write(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
-+ MII_BMCR, err);
-+ if (err)
-+ return err;
++ /* The ISR latches, so clear it and re-read */
++ falcon_xmac_readl(efx, ®, XM_MGT_INT_REG_MAC_B0);
++ falcon_xmac_readl(efx, ®, XM_MGT_INT_REG_MAC_B0);
++
++ if (EFX_DWORD_FIELD(reg, XM_LCLFLT) ||
++ EFX_DWORD_FIELD(reg, XM_RMTFLT)) {
++ EFX_INFO(efx, "MGT_INT: "EFX_DWORD_FMT"\n", EFX_DWORD_VAL(reg));
++ return 0;
++ }
+
-+ return 0;
++ return 1;
+}
+
-+static int xcvr_init_10g_bcm8706(struct niu *np)
++static void falcon_mask_status_intr(struct efx_nic *efx, int enable)
+{
-+ int err = 0;
-+ u64 val;
++ efx_dword_t reg;
+
-+ if ((np->flags & NIU_FLAGS_HOTPLUG_PHY) &&
-+ (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) == 0)
-+ return err;
++ if (FALCON_REV(efx) < FALCON_REV_B0)
++ return;
+
-+ val = nr64_mac(XMAC_CONFIG);
-+ val &= ~XMAC_CONFIG_LED_POLARITY;
-+ val |= XMAC_CONFIG_FORCE_LED_ON;
-+ nw64_mac(XMAC_CONFIG, val);
++ /* Flush the ISR */
++ if (enable)
++ falcon_xmac_readl(efx, ®, XM_MGT_INT_REG_MAC_B0);
+
-+ val = nr64(MIF_CONFIG);
-+ val |= MIF_CONFIG_INDIRECT_MODE;
-+ nw64(MIF_CONFIG, val);
++ EFX_POPULATE_DWORD_2(reg,
++ XM_MSK_RMTFLT, !enable,
++ XM_MSK_LCLFLT, !enable);
++ falcon_xmac_writel(efx, ®, XM_MGT_INT_MSK_REG_MAC_B0);
++}
+
-+ err = bcm8704_reset(np);
-+ if (err)
-+ return err;
++int falcon_init_xmac(struct efx_nic *efx)
++{
++ int rc;
+
-+ err = xcvr_10g_set_lb_bcm870x(np);
-+ if (err)
-+ return err;
++ /* Initialize the PHY first so the clock is around */
++ rc = efx->phy_op->init(efx);
++ if (rc)
++ goto fail1;
+
-+ err = bcm8706_init_user_dev3(np);
-+ if (err)
-+ return err;
++ rc = falcon_reset_xaui(efx);
++ if (rc)
++ goto fail2;
+
-+ err = xcvr_diag_bcm870x(np);
-+ if (err)
-+ return err;
++ /* Wait again. Give the PHY and MAC time to come back */
++ schedule_timeout_uninterruptible(HZ / 10);
++
++ rc = falcon_reset_xmac(efx);
++ if (rc)
++ goto fail2;
+
++ falcon_mask_status_intr(efx, 1);
+ return 0;
++
++ fail2:
++ efx->phy_op->fini(efx);
++ fail1:
++ return rc;
+}
+
-+static int xcvr_init_10g_bcm8704(struct niu *np)
++int falcon_xaui_link_ok(struct efx_nic *efx)
+{
-+ int err;
++ efx_dword_t reg;
++ int align_done, sync_status, link_ok = 0;
+
-+ err = bcm8704_reset(np);
-+ if (err)
-+ return err;
++ /* Read link status */
++ falcon_xmac_readl(efx, ®, XX_CORE_STAT_REG_MAC);
+
-+ err = bcm8704_init_user_dev3(np);
-+ if (err)
-+ return err;
++ align_done = EFX_DWORD_FIELD(reg, XX_ALIGN_DONE);
++ sync_status = EFX_DWORD_FIELD(reg, XX_SYNC_STAT);
++ if (align_done && (sync_status == XX_SYNC_STAT_DECODE_SYNCED))
++ link_ok = 1;
++
++ /* Clear link status ready for next read */
++ EFX_SET_DWORD_FIELD(reg, XX_COMMA_DET, XX_COMMA_DET_RESET);
++ EFX_SET_DWORD_FIELD(reg, XX_CHARERR, XX_CHARERR_RESET);
++ EFX_SET_DWORD_FIELD(reg, XX_DISPERR, XX_DISPERR_RESET);
++ falcon_xmac_writel(efx, ®, XX_CORE_STAT_REG_MAC);
++
++ /* If the link is up, then check the phy side of the xaui link
++ * (error conditions from the wire side propoagate back through
++ * the phy to the xaui side). */
++ if (efx->link_up && link_ok) {
++ int has_phyxs = efx->phy_op->mmds & (1 << MDIO_MMD_PHYXS);
++ if (has_phyxs)
++ link_ok = mdio_clause45_phyxgxs_lane_sync(efx);
++ }
++
++ /* If the PHY and XAUI links are up, then check the mac's xgmii
++ * fault state */
++ if (efx->link_up && link_ok)
++ link_ok = falcon_xgmii_status(efx);
++
++ return link_ok;
++}
++
++static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
++{
++ unsigned int max_frame_len;
++ efx_dword_t reg;
++ int rx_fc = (efx->flow_control & EFX_FC_RX) ? 1 : 0;
++
++ /* Configure MAC - cut-thru mode is hard wired on */
++ EFX_POPULATE_DWORD_3(reg,
++ XM_RX_JUMBO_MODE, 1,
++ XM_TX_STAT_EN, 1,
++ XM_RX_STAT_EN, 1);
++ falcon_xmac_writel(efx, ®, XM_GLB_CFG_REG_MAC);
++
++ /* Configure TX */
++ EFX_POPULATE_DWORD_6(reg,
++ XM_TXEN, 1,
++ XM_TX_PRMBL, 1,
++ XM_AUTO_PAD, 1,
++ XM_TXCRC, 1,
++ XM_FCNTL, 1,
++ XM_IPG, 0x3);
++ falcon_xmac_writel(efx, ®, XM_TX_CFG_REG_MAC);
++
++ /* Configure RX */
++ EFX_POPULATE_DWORD_5(reg,
++ XM_RXEN, 1,
++ XM_AUTO_DEPAD, 0,
++ XM_ACPT_ALL_MCAST, 1,
++ XM_ACPT_ALL_UCAST, efx->promiscuous,
++ XM_PASS_CRC_ERR, 1);
++ falcon_xmac_writel(efx, ®, XM_RX_CFG_REG_MAC);
++
++ /* Set frame length */
++ max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu);
++ EFX_POPULATE_DWORD_1(reg, XM_MAX_RX_FRM_SIZE, max_frame_len);
++ falcon_xmac_writel(efx, ®, XM_RX_PARAM_REG_MAC);
++ EFX_POPULATE_DWORD_2(reg,
++ XM_MAX_TX_FRM_SIZE, max_frame_len,
++ XM_TX_JUMBO_MODE, 1);
++ falcon_xmac_writel(efx, ®, XM_TX_PARAM_REG_MAC);
++
++ EFX_POPULATE_DWORD_2(reg,
++ XM_PAUSE_TIME, 0xfffe, /* MAX PAUSE TIME */
++ XM_DIS_FCNTL, rx_fc ? 0 : 1);
++ falcon_xmac_writel(efx, ®, XM_FC_REG_MAC);
++
++ /* Set MAC address */
++ EFX_POPULATE_DWORD_4(reg,
++ XM_ADR_0, efx->net_dev->dev_addr[0],
++ XM_ADR_1, efx->net_dev->dev_addr[1],
++ XM_ADR_2, efx->net_dev->dev_addr[2],
++ XM_ADR_3, efx->net_dev->dev_addr[3]);
++ falcon_xmac_writel(efx, ®, XM_ADR_LO_REG_MAC);
++ EFX_POPULATE_DWORD_2(reg,
++ XM_ADR_4, efx->net_dev->dev_addr[4],
++ XM_ADR_5, efx->net_dev->dev_addr[5]);
++ falcon_xmac_writel(efx, ®, XM_ADR_HI_REG_MAC);
++}
++
++/* Try and bring the Falcon side of the Falcon-Phy XAUI link fails
++ * to come back up. Bash it until it comes back up */
++static int falcon_check_xaui_link_up(struct efx_nic *efx)
++{
++ int max_tries, tries;
++ tries = EFX_WORKAROUND_5147(efx) ? 5 : 1;
++ max_tries = tries;
+
-+ err = xcvr_10g_set_lb_bcm870x(np);
-+ if (err)
-+ return err;
++ if (efx->phy_type == PHY_TYPE_NONE)
++ return 0;
+
-+ err = xcvr_diag_bcm870x(np);
-+ if (err)
-+ return err;
++ while (tries) {
++ if (falcon_xaui_link_ok(efx))
++ return 1;
++
++ EFX_LOG(efx, "%s Clobbering XAUI (%d tries left).\n",
++ __func__, tries);
++ (void) falcon_reset_xaui(efx);
++ udelay(200);
++ tries--;
++ }
+
++ EFX_ERR(efx, "Failed to bring XAUI link back up in %d tries!\n",
++ max_tries);
+ 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;
- }
-
++void falcon_reconfigure_xmac(struct efx_nic *efx)
++{
++ int xaui_link_ok;
+
++ falcon_mask_status_intr(efx, 0);
+
-+static int xcvr_init_1g_rgmii(struct niu *np)
++ falcon_deconfigure_mac_wrapper(efx);
++ efx->phy_op->reconfigure(efx);
++ falcon_reconfigure_xmac_core(efx);
++ falcon_reconfigure_mac_wrapper(efx);
++
++ /* Ensure XAUI link is up */
++ xaui_link_ok = falcon_check_xaui_link_up(efx);
++
++ if (xaui_link_ok && efx->link_up)
++ falcon_mask_status_intr(efx, 1);
++}
++
++void falcon_fini_xmac(struct efx_nic *efx)
+{
-+ int err;
-+ u64 val;
-+ u16 bmcr, bmsr, estat;
++ /* Isolate the MAC - PHY */
++ falcon_deconfigure_mac_wrapper(efx);
+
-+ val = nr64(MIF_CONFIG);
-+ val &= ~MIF_CONFIG_INDIRECT_MODE;
-+ nw64(MIF_CONFIG, val);
++ /* Potentially power down the PHY */
++ efx->phy_op->fini(efx);
++}
+
-+ err = mii_reset(np);
-+ if (err)
-+ return err;
++void falcon_update_stats_xmac(struct efx_nic *efx)
++{
++ struct efx_mac_stats *mac_stats = &efx->mac_stats;
++ int rc;
+
-+ err = mii_read(np, np->phy_addr, MII_BMSR);
-+ if (err < 0)
-+ return err;
-+ bmsr = err;
++ rc = falcon_dma_stats(efx, XgDmaDone_offset);
++ if (rc)
++ return;
+
-+ estat = 0;
-+ if (bmsr & BMSR_ESTATEN) {
-+ err = mii_read(np, np->phy_addr, MII_ESTATUS);
-+ if (err < 0)
-+ return err;
-+ estat = err;
++ /* Update MAC stats from DMAed values */
++ FALCON_STAT(efx, XgRxOctets, rx_bytes);
++ FALCON_STAT(efx, XgRxOctetsOK, rx_good_bytes);
++ FALCON_STAT(efx, XgRxPkts, rx_packets);
++ FALCON_STAT(efx, XgRxPktsOK, rx_good);
++ FALCON_STAT(efx, XgRxBroadcastPkts, rx_broadcast);
++ FALCON_STAT(efx, XgRxMulticastPkts, rx_multicast);
++ FALCON_STAT(efx, XgRxUnicastPkts, rx_unicast);
++ FALCON_STAT(efx, XgRxUndersizePkts, rx_lt64);
++ FALCON_STAT(efx, XgRxOversizePkts, rx_gtjumbo);
++ FALCON_STAT(efx, XgRxJabberPkts, rx_bad_gtjumbo);
++ FALCON_STAT(efx, XgRxUndersizeFCSerrorPkts, rx_bad_lt64);
++ FALCON_STAT(efx, XgRxDropEvents, rx_overflow);
++ FALCON_STAT(efx, XgRxFCSerrorPkts, rx_bad);
++ FALCON_STAT(efx, XgRxAlignError, rx_align_error);
++ FALCON_STAT(efx, XgRxSymbolError, rx_symbol_error);
++ FALCON_STAT(efx, XgRxInternalMACError, rx_internal_error);
++ FALCON_STAT(efx, XgRxControlPkts, rx_control);
++ FALCON_STAT(efx, XgRxPausePkts, rx_pause);
++ FALCON_STAT(efx, XgRxPkts64Octets, rx_64);
++ FALCON_STAT(efx, XgRxPkts65to127Octets, rx_65_to_127);
++ FALCON_STAT(efx, XgRxPkts128to255Octets, rx_128_to_255);
++ FALCON_STAT(efx, XgRxPkts256to511Octets, rx_256_to_511);
++ FALCON_STAT(efx, XgRxPkts512to1023Octets, rx_512_to_1023);
++ FALCON_STAT(efx, XgRxPkts1024to15xxOctets, rx_1024_to_15xx);
++ FALCON_STAT(efx, XgRxPkts15xxtoMaxOctets, rx_15xx_to_jumbo);
++ FALCON_STAT(efx, XgRxLengthError, rx_length_error);
++ FALCON_STAT(efx, XgTxPkts, tx_packets);
++ FALCON_STAT(efx, XgTxOctets, tx_bytes);
++ FALCON_STAT(efx, XgTxMulticastPkts, tx_multicast);
++ FALCON_STAT(efx, XgTxBroadcastPkts, tx_broadcast);
++ FALCON_STAT(efx, XgTxUnicastPkts, tx_unicast);
++ FALCON_STAT(efx, XgTxControlPkts, tx_control);
++ FALCON_STAT(efx, XgTxPausePkts, tx_pause);
++ FALCON_STAT(efx, XgTxPkts64Octets, tx_64);
++ FALCON_STAT(efx, XgTxPkts65to127Octets, tx_65_to_127);
++ FALCON_STAT(efx, XgTxPkts128to255Octets, tx_128_to_255);
++ FALCON_STAT(efx, XgTxPkts256to511Octets, tx_256_to_511);
++ FALCON_STAT(efx, XgTxPkts512to1023Octets, tx_512_to_1023);
++ FALCON_STAT(efx, XgTxPkts1024to15xxOctets, tx_1024_to_15xx);
++ FALCON_STAT(efx, XgTxPkts1519toMaxOctets, tx_15xx_to_jumbo);
++ FALCON_STAT(efx, XgTxUndersizePkts, tx_lt64);
++ FALCON_STAT(efx, XgTxOversizePkts, tx_gtjumbo);
++ FALCON_STAT(efx, XgTxNonTcpUdpPkt, tx_non_tcpudp);
++ FALCON_STAT(efx, XgTxMacSrcErrPkt, tx_mac_src_error);
++ FALCON_STAT(efx, XgTxIpSrcErrPkt, tx_ip_src_error);
++
++ /* Update derived statistics */
++ mac_stats->tx_good_bytes =
++ (mac_stats->tx_bytes - mac_stats->tx_bad_bytes);
++ mac_stats->rx_bad_bytes =
++ (mac_stats->rx_bytes - mac_stats->rx_good_bytes);
++}
++
++#define EFX_XAUI_RETRAIN_MAX 8
++
++int falcon_check_xmac(struct efx_nic *efx)
++{
++ unsigned xaui_link_ok;
++ int rc;
++
++ falcon_mask_status_intr(efx, 0);
++ xaui_link_ok = falcon_xaui_link_ok(efx);
++
++ if (EFX_WORKAROUND_5147(efx) && !xaui_link_ok)
++ (void) falcon_reset_xaui(efx);
++
++ /* Call the PHY check_hw routine */
++ rc = efx->phy_op->check_hw(efx);
++
++ /* Unmask interrupt if everything was (and still is) ok */
++ if (xaui_link_ok && efx->link_up)
++ falcon_mask_status_intr(efx, 1);
++
++ return rc;
++}
++
++/* Simulate a PHY event */
++void falcon_xmac_sim_phy_event(struct efx_nic *efx)
++{
++ efx_qword_t phy_event;
++
++ EFX_POPULATE_QWORD_2(phy_event,
++ EV_CODE, GLOBAL_EV_DECODE,
++ XG_PHY_INTR, 1);
++ falcon_generate_event(&efx->channel[0], &phy_event);
++}
++
++int falcon_xmac_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
++{
++ mdio_clause45_get_settings(efx, ecmd);
++ ecmd->transceiver = XCVR_INTERNAL;
++ ecmd->phy_address = efx->mii.phy_id;
++ ecmd->autoneg = AUTONEG_DISABLE;
++ ecmd->duplex = DUPLEX_FULL;
++ return 0;
++}
++
++int falcon_xmac_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
++{
++ if (ecmd->transceiver != XCVR_INTERNAL)
++ return -EINVAL;
++ if (ecmd->autoneg != AUTONEG_DISABLE)
++ return -EINVAL;
++ if (ecmd->duplex != DUPLEX_FULL)
++ return -EINVAL;
++
++ return mdio_clause45_set_settings(efx, ecmd);
++}
++
++
++int falcon_xmac_set_pause(struct efx_nic *efx, enum efx_fc_type flow_control)
++{
++ int reset;
++
++ if (flow_control & EFX_FC_AUTO) {
++ EFX_LOG(efx, "10G does not support flow control "
++ "autonegotiation\n");
++ return -EINVAL;
+ }
+
-+ bmcr = 0;
-+ err = mii_write(np, np->phy_addr, MII_BMCR, bmcr);
-+ if (err)
-+ return err;
++ if ((flow_control & EFX_FC_TX) && !(flow_control & EFX_FC_RX))
++ return -EINVAL;
+
-+ if (bmsr & BMSR_ESTATEN) {
-+ u16 ctrl1000 = 0;
++ /* TX flow control may automatically turn itself off if the
++ * link partner (intermittently) stops responding to pause
++ * frames. There isn't any indication that this has happened,
++ * so the best we do is leave it up to the user to spot this
++ * and fix it be cycling transmit flow control on this end. */
++ reset = ((flow_control & EFX_FC_TX) &&
++ !(efx->flow_control & EFX_FC_TX));
++ if (EFX_WORKAROUND_11482(efx) && reset) {
++ if (FALCON_REV(efx) >= FALCON_REV_B0) {
++ /* Recover by resetting the EM block */
++ if (efx->link_up)
++ falcon_drain_tx_fifo(efx);
++ } else {
++ /* Schedule a reset to recover */
++ efx_schedule_reset(efx, RESET_TYPE_INVISIBLE);
++ }
++ }
+
-+ if (estat & ESTATUS_1000_TFULL)
-+ ctrl1000 |= ADVERTISE_1000FULL;
-+ err = mii_write(np, np->phy_addr, MII_CTRL1000, ctrl1000);
-+ if (err)
-+ return err;
++ efx->flow_control = flow_control;
++
++ return 0;
++}
+diff --git a/drivers/net/sfc/gmii.h b/drivers/net/sfc/gmii.h
+new file mode 100644
+index 0000000..d25bbd1
+--- /dev/null
++++ b/drivers/net/sfc/gmii.h
+@@ -0,0 +1,195 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005-2006 Fen Systems Ltd.
++ * Copyright 2006 Solarflare Communications 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, incorporated herein by reference.
++ */
++
++#ifndef EFX_GMII_H
++#define EFX_GMII_H
++
++/*
++ * GMII interface
++ */
++
++#include <linux/mii.h>
++
++/* GMII registers, excluding registers already defined as MII
++ * registers in mii.h
++ */
++#define GMII_IER 0x12 /* Interrupt enable register */
++#define GMII_ISR 0x13 /* Interrupt status register */
++
++/* Interrupt enable register */
++#define IER_ANEG_ERR 0x8000 /* Bit 15 - autonegotiation error */
++#define IER_SPEED_CHG 0x4000 /* Bit 14 - speed changed */
++#define IER_DUPLEX_CHG 0x2000 /* Bit 13 - duplex changed */
++#define IER_PAGE_RCVD 0x1000 /* Bit 12 - page received */
++#define IER_ANEG_DONE 0x0800 /* Bit 11 - autonegotiation complete */
++#define IER_LINK_CHG 0x0400 /* Bit 10 - link status changed */
++#define IER_SYM_ERR 0x0200 /* Bit 9 - symbol error */
++#define IER_FALSE_CARRIER 0x0100 /* Bit 8 - false carrier */
++#define IER_FIFO_ERR 0x0080 /* Bit 7 - FIFO over/underflow */
++#define IER_MDIX_CHG 0x0040 /* Bit 6 - MDI crossover changed */
++#define IER_DOWNSHIFT 0x0020 /* Bit 5 - downshift */
++#define IER_ENERGY 0x0010 /* Bit 4 - energy detect */
++#define IER_DTE_POWER 0x0004 /* Bit 2 - DTE power detect */
++#define IER_POLARITY_CHG 0x0002 /* Bit 1 - polarity changed */
++#define IER_JABBER 0x0001 /* Bit 0 - jabber */
++
++/* Interrupt status register */
++#define ISR_ANEG_ERR 0x8000 /* Bit 15 - autonegotiation error */
++#define ISR_SPEED_CHG 0x4000 /* Bit 14 - speed changed */
++#define ISR_DUPLEX_CHG 0x2000 /* Bit 13 - duplex changed */
++#define ISR_PAGE_RCVD 0x1000 /* Bit 12 - page received */
++#define ISR_ANEG_DONE 0x0800 /* Bit 11 - autonegotiation complete */
++#define ISR_LINK_CHG 0x0400 /* Bit 10 - link status changed */
++#define ISR_SYM_ERR 0x0200 /* Bit 9 - symbol error */
++#define ISR_FALSE_CARRIER 0x0100 /* Bit 8 - false carrier */
++#define ISR_FIFO_ERR 0x0080 /* Bit 7 - FIFO over/underflow */
++#define ISR_MDIX_CHG 0x0040 /* Bit 6 - MDI crossover changed */
++#define ISR_DOWNSHIFT 0x0020 /* Bit 5 - downshift */
++#define ISR_ENERGY 0x0010 /* Bit 4 - energy detect */
++#define ISR_DTE_POWER 0x0004 /* Bit 2 - DTE power detect */
++#define ISR_POLARITY_CHG 0x0002 /* Bit 1 - polarity changed */
++#define ISR_JABBER 0x0001 /* Bit 0 - jabber */
++
++/* Logically extended advertisement register */
++#define GM_ADVERTISE_SLCT ADVERTISE_SLCT
++#define GM_ADVERTISE_CSMA ADVERTISE_CSMA
++#define GM_ADVERTISE_10HALF ADVERTISE_10HALF
++#define GM_ADVERTISE_1000XFULL ADVERTISE_1000XFULL
++#define GM_ADVERTISE_10FULL ADVERTISE_10FULL
++#define GM_ADVERTISE_1000XHALF ADVERTISE_1000XHALF
++#define GM_ADVERTISE_100HALF ADVERTISE_100HALF
++#define GM_ADVERTISE_1000XPAUSE ADVERTISE_1000XPAUSE
++#define GM_ADVERTISE_100FULL ADVERTISE_100FULL
++#define GM_ADVERTISE_1000XPSE_ASYM ADVERTISE_1000XPSE_ASYM
++#define GM_ADVERTISE_100BASE4 ADVERTISE_100BASE4
++#define GM_ADVERTISE_PAUSE_CAP ADVERTISE_PAUSE_CAP
++#define GM_ADVERTISE_PAUSE_ASYM ADVERTISE_PAUSE_ASYM
++#define GM_ADVERTISE_RESV ADVERTISE_RESV
++#define GM_ADVERTISE_RFAULT ADVERTISE_RFAULT
++#define GM_ADVERTISE_LPACK ADVERTISE_LPACK
++#define GM_ADVERTISE_NPAGE ADVERTISE_NPAGE
++#define GM_ADVERTISE_1000FULL (ADVERTISE_1000FULL << 8)
++#define GM_ADVERTISE_1000HALF (ADVERTISE_1000HALF << 8)
++#define GM_ADVERTISE_1000 (GM_ADVERTISE_1000FULL | \
++ GM_ADVERTISE_1000HALF)
++#define GM_ADVERTISE_FULL (GM_ADVERTISE_1000FULL | \
++ ADVERTISE_FULL)
++#define GM_ADVERTISE_ALL (GM_ADVERTISE_1000FULL | \
++ GM_ADVERTISE_1000HALF | \
++ ADVERTISE_ALL)
++
++/* Logically extended link partner ability register */
++#define GM_LPA_SLCT LPA_SLCT
++#define GM_LPA_10HALF LPA_10HALF
++#define GM_LPA_1000XFULL LPA_1000XFULL
++#define GM_LPA_10FULL LPA_10FULL
++#define GM_LPA_1000XHALF LPA_1000XHALF
++#define GM_LPA_100HALF LPA_100HALF
++#define GM_LPA_1000XPAUSE LPA_1000XPAUSE
++#define GM_LPA_100FULL LPA_100FULL
++#define GM_LPA_1000XPAUSE_ASYM LPA_1000XPAUSE_ASYM
++#define GM_LPA_100BASE4 LPA_100BASE4
++#define GM_LPA_PAUSE_CAP LPA_PAUSE_CAP
++#define GM_LPA_PAUSE_ASYM LPA_PAUSE_ASYM
++#define GM_LPA_RESV LPA_RESV
++#define GM_LPA_RFAULT LPA_RFAULT
++#define GM_LPA_LPACK LPA_LPACK
++#define GM_LPA_NPAGE LPA_NPAGE
++#define GM_LPA_1000FULL (LPA_1000FULL << 6)
++#define GM_LPA_1000HALF (LPA_1000HALF << 6)
++#define GM_LPA_10000FULL 0x00040000
++#define GM_LPA_10000HALF 0x00080000
++#define GM_LPA_DUPLEX (GM_LPA_1000FULL | GM_LPA_10000FULL \
++ | LPA_DUPLEX)
++#define GM_LPA_10 (LPA_10FULL | LPA_10HALF)
++#define GM_LPA_100 LPA_100
++#define GM_LPA_1000 (GM_LPA_1000FULL | GM_LPA_1000HALF)
++#define GM_LPA_10000 (GM_LPA_10000FULL | GM_LPA_10000HALF)
++
++/* Retrieve GMII autonegotiation advertised abilities
++ *
++ * The MII advertisment register (MII_ADVERTISE) is logically extended
++ * to include advertisement bits ADVERTISE_1000FULL and
++ * ADVERTISE_1000HALF from MII_CTRL1000. The result can be tested
++ * against the GM_ADVERTISE_xxx constants.
++ */
++static inline unsigned int gmii_advertised(struct mii_if_info *gmii)
++{
++ unsigned int advertise;
++ unsigned int ctrl1000;
++
++ advertise = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_ADVERTISE);
++ ctrl1000 = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_CTRL1000);
++ return (((ctrl1000 << 8) & GM_ADVERTISE_1000) | advertise);
++}
++
++/* Retrieve GMII autonegotiation link partner abilities
++ *
++ * The MII link partner ability register (MII_LPA) is logically
++ * extended by adding bits LPA_1000HALF and LPA_1000FULL from
++ * MII_STAT1000. The result can be tested against the GM_LPA_xxx
++ * constants.
++ */
++static inline unsigned int gmii_lpa(struct mii_if_info *gmii)
++{
++ unsigned int lpa;
++ unsigned int stat1000;
++
++ lpa = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_LPA);
++ stat1000 = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_STAT1000);
++ return (((stat1000 << 6) & GM_LPA_1000) | lpa);
++}
++
++/* Calculate GMII autonegotiated link technology
++ *
++ * "negotiated" should be the result of gmii_advertised() logically
++ * ANDed with the result of gmii_lpa().
++ *
++ * "tech" will be negotiated with the unused bits masked out. For
++ * example, if both ends of the link are capable of both
++ * GM_LPA_1000FULL and GM_LPA_100FULL, GM_LPA_100FULL will be masked
++ * out.
++ */
++static inline unsigned int gmii_nway_result(unsigned int negotiated)
++{
++ unsigned int other_bits;
++
++ /* Mask out the speed and duplexity bits */
++ other_bits = negotiated & ~(GM_LPA_10 | GM_LPA_100 | GM_LPA_1000);
++
++ if (negotiated & GM_LPA_1000FULL)
++ return (other_bits | GM_LPA_1000FULL);
++ else if (negotiated & GM_LPA_1000HALF)
++ return (other_bits | GM_LPA_1000HALF);
++ else
++ return (other_bits | mii_nway_result(negotiated));
++}
++
++/* Calculate GMII non-autonegotiated link technology
++ *
++ * This provides an equivalent to gmii_nway_result for the case when
++ * autonegotiation is disabled.
++ */
++static inline unsigned int gmii_forced_result(unsigned int bmcr)
++{
++ unsigned int result;
++ int full_duplex;
++
++ full_duplex = bmcr & BMCR_FULLDPLX;
++ if (bmcr & BMCR_SPEED1000)
++ result = full_duplex ? GM_LPA_1000FULL : GM_LPA_1000HALF;
++ else if (bmcr & BMCR_SPEED100)
++ result = full_duplex ? GM_LPA_100FULL : GM_LPA_100HALF;
++ else
++ result = full_duplex ? GM_LPA_10FULL : GM_LPA_10HALF;
++ return result;
++}
++
++#endif /* EFX_GMII_H */
+diff --git a/drivers/net/sfc/i2c-direct.c b/drivers/net/sfc/i2c-direct.c
+new file mode 100644
+index 0000000..b6c62d0
+--- /dev/null
++++ b/drivers/net/sfc/i2c-direct.c
+@@ -0,0 +1,381 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005 Fen Systems Ltd.
++ * Copyright 2006-2008 Solarflare Communications 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, incorporated herein by reference.
++ */
++
++#include <linux/delay.h>
++#include "net_driver.h"
++#include "i2c-direct.h"
++
++/*
++ * I2C data (SDA) and clock (SCL) line read/writes with appropriate
++ * delays.
++ */
++
++static inline void setsda(struct efx_i2c_interface *i2c, int state)
++{
++ udelay(i2c->op->udelay);
++ i2c->sda = state;
++ i2c->op->setsda(i2c);
++ udelay(i2c->op->udelay);
++}
++
++static inline void setscl(struct efx_i2c_interface *i2c, int state)
++{
++ udelay(i2c->op->udelay);
++ i2c->scl = state;
++ i2c->op->setscl(i2c);
++ udelay(i2c->op->udelay);
++}
++
++static inline int getsda(struct efx_i2c_interface *i2c)
++{
++ int sda;
++
++ udelay(i2c->op->udelay);
++ sda = i2c->op->getsda(i2c);
++ udelay(i2c->op->udelay);
++ return sda;
++}
++
++static inline int getscl(struct efx_i2c_interface *i2c)
++{
++ int scl;
++
++ udelay(i2c->op->udelay);
++ scl = i2c->op->getscl(i2c);
++ udelay(i2c->op->udelay);
++ return scl;
++}
++
++/*
++ * I2C low-level protocol operations
++ *
++ */
++
++static inline void i2c_release(struct efx_i2c_interface *i2c)
++{
++ EFX_WARN_ON_PARANOID(!i2c->scl);
++ EFX_WARN_ON_PARANOID(!i2c->sda);
++ /* Devices may time out if operations do not end */
++ setscl(i2c, 1);
++ setsda(i2c, 1);
++ EFX_BUG_ON_PARANOID(getsda(i2c) != 1);
++ EFX_BUG_ON_PARANOID(getscl(i2c) != 1);
++}
++
++static inline void i2c_start(struct efx_i2c_interface *i2c)
++{
++ /* We may be restarting immediately after a {send,recv}_bit,
++ * so SCL will not necessarily already be high.
++ */
++ EFX_WARN_ON_PARANOID(!i2c->sda);
++ setscl(i2c, 1);
++ setsda(i2c, 0);
++ setscl(i2c, 0);
++ setsda(i2c, 1);
++}
++
++static inline void i2c_send_bit(struct efx_i2c_interface *i2c, int bit)
++{
++ EFX_WARN_ON_PARANOID(i2c->scl != 0);
++ setsda(i2c, bit);
++ setscl(i2c, 1);
++ setscl(i2c, 0);
++ setsda(i2c, 1);
++}
++
++static inline int i2c_recv_bit(struct efx_i2c_interface *i2c)
++{
++ int bit;
++
++ EFX_WARN_ON_PARANOID(i2c->scl != 0);
++ EFX_WARN_ON_PARANOID(!i2c->sda);
++ setscl(i2c, 1);
++ bit = getsda(i2c);
++ setscl(i2c, 0);
++ return bit;
++}
++
++static inline void i2c_stop(struct efx_i2c_interface *i2c)
++{
++ EFX_WARN_ON_PARANOID(i2c->scl != 0);
++ setsda(i2c, 0);
++ setscl(i2c, 1);
++ setsda(i2c, 1);
++}
++
++/*
++ * I2C mid-level protocol operations
++ *
++ */
++
++/* Sends a byte via the I2C bus and checks for an acknowledgement from
++ * the slave device.
++ */
++static int i2c_send_byte(struct efx_i2c_interface *i2c, u8 byte)
++{
++ int i;
++
++ /* Send byte */
++ for (i = 0; i < 8; i++) {
++ i2c_send_bit(i2c, !!(byte & 0x80));
++ byte <<= 1;
+ }
+
-+ bmcr = (BMCR_SPEED1000 | BMCR_FULLDPLX);
++ /* Check for acknowledgement from slave */
++ return (i2c_recv_bit(i2c) == 0 ? 0 : -EIO);
++}
+
-+ err = mii_write(np, np->phy_addr, MII_BMCR, bmcr);
-+ if (err)
-+ return err;
++/* Receives a byte via the I2C bus and sends ACK/NACK to the slave device. */
++static u8 i2c_recv_byte(struct efx_i2c_interface *i2c, int ack)
++{
++ u8 value = 0;
++ int i;
+
-+ err = mii_read(np, np->phy_addr, MII_BMCR);
-+ if (err < 0)
-+ return err;
-+ bmcr = mii_read(np, np->phy_addr, MII_BMCR);
++ /* Receive byte */
++ for (i = 0; i < 8; i++)
++ value = (value << 1) | i2c_recv_bit(i2c);
+
-+ err = mii_read(np, np->phy_addr, MII_BMSR);
-+ if (err < 0)
-+ return err;
++ /* Send ACK/NACK */
++ i2c_send_bit(i2c, (ack ? 0 : 1));
+
-+ return 0;
++ return value;
+}
+
++/* Calculate command byte for a read operation */
++static inline u8 i2c_read_cmd(u8 device_id)
++{
++ return ((device_id << 1) | 1);
++}
+
- 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)
++/* Calculate command byte for a write operation */
++static inline u8 i2c_write_cmd(u8 device_id)
+{
-+ int err, link_up;
-+ link_up = 0;
++ return ((device_id << 1) | 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;
++int efx_i2c_check_presence(struct efx_i2c_interface *i2c, u8 device_id)
++{
++ int rc;
++
++ /* If someone is driving the bus low we just give up. */
++ if (getsda(i2c) == 0 || getscl(i2c) == 0) {
++ EFX_ERR(i2c->efx, "%s someone is holding the I2C bus low."
++ " Giving up.\n", __func__);
++ return -EFAULT;
+ }
+
-+ err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
-+ BCM8704_PCS_10G_R_STATUS);
-+ if (err < 0)
++ /* Pretend to initiate a device write */
++ i2c_start(i2c);
++ rc = i2c_send_byte(i2c, i2c_write_cmd(device_id));
++ if (rc)
+ goto out;
+
-+ if (!(err & PCS_10G_R_STATUS_BLK_LOCK)) {
-+ err = 0;
++ out:
++ i2c_stop(i2c);
++ i2c_release(i2c);
++
++ return rc;
++}
++
++/* This performs a fast read of one or more consecutive bytes from an
++ * I2C device. Not all devices support consecutive reads of more than
++ * one byte; for these devices use efx_i2c_read() instead.
++ */
++int efx_i2c_fast_read(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset, u8 *data, unsigned int len)
++{
++ int i;
++ int rc;
++
++ EFX_WARN_ON_PARANOID(getsda(i2c) != 1);
++ EFX_WARN_ON_PARANOID(getscl(i2c) != 1);
++ EFX_WARN_ON_PARANOID(data == NULL);
++ EFX_WARN_ON_PARANOID(len < 1);
++
++ /* Select device and starting offset */
++ i2c_start(i2c);
++ rc = i2c_send_byte(i2c, i2c_write_cmd(device_id));
++ if (rc)
++ goto out;
++ rc = i2c_send_byte(i2c, offset);
++ if (rc)
+ goto out;
-+ }
+
-+ err = mdio_read(np, np->phy_addr, BCM8704_PHYXS_DEV_ADDR,
-+ BCM8704_PHYXS_XGXS_LANE_STAT);
-+ if (err < 0)
++ /* Read data from device */
++ i2c_start(i2c);
++ rc = i2c_send_byte(i2c, i2c_read_cmd(device_id));
++ if (rc)
+ 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;
++ for (i = 0; i < (len - 1); i++)
++ /* Read and acknowledge all but the last byte */
++ data[i] = i2c_recv_byte(i2c, 1);
++ /* Read last byte with no acknowledgement */
++ data[i] = i2c_recv_byte(i2c, 0);
++
++ out:
++ i2c_stop(i2c);
++ i2c_release(i2c);
++
++ return rc;
++}
++
++/* This performs a fast write of one or more consecutive bytes to an
++ * I2C device. Not all devices support consecutive writes of more
++ * than one byte; for these devices use efx_i2c_write() instead.
++ */
++int efx_i2c_fast_write(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset,
++ const u8 *data, unsigned int len)
++{
++ int i;
++ int rc;
++
++ EFX_WARN_ON_PARANOID(getsda(i2c) != 1);
++ EFX_WARN_ON_PARANOID(getscl(i2c) != 1);
++ EFX_WARN_ON_PARANOID(len < 1);
++
++ /* Select device and starting offset */
++ i2c_start(i2c);
++ rc = i2c_send_byte(i2c, i2c_write_cmd(device_id));
++ if (rc)
+ goto out;
++ rc = i2c_send_byte(i2c, offset);
++ if (rc)
++ goto out;
++
++ /* Write data to device */
++ for (i = 0; i < len; i++) {
++ rc = i2c_send_byte(i2c, data[i]);
++ if (rc)
++ goto out;
+ }
+
-+ link_up = 1;
-+ np->link_config.active_speed = SPEED_10000;
-+ np->link_config.active_duplex = DUPLEX_FULL;
-+ err = 0;
++ out:
++ i2c_stop(i2c);
++ i2c_release(i2c);
+
-+out:
-+ *link_up_p = link_up;
-+ if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
-+ err = 0;
-+ return err;
++ return rc;
+}
+
- 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)
++/* I2C byte-by-byte read */
++int efx_i2c_read(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset, u8 *data, unsigned int len)
+{
-+ u64 sig, mask, val;
++ int rc;
+
-+ 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;
++ /* i2c_fast_read with length 1 is a single byte read */
++ for (; len > 0; offset++, data++, len--) {
++ rc = efx_i2c_fast_read(i2c, device_id, offset, data, 1);
++ if (rc)
++ return rc;
++ }
+
-+ 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;
++ return 0;
++}
+
-+ default:
-+ return 0;
++/* I2C byte-by-byte write */
++int efx_i2c_write(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset, const u8 *data, unsigned int len)
++{
++ int rc;
++
++ /* i2c_fast_write with length 1 is a single byte write */
++ for (; len > 0; offset++, data++, len--) {
++ rc = efx_i2c_fast_write(i2c, device_id, offset, data, 1);
++ if (rc)
++ return rc;
++ mdelay(i2c->op->mdelay);
+ }
+
-+ if ((sig & mask) != val)
-+ return 0;
-+ return 1;
++ return 0;
+}
+
-+static int link_status_10g_hotplug(struct niu *np, int *link_up_p)
++
++/* This is just a slightly neater wrapper round efx_i2c_fast_write
++ * in the case where the target doesn't take an offset
++ */
++int efx_i2c_send_bytes(struct efx_i2c_interface *i2c,
++ u8 device_id, const u8 *data, unsigned int len)
+{
-+ unsigned long flags;
-+ int err = 0;
-+ int phy_present;
-+ int phy_present_prev;
++ return efx_i2c_fast_write(i2c, device_id, data[0], data + 1, len - 1);
++}
+
-+ spin_lock_irqsave(&np->lock, flags);
++/* I2C receiving of bytes - does not send an offset byte */
++int efx_i2c_recv_bytes(struct efx_i2c_interface *i2c, u8 device_id,
++ u8 *bytes, unsigned int len)
++{
++ int i;
++ int rc;
+
-+ 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);
-+ }
++ EFX_WARN_ON_PARANOID(getsda(i2c) != 1);
++ EFX_WARN_ON_PARANOID(getscl(i2c) != 1);
++ EFX_WARN_ON_PARANOID(len < 1);
+
-+ spin_unlock_irqrestore(&np->lock, flags);
++ /* Select device */
++ i2c_start(i2c);
+
-+ return err;
-+}
++ /* Read data from device */
++ rc = i2c_send_byte(i2c, i2c_read_cmd(device_id));
++ if (rc)
++ goto out;
+
- 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,
-+};
++ for (i = 0; i < (len - 1); i++)
++ /* Read and acknowledge all but the last byte */
++ bytes[i] = i2c_recv_byte(i2c, 1);
++ /* Read last byte with no acknowledgement */
++ bytes[i] = i2c_recv_byte(i2c, 0);
+
-+static const struct niu_phy_ops phy_ops_1g_rgmii = {
-+ .xcvr_init = xcvr_init_1g_rgmii,
-+ .link_status = link_status_1g_rgmii,
-+};
++ out:
++ i2c_stop(i2c);
++ i2c_release(i2c);
+
- 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,
-+};
++ return rc;
++}
+
- 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,
-+};
++/* SMBus and some I2C devices will time out if the I2C clock is
++ * held low for too long. This is most likely to happen in virtualised
++ * systems (when the entire domain is descheduled) but could in
++ * principle happen due to preemption on any busy system (and given the
++ * potential length of an I2C operation turning preemption off is not
++ * a sensible option). The following functions deal with the failure by
++ * retrying up to a fixed number of times.
++ */
+
- 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,
-+};
++#define I2C_MAX_RETRIES (10)
+
-+static const struct niu_phy_template phy_template_10g_serdes = {
-+ .ops = &phy_ops_10g_serdes,
-+ .phy_addr_base = 0,
-+};
++/* The timeout problem will result in -EIO. If the wrapped function
++ * returns any other error, pass this up and do not retry. */
++#define RETRY_WRAPPER(_f) \
++ int retries = I2C_MAX_RETRIES; \
++ int rc; \
++ while (retries) { \
++ rc = _f; \
++ if (rc != -EIO) \
++ return rc; \
++ retries--; \
++ } \
++ return rc; \
+
-+static int niu_atca_port_num[4] = {
-+ 0, 0, 11, 10
-+};
++int efx_i2c_check_presence_retry(struct efx_i2c_interface *i2c, u8 device_id)
++{
++ RETRY_WRAPPER(efx_i2c_check_presence(i2c, device_id))
++}
+
-+static int serdes_init_10g_serdes(struct niu *np)
++int efx_i2c_read_retry(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset, u8 *data, unsigned int len)
+{
-+ 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;
++ RETRY_WRAPPER(efx_i2c_read(i2c, device_id, offset, data, len))
++}
+
-+ 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;
++int efx_i2c_write_retry(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset, const u8 *data, unsigned int len)
++{
++ RETRY_WRAPPER(efx_i2c_write(i2c, device_id, offset, data, len))
++}
+diff --git a/drivers/net/sfc/i2c-direct.h b/drivers/net/sfc/i2c-direct.h
+new file mode 100644
+index 0000000..291e561
+--- /dev/null
++++ b/drivers/net/sfc/i2c-direct.h
+@@ -0,0 +1,91 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005 Fen Systems Ltd.
++ * Copyright 2006 Solarflare Communications 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, incorporated herein by reference.
++ */
+
-+ 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;
++#ifndef EFX_I2C_DIRECT_H
++#define EFX_I2C_DIRECT_H
+
-+ 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));
-+ }
++#include "net_driver.h"
+
-+ esr_reset(np);
-+ nw64(pll_cfg, ENET_SERDES_PLL_FBDIV2);
-+ nw64(ctrl_reg, ctrl_val);
-+ nw64(test_cfg_reg, test_cfg_val);
++/*
++ * Direct control of an I2C bus
++ */
+
-+ /* Initialize all 4 lanes of the SERDES. */
-+ for (i = 0; i < 4; i++) {
-+ u32 rxtx_ctrl, glue0;
++struct efx_i2c_interface;
+
-+ err = esr_read_rxtx_ctrl(np, i, &rxtx_ctrl);
-+ if (err)
-+ return err;
-+ err = esr_read_glue0(np, i, &glue0);
-+ if (err)
-+ return err;
++/**
++ * struct efx_i2c_bit_operations - I2C bus direct control methods
++ *
++ * I2C bus direct control methods.
++ *
++ * @setsda: Set state of SDA line
++ * @setscl: Set state of SCL line
++ * @getsda: Get state of SDA line
++ * @getscl: Get state of SCL line
++ * @udelay: Delay between each bit operation
++ * @mdelay: Delay between each byte write
++ */
++struct efx_i2c_bit_operations {
++ void (*setsda) (struct efx_i2c_interface *i2c);
++ void (*setscl) (struct efx_i2c_interface *i2c);
++ int (*getsda) (struct efx_i2c_interface *i2c);
++ int (*getscl) (struct efx_i2c_interface *i2c);
++ unsigned int udelay;
++ unsigned int mdelay;
++};
+
-+ rxtx_ctrl &= ~(ESR_RXTX_CTRL_VMUXLO);
-+ rxtx_ctrl |= (ESR_RXTX_CTRL_ENSTRETCH |
-+ (2 << ESR_RXTX_CTRL_VMUXLO_SHIFT));
++/**
++ * struct efx_i2c_interface - an I2C interface
++ *
++ * An I2C interface.
++ *
++ * @efx: Attached Efx NIC
++ * @op: I2C bus control methods
++ * @sda: Current output state of SDA line
++ * @scl: Current output state of SCL line
++ */
++struct efx_i2c_interface {
++ struct efx_nic *efx;
++ struct efx_i2c_bit_operations *op;
++ unsigned int sda:1;
++ unsigned int scl:1;
++};
++
++extern int efx_i2c_check_presence(struct efx_i2c_interface *i2c, u8 device_id);
++extern int efx_i2c_fast_read(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset,
++ u8 *data, unsigned int len);
++extern int efx_i2c_fast_write(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset,
++ const u8 *data, unsigned int len);
++extern int efx_i2c_read(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset, u8 *data, unsigned int len);
++extern int efx_i2c_write(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset,
++ const u8 *data, unsigned int len);
++
++extern int efx_i2c_send_bytes(struct efx_i2c_interface *i2c, u8 device_id,
++ const u8 *bytes, unsigned int len);
++
++extern int efx_i2c_recv_bytes(struct efx_i2c_interface *i2c, u8 device_id,
++ u8 *bytes, unsigned int len);
++
++
++/* Versions of the API that retry on failure. */
++extern int efx_i2c_check_presence_retry(struct efx_i2c_interface *i2c,
++ u8 device_id);
++
++extern int efx_i2c_read_retry(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset, u8 *data, unsigned int len);
++
++extern int efx_i2c_write_retry(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset,
++ const u8 *data, unsigned int len);
+
-+ 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));
++#endif /* EFX_I2C_DIRECT_H */
+diff --git a/drivers/net/sfc/mac.h b/drivers/net/sfc/mac.h
+new file mode 100644
+index 0000000..edd07d4
+--- /dev/null
++++ b/drivers/net/sfc/mac.h
+@@ -0,0 +1,33 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005-2006 Fen Systems Ltd.
++ * Copyright 2006-2007 Solarflare Communications 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, incorporated herein by reference.
++ */
+
-+ err = esr_write_rxtx_ctrl(np, i, rxtx_ctrl);
-+ if (err)
-+ return err;
-+ err = esr_write_glue0(np, i, glue0);
-+ if (err)
-+ return err;
-+ }
++#ifndef EFX_MAC_H
++#define EFX_MAC_H
+
++#include "net_driver.h"
+
-+ 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;
++extern void falcon_xmac_writel(struct efx_nic *efx,
++ efx_dword_t *value, unsigned int mac_reg);
++extern void falcon_xmac_readl(struct efx_nic *efx,
++ efx_dword_t *value, unsigned int mac_reg);
++extern int falcon_init_xmac(struct efx_nic *efx);
++extern void falcon_reconfigure_xmac(struct efx_nic *efx);
++extern void falcon_update_stats_xmac(struct efx_nic *efx);
++extern void falcon_fini_xmac(struct efx_nic *efx);
++extern int falcon_check_xmac(struct efx_nic *efx);
++extern void falcon_xmac_sim_phy_event(struct efx_nic *efx);
++extern int falcon_xmac_get_settings(struct efx_nic *efx,
++ struct ethtool_cmd *ecmd);
++extern int falcon_xmac_set_settings(struct efx_nic *efx,
++ struct ethtool_cmd *ecmd);
++extern int falcon_xmac_set_pause(struct efx_nic *efx,
++ enum efx_fc_type pause_params);
+
-+ 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;
++#endif
+diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c
+new file mode 100644
+index 0000000..dc06bb0
+--- /dev/null
++++ b/drivers/net/sfc/mdio_10g.c
+@@ -0,0 +1,282 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2006-2008 Solarflare Communications 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, incorporated herein by reference.
++ */
++/*
++ * Useful functions for working with MDIO clause 45 PHYs
++ */
++#include <linux/types.h>
++#include <linux/ethtool.h>
++#include <linux/delay.h>
++#include "net_driver.h"
++#include "mdio_10g.h"
++#include "boards.h"
+
-+ default:
-+ return -EINVAL;
++int mdio_clause45_reset_mmd(struct efx_nic *port, int mmd,
++ int spins, int spintime)
++{
++ u32 ctrl;
++ int phy_id = port->mii.phy_id;
++
++ /* Catch callers passing values in the wrong units (or just silly) */
++ EFX_BUG_ON_PARANOID(spins * spintime >= 5000);
++
++ mdio_clause45_write(port, phy_id, mmd, MDIO_MMDREG_CTRL1,
++ (1 << MDIO_MMDREG_CTRL1_RESET_LBN));
++ /* Wait for the reset bit to clear. */
++ do {
++ msleep(spintime);
++ ctrl = mdio_clause45_read(port, phy_id, mmd, MDIO_MMDREG_CTRL1);
++ spins--;
++
++ } while (spins && (ctrl & (1 << MDIO_MMDREG_CTRL1_RESET_LBN)));
++
++ return spins ? spins : -ETIMEDOUT;
++}
++
++static int mdio_clause45_check_mmd(struct efx_nic *efx, int mmd,
++ int fault_fatal)
++{
++ int status;
++ int phy_id = efx->mii.phy_id;
++
++ /* Read MMD STATUS2 to check it is responding. */
++ status = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_STAT2);
++ if (((status >> MDIO_MMDREG_STAT2_PRESENT_LBN) &
++ ((1 << MDIO_MMDREG_STAT2_PRESENT_WIDTH) - 1)) !=
++ MDIO_MMDREG_STAT2_PRESENT_VAL) {
++ EFX_ERR(efx, "PHY MMD %d not responding.\n", mmd);
++ return -EIO;
+ }
+
-+ 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;
++ /* Read MMD STATUS 1 to check for fault. */
++ status = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_STAT1);
++ if ((status & (1 << MDIO_MMDREG_STAT1_FAULT_LBN)) != 0) {
++ if (fault_fatal) {
++ EFX_ERR(efx, "PHY MMD %d reporting fatal"
++ " fault: status %x\n", mmd, status);
++ return -EIO;
++ } else {
++ EFX_LOG(efx, "PHY MMD %d reporting status"
++ " %x (expected)\n", mmd, status);
+ }
+ }
-+
+ 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;
++/* This ought to be ridiculous overkill. We expect it to fail rarely */
++#define MDIO45_RESET_TIME 1000 /* ms */
++#define MDIO45_RESET_ITERS 100
++
++int mdio_clause45_wait_reset_mmds(struct efx_nic *efx,
++ unsigned int mmd_mask)
++{
++ const int spintime = MDIO45_RESET_TIME / MDIO45_RESET_ITERS;
++ int tries = MDIO45_RESET_ITERS;
++ int rc = 0;
++ int in_reset;
++
++ while (tries) {
++ int mask = mmd_mask;
++ int mmd = 0;
++ int stat;
++ in_reset = 0;
++ while (mask) {
++ if (mask & 1) {
++ stat = mdio_clause45_read(efx,
++ efx->mii.phy_id,
++ mmd,
++ MDIO_MMDREG_CTRL1);
++ if (stat < 0) {
++ EFX_ERR(efx, "failed to read status of"
++ " MMD %d\n", mmd);
++ return -EIO;
++ }
++ if (stat & (1 << MDIO_MMDREG_CTRL1_RESET_LBN))
++ in_reset |= (1 << mmd);
+ }
++ mask = mask >> 1;
++ mmd++;
++ }
++ if (!in_reset)
+ break;
++ tries--;
++ msleep(spintime);
++ }
++ if (in_reset != 0) {
++ EFX_ERR(efx, "not all MMDs came out of reset in time."
++ " MMDs still in reset: %x\n", in_reset);
++ rc = -ETIMEDOUT;
++ }
++ return rc;
++}
+
-+ 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);
++int mdio_clause45_check_mmds(struct efx_nic *efx,
++ unsigned int mmd_mask, unsigned int fatal_mask)
++{
++ int devices, mmd = 0;
++ int probe_mmd;
++
++ /* Historically we have probed the PHYXS to find out what devices are
++ * present,but that doesn't work so well if the PHYXS isn't expected
++ * to exist, if so just find the first item in the list supplied. */
++ probe_mmd = (mmd_mask & MDIO_MMDREG_DEVS0_PHYXS) ? MDIO_MMD_PHYXS :
++ __ffs(mmd_mask);
++ devices = mdio_clause45_read(efx, efx->mii.phy_id,
++ probe_mmd, MDIO_MMDREG_DEVS0);
++
++ /* Check all the expected MMDs are present */
++ if (devices < 0) {
++ EFX_ERR(efx, "failed to read devices present\n");
++ return -EIO;
++ }
++ if ((devices & mmd_mask) != mmd_mask) {
++ EFX_ERR(efx, "required MMDs not present: got %x, "
++ "wanted %x\n", devices, mmd_mask);
++ return -ENODEV;
+ }
++ EFX_TRACE(efx, "Devices present: %x\n", devices);
+
- 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);
++ /* Check all required MMDs are responding and happy. */
++ while (mmd_mask) {
++ if (mmd_mask & 1) {
++ int fault_fatal = fatal_mask & 1;
++ if (mdio_clause45_check_mmd(efx, mmd, fault_fatal))
++ return -EIO;
++ }
++ mmd_mask = mmd_mask >> 1;
++ fatal_mask = fatal_mask >> 1;
++ mmd++;
+ }
- }
-
- 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);
++
++ return 0;
++}
++
++int mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
++{
++ int phy_id = efx->mii.phy_id;
++ int status;
++ int ok = 1;
++ int mmd = 0;
++ int good;
++
++ while (mmd_mask) {
++ if (mmd_mask & 1) {
++ /* Double reads because link state is latched, and a
++ * read moves the current state into the register */
++ status = mdio_clause45_read(efx, phy_id,
++ mmd, MDIO_MMDREG_STAT1);
++ status = mdio_clause45_read(efx, phy_id,
++ mmd, MDIO_MMDREG_STAT1);
++
++ good = status & (1 << MDIO_MMDREG_STAT1_LINK_LBN);
++ ok = ok && good;
++ }
++ mmd_mask = (mmd_mask >> 1);
++ mmd++;
+ }
- }
-
- 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;
-
++ return ok;
++}
+
-+ 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);
++/**
++ * mdio_clause45_get_settings - Read (some of) the PHY settings over MDIO.
++ * @efx: Efx NIC
++ * @ecmd: Buffer for settings
++ *
++ * On return the 'port', 'speed', 'supported' and 'advertising' fields of
++ * ecmd have been filled out based on the PMA type.
++ */
++void mdio_clause45_get_settings(struct efx_nic *efx,
++ struct ethtool_cmd *ecmd)
++{
++ int pma_type;
++
++ /* If no PMA is present we are presumably talking something XAUI-ish
++ * like CX4. Which we report as FIBRE (see below) */
++ if ((efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_PMAPMD)) == 0) {
++ ecmd->speed = SPEED_10000;
++ ecmd->port = PORT_FIBRE;
++ ecmd->supported = SUPPORTED_FIBRE;
++ ecmd->advertising = ADVERTISED_FIBRE;
++ return;
++ }
++
++ pma_type = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PMAPMD, MDIO_MMDREG_CTRL2);
++ pma_type &= MDIO_PMAPMD_CTRL2_TYPE_MASK;
++
++ switch (pma_type) {
++ /* We represent CX4 as fibre in the absence of anything
++ better. */
++ case MDIO_PMAPMD_CTRL2_10G_CX4:
++ ecmd->speed = SPEED_10000;
++ ecmd->port = PORT_FIBRE;
++ ecmd->supported = SUPPORTED_FIBRE;
++ ecmd->advertising = ADVERTISED_FIBRE;
++ break;
++ /* 10G Base-T */
++ case MDIO_PMAPMD_CTRL2_10G_BT:
++ ecmd->speed = SPEED_10000;
++ ecmd->port = PORT_TP;
++ ecmd->supported = SUPPORTED_TP | SUPPORTED_10000baseT_Full;
++ ecmd->advertising = (ADVERTISED_FIBRE
++ | ADVERTISED_10000baseT_Full);
++ break;
++ case MDIO_PMAPMD_CTRL2_1G_BT:
++ ecmd->speed = SPEED_1000;
++ ecmd->port = PORT_TP;
++ ecmd->supported = SUPPORTED_TP | SUPPORTED_1000baseT_Full;
++ ecmd->advertising = (ADVERTISED_FIBRE
++ | ADVERTISED_1000baseT_Full);
++ break;
++ case MDIO_PMAPMD_CTRL2_100_BT:
++ ecmd->speed = SPEED_100;
++ ecmd->port = PORT_TP;
++ ecmd->supported = SUPPORTED_TP | SUPPORTED_100baseT_Full;
++ ecmd->advertising = (ADVERTISED_FIBRE
++ | ADVERTISED_100baseT_Full);
++ break;
++ case MDIO_PMAPMD_CTRL2_10_BT:
++ ecmd->speed = SPEED_10;
++ ecmd->port = PORT_TP;
++ ecmd->supported = SUPPORTED_TP | SUPPORTED_10baseT_Full;
++ ecmd->advertising = ADVERTISED_FIBRE | ADVERTISED_10baseT_Full;
++ break;
++ /* All the other defined modes are flavours of
++ * 10G optical */
++ default:
++ ecmd->speed = SPEED_10000;
++ ecmd->port = PORT_FIBRE;
++ ecmd->supported = SUPPORTED_FIBRE;
++ ecmd->advertising = ADVERTISED_FIBRE;
+ 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
++/**
++ * mdio_clause45_set_settings - Set (some of) the PHY settings over MDIO.
++ * @efx: Efx NIC
++ * @ecmd: New settings
++ *
++ * Currently this just enforces that we are _not_ changing the
++ * 'port', 'speed', 'supported' or 'advertising' settings as these
++ * cannot be changed on any currently supported PHY.
++ */
++int mdio_clause45_set_settings(struct efx_nic *efx,
++ struct ethtool_cmd *ecmd)
++{
++ struct ethtool_cmd tmpcmd;
++ mdio_clause45_get_settings(efx, &tmpcmd);
++ /* None of the current PHYs support more than one mode
++ * of operation (and only 10GBT ever will), so keep things
++ * simple for now */
++ if ((ecmd->speed == tmpcmd.speed) && (ecmd->port == tmpcmd.port) &&
++ (ecmd->supported == tmpcmd.supported) &&
++ (ecmd->advertising == tmpcmd.advertising))
++ return 0;
++ return -EOPNOTSUPP;
++}
+diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h
+new file mode 100644
+index 0000000..2214b6d
+--- /dev/null
++++ b/drivers/net/sfc/mdio_10g.h
+@@ -0,0 +1,232 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2006-2008 Solarflare Communications Inc.
+ *
-+ * 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
++ * 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, incorporated herein by reference.
+ */
-+static int niu_board_model_match(struct niu *np, const char *model)
++
++#ifndef EFX_MDIO_10G_H
++#define EFX_MDIO_10G_H
++
++/*
++ * Definitions needed for doing 10G MDIO as specified in clause 45
++ * MDIO, which do not appear in Linux yet. Also some helper functions.
++ */
++
++#include "efx.h"
++#include "boards.h"
++
++/* Numbering of the MDIO Manageable Devices (MMDs) */
++/* Physical Medium Attachment/ Physical Medium Dependent sublayer */
++#define MDIO_MMD_PMAPMD (1)
++/* WAN Interface Sublayer */
++#define MDIO_MMD_WIS (2)
++/* Physical Coding Sublayer */
++#define MDIO_MMD_PCS (3)
++/* PHY Extender Sublayer */
++#define MDIO_MMD_PHYXS (4)
++/* Extender Sublayer */
++#define MDIO_MMD_DTEXS (5)
++/* Transmission convergence */
++#define MDIO_MMD_TC (6)
++/* Auto negotiation */
++#define MDIO_MMD_AN (7)
++
++/* Generic register locations */
++#define MDIO_MMDREG_CTRL1 (0)
++#define MDIO_MMDREG_STAT1 (1)
++#define MDIO_MMDREG_IDHI (2)
++#define MDIO_MMDREG_IDLOW (3)
++#define MDIO_MMDREG_SPEED (4)
++#define MDIO_MMDREG_DEVS0 (5)
++#define MDIO_MMDREG_DEVS1 (6)
++#define MDIO_MMDREG_CTRL2 (7)
++#define MDIO_MMDREG_STAT2 (8)
++
++/* Bits in MMDREG_CTRL1 */
++/* Reset */
++#define MDIO_MMDREG_CTRL1_RESET_LBN (15)
++#define MDIO_MMDREG_CTRL1_RESET_WIDTH (1)
++
++/* Bits in MMDREG_STAT1 */
++#define MDIO_MMDREG_STAT1_FAULT_LBN (7)
++#define MDIO_MMDREG_STAT1_FAULT_WIDTH (1)
++/* Link state */
++#define MDIO_MMDREG_STAT1_LINK_LBN (2)
++#define MDIO_MMDREG_STAT1_LINK_WIDTH (1)
++
++/* Bits in ID reg */
++#define MDIO_ID_REV(_id32) (_id32 & 0xf)
++#define MDIO_ID_MODEL(_id32) ((_id32 >> 4) & 0x3f)
++#define MDIO_ID_OUI(_id32) (_id32 >> 10)
++
++/* Bits in MMDREG_DEVS0. Someone thoughtfully layed things out
++ * so the 'bit present' bit number of an MMD is the number of
++ * that MMD */
++#define DEV_PRESENT_BIT(_b) (1 << _b)
++
++#define MDIO_MMDREG_DEVS0_PHYXS DEV_PRESENT_BIT(MDIO_MMD_PHYXS)
++#define MDIO_MMDREG_DEVS0_PCS DEV_PRESENT_BIT(MDIO_MMD_PCS)
++#define MDIO_MMDREG_DEVS0_PMAPMD DEV_PRESENT_BIT(MDIO_MMD_PMAPMD)
++
++/* Bits in MMDREG_STAT2 */
++#define MDIO_MMDREG_STAT2_PRESENT_VAL (2)
++#define MDIO_MMDREG_STAT2_PRESENT_LBN (14)
++#define MDIO_MMDREG_STAT2_PRESENT_WIDTH (2)
++
++/* PMA type (4 bits) */
++#define MDIO_PMAPMD_CTRL2_10G_CX4 (0x0)
++#define MDIO_PMAPMD_CTRL2_10G_EW (0x1)
++#define MDIO_PMAPMD_CTRL2_10G_LW (0x2)
++#define MDIO_PMAPMD_CTRL2_10G_SW (0x3)
++#define MDIO_PMAPMD_CTRL2_10G_LX4 (0x4)
++#define MDIO_PMAPMD_CTRL2_10G_ER (0x5)
++#define MDIO_PMAPMD_CTRL2_10G_LR (0x6)
++#define MDIO_PMAPMD_CTRL2_10G_SR (0x7)
++/* Reserved */
++#define MDIO_PMAPMD_CTRL2_10G_BT (0x9)
++/* Reserved */
++/* Reserved */
++#define MDIO_PMAPMD_CTRL2_1G_BT (0xc)
++/* Reserved */
++#define MDIO_PMAPMD_CTRL2_100_BT (0xe)
++#define MDIO_PMAPMD_CTRL2_10_BT (0xf)
++#define MDIO_PMAPMD_CTRL2_TYPE_MASK (0xf)
++
++/* /\* PHY XGXS lane state *\/ */
++#define MDIO_PHYXS_LANE_STATE (0x18)
++#define MDIO_PHYXS_LANE_ALIGNED_LBN (12)
++
++/* AN registers */
++#define MDIO_AN_STATUS (1)
++#define MDIO_AN_STATUS_XNP_LBN (7)
++#define MDIO_AN_STATUS_PAGE_LBN (6)
++#define MDIO_AN_STATUS_AN_DONE_LBN (5)
++#define MDIO_AN_STATUS_LP_AN_CAP_LBN (0)
++
++#define MDIO_AN_10GBT_STATUS (33)
++#define MDIO_AN_10GBT_STATUS_MS_FLT_LBN (15) /* MASTER/SLAVE config fault */
++#define MDIO_AN_10GBT_STATUS_MS_LBN (14) /* MASTER/SLAVE config */
++#define MDIO_AN_10GBT_STATUS_LOC_OK_LBN (13) /* Local OK */
++#define MDIO_AN_10GBT_STATUS_REM_OK_LBN (12) /* Remote OK */
++#define MDIO_AN_10GBT_STATUS_LP_10G_LBN (11) /* Link partner is 10GBT capable */
++#define MDIO_AN_10GBT_STATUS_LP_LTA_LBN (10) /* LP loop timing ability */
++#define MDIO_AN_10GBT_STATUS_LP_TRR_LBN (9) /* LP Training Reset Request */
++
++
++/* Packing of the prt and dev arguments of clause 45 style MDIO into a
++ * single int so they can be passed into the mdio_read/write functions
++ * that currently exist. Note that as Falcon is the only current user,
++ * the packed form is chosen to match what Falcon needs to write into
++ * a register. This is checked at compile-time so do not change it. If
++ * your target chip needs things layed out differently you will need
++ * to unpack the arguments in your chip-specific mdio functions.
++ */
++ /* These are defined by the standard. */
++#define MDIO45_PRT_ID_WIDTH (5)
++#define MDIO45_DEV_ID_WIDTH (5)
++
++/* The prt ID is just packed in immediately to the left of the dev ID */
++#define MDIO45_PRT_DEV_WIDTH (MDIO45_PRT_ID_WIDTH + MDIO45_DEV_ID_WIDTH)
++
++#define MDIO45_PRT_ID_MASK ((1 << MDIO45_PRT_DEV_WIDTH) - 1)
++/* This is the prt + dev extended by 1 bit to hold the 'is clause 45' flag. */
++#define MDIO45_XPRT_ID_WIDTH (MDIO45_PRT_DEV_WIDTH + 1)
++#define MDIO45_XPRT_ID_MASK ((1 << MDIO45_XPRT_ID_WIDTH) - 1)
++#define MDIO45_XPRT_ID_IS10G (1 << (MDIO45_XPRT_ID_WIDTH - 1))
++
++
++#define MDIO45_PRT_ID_COMP_LBN MDIO45_DEV_ID_WIDTH
++#define MDIO45_PRT_ID_COMP_WIDTH MDIO45_PRT_ID_WIDTH
++#define MDIO45_DEV_ID_COMP_LBN 0
++#define MDIO45_DEV_ID_COMP_WIDTH MDIO45_DEV_ID_WIDTH
++
++/* Compose port and device into a phy_id */
++static inline int mdio_clause45_pack(u8 prt, u8 dev)
+{
-+ return !strncmp(np->vpd.board_model, model, strlen(model));
++ efx_dword_t phy_id;
++ EFX_POPULATE_DWORD_2(phy_id, MDIO45_PRT_ID_COMP, prt,
++ MDIO45_DEV_ID_COMP, dev);
++ return MDIO45_XPRT_ID_IS10G | EFX_DWORD_VAL(phy_id);
+}
+
-+static int niu_pci_vpd_get_nports(struct niu *np)
++static inline void mdio_clause45_unpack(u32 val, u8 *prt, u8 *dev)
+{
-+ int ports = 0;
++ efx_dword_t phy_id;
++ EFX_POPULATE_DWORD_1(phy_id, EFX_DWORD_0, val);
++ *prt = EFX_DWORD_FIELD(phy_id, MDIO45_PRT_ID_COMP);
++ *dev = EFX_DWORD_FIELD(phy_id, MDIO45_DEV_ID_COMP);
++}
+
-+ 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;
-+ }
++static inline int mdio_clause45_read(struct efx_nic *efx,
++ u8 prt, u8 dev, u16 addr)
++{
++ return efx->mii.mdio_read(efx->net_dev,
++ mdio_clause45_pack(prt, dev), addr);
++}
+
-+ return ports;
++static inline void mdio_clause45_write(struct efx_nic *efx,
++ u8 prt, u8 dev, u16 addr, int value)
++{
++ efx->mii.mdio_write(efx->net_dev,
++ mdio_clause45_pack(prt, dev), addr, value);
+}
+
- 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;
++static inline u32 mdio_clause45_read_id(struct efx_nic *efx, int mmd)
++{
++ int phy_id = efx->mii.phy_id;
++ u16 id_low = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_IDLOW);
++ u16 id_hi = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_IDHI);
++ return (id_hi << 16) | (id_low);
++}
+
-+ /* 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;
++static inline int mdio_clause45_phyxgxs_lane_sync(struct efx_nic *efx)
++{
++ int i, sync, lane_status;
+
-+ 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;
++ for (i = 0; i < 2; ++i)
++ lane_status = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PHYXS,
++ MDIO_PHYXS_LANE_STATE);
+
-+ 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;
++ sync = (lane_status & (1 << MDIO_PHYXS_LANE_ALIGNED_LBN)) != 0;
++ if (!sync)
++ EFX_INFO(efx, "XGXS lane status: %x\n", lane_status);
++ return sync;
++}
+
-+ 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;
++extern const char *mdio_clause45_mmd_name(int mmd);
+
-+ } 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"
++/*
++ * Reset a specific MMD and wait for reset to clear.
++ * Return number of spins left (>0) on success, -%ETIMEDOUT on failure.
++ *
++ * This function will sleep
++ */
++extern int mdio_clause45_reset_mmd(struct efx_nic *efx, int mmd,
++ int spins, int spintime);
+
- #define NIU_VPD_MIN_MAJOR 3
- #define NIU_VPD_MIN_MINOR 4
-
-@@ -3061,6 +3071,7 @@ struct niu_parent {
- #define PLAT_TYPE_NIU 0x02
- #define PLAT_TYPE_VF_P0 0x03
- #define PLAT_TYPE_VF_P1 0x04
-+#define PLAT_TYPE_ATCA_CP3220 0x08
-
- u8 num_ports;
-
-@@ -3198,10 +3209,13 @@ struct niu {
- struct niu_parent *parent;
-
- u32 flags;
-+#define NIU_FLAGS_HOTPLUG_PHY_PRESENT 0x02000000 /* Removebale PHY detected*/
-+#define NIU_FLAGS_HOTPLUG_PHY 0x01000000 /* Removebale PHY */
-+#define NIU_FLAGS_VPD_VALID 0x00800000 /* VPD has valid version */
- #define NIU_FLAGS_MSIX 0x00400000 /* MSI-X in use */
- #define NIU_FLAGS_MCAST 0x00200000 /* multicast filter enabled */
- #define NIU_FLAGS_PROMISC 0x00100000 /* PROMISC enabled */
--#define NIU_FLAGS_VPD_VALID 0x00080000 /* VPD has valid version */
-+#define NIU_FLAGS_XCVR_SERDES 0x00080000 /* 0=PHY 1=SERDES */
- #define NIU_FLAGS_10G 0x00040000 /* 0=1G 1=10G */
- #define NIU_FLAGS_FIBER 0x00020000 /* 0=COPPER 1=FIBER */
- #define NIU_FLAGS_XMAC 0x00010000 /* 0=BMAC 1=XMAC */
-diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
-index 2e39e02..3b2a6c5 100644
---- a/drivers/net/pasemi_mac.c
-+++ b/drivers/net/pasemi_mac.c
-@@ -55,15 +55,10 @@
- * - Multiqueue RX/TX
- */
-
--
--/* Must be a power of two */
--#define RX_RING_SIZE 2048
--#define TX_RING_SIZE 4096
--
- #define LRO_MAX_AGGR 64
-
- #define PE_MIN_MTU 64
--#define PE_MAX_MTU 1500
-+#define PE_MAX_MTU 9000
- #define PE_DEF_MTU ETH_DATA_LEN
-
- #define DEFAULT_MSG_ENABLE \
-@@ -76,16 +71,6 @@
- NETIF_MSG_RX_ERR | \
- NETIF_MSG_TX_ERR)
-
--#define TX_DESC(tx, num) ((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)])
--#define TX_DESC_INFO(tx, num) ((tx)->ring_info[(num) & (TX_RING_SIZE-1)])
--#define RX_DESC(rx, num) ((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])
--#define RX_DESC_INFO(rx, num) ((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
--#define RX_BUFF(rx, num) ((rx)->buffers[(num) & (RX_RING_SIZE-1)])
--
--#define RING_USED(ring) (((ring)->next_to_fill - (ring)->next_to_clean) \
-- & ((ring)->size - 1))
--#define RING_AVAIL(ring) ((ring->size) - RING_USED(ring))
--
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR ("Olof Johansson <olof at lixom.net>");
- MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver");
-@@ -94,6 +79,8 @@ static int debug = -1; /* -1 == use DEFAULT_MSG_ENABLE as value */
- module_param(debug, int, 0);
- MODULE_PARM_DESC(debug, "PA Semi MAC bitmapped debugging message enable value");
-
-+extern const struct ethtool_ops pasemi_mac_ethtool_ops;
++/* As mdio_clause45_check_mmd but for multiple MMDs */
++int mdio_clause45_check_mmds(struct efx_nic *efx,
++ unsigned int mmd_mask, unsigned int fatal_mask);
+
- 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)
++/* Check the link status of specified mmds in bit mask */
++extern int mdio_clause45_links_ok(struct efx_nic *efx,
++ unsigned int mmd_mask);
++
++/* Read (some of) the PHY settings over MDIO */
++extern void mdio_clause45_get_settings(struct efx_nic *efx,
++ struct ethtool_cmd *ecmd);
++
++/* Set (some of) the PHY settings over MDIO */
++extern int mdio_clause45_set_settings(struct efx_nic *efx,
++ struct ethtool_cmd *ecmd);
++
++/* Wait for specified MMDs to exit reset within a timeout */
++extern int mdio_clause45_wait_reset_mmds(struct efx_nic *efx,
++ unsigned int mmd_mask);
++
++#endif /* EFX_MDIO_10G_H */
+diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
+new file mode 100644
+index 0000000..c505482
+--- /dev/null
++++ b/drivers/net/sfc/net_driver.h
+@@ -0,0 +1,883 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005-2006 Fen Systems Ltd.
++ * Copyright 2005-2008 Solarflare Communications 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, incorporated herein by reference.
++ */
++
++/* Common definitions for all Efx net driver code */
++
++#ifndef EFX_NET_DRIVER_H
++#define EFX_NET_DRIVER_H
++
++#include <linux/version.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/ethtool.h>
++#include <linux/if_vlan.h>
++#include <linux/timer.h>
++#include <linux/mii.h>
++#include <linux/list.h>
++#include <linux/pci.h>
++#include <linux/device.h>
++#include <linux/highmem.h>
++#include <linux/workqueue.h>
++#include <linux/inet_lro.h>
++
++#include "enum.h"
++#include "bitfield.h"
++#include "i2c-direct.h"
++
++#define EFX_MAX_LRO_DESCRIPTORS 8
++#define EFX_MAX_LRO_AGGR MAX_SKB_FRAGS
++
++/**************************************************************************
++ *
++ * Build definitions
++ *
++ **************************************************************************/
++#ifndef EFX_DRIVER_NAME
++#define EFX_DRIVER_NAME "sfc"
++#endif
++#define EFX_DRIVER_VERSION "2.2.0136"
++
++#ifdef EFX_ENABLE_DEBUG
++#define EFX_BUG_ON_PARANOID(x) BUG_ON(x)
++#define EFX_WARN_ON_PARANOID(x) WARN_ON(x)
++#else
++#define EFX_BUG_ON_PARANOID(x) do {} while (0)
++#define EFX_WARN_ON_PARANOID(x) do {} while (0)
++#endif
++
++#define NET_DEV_REGISTERED(efx) \
++ ((efx)->net_dev->reg_state == NETREG_REGISTERED)
++
++/* Include net device name in log messages if it has been registered.
++ * Use efx->name not efx->net_dev->name so that races with (un)registration
++ * are harmless.
++ */
++#define NET_DEV_NAME(efx) (NET_DEV_REGISTERED(efx) ? (efx)->name : "")
++
++/* Un-rate-limited logging */
++#define EFX_ERR(efx, fmt, args...) \
++dev_err(&((efx)->pci_dev->dev), "ERR: %s " fmt, NET_DEV_NAME(efx), ##args)
++
++#define EFX_INFO(efx, fmt, args...) \
++dev_info(&((efx)->pci_dev->dev), "INFO: %s " fmt, NET_DEV_NAME(efx), ##args)
++
++#ifdef EFX_ENABLE_DEBUG
++#define EFX_LOG(efx, fmt, args...) \
++dev_info(&((efx)->pci_dev->dev), "DBG: %s " fmt, NET_DEV_NAME(efx), ##args)
++#else
++#define EFX_LOG(efx, fmt, args...) \
++dev_dbg(&((efx)->pci_dev->dev), "DBG: %s " fmt, NET_DEV_NAME(efx), ##args)
++#endif
++
++#define EFX_TRACE(efx, fmt, args...) do {} while (0)
++
++#define EFX_REGDUMP(efx, fmt, args...) do {} while (0)
++
++/* Rate-limited logging */
++#define EFX_ERR_RL(efx, fmt, args...) \
++do {if (net_ratelimit()) EFX_ERR(efx, fmt, ##args); } while (0)
++
++#define EFX_INFO_RL(efx, fmt, args...) \
++do {if (net_ratelimit()) EFX_INFO(efx, fmt, ##args); } while (0)
++
++#define EFX_LOG_RL(efx, fmt, args...) \
++do {if (net_ratelimit()) EFX_LOG(efx, fmt, ##args); } while (0)
++
++/* Kernel headers may redefine inline anyway */
++#ifndef inline
++#define inline inline __attribute__ ((always_inline))
++#endif
++
++/**************************************************************************
++ *
++ * Efx data structures
++ *
++ **************************************************************************/
++
++#define EFX_MAX_CHANNELS 32
++#define EFX_MAX_TX_QUEUES 1
++#define EFX_MAX_RX_QUEUES EFX_MAX_CHANNELS
++
++/**
++ * struct efx_special_buffer - An Efx special buffer
++ * @addr: CPU base address of the buffer
++ * @dma_addr: DMA base address of the buffer
++ * @len: Buffer length, in bytes
++ * @index: Buffer index within controller;s buffer table
++ * @entries: Number of buffer table entries
++ *
++ * Special buffers are used for the event queues and the TX and RX
++ * descriptor queues for each channel. They are *not* used for the
++ * actual transmit and receive buffers.
++ *
++ * Note that for Falcon, TX and RX descriptor queues live in host memory.
++ * Allocation and freeing procedures must take this into account.
++ */
++struct efx_special_buffer {
++ void *addr;
++ dma_addr_t dma_addr;
++ unsigned int len;
++ int index;
++ int entries;
++};
++
++/**
++ * struct efx_tx_buffer - An Efx TX buffer
++ * @skb: The associated socket buffer.
++ * Set only on the final fragment of a packet; %NULL for all other
++ * fragments. When this fragment completes, then we can free this
++ * skb.
++ * @dma_addr: DMA address of the fragment.
++ * @len: Length of this fragment.
++ * This field is zero when the queue slot is empty.
++ * @continuation: True if this fragment is not the end of a packet.
++ * @unmap_single: True if pci_unmap_single should be used.
++ * @unmap_addr: DMA address to unmap
++ * @unmap_len: Length of this fragment to unmap
++ */
++struct efx_tx_buffer {
++ const struct sk_buff *skb;
++ dma_addr_t dma_addr;
++ unsigned short len;
++ unsigned char continuation;
++ unsigned char unmap_single;
++ dma_addr_t unmap_addr;
++ unsigned short unmap_len;
++};
++
++/**
++ * struct efx_tx_queue - An Efx TX queue
++ *
++ * This is a ring buffer of TX fragments.
++ * Since the TX completion path always executes on the same
++ * CPU and the xmit path can operate on different CPUs,
++ * performance is increased by ensuring that the completion
++ * path and the xmit path operate on different cache lines.
++ * This is particularly important if the xmit path is always
++ * executing on one CPU which is different from the completion
++ * path. There is also a cache line for members which are
++ * read but not written on the fast path.
++ *
++ * @efx: The associated Efx NIC
++ * @queue: DMA queue number
++ * @used: Queue is used by net driver
++ * @channel: The associated channel
++ * @buffer: The software buffer ring
++ * @txd: The hardware descriptor ring
++ * @read_count: Current read pointer.
++ * This is the number of buffers that have been removed from both rings.
++ * @stopped: Stopped flag.
++ * Set if this TX queue is currently stopping its port.
++ * @insert_count: Current insert pointer
++ * This is the number of buffers that have been added to the
++ * software ring.
++ * @write_count: Current write pointer
++ * This is the number of buffers that have been added to the
++ * hardware ring.
++ * @old_read_count: The value of read_count when last checked.
++ * This is here for performance reasons. The xmit path will
++ * only get the up-to-date value of read_count if this
++ * variable indicates that the queue is full. This is to
++ * avoid cache-line ping-pong between the xmit path and the
++ * completion path.
++ */
++struct efx_tx_queue {
++ /* Members which don't change on the fast path */
++ struct efx_nic *efx ____cacheline_aligned_in_smp;
++ int queue;
++ int used;
++ struct efx_channel *channel;
++ struct efx_nic *nic;
++ struct efx_tx_buffer *buffer;
++ struct efx_special_buffer txd;
++
++ /* Members used mainly on the completion path */
++ unsigned int read_count ____cacheline_aligned_in_smp;
++ int stopped;
++
++ /* Members used only on the xmit path */
++ unsigned int insert_count ____cacheline_aligned_in_smp;
++ unsigned int write_count;
++ unsigned int old_read_count;
++};
++
++/**
++ * struct efx_rx_buffer - An Efx RX data buffer
++ * @dma_addr: DMA base address of the buffer
++ * @skb: The associated socket buffer, if any.
++ * If both this and page are %NULL, the buffer slot is currently free.
++ * @page: The associated page buffer, if any.
++ * If both this and skb are %NULL, the buffer slot is currently free.
++ * @data: Pointer to ethernet header
++ * @len: Buffer length, in bytes.
++ * @unmap_addr: DMA address to unmap
++ */
++struct efx_rx_buffer {
++ dma_addr_t dma_addr;
++ struct sk_buff *skb;
++ struct page *page;
++ char *data;
++ unsigned int len;
++ dma_addr_t unmap_addr;
++};
++
++/**
++ * struct efx_rx_queue - An Efx RX queue
++ * @efx: The associated Efx NIC
++ * @queue: DMA queue number
++ * @used: Queue is used by net driver
++ * @channel: The associated channel
++ * @buffer: The software buffer ring
++ * @rxd: The hardware descriptor ring
++ * @added_count: Number of buffers added to the receive queue.
++ * @notified_count: Number of buffers given to NIC (<= @added_count).
++ * @removed_count: Number of buffers removed from the receive queue.
++ * @add_lock: Receive queue descriptor add spin lock.
++ * This lock must be held in order to add buffers to the RX
++ * descriptor ring (rxd and buffer) and to update added_count (but
++ * not removed_count).
++ * @max_fill: RX descriptor maximum fill level (<= ring size)
++ * @fast_fill_trigger: RX descriptor fill level that will trigger a fast fill
++ * (<= @max_fill)
++ * @fast_fill_limit: The level to which a fast fill will fill
++ * (@fast_fill_trigger <= @fast_fill_limit <= @max_fill)
++ * @min_fill: RX descriptor minimum non-zero fill level.
++ * This records the minimum fill level observed when a ring
++ * refill was triggered.
++ * @min_overfill: RX descriptor minimum overflow fill level.
++ * This records the minimum fill level at which RX queue
++ * overflow was observed. It should never be set.
++ * @alloc_page_count: RX allocation strategy counter.
++ * @alloc_skb_count: RX allocation strategy counter.
++ * @work: Descriptor push work thread
++ * @buf_page: Page for next RX buffer.
++ * We can use a single page for multiple RX buffers. This tracks
++ * the remaining space in the allocation.
++ * @buf_dma_addr: Page's DMA address.
++ * @buf_data: Page's host address.
++ */
++struct efx_rx_queue {
++ struct efx_nic *efx;
++ int queue;
++ int used;
++ struct efx_channel *channel;
++ struct efx_rx_buffer *buffer;
++ struct efx_special_buffer rxd;
++
++ int added_count;
++ int notified_count;
++ int removed_count;
++ spinlock_t add_lock;
++ unsigned int max_fill;
++ unsigned int fast_fill_trigger;
++ unsigned int fast_fill_limit;
++ unsigned int min_fill;
++ unsigned int min_overfill;
++ unsigned int alloc_page_count;
++ unsigned int alloc_skb_count;
++ struct delayed_work work;
++ unsigned int slow_fill_count;
++
++ struct page *buf_page;
++ dma_addr_t buf_dma_addr;
++ char *buf_data;
++};
++
++/**
++ * struct efx_buffer - An Efx general-purpose buffer
++ * @addr: host base address of the buffer
++ * @dma_addr: DMA base address of the buffer
++ * @len: Buffer length, in bytes
++ *
++ * Falcon uses these buffers for its interrupt status registers and
++ * MAC stats dumps.
++ */
++struct efx_buffer {
++ void *addr;
++ dma_addr_t dma_addr;
++ unsigned int len;
++};
++
++
++/* Flags for channel->used_flags */
++#define EFX_USED_BY_RX 1
++#define EFX_USED_BY_TX 2
++#define EFX_USED_BY_RX_TX (EFX_USED_BY_RX | EFX_USED_BY_TX)
++
++enum efx_rx_alloc_method {
++ RX_ALLOC_METHOD_AUTO = 0,
++ RX_ALLOC_METHOD_SKB = 1,
++ RX_ALLOC_METHOD_PAGE = 2,
++};
++
++/**
++ * struct efx_channel - An Efx channel
++ *
++ * A channel comprises an event queue, at least one TX queue, at least
++ * one RX queue, and an associated tasklet for processing the event
++ * queue.
++ *
++ * @efx: Associated Efx NIC
++ * @evqnum: Event queue number
++ * @channel: Channel instance number
++ * @used_flags: Channel is used by net driver
++ * @enabled: Channel enabled indicator
++ * @irq: IRQ number (MSI and MSI-X only)
++ * @has_interrupt: Channel has an interrupt
++ * @irq_moderation: IRQ moderation value (in us)
++ * @napi_dev: Net device used with NAPI
++ * @napi_str: NAPI control structure
++ * @reset_work: Scheduled reset work thread
++ * @work_pending: Is work pending via NAPI?
++ * @eventq: Event queue buffer
++ * @eventq_read_ptr: Event queue read pointer
++ * @last_eventq_read_ptr: Last event queue read pointer value.
++ * @eventq_magic: Event queue magic value for driver-generated test events
++ * @lro_mgr: LRO state
++ * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors
++ * and diagnostic counters
++ * @rx_alloc_push_pages: RX allocation method currently in use for pushing
++ * descriptors
++ * @rx_alloc_pop_pages: RX allocation method currently in use for popping
++ * descriptors
++ * @n_rx_tobe_disc: Count of RX_TOBE_DISC errors
++ * @n_rx_ip_frag_err: Count of RX IP fragment errors
++ * @n_rx_ip_hdr_chksum_err: Count of RX IP header checksum errors
++ * @n_rx_tcp_udp_chksum_err: Count of RX TCP and UDP checksum errors
++ * @n_rx_frm_trunc: Count of RX_FRM_TRUNC errors
++ * @n_rx_overlength: Count of RX_OVERLENGTH errors
++ * @n_skbuff_leaks: Count of skbuffs leaked due to RX overrun
++ */
++struct efx_channel {
++ struct efx_nic *efx;
++ int evqnum;
++ int channel;
++ int used_flags;
++ int enabled;
++ int irq;
++ unsigned int has_interrupt;
++ unsigned int irq_moderation;
++ struct net_device *napi_dev;
++ struct napi_struct napi_str;
++ struct work_struct reset_work;
++ int work_pending;
++ struct efx_special_buffer eventq;
++ unsigned int eventq_read_ptr;
++ unsigned int last_eventq_read_ptr;
++ unsigned int eventq_magic;
++
++ struct net_lro_mgr lro_mgr;
++ int rx_alloc_level;
++ int rx_alloc_push_pages;
++ int rx_alloc_pop_pages;
++
++ unsigned n_rx_tobe_disc;
++ unsigned n_rx_ip_frag_err;
++ unsigned n_rx_ip_hdr_chksum_err;
++ unsigned n_rx_tcp_udp_chksum_err;
++ unsigned n_rx_frm_trunc;
++ unsigned n_rx_overlength;
++ unsigned n_skbuff_leaks;
++
++ /* Used to pipeline received packets in order to optimise memory
++ * access with prefetches.
++ */
++ struct efx_rx_buffer *rx_pkt;
++ int rx_pkt_csummed;
++
++};
++
++/**
++ * struct efx_blinker - S/W LED blinking context
++ * @led_num: LED ID (board-specific meaning)
++ * @state: Current state - on or off
++ * @resubmit: Timer resubmission flag
++ * @timer: Control timer for blinking
++ */
++struct efx_blinker {
++ int led_num;
++ int state;
++ int resubmit;
++ struct timer_list timer;
++};
++
++
++/**
++ * struct efx_board - board information
++ * @type: Board model type
++ * @major: Major rev. ('A', 'B' ...)
++ * @minor: Minor rev. (0, 1, ...)
++ * @init: Initialisation function
++ * @init_leds: Sets up board LEDs
++ * @set_fault_led: Turns the fault LED on or off
++ * @blink: Starts/stops blinking
++ * @blinker: used to blink LEDs in software
++ */
++struct efx_board {
++ int type;
++ int major;
++ int minor;
++ int (*init) (struct efx_nic *nic);
++ /* As the LEDs are typically attached to the PHY, LEDs
++ * have a separate init callback that happens later than
++ * board init. */
++ int (*init_leds)(struct efx_nic *efx);
++ void (*set_fault_led) (struct efx_nic *efx, int state);
++ void (*blink) (struct efx_nic *efx, int start);
++ struct efx_blinker blinker;
++};
++
++enum efx_int_mode {
++ /* Be careful if altering to correct macro below */
++ EFX_INT_MODE_MSIX = 0,
++ EFX_INT_MODE_MSI = 1,
++ EFX_INT_MODE_LEGACY = 2,
++ EFX_INT_MODE_MAX /* Insert any new items before this */
++};
++#define EFX_INT_MODE_USE_MSI(x) (((x)->interrupt_mode) <= EFX_INT_MODE_MSI)
++
++enum phy_type {
++ PHY_TYPE_NONE = 0,
++ PHY_TYPE_CX4_RTMR = 1,
++ PHY_TYPE_1G_ALASKA = 2,
++ PHY_TYPE_10XPRESS = 3,
++ PHY_TYPE_XFP = 4,
++ PHY_TYPE_PM8358 = 6,
++ PHY_TYPE_MAX /* Insert any new items before this */
++};
++
++#define PHY_ADDR_INVALID 0xff
++
++enum nic_state {
++ STATE_INIT = 0,
++ STATE_RUNNING = 1,
++ STATE_FINI = 2,
++ STATE_RESETTING = 3, /* rtnl_lock always held */
++ STATE_DISABLED = 4,
++ STATE_MAX,
++};
++
++/*
++ * Alignment of page-allocated RX buffers
++ *
++ * Controls the number of bytes inserted at the start of an RX buffer.
++ * This is the equivalent of NET_IP_ALIGN [which controls the alignment
++ * of the skb->head for hardware DMA].
++ */
++#if defined(__i386__) || defined(__x86_64__)
++#define EFX_PAGE_IP_ALIGN 0
++#else
++#define EFX_PAGE_IP_ALIGN NET_IP_ALIGN
++#endif
++
++/*
++ * Alignment of the skb->head which wraps a page-allocated RX buffer
++ *
++ * The skb allocated to wrap an rx_buffer can have this alignment. Since
++ * the data is memcpy'd from the rx_buf, it does not need to be equal to
++ * EFX_PAGE_IP_ALIGN.
++ */
++#define EFX_PAGE_SKB_ALIGN 2
++
++/* Forward declaration */
++struct efx_nic;
++
++/* Pseudo bit-mask flow control field */
++enum efx_fc_type {
++ EFX_FC_RX = 1,
++ EFX_FC_TX = 2,
++ EFX_FC_AUTO = 4,
++};
++
++/**
++ * struct efx_phy_operations - Efx PHY operations table
++ * @init: Initialise PHY
++ * @fini: Shut down PHY
++ * @reconfigure: Reconfigure PHY (e.g. for new link parameters)
++ * @clear_interrupt: Clear down interrupt
++ * @blink: Blink LEDs
++ * @check_hw: Check hardware
++ * @reset_xaui: Reset XAUI side of PHY for (software sequenced reset)
++ * @mmds: MMD presence mask
++ */
++struct efx_phy_operations {
++ int (*init) (struct efx_nic *efx);
++ void (*fini) (struct efx_nic *efx);
++ void (*reconfigure) (struct efx_nic *efx);
++ void (*clear_interrupt) (struct efx_nic *efx);
++ int (*check_hw) (struct efx_nic *efx);
++ void (*reset_xaui) (struct efx_nic *efx);
++ int mmds;
++};
++
++/*
++ * Efx extended statistics
++ *
++ * Not all statistics are provided by all supported MACs. The purpose
++ * is this structure is to contain the raw statistics provided by each
++ * MAC.
++ */
++struct efx_mac_stats {
++ u64 tx_bytes;
++ u64 tx_good_bytes;
++ u64 tx_bad_bytes;
++ unsigned long tx_packets;
++ unsigned long tx_bad;
++ unsigned long tx_pause;
++ unsigned long tx_control;
++ unsigned long tx_unicast;
++ unsigned long tx_multicast;
++ unsigned long tx_broadcast;
++ unsigned long tx_lt64;
++ unsigned long tx_64;
++ unsigned long tx_65_to_127;
++ unsigned long tx_128_to_255;
++ unsigned long tx_256_to_511;
++ unsigned long tx_512_to_1023;
++ unsigned long tx_1024_to_15xx;
++ unsigned long tx_15xx_to_jumbo;
++ unsigned long tx_gtjumbo;
++ unsigned long tx_collision;
++ unsigned long tx_single_collision;
++ unsigned long tx_multiple_collision;
++ unsigned long tx_excessive_collision;
++ unsigned long tx_deferred;
++ unsigned long tx_late_collision;
++ unsigned long tx_excessive_deferred;
++ unsigned long tx_non_tcpudp;
++ unsigned long tx_mac_src_error;
++ unsigned long tx_ip_src_error;
++ u64 rx_bytes;
++ u64 rx_good_bytes;
++ u64 rx_bad_bytes;
++ unsigned long rx_packets;
++ unsigned long rx_good;
++ unsigned long rx_bad;
++ unsigned long rx_pause;
++ unsigned long rx_control;
++ unsigned long rx_unicast;
++ unsigned long rx_multicast;
++ unsigned long rx_broadcast;
++ unsigned long rx_lt64;
++ unsigned long rx_64;
++ unsigned long rx_65_to_127;
++ unsigned long rx_128_to_255;
++ unsigned long rx_256_to_511;
++ unsigned long rx_512_to_1023;
++ unsigned long rx_1024_to_15xx;
++ unsigned long rx_15xx_to_jumbo;
++ unsigned long rx_gtjumbo;
++ unsigned long rx_bad_lt64;
++ unsigned long rx_bad_64_to_15xx;
++ unsigned long rx_bad_15xx_to_jumbo;
++ unsigned long rx_bad_gtjumbo;
++ unsigned long rx_overflow;
++ unsigned long rx_missed;
++ unsigned long rx_false_carrier;
++ unsigned long rx_symbol_error;
++ unsigned long rx_align_error;
++ unsigned long rx_length_error;
++ unsigned long rx_internal_error;
++ unsigned long rx_good_lt64;
++};
++
++/* Number of bits used in a multicast filter hash address */
++#define EFX_MCAST_HASH_BITS 8
++
++/* Number of (single-bit) entries in a multicast filter hash */
++#define EFX_MCAST_HASH_ENTRIES (1 << EFX_MCAST_HASH_BITS)
++
++/* An Efx multicast filter hash */
++union efx_multicast_hash {
++ u8 byte[EFX_MCAST_HASH_ENTRIES / 8];
++ efx_oword_t oword[EFX_MCAST_HASH_ENTRIES / sizeof(efx_oword_t) / 8];
++};
++
++/**
++ * struct efx_nic - an Efx NIC
++ * @name: Device name (net device name or bus id before net device registered)
++ * @pci_dev: The PCI device
++ * @type: Controller type attributes
++ * @legacy_irq: IRQ number
++ * @workqueue: Workqueue for resets, port reconfigures and the HW monitor
++ * @reset_work: Scheduled reset workitem
++ * @monitor_work: Hardware monitor workitem
++ * @membase_phys: Memory BAR value as physical address
++ * @membase: Memory BAR value
++ * @biu_lock: BIU (bus interface unit) lock
++ * @interrupt_mode: Interrupt mode
++ * @i2c: I2C interface
++ * @board_info: Board-level information
++ * @state: Device state flag. Serialised by the rtnl_lock.
++ * @reset_pending: Pending reset method (normally RESET_TYPE_NONE)
++ * @tx_queue: TX DMA queues
++ * @rx_queue: RX DMA queues
++ * @channel: Channels
++ * @rss_queues: Number of RSS queues
++ * @rx_buffer_len: RX buffer length
++ * @rx_buffer_order: Order (log2) of number of pages for each RX buffer
++ * @irq_status: Interrupt status buffer
++ * @last_irq_cpu: Last CPU to handle interrupt.
++ * This register is written with the SMP processor ID whenever an
++ * interrupt is handled. It is used by falcon_test_interrupt()
++ * to verify that an interrupt has occurred.
++ * @n_rx_nodesc_drop_cnt: RX no descriptor drop count
++ * @nic_data: Hardware dependant state
++ * @mac_lock: MAC access lock. Protects @port_enabled, efx_monitor() and
++ * efx_reconfigure_port()
++ * @port_enabled: Port enabled indicator.
++ * Serialises efx_stop_all(), efx_start_all() and efx_monitor() and
++ * efx_reconfigure_work with kernel interfaces. Safe to read under any
++ * one of the rtnl_lock, mac_lock, or netif_tx_lock, but all three must
++ * be held to modify it.
++ * @port_initialized: Port initialized?
++ * @net_dev: Operating system network device. Consider holding the rtnl lock
++ * @rx_checksum_enabled: RX checksumming enabled
++ * @netif_stop_count: Port stop count
++ * @netif_stop_lock: Port stop lock
++ * @mac_stats: MAC statistics. These include all statistics the MACs
++ * can provide. Generic code converts these into a standard
++ * &struct net_device_stats.
++ * @stats_buffer: DMA buffer for statistics
++ * @stats_lock: Statistics update lock
++ * @mac_address: Permanent MAC address
++ * @phy_type: PHY type
++ * @phy_lock: PHY access lock
++ * @phy_op: PHY interface
++ * @phy_data: PHY private data (including PHY-specific stats)
++ * @mii: PHY interface
++ * @phy_powered: PHY power state
++ * @tx_disabled: PHY transmitter turned off
++ * @link_up: Link status
++ * @link_options: Link options (MII/GMII format)
++ * @n_link_state_changes: Number of times the link has changed state
++ * @promiscuous: Promiscuous flag. Protected by netif_tx_lock.
++ * @multicast_hash: Multicast hash table
++ * @flow_control: Flow control flags - separate RX/TX so can't use link_options
++ * @reconfigure_work: work item for dealing with PHY events
++ *
++ * The @priv field of the corresponding &struct net_device points to
++ * this.
++ */
++struct efx_nic {
++ char name[IFNAMSIZ];
++ struct pci_dev *pci_dev;
++ const struct efx_nic_type *type;
++ int legacy_irq;
++ struct workqueue_struct *workqueue;
++ struct work_struct reset_work;
++ struct delayed_work monitor_work;
++ unsigned long membase_phys;
++ void __iomem *membase;
++ spinlock_t biu_lock;
++ enum efx_int_mode interrupt_mode;
++
++ struct efx_i2c_interface i2c;
++ struct efx_board board_info;
++
++ enum nic_state state;
++ enum reset_type reset_pending;
++
++ struct efx_tx_queue tx_queue[EFX_MAX_TX_QUEUES];
++ struct efx_rx_queue rx_queue[EFX_MAX_RX_QUEUES];
++ struct efx_channel channel[EFX_MAX_CHANNELS];
++
++ int rss_queues;
++ unsigned int rx_buffer_len;
++ unsigned int rx_buffer_order;
++
++ struct efx_buffer irq_status;
++ volatile signed int last_irq_cpu;
++
++ unsigned n_rx_nodesc_drop_cnt;
++
++ void *nic_data;
++
++ struct mutex mac_lock;
++ int port_enabled;
++
++ int port_initialized;
++ struct net_device *net_dev;
++ int rx_checksum_enabled;
++
++ atomic_t netif_stop_count;
++ spinlock_t netif_stop_lock;
++
++ struct efx_mac_stats mac_stats;
++ struct efx_buffer stats_buffer;
++ spinlock_t stats_lock;
++
++ unsigned char mac_address[ETH_ALEN];
++
++ enum phy_type phy_type;
++ spinlock_t phy_lock;
++ struct efx_phy_operations *phy_op;
++ void *phy_data;
++ struct mii_if_info mii;
++
++ int link_up;
++ unsigned int link_options;
++ unsigned int n_link_state_changes;
++
++ int promiscuous;
++ union efx_multicast_hash multicast_hash;
++ enum efx_fc_type flow_control;
++ struct work_struct reconfigure_work;
++
++ atomic_t rx_reset;
++};
++
++/**
++ * struct efx_nic_type - Efx device type definition
++ * @mem_bar: Memory BAR number
++ * @mem_map_size: Memory BAR mapped size
++ * @txd_ptr_tbl_base: TX descriptor ring base address
++ * @rxd_ptr_tbl_base: RX descriptor ring base address
++ * @buf_tbl_base: Buffer table base address
++ * @evq_ptr_tbl_base: Event queue pointer table base address
++ * @evq_rptr_tbl_base: Event queue read-pointer table base address
++ * @txd_ring_mask: TX descriptor ring size - 1 (must be a power of two - 1)
++ * @rxd_ring_mask: RX descriptor ring size - 1 (must be a power of two - 1)
++ * @evq_size: Event queue size (must be a power of two)
++ * @max_dma_mask: Maximum possible DMA mask
++ * @tx_dma_mask: TX DMA mask
++ * @bug5391_mask: Address mask for bug 5391 workaround
++ * @rx_xoff_thresh: RX FIFO XOFF watermark (bytes)
++ * @rx_xon_thresh: RX FIFO XON watermark (bytes)
++ * @rx_buffer_padding: Padding added to each RX buffer
++ * @max_interrupt_mode: Highest capability interrupt mode supported
++ * from &enum efx_init_mode.
++ * @phys_addr_channels: Number of channels with physically addressed
++ * descriptors
++ */
++struct efx_nic_type {
++ unsigned int mem_bar;
++ unsigned int mem_map_size;
++ unsigned int txd_ptr_tbl_base;
++ unsigned int rxd_ptr_tbl_base;
++ unsigned int buf_tbl_base;
++ unsigned int evq_ptr_tbl_base;
++ unsigned int evq_rptr_tbl_base;
++
++ unsigned int txd_ring_mask;
++ unsigned int rxd_ring_mask;
++ unsigned int evq_size;
++ dma_addr_t max_dma_mask;
++ unsigned int tx_dma_mask;
++ unsigned bug5391_mask;
++
++ int rx_xoff_thresh;
++ int rx_xon_thresh;
++ unsigned int rx_buffer_padding;
++ unsigned int max_interrupt_mode;
++ unsigned int phys_addr_channels;
++};
++
++/**************************************************************************
++ *
++ * Prototypes and inline functions
++ *
++ *************************************************************************/
++
++/* Iterate over all used channels */
++#define efx_for_each_channel(_channel, _efx) \
++ for (_channel = &_efx->channel[0]; \
++ _channel < &_efx->channel[EFX_MAX_CHANNELS]; \
++ _channel++) \
++ if (!_channel->used_flags) \
++ continue; \
++ else
++
++/* Iterate over all used channels with interrupts */
++#define efx_for_each_channel_with_interrupt(_channel, _efx) \
++ for (_channel = &_efx->channel[0]; \
++ _channel < &_efx->channel[EFX_MAX_CHANNELS]; \
++ _channel++) \
++ if (!(_channel->used_flags && _channel->has_interrupt)) \
++ continue; \
++ else
++
++/* Iterate over all used TX queues */
++#define efx_for_each_tx_queue(_tx_queue, _efx) \
++ for (_tx_queue = &_efx->tx_queue[0]; \
++ _tx_queue < &_efx->tx_queue[EFX_MAX_TX_QUEUES]; \
++ _tx_queue++) \
++ if (!_tx_queue->used) \
++ continue; \
++ else
++
++/* Iterate over all TX queues belonging to a channel */
++#define efx_for_each_channel_tx_queue(_tx_queue, _channel) \
++ for (_tx_queue = &_channel->efx->tx_queue[0]; \
++ _tx_queue < &_channel->efx->tx_queue[EFX_MAX_TX_QUEUES]; \
++ _tx_queue++) \
++ if ((!_tx_queue->used) || \
++ (_tx_queue->channel != _channel)) \
++ continue; \
++ else
++
++/* Iterate over all used RX queues */
++#define efx_for_each_rx_queue(_rx_queue, _efx) \
++ for (_rx_queue = &_efx->rx_queue[0]; \
++ _rx_queue < &_efx->rx_queue[EFX_MAX_RX_QUEUES]; \
++ _rx_queue++) \
++ if (!_rx_queue->used) \
++ continue; \
++ else
++
++/* Iterate over all RX queues belonging to a channel */
++#define efx_for_each_channel_rx_queue(_rx_queue, _channel) \
++ for (_rx_queue = &_channel->efx->rx_queue[0]; \
++ _rx_queue < &_channel->efx->rx_queue[EFX_MAX_RX_QUEUES]; \
++ _rx_queue++) \
++ if ((!_rx_queue->used) || \
++ (_rx_queue->channel != _channel)) \
++ continue; \
++ else
++
++/* Returns a pointer to the specified receive buffer in the RX
++ * descriptor queue.
++ */
++static inline struct efx_rx_buffer *efx_rx_buffer(struct efx_rx_queue *rx_queue,
++ unsigned int index)
+{
-+ struct pasemi_mac_csring *ring;
-+ u32 val;
-+ unsigned int cfg;
-+ int chno;
++ return (&rx_queue->buffer[index]);
++}
++
++/* Set bit in a little-endian bitfield */
++static inline void set_bit_le(int nr, unsigned char *addr)
++{
++ addr[nr / 8] |= (1 << (nr % 8));
++}
++
++/* Clear bit in a little-endian bitfield */
++static inline void clear_bit_le(int nr, unsigned char *addr)
++{
++ addr[nr / 8] &= ~(1 << (nr % 8));
++}
++
++
++/**
++ * EFX_MAX_FRAME_LEN - calculate maximum frame length
++ *
++ * This calculates the maximum frame length that will be used for a
++ * given MTU. The frame length will be equal to the MTU plus a
++ * constant amount of header space and padding. This is the quantity
++ * that the net driver will program into the MAC as the maximum frame
++ * length.
++ *
++ * The 10G MAC used in Falcon requires 8-byte alignment on the frame
++ * length, so we round up to the nearest 8.
++ */
++#define EFX_MAX_FRAME_LEN(mtu) \
++ ((((mtu) + ETH_HLEN + VLAN_HLEN + 4/* FCS */) + 7) & ~7)
++
++
++#endif /* EFX_NET_DRIVER_H */
+diff --git a/drivers/net/sfc/phy.h b/drivers/net/sfc/phy.h
+new file mode 100644
+index 0000000..9d02c84
+--- /dev/null
++++ b/drivers/net/sfc/phy.h
+@@ -0,0 +1,48 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2007 Solarflare Communications 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, incorporated herein by reference.
++ */
++
++#ifndef EFX_PHY_H
++#define EFX_PHY_H
++
++/****************************************************************************
++ * 10Xpress (SFX7101) PHY
++ */
++extern struct efx_phy_operations falcon_tenxpress_phy_ops;
++
++enum tenxpress_state {
++ TENXPRESS_STATUS_OFF = 0,
++ TENXPRESS_STATUS_OTEMP = 1,
++ TENXPRESS_STATUS_NORMAL = 2,
++};
++
++extern void tenxpress_set_state(struct efx_nic *efx,
++ enum tenxpress_state state);
++extern void tenxpress_phy_blink(struct efx_nic *efx, int blink);
++extern void tenxpress_crc_err(struct efx_nic *efx);
++
++/****************************************************************************
++ * Exported functions from the driver for XFP optical PHYs
++ */
++extern struct efx_phy_operations falcon_xfp_phy_ops;
++
++/* The QUAKE XFP PHY provides various H/W control states for LEDs */
++#define QUAKE_LED_LINK_INVAL (0)
++#define QUAKE_LED_LINK_STAT (1)
++#define QUAKE_LED_LINK_ACT (2)
++#define QUAKE_LED_LINK_ACTSTAT (3)
++#define QUAKE_LED_OFF (4)
++#define QUAKE_LED_ON (5)
++#define QUAKE_LED_LINK_INPUT (6) /* Pin is an input. */
++/* What link the LED tracks */
++#define QUAKE_LED_TXLINK (0)
++#define QUAKE_LED_RXLINK (8)
++
++extern void xfp_set_led(struct efx_nic *p, int led, int state);
++
++#endif
+diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c
+new file mode 100644
+index 0000000..551299b
+--- /dev/null
++++ b/drivers/net/sfc/rx.c
+@@ -0,0 +1,875 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005-2006 Fen Systems Ltd.
++ * Copyright 2005-2008 Solarflare Communications 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, incorporated herein by reference.
++ */
+
-+ ring = pasemi_dma_alloc_chan(TXCHAN, sizeof(struct pasemi_mac_csring),
-+ offsetof(struct pasemi_mac_csring, chan));
++#include <linux/socket.h>
++#include <linux/in.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/udp.h>
++#include <net/ip.h>
++#include <net/checksum.h>
++#include "net_driver.h"
++#include "rx.h"
++#include "efx.h"
++#include "falcon.h"
++#include "workarounds.h"
+
-+ if (!ring) {
-+ dev_err(&mac->pdev->dev, "Can't allocate checksum channel\n");
-+ goto out_chan;
-+ }
++/* Number of RX descriptors pushed at once. */
++#define EFX_RX_BATCH 8
+
-+ chno = ring->chan.chno;
++/* Size of buffer allocated for skb header area. */
++#define EFX_SKB_HEADERS 64u
+
-+ ring->size = CS_RING_SIZE;
-+ ring->next_to_fill = 0;
++/*
++ * rx_alloc_method - RX buffer allocation method
++ *
++ * This driver supports two methods for allocating and using RX buffers:
++ * each RX buffer may be backed by an skb or by an order-n page.
++ *
++ * When LRO is in use then the second method has a lower overhead,
++ * since we don't have to allocate then free skbs on reassembled frames.
++ *
++ * Values:
++ * - RX_ALLOC_METHOD_AUTO = 0
++ * - RX_ALLOC_METHOD_SKB = 1
++ * - RX_ALLOC_METHOD_PAGE = 2
++ *
++ * The heuristic for %RX_ALLOC_METHOD_AUTO is a simple hysteresis count
++ * controlled by the parameters below.
++ *
++ * - Since pushing and popping descriptors are separated by the rx_queue
++ * size, so the watermarks should be ~rxd_size.
++ * - The performance win by using page-based allocation for LRO is less
++ * than the performance hit of using page-based allocation of non-LRO,
++ * so the watermarks should reflect this.
++ *
++ * Per channel we maintain a single variable, updated by each channel:
++ *
++ * rx_alloc_level += (lro_performed ? RX_ALLOC_FACTOR_LRO :
++ * RX_ALLOC_FACTOR_SKB)
++ * Per NAPI poll interval, we constrain rx_alloc_level to 0..MAX (which
++ * limits the hysteresis), and update the allocation strategy:
++ *
++ * rx_alloc_method = (rx_alloc_level > RX_ALLOC_LEVEL_LRO ?
++ * RX_ALLOC_METHOD_PAGE : RX_ALLOC_METHOD_SKB)
++ */
++static int rx_alloc_method = RX_ALLOC_METHOD_PAGE;
+
-+ /* Allocate descriptors */
-+ if (pasemi_dma_alloc_ring(&ring->chan, CS_RING_SIZE))
-+ goto out_ring_desc;
++#define RX_ALLOC_LEVEL_LRO 0x2000
++#define RX_ALLOC_LEVEL_MAX 0x3000
++#define RX_ALLOC_FACTOR_LRO 1
++#define RX_ALLOC_FACTOR_SKB (-2)
+
-+ 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);
++/* This is the percentage fill level below which new RX descriptors
++ * will be added to the RX descriptor ring.
++ */
++static unsigned int rx_refill_threshold = 90;
+
-+ write_dma_reg(PAS_DMA_TXCHAN_BASEU(chno), val);
++/* This is the percentage fill level to which an RX queue will be refilled
++ * when the "RX refill threshold" is reached.
++ */
++static unsigned int rx_refill_limit = 95;
+
-+ 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;
++/*
++ * RX maximum head room required.
++ *
++ * This must be at least 1 to prevent overflow and at least 2 to allow
++ * pipelined receives.
++ */
++#define EFX_RXD_HEAD_ROOM 2
+
-+ pasemi_dma_clear_flag(ring->events[0]);
-+ pasemi_dma_clear_flag(ring->events[1]);
++/* Macros for zero-order pages (potentially) containing multiple RX buffers */
++#define RX_DATA_OFFSET(_data) \
++ (((unsigned long) (_data)) & (PAGE_SIZE-1))
++#define RX_BUF_OFFSET(_rx_buf) \
++ RX_DATA_OFFSET((_rx_buf)->data)
+
-+ ring->fun = pasemi_dma_alloc_fun();
-+ if (ring->fun < 0)
-+ goto out_fun;
++#define RX_PAGE_SIZE(_efx) \
++ (PAGE_SIZE * (1u << (_efx)->rx_buffer_order))
+
-+ 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;
++/**************************************************************************
++ *
++ * Linux generic LRO handling
++ *
++ **************************************************************************
++ */
+
-+ write_dma_reg(PAS_DMA_TXCHAN_CFG(chno), cfg);
++static int efx_lro_get_skb_hdr(struct sk_buff *skb, void **ip_hdr,
++ void **tcpudp_hdr, u64 *hdr_flags, void *priv)
++{
++ struct efx_channel *channel = (struct efx_channel *)priv;
++ struct iphdr *iph;
++ struct tcphdr *th;
+
-+ /* 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);
++ iph = (struct iphdr *)skb->data;
++ if (skb->protocol != htons(ETH_P_IP) || iph->protocol != IPPROTO_TCP)
++ goto fail;
+
-+ return ring;
++ th = (struct tcphdr *)(skb->data + iph->ihl * 4);
+
-+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:
++ *tcpudp_hdr = th;
++ *ip_hdr = iph;
++ *hdr_flags = LRO_IPV4 | LRO_TCP;
+
-+ return NULL;
++ channel->rx_alloc_level += RX_ALLOC_FACTOR_LRO;
++ return 0;
++fail:
++ channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB;
++ return -1;
+}
+
-+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;
++static int efx_get_frag_hdr(struct skb_frag_struct *frag, void **mac_hdr,
++ void **ip_hdr, void **tcpudp_hdr, u64 *hdr_flags,
++ void *priv)
++{
++ struct efx_channel *channel = (struct efx_channel *)priv;
++ struct ethhdr *eh;
++ struct iphdr *iph;
++
++ /* We support EtherII and VLAN encapsulated IPv4 */
++ eh = (struct ethhdr *)(page_address(frag->page) + frag->page_offset);
++ *mac_hdr = eh;
+
-+ for (i = 0; i < MAX_CS; i++)
-+ if (mac->cs[i])
-+ mac->num_cs++;
++ if (eh->h_proto == htons(ETH_P_IP)) {
++ iph = (struct iphdr *)(eh + 1);
++ } else {
++ struct vlan_ethhdr *veh = (struct vlan_ethhdr *)eh;
++ if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP))
++ goto fail;
++
++ iph = (struct iphdr *)(veh + 1);
++ }
++ *ip_hdr = iph;
++
++ /* We can only do LRO over TCP */
++ if (iph->protocol != IPPROTO_TCP)
++ goto fail;
++
++ *hdr_flags = LRO_IPV4 | LRO_TCP;
++ *tcpudp_hdr = (struct tcphdr *)((u8 *) iph + iph->ihl * 4);
++
++ channel->rx_alloc_level += RX_ALLOC_FACTOR_LRO;
++ return 0;
++ fail:
++ channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB;
++ return -1;
+}
+
-+static void pasemi_mac_free_csring(struct pasemi_mac_csring *csring)
++int efx_lro_init(struct net_lro_mgr *lro_mgr, struct efx_nic *efx)
+{
-+ 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);
-+}
++ size_t s = sizeof(struct net_lro_desc) * EFX_MAX_LRO_DESCRIPTORS;
++ struct net_lro_desc *lro_arr;
+
- 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;
-+ }
++ /* Allocate the LRO descriptors structure */
++ lro_arr = kzalloc(s, GFP_KERNEL);
++ if (lro_arr == NULL)
++ return -ENOMEM;
+
-+ skb = TX_DESC_INFO(txring, i+1).skb;
-+ nr_frags = TX_DESC_INFO(txring, i).dma;
++ lro_mgr->lro_arr = lro_arr;
++ lro_mgr->max_desc = EFX_MAX_LRO_DESCRIPTORS;
++ lro_mgr->max_aggr = EFX_MAX_LRO_AGGR;
++ lro_mgr->frag_align_pad = EFX_PAGE_SKB_ALIGN;
+
- 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;
-+ }
++ lro_mgr->get_skb_header = efx_lro_get_skb_hdr;
++ lro_mgr->get_frag_header = efx_get_frag_hdr;
++ lro_mgr->dev = efx->net_dev;
+
-+ /* Zero out rmon counters */
-+ for (i = 0; i < 32; i++)
-+ write_mac_reg(mac, PAS_MAC_RMON(i), 0);
++ lro_mgr->features = LRO_F_NAPI;
+
- /* 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;
-+ }
++ /* We can pass packets up with the checksum intact */
++ lro_mgr->ip_summed = CHECKSUM_UNNECESSARY;
+
-+ mac->num_cs = 0;
++ lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY;
+
- /* 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)
++ return 0;
++}
++
++void efx_lro_fini(struct net_lro_mgr *lro_mgr)
+{
-+ 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;
++ kfree(lro_mgr->lro_arr);
++ lro_mgr->lro_arr = NULL;
++}
+
-+ 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;
++/**
++ * efx_init_rx_buffer_skb - create new RX buffer using skb-based allocation
++ *
++ * @rx_queue: Efx RX queue
++ * @rx_buf: RX buffer structure to populate
++ *
++ * This allocates memory for a new receive buffer, maps it for DMA,
++ * and populates a struct efx_rx_buffer with the relevant
++ * information. Return a negative error code or 0 on success.
++ */
++static inline int efx_init_rx_buffer_skb(struct efx_rx_queue *rx_queue,
++ struct efx_rx_buffer *rx_buf)
++{
++ struct efx_nic *efx = rx_queue->efx;
++ struct net_device *net_dev = efx->net_dev;
++ int skb_len = efx->rx_buffer_len;
+
-+ 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();
++ rx_buf->skb = netdev_alloc_skb(net_dev, skb_len);
++ if (unlikely(!rx_buf->skb))
++ return -ENOMEM;
++
++ /* Adjust the SKB for padding and checksum */
++ skb_reserve(rx_buf->skb, NET_IP_ALIGN);
++ rx_buf->len = skb_len - NET_IP_ALIGN;
++ rx_buf->data = (char *)rx_buf->skb->data;
++ rx_buf->skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++ rx_buf->dma_addr = pci_map_single(efx->pci_dev,
++ rx_buf->data, rx_buf->len,
++ PCI_DMA_FROMDEVICE);
++
++ if (unlikely(pci_dma_mapping_error(rx_buf->dma_addr))) {
++ dev_kfree_skb_any(rx_buf->skb);
++ rx_buf->skb = NULL;
++ return -EIO;
+ }
+
-+ /* Do the checksum offloaded */
-+ fill = csring->next_to_fill;
-+ hdr = fill;
++ return 0;
++}
+
-+ 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;
++/**
++ * efx_init_rx_buffer_page - create new RX buffer using page-based allocation
++ *
++ * @rx_queue: Efx RX queue
++ * @rx_buf: RX buffer structure to populate
++ *
++ * This allocates memory for a new receive buffer, maps it for DMA,
++ * and populates a struct efx_rx_buffer with the relevant
++ * information. Return a negative error code or 0 on success.
++ */
++static inline int efx_init_rx_buffer_page(struct efx_rx_queue *rx_queue,
++ struct efx_rx_buffer *rx_buf)
++{
++ struct efx_nic *efx = rx_queue->efx;
++ int bytes, space, offset;
+
-+ 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]);
++ bytes = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN;
+
-+ fill += i;
-+ if (fill & 1)
-+ fill++;
++ /* If there is space left in the previously allocated page,
++ * then use it. Otherwise allocate a new one */
++ rx_buf->page = rx_queue->buf_page;
++ if (rx_buf->page == NULL) {
++ dma_addr_t dma_addr;
+
-+ /* 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++;
++ rx_buf->page = alloc_pages(__GFP_COLD | __GFP_COMP | GFP_ATOMIC,
++ efx->rx_buffer_order);
++ if (unlikely(rx_buf->page == NULL))
++ return -ENOMEM;
+
-+ evt = !csring->last_event;
-+ csring->last_event = evt;
++ dma_addr = pci_map_page(efx->pci_dev, rx_buf->page,
++ 0, RX_PAGE_SIZE(efx),
++ PCI_DMA_FROMDEVICE);
++
++ if (unlikely(pci_dma_mapping_error(dma_addr))) {
++ __free_pages(rx_buf->page, efx->rx_buffer_order);
++ rx_buf->page = NULL;
++ return -EIO;
++ }
+
-+ /* 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);
++ rx_queue->buf_page = rx_buf->page;
++ rx_queue->buf_dma_addr = dma_addr;
++ rx_queue->buf_data = ((char *) page_address(rx_buf->page) +
++ EFX_PAGE_IP_ALIGN);
++ }
++
++ offset = RX_DATA_OFFSET(rx_queue->buf_data);
++ rx_buf->len = bytes;
++ rx_buf->dma_addr = rx_queue->buf_dma_addr + offset;
++ rx_buf->data = rx_queue->buf_data;
++
++ /* Try to pack multiple buffers per page */
++ if (efx->rx_buffer_order == 0) {
++ /* The next buffer starts on the next 512 byte boundary */
++ rx_queue->buf_data += ((bytes + 0x1ff) & ~0x1ff);
++ offset += ((bytes + 0x1ff) & ~0x1ff);
++
++ space = RX_PAGE_SIZE(efx) - offset;
++ if (space >= bytes) {
++ /* Refs dropped on kernel releasing each skb */
++ get_page(rx_queue->buf_page);
++ goto out;
++ }
++ }
+
-+ cs_size = fill - hdr;
-+ write_dma_reg(PAS_DMA_TXCHAN_INCR(csring->chan.chno), (cs_size) >> 1);
++ /* This is the final RX buffer for this page, so mark it for
++ * unmapping */
++ rx_queue->buf_page = NULL;
++ rx_buf->unmap_addr = rx_queue->buf_dma_addr;
+
-+ /* 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;
++ out:
++ return 0;
++}
+
-+ write_dma_reg(PAS_DMA_TXCHAN_INCR(txring->chan.chno), 2);
++/* This allocates memory for a new receive buffer, maps it for DMA,
++ * and populates a struct efx_rx_buffer with the relevant
++ * information.
++ */
++static inline int efx_init_rx_buffer(struct efx_rx_queue *rx_queue,
++ struct efx_rx_buffer *new_rx_buf)
++{
++ int rc = 0;
+
-+ return;
++ if (rx_queue->channel->rx_alloc_push_pages) {
++ new_rx_buf->skb = NULL;
++ rc = efx_init_rx_buffer_page(rx_queue, new_rx_buf);
++ rx_queue->alloc_page_count++;
++ } else {
++ new_rx_buf->page = NULL;
++ rc = efx_init_rx_buffer_skb(rx_queue, new_rx_buf);
++ rx_queue->alloc_skb_count++;
++ }
++
++ if (unlikely(rc < 0))
++ EFX_LOG_RL(rx_queue->efx, "%s RXQ[%d] =%d\n", __func__,
++ rx_queue->queue, rc);
++ return rc;
+}
+
- 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);
++static inline void efx_unmap_rx_buffer(struct efx_nic *efx,
++ struct efx_rx_buffer *rx_buf)
++{
++ if (rx_buf->page) {
++ EFX_BUG_ON_PARANOID(rx_buf->skb);
++ if (rx_buf->unmap_addr) {
++ pci_unmap_page(efx->pci_dev, rx_buf->unmap_addr,
++ RX_PAGE_SIZE(efx), PCI_DMA_FROMDEVICE);
++ rx_buf->unmap_addr = 0;
+ }
++ } else if (likely(rx_buf->skb)) {
++ pci_unmap_single(efx->pci_dev, rx_buf->dma_addr,
++ rx_buf->len, PCI_DMA_FROMDEVICE);
+ }
-
-- 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);
++static inline void efx_free_rx_buffer(struct efx_nic *efx,
++ struct efx_rx_buffer *rx_buf)
++{
++ if (rx_buf->page) {
++ __free_pages(rx_buf->page, efx->rx_buffer_order);
++ rx_buf->page = NULL;
++ } else if (likely(rx_buf->skb)) {
++ dev_kfree_skb_any(rx_buf->skb);
++ rx_buf->skb = NULL;
+ }
++}
+
-+ 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)
++static inline void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue,
++ struct efx_rx_buffer *rx_buf)
+{
-+ const struct pasemi_mac *mac = netdev_priv(dev);
++ efx_unmap_rx_buffer(rx_queue->efx, rx_buf);
++ efx_free_rx_buffer(rx_queue->efx, rx_buf);
++}
+
-+ disable_irq(mac->tx->chan.irq);
-+ pasemi_mac_tx_intr(mac->tx->chan.irq, mac->tx);
-+ enable_irq(mac->tx->chan.irq);
++/**
++ * efx_fast_push_rx_descriptors - push new RX descriptors quickly
++ * @rx_queue: RX descriptor queue
++ * @retry: Recheck the fill level
++ * This will aim to fill the RX descriptor queue up to
++ * @rx_queue->@fast_fill_limit. If there is insufficient atomic
++ * memory to do so, the caller should retry.
++ */
++static int __efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue,
++ int retry)
++{
++ struct efx_rx_buffer *rx_buf;
++ unsigned fill_level, index;
++ int i, space, rc = 0;
++
++ /* Calculate current fill level. Do this outside the lock,
++ * because most of the time we'll end up not wanting to do the
++ * fill anyway.
++ */
++ fill_level = (rx_queue->added_count - rx_queue->removed_count);
++ EFX_BUG_ON_PARANOID(fill_level >
++ rx_queue->efx->type->rxd_ring_mask + 1);
+
-+ disable_irq(mac->rx->chan.irq);
-+ pasemi_mac_rx_intr(mac->rx->chan.irq, mac->rx);
-+ enable_irq(mac->rx->chan.irq);
-+}
-+#endif
++ /* Don't fill if we don't need to */
++ if (fill_level >= rx_queue->fast_fill_trigger)
++ return 0;
+
- 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);
++ /* Record minimum fill level */
++ if (unlikely(fill_level < rx_queue->min_fill))
++ if (fill_level)
++ rx_queue->min_fill = fill_level;
++
++ /* Acquire RX add lock. If this lock is contended, then a fast
++ * fill must already be in progress (e.g. in the refill
++ * tasklet), so we don't need to do anything
++ */
++ if (!spin_trylock_bh(&rx_queue->add_lock))
++ return -1;
+
-+ }
++ retry:
++ /* Recalculate current fill level now that we have the lock */
++ fill_level = (rx_queue->added_count - rx_queue->removed_count);
++ EFX_BUG_ON_PARANOID(fill_level >
++ rx_queue->efx->type->rxd_ring_mask + 1);
++ space = rx_queue->fast_fill_limit - fill_level;
++ if (space < EFX_RX_BATCH)
++ goto out_unlock;
+
-+ /* 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;
++ EFX_TRACE(rx_queue->efx, "RX queue %d fast-filling descriptor ring from"
++ " level %d to level %d using %s allocation\n",
++ rx_queue->queue, fill_level, rx_queue->fast_fill_limit,
++ rx_queue->channel->rx_alloc_push_pages ? "page" : "skb");
++
++ do {
++ for (i = 0; i < EFX_RX_BATCH; ++i) {
++ index = (rx_queue->added_count &
++ rx_queue->efx->type->rxd_ring_mask);
++ rx_buf = efx_rx_buffer(rx_queue, index);
++ rc = efx_init_rx_buffer(rx_queue, rx_buf);
++ if (unlikely(rc))
++ goto out;
++ ++rx_queue->added_count;
+ }
- }
-
- /* Change maxf, i.e. what size frames are accepted.
-@@ -1482,6 +1720,7 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
- /* MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
- mac->bufsz = new_mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
-
-+out:
- if (running) {
- write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
- rcmdsta | PAS_DMA_RXINT_RCMDSTA_EN);
-@@ -1494,7 +1733,7 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
- pasemi_mac_intf_enable(mac);
- }
-
-- return 0;
-+ return ret;
- }
-
- static int __devinit
-@@ -1528,7 +1767,7 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
- netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64);
-
- dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG |
-- NETIF_F_HIGHDMA;
-+ NETIF_F_HIGHDMA | NETIF_F_GSO;
-
- mac->lro_mgr.max_aggr = LRO_MAX_AGGR;
- mac->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS;
-@@ -1588,8 +1827,12 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
- dev->mtu = PE_DEF_MTU;
- /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
- mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
-+#ifdef CONFIG_NET_POLL_CONTROLLER
-+ dev->poll_controller = pasemi_mac_netpoll;
-+#endif
-
- dev->change_mtu = pasemi_mac_change_mtu;
-+ dev->ethtool_ops = &pasemi_mac_ethtool_ops;
-
- if (err)
- goto out;
-diff --git a/drivers/net/pasemi_mac.h b/drivers/net/pasemi_mac.h
-index 99e7b93..1a115ec 100644
---- a/drivers/net/pasemi_mac.h
-+++ b/drivers/net/pasemi_mac.h
-@@ -26,7 +26,14 @@
- #include <linux/spinlock.h>
- #include <linux/phy.h>
-
-+/* Must be a power of two */
-+#define RX_RING_SIZE 2048
-+#define TX_RING_SIZE 4096
-+#define CS_RING_SIZE (TX_RING_SIZE*2)
++ } while ((space -= EFX_RX_BATCH) >= EFX_RX_BATCH);
+
++ EFX_TRACE(rx_queue->efx, "RX queue %d fast-filled descriptor ring "
++ "to level %d\n", rx_queue->queue,
++ rx_queue->added_count - rx_queue->removed_count);
+
- #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;
-+};
++ out:
++ /* Send write pointer to card. */
++ falcon_notify_rx_desc(rx_queue);
+
- 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)])
++ /* If the fast fill is running inside from the refill tasklet, then
++ * for SMP systems it may be running on a different CPU to
++ * RX event processing, which means that the fill level may now be
++ * out of date. */
++ if (unlikely(retry && (rc == 0)))
++ goto retry;
+
-+#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)
++ out_unlock:
++ spin_unlock_bh(&rx_queue->add_lock);
+
- #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)
-
++ return rc;
++}
+
- #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.
++/**
++ * efx_fast_push_rx_descriptors - push new RX descriptors quickly
++ * @rx_queue: RX descriptor queue
+ *
-+ * You 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
++ * This will aim to fill the RX descriptor queue up to
++ * @rx_queue->@fast_fill_limit. If there is insufficient memory to do so,
++ * it will schedule a work item to immediately continue the fast fill
+ */
++void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue)
++{
++ int rc;
+
++ rc = __efx_fast_push_rx_descriptors(rx_queue, 0);
++ if (unlikely(rc)) {
++ /* Schedule the work item to run immediately. The hope is
++ * that work is immediately pending to free some memory
++ * (e.g. an RX event or TX completion)
++ */
++ efx_schedule_slow_fill(rx_queue, 0);
++ }
++}
+
-+#include <linux/netdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/pci.h>
-+#include <linux/inet_lro.h>
++void efx_rx_work(struct work_struct *data)
++{
++ struct efx_rx_queue *rx_queue;
++ int rc;
+
-+#include <asm/pasemi_dma.h>
-+#include "pasemi_mac.h"
++ rx_queue = container_of(data, struct efx_rx_queue, work.work);
+
-+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" },
-+};
++ if (unlikely(!rx_queue->channel->enabled))
++ return;
+
-+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;
++ EFX_TRACE(rx_queue->efx, "RX queue %d worker thread executing on CPU "
++ "%d\n", rx_queue->queue, raw_smp_processor_id());
+
-+ return phy_ethtool_gset(phydev, cmd);
++ ++rx_queue->slow_fill_count;
++ /* Push new RX descriptors, allowing at least 1 jiffy for
++ * the kernel to free some more memory. */
++ rc = __efx_fast_push_rx_descriptors(rx_queue, 1);
++ if (rc)
++ efx_schedule_slow_fill(rx_queue, 1);
+}
+
-+static void
-+pasemi_mac_ethtool_get_drvinfo(struct net_device *netdev,
-+ struct ethtool_drvinfo *drvinfo)
++static inline void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
++ struct efx_rx_buffer *rx_buf,
++ int len, int *discard,
++ int *leak_packet)
+{
-+ struct pasemi_mac *mac;
-+ mac = netdev_priv(netdev);
++ struct efx_nic *efx = rx_queue->efx;
++ unsigned max_len = rx_buf->len - efx->type->rx_buffer_padding;
+
-+ /* 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);
-+}
++ if (likely(len <= max_len))
++ return;
+
-+static u32
-+pasemi_mac_ethtool_get_msglevel(struct net_device *netdev)
-+{
-+ struct pasemi_mac *mac = netdev_priv(netdev);
-+ return mac->msg_enable;
++ /* The packet must be discarded, but this is only a fatal error
++ * if the caller indicated it was
++ */
++ *discard = 1;
++
++ if ((len > rx_buf->len) && EFX_WORKAROUND_8071(efx)) {
++ EFX_ERR_RL(efx, " RX queue %d seriously overlength "
++ "RX event (0x%x > 0x%x+0x%x). Leaking\n",
++ rx_queue->queue, len, max_len,
++ efx->type->rx_buffer_padding);
++ /* If this buffer was skb-allocated, then the meta
++ * data at the end of the skb will be trashed. So
++ * we have no choice but to leak the fragment.
++ */
++ *leak_packet = (rx_buf->skb != NULL);
++ efx_schedule_reset(efx, RESET_TYPE_RX_RECOVERY);
++ } else {
++ EFX_ERR_RL(efx, " RX queue %d overlength RX event "
++ "(0x%x > 0x%x)\n", rx_queue->queue, len, max_len);
++ }
++
++ rx_queue->channel->n_rx_overlength++;
+}
+
-+static void
-+pasemi_mac_ethtool_set_msglevel(struct net_device *netdev,
-+ u32 level)
++/* Pass a received packet up through the generic LRO stack
++ *
++ * Handles driverlink veto, and passes the fragment up via
++ * the appropriate LRO method
++ */
++static inline void efx_rx_packet_lro(struct efx_channel *channel,
++ struct efx_rx_buffer *rx_buf)
+{
-+ struct pasemi_mac *mac = netdev_priv(netdev);
-+ mac->msg_enable = level;
-+}
++ struct net_lro_mgr *lro_mgr = &channel->lro_mgr;
++ void *priv = channel;
+
++ /* Pass the skb/page into the LRO engine */
++ if (rx_buf->page) {
++ struct skb_frag_struct frags;
+
-+static void
-+pasemi_mac_ethtool_get_ringparam(struct net_device *netdev,
-+ struct ethtool_ringparam *ering)
-+{
-+ struct pasemi_mac *mac = netdev->priv;
++ frags.page = rx_buf->page;
++ frags.page_offset = RX_BUF_OFFSET(rx_buf);
++ frags.size = rx_buf->len;
+
-+ 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;
-+}
++ lro_receive_frags(lro_mgr, &frags, rx_buf->len,
++ rx_buf->len, priv, 0);
+
-+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;
++ EFX_BUG_ON_PARANOID(rx_buf->skb);
++ rx_buf->page = NULL;
++ } else {
++ EFX_BUG_ON_PARANOID(!rx_buf->skb);
++
++ lro_receive_skb(lro_mgr, rx_buf->skb, priv);
++ rx_buf->skb = NULL;
+ }
+}
+
-+static void pasemi_mac_get_ethtool_stats(struct net_device *netdev,
-+ struct ethtool_stats *stats, u64 *data)
++/* Allocate and construct an SKB around a struct page.*/
++static inline struct sk_buff *efx_rx_mk_skb(struct efx_rx_buffer *rx_buf,
++ struct efx_nic *efx,
++ int hdr_len)
+{
-+ struct pasemi_mac *mac = netdev->priv;
-+ int i;
++ struct sk_buff *skb;
+
-+ 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));
++ /* Allocate an SKB to store the headers */
++ skb = netdev_alloc_skb(efx->net_dev, hdr_len + EFX_PAGE_SKB_ALIGN);
++ if (unlikely(skb == NULL)) {
++ EFX_ERR_RL(efx, "RX out of memory for skb\n");
++ return NULL;
++ }
++
++ EFX_BUG_ON_PARANOID(skb_shinfo(skb)->nr_frags);
++ EFX_BUG_ON_PARANOID(rx_buf->len < hdr_len);
++
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ skb_reserve(skb, EFX_PAGE_SKB_ALIGN);
++
++ skb->len = rx_buf->len;
++ skb->truesize = rx_buf->len + sizeof(struct sk_buff);
++ memcpy(skb->data, rx_buf->data, hdr_len);
++ skb->tail += hdr_len;
++
++ /* Append the remaining page onto the frag list */
++ if (unlikely(rx_buf->len > hdr_len)) {
++ struct skb_frag_struct *frag = skb_shinfo(skb)->frags;
++ frag->page = rx_buf->page;
++ frag->page_offset = RX_BUF_OFFSET(rx_buf) + hdr_len;
++ frag->size = skb->len - hdr_len;
++ skb_shinfo(skb)->nr_frags = 1;
++ skb->data_len = frag->size;
++ } else {
++ __free_pages(rx_buf->page, efx->rx_buffer_order);
++ skb->data_len = 0;
++ }
++
++ /* Ownership has transferred from the rx_buf to skb */
++ rx_buf->page = NULL;
++
++ /* Move past the ethernet header */
++ skb->protocol = eth_type_trans(skb, efx->net_dev);
++
++ return skb;
+}
+
-+static void pasemi_mac_get_strings(struct net_device *netdev, u32 stringset,
-+ u8 *data)
++void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
++ unsigned int len, int checksummed, int discard)
+{
-+ memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys));
-+}
++ struct efx_nic *efx = rx_queue->efx;
++ struct efx_rx_buffer *rx_buf;
++ int leak_packet = 0;
++
++ rx_buf = efx_rx_buffer(rx_queue, index);
++ EFX_BUG_ON_PARANOID(!rx_buf->data);
++ EFX_BUG_ON_PARANOID(rx_buf->skb && rx_buf->page);
++ EFX_BUG_ON_PARANOID(!(rx_buf->skb || rx_buf->page));
++
++ /* This allows the refill path to post another buffer.
++ * EFX_RXD_HEAD_ROOM ensures that the slot we are using
++ * isn't overwritten yet.
++ */
++ rx_queue->removed_count++;
++
++ /* Validate the length encoded in the event vs the descriptor pushed */
++ efx_rx_packet__check_len(rx_queue, rx_buf, len,
++ &discard, &leak_packet);
++
++ EFX_TRACE(efx, "RX queue %d received id %x at %llx+%x %s%s\n",
++ rx_queue->queue, index,
++ (unsigned long long)rx_buf->dma_addr, len,
++ (checksummed ? " [SUMMED]" : ""),
++ (discard ? " [DISCARD]" : ""));
++
++ /* Discard packet, if instructed to do so */
++ if (unlikely(discard)) {
++ if (unlikely(leak_packet))
++ rx_queue->channel->n_skbuff_leaks++;
++ else
++ /* We haven't called efx_unmap_rx_buffer yet,
++ * so fini the entire rx_buffer here */
++ efx_fini_rx_buffer(rx_queue, rx_buf);
++ return;
++ }
+
-+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,
-+};
++ /* Release card resources - assumes all RX buffers consumed in-order
++ * per RX queue
++ */
++ efx_unmap_rx_buffer(efx, rx_buf);
+
-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)
++ /* Prefetch nice and early so data will (hopefully) be in cache by
++ * the time we look at it.
++ */
++ prefetch(rx_buf->data);
++
++ /* Pipeline receives so that we give time for packet headers to be
++ * prefetched into cache.
++ */
++ rx_buf->len = len;
++ if (rx_queue->channel->rx_pkt)
++ __efx_rx_packet(rx_queue->channel,
++ rx_queue->channel->rx_pkt,
++ rx_queue->channel->rx_pkt_csummed);
++ rx_queue->channel->rx_pkt = rx_buf;
++ rx_queue->channel->rx_pkt_csummed = checksummed;
++}
++
++/* Handle a received packet. Second half: Touches packet payload. */
++void __efx_rx_packet(struct efx_channel *channel,
++ struct efx_rx_buffer *rx_buf, int checksummed)
+{
-+ int ret;
++ struct efx_nic *efx = channel->efx;
++ struct sk_buff *skb;
++ int lro = efx->net_dev->features & NETIF_F_LRO;
+
-+ /* Aneg firsly. */
-+ ret = genphy_config_aneg(phydev);
++ if (rx_buf->skb) {
++ prefetch(skb_shinfo(rx_buf->skb));
+
-+ /* Then we can set up the delay. */
-+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
-+ u16 reg;
++ skb_put(rx_buf->skb, rx_buf->len);
+
-+ /*
-+ * There is no BCM5481 specification available, so down
-+ * here is everything we know about "register 0x18". This
-+ * at least helps BCM5481 to successfuly receive packets
-+ * on MPC8360E-RDK board. Peter Barada <peterb at logicpd.com>
-+ * says: "This sets delay between the RXD and RXC signals
-+ * instead of using trace lengths to achieve timing".
-+ */
++ /* Move past the ethernet header. rx_buf->data still points
++ * at the ethernet header */
++ rx_buf->skb->protocol = eth_type_trans(rx_buf->skb,
++ efx->net_dev);
++ }
+
-+ /* Set RDX clk delay. */
-+ reg = 0x7 | (0x7 << 12);
-+ phy_write(phydev, 0x18, reg);
++ /* Both our generic-LRO and SFC-SSR support skb and page based
++ * allocation, but neither support switching from one to the
++ * other on the fly. If we spot that the allocation mode has
++ * changed, then flush the LRO state.
++ */
++ if (unlikely(channel->rx_alloc_pop_pages != (rx_buf->page != NULL))) {
++ efx_flush_lro(channel);
++ channel->rx_alloc_pop_pages = (rx_buf->page != NULL);
++ }
++ if (likely(checksummed && lro)) {
++ efx_rx_packet_lro(channel, rx_buf);
++ goto done;
++ }
+
-+ reg = phy_read(phydev, 0x18);
-+ /* Set RDX-RXC skew. */
-+ reg |= (1 << 8);
-+ /* Write bits 14:0. */
-+ reg |= (1 << 15);
-+ phy_write(phydev, 0x18, reg);
++ /* Form an skb if required */
++ if (rx_buf->page) {
++ int hdr_len = min(rx_buf->len, EFX_SKB_HEADERS);
++ skb = efx_rx_mk_skb(rx_buf, efx, hdr_len);
++ if (unlikely(skb == NULL)) {
++ efx_free_rx_buffer(efx, rx_buf);
++ goto done;
++ }
++ } else {
++ /* We now own the SKB */
++ skb = rx_buf->skb;
++ rx_buf->skb = NULL;
+ }
+
-+ return ret;
++ EFX_BUG_ON_PARANOID(rx_buf->page);
++ EFX_BUG_ON_PARANOID(rx_buf->skb);
++ EFX_BUG_ON_PARANOID(!skb);
++
++ /* Set the SKB flags */
++ if (unlikely(!checksummed || !efx->rx_checksum_enabled))
++ skb->ip_summed = CHECKSUM_NONE;
++
++ /* Pass the packet up */
++ netif_receive_skb(skb);
++
++ /* Update allocation strategy method */
++ channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB;
++
++ /* fall-thru */
++done:
++ efx->net_dev->last_rx = jiffies;
+}
+
- 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 },
-+};
++void efx_rx_strategy(struct efx_channel *channel)
++{
++ enum efx_rx_alloc_method method = rx_alloc_method;
+
-+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 },
-+};
++ /* Only makes sense to use page based allocation if LRO is enabled */
++ if (!(channel->efx->net_dev->features & NETIF_F_LRO)) {
++ method = RX_ALLOC_METHOD_SKB;
++ } else if (method == RX_ALLOC_METHOD_AUTO) {
++ /* Constrain the rx_alloc_level */
++ if (channel->rx_alloc_level < 0)
++ channel->rx_alloc_level = 0;
++ else if (channel->rx_alloc_level > RX_ALLOC_LEVEL_MAX)
++ channel->rx_alloc_level = RX_ALLOC_LEVEL_MAX;
+
- 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);
++ /* Decide on the allocation method */
++ method = ((channel->rx_alloc_level > RX_ALLOC_LEVEL_LRO) ?
++ RX_ALLOC_METHOD_PAGE : RX_ALLOC_METHOD_SKB);
++ }
+
- 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);
++ /* Push the option */
++ channel->rx_alloc_push_pages = (method == RX_ALLOC_METHOD_PAGE);
++}
+
-+/*
-+ * 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 *))
++int efx_probe_rx_queue(struct efx_rx_queue *rx_queue)
+{
-+ struct phy_fixup *fixup;
++ struct efx_nic *efx = rx_queue->efx;
++ unsigned int rxq_size;
++ int rc;
+
-+ fixup = kzalloc(sizeof(struct phy_fixup), GFP_KERNEL);
-+ if (!fixup)
-+ return -ENOMEM;
++ EFX_LOG(efx, "creating RX queue %d\n", rx_queue->queue);
+
-+ strncpy(fixup->bus_id, bus_id, BUS_ID_SIZE);
-+ fixup->phy_uid = phy_uid;
-+ fixup->phy_uid_mask = phy_uid_mask;
-+ fixup->run = run;
++ /* Allocate RX buffers */
++ rxq_size = (efx->type->rxd_ring_mask + 1) * sizeof(*rx_queue->buffer);
++ rx_queue->buffer = kzalloc(rxq_size, GFP_KERNEL);
++ if (!rx_queue->buffer) {
++ rc = -ENOMEM;
++ goto fail1;
++ }
+
-+ mutex_lock(&phy_fixup_lock);
-+ list_add_tail(&fixup->list, &phy_fixup_list);
-+ mutex_unlock(&phy_fixup_lock);
++ rc = falcon_probe_rx(rx_queue);
++ if (rc)
++ goto fail2;
+
+ 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);
++ fail2:
++ kfree(rx_queue->buffer);
++ rx_queue->buffer = NULL;
++ fail1:
++ rx_queue->used = 0;
+
-+/* 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);
++ return rc;
+}
-+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)
++int efx_init_rx_queue(struct efx_rx_queue *rx_queue)
+{
-+ if (strcmp(fixup->bus_id, phydev->dev.bus_id) != 0)
-+ if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0)
-+ return 0;
++ struct efx_nic *efx = rx_queue->efx;
++ unsigned int max_fill, trigger, limit;
+
-+ if ((fixup->phy_uid & fixup->phy_uid_mask) !=
-+ (phydev->phy_id & fixup->phy_uid_mask))
-+ if (fixup->phy_uid != PHY_ANY_UID)
-+ return 0;
++ EFX_LOG(rx_queue->efx, "initialising RX queue %d\n", rx_queue->queue);
+
-+ return 1;
++ /* Initialise ptr fields */
++ rx_queue->added_count = 0;
++ rx_queue->notified_count = 0;
++ rx_queue->removed_count = 0;
++ rx_queue->min_fill = -1U;
++ rx_queue->min_overfill = -1U;
++
++ /* Initialise limit fields */
++ max_fill = efx->type->rxd_ring_mask + 1 - EFX_RXD_HEAD_ROOM;
++ trigger = max_fill * min(rx_refill_threshold, 100U) / 100U;
++ limit = max_fill * min(rx_refill_limit, 100U) / 100U;
++
++ rx_queue->max_fill = max_fill;
++ rx_queue->fast_fill_trigger = trigger;
++ rx_queue->fast_fill_limit = limit;
++
++ /* Set up RX descriptor ring */
++ return falcon_init_rx(rx_queue);
+}
+
-+/* Runs any matching fixups for this phydev */
-+int phy_scan_fixups(struct phy_device *phydev)
++void efx_fini_rx_queue(struct efx_rx_queue *rx_queue)
+{
-+ struct phy_fixup *fixup;
++ int i;
++ struct efx_rx_buffer *rx_buf;
+
-+ mutex_lock(&phy_fixup_lock);
-+ list_for_each_entry(fixup, &phy_fixup_list, list) {
-+ if (phy_needs_fixup(phydev, fixup)) {
-+ int err;
++ EFX_LOG(rx_queue->efx, "shutting down RX queue %d\n", rx_queue->queue);
+
-+ err = fixup->run(phydev);
++ falcon_fini_rx(rx_queue);
+
-+ if (err < 0)
-+ return err;
++ /* Release RX buffers NB start at index 0 not current HW ptr */
++ if (rx_queue->buffer) {
++ for (i = 0; i <= rx_queue->efx->type->rxd_ring_mask; i++) {
++ rx_buf = efx_rx_buffer(rx_queue, i);
++ efx_fini_rx_buffer(rx_queue, rx_buf);
+ }
+ }
-+ mutex_unlock(&phy_fixup_lock);
+
-+ return 0;
++ /* For a page that is part-way through splitting into RX buffers */
++ if (rx_queue->buf_page != NULL) {
++ pci_unmap_page(rx_queue->efx->pci_dev, rx_queue->buf_dma_addr,
++ RX_PAGE_SIZE(rx_queue->efx), PCI_DMA_FROMDEVICE);
++ __free_pages(rx_queue->buf_page,
++ rx_queue->efx->rx_buffer_order);
++ rx_queue->buf_page = NULL;
++ }
+}
-+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;
++void efx_remove_rx_queue(struct efx_rx_queue *rx_queue)
++{
++ EFX_LOG(rx_queue->efx, "destroying RX queue %d\n", rx_queue->queue);
+
-+ *phy_id |= (phy_reg & 0xffff);
++ falcon_remove_rx(rx_queue);
+
-+ return 0;
++ kfree(rx_queue->buffer);
++ rx_queue->buffer = NULL;
++ rx_queue->used = 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
++void efx_flush_lro(struct efx_channel *channel)
++{
++ lro_flush_all(&channel->lro_mgr);
++}
++
++
++module_param(rx_alloc_method, int, 0644);
++MODULE_PARM_DESC(rx_alloc_method, "Allocation method used for RX buffers");
++
++module_param(rx_refill_threshold, uint, 0444);
++MODULE_PARM_DESC(rx_refill_threshold,
++ "RX descriptor ring fast/slow fill threshold (%)");
++
+diff --git a/drivers/net/sfc/rx.h b/drivers/net/sfc/rx.h
+new file mode 100644
+index 0000000..f35e377
+--- /dev/null
++++ b/drivers/net/sfc/rx.h
+@@ -0,0 +1,29 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2006 Solarflare Communications Inc.
+ *
-+ * Description: Reads the ID registers of the PHY at @addr on the
-+ * @bus, then allocates and returns the phy_device to represent it.
++ * 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, incorporated herein by reference.
+ */
-+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);
++#ifndef EFX_RX_H
++#define EFX_RX_H
+
- 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;
++#include "net_driver.h"
+
-+ /*
-+ * Run the fixups on this PHY, just in case the
-+ * board code needs to change something after a reset
-+ */
-+ err = phy_scan_fixups(phydev);
++int efx_probe_rx_queue(struct efx_rx_queue *rx_queue);
++void efx_remove_rx_queue(struct efx_rx_queue *rx_queue);
++int efx_init_rx_queue(struct efx_rx_queue *rx_queue);
++void efx_fini_rx_queue(struct efx_rx_queue *rx_queue);
++
++int efx_lro_init(struct net_lro_mgr *lro_mgr, struct efx_nic *efx);
++void efx_lro_fini(struct net_lro_mgr *lro_mgr);
++void efx_flush_lro(struct efx_channel *channel);
++void efx_rx_strategy(struct efx_channel *channel);
++void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue);
++void efx_rx_work(struct work_struct *data);
++void __efx_rx_packet(struct efx_channel *channel,
++ struct efx_rx_buffer *rx_buf, int checksummed);
+
-+ 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;
++#endif /* EFX_RX_H */
+diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c
+new file mode 100644
+index 0000000..11fa9fb
+--- /dev/null
++++ b/drivers/net/sfc/sfe4001.c
+@@ -0,0 +1,252 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2007 Solarflare Communications 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, incorporated herein by reference.
++ */
+
-+ 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)
++/*****************************************************************************
++ * Support for the SFE4001 NIC: driver code for the PCA9539 I/O expander that
++ * controls the PHY power rails, and for the MAX6647 temp. sensor used to check
++ * the PHY
++ */
++#include <linux/delay.h>
++#include "efx.h"
++#include "phy.h"
++#include "boards.h"
++#include "falcon.h"
++#include "falcon_hwdefs.h"
++#include "mac.h"
++
++/**************************************************************************
++ *
++ * I2C IO Expander device
++ *
++ **************************************************************************/
++#define PCA9539 0x74
++
++#define P0_IN 0x00
++#define P0_OUT 0x02
++#define P0_INVERT 0x04
++#define P0_CONFIG 0x06
++
++#define P0_EN_1V0X_LBN 0
++#define P0_EN_1V0X_WIDTH 1
++#define P0_EN_1V2_LBN 1
++#define P0_EN_1V2_WIDTH 1
++#define P0_EN_2V5_LBN 2
++#define P0_EN_2V5_WIDTH 1
++#define P0_EN_3V3X_LBN 3
++#define P0_EN_3V3X_WIDTH 1
++#define P0_EN_5V_LBN 4
++#define P0_EN_5V_WIDTH 1
++#define P0_SHORTEN_JTAG_LBN 5
++#define P0_SHORTEN_JTAG_WIDTH 1
++#define P0_X_TRST_LBN 6
++#define P0_X_TRST_WIDTH 1
++#define P0_DSP_RESET_LBN 7
++#define P0_DSP_RESET_WIDTH 1
++
++#define P1_IN 0x01
++#define P1_OUT 0x03
++#define P1_INVERT 0x05
++#define P1_CONFIG 0x07
++
++#define P1_AFE_PWD_LBN 0
++#define P1_AFE_PWD_WIDTH 1
++#define P1_DSP_PWD25_LBN 1
++#define P1_DSP_PWD25_WIDTH 1
++#define P1_RESERVED_LBN 2
++#define P1_RESERVED_WIDTH 2
++#define P1_SPARE_LBN 4
++#define P1_SPARE_WIDTH 4
++
++
++/**************************************************************************
++ *
++ * Temperature Sensor
++ *
++ **************************************************************************/
++#define MAX6647 0x4e
++
++#define RLTS 0x00
++#define RLTE 0x01
++#define RSL 0x02
++#define RCL 0x03
++#define RCRA 0x04
++#define RLHN 0x05
++#define RLLI 0x06
++#define RRHI 0x07
++#define RRLS 0x08
++#define WCRW 0x0a
++#define WLHO 0x0b
++#define WRHA 0x0c
++#define WRLN 0x0e
++#define OSHT 0x0f
++#define REET 0x10
++#define RIET 0x11
++#define RWOE 0x19
++#define RWOI 0x20
++#define HYS 0x21
++#define QUEUE 0x22
++#define MFID 0xfe
++#define REVID 0xff
++
++/* Status bits */
++#define MAX6647_BUSY (1 << 7) /* ADC is converting */
++#define MAX6647_LHIGH (1 << 6) /* Local high temp. alarm */
++#define MAX6647_LLOW (1 << 5) /* Local low temp. alarm */
++#define MAX6647_RHIGH (1 << 4) /* Remote high temp. alarm */
++#define MAX6647_RLOW (1 << 3) /* Remote low temp. alarm */
++#define MAX6647_FAULT (1 << 2) /* DXN/DXP short/open circuit */
++#define MAX6647_EOT (1 << 1) /* Remote junction overtemp. */
++#define MAX6647_IOT (1 << 0) /* Local junction overtemp. */
++
++static const u8 xgphy_max_temperature = 90;
++
++void sfe4001_poweroff(struct efx_nic *efx)
++{
++ struct efx_i2c_interface *i2c = &efx->i2c;
++
++ u8 cfg, out, in;
++
++ EFX_INFO(efx, "%s\n", __func__);
++
++ /* Turn off all power rails */
++ out = 0xff;
++ (void) efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1);
++
++ /* Disable port 1 outputs on IO expander */
++ cfg = 0xff;
++ (void) efx_i2c_write(i2c, PCA9539, P1_CONFIG, &cfg, 1);
++
++ /* Disable port 0 outputs on IO expander */
++ cfg = 0xff;
++ (void) efx_i2c_write(i2c, PCA9539, P0_CONFIG, &cfg, 1);
++
++ /* Clear any over-temperature alert */
++ (void) efx_i2c_read(i2c, MAX6647, RSL, &in, 1);
++}
++
++/* This board uses an I2C expander to provider power to the PHY, which needs to
++ * be turned on before the PHY can be used.
++ * Context: Process context, rtnl lock held
++ */
++int sfe4001_poweron(struct efx_nic *efx)
+{
-+ int status;
-+ struct gelic_card *card;
-+ u64 v1, v2;
++ struct efx_i2c_interface *i2c = &efx->i2c;
++ unsigned int count;
++ int rc;
++ u8 out, in, cfg;
++ efx_dword_t reg;
+
-+ if (ps3_compare_firmware_version(2, 2, 0) < 0 ||
-+ !capable(CAP_NET_ADMIN))
-+ return -EPERM;
++ /* 10Xpress has fixed-function LED pins, so there is no board-specific
++ * blink code. */
++ efx->board_info.blink = tenxpress_phy_blink;
++
++ /* Ensure that XGXS and XAUI SerDes are held in reset */
++ EFX_POPULATE_DWORD_7(reg, XX_PWRDNA_EN, 1,
++ XX_PWRDNB_EN, 1,
++ XX_RSTPLLAB_EN, 1,
++ XX_RESETA_EN, 1,
++ XX_RESETB_EN, 1,
++ XX_RSTXGXSRX_EN, 1,
++ XX_RSTXGXSTX_EN, 1);
++ falcon_xmac_writel(efx, ®, XX_PWR_RST_REG_MAC);
++ udelay(10);
+
-+ if (wol->wolopts & ~WAKE_MAGIC)
-+ return -EINVAL;
++ /* Set DSP over-temperature alert threshold */
++ EFX_INFO(efx, "DSP cut-out at %dC\n", xgphy_max_temperature);
++ rc = efx_i2c_write(i2c, MAX6647, WLHO,
++ &xgphy_max_temperature, 1);
++ if (rc)
++ goto fail1;
+
-+ 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;
-+ }
++ /* Read it back and verify */
++ rc = efx_i2c_read(i2c, MAX6647, RLHN, &in, 1);
++ if (rc)
++ goto fail1;
++ if (in != xgphy_max_temperature) {
++ rc = -EFAULT;
++ goto fail1;
+ }
++
++ /* Clear any previous over-temperature alert */
++ rc = efx_i2c_read(i2c, MAX6647, RSL, &in, 1);
++ if (rc)
++ goto fail1;
++
++ /* Enable port 0 and port 1 outputs on IO expander */
++ cfg = 0x00;
++ rc = efx_i2c_write(i2c, PCA9539, P0_CONFIG, &cfg, 1);
++ if (rc)
++ goto fail1;
++ cfg = 0xff & ~(1 << P1_SPARE_LBN);
++ rc = efx_i2c_write(i2c, PCA9539, P1_CONFIG, &cfg, 1);
++ if (rc)
++ goto fail2;
++
++ /* Turn all power off then wait 1 sec. This ensures PHY is reset */
++ out = 0xff & ~((0 << P0_EN_1V2_LBN) | (0 << P0_EN_2V5_LBN) |
++ (0 << P0_EN_3V3X_LBN) | (0 << P0_EN_5V_LBN) |
++ (0 << P0_EN_1V0X_LBN));
++ rc = efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1);
++ if (rc)
++ goto fail3;
++
++ schedule_timeout_uninterruptible(HZ);
++ count = 0;
++ do {
++ /* Turn on 1.2V, 2.5V, 3.3V and 5V power rails */
++ out = 0xff & ~((1 << P0_EN_1V2_LBN) | (1 << P0_EN_2V5_LBN) |
++ (1 << P0_EN_3V3X_LBN) | (1 << P0_EN_5V_LBN) |
++ (1 << P0_X_TRST_LBN));
++
++ rc = efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1);
++ if (rc)
++ goto fail3;
++ msleep(10);
++
++ /* Turn on 1V power rail */
++ out &= ~(1 << P0_EN_1V0X_LBN);
++ rc = efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1);
++ if (rc)
++ goto fail3;
++
++ EFX_INFO(efx, "waiting for power (attempt %d)...\n", count);
++
++ schedule_timeout_uninterruptible(HZ);
++
++ /* Check DSP is powered */
++ rc = efx_i2c_read(i2c, PCA9539, P1_IN, &in, 1);
++ if (rc)
++ goto fail3;
++ if (in & (1 << P1_AFE_PWD_LBN))
++ goto done;
++
++ } while (++count < 20);
++
++ EFX_INFO(efx, "timed out waiting for power\n");
++ rc = -ETIMEDOUT;
++ goto fail3;
++
+done:
-+ return status;
++ EFX_INFO(efx, "PHY is powered on\n");
++ return 0;
++
++fail3:
++ /* Turn off all power rails */
++ out = 0xff;
++ (void) efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1);
++ /* Disable port 1 outputs on IO expander */
++ out = 0xff;
++ (void) efx_i2c_write(i2c, PCA9539, P1_CONFIG, &out, 1);
++fail2:
++ /* Disable port 0 outputs on IO expander */
++ out = 0xff;
++ (void) efx_i2c_write(i2c, PCA9539, P0_CONFIG, &out, 1);
++fail1:
++ return rc;
+}
+diff --git a/drivers/net/sfc/spi.h b/drivers/net/sfc/spi.h
+new file mode 100644
+index 0000000..34412f3
+--- /dev/null
++++ b/drivers/net/sfc/spi.h
+@@ -0,0 +1,71 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005 Fen Systems Ltd.
++ * Copyright 2006 Solarflare Communications 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, incorporated herein by reference.
++ */
+
- 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,
-+};
++#ifndef EFX_SPI_H
++#define EFX_SPI_H
+
-+/* for GELIC_LV1_WOL_MAGIC_PACKET */
-+enum gelic_lv1_wol_mp_arg {
-+ GELIC_LV1_WOL_MP_DISABLE = 0,
-+ GELIC_LV1_WOL_MP_ENABLE = 1,
-+};
++#include "net_driver.h"
+
-+/* 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,
-+};
++/**************************************************************************
++ *
++ * Basic SPI command set and bit definitions
++ *
++ *************************************************************************/
+
- /* status returened from GET_ETH_PORT_STATUS */
- enum gelic_lv1_ether_port_status {
- GELIC_LV1_ETHER_LINK_UP = 0x0000000000000001L,
-diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c
-index c16de51..0d32123 100644
---- a/drivers/net/ps3_gelic_wireless.c
-+++ b/drivers/net/ps3_gelic_wireless.c
-@@ -87,7 +87,7 @@ static inline int wpa2_capable(void)
-
- static inline int precise_ie(void)
- {
-- return 0; /* FIXME */
-+ return (0 <= ps3_compare_firmware_version(2, 2, 0));
- }
- /*
- * post_eurus_cmd helpers
-diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
-index a6aeb9d..b7f7b22 100644
---- a/drivers/net/qla3xxx.c
-+++ b/drivers/net/qla3xxx.c
-@@ -2472,8 +2472,7 @@ static int ql_send_map(struct ql3_adapter *qdev,
-
- if (seg_cnt == 1) {
- /* Terminate the last segment. */
-- oal_entry->len =
-- cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
-+ oal_entry->len |= cpu_to_le32(OAL_LAST_ENTRY);
- } else {
- oal = tx_cb->oal;
- for (completed_segs=0; completed_segs<frag_cnt; completed_segs++,seg++) {
-@@ -2530,8 +2529,7 @@ static int ql_send_map(struct ql3_adapter *qdev,
- frag->size);
- }
- /* Terminate the last segment. */
-- oal_entry->len =
-- cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
-+ oal_entry->len |= cpu_to_le32(OAL_LAST_ENTRY);
- }
-
- return NETDEV_TX_OK;
-diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
-index c082cf0..157fd93 100644
---- a/drivers/net/s2io.c
-+++ b/drivers/net/s2io.c
-@@ -50,6 +50,8 @@
- * Possible values '1' for enable , '0' for disable.
- * Default is '2' - which means disable in promisc mode
- * and enable in non-promiscuous mode.
-+ * multiq: This parameter used to enable/disable MULTIQUEUE support.
-+ * Possible values '1' for enable and '0' for disable. Default is '0'
- ************************************************************************/
-
- #include <linux/module.h>
-@@ -84,7 +86,7 @@
- #include "s2io.h"
- #include "s2io-regs.h"
-
--#define DRV_VERSION "2.0.26.20"
-+#define DRV_VERSION "2.0.26.22"
-
- /* S2io Driver name & version. */
- static char s2io_driver_name[] = "Neterion";
-@@ -115,20 +117,6 @@ static inline int RXD_IS_UP2DT(struct RxD_t *rxdp)
-
- #define LINK_IS_UP(val64) (!(val64 & (ADAPTER_STATUS_RMAC_REMOTE_FAULT | \
- ADAPTER_STATUS_RMAC_LOCAL_FAULT)))
--#define TASKLET_IN_USE test_and_set_bit(0, (&sp->tasklet_status))
--#define PANIC 1
--#define LOW 2
--static inline int rx_buffer_level(struct s2io_nic * sp, int rxb_size, int ring)
--{
-- struct mac_info *mac_control;
--
-- mac_control = &sp->mac_control;
-- if (rxb_size <= rxd_count[sp->rxd_mode])
-- return PANIC;
-- else if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16)
-- return LOW;
-- return 0;
--}
-
- static inline int is_s2io_card_up(const struct s2io_nic * sp)
- {
-@@ -386,6 +374,26 @@ static void s2io_vlan_rx_register(struct net_device *dev,
- /* A flag indicating whether 'RX_PA_CFG_STRIP_VLAN_TAG' bit is set or not */
- static int vlan_strip_flag;
-
-+/* Unregister the vlan */
-+static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
-+{
-+ int i;
-+ struct s2io_nic *nic = dev->priv;
-+ unsigned long flags[MAX_TX_FIFOS];
-+ struct mac_info *mac_control = &nic->mac_control;
-+ struct config_param *config = &nic->config;
++/*
++ * Commands common to all known devices.
++ *
++ */
+
-+ for (i = 0; i < config->tx_fifo_num; i++)
-+ spin_lock_irqsave(&mac_control->fifos[i].tx_lock, flags[i]);
++/* Write status register */
++#define SPI_WRSR 0x01
+
-+ if (nic->vlgrp)
-+ vlan_group_set_device(nic->vlgrp, vid, NULL);
++/* Write data to memory array */
++#define SPI_WRITE 0x02
+
-+ for (i = config->tx_fifo_num - 1; i >= 0; i--)
-+ spin_unlock_irqrestore(&mac_control->fifos[i].tx_lock,
-+ flags[i]);
-+}
++/* Read data from memory array */
++#define SPI_READ 0x03
+
- /*
- * 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);
-+ }
-+}
++/* Reset write enable latch */
++#define SPI_WRDI 0x04
+
-+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);
-+ }
-+}
++/* Read status register */
++#define SPI_RDSR 0x05
+
-+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);
++/* Set write enable latch */
++#define SPI_WREN 0x06
++
++/* SST: Enable write to status register */
++#define SPI_SST_EWSR 0x50
++
++/*
++ * Status register bits. Not all bits are supported on all devices.
++ *
++ */
++
++/* Write-protect pin enabled */
++#define SPI_STATUS_WPEN 0x80
++
++/* Block protection bit 2 */
++#define SPI_STATUS_BP2 0x10
++
++/* Block protection bit 1 */
++#define SPI_STATUS_BP1 0x08
++
++/* Block protection bit 0 */
++#define SPI_STATUS_BP0 0x04
++
++/* State of the write enable latch */
++#define SPI_STATUS_WEN 0x02
++
++/* Device busy flag */
++#define SPI_STATUS_NRDY 0x01
++
++#endif /* EFX_SPI_H */
+diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
+new file mode 100644
+index 0000000..a2e9f79
+--- /dev/null
++++ b/drivers/net/sfc/tenxpress.c
+@@ -0,0 +1,434 @@
++/****************************************************************************
++ * Driver for Solarflare 802.3an compliant PHY
++ * Copyright 2007 Solarflare Communications 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, incorporated herein by reference.
++ */
++
++#include <linux/delay.h>
++#include <linux/seq_file.h>
++#include "efx.h"
++#include "gmii.h"
++#include "mdio_10g.h"
++#include "falcon.h"
++#include "phy.h"
++#include "falcon_hwdefs.h"
++#include "boards.h"
++#include "mac.h"
++
++/* We expect these MMDs to be in the package */
++/* AN not here as mdio_check_mmds() requires STAT2 support */
++#define TENXPRESS_REQUIRED_DEVS (MDIO_MMDREG_DEVS0_PMAPMD | \
++ MDIO_MMDREG_DEVS0_PCS | \
++ MDIO_MMDREG_DEVS0_PHYXS)
++
++/* We complain if we fail to see the link partner as 10G capable this many
++ * times in a row (must be > 1 as sampling the autoneg. registers is racy)
++ */
++#define MAX_BAD_LP_TRIES (5)
++
++/* Extended control register */
++#define PMA_PMD_XCONTROL_REG 0xc000
++#define PMA_PMD_LNPGA_POWERDOWN_LBN 8
++#define PMA_PMD_LNPGA_POWERDOWN_WIDTH 1
++
++/* extended status register */
++#define PMA_PMD_XSTATUS_REG 0xc001
++#define PMA_PMD_XSTAT_FLP_LBN (12)
++
++/* LED control register */
++#define PMA_PMD_LED_CTRL_REG (0xc007)
++#define PMA_PMA_LED_ACTIVITY_LBN (3)
++
++/* LED function override register */
++#define PMA_PMD_LED_OVERR_REG (0xc009)
++/* Bit positions for different LEDs (there are more but not wired on SFE4001)*/
++#define PMA_PMD_LED_LINK_LBN (0)
++#define PMA_PMD_LED_SPEED_LBN (2)
++#define PMA_PMD_LED_TX_LBN (4)
++#define PMA_PMD_LED_RX_LBN (6)
++/* Override settings */
++#define PMA_PMD_LED_AUTO (0) /* H/W control */
++#define PMA_PMD_LED_ON (1)
++#define PMA_PMD_LED_OFF (2)
++#define PMA_PMD_LED_FLASH (3)
++/* All LEDs under hardware control */
++#define PMA_PMD_LED_FULL_AUTO (0)
++/* Green and Amber under hardware control, Red off */
++#define PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN)
++
++
++/* Self test (BIST) control register */
++#define PMA_PMD_BIST_CTRL_REG (0xc014)
++#define PMA_PMD_BIST_BER_LBN (2) /* Run BER test */
++#define PMA_PMD_BIST_CONT_LBN (1) /* Run continuous BIST until cleared */
++#define PMA_PMD_BIST_SINGLE_LBN (0) /* Run 1 BIST iteration (self clears) */
++/* Self test status register */
++#define PMA_PMD_BIST_STAT_REG (0xc015)
++#define PMA_PMD_BIST_ENX_LBN (3)
++#define PMA_PMD_BIST_PMA_LBN (2)
++#define PMA_PMD_BIST_RXD_LBN (1)
++#define PMA_PMD_BIST_AFE_LBN (0)
++
++#define BIST_MAX_DELAY (1000)
++#define BIST_POLL_DELAY (10)
++
++/* Misc register defines */
++#define PCS_CLOCK_CTRL_REG 0xd801
++#define PLL312_RST_N_LBN 2
++
++#define PCS_SOFT_RST2_REG 0xd806
++#define SERDES_RST_N_LBN 13
++#define XGXS_RST_N_LBN 12
++
++#define PCS_TEST_SELECT_REG 0xd807 /* PRM 10.5.8 */
++#define CLK312_EN_LBN 3
++
++/* Boot status register */
++#define PCS_BOOT_STATUS_REG (0xd000)
++#define PCS_BOOT_FATAL_ERR_LBN (0)
++#define PCS_BOOT_PROGRESS_LBN (1)
++#define PCS_BOOT_PROGRESS_WIDTH (2)
++#define PCS_BOOT_COMPLETE_LBN (3)
++#define PCS_BOOT_MAX_DELAY (100)
++#define PCS_BOOT_POLL_DELAY (10)
++
++/* Time to wait between powering down the LNPGA and turning off the power
++ * rails */
++#define LNPGA_PDOWN_WAIT (HZ / 5)
++
++static int crc_error_reset_threshold = 100;
++module_param(crc_error_reset_threshold, int, 0644);
++MODULE_PARM_DESC(crc_error_reset_threshold,
++ "Max number of CRC errors before XAUI reset");
++
++struct tenxpress_phy_data {
++ enum tenxpress_state state;
++ atomic_t bad_crc_count;
++ int bad_lp_tries;
++};
++
++static int tenxpress_state_is(struct efx_nic *efx, int state)
++{
++ struct tenxpress_phy_data *phy_data = efx->phy_data;
++ return (phy_data != NULL) && (state == phy_data->state);
++}
++
++void tenxpress_set_state(struct efx_nic *efx,
++ enum tenxpress_state state)
++{
++ struct tenxpress_phy_data *phy_data = efx->phy_data;
++ if (phy_data != NULL)
++ phy_data->state = state;
++}
++
++void tenxpress_crc_err(struct efx_nic *efx)
++{
++ struct tenxpress_phy_data *phy_data = efx->phy_data;
++ if (phy_data != NULL)
++ atomic_inc(&phy_data->bad_crc_count);
++}
++
++/* Check that the C166 has booted successfully */
++static int tenxpress_phy_check(struct efx_nic *efx)
++{
++ int phy_id = efx->mii.phy_id;
++ int count = PCS_BOOT_MAX_DELAY / PCS_BOOT_POLL_DELAY;
++ int boot_stat;
++
++ /* Wait for the boot to complete (or not) */
++ while (count) {
++ boot_stat = mdio_clause45_read(efx, phy_id,
++ MDIO_MMD_PCS,
++ PCS_BOOT_STATUS_REG);
++ if (boot_stat & (1 << PCS_BOOT_COMPLETE_LBN))
++ break;
++ count--;
++ udelay(PCS_BOOT_POLL_DELAY);
+ }
-+}
+
-+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);
++ if (!count) {
++ EFX_ERR(efx, "%s: PHY boot timed out. Last status "
++ "%x\n", __func__,
++ (boot_stat >> PCS_BOOT_PROGRESS_LBN) &
++ ((1 << PCS_BOOT_PROGRESS_WIDTH) - 1));
++ return -ETIMEDOUT;
+ }
++
++ return 0;
+}
+
-+static inline void s2io_wake_all_tx_queue(struct s2io_nic *sp)
++static void tenxpress_reset_xaui(struct efx_nic *efx);
++
++static int tenxpress_init(struct efx_nic *efx)
+{
-+ 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);
-+ }
++ int rc, reg;
++
++ /* Turn on the clock */
++ reg = (1 << CLK312_EN_LBN);
++ mdio_clause45_write(efx, efx->mii.phy_id,
++ MDIO_MMD_PCS, PCS_TEST_SELECT_REG, reg);
++
++ rc = tenxpress_phy_check(efx);
++ if (rc < 0)
++ return rc;
++
++ /* Set the LEDs up as: Green = Link, Amber = Link/Act, Red = Off */
++ reg = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG);
++ reg |= (1 << PMA_PMA_LED_ACTIVITY_LBN);
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
++ PMA_PMD_LED_CTRL_REG, reg);
++
++ reg = PMA_PMD_LED_DEFAULT;
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
++ PMA_PMD_LED_OVERR_REG, reg);
++
++ return rc;
+}
+
-+static inline void s2io_wake_tx_queue(
-+ struct fifo_info *fifo, int cnt, u8 multiq)
++static int tenxpress_phy_init(struct efx_nic *efx)
+{
++ struct tenxpress_phy_data *phy_data;
++ int rc = 0;
+
-+#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);
-+ }
-+ }
-+}
++ phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
++ efx->phy_data = phy_data;
+
- /**
- * 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;
-- }
++ tenxpress_set_state(efx, TENXPRESS_STATUS_NORMAL);
+
- 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);
++ rc = mdio_clause45_wait_reset_mmds(efx,
++ TENXPRESS_REQUIRED_DEVS);
++ if (rc < 0)
++ goto fail;
+
-+ if ((ip->frag_off & htons(IP_OFFSET|IP_MF)) == 0) {
-+ th = (struct tcphdr *)(((unsigned char *)ip) +
-+ ip->ihl*4);
++ rc = mdio_clause45_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0);
++ if (rc < 0)
++ goto fail;
+
-+ 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];
++ rc = tenxpress_init(efx);
++ if (rc < 0)
++ goto fail;
++
++ schedule_timeout_uninterruptible(HZ / 5); /* 200ms */
++
++ /* Let XGXS and SerDes out of reset and resets 10XPress */
++ falcon_reset_xaui(efx);
++
++ return 0;
++
++ fail:
++ kfree(efx->phy_data);
++ efx->phy_data = NULL;
++ return rc;
++}
++
++static void tenxpress_set_bad_lp(struct efx_nic *efx, int bad_lp)
++{
++ struct tenxpress_phy_data *pd = efx->phy_data;
++ int reg;
++
++ /* Nothing to do if all is well and was previously so. */
++ if (!(bad_lp || pd->bad_lp_tries))
++ return;
+
-+ 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;
++ reg = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG);
++
++ if (bad_lp)
++ pd->bad_lp_tries++;
++ else
++ pd->bad_lp_tries = 0;
++
++ if (pd->bad_lp_tries == MAX_BAD_LP_TRIES) {
++ pd->bad_lp_tries = 0; /* Restart count */
++ reg &= ~(PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN);
++ reg |= (PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN);
++ EFX_ERR(efx, "This NIC appears to be plugged into"
++ " a port that is not 10GBASE-T capable.\n"
++ " This PHY is 10GBASE-T ONLY, so no link can"
++ " be established.\n");
++ } else {
++ reg |= (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN);
+ }
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
++ PMA_PMD_LED_OVERR_REG, reg);
++}
+
-+#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;
++/* Check link status and return a boolean OK value. If the link is NOT
++ * OK we have a quick rummage round to see if we appear to be plugged
++ * into a non-10GBT port and if so warn the user that they won't get
++ * link any time soon as we are 10GBT only, unless caller specified
++ * not to do this check (it isn't useful in loopback) */
++static int tenxpress_link_ok(struct efx_nic *efx, int check_lp)
++{
++ int ok = mdio_clause45_links_ok(efx, TENXPRESS_REQUIRED_DEVS);
++
++ if (ok) {
++ tenxpress_set_bad_lp(efx, 0);
++ } else if (check_lp) {
++ /* Are we plugged into the wrong sort of link? */
++ int bad_lp = 0;
++ int phy_id = efx->mii.phy_id;
++ int an_stat = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
++ MDIO_AN_STATUS);
++ int xphy_stat = mdio_clause45_read(efx, phy_id,
++ MDIO_MMD_PMAPMD,
++ PMA_PMD_XSTATUS_REG);
++ /* Are we plugged into anything that sends FLPs? If
++ * not we can't distinguish between not being plugged
++ * in and being plugged into a non-AN antique. The FLP
++ * bit has the advantage of not clearing when autoneg
++ * restarts. */
++ if (!(xphy_stat & (1 << PMA_PMD_XSTAT_FLP_LBN))) {
++ tenxpress_set_bad_lp(efx, 0);
++ return ok;
++ }
++
++ /* If it can do 10GBT it must be XNP capable */
++ bad_lp = !(an_stat & (1 << MDIO_AN_STATUS_XNP_LBN));
++ if (!bad_lp && (an_stat & (1 << MDIO_AN_STATUS_PAGE_LBN))) {
++ bad_lp = !(mdio_clause45_read(efx, phy_id,
++ MDIO_MMD_AN, MDIO_AN_10GBT_STATUS) &
++ (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN));
+ }
-+ } 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;
-- }
++ tenxpress_set_bad_lp(efx, bad_lp);
++ }
++ return ok;
++}
+
- 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));
++static void tenxpress_phy_reconfigure(struct efx_nic *efx)
++{
++ if (!tenxpress_state_is(efx, TENXPRESS_STATUS_NORMAL))
++ return;
+
-+ if (tx_fifo_num < 1)
-+ tx_fifo_num = 1;
++ efx->link_up = tenxpress_link_ok(efx, 0);
++ efx->link_options = GM_LPA_10000FULL;
++}
++
++static void tenxpress_phy_clear_interrupt(struct efx_nic *efx)
++{
++ /* Nothing done here - LASI interrupts aren't reliable so poll */
++}
++
++
++/* Poll PHY for interrupt */
++static int tenxpress_phy_check_hw(struct efx_nic *efx)
++{
++ struct tenxpress_phy_data *phy_data = efx->phy_data;
++ int phy_up = tenxpress_state_is(efx, TENXPRESS_STATUS_NORMAL);
++ int link_ok;
++
++ link_ok = phy_up && tenxpress_link_ok(efx, 1);
++
++ if (link_ok != efx->link_up)
++ falcon_xmac_sim_phy_event(efx);
++
++ /* Nothing to check if we've already shut down the PHY */
++ if (!phy_up)
++ return 0;
++
++ if (atomic_read(&phy_data->bad_crc_count) > crc_error_reset_threshold) {
++ EFX_ERR(efx, "Resetting XAUI due to too many CRC errors\n");
++ falcon_reset_xaui(efx);
++ atomic_set(&phy_data->bad_crc_count, 0);
++ }
++
++ return 0;
++}
++
++static void tenxpress_phy_fini(struct efx_nic *efx)
++{
++ int reg;
++
++ /* Power down the LNPGA */
++ reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN);
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
++ PMA_PMD_XCONTROL_REG, reg);
++
++ /* Waiting here ensures that the board fini, which can turn off the
++ * power to the PHY, won't get run until the LNPGA powerdown has been
++ * given long enough to complete. */
++ schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */
++
++ kfree(efx->phy_data);
++ efx->phy_data = NULL;
++}
++
++
++/* Set the RX and TX LEDs and Link LED flashing. The other LEDs
++ * (which probably aren't wired anyway) are left in AUTO mode */
++void tenxpress_phy_blink(struct efx_nic *efx, int blink)
++{
++ int reg;
++
++ if (blink)
++ reg = (PMA_PMD_LED_FLASH << PMA_PMD_LED_TX_LBN) |
++ (PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN) |
++ (PMA_PMD_LED_FLASH << PMA_PMD_LED_LINK_LBN);
++ else
++ reg = PMA_PMD_LED_DEFAULT;
++
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
++ PMA_PMD_LED_OVERR_REG, reg);
++}
++
++static void tenxpress_reset_xaui(struct efx_nic *efx)
++{
++ int phy = efx->mii.phy_id;
++ int clk_ctrl, test_select, soft_rst2;
++
++ /* Real work is done on clock_ctrl other resets are thought to be
++ * optional but make the reset more reliable
++ */
++
++ /* Read */
++ clk_ctrl = mdio_clause45_read(efx, phy, MDIO_MMD_PCS,
++ PCS_CLOCK_CTRL_REG);
++ test_select = mdio_clause45_read(efx, phy, MDIO_MMD_PCS,
++ PCS_TEST_SELECT_REG);
++ soft_rst2 = mdio_clause45_read(efx, phy, MDIO_MMD_PCS,
++ PCS_SOFT_RST2_REG);
++
++ /* Put in reset */
++ test_select &= ~(1 << CLK312_EN_LBN);
++ mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
++ PCS_TEST_SELECT_REG, test_select);
++
++ soft_rst2 &= ~((1 << XGXS_RST_N_LBN) | (1 << SERDES_RST_N_LBN));
++ mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
++ PCS_SOFT_RST2_REG, soft_rst2);
++
++ clk_ctrl &= ~(1 << PLL312_RST_N_LBN);
++ mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
++ PCS_CLOCK_CTRL_REG, clk_ctrl);
++ udelay(10);
++
++ /* Remove reset */
++ clk_ctrl |= (1 << PLL312_RST_N_LBN);
++ mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
++ PCS_CLOCK_CTRL_REG, clk_ctrl);
++ udelay(10);
++
++ soft_rst2 |= ((1 << XGXS_RST_N_LBN) | (1 << SERDES_RST_N_LBN));
++ mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
++ PCS_SOFT_RST2_REG, soft_rst2);
++ udelay(10);
++
++ test_select |= (1 << CLK312_EN_LBN);
++ mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
++ PCS_TEST_SELECT_REG, test_select);
++ udelay(10);
++}
++
++struct efx_phy_operations falcon_tenxpress_phy_ops = {
++ .init = tenxpress_phy_init,
++ .reconfigure = tenxpress_phy_reconfigure,
++ .check_hw = tenxpress_phy_check_hw,
++ .fini = tenxpress_phy_fini,
++ .clear_interrupt = tenxpress_phy_clear_interrupt,
++ .reset_xaui = tenxpress_reset_xaui,
++ .mmds = TENXPRESS_REQUIRED_DEVS,
++};
+diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c
+new file mode 100644
+index 0000000..fbb866b
+--- /dev/null
++++ b/drivers/net/sfc/tx.c
+@@ -0,0 +1,452 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005-2006 Fen Systems Ltd.
++ * Copyright 2005-2008 Solarflare Communications 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, incorporated herein by reference.
++ */
++
++#include <linux/pci.h>
++#include <linux/tcp.h>
++#include <linux/ip.h>
++#include <linux/in.h>
++#include <linux/if_ether.h>
++#include <linux/highmem.h>
++#include "net_driver.h"
++#include "tx.h"
++#include "efx.h"
++#include "falcon.h"
++#include "workarounds.h"
++
++/*
++ * TX descriptor ring full threshold
++ *
++ * The tx_queue descriptor ring fill-level must fall below this value
++ * before we restart the netif queue
++ */
++#define EFX_NETDEV_TX_THRESHOLD(_tx_queue) \
++ (_tx_queue->efx->type->txd_ring_mask / 2u)
++
++/* We want to be able to nest calls to netif_stop_queue(), since each
++ * channel can have an individual stop on the queue.
++ */
++void efx_stop_queue(struct efx_nic *efx)
++{
++ spin_lock_bh(&efx->netif_stop_lock);
++ EFX_TRACE(efx, "stop TX queue\n");
++
++ atomic_inc(&efx->netif_stop_count);
++ netif_stop_queue(efx->net_dev);
++
++ spin_unlock_bh(&efx->netif_stop_lock);
++}
++
++/* Wake netif's TX queue
++ * We want to be able to nest calls to netif_stop_queue(), since each
++ * channel can have an individual stop on the queue.
++ */
++inline void efx_wake_queue(struct efx_nic *efx)
++{
++ local_bh_disable();
++ if (atomic_dec_and_lock(&efx->netif_stop_count,
++ &efx->netif_stop_lock)) {
++ EFX_TRACE(efx, "waking TX queue\n");
++ netif_wake_queue(efx->net_dev);
++ spin_unlock(&efx->netif_stop_lock);
++ }
++ local_bh_enable();
++}
++
++static inline void efx_dequeue_buffer(struct efx_tx_queue *tx_queue,
++ struct efx_tx_buffer *buffer)
++{
++ if (buffer->unmap_len) {
++ struct pci_dev *pci_dev = tx_queue->efx->pci_dev;
++ if (buffer->unmap_single)
++ pci_unmap_single(pci_dev, buffer->unmap_addr,
++ buffer->unmap_len, PCI_DMA_TODEVICE);
+ else
-+ tx_fifo_num = MAX_TX_FIFOS;
++ pci_unmap_page(pci_dev, buffer->unmap_addr,
++ buffer->unmap_len, PCI_DMA_TODEVICE);
++ buffer->unmap_len = 0;
++ buffer->unmap_single = 0;
++ }
+
- 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;
++ if (buffer->skb) {
++ dev_kfree_skb_any((struct sk_buff *) buffer->skb);
++ buffer->skb = NULL;
++ EFX_TRACE(tx_queue->efx, "TX queue %d transmission id %x "
++ "complete\n", tx_queue->queue, read_ptr);
+ }
-+#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;
++
++/*
++ * Add a socket buffer to a TX queue
++ *
++ * This maps all fragments of a socket buffer for DMA and adds them to
++ * the TX queue. The queue's insert pointer will be incremented by
++ * the number of fragments in the socket buffer.
++ *
++ * If any DMA mapping fails, any mapped fragments will be unmapped,
++ * the queue's insert pointer will be restored to its original value.
++ *
++ * Returns NETDEV_TX_OK or NETDEV_TX_BUSY
++ * You must hold netif_tx_lock() to call this function.
++ */
++static inline int efx_enqueue_skb(struct efx_tx_queue *tx_queue,
++ const struct sk_buff *skb)
++{
++ struct efx_nic *efx = tx_queue->efx;
++ struct pci_dev *pci_dev = efx->pci_dev;
++ struct efx_tx_buffer *buffer;
++ skb_frag_t *fragment;
++ struct page *page;
++ int page_offset;
++ unsigned int len, unmap_len = 0, fill_level, insert_ptr, misalign;
++ dma_addr_t dma_addr, unmap_addr = 0;
++ unsigned int dma_len;
++ unsigned unmap_single;
++ int q_space, i = 0;
++ int rc = NETDEV_TX_OK;
++
++ EFX_BUG_ON_PARANOID(tx_queue->write_count != tx_queue->insert_count);
++
++ /* Get size of the initial fragment */
++ len = skb_headlen(skb);
++
++ fill_level = tx_queue->insert_count - tx_queue->old_read_count;
++ q_space = efx->type->txd_ring_mask - 1 - fill_level;
++
++ /* Map for DMA. Use pci_map_single rather than pci_map_page
++ * since this is more efficient on machines with sparse
++ * memory.
++ */
++ unmap_single = 1;
++ dma_addr = pci_map_single(pci_dev, skb->data, len, PCI_DMA_TODEVICE);
++
++ /* Process all fragments */
++ while (1) {
++ if (unlikely(pci_dma_mapping_error(dma_addr)))
++ goto pci_err;
++
++ /* Store fields for marking in the per-fragment final
++ * descriptor */
++ unmap_len = len;
++ unmap_addr = dma_addr;
++
++ /* Add to TX queue, splitting across DMA boundaries */
++ do {
++ if (unlikely(q_space-- <= 0)) {
++ /* It might be that completions have
++ * happened since the xmit path last
++ * checked. Update the xmit path's
++ * copy of read_count.
++ */
++ ++tx_queue->stopped;
++ /* This memory barrier protects the
++ * change of stopped from the access
++ * of read_count. */
++ smp_mb();
++ tx_queue->old_read_count =
++ *(volatile unsigned *)
++ &tx_queue->read_count;
++ fill_level = (tx_queue->insert_count
++ - tx_queue->old_read_count);
++ q_space = (efx->type->txd_ring_mask - 1 -
++ fill_level);
++ if (unlikely(q_space-- <= 0))
++ goto stop;
++ smp_mb();
++ --tx_queue->stopped;
++ }
++
++ insert_ptr = (tx_queue->insert_count &
++ efx->type->txd_ring_mask);
++ buffer = &tx_queue->buffer[insert_ptr];
++ EFX_BUG_ON_PARANOID(buffer->skb);
++ EFX_BUG_ON_PARANOID(buffer->len);
++ EFX_BUG_ON_PARANOID(buffer->continuation != 1);
++ EFX_BUG_ON_PARANOID(buffer->unmap_len);
++
++ dma_len = (((~dma_addr) & efx->type->tx_dma_mask) + 1);
++ if (likely(dma_len > len))
++ dma_len = len;
++
++ misalign = (unsigned)dma_addr & efx->type->bug5391_mask;
++ if (misalign && dma_len + misalign > 512)
++ dma_len = 512 - misalign;
++
++ /* Fill out per descriptor fields */
++ buffer->len = dma_len;
++ buffer->dma_addr = dma_addr;
++ len -= dma_len;
++ dma_addr += dma_len;
++ ++tx_queue->insert_count;
++ } while (len);
++
++ /* Transfer ownership of the unmapping to the final buffer */
++ buffer->unmap_addr = unmap_addr;
++ buffer->unmap_single = unmap_single;
++ buffer->unmap_len = unmap_len;
++ unmap_len = 0;
++
++ /* Get address and size of next fragment */
++ if (i >= skb_shinfo(skb)->nr_frags)
++ break;
++ fragment = &skb_shinfo(skb)->frags[i];
++ len = fragment->size;
++ page = fragment->page;
++ page_offset = fragment->page_offset;
++ i++;
++ /* Map for DMA */
++ unmap_single = 0;
++ dma_addr = pci_map_page(pci_dev, page, page_offset, len,
++ PCI_DMA_TODEVICE);
+ }
+
-+ 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;
++ /* Transfer ownership of the skb to the final buffer */
++ buffer->skb = skb;
++ buffer->continuation = 0;
++
++ /* Pass off to hardware */
++ falcon_push_buffers(tx_queue);
++
++ return NETDEV_TX_OK;
++
++ pci_err:
++ EFX_ERR_RL(efx, " TX queue %d could not map skb with %d bytes %d "
++ "fragments for DMA\n", tx_queue->queue, skb->len,
++ skb_shinfo(skb)->nr_frags + 1);
++
++ /* Mark the packet as transmitted, and free the SKB ourselves */
++ dev_kfree_skb_any((struct sk_buff *)skb);
++ goto unwind;
++
++ stop:
++ rc = NETDEV_TX_BUSY;
++
++ if (tx_queue->stopped == 1)
++ efx_stop_queue(efx);
++
++ unwind:
++ /* Work backwards until we hit the original insert pointer value */
++ while (tx_queue->insert_count != tx_queue->write_count) {
++ --tx_queue->insert_count;
++ insert_ptr = tx_queue->insert_count & efx->type->txd_ring_mask;
++ buffer = &tx_queue->buffer[insert_ptr];
++ efx_dequeue_buffer(tx_queue, buffer);
++ buffer->len = 0;
++ }
++
++ /* Free the fragment we were mid-way through pushing */
++ if (unmap_len)
++ pci_unmap_page(pci_dev, unmap_addr, unmap_len,
++ PCI_DMA_TODEVICE);
++
++ return rc;
++}
++
++/* Remove packets from the TX queue
++ *
++ * This removes packets from the TX queue, up to and including the
++ * specified index.
++ */
++static inline void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
++ unsigned int index)
++{
++ struct efx_nic *efx = tx_queue->efx;
++ unsigned int stop_index, read_ptr;
++ unsigned int mask = tx_queue->efx->type->txd_ring_mask;
++
++ stop_index = (index + 1) & mask;
++ read_ptr = tx_queue->read_count & mask;
++
++ while (read_ptr != stop_index) {
++ struct efx_tx_buffer *buffer = &tx_queue->buffer[read_ptr];
++ if (unlikely(buffer->len == 0)) {
++ EFX_ERR(tx_queue->efx, "TX queue %d spurious TX "
++ "completion id %x\n", tx_queue->queue,
++ read_ptr);
++ efx_schedule_reset(efx, RESET_TYPE_TX_SKIP);
++ return;
++ }
++
++ efx_dequeue_buffer(tx_queue, buffer);
++ buffer->continuation = 1;
++ buffer->len = 0;
++
++ ++tx_queue->read_count;
++ read_ptr = tx_queue->read_count & mask;
+ }
++}
+
- 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;
++/* Initiate a packet transmission on the specified TX queue.
++ * Note that returning anything other than NETDEV_TX_OK will cause the
++ * OS to free the skb.
++ *
++ * This function is split out from efx_hard_start_xmit to allow the
++ * loopback test to direct packets via specific TX queues. It is
++ * therefore a non-static inline, so as not to penalise performance
++ * for non-loopback transmissions.
++ *
++ * Context: netif_tx_lock held
++ */
++inline int efx_xmit(struct efx_nic *efx,
++ struct efx_tx_queue *tx_queue, struct sk_buff *skb)
++{
++ int rc;
+
-+ /* 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;
++ /* Map fragments for DMA and add to TX queue */
++ rc = efx_enqueue_skb(tx_queue, skb);
++ if (unlikely(rc != NETDEV_TX_OK))
++ goto out;
++
++ /* Update last TX timer */
++ efx->net_dev->trans_start = jiffies;
++
++ out:
++ return rc;
++}
++
++/* Initiate a packet transmission. We use one channel per CPU
++ * (sharing when we have more CPUs than channels). On Falcon, the TX
++ * completion events will be directed back to the CPU that transmitted
++ * the packet, which should be cache-efficient.
++ *
++ * Context: non-blocking.
++ * Note that returning anything other than NETDEV_TX_OK will cause the
++ * OS to free the skb.
++ */
++int efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++ return efx_xmit(efx, &efx->tx_queue[0], skb);
++}
++
++void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
++{
++ unsigned fill_level;
++ struct efx_nic *efx = tx_queue->efx;
++
++ EFX_BUG_ON_PARANOID(index > efx->type->txd_ring_mask);
++
++ efx_dequeue_buffers(tx_queue, index);
++
++ /* See if we need to restart the netif queue. This barrier
++ * separates the update of read_count from the test of
++ * stopped. */
++ smp_mb();
++ if (unlikely(tx_queue->stopped)) {
++ fill_level = tx_queue->insert_count - tx_queue->read_count;
++ if (fill_level < EFX_NETDEV_TX_THRESHOLD(tx_queue)) {
++ EFX_BUG_ON_PARANOID(!NET_DEV_REGISTERED(efx));
++
++ /* Do this under netif_tx_lock(), to avoid racing
++ * with efx_xmit(). */
++ netif_tx_lock(efx->net_dev);
++ if (tx_queue->stopped) {
++ tx_queue->stopped = 0;
++ efx_wake_queue(efx);
++ }
++ netif_tx_unlock(efx->net_dev);
++ }
+ }
++}
+
-+ 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];
++int efx_probe_tx_queue(struct efx_tx_queue *tx_queue)
++{
++ struct efx_nic *efx = tx_queue->efx;
++ unsigned int txq_size;
++ int i, rc;
+
-+ /* 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];
++ EFX_LOG(efx, "creating TX queue %d\n", tx_queue->queue);
+
-
- 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);
++ /* Allocate software ring */
++ txq_size = (efx->type->txd_ring_mask + 1) * sizeof(*tx_queue->buffer);
++ tx_queue->buffer = kzalloc(txq_size, GFP_KERNEL);
++ if (!tx_queue->buffer) {
++ rc = -ENOMEM;
++ goto fail1;
++ }
++ for (i = 0; i <= efx->type->txd_ring_mask; ++i)
++ tx_queue->buffer[i].continuation = 1;
+
-+ DBG_PRINT(ERR_DBG, "%s: Using %d Tx fifo(s)\n", dev->name,
-+ sp->config.tx_fifo_num);
++ /* Allocate hardware ring */
++ rc = falcon_probe_tx(tx_queue);
++ if (rc)
++ goto fail2;
+
- 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);
++ return 0;
+
-+ 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);
++ fail2:
++ kfree(tx_queue->buffer);
++ tx_queue->buffer = NULL;
++ fail1:
++ tx_queue->used = 0;
++
++ return rc;
++}
++
++int efx_init_tx_queue(struct efx_tx_queue *tx_queue)
++{
++ EFX_LOG(tx_queue->efx, "initialising TX queue %d\n", tx_queue->queue);
++
++ tx_queue->insert_count = 0;
++ tx_queue->write_count = 0;
++ tx_queue->read_count = 0;
++ tx_queue->old_read_count = 0;
++ BUG_ON(tx_queue->stopped);
++
++ /* Set up TX descriptor ring */
++ return falcon_init_tx(tx_queue);
++}
++
++void efx_release_tx_buffers(struct efx_tx_queue *tx_queue)
++{
++ struct efx_tx_buffer *buffer;
++
++ if (!tx_queue->buffer)
++ return;
++
++ /* Free any buffers left in the ring */
++ while (tx_queue->read_count != tx_queue->write_count) {
++ buffer = &tx_queue->buffer[tx_queue->read_count &
++ tx_queue->efx->type->txd_ring_mask];
++ efx_dequeue_buffer(tx_queue, buffer);
++ buffer->continuation = 1;
++ buffer->len = 0;
++
++ ++tx_queue->read_count;
+ }
++}
+
- if (sp->lro)
- DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
- dev->name);
-@@ -8064,7 +8202,8 @@ module_init(s2io_starter);
- module_exit(s2io_closer);
-
- static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip,
-- struct tcphdr **tcp, struct RxD_t *rxdp)
-+ struct tcphdr **tcp, struct RxD_t *rxdp,
-+ struct s2io_nic *sp)
- {
- int ip_off;
- u8 l2_type = (u8)((rxdp->Control_1 >> 37) & 0x7), ip_len;
-@@ -8075,19 +8214,20 @@ static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip,
- return -1;
- }
-
-- /* TODO:
-- * By default the VLAN field in the MAC is stripped by the card, if this
-- * feature is turned off in rx_pa_cfg register, then the ip_off field
-- * has to be shifted by a further 2 bytes
-- */
-- switch (l2_type) {
-- case 0: /* DIX type */
-- case 4: /* DIX type with VLAN */
-- ip_off = HEADER_ETHERNET_II_802_3_SIZE;
-- break;
-+ /* Checking for DIX type or DIX type with VLAN */
-+ if ((l2_type == 0)
-+ || (l2_type == 4)) {
-+ ip_off = HEADER_ETHERNET_II_802_3_SIZE;
-+ /*
-+ * If vlan stripping is disabled and the frame is VLAN tagged,
-+ * shift the offset by the VLAN header size bytes.
-+ */
-+ if ((!vlan_strip_flag) &&
-+ (rxdp->Control_1 & RXD_FRAME_VLAN_TAG))
-+ ip_off += HEADER_VLAN_SIZE;
-+ } else {
- /* LLC, SNAP etc are considered non-mergeable */
-- default:
-- return -1;
-+ return -1;
- }
-
- *ip = (struct iphdr *)((u8 *)buffer + ip_off);
-@@ -8114,7 +8254,7 @@ static inline int get_l4_pyld_length(struct iphdr *ip, struct tcphdr *tcp)
- }
-
- static void initiate_new_session(struct lro *lro, u8 *l2h,
-- struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len)
-+ struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len, u16 vlan_tag)
- {
- DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
- lro->l2h = l2h;
-@@ -8125,6 +8265,7 @@ static void initiate_new_session(struct lro *lro, u8 *l2h,
- lro->sg_num = 1;
- lro->total_len = ntohs(ip->tot_len);
- lro->frags_len = 0;
-+ lro->vlan_tag = vlan_tag;
- /*
- * check if we saw TCP timestamp. Other consistency checks have
- * already been done.
-@@ -8256,15 +8397,16 @@ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,
- struct iphdr *ip;
- struct tcphdr *tcph;
- int ret = 0, i;
-+ u16 vlan_tag = 0;
-
- if (!(ret = check_L2_lro_capable(buffer, &ip, (struct tcphdr **)tcp,
-- rxdp))) {
-+ rxdp, sp))) {
- DBG_PRINT(INFO_DBG,"IP Saddr: %x Daddr: %x\n",
- ip->saddr, ip->daddr);
-- } else {
-+ } else
- return ret;
-- }
-
-+ vlan_tag = RXD_GET_VLAN_TAG(rxdp->Control_2);
- tcph = (struct tcphdr *)*tcp;
- *tcp_len = get_l4_pyld_length(ip, tcph);
- for (i=0; i<MAX_LRO_SESSIONS; i++) {
-@@ -8324,7 +8466,8 @@ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,
-
- switch (ret) {
- case 3:
-- initiate_new_session(*lro, buffer, ip, tcph, *tcp_len);
-+ initiate_new_session(*lro, buffer, ip, tcph, *tcp_len,
-+ vlan_tag);
- break;
- case 2:
- update_L3L4_header(sp, *lro);
-@@ -8352,15 +8495,25 @@ static void clear_lro_session(struct lro *lro)
- memset(lro, 0, lro_struct_size);
- }
-
--static void queue_rx_frame(struct sk_buff *skb)
-+static void queue_rx_frame(struct sk_buff *skb, u16 vlan_tag)
- {
- struct net_device *dev = skb->dev;
-+ struct s2io_nic *sp = dev->priv;
-
- skb->protocol = eth_type_trans(skb, dev);
-- if (napi)
-- netif_receive_skb(skb);
-- else
-- netif_rx(skb);
-+ if (sp->vlgrp && vlan_tag
-+ && (vlan_strip_flag)) {
-+ /* Queueing the vlan frame to the upper layer */
-+ if (sp->config.napi)
-+ vlan_hwaccel_receive_skb(skb, sp->vlgrp, vlan_tag);
-+ else
-+ vlan_hwaccel_rx(skb, sp->vlgrp, vlan_tag);
-+ } else {
-+ if (sp->config.napi)
-+ netif_receive_skb(skb);
-+ else
-+ netif_rx(skb);
++void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
++{
++ EFX_LOG(tx_queue->efx, "shutting down TX queue %d\n", tx_queue->queue);
++
++ /* Flush TX queue, remove descriptor ring */
++ falcon_fini_tx(tx_queue);
++
++ efx_release_tx_buffers(tx_queue);
++
++ /* Release queue's stop on port, if any */
++ if (tx_queue->stopped) {
++ tx_queue->stopped = 0;
++ efx_wake_queue(tx_queue->efx);
+ }
- }
-
- 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};
++void efx_remove_tx_queue(struct efx_tx_queue *tx_queue)
++{
++ EFX_LOG(tx_queue->efx, "destroying TX queue %d\n", tx_queue->queue);
++ falcon_remove_tx(tx_queue);
+
- /* 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;
++ kfree(tx_queue->buffer);
++ tx_queue->buffer = NULL;
++ tx_queue->used = 0;
++}
+
- 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;
+diff --git a/drivers/net/sfc/tx.h b/drivers/net/sfc/tx.h
+new file mode 100644
+index 0000000..1526a73
+--- /dev/null
++++ b/drivers/net/sfc/tx.h
+@@ -0,0 +1,24 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2006 Fen Systems Ltd.
++ * Copyright 2006-2008 Solarflare Communications 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, incorporated herein by reference.
++ */
+
-+ /* 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];
++#ifndef EFX_TX_H
++#define EFX_TX_H
+
-+ /* Total fifos for tcp packets */
-+ u8 total_tcp_fifos;
++#include "net_driver.h"
+
-+ /*
-+ * 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;
++int efx_probe_tx_queue(struct efx_tx_queue *tx_queue);
++void efx_remove_tx_queue(struct efx_tx_queue *tx_queue);
++int efx_init_tx_queue(struct efx_tx_queue *tx_queue);
++void efx_fini_tx_queue(struct efx_tx_queue *tx_queue);
+
-+ u8 total_udp_fifos;
++int efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev);
++void efx_release_tx_buffers(struct efx_tx_queue *tx_queue);
+
-+ /*
-+ * Beginning index of fifo for all other packets
-+ * Value will be equal to (tx_fifo_num - FIFO_OTHER_MAX_NUM)
-+ */
-+ u8 other_fifo_idx;
++#endif /* EFX_TX_H */
+diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h
+new file mode 100644
+index 0000000..dca62f1
+--- /dev/null
++++ b/drivers/net/sfc/workarounds.h
+@@ -0,0 +1,56 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2006-2008 Solarflare Communications 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, incorporated herein by reference.
++ */
+
- /* 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};
++#ifndef EFX_WORKAROUNDS_H
++#define EFX_WORKAROUNDS_H
+
- 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};
++/*
++ * Hardware workarounds.
++ * Bug numbers are from Solarflare's Bugzilla.
++ */
++
++#define EFX_WORKAROUND_ALWAYS(efx) 1
++#define EFX_WORKAROUND_FALCON_A(efx) (FALCON_REV(efx) <= FALCON_REV_A1)
++
++/* XAUI resets if link not detected */
++#define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS
++/* SNAP frames have TOBE_DISC set */
++#define EFX_WORKAROUND_5475 EFX_WORKAROUND_ALWAYS
++/* RX PCIe double split performance issue */
++#define EFX_WORKAROUND_7575 EFX_WORKAROUND_ALWAYS
++/* TX pkt parser problem with <= 16 byte TXes */
++#define EFX_WORKAROUND_9141 EFX_WORKAROUND_ALWAYS
++/* XGXS and XAUI reset sequencing in SW */
++#define EFX_WORKAROUND_9388 EFX_WORKAROUND_ALWAYS
++/* Low rate CRC errors require XAUI reset */
++#define EFX_WORKAROUND_10750 EFX_WORKAROUND_ALWAYS
++/* TX_EV_PKT_ERR can be caused by a dangling TX descriptor
++ * or a PCIe error (bug 11028) */
++#define EFX_WORKAROUND_10727 EFX_WORKAROUND_ALWAYS
++/* Transmit flow control may get disabled */
++#define EFX_WORKAROUND_11482 EFX_WORKAROUND_ALWAYS
++/* Flush events can take a very long time to appear */
++#define EFX_WORKAROUND_11557 EFX_WORKAROUND_ALWAYS
++
++/* Spurious parity errors in TSORT buffers */
++#define EFX_WORKAROUND_5129 EFX_WORKAROUND_FALCON_A
++/* iSCSI parsing errors */
++#define EFX_WORKAROUND_5583 EFX_WORKAROUND_FALCON_A
++/* RX events go missing */
++#define EFX_WORKAROUND_5676 EFX_WORKAROUND_FALCON_A
++/* RX_RESET on A1 */
++#define EFX_WORKAROUND_6555 EFX_WORKAROUND_FALCON_A
++/* Increase filter depth to avoid RX_RESET */
++#define EFX_WORKAROUND_7244 EFX_WORKAROUND_FALCON_A
++/* Flushes may never complete */
++#define EFX_WORKAROUND_7803 EFX_WORKAROUND_FALCON_A
++/* Leak overlength packets rather than free */
++#define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A
+
- 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};
++#endif /* EFX_WORKAROUNDS_H */
+diff --git a/drivers/net/sfc/xenpack.h b/drivers/net/sfc/xenpack.h
+new file mode 100644
+index 0000000..b0d1f22
+--- /dev/null
++++ b/drivers/net/sfc/xenpack.h
+@@ -0,0 +1,62 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2006 Solarflare Communications 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, incorporated herein by reference.
++ */
+
- 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};
++#ifndef EFX_XENPACK_H
++#define EFX_XENPACK_H
+
- 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};
++/* Exported functions from Xenpack standard PHY control */
+
- 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};
++#include "mdio_10g.h"
+
- 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};
++/****************************************************************************/
++/* XENPACK MDIO register extensions */
++#define MDIO_XP_LASI_RX_CTRL (0x9000)
++#define MDIO_XP_LASI_TX_CTRL (0x9001)
++#define MDIO_XP_LASI_CTRL (0x9002)
++#define MDIO_XP_LASI_RX_STAT (0x9003)
++#define MDIO_XP_LASI_TX_STAT (0x9004)
++#define MDIO_XP_LASI_STAT (0x9005)
++
++/* Control/Status bits */
++#define XP_LASI_LS_ALARM (1 << 0)
++#define XP_LASI_TX_ALARM (1 << 1)
++#define XP_LASI_RX_ALARM (1 << 2)
++/* These two are Quake vendor extensions to the standard XENPACK defines */
++#define XP_LASI_LS_INTB (1 << 3)
++#define XP_LASI_TEST (1 << 7)
+
- 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};
++/* Enable LASI interrupts for PHY */
++static inline void xenpack_enable_lasi_irqs(struct efx_nic *efx)
++{
++ int reg;
++ int phy_id = efx->mii.phy_id;
++ /* Read to clear LASI status register */
++ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
++ MDIO_XP_LASI_STAT);
+
- 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};
++ mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
++ MDIO_XP_LASI_CTRL, XP_LASI_LS_ALARM);
++}
+
- 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};
++/* Read the LASI interrupt status to clear the interrupt. */
++static inline int xenpack_clear_lasi_irqs(struct efx_nic *efx)
++{
++ /* Read to clear link status alarm */
++ return mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PMAPMD, MDIO_XP_LASI_STAT);
++}
+
- 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};
++/* Turn off LASI interrupts */
++static inline void xenpack_disable_lasi_irqs(struct efx_nic *efx)
++{
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
++ MDIO_XP_LASI_CTRL, 0);
++}
+
- 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;
++#endif /* EFX_XENPACK_H */
+diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c
+new file mode 100644
+index 0000000..66dd5bf
+--- /dev/null
++++ b/drivers/net/sfc/xfp_phy.c
+@@ -0,0 +1,132 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2006-2008 Solarflare Communications 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, incorporated herein by reference.
++ */
++/*
++ * Driver for XFP optical PHYs (plus some support specific to the Quake 2032)
++ * See www.amcc.com for details (search for qt2032)
++ */
++
++#include <linux/timer.h>
++#include <linux/delay.h>
++#include "efx.h"
++#include "gmii.h"
++#include "mdio_10g.h"
++#include "xenpack.h"
++#include "phy.h"
++#include "mac.h"
++
++#define XFP_REQUIRED_DEVS (MDIO_MMDREG_DEVS0_PCS | \
++ MDIO_MMDREG_DEVS0_PMAPMD | \
++ MDIO_MMDREG_DEVS0_PHYXS)
++
++/****************************************************************************/
++/* Quake-specific MDIO registers */
++#define MDIO_QUAKE_LED0_REG (0xD006)
++
++void xfp_set_led(struct efx_nic *p, int led, int mode)
++{
++ int addr = MDIO_QUAKE_LED0_REG + led;
++ mdio_clause45_write(p, p->mii.phy_id, MDIO_MMD_PMAPMD, addr,
++ mode);
++}
++
++#define XFP_MAX_RESET_TIME 500
++#define XFP_RESET_WAIT 10
++
++/* Reset the PHYXS MMD. This is documented (for the Quake PHY) as doing
++ * a complete soft reset.
++ */
++static int xfp_reset_phy(struct efx_nic *efx)
++{
++ int rc;
++
++ rc = mdio_clause45_reset_mmd(efx, MDIO_MMD_PHYXS,
++ XFP_MAX_RESET_TIME / XFP_RESET_WAIT,
++ XFP_RESET_WAIT);
++ if (rc < 0)
++ goto fail;
++
++ /* Wait 250ms for the PHY to complete bootup */
++ msleep(250);
++
++ /* Check that all the MMDs we expect are present and responding. We
++ * expect faults on some if the link is down, but not on the PHY XS */
++ rc = mdio_clause45_check_mmds(efx, XFP_REQUIRED_DEVS,
++ MDIO_MMDREG_DEVS0_PHYXS);
++ if (rc < 0)
++ goto fail;
++
++ efx->board_info.init_leds(efx);
++
++ return rc;
++
++ fail:
++ EFX_ERR(efx, "XFP: reset timed out!\n");
++ return rc;
++}
++
++static int xfp_phy_init(struct efx_nic *efx)
++{
++ u32 devid = mdio_clause45_read_id(efx, MDIO_MMD_PHYXS);
++ int rc;
++
++ EFX_INFO(efx, "XFP: PHY ID reg %x (OUI %x model %x revision"
++ " %x)\n", devid, MDIO_ID_OUI(devid), MDIO_ID_MODEL(devid),
++ MDIO_ID_REV(devid));
++
++ rc = xfp_reset_phy(efx);
++
++ EFX_INFO(efx, "XFP: PHY init %s.\n",
++ rc ? "failed" : "successful");
++
++ return rc;
++}
++
++static void xfp_phy_clear_interrupt(struct efx_nic *efx)
++{
++ xenpack_clear_lasi_irqs(efx);
++}
++
++static int xfp_link_ok(struct efx_nic *efx)
++{
++ return mdio_clause45_links_ok(efx, XFP_REQUIRED_DEVS);
++}
++
++static int xfp_phy_check_hw(struct efx_nic *efx)
++{
++ int rc = 0;
++ int link_up = xfp_link_ok(efx);
++ /* Simulate a PHY event if link state has changed */
++ if (link_up != efx->link_up)
++ falcon_xmac_sim_phy_event(efx);
++
++ return rc;
++}
++
++static void xfp_phy_reconfigure(struct efx_nic *efx)
++{
++ efx->link_up = xfp_link_ok(efx);
++ efx->link_options = GM_LPA_10000FULL;
++}
++
++
++static void xfp_phy_fini(struct efx_nic *efx)
++{
++ /* Clobber the LED if it was blinking */
++ efx->board_info.blink(efx, 0);
++}
++
++struct efx_phy_operations falcon_xfp_phy_ops = {
++ .init = xfp_phy_init,
++ .reconfigure = xfp_phy_reconfigure,
++ .check_hw = xfp_phy_check_hw,
++ .fini = xfp_phy_fini,
++ .clear_interrupt = xfp_phy_clear_interrupt,
++ .reset_xaui = efx_port_dummy_op_void,
++ .mmds = XFP_REQUIRED_DEVS,
++};
+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,
+ }
};
- /* 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++;
+@@ -850,3 +851,4 @@ module_exit(sgiseeq_module_exit);
+ MODULE_DESCRIPTION("SGI Seeq 8003 driver");
+ MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips at linux-mips.org>");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:sgiseeq");
+diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
+index 20745fd..abc63b0 100644
+--- a/drivers/net/sis190.c
++++ b/drivers/net/sis190.c
+@@ -212,6 +212,12 @@ enum _DescStatusBit {
+ THOL2 = 0x20000000,
+ THOL1 = 0x10000000,
+ THOL0 = 0x00000000,
++
++ WND = 0x00080000,
++ TABRT = 0x00040000,
++ FIFO = 0x00020000,
++ LINK = 0x00010000,
++ ColCountMask = 0x0000ffff,
+ /* RxDesc.status */
+ IPON = 0x20000000,
+ TCPON = 0x10000000,
+@@ -480,30 +486,23 @@ static inline void sis190_make_unusable_by_asic(struct RxDesc *desc)
+ desc->status = 0x0;
+ }
+
+-static int sis190_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
+- struct RxDesc *desc, u32 rx_buf_sz)
++static struct sk_buff *sis190_alloc_rx_skb(struct sis190_private *tp,
++ struct RxDesc *desc)
+ {
++ u32 rx_buf_sz = tp->rx_buf_sz;
+ struct sk_buff *skb;
+- dma_addr_t mapping;
+- int ret = 0;
+-
+- skb = dev_alloc_skb(rx_buf_sz);
+- if (!skb)
+- goto err_out;
+-
+- *sk_buff = skb;
- 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;
- }
+- mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
+- PCI_DMA_FROMDEVICE);
++ skb = netdev_alloc_skb(tp->dev, rx_buf_sz);
++ if (likely(skb)) {
++ dma_addr_t mapping;
- if (tx_status & (TxOutOfWindow | TxAborted)) {
-- priv->stats.tx_errors++;
-+ dev->stats.tx_errors++;
+- sis190_map_to_asic(desc, mapping, rx_buf_sz);
+-out:
+- return ret;
++ mapping = pci_map_single(tp->pci_dev, skb->data, tp->rx_buf_sz,
++ PCI_DMA_FROMDEVICE);
++ sis190_map_to_asic(desc, mapping, rx_buf_sz);
++ } else
++ sis190_make_unusable_by_asic(desc);
- if (tx_status & TxAborted)
-- priv->stats.tx_aborted_errors++;
-+ dev->stats.tx_aborted_errors++;
+-err_out:
+- ret = -ENOMEM;
+- sis190_make_unusable_by_asic(desc);
+- goto out;
++ return skb;
+ }
- if (tx_status & TxCarrierLost)
-- priv->stats.tx_carrier_errors++;
-+ dev->stats.tx_carrier_errors++;
+ static u32 sis190_rx_fill(struct sis190_private *tp, struct net_device *dev,
+@@ -512,37 +511,41 @@ static u32 sis190_rx_fill(struct sis190_private *tp, struct net_device *dev,
+ u32 cur;
+
+ for (cur = start; cur < end; cur++) {
+- int ret, i = cur % NUM_RX_DESC;
++ unsigned int i = cur % NUM_RX_DESC;
- if (tx_status & TxOutOfWindow)
-- priv->stats.tx_window_errors++;
-+ dev->stats.tx_window_errors++;
- }
+ if (tp->Rx_skbuff[i])
+ continue;
- if (tx_status & TxUnderrun)
-- priv->stats.tx_fifo_errors++;
-+ dev->stats.tx_fifo_errors++;
+- ret = sis190_alloc_rx_skb(tp->pci_dev, tp->Rx_skbuff + i,
+- tp->RxDescRing + i, tp->rx_buf_sz);
+- if (ret < 0)
++ tp->Rx_skbuff[i] = sis190_alloc_rx_skb(tp, tp->RxDescRing + i);
++
++ if (!tp->Rx_skbuff[i])
+ break;
}
-
- if (priv->tx_tail != old_tx_tail)
-@@ -704,27 +703,29 @@ static void _sc92031_tx_tasklet(struct net_device *dev)
- netif_wake_queue(dev);
+ return cur - start;
}
--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)
+-static inline int sis190_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
+- struct RxDesc *desc, int rx_buf_sz)
++static bool sis190_try_rx_copy(struct sis190_private *tp,
++ struct sk_buff **sk_buff, int pkt_size,
++ dma_addr_t addr)
{
- 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)
+- int ret = -1;
++ struct sk_buff *skb;
++ bool done = false;
- rx_len -= rx_size_align + 4;
+- if (pkt_size < rx_copybreak) {
+- struct sk_buff *skb;
++ if (pkt_size >= rx_copybreak)
++ goto out;
- 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++;
- }
+- if (skb) {
+- skb_reserve(skb, NET_IP_ALIGN);
+- skb_copy_to_linear_data(skb, sk_buff[0]->data, pkt_size);
+- *sk_buff = skb;
+- sis190_give_to_asic(desc, rx_buf_sz);
+- ret = 0;
+- }
+- }
+- return ret;
++ skb = netdev_alloc_skb(tp->dev, pkt_size + 2);
++ if (!skb)
++ goto out;
++
++ pci_dma_sync_single_for_device(tp->pci_dev, addr, pkt_size,
++ PCI_DMA_FROMDEVICE);
++ skb_reserve(skb, 2);
++ skb_copy_to_linear_data(skb, sk_buff[0]->data, pkt_size);
++ *sk_buff = skb;
++ done = true;
++out:
++ return done;
}
-@@ -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++;
- }
+ static inline int sis190_rx_pkt_err(u32 status, struct net_device_stats *stats)
+@@ -592,9 +595,9 @@ static int sis190_rx_interrupt(struct net_device *dev,
+ sis190_give_to_asic(desc, tp->rx_buf_sz);
+ else {
+ struct sk_buff *skb = tp->Rx_skbuff[entry];
++ dma_addr_t addr = le32_to_cpu(desc->addr);
+ int pkt_size = (status & RxSizeMask) - 4;
+- void (*pci_action)(struct pci_dev *, dma_addr_t,
+- size_t, int) = pci_dma_sync_single_for_device;
++ struct pci_dev *pdev = tp->pci_dev;
+
+ if (unlikely(pkt_size > tp->rx_buf_sz)) {
+ net_intr(tp, KERN_INFO
+@@ -606,20 +609,18 @@ static int sis190_rx_interrupt(struct net_device *dev,
+ continue;
+ }
- if (intr_status & (LinkFail | LinkOK))
-@@ -936,38 +935,36 @@ static struct net_device_stats *sc92031_get_stats(struct net_device *dev)
+- pci_dma_sync_single_for_cpu(tp->pci_dev,
+- le32_to_cpu(desc->addr), tp->rx_buf_sz,
+- PCI_DMA_FROMDEVICE);
- 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;
+- if (sis190_try_rx_copy(&skb, pkt_size, desc,
+- tp->rx_buf_sz)) {
+- pci_action = pci_unmap_single;
++ if (sis190_try_rx_copy(tp, &skb, pkt_size, addr)) {
++ pci_dma_sync_single_for_device(pdev, addr,
++ tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
++ sis190_give_to_asic(desc, tp->rx_buf_sz);
++ } else {
++ pci_unmap_single(pdev, addr, tp->rx_buf_sz,
++ PCI_DMA_FROMDEVICE);
+ tp->Rx_skbuff[entry] = NULL;
+ sis190_make_unusable_by_asic(desc);
+ }
- spin_unlock_bh(&priv->lock);
- }
+- pci_action(tp->pci_dev, le32_to_cpu(desc->addr),
+- tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
+-
+ skb_put(skb, pkt_size);
+ skb->protocol = eth_type_trans(skb, dev);
-- return &priv->stats;
-+ return &dev->stats;
+@@ -658,9 +659,31 @@ static void sis190_unmap_tx_skb(struct pci_dev *pdev, struct sk_buff *skb,
+ memset(desc, 0x00, sizeof(*desc));
}
- 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;
++static inline int sis190_tx_pkt_err(u32 status, struct net_device_stats *stats)
++{
++#define TxErrMask (WND | TABRT | FIFO | LINK)
+
- 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);
++ if (!unlikely(status & TxErrMask))
++ return 0;
++
++ if (status & WND)
++ stats->tx_window_errors++;
++ if (status & TABRT)
++ stats->tx_aborted_errors++;
++ if (status & FIFO)
++ stats->tx_fifo_errors++;
++ if (status & LINK)
++ stats->tx_carrier_errors++;
++
++ stats->tx_errors++;
++
++ return -1;
++}
++
+ static void sis190_tx_interrupt(struct net_device *dev,
+ struct sis190_private *tp, void __iomem *ioaddr)
+ {
++ struct net_device_stats *stats = &dev->stats;
+ u32 pending, dirty_tx = tp->dirty_tx;
+ /*
+ * It would not be needed if queueing was allowed to be enabled
+@@ -675,15 +698,19 @@ static void sis190_tx_interrupt(struct net_device *dev,
+ for (; pending; pending--, dirty_tx++) {
+ unsigned int entry = dirty_tx % NUM_TX_DESC;
+ struct TxDesc *txd = tp->TxDescRing + entry;
++ u32 status = le32_to_cpu(txd->status);
+ struct sk_buff *skb;
-- return err;
-+ return NETDEV_TX_OK;
- }
+- if (le32_to_cpu(txd->status) & OWNbit)
++ if (status & OWNbit)
+ break;
- 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,
- }
- };
+ skb = tp->Tx_skbuff[entry];
-@@ -850,3 +851,4 @@ module_exit(sgiseeq_module_exit);
- MODULE_DESCRIPTION("SGI Seeq 8003 driver");
- MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips at linux-mips.org>");
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:sgiseeq");
+- dev->stats.tx_packets++;
+- dev->stats.tx_bytes += skb->len;
++ if (likely(sis190_tx_pkt_err(status, stats) == 0)) {
++ stats->tx_packets++;
++ stats->tx_bytes += skb->len;
++ stats->collisions += ((status & ColCountMask) - 1);
++ }
+
+ sis190_unmap_tx_skb(tp->pci_dev, skb, txd);
+ tp->Tx_skbuff[entry] = NULL;
+@@ -904,10 +931,9 @@ static void sis190_phy_task(struct work_struct *work)
+ mod_timer(&tp->timer, jiffies + HZ/10);
+ } else if (!(mdio_read_latched(ioaddr, phy_id, MII_BMSR) &
+ BMSR_ANEGCOMPLETE)) {
+- net_link(tp, KERN_WARNING "%s: PHY reset until link up.\n",
+- dev->name);
+ netif_carrier_off(dev);
+- mdio_write(ioaddr, phy_id, MII_BMCR, val | BMCR_RESET);
++ net_link(tp, KERN_WARNING "%s: auto-negotiating...\n",
++ dev->name);
+ mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT);
+ } else {
+ /* Rejoice ! */
diff --git a/drivers/net/sk98lin/Makefile b/drivers/net/sk98lin/Makefile
deleted file mode 100644
index afd900d..0000000
@@ -525365,6 +716475,64 @@
RifLength = ri & FDDI_RCF_LEN_MASK;
if (len < (int) (FDDI_MAC_HDR_LEN + RifLength)) {
printk("fddi: Invalid RIF.\n");
+diff --git a/drivers/net/slip.c b/drivers/net/slip.c
+index 5a55ede..84af68f 100644
+--- a/drivers/net/slip.c
++++ b/drivers/net/slip.c
+@@ -396,14 +396,14 @@ static void sl_encaps(struct slip *sl, unsigned char *icp, int len)
+
+ /* Order of next two lines is *very* important.
+ * When we are sending a little amount of data,
+- * the transfer may be completed inside driver.write()
++ * the transfer may be completed inside the ops->write()
+ * routine, because it's running with interrupts enabled.
+ * In this case we *never* got WRITE_WAKEUP event,
+ * if we did not request it before write operation.
+ * 14 Oct 1994 Dmitry Gorodchanin.
+ */
+ sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+- actual = sl->tty->driver->write(sl->tty, sl->xbuff, count);
++ actual = sl->tty->ops->write(sl->tty, sl->xbuff, count);
+ #ifdef SL_CHECK_TRANSMIT
+ sl->dev->trans_start = jiffies;
+ #endif
+@@ -437,7 +437,7 @@ static void slip_write_wakeup(struct tty_struct *tty)
+ return;
+ }
+
+- actual = tty->driver->write(tty, sl->xhead, sl->xleft);
++ actual = tty->ops->write(tty, sl->xhead, sl->xleft);
+ sl->xleft -= actual;
+ sl->xhead += actual;
+ }
+@@ -462,7 +462,7 @@ static void sl_tx_timeout(struct net_device *dev)
+ }
+ printk(KERN_WARNING "%s: transmit timed out, %s?\n",
+ dev->name,
+- (sl->tty->driver->chars_in_buffer(sl->tty) || sl->xleft) ?
++ (tty_chars_in_buffer(sl->tty) || sl->xleft) ?
+ "bad line quality" : "driver error");
+ sl->xleft = 0;
+ sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+@@ -830,6 +830,9 @@ static int slip_open(struct tty_struct *tty)
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
++ if (tty->ops->write == NULL)
++ return -EOPNOTSUPP;
++
+ /* RTnetlink lock is misused here to serialize concurrent
+ opens of slip channels. There are better ways, but it is
+ the simplest one.
+@@ -1432,7 +1435,7 @@ static void sl_outfill(unsigned long sls)
+ /* put END into tty queue. Is it right ??? */
+ if (!netif_queue_stopped(sl->dev)) {
+ /* if device busy no outfill */
+- sl->tty->driver->write(sl->tty, &s, 1);
++ sl->tty->ops->write(sl->tty, &s, 1);
+ }
+ } else
+ set_bit(SLF_OUTWAIT, &sl->flags);
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 76cc1d3..4e28002 100644
--- a/drivers/net/smc911x.c
@@ -529495,7 +720663,7 @@
static int __init tc35815_init_module(void)
{
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
-index 17585e5..e83b166 100644
+index 17585e5..432e837 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/tehuti.c
@@ -625,6 +625,12 @@ static void __init bdx_firmware_endianess(void)
@@ -529515,7 +720683,7 @@
DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]);
}
-+ if (!capable(CAP_NET_ADMIN))
++ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
switch (data[0]) {
@@ -529538,7 +720706,7 @@
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
+index 96043c5..b66c75e 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -64,8 +64,8 @@
@@ -529584,6 +720752,15 @@
if (!new_skb) {
ret = -1;
} else {
+@@ -4349,7 +4361,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb)
+ }
+
+ segs = skb_gso_segment(skb, tp->dev->features & ~NETIF_F_TSO);
+- if (unlikely(IS_ERR(segs)))
++ if (IS_ERR(segs))
+ goto tg3_tso_bug_end;
+
+ do {
@@ -4462,7 +4474,9 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
would_hit_hwbug = 0;
@@ -529706,11 +720883,122 @@
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/de4x5.c b/drivers/net/tulip/de4x5.c
+index 6c6fc32..bc30c6e 100644
+--- a/drivers/net/tulip/de4x5.c
++++ b/drivers/net/tulip/de4x5.c
+@@ -482,7 +482,6 @@
+ static char version[] __devinitdata = "de4x5.c:V0.546 2001/02/22 davies at maniac.ultranet.com\n";
+
+ #define c_char const char
+-#define TWIDDLE(a) (u_short)le16_to_cpu(get_unaligned((__le16 *)(a)))
+
+ /*
+ ** MII Information
+@@ -4405,7 +4404,7 @@ srom_infoleaf_info(struct net_device *dev)
+ }
+ }
+
+- lp->infoleaf_offset = TWIDDLE(p+1);
++ lp->infoleaf_offset = get_unaligned_le16(p + 1);
+
+ return 0;
+ }
+@@ -4476,7 +4475,7 @@ srom_exec(struct net_device *dev, u_char *p)
+
+ while (count--) {
+ gep_wr(((lp->chipset==DC21140) && (lp->ibn!=5) ?
+- *p++ : TWIDDLE(w++)), dev);
++ *p++ : get_unaligned_le16(w++)), dev);
+ mdelay(2); /* 2ms per action */
+ }
+
+@@ -4711,10 +4710,10 @@ type1_infoblock(struct net_device *dev, u_char count, u_char *p)
+ lp->active = *p++;
+ lp->phy[lp->active].gep = (*p ? p : NULL); p += (*p + 1);
+ lp->phy[lp->active].rst = (*p ? p : NULL); p += (*p + 1);
+- lp->phy[lp->active].mc = TWIDDLE(p); p += 2;
+- lp->phy[lp->active].ana = TWIDDLE(p); p += 2;
+- lp->phy[lp->active].fdx = TWIDDLE(p); p += 2;
+- lp->phy[lp->active].ttm = TWIDDLE(p);
++ lp->phy[lp->active].mc = get_unaligned_le16(p); p += 2;
++ lp->phy[lp->active].ana = get_unaligned_le16(p); p += 2;
++ lp->phy[lp->active].fdx = get_unaligned_le16(p); p += 2;
++ lp->phy[lp->active].ttm = get_unaligned_le16(p);
+ return 0;
+ } else if ((lp->media == INIT) && (lp->timeout < 0)) {
+ lp->ibn = 1;
+@@ -4751,16 +4750,16 @@ type2_infoblock(struct net_device *dev, u_char count, u_char *p)
+ lp->infoblock_media = (*p) & MEDIA_CODE;
+
+ if ((*p++) & EXT_FIELD) {
+- lp->cache.csr13 = TWIDDLE(p); p += 2;
+- lp->cache.csr14 = TWIDDLE(p); p += 2;
+- lp->cache.csr15 = TWIDDLE(p); p += 2;
++ lp->cache.csr13 = get_unaligned_le16(p); p += 2;
++ lp->cache.csr14 = get_unaligned_le16(p); p += 2;
++ lp->cache.csr15 = get_unaligned_le16(p); p += 2;
+ } else {
+ lp->cache.csr13 = CSR13;
+ lp->cache.csr14 = CSR14;
+ lp->cache.csr15 = CSR15;
+ }
+- lp->cache.gepc = ((s32)(TWIDDLE(p)) << 16); p += 2;
+- lp->cache.gep = ((s32)(TWIDDLE(p)) << 16);
++ lp->cache.gepc = ((s32)(get_unaligned_le16(p)) << 16); p += 2;
++ lp->cache.gep = ((s32)(get_unaligned_le16(p)) << 16);
+ lp->infoblock_csr6 = OMR_SIA;
+ lp->useMII = false;
+
+@@ -4792,10 +4791,10 @@ type3_infoblock(struct net_device *dev, u_char count, u_char *p)
+ if (MOTO_SROM_BUG) lp->active = 0;
+ lp->phy[lp->active].gep = (*p ? p : NULL); p += (2 * (*p) + 1);
+ lp->phy[lp->active].rst = (*p ? p : NULL); p += (2 * (*p) + 1);
+- lp->phy[lp->active].mc = TWIDDLE(p); p += 2;
+- lp->phy[lp->active].ana = TWIDDLE(p); p += 2;
+- lp->phy[lp->active].fdx = TWIDDLE(p); p += 2;
+- lp->phy[lp->active].ttm = TWIDDLE(p); p += 2;
++ lp->phy[lp->active].mc = get_unaligned_le16(p); p += 2;
++ lp->phy[lp->active].ana = get_unaligned_le16(p); p += 2;
++ lp->phy[lp->active].fdx = get_unaligned_le16(p); p += 2;
++ lp->phy[lp->active].ttm = get_unaligned_le16(p); p += 2;
+ lp->phy[lp->active].mci = *p;
+ return 0;
+ } else if ((lp->media == INIT) && (lp->timeout < 0)) {
+@@ -4835,8 +4834,8 @@ type4_infoblock(struct net_device *dev, u_char count, u_char *p)
+ lp->cache.csr13 = CSR13; /* Hard coded defaults */
+ lp->cache.csr14 = CSR14;
+ lp->cache.csr15 = CSR15;
+- lp->cache.gepc = ((s32)(TWIDDLE(p)) << 16); p += 2;
+- lp->cache.gep = ((s32)(TWIDDLE(p)) << 16); p += 2;
++ lp->cache.gepc = ((s32)(get_unaligned_le16(p)) << 16); p += 2;
++ lp->cache.gep = ((s32)(get_unaligned_le16(p)) << 16); p += 2;
+ csr6 = *p++;
+ flags = *p++;
+
+diff --git a/drivers/net/tulip/de4x5.h b/drivers/net/tulip/de4x5.h
+index 9fb8d7f..f5f33b3 100644
+--- a/drivers/net/tulip/de4x5.h
++++ b/drivers/net/tulip/de4x5.h
+@@ -1017,4 +1017,4 @@ struct de4x5_ioctl {
+ #define DE4X5_SET_OMR 0x0d /* Set the OMR Register contents */
+ #define DE4X5_GET_REG 0x0e /* Get the DE4X5 Registers */
+
+-#define MOTO_SROM_BUG ((lp->active == 8) && (((le32_to_cpu(get_unaligned(((__le32 *)dev->dev_addr))))&0x00ffffff)==0x3e0008))
++#define MOTO_SROM_BUG (lp->active == 8 && (get_unaligned_le32(dev->dev_addr) & 0x00ffffff) == 0x3e0008)
diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h
-index 3f69f53..908422f 100644
+index 3f69f53..92c68a2 100644
--- a/drivers/net/tulip/tulip.h
+++ b/drivers/net/tulip/tulip.h
-@@ -268,7 +268,12 @@ enum t21143_csr6_bits {
+@@ -25,6 +25,7 @@
+ #include <linux/pci.h>
+ #include <asm/io.h>
+ #include <asm/irq.h>
++#include <asm/unaligned.h>
+
+
+
+@@ -268,7 +269,12 @@ enum t21143_csr6_bits {
#define RX_RING_SIZE 128
#define MEDIA_MASK 31
@@ -529724,10 +721012,34 @@
#define TULIP_MIN_CACHE_LINE 8 /* in units of 32-bit words */
+@@ -299,11 +305,7 @@ enum t21143_csr6_bits {
+
+ #define RUN_AT(x) (jiffies + (x))
+
+-#if defined(__i386__) /* AKA get_unaligned() */
+-#define get_u16(ptr) (*(u16 *)(ptr))
+-#else
+-#define get_u16(ptr) (((u8*)(ptr))[0] + (((u8*)(ptr))[1]<<8))
+-#endif
++#define get_u16(ptr) get_unaligned_le16((ptr))
+
+ struct medialeaf {
+ u8 type;
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
-index 82f404b..fa1c1c3 100644
+index 82f404b..f9d13fa 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
+@@ -327,8 +327,8 @@ static void tulip_up(struct net_device *dev)
+ tp->dirty_rx = tp->dirty_tx = 0;
+
+ if (tp->flags & MC_HASH_ONLY) {
+- u32 addr_low = le32_to_cpu(get_unaligned((__le32 *)dev->dev_addr));
+- u32 addr_high = le16_to_cpu(get_unaligned((__le16 *)(dev->dev_addr+4)));
++ u32 addr_low = get_unaligned_le32(dev->dev_addr);
++ u32 addr_high = get_unaligned_le16(dev->dev_addr + 4);
+ if (tp->chip_id == AX88140) {
+ iowrite32(0, ioaddr + CSR13);
+ iowrite32(addr_low, ioaddr + CSR14);
@@ -1154,18 +1154,13 @@ static void __devinit tulip_mwi_config (struct pci_dev *pdev,
tp->csr0 = csr0 = 0;
@@ -529763,6 +721075,23 @@
#endif
/* Stop the chip's Tx and Rx processes. */
+@@ -1446,13 +1437,13 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
+ do
+ value = ioread32(ioaddr + CSR9);
+ while (value < 0 && --boguscnt > 0);
+- put_unaligned(cpu_to_le16(value), ((__le16*)dev->dev_addr) + i);
++ put_unaligned_le16(value, ((__le16 *)dev->dev_addr) + i);
+ sum += value & 0xffff;
+ }
+ } else if (chip_idx == COMET) {
+ /* No need to read the EEPROM. */
+- put_unaligned(cpu_to_le32(ioread32(ioaddr + 0xA4)), (__le32 *)dev->dev_addr);
+- put_unaligned(cpu_to_le16(ioread32(ioaddr + 0xA8)), (__le16 *)(dev->dev_addr + 4));
++ put_unaligned_le32(ioread32(ioaddr + 0xA4), dev->dev_addr);
++ put_unaligned_le16(ioread32(ioaddr + 0xA8), dev->dev_addr + 4);
+ for (i = 0; i < 6; i ++)
+ sum += dev->dev_addr[i];
+ } else {
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
@@ -532250,6 +723579,48 @@
return NOTIFY_DONE;
if (!dev_is_ethdev(dev))
+diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
+index 63abfd7..e03eef2 100644
+--- a/drivers/net/wan/pc300_tty.c
++++ b/drivers/net/wan/pc300_tty.c
+@@ -178,6 +178,20 @@ static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char signal)
+ CPC_TTY_UNLOCK(card,flags);
+ }
+
++
++static const struct tty_operations pc300_ops = {
++ .open = cpc_tty_open,
++ .close = cpc_tty_close,
++ .write = cpc_tty_write,
++ .write_room = cpc_tty_write_room,
++ .chars_in_buffer = cpc_tty_chars_in_buffer,
++ .tiocmset = pc300_tiocmset,
++ .tiocmget = pc300_tiocmget,
++ .flush_buffer = cpc_tty_flush_buffer,
++ .hangup = cpc_tty_hangup,
++};
++
++
+ /*
+ * PC300 TTY initialization routine
+ *
+@@ -225,15 +239,7 @@ void cpc_tty_init(pc300dev_t *pc300dev)
+ serial_drv.flags = TTY_DRIVER_REAL_RAW;
+
+ /* interface routines from the upper tty layer to the tty driver */
+- serial_drv.open = cpc_tty_open;
+- serial_drv.close = cpc_tty_close;
+- serial_drv.write = cpc_tty_write;
+- serial_drv.write_room = cpc_tty_write_room;
+- serial_drv.chars_in_buffer = cpc_tty_chars_in_buffer;
+- serial_drv.tiocmset = pc300_tiocmset;
+- serial_drv.tiocmget = pc300_tiocmget;
+- serial_drv.flush_buffer = cpc_tty_flush_buffer;
+- serial_drv.hangup = cpc_tty_hangup;
++ tty_set_operations(&serial_drv, &pc300_ops);
+
+ /* register the TTY driver */
+ if (tty_register_driver(&serial_drv)) {
diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c
index 61e24b7..29b4b94 100644
--- a/drivers/net/wan/syncppp.c
@@ -532263,6 +723634,584 @@
kfree_skb(skb);
return 0;
}
+diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
+index 0f8aca8..249e180 100644
+--- a/drivers/net/wan/x25_asy.c
++++ b/drivers/net/wan/x25_asy.c
+@@ -17,7 +17,7 @@
+ #include <linux/module.h>
+
+ #include <asm/system.h>
+-#include <asm/uaccess.h>
++#include <linux/uaccess.h>
+ #include <linux/bitops.h>
+ #include <linux/string.h>
+ #include <linux/mm.h>
+@@ -95,7 +95,7 @@ static struct x25_asy *x25_asy_alloc(void)
+ x25_asy_devs[i] = dev;
+ return sl;
+ } else {
+- printk("x25_asy_alloc() - register_netdev() failure.\n");
++ printk(KERN_WARNING "x25_asy_alloc() - register_netdev() failure.\n");
+ free_netdev(dev);
+ }
+ }
+@@ -112,23 +112,22 @@ static void x25_asy_free(struct x25_asy *sl)
+ kfree(sl->xbuff);
+ sl->xbuff = NULL;
+
+- if (!test_and_clear_bit(SLF_INUSE, &sl->flags)) {
+- printk("%s: x25_asy_free for already free unit.\n", sl->dev->name);
+- }
++ if (!test_and_clear_bit(SLF_INUSE, &sl->flags))
++ printk(KERN_ERR "%s: x25_asy_free for already free unit.\n",
++ sl->dev->name);
+ }
+
+ static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
+ {
+ struct x25_asy *sl = dev->priv;
+ unsigned char *xbuff, *rbuff;
+- int len = 2* newmtu;
++ int len = 2 * newmtu;
+
+ xbuff = kmalloc(len + 4, GFP_ATOMIC);
+ rbuff = kmalloc(len + 4, GFP_ATOMIC);
+
+- if (xbuff == NULL || rbuff == NULL)
+- {
+- printk("%s: unable to grow X.25 buffers, MTU change cancelled.\n",
++ if (xbuff == NULL || rbuff == NULL) {
++ printk(KERN_WARNING "%s: unable to grow X.25 buffers, MTU change cancelled.\n",
+ dev->name);
+ kfree(xbuff);
+ kfree(rbuff);
+@@ -193,25 +192,23 @@ static void x25_asy_bump(struct x25_asy *sl)
+ int err;
+
+ count = sl->rcount;
+- sl->stats.rx_bytes+=count;
+-
++ sl->stats.rx_bytes += count;
++
+ skb = dev_alloc_skb(count+1);
+- if (skb == NULL)
+- {
+- printk("%s: memory squeeze, dropping packet.\n", sl->dev->name);
++ if (skb == NULL) {
++ printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n",
++ sl->dev->name);
+ sl->stats.rx_dropped++;
+ return;
+ }
+- skb_push(skb,1); /* LAPB internal control */
+- memcpy(skb_put(skb,count), sl->rbuff, count);
++ skb_push(skb, 1); /* LAPB internal control */
++ memcpy(skb_put(skb, count), sl->rbuff, count);
+ skb->protocol = x25_type_trans(skb, sl->dev);
+- if((err=lapb_data_received(skb->dev, skb))!=LAPB_OK)
+- {
++ err = lapb_data_received(skb->dev, skb);
++ if (err != LAPB_OK) {
+ kfree_skb(skb);
+- printk(KERN_DEBUG "x25_asy: data received err - %d\n",err);
+- }
+- else
+- {
++ printk(KERN_DEBUG "x25_asy: data received err - %d\n", err);
++ } else {
+ netif_rx(skb);
+ sl->dev->last_rx = jiffies;
+ sl->stats.rx_packets++;
+@@ -224,10 +221,11 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len)
+ unsigned char *p;
+ int actual, count, mtu = sl->dev->mtu;
+
+- if (len > mtu)
+- { /* Sigh, shouldn't occur BUT ... */
++ if (len > mtu) {
++ /* Sigh, shouldn't occur BUT ... */
+ len = mtu;
+- printk ("%s: truncating oversized transmit packet!\n", sl->dev->name);
++ printk(KERN_DEBUG "%s: truncating oversized transmit packet!\n",
++ sl->dev->name);
+ sl->stats.tx_dropped++;
+ x25_asy_unlock(sl);
+ return;
+@@ -245,7 +243,7 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len)
+ * 14 Oct 1994 Dmitry Gorodchanin.
+ */
+ sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+- actual = sl->tty->driver->write(sl->tty, sl->xbuff, count);
++ actual = sl->tty->ops->write(sl->tty, sl->xbuff, count);
+ sl->xleft = count - actual;
+ sl->xhead = sl->xbuff + actual;
+ /* VSV */
+@@ -265,8 +263,7 @@ static void x25_asy_write_wakeup(struct tty_struct *tty)
+ if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))
+ return;
+
+- if (sl->xleft <= 0)
+- {
++ if (sl->xleft <= 0) {
+ /* Now serial buffer is almost free & we can start
+ * transmission of another packet */
+ sl->stats.tx_packets++;
+@@ -275,14 +272,14 @@ static void x25_asy_write_wakeup(struct tty_struct *tty)
+ return;
+ }
+
+- actual = tty->driver->write(tty, sl->xhead, sl->xleft);
++ actual = tty->ops->write(tty, sl->xhead, sl->xleft);
+ sl->xleft -= actual;
+ sl->xhead += actual;
+ }
+
+ static void x25_asy_timeout(struct net_device *dev)
+ {
+- struct x25_asy *sl = (struct x25_asy*)(dev->priv);
++ struct x25_asy *sl = dev->priv;
+
+ spin_lock(&sl->lock);
+ if (netif_queue_stopped(dev)) {
+@@ -290,7 +287,7 @@ static void x25_asy_timeout(struct net_device *dev)
+ * 14 Oct 1994 Dmitry Gorodchanin.
+ */
+ printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
+- (sl->tty->driver->chars_in_buffer(sl->tty) || sl->xleft) ?
++ (tty_chars_in_buffer(sl->tty) || sl->xleft) ?
+ "bad line quality" : "driver error");
+ sl->xleft = 0;
+ sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+@@ -303,31 +300,34 @@ static void x25_asy_timeout(struct net_device *dev)
+
+ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+- struct x25_asy *sl = (struct x25_asy*)(dev->priv);
++ struct x25_asy *sl = dev->priv;
+ int err;
+
+ if (!netif_running(sl->dev)) {
+- printk("%s: xmit call when iface is down\n", dev->name);
++ printk(KERN_ERR "%s: xmit call when iface is down\n",
++ dev->name);
+ kfree_skb(skb);
+ return 0;
+ }
+-
+- switch(skb->data[0])
+- {
+- case 0x00:break;
+- case 0x01: /* Connection request .. do nothing */
+- if((err=lapb_connect_request(dev))!=LAPB_OK)
+- printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err);
+- kfree_skb(skb);
+- return 0;
+- case 0x02: /* Disconnect request .. do nothing - hang up ?? */
+- if((err=lapb_disconnect_request(dev))!=LAPB_OK)
+- printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err);
+- default:
+- kfree_skb(skb);
+- return 0;
++
++ switch (skb->data[0]) {
++ case 0x00:
++ break;
++ case 0x01: /* Connection request .. do nothing */
++ err = lapb_connect_request(dev);
++ if (err != LAPB_OK)
++ printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err);
++ kfree_skb(skb);
++ return 0;
++ case 0x02: /* Disconnect request .. do nothing - hang up ?? */
++ err = lapb_disconnect_request(dev);
++ if (err != LAPB_OK)
++ printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err);
++ default:
++ kfree_skb(skb);
++ return 0;
+ }
+- skb_pull(skb,1); /* Remove control byte */
++ skb_pull(skb, 1); /* Remove control byte */
+ /*
+ * If we are busy already- too bad. We ought to be able
+ * to queue things at this point, to allow for a little
+@@ -338,10 +338,10 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
+ * So, no queues !
+ * 14 Oct 1994 Dmitry Gorodchanin.
+ */
+-
+- if((err=lapb_data_request(dev,skb))!=LAPB_OK)
+- {
+- printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err);
++
++ err = lapb_data_request(dev, skb);
++ if (err != LAPB_OK) {
++ printk(KERN_ERR "x25_asy: lapb_data_request error - %d\n", err);
+ kfree_skb(skb);
+ return 0;
+ }
+@@ -357,7 +357,7 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
+ * Called when I frame data arrives. We did the work above - throw it
+ * at the net layer.
+ */
+-
++
+ static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb)
+ {
+ skb->dev->last_rx = jiffies;
+@@ -369,24 +369,22 @@ static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb)
+ * busy cases too well. Its tricky to see how to do this nicely -
+ * perhaps lapb should allow us to bounce this ?
+ */
+-
++
+ static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb)
+ {
+- struct x25_asy *sl=dev->priv;
+-
++ struct x25_asy *sl = dev->priv;
++
+ spin_lock(&sl->lock);
+- if (netif_queue_stopped(sl->dev) || sl->tty == NULL)
+- {
++ if (netif_queue_stopped(sl->dev) || sl->tty == NULL) {
+ spin_unlock(&sl->lock);
+ printk(KERN_ERR "x25_asy: tbusy drop\n");
+ kfree_skb(skb);
+ return;
+ }
+ /* We were not busy, so we are now... :-) */
+- if (skb != NULL)
+- {
++ if (skb != NULL) {
+ x25_asy_lock(sl);
+- sl->stats.tx_bytes+=skb->len;
++ sl->stats.tx_bytes += skb->len;
+ x25_asy_encaps(sl, skb->data, skb->len);
+ dev_kfree_skb(skb);
+ }
+@@ -396,15 +394,16 @@ static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb)
+ /*
+ * LAPB connection establish/down information.
+ */
+-
++
+ static void x25_asy_connected(struct net_device *dev, int reason)
+ {
+ struct x25_asy *sl = dev->priv;
+ struct sk_buff *skb;
+ unsigned char *ptr;
+
+- if ((skb = dev_alloc_skb(1)) == NULL) {
+- printk(KERN_ERR "lapbeth: out of memory\n");
++ skb = dev_alloc_skb(1);
++ if (skb == NULL) {
++ printk(KERN_ERR "x25_asy: out of memory\n");
+ return;
+ }
+
+@@ -422,7 +421,8 @@ static void x25_asy_disconnected(struct net_device *dev, int reason)
+ struct sk_buff *skb;
+ unsigned char *ptr;
+
+- if ((skb = dev_alloc_skb(1)) == NULL) {
++ skb = dev_alloc_skb(1);
++ if (skb == NULL) {
+ printk(KERN_ERR "x25_asy: out of memory\n");
+ return;
+ }
+@@ -449,7 +449,7 @@ static struct lapb_register_struct x25_asy_callbacks = {
+ /* Open the low-level part of the X.25 channel. Easy! */
+ static int x25_asy_open(struct net_device *dev)
+ {
+- struct x25_asy *sl = (struct x25_asy*)(dev->priv);
++ struct x25_asy *sl = dev->priv;
+ unsigned long len;
+ int err;
+
+@@ -466,13 +466,11 @@ static int x25_asy_open(struct net_device *dev)
+ len = dev->mtu * 2;
+
+ sl->rbuff = kmalloc(len + 4, GFP_KERNEL);
+- if (sl->rbuff == NULL) {
++ if (sl->rbuff == NULL)
+ goto norbuff;
+- }
+ sl->xbuff = kmalloc(len + 4, GFP_KERNEL);
+- if (sl->xbuff == NULL) {
++ if (sl->xbuff == NULL)
+ goto noxbuff;
+- }
+
+ sl->buffsize = len;
+ sl->rcount = 0;
+@@ -480,11 +478,12 @@ static int x25_asy_open(struct net_device *dev)
+ sl->flags &= (1 << SLF_INUSE); /* Clear ESCAPE & ERROR flags */
+
+ netif_start_queue(dev);
+-
++
+ /*
+ * Now attach LAPB
+ */
+- if((err=lapb_register(dev, &x25_asy_callbacks))==LAPB_OK)
++ err = lapb_register(dev, &x25_asy_callbacks);
++ if (err == LAPB_OK)
+ return 0;
+
+ /* Cleanup */
+@@ -499,18 +498,20 @@ norbuff:
+ /* Close the low-level part of the X.25 channel. Easy! */
+ static int x25_asy_close(struct net_device *dev)
+ {
+- struct x25_asy *sl = (struct x25_asy*)(dev->priv);
++ struct x25_asy *sl = dev->priv;
+ int err;
+
+ spin_lock(&sl->lock);
+- if (sl->tty)
++ if (sl->tty)
+ sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+
+ netif_stop_queue(dev);
+ sl->rcount = 0;
+ sl->xleft = 0;
+- if((err=lapb_unregister(dev))!=LAPB_OK)
+- printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",err);
++ err = lapb_unregister(dev);
++ if (err != LAPB_OK)
++ printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",
++ err);
+ spin_unlock(&sl->lock);
+ return 0;
+ }
+@@ -521,8 +522,9 @@ static int x25_asy_close(struct net_device *dev)
+ * a block of X.25 data has been received, which can now be decapsulated
+ * and sent on to some IP layer for further processing.
+ */
+-
+-static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
++
++static void x25_asy_receive_buf(struct tty_struct *tty,
++ const unsigned char *cp, char *fp, int count)
+ {
+ struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
+
+@@ -533,9 +535,8 @@ static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp,
+ /* Read the characters out of the buffer */
+ while (count--) {
+ if (fp && *fp++) {
+- if (!test_and_set_bit(SLF_ERROR, &sl->flags)) {
++ if (!test_and_set_bit(SLF_ERROR, &sl->flags))
+ sl->stats.rx_errors++;
+- }
+ cp++;
+ continue;
+ }
+@@ -556,31 +557,31 @@ static int x25_asy_open_tty(struct tty_struct *tty)
+ struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
+ int err;
+
++ if (tty->ops->write == NULL)
++ return -EOPNOTSUPP;
++
+ /* First make sure we're not already connected. */
+- if (sl && sl->magic == X25_ASY_MAGIC) {
++ if (sl && sl->magic == X25_ASY_MAGIC)
+ return -EEXIST;
+- }
+
+ /* OK. Find a free X.25 channel to use. */
+- if ((sl = x25_asy_alloc()) == NULL) {
++ sl = x25_asy_alloc();
++ if (sl == NULL)
+ return -ENFILE;
+- }
+
+ sl->tty = tty;
+ tty->disc_data = sl;
+ tty->receive_room = 65536;
+- if (tty->driver->flush_buffer) {
+- tty->driver->flush_buffer(tty);
+- }
++ tty_driver_flush_buffer(tty);
+ tty_ldisc_flush(tty);
+
+ /* Restore default settings */
+ sl->dev->type = ARPHRD_X25;
+-
++
+ /* Perform the low-level X.25 async init */
+- if ((err = x25_asy_open(sl->dev)))
++ err = x25_asy_open(sl->dev);
++ if (err)
+ return err;
+-
+ /* Done. We have linked the TTY line to a channel. */
+ return sl->dev->base_addr;
+ }
+@@ -601,9 +602,7 @@ static void x25_asy_close_tty(struct tty_struct *tty)
+ return;
+
+ if (sl->dev->flags & IFF_UP)
+- {
+- (void) dev_close(sl->dev);
+- }
++ dev_close(sl->dev);
+
+ tty->disc_data = NULL;
+ sl->tty = NULL;
+@@ -613,8 +612,7 @@ static void x25_asy_close_tty(struct tty_struct *tty)
+
+ static struct net_device_stats *x25_asy_get_stats(struct net_device *dev)
+ {
+- struct x25_asy *sl = (struct x25_asy*)(dev->priv);
+-
++ struct x25_asy *sl = dev->priv;
+ return &sl->stats;
+ }
+
+@@ -641,21 +639,19 @@ int x25_asy_esc(unsigned char *s, unsigned char *d, int len)
+ * character sequence, according to the X.25 protocol.
+ */
+
+- while (len-- > 0)
+- {
+- switch(c = *s++)
+- {
+- case X25_END:
+- *ptr++ = X25_ESC;
+- *ptr++ = X25_ESCAPE(X25_END);
+- break;
+- case X25_ESC:
+- *ptr++ = X25_ESC;
+- *ptr++ = X25_ESCAPE(X25_ESC);
+- break;
+- default:
+- *ptr++ = c;
+- break;
++ while (len-- > 0) {
++ switch (c = *s++) {
++ case X25_END:
++ *ptr++ = X25_ESC;
++ *ptr++ = X25_ESCAPE(X25_END);
++ break;
++ case X25_ESC:
++ *ptr++ = X25_ESC;
++ *ptr++ = X25_ESCAPE(X25_ESC);
++ break;
++ default:
++ *ptr++ = c;
++ break;
+ }
+ }
+ *ptr++ = X25_END;
+@@ -665,31 +661,25 @@ int x25_asy_esc(unsigned char *s, unsigned char *d, int len)
+ static void x25_asy_unesc(struct x25_asy *sl, unsigned char s)
+ {
+
+- switch(s)
+- {
+- case X25_END:
+- if (!test_and_clear_bit(SLF_ERROR, &sl->flags) && (sl->rcount > 2))
+- {
+- x25_asy_bump(sl);
+- }
+- clear_bit(SLF_ESCAPE, &sl->flags);
+- sl->rcount = 0;
+- return;
+-
+- case X25_ESC:
+- set_bit(SLF_ESCAPE, &sl->flags);
+- return;
+-
+- case X25_ESCAPE(X25_ESC):
+- case X25_ESCAPE(X25_END):
+- if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))
+- s = X25_UNESCAPE(s);
+- break;
+- }
+- if (!test_bit(SLF_ERROR, &sl->flags))
+- {
+- if (sl->rcount < sl->buffsize)
+- {
++ switch (s) {
++ case X25_END:
++ if (!test_and_clear_bit(SLF_ERROR, &sl->flags)
++ && sl->rcount > 2)
++ x25_asy_bump(sl);
++ clear_bit(SLF_ESCAPE, &sl->flags);
++ sl->rcount = 0;
++ return;
++ case X25_ESC:
++ set_bit(SLF_ESCAPE, &sl->flags);
++ return;
++ case X25_ESCAPE(X25_ESC):
++ case X25_ESCAPE(X25_END):
++ if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))
++ s = X25_UNESCAPE(s);
++ break;
++ }
++ if (!test_bit(SLF_ERROR, &sl->flags)) {
++ if (sl->rcount < sl->buffsize) {
+ sl->rbuff[sl->rcount++] = s;
+ return;
+ }
+@@ -709,7 +699,7 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file,
+ if (!sl || sl->magic != X25_ASY_MAGIC)
+ return -EINVAL;
+
+- switch(cmd) {
++ switch (cmd) {
+ case SIOCGIFNAME:
+ if (copy_to_user((void __user *)arg, sl->dev->name,
+ strlen(sl->dev->name) + 1))
+@@ -724,8 +714,8 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file,
+
+ static int x25_asy_open_dev(struct net_device *dev)
+ {
+- struct x25_asy *sl = (struct x25_asy*)(dev->priv);
+- if(sl->tty==NULL)
++ struct x25_asy *sl = dev->priv;
++ if (sl->tty == NULL)
+ return -ENODEV;
+ return 0;
+ }
+@@ -741,9 +731,9 @@ static void x25_asy_setup(struct net_device *dev)
+ set_bit(SLF_INUSE, &sl->flags);
+
+ /*
+- * Finish setting up the DEVICE info.
++ * Finish setting up the DEVICE info.
+ */
+-
++
+ dev->mtu = SL_MTU;
+ dev->hard_start_xmit = x25_asy_xmit;
+ dev->tx_timeout = x25_asy_timeout;
+@@ -778,9 +768,10 @@ static int __init init_x25_asy(void)
+ x25_asy_maxdev = 4; /* Sanity */
+
+ printk(KERN_INFO "X.25 async: version 0.00 ALPHA "
+- "(dynamic channels, max=%d).\n", x25_asy_maxdev );
++ "(dynamic channels, max=%d).\n", x25_asy_maxdev);
+
+- x25_asy_devs = kcalloc(x25_asy_maxdev, sizeof(struct net_device*), GFP_KERNEL);
++ x25_asy_devs = kcalloc(x25_asy_maxdev, sizeof(struct net_device *),
++ GFP_KERNEL);
+ if (!x25_asy_devs) {
+ printk(KERN_WARNING "X25 async: Can't allocate x25_asy_ctrls[] "
+ "array! Uaargh! (-> No X.25 available)\n");
+@@ -802,7 +793,7 @@ static void __exit exit_x25_asy(void)
+ struct x25_asy *sl = dev->priv;
+
+ spin_lock_bh(&sl->lock);
+- if (sl->tty)
++ if (sl->tty)
+ tty_hangup(sl->tty);
+
+ spin_unlock_bh(&sl->lock);
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 714a6ca..fdf5aa8 100644
--- a/drivers/net/wireless/Kconfig
@@ -532419,7 +724368,7 @@
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
+index 091dfe2..2c343aa 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -35,7 +35,6 @@ obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o
@@ -532436,7 +724385,7 @@
-obj-$(CONFIG_IWL3945) += iwlwifi/
-obj-$(CONFIG_IWL4965) += iwlwifi/
-+obj-$(CONFIG_IWLCORE) += iwlwifi/
++obj-$(CONFIG_IWLWIFI) += iwlwifi/
obj-$(CONFIG_RT2X00) += rt2x00/
-obj-$(CONFIG_P54_COMMON) += p54common.o
@@ -532735,6 +724684,246 @@
static const struct ieee80211_chan_range cranges[] = {
{1, 11}, /* FCC */
{1, 11}, /* IC */
+diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
+index 932d6b1..45f47c1 100644
+--- a/drivers/net/wireless/airo.c
++++ b/drivers/net/wireless/airo.c
+@@ -3657,7 +3657,7 @@ void mpi_receive_802_11 (struct airo_info *ai)
+ ptr += hdrlen;
+ if (hdrlen == 24)
+ ptr += 6;
+- gap = le16_to_cpu(get_unaligned((__le16 *)ptr));
++ gap = get_unaligned_le16(ptr);
+ ptr += sizeof(__le16);
+ if (gap) {
+ if (gap <= 8)
+@@ -4347,24 +4347,28 @@ static int proc_config_open( struct inode *inode, struct file *file );
+ static int proc_wepkey_open( struct inode *inode, struct file *file );
+
+ static const struct file_operations proc_statsdelta_ops = {
++ .owner = THIS_MODULE,
+ .read = proc_read,
+ .open = proc_statsdelta_open,
+ .release = proc_close
+ };
+
+ static const struct file_operations proc_stats_ops = {
++ .owner = THIS_MODULE,
+ .read = proc_read,
+ .open = proc_stats_open,
+ .release = proc_close
+ };
+
+ static const struct file_operations proc_status_ops = {
++ .owner = THIS_MODULE,
+ .read = proc_read,
+ .open = proc_status_open,
+ .release = proc_close
+ };
+
+ static const struct file_operations proc_SSID_ops = {
++ .owner = THIS_MODULE,
+ .read = proc_read,
+ .write = proc_write,
+ .open = proc_SSID_open,
+@@ -4372,6 +4376,7 @@ static const struct file_operations proc_SSID_ops = {
+ };
+
+ static const struct file_operations proc_BSSList_ops = {
++ .owner = THIS_MODULE,
+ .read = proc_read,
+ .write = proc_write,
+ .open = proc_BSSList_open,
+@@ -4379,6 +4384,7 @@ static const struct file_operations proc_BSSList_ops = {
+ };
+
+ static const struct file_operations proc_APList_ops = {
++ .owner = THIS_MODULE,
+ .read = proc_read,
+ .write = proc_write,
+ .open = proc_APList_open,
+@@ -4386,6 +4392,7 @@ static const struct file_operations proc_APList_ops = {
+ };
+
+ static const struct file_operations proc_config_ops = {
++ .owner = THIS_MODULE,
+ .read = proc_read,
+ .write = proc_write,
+ .open = proc_config_open,
+@@ -4393,6 +4400,7 @@ static const struct file_operations proc_config_ops = {
+ };
+
+ static const struct file_operations proc_wepkey_ops = {
++ .owner = THIS_MODULE,
+ .read = proc_read,
+ .write = proc_write,
+ .open = proc_wepkey_open,
+@@ -4411,10 +4419,6 @@ struct proc_data {
+ void (*on_close) (struct inode *, struct file *);
+ };
+
+-#ifndef SETPROC_OPS
+-#define SETPROC_OPS(entry, ops) (entry)->proc_fops = &(ops)
+-#endif
+-
+ static int setup_proc_entry( struct net_device *dev,
+ struct airo_info *apriv ) {
+ struct proc_dir_entry *entry;
+@@ -4430,100 +4434,76 @@ static int setup_proc_entry( struct net_device *dev,
+ apriv->proc_entry->owner = THIS_MODULE;
+
+ /* Setup the StatsDelta */
+- entry = create_proc_entry("StatsDelta",
+- S_IFREG | (S_IRUGO&proc_perm),
+- apriv->proc_entry);
++ entry = proc_create_data("StatsDelta",
++ S_IFREG | (S_IRUGO&proc_perm),
++ apriv->proc_entry, &proc_statsdelta_ops, dev);
+ if (!entry)
+ goto fail_stats_delta;
+ entry->uid = proc_uid;
+ entry->gid = proc_gid;
+- entry->data = dev;
+- entry->owner = THIS_MODULE;
+- SETPROC_OPS(entry, proc_statsdelta_ops);
+
+ /* Setup the Stats */
+- entry = create_proc_entry("Stats",
+- S_IFREG | (S_IRUGO&proc_perm),
+- apriv->proc_entry);
++ entry = proc_create_data("Stats",
++ S_IFREG | (S_IRUGO&proc_perm),
++ apriv->proc_entry, &proc_stats_ops, dev);
+ if (!entry)
+ goto fail_stats;
+ entry->uid = proc_uid;
+ entry->gid = proc_gid;
+- entry->data = dev;
+- entry->owner = THIS_MODULE;
+- SETPROC_OPS(entry, proc_stats_ops);
+
+ /* Setup the Status */
+- entry = create_proc_entry("Status",
+- S_IFREG | (S_IRUGO&proc_perm),
+- apriv->proc_entry);
++ entry = proc_create_data("Status",
++ S_IFREG | (S_IRUGO&proc_perm),
++ apriv->proc_entry, &proc_status_ops, dev);
+ if (!entry)
+ goto fail_status;
+ entry->uid = proc_uid;
+ entry->gid = proc_gid;
+- entry->data = dev;
+- entry->owner = THIS_MODULE;
+- SETPROC_OPS(entry, proc_status_ops);
+
+ /* Setup the Config */
+- entry = create_proc_entry("Config",
+- S_IFREG | proc_perm,
+- apriv->proc_entry);
++ entry = proc_create_data("Config",
++ S_IFREG | proc_perm,
++ apriv->proc_entry, &proc_config_ops, dev);
+ if (!entry)
+ goto fail_config;
+ entry->uid = proc_uid;
+ entry->gid = proc_gid;
+- entry->data = dev;
+- entry->owner = THIS_MODULE;
+- SETPROC_OPS(entry, proc_config_ops);
+
+ /* Setup the SSID */
+- entry = create_proc_entry("SSID",
+- S_IFREG | proc_perm,
+- apriv->proc_entry);
++ entry = proc_create_data("SSID",
++ S_IFREG | proc_perm,
++ apriv->proc_entry, &proc_SSID_ops, dev);
+ if (!entry)
+ goto fail_ssid;
+ entry->uid = proc_uid;
+ entry->gid = proc_gid;
+- entry->data = dev;
+- entry->owner = THIS_MODULE;
+- SETPROC_OPS(entry, proc_SSID_ops);
+
+ /* Setup the APList */
+- entry = create_proc_entry("APList",
+- S_IFREG | proc_perm,
+- apriv->proc_entry);
++ entry = proc_create_data("APList",
++ S_IFREG | proc_perm,
++ apriv->proc_entry, &proc_APList_ops, dev);
+ if (!entry)
+ goto fail_aplist;
+ entry->uid = proc_uid;
+ entry->gid = proc_gid;
+- entry->data = dev;
+- entry->owner = THIS_MODULE;
+- SETPROC_OPS(entry, proc_APList_ops);
+
+ /* Setup the BSSList */
+- entry = create_proc_entry("BSSList",
+- S_IFREG | proc_perm,
+- apriv->proc_entry);
++ entry = proc_create_data("BSSList",
++ S_IFREG | proc_perm,
++ apriv->proc_entry, &proc_BSSList_ops, dev);
+ if (!entry)
+ goto fail_bsslist;
+ entry->uid = proc_uid;
+ entry->gid = proc_gid;
+- entry->data = dev;
+- entry->owner = THIS_MODULE;
+- SETPROC_OPS(entry, proc_BSSList_ops);
+
+ /* Setup the WepKey */
+- entry = create_proc_entry("WepKey",
+- S_IFREG | proc_perm,
+- apriv->proc_entry);
++ entry = proc_create_data("WepKey",
++ S_IFREG | proc_perm,
++ apriv->proc_entry, &proc_wepkey_ops, dev);
+ if (!entry)
+ goto fail_wepkey;
+ entry->uid = proc_uid;
+ entry->gid = proc_gid;
+- entry->data = dev;
+- entry->owner = THIS_MODULE;
+- SETPROC_OPS(entry, proc_wepkey_ops);
+
+ return 0;
+
+@@ -5625,9 +5605,9 @@ static int __init airo_init_module( void )
+ int have_isa_dev = 0;
+ #endif
+
+- airo_entry = create_proc_entry("aironet",
++ airo_entry = create_proc_entry("driver/aironet",
+ S_IFDIR | airo_perm,
+- proc_root_driver);
++ NULL);
+
+ if (airo_entry) {
+ airo_entry->uid = proc_uid;
+@@ -5651,7 +5631,7 @@ static int __init airo_init_module( void )
+ airo_print_info("", "Finished probing for PCI adapters");
+
+ if (i) {
+- remove_proc_entry("aironet", proc_root_driver);
++ remove_proc_entry("driver/aironet", NULL);
+ return i;
+ }
+ #endif
+@@ -5673,7 +5653,7 @@ static void __exit airo_cleanup_module( void )
+ #ifdef CONFIG_PCI
+ pci_unregister_driver(&airo_driver);
+ #endif
+- remove_proc_entry("aironet", proc_root_driver);
++ remove_proc_entry("driver/aironet", NULL);
+ }
+
+ /*
diff --git a/drivers/net/wireless/ath5k/Kconfig b/drivers/net/wireless/ath5k/Kconfig
new file mode 100644
index 0000000..f1f2aea
@@ -533144,10 +725333,21 @@
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
+index bef967c..4e5c8fc 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
-@@ -80,7 +80,7 @@ MODULE_AUTHOR("Nick Kossifidis");
+@@ -58,10 +58,6 @@
+ #include "reg.h"
+ #include "debug.h"
+
+-/* unaligned little endian access */
+-#define LE_READ_2(_p) (le16_to_cpu(get_unaligned((__le16 *)(_p))))
+-#define LE_READ_4(_p) (le32_to_cpu(get_unaligned((__le32 *)(_p))))
+-
+ enum {
+ ATH_LED_TX,
+ ATH_LED_RX,
+@@ -80,7 +76,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");
@@ -533156,7 +725356,7 @@
/* Known PCI ids */
-@@ -118,12 +118,15 @@ static struct ath5k_srev_name srev_names[] = {
+@@ -118,12 +114,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 },
@@ -533172,7 +725372,7 @@
{ "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[] = {
+@@ -132,6 +131,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 },
@@ -533180,7 +725380,7 @@
{ "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,
+@@ -240,6 +240,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);
@@ -533189,7 +725389,7 @@
/* 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);
+@@ -278,7 +280,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,
@@ -533199,7 +725399,7 @@
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,
+@@ -511,35 +514,46 @@ ath5k_pci_probe(struct pci_dev *pdev,
sc->ah->ah_mac_srev,
sc->ah->ah_phy_revision);
@@ -533263,7 +725463,7 @@
}
}
-@@ -693,11 +711,14 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
+@@ -693,11 +707,14 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
goto err;
}
@@ -533281,7 +725481,7 @@
/*
* Allocate tx+rx descriptors and populate the lists.
-@@ -837,12 +858,9 @@ ath5k_copy_rates(struct ieee80211_rate *rates,
+@@ -837,12 +854,9 @@ ath5k_copy_rates(struct ieee80211_rate *rates,
return 0;
for (i = 0, count = 0; i < rt->rate_count && max > 0; i++) {
@@ -533297,7 +725497,7 @@
count++;
max--;
}
-@@ -856,43 +874,22 @@ ath5k_copy_channels(struct ath5k_hw *ah,
+@@ -856,43 +870,22 @@ ath5k_copy_channels(struct ath5k_hw *ah,
unsigned int mode,
unsigned int max)
{
@@ -533349,7 +725549,7 @@
chfreq = CHANNEL_2GHZ;
break;
default:
-@@ -901,25 +898,31 @@ ath5k_copy_channels(struct ath5k_hw *ah,
+@@ -901,25 +894,31 @@ ath5k_copy_channels(struct ath5k_hw *ah,
}
for (i = 0, count = 0; i < size && max > 0; i++) {
@@ -533396,7 +725596,7 @@
count++;
max--;
}
-@@ -927,95 +930,78 @@ ath5k_copy_channels(struct ath5k_hw *ah,
+@@ -927,95 +926,78 @@ ath5k_copy_channels(struct ath5k_hw *ah,
return count;
}
@@ -533439,13 +725639,13 @@
- struct ieee80211_hw_mode *modes = sc->modes;
- unsigned int i, max_r, max_c;
- int ret;
+-
+- BUILD_BUG_ON(ARRAY_SIZE(sc->modes) < 3);
+ 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;
@@ -533547,7 +725747,7 @@
}
/*
-@@ -1030,11 +1016,15 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
+@@ -1030,11 +1012,15 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
struct ath5k_hw *ah = sc->ah;
int ret;
@@ -533567,7 +725767,7 @@
/*
* 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)
+@@ -1044,13 +1030,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 */
@@ -533585,7 +725785,7 @@
ath5k_hw_set_txpower_limit(sc->ah, 0);
/*
-@@ -1081,6 +1071,9 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
+@@ -1081,6 +1067,9 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
return 0;
}
@@ -533595,7 +725795,7 @@
static void
ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
{
-@@ -1121,10 +1114,6 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
+@@ -1121,10 +1110,6 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
continue;
}
sc->hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD;
@@ -533606,7 +725806,7 @@
/* 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)
+@@ -1142,6 +1127,12 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
}
sc->curmode = mode;
@@ -533619,7 +725819,7 @@
}
static void
-@@ -1164,6 +1159,72 @@ ath5k_mode_setup(struct ath5k_softc *sc)
+@@ -1164,6 +1155,72 @@ ath5k_mode_setup(struct ath5k_softc *sc)
ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
}
@@ -533692,7 +725892,7 @@
-@@ -1268,7 +1329,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
+@@ -1268,7 +1325,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,
@@ -533702,7 +725902,7 @@
if (ret)
goto err_unmap;
-@@ -1503,8 +1565,7 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+@@ -1503,8 +1561,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) {
@@ -533712,7 +725912,7 @@
ath5k_txbuf_free(sc, bf);
-@@ -1629,20 +1690,20 @@ ath5k_rx_stop(struct ath5k_softc *sc)
+@@ -1629,20 +1686,20 @@ ath5k_rx_stop(struct ath5k_softc *sc)
static unsigned int
ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
@@ -533737,7 +725937,7 @@
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,
+@@ -1655,28 +1712,62 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
static void
@@ -533764,11 +725964,7 @@
+ * 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);
@@ -533790,7 +725986,11 @@
+ *
+ * NOTE: here we assume mactime to be after the frame was
+ * received, not like mac80211 which defines it at the start.
-+ */
+ */
+- 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);
+ if (bc_tstamp > rxs->mactime) {
ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
- "detected HW merge from received beacon\n");
@@ -533811,7 +726011,7 @@
}
}
-@@ -1685,12 +1780,11 @@ static void
+@@ -1685,12 +1776,11 @@ static void
ath5k_tasklet_rx(unsigned long data)
{
struct ieee80211_rx_status rxs = {};
@@ -533825,7 +726025,7 @@
int ret;
int hdrlen;
int pad;
-@@ -1713,7 +1807,7 @@ ath5k_tasklet_rx(unsigned long data)
+@@ -1713,7 +1803,7 @@ ath5k_tasklet_rx(unsigned long data)
if (unlikely(ds->ds_link == bf->daddr)) /* this is the end */
break;
@@ -533834,7 +726034,7 @@
if (unlikely(ret == -EINPROGRESS))
break;
else if (unlikely(ret)) {
-@@ -1722,16 +1816,15 @@ ath5k_tasklet_rx(unsigned long data)
+@@ -1722,16 +1812,15 @@ ath5k_tasklet_rx(unsigned long data)
return;
}
@@ -533855,7 +726055,7 @@
/*
* Decrypt error. If the error occurred
* because there was no hardware key, then
-@@ -1742,30 +1835,29 @@ ath5k_tasklet_rx(unsigned long data)
+@@ -1742,30 +1831,29 @@ ath5k_tasklet_rx(unsigned long data)
*
* XXX do key cache faulting
*/
@@ -533894,7 +726094,7 @@
/*
* the hardware adds a padding to 4 byte boundaries between
-@@ -1787,13 +1879,23 @@ accept:
+@@ -1787,13 +1875,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.
@@ -533922,7 +726122,7 @@
/*
* signal quality:
-@@ -1803,25 +1905,25 @@ accept:
+@@ -1803,25 +1901,25 @@ accept:
/* noise floor in dBm, from the last noise calibration */
rxs.noise = sc->ah->ah_noise_floor;
/* signal level in dBm */
@@ -533955,7 +726155,7 @@
ath5k_led_event(sc, ATH_LED_RX);
next:
list_move_tail(&bf->list, &sc->rxbuf);
-@@ -1840,6 +1942,7 @@ static void
+@@ -1840,6 +1938,7 @@ static void
ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
{
struct ieee80211_tx_status txs = {};
@@ -533963,7 +726163,7 @@
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)
+@@ -1852,7 +1951,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);
@@ -533972,7 +726172,7 @@
if (unlikely(ret == -EINPROGRESS))
break;
else if (unlikely(ret)) {
-@@ -1867,17 +1970,16 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+@@ -1867,17 +1966,16 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
PCI_DMA_TODEVICE);
txs.control = bf->ctl;
@@ -533995,7 +726195,7 @@
}
ieee80211_tx_status(sc->hw, skb, &txs);
-@@ -1958,8 +2060,9 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
+@@ -1958,8 +2056,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),
@@ -534007,7 +726207,7 @@
if (ret)
goto err_unmap;
-@@ -2050,7 +2153,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
+@@ -2050,7 +2149,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,
@@ -534016,7 +726216,7 @@
* 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)
+@@ -2150,7 +2249,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
@@ -534025,7 +726225,7 @@
*
* AP mode is missing.
*/
-@@ -2170,7 +2273,7 @@ ath5k_beacon_config(struct ath5k_softc *sc)
+@@ -2170,7 +2269,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
@@ -534034,7 +726234,7 @@
*/
ath5k_beaconq_config(sc);
-@@ -2211,7 +2314,8 @@ ath5k_init(struct ath5k_softc *sc)
+@@ -2211,7 +2310,8 @@ ath5k_init(struct ath5k_softc *sc)
* be followed by initialization of the appropriate bits
* and then setup of the interrupt mask.
*/
@@ -534044,7 +726244,7 @@
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)
+@@ -2238,7 +2338,8 @@ ath5k_init(struct ath5k_softc *sc)
* Enable interrupts.
*/
sc->imask = AR5K_INT_RX | AR5K_INT_TX | AR5K_INT_RXEOL |
@@ -534054,7 +726254,7 @@
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)
+@@ -2382,8 +2483,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
@@ -534065,7 +726265,7 @@
*/
if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
/* XXX: only if VEOL suppported */
-@@ -2418,7 +2523,11 @@ ath5k_intr(int irq, void *dev_id)
+@@ -2418,7 +2519,11 @@ ath5k_intr(int irq, void *dev_id)
if (status & AR5K_INT_BMISS) {
}
if (status & AR5K_INT_MIB) {
@@ -534078,7 +726278,7 @@
}
}
} while (ath5k_hw_is_intr_pending(ah) && counter-- > 0);
-@@ -2448,7 +2557,8 @@ ath5k_calibrate(unsigned long data)
+@@ -2448,7 +2553,8 @@ ath5k_calibrate(unsigned long data)
struct ath5k_hw *ah = sc->ah;
ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
@@ -534088,7 +726288,7 @@
if (ath5k_hw_get_rf_gain(ah) == AR5K_RFGAIN_NEED_CHANGE) {
/*
-@@ -2460,7 +2570,8 @@ ath5k_calibrate(unsigned long data)
+@@ -2460,7 +2566,8 @@ ath5k_calibrate(unsigned long data)
}
if (ath5k_hw_phy_calibrate(ah, sc->curchan))
ATH5K_ERR(sc, "calibration of channel %u failed\n",
@@ -534098,7 +726298,7 @@
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,
+@@ -2558,7 +2665,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
memmove(skb->data, skb->data+pad, hdrlen);
}
@@ -534107,7 +726307,7 @@
spin_lock_irqsave(&sc->txbuflock, flags);
if (list_empty(&sc->txbuf)) {
-@@ -2597,11 +2708,6 @@ ath5k_reset(struct ieee80211_hw *hw)
+@@ -2597,11 +2704,6 @@ ath5k_reset(struct ieee80211_hw *hw)
int ret;
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
@@ -534119,7 +726319,7 @@
ath5k_hw_set_intr(ah, 0);
ath5k_txq_cleanup(sc);
-@@ -2692,6 +2798,9 @@ end:
+@@ -2692,6 +2794,9 @@ end:
mutex_unlock(&sc->lock);
}
@@ -534129,7 +726329,7 @@
static int
ath5k_config(struct ieee80211_hw *hw,
struct ieee80211_conf *conf)
-@@ -2699,9 +2808,9 @@ ath5k_config(struct ieee80211_hw *hw,
+@@ -2699,9 +2804,9 @@ ath5k_config(struct ieee80211_hw *hw,
struct ath5k_softc *sc = hw->priv;
sc->bintval = conf->beacon_int;
@@ -534141,7 +726341,19 @@
}
static int
-@@ -2869,7 +2978,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+@@ -2800,9 +2905,9 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
+ if (!mclist)
+ break;
+ /* calculate XOR of eight 6-bit values */
+- val = LE_READ_4(mclist->dmi_addr + 0);
++ val = get_unaligned_le32(mclist->dmi_addr + 0);
+ pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
+- val = LE_READ_4(mclist->dmi_addr + 3);
++ val = get_unaligned_le32(mclist->dmi_addr + 3);
+ pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
+ pos &= 0x3f;
+ mfilt[pos / 32] |= (1 << (pos % 32));
+@@ -2869,7 +2974,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
switch(key->alg) {
case ALG_WEP:
@@ -534152,7 +726364,7 @@
case ALG_TKIP:
case ALG_CCMP:
return -EOPNOTSUPP;
-@@ -2909,6 +3020,10 @@ ath5k_get_stats(struct ieee80211_hw *hw,
+@@ -2909,6 +3016,10 @@ ath5k_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats)
{
struct ath5k_softc *sc = hw->priv;
@@ -539183,7 +731395,7 @@
led->dev = NULL;
}
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
-index c73a75b..4bf8a99 100644
+index c73a75b..8c24cd7 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -46,7 +46,9 @@
@@ -539847,6 +732059,15 @@
B43_WARN_ON(dma_reason[4] & B43_DMAIRQ_RX_DONE);
B43_WARN_ON(dma_reason[5] & B43_DMAIRQ_RX_DONE);
+@@ -1915,7 +2171,7 @@ static int b43_write_initvals(struct b43_wldev *dev,
+ goto err_format;
+ array_size -= sizeof(iv->data.d32);
+
+- value = be32_to_cpu(get_unaligned(&iv->data.d32));
++ value = get_unaligned_be32(&iv->data.d32);
+ b43_write32(dev, offset, value);
+
+ iv = (const struct b43_iv *)((const uint8_t *)iv +
@@ -2045,7 +2301,7 @@ static void b43_gpio_cleanup(struct b43_wldev *dev)
}
@@ -542693,7 +734914,7 @@
struct b43legacy_firmware fw;
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
-index 0f7a6e7..ef829ee 100644
+index 0f7a6e7..14a5eea 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);
@@ -543150,6 +735371,15 @@
}
static void handle_irq_ucode_debug(struct b43legacy_wldev *dev)
+@@ -1692,7 +1720,7 @@ static int b43legacy_write_initvals(struct b43legacy_wldev *dev,
+ goto err_format;
+ array_size -= sizeof(iv->data.d32);
+
+- value = be32_to_cpu(get_unaligned(&iv->data.d32));
++ value = get_unaligned_be32(&iv->data.d32);
+ b43legacy_write32(dev, offset, value);
+
+ iv = (const struct b43legacy_iv *)((const uint8_t *)iv +
@@ -2552,14 +2580,16 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
antenna_rx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_rx);
@@ -560956,13 +753186,22 @@
} __attribute__ ((packed));
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
-index b54ff71..c4e631d 100644
+index b54ff71..d5b7a76 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
-@@ -1,7 +1,22 @@
+@@ -1,7 +1,29 @@
++config IWLWIFI
++ bool
++ default n
++
+config IWLCORE
+ tristate "Intel Wireless Wifi Core"
+ depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
++ select IWLWIFI
++ select MAC80211_LEDS if IWLWIFI_LEDS
++ select LEDS_CLASS if IWLWIFI_LEDS
++ select RFKILL if IWLWIFI_RFKILL
++ select RFKILL_INPUT if IWLWIFI_RFKILL
+
+config IWLWIFI_LEDS
+ bool
@@ -560971,8 +753210,6 @@
+config IWLWIFI_RFKILL
+ boolean "IWLWIFI RF kill support"
+ depends on IWLCORE
-+ select RFKILL
-+ select RFKILL_INPUT
+
config IWL4965
tristate "Intel Wireless WiFi 4965AGN"
@@ -560982,7 +753219,7 @@
---help---
Select to build the driver supporting the:
-@@ -24,21 +39,24 @@ config IWL4965
+@@ -24,21 +46,22 @@ config IWL4965
say M here and read <file:Documentation/kbuild/modules.txt>. The
module will be called iwl4965.ko.
@@ -561005,8 +753242,6 @@
+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
@@ -561015,7 +753250,7 @@
config IWL4965_SPECTRUM_MEASUREMENT
bool "Enable Spectrum Measurement in iwl4965 driver"
depends on IWL4965
-@@ -52,7 +70,7 @@ config IWL4965_SENSITIVITY
+@@ -52,7 +75,7 @@ config IWL4965_SENSITIVITY
This option will enable sensitivity calibration for the iwl4965
driver.
@@ -561024,7 +753259,7 @@
bool "Enable full debugging output in iwl4965 driver"
depends on IWL4965
---help---
-@@ -78,6 +96,12 @@ config IWL4965_DEBUG
+@@ -78,10 +101,19 @@ config IWL4965_DEBUG
as the debug information can assist others in helping you resolve
any problems you may encounter.
@@ -561037,7 +753272,14 @@
config IWL3945
tristate "Intel PRO/Wireless 3945ABG/BG Network Connection"
depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
-@@ -104,19 +128,20 @@ config IWL3945
+ select FW_LOADER
++ select IWLWIFI
++ select MAC80211_LEDS if IWL3945_LEDS
++ select LEDS_CLASS if IWL3945_LEDS
+ ---help---
+ Select to build the driver supporting the:
+
+@@ -104,19 +136,18 @@ config IWL3945
say M here and read <file:Documentation/kbuild/modules.txt>. The
module will be called iwl3945.ko.
@@ -561057,8 +753299,6 @@
+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.
+
@@ -562762,7 +755002,7 @@
#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
-index 8d4d91d..598e4ee 100644
+index 8d4d91d..d340683 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -1,6 +1,6 @@
@@ -563101,8 +755341,58 @@
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),
+@@ -279,51 +554,46 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
+ iwl3945_rt->rt_hdr.it_pad = 0;
+
+ /* total header + data */
+- put_unaligned(cpu_to_le16(sizeof(*iwl3945_rt)),
+- &iwl3945_rt->rt_hdr.it_len);
++ put_unaligned_le16(sizeof(*iwl3945_rt), &iwl3945_rt->rt_hdr.it_len);
+
+ /* Indicate all the fields we add to the radiotap header */
+- put_unaligned(cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
+- (1 << IEEE80211_RADIOTAP_FLAGS) |
+- (1 << IEEE80211_RADIOTAP_RATE) |
+- (1 << IEEE80211_RADIOTAP_CHANNEL) |
+- (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
+- (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
+- (1 << IEEE80211_RADIOTAP_ANTENNA)),
+- &iwl3945_rt->rt_hdr.it_present);
++ put_unaligned_le32((1 << IEEE80211_RADIOTAP_TSFT) |
++ (1 << IEEE80211_RADIOTAP_FLAGS) |
++ (1 << IEEE80211_RADIOTAP_RATE) |
++ (1 << IEEE80211_RADIOTAP_CHANNEL) |
++ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
++ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
++ (1 << IEEE80211_RADIOTAP_ANTENNA),
++ &iwl3945_rt->rt_hdr.it_present);
+
+ /* Zero the flags, we'll add to them as we go */
+ iwl3945_rt->rt_flags = 0;
+
+- put_unaligned(cpu_to_le64(tsf), &iwl3945_rt->rt_tsf);
++ put_unaligned_le64(tsf, &iwl3945_rt->rt_tsf);
+
+ iwl3945_rt->rt_dbmsignal = signal;
+ iwl3945_rt->rt_dbmnoise = noise;
+
+ /* Convert the channel frequency and set the flags */
+- put_unaligned(cpu_to_le16(stats->freq), &iwl3945_rt->rt_channelMHz);
++ put_unaligned_le16(stats->freq, &iwl3945_rt->rt_channelMHz);
+ if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
+- put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM |
+- IEEE80211_CHAN_5GHZ),
++ put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ,
+ &iwl3945_rt->rt_chbitmask);
+ else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
+- put_unaligned(cpu_to_le16(IEEE80211_CHAN_CCK |
+- IEEE80211_CHAN_2GHZ),
++ put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ,
+ &iwl3945_rt->rt_chbitmask);
+ else /* 802.11g */
+- put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM |
+- IEEE80211_CHAN_2GHZ),
++ put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ,
&iwl3945_rt->rt_chbitmask);
- rate = iwl3945_rate_index_from_plcp(rate);
@@ -563119,7 +755409,7 @@
/* 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,
+@@ -368,6 +638,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);
@@ -563130,7 +755420,7 @@
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,
+@@ -377,25 +651,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)
{
@@ -563171,7 +755461,7 @@
if ((unlikely(rx_stats->phy_count > 20))) {
IWL_DEBUG_DROP
-@@ -411,12 +692,12 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
+@@ -411,12 +688,12 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
}
if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
@@ -563186,7 +755476,7 @@
/* 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,
+@@ -432,51 +709,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.
@@ -563255,7 +755545,7 @@
}
switch (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FTYPE) {
-@@ -563,7 +840,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
+@@ -563,7 +836,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
}
}
@@ -563264,7 +755554,7 @@
break;
case IEEE80211_FTYPE_CTL:
-@@ -580,7 +857,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
+@@ -580,7 +853,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
print_mac(mac2, header->addr2),
print_mac(mac3, header->addr3));
else
@@ -563273,7 +755563,7 @@
break;
}
}
-@@ -689,7 +966,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
+@@ -689,7 +962,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;
@@ -563282,7 +755572,7 @@
u16 rate_mask;
int rate;
u8 rts_retry_limit;
-@@ -709,7 +986,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
+@@ -709,7 +982,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) &&
@@ -563291,7 +755581,7 @@
(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)
+@@ -996,19 +1269,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) {
@@ -563316,7 +755606,7 @@
} else
IWL_DEBUG_INFO("SKU OP mode is basic\n");
-@@ -1016,24 +1293,24 @@ int iwl3945_hw_nic_init(struct iwl3945_priv *priv)
+@@ -1016,24 +1289,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,
@@ -563345,7 +755635,7 @@
}
spin_unlock_irqrestore(&priv->lock, flags);
-@@ -1552,14 +1829,14 @@ int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv)
+@@ -1552,14 +1825,14 @@ int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv)
.channel = priv->active_rxon.channel,
};
@@ -563363,7 +755653,7 @@
return -EINVAL;
}
-@@ -2241,8 +2518,8 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
+@@ -2241,8 +2514,8 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
table[index].next_rate_index = iwl3945_rates[prev_index].table_rs_index;
}
@@ -563374,7 +755664,7 @@
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)
+@@ -2257,8 +2530,8 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
break;
@@ -563385,7 +755675,7 @@
/* 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)
+@@ -2269,7 +2542,7 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
break;
default:
@@ -563394,7 +755684,7 @@
break;
}
-@@ -2303,7 +2580,6 @@ int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv)
+@@ -2303,7 +2576,6 @@ int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv)
return -ENOMEM;
}
@@ -563402,7 +755692,7 @@
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)
+@@ -2311,6 +2583,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;
@@ -563411,7 +755701,7 @@
return 0;
}
-@@ -2323,7 +2601,7 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv,
+@@ -2323,7 +2597,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));
@@ -563420,7 +755710,7 @@
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,
+@@ -2350,6 +2624,7 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv,
void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv)
{
@@ -563428,7 +755718,7 @@
priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx;
}
-@@ -2364,9 +2643,25 @@ void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv)
+@@ -2364,9 +2639,25 @@ void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv)
cancel_delayed_work(&priv->thermal_periodic);
}
@@ -590038,7 +782328,7 @@
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
+index 69f94c9..1a409fc 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -4,22 +4,14 @@
@@ -590730,7 +783020,7 @@
{
struct ieeetypes_fhparamset *pFH;
struct ieeetypes_dsparamset *pDS;
-@@ -702,9 +513,9 @@ static int lbs_process_bss(struct bss_descriptor *bss,
+@@ -702,16 +513,16 @@ static int lbs_process_bss(struct bss_descriptor *bss,
struct ieeetypes_ibssparamset *pibss;
DECLARE_MAC_BUF(mac);
struct ieeetypes_countryinfoset *pcountryinfo;
@@ -590743,6 +783033,14 @@
int ret;
lbs_deb_enter(LBS_DEB_SCAN);
+
+ if (*bytesleft >= sizeof(beaconsize)) {
+ /* Extract & convert beacon size from the command buffer */
+- beaconsize = le16_to_cpu(get_unaligned((__le16 *)*pbeaconinfo));
++ beaconsize = get_unaligned_le16(*pbeaconinfo);
+ *bytesleft -= sizeof(beaconsize);
+ *pbeaconinfo += sizeof(beaconsize);
+ }
@@ -776,12 +587,11 @@ static int lbs_process_bss(struct bss_descriptor *bss,
/* process variable IE */
@@ -613244,10 +805542,60 @@
-
#endif /* RTL818X_H */
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
-index 88efe1b..bced3fe 100644
+index 88efe1b..5dd23c9 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)
+@@ -768,41 +768,17 @@ static __u8 *UnStuffData(__u8 * src, __u8 * end, __u8 * dst,
+ /* General routines for STRIP */
+
+ /*
+- * get_baud returns the current baud rate, as one of the constants defined in
+- * termbits.h
+- * If the user has issued a baud rate override using the 'setserial' command
+- * and the logical current rate is set to 38.4, then the true baud rate
+- * currently in effect (57.6 or 115.2) is returned.
+- */
+-static unsigned int get_baud(struct tty_struct *tty)
+-{
+- if (!tty || !tty->termios)
+- return (0);
+- if ((tty->termios->c_cflag & CBAUD) == B38400 && tty->driver_data) {
+- struct async_struct *info =
+- (struct async_struct *) tty->driver_data;
+- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+- return (B57600);
+- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+- return (B115200);
+- }
+- return (tty->termios->c_cflag & CBAUD);
+-}
+-
+-/*
+ * set_baud sets the baud rate to the rate defined by baudcode
+- * Note: The rate B38400 should be avoided, because the user may have
+- * issued a 'setserial' speed override to map that to a different speed.
+- * We could achieve a true rate of 38400 if we needed to by cancelling
+- * any user speed override that is in place, but that might annoy the
+- * user, so it is simplest to just avoid using 38400.
+ */
+-static void set_baud(struct tty_struct *tty, unsigned int baudcode)
++static void set_baud(struct tty_struct *tty, speed_t baudrate)
+ {
+- struct ktermios old_termios = *(tty->termios);
+- tty->termios->c_cflag &= ~CBAUD; /* Clear the old baud setting */
+- tty->termios->c_cflag |= baudcode; /* Set the new baud setting */
+- tty->driver->set_termios(tty, &old_termios);
++ struct ktermios old_termios;
++
++ mutex_lock(&tty->termios_mutex);
++ old_termios =*(tty->termios);
++ tty_encode_baud_rate(tty, baudrate, baudrate);
++ tty->ops->set_termios(tty, &old_termios);
++ mutex_unlock(&tty->termios_mutex);
+ }
+
+ /*
+@@ -962,12 +938,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)
{
@@ -613263,6 +805611,88 @@
++i;
}
return NULL;
+@@ -1217,7 +1193,7 @@ static void ResetRadio(struct strip *strip_info)
+ strip_info->watchdog_doreset = jiffies + 1 * HZ;
+
+ /* If the user has selected a baud rate above 38.4 see what magic we have to do */
+- if (strip_info->user_baud > B38400) {
++ if (strip_info->user_baud > 38400) {
+ /*
+ * Subtle stuff: Pay attention :-)
+ * If the serial port is currently at the user's selected (>38.4) rate,
+@@ -1227,17 +1203,17 @@ static void ResetRadio(struct strip *strip_info)
+ * issued the ATS304 command last time through, so this time we restore
+ * the user's selected rate and issue the normal starmode reset string.
+ */
+- if (strip_info->user_baud == get_baud(tty)) {
++ if (strip_info->user_baud == tty_get_baud_rate(tty)) {
+ static const char b0[] = "ate0q1s304=57600\r";
+ static const char b1[] = "ate0q1s304=115200\r";
+ static const StringDescriptor baudstring[2] =
+ { {b0, sizeof(b0) - 1}
+ , {b1, sizeof(b1) - 1}
+ };
+- set_baud(tty, B19200);
+- if (strip_info->user_baud == B57600)
++ set_baud(tty, 19200);
++ if (strip_info->user_baud == 57600)
+ s = baudstring[0];
+- else if (strip_info->user_baud == B115200)
++ else if (strip_info->user_baud == 115200)
+ s = baudstring[1];
+ else
+ s = baudstring[1]; /* For now */
+@@ -1245,7 +1221,7 @@ static void ResetRadio(struct strip *strip_info)
+ set_baud(tty, strip_info->user_baud);
+ }
+
+- tty->driver->write(tty, s.string, s.length);
++ tty->ops->write(tty, s.string, s.length);
+ #ifdef EXT_COUNTERS
+ strip_info->tx_ebytes += s.length;
+ #endif
+@@ -1267,7 +1243,7 @@ static void strip_write_some_more(struct tty_struct *tty)
+
+ if (strip_info->tx_left > 0) {
+ int num_written =
+- tty->driver->write(tty, strip_info->tx_head,
++ tty->ops->write(tty, strip_info->tx_head,
+ strip_info->tx_left);
+ strip_info->tx_left -= num_written;
+ strip_info->tx_head += num_written;
+@@ -2457,7 +2433,7 @@ static int strip_open_low(struct net_device *dev)
+ strip_info->working = FALSE;
+ strip_info->firmware_level = NoStructure;
+ strip_info->next_command = CompatibilityCommand;
+- strip_info->user_baud = get_baud(strip_info->tty);
++ strip_info->user_baud = tty_get_baud_rate(strip_info->tty);
+
+ printk(KERN_INFO "%s: Initializing Radio.\n",
+ strip_info->dev->name);
+@@ -2632,6 +2608,13 @@ static int strip_open(struct tty_struct *tty)
+ return -EEXIST;
+
+ /*
++ * We need a write method.
++ */
++
++ if (tty->ops->write == NULL)
++ return -EOPNOTSUPP;
++
++ /*
+ * OK. Find a free STRIP channel to use.
+ */
+ if ((strip_info = strip_alloc()) == NULL)
+@@ -2652,8 +2635,7 @@ static int strip_open(struct tty_struct *tty)
+ tty->disc_data = strip_info;
+ tty->receive_room = 65536;
+
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ tty_driver_flush_buffer(tty);
+
+ /*
+ * Restore default settings
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
@@ -614085,7 +806515,7 @@
/* 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
+index 7942b15..5316074 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);
@@ -614124,6 +806554,20 @@
out:
spin_unlock(&intr->lock);
}
+@@ -538,11 +545,11 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
+ * be padded. Unaligned access might also happen if the length_info
+ * structure is not present.
+ */
+- if (get_unaligned(&length_info->tag) == cpu_to_le16(RX_LENGTH_INFO_TAG))
++ if (get_unaligned_le16(&length_info->tag) == RX_LENGTH_INFO_TAG)
+ {
+ unsigned int l, k, n;
+ for (i = 0, l = 0;; i++) {
+- k = le16_to_cpu(get_unaligned(&length_info->length[i]));
++ k = get_unaligned_le16(&length_info->length[i]);
+ if (k == 0)
+ return;
+ n = l+k;
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 7483d45..e62018a 100644
--- a/drivers/net/xen-netfront.c
@@ -614135,7 +806579,7 @@
+MODULE_ALIAS("xen:vif");
+MODULE_ALIAS("xennet");
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
-index fe6ff3e..2464072 100644
+index fe6ff3e..57e1f49 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -770,14 +770,14 @@ static void yellowfin_init_ring(struct net_device *dev)
@@ -614155,6 +806599,95 @@
} else {
/* Symbios chips write only tx_errs word. */
yp->tx_ring[j].dbdma_cmd =
+@@ -1062,7 +1062,7 @@ static int yellowfin_rx(struct net_device *dev)
+ buf_addr = rx_skb->data;
+ data_size = (le32_to_cpu(desc->dbdma_cmd) -
+ le32_to_cpu(desc->result_status)) & 0xffff;
+- frame_status = le16_to_cpu(get_unaligned((__le16*)&(buf_addr[data_size - 2])));
++ frame_status = get_unaligned_le16(&(buf_addr[data_size - 2]));
+ if (yellowfin_debug > 4)
+ printk(KERN_DEBUG " yellowfin_rx() status was %4.4x.\n",
+ frame_status);
+diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c
+index e07492b..208dd12 100644
+--- a/drivers/nubus/proc.c
++++ b/drivers/nubus/proc.c
+@@ -21,6 +21,7 @@
+ #include <linux/kernel.h>
+ #include <linux/nubus.h>
+ #include <linux/proc_fs.h>
++#include <linux/seq_file.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+
+@@ -28,38 +29,36 @@
+ #include <asm/byteorder.h>
+
+ static int
+-get_nubus_dev_info(char *buf, char **start, off_t pos, int count)
++nubus_devices_proc_show(struct seq_file *m, void *v)
+ {
+ struct nubus_dev *dev = nubus_devices;
+- off_t at = 0;
+- int len, cnt;
+
+- cnt = 0;
+- while (dev && count > cnt) {
+- len = sprintf(buf, "%x\t%04x %04x %04x %04x",
++ while (dev) {
++ seq_printf(m, "%x\t%04x %04x %04x %04x",
+ dev->board->slot,
+ dev->category,
+ dev->type,
+ dev->dr_sw,
+ dev->dr_hw);
+- len += sprintf(buf+len,
+- "\t%08lx",
+- dev->board->slot_addr);
+- buf[len++] = '\n';
+- at += len;
+- if (at >= pos) {
+- if (!*start) {
+- *start = buf + (pos - (at - len));
+- cnt = at - pos;
+- } else
+- cnt += len;
+- buf += len;
+- }
++ seq_printf(m, "\t%08lx\n", dev->board->slot_addr);
+ dev = dev->next;
+ }
+- return (count > cnt) ? cnt : count;
++ return 0;
++}
++
++static int nubus_devices_proc_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, nubus_devices_proc_show, NULL);
+ }
+
++static const struct file_operations nubus_devices_proc_fops = {
++ .owner = THIS_MODULE,
++ .open = nubus_devices_proc_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
+ static struct proc_dir_entry *proc_bus_nubus_dir;
+
+ static void nubus_proc_subdir(struct nubus_dev* dev,
+@@ -171,8 +170,7 @@ void __init nubus_proc_init(void)
+ {
+ if (!MACH_IS_MAC)
+ return;
+- proc_bus_nubus_dir = proc_mkdir("nubus", proc_bus);
+- create_proc_info_entry("devices", 0, proc_bus_nubus_dir,
+- get_nubus_dev_info);
++ proc_bus_nubus_dir = proc_mkdir("bus/nubus", NULL);
++ proc_create("devices", 0, proc_bus_nubus_dir, &nubus_devices_proc_fops);
+ proc_bus_nubus_add_devices();
+ }
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index c03072b..3a7a11a 100644
--- a/drivers/of/Kconfig
@@ -614593,6 +807126,168 @@
+EXPORT_SYMBOL(of_register_i2c_devices);
+
+MODULE_LICENSE("GPL");
+diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
+index b07ba2a..9304c45 100644
+--- a/drivers/oprofile/buffer_sync.c
++++ b/drivers/oprofile/buffer_sync.c
+@@ -491,7 +491,7 @@ typedef enum {
+ */
+ void sync_buffer(int cpu)
+ {
+- struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[cpu];
++ struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu);
+ struct mm_struct *mm = NULL;
+ struct task_struct * new;
+ unsigned long cookie = 0;
+diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
+index c93d3d2..efcbf4b 100644
+--- a/drivers/oprofile/cpu_buffer.c
++++ b/drivers/oprofile/cpu_buffer.c
+@@ -27,7 +27,7 @@
+ #include "buffer_sync.h"
+ #include "oprof.h"
+
+-struct oprofile_cpu_buffer cpu_buffer[NR_CPUS] __cacheline_aligned;
++DEFINE_PER_CPU_SHARED_ALIGNED(struct oprofile_cpu_buffer, cpu_buffer);
+
+ static void wq_sync_buffer(struct work_struct *work);
+
+@@ -39,7 +39,7 @@ void free_cpu_buffers(void)
+ int i;
+
+ for_each_online_cpu(i)
+- vfree(cpu_buffer[i].buffer);
++ vfree(per_cpu(cpu_buffer, i).buffer);
+ }
+
+ int alloc_cpu_buffers(void)
+@@ -49,7 +49,7 @@ int alloc_cpu_buffers(void)
+ unsigned long buffer_size = fs_cpu_buffer_size;
+
+ for_each_online_cpu(i) {
+- struct oprofile_cpu_buffer * b = &cpu_buffer[i];
++ struct oprofile_cpu_buffer *b = &per_cpu(cpu_buffer, i);
+
+ b->buffer = vmalloc_node(sizeof(struct op_sample) * buffer_size,
+ cpu_to_node(i));
+@@ -83,7 +83,7 @@ void start_cpu_work(void)
+ work_enabled = 1;
+
+ for_each_online_cpu(i) {
+- struct oprofile_cpu_buffer * b = &cpu_buffer[i];
++ struct oprofile_cpu_buffer *b = &per_cpu(cpu_buffer, i);
+
+ /*
+ * Spread the work by 1 jiffy per cpu so they dont all
+@@ -100,7 +100,7 @@ void end_cpu_work(void)
+ work_enabled = 0;
+
+ for_each_online_cpu(i) {
+- struct oprofile_cpu_buffer * b = &cpu_buffer[i];
++ struct oprofile_cpu_buffer *b = &per_cpu(cpu_buffer, i);
+
+ cancel_delayed_work(&b->work);
+ }
+@@ -227,7 +227,7 @@ static void oprofile_end_trace(struct oprofile_cpu_buffer * cpu_buf)
+ void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
+ unsigned long event, int is_kernel)
+ {
+- struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()];
++ struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
+
+ if (!backtrace_depth) {
+ log_sample(cpu_buf, pc, is_kernel, event);
+@@ -254,13 +254,13 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
+
+ void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event)
+ {
+- struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()];
++ struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
+ log_sample(cpu_buf, pc, is_kernel, event);
+ }
+
+ void oprofile_add_trace(unsigned long pc)
+ {
+- struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()];
++ struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
+
+ if (!cpu_buf->tracing)
+ return;
+diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h
+index c66c025..1358817 100644
+--- a/drivers/oprofile/cpu_buffer.h
++++ b/drivers/oprofile/cpu_buffer.h
+@@ -14,6 +14,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/workqueue.h>
+ #include <linux/cache.h>
++#include <linux/sched.h>
+
+ struct task_struct;
+
+@@ -47,7 +48,7 @@ struct oprofile_cpu_buffer {
+ struct delayed_work work;
+ } ____cacheline_aligned;
+
+-extern struct oprofile_cpu_buffer cpu_buffer[];
++DECLARE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer);
+
+ void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf);
+
+diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c
+index d1f6d77..f99b28e 100644
+--- a/drivers/oprofile/oprofile_stats.c
++++ b/drivers/oprofile/oprofile_stats.c
+@@ -23,7 +23,7 @@ void oprofile_reset_stats(void)
+ int i;
+
+ for_each_possible_cpu(i) {
+- cpu_buf = &cpu_buffer[i];
++ cpu_buf = &per_cpu(cpu_buffer, i);
+ cpu_buf->sample_received = 0;
+ cpu_buf->sample_lost_overflow = 0;
+ cpu_buf->backtrace_aborted = 0;
+@@ -49,7 +49,7 @@ void oprofile_create_stats_files(struct super_block * sb, struct dentry * root)
+ return;
+
+ for_each_possible_cpu(i) {
+- cpu_buf = &cpu_buffer[i];
++ cpu_buf = &per_cpu(cpu_buffer, i);
+ snprintf(buf, 10, "cpu%d", i);
+ cpudir = oprofilefs_mkdir(sb, dir, buf);
+
+diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
+index 62db3c3..07d2a8d 100644
+--- a/drivers/parisc/ccio-dma.c
++++ b/drivers/parisc/ccio-dma.c
+@@ -1551,8 +1551,7 @@ static int __init ccio_probe(struct parisc_device *dev)
+ {
+ int i;
+ struct ioc *ioc, **ioc_p = &ioc_list;
+- struct proc_dir_entry *info_entry, *bitmap_entry;
+-
++
+ ioc = kzalloc(sizeof(struct ioc), GFP_KERNEL);
+ if (ioc == NULL) {
+ printk(KERN_ERR MODULE_NAME ": memory allocation failure\n");
+@@ -1580,13 +1579,10 @@ static int __init ccio_probe(struct parisc_device *dev)
+ HBA_DATA(dev->dev.platform_data)->iommu = ioc;
+
+ if (ioc_count == 0) {
+- info_entry = create_proc_entry(MODULE_NAME, 0, proc_runway_root);
+- if (info_entry)
+- info_entry->proc_fops = &ccio_proc_info_fops;
+-
+- bitmap_entry = create_proc_entry(MODULE_NAME"-bitmap", 0, proc_runway_root);
+- if (bitmap_entry)
+- bitmap_entry->proc_fops = &ccio_proc_bitmap_fops;
++ proc_create(MODULE_NAME, 0, proc_runway_root,
++ &ccio_proc_info_fops);
++ proc_create(MODULE_NAME"-bitmap", 0, proc_runway_root,
++ &ccio_proc_bitmap_fops);
+ }
+
+ ioc_count++;
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 03c763c..d9c6322 100644
--- a/drivers/parisc/dino.c
@@ -614605,6 +807300,38 @@
list_del(&dev->bus_list);
}
+diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
+index 8c4d2c1..afc849b 100644
+--- a/drivers/parisc/sba_iommu.c
++++ b/drivers/parisc/sba_iommu.c
+@@ -1895,7 +1895,9 @@ sba_driver_callback(struct parisc_device *dev)
+ int i;
+ char *version;
+ void __iomem *sba_addr = ioremap_nocache(dev->hpa.start, SBA_FUNC_SIZE);
+- struct proc_dir_entry *info_entry, *bitmap_entry, *root;
++#ifdef CONFIG_PROC_FS
++ struct proc_dir_entry *root;
++#endif
+
+ sba_dump_ranges(sba_addr);
+
+@@ -1973,14 +1975,8 @@ sba_driver_callback(struct parisc_device *dev)
+ break;
+ }
+
+- info_entry = create_proc_entry("sba_iommu", 0, root);
+- bitmap_entry = create_proc_entry("sba_iommu-bitmap", 0, root);
+-
+- if (info_entry)
+- info_entry->proc_fops = &sba_proc_fops;
+-
+- if (bitmap_entry)
+- bitmap_entry->proc_fops = &sba_proc_bitmap_fops;
++ proc_create("sba_iommu", 0, root, &sba_proc_fops);
++ proc_create("sba_iommu-bitmap", 0, root, &sba_proc_bitmap_fops);
+ #endif
+
+ parisc_vmerge_boundary = IOVP_SIZE;
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index b7bcdcc..209b4a4 100644
--- a/drivers/parport/Kconfig
@@ -614618,6 +807345,104 @@
---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/parport/ieee1284.c b/drivers/parport/ieee1284.c
+index 54a6ef7..0338b09 100644
+--- a/drivers/parport/ieee1284.c
++++ b/drivers/parport/ieee1284.c
+@@ -76,7 +76,7 @@ int parport_wait_event (struct parport *port, signed long timeout)
+ semaphore. */
+ return 1;
+
+- init_timer (&timer);
++ init_timer_on_stack(&timer);
+ timer.expires = jiffies + timeout;
+ timer.function = timeout_waiting_on_port;
+ port_from_cookie[port->number % PARPORT_MAX] = port;
+@@ -88,6 +88,8 @@ int parport_wait_event (struct parport *port, signed long timeout)
+ /* Timed out. */
+ ret = 1;
+
++ destroy_timer_on_stack(&timer);
++
+ return ret;
+ }
+
+diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
+index 0e77ae2..e6a7e84 100644
+--- a/drivers/parport/parport_gsc.c
++++ b/drivers/parport/parport_gsc.c
+@@ -365,11 +365,11 @@ static int __devinit parport_init_chip(struct parisc_device *dev)
+ if (boot_cpu_data.cpu_type > pcxt && !pdc_add_valid(port+4)) {
+
+ /* Initialize bidirectional-mode (0x10) & data-tranfer-mode #1 (0x20) */
+- printk("%s: initialize bidirectional-mode.\n", __FUNCTION__);
++ printk("%s: initialize bidirectional-mode.\n", __func__);
+ parport_writeb ( (0x10 + 0x20), port + 4);
+
+ } else {
+- printk("%s: enhanced parport-modes not supported.\n", __FUNCTION__);
++ printk("%s: enhanced parport-modes not supported.\n", __func__);
+ }
+
+ p = parport_gsc_probe_port(port, 0, dev->irq,
+diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
+index a858089..e0c2a45 100644
+--- a/drivers/parport/parport_pc.c
++++ b/drivers/parport/parport_pc.c
+@@ -1415,7 +1415,7 @@ static void __devinit winbond_check(int io, int key)
+ {
+ int devid,devrev,oldid,x_devid,x_devrev,x_oldid;
+
+- if (!request_region(io, 3, __FUNCTION__))
++ if (!request_region(io, 3, __func__))
+ return;
+
+ /* First probe without key */
+@@ -1449,7 +1449,7 @@ static void __devinit winbond_check2(int io,int key)
+ {
+ int devid,devrev,oldid,x_devid,x_devrev,x_oldid;
+
+- if (!request_region(io, 3, __FUNCTION__))
++ if (!request_region(io, 3, __func__))
+ return;
+
+ /* First probe without the key */
+@@ -1482,7 +1482,7 @@ static void __devinit smsc_check(int io, int key)
+ {
+ int id,rev,oldid,oldrev,x_id,x_rev,x_oldid,x_oldrev;
+
+- if (!request_region(io, 3, __FUNCTION__))
++ if (!request_region(io, 3, __func__))
+ return;
+
+ /* First probe without the key */
+@@ -1547,7 +1547,7 @@ static void __devinit detect_and_report_it87(void)
+ u8 r;
+ if (verbose_probing)
+ printk(KERN_DEBUG "IT8705 Super-IO detection, now testing port 2E ...\n");
+- if (!request_region(0x2e, 1, __FUNCTION__))
++ if (!request_region(0x2e, 1, __func__))
+ return;
+ outb(0x87, 0x2e);
+ outb(0x01, 0x2e);
+@@ -3082,6 +3082,7 @@ static struct pci_driver parport_pc_pci_driver;
+ static int __init parport_pc_init_superio(int autoirq, int autodma) {return 0;}
+ #endif /* CONFIG_PCI */
+
++#ifdef CONFIG_PNP
+
+ static const struct pnp_device_id parport_pc_pnp_tbl[] = {
+ /* Standard LPT Printer Port */
+@@ -3148,6 +3149,9 @@ static struct pnp_driver parport_pc_pnp_driver = {
+ .remove = parport_pc_pnp_remove,
+ };
+
++#else
++static struct pnp_driver parport_pc_pnp_driver;
++#endif /* CONFIG_PNP */
+
+ static int __devinit parport_pc_platform_probe(struct platform_device *pdev)
+ {
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index fc405f0..ec8f700 100644
--- a/drivers/pci/access.c
@@ -616855,10 +809680,44 @@
#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
+index ca656b2..8264a76 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)
+@@ -93,11 +93,10 @@ struct controller {
+ u8 slot_device_offset;
+ u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */
+ u8 slot_bus; /* Bus where the slots handled by this controller sit */
+- u8 ctrlcap;
++ u32 slot_cap;
+ u8 cap_base;
+ struct timer_list poll_timer;
+ volatile int cmd_busy;
+- spinlock_t lock;
+ };
+
+ #define INT_BUTTON_IGNORE 0
+@@ -137,13 +136,13 @@ struct controller {
+ #define HP_SUPR_RM_SUP 0x00000020
+ #define EMI_PRSN 0x00020000
+
+-#define ATTN_BUTTN(cap) (cap & ATTN_BUTTN_PRSN)
+-#define POWER_CTRL(cap) (cap & PWR_CTRL_PRSN)
+-#define MRL_SENS(cap) (cap & MRL_SENS_PRSN)
+-#define ATTN_LED(cap) (cap & ATTN_LED_PRSN)
+-#define PWR_LED(cap) (cap & PWR_LED_PRSN)
+-#define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP)
+-#define EMI(cap) (cap & EMI_PRSN)
++#define ATTN_BUTTN(ctrl) ((ctrl)->slot_cap & ATTN_BUTTN_PRSN)
++#define POWER_CTRL(ctrl) ((ctrl)->slot_cap & PWR_CTRL_PRSN)
++#define MRL_SENS(ctrl) ((ctrl)->slot_cap & MRL_SENS_PRSN)
++#define ATTN_LED(ctrl) ((ctrl)->slot_cap & ATTN_LED_PRSN)
++#define PWR_LED(ctrl) ((ctrl)->slot_cap & PWR_LED_PRSN)
++#define HP_SUPR_RM(ctrl) ((ctrl)->slot_cap & HP_SUPR_RM_SUP)
++#define EMI(ctrl) ((ctrl)->slot_cap & EMI_PRSN)
+
+ extern int pciehp_sysfs_enable_slot(struct slot *slot);
+ extern int pciehp_sysfs_disable_slot(struct slot *slot);
+@@ -168,7 +167,7 @@ static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
return slot;
}
@@ -616868,10 +809727,31 @@
}
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
-index 5fa4ba0..aee19f0 100644
+index 5fa4ba0..43d8ddb 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)
+@@ -41,6 +41,7 @@ int pciehp_debug;
+ int pciehp_poll_mode;
+ int pciehp_poll_time;
+ int pciehp_force;
++int pciehp_slot_with_bus;
+ struct workqueue_struct *pciehp_wq;
+
+ #define DRIVER_VERSION "0.4"
+@@ -55,10 +56,12 @@ module_param(pciehp_debug, bool, 0644);
+ module_param(pciehp_poll_mode, bool, 0644);
+ module_param(pciehp_poll_time, int, 0644);
+ module_param(pciehp_force, bool, 0644);
++module_param(pciehp_slot_with_bus, bool, 0644);
+ MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not");
+ MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not");
+ MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds");
+ MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing");
++MODULE_PARM_DESC(pciehp_slot_with_bus, "Use bus number in the slot name");
+
+ #define PCIE_MODULE_NAME "pciehp"
+
+@@ -184,7 +187,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
@@ -616880,7 +809760,40 @@
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)
+@@ -193,8 +196,12 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
+
+ static void make_slot_name(struct slot *slot)
+ {
+- snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
+- slot->bus, slot->number);
++ if (pciehp_slot_with_bus)
++ snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
++ slot->bus, slot->number);
++ else
++ snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d",
++ slot->number);
+ }
+
+ static int init_slots(struct controller *ctrl)
+@@ -251,7 +258,7 @@ static int init_slots(struct controller *ctrl)
+ goto error_info;
+ }
+ /* create additional sysfs entries */
+- if (EMI(ctrl->ctrlcap)) {
++ if (EMI(ctrl)) {
+ retval = sysfs_create_file(&hotplug_slot->kobj,
+ &hotplug_slot_attr_lock.attr);
+ if (retval) {
+@@ -284,7 +291,7 @@ static void cleanup_slots(struct controller *ctrl)
+ list_for_each_safe(tmp, next, &ctrl->slot_list) {
+ slot = list_entry(tmp, struct slot, slot_list);
+ list_del(&slot->slot_list);
+- if (EMI(ctrl->ctrlcap))
++ if (EMI(ctrl))
+ sysfs_remove_file(&slot->hotplug_slot->kobj,
+ &hotplug_slot_attr_lock.attr);
+ cancel_delayed_work(&slot->work);
+@@ -301,11 +308,11 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
{
struct slot *slot = hotplug_slot->private;
@@ -616889,7 +809802,12 @@
hotplug_slot->info->attention_status = status;
-@@ -316,7 +316,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
+- if (ATTN_LED(slot->ctrl->ctrlcap))
++ if (ATTN_LED(slot->ctrl))
+ slot->hpc_ops->set_attention_status(slot, status);
+
+ return 0;
+@@ -316,7 +323,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
@@ -616898,7 +809816,7 @@
return pciehp_sysfs_enable_slot(slot);
}
-@@ -326,7 +326,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
+@@ -326,7 +333,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
@@ -616907,7 +809825,7 @@
return pciehp_sysfs_disable_slot(slot);
}
-@@ -336,7 +336,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
+@@ -336,7 +343,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private;
int retval;
@@ -616916,7 +809834,7 @@
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)
+@@ -350,7 +357,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private;
int retval;
@@ -616925,7 +809843,7 @@
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)
+@@ -364,7 +371,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private;
int retval;
@@ -616934,7 +809852,7 @@
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)
+@@ -378,7 +385,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private;
int retval;
@@ -616943,7 +809861,7 @@
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)
+@@ -392,7 +399,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;
@@ -616952,7 +809870,7 @@
*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
+@@ -404,7 +411,7 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
struct slot *slot = hotplug_slot->private;
int retval;
@@ -616961,7 +809879,7 @@
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
+@@ -418,7 +425,7 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
struct slot *slot = hotplug_slot->private;
int retval;
@@ -616970,7 +809888,7 @@
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_
+@@ -437,7 +444,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
if (!ctrl) {
@@ -616979,7 +809897,7 @@
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_
+@@ -454,7 +461,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",
@@ -616988,7 +809906,16 @@
PCI_FUNC(pdev->devfn), pdev->irq);
/* Setup the slot information structures */
-@@ -503,13 +503,13 @@ static void pciehp_remove (struct pcie_device *dev)
+@@ -472,7 +479,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
+ if (rc) /* -ENODEV: shouldn't happen, but deal with it */
+ value = 0;
+ }
+- if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
++ if ((POWER_CTRL(ctrl)) && !value) {
+ rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
+ if (rc)
+ goto err_out_free_ctrl_slot;
+@@ -503,13 +510,13 @@ static void pciehp_remove (struct pcie_device *dev)
#ifdef CONFIG_PM
static int pciehp_suspend (struct pcie_device *dev, pm_message_t state)
{
@@ -617004,7 +809931,7 @@
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)
+@@ -563,7 +570,7 @@ static int __init pcied_init(void)
dbg("pcie_port_service_register = %d\n", retval);
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
if (retval)
@@ -617014,11 +809941,15 @@
}
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
-index b23061c..0c481f7 100644
+index b23061c..0a7aa62 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)) {
+@@ -178,21 +178,21 @@ u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
+ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
+ {
+ /* turn off slot, turn on Amber LED, turn off Green LED if supported*/
+- if (POWER_CTRL(ctrl->ctrlcap)) {
++ if (POWER_CTRL(ctrl)) {
if (pslot->hpc_ops->power_off_slot(pslot)) {
err("%s: Issue of Slot Power Off command failed\n",
- __FUNCTION__);
@@ -617026,8 +809957,13 @@
return;
}
}
-@@ -192,7 +192,7 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
- if (ATTN_LED(ctrl->ctrlcap)) {
+
+- if (PWR_LED(ctrl->ctrlcap))
++ if (PWR_LED(ctrl))
+ pslot->hpc_ops->green_led_off(pslot);
+
+- if (ATTN_LED(ctrl->ctrlcap)) {
++ if (ATTN_LED(ctrl)) {
if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
err("%s: Issue of Set Attention Led command failed\n",
- __FUNCTION__);
@@ -617035,7 +809971,7 @@
return;
}
}
-@@ -211,7 +211,7 @@ static int board_added(struct slot *p_slot)
+@@ -211,17 +211,17 @@ 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",
@@ -617043,7 +809979,19 @@
+ __func__, p_slot->device,
ctrl->slot_device_offset, p_slot->hp_slot);
- if (POWER_CTRL(ctrl->ctrlcap)) {
+- if (POWER_CTRL(ctrl->ctrlcap)) {
++ if (POWER_CTRL(ctrl)) {
+ /* Power on slot */
+ retval = p_slot->hpc_ops->power_on_slot(p_slot);
+ if (retval)
+ return retval;
+ }
+
+- if (PWR_LED(ctrl->ctrlcap))
++ if (PWR_LED(ctrl))
+ p_slot->hpc_ops->green_led_blink(p_slot);
+
+ /* Wait for ~1 second */
@@ -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);
@@ -617061,14 +810009,24 @@
retval = POWER_FAILURE;
goto err_exit;
}
-@@ -277,14 +277,14 @@ static int remove_board(struct slot *p_slot)
+@@ -254,7 +254,7 @@ static int board_added(struct slot *p_slot)
+ */
+ if (pcie_mch_quirk)
+ pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
+- if (PWR_LED(ctrl->ctrlcap))
++ if (PWR_LED(ctrl))
+ p_slot->hpc_ops->green_led_on(p_slot);
+
+ return 0;
+@@ -277,19 +277,19 @@ 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)) {
+- if (POWER_CTRL(ctrl->ctrlcap)) {
++ if (POWER_CTRL(ctrl)) {
/* power off slot */
retval = p_slot->hpc_ops->power_off_slot(p_slot);
if (retval) {
@@ -617078,6 +810036,12 @@
return retval;
}
}
+
+- if (PWR_LED(ctrl->ctrlcap))
++ if (PWR_LED(ctrl))
+ /* turn off Green LED */
+ p_slot->hpc_ops->green_led_off(p_slot);
+
@@ -319,7 +319,7 @@ static void pciehp_power_thread(struct work_struct *work)
case POWEROFF_STATE:
mutex_unlock(&p_slot->lock);
@@ -617087,6 +810051,15 @@
pciehp_disable_slot(p_slot);
mutex_lock(&p_slot->lock);
p_slot->state = STATIC_STATE;
+@@ -327,7 +327,7 @@ static void pciehp_power_thread(struct work_struct *work)
+ case POWERON_STATE:
+ mutex_unlock(&p_slot->lock);
+ if (pciehp_enable_slot(p_slot) &&
+- PWR_LED(p_slot->ctrl->ctrlcap))
++ PWR_LED(p_slot->ctrl))
+ p_slot->hpc_ops->green_led_off(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);
@@ -617096,7 +810069,19 @@
return;
}
info->p_slot = p_slot;
-@@ -424,7 +424,7 @@ static void handle_button_press_event(struct slot *p_slot)
+@@ -409,9 +409,9 @@ static void handle_button_press_event(struct slot *p_slot)
+ "press.\n", p_slot->name);
+ }
+ /* blink green LED and turn off amber */
+- if (PWR_LED(ctrl->ctrlcap))
++ if (PWR_LED(ctrl))
+ p_slot->hpc_ops->green_led_blink(p_slot);
+- if (ATTN_LED(ctrl->ctrlcap))
++ if (ATTN_LED(ctrl))
+ p_slot->hpc_ops->set_attention_status(p_slot, 0);
+
+ schedule_delayed_work(&p_slot->work, 5*HZ);
+@@ -424,16 +424,16 @@ 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);
@@ -617104,7 +810089,19 @@
+ dbg("%s: button cancel\n", __func__);
cancel_delayed_work(&p_slot->work);
if (p_slot->state == BLINKINGOFF_STATE) {
- if (PWR_LED(ctrl->ctrlcap))
+- if (PWR_LED(ctrl->ctrlcap))
++ if (PWR_LED(ctrl))
+ p_slot->hpc_ops->green_led_on(p_slot);
+ } else {
+- if (PWR_LED(ctrl->ctrlcap))
++ if (PWR_LED(ctrl))
+ p_slot->hpc_ops->green_led_off(p_slot);
+ }
+- if (ATTN_LED(ctrl->ctrlcap))
++ if (ATTN_LED(ctrl))
+ p_slot->hpc_ops->set_attention_status(p_slot, 0);
+ info("PCI slot #%s - action canceled due to button press\n",
+ p_slot->name);
@@ -465,7 +465,7 @@ static void handle_surprise_event(struct slot *p_slot)
info = kmalloc(sizeof(*info), GFP_KERNEL);
@@ -617114,7 +810111,28 @@
return;
}
info->p_slot = p_slot;
-@@ -526,7 +526,7 @@ int pciehp_enable_slot(struct slot *p_slot)
+@@ -492,16 +492,16 @@ static void interrupt_event_handler(struct work_struct *work)
+ handle_button_press_event(p_slot);
+ break;
+ case INT_POWER_FAULT:
+- if (!POWER_CTRL(ctrl->ctrlcap))
++ if (!POWER_CTRL(ctrl))
+ break;
+- if (ATTN_LED(ctrl->ctrlcap))
++ if (ATTN_LED(ctrl))
+ p_slot->hpc_ops->set_attention_status(p_slot, 1);
+- if (PWR_LED(ctrl->ctrlcap))
++ if (PWR_LED(ctrl))
+ p_slot->hpc_ops->green_led_off(p_slot);
+ break;
+ case INT_PRESENCE_ON:
+ case INT_PRESENCE_OFF:
+- if (!HP_SUPR_RM(ctrl->ctrlcap))
++ if (!HP_SUPR_RM(ctrl))
+ break;
+ dbg("Surprise Removal\n");
+ update_slot_info(p_slot);
+@@ -526,25 +526,25 @@ int pciehp_enable_slot(struct slot *p_slot)
rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
if (rc || !getstatus) {
@@ -617123,8 +810141,9 @@
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)) {
+ }
+- if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
++ if (MRL_SENS(p_slot->ctrl)) {
rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if (rc || getstatus) {
- info("%s: latch open on slot(%s)\n", __FUNCTION__,
@@ -617132,8 +810151,11 @@
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)) {
+ }
+ }
+
+- if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
++ if (POWER_CTRL(p_slot->ctrl)) {
rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (rc || getstatus) {
- info("%s: already enabled on slot(%s)\n", __FUNCTION__,
@@ -617141,8 +810163,12 @@
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)) {
+@@ -576,30 +576,30 @@ int pciehp_disable_slot(struct slot *p_slot)
+ /* Check to see if (latch closed, card present, power on) */
+ mutex_lock(&p_slot->ctrl->crit_sect);
+
+- if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) {
++ if (!HP_SUPR_RM(p_slot->ctrl)) {
ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
if (ret || !getstatus) {
- info("%s: no adapter on slot(%s)\n", __FUNCTION__,
@@ -617150,8 +810176,11 @@
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)) {
+ }
+ }
+
+- if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
++ if (MRL_SENS(p_slot->ctrl)) {
ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if (ret || getstatus) {
- info("%s: latch open on slot(%s)\n", __FUNCTION__,
@@ -617159,8 +810188,11 @@
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)) {
+ }
+ }
+
+- if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
++ if (POWER_CTRL(p_slot->ctrl)) {
ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (ret || !getstatus) {
- info("%s: already disabled slot(%s)\n", __FUNCTION__,
@@ -617169,10 +810201,61 @@
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
+index 698975a..891f81a 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)
+@@ -221,6 +221,32 @@ static void start_int_poll_timer(struct controller *ctrl, int sec)
+ add_timer(&ctrl->poll_timer);
+ }
+
++static inline int pciehp_request_irq(struct controller *ctrl)
++{
++ int retval, irq = ctrl->pci_dev->irq;
++
++ /* Install interrupt polling timer. Start with 10 sec delay */
++ if (pciehp_poll_mode) {
++ init_timer(&ctrl->poll_timer);
++ start_int_poll_timer(ctrl, 10);
++ return 0;
++ }
++
++ /* Installs the interrupt handler */
++ retval = request_irq(irq, pcie_isr, IRQF_SHARED, MY_NAME, ctrl);
++ if (retval)
++ err("Cannot get irq %d for the hotplug controller\n", irq);
++ return retval;
++}
++
++static inline void pciehp_free_irq(struct controller *ctrl)
++{
++ if (pciehp_poll_mode)
++ del_timer_sync(&ctrl->poll_timer);
++ else
++ free_irq(ctrl->pci_dev->irq, ctrl);
++}
++
+ static inline int pcie_wait_cmd(struct controller *ctrl)
+ {
+ int retval = 0;
+@@ -242,23 +268,21 @@ static inline int pcie_wait_cmd(struct controller *ctrl)
+
+ /**
+ * pcie_write_cmd - Issue controller command
+- * @slot: slot to which the command is issued
++ * @ctrl: controller to which the command is issued
+ * @cmd: command value written to slot control register
+ * @mask: bitmask of slot control register to be modified
+ */
+-static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
++static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
+ {
+- struct controller *ctrl = slot->ctrl;
+ int retval = 0;
+ u16 slot_status;
+ u16 slot_ctrl;
+- unsigned long flags;
+
+ mutex_lock(&ctrl->ctrl_lock);
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (retval) {
@@ -617181,7 +810264,7 @@
goto out;
}
-@@ -267,13 +267,13 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
+@@ -267,26 +291,26 @@ 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",
@@ -617189,24 +810272,35 @@
+ __func__);
}
- spin_lock_irqsave(&ctrl->lock, flags);
+- spin_lock_irqsave(&ctrl->lock, flags);
retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
if (retval) {
- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+- goto out_spin_unlock;
+ err("%s: Cannot read SLOTCTRL register\n", __func__);
- goto out_spin_unlock;
++ goto out;
}
-@@ -283,7 +283,7 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
+ slot_ctrl &= ~mask;
+- slot_ctrl |= ((cmd & mask) | CMD_CMPL_INTR_ENABLE);
++ slot_ctrl |= (cmd & mask);
++ /* Don't enable command completed if caller is changing it. */
++ if (!(mask & CMD_CMPL_INTR_ENABLE))
++ slot_ctrl |= CMD_CMPL_INTR_ENABLE;
+
ctrl->cmd_busy = 1;
++ smp_mb();
retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl);
if (retval)
- err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
+-
+- out_spin_unlock:
+- spin_unlock_irqrestore(&ctrl->lock, flags);
+ 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)
+ /*
+ * Wait for command completion.
+@@ -305,14 +329,14 @@ static int hpc_check_lnk_status(struct controller *ctrl)
retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
if (retval) {
@@ -617224,7 +810318,7 @@
retval = -1;
return retval;
}
-@@ -329,12 +329,12 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
+@@ -329,12 +353,12 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
if (retval) {
@@ -617239,7 +810333,7 @@
atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6;
-@@ -368,11 +368,11 @@ static int hpc_get_power_status(struct slot *slot, u8 *status)
+@@ -368,11 +392,11 @@ static int hpc_get_power_status(struct slot *slot, u8 *status)
retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
if (retval) {
@@ -617253,7 +810347,7 @@
pwr_state = (slot_ctrl & PWR_CTRL) >> 10;
-@@ -399,7 +399,7 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
+@@ -399,7 +423,7 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (retval) {
@@ -617262,7 +810356,7 @@
return retval;
}
-@@ -417,7 +417,7 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
+@@ -417,7 +441,7 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (retval) {
@@ -617271,7 +810365,7 @@
return retval;
}
card_state = (u8)((slot_status & PRSN_STATE) >> 6);
-@@ -435,7 +435,7 @@ static int hpc_query_power_fault(struct slot *slot)
+@@ -435,7 +459,7 @@ static int hpc_query_power_fault(struct slot *slot)
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (retval) {
@@ -617280,7 +810374,7 @@
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)
+@@ -451,7 +475,7 @@ static int hpc_get_emi_status(struct slot *slot, u8 *status)
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (retval) {
@@ -617289,43 +810383,105 @@
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)
+@@ -467,12 +491,7 @@ static int hpc_toggle_emi(struct slot *slot)
+
+ slot_cmd = EMI_CTRL;
+ cmd_mask = EMI_CTRL;
+- if (!pciehp_poll_mode) {
+- slot_cmd = slot_cmd | HP_INTR_ENABLE;
+- cmd_mask = cmd_mask | HP_INTR_ENABLE;
+- }
+-
+- rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
++ rc = pcie_write_cmd(slot->ctrl, slot_cmd, cmd_mask);
+ slot->last_emi_toggle = get_seconds();
- rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
+ return rc;
+@@ -499,14 +518,9 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
+ default:
+ return -1;
+ }
+- if (!pciehp_poll_mode) {
+- slot_cmd = slot_cmd | HP_INTR_ENABLE;
+- cmd_mask = cmd_mask | HP_INTR_ENABLE;
+- }
+-
+- rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
++ rc = pcie_write_cmd(ctrl, 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);
+@@ -519,15 +533,9 @@ static void hpc_set_green_led_on(struct slot *slot)
+ slot_cmd = 0x0100;
+ cmd_mask = PWR_LED_CTRL;
+- if (!pciehp_poll_mode) {
+- slot_cmd = slot_cmd | HP_INTR_ENABLE;
+- cmd_mask = cmd_mask | HP_INTR_ENABLE;
+- }
+-
+- pcie_write_cmd(slot, slot_cmd, cmd_mask);
+-
++ pcie_write_cmd(ctrl, 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)
+@@ -538,14 +546,9 @@ static void hpc_set_green_led_off(struct slot *slot)
- pcie_write_cmd(slot, slot_cmd, cmd_mask);
+ slot_cmd = 0x0300;
+ cmd_mask = PWR_LED_CTRL;
+- if (!pciehp_poll_mode) {
+- slot_cmd = slot_cmd | HP_INTR_ENABLE;
+- cmd_mask = cmd_mask | HP_INTR_ENABLE;
+- }
+-
+- pcie_write_cmd(slot, slot_cmd, cmd_mask);
++ pcie_write_cmd(ctrl, 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);
+@@ -556,23 +559,19 @@ static void hpc_set_green_led_blink(struct slot *slot)
+ slot_cmd = 0x0200;
+ cmd_mask = PWR_LED_CTRL;
+- if (!pciehp_poll_mode) {
+- slot_cmd = slot_cmd | HP_INTR_ENABLE;
+- cmd_mask = cmd_mask | HP_INTR_ENABLE;
+- }
+-
+- pcie_write_cmd(slot, slot_cmd, cmd_mask);
+-
++ pcie_write_cmd(ctrl, 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)
+ {
+- if (pciehp_poll_mode)
+- del_timer(&ctrl->poll_timer);
+- else
+- free_irq(ctrl->pci_dev->irq, ctrl);
++ /* Mask Hot-plug Interrupt Enable */
++ if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE))
++ err("%s: Cannot mask hotplut interrupt enable\n", __func__);
++
++ /* Free interrupt handler or interrupt polling timer */
++ pciehp_free_irq(ctrl);
+
+ /*
+ * If this is the last controller to be released, destroy the
+@@ -590,12 +589,12 @@ static int hpc_power_on_slot(struct slot * slot)
u16 slot_status;
int retval = 0;
@@ -617340,7 +810496,7 @@
return retval;
}
slot_status &= PWR_FAULT_DETECTED;
-@@ -603,7 +603,7 @@ static int hpc_power_on_slot(struct slot * slot)
+@@ -603,7 +602,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",
@@ -617349,8 +810505,28 @@
return retval;
}
}
-@@ -627,11 +627,11 @@ static int hpc_power_on_slot(struct slot * slot)
- retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
+@@ -612,26 +611,20 @@ static int hpc_power_on_slot(struct slot * slot)
+ cmd_mask = PWR_CTRL;
+ /* Enable detection that we turned off at slot power-off time */
+ if (!pciehp_poll_mode) {
+- slot_cmd = slot_cmd |
+- PWR_FAULT_DETECT_ENABLE |
+- MRL_DETECT_ENABLE |
+- PRSN_DETECT_ENABLE |
+- HP_INTR_ENABLE;
+- cmd_mask = cmd_mask |
+- PWR_FAULT_DETECT_ENABLE |
+- MRL_DETECT_ENABLE |
+- PRSN_DETECT_ENABLE |
+- HP_INTR_ENABLE;
++ slot_cmd |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
++ PRSN_DETECT_ENABLE);
++ cmd_mask |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
++ PRSN_DETECT_ENABLE);
+ }
+
+- retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
++ retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
if (retval) {
- err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd);
@@ -617363,7 +810539,7 @@
return retval;
}
-@@ -677,7 +677,7 @@ static int hpc_power_off_slot(struct slot * slot)
+@@ -677,7 +670,7 @@ static int hpc_power_off_slot(struct slot * slot)
int retval = 0;
int changed;
@@ -617372,9 +810548,27 @@
/*
* Set Bad DLLP Mask bit in Correctable Error Mask
-@@ -710,12 +710,12 @@ static int hpc_power_off_slot(struct slot * slot)
+@@ -697,25 +690,20 @@ static int hpc_power_off_slot(struct slot * slot)
+ * till the slot is powered on again.
+ */
+ if (!pciehp_poll_mode) {
+- slot_cmd = (slot_cmd &
+- ~PWR_FAULT_DETECT_ENABLE &
+- ~MRL_DETECT_ENABLE &
+- ~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE;
+- cmd_mask = cmd_mask |
+- PWR_FAULT_DETECT_ENABLE |
+- MRL_DETECT_ENABLE |
+- PRSN_DETECT_ENABLE |
+- HP_INTR_ENABLE;
++ slot_cmd &= ~(PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
++ PRSN_DETECT_ENABLE);
++ cmd_mask |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
++ PRSN_DETECT_ENABLE);
+ }
- retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
+- retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
++ retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
if (retval) {
- err("%s: Write command failed!\n", __FUNCTION__);
+ err("%s: Write command failed!\n", __func__);
@@ -617387,123 +810581,176 @@
/*
* 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) {
+@@ -733,139 +721,56 @@ static int hpc_power_off_slot(struct slot * slot)
+ static irqreturn_t pcie_isr(int irq, void *dev_id)
+ {
+ struct controller *ctrl = (struct controller *)dev_id;
+- u16 slot_status, intr_detect, intr_loc;
+- u16 temp_word;
+- int hp_slot = 0; /* only 1 slot per PCI Express port */
+- int rc = 0;
+- unsigned long flags;
+-
+- 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;
+- return IRQ_NONE;
+- }
++ u16 detected, intr_loc;
+- intr_detect = (ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED |
+- MRL_SENS_CHANGED | PRSN_DETECT_CHANGED | CMD_COMPLETED);
+-
+- intr_loc = slot_status & intr_detect;
+-
+- /* Check to see if it was our interrupt */
+- 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",
+- /* 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);
+- spin_unlock_irqrestore(&ctrl->lock, flags);
++ /*
++ * In order to guarantee that all interrupt events are
++ * serviced, we need to re-inspect Slot Status register after
++ * clearing what is presumed to be the last pending interrupt.
++ */
++ intr_loc = 0;
++ do {
++ if (pciehp_readw(ctrl, SLOTSTATUS, &detected)) {
++ err("%s: Cannot read SLOTSTATUS\n", __func__);
return IRQ_NONE;
}
- dbg("%s: pciehp_readw(SLOTCTRL) with value %x\n",
+- 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",
+- 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);
+- spin_unlock_irqrestore(&ctrl->lock, flags);
++ detected &= (ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED |
++ MRL_SENS_CHANGED | PRSN_DETECT_CHANGED |
++ CMD_COMPLETED);
++ intr_loc |= detected;
++ if (!intr_loc)
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",
+- }
+- spin_unlock_irqrestore(&ctrl->lock, flags);
+-
+- rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+- if (rc) {
+- err("%s: Cannot read SLOT_STATUS register\n",
- __FUNCTION__);
-+ __func__);
++ if (pciehp_writew(ctrl, SLOTSTATUS, detected)) {
++ err("%s: Cannot write to SLOTSTATUS\n", __func__);
return IRQ_NONE;
}
- dbg("%s: pciehp_readw(SLOTSTATUS) with value %x\n",
+- dbg("%s: pciehp_readw(SLOTSTATUS) with value %x\n",
- __FUNCTION__, slot_status);
-+ __func__, slot_status);
++ } while (detected);
- /* 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",
+- /* 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;
- }
+- return IRQ_NONE;
+- }
+- }
++ dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
+
++ /* Check Command Complete Interrupt Pending */
+ if (intr_loc & CMD_COMPLETED) {
+- /*
+- * Command Complete Interrupt Pending
+- */
+ ctrl->cmd_busy = 0;
++ smp_mb();
+ wake_up_interruptible(&ctrl->queue);
}
-@@ -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) {
+
++ /* Check MRL Sensor Changed */
+ if (intr_loc & MRL_SENS_CHANGED)
+- pciehp_handle_switch_change(hp_slot, ctrl);
++ pciehp_handle_switch_change(0, ctrl);
+
++ /* Check Attention Button Pressed */
+ if (intr_loc & ATTN_BUTTN_PRESSED)
+- pciehp_handle_attention_button(hp_slot, ctrl);
++ pciehp_handle_attention_button(0, ctrl);
+
++ /* Check Presence Detect Changed */
+ if (intr_loc & PRSN_DETECT_CHANGED)
+- pciehp_handle_presence_change(hp_slot, ctrl);
++ pciehp_handle_presence_change(0, ctrl);
+
++ /* Check Power Fault Detected */
+ if (intr_loc & PWR_FAULT_DETECTED)
+- pciehp_handle_power_fault(hp_slot, ctrl);
+-
+- /* Clear all events after serving them */
+- 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",
+- return IRQ_NONE;
+- }
+- /* Unmask 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 SLOTCTRL register\n",
- __FUNCTION__);
-+ __func__);
- spin_unlock_irqrestore(&ctrl->lock, flags);
- return IRQ_NONE;
- }
-
+- 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",
+- 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",
+- spin_unlock_irqrestore(&ctrl->lock, flags);
+- return IRQ_NONE;
+- }
+- spin_unlock_irqrestore(&ctrl->lock, flags);
+-
+- 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",
+- return IRQ_NONE;
+- }
+-
+- /* 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 failed\n",
- __FUNCTION__);
-+ __func__);
- return IRQ_NONE;
- }
- dbg("%s: pciehp_writew(SLOTSTATUS) with value %x\n",
+- return IRQ_NONE;
+- }
+- dbg("%s: pciehp_writew(SLOTSTATUS) with value %x\n",
- __FUNCTION__, temp_word);
-+ __func__, temp_word);
- }
+- }
++ pciehp_handle_power_fault(0, ctrl);
return IRQ_HANDLED;
-@@ -879,7 +879,7 @@ static int hpc_get_max_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
+ }
+@@ -879,7 +784,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) {
@@ -617512,7 +810759,7 @@
return retval;
}
-@@ -908,7 +908,7 @@ static int hpc_get_max_lnk_width(struct slot *slot,
+@@ -908,7 +813,7 @@ static int hpc_get_max_lnk_width(struct slot *slot,
retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap);
if (retval) {
@@ -617521,7 +810768,7 @@
return retval;
}
-@@ -957,7 +957,7 @@ static int hpc_get_cur_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
+@@ -957,7 +862,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) {
@@ -617530,7 +810777,7 @@
return retval;
}
-@@ -986,7 +986,7 @@ static int hpc_get_cur_lnk_width(struct slot *slot,
+@@ -986,7 +891,7 @@ static int hpc_get_cur_lnk_width(struct slot *slot,
retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
if (retval) {
@@ -617539,186 +810786,389 @@
return retval;
}
-@@ -1130,38 +1130,38 @@ static int pcie_init_hardware_part1(struct controller *ctrl,
+@@ -1052,7 +957,7 @@ static struct hpc_ops pciehp_hpc_ops = {
+ };
- 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;
+ #ifdef CONFIG_ACPI
+-int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
++static int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
+ {
+ acpi_status status;
+ acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
+@@ -1112,7 +1017,7 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
+ break;
}
+- err("Cannot get control of hotplug hardware for pci %s\n",
++ dbg("Cannot get control of hotplug hardware for pci %s\n",
+ pci_name(dev));
+
+ kfree(string.pointer);
+@@ -1123,45 +1028,9 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
+ static int pcie_init_hardware_part1(struct controller *ctrl,
+ struct pcie_device *dev)
+ {
+- int rc;
+- u16 temp_word;
+- u32 slot_cap;
+- u16 slot_status;
+-
+- rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+- if (rc) {
+- err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
+- return -1;
+- }
+-
/* Mask Hot-plug Interrupt Enable */
- rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
- if (rc) {
+- 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",
+- 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) {
+- 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) {
+- 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) {
+- 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__);
++ if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) {
++ err("%s: Cannot mask hotplug interrupt enable\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;
- }
+@@ -1169,205 +1038,125 @@ static int pcie_init_hardware_part1(struct controller *ctrl,
-@@ -1185,7 +1185,7 @@ int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
+ int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
+ {
+- int rc;
+- u16 temp_word;
+- u16 intr_enable = 0;
+- u32 slot_cap;
+- u16 slot_status;
++ u16 cmd, mask;
- rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
- if (rc) {
+- rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+- if (rc) {
+- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+- goto abort;
+- }
+-
+- intr_enable = intr_enable | PRSN_DETECT_ENABLE;
+-
+- 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;
+- goto abort;
++ /*
++ * We need to clear all events before enabling hotplug interrupt
++ * notification mechanism in order for hotplug controler to
++ * generate interrupts.
++ */
++ if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) {
++ err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
++ return -1;
}
-@@ -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) {
+- if (ATTN_BUTTN(slot_cap))
+- intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
+-
+- if (POWER_CTRL(slot_cap))
+- intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
++ cmd = PRSN_DETECT_ENABLE;
++ if (ATTN_BUTTN(ctrl))
++ cmd |= ATTN_BUTTN_ENABLE;
++ if (POWER_CTRL(ctrl))
++ cmd |= PWR_FAULT_DETECT_ENABLE;
++ if (MRL_SENS(ctrl))
++ cmd |= MRL_DETECT_ENABLE;
++ if (!pciehp_poll_mode)
++ cmd |= HP_INTR_ENABLE;
+
+- if (MRL_SENS(slot_cap))
+- intr_enable = intr_enable | MRL_DETECT_ENABLE;
++ mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE |
++ PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | HP_INTR_ENABLE;
+
+- temp_word = (temp_word & ~intr_enable) | intr_enable;
+-
+- if (pciehp_poll_mode) {
+- temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
+- } else {
+- temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
+- }
+-
+- /*
+- * Unmask Hot-plug Interrupt Enable for the interrupt
+- * notification mechanism case.
+- */
+- 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__);
++ if (pcie_write_cmd(ctrl, cmd, mask)) {
++ err("%s: Cannot enable software notification\n", __func__);
goto abort;
}
- rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
- if (rc) {
+- 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;
- }
+- goto abort_disable_intr;
+- }
- temp_word = 0x1F; /* Clear all events */
- rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
- if (rc) {
+- 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;
- }
+- goto abort_disable_intr;
+- }
+-
+- if (pciehp_force) {
++ if (pciehp_force)
+ dbg("Bypassing BIOS check for pciehp use on %s\n",
+ pci_name(ctrl->pci_dev));
+- } else {
+- rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
+- if (rc)
+- goto abort_disable_intr;
+- }
++ else if (pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev))
++ goto abort_disable_intr;
-@@ -1247,7 +1247,7 @@ abort_disable_intr:
- rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
- }
- if (rc)
+ return 0;
+
+ /* We end up here for the many possible ways to fail this API. */
+ abort_disable_intr:
+- rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+- if (!rc) {
+- temp_word &= ~(intr_enable | HP_INTR_ENABLE);
+- rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+- }
+- if (rc)
- err("%s : disabling interrupts failed\n", __FUNCTION__);
++ if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE))
+ 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",
+-int pcie_init(struct controller *ctrl, struct pcie_device *dev)
++static inline void dbg_ctrl(struct controller *ctrl)
+ {
+- int rc;
+- u16 cap_reg;
+- u32 slot_cap;
+- int cap_base;
+- u16 slot_status, slot_ctrl;
+- struct pci_dev *pdev;
+-
+- pdev = dev->port;
+- 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) {
+-
+- 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;
+- goto abort;
+- }
++ int i;
++ u16 reg16;
++ struct pci_dev *pdev = ctrl->pci_dev;
+- 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);
++ if (!pciehp_debug)
++ return;
- rc = pciehp_readw(ctrl, CAPREG, &cap_reg);
- if (rc) {
+- 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",
+- 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 "
+-
+- 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;
- }
+- goto abort;
+- }
++ dbg("Hotplug Controller:\n");
++ dbg(" Seg/Bus/Dev/Func/IRQ : %s IRQ %d\n", pci_name(pdev), pdev->irq);
++ dbg(" Vendor ID : 0x%04x\n", pdev->vendor);
++ dbg(" Device ID : 0x%04x\n", pdev->device);
++ dbg(" Subsystem ID : 0x%04x\n", pdev->subsystem_device);
++ dbg(" Subsystem Vendor ID : 0x%04x\n", pdev->subsystem_vendor);
++ dbg(" PCIe Cap offset : 0x%02x\n", ctrl->cap_base);
++ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
++ if (!pci_resource_len(pdev, i))
++ continue;
++ dbg(" PCI resource [%d] : 0x%llx at 0x%llx\n", i,
++ (unsigned long long)pci_resource_len(pdev, i),
++ (unsigned long long)pci_resource_start(pdev, i));
++ }
++ dbg("Slot Capabilities : 0x%08x\n", ctrl->slot_cap);
++ dbg(" Physical Slot Number : %d\n", ctrl->first_slot);
++ dbg(" Attention Button : %3s\n", ATTN_BUTTN(ctrl) ? "yes" : "no");
++ dbg(" Power Controller : %3s\n", POWER_CTRL(ctrl) ? "yes" : "no");
++ dbg(" MRL Sensor : %3s\n", MRL_SENS(ctrl) ? "yes" : "no");
++ dbg(" Attention Indicator : %3s\n", ATTN_LED(ctrl) ? "yes" : "no");
++ dbg(" Power Indicator : %3s\n", PWR_LED(ctrl) ? "yes" : "no");
++ dbg(" Hot-Plug Surprise : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no");
++ dbg(" EMI Present : %3s\n", EMI(ctrl) ? "yes" : "no");
++ pciehp_readw(ctrl, SLOTSTATUS, ®16);
++ dbg("Slot Status : 0x%04x\n", reg16);
++ pciehp_readw(ctrl, SLOTSTATUS, ®16);
++ dbg("Slot Control : 0x%04x\n", reg16);
++}
- rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
- if (rc) {
+- 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",
+- 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);
++int pcie_init(struct controller *ctrl, struct pcie_device *dev)
++{
++ u32 slot_cap;
++ struct pci_dev *pdev = dev->port;
- if (!(slot_cap & HP_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__);
++ ctrl->pci_dev = pdev;
++ ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
++ if (!ctrl->cap_base) {
++ err("%s: Cannot find PCI Express capability\n", __func__);
goto abort;
}
- /* For debugging purpose */
- rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
- if (rc) {
+- /* 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__);
++ if (pciehp_readl(ctrl, SLOTCAP, &slot_cap)) {
++ err("%s: Cannot read SLOTCAP register\n", __func__);
goto abort;
}
- dbg("%s: SLOTSTATUS offset %x slot_status %x\n",
+- 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) {
+-
+- 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",
+- 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)
+- dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc,
+- (unsigned long long)pci_resource_start(pdev, rc),
+- (unsigned long long)pci_resource_len(pdev, rc));
+-
+- info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
+- pdev->vendor, pdev->device,
+- pdev->subsystem_vendor, pdev->subsystem_device);
+
++ ctrl->slot_cap = slot_cap;
++ ctrl->first_slot = slot_cap >> 19;
++ ctrl->slot_device_offset = 0;
++ ctrl->num_slots = 1;
++ ctrl->hpc_ops = &pciehp_hpc_ops;
+ mutex_init(&ctrl->crit_sect);
+ mutex_init(&ctrl->ctrl_lock);
+- spin_lock_init(&ctrl->lock);
+-
+- /* setup wait queue */
+ init_waitqueue_head(&ctrl->queue);
++ dbg_ctrl(ctrl);
+
+- /* return PCI Controller Info */
+- ctrl->slot_device_offset = 0;
+- ctrl->num_slots = 1;
+- ctrl->first_slot = slot_cap >> 19;
+- ctrl->ctrlcap = slot_cap & 0x0000007f;
++ info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
++ pdev->vendor, pdev->device,
++ pdev->subsystem_vendor, pdev->subsystem_device);
- 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",
+- rc = pcie_init_hardware_part1(ctrl, dev);
+- if (rc)
++ if (pcie_init_hardware_part1(ctrl, dev))
+ goto abort;
+
+- if (pciehp_poll_mode) {
+- /* Install interrupt polling timer. Start with 10 sec delay */
+- init_timer(&ctrl->poll_timer);
+- start_int_poll_timer(ctrl, 10);
+- } else {
+- /* Installs the interrupt handler */
+- 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",
+- atomic_read(&pciehp_num_controllers), rc);
+- if (rc) {
+- err("Can't get irq %d for the hotplug controller\n",
+- ctrl->pci_dev->irq);
+- goto abort;
+- }
+- }
+- dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
+- PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);
++ if (pciehp_request_irq(ctrl))
++ goto abort;
+
+ /*
+ * If this is the first controller to be initialized,
+@@ -1376,21 +1165,17 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev)
+ if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
+ pciehp_wq = create_singlethread_workqueue("pciehpd");
+ if (!pciehp_wq) {
+- rc = -ENOMEM;
+ goto abort_free_irq;
+ }
+ }
+
+- rc = pcie_init_hardware_part2(ctrl, dev);
+- if (rc == 0) {
+- ctrl->hpc_ops = &pciehp_hpc_ops;
+- return 0;
+- }
++ if (pcie_init_hardware_part2(ctrl, dev))
++ goto abort_free_irq;
++
++ return 0;
++
+ abort_free_irq:
+- if (pciehp_poll_mode)
+- del_timer_sync(&ctrl->poll_timer);
+- else
+- free_irq(ctrl->pci_dev->irq, ctrl);
++ pciehp_free_irq(ctrl);
+ abort:
+ return -1;
+ }
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
@@ -618129,10 +811579,30 @@
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
+index 80dec97..1648076 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)
+@@ -39,6 +39,7 @@
+ int shpchp_debug;
+ int shpchp_poll_mode;
+ int shpchp_poll_time;
++int shpchp_slot_with_bus;
+ struct workqueue_struct *shpchp_wq;
+
+ #define DRIVER_VERSION "0.4"
+@@ -52,9 +53,11 @@ MODULE_LICENSE("GPL");
+ module_param(shpchp_debug, bool, 0644);
+ module_param(shpchp_poll_mode, bool, 0644);
+ module_param(shpchp_poll_time, int, 0644);
++module_param(shpchp_slot_with_bus, bool, 0644);
+ MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not");
+ MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not");
+ MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds");
++MODULE_PARM_DESC(shpchp_slot_with_bus, "Use bus number in the slot name");
+
+ #define SHPC_MODULE_NAME "shpchp"
+
+@@ -91,7 +94,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
@@ -618141,7 +811611,22 @@
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)
+@@ -100,8 +103,12 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
+
+ static void make_slot_name(struct slot *slot)
+ {
+- snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
+- slot->bus, slot->number);
++ if (shpchp_slot_with_bus)
++ snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
++ slot->bus, slot->number);
++ else
++ snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d",
++ slot->number);
+ }
+
+ static int init_slots(struct controller *ctrl)
+@@ -195,7 +202,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
{
struct slot *slot = get_slot(hotplug_slot);
@@ -618150,7 +811635,7 @@
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)
+@@ -207,7 +214,7 @@ static int enable_slot (struct hotplug_slot *hotplug_slot)
{
struct slot *slot = get_slot(hotplug_slot);
@@ -618159,7 +811644,7 @@
return shpchp_sysfs_enable_slot(slot);
}
-@@ -216,7 +216,7 @@ static int disable_slot (struct hotplug_slot *hotplug_slot)
+@@ -216,7 +223,7 @@ static int disable_slot (struct hotplug_slot *hotplug_slot)
{
struct slot *slot = get_slot(hotplug_slot);
@@ -618168,7 +811653,7 @@
return shpchp_sysfs_disable_slot(slot);
}
-@@ -226,7 +226,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
+@@ -226,7 +233,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = get_slot(hotplug_slot);
int retval;
@@ -618177,7 +811662,7 @@
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)
+@@ -240,7 +247,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = get_slot(hotplug_slot);
int retval;
@@ -618186,7 +811671,7 @@
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)
+@@ -254,7 +261,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = get_slot(hotplug_slot);
int retval;
@@ -618195,7 +811680,7 @@
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)
+@@ -268,7 +275,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = get_slot(hotplug_slot);
int retval;
@@ -618204,7 +811689,7 @@
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)
+@@ -282,7 +289,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;
@@ -618213,7 +811698,7 @@
*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
+@@ -294,7 +301,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;
@@ -618222,7 +811707,7 @@
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
+@@ -308,7 +315,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;
@@ -618231,7 +811716,7 @@
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)
+@@ -338,7 +345,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
if (!ctrl) {
@@ -618240,7 +811725,7 @@
goto err_out_none;
}
INIT_LIST_HEAD(&ctrl->slot_list);
-@@ -402,7 +402,7 @@ static int __init shpcd_init(void)
+@@ -402,7 +409,7 @@ static int __init shpcd_init(void)
int retval = 0;
retval = pci_register_driver(&shpc_driver);
@@ -619159,8 +812644,148 @@
return new_iova;
}
+diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
+index 26938da..8c61304 100644
+--- a/drivers/pci/msi.c
++++ b/drivers/pci/msi.c
+@@ -123,7 +123,7 @@ static void msix_flush_writes(unsigned int irq)
+ }
+ }
+
+-static void msi_set_mask_bit(unsigned int irq, int flag)
++static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag)
+ {
+ struct msi_desc *entry;
+
+@@ -137,8 +137,8 @@ static void msi_set_mask_bit(unsigned int irq, int flag)
+
+ pos = (long)entry->mask_base;
+ pci_read_config_dword(entry->dev, pos, &mask_bits);
+- mask_bits &= ~(1);
+- mask_bits |= flag;
++ mask_bits &= ~(mask);
++ mask_bits |= flag & mask;
+ pci_write_config_dword(entry->dev, pos, mask_bits);
+ } else {
+ msi_set_enable(entry->dev, !flag);
+@@ -241,13 +241,13 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg)
+
+ void mask_msi_irq(unsigned int irq)
+ {
+- msi_set_mask_bit(irq, 1);
++ msi_set_mask_bits(irq, 1, 1);
+ msix_flush_writes(irq);
+ }
+
+ void unmask_msi_irq(unsigned int irq)
+ {
+- msi_set_mask_bit(irq, 0);
++ msi_set_mask_bits(irq, 1, 0);
+ msix_flush_writes(irq);
+ }
+
+@@ -291,7 +291,8 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
+ msi_set_enable(dev, 0);
+ write_msi_msg(dev->irq, &entry->msg);
+ if (entry->msi_attrib.maskbit)
+- msi_set_mask_bit(dev->irq, entry->msi_attrib.masked);
++ msi_set_mask_bits(dev->irq, entry->msi_attrib.maskbits_mask,
++ entry->msi_attrib.masked);
+
+ pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
+ control &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
+@@ -315,7 +316,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
+
+ list_for_each_entry(entry, &dev->msi_list, list) {
+ write_msi_msg(entry->irq, &entry->msg);
+- msi_set_mask_bit(entry->irq, entry->msi_attrib.masked);
++ msi_set_mask_bits(entry->irq, 1, entry->msi_attrib.masked);
+ }
+
+ BUG_ON(list_empty(&dev->msi_list));
+@@ -382,6 +383,7 @@ static int msi_capability_init(struct pci_dev *dev)
+ pci_write_config_dword(dev,
+ msi_mask_bits_reg(pos, is_64bit_address(control)),
+ maskbits);
++ entry->msi_attrib.maskbits_mask = temp;
+ }
+ list_add_tail(&entry->list, &dev->msi_list);
+
+@@ -569,10 +571,9 @@ int pci_enable_msi(struct pci_dev* dev)
+ }
+ EXPORT_SYMBOL(pci_enable_msi);
+
+-void pci_disable_msi(struct pci_dev* dev)
++void pci_msi_shutdown(struct pci_dev* dev)
+ {
+ struct msi_desc *entry;
+- int default_irq;
+
+ if (!pci_msi_enable || !dev || !dev->msi_enabled)
+ return;
+@@ -583,15 +584,31 @@ void pci_disable_msi(struct pci_dev* dev)
+
+ BUG_ON(list_empty(&dev->msi_list));
+ entry = list_entry(dev->msi_list.next, struct msi_desc, list);
+- if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
+- return;
++ /* Return the the pci reset with msi irqs unmasked */
++ if (entry->msi_attrib.maskbit) {
++ u32 mask = entry->msi_attrib.maskbits_mask;
++ msi_set_mask_bits(dev->irq, mask, ~mask);
+ }
+-
+- default_irq = entry->msi_attrib.default_irq;
+- msi_free_irqs(dev);
++ if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI)
++ return;
+
+ /* Restore dev->irq to its default pin-assertion irq */
+- dev->irq = default_irq;
++ dev->irq = entry->msi_attrib.default_irq;
++}
++void pci_disable_msi(struct pci_dev* dev)
++{
++ struct msi_desc *entry;
++
++ if (!pci_msi_enable || !dev || !dev->msi_enabled)
++ return;
++
++ pci_msi_shutdown(dev);
++
++ entry = list_entry(dev->msi_list.next, struct msi_desc, list);
++ if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI)
++ return;
++
++ msi_free_irqs(dev);
+ }
+ EXPORT_SYMBOL(pci_disable_msi);
+
+@@ -684,7 +701,7 @@ static void msix_free_all_irqs(struct pci_dev *dev)
+ msi_free_irqs(dev);
+ }
+
+-void pci_disable_msix(struct pci_dev* dev)
++void pci_msix_shutdown(struct pci_dev* dev)
+ {
+ if (!pci_msi_enable || !dev || !dev->msix_enabled)
+ return;
+@@ -692,6 +709,13 @@ void pci_disable_msix(struct pci_dev* dev)
+ msix_set_enable(dev, 0);
+ pci_intx_for_msi(dev, 1);
+ dev->msix_enabled = 0;
++}
++void pci_disable_msix(struct pci_dev* dev)
++{
++ if (!pci_msi_enable || !dev || !dev->msix_enabled)
++ return;
++
++ pci_msix_shutdown(dev);
+
+ msix_free_all_irqs(dev);
+ }
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
-index e571c72..e8d94fa 100644
+index e571c72..72cf61e 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,
@@ -619185,6 +812810,15 @@
current->mempolicy = oldpol;
#endif
return error;
+@@ -357,6 +360,8 @@ static void pci_device_shutdown(struct device *dev)
+
+ if (drv && drv->shutdown)
+ drv->shutdown(pci_dev);
++ pci_msi_shutdown(pci_dev);
++ pci_msix_shutdown(pci_dev);
+ }
+
+ /**
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 8dcf145..271d41c 100644
--- a/drivers/pci/pci-sysfs.c
@@ -619454,7 +813088,7 @@
#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
+index 287a931..5a0c6ad 100644
--- a/drivers/pci/pcie/Kconfig
+++ b/drivers/pci/pcie/Kconfig
@@ -26,3 +26,23 @@ config HOTPLUG_PCI_PCIE
@@ -619468,7 +813102,7 @@
+config PCIEASPM
+ bool "PCI Express ASPM support(Experimental)"
+ depends on PCI && EXPERIMENTAL && PCIEPORTBUS
-+ default y
++ default n
+ help
+ This enables PCI Express ASPM (Active State Power Management) and
+ Clock Power Management. ASPM supports state L0/L0s/L1.
@@ -619518,16 +813152,19 @@
return status;
}
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
-index 8c199ae..96ac540 100644
+index 8c199ae..d39a78d 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)
+@@ -31,10 +31,13 @@ int aer_osc_setup(struct pcie_device *pciedev)
+ {
+ acpi_status status = AE_NOT_FOUND;
struct pci_dev *pdev = pciedev->port;
- acpi_handle handle = 0;
-
+- acpi_handle handle = 0;
++ acpi_handle handle = NULL;
++
+ if (acpi_pci_disabled)
+ return -1;
-+
+
/* Find root host bridge */
- while (pdev->bus && pdev->bus->self)
+ while (pdev->bus->self)
@@ -620422,7 +814059,7 @@
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
+index 2db2e4b..4a55bf3 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -9,6 +9,7 @@
@@ -620557,7 +814194,43 @@
kfree(pci_dev);
}
-@@ -849,7 +882,6 @@ struct pci_dev *alloc_pci_dev(void)
+@@ -809,11 +842,14 @@ static void set_pcie_port_type(struct pci_dev *pdev)
+ * reading the dword at 0x100 which must either be 0 or a valid extended
+ * capability header.
+ */
+-int pci_cfg_space_size(struct pci_dev *dev)
++int pci_cfg_space_size_ext(struct pci_dev *dev, unsigned check_exp_pcix)
+ {
+ int pos;
+ u32 status;
+
++ if (!check_exp_pcix)
++ goto skip;
++
+ pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ if (!pos) {
+ pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+@@ -825,6 +861,7 @@ int pci_cfg_space_size(struct pci_dev *dev)
+ goto fail;
+ }
+
++ skip:
+ if (pci_read_config_dword(dev, 256, &status) != PCIBIOS_SUCCESSFUL)
+ goto fail;
+ if (status == 0xffffffff)
+@@ -836,6 +873,11 @@ int pci_cfg_space_size(struct pci_dev *dev)
+ return PCI_CFG_SPACE_SIZE;
+ }
+
++int pci_cfg_space_size(struct pci_dev *dev)
++{
++ return pci_cfg_space_size_ext(dev, 1);
++}
++
+ static void pci_release_bus_bridge_dev(struct device *dev)
+ {
+ kfree(dev);
+@@ -849,7 +891,6 @@ struct pci_dev *alloc_pci_dev(void)
if (!dev)
return NULL;
@@ -620565,7 +814238,7 @@
INIT_LIST_HEAD(&dev->bus_list);
pci_msi_init_pci_dev(dev);
-@@ -862,8 +894,7 @@ EXPORT_SYMBOL(alloc_pci_dev);
+@@ -862,8 +903,7 @@ EXPORT_SYMBOL(alloc_pci_dev);
* Read the config data for a PCI device, sanity-check it
* and fill in the dev structure...
*/
@@ -620575,7 +814248,7 @@
{
struct pci_dev *dev;
u32 l;
-@@ -922,6 +953,8 @@ pci_scan_device(struct pci_bus *bus, int devfn)
+@@ -922,6 +962,8 @@ pci_scan_device(struct pci_bus *bus, int devfn)
return NULL;
}
@@ -620584,7 +814257,15 @@
return dev;
}
-@@ -946,7 +979,6 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
+@@ -931,7 +973,6 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
+ dev->dev.release = pci_release_dev;
+ pci_dev_get(dev);
+
+- set_dev_node(&dev->dev, pcibus_to_node(bus));
+ dev->dev.dma_mask = &dev->dma_mask;
+ dev->dev.dma_parms = &dev->dma_parms;
+ dev->dev.coherent_dma_mask = 0xffffffffull;
+@@ -946,7 +987,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.
*/
@@ -620592,7 +814273,7 @@
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);
+@@ -973,7 +1013,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
@@ -620601,7 +814282,7 @@
*/
int pci_scan_slot(struct pci_bus *bus, int devfn)
{
-@@ -1005,6 +1037,10 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
+@@ -1005,6 +1045,10 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
break;
}
}
@@ -620612,7 +814293,37 @@
return nr;
}
-@@ -1175,7 +1211,7 @@ static void __init pci_insertion_sort_klist(struct pci_dev *a, struct list_head
+@@ -1044,6 +1088,10 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
+ return max;
+ }
+
++void __attribute__((weak)) set_pci_bus_resources_arch_default(struct pci_bus *b)
++{
++}
++
+ struct pci_bus * pci_create_bus(struct device *parent,
+ int bus, struct pci_ops *ops, void *sysdata)
+ {
+@@ -1083,6 +1131,9 @@ struct pci_bus * pci_create_bus(struct device *parent,
+ goto dev_reg_err;
+ b->bridge = get_device(dev);
+
++ if (!parent)
++ set_dev_node(b->bridge, pcibus_to_node(b));
++
+ b->dev.class = &pcibus_class;
+ b->dev.parent = b->bridge;
+ sprintf(b->dev.bus_id, "%04x:%02x", pci_domain_nr(b), bus);
+@@ -1100,6 +1151,8 @@ struct pci_bus * pci_create_bus(struct device *parent,
+ b->resource[0] = &ioport_resource;
+ b->resource[1] = &iomem_resource;
+
++ set_pci_bus_resources_arch_default(b);
++
+ return b;
+
+ dev_create_file_err:
+@@ -1175,7 +1228,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);
}
@@ -620621,7 +814332,7 @@
{
LIST_HEAD(sorted_devices);
struct list_head *pos, *tmp;
-@@ -1196,36 +1232,3 @@ static void __init pci_sort_breadthfirst_klist(void)
+@@ -1196,36 +1249,3 @@ static void __init pci_sort_breadthfirst_klist(void)
list_splice(&sorted_devices, &device_klist->k_list);
spin_unlock(&device_klist->k_lock);
}
@@ -620658,6 +814369,56 @@
- pci_sort_breadthfirst_klist();
-}
-
+diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
+index ef18fcd..963a976 100644
+--- a/drivers/pci/proc.c
++++ b/drivers/pci/proc.c
+@@ -293,6 +293,7 @@ static int proc_bus_pci_release(struct inode *inode, struct file *file)
+ #endif /* HAVE_PCI_MMAP */
+
+ static const struct file_operations proc_bus_pci_operations = {
++ .owner = THIS_MODULE,
+ .llseek = proc_bus_pci_lseek,
+ .read = proc_bus_pci_read,
+ .write = proc_bus_pci_write,
+@@ -406,11 +407,10 @@ int pci_proc_attach_device(struct pci_dev *dev)
+ }
+
+ sprintf(name, "%02x.%x", PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+- e = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, bus->procdir);
++ e = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR, bus->procdir,
++ &proc_bus_pci_operations, dev);
+ if (!e)
+ return -ENOMEM;
+- e->proc_fops = &proc_bus_pci_operations;
+- e->data = dev;
+ e->size = dev->cfg_size;
+ dev->procent = e;
+
+@@ -462,6 +462,7 @@ static int proc_bus_pci_dev_open(struct inode *inode, struct file *file)
+ return seq_open(file, &proc_bus_pci_devices_op);
+ }
+ static const struct file_operations proc_bus_pci_dev_operations = {
++ .owner = THIS_MODULE,
+ .open = proc_bus_pci_dev_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -470,12 +471,10 @@ static const struct file_operations proc_bus_pci_dev_operations = {
+
+ static int __init pci_proc_init(void)
+ {
+- struct proc_dir_entry *entry;
+ struct pci_dev *dev = NULL;
+- proc_bus_pci_dir = proc_mkdir("pci", proc_bus);
+- entry = create_proc_entry("devices", 0, proc_bus_pci_dir);
+- if (entry)
+- entry->proc_fops = &proc_bus_pci_dev_operations;
++ proc_bus_pci_dir = proc_mkdir("bus/pci", NULL);
++ proc_create("devices", 0, proc_bus_pci_dir,
++ &proc_bus_pci_dev_operations);
+ proc_initialized = 1;
+ while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ pci_proc_attach_device(dev);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index e887aa4..afd914e 100644
--- a/drivers/pci/quirks.c
@@ -621080,332 +814841,5565 @@
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)
+-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..1b0eb5a 100644
+--- a/drivers/pcmcia/Kconfig
++++ b/drivers/pcmcia/Kconfig
+@@ -38,7 +38,6 @@ config PCMCIA_DEBUG
+ config PCMCIA
+ tristate "16-bit PCMCIA support"
+ select CRC32
+- select HAVE_IDE
+ default y
+ ---help---
+ This option enables support for 16-bit PCMCIA cards. Most older
+@@ -220,6 +219,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/cistpl.c b/drivers/pcmcia/cistpl.c
+index 06a85d7..3637953 100644
+--- a/drivers/pcmcia/cistpl.c
++++ b/drivers/pcmcia/cistpl.c
+@@ -402,15 +402,6 @@ EXPORT_SYMBOL(pcmcia_replace_cis);
+
+ ======================================================================*/
+
+-static inline u16 cis_get_u16(void *ptr)
+-{
+- return le16_to_cpu(get_unaligned((__le16 *) ptr));
+-}
+-static inline u32 cis_get_u32(void *ptr)
+-{
+- return le32_to_cpu(get_unaligned((__le32 *) ptr));
+-}
+-
+ typedef struct tuple_flags {
+ u_int link_space:4;
+ u_int has_link:1;
+@@ -471,7 +462,7 @@ static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
+ /* Get indirect link from the MFC tuple */
+ read_cis_cache(s, LINK_SPACE(tuple->Flags),
+ tuple->LinkOffset, 5, link);
+- ofs = cis_get_u32(link + 1);
++ ofs = get_unaligned_le32(link + 1);
+ SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR);
+ /* Move to the next indirect link */
+ tuple->LinkOffset += 5;
+@@ -679,8 +670,8 @@ static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
+ if (tuple->TupleDataLen < 5)
+ return CS_BAD_TUPLE;
+ p = (u_char *) tuple->TupleData;
+- csum->addr = tuple->CISOffset + cis_get_u16(p) - 2;
+- csum->len = cis_get_u16(p + 2);
++ csum->addr = tuple->CISOffset + get_unaligned_le16(p) - 2;
++ csum->len = get_unaligned_le16(p + 2);
+ csum->sum = *(p + 4);
+ return CS_SUCCESS;
+ }
+@@ -691,7 +682,7 @@ static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
+ {
+ if (tuple->TupleDataLen < 4)
+ return CS_BAD_TUPLE;
+- link->addr = cis_get_u32(tuple->TupleData);
++ link->addr = get_unaligned_le32(tuple->TupleData);
+ return CS_SUCCESS;
+ }
+
+@@ -710,7 +701,7 @@ static int parse_longlink_mfc(tuple_t *tuple,
+ return CS_BAD_TUPLE;
+ for (i = 0; i < link->nfn; i++) {
+ link->fn[i].space = *p; p++;
+- link->fn[i].addr = cis_get_u32(p);
++ link->fn[i].addr = get_unaligned_le32(p);
+ p += 4;
+ }
+ return CS_SUCCESS;
+@@ -800,8 +791,8 @@ static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
+ {
+ if (tuple->TupleDataLen < 4)
+ return CS_BAD_TUPLE;
+- m->manf = cis_get_u16(tuple->TupleData);
+- m->card = cis_get_u16(tuple->TupleData + 2);
++ m->manf = get_unaligned_le16(tuple->TupleData);
++ m->card = get_unaligned_le16(tuple->TupleData + 2);
+ return CS_SUCCESS;
+ }
+
+@@ -1100,7 +1091,7 @@ static int parse_cftable_entry(tuple_t *tuple,
+ break;
+ case 0x20:
+ entry->mem.nwin = 1;
+- entry->mem.win[0].len = cis_get_u16(p) << 8;
++ entry->mem.win[0].len = get_unaligned_le16(p) << 8;
+ entry->mem.win[0].card_addr = 0;
+ entry->mem.win[0].host_addr = 0;
+ p += 2;
+@@ -1108,8 +1099,8 @@ static int parse_cftable_entry(tuple_t *tuple,
+ break;
+ case 0x40:
+ entry->mem.nwin = 1;
+- entry->mem.win[0].len = cis_get_u16(p) << 8;
+- entry->mem.win[0].card_addr = cis_get_u16(p + 2) << 8;
++ entry->mem.win[0].len = get_unaligned_le16(p) << 8;
++ entry->mem.win[0].card_addr = get_unaligned_le16(p + 2) << 8;
+ entry->mem.win[0].host_addr = 0;
+ p += 4;
+ if (p > q) return CS_BAD_TUPLE;
+@@ -1146,7 +1137,7 @@ static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
+ p = (u_char *)tuple->TupleData;
+ bar->attr = *p;
+ p += 2;
+- bar->size = cis_get_u32(p);
++ bar->size = get_unaligned_le32(p);
+ return CS_SUCCESS;
+ }
+
+@@ -1159,7 +1150,7 @@ static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
+ return CS_BAD_TUPLE;
+ config->last_idx = *(++p);
+ p++;
+- config->base = cis_get_u32(p);
++ config->base = get_unaligned_le32(p);
+ config->subtuples = tuple->TupleDataLen - 6;
+ return CS_SUCCESS;
+ }
+@@ -1275,7 +1266,7 @@ static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2)
+
+ v2->vers = p[0];
+ v2->comply = p[1];
+- v2->dindex = cis_get_u16(p +2 );
++ v2->dindex = get_unaligned_le16(p +2 );
+ v2->vspec8 = p[6];
+ v2->vspec9 = p[7];
+ v2->nhdr = p[8];
+@@ -1316,8 +1307,8 @@ static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
+
+ fmt->type = p[0];
+ fmt->edc = p[1];
+- fmt->offset = cis_get_u32(p + 2);
+- fmt->length = cis_get_u32(p + 6);
++ fmt->offset = get_unaligned_le32(p + 2);
++ fmt->length = get_unaligned_le32(p + 6);
+
+ return CS_SUCCESS;
+ }
+diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
+index 56230db..29276bd 100644
+--- a/drivers/pcmcia/cs.c
++++ b/drivers/pcmcia/cs.c
+@@ -652,6 +652,9 @@ static int pccardd(void *__skt)
+ complete(&skt->thread_done);
+ return 0;
+ }
++ ret = pccard_sysfs_add_socket(&skt->dev);
++ if (ret)
++ dev_warn(&skt->dev, "err %d adding socket attributes\n", ret);
+
+ add_wait_queue(&skt->thread_wait, &wait);
+ complete(&skt->thread_done);
+@@ -694,6 +697,7 @@ static int pccardd(void *__skt)
+ remove_wait_queue(&skt->thread_wait, &wait);
+
+ /* remove from the device core */
++ pccard_sysfs_remove_socket(&skt->dev);
+ device_unregister(&skt->dev);
+
+ return 0;
+@@ -940,20 +944,13 @@ EXPORT_SYMBOL(pcmcia_socket_class);
+
+ static int __init init_pcmcia_cs(void)
+ {
+- int ret;
+-
+ init_completion(&pcmcia_unload);
+- ret = class_register(&pcmcia_socket_class);
+- if (ret)
+- return (ret);
+- return class_interface_register(&pccard_sysfs_interface);
++ return class_register(&pcmcia_socket_class);
+ }
+
+ static void __exit exit_pcmcia_cs(void)
+ {
+- class_interface_unregister(&pccard_sysfs_interface);
+ class_unregister(&pcmcia_socket_class);
+-
+ wait_for_completion(&pcmcia_unload);
+ }
+
+diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
+index 9fa207e..e7d5d14 100644
+--- a/drivers/pcmcia/cs_internal.h
++++ b/drivers/pcmcia/cs_internal.h
+@@ -121,7 +121,8 @@ struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align,
+ void release_resource_db(struct pcmcia_socket *s);
+
+ /* In socket_sysfs.c */
+-extern struct class_interface pccard_sysfs_interface;
++extern int pccard_sysfs_add_socket(struct device *dev);
++extern void pccard_sysfs_remove_socket(struct device *dev);
+
+ /* In cs.c */
+ extern struct rw_semaphore pcmcia_socket_list_rwsem;
+diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
+index 27523c5..5f186ab 100644
+--- a/drivers/pcmcia/pcmcia_ioctl.c
++++ b/drivers/pcmcia/pcmcia_ioctl.c
+@@ -787,7 +787,7 @@ void __init pcmcia_setup_ioctl(void) {
+ major_dev = i;
+
+ #ifdef CONFIG_PROC_FS
+- proc_pccard = proc_mkdir("pccard", proc_bus);
++ proc_pccard = proc_mkdir("bus/pccard", NULL);
+ if (proc_pccard)
+ create_proc_read_entry("drivers",0,proc_pccard,proc_read_drivers,NULL);
+ #endif
+@@ -798,7 +798,7 @@ void __exit pcmcia_cleanup_ioctl(void) {
+ #ifdef CONFIG_PROC_FS
+ if (proc_pccard) {
+ remove_proc_entry("drivers", proc_pccard);
+- remove_proc_entry("pccard", proc_bus);
++ remove_proc_entry("bus/pccard", NULL);
+ }
+ #endif
+ if (major_dev != -1)
+diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c
+index fbf2f3a..e7ab060 100644
+--- a/drivers/pcmcia/pxa2xx_cm_x270.c
++++ b/drivers/pcmcia/pxa2xx_cm_x270.c
+@@ -20,6 +20,7 @@
+ #include <asm/hardware.h>
+
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/cm-x270.h>
+
+ #include "soc_common.h"
+diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
+index b440900..562384d 100644
+--- a/drivers/pcmcia/socket_sysfs.c
++++ b/drivers/pcmcia/socket_sysfs.c
+@@ -356,19 +356,23 @@ static ssize_t pccard_store_cis(struct kobject *kobj,
+ }
+
+
+-static struct device_attribute *pccard_socket_attributes[] = {
+- &dev_attr_card_type,
+- &dev_attr_card_voltage,
+- &dev_attr_card_vpp,
+- &dev_attr_card_vcc,
+- &dev_attr_card_insert,
+- &dev_attr_card_pm_state,
+- &dev_attr_card_eject,
+- &dev_attr_card_irq_mask,
+- &dev_attr_available_resources_setup_done,
++static struct attribute *pccard_socket_attributes[] = {
++ &dev_attr_card_type.attr,
++ &dev_attr_card_voltage.attr,
++ &dev_attr_card_vpp.attr,
++ &dev_attr_card_vcc.attr,
++ &dev_attr_card_insert.attr,
++ &dev_attr_card_pm_state.attr,
++ &dev_attr_card_eject.attr,
++ &dev_attr_card_irq_mask.attr,
++ &dev_attr_available_resources_setup_done.attr,
+ NULL,
+ };
+
++static const struct attribute_group socket_attrs = {
++ .attrs = pccard_socket_attributes,
++};
++
+ static struct bin_attribute pccard_cis_attr = {
+ .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR },
+ .size = 0x200,
+@@ -376,35 +380,21 @@ static struct bin_attribute pccard_cis_attr = {
+ .write = pccard_store_cis,
+ };
+
+-static int __devinit pccard_sysfs_add_socket(struct device *dev,
+- struct class_interface *class_intf)
++int pccard_sysfs_add_socket(struct device *dev)
+ {
+- struct device_attribute **attr;
+ int ret = 0;
+
+- for (attr = pccard_socket_attributes; *attr; attr++) {
+- ret = device_create_file(dev, *attr);
++ ret = sysfs_create_group(&dev->kobj, &socket_attrs);
++ if (!ret) {
++ ret = sysfs_create_bin_file(&dev->kobj, &pccard_cis_attr);
+ if (ret)
+- break;
++ sysfs_remove_group(&dev->kobj, &socket_attrs);
+ }
+- if (!ret)
+- ret = sysfs_create_bin_file(&dev->kobj, &pccard_cis_attr);
+-
+ return ret;
+ }
+
+-static void __devexit pccard_sysfs_remove_socket(struct device *dev,
+- struct class_interface *class_intf)
++void pccard_sysfs_remove_socket(struct device *dev)
+ {
+- struct device_attribute **attr;
+-
+ sysfs_remove_bin_file(&dev->kobj, &pccard_cis_attr);
+- for (attr = pccard_socket_attributes; *attr; attr++)
+- device_remove_file(dev, *attr);
++ sysfs_remove_group(&dev->kobj, &socket_attrs);
+ }
+-
+-struct class_interface pccard_sysfs_interface = {
+- .class = &pcmcia_socket_class,
+- .add_dev = &pccard_sysfs_add_socket,
+- .remove_dev = __devexit_p(&pccard_sysfs_remove_socket),
+-};
+diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
+index 31a633f..4fe7c58 100644
+--- a/drivers/pnp/base.h
++++ b/drivers/pnp/base.h
+@@ -1,12 +1,78 @@
+ extern spinlock_t pnp_lock;
+ void *pnp_alloc(long size);
++
++int pnp_register_protocol(struct pnp_protocol *protocol);
++void pnp_unregister_protocol(struct pnp_protocol *protocol);
++
++#define PNP_EISA_ID_MASK 0x7fffffff
++void pnp_eisa_id_to_string(u32 id, char *str);
++struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id, char *pnpid);
++struct pnp_card *pnp_alloc_card(struct pnp_protocol *, int id, char *pnpid);
++
++int pnp_add_device(struct pnp_dev *dev);
++struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id);
+ int pnp_interface_attach_device(struct pnp_dev *dev);
++
++int pnp_add_card(struct pnp_card *card);
++struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id);
++void pnp_remove_card(struct pnp_card *card);
++int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev);
++void pnp_remove_card_device(struct pnp_dev *dev);
++
++struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev);
++struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
++ int priority);
++int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
++ struct pnp_irq *data);
++int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option,
++ struct pnp_dma *data);
++int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option,
++ struct pnp_port *data);
++int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option,
++ struct pnp_mem *data);
++void pnp_init_resources(struct pnp_dev *dev);
++
+ void pnp_fixup_device(struct pnp_dev *dev);
+ void pnp_free_option(struct pnp_option *option);
+ int __pnp_add_device(struct pnp_dev *dev);
+ void __pnp_remove_device(struct pnp_dev *dev);
+
+-int pnp_check_port(struct pnp_dev * dev, int idx);
+-int pnp_check_mem(struct pnp_dev * dev, int idx);
+-int pnp_check_irq(struct pnp_dev * dev, int idx);
+-int pnp_check_dma(struct pnp_dev * dev, int idx);
++int pnp_check_port(struct pnp_dev *dev, struct resource *res);
++int pnp_check_mem(struct pnp_dev *dev, struct resource *res);
++int pnp_check_irq(struct pnp_dev *dev, struct resource *res);
++int pnp_check_dma(struct pnp_dev *dev, struct resource *res);
++
++void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc);
++
++void pnp_init_resource(struct resource *res);
++
++struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
++ unsigned int type, unsigned int num);
++
++#define PNP_MAX_PORT 40
++#define PNP_MAX_MEM 24
++#define PNP_MAX_IRQ 2
++#define PNP_MAX_DMA 2
++
++struct pnp_resource {
++ struct resource res;
++ unsigned int index; /* ISAPNP config register index */
++};
++
++struct pnp_resource_table {
++ struct pnp_resource port[PNP_MAX_PORT];
++ struct pnp_resource mem[PNP_MAX_MEM];
++ struct pnp_resource dma[PNP_MAX_DMA];
++ struct pnp_resource irq[PNP_MAX_IRQ];
++};
++
++struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
++ int flags);
++struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
++ int flags);
++struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
++ resource_size_t start,
++ resource_size_t end, int flags);
++struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
++ resource_size_t start,
++ resource_size_t end, int flags);
+diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
+index da1c990..a762a41 100644
+--- a/drivers/pnp/card.c
++++ b/drivers/pnp/card.c
+@@ -5,6 +5,7 @@
+ */
+
+ #include <linux/module.h>
++#include <linux/ctype.h>
+ #include <linux/slab.h>
+ #include <linux/pnp.h>
+ #include "base.h"
+@@ -100,19 +101,33 @@ static int card_probe(struct pnp_card *card, struct pnp_card_driver *drv)
+ * @id: pointer to a pnp_id structure
+ * @card: pointer to the desired card
+ */
+-int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card)
++struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id)
+ {
+- struct pnp_id *ptr;
++ struct pnp_id *dev_id, *ptr;
+
+- id->next = NULL;
++ dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
++ if (!dev_id)
++ return NULL;
++
++ dev_id->id[0] = id[0];
++ dev_id->id[1] = id[1];
++ dev_id->id[2] = id[2];
++ dev_id->id[3] = tolower(id[3]);
++ dev_id->id[4] = tolower(id[4]);
++ dev_id->id[5] = tolower(id[5]);
++ dev_id->id[6] = tolower(id[6]);
++ dev_id->id[7] = '\0';
++
++ dev_id->next = NULL;
+ ptr = card->id;
+ while (ptr && ptr->next)
+ ptr = ptr->next;
+ if (ptr)
+- ptr->next = id;
++ ptr->next = dev_id;
+ else
+- card->id = id;
+- return 0;
++ card->id = dev_id;
++
++ return dev_id;
+ }
+
+ static void pnp_free_card_ids(struct pnp_card *card)
+@@ -136,6 +151,31 @@ static void pnp_release_card(struct device *dmdev)
+ kfree(card);
+ }
+
++struct pnp_card *pnp_alloc_card(struct pnp_protocol *protocol, int id, char *pnpid)
++{
++ struct pnp_card *card;
++ struct pnp_id *dev_id;
++
++ card = kzalloc(sizeof(struct pnp_card), GFP_KERNEL);
++ if (!card)
++ return NULL;
++
++ card->protocol = protocol;
++ card->number = id;
++
++ card->dev.parent = &card->protocol->dev;
++ sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number,
++ card->number);
++
++ dev_id = pnp_add_card_id(card, pnpid);
++ if (!dev_id) {
++ kfree(card);
++ return NULL;
++ }
++
++ return card;
++}
++
+ static ssize_t pnp_show_card_name(struct device *dmdev,
+ struct device_attribute *attr, char *buf)
+ {
+@@ -191,9 +231,6 @@ int pnp_add_card(struct pnp_card *card)
+ int error;
+ struct list_head *pos, *temp;
+
+- sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number,
+- card->number);
+- card->dev.parent = &card->protocol->dev;
+ card->dev.bus = NULL;
+ card->dev.release = &pnp_release_card;
+ error = device_register(&card->dev);
+diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
+index 7d366ca..20771b7 100644
+--- a/drivers/pnp/core.c
++++ b/drivers/pnp/core.c
+@@ -106,18 +106,53 @@ static void pnp_release_device(struct device *dmdev)
+ pnp_free_option(dev->independent);
+ pnp_free_option(dev->dependent);
+ pnp_free_ids(dev);
++ kfree(dev->res);
+ kfree(dev);
+ }
+
+-int __pnp_add_device(struct pnp_dev *dev)
++struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid)
+ {
+- int ret;
++ struct pnp_dev *dev;
++ struct pnp_id *dev_id;
+
+- pnp_fixup_device(dev);
++ dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
++ if (!dev)
++ return NULL;
++
++ dev->res = kzalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
++ if (!dev->res) {
++ kfree(dev);
++ return NULL;
++ }
++
++ dev->protocol = protocol;
++ dev->number = id;
++ dev->dma_mask = DMA_24BIT_MASK;
++
++ dev->dev.parent = &dev->protocol->dev;
+ dev->dev.bus = &pnp_bus_type;
+ dev->dev.dma_mask = &dev->dma_mask;
+- dev->dma_mask = dev->dev.coherent_dma_mask = DMA_24BIT_MASK;
++ dev->dev.coherent_dma_mask = dev->dma_mask;
+ dev->dev.release = &pnp_release_device;
++
++ sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number,
++ dev->number);
++
++ dev_id = pnp_add_id(dev, pnpid);
++ if (!dev_id) {
++ kfree(dev->res);
++ kfree(dev);
++ return NULL;
++ }
++
++ return dev;
++}
++
++int __pnp_add_device(struct pnp_dev *dev)
++{
++ int ret;
++
++ pnp_fixup_device(dev);
+ dev->status = PNP_READY;
+ spin_lock(&pnp_lock);
+ list_add_tail(&dev->global_list, &pnp_global);
+@@ -145,9 +180,6 @@ int pnp_add_device(struct pnp_dev *dev)
+ if (dev->card)
+ return -EINVAL;
+
+- dev->dev.parent = &dev->protocol->dev;
+- sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number,
+- dev->number);
+ ret = __pnp_add_device(dev);
+ if (ret)
+ return ret;
+diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
+index 12a1645..d3f869e 100644
+--- a/drivers/pnp/driver.c
++++ b/drivers/pnp/driver.c
+@@ -167,7 +167,7 @@ static int pnp_bus_suspend(struct device *dev, pm_message_t state)
+ return error;
+ }
+
+- if (pnp_dev->protocol && pnp_dev->protocol->suspend)
++ if (pnp_dev->protocol->suspend)
+ pnp_dev->protocol->suspend(pnp_dev, state);
+ return 0;
+ }
+@@ -181,7 +181,7 @@ static int pnp_bus_resume(struct device *dev)
+ if (!pnp_drv)
+ return 0;
+
+- if (pnp_dev->protocol && pnp_dev->protocol->resume)
++ if (pnp_dev->protocol->resume)
+ pnp_dev->protocol->resume(pnp_dev);
+
+ if (pnp_can_write(pnp_dev)) {
+@@ -226,22 +226,36 @@ void pnp_unregister_driver(struct pnp_driver *drv)
+
+ /**
+ * pnp_add_id - adds an EISA id to the specified device
+- * @id: pointer to a pnp_id structure
+ * @dev: pointer to the desired device
++ * @id: pointer to an EISA id string
+ */
+-int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev)
++struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id)
+ {
+- struct pnp_id *ptr;
++ struct pnp_id *dev_id, *ptr;
+
+- id->next = NULL;
++ dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
++ if (!dev_id)
++ return NULL;
++
++ dev_id->id[0] = id[0];
++ dev_id->id[1] = id[1];
++ dev_id->id[2] = id[2];
++ dev_id->id[3] = tolower(id[3]);
++ dev_id->id[4] = tolower(id[4]);
++ dev_id->id[5] = tolower(id[5]);
++ dev_id->id[6] = tolower(id[6]);
++ dev_id->id[7] = '\0';
++
++ dev_id->next = NULL;
+ ptr = dev->id;
+ while (ptr && ptr->next)
+ ptr = ptr->next;
+ if (ptr)
+- ptr->next = id;
++ ptr->next = dev_id;
+ else
+- dev->id = id;
+- return 0;
++ dev->id = dev_id;
++
++ return dev_id;
+ }
+
+ EXPORT_SYMBOL(pnp_register_driver);
+diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
+index 9826584..5d9301d 100644
+--- a/drivers/pnp/interface.c
++++ b/drivers/pnp/interface.c
+@@ -248,6 +248,7 @@ static ssize_t pnp_show_current_resources(struct device *dmdev,
+ char *buf)
+ {
+ struct pnp_dev *dev = to_pnp_dev(dmdev);
++ struct resource *res;
+ int i, ret;
+ pnp_info_buffer_t *buffer;
+
+@@ -267,50 +268,46 @@ static ssize_t pnp_show_current_resources(struct device *dmdev,
+ else
+ pnp_printf(buffer, "disabled\n");
+
+- for (i = 0; i < PNP_MAX_PORT; i++) {
+- if (pnp_port_valid(dev, i)) {
++ for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
++ if (pnp_resource_valid(res)) {
+ pnp_printf(buffer, "io");
+- if (pnp_port_flags(dev, i) & IORESOURCE_DISABLED)
++ if (res->flags & IORESOURCE_DISABLED)
+ pnp_printf(buffer, " disabled\n");
+ else
+ pnp_printf(buffer, " 0x%llx-0x%llx\n",
+- (unsigned long long)
+- pnp_port_start(dev, i),
+- (unsigned long long)pnp_port_end(dev,
+- i));
++ (unsigned long long) res->start,
++ (unsigned long long) res->end);
+ }
+ }
+- for (i = 0; i < PNP_MAX_MEM; i++) {
+- if (pnp_mem_valid(dev, i)) {
++ for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
++ if (pnp_resource_valid(res)) {
+ pnp_printf(buffer, "mem");
+- if (pnp_mem_flags(dev, i) & IORESOURCE_DISABLED)
++ if (res->flags & IORESOURCE_DISABLED)
+ pnp_printf(buffer, " disabled\n");
+ else
+ pnp_printf(buffer, " 0x%llx-0x%llx\n",
+- (unsigned long long)
+- pnp_mem_start(dev, i),
+- (unsigned long long)pnp_mem_end(dev,
+- i));
++ (unsigned long long) res->start,
++ (unsigned long long) res->end);
+ }
+ }
+- for (i = 0; i < PNP_MAX_IRQ; i++) {
+- if (pnp_irq_valid(dev, i)) {
++ for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) {
++ if (pnp_resource_valid(res)) {
+ pnp_printf(buffer, "irq");
+- if (pnp_irq_flags(dev, i) & IORESOURCE_DISABLED)
++ if (res->flags & IORESOURCE_DISABLED)
+ pnp_printf(buffer, " disabled\n");
+ else
+ pnp_printf(buffer, " %lld\n",
+- (unsigned long long)pnp_irq(dev, i));
++ (unsigned long long) res->start);
+ }
+ }
+- for (i = 0; i < PNP_MAX_DMA; i++) {
+- if (pnp_dma_valid(dev, i)) {
++ for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) {
++ if (pnp_resource_valid(res)) {
+ pnp_printf(buffer, "dma");
+- if (pnp_dma_flags(dev, i) & IORESOURCE_DISABLED)
++ if (res->flags & IORESOURCE_DISABLED)
+ pnp_printf(buffer, " disabled\n");
+ else
+ pnp_printf(buffer, " %lld\n",
+- (unsigned long long)pnp_dma(dev, i));
++ (unsigned long long) res->start);
+ }
+ }
+ ret = (buffer->curr - buf);
+@@ -323,8 +320,10 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
+ const char *ubuf, size_t count)
+ {
+ struct pnp_dev *dev = to_pnp_dev(dmdev);
++ struct pnp_resource *pnp_res;
+ char *buf = (void *)ubuf;
+ int retval = 0;
++ resource_size_t start, end;
+
+ if (dev->status & PNP_ATTACHED) {
+ retval = -EBUSY;
+@@ -351,20 +350,20 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
+ if (!strnicmp(buf, "auto", 4)) {
+ if (dev->active)
+ goto done;
+- pnp_init_resource_table(&dev->res);
++ pnp_init_resources(dev);
+ retval = pnp_auto_config_dev(dev);
+ goto done;
+ }
+ if (!strnicmp(buf, "clear", 5)) {
+ if (dev->active)
+ goto done;
+- pnp_init_resource_table(&dev->res);
++ pnp_init_resources(dev);
+ goto done;
+ }
+ if (!strnicmp(buf, "get", 3)) {
+ mutex_lock(&pnp_res_mutex);
+ if (pnp_can_read(dev))
+- dev->protocol->get(dev, &dev->res);
++ dev->protocol->get(dev);
+ mutex_unlock(&pnp_res_mutex);
+ goto done;
+ }
+@@ -373,7 +372,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
+ if (dev->active)
+ goto done;
+ buf += 3;
+- pnp_init_resource_table(&dev->res);
++ pnp_init_resources(dev);
+ mutex_lock(&pnp_res_mutex);
+ while (1) {
+ while (isspace(*buf))
+@@ -382,76 +381,60 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
+ buf += 2;
+ while (isspace(*buf))
+ ++buf;
+- dev->res.port_resource[nport].start =
+- simple_strtoul(buf, &buf, 0);
++ start = simple_strtoul(buf, &buf, 0);
+ while (isspace(*buf))
+ ++buf;
+ if (*buf == '-') {
+ buf += 1;
+ while (isspace(*buf))
+ ++buf;
+- dev->res.port_resource[nport].end =
+- simple_strtoul(buf, &buf, 0);
++ end = simple_strtoul(buf, &buf, 0);
+ } else
+- dev->res.port_resource[nport].end =
+- dev->res.port_resource[nport].start;
+- dev->res.port_resource[nport].flags =
+- IORESOURCE_IO;
+- nport++;
+- if (nport >= PNP_MAX_PORT)
+- break;
++ end = start;
++ pnp_res = pnp_add_io_resource(dev, start, end,
++ 0);
++ if (pnp_res)
++ pnp_res->index = nport++;
+ continue;
+ }
+ if (!strnicmp(buf, "mem", 3)) {
+ buf += 3;
+ while (isspace(*buf))
+ ++buf;
+- dev->res.mem_resource[nmem].start =
+- simple_strtoul(buf, &buf, 0);
++ start = simple_strtoul(buf, &buf, 0);
+ while (isspace(*buf))
+ ++buf;
+ if (*buf == '-') {
+ buf += 1;
+ while (isspace(*buf))
+ ++buf;
+- dev->res.mem_resource[nmem].end =
+- simple_strtoul(buf, &buf, 0);
++ end = simple_strtoul(buf, &buf, 0);
+ } else
+- dev->res.mem_resource[nmem].end =
+- dev->res.mem_resource[nmem].start;
+- dev->res.mem_resource[nmem].flags =
+- IORESOURCE_MEM;
+- nmem++;
+- if (nmem >= PNP_MAX_MEM)
+- break;
++ end = start;
++ pnp_res = pnp_add_mem_resource(dev, start, end,
++ 0);
++ if (pnp_res)
++ pnp_res->index = nmem++;
+ continue;
+ }
+ if (!strnicmp(buf, "irq", 3)) {
+ buf += 3;
+ while (isspace(*buf))
+ ++buf;
+- dev->res.irq_resource[nirq].start =
+- dev->res.irq_resource[nirq].end =
+- simple_strtoul(buf, &buf, 0);
+- dev->res.irq_resource[nirq].flags =
+- IORESOURCE_IRQ;
+- nirq++;
+- if (nirq >= PNP_MAX_IRQ)
+- break;
++ start = simple_strtoul(buf, &buf, 0);
++ pnp_res = pnp_add_irq_resource(dev, start, 0);
++ if (pnp_res)
++ nirq++;
+ continue;
+ }
+ if (!strnicmp(buf, "dma", 3)) {
+ buf += 3;
+ while (isspace(*buf))
+ ++buf;
+- dev->res.dma_resource[ndma].start =
+- dev->res.dma_resource[ndma].end =
+- simple_strtoul(buf, &buf, 0);
+- dev->res.dma_resource[ndma].flags =
+- IORESOURCE_DMA;
+- ndma++;
+- if (ndma >= PNP_MAX_DMA)
+- break;
++ start = simple_strtoul(buf, &buf, 0);
++ pnp_res = pnp_add_dma_resource(dev, start, 0);
++ if (pnp_res)
++ pnp_res->index = ndma++;
+ continue;
+ }
+ break;
+diff --git a/drivers/pnp/isapnp/Makefile b/drivers/pnp/isapnp/Makefile
+index cac18bb..3e38f06 100644
+--- a/drivers/pnp/isapnp/Makefile
++++ b/drivers/pnp/isapnp/Makefile
+@@ -5,3 +5,7 @@
+ isapnp-proc-$(CONFIG_PROC_FS) = proc.o
+
+ obj-y := core.o compat.o $(isapnp-proc-y)
++
++ifeq ($(CONFIG_PNP_DEBUG),y)
++EXTRA_CFLAGS += -DDEBUG
++endif
+diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
+index 257f5d8..f1bccdb 100644
+--- a/drivers/pnp/isapnp/core.c
++++ b/drivers/pnp/isapnp/core.c
+@@ -44,6 +44,8 @@
+ #include <linux/mutex.h>
+ #include <asm/io.h>
+
++#include "../base.h"
++
+ #if 0
+ #define ISAPNP_REGION_OK
+ #endif
+@@ -88,6 +90,14 @@ MODULE_LICENSE("GPL");
+ #define _LTAG_MEM32RANGE 0x85
+ #define _LTAG_FIXEDMEM32RANGE 0x86
+
++/* Logical device control and configuration registers */
++
++#define ISAPNP_CFG_ACTIVATE 0x30 /* byte */
++#define ISAPNP_CFG_MEM 0x40 /* 4 * dword */
++#define ISAPNP_CFG_PORT 0x60 /* 8 * word */
++#define ISAPNP_CFG_IRQ 0x70 /* 2 * word */
++#define ISAPNP_CFG_DMA 0x74 /* 2 * byte */
++
+ /*
+ * Sizes of ISAPNP logical device configuration register sets.
+ * See PNP-ISA-v1.0a.pdf, Appendix A.
+@@ -388,28 +398,6 @@ static void __init isapnp_skip_bytes(int count)
+ }
+
+ /*
+- * Parse EISA id.
+- */
+-static void isapnp_parse_id(struct pnp_dev *dev, unsigned short vendor,
+- unsigned short device)
+-{
+- struct pnp_id *id;
+-
+- if (!dev)
+- return;
+- id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
+- if (!id)
+- return;
+- sprintf(id->id, "%c%c%c%x%x%x%x",
+- 'A' + ((vendor >> 2) & 0x3f) - 1,
+- 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
+- 'A' + ((vendor >> 8) & 0x1f) - 1,
+- (device >> 4) & 0x0f,
+- device & 0x0f, (device >> 12) & 0x0f, (device >> 8) & 0x0f);
+- pnp_add_id(id, dev);
+-}
+-
+-/*
+ * Parse logical device tag.
+ */
+ static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card,
+@@ -417,30 +405,31 @@ static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card,
+ {
+ unsigned char tmp[6];
+ struct pnp_dev *dev;
++ u32 eisa_id;
++ char id[8];
+
+ isapnp_peek(tmp, size);
+- dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
++ eisa_id = tmp[0] | tmp[1] << 8 | tmp[2] << 16 | tmp[3] << 24;
++ pnp_eisa_id_to_string(eisa_id, id);
++
++ dev = pnp_alloc_dev(&isapnp_protocol, number, id);
+ if (!dev)
+ return NULL;
+- dev->number = number;
+- isapnp_parse_id(dev, (tmp[1] << 8) | tmp[0], (tmp[3] << 8) | tmp[2]);
+- dev->regs = tmp[4];
++
+ dev->card = card;
+- if (size > 5)
+- dev->regs |= tmp[5] << 8;
+- dev->protocol = &isapnp_protocol;
+ dev->capabilities |= PNP_CONFIGURABLE;
+ dev->capabilities |= PNP_READ;
+ dev->capabilities |= PNP_WRITE;
+ dev->capabilities |= PNP_DISABLE;
+- pnp_init_resource_table(&dev->res);
++ pnp_init_resources(dev);
+ return dev;
+ }
+
+ /*
+ * Add IRQ resource to resources list.
+ */
+-static void __init isapnp_parse_irq_resource(struct pnp_option *option,
++static void __init isapnp_parse_irq_resource(struct pnp_dev *dev,
++ struct pnp_option *option,
+ int size)
+ {
+ unsigned char tmp[3];
+@@ -457,13 +446,14 @@ static void __init isapnp_parse_irq_resource(struct pnp_option *option,
+ irq->flags = tmp[2];
+ else
+ irq->flags = IORESOURCE_IRQ_HIGHEDGE;
+- pnp_register_irq_resource(option, irq);
++ pnp_register_irq_resource(dev, option, irq);
+ }
+
+ /*
+ * Add DMA resource to resources list.
+ */
+-static void __init isapnp_parse_dma_resource(struct pnp_option *option,
++static void __init isapnp_parse_dma_resource(struct pnp_dev *dev,
++ struct pnp_option *option,
+ int size)
+ {
+ unsigned char tmp[2];
+@@ -475,13 +465,14 @@ static void __init isapnp_parse_dma_resource(struct pnp_option *option,
+ return;
+ dma->map = tmp[0];
+ dma->flags = tmp[1];
+- pnp_register_dma_resource(option, dma);
++ pnp_register_dma_resource(dev, option, dma);
+ }
+
+ /*
+ * Add port resource to resources list.
+ */
+-static void __init isapnp_parse_port_resource(struct pnp_option *option,
++static void __init isapnp_parse_port_resource(struct pnp_dev *dev,
++ struct pnp_option *option,
+ int size)
+ {
+ unsigned char tmp[7];
+@@ -496,13 +487,14 @@ static void __init isapnp_parse_port_resource(struct pnp_option *option,
+ port->align = tmp[5];
+ port->size = tmp[6];
+ port->flags = tmp[0] ? PNP_PORT_FLAG_16BITADDR : 0;
+- pnp_register_port_resource(option, port);
++ pnp_register_port_resource(dev, option, port);
+ }
+
+ /*
+ * Add fixed port resource to resources list.
+ */
+-static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option,
++static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev,
++ struct pnp_option *option,
+ int size)
+ {
+ unsigned char tmp[3];
+@@ -516,13 +508,14 @@ static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option,
+ port->size = tmp[2];
+ port->align = 0;
+ port->flags = PNP_PORT_FLAG_FIXED;
+- pnp_register_port_resource(option, port);
++ pnp_register_port_resource(dev, option, port);
+ }
+
+ /*
+ * Add memory resource to resources list.
+ */
+-static void __init isapnp_parse_mem_resource(struct pnp_option *option,
++static void __init isapnp_parse_mem_resource(struct pnp_dev *dev,
++ struct pnp_option *option,
+ int size)
+ {
+ unsigned char tmp[9];
+@@ -537,13 +530,14 @@ static void __init isapnp_parse_mem_resource(struct pnp_option *option,
+ mem->align = (tmp[6] << 8) | tmp[5];
+ mem->size = ((tmp[8] << 8) | tmp[7]) << 8;
+ mem->flags = tmp[0];
+- pnp_register_mem_resource(option, mem);
++ pnp_register_mem_resource(dev, option, mem);
+ }
+
+ /*
+ * Add 32-bit memory resource to resources list.
+ */
+-static void __init isapnp_parse_mem32_resource(struct pnp_option *option,
++static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev,
++ struct pnp_option *option,
+ int size)
+ {
+ unsigned char tmp[17];
+@@ -560,13 +554,14 @@ static void __init isapnp_parse_mem32_resource(struct pnp_option *option,
+ mem->size =
+ (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13];
+ mem->flags = tmp[0];
+- pnp_register_mem_resource(option, mem);
++ pnp_register_mem_resource(dev, option, mem);
+ }
+
+ /*
+ * Add 32-bit fixed memory resource to resources list.
+ */
+-static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option,
++static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev,
++ struct pnp_option *option,
+ int size)
+ {
+ unsigned char tmp[9];
+@@ -581,7 +576,7 @@ static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option,
+ mem->size = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
+ mem->align = 0;
+ mem->flags = tmp[0];
+- pnp_register_mem_resource(option, mem);
++ pnp_register_mem_resource(dev, option, mem);
+ }
+
+ /*
+@@ -613,6 +608,8 @@ static int __init isapnp_create_device(struct pnp_card *card,
+ unsigned char type, tmp[17];
+ struct pnp_option *option;
+ struct pnp_dev *dev;
++ u32 eisa_id;
++ char id[8];
+
+ if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
+ return 1;
+@@ -652,8 +649,10 @@ static int __init isapnp_create_device(struct pnp_card *card,
+ case _STAG_COMPATDEVID:
+ if (size == 4 && compat < DEVICE_COUNT_COMPATIBLE) {
+ isapnp_peek(tmp, 4);
+- isapnp_parse_id(dev, (tmp[1] << 8) | tmp[0],
+- (tmp[3] << 8) | tmp[2]);
++ eisa_id = tmp[0] | tmp[1] << 8 |
++ tmp[2] << 16 | tmp[3] << 24;
++ pnp_eisa_id_to_string(eisa_id, id);
++ pnp_add_id(dev, id);
+ compat++;
+ size = 0;
+ }
+@@ -661,13 +660,13 @@ static int __init isapnp_create_device(struct pnp_card *card,
+ case _STAG_IRQ:
+ if (size < 2 || size > 3)
+ goto __skip;
+- isapnp_parse_irq_resource(option, size);
++ isapnp_parse_irq_resource(dev, option, size);
+ size = 0;
+ break;
+ case _STAG_DMA:
+ if (size != 2)
+ goto __skip;
+- isapnp_parse_dma_resource(option, size);
++ isapnp_parse_dma_resource(dev, option, size);
+ size = 0;
+ break;
+ case _STAG_STARTDEP:
+@@ -687,17 +686,18 @@ static int __init isapnp_create_device(struct pnp_card *card,
+ if (size != 0)
+ goto __skip;
+ priority = 0;
++ dev_dbg(&dev->dev, "end dependent options\n");
+ break;
+ case _STAG_IOPORT:
+ if (size != 7)
+ goto __skip;
+- isapnp_parse_port_resource(option, size);
++ isapnp_parse_port_resource(dev, option, size);
+ size = 0;
+ break;
+ case _STAG_FIXEDIO:
+ if (size != 3)
+ goto __skip;
+- isapnp_parse_fixed_port_resource(option, size);
++ isapnp_parse_fixed_port_resource(dev, option, size);
+ size = 0;
+ break;
+ case _STAG_VENDOR:
+@@ -705,7 +705,7 @@ static int __init isapnp_create_device(struct pnp_card *card,
+ case _LTAG_MEMRANGE:
+ if (size != 9)
+ goto __skip;
+- isapnp_parse_mem_resource(option, size);
++ isapnp_parse_mem_resource(dev, option, size);
+ size = 0;
+ break;
+ case _LTAG_ANSISTR:
+@@ -720,13 +720,13 @@ static int __init isapnp_create_device(struct pnp_card *card,
+ case _LTAG_MEM32RANGE:
+ if (size != 17)
+ goto __skip;
+- isapnp_parse_mem32_resource(option, size);
++ isapnp_parse_mem32_resource(dev, option, size);
+ size = 0;
+ break;
+ case _LTAG_FIXEDMEM32RANGE:
+ if (size != 9)
+ goto __skip;
+- isapnp_parse_fixed_mem32_resource(option, size);
++ isapnp_parse_fixed_mem32_resource(dev, option, size);
+ size = 0;
+ break;
+ case _STAG_END:
+@@ -734,9 +734,8 @@ static int __init isapnp_create_device(struct pnp_card *card,
+ isapnp_skip_bytes(size);
+ return 1;
+ default:
+- printk(KERN_ERR
+- "isapnp: unexpected or unknown tag type 0x%x for logical device %i (device %i), ignored\n",
+- type, dev->number, card->number);
++ dev_err(&dev->dev, "unknown tag %#x (card %i), "
++ "ignored\n", type, card->number);
+ }
+ __skip:
+ if (size > 0)
+@@ -789,9 +788,8 @@ static void __init isapnp_parse_resource_map(struct pnp_card *card)
+ isapnp_skip_bytes(size);
+ return;
+ default:
+- printk(KERN_ERR
+- "isapnp: unexpected or unknown tag type 0x%x for device %i, ignored\n",
+- type, card->number);
++ dev_err(&card->dev, "unknown tag %#x, ignored\n",
++ type);
+ }
+ __skip:
+ if (size > 0)
+@@ -822,25 +820,6 @@ static unsigned char __init isapnp_checksum(unsigned char *data)
+ }
+
+ /*
+- * Parse EISA id for ISA PnP card.
+- */
+-static void isapnp_parse_card_id(struct pnp_card *card, unsigned short vendor,
+- unsigned short device)
+-{
+- struct pnp_id *id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
+-
+- if (!id)
+- return;
+- sprintf(id->id, "%c%c%c%x%x%x%x",
+- 'A' + ((vendor >> 2) & 0x3f) - 1,
+- 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
+- 'A' + ((vendor >> 8) & 0x1f) - 1,
+- (device >> 4) & 0x0f,
+- device & 0x0f, (device >> 12) & 0x0f, (device >> 8) & 0x0f);
+- pnp_add_card_id(id, card);
+-}
+-
+-/*
+ * Build device list for all present ISA PnP devices.
+ */
+ static int __init isapnp_build_device_list(void)
+@@ -848,6 +827,8 @@ static int __init isapnp_build_device_list(void)
+ int csn;
+ unsigned char header[9], checksum;
+ struct pnp_card *card;
++ u32 eisa_id;
++ char id[8];
+
+ isapnp_wait();
+ isapnp_key();
+@@ -855,32 +836,30 @@ static int __init isapnp_build_device_list(void)
+ isapnp_wake(csn);
+ isapnp_peek(header, 9);
+ checksum = isapnp_checksum(header);
++ eisa_id = header[0] | header[1] << 8 |
++ header[2] << 16 | header[3] << 24;
++ pnp_eisa_id_to_string(eisa_id, id);
++ card = pnp_alloc_card(&isapnp_protocol, csn, id);
++ if (!card)
++ continue;
++
+ #if 0
+- printk(KERN_DEBUG
++ dev_info(&card->dev,
+ "vendor: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ header[0], header[1], header[2], header[3], header[4],
+ header[5], header[6], header[7], header[8]);
+- printk(KERN_DEBUG "checksum = 0x%x\n", checksum);
++ dev_info(&card->dev, "checksum = %#x\n", checksum);
+ #endif
+- if ((card =
+- kzalloc(sizeof(struct pnp_card), GFP_KERNEL)) == NULL)
+- continue;
+-
+- card->number = csn;
+ INIT_LIST_HEAD(&card->devices);
+- isapnp_parse_card_id(card, (header[1] << 8) | header[0],
+- (header[3] << 8) | header[2]);
+ card->serial =
+ (header[7] << 24) | (header[6] << 16) | (header[5] << 8) |
+ header[4];
+ isapnp_checksum_value = 0x00;
+ isapnp_parse_resource_map(card);
+ if (isapnp_checksum_value != 0x00)
+- printk(KERN_ERR
+- "isapnp: checksum for device %i is not valid (0x%x)\n",
+- csn, isapnp_checksum_value);
++ dev_err(&card->dev, "invalid checksum %#x\n",
++ isapnp_checksum_value);
+ card->checksum = isapnp_checksum_value;
+- card->protocol = &isapnp_protocol;
+
+ pnp_add_card(card);
+ }
+@@ -947,100 +926,117 @@ EXPORT_SYMBOL(isapnp_cfg_begin);
+ EXPORT_SYMBOL(isapnp_cfg_end);
+ EXPORT_SYMBOL(isapnp_write_byte);
+
+-static int isapnp_read_resources(struct pnp_dev *dev,
+- struct pnp_resource_table *res)
++static int isapnp_get_resources(struct pnp_dev *dev)
+ {
+- int tmp, ret;
++ struct pnp_resource *pnp_res;
++ int i, ret;
+
++ dev_dbg(&dev->dev, "get resources\n");
++ pnp_init_resources(dev);
++ isapnp_cfg_begin(dev->card->number, dev->number);
+ dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE);
+- if (dev->active) {
+- for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) {
+- ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1));
+- if (!ret)
+- continue;
+- res->port_resource[tmp].start = ret;
+- res->port_resource[tmp].flags = IORESOURCE_IO;
++ if (!dev->active)
++ goto __end;
++
++ for (i = 0; i < ISAPNP_MAX_PORT; i++) {
++ ret = isapnp_read_word(ISAPNP_CFG_PORT + (i << 1));
++ if (ret) {
++ pnp_res = pnp_add_io_resource(dev, ret, ret, 0);
++ if (pnp_res)
++ pnp_res->index = i;
+ }
+- for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) {
+- ret =
+- isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8;
+- if (!ret)
+- continue;
+- res->mem_resource[tmp].start = ret;
+- res->mem_resource[tmp].flags = IORESOURCE_MEM;
++ }
++ for (i = 0; i < ISAPNP_MAX_MEM; i++) {
++ ret = isapnp_read_word(ISAPNP_CFG_MEM + (i << 3)) << 8;
++ if (ret) {
++ pnp_res = pnp_add_mem_resource(dev, ret, ret, 0);
++ if (pnp_res)
++ pnp_res->index = i;
+ }
+- for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) {
+- ret =
+- (isapnp_read_word(ISAPNP_CFG_IRQ + (tmp << 1)) >>
+- 8);
+- if (!ret)
+- continue;
+- res->irq_resource[tmp].start =
+- res->irq_resource[tmp].end = ret;
+- res->irq_resource[tmp].flags = IORESOURCE_IRQ;
++ }
++ for (i = 0; i < ISAPNP_MAX_IRQ; i++) {
++ ret = isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1)) >> 8;
++ if (ret) {
++ pnp_res = pnp_add_irq_resource(dev, ret, 0);
++ if (pnp_res)
++ pnp_res->index = i;
+ }
+- for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) {
+- ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp);
+- if (ret == 4)
+- continue;
+- res->dma_resource[tmp].start =
+- res->dma_resource[tmp].end = ret;
+- res->dma_resource[tmp].flags = IORESOURCE_DMA;
++ }
++ for (i = 0; i < ISAPNP_MAX_DMA; i++) {
++ ret = isapnp_read_byte(ISAPNP_CFG_DMA + i);
++ if (ret != 4) {
++ pnp_res = pnp_add_dma_resource(dev, ret, 0);
++ if (pnp_res)
++ pnp_res->index = i;
+ }
+ }
+- return 0;
+-}
+-
+-static int isapnp_get_resources(struct pnp_dev *dev,
+- struct pnp_resource_table *res)
+-{
+- int ret;
+
+- pnp_init_resource_table(res);
+- isapnp_cfg_begin(dev->card->number, dev->number);
+- ret = isapnp_read_resources(dev, res);
++__end:
+ isapnp_cfg_end();
+- return ret;
++ return 0;
+ }
+
+-static int isapnp_set_resources(struct pnp_dev *dev,
+- struct pnp_resource_table *res)
++static int isapnp_set_resources(struct pnp_dev *dev)
+ {
+- int tmp;
++ struct pnp_resource *pnp_res;
++ struct resource *res;
++ int tmp, index;
+
++ dev_dbg(&dev->dev, "set resources\n");
+ isapnp_cfg_begin(dev->card->number, dev->number);
+ dev->active = 1;
+- for (tmp = 0;
+- tmp < ISAPNP_MAX_PORT
+- && (res->port_resource[tmp].
+- flags & (IORESOURCE_IO | IORESOURCE_UNSET)) == IORESOURCE_IO;
+- tmp++)
+- isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1),
+- res->port_resource[tmp].start);
+- for (tmp = 0;
+- tmp < ISAPNP_MAX_IRQ
+- && (res->irq_resource[tmp].
+- flags & (IORESOURCE_IRQ | IORESOURCE_UNSET)) == IORESOURCE_IRQ;
+- tmp++) {
+- int irq = res->irq_resource[tmp].start;
+- if (irq == 2)
+- irq = 9;
+- isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq);
++ for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) {
++ pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, tmp);
++ if (!pnp_res)
++ continue;
++ res = &pnp_res->res;
++ if (pnp_resource_valid(res)) {
++ index = pnp_res->index;
++ dev_dbg(&dev->dev, " set io %d to %#llx\n",
++ index, (unsigned long long) res->start);
++ isapnp_write_word(ISAPNP_CFG_PORT + (index << 1),
++ res->start);
++ }
++ }
++ for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) {
++ pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, tmp);
++ if (!pnp_res)
++ continue;
++ res = &pnp_res->res;
++ if (pnp_resource_valid(res)) {
++ int irq = res->start;
++ if (irq == 2)
++ irq = 9;
++ index = pnp_res->index;
++ dev_dbg(&dev->dev, " set irq %d to %d\n", index, irq);
++ isapnp_write_byte(ISAPNP_CFG_IRQ + (index << 1), irq);
++ }
++ }
++ for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) {
++ pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, tmp);
++ if (!pnp_res)
++ continue;
++ res = &pnp_res->res;
++ if (pnp_resource_valid(res)) {
++ index = pnp_res->index;
++ dev_dbg(&dev->dev, " set dma %d to %lld\n",
++ index, (unsigned long long) res->start);
++ isapnp_write_byte(ISAPNP_CFG_DMA + index, res->start);
++ }
++ }
++ for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) {
++ pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, tmp);
++ if (!pnp_res)
++ continue;
++ res = &pnp_res->res;
++ if (pnp_resource_valid(res)) {
++ index = pnp_res->index;
++ dev_dbg(&dev->dev, " set mem %d to %#llx\n",
++ index, (unsigned long long) res->start);
++ isapnp_write_word(ISAPNP_CFG_MEM + (index << 3),
++ (res->start >> 8) & 0xffff);
++ }
+ }
+- for (tmp = 0;
+- tmp < ISAPNP_MAX_DMA
+- && (res->dma_resource[tmp].
+- flags & (IORESOURCE_DMA | IORESOURCE_UNSET)) == IORESOURCE_DMA;
+- tmp++)
+- isapnp_write_byte(ISAPNP_CFG_DMA + tmp,
+- res->dma_resource[tmp].start);
+- for (tmp = 0;
+- tmp < ISAPNP_MAX_MEM
+- && (res->mem_resource[tmp].
+- flags & (IORESOURCE_MEM | IORESOURCE_UNSET)) == IORESOURCE_MEM;
+- tmp++)
+- isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3),
+- (res->mem_resource[tmp].start >> 8) & 0xffff);
+ /* FIXME: We aren't handling 32bit mems properly here */
+ isapnp_activate(dev->number);
+ isapnp_cfg_end();
+@@ -1138,13 +1134,13 @@ static int __init isapnp_init(void)
+ protocol_for_each_card(&isapnp_protocol, card) {
+ cards++;
+ if (isapnp_verbose) {
+- printk(KERN_INFO "isapnp: Card '%s'\n",
+- card->name[0] ? card->name : "Unknown");
++ dev_info(&card->dev, "card '%s'\n",
++ card->name[0] ? card->name : "unknown");
+ if (isapnp_verbose < 2)
+ continue;
+ card_for_each_dev(card, dev) {
+- printk(KERN_INFO "isapnp: Device '%s'\n",
+- dev->name[0] ? dev->name : "Unknown");
++ dev_info(&card->dev, "device '%s'\n",
++ dev->name[0] ? dev->name : "unknown");
+ }
+ }
+ }
+diff --git a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c
+index 2b8266c..3f94eda 100644
+--- a/drivers/pnp/isapnp/proc.c
++++ b/drivers/pnp/isapnp/proc.c
+@@ -85,6 +85,7 @@ static ssize_t isapnp_proc_bus_read(struct file *file, char __user * buf,
+ }
+
+ static const struct file_operations isapnp_proc_bus_file_operations = {
++ .owner = THIS_MODULE,
+ .llseek = isapnp_proc_bus_lseek,
+ .read = isapnp_proc_bus_read,
+ };
+@@ -102,12 +103,10 @@ static int isapnp_proc_attach_device(struct pnp_dev *dev)
+ return -ENOMEM;
+ }
+ sprintf(name, "%02x", dev->number);
+- e = dev->procent = create_proc_entry(name, S_IFREG | S_IRUGO, de);
++ e = dev->procent = proc_create_data(name, S_IFREG | S_IRUGO, de,
++ &isapnp_proc_bus_file_operations, dev);
+ if (!e)
+ return -ENOMEM;
+- e->proc_fops = &isapnp_proc_bus_file_operations;
+- e->owner = THIS_MODULE;
+- e->data = dev;
+ e->size = 256;
+ return 0;
+ }
+@@ -116,7 +115,7 @@ int __init isapnp_proc_init(void)
+ {
+ struct pnp_dev *dev;
+
+- isapnp_proc_bus_dir = proc_mkdir("isapnp", proc_bus);
++ isapnp_proc_bus_dir = proc_mkdir("bus/isapnp", NULL);
+ protocol_for_each_dev(&isapnp_protocol, dev) {
+ isapnp_proc_attach_device(dev);
+ }
+diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
+index c28caf2..bea0914 100644
+--- a/drivers/pnp/manager.c
++++ b/drivers/pnp/manager.c
+@@ -19,100 +19,118 @@ DEFINE_MUTEX(pnp_res_mutex);
+
+ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
+ {
+- resource_size_t *start, *end;
+- unsigned long *flags;
++ struct pnp_resource *pnp_res;
++ struct resource *res;
+
+- if (idx >= PNP_MAX_PORT) {
++ pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, idx);
++ if (!pnp_res) {
+ dev_err(&dev->dev, "too many I/O port resources\n");
+ /* pretend we were successful so at least the manager won't try again */
+ return 1;
+ }
+
++ res = &pnp_res->res;
++
+ /* check if this resource has been manually set, if so skip */
+- if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO))
++ if (!(res->flags & IORESOURCE_AUTO)) {
++ dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx "
++ "flags %#lx\n", idx, (unsigned long long) res->start,
++ (unsigned long long) res->end, res->flags);
+ return 1;
+-
+- start = &dev->res.port_resource[idx].start;
+- end = &dev->res.port_resource[idx].end;
+- flags = &dev->res.port_resource[idx].flags;
++ }
+
+ /* set the initial values */
+- *flags |= rule->flags | IORESOURCE_IO;
+- *flags &= ~IORESOURCE_UNSET;
++ pnp_res->index = idx;
++ res->flags |= rule->flags | IORESOURCE_IO;
++ res->flags &= ~IORESOURCE_UNSET;
+
+ if (!rule->size) {
+- *flags |= IORESOURCE_DISABLED;
++ res->flags |= IORESOURCE_DISABLED;
++ dev_dbg(&dev->dev, " io %d disabled\n", idx);
+ return 1; /* skip disabled resource requests */
+ }
+
+- *start = rule->min;
+- *end = *start + rule->size - 1;
++ res->start = rule->min;
++ res->end = res->start + rule->size - 1;
+
+ /* run through until pnp_check_port is happy */
+- while (!pnp_check_port(dev, idx)) {
+- *start += rule->align;
+- *end = *start + rule->size - 1;
+- if (*start > rule->max || !rule->align)
++ while (!pnp_check_port(dev, res)) {
++ res->start += rule->align;
++ res->end = res->start + rule->size - 1;
++ if (res->start > rule->max || !rule->align) {
++ dev_dbg(&dev->dev, " couldn't assign io %d\n", idx);
+ return 0;
++ }
+ }
++ dev_dbg(&dev->dev, " assign io %d %#llx-%#llx\n", idx,
++ (unsigned long long) res->start, (unsigned long long) res->end);
+ return 1;
+ }
+
+ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
+ {
+- resource_size_t *start, *end;
+- unsigned long *flags;
++ struct pnp_resource *pnp_res;
++ struct resource *res;
+
+- if (idx >= PNP_MAX_MEM) {
++ pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, idx);
++ if (!pnp_res) {
+ dev_err(&dev->dev, "too many memory resources\n");
+ /* pretend we were successful so at least the manager won't try again */
+ return 1;
+ }
+
++ res = &pnp_res->res;
++
+ /* check if this resource has been manually set, if so skip */
+- if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO))
++ if (!(res->flags & IORESOURCE_AUTO)) {
++ dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx "
++ "flags %#lx\n", idx, (unsigned long long) res->start,
++ (unsigned long long) res->end, res->flags);
+ return 1;
+-
+- start = &dev->res.mem_resource[idx].start;
+- end = &dev->res.mem_resource[idx].end;
+- flags = &dev->res.mem_resource[idx].flags;
++ }
+
+ /* set the initial values */
+- *flags |= rule->flags | IORESOURCE_MEM;
+- *flags &= ~IORESOURCE_UNSET;
++ pnp_res->index = idx;
++ res->flags |= rule->flags | IORESOURCE_MEM;
++ res->flags &= ~IORESOURCE_UNSET;
+
+ /* convert pnp flags to standard Linux flags */
+ if (!(rule->flags & IORESOURCE_MEM_WRITEABLE))
+- *flags |= IORESOURCE_READONLY;
++ res->flags |= IORESOURCE_READONLY;
+ if (rule->flags & IORESOURCE_MEM_CACHEABLE)
+- *flags |= IORESOURCE_CACHEABLE;
++ res->flags |= IORESOURCE_CACHEABLE;
+ if (rule->flags & IORESOURCE_MEM_RANGELENGTH)
+- *flags |= IORESOURCE_RANGELENGTH;
++ res->flags |= IORESOURCE_RANGELENGTH;
+ if (rule->flags & IORESOURCE_MEM_SHADOWABLE)
+- *flags |= IORESOURCE_SHADOWABLE;
++ res->flags |= IORESOURCE_SHADOWABLE;
+
+ if (!rule->size) {
+- *flags |= IORESOURCE_DISABLED;
++ res->flags |= IORESOURCE_DISABLED;
++ dev_dbg(&dev->dev, " mem %d disabled\n", idx);
+ return 1; /* skip disabled resource requests */
+ }
+
+- *start = rule->min;
+- *end = *start + rule->size - 1;
++ res->start = rule->min;
++ res->end = res->start + rule->size - 1;
+
+ /* run through until pnp_check_mem is happy */
+- while (!pnp_check_mem(dev, idx)) {
+- *start += rule->align;
+- *end = *start + rule->size - 1;
+- if (*start > rule->max || !rule->align)
++ while (!pnp_check_mem(dev, res)) {
++ res->start += rule->align;
++ res->end = res->start + rule->size - 1;
++ if (res->start > rule->max || !rule->align) {
++ dev_dbg(&dev->dev, " couldn't assign mem %d\n", idx);
+ return 0;
++ }
+ }
++ dev_dbg(&dev->dev, " assign mem %d %#llx-%#llx\n", idx,
++ (unsigned long long) res->start, (unsigned long long) res->end);
+ return 1;
+ }
+
+ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
+ {
+- resource_size_t *start, *end;
+- unsigned long *flags;
++ struct pnp_resource *pnp_res;
++ struct resource *res;
+ int i;
+
+ /* IRQ priority: this table is good for i386 */
+@@ -120,49 +138,59 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
+ 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
+ };
+
+- if (idx >= PNP_MAX_IRQ) {
++ pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, idx);
++ if (!pnp_res) {
+ dev_err(&dev->dev, "too many IRQ resources\n");
+ /* pretend we were successful so at least the manager won't try again */
+ return 1;
+ }
+
++ res = &pnp_res->res;
++
+ /* check if this resource has been manually set, if so skip */
+- if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO))
++ if (!(res->flags & IORESOURCE_AUTO)) {
++ dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n",
++ idx, (int) res->start, res->flags);
+ return 1;
+-
+- start = &dev->res.irq_resource[idx].start;
+- end = &dev->res.irq_resource[idx].end;
+- flags = &dev->res.irq_resource[idx].flags;
++ }
+
+ /* set the initial values */
+- *flags |= rule->flags | IORESOURCE_IRQ;
+- *flags &= ~IORESOURCE_UNSET;
++ pnp_res->index = idx;
++ res->flags |= rule->flags | IORESOURCE_IRQ;
++ res->flags &= ~IORESOURCE_UNSET;
+
+ if (bitmap_empty(rule->map, PNP_IRQ_NR)) {
+- *flags |= IORESOURCE_DISABLED;
++ res->flags |= IORESOURCE_DISABLED;
++ dev_dbg(&dev->dev, " irq %d disabled\n", idx);
+ return 1; /* skip disabled resource requests */
+ }
+
+ /* TBD: need check for >16 IRQ */
+- *start = find_next_bit(rule->map, PNP_IRQ_NR, 16);
+- if (*start < PNP_IRQ_NR) {
+- *end = *start;
++ res->start = find_next_bit(rule->map, PNP_IRQ_NR, 16);
++ if (res->start < PNP_IRQ_NR) {
++ res->end = res->start;
++ dev_dbg(&dev->dev, " assign irq %d %d\n", idx,
++ (int) res->start);
+ return 1;
+ }
+ for (i = 0; i < 16; i++) {
+ if (test_bit(xtab[i], rule->map)) {
+- *start = *end = xtab[i];
+- if (pnp_check_irq(dev, idx))
++ res->start = res->end = xtab[i];
++ if (pnp_check_irq(dev, res)) {
++ dev_dbg(&dev->dev, " assign irq %d %d\n", idx,
++ (int) res->start);
+ return 1;
++ }
+ }
+ }
++ dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx);
+ return 0;
+ }
+
+ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
+ {
+- resource_size_t *start, *end;
+- unsigned long *flags;
++ struct pnp_resource *pnp_res;
++ struct resource *res;
+ int i;
+
+ /* DMA priority: this table is good for i386 */
+@@ -170,71 +198,89 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
+ 1, 3, 5, 6, 7, 0, 2, 4
+ };
+
+- if (idx >= PNP_MAX_DMA) {
++ pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, idx);
++ if (!pnp_res) {
+ dev_err(&dev->dev, "too many DMA resources\n");
+ return;
+ }
+
++ res = &pnp_res->res;
++
+ /* check if this resource has been manually set, if so skip */
+- if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO))
++ if (!(res->flags & IORESOURCE_AUTO)) {
++ dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n",
++ idx, (int) res->start, res->flags);
+ return;
+-
+- start = &dev->res.dma_resource[idx].start;
+- end = &dev->res.dma_resource[idx].end;
+- flags = &dev->res.dma_resource[idx].flags;
++ }
+
+ /* set the initial values */
+- *flags |= rule->flags | IORESOURCE_DMA;
+- *flags &= ~IORESOURCE_UNSET;
++ pnp_res->index = idx;
++ res->flags |= rule->flags | IORESOURCE_DMA;
++ res->flags &= ~IORESOURCE_UNSET;
+
+ for (i = 0; i < 8; i++) {
+ if (rule->map & (1 << xtab[i])) {
+- *start = *end = xtab[i];
+- if (pnp_check_dma(dev, idx))
++ res->start = res->end = xtab[i];
++ if (pnp_check_dma(dev, res)) {
++ dev_dbg(&dev->dev, " assign dma %d %d\n", idx,
++ (int) res->start);
+ return;
++ }
+ }
+ }
+ #ifdef MAX_DMA_CHANNELS
+- *start = *end = MAX_DMA_CHANNELS;
++ res->start = res->end = MAX_DMA_CHANNELS;
+ #endif
+- *flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
++ res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
++ dev_dbg(&dev->dev, " disable dma %d\n", idx);
++}
++
++void pnp_init_resource(struct resource *res)
++{
++ unsigned long type;
++
++ type = res->flags & (IORESOURCE_IO | IORESOURCE_MEM |
++ IORESOURCE_IRQ | IORESOURCE_DMA);
++
++ res->name = NULL;
++ res->flags = type | IORESOURCE_AUTO | IORESOURCE_UNSET;
++ if (type == IORESOURCE_IRQ || type == IORESOURCE_DMA) {
++ res->start = -1;
++ res->end = -1;
++ } else {
++ res->start = 0;
++ res->end = 0;
++ }
+ }
+
+ /**
+ * pnp_init_resources - Resets a resource table to default values.
+ * @table: pointer to the desired resource table
+ */
+-void pnp_init_resource_table(struct pnp_resource_table *table)
++void pnp_init_resources(struct pnp_dev *dev)
+ {
++ struct resource *res;
+ int idx;
+
+ for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
+- table->irq_resource[idx].name = NULL;
+- table->irq_resource[idx].start = -1;
+- table->irq_resource[idx].end = -1;
+- table->irq_resource[idx].flags =
+- IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET;
++ res = &dev->res->irq[idx].res;
++ res->flags = IORESOURCE_IRQ;
++ pnp_init_resource(res);
+ }
+ for (idx = 0; idx < PNP_MAX_DMA; idx++) {
+- table->dma_resource[idx].name = NULL;
+- table->dma_resource[idx].start = -1;
+- table->dma_resource[idx].end = -1;
+- table->dma_resource[idx].flags =
+- IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET;
++ res = &dev->res->dma[idx].res;
++ res->flags = IORESOURCE_DMA;
++ pnp_init_resource(res);
+ }
+ for (idx = 0; idx < PNP_MAX_PORT; idx++) {
+- table->port_resource[idx].name = NULL;
+- table->port_resource[idx].start = 0;
+- table->port_resource[idx].end = 0;
+- table->port_resource[idx].flags =
+- IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET;
++ res = &dev->res->port[idx].res;
++ res->flags = IORESOURCE_IO;
++ pnp_init_resource(res);
+ }
+ for (idx = 0; idx < PNP_MAX_MEM; idx++) {
+- table->mem_resource[idx].name = NULL;
+- table->mem_resource[idx].start = 0;
+- table->mem_resource[idx].end = 0;
+- table->mem_resource[idx].flags =
+- IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET;
++ res = &dev->res->mem[idx].res;
++ res->flags = IORESOURCE_MEM;
++ pnp_init_resource(res);
+ }
+ }
+
+@@ -242,41 +288,38 @@ void pnp_init_resource_table(struct pnp_resource_table *table)
+ * pnp_clean_resources - clears resources that were not manually set
+ * @res: the resources to clean
+ */
+-static void pnp_clean_resource_table(struct pnp_resource_table *res)
++static void pnp_clean_resource_table(struct pnp_dev *dev)
+ {
++ struct resource *res;
+ int idx;
+
+ for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
+- if (!(res->irq_resource[idx].flags & IORESOURCE_AUTO))
+- continue;
+- res->irq_resource[idx].start = -1;
+- res->irq_resource[idx].end = -1;
+- res->irq_resource[idx].flags =
+- IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET;
++ res = &dev->res->irq[idx].res;
++ if (res->flags & IORESOURCE_AUTO) {
++ res->flags = IORESOURCE_IRQ;
++ pnp_init_resource(res);
++ }
+ }
+ for (idx = 0; idx < PNP_MAX_DMA; idx++) {
+- if (!(res->dma_resource[idx].flags & IORESOURCE_AUTO))
+- continue;
+- res->dma_resource[idx].start = -1;
+- res->dma_resource[idx].end = -1;
+- res->dma_resource[idx].flags =
+- IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET;
++ res = &dev->res->dma[idx].res;
++ if (res->flags & IORESOURCE_AUTO) {
++ res->flags = IORESOURCE_DMA;
++ pnp_init_resource(res);
++ }
+ }
+ for (idx = 0; idx < PNP_MAX_PORT; idx++) {
+- if (!(res->port_resource[idx].flags & IORESOURCE_AUTO))
+- continue;
+- res->port_resource[idx].start = 0;
+- res->port_resource[idx].end = 0;
+- res->port_resource[idx].flags =
+- IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET;
++ res = &dev->res->port[idx].res;
++ if (res->flags & IORESOURCE_AUTO) {
++ res->flags = IORESOURCE_IO;
++ pnp_init_resource(res);
++ }
+ }
+ for (idx = 0; idx < PNP_MAX_MEM; idx++) {
+- if (!(res->mem_resource[idx].flags & IORESOURCE_AUTO))
+- continue;
+- res->mem_resource[idx].start = 0;
+- res->mem_resource[idx].end = 0;
+- res->mem_resource[idx].flags =
+- IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET;
++ res = &dev->res->mem[idx].res;
++ if (res->flags & IORESOURCE_AUTO) {
++ res->flags = IORESOURCE_MEM;
++ pnp_init_resource(res);
++ }
+ }
+ }
+
+@@ -298,9 +341,11 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
+ if (!pnp_can_configure(dev))
+ return -ENODEV;
+
++ dbg_pnp_show_resources(dev, "before pnp_assign_resources");
+ mutex_lock(&pnp_res_mutex);
+- pnp_clean_resource_table(&dev->res); /* start with a fresh slate */
++ pnp_clean_resource_table(dev);
+ if (dev->independent) {
++ dev_dbg(&dev->dev, "assigning independent options\n");
+ port = dev->independent->port;
+ mem = dev->independent->mem;
+ irq = dev->independent->irq;
+@@ -333,6 +378,8 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
+ if (depnum) {
+ struct pnp_option *dep;
+ int i;
++
++ dev_dbg(&dev->dev, "assigning dependent option %d\n", depnum);
+ for (i = 1, dep = dev->dependent; i < depnum;
+ i++, dep = dep->next)
+ if (!dep)
+@@ -368,68 +415,17 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
+ goto fail;
+
+ mutex_unlock(&pnp_res_mutex);
++ dbg_pnp_show_resources(dev, "after pnp_assign_resources");
+ return 1;
+
+ fail:
+- pnp_clean_resource_table(&dev->res);
++ pnp_clean_resource_table(dev);
+ mutex_unlock(&pnp_res_mutex);
++ dbg_pnp_show_resources(dev, "after pnp_assign_resources (failed)");
+ return 0;
+ }
+
+ /**
+- * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table
+- * @dev: pointer to the desired device
+- * @res: pointer to the new resource config
+- * @mode: 0 or PNP_CONFIG_FORCE
+- *
+- * This function can be used by drivers that want to manually set thier resources.
+- */
+-int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res,
+- int mode)
+-{
+- int i;
+- struct pnp_resource_table *bak;
+-
+- if (!pnp_can_configure(dev))
+- return -ENODEV;
+- bak = pnp_alloc(sizeof(struct pnp_resource_table));
+- if (!bak)
+- return -ENOMEM;
+- *bak = dev->res;
+-
+- mutex_lock(&pnp_res_mutex);
+- dev->res = *res;
+- if (!(mode & PNP_CONFIG_FORCE)) {
+- for (i = 0; i < PNP_MAX_PORT; i++) {
+- if (!pnp_check_port(dev, i))
+- goto fail;
+- }
+- for (i = 0; i < PNP_MAX_MEM; i++) {
+- if (!pnp_check_mem(dev, i))
+- goto fail;
+- }
+- for (i = 0; i < PNP_MAX_IRQ; i++) {
+- if (!pnp_check_irq(dev, i))
+- goto fail;
+- }
+- for (i = 0; i < PNP_MAX_DMA; i++) {
+- if (!pnp_check_dma(dev, i))
+- goto fail;
+- }
+- }
+- mutex_unlock(&pnp_res_mutex);
+-
+- kfree(bak);
+- return 0;
+-
+-fail:
+- dev->res = *bak;
+- mutex_unlock(&pnp_res_mutex);
+- kfree(bak);
+- return -EINVAL;
+-}
+-
+-/**
+ * pnp_auto_config_dev - automatically assigns resources to a device
+ * @dev: pointer to the desired device
+ */
+@@ -473,7 +469,8 @@ int pnp_start_dev(struct pnp_dev *dev)
+ return -EINVAL;
+ }
+
+- if (dev->protocol->set(dev, &dev->res) < 0) {
++ dbg_pnp_show_resources(dev, "pnp_start_dev");
++ if (dev->protocol->set(dev) < 0) {
+ dev_err(&dev->dev, "activation failed\n");
+ return -EIO;
+ }
+@@ -549,30 +546,13 @@ int pnp_disable_dev(struct pnp_dev *dev)
+
+ /* release the resources so that other devices can use them */
+ mutex_lock(&pnp_res_mutex);
+- pnp_clean_resource_table(&dev->res);
++ pnp_clean_resource_table(dev);
+ mutex_unlock(&pnp_res_mutex);
+
+ return 0;
+ }
+
+-/**
+- * pnp_resource_change - change one resource
+- * @resource: pointer to resource to be changed
+- * @start: start of region
+- * @size: size of region
+- */
+-void pnp_resource_change(struct resource *resource, resource_size_t start,
+- resource_size_t size)
+-{
+- resource->flags &= ~(IORESOURCE_AUTO | IORESOURCE_UNSET);
+- resource->start = start;
+- resource->end = start + size - 1;
+-}
+-
+-EXPORT_SYMBOL(pnp_manual_config_dev);
+ EXPORT_SYMBOL(pnp_start_dev);
+ EXPORT_SYMBOL(pnp_stop_dev);
+ EXPORT_SYMBOL(pnp_activate_dev);
+ EXPORT_SYMBOL(pnp_disable_dev);
+-EXPORT_SYMBOL(pnp_resource_change);
+-EXPORT_SYMBOL(pnp_init_resource_table);
+diff --git a/drivers/pnp/pnpacpi/Makefile b/drivers/pnp/pnpacpi/Makefile
+index 905326f..2d7a1e6 100644
+--- a/drivers/pnp/pnpacpi/Makefile
++++ b/drivers/pnp/pnpacpi/Makefile
+@@ -3,3 +3,7 @@
+ #
+
+ obj-y := core.o rsparser.o
++
++ifeq ($(CONFIG_PNP_DEBUG),y)
++EXTRA_CFLAGS += -DDEBUG
++endif
+diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
+index c283a9a..5090277 100644
+--- a/drivers/pnp/pnpacpi/core.c
++++ b/drivers/pnp/pnpacpi/core.c
+@@ -25,6 +25,7 @@
+ #include <acpi/acpi_bus.h>
+ #include <acpi/actypes.h>
+
++#include "../base.h"
+ #include "pnpacpi.h"
+
+ static int num = 0;
+@@ -44,7 +45,7 @@ static struct acpi_device_id excluded_id_list[] __initdata = {
+ {"", 0},
+ };
+
+-static inline int is_exclusive_device(struct acpi_device *dev)
++static inline int __init is_exclusive_device(struct acpi_device *dev)
+ {
+ return (!acpi_match_device_ids(dev, excluded_id_list));
+ }
+@@ -72,40 +73,24 @@ static int __init ispnpidacpi(char *id)
+ return 1;
+ }
+
+-static void __init pnpidacpi_to_pnpid(char *id, char *str)
++static int pnpacpi_get_resources(struct pnp_dev *dev)
+ {
+- str[0] = id[0];
+- str[1] = id[1];
+- str[2] = id[2];
+- str[3] = tolower(id[3]);
+- str[4] = tolower(id[4]);
+- str[5] = tolower(id[5]);
+- str[6] = tolower(id[6]);
+- str[7] = '\0';
++ dev_dbg(&dev->dev, "get resources\n");
++ return pnpacpi_parse_allocated_resource(dev);
+ }
+
+-static int pnpacpi_get_resources(struct pnp_dev *dev,
+- struct pnp_resource_table *res)
+-{
+- acpi_status status;
+-
+- status = pnpacpi_parse_allocated_resource((acpi_handle) dev->data,
+- &dev->res);
+- return ACPI_FAILURE(status) ? -ENODEV : 0;
+-}
+-
+-static int pnpacpi_set_resources(struct pnp_dev *dev,
+- struct pnp_resource_table *res)
++static int pnpacpi_set_resources(struct pnp_dev *dev)
+ {
+ acpi_handle handle = dev->data;
+ struct acpi_buffer buffer;
+- int ret = 0;
++ int ret;
+ acpi_status status;
+
+- ret = pnpacpi_build_resource_template(handle, &buffer);
++ dev_dbg(&dev->dev, "set resources\n");
++ ret = pnpacpi_build_resource_template(dev, &buffer);
+ if (ret)
+ return ret;
+- ret = pnpacpi_encode_resources(res, &buffer);
++ ret = pnpacpi_encode_resources(dev, &buffer);
+ if (ret) {
+ kfree(buffer.pointer);
+ return ret;
+@@ -163,7 +148,6 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
+ {
+ acpi_handle temp = NULL;
+ acpi_status status;
+- struct pnp_id *dev_id;
+ struct pnp_dev *dev;
+
+ status = acpi_get_handle(device->handle, "_CRS", &temp);
+@@ -171,11 +155,10 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
+ is_exclusive_device(device))
+ return 0;
+
+- dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
+- if (!dev) {
+- pnp_err("Out of memory");
++ dev = pnp_alloc_dev(&pnpacpi_protocol, num, acpi_device_hid(device));
++ if (!dev)
+ return -ENOMEM;
+- }
++
+ dev->data = device->handle;
+ /* .enabled means the device can decode the resources */
+ dev->active = device->status.enabled;
+@@ -191,44 +174,17 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
+ if (ACPI_SUCCESS(status))
+ dev->capabilities |= PNP_DISABLE;
+
+- dev->protocol = &pnpacpi_protocol;
+-
+ if (strlen(acpi_device_name(device)))
+ strncpy(dev->name, acpi_device_name(device), sizeof(dev->name));
+ else
+ strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name));
+
+- dev->number = num;
+-
+- /* set the initial values for the PnP device */
+- dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
+- if (!dev_id)
+- goto err;
+- pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id);
+- pnp_add_id(dev_id, dev);
+-
+- if (dev->active) {
+- /* parse allocated resource */
+- status = pnpacpi_parse_allocated_resource(device->handle,
+- &dev->res);
+- if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
+- pnp_err("PnPACPI: METHOD_NAME__CRS failure for %s",
+- dev_id->id);
+- goto err1;
+- }
+- }
++ if (dev->active)
++ pnpacpi_parse_allocated_resource(dev);
+
+- if (dev->capabilities & PNP_CONFIGURABLE) {
+- status = pnpacpi_parse_resource_option_data(device->handle,
+- dev);
+- if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
+- pnp_err("PnPACPI: METHOD_NAME__PRS failure for %s",
+- dev_id->id);
+- goto err1;
+- }
+- }
++ if (dev->capabilities & PNP_CONFIGURABLE)
++ pnpacpi_parse_resource_option_data(dev);
+
+- /* parse compatible ids */
+ if (device->flags.compatible_ids) {
+ struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
+ int i;
+@@ -236,27 +192,17 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
+ for (i = 0; i < cid_list->count; i++) {
+ if (!ispnpidacpi(cid_list->id[i].value))
+ continue;
+- dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
+- if (!dev_id)
+- continue;
+-
+- pnpidacpi_to_pnpid(cid_list->id[i].value, dev_id->id);
+- pnp_add_id(dev_id, dev);
++ pnp_add_id(dev, cid_list->id[i].value);
+ }
+ }
+
+ /* clear out the damaged flags */
+ if (!dev->active)
+- pnp_init_resource_table(&dev->res);
++ pnp_init_resources(dev);
+ pnp_add_device(dev);
+ num++;
+
+ return AE_OK;
+-err1:
+- kfree(dev_id);
+-err:
+- kfree(dev);
+- return -EINVAL;
+ }
+
+ static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle,
+diff --git a/drivers/pnp/pnpacpi/pnpacpi.h b/drivers/pnp/pnpacpi/pnpacpi.h
+index f28e2ed..3e60225 100644
+--- a/drivers/pnp/pnpacpi/pnpacpi.h
++++ b/drivers/pnp/pnpacpi/pnpacpi.h
+@@ -5,8 +5,8 @@
+ #include <linux/acpi.h>
+ #include <linux/pnp.h>
+
+-acpi_status pnpacpi_parse_allocated_resource(acpi_handle, struct pnp_resource_table*);
+-acpi_status pnpacpi_parse_resource_option_data(acpi_handle, struct pnp_dev*);
+-int pnpacpi_encode_resources(struct pnp_resource_table *, struct acpi_buffer *);
+-int pnpacpi_build_resource_template(acpi_handle, struct acpi_buffer*);
++int pnpacpi_parse_allocated_resource(struct pnp_dev *);
++int pnpacpi_parse_resource_option_data(struct pnp_dev *);
++int pnpacpi_encode_resources(struct pnp_dev *, struct acpi_buffer *);
++int pnpacpi_build_resource_template(struct pnp_dev *, struct acpi_buffer *);
+ #endif
+diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
+index 2dcd196..0201c8a 100644
+--- a/drivers/pnp/pnpacpi/rsparser.c
++++ b/drivers/pnp/pnpacpi/rsparser.c
+@@ -21,6 +21,8 @@
+ #include <linux/kernel.h>
+ #include <linux/acpi.h>
+ #include <linux/pci.h>
++#include <linux/pnp.h>
++#include "../base.h"
+ #include "pnpacpi.h"
+
+ #ifdef CONFIG_IA64
+@@ -32,19 +34,26 @@
+ /*
+ * Allocated Resources
+ */
+-static int irq_flags(int triggering, int polarity)
++static int irq_flags(int triggering, int polarity, int shareable)
+ {
++ int flags;
++
+ if (triggering == ACPI_LEVEL_SENSITIVE) {
+ if (polarity == ACPI_ACTIVE_LOW)
+- return IORESOURCE_IRQ_LOWLEVEL;
++ flags = IORESOURCE_IRQ_LOWLEVEL;
+ else
+- return IORESOURCE_IRQ_HIGHLEVEL;
++ flags = IORESOURCE_IRQ_HIGHLEVEL;
+ } else {
+ if (polarity == ACPI_ACTIVE_LOW)
+- return IORESOURCE_IRQ_LOWEDGE;
++ flags = IORESOURCE_IRQ_LOWEDGE;
+ else
+- return IORESOURCE_IRQ_HIGHEDGE;
++ flags = IORESOURCE_IRQ_HIGHEDGE;
+ }
++
++ if (shareable)
++ flags |= IORESOURCE_IRQ_SHAREABLE;
++
++ return flags;
+ }
+
+ static void decode_irq_flags(int flag, int *triggering, int *polarity)
+@@ -69,27 +78,16 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity)
+ }
+ }
+
+-static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
++static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
+ u32 gsi, int triggering,
+ int polarity, int shareable)
+ {
+- int i = 0;
+- int irq;
++ int irq, flags;
+ int p, t;
+- static unsigned char warned;
+
+ if (!valid_IRQ(gsi))
+ return;
+
+- 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;
+- return;
+- }
+ /*
+ * in IO-APIC mode, use overrided attribute. Two reasons:
+ * 1. BIOS bug in DSDT
+@@ -100,27 +98,21 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
+ p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
+
+ if (triggering != t || polarity != p) {
+- pnp_warn("IRQ %d override to %s, %s",
++ dev_warn(&dev->dev, "IRQ %d override to %s, %s\n",
+ gsi, t ? "edge":"level", p ? "low":"high");
+ triggering = t;
+ polarity = p;
+ }
+ }
+
+- res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag
+- res->irq_resource[i].flags |= irq_flags(triggering, polarity);
++ flags = irq_flags(triggering, polarity, shareable);
+ irq = acpi_register_gsi(gsi, triggering, polarity);
+- if (irq < 0) {
+- res->irq_resource[i].flags |= IORESOURCE_DISABLED;
+- return;
+- }
+-
+- if (shareable)
+- res->irq_resource[i].flags |= IORESOURCE_IRQ_SHAREABLE;
++ if (irq >= 0)
++ pcibios_penalize_isa_irq(irq, 1);
++ else
++ flags |= IORESOURCE_DISABLED;
+
+- res->irq_resource[i].start = irq;
+- res->irq_resource[i].end = irq;
+- pcibios_penalize_isa_irq(irq, 1);
++ pnp_add_irq_resource(dev, irq, flags);
+ }
+
+ static int dma_flags(int type, int bus_master, int transfer)
+@@ -166,88 +158,36 @@ static int dma_flags(int type, int bus_master, int transfer)
+ return flags;
+ }
+
+-static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res,
+- u32 dma, int type,
+- int bus_master, int transfer)
++static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
++ u64 len, int io_decode)
+ {
+- int i = 0;
+- static unsigned char warned;
+-
+- while (i < PNP_MAX_DMA &&
+- !(res->dma_resource[i].flags & IORESOURCE_UNSET))
+- i++;
+- if (i < PNP_MAX_DMA) {
+- res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag
+- res->dma_resource[i].flags |=
+- dma_flags(type, bus_master, transfer);
+- if (dma == -1) {
+- res->dma_resource[i].flags |= IORESOURCE_DISABLED;
+- return;
+- }
+- res->dma_resource[i].start = dma;
+- res->dma_resource[i].end = dma;
+- } else if (!warned) {
+- printk(KERN_WARNING "pnpacpi: exceeded the max number of DMA "
+- "resources: %d \n", PNP_MAX_DMA);
+- warned = 1;
+- }
+-}
++ int flags = 0;
++ u64 end = start + len - 1;
+
+-static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res,
+- u64 io, u64 len, int io_decode)
+-{
+- int i = 0;
+- static unsigned char warned;
++ if (io_decode == ACPI_DECODE_16)
++ flags |= PNP_PORT_FLAG_16BITADDR;
++ if (len == 0 || end >= 0x10003)
++ flags |= IORESOURCE_DISABLED;
+
+- while (!(res->port_resource[i].flags & IORESOURCE_UNSET) &&
+- i < PNP_MAX_PORT)
+- i++;
+- if (i < PNP_MAX_PORT) {
+- res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag
+- if (io_decode == ACPI_DECODE_16)
+- res->port_resource[i].flags |= PNP_PORT_FLAG_16BITADDR;
+- if (len <= 0 || (io + len - 1) >= 0x10003) {
+- res->port_resource[i].flags |= IORESOURCE_DISABLED;
+- return;
+- }
+- res->port_resource[i].start = io;
+- res->port_resource[i].end = io + len - 1;
+- } else if (!warned) {
+- printk(KERN_WARNING "pnpacpi: exceeded the max number of IO "
+- "resources: %d \n", PNP_MAX_PORT);
+- warned = 1;
+- }
++ pnp_add_io_resource(dev, start, end, flags);
+ }
+
+-static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res,
+- u64 mem, u64 len,
++static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
++ u64 start, u64 len,
+ int write_protect)
+ {
+- int i = 0;
+- static unsigned char warned;
++ int flags = 0;
++ u64 end = start + len - 1;
+
+- while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) &&
+- (i < PNP_MAX_MEM))
+- i++;
+- if (i < PNP_MAX_MEM) {
+- res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag
+- if (len <= 0) {
+- res->mem_resource[i].flags |= IORESOURCE_DISABLED;
+- return;
+- }
+- if (write_protect == ACPI_READ_WRITE_MEMORY)
+- res->mem_resource[i].flags |= IORESOURCE_MEM_WRITEABLE;
+-
+- res->mem_resource[i].start = mem;
+- res->mem_resource[i].end = mem + len - 1;
+- } else if (!warned) {
+- printk(KERN_WARNING "pnpacpi: exceeded the max number of mem "
+- "resources: %d\n", PNP_MAX_MEM);
+- warned = 1;
+- }
++ if (len == 0)
++ flags |= IORESOURCE_DISABLED;
++ if (write_protect == ACPI_READ_WRITE_MEMORY)
++ flags |= IORESOURCE_MEM_WRITEABLE;
++
++ pnp_add_mem_resource(dev, start, end, flags);
+ }
+
+-static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table,
++static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
+ struct acpi_resource *res)
+ {
+ struct acpi_resource_address64 addr, *p = &addr;
+@@ -255,7 +195,7 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res
+
+ status = acpi_resource_to_address64(res, p);
+ if (!ACPI_SUCCESS(status)) {
+- pnp_warn("PnPACPI: failed to convert resource type %d",
++ dev_warn(&dev->dev, "failed to convert resource type %d\n",
+ res->type);
+ return;
+ }
+@@ -264,11 +204,11 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res
+ return;
+
+ if (p->resource_type == ACPI_MEMORY_RANGE)
+- pnpacpi_parse_allocated_memresource(res_table,
++ pnpacpi_parse_allocated_memresource(dev,
+ p->minimum, p->address_length,
+ p->info.mem.write_protect);
+ else if (p->resource_type == ACPI_IO_RANGE)
+- pnpacpi_parse_allocated_ioresource(res_table,
++ pnpacpi_parse_allocated_ioresource(dev,
+ p->minimum, p->address_length,
+ p->granularity == 0xfff ? ACPI_DECODE_10 :
+ ACPI_DECODE_16);
+@@ -277,8 +217,16 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res
+ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
+ void *data)
+ {
+- struct pnp_resource_table *res_table = data;
+- int i;
++ struct pnp_dev *dev = data;
++ struct acpi_resource_irq *irq;
++ struct acpi_resource_dma *dma;
++ struct acpi_resource_io *io;
++ struct acpi_resource_fixed_io *fixed_io;
++ struct acpi_resource_memory24 *memory24;
++ struct acpi_resource_memory32 *memory32;
++ struct acpi_resource_fixed_memory32 *fixed_memory32;
++ struct acpi_resource_extended_irq *extended_irq;
++ int i, flags;
+
+ switch (res->type) {
+ case ACPI_RESOURCE_TYPE_IRQ:
+@@ -286,29 +234,33 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
+ * Per spec, only one interrupt per descriptor is allowed in
+ * _CRS, but some firmware violates this, so parse them all.
+ */
+- for (i = 0; i < res->data.irq.interrupt_count; i++) {
+- pnpacpi_parse_allocated_irqresource(res_table,
+- res->data.irq.interrupts[i],
+- res->data.irq.triggering,
+- res->data.irq.polarity,
+- res->data.irq.sharable);
++ irq = &res->data.irq;
++ for (i = 0; i < irq->interrupt_count; i++) {
++ pnpacpi_parse_allocated_irqresource(dev,
++ irq->interrupts[i],
++ irq->triggering,
++ irq->polarity,
++ irq->sharable);
+ }
+ break;
+
+ case ACPI_RESOURCE_TYPE_DMA:
+- if (res->data.dma.channel_count > 0)
+- pnpacpi_parse_allocated_dmaresource(res_table,
+- res->data.dma.channels[0],
+- res->data.dma.type,
+- res->data.dma.bus_master,
+- res->data.dma.transfer);
++ dma = &res->data.dma;
++ if (dma->channel_count > 0) {
++ flags = dma_flags(dma->type, dma->bus_master,
++ dma->transfer);
++ if (dma->channels[0] == (u8) -1)
++ flags |= IORESOURCE_DISABLED;
++ pnp_add_dma_resource(dev, dma->channels[0], flags);
++ }
+ break;
+
+ case ACPI_RESOURCE_TYPE_IO:
+- pnpacpi_parse_allocated_ioresource(res_table,
+- res->data.io.minimum,
+- res->data.io.address_length,
+- res->data.io.io_decode);
++ io = &res->data.io;
++ pnpacpi_parse_allocated_ioresource(dev,
++ io->minimum,
++ io->address_length,
++ io->io_decode);
+ break;
+
+ case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+@@ -316,9 +268,10 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
+ break;
+
+ case ACPI_RESOURCE_TYPE_FIXED_IO:
+- pnpacpi_parse_allocated_ioresource(res_table,
+- res->data.fixed_io.address,
+- res->data.fixed_io.address_length,
++ fixed_io = &res->data.fixed_io;
++ pnpacpi_parse_allocated_ioresource(dev,
++ fixed_io->address,
++ fixed_io->address_length,
+ ACPI_DECODE_10);
+ break;
+
+@@ -329,27 +282,30 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
+ break;
+
+ case ACPI_RESOURCE_TYPE_MEMORY24:
+- pnpacpi_parse_allocated_memresource(res_table,
+- res->data.memory24.minimum,
+- res->data.memory24.address_length,
+- res->data.memory24.write_protect);
++ memory24 = &res->data.memory24;
++ pnpacpi_parse_allocated_memresource(dev,
++ memory24->minimum,
++ memory24->address_length,
++ memory24->write_protect);
+ break;
+ case ACPI_RESOURCE_TYPE_MEMORY32:
+- pnpacpi_parse_allocated_memresource(res_table,
+- res->data.memory32.minimum,
+- res->data.memory32.address_length,
+- res->data.memory32.write_protect);
++ memory32 = &res->data.memory32;
++ pnpacpi_parse_allocated_memresource(dev,
++ memory32->minimum,
++ memory32->address_length,
++ memory32->write_protect);
+ break;
+ case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+- pnpacpi_parse_allocated_memresource(res_table,
+- res->data.fixed_memory32.address,
+- res->data.fixed_memory32.address_length,
+- res->data.fixed_memory32.write_protect);
++ fixed_memory32 = &res->data.fixed_memory32;
++ pnpacpi_parse_allocated_memresource(dev,
++ fixed_memory32->address,
++ fixed_memory32->address_length,
++ fixed_memory32->write_protect);
+ break;
+ case ACPI_RESOURCE_TYPE_ADDRESS16:
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
+- pnpacpi_parse_allocated_address_space(res_table, res);
++ pnpacpi_parse_allocated_address_space(dev, res);
+ break;
+
+ case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+@@ -358,15 +314,16 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
+ break;
+
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+- if (res->data.extended_irq.producer_consumer == ACPI_PRODUCER)
++ extended_irq = &res->data.extended_irq;
++ if (extended_irq->producer_consumer == ACPI_PRODUCER)
+ return AE_OK;
+
+- for (i = 0; i < res->data.extended_irq.interrupt_count; i++) {
+- pnpacpi_parse_allocated_irqresource(res_table,
+- res->data.extended_irq.interrupts[i],
+- res->data.extended_irq.triggering,
+- res->data.extended_irq.polarity,
+- res->data.extended_irq.sharable);
++ for (i = 0; i < extended_irq->interrupt_count; i++) {
++ pnpacpi_parse_allocated_irqresource(dev,
++ extended_irq->interrupts[i],
++ extended_irq->triggering,
++ extended_irq->polarity,
++ extended_irq->sharable);
+ }
+ break;
+
+@@ -374,24 +331,36 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
+ break;
+
+ default:
+- pnp_warn("PnPACPI: unknown resource type %d", res->type);
++ dev_warn(&dev->dev, "unknown resource type %d in _CRS\n",
++ res->type);
+ return AE_ERROR;
+ }
+
+ return AE_OK;
+ }
+
+-acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle,
+- struct pnp_resource_table * res)
++int pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
+ {
+- /* Blank the resource table values */
+- pnp_init_resource_table(res);
++ acpi_handle handle = dev->data;
++ acpi_status status;
++
++ dev_dbg(&dev->dev, "parse allocated resources\n");
+
+- return acpi_walk_resources(handle, METHOD_NAME__CRS,
+- pnpacpi_allocated_resource, res);
++ pnp_init_resources(dev);
++
++ status = acpi_walk_resources(handle, METHOD_NAME__CRS,
++ pnpacpi_allocated_resource, dev);
++
++ if (ACPI_FAILURE(status)) {
++ if (status != AE_NOT_FOUND)
++ dev_err(&dev->dev, "can't evaluate _CRS: %d", status);
++ return -EPERM;
++ }
++ return 0;
+ }
+
+-static __init void pnpacpi_parse_dma_option(struct pnp_option *option,
++static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
++ struct pnp_option *option,
+ struct acpi_resource_dma *p)
+ {
+ int i;
+@@ -408,10 +377,11 @@ static __init void pnpacpi_parse_dma_option(struct pnp_option *option,
+
+ dma->flags = dma_flags(p->type, p->bus_master, p->transfer);
+
+- pnp_register_dma_resource(option, dma);
++ pnp_register_dma_resource(dev, option, dma);
+ }
+
+-static __init void pnpacpi_parse_irq_option(struct pnp_option *option,
++static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
++ struct pnp_option *option,
+ struct acpi_resource_irq *p)
+ {
+ int i;
+@@ -426,12 +396,13 @@ static __init void pnpacpi_parse_irq_option(struct pnp_option *option,
+ for (i = 0; i < p->interrupt_count; i++)
+ if (p->interrupts[i])
+ __set_bit(p->interrupts[i], irq->map);
+- irq->flags = irq_flags(p->triggering, p->polarity);
++ irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
+
+- pnp_register_irq_resource(option, irq);
++ pnp_register_irq_resource(dev, option, irq);
+ }
+
+-static __init void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
++static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
++ struct pnp_option *option,
+ struct acpi_resource_extended_irq *p)
+ {
+ int i;
+@@ -446,12 +417,13 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
+ for (i = 0; i < p->interrupt_count; i++)
+ if (p->interrupts[i])
+ __set_bit(p->interrupts[i], irq->map);
+- irq->flags = irq_flags(p->triggering, p->polarity);
++ irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
+
+- pnp_register_irq_resource(option, irq);
++ pnp_register_irq_resource(dev, option, irq);
+ }
+
+-static __init void pnpacpi_parse_port_option(struct pnp_option *option,
++static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
++ struct pnp_option *option,
+ struct acpi_resource_io *io)
+ {
+ struct pnp_port *port;
+@@ -467,10 +439,11 @@ static __init void pnpacpi_parse_port_option(struct pnp_option *option,
+ port->size = io->address_length;
+ port->flags = ACPI_DECODE_16 == io->io_decode ?
+ PNP_PORT_FLAG_16BITADDR : 0;
+- pnp_register_port_resource(option, port);
++ pnp_register_port_resource(dev, option, port);
+ }
+
+-static __init void pnpacpi_parse_fixed_port_option(struct pnp_option *option,
++static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
++ struct pnp_option *option,
+ struct acpi_resource_fixed_io *io)
+ {
+ struct pnp_port *port;
+@@ -484,10 +457,11 @@ static __init void pnpacpi_parse_fixed_port_option(struct pnp_option *option,
+ port->size = io->address_length;
+ port->align = 0;
+ port->flags = PNP_PORT_FLAG_FIXED;
+- pnp_register_port_resource(option, port);
++ pnp_register_port_resource(dev, option, port);
+ }
+
+-static __init void pnpacpi_parse_mem24_option(struct pnp_option *option,
++static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
++ struct pnp_option *option,
+ struct acpi_resource_memory24 *p)
+ {
+ struct pnp_mem *mem;
+@@ -505,10 +479,11 @@ static __init void pnpacpi_parse_mem24_option(struct pnp_option *option,
+ mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
+ IORESOURCE_MEM_WRITEABLE : 0;
+
+- pnp_register_mem_resource(option, mem);
++ pnp_register_mem_resource(dev, option, mem);
+ }
+
+-static __init void pnpacpi_parse_mem32_option(struct pnp_option *option,
++static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
++ struct pnp_option *option,
+ struct acpi_resource_memory32 *p)
+ {
+ struct pnp_mem *mem;
+@@ -526,10 +501,11 @@ static __init void pnpacpi_parse_mem32_option(struct pnp_option *option,
+ mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
+ IORESOURCE_MEM_WRITEABLE : 0;
+
+- pnp_register_mem_resource(option, mem);
++ pnp_register_mem_resource(dev, option, mem);
+ }
+
+-static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
++static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
++ struct pnp_option *option,
+ struct acpi_resource_fixed_memory32 *p)
+ {
+ struct pnp_mem *mem;
+@@ -546,10 +522,11 @@ static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
+ mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
+ IORESOURCE_MEM_WRITEABLE : 0;
+
+- pnp_register_mem_resource(option, mem);
++ pnp_register_mem_resource(dev, option, mem);
+ }
+
+-static __init void pnpacpi_parse_address_option(struct pnp_option *option,
++static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
++ struct pnp_option *option,
+ struct acpi_resource *r)
+ {
+ struct acpi_resource_address64 addr, *p = &addr;
+@@ -577,7 +554,7 @@ static __init void pnpacpi_parse_address_option(struct pnp_option *option,
+ mem->flags = (p->info.mem.write_protect ==
+ ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE
+ : 0;
+- pnp_register_mem_resource(option, mem);
++ pnp_register_mem_resource(dev, option, mem);
+ } else if (p->resource_type == ACPI_IO_RANGE) {
+ port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
+ if (!port)
+@@ -586,7 +563,7 @@ static __init void pnpacpi_parse_address_option(struct pnp_option *option,
+ port->size = p->address_length;
+ port->align = 0;
+ port->flags = PNP_PORT_FLAG_FIXED;
+- pnp_register_port_resource(option, port);
++ pnp_register_port_resource(dev, option, port);
+ }
+ }
+
+@@ -606,11 +583,11 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
+
+ switch (res->type) {
+ case ACPI_RESOURCE_TYPE_IRQ:
+- pnpacpi_parse_irq_option(option, &res->data.irq);
++ pnpacpi_parse_irq_option(dev, option, &res->data.irq);
+ break;
+
+ case ACPI_RESOURCE_TYPE_DMA:
+- pnpacpi_parse_dma_option(option, &res->data.dma);
++ pnpacpi_parse_dma_option(dev, option, &res->data.dma);
+ break;
+
+ case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+@@ -640,19 +617,22 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
+ case ACPI_RESOURCE_TYPE_END_DEPENDENT:
+ /*only one EndDependentFn is allowed */
+ if (!parse_data->option_independent) {
+- pnp_warn("PnPACPI: more than one EndDependentFn");
++ dev_warn(&dev->dev, "more than one EndDependentFn "
++ "in _PRS\n");
+ return AE_ERROR;
+ }
+ parse_data->option = parse_data->option_independent;
+ parse_data->option_independent = NULL;
++ dev_dbg(&dev->dev, "end dependent options\n");
+ break;
+
+ case ACPI_RESOURCE_TYPE_IO:
+- pnpacpi_parse_port_option(option, &res->data.io);
++ pnpacpi_parse_port_option(dev, option, &res->data.io);
+ break;
+
+ case ACPI_RESOURCE_TYPE_FIXED_IO:
+- pnpacpi_parse_fixed_port_option(option, &res->data.fixed_io);
++ pnpacpi_parse_fixed_port_option(dev, option,
++ &res->data.fixed_io);
+ break;
+
+ case ACPI_RESOURCE_TYPE_VENDOR:
+@@ -660,57 +640,67 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
+ break;
+
+ case ACPI_RESOURCE_TYPE_MEMORY24:
+- pnpacpi_parse_mem24_option(option, &res->data.memory24);
++ pnpacpi_parse_mem24_option(dev, option, &res->data.memory24);
+ break;
+
+ case ACPI_RESOURCE_TYPE_MEMORY32:
+- pnpacpi_parse_mem32_option(option, &res->data.memory32);
++ pnpacpi_parse_mem32_option(dev, option, &res->data.memory32);
+ break;
+
+ case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+- pnpacpi_parse_fixed_mem32_option(option,
++ pnpacpi_parse_fixed_mem32_option(dev, option,
+ &res->data.fixed_memory32);
+ break;
+
+ case ACPI_RESOURCE_TYPE_ADDRESS16:
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
+- pnpacpi_parse_address_option(option, res);
++ pnpacpi_parse_address_option(dev, option, res);
+ break;
+
+ case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+ break;
+
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+- pnpacpi_parse_ext_irq_option(option, &res->data.extended_irq);
++ pnpacpi_parse_ext_irq_option(dev, option,
++ &res->data.extended_irq);
+ break;
+
+ case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
+ break;
+
+ default:
+- pnp_warn("PnPACPI: unknown resource type %d", res->type);
++ dev_warn(&dev->dev, "unknown resource type %d in _PRS\n",
++ res->type);
+ return AE_ERROR;
+ }
+
+ return AE_OK;
+ }
+
+-acpi_status __init pnpacpi_parse_resource_option_data(acpi_handle handle,
+- struct pnp_dev *dev)
++int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
+ {
++ acpi_handle handle = dev->data;
+ acpi_status status;
+ struct acpipnp_parse_option_s parse_data;
+
++ dev_dbg(&dev->dev, "parse resource options\n");
++
+ parse_data.option = pnp_register_independent_option(dev);
+ if (!parse_data.option)
+- return AE_ERROR;
++ return -ENOMEM;
++
+ parse_data.option_independent = parse_data.option;
+ parse_data.dev = dev;
+ status = acpi_walk_resources(handle, METHOD_NAME__PRS,
+ pnpacpi_option_resource, &parse_data);
+
+- return status;
++ if (ACPI_FAILURE(status)) {
++ if (status != AE_NOT_FOUND)
++ dev_err(&dev->dev, "can't evaluate _PRS: %d", status);
++ return -EPERM;
++ }
++ return 0;
+ }
+
+ static int pnpacpi_supported_resource(struct acpi_resource *res)
+@@ -758,9 +748,10 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
+ return AE_OK;
+ }
+
+-int pnpacpi_build_resource_template(acpi_handle handle,
++int pnpacpi_build_resource_template(struct pnp_dev *dev,
+ struct acpi_buffer *buffer)
+ {
++ acpi_handle handle = dev->data;
+ struct acpi_resource *resource;
+ int res_cnt = 0;
+ acpi_status status;
+@@ -768,7 +759,7 @@ int pnpacpi_build_resource_template(acpi_handle handle,
+ status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+ pnpacpi_count_resources, &res_cnt);
+ if (ACPI_FAILURE(status)) {
+- pnp_err("Evaluate _CRS failed");
++ dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);
+ return -EINVAL;
+ }
+ if (!res_cnt)
+@@ -777,13 +768,13 @@ int pnpacpi_build_resource_template(acpi_handle handle,
+ buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL);
+ if (!buffer->pointer)
+ return -ENOMEM;
+- pnp_dbg("Res cnt %d", res_cnt);
++
+ resource = (struct acpi_resource *)buffer->pointer;
+ status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+ pnpacpi_type_resources, &resource);
+ if (ACPI_FAILURE(status)) {
+ kfree(buffer->pointer);
+- pnp_err("Evaluate _CRS failed");
++ dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);
+ return -EINVAL;
+ }
+ /* resource will pointer the end resource now */
+@@ -792,129 +783,184 @@ int pnpacpi_build_resource_template(acpi_handle handle,
+ return 0;
+ }
+
+-static void pnpacpi_encode_irq(struct acpi_resource *resource,
++static void pnpacpi_encode_irq(struct pnp_dev *dev,
++ struct acpi_resource *resource,
+ struct resource *p)
+ {
++ struct acpi_resource_irq *irq = &resource->data.irq;
+ int triggering, polarity;
+
+ decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
+- resource->data.irq.triggering = triggering;
+- resource->data.irq.polarity = polarity;
++ irq->triggering = triggering;
++ irq->polarity = polarity;
+ if (triggering == ACPI_EDGE_SENSITIVE)
+- resource->data.irq.sharable = ACPI_EXCLUSIVE;
++ irq->sharable = ACPI_EXCLUSIVE;
+ else
+- resource->data.irq.sharable = ACPI_SHARED;
+- resource->data.irq.interrupt_count = 1;
+- resource->data.irq.interrupts[0] = p->start;
++ irq->sharable = ACPI_SHARED;
++ irq->interrupt_count = 1;
++ irq->interrupts[0] = p->start;
++
++ dev_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start,
++ triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
++ polarity == ACPI_ACTIVE_LOW ? "low" : "high",
++ irq->sharable == ACPI_SHARED ? "shared" : "exclusive");
+ }
+
+-static void pnpacpi_encode_ext_irq(struct acpi_resource *resource,
++static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
++ struct acpi_resource *resource,
+ struct resource *p)
+ {
++ struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
+ int triggering, polarity;
+
+ decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
+- resource->data.extended_irq.producer_consumer = ACPI_CONSUMER;
+- resource->data.extended_irq.triggering = triggering;
+- resource->data.extended_irq.polarity = polarity;
++ extended_irq->producer_consumer = ACPI_CONSUMER;
++ extended_irq->triggering = triggering;
++ extended_irq->polarity = polarity;
+ if (triggering == ACPI_EDGE_SENSITIVE)
+- resource->data.irq.sharable = ACPI_EXCLUSIVE;
++ extended_irq->sharable = ACPI_EXCLUSIVE;
+ else
+- resource->data.irq.sharable = ACPI_SHARED;
+- resource->data.extended_irq.interrupt_count = 1;
+- resource->data.extended_irq.interrupts[0] = p->start;
++ extended_irq->sharable = ACPI_SHARED;
++ extended_irq->interrupt_count = 1;
++ extended_irq->interrupts[0] = p->start;
++
++ dev_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start,
++ triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
++ polarity == ACPI_ACTIVE_LOW ? "low" : "high",
++ extended_irq->sharable == ACPI_SHARED ? "shared" : "exclusive");
+ }
+
+-static void pnpacpi_encode_dma(struct acpi_resource *resource,
++static void pnpacpi_encode_dma(struct pnp_dev *dev,
++ struct acpi_resource *resource,
+ struct resource *p)
+ {
++ struct acpi_resource_dma *dma = &resource->data.dma;
++
+ /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
+ switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
+ case IORESOURCE_DMA_TYPEA:
+- resource->data.dma.type = ACPI_TYPE_A;
++ dma->type = ACPI_TYPE_A;
+ break;
+ case IORESOURCE_DMA_TYPEB:
+- resource->data.dma.type = ACPI_TYPE_B;
++ dma->type = ACPI_TYPE_B;
+ break;
+ case IORESOURCE_DMA_TYPEF:
+- resource->data.dma.type = ACPI_TYPE_F;
++ dma->type = ACPI_TYPE_F;
+ break;
+ default:
+- resource->data.dma.type = ACPI_COMPATIBILITY;
++ dma->type = ACPI_COMPATIBILITY;
+ }
+
+ switch (p->flags & IORESOURCE_DMA_TYPE_MASK) {
+ case IORESOURCE_DMA_8BIT:
+- resource->data.dma.transfer = ACPI_TRANSFER_8;
++ dma->transfer = ACPI_TRANSFER_8;
+ break;
+ case IORESOURCE_DMA_8AND16BIT:
+- resource->data.dma.transfer = ACPI_TRANSFER_8_16;
++ dma->transfer = ACPI_TRANSFER_8_16;
+ break;
+ default:
+- resource->data.dma.transfer = ACPI_TRANSFER_16;
++ dma->transfer = ACPI_TRANSFER_16;
+ }
+
+- resource->data.dma.bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
+- resource->data.dma.channel_count = 1;
+- resource->data.dma.channels[0] = p->start;
++ dma->bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
++ dma->channel_count = 1;
++ dma->channels[0] = p->start;
++
++ dev_dbg(&dev->dev, " encode dma %d "
++ "type %#x transfer %#x master %d\n",
++ (int) p->start, dma->type, dma->transfer, dma->bus_master);
+ }
+
+-static void pnpacpi_encode_io(struct acpi_resource *resource,
++static void pnpacpi_encode_io(struct pnp_dev *dev,
++ struct acpi_resource *resource,
+ struct resource *p)
+ {
++ struct acpi_resource_io *io = &resource->data.io;
++
+ /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
+- resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
++ io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
+ ACPI_DECODE_16 : ACPI_DECODE_10;
+- resource->data.io.minimum = p->start;
+- resource->data.io.maximum = p->end;
+- resource->data.io.alignment = 0; /* Correct? */
+- resource->data.io.address_length = p->end - p->start + 1;
++ io->minimum = p->start;
++ io->maximum = p->end;
++ io->alignment = 0; /* Correct? */
++ io->address_length = p->end - p->start + 1;
++
++ dev_dbg(&dev->dev, " encode io %#llx-%#llx decode %#x\n",
++ (unsigned long long) p->start, (unsigned long long) p->end,
++ io->io_decode);
+ }
+
+-static void pnpacpi_encode_fixed_io(struct acpi_resource *resource,
++static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
++ struct acpi_resource *resource,
+ struct resource *p)
+ {
+- resource->data.fixed_io.address = p->start;
+- resource->data.fixed_io.address_length = p->end - p->start + 1;
++ struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io;
++
++ fixed_io->address = p->start;
++ fixed_io->address_length = p->end - p->start + 1;
++
++ dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n",
++ (unsigned long long) p->start, (unsigned long long) p->end);
+ }
+
+-static void pnpacpi_encode_mem24(struct acpi_resource *resource,
++static void pnpacpi_encode_mem24(struct pnp_dev *dev,
++ struct acpi_resource *resource,
+ struct resource *p)
+ {
++ struct acpi_resource_memory24 *memory24 = &resource->data.memory24;
++
+ /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
+- resource->data.memory24.write_protect =
++ memory24->write_protect =
+ (p->flags & IORESOURCE_MEM_WRITEABLE) ?
+ ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
+- resource->data.memory24.minimum = p->start;
+- resource->data.memory24.maximum = p->end;
+- resource->data.memory24.alignment = 0;
+- resource->data.memory24.address_length = p->end - p->start + 1;
++ memory24->minimum = p->start;
++ memory24->maximum = p->end;
++ memory24->alignment = 0;
++ memory24->address_length = p->end - p->start + 1;
++
++ dev_dbg(&dev->dev, " encode mem24 %#llx-%#llx write_protect %#x\n",
++ (unsigned long long) p->start, (unsigned long long) p->end,
++ memory24->write_protect);
+ }
+
+-static void pnpacpi_encode_mem32(struct acpi_resource *resource,
++static void pnpacpi_encode_mem32(struct pnp_dev *dev,
++ struct acpi_resource *resource,
+ struct resource *p)
+ {
+- resource->data.memory32.write_protect =
++ struct acpi_resource_memory32 *memory32 = &resource->data.memory32;
++
++ memory32->write_protect =
+ (p->flags & IORESOURCE_MEM_WRITEABLE) ?
+ ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
+- resource->data.memory32.minimum = p->start;
+- resource->data.memory32.maximum = p->end;
+- resource->data.memory32.alignment = 0;
+- resource->data.memory32.address_length = p->end - p->start + 1;
++ memory32->minimum = p->start;
++ memory32->maximum = p->end;
++ memory32->alignment = 0;
++ memory32->address_length = p->end - p->start + 1;
++
++ dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx write_protect %#x\n",
++ (unsigned long long) p->start, (unsigned long long) p->end,
++ memory32->write_protect);
+ }
+
+-static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource,
++static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
++ struct acpi_resource *resource,
+ struct resource *p)
+ {
+- resource->data.fixed_memory32.write_protect =
++ struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32;
++
++ fixed_memory32->write_protect =
+ (p->flags & IORESOURCE_MEM_WRITEABLE) ?
+ ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
+- resource->data.fixed_memory32.address = p->start;
+- resource->data.fixed_memory32.address_length = p->end - p->start + 1;
++ fixed_memory32->address = p->start;
++ fixed_memory32->address_length = p->end - p->start + 1;
++
++ dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx "
++ "write_protect %#x\n",
++ (unsigned long long) p->start, (unsigned long long) p->end,
++ fixed_memory32->write_protect);
+ }
+
+-int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
+- struct acpi_buffer *buffer)
++int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer)
+ {
+ int i = 0;
+ /* pnpacpi_build_resource_template allocates extra mem */
+@@ -922,58 +968,48 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
+ struct acpi_resource *resource = buffer->pointer;
+ int port = 0, irq = 0, dma = 0, mem = 0;
+
+- pnp_dbg("res cnt %d", res_cnt);
++ dev_dbg(&dev->dev, "encode %d resources\n", res_cnt);
+ while (i < res_cnt) {
+ switch (resource->type) {
+ case ACPI_RESOURCE_TYPE_IRQ:
+- pnp_dbg("Encode irq");
+- pnpacpi_encode_irq(resource,
+- &res_table->irq_resource[irq]);
++ pnpacpi_encode_irq(dev, resource,
++ pnp_get_resource(dev, IORESOURCE_IRQ, irq));
+ irq++;
+ break;
+
+ case ACPI_RESOURCE_TYPE_DMA:
+- pnp_dbg("Encode dma");
+- pnpacpi_encode_dma(resource,
+- &res_table->dma_resource[dma]);
++ pnpacpi_encode_dma(dev, resource,
++ pnp_get_resource(dev, IORESOURCE_DMA, dma));
+ dma++;
+ break;
+ case ACPI_RESOURCE_TYPE_IO:
+- pnp_dbg("Encode io");
+- pnpacpi_encode_io(resource,
+- &res_table->port_resource[port]);
++ pnpacpi_encode_io(dev, resource,
++ pnp_get_resource(dev, IORESOURCE_IO, port));
+ port++;
+ break;
+ case ACPI_RESOURCE_TYPE_FIXED_IO:
+- pnp_dbg("Encode fixed io");
+- pnpacpi_encode_fixed_io(resource,
+- &res_table->
+- port_resource[port]);
++ pnpacpi_encode_fixed_io(dev, resource,
++ pnp_get_resource(dev, IORESOURCE_IO, port));
+ port++;
+ break;
+ case ACPI_RESOURCE_TYPE_MEMORY24:
+- pnp_dbg("Encode mem24");
+- pnpacpi_encode_mem24(resource,
+- &res_table->mem_resource[mem]);
++ pnpacpi_encode_mem24(dev, resource,
++ pnp_get_resource(dev, IORESOURCE_MEM, mem));
+ mem++;
+ break;
+ case ACPI_RESOURCE_TYPE_MEMORY32:
+- pnp_dbg("Encode mem32");
+- pnpacpi_encode_mem32(resource,
+- &res_table->mem_resource[mem]);
++ pnpacpi_encode_mem32(dev, resource,
++ pnp_get_resource(dev, IORESOURCE_MEM, mem));
+ mem++;
+ break;
+ case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+- pnp_dbg("Encode fixed mem32");
+- pnpacpi_encode_fixed_mem32(resource,
+- &res_table->
+- mem_resource[mem]);
++ pnpacpi_encode_fixed_mem32(dev, resource,
++ pnp_get_resource(dev, IORESOURCE_MEM, mem));
+ mem++;
+ break;
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+- pnp_dbg("Encode ext irq");
+- pnpacpi_encode_ext_irq(resource,
+- &res_table->irq_resource[irq]);
++ pnpacpi_encode_ext_irq(dev, resource,
++ pnp_get_resource(dev, IORESOURCE_IRQ, irq));
+ irq++;
+ break;
+ case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+@@ -986,7 +1022,8 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
+ case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+ case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
+ default: /* other type */
+- pnp_warn("unknown resource type %d", resource->type);
++ dev_warn(&dev->dev, "can't encode unknown resource "
++ "type %d\n", resource->type);
+ return -EINVAL;
+ }
+ resource++;
+diff --git a/drivers/pnp/pnpbios/Makefile b/drivers/pnp/pnpbios/Makefile
+index 3cd3ed7..310e2b3 100644
+--- a/drivers/pnp/pnpbios/Makefile
++++ b/drivers/pnp/pnpbios/Makefile
+@@ -5,3 +5,7 @@
+ pnpbios-proc-$(CONFIG_PNPBIOS_PROC_FS) = proc.o
+
+ obj-y := core.o bioscalls.o rsparser.o $(pnpbios-proc-y)
++
++ifeq ($(CONFIG_PNP_DEBUG),y)
++EXTRA_CFLAGS += -DDEBUG
++endif
+diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c
+index a8364d8..7ff8244 100644
+--- a/drivers/pnp/pnpbios/bioscalls.c
++++ b/drivers/pnp/pnpbios/bioscalls.c
+@@ -7,7 +7,6 @@
+ #include <linux/init.h>
+ #include <linux/linkage.h>
+ #include <linux/kernel.h>
+-#include <linux/pnpbios.h>
+ #include <linux/device.h>
+ #include <linux/pnp.h>
+ #include <linux/mm.h>
+diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
+index a8a5150..19a4be1 100644
+--- a/drivers/pnp/pnpbios/core.c
++++ b/drivers/pnp/pnpbios/core.c
+@@ -50,7 +50,6 @@
+ #include <linux/init.h>
+ #include <linux/linkage.h>
+ #include <linux/kernel.h>
+-#include <linux/pnpbios.h>
+ #include <linux/device.h>
+ #include <linux/pnp.h>
+ #include <linux/mm.h>
+@@ -69,6 +68,7 @@
+ #include <asm/system.h>
+ #include <asm/byteorder.h>
+
++#include "../base.h"
+ #include "pnpbios.h"
+
+ /*
+@@ -203,8 +203,7 @@ static int pnp_dock_thread(void *unused)
+
+ #endif /* CONFIG_HOTPLUG */
+
+-static int pnpbios_get_resources(struct pnp_dev *dev,
+- struct pnp_resource_table *res)
++static int pnpbios_get_resources(struct pnp_dev *dev)
+ {
+ u8 nodenum = dev->number;
+ struct pnp_bios_node *node;
+@@ -212,6 +211,7 @@ static int pnpbios_get_resources(struct pnp_dev *dev,
+ if (!pnpbios_is_dynamic(dev))
+ return -EPERM;
+
++ dev_dbg(&dev->dev, "get resources\n");
+ node = kzalloc(node_info.max_node_size, GFP_KERNEL);
+ if (!node)
+ return -1;
+@@ -219,14 +219,13 @@ static int pnpbios_get_resources(struct pnp_dev *dev,
+ kfree(node);
+ return -ENODEV;
+ }
+- pnpbios_read_resources_from_node(res, node);
++ pnpbios_read_resources_from_node(dev, node);
+ dev->active = pnp_is_active(dev);
+ kfree(node);
+ return 0;
+ }
+
+-static int pnpbios_set_resources(struct pnp_dev *dev,
+- struct pnp_resource_table *res)
++static int pnpbios_set_resources(struct pnp_dev *dev)
+ {
+ u8 nodenum = dev->number;
+ struct pnp_bios_node *node;
+@@ -235,6 +234,7 @@ static int pnpbios_set_resources(struct pnp_dev *dev,
+ if (!pnpbios_is_dynamic(dev))
+ return -EPERM;
+
++ dev_dbg(&dev->dev, "set resources\n");
+ node = kzalloc(node_info.max_node_size, GFP_KERNEL);
+ if (!node)
+ return -1;
+@@ -242,7 +242,7 @@ static int pnpbios_set_resources(struct pnp_dev *dev,
+ kfree(node);
+ return -ENODEV;
+ }
+- if (pnpbios_write_resources_to_node(res, node) < 0) {
++ if (pnpbios_write_resources_to_node(dev, node) < 0) {
+ kfree(node);
+ return -1;
+ }
+@@ -317,7 +317,6 @@ static int __init insert_device(struct pnp_bios_node *node)
+ {
+ struct list_head *pos;
+ struct pnp_dev *dev;
+- struct pnp_id *dev_id;
+ char id[8];
+
+ /* check if the device is already added */
+@@ -327,20 +326,11 @@ static int __init insert_device(struct pnp_bios_node *node)
+ return -1;
+ }
+
+- dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
++ pnp_eisa_id_to_string(node->eisa_id & PNP_EISA_ID_MASK, id);
++ dev = pnp_alloc_dev(&pnpbios_protocol, node->handle, id);
+ if (!dev)
+ return -1;
+
+- dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
+- if (!dev_id) {
+- kfree(dev);
+- return -1;
+- }
+-
+- dev->number = node->handle;
+- pnpid32_to_pnpid(node->eisa_id, id);
+- memcpy(dev_id->id, id, 7);
+- pnp_add_id(dev_id, dev);
+ pnpbios_parse_data_stream(dev, node);
+ dev->active = pnp_is_active(dev);
+ dev->flags = node->flags;
+@@ -353,11 +343,10 @@ static int __init insert_device(struct pnp_bios_node *node)
+ dev->capabilities |= PNP_WRITE;
+ if (dev->flags & PNPBIOS_REMOVABLE)
+ dev->capabilities |= PNP_REMOVABLE;
+- dev->protocol = &pnpbios_protocol;
+
+ /* clear out the damaged flags */
+ if (!dev->active)
+- pnp_init_resource_table(&dev->res);
++ pnp_init_resources(dev);
+
+ pnp_add_device(dev);
+ pnpbios_interface_attach_device(node);
+diff --git a/drivers/pnp/pnpbios/pnpbios.h b/drivers/pnp/pnpbios/pnpbios.h
+index d8cb2fd..b09cf6d 100644
+--- a/drivers/pnp/pnpbios/pnpbios.h
++++ b/drivers/pnp/pnpbios/pnpbios.h
+@@ -2,6 +2,142 @@
+ * pnpbios.h - contains local definitions
+ */
+
++/*
++ * Include file for the interface to a PnP BIOS
++ *
++ * Original BIOS code (C) 1998 Christian Schmidt (chr.schmidt at tu-bs.de)
++ * PnP handler parts (c) 1998 Tom Lees <tom at lpsg.demon.co.uk>
++ * Minor reorganizations by David Hinds <dahinds at users.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, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You 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
++ */
++
++/*
++ * Return codes
++ */
++#define PNP_SUCCESS 0x00
++#define PNP_NOT_SET_STATICALLY 0x7f
++#define PNP_UNKNOWN_FUNCTION 0x81
++#define PNP_FUNCTION_NOT_SUPPORTED 0x82
++#define PNP_INVALID_HANDLE 0x83
++#define PNP_BAD_PARAMETER 0x84
++#define PNP_SET_FAILED 0x85
++#define PNP_EVENTS_NOT_PENDING 0x86
++#define PNP_SYSTEM_NOT_DOCKED 0x87
++#define PNP_NO_ISA_PNP_CARDS 0x88
++#define PNP_UNABLE_TO_DETERMINE_DOCK_CAPABILITIES 0x89
++#define PNP_CONFIG_CHANGE_FAILED_NO_BATTERY 0x8a
++#define PNP_CONFIG_CHANGE_FAILED_RESOURCE_CONFLICT 0x8b
++#define PNP_BUFFER_TOO_SMALL 0x8c
++#define PNP_USE_ESCD_SUPPORT 0x8d
++#define PNP_MESSAGE_NOT_SUPPORTED 0x8e
++#define PNP_HARDWARE_ERROR 0x8f
++
++#define ESCD_SUCCESS 0x00
++#define ESCD_IO_ERROR_READING 0x55
++#define ESCD_INVALID 0x56
++#define ESCD_BUFFER_TOO_SMALL 0x59
++#define ESCD_NVRAM_TOO_SMALL 0x5a
++#define ESCD_FUNCTION_NOT_SUPPORTED 0x81
++
++/*
++ * Events that can be received by "get event"
++ */
++#define PNPEV_ABOUT_TO_CHANGE_CONFIG 0x0001
++#define PNPEV_DOCK_CHANGED 0x0002
++#define PNPEV_SYSTEM_DEVICE_CHANGED 0x0003
++#define PNPEV_CONFIG_CHANGED_FAILED 0x0004
++#define PNPEV_UNKNOWN_SYSTEM_EVENT 0xffff
++/* 0x8000 through 0xfffe are OEM defined */
++
++/*
++ * Messages that should be sent through "send message"
++ */
++#define PNPMSG_OK 0x00
++#define PNPMSG_ABORT 0x01
++#define PNPMSG_UNDOCK_DEFAULT_ACTION 0x40
++#define PNPMSG_POWER_OFF 0x41
++#define PNPMSG_PNP_OS_ACTIVE 0x42
++#define PNPMSG_PNP_OS_INACTIVE 0x43
++
++/*
++ * Plug and Play BIOS flags
++ */
++#define PNPBIOS_NO_DISABLE 0x0001
++#define PNPBIOS_NO_CONFIG 0x0002
++#define PNPBIOS_OUTPUT 0x0004
++#define PNPBIOS_INPUT 0x0008
++#define PNPBIOS_BOOTABLE 0x0010
++#define PNPBIOS_DOCK 0x0020
++#define PNPBIOS_REMOVABLE 0x0040
++#define pnpbios_is_static(x) (((x)->flags & 0x0100) == 0x0000)
++#define pnpbios_is_dynamic(x) ((x)->flags & 0x0080)
++
++/*
++ * Function Parameters
++ */
++#define PNPMODE_STATIC 1
++#define PNPMODE_DYNAMIC 0
++
++/* 0x8000 through 0xffff are OEM defined */
++
++#pragma pack(1)
++struct pnp_dev_node_info {
++ __u16 no_nodes;
++ __u16 max_node_size;
++};
++struct pnp_docking_station_info {
++ __u32 location_id;
++ __u32 serial;
++ __u16 capabilities;
++};
++struct pnp_isa_config_struc {
++ __u8 revision;
++ __u8 no_csns;
++ __u16 isa_rd_data_port;
++ __u16 reserved;
++};
++struct escd_info_struc {
++ __u16 min_escd_write_size;
++ __u16 escd_size;
++ __u32 nv_storage_base;
++};
++struct pnp_bios_node {
++ __u16 size;
++ __u8 handle;
++ __u32 eisa_id;
++ __u8 type_code[3];
++ __u16 flags;
++ __u8 data[0];
++};
++#pragma pack()
++
++/* non-exported */
++extern struct pnp_dev_node_info node_info;
++
++extern int pnp_bios_dev_node_info(struct pnp_dev_node_info *data);
++extern int pnp_bios_get_dev_node(u8 *nodenum, char config,
++ struct pnp_bios_node *data);
++extern int pnp_bios_set_dev_node(u8 nodenum, char config,
++ struct pnp_bios_node *data);
++extern int pnp_bios_get_stat_res(char *info);
++extern int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data);
++extern int pnp_bios_escd_info(struct escd_info_struc *data);
++extern int pnp_bios_read_escd(char *data, u32 nvram_base);
++extern int pnp_bios_dock_station_info(struct pnp_docking_station_info *data);
++
+ #pragma pack(1)
+ union pnp_bios_install_struct {
+ struct {
+@@ -28,8 +164,8 @@ extern int pnp_bios_present(void);
+ extern int pnpbios_dont_use_current_config;
+
+ extern int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node * node);
+-extern int pnpbios_read_resources_from_node(struct pnp_resource_table *res, struct pnp_bios_node * node);
+-extern int pnpbios_write_resources_to_node(struct pnp_resource_table *res, struct pnp_bios_node * node);
++extern int pnpbios_read_resources_from_node(struct pnp_dev *dev, struct pnp_bios_node *node);
++extern int pnpbios_write_resources_to_node(struct pnp_dev *dev, struct pnp_bios_node *node);
+ extern void pnpid32_to_pnpid(u32 id, char *str);
+
+ extern void pnpbios_print_status(const char * module, u16 status);
+diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c
+index bb19bc9..b35d921 100644
+--- a/drivers/pnp/pnpbios/proc.c
++++ b/drivers/pnp/pnpbios/proc.c
+@@ -23,7 +23,7 @@
+ #include <linux/slab.h>
+ #include <linux/types.h>
+ #include <linux/proc_fs.h>
+-#include <linux/pnpbios.h>
++#include <linux/pnp.h>
+ #include <linux/init.h>
+
+ #include <asm/uaccess.h>
+@@ -256,7 +256,7 @@ int pnpbios_interface_attach_device(struct pnp_bios_node *node)
+ */
+ int __init pnpbios_proc_init(void)
+ {
+- proc_pnp = proc_mkdir("pnp", proc_bus);
++ proc_pnp = proc_mkdir("bus/pnp", NULL);
+ if (!proc_pnp)
+ return -EIO;
+ proc_pnp_boot = proc_mkdir("boot", proc_pnp);
+@@ -294,5 +294,5 @@ void __exit pnpbios_proc_exit(void)
+ remove_proc_entry("configuration_info", proc_pnp);
+ remove_proc_entry("devices", proc_pnp);
+ remove_proc_entry("boot", proc_pnp);
+- remove_proc_entry("pnp", proc_bus);
++ remove_proc_entry("bus/pnp", NULL);
+ }
+diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
+index caade35..2e2c457 100644
+--- a/drivers/pnp/pnpbios/rsparser.c
++++ b/drivers/pnp/pnpbios/rsparser.c
+@@ -4,7 +4,6 @@
+
+ #include <linux/ctype.h>
+ #include <linux/pnp.h>
+-#include <linux/pnpbios.h>
+ #include <linux/string.h>
+ #include <linux/slab.h>
+
+@@ -16,6 +15,7 @@ inline void pcibios_penalize_isa_irq(int irq, int active)
+ }
+ #endif /* CONFIG_PCI */
+
++#include "../base.h"
+ #include "pnpbios.h"
+
+ /* standard resource tags */
+@@ -53,97 +53,43 @@ inline void pcibios_penalize_isa_irq(int irq, int active)
+ * Allocated Resources
+ */
+
+-static void pnpbios_parse_allocated_irqresource(struct pnp_resource_table *res,
+- int irq)
++static void pnpbios_parse_allocated_ioresource(struct pnp_dev *dev,
++ int start, int len)
+ {
+- int i = 0;
+-
+- while (!(res->irq_resource[i].flags & IORESOURCE_UNSET)
+- && i < PNP_MAX_IRQ)
+- i++;
+- if (i < PNP_MAX_IRQ) {
+- res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag
+- if (irq == -1) {
+- res->irq_resource[i].flags |= IORESOURCE_DISABLED;
+- return;
+- }
+- res->irq_resource[i].start =
+- res->irq_resource[i].end = (unsigned long)irq;
+- pcibios_penalize_isa_irq(irq, 1);
+- }
+-}
++ int flags = 0;
++ int end = start + len - 1;
+
+-static void pnpbios_parse_allocated_dmaresource(struct pnp_resource_table *res,
+- int dma)
+-{
+- int i = 0;
+-
+- while (i < PNP_MAX_DMA &&
+- !(res->dma_resource[i].flags & IORESOURCE_UNSET))
+- i++;
+- if (i < PNP_MAX_DMA) {
+- res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag
+- if (dma == -1) {
+- res->dma_resource[i].flags |= IORESOURCE_DISABLED;
+- return;
+- }
+- res->dma_resource[i].start =
+- res->dma_resource[i].end = (unsigned long)dma;
+- }
+-}
++ if (len <= 0 || end >= 0x10003)
++ flags |= IORESOURCE_DISABLED;
+
+-static void pnpbios_parse_allocated_ioresource(struct pnp_resource_table *res,
+- int io, int len)
+-{
+- int i = 0;
+-
+- while (!(res->port_resource[i].flags & IORESOURCE_UNSET)
+- && i < PNP_MAX_PORT)
+- i++;
+- if (i < PNP_MAX_PORT) {
+- res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag
+- if (len <= 0 || (io + len - 1) >= 0x10003) {
+- res->port_resource[i].flags |= IORESOURCE_DISABLED;
+- return;
+- }
+- res->port_resource[i].start = (unsigned long)io;
+- res->port_resource[i].end = (unsigned long)(io + len - 1);
+- }
++ pnp_add_io_resource(dev, start, end, flags);
+ }
+
+-static void pnpbios_parse_allocated_memresource(struct pnp_resource_table *res,
+- int mem, int len)
++static void pnpbios_parse_allocated_memresource(struct pnp_dev *dev,
++ int start, int len)
+ {
+- int i = 0;
+-
+- while (!(res->mem_resource[i].flags & IORESOURCE_UNSET)
+- && i < PNP_MAX_MEM)
+- i++;
+- if (i < PNP_MAX_MEM) {
+- res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag
+- if (len <= 0) {
+- res->mem_resource[i].flags |= IORESOURCE_DISABLED;
+- return;
+- }
+- res->mem_resource[i].start = (unsigned long)mem;
+- res->mem_resource[i].end = (unsigned long)(mem + len - 1);
+- }
++ int flags = 0;
++ int end = start + len - 1;
++
++ if (len <= 0)
++ flags |= IORESOURCE_DISABLED;
++
++ pnp_add_mem_resource(dev, start, end, flags);
+ }
+
+-static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
+- unsigned char *end,
+- struct
+- pnp_resource_table
+- *res)
++static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev,
++ unsigned char *p,
++ unsigned char *end)
+ {
+ unsigned int len, tag;
+- int io, size, mask, i;
++ int io, size, mask, i, flags;
+
+ if (!p)
+ return NULL;
+
+- /* Blank the resource table values */
+- pnp_init_resource_table(res);
++ dev_dbg(&dev->dev, "parse allocated resources\n");
++
++ pnp_init_resources(dev);
+
+ while ((char *)p < (char *)end) {
+
+@@ -163,7 +109,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
+ goto len_err;
+ io = *(short *)&p[4];
+ size = *(short *)&p[10];
+- pnpbios_parse_allocated_memresource(res, io, size);
++ pnpbios_parse_allocated_memresource(dev, io, size);
+ break;
+
+ case LARGE_TAG_ANSISTR:
+@@ -179,7 +125,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
+ goto len_err;
+ io = *(int *)&p[4];
+ size = *(int *)&p[16];
+- pnpbios_parse_allocated_memresource(res, io, size);
++ pnpbios_parse_allocated_memresource(dev, io, size);
+ break;
+
+ case LARGE_TAG_FIXEDMEM32:
+@@ -187,29 +133,37 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
+ goto len_err;
+ io = *(int *)&p[4];
+ size = *(int *)&p[8];
+- pnpbios_parse_allocated_memresource(res, io, size);
++ pnpbios_parse_allocated_memresource(dev, io, size);
+ break;
+
+ case SMALL_TAG_IRQ:
+ if (len < 2 || len > 3)
+ goto len_err;
++ flags = 0;
+ io = -1;
+ mask = p[1] + p[2] * 256;
+ for (i = 0; i < 16; i++, mask = mask >> 1)
+ if (mask & 0x01)
+ io = i;
+- pnpbios_parse_allocated_irqresource(res, io);
++ if (io != -1)
++ pcibios_penalize_isa_irq(io, 1);
++ else
++ flags = IORESOURCE_DISABLED;
++ pnp_add_irq_resource(dev, io, flags);
+ break;
+
+ case SMALL_TAG_DMA:
+ if (len != 2)
+ goto len_err;
++ flags = 0;
+ io = -1;
+ mask = p[1];
+ for (i = 0; i < 8; i++, mask = mask >> 1)
+ if (mask & 0x01)
+ io = i;
+- pnpbios_parse_allocated_dmaresource(res, io);
++ if (io == -1)
++ flags = IORESOURCE_DISABLED;
++ pnp_add_dma_resource(dev, io, flags);
+ break;
+
+ case SMALL_TAG_PORT:
+@@ -217,7 +171,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
+ goto len_err;
+ io = p[2] + p[3] * 256;
+ size = p[7];
+- pnpbios_parse_allocated_ioresource(res, io, size);
++ pnpbios_parse_allocated_ioresource(dev, io, size);
+ break;
+
+ case SMALL_TAG_VENDOR:
+@@ -229,7 +183,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
+ goto len_err;
+ io = p[1] + p[2] * 256;
+ size = p[3];
+- pnpbios_parse_allocated_ioresource(res, io, size);
++ pnpbios_parse_allocated_ioresource(dev, io, size);
+ break;
+
+ case SMALL_TAG_END:
+@@ -239,9 +193,8 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
+
+ default: /* an unkown tag */
+ len_err:
+- printk(KERN_ERR
+- "PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
+- tag, len);
++ dev_err(&dev->dev, "unknown tag %#x length %d\n",
++ tag, len);
+ break;
+ }
+
+@@ -252,8 +205,7 @@ len_err:
+ p += len + 1;
+ }
+
+- printk(KERN_ERR
+- "PnPBIOS: Resource structure does not contain an end tag.\n");
++ dev_err(&dev->dev, "no end tag in resource structure\n");
+
+ return NULL;
+ }
+@@ -262,7 +214,8 @@ len_err:
+ * Resource Configuration Options
+ */
+
+-static __init void pnpbios_parse_mem_option(unsigned char *p, int size,
++static __init void pnpbios_parse_mem_option(struct pnp_dev *dev,
++ unsigned char *p, int size,
+ struct pnp_option *option)
+ {
+ struct pnp_mem *mem;
+@@ -275,10 +228,11 @@ static __init void pnpbios_parse_mem_option(unsigned char *p, int size,
+ mem->align = (p[9] << 8) | p[8];
+ mem->size = ((p[11] << 8) | p[10]) << 8;
+ mem->flags = p[3];
+- pnp_register_mem_resource(option, mem);
++ pnp_register_mem_resource(dev, option, mem);
+ }
+
+-static __init void pnpbios_parse_mem32_option(unsigned char *p, int size,
++static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev,
++ unsigned char *p, int size,
+ struct pnp_option *option)
+ {
+ struct pnp_mem *mem;
+@@ -291,10 +245,11 @@ static __init void pnpbios_parse_mem32_option(unsigned char *p, int size,
+ mem->align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12];
+ mem->size = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16];
+ mem->flags = p[3];
+- pnp_register_mem_resource(option, mem);
++ pnp_register_mem_resource(dev, option, mem);
+ }
+
+-static __init void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size,
++static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev,
++ unsigned char *p, int size,
+ struct pnp_option *option)
+ {
+ struct pnp_mem *mem;
+@@ -306,11 +261,12 @@ static __init void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size,
+ mem->size = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
+ mem->align = 0;
+ mem->flags = p[3];
+- pnp_register_mem_resource(option, mem);
++ pnp_register_mem_resource(dev, option, mem);
+ }
+
+-static __init void pnpbios_parse_irq_option(unsigned char *p, int size,
+- struct pnp_option *option)
++static __init void pnpbios_parse_irq_option(struct pnp_dev *dev,
++ unsigned char *p, int size,
++ struct pnp_option *option)
+ {
+ struct pnp_irq *irq;
+ unsigned long bits;
+@@ -324,11 +280,12 @@ static __init void pnpbios_parse_irq_option(unsigned char *p, int size,
+ irq->flags = p[3];
+ else
+ irq->flags = IORESOURCE_IRQ_HIGHEDGE;
+- pnp_register_irq_resource(option, irq);
++ pnp_register_irq_resource(dev, option, irq);
+ }
+
+-static __init void pnpbios_parse_dma_option(unsigned char *p, int size,
+- struct pnp_option *option)
++static __init void pnpbios_parse_dma_option(struct pnp_dev *dev,
++ unsigned char *p, int size,
++ struct pnp_option *option)
+ {
+ struct pnp_dma *dma;
+
+@@ -337,10 +294,11 @@ static __init void pnpbios_parse_dma_option(unsigned char *p, int size,
+ return;
+ dma->map = p[1];
+ dma->flags = p[2];
+- pnp_register_dma_resource(option, dma);
++ pnp_register_dma_resource(dev, option, dma);
+ }
+
+-static __init void pnpbios_parse_port_option(unsigned char *p, int size,
++static __init void pnpbios_parse_port_option(struct pnp_dev *dev,
++ unsigned char *p, int size,
+ struct pnp_option *option)
+ {
+ struct pnp_port *port;
+@@ -353,10 +311,11 @@ static __init void pnpbios_parse_port_option(unsigned char *p, int size,
+ port->align = p[6];
+ port->size = p[7];
+ port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0;
+- pnp_register_port_resource(option, port);
++ pnp_register_port_resource(dev, option, port);
+ }
+
+-static __init void pnpbios_parse_fixed_port_option(unsigned char *p, int size,
++static __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev,
++ unsigned char *p, int size,
+ struct pnp_option *option)
+ {
+ struct pnp_port *port;
+@@ -368,7 +327,7 @@ static __init void pnpbios_parse_fixed_port_option(unsigned char *p, int size,
+ port->size = p[3];
+ port->align = 0;
+ port->flags = PNP_PORT_FLAG_FIXED;
+- pnp_register_port_resource(option, port);
++ pnp_register_port_resource(dev, option, port);
+ }
+
+ static __init unsigned char *
+@@ -382,6 +341,8 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
+ if (!p)
+ return NULL;
+
++ dev_dbg(&dev->dev, "parse resource options\n");
++
+ option_independent = option = pnp_register_independent_option(dev);
+ if (!option)
+ return NULL;
+@@ -402,37 +363,37 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
+ case LARGE_TAG_MEM:
+ if (len != 9)
+ goto len_err;
+- pnpbios_parse_mem_option(p, len, option);
++ pnpbios_parse_mem_option(dev, p, len, option);
+ break;
+
+ case LARGE_TAG_MEM32:
+ if (len != 17)
+ goto len_err;
+- pnpbios_parse_mem32_option(p, len, option);
++ pnpbios_parse_mem32_option(dev, p, len, option);
+ break;
+
+ case LARGE_TAG_FIXEDMEM32:
+ if (len != 9)
+ goto len_err;
+- pnpbios_parse_fixed_mem32_option(p, len, option);
++ pnpbios_parse_fixed_mem32_option(dev, p, len, option);
+ break;
+
+ case SMALL_TAG_IRQ:
+ if (len < 2 || len > 3)
+ goto len_err;
+- pnpbios_parse_irq_option(p, len, option);
++ pnpbios_parse_irq_option(dev, p, len, option);
+ break;
+
+ case SMALL_TAG_DMA:
+ if (len != 2)
+ goto len_err;
+- pnpbios_parse_dma_option(p, len, option);
++ pnpbios_parse_dma_option(dev, p, len, option);
+ break;
+
+ case SMALL_TAG_PORT:
+ if (len != 7)
+ goto len_err;
+- pnpbios_parse_port_option(p, len, option);
++ pnpbios_parse_port_option(dev, p, len, option);
+ break;
+
+ case SMALL_TAG_VENDOR:
+@@ -442,7 +403,7 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
+ case SMALL_TAG_FIXEDPORT:
+ if (len != 3)
+ goto len_err;
+- pnpbios_parse_fixed_port_option(p, len, option);
++ pnpbios_parse_fixed_port_option(dev, p, len, option);
+ break;
+
+ case SMALL_TAG_STARTDEP:
+@@ -460,9 +421,10 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
+ if (len != 0)
+ goto len_err;
+ if (option_independent == option)
+- printk(KERN_WARNING
+- "PnPBIOS: Missing SMALL_TAG_STARTDEP tag\n");
++ dev_warn(&dev->dev, "missing "
++ "SMALL_TAG_STARTDEP tag\n");
+ option = option_independent;
++ dev_dbg(&dev->dev, "end dependent options\n");
+ break;
+
+ case SMALL_TAG_END:
+@@ -470,9 +432,8 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
+
+ default: /* an unkown tag */
+ len_err:
+- printk(KERN_ERR
+- "PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
+- tag, len);
++ dev_err(&dev->dev, "unknown tag %#x length %d\n",
++ tag, len);
+ break;
+ }
+
+@@ -483,8 +444,7 @@ len_err:
+ p += len + 1;
+ }
+
+- printk(KERN_ERR
+- "PnPBIOS: Resource structure does not contain an end tag.\n");
++ dev_err(&dev->dev, "no end tag in resource structure\n");
+
+ return NULL;
+ }
+@@ -493,32 +453,12 @@ len_err:
+ * Compatible Device IDs
+ */
+
+-#define HEX(id,a) hex[((id)>>a) & 15]
+-#define CHAR(id,a) (0x40 + (((id)>>a) & 31))
+-
+-void pnpid32_to_pnpid(u32 id, char *str)
+-{
+- const char *hex = "0123456789abcdef";
+-
+- id = be32_to_cpu(id);
+- str[0] = CHAR(id, 26);
+- str[1] = CHAR(id, 21);
+- str[2] = CHAR(id, 16);
+- str[3] = HEX(id, 12);
+- str[4] = HEX(id, 8);
+- str[5] = HEX(id, 4);
+- str[6] = HEX(id, 0);
+- str[7] = '\0';
+-}
+-
+-#undef CHAR
+-#undef HEX
+-
+ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p,
+ unsigned char *end,
+ struct pnp_dev *dev)
+ {
+ int len, tag;
++ u32 eisa_id;
+ char id[8];
+ struct pnp_id *dev_id;
+
+@@ -548,13 +488,11 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p,
+ case SMALL_TAG_COMPATDEVID: /* compatible ID */
+ if (len != 4)
+ goto len_err;
+- dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
++ eisa_id = p[1] | p[2] << 8 | p[3] << 16 | p[4] << 24;
++ pnp_eisa_id_to_string(eisa_id & PNP_EISA_ID_MASK, id);
++ dev_id = pnp_add_id(dev, id);
+ if (!dev_id)
+ return NULL;
+- pnpid32_to_pnpid(p[1] | p[2] << 8 | p[3] << 16 | p[4] <<
+- 24, id);
+- memcpy(&dev_id->id, id, 7);
+- pnp_add_id(dev_id, dev);
+ break;
+
+ case SMALL_TAG_END:
+@@ -564,9 +502,8 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p,
+
+ default: /* an unkown tag */
+ len_err:
+- printk(KERN_ERR
+- "PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
+- tag, len);
++ dev_err(&dev->dev, "unknown tag %#x length %d\n",
++ tag, len);
+ break;
+ }
+
+@@ -577,8 +514,7 @@ len_err:
+ p += len + 1;
+ }
+
+- printk(KERN_ERR
+- "PnPBIOS: Resource structure does not contain an end tag.\n");
++ dev_err(&dev->dev, "no end tag in resource structure\n");
+
+ return NULL;
+ }
+@@ -587,7 +523,8 @@ len_err:
+ * Allocated Resource Encoding
+ */
+
+-static void pnpbios_encode_mem(unsigned char *p, struct resource *res)
++static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p,
++ struct resource *res)
+ {
+ unsigned long base = res->start;
+ unsigned long len = res->end - res->start + 1;
+@@ -598,9 +535,13 @@ static void pnpbios_encode_mem(unsigned char *p, struct resource *res)
+ p[7] = ((base >> 8) >> 8) & 0xff;
+ p[10] = (len >> 8) & 0xff;
+ p[11] = ((len >> 8) >> 8) & 0xff;
++
++ dev_dbg(&dev->dev, " encode mem %#llx-%#llx\n",
++ (unsigned long long) res->start, (unsigned long long) res->end);
+ }
+
+-static void pnpbios_encode_mem32(unsigned char *p, struct resource *res)
++static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
++ struct resource *res)
+ {
+ unsigned long base = res->start;
+ unsigned long len = res->end - res->start + 1;
+@@ -617,9 +558,13 @@ static void pnpbios_encode_mem32(unsigned char *p, struct resource *res)
+ p[17] = (len >> 8) & 0xff;
+ p[18] = (len >> 16) & 0xff;
+ p[19] = (len >> 24) & 0xff;
++
++ dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx\n",
++ (unsigned long long) res->start, (unsigned long long) res->end);
+ }
+
+-static void pnpbios_encode_fixed_mem32(unsigned char *p, struct resource *res)
++static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
++ struct resource *res)
+ {
+ unsigned long base = res->start;
+ unsigned long len = res->end - res->start + 1;
+@@ -632,26 +577,36 @@ static void pnpbios_encode_fixed_mem32(unsigned char *p, struct resource *res)
+ p[9] = (len >> 8) & 0xff;
+ p[10] = (len >> 16) & 0xff;
+ p[11] = (len >> 24) & 0xff;
++
++ dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx\n",
++ (unsigned long long) res->start, (unsigned long long) res->end);
+ }
+
+-static void pnpbios_encode_irq(unsigned char *p, struct resource *res)
++static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p,
++ struct resource *res)
+ {
+ unsigned long map = 0;
+
+ map = 1 << res->start;
+ p[1] = map & 0xff;
+ p[2] = (map >> 8) & 0xff;
++
++ dev_dbg(&dev->dev, " encode irq %d\n", res->start);
+ }
+
+-static void pnpbios_encode_dma(unsigned char *p, struct resource *res)
++static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p,
++ struct resource *res)
+ {
+ unsigned long map = 0;
+
+ map = 1 << res->start;
+ p[1] = map & 0xff;
++
++ dev_dbg(&dev->dev, " encode dma %d\n", res->start);
+ }
+
+-static void pnpbios_encode_port(unsigned char *p, struct resource *res)
++static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
++ struct resource *res)
+ {
+ unsigned long base = res->start;
+ unsigned long len = res->end - res->start + 1;
+@@ -661,9 +616,13 @@ static void pnpbios_encode_port(unsigned char *p, struct resource *res)
+ p[4] = base & 0xff;
+ p[5] = (base >> 8) & 0xff;
+ p[7] = len & 0xff;
++
++ dev_dbg(&dev->dev, " encode io %#llx-%#llx\n",
++ (unsigned long long) res->start, (unsigned long long) res->end);
+ }
+
+-static void pnpbios_encode_fixed_port(unsigned char *p, struct resource *res)
++static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p,
++ struct resource *res)
+ {
+ unsigned long base = res->start;
+ unsigned long len = res->end - res->start + 1;
+@@ -671,13 +630,15 @@ static void pnpbios_encode_fixed_port(unsigned char *p, struct resource *res)
+ p[1] = base & 0xff;
+ p[2] = (base >> 8) & 0xff;
+ p[3] = len & 0xff;
++
++ dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n",
++ (unsigned long long) res->start, (unsigned long long) res->end);
+ }
+
+-static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p,
+- unsigned char *end,
+- struct
+- pnp_resource_table
+- *res)
++static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev
++ *dev,
++ unsigned char *p,
++ unsigned char *end)
+ {
+ unsigned int len, tag;
+ int port = 0, irq = 0, dma = 0, mem = 0;
+@@ -701,42 +662,48 @@ static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p,
+ case LARGE_TAG_MEM:
+ if (len != 9)
+ goto len_err;
+- pnpbios_encode_mem(p, &res->mem_resource[mem]);
++ pnpbios_encode_mem(dev, p,
++ pnp_get_resource(dev, IORESOURCE_MEM, mem));
+ mem++;
+ break;
+
+ case LARGE_TAG_MEM32:
+ if (len != 17)
+ goto len_err;
+- pnpbios_encode_mem32(p, &res->mem_resource[mem]);
++ pnpbios_encode_mem32(dev, p,
++ pnp_get_resource(dev, IORESOURCE_MEM, mem));
+ mem++;
+ break;
+
+ case LARGE_TAG_FIXEDMEM32:
+ if (len != 9)
+ goto len_err;
+- pnpbios_encode_fixed_mem32(p, &res->mem_resource[mem]);
++ pnpbios_encode_fixed_mem32(dev, p,
++ pnp_get_resource(dev, IORESOURCE_MEM, mem));
+ mem++;
+ break;
+
+ case SMALL_TAG_IRQ:
+ if (len < 2 || len > 3)
+ goto len_err;
+- pnpbios_encode_irq(p, &res->irq_resource[irq]);
++ pnpbios_encode_irq(dev, p,
++ pnp_get_resource(dev, IORESOURCE_IRQ, irq));
+ irq++;
+ break;
+
+ case SMALL_TAG_DMA:
+ if (len != 2)
+ goto len_err;
+- pnpbios_encode_dma(p, &res->dma_resource[dma]);
++ pnpbios_encode_dma(dev, p,
++ pnp_get_resource(dev, IORESOURCE_DMA, dma));
+ dma++;
+ break;
+
+ case SMALL_TAG_PORT:
+ if (len != 7)
+ goto len_err;
+- pnpbios_encode_port(p, &res->port_resource[port]);
++ pnpbios_encode_port(dev, p,
++ pnp_get_resource(dev, IORESOURCE_IO, port));
+ port++;
+ break;
+
+@@ -747,7 +714,8 @@ static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p,
+ case SMALL_TAG_FIXEDPORT:
+ if (len != 3)
+ goto len_err;
+- pnpbios_encode_fixed_port(p, &res->port_resource[port]);
++ pnpbios_encode_fixed_port(dev, p,
++ pnp_get_resource(dev, IORESOURCE_IO, port));
+ port++;
+ break;
+
+@@ -758,9 +726,8 @@ static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p,
+
+ default: /* an unkown tag */
+ len_err:
+- printk(KERN_ERR
+- "PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
+- tag, len);
++ dev_err(&dev->dev, "unknown tag %#x length %d\n",
++ tag, len);
+ break;
+ }
+
+@@ -771,8 +738,7 @@ len_err:
+ p += len + 1;
+ }
+
+- printk(KERN_ERR
+- "PnPBIOS: Resource structure does not contain an end tag.\n");
++ dev_err(&dev->dev, "no end tag in resource structure\n");
+
+ return NULL;
+ }
+@@ -787,7 +753,7 @@ int __init pnpbios_parse_data_stream(struct pnp_dev *dev,
+ unsigned char *p = (char *)node->data;
+ unsigned char *end = (char *)(node->data + node->size);
+
+- p = pnpbios_parse_allocated_resource_data(p, end, &dev->res);
++ p = pnpbios_parse_allocated_resource_data(dev, p, end);
+ if (!p)
+ return -EIO;
+ p = pnpbios_parse_resource_option_data(p, end, dev);
+@@ -799,25 +765,25 @@ int __init pnpbios_parse_data_stream(struct pnp_dev *dev,
+ return 0;
+ }
+
+-int pnpbios_read_resources_from_node(struct pnp_resource_table *res,
++int pnpbios_read_resources_from_node(struct pnp_dev *dev,
+ struct pnp_bios_node *node)
+ {
+ unsigned char *p = (char *)node->data;
+ unsigned char *end = (char *)(node->data + node->size);
+
+- p = pnpbios_parse_allocated_resource_data(p, end, res);
++ p = pnpbios_parse_allocated_resource_data(dev, p, end);
+ if (!p)
+ return -EIO;
+ return 0;
+ }
+
+-int pnpbios_write_resources_to_node(struct pnp_resource_table *res,
++int pnpbios_write_resources_to_node(struct pnp_dev *dev,
+ struct pnp_bios_node *node)
+ {
+ unsigned char *p = (char *)node->data;
+ unsigned char *end = (char *)(node->data + node->size);
+
+- p = pnpbios_encode_allocated_resource_data(p, end, res);
++ p = pnpbios_encode_allocated_resource_data(dev, p, end);
+ if (!p)
+ return -EIO;
+ return 0;
+diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
+index 3799320..d049a22 100644
+--- a/drivers/pnp/quirks.c
++++ b/drivers/pnp/quirks.c
+@@ -49,8 +49,11 @@ static void quirk_awe32_resources(struct pnp_dev *dev)
+ port2->max += 0x400;
+ port3->min += 0x800;
+ port3->max += 0x800;
++ dev_info(&dev->dev,
++ "AWE32 quirk - added ioports 0x%lx and 0x%lx\n",
++ (unsigned long)port2->min,
++ (unsigned long)port3->min);
+ }
+- printk(KERN_INFO "pnp: AWE32 quirk - adding two ports\n");
+ }
+
+ static void quirk_cmi8330_resources(struct pnp_dev *dev)
+@@ -73,7 +76,8 @@ static void quirk_cmi8330_resources(struct pnp_dev *dev)
+ IORESOURCE_DMA_8BIT)
+ dma->map = 0x000A;
+ }
+- printk(KERN_INFO "pnp: CMI8330 quirk - fixing interrupts and dma\n");
++ dev_info(&dev->dev, "CMI8330 quirk - forced possible IRQs to 5, 7, 10 "
++ "and DMA channels to 1, 3\n");
+ }
+
+ static void quirk_sb16audio_resources(struct pnp_dev *dev)
+@@ -104,8 +108,7 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev)
+ changed = 1;
+ }
+ if (changed)
+- printk(KERN_INFO
+- "pnp: SB audio device quirk - increasing port range\n");
++ dev_info(&dev->dev, "SB audio device quirk - increased port range\n");
+ }
+
+
+@@ -114,6 +117,7 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev)
+ static void quirk_system_pci_resources(struct pnp_dev *dev)
+ {
+ struct pci_dev *pdev = NULL;
++ struct resource *res;
+ resource_size_t pnp_start, pnp_end, pci_start, pci_end;
+ int i, j;
+
+@@ -134,13 +138,15 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
+
+ pci_start = pci_resource_start(pdev, i);
+ pci_end = pci_resource_end(pdev, i);
+- for (j = 0; j < PNP_MAX_MEM; j++) {
+- if (!pnp_mem_valid(dev, j) ||
+- pnp_mem_len(dev, j) == 0)
++ for (j = 0;
++ (res = pnp_get_resource(dev, IORESOURCE_MEM, j));
++ j++) {
++ if (res->flags & IORESOURCE_UNSET ||
++ (res->start == 0 && res->end == 0))
+ continue;
+
+- pnp_start = pnp_mem_start(dev, j);
+- pnp_end = pnp_mem_end(dev, j);
++ pnp_start = res->start;
++ pnp_end = res->end;
+
+ /*
+ * If the PNP region doesn't overlap the PCI
+@@ -173,7 +179,7 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
+ pci_name(pdev), i,
+ (unsigned long long) pci_start,
+ (unsigned long long) pci_end);
+- pnp_mem_flags(dev, j) = 0;
++ res->flags = 0;
+ }
+ }
+ }
+@@ -214,8 +220,8 @@ void pnp_fixup_device(struct pnp_dev *dev)
+ quirk = pnp_fixups[i].quirk_function;
+
+ #ifdef DEBUG
+- dev_dbg(&dev->dev, "calling quirk 0x%p", quirk);
+- print_fn_descriptor_symbol(": %s()\n",
++ dev_dbg(&dev->dev, "calling ");
++ print_fn_descriptor_symbol("%s()\n",
+ (unsigned long) *quirk);
+ #endif
+ (*quirk)(dev);
+diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
+index e50ebcf..2041620 100644
+--- a/drivers/pnp/resource.c
++++ b/drivers/pnp/resource.c
+@@ -53,6 +53,8 @@ struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev)
+ if (dev->independent)
+ dev_err(&dev->dev, "independent resource already registered\n");
+ dev->independent = option;
++
++ dev_dbg(&dev->dev, "new independent option\n");
+ return option;
+ }
+
+@@ -70,12 +72,18 @@ struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
+ parent->next = option;
+ } else
+ dev->dependent = option;
++
++ dev_dbg(&dev->dev, "new dependent option (priority %#x)\n", priority);
+ return option;
+ }
+
+-int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data)
++int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
++ struct pnp_irq *data)
+ {
+ struct pnp_irq *ptr;
++#ifdef DEBUG
++ char buf[PNP_IRQ_NR]; /* hex-encoded, so this is overkill but safe */
++#endif
+
+ ptr = option->irq;
+ while (ptr && ptr->next)
+@@ -94,10 +102,17 @@ int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data)
+ pcibios_penalize_isa_irq(i, 0);
+ }
+ #endif
++
++#ifdef DEBUG
++ bitmap_scnprintf(buf, sizeof(buf), data->map, PNP_IRQ_NR);
++ dev_dbg(&dev->dev, " irq bitmask %s flags %#x\n", buf,
++ data->flags);
++#endif
+ return 0;
+ }
+
+-int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data)
++int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option,
++ struct pnp_dma *data)
+ {
+ struct pnp_dma *ptr;
+
+@@ -109,10 +124,13 @@ int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data)
+ else
+ option->dma = data;
+
++ dev_dbg(&dev->dev, " dma bitmask %#x flags %#x\n", data->map,
++ data->flags);
+ return 0;
+ }
+
+-int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data)
++int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option,
++ struct pnp_port *data)
{
-- return pci_find_present(ids) == NULL ? 0 : 1;
--}
-+ struct pci_dev *found = NULL;
+ struct pnp_port *ptr;
-+ 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 */
+@@ -124,10 +142,14 @@ int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data)
+ else
+ option->port = data;
- /* 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)
++ dev_dbg(&dev->dev, " io "
++ "min %#x max %#x align %d size %d flags %#x\n",
++ data->min, data->max, data->align, data->size, data->flags);
+ return 0;
+ }
+
+-int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data)
++int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option,
++ struct pnp_mem *data)
{
- 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;
+ struct pnp_mem *ptr;
+
+@@ -138,6 +160,10 @@ int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data)
+ ptr->next = data;
+ else
+ option->mem = data;
++
++ dev_dbg(&dev->dev, " mem "
++ "min %#x max %#x align %d size %d flags %#x\n",
++ data->min, data->max, data->align, data->size, data->flags);
+ return 0;
}
- /* 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
+@@ -213,17 +239,18 @@ void pnp_free_option(struct pnp_option *option)
+ #define cannot_compare(flags) \
+ ((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED))
+
+-int pnp_check_port(struct pnp_dev *dev, int idx)
++int pnp_check_port(struct pnp_dev *dev, struct resource *res)
+ {
+- int tmp;
++ int i;
+ struct pnp_dev *tdev;
++ struct resource *tres;
+ resource_size_t *port, *end, *tport, *tend;
+
+- port = &dev->res.port_resource[idx].start;
+- end = &dev->res.port_resource[idx].end;
++ port = &res->start;
++ end = &res->end;
+
+ /* if the resource doesn't exist, don't complain about it */
+- if (cannot_compare(dev->res.port_resource[idx].flags))
++ if (cannot_compare(res->flags))
+ return 1;
+
+ /* check if the resource is already in use, skip if the
+@@ -234,18 +261,18 @@ int pnp_check_port(struct pnp_dev *dev, int idx)
}
- b_res->start = min_align;
- b_res->end = size + min_align - 1;
-+ b_res->flags |= IORESOURCE_STARTALIGN;
+
+ /* check if the resource is reserved */
+- for (tmp = 0; tmp < 8; tmp++) {
+- int rport = pnp_reserve_io[tmp << 1];
+- int rend = pnp_reserve_io[(tmp << 1) + 1] + rport - 1;
++ for (i = 0; i < 8; i++) {
++ int rport = pnp_reserve_io[i << 1];
++ int rend = pnp_reserve_io[(i << 1) + 1] + rport - 1;
+ if (ranged_conflict(port, end, &rport, &rend))
+ return 0;
+ }
+
+ /* check for internal conflicts */
+- for (tmp = 0; tmp < PNP_MAX_PORT && tmp != idx; tmp++) {
+- if (dev->res.port_resource[tmp].flags & IORESOURCE_IO) {
+- tport = &dev->res.port_resource[tmp].start;
+- tend = &dev->res.port_resource[tmp].end;
++ for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
++ if (tres != res && tres->flags & IORESOURCE_IO) {
++ tport = &tres->start;
++ tend = &tres->end;
+ if (ranged_conflict(port, end, tport, tend))
+ return 0;
+ }
+@@ -255,13 +282,14 @@ int pnp_check_port(struct pnp_dev *dev, int idx)
+ pnp_for_each_dev(tdev) {
+ if (tdev == dev)
+ continue;
+- for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) {
+- if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) {
+- if (cannot_compare
+- (tdev->res.port_resource[tmp].flags))
++ for (i = 0;
++ (tres = pnp_get_resource(tdev, IORESOURCE_IO, i));
++ i++) {
++ if (tres->flags & IORESOURCE_IO) {
++ if (cannot_compare(tres->flags))
+ continue;
+- tport = &tdev->res.port_resource[tmp].start;
+- tend = &tdev->res.port_resource[tmp].end;
++ tport = &tres->start;
++ tend = &tres->end;
+ if (ranged_conflict(port, end, tport, tend))
+ return 0;
+ }
+@@ -271,17 +299,18 @@ int pnp_check_port(struct pnp_dev *dev, int idx)
return 1;
}
--static void __devinit
--pci_bus_size_cardbus(struct pci_bus *bus)
-+static void pci_bus_size_cardbus(struct pci_bus *bus)
+-int pnp_check_mem(struct pnp_dev *dev, int idx)
++int pnp_check_mem(struct pnp_dev *dev, struct resource *res)
{
- 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;
+- int tmp;
++ int i;
+ struct pnp_dev *tdev;
++ struct resource *tres;
+ resource_size_t *addr, *end, *taddr, *tend;
+
+- addr = &dev->res.mem_resource[idx].start;
+- end = &dev->res.mem_resource[idx].end;
++ addr = &res->start;
++ end = &res->end;
+
+ /* if the resource doesn't exist, don't complain about it */
+- if (cannot_compare(dev->res.mem_resource[idx].flags))
++ if (cannot_compare(res->flags))
+ return 1;
- /*
- * 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;
+ /* check if the resource is already in use, skip if the
+@@ -292,18 +321,18 @@ int pnp_check_mem(struct pnp_dev *dev, int idx)
+ }
-- 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;
+ /* check if the resource is reserved */
+- for (tmp = 0; tmp < 8; tmp++) {
+- int raddr = pnp_reserve_mem[tmp << 1];
+- int rend = pnp_reserve_mem[(tmp << 1) + 1] + raddr - 1;
++ for (i = 0; i < 8; i++) {
++ int raddr = pnp_reserve_mem[i << 1];
++ int rend = pnp_reserve_mem[(i << 1) + 1] + raddr - 1;
+ if (ranged_conflict(addr, end, &raddr, &rend))
+ return 0;
}
+
+ /* check for internal conflicts */
+- for (tmp = 0; tmp < PNP_MAX_MEM && tmp != idx; tmp++) {
+- if (dev->res.mem_resource[tmp].flags & IORESOURCE_MEM) {
+- taddr = &dev->res.mem_resource[tmp].start;
+- tend = &dev->res.mem_resource[tmp].end;
++ for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
++ if (tres != res && tres->flags & IORESOURCE_MEM) {
++ taddr = &tres->start;
++ tend = &tres->end;
+ if (ranged_conflict(addr, end, taddr, tend))
+ return 0;
+ }
+@@ -313,13 +342,14 @@ int pnp_check_mem(struct pnp_dev *dev, int idx)
+ pnp_for_each_dev(tdev) {
+ if (tdev == dev)
+ continue;
+- for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) {
+- if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) {
+- if (cannot_compare
+- (tdev->res.mem_resource[tmp].flags))
++ for (i = 0;
++ (tres = pnp_get_resource(tdev, IORESOURCE_MEM, i));
++ i++) {
++ if (tres->flags & IORESOURCE_MEM) {
++ if (cannot_compare(tres->flags))
+ continue;
+- taddr = &tdev->res.mem_resource[tmp].start;
+- tend = &tdev->res.mem_resource[tmp].end;
++ taddr = &tres->start;
++ tend = &tres->end;
+ if (ranged_conflict(addr, end, taddr, tend))
+ return 0;
+ }
+@@ -334,14 +364,17 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id)
+ return IRQ_HANDLED;
}
-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)
+-int pnp_check_irq(struct pnp_dev *dev, int idx)
++int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
+ {
+- int tmp;
++ int i;
+ struct pnp_dev *tdev;
+- resource_size_t *irq = &dev->res.irq_resource[idx].start;
++ struct resource *tres;
++ resource_size_t *irq;
++
++ irq = &res->start;
+
+ /* if the resource doesn't exist, don't complain about it */
+- if (cannot_compare(dev->res.irq_resource[idx].flags))
++ if (cannot_compare(res->flags))
+ return 1;
- 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;
-+ }
+ /* check if the resource is valid */
+@@ -349,15 +382,15 @@ int pnp_check_irq(struct pnp_dev *dev, int idx)
+ return 0;
- /* 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);
+ /* check if the resource is reserved */
+- for (tmp = 0; tmp < 16; tmp++) {
+- if (pnp_reserve_irq[tmp] == *irq)
++ for (i = 0; i < 16; i++) {
++ if (pnp_reserve_irq[i] == *irq)
+ return 0;
}
- return ret;
+ /* check for internal conflicts */
+- for (tmp = 0; tmp < PNP_MAX_IRQ && tmp != idx; tmp++) {
+- if (dev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) {
+- if (dev->res.irq_resource[tmp].start == *irq)
++ for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) {
++ if (tres != res && tres->flags & IORESOURCE_IRQ) {
++ if (tres->start == *irq)
+ return 0;
+ }
+ }
+@@ -388,12 +421,13 @@ int pnp_check_irq(struct pnp_dev *dev, int idx)
+ pnp_for_each_dev(tdev) {
+ if (tdev == dev)
+ continue;
+- for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) {
+- if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) {
+- if (cannot_compare
+- (tdev->res.irq_resource[tmp].flags))
++ for (i = 0;
++ (tres = pnp_get_resource(tdev, IORESOURCE_IRQ, i));
++ i++) {
++ if (tres->flags & IORESOURCE_IRQ) {
++ if (cannot_compare(tres->flags))
+ continue;
+- if ((tdev->res.irq_resource[tmp].start == *irq))
++ if (tres->start == *irq)
+ return 0;
+ }
+ }
+@@ -402,15 +436,18 @@ int pnp_check_irq(struct pnp_dev *dev, int idx)
+ return 1;
}
--#ifdef CONFIG_EMBEDDED
-+#if 0
- int pci_assign_resource_fixed(struct pci_dev *dev, int resno)
+-int pnp_check_dma(struct pnp_dev *dev, int idx)
++int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
{
- 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;
+ #ifndef CONFIG_IA64
+- int tmp;
++ int i;
+ struct pnp_dev *tdev;
+- resource_size_t *dma = &dev->res.dma_resource[idx].start;
++ struct resource *tres;
++ resource_size_t *dma;
++
++ dma = &res->start;
+
+ /* if the resource doesn't exist, don't complain about it */
+- if (cannot_compare(dev->res.dma_resource[idx].flags))
++ if (cannot_compare(res->flags))
+ return 1;
-- 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;
+ /* check if the resource is valid */
+@@ -418,15 +455,15 @@ int pnp_check_dma(struct pnp_dev *dev, int idx)
+ return 0;
-- 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)
+ /* check if the resource is reserved */
+- for (tmp = 0; tmp < 8; tmp++) {
+- if (pnp_reserve_dma[tmp] == *dma)
++ for (i = 0; i < 8; i++) {
++ if (pnp_reserve_dma[i] == *dma)
+ return 0;
+ }
+
+ /* check for internal conflicts */
+- for (tmp = 0; tmp < PNP_MAX_DMA && tmp != idx; tmp++) {
+- if (dev->res.dma_resource[tmp].flags & IORESOURCE_DMA) {
+- if (dev->res.dma_resource[tmp].start == *dma)
++ for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) {
++ if (tres != res && tres->flags & IORESOURCE_DMA) {
++ if (tres->start == *dma)
+ return 0;
}
}
+@@ -443,12 +480,13 @@ int pnp_check_dma(struct pnp_dev *dev, int idx)
+ pnp_for_each_dev(tdev) {
+ if (tdev == dev)
+ continue;
+- for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) {
+- if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) {
+- if (cannot_compare
+- (tdev->res.dma_resource[tmp].flags))
++ for (i = 0;
++ (tres = pnp_get_resource(tdev, IORESOURCE_DMA, i));
++ i++) {
++ if (tres->flags & IORESOURCE_DMA) {
++ if (cannot_compare(tres->flags))
+ continue;
+- if ((tdev->res.dma_resource[tmp].start == *dma))
++ if (tres->start == *dma)
+ return 0;
+ }
+ }
+@@ -461,6 +499,193 @@ int pnp_check_dma(struct pnp_dev *dev, int idx)
+ #endif
}
+
++struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
++ unsigned int type, unsigned int num)
++{
++ struct pnp_resource_table *res = dev->res;
+
-+int pci_enable_resources(struct pci_dev *dev, int mask)
++ switch (type) {
++ case IORESOURCE_IO:
++ if (num >= PNP_MAX_PORT)
++ return NULL;
++ return &res->port[num];
++ case IORESOURCE_MEM:
++ if (num >= PNP_MAX_MEM)
++ return NULL;
++ return &res->mem[num];
++ case IORESOURCE_IRQ:
++ if (num >= PNP_MAX_IRQ)
++ return NULL;
++ return &res->irq[num];
++ case IORESOURCE_DMA:
++ if (num >= PNP_MAX_DMA)
++ return NULL;
++ return &res->dma[num];
++ }
++ return NULL;
++}
++
++struct resource *pnp_get_resource(struct pnp_dev *dev,
++ unsigned int type, unsigned int num)
+{
-+ u16 cmd, old_cmd;
++ struct pnp_resource *pnp_res;
++
++ pnp_res = pnp_get_pnp_resource(dev, type, num);
++ if (pnp_res)
++ return &pnp_res->res;
++
++ return NULL;
++}
++EXPORT_SYMBOL(pnp_get_resource);
++
++static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev, int type)
++{
++ struct pnp_resource *pnp_res;
+ int i;
-+ struct resource *r;
+
-+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
-+ old_cmd = cmd;
++ switch (type) {
++ case IORESOURCE_IO:
++ for (i = 0; i < PNP_MAX_PORT; i++) {
++ pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, i);
++ if (pnp_res && !pnp_resource_valid(&pnp_res->res))
++ return pnp_res;
++ }
++ break;
++ case IORESOURCE_MEM:
++ for (i = 0; i < PNP_MAX_MEM; i++) {
++ pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, i);
++ if (pnp_res && !pnp_resource_valid(&pnp_res->res))
++ return pnp_res;
++ }
++ break;
++ case IORESOURCE_IRQ:
++ for (i = 0; i < PNP_MAX_IRQ; i++) {
++ pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, i);
++ if (pnp_res && !pnp_resource_valid(&pnp_res->res))
++ return pnp_res;
++ }
++ break;
++ case IORESOURCE_DMA:
++ for (i = 0; i < PNP_MAX_DMA; i++) {
++ pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, i);
++ if (pnp_res && !pnp_resource_valid(&pnp_res->res))
++ return pnp_res;
++ }
++ break;
++ }
++ return NULL;
++}
+
-+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-+ if (!(mask & (1 << i)))
-+ continue;
++struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
++ int flags)
++{
++ struct pnp_resource *pnp_res;
++ struct resource *res;
++ static unsigned char warned;
+
-+ r = &dev->resource[i];
++ pnp_res = pnp_new_resource(dev, IORESOURCE_IRQ);
++ if (!pnp_res) {
++ if (!warned) {
++ dev_err(&dev->dev, "can't add resource for IRQ %d\n",
++ irq);
++ warned = 1;
++ }
++ return NULL;
++ }
+
-+ if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
-+ continue;
-+ if ((i == PCI_ROM_RESOURCE) &&
-+ (!(r->flags & IORESOURCE_ROM_ENABLE)))
-+ continue;
++ res = &pnp_res->res;
++ res->flags = IORESOURCE_IRQ | flags;
++ res->start = irq;
++ res->end = irq;
+
-+ 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;
++ dev_dbg(&dev->dev, " add irq %d flags %#x\n", irq, flags);
++ return pnp_res;
++}
++
++struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
++ int flags)
++{
++ struct pnp_resource *pnp_res;
++ struct resource *res;
++ static unsigned char warned;
++
++ pnp_res = pnp_new_resource(dev, IORESOURCE_DMA);
++ if (!pnp_res) {
++ if (!warned) {
++ dev_err(&dev->dev, "can't add resource for DMA %d\n",
++ dma);
++ warned = 1;
+ }
++ return NULL;
++ }
+
-+ if (r->flags & IORESOURCE_IO)
-+ cmd |= PCI_COMMAND_IO;
-+ if (r->flags & IORESOURCE_MEM)
-+ cmd |= PCI_COMMAND_MEMORY;
++ res = &pnp_res->res;
++ res->flags = IORESOURCE_DMA | flags;
++ res->start = dma;
++ res->end = dma;
++
++ dev_dbg(&dev->dev, " add dma %d flags %#x\n", dma, flags);
++ return pnp_res;
++}
++
++struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
++ resource_size_t start,
++ resource_size_t end, int flags)
++{
++ struct pnp_resource *pnp_res;
++ struct resource *res;
++ static unsigned char warned;
++
++ pnp_res = pnp_new_resource(dev, IORESOURCE_IO);
++ if (!pnp_res) {
++ if (!warned) {
++ dev_err(&dev->dev, "can't add resource for IO "
++ "%#llx-%#llx\n",(unsigned long long) start,
++ (unsigned long long) end);
++ warned = 1;
++ }
++ return NULL;
+ }
+
-+ if (cmd != old_cmd) {
-+ dev_info(&dev->dev, "enabling device (%04x -> %04x)\n",
-+ old_cmd, cmd);
-+ pci_write_config_word(dev, PCI_COMMAND, cmd);
++ res = &pnp_res->res;
++ res->flags = IORESOURCE_IO | flags;
++ res->start = start;
++ res->end = end;
++
++ dev_dbg(&dev->dev, " add io %#llx-%#llx flags %#x\n",
++ (unsigned long long) start, (unsigned long long) end, flags);
++ return pnp_res;
++}
++
++struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
++ resource_size_t start,
++ resource_size_t end, int flags)
++{
++ struct pnp_resource *pnp_res;
++ struct resource *res;
++ static unsigned char warned;
++
++ pnp_res = pnp_new_resource(dev, IORESOURCE_MEM);
++ if (!pnp_res) {
++ if (!warned) {
++ dev_err(&dev->dev, "can't add resource for MEM "
++ "%#llx-%#llx\n",(unsigned long long) start,
++ (unsigned long long) end);
++ warned = 1;
++ }
++ return NULL;
+ }
-+ return 0;
++
++ res = &pnp_res->res;
++ res->flags = IORESOURCE_MEM | flags;
++ res->start = start;
++ res->end = end;
++
++ dev_dbg(&dev->dev, " add mem %#llx-%#llx flags %#x\n",
++ (unsigned long long) start, (unsigned long long) end, flags);
++ return pnp_res;
+}
-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
++
+ /* format is: pnp_reserve_irq=irq1[,irq2] .... */
+ static int __init pnp_setup_reserve_irq(char *str)
+ {
+diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c
+index 13c608f..3eba85e 100644
+--- a/drivers/pnp/support.c
++++ b/drivers/pnp/support.c
+@@ -25,3 +25,66 @@ int pnp_is_active(struct pnp_dev *dev)
+ }
-diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c
-index fbf2f3a..e7ab060 100644
---- a/drivers/pcmcia/pxa2xx_cm_x270.c
-+++ b/drivers/pcmcia/pxa2xx_cm_x270.c
-@@ -20,6 +20,7 @@
- #include <asm/hardware.h>
+ EXPORT_SYMBOL(pnp_is_active);
++
++/*
++ * Functionally similar to acpi_ex_eisa_id_to_string(), but that's
++ * buried in the ACPI CA, and we can't depend on it being present.
++ */
++void pnp_eisa_id_to_string(u32 id, char *str)
++{
++ id = be32_to_cpu(id);
++
++ /*
++ * According to the specs, the first three characters are five-bit
++ * compressed ASCII, and the left-over high order bit should be zero.
++ * However, the Linux ISAPNP code historically used six bits for the
++ * first character, and there seem to be IDs that depend on that,
++ * e.g., "nEC8241" in the Linux 8250_pnp serial driver and the
++ * FreeBSD sys/pc98/cbus/sio_cbus.c driver.
++ */
++ str[0] = 'A' + ((id >> 26) & 0x3f) - 1;
++ str[1] = 'A' + ((id >> 21) & 0x1f) - 1;
++ str[2] = 'A' + ((id >> 16) & 0x1f) - 1;
++ str[3] = hex_asc((id >> 12) & 0xf);
++ str[4] = hex_asc((id >> 8) & 0xf);
++ str[5] = hex_asc((id >> 4) & 0xf);
++ str[6] = hex_asc((id >> 0) & 0xf);
++ str[7] = '\0';
++}
++
++void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
++{
++#ifdef DEBUG
++ struct resource *res;
++ int i;
++
++ dev_dbg(&dev->dev, "current resources: %s\n", desc);
++
++ for (i = 0; i < PNP_MAX_IRQ; i++) {
++ res = pnp_get_resource(dev, IORESOURCE_IRQ, i);
++ if (res && !(res->flags & IORESOURCE_UNSET))
++ dev_dbg(&dev->dev, " irq %lld flags %#lx\n",
++ (unsigned long long) res->start, res->flags);
++ }
++ for (i = 0; i < PNP_MAX_DMA; i++) {
++ res = pnp_get_resource(dev, IORESOURCE_DMA, i);
++ if (res && !(res->flags & IORESOURCE_UNSET))
++ dev_dbg(&dev->dev, " dma %lld flags %#lx\n",
++ (unsigned long long) res->start, res->flags);
++ }
++ for (i = 0; i < PNP_MAX_PORT; i++) {
++ res = pnp_get_resource(dev, IORESOURCE_IO, i);
++ if (res && !(res->flags & IORESOURCE_UNSET))
++ dev_dbg(&dev->dev, " io %#llx-%#llx flags %#lx\n",
++ (unsigned long long) res->start,
++ (unsigned long long) res->end, res->flags);
++ }
++ for (i = 0; i < PNP_MAX_MEM; i++) {
++ res = pnp_get_resource(dev, IORESOURCE_MEM, i);
++ if (res && !(res->flags & IORESOURCE_UNSET))
++ dev_dbg(&dev->dev, " mem %#llx-%#llx flags %#lx\n",
++ (unsigned long long) res->start,
++ (unsigned long long) res->end, res->flags);
++ }
++#endif
++}
+diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c
+index 55c4563..9c2496d 100644
+--- a/drivers/pnp/system.c
++++ b/drivers/pnp/system.c
+@@ -56,14 +56,15 @@ static void reserve_range(struct pnp_dev *dev, resource_size_t start,
- #include <asm/arch/pxa-regs.h>
-+#include <asm/arch/pxa2xx-gpio.h>
- #include <asm/arch/cm-x270.h>
+ static void reserve_resources_of_dev(struct pnp_dev *dev)
+ {
++ struct resource *res;
+ int i;
- #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;
+- for (i = 0; i < PNP_MAX_PORT; i++) {
+- if (!pnp_port_valid(dev, i))
++ for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
++ if (res->flags & IORESOURCE_UNSET)
+ continue;
+- if (pnp_port_start(dev, i) == 0)
++ if (res->start == 0)
+ continue; /* disabled */
+- if (pnp_port_start(dev, i) < 0x100)
++ if (res->start < 0x100)
+ /*
+ * Below 0x100 is only standard PC hardware
+ * (pics, kbd, timer, dma, ...)
+@@ -73,19 +74,17 @@ static void reserve_resources_of_dev(struct pnp_dev *dev)
+ * So, do nothing
+ */
+ continue;
+- if (pnp_port_end(dev, i) < pnp_port_start(dev, i))
++ if (res->end < res->start)
+ continue; /* invalid */
+
+- reserve_range(dev, pnp_port_start(dev, i),
+- pnp_port_end(dev, i), 1);
++ reserve_range(dev, res->start, res->end, 1);
}
- /*
+
+- for (i = 0; i < PNP_MAX_MEM; i++) {
+- if (!pnp_mem_valid(dev, i))
++ for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
++ if (res->flags & IORESOURCE_UNSET)
+ continue;
+
+- reserve_range(dev, pnp_mem_start(dev, i),
+- pnp_mem_end(dev, i), 0);
++ reserve_range(dev, res->start, res->end, 0);
+ }
+ }
+
+diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
+index bdb9b72..71be36f 100644
+--- a/drivers/power/ds2760_battery.c
++++ b/drivers/power/ds2760_battery.c
+@@ -262,7 +262,7 @@ static void ds2760_battery_work(struct work_struct *work)
+ struct ds2760_device_info, monitor_work.work);
+ const int interval = HZ * 60;
+
+- dev_dbg(di->dev, "%s\n", __FUNCTION__);
++ dev_dbg(di->dev, "%s\n", __func__);
+
+ ds2760_battery_update_status(di);
+ queue_delayed_work(di->monitor_wqueue, &di->monitor_work, interval);
+@@ -275,7 +275,7 @@ static void ds2760_battery_external_power_changed(struct power_supply *psy)
+ {
+ struct ds2760_device_info *di = to_ds2760_device_info(psy);
+
+- dev_dbg(di->dev, "%s\n", __FUNCTION__);
++ dev_dbg(di->dev, "%s\n", __func__);
+
+ cancel_delayed_work(&di->monitor_work);
+ queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ/10);
+diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
+index af7a231..ab1e828 100644
+--- a/drivers/power/olpc_battery.c
++++ b/drivers/power/olpc_battery.c
+@@ -315,7 +315,6 @@ static int __init olpc_bat_init(void)
+ if (ret)
+ goto battery_failed;
+
+- olpc_register_battery_callback(&olpc_battery_trigger_uevent);
+ goto success;
+
+ battery_failed:
+@@ -328,7 +327,6 @@ success:
+
+ static void __exit olpc_bat_exit(void)
+ {
+- olpc_deregister_battery_callback();
+ power_supply_unregister(&olpc_bat);
+ power_supply_unregister(&olpc_ac);
+ platform_device_unregister(bat_pdev);
+diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
+index 03d6a38..138dd76 100644
+--- a/drivers/power/power_supply_core.c
++++ b/drivers/power/power_supply_core.c
+@@ -39,7 +39,7 @@ static void power_supply_changed_work(struct work_struct *work)
+ struct power_supply *psy = container_of(work, struct power_supply,
+ changed_work);
+
+- dev_dbg(psy->dev, "%s\n", __FUNCTION__);
++ dev_dbg(psy->dev, "%s\n", __func__);
+
+ class_for_each_device(power_supply_class, psy,
+ __power_supply_changed_work);
+@@ -51,7 +51,7 @@ static void power_supply_changed_work(struct work_struct *work)
+
+ void power_supply_changed(struct power_supply *psy)
+ {
+- dev_dbg(psy->dev, "%s\n", __FUNCTION__);
++ dev_dbg(psy->dev, "%s\n", __func__);
+
+ schedule_work(&psy->changed_work);
+ }
+@@ -82,7 +82,7 @@ int power_supply_am_i_supplied(struct power_supply *psy)
+ error = class_for_each_device(power_supply_class, psy,
+ __power_supply_am_i_supplied);
+
+- dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, error);
++ dev_dbg(psy->dev, "%s %d\n", __func__, error);
+
+ return error;
+ }
+diff --git a/drivers/power/power_supply_leds.c b/drivers/power/power_supply_leds.c
+index fa3034f..2dece40 100644
+--- a/drivers/power/power_supply_leds.c
++++ b/drivers/power/power_supply_leds.c
+@@ -24,7 +24,7 @@ static void power_supply_update_bat_leds(struct power_supply *psy)
+ if (psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))
+ return;
+
+- dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, status.intval);
++ dev_dbg(psy->dev, "%s %d\n", __func__, status.intval);
+
+ switch (status.intval) {
+ case POWER_SUPPLY_STATUS_FULL:
+@@ -101,7 +101,7 @@ static void power_supply_update_gen_leds(struct power_supply *psy)
+ if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &online))
+ return;
+
+- dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, online.intval);
++ dev_dbg(psy->dev, "%s %d\n", __func__, online.intval);
+
+ if (online.intval)
+ led_trigger_event(psy->online_trig, LED_FULL);
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
@@ -621575,8 +820569,2028 @@
+ lv1_pause(1);
}
+
+diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig
+index 4142115..c32822a 100644
+--- a/drivers/rapidio/Kconfig
++++ b/drivers/rapidio/Kconfig
+@@ -1,14 +1,6 @@
+ #
+ # RapidIO configuration
+ #
+-config RAPIDIO_8_BIT_TRANSPORT
+- bool "8-bit transport addressing"
+- depends on RAPIDIO
+- ---help---
+- By default, the kernel assumes a 16-bit addressed RapidIO
+- network. By selecting this option, the kernel will support
+- an 8-bit addressed network.
+-
+ config RAPIDIO_DISC_TIMEOUT
+ int "Discovery timeout duration (seconds)"
+ depends on RAPIDIO
+diff --git a/drivers/rapidio/rio-access.c b/drivers/rapidio/rio-access.c
+index 8b56bbd..a3824ba 100644
+--- a/drivers/rapidio/rio-access.c
++++ b/drivers/rapidio/rio-access.c
+@@ -48,7 +48,7 @@ int __rio_local_read_config_##size \
+ u32 data = 0; \
+ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
+ spin_lock_irqsave(&rio_config_lock, flags); \
+- res = mport->ops->lcread(mport->id, offset, len, &data); \
++ res = mport->ops->lcread(mport, mport->id, offset, len, &data); \
+ *value = (type)data; \
+ spin_unlock_irqrestore(&rio_config_lock, flags); \
+ return res; \
+@@ -71,7 +71,7 @@ int __rio_local_write_config_##size \
+ unsigned long flags; \
+ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
+ spin_lock_irqsave(&rio_config_lock, flags); \
+- res = mport->ops->lcwrite(mport->id, offset, len, value); \
++ res = mport->ops->lcwrite(mport, mport->id, offset, len, value);\
+ spin_unlock_irqrestore(&rio_config_lock, flags); \
+ return res; \
+ }
+@@ -108,7 +108,7 @@ int rio_mport_read_config_##size \
+ u32 data = 0; \
+ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
+ spin_lock_irqsave(&rio_config_lock, flags); \
+- res = mport->ops->cread(mport->id, destid, hopcount, offset, len, &data); \
++ res = mport->ops->cread(mport, mport->id, destid, hopcount, offset, len, &data); \
+ *value = (type)data; \
+ spin_unlock_irqrestore(&rio_config_lock, flags); \
+ return res; \
+@@ -131,7 +131,7 @@ int rio_mport_write_config_##size \
+ unsigned long flags; \
+ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
+ spin_lock_irqsave(&rio_config_lock, flags); \
+- res = mport->ops->cwrite(mport->id, destid, hopcount, offset, len, value); \
++ res = mport->ops->cwrite(mport, mport->id, destid, hopcount, offset, len, value); \
+ spin_unlock_irqrestore(&rio_config_lock, flags); \
+ return res; \
+ }
+@@ -166,7 +166,7 @@ int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data)
+ unsigned long flags;
+
+ spin_lock_irqsave(&rio_doorbell_lock, flags);
+- res = mport->ops->dsend(mport->id, destid, data);
++ res = mport->ops->dsend(mport, mport->id, destid, data);
+ spin_unlock_irqrestore(&rio_doorbell_lock, flags);
+
+ return res;
+diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
+index 4442072..a926c89 100644
+--- a/drivers/rapidio/rio-scan.c
++++ b/drivers/rapidio/rio-scan.c
+@@ -73,7 +73,7 @@ static u16 rio_get_device_id(struct rio_mport *port, u16 destid, u8 hopcount)
+
+ rio_mport_read_config_32(port, destid, hopcount, RIO_DID_CSR, &result);
+
+- return RIO_GET_DID(result);
++ return RIO_GET_DID(port->sys_size, result);
+ }
+
+ /**
+@@ -88,7 +88,7 @@ static u16 rio_get_device_id(struct rio_mport *port, u16 destid, u8 hopcount)
+ static void rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u16 did)
+ {
+ rio_mport_write_config_32(port, destid, hopcount, RIO_DID_CSR,
+- RIO_SET_DID(did));
++ RIO_SET_DID(port->sys_size, did));
+ }
+
+ /**
+@@ -100,7 +100,8 @@ static void rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u
+ */
+ static void rio_local_set_device_id(struct rio_mport *port, u16 did)
+ {
+- rio_local_write_config_32(port, RIO_DID_CSR, RIO_SET_DID(did));
++ rio_local_write_config_32(port, RIO_DID_CSR, RIO_SET_DID(port->sys_size,
++ did));
+ }
+
+ /**
+@@ -350,8 +351,18 @@ static struct rio_dev *rio_setup_device(struct rio_net *net,
+ rswitch->switchid = next_switchid;
+ rswitch->hopcount = hopcount;
+ rswitch->destid = destid;
++ rswitch->route_table = kzalloc(sizeof(u8)*
++ RIO_MAX_ROUTE_ENTRIES(port->sys_size),
++ GFP_KERNEL);
++ if (!rswitch->route_table) {
++ kfree(rdev);
++ rdev = NULL;
++ kfree(rswitch);
++ goto out;
++ }
+ /* Initialize switch route table */
+- for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES; rdid++)
++ for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size);
++ rdid++)
+ rswitch->route_table[rdid] = RIO_INVALID_ROUTE;
+ rdev->rswitch = rswitch;
+ sprintf(rio_name(rdev), "%02x:s:%04x", rdev->net->id,
+@@ -480,7 +491,7 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount)
+ {
+ u32 result;
+
+- rio_mport_read_config_32(port, RIO_ANY_DESTID, hopcount,
++ rio_mport_read_config_32(port, RIO_ANY_DESTID(port->sys_size), hopcount,
+ RIO_HOST_DID_LOCK_CSR, &result);
+
+ return (u16) (result & 0xffff);
+@@ -571,14 +582,16 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
+ }
+
+ /* Attempt to acquire device lock */
+- rio_mport_write_config_32(port, RIO_ANY_DESTID, hopcount,
++ rio_mport_write_config_32(port, RIO_ANY_DESTID(port->sys_size),
++ hopcount,
+ RIO_HOST_DID_LOCK_CSR, port->host_deviceid);
+ while ((tmp = rio_get_host_deviceid_lock(port, hopcount))
+ < port->host_deviceid) {
+ /* Delay a bit */
+ mdelay(1);
+ /* Attempt to acquire device lock again */
+- rio_mport_write_config_32(port, RIO_ANY_DESTID, hopcount,
++ rio_mport_write_config_32(port, RIO_ANY_DESTID(port->sys_size),
++ hopcount,
+ RIO_HOST_DID_LOCK_CSR,
+ port->host_deviceid);
+ }
+@@ -590,7 +603,9 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
+ }
+
+ /* Setup new RIO device */
+- if ((rdev = rio_setup_device(net, port, RIO_ANY_DESTID, hopcount, 1))) {
++ rdev = rio_setup_device(net, port, RIO_ANY_DESTID(port->sys_size),
++ hopcount, 1);
++ if (rdev) {
+ /* Add device to the global and bus/net specific list. */
+ list_add_tail(&rdev->net_list, &net->devices);
+ } else
+@@ -598,7 +613,8 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
+
+ if (rio_is_switch(rdev)) {
+ next_switchid++;
+- sw_inport = rio_get_swpinfo_inport(port, RIO_ANY_DESTID, hopcount);
++ sw_inport = rio_get_swpinfo_inport(port,
++ RIO_ANY_DESTID(port->sys_size), hopcount);
+ rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE,
+ port->host_deviceid, sw_inport);
+ rdev->rswitch->route_table[port->host_deviceid] = sw_inport;
+@@ -612,7 +628,8 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
+ }
+
+ num_ports =
+- rio_get_swpinfo_tports(port, RIO_ANY_DESTID, hopcount);
++ rio_get_swpinfo_tports(port, RIO_ANY_DESTID(port->sys_size),
++ hopcount);
+ pr_debug(
+ "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n",
+ rio_name(rdev), rdev->vid, rdev->did, num_ports);
+@@ -624,13 +641,15 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
+ cur_destid = next_destid;
+
+ if (rio_sport_is_active
+- (port, RIO_ANY_DESTID, hopcount, port_num)) {
++ (port, RIO_ANY_DESTID(port->sys_size), hopcount,
++ port_num)) {
+ pr_debug(
+ "RIO: scanning device on port %d\n",
+ port_num);
+ rio_route_add_entry(port, rdev->rswitch,
+- RIO_GLOBAL_TABLE,
+- RIO_ANY_DESTID, port_num);
++ RIO_GLOBAL_TABLE,
++ RIO_ANY_DESTID(port->sys_size),
++ port_num);
+
+ if (rio_enum_peer(net, port, hopcount + 1) < 0)
+ return -1;
+@@ -735,7 +754,8 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
+ pr_debug(
+ "RIO: scanning device on port %d\n",
+ port_num);
+- for (ndestid = 0; ndestid < RIO_ANY_DESTID;
++ for (ndestid = 0;
++ ndestid < RIO_ANY_DESTID(port->sys_size);
+ ndestid++) {
+ rio_route_get_entry(port, rdev->rswitch,
+ RIO_GLOBAL_TABLE,
+@@ -917,7 +937,9 @@ static void rio_build_route_tables(void)
+
+ list_for_each_entry(rdev, &rio_devices, global_list)
+ if (rio_is_switch(rdev))
+- for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++) {
++ for (i = 0;
++ i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
++ i++) {
+ if (rio_route_get_entry
+ (rdev->net->hport, rdev->rswitch, RIO_GLOBAL_TABLE,
+ i, &sport) < 0)
+@@ -981,7 +1003,8 @@ int rio_disc_mport(struct rio_mport *mport)
+ del_timer_sync(&rio_enum_timer);
+
+ pr_debug("done\n");
+- if (rio_disc_peer(net, mport, RIO_ANY_DESTID, 0) < 0) {
++ if (rio_disc_peer(net, mport, RIO_ANY_DESTID(mport->sys_size),
++ 0) < 0) {
+ printk(KERN_INFO
+ "RIO: master port %d device has failed discovery\n",
+ mport->id);
+diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c
+index 659e311..97a147f 100644
+--- a/drivers/rapidio/rio-sysfs.c
++++ b/drivers/rapidio/rio-sysfs.c
+@@ -43,7 +43,8 @@ static ssize_t routes_show(struct device *dev, struct device_attribute *attr, ch
+ if (!rdev->rswitch)
+ goto out;
+
+- for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++) {
++ for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
++ i++) {
+ if (rdev->rswitch->route_table[i] == RIO_INVALID_ROUTE)
+ continue;
+ str +=
+diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
+index 80c5f1b..680661a 100644
+--- a/drivers/rapidio/rio.c
++++ b/drivers/rapidio/rio.c
+@@ -43,7 +43,7 @@ u16 rio_local_get_device_id(struct rio_mport *port)
+
+ rio_local_read_config_32(port, RIO_DID_CSR, &result);
+
+- return (RIO_GET_DID(result));
++ return (RIO_GET_DID(port->sys_size, result));
+ }
+
+ /**
+diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h
+index 80e3f03..7786d02 100644
+--- a/drivers/rapidio/rio.h
++++ b/drivers/rapidio/rio.h
+@@ -51,10 +51,5 @@ extern struct rio_route_ops __end_rio_route_ops[];
+ DECLARE_RIO_ROUTE_SECTION(.rio_route_ops, \
+ vid, did, add_hook, get_hook)
+
+-#ifdef CONFIG_RAPIDIO_8_BIT_TRANSPORT
+-#define RIO_GET_DID(x) ((x & 0x00ff0000) >> 16)
+-#define RIO_SET_DID(x) ((x & 0x000000ff) << 16)
+-#else
+-#define RIO_GET_DID(x) (x & 0xffff)
+-#define RIO_SET_DID(x) (x & 0xffff)
+-#endif
++#define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16))
++#define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16))
+diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
+index 02a4c8c..6cc2c03 100644
+--- a/drivers/rtc/Kconfig
++++ b/drivers/rtc/Kconfig
+@@ -20,10 +20,6 @@ menuconfig RTC_CLASS
+
+ if RTC_CLASS
+
+-if GEN_RTC || RTC
+-comment "Conflicting RTC option has been selected, check GEN_RTC and RTC"
+-endif
+-
+ config RTC_HCTOSYS
+ bool "Set system time from RTC on startup and resume"
+ depends on RTC_CLASS = y
+@@ -304,6 +300,7 @@ comment "Platform RTC drivers"
+ config RTC_DRV_CMOS
+ tristate "PC-style 'CMOS'"
+ depends on X86 || ALPHA || ARM || M32R || ATARI || PPC || MIPS
++ default y if X86
+ help
+ Say "yes" here to get direct support for the real time clock
+ found in every PC or ACPI-based system, and some other boards.
+diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
+index 52abffc..39e64ab 100644
+--- a/drivers/rtc/rtc-at91rm9200.c
++++ b/drivers/rtc/rtc-at91rm9200.c
+@@ -83,7 +83,7 @@ static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm)
+ tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
+ tm->tm_year = tm->tm_year - 1900;
+
+- pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
++ pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
+ 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+@@ -97,7 +97,7 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
+ {
+ unsigned long cr;
+
+- pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
++ pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
+ 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+@@ -142,7 +142,7 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
+ alrm->enabled = (at91_sys_read(AT91_RTC_IMR) & AT91_RTC_ALARM)
+ ? 1 : 0;
+
+- pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
++ pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
+ 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+@@ -178,7 +178,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+ if (alrm->enabled)
+ at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM);
+
+- pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
++ pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
+ at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,
+ tm.tm_min, tm.tm_sec);
+
+@@ -193,7 +193,7 @@ static int at91_rtc_ioctl(struct device *dev, unsigned int cmd,
+ {
+ int ret = 0;
+
+- pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __FUNCTION__, cmd, arg);
++ pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __func__, cmd, arg);
+
+ switch (cmd) {
+ case RTC_AIE_OFF: /* alarm off */
+@@ -265,7 +265,7 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id)
+
+ rtc_update_irq(rtc, 1, events);
+
+- pr_debug("%s(): num=%ld, events=0x%02lx\n", __FUNCTION__,
++ pr_debug("%s(): num=%ld, events=0x%02lx\n", __func__,
+ events >> 8, events & 0x000000FF);
+
+ return IRQ_HANDLED;
+diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
+index 56728a2..38d8742 100644
+--- a/drivers/rtc/rtc-at91sam9.c
++++ b/drivers/rtc/rtc-at91sam9.c
+@@ -288,7 +288,7 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *_rtc)
+
+ rtc_update_irq(rtc->rtcdev, 1, events);
+
+- pr_debug("%s: num=%ld, events=0x%02lx\n", __FUNCTION__,
++ pr_debug("%s: num=%ld, events=0x%02lx\n", __func__,
+ events >> 8, events & 0x000000FF);
+
+ return IRQ_HANDLED;
+diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c
+index 4f28045..8624f55 100644
+--- a/drivers/rtc/rtc-bfin.c
++++ b/drivers/rtc/rtc-bfin.c
+@@ -419,7 +419,7 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev)
+ return -ENOMEM;
+
+ rtc->rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &bfin_rtc_ops, THIS_MODULE);
+- if (unlikely(IS_ERR(rtc))) {
++ if (IS_ERR(rtc)) {
+ ret = PTR_ERR(rtc->rtc_dev);
+ goto err;
+ }
+diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
+index dcdc142..d060a06 100644
+--- a/drivers/rtc/rtc-cmos.c
++++ b/drivers/rtc/rtc-cmos.c
+@@ -854,11 +854,12 @@ cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
+ * don't define the IRQ. It should always be safe to
+ * hardcode it in these cases
+ */
+- return cmos_do_probe(&pnp->dev, &pnp->res.port_resource[0], 8);
++ return cmos_do_probe(&pnp->dev,
++ pnp_get_resource(pnp, IORESOURCE_IO, 0), 8);
+ else
+ return cmos_do_probe(&pnp->dev,
+- &pnp->res.port_resource[0],
+- pnp->res.irq_resource[0].start);
++ pnp_get_resource(pnp, IORESOURCE_IO, 0),
++ pnp_irq(pnp, 0));
+ }
+
+ static void __exit cmos_pnp_remove(struct pnp_dev *pnp)
+diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
+index 7b002ce..b939781 100644
+--- a/drivers/rtc/rtc-ds1302.c
++++ b/drivers/rtc/rtc-ds1302.c
+@@ -122,7 +122,7 @@ static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm)
+
+ dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+- __FUNCTION__,
++ __func__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday);
+
+diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
+index f389a28..bbf97e6 100644
+--- a/drivers/rtc/rtc-ds1307.c
++++ b/drivers/rtc/rtc-ds1307.c
+@@ -99,45 +99,38 @@ struct ds1307 {
+ };
+
+ struct chip_desc {
+- char name[9];
+ unsigned nvram56:1;
+ unsigned alarm:1;
+- enum ds_type type;
+ };
+
+-static const struct chip_desc chips[] = { {
+- .name = "ds1307",
+- .type = ds_1307,
++static const struct chip_desc chips[] = {
++[ds_1307] = {
+ .nvram56 = 1,
+-}, {
+- .name = "ds1337",
+- .type = ds_1337,
++},
++[ds_1337] = {
+ .alarm = 1,
+-}, {
+- .name = "ds1338",
+- .type = ds_1338,
++},
++[ds_1338] = {
+ .nvram56 = 1,
+-}, {
+- .name = "ds1339",
+- .type = ds_1339,
++},
++[ds_1339] = {
+ .alarm = 1,
+-}, {
+- .name = "ds1340",
+- .type = ds_1340,
+-}, {
+- .name = "m41t00",
+- .type = m41t00,
++},
++[ds_1340] = {
++},
++[m41t00] = {
+ }, };
+
+-static inline const struct chip_desc *find_chip(const char *s)
+-{
+- unsigned i;
+-
+- for (i = 0; i < ARRAY_SIZE(chips); i++)
+- if (strnicmp(s, chips[i].name, sizeof chips[i].name) == 0)
+- return &chips[i];
+- return NULL;
+-}
++static const struct i2c_device_id ds1307_id[] = {
++ { "ds1307", ds_1307 },
++ { "ds1337", ds_1337 },
++ { "ds1338", ds_1338 },
++ { "ds1339", ds_1339 },
++ { "ds1340", ds_1340 },
++ { "m41t00", m41t00 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, ds1307_id);
+
+ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
+ {
+@@ -326,21 +319,15 @@ static struct bin_attribute nvram = {
+
+ static struct i2c_driver ds1307_driver;
+
+-static int __devinit ds1307_probe(struct i2c_client *client)
++static int __devinit ds1307_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct ds1307 *ds1307;
+ int err = -ENODEV;
+ int tmp;
+- const struct chip_desc *chip;
++ const struct chip_desc *chip = &chips[id->driver_data];
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+
+- chip = find_chip(client->name);
+- if (!chip) {
+- dev_err(&client->dev, "unknown chip type '%s'\n",
+- client->name);
+- return -ENODEV;
+- }
+-
+ if (!i2c_check_functionality(adapter,
+ I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+ return -EIO;
+@@ -361,7 +348,7 @@ static int __devinit ds1307_probe(struct i2c_client *client)
+ ds1307->msg[1].len = sizeof(ds1307->regs);
+ ds1307->msg[1].buf = ds1307->regs;
+
+- ds1307->type = chip->type;
++ ds1307->type = id->driver_data;
+
+ switch (ds1307->type) {
+ case ds_1337:
+@@ -550,6 +537,7 @@ static struct i2c_driver ds1307_driver = {
+ },
+ .probe = ds1307_probe,
+ .remove = __devexit_p(ds1307_remove),
++ .id_table = ds1307_id,
+ };
+
+ static int __init ds1307_init(void)
+diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
+index 45bda18..fa2d2f8 100644
+--- a/drivers/rtc/rtc-ds1374.c
++++ b/drivers/rtc/rtc-ds1374.c
+@@ -41,6 +41,12 @@
+ #define DS1374_REG_SR_AF 0x01 /* Alarm Flag */
+ #define DS1374_REG_TCR 0x09 /* Trickle Charge */
+
++static const struct i2c_device_id ds1374_id[] = {
++ { "rtc-ds1374", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, ds1374_id);
++
+ struct ds1374 {
+ struct i2c_client *client;
+ struct rtc_device *rtc;
+@@ -355,7 +361,8 @@ static const struct rtc_class_ops ds1374_rtc_ops = {
+ .ioctl = ds1374_ioctl,
+ };
+
+-static int ds1374_probe(struct i2c_client *client)
++static int ds1374_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct ds1374 *ds1374;
+ int ret;
+@@ -429,6 +436,7 @@ static struct i2c_driver ds1374_driver = {
+ },
+ .probe = ds1374_probe,
+ .remove = __devexit_p(ds1374_remove),
++ .id_table = ds1374_id,
+ };
+
+ static int __init ds1374_init(void)
+diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
+index d08912f..a83a40b 100644
+--- a/drivers/rtc/rtc-ds1511.c
++++ b/drivers/rtc/rtc-ds1511.c
+@@ -181,8 +181,7 @@ ds1511_wdog_disable(void)
+ * stupidly, some callers call with year unmolested;
+ * and some call with year = year - 1900. thanks.
+ */
+- int
+-ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm)
++static int ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm)
+ {
+ u8 mon, day, dow, hrs, min, sec, yrs, cen;
+ unsigned int flags;
+@@ -245,8 +244,7 @@ ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm)
+ return 0;
+ }
+
+- int
+-ds1511_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
++static int ds1511_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
+ {
+ unsigned int century;
+ unsigned int flags;
+diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c
+index e0900ca..6fa4556 100644
+--- a/drivers/rtc/rtc-ds1672.c
++++ b/drivers/rtc/rtc-ds1672.c
+@@ -50,13 +50,13 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+
+ /* read date registers */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
++ dev_err(&client->dev, "%s: read error\n", __func__);
+ return -EIO;
+ }
+
+ dev_dbg(&client->dev,
+ "%s: raw read data - counters=%02x,%02x,%02x,%02x\n",
+- __FUNCTION__, buf[0], buf[1], buf[2], buf[3]);
++ __func__, buf[0], buf[1], buf[2], buf[3]);
+
+ time = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+
+@@ -64,7 +64,7 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+
+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+- __FUNCTION__, tm->tm_sec, tm->tm_min, tm->tm_hour,
++ __func__, tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ return 0;
+@@ -84,7 +84,7 @@ static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs)
+
+ xfer = i2c_master_send(client, buf, 6);
+ if (xfer != 6) {
+- dev_err(&client->dev, "%s: send: %d\n", __FUNCTION__, xfer);
++ dev_err(&client->dev, "%s: send: %d\n", __func__, xfer);
+ return -EIO;
+ }
+
+@@ -98,7 +98,7 @@ static int ds1672_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+ dev_dbg(&client->dev,
+ "%s: secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+- __FUNCTION__,
++ __func__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+@@ -133,7 +133,7 @@ static int ds1672_get_control(struct i2c_client *client, u8 *status)
+
+ /* read control register */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
++ dev_err(&client->dev, "%s: read error\n", __func__);
+ return -EIO;
+ }
+
+@@ -199,7 +199,7 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
+ struct i2c_client *client;
+ struct rtc_device *rtc;
+
+- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
++ dev_dbg(&adapter->dev, "%s\n", __func__);
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ err = -ENODEV;
+diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c
+index 725b0c7..fbb90b1 100644
+--- a/drivers/rtc/rtc-isl1208.c
++++ b/drivers/rtc/rtc-isl1208.c
+@@ -15,16 +15,15 @@
+ #include <linux/bcd.h>
+ #include <linux/rtc.h>
+
+-#define DRV_NAME "isl1208"
+-#define DRV_VERSION "0.2"
++#define DRV_VERSION "0.3"
+
+ /* Register map */
+ /* rtc section */
+ #define ISL1208_REG_SC 0x00
+ #define ISL1208_REG_MN 0x01
+ #define ISL1208_REG_HR 0x02
+-#define ISL1208_REG_HR_MIL (1<<7) /* 24h/12h mode */
+-#define ISL1208_REG_HR_PM (1<<5) /* PM/AM bit in 12h mode */
++#define ISL1208_REG_HR_MIL (1<<7) /* 24h/12h mode */
++#define ISL1208_REG_HR_PM (1<<5) /* PM/AM bit in 12h mode */
+ #define ISL1208_REG_DT 0x03
+ #define ISL1208_REG_MO 0x04
+ #define ISL1208_REG_YR 0x05
+@@ -33,14 +32,14 @@
+
+ /* control/status section */
+ #define ISL1208_REG_SR 0x07
+-#define ISL1208_REG_SR_ARST (1<<7) /* auto reset */
+-#define ISL1208_REG_SR_XTOSCB (1<<6) /* crystal oscillator */
+-#define ISL1208_REG_SR_WRTC (1<<4) /* write rtc */
+-#define ISL1208_REG_SR_ALM (1<<2) /* alarm */
+-#define ISL1208_REG_SR_BAT (1<<1) /* battery */
+-#define ISL1208_REG_SR_RTCF (1<<0) /* rtc fail */
++#define ISL1208_REG_SR_ARST (1<<7) /* auto reset */
++#define ISL1208_REG_SR_XTOSCB (1<<6) /* crystal oscillator */
++#define ISL1208_REG_SR_WRTC (1<<4) /* write rtc */
++#define ISL1208_REG_SR_ALM (1<<2) /* alarm */
++#define ISL1208_REG_SR_BAT (1<<1) /* battery */
++#define ISL1208_REG_SR_RTCF (1<<0) /* rtc fail */
+ #define ISL1208_REG_INT 0x08
+-#define ISL1208_REG_09 0x09 /* reserved */
++#define ISL1208_REG_09 0x09 /* reserved */
+ #define ISL1208_REG_ATR 0x0a
+ #define ISL1208_REG_DTR 0x0b
+
+@@ -58,39 +57,21 @@
+ #define ISL1208_REG_USR2 0x13
+ #define ISL1208_USR_SECTION_LEN 2
+
+-/* i2c configuration */
+-#define ISL1208_I2C_ADDR 0xde
+-
+-static const unsigned short normal_i2c[] = {
+- ISL1208_I2C_ADDR>>1, I2C_CLIENT_END
+-};
+-I2C_CLIENT_INSMOD; /* defines addr_data */
+-
+-static int isl1208_attach_adapter(struct i2c_adapter *adapter);
+-static int isl1208_detach_client(struct i2c_client *client);
+-
+-static struct i2c_driver isl1208_driver = {
+- .driver = {
+- .name = DRV_NAME,
+- },
+- .id = I2C_DRIVERID_ISL1208,
+- .attach_adapter = &isl1208_attach_adapter,
+- .detach_client = &isl1208_detach_client,
+-};
++static struct i2c_driver isl1208_driver;
+
+ /* block read */
+ static int
+ isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[],
+- unsigned len)
++ unsigned len)
+ {
+ u8 reg_addr[1] = { reg };
+ struct i2c_msg msgs[2] = {
+- { client->addr, client->flags, sizeof(reg_addr), reg_addr },
+- { client->addr, client->flags | I2C_M_RD, len, buf }
++ {client->addr, 0, sizeof(reg_addr), reg_addr}
++ ,
++ {client->addr, I2C_M_RD, len, buf}
+ };
+ int ret;
+
+- BUG_ON(len == 0);
+ BUG_ON(reg > ISL1208_REG_USR2);
+ BUG_ON(reg + len > ISL1208_REG_USR2 + 1);
+
+@@ -103,15 +84,14 @@ isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[],
+ /* block write */
+ static int
+ isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[],
+- unsigned len)
++ unsigned len)
+ {
+ u8 i2c_buf[ISL1208_REG_USR2 + 2];
+ struct i2c_msg msgs[1] = {
+- { client->addr, client->flags, len + 1, i2c_buf }
++ {client->addr, 0, len + 1, i2c_buf}
+ };
+ int ret;
+
+- BUG_ON(len == 0);
+ BUG_ON(reg > ISL1208_REG_USR2);
+ BUG_ON(reg + len > ISL1208_REG_USR2 + 1);
+
+@@ -125,7 +105,8 @@ isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[],
+ }
+
+ /* simple check to see wether we have a isl1208 */
+-static int isl1208_i2c_validate_client(struct i2c_client *client)
++static int
++isl1208_i2c_validate_client(struct i2c_client *client)
+ {
+ u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, };
+ u8 zero_mask[ISL1208_RTC_SECTION_LEN] = {
+@@ -139,24 +120,29 @@ static int isl1208_i2c_validate_client(struct i2c_client *client)
+ return ret;
+
+ for (i = 0; i < ISL1208_RTC_SECTION_LEN; ++i) {
+- if (regs[i] & zero_mask[i]) /* check if bits are cleared */
++ if (regs[i] & zero_mask[i]) /* check if bits are cleared */
+ return -ENODEV;
+ }
+
+ return 0;
+ }
+
+-static int isl1208_i2c_get_sr(struct i2c_client *client)
++static int
++isl1208_i2c_get_sr(struct i2c_client *client)
+ {
+- return i2c_smbus_read_byte_data(client, ISL1208_REG_SR) == -1 ? -EIO:0;
++ int sr = i2c_smbus_read_byte_data(client, ISL1208_REG_SR);
++ if (sr < 0)
++ return -EIO;
++
++ return sr;
+ }
+
+-static int isl1208_i2c_get_atr(struct i2c_client *client)
++static int
++isl1208_i2c_get_atr(struct i2c_client *client)
+ {
+ int atr = i2c_smbus_read_byte_data(client, ISL1208_REG_ATR);
+-
+ if (atr < 0)
+- return -EIO;
++ return atr;
+
+ /* The 6bit value in the ATR register controls the load
+ * capacitance C_load * in steps of 0.25pF
+@@ -169,51 +155,54 @@ static int isl1208_i2c_get_atr(struct i2c_client *client)
+ *
+ */
+
+- atr &= 0x3f; /* mask out lsb */
+- atr ^= 1<<5; /* invert 6th bit */
+- atr += 2*9; /* add offset of 4.5pF; unit[atr] = 0.25pF */
++ atr &= 0x3f; /* mask out lsb */
++ atr ^= 1 << 5; /* invert 6th bit */
++ atr += 2 * 9; /* add offset of 4.5pF; unit[atr] = 0.25pF */
+
+ return atr;
+ }
+
+-static int isl1208_i2c_get_dtr(struct i2c_client *client)
++static int
++isl1208_i2c_get_dtr(struct i2c_client *client)
+ {
+ int dtr = i2c_smbus_read_byte_data(client, ISL1208_REG_DTR);
+-
+ if (dtr < 0)
+ return -EIO;
+
+ /* dtr encodes adjustments of {-60,-40,-20,0,20,40,60} ppm */
+- dtr = ((dtr & 0x3) * 20) * (dtr & (1<<2) ? -1 : 1);
++ dtr = ((dtr & 0x3) * 20) * (dtr & (1 << 2) ? -1 : 1);
+
+ return dtr;
+ }
+
+-static int isl1208_i2c_get_usr(struct i2c_client *client)
++static int
++isl1208_i2c_get_usr(struct i2c_client *client)
+ {
+ u8 buf[ISL1208_USR_SECTION_LEN] = { 0, };
+ int ret;
+
+- ret = isl1208_i2c_read_regs (client, ISL1208_REG_USR1, buf,
+- ISL1208_USR_SECTION_LEN);
++ ret = isl1208_i2c_read_regs(client, ISL1208_REG_USR1, buf,
++ ISL1208_USR_SECTION_LEN);
+ if (ret < 0)
+ return ret;
+
+ return (buf[1] << 8) | buf[0];
+ }
+
+-static int isl1208_i2c_set_usr(struct i2c_client *client, u16 usr)
++static int
++isl1208_i2c_set_usr(struct i2c_client *client, u16 usr)
+ {
+ u8 buf[ISL1208_USR_SECTION_LEN];
+
+ buf[0] = usr & 0xff;
+ buf[1] = (usr >> 8) & 0xff;
+
+- return isl1208_i2c_set_regs (client, ISL1208_REG_USR1, buf,
+- ISL1208_USR_SECTION_LEN);
++ return isl1208_i2c_set_regs(client, ISL1208_REG_USR1, buf,
++ ISL1208_USR_SECTION_LEN);
+ }
+
+-static int isl1208_rtc_proc(struct device *dev, struct seq_file *seq)
++static int
++isl1208_rtc_proc(struct device *dev, struct seq_file *seq)
+ {
+ struct i2c_client *const client = to_i2c_client(dev);
+ int sr, dtr, atr, usr;
+@@ -230,20 +219,19 @@ static int isl1208_rtc_proc(struct device *dev, struct seq_file *seq)
+ (sr & ISL1208_REG_SR_ALM) ? " ALM" : "",
+ (sr & ISL1208_REG_SR_WRTC) ? " WRTC" : "",
+ (sr & ISL1208_REG_SR_XTOSCB) ? " XTOSCB" : "",
+- (sr & ISL1208_REG_SR_ARST) ? " ARST" : "",
+- sr);
++ (sr & ISL1208_REG_SR_ARST) ? " ARST" : "", sr);
+
+ seq_printf(seq, "batt_status\t: %s\n",
+ (sr & ISL1208_REG_SR_RTCF) ? "bad" : "okay");
+
+ dtr = isl1208_i2c_get_dtr(client);
+- if (dtr >= 0 -1)
++ if (dtr >= 0 - 1)
+ seq_printf(seq, "digital_trim\t: %d ppm\n", dtr);
+
+ atr = isl1208_i2c_get_atr(client);
+ if (atr >= 0)
+ seq_printf(seq, "analog_trim\t: %d.%.2d pF\n",
+- atr>>2, (atr&0x3)*25);
++ atr >> 2, (atr & 0x3) * 25);
+
+ usr = isl1208_i2c_get_usr(client);
+ if (usr >= 0)
+@@ -252,9 +240,8 @@ static int isl1208_rtc_proc(struct device *dev, struct seq_file *seq)
+ return 0;
+ }
+
+-
+-static int isl1208_i2c_read_time(struct i2c_client *client,
+- struct rtc_time *tm)
++static int
++isl1208_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
+ {
+ int sr;
+ u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, };
+@@ -274,27 +261,30 @@ static int isl1208_i2c_read_time(struct i2c_client *client,
+
+ tm->tm_sec = BCD2BIN(regs[ISL1208_REG_SC]);
+ tm->tm_min = BCD2BIN(regs[ISL1208_REG_MN]);
+- { /* HR field has a more complex interpretation */
++
++ /* HR field has a more complex interpretation */
++ {
+ const u8 _hr = regs[ISL1208_REG_HR];
+- if (_hr & ISL1208_REG_HR_MIL) /* 24h format */
++ if (_hr & ISL1208_REG_HR_MIL) /* 24h format */
+ tm->tm_hour = BCD2BIN(_hr & 0x3f);
+- else { // 12h format
++ else {
++ /* 12h format */
+ tm->tm_hour = BCD2BIN(_hr & 0x1f);
+- if (_hr & ISL1208_REG_HR_PM) /* PM flag set */
++ if (_hr & ISL1208_REG_HR_PM) /* PM flag set */
+ tm->tm_hour += 12;
+ }
+ }
+
+ tm->tm_mday = BCD2BIN(regs[ISL1208_REG_DT]);
+- tm->tm_mon = BCD2BIN(regs[ISL1208_REG_MO]) - 1; /* rtc starts at 1 */
++ tm->tm_mon = BCD2BIN(regs[ISL1208_REG_MO]) - 1; /* rtc starts at 1 */
+ tm->tm_year = BCD2BIN(regs[ISL1208_REG_YR]) + 100;
+ tm->tm_wday = BCD2BIN(regs[ISL1208_REG_DW]);
+
+ return 0;
+ }
+
+-static int isl1208_i2c_read_alarm(struct i2c_client *client,
+- struct rtc_wkalrm *alarm)
++static int
++isl1208_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
+ {
+ struct rtc_time *const tm = &alarm->time;
+ u8 regs[ISL1208_ALARM_SECTION_LEN] = { 0, };
+@@ -307,7 +297,7 @@ static int isl1208_i2c_read_alarm(struct i2c_client *client,
+ }
+
+ sr = isl1208_i2c_read_regs(client, ISL1208_REG_SCA, regs,
+- ISL1208_ALARM_SECTION_LEN);
++ ISL1208_ALARM_SECTION_LEN);
+ if (sr < 0) {
+ dev_err(&client->dev, "%s: reading alarm section failed\n",
+ __func__);
+@@ -315,23 +305,25 @@ static int isl1208_i2c_read_alarm(struct i2c_client *client,
+ }
+
+ /* MSB of each alarm register is an enable bit */
+- tm->tm_sec = BCD2BIN(regs[ISL1208_REG_SCA-ISL1208_REG_SCA] & 0x7f);
+- tm->tm_min = BCD2BIN(regs[ISL1208_REG_MNA-ISL1208_REG_SCA] & 0x7f);
+- tm->tm_hour = BCD2BIN(regs[ISL1208_REG_HRA-ISL1208_REG_SCA] & 0x3f);
+- tm->tm_mday = BCD2BIN(regs[ISL1208_REG_DTA-ISL1208_REG_SCA] & 0x3f);
+- tm->tm_mon = BCD2BIN(regs[ISL1208_REG_MOA-ISL1208_REG_SCA] & 0x1f)-1;
+- tm->tm_wday = BCD2BIN(regs[ISL1208_REG_DWA-ISL1208_REG_SCA] & 0x03);
++ tm->tm_sec = BCD2BIN(regs[ISL1208_REG_SCA - ISL1208_REG_SCA] & 0x7f);
++ tm->tm_min = BCD2BIN(regs[ISL1208_REG_MNA - ISL1208_REG_SCA] & 0x7f);
++ tm->tm_hour = BCD2BIN(regs[ISL1208_REG_HRA - ISL1208_REG_SCA] & 0x3f);
++ tm->tm_mday = BCD2BIN(regs[ISL1208_REG_DTA - ISL1208_REG_SCA] & 0x3f);
++ tm->tm_mon =
++ BCD2BIN(regs[ISL1208_REG_MOA - ISL1208_REG_SCA] & 0x1f) - 1;
++ tm->tm_wday = BCD2BIN(regs[ISL1208_REG_DWA - ISL1208_REG_SCA] & 0x03);
+
+ return 0;
+ }
+
+-static int isl1208_rtc_read_time(struct device *dev, struct rtc_time *tm)
++static int
++isl1208_rtc_read_time(struct device *dev, struct rtc_time *tm)
+ {
+ return isl1208_i2c_read_time(to_i2c_client(dev), tm);
+ }
+
+-static int isl1208_i2c_set_time(struct i2c_client *client,
+- struct rtc_time const *tm)
++static int
++isl1208_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
+ {
+ int sr;
+ u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, };
+@@ -353,7 +345,7 @@ static int isl1208_i2c_set_time(struct i2c_client *client,
+ }
+
+ /* set WRTC */
+- sr = i2c_smbus_write_byte_data (client, ISL1208_REG_SR,
++ sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR,
+ sr | ISL1208_REG_SR_WRTC);
+ if (sr < 0) {
+ dev_err(&client->dev, "%s: writing SR failed\n", __func__);
+@@ -369,7 +361,7 @@ static int isl1208_i2c_set_time(struct i2c_client *client,
+ }
+
+ /* clear WRTC again */
+- sr = i2c_smbus_write_byte_data (client, ISL1208_REG_SR,
++ sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR,
+ sr & ~ISL1208_REG_SR_WRTC);
+ if (sr < 0) {
+ dev_err(&client->dev, "%s: writing SR failed\n", __func__);
+@@ -380,70 +372,69 @@ static int isl1208_i2c_set_time(struct i2c_client *client,
+ }
+
+
+-static int isl1208_rtc_set_time(struct device *dev, struct rtc_time *tm)
++static int
++isl1208_rtc_set_time(struct device *dev, struct rtc_time *tm)
+ {
+ return isl1208_i2c_set_time(to_i2c_client(dev), tm);
+ }
+
+-static int isl1208_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
++static int
++isl1208_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+ {
+ return isl1208_i2c_read_alarm(to_i2c_client(dev), alarm);
+ }
+
+ static const struct rtc_class_ops isl1208_rtc_ops = {
+- .proc = isl1208_rtc_proc,
+- .read_time = isl1208_rtc_read_time,
+- .set_time = isl1208_rtc_set_time,
+- .read_alarm = isl1208_rtc_read_alarm,
+- //.set_alarm = isl1208_rtc_set_alarm,
++ .proc = isl1208_rtc_proc,
++ .read_time = isl1208_rtc_read_time,
++ .set_time = isl1208_rtc_set_time,
++ .read_alarm = isl1208_rtc_read_alarm,
++ /*.set_alarm = isl1208_rtc_set_alarm, */
+ };
+
+ /* sysfs interface */
+
+-static ssize_t isl1208_sysfs_show_atrim(struct device *dev,
+- struct device_attribute *attr,
+- char *buf)
++static ssize_t
++isl1208_sysfs_show_atrim(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- int atr;
+-
+- atr = isl1208_i2c_get_atr(to_i2c_client(dev));
++ int atr = isl1208_i2c_get_atr(to_i2c_client(dev));
+ if (atr < 0)
+ return atr;
+
+- return sprintf(buf, "%d.%.2d pF\n", atr>>2, (atr&0x3)*25);
++ return sprintf(buf, "%d.%.2d pF\n", atr >> 2, (atr & 0x3) * 25);
+ }
++
+ static DEVICE_ATTR(atrim, S_IRUGO, isl1208_sysfs_show_atrim, NULL);
+
+-static ssize_t isl1208_sysfs_show_dtrim(struct device *dev,
+- struct device_attribute *attr,
+- char *buf)
++static ssize_t
++isl1208_sysfs_show_dtrim(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- int dtr;
+-
+- dtr = isl1208_i2c_get_dtr(to_i2c_client(dev));
++ int dtr = isl1208_i2c_get_dtr(to_i2c_client(dev));
+ if (dtr < 0)
+ return dtr;
+
+ return sprintf(buf, "%d ppm\n", dtr);
+ }
++
+ static DEVICE_ATTR(dtrim, S_IRUGO, isl1208_sysfs_show_dtrim, NULL);
+
+-static ssize_t isl1208_sysfs_show_usr(struct device *dev,
+- struct device_attribute *attr,
+- char *buf)
++static ssize_t
++isl1208_sysfs_show_usr(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- int usr;
+-
+- usr = isl1208_i2c_get_usr(to_i2c_client(dev));
++ int usr = isl1208_i2c_get_usr(to_i2c_client(dev));
+ if (usr < 0)
+ return usr;
+
+ return sprintf(buf, "0x%.4x\n", usr);
+ }
+
+-static ssize_t isl1208_sysfs_store_usr(struct device *dev,
+- struct device_attribute *attr,
+- const char *buf, size_t count)
++static ssize_t
++isl1208_sysfs_store_usr(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ int usr = -1;
+
+@@ -460,124 +451,123 @@ static ssize_t isl1208_sysfs_store_usr(struct device *dev,
+
+ return isl1208_i2c_set_usr(to_i2c_client(dev), usr) ? -EIO : count;
+ }
++
+ static DEVICE_ATTR(usr, S_IRUGO | S_IWUSR, isl1208_sysfs_show_usr,
+ isl1208_sysfs_store_usr);
+
+ static int
+-isl1208_probe(struct i2c_adapter *adapter, int addr, int kind)
++isl1208_sysfs_register(struct device *dev)
+ {
+- int rc = 0;
+- struct i2c_client *new_client = NULL;
+- struct rtc_device *rtc = NULL;
++ int err;
+
+- if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+- rc = -ENODEV;
+- goto failout;
++ err = device_create_file(dev, &dev_attr_atrim);
++ if (err)
++ return err;
++
++ err = device_create_file(dev, &dev_attr_dtrim);
++ if (err) {
++ device_remove_file(dev, &dev_attr_atrim);
++ return err;
+ }
+
+- new_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+- if (new_client == NULL) {
+- rc = -ENOMEM;
+- goto failout;
++ err = device_create_file(dev, &dev_attr_usr);
++ if (err) {
++ device_remove_file(dev, &dev_attr_atrim);
++ device_remove_file(dev, &dev_attr_dtrim);
+ }
+
+- new_client->addr = addr;
+- new_client->adapter = adapter;
+- new_client->driver = &isl1208_driver;
+- new_client->flags = 0;
+- strcpy(new_client->name, DRV_NAME);
++ return 0;
++}
+
+- if (kind < 0) {
+- rc = isl1208_i2c_validate_client(new_client);
+- if (rc < 0)
+- goto failout;
+- }
++static int
++isl1208_sysfs_unregister(struct device *dev)
++{
++ device_remove_file(dev, &dev_attr_atrim);
++ device_remove_file(dev, &dev_attr_atrim);
++ device_remove_file(dev, &dev_attr_usr);
++
++ return 0;
++}
++
++static int
++isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
++{
++ int rc = 0;
++ struct rtc_device *rtc;
++
++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
++ return -ENODEV;
+
+- rc = i2c_attach_client(new_client);
+- if (rc < 0)
+- goto failout;
++ if (isl1208_i2c_validate_client(client) < 0)
++ return -ENODEV;
+
+- dev_info(&new_client->dev,
++ dev_info(&client->dev,
+ "chip found, driver version " DRV_VERSION "\n");
+
+ rtc = rtc_device_register(isl1208_driver.driver.name,
+- &new_client->dev,
+- &isl1208_rtc_ops, THIS_MODULE);
++ &client->dev, &isl1208_rtc_ops,
++ THIS_MODULE);
++ if (IS_ERR(rtc))
++ return PTR_ERR(rtc);
+
+- if (IS_ERR(rtc)) {
+- rc = PTR_ERR(rtc);
+- goto failout_detach;
+- }
+-
+- i2c_set_clientdata(new_client, rtc);
++ i2c_set_clientdata(client, rtc);
+
+- rc = isl1208_i2c_get_sr(new_client);
++ rc = isl1208_i2c_get_sr(client);
+ if (rc < 0) {
+- dev_err(&new_client->dev, "reading status failed\n");
+- goto failout_unregister;
++ dev_err(&client->dev, "reading status failed\n");
++ goto exit_unregister;
+ }
+
+ if (rc & ISL1208_REG_SR_RTCF)
+- dev_warn(&new_client->dev, "rtc power failure detected, "
++ dev_warn(&client->dev, "rtc power failure detected, "
+ "please set clock.\n");
+
+- rc = device_create_file(&new_client->dev, &dev_attr_atrim);
+- if (rc < 0)
+- goto failout_unregister;
+- rc = device_create_file(&new_client->dev, &dev_attr_dtrim);
+- if (rc < 0)
+- goto failout_atrim;
+- rc = device_create_file(&new_client->dev, &dev_attr_usr);
+- if (rc < 0)
+- goto failout_dtrim;
++ rc = isl1208_sysfs_register(&client->dev);
++ if (rc)
++ goto exit_unregister;
+
+ return 0;
+
+- failout_dtrim:
+- device_remove_file(&new_client->dev, &dev_attr_dtrim);
+- failout_atrim:
+- device_remove_file(&new_client->dev, &dev_attr_atrim);
+- failout_unregister:
++exit_unregister:
+ rtc_device_unregister(rtc);
+- failout_detach:
+- i2c_detach_client(new_client);
+- failout:
+- kfree(new_client);
+- return rc;
+-}
+
+-static int
+-isl1208_attach_adapter (struct i2c_adapter *adapter)
+-{
+- return i2c_probe(adapter, &addr_data, isl1208_probe);
++ return rc;
+ }
+
+ static int
+-isl1208_detach_client(struct i2c_client *client)
++isl1208_remove(struct i2c_client *client)
+ {
+- int rc;
+- struct rtc_device *const rtc = i2c_get_clientdata(client);
++ struct rtc_device *rtc = i2c_get_clientdata(client);
+
+- if (rtc)
+- rtc_device_unregister(rtc); /* do we need to kfree? */
+-
+- rc = i2c_detach_client(client);
+- if (rc)
+- return rc;
+-
+- kfree(client);
++ isl1208_sysfs_unregister(&client->dev);
++ rtc_device_unregister(rtc);
+
+ return 0;
+ }
+
+-/* module management */
++static const struct i2c_device_id isl1208_id[] = {
++ { "isl1208", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, isl1208_id);
++
++static struct i2c_driver isl1208_driver = {
++ .driver = {
++ .name = "rtc-isl1208",
++ },
++ .probe = isl1208_probe,
++ .remove = isl1208_remove,
++ .id_table = isl1208_id,
++};
+
+-static int __init isl1208_init(void)
++static int __init
++isl1208_init(void)
+ {
+ return i2c_add_driver(&isl1208_driver);
+ }
+
+-static void __exit isl1208_exit(void)
++static void __exit
++isl1208_exit(void)
+ {
+ i2c_del_driver(&isl1208_driver);
+ }
+diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
+index 1cb33ca..316bfaa 100644
+--- a/drivers/rtc/rtc-m41t80.c
++++ b/drivers/rtc/rtc-m41t80.c
+@@ -60,48 +60,21 @@
+
+ #define DRV_VERSION "0.05"
+
+-struct m41t80_chip_info {
+- const char *name;
+- u8 features;
+-};
+-
+-static const struct m41t80_chip_info m41t80_chip_info_tbl[] = {
+- {
+- .name = "m41t80",
+- .features = 0,
+- },
+- {
+- .name = "m41t81",
+- .features = M41T80_FEATURE_HT,
+- },
+- {
+- .name = "m41t81s",
+- .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+- },
+- {
+- .name = "m41t82",
+- .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+- },
+- {
+- .name = "m41t83",
+- .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+- },
+- {
+- .name = "m41st84",
+- .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+- },
+- {
+- .name = "m41st85",
+- .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+- },
+- {
+- .name = "m41st87",
+- .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+- },
++static const struct i2c_device_id m41t80_id[] = {
++ { "m41t80", 0 },
++ { "m41t81", M41T80_FEATURE_HT },
++ { "m41t81s", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
++ { "m41t82", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
++ { "m41t83", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
++ { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
++ { "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
++ { "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
++ { }
+ };
++MODULE_DEVICE_TABLE(i2c, m41t80_id);
+
+ struct m41t80_data {
+- const struct m41t80_chip_info *chip;
++ u8 features;
+ struct rtc_device *rtc;
+ };
+
+@@ -208,7 +181,7 @@ static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq)
+ struct m41t80_data *clientdata = i2c_get_clientdata(client);
+ u8 reg;
+
+- if (clientdata->chip->features & M41T80_FEATURE_BL) {
++ if (clientdata->features & M41T80_FEATURE_BL) {
+ reg = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
+ seq_printf(seq, "battery\t\t: %s\n",
+ (reg & M41T80_FLAGS_BATT_LOW) ? "exhausted" : "ok");
+@@ -756,12 +729,12 @@ static struct notifier_block wdt_notifier = {
+ *
+ *****************************************************************************
+ */
+-static int m41t80_probe(struct i2c_client *client)
++static int m41t80_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+- int i, rc = 0;
++ int rc = 0;
+ struct rtc_device *rtc = NULL;
+ struct rtc_time tm;
+- const struct m41t80_chip_info *chip;
+ struct m41t80_data *clientdata = NULL;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C
+@@ -773,19 +746,6 @@ static int m41t80_probe(struct i2c_client *client)
+ dev_info(&client->dev,
+ "chip found, driver version " DRV_VERSION "\n");
+
+- chip = NULL;
+- for (i = 0; i < ARRAY_SIZE(m41t80_chip_info_tbl); i++) {
+- if (!strcmp(m41t80_chip_info_tbl[i].name, client->name)) {
+- chip = &m41t80_chip_info_tbl[i];
+- break;
+- }
+- }
+- if (!chip) {
+- dev_err(&client->dev, "%s is not supported\n", client->name);
+- rc = -ENODEV;
+- goto exit;
+- }
+-
+ clientdata = kzalloc(sizeof(*clientdata), GFP_KERNEL);
+ if (!clientdata) {
+ rc = -ENOMEM;
+@@ -801,7 +761,7 @@ static int m41t80_probe(struct i2c_client *client)
+ }
+
+ clientdata->rtc = rtc;
+- clientdata->chip = chip;
++ clientdata->features = id->driver_data;
+ i2c_set_clientdata(client, clientdata);
+
+ /* Make sure HT (Halt Update) bit is cleared */
+@@ -810,7 +770,7 @@ static int m41t80_probe(struct i2c_client *client)
+ goto ht_err;
+
+ if (rc & M41T80_ALHOUR_HT) {
+- if (chip->features & M41T80_FEATURE_HT) {
++ if (clientdata->features & M41T80_FEATURE_HT) {
+ m41t80_get_datetime(client, &tm);
+ dev_info(&client->dev, "HT bit was set!\n");
+ dev_info(&client->dev,
+@@ -842,7 +802,7 @@ static int m41t80_probe(struct i2c_client *client)
+ goto exit;
+
+ #ifdef CONFIG_RTC_DRV_M41T80_WDT
+- if (chip->features & M41T80_FEATURE_HT) {
++ if (clientdata->features & M41T80_FEATURE_HT) {
+ rc = misc_register(&wdt_dev);
+ if (rc)
+ goto exit;
+@@ -878,7 +838,7 @@ static int m41t80_remove(struct i2c_client *client)
+ struct rtc_device *rtc = clientdata->rtc;
+
+ #ifdef CONFIG_RTC_DRV_M41T80_WDT
+- if (clientdata->chip->features & M41T80_FEATURE_HT) {
++ if (clientdata->features & M41T80_FEATURE_HT) {
+ misc_deregister(&wdt_dev);
+ unregister_reboot_notifier(&wdt_notifier);
+ }
+@@ -896,6 +856,7 @@ static struct i2c_driver m41t80_driver = {
+ },
+ .probe = m41t80_probe,
+ .remove = m41t80_remove,
++ .id_table = m41t80_id,
+ };
+
+ static int __init m41t80_rtc_init(void)
+diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c
+index 7683412..ded3c0a 100644
+--- a/drivers/rtc/rtc-max6900.c
++++ b/drivers/rtc/rtc-max6900.c
+@@ -98,7 +98,7 @@ static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf)
+ rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (rc != ARRAY_SIZE(msgs)) {
+ dev_err(&client->dev, "%s: register read failed\n",
+- __FUNCTION__);
++ __func__);
+ return -EIO;
+ }
+ return 0;
+@@ -150,7 +150,7 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf)
+
+ write_failed:
+ dev_err(&client->dev, "%s: register write failed\n",
+- __FUNCTION__);
++ __func__);
+ return -EIO;
+ }
+
+@@ -214,7 +214,7 @@ static int max6900_i2c_clear_write_protect(struct i2c_client *client)
+ rc = i2c_smbus_write_byte_data (client, MAX6900_REG_CONTROL_WRITE, 0);
+ if (rc < 0) {
+ dev_err(&client->dev, "%s: control register write failed\n",
+- __FUNCTION__);
++ __func__);
+ return -EIO;
+ }
+ return 0;
+diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c
+index 1f956dc..12f0310 100644
+--- a/drivers/rtc/rtc-max6902.c
++++ b/drivers/rtc/rtc-max6902.c
+@@ -140,7 +140,7 @@ static int max6902_get_datetime(struct device *dev, struct rtc_time *dt)
+ dt->tm_year -= 1900;
+
+ #ifdef MAX6902_DEBUG
+- printk("\n%s : Read RTC values\n",__FUNCTION__);
++ printk("\n%s : Read RTC values\n",__func__);
+ printk("tm_hour: %i\n",dt->tm_hour);
+ printk("tm_min : %i\n",dt->tm_min);
+ printk("tm_sec : %i\n",dt->tm_sec);
+@@ -158,7 +158,7 @@ static int max6902_set_datetime(struct device *dev, struct rtc_time *dt)
+ dt->tm_year = dt->tm_year+1900;
+
+ #ifdef MAX6902_DEBUG
+- printk("\n%s : Setting RTC values\n",__FUNCTION__);
++ printk("\n%s : Setting RTC values\n",__func__);
+ printk("tm_sec : %i\n",dt->tm_sec);
+ printk("tm_min : %i\n",dt->tm_min);
+ printk("tm_hour: %i\n",dt->tm_hour);
+diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
+index b3317fc..0fc4c36 100644
+--- a/drivers/rtc/rtc-pcf8563.c
++++ b/drivers/rtc/rtc-pcf8563.c
+@@ -18,17 +18,7 @@
+ #include <linux/bcd.h>
+ #include <linux/rtc.h>
+
+-#define DRV_VERSION "0.4.2"
+-
+-/* Addresses to scan: none
+- * This chip cannot be reliably autodetected. An empty eeprom
+- * located at 0x51 will pass the validation routine due to
+- * the way the registers are implemented.
+- */
+-static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
+-
+-/* Module parameters */
+-I2C_CLIENT_INSMOD;
++#define DRV_VERSION "0.4.3"
+
+ #define PCF8563_REG_ST1 0x00 /* status */
+ #define PCF8563_REG_ST2 0x01
+@@ -53,8 +43,10 @@ I2C_CLIENT_INSMOD;
+ #define PCF8563_SC_LV 0x80 /* low voltage */
+ #define PCF8563_MO_C 0x80 /* century */
+
++static struct i2c_driver pcf8563_driver;
++
+ struct pcf8563 {
+- struct i2c_client client;
++ struct rtc_device *rtc;
+ /*
+ * The meaning of MO_C bit varies by the chip type.
+ * From PCF8563 datasheet: this bit is toggled when the years
+@@ -72,16 +64,13 @@ struct pcf8563 {
+ int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
+ };
+
+-static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind);
+-static int pcf8563_detach(struct i2c_client *client);
+-
+ /*
+ * In the routines that deal directly with the pcf8563 hardware, we use
+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
+ */
+ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+ {
+- struct pcf8563 *pcf8563 = container_of(client, struct pcf8563, client);
++ struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
+ unsigned char buf[13] = { PCF8563_REG_ST1 };
+
+ struct i2c_msg msgs[] = {
+@@ -91,7 +80,7 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+
+ /* read registers */
+ if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
+- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
++ dev_err(&client->dev, "%s: read error\n", __func__);
+ return -EIO;
+ }
+
+@@ -102,7 +91,7 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+ dev_dbg(&client->dev,
+ "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "
+ "mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
+- __FUNCTION__,
++ __func__,
+ buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6], buf[7],
+ buf[8]);
+@@ -123,7 +112,7 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+
+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+- __FUNCTION__,
++ __func__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+@@ -138,13 +127,13 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+
+ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+ {
+- struct pcf8563 *pcf8563 = container_of(client, struct pcf8563, client);
++ struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
+ int i, err;
+ unsigned char buf[9];
+
+ dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+- __FUNCTION__,
++ __func__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+@@ -174,7 +163,7 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+ if (err != sizeof(data)) {
+ dev_err(&client->dev,
+ "%s: err=%d addr=%02x, data=%02x\n",
+- __FUNCTION__, err, data[0], data[1]);
++ __func__, err, data[0], data[1]);
+ return -EIO;
+ }
+ };
+@@ -219,7 +208,7 @@ static int pcf8563_validate_client(struct i2c_client *client)
+ if (xfer != ARRAY_SIZE(msgs)) {
+ dev_err(&client->dev,
+ "%s: could not read register 0x%02X\n",
+- __FUNCTION__, pattern[i].reg);
++ __func__, pattern[i].reg);
+
+ return -EIO;
+ }
+@@ -231,7 +220,7 @@ static int pcf8563_validate_client(struct i2c_client *client)
+ dev_dbg(&client->dev,
+ "%s: pattern=%d, reg=%x, mask=0x%02x, min=%d, "
+ "max=%d, value=%d, raw=0x%02X\n",
+- __FUNCTION__, i, pattern[i].reg, pattern[i].mask,
++ __func__, i, pattern[i].reg, pattern[i].mask,
+ pattern[i].min, pattern[i].max,
+ value, buf);
+
+@@ -257,100 +246,75 @@ static const struct rtc_class_ops pcf8563_rtc_ops = {
+ .set_time = pcf8563_rtc_set_time,
+ };
+
+-static int pcf8563_attach(struct i2c_adapter *adapter)
+-{
+- return i2c_probe(adapter, &addr_data, pcf8563_probe);
+-}
+-
+-static struct i2c_driver pcf8563_driver = {
+- .driver = {
+- .name = "pcf8563",
+- },
+- .id = I2C_DRIVERID_PCF8563,
+- .attach_adapter = &pcf8563_attach,
+- .detach_client = &pcf8563_detach,
+-};
+-
+-static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind)
++static int pcf8563_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ struct pcf8563 *pcf8563;
+- struct i2c_client *client;
+- struct rtc_device *rtc;
+
+ int err = 0;
+
+- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
++ dev_dbg(&client->dev, "%s\n", __func__);
+
+- if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+- err = -ENODEV;
+- goto exit;
+- }
++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
++ return -ENODEV;
+
+- if (!(pcf8563 = kzalloc(sizeof(struct pcf8563), GFP_KERNEL))) {
+- err = -ENOMEM;
+- goto exit;
+- }
+-
+- client = &pcf8563->client;
+- client->addr = address;
+- client->driver = &pcf8563_driver;
+- client->adapter = adapter;
+-
+- strlcpy(client->name, pcf8563_driver.driver.name, I2C_NAME_SIZE);
++ pcf8563 = kzalloc(sizeof(struct pcf8563), GFP_KERNEL);
++ if (!pcf8563)
++ return -ENOMEM;
+
+ /* Verify the chip is really an PCF8563 */
+- if (kind < 0) {
+- if (pcf8563_validate_client(client) < 0) {
+- err = -ENODEV;
+- goto exit_kfree;
+- }
+- }
+-
+- /* Inform the i2c layer */
+- if ((err = i2c_attach_client(client)))
++ if (pcf8563_validate_client(client) < 0) {
++ err = -ENODEV;
+ goto exit_kfree;
++ }
+
+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+
+- rtc = rtc_device_register(pcf8563_driver.driver.name, &client->dev,
+- &pcf8563_rtc_ops, THIS_MODULE);
++ pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name,
++ &client->dev, &pcf8563_rtc_ops, THIS_MODULE);
+
+- if (IS_ERR(rtc)) {
+- err = PTR_ERR(rtc);
+- goto exit_detach;
++ if (IS_ERR(pcf8563->rtc)) {
++ err = PTR_ERR(pcf8563->rtc);
++ goto exit_kfree;
+ }
+
+- i2c_set_clientdata(client, rtc);
++ i2c_set_clientdata(client, pcf8563);
+
+ return 0;
+
+-exit_detach:
+- i2c_detach_client(client);
+-
+ exit_kfree:
+ kfree(pcf8563);
+
+-exit:
+ return err;
+ }
+
+-static int pcf8563_detach(struct i2c_client *client)
++static int pcf8563_remove(struct i2c_client *client)
+ {
+- struct pcf8563 *pcf8563 = container_of(client, struct pcf8563, client);
+- int err;
+- struct rtc_device *rtc = i2c_get_clientdata(client);
++ struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
+
+- if (rtc)
+- rtc_device_unregister(rtc);
+-
+- if ((err = i2c_detach_client(client)))
+- return err;
++ if (pcf8563->rtc)
++ rtc_device_unregister(pcf8563->rtc);
+
+ kfree(pcf8563);
+
+ return 0;
+ }
+
++static const struct i2c_device_id pcf8563_id[] = {
++ { "pcf8563", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, pcf8563_id);
++
++static struct i2c_driver pcf8563_driver = {
++ .driver = {
++ .name = "rtc-pcf8563",
++ },
++ .probe = pcf8563_probe,
++ .remove = pcf8563_remove,
++ .id_table = pcf8563_id,
++};
++
+ static int __init pcf8563_init(void)
+ {
+ return i2c_add_driver(&pcf8563_driver);
+diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c
+index 8b39970..3d09d8f 100644
+--- a/drivers/rtc/rtc-pcf8583.c
++++ b/drivers/rtc/rtc-pcf8583.c
+@@ -15,7 +15,7 @@
+ #include <linux/i2c.h>
+ #include <linux/slab.h>
+ #include <linux/string.h>
+-#include <linux/mc146818rtc.h>
++#include <linux/rtc.h>
+ #include <linux/init.h>
+ #include <linux/errno.h>
+ #include <linux/bcd.h>
+diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c
+index 8d300e6..0c6257a 100644
+--- a/drivers/rtc/rtc-proc.c
++++ b/drivers/rtc/rtc-proc.c
+@@ -108,12 +108,10 @@ void rtc_proc_add_device(struct rtc_device *rtc)
+ if (rtc->id == 0) {
+ struct proc_dir_entry *ent;
+
+- ent = create_proc_entry("driver/rtc", 0, NULL);
+- if (ent) {
+- ent->proc_fops = &rtc_proc_fops;
++ ent = proc_create_data("driver/rtc", 0, NULL,
++ &rtc_proc_fops, rtc);
++ if (ent)
+ ent->owner = rtc->owner;
+- ent->data = rtc;
+- }
+ }
+ }
+
+diff --git a/drivers/rtc/rtc-rs5c313.c b/drivers/rtc/rtc-rs5c313.c
+index 664e89a..1c14d44 100644
+--- a/drivers/rtc/rtc-rs5c313.c
++++ b/drivers/rtc/rtc-rs5c313.c
+@@ -228,7 +228,7 @@ static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm)
+ ndelay(700); /* CE:L */
+
+ if (cnt++ > 100) {
+- dev_err(dev, "%s: timeout error\n", __FUNCTION__);
++ dev_err(dev, "%s: timeout error\n", __func__);
+ return -EIO;
+ }
+ }
+@@ -289,7 +289,7 @@ static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm)
+ ndelay(700); /* CE:L */
+
+ if (cnt++ > 100) {
+- dev_err(dev, "%s: timeout error\n", __FUNCTION__);
++ dev_err(dev, "%s: timeout error\n", __func__);
+ return -EIO;
+ }
+ }
+diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
+index 6b67b50..56caf6b 100644
+--- a/drivers/rtc/rtc-rs5c372.c
++++ b/drivers/rtc/rtc-rs5c372.c
+@@ -69,6 +69,15 @@ enum rtc_type {
+ rtc_rv5c387a,
+ };
+
++static const struct i2c_device_id rs5c372_id[] = {
++ { "rs5c372a", rtc_rs5c372a },
++ { "rs5c372b", rtc_rs5c372b },
++ { "rv5c386", rtc_rv5c386 },
++ { "rv5c387a", rtc_rv5c387a },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, rs5c372_id);
++
+ /* REVISIT: this assumes that:
+ * - we're in the 21st century, so it's safe to ignore the century
+ * bit for rv5c38[67] (REG_MONTH bit 7);
+@@ -99,7 +108,7 @@ static int rs5c_get_regs(struct rs5c372 *rs5c)
+ * least 80219 chips; this works around that bug.
+ */
+ if ((i2c_transfer(client->adapter, msgs, 1)) != 1) {
+- pr_debug("%s: can't read registers\n", rs5c->rtc->name);
++ dev_warn(&client->dev, "can't read registers\n");
+ return -EIO;
+ }
+
+@@ -166,7 +175,7 @@ static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+
+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+- __FUNCTION__,
++ __func__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+@@ -181,7 +190,7 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+
+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+- __FUNCTION__,
++ __func__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+@@ -195,7 +204,7 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+ buf[7] = BIN2BCD(tm->tm_year - 100);
+
+ if ((i2c_master_send(client, buf, 8)) != 8) {
+- dev_err(&client->dev, "%s: write error\n", __FUNCTION__);
++ dev_err(&client->dev, "%s: write error\n", __func__);
+ return -EIO;
+ }
+
+@@ -220,7 +229,7 @@ static int rs5c372_get_trim(struct i2c_client *client, int *osc, int *trim)
+ *osc = (tmp & RS5C372_TRIM_XSL) ? 32000 : 32768;
+
+ if (trim) {
+- dev_dbg(&client->dev, "%s: raw trim=%x\n", __FUNCTION__, tmp);
++ dev_dbg(&client->dev, "%s: raw trim=%x\n", __func__, tmp);
+ tmp &= RS5C372_TRIM_MASK;
+ if (tmp & 0x3e) {
+ int t = tmp & 0x3f;
+@@ -494,13 +503,14 @@ static void rs5c_sysfs_unregister(struct device *dev)
+
+ static struct i2c_driver rs5c372_driver;
+
+-static int rs5c372_probe(struct i2c_client *client)
++static int rs5c372_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ int err = 0;
+ struct rs5c372 *rs5c372;
+ struct rtc_time tm;
+
+- dev_dbg(&client->dev, "%s\n", __FUNCTION__);
++ dev_dbg(&client->dev, "%s\n", __func__);
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ err = -ENODEV;
+@@ -512,29 +522,17 @@ static int rs5c372_probe(struct i2c_client *client)
+ goto exit;
+ }
+
+- /* we read registers 0x0f then 0x00-0x0f; skip the first one */
+- rs5c372->regs=&rs5c372->buf[1];
+-
+ rs5c372->client = client;
+ i2c_set_clientdata(client, rs5c372);
++ rs5c372->type = id->driver_data;
++
++ /* we read registers 0x0f then 0x00-0x0f; skip the first one */
++ rs5c372->regs = &rs5c372->buf[1];
+
+ err = rs5c_get_regs(rs5c372);
+ if (err < 0)
+ goto exit_kfree;
+
+- if (strcmp(client->name, "rs5c372a") == 0)
+- rs5c372->type = rtc_rs5c372a;
+- else if (strcmp(client->name, "rs5c372b") == 0)
+- rs5c372->type = rtc_rs5c372b;
+- else if (strcmp(client->name, "rv5c386") == 0)
+- rs5c372->type = rtc_rv5c386;
+- else if (strcmp(client->name, "rv5c387a") == 0)
+- rs5c372->type = rtc_rv5c387a;
+- else {
+- rs5c372->type = rtc_rs5c372b;
+- dev_warn(&client->dev, "assuming rs5c372b\n");
+- }
+-
+ /* clock may be set for am/pm or 24 hr time */
+ switch (rs5c372->type) {
+ case rtc_rs5c372a:
+@@ -651,6 +649,7 @@ static struct i2c_driver rs5c372_driver = {
+ },
+ .probe = rs5c372_probe,
+ .remove = rs5c372_remove,
++ .id_table = rs5c372_id,
+ };
+
+ static __init int rs5c372_init(void)
+diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
+index e8abc90..29f47ba 100644
+--- a/drivers/rtc/rtc-s35390a.c
++++ b/drivers/rtc/rtc-s35390a.c
+@@ -34,6 +34,12 @@
+ #define S35390A_FLAG_RESET 0x80
+ #define S35390A_FLAG_TEST 0x01
+
++static const struct i2c_device_id s35390a_id[] = {
++ { "s35390a", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, s35390a_id);
++
+ struct s35390a {
+ struct i2c_client *client[8];
+ struct rtc_device *rtc;
+@@ -195,7 +201,8 @@ static const struct rtc_class_ops s35390a_rtc_ops = {
+
+ static struct i2c_driver s35390a_driver;
+
+-static int s35390a_probe(struct i2c_client *client)
++static int s35390a_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ int err;
+ unsigned int i;
+@@ -296,6 +303,7 @@ static struct i2c_driver s35390a_driver = {
+ },
+ .probe = s35390a_probe,
+ .remove = s35390a_remove,
++ .id_table = s35390a_id,
+ };
+
+ static int __init s35390a_rtc_init(void)
+diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
+index 9f4d512..f26e0ca 100644
+--- a/drivers/rtc/rtc-s3c.c
++++ b/drivers/rtc/rtc-s3c.c
+@@ -68,7 +68,7 @@ static void s3c_rtc_setaie(int to)
+ {
+ unsigned int tmp;
+
+- pr_debug("%s: aie=%d\n", __FUNCTION__, to);
++ pr_debug("%s: aie=%d\n", __func__, to);
+
+ tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
+
+@@ -82,7 +82,7 @@ static void s3c_rtc_setpie(int to)
+ {
+ unsigned int tmp;
+
+- pr_debug("%s: pie=%d\n", __FUNCTION__, to);
++ pr_debug("%s: pie=%d\n", __func__, to);
+
+ spin_lock_irq(&s3c_rtc_pie_lock);
+ tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE;
+@@ -457,7 +457,7 @@ static int s3c_rtc_probe(struct platform_device *pdev)
+ struct resource *res;
+ int ret;
+
+- pr_debug("%s: probe=%p\n", __FUNCTION__, pdev);
++ pr_debug("%s: probe=%p\n", __func__, pdev);
+
+ /* find the IRQs */
+
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
-index 9e9caa5..c594b34 100644
+index 9e9caa5..110699b 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -1,8 +1,9 @@
@@ -621923,6 +822937,15 @@
}
return ret;
+@@ -349,7 +361,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
+
+ dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+- __FUNCTION__,
++ __func__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday);
+
@@ -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);
@@ -622076,6 +823099,476 @@
+ "Angelo Castello <angelo.castello at st.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
+diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
+index 4d27ccc..2531ce4 100644
+--- a/drivers/rtc/rtc-sysfs.c
++++ b/drivers/rtc/rtc-sysfs.c
+@@ -145,6 +145,8 @@ rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr,
+ unsigned long now, alarm;
+ struct rtc_wkalrm alm;
+ struct rtc_device *rtc = to_rtc_device(dev);
++ char *buf_ptr;
++ int adjust = 0;
+
+ /* Only request alarms that trigger in the future. Disable them
+ * by writing another time, e.g. 0 meaning Jan 1 1970 UTC.
+@@ -154,7 +156,15 @@ rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr,
+ return retval;
+ rtc_tm_to_time(&alm.time, &now);
+
+- alarm = simple_strtoul(buf, NULL, 0);
++ buf_ptr = (char *)buf;
++ if (*buf_ptr == '+') {
++ buf_ptr++;
++ adjust = 1;
++ }
++ alarm = simple_strtoul(buf_ptr, NULL, 0);
++ if (adjust) {
++ alarm += now;
++ }
+ if (alarm > now) {
+ /* Avoid accidentally clobbering active alarms; we can't
+ * entirely prevent that here, without even the minimal
+diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c
+index 254c9fc..bc93002 100644
+--- a/drivers/rtc/rtc-test.c
++++ b/drivers/rtc/rtc-test.c
+@@ -147,7 +147,7 @@ static int __devexit test_remove(struct platform_device *plat_dev)
+ return 0;
+ }
+
+-static struct platform_driver test_drv = {
++static struct platform_driver test_driver = {
+ .probe = test_probe,
+ .remove = __devexit_p(test_remove),
+ .driver = {
+@@ -160,7 +160,7 @@ static int __init test_init(void)
+ {
+ int err;
+
+- if ((err = platform_driver_register(&test_drv)))
++ if ((err = platform_driver_register(&test_driver)))
+ return err;
+
+ if ((test0 = platform_device_alloc("rtc-test", 0)) == NULL) {
+@@ -191,7 +191,7 @@ exit_free_test0:
+ platform_device_put(test0);
+
+ exit_driver_unregister:
+- platform_driver_unregister(&test_drv);
++ platform_driver_unregister(&test_driver);
+ return err;
+ }
+
+@@ -199,7 +199,7 @@ static void __exit test_exit(void)
+ {
+ platform_device_unregister(test0);
+ platform_device_unregister(test1);
+- platform_driver_unregister(&test_drv);
++ platform_driver_unregister(&test_driver);
+ }
+
+ MODULE_AUTHOR("Alessandro Zummo <a.zummo at towertech.it>");
+diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c
+index 24203a0..10025d8 100644
+--- a/drivers/rtc/rtc-v3020.c
++++ b/drivers/rtc/rtc-v3020.c
+@@ -107,7 +107,7 @@ static int v3020_read_time(struct device *dev, struct rtc_time *dt)
+ dt->tm_year = BCD2BIN(tmp)+100;
+
+ #ifdef DEBUG
+- printk("\n%s : Read RTC values\n",__FUNCTION__);
++ printk("\n%s : Read RTC values\n",__func__);
+ printk("tm_hour: %i\n",dt->tm_hour);
+ printk("tm_min : %i\n",dt->tm_min);
+ printk("tm_sec : %i\n",dt->tm_sec);
+@@ -126,7 +126,7 @@ static int v3020_set_time(struct device *dev, struct rtc_time *dt)
+ struct v3020 *chip = dev_get_drvdata(dev);
+
+ #ifdef DEBUG
+- printk("\n%s : Setting RTC values\n",__FUNCTION__);
++ printk("\n%s : Setting RTC values\n",__func__);
+ printk("tm_sec : %i\n",dt->tm_sec);
+ printk("tm_min : %i\n",dt->tm_min);
+ printk("tm_hour: %i\n",dt->tm_hour);
+diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c
+index b90fb18..eaf5594 100644
+--- a/drivers/rtc/rtc-x1205.c
++++ b/drivers/rtc/rtc-x1205.c
+@@ -22,20 +22,7 @@
+ #include <linux/rtc.h>
+ #include <linux/delay.h>
+
+-#define DRV_VERSION "1.0.7"
+-
+-/* Addresses to scan: none. This chip is located at
+- * 0x6f and uses a two bytes register addressing.
+- * Two bytes need to be written to read a single register,
+- * while most other chips just require one and take the second
+- * one as the data to be written. To prevent corrupting
+- * unknown chips, the user must explicitly set the probe parameter.
+- */
+-
+-static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
+-
+-/* Insmod parameters */
+-I2C_CLIENT_INSMOD;
++#define DRV_VERSION "1.0.8"
+
+ /* offsets into CCR area */
+
+@@ -91,19 +78,7 @@ I2C_CLIENT_INSMOD;
+
+ #define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */
+
+-/* Prototypes */
+-static int x1205_attach(struct i2c_adapter *adapter);
+-static int x1205_detach(struct i2c_client *client);
+-static int x1205_probe(struct i2c_adapter *adapter, int address, int kind);
+-
+-static struct i2c_driver x1205_driver = {
+- .driver = {
+- .name = "x1205",
+- },
+- .id = I2C_DRIVERID_X1205,
+- .attach_adapter = &x1205_attach,
+- .detach_client = &x1205_detach,
+-};
++static struct i2c_driver x1205_driver;
+
+ /*
+ * In the routines that deal directly with the x1205 hardware, we use
+@@ -124,14 +99,14 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
+
+ /* read date registers */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
++ dev_err(&client->dev, "%s: read error\n", __func__);
+ return -EIO;
+ }
+
+ dev_dbg(&client->dev,
+ "%s: raw read data - sec=%02x, min=%02x, hr=%02x, "
+ "mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n",
+- __FUNCTION__,
++ __func__,
+ buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6], buf[7]);
+
+@@ -146,7 +121,7 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
+
+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+- __FUNCTION__,
++ __func__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+@@ -164,7 +139,7 @@ static int x1205_get_status(struct i2c_client *client, unsigned char *sr)
+
+ /* read status register */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
++ dev_err(&client->dev, "%s: read error\n", __func__);
+ return -EIO;
+ }
+
+@@ -187,7 +162,7 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
+
+ dev_dbg(&client->dev,
+ "%s: secs=%d, mins=%d, hours=%d\n",
+- __FUNCTION__,
++ __func__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour);
+
+ buf[CCR_SEC] = BIN2BCD(tm->tm_sec);
+@@ -200,7 +175,7 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
+ if (datetoo) {
+ dev_dbg(&client->dev,
+ "%s: mday=%d, mon=%d, year=%d, wday=%d\n",
+- __FUNCTION__,
++ __func__,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ buf[CCR_MDAY] = BIN2BCD(tm->tm_mday);
+@@ -216,12 +191,12 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
+
+ /* this sequence is required to unlock the chip */
+ if ((xfer = i2c_master_send(client, wel, 3)) != 3) {
+- dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer);
++ dev_err(&client->dev, "%s: wel - %d\n", __func__, xfer);
+ return -EIO;
+ }
+
+ if ((xfer = i2c_master_send(client, rwel, 3)) != 3) {
+- dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer);
++ dev_err(&client->dev, "%s: rwel - %d\n", __func__, xfer);
+ return -EIO;
+ }
+
+@@ -233,7 +208,7 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
+ if (xfer != 3) {
+ dev_err(&client->dev,
+ "%s: xfer=%d addr=%02x, data=%02x\n",
+- __FUNCTION__,
++ __func__,
+ xfer, rdata[1], rdata[2]);
+ return -EIO;
+ }
+@@ -241,7 +216,7 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
+
+ /* disable further writes */
+ if ((xfer = i2c_master_send(client, diswe, 3)) != 3) {
+- dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer);
++ dev_err(&client->dev, "%s: diswe - %d\n", __func__, xfer);
+ return -EIO;
+ }
+
+@@ -274,11 +249,11 @@ static int x1205_get_dtrim(struct i2c_client *client, int *trim)
+
+ /* read dtr register */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
++ dev_err(&client->dev, "%s: read error\n", __func__);
+ return -EIO;
+ }
+
+- dev_dbg(&client->dev, "%s: raw dtr=%x\n", __FUNCTION__, dtr);
++ dev_dbg(&client->dev, "%s: raw dtr=%x\n", __func__, dtr);
+
+ *trim = 0;
+
+@@ -306,11 +281,11 @@ static int x1205_get_atrim(struct i2c_client *client, int *trim)
+
+ /* read atr register */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
++ dev_err(&client->dev, "%s: read error\n", __func__);
+ return -EIO;
+ }
+
+- dev_dbg(&client->dev, "%s: raw atr=%x\n", __FUNCTION__, atr);
++ dev_dbg(&client->dev, "%s: raw atr=%x\n", __func__, atr);
+
+ /* atr is a two's complement value on 6 bits,
+ * perform sign extension. The formula is
+@@ -319,11 +294,11 @@ static int x1205_get_atrim(struct i2c_client *client, int *trim)
+ if (atr & 0x20)
+ atr |= 0xC0;
+
+- dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __FUNCTION__, atr, atr);
++ dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __func__, atr, atr);
+
+ *trim = (atr * 250) + 11000;
+
+- dev_dbg(&client->dev, "%s: real=%d\n", __FUNCTION__, *trim);
++ dev_dbg(&client->dev, "%s: real=%d\n", __func__, *trim);
+
+ return 0;
+ }
+@@ -377,7 +352,7 @@ static int x1205_validate_client(struct i2c_client *client)
+ if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) {
+ dev_err(&client->dev,
+ "%s: could not read register %x\n",
+- __FUNCTION__, probe_zero_pattern[i]);
++ __func__, probe_zero_pattern[i]);
+
+ return -EIO;
+ }
+@@ -385,7 +360,7 @@ static int x1205_validate_client(struct i2c_client *client)
+ if ((buf & probe_zero_pattern[i+1]) != 0) {
+ dev_err(&client->dev,
+ "%s: register=%02x, zero pattern=%d, value=%x\n",
+- __FUNCTION__, probe_zero_pattern[i], i, buf);
++ __func__, probe_zero_pattern[i], i, buf);
+
+ return -ENODEV;
+ }
+@@ -405,7 +380,7 @@ static int x1205_validate_client(struct i2c_client *client)
+ if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) {
+ dev_err(&client->dev,
+ "%s: could not read register %x\n",
+- __FUNCTION__, probe_limits_pattern[i].reg);
++ __func__, probe_limits_pattern[i].reg);
+
+ return -EIO;
+ }
+@@ -416,7 +391,7 @@ static int x1205_validate_client(struct i2c_client *client)
+ value < probe_limits_pattern[i].min) {
+ dev_dbg(&client->dev,
+ "%s: register=%x, lim pattern=%d, value=%d\n",
+- __FUNCTION__, probe_limits_pattern[i].reg,
++ __func__, probe_limits_pattern[i].reg,
+ i, value);
+
+ return -ENODEV;
+@@ -497,58 +472,50 @@ static ssize_t x1205_sysfs_show_dtrim(struct device *dev,
+ }
+ static DEVICE_ATTR(dtrim, S_IRUGO, x1205_sysfs_show_dtrim, NULL);
+
+-static int x1205_attach(struct i2c_adapter *adapter)
++static int x1205_sysfs_register(struct device *dev)
+ {
+- return i2c_probe(adapter, &addr_data, x1205_probe);
++ int err;
++
++ err = device_create_file(dev, &dev_attr_atrim);
++ if (err)
++ return err;
++
++ err = device_create_file(dev, &dev_attr_dtrim);
++ if (err)
++ device_remove_file(dev, &dev_attr_atrim);
++
++ return err;
+ }
+
+-static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
++static void x1205_sysfs_unregister(struct device *dev)
++{
++ device_remove_file(dev, &dev_attr_atrim);
++ device_remove_file(dev, &dev_attr_dtrim);
++}
++
++
++static int x1205_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
+ {
+ int err = 0;
+ unsigned char sr;
+- struct i2c_client *client;
+ struct rtc_device *rtc;
+
+- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+-
+- if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+- err = -ENODEV;
+- goto exit;
+- }
+-
+- if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
+- err = -ENOMEM;
+- goto exit;
+- }
+-
+- /* I2C client */
+- client->addr = address;
+- client->driver = &x1205_driver;
+- client->adapter = adapter;
+-
+- strlcpy(client->name, x1205_driver.driver.name, I2C_NAME_SIZE);
++ dev_dbg(&client->dev, "%s\n", __func__);
+
+- /* Verify the chip is really an X1205 */
+- if (kind < 0) {
+- if (x1205_validate_client(client) < 0) {
+- err = -ENODEV;
+- goto exit_kfree;
+- }
+- }
++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
++ return -ENODEV;
+
+- /* Inform the i2c layer */
+- if ((err = i2c_attach_client(client)))
+- goto exit_kfree;
++ if (x1205_validate_client(client) < 0)
++ return -ENODEV;
+
+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+
+ rtc = rtc_device_register(x1205_driver.driver.name, &client->dev,
+ &x1205_rtc_ops, THIS_MODULE);
+
+- if (IS_ERR(rtc)) {
+- err = PTR_ERR(rtc);
+- goto exit_detach;
+- }
++ if (IS_ERR(rtc))
++ return PTR_ERR(rtc);
+
+ i2c_set_clientdata(client, rtc);
+
+@@ -565,45 +532,42 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
+ else
+ dev_err(&client->dev, "couldn't read status\n");
+
+- err = device_create_file(&client->dev, &dev_attr_atrim);
+- if (err) goto exit_devreg;
+- err = device_create_file(&client->dev, &dev_attr_dtrim);
+- if (err) goto exit_atrim;
++ err = x1205_sysfs_register(&client->dev);
++ if (err)
++ goto exit_devreg;
+
+ return 0;
+
+-exit_atrim:
+- device_remove_file(&client->dev, &dev_attr_atrim);
+-
+ exit_devreg:
+ rtc_device_unregister(rtc);
+
+-exit_detach:
+- i2c_detach_client(client);
+-
+-exit_kfree:
+- kfree(client);
+-
+-exit:
+ return err;
+ }
+
+-static int x1205_detach(struct i2c_client *client)
++static int x1205_remove(struct i2c_client *client)
+ {
+- int err;
+ struct rtc_device *rtc = i2c_get_clientdata(client);
+
+- if (rtc)
+- rtc_device_unregister(rtc);
+-
+- if ((err = i2c_detach_client(client)))
+- return err;
+-
+- kfree(client);
+-
++ rtc_device_unregister(rtc);
++ x1205_sysfs_unregister(&client->dev);
+ return 0;
+ }
+
++static const struct i2c_device_id x1205_id[] = {
++ { "x1205", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, x1205_id);
++
++static struct i2c_driver x1205_driver = {
++ .driver = {
++ .name = "rtc-x1205",
++ },
++ .probe = x1205_probe,
++ .remove = x1205_remove,
++ .id_table = x1205_id,
++};
++
+ static int __init x1205_init(void)
+ {
+ return i2c_add_driver(&x1205_driver);
+diff --git a/drivers/s390/Makefile b/drivers/s390/Makefile
+index 5a88870..4f4e7cf 100644
+--- a/drivers/s390/Makefile
++++ b/drivers/s390/Makefile
+@@ -5,7 +5,7 @@
+ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
+
+ obj-y += s390mach.o sysinfo.o s390_rdev.o
+-obj-y += cio/ block/ char/ crypto/ net/ scsi/
++obj-y += cio/ block/ char/ crypto/ net/ scsi/ kvm/
+
+ drivers-y += drivers/s390/built-in.o
+
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
index e879b21..0788319 100644
--- a/drivers/s390/block/Kconfig
@@ -622303,10 +823796,70 @@
/* externals in dasd_eer.c */
#ifdef CONFIG_DASD_EER
+diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
+index 556063e..03c0e40 100644
+--- a/drivers/s390/block/dasd_proc.c
++++ b/drivers/s390/block/dasd_proc.c
+@@ -157,6 +157,7 @@ static int dasd_devices_open(struct inode *inode, struct file *file)
+ }
+
+ static const struct file_operations dasd_devices_file_ops = {
++ .owner = THIS_MODULE,
+ .open = dasd_devices_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -311,17 +312,16 @@ out_error:
+ int
+ dasd_proc_init(void)
+ {
+- dasd_proc_root_entry = proc_mkdir("dasd", &proc_root);
++ dasd_proc_root_entry = proc_mkdir("dasd", NULL);
+ if (!dasd_proc_root_entry)
+ goto out_nodasd;
+ dasd_proc_root_entry->owner = THIS_MODULE;
+- dasd_devices_entry = create_proc_entry("devices",
+- S_IFREG | S_IRUGO | S_IWUSR,
+- dasd_proc_root_entry);
++ dasd_devices_entry = proc_create("devices",
++ S_IFREG | S_IRUGO | S_IWUSR,
++ dasd_proc_root_entry,
++ &dasd_devices_file_ops);
+ if (!dasd_devices_entry)
+ goto out_nodevices;
+- dasd_devices_entry->proc_fops = &dasd_devices_file_ops;
+- dasd_devices_entry->owner = THIS_MODULE;
+ dasd_statistics_entry = create_proc_entry("statistics",
+ S_IFREG | S_IRUGO | S_IWUSR,
+ dasd_proc_root_entry);
+@@ -335,7 +335,7 @@ dasd_proc_init(void)
+ out_nostatistics:
+ remove_proc_entry("devices", dasd_proc_root_entry);
+ out_nodevices:
+- remove_proc_entry("dasd", &proc_root);
++ remove_proc_entry("dasd", NULL);
+ out_nodasd:
+ return -ENOENT;
+ }
+@@ -345,5 +345,5 @@ dasd_proc_exit(void)
+ {
+ remove_proc_entry("devices", dasd_proc_root_entry);
+ remove_proc_entry("statistics", dasd_proc_root_entry);
+- remove_proc_entry("dasd", &proc_root);
++ remove_proc_entry("dasd", NULL);
+ }
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
-index e6c94db..04787ea 100644
+index e6c94db..bb52d2f 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
+@@ -36,7 +36,7 @@ static int dcssblk_open(struct inode *inode, struct file *filp);
+ static int dcssblk_release(struct inode *inode, struct file *filp);
+ static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
+ static int dcssblk_direct_access(struct block_device *bdev, sector_t secnum,
+- unsigned long *data);
++ void **kaddr, unsigned long *pfn);
+
+ static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0";
+
@@ -142,57 +142,6 @@ dcssblk_get_device_by_name(char *name)
return NULL;
}
@@ -622374,6 +823927,49 @@
goto dealloc_gendisk;
}
seg_byte_size = (dev_info->end - dev_info->start + 1);
+@@ -687,7 +636,7 @@ fail:
+
+ static int
+ dcssblk_direct_access (struct block_device *bdev, sector_t secnum,
+- unsigned long *data)
++ void **kaddr, unsigned long *pfn)
+ {
+ struct dcssblk_dev_info *dev_info;
+ unsigned long pgoff;
+@@ -700,7 +649,9 @@ dcssblk_direct_access (struct block_device *bdev, sector_t secnum,
+ pgoff = secnum / (PAGE_SIZE / 512);
+ if ((pgoff+1)*PAGE_SIZE-1 > dev_info->end - dev_info->start)
+ return -ERANGE;
+- *data = (unsigned long) (dev_info->start+pgoff*PAGE_SIZE);
++ *kaddr = (void *) (dev_info->start+pgoff*PAGE_SIZE);
++ *pfn = virt_to_phys(*kaddr) >> PAGE_SHIFT;
++
+ return 0;
+ }
+
+diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
+index 0e1f35c..3e5653c 100644
+--- a/drivers/s390/char/con3215.c
++++ b/drivers/s390/char/con3215.c
+@@ -982,15 +982,16 @@ tty3215_write(struct tty_struct * tty,
+ /*
+ * Put character routine for 3215 ttys
+ */
+-static void
++static int
+ tty3215_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ struct raw3215_info *raw;
+
+ if (!tty)
+- return;
++ return 0;
+ raw = (struct raw3215_info *) tty->driver_data;
+ raw3215_putchar(raw, ch);
++ return 1;
+ }
+
+ static void
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index 67009bf..1e1f506 100644
--- a/drivers/s390/char/monreader.c
@@ -622453,8 +824049,66 @@
rc = -EINVAL;
goto out_iucv;
}
+diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c
+index b8f35bc..9e784d5 100644
+--- a/drivers/s390/char/sclp_config.c
++++ b/drivers/s390/char/sclp_config.c
+@@ -10,6 +10,7 @@
+ #include <linux/cpu.h>
+ #include <linux/sysdev.h>
+ #include <linux/workqueue.h>
++#include <asm/smp.h>
+ #include "sclp.h"
+
+ #define TAG "sclp_config: "
+@@ -19,9 +20,11 @@ struct conf_mgm_data {
+ u8 ev_qualifier;
+ } __attribute__((packed));
+
++#define EV_QUAL_CPU_CHANGE 1
+ #define EV_QUAL_CAP_CHANGE 3
+
+ static struct work_struct sclp_cpu_capability_work;
++static struct work_struct sclp_cpu_change_work;
+
+ static void sclp_cpu_capability_notify(struct work_struct *work)
+ {
+@@ -37,13 +40,24 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
+ put_online_cpus();
+ }
+
++static void sclp_cpu_change_notify(struct work_struct *work)
++{
++ smp_rescan_cpus();
++}
++
+ static void sclp_conf_receiver_fn(struct evbuf_header *evbuf)
+ {
+ struct conf_mgm_data *cdata;
+
+ cdata = (struct conf_mgm_data *)(evbuf + 1);
+- if (cdata->ev_qualifier == EV_QUAL_CAP_CHANGE)
++ switch (cdata->ev_qualifier) {
++ case EV_QUAL_CPU_CHANGE:
++ schedule_work(&sclp_cpu_change_work);
++ break;
++ case EV_QUAL_CAP_CHANGE:
+ schedule_work(&sclp_cpu_capability_work);
++ break;
++ }
+ }
+
+ static struct sclp_register sclp_conf_register =
+@@ -57,6 +71,7 @@ static int __init sclp_conf_init(void)
+ int rc;
+
+ INIT_WORK(&sclp_cpu_capability_work, sclp_cpu_capability_notify);
++ INIT_WORK(&sclp_cpu_change_work, sclp_cpu_change_notify);
+
+ rc = sclp_register(&sclp_conf_register);
+ if (rc) {
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
-index 2e616e3..e3b3d39 100644
+index 2e616e3..40b1152 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)
@@ -622466,8 +824120,25 @@
sclp_sync_wait();
else
wait_event(sclp_tty_waitq,
+@@ -412,14 +412,14 @@ sclp_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
+ * - including previous characters from sclp_tty_put_char() and strings from
+ * sclp_write() without final '\n' - will be written.
+ */
+-static void
++static int
+ sclp_tty_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ sclp_tty_chars[sclp_tty_chars_count++] = ch;
+ if (ch == '\n' || sclp_tty_chars_count >= SCLP_TTY_BUF_SIZE) {
+ sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count);
+ sclp_tty_chars_count = 0;
+- }
++ } return 1;
+ }
+
+ /*
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
-index f7b258d..ed50759 100644
+index f7b258d..35707c0 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)
@@ -622500,16 +824171,25 @@
}
#define SCLP_VT220_SESSION_ENDED 0x01
-@@ -529,7 +528,7 @@ sclp_vt220_close(struct tty_struct *tty, struct file *filp)
- static void
+@@ -525,11 +524,15 @@ sclp_vt220_close(struct tty_struct *tty, struct file *filp)
+ * NOTE: include/linux/tty_driver.h specifies that a character should be
+ * ignored if there is no room in the queue. This driver implements a different
+ * semantic in that it will block when there is no more room left.
++ *
++ * FIXME: putchar can currently be called from BH and other non blocking
++ * handlers so this semantic isn't a good idea.
+ */
+-static void
++static int
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);
++ return 1;
}
/*
-@@ -746,7 +745,7 @@ __initcall(sclp_vt220_tty_init);
+@@ -746,7 +749,7 @@ __initcall(sclp_vt220_tty_init);
static void
sclp_vt220_con_write(struct console *con, const char *buf, unsigned int count)
{
@@ -622577,6 +824257,63 @@
+void unregister_tape_dev(struct device *device, struct tape_class_device *tcd);
#endif /* __TAPE_CLASS_H__ */
+diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c
+index c9b96d5..e7c888c 100644
+--- a/drivers/s390/char/tape_proc.c
++++ b/drivers/s390/char/tape_proc.c
+@@ -111,6 +111,7 @@ static int tape_proc_open(struct inode *inode, struct file *file)
+
+ static const struct file_operations tape_proc_ops =
+ {
++ .owner = THIS_MODULE,
+ .open = tape_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -124,14 +125,12 @@ void
+ tape_proc_init(void)
+ {
+ tape_proc_devices =
+- create_proc_entry ("tapedevices", S_IFREG | S_IRUGO | S_IWUSR,
+- &proc_root);
++ proc_create("tapedevices", S_IFREG | S_IRUGO | S_IWUSR, NULL,
++ &tape_proc_ops);
+ if (tape_proc_devices == NULL) {
+ PRINT_WARN("tape: Cannot register procfs entry tapedevices\n");
+ return;
+ }
+- tape_proc_devices->proc_fops = &tape_proc_ops;
+- tape_proc_devices->owner = THIS_MODULE;
+ }
+
+ /*
+@@ -141,5 +140,5 @@ void
+ tape_proc_cleanup(void)
+ {
+ if (tape_proc_devices != NULL)
+- remove_proc_entry ("tapedevices", &proc_root);
++ remove_proc_entry ("tapedevices", NULL);
+ }
+diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
+index 70b1980..c1f2ade 100644
+--- a/drivers/s390/char/tty3270.c
++++ b/drivers/s390/char/tty3270.c
+@@ -965,7 +965,7 @@ tty3270_write_room(struct tty_struct *tty)
+ * Insert character into the screen at the current position with the
+ * current color and highlight. This function does NOT do cursor movement.
+ */
+-static void
++static int
+ tty3270_put_character(struct tty3270 *tp, char ch)
+ {
+ struct tty3270_line *line;
+@@ -986,6 +986,7 @@ tty3270_put_character(struct tty3270 *tp, char ch)
+ cell->character = tp->view.ascebc[(unsigned int) ch];
+ cell->highlight = tp->highlight;
+ cell->f_color = tp->f_color;
++ return 1;
+ }
+
+ /*
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index 7689b50..83ae9a8 100644
--- a/drivers/s390/char/vmur.c
@@ -622697,8 +824434,28 @@
return -ENOMEM;
}
if (memcpy_hsa_kernel(sa, sys_info.sa_base, sys_info.sa_size) < 0) {
+diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
+index e8597ec..40ef948 100644
+--- a/drivers/s390/cio/blacklist.c
++++ b/drivers/s390/cio/blacklist.c
+@@ -374,13 +374,10 @@ cio_ignore_proc_init (void)
+ {
+ struct proc_dir_entry *entry;
+
+- entry = create_proc_entry ("cio_ignore", S_IFREG | S_IRUGO | S_IWUSR,
+- &proc_root);
++ entry = proc_create("cio_ignore", S_IFREG | S_IRUGO | S_IWUSR, NULL,
++ &cio_ignore_proc_fops);
+ if (!entry)
+ return -ENOENT;
+-
+- entry->proc_fops = &cio_ignore_proc_fops;
+-
+ return 0;
+ }
+
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
-index 03914fa..fe1ad17 100644
+index 03914fa..26a930e 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -16,7 +16,6 @@
@@ -622709,6 +824466,186 @@
#include <asm/ccwdev.h>
#include <asm/ccwgroup.h>
+@@ -153,44 +152,89 @@ __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
+ return 0;
+ }
+
++static int __get_next_bus_id(const char **buf, char *bus_id)
++{
++ int rc, len;
++ char *start, *end;
++
++ start = (char *)*buf;
++ end = strchr(start, ',');
++ if (!end) {
++ /* Last entry. Strip trailing newline, if applicable. */
++ end = strchr(start, '\n');
++ if (end)
++ *end = '\0';
++ len = strlen(start) + 1;
++ } else {
++ len = end - start + 1;
++ end++;
++ }
++ if (len < BUS_ID_SIZE) {
++ strlcpy(bus_id, start, len);
++ rc = 0;
++ } else
++ rc = -EINVAL;
++ *buf = end;
++ return rc;
++}
++
++static int __is_valid_bus_id(char bus_id[BUS_ID_SIZE])
++{
++ int cssid, ssid, devno;
++
++ /* Must be of form %x.%x.%04x */
++ if (sscanf(bus_id, "%x.%1x.%04x", &cssid, &ssid, &devno) != 3)
++ return 0;
++ return 1;
++}
++
+ /**
+- * ccwgroup_create() - create and register a ccw group device
++ * ccwgroup_create_from_string() - create and register a ccw group device
+ * @root: parent device for the new device
+ * @creator_id: identifier of creating driver
+ * @cdrv: ccw driver of slave devices
+- * @argc: number of slave devices
+- * @argv: bus ids of slave devices
++ * @num_devices: number of slave devices
++ * @buf: buffer containing comma separated bus ids of slave devices
+ *
+ * Create and register a new ccw group device as a child of @root. Slave
+- * devices are obtained from the list of bus ids given in @argv[] and must all
++ * devices are obtained from the list of bus ids given in @buf and must all
+ * belong to @cdrv.
+ * Returns:
+ * %0 on success and an error code on failure.
+ * Context:
+ * non-atomic
+ */
+-int ccwgroup_create(struct device *root, unsigned int creator_id,
+- struct ccw_driver *cdrv, int argc, char *argv[])
++int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
++ struct ccw_driver *cdrv, int num_devices,
++ const char *buf)
+ {
+ struct ccwgroup_device *gdev;
+- int i;
+- int rc;
++ int rc, i;
++ char tmp_bus_id[BUS_ID_SIZE];
++ const char *curr_buf;
+
+- if (argc > 256) /* disallow dumb users */
+- return -EINVAL;
+-
+- gdev = kzalloc(sizeof(*gdev) + argc*sizeof(gdev->cdev[0]), GFP_KERNEL);
++ gdev = kzalloc(sizeof(*gdev) + num_devices * sizeof(gdev->cdev[0]),
++ GFP_KERNEL);
+ if (!gdev)
+ return -ENOMEM;
+
+ atomic_set(&gdev->onoff, 0);
+ mutex_init(&gdev->reg_mutex);
+ mutex_lock(&gdev->reg_mutex);
+- for (i = 0; i < argc; i++) {
+- gdev->cdev[i] = get_ccwdev_by_busid(cdrv, argv[i]);
+-
+- /* all devices have to be of the same type in
+- * order to be grouped */
++ curr_buf = buf;
++ for (i = 0; i < num_devices && curr_buf; i++) {
++ rc = __get_next_bus_id(&curr_buf, tmp_bus_id);
++ if (rc != 0)
++ goto error;
++ if (!__is_valid_bus_id(tmp_bus_id)) {
++ rc = -EINVAL;
++ goto error;
++ }
++ gdev->cdev[i] = get_ccwdev_by_busid(cdrv, tmp_bus_id);
++ /*
++ * All devices have to be of the same type in
++ * order to be grouped.
++ */
+ if (!gdev->cdev[i]
+ || gdev->cdev[i]->id.driver_info !=
+ gdev->cdev[0]->id.driver_info) {
+@@ -204,9 +248,18 @@ int ccwgroup_create(struct device *root, unsigned int creator_id,
+ }
+ dev_set_drvdata(&gdev->cdev[i]->dev, gdev);
+ }
+-
++ /* Check for sufficient number of bus ids. */
++ if (i < num_devices && !curr_buf) {
++ rc = -EINVAL;
++ goto error;
++ }
++ /* Check for trailing stuff. */
++ if (i == num_devices && strlen(curr_buf) > 0) {
++ rc = -EINVAL;
++ goto error;
++ }
+ gdev->creator_id = creator_id;
+- gdev->count = argc;
++ gdev->count = num_devices;
+ gdev->dev.bus = &ccwgroup_bus_type;
+ gdev->dev.parent = root;
+ gdev->dev.release = ccwgroup_release;
+@@ -234,7 +287,7 @@ int ccwgroup_create(struct device *root, unsigned int creator_id,
+ device_remove_file(&gdev->dev, &dev_attr_ungroup);
+ device_unregister(&gdev->dev);
+ error:
+- for (i = 0; i < argc; i++)
++ for (i = 0; i < num_devices; i++)
+ if (gdev->cdev[i]) {
+ if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev)
+ dev_set_drvdata(&gdev->cdev[i]->dev, NULL);
+@@ -244,6 +297,7 @@ error:
+ put_device(&gdev->dev);
+ return rc;
+ }
++EXPORT_SYMBOL(ccwgroup_create_from_string);
+
+ static int __init
+ init_ccwgroup (void)
+@@ -319,7 +373,7 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const
+ {
+ struct ccwgroup_device *gdev;
+ struct ccwgroup_driver *gdrv;
+- unsigned int value;
++ unsigned long value;
+ int ret;
+
+ gdev = to_ccwgroupdev(dev);
+@@ -330,7 +384,9 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const
+ if (!try_module_get(gdrv->owner))
+ return -EINVAL;
+
+- value = simple_strtoul(buf, NULL, 0);
++ ret = strict_strtoul(buf, 0, &value);
++ if (ret)
++ goto out;
+ ret = count;
+ if (value == 1)
+ ccwgroup_set_online(gdev);
+@@ -338,6 +394,7 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const
+ ccwgroup_set_offline(gdev);
+ else
+ ret = -EINVAL;
++out:
+ module_put(gdrv->owner);
+ return ret;
+ }
+@@ -519,6 +576,5 @@ void ccwgroup_remove_ccwdev(struct ccw_device *cdev)
+ MODULE_LICENSE("GPL");
+ EXPORT_SYMBOL(ccwgroup_driver_register);
+ EXPORT_SYMBOL(ccwgroup_driver_unregister);
+-EXPORT_SYMBOL(ccwgroup_create);
+ EXPORT_SYMBOL(ccwgroup_probe_ccwdev);
+ EXPORT_SYMBOL(ccwgroup_remove_ccwdev);
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 007aaeb..5de8690 100644
--- a/drivers/s390/cio/chsc.c
@@ -622780,7 +824717,7 @@
return ret;
}
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
-index 60590a1..23ffcc4 100644
+index 60590a1..08a5781 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -24,6 +24,7 @@
@@ -622791,7 +824728,48 @@
#include "cio.h"
#include "css.h"
#include "chsc.h"
-@@ -649,13 +650,10 @@ do_IRQ (struct pt_regs *regs)
+@@ -406,8 +407,7 @@ cio_modify (struct subchannel *sch)
+ /*
+ * Enable subchannel.
+ */
+-int cio_enable_subchannel(struct subchannel *sch, unsigned int isc,
+- u32 intparm)
++int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
+ {
+ char dbf_txt[15];
+ int ccode;
+@@ -425,7 +425,7 @@ int cio_enable_subchannel(struct subchannel *sch, unsigned int isc,
+
+ for (retry = 5, ret = 0; retry > 0; retry--) {
+ sch->schib.pmcw.ena = 1;
+- sch->schib.pmcw.isc = isc;
++ sch->schib.pmcw.isc = sch->isc;
+ sch->schib.pmcw.intparm = intparm;
+ ret = cio_modify(sch);
+ if (ret == -ENODEV)
+@@ -599,6 +599,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
+ else
+ sch->opm = chp_get_sch_opm(sch);
+ sch->lpm = sch->schib.pmcw.pam & sch->opm;
++ sch->isc = 3;
+
+ CIO_DEBUG(KERN_INFO, 0,
+ "Detected device %04x on subchannel 0.%x.%04X"
+@@ -609,13 +610,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
+
+ /*
+ * We now have to initially ...
+- * ... set "interruption subclass"
+ * ... enable "concurrent sense"
+ * ... enable "multipath mode" if more than one
+ * CHPID is available. This is done regardless
+ * whether multiple paths are available for us.
+ */
+- sch->schib.pmcw.isc = 3; /* could be smth. else */
+ sch->schib.pmcw.csense = 1; /* concurrent sense */
+ sch->schib.pmcw.ena = 0;
+ if ((sch->lpm & (sch->lpm - 1)) != 0)
+@@ -649,13 +648,10 @@ do_IRQ (struct pt_regs *regs)
old_regs = set_irq_regs(regs);
irq_enter();
@@ -622809,7 +824787,7 @@
/*
* Get interrupt information from lowcore
*/
-@@ -672,10 +670,14 @@ do_IRQ (struct pt_regs *regs)
+@@ -672,10 +668,14 @@ do_IRQ (struct pt_regs *regs)
continue;
}
sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
@@ -622827,7 +824805,7 @@
/* 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)
+@@ -683,8 +683,7 @@ do_IRQ (struct pt_regs *regs)
if (sch->driver && sch->driver->irq)
sch->driver->irq(sch);
}
@@ -622837,7 +824815,7 @@
/*
* Are more interrupts pending?
* If so, the tpi instruction will update the lowcore
-@@ -710,8 +711,9 @@ void *cio_get_console_priv(void)
+@@ -710,8 +709,9 @@ void *cio_get_console_priv(void)
/*
* busy wait for the next interrupt on the console
*/
@@ -622849,11 +824827,36 @@
{
unsigned long cr6 __attribute__ ((aligned (8)));
unsigned long save_cr6 __attribute__ ((aligned (8)));
+@@ -810,6 +810,7 @@ cio_probe_console(void)
+ * enable console I/O-interrupt subclass 7
+ */
+ ctl_set_bit(6, 24);
++ console_subchannel.isc = 7;
+ console_subchannel.schib.pmcw.isc = 7;
+ console_subchannel.schib.pmcw.intparm =
+ (u32)(addr_t)&console_subchannel;
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
-index 52afa4c..08f2235 100644
+index 52afa4c..3c75412 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
-@@ -100,6 +100,7 @@ extern int cio_modify (struct subchannel *);
+@@ -74,6 +74,7 @@ struct subchannel {
+ __u8 lpm; /* logical path mask */
+ __u8 opm; /* operational path mask */
+ struct schib schib; /* subchannel information block */
++ int isc; /* desired interruption subclass */
+ struct chsc_ssd_info ssd_info; /* subchannel description */
+ struct device dev; /* entry in device tree */
+ struct css_driver *driver;
+@@ -85,7 +86,7 @@ struct subchannel {
+ #define to_subchannel(n) container_of(n, struct subchannel, dev)
+
+ extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id);
+-extern int cio_enable_subchannel(struct subchannel *, unsigned int, u32);
++extern int cio_enable_subchannel(struct subchannel *, u32);
+ extern int cio_disable_subchannel (struct subchannel *);
+ extern int cio_cancel (struct subchannel *);
+ extern int cio_clear (struct subchannel *);
+@@ -100,6 +101,7 @@ extern int cio_modify (struct subchannel *);
int cio_create_sch_lock(struct subchannel *);
void do_adapter_IO(void);
@@ -622861,8 +824864,37 @@
/* Use with care. */
#ifdef CONFIG_CCW_CONSOLE
+diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
+index f4c132a..2808b68 100644
+--- a/drivers/s390/cio/cmf.c
++++ b/drivers/s390/cio/cmf.c
+@@ -1219,16 +1219,21 @@ static ssize_t cmb_enable_store(struct device *dev,
+ {
+ struct ccw_device *cdev;
+ int ret;
++ unsigned long val;
++
++ ret = strict_strtoul(buf, 16, &val);
++ if (ret)
++ return ret;
+
+ cdev = to_ccwdev(dev);
+
+- switch (buf[0]) {
+- case '0':
++ switch (val) {
++ case 0:
+ ret = disable_cmf(cdev);
+ if (ret)
+ dev_info(&cdev->dev, "disable_cmf failed (%d)\n", ret);
+ break;
+- case '1':
++ case 1:
+ ret = enable_cmf(cdev);
+ if (ret && ret != -EBUSY)
+ dev_info(&cdev->dev, "enable_cmf failed (%d)\n", ret);
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
-index 3b45bbe..c1afab5 100644
+index 3b45bbe..595e327 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -533,6 +533,12 @@ void css_schedule_eval_all(void)
@@ -622894,15 +824926,26 @@
}
static ssize_t
-@@ -696,6 +706,7 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,
+@@ -695,17 +705,23 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,
+ {
struct channel_subsystem *css = to_css(dev);
int ret;
++ unsigned long val;
+- switch (buf[0]) {
+- case '0':
++ ret = strict_strtoul(buf, 16, &val);
++ if (ret)
++ return ret;
+ mutex_lock(&css->mutex);
- switch (buf[0]) {
- case '0':
++ switch (val) {
++ 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,
+ break;
+- case '1':
++ case 1:
+ ret = css->cm_enabled ? 0 : chsc_secm(css, 1);
+ break;
default:
ret = -EINVAL;
}
@@ -622910,7 +824953,7 @@
return ret < 0 ? ret : count;
}
-@@ -752,9 +764,11 @@ static int css_reboot_event(struct notifier_block *this,
+@@ -752,9 +768,11 @@ static int css_reboot_event(struct notifier_block *this,
struct channel_subsystem *css;
css = channel_subsystems[i];
@@ -622935,10 +824978,56 @@
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
+index fec004f..abfd601 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);
+@@ -512,8 +512,8 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+ struct ccw_device *cdev = to_ccwdev(dev);
+- int i, force;
+- char *tmp;
++ int force, ret;
++ unsigned long i;
+
+ if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0)
+ return -EAGAIN;
+@@ -525,25 +525,30 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
+ if (!strncmp(buf, "force\n", count)) {
+ force = 1;
+ i = 1;
++ ret = 0;
+ } else {
+ force = 0;
+- i = simple_strtoul(buf, &tmp, 16);
++ ret = strict_strtoul(buf, 16, &i);
+ }
+-
++ if (ret)
++ goto out;
+ switch (i) {
+ case 0:
+ online_store_handle_offline(cdev);
++ ret = count;
+ break;
+ case 1:
+ online_store_handle_online(cdev, force);
++ ret = count;
+ break;
+ default:
+- count = -EINVAL;
++ ret = -EINVAL;
+ }
++out:
+ if (cdev->drv)
+ module_put(cdev->drv->owner);
+ atomic_set(&cdev->private->onoff, 0);
+- return count;
++ return ret;
+ }
+
+ static ssize_t
+@@ -577,7 +582,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);
@@ -622956,8 +825045,50 @@
int cmf_reenable(struct ccw_device *);
+extern struct device_attribute dev_attr_cmb_enable;
#endif
+diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
+index 4b92c84..99403b0 100644
+--- a/drivers/s390/cio/device_fsm.c
++++ b/drivers/s390/cio/device_fsm.c
+@@ -555,8 +555,7 @@ ccw_device_recognition(struct ccw_device *cdev)
+ (cdev->private->state != DEV_STATE_BOXED))
+ return -EINVAL;
+ sch = to_subchannel(cdev->dev.parent);
+- ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc,
+- (u32)(addr_t)sch);
++ ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
+ if (ret != 0)
+ /* Couldn't enable the subchannel for i/o. Sick device. */
+ return ret;
+@@ -667,8 +666,7 @@ ccw_device_online(struct ccw_device *cdev)
+ sch = to_subchannel(cdev->dev.parent);
+ if (css_init_done && !get_device(&cdev->dev))
+ return -ENODEV;
+- ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc,
+- (u32)(addr_t)sch);
++ ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
+ if (ret != 0) {
+ /* Couldn't enable the subchannel for i/o. Sick device. */
+ if (ret == -ENODEV)
+@@ -1048,8 +1046,7 @@ ccw_device_start_id(struct ccw_device *cdev, enum dev_event dev_event)
+ struct subchannel *sch;
+
+ sch = to_subchannel(cdev->dev.parent);
+- if (cio_enable_subchannel(sch, sch->schib.pmcw.isc,
+- (u32)(addr_t)sch) != 0)
++ if (cio_enable_subchannel(sch, (u32)(addr_t)sch) != 0)
+ /* Couldn't enable the subchannel for i/o. Sick device. */
+ return;
+
+@@ -1082,7 +1079,6 @@ device_trigger_reprobe(struct subchannel *sch)
+ */
+ sch->lpm = sch->schib.pmcw.pam & sch->opm;
+ /* Re-set some bits in the pmcw that were lost. */
+- sch->schib.pmcw.isc = 3;
+ sch->schib.pmcw.csense = 1;
+ sch->schib.pmcw.ena = 0;
+ if ((sch->lpm & (sch->lpm - 1)) != 0)
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
-index 49b58eb..a1718a0 100644
+index 49b58eb..f308ad5 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,
@@ -622977,6 +825108,15 @@
return ret;
}
+@@ -501,7 +508,7 @@ ccw_device_stlck(struct ccw_device *cdev)
+ return -ENOMEM;
+ }
+ spin_lock_irqsave(sch->lock, flags);
+- ret = cio_enable_subchannel(sch, 3, (u32)(addr_t)sch);
++ ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
+ if (ret)
+ goto out_unlock;
+ /*
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
@@ -623011,7 +825151,7 @@
/*
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
-index 2b5bfb7..10aa1e7 100644
+index 2b5bfb7..445cf36 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -38,11 +38,11 @@
@@ -623251,6 +825391,40 @@
/* 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;
+@@ -3638,7 +3632,7 @@ qdio_add_procfs_entry(void)
+ {
+ proc_perf_file_registration=0;
+ qdio_perf_proc_file=create_proc_entry(QDIO_PERF,
+- S_IFREG|0444,&proc_root);
++ S_IFREG|0444,NULL);
+ if (qdio_perf_proc_file) {
+ qdio_perf_proc_file->read_proc=&qdio_perf_procfile_read;
+ } else proc_perf_file_registration=-1;
+@@ -3653,7 +3647,7 @@ static void
+ qdio_remove_procfs_entry(void)
+ {
+ if (!proc_perf_file_registration) /* means if it went ok earlier */
+- remove_proc_entry(QDIO_PERF,&proc_root);
++ remove_proc_entry(QDIO_PERF,NULL);
+ }
+
+ /**
+@@ -3669,11 +3663,11 @@ qdio_performance_stats_show(struct bus_type *bus, char *buf)
+ static ssize_t
+ qdio_performance_stats_store(struct bus_type *bus, const char *buf, size_t count)
+ {
+- char *tmp;
+- int i;
++ unsigned long i;
++ int ret;
+
+- i = simple_strtoul(buf, &tmp, 16);
+- if ((i == 0) || (i == 1)) {
++ ret = strict_strtoul(buf, 16, &i);
++ if (!ret && ((i == 0) || (i == 1))) {
+ if (i == qdio_performance_stats)
+ return count;
+ qdio_performance_stats = i;
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index da8a272..c3df6b2 100644
--- a/drivers/s390/cio/qdio.h
@@ -624577,6 +826751,366 @@
ap_dev->reply = &zdev->reply;
ap_dev->private = zdev;
rc = zcrypt_device_register(zdev);
+diff --git a/drivers/s390/kvm/Makefile b/drivers/s390/kvm/Makefile
+new file mode 100644
+index 0000000..4a5ec39
+--- /dev/null
++++ b/drivers/s390/kvm/Makefile
+@@ -0,0 +1,9 @@
++# Makefile for kvm guest drivers on s390
++#
++# Copyright IBM Corp. 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.
++
++obj-$(CONFIG_VIRTIO) += kvm_virtio.o
+diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
+new file mode 100644
+index 0000000..47a7e62
+--- /dev/null
++++ b/drivers/s390/kvm/kvm_virtio.c
+@@ -0,0 +1,339 @@
++/*
++ * kvm_virtio.c - virtio for kvm on s390
++ *
++ * Copyright IBM Corp. 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): Christian Borntraeger <borntraeger at de.ibm.com>
++ */
++
++#include <linux/init.h>
++#include <linux/bootmem.h>
++#include <linux/err.h>
++#include <linux/virtio.h>
++#include <linux/virtio_config.h>
++#include <linux/interrupt.h>
++#include <linux/virtio_ring.h>
++#include <linux/pfn.h>
++#include <asm/io.h>
++#include <asm/kvm_para.h>
++#include <asm/kvm_virtio.h>
++#include <asm/setup.h>
++#include <asm/s390_ext.h>
++
++#define VIRTIO_SUBCODE_64 0x0D00
++
++/*
++ * The pointer to our (page) of device descriptions.
++ */
++static void *kvm_devices;
++
++/*
++ * Unique numbering for kvm devices.
++ */
++static unsigned int dev_index;
++
++struct kvm_device {
++ struct virtio_device vdev;
++ struct kvm_device_desc *desc;
++};
++
++#define to_kvmdev(vd) container_of(vd, struct kvm_device, vdev)
++
++/*
++ * memory layout:
++ * - kvm_device_descriptor
++ * struct kvm_device_desc
++ * - configuration
++ * struct kvm_vqconfig
++ * - feature bits
++ * - config space
++ */
++static struct kvm_vqconfig *kvm_vq_config(const struct kvm_device_desc *desc)
++{
++ return (struct kvm_vqconfig *)(desc + 1);
++}
++
++static u8 *kvm_vq_features(const struct kvm_device_desc *desc)
++{
++ return (u8 *)(kvm_vq_config(desc) + desc->num_vq);
++}
++
++static u8 *kvm_vq_configspace(const struct kvm_device_desc *desc)
++{
++ return kvm_vq_features(desc) + desc->feature_len * 2;
++}
++
++/*
++ * The total size of the config page used by this device (incl. desc)
++ */
++static unsigned desc_size(const struct kvm_device_desc *desc)
++{
++ return sizeof(*desc)
++ + desc->num_vq * sizeof(struct kvm_vqconfig)
++ + desc->feature_len * 2
++ + desc->config_len;
++}
++
++/*
++ * This tests (and acknowleges) a feature bit.
++ */
++static bool kvm_feature(struct virtio_device *vdev, unsigned fbit)
++{
++ struct kvm_device_desc *desc = to_kvmdev(vdev)->desc;
++ u8 *features;
++
++ if (fbit / 8 > desc->feature_len)
++ return false;
++
++ features = kvm_vq_features(desc);
++ if (!(features[fbit / 8] & (1 << (fbit % 8))))
++ return false;
++
++ /*
++ * We set the matching bit in the other half of the bitmap to tell the
++ * Host we want to use this feature.
++ */
++ features[desc->feature_len + fbit / 8] |= (1 << (fbit % 8));
++ return true;
++}
++
++/*
++ * Reading and writing elements in config space
++ */
++static void kvm_get(struct virtio_device *vdev, unsigned int offset,
++ void *buf, unsigned len)
++{
++ struct kvm_device_desc *desc = to_kvmdev(vdev)->desc;
++
++ BUG_ON(offset + len > desc->config_len);
++ memcpy(buf, kvm_vq_configspace(desc) + offset, len);
++}
++
++static void kvm_set(struct virtio_device *vdev, unsigned int offset,
++ const void *buf, unsigned len)
++{
++ struct kvm_device_desc *desc = to_kvmdev(vdev)->desc;
++
++ BUG_ON(offset + len > desc->config_len);
++ memcpy(kvm_vq_configspace(desc) + offset, buf, len);
++}
++
++/*
++ * The operations to get and set the status word just access
++ * the status field of the device descriptor. set_status will also
++ * make a hypercall to the host, to tell about status changes
++ */
++static u8 kvm_get_status(struct virtio_device *vdev)
++{
++ return to_kvmdev(vdev)->desc->status;
++}
++
++static void kvm_set_status(struct virtio_device *vdev, u8 status)
++{
++ BUG_ON(!status);
++ to_kvmdev(vdev)->desc->status = status;
++ kvm_hypercall1(KVM_S390_VIRTIO_SET_STATUS,
++ (unsigned long) to_kvmdev(vdev)->desc);
++}
++
++/*
++ * To reset the device, we use the KVM_VIRTIO_RESET hypercall, using the
++ * descriptor address. The Host will zero the status and all the
++ * features.
++ */
++static void kvm_reset(struct virtio_device *vdev)
++{
++ kvm_hypercall1(KVM_S390_VIRTIO_RESET,
++ (unsigned long) to_kvmdev(vdev)->desc);
++}
++
++/*
++ * When the virtio_ring code wants to notify the Host, it calls us here and we
++ * make a hypercall. We hand the address of the virtqueue so the Host
++ * knows which virtqueue we're talking about.
++ */
++static void kvm_notify(struct virtqueue *vq)
++{
++ struct kvm_vqconfig *config = vq->priv;
++
++ kvm_hypercall1(KVM_S390_VIRTIO_NOTIFY, config->address);
++}
++
++/*
++ * This routine finds the first virtqueue described in the configuration of
++ * this device and sets it up.
++ */
++static struct virtqueue *kvm_find_vq(struct virtio_device *vdev,
++ unsigned index,
++ void (*callback)(struct virtqueue *vq))
++{
++ struct kvm_device *kdev = to_kvmdev(vdev);
++ struct kvm_vqconfig *config;
++ struct virtqueue *vq;
++ int err;
++
++ if (index >= kdev->desc->num_vq)
++ return ERR_PTR(-ENOENT);
++
++ config = kvm_vq_config(kdev->desc)+index;
++
++ err = vmem_add_mapping(config->address,
++ vring_size(config->num, PAGE_SIZE));
++ if (err)
++ goto out;
++
++ vq = vring_new_virtqueue(config->num, vdev, (void *) config->address,
++ kvm_notify, callback);
++ if (!vq) {
++ err = -ENOMEM;
++ goto unmap;
++ }
++
++ /*
++ * register a callback token
++ * The host will sent this via the external interrupt parameter
++ */
++ config->token = (u64) vq;
++
++ vq->priv = config;
++ return vq;
++unmap:
++ vmem_remove_mapping(config->address,
++ vring_size(config->num, PAGE_SIZE));
++out:
++ return ERR_PTR(err);
++}
++
++static void kvm_del_vq(struct virtqueue *vq)
++{
++ struct kvm_vqconfig *config = vq->priv;
++
++ vring_del_virtqueue(vq);
++ vmem_remove_mapping(config->address,
++ vring_size(config->num, PAGE_SIZE));
++}
++
++/*
++ * The config ops structure as defined by virtio config
++ */
++static struct virtio_config_ops kvm_vq_configspace_ops = {
++ .feature = kvm_feature,
++ .get = kvm_get,
++ .set = kvm_set,
++ .get_status = kvm_get_status,
++ .set_status = kvm_set_status,
++ .reset = kvm_reset,
++ .find_vq = kvm_find_vq,
++ .del_vq = kvm_del_vq,
++};
++
++/*
++ * The root device for the kvm virtio devices.
++ * This makes them appear as /sys/devices/kvm_s390/0,1,2 not /sys/devices/0,1,2.
++ */
++static struct device kvm_root = {
++ .parent = NULL,
++ .bus_id = "kvm_s390",
++};
++
++/*
++ * adds a new device and register it with virtio
++ * appropriate drivers are loaded by the device model
++ */
++static void add_kvm_device(struct kvm_device_desc *d)
++{
++ struct kvm_device *kdev;
++
++ kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
++ if (!kdev) {
++ printk(KERN_EMERG "Cannot allocate kvm dev %u\n",
++ dev_index++);
++ return;
++ }
++
++ kdev->vdev.dev.parent = &kvm_root;
++ kdev->vdev.index = dev_index++;
++ kdev->vdev.id.device = d->type;
++ kdev->vdev.config = &kvm_vq_configspace_ops;
++ kdev->desc = d;
++
++ if (register_virtio_device(&kdev->vdev) != 0) {
++ printk(KERN_ERR "Failed to register kvm device %u\n",
++ kdev->vdev.index);
++ kfree(kdev);
++ }
++}
++
++/*
++ * scan_devices() simply iterates through the device page.
++ * The type 0 is reserved to mean "end of devices".
++ */
++static void scan_devices(void)
++{
++ unsigned int i;
++ struct kvm_device_desc *d;
++
++ for (i = 0; i < PAGE_SIZE; i += desc_size(d)) {
++ d = kvm_devices + i;
++
++ if (d->type == 0)
++ break;
++
++ add_kvm_device(d);
++ }
++}
++
++/*
++ * we emulate the request_irq behaviour on top of s390 extints
++ */
++static void kvm_extint_handler(u16 code)
++{
++ void *data = (void *) *(long *) __LC_PFAULT_INTPARM;
++ u16 subcode = S390_lowcore.cpu_addr;
++
++ if ((subcode & 0xff00) != VIRTIO_SUBCODE_64)
++ return;
++
++ vring_interrupt(0, data);
++}
++
++/*
++ * Init function for virtio
++ * devices are in a single page above top of "normal" mem
++ */
++static int __init kvm_devices_init(void)
++{
++ int rc;
++
++ if (!MACHINE_IS_KVM)
++ return -ENODEV;
++
++ rc = device_register(&kvm_root);
++ if (rc) {
++ printk(KERN_ERR "Could not register kvm_s390 root device");
++ return rc;
++ }
++
++ rc = vmem_add_mapping(PFN_PHYS(max_pfn), PAGE_SIZE);
++ if (rc) {
++ device_unregister(&kvm_root);
++ return rc;
++ }
++
++ kvm_devices = (void *) PFN_PHYS(max_pfn);
++
++ ctl_set_bit(0, 9);
++ register_external_interrupt(0x2603, kvm_extint_handler);
++
++ scan_devices();
++ return 0;
++}
++
++/*
++ * We do this after core stuff, but before the drivers.
++ */
++postcore_initcall(kvm_devices_init);
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index eada69d..a7745c8 100644
--- a/drivers/s390/net/Kconfig
@@ -637698,8 +840232,59 @@
-}
-
-#endif
+diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c
+index 76728ae..8e76973 100644
+--- a/drivers/s390/net/cu3088.c
++++ b/drivers/s390/net/cu3088.c
+@@ -62,30 +62,14 @@ static struct device *cu3088_root_dev;
+ static ssize_t
+ group_write(struct device_driver *drv, const char *buf, size_t count)
+ {
+- const char *start, *end;
+- char bus_ids[2][BUS_ID_SIZE], *argv[2];
+- int i;
+ int ret;
+ struct ccwgroup_driver *cdrv;
+
+ cdrv = to_ccwgroupdrv(drv);
+ if (!cdrv)
+ return -EINVAL;
+- start = buf;
+- for (i=0; i<2; 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 + 1);
+- strlcpy (bus_ids[i], start, len);
+- argv[i] = bus_ids[i];
+- start = end + 1;
+- }
+-
+- ret = ccwgroup_create(cu3088_root_dev, cdrv->driver_id,
+- &cu3088_driver, 2, argv);
++ ret = ccwgroup_create_from_string(cu3088_root_dev, cdrv->driver_id,
++ &cu3088_driver, 2, buf);
+
+ return (ret == 0) ? count : ret;
+ }
+diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
+index f51ed99..dd22f4b 100644
+--- a/drivers/s390/net/lcs.c
++++ b/drivers/s390/net/lcs.c
+@@ -1793,7 +1793,8 @@ lcs_get_skb(struct lcs_card *card, char *skb_data, unsigned int skb_len)
+ skb->protocol = card->lan_type_trans(skb, card->dev);
+ card->stats.rx_bytes += skb_len;
+ card->stats.rx_packets++;
+- *((__u32 *)skb->cb) = ++card->pkt_seq;
++ if (skb->protocol == htons(ETH_P_802_2))
++ *((__u32 *)skb->cb) = ++card->pkt_seq;
+ netif_rx(skb);
+ }
+
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
-index 874a199..8f876f6 100644
+index 874a199..e4ba6a0 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)
@@ -637828,7 +840413,16 @@
/**
* Some sanity checks ...
*/
-@@ -1344,7 +1344,7 @@ static struct net_device_stats *netiucv_stats (struct net_device * dev)
+@@ -1313,8 +1313,6 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
+ * and throw away packet.
+ */
+ if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
+- if (!in_atomic())
+- fsm_event(privptr->fsm, DEV_EVENT_START, dev);
+ dev_kfree_skb(skb);
+ privptr->stats.tx_dropped++;
+ privptr->stats.tx_errors++;
+@@ -1344,7 +1342,7 @@ static struct net_device_stats *netiucv_stats (struct net_device * dev)
{
struct netiucv_priv *priv = netdev_priv(dev);
@@ -637837,7 +840431,7 @@
return &priv->stats;
}
-@@ -1360,7 +1360,7 @@ static struct net_device_stats *netiucv_stats (struct net_device * dev)
+@@ -1360,7 +1358,7 @@ static struct net_device_stats *netiucv_stats (struct net_device * dev)
*/
static int netiucv_change_mtu(struct net_device * dev, int new_mtu)
{
@@ -637846,7 +840440,7 @@
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,
+@@ -1378,7 +1376,7 @@ static ssize_t user_show(struct device *dev, struct device_attribute *attr,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -637855,7 +840449,7 @@
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,
+@@ -1393,7 +1391,7 @@ static ssize_t user_write(struct device *dev, struct device_attribute *attr,
int i;
struct iucv_connection *cp;
@@ -637864,7 +840458,7 @@
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,
+@@ -1449,7 +1447,7 @@ static ssize_t buffer_show (struct device *dev, struct device_attribute *attr,
char *buf)
{ struct netiucv_priv *priv = dev->driver_data;
@@ -637873,7 +840467,7 @@
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,
+@@ -1461,7 +1459,7 @@ static ssize_t buffer_write (struct device *dev, struct device_attribute *attr,
char *e;
int bs1;
@@ -637882,7 +840476,7 @@
if (count >= 39)
return -EINVAL;
-@@ -1513,7 +1513,7 @@ static ssize_t dev_fsm_show (struct device *dev, struct device_attribute *attr,
+@@ -1513,7 +1511,7 @@ static ssize_t dev_fsm_show (struct device *dev, struct device_attribute *attr,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -637891,7 +840485,7 @@
return sprintf(buf, "%s\n", fsm_getstate_str(priv->fsm));
}
-@@ -1524,7 +1524,7 @@ static ssize_t conn_fsm_show (struct device *dev,
+@@ -1524,7 +1522,7 @@ static ssize_t conn_fsm_show (struct device *dev,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -637900,7 +840494,7 @@
return sprintf(buf, "%s\n", fsm_getstate_str(priv->conn->fsm));
}
-@@ -1535,7 +1535,7 @@ static ssize_t maxmulti_show (struct device *dev,
+@@ -1535,7 +1533,7 @@ static ssize_t maxmulti_show (struct device *dev,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -637909,7 +840503,7 @@
return sprintf(buf, "%ld\n", priv->conn->prof.maxmulti);
}
-@@ -1545,7 +1545,7 @@ static ssize_t maxmulti_write (struct device *dev,
+@@ -1545,7 +1543,7 @@ static ssize_t maxmulti_write (struct device *dev,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -637918,7 +840512,7 @@
priv->conn->prof.maxmulti = 0;
return count;
}
-@@ -1557,7 +1557,7 @@ static ssize_t maxcq_show (struct device *dev, struct device_attribute *attr,
+@@ -1557,7 +1555,7 @@ static ssize_t maxcq_show (struct device *dev, struct device_attribute *attr,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -637927,7 +840521,7 @@
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,
+@@ -1566,7 +1564,7 @@ static ssize_t maxcq_write (struct device *dev, struct device_attribute *attr,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -637936,7 +840530,7 @@
priv->conn->prof.maxcqueue = 0;
return count;
}
-@@ -1578,7 +1578,7 @@ static ssize_t sdoio_show (struct device *dev, struct device_attribute *attr,
+@@ -1578,7 +1576,7 @@ static ssize_t sdoio_show (struct device *dev, struct device_attribute *attr,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -637945,7 +840539,7 @@
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,
+@@ -1587,7 +1585,7 @@ static ssize_t sdoio_write (struct device *dev, struct device_attribute *attr,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -637954,7 +840548,7 @@
priv->conn->prof.doios_single = 0;
return count;
}
-@@ -1599,7 +1599,7 @@ static ssize_t mdoio_show (struct device *dev, struct device_attribute *attr,
+@@ -1599,7 +1597,7 @@ static ssize_t mdoio_show (struct device *dev, struct device_attribute *attr,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -637963,7 +840557,7 @@
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,
+@@ -1608,7 +1606,7 @@ static ssize_t mdoio_write (struct device *dev, struct device_attribute *attr,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -637972,7 +840566,7 @@
priv->conn->prof.doios_multi = 0;
return count;
}
-@@ -1620,7 +1620,7 @@ static ssize_t txlen_show (struct device *dev, struct device_attribute *attr,
+@@ -1620,7 +1618,7 @@ static ssize_t txlen_show (struct device *dev, struct device_attribute *attr,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -637981,7 +840575,7 @@
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,
+@@ -1629,7 +1627,7 @@ static ssize_t txlen_write (struct device *dev, struct device_attribute *attr,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -637990,7 +840584,7 @@
priv->conn->prof.txlen = 0;
return count;
}
-@@ -1641,7 +1641,7 @@ static ssize_t txtime_show (struct device *dev, struct device_attribute *attr,
+@@ -1641,7 +1639,7 @@ static ssize_t txtime_show (struct device *dev, struct device_attribute *attr,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -637999,7 +840593,7 @@
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,
+@@ -1650,7 +1648,7 @@ static ssize_t txtime_write (struct device *dev, struct device_attribute *attr,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -638008,7 +840602,7 @@
priv->conn->prof.tx_time = 0;
return count;
}
-@@ -1662,7 +1662,7 @@ static ssize_t txpend_show (struct device *dev, struct device_attribute *attr,
+@@ -1662,7 +1660,7 @@ static ssize_t txpend_show (struct device *dev, struct device_attribute *attr,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -638017,7 +840611,7 @@
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,
+@@ -1671,7 +1669,7 @@ static ssize_t txpend_write (struct device *dev, struct device_attribute *attr,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -638026,7 +840620,7 @@
priv->conn->prof.tx_pending = 0;
return count;
}
-@@ -1683,7 +1683,7 @@ static ssize_t txmpnd_show (struct device *dev, struct device_attribute *attr,
+@@ -1683,7 +1681,7 @@ static ssize_t txmpnd_show (struct device *dev, struct device_attribute *attr,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -638035,7 +840629,7 @@
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,
+@@ -1692,7 +1690,7 @@ static ssize_t txmpnd_write (struct device *dev, struct device_attribute *attr,
{
struct netiucv_priv *priv = dev->driver_data;
@@ -638044,7 +840638,7 @@
priv->conn->prof.tx_max_pending = 0;
return count;
}
-@@ -1732,7 +1732,7 @@ static int netiucv_add_files(struct device *dev)
+@@ -1732,7 +1730,7 @@ static int netiucv_add_files(struct device *dev)
{
int ret;
@@ -638053,7 +840647,7 @@
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)
+@@ -1744,7 +1742,7 @@ static int netiucv_add_files(struct device *dev)
static void netiucv_remove_files(struct device *dev)
{
@@ -638062,7 +840656,7 @@
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)
+@@ -1756,7 +1754,7 @@ static int netiucv_register_device(struct net_device *ndev)
int ret;
@@ -638071,7 +840665,7 @@
if (dev) {
snprintf(dev->bus_id, BUS_ID_SIZE, "net%s", ndev->name);
-@@ -1792,7 +1792,7 @@ out_unreg:
+@@ -1792,7 +1790,7 @@ out_unreg:
static void netiucv_unregister_device(struct device *dev)
{
@@ -638080,7 +840674,7 @@
netiucv_remove_files(dev);
device_unregister(dev);
}
-@@ -1857,7 +1857,7 @@ out:
+@@ -1857,7 +1855,7 @@ out:
*/
static void netiucv_remove_connection(struct iucv_connection *conn)
{
@@ -638089,7 +840683,7 @@
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)
+@@ -1881,7 +1879,7 @@ static void netiucv_free_netdevice(struct net_device *dev)
{
struct netiucv_priv *privptr = netdev_priv(dev);
@@ -638098,7 +840692,7 @@
if (!dev)
return;
-@@ -1963,7 +1963,7 @@ static ssize_t conn_write(struct device_driver *drv,
+@@ -1963,7 +1961,7 @@ static ssize_t conn_write(struct device_driver *drv,
struct netiucv_priv *priv;
struct iucv_connection *cp;
@@ -638107,7 +840701,7 @@
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,
+@@ -2048,7 +2046,7 @@ static ssize_t remove_write (struct device_driver *drv,
const char *p;
int i;
@@ -638116,7 +840710,7 @@
if (count >= IFNAMSIZ)
count = IFNAMSIZ - 1;;
-@@ -2116,7 +2116,7 @@ static void __exit netiucv_exit(void)
+@@ -2116,7 +2114,7 @@ static void __exit netiucv_exit(void)
struct netiucv_priv *priv;
struct device *dev;
@@ -638125,16 +840719,15 @@
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)
+@@ -2146,7 +2144,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__);
+ netiucv_driver.groups = netiucv_drv_attr_groups;
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
@@ -639396,10 +841989,10 @@
-#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
+index 0000000..699ac11
--- /dev/null
+++ b/drivers/s390/net/qeth_core.h
-@@ -0,0 +1,905 @@
+@@ -0,0 +1,873 @@
+/*
+ * drivers/s390/net/qeth_core.h
+ *
@@ -639474,22 +842067,7 @@
+ 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);
-+}
++ qeth_dbf_longtext(QETH_DBF_##name, level, text)
+
+/**
+ * some more debug stuff
@@ -640175,27 +842753,6 @@
+ 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) {
@@ -640208,6 +842765,12 @@
+ }
+}
+
++static inline void qeth_put_buffer_pool_entry(struct qeth_card *card,
++ struct qeth_buffer_pool_entry *entry)
++{
++ list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list);
++}
++
+struct qeth_eddp_context;
+extern struct ccwgroup_driver qeth_l2_ccwgroup_driver;
+extern struct ccwgroup_driver qeth_l3_ccwgroup_driver;
@@ -640245,8 +842808,6 @@
+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 *,
@@ -640282,8 +842843,6 @@
+ 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,
@@ -640296,6 +842855,8 @@
+ 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 *);
++void qeth_dbf_longtext(enum qeth_dbf_names dbf_nix, int level, char *text, ...);
++int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *);
+
+/* exports for OSN */
+int qeth_osn_assist(struct net_device *, void *, int);
@@ -640307,10 +842868,10 @@
+#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
+index 0000000..436bf1f
--- /dev/null
+++ b/drivers/s390/net/qeth_core_main.c
-@@ -0,0 +1,4492 @@
+@@ -0,0 +1,4512 @@
+/*
+ * drivers/s390/net/qeth_core_main.c
+ *
@@ -640339,9 +842900,6 @@
+#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 */
@@ -642568,14 +845126,6 @@
+}
+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;
@@ -642916,7 +845466,6 @@
+ 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) :
@@ -643105,8 +845654,6 @@
+ 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 |=
@@ -643350,49 +845897,6 @@
+}
+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)
+{
@@ -643413,8 +845917,8 @@
+}
+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)
++static inline 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;
@@ -643456,15 +845960,13 @@
+ *next_element_to_fill = element;
+}
+
-+static int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
++static inline 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);
@@ -643523,8 +846025,6 @@
+ 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);
@@ -643576,8 +846076,6 @@
+ 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);
@@ -644140,27 +846638,8 @@
+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));
++ return ccwgroup_create_from_string(root_dev, driver_id,
++ &qeth_ccw_driver, 3, buf);
+}
+
+int qeth_core_hardsetup_card(struct qeth_card *card)
@@ -644198,8 +846677,9 @@
+ QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
+ return rc;
+ }
-+
-+ mpno = QETH_MAX_PORTNO;
++ mpno = qdio_get_ssqd_pct(CARD_DDEV(card));
++ if (mpno)
++ mpno = min(mpno - 1, 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);
@@ -644293,7 +846773,6 @@
+ 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))
@@ -644399,6 +846878,18 @@
+ }
+}
+
++void qeth_dbf_longtext(enum qeth_dbf_names dbf_nix, int level, char *text, ...)
++{
++ char dbf_txt_buf[32];
++
++ if (level > (qeth_dbf[dbf_nix].id)->level)
++ return;
++ snprintf(dbf_txt_buf, sizeof(dbf_txt_buf), text);
++ debug_text_event(qeth_dbf[dbf_nix].id, level, dbf_txt_buf);
++
++}
++EXPORT_SYMBOL_GPL(qeth_dbf_longtext);
++
+static int qeth_register_dbf_views(void)
+{
+ int ret;
@@ -644746,6 +847237,96 @@
+}
+EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo);
+
++int qeth_core_ethtool_get_settings(struct net_device *netdev,
++ struct ethtool_cmd *ecmd)
++{
++ struct qeth_card *card = netdev_priv(netdev);
++ enum qeth_link_types link_type;
++
++ if ((card->info.type == QETH_CARD_TYPE_IQD) || (card->info.guestlan))
++ link_type = QETH_LINK_TYPE_10GBIT_ETH;
++ else
++ link_type = card->info.link_type;
++
++ ecmd->transceiver = XCVR_INTERNAL;
++ ecmd->supported = SUPPORTED_Autoneg;
++ ecmd->advertising = ADVERTISED_Autoneg;
++ ecmd->duplex = DUPLEX_FULL;
++ ecmd->autoneg = AUTONEG_ENABLE;
++
++ switch (link_type) {
++ case QETH_LINK_TYPE_FAST_ETH:
++ case QETH_LINK_TYPE_LANE_ETH100:
++ ecmd->supported |= SUPPORTED_10baseT_Half |
++ SUPPORTED_10baseT_Full |
++ SUPPORTED_100baseT_Half |
++ SUPPORTED_100baseT_Full |
++ SUPPORTED_TP;
++ ecmd->advertising |= ADVERTISED_10baseT_Half |
++ ADVERTISED_10baseT_Full |
++ ADVERTISED_100baseT_Half |
++ ADVERTISED_100baseT_Full |
++ ADVERTISED_TP;
++ ecmd->speed = SPEED_100;
++ ecmd->port = PORT_TP;
++ break;
++
++ case QETH_LINK_TYPE_GBIT_ETH:
++ case QETH_LINK_TYPE_LANE_ETH1000:
++ ecmd->supported |= SUPPORTED_10baseT_Half |
++ SUPPORTED_10baseT_Full |
++ SUPPORTED_100baseT_Half |
++ SUPPORTED_100baseT_Full |
++ SUPPORTED_1000baseT_Half |
++ SUPPORTED_1000baseT_Full |
++ SUPPORTED_FIBRE;
++ ecmd->advertising |= ADVERTISED_10baseT_Half |
++ ADVERTISED_10baseT_Full |
++ ADVERTISED_100baseT_Half |
++ ADVERTISED_100baseT_Full |
++ ADVERTISED_1000baseT_Half |
++ ADVERTISED_1000baseT_Full |
++ ADVERTISED_FIBRE;
++ ecmd->speed = SPEED_1000;
++ ecmd->port = PORT_FIBRE;
++ break;
++
++ case QETH_LINK_TYPE_10GBIT_ETH:
++ ecmd->supported |= SUPPORTED_10baseT_Half |
++ SUPPORTED_10baseT_Full |
++ SUPPORTED_100baseT_Half |
++ SUPPORTED_100baseT_Full |
++ SUPPORTED_1000baseT_Half |
++ SUPPORTED_1000baseT_Full |
++ SUPPORTED_10000baseT_Full |
++ SUPPORTED_FIBRE;
++ ecmd->advertising |= ADVERTISED_10baseT_Half |
++ ADVERTISED_10baseT_Full |
++ ADVERTISED_100baseT_Half |
++ ADVERTISED_100baseT_Full |
++ ADVERTISED_1000baseT_Half |
++ ADVERTISED_1000baseT_Full |
++ ADVERTISED_10000baseT_Full |
++ ADVERTISED_FIBRE;
++ ecmd->speed = SPEED_10000;
++ ecmd->port = PORT_FIBRE;
++ break;
++
++ default:
++ ecmd->supported |= SUPPORTED_10baseT_Half |
++ SUPPORTED_10baseT_Full |
++ SUPPORTED_TP;
++ ecmd->advertising |= ADVERTISED_10baseT_Half |
++ ADVERTISED_10baseT_Full |
++ ADVERTISED_TP;
++ ecmd->speed = SPEED_10;
++ ecmd->port = PORT_TP;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(qeth_core_ethtool_get_settings);
++
+static int __init qeth_core_init(void)
+{
+ int rc;
@@ -647999,10 +850580,10 @@
-#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
+index 0000000..86ec50d
--- /dev/null
+++ b/drivers/s390/net/qeth_l2_main.c
-@@ -0,0 +1,1234 @@
+@@ -0,0 +1,1248 @@
+/*
+ * drivers/s390/net/qeth_l2_main.c
+ *
@@ -648027,9 +850608,6 @@
+#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 *);
@@ -648640,8 +851218,6 @@
+ 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;
@@ -648663,9 +851239,12 @@
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ hdr = (struct qeth_hdr *)skb->data;
+ else {
-+ new_skb = qeth_prepare_skb(card, skb, &hdr);
++ /* create a clone with writeable headroom */
++ new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr));
+ if (!new_skb)
+ goto tx_drop;
++ hdr = (struct qeth_hdr *)skb_push(new_skb,
++ sizeof(struct qeth_hdr));
+ qeth_l2_fill_header(card, hdr, new_skb, ipv, cast_type);
+ }
+
@@ -648752,7 +851331,6 @@
+ 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) {
@@ -648857,6 +851435,22 @@
+ return;
+}
+
++static int qeth_l2_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) {
++ card->options.large_send = QETH_LARGE_SEND_EDDP;
++ 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_l2_ethtool_ops = {
+ .get_link = ethtool_op_get_link,
+ .get_tx_csum = ethtool_op_get_tx_csum,
@@ -648864,11 +851458,12 @@
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+ .get_tso = ethtool_op_get_tso,
-+ .set_tso = ethtool_op_set_tso,
++ .set_tso = qeth_l2_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,
++ .get_settings = qeth_core_ethtool_get_settings,
+};
+
+static struct ethtool_ops qeth_l2_osn_ops = {
@@ -649239,10 +851834,10 @@
+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
+index 0000000..9f143c8
--- /dev/null
+++ b/drivers/s390/net/qeth_l3.h
-@@ -0,0 +1,67 @@
+@@ -0,0 +1,64 @@
+/*
+ * drivers/s390/net/qeth_l3.h
+ *
@@ -649258,9 +851853,6 @@
+
+#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;
@@ -649312,10 +851904,10 @@
+#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
+index 0000000..94a8ead
--- /dev/null
+++ b/drivers/s390/net/qeth_l3_main.c
-@@ -0,0 +1,3396 @@
+@@ -0,0 +1,3402 @@
+/*
+ * drivers/s390/net/qeth_l3_main.c
+ *
@@ -649346,8 +851938,6 @@
+#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 *);
@@ -651411,6 +854001,11 @@
+ (card->state == CARD_STATE_UP)) {
+ if (recovery_mode)
+ qeth_l3_stop(card->dev);
++ else {
++ rtnl_lock();
++ dev_close(card->dev);
++ rtnl_unlock();
++ }
+ if (!card->use_hard_stop) {
+ rc = qeth_send_stoplan(card);
+ if (rc)
@@ -651877,8 +854472,6 @@
+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;
@@ -651888,9 +854481,10 @@
+ * 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;
++ if ((ipv == 4) || (card->info.type == QETH_CARD_TYPE_IQD))
++ hdr->hdr.l3.ext_flags = QETH_HDR_EXT_VLAN_FRAME;
++ else
++ hdr->hdr.l3.ext_flags = QETH_HDR_EXT_INCLUDE_VLAN_TAG;
+ hdr->hdr.l3.vlan_id = vlan_tx_tag_get(skb);
+ }
+
@@ -651956,8 +854550,6 @@
+ 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)))
@@ -652208,6 +854800,7 @@
+ .get_ethtool_stats = qeth_core_get_ethtool_stats,
+ .get_stats_count = qeth_core_get_stats_count,
+ .get_drvinfo = qeth_core_get_drvinfo,
++ .get_settings = qeth_core_ethtool_get_settings,
+};
+
+/*
@@ -652300,7 +854893,6 @@
+ 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) {
@@ -652458,9 +855050,15 @@
+ netif_carrier_on(card->dev);
+
+ qeth_set_allowed_threads(card, 0xffffffff, 0);
-+ if ((recover_flag == CARD_STATE_RECOVER) && recovery_mode) {
++ if (recover_flag == CARD_STATE_RECOVER) {
++ if (recovery_mode)
+ qeth_l3_open(card->dev);
-+ qeth_l3_set_multicast_list(card->dev);
++ else {
++ rtnl_lock();
++ dev_open(card->dev);
++ rtnl_unlock();
++ }
++ qeth_l3_set_multicast_list(card->dev);
+ }
+ /* let user_space know that device is online */
+ kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
@@ -653776,55974 +856374,79905 @@
+++ /dev/null
@@ -1,8956 +0,0 @@
-/*
-- * linux/drivers/s390/net/qeth_main.c
-- *
-- * Linux on zSeries OSA Express and HiperSockets support
-- *
-- * Copyright 2000,2003 IBM Corporation
-- *
-- * Author(s): Original Code written by
-- * Utz Bacher (utz.bacher at de.ibm.com)
-- * Rewritten by
-- * Frank Pavlic (fpavlic at de.ibm.com) and
-- * Thomas Spatzier <tspat at de.ibm.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2, or (at your option)
-- * any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- * linux/drivers/s390/net/qeth_main.c
+- *
+- * Linux on zSeries OSA Express and HiperSockets support
+- *
+- * Copyright 2000,2003 IBM Corporation
+- *
+- * Author(s): Original Code written by
+- * Utz Bacher (utz.bacher at de.ibm.com)
+- * Rewritten by
+- * Frank Pavlic (fpavlic at de.ibm.com) and
+- * Thomas Spatzier <tspat at de.ibm.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-
+-#include <linux/module.h>
+-#include <linux/moduleparam.h>
+-#include <linux/string.h>
+-#include <linux/errno.h>
+-#include <linux/mm.h>
+-#include <linux/ip.h>
+-#include <linux/inetdevice.h>
+-#include <linux/netdevice.h>
+-#include <linux/sched.h>
+-#include <linux/workqueue.h>
+-#include <linux/kernel.h>
+-#include <linux/slab.h>
+-#include <linux/interrupt.h>
+-#include <linux/tcp.h>
+-#include <linux/icmp.h>
+-#include <linux/skbuff.h>
+-#include <linux/in.h>
+-#include <linux/igmp.h>
+-#include <linux/init.h>
+-#include <linux/reboot.h>
+-#include <linux/mii.h>
+-#include <linux/rcupdate.h>
+-#include <linux/ethtool.h>
+-
+-#include <net/arp.h>
+-#include <net/ip.h>
+-#include <net/route.h>
+-
+-#include <asm/ebcdic.h>
+-#include <asm/io.h>
+-#include <asm/qeth.h>
+-#include <asm/timex.h>
+-#include <asm/semaphore.h>
+-#include <asm/uaccess.h>
+-#include <asm/s390_rdev.h>
+-
+-#include "qeth.h"
+-#include "qeth_mpc.h"
+-#include "qeth_fs.h"
+-#include "qeth_eddp.h"
+-#include "qeth_tso.h"
+-
+-static const char *version = "qeth S/390 OSA-Express driver";
+-
+-/**
+- * Debug Facility Stuff
+- */
+-static debug_info_t *qeth_dbf_setup = NULL;
+-static debug_info_t *qeth_dbf_data = NULL;
+-static debug_info_t *qeth_dbf_misc = NULL;
+-static debug_info_t *qeth_dbf_control = NULL;
+-debug_info_t *qeth_dbf_trace = NULL;
+-static debug_info_t *qeth_dbf_sense = NULL;
+-static debug_info_t *qeth_dbf_qerr = NULL;
+-
+-DEFINE_PER_CPU(char[256], qeth_dbf_txt_buf);
+-
+-static struct lock_class_key qdio_out_skb_queue_key;
+-
+-/**
+- * some more definitions and declarations
+- */
+-static unsigned int known_devices[][10] = QETH_MODELLIST_ARRAY;
+-
+-/* list of our cards */
+-struct qeth_card_list_struct qeth_card_list;
+-/*process list want to be notified*/
+-spinlock_t qeth_notify_lock;
+-struct list_head qeth_notify_list;
+-
+-static void qeth_send_control_data_cb(struct qeth_channel *,
+- struct qeth_cmd_buffer *);
+-
+-/**
+- * here we go with function implementation
+- */
+-static void
+-qeth_init_qdio_info(struct qeth_card *card);
+-
+-static int
+-qeth_init_qdio_queues(struct qeth_card *card);
+-
+-static int
+-qeth_alloc_qdio_buffers(struct qeth_card *card);
+-
+-static void
+-qeth_free_qdio_buffers(struct qeth_card *);
+-
+-static void
+-qeth_clear_qdio_buffers(struct qeth_card *);
+-
+-static void
+-qeth_clear_ip_list(struct qeth_card *, int, int);
+-
+-static void
+-qeth_clear_ipacmd_list(struct qeth_card *);
+-
+-static int
+-qeth_qdio_clear_card(struct qeth_card *, int);
+-
+-static void
+-qeth_clear_working_pool_list(struct qeth_card *);
+-
+-static void
+-qeth_clear_cmd_buffers(struct qeth_channel *);
+-
+-static int
+-qeth_stop(struct net_device *);
+-
+-static void
+-qeth_clear_ipato_list(struct qeth_card *);
+-
+-static int
+-qeth_is_addr_covered_by_ipato(struct qeth_card *, struct qeth_ipaddr *);
+-
+-static void
+-qeth_irq_tasklet(unsigned long);
+-
+-static int
+-qeth_set_online(struct ccwgroup_device *);
+-
+-static int
+-__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode);
+-
+-static struct qeth_ipaddr *
+-qeth_get_addr_buffer(enum qeth_prot_versions);
+-
+-static void
+-qeth_set_multicast_list(struct net_device *);
+-
+-static void
+-qeth_setadp_promisc_mode(struct qeth_card *);
+-
+-static int
+-qeth_hard_header_parse(const struct sk_buff *skb, unsigned char *haddr);
+-
+-static void
+-qeth_notify_processes(void)
+-{
+- /*notify all registered processes */
+- struct qeth_notify_list_struct *n_entry;
+-
+- QETH_DBF_TEXT(trace,3,"procnoti");
+- spin_lock(&qeth_notify_lock);
+- list_for_each_entry(n_entry, &qeth_notify_list, list) {
+- send_sig(n_entry->signum, n_entry->task, 1);
+- }
+- spin_unlock(&qeth_notify_lock);
+-
+-}
+-int
+-qeth_notifier_unregister(struct task_struct *p)
+-{
+- struct qeth_notify_list_struct *n_entry, *tmp;
+-
+- QETH_DBF_TEXT(trace, 2, "notunreg");
+- spin_lock(&qeth_notify_lock);
+- list_for_each_entry_safe(n_entry, tmp, &qeth_notify_list, list) {
+- if (n_entry->task == p) {
+- list_del(&n_entry->list);
+- kfree(n_entry);
+- goto out;
+- }
+- }
+-out:
+- spin_unlock(&qeth_notify_lock);
+- return 0;
+-}
+-int
+-qeth_notifier_register(struct task_struct *p, int signum)
+-{
+- struct qeth_notify_list_struct *n_entry;
+-
+- /*check first if entry already exists*/
+- spin_lock(&qeth_notify_lock);
+- list_for_each_entry(n_entry, &qeth_notify_list, list) {
+- if (n_entry->task == p) {
+- n_entry->signum = signum;
+- spin_unlock(&qeth_notify_lock);
+- return 0;
+- }
+- }
+- spin_unlock(&qeth_notify_lock);
+-
+- n_entry = (struct qeth_notify_list_struct *)
+- kmalloc(sizeof(struct qeth_notify_list_struct),GFP_KERNEL);
+- if (!n_entry)
+- return -ENOMEM;
+- n_entry->task = p;
+- n_entry->signum = signum;
+- spin_lock(&qeth_notify_lock);
+- list_add(&n_entry->list,&qeth_notify_list);
+- spin_unlock(&qeth_notify_lock);
+- return 0;
+-}
+-
+-
+-/**
+- * free channel command buffers
+- */
+-static void
+-qeth_clean_channel(struct qeth_channel *channel)
+-{
+- int cnt;
+-
+- QETH_DBF_TEXT(setup, 2, "freech");
+- for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
+- kfree(channel->iob[cnt].data);
+-}
+-
+-/**
+- * free card
+- */
+-static void
+-qeth_free_card(struct qeth_card *card)
+-{
+-
+- QETH_DBF_TEXT(setup, 2, "freecrd");
+- QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+- qeth_clean_channel(&card->read);
+- qeth_clean_channel(&card->write);
+- if (card->dev)
+- free_netdev(card->dev);
+- qeth_clear_ip_list(card, 0, 0);
+- qeth_clear_ipato_list(card);
+- kfree(card->ip_tbd_list);
+- qeth_free_qdio_buffers(card);
+- kfree(card);
+-}
+-
+-/**
+- * alloc memory for command buffer per channel
+- */
+-static int
+-qeth_setup_channel(struct qeth_channel *channel)
+-{
+- int cnt;
+-
+- QETH_DBF_TEXT(setup, 2, "setupch");
+- for (cnt=0; cnt < QETH_CMD_BUFFER_NO; cnt++) {
+- channel->iob[cnt].data = (char *)
+- kmalloc(QETH_BUFSIZE, GFP_DMA|GFP_KERNEL);
+- if (channel->iob[cnt].data == NULL)
+- break;
+- channel->iob[cnt].state = BUF_STATE_FREE;
+- channel->iob[cnt].channel = channel;
+- channel->iob[cnt].callback = qeth_send_control_data_cb;
+- channel->iob[cnt].rc = 0;
+- }
+- if (cnt < QETH_CMD_BUFFER_NO) {
+- while (cnt-- > 0)
+- kfree(channel->iob[cnt].data);
+- return -ENOMEM;
+- }
+- channel->buf_no = 0;
+- channel->io_buf_no = 0;
+- atomic_set(&channel->irq_pending, 0);
+- spin_lock_init(&channel->iob_lock);
+-
+- init_waitqueue_head(&channel->wait_q);
+- channel->irq_tasklet.data = (unsigned long) channel;
+- channel->irq_tasklet.func = qeth_irq_tasklet;
+- return 0;
+-}
+-
+-/**
+- * alloc memory for card structure
+- */
+-static struct qeth_card *
+-qeth_alloc_card(void)
+-{
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT(setup, 2, "alloccrd");
+- card = kzalloc(sizeof(struct qeth_card), GFP_DMA|GFP_KERNEL);
+- if (!card)
+- return NULL;
+- QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+- if (qeth_setup_channel(&card->read)) {
+- kfree(card);
+- return NULL;
+- }
+- if (qeth_setup_channel(&card->write)) {
+- qeth_clean_channel(&card->read);
+- kfree(card);
+- return NULL;
+- }
+- return card;
+-}
+-
+-static long
+-__qeth_check_irb_error(struct ccw_device *cdev, unsigned long intparm,
+- struct irb *irb)
+-{
+- if (!IS_ERR(irb))
+- return 0;
+-
+- switch (PTR_ERR(irb)) {
+- case -EIO:
+- PRINT_WARN("i/o-error on device %s\n", cdev->dev.bus_id);
+- QETH_DBF_TEXT(trace, 2, "ckirberr");
+- QETH_DBF_TEXT_(trace, 2, " rc%d", -EIO);
+- break;
+- case -ETIMEDOUT:
+- PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id);
+- QETH_DBF_TEXT(trace, 2, "ckirberr");
+- QETH_DBF_TEXT_(trace, 2, " rc%d", -ETIMEDOUT);
+- if (intparm == QETH_RCD_PARM) {
+- struct qeth_card *card = CARD_FROM_CDEV(cdev);
+-
+- if (card && (card->data.ccwdev == cdev)) {
+- card->data.state = CH_STATE_DOWN;
+- wake_up(&card->wait_q);
+- }
+- }
+- break;
+- default:
+- PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb),
+- cdev->dev.bus_id);
+- QETH_DBF_TEXT(trace, 2, "ckirberr");
+- QETH_DBF_TEXT(trace, 2, " rc???");
+- }
+- return PTR_ERR(irb);
+-}
+-
+-static int
+-qeth_get_problem(struct ccw_device *cdev, struct irb *irb)
+-{
+- int dstat,cstat;
+- char *sense;
+-
+- sense = (char *) irb->ecw;
+- cstat = irb->scsw.cstat;
+- dstat = irb->scsw.dstat;
+-
+- if (cstat & (SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK |
+- SCHN_STAT_CHN_DATA_CHK | SCHN_STAT_CHAIN_CHECK |
+- SCHN_STAT_PROT_CHECK | SCHN_STAT_PROG_CHECK)) {
+- QETH_DBF_TEXT(trace,2, "CGENCHK");
+- PRINT_WARN("check on device %s, dstat=x%x, cstat=x%x ",
+- cdev->dev.bus_id, dstat, cstat);
+- HEXDUMP16(WARN, "irb: ", irb);
+- HEXDUMP16(WARN, "irb: ", ((char *) irb) + 32);
+- return 1;
+- }
+-
+- if (dstat & DEV_STAT_UNIT_CHECK) {
+- if (sense[SENSE_RESETTING_EVENT_BYTE] &
+- SENSE_RESETTING_EVENT_FLAG) {
+- QETH_DBF_TEXT(trace,2,"REVIND");
+- return 1;
+- }
+- if (sense[SENSE_COMMAND_REJECT_BYTE] &
+- SENSE_COMMAND_REJECT_FLAG) {
+- QETH_DBF_TEXT(trace,2,"CMDREJi");
+- return 0;
+- }
+- if ((sense[2] == 0xaf) && (sense[3] == 0xfe)) {
+- QETH_DBF_TEXT(trace,2,"AFFE");
+- return 1;
+- }
+- if ((!sense[0]) && (!sense[1]) && (!sense[2]) && (!sense[3])) {
+- QETH_DBF_TEXT(trace,2,"ZEROSEN");
+- return 0;
+- }
+- QETH_DBF_TEXT(trace,2,"DGENCHK");
+- return 1;
+- }
+- return 0;
+-}
+-static int qeth_issue_next_read(struct qeth_card *);
+-
+-/**
+- * interrupt handler
+- */
+-static void
+-qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
+-{
+- int rc;
+- int cstat,dstat;
+- struct qeth_cmd_buffer *buffer;
+- struct qeth_channel *channel;
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT(trace,5,"irq");
+-
+- if (__qeth_check_irb_error(cdev, intparm, irb))
+- return;
+- cstat = irb->scsw.cstat;
+- dstat = irb->scsw.dstat;
+-
+- card = CARD_FROM_CDEV(cdev);
+- if (!card)
+- return;
+-
+- if (card->read.ccwdev == cdev){
+- channel = &card->read;
+- QETH_DBF_TEXT(trace,5,"read");
+- } else if (card->write.ccwdev == cdev) {
+- channel = &card->write;
+- QETH_DBF_TEXT(trace,5,"write");
+- } else {
+- channel = &card->data;
+- QETH_DBF_TEXT(trace,5,"data");
+- }
+- atomic_set(&channel->irq_pending, 0);
+-
+- if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC))
+- channel->state = CH_STATE_STOPPED;
+-
+- if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC))
+- channel->state = CH_STATE_HALTED;
+-
+- /*let's wake up immediately on data channel*/
+- if ((channel == &card->data) && (intparm != 0) &&
+- (intparm != QETH_RCD_PARM))
+- goto out;
+-
+- if (intparm == QETH_CLEAR_CHANNEL_PARM) {
+- QETH_DBF_TEXT(trace, 6, "clrchpar");
+- /* we don't have to handle this further */
+- intparm = 0;
+- }
+- if (intparm == QETH_HALT_CHANNEL_PARM) {
+- QETH_DBF_TEXT(trace, 6, "hltchpar");
+- /* we don't have to handle this further */
+- intparm = 0;
+- }
+- if ((dstat & DEV_STAT_UNIT_EXCEP) ||
+- (dstat & DEV_STAT_UNIT_CHECK) ||
+- (cstat)) {
+- if (irb->esw.esw0.erw.cons) {
+- /* TODO: we should make this s390dbf */
+- PRINT_WARN("sense data available on channel %s.\n",
+- CHANNEL_ID(channel));
+- PRINT_WARN(" cstat 0x%X\n dstat 0x%X\n", cstat, dstat);
+- HEXDUMP16(WARN,"irb: ",irb);
+- HEXDUMP16(WARN,"sense data: ",irb->ecw);
+- }
+- if (intparm == QETH_RCD_PARM) {
+- channel->state = CH_STATE_DOWN;
+- goto out;
+- }
+- rc = qeth_get_problem(cdev,irb);
+- if (rc) {
+- qeth_schedule_recovery(card);
+- goto out;
+- }
+- }
+-
+- if (intparm == QETH_RCD_PARM) {
+- channel->state = CH_STATE_RCD_DONE;
+- goto out;
+- }
+- if (intparm) {
+- buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
+- buffer->state = BUF_STATE_PROCESSED;
+- }
+- if (channel == &card->data)
+- return;
+-
+- if (channel == &card->read &&
+- channel->state == CH_STATE_UP)
+- qeth_issue_next_read(card);
+-
+- qeth_irq_tasklet((unsigned long)channel);
+- return;
+-out:
+- wake_up(&card->wait_q);
+-}
+-
+-/**
+- * tasklet function scheduled from irq handler
+- */
+-static void
+-qeth_irq_tasklet(unsigned long data)
+-{
+- struct qeth_card *card;
+- struct qeth_channel *channel;
+- struct qeth_cmd_buffer *iob;
+- __u8 index;
+-
+- QETH_DBF_TEXT(trace,5,"irqtlet");
+- channel = (struct qeth_channel *) data;
+- iob = channel->iob;
+- index = channel->buf_no;
+- card = CARD_FROM_CDEV(channel->ccwdev);
+- while (iob[index].state == BUF_STATE_PROCESSED) {
+- if (iob[index].callback !=NULL) {
+- iob[index].callback(channel,iob + index);
+- }
+- index = (index + 1) % QETH_CMD_BUFFER_NO;
+- }
+- channel->buf_no = index;
+- wake_up(&card->wait_q);
+-}
+-
+-static int qeth_stop_card(struct qeth_card *, int);
+-
+-static int
+-__qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode)
+-{
+- struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data;
+- int rc = 0, rc2 = 0, rc3 = 0;
+- enum qeth_card_states recover_flag;
+-
+- QETH_DBF_TEXT(setup, 3, "setoffl");
+- QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
+-
+- if (card->dev && netif_carrier_ok(card->dev))
+- netif_carrier_off(card->dev);
+- recover_flag = card->state;
+- if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){
+- PRINT_WARN("Stopping card %s interrupted by user!\n",
+- CARD_BUS_ID(card));
+- return -ERESTARTSYS;
+- }
+- rc = ccw_device_set_offline(CARD_DDEV(card));
+- rc2 = ccw_device_set_offline(CARD_WDEV(card));
+- rc3 = ccw_device_set_offline(CARD_RDEV(card));
+- if (!rc)
+- rc = (rc2) ? rc2 : rc3;
+- if (rc)
+- QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+- if (recover_flag == CARD_STATE_UP)
+- card->state = CARD_STATE_RECOVER;
+- qeth_notify_processes();
+- return 0;
+-}
+-
+-static int
+-qeth_set_offline(struct ccwgroup_device *cgdev)
+-{
+- return __qeth_set_offline(cgdev, 0);
+-}
+-
+-static int
+-qeth_threads_running(struct qeth_card *card, unsigned long threads);
+-
+-
+-static void
+-qeth_remove_device(struct ccwgroup_device *cgdev)
+-{
+- struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data;
+- unsigned long flags;
+-
+- QETH_DBF_TEXT(setup, 3, "rmdev");
+- QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
+-
+- if (!card)
+- return;
+-
+- wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
+-
+- if (cgdev->state == CCWGROUP_ONLINE){
+- card->use_hard_stop = 1;
+- qeth_set_offline(cgdev);
+- }
+- /* remove form our internal list */
+- write_lock_irqsave(&qeth_card_list.rwlock, flags);
+- list_del(&card->list);
+- write_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+- if (card->dev)
+- unregister_netdev(card->dev);
+- qeth_remove_device_attributes(&cgdev->dev);
+- qeth_free_card(card);
+- cgdev->dev.driver_data = NULL;
+- put_device(&cgdev->dev);
+-}
+-
+-static int
+-qeth_register_addr_entry(struct qeth_card *, struct qeth_ipaddr *);
+-static int
+-qeth_deregister_addr_entry(struct qeth_card *, struct qeth_ipaddr *);
+-
+-/**
+- * Add/remove address to/from card's ip list, i.e. try to add or remove
+- * reference to/from an IP address that is already registered on the card.
+- * Returns:
+- * 0 address was on card and its reference count has been adjusted,
+- * but is still > 0, so nothing has to be done
+- * also returns 0 if card was not on card and the todo was to delete
+- * the address -> there is also nothing to be done
+- * 1 address was not on card and the todo is to add it to the card's ip
+- * list
+- * -1 address was on card and its reference count has been decremented
+- * to <= 0 by the todo -> address must be removed from card
+- */
+-static int
+-__qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,
+- struct qeth_ipaddr **__addr)
+-{
+- struct qeth_ipaddr *addr;
+- int found = 0;
+-
+- list_for_each_entry(addr, &card->ip_list, entry) {
+- if (card->options.layer2) {
+- if ((addr->type == todo->type) &&
+- (memcmp(&addr->mac, &todo->mac,
+- OSA_ADDR_LEN) == 0)) {
+- found = 1;
+- break;
+- }
+- continue;
+- }
+- if ((addr->proto == QETH_PROT_IPV4) &&
+- (todo->proto == QETH_PROT_IPV4) &&
+- (addr->type == todo->type) &&
+- (addr->u.a4.addr == todo->u.a4.addr) &&
+- (addr->u.a4.mask == todo->u.a4.mask)) {
+- found = 1;
+- break;
+- }
+- if ((addr->proto == QETH_PROT_IPV6) &&
+- (todo->proto == QETH_PROT_IPV6) &&
+- (addr->type == todo->type) &&
+- (addr->u.a6.pfxlen == todo->u.a6.pfxlen) &&
+- (memcmp(&addr->u.a6.addr, &todo->u.a6.addr,
+- sizeof(struct in6_addr)) == 0)) {
+- found = 1;
+- break;
+- }
+- }
+- if (found) {
+- addr->users += todo->users;
+- if (addr->users <= 0){
+- *__addr = addr;
+- return -1;
+- } else {
+- /* for VIPA and RXIP limit refcount to 1 */
+- if (addr->type != QETH_IP_TYPE_NORMAL)
+- addr->users = 1;
+- return 0;
+- }
+- }
+- if (todo->users > 0) {
+- /* for VIPA and RXIP limit refcount to 1 */
+- if (todo->type != QETH_IP_TYPE_NORMAL)
+- todo->users = 1;
+- return 1;
+- } else
+- return 0;
+-}
+-
+-static int
+-__qeth_address_exists_in_list(struct list_head *list, struct qeth_ipaddr *addr,
+- int same_type)
+-{
+- struct qeth_ipaddr *tmp;
+-
+- list_for_each_entry(tmp, list, entry) {
+- if ((tmp->proto == QETH_PROT_IPV4) &&
+- (addr->proto == QETH_PROT_IPV4) &&
+- ((same_type && (tmp->type == addr->type)) ||
+- (!same_type && (tmp->type != addr->type)) ) &&
+- (tmp->u.a4.addr == addr->u.a4.addr) ){
+- return 1;
+- }
+- if ((tmp->proto == QETH_PROT_IPV6) &&
+- (addr->proto == QETH_PROT_IPV6) &&
+- ((same_type && (tmp->type == addr->type)) ||
+- (!same_type && (tmp->type != addr->type)) ) &&
+- (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
+- sizeof(struct in6_addr)) == 0) ) {
+- return 1;
+- }
+- }
+- return 0;
+-}
+-
+-/*
+- * Add IP to be added to todo list. If there is already an "add todo"
+- * in this list we just incremenent the reference count.
+- * Returns 0 if we just incremented reference count.
+- */
+-static int
+-__qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add)
+-{
+- struct qeth_ipaddr *tmp, *t;
+- int found = 0;
+-
+- list_for_each_entry_safe(tmp, t, card->ip_tbd_list, entry) {
+- if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) &&
+- (tmp->type == QETH_IP_TYPE_DEL_ALL_MC))
+- return 0;
+- if (card->options.layer2) {
+- if ((tmp->type == addr->type) &&
+- (tmp->is_multicast == addr->is_multicast) &&
+- (memcmp(&tmp->mac, &addr->mac,
+- OSA_ADDR_LEN) == 0)) {
+- found = 1;
+- break;
+- }
+- continue;
+- }
+- if ((tmp->proto == QETH_PROT_IPV4) &&
+- (addr->proto == QETH_PROT_IPV4) &&
+- (tmp->type == addr->type) &&
+- (tmp->is_multicast == addr->is_multicast) &&
+- (tmp->u.a4.addr == addr->u.a4.addr) &&
+- (tmp->u.a4.mask == addr->u.a4.mask)) {
+- found = 1;
+- break;
+- }
+- if ((tmp->proto == QETH_PROT_IPV6) &&
+- (addr->proto == QETH_PROT_IPV6) &&
+- (tmp->type == addr->type) &&
+- (tmp->is_multicast == addr->is_multicast) &&
+- (tmp->u.a6.pfxlen == addr->u.a6.pfxlen) &&
+- (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
+- sizeof(struct in6_addr)) == 0)) {
+- found = 1;
+- break;
+- }
+- }
+- if (found){
+- if (addr->users != 0)
+- tmp->users += addr->users;
+- else
+- tmp->users += add? 1:-1;
+- if (tmp->users == 0) {
+- list_del(&tmp->entry);
+- kfree(tmp);
+- }
+- return 0;
+- } else {
+- if (addr->type == QETH_IP_TYPE_DEL_ALL_MC)
+- list_add(&addr->entry, card->ip_tbd_list);
+- else {
+- if (addr->users == 0)
+- addr->users += add? 1:-1;
+- if (add && (addr->type == QETH_IP_TYPE_NORMAL) &&
+- qeth_is_addr_covered_by_ipato(card, addr)){
+- QETH_DBF_TEXT(trace, 2, "tkovaddr");
+- addr->set_flags |= QETH_IPA_SETIP_TAKEOVER_FLAG;
+- }
+- list_add_tail(&addr->entry, card->ip_tbd_list);
+- }
+- return 1;
+- }
+-}
+-
+-/**
+- * Remove IP address from list
+- */
+-static int
+-qeth_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
+-{
+- unsigned long flags;
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace, 4, "delip");
+-
+- if (card->options.layer2)
+- QETH_DBF_HEX(trace, 4, &addr->mac, 6);
+- else if (addr->proto == QETH_PROT_IPV4)
+- QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
+- else {
+- QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
+- QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
+- }
+- spin_lock_irqsave(&card->ip_lock, flags);
+- rc = __qeth_insert_ip_todo(card, addr, 0);
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- return rc;
+-}
+-
+-static int
+-qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
+-{
+- unsigned long flags;
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace, 4, "addip");
+- if (card->options.layer2)
+- QETH_DBF_HEX(trace, 4, &addr->mac, 6);
+- else if (addr->proto == QETH_PROT_IPV4)
+- QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
+- else {
+- QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
+- QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
+- }
+- spin_lock_irqsave(&card->ip_lock, flags);
+- rc = __qeth_insert_ip_todo(card, addr, 1);
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- return rc;
+-}
+-
+-static void
+-__qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags)
+-{
+- struct qeth_ipaddr *addr, *tmp;
+- int rc;
+-again:
+- list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) {
+- if (addr->is_multicast) {
+- list_del(&addr->entry);
+- spin_unlock_irqrestore(&card->ip_lock, *flags);
+- rc = qeth_deregister_addr_entry(card, addr);
+- spin_lock_irqsave(&card->ip_lock, *flags);
+- if (!rc) {
+- kfree(addr);
+- goto again;
+- } else
+- list_add(&addr->entry, &card->ip_list);
+- }
+- }
+-}
+-
+-static void
+-qeth_set_ip_addr_list(struct qeth_card *card)
+-{
+- struct list_head *tbd_list;
+- struct qeth_ipaddr *todo, *addr;
+- unsigned long flags;
+- int rc;
+-
+- QETH_DBF_TEXT(trace, 2, "sdiplist");
+- QETH_DBF_HEX(trace, 2, &card, sizeof(void *));
+-
+- spin_lock_irqsave(&card->ip_lock, flags);
+- tbd_list = card->ip_tbd_list;
+- card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC);
+- if (!card->ip_tbd_list) {
+- QETH_DBF_TEXT(trace, 0, "silnomem");
+- card->ip_tbd_list = tbd_list;
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- return;
+- } else
+- INIT_LIST_HEAD(card->ip_tbd_list);
+-
+- while (!list_empty(tbd_list)){
+- todo = list_entry(tbd_list->next, struct qeth_ipaddr, entry);
+- list_del(&todo->entry);
+- if (todo->type == QETH_IP_TYPE_DEL_ALL_MC){
+- __qeth_delete_all_mc(card, &flags);
+- kfree(todo);
+- continue;
+- }
+- rc = __qeth_ref_ip_on_card(card, todo, &addr);
+- if (rc == 0) {
+- /* nothing to be done; only adjusted refcount */
+- kfree(todo);
+- } else if (rc == 1) {
+- /* new entry to be added to on-card list */
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- rc = qeth_register_addr_entry(card, todo);
+- spin_lock_irqsave(&card->ip_lock, flags);
+- if (!rc)
+- list_add_tail(&todo->entry, &card->ip_list);
+- else
+- kfree(todo);
+- } else if (rc == -1) {
+- /* on-card entry to be removed */
+- list_del_init(&addr->entry);
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- rc = qeth_deregister_addr_entry(card, addr);
+- spin_lock_irqsave(&card->ip_lock, flags);
+- if (!rc)
+- kfree(addr);
+- else
+- list_add_tail(&addr->entry, &card->ip_list);
+- kfree(todo);
+- }
+- }
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- kfree(tbd_list);
+-}
+-
+-static void qeth_delete_mc_addresses(struct qeth_card *);
+-static void qeth_add_multicast_ipv4(struct qeth_card *);
+-static void qeth_layer2_add_multicast(struct qeth_card *);
+-#ifdef CONFIG_QETH_IPV6
+-static void qeth_add_multicast_ipv6(struct qeth_card *);
+-#endif
+-
+-static int
+-qeth_set_thread_start_bit(struct qeth_card *card, unsigned long thread)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&card->thread_mask_lock, flags);
+- if ( !(card->thread_allowed_mask & thread) ||
+- (card->thread_start_mask & thread) ) {
+- spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+- return -EPERM;
+- }
+- card->thread_start_mask |= thread;
+- spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+- return 0;
+-}
+-
+-static void
+-qeth_clear_thread_start_bit(struct qeth_card *card, unsigned long thread)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&card->thread_mask_lock, flags);
+- card->thread_start_mask &= ~thread;
+- spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+- wake_up(&card->wait_q);
+-}
+-
+-static void
+-qeth_clear_thread_running_bit(struct qeth_card *card, unsigned long thread)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&card->thread_mask_lock, flags);
+- card->thread_running_mask &= ~thread;
+- spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+- wake_up(&card->wait_q);
+-}
+-
+-static int
+-__qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
+-{
+- unsigned long flags;
+- int rc = 0;
+-
+- spin_lock_irqsave(&card->thread_mask_lock, flags);
+- if (card->thread_start_mask & thread){
+- if ((card->thread_allowed_mask & thread) &&
+- !(card->thread_running_mask & thread)){
+- rc = 1;
+- card->thread_start_mask &= ~thread;
+- card->thread_running_mask |= thread;
+- } else
+- rc = -EPERM;
+- }
+- spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+- return rc;
+-}
+-
+-static int
+-qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
+-{
+- int rc = 0;
+-
+- wait_event(card->wait_q,
+- (rc = __qeth_do_run_thread(card, thread)) >= 0);
+- return rc;
+-}
+-
+-static int
+-qeth_recover(void *ptr)
+-{
+- struct qeth_card *card;
+- int rc = 0;
+-
+- card = (struct qeth_card *) ptr;
+- daemonize("qeth_recover");
+- QETH_DBF_TEXT(trace,2,"recover1");
+- QETH_DBF_HEX(trace, 2, &card, sizeof(void *));
+- if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))
+- return 0;
+- QETH_DBF_TEXT(trace,2,"recover2");
+- PRINT_WARN("Recovery of device %s started ...\n",
+- CARD_BUS_ID(card));
+- card->use_hard_stop = 1;
+- __qeth_set_offline(card->gdev,1);
+- rc = __qeth_set_online(card->gdev,1);
+- /* don't run another scheduled recovery */
+- qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
+- qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
+- if (!rc)
+- PRINT_INFO("Device %s successfully recovered!\n",
+- CARD_BUS_ID(card));
+- else
+- PRINT_INFO("Device %s could not be recovered!\n",
+- CARD_BUS_ID(card));
+- return 0;
+-}
+-
+-void
+-qeth_schedule_recovery(struct qeth_card *card)
+-{
+- QETH_DBF_TEXT(trace,2,"startrec");
+- if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0)
+- schedule_work(&card->kernel_thread_starter);
+-}
+-
+-static int
+-qeth_do_start_thread(struct qeth_card *card, unsigned long thread)
+-{
+- unsigned long flags;
+- int rc = 0;
+-
+- spin_lock_irqsave(&card->thread_mask_lock, flags);
+- QETH_DBF_TEXT_(trace, 4, " %02x%02x%02x",
+- (u8) card->thread_start_mask,
+- (u8) card->thread_allowed_mask,
+- (u8) card->thread_running_mask);
+- rc = (card->thread_start_mask & thread);
+- spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+- return rc;
+-}
+-
+-static void
+-qeth_start_kernel_thread(struct work_struct *work)
+-{
+- struct qeth_card *card = container_of(work, struct qeth_card, kernel_thread_starter);
+- QETH_DBF_TEXT(trace , 2, "strthrd");
+-
+- if (card->read.state != CH_STATE_UP &&
+- card->write.state != CH_STATE_UP)
+- return;
+- if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))
+- kernel_thread(qeth_recover, (void *) card, SIGCHLD);
+-}
+-
+-
+-static void
+-qeth_set_intial_options(struct qeth_card *card)
+-{
+- card->options.route4.type = NO_ROUTER;
+-#ifdef CONFIG_QETH_IPV6
+- card->options.route6.type = NO_ROUTER;
+-#endif /* QETH_IPV6 */
+- card->options.checksum_type = QETH_CHECKSUM_DEFAULT;
+- card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
+- card->options.macaddr_mode = QETH_TR_MACADDR_NONCANONICAL;
+- card->options.fake_broadcast = 0;
+- card->options.add_hhlen = DEFAULT_ADD_HHLEN;
+- card->options.fake_ll = 0;
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- card->options.layer2 = 1;
+- else
+- card->options.layer2 = 0;
+- card->options.performance_stats = 0;
+- card->options.rx_sg_cb = QETH_RX_SG_CB;
+-}
+-
+-/**
+- * initialize channels ,card and all state machines
+- */
+-static int
+-qeth_setup_card(struct qeth_card *card)
+-{
+-
+- QETH_DBF_TEXT(setup, 2, "setupcrd");
+- QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+-
+- card->read.state = CH_STATE_DOWN;
+- card->write.state = CH_STATE_DOWN;
+- card->data.state = CH_STATE_DOWN;
+- card->state = CARD_STATE_DOWN;
+- card->lan_online = 0;
+- card->use_hard_stop = 0;
+- card->dev = NULL;
+-#ifdef CONFIG_QETH_VLAN
+- spin_lock_init(&card->vlanlock);
+- card->vlangrp = NULL;
+-#endif
+- spin_lock_init(&card->lock);
+- spin_lock_init(&card->ip_lock);
+- spin_lock_init(&card->thread_mask_lock);
+- card->thread_start_mask = 0;
+- card->thread_allowed_mask = 0;
+- card->thread_running_mask = 0;
+- INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread);
+- INIT_LIST_HEAD(&card->ip_list);
+- card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+- if (!card->ip_tbd_list) {
+- QETH_DBF_TEXT(setup, 0, "iptbdnom");
+- return -ENOMEM;
+- }
+- INIT_LIST_HEAD(card->ip_tbd_list);
+- INIT_LIST_HEAD(&card->cmd_waiter_list);
+- init_waitqueue_head(&card->wait_q);
+- /* intial options */
+- qeth_set_intial_options(card);
+- /* IP address takeover */
+- INIT_LIST_HEAD(&card->ipato.entries);
+- card->ipato.enabled = 0;
+- card->ipato.invert4 = 0;
+- card->ipato.invert6 = 0;
+- /* init QDIO stuff */
+- qeth_init_qdio_info(card);
+- return 0;
+-}
+-
+-static int
+-is_1920_device (struct qeth_card *card)
+-{
+- int single_queue = 0;
+- struct ccw_device *ccwdev;
+- struct channelPath_dsc {
+- u8 flags;
+- u8 lsn;
+- u8 desc;
+- u8 chpid;
+- u8 swla;
+- u8 zeroes;
+- u8 chla;
+- u8 chpp;
+- } *chp_dsc;
+-
+- QETH_DBF_TEXT(setup, 2, "chk_1920");
+-
+- ccwdev = card->data.ccwdev;
+- chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0);
+- if (chp_dsc != NULL) {
+- /* CHPP field bit 6 == 1 -> single queue */
+- single_queue = ((chp_dsc->chpp & 0x02) == 0x02);
+- kfree(chp_dsc);
+- }
+- QETH_DBF_TEXT_(setup, 2, "rc:%x", single_queue);
+- return single_queue;
+-}
+-
+-static int
+-qeth_determine_card_type(struct qeth_card *card)
+-{
+- int i = 0;
+-
+- QETH_DBF_TEXT(setup, 2, "detcdtyp");
+-
+- card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
+- card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
+- while (known_devices[i][4]) {
+- if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) &&
+- (CARD_RDEV(card)->id.dev_model == known_devices[i][3])) {
+- card->info.type = known_devices[i][4];
+- card->qdio.no_out_queues = known_devices[i][8];
+- card->info.is_multicast_different = known_devices[i][9];
+- if (is_1920_device(card)) {
+- PRINT_INFO("Priority Queueing not able "
+- "due to hardware limitations!\n");
+- card->qdio.no_out_queues = 1;
+- card->qdio.default_out_queue = 0;
+- }
+- return 0;
+- }
+- i++;
+- }
+- card->info.type = QETH_CARD_TYPE_UNKNOWN;
+- PRINT_ERR("unknown card type on device %s\n", CARD_BUS_ID(card));
+- return -ENOENT;
+-}
+-
+-static int
+-qeth_probe_device(struct ccwgroup_device *gdev)
+-{
+- struct qeth_card *card;
+- struct device *dev;
+- unsigned long flags;
+- int rc;
+-
+- QETH_DBF_TEXT(setup, 2, "probedev");
+-
+- dev = &gdev->dev;
+- if (!get_device(dev))
+- return -ENODEV;
+-
+- QETH_DBF_TEXT_(setup, 2, "%s", gdev->dev.bus_id);
+-
+- card = qeth_alloc_card();
+- if (!card) {
+- put_device(dev);
+- QETH_DBF_TEXT_(setup, 2, "1err%d", -ENOMEM);
+- return -ENOMEM;
+- }
+- card->read.ccwdev = gdev->cdev[0];
+- card->write.ccwdev = gdev->cdev[1];
+- card->data.ccwdev = gdev->cdev[2];
+- gdev->dev.driver_data = card;
+- card->gdev = gdev;
+- gdev->cdev[0]->handler = qeth_irq;
+- gdev->cdev[1]->handler = qeth_irq;
+- gdev->cdev[2]->handler = qeth_irq;
+-
+- if ((rc = qeth_determine_card_type(card))){
+- PRINT_WARN("%s: not a valid card type\n", __func__);
+- QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+- put_device(dev);
+- qeth_free_card(card);
+- return rc;
+- }
+- if ((rc = qeth_setup_card(card))){
+- QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+- put_device(dev);
+- qeth_free_card(card);
+- return rc;
+- }
+- rc = qeth_create_device_attributes(dev);
+- if (rc) {
+- put_device(dev);
+- qeth_free_card(card);
+- return rc;
+- }
+- /* insert into our internal list */
+- write_lock_irqsave(&qeth_card_list.rwlock, flags);
+- list_add_tail(&card->list, &qeth_card_list.list);
+- write_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+- return rc;
+-}
+-
+-
+-static int qeth_read_conf_data(struct qeth_card *card, void **buffer,
+- int *length)
+-{
+- struct ciw *ciw;
+- char *rcd_buf;
+- int ret;
+- struct qeth_channel *channel = &card->data;
+- unsigned long flags;
+-
+- /*
+- * scan for RCD command in extended SenseID data
+- */
+- ciw = ccw_device_get_ciw(channel->ccwdev, CIW_TYPE_RCD);
+- if (!ciw || ciw->cmd == 0)
+- return -EOPNOTSUPP;
+- rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA);
+- if (!rcd_buf)
+- return -ENOMEM;
+-
+- channel->ccw.cmd_code = ciw->cmd;
+- channel->ccw.cda = (__u32) __pa (rcd_buf);
+- channel->ccw.count = ciw->count;
+- channel->ccw.flags = CCW_FLAG_SLI;
+- channel->state = CH_STATE_RCD;
+- spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+- ret = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
+- QETH_RCD_PARM, LPM_ANYPATH, 0,
+- QETH_RCD_TIMEOUT);
+- spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+- if (!ret)
+- wait_event(card->wait_q,
+- (channel->state == CH_STATE_RCD_DONE ||
+- channel->state == CH_STATE_DOWN));
+- if (channel->state == CH_STATE_DOWN)
+- ret = -EIO;
+- else
+- channel->state = CH_STATE_DOWN;
+- if (ret) {
+- kfree(rcd_buf);
+- *buffer = NULL;
+- *length = 0;
+- } else {
+- *length = ciw->count;
+- *buffer = rcd_buf;
+- }
+- return ret;
+-}
+-
+-static int
+-qeth_get_unitaddr(struct qeth_card *card)
+-{
+- int length;
+- char *prcd;
+- int rc;
+-
+- QETH_DBF_TEXT(setup, 2, "getunit");
+- rc = qeth_read_conf_data(card, (void **) &prcd, &length);
+- if (rc) {
+- PRINT_ERR("qeth_read_conf_data for device %s returned %i\n",
+- CARD_DDEV_ID(card), rc);
+- return rc;
+- }
+- card->info.chpid = prcd[30];
+- card->info.unit_addr2 = prcd[31];
+- card->info.cula = prcd[63];
+- card->info.guestlan = ((prcd[0x10] == _ascebc['V']) &&
+- (prcd[0x11] == _ascebc['M']));
+- kfree(prcd);
+- return 0;
+-}
+-
+-static void
+-qeth_init_tokens(struct qeth_card *card)
+-{
+- card->token.issuer_rm_w = 0x00010103UL;
+- card->token.cm_filter_w = 0x00010108UL;
+- card->token.cm_connection_w = 0x0001010aUL;
+- card->token.ulp_filter_w = 0x0001010bUL;
+- card->token.ulp_connection_w = 0x0001010dUL;
+-}
+-
+-static inline __u16
+-raw_devno_from_bus_id(char *id)
+-{
+- id += (strlen(id) - 4);
+- return (__u16) simple_strtoul(id, &id, 16);
+-}
+-/**
+- * setup channel
+- */
+-static void
+-qeth_setup_ccw(struct qeth_channel *channel,unsigned char *iob, __u32 len)
+-{
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT(trace, 4, "setupccw");
+- card = CARD_FROM_CDEV(channel->ccwdev);
+- if (channel == &card->read)
+- memcpy(&channel->ccw, READ_CCW, sizeof(struct ccw1));
+- else
+- memcpy(&channel->ccw, WRITE_CCW, sizeof(struct ccw1));
+- channel->ccw.count = len;
+- channel->ccw.cda = (__u32) __pa(iob);
+-}
+-
+-/**
+- * get free buffer for ccws (IDX activation, lancmds,ipassists...)
+- */
+-static struct qeth_cmd_buffer *
+-__qeth_get_buffer(struct qeth_channel *channel)
+-{
+- __u8 index;
+-
+- QETH_DBF_TEXT(trace, 6, "getbuff");
+- index = channel->io_buf_no;
+- do {
+- if (channel->iob[index].state == BUF_STATE_FREE) {
+- channel->iob[index].state = BUF_STATE_LOCKED;
+- channel->io_buf_no = (channel->io_buf_no + 1) %
+- QETH_CMD_BUFFER_NO;
+- memset(channel->iob[index].data, 0, QETH_BUFSIZE);
+- return channel->iob + index;
+- }
+- index = (index + 1) % QETH_CMD_BUFFER_NO;
+- } while(index != channel->io_buf_no);
+-
+- return NULL;
+-}
+-
+-/**
+- * release command buffer
+- */
+-static void
+-qeth_release_buffer(struct qeth_channel *channel, struct qeth_cmd_buffer *iob)
+-{
+- unsigned long flags;
+-
+- QETH_DBF_TEXT(trace, 6, "relbuff");
+- spin_lock_irqsave(&channel->iob_lock, flags);
+- memset(iob->data, 0, QETH_BUFSIZE);
+- iob->state = BUF_STATE_FREE;
+- iob->callback = qeth_send_control_data_cb;
+- iob->rc = 0;
+- spin_unlock_irqrestore(&channel->iob_lock, flags);
+-}
+-
+-static struct qeth_cmd_buffer *
+-qeth_get_buffer(struct qeth_channel *channel)
+-{
+- struct qeth_cmd_buffer *buffer = NULL;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&channel->iob_lock, flags);
+- buffer = __qeth_get_buffer(channel);
+- spin_unlock_irqrestore(&channel->iob_lock, flags);
+- return buffer;
+-}
+-
+-static struct qeth_cmd_buffer *
+-qeth_wait_for_buffer(struct qeth_channel *channel)
+-{
+- struct qeth_cmd_buffer *buffer;
+- wait_event(channel->wait_q,
+- ((buffer = qeth_get_buffer(channel)) != NULL));
+- return buffer;
+-}
+-
+-static void
+-qeth_clear_cmd_buffers(struct qeth_channel *channel)
+-{
+- int cnt;
+-
+- for (cnt=0; cnt < QETH_CMD_BUFFER_NO; cnt++)
+- qeth_release_buffer(channel,&channel->iob[cnt]);
+- channel->buf_no = 0;
+- channel->io_buf_no = 0;
+-}
+-
+-/**
+- * start IDX for read and write channel
+- */
+-static int
+-qeth_idx_activate_get_answer(struct qeth_channel *channel,
+- void (*idx_reply_cb)(struct qeth_channel *,
+- struct qeth_cmd_buffer *))
+-{
+- struct qeth_cmd_buffer *iob;
+- unsigned long flags;
+- int rc;
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT(setup, 2, "idxanswr");
+- card = CARD_FROM_CDEV(channel->ccwdev);
+- iob = qeth_get_buffer(channel);
+- iob->callback = idx_reply_cb;
+- memcpy(&channel->ccw, READ_CCW, sizeof(struct ccw1));
+- channel->ccw.count = QETH_BUFSIZE;
+- channel->ccw.cda = (__u32) __pa(iob->data);
+-
+- wait_event(card->wait_q,
+- atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
+- QETH_DBF_TEXT(setup, 6, "noirqpnd");
+- spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+- rc = ccw_device_start(channel->ccwdev,
+- &channel->ccw,(addr_t) iob, 0, 0);
+- spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+-
+- if (rc) {
+- PRINT_ERR("qeth: Error2 in activating channel rc=%d\n",rc);
+- QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+- atomic_set(&channel->irq_pending, 0);
+- wake_up(&card->wait_q);
+- return rc;
+- }
+- rc = wait_event_interruptible_timeout(card->wait_q,
+- channel->state == CH_STATE_UP, QETH_TIMEOUT);
+- if (rc == -ERESTARTSYS)
+- return rc;
+- if (channel->state != CH_STATE_UP){
+- rc = -ETIME;
+- QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+- qeth_clear_cmd_buffers(channel);
+- } else
+- rc = 0;
+- return rc;
+-}
+-
+-static int
+-qeth_idx_activate_channel(struct qeth_channel *channel,
+- void (*idx_reply_cb)(struct qeth_channel *,
+- struct qeth_cmd_buffer *))
+-{
+- struct qeth_card *card;
+- struct qeth_cmd_buffer *iob;
+- unsigned long flags;
+- __u16 temp;
+- int rc;
+-
+- card = CARD_FROM_CDEV(channel->ccwdev);
+-
+- QETH_DBF_TEXT(setup, 2, "idxactch");
+-
+- iob = qeth_get_buffer(channel);
+- iob->callback = idx_reply_cb;
+- memcpy(&channel->ccw, WRITE_CCW, sizeof(struct ccw1));
+- channel->ccw.count = IDX_ACTIVATE_SIZE;
+- channel->ccw.cda = (__u32) __pa(iob->data);
+- if (channel == &card->write) {
+- memcpy(iob->data, IDX_ACTIVATE_WRITE, IDX_ACTIVATE_SIZE);
+- memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
+- &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+- card->seqno.trans_hdr++;
+- } else {
+- memcpy(iob->data, IDX_ACTIVATE_READ, IDX_ACTIVATE_SIZE);
+- memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
+- &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+- }
+- memcpy(QETH_IDX_ACT_ISSUER_RM_TOKEN(iob->data),
+- &card->token.issuer_rm_w,QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_IDX_ACT_FUNC_LEVEL(iob->data),
+- &card->info.func_level,sizeof(__u16));
+- temp = raw_devno_from_bus_id(CARD_DDEV_ID(card));
+- memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(iob->data), &temp, 2);
+- temp = (card->info.cula << 8) + card->info.unit_addr2;
+- memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(iob->data), &temp, 2);
+-
+- wait_event(card->wait_q,
+- atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
+- QETH_DBF_TEXT(setup, 6, "noirqpnd");
+- spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+- rc = ccw_device_start(channel->ccwdev,
+- &channel->ccw,(addr_t) iob, 0, 0);
+- spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+-
+- if (rc) {
+- PRINT_ERR("qeth: Error1 in activating channel. rc=%d\n",rc);
+- QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+- atomic_set(&channel->irq_pending, 0);
+- wake_up(&card->wait_q);
+- return rc;
+- }
+- rc = wait_event_interruptible_timeout(card->wait_q,
+- channel->state == CH_STATE_ACTIVATING, QETH_TIMEOUT);
+- if (rc == -ERESTARTSYS)
+- return rc;
+- if (channel->state != CH_STATE_ACTIVATING) {
+- PRINT_WARN("qeth: IDX activate timed out!\n");
+- QETH_DBF_TEXT_(setup, 2, "2err%d", -ETIME);
+- qeth_clear_cmd_buffers(channel);
+- return -ETIME;
+- }
+- return qeth_idx_activate_get_answer(channel,idx_reply_cb);
+-}
+-
+-static int
+-qeth_peer_func_level(int level)
+-{
+- if ((level & 0xff) == 8)
+- return (level & 0xff) + 0x400;
+- if (((level >> 8) & 3) == 1)
+- return (level & 0xff) + 0x200;
+- return level;
+-}
+-
+-static void
+-qeth_idx_write_cb(struct qeth_channel *channel, struct qeth_cmd_buffer *iob)
+-{
+- struct qeth_card *card;
+- __u16 temp;
+-
+- QETH_DBF_TEXT(setup ,2, "idxwrcb");
+-
+- if (channel->state == CH_STATE_DOWN) {
+- channel->state = CH_STATE_ACTIVATING;
+- goto out;
+- }
+- card = CARD_FROM_CDEV(channel->ccwdev);
+-
+- if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
+- if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
+- PRINT_ERR("IDX_ACTIVATE on write channel device %s: "
+- "adapter exclusively used by another host\n",
+- CARD_WDEV_ID(card));
+- else
+- PRINT_ERR("IDX_ACTIVATE on write channel device %s: "
+- "negative reply\n", CARD_WDEV_ID(card));
+- goto out;
+- }
+- memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
+- if ((temp & ~0x0100) != qeth_peer_func_level(card->info.func_level)) {
+- PRINT_WARN("IDX_ACTIVATE on write channel device %s: "
+- "function level mismatch "
+- "(sent: 0x%x, received: 0x%x)\n",
+- CARD_WDEV_ID(card), card->info.func_level, temp);
+- goto out;
+- }
+- channel->state = CH_STATE_UP;
+-out:
+- qeth_release_buffer(channel, iob);
+-}
+-
+-static int
+-qeth_check_idx_response(unsigned char *buffer)
+-{
+- if (!buffer)
+- return 0;
+-
+- QETH_DBF_HEX(control, 2, buffer, QETH_DBF_CONTROL_LEN);
+- if ((buffer[2] & 0xc0) == 0xc0) {
+- PRINT_WARN("received an IDX TERMINATE "
+- "with cause code 0x%02x%s\n",
+- buffer[4],
+- ((buffer[4] == 0x22) ?
+- " -- try another portname" : ""));
+- QETH_DBF_TEXT(trace, 2, "ckidxres");
+- QETH_DBF_TEXT(trace, 2, " idxterm");
+- QETH_DBF_TEXT_(trace, 2, " rc%d", -EIO);
+- return -EIO;
+- }
+- return 0;
+-}
+-
+-static void
+-qeth_idx_read_cb(struct qeth_channel *channel, struct qeth_cmd_buffer *iob)
+-{
+- struct qeth_card *card;
+- __u16 temp;
+-
+- QETH_DBF_TEXT(setup , 2, "idxrdcb");
+- if (channel->state == CH_STATE_DOWN) {
+- channel->state = CH_STATE_ACTIVATING;
+- goto out;
+- }
+-
+- card = CARD_FROM_CDEV(channel->ccwdev);
+- if (qeth_check_idx_response(iob->data)) {
+- goto out;
+- }
+- if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
+- if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
+- PRINT_ERR("IDX_ACTIVATE on read channel device %s: "
+- "adapter exclusively used by another host\n",
+- CARD_RDEV_ID(card));
+- else
+- PRINT_ERR("IDX_ACTIVATE on read channel device %s: "
+- "negative reply\n", CARD_RDEV_ID(card));
+- goto out;
+- }
+-
+-/**
+- * temporary fix for microcode bug
+- * to revert it,replace OR by AND
+- */
+- if ( (!QETH_IDX_NO_PORTNAME_REQUIRED(iob->data)) ||
+- (card->info.type == QETH_CARD_TYPE_OSAE) )
+- card->info.portname_required = 1;
+-
+- memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
+- if (temp != qeth_peer_func_level(card->info.func_level)) {
+- PRINT_WARN("IDX_ACTIVATE on read channel device %s: function "
+- "level mismatch (sent: 0x%x, received: 0x%x)\n",
+- CARD_RDEV_ID(card), card->info.func_level, temp);
+- goto out;
+- }
+- memcpy(&card->token.issuer_rm_r,
+- QETH_IDX_ACT_ISSUER_RM_TOKEN(iob->data),
+- QETH_MPC_TOKEN_LENGTH);
+- memcpy(&card->info.mcl_level[0],
+- QETH_IDX_REPLY_LEVEL(iob->data), QETH_MCL_LENGTH);
+- channel->state = CH_STATE_UP;
+-out:
+- qeth_release_buffer(channel,iob);
+-}
+-
+-static int
+-qeth_issue_next_read(struct qeth_card *card)
+-{
+- int rc;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(trace,5,"issnxrd");
+- if (card->read.state != CH_STATE_UP)
+- return -EIO;
+- iob = qeth_get_buffer(&card->read);
+- if (!iob) {
+- PRINT_WARN("issue_next_read failed: no iob available!\n");
+- return -ENOMEM;
+- }
+- qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE);
+- QETH_DBF_TEXT(trace, 6, "noirqpnd");
+- rc = ccw_device_start(card->read.ccwdev, &card->read.ccw,
+- (addr_t) iob, 0, 0);
+- if (rc) {
+- PRINT_ERR("Error in starting next read ccw! rc=%i\n", rc);
+- atomic_set(&card->read.irq_pending, 0);
+- qeth_schedule_recovery(card);
+- wake_up(&card->wait_q);
+- }
+- return rc;
+-}
+-
+-static struct qeth_reply *
+-qeth_alloc_reply(struct qeth_card *card)
+-{
+- struct qeth_reply *reply;
+-
+- reply = kzalloc(sizeof(struct qeth_reply), GFP_ATOMIC);
+- if (reply){
+- atomic_set(&reply->refcnt, 1);
+- atomic_set(&reply->received, 0);
+- reply->card = card;
+- };
+- return reply;
+-}
+-
+-static void
+-qeth_get_reply(struct qeth_reply *reply)
+-{
+- WARN_ON(atomic_read(&reply->refcnt) <= 0);
+- atomic_inc(&reply->refcnt);
+-}
+-
+-static void
+-qeth_put_reply(struct qeth_reply *reply)
+-{
+- WARN_ON(atomic_read(&reply->refcnt) <= 0);
+- if (atomic_dec_and_test(&reply->refcnt))
+- kfree(reply);
+-}
+-
+-static void
+-qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, struct qeth_card *card)
+-{
+- int rc;
+- int com;
+- char * ipa_name;
+-
+- com = cmd->hdr.command;
+- rc = cmd->hdr.return_code;
+- ipa_name = qeth_get_ipa_cmd_name(com);
+-
+- PRINT_ERR("%s(x%X) for %s returned x%X \"%s\"\n", ipa_name, com,
+- QETH_CARD_IFNAME(card), rc, qeth_get_ipa_msg(rc));
+-}
+-
+-static struct qeth_ipa_cmd *
+-qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
+-{
+- struct qeth_ipa_cmd *cmd = NULL;
+-
+- QETH_DBF_TEXT(trace,5,"chkipad");
+- if (IS_IPA(iob->data)){
+- cmd = (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data);
+- if (IS_IPA_REPLY(cmd)) {
+- if (cmd->hdr.return_code)
+- qeth_issue_ipa_msg(cmd, card);
+- return cmd;
+- }
+- else {
+- switch (cmd->hdr.command) {
+- case IPA_CMD_STOPLAN:
+- PRINT_WARN("Link failure on %s (CHPID 0x%X) - "
+- "there is a network problem or "
+- "someone pulled the cable or "
+- "disabled the port.\n",
+- QETH_CARD_IFNAME(card),
+- card->info.chpid);
+- card->lan_online = 0;
+- if (card->dev && netif_carrier_ok(card->dev))
+- netif_carrier_off(card->dev);
+- return NULL;
+- case IPA_CMD_STARTLAN:
+- PRINT_INFO("Link reestablished on %s "
+- "(CHPID 0x%X). Scheduling "
+- "IP address reset.\n",
+- QETH_CARD_IFNAME(card),
+- card->info.chpid);
+- netif_carrier_on(card->dev);
+- qeth_schedule_recovery(card);
+- return NULL;
+- case IPA_CMD_MODCCID:
+- return cmd;
+- case IPA_CMD_REGISTER_LOCAL_ADDR:
+- QETH_DBF_TEXT(trace,3, "irla");
+- break;
+- case IPA_CMD_UNREGISTER_LOCAL_ADDR:
+- QETH_DBF_TEXT(trace,3, "urla");
+- break;
+- default:
+- PRINT_WARN("Received data is IPA "
+- "but not a reply!\n");
+- break;
+- }
+- }
+- }
+- return cmd;
+-}
+-
+-/**
+- * wake all waiting ipa commands
+- */
+-static void
+-qeth_clear_ipacmd_list(struct qeth_card *card)
+-{
+- struct qeth_reply *reply, *r;
+- unsigned long flags;
+-
+- QETH_DBF_TEXT(trace, 4, "clipalst");
+-
+- spin_lock_irqsave(&card->lock, flags);
+- list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
+- qeth_get_reply(reply);
+- reply->rc = -EIO;
+- atomic_inc(&reply->received);
+- list_del_init(&reply->list);
+- wake_up(&reply->wait_q);
+- qeth_put_reply(reply);
+- }
+- spin_unlock_irqrestore(&card->lock, flags);
+-}
+-
+-static void
+-qeth_send_control_data_cb(struct qeth_channel *channel,
+- struct qeth_cmd_buffer *iob)
+-{
+- struct qeth_card *card;
+- struct qeth_reply *reply, *r;
+- struct qeth_ipa_cmd *cmd;
+- unsigned long flags;
+- int keep_reply;
+-
+- QETH_DBF_TEXT(trace,4,"sndctlcb");
+-
+- card = CARD_FROM_CDEV(channel->ccwdev);
+- if (qeth_check_idx_response(iob->data)) {
+- qeth_clear_ipacmd_list(card);
+- qeth_schedule_recovery(card);
+- goto out;
+- }
+-
+- cmd = qeth_check_ipa_data(card, iob);
+- if ((cmd == NULL) && (card->state != CARD_STATE_DOWN))
+- goto out;
+- /*in case of OSN : check if cmd is set */
+- if (card->info.type == QETH_CARD_TYPE_OSN &&
+- cmd &&
+- cmd->hdr.command != IPA_CMD_STARTLAN &&
+- card->osn_info.assist_cb != NULL) {
+- card->osn_info.assist_cb(card->dev, cmd);
+- goto out;
+- }
+-
+- spin_lock_irqsave(&card->lock, flags);
+- list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
+- if ((reply->seqno == QETH_IDX_COMMAND_SEQNO) ||
+- ((cmd) && (reply->seqno == cmd->hdr.seqno))) {
+- qeth_get_reply(reply);
+- list_del_init(&reply->list);
+- spin_unlock_irqrestore(&card->lock, flags);
+- keep_reply = 0;
+- if (reply->callback != NULL) {
+- if (cmd) {
+- reply->offset = (__u16)((char*)cmd -
+- (char *)iob->data);
+- keep_reply = reply->callback(card,
+- reply,
+- (unsigned long)cmd);
+- } else
+- keep_reply = reply->callback(card,
+- reply,
+- (unsigned long)iob);
+- }
+- if (cmd)
+- reply->rc = (u16) cmd->hdr.return_code;
+- else if (iob->rc)
+- reply->rc = iob->rc;
+- if (keep_reply) {
+- spin_lock_irqsave(&card->lock, flags);
+- list_add_tail(&reply->list,
+- &card->cmd_waiter_list);
+- spin_unlock_irqrestore(&card->lock, flags);
+- } else {
+- atomic_inc(&reply->received);
+- wake_up(&reply->wait_q);
+- }
+- qeth_put_reply(reply);
+- goto out;
+- }
+- }
+- spin_unlock_irqrestore(&card->lock, flags);
+-out:
+- memcpy(&card->seqno.pdu_hdr_ack,
+- QETH_PDU_HEADER_SEQ_NO(iob->data),
+- QETH_SEQ_NO_LENGTH);
+- qeth_release_buffer(channel,iob);
+-}
+-
+-static void
+-qeth_prepare_control_data(struct qeth_card *card, int len,
+- struct qeth_cmd_buffer *iob)
+-{
+- qeth_setup_ccw(&card->write,iob->data,len);
+- iob->callback = qeth_release_buffer;
+-
+- memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
+- &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+- card->seqno.trans_hdr++;
+- memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
+- &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
+- card->seqno.pdu_hdr++;
+- memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
+- &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
+- QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
+-}
+-
+-static int
+-qeth_send_control_data(struct qeth_card *card, int len,
+- struct qeth_cmd_buffer *iob,
+- int (*reply_cb)
+- (struct qeth_card *, struct qeth_reply*, unsigned long),
+- void *reply_param)
+-
+-{
+- int rc;
+- unsigned long flags;
+- struct qeth_reply *reply = NULL;
+- unsigned long timeout;
+-
+- QETH_DBF_TEXT(trace, 2, "sendctl");
+-
+- reply = qeth_alloc_reply(card);
+- if (!reply) {
+- PRINT_WARN("Could no alloc qeth_reply!\n");
+- return -ENOMEM;
+- }
+- reply->callback = reply_cb;
+- reply->param = reply_param;
+- if (card->state == CARD_STATE_DOWN)
+- reply->seqno = QETH_IDX_COMMAND_SEQNO;
+- else
+- reply->seqno = card->seqno.ipa++;
+- init_waitqueue_head(&reply->wait_q);
+- spin_lock_irqsave(&card->lock, flags);
+- list_add_tail(&reply->list, &card->cmd_waiter_list);
+- spin_unlock_irqrestore(&card->lock, flags);
+- QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
+-
+- while (atomic_cmpxchg(&card->write.irq_pending, 0, 1)) ;
+- qeth_prepare_control_data(card, len, iob);
+-
+- if (IS_IPA(iob->data))
+- timeout = jiffies + QETH_IPA_TIMEOUT;
+- else
+- timeout = jiffies + QETH_TIMEOUT;
+-
+- QETH_DBF_TEXT(trace, 6, "noirqpnd");
+- spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
+- rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
+- (addr_t) iob, 0, 0);
+- spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
+- if (rc){
+- PRINT_WARN("qeth_send_control_data: "
+- "ccw_device_start rc = %i\n", rc);
+- QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+- spin_lock_irqsave(&card->lock, flags);
+- list_del_init(&reply->list);
+- qeth_put_reply(reply);
+- spin_unlock_irqrestore(&card->lock, flags);
+- qeth_release_buffer(iob->channel, iob);
+- atomic_set(&card->write.irq_pending, 0);
+- wake_up(&card->wait_q);
+- return rc;
+- }
+- while (!atomic_read(&reply->received)) {
+- if (time_after(jiffies, timeout)) {
+- spin_lock_irqsave(&reply->card->lock, flags);
+- list_del_init(&reply->list);
+- spin_unlock_irqrestore(&reply->card->lock, flags);
+- reply->rc = -ETIME;
+- atomic_inc(&reply->received);
+- wake_up(&reply->wait_q);
+- }
+- cpu_relax();
+- };
+- rc = reply->rc;
+- qeth_put_reply(reply);
+- return rc;
+-}
+-
+-static int
+-qeth_osn_send_control_data(struct qeth_card *card, int len,
+- struct qeth_cmd_buffer *iob)
+-{
+- unsigned long flags;
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace, 5, "osndctrd");
+-
+- wait_event(card->wait_q,
+- atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
+- qeth_prepare_control_data(card, len, iob);
+- QETH_DBF_TEXT(trace, 6, "osnoirqp");
+- spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
+- rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
+- (addr_t) iob, 0, 0);
+- spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
+- if (rc){
+- PRINT_WARN("qeth_osn_send_control_data: "
+- "ccw_device_start rc = %i\n", rc);
+- QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+- qeth_release_buffer(iob->channel, iob);
+- atomic_set(&card->write.irq_pending, 0);
+- wake_up(&card->wait_q);
+- }
+- return rc;
+-}
+-
+-static inline void
+-qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+- char prot_type)
+-{
+- memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+- memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1);
+- memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+- &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+-}
+-
+-static int
+-qeth_osn_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+- int data_len)
+-{
+- u16 s1, s2;
+-
+- QETH_DBF_TEXT(trace,4,"osndipa");
+-
+- qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2);
+- s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
+- s2 = (u16)data_len;
+- memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
+- memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
+- memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
+- memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
+- return qeth_osn_send_control_data(card, s1, iob);
+-}
+-
+-static int
+-qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+- int (*reply_cb)
+- (struct qeth_card *,struct qeth_reply*, unsigned long),
+- void *reply_param)
+-{
+- int rc;
+- char prot_type;
+-
+- QETH_DBF_TEXT(trace,4,"sendipa");
+-
+- if (card->options.layer2)
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- prot_type = QETH_PROT_OSN2;
+- else
+- prot_type = QETH_PROT_LAYER2;
+- else
+- prot_type = QETH_PROT_TCPIP;
+- qeth_prepare_ipa_cmd(card,iob,prot_type);
+- rc = qeth_send_control_data(card, IPA_CMD_LENGTH, iob,
+- reply_cb, reply_param);
+- return rc;
+-}
+-
+-
+-static int
+-qeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(setup, 2, "cmenblcb");
+-
+- iob = (struct qeth_cmd_buffer *) data;
+- memcpy(&card->token.cm_filter_r,
+- QETH_CM_ENABLE_RESP_FILTER_TOKEN(iob->data),
+- QETH_MPC_TOKEN_LENGTH);
+- QETH_DBF_TEXT_(setup, 2, " rc%d", iob->rc);
+- return 0;
+-}
+-
+-static int
+-qeth_cm_enable(struct qeth_card *card)
+-{
+- int rc;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(setup,2,"cmenable");
+-
+- iob = qeth_wait_for_buffer(&card->write);
+- memcpy(iob->data, CM_ENABLE, CM_ENABLE_SIZE);
+- memcpy(QETH_CM_ENABLE_ISSUER_RM_TOKEN(iob->data),
+- &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_CM_ENABLE_FILTER_TOKEN(iob->data),
+- &card->token.cm_filter_w, QETH_MPC_TOKEN_LENGTH);
+-
+- rc = qeth_send_control_data(card, CM_ENABLE_SIZE, iob,
+- qeth_cm_enable_cb, NULL);
+- return rc;
+-}
+-
+-static int
+-qeth_cm_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long data)
+-{
+-
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(setup, 2, "cmsetpcb");
+-
+- iob = (struct qeth_cmd_buffer *) data;
+- memcpy(&card->token.cm_connection_r,
+- QETH_CM_SETUP_RESP_DEST_ADDR(iob->data),
+- QETH_MPC_TOKEN_LENGTH);
+- QETH_DBF_TEXT_(setup, 2, " rc%d", iob->rc);
+- return 0;
+-}
+-
+-static int
+-qeth_cm_setup(struct qeth_card *card)
+-{
+- int rc;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(setup,2,"cmsetup");
+-
+- iob = qeth_wait_for_buffer(&card->write);
+- memcpy(iob->data, CM_SETUP, CM_SETUP_SIZE);
+- memcpy(QETH_CM_SETUP_DEST_ADDR(iob->data),
+- &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_CM_SETUP_CONNECTION_TOKEN(iob->data),
+- &card->token.cm_connection_w, QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_CM_SETUP_FILTER_TOKEN(iob->data),
+- &card->token.cm_filter_r, QETH_MPC_TOKEN_LENGTH);
+- rc = qeth_send_control_data(card, CM_SETUP_SIZE, iob,
+- qeth_cm_setup_cb, NULL);
+- return rc;
+-
+-}
+-
+-static int
+-qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long data)
+-{
+-
+- __u16 mtu, framesize;
+- __u16 len;
+- __u8 link_type;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(setup, 2, "ulpenacb");
+-
+- iob = (struct qeth_cmd_buffer *) data;
+- memcpy(&card->token.ulp_filter_r,
+- QETH_ULP_ENABLE_RESP_FILTER_TOKEN(iob->data),
+- QETH_MPC_TOKEN_LENGTH);
+- if (qeth_get_mtu_out_of_mpc(card->info.type)) {
+- memcpy(&framesize, QETH_ULP_ENABLE_RESP_MAX_MTU(iob->data), 2);
+- mtu = qeth_get_mtu_outof_framesize(framesize);
+- if (!mtu) {
+- iob->rc = -EINVAL;
+- QETH_DBF_TEXT_(setup, 2, " rc%d", iob->rc);
+- return 0;
+- }
+- card->info.max_mtu = mtu;
+- card->info.initial_mtu = mtu;
+- card->qdio.in_buf_size = mtu + 2 * PAGE_SIZE;
+- } else {
+- card->info.initial_mtu = qeth_get_initial_mtu_for_card(card);
+- card->info.max_mtu = qeth_get_max_mtu_for_card(card->info.type);
+- card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
+- }
+-
+- memcpy(&len, QETH_ULP_ENABLE_RESP_DIFINFO_LEN(iob->data), 2);
+- if (len >= QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE) {
+- memcpy(&link_type,
+- QETH_ULP_ENABLE_RESP_LINK_TYPE(iob->data), 1);
+- card->info.link_type = link_type;
+- } else
+- card->info.link_type = 0;
+- QETH_DBF_TEXT_(setup, 2, " rc%d", iob->rc);
+- return 0;
+-}
+-
+-static int
+-qeth_ulp_enable(struct qeth_card *card)
+-{
+- int rc;
+- char prot_type;
+- struct qeth_cmd_buffer *iob;
+-
+- /*FIXME: trace view callbacks*/
+- QETH_DBF_TEXT(setup,2,"ulpenabl");
+-
+- iob = qeth_wait_for_buffer(&card->write);
+- memcpy(iob->data, ULP_ENABLE, ULP_ENABLE_SIZE);
+-
+- *(QETH_ULP_ENABLE_LINKNUM(iob->data)) =
+- (__u8) card->info.portno;
+- if (card->options.layer2)
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- prot_type = QETH_PROT_OSN2;
+- else
+- prot_type = QETH_PROT_LAYER2;
+- else
+- prot_type = QETH_PROT_TCPIP;
+-
+- memcpy(QETH_ULP_ENABLE_PROT_TYPE(iob->data),&prot_type,1);
+- memcpy(QETH_ULP_ENABLE_DEST_ADDR(iob->data),
+- &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_ULP_ENABLE_FILTER_TOKEN(iob->data),
+- &card->token.ulp_filter_w, QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_ULP_ENABLE_PORTNAME_AND_LL(iob->data),
+- card->info.portname, 9);
+- rc = qeth_send_control_data(card, ULP_ENABLE_SIZE, iob,
+- qeth_ulp_enable_cb, NULL);
+- return rc;
+-
+-}
+-
+-static int
+-qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(setup, 2, "ulpstpcb");
+-
+- iob = (struct qeth_cmd_buffer *) data;
+- memcpy(&card->token.ulp_connection_r,
+- QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(iob->data),
+- QETH_MPC_TOKEN_LENGTH);
+- QETH_DBF_TEXT_(setup, 2, " rc%d", iob->rc);
+- return 0;
+-}
+-
+-static int
+-qeth_ulp_setup(struct qeth_card *card)
+-{
+- int rc;
+- __u16 temp;
+- struct qeth_cmd_buffer *iob;
+- struct ccw_dev_id dev_id;
+-
+- QETH_DBF_TEXT(setup,2,"ulpsetup");
+-
+- iob = qeth_wait_for_buffer(&card->write);
+- memcpy(iob->data, ULP_SETUP, ULP_SETUP_SIZE);
+-
+- memcpy(QETH_ULP_SETUP_DEST_ADDR(iob->data),
+- &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_ULP_SETUP_CONNECTION_TOKEN(iob->data),
+- &card->token.ulp_connection_w, QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_ULP_SETUP_FILTER_TOKEN(iob->data),
+- &card->token.ulp_filter_r, QETH_MPC_TOKEN_LENGTH);
+-
+- ccw_device_get_id(CARD_DDEV(card), &dev_id);
+- memcpy(QETH_ULP_SETUP_CUA(iob->data), &dev_id.devno, 2);
+- temp = (card->info.cula << 8) + card->info.unit_addr2;
+- memcpy(QETH_ULP_SETUP_REAL_DEVADDR(iob->data), &temp, 2);
+- rc = qeth_send_control_data(card, ULP_SETUP_SIZE, iob,
+- qeth_ulp_setup_cb, NULL);
+- return rc;
+-}
+-
+-static inline int
+-qeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error,
+- unsigned int siga_error, const char *dbftext)
+-{
+- if (qdio_error || siga_error) {
+- QETH_DBF_TEXT(trace, 2, dbftext);
+- QETH_DBF_TEXT(qerr, 2, dbftext);
+- QETH_DBF_TEXT_(qerr, 2, " F15=%02X",
+- buf->element[15].flags & 0xff);
+- QETH_DBF_TEXT_(qerr, 2, " F14=%02X",
+- buf->element[14].flags & 0xff);
+- QETH_DBF_TEXT_(qerr, 2, " qerr=%X", qdio_error);
+- QETH_DBF_TEXT_(qerr, 2, " serr=%X", siga_error);
+- return 1;
+- }
+- return 0;
+-}
+-
+-static struct sk_buff *
+-qeth_get_skb(unsigned int length, struct qeth_hdr *hdr)
+-{
+- struct sk_buff* skb;
+- int add_len;
+-
+- add_len = 0;
+- if (hdr->hdr.osn.id == QETH_HEADER_TYPE_OSN)
+- add_len = sizeof(struct qeth_hdr);
+-#ifdef CONFIG_QETH_VLAN
+- else
+- add_len = VLAN_HLEN;
+-#endif
+- skb = dev_alloc_skb(length + add_len);
+- if (skb && add_len)
+- skb_reserve(skb, add_len);
+- return skb;
+-}
+-
+-static inline int
+-qeth_create_skb_frag(struct qdio_buffer_element *element,
+- struct sk_buff **pskb,
+- int offset, int *pfrag, int data_len)
+-{
+- struct page *page = virt_to_page(element->addr);
+- if (*pfrag == 0) {
+- /* the upper protocol layers assume that there is data in the
+- * skb itself. Copy a small amount (64 bytes) to make them
+- * happy. */
+- *pskb = dev_alloc_skb(64 + QETH_FAKE_LL_LEN_ETH);
+- if (!(*pskb))
+- return -ENOMEM;
+- skb_reserve(*pskb, QETH_FAKE_LL_LEN_ETH);
+- if (data_len <= 64) {
+- memcpy(skb_put(*pskb, data_len), element->addr + offset,
+- data_len);
+- } else {
+- get_page(page);
+- memcpy(skb_put(*pskb, 64), element->addr + offset, 64);
+- skb_fill_page_desc(*pskb, *pfrag, page, offset + 64,
+- data_len - 64);
+- (*pskb)->data_len += data_len - 64;
+- (*pskb)->len += data_len - 64;
+- (*pskb)->truesize += data_len - 64;
+- }
+- } else {
+- get_page(page);
+- skb_fill_page_desc(*pskb, *pfrag, page, offset, data_len);
+- (*pskb)->data_len += data_len;
+- (*pskb)->len += data_len;
+- (*pskb)->truesize += data_len;
+- }
+- (*pfrag)++;
+- return 0;
+-}
+-
+-static inline struct qeth_buffer_pool_entry *
+-qeth_find_free_buffer_pool_entry(struct qeth_card *card)
+-{
+- struct list_head *plh;
+- struct qeth_buffer_pool_entry *entry;
+- int i, free;
+- struct page *page;
+-
+- if (list_empty(&card->qdio.in_buf_pool.entry_list))
+- return NULL;
+-
+- list_for_each(plh, &card->qdio.in_buf_pool.entry_list) {
+- entry = list_entry(plh, struct qeth_buffer_pool_entry, list);
+- free = 1;
+- for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
+- if (page_count(virt_to_page(entry->elements[i])) > 1) {
+- free = 0;
+- break;
+- }
+- }
+- if (free) {
+- list_del_init(&entry->list);
+- return entry;
+- }
+- }
+-
+- /* no free buffer in pool so take first one and swap pages */
+- entry = list_entry(card->qdio.in_buf_pool.entry_list.next,
+- struct qeth_buffer_pool_entry, list);
+- for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
+- if (page_count(virt_to_page(entry->elements[i])) > 1) {
+- page = alloc_page(GFP_ATOMIC|GFP_DMA);
+- if (!page) {
+- return NULL;
+- } else {
+- free_page((unsigned long)entry->elements[i]);
+- entry->elements[i] = page_address(page);
+- if (card->options.performance_stats)
+- card->perf_stats.sg_alloc_page_rx++;
+- }
+- }
+- }
+- list_del_init(&entry->list);
+- return entry;
+-}
+-
+-static struct sk_buff *
+-qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
+- struct qdio_buffer_element **__element, int *__offset,
+- struct qeth_hdr **hdr)
+-{
+- struct qdio_buffer_element *element = *__element;
+- int offset = *__offset;
+- struct sk_buff *skb = NULL;
+- int skb_len;
+- void *data_ptr;
+- int data_len;
+- int use_rx_sg = 0;
+- int frag = 0;
+-
+- QETH_DBF_TEXT(trace,6,"nextskb");
+- /* qeth_hdr must not cross element boundaries */
+- if (element->length < offset + sizeof(struct qeth_hdr)){
+- if (qeth_is_last_sbale(element))
+- return NULL;
+- element++;
+- offset = 0;
+- if (element->length < sizeof(struct qeth_hdr))
+- return NULL;
+- }
+- *hdr = element->addr + offset;
+-
+- offset += sizeof(struct qeth_hdr);
+- if (card->options.layer2)
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- skb_len = (*hdr)->hdr.osn.pdu_length;
+- else
+- skb_len = (*hdr)->hdr.l2.pkt_length;
+- else
+- skb_len = (*hdr)->hdr.l3.length;
+-
+- if (!skb_len)
+- return NULL;
+- if ((skb_len >= card->options.rx_sg_cb) &&
+- (!(card->info.type == QETH_CARD_TYPE_OSN)) &&
+- (!atomic_read(&card->force_alloc_skb))) {
+- use_rx_sg = 1;
+- } else {
+- if (card->options.fake_ll) {
+- if (card->dev->type == ARPHRD_IEEE802_TR) {
+- if (!(skb = qeth_get_skb(skb_len +
+- QETH_FAKE_LL_LEN_TR, *hdr)))
+- goto no_mem;
+- skb_reserve(skb, QETH_FAKE_LL_LEN_TR);
+- } else {
+- if (!(skb = qeth_get_skb(skb_len +
+- QETH_FAKE_LL_LEN_ETH, *hdr)))
+- goto no_mem;
+- skb_reserve(skb, QETH_FAKE_LL_LEN_ETH);
+- }
+- } else {
+- skb = qeth_get_skb(skb_len, *hdr);
+- if (!skb)
+- goto no_mem;
+- }
+- }
+-
+- data_ptr = element->addr + offset;
+- while (skb_len) {
+- data_len = min(skb_len, (int)(element->length - offset));
+- if (data_len) {
+- if (use_rx_sg) {
+- if (qeth_create_skb_frag(element, &skb, offset,
+- &frag, data_len))
+- goto no_mem;
+- } else {
+- memcpy(skb_put(skb, data_len), data_ptr,
+- data_len);
+- }
+- }
+- skb_len -= data_len;
+- if (skb_len){
+- if (qeth_is_last_sbale(element)){
+- QETH_DBF_TEXT(trace,4,"unexeob");
+- QETH_DBF_TEXT_(trace,4,"%s",CARD_BUS_ID(card));
+- QETH_DBF_TEXT(qerr,2,"unexeob");
+- QETH_DBF_TEXT_(qerr,2,"%s",CARD_BUS_ID(card));
+- QETH_DBF_HEX(misc,4,buffer,sizeof(*buffer));
+- dev_kfree_skb_any(skb);
+- card->stats.rx_errors++;
+- return NULL;
+- }
+- element++;
+- offset = 0;
+- data_ptr = element->addr;
+- } else {
+- offset += data_len;
+- }
+- }
+- *__element = element;
+- *__offset = offset;
+- if (use_rx_sg && card->options.performance_stats) {
+- card->perf_stats.sg_skbs_rx++;
+- card->perf_stats.sg_frags_rx += skb_shinfo(skb)->nr_frags;
+- }
+- return skb;
+-no_mem:
+- if (net_ratelimit()){
+- PRINT_WARN("No memory for packet received on %s.\n",
+- QETH_CARD_IFNAME(card));
+- QETH_DBF_TEXT(trace,2,"noskbmem");
+- QETH_DBF_TEXT_(trace,2,"%s",CARD_BUS_ID(card));
+- }
+- card->stats.rx_dropped++;
+- return NULL;
+-}
+-
+-static __be16
+-qeth_type_trans(struct sk_buff *skb, struct net_device *dev)
+-{
+- struct qeth_card *card;
+- struct ethhdr *eth;
+-
+- QETH_DBF_TEXT(trace,6,"typtrans");
+-
+- card = (struct qeth_card *)dev->priv;
+-#ifdef CONFIG_TR
+- if ((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+- (card->info.link_type == QETH_LINK_TYPE_LANE_TR))
+- return tr_type_trans(skb,dev);
+-#endif /* CONFIG_TR */
+- skb_reset_mac_header(skb);
+- skb_pull(skb, ETH_HLEN );
+- eth = eth_hdr(skb);
+-
+- if (*eth->h_dest & 1) {
+- if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
+- skb->pkt_type = PACKET_BROADCAST;
+- else
+- skb->pkt_type = PACKET_MULTICAST;
+- } else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
+- skb->pkt_type = PACKET_OTHERHOST;
+-
+- if (ntohs(eth->h_proto) >= 1536)
+- return eth->h_proto;
+- if (*(unsigned short *) (skb->data) == 0xFFFF)
+- return htons(ETH_P_802_3);
+- return htons(ETH_P_802_2);
+-}
+-
+-static void
+-qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb,
+- struct qeth_hdr *hdr)
+-{
+- struct trh_hdr *fake_hdr;
+- struct trllc *fake_llc;
+- struct iphdr *ip_hdr;
+-
+- QETH_DBF_TEXT(trace,5,"skbfktr");
+- skb_set_mac_header(skb, (int)-QETH_FAKE_LL_LEN_TR);
+- /* this is a fake ethernet header */
+- fake_hdr = tr_hdr(skb);
+-
+- /* the destination MAC address */
+- switch (skb->pkt_type){
+- case PACKET_MULTICAST:
+- switch (skb->protocol){
+-#ifdef CONFIG_QETH_IPV6
+- case __constant_htons(ETH_P_IPV6):
+- ndisc_mc_map((struct in6_addr *)
+- skb->data + QETH_FAKE_LL_V6_ADDR_POS,
+- fake_hdr->daddr, card->dev, 0);
+- break;
+-#endif /* CONFIG_QETH_IPV6 */
+- case __constant_htons(ETH_P_IP):
+- ip_hdr = (struct iphdr *)skb->data;
+- ip_tr_mc_map(ip_hdr->daddr, fake_hdr->daddr);
+- break;
+- default:
+- memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN);
+- }
+- break;
+- case PACKET_BROADCAST:
+- memset(fake_hdr->daddr, 0xff, TR_ALEN);
+- break;
+- default:
+- memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN);
+- }
+- /* the source MAC address */
+- if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR)
+- memcpy(fake_hdr->saddr, &hdr->hdr.l3.dest_addr[2], TR_ALEN);
+- else
+- memset(fake_hdr->saddr, 0, TR_ALEN);
+- fake_hdr->rcf=0;
+- fake_llc = (struct trllc*)&(fake_hdr->rcf);
+- fake_llc->dsap = EXTENDED_SAP;
+- fake_llc->ssap = EXTENDED_SAP;
+- fake_llc->llc = UI_CMD;
+- fake_llc->protid[0] = 0;
+- fake_llc->protid[1] = 0;
+- fake_llc->protid[2] = 0;
+- fake_llc->ethertype = ETH_P_IP;
+-}
+-
+-static void
+-qeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb,
+- struct qeth_hdr *hdr)
+-{
+- struct ethhdr *fake_hdr;
+- struct iphdr *ip_hdr;
+-
+- QETH_DBF_TEXT(trace,5,"skbfketh");
+- skb_set_mac_header(skb, -QETH_FAKE_LL_LEN_ETH);
+- /* this is a fake ethernet header */
+- fake_hdr = eth_hdr(skb);
+-
+- /* the destination MAC address */
+- switch (skb->pkt_type){
+- case PACKET_MULTICAST:
+- switch (skb->protocol){
+-#ifdef CONFIG_QETH_IPV6
+- case __constant_htons(ETH_P_IPV6):
+- ndisc_mc_map((struct in6_addr *)
+- skb->data + QETH_FAKE_LL_V6_ADDR_POS,
+- fake_hdr->h_dest, card->dev, 0);
+- break;
+-#endif /* CONFIG_QETH_IPV6 */
+- case __constant_htons(ETH_P_IP):
+- ip_hdr = (struct iphdr *)skb->data;
+- ip_eth_mc_map(ip_hdr->daddr, fake_hdr->h_dest);
+- break;
+- default:
+- memcpy(fake_hdr->h_dest, card->dev->dev_addr, ETH_ALEN);
+- }
+- break;
+- case PACKET_BROADCAST:
+- memset(fake_hdr->h_dest, 0xff, ETH_ALEN);
+- break;
+- default:
+- memcpy(fake_hdr->h_dest, card->dev->dev_addr, ETH_ALEN);
+- }
+- /* the source MAC address */
+- if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR)
+- memcpy(fake_hdr->h_source, &hdr->hdr.l3.dest_addr[2], ETH_ALEN);
+- else
+- memset(fake_hdr->h_source, 0, ETH_ALEN);
+- /* the protocol */
+- fake_hdr->h_proto = skb->protocol;
+-}
+-
+-static inline void
+-qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
+- struct qeth_hdr *hdr)
+-{
+- if (card->dev->type == ARPHRD_IEEE802_TR)
+- qeth_rebuild_skb_fake_ll_tr(card, skb, hdr);
+- else
+- qeth_rebuild_skb_fake_ll_eth(card, skb, hdr);
+-}
+-
+-static inline void
+-qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
+- struct qeth_hdr *hdr)
+-{
+- skb->pkt_type = PACKET_HOST;
+- skb->protocol = qeth_type_trans(skb, skb->dev);
+- if (card->options.checksum_type == NO_CHECKSUMMING)
+- skb->ip_summed = CHECKSUM_UNNECESSARY;
+- else
+- skb->ip_summed = CHECKSUM_NONE;
+- *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
+-}
+-
+-static __u16
+-qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
+- struct qeth_hdr *hdr)
+-{
+- unsigned short vlan_id = 0;
+-#ifdef CONFIG_QETH_IPV6
+- if (hdr->hdr.l3.flags & QETH_HDR_PASSTHRU) {
+- skb->pkt_type = PACKET_HOST;
+- skb->protocol = qeth_type_trans(skb, card->dev);
+- return 0;
+- }
+-#endif /* CONFIG_QETH_IPV6 */
+- skb->protocol = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 :
+- ETH_P_IP);
+- switch (hdr->hdr.l3.flags & QETH_HDR_CAST_MASK){
+- case QETH_CAST_UNICAST:
+- skb->pkt_type = PACKET_HOST;
+- break;
+- case QETH_CAST_MULTICAST:
+- skb->pkt_type = PACKET_MULTICAST;
+- card->stats.multicast++;
+- break;
+- case QETH_CAST_BROADCAST:
+- skb->pkt_type = PACKET_BROADCAST;
+- card->stats.multicast++;
+- break;
+- case QETH_CAST_ANYCAST:
+- case QETH_CAST_NOCAST:
+- default:
+- skb->pkt_type = PACKET_HOST;
+- }
+-
+- if (hdr->hdr.l3.ext_flags &
+- (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) {
+- vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)?
+- hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]);
+- }
+-
+- if (card->options.fake_ll)
+- qeth_rebuild_skb_fake_ll(card, skb, hdr);
+- else
+- skb_reset_mac_header(skb);
+- skb->ip_summed = card->options.checksum_type;
+- if (card->options.checksum_type == HW_CHECKSUMMING){
+- if ( (hdr->hdr.l3.ext_flags &
+- (QETH_HDR_EXT_CSUM_HDR_REQ |
+- QETH_HDR_EXT_CSUM_TRANSP_REQ)) ==
+- (QETH_HDR_EXT_CSUM_HDR_REQ |
+- QETH_HDR_EXT_CSUM_TRANSP_REQ) )
+- skb->ip_summed = CHECKSUM_UNNECESSARY;
+- else
+- skb->ip_summed = SW_CHECKSUMMING;
+- }
+- return vlan_id;
+-}
+-
+-static void
+-qeth_process_inbound_buffer(struct qeth_card *card,
+- struct qeth_qdio_buffer *buf, int index)
+-{
+- struct qdio_buffer_element *element;
+- struct sk_buff *skb;
+- struct qeth_hdr *hdr;
+- int offset;
+- int rxrc;
+- __u16 vlan_tag = 0;
+-
+- /* get first element of current buffer */
+- element = (struct qdio_buffer_element *)&buf->buffer->element[0];
+- offset = 0;
+- if (card->options.performance_stats)
+- card->perf_stats.bufs_rec++;
+- while((skb = qeth_get_next_skb(card, buf->buffer, &element,
+- &offset, &hdr))) {
+- skb->dev = card->dev;
+- if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
+- qeth_layer2_rebuild_skb(card, skb, hdr);
+- else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3)
+- vlan_tag = qeth_rebuild_skb(card, skb, hdr);
+- else if (hdr->hdr.osn.id == QETH_HEADER_TYPE_OSN) {
+- skb_push(skb, sizeof(struct qeth_hdr));
+- skb_copy_to_linear_data(skb, hdr,
+- sizeof(struct qeth_hdr));
+- } else { /* unknown header type */
+- dev_kfree_skb_any(skb);
+- QETH_DBF_TEXT(trace, 3, "inbunkno");
+- QETH_DBF_HEX(control, 3, hdr, QETH_DBF_CONTROL_LEN);
+- continue;
+- }
+- /* is device UP ? */
+- if (!(card->dev->flags & IFF_UP)){
+- dev_kfree_skb_any(skb);
+- continue;
+- }
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- rxrc = card->osn_info.data_cb(skb);
+- else
+-#ifdef CONFIG_QETH_VLAN
+- if (vlan_tag)
+- if (card->vlangrp)
+- vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag);
+- else {
+- dev_kfree_skb_any(skb);
+- continue;
+- }
+- else
+-#endif
+- rxrc = netif_rx(skb);
+- card->dev->last_rx = jiffies;
+- card->stats.rx_packets++;
+- card->stats.rx_bytes += skb->len;
+- }
+-}
+-
+-static int
+-qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf)
+-{
+- struct qeth_buffer_pool_entry *pool_entry;
+- int i;
+-
+- pool_entry = qeth_find_free_buffer_pool_entry(card);
+- if (!pool_entry)
+- return 1;
+- /*
+- * since the buffer is accessed only from the input_tasklet
+- * there shouldn't be a need to synchronize; also, since we use
+- * the QETH_IN_BUF_REQUEUE_THRESHOLD we should never run out off
+- * buffers
+- */
+- BUG_ON(!pool_entry);
+-
+- buf->pool_entry = pool_entry;
+- for(i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i){
+- buf->buffer->element[i].length = PAGE_SIZE;
+- buf->buffer->element[i].addr = pool_entry->elements[i];
+- if (i == QETH_MAX_BUFFER_ELEMENTS(card) - 1)
+- buf->buffer->element[i].flags = SBAL_FLAGS_LAST_ENTRY;
+- else
+- buf->buffer->element[i].flags = 0;
+- }
+- buf->state = QETH_QDIO_BUF_EMPTY;
+- return 0;
+-}
+-
+-static void
+-qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
+- struct qeth_qdio_out_buffer *buf)
+-{
+- int i;
+- struct sk_buff *skb;
+-
+- /* is PCI flag set on buffer? */
+- if (buf->buffer->element[0].flags & 0x40)
+- atomic_dec(&queue->set_pci_flags_count);
+-
+- while ((skb = skb_dequeue(&buf->skb_list))){
+- atomic_dec(&skb->users);
+- dev_kfree_skb_any(skb);
+- }
+- qeth_eddp_buf_release_contexts(buf);
+- for(i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i){
+- buf->buffer->element[i].length = 0;
+- buf->buffer->element[i].addr = NULL;
+- buf->buffer->element[i].flags = 0;
+- }
+- buf->next_element_to_fill = 0;
+- atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
+-}
+-
+-static void
+-qeth_queue_input_buffer(struct qeth_card *card, int index)
+-{
+- struct qeth_qdio_q *queue = card->qdio.in_q;
+- int count;
+- int i;
+- int rc;
+- int newcount = 0;
+-
+- QETH_DBF_TEXT(trace,6,"queinbuf");
+- count = (index < queue->next_buf_to_init)?
+- card->qdio.in_buf_pool.buf_count -
+- (queue->next_buf_to_init - index) :
+- card->qdio.in_buf_pool.buf_count -
+- (queue->next_buf_to_init + QDIO_MAX_BUFFERS_PER_Q - index);
+- /* only requeue at a certain threshold to avoid SIGAs */
+- if (count >= QETH_IN_BUF_REQUEUE_THRESHOLD(card)){
+- for (i = queue->next_buf_to_init;
+- i < queue->next_buf_to_init + count; ++i) {
+- if (qeth_init_input_buffer(card,
+- &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q])) {
+- break;
+- } else {
+- newcount++;
+- }
+- }
+-
+- if (newcount < count) {
+- /* we are in memory shortage so we switch back to
+- traditional skb allocation and drop packages */
+- if (!atomic_read(&card->force_alloc_skb) &&
+- net_ratelimit())
+- PRINT_WARN("Switch to alloc skb\n");
+- atomic_set(&card->force_alloc_skb, 3);
+- count = newcount;
+- } else {
+- if ((atomic_read(&card->force_alloc_skb) == 1) &&
+- net_ratelimit())
+- PRINT_WARN("Switch to sg\n");
+- atomic_add_unless(&card->force_alloc_skb, -1, 0);
+- }
+-
+- /*
+- * according to old code it should be avoided to requeue all
+- * 128 buffers in order to benefit from PCI avoidance.
+- * this function keeps at least one buffer (the buffer at
+- * 'index') un-requeued -> this buffer is the first buffer that
+- * will be requeued the next time
+- */
+- if (card->options.performance_stats) {
+- card->perf_stats.inbound_do_qdio_cnt++;
+- card->perf_stats.inbound_do_qdio_start_time =
+- qeth_get_micros();
+- }
+- rc = do_QDIO(CARD_DDEV(card),
+- QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT,
+- 0, queue->next_buf_to_init, count, NULL);
+- if (card->options.performance_stats)
+- card->perf_stats.inbound_do_qdio_time +=
+- qeth_get_micros() -
+- card->perf_stats.inbound_do_qdio_start_time;
+- if (rc){
+- PRINT_WARN("qeth_queue_input_buffer's do_QDIO "
+- "return %i (device %s).\n",
+- rc, CARD_DDEV_ID(card));
+- QETH_DBF_TEXT(trace,2,"qinberr");
+- QETH_DBF_TEXT_(trace,2,"%s",CARD_BUS_ID(card));
+- }
+- queue->next_buf_to_init = (queue->next_buf_to_init + count) %
+- QDIO_MAX_BUFFERS_PER_Q;
+- }
+-}
+-
+-static inline void
+-qeth_put_buffer_pool_entry(struct qeth_card *card,
+- struct qeth_buffer_pool_entry *entry)
+-{
+- QETH_DBF_TEXT(trace, 6, "ptbfplen");
+- list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list);
+-}
+-
+-static void
+-qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status,
+- unsigned int qdio_err, unsigned int siga_err,
+- unsigned int queue, int first_element, int count,
+- unsigned long card_ptr)
+-{
+- struct net_device *net_dev;
+- struct qeth_card *card;
+- struct qeth_qdio_buffer *buffer;
+- int index;
+- int i;
+-
+- QETH_DBF_TEXT(trace, 6, "qdinput");
+- card = (struct qeth_card *) card_ptr;
+- net_dev = card->dev;
+- if (card->options.performance_stats) {
+- card->perf_stats.inbound_cnt++;
+- card->perf_stats.inbound_start_time = qeth_get_micros();
+- }
+- if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
+- if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
+- QETH_DBF_TEXT(trace, 1,"qdinchk");
+- QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
+- QETH_DBF_TEXT_(trace,1,"%04X%04X",first_element,count);
+- QETH_DBF_TEXT_(trace,1,"%04X%04X", queue, status);
+- qeth_schedule_recovery(card);
+- return;
+- }
+- }
+- for (i = first_element; i < (first_element + count); ++i) {
+- index = i % QDIO_MAX_BUFFERS_PER_Q;
+- buffer = &card->qdio.in_q->bufs[index];
+- if (!((status & QDIO_STATUS_LOOK_FOR_ERROR) &&
+- qeth_check_qdio_errors(buffer->buffer,
+- qdio_err, siga_err,"qinerr")))
+- qeth_process_inbound_buffer(card, buffer, index);
+- /* clear buffer and give back to hardware */
+- qeth_put_buffer_pool_entry(card, buffer->pool_entry);
+- qeth_queue_input_buffer(card, index);
+- }
+- if (card->options.performance_stats)
+- card->perf_stats.inbound_time += qeth_get_micros() -
+- card->perf_stats.inbound_start_time;
+-}
+-
+-static int
+-qeth_handle_send_error(struct qeth_card *card,
+- struct qeth_qdio_out_buffer *buffer,
+- unsigned int qdio_err, unsigned int siga_err)
+-{
+- int sbalf15 = buffer->buffer->element[15].flags & 0xff;
+- int cc = siga_err & 3;
+-
+- QETH_DBF_TEXT(trace, 6, "hdsnderr");
+- qeth_check_qdio_errors(buffer->buffer, qdio_err, siga_err, "qouterr");
+- switch (cc) {
+- case 0:
+- if (qdio_err){
+- QETH_DBF_TEXT(trace, 1,"lnkfail");
+- QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
+- QETH_DBF_TEXT_(trace,1,"%04x %02x",
+- (u16)qdio_err, (u8)sbalf15);
+- return QETH_SEND_ERROR_LINK_FAILURE;
+- }
+- return QETH_SEND_ERROR_NONE;
+- case 2:
+- if (siga_err & QDIO_SIGA_ERROR_B_BIT_SET) {
+- QETH_DBF_TEXT(trace, 1, "SIGAcc2B");
+- QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
+- return QETH_SEND_ERROR_KICK_IT;
+- }
+- if ((sbalf15 >= 15) && (sbalf15 <= 31))
+- return QETH_SEND_ERROR_RETRY;
+- return QETH_SEND_ERROR_LINK_FAILURE;
+- /* look at qdio_error and sbalf 15 */
+- case 1:
+- QETH_DBF_TEXT(trace, 1, "SIGAcc1");
+- QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
+- return QETH_SEND_ERROR_LINK_FAILURE;
+- case 3:
+- default:
+- QETH_DBF_TEXT(trace, 1, "SIGAcc3");
+- QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
+- return QETH_SEND_ERROR_KICK_IT;
+- }
+-}
+-
+-void
+-qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
+- int index, int count)
+-{
+- struct qeth_qdio_out_buffer *buf;
+- int rc;
+- int i;
+- unsigned int qdio_flags;
+-
+- QETH_DBF_TEXT(trace, 6, "flushbuf");
+-
+- for (i = index; i < index + count; ++i) {
+- buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
+- buf->buffer->element[buf->next_element_to_fill - 1].flags |=
+- SBAL_FLAGS_LAST_ENTRY;
+-
+- if (queue->card->info.type == QETH_CARD_TYPE_IQD)
+- continue;
+-
+- if (!queue->do_pack){
+- if ((atomic_read(&queue->used_buffers) >=
+- (QETH_HIGH_WATERMARK_PACK -
+- QETH_WATERMARK_PACK_FUZZ)) &&
+- !atomic_read(&queue->set_pci_flags_count)){
+- /* it's likely that we'll go to packing
+- * mode soon */
+- atomic_inc(&queue->set_pci_flags_count);
+- buf->buffer->element[0].flags |= 0x40;
+- }
+- } else {
+- if (!atomic_read(&queue->set_pci_flags_count)){
+- /*
+- * there's no outstanding PCI any more, so we
+- * have to request a PCI to be sure that the PCI
+- * will wake at some time in the future then we
+- * can flush packed buffers that might still be
+- * hanging around, which can happen if no
+- * further send was requested by the stack
+- */
+- atomic_inc(&queue->set_pci_flags_count);
+- buf->buffer->element[0].flags |= 0x40;
+- }
+- }
+- }
+-
+- queue->card->dev->trans_start = jiffies;
+- if (queue->card->options.performance_stats) {
+- queue->card->perf_stats.outbound_do_qdio_cnt++;
+- queue->card->perf_stats.outbound_do_qdio_start_time =
+- qeth_get_micros();
+- }
+- qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
+- if (under_int)
+- qdio_flags |= QDIO_FLAG_UNDER_INTERRUPT;
+- if (atomic_read(&queue->set_pci_flags_count))
+- qdio_flags |= QDIO_FLAG_PCI_OUT;
+- rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags,
+- queue->queue_no, index, count, NULL);
+- if (queue->card->options.performance_stats)
+- queue->card->perf_stats.outbound_do_qdio_time +=
+- qeth_get_micros() -
+- queue->card->perf_stats.outbound_do_qdio_start_time;
+- if (rc){
+- QETH_DBF_TEXT(trace, 2, "flushbuf");
+- QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+- QETH_DBF_TEXT_(trace, 2, "%s", CARD_DDEV_ID(queue->card));
+- queue->card->stats.tx_errors += count;
+- /* this must not happen under normal circumstances. if it
+- * happens something is really wrong -> recover */
+- qeth_schedule_recovery(queue->card);
+- return;
+- }
+- atomic_add(count, &queue->used_buffers);
+- if (queue->card->options.performance_stats)
+- queue->card->perf_stats.bufs_sent += count;
+-}
+-
+-/*
+- * Switched to packing state if the number of used buffers on a queue
+- * reaches a certain limit.
+- */
+-static void
+-qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue)
+-{
+- if (!queue->do_pack) {
+- if (atomic_read(&queue->used_buffers)
+- >= QETH_HIGH_WATERMARK_PACK){
+- /* switch non-PACKING -> PACKING */
+- QETH_DBF_TEXT(trace, 6, "np->pack");
+- if (queue->card->options.performance_stats)
+- queue->card->perf_stats.sc_dp_p++;
+- queue->do_pack = 1;
+- }
+- }
+-}
+-
+-/*
+- * Switches from packing to non-packing mode. If there is a packing
+- * buffer on the queue this buffer will be prepared to be flushed.
+- * In that case 1 is returned to inform the caller. If no buffer
+- * has to be flushed, zero is returned.
+- */
+-static int
+-qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
+-{
+- struct qeth_qdio_out_buffer *buffer;
+- int flush_count = 0;
+-
+- if (queue->do_pack) {
+- if (atomic_read(&queue->used_buffers)
+- <= QETH_LOW_WATERMARK_PACK) {
+- /* switch PACKING -> non-PACKING */
+- QETH_DBF_TEXT(trace, 6, "pack->np");
+- if (queue->card->options.performance_stats)
+- queue->card->perf_stats.sc_p_dp++;
+- queue->do_pack = 0;
+- /* flush packing buffers */
+- buffer = &queue->bufs[queue->next_buf_to_fill];
+- if ((atomic_read(&buffer->state) ==
+- QETH_QDIO_BUF_EMPTY) &&
+- (buffer->next_element_to_fill > 0)) {
+- atomic_set(&buffer->state,QETH_QDIO_BUF_PRIMED);
+- flush_count++;
+- queue->next_buf_to_fill =
+- (queue->next_buf_to_fill + 1) %
+- QDIO_MAX_BUFFERS_PER_Q;
+- }
+- }
+- }
+- return flush_count;
+-}
+-
+-/*
+- * Called to flush a packing buffer if no more pci flags are on the queue.
+- * Checks if there is a packing buffer and prepares it to be flushed.
+- * In that case returns 1, otherwise zero.
+- */
+-static int
+-qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue)
+-{
+- struct qeth_qdio_out_buffer *buffer;
+-
+- buffer = &queue->bufs[queue->next_buf_to_fill];
+- if((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
+- (buffer->next_element_to_fill > 0)){
+- /* it's a packing buffer */
+- atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
+- queue->next_buf_to_fill =
+- (queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q;
+- return 1;
+- }
+- return 0;
+-}
+-
+-static void
+-qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
+-{
+- int index;
+- int flush_cnt = 0;
+- int q_was_packing = 0;
+-
+- /*
+- * check if weed have to switch to non-packing mode or if
+- * we have to get a pci flag out on the queue
+- */
+- if ((atomic_read(&queue->used_buffers) <= QETH_LOW_WATERMARK_PACK) ||
+- !atomic_read(&queue->set_pci_flags_count)){
+- if (atomic_xchg(&queue->state, QETH_OUT_Q_LOCKED_FLUSH) ==
+- QETH_OUT_Q_UNLOCKED) {
+- /*
+- * If we get in here, there was no action in
+- * do_send_packet. So, we check if there is a
+- * packing buffer to be flushed here.
+- */
+- netif_stop_queue(queue->card->dev);
+- index = queue->next_buf_to_fill;
+- q_was_packing = queue->do_pack;
+- flush_cnt += qeth_switch_to_nonpacking_if_needed(queue);
+- if (!flush_cnt &&
+- !atomic_read(&queue->set_pci_flags_count))
+- flush_cnt +=
+- qeth_flush_buffers_on_no_pci(queue);
+- if (queue->card->options.performance_stats &&
+- q_was_packing)
+- queue->card->perf_stats.bufs_sent_pack +=
+- flush_cnt;
+- if (flush_cnt)
+- qeth_flush_buffers(queue, 1, index, flush_cnt);
+- atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+- }
+- }
+-}
+-
+-static void
+-qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status,
+- unsigned int qdio_error, unsigned int siga_error,
+- unsigned int __queue, int first_element, int count,
+- unsigned long card_ptr)
+-{
+- struct qeth_card *card = (struct qeth_card *) card_ptr;
+- struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue];
+- struct qeth_qdio_out_buffer *buffer;
+- int i;
+-
+- QETH_DBF_TEXT(trace, 6, "qdouhdl");
+- if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
+- if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
+- QETH_DBF_TEXT(trace, 2, "achkcond");
+- QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card));
+- QETH_DBF_TEXT_(trace, 2, "%08x", status);
+- netif_stop_queue(card->dev);
+- qeth_schedule_recovery(card);
+- return;
+- }
+- }
+- if (card->options.performance_stats) {
+- card->perf_stats.outbound_handler_cnt++;
+- card->perf_stats.outbound_handler_start_time =
+- qeth_get_micros();
+- }
+- for(i = first_element; i < (first_element + count); ++i){
+- buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
+- /*we only handle the KICK_IT error by doing a recovery */
+- if (qeth_handle_send_error(card, buffer,
+- qdio_error, siga_error)
+- == QETH_SEND_ERROR_KICK_IT){
+- netif_stop_queue(card->dev);
+- qeth_schedule_recovery(card);
+- return;
+- }
+- qeth_clear_output_buffer(queue, buffer);
+- }
+- atomic_sub(count, &queue->used_buffers);
+- /* check if we need to do something on this outbound queue */
+- if (card->info.type != QETH_CARD_TYPE_IQD)
+- qeth_check_outbound_queue(queue);
+-
+- netif_wake_queue(queue->card->dev);
+- if (card->options.performance_stats)
+- card->perf_stats.outbound_handler_time += qeth_get_micros() -
+- card->perf_stats.outbound_handler_start_time;
+-}
+-
+-static void
+-qeth_create_qib_param_field(struct qeth_card *card, char *param_field)
+-{
+-
+- param_field[0] = _ascebc['P'];
+- param_field[1] = _ascebc['C'];
+- param_field[2] = _ascebc['I'];
+- param_field[3] = _ascebc['T'];
+- *((unsigned int *) (¶m_field[4])) = QETH_PCI_THRESHOLD_A(card);
+- *((unsigned int *) (¶m_field[8])) = QETH_PCI_THRESHOLD_B(card);
+- *((unsigned int *) (¶m_field[12])) = QETH_PCI_TIMER_VALUE(card);
+-}
+-
+-static void
+-qeth_create_qib_param_field_blkt(struct qeth_card *card, char *param_field)
+-{
+- param_field[16] = _ascebc['B'];
+- param_field[17] = _ascebc['L'];
+- param_field[18] = _ascebc['K'];
+- param_field[19] = _ascebc['T'];
+- *((unsigned int *) (¶m_field[20])) = card->info.blkt.time_total;
+- *((unsigned int *) (¶m_field[24])) = card->info.blkt.inter_packet;
+- *((unsigned int *) (¶m_field[28])) = card->info.blkt.inter_packet_jumbo;
+-}
+-
+-static void
+-qeth_initialize_working_pool_list(struct qeth_card *card)
+-{
+- struct qeth_buffer_pool_entry *entry;
+-
+- QETH_DBF_TEXT(trace,5,"inwrklst");
+-
+- list_for_each_entry(entry,
+- &card->qdio.init_pool.entry_list, init_list) {
+- qeth_put_buffer_pool_entry(card,entry);
+- }
+-}
+-
+-static void
+-qeth_clear_working_pool_list(struct qeth_card *card)
+-{
+- struct qeth_buffer_pool_entry *pool_entry, *tmp;
+-
+- QETH_DBF_TEXT(trace,5,"clwrklst");
+- list_for_each_entry_safe(pool_entry, tmp,
+- &card->qdio.in_buf_pool.entry_list, list){
+- list_del(&pool_entry->list);
+- }
+-}
+-
+-static void
+-qeth_free_buffer_pool(struct qeth_card *card)
+-{
+- struct qeth_buffer_pool_entry *pool_entry, *tmp;
+- int i=0;
+- QETH_DBF_TEXT(trace,5,"freepool");
+- list_for_each_entry_safe(pool_entry, tmp,
+- &card->qdio.init_pool.entry_list, init_list){
+- for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i)
+- free_page((unsigned long)pool_entry->elements[i]);
+- list_del(&pool_entry->init_list);
+- kfree(pool_entry);
+- }
+-}
+-
+-static int
+-qeth_alloc_buffer_pool(struct qeth_card *card)
+-{
+- struct qeth_buffer_pool_entry *pool_entry;
+- void *ptr;
+- int i, j;
+-
+- QETH_DBF_TEXT(trace,5,"alocpool");
+- for (i = 0; i < card->qdio.init_pool.buf_count; ++i){
+- pool_entry = kmalloc(sizeof(*pool_entry), GFP_KERNEL);
+- if (!pool_entry){
+- qeth_free_buffer_pool(card);
+- return -ENOMEM;
+- }
+- for(j = 0; j < QETH_MAX_BUFFER_ELEMENTS(card); ++j){
+- ptr = (void *) __get_free_page(GFP_KERNEL|GFP_DMA);
+- if (!ptr) {
+- while (j > 0)
+- free_page((unsigned long)
+- pool_entry->elements[--j]);
+- kfree(pool_entry);
+- qeth_free_buffer_pool(card);
+- return -ENOMEM;
+- }
+- pool_entry->elements[j] = ptr;
+- }
+- list_add(&pool_entry->init_list,
+- &card->qdio.init_pool.entry_list);
+- }
+- return 0;
+-}
+-
+-int
+-qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt)
+-{
+- QETH_DBF_TEXT(trace, 2, "realcbp");
+-
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
+-
+- /* TODO: steel/add buffers from/to a running card's buffer pool (?) */
+- qeth_clear_working_pool_list(card);
+- qeth_free_buffer_pool(card);
+- card->qdio.in_buf_pool.buf_count = bufcnt;
+- card->qdio.init_pool.buf_count = bufcnt;
+- return qeth_alloc_buffer_pool(card);
+-}
+-
+-static int
+-qeth_alloc_qdio_buffers(struct qeth_card *card)
+-{
+- int i, j;
+-
+- QETH_DBF_TEXT(setup, 2, "allcqdbf");
+-
+- if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED,
+- QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED)
+- return 0;
+-
+- card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q),
+- GFP_KERNEL|GFP_DMA);
+- if (!card->qdio.in_q)
+- goto out_nomem;
+- QETH_DBF_TEXT(setup, 2, "inq");
+- QETH_DBF_HEX(setup, 2, &card->qdio.in_q, sizeof(void *));
+- memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q));
+- /* give inbound qeth_qdio_buffers their qdio_buffers */
+- for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
+- card->qdio.in_q->bufs[i].buffer =
+- &card->qdio.in_q->qdio_bufs[i];
+- /* inbound buffer pool */
+- if (qeth_alloc_buffer_pool(card))
+- goto out_freeinq;
+- /* outbound */
+- card->qdio.out_qs =
+- kmalloc(card->qdio.no_out_queues *
+- sizeof(struct qeth_qdio_out_q *), GFP_KERNEL);
+- if (!card->qdio.out_qs)
+- goto out_freepool;
+- for (i = 0; i < card->qdio.no_out_queues; ++i) {
+- card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q),
+- GFP_KERNEL|GFP_DMA);
+- if (!card->qdio.out_qs[i])
+- goto out_freeoutq;
+- QETH_DBF_TEXT_(setup, 2, "outq %i", i);
+- QETH_DBF_HEX(setup, 2, &card->qdio.out_qs[i], sizeof(void *));
+- memset(card->qdio.out_qs[i], 0, sizeof(struct qeth_qdio_out_q));
+- card->qdio.out_qs[i]->queue_no = i;
+- /* give outbound qeth_qdio_buffers their qdio_buffers */
+- for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j){
+- card->qdio.out_qs[i]->bufs[j].buffer =
+- &card->qdio.out_qs[i]->qdio_bufs[j];
+- skb_queue_head_init(&card->qdio.out_qs[i]->bufs[j].
+- skb_list);
+- lockdep_set_class(
+- &card->qdio.out_qs[i]->bufs[j].skb_list.lock,
+- &qdio_out_skb_queue_key);
+- INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list);
+- }
+- }
+- return 0;
+-
+-out_freeoutq:
+- while (i > 0)
+- kfree(card->qdio.out_qs[--i]);
+- kfree(card->qdio.out_qs);
+- card->qdio.out_qs = NULL;
+-out_freepool:
+- qeth_free_buffer_pool(card);
+-out_freeinq:
+- kfree(card->qdio.in_q);
+- card->qdio.in_q = NULL;
+-out_nomem:
+- atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
+- return -ENOMEM;
+-}
+-
+-static void
+-qeth_free_qdio_buffers(struct qeth_card *card)
+-{
+- int i, j;
+-
+- QETH_DBF_TEXT(trace, 2, "freeqdbf");
+- if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
+- QETH_QDIO_UNINITIALIZED)
+- return;
+- kfree(card->qdio.in_q);
+- card->qdio.in_q = NULL;
+- /* inbound buffer pool */
+- qeth_free_buffer_pool(card);
+- /* free outbound qdio_qs */
+- if (card->qdio.out_qs) {
+- for (i = 0; i < card->qdio.no_out_queues; ++i) {
+- for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
+- qeth_clear_output_buffer(card->qdio.out_qs[i],
+- &card->qdio.out_qs[i]->bufs[j]);
+- kfree(card->qdio.out_qs[i]);
+- }
+- kfree(card->qdio.out_qs);
+- card->qdio.out_qs = NULL;
+- }
+-}
+-
+-static void
+-qeth_clear_qdio_buffers(struct qeth_card *card)
+-{
+- int i, j;
+-
+- QETH_DBF_TEXT(trace, 2, "clearqdbf");
+- /* clear outbound buffers to free skbs */
+- for (i = 0; i < card->qdio.no_out_queues; ++i)
+- if (card->qdio.out_qs && card->qdio.out_qs[i]) {
+- for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
+- qeth_clear_output_buffer(card->qdio.out_qs[i],
+- &card->qdio.out_qs[i]->bufs[j]);
+- }
+-}
+-
+-static void
+-qeth_init_qdio_info(struct qeth_card *card)
+-{
+- QETH_DBF_TEXT(setup, 4, "intqdinf");
+- atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
+- /* inbound */
+- card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
+- card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT;
+- card->qdio.in_buf_pool.buf_count = card->qdio.init_pool.buf_count;
+- INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list);
+- INIT_LIST_HEAD(&card->qdio.init_pool.entry_list);
+-}
+-
+-static int
+-qeth_init_qdio_queues(struct qeth_card *card)
+-{
+- int i, j;
+- int rc;
+-
+- QETH_DBF_TEXT(setup, 2, "initqdqs");
+-
+- /* inbound queue */
+- memset(card->qdio.in_q->qdio_bufs, 0,
+- QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
+- qeth_initialize_working_pool_list(card);
+- /*give only as many buffers to hardware as we have buffer pool entries*/
+- for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; ++i)
+- qeth_init_input_buffer(card, &card->qdio.in_q->bufs[i]);
+- card->qdio.in_q->next_buf_to_init = card->qdio.in_buf_pool.buf_count - 1;
+- rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0, 0,
+- card->qdio.in_buf_pool.buf_count - 1, NULL);
+- if (rc) {
+- QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+- return rc;
+- }
+- rc = qdio_synchronize(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0);
+- if (rc) {
+- QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+- return rc;
+- }
+- /* outbound queue */
+- for (i = 0; i < card->qdio.no_out_queues; ++i){
+- memset(card->qdio.out_qs[i]->qdio_bufs, 0,
+- QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
+- for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j){
+- qeth_clear_output_buffer(card->qdio.out_qs[i],
+- &card->qdio.out_qs[i]->bufs[j]);
+- }
+- card->qdio.out_qs[i]->card = card;
+- card->qdio.out_qs[i]->next_buf_to_fill = 0;
+- card->qdio.out_qs[i]->do_pack = 0;
+- atomic_set(&card->qdio.out_qs[i]->used_buffers,0);
+- atomic_set(&card->qdio.out_qs[i]->set_pci_flags_count, 0);
+- atomic_set(&card->qdio.out_qs[i]->state,
+- QETH_OUT_Q_UNLOCKED);
+- }
+- return 0;
+-}
+-
+-static int
+-qeth_qdio_establish(struct qeth_card *card)
+-{
+- struct qdio_initialize init_data;
+- char *qib_param_field;
+- struct qdio_buffer **in_sbal_ptrs;
+- struct qdio_buffer **out_sbal_ptrs;
+- int i, j, k;
+- int rc = 0;
+-
+- QETH_DBF_TEXT(setup, 2, "qdioest");
+-
+- qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char),
+- GFP_KERNEL);
+- if (!qib_param_field)
+- return -ENOMEM;
+-
+- qeth_create_qib_param_field(card, qib_param_field);
+- qeth_create_qib_param_field_blkt(card, qib_param_field);
+-
+- in_sbal_ptrs = kmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(void *),
+- GFP_KERNEL);
+- if (!in_sbal_ptrs) {
+- kfree(qib_param_field);
+- return -ENOMEM;
+- }
+- for(i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
+- in_sbal_ptrs[i] = (struct qdio_buffer *)
+- virt_to_phys(card->qdio.in_q->bufs[i].buffer);
+-
+- out_sbal_ptrs =
+- kmalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q *
+- sizeof(void *), GFP_KERNEL);
+- if (!out_sbal_ptrs) {
+- kfree(in_sbal_ptrs);
+- kfree(qib_param_field);
+- return -ENOMEM;
+- }
+- for(i = 0, k = 0; i < card->qdio.no_out_queues; ++i)
+- for(j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k){
+- out_sbal_ptrs[k] = (struct qdio_buffer *)
+- virt_to_phys(card->qdio.out_qs[i]->
+- bufs[j].buffer);
+- }
+-
+- memset(&init_data, 0, sizeof(struct qdio_initialize));
+- init_data.cdev = CARD_DDEV(card);
+- init_data.q_format = qeth_get_qdio_q_format(card);
+- init_data.qib_param_field_format = 0;
+- init_data.qib_param_field = qib_param_field;
+- init_data.min_input_threshold = QETH_MIN_INPUT_THRESHOLD;
+- init_data.max_input_threshold = QETH_MAX_INPUT_THRESHOLD;
+- init_data.min_output_threshold = QETH_MIN_OUTPUT_THRESHOLD;
+- init_data.max_output_threshold = QETH_MAX_OUTPUT_THRESHOLD;
+- init_data.no_input_qs = 1;
+- init_data.no_output_qs = card->qdio.no_out_queues;
+- init_data.input_handler = (qdio_handler_t *)
+- qeth_qdio_input_handler;
+- init_data.output_handler = (qdio_handler_t *)
+- qeth_qdio_output_handler;
+- init_data.int_parm = (unsigned long) card;
+- init_data.flags = QDIO_INBOUND_0COPY_SBALS |
+- QDIO_OUTBOUND_0COPY_SBALS |
+- QDIO_USE_OUTBOUND_PCIS;
+- init_data.input_sbal_addr_array = (void **) in_sbal_ptrs;
+- init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
+-
+- if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED,
+- QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED)
+- if ((rc = qdio_initialize(&init_data)))
+- atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
+-
+- kfree(out_sbal_ptrs);
+- kfree(in_sbal_ptrs);
+- kfree(qib_param_field);
+- return rc;
+-}
+-
+-static int
+-qeth_qdio_activate(struct qeth_card *card)
+-{
+- QETH_DBF_TEXT(setup,3,"qdioact");
+- return qdio_activate(CARD_DDEV(card), 0);
+-}
+-
+-static int
+-qeth_clear_channel(struct qeth_channel *channel)
+-{
+- unsigned long flags;
+- struct qeth_card *card;
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"clearch");
+- card = CARD_FROM_CDEV(channel->ccwdev);
+- spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+- rc = ccw_device_clear(channel->ccwdev, QETH_CLEAR_CHANNEL_PARM);
+- spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+-
+- if (rc)
+- return rc;
+- rc = wait_event_interruptible_timeout(card->wait_q,
+- channel->state==CH_STATE_STOPPED, QETH_TIMEOUT);
+- if (rc == -ERESTARTSYS)
+- return rc;
+- if (channel->state != CH_STATE_STOPPED)
+- return -ETIME;
+- channel->state = CH_STATE_DOWN;
+- return 0;
+-}
+-
+-static int
+-qeth_halt_channel(struct qeth_channel *channel)
+-{
+- unsigned long flags;
+- struct qeth_card *card;
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"haltch");
+- card = CARD_FROM_CDEV(channel->ccwdev);
+- spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+- rc = ccw_device_halt(channel->ccwdev, QETH_HALT_CHANNEL_PARM);
+- spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+-
+- if (rc)
+- return rc;
+- rc = wait_event_interruptible_timeout(card->wait_q,
+- channel->state==CH_STATE_HALTED, QETH_TIMEOUT);
+- if (rc == -ERESTARTSYS)
+- return rc;
+- if (channel->state != CH_STATE_HALTED)
+- return -ETIME;
+- return 0;
+-}
+-
+-static int
+-qeth_halt_channels(struct qeth_card *card)
+-{
+- int rc1 = 0, rc2=0, rc3 = 0;
+-
+- QETH_DBF_TEXT(trace,3,"haltchs");
+- rc1 = qeth_halt_channel(&card->read);
+- rc2 = qeth_halt_channel(&card->write);
+- rc3 = qeth_halt_channel(&card->data);
+- if (rc1)
+- return rc1;
+- if (rc2)
+- return rc2;
+- return rc3;
+-}
+-static int
+-qeth_clear_channels(struct qeth_card *card)
+-{
+- int rc1 = 0, rc2=0, rc3 = 0;
+-
+- QETH_DBF_TEXT(trace,3,"clearchs");
+- rc1 = qeth_clear_channel(&card->read);
+- rc2 = qeth_clear_channel(&card->write);
+- rc3 = qeth_clear_channel(&card->data);
+- if (rc1)
+- return rc1;
+- if (rc2)
+- return rc2;
+- return rc3;
+-}
+-
+-static int
+-qeth_clear_halt_card(struct qeth_card *card, int halt)
+-{
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace,3,"clhacrd");
+- QETH_DBF_HEX(trace, 3, &card, sizeof(void *));
+-
+- if (halt)
+- rc = qeth_halt_channels(card);
+- if (rc)
+- return rc;
+- return qeth_clear_channels(card);
+-}
+-
+-static int
+-qeth_qdio_clear_card(struct qeth_card *card, int use_halt)
+-{
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace,3,"qdioclr");
+- switch (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ESTABLISHED,
+- QETH_QDIO_CLEANING)) {
+- case QETH_QDIO_ESTABLISHED:
+- if ((rc = qdio_cleanup(CARD_DDEV(card),
+- (card->info.type == QETH_CARD_TYPE_IQD) ?
+- QDIO_FLAG_CLEANUP_USING_HALT :
+- QDIO_FLAG_CLEANUP_USING_CLEAR)))
+- QETH_DBF_TEXT_(trace, 3, "1err%d", rc);
+- atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
+- break;
+- case QETH_QDIO_CLEANING:
+- return rc;
+- default:
+- break;
+- }
+- if ((rc = qeth_clear_halt_card(card, use_halt)))
+- QETH_DBF_TEXT_(trace, 3, "2err%d", rc);
+- card->state = CARD_STATE_DOWN;
+- return rc;
+-}
+-
+-static int
+-qeth_dm_act(struct qeth_card *card)
+-{
+- int rc;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(setup,2,"dmact");
+-
+- iob = qeth_wait_for_buffer(&card->write);
+- memcpy(iob->data, DM_ACT, DM_ACT_SIZE);
+-
+- memcpy(QETH_DM_ACT_DEST_ADDR(iob->data),
+- &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_DM_ACT_CONNECTION_TOKEN(iob->data),
+- &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+- rc = qeth_send_control_data(card, DM_ACT_SIZE, iob, NULL, NULL);
+- return rc;
+-}
+-
+-static int
+-qeth_mpc_initialize(struct qeth_card *card)
+-{
+- int rc;
+-
+- QETH_DBF_TEXT(setup,2,"mpcinit");
+-
+- if ((rc = qeth_issue_next_read(card))){
+- QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+- return rc;
+- }
+- if ((rc = qeth_cm_enable(card))){
+- QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+- goto out_qdio;
+- }
+- if ((rc = qeth_cm_setup(card))){
+- QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+- goto out_qdio;
+- }
+- if ((rc = qeth_ulp_enable(card))){
+- QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
+- goto out_qdio;
+- }
+- if ((rc = qeth_ulp_setup(card))){
+- QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
+- goto out_qdio;
+- }
+- if ((rc = qeth_alloc_qdio_buffers(card))){
+- QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
+- goto out_qdio;
+- }
+- if ((rc = qeth_qdio_establish(card))){
+- QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
+- qeth_free_qdio_buffers(card);
+- goto out_qdio;
+- }
+- if ((rc = qeth_qdio_activate(card))){
+- QETH_DBF_TEXT_(setup, 2, "7err%d", rc);
+- goto out_qdio;
+- }
+- if ((rc = qeth_dm_act(card))){
+- QETH_DBF_TEXT_(setup, 2, "8err%d", rc);
+- goto out_qdio;
+- }
+-
+- return 0;
+-out_qdio:
+- qeth_qdio_clear_card(card, card->info.type!=QETH_CARD_TYPE_IQD);
+- return rc;
+-}
+-
+-static struct net_device *
+-qeth_get_netdevice(enum qeth_card_types type, enum qeth_link_types linktype)
+-{
+- struct net_device *dev = NULL;
+-
+- switch (type) {
+- case QETH_CARD_TYPE_OSAE:
+- switch (linktype) {
+- case QETH_LINK_TYPE_LANE_TR:
+- case QETH_LINK_TYPE_HSTR:
+-#ifdef CONFIG_TR
+- dev = alloc_trdev(0);
+-#endif /* CONFIG_TR */
+- break;
+- default:
+- dev = alloc_etherdev(0);
+- }
+- break;
+- case QETH_CARD_TYPE_IQD:
+- dev = alloc_netdev(0, "hsi%d", ether_setup);
+- break;
+- case QETH_CARD_TYPE_OSN:
+- dev = alloc_netdev(0, "osn%d", ether_setup);
+- break;
+- default:
+- dev = alloc_etherdev(0);
+- }
+- return dev;
+-}
+-
+-/*hard_header fake function; used in case fake_ll is set */
+-static int
+-qeth_fake_header(struct sk_buff *skb, struct net_device *dev,
+- unsigned short type, const void *daddr, const void *saddr,
+- unsigned len)
+-{
+- if(dev->type == ARPHRD_IEEE802_TR){
+- struct trh_hdr *hdr;
+- hdr = (struct trh_hdr *)skb_push(skb, QETH_FAKE_LL_LEN_TR);
+- memcpy(hdr->saddr, dev->dev_addr, TR_ALEN);
+- memcpy(hdr->daddr, "FAKELL", TR_ALEN);
+- return QETH_FAKE_LL_LEN_TR;
+-
+- } else {
+- struct ethhdr *hdr;
+- hdr = (struct ethhdr *)skb_push(skb, QETH_FAKE_LL_LEN_ETH);
+- memcpy(hdr->h_source, dev->dev_addr, ETH_ALEN);
+- memcpy(hdr->h_dest, "FAKELL", ETH_ALEN);
+- if (type != ETH_P_802_3)
+- hdr->h_proto = htons(type);
+- else
+- hdr->h_proto = htons(len);
+- return QETH_FAKE_LL_LEN_ETH;
+-
+- }
+-}
+-
+-static const struct header_ops qeth_fake_ops = {
+- .create = qeth_fake_header,
+- .parse = qeth_hard_header_parse,
+-};
+-
+-static int
+-qeth_send_packet(struct qeth_card *, struct sk_buff *);
+-
+-static int
+-qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+-{
+- int rc;
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT(trace, 6, "hrdstxmi");
+- card = (struct qeth_card *)dev->priv;
+- if (skb==NULL) {
+- card->stats.tx_dropped++;
+- card->stats.tx_errors++;
+- /* return OK; otherwise ksoftirqd goes to 100% */
+- return NETDEV_TX_OK;
+- }
+- if ((card->state != CARD_STATE_UP) || !card->lan_online) {
+- card->stats.tx_dropped++;
+- card->stats.tx_errors++;
+- card->stats.tx_carrier_errors++;
+- dev_kfree_skb_any(skb);
+- /* return OK; otherwise ksoftirqd goes to 100% */
+- return NETDEV_TX_OK;
+- }
+- if (card->options.performance_stats) {
+- card->perf_stats.outbound_cnt++;
+- card->perf_stats.outbound_start_time = qeth_get_micros();
+- }
+- netif_stop_queue(dev);
+- if ((rc = qeth_send_packet(card, skb))) {
+- if (rc == -EBUSY) {
+- return NETDEV_TX_BUSY;
+- } else {
+- card->stats.tx_errors++;
+- card->stats.tx_dropped++;
+- dev_kfree_skb_any(skb);
+- /*set to OK; otherwise ksoftirqd goes to 100% */
+- rc = NETDEV_TX_OK;
+- }
+- }
+- netif_wake_queue(dev);
+- if (card->options.performance_stats)
+- card->perf_stats.outbound_time += qeth_get_micros() -
+- card->perf_stats.outbound_start_time;
+- return rc;
+-}
+-
+-static int
+-qeth_verify_vlan_dev(struct net_device *dev, struct qeth_card *card)
+-{
+- int rc = 0;
+-#ifdef CONFIG_QETH_VLAN
+- struct vlan_group *vg;
+- int i;
+-
+- if (!(vg = card->vlangrp))
+- return rc;
+-
+- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++){
+- if (vlan_group_get_device(vg, i) == dev){
+- rc = QETH_VLAN_CARD;
+- break;
+- }
+- }
+- if (rc && !(vlan_dev_info(dev)->real_dev->priv == (void *)card))
+- return 0;
+-
+-#endif
+- return rc;
+-}
+-
+-static int
+-qeth_verify_dev(struct net_device *dev)
+-{
+- struct qeth_card *card;
+- unsigned long flags;
+- int rc = 0;
+-
+- read_lock_irqsave(&qeth_card_list.rwlock, flags);
+- list_for_each_entry(card, &qeth_card_list.list, list){
+- if (card->dev == dev){
+- rc = QETH_REAL_CARD;
+- break;
+- }
+- rc = qeth_verify_vlan_dev(dev, card);
+- if (rc)
+- break;
+- }
+- read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+-
+- return rc;
+-}
+-
+-static struct qeth_card *
+-qeth_get_card_from_dev(struct net_device *dev)
+-{
+- struct qeth_card *card = NULL;
+- int rc;
+-
+- rc = qeth_verify_dev(dev);
+- if (rc == QETH_REAL_CARD)
+- card = (struct qeth_card *)dev->priv;
+- else if (rc == QETH_VLAN_CARD)
+- card = (struct qeth_card *)
+- vlan_dev_info(dev)->real_dev->priv;
+-
+- QETH_DBF_TEXT_(trace, 4, "%d", rc);
+- return card ;
+-}
+-
+-static void
+-qeth_tx_timeout(struct net_device *dev)
+-{
+- struct qeth_card *card;
+-
+- card = (struct qeth_card *) dev->priv;
+- card->stats.tx_errors++;
+- qeth_schedule_recovery(card);
+-}
+-
+-static int
+-qeth_open(struct net_device *dev)
+-{
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT(trace, 4, "qethopen");
+-
+- card = (struct qeth_card *) dev->priv;
+-
+- if (card->state != CARD_STATE_SOFTSETUP)
+- return -ENODEV;
+-
+- if ( (card->info.type != QETH_CARD_TYPE_OSN) &&
+- (card->options.layer2) &&
+- (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) {
+- QETH_DBF_TEXT(trace,4,"nomacadr");
+- return -EPERM;
+- }
+- card->data.state = CH_STATE_UP;
+- card->state = CARD_STATE_UP;
+- card->dev->flags |= IFF_UP;
+- netif_start_queue(dev);
+-
+- if (!card->lan_online && netif_carrier_ok(dev))
+- netif_carrier_off(dev);
+- return 0;
+-}
+-
+-static int
+-qeth_stop(struct net_device *dev)
+-{
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT(trace, 4, "qethstop");
+-
+- card = (struct qeth_card *) dev->priv;
+-
+- netif_tx_disable(dev);
+- card->dev->flags &= ~IFF_UP;
+- if (card->state == CARD_STATE_UP)
+- card->state = CARD_STATE_SOFTSETUP;
+- return 0;
+-}
+-
+-static int
+-qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
+-{
+- int cast_type = RTN_UNSPEC;
+-
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- return cast_type;
+-
+- if (skb->dst && skb->dst->neighbour){
+- cast_type = skb->dst->neighbour->type;
+- if ((cast_type == RTN_BROADCAST) ||
+- (cast_type == RTN_MULTICAST) ||
+- (cast_type == RTN_ANYCAST))
+- return cast_type;
+- else
+- return RTN_UNSPEC;
+- }
+- /* try something else */
+- if (skb->protocol == ETH_P_IPV6)
+- return (skb_network_header(skb)[24] == 0xff) ?
+- RTN_MULTICAST : 0;
+- else if (skb->protocol == ETH_P_IP)
+- return ((skb_network_header(skb)[16] & 0xf0) == 0xe0) ?
+- RTN_MULTICAST : 0;
+- /* ... */
+- if (!memcmp(skb->data, skb->dev->broadcast, 6))
+- return RTN_BROADCAST;
+- else {
+- u16 hdr_mac;
+-
+- hdr_mac = *((u16 *)skb->data);
+- /* tr multicast? */
+- switch (card->info.link_type) {
+- case QETH_LINK_TYPE_HSTR:
+- case QETH_LINK_TYPE_LANE_TR:
+- if ((hdr_mac == QETH_TR_MAC_NC) ||
+- (hdr_mac == QETH_TR_MAC_C))
+- return RTN_MULTICAST;
+- break;
+- /* eth or so multicast? */
+- default:
+- if ((hdr_mac == QETH_ETH_MAC_V4) ||
+- (hdr_mac == QETH_ETH_MAC_V6))
+- return RTN_MULTICAST;
+- }
+- }
+- return cast_type;
+-}
+-
+-static int
+-qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
+- int ipv, int cast_type)
+-{
+- if (!ipv && (card->info.type == QETH_CARD_TYPE_OSAE))
+- return card->qdio.default_out_queue;
+- switch (card->qdio.no_out_queues) {
+- case 4:
+- if (cast_type && card->info.is_multicast_different)
+- return card->info.is_multicast_different &
+- (card->qdio.no_out_queues - 1);
+- if (card->qdio.do_prio_queueing && (ipv == 4)) {
+- const u8 tos = ip_hdr(skb)->tos;
+-
+- if (card->qdio.do_prio_queueing==QETH_PRIO_Q_ING_TOS){
+- if (tos & IP_TOS_NOTIMPORTANT)
+- return 3;
+- if (tos & IP_TOS_HIGHRELIABILITY)
+- return 2;
+- if (tos & IP_TOS_HIGHTHROUGHPUT)
+- return 1;
+- if (tos & IP_TOS_LOWDELAY)
+- return 0;
+- }
+- if (card->qdio.do_prio_queueing==QETH_PRIO_Q_ING_PREC)
+- return 3 - (tos >> 6);
+- } else if (card->qdio.do_prio_queueing && (ipv == 6)) {
+- /* TODO: IPv6!!! */
+- }
+- return card->qdio.default_out_queue;
+- case 1: /* fallthrough for single-out-queue 1920-device */
+- default:
+- return card->qdio.default_out_queue;
+- }
+-}
+-
+-static inline int
+-qeth_get_ip_version(struct sk_buff *skb)
+-{
+- switch (skb->protocol) {
+- case ETH_P_IPV6:
+- return 6;
+- case ETH_P_IP:
+- return 4;
+- default:
+- return 0;
+- }
+-}
+-
+-static struct qeth_hdr *
+-__qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv)
+-{
+-#ifdef CONFIG_QETH_VLAN
+- u16 *tag;
+- if (card->vlangrp && vlan_tx_tag_present(skb) &&
+- ((ipv == 6) || card->options.layer2) ) {
+- /*
+- * Move the mac addresses (6 bytes src, 6 bytes dest)
+- * to the beginning of the new header. We are using three
+- * memcpys instead of one memmove to save cycles.
+- */
+- skb_push(skb, VLAN_HLEN);
+- skb_copy_to_linear_data(skb, skb->data + 4, 4);
+- skb_copy_to_linear_data_offset(skb, 4, skb->data + 8, 4);
+- skb_copy_to_linear_data_offset(skb, 8, skb->data + 12, 4);
+- tag = (u16 *)(skb->data + 12);
+- /*
+- * first two bytes = ETH_P_8021Q (0x8100)
+- * second two bytes = VLANID
+- */
+- *tag = __constant_htons(ETH_P_8021Q);
+- *(tag + 1) = htons(vlan_tx_tag_get(skb));
+- }
+-#endif
+- return ((struct qeth_hdr *)
+- qeth_push_skb(card, skb, sizeof(struct qeth_hdr)));
+-}
+-
+-static void
+-__qeth_free_new_skb(struct sk_buff *orig_skb, struct sk_buff *new_skb)
+-{
+- if (orig_skb != new_skb)
+- dev_kfree_skb_any(new_skb);
+-}
+-
+-static struct sk_buff *
+-qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb,
+- struct qeth_hdr **hdr, int ipv)
+-{
+- struct sk_buff *new_skb, *new_skb2;
+-
+- QETH_DBF_TEXT(trace, 6, "prepskb");
+- new_skb = skb;
+- new_skb = qeth_pskb_unshare(skb, GFP_ATOMIC);
+- if (!new_skb)
+- return NULL;
+- new_skb2 = qeth_realloc_headroom(card, new_skb,
+- sizeof(struct qeth_hdr));
+- if (!new_skb2) {
+- __qeth_free_new_skb(skb, new_skb);
+- return NULL;
+- }
+- if (new_skb != skb)
+- __qeth_free_new_skb(new_skb2, new_skb);
+- new_skb = new_skb2;
+- *hdr = __qeth_prepare_skb(card, new_skb, ipv);
+- if (*hdr == NULL) {
+- __qeth_free_new_skb(skb, new_skb);
+- return NULL;
+- }
+- return new_skb;
+-}
+-
+-static inline u8
+-qeth_get_qeth_hdr_flags4(int cast_type)
+-{
+- if (cast_type == RTN_MULTICAST)
+- return QETH_CAST_MULTICAST;
+- if (cast_type == RTN_BROADCAST)
+- return QETH_CAST_BROADCAST;
+- return QETH_CAST_UNICAST;
+-}
+-
+-static inline u8
+-qeth_get_qeth_hdr_flags6(int cast_type)
+-{
+- u8 ct = QETH_HDR_PASSTHRU | QETH_HDR_IPV6;
+- if (cast_type == RTN_MULTICAST)
+- return ct | QETH_CAST_MULTICAST;
+- if (cast_type == RTN_ANYCAST)
+- return ct | QETH_CAST_ANYCAST;
+- if (cast_type == RTN_BROADCAST)
+- return ct | QETH_CAST_BROADCAST;
+- return ct | QETH_CAST_UNICAST;
+-}
+-
+-static void
+-qeth_layer2_get_packet_type(struct qeth_card *card, struct qeth_hdr *hdr,
+- struct sk_buff *skb)
+-{
+- __u16 hdr_mac;
+-
+- if (!memcmp(skb->data+QETH_HEADER_SIZE,
+- skb->dev->broadcast,6)) { /* broadcast? */
+- *(__u32 *)hdr->hdr.l2.flags |=
+- QETH_LAYER2_FLAG_BROADCAST << 8;
+- return;
+- }
+- hdr_mac=*((__u16*)skb->data);
+- /* tr multicast? */
+- switch (card->info.link_type) {
+- case QETH_LINK_TYPE_HSTR:
+- case QETH_LINK_TYPE_LANE_TR:
+- if ((hdr_mac == QETH_TR_MAC_NC) ||
+- (hdr_mac == QETH_TR_MAC_C) )
+- *(__u32 *)hdr->hdr.l2.flags |=
+- QETH_LAYER2_FLAG_MULTICAST << 8;
+- else
+- *(__u32 *)hdr->hdr.l2.flags |=
+- QETH_LAYER2_FLAG_UNICAST << 8;
+- break;
+- /* eth or so multicast? */
+- default:
+- if ( (hdr_mac==QETH_ETH_MAC_V4) ||
+- (hdr_mac==QETH_ETH_MAC_V6) )
+- *(__u32 *)hdr->hdr.l2.flags |=
+- QETH_LAYER2_FLAG_MULTICAST << 8;
+- else
+- *(__u32 *)hdr->hdr.l2.flags |=
+- QETH_LAYER2_FLAG_UNICAST << 8;
+- }
+-}
+-
+-static void
+-qeth_layer2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
+- struct sk_buff *skb, int cast_type)
+-{
+- memset(hdr, 0, sizeof(struct qeth_hdr));
+- hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2;
+-
+- /* set byte 0 to "0x02" and byte 3 to casting flags */
+- if (cast_type==RTN_MULTICAST)
+- *(__u32 *)hdr->hdr.l2.flags |= QETH_LAYER2_FLAG_MULTICAST << 8;
+- else if (cast_type==RTN_BROADCAST)
+- *(__u32 *)hdr->hdr.l2.flags |= QETH_LAYER2_FLAG_BROADCAST << 8;
+- else
+- qeth_layer2_get_packet_type(card, hdr, skb);
+-
+- hdr->hdr.l2.pkt_length = skb->len-QETH_HEADER_SIZE;
+-#ifdef CONFIG_QETH_VLAN
+- /* VSWITCH relies on the VLAN
+- * information to be present in
+- * the QDIO header */
+- if ((card->vlangrp != NULL) &&
+- vlan_tx_tag_present(skb)) {
+- *(__u32 *)hdr->hdr.l2.flags |= QETH_LAYER2_FLAG_VLAN << 8;
+- hdr->hdr.l2.vlan_id = vlan_tx_tag_get(skb);
+- }
+-#endif
+-}
+-
+-void
+-qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
+- struct sk_buff *skb, int ipv, int cast_type)
+-{
+- QETH_DBF_TEXT(trace, 6, "fillhdr");
+-
+- memset(hdr, 0, sizeof(struct qeth_hdr));
+- if (card->options.layer2) {
+- qeth_layer2_fill_header(card, hdr, skb, cast_type);
+- return;
+- }
+- hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
+- hdr->hdr.l3.ext_flags = 0;
+-#ifdef CONFIG_QETH_VLAN
+- /*
+- * before we're going to overwrite this location with next hop ip.
+- * v6 uses passthrough, v4 sets the tag in the QDIO header.
+- */
+- if (card->vlangrp && vlan_tx_tag_present(skb)) {
+- hdr->hdr.l3.ext_flags = (ipv == 4) ?
+- QETH_HDR_EXT_VLAN_FRAME :
+- QETH_HDR_EXT_INCLUDE_VLAN_TAG;
+- hdr->hdr.l3.vlan_id = vlan_tx_tag_get(skb);
+- }
+-#endif /* CONFIG_QETH_VLAN */
+- hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr);
+- if (ipv == 4) { /* IPv4 */
+- hdr->hdr.l3.flags = qeth_get_qeth_hdr_flags4(cast_type);
+- memset(hdr->hdr.l3.dest_addr, 0, 12);
+- if ((skb->dst) && (skb->dst->neighbour)) {
+- *((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
+- *((u32 *) skb->dst->neighbour->primary_key);
+- } else {
+- /* fill in destination address used in ip header */
+- *((u32 *)(&hdr->hdr.l3.dest_addr[12])) =
+- ip_hdr(skb)->daddr;
+- }
+- } else if (ipv == 6) { /* IPv6 or passthru */
+- hdr->hdr.l3.flags = qeth_get_qeth_hdr_flags6(cast_type);
+- if ((skb->dst) && (skb->dst->neighbour)) {
+- memcpy(hdr->hdr.l3.dest_addr,
+- skb->dst->neighbour->primary_key, 16);
+- } else {
+- /* fill in destination address used in ip header */
+- memcpy(hdr->hdr.l3.dest_addr,
+- &ipv6_hdr(skb)->daddr, 16);
+- }
+- } else { /* passthrough */
+- if((skb->dev->type == ARPHRD_IEEE802_TR) &&
+- !memcmp(skb->data + sizeof(struct qeth_hdr) +
+- sizeof(__u16), skb->dev->broadcast, 6)) {
+- hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
+- QETH_HDR_PASSTHRU;
+- } else if (!memcmp(skb->data + sizeof(struct qeth_hdr),
+- skb->dev->broadcast, 6)) { /* broadcast? */
+- hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
+- QETH_HDR_PASSTHRU;
+- } else {
+- hdr->hdr.l3.flags = (cast_type == RTN_MULTICAST) ?
+- QETH_CAST_MULTICAST | QETH_HDR_PASSTHRU :
+- QETH_CAST_UNICAST | QETH_HDR_PASSTHRU;
+- }
+- }
+-}
+-
+-static void
+-__qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
+- int is_tso, int *next_element_to_fill)
+-{
+- int length = skb->len;
+- int length_here;
+- int element;
+- char *data;
+- int first_lap ;
+-
+- element = *next_element_to_fill;
+- data = skb->data;
+- first_lap = (is_tso == 0 ? 1 : 0);
+-
+- while (length > 0) {
+- /* length_here is the remaining amount of data in this page */
+- length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
+- if (length < length_here)
+- length_here = length;
+-
+- buffer->element[element].addr = data;
+- buffer->element[element].length = length_here;
+- length -= length_here;
+- if (!length) {
+- if (first_lap)
+- buffer->element[element].flags = 0;
+- else
+- buffer->element[element].flags =
+- SBAL_FLAGS_LAST_FRAG;
+- } else {
+- if (first_lap)
+- buffer->element[element].flags =
+- SBAL_FLAGS_FIRST_FRAG;
+- else
+- buffer->element[element].flags =
+- SBAL_FLAGS_MIDDLE_FRAG;
+- }
+- data += length_here;
+- element++;
+- first_lap = 0;
+- }
+- *next_element_to_fill = element;
+-}
+-
+-static int
+-qeth_fill_buffer(struct qeth_qdio_out_q *queue,
+- struct qeth_qdio_out_buffer *buf,
+- struct sk_buff *skb)
+-{
+- struct qdio_buffer *buffer;
+- struct qeth_hdr_tso *hdr;
+- int flush_cnt = 0, hdr_len, large_send = 0;
+-
+- QETH_DBF_TEXT(trace, 6, "qdfillbf");
+-
+- buffer = buf->buffer;
+- atomic_inc(&skb->users);
+- skb_queue_tail(&buf->skb_list, skb);
+-
+- hdr = (struct qeth_hdr_tso *) skb->data;
+- /*check first on TSO ....*/
+- if (hdr->hdr.hdr.l3.id == QETH_HEADER_TYPE_TSO) {
+- int element = buf->next_element_to_fill;
+-
+- hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len;
+- /*fill first buffer entry only with header information */
+- buffer->element[element].addr = skb->data;
+- buffer->element[element].length = hdr_len;
+- buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
+- buf->next_element_to_fill++;
+- skb->data += hdr_len;
+- skb->len -= hdr_len;
+- large_send = 1;
+- }
+- if (skb_shinfo(skb)->nr_frags == 0)
+- __qeth_fill_buffer(skb, buffer, large_send,
+- (int *)&buf->next_element_to_fill);
+- else
+- __qeth_fill_buffer_frag(skb, buffer, large_send,
+- (int *)&buf->next_element_to_fill);
+-
+- if (!queue->do_pack) {
+- QETH_DBF_TEXT(trace, 6, "fillbfnp");
+- /* set state to PRIMED -> will be flushed */
+- atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+- flush_cnt = 1;
+- } else {
+- QETH_DBF_TEXT(trace, 6, "fillbfpa");
+- if (queue->card->options.performance_stats)
+- queue->card->perf_stats.skbs_sent_pack++;
+- if (buf->next_element_to_fill >=
+- QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
+- /*
+- * packed buffer if full -> set state PRIMED
+- * -> will be flushed
+- */
+- atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+- flush_cnt = 1;
+- }
+- }
+- return flush_cnt;
+-}
+-
+-static int
+-qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue,
+- struct sk_buff *skb, struct qeth_hdr *hdr,
+- int elements_needed,
+- struct qeth_eddp_context *ctx)
+-{
+- struct qeth_qdio_out_buffer *buffer;
+- int buffers_needed = 0;
+- int flush_cnt = 0;
+- int index;
+-
+- QETH_DBF_TEXT(trace, 6, "dosndpfa");
+-
+- /* spin until we get the queue ... */
+- while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
+- QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
+- /* ... now we've got the queue */
+- index = queue->next_buf_to_fill;
+- buffer = &queue->bufs[queue->next_buf_to_fill];
+- /*
+- * check if buffer is empty to make sure that we do not 'overtake'
+- * ourselves and try to fill a buffer that is already primed
+- */
+- if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY)
+- goto out;
+- if (ctx == NULL)
+- queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
+- QDIO_MAX_BUFFERS_PER_Q;
+- else {
+- buffers_needed = qeth_eddp_check_buffers_for_context(queue,ctx);
+- if (buffers_needed < 0)
+- goto out;
+- queue->next_buf_to_fill =
+- (queue->next_buf_to_fill + buffers_needed) %
+- QDIO_MAX_BUFFERS_PER_Q;
+- }
+- atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+- if (ctx == NULL) {
+- qeth_fill_buffer(queue, buffer, skb);
+- qeth_flush_buffers(queue, 0, index, 1);
+- } else {
+- flush_cnt = qeth_eddp_fill_buffer(queue, ctx, index);
+- WARN_ON(buffers_needed != flush_cnt);
+- qeth_flush_buffers(queue, 0, index, flush_cnt);
+- }
+- return 0;
+-out:
+- atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+- return -EBUSY;
+-}
+-
+-static int
+-qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
+- struct sk_buff *skb, struct qeth_hdr *hdr,
+- int elements_needed, struct qeth_eddp_context *ctx)
+-{
+- struct qeth_qdio_out_buffer *buffer;
+- int start_index;
+- int flush_count = 0;
+- int do_pack = 0;
+- int tmp;
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace, 6, "dosndpkt");
+-
+- /* spin until we get the queue ... */
+- while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
+- QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
+- start_index = queue->next_buf_to_fill;
+- buffer = &queue->bufs[queue->next_buf_to_fill];
+- /*
+- * check if buffer is empty to make sure that we do not 'overtake'
+- * ourselves and try to fill a buffer that is already primed
+- */
+- if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) {
+- atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+- return -EBUSY;
+- }
+- /* check if we need to switch packing state of this queue */
+- qeth_switch_to_packing_if_needed(queue);
+- if (queue->do_pack){
+- do_pack = 1;
+- if (ctx == NULL) {
+- /* does packet fit in current buffer? */
+- if((QETH_MAX_BUFFER_ELEMENTS(card) -
+- buffer->next_element_to_fill) < elements_needed){
+- /* ... no -> set state PRIMED */
+- atomic_set(&buffer->state,QETH_QDIO_BUF_PRIMED);
+- flush_count++;
+- queue->next_buf_to_fill =
+- (queue->next_buf_to_fill + 1) %
+- QDIO_MAX_BUFFERS_PER_Q;
+- buffer = &queue->bufs[queue->next_buf_to_fill];
+- /* we did a step forward, so check buffer state
+- * again */
+- if (atomic_read(&buffer->state) !=
+- QETH_QDIO_BUF_EMPTY){
+- qeth_flush_buffers(queue, 0, start_index, flush_count);
+- atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+- return -EBUSY;
+- }
+- }
+- } else {
+- /* check if we have enough elements (including following
+- * free buffers) to handle eddp context */
+- if (qeth_eddp_check_buffers_for_context(queue,ctx) < 0){
+- if (net_ratelimit())
+- PRINT_WARN("eddp tx_dropped 1\n");
+- rc = -EBUSY;
+- goto out;
+- }
+- }
+- }
+- if (ctx == NULL)
+- tmp = qeth_fill_buffer(queue, buffer, skb);
+- else {
+- tmp = qeth_eddp_fill_buffer(queue,ctx,queue->next_buf_to_fill);
+- if (tmp < 0) {
+- printk("eddp tx_dropped 2\n");
+- rc = - EBUSY;
+- goto out;
+- }
+- }
+- queue->next_buf_to_fill = (queue->next_buf_to_fill + tmp) %
+- QDIO_MAX_BUFFERS_PER_Q;
+- flush_count += tmp;
+-out:
+- if (flush_count)
+- qeth_flush_buffers(queue, 0, start_index, flush_count);
+- else if (!atomic_read(&queue->set_pci_flags_count))
+- atomic_xchg(&queue->state, QETH_OUT_Q_LOCKED_FLUSH);
+- /*
+- * queue->state will go from LOCKED -> UNLOCKED or from
+- * LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us
+- * (switch packing state or flush buffer to get another pci flag out).
+- * In that case we will enter this loop
+- */
+- while (atomic_dec_return(&queue->state)){
+- flush_count = 0;
+- start_index = queue->next_buf_to_fill;
+- /* check if we can go back to non-packing state */
+- flush_count += qeth_switch_to_nonpacking_if_needed(queue);
+- /*
+- * check if we need to flush a packing buffer to get a pci
+- * flag out on the queue
+- */
+- if (!flush_count && !atomic_read(&queue->set_pci_flags_count))
+- flush_count += qeth_flush_buffers_on_no_pci(queue);
+- if (flush_count)
+- qeth_flush_buffers(queue, 0, start_index, flush_count);
+- }
+- /* at this point the queue is UNLOCKED again */
+- if (queue->card->options.performance_stats && do_pack)
+- queue->card->perf_stats.bufs_sent_pack += flush_count;
+-
+- return rc;
+-}
+-
+-static int
+-qeth_get_elements_no(struct qeth_card *card, void *hdr,
+- struct sk_buff *skb, int elems)
+-{
+- int elements_needed = 0;
+-
+- if (skb_shinfo(skb)->nr_frags > 0)
+- elements_needed = (skb_shinfo(skb)->nr_frags + 1);
+- if (elements_needed == 0)
+- elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
+- + skb->len) >> PAGE_SHIFT);
+- if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){
+- PRINT_ERR("Invalid size of IP packet "
+- "(Number=%d / Length=%d). Discarded.\n",
+- (elements_needed+elems), skb->len);
+- return 0;
+- }
+- return elements_needed;
+-}
+-
+-static void qeth_tx_csum(struct sk_buff *skb)
+-{
+- int tlen;
+-
+- if (skb->protocol == htons(ETH_P_IP)) {
+- tlen = ntohs(ip_hdr(skb)->tot_len) - (ip_hdr(skb)->ihl << 2);
+- switch (ip_hdr(skb)->protocol) {
+- case IPPROTO_TCP:
+- tcp_hdr(skb)->check = 0;
+- tcp_hdr(skb)->check = csum_tcpudp_magic(
+- ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
+- tlen, ip_hdr(skb)->protocol,
+- skb_checksum(skb, skb_transport_offset(skb),
+- tlen, 0));
+- break;
+- case IPPROTO_UDP:
+- udp_hdr(skb)->check = 0;
+- udp_hdr(skb)->check = csum_tcpudp_magic(
+- ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
+- tlen, ip_hdr(skb)->protocol,
+- skb_checksum(skb, skb_transport_offset(skb),
+- tlen, 0));
+- break;
+- }
+- } else if (skb->protocol == htons(ETH_P_IPV6)) {
+- switch (ipv6_hdr(skb)->nexthdr) {
+- case IPPROTO_TCP:
+- tcp_hdr(skb)->check = 0;
+- tcp_hdr(skb)->check = csum_ipv6_magic(
+- &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
+- ipv6_hdr(skb)->payload_len,
+- ipv6_hdr(skb)->nexthdr,
+- skb_checksum(skb, skb_transport_offset(skb),
+- ipv6_hdr(skb)->payload_len, 0));
+- break;
+- case IPPROTO_UDP:
+- udp_hdr(skb)->check = 0;
+- udp_hdr(skb)->check = csum_ipv6_magic(
+- &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
+- ipv6_hdr(skb)->payload_len,
+- ipv6_hdr(skb)->nexthdr,
+- skb_checksum(skb, skb_transport_offset(skb),
+- ipv6_hdr(skb)->payload_len, 0));
+- break;
+- }
+- }
+-}
+-
+-static int
+-qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
+-{
+- int ipv = 0;
+- int cast_type;
+- struct qeth_qdio_out_q *queue;
+- struct qeth_hdr *hdr = NULL;
+- int elements_needed = 0;
+- enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
+- struct qeth_eddp_context *ctx = NULL;
+- int tx_bytes = skb->len;
+- unsigned short nr_frags = skb_shinfo(skb)->nr_frags;
+- unsigned short tso_size = skb_shinfo(skb)->gso_size;
+- struct sk_buff *new_skb, *new_skb2;
+- int rc;
+-
+- QETH_DBF_TEXT(trace, 6, "sendpkt");
+-
+- new_skb = skb;
+- if ((card->info.type == QETH_CARD_TYPE_OSN) &&
+- (skb->protocol == htons(ETH_P_IPV6)))
+- return -EPERM;
+- cast_type = qeth_get_cast_type(card, skb);
+- if ((cast_type == RTN_BROADCAST) &&
+- (card->info.broadcast_capable == 0))
+- return -EPERM;
+- queue = card->qdio.out_qs
+- [qeth_get_priority_queue(card, skb, ipv, cast_type)];
+- if (!card->options.layer2) {
+- ipv = qeth_get_ip_version(skb);
+- if ((card->dev->header_ops == &qeth_fake_ops) && ipv) {
+- new_skb = qeth_pskb_unshare(skb, GFP_ATOMIC);
+- if (!new_skb)
+- return -ENOMEM;
+- if(card->dev->type == ARPHRD_IEEE802_TR){
+- skb_pull(new_skb, QETH_FAKE_LL_LEN_TR);
+- } else {
+- skb_pull(new_skb, QETH_FAKE_LL_LEN_ETH);
+- }
+- }
+- }
+- if (skb_is_gso(skb))
+- large_send = card->options.large_send;
+- /* check on OSN device*/
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- hdr = (struct qeth_hdr *)new_skb->data;
+- /*are we able to do TSO ? */
+- if ((large_send == QETH_LARGE_SEND_TSO) &&
+- (cast_type == RTN_UNSPEC)) {
+- rc = qeth_tso_prepare_packet(card, new_skb, ipv, cast_type);
+- if (rc) {
+- __qeth_free_new_skb(skb, new_skb);
+- return rc;
+- }
+- elements_needed++;
+- } else if (card->info.type != QETH_CARD_TYPE_OSN) {
+- new_skb2 = qeth_prepare_skb(card, new_skb, &hdr, ipv);
+- if (!new_skb2) {
+- __qeth_free_new_skb(skb, new_skb);
+- return -EINVAL;
+- }
+- if (new_skb != skb)
+- __qeth_free_new_skb(new_skb2, new_skb);
+- new_skb = new_skb2;
+- qeth_fill_header(card, hdr, new_skb, ipv, cast_type);
+- }
+- if (large_send == QETH_LARGE_SEND_EDDP) {
+- ctx = qeth_eddp_create_context(card, new_skb, hdr,
+- skb->sk->sk_protocol);
+- if (ctx == NULL) {
+- __qeth_free_new_skb(skb, new_skb);
+- PRINT_WARN("could not create eddp context\n");
+- return -EINVAL;
+- }
+- } else {
+- int elems = qeth_get_elements_no(card,(void*) hdr, new_skb,
+- elements_needed);
+- if (!elems) {
+- __qeth_free_new_skb(skb, new_skb);
+- return -EINVAL;
+- }
+- elements_needed += elems;
+- }
+-
+- if ((large_send == QETH_LARGE_SEND_NO) &&
+- (skb->ip_summed == CHECKSUM_PARTIAL))
+- qeth_tx_csum(new_skb);
+-
+- if (card->info.type != QETH_CARD_TYPE_IQD)
+- rc = qeth_do_send_packet(card, queue, new_skb, hdr,
+- elements_needed, ctx);
+- else {
+- if ((!card->options.layer2) &&
+- (ipv == 0)) {
+- __qeth_free_new_skb(skb, new_skb);
+- return -EPERM;
+- }
+- rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr,
+- elements_needed, ctx);
+- }
+- if (!rc) {
+- card->stats.tx_packets++;
+- card->stats.tx_bytes += tx_bytes;
+- if (new_skb != skb)
+- dev_kfree_skb_any(skb);
+- if (card->options.performance_stats) {
+- if (tso_size &&
+- !(large_send == QETH_LARGE_SEND_NO)) {
+- card->perf_stats.large_send_bytes += tx_bytes;
+- card->perf_stats.large_send_cnt++;
+- }
+- if (nr_frags > 0) {
+- card->perf_stats.sg_skbs_sent++;
+- /* nr_frags + skb->data */
+- card->perf_stats.sg_frags_sent +=
+- nr_frags + 1;
+- }
+- }
+- } else {
+- card->stats.tx_dropped++;
+- __qeth_free_new_skb(skb, new_skb);
+- }
+- if (ctx != NULL) {
+- /* drop creator's reference */
+- qeth_eddp_put_context(ctx);
+- /* free skb; it's not referenced by a buffer */
+- if (!rc)
+- dev_kfree_skb_any(new_skb);
+- }
+- return rc;
+-}
+-
+-static int
+-qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
+-{
+- struct qeth_card *card = (struct qeth_card *) dev->priv;
+- int rc = 0;
+-
+- switch(regnum){
+- case MII_BMCR: /* Basic mode control register */
+- rc = BMCR_FULLDPLX;
+- if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH)&&
+- (card->info.link_type != QETH_LINK_TYPE_OSN) &&
+- (card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH))
+- rc |= BMCR_SPEED100;
+- break;
+- case MII_BMSR: /* Basic mode status register */
+- rc = BMSR_ERCAP | BMSR_ANEGCOMPLETE | BMSR_LSTATUS |
+- BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | BMSR_100FULL |
+- BMSR_100BASE4;
+- break;
+- case MII_PHYSID1: /* PHYS ID 1 */
+- rc = (dev->dev_addr[0] << 16) | (dev->dev_addr[1] << 8) |
+- dev->dev_addr[2];
+- rc = (rc >> 5) & 0xFFFF;
+- break;
+- case MII_PHYSID2: /* PHYS ID 2 */
+- rc = (dev->dev_addr[2] << 10) & 0xFFFF;
+- break;
+- case MII_ADVERTISE: /* Advertisement control reg */
+- rc = ADVERTISE_ALL;
+- break;
+- case MII_LPA: /* Link partner ability reg */
+- rc = LPA_10HALF | LPA_10FULL | LPA_100HALF | LPA_100FULL |
+- LPA_100BASE4 | LPA_LPACK;
+- break;
+- case MII_EXPANSION: /* Expansion register */
+- break;
+- case MII_DCOUNTER: /* disconnect counter */
+- break;
+- case MII_FCSCOUNTER: /* false carrier counter */
+- break;
+- case MII_NWAYTEST: /* N-way auto-neg test register */
+- break;
+- case MII_RERRCOUNTER: /* rx error counter */
+- rc = card->stats.rx_errors;
+- break;
+- case MII_SREVISION: /* silicon revision */
+- break;
+- case MII_RESV1: /* reserved 1 */
+- break;
+- case MII_LBRERROR: /* loopback, rx, bypass error */
+- break;
+- case MII_PHYADDR: /* physical address */
+- break;
+- case MII_RESV2: /* reserved 2 */
+- break;
+- case MII_TPISTATUS: /* TPI status for 10mbps */
+- break;
+- case MII_NCONFIG: /* network interface config */
+- break;
+- default:
+- break;
+- }
+- return rc;
+-}
+-
+-
+-static const char *
+-qeth_arp_get_error_cause(int *rc)
+-{
+- switch (*rc) {
+- case QETH_IPA_ARP_RC_FAILED:
+- *rc = -EIO;
+- return "operation failed";
+- case QETH_IPA_ARP_RC_NOTSUPP:
+- *rc = -EOPNOTSUPP;
+- return "operation not supported";
+- case QETH_IPA_ARP_RC_OUT_OF_RANGE:
+- *rc = -EINVAL;
+- return "argument out of range";
+- case QETH_IPA_ARP_RC_Q_NOTSUPP:
+- *rc = -EOPNOTSUPP;
+- return "query operation not supported";
+- case QETH_IPA_ARP_RC_Q_NO_DATA:
+- *rc = -ENOENT;
+- return "no query data available";
+- default:
+- return "unknown error";
+- }
+-}
+-
+-static int
+-qeth_send_simple_setassparms(struct qeth_card *, enum qeth_ipa_funcs,
+- __u16, long);
+-
+-static int
+-qeth_arp_set_no_entries(struct qeth_card *card, int no_entries)
+-{
+- int tmp;
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"arpstnoe");
+-
+- /*
+- * currently GuestLAN only supports the ARP assist function
+- * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES;
+- * thus we say EOPNOTSUPP for this ARP function
+- */
+- if (card->info.guestlan)
+- return -EOPNOTSUPP;
+- if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
+- PRINT_WARN("ARP processing not supported "
+- "on %s!\n", QETH_CARD_IFNAME(card));
+- return -EOPNOTSUPP;
+- }
+- rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
+- IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
+- no_entries);
+- if (rc) {
+- tmp = rc;
+- PRINT_WARN("Could not set number of ARP entries on %s: "
+- "%s (0x%x/%d)\n",
+- QETH_CARD_IFNAME(card), qeth_arp_get_error_cause(&rc),
+- tmp, tmp);
+- }
+- return rc;
+-}
+-
+-static void
+-qeth_copy_arp_entries_stripped(struct qeth_arp_query_info *qinfo,
+- struct qeth_arp_query_data *qdata,
+- int entry_size, int uentry_size)
+-{
+- char *entry_ptr;
+- char *uentry_ptr;
+- int i;
+-
+- entry_ptr = (char *)&qdata->data;
+- uentry_ptr = (char *)(qinfo->udata + qinfo->udata_offset);
+- for (i = 0; i < qdata->no_entries; ++i){
+- /* strip off 32 bytes "media specific information" */
+- memcpy(uentry_ptr, (entry_ptr + 32), entry_size - 32);
+- entry_ptr += entry_size;
+- uentry_ptr += uentry_size;
+- }
+-}
+-
+-static int
+-qeth_arp_query_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_ipa_cmd *cmd;
+- struct qeth_arp_query_data *qdata;
+- struct qeth_arp_query_info *qinfo;
+- int entry_size;
+- int uentry_size;
+- int i;
+-
+- QETH_DBF_TEXT(trace,4,"arpquecb");
+-
+- qinfo = (struct qeth_arp_query_info *) reply->param;
+- cmd = (struct qeth_ipa_cmd *) data;
+- if (cmd->hdr.return_code) {
+- QETH_DBF_TEXT_(trace,4,"qaer1%i", cmd->hdr.return_code);
+- return 0;
+- }
+- if (cmd->data.setassparms.hdr.return_code) {
+- cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
+- QETH_DBF_TEXT_(trace,4,"qaer2%i", cmd->hdr.return_code);
+- return 0;
+- }
+- qdata = &cmd->data.setassparms.data.query_arp;
+- switch(qdata->reply_bits){
+- case 5:
+- uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry5);
+- if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
+- uentry_size = sizeof(struct qeth_arp_qi_entry5_short);
+- break;
+- case 7:
+- /* fall through to default */
+- default:
+- /* tr is the same as eth -> entry7 */
+- uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry7);
+- if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
+- uentry_size = sizeof(struct qeth_arp_qi_entry7_short);
+- break;
+- }
+- /* check if there is enough room in userspace */
+- if ((qinfo->udata_len - qinfo->udata_offset) <
+- qdata->no_entries * uentry_size){
+- QETH_DBF_TEXT_(trace, 4, "qaer3%i", -ENOMEM);
+- cmd->hdr.return_code = -ENOMEM;
+- PRINT_WARN("query ARP user space buffer is too small for "
+- "the returned number of ARP entries. "
+- "Aborting query!\n");
+- goto out_error;
+- }
+- QETH_DBF_TEXT_(trace, 4, "anore%i",
+- cmd->data.setassparms.hdr.number_of_replies);
+- QETH_DBF_TEXT_(trace, 4, "aseqn%i", cmd->data.setassparms.hdr.seq_no);
+- QETH_DBF_TEXT_(trace, 4, "anoen%i", qdata->no_entries);
+-
+- if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) {
+- /* strip off "media specific information" */
+- qeth_copy_arp_entries_stripped(qinfo, qdata, entry_size,
+- uentry_size);
+- } else
+- /*copy entries to user buffer*/
+- memcpy(qinfo->udata + qinfo->udata_offset,
+- (char *)&qdata->data, qdata->no_entries*uentry_size);
+-
+- qinfo->no_entries += qdata->no_entries;
+- qinfo->udata_offset += (qdata->no_entries*uentry_size);
+- /* check if all replies received ... */
+- if (cmd->data.setassparms.hdr.seq_no <
+- cmd->data.setassparms.hdr.number_of_replies)
+- return 1;
+- memcpy(qinfo->udata, &qinfo->no_entries, 4);
+- /* keep STRIP_ENTRIES flag so the user program can distinguish
+- * stripped entries from normal ones */
+- if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
+- qdata->reply_bits |= QETH_QARP_STRIP_ENTRIES;
+- memcpy(qinfo->udata + QETH_QARP_MASK_OFFSET,&qdata->reply_bits,2);
+- return 0;
+-out_error:
+- i = 0;
+- memcpy(qinfo->udata, &i, 4);
+- return 0;
+-}
+-
+-static int
+-qeth_send_ipa_arp_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+- int len, int (*reply_cb)(struct qeth_card *,
+- struct qeth_reply *,
+- unsigned long),
+- void *reply_param)
+-{
+- QETH_DBF_TEXT(trace,4,"sendarp");
+-
+- memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+- memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+- &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+- return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
+- reply_cb, reply_param);
+-}
+-
+-static int
+-qeth_send_ipa_snmp_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+- int len, int (*reply_cb)(struct qeth_card *,
+- struct qeth_reply *,
+- unsigned long),
+- void *reply_param)
+-{
+- u16 s1, s2;
+-
+- QETH_DBF_TEXT(trace,4,"sendsnmp");
+-
+- memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+- memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+- &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+- /* adjust PDU length fields in IPA_PDU_HEADER */
+- s1 = (u32) IPA_PDU_HEADER_SIZE + len;
+- s2 = (u32) len;
+- memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
+- memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
+- memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
+- memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
+- return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
+- reply_cb, reply_param);
+-}
+-
+-static struct qeth_cmd_buffer *
+-qeth_get_setassparms_cmd(struct qeth_card *, enum qeth_ipa_funcs,
+- __u16, __u16, enum qeth_prot_versions);
+-static int
+-qeth_arp_query(struct qeth_card *card, char __user *udata)
+-{
+- struct qeth_cmd_buffer *iob;
+- struct qeth_arp_query_info qinfo = {0, };
+- int tmp;
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"arpquery");
+-
+- if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/
+- IPA_ARP_PROCESSING)) {
+- PRINT_WARN("ARP processing not supported "
+- "on %s!\n", QETH_CARD_IFNAME(card));
+- return -EOPNOTSUPP;
+- }
+- /* get size of userspace buffer and mask_bits -> 6 bytes */
+- if (copy_from_user(&qinfo, udata, 6))
+- return -EFAULT;
+- if (!(qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL)))
+- return -ENOMEM;
+- qinfo.udata_offset = QETH_QARP_ENTRIES_OFFSET;
+- iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
+- IPA_CMD_ASS_ARP_QUERY_INFO,
+- sizeof(int),QETH_PROT_IPV4);
+-
+- rc = qeth_send_ipa_arp_cmd(card, iob,
+- QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN,
+- qeth_arp_query_cb, (void *)&qinfo);
+- if (rc) {
+- tmp = rc;
+- PRINT_WARN("Error while querying ARP cache on %s: %s "
+- "(0x%x/%d)\n",
+- QETH_CARD_IFNAME(card), qeth_arp_get_error_cause(&rc),
+- tmp, tmp);
+- if (copy_to_user(udata, qinfo.udata, 4))
+- rc = -EFAULT;
+- } else {
+- if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
+- rc = -EFAULT;
+- }
+- kfree(qinfo.udata);
+- return rc;
+-}
+-
+-/**
+- * SNMP command callback
+- */
+-static int
+-qeth_snmp_command_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long sdata)
+-{
+- struct qeth_ipa_cmd *cmd;
+- struct qeth_arp_query_info *qinfo;
+- struct qeth_snmp_cmd *snmp;
+- unsigned char *data;
+- __u16 data_len;
+-
+- QETH_DBF_TEXT(trace,3,"snpcmdcb");
+-
+- cmd = (struct qeth_ipa_cmd *) sdata;
+- data = (unsigned char *)((char *)cmd - reply->offset);
+- qinfo = (struct qeth_arp_query_info *) reply->param;
+- snmp = &cmd->data.setadapterparms.data.snmp;
+-
+- if (cmd->hdr.return_code) {
+- QETH_DBF_TEXT_(trace,4,"scer1%i", cmd->hdr.return_code);
+- return 0;
+- }
+- if (cmd->data.setadapterparms.hdr.return_code) {
+- cmd->hdr.return_code = cmd->data.setadapterparms.hdr.return_code;
+- QETH_DBF_TEXT_(trace,4,"scer2%i", cmd->hdr.return_code);
+- return 0;
+- }
+- data_len = *((__u16*)QETH_IPA_PDU_LEN_PDU1(data));
+- if (cmd->data.setadapterparms.hdr.seq_no == 1)
+- data_len -= (__u16)((char *)&snmp->data - (char *)cmd);
+- else
+- data_len -= (__u16)((char*)&snmp->request - (char *)cmd);
+-
+- /* check if there is enough room in userspace */
+- if ((qinfo->udata_len - qinfo->udata_offset) < data_len) {
+- QETH_DBF_TEXT_(trace, 4, "scer3%i", -ENOMEM);
+- cmd->hdr.return_code = -ENOMEM;
+- return 0;
+- }
+- QETH_DBF_TEXT_(trace, 4, "snore%i",
+- cmd->data.setadapterparms.hdr.used_total);
+- QETH_DBF_TEXT_(trace, 4, "sseqn%i", cmd->data.setadapterparms.hdr.seq_no);
+- /*copy entries to user buffer*/
+- if (cmd->data.setadapterparms.hdr.seq_no == 1) {
+- memcpy(qinfo->udata + qinfo->udata_offset,
+- (char *)snmp,
+- data_len + offsetof(struct qeth_snmp_cmd,data));
+- qinfo->udata_offset += offsetof(struct qeth_snmp_cmd, data);
+- } else {
+- memcpy(qinfo->udata + qinfo->udata_offset,
+- (char *)&snmp->request, data_len);
+- }
+- qinfo->udata_offset += data_len;
+- /* check if all replies received ... */
+- QETH_DBF_TEXT_(trace, 4, "srtot%i",
+- cmd->data.setadapterparms.hdr.used_total);
+- QETH_DBF_TEXT_(trace, 4, "srseq%i",
+- cmd->data.setadapterparms.hdr.seq_no);
+- if (cmd->data.setadapterparms.hdr.seq_no <
+- cmd->data.setadapterparms.hdr.used_total)
+- return 1;
+- return 0;
+-}
+-
+-static struct qeth_cmd_buffer *
+-qeth_get_ipacmd_buffer(struct qeth_card *, enum qeth_ipa_cmds,
+- enum qeth_prot_versions );
+-
+-static struct qeth_cmd_buffer *
+-qeth_get_adapter_cmd(struct qeth_card *card, __u32 command, __u32 cmdlen)
+-{
+- struct qeth_cmd_buffer *iob;
+- struct qeth_ipa_cmd *cmd;
+-
+- iob = qeth_get_ipacmd_buffer(card,IPA_CMD_SETADAPTERPARMS,
+- QETH_PROT_IPV4);
+- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+- cmd->data.setadapterparms.hdr.cmdlength = cmdlen;
+- cmd->data.setadapterparms.hdr.command_code = command;
+- cmd->data.setadapterparms.hdr.used_total = 1;
+- cmd->data.setadapterparms.hdr.seq_no = 1;
+-
+- return iob;
+-}
+-
+-/**
+- * function to send SNMP commands to OSA-E card
+- */
+-static int
+-qeth_snmp_command(struct qeth_card *card, char __user *udata)
+-{
+- struct qeth_cmd_buffer *iob;
+- struct qeth_ipa_cmd *cmd;
+- struct qeth_snmp_ureq *ureq;
+- int req_len;
+- struct qeth_arp_query_info qinfo = {0, };
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace,3,"snmpcmd");
+-
+- if (card->info.guestlan)
+- return -EOPNOTSUPP;
+-
+- if ((!qeth_adp_supported(card,IPA_SETADP_SET_SNMP_CONTROL)) &&
+- (!card->options.layer2) ) {
+- PRINT_WARN("SNMP Query MIBS not supported "
+- "on %s!\n", QETH_CARD_IFNAME(card));
+- return -EOPNOTSUPP;
+- }
+- /* skip 4 bytes (data_len struct member) to get req_len */
+- if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int)))
+- return -EFAULT;
+- ureq = kmalloc(req_len+sizeof(struct qeth_snmp_ureq_hdr), GFP_KERNEL);
+- if (!ureq) {
+- QETH_DBF_TEXT(trace, 2, "snmpnome");
+- return -ENOMEM;
+- }
+- if (copy_from_user(ureq, udata,
+- req_len+sizeof(struct qeth_snmp_ureq_hdr))){
+- kfree(ureq);
+- return -EFAULT;
+- }
+- qinfo.udata_len = ureq->hdr.data_len;
+- if (!(qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL))){
+- kfree(ureq);
+- return -ENOMEM;
+- }
+- qinfo.udata_offset = sizeof(struct qeth_snmp_ureq_hdr);
+-
+- iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_SNMP_CONTROL,
+- QETH_SNMP_SETADP_CMDLENGTH + req_len);
+- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+- memcpy(&cmd->data.setadapterparms.data.snmp, &ureq->cmd, req_len);
+- rc = qeth_send_ipa_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len,
+- qeth_snmp_command_cb, (void *)&qinfo);
+- if (rc)
+- PRINT_WARN("SNMP command failed on %s: (0x%x)\n",
+- QETH_CARD_IFNAME(card), rc);
+- else {
+- if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
+- rc = -EFAULT;
+- }
+-
+- kfree(ureq);
+- kfree(qinfo.udata);
+- return rc;
+-}
+-
+-static int
+-qeth_default_setassparms_cb(struct qeth_card *, struct qeth_reply *,
+- unsigned long);
+-
+-static int
+-qeth_default_setadapterparms_cb(struct qeth_card *card,
+- struct qeth_reply *reply,
+- unsigned long data);
+-static int
+-qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *,
+- __u16, long,
+- int (*reply_cb)
+- (struct qeth_card *, struct qeth_reply *, unsigned long),
+- void *reply_param);
+-
+-static int
+-qeth_arp_add_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry)
+-{
+- struct qeth_cmd_buffer *iob;
+- char buf[16];
+- int tmp;
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"arpadent");
+-
+- /*
+- * currently GuestLAN only supports the ARP assist function
+- * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY;
+- * thus we say EOPNOTSUPP for this ARP function
+- */
+- if (card->info.guestlan)
+- return -EOPNOTSUPP;
+- if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
+- PRINT_WARN("ARP processing not supported "
+- "on %s!\n", QETH_CARD_IFNAME(card));
+- return -EOPNOTSUPP;
+- }
+-
+- iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
+- IPA_CMD_ASS_ARP_ADD_ENTRY,
+- sizeof(struct qeth_arp_cache_entry),
+- QETH_PROT_IPV4);
+- rc = qeth_send_setassparms(card, iob,
+- sizeof(struct qeth_arp_cache_entry),
+- (unsigned long) entry,
+- qeth_default_setassparms_cb, NULL);
+- if (rc) {
+- tmp = rc;
+- qeth_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
+- PRINT_WARN("Could not add ARP entry for address %s on %s: "
+- "%s (0x%x/%d)\n",
+- buf, QETH_CARD_IFNAME(card),
+- qeth_arp_get_error_cause(&rc), tmp, tmp);
+- }
+- return rc;
+-}
+-
+-static int
+-qeth_arp_remove_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry)
+-{
+- struct qeth_cmd_buffer *iob;
+- char buf[16] = {0, };
+- int tmp;
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"arprment");
+-
+- /*
+- * currently GuestLAN only supports the ARP assist function
+- * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY;
+- * thus we say EOPNOTSUPP for this ARP function
+- */
+- if (card->info.guestlan)
+- return -EOPNOTSUPP;
+- if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
+- PRINT_WARN("ARP processing not supported "
+- "on %s!\n", QETH_CARD_IFNAME(card));
+- return -EOPNOTSUPP;
+- }
+- memcpy(buf, entry, 12);
+- iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
+- IPA_CMD_ASS_ARP_REMOVE_ENTRY,
+- 12,
+- QETH_PROT_IPV4);
+- rc = qeth_send_setassparms(card, iob,
+- 12, (unsigned long)buf,
+- qeth_default_setassparms_cb, NULL);
+- if (rc) {
+- tmp = rc;
+- memset(buf, 0, 16);
+- qeth_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
+- PRINT_WARN("Could not delete ARP entry for address %s on %s: "
+- "%s (0x%x/%d)\n",
+- buf, QETH_CARD_IFNAME(card),
+- qeth_arp_get_error_cause(&rc), tmp, tmp);
+- }
+- return rc;
+-}
+-
+-static int
+-qeth_arp_flush_cache(struct qeth_card *card)
+-{
+- int rc;
+- int tmp;
+-
+- QETH_DBF_TEXT(trace,3,"arpflush");
+-
+- /*
+- * currently GuestLAN only supports the ARP assist function
+- * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE;
+- * thus we say EOPNOTSUPP for this ARP function
+- */
+- if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD))
+- return -EOPNOTSUPP;
+- if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
+- PRINT_WARN("ARP processing not supported "
+- "on %s!\n", QETH_CARD_IFNAME(card));
+- return -EOPNOTSUPP;
+- }
+- rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
+- IPA_CMD_ASS_ARP_FLUSH_CACHE, 0);
+- if (rc){
+- tmp = rc;
+- PRINT_WARN("Could not flush ARP cache on %s: %s (0x%x/%d)\n",
+- QETH_CARD_IFNAME(card), qeth_arp_get_error_cause(&rc),
+- tmp, tmp);
+- }
+- return rc;
+-}
+-
+-static int
+-qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+-{
+- struct qeth_card *card = (struct qeth_card *)dev->priv;
+- struct qeth_arp_cache_entry arp_entry;
+- struct mii_ioctl_data *mii_data;
+- int rc = 0;
+-
+- if (!card)
+- return -ENODEV;
+-
+- if ((card->state != CARD_STATE_UP) &&
+- (card->state != CARD_STATE_SOFTSETUP))
+- return -ENODEV;
+-
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- return -EPERM;
+-
+- switch (cmd){
+- case SIOC_QETH_ARP_SET_NO_ENTRIES:
+- if ( !capable(CAP_NET_ADMIN) ||
+- (card->options.layer2) ) {
+- rc = -EPERM;
+- break;
+- }
+- rc = qeth_arp_set_no_entries(card, rq->ifr_ifru.ifru_ivalue);
+- break;
+- case SIOC_QETH_ARP_QUERY_INFO:
+- if ( !capable(CAP_NET_ADMIN) ||
+- (card->options.layer2) ) {
+- rc = -EPERM;
+- break;
+- }
+- rc = qeth_arp_query(card, rq->ifr_ifru.ifru_data);
+- break;
+- case SIOC_QETH_ARP_ADD_ENTRY:
+- if ( !capable(CAP_NET_ADMIN) ||
+- (card->options.layer2) ) {
+- rc = -EPERM;
+- break;
+- }
+- if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
+- sizeof(struct qeth_arp_cache_entry)))
+- rc = -EFAULT;
+- else
+- rc = qeth_arp_add_entry(card, &arp_entry);
+- break;
+- case SIOC_QETH_ARP_REMOVE_ENTRY:
+- if ( !capable(CAP_NET_ADMIN) ||
+- (card->options.layer2) ) {
+- rc = -EPERM;
+- break;
+- }
+- if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
+- sizeof(struct qeth_arp_cache_entry)))
+- rc = -EFAULT;
+- else
+- rc = qeth_arp_remove_entry(card, &arp_entry);
+- break;
+- case SIOC_QETH_ARP_FLUSH_CACHE:
+- if ( !capable(CAP_NET_ADMIN) ||
+- (card->options.layer2) ) {
+- rc = -EPERM;
+- break;
+- }
+- rc = qeth_arp_flush_cache(card);
+- break;
+- case SIOC_QETH_ADP_SET_SNMP_CONTROL:
+- rc = qeth_snmp_command(card, rq->ifr_ifru.ifru_data);
+- break;
+- case SIOC_QETH_GET_CARD_TYPE:
+- if ((card->info.type == QETH_CARD_TYPE_OSAE) &&
+- !card->info.guestlan)
+- return 1;
+- return 0;
+- break;
+- case SIOCGMIIPHY:
+- mii_data = if_mii(rq);
+- mii_data->phy_id = 0;
+- break;
+- case SIOCGMIIREG:
+- mii_data = if_mii(rq);
+- if (mii_data->phy_id != 0)
+- rc = -EINVAL;
+- else
+- mii_data->val_out = qeth_mdio_read(dev,mii_data->phy_id,
+- mii_data->reg_num);
+- break;
+- default:
+- rc = -EOPNOTSUPP;
+- }
+- if (rc)
+- QETH_DBF_TEXT_(trace, 2, "ioce%d", rc);
+- return rc;
+-}
+-
+-static struct net_device_stats *
+-qeth_get_stats(struct net_device *dev)
+-{
+- struct qeth_card *card;
+-
+- card = (struct qeth_card *) (dev->priv);
+-
+- QETH_DBF_TEXT(trace,5,"getstat");
+-
+- return &card->stats;
+-}
+-
+-static int
+-qeth_change_mtu(struct net_device *dev, int new_mtu)
+-{
+- struct qeth_card *card;
+- char dbf_text[15];
+-
+- card = (struct qeth_card *) (dev->priv);
+-
+- QETH_DBF_TEXT(trace,4,"chgmtu");
+- sprintf(dbf_text, "%8x", new_mtu);
+- QETH_DBF_TEXT(trace,4,dbf_text);
+-
+- if (new_mtu < 64)
+- return -EINVAL;
+- if (new_mtu > 65535)
+- return -EINVAL;
+- if ((!qeth_is_supported(card,IPA_IP_FRAGMENTATION)) &&
+- (!qeth_mtu_is_valid(card, new_mtu)))
+- return -EINVAL;
+- dev->mtu = new_mtu;
+- return 0;
+-}
+-
+-#ifdef CONFIG_QETH_VLAN
+-static void
+-qeth_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
+-{
+- struct qeth_card *card;
+- unsigned long flags;
+-
+- QETH_DBF_TEXT(trace,4,"vlanreg");
+-
+- card = (struct qeth_card *) dev->priv;
+- spin_lock_irqsave(&card->vlanlock, flags);
+- card->vlangrp = grp;
+- spin_unlock_irqrestore(&card->vlanlock, flags);
+-}
+-
+-static void
+-qeth_free_vlan_buffer(struct qeth_card *card, struct qeth_qdio_out_buffer *buf,
+- unsigned short vid)
+-{
+- int i;
+- struct sk_buff *skb;
+- struct sk_buff_head tmp_list;
+-
+- skb_queue_head_init(&tmp_list);
+- lockdep_set_class(&tmp_list.lock, &qdio_out_skb_queue_key);
+- for(i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i){
+- while ((skb = skb_dequeue(&buf->skb_list))){
+- if (vlan_tx_tag_present(skb) &&
+- (vlan_tx_tag_get(skb) == vid)) {
+- atomic_dec(&skb->users);
+- dev_kfree_skb(skb);
+- } else
+- skb_queue_tail(&tmp_list, skb);
+- }
+- }
+- while ((skb = skb_dequeue(&tmp_list)))
+- skb_queue_tail(&buf->skb_list, skb);
+-}
+-
+-static void
+-qeth_free_vlan_skbs(struct qeth_card *card, unsigned short vid)
+-{
+- int i, j;
+-
+- QETH_DBF_TEXT(trace, 4, "frvlskbs");
+- for (i = 0; i < card->qdio.no_out_queues; ++i){
+- for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
+- qeth_free_vlan_buffer(card, &card->qdio.
+- out_qs[i]->bufs[j], vid);
+- }
+-}
+-
+-static void
+-qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid)
+-{
+- struct in_device *in_dev;
+- struct in_ifaddr *ifa;
+- struct qeth_ipaddr *addr;
+-
+- QETH_DBF_TEXT(trace, 4, "frvaddr4");
+-
+- rcu_read_lock();
+- in_dev = __in_dev_get_rcu(vlan_group_get_device(card->vlangrp, vid));
+- if (!in_dev)
+- goto out;
+- for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
+- addr = qeth_get_addr_buffer(QETH_PROT_IPV4);
+- if (addr){
+- addr->u.a4.addr = ifa->ifa_address;
+- addr->u.a4.mask = ifa->ifa_mask;
+- addr->type = QETH_IP_TYPE_NORMAL;
+- if (!qeth_delete_ip(card, addr))
+- kfree(addr);
+- }
+- }
+-out:
+- rcu_read_unlock();
+-}
+-
+-static void
+-qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid)
+-{
+-#ifdef CONFIG_QETH_IPV6
+- struct inet6_dev *in6_dev;
+- struct inet6_ifaddr *ifa;
+- struct qeth_ipaddr *addr;
+-
+- QETH_DBF_TEXT(trace, 4, "frvaddr6");
+-
+- in6_dev = in6_dev_get(vlan_group_get_device(card->vlangrp, vid));
+- if (!in6_dev)
+- return;
+- for (ifa = in6_dev->addr_list; ifa; ifa = ifa->lst_next){
+- addr = qeth_get_addr_buffer(QETH_PROT_IPV6);
+- if (addr){
+- memcpy(&addr->u.a6.addr, &ifa->addr,
+- sizeof(struct in6_addr));
+- addr->u.a6.pfxlen = ifa->prefix_len;
+- addr->type = QETH_IP_TYPE_NORMAL;
+- if (!qeth_delete_ip(card, addr))
+- kfree(addr);
+- }
+- }
+- in6_dev_put(in6_dev);
+-#endif /* CONFIG_QETH_IPV6 */
+-}
+-
+-static void
+-qeth_free_vlan_addresses(struct qeth_card *card, unsigned short vid)
+-{
+- if (card->options.layer2 || !card->vlangrp)
+- return;
+- qeth_free_vlan_addresses4(card, vid);
+- qeth_free_vlan_addresses6(card, vid);
+-}
+-
+-static int
+-qeth_layer2_send_setdelvlan_cb(struct qeth_card *card,
+- struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_ipa_cmd *cmd;
+-
+- QETH_DBF_TEXT(trace, 2, "L2sdvcb");
+- cmd = (struct qeth_ipa_cmd *) data;
+- if (cmd->hdr.return_code) {
+- PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
+- "Continuing\n",cmd->data.setdelvlan.vlan_id,
+- QETH_CARD_IFNAME(card), cmd->hdr.return_code);
+- QETH_DBF_TEXT_(trace, 2, "L2VL%4x", cmd->hdr.command);
+- QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card));
+- QETH_DBF_TEXT_(trace, 2, "err%d", cmd->hdr.return_code);
+- }
+- return 0;
+-}
+-
+-static int
+-qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i,
+- enum qeth_ipa_cmds ipacmd)
+-{
+- struct qeth_ipa_cmd *cmd;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT_(trace, 4, "L2sdv%x",ipacmd);
+- iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
+- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+- cmd->data.setdelvlan.vlan_id = i;
+- return qeth_send_ipa_cmd(card, iob,
+- qeth_layer2_send_setdelvlan_cb, NULL);
+-}
+-
+-static void
+-qeth_layer2_process_vlans(struct qeth_card *card, int clear)
+-{
+- unsigned short i;
+-
+- QETH_DBF_TEXT(trace, 3, "L2prcvln");
+-
+- if (!card->vlangrp)
+- return;
+- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+- if (vlan_group_get_device(card->vlangrp, i) == NULL)
+- continue;
+- if (clear)
+- qeth_layer2_send_setdelvlan(card, i, IPA_CMD_DELVLAN);
+- else
+- qeth_layer2_send_setdelvlan(card, i, IPA_CMD_SETVLAN);
+- }
+-}
+-
+-/*add_vid is layer 2 used only ....*/
+-static void
+-qeth_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
+-{
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT_(trace, 4, "aid:%d", vid);
+-
+- card = (struct qeth_card *) dev->priv;
+- if (!card->options.layer2)
+- return;
+- qeth_layer2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
+-}
+-
+-/*... kill_vid used for both modes*/
+-static void
+-qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+-{
+- struct qeth_card *card;
+- unsigned long flags;
+-
+- QETH_DBF_TEXT_(trace, 4, "kid:%d", vid);
+-
+- card = (struct qeth_card *) dev->priv;
+- /* free all skbs for the vlan device */
+- qeth_free_vlan_skbs(card, vid);
+- spin_lock_irqsave(&card->vlanlock, flags);
+- /* unregister IP addresses of vlan device */
+- qeth_free_vlan_addresses(card, vid);
+- vlan_group_set_device(card->vlangrp, vid, NULL);
+- spin_unlock_irqrestore(&card->vlanlock, flags);
+- if (card->options.layer2)
+- qeth_layer2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
+- qeth_set_multicast_list(card->dev);
+-}
+-#endif
+-/**
+- * Examine hardware response to SET_PROMISC_MODE
+- */
+-static int
+-qeth_setadp_promisc_mode_cb(struct qeth_card *card,
+- struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_ipa_cmd *cmd;
+- struct qeth_ipacmd_setadpparms *setparms;
+-
+- QETH_DBF_TEXT(trace,4,"prmadpcb");
+-
+- cmd = (struct qeth_ipa_cmd *) data;
+- setparms = &(cmd->data.setadapterparms);
+-
+- qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
+- if (cmd->hdr.return_code) {
+- QETH_DBF_TEXT_(trace,4,"prmrc%2.2x",cmd->hdr.return_code);
+- setparms->data.mode = SET_PROMISC_MODE_OFF;
+- }
+- card->info.promisc_mode = setparms->data.mode;
+- return 0;
+-}
+-/*
+- * Set promiscuous mode (on or off) (SET_PROMISC_MODE command)
- */
+-static void
+-qeth_setadp_promisc_mode(struct qeth_card *card)
+-{
+- enum qeth_ipa_promisc_modes mode;
+- struct net_device *dev = card->dev;
+- struct qeth_cmd_buffer *iob;
+- struct qeth_ipa_cmd *cmd;
-
+- QETH_DBF_TEXT(trace, 4, "setprom");
-
--#include <linux/module.h>
--#include <linux/moduleparam.h>
--#include <linux/string.h>
--#include <linux/errno.h>
--#include <linux/mm.h>
--#include <linux/ip.h>
--#include <linux/inetdevice.h>
--#include <linux/netdevice.h>
--#include <linux/sched.h>
--#include <linux/workqueue.h>
--#include <linux/kernel.h>
--#include <linux/slab.h>
--#include <linux/interrupt.h>
--#include <linux/tcp.h>
--#include <linux/icmp.h>
--#include <linux/skbuff.h>
--#include <linux/in.h>
--#include <linux/igmp.h>
--#include <linux/init.h>
--#include <linux/reboot.h>
--#include <linux/mii.h>
--#include <linux/rcupdate.h>
--#include <linux/ethtool.h>
+- 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);
-
--#include <net/arp.h>
--#include <net/ip.h>
--#include <net/route.h>
+- 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);
+-}
-
--#include <asm/ebcdic.h>
--#include <asm/io.h>
--#include <asm/qeth.h>
--#include <asm/timex.h>
--#include <asm/semaphore.h>
--#include <asm/uaccess.h>
--#include <asm/s390_rdev.h>
+-/**
+- * set multicast address on card
+- */
+-static void
+-qeth_set_multicast_list(struct net_device *dev)
+-{
+- struct qeth_card *card = (struct qeth_card *) dev->priv;
-
--#include "qeth.h"
--#include "qeth_mpc.h"
--#include "qeth_fs.h"
--#include "qeth_eddp.h"
--#include "qeth_tso.h"
+- 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 const char *version = "qeth S/390 OSA-Express driver";
+-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;
-
--/**
-- * 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;
+- 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);
-
--DEFINE_PER_CPU(char[256], qeth_dbf_txt_buf);
+- return iob;
+-}
-
--static struct lock_class_key qdio_out_skb_queue_key;
+-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;
-
--/**
-- * some more definitions and declarations
-- */
--static unsigned int known_devices[][10] = QETH_MODELLIST_ARRAY;
+- QETH_DBF_TEXT(trace,4,"setdelmc");
-
--/* 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;
+- 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);
-
--static void qeth_send_control_data_cb(struct qeth_channel *,
-- struct qeth_cmd_buffer *);
+- rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
-
--/**
-- * here we go with function implementation
-- */
+- return rc;
+-}
-static void
--qeth_init_qdio_info(struct qeth_card *card);
+-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_init_qdio_queues(struct qeth_card *card);
+-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];
-
--static int
--qeth_alloc_qdio_buffers(struct qeth_card *card);
+- QETH_DBF_TEXT(trace,4,"setdelip");
+- QETH_DBF_TEXT_(trace,4,"flags%02X", flags);
-
--static void
--qeth_free_qdio_buffers(struct qeth_card *);
+- 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;
+- }
-
--static void
--qeth_clear_qdio_buffers(struct qeth_card *);
+- rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
-
--static void
--qeth_clear_ip_list(struct qeth_card *, int, int);
+- return rc;
+-}
-
--static void
--qeth_clear_ipacmd_list(struct qeth_card *);
+-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_qdio_clear_card(struct qeth_card *, 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 void
--qeth_clear_working_pool_list(struct qeth_card *);
+-static int
+-qeth_layer3_register_addr_entry(struct qeth_card *card,
+- struct qeth_ipaddr *addr)
+-{
+- char buf[50];
+- int rc;
+- int cnt = 3;
-
--static void
--qeth_clear_cmd_buffers(struct qeth_channel *);
+- 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_stop(struct net_device *);
+-qeth_layer3_deregister_addr_entry(struct qeth_card *card,
+- struct qeth_ipaddr *addr)
+-{
+- //char buf[50];
+- int rc;
-
--static void
--qeth_clear_ipato_list(struct qeth_card *);
+- 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_is_addr_covered_by_ipato(struct qeth_card *, struct qeth_ipaddr *);
+-qeth_register_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr)
+-{
+- if (card->options.layer2)
+- return qeth_layer2_register_addr_entry(card, addr);
-
--static void
--qeth_irq_tasklet(unsigned long);
+- return qeth_layer3_register_addr_entry(card, addr);
+-}
-
-static int
--qeth_set_online(struct ccwgroup_device *);
+-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_set_online(struct ccwgroup_device *gdev, int recovery_mode);
+-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;
-
--static struct qeth_ipaddr *
--qeth_get_addr_buffer(enum qeth_prot_versions);
+- return 0;
+-}
-
--static void
--qeth_set_multicast_list(struct net_device *);
+-static u32
+-qeth_ethtool_get_rx_csum(struct net_device *dev)
+-{
+- struct qeth_card *card = (struct qeth_card *)dev->priv;
-
--static void
--qeth_setadp_promisc_mode(struct qeth_card *);
+- return (card->options.checksum_type == HW_CHECKSUMMING);
+-}
-
-static int
--qeth_hard_header_parse(const struct sk_buff *skb, unsigned char *haddr);
+-qeth_ethtool_set_rx_csum(struct net_device *dev, u32 data)
+-{
+- struct qeth_card *card = (struct qeth_card *)dev->priv;
-
--static void
--qeth_notify_processes(void)
+- 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)
-{
-- /*notify all registered processes */
-- struct qeth_notify_list_struct *n_entry;
+- struct qeth_card *card = (struct qeth_card *)dev->priv;
-
-- 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);
+- 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;
-}
--int
--qeth_notifier_unregister(struct task_struct *p)
+-
+-static u32
+-qeth_ethtool_get_tso(struct net_device *dev)
-{
-- struct qeth_notify_list_struct *n_entry, *tmp;
+- struct qeth_card *card = (struct qeth_card *)dev->priv;
-
-- 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;
+- 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;
- }
-- }
--out:
-- spin_unlock(&qeth_notify_lock);
+- } else
+- dev->features &= ~NETIF_F_TSO;
- return 0;
-}
--int
--qeth_notifier_register(struct task_struct *p, int signum)
+-
+-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)
-{
-- struct qeth_notify_list_struct *n_entry;
+- const struct qeth_card *card;
+- const struct ethhdr *eth;
+- struct net_device *dev = skb->dev;
-
-- /*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;
+- 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;
- }
- }
-- 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;
+-#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,
+-};
-
--/**
-- * free channel command buffers
-- */
--static void
--qeth_clean_channel(struct qeth_channel *channel)
+-static int
+-qeth_netdev_init(struct net_device *dev)
-{
-- int cnt;
+- struct qeth_card *card;
-
-- QETH_DBF_TEXT(setup, 2, "freech");
-- for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
-- kfree(channel->iob[cnt].data);
+- 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;
-}
-
--/**
-- * free card
-- */
-static void
--qeth_free_card(struct qeth_card *card)
+-qeth_init_func_level(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);
+- 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;
+- }
-}
-
-/**
-- * alloc memory for command buffer per channel
+- * hardsetup card, initialize MPC and QDIO stuff
- */
-static int
--qeth_setup_channel(struct qeth_channel *channel)
+-qeth_hardsetup_card(struct qeth_card *card)
-{
-- int cnt;
+- int retries = 3;
+- int rc;
-
-- 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;
+- 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));
- }
-- if (cnt < QETH_CMD_BUFFER_NO) {
-- while (cnt-- > 0)
-- kfree(channel->iob[cnt].data);
-- return -ENOMEM;
+- 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;
- }
-- 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;
+- 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;
-}
-
--/**
-- * alloc memory for card structure
-- */
--static struct qeth_card *
--qeth_alloc_card(void)
+-static int
+-qeth_default_setassparms_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long data)
-{
-- struct qeth_card *card;
+- struct qeth_ipa_cmd *cmd;
-
-- 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;
+- 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 (qeth_setup_channel(&card->write)) {
-- qeth_clean_channel(&card->read);
-- kfree(card);
-- return NULL;
+- 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 card;
+- return 0;
-}
-
--static long
--__qeth_check_irb_error(struct ccw_device *cdev, unsigned long intparm,
-- struct irb *irb)
+-static int
+-qeth_default_setadapterparms_cb(struct qeth_card *card,
+- struct qeth_reply *reply,
+- unsigned long data)
-{
-- if (!IS_ERR(irb))
-- return 0;
+- struct qeth_ipa_cmd *cmd;
-
-- 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);
+- QETH_DBF_TEXT(trace,4,"defadpcb");
-
-- 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);
+- 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_get_problem(struct ccw_device *cdev, struct irb *irb)
+-qeth_query_setadapterparms_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long data)
-{
-- int dstat,cstat;
-- char *sense;
+- struct qeth_ipa_cmd *cmd;
-
-- sense = (char *) irb->ecw;
-- cstat = irb->scsw.cstat;
-- dstat = irb->scsw.dstat;
+- QETH_DBF_TEXT(trace,3,"quyadpcb");
-
-- 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;
-- }
+- 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);
+-}
-
-- 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;
+-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_issue_next_read(struct qeth_card *);
-
--/**
-- * interrupt handler
-- */
--static void
--qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
+-static int
+-qeth_setadpparms_change_macaddr(struct qeth_card *card)
-{
- int rc;
-- int cstat,dstat;
-- struct qeth_cmd_buffer *buffer;
-- struct qeth_channel *channel;
-- struct qeth_card *card;
+- struct qeth_cmd_buffer *iob;
+- struct qeth_ipa_cmd *cmd;
-
-- QETH_DBF_TEXT(trace,5,"irq");
+- QETH_DBF_TEXT(trace,4,"chgmac");
-
-- if (__qeth_check_irb_error(cdev, intparm, irb))
-- return;
-- cstat = irb->scsw.cstat;
-- dstat = irb->scsw.dstat;
+- 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;
+-}
-
-- card = CARD_FROM_CDEV(cdev);
-- if (!card)
-- return;
+-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;
-
-- 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);
+- QETH_DBF_TEXT(trace,4,"adpmode");
-
-- if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC))
-- channel->state = CH_STATE_STOPPED;
+- 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;
+-}
-
-- if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC))
-- channel->state = CH_STATE_HALTED;
+-static int
+-qeth_setadapter_hstr(struct qeth_card *card)
+-{
+- int rc;
-
-- /*let's wake up immediately on data channel*/
-- if ((channel == &card->data) && (intparm != 0) &&
-- (intparm != QETH_RCD_PARM))
-- goto out;
+- QETH_DBF_TEXT(trace,4,"adphstr");
-
-- if (intparm == QETH_CLEAR_CHANNEL_PARM) {
-- QETH_DBF_TEXT(trace, 6, "clrchpar");
-- /* we don't have to handle this further */
-- intparm = 0;
+- 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 (intparm == QETH_HALT_CHANNEL_PARM) {
-- QETH_DBF_TEXT(trace, 6, "hltchpar");
-- /* we don't have to handle this further */
-- intparm = 0;
+- 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;
- }
-- 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;
-- }
+- 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 (intparm == QETH_RCD_PARM) {
-- channel->state = CH_STATE_RCD_DONE;
-- goto out;
+- 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);
- }
-- if (intparm) {
-- buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
-- buffer->state = BUF_STATE_PROCESSED;
+-
+- 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
- }
-- if (channel == &card->data)
-- return;
+- 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;
+-}
-
-- if (channel == &card->read &&
-- channel->state == CH_STATE_UP)
-- qeth_issue_next_read(card);
+-static int
+-qeth_query_ipassists(struct qeth_card *card, enum qeth_prot_versions prot)
+-{
+- int rc;
+- struct qeth_cmd_buffer *iob;
-
-- qeth_irq_tasklet((unsigned long)channel);
-- return;
--out:
-- wake_up(&card->wait_q);
+- 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;
-}
-
--/**
-- * tasklet function scheduled from irq handler
-- */
--static void
--qeth_irq_tasklet(unsigned long data)
+-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_card *card;
-- struct qeth_channel *channel;
- struct qeth_cmd_buffer *iob;
-- __u8 index;
+- struct qeth_ipa_cmd *cmd;
-
-- 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;
+- 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;
- }
-- channel->buf_no = index;
-- wake_up(&card->wait_q);
+- 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_stop_card(struct qeth_card *, int);
+-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_set_offline(struct ccwgroup_device *cgdev, int recovery_mode)
+-qeth_start_ipa_source_mac(struct qeth_card *card)
-{
-- struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data;
-- int rc = 0, rc2 = 0, rc3 = 0;
-- enum qeth_card_states recover_flag;
+- int rc;
-
-- QETH_DBF_TEXT(setup, 3, "setoffl");
-- QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
+- QETH_DBF_TEXT(trace,3,"stsrcmac");
-
-- 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;
+- 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 = 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;
+-
+- rc = qeth_send_simple_setassparms(card, IPA_SOURCE_MAC,
+- IPA_CMD_ASS_START, 0);
- 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;
+- PRINT_WARN("Could not start inbound source "
+- "assist on %s: 0x%x\n",
+- QETH_CARD_IFNAME(card), rc);
+- return rc;
-}
-
-static int
--qeth_set_offline(struct ccwgroup_device *cgdev)
+-qeth_start_ipa_vlan(struct qeth_card *card)
-{
-- return __qeth_set_offline(cgdev, 0);
+- 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_threads_running(struct qeth_card *card, unsigned long threads);
+-qeth_start_ipa_multicast(struct qeth_card *card)
+-{
+- int rc;
-
+- QETH_DBF_TEXT(trace,3,"stmcast");
-
--static void
--qeth_remove_device(struct ccwgroup_device *cgdev)
+- 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)
-{
-- struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data;
-- unsigned long flags;
+- int rc;
-
-- QETH_DBF_TEXT(setup, 3, "rmdev");
-- QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
+- QETH_DBF_TEXT(trace,3,"softipv6");
-
-- if (!card)
-- return;
+- 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;
+-}
-
-- wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
+-#endif
-
-- if (cgdev->state == CCWGROUP_ONLINE){
-- card->use_hard_stop = 1;
-- qeth_set_offline(cgdev);
+-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;
- }
-- /* 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);
+- rc = qeth_softsetup_ipv6(card);
+-#endif
+- return rc ;
-}
-
-static int
--qeth_register_addr_entry(struct qeth_card *, struct qeth_ipaddr *);
+-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_deregister_addr_entry(struct qeth_card *, struct qeth_ipaddr *);
+-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;
+-}
-
--/**
-- * 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)
+-qeth_start_ipa_checksum(struct qeth_card *card)
-{
-- struct qeth_ipaddr *addr;
-- int found = 0;
+- int rc = 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;
-- }
+- 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 (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 (card->options.checksum_type == SW_CHECKSUMMING) {
+- PRINT_WARN("Using SW checksumming on %s.\n",
+- QETH_CARD_IFNAME(card));
+- 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
+- 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_address_exists_in_list(struct list_head *list, struct qeth_ipaddr *addr,
-- int same_type)
+-qeth_start_ipa_tso(struct qeth_card *card)
-{
-- struct qeth_ipaddr *tmp;
+- int rc;
-
-- 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;
-- }
+- 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;
-}
-
--/*
-- * 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)
+-qeth_send_setrouting(struct qeth_card *card, enum qeth_routing_types type,
+- enum qeth_prot_versions prot)
-{
-- struct qeth_ipaddr *tmp, *t;
-- int found = 0;
+- int rc;
+- struct qeth_ipa_cmd *cmd;
+- struct qeth_cmd_buffer *iob;
-
-- 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;
+- 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;
- }
-- 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;
+- } 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;
- }
- }
-- 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);
-- }
+-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;
-- } 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);
+- 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;
- }
-- return 1;
+- 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;
-}
-
--/**
-- * Remove IP address from list
+-/*
+- * softsetup card: init IPA stuff
- */
-static int
--qeth_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
+-qeth_softsetup_card(struct qeth_card *card)
-{
-- unsigned long flags;
-- int rc = 0;
+- int rc;
-
-- QETH_DBF_TEXT(trace, 4, "delip");
+- QETH_DBF_TEXT(setup, 2, "softsetp");
-
-- 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);
+- 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;
- }
-- spin_lock_irqsave(&card->ip_lock, flags);
-- rc = __qeth_insert_ip_todo(card, addr, 0);
-- spin_unlock_irqrestore(&card->ip_lock, flags);
-- return rc;
+- 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_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
+-qeth_get_unique_id_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long data)
-{
-- unsigned long flags;
-- int rc = 0;
+- struct qeth_ipa_cmd *cmd;
-
-- 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);
+- 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 {
-- QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
-- QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
+- 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);
- }
-- spin_lock_irqsave(&card->ip_lock, flags);
-- rc = __qeth_insert_ip_todo(card, addr, 1);
-- spin_unlock_irqrestore(&card->ip_lock, flags);
+- 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_delete_all_mc(struct qeth_card *card, unsigned long *flags)
+-qeth_clear_ip_list(struct qeth_card *card, int clean, int recover)
-{
- 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);
+- 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_ip_addr_list(struct qeth_card *card)
+-qeth_set_allowed_threads(struct qeth_card *card, unsigned long threads,
+- int clear_start_mask)
-{
-- 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->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);
+-}
-
-- 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);
+-static int
+-qeth_threads_running(struct qeth_card *card, unsigned long threads)
+-{
+- unsigned long flags;
+- int rc = 0;
-
-- 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;
+- 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();
- }
-- 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);
+- 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;
- }
-- spin_unlock_irqrestore(&card->ip_lock, flags);
-- kfree(tbd_list);
+- 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_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)
+-qeth_get_unique_id(struct qeth_card *card)
-{
-- unsigned long flags;
+- int rc = 0;
+-#ifdef CONFIG_QETH_IPV6
+- struct qeth_cmd_buffer *iob;
+- struct qeth_ipa_cmd *cmd;
-
-- 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;
+- 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;
- }
-- card->thread_start_mask |= thread;
-- spin_unlock_irqrestore(&card->thread_mask_lock, flags);
-- 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_clear_thread_start_bit(struct qeth_card *card, unsigned long thread)
+-qeth_print_status_with_portname(struct qeth_card *card)
-{
-- unsigned long flags;
+- 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);
-
-- 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)
+-qeth_print_status_no_portname(struct qeth_card *card)
-{
-- 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);
+- 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 int
--__qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
+-static void
+-qeth_print_status_message(struct qeth_card *card)
-{
-- unsigned long flags;
-- int rc = 0;
+- 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]);
-
-- 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;
+- 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);
- }
-- spin_unlock_irqrestore(&card->thread_mask_lock, flags);
-- return rc;
+- if (card->info.portname_required)
+- qeth_print_status_with_portname(card);
+- else
+- qeth_print_status_no_portname(card);
-}
-
-static int
--qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
+-qeth_register_netdev(struct qeth_card *card)
-{
-- int rc = 0;
--
-- wait_event(card->wait_q,
-- (rc = __qeth_do_run_thread(card, thread)) >= 0);
-- return rc;
+- 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 int
--qeth_recover(void *ptr)
+-static void
+-qeth_start_again(struct qeth_card *card, int recovery_mode)
-{
-- struct qeth_card *card;
-- int rc = 0;
+- QETH_DBF_TEXT(setup ,2, "startag");
-
-- 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;
+- 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);
-}
-
--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;
+-/* 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; \
+- }
-
-- 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)
+-static void qeth_make_parameters_consistent(struct qeth_card *card)
-{
-- 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)
+- if (card->options.layer2 == 0)
- 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;
+- 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");
-}
-
--/**
-- * initialize channels ,card and all state machines
-- */
+-
-static int
--qeth_setup_card(struct qeth_card *card)
+-__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;
-
-- QETH_DBF_TEXT(setup, 2, "setupcrd");
+- BUG_ON(!card);
+- QETH_DBF_TEXT(setup ,2, "setonlin");
- 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;
+- 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;
- }
-- 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;
+- 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_DBF_TEXT(setup, 2, "chk_1920");
+- qeth_make_parameters_consistent(card);
-
-- 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);
+- if ((rc = qeth_hardsetup_card(card))){
+- QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+- goto out_remove;
- }
-- QETH_DBF_TEXT_(setup, 2, "rc:%x", single_queue);
-- return single_queue;
--}
+- card->state = CARD_STATE_HARDSETUP;
-
--static int
--qeth_determine_card_type(struct qeth_card *card)
--{
-- int i = 0;
+- if (!(rc = qeth_query_ipassists(card,QETH_PROT_IPV4)))
+- rc = qeth_get_unique_id(card);
-
-- QETH_DBF_TEXT(setup, 2, "detcdtyp");
+- 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;
+- }
-
-- 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++;
+- if ((rc = qeth_init_qdio_queues(card))){
+- QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
+- goto out_remove;
- }
-- card->info.type = QETH_CARD_TYPE_UNKNOWN;
-- PRINT_ERR("unknown card type on device %s\n", CARD_BUS_ID(card));
-- return -ENOENT;
+- 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_probe_device(struct ccwgroup_device *gdev)
+-qeth_set_online(struct ccwgroup_device *gdev)
-{
-- struct qeth_card *card;
-- struct device *dev;
-- unsigned long flags;
-- int rc;
+- return __qeth_set_online(gdev, 0);
+-}
-
-- QETH_DBF_TEXT(setup, 2, "probedev");
+-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);
-
-- dev = &gdev->dev;
-- if (!get_device(dev))
-- return -ENODEV;
+-struct device *qeth_root_dev = NULL;
-
-- QETH_DBF_TEXT_(setup, 2, "%s", gdev->dev.bus_id);
+-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,
+-};
-
-- card = qeth_alloc_card();
-- if (!card) {
-- put_device(dev);
-- QETH_DBF_TEXT_(setup, 2, "1err%d", -ENOMEM);
+-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;
- }
-- 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;
+- debug_register_view(qeth_dbf_setup, &debug_hex_ascii_view);
+- debug_set_level(qeth_dbf_setup, QETH_DBF_SETUP_LEVEL);
-
-- 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;
--}
+- 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);
-
--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;
+- debug_register_view(qeth_dbf_control, &debug_hex_ascii_view);
+- debug_set_level(qeth_dbf_control, QETH_DBF_CONTROL_LEVEL);
-
-- /*
-- * 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;
+- debug_register_view(qeth_dbf_sense, &debug_hex_ascii_view);
+- debug_set_level(qeth_dbf_sense, QETH_DBF_SENSE_LEVEL);
-
-- 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;
--}
+- debug_register_view(qeth_dbf_qerr, &debug_hex_ascii_view);
+- debug_set_level(qeth_dbf_qerr, QETH_DBF_QERR_LEVEL);
-
--static int
--qeth_get_unitaddr(struct qeth_card *card)
--{
-- int length;
-- char *prcd;
-- int rc;
+- debug_register_view(qeth_dbf_trace, &debug_hex_ascii_view);
+- debug_set_level(qeth_dbf_trace, QETH_DBF_TRACE_LEVEL);
-
-- 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;
--}
+-#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 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)
+-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;
-
-- 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);
--}
+- 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;
-
--/**
-- * get free buffer for ccws (IDX activation, lancmds,ipassists...)
-- */
--static struct qeth_cmd_buffer *
--__qeth_get_buffer(struct qeth_channel *channel)
--{
-- __u8 index;
+- rcu_read_lock();
+- in_dev = __in_dev_get_rcu(dev);
+- if (in_dev == NULL) {
+- rcu_read_unlock();
+- return -EINVAL;
+- }
-
-- 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);
+- parms = in_dev->arp_parms;
+- __neigh_parms_put(neigh->parms);
+- neigh->parms = neigh_parms_clone(parms);
+- rcu_read_unlock();
-
-- return NULL;
+- 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*/
-
--/**
-- * release command buffer
+-/*
+- * IP address takeover related functions
- */
-static void
--qeth_release_buffer(struct qeth_channel *channel, struct qeth_cmd_buffer *iob)
+-qeth_clear_ipato_list(struct qeth_card *card)
-{
+- struct qeth_ipato_entry *ipatoe, *tmp;
- 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);
+- 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);
-}
-
--static struct qeth_cmd_buffer *
--qeth_get_buffer(struct qeth_channel *channel)
+-int
+-qeth_add_ipato_entry(struct qeth_card *card, struct qeth_ipato_entry *new)
-{
-- struct qeth_cmd_buffer *buffer = NULL;
+- struct qeth_ipato_entry *ipatoe;
- unsigned long flags;
+- int rc = 0;
-
-- spin_lock_irqsave(&channel->iob_lock, flags);
-- buffer = __qeth_get_buffer(channel);
-- spin_unlock_irqrestore(&channel->iob_lock, flags);
-- return buffer;
+- 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;
-}
-
--static struct qeth_cmd_buffer *
--qeth_wait_for_buffer(struct qeth_channel *channel)
+-void
+-qeth_del_ipato_entry(struct qeth_card *card, enum qeth_prot_versions proto,
+- u8 *addr, int mask_bits)
-{
-- struct qeth_cmd_buffer *buffer;
-- wait_event(channel->wait_q,
-- ((buffer = qeth_get_buffer(channel)) != NULL));
-- return buffer;
+- 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_clear_cmd_buffers(struct qeth_channel *channel)
+-qeth_convert_addr_to_bits(u8 *addr, u8 *bits, int len)
-{
-- int cnt;
+- int i, j;
+- u8 octet;
-
-- 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;
+- for (i = 0; i < len; ++i){
+- octet = addr[i];
+- for (j = 7; j >= 0; --j){
+- bits[i*8 + j] = octet & 1;
+- octet >>= 1;
+- }
+- }
-}
-
--/**
-- * 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 *))
+-qeth_is_addr_covered_by_ipato(struct qeth_card *card, struct qeth_ipaddr *addr)
-{
-- 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);
+- struct qeth_ipato_entry *ipatoe;
+- u8 addr_bits[128] = {0, };
+- u8 ipatoe_bits[128] = {0, };
+- int rc = 0;
-
-- 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 (!card->ipato.enabled)
+- return 0;
-
-- 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;
+- 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;
- }
-- 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;
+- /* 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;
-}
-
--static int
--qeth_idx_activate_channel(struct qeth_channel *channel,
-- void (*idx_reply_cb)(struct qeth_channel *,
-- struct qeth_cmd_buffer *))
+-/*
+- * VIPA related functions
+- */
+-int
+-qeth_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
+- const u8 *addr)
-{
-- struct qeth_card *card;
-- struct qeth_cmd_buffer *iob;
+- struct qeth_ipaddr *ipaddr;
- unsigned long flags;
-- __u16 temp;
-- int rc;
+- int rc = 0;
-
-- card = CARD_FROM_CDEV(channel->ccwdev);
+- 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;
+-}
-
-- QETH_DBF_TEXT(setup, 2, "idxactch");
+-void
+-qeth_del_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
+- const u8 *addr)
+-{
+- struct qeth_ipaddr *ipaddr;
-
-- 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);
+- 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);
+-}
-
-- 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);
+-/*
+- * 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;
-
-- 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)
+- 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 (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);
+- if (!qeth_add_ip(card, ipaddr))
+- kfree(ipaddr);
+- qeth_set_ip_addr_list(card);
+- return 0;
-}
-
--static int
--qeth_peer_func_level(int level)
+-void
+-qeth_del_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
+- const u8 *addr)
-{
-- if ((level & 0xff) == 8)
-- return (level & 0xff) + 0x400;
-- if (((level >> 8) & 3) == 1)
-- return (level & 0xff) + 0x200;
-- return level;
+- 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);
-}
-
--static void
--qeth_idx_write_cb(struct qeth_channel *channel, struct qeth_cmd_buffer *iob)
+-/**
+- * 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;
-- __u16 temp;
-
-- QETH_DBF_TEXT(setup ,2, "idxwrcb");
+- 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;
-
-- if (channel->state == CH_STATE_DOWN) {
-- channel->state = CH_STATE_ACTIVATING;
+- 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;
-- }
-- 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;
+- 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;
- }
-- channel->state = CH_STATE_UP;
+- qeth_set_ip_addr_list(card);
-out:
-- qeth_release_buffer(channel, iob);
+- return NOTIFY_DONE;
-}
-
+-static struct notifier_block qeth_ip_notifier = {
+- qeth_ip_event,
+- NULL,
+-};
+-
+-#ifdef CONFIG_QETH_IPV6
+-/**
+- * IPv6 event handler
+- */
-static int
--qeth_check_idx_response(unsigned char *buffer)
+-qeth_ip6_event(struct notifier_block *this,
+- unsigned long event,void *ptr)
-{
-- 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 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;
-- __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;
-- }
+- QETH_DBF_TEXT(trace,3,"ip6event");
-
--/**
-- * 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;
+- card = qeth_get_card_from_dev(dev);
+- if (!card)
+- return NOTIFY_DONE;
+- if (!qeth_is_supported(card, IPA_IPV6))
+- return NOTIFY_DONE;
-
-- 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);
+- 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;
- }
-- 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;
+- qeth_set_ip_addr_list(card);
-out:
-- qeth_release_buffer(channel,iob);
+- return NOTIFY_DONE;
-}
-
+-static struct notifier_block qeth_ip6_notifier = {
+- qeth_ip6_event,
+- NULL,
+-};
+-#endif
+-
-static int
--qeth_issue_next_read(struct qeth_card *card)
+-__qeth_reboot_event_card(struct device *dev, void *data)
-{
-- int rc;
-- struct qeth_cmd_buffer *iob;
+- struct qeth_card *card;
-
-- 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;
+- 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 struct qeth_reply *
--qeth_alloc_reply(struct qeth_card *card)
+-static int
+-qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
-{
-- struct qeth_reply *reply;
+- int ret;
-
-- 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;
+- ret = driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
+- __qeth_reboot_event_card);
+- return ret ? NOTIFY_BAD : NOTIFY_DONE;
-}
-
--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)
+-static struct notifier_block qeth_reboot_notifier = {
+- qeth_reboot_event,
+- NULL,
+-};
+-
+-static int
+-qeth_register_notifiers(void)
-{
-- WARN_ON(atomic_read(&reply->refcnt) <= 0);
-- if (atomic_dec_and_test(&reply->refcnt))
-- kfree(reply);
+- 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_issue_ipa_msg(struct qeth_ipa_cmd *cmd, struct qeth_card *card)
+-qeth_unregister_notifiers(void)
-{
-- int rc;
-- int com;
-- char * ipa_name;
-
-- com = cmd->hdr.command;
-- rc = cmd->hdr.return_code;
-- ipa_name = qeth_get_ipa_cmd_name(com);
+- 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 */
-
-- 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)
+-#ifdef CONFIG_QETH_IPV6
+-static int
+-qeth_ipv6_init(void)
-{
-- struct qeth_ipa_cmd *cmd = NULL;
+- 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);
-
-- 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;
+- 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;
-}
-
--/**
-- * wake all waiting ipa commands
-- */
-static void
--qeth_clear_ipacmd_list(struct qeth_card *card)
+-qeth_ipv6_uninit(void)
-{
-- 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);
+- 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_send_control_data_cb(struct qeth_channel *channel,
-- struct qeth_cmd_buffer *iob)
+-qeth_sysfs_unregister(void)
-{
-- struct qeth_card *card;
-- struct qeth_reply *reply, *r;
-- struct qeth_ipa_cmd *cmd;
-- unsigned long flags;
-- int keep_reply;
+- s390_root_dev_unregister(qeth_root_dev);
+- qeth_remove_driver_attributes();
+- ccw_driver_unregister(&qeth_ccw_driver);
+- ccwgroup_driver_unregister(&qeth_ccwgroup_driver);
+-}
-
-- QETH_DBF_TEXT(trace,4,"sndctlcb");
+-/**
+- * register qeth at sysfs
+- */
+-static int
+-qeth_sysfs_register(void)
+-{
+- int rc;
-
-- card = CARD_FROM_CDEV(channel->ccwdev);
-- if (qeth_check_idx_response(iob->data)) {
-- qeth_clear_ipacmd_list(card);
-- qeth_schedule_recovery(card);
+- rc = ccwgroup_driver_register(&qeth_ccwgroup_driver);
+- if (rc)
- 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);
+- 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;
-- }
-
-- 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);
+- qeth_remove_driver_attributes();
+-out_qeth_attr:
+- ccw_driver_unregister(&qeth_ccw_driver);
+-out_ccw_driver:
+- ccwgroup_driver_unregister(&qeth_ccwgroup_driver);
-out:
-- memcpy(&card->seqno.pdu_hdr_ack,
-- QETH_PDU_HEADER_SEQ_NO(iob->data),
-- QETH_SEQ_NO_LENGTH);
-- qeth_release_buffer(channel,iob);
+- return rc;
-}
-
--static void
--qeth_prepare_control_data(struct qeth_card *card, int len,
-- struct qeth_cmd_buffer *iob)
+-/***
+- * init function
+- */
+-static int __init
+-qeth_init(void)
-{
-- qeth_setup_ccw(&card->write,iob->data,len);
-- iob->callback = qeth_release_buffer;
+- int rc;
-
-- 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);
--}
+- PRINT_INFO("loading %s\n", version);
-
--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)
+- 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);
-
--{
-- int rc;
-- unsigned long flags;
-- struct qeth_reply *reply = NULL;
-- unsigned long timeout;
+- rc = qeth_register_dbf_views();
+- if (rc)
+- goto out_err;
-
-- QETH_DBF_TEXT(trace, 2, "sendctl");
+- rc = qeth_sysfs_register();
+- if (rc)
+- goto out_dbf;
-
-- reply = qeth_alloc_reply(card);
-- if (!reply) {
-- PRINT_WARN("Could no alloc qeth_reply!\n");
-- return -ENOMEM;
+-#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;
- }
-- 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);
+-#endif /* QETH_IPV6 */
+- rc = qeth_register_notifiers();
+- if (rc)
+- goto out_ipv6;
+- rc = qeth_create_procfs_entries();
+- if (rc)
+- goto out_notifiers;
-
-- if (IS_IPA(iob->data))
-- timeout = jiffies + QETH_IPA_TIMEOUT;
-- else
-- timeout = jiffies + QETH_TIMEOUT;
+- return rc;
-
-- 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);
+-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 int
--qeth_osn_send_control_data(struct qeth_card *card, int len,
-- struct qeth_cmd_buffer *iob)
+-static void
+-__exit qeth_exit(void)
-{
+- struct qeth_card *card, *tmp;
- unsigned long flags;
-- int rc = 0;
-
-- QETH_DBF_TEXT(trace, 5, "osndctrd");
+- QETH_DBF_TEXT(trace,1, "cleanup.");
-
-- 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);
+- /*
+- * 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;
- }
-- return rc;
+- 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");
-}
-
--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);
--}
+-EXPORT_SYMBOL(qeth_osn_register);
+-EXPORT_SYMBOL(qeth_osn_deregister);
+-EXPORT_SYMBOL(qeth_osn_assist);
+-module_init(qeth_init);
+-module_exit(qeth_exit);
+-MODULE_AUTHOR("Frank Pavlic <fpavlic at de.ibm.com>");
+-MODULE_DESCRIPTION("Linux on zSeries OSA Express and HiperSockets support\n" \
+- "Copyright 2000,2003 IBM Corporation\n");
-
--static int
--qeth_osn_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
-- int data_len)
--{
-- u16 s1, s2;
+-MODULE_LICENSE("GPL");
+diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c
+deleted file mode 100644
+index f29a4bc..0000000
+--- a/drivers/s390/net/qeth_mpc.c
++++ /dev/null
+@@ -1,269 +0,0 @@
+-/*
+- * linux/drivers/s390/net/qeth_mpc.c
+- *
+- * Linux on zSeries OSA Express and HiperSockets support
+- *
+- * Copyright 2000,2003 IBM Corporation
+- * Author(s): Frank Pavlic <fpavlic at de.ibm.com>
+- * Thomas Spatzier <tspat at de.ibm.com>
+- *
+- */
+-#include <asm/cio.h>
+-#include "qeth_mpc.h"
-
-- QETH_DBF_TEXT(trace,4,"osndipa");
+-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
+-};
-
-- 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);
--}
+-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
+-};
-
--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;
+-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
+-};
-
-- QETH_DBF_TEXT(trace,4,"sendipa");
+-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
+-};
-
-- 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;
--}
+-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
+-};
-
--static int
--qeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
-- unsigned long data)
--{
-- struct qeth_cmd_buffer *iob;
+-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
+-};
-
-- QETH_DBF_TEXT(setup, 2, "cmenblcb");
+-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,
+-};
-
-- 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;
+-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;
-}
-
--static int
--qeth_cm_enable(struct qeth_card *card)
+-
+-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 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;
+- 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;
-}
-
--static int
--qeth_cm_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
-- unsigned long data)
--{
-
-- struct qeth_cmd_buffer *iob;
+diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h
+deleted file mode 100644
+index 6de2da5..0000000
+--- a/drivers/s390/net/qeth_mpc.h
++++ /dev/null
+@@ -1,583 +0,0 @@
+-/*
+- * linux/drivers/s390/net/qeth_mpc.h
+- *
+- * Linux on zSeries OSA Express and HiperSockets support
+- *
+- * Copyright 2000,2003 IBM Corporation
+- * Author(s): Utz Bacher <utz.bacher at de.ibm.com>
+- * Thomas Spatzier <tspat at de.ibm.com>
+- * Frank Pavlic <fpavlic at de.ibm.com>
+- *
+- */
+-#ifndef __QETH_MPC_H__
+-#define __QETH_MPC_H__
-
-- QETH_DBF_TEXT(setup, 2, "cmsetpcb");
+-#include <asm/qeth.h>
-
-- 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;
--}
+-#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)
-
--static int
--qeth_cm_setup(struct qeth_card *card)
--{
-- int rc;
-- struct qeth_cmd_buffer *iob;
+-extern unsigned char IPA_PDU_HEADER[];
+-#define QETH_IPA_CMD_DEST_ADDR(buffer) (buffer+0x2c)
-
-- QETH_DBF_TEXT(setup,2,"cmsetup");
+-#define IPA_CMD_LENGTH (IPA_PDU_HEADER_SIZE + sizeof(struct qeth_ipa_cmd))
-
-- 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;
+-#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
-
--static int
--qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
-- unsigned long data)
--{
+-#define QETH_CLEAR_CHANNEL_PARM -10
+-#define QETH_HALT_CHANNEL_PARM -11
+-#define QETH_RCD_PARM -12
-
-- __u16 mtu, framesize;
-- __u16 len;
-- __u8 link_type;
-- struct qeth_cmd_buffer *iob;
+-/*****************************************************************************/
+-/* 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
-
-- QETH_DBF_TEXT(setup, 2, "ulpenacb");
+-enum qeth_card_types {
+- QETH_CARD_TYPE_UNKNOWN = 0,
+- QETH_CARD_TYPE_OSAE = 10,
+- QETH_CARD_TYPE_IQD = 1234,
+- QETH_CARD_TYPE_OSN = 11,
+-};
-
-- 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;
-- }
+-#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,
+-};
-
-- 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;
--}
+-enum qeth_tr_macaddr_modes {
+- QETH_TR_MACADDR_NONCANONICAL = 0,
+- QETH_TR_MACADDR_CANONICAL = 1,
+-};
-
--static int
--qeth_ulp_enable(struct qeth_card *card)
--{
-- int rc;
-- char prot_type;
-- struct qeth_cmd_buffer *iob;
+-enum qeth_tr_broadcast_modes {
+- QETH_TR_BROADCAST_ALLRINGS = 0,
+- QETH_TR_BROADCAST_LOCAL = 1,
+-};
-
-- /*FIXME: trace view callbacks*/
-- QETH_DBF_TEXT(setup,2,"ulpenabl");
+-/* 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
-
-- iob = qeth_wait_for_buffer(&card->write);
-- memcpy(iob->data, ULP_ENABLE, ULP_ENABLE_SIZE);
+-/*
+- * 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,
+-};
-
-- *(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;
+-/* 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
+-};
-
-- 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;
+-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,
+-};
-
--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");
+-/* Return Codes for IPA Commands
+- * according to OSA card Specs */
-
-- 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;
--}
+-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
+-};
-
--static int
--qeth_ulp_setup(struct qeth_card *card)
--{
-- int rc;
-- __u16 temp;
-- struct qeth_cmd_buffer *iob;
-- struct ccw_dev_id dev_id;
+-/* 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,
+-};
-
-- QETH_DBF_TEXT(setup,2,"ulpsetup");
+-/* 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,
+-};
-
-- iob = qeth_wait_for_buffer(&card->write);
-- memcpy(iob->data, ULP_SETUP, ULP_SETUP_SIZE);
+-/* 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,
+-};
-
-- 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);
+-/* (SET)DELIP(M) IPA stuff ***************************************************/
+-struct qeth_ipacmd_setdelip4 {
+- __u8 ip_addr[4];
+- __u8 mask[4];
+- __u32 flags;
+-} __attribute__ ((packed));
-
-- 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;
--}
+-struct qeth_ipacmd_setdelip6 {
+- __u8 ip_addr[16];
+- __u8 mask[16];
+- __u32 flags;
+-} __attribute__ ((packed));
-
--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;
--}
+-struct qeth_ipacmd_setdelipm {
+- __u8 mac[6];
+- __u8 padding[2];
+- __u8 ip6[12];
+- __u8 ip4[4];
+-} __attribute__ ((packed));
-
--static struct sk_buff *
--qeth_get_skb(unsigned int length, struct qeth_hdr *hdr)
--{
-- struct sk_buff* skb;
-- int add_len;
+-struct qeth_ipacmd_layer2setdelmac {
+- __u32 mac_length;
+- __u8 mac[6];
+-} __attribute__ ((packed));
-
-- 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;
--}
+-struct qeth_ipacmd_layer2setdelvlan {
+- __u16 vlan_id;
+-} __attribute__ ((packed));
-
--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;
+-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));
-
-- if (list_empty(&card->qdio.in_buf_pool.entry_list))
-- return NULL;
+-struct qeth_arp_query_data {
+- __u16 request_bits;
+- __u16 reply_bits;
+- __u32 no_entries;
+- char data;
+-} __attribute__((packed));
-
-- 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;
-- }
-- }
+-/* 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;
+-};
-
-- /* 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;
--}
+-/* 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));
-
--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;
+-/* SETRTG IPA Command: ****************************************************/
+-struct qeth_set_routing {
+- __u8 type;
+-};
-
-- 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;
+-/* 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));
-
-- 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;
-- }
-- }
+-struct qeth_change_addr {
+- __u32 cmd;
+- __u32 addr_size;
+- __u32 no_macs;
+- __u8 addr[OSA_ADDR_LEN];
+-} __attribute__ ((packed));
-
-- 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;
+-struct qeth_snmp_cmd {
+- __u8 token[16];
+- __u32 request;
+- __u32 interface;
+- __u32 returncode;
+- __u32 firmwarelevel;
+- __u32 seqno;
+- __u8 data;
+-} __attribute__ ((packed));
-
-- QETH_DBF_TEXT(trace,6,"typtrans");
+-struct qeth_snmp_ureq_hdr {
+- __u32 data_len;
+- __u32 req_len;
+- __u32 reserved1;
+- __u32 reserved2;
+-} __attribute__ ((packed));
-
-- 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);
+-struct qeth_snmp_ureq {
+- struct qeth_snmp_ureq_hdr hdr;
+- struct qeth_snmp_cmd cmd;
+-} __attribute__((packed));
-
-- 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;
+-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));
-
-- 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);
--}
+-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));
-
--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;
+-/* IPFRAME IPA Command: ***************************************************/
+-/* TODO: define in analogy to commands define above */
-
-- 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);
+-/* ADD_ADDR_ENTRY IPA Command: ********************************************/
+-/* TODO: define in analogy to commands define above */
-
-- /* 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;
--}
+-/* DELETE_ADDR_ENTRY IPA Command: *****************************************/
+-/* TODO: define in analogy to commands define above */
-
--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;
+-/* CREATE_ADDR IPA Command: ***********************************************/
+-struct qeth_create_destroy_address {
+- __u8 unique_id[8];
+-} __attribute__ ((packed));
-
-- 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);
+-/* REGISTER_LOCAL_ADDR IPA Command: ***************************************/
+-/* TODO: define in analogy to commands define above */
-
-- /* 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;
--}
+-/* UNREGISTER_LOCAL_ADDR IPA Command: *************************************/
+-/* TODO: define in analogy to commands define above */
-
--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);
--}
+-/* 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));
-
--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;
--}
+-/* 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));
-
--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;
-- }
+-/*
+- * 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,
+-};
-
-- 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;
--}
+-extern char *
+-qeth_get_ipa_msg(enum qeth_ipa_return_codes rc);
+-extern char *
+-qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd);
-
--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;
+-#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
-
-- /* 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;
-- }
--}
+-#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))
-
--static int
--qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf)
--{
-- struct qeth_buffer_pool_entry *pool_entry;
-- int i;
+-/*****************************************************************************/
+-/* END OF IP Assist related definitions */
+-/*****************************************************************************/
-
-- 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;
--}
+-extern unsigned char WRITE_CCW[];
+-extern unsigned char READ_CCW[];
-
--static void
--qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
-- struct qeth_qdio_out_buffer *buf)
--{
-- int i;
-- struct sk_buff *skb;
+-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)
-
-- /* is PCI flag set on buffer? */
-- if (buf->buffer->element[0].flags & 0x40)
-- atomic_dec(&queue->set_pci_flags_count);
+-#define QETH_CM_ENABLE_RESP_FILTER_TOKEN(buffer) \
+- (PDU_ENCAPSULATION(buffer)+ 0x13)
-
-- 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;
+-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)
-
-- 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++;
-- }
-- }
+-#define QETH_CM_SETUP_RESP_DEST_ADDR(buffer) \
+- (PDU_ENCAPSULATION(buffer) + 0x1a)
-
-- 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);
-- }
+-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)
-
-- /*
-- * 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;
-- }
--}
+-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)
-
--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);
--}
+-#define QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(buffer) \
+- (PDU_ENCAPSULATION(buffer)+0x1a)
-
--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;
--}
+-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)
-
--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;
+-#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)
-
-- QETH_DBF_TEXT(trace, 6, "flushbuf");
+-extern unsigned char IDX_ACTIVATE_READ[];
+-extern unsigned char IDX_ACTIVATE_WRITE[];
-
-- 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;
+-#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]
-
-- if (queue->card->info.type == QETH_CARD_TYPE_IQD)
-- continue;
+-#define PDU_ENCAPSULATION(buffer) \
+- (buffer + *(buffer + (*(buffer+0x0b)) + \
+- *(buffer + *(buffer+0x0b)+0x11) +0x07))
-
-- 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;
-- }
-- }
-- }
+-#define IS_IPA(buffer) \
+- ((buffer) && \
+- ( *(buffer + ((*(buffer+0x0b))+4) )==0xc1) )
-
-- 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;
--}
+-#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 @@
-/*
-- * Switched to packing state if the number of used buffers on a queue
-- * reaches a certain limit.
+- *
+- * linux/drivers/s390/net/qeth_fs.c
+- *
+- * Linux on zSeries OSA Express and HiperSockets support
+- * This file contains code related to procfs.
+- *
+- * Copyright 2000,2003 IBM Corporation
+- *
+- * Author(s): Thomas Spatzier <tspat at de.ibm.com>
+- *
- */
--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;
-- }
-- }
--}
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/proc_fs.h>
+-#include <linux/seq_file.h>
+-#include <linux/list.h>
+-#include <linux/rwsem.h>
-
--/*
-- * 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;
+-#include "qeth.h"
+-#include "qeth_mpc.h"
+-#include "qeth_fs.h"
-
-- 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;
--}
+-/***** /proc/qeth *****/
+-#define QETH_PROCFILE_NAME "qeth"
+-static struct proc_dir_entry *qeth_procfile;
-
--/*
-- * 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)
+-qeth_procfile_seq_match(struct device *dev, void *data)
-{
-- 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;
+- return(dev ? 1 : 0);
-}
-
--static void
--qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
+-static void *
+-qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)
-{
-- int index;
-- int flush_cnt = 0;
-- int q_was_packing = 0;
+- struct device *dev = NULL;
+- loff_t nr = 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);
-- }
+- 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_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)
+-qeth_procfile_seq_stop(struct seq_file *s, void* it)
-{
-- 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)
+-static void *
+-qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
-{
+- struct device *prev, *next;
-
-- 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;
+- 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 void
--qeth_initialize_working_pool_list(struct qeth_card *card)
+-static inline const char *
+-qeth_get_router_str(struct qeth_card *card, int ipv)
-{
-- struct qeth_buffer_pool_entry *entry;
+- enum qeth_routing_types routing_type = NO_ROUTER;
-
-- QETH_DBF_TEXT(trace,5,"inwrklst");
+- 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 */
+- }
-
-- list_for_each_entry(entry,
-- &card->qdio.init_pool.entry_list, init_list) {
-- qeth_put_buffer_pool_entry(card,entry);
+- 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 void
--qeth_clear_working_pool_list(struct qeth_card *card)
+-static int
+-qeth_procfile_seq_show(struct seq_file *s, void *it)
-{
-- struct qeth_buffer_pool_entry *pool_entry, *tmp;
+- struct device *device;
+- struct qeth_card *card;
+- char tmp[12]; /* for qeth_get_prioq_str */
-
-- 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);
+- 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 void
--qeth_free_buffer_pool(struct qeth_card *card)
+-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)
-{
-- 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);
-- }
+- 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_alloc_buffer_pool(struct qeth_card *card)
+-qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
-{
-- struct qeth_buffer_pool_entry *pool_entry;
-- void *ptr;
-- int i, j;
+- struct device *device;
+- struct qeth_card *card;
-
-- 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);
-- }
+-
+- 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;
-}
-
--int
--qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt)
+-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)
-{
-- QETH_DBF_TEXT(trace, 2, "realcbp");
+- return seq_open(file, &qeth_perf_procfile_seq_ops);
+-}
-
-- if ((card->state != CARD_STATE_DOWN) &&
-- (card->state != CARD_STATE_RECOVER))
-- return -EPERM;
+-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,
+-};
-
-- /* 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 __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;
-}
-
--static int
--qeth_alloc_qdio_buffers(struct qeth_card *card)
+-void __exit
+-qeth_remove_procfs_entries(void)
-{
-- int i, j;
+- if (qeth_procfile)
+- remove_proc_entry(QETH_PROCFILE_NAME, NULL);
+- if (qeth_perf_procfile)
+- remove_proc_entry(QETH_PERF_PROCFILE_NAME, NULL);
+-}
-
-- QETH_DBF_TEXT(setup, 2, "allcqdbf");
+diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
+deleted file mode 100644
+index 2cc3f3a..0000000
+--- a/drivers/s390/net/qeth_sys.c
++++ /dev/null
+@@ -1,1858 +0,0 @@
+-/*
+- *
+- * linux/drivers/s390/net/qeth_sys.c
+- *
+- * Linux on zSeries OSA Express and HiperSockets support
+- * This file contains code related to sysfs.
+- *
+- * Copyright 2000,2003 IBM Corporation
+- *
+- * Author(s): Thomas Spatzier <tspat at de.ibm.com>
+- * Frank Pavlic <fpavlic at de.ibm.com>
+- *
+- */
+-#include <linux/list.h>
+-#include <linux/rwsem.h>
-
-- if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED,
-- QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED)
-- return 0;
+-#include <asm/ebcdic.h>
-
-- 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;
+-#include "qeth.h"
+-#include "qeth_mpc.h"
+-#include "qeth_fs.h"
-
--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;
+-/*****************************************************************************/
+-/* */
+-/* /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 void
--qeth_free_qdio_buffers(struct qeth_card *card)
+-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)
-{
-- int i, j;
+- struct qeth_card *card = dev->driver_data;
+- if (!card)
+- return -EINVAL;
-
-- 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;
-- }
+- return sprintf(buf, "%02X\n", card->info.chpid);
-}
-
--static void
--qeth_clear_qdio_buffers(struct qeth_card *card)
+-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)
-{
-- int i, j;
+- struct qeth_card *card = dev->driver_data;
+- if (!card)
+- return -EINVAL;
+- return sprintf(buf, "%s\n", QETH_CARD_IFNAME(card));
+-}
-
-- 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 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 void
--qeth_init_qdio_info(struct qeth_card *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)
-{
-- 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);
+- struct qeth_card *card = dev->driver_data;
+- if (!card)
+- return -EINVAL;
+-
+- return sprintf(buf, "%i\n", card->info.portno);
-}
-
--static int
--qeth_init_qdio_queues(struct qeth_card *card)
+-static ssize_t
+-qeth_dev_portno_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-- int i, j;
-- int rc;
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+- unsigned int portno;
-
-- QETH_DBF_TEXT(setup, 2, "initqdqs");
+- if (!card)
+- return -EINVAL;
-
-- /* 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);
+- 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;
- }
-- return 0;
+-
+- card->info.portno = portno;
+- return count;
-}
-
--static int
--qeth_qdio_establish(struct qeth_card *card)
+-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 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;
+- struct qeth_card *card = dev->driver_data;
+- char portname[9] = {0, };
-
-- QETH_DBF_TEXT(setup, 2, "qdioest");
+- if (!card)
+- return -EINVAL;
-
-- qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char),
-- GFP_KERNEL);
-- if (!qib_param_field)
-- return -ENOMEM;
+- 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");
+-}
-
-- qeth_create_qib_param_field(card, qib_param_field);
-- qeth_create_qib_param_field_blkt(card, qib_param_field);
+-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;
-
-- 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);
+- if (!card)
+- return -EINVAL;
-
-- 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);
-- }
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
-
-- 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;
+- tmp = strsep((char **) &buf, "\n");
+- if ((strlen(tmp) > 8) || (strlen(tmp) == 0))
+- return -EINVAL;
-
-- 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);
+- 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);
-
-- kfree(out_sbal_ptrs);
-- kfree(in_sbal_ptrs);
-- kfree(qib_param_field);
-- return rc;
+- return count;
-}
-
--static int
--qeth_qdio_activate(struct qeth_card *card)
--{
-- QETH_DBF_TEXT(setup,3,"qdioact");
-- return qdio_activate(CARD_DDEV(card), 0);
--}
+-static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
+- qeth_dev_portname_store);
-
--static int
--qeth_clear_channel(struct qeth_channel *channel)
+-static ssize_t
+-qeth_dev_checksum_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-- unsigned long flags;
-- struct qeth_card *card;
-- int rc;
+- struct qeth_card *card = dev->driver_data;
-
-- 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 (!card)
+- return -EINVAL;
-
-- 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;
+- return sprintf(buf, "%s checksumming\n", qeth_get_checksum_str(card));
-}
-
--static int
--qeth_halt_channel(struct qeth_channel *channel)
+-static ssize_t
+-qeth_dev_checksum_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-- unsigned long flags;
-- struct qeth_card *card;
-- int rc;
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
-
-- 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 (!card)
+- return -EINVAL;
-
-- 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;
+- 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 int
--qeth_halt_channels(struct qeth_card *card)
--{
-- int rc1 = 0, rc2=0, rc3 = 0;
+-static DEVICE_ATTR(checksumming, 0644, qeth_dev_checksum_show,
+- qeth_dev_checksum_store);
-
-- 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)
+-static ssize_t
+-qeth_dev_prioqing_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-- int rc1 = 0, rc2=0, rc3 = 0;
+- struct qeth_card *card = dev->driver_data;
-
-- 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;
+- 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 int
--qeth_clear_halt_card(struct qeth_card *card, int halt)
+-static ssize_t
+-qeth_dev_prioqing_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-- int rc = 0;
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
-
-- QETH_DBF_TEXT(trace,3,"clhacrd");
-- QETH_DBF_HEX(trace, 3, &card, sizeof(void *));
+- if (!card)
+- return -EINVAL;
-
-- if (halt)
-- rc = qeth_halt_channels(card);
-- if (rc)
-- return rc;
-- return qeth_clear_channels(card);
--}
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
-
--static int
--qeth_qdio_clear_card(struct qeth_card *card, int use_halt)
--{
-- int rc = 0;
+- /* 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;
+- }
-
-- 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;
+- 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;
- }
-- if ((rc = qeth_clear_halt_card(card, use_halt)))
-- QETH_DBF_TEXT_(trace, 3, "2err%d", rc);
-- card->state = CARD_STATE_DOWN;
-- return rc;
+- return count;
-}
-
--static int
--qeth_dm_act(struct qeth_card *card)
--{
-- int rc;
-- struct qeth_cmd_buffer *iob;
+-static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show,
+- qeth_dev_prioqing_store);
-
-- QETH_DBF_TEXT(setup,2,"dmact");
+-static ssize_t
+-qeth_dev_bufcnt_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
-
-- iob = qeth_wait_for_buffer(&card->write);
-- memcpy(iob->data, DM_ACT, DM_ACT_SIZE);
+- if (!card)
+- return -EINVAL;
-
-- 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;
+- return sprintf(buf, "%i\n", card->qdio.in_buf_pool.buf_count);
-}
-
--static int
--qeth_mpc_initialize(struct qeth_card *card)
+-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;
-
-- QETH_DBF_TEXT(setup,2,"mpcinit");
+- if (!card)
+- return -EINVAL;
-
-- 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;
-- }
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
-
-- return 0;
--out_qdio:
-- qeth_qdio_clear_card(card, card->info.type!=QETH_CARD_TYPE_IQD);
-- return rc;
+- 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 struct net_device *
--qeth_get_netdevice(enum qeth_card_types type, enum qeth_link_types linktype)
--{
-- struct net_device *dev = NULL;
+-static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
+- qeth_dev_bufcnt_store);
-
-- 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;
+-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:
-- dev = alloc_etherdev(0);
+- return sprintf(buf, "%s\n", "no");
- }
-- 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)
+-static ssize_t
+-qeth_dev_route4_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-- 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;
+- struct qeth_card *card = dev->driver_data;
-
-- } 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;
+- if (!card)
+- return -EINVAL;
-
-- }
+- return qeth_dev_route_show(card, &card->options.route4, buf);
-}
-
--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)
+-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;
-- 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();
+- 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;
- }
-- 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;
-- }
+- 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);
- }
-- 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;
+- return count;
-}
-
--static int
--qeth_verify_vlan_dev(struct net_device *dev, struct qeth_card *card)
+-static ssize_t
+-qeth_dev_route4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-- int rc = 0;
--#ifdef CONFIG_QETH_VLAN
-- struct vlan_group *vg;
-- int i;
--
-- if (!(vg = card->vlangrp))
-- return rc;
+- struct qeth_card *card = dev->driver_data;
-
-- 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;
+- if (!card)
+- return -EINVAL;
-
--#endif
-- return rc;
+- return qeth_dev_route_store(card, &card->options.route4,
+- QETH_PROT_IPV4, buf, count);
-}
-
--static int
--qeth_verify_dev(struct net_device *dev)
+-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;
-- unsigned long flags;
-- int rc = 0;
+- struct qeth_card *card = dev->driver_data;
-
-- 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);
+- if (!card)
+- return -EINVAL;
-
-- return rc;
+- 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 struct qeth_card *
--qeth_get_card_from_dev(struct net_device *dev)
+-static ssize_t
+-qeth_dev_route6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-- struct qeth_card *card = NULL;
-- int rc;
+- struct qeth_card *card = dev->driver_data;
-
-- 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;
+- if (!card)
+- return -EINVAL;
-
-- QETH_DBF_TEXT_(trace, 4, "%d", rc);
-- return card ;
+- 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 void
--qeth_tx_timeout(struct net_device *dev)
+-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;
+- struct qeth_card *card = dev->driver_data;
-
-- card = (struct qeth_card *) dev->priv;
-- card->stats.tx_errors++;
-- qeth_schedule_recovery(card);
+- if (!card)
+- return -EINVAL;
+-
+- return sprintf(buf, "%i\n", card->options.add_hhlen);
-}
-
--static int
--qeth_open(struct net_device *dev)
+-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;
--
-- QETH_DBF_TEXT(trace, 4, "qethopen");
--
-- card = (struct qeth_card *) dev->priv;
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+- int i;
-
-- if (card->state != CARD_STATE_SOFTSETUP)
-- return -ENODEV;
+- if (!card)
+- return -EINVAL;
-
-- 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");
+- 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->data.state = CH_STATE_UP;
-- card->state = CARD_STATE_UP;
-- card->dev->flags |= IFF_UP;
-- netif_start_queue(dev);
+- card->options.add_hhlen = i;
-
-- if (!card->lan_online && netif_carrier_ok(dev))
-- netif_carrier_off(dev);
-- return 0;
+- return count;
-}
-
--static int
--qeth_stop(struct net_device *dev)
--{
-- struct qeth_card *card;
+-static DEVICE_ATTR(add_hhlen, 0644, qeth_dev_add_hhlen_show,
+- qeth_dev_add_hhlen_store);
-
-- QETH_DBF_TEXT(trace, 4, "qethstop");
+-static ssize_t
+-qeth_dev_fake_ll_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
-
-- card = (struct qeth_card *) dev->priv;
+- if (!card)
+- return -EINVAL;
-
-- netif_tx_disable(dev);
-- card->dev->flags &= ~IFF_UP;
-- if (card->state == CARD_STATE_UP)
-- card->state = CARD_STATE_SOFTSETUP;
-- return 0;
+- return sprintf(buf, "%i\n", card->options.fake_ll? 1:0);
-}
-
--static int
--qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
+-static ssize_t
+-qeth_dev_fake_ll_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-- int cast_type = RTN_UNSPEC;
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+- int i;
-
-- if (card->info.type == QETH_CARD_TYPE_OSN)
-- return cast_type;
+- if (!card)
+- return -EINVAL;
-
-- 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;
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
-
-- 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;
+- 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 int
--qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
-- int ipv, int cast_type)
+-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)
-{
-- 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;
+- struct qeth_card *card = dev->driver_data;
-
-- 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;
-- }
+- if (!card)
+- return -EINVAL;
+-
+- return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
-}
-
--static inline int
--qeth_get_ip_version(struct sk_buff *skb)
+-static ssize_t
+-qeth_dev_fake_broadcast_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-- switch (skb->protocol) {
-- case ETH_P_IPV6:
-- return 6;
-- case ETH_P_IP:
-- return 4;
-- default:
-- return 0;
+- 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 struct qeth_hdr *
--__qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv)
+-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)
-{
--#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)));
+- 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 void
--__qeth_free_new_skb(struct sk_buff *orig_skb, struct sk_buff *new_skb)
+-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)
-{
-- if (orig_skb != new_skb)
-- dev_kfree_skb_any(new_skb);
+- 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 struct sk_buff *
--qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb,
-- struct qeth_hdr **hdr, int ipv)
+-static ssize_t
+-qeth_dev_broadcast_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-- 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;
+- 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;
- }
-- 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;
+-
+- 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 new_skb;
+- return count;
-}
-
--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 DEVICE_ATTR(broadcast_mode, 0644, qeth_dev_broadcast_mode_show,
+- qeth_dev_broadcast_mode_store);
-
--static inline u8
--qeth_get_qeth_hdr_flags6(int cast_type)
+-static ssize_t
+-qeth_dev_canonical_macaddr_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-- 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;
--}
+- struct qeth_card *card = dev->driver_data;
-
--static void
--qeth_layer2_get_packet_type(struct qeth_card *card, struct qeth_hdr *hdr,
-- struct sk_buff *skb)
--{
-- __u16 hdr_mac;
+- if (!card)
+- return -EINVAL;
-
-- 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;
-- }
+- 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 void
--qeth_layer2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
-- struct sk_buff *skb, int cast_type)
+-static ssize_t
+-qeth_dev_canonical_macaddr_store(struct device *dev, struct device_attribute *attr, const char *buf,
+- size_t count)
-{
-- memset(hdr, 0, sizeof(struct qeth_hdr));
-- hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2;
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+- int i;
-
-- /* 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);
+- if (!card)
+- return -EINVAL;
-
-- 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);
+- 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;
- }
--#endif
+-
+- 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;
-}
-
--void
--qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
-- struct sk_buff *skb, int ipv, int cast_type)
+-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)
-{
-- QETH_DBF_TEXT(trace, 6, "fillhdr");
+- struct qeth_card *card = dev->driver_data;
-
-- 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;
-- }
-- }
+- if (!card)
+- return -EINVAL;
+-
+- return sprintf(buf, "%i\n", card->options.layer2 ? 1:0);
-}
-
--static void
--__qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
-- int is_tso, int *next_element_to_fill)
+-static ssize_t
+-qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-- int length = skb->len;
-- int length_here;
-- int element;
-- char *data;
-- int first_lap ;
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+- int i;
-
-- element = *next_element_to_fill;
-- data = skb->data;
-- first_lap = (is_tso == 0 ? 1 : 0);
+- if (!card)
+- return -EINVAL;
+- if (card->info.type == QETH_CARD_TYPE_IQD) {
+- PRINT_WARN("Layer2 on Hipersockets is not supported! \n");
+- return -EPERM;
+- }
-
-- 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;
+- if (((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER)))
+- return -EPERM;
-
-- 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;
+- 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;
- }
-- *next_element_to_fill = element;
+- return count;
-}
-
--static int
--qeth_fill_buffer(struct qeth_qdio_out_q *queue,
-- struct qeth_qdio_out_buffer *buf,
-- struct sk_buff *skb)
+-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 qdio_buffer *buffer;
-- struct qeth_hdr_tso *hdr;
-- int flush_cnt = 0, hdr_len, large_send = 0;
+- struct qeth_card *card = dev->driver_data;
-
-- QETH_DBF_TEXT(trace, 6, "qdfillbf");
+- if (!card)
+- return -EINVAL;
-
-- buffer = buf->buffer;
-- atomic_inc(&skb->users);
-- skb_queue_tail(&buf->skb_list, skb);
+- return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0);
+-}
-
-- 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;
+-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;
-
-- 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 (!card)
+- return -EINVAL;
-
-- 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;
+- 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 {
-- 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;
-- }
+- PRINT_WARN("performance_stats: write 0 or 1 to this file!\n");
+- return -EINVAL;
- }
-- return flush_cnt;
+- return count;
-}
-
--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)
+-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_qdio_out_buffer *buffer;
-- int buffers_needed = 0;
-- int flush_cnt = 0;
-- int index;
+- struct qeth_card *card = dev->driver_data;
-
-- QETH_DBF_TEXT(trace, 6, "dosndpfa");
+- if (!card)
+- return -EINVAL;
-
-- /* 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);
+- 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");
- }
-- 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)
+-static ssize_t
+-qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-- struct qeth_qdio_out_buffer *buffer;
-- int start_index;
-- int flush_count = 0;
-- int do_pack = 0;
-- int tmp;
+- struct qeth_card *card = dev->driver_data;
+- enum qeth_large_send_types type;
- int rc = 0;
+- char *tmp;
-
-- 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);
+- 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;
- }
-- /* 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;
+- if (card->options.large_send == type)
+- return count;
+- if ((rc = qeth_set_large_send(card, type)))
+- return rc;
+- return count;
-}
-
--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 DEVICE_ATTR(large_send, 0644, qeth_dev_large_send_show,
+- qeth_dev_large_send_store);
-
--static void qeth_tx_csum(struct sk_buff *skb)
+-static ssize_t
+-qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value )
-{
-- 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;
-- }
-- }
+- if (!card)
+- return -EINVAL;
+-
+- return sprintf(buf, "%i\n", value);
-}
-
--static int
--qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
+-static ssize_t
+-qeth_dev_blkt_store(struct qeth_card *card, const char *buf, size_t count,
+- int *value, int max_value)
-{
-- 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;
+- char *tmp;
+- int i;
-
-- QETH_DBF_TEXT(trace, 6, "sendpkt");
+- if (!card)
+- return -EINVAL;
-
-- 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))
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
- 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;
-- }
-- }
+- i = simple_strtoul(buf, &tmp, 10);
+- if (i <= max_value) {
+- *value = i;
- } 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);
+- PRINT_WARN("blkt total time: write values between"
+- " 0 and %d to this file!\n", max_value);
+- return -EINVAL;
- }
-- return rc;
+- return count;
-}
-
--static int
--qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
+-static ssize_t
+-qeth_dev_blkt_total_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-- struct qeth_card *card = (struct qeth_card *) dev->priv;
-- int rc = 0;
+- struct qeth_card *card = dev->driver_data;
-
-- 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;
+- return qeth_dev_blkt_show(buf, card, card->info.blkt.time_total);
-}
-
-
--static const char *
--qeth_arp_get_error_cause(int *rc)
+-static ssize_t
+-qeth_dev_blkt_total_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-- 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";
-- }
+- struct qeth_card *card = dev->driver_data;
+-
+- return qeth_dev_blkt_store(card, buf, count,
+- &card->info.blkt.time_total,1000);
-}
-
--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)
+-
+-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)
-{
-- int tmp;
-- int rc;
+- struct qeth_card *card = dev->driver_data;
-
-- QETH_DBF_TEXT(trace,3,"arpstnoe");
+- return qeth_dev_blkt_show(buf, card, card->info.blkt.inter_packet);
+-}
-
-- /*
-- * 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 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 void
--qeth_copy_arp_entries_stripped(struct qeth_arp_query_info *qinfo,
-- struct qeth_arp_query_data *qdata,
-- int entry_size, int uentry_size)
+-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)
-{
-- char *entry_ptr;
-- char *uentry_ptr;
-- int i;
+- struct qeth_card *card = dev->driver_data;
-
-- 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;
-- }
+- return qeth_dev_blkt_show(buf, card,
+- card->info.blkt.inter_packet_jumbo);
-}
-
--static int
--qeth_arp_query_cb(struct qeth_card *card, struct qeth_reply *reply,
-- unsigned long data)
+-
+-static ssize_t
+-qeth_dev_blkt_inter_jumbo_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-- 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;
+- struct qeth_card *card = dev->driver_data;
-
-- QETH_DBF_TEXT(trace,4,"arpquecb");
+- return qeth_dev_blkt_store(card, buf, count,
+- &card->info.blkt.inter_packet_jumbo,100);
+-}
-
-- 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);
+-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,
+-};
-
-- 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);
+-static struct attribute_group qeth_device_attr_group = {
+- .attrs = (struct attribute **)qeth_device_attrs,
+-};
-
-- 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 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_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_check_layer2(struct qeth_card *card)
-{
-- 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);
+- if (card->options.layer2)
+- return -EPERM;
+- return 0;
-}
-
--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)
+-
+-static ssize_t
+-qeth_dev_ipato_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-- u16 s1, s2;
+- struct qeth_card *card = dev->driver_data;
-
-- QETH_DBF_TEXT(trace,4,"sendsnmp");
+- if (!card)
+- return -EINVAL;
-
-- 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);
+- if (qeth_check_layer2(card))
+- return -EPERM;
+- return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
-}
-
--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)
+-static ssize_t
+-qeth_dev_ipato_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-- struct qeth_cmd_buffer *iob;
-- struct qeth_arp_query_info qinfo = {0, };
-- int tmp;
-- int rc;
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
-
-- QETH_DBF_TEXT(trace,3,"arpquery");
+- if (!card)
+- return -EINVAL;
-
-- 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);
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
-
-- 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;
+- 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 {
-- if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
-- rc = -EFAULT;
+- PRINT_WARN("ipato_enable: write 0, 1 or 'toggle' to "
+- "this file\n");
+- return -EINVAL;
- }
-- kfree(qinfo.udata);
-- return rc;
+- return count;
-}
-
--/**
-- * SNMP command callback
-- */
--static int
--qeth_snmp_command_cb(struct qeth_card *card, struct qeth_reply *reply,
-- unsigned long sdata)
+-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_ipa_cmd *cmd;
-- struct qeth_arp_query_info *qinfo;
-- struct qeth_snmp_cmd *snmp;
-- unsigned char *data;
-- __u16 data_len;
+- struct qeth_card *card = dev->driver_data;
-
-- QETH_DBF_TEXT(trace,3,"snpcmdcb");
+- if (!card)
+- return -EINVAL;
-
-- 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 (qeth_check_layer2(card))
+- return -EPERM;
-
-- 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);
+- return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
+-}
-
-- /* 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);
+-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 {
-- memcpy(qinfo->udata + qinfo->udata_offset,
-- (char *)&snmp->request, data_len);
+- PRINT_WARN("ipato_invert4: write 0, 1 or 'toggle' to "
+- "this file\n");
+- return -EINVAL;
- }
-- 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;
+- return count;
-}
-
--static struct qeth_cmd_buffer *
--qeth_get_ipacmd_buffer(struct qeth_card *, enum qeth_ipa_cmds,
-- enum qeth_prot_versions );
+-static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
+- qeth_dev_ipato_invert4_show,
+- qeth_dev_ipato_invert4_store);
-
--static struct qeth_cmd_buffer *
--qeth_get_adapter_cmd(struct qeth_card *card, __u32 command, __u32 cmdlen)
+-static ssize_t
+-qeth_dev_ipato_add_show(char *buf, struct qeth_card *card,
+- enum qeth_prot_versions proto)
-{
-- struct qeth_cmd_buffer *iob;
-- struct qeth_ipa_cmd *cmd;
+- 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;
-
-- 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;
+- if (qeth_check_layer2(card))
+- return -EPERM;
-
-- return iob;
+- entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
+- /* add strlen for "/<mask>\n" */
+- entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
+- spin_lock_irqsave(&card->ip_lock, flags);
+- list_for_each_entry(ipatoe, &card->ipato.entries, entry){
+- if (ipatoe->proto != proto)
+- continue;
+- /* String must not be longer than PAGE_SIZE. So we check if
+- * string length gets near PAGE_SIZE. Then we can savely display
+- * the next IPv6 address (worst case, compared to IPv4) */
+- if ((PAGE_SIZE - i) <= entry_len)
+- break;
+- qeth_ipaddr_to_string(proto, ipatoe->addr, addr_str);
+- i += snprintf(buf + i, PAGE_SIZE - i,
+- "%s/%i\n", addr_str, ipatoe->mask_bits);
+- }
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- i += snprintf(buf + i, PAGE_SIZE - i, "\n");
+-
+- return i;
-}
-
--/**
-- * function to send SNMP commands to OSA-E card
-- */
--static int
--qeth_snmp_command(struct qeth_card *card, char __user *udata)
+-static ssize_t
+-qeth_dev_ipato_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-- 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;
+- struct qeth_card *card = dev->driver_data;
-
-- QETH_DBF_TEXT(trace,3,"snmpcmd");
+- if (!card)
+- return -EINVAL;
-
-- if (card->info.guestlan)
-- return -EOPNOTSUPP;
+- return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
+-}
-
-- 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;
+-static int
+-qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto,
+- u8 *addr, int *mask_bits)
+-{
+- const char *start, *end;
+- char *tmp;
+- char buffer[40] = {0, };
+-
+- start = buf;
+- /* get address string */
+- end = strchr(start, '/');
+- if (!end || (end - start >= 40)){
+- PRINT_WARN("Invalid format for ipato_addx/delx. "
+- "Use <ip addr>/<mask bits>\n");
+- return -EINVAL;
- }
-- /* 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;
+- strncpy(buffer, start, end - start);
+- if (qeth_string_to_ipaddr(buffer, proto, addr)){
+- PRINT_WARN("Invalid IP address format!\n");
+- return -EINVAL;
- }
-- if (copy_from_user(ureq, udata,
-- req_len+sizeof(struct qeth_snmp_ureq_hdr))){
-- kfree(ureq);
-- return -EFAULT;
+- 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;
- }
-- qinfo.udata_len = ureq->hdr.data_len;
-- if (!(qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL))){
-- kfree(ureq);
+- 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;
- }
-- qinfo.udata_offset = sizeof(struct qeth_snmp_ureq_hdr);
+- ipatoe->proto = proto;
+- memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
+- ipatoe->mask_bits = mask_bits;
-
-- 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;
+- if ((rc = qeth_add_ipato_entry(card, ipatoe))){
+- kfree(ipatoe);
+- return rc;
- }
-
-- kfree(ureq);
-- kfree(qinfo.udata);
-- return rc;
+- return count;
-}
-
--static int
--qeth_default_setassparms_cb(struct qeth_card *, struct qeth_reply *,
-- unsigned long);
+-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;
-
--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);
+- if (!card)
+- return -EINVAL;
-
--static int
--qeth_arp_add_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry)
+- 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)
-{
-- struct qeth_cmd_buffer *iob;
-- char buf[16];
-- int tmp;
+- u8 addr[16];
+- int mask_bits;
- int rc;
-
-- QETH_DBF_TEXT(trace,3,"arpadent");
+- if (qeth_check_layer2(card))
+- return -EPERM;
+- if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits)))
+- return rc;
-
-- /*
-- * 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;
-- }
+- qeth_del_ipato_entry(card, proto, addr, mask_bits);
-
-- 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;
+- return count;
-}
-
--static int
--qeth_arp_remove_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry)
+-static ssize_t
+-qeth_dev_ipato_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-- struct qeth_cmd_buffer *iob;
-- char buf[16] = {0, };
-- int tmp;
-- int rc;
+- struct qeth_card *card = dev->driver_data;
-
-- QETH_DBF_TEXT(trace,3,"arprment");
+- if (!card)
+- return -EINVAL;
-
-- /*
-- * 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;
+- return qeth_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
-}
-
--static int
--qeth_arp_flush_cache(struct qeth_card *card)
+-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)
-{
-- int rc;
-- int tmp;
+- struct qeth_card *card = dev->driver_data;
-
-- QETH_DBF_TEXT(trace,3,"arpflush");
+- if (!card)
+- return -EINVAL;
-
-- /*
-- * 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;
+- if (qeth_check_layer2(card))
+- return -EPERM;
+-
+- return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
-}
-
--static int
--qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+-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 = (struct qeth_card *)dev->priv;
-- struct qeth_arp_cache_entry arp_entry;
-- struct mii_ioctl_data *mii_data;
-- int rc = 0;
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
-
- if (!card)
-- return -ENODEV;
--
-- if ((card->state != CARD_STATE_UP) &&
-- (card->state != CARD_STATE_SOFTSETUP))
-- return -ENODEV;
+- return -EINVAL;
-
-- if (card->info.type == QETH_CARD_TYPE_OSN)
+- if (qeth_check_layer2(card))
- 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;
+- 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;
- }
-- if (rc)
-- QETH_DBF_TEXT_(trace, 2, "ioce%d", rc);
-- return rc;
+- return count;
-}
-
--static struct net_device_stats *
--qeth_get_stats(struct net_device *dev)
--{
-- struct qeth_card *card;
+-static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
+- qeth_dev_ipato_invert6_show,
+- qeth_dev_ipato_invert6_store);
-
-- card = (struct qeth_card *) (dev->priv);
-
-- QETH_DBF_TEXT(trace,5,"getstat");
+-static ssize_t
+-qeth_dev_ipato_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
-
-- return &card->stats;
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
-}
-
--static int
--qeth_change_mtu(struct net_device *dev, int new_mtu)
+-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;
-- char dbf_text[15];
+- struct qeth_card *card = dev->driver_data;
-
-- card = (struct qeth_card *) (dev->priv);
+- if (!card)
+- return -EINVAL;
-
-- QETH_DBF_TEXT(trace,4,"chgmtu");
-- sprintf(dbf_text, "%8x", new_mtu);
-- QETH_DBF_TEXT(trace,4,dbf_text);
+- return qeth_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
+-}
-
-- 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)))
+-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;
-- dev->mtu = new_mtu;
-- return 0;
+-
+- return qeth_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
-}
-
--#ifdef CONFIG_QETH_VLAN
--static void
--qeth_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
+-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_card *card;
+- 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;
-
-- QETH_DBF_TEXT(trace,4,"vlanreg");
+- if (qeth_check_layer2(card))
+- return -EPERM;
-
-- card = (struct qeth_card *) dev->priv;
-- spin_lock_irqsave(&card->vlanlock, flags);
-- card->vlangrp = grp;
-- spin_unlock_irqrestore(&card->vlanlock, flags);
+- 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 void
--qeth_free_vlan_buffer(struct qeth_card *card, struct qeth_qdio_out_buffer *buf,
-- unsigned short vid)
+-static ssize_t
+-qeth_dev_vipa_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-- int i;
-- struct sk_buff *skb;
-- struct sk_buff_head tmp_list;
+- struct qeth_card *card = dev->driver_data;
-
-- 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);
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
-}
-
--static void
--qeth_free_vlan_skbs(struct qeth_card *card, unsigned short vid)
+-static int
+-qeth_parse_vipae(const char* buf, enum qeth_prot_versions proto,
+- u8 *addr)
-{
-- 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);
+- if (qeth_string_to_ipaddr(buf, proto, addr)){
+- PRINT_WARN("Invalid IP address format!\n");
+- return -EINVAL;
- }
+- return 0;
-}
-
--static void
--qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid)
+-static ssize_t
+-qeth_dev_vipa_add_store(const char *buf, size_t count,
+- struct qeth_card *card, enum qeth_prot_versions proto)
-{
-- struct in_device *in_dev;
-- struct in_ifaddr *ifa;
-- struct qeth_ipaddr *addr;
+- u8 addr[16] = {0, };
+- int rc;
-
-- QETH_DBF_TEXT(trace, 4, "frvaddr4");
+- if (qeth_check_layer2(card))
+- return -EPERM;
+- if ((rc = qeth_parse_vipae(buf, proto, addr)))
+- return rc;
-
-- 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();
+- if ((rc = qeth_add_vipa(card, proto, addr)))
+- return rc;
+-
+- return count;
-}
-
--static void
--qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid)
+-static ssize_t
+-qeth_dev_vipa_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
--#ifdef CONFIG_QETH_IPV6
-- struct inet6_dev *in6_dev;
-- struct inet6_ifaddr *ifa;
-- struct qeth_ipaddr *addr;
+- struct qeth_card *card = dev->driver_data;
-
-- QETH_DBF_TEXT(trace, 4, "frvaddr6");
+- if (!card)
+- return -EINVAL;
-
-- 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 */
+- return qeth_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
-}
-
--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 QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
+- qeth_dev_vipa_add4_show,
+- qeth_dev_vipa_add4_store);
-
--static int
--qeth_layer2_send_setdelvlan_cb(struct qeth_card *card,
-- struct qeth_reply *reply,
-- unsigned long data)
+-static ssize_t
+-qeth_dev_vipa_del_store(const char *buf, size_t count,
+- struct qeth_card *card, enum qeth_prot_versions proto)
-{
-- struct qeth_ipa_cmd *cmd;
+- u8 addr[16];
+- int rc;
-
-- 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;
--}
+- if (qeth_check_layer2(card))
+- return -EPERM;
+- if ((rc = qeth_parse_vipae(buf, proto, addr)))
+- return rc;
-
--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_del_vipa(card, proto, addr);
-
-- 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);
+- return count;
-}
-
--static void
--qeth_layer2_process_vlans(struct qeth_card *card, int clear)
+-static ssize_t
+-qeth_dev_vipa_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-- unsigned short i;
+- struct qeth_card *card = dev->driver_data;
-
-- QETH_DBF_TEXT(trace, 3, "L2prcvln");
+- if (!card)
+- return -EINVAL;
-
-- 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);
-- }
+- return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
-}
-
--/*add_vid is layer 2 used only ....*/
--static void
--qeth_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
+-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;
+- struct qeth_card *card = dev->driver_data;
-
-- QETH_DBF_TEXT_(trace, 4, "aid:%d", vid);
+- if (!card)
+- return -EINVAL;
-
-- card = (struct qeth_card *) dev->priv;
-- if (!card->options.layer2)
-- return;
-- qeth_layer2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
+- return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV6);
-}
-
--/*... kill_vid used for both modes*/
--static void
--qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+-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;
-- unsigned long flags;
+- struct qeth_card *card = dev->driver_data;
-
-- QETH_DBF_TEXT_(trace, 4, "kid:%d", vid);
+- if (!card)
+- return -EINVAL;
-
-- 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);
+- return qeth_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
-}
--#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)
+-
+-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_ipa_cmd *cmd;
-- struct qeth_ipacmd_setadpparms *setparms;
+- struct qeth_card *card = dev->driver_data;
-
-- QETH_DBF_TEXT(trace,4,"prmadpcb");
+- if (!card)
+- return -EINVAL;
-
-- cmd = (struct qeth_ipa_cmd *) data;
-- setparms = &(cmd->data.setadapterparms);
+- if (qeth_check_layer2(card))
+- return -EPERM;
-
-- 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;
+- return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
-}
--/*
-- * Set promiscuous mode (on or off) (SET_PROMISC_MODE command)
-- */
--static void
--qeth_setadp_promisc_mode(struct qeth_card *card)
+-
+-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)
-{
-- enum qeth_ipa_promisc_modes mode;
-- struct net_device *dev = card->dev;
-- struct qeth_cmd_buffer *iob;
-- struct qeth_ipa_cmd *cmd;
+- 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;
-
-- QETH_DBF_TEXT(trace, 4, "setprom");
+- if (qeth_check_layer2(card))
+- return -EPERM;
-
-- 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);
+- 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");
-
-- 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);
+- return i;
-}
-
--/**
-- * set multicast address on card
-- */
--static void
--qeth_set_multicast_list(struct net_device *dev)
+-static ssize_t
+-qeth_dev_rxip_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-- struct qeth_card *card = (struct qeth_card *) dev->priv;
+- struct qeth_card *card = dev->driver_data;
-
-- if (card->info.type == QETH_CARD_TYPE_OSN)
-- return ;
+- if (!card)
+- return -EINVAL;
-
-- 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);
+- return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
-}
-
-static int
--qeth_neigh_setup(struct net_device *dev, struct neigh_parms *np)
+-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 void
--qeth_get_mac_for_ipm(__u32 ipm, char *mac, struct net_device *dev)
+-static ssize_t
+-qeth_dev_rxip_add_store(const char *buf, size_t count,
+- struct qeth_card *card, enum qeth_prot_versions proto)
-{
-- if (dev->type == ARPHRD_IEEE802_TR)
-- ip_tr_mc_map(ipm, mac);
-- else
-- ip_eth_mc_map(ipm, mac);
--}
+- u8 addr[16] = {0, };
+- int rc;
-
--static struct qeth_ipaddr *
--qeth_get_addr_buffer(enum qeth_prot_versions prot)
--{
-- struct qeth_ipaddr *addr;
+- if (qeth_check_layer2(card))
+- return -EPERM;
+- if ((rc = qeth_parse_rxipe(buf, proto, addr)))
+- return rc;
-
-- 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;
+- if ((rc = qeth_add_rxip(card, proto, addr)))
+- return rc;
+-
+- return count;
-}
-
--int
--qeth_osn_assist(struct net_device *dev,
-- void *data,
-- int data_len)
+-static ssize_t
+-qeth_dev_rxip_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-- struct qeth_cmd_buffer *iob;
-- struct qeth_card *card;
-- int rc;
+- struct qeth_card *card = dev->driver_data;
-
-- 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;
+- return -EINVAL;
+-
+- return qeth_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
-}
-
--static struct net_device *
--qeth_netdev_by_devno(unsigned char *read_dev_no)
+-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)
-{
-- struct qeth_card *card;
-- struct net_device *ndev;
-- unsigned char *readno;
-- __u16 temp_dev_no, card_dev_no;
-- char *endp;
-- unsigned long flags;
+- u8 addr[16];
+- int rc;
-
-- 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;
+- 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;
-}
-
--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 *))
+-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;
+- struct qeth_card *card = dev->driver_data;
-
-- 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;
+-
+- return qeth_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4);
-}
-
--void
--qeth_osn_deregister(struct net_device * dev)
+-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;
+- struct qeth_card *card = dev->driver_data;
-
-- 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;
+- return -EINVAL;
+-
+- return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV6);
-}
-
--static void
--qeth_delete_mc_addresses(struct qeth_card *card)
+-static ssize_t
+-qeth_dev_rxip_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-- struct qeth_ipaddr *iptodo;
-- unsigned long flags;
+- struct qeth_card *card = dev->driver_data;
-
-- 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);
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
-}
-
--static void
--qeth_add_mc(struct qeth_card *card, struct in_device *in4_dev)
+-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_ipaddr *ipm;
-- struct ip_mc_list *im4;
-- char buf[MAX_ADDR_LEN];
+- struct qeth_card *card = dev->driver_data;
-
-- 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);
-- }
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
-}
-
--static inline void
--qeth_add_vlan_mc(struct qeth_card *card)
+-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)
-{
--#ifdef CONFIG_QETH_VLAN
-- struct in_device *in_dev;
-- struct vlan_group *vg;
-- int i;
+- int ret;
+- struct qeth_card *card = dev->driver_data;
-
-- QETH_DBF_TEXT(trace,4,"addmcvl");
-- if ( ((card->options.layer2 == 0) &&
-- (!qeth_is_supported(card,IPA_FULL_VLAN))) ||
-- (card->vlangrp == NULL) )
-- return ;
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- return sysfs_create_group(&dev->kobj,
+- &qeth_osn_device_attr_group);
-
-- 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);
+- 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;
- }
--#endif
+- 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;
-}
-
--static void
--qeth_add_multicast_ipv4(struct qeth_card *card)
+-void
+-qeth_remove_device_attributes(struct device *dev)
-{
-- struct in_device *in4_dev;
+- struct qeth_card *card = dev->driver_data;
-
-- QETH_DBF_TEXT(trace,4,"chkmcv4");
-- in4_dev = in_dev_get(card->dev);
-- if (in4_dev == NULL)
+- if (card->info.type == QETH_CARD_TYPE_OSN) {
+- sysfs_remove_group(&dev->kobj, &qeth_osn_device_attr_group);
- 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);
+- }
+- 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);
-}
-
--static void
--qeth_layer2_add_multicast(struct qeth_card *card)
+-/**********************/
+-/* DRIVER ATTRIBUTES */
+-/**********************/
+-static ssize_t
+-qeth_driver_group_store(struct device_driver *ddrv, const char *buf,
+- size_t count)
-{
-- struct qeth_ipaddr *ipm;
-- struct dev_mc_list *dm;
+- const char *start, *end;
+- char bus_ids[3][BUS_ID_SIZE], *argv[3];
+- int i;
+- int err;
-
-- 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);
+- 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;
-}
-
--#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 DRIVER_ATTR(group, 0200, NULL, qeth_driver_group_store);
-
--static inline void
--qeth_add_vlan_mc6(struct qeth_card *card)
+-static ssize_t
+-qeth_driver_notifier_register_store(struct device_driver *ddrv, const char *buf,
+- size_t count)
-{
--#ifdef CONFIG_QETH_VLAN
-- struct inet6_dev *in_dev;
-- struct vlan_group *vg;
-- int i;
+- int rc;
+- int signum;
+- char *tmp, *tmp2;
-
-- QETH_DBF_TEXT(trace,4,"admc6vl");
-- if ( ((card->options.layer2 == 0) &&
-- (!qeth_is_supported(card,IPA_FULL_VLAN))) ||
-- (card->vlangrp == NULL))
-- return ;
+- tmp = strsep((char **) &buf, "\n");
+- if (!strncmp(tmp, "unregister", 10)){
+- if ((rc = qeth_notifier_unregister(current)))
+- return rc;
+- return count;
+- }
-
-- 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);
+- signum = simple_strtoul(tmp, &tmp2, 10);
+- if ((signum < 0) || (signum > 32)){
+- PRINT_WARN("Signal number %d is out of range\n", signum);
+- return -EINVAL;
- }
--#endif /* CONFIG_QETH_VLAN */
+- if ((rc = qeth_notifier_register(current, signum)))
+- return rc;
+-
+- return count;
-}
-
--static void
--qeth_add_multicast_ipv6(struct qeth_card *card)
+-static DRIVER_ATTR(notifier_register, 0200, NULL,
+- qeth_driver_notifier_register_store);
+-
+-int
+-qeth_create_driver_attributes(void)
-{
-- struct inet6_dev *in6_dev;
+- int rc;
-
-- 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);
+- 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);
-}
--#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))
+-void
+-qeth_remove_driver_attributes(void)
-{
-- 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);
+- driver_remove_file(&qeth_ccwgroup_driver.driver,
+- &driver_attr_group);
+- driver_remove_file(&qeth_ccwgroup_driver.driver,
+- &driver_attr_notifier_register);
-}
+diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h
+deleted file mode 100644
+index c20e923..0000000
+--- a/drivers/s390/net/qeth_tso.h
++++ /dev/null
+@@ -1,148 +0,0 @@
+-/*
+- * linux/drivers/s390/net/qeth_tso.h
+- *
+- * Header file for qeth TCP Segmentation Offload support.
+- *
+- * Copyright 2004 IBM Corporation
+- *
+- * Author(s): Frank Pavlic <fpavlic at de.ibm.com>
+- *
+- */
+-#ifndef __QETH_TSO_H__
+-#define __QETH_TSO_H__
-
--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;
+-#include <linux/skbuff.h>
+-#include <linux/tcp.h>
+-#include <linux/ip.h>
+-#include <linux/ipv6.h>
+-#include <net/ip6_checksum.h>
+-#include "qeth.h"
+-#include "qeth_mpc.h"
-
-- 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)
+-static inline struct qeth_hdr_tso *
+-qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb)
-{
-- QETH_DBF_TEXT(trace, 2, "L2Sgmac");
-- return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_SETGMAC,
-- qeth_layer2_send_setgroupmac_cb);
+- QETH_DBF_TEXT(trace, 5, "tsoprsk");
+- return qeth_push_skb(card, *skb, sizeof(struct qeth_hdr_tso));
-}
-
--static int
--qeth_layer2_send_delgroupmac_cb(struct qeth_card *card,
-- struct qeth_reply *reply,
-- unsigned long data)
+-/**
+- * fill header for a TSO packet
+- */
+-static inline void
+-qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb)
-{
-- struct qeth_ipa_cmd *cmd;
-- __u8 *mac;
+- struct qeth_hdr_tso *hdr;
+- struct tcphdr *tcph;
+- struct iphdr *iph;
-
-- 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;
+- 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));
-}
-
--static int
--qeth_layer2_send_delgroupmac(struct qeth_card *card, __u8 *mac)
+-/**
+- * change some header values as requested by hardware
+- */
+-static inline void
+-qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb)
-{
-- QETH_DBF_TEXT(trace, 2, "L2Dgmac");
-- return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_DELGMAC,
-- qeth_layer2_send_delgroupmac_cb);
+- 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 int
--qeth_layer2_send_setmac_cb(struct qeth_card *card,
-- struct qeth_reply *reply,
-- unsigned long data)
+-static inline int
+-qeth_tso_prepare_packet(struct qeth_card *card, struct sk_buff *skb,
+- int ipv, int cast_type)
-{
-- struct qeth_ipa_cmd *cmd;
+- struct qeth_hdr_tso *hdr;
-
-- 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);
+- 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 int
--qeth_layer2_send_setmac(struct qeth_card *card, __u8 *mac)
+-static inline void
+-__qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer,
+- int is_tso, int *next_element_to_fill)
-{
-- QETH_DBF_TEXT(trace, 2, "L2Setmac");
-- return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_SETVMAC,
-- qeth_layer2_send_setmac_cb);
--}
+- struct skb_frag_struct *frag;
+- int fragno;
+- unsigned long addr;
+- int element, cnt, dlen;
-
--static int
--qeth_layer2_send_delmac_cb(struct qeth_card *card,
-- struct qeth_reply *reply,
-- unsigned long data)
--{
-- struct qeth_ipa_cmd *cmd;
+- fragno = skb_shinfo(skb)->nr_frags;
+- element = *next_element_to_fill;
+- dlen = 0;
-
-- 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;
+- 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++;
- }
-- card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
+- for (cnt = 0; cnt < fragno; cnt++) {
+- frag = &skb_shinfo(skb)->frags[cnt];
+- addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
+- frag->page_offset;
+- buffer->element[element].addr = (char *)addr;
+- buffer->element[element].length = frag->size;
+- if (cnt < (fragno - 1))
+- buffer->element[element].flags =
+- SBAL_FLAGS_MIDDLE_FRAG;
+- else
+- buffer->element[element].flags =
+- SBAL_FLAGS_LAST_FRAG;
+- element++;
+- }
+- *next_element_to_fill = element;
+-}
+-#endif /* __QETH_TSO_H__ */
+diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
+index 644a06e..4d4b542 100644
+--- a/drivers/s390/s390mach.c
++++ b/drivers/s390/s390mach.c
+@@ -59,15 +59,15 @@ repeat:
+
+ printk(KERN_WARNING"%s: Code does not support more "
+ "than two chained crws; please report to "
+- "linux390 at de.ibm.com!\n", __FUNCTION__);
++ "linux390 at de.ibm.com!\n", __func__);
+ ccode = stcrw(&tmp_crw);
+ printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, "
+ "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
+- __FUNCTION__, tmp_crw.slct, tmp_crw.oflw,
++ __func__, tmp_crw.slct, tmp_crw.oflw,
+ tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc,
+ tmp_crw.erc, tmp_crw.rsid);
+ printk(KERN_WARNING"%s: This was crw number %x in the "
+- "chain\n", __FUNCTION__, chain);
++ "chain\n", __func__, chain);
+ if (ccode != 0)
+ break;
+ chain = tmp_crw.chn ? chain + 1 : 0;
+@@ -83,7 +83,7 @@ repeat:
+ crw[chain].rsid);
+ /* Check for overflows. */
+ if (crw[chain].oflw) {
+- pr_debug("%s: crw overflow detected!\n", __FUNCTION__);
++ pr_debug("%s: crw overflow detected!\n", __func__);
+ css_schedule_eval_all();
+ chain = 0;
+ continue;
+diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h
+index d3ca428..ca681f9 100644
+--- a/drivers/s390/s390mach.h
++++ b/drivers/s390/s390mach.h
+@@ -105,4 +105,8 @@ static inline int stcrw(struct crw *pcrw )
+ #define ED_ETR_SYNC 12 /* External damage ETR sync check */
+ #define ED_ETR_SWITCH 13 /* External damage ETR switch to local */
+
++struct pt_regs;
++
++void s390_handle_mcck(void);
++void s390_do_machine_check(struct pt_regs *regs);
+ #endif /* __s390mach */
+diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
+index 874b55e..8c7e2b7 100644
+--- a/drivers/s390/scsi/zfcp_aux.c
++++ b/drivers/s390/scsi/zfcp_aux.c
+@@ -1030,10 +1030,10 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
+
+ /* initialize debug locks */
+
+- spin_lock_init(&adapter->erp_dbf_lock);
+ spin_lock_init(&adapter->hba_dbf_lock);
+ spin_lock_init(&adapter->san_dbf_lock);
+ spin_lock_init(&adapter->scsi_dbf_lock);
++ spin_lock_init(&adapter->rec_dbf_lock);
+
+ retval = zfcp_adapter_debug_register(adapter);
+ if (retval)
+@@ -1325,10 +1325,10 @@ zfcp_nameserver_enqueue(struct zfcp_adapter *adapter)
+
+ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_FC
+
+-static void
+-zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
+- struct fsf_status_read_buffer *status_buffer)
++static void zfcp_fsf_incoming_els_rscn(struct zfcp_fsf_req *fsf_req)
+ {
++ struct fsf_status_read_buffer *status_buffer = (void*)fsf_req->data;
++ struct zfcp_adapter *adapter = fsf_req->adapter;
+ struct fcp_rscn_head *fcp_rscn_head;
+ struct fcp_rscn_element *fcp_rscn_element;
+ struct zfcp_port *port;
+@@ -1375,7 +1375,8 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
+ ZFCP_LOG_INFO("incoming RSCN, trying to open "
+ "port 0x%016Lx\n", port->wwpn);
+ zfcp_erp_port_reopen(port,
+- ZFCP_STATUS_COMMON_ERP_FAILED);
++ ZFCP_STATUS_COMMON_ERP_FAILED,
++ 82, fsf_req);
+ continue;
+ }
+
+@@ -1406,10 +1407,10 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
+ }
+ }
+
+-static void
+-zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter,
+- struct fsf_status_read_buffer *status_buffer)
++static void zfcp_fsf_incoming_els_plogi(struct zfcp_fsf_req *fsf_req)
+ {
++ struct fsf_status_read_buffer *status_buffer = (void*)fsf_req->data;
++ struct zfcp_adapter *adapter = fsf_req->adapter;
+ struct fsf_plogi *els_plogi;
+ struct zfcp_port *port;
+ unsigned long flags;
+@@ -1428,14 +1429,14 @@ zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter,
+ status_buffer->d_id,
+ zfcp_get_busid_by_adapter(adapter));
+ } else {
+- zfcp_erp_port_forced_reopen(port, 0);
++ zfcp_erp_port_forced_reopen(port, 0, 83, fsf_req);
+ }
+ }
+
+-static void
+-zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter,
+- struct fsf_status_read_buffer *status_buffer)
++static void zfcp_fsf_incoming_els_logo(struct zfcp_fsf_req *fsf_req)
+ {
++ struct fsf_status_read_buffer *status_buffer = (void*)fsf_req->data;
++ struct zfcp_adapter *adapter = fsf_req->adapter;
+ struct fcp_logo *els_logo = (struct fcp_logo *) status_buffer->payload;
+ struct zfcp_port *port;
+ unsigned long flags;
+@@ -1453,7 +1454,7 @@ zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter,
+ status_buffer->d_id,
+ zfcp_get_busid_by_adapter(adapter));
+ } else {
+- zfcp_erp_port_forced_reopen(port, 0);
++ zfcp_erp_port_forced_reopen(port, 0, 84, fsf_req);
+ }
+ }
+
+@@ -1480,12 +1481,12 @@ zfcp_fsf_incoming_els(struct zfcp_fsf_req *fsf_req)
+
+ zfcp_san_dbf_event_incoming_els(fsf_req);
+ if (els_type == LS_PLOGI)
+- zfcp_fsf_incoming_els_plogi(adapter, status_buffer);
++ zfcp_fsf_incoming_els_plogi(fsf_req);
+ else if (els_type == LS_LOGO)
+- zfcp_fsf_incoming_els_logo(adapter, status_buffer);
++ zfcp_fsf_incoming_els_logo(fsf_req);
+ else if ((els_type & 0xffff0000) == LS_RSCN)
+ /* we are only concerned with the command, not the length */
+- zfcp_fsf_incoming_els_rscn(adapter, status_buffer);
++ zfcp_fsf_incoming_els_rscn(fsf_req);
+ else
+ zfcp_fsf_incoming_els_unknown(adapter, status_buffer);
+ }
+diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
+index edc5015..66d3b88 100644
+--- a/drivers/s390/scsi/zfcp_ccw.c
++++ b/drivers/s390/scsi/zfcp_ccw.c
+@@ -170,9 +170,10 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device)
+ BUG_ON(!zfcp_reqlist_isempty(adapter));
+ adapter->req_no = 0;
+
+- zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING,
+- ZFCP_SET);
+- zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
++ zfcp_erp_modify_adapter_status(adapter, 10, NULL,
++ ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
++ zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 85,
++ NULL);
+ zfcp_erp_wait(adapter);
+ goto out;
+
+@@ -197,7 +198,7 @@ zfcp_ccw_set_offline(struct ccw_device *ccw_device)
+
+ down(&zfcp_data.config_sema);
+ adapter = dev_get_drvdata(&ccw_device->dev);
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 86, NULL);
+ zfcp_erp_wait(adapter);
+ zfcp_erp_thread_kill(adapter);
+ up(&zfcp_data.config_sema);
+@@ -223,24 +224,21 @@ zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
+ case CIO_GONE:
+ ZFCP_LOG_NORMAL("adapter %s: device gone\n",
+ zfcp_get_busid_by_adapter(adapter));
+- debug_text_event(adapter->erp_dbf,1,"dev_gone");
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 87, NULL);
+ break;
+ case CIO_NO_PATH:
+ ZFCP_LOG_NORMAL("adapter %s: no path\n",
+ zfcp_get_busid_by_adapter(adapter));
+- debug_text_event(adapter->erp_dbf,1,"no_path");
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 88, NULL);
+ break;
+ case CIO_OPER:
+ ZFCP_LOG_NORMAL("adapter %s: operational again\n",
+ zfcp_get_busid_by_adapter(adapter));
+- debug_text_event(adapter->erp_dbf,1,"dev_oper");
+- zfcp_erp_modify_adapter_status(adapter,
++ zfcp_erp_modify_adapter_status(adapter, 11, NULL,
+ ZFCP_STATUS_COMMON_RUNNING,
+ ZFCP_SET);
+- zfcp_erp_adapter_reopen(adapter,
+- ZFCP_STATUS_COMMON_ERP_FAILED);
++ zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
++ 89, NULL);
+ break;
+ }
+ zfcp_erp_wait(adapter);
+@@ -272,7 +270,7 @@ zfcp_ccw_shutdown(struct ccw_device *cdev)
+
+ down(&zfcp_data.config_sema);
+ adapter = dev_get_drvdata(&cdev->dev);
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 90, NULL);
+ zfcp_erp_wait(adapter);
+ up(&zfcp_data.config_sema);
+ }
+diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
+index 701046c..37b85c6 100644
+--- a/drivers/s390/scsi/zfcp_dbf.c
++++ b/drivers/s390/scsi/zfcp_dbf.c
+@@ -31,123 +31,128 @@ MODULE_PARM_DESC(dbfsize,
+
+ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHER
+
+-static int
+-zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck)
++static void zfcp_dbf_hexdump(debug_info_t *dbf, void *to, int to_len,
++ int level, char *from, int from_len)
++{
++ int offset;
++ struct zfcp_dbf_dump *dump = to;
++ int room = to_len - sizeof(*dump);
++
++ for (offset = 0; offset < from_len; offset += dump->size) {
++ memset(to, 0, to_len);
++ strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
++ dump->total_size = from_len;
++ dump->offset = offset;
++ dump->size = min(from_len - offset, room);
++ memcpy(dump->data, from + offset, dump->size);
++ debug_event(dbf, level, dump, dump->size);
++ }
++}
++
++/* FIXME: this duplicate this code in s390 debug feature */
++static void zfcp_dbf_timestamp(unsigned long long stck, struct timespec *time)
+ {
+ unsigned long long sec;
+- struct timespec dbftime;
+- int len = 0;
+
+ stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
+ sec = stck >> 12;
+ do_div(sec, 1000000);
+- dbftime.tv_sec = sec;
++ time->tv_sec = sec;
+ stck -= (sec * 1000000) << 12;
+- dbftime.tv_nsec = ((stck * 1000) >> 12);
+- len += sprintf(out_buf + len, "%-24s%011lu:%06lu\n",
+- label, dbftime.tv_sec, dbftime.tv_nsec);
-
-- return 0;
--}
+- 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
--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);
--}
+-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
--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;
--}
+-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;
-
--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;
+- if (offset == 0)
+- len += sprintf(out_buf + len, "%-24s ", label);
-
-- 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);
++ 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;
+ }
+ }
-
-- return iob;
--}
+- if (total_size == 0)
+- len += sprintf(out_buf + len, "\n");
-
+- return len;
++ if (!total_size)
++ *p += sprintf(*p, "\n");
+ }
+
-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;
-- }
--}
+-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
--qeth_send_setdelip(struct qeth_card *card, struct qeth_ipaddr *addr,
-- int ipacmd, unsigned int flags)
+-zfcp_hba_dbf_view_response(char *out_buf,
+- struct zfcp_hba_dbf_record_response *rec)
-{
-- int rc;
-- struct qeth_cmd_buffer *iob;
-- struct qeth_ipa_cmd *cmd;
-- __u8 netmask[16];
+- int len = 0;
-
-- QETH_DBF_TEXT(trace,4,"setdelip");
-- QETH_DBF_TEXT_(trace,4,"flags%02X", flags);
+- 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);
-
-- 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;
-- }
+- 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;
+ }
-
-- rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
+- 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;
-
-- return rc;
--}
+- 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
--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]);
--}
+-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;
-
--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]);
--}
+- 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
--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));
-- }
+-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 {
-- 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;
--}
+- 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
--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;
--}
+-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);
-
--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);
+- 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);
-
-- return qeth_layer3_register_addr_entry(card, addr);
--}
++ 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
--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);
--}
+-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);
+ }
-
--static u32
--qeth_ethtool_get_tx_csum(struct net_device *dev)
--{
-- return (dev->features & NETIF_F_HW_CSUM) != 0;
--}
+- len += sprintf(out_buf + len, "\n");
-
--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 len;
++ p += sprintf(p, "\n");
++ return p - out_buf;
+ }
+
+ static struct debug_view zfcp_scsi_dbf_view = {
+@@ -897,13 +1217,14 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
+ char dbf_name[DEBUG_MAX_NAME_LEN];
+
+ /* debug feature area which records recovery activity */
+- sprintf(dbf_name, "zfcp_%s_erp", zfcp_get_busid_by_adapter(adapter));
+- adapter->erp_dbf = debug_register(dbf_name, dbfsize, 2,
+- sizeof(struct zfcp_erp_dbf_record));
+- if (!adapter->erp_dbf)
++ sprintf(dbf_name, "zfcp_%s_rec", zfcp_get_busid_by_adapter(adapter));
++ adapter->rec_dbf = debug_register(dbf_name, dbfsize, 1,
++ sizeof(struct zfcp_rec_dbf_record));
++ if (!adapter->rec_dbf)
+ goto failed;
+- debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view);
+- debug_set_level(adapter->erp_dbf, 3);
++ debug_register_view(adapter->rec_dbf, &debug_hex_ascii_view);
++ debug_register_view(adapter->rec_dbf, &zfcp_rec_dbf_view);
++ debug_set_level(adapter->rec_dbf, 3);
+
+ /* debug feature area which records HBA (FSF and QDIO) conditions */
+ sprintf(dbf_name, "zfcp_%s_hba", zfcp_get_busid_by_adapter(adapter));
+@@ -952,11 +1273,11 @@ void zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter)
+ debug_unregister(adapter->scsi_dbf);
+ debug_unregister(adapter->san_dbf);
+ debug_unregister(adapter->hba_dbf);
+- debug_unregister(adapter->erp_dbf);
++ debug_unregister(adapter->rec_dbf);
+ adapter->scsi_dbf = NULL;
+ adapter->san_dbf = NULL;
+ adapter->hba_dbf = NULL;
+- adapter->erp_dbf = NULL;
++ adapter->rec_dbf = NULL;
+ }
+
+ #undef ZFCP_LOG_AREA
+diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
+new file mode 100644
+index 0000000..54c34e4
+--- /dev/null
++++ b/drivers/s390/scsi/zfcp_dbf.h
+@@ -0,0 +1,228 @@
++/*
++ * This file is part of the zfcp device driver for
++ * FCP adapters for IBM System z9 and zSeries.
++ *
++ * Copyright IBM Corp. 2008, 2008
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef ZFCP_DBF_H
++#define ZFCP_DBF_H
++
++#include "zfcp_fsf.h"
++
++#define ZFCP_DBF_TAG_SIZE 4
++
++struct zfcp_dbf_dump {
++ u8 tag[ZFCP_DBF_TAG_SIZE];
++ u32 total_size; /* size of total dump data */
++ u32 offset; /* how much data has being already dumped */
++ u32 size; /* how much data comes with this record */
++ u8 data[]; /* dump data */
++} __attribute__ ((packed));
++
++struct zfcp_rec_dbf_record_thread {
++ u32 total;
++ u32 ready;
++ u32 running;
++} __attribute__ ((packed));
++
++struct zfcp_rec_dbf_record_target {
++ u64 ref;
++ u32 status;
++ u32 d_id;
++ u64 wwpn;
++ u64 fcp_lun;
++ u32 erp_count;
++} __attribute__ ((packed));
++
++struct zfcp_rec_dbf_record_trigger {
++ u8 want;
++ u8 need;
++ u32 as;
++ u32 ps;
++ u32 us;
++ u64 ref;
++ u64 action;
++ u64 wwpn;
++ u64 fcp_lun;
++} __attribute__ ((packed));
++
++struct zfcp_rec_dbf_record_action {
++ u32 status;
++ u32 step;
++ u64 action;
++ u64 fsf_req;
++} __attribute__ ((packed));
++
++struct zfcp_rec_dbf_record {
++ u8 id;
++ u8 id2;
++ union {
++ struct zfcp_rec_dbf_record_action action;
++ struct zfcp_rec_dbf_record_thread thread;
++ struct zfcp_rec_dbf_record_target target;
++ struct zfcp_rec_dbf_record_trigger trigger;
++ } u;
++} __attribute__ ((packed));
++
++enum {
++ ZFCP_REC_DBF_ID_ACTION,
++ ZFCP_REC_DBF_ID_THREAD,
++ ZFCP_REC_DBF_ID_TARGET,
++ ZFCP_REC_DBF_ID_TRIGGER,
++};
++
++struct zfcp_hba_dbf_record_response {
++ u32 fsf_command;
++ u64 fsf_reqid;
++ u32 fsf_seqno;
++ u64 fsf_issued;
++ u32 fsf_prot_status;
++ u32 fsf_status;
++ u8 fsf_prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE];
++ u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE];
++ u32 fsf_req_status;
++ u8 sbal_first;
++ u8 sbal_curr;
++ u8 sbal_last;
++ u8 pool;
++ u64 erp_action;
++ union {
++ struct {
++ u64 cmnd;
++ u64 serial;
++ } fcp;
++ struct {
++ u64 wwpn;
++ u32 d_id;
++ u32 port_handle;
++ } port;
++ struct {
++ u64 wwpn;
++ u64 fcp_lun;
++ u32 port_handle;
++ u32 lun_handle;
++ } unit;
++ struct {
++ u32 d_id;
++ u8 ls_code;
++ } els;
++ } u;
++} __attribute__ ((packed));
++
++struct zfcp_hba_dbf_record_status {
++ u8 failed;
++ u32 status_type;
++ u32 status_subtype;
++ struct fsf_queue_designator
++ queue_designator;
++ u32 payload_size;
++#define ZFCP_DBF_UNSOL_PAYLOAD 80
++#define ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL 32
++#define ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD 56
++#define ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT 2 * sizeof(u32)
++ u8 payload[ZFCP_DBF_UNSOL_PAYLOAD];
++} __attribute__ ((packed));
++
++struct zfcp_hba_dbf_record_qdio {
++ u32 status;
++ u32 qdio_error;
++ u32 siga_error;
++ u8 sbal_index;
++ u8 sbal_count;
++} __attribute__ ((packed));
++
++struct zfcp_hba_dbf_record {
++ u8 tag[ZFCP_DBF_TAG_SIZE];
++ u8 tag2[ZFCP_DBF_TAG_SIZE];
++ union {
++ struct zfcp_hba_dbf_record_response response;
++ struct zfcp_hba_dbf_record_status status;
++ struct zfcp_hba_dbf_record_qdio qdio;
++ } u;
++} __attribute__ ((packed));
++
++struct zfcp_san_dbf_record_ct_request {
++ u16 cmd_req_code;
++ u8 revision;
++ u8 gs_type;
++ u8 gs_subtype;
++ u8 options;
++ u16 max_res_size;
++ u32 len;
++#define ZFCP_DBF_CT_PAYLOAD 24
++ u8 payload[ZFCP_DBF_CT_PAYLOAD];
++} __attribute__ ((packed));
++
++struct zfcp_san_dbf_record_ct_response {
++ u16 cmd_rsp_code;
++ u8 revision;
++ u8 reason_code;
++ u8 expl;
++ u8 vendor_unique;
++ u32 len;
++ u8 payload[ZFCP_DBF_CT_PAYLOAD];
++} __attribute__ ((packed));
++
++struct zfcp_san_dbf_record_els {
++ u8 ls_code;
++ u32 len;
++#define ZFCP_DBF_ELS_PAYLOAD 32
++#define ZFCP_DBF_ELS_MAX_PAYLOAD 1024
++ u8 payload[ZFCP_DBF_ELS_PAYLOAD];
++} __attribute__ ((packed));
++
++struct zfcp_san_dbf_record {
++ u8 tag[ZFCP_DBF_TAG_SIZE];
++ u64 fsf_reqid;
++ u32 fsf_seqno;
++ u32 s_id;
++ u32 d_id;
++ union {
++ struct zfcp_san_dbf_record_ct_request ct_req;
++ struct zfcp_san_dbf_record_ct_response ct_resp;
++ struct zfcp_san_dbf_record_els els;
++ } u;
++} __attribute__ ((packed));
++
++struct zfcp_scsi_dbf_record {
++ u8 tag[ZFCP_DBF_TAG_SIZE];
++ u8 tag2[ZFCP_DBF_TAG_SIZE];
++ u32 scsi_id;
++ u32 scsi_lun;
++ u32 scsi_result;
++ u64 scsi_cmnd;
++ u64 scsi_serial;
++#define ZFCP_DBF_SCSI_OPCODE 16
++ u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE];
++ u8 scsi_retries;
++ u8 scsi_allowed;
++ u64 fsf_reqid;
++ u32 fsf_seqno;
++ u64 fsf_issued;
++ u64 old_fsf_reqid;
++ u8 rsp_validity;
++ u8 rsp_scsi_status;
++ u32 rsp_resid;
++ u8 rsp_code;
++#define ZFCP_DBF_SCSI_FCP_SNS_INFO 16
++#define ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO 256
++ u32 sns_info_len;
++ u8 sns_info[ZFCP_DBF_SCSI_FCP_SNS_INFO];
++} __attribute__ ((packed));
++
++#endif /* ZFCP_DBF_H */
+diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
+index 9e9f6c1..bda8c77 100644
+--- a/drivers/s390/scsi/zfcp_def.h
++++ b/drivers/s390/scsi/zfcp_def.h
+@@ -47,6 +47,7 @@
+ #include <asm/qdio.h>
+ #include <asm/debug.h>
+ #include <asm/ebcdic.h>
++#include "zfcp_dbf.h"
+ #include "zfcp_fsf.h"
+
+
+@@ -262,167 +263,6 @@ struct fcp_logo {
+ } __attribute__((packed));
+
+ /*
+- * DBF stuff
+- */
+-#define ZFCP_DBF_TAG_SIZE 4
-
-- return 0;
--}
+-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));
-
--static u32
--qeth_ethtool_get_rx_csum(struct net_device *dev)
--{
-- struct qeth_card *card = (struct qeth_card *)dev->priv;
+-/* FIXME: to be inflated when reworking the erp dbf */
+-struct zfcp_erp_dbf_record {
+- u8 dummy[16];
+-} __attribute__ ((packed));
-
-- return (card->options.checksum_type == HW_CHECKSUMMING);
--}
+-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));
-
--static int
--qeth_ethtool_set_rx_csum(struct net_device *dev, u32 data)
--{
-- struct qeth_card *card = (struct qeth_card *)dev->priv;
+-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));
-
-- 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;
--}
+-struct zfcp_hba_dbf_record_qdio {
+- u32 status;
+- u32 qdio_error;
+- u32 siga_error;
+- u8 sbal_index;
+- u8 sbal_count;
+-} __attribute__ ((packed));
-
--static u32
--qeth_ethtool_get_sg(struct net_device *dev)
--{
-- struct qeth_card *card = (struct qeth_card *)dev->priv;
+-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));
-
-- return ((card->options.large_send != QETH_LARGE_SEND_NO) &&
-- (dev->features & NETIF_F_SG));
--}
+-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));
-
--static int
--qeth_ethtool_set_sg(struct net_device *dev, u32 data)
--{
-- struct qeth_card *card = (struct qeth_card *)dev->priv;
+-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));
-
-- 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;
--}
+-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));
-
--static u32
--qeth_ethtool_get_tso(struct net_device *dev)
--{
-- struct qeth_card *card = (struct qeth_card *)dev->priv;
+-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));
-
-- return ((card->options.large_send != QETH_LARGE_SEND_NO) &&
-- (dev->features & NETIF_F_TSO));
--}
+-/*
+ * 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
--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,
--};
--
+-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
--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,
--};
+-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
--qeth_netdev_init(struct net_device *dev)
--{
-- struct qeth_card *card;
--
-- card = (struct qeth_card *) dev->priv;
--
-- QETH_DBF_TEXT(trace,3,"initdev");
+-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;
-
-- 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;
+- 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;
-
--#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;
+- 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;
-
-- 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;
--}
+- 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;
-
--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;
-- }
--}
+- 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;
-
--/**
-- * hardsetup card, initialize MPC and QDIO stuff
-- */
--static int
--qeth_hardsetup_card(struct qeth_card *card)
--{
-- int retries = 3;
-- int rc;
+- 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));
-
-- QETH_DBF_TEXT(setup, 2, "hrdsetup");
+ 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;
-
-- 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;
--}
+ 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;
-
--static int
--qeth_default_setassparms_cb(struct qeth_card *card, struct qeth_reply *reply,
-- unsigned long data)
--{
-- struct qeth_ipa_cmd *cmd;
+- 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;
-
-- QETH_DBF_TEXT(trace,4,"defadpcb");
+- 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;
-
-- 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;
--}
+- debug_text_event(adapter->erp_dbf, 2, "a_adis");
+- debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int));
-
--static int
--qeth_default_setadapterparms_cb(struct qeth_card *card,
-- struct qeth_reply *reply,
-- unsigned long data)
--{
-- struct qeth_ipa_cmd *cmd;
+ 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");
-
-- QETH_DBF_TEXT(trace,4,"defadpcb");
+ 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");
-
-- cmd = (struct qeth_ipa_cmd *) data;
-- if (cmd->hdr.return_code == 0)
-- cmd->hdr.return_code = cmd->data.setadapterparms.hdr.return_code;
-- return 0;
--}
+ 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));
-
--static int
--qeth_query_setadapterparms_cb(struct qeth_card *card, struct qeth_reply *reply,
-- unsigned long data)
--{
-- struct qeth_ipa_cmd *cmd;
+ 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));
-
-- QETH_DBF_TEXT(trace,3,"quyadpcb");
+ 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));
-
-- 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);
--}
+ 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));
-
--static int
--qeth_query_setadapterparms(struct qeth_card *card)
--{
-- int rc;
-- struct qeth_cmd_buffer *iob;
+ 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");
-
-- 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;
--}
+ 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
--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;
--}
--
+-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
--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");
+-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));
-
-- 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;
--}
+ 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));
-
--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;
+ 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));
-
-- QETH_DBF_TEXT(trace,4,"adpmode");
+ 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;
-
-- 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;
--}
+- 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
--qeth_setadapter_hstr(struct qeth_card *card)
--{
-- int rc;
+-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");
-
-- QETH_DBF_TEXT(trace,4,"adphstr");
+ 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;
-
-- 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;
--}
+- 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;
-
--static int
--qeth_setadapter_parms(struct qeth_card *card)
--{
-- int rc;
+- 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;
-
-- QETH_DBF_TEXT(setup, 2, "setadprm");
+- 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;
-
-- 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);
-- }
+- 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;
-
-- if ((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
-- (card->info.link_type == QETH_LINK_TYPE_LANE_TR))
-- rc = qeth_setadapter_hstr(card);
+- 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);
-
-- return rc;
--}
+ 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));
-
--static int
--qeth_layer2_initialize(struct qeth_card *card)
--{
-- int rc = 0;
+ 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 *);
-
-- QETH_DBF_TEXT(setup, 2, "doL2init");
-- QETH_DBF_TEXT_(setup, 2, "doL2%s", CARD_BUS_ID(card));
+-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);
-
-- 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);
+-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..9af2330 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:
-
-- 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;
--}
+ /* 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;
+ }
+@@ -2003,7 +1927,8 @@ zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter,
+
+ /* setup new FSF request */
+ retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA,
+- 0, NULL, &lock_flags, &fsf_req);
++ ZFCP_WAIT_FOR_SBAL, NULL, &lock_flags,
++ &fsf_req);
+ if (retval) {
+ ZFCP_LOG_INFO("error: Could not create exchange configuration "
+ "data request for adapter %s.\n",
+@@ -2111,29 +2036,28 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
+ min(FC_SERIAL_NUMBER_SIZE, 17));
+ }
+
+- ZFCP_LOG_NORMAL("The adapter %s reported the following "
+- "characteristics:\n"
+- "WWNN 0x%016Lx, "
+- "WWPN 0x%016Lx, "
+- "S_ID 0x%06x,\n"
+- "adapter version 0x%x, "
+- "LIC version 0x%x, "
+- "FC link speed %d Gb/s\n",
+- zfcp_get_busid_by_adapter(adapter),
+- (wwn_t) fc_host_node_name(shost),
+- (wwn_t) fc_host_port_name(shost),
+- fc_host_port_id(shost),
+- adapter->hydra_version,
+- adapter->fsf_lic_version,
+- fc_host_speed(shost));
++ if (fsf_req->erp_action)
++ ZFCP_LOG_NORMAL("The adapter %s reported the following "
++ "characteristics:\n"
++ "WWNN 0x%016Lx, WWPN 0x%016Lx, "
++ "S_ID 0x%06x,\n"
++ "adapter version 0x%x, "
++ "LIC version 0x%x, "
++ "FC link speed %d Gb/s\n",
++ zfcp_get_busid_by_adapter(adapter),
++ (wwn_t) fc_host_node_name(shost),
++ (wwn_t) fc_host_port_name(shost),
++ fc_host_port_id(shost),
++ adapter->hydra_version,
++ adapter->fsf_lic_version,
++ fc_host_speed(shost));
+ if (ZFCP_QTCB_VERSION < bottom->low_qtcb_version) {
+ ZFCP_LOG_NORMAL("error: the adapter %s "
+ "only supports newer control block "
+ "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 +2066,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,21 +2106,19 @@ 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 "
+- "network detected at adapter %s.\n",
++ if (fsf_req->erp_action)
++ ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
++ "network detected at adapter "
++ "%s.\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ default:
+@@ -2208,9 +2129,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 +2141,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");
-
--static int
--qeth_send_startlan(struct qeth_card *card, enum qeth_prot_versions prot)
--{
-- int rc;
+ 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 +2334,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 +2434,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 +2457,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 +2466,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 +2486,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 +2535,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 +2565,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 +2668,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 +2683,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 +2693,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 +2805,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 +2826,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 +2836,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 +2884,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 +3015,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 +3024,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 +3045,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 +3055,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 +3095,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 +3109,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 +3117,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 +3179,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 +3198,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 +3310,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 +3326,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 +3335,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 +3344,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 +3375,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 +3529,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 +3565,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 +3687,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 +3703,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 +3719,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 +3729,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 +3745,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 +3767,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 +3780,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 +3793,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 +3801,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 +3811,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 +3820,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 +3840,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+
+ case FSF_FCP_RSP_AVAILABLE:
+ break;
-
-- QETH_DBF_TEXT_(setup, 2, "strtlan%i", prot);
+- 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 +4419,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 +4608,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 +4657,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);
-
-- rc = qeth_send_startstoplan(card, IPA_CMD_STARTLAN, prot);
-- return rc;
--}
+ if (unlikely(retval)) {
+ /* Queues are down..... */
+ retval = -EIO;
+@@ -4885,7 +4671,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_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
+index 8cce5cc..099970b 100644
+--- a/drivers/s390/scsi/zfcp_fsf.h
++++ b/drivers/s390/scsi/zfcp_fsf.h
+@@ -213,6 +213,7 @@
+ #define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010
+ #define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
+ #define FSF_FEATURE_UPDATE_ALERT 0x00000100
++#define FSF_FEATURE_MEASUREMENT_DATA 0x00000200
+
+ /* host connection features */
+ #define FSF_FEATURE_NPIV_MODE 0x00000001
+@@ -340,6 +341,15 @@ struct fsf_qtcb_prefix {
+ u8 res1[20];
+ } __attribute__ ((packed));
+
++struct fsf_statistics_info {
++ u64 input_req;
++ u64 output_req;
++ u64 control_req;
++ u64 input_mb;
++ u64 output_mb;
++ u64 seconds_act;
++} __attribute__ ((packed));
++
+ union fsf_status_qual {
+ u8 byte[FSF_STATUS_QUALIFIER_SIZE];
+ u16 halfword[FSF_STATUS_QUALIFIER_SIZE / sizeof (u16)];
+@@ -436,7 +446,8 @@ struct fsf_qtcb_bottom_config {
+ u32 hardware_version;
+ u8 serial_number[32];
+ struct fsf_nport_serv_param plogi_payload;
+- u8 res4[160];
++ struct fsf_statistics_info stat_info;
++ u8 res4[112];
+ } __attribute__ ((packed));
+
+ struct fsf_qtcb_bottom_port {
+@@ -469,7 +480,10 @@ struct fsf_qtcb_bottom_port {
+ u64 control_requests;
+ u64 input_mb; /* where 1 MByte == 1.000.000 Bytes */
+ u64 output_mb; /* where 1 MByte == 1.000.000 Bytes */
+- u8 res2[256];
++ u8 cp_util;
++ u8 cb_util;
++ u8 a_util;
++ u8 res2[253];
+ } __attribute__ ((packed));
+
+ union fsf_qtcb_bottom {
+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..0168755 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 *);
+@@ -39,6 +40,7 @@ static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int,
+ unsigned int, unsigned int);
+
+ static struct device_attribute *zfcp_sysfs_sdev_attrs[];
++static struct device_attribute *zfcp_a_stats_attrs[];
+
+ struct zfcp_data zfcp_data = {
+ .scsi_host_template = {
+@@ -51,6 +53,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,
+@@ -59,6 +62,7 @@ struct zfcp_data zfcp_data = {
+ .use_clustering = 1,
+ .sdev_attrs = zfcp_sysfs_sdev_attrs,
+ .max_sectors = ZFCP_MAX_SECTORS,
++ .shost_attrs = zfcp_a_stats_attrs,
+ },
+ .driver_version = ZFCP_VERSION,
+ };
+@@ -179,11 +183,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 +445,32 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
+ return retval;
+ }
+
-static int
--qeth_send_stoplan(struct qeth_card *card)
--{
-- int rc = 0;
--
+-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;
++}
+
- /*
-- * TODO: according to the IPA format document page 14,
-- * TCP/IP (we!) never issue a STOPLAN
-- * is this right ?!?
+- * 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.
- */
-- 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;
+- 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 {
--#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);
+- ZFCP_LOG_DEBUG("target reset succeeded (unit=%p)\n", unit);
+- retval = SUCCESS;
- }
-- return rc;
--}
--
--static int
--qeth_start_ipa_ip_fragmentation(struct qeth_card *card)
--{
-- int rc;
+- out:
+- return retval;
++ return retval ? FAILED : SUCCESS;
+ }
+
+ static int
+@@ -553,7 +530,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;
+@@ -834,4 +811,116 @@ static struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
+ NULL
+ };
+
++static ssize_t zfcp_sysfs_adapter_util_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct Scsi_Host *scsi_host = dev_to_shost(dev);
++ struct fsf_qtcb_bottom_port *qtcb_port;
++ int retval;
++ struct zfcp_adapter *adapter;
++
++ adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
++ if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
++ return -EOPNOTSUPP;
++
++ qtcb_port = kzalloc(sizeof(struct fsf_qtcb_bottom_port), GFP_KERNEL);
++ if (!qtcb_port)
++ return -ENOMEM;
++
++ retval = zfcp_fsf_exchange_port_data_sync(adapter, qtcb_port);
++ if (!retval)
++ retval = sprintf(buf, "%u %u %u\n", qtcb_port->cp_util,
++ qtcb_port->cb_util, qtcb_port->a_util);
++ kfree(qtcb_port);
++ return retval;
++}
++
++static int zfcp_sysfs_adapter_ex_config(struct device *dev,
++ struct fsf_statistics_info *stat_inf)
++{
++ int retval;
++ struct fsf_qtcb_bottom_config *qtcb_config;
++ struct Scsi_Host *scsi_host = dev_to_shost(dev);
++ struct zfcp_adapter *adapter;
++
++ adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
++ if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
++ return -EOPNOTSUPP;
++
++ qtcb_config = kzalloc(sizeof(struct fsf_qtcb_bottom_config),
++ GFP_KERNEL);
++ if (!qtcb_config)
++ return -ENOMEM;
++
++ retval = zfcp_fsf_exchange_config_data_sync(adapter, qtcb_config);
++ if (!retval)
++ *stat_inf = qtcb_config->stat_info;
++
++ kfree(qtcb_config);
++ return retval;
++}
++
++static ssize_t zfcp_sysfs_adapter_request_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct fsf_statistics_info stat_info;
++ int retval;
++
++ retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
++ if (retval)
++ return retval;
++
++ return sprintf(buf, "%llu %llu %llu\n",
++ (unsigned long long) stat_info.input_req,
++ (unsigned long long) stat_info.output_req,
++ (unsigned long long) stat_info.control_req);
++}
++
++static ssize_t zfcp_sysfs_adapter_mb_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct fsf_statistics_info stat_info;
++ int retval;
++
++ retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
++ if (retval)
++ return retval;
++
++ return sprintf(buf, "%llu %llu\n",
++ (unsigned long long) stat_info.input_mb,
++ (unsigned long long) stat_info.output_mb);
++}
++
++static ssize_t zfcp_sysfs_adapter_sec_active_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct fsf_statistics_info stat_info;
++ int retval;
++
++ retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
++ if (retval)
++ return retval;
++
++ return sprintf(buf, "%llu\n",
++ (unsigned long long) stat_info.seconds_act);
++}
++
++static DEVICE_ATTR(utilization, S_IRUGO, zfcp_sysfs_adapter_util_show, NULL);
++static DEVICE_ATTR(requests, S_IRUGO, zfcp_sysfs_adapter_request_show, NULL);
++static DEVICE_ATTR(megabytes, S_IRUGO, zfcp_sysfs_adapter_mb_show, NULL);
++static DEVICE_ATTR(seconds_active, S_IRUGO,
++ zfcp_sysfs_adapter_sec_active_show, NULL);
++
++static struct device_attribute *zfcp_a_stats_attrs[] = {
++ &dev_attr_utilization,
++ &dev_attr_requests,
++ &dev_attr_megabytes,
++ &dev_attr_seconds_active,
++ NULL
++};
++
+ #undef ZFCP_LOG_AREA
+diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c
+index 705c6d4..ccbba4d 100644
+--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c
++++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c
+@@ -89,7 +89,7 @@ zfcp_sysfs_port_add_store(struct device *dev, struct device_attribute *attr, con
+
+ retval = 0;
+
+- zfcp_erp_port_reopen(port, 0);
++ zfcp_erp_port_reopen(port, 0, 91, NULL);
+ zfcp_erp_wait(port->adapter);
+ zfcp_port_put(port);
+ out:
+@@ -147,7 +147,7 @@ zfcp_sysfs_port_remove_store(struct device *dev, struct device_attribute *attr,
+ goto out;
+ }
+
+- zfcp_erp_port_shutdown(port, 0);
++ zfcp_erp_port_shutdown(port, 0, 92, NULL);
+ zfcp_erp_wait(adapter);
+ zfcp_port_put(port);
+ zfcp_port_dequeue(port);
+@@ -191,9 +191,10 @@ zfcp_sysfs_adapter_failed_store(struct device *dev, struct device_attribute *att
+ goto out;
+ }
+
+- zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING,
+- ZFCP_SET);
+- zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
++ zfcp_erp_modify_adapter_status(adapter, 44, NULL,
++ ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
++ zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 93,
++ NULL);
+ zfcp_erp_wait(adapter);
+ out:
+ up(&zfcp_data.config_sema);
+diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
+index 1320c05..703c1b5 100644
+--- a/drivers/s390/scsi/zfcp_sysfs_port.c
++++ b/drivers/s390/scsi/zfcp_sysfs_port.c
+@@ -94,7 +94,7 @@ zfcp_sysfs_unit_add_store(struct device *dev, struct device_attribute *attr, con
+
+ retval = 0;
+
+- zfcp_erp_unit_reopen(unit, 0);
++ zfcp_erp_unit_reopen(unit, 0, 94, NULL);
+ zfcp_erp_wait(unit->port->adapter);
+ zfcp_unit_put(unit);
+ out:
+@@ -150,7 +150,7 @@ zfcp_sysfs_unit_remove_store(struct device *dev, struct device_attribute *attr,
+ goto out;
+ }
+
+- zfcp_erp_unit_shutdown(unit, 0);
++ zfcp_erp_unit_shutdown(unit, 0, 95, NULL);
+ zfcp_erp_wait(unit->port->adapter);
+ zfcp_unit_put(unit);
+ zfcp_unit_dequeue(unit);
+@@ -193,8 +193,9 @@ zfcp_sysfs_port_failed_store(struct device *dev, struct device_attribute *attr,
+ goto out;
+ }
+
+- zfcp_erp_modify_port_status(port, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
+- zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED);
++ zfcp_erp_modify_port_status(port, 45, NULL,
++ ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
++ zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, 96, NULL);
+ zfcp_erp_wait(port->adapter);
+ out:
+ up(&zfcp_data.config_sema);
+diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c
+index 63f75ee..80fb2c2 100644
+--- a/drivers/s390/scsi/zfcp_sysfs_unit.c
++++ b/drivers/s390/scsi/zfcp_sysfs_unit.c
+@@ -94,8 +94,9 @@ zfcp_sysfs_unit_failed_store(struct device *dev, struct device_attribute *attr,
+ goto out;
+ }
+
+- zfcp_erp_modify_unit_status(unit, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
+- zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED);
++ zfcp_erp_modify_unit_status(unit, 46, NULL,
++ ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
++ zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, 97, NULL);
+ zfcp_erp_wait(unit->port->adapter);
+ out:
+ up(&zfcp_data.config_sema);
+diff --git a/drivers/s390/sysinfo.c b/drivers/s390/sysinfo.c
+index 291ff62..c3e4ab0 100644
+--- a/drivers/s390/sysinfo.c
++++ b/drivers/s390/sysinfo.c
+@@ -11,111 +11,13 @@
+ #include <linux/init.h>
+ #include <linux/delay.h>
+ #include <asm/ebcdic.h>
++#include <asm/sysinfo.h>
+
+ /* Sigh, math-emu. Don't ask. */
+ #include <asm/sfp-util.h>
+ #include <math-emu/soft-fp.h>
+ #include <math-emu/single.h>
+
+-struct sysinfo_1_1_1 {
+- char reserved_0[32];
+- char manufacturer[16];
+- char type[4];
+- char reserved_1[12];
+- char model_capacity[16];
+- char sequence[16];
+- char plant[4];
+- char model[16];
+-};
-
-- QETH_DBF_TEXT(trace,3,"ipaipfrg");
+-struct sysinfo_1_2_1 {
+- char reserved_0[80];
+- char sequence[16];
+- char plant[4];
+- char reserved_1[2];
+- unsigned short cpu_address;
+-};
-
-- if (!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) {
-- PRINT_INFO("Hardware IP fragmentation not supported on %s\n",
-- QETH_CARD_IFNAME(card));
-- return -EOPNOTSUPP;
-- }
+-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];
+-};
-
-- 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;
--}
+-struct sysinfo_1_2_2_extension {
+- unsigned int alt_capability;
+- unsigned short alt_adjustment[0];
+-};
-
--static int
--qeth_start_ipa_source_mac(struct qeth_card *card)
--{
-- int rc;
+-struct sysinfo_2_2_1 {
+- char reserved_0[80];
+- char sequence[16];
+- char plant[4];
+- unsigned short cpu_id;
+- unsigned short cpu_address;
+-};
-
-- QETH_DBF_TEXT(trace,3,"stsrcmac");
+-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;
+-};
-
-- if (!card->options.fake_ll)
-- return -EOPNOTSUPP;
+-#define LPAR_CHAR_DEDICATED (1 << 7)
+-#define LPAR_CHAR_SHARED (1 << 6)
+-#define LPAR_CHAR_LIMITED (1 << 5)
-
-- if (!qeth_is_supported(card, IPA_SOURCE_MAC)) {
-- PRINT_INFO("Inbound source address not "
-- "supported on %s\n", QETH_CARD_IFNAME(card));
-- return -EOPNOTSUPP;
-- }
+-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];
-
-- 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;
--}
+- } vm[8];
+-};
-
--static int
--qeth_start_ipa_vlan(struct qeth_card *card)
+-static inline int stsi(void *sysinfo, int fc, int sel1, int sel2)
-{
-- 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;
-- }
+- register int r0 asm("0") = (fc << 28) | sel1;
+- register int r1 asm("1") = sel2;
-
-- 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;
+- 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 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;
-- }
+ 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/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
+index a4e7581..2357034 100644
+--- a/drivers/sbus/char/cpwatchdog.c
++++ b/drivers/sbus/char/cpwatchdog.c
+@@ -637,7 +637,7 @@ static int wd_inittimer(int whichdog)
+ break;
+ default:
+ printk("%s: %s: invalid watchdog id: %i\n",
+- WD_OBPNAME, __FUNCTION__, whichdog);
++ WD_OBPNAME, __func__, whichdog);
+ return(1);
+ }
+ if(0 != misc_register(whichmisc))
+diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c
+index 44d2ef9..383f32c 100644
+--- a/drivers/sbus/char/uctrl.c
++++ b/drivers/sbus/char/uctrl.c
+@@ -393,13 +393,13 @@ static int __init ts102_uctrl_init(void)
+ err = request_irq(driver->irq, uctrl_interrupt, 0, "uctrl", driver);
+ if (err) {
+ printk("%s: unable to register irq %d\n",
+- __FUNCTION__, driver->irq);
++ __func__, driver->irq);
+ return err;
+ }
+
+ if (misc_register(&uctrl_dev)) {
+ printk("%s: unable to get misc minor %d\n",
+- __FUNCTION__, uctrl_dev.minor);
++ __func__, uctrl_dev.minor);
+ free_irq(driver->irq, driver);
+ return -ENODEV;
+ }
+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));
-
-- 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;
--}
+ /* 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);
-
--#ifdef CONFIG_QETH_IPV6
--static int
--qeth_softsetup_ipv6(struct qeth_card *card)
--{
-- int rc;
+- memcpy(buf, data, transfer_len);
-
-- QETH_DBF_TEXT(trace,3,"softipv6");
+- 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));
-
-- 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;
--}
+ /* 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
-
--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);
+-#ifndef CONFIG_PCI
+-#undef CONFIG_SCSI_OMIT_FLASHPOINT
+-#define CONFIG_SCSI_OMIT_FLASHPOINT
+-#define BusLogic_InitializeProbeInfoListISA BusLogic_InitializeProbeInfoList
-#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)
+-/*
+ 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..b898d38 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
+@@ -1499,7 +1499,7 @@ static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
+ thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
+ ioport = ((struct sccb_card *)pCurrCard)->ioPort;
+
+- if ((p_Sccb->TargID > MAX_SCSI_TAR) || (p_Sccb->Lun > MAX_LUN)) {
++ if ((p_Sccb->TargID >= MAX_SCSI_TAR) || (p_Sccb->Lun >= MAX_LUN)) {
+
+ p_Sccb->HostStatus = SCCB_COMPLETE;
+ p_Sccb->SccbStatus = SCCB_ERROR;
+@@ -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..99c57b0 100644
+--- a/drivers/scsi/Kconfig
++++ b/drivers/scsi/Kconfig
+@@ -588,18 +588,20 @@ config SCSI_BUSLOGIC
+ <http://www.tldp.org/docs.html#howto>, and the files
+ <file:Documentation/scsi/BusLogic.txt> and
+ <file:Documentation/scsi/FlashPoint.txt> for more information.
++ Note that support for FlashPoint is only available for 32-bit
++ x86 configurations.
+
+ To compile this driver as a module, choose M here: the
+ module will be called BusLogic.
+
+-config SCSI_OMIT_FLASHPOINT
+- bool "Omit FlashPoint support"
+- depends on SCSI_BUSLOGIC
++config SCSI_FLASHPOINT
++ bool "FlashPoint support"
++ depends on SCSI_BUSLOGIC && PCI && X86_32
+ help
+- This option allows you to omit the FlashPoint support from the
++ This option allows you to add FlashPoint support to the
+ BusLogic SCSI driver. The FlashPoint SCCB Manager code is
+- substantial, so users of MultiMaster Host Adapters may wish to omit
+- it.
++ substantial, so users of MultiMaster Host Adapters may not
++ wish to include it.
+
+ config SCSI_DMX3191D
+ tristate "DMX3191D SCSI support"
+@@ -1675,6 +1677,16 @@ config MAC_SCSI
+ SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
++config SCSI_MAC_ESP
++ tristate "Macintosh NCR53c9[46] SCSI"
++ depends on MAC && SCSI
++ help
++ This is the NCR 53c9x SCSI controller found on most of the 68040
++ based Macintoshes.
++
++ To compile this driver as a module, choose M here: the module
++ will be called mac_esp.
++
+ config MVME147_SCSI
+ bool "WD33C93 SCSI driver for MVME147"
+ depends on MVME147 && SCSI=y
+diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
+index 23e6ecb..6c775e3 100644
+--- a/drivers/scsi/Makefile
++++ b/drivers/scsi/Makefile
+@@ -46,6 +46,7 @@ obj-$(CONFIG_MVME147_SCSI) += mvme147.o wd33c93.o
+ obj-$(CONFIG_SGIWD93_SCSI) += sgiwd93.o wd33c93.o
+ obj-$(CONFIG_ATARI_SCSI) += atari_scsi.o
+ obj-$(CONFIG_MAC_SCSI) += mac_scsi.o
++obj-$(CONFIG_SCSI_MAC_ESP) += esp_scsi.o mac_esp.o
+ obj-$(CONFIG_SUN3_SCSI) += sun3_scsi.o sun3_scsi_vme.o
+ obj-$(CONFIG_MVME16x_SCSI) += 53c700.o mvme16x_scsi.o
+ obj-$(CONFIG_BVME6000_SCSI) += 53c700.o bvme6000_scsi.o
+diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
+index 5ac3a3e..07d572f 100644
+--- a/drivers/scsi/a2091.c
++++ b/drivers/scsi/a2091.c
+@@ -179,6 +179,9 @@ int __init a2091_detect(struct scsi_host_template *tpnt)
+ DMA(instance)->DAWR = DAWR_A2091;
+ regs.SASR = &(DMA(instance)->SASR);
+ regs.SCMD = &(DMA(instance)->SCMD);
++ HDATA(instance)->no_sync = 0xff;
++ HDATA(instance)->fast = 0;
++ HDATA(instance)->dma_mode = CTRL_DMA;
+ wd33c93_init(instance, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
+ request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED, "A2091 SCSI",
+ instance);
+diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
+index 3aeec96..8b449d8 100644
+--- a/drivers/scsi/a3000.c
++++ b/drivers/scsi/a3000.c
+@@ -178,6 +178,9 @@ int __init a3000_detect(struct scsi_host_template *tpnt)
+ DMA(a3000_host)->DAWR = DAWR_A3000;
+ regs.SASR = &(DMA(a3000_host)->SASR);
+ regs.SCMD = &(DMA(a3000_host)->SCMD);
++ HDATA(a3000_host)->no_sync = 0xff;
++ HDATA(a3000_host)->fast = 0;
++ HDATA(a3000_host)->dma_mode = CTRL_DMA;
+ wd33c93_init(a3000_host, regs, dma_setup, dma_stop, WD33C93_FS_12_15);
+ if (request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, "A3000 SCSI",
+ a3000_intr))
+diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
+index c05092f..460d402 100644
+--- a/drivers/scsi/aacraid/aachba.c
++++ b/drivers/scsi/aacraid/aachba.c
+@@ -31,7 +31,6 @@
+ #include <linux/slab.h>
+ #include <linux/completion.h>
+ #include <linux/blkdev.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ #include <linux/highmem.h> /* For flush_kernel_dcache_page */
+
+@@ -205,7 +204,7 @@ MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health"
+
+ int aac_check_reset = 1;
+ module_param_named(check_reset, aac_check_reset, int, S_IRUGO|S_IWUSR);
+-MODULE_PARM_DESC(aac_check_reset, "If adapter fails health check, reset the"
++MODULE_PARM_DESC(check_reset, "If adapter fails health check, reset the"
+ " adapter. a value of -1 forces the reset to adapters programmed to"
+ " ignore it.");
+
+@@ -379,24 +378,6 @@ int aac_get_containers(struct aac_dev *dev)
+ return status;
+ }
+
+-static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len)
-{
-- 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;
--}
+- void *buf;
+- int transfer_len;
+- struct scatterlist *sg = scsi_sglist(scsicmd);
-
--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;
+- buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+- transfer_len = min(sg->length, len + offset);
-
-- 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);
+- transfer_len -= offset;
+- if (buf && transfer_len > 0)
+- memcpy(buf + offset, data, transfer_len);
-
-- return rc;
+- flush_kernel_dcache_page(kmap_atomic_to_page(buf - sg->offset));
+- kunmap_atomic(buf - sg->offset, KM_IRQ0);
-
-}
-
--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;
+ static void get_container_name_callback(void *context, struct fib * fibptr)
+ {
+ struct aac_get_name_resp * get_name_reply;
+@@ -419,14 +400,17 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
+ while (*sp == ' ')
+ ++sp;
+ if (*sp) {
++ struct inquiry_data inq;
+ char d[sizeof(((struct inquiry_data *)NULL)->inqd_pid)];
+ int count = sizeof(d);
+ char *dp = d;
+ do {
+ *dp++ = (*sp) ? *sp++ : ' ';
+ } while (--count > 0);
+- aac_internal_transfer(scsicmd, d,
+- offsetof(struct inquiry_data, inqd_pid), sizeof(d));
++
++ scsi_sg_copy_to_buffer(scsicmd, &inq, sizeof(inq));
++ memcpy(inq.inqd_pid, d, sizeof(d));
++ scsi_sg_copy_from_buffer(scsicmd, &inq, sizeof(inq));
+ }
+ }
+
+@@ -811,7 +795,7 @@ static void get_container_serial_callback(void *context, struct fib * fibptr)
+ sp[2] = 0;
+ sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X",
+ le32_to_cpu(get_serial_reply->uid));
+- aac_internal_transfer(scsicmd, sp, 0, sizeof(sp));
++ scsi_sg_copy_from_buffer(scsicmd, sp, sizeof(sp));
+ }
+
+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+@@ -1331,7 +1315,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
+ tmp>>24,(tmp>>16)&0xff,tmp&0xff,
+ le32_to_cpu(dev->adapter_info.biosbuild));
+ buffer[0] = '\0';
+- if (aac_show_serial_number(
++ if (aac_get_serial_number(
+ shost_to_class(dev->scsi_host_ptr), buffer))
+ printk(KERN_INFO "%s%d: serial %s",
+ dev->name, dev->id, buffer);
+@@ -1986,8 +1970,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ arr[4] = 0x0;
+ arr[5] = 0x80;
+ arr[1] = scsicmd->cmnd[2];
+- aac_internal_transfer(scsicmd, &inq_data, 0,
+- sizeof(inq_data));
++ scsi_sg_copy_from_buffer(scsicmd, &inq_data,
++ sizeof(inq_data));
+ scsicmd->result = DID_OK << 16 |
+ COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+ } else if (scsicmd->cmnd[2] == 0x80) {
+@@ -1995,8 +1979,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ arr[3] = setinqserial(dev, &arr[4],
+ scmd_id(scsicmd));
+ arr[1] = scsicmd->cmnd[2];
+- aac_internal_transfer(scsicmd, &inq_data, 0,
+- sizeof(inq_data));
++ scsi_sg_copy_from_buffer(scsicmd, &inq_data,
++ sizeof(inq_data));
+ return aac_get_container_serial(scsicmd);
+ } else {
+ /* vpd page not implemented */
+@@ -2027,7 +2011,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ if (cid == host->this_id) {
+ setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types));
+ inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */
+- aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
++ scsi_sg_copy_from_buffer(scsicmd, &inq_data,
++ sizeof(inq_data));
+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+ scsicmd->scsi_done(scsicmd);
+ return 0;
+@@ -2036,7 +2021,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ return -1;
+ setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
+ inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */
+- aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
++ scsi_sg_copy_from_buffer(scsicmd, &inq_data, sizeof(inq_data));
+ return aac_get_container_name(scsicmd);
+ }
+ case SERVICE_ACTION_IN:
+@@ -2047,6 +2032,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ {
+ u64 capacity;
+ char cp[13];
++ unsigned int alloc_len;
+
+ dprintk((KERN_DEBUG "READ CAPACITY_16 command.\n"));
+ capacity = fsa_dev_ptr[cid].size - 1;
+@@ -2063,18 +2049,16 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ cp[10] = 2;
+ cp[11] = 0;
+ cp[12] = 0;
+- aac_internal_transfer(scsicmd, cp, 0,
+- min_t(size_t, scsicmd->cmnd[13], sizeof(cp)));
+- if (sizeof(cp) < scsicmd->cmnd[13]) {
+- unsigned int len, offset = sizeof(cp);
+
+- memset(cp, 0, offset);
+- do {
+- len = min_t(size_t, scsicmd->cmnd[13] - offset,
+- sizeof(cp));
+- aac_internal_transfer(scsicmd, cp, offset, len);
+- } while ((offset += len) < scsicmd->cmnd[13]);
- }
++ alloc_len = ((scsicmd->cmnd[10] << 24)
++ + (scsicmd->cmnd[11] << 16)
++ + (scsicmd->cmnd[12] << 8) + scsicmd->cmnd[13]);
++
++ alloc_len = min_t(size_t, alloc_len, sizeof(cp));
++ scsi_sg_copy_from_buffer(scsicmd, cp, alloc_len);
++ if (alloc_len < scsi_bufflen(scsicmd))
++ scsi_set_resid(scsicmd,
++ scsi_bufflen(scsicmd) - alloc_len);
+
+ /* Do not cache partition table for arrays */
+ scsicmd->device->removable = 1;
+@@ -2104,7 +2088,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ cp[5] = 0;
+ cp[6] = 2;
+ cp[7] = 0;
+- aac_internal_transfer(scsicmd, cp, 0, sizeof(cp));
++ scsi_sg_copy_from_buffer(scsicmd, cp, sizeof(cp));
+ /* Do not cache partition table for arrays */
+ scsicmd->device->removable = 1;
+
+@@ -2139,7 +2123,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ if (mode_buf_length > scsicmd->cmnd[4])
+ mode_buf_length = scsicmd->cmnd[4];
+ }
+- aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
++ scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length);
+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+ scsicmd->scsi_done(scsicmd);
+
+@@ -2174,7 +2158,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ if (mode_buf_length > scsicmd->cmnd[8])
+ mode_buf_length = scsicmd->cmnd[8];
+ }
+- aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
++ scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length);
+
+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+ scsicmd->scsi_done(scsicmd);
+diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
+index ace0b75..113ca9c 100644
+--- a/drivers/scsi/aacraid/aacraid.h
++++ b/drivers/scsi/aacraid/aacraid.h
+@@ -1850,9 +1850,9 @@ int aac_get_containers(struct aac_dev *dev);
+ int aac_scsi_cmd(struct scsi_cmnd *cmd);
+ int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg);
+ #ifndef shost_to_class
+-#define shost_to_class(shost) &shost->shost_classdev
++#define shost_to_class(shost) &shost->shost_dev
+ #endif
+-ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf);
++ssize_t aac_get_serial_number(struct device *dev, char *buf);
+ int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg);
+ int aac_rx_init(struct aac_dev *dev);
+ int aac_rkt_init(struct aac_dev *dev);
+diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
+index abef051..5fd83de 100644
+--- a/drivers/scsi/aacraid/commctrl.c
++++ b/drivers/scsi/aacraid/commctrl.c
+@@ -39,7 +39,7 @@
+ #include <linux/blkdev.h>
+ #include <linux/delay.h> /* ssleep prototype */
+ #include <linux/kthread.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include "aacraid.h"
+diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
+index 89cc8b7..294a802 100644
+--- a/drivers/scsi/aacraid/comminit.c
++++ b/drivers/scsi/aacraid/comminit.c
+@@ -39,7 +39,6 @@
+ #include <linux/completion.h>
+ #include <linux/mm.h>
+ #include <scsi/scsi_host.h>
+-#include <asm/semaphore.h>
+
+ #include "aacraid.h"
+
+diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
+index 4743449..ef67816 100644
+--- a/drivers/scsi/aacraid/commsup.c
++++ b/drivers/scsi/aacraid/commsup.c
+@@ -41,11 +41,11 @@
+ #include <linux/delay.h>
+ #include <linux/kthread.h>
+ #include <linux/interrupt.h>
++#include <linux/semaphore.h>
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi_device.h>
+ #include <scsi/scsi_cmnd.h>
+-#include <asm/semaphore.h>
+
+ #include "aacraid.h"
+
+@@ -515,10 +515,12 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
+ }
+ udelay(5);
+ }
+- } else
+- (void)down_interruptible(&fibptr->event_wait);
++ } else if (down_interruptible(&fibptr->event_wait) == 0) {
++ fibptr->done = 2;
++ up(&fibptr->event_wait);
++ }
+ spin_lock_irqsave(&fibptr->event_lock, flags);
+- if (fibptr->done == 0) {
++ if ((fibptr->done == 0) || (fibptr->done == 2)) {
+ fibptr->done = 2; /* Tell interrupt we aborted */
+ spin_unlock_irqrestore(&fibptr->event_lock, flags);
+ return -EINTR;
+@@ -594,7 +596,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid)
+ if (le32_to_cpu(*q->headers.consumer) >= q->entries)
+ *q->headers.consumer = cpu_to_le32(1);
+ else
+- *q->headers.consumer = cpu_to_le32(le32_to_cpu(*q->headers.consumer)+1);
++ le32_add_cpu(q->headers.consumer, 1);
+
+ if (wasfull) {
+ switch (qid) {
+diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
+index d1163de..933f208 100644
+--- a/drivers/scsi/aacraid/dpcsup.c
++++ b/drivers/scsi/aacraid/dpcsup.c
+@@ -36,7 +36,7 @@
+ #include <linux/slab.h>
+ #include <linux/completion.h>
+ #include <linux/blkdev.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+
+ #include "aacraid.h"
+
+diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
+index ae5f74f..c109f63 100644
+--- a/drivers/scsi/aacraid/linit.c
++++ b/drivers/scsi/aacraid/linit.c
+@@ -42,7 +42,6 @@
+ #include <linux/syscalls.h>
+ #include <linux/delay.h>
+ #include <linux/kthread.h>
+-#include <asm/semaphore.h>
+
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_cmnd.h>
+@@ -755,10 +754,10 @@ static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long
+ }
+ #endif
+
+-static ssize_t aac_show_model(struct class_device *class_dev,
+- char *buf)
++static ssize_t aac_show_model(struct device *device,
++ struct device_attribute *attr, char *buf)
+ {
+- struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++ struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ int len;
+
+ if (dev->supplement_adapter_info.AdapterTypeText[0]) {
+@@ -774,10 +773,10 @@ static ssize_t aac_show_model(struct class_device *class_dev,
+ return len;
+ }
+
+-static ssize_t aac_show_vendor(struct class_device *class_dev,
+- char *buf)
++static ssize_t aac_show_vendor(struct device *device,
++ struct device_attribute *attr, char *buf)
+ {
+- struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++ struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ int len;
+
+ if (dev->supplement_adapter_info.AdapterTypeText[0]) {
+@@ -793,10 +792,11 @@ static ssize_t aac_show_vendor(struct class_device *class_dev,
+ return len;
+ }
+
+-static ssize_t aac_show_flags(struct class_device *class_dev, char *buf)
++static ssize_t aac_show_flags(struct device *cdev,
++ struct device_attribute *attr, char *buf)
+ {
+ int len = 0;
+- struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++ struct aac_dev *dev = (struct aac_dev*)class_to_shost(cdev)->hostdata;
+
+ if (nblank(dprintk(x)))
+ len = snprintf(buf, PAGE_SIZE, "dprintk\n");
+@@ -812,10 +812,11 @@ static ssize_t aac_show_flags(struct class_device *class_dev, char *buf)
+ return len;
+ }
+
+-static ssize_t aac_show_kernel_version(struct class_device *class_dev,
+- char *buf)
++static ssize_t aac_show_kernel_version(struct device *device,
++ struct device_attribute *attr,
++ char *buf)
+ {
+- struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++ struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ int len, tmp;
+
+ tmp = le32_to_cpu(dev->adapter_info.kernelrev);
+@@ -825,10 +826,11 @@ static ssize_t aac_show_kernel_version(struct class_device *class_dev,
+ return len;
+ }
+
+-static ssize_t aac_show_monitor_version(struct class_device *class_dev,
+- char *buf)
++static ssize_t aac_show_monitor_version(struct device *device,
++ struct device_attribute *attr,
++ char *buf)
+ {
+- struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++ struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ int len, tmp;
+
+ tmp = le32_to_cpu(dev->adapter_info.monitorrev);
+@@ -838,10 +840,11 @@ static ssize_t aac_show_monitor_version(struct class_device *class_dev,
+ return len;
+ }
+
+-static ssize_t aac_show_bios_version(struct class_device *class_dev,
+- char *buf)
++static ssize_t aac_show_bios_version(struct device *device,
++ struct device_attribute *attr,
++ char *buf)
+ {
+- struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++ struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ int len, tmp;
+
+ tmp = le32_to_cpu(dev->adapter_info.biosrev);
+@@ -851,9 +854,10 @@ static ssize_t aac_show_bios_version(struct class_device *class_dev,
+ return len;
+ }
+
+-ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf)
++ssize_t aac_show_serial_number(struct device *device,
++ struct device_attribute *attr, char *buf)
+ {
+- struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++ struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ int len = 0;
+
+ if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
+@@ -869,35 +873,39 @@ ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf)
+ return len;
+ }
+
+-static ssize_t aac_show_max_channel(struct class_device *class_dev, char *buf)
++static ssize_t aac_show_max_channel(struct device *device,
++ struct device_attribute *attr, char *buf)
+ {
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+- class_to_shost(class_dev)->max_channel);
++ class_to_shost(device)->max_channel);
+ }
+
+-static ssize_t aac_show_max_id(struct class_device *class_dev, char *buf)
++static ssize_t aac_show_max_id(struct device *device,
++ struct device_attribute *attr, char *buf)
+ {
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+- class_to_shost(class_dev)->max_id);
++ class_to_shost(device)->max_id);
+ }
+
+-static ssize_t aac_store_reset_adapter(struct class_device *class_dev,
+- const char *buf, size_t count)
++static ssize_t aac_store_reset_adapter(struct device *device,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ int retval = -EACCES;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return retval;
+- retval = aac_reset_adapter((struct aac_dev*)class_to_shost(class_dev)->hostdata, buf[0] == '!');
++ retval = aac_reset_adapter((struct aac_dev*)class_to_shost(device)->hostdata, buf[0] == '!');
+ if (retval >= 0)
+ retval = count;
+ return retval;
+ }
+
+-static ssize_t aac_show_reset_adapter(struct class_device *class_dev,
+- char *buf)
++static ssize_t aac_show_reset_adapter(struct device *device,
++ struct device_attribute *attr,
++ char *buf)
+ {
+- struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++ struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ int len, tmp;
+
+ tmp = aac_adapter_check_health(dev);
+@@ -907,70 +915,70 @@ static ssize_t aac_show_reset_adapter(struct class_device *class_dev,
+ return len;
+ }
+
+-static struct class_device_attribute aac_model = {
++static struct device_attribute aac_model = {
+ .attr = {
+ .name = "model",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_model,
+ };
+-static struct class_device_attribute aac_vendor = {
++static struct device_attribute aac_vendor = {
+ .attr = {
+ .name = "vendor",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_vendor,
+ };
+-static struct class_device_attribute aac_flags = {
++static struct device_attribute aac_flags = {
+ .attr = {
+ .name = "flags",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_flags,
+ };
+-static struct class_device_attribute aac_kernel_version = {
++static struct device_attribute aac_kernel_version = {
+ .attr = {
+ .name = "hba_kernel_version",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_kernel_version,
+ };
+-static struct class_device_attribute aac_monitor_version = {
++static struct device_attribute aac_monitor_version = {
+ .attr = {
+ .name = "hba_monitor_version",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_monitor_version,
+ };
+-static struct class_device_attribute aac_bios_version = {
++static struct device_attribute aac_bios_version = {
+ .attr = {
+ .name = "hba_bios_version",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_bios_version,
+ };
+-static struct class_device_attribute aac_serial_number = {
++static struct device_attribute aac_serial_number = {
+ .attr = {
+ .name = "serial_number",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_serial_number,
+ };
+-static struct class_device_attribute aac_max_channel = {
++static struct device_attribute aac_max_channel = {
+ .attr = {
+ .name = "max_channel",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_max_channel,
+ };
+-static struct class_device_attribute aac_max_id = {
++static struct device_attribute aac_max_id = {
+ .attr = {
+ .name = "max_id",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_max_id,
+ };
+-static struct class_device_attribute aac_reset = {
++static struct device_attribute aac_reset = {
+ .attr = {
+ .name = "reset_host",
+ .mode = S_IWUSR|S_IRUGO,
+@@ -979,7 +987,7 @@ static struct class_device_attribute aac_reset = {
+ .show = aac_show_reset_adapter,
+ };
+
+-static struct class_device_attribute *aac_attrs[] = {
++static struct device_attribute *aac_attrs[] = {
+ &aac_model,
+ &aac_vendor,
+ &aac_flags,
+@@ -993,6 +1001,10 @@ static struct class_device_attribute *aac_attrs[] = {
+ NULL
+ };
+
++ssize_t aac_get_serial_number(struct device *device, char *buf)
++{
++ return aac_show_serial_number(device, &aac_serial_number, buf);
++}
+
+ static const struct file_operations aac_cfg_fops = {
+ .owner = THIS_MODULE,
+diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
+index 1f18b83..073208b 100644
+--- a/drivers/scsi/aacraid/rx.c
++++ b/drivers/scsi/aacraid/rx.c
+@@ -39,7 +39,6 @@
+ #include <linux/completion.h>
+ #include <linux/time.h>
+ #include <linux/interrupt.h>
+-#include <asm/semaphore.h>
+
+ #include <scsi/scsi_host.h>
+
+diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
+index cfc3410..fc1a557 100644
+--- a/drivers/scsi/aacraid/sa.c
++++ b/drivers/scsi/aacraid/sa.c
+@@ -39,7 +39,6 @@
+ #include <linux/completion.h>
+ #include <linux/time.h>
+ #include <linux/interrupt.h>
+-#include <asm/semaphore.h>
+
+ #include <scsi/scsi_host.h>
+
+diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
+index 6ccdc96..f5215fd 100644
+--- a/drivers/scsi/aha152x.c
++++ b/drivers/scsi/aha152x.c
+@@ -994,13 +994,13 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete,
+ SCpnt->SCp.sent_command = 0;
+
+ if(SCpnt->SCp.phase & (resetting|check_condition)) {
+- if(SCpnt->host_scribble==0 || SCSEM(SCpnt) || SCNEXT(SCpnt)) {
++ if (!SCpnt->host_scribble || SCSEM(SCpnt) || SCNEXT(SCpnt)) {
+ printk(ERR_LEAD "cannot reuse command\n", CMDINFO(SCpnt));
+ return FAILED;
+ }
+ } else {
+ SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC);
+- if(SCpnt->host_scribble==0) {
++ if(!SCpnt->host_scribble) {
+ printk(ERR_LEAD "allocation failed\n", CMDINFO(SCpnt));
+ return FAILED;
+ }
+@@ -1162,7 +1162,7 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
+ }
+
+ DO_LOCK(flags);
+- issued = remove_SC(&ISSUE_SC, SCpnt)==0;
++ issued = remove_SC(&ISSUE_SC, SCpnt) == NULL;
+ disconnected = issued && remove_SC(&DISCONNECTED_SC, SCpnt);
+ DO_UNLOCK(flags);
+
+@@ -1432,15 +1432,10 @@ static void run(struct work_struct *work)
+ */
+ static irqreturn_t intr(int irqno, void *dev_id)
+ {
+- struct Scsi_Host *shpnt = (struct Scsi_Host *)dev_id;
++ struct Scsi_Host *shpnt = dev_id;
+ unsigned long flags;
+ unsigned char rev, dmacntrl0;
+
+- if (!shpnt) {
+- printk(KERN_ERR "aha152x: catched interrupt %d for unknown controller.\n", irqno);
+- return IRQ_NONE;
- }
--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;
+ /*
+ * Read a couple of registers that are known to not be all 1's. If
+ * we read all 1's (-1), that means that either:
+diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
+index 5a1471c..8059494 100644
+--- a/drivers/scsi/aha1542.c
++++ b/drivers/scsi/aha1542.c
+@@ -153,8 +153,6 @@ struct aha1542_hostdata {
+
+ #define HOSTDATA(host) ((struct aha1542_hostdata *) &host->hostdata)
+
+-static struct Scsi_Host *aha_host[7]; /* One for each IRQ level (9-15) */
-
-- QETH_DBF_TEXT(trace,3,"setrtg4");
+ static DEFINE_SPINLOCK(aha1542_lock);
+
+
+@@ -163,8 +161,7 @@ static DEFINE_SPINLOCK(aha1542_lock);
+
+ static void setup_mailboxes(int base_io, struct Scsi_Host *shpnt);
+ static int aha1542_restart(struct Scsi_Host *shost);
+-static void aha1542_intr_handle(struct Scsi_Host *shost, void *dev_id);
+-static irqreturn_t do_aha1542_intr_handle(int irq, void *dev_id);
++static void aha1542_intr_handle(struct Scsi_Host *shost);
+
+ #define aha1542_intr_reset(base) outb(IRST, CONTROL(base))
+
+@@ -404,23 +401,19 @@ fail:
+ }
+
+ /* A quick wrapper for do_aha1542_intr_handle to grab the spin lock */
+-static irqreturn_t do_aha1542_intr_handle(int irq, void *dev_id)
++static irqreturn_t do_aha1542_intr_handle(int dummy, void *dev_id)
+ {
+ unsigned long flags;
+- struct Scsi_Host *shost;
-
-- qeth_correct_routing_type(card, &card->options.route4.type,
-- QETH_PROT_IPV4);
+- shost = aha_host[irq - 9];
+- if (!shost)
+- panic("Splunge!");
++ struct Scsi_Host *shost = dev_id;
+
+ spin_lock_irqsave(shost->host_lock, flags);
+- aha1542_intr_handle(shost, dev_id);
++ aha1542_intr_handle(shost);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ return IRQ_HANDLED;
+ }
+
+ /* A "high" level interrupt handler */
+-static void aha1542_intr_handle(struct Scsi_Host *shost, void *dev_id)
++static void aha1542_intr_handle(struct Scsi_Host *shost)
+ {
+ void (*my_done) (Scsi_Cmnd *) = NULL;
+ int errstatus, mbi, mbo, mbistatus;
+@@ -1197,7 +1190,8 @@ fail:
+
+ DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level));
+ spin_lock_irqsave(&aha1542_lock, flags);
+- if (request_irq(irq_level, do_aha1542_intr_handle, 0, "aha1542", NULL)) {
++ if (request_irq(irq_level, do_aha1542_intr_handle, 0,
++ "aha1542", shpnt)) {
+ printk(KERN_ERR "Unable to allocate IRQ for adaptec controller.\n");
+ spin_unlock_irqrestore(&aha1542_lock, flags);
+ goto unregister;
+@@ -1205,7 +1199,7 @@ fail:
+ if (dma_chan != 0xFF) {
+ if (request_dma(dma_chan, "aha1542")) {
+ printk(KERN_ERR "Unable to allocate DMA channel for Adaptec.\n");
+- free_irq(irq_level, NULL);
++ free_irq(irq_level, shpnt);
+ spin_unlock_irqrestore(&aha1542_lock, flags);
+ goto unregister;
+ }
+@@ -1214,7 +1208,7 @@ fail:
+ enable_dma(dma_chan);
+ }
+ }
+- aha_host[irq_level - 9] = shpnt;
++
+ shpnt->this_id = scsi_id;
+ shpnt->unique_id = base_io;
+ shpnt->io_port = base_io;
+@@ -1276,7 +1270,7 @@ unregister:
+ static int aha1542_release(struct Scsi_Host *shost)
+ {
+ if (shost->irq)
+- free_irq(shost->irq, NULL);
++ free_irq(shost->irq, shost);
+ if (shost->dma_channel != 0xff)
+ free_dma(shost->dma_channel);
+ if (shost->io_port && shost->n_io_port)
+diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c
+index 1ac1197..f220e5e 100644
+--- a/drivers/scsi/aic7xxx/aic7770_osm.c
++++ b/drivers/scsi/aic7xxx/aic7770_osm.c
+@@ -50,7 +50,7 @@ aic7770_map_registers(struct ahc_softc *ahc, u_int port)
+ /*
+ * Lock out other contenders for our i/o space.
+ */
+- if (request_region(port, AHC_EISA_IOSIZE, "aic7xxx") == 0)
++ if (!request_region(port, AHC_EISA_IOSIZE, "aic7xxx"))
+ return (ENOMEM);
+ ahc->tag = BUS_SPACE_PIO;
+ ahc->bsh.ioport = port;
+diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
+index 2f00467..be5558a 100644
+--- a/drivers/scsi/aic7xxx/aic79xx.h
++++ b/drivers/scsi/aic7xxx/aic79xx.h
+@@ -815,7 +815,7 @@ struct ahd_tmode_tstate {
+ struct ahd_phase_table_entry {
+ uint8_t phase;
+ uint8_t mesg_out; /* Message response to parity errors */
+- char *phasemsg;
++ const char *phasemsg;
+ };
+
+ /************************** Serial EEPROM Format ******************************/
+@@ -1314,7 +1314,7 @@ typedef int (ahd_device_setup_t)(struct ahd_softc *);
+ struct ahd_pci_identity {
+ uint64_t full_id;
+ uint64_t id_mask;
+- char *name;
++ const char *name;
+ ahd_device_setup_t *setup;
+ };
+
+@@ -1322,7 +1322,7 @@ struct ahd_pci_identity {
+ struct aic7770_identity {
+ uint32_t full_id;
+ uint32_t id_mask;
+- char *name;
++ const char *name;
+ ahd_device_setup_t *setup;
+ };
+ extern struct aic7770_identity aic7770_ident_table [];
+@@ -1333,12 +1333,11 @@ extern const int ahd_num_aic7770_devs;
+
+ /*************************** Function Declarations ****************************/
+ /******************************************************************************/
+-void ahd_reset_cmds_pending(struct ahd_softc *ahd);
+
+ /***************************** PCI Front End *********************************/
+-struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t);
++const struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t);
+ int ahd_pci_config(struct ahd_softc *,
+- struct ahd_pci_identity *);
++ const struct ahd_pci_identity *);
+ int ahd_pci_test_register_access(struct ahd_softc *);
+ #ifdef CONFIG_PM
+ void ahd_pci_suspend(struct ahd_softc *);
+@@ -1376,16 +1375,6 @@ int ahd_write_flexport(struct ahd_softc *ahd,
+ int ahd_read_flexport(struct ahd_softc *ahd, u_int addr,
+ uint8_t *value);
+
+-/*************************** Interrupt Services *******************************/
+-void ahd_run_qoutfifo(struct ahd_softc *ahd);
+-#ifdef AHD_TARGET_MODE
+-void ahd_run_tqinfifo(struct ahd_softc *ahd, int paused);
+-#endif
+-void ahd_handle_hwerrint(struct ahd_softc *ahd);
+-void ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat);
+-void ahd_handle_scsiint(struct ahd_softc *ahd,
+- u_int intstat);
-
-- 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;
--}
+ /***************************** Error Recovery *********************************/
+ typedef enum {
+ SEARCH_COMPLETE,
+@@ -1479,7 +1468,7 @@ extern uint32_t ahd_debug;
+ void ahd_print_devinfo(struct ahd_softc *ahd,
+ struct ahd_devinfo *devinfo);
+ void ahd_dump_card_state(struct ahd_softc *ahd);
+-int ahd_print_register(ahd_reg_parse_entry_t *table,
++int ahd_print_register(const ahd_reg_parse_entry_t *table,
+ u_int num_entries,
+ const char *name,
+ u_int address,
+diff --git a/drivers/scsi/aic7xxx/aic79xx.reg b/drivers/scsi/aic7xxx/aic79xx.reg
+index be14e2e..cca16fc 100644
+--- a/drivers/scsi/aic7xxx/aic79xx.reg
++++ b/drivers/scsi/aic7xxx/aic79xx.reg
+@@ -198,6 +198,7 @@ register SEQINTCODE {
+ register CLRINT {
+ address 0x003
+ access_mode WO
++ count 19
+ field CLRHWERRINT 0x80 /* Rev B or greater */
+ field CLRBRKADRINT 0x40
+ field CLRSWTMINT 0x20
+@@ -245,6 +246,7 @@ register CLRERR {
+ register HCNTRL {
+ address 0x005
+ access_mode RW
++ count 12
+ field SEQ_RESET 0x80 /* Rev B or greater */
+ field POWRDN 0x40
+ field SWINT 0x10
+@@ -262,6 +264,7 @@ register HNSCB_QOFF {
+ address 0x006
+ access_mode RW
+ size 2
++ count 2
+ }
+
+ /*
+@@ -270,6 +273,7 @@ register HNSCB_QOFF {
+ register HESCB_QOFF {
+ address 0x008
+ access_mode RW
++ count 2
+ }
+
+ /*
+@@ -287,6 +291,7 @@ register HS_MAILBOX {
+ */
+ register SEQINTSTAT {
+ address 0x00C
++ count 1
+ access_mode RO
+ field SEQ_SWTMRTO 0x10
+ field SEQ_SEQINT 0x08
+@@ -332,6 +337,7 @@ register SNSCB_QOFF {
+ */
+ register SESCB_QOFF {
+ address 0x012
++ count 2
+ access_mode RW
+ modes M_CCHAN
+ }
+@@ -397,6 +403,7 @@ register DFCNTRL {
+ address 0x019
+ access_mode RW
+ modes M_DFF0, M_DFF1
++ count 11
+ field PRELOADEN 0x80
+ field SCSIENWRDIS 0x40 /* Rev B only. */
+ field SCSIEN 0x20
+@@ -415,6 +422,7 @@ register DFCNTRL {
+ */
+ register DSCOMMAND0 {
+ address 0x019
++ count 1
+ access_mode RW
+ modes M_CFG
+ field CACHETHEN 0x80 /* Cache Threshold enable */
+@@ -580,6 +588,7 @@ register DFF_THRSH {
+ address 0x088
+ access_mode RW
+ modes M_CFG
++ count 1
+ field WR_DFTHRSH 0x70 {
+ WR_DFTHRSH_MIN,
+ WR_DFTHRSH_25,
+@@ -800,6 +809,7 @@ register PCIXCTL {
+ address 0x093
+ access_mode RW
+ modes M_CFG
++ count 1
+ field SERRPULSE 0x80
+ field UNEXPSCIEN 0x20
+ field SPLTSMADIS 0x10
+@@ -844,6 +854,7 @@ register DCHSPLTSTAT0 {
+ address 0x096
+ access_mode RW
+ modes M_DFF0, M_DFF1
++ count 2
+ field STAETERM 0x80
+ field SCBCERR 0x40
+ field SCADERR 0x20
+@@ -895,6 +906,7 @@ register DCHSPLTSTAT1 {
+ address 0x097
+ access_mode RW
+ modes M_DFF0, M_DFF1
++ count 2
+ field RXDATABUCKET 0x01
+ }
+
+@@ -1048,6 +1060,7 @@ register SGSPLTSTAT0 {
+ address 0x09E
+ access_mode RW
+ modes M_DFF0, M_DFF1
++ count 2
+ field STAETERM 0x80
+ field SCBCERR 0x40
+ field SCADERR 0x20
+@@ -1065,6 +1078,7 @@ register SGSPLTSTAT1 {
+ address 0x09F
+ access_mode RW
+ modes M_DFF0, M_DFF1
++ count 2
+ field RXDATABUCKET 0x01
+ }
+
+@@ -1086,6 +1100,7 @@ register DF0PCISTAT {
+ address 0x0A0
+ access_mode RW
+ modes M_CFG
++ count 1
+ field DPE 0x80
+ field SSE 0x40
+ field RMA 0x20
+@@ -1184,6 +1199,7 @@ register TARGPCISTAT {
+ address 0x0A7
+ access_mode RW
+ modes M_CFG
++ count 5
+ field DPE 0x80
+ field SSE 0x40
+ field STA 0x08
+@@ -1198,6 +1214,7 @@ register LQIN {
+ address 0x020
+ access_mode RW
+ size 20
++ count 2
+ modes M_DFF0, M_DFF1, M_SCSI
+ }
+
+@@ -1229,6 +1246,7 @@ register LUNPTR {
+ address 0x022
+ access_mode RW
+ modes M_CFG
++ count 2
+ }
+
+ /*
+@@ -1259,6 +1277,7 @@ register CMDLENPTR {
+ address 0x025
+ access_mode RW
+ modes M_CFG
++ count 1
+ }
+
+ /*
+@@ -1270,6 +1289,7 @@ register ATTRPTR {
+ address 0x026
+ access_mode RW
+ modes M_CFG
++ count 1
+ }
+
+ /*
+@@ -1281,6 +1301,7 @@ register FLAGPTR {
+ address 0x027
+ access_mode RW
+ modes M_CFG
++ count 1
+ }
+
+ /*
+@@ -1291,6 +1312,7 @@ register CMDPTR {
+ address 0x028
+ access_mode RW
+ modes M_CFG
++ count 1
+ }
+
+ /*
+@@ -1301,6 +1323,7 @@ register QNEXTPTR {
+ address 0x029
+ access_mode RW
+ modes M_CFG
++ count 1
+ }
+
+ /*
+@@ -1323,6 +1346,7 @@ register ABRTBYTEPTR {
+ address 0x02B
+ access_mode RW
+ modes M_CFG
++ count 1
+ }
+
+ /*
+@@ -1333,6 +1357,7 @@ register ABRTBITPTR {
+ address 0x02C
+ access_mode RW
+ modes M_CFG
++ count 1
+ }
+
+ /*
+@@ -1370,6 +1395,7 @@ register LUNLEN {
+ address 0x030
+ access_mode RW
+ modes M_CFG
++ count 2
+ mask ILUNLEN 0x0F
+ mask TLUNLEN 0xF0
+ }
+@@ -1383,6 +1409,7 @@ register CDBLIMIT {
+ address 0x031
+ access_mode RW
+ modes M_CFG
++ count 1
+ }
+
+ /*
+@@ -1394,6 +1421,7 @@ register MAXCMD {
+ address 0x032
+ access_mode RW
+ modes M_CFG
++ count 9
+ }
+
+ /*
+@@ -1458,6 +1486,7 @@ register LQCTL1 {
+ address 0x038
+ access_mode RW
+ modes M_DFF0, M_DFF1, M_SCSI
++ count 2
+ field PCI2PCI 0x04
+ field SINGLECMD 0x02
+ field ABORTPENDING 0x01
+@@ -1470,6 +1499,7 @@ register LQCTL2 {
+ address 0x039
+ access_mode RW
+ modes M_DFF0, M_DFF1, M_SCSI
++ count 5
+ field LQIRETRY 0x80
+ field LQICONTINUE 0x40
+ field LQITOIDLE 0x20
+@@ -1528,6 +1558,7 @@ register SCSISEQ1 {
+ address 0x03B
+ access_mode RW
+ modes M_DFF0, M_DFF1, M_SCSI
++ count 8
+ field MANUALCTL 0x40
+ field ENSELI 0x20
+ field ENRSELI 0x10
+@@ -1667,6 +1698,9 @@ register SCSISIGO {
+ }
+ }
+
++/*
++ * SCSI Control Signal In
++ */
+ register SCSISIGI {
+ address 0x041
+ access_mode RO
+@@ -1703,6 +1737,7 @@ register MULTARGID {
+ access_mode RW
+ modes M_CFG
+ size 2
++ count 2
+ }
+
+ /*
+@@ -1758,6 +1793,7 @@ register TARGIDIN {
+ address 0x048
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
++ count 2
+ field CLKOUT 0x80
+ field TARGID 0x0F
+ }
+@@ -1798,6 +1834,7 @@ register OPTIONMODE {
+ address 0x04A
+ access_mode RW
+ modes M_CFG
++ count 4
+ field BIOSCANCTL 0x80
+ field AUTOACKEN 0x40
+ field BIASCANCTL 0x20
+@@ -1850,6 +1887,7 @@ register SIMODE0 {
+ address 0x04B
+ access_mode RW
+ modes M_CFG
++ count 8
+ field ENSELDO 0x40
+ field ENSELDI 0x20
+ field ENSELINGO 0x10
+@@ -1945,6 +1983,7 @@ register PERRDIAG {
+ address 0x04E
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
++ count 3
+ field HIZERO 0x80
+ field HIPERR 0x40
+ field PREVPHASE 0x20
+@@ -1962,6 +2001,7 @@ register LQISTATE {
+ address 0x04E
+ access_mode RO
+ modes M_CFG
++ count 6
+ }
+
+ /*
+@@ -1971,6 +2011,7 @@ register SOFFCNT {
+ address 0x04F
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
++ count 1
+ }
+
+ /*
+@@ -1980,6 +2021,7 @@ register LQOSTATE {
+ address 0x04F
+ access_mode RO
+ modes M_CFG
++ count 2
+ }
+
+ /*
+@@ -1989,6 +2031,7 @@ register LQISTAT0 {
+ address 0x050
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
++ count 2
+ field LQIATNQAS 0x20
+ field LQICRCT1 0x10
+ field LQICRCT2 0x08
+@@ -2004,6 +2047,7 @@ register CLRLQIINT0 {
+ address 0x050
+ access_mode WO
+ modes M_DFF0, M_DFF1, M_SCSI
++ count 1
+ field CLRLQIATNQAS 0x20
+ field CLRLQICRCT1 0x10
+ field CLRLQICRCT2 0x08
+@@ -2019,6 +2063,7 @@ register LQIMODE0 {
+ address 0x050
+ access_mode RW
+ modes M_CFG
++ count 3
+ field ENLQIATNQASK 0x20
+ field ENLQICRCT1 0x10
+ field ENLQICRCT2 0x08
+@@ -2034,6 +2079,7 @@ register LQISTAT1 {
+ address 0x051
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
++ count 3
+ field LQIPHASE_LQ 0x80
+ field LQIPHASE_NLQ 0x40
+ field LQIABORT 0x20
+@@ -2051,6 +2097,7 @@ register CLRLQIINT1 {
+ address 0x051
+ access_mode WO
+ modes M_DFF0, M_DFF1, M_SCSI
++ count 4
+ field CLRLQIPHASE_LQ 0x80
+ field CLRLQIPHASE_NLQ 0x40
+ field CLRLIQABORT 0x20
+@@ -2068,6 +2115,7 @@ register LQIMODE1 {
+ address 0x051
+ access_mode RW
+ modes M_CFG
++ count 4
+ field ENLQIPHASE_LQ 0x80 /* LQIPHASE1 */
+ field ENLQIPHASE_NLQ 0x40 /* LQIPHASE2 */
+ field ENLIQABORT 0x20
+@@ -2102,6 +2150,7 @@ register SSTAT3 {
+ address 0x053
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
++ count 3
+ field NTRAMPERR 0x02
+ field OSRAMPERR 0x01
+ }
+@@ -2113,6 +2162,7 @@ register CLRSINT3 {
+ address 0x053
+ access_mode WO
+ modes M_DFF0, M_DFF1, M_SCSI
++ count 3
+ field CLRNTRAMPERR 0x02
+ field CLROSRAMPERR 0x01
+ }
+@@ -2124,6 +2174,7 @@ register SIMODE3 {
+ address 0x053
+ access_mode RW
+ modes M_CFG
++ count 4
+ field ENNTRAMPERR 0x02
+ field ENOSRAMPERR 0x01
+ }
+@@ -2135,6 +2186,7 @@ register LQOSTAT0 {
+ address 0x054
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
++ count 2
+ field LQOTARGSCBPERR 0x10
+ field LQOSTOPT2 0x08
+ field LQOATNLQ 0x04
+@@ -2149,6 +2201,7 @@ register CLRLQOINT0 {
+ address 0x054
+ access_mode WO
+ modes M_DFF0, M_DFF1, M_SCSI
++ count 3
+ field CLRLQOTARGSCBPERR 0x10
+ field CLRLQOSTOPT2 0x08
+ field CLRLQOATNLQ 0x04
+@@ -2163,6 +2216,7 @@ register LQOMODE0 {
+ address 0x054
+ access_mode RW
+ modes M_CFG
++ count 4
+ field ENLQOTARGSCBPERR 0x10
+ field ENLQOSTOPT2 0x08
+ field ENLQOATNLQ 0x04
+@@ -2191,6 +2245,7 @@ register CLRLQOINT1 {
+ address 0x055
+ access_mode WO
+ modes M_DFF0, M_DFF1, M_SCSI
++ count 7
+ field CLRLQOINITSCBPERR 0x10
+ field CLRLQOSTOPI2 0x08
+ field CLRLQOBADQAS 0x04
+@@ -2205,6 +2260,7 @@ register LQOMODE1 {
+ address 0x055
+ access_mode RW
+ modes M_CFG
++ count 4
+ field ENLQOINITSCBPERR 0x10
+ field ENLQOSTOPI2 0x08
+ field ENLQOBADQAS 0x04
+@@ -2232,6 +2288,7 @@ register OS_SPACE_CNT {
+ address 0x056
+ access_mode RO
+ modes M_CFG
++ count 2
+ }
+
+ /*
+@@ -2286,13 +2343,19 @@ register NEXTSCB {
+ modes M_SCSI
+ }
+
+-/* Rev B only. */
++/*
++ * LQO SCSI Control
++ * (Rev B only.)
++ */
+ register LQOSCSCTL {
+ address 0x05A
+ access_mode RW
+ size 1
+ modes M_CFG
++ count 1
+ field LQOH2A_VERSION 0x80
++ field LQOBUSETDLY 0x40
++ field LQONOHOLDLACK 0x02
+ field LQONOCHKOVER 0x01
+ }
+
+@@ -2459,6 +2522,7 @@ register NEGPERIOD {
+ address 0x061
+ access_mode RW
+ modes M_SCSI
++ count 1
+ }
+
+ /*
+@@ -2478,6 +2542,7 @@ register NEGOFFSET {
+ address 0x062
+ access_mode RW
+ modes M_SCSI
++ count 1
+ }
+
+ /*
+@@ -2487,6 +2552,7 @@ register NEGPPROPTS {
+ address 0x063
+ access_mode RW
+ modes M_SCSI
++ count 1
+ field PPROPT_PACE 0x08
+ field PPROPT_QAS 0x04
+ field PPROPT_DT 0x02
+@@ -2516,12 +2582,19 @@ register ANNEXCOL {
+ address 0x065
+ access_mode RW
+ modes M_SCSI
++ count 7
+ }
+
++/*
++ * SCSI Check
++ * (Rev. B only)
++ */
+ register SCSCHKN {
+ address 0x066
+ access_mode RW
+ modes M_CFG
++ count 1
++ field BIDICHKDIS 0x80
+ field STSELSKIDDIS 0x40
+ field CURRFIFODEF 0x20
+ field WIDERESEN 0x10
+@@ -2561,6 +2634,7 @@ register ANNEXDAT {
+ address 0x066
+ access_mode RW
+ modes M_SCSI
++ count 3
+ }
+
+ /*
+@@ -2596,6 +2670,7 @@ register TOWNID {
+ address 0x069
+ access_mode RW
+ modes M_SCSI
++ count 2
+ }
+
+ /*
+@@ -2737,6 +2812,7 @@ register SCBAUTOPTR {
+ address 0x0AB
+ access_mode RW
+ modes M_CFG
++ count 1
+ field AUSCBPTR_EN 0x80
+ field SCBPTR_ADDR 0x38
+ field SCBPTR_OFF 0x07
+@@ -2881,6 +2957,7 @@ register BRDDAT {
+ address 0x0B8
+ access_mode RW
+ modes M_SCSI
++ count 2
+ }
+
+ /*
+@@ -2890,6 +2967,7 @@ register BRDCTL {
+ address 0x0B9
+ access_mode RW
+ modes M_SCSI
++ count 7
+ field FLXARBACK 0x80
+ field FLXARBREQ 0x40
+ field BRDADDR 0x38
+@@ -2905,6 +2983,7 @@ register SEEADR {
+ address 0x0BA
+ access_mode RW
+ modes M_SCSI
++ count 4
+ }
+
+ /*
+@@ -2915,6 +2994,7 @@ register SEEDAT {
+ access_mode RW
+ size 2
+ modes M_SCSI
++ count 4
+ }
+
+ /*
+@@ -2924,6 +3004,7 @@ register SEESTAT {
+ address 0x0BE
+ access_mode RO
+ modes M_SCSI
++ count 1
+ field INIT_DONE 0x80
+ field SEEOPCODE 0x70
+ field LDALTID_L 0x08
+@@ -2939,6 +3020,7 @@ register SEECTL {
+ address 0x0BE
+ access_mode RW
+ modes M_SCSI
++ count 4
+ field SEEOPCODE 0x70 {
+ SEEOP_ERASE 0x70,
+ SEEOP_READ 0x60,
+@@ -3000,6 +3082,7 @@ register DSPDATACTL {
+ address 0x0C1
+ access_mode RW
+ modes M_CFG
++ count 3
+ field BYPASSENAB 0x80
+ field DESQDIS 0x10
+ field RCVROFFSTDIS 0x04
+@@ -3058,6 +3141,7 @@ register DSPSELECT {
+ address 0x0C4
+ access_mode RW
+ modes M_CFG
++ count 1
+ field AUTOINCEN 0x80
+ field DSPSEL 0x1F
+ }
+@@ -3071,6 +3155,7 @@ register WRTBIASCTL {
+ address 0x0C5
+ access_mode WO
+ modes M_CFG
++ count 3
+ field AUTOXBCDIS 0x80
+ field XMITMANVAL 0x3F
+ }
+@@ -3196,7 +3281,8 @@ register OVLYADDR {
+ */
+ register SEQCTL0 {
+ address 0x0D6
+- access_mode RW
++ access_mode RW
++ count 11
+ field PERRORDIS 0x80
+ field PAUSEDIS 0x40
+ field FAILDIS 0x20
+@@ -3226,7 +3312,8 @@ register SEQCTL1 {
+ */
+ register FLAGS {
+ address 0x0D8
+- access_mode RO
++ access_mode RO
++ count 23
+ field ZERO 0x02
+ field CARRY 0x01
+ }
+@@ -3255,7 +3342,8 @@ register SEQINTCTL {
+ */
+ register SEQRAM {
+ address 0x0DA
+- access_mode RW
++ access_mode RW
++ count 2
+ }
+
+ /*
+@@ -3266,6 +3354,7 @@ register PRGMCNT {
+ address 0x0DE
+ access_mode RW
+ size 2
++ count 5
+ }
+
+ /*
+@@ -3273,7 +3362,7 @@ register PRGMCNT {
+ */
+ register ACCUM {
+ address 0x0E0
+- access_mode RW
++ access_mode RW
+ accumulator
+ }
+
+@@ -3401,6 +3490,7 @@ register INTVEC1_ADDR {
+ access_mode RW
+ size 2
+ modes M_CFG
++ count 1
+ }
+
+ /*
+@@ -3412,6 +3502,7 @@ register CURADDR {
+ access_mode RW
+ size 2
+ modes M_SCSI
++ count 2
+ }
+
+ /*
+@@ -3423,6 +3514,7 @@ register INTVEC2_ADDR {
+ access_mode RW
+ size 2
+ modes M_CFG
++ count 1
+ }
+
+ /*
+@@ -3579,6 +3671,7 @@ scratch_ram {
+ /* Parameters for DMA Logic */
+ DMAPARAMS {
+ size 1
++ count 8
+ field PRELOADEN 0x80
+ field WIDEODD 0x40
+ field SCSIEN 0x20
+@@ -3648,9 +3741,11 @@ scratch_ram {
+ */
+ KERNEL_TQINPOS {
+ size 1
++ count 1
+ }
+- TQINPOS {
++ TQINPOS {
+ size 1
++ count 8
+ }
+ /*
+ * Base address of our shared data with the kernel driver in host
+@@ -3681,6 +3776,7 @@ scratch_ram {
+ }
+ ARG_2 {
+ size 1
++ count 1
+ alias RETURN_2
+ }
+
+@@ -3698,6 +3794,7 @@ scratch_ram {
+ */
+ SCSISEQ_TEMPLATE {
+ size 1
++ count 7
+ field MANUALCTL 0x40
+ field ENSELI 0x20
+ field ENRSELI 0x10
+@@ -3711,6 +3808,7 @@ scratch_ram {
+ */
+ INITIATOR_TAG {
+ size 1
++ count 1
+ }
+
+ SEQ_FLAGS2 {
+@@ -3777,6 +3875,7 @@ scratch_ram {
+ */
+ CMDSIZE_TABLE {
+ size 8
++ count 8
+ }
+ /*
+ * When an SCB with the MK_MESSAGE flag is
+@@ -3803,8 +3902,8 @@ scratch_ram {
+ /************************* Hardware SCB Definition ****************************/
+ scb {
+ address 0x180
+- size 64
+- modes 0, 1, 2, 3
++ size 64
++ modes 0, 1, 2, 3
+ SCB_RESIDUAL_DATACNT {
+ size 4
+ alias SCB_CDB_STORE
+diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
+index ade0fb8..55508b0 100644
+--- a/drivers/scsi/aic7xxx/aic79xx_core.c
++++ b/drivers/scsi/aic7xxx/aic79xx_core.c
+@@ -52,7 +52,7 @@
+
+
+ /***************************** Lookup Tables **********************************/
+-static char *ahd_chip_names[] =
++static const char *const ahd_chip_names[] =
+ {
+ "NONE",
+ "aic7901",
+@@ -66,10 +66,10 @@ static const u_int num_chip_names = ARRAY_SIZE(ahd_chip_names);
+ */
+ struct ahd_hard_error_entry {
+ uint8_t errno;
+- char *errmesg;
++ const char *errmesg;
+ };
+
+-static struct ahd_hard_error_entry ahd_hard_errors[] = {
++static const struct ahd_hard_error_entry ahd_hard_errors[] = {
+ { DSCTMOUT, "Discard Timer has timed out" },
+ { ILLOPCODE, "Illegal Opcode in sequencer program" },
+ { SQPARERR, "Sequencer Parity Error" },
+@@ -79,7 +79,7 @@ static struct ahd_hard_error_entry ahd_hard_errors[] = {
+ };
+ static const u_int num_errors = ARRAY_SIZE(ahd_hard_errors);
+
+-static struct ahd_phase_table_entry ahd_phase_table[] =
++static const struct ahd_phase_table_entry ahd_phase_table[] =
+ {
+ { P_DATAOUT, MSG_NOOP, "in Data-out phase" },
+ { P_DATAIN, MSG_INITIATOR_DET_ERR, "in Data-in phase" },
+@@ -213,7 +213,7 @@ static void ahd_dumpseq(struct ahd_softc *ahd);
+ #endif
+ static void ahd_loadseq(struct ahd_softc *ahd);
+ static int ahd_check_patch(struct ahd_softc *ahd,
+- struct patch **start_patch,
++ const struct patch **start_patch,
+ u_int start_instr, u_int *skip_addr);
+ static u_int ahd_resolve_seqaddr(struct ahd_softc *ahd,
+ u_int address);
+@@ -254,7 +254,7 @@ static void ahd_freeze_devq(struct ahd_softc *ahd,
+ struct scb *scb);
+ static void ahd_handle_scb_status(struct ahd_softc *ahd,
+ struct scb *scb);
+-static struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase);
++static const struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase);
+ static void ahd_shutdown(void *arg);
+ static void ahd_update_coalescing_values(struct ahd_softc *ahd,
+ u_int timer,
+@@ -266,8 +266,774 @@ static int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb,
+ int target, char channel, int lun,
+ u_int tag, role_t role);
+
+-/******************************** Private Inlines *****************************/
++static void ahd_reset_cmds_pending(struct ahd_softc *ahd);
++
++/*************************** Interrupt Services *******************************/
++static void ahd_run_qoutfifo(struct ahd_softc *ahd);
++#ifdef AHD_TARGET_MODE
++static void ahd_run_tqinfifo(struct ahd_softc *ahd, int paused);
++#endif
++static void ahd_handle_hwerrint(struct ahd_softc *ahd);
++static void ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat);
++static void ahd_handle_scsiint(struct ahd_softc *ahd,
++ u_int intstat);
++
++/************************ Sequencer Execution Control *************************/
++void
++ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
++{
++ if (ahd->src_mode == src && ahd->dst_mode == dst)
++ return;
++#ifdef AHD_DEBUG
++ if (ahd->src_mode == AHD_MODE_UNKNOWN
++ || ahd->dst_mode == AHD_MODE_UNKNOWN)
++ panic("Setting mode prior to saving it.\n");
++ if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
++ printf("%s: Setting mode 0x%x\n", ahd_name(ahd),
++ ahd_build_mode_state(ahd, src, dst));
++#endif
++ ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst));
++ ahd->src_mode = src;
++ ahd->dst_mode = dst;
++}
++
++static void
++ahd_update_modes(struct ahd_softc *ahd)
++{
++ ahd_mode_state mode_ptr;
++ ahd_mode src;
++ ahd_mode dst;
++
++ mode_ptr = ahd_inb(ahd, MODE_PTR);
++#ifdef AHD_DEBUG
++ if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
++ printf("Reading mode 0x%x\n", mode_ptr);
++#endif
++ ahd_extract_mode_state(ahd, mode_ptr, &src, &dst);
++ ahd_known_modes(ahd, src, dst);
++}
++
++static void
++ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode,
++ ahd_mode dstmode, const char *file, int line)
++{
++#ifdef AHD_DEBUG
++ if ((srcmode & AHD_MK_MSK(ahd->src_mode)) == 0
++ || (dstmode & AHD_MK_MSK(ahd->dst_mode)) == 0) {
++ panic("%s:%s:%d: Mode assertion failed.\n",
++ ahd_name(ahd), file, line);
++ }
++#endif
++}
++
++#define AHD_ASSERT_MODES(ahd, source, dest) \
++ ahd_assert_modes(ahd, source, dest, __FILE__, __LINE__);
++
++ahd_mode_state
++ahd_save_modes(struct ahd_softc *ahd)
++{
++ if (ahd->src_mode == AHD_MODE_UNKNOWN
++ || ahd->dst_mode == AHD_MODE_UNKNOWN)
++ ahd_update_modes(ahd);
++
++ return (ahd_build_mode_state(ahd, ahd->src_mode, ahd->dst_mode));
++}
++
++void
++ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state)
++{
++ ahd_mode src;
++ ahd_mode dst;
++
++ ahd_extract_mode_state(ahd, state, &src, &dst);
++ ahd_set_modes(ahd, src, dst);
++}
++
++/*
++ * Determine whether the sequencer has halted code execution.
++ * Returns non-zero status if the sequencer is stopped.
++ */
++int
++ahd_is_paused(struct ahd_softc *ahd)
++{
++ return ((ahd_inb(ahd, HCNTRL) & PAUSE) != 0);
++}
++
++/*
++ * Request that the sequencer stop and wait, indefinitely, for it
++ * to stop. The sequencer will only acknowledge that it is paused
++ * once it has reached an instruction boundary and PAUSEDIS is
++ * cleared in the SEQCTL register. The sequencer may use PAUSEDIS
++ * for critical sections.
++ */
++void
++ahd_pause(struct ahd_softc *ahd)
++{
++ ahd_outb(ahd, HCNTRL, ahd->pause);
++
++ /*
++ * Since the sequencer can disable pausing in a critical section, we
++ * must loop until it actually stops.
++ */
++ while (ahd_is_paused(ahd) == 0)
++ ;
++}
++
++/*
++ * Allow the sequencer to continue program execution.
++ * We check here to ensure that no additional interrupt
++ * sources that would cause the sequencer to halt have been
++ * asserted. If, for example, a SCSI bus reset is detected
++ * while we are fielding a different, pausing, interrupt type,
++ * we don't want to release the sequencer before going back
++ * into our interrupt handler and dealing with this new
++ * condition.
++ */
++void
++ahd_unpause(struct ahd_softc *ahd)
++{
++ /*
++ * Automatically restore our modes to those saved
++ * prior to the first change of the mode.
++ */
++ if (ahd->saved_src_mode != AHD_MODE_UNKNOWN
++ && ahd->saved_dst_mode != AHD_MODE_UNKNOWN) {
++ if ((ahd->flags & AHD_UPDATE_PEND_CMDS) != 0)
++ ahd_reset_cmds_pending(ahd);
++ ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
++ }
++
++ if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0)
++ ahd_outb(ahd, HCNTRL, ahd->unpause);
++
++ ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN);
++}
++
++/*********************** Scatter Gather List Handling *************************/
++void *
++ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
++ void *sgptr, dma_addr_t addr, bus_size_t len, int last)
++{
++ scb->sg_count++;
++ if (sizeof(dma_addr_t) > 4
++ && (ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
++ struct ahd_dma64_seg *sg;
++
++ sg = (struct ahd_dma64_seg *)sgptr;
++ sg->addr = ahd_htole64(addr);
++ sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0));
++ return (sg + 1);
++ } else {
++ struct ahd_dma_seg *sg;
+
++ sg = (struct ahd_dma_seg *)sgptr;
++ sg->addr = ahd_htole32(addr & 0xFFFFFFFF);
++ sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000)
++ | (last ? AHD_DMA_LAST_SEG : 0));
++ return (sg + 1);
++ }
++}
++
++static void
++ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb)
++{
++ /* XXX Handle target mode SCBs. */
++ scb->crc_retry_count = 0;
++ if ((scb->flags & SCB_PACKETIZED) != 0) {
++ /* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */
++ scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE;
++ } else {
++ if (ahd_get_transfer_length(scb) & 0x01)
++ scb->hscb->task_attribute = SCB_XFERLEN_ODD;
++ else
++ scb->hscb->task_attribute = 0;
++ }
++
++ if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR
++ || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0)
++ scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr =
++ ahd_htole32(scb->sense_busaddr);
++}
++
++static void
++ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb)
++{
++ /*
++ * Copy the first SG into the "current" data ponter area.
++ */
++ if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
++ struct ahd_dma64_seg *sg;
++
++ sg = (struct ahd_dma64_seg *)scb->sg_list;
++ scb->hscb->dataptr = sg->addr;
++ scb->hscb->datacnt = sg->len;
++ } else {
++ struct ahd_dma_seg *sg;
++ uint32_t *dataptr_words;
++
++ sg = (struct ahd_dma_seg *)scb->sg_list;
++ dataptr_words = (uint32_t*)&scb->hscb->dataptr;
++ dataptr_words[0] = sg->addr;
++ dataptr_words[1] = 0;
++ if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) {
++ uint64_t high_addr;
++
++ high_addr = ahd_le32toh(sg->len) & 0x7F000000;
++ scb->hscb->dataptr |= ahd_htole64(high_addr << 8);
++ }
++ scb->hscb->datacnt = sg->len;
++ }
++ /*
++ * Note where to find the SG entries in bus space.
++ * We also set the full residual flag which the
++ * sequencer will clear as soon as a data transfer
++ * occurs.
++ */
++ scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID);
++}
++
++static void
++ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb)
++{
++ scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL);
++ scb->hscb->dataptr = 0;
++ scb->hscb->datacnt = 0;
++}
++
++/************************** Memory mapping routines ***************************/
++static void *
++ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr)
++{
++ dma_addr_t sg_offset;
++
++ /* sg_list_phys points to entry 1, not 0 */
++ sg_offset = sg_busaddr - (scb->sg_list_busaddr - ahd_sg_size(ahd));
++ return ((uint8_t *)scb->sg_list + sg_offset);
++}
++
++static uint32_t
++ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg)
++{
++ dma_addr_t sg_offset;
++
++ /* sg_list_phys points to entry 1, not 0 */
++ sg_offset = ((uint8_t *)sg - (uint8_t *)scb->sg_list)
++ - ahd_sg_size(ahd);
++
++ return (scb->sg_list_busaddr + sg_offset);
++}
++
++static void
++ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op)
++{
++ ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat,
++ scb->hscb_map->dmamap,
++ /*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr,
++ /*len*/sizeof(*scb->hscb), op);
++}
++
++void
++ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op)
++{
++ if (scb->sg_count == 0)
++ return;
++
++ ahd_dmamap_sync(ahd, ahd->scb_data.sg_dmat,
++ scb->sg_map->dmamap,
++ /*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd),
++ /*len*/ahd_sg_size(ahd) * scb->sg_count, op);
++}
++
++static void
++ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op)
++{
++ ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat,
++ scb->sense_map->dmamap,
++ /*offset*/scb->sense_busaddr,
++ /*len*/AHD_SENSE_BUFSIZE, op);
++}
++
++#ifdef AHD_TARGET_MODE
++static uint32_t
++ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index)
++{
++ return (((uint8_t *)&ahd->targetcmds[index])
++ - (uint8_t *)ahd->qoutfifo);
++}
++#endif
++
++/*********************** Miscelaneous Support Functions ***********************/
++/*
++ * Return pointers to the transfer negotiation information
++ * for the specified our_id/remote_id pair.
++ */
++struct ahd_initiator_tinfo *
++ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id,
++ u_int remote_id, struct ahd_tmode_tstate **tstate)
++{
++ /*
++ * Transfer data structures are stored from the perspective
++ * of the target role. Since the parameters for a connection
++ * in the initiator role to a given target are the same as
++ * when the roles are reversed, we pretend we are the target.
++ */
++ if (channel == 'B')
++ our_id += 8;
++ *tstate = ahd->enabled_targets[our_id];
++ return (&(*tstate)->transinfo[remote_id]);
++}
++
++uint16_t
++ahd_inw(struct ahd_softc *ahd, u_int port)
++{
++ /*
++ * Read high byte first as some registers increment
++ * or have other side effects when the low byte is
++ * read.
++ */
++ uint16_t r = ahd_inb(ahd, port+1) << 8;
++ return r | ahd_inb(ahd, port);
++}
++
++void
++ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)
++{
++ /*
++ * Write low byte first to accomodate registers
++ * such as PRGMCNT where the order maters.
++ */
++ ahd_outb(ahd, port, value & 0xFF);
++ ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
++}
++
++uint32_t
++ahd_inl(struct ahd_softc *ahd, u_int port)
++{
++ return ((ahd_inb(ahd, port))
++ | (ahd_inb(ahd, port+1) << 8)
++ | (ahd_inb(ahd, port+2) << 16)
++ | (ahd_inb(ahd, port+3) << 24));
++}
++
++void
++ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value)
++{
++ ahd_outb(ahd, port, (value) & 0xFF);
++ ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF);
++ ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF);
++ ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF);
++}
++
++uint64_t
++ahd_inq(struct ahd_softc *ahd, u_int port)
++{
++ return ((ahd_inb(ahd, port))
++ | (ahd_inb(ahd, port+1) << 8)
++ | (ahd_inb(ahd, port+2) << 16)
++ | (ahd_inb(ahd, port+3) << 24)
++ | (((uint64_t)ahd_inb(ahd, port+4)) << 32)
++ | (((uint64_t)ahd_inb(ahd, port+5)) << 40)
++ | (((uint64_t)ahd_inb(ahd, port+6)) << 48)
++ | (((uint64_t)ahd_inb(ahd, port+7)) << 56));
++}
++
++void
++ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value)
++{
++ ahd_outb(ahd, port, value & 0xFF);
++ ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
++ ahd_outb(ahd, port+2, (value >> 16) & 0xFF);
++ ahd_outb(ahd, port+3, (value >> 24) & 0xFF);
++ ahd_outb(ahd, port+4, (value >> 32) & 0xFF);
++ ahd_outb(ahd, port+5, (value >> 40) & 0xFF);
++ ahd_outb(ahd, port+6, (value >> 48) & 0xFF);
++ ahd_outb(ahd, port+7, (value >> 56) & 0xFF);
++}
++
++u_int
++ahd_get_scbptr(struct ahd_softc *ahd)
++{
++ AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
++ ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
++ return (ahd_inb(ahd, SCBPTR) | (ahd_inb(ahd, SCBPTR + 1) << 8));
++}
++
++void
++ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr)
++{
++ AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
++ ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
++ ahd_outb(ahd, SCBPTR, scbptr & 0xFF);
++ ahd_outb(ahd, SCBPTR+1, (scbptr >> 8) & 0xFF);
++}
++
++#if 0 /* unused */
++static u_int
++ahd_get_hnscb_qoff(struct ahd_softc *ahd)
++{
++ return (ahd_inw_atomic(ahd, HNSCB_QOFF));
++}
++#endif
++
++static void
++ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value)
++{
++ ahd_outw_atomic(ahd, HNSCB_QOFF, value);
++}
++
++#if 0 /* unused */
++static u_int
++ahd_get_hescb_qoff(struct ahd_softc *ahd)
++{
++ return (ahd_inb(ahd, HESCB_QOFF));
++}
++#endif
++
++static void
++ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value)
++{
++ ahd_outb(ahd, HESCB_QOFF, value);
++}
++
++static u_int
++ahd_get_snscb_qoff(struct ahd_softc *ahd)
++{
++ u_int oldvalue;
++
++ AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
++ oldvalue = ahd_inw(ahd, SNSCB_QOFF);
++ ahd_outw(ahd, SNSCB_QOFF, oldvalue);
++ return (oldvalue);
++}
++
++static void
++ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value)
++{
++ AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
++ ahd_outw(ahd, SNSCB_QOFF, value);
++}
++
++#if 0 /* unused */
++static u_int
++ahd_get_sescb_qoff(struct ahd_softc *ahd)
++{
++ AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
++ return (ahd_inb(ahd, SESCB_QOFF));
++}
++#endif
++
++static void
++ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value)
++{
++ AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
++ ahd_outb(ahd, SESCB_QOFF, value);
++}
++
++#if 0 /* unused */
++static u_int
++ahd_get_sdscb_qoff(struct ahd_softc *ahd)
++{
++ AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
++ return (ahd_inb(ahd, SDSCB_QOFF) | (ahd_inb(ahd, SDSCB_QOFF + 1) << 8));
++}
++#endif
++
++static void
++ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value)
++{
++ AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
++ ahd_outb(ahd, SDSCB_QOFF, value & 0xFF);
++ ahd_outb(ahd, SDSCB_QOFF+1, (value >> 8) & 0xFF);
++}
++
++u_int
++ahd_inb_scbram(struct ahd_softc *ahd, u_int offset)
++{
++ u_int value;
++
++ /*
++ * Workaround PCI-X Rev A. hardware bug.
++ * After a host read of SCB memory, the chip
++ * may become confused into thinking prefetch
++ * was required. This starts the discard timer
++ * running and can cause an unexpected discard
++ * timer interrupt. The work around is to read
++ * a normal register prior to the exhaustion of
++ * the discard timer. The mode pointer register
++ * has no side effects and so serves well for
++ * this purpose.
++ *
++ * Razor #528
++ */
++ value = ahd_inb(ahd, offset);
++ if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0)
++ ahd_inb(ahd, MODE_PTR);
++ return (value);
++}
++
++u_int
++ahd_inw_scbram(struct ahd_softc *ahd, u_int offset)
++{
++ return (ahd_inb_scbram(ahd, offset)
++ | (ahd_inb_scbram(ahd, offset+1) << 8));
++}
++
++static uint32_t
++ahd_inl_scbram(struct ahd_softc *ahd, u_int offset)
++{
++ return (ahd_inw_scbram(ahd, offset)
++ | (ahd_inw_scbram(ahd, offset+2) << 16));
++}
++
++static uint64_t
++ahd_inq_scbram(struct ahd_softc *ahd, u_int offset)
++{
++ return (ahd_inl_scbram(ahd, offset)
++ | ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32);
++}
++
++struct scb *
++ahd_lookup_scb(struct ahd_softc *ahd, u_int tag)
++{
++ struct scb* scb;
++
++ if (tag >= AHD_SCB_MAX)
++ return (NULL);
++ scb = ahd->scb_data.scbindex[tag];
++ if (scb != NULL)
++ ahd_sync_scb(ahd, scb,
++ BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
++ return (scb);
++}
++
++static void
++ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
++{
++ struct hardware_scb *q_hscb;
++ struct map_node *q_hscb_map;
++ uint32_t saved_hscb_busaddr;
++
++ /*
++ * Our queuing method is a bit tricky. The card
++ * knows in advance which HSCB (by address) to download,
++ * and we can't disappoint it. To achieve this, the next
++ * HSCB to download is saved off in ahd->next_queued_hscb.
++ * When we are called to queue "an arbitrary scb",
++ * we copy the contents of the incoming HSCB to the one
++ * the sequencer knows about, swap HSCB pointers and
++ * finally assign the SCB to the tag indexed location
++ * in the scb_array. This makes sure that we can still
++ * locate the correct SCB by SCB_TAG.
++ */
++ q_hscb = ahd->next_queued_hscb;
++ q_hscb_map = ahd->next_queued_hscb_map;
++ saved_hscb_busaddr = q_hscb->hscb_busaddr;
++ memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
++ q_hscb->hscb_busaddr = saved_hscb_busaddr;
++ q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
++
++ /* Now swap HSCB pointers. */
++ ahd->next_queued_hscb = scb->hscb;
++ ahd->next_queued_hscb_map = scb->hscb_map;
++ scb->hscb = q_hscb;
++ scb->hscb_map = q_hscb_map;
++
++ /* Now define the mapping from tag to SCB in the scbindex */
++ ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
++}
++
++/*
++ * Tell the sequencer about a new transaction to execute.
++ */
++void
++ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb)
++{
++ ahd_swap_with_next_hscb(ahd, scb);
++
++ if (SCBID_IS_NULL(SCB_GET_TAG(scb)))
++ panic("Attempt to queue invalid SCB tag %x\n",
++ SCB_GET_TAG(scb));
++
++ /*
++ * Keep a history of SCBs we've downloaded in the qinfifo.
++ */
++ ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb);
++ ahd->qinfifonext++;
++
++ if (scb->sg_count != 0)
++ ahd_setup_data_scb(ahd, scb);
++ else
++ ahd_setup_noxfer_scb(ahd, scb);
++ ahd_setup_scb_common(ahd, scb);
++
++ /*
++ * Make sure our data is consistent from the
++ * perspective of the adapter.
++ */
++ ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
++
++#ifdef AHD_DEBUG
++ if ((ahd_debug & AHD_SHOW_QUEUE) != 0) {
++ uint64_t host_dataptr;
++
++ host_dataptr = ahd_le64toh(scb->hscb->dataptr);
++ printf("%s: Queueing SCB %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
++ ahd_name(ahd),
++ SCB_GET_TAG(scb), scb->hscb->scsiid,
++ ahd_le32toh(scb->hscb->hscb_busaddr),
++ (u_int)((host_dataptr >> 32) & 0xFFFFFFFF),
++ (u_int)(host_dataptr & 0xFFFFFFFF),
++ ahd_le32toh(scb->hscb->datacnt));
++ }
++#endif
++ /* Tell the adapter about the newly queued SCB */
++ ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
++}
++
++/************************** Interrupt Processing ******************************/
++static void
++ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
++{
++ ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
++ /*offset*/0,
++ /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op);
++}
++
++static void
++ahd_sync_tqinfifo(struct ahd_softc *ahd, int op)
++{
++#ifdef AHD_TARGET_MODE
++ if ((ahd->flags & AHD_TARGETROLE) != 0) {
++ ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
++ ahd->shared_data_map.dmamap,
++ ahd_targetcmd_offset(ahd, 0),
++ sizeof(struct target_cmd) * AHD_TMODE_CMDS,
++ op);
++ }
++#endif
++}
++
++/*
++ * See if the firmware has posted any completed commands
++ * into our in-core command complete fifos.
++ */
++#define AHD_RUN_QOUTFIFO 0x1
++#define AHD_RUN_TQINFIFO 0x2
++static u_int
++ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
++{
++ u_int retval;
++
++ retval = 0;
++ ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
++ /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),
++ /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD);
++ if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag
++ == ahd->qoutfifonext_valid_tag)
++ retval |= AHD_RUN_QOUTFIFO;
++#ifdef AHD_TARGET_MODE
++ if ((ahd->flags & AHD_TARGETROLE) != 0
++ && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {
++ ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
++ ahd->shared_data_map.dmamap,
++ ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),
++ /*len*/sizeof(struct target_cmd),
++ BUS_DMASYNC_POSTREAD);
++ if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0)
++ retval |= AHD_RUN_TQINFIFO;
++ }
++#endif
++ return (retval);
++}
++
++/*
++ * Catch an interrupt from the adapter
++ */
++int
++ahd_intr(struct ahd_softc *ahd)
++{
++ u_int intstat;
++
++ if ((ahd->pause & INTEN) == 0) {
++ /*
++ * Our interrupt is not enabled on the chip
++ * and may be disabled for re-entrancy reasons,
++ * so just return. This is likely just a shared
++ * interrupt.
++ */
++ return (0);
++ }
++
++ /*
++ * Instead of directly reading the interrupt status register,
++ * infer the cause of the interrupt by checking our in-core
++ * completion queues. This avoids a costly PCI bus read in
++ * most cases.
++ */
++ if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0
++ && (ahd_check_cmdcmpltqueues(ahd) != 0))
++ intstat = CMDCMPLT;
++ else
++ intstat = ahd_inb(ahd, INTSTAT);
++
++ if ((intstat & INT_PEND) == 0)
++ return (0);
++
++ if (intstat & CMDCMPLT) {
++ ahd_outb(ahd, CLRINT, CLRCMDINT);
++
++ /*
++ * Ensure that the chip sees that we've cleared
++ * this interrupt before we walk the output fifo.
++ * Otherwise, we may, due to posted bus writes,
++ * clear the interrupt after we finish the scan,
++ * and after the sequencer has added new entries
++ * and asserted the interrupt again.
++ */
++ if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
++ if (ahd_is_paused(ahd)) {
++ /*
++ * Potentially lost SEQINT.
++ * If SEQINTCODE is non-zero,
++ * simulate the SEQINT.
++ */
++ if (ahd_inb(ahd, SEQINTCODE) != NO_SEQINT)
++ intstat |= SEQINT;
++ }
++ } else {
++ ahd_flush_device_writes(ahd);
++ }
++ ahd_run_qoutfifo(ahd);
++ ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]++;
++ ahd->cmdcmplt_total++;
++#ifdef AHD_TARGET_MODE
++ if ((ahd->flags & AHD_TARGETROLE) != 0)
++ ahd_run_tqinfifo(ahd, /*paused*/FALSE);
++#endif
++ }
++
++ /*
++ * Handle statuses that may invalidate our cached
++ * copy of INTSTAT separately.
++ */
++ if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) {
++ /* Hot eject. Do nothing */
++ } else if (intstat & HWERRINT) {
++ ahd_handle_hwerrint(ahd);
++ } else if ((intstat & (PCIINT|SPLTINT)) != 0) {
++ ahd->bus_intr(ahd);
++ } else {
++
++ if ((intstat & SEQINT) != 0)
++ ahd_handle_seqint(ahd, intstat);
++
++ if ((intstat & SCSIINT) != 0)
++ ahd_handle_scsiint(ahd, intstat);
++ }
++ return (1);
++}
++
++/******************************** Private Inlines *****************************/
+ static __inline void
+ ahd_assert_atn(struct ahd_softc *ahd)
+ {
+@@ -280,7 +1046,7 @@ ahd_assert_atn(struct ahd_softc *ahd)
+ * are currently in a packetized transfer. We could
+ * just as easily be sending or receiving a message.
+ */
+-static __inline int
++static int
+ ahd_currently_packetized(struct ahd_softc *ahd)
+ {
+ ahd_mode_state saved_modes;
+@@ -896,7 +1662,7 @@ clrchn:
+ * a copy of the first byte (little endian) of the sgptr
+ * hscb field.
+ */
+-void
++static void
+ ahd_run_qoutfifo(struct ahd_softc *ahd)
+ {
+ struct ahd_completion *completion;
+@@ -935,7 +1701,7 @@ ahd_run_qoutfifo(struct ahd_softc *ahd)
+ }
+
+ /************************* Interrupt Handling *********************************/
+-void
++static void
+ ahd_handle_hwerrint(struct ahd_softc *ahd)
+ {
+ /*
+@@ -1009,7 +1775,7 @@ ahd_dump_sglist(struct scb *scb)
+ }
+ #endif /* AHD_DEBUG */
+
+-void
++static void
+ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
+ {
+ u_int seqintcode;
+@@ -1621,7 +2387,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
+ ahd_unpause(ahd);
+ }
+
+-void
++static void
+ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
+ {
+ struct scb *scb;
+@@ -3571,11 +4337,11 @@ ahd_print_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
+ devinfo->target, devinfo->lun);
+ }
+
+-static struct ahd_phase_table_entry*
++static const struct ahd_phase_table_entry*
+ ahd_lookup_phase_entry(int phase)
+ {
+- struct ahd_phase_table_entry *entry;
+- struct ahd_phase_table_entry *last_entry;
++ const struct ahd_phase_table_entry *entry;
++ const struct ahd_phase_table_entry *last_entry;
+
+ /*
+ * num_phases doesn't include the default entry which
+@@ -3941,7 +4707,7 @@ ahd_clear_msg_state(struct ahd_softc *ahd)
+ */
+ static void
+ ahd_handle_message_phase(struct ahd_softc *ahd)
+-{
++{
+ struct ahd_devinfo devinfo;
+ u_int bus_phase;
+ int end_session;
+@@ -5983,8 +6749,7 @@ found:
+ */
+ void
+ ahd_free_scb(struct ahd_softc *ahd, struct scb *scb)
+-{
-
--int
--qeth_setrouting_v6(struct qeth_card *card)
++{
+ /* Clean up for the next user */
+ scb->flags = SCB_FLAG_NONE;
+ scb->hscb->control = 0;
+@@ -6272,6 +7037,24 @@ static const char *termstat_strings[] = {
+ "Not Configured"
+ };
+
++/***************************** Timer Facilities *******************************/
++#define ahd_timer_init init_timer
++#define ahd_timer_stop del_timer_sync
++typedef void ahd_linux_callback_t (u_long);
++
++static void
++ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
++{
++ struct ahd_softc *ahd;
++
++ ahd = (struct ahd_softc *)arg;
++ del_timer(timer);
++ timer->data = (u_long)arg;
++ timer->expires = jiffies + (usec * HZ)/1000000;
++ timer->function = (ahd_linux_callback_t*)func;
++ add_timer(timer);
++}
++
+ /*
+ * Start the board, ready for normal operation
+ */
+@@ -7370,7 +8153,7 @@ ahd_qinfifo_count(struct ahd_softc *ahd)
+ + ARRAY_SIZE(ahd->qinfifo) - wrap_qinpos);
+ }
+
+-void
++static void
+ ahd_reset_cmds_pending(struct ahd_softc *ahd)
+ {
+ struct scb *scb;
+@@ -8571,7 +9354,7 @@ ahd_loadseq(struct ahd_softc *ahd)
+ struct cs cs_table[num_critical_sections];
+ u_int begin_set[num_critical_sections];
+ u_int end_set[num_critical_sections];
+- struct patch *cur_patch;
++ const struct patch *cur_patch;
+ u_int cs_count;
+ u_int cur_cs;
+ u_int i;
+@@ -8726,11 +9509,11 @@ ahd_loadseq(struct ahd_softc *ahd)
+ }
+
+ static int
+-ahd_check_patch(struct ahd_softc *ahd, struct patch **start_patch,
++ahd_check_patch(struct ahd_softc *ahd, const struct patch **start_patch,
+ u_int start_instr, u_int *skip_addr)
+ {
+- struct patch *cur_patch;
+- struct patch *last_patch;
++ const struct patch *cur_patch;
++ const struct patch *last_patch;
+ u_int num_patches;
+
+ num_patches = ARRAY_SIZE(patches);
+@@ -8764,7 +9547,7 @@ ahd_check_patch(struct ahd_softc *ahd, struct patch **start_patch,
+ static u_int
+ ahd_resolve_seqaddr(struct ahd_softc *ahd, u_int address)
+ {
+- struct patch *cur_patch;
++ const struct patch *cur_patch;
+ int address_offset;
+ u_int skip_addr;
+ u_int i;
+@@ -8895,7 +9678,7 @@ sized:
+ }
+
+ int
+-ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries,
++ahd_print_register(const ahd_reg_parse_entry_t *table, u_int num_entries,
+ const char *name, u_int address, u_int value,
+ u_int *cur_column, u_int wrap_point)
+ {
+@@ -9886,7 +10669,7 @@ ahd_update_scsiid(struct ahd_softc *ahd, u_int targid_mask)
+ #endif
+ }
+
+-void
++static void
+ ahd_run_tqinfifo(struct ahd_softc *ahd, int paused)
+ {
+ struct target_cmd *cmd;
+diff --git a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h
+index 45e5557..5f12cf9 100644
+--- a/drivers/scsi/aic7xxx/aic79xx_inline.h
++++ b/drivers/scsi/aic7xxx/aic79xx_inline.h
+@@ -63,18 +63,15 @@ static __inline ahd_mode_state ahd_build_mode_state(struct ahd_softc *ahd,
+ static __inline void ahd_extract_mode_state(struct ahd_softc *ahd,
+ ahd_mode_state state,
+ ahd_mode *src, ahd_mode *dst);
+-static __inline void ahd_set_modes(struct ahd_softc *ahd, ahd_mode src,
+- ahd_mode dst);
+-static __inline void ahd_update_modes(struct ahd_softc *ahd);
+-static __inline void ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode,
+- ahd_mode dstmode, const char *file,
+- int line);
+-static __inline ahd_mode_state ahd_save_modes(struct ahd_softc *ahd);
+-static __inline void ahd_restore_modes(struct ahd_softc *ahd,
+- ahd_mode_state state);
+-static __inline int ahd_is_paused(struct ahd_softc *ahd);
+-static __inline void ahd_pause(struct ahd_softc *ahd);
+-static __inline void ahd_unpause(struct ahd_softc *ahd);
++
++void ahd_set_modes(struct ahd_softc *ahd, ahd_mode src,
++ ahd_mode dst);
++ahd_mode_state ahd_save_modes(struct ahd_softc *ahd);
++void ahd_restore_modes(struct ahd_softc *ahd,
++ ahd_mode_state state);
++int ahd_is_paused(struct ahd_softc *ahd);
++void ahd_pause(struct ahd_softc *ahd);
++void ahd_unpause(struct ahd_softc *ahd);
+
+ static __inline void
+ ahd_known_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
+@@ -99,256 +96,16 @@ ahd_extract_mode_state(struct ahd_softc *ahd, ahd_mode_state state,
+ *dst = (state & DST_MODE) >> DST_MODE_SHIFT;
+ }
+
+-static __inline void
+-ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
-{
-- 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));
-- }
+- if (ahd->src_mode == src && ahd->dst_mode == dst)
+- return;
+-#ifdef AHD_DEBUG
+- if (ahd->src_mode == AHD_MODE_UNKNOWN
+- || ahd->dst_mode == AHD_MODE_UNKNOWN)
+- panic("Setting mode prior to saving it.\n");
+- if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
+- printf("%s: Setting mode 0x%x\n", ahd_name(ahd),
+- ahd_build_mode_state(ahd, src, dst));
-#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;
+- ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst));
+- ahd->src_mode = src;
+- ahd->dst_mode = dst;
-}
-
--/*
-- * softsetup card: init IPA stuff
-- */
--static int
--qeth_softsetup_card(struct qeth_card *card)
+-static __inline void
+-ahd_update_modes(struct ahd_softc *ahd)
-{
-- int rc;
--
-- QETH_DBF_TEXT(setup, 2, "softsetp");
+- ahd_mode_state mode_ptr;
+- ahd_mode src;
+- ahd_mode dst;
-
-- 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);
+- mode_ptr = ahd_inb(ahd, MODE_PTR);
+-#ifdef AHD_DEBUG
+- if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
+- printf("Reading mode 0x%x\n", mode_ptr);
-#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;
+- ahd_extract_mode_state(ahd, mode_ptr, &src, &dst);
+- ahd_known_modes(ahd, src, dst);
-}
-
--#ifdef CONFIG_QETH_IPV6
--static int
--qeth_get_unique_id_cb(struct qeth_card *card, struct qeth_reply *reply,
-- unsigned long data)
+-static __inline void
+-ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode,
+- ahd_mode dstmode, const char *file, int line)
-{
-- 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);
+-#ifdef AHD_DEBUG
+- if ((srcmode & AHD_MK_MSK(ahd->src_mode)) == 0
+- || (dstmode & AHD_MK_MSK(ahd->dst_mode)) == 0) {
+- panic("%s:%s:%d: Mode assertion failed.\n",
+- ahd_name(ahd), file, line);
- }
-- 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)
+-static __inline ahd_mode_state
+-ahd_save_modes(struct ahd_softc *ahd)
-{
-- unsigned long flags;
+- if (ahd->src_mode == AHD_MODE_UNKNOWN
+- || ahd->dst_mode == AHD_MODE_UNKNOWN)
+- ahd_update_modes(ahd);
-
-- 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);
+- return (ahd_build_mode_state(ahd, ahd->src_mode, ahd->dst_mode));
-}
-
--static int
--qeth_threads_running(struct qeth_card *card, unsigned long threads)
+-static __inline void
+-ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state)
-{
-- unsigned long flags;
-- int rc = 0;
+- ahd_mode src;
+- ahd_mode dst;
-
-- spin_lock_irqsave(&card->thread_mask_lock, flags);
-- rc = (card->thread_running_mask & threads);
-- spin_unlock_irqrestore(&card->thread_mask_lock, flags);
-- return rc;
+- ahd_extract_mode_state(ahd, state, &src, &dst);
+- ahd_set_modes(ahd, src, dst);
-}
-
--static int
--qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
+-#define AHD_ASSERT_MODES(ahd, source, dest) \
+- ahd_assert_modes(ahd, source, dest, __FILE__, __LINE__);
+-
+-/*
+- * Determine whether the sequencer has halted code execution.
+- * Returns non-zero status if the sequencer is stopped.
+- */
+-static __inline int
+-ahd_is_paused(struct ahd_softc *ahd)
-{
-- return wait_event_interruptible(card->wait_q,
-- qeth_threads_running(card, threads) == 0);
+- return ((ahd_inb(ahd, HCNTRL) & PAUSE) != 0);
-}
-
--static int
--qeth_stop_card(struct qeth_card *card, int recovery_mode)
+-/*
+- * Request that the sequencer stop and wait, indefinitely, for it
+- * to stop. The sequencer will only acknowledge that it is paused
+- * once it has reached an instruction boundary and PAUSEDIS is
+- * cleared in the SEQCTL register. The sequencer may use PAUSEDIS
+- * for critical sections.
+- */
+-static __inline void
+-ahd_pause(struct ahd_softc *ahd)
-{
-- int rc = 0;
+- ahd_outb(ahd, HCNTRL, ahd->pause);
-
-- QETH_DBF_TEXT(setup ,2,"stopcard");
-- QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+- /*
+- * Since the sequencer can disable pausing in a critical section, we
+- * must loop until it actually stops.
+- */
+- while (ahd_is_paused(ahd) == 0)
+- ;
+-}
-
-- 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);
+-/*
+- * Allow the sequencer to continue program execution.
+- * We check here to ensure that no additional interrupt
+- * sources that would cause the sequencer to halt have been
+- * asserted. If, for example, a SCSI bus reset is detected
+- * while we are fielding a different, pausing, interrupt type,
+- * we don't want to release the sequencer before going back
+- * into our interrupt handler and dealing with this new
+- * condition.
+- */
+-static __inline void
+-ahd_unpause(struct ahd_softc *ahd)
+-{
+- /*
+- * Automatically restore our modes to those saved
+- * prior to the first change of the mode.
+- */
+- if (ahd->saved_src_mode != AHD_MODE_UNKNOWN
+- && ahd->saved_dst_mode != AHD_MODE_UNKNOWN) {
+- if ((ahd->flags & AHD_UPDATE_PEND_CMDS) != 0)
+- ahd_reset_cmds_pending(ahd);
+- ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
+- }
+-
+- if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0)
+- ahd_outb(ahd, HCNTRL, ahd->unpause);
+-
+- ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN);
+-}
+-
+ /*********************** Scatter Gather List Handling *************************/
+-static __inline void *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
+- void *sgptr, dma_addr_t addr,
+- bus_size_t len, int last);
+-static __inline void ahd_setup_scb_common(struct ahd_softc *ahd,
+- struct scb *scb);
+-static __inline void ahd_setup_data_scb(struct ahd_softc *ahd,
+- struct scb *scb);
+-static __inline void ahd_setup_noxfer_scb(struct ahd_softc *ahd,
+- struct scb *scb);
+-
+-static __inline void *
+-ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
+- void *sgptr, dma_addr_t addr, bus_size_t len, int last)
+-{
+- scb->sg_count++;
+- if (sizeof(dma_addr_t) > 4
+- && (ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
+- struct ahd_dma64_seg *sg;
+-
+- sg = (struct ahd_dma64_seg *)sgptr;
+- sg->addr = ahd_htole64(addr);
+- sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0));
+- return (sg + 1);
+- } else {
+- struct ahd_dma_seg *sg;
+-
+- sg = (struct ahd_dma_seg *)sgptr;
+- sg->addr = ahd_htole32(addr & 0xFFFFFFFF);
+- sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000)
+- | (last ? AHD_DMA_LAST_SEG : 0));
+- return (sg + 1);
- }
-- card->use_hard_stop = 0;
-- return rc;
-}
-
+-static __inline void
+-ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb)
+-{
+- /* XXX Handle target mode SCBs. */
+- scb->crc_retry_count = 0;
+- if ((scb->flags & SCB_PACKETIZED) != 0) {
+- /* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */
+- scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE;
+- } else {
+- if (ahd_get_transfer_length(scb) & 0x01)
+- scb->hscb->task_attribute = SCB_XFERLEN_ODD;
+- else
+- scb->hscb->task_attribute = 0;
+- }
-
--static int
--qeth_get_unique_id(struct qeth_card *card)
+- if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR
+- || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0)
+- scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr =
+- ahd_htole32(scb->sense_busaddr);
+-}
+-
+-static __inline void
+-ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb)
-{
-- int rc = 0;
--#ifdef CONFIG_QETH_IPV6
-- struct qeth_cmd_buffer *iob;
-- struct qeth_ipa_cmd *cmd;
+- /*
+- * Copy the first SG into the "current" data ponter area.
+- */
+- if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
+- struct ahd_dma64_seg *sg;
-
-- QETH_DBF_TEXT(setup, 2, "guniqeid");
+- sg = (struct ahd_dma64_seg *)scb->sg_list;
+- scb->hscb->dataptr = sg->addr;
+- scb->hscb->datacnt = sg->len;
+- } else {
+- struct ahd_dma_seg *sg;
+- uint32_t *dataptr_words;
-
-- if (!qeth_is_supported(card,IPA_IPV6)) {
-- card->info.unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED |
-- UNIQUE_ID_NOT_BY_CARD;
-- return 0;
+- sg = (struct ahd_dma_seg *)scb->sg_list;
+- dataptr_words = (uint32_t*)&scb->hscb->dataptr;
+- dataptr_words[0] = sg->addr;
+- dataptr_words[1] = 0;
+- if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) {
+- uint64_t high_addr;
+-
+- high_addr = ahd_le32toh(sg->len) & 0x7F000000;
+- scb->hscb->dataptr |= ahd_htole64(high_addr << 8);
+- }
+- scb->hscb->datacnt = sg->len;
- }
+- /*
+- * Note where to find the SG entries in bus space.
+- * We also set the full residual flag which the
+- * sequencer will clear as soon as a data transfer
+- * occurs.
+- */
+- scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID);
+-}
-
-- 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;
+-static __inline void
+-ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb)
+-{
+- scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL);
+- scb->hscb->dataptr = 0;
+- scb->hscb->datacnt = 0;
+-}
++void *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
++ void *sgptr, dma_addr_t addr,
++ bus_size_t len, int last);
+
+ /************************** Memory mapping routines ***************************/
+ static __inline size_t ahd_sg_size(struct ahd_softc *ahd);
+-static __inline void *
+- ahd_sg_bus_to_virt(struct ahd_softc *ahd,
+- struct scb *scb,
+- uint32_t sg_busaddr);
+-static __inline uint32_t
+- ahd_sg_virt_to_bus(struct ahd_softc *ahd,
+- struct scb *scb,
+- void *sg);
+-static __inline void ahd_sync_scb(struct ahd_softc *ahd,
+- struct scb *scb, int op);
+-static __inline void ahd_sync_sglist(struct ahd_softc *ahd,
+- struct scb *scb, int op);
+-static __inline void ahd_sync_sense(struct ahd_softc *ahd,
+- struct scb *scb, int op);
+-static __inline uint32_t
+- ahd_targetcmd_offset(struct ahd_softc *ahd,
+- u_int index);
++
++void ahd_sync_sglist(struct ahd_softc *ahd,
++ struct scb *scb, int op);
+
+ static __inline size_t
+ ahd_sg_size(struct ahd_softc *ahd)
+@@ -358,104 +115,32 @@ ahd_sg_size(struct ahd_softc *ahd)
+ return (sizeof(struct ahd_dma_seg));
+ }
+
+-static __inline void *
+-ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr)
+-{
+- dma_addr_t sg_offset;
-
-- 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;
+- /* sg_list_phys points to entry 1, not 0 */
+- sg_offset = sg_busaddr - (scb->sg_list_busaddr - ahd_sg_size(ahd));
+- return ((uint8_t *)scb->sg_list + sg_offset);
-}
--static void
--qeth_print_status_with_portname(struct qeth_card *card)
+-
+-static __inline uint32_t
+-ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg)
-{
-- char dbf_text[15];
-- int i;
+- dma_addr_t sg_offset;
-
-- 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);
+- /* sg_list_phys points to entry 1, not 0 */
+- sg_offset = ((uint8_t *)sg - (uint8_t *)scb->sg_list)
+- - ahd_sg_size(ahd);
-
+- return (scb->sg_list_busaddr + sg_offset);
-}
-
--static void
--qeth_print_status_no_portname(struct qeth_card *card)
+-static __inline void
+-ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op)
-{
-- 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));
+- ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat,
+- scb->hscb_map->dmamap,
+- /*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr,
+- /*len*/sizeof(*scb->hscb), op);
-}
-
--static void
--qeth_print_status_message(struct qeth_card *card)
+-static __inline void
+-ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op)
-{
-- 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]);
+- if (scb->sg_count == 0)
+- return;
-
-- 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);
+- ahd_dmamap_sync(ahd, ahd->scb_data.sg_dmat,
+- scb->sg_map->dmamap,
+- /*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd),
+- /*len*/ahd_sg_size(ahd) * scb->sg_count, op);
+-}
+-
+-static __inline void
+-ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op)
+-{
+- ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat,
+- scb->sense_map->dmamap,
+- /*offset*/scb->sense_busaddr,
+- /*len*/AHD_SENSE_BUFSIZE, op);
+-}
+-
+-static __inline uint32_t
+-ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index)
+-{
+- return (((uint8_t *)&ahd->targetcmds[index])
+- - (uint8_t *)ahd->qoutfifo);
+-}
+-
+ /*********************** Miscellaneous Support Functions ***********************/
+-static __inline struct ahd_initiator_tinfo *
+- ahd_fetch_transinfo(struct ahd_softc *ahd,
+- char channel, u_int our_id,
+- u_int remote_id,
+- struct ahd_tmode_tstate **tstate);
+-static __inline uint16_t
+- ahd_inw(struct ahd_softc *ahd, u_int port);
+-static __inline void ahd_outw(struct ahd_softc *ahd, u_int port,
+- u_int value);
+-static __inline uint32_t
+- ahd_inl(struct ahd_softc *ahd, u_int port);
+-static __inline void ahd_outl(struct ahd_softc *ahd, u_int port,
+- uint32_t value);
+-static __inline uint64_t
+- ahd_inq(struct ahd_softc *ahd, u_int port);
+-static __inline void ahd_outq(struct ahd_softc *ahd, u_int port,
+- uint64_t value);
+-static __inline u_int ahd_get_scbptr(struct ahd_softc *ahd);
+-static __inline void ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr);
+-static __inline u_int ahd_get_hnscb_qoff(struct ahd_softc *ahd);
+-static __inline void ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value);
+-static __inline u_int ahd_get_hescb_qoff(struct ahd_softc *ahd);
+-static __inline void ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value);
+-static __inline u_int ahd_get_snscb_qoff(struct ahd_softc *ahd);
+-static __inline void ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value);
+-static __inline u_int ahd_get_sescb_qoff(struct ahd_softc *ahd);
+-static __inline void ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value);
+-static __inline u_int ahd_get_sdscb_qoff(struct ahd_softc *ahd);
+-static __inline void ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value);
+-static __inline u_int ahd_inb_scbram(struct ahd_softc *ahd, u_int offset);
+-static __inline u_int ahd_inw_scbram(struct ahd_softc *ahd, u_int offset);
+-static __inline uint32_t
+- ahd_inl_scbram(struct ahd_softc *ahd, u_int offset);
+-static __inline uint64_t
+- ahd_inq_scbram(struct ahd_softc *ahd, u_int offset);
+-static __inline void ahd_swap_with_next_hscb(struct ahd_softc *ahd,
+- struct scb *scb);
+-static __inline void ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb);
++struct ahd_initiator_tinfo *
++ ahd_fetch_transinfo(struct ahd_softc *ahd,
++ char channel, u_int our_id,
++ u_int remote_id,
++ struct ahd_tmode_tstate **tstate);
++uint16_t
++ ahd_inw(struct ahd_softc *ahd, u_int port);
++void ahd_outw(struct ahd_softc *ahd, u_int port,
++ u_int value);
++uint32_t
++ ahd_inl(struct ahd_softc *ahd, u_int port);
++void ahd_outl(struct ahd_softc *ahd, u_int port,
++ uint32_t value);
++uint64_t
++ ahd_inq(struct ahd_softc *ahd, u_int port);
++void ahd_outq(struct ahd_softc *ahd, u_int port,
++ uint64_t value);
++u_int ahd_get_scbptr(struct ahd_softc *ahd);
++void ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr);
++u_int ahd_inb_scbram(struct ahd_softc *ahd, u_int offset);
++u_int ahd_inw_scbram(struct ahd_softc *ahd, u_int offset);
++struct scb *
++ ahd_lookup_scb(struct ahd_softc *ahd, u_int tag);
++void ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb);
++
+ static __inline uint8_t *
+ ahd_get_sense_buf(struct ahd_softc *ahd,
+ struct scb *scb);
+@@ -463,25 +148,7 @@ static __inline uint32_t
+ ahd_get_sense_bufaddr(struct ahd_softc *ahd,
+ struct scb *scb);
+
+-/*
+- * Return pointers to the transfer negotiation information
+- * for the specified our_id/remote_id pair.
+- */
+-static __inline struct ahd_initiator_tinfo *
+-ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id,
+- u_int remote_id, struct ahd_tmode_tstate **tstate)
+-{
+- /*
+- * Transfer data structures are stored from the perspective
+- * of the target role. Since the parameters for a connection
+- * in the initiator role to a given target are the same as
+- * when the roles are reversed, we pretend we are the target.
+- */
+- if (channel == 'B')
+- our_id += 8;
+- *tstate = ahd->enabled_targets[our_id];
+- return (&(*tstate)->transinfo[remote_id]);
-}
--
--static int
--qeth_register_netdev(struct qeth_card *card)
++#if 0 /* unused */
+
+ #define AHD_COPY_COL_IDX(dst, src) \
+ do { \
+@@ -489,304 +156,7 @@ do { \
+ dst->hscb->lun = src->hscb->lun; \
+ } while (0)
+
+-static __inline uint16_t
+-ahd_inw(struct ahd_softc *ahd, u_int port)
-{
-- 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);
+- /*
+- * Read high byte first as some registers increment
+- * or have other side effects when the low byte is
+- * read.
+- */
+- uint16_t r = ahd_inb(ahd, port+1) << 8;
+- return r | ahd_inb(ahd, port);
-}
-
--static void
--qeth_start_again(struct qeth_card *card, int recovery_mode)
+-static __inline void
+-ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)
-{
-- 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);
+- /*
+- * Write low byte first to accomodate registers
+- * such as PRGMCNT where the order maters.
+- */
+- ahd_outb(ahd, port, value & 0xFF);
+- ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
-}
-
+-static __inline uint32_t
+-ahd_inl(struct ahd_softc *ahd, u_int port)
+-{
+- return ((ahd_inb(ahd, port))
+- | (ahd_inb(ahd, port+1) << 8)
+- | (ahd_inb(ahd, port+2) << 16)
+- | (ahd_inb(ahd, port+3) << 24));
+-}
-
--/* 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)
+-static __inline void
+-ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value)
-{
+- ahd_outb(ahd, port, (value) & 0xFF);
+- ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF);
+- ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF);
+- ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF);
+-}
-
-- 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 __inline uint64_t
+-ahd_inq(struct ahd_softc *ahd, u_int port)
+-{
+- return ((ahd_inb(ahd, port))
+- | (ahd_inb(ahd, port+1) << 8)
+- | (ahd_inb(ahd, port+2) << 16)
+- | (ahd_inb(ahd, port+3) << 24)
+- | (((uint64_t)ahd_inb(ahd, port+4)) << 32)
+- | (((uint64_t)ahd_inb(ahd, port+5)) << 40)
+- | (((uint64_t)ahd_inb(ahd, port+6)) << 48)
+- | (((uint64_t)ahd_inb(ahd, port+7)) << 56));
-}
-
+-static __inline void
+-ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value)
+-{
+- ahd_outb(ahd, port, value & 0xFF);
+- ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
+- ahd_outb(ahd, port+2, (value >> 16) & 0xFF);
+- ahd_outb(ahd, port+3, (value >> 24) & 0xFF);
+- ahd_outb(ahd, port+4, (value >> 32) & 0xFF);
+- ahd_outb(ahd, port+5, (value >> 40) & 0xFF);
+- ahd_outb(ahd, port+6, (value >> 48) & 0xFF);
+- ahd_outb(ahd, port+7, (value >> 56) & 0xFF);
+-}
-
--static int
--__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode)
+-static __inline u_int
+-ahd_get_scbptr(struct ahd_softc *ahd)
-{
-- struct qeth_card *card = gdev->dev.driver_data;
-- int rc = 0;
-- enum qeth_card_states recover_flag;
+- AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
+- ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
+- return (ahd_inb(ahd, SCBPTR) | (ahd_inb(ahd, SCBPTR + 1) << 8));
+-}
-
-- BUG_ON(!card);
-- QETH_DBF_TEXT(setup ,2, "setonlin");
-- QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+-static __inline void
+-ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr)
+-{
+- AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
+- ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
+- ahd_outb(ahd, SCBPTR, scbptr & 0xFF);
+- ahd_outb(ahd, SCBPTR+1, (scbptr >> 8) & 0xFF);
+-}
-
-- 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;
-- }
+-static __inline u_int
+-ahd_get_hnscb_qoff(struct ahd_softc *ahd)
+-{
+- return (ahd_inw_atomic(ahd, HNSCB_QOFF));
+-}
-
-- 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;
-- }
+-static __inline void
+-ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value)
+-{
+- ahd_outw_atomic(ahd, HNSCB_QOFF, value);
+-}
-
-- qeth_make_parameters_consistent(card);
+-static __inline u_int
+-ahd_get_hescb_qoff(struct ahd_softc *ahd)
+-{
+- return (ahd_inb(ahd, HESCB_QOFF));
+-}
-
-- if ((rc = qeth_hardsetup_card(card))){
-- QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
-- goto out_remove;
-- }
-- card->state = CARD_STATE_HARDSETUP;
+-static __inline void
+-ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value)
+-{
+- ahd_outb(ahd, HESCB_QOFF, value);
+-}
-
-- if (!(rc = qeth_query_ipassists(card,QETH_PROT_IPV4)))
-- rc = qeth_get_unique_id(card);
+-static __inline u_int
+-ahd_get_snscb_qoff(struct ahd_softc *ahd)
+-{
+- u_int oldvalue;
-
-- 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;
-- }
+- AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+- oldvalue = ahd_inw(ahd, SNSCB_QOFF);
+- ahd_outw(ahd, SNSCB_QOFF, oldvalue);
+- return (oldvalue);
+-}
-
-- 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);
+-static __inline void
+-ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value)
+-{
+- AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+- ahd_outw(ahd, SNSCB_QOFF, value);
+-}
-
-- 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 __inline u_int
+-ahd_get_sescb_qoff(struct ahd_softc *ahd)
+-{
+- AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+- return (ahd_inb(ahd, SESCB_QOFF));
-}
-
--static int
--qeth_set_online(struct ccwgroup_device *gdev)
+-static __inline void
+-ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value)
-{
-- return __qeth_set_online(gdev, 0);
+- AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+- ahd_outb(ahd, SESCB_QOFF, value);
-}
-
--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 __inline u_int
+-ahd_get_sdscb_qoff(struct ahd_softc *ahd)
+-{
+- AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+- return (ahd_inb(ahd, SDSCB_QOFF) | (ahd_inb(ahd, SDSCB_QOFF + 1) << 8));
+-}
-
--struct device *qeth_root_dev = NULL;
+-static __inline void
+-ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value)
+-{
+- AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+- ahd_outb(ahd, SDSCB_QOFF, value & 0xFF);
+- ahd_outb(ahd, SDSCB_QOFF+1, (value >> 8) & 0xFF);
+-}
-
--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,
--};
+-static __inline u_int
+-ahd_inb_scbram(struct ahd_softc *ahd, u_int offset)
+-{
+- u_int value;
-
--struct ccw_driver qeth_ccw_driver = {
-- .name = "qeth",
-- .ids = qeth_ids,
-- .probe = ccwgroup_probe_ccwdev,
-- .remove = ccwgroup_remove_ccwdev,
--};
+- /*
+- * Workaround PCI-X Rev A. hardware bug.
+- * After a host read of SCB memory, the chip
+- * may become confused into thinking prefetch
+- * was required. This starts the discard timer
+- * running and can cause an unexpected discard
+- * timer interrupt. The work around is to read
+- * a normal register prior to the exhaustion of
+- * the discard timer. The mode pointer register
+- * has no side effects and so serves well for
+- * this purpose.
+- *
+- * Razor #528
+- */
+- value = ahd_inb(ahd, offset);
+- if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0)
+- ahd_inb(ahd, MODE_PTR);
+- return (value);
+-}
-
+-static __inline u_int
+-ahd_inw_scbram(struct ahd_softc *ahd, u_int offset)
+-{
+- return (ahd_inb_scbram(ahd, offset)
+- | (ahd_inb_scbram(ahd, offset+1) << 8));
+-}
-
--static void
--qeth_unregister_dbf_views(void)
+-static __inline uint32_t
+-ahd_inl_scbram(struct ahd_softc *ahd, u_int offset)
-{
-- 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);
+- return (ahd_inw_scbram(ahd, offset)
+- | (ahd_inw_scbram(ahd, offset+2) << 16));
-}
--static int
--qeth_register_dbf_views(void)
+-
+-static __inline uint64_t
+-ahd_inq_scbram(struct ahd_softc *ahd, u_int offset)
-{
-- 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);
+- return (ahd_inl_scbram(ahd, offset)
+- | ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32);
+-}
-
-- 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);
+-static __inline struct scb *
+-ahd_lookup_scb(struct ahd_softc *ahd, u_int tag)
+-{
+- struct scb* scb;
-
-- debug_register_view(qeth_dbf_misc, &debug_hex_ascii_view);
-- debug_set_level(qeth_dbf_misc, QETH_DBF_MISC_LEVEL);
+- if (tag >= AHD_SCB_MAX)
+- return (NULL);
+- scb = ahd->scb_data.scbindex[tag];
+- if (scb != NULL)
+- ahd_sync_scb(ahd, scb,
+- BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+- return (scb);
+-}
-
-- debug_register_view(qeth_dbf_data, &debug_hex_ascii_view);
-- debug_set_level(qeth_dbf_data, QETH_DBF_DATA_LEVEL);
+-static __inline void
+-ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
+-{
+- struct hardware_scb *q_hscb;
+- struct map_node *q_hscb_map;
+- uint32_t saved_hscb_busaddr;
-
-- debug_register_view(qeth_dbf_control, &debug_hex_ascii_view);
-- debug_set_level(qeth_dbf_control, QETH_DBF_CONTROL_LEVEL);
+- /*
+- * Our queuing method is a bit tricky. The card
+- * knows in advance which HSCB (by address) to download,
+- * and we can't disappoint it. To achieve this, the next
+- * HSCB to download is saved off in ahd->next_queued_hscb.
+- * When we are called to queue "an arbitrary scb",
+- * we copy the contents of the incoming HSCB to the one
+- * the sequencer knows about, swap HSCB pointers and
+- * finally assign the SCB to the tag indexed location
+- * in the scb_array. This makes sure that we can still
+- * locate the correct SCB by SCB_TAG.
+- */
+- q_hscb = ahd->next_queued_hscb;
+- q_hscb_map = ahd->next_queued_hscb_map;
+- saved_hscb_busaddr = q_hscb->hscb_busaddr;
+- memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
+- q_hscb->hscb_busaddr = saved_hscb_busaddr;
+- q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
-
-- debug_register_view(qeth_dbf_sense, &debug_hex_ascii_view);
-- debug_set_level(qeth_dbf_sense, QETH_DBF_SENSE_LEVEL);
+- /* Now swap HSCB pointers. */
+- ahd->next_queued_hscb = scb->hscb;
+- ahd->next_queued_hscb_map = scb->hscb_map;
+- scb->hscb = q_hscb;
+- scb->hscb_map = q_hscb_map;
-
-- debug_register_view(qeth_dbf_qerr, &debug_hex_ascii_view);
-- debug_set_level(qeth_dbf_qerr, QETH_DBF_QERR_LEVEL);
+- /* Now define the mapping from tag to SCB in the scbindex */
+- ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
+-}
-
-- debug_register_view(qeth_dbf_trace, &debug_hex_ascii_view);
-- debug_set_level(qeth_dbf_trace, QETH_DBF_TRACE_LEVEL);
+-/*
+- * Tell the sequencer about a new transaction to execute.
+- */
+-static __inline void
+-ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb)
+-{
+- ahd_swap_with_next_hscb(ahd, scb);
-
-- return 0;
--}
+- if (SCBID_IS_NULL(SCB_GET_TAG(scb)))
+- panic("Attempt to queue invalid SCB tag %x\n",
+- SCB_GET_TAG(scb));
-
--#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 *);
+- /*
+- * Keep a history of SCBs we've downloaded in the qinfifo.
+- */
+- ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb);
+- ahd->qinfifonext++;
-
--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
--};
+- if (scb->sg_count != 0)
+- ahd_setup_data_scb(ahd, scb);
+- else
+- ahd_setup_noxfer_scb(ahd, scb);
+- ahd_setup_scb_common(ahd, scb);
-
--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;
+- /*
+- * Make sure our data is consistent from the
+- * perspective of the adapter.
+- */
+- ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
-
-- 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;
+-#ifdef AHD_DEBUG
+- if ((ahd_debug & AHD_SHOW_QUEUE) != 0) {
+- uint64_t host_dataptr;
-
-- rcu_read_lock();
-- in_dev = __in_dev_get_rcu(dev);
-- if (in_dev == NULL) {
-- rcu_read_unlock();
-- return -EINVAL;
+- host_dataptr = ahd_le64toh(scb->hscb->dataptr);
+- printf("%s: Queueing SCB %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
+- ahd_name(ahd),
+- SCB_GET_TAG(scb), scb->hscb->scsiid,
+- ahd_le32toh(scb->hscb->hscb_busaddr),
+- (u_int)((host_dataptr >> 32) & 0xFFFFFFFF),
+- (u_int)(host_dataptr & 0xFFFFFFFF),
+- ahd_le32toh(scb->hscb->datacnt));
- }
+ #endif
+- /* Tell the adapter about the newly queued SCB */
+- ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
+-}
+
+ static __inline uint8_t *
+ ahd_get_sense_buf(struct ahd_softc *ahd, struct scb *scb)
+@@ -801,151 +171,6 @@ ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb)
+ }
+
+ /************************** Interrupt Processing ******************************/
+-static __inline void ahd_sync_qoutfifo(struct ahd_softc *ahd, int op);
+-static __inline void ahd_sync_tqinfifo(struct ahd_softc *ahd, int op);
+-static __inline u_int ahd_check_cmdcmpltqueues(struct ahd_softc *ahd);
+-static __inline int ahd_intr(struct ahd_softc *ahd);
-
-- parms = in_dev->arp_parms;
-- __neigh_parms_put(neigh->parms);
-- neigh->parms = neigh_parms_clone(parms);
-- rcu_read_unlock();
+-static __inline void
+-ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
+-{
+- ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
+- /*offset*/0,
+- /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op);
+-}
-
-- 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);
+-static __inline void
+-ahd_sync_tqinfifo(struct ahd_softc *ahd, int op)
+-{
+-#ifdef AHD_TARGET_MODE
+- if ((ahd->flags & AHD_TARGETROLE) != 0) {
+- ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
+- ahd->shared_data_map.dmamap,
+- ahd_targetcmd_offset(ahd, 0),
+- sizeof(struct target_cmd) * AHD_TMODE_CMDS,
+- op);
+- }
+-#endif
-}
--#endif /*CONFIG_QETH_IPV6*/
-
-/*
-- * IP address takeover related functions
+- * See if the firmware has posted any completed commands
+- * into our in-core command complete fifos.
- */
--static void
--qeth_clear_ipato_list(struct qeth_card *card)
+-#define AHD_RUN_QOUTFIFO 0x1
+-#define AHD_RUN_TQINFIFO 0x2
+-static __inline u_int
+-ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
-{
-- struct qeth_ipato_entry *ipatoe, *tmp;
-- unsigned long flags;
+- u_int retval;
-
-- spin_lock_irqsave(&card->ip_lock, flags);
-- list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry) {
-- list_del(&ipatoe->entry);
-- kfree(ipatoe);
+- retval = 0;
+- ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
+- /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),
+- /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD);
+- if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag
+- == ahd->qoutfifonext_valid_tag)
+- retval |= AHD_RUN_QOUTFIFO;
+-#ifdef AHD_TARGET_MODE
+- if ((ahd->flags & AHD_TARGETROLE) != 0
+- && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {
+- ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
+- ahd->shared_data_map.dmamap,
+- ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),
+- /*len*/sizeof(struct target_cmd),
+- BUS_DMASYNC_POSTREAD);
+- if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0)
+- retval |= AHD_RUN_TQINFIFO;
- }
-- spin_unlock_irqrestore(&card->ip_lock, flags);
+-#endif
+- return (retval);
-}
-
--int
--qeth_add_ipato_entry(struct qeth_card *card, struct qeth_ipato_entry *new)
+-/*
+- * Catch an interrupt from the adapter
+- */
+-static __inline int
+-ahd_intr(struct ahd_softc *ahd)
-{
-- struct qeth_ipato_entry *ipatoe;
-- unsigned long flags;
-- int rc = 0;
+- u_int intstat;
-
-- 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 ((ahd->pause & INTEN) == 0) {
+- /*
+- * Our interrupt is not enabled on the chip
+- * and may be disabled for re-entrancy reasons,
+- * so just return. This is likely just a shared
+- * interrupt.
+- */
+- return (0);
+- }
+-
+- /*
+- * Instead of directly reading the interrupt status register,
+- * infer the cause of the interrupt by checking our in-core
+- * completion queues. This avoids a costly PCI bus read in
+- * most cases.
+- */
+- if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0
+- && (ahd_check_cmdcmpltqueues(ahd) != 0))
+- intstat = CMDCMPLT;
+- else
+- intstat = ahd_inb(ahd, INTSTAT);
+-
+- if ((intstat & INT_PEND) == 0)
+- return (0);
+-
+- if (intstat & CMDCMPLT) {
+- ahd_outb(ahd, CLRINT, CLRCMDINT);
+-
+- /*
+- * Ensure that the chip sees that we've cleared
+- * this interrupt before we walk the output fifo.
+- * Otherwise, we may, due to posted bus writes,
+- * clear the interrupt after we finish the scan,
+- * and after the sequencer has added new entries
+- * and asserted the interrupt again.
+- */
+- if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
+- if (ahd_is_paused(ahd)) {
+- /*
+- * Potentially lost SEQINT.
+- * If SEQINTCODE is non-zero,
+- * simulate the SEQINT.
+- */
+- if (ahd_inb(ahd, SEQINTCODE) != NO_SEQINT)
+- intstat |= SEQINT;
+- }
+- } else {
+- ahd_flush_device_writes(ahd);
- }
+- ahd_run_qoutfifo(ahd);
+- ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]++;
+- ahd->cmdcmplt_total++;
+-#ifdef AHD_TARGET_MODE
+- if ((ahd->flags & AHD_TARGETROLE) != 0)
+- ahd_run_tqinfifo(ahd, /*paused*/FALSE);
+-#endif
- }
-- if (!rc) {
-- list_add_tail(&new->entry, &card->ipato.entries);
+-
+- /*
+- * Handle statuses that may invalidate our cached
+- * copy of INTSTAT separately.
+- */
+- if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) {
+- /* Hot eject. Do nothing */
+- } else if (intstat & HWERRINT) {
+- ahd_handle_hwerrint(ahd);
+- } else if ((intstat & (PCIINT|SPLTINT)) != 0) {
+- ahd->bus_intr(ahd);
+- } else {
+-
+- if ((intstat & SEQINT) != 0)
+- ahd_handle_seqint(ahd, intstat);
+-
+- if ((intstat & SCSIINT) != 0)
+- ahd_handle_scsiint(ahd, intstat);
+- }
+- return (1);
+-}
++int ahd_intr(struct ahd_softc *ahd);
+
+ #endif /* _AIC79XX_INLINE_H_ */
+diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
+index 72fccd9..0f829b3 100644
+--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
++++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
+@@ -193,7 +193,7 @@ struct ahd_linux_iocell_opts
+ #define AIC79XX_PRECOMP_INDEX 0
+ #define AIC79XX_SLEWRATE_INDEX 1
+ #define AIC79XX_AMPLITUDE_INDEX 2
+-static struct ahd_linux_iocell_opts aic79xx_iocell_info[] =
++static const struct ahd_linux_iocell_opts aic79xx_iocell_info[] =
+ {
+ AIC79XX_DEFAULT_IOOPTS,
+ AIC79XX_DEFAULT_IOOPTS,
+@@ -369,10 +369,167 @@ static void ahd_release_simq(struct ahd_softc *ahd);
+ static int ahd_linux_unit;
+
+
++/************************** OS Utility Wrappers *******************************/
++void ahd_delay(long);
++void
++ahd_delay(long usec)
++{
++ /*
++ * udelay on Linux can have problems for
++ * multi-millisecond waits. Wait at most
++ * 1024us per call.
++ */
++ while (usec > 0) {
++ udelay(usec % 1024);
++ usec -= 1024;
++ }
++}
++
++
++/***************************** Low Level I/O **********************************/
++uint8_t ahd_inb(struct ahd_softc * ahd, long port);
++void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val);
++void ahd_outw_atomic(struct ahd_softc * ahd,
++ long port, uint16_t val);
++void ahd_outsb(struct ahd_softc * ahd, long port,
++ uint8_t *, int count);
++void ahd_insb(struct ahd_softc * ahd, long port,
++ uint8_t *, int count);
++
++uint8_t
++ahd_inb(struct ahd_softc * ahd, long port)
++{
++ uint8_t x;
++
++ if (ahd->tags[0] == BUS_SPACE_MEMIO) {
++ x = readb(ahd->bshs[0].maddr + port);
++ } else {
++ x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
++ }
++ mb();
++ return (x);
++}
++
++#if 0 /* unused */
++static uint16_t
++ahd_inw_atomic(struct ahd_softc * ahd, long port)
++{
++ uint8_t x;
++
++ if (ahd->tags[0] == BUS_SPACE_MEMIO) {
++ x = readw(ahd->bshs[0].maddr + port);
++ } else {
++ x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
++ }
++ mb();
++ return (x);
++}
++#endif
++
++void
++ahd_outb(struct ahd_softc * ahd, long port, uint8_t val)
++{
++ if (ahd->tags[0] == BUS_SPACE_MEMIO) {
++ writeb(val, ahd->bshs[0].maddr + port);
++ } else {
++ outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
++ }
++ mb();
++}
++
++void
++ahd_outw_atomic(struct ahd_softc * ahd, long port, uint16_t val)
++{
++ if (ahd->tags[0] == BUS_SPACE_MEMIO) {
++ writew(val, ahd->bshs[0].maddr + port);
++ } else {
++ outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
++ }
++ mb();
++}
++
++void
++ahd_outsb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
++{
++ int i;
++
++ /*
++ * There is probably a more efficient way to do this on Linux
++ * but we don't use this for anything speed critical and this
++ * should work.
++ */
++ for (i = 0; i < count; i++)
++ ahd_outb(ahd, port, *array++);
++}
++
++void
++ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
++{
++ int i;
++
++ /*
++ * There is probably a more efficient way to do this on Linux
++ * but we don't use this for anything speed critical and this
++ * should work.
++ */
++ for (i = 0; i < count; i++)
++ *array++ = ahd_inb(ahd, port);
++}
++
++/******************************* PCI Routines *********************************/
++uint32_t
++ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width)
++{
++ switch (width) {
++ case 1:
++ {
++ uint8_t retval;
++
++ pci_read_config_byte(pci, reg, &retval);
++ return (retval);
++ }
++ case 2:
++ {
++ uint16_t retval;
++ pci_read_config_word(pci, reg, &retval);
++ return (retval);
++ }
++ case 4:
++ {
++ uint32_t retval;
++ pci_read_config_dword(pci, reg, &retval);
++ return (retval);
++ }
++ default:
++ panic("ahd_pci_read_config: Read size too big");
++ /* NOTREACHED */
++ return (0);
++ }
++}
++
++void
++ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width)
++{
++ switch (width) {
++ case 1:
++ pci_write_config_byte(pci, reg, value);
++ break;
++ case 2:
++ pci_write_config_word(pci, reg, value);
++ break;
++ case 4:
++ pci_write_config_dword(pci, reg, value);
++ break;
++ default:
++ panic("ahd_pci_write_config: Write size too big");
++ /* NOTREACHED */
++ }
++}
++
+ /****************************** Inlines ***************************************/
+-static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
++static void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
+
+-static __inline void
++static void
+ ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
+ {
+ struct scsi_cmnd *cmd;
+@@ -400,13 +557,11 @@ ahd_linux_info(struct Scsi_Host *host)
+ bp = &buffer[0];
+ ahd = *(struct ahd_softc **)host->hostdata;
+ memset(bp, 0, sizeof(buffer));
+- strcpy(bp, "Adaptec AIC79XX PCI-X SCSI HBA DRIVER, Rev ");
+- strcat(bp, AIC79XX_DRIVER_VERSION);
+- strcat(bp, "\n");
+- strcat(bp, " <");
++ strcpy(bp, "Adaptec AIC79XX PCI-X SCSI HBA DRIVER, Rev " AIC79XX_DRIVER_VERSION "\n"
++ " <");
+ strcat(bp, ahd->description);
+- strcat(bp, ">\n");
+- strcat(bp, " ");
++ strcat(bp, ">\n"
++ " ");
+ ahd_controller_info(ahd, ahd_info);
+ strcat(bp, ahd_info);
+
+@@ -432,7 +587,7 @@ ahd_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
+ return rtn;
+ }
+
+-static inline struct scsi_target **
++static struct scsi_target **
+ ahd_linux_target_in_softc(struct scsi_target *starget)
+ {
+ struct ahd_softc *ahd =
+@@ -991,7 +1146,7 @@ aic79xx_setup(char *s)
+ char *p;
+ char *end;
+
+- static struct {
++ static const struct {
+ const char *name;
+ uint32_t *flag;
+ } options[] = {
+@@ -1223,7 +1378,7 @@ ahd_platform_init(struct ahd_softc *ahd)
+ * Lookup and commit any modified IO Cell options.
+ */
+ if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) {
+- struct ahd_linux_iocell_opts *iocell_opts;
++ const struct ahd_linux_iocell_opts *iocell_opts;
+
+ iocell_opts = &aic79xx_iocell_info[ahd->unit];
+ if (iocell_opts->precomp != AIC79XX_DEFAULT_PRECOMP)
+@@ -1413,6 +1568,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 +1589,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 +1645,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;
+@@ -2610,7 +2768,7 @@ static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp)
+ uint8_t precomp;
+
+ if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) {
+- struct ahd_linux_iocell_opts *iocell_opts;
++ const struct ahd_linux_iocell_opts *iocell_opts;
+
+ iocell_opts = &aic79xx_iocell_info[ahd->unit];
+ precomp = iocell_opts->precomp;
+diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
+index 853998b..8d6612c 100644
+--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
++++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
+@@ -222,22 +222,6 @@ typedef struct timer_list ahd_timer_t;
+ /***************************** Timer Facilities *******************************/
+ #define ahd_timer_init init_timer
+ #define ahd_timer_stop del_timer_sync
+-typedef void ahd_linux_callback_t (u_long);
+-static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec,
+- ahd_callback_t *func, void *arg);
+-
+-static __inline void
+-ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
+-{
+- struct ahd_softc *ahd;
+-
+- ahd = (struct ahd_softc *)arg;
+- del_timer(timer);
+- timer->data = (u_long)arg;
+- timer->expires = jiffies + (usec * HZ)/1000000;
+- timer->function = (ahd_linux_callback_t*)func;
+- add_timer(timer);
+-}
+
+ /***************************** SMP support ************************************/
+ #include <linux/spinlock.h>
+@@ -376,7 +360,7 @@ struct ahd_platform_data {
+ #define AHD_LINUX_NOIRQ ((uint32_t)~0)
+ uint32_t irq; /* IRQ for this adapter */
+ uint32_t bios_address;
+- uint32_t mem_busaddr; /* Mem Base Addr */
++ resource_size_t mem_busaddr; /* Mem Base Addr */
+ };
+
+ /************************** OS Utility Wrappers *******************************/
+@@ -386,111 +370,18 @@ struct ahd_platform_data {
+ #define malloc(size, type, flags) kmalloc(size, flags)
+ #define free(ptr, type) kfree(ptr)
+
+-static __inline void ahd_delay(long);
+-static __inline void
+-ahd_delay(long usec)
+-{
+- /*
+- * udelay on Linux can have problems for
+- * multi-millisecond waits. Wait at most
+- * 1024us per call.
+- */
+- while (usec > 0) {
+- udelay(usec % 1024);
+- usec -= 1024;
- }
-- 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)
++void ahd_delay(long);
+
+ /***************************** Low Level I/O **********************************/
+-static __inline uint8_t ahd_inb(struct ahd_softc * ahd, long port);
+-static __inline uint16_t ahd_inw_atomic(struct ahd_softc * ahd, long port);
+-static __inline void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val);
+-static __inline void ahd_outw_atomic(struct ahd_softc * ahd,
++uint8_t ahd_inb(struct ahd_softc * ahd, long port);
++void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val);
++void ahd_outw_atomic(struct ahd_softc * ahd,
+ long port, uint16_t val);
+-static __inline void ahd_outsb(struct ahd_softc * ahd, long port,
++void ahd_outsb(struct ahd_softc * ahd, long port,
+ uint8_t *, int count);
+-static __inline void ahd_insb(struct ahd_softc * ahd, long port,
++void ahd_insb(struct ahd_softc * ahd, long port,
+ uint8_t *, int count);
+
+-static __inline uint8_t
+-ahd_inb(struct ahd_softc * ahd, long port)
-{
-- struct qeth_ipato_entry *ipatoe, *tmp;
-- unsigned long flags;
+- uint8_t x;
-
-- 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);
-- }
+- if (ahd->tags[0] == BUS_SPACE_MEMIO) {
+- x = readb(ahd->bshs[0].maddr + port);
+- } else {
+- x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
- }
-- spin_unlock_irqrestore(&card->ip_lock, flags);
+- mb();
+- return (x);
-}
-
--static void
--qeth_convert_addr_to_bits(u8 *addr, u8 *bits, int len)
+-static __inline uint16_t
+-ahd_inw_atomic(struct ahd_softc * ahd, long port)
-{
-- int i, j;
-- u8 octet;
+- uint8_t x;
-
-- for (i = 0; i < len; ++i){
-- octet = addr[i];
-- for (j = 7; j >= 0; --j){
-- bits[i*8 + j] = octet & 1;
-- octet >>= 1;
-- }
+- if (ahd->tags[0] == BUS_SPACE_MEMIO) {
+- x = readw(ahd->bshs[0].maddr + port);
+- } else {
+- x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
- }
+- mb();
+- return (x);
-}
-
--static int
--qeth_is_addr_covered_by_ipato(struct qeth_card *card, struct qeth_ipaddr *addr)
+-static __inline void
+-ahd_outb(struct ahd_softc * ahd, long port, uint8_t val)
-{
-- 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;
+- if (ahd->tags[0] == BUS_SPACE_MEMIO) {
+- writeb(val, ahd->bshs[0].maddr + port);
+- } else {
+- outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
- }
-- /* 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;
+- mb();
-}
-
--/*
-- * VIPA related functions
-- */
--int
--qeth_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
-- const u8 *addr)
+-static __inline void
+-ahd_outw_atomic(struct ahd_softc * ahd, long port, uint16_t val)
-{
-- 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 (ahd->tags[0] == BUS_SPACE_MEMIO) {
+- writew(val, ahd->bshs[0].maddr + port);
+- } else {
+- outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
- }
-- if (!qeth_add_ip(card, ipaddr))
-- kfree(ipaddr);
-- qeth_set_ip_addr_list(card);
-- return rc;
+- mb();
-}
-
--void
--qeth_del_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
-- const u8 *addr)
+-static __inline void
+-ahd_outsb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
-{
-- struct qeth_ipaddr *ipaddr;
+- int i;
-
-- 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);
+- /*
+- * There is probably a more efficient way to do this on Linux
+- * but we don't use this for anything speed critical and this
+- * should work.
+- */
+- for (i = 0; i < count; i++)
+- ahd_outb(ahd, port, *array++);
-}
-
--/*
-- * proxy ARP related functions
-- */
--int
--qeth_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
-- const u8 *addr)
+-static __inline void
+-ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
-{
-- struct qeth_ipaddr *ipaddr;
-- unsigned long flags;
-- int rc = 0;
+- int i;
-
-- 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;
+- /*
+- * There is probably a more efficient way to do this on Linux
+- * but we don't use this for anything speed critical and this
+- * should work.
+- */
+- for (i = 0; i < count; i++)
+- *array++ = ahd_inb(ahd, port);
-}
-
--void
--qeth_del_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
-- const u8 *addr)
+ /**************************** Initialization **********************************/
+ int ahd_linux_register_host(struct ahd_softc *,
+ struct scsi_host_template *);
+@@ -593,62 +484,12 @@ void ahd_linux_pci_exit(void);
+ int ahd_pci_map_registers(struct ahd_softc *ahd);
+ int ahd_pci_map_int(struct ahd_softc *ahd);
+
+-static __inline uint32_t ahd_pci_read_config(ahd_dev_softc_t pci,
++uint32_t ahd_pci_read_config(ahd_dev_softc_t pci,
+ int reg, int width);
+-
+-static __inline uint32_t
+-ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width)
-{
-- struct qeth_ipaddr *ipaddr;
+- switch (width) {
+- case 1:
+- {
+- uint8_t retval;
-
-- 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);
+- pci_read_config_byte(pci, reg, &retval);
+- return (retval);
+- }
+- case 2:
+- {
+- uint16_t retval;
+- pci_read_config_word(pci, reg, &retval);
+- return (retval);
+- }
+- case 4:
+- {
+- uint32_t retval;
+- pci_read_config_dword(pci, reg, &retval);
+- return (retval);
+- }
+- default:
+- panic("ahd_pci_read_config: Read size too big");
+- /* NOTREACHED */
+- return (0);
+- }
-}
-
--/**
-- * IP event handler
-- */
--static int
--qeth_ip_event(struct notifier_block *this,
-- unsigned long event,void *ptr)
+-static __inline void ahd_pci_write_config(ahd_dev_softc_t pci,
++void ahd_pci_write_config(ahd_dev_softc_t pci,
+ int reg, uint32_t value,
+ int width);
+
+-static __inline void
+-ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width)
-{
-- 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);
+- switch (width) {
+- case 1:
+- pci_write_config_byte(pci, reg, value);
- break;
-- case NETDEV_DOWN:
-- if (!qeth_delete_ip(card, addr))
-- kfree(addr);
+- case 2:
+- pci_write_config_word(pci, reg, value);
- break;
-- default:
+- case 4:
+- pci_write_config_dword(pci, reg, value);
- break;
+- default:
+- panic("ahd_pci_write_config: Write size too big");
+- /* NOTREACHED */
- }
-- qeth_set_ip_addr_list(card);
--out:
-- return NOTIFY_DONE;
-}
-
--static struct notifier_block qeth_ip_notifier = {
-- qeth_ip_event,
-- NULL,
--};
+ static __inline int ahd_get_pci_function(ahd_dev_softc_t);
+ static __inline int
+ ahd_get_pci_function(ahd_dev_softc_t pci)
+diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+index dfaaae5..6593056 100644
+--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
++++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+@@ -49,7 +49,7 @@
+ ID2C(x), \
+ ID2C(IDIROC(x))
+
+-static struct pci_device_id ahd_linux_pci_id_table[] = {
++static const struct pci_device_id ahd_linux_pci_id_table[] = {
+ /* aic7901 based controllers */
+ ID(ID_AHA_29320A),
+ ID(ID_AHA_29320ALP),
+@@ -159,7 +159,7 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ char buf[80];
+ struct ahd_softc *ahd;
+ ahd_dev_softc_t pci;
+- struct ahd_pci_identity *entry;
++ const struct ahd_pci_identity *entry;
+ char *name;
+ int error;
+ struct device *dev = &pdev->dev;
+@@ -249,8 +249,8 @@ ahd_linux_pci_exit(void)
+ }
+
+ static int
+-ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base,
+- u_long *base2)
++ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, resource_size_t *base,
++ resource_size_t *base2)
+ {
+ *base = pci_resource_start(ahd->dev_softc, 0);
+ /*
+@@ -272,11 +272,11 @@ ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base,
+
+ static int
+ ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
+- u_long *bus_addr,
++ resource_size_t *bus_addr,
+ uint8_t __iomem **maddr)
+ {
+- u_long start;
+- u_long base_page;
++ resource_size_t start;
++ resource_size_t base_page;
+ u_long base_offset;
+ int error = 0;
+
+@@ -310,7 +310,7 @@ int
+ ahd_pci_map_registers(struct ahd_softc *ahd)
+ {
+ uint32_t command;
+- u_long base;
++ resource_size_t base;
+ uint8_t __iomem *maddr;
+ int error;
+
+@@ -346,31 +346,32 @@ ahd_pci_map_registers(struct ahd_softc *ahd)
+ } else
+ command |= PCIM_CMD_MEMEN;
+ } else if (bootverbose) {
+- printf("aic79xx: PCI%d:%d:%d MEM region 0x%lx "
++ printf("aic79xx: PCI%d:%d:%d MEM region 0x%llx "
+ "unavailable. Cannot memory map device.\n",
+ ahd_get_pci_bus(ahd->dev_softc),
+ ahd_get_pci_slot(ahd->dev_softc),
+ ahd_get_pci_function(ahd->dev_softc),
+- base);
++ (unsigned long long)base);
+ }
+
+ if (maddr == NULL) {
+- u_long base2;
++ resource_size_t base2;
+
+ error = ahd_linux_pci_reserve_io_regions(ahd, &base, &base2);
+ if (error == 0) {
+ ahd->tags[0] = BUS_SPACE_PIO;
+ ahd->tags[1] = BUS_SPACE_PIO;
+- ahd->bshs[0].ioport = base;
+- ahd->bshs[1].ioport = base2;
++ ahd->bshs[0].ioport = (u_long)base;
++ ahd->bshs[1].ioport = (u_long)base2;
+ command |= PCIM_CMD_PORTEN;
+ } else {
+- printf("aic79xx: PCI%d:%d:%d IO regions 0x%lx and 0x%lx"
+- "unavailable. Cannot map device.\n",
++ printf("aic79xx: PCI%d:%d:%d IO regions 0x%llx and "
++ "0x%llx unavailable. Cannot map device.\n",
+ ahd_get_pci_bus(ahd->dev_softc),
+ ahd_get_pci_slot(ahd->dev_softc),
+ ahd_get_pci_function(ahd->dev_softc),
+- base, base2);
++ (unsigned long long)base,
++ (unsigned long long)base2);
+ }
+ }
+ ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, 4);
+diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
+index c9f79fd..c25b6ad 100644
+--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
++++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
+@@ -97,7 +97,7 @@ static ahd_device_setup_t ahd_aic7901A_setup;
+ static ahd_device_setup_t ahd_aic7902_setup;
+ static ahd_device_setup_t ahd_aic790X_setup;
+
+-static struct ahd_pci_identity ahd_pci_ident_table [] =
++static const struct ahd_pci_identity ahd_pci_ident_table[] =
+ {
+ /* aic7901 based controllers */
+ {
+@@ -253,7 +253,7 @@ static void ahd_configure_termination(struct ahd_softc *ahd,
+ static void ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat);
+ static void ahd_pci_intr(struct ahd_softc *ahd);
+
+-struct ahd_pci_identity *
++const struct ahd_pci_identity *
+ ahd_find_pci_device(ahd_dev_softc_t pci)
+ {
+ uint64_t full_id;
+@@ -261,7 +261,7 @@ ahd_find_pci_device(ahd_dev_softc_t pci)
+ uint16_t vendor;
+ uint16_t subdevice;
+ uint16_t subvendor;
+- struct ahd_pci_identity *entry;
++ const struct ahd_pci_identity *entry;
+ u_int i;
+
+ vendor = ahd_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
+@@ -292,7 +292,7 @@ ahd_find_pci_device(ahd_dev_softc_t pci)
+ }
+
+ int
+-ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
++ahd_pci_config(struct ahd_softc *ahd, const struct ahd_pci_identity *entry)
+ {
+ struct scb_data *shared_scb_data;
+ u_int command;
+diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c
+index 6b28beb..014bed7 100644
+--- a/drivers/scsi/aic7xxx/aic79xx_proc.c
++++ b/drivers/scsi/aic7xxx/aic79xx_proc.c
+@@ -57,7 +57,7 @@ static int ahd_proc_write_seeprom(struct ahd_softc *ahd,
+ * Table of syncrates that don't follow the "divisible by 4"
+ * rule. This table will be expanded in future SCSI specs.
+ */
+-static struct {
++static const struct {
+ u_int period_factor;
+ u_int period; /* in 100ths of ns */
+ } scsi_syncrates[] = {
+diff --git a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
+index 2068e00..c21ceab 100644
+--- a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
++++ b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
+@@ -48,13 +48,6 @@ ahd_reg_print_t ahd_error_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_clrerr_print;
+-#else
+-#define ahd_clrerr_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CLRERR", 0x04, regvalue, cur_col, wrap)
+-#endif
-
--#ifdef CONFIG_QETH_IPV6
--/**
-- * IPv6 event handler
-- */
--static int
--qeth_ip6_event(struct notifier_block *this,
-- unsigned long event,void *ptr)
--{
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_hcntrl_print;
+ #else
+ #define ahd_hcntrl_print(regvalue, cur_col, wrap) \
+@@ -167,13 +160,6 @@ ahd_reg_print_t ahd_sg_cache_shadow_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_arbctl_print;
+-#else
+-#define ahd_arbctl_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "ARBCTL", 0x1b, regvalue, cur_col, wrap)
+-#endif
-
-- 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;
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_sg_cache_pre_print;
+ #else
+ #define ahd_sg_cache_pre_print(regvalue, cur_col, wrap) \
+@@ -188,20 +174,6 @@ ahd_reg_print_t ahd_lqin_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_typeptr_print;
+-#else
+-#define ahd_typeptr_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "TYPEPTR", 0x20, regvalue, cur_col, wrap)
+-#endif
-
-- QETH_DBF_TEXT(trace,3,"ip6event");
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_tagptr_print;
+-#else
+-#define ahd_tagptr_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "TAGPTR", 0x21, regvalue, cur_col, wrap)
+-#endif
-
-- card = qeth_get_card_from_dev(dev);
-- if (!card)
-- return NOTIFY_DONE;
-- if (!qeth_is_supported(card, IPA_IPV6))
-- return NOTIFY_DONE;
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_lunptr_print;
+ #else
+ #define ahd_lunptr_print(regvalue, cur_col, wrap) \
+@@ -209,20 +181,6 @@ ahd_reg_print_t ahd_lunptr_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_datalenptr_print;
+-#else
+-#define ahd_datalenptr_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DATALENPTR", 0x23, regvalue, cur_col, wrap)
+-#endif
-
-- 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;
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_statlenptr_print;
+-#else
+-#define ahd_statlenptr_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "STATLENPTR", 0x24, regvalue, cur_col, wrap)
+-#endif
-
-- 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;
--}
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_cmdlenptr_print;
+ #else
+ #define ahd_cmdlenptr_print(regvalue, cur_col, wrap) \
+@@ -258,13 +216,6 @@ ahd_reg_print_t ahd_qnextptr_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_idptr_print;
+-#else
+-#define ahd_idptr_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "IDPTR", 0x2a, regvalue, cur_col, wrap)
+-#endif
-
--static struct notifier_block qeth_ip6_notifier = {
-- qeth_ip6_event,
-- NULL,
--};
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_abrtbyteptr_print;
+ #else
+ #define ahd_abrtbyteptr_print(regvalue, cur_col, wrap) \
+@@ -279,27 +230,6 @@ ahd_reg_print_t ahd_abrtbitptr_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_maxcmdbytes_print;
+-#else
+-#define ahd_maxcmdbytes_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "MAXCMDBYTES", 0x2d, regvalue, cur_col, wrap)
-#endif
-
--static int
--__qeth_reboot_event_card(struct device *dev, void *data)
--{
-- struct qeth_card *card;
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_maxcmd2rcv_print;
+-#else
+-#define ahd_maxcmd2rcv_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "MAXCMD2RCV", 0x2e, regvalue, cur_col, wrap)
+-#endif
-
-- 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;
--}
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_shortthresh_print;
+-#else
+-#define ahd_shortthresh_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SHORTTHRESH", 0x2f, regvalue, cur_col, wrap)
+-#endif
-
--static int
--qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
--{
-- int ret;
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_lunlen_print;
+ #else
+ #define ahd_lunlen_print(regvalue, cur_col, wrap) \
+@@ -328,41 +258,6 @@ ahd_reg_print_t ahd_maxcmdcnt_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_lqrsvd01_print;
+-#else
+-#define ahd_lqrsvd01_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "LQRSVD01", 0x34, regvalue, cur_col, wrap)
+-#endif
-
-- ret = driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
-- __qeth_reboot_event_card);
-- return ret ? NOTIFY_BAD : NOTIFY_DONE;
--}
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_lqrsvd16_print;
+-#else
+-#define ahd_lqrsvd16_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "LQRSVD16", 0x35, regvalue, cur_col, wrap)
+-#endif
-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_lqrsvd17_print;
+-#else
+-#define ahd_lqrsvd17_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "LQRSVD17", 0x36, regvalue, cur_col, wrap)
+-#endif
-
--static struct notifier_block qeth_reboot_notifier = {
-- qeth_reboot_event,
-- NULL,
--};
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_cmdrsvd0_print;
+-#else
+-#define ahd_cmdrsvd0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CMDRSVD0", 0x37, regvalue, cur_col, wrap)
+-#endif
-
--static int
--qeth_register_notifiers(void)
--{
-- int r;
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_lqctl0_print;
+-#else
+-#define ahd_lqctl0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "LQCTL0", 0x38, regvalue, cur_col, wrap)
+-#endif
-
-- 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;
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_lqctl1_print;
+ #else
+ #define ahd_lqctl1_print(regvalue, cur_col, wrap) \
+@@ -370,13 +265,6 @@ ahd_reg_print_t ahd_lqctl1_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_scsbist0_print;
+-#else
+-#define ahd_scsbist0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SCSBIST0", 0x39, regvalue, cur_col, wrap)
-#endif
-- return 0;
-
--#ifdef CONFIG_QETH_IPV6
--out_ipv4:
-- unregister_inetaddr_notifier(&qeth_ip_notifier);
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_lqctl2_print;
+ #else
+ #define ahd_lqctl2_print(regvalue, cur_col, wrap) \
+@@ -384,13 +272,6 @@ ahd_reg_print_t ahd_lqctl2_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_scsbist1_print;
+-#else
+-#define ahd_scsbist1_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SCSBIST1", 0x3a, regvalue, cur_col, wrap)
-#endif
--out_reboot:
-- unregister_reboot_notifier(&qeth_reboot_notifier);
-- return r;
--}
-
--/**
-- * unregister all event notifiers
-- */
--static void
--qeth_unregister_notifiers(void)
--{
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_scsiseq0_print;
+ #else
+ #define ahd_scsiseq0_print(regvalue, cur_col, wrap) \
+@@ -412,20 +293,6 @@ ahd_reg_print_t ahd_sxfrctl0_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dlcount_print;
+-#else
+-#define ahd_dlcount_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap)
+-#endif
-
-- 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 */
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_businitid_print;
+-#else
+-#define ahd_businitid_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap)
+-#endif
-
--}
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_sxfrctl1_print;
+ #else
+ #define ahd_sxfrctl1_print(regvalue, cur_col, wrap) \
+@@ -433,20 +300,6 @@ ahd_reg_print_t ahd_sxfrctl1_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_bustargid_print;
+-#else
+-#define ahd_bustargid_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "BUSTARGID", 0x3e, regvalue, cur_col, wrap)
+-#endif
-
--#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);
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_sxfrctl2_print;
+-#else
+-#define ahd_sxfrctl2_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SXFRCTL2", 0x3e, regvalue, cur_col, wrap)
+-#endif
-
-- arp_direct_ops = (struct neigh_ops*)
-- kmalloc(sizeof(struct neigh_ops), GFP_KERNEL);
-- if (!arp_direct_ops)
-- return -ENOMEM;
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_dffstat_print;
+ #else
+ #define ahd_dffstat_print(regvalue, cur_col, wrap) \
+@@ -454,17 +307,17 @@ ahd_reg_print_t ahd_dffstat_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_scsisigo_print;
++ahd_reg_print_t ahd_multargid_print;
+ #else
+-#define ahd_scsisigo_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SCSISIGO", 0x40, regvalue, cur_col, wrap)
++#define ahd_multargid_print(regvalue, cur_col, wrap) \
++ ahd_print_register(NULL, 0, "MULTARGID", 0x40, regvalue, cur_col, wrap)
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_multargid_print;
++ahd_reg_print_t ahd_scsisigo_print;
+ #else
+-#define ahd_multargid_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "MULTARGID", 0x40, regvalue, cur_col, wrap)
++#define ahd_scsisigo_print(regvalue, cur_col, wrap) \
++ ahd_print_register(NULL, 0, "SCSISIGO", 0x40, regvalue, cur_col, wrap)
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+@@ -482,13 +335,6 @@ ahd_reg_print_t ahd_scsiphase_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_scsidat0_img_print;
+-#else
+-#define ahd_scsidat0_img_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SCSIDAT0_IMG", 0x43, regvalue, cur_col, wrap)
+-#endif
-
-- memcpy(arp_direct_ops, &arp_direct_ops_template,
-- sizeof(struct neigh_ops));
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_scsidat_print;
+ #else
+ #define ahd_scsidat_print(regvalue, cur_col, wrap) \
+@@ -531,13 +377,6 @@ ahd_reg_print_t ahd_sblkctl_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_clrsint0_print;
+-#else
+-#define ahd_clrsint0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CLRSINT0", 0x4b, regvalue, cur_col, wrap)
+-#endif
-
-- return 0;
--}
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_sstat0_print;
+ #else
+ #define ahd_sstat0_print(regvalue, cur_col, wrap) \
+@@ -552,10 +391,10 @@ ahd_reg_print_t ahd_simode0_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_clrsint1_print;
++ahd_reg_print_t ahd_clrsint0_print;
+ #else
+-#define ahd_clrsint1_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CLRSINT1", 0x4c, regvalue, cur_col, wrap)
++#define ahd_clrsint0_print(regvalue, cur_col, wrap) \
++ ahd_print_register(NULL, 0, "CLRSINT0", 0x4b, regvalue, cur_col, wrap)
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+@@ -566,17 +405,17 @@ ahd_reg_print_t ahd_sstat1_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_sstat2_print;
++ahd_reg_print_t ahd_clrsint1_print;
+ #else
+-#define ahd_sstat2_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SSTAT2", 0x4d, regvalue, cur_col, wrap)
++#define ahd_clrsint1_print(regvalue, cur_col, wrap) \
++ ahd_print_register(NULL, 0, "CLRSINT1", 0x4c, regvalue, cur_col, wrap)
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_simode2_print;
++ahd_reg_print_t ahd_sstat2_print;
+ #else
+-#define ahd_simode2_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SIMODE2", 0x4d, regvalue, cur_col, wrap)
++#define ahd_sstat2_print(regvalue, cur_col, wrap) \
++ ahd_print_register(NULL, 0, "SSTAT2", 0x4d, regvalue, cur_col, wrap)
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+@@ -622,17 +461,17 @@ ahd_reg_print_t ahd_lqistat0_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_clrlqiint0_print;
++ahd_reg_print_t ahd_lqimode0_print;
+ #else
+-#define ahd_clrlqiint0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CLRLQIINT0", 0x50, regvalue, cur_col, wrap)
++#define ahd_lqimode0_print(regvalue, cur_col, wrap) \
++ ahd_print_register(NULL, 0, "LQIMODE0", 0x50, regvalue, cur_col, wrap)
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_lqimode0_print;
++ahd_reg_print_t ahd_clrlqiint0_print;
+ #else
+-#define ahd_lqimode0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "LQIMODE0", 0x50, regvalue, cur_col, wrap)
++#define ahd_clrlqiint0_print(regvalue, cur_col, wrap) \
++ ahd_print_register(NULL, 0, "CLRLQIINT0", 0x50, regvalue, cur_col, wrap)
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+@@ -790,13 +629,6 @@ ahd_reg_print_t ahd_seqintsrc_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_currscb_print;
+-#else
+-#define ahd_currscb_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CURRSCB", 0x5c, regvalue, cur_col, wrap)
+-#endif
-
--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 */
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_seqimode_print;
+ #else
+ #define ahd_seqimode_print(regvalue, cur_col, wrap) \
+@@ -804,24 +636,17 @@ ahd_reg_print_t ahd_seqimode_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_mdffstat_print;
+-#else
+-#define ahd_mdffstat_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "MDFFSTAT", 0x5d, regvalue, cur_col, wrap)
+-#endif
-
--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);
--}
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_crccontrol_print;
++ahd_reg_print_t ahd_currscb_print;
+ #else
+-#define ahd_crccontrol_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CRCCONTROL", 0x5d, regvalue, cur_col, wrap)
++#define ahd_currscb_print(regvalue, cur_col, wrap) \
++ ahd_print_register(NULL, 0, "CURRSCB", 0x5c, regvalue, cur_col, wrap)
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dfftag_print;
++ahd_reg_print_t ahd_mdffstat_print;
+ #else
+-#define ahd_dfftag_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DFFTAG", 0x5e, regvalue, cur_col, wrap)
++#define ahd_mdffstat_print(regvalue, cur_col, wrap) \
++ ahd_print_register(NULL, 0, "MDFFSTAT", 0x5d, regvalue, cur_col, wrap)
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+@@ -832,20 +657,6 @@ ahd_reg_print_t ahd_lastscb_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_scsitest_print;
+-#else
+-#define ahd_scsitest_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SCSITEST", 0x5e, regvalue, cur_col, wrap)
+-#endif
-
--/**
-- * register qeth at sysfs
-- */
--static int
--qeth_sysfs_register(void)
--{
-- int rc;
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_iopdnctl_print;
+-#else
+-#define ahd_iopdnctl_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "IOPDNCTL", 0x5f, regvalue, cur_col, wrap)
+-#endif
-
-- rc = ccwgroup_driver_register(&qeth_ccwgroup_driver);
-- if (rc)
-- goto out;
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_shaddr_print;
+ #else
+ #define ahd_shaddr_print(regvalue, cur_col, wrap) \
+@@ -860,13 +671,6 @@ ahd_reg_print_t ahd_negoaddr_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dgrpcrci_print;
+-#else
+-#define ahd_dgrpcrci_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DGRPCRCI", 0x60, regvalue, cur_col, wrap)
+-#endif
-
-- rc = ccw_driver_register(&qeth_ccw_driver);
-- if (rc)
-- goto out_ccw_driver;
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_negperiod_print;
+ #else
+ #define ahd_negperiod_print(regvalue, cur_col, wrap) \
+@@ -874,13 +678,6 @@ ahd_reg_print_t ahd_negperiod_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_packcrci_print;
+-#else
+-#define ahd_packcrci_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "PACKCRCI", 0x62, regvalue, cur_col, wrap)
+-#endif
-
-- rc = qeth_create_driver_attributes();
-- if (rc)
-- goto out_qeth_attr;
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_negoffset_print;
+ #else
+ #define ahd_negoffset_print(regvalue, cur_col, wrap) \
+@@ -930,13 +727,6 @@ ahd_reg_print_t ahd_iownid_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_pll960ctl0_print;
+-#else
+-#define ahd_pll960ctl0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "PLL960CTL0", 0x68, regvalue, cur_col, wrap)
+-#endif
-
-- qeth_root_dev = s390_root_dev_register("qeth");
-- rc = IS_ERR(qeth_root_dev) ? PTR_ERR(qeth_root_dev) : 0;
-- if (!rc)
-- goto out;
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_shcnt_print;
+ #else
+ #define ahd_shcnt_print(regvalue, cur_col, wrap) \
+@@ -951,27 +741,6 @@ ahd_reg_print_t ahd_townid_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_pll960ctl1_print;
+-#else
+-#define ahd_pll960ctl1_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "PLL960CTL1", 0x69, regvalue, cur_col, wrap)
+-#endif
-
-- 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;
--}
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_pll960cnt0_print;
+-#else
+-#define ahd_pll960cnt0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "PLL960CNT0", 0x6a, regvalue, cur_col, wrap)
+-#endif
-
--/***
-- * init function
-- */
--static int __init
--qeth_init(void)
--{
-- int rc;
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_xsig_print;
+-#else
+-#define ahd_xsig_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "XSIG", 0x6a, regvalue, cur_col, wrap)
+-#endif
-
-- PRINT_INFO("loading %s\n", version);
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_seloid_print;
+ #else
+ #define ahd_seloid_print(regvalue, cur_col, wrap) \
+@@ -979,41 +748,6 @@ ahd_reg_print_t ahd_seloid_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_pll400ctl0_print;
+-#else
+-#define ahd_pll400ctl0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "PLL400CTL0", 0x6c, regvalue, cur_col, wrap)
+-#endif
-
-- 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);
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_fairness_print;
+-#else
+-#define ahd_fairness_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "FAIRNESS", 0x6c, regvalue, cur_col, wrap)
+-#endif
-
-- rc = qeth_register_dbf_views();
-- if (rc)
-- goto out_err;
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_pll400ctl1_print;
+-#else
+-#define ahd_pll400ctl1_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "PLL400CTL1", 0x6d, regvalue, cur_col, wrap)
+-#endif
-
-- rc = qeth_sysfs_register();
-- if (rc)
-- goto out_dbf;
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_unfairness_print;
+-#else
+-#define ahd_unfairness_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap)
+-#endif
-
--#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;
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_pll400cnt0_print;
+-#else
+-#define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap)
+-#endif
-
-- return rc;
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_haddr_print;
+ #else
+ #define ahd_haddr_print(regvalue, cur_col, wrap) \
+@@ -1021,27 +755,6 @@ ahd_reg_print_t ahd_haddr_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_plldelay_print;
+-#else
+-#define ahd_plldelay_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "PLLDELAY", 0x70, regvalue, cur_col, wrap)
+-#endif
-
--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;
--}
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_hodmaadr_print;
+-#else
+-#define ahd_hodmaadr_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "HODMAADR", 0x70, regvalue, cur_col, wrap)
+-#endif
-
--static void
--__exit qeth_exit(void)
--{
-- struct qeth_card *card, *tmp;
-- unsigned long flags;
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_hodmacnt_print;
+-#else
+-#define ahd_hodmacnt_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "HODMACNT", 0x78, regvalue, cur_col, wrap)
+-#endif
-
-- QETH_DBF_TEXT(trace,1, "cleanup.");
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_hcnt_print;
+ #else
+ #define ahd_hcnt_print(regvalue, cur_col, wrap) \
+@@ -1049,10 +762,10 @@ ahd_reg_print_t ahd_hcnt_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_hodmaen_print;
++ahd_reg_print_t ahd_sghaddr_print;
+ #else
+-#define ahd_hodmaen_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "HODMAEN", 0x7a, regvalue, cur_col, wrap)
++#define ahd_sghaddr_print(regvalue, cur_col, wrap) \
++ ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap)
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+@@ -1063,10 +776,10 @@ ahd_reg_print_t ahd_scbhaddr_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_sghaddr_print;
++ahd_reg_print_t ahd_sghcnt_print;
+ #else
+-#define ahd_sghaddr_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap)
++#define ahd_sghcnt_print(regvalue, cur_col, wrap) \
++ ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap)
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+@@ -1077,13 +790,6 @@ ahd_reg_print_t ahd_scbhcnt_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_sghcnt_print;
+-#else
+-#define ahd_sghcnt_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap)
+-#endif
-
-- /*
-- * 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();
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_dff_thrsh_print;
+ #else
+ #define ahd_dff_thrsh_print(regvalue, cur_col, wrap) \
+@@ -1091,132 +797,6 @@ ahd_reg_print_t ahd_dff_thrsh_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_romaddr_print;
+-#else
+-#define ahd_romaddr_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "ROMADDR", 0x8a, regvalue, cur_col, wrap)
-#endif
-- qeth_unregister_notifiers();
-- qeth_remove_procfs_entries();
-- qeth_sysfs_unregister();
-- qeth_unregister_dbf_views();
-- printk("qeth: removed\n");
--}
-
--EXPORT_SYMBOL(qeth_osn_register);
--EXPORT_SYMBOL(qeth_osn_deregister);
--EXPORT_SYMBOL(qeth_osn_assist);
--module_init(qeth_init);
--module_exit(qeth_exit);
--MODULE_AUTHOR("Frank Pavlic <fpavlic at de.ibm.com>");
--MODULE_DESCRIPTION("Linux on zSeries OSA Express and HiperSockets support\n" \
-- "Copyright 2000,2003 IBM Corporation\n");
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_romcntrl_print;
+-#else
+-#define ahd_romcntrl_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "ROMCNTRL", 0x8d, regvalue, cur_col, wrap)
+-#endif
-
--MODULE_LICENSE("GPL");
-diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c
-deleted file mode 100644
-index f29a4bc..0000000
---- a/drivers/s390/net/qeth_mpc.c
-+++ /dev/null
-@@ -1,269 +0,0 @@
--/*
-- * linux/drivers/s390/net/qeth_mpc.c
-- *
-- * Linux on zSeries OSA Express and HiperSockets support
-- *
-- * Copyright 2000,2003 IBM Corporation
-- * Author(s): Frank Pavlic <fpavlic at de.ibm.com>
-- * Thomas Spatzier <tspat at de.ibm.com>
-- *
-- */
--#include <asm/cio.h>
--#include "qeth_mpc.h"
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_romdata_print;
+-#else
+-#define ahd_romdata_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "ROMDATA", 0x8e, regvalue, cur_col, wrap)
+-#endif
-
--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
--};
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_cmcrxmsg0_print;
+-#else
+-#define ahd_cmcrxmsg0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CMCRXMSG0", 0x90, regvalue, cur_col, wrap)
+-#endif
-
--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
--};
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_roenable_print;
+-#else
+-#define ahd_roenable_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "ROENABLE", 0x90, regvalue, cur_col, wrap)
+-#endif
-
--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
--};
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_ovlyrxmsg0_print;
+-#else
+-#define ahd_ovlyrxmsg0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "OVLYRXMSG0", 0x90, regvalue, cur_col, wrap)
+-#endif
-
--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
--};
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dchrxmsg0_print;
+-#else
+-#define ahd_dchrxmsg0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DCHRXMSG0", 0x90, regvalue, cur_col, wrap)
+-#endif
-
--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
--};
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_ovlyrxmsg1_print;
+-#else
+-#define ahd_ovlyrxmsg1_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "OVLYRXMSG1", 0x91, regvalue, cur_col, wrap)
+-#endif
-
--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
--};
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_nsenable_print;
+-#else
+-#define ahd_nsenable_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "NSENABLE", 0x91, regvalue, cur_col, wrap)
+-#endif
-
--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
--};
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_cmcrxmsg1_print;
+-#else
+-#define ahd_cmcrxmsg1_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CMCRXMSG1", 0x91, regvalue, cur_col, wrap)
+-#endif
-
--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,
--};
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dchrxmsg1_print;
+-#else
+-#define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap)
+-#endif
-
--unsigned char WRITE_CCW[]={
-- 0x01,CCW_FLAG_SLI,0,0,
-- 0,0,0,0
--};
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dchrxmsg2_print;
+-#else
+-#define ahd_dchrxmsg2_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DCHRXMSG2", 0x92, regvalue, cur_col, wrap)
+-#endif
-
--unsigned char READ_CCW[]={
-- 0x02,CCW_FLAG_SLI,0,0,
-- 0,0,0,0
--};
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_cmcrxmsg2_print;
+-#else
+-#define ahd_cmcrxmsg2_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CMCRXMSG2", 0x92, regvalue, cur_col, wrap)
+-#endif
-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_ost_print;
+-#else
+-#define ahd_ost_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "OST", 0x92, regvalue, cur_col, wrap)
+-#endif
-
--struct ipa_rc_msg {
-- enum qeth_ipa_return_codes rc;
-- char *msg;
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_ovlyrxmsg2_print;
+-#else
+-#define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dchrxmsg3_print;
+-#else
+-#define ahd_dchrxmsg3_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DCHRXMSG3", 0x93, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_ovlyrxmsg3_print;
+-#else
+-#define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_cmcrxmsg3_print;
+-#else
+-#define ahd_cmcrxmsg3_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CMCRXMSG3", 0x93, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_pcixctl_print;
+ #else
+ #define ahd_pcixctl_print(regvalue, cur_col, wrap) \
+@@ -1224,34 +804,6 @@ ahd_reg_print_t ahd_pcixctl_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_ovlyseqbcnt_print;
+-#else
+-#define ahd_ovlyseqbcnt_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "OVLYSEQBCNT", 0x94, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dchseqbcnt_print;
+-#else
+-#define ahd_dchseqbcnt_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DCHSEQBCNT", 0x94, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_cmcseqbcnt_print;
+-#else
+-#define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_cmcspltstat0_print;
+-#else
+-#define ahd_cmcspltstat0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CMCSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_dchspltstat0_print;
+ #else
+ #define ahd_dchspltstat0_print(regvalue, cur_col, wrap) \
+@@ -1259,27 +811,6 @@ ahd_reg_print_t ahd_dchspltstat0_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_ovlyspltstat0_print;
+-#else
+-#define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_cmcspltstat1_print;
+-#else
+-#define ahd_cmcspltstat1_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CMCSPLTSTAT1", 0x97, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_ovlyspltstat1_print;
+-#else
+-#define ahd_ovlyspltstat1_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "OVLYSPLTSTAT1", 0x97, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_dchspltstat1_print;
+ #else
+ #define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \
+@@ -1287,90 +818,6 @@ ahd_reg_print_t ahd_dchspltstat1_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_sgrxmsg0_print;
+-#else
+-#define ahd_sgrxmsg0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SGRXMSG0", 0x98, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_slvspltoutadr0_print;
+-#else
+-#define ahd_slvspltoutadr0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SLVSPLTOUTADR0", 0x98, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_sgrxmsg1_print;
+-#else
+-#define ahd_sgrxmsg1_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SGRXMSG1", 0x99, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_slvspltoutadr1_print;
+-#else
+-#define ahd_slvspltoutadr1_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SLVSPLTOUTADR1", 0x99, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_sgrxmsg2_print;
+-#else
+-#define ahd_sgrxmsg2_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SGRXMSG2", 0x9a, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_slvspltoutadr2_print;
+-#else
+-#define ahd_slvspltoutadr2_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SLVSPLTOUTADR2", 0x9a, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_sgrxmsg3_print;
+-#else
+-#define ahd_sgrxmsg3_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SGRXMSG3", 0x9b, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_slvspltoutadr3_print;
+-#else
+-#define ahd_slvspltoutadr3_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SLVSPLTOUTADR3", 0x9b, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_sgseqbcnt_print;
+-#else
+-#define ahd_sgseqbcnt_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SGSEQBCNT", 0x9c, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_slvspltoutattr0_print;
+-#else
+-#define ahd_slvspltoutattr0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SLVSPLTOUTATTR0", 0x9c, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_slvspltoutattr1_print;
+-#else
+-#define ahd_slvspltoutattr1_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SLVSPLTOUTATTR1", 0x9d, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_slvspltoutattr2_print;
+-#else
+-#define ahd_slvspltoutattr2_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SLVSPLTOUTATTR2", 0x9e, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_sgspltstat0_print;
+ #else
+ #define ahd_sgspltstat0_print(regvalue, cur_col, wrap) \
+@@ -1385,13 +832,6 @@ ahd_reg_print_t ahd_sgspltstat1_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_sfunct_print;
+-#else
+-#define ahd_sfunct_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_df0pcistat_print;
+ #else
+ #define ahd_df0pcistat_print(regvalue, cur_col, wrap) \
+@@ -1406,41 +846,6 @@ ahd_reg_print_t ahd_reg0_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_df1pcistat_print;
+-#else
+-#define ahd_df1pcistat_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DF1PCISTAT", 0xa1, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_sgpcistat_print;
+-#else
+-#define ahd_sgpcistat_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SGPCISTAT", 0xa2, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_reg1_print;
+-#else
+-#define ahd_reg1_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "REG1", 0xa2, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_cmcpcistat_print;
+-#else
+-#define ahd_cmcpcistat_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CMCPCISTAT", 0xa3, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_ovlypcistat_print;
+-#else
+-#define ahd_ovlypcistat_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "OVLYPCISTAT", 0xa4, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_reg_isr_print;
+ #else
+ #define ahd_reg_isr_print(regvalue, cur_col, wrap) \
+@@ -1455,13 +860,6 @@ ahd_reg_print_t ahd_sg_state_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_msipcistat_print;
+-#else
+-#define ahd_msipcistat_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "MSIPCISTAT", 0xa6, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_targpcistat_print;
+ #else
+ #define ahd_targpcistat_print(regvalue, cur_col, wrap) \
+@@ -1469,13 +867,6 @@ ahd_reg_print_t ahd_targpcistat_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_data_count_odd_print;
+-#else
+-#define ahd_data_count_odd_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DATA_COUNT_ODD", 0xa7, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_scbptr_print;
+ #else
+ #define ahd_scbptr_print(regvalue, cur_col, wrap) \
+@@ -1483,13 +874,6 @@ ahd_reg_print_t ahd_scbptr_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_ccscbacnt_print;
+-#else
+-#define ahd_ccscbacnt_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CCSCBACNT", 0xab, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_scbautoptr_print;
+ #else
+ #define ahd_scbautoptr_print(regvalue, cur_col, wrap) \
+@@ -1504,13 +888,6 @@ ahd_reg_print_t ahd_ccsgaddr_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_ccscbadr_bk_print;
+-#else
+-#define ahd_ccscbadr_bk_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_ccscbaddr_print;
+ #else
+ #define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \
+@@ -1518,13 +895,6 @@ ahd_reg_print_t ahd_ccscbaddr_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_cmc_rambist_print;
+-#else
+-#define ahd_cmc_rambist_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "CMC_RAMBIST", 0xad, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_ccscbctl_print;
+ #else
+ #define ahd_ccscbctl_print(regvalue, cur_col, wrap) \
+@@ -1546,13 +916,6 @@ ahd_reg_print_t ahd_ccsgram_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_flexadr_print;
+-#else
+-#define ahd_flexadr_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "FLEXADR", 0xb0, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_ccscbram_print;
+ #else
+ #define ahd_ccscbram_print(regvalue, cur_col, wrap) \
+@@ -1560,27 +923,6 @@ ahd_reg_print_t ahd_ccscbram_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_flexcnt_print;
+-#else
+-#define ahd_flexcnt_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "FLEXCNT", 0xb3, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_flexdmastat_print;
+-#else
+-#define ahd_flexdmastat_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "FLEXDMASTAT", 0xb5, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_flexdata_print;
+-#else
+-#define ahd_flexdata_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "FLEXDATA", 0xb6, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_brddat_print;
+ #else
+ #define ahd_brddat_print(regvalue, cur_col, wrap) \
+@@ -1623,27 +965,6 @@ ahd_reg_print_t ahd_seestat_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_scbcnt_print;
+-#else
+-#define ahd_scbcnt_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SCBCNT", 0xbf, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dfwaddr_print;
+-#else
+-#define ahd_dfwaddr_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DFWADDR", 0xc0, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dspfltrctl_print;
+-#else
+-#define ahd_dspfltrctl_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DSPFLTRCTL", 0xc0, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_dspdatactl_print;
+ #else
+ #define ahd_dspdatactl_print(regvalue, cur_col, wrap) \
+@@ -1651,27 +972,6 @@ ahd_reg_print_t ahd_dspdatactl_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dfraddr_print;
+-#else
+-#define ahd_dfraddr_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DFRADDR", 0xc2, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dspreqctl_print;
+-#else
+-#define ahd_dspreqctl_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DSPREQCTL", 0xc2, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dspackctl_print;
+-#else
+-#define ahd_dspackctl_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DSPACKCTL", 0xc3, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_dfdat_print;
+ #else
+ #define ahd_dfdat_print(regvalue, cur_col, wrap) \
+@@ -1693,76 +993,6 @@ ahd_reg_print_t ahd_wrtbiasctl_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_rcvrbiosctl_print;
+-#else
+-#define ahd_rcvrbiosctl_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "RCVRBIOSCTL", 0xc6, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_wrtbiascalc_print;
+-#else
+-#define ahd_wrtbiascalc_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "WRTBIASCALC", 0xc7, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_rcvrbiascalc_print;
+-#else
+-#define ahd_rcvrbiascalc_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "RCVRBIASCALC", 0xc8, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dfptrs_print;
+-#else
+-#define ahd_dfptrs_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_skewcalc_print;
+-#else
+-#define ahd_skewcalc_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SKEWCALC", 0xc9, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dfbkptr_print;
+-#else
+-#define ahd_dfbkptr_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dfdbctl_print;
+-#else
+-#define ahd_dfdbctl_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DFDBCTL", 0xcb, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dfscnt_print;
+-#else
+-#define ahd_dfscnt_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DFSCNT", 0xcc, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_dfbcnt_print;
+-#else
+-#define ahd_dfbcnt_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "DFBCNT", 0xce, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_ovlyaddr_print;
+-#else
+-#define ahd_ovlyaddr_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "OVLYADDR", 0xd4, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_seqctl0_print;
+ #else
+ #define ahd_seqctl0_print(regvalue, cur_col, wrap) \
+@@ -1770,13 +1000,6 @@ ahd_reg_print_t ahd_seqctl0_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_seqctl1_print;
+-#else
+-#define ahd_seqctl1_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SEQCTL1", 0xd7, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_flags_print;
+ #else
+ #define ahd_flags_print(regvalue, cur_col, wrap) \
+@@ -1826,20 +1049,6 @@ ahd_reg_print_t ahd_dindex_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_brkaddr0_print;
+-#else
+-#define ahd_brkaddr0_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "BRKADDR0", 0xe6, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_brkaddr1_print;
+-#else
+-#define ahd_brkaddr1_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_allones_print;
+ #else
+ #define ahd_allones_print(regvalue, cur_col, wrap) \
+@@ -1875,13 +1084,6 @@ ahd_reg_print_t ahd_dindir_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_function1_print;
+-#else
+-#define ahd_function1_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "FUNCTION1", 0xf0, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_stack_print;
+ #else
+ #define ahd_stack_print(regvalue, cur_col, wrap) \
+@@ -1903,13 +1105,6 @@ ahd_reg_print_t ahd_curaddr_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_lastaddr_print;
+-#else
+-#define ahd_lastaddr_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "LASTADDR", 0xf6, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_intvec2_addr_print;
+ #else
+ #define ahd_intvec2_addr_print(regvalue, cur_col, wrap) \
+@@ -1931,24 +1126,17 @@ ahd_reg_print_t ahd_accum_save_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_waiting_scb_tails_print;
+-#else
+-#define ahd_waiting_scb_tails_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "WAITING_SCB_TAILS", 0x100, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_ahd_pci_config_base_print;
++ahd_reg_print_t ahd_sram_base_print;
+ #else
+-#define ahd_ahd_pci_config_base_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "AHD_PCI_CONFIG_BASE", 0x100, regvalue, cur_col, wrap)
++#define ahd_sram_base_print(regvalue, cur_col, wrap) \
++ ahd_print_register(NULL, 0, "SRAM_BASE", 0x100, regvalue, cur_col, wrap)
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_sram_base_print;
++ahd_reg_print_t ahd_waiting_scb_tails_print;
+ #else
+-#define ahd_sram_base_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SRAM_BASE", 0x100, regvalue, cur_col, wrap)
++#define ahd_waiting_scb_tails_print(regvalue, cur_col, wrap) \
++ ahd_print_register(NULL, 0, "WAITING_SCB_TAILS", 0x100, regvalue, cur_col, wrap)
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+@@ -2218,17 +1406,17 @@ ahd_reg_print_t ahd_mk_message_scsiid_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_scb_base_print;
++ahd_reg_print_t ahd_scb_residual_datacnt_print;
+ #else
+-#define ahd_scb_base_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SCB_BASE", 0x180, regvalue, cur_col, wrap)
++#define ahd_scb_residual_datacnt_print(regvalue, cur_col, wrap) \
++ ahd_print_register(NULL, 0, "SCB_RESIDUAL_DATACNT", 0x180, regvalue, cur_col, wrap)
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_scb_residual_datacnt_print;
++ahd_reg_print_t ahd_scb_base_print;
+ #else
+-#define ahd_scb_residual_datacnt_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SCB_RESIDUAL_DATACNT", 0x180, regvalue, cur_col, wrap)
++#define ahd_scb_base_print(regvalue, cur_col, wrap) \
++ ahd_print_register(NULL, 0, "SCB_BASE", 0x180, regvalue, cur_col, wrap)
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+@@ -2246,27 +1434,6 @@ ahd_reg_print_t ahd_scb_scsi_status_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_scb_target_phases_print;
+-#else
+-#define ahd_scb_target_phases_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SCB_TARGET_PHASES", 0x189, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_scb_target_data_dir_print;
+-#else
+-#define ahd_scb_target_data_dir_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SCB_TARGET_DATA_DIR", 0x18a, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_scb_target_itag_print;
+-#else
+-#define ahd_scb_target_itag_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SCB_TARGET_ITAG", 0x18b, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_scb_sense_busaddr_print;
+ #else
+ #define ahd_scb_sense_busaddr_print(regvalue, cur_col, wrap) \
+@@ -2365,13 +1532,6 @@ ahd_reg_print_t ahd_scb_next2_print;
+ #endif
+
+ #if AIC_DEBUG_REGISTERS
+-ahd_reg_print_t ahd_scb_spare_print;
+-#else
+-#define ahd_scb_spare_print(regvalue, cur_col, wrap) \
+- ahd_print_register(NULL, 0, "SCB_SPARE", 0x1b0, regvalue, cur_col, wrap)
+-#endif
+-
+-#if AIC_DEBUG_REGISTERS
+ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #else
+ #define ahd_scb_disconnected_lists_print(regvalue, cur_col, wrap) \
+@@ -2557,10 +1717,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+
+ #define SG_CACHE_PRE 0x1b
+
+-#define LQIN 0x20
+-
+ #define TYPEPTR 0x20
+
++#define LQIN 0x20
++
+ #define TAGPTR 0x21
+
+ #define LUNPTR 0x22
+@@ -2620,14 +1780,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define SINGLECMD 0x02
+ #define ABORTPENDING 0x01
+
+-#define SCSBIST0 0x39
+-#define GSBISTERR 0x40
+-#define GSBISTDONE 0x20
+-#define GSBISTRUN 0x10
+-#define OSBISTERR 0x04
+-#define OSBISTDONE 0x02
+-#define OSBISTRUN 0x01
+-
+ #define LQCTL2 0x39
+ #define LQIRETRY 0x80
+ #define LQICONTINUE 0x40
+@@ -2638,10 +1790,13 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define LQOTOIDLE 0x02
+ #define LQOPAUSE 0x01
+
+-#define SCSBIST1 0x3a
+-#define NTBISTERR 0x04
+-#define NTBISTDONE 0x02
+-#define NTBISTRUN 0x01
++#define SCSBIST0 0x39
++#define GSBISTERR 0x40
++#define GSBISTDONE 0x20
++#define GSBISTRUN 0x10
++#define OSBISTERR 0x04
++#define OSBISTDONE 0x02
++#define OSBISTRUN 0x01
+
+ #define SCSISEQ0 0x3a
+ #define TEMODEO 0x80
+@@ -2650,8 +1805,15 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define FORCEBUSFREE 0x10
+ #define SCSIRSTO 0x01
+
++#define SCSBIST1 0x3a
++#define NTBISTERR 0x04
++#define NTBISTDONE 0x02
++#define NTBISTRUN 0x01
++
+ #define SCSISEQ1 0x3b
+
++#define BUSINITID 0x3c
++
+ #define SXFRCTL0 0x3c
+ #define DFON 0x80
+ #define DFPEXP 0x40
+@@ -2660,8 +1822,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+
+ #define DLCOUNT 0x3c
+
+-#define BUSINITID 0x3c
+-
+ #define SXFRCTL1 0x3d
+ #define BITBUCKET 0x80
+ #define ENSACHK 0x40
+@@ -2686,6 +1846,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define CURRFIFO_1 0x01
+ #define CURRFIFO_0 0x00
+
++#define MULTARGID 0x40
++
+ #define SCSISIGO 0x40
+ #define CDO 0x80
+ #define IOO 0x40
+@@ -2696,8 +1858,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define REQO 0x02
+ #define ACKO 0x01
+
+-#define MULTARGID 0x40
+-
+ #define SCSISIGI 0x41
+ #define ATNI 0x10
+ #define SELI 0x08
+@@ -2744,15 +1904,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define ENAB20 0x04
+ #define SELWIDE 0x02
+
+-#define CLRSINT0 0x4b
+-#define CLRSELDO 0x40
+-#define CLRSELDI 0x20
+-#define CLRSELINGO 0x10
+-#define CLRIOERR 0x08
+-#define CLROVERRUN 0x04
+-#define CLRSPIORDY 0x02
+-#define CLRARBDO 0x01
+-
+ #define SSTAT0 0x4b
+ #define TARGET 0x80
+ #define SELDO 0x40
+@@ -2772,14 +1923,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define ENSPIORDY 0x02
+ #define ENARBDO 0x01
+
+-#define CLRSINT1 0x4c
+-#define CLRSELTIMEO 0x80
+-#define CLRATNO 0x40
+-#define CLRSCSIRSTI 0x20
+-#define CLRBUSFREE 0x08
+-#define CLRSCSIPERR 0x04
+-#define CLRSTRB2FAST 0x02
+-#define CLRREQINIT 0x01
++#define CLRSINT0 0x4b
++#define CLRSELDO 0x40
++#define CLRSELDI 0x20
++#define CLRSELINGO 0x10
++#define CLRIOERR 0x08
++#define CLROVERRUN 0x04
++#define CLRSPIORDY 0x02
++#define CLRARBDO 0x01
+
+ #define SSTAT1 0x4c
+ #define SELTO 0x80
+@@ -2791,6 +1942,15 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define STRB2FAST 0x02
+ #define REQINIT 0x01
+
++#define CLRSINT1 0x4c
++#define CLRSELTIMEO 0x80
++#define CLRATNO 0x40
++#define CLRSCSIRSTI 0x20
++#define CLRBUSFREE 0x08
++#define CLRSCSIPERR 0x04
++#define CLRSTRB2FAST 0x02
++#define CLRREQINIT 0x01
++
+ #define SSTAT2 0x4d
+ #define BUSFREETIME 0xc0
+ #define NONPACKREQ 0x20
+@@ -2838,14 +1998,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define LQIATNLQ 0x02
+ #define LQIATNCMD 0x01
+
+-#define CLRLQIINT0 0x50
+-#define CLRLQIATNQAS 0x20
+-#define CLRLQICRCT1 0x10
+-#define CLRLQICRCT2 0x08
+-#define CLRLQIBADLQT 0x04
+-#define CLRLQIATNLQ 0x02
+-#define CLRLQIATNCMD 0x01
+-
+ #define LQIMODE0 0x50
+ #define ENLQIATNQASK 0x20
+ #define ENLQICRCT1 0x10
+@@ -2854,6 +2006,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define ENLQIATNLQ 0x02
+ #define ENLQIATNCMD 0x01
+
++#define CLRLQIINT0 0x50
++#define CLRLQIATNQAS 0x20
++#define CLRLQICRCT1 0x10
++#define CLRLQICRCT2 0x08
++#define CLRLQIBADLQT 0x04
++#define CLRLQIATNLQ 0x02
++#define CLRLQIATNCMD 0x01
++
+ #define LQIMODE1 0x51
+ #define ENLQIPHASE_LQ 0x80
+ #define ENLQIPHASE_NLQ 0x40
+@@ -2976,6 +2136,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+
+ #define LQOSCSCTL 0x5a
+ #define LQOH2A_VERSION 0x80
++#define LQOBUSETDLY 0x40
++#define LQONOHOLDLACK 0x02
+ #define LQONOCHKOVER 0x01
+
+ #define NEXTSCB 0x5a
+@@ -2998,8 +2160,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define CFG4ICMD 0x02
+ #define CFG4TCMD 0x01
+
+-#define CURRSCB 0x5c
+-
+ #define SEQIMODE 0x5c
+ #define ENCTXTDONE 0x40
+ #define ENSAVEPTRS 0x20
+@@ -3009,6 +2169,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define ENCFG4ICMD 0x02
+ #define ENCFG4TCMD 0x01
+
++#define CURRSCB 0x5c
++
+ #define MDFFSTAT 0x5d
+ #define SHCNTNEGATIVE 0x40
+ #define SHCNTMINUS1 0x20
+@@ -3023,29 +2185,29 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+
+ #define DFFTAG 0x5e
+
+-#define LASTSCB 0x5e
+-
+ #define SCSITEST 0x5e
+ #define CNTRTEST 0x08
+ #define SEL_TXPLL_DEBUG 0x04
+
++#define LASTSCB 0x5e
++
+ #define IOPDNCTL 0x5f
+ #define DISABLE_OE 0x80
+ #define PDN_IDIST 0x04
+ #define PDN_DIFFSENSE 0x01
+
++#define DGRPCRCI 0x60
++
+ #define SHADDR 0x60
+
+ #define NEGOADDR 0x60
+
+-#define DGRPCRCI 0x60
+-
+ #define NEGPERIOD 0x61
+
+-#define PACKCRCI 0x62
+-
+ #define NEGOFFSET 0x62
+
++#define PACKCRCI 0x62
++
+ #define NEGPPROPTS 0x63
+ #define PPROPT_PACE 0x08
+ #define PPROPT_QAS 0x04
+@@ -3066,6 +2228,7 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define ANNEXDAT 0x66
+
+ #define SCSCHKN 0x66
++#define BIDICHKDIS 0x80
+ #define STSELSKIDDIS 0x40
+ #define CURRFIFODEF 0x20
+ #define WIDERESEN 0x10
+@@ -3090,6 +2253,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+
+ #define SELOID 0x6b
+
++#define FAIRNESS 0x6c
++
+ #define PLL400CTL0 0x6c
+ #define PLL_VCOSEL 0x80
+ #define PLL_PWDN 0x40
+@@ -3099,8 +2264,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define PLL_DLPF 0x02
+ #define PLL_ENFBM 0x01
+
+-#define FAIRNESS 0x6c
+-
+ #define PLL400CTL1 0x6d
+ #define PLL_CNTEN 0x80
+ #define PLL_CNTCLR 0x40
+@@ -3112,25 +2275,25 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+
+ #define HADDR 0x70
+
++#define HODMAADR 0x70
++
+ #define PLLDELAY 0x70
+ #define SPLIT_DROP_REQ 0x80
+
+-#define HODMAADR 0x70
++#define HCNT 0x78
+
+ #define HODMACNT 0x78
+
+-#define HCNT 0x78
+-
+ #define HODMAEN 0x7a
+
+-#define SCBHADDR 0x7c
+-
+ #define SGHADDR 0x7c
+
+-#define SCBHCNT 0x84
++#define SCBHADDR 0x7c
+
+ #define SGHCNT 0x84
+
++#define SCBHCNT 0x84
++
+ #define DFF_THRSH 0x88
+ #define WR_DFTHRSH 0x70
+ #define RD_DFTHRSH 0x07
+@@ -3163,6 +2326,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+
+ #define CMCRXMSG0 0x90
+
++#define OVLYRXMSG0 0x90
++
++#define DCHRXMSG0 0x90
++
+ #define ROENABLE 0x90
+ #define MSIROEN 0x20
+ #define OVLYROEN 0x10
+@@ -3171,11 +2338,11 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define DCH1ROEN 0x02
+ #define DCH0ROEN 0x01
+
+-#define OVLYRXMSG0 0x90
++#define OVLYRXMSG1 0x91
+
+-#define DCHRXMSG0 0x90
++#define CMCRXMSG1 0x91
+
+-#define OVLYRXMSG1 0x91
++#define DCHRXMSG1 0x91
+
+ #define NSENABLE 0x91
+ #define MSINSEN 0x20
+@@ -3185,10 +2352,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define DCH1NSEN 0x02
+ #define DCH0NSEN 0x01
+
+-#define CMCRXMSG1 0x91
+-
+-#define DCHRXMSG1 0x91
+-
+ #define DCHRXMSG2 0x92
+
+ #define CMCRXMSG2 0x92
+@@ -3212,24 +2375,24 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define TSCSERREN 0x02
+ #define CMPABCDIS 0x01
+
++#define CMCSEQBCNT 0x94
++
+ #define OVLYSEQBCNT 0x94
+
+ #define DCHSEQBCNT 0x94
+
+-#define CMCSEQBCNT 0x94
+-
+-#define CMCSPLTSTAT0 0x96
+-
+ #define DCHSPLTSTAT0 0x96
+
+ #define OVLYSPLTSTAT0 0x96
+
+-#define CMCSPLTSTAT1 0x97
++#define CMCSPLTSTAT0 0x96
+
+ #define OVLYSPLTSTAT1 0x97
+
+ #define DCHSPLTSTAT1 0x97
+
++#define CMCSPLTSTAT1 0x97
++
+ #define SGRXMSG0 0x98
+ #define CDNUM 0xf8
+ #define CFNUM 0x07
+@@ -3257,18 +2420,15 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define TAG_NUM 0x1f
+ #define RLXORD 0x10
+
+-#define SGSEQBCNT 0x9c
+-
+ #define SLVSPLTOUTATTR0 0x9c
+ #define LOWER_BCNT 0xff
+
++#define SGSEQBCNT 0x9c
++
+ #define SLVSPLTOUTATTR1 0x9d
+ #define CMPLT_DNUM 0xf8
+ #define CMPLT_FNUM 0x07
+
+-#define SLVSPLTOUTATTR2 0x9e
+-#define CMPLT_BNUM 0xff
+-
+ #define SGSPLTSTAT0 0x9e
+ #define STAETERM 0x80
+ #define SCBCERR 0x40
+@@ -3279,6 +2439,9 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define RXSCEMSG 0x02
+ #define RXSPLTRSP 0x01
+
++#define SLVSPLTOUTATTR2 0x9e
++#define CMPLT_BNUM 0xff
++
+ #define SGSPLTSTAT1 0x9f
+ #define RXDATABUCKET 0x01
+
+@@ -3334,10 +2497,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+
+ #define CCSGADDR 0xac
+
+-#define CCSCBADR_BK 0xac
+-
+ #define CCSCBADDR 0xac
+
++#define CCSCBADR_BK 0xac
++
+ #define CMC_RAMBIST 0xad
+ #define SG_ELEMENT_SIZE 0x80
+ #define SCBRAMBIST_FAIL 0x40
+@@ -3391,9 +2554,9 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define SEEDAT 0xbc
+
+ #define SEECTL 0xbe
++#define SEEOP_EWDS 0x40
+ #define SEEOP_WALL 0x40
+ #define SEEOP_EWEN 0x40
+-#define SEEOP_EWDS 0x40
+ #define SEEOPCODE 0x70
+ #define SEERST 0x02
+ #define SEESTART 0x01
+@@ -3410,25 +2573,25 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+
+ #define SCBCNT 0xbf
+
+-#define DFWADDR 0xc0
+-
+ #define DSPFLTRCTL 0xc0
+ #define FLTRDISABLE 0x20
+ #define EDGESENSE 0x10
+ #define DSPFCNTSEL 0x0f
+
++#define DFWADDR 0xc0
++
+ #define DSPDATACTL 0xc1
+ #define BYPASSENAB 0x80
+ #define DESQDIS 0x10
+ #define RCVROFFSTDIS 0x04
+ #define XMITOFFSTDIS 0x02
+
+-#define DFRADDR 0xc2
+-
+ #define DSPREQCTL 0xc2
+ #define MANREQCTL 0xc0
+ #define MANREQDLY 0x3f
+
++#define DFRADDR 0xc2
++
+ #define DSPACKCTL 0xc3
+ #define MANACKCTL 0xc0
+ #define MANACKDLY 0x3f
+@@ -3449,14 +2612,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+
+ #define WRTBIASCALC 0xc7
+
+-#define RCVRBIASCALC 0xc8
+-
+ #define DFPTRS 0xc8
+
+-#define SKEWCALC 0xc9
++#define RCVRBIASCALC 0xc8
+
+ #define DFBKPTR 0xc9
+
++#define SKEWCALC 0xc9
++
+ #define DFDBCTL 0xcb
+ #define DFF_CIO_WR_RDY 0x20
+ #define DFF_CIO_RD_RDY 0x10
+@@ -3541,12 +2704,12 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+
+ #define ACCUM_SAVE 0xfa
+
+-#define WAITING_SCB_TAILS 0x100
+-
+ #define AHD_PCI_CONFIG_BASE 0x100
+
+ #define SRAM_BASE 0x100
+
++#define WAITING_SCB_TAILS 0x100
++
+ #define WAITING_TID_HEAD 0x120
+
+ #define WAITING_TID_TAIL 0x122
+@@ -3575,8 +2738,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define PRELOADEN 0x80
+ #define WIDEODD 0x40
+ #define SCSIEN 0x20
+-#define SDMAEN 0x10
+ #define SDMAENACK 0x10
++#define SDMAEN 0x10
+ #define HDMAEN 0x08
+ #define HDMAENACK 0x08
+ #define DIRECTION 0x04
+@@ -3674,12 +2837,12 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+
+ #define MK_MESSAGE_SCSIID 0x162
+
+-#define SCB_BASE 0x180
+-
+ #define SCB_RESIDUAL_DATACNT 0x180
+ #define SCB_CDB_STORE 0x180
+ #define SCB_HOST_CDB_PTR 0x180
+
++#define SCB_BASE 0x180
++
+ #define SCB_RESIDUAL_SGPTR 0x184
+ #define SG_ADDR_MASK 0xf8
+ #define SG_OVERRUN_RESID 0x02
+@@ -3747,6 +2910,17 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define SCB_DISCONNECTED_LISTS 0x1b8
+
+
++#define CMD_GROUP_CODE_SHIFT 0x05
++#define STIMESEL_MIN 0x18
++#define STIMESEL_SHIFT 0x03
++#define INVALID_ADDR 0x80
++#define AHD_PRECOMP_MASK 0x07
++#define TARGET_DATA_IN 0x01
++#define CCSCBADDR_MAX 0x80
++#define NUMDSPS 0x14
++#define SEEOP_EWEN_ADDR 0xc0
++#define AHD_ANNEXCOL_PER_DEV0 0x04
++#define DST_MODE_SHIFT 0x04
+ #define AHD_TIMER_MAX_US 0x18ffe7
+ #define AHD_TIMER_MAX_TICKS 0xffff
+ #define AHD_SENSE_BUFSIZE 0x100
+@@ -3781,43 +2955,32 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
+ #define LUNLEN_SINGLE_LEVEL_LUN 0x0f
+ #define NVRAM_SCB_OFFSET 0x2c
+ #define STATUS_PKT_SENSE 0xff
+-#define CMD_GROUP_CODE_SHIFT 0x05
+ #define MAX_OFFSET_PACED_BUG 0x7f
+ #define STIMESEL_BUG_ADJ 0x08
+-#define STIMESEL_MIN 0x18
+-#define STIMESEL_SHIFT 0x03
+ #define CCSGRAM_MAXSEGS 0x10
+-#define INVALID_ADDR 0x80
+ #define SEEOP_ERAL_ADDR 0x80
+ #define AHD_SLEWRATE_DEF_REVB 0x08
+ #define AHD_PRECOMP_CUTBACK_17 0x04
+-#define AHD_PRECOMP_MASK 0x07
+ #define SRC_MODE_SHIFT 0x00
+ #define PKT_OVERRUN_BUFSIZE 0x200
+ #define SCB_TRANSFER_SIZE_1BYTE_LUN 0x30
+-#define TARGET_DATA_IN 0x01
+ #define HOST_MSG 0xff
+ #define MAX_OFFSET 0xfe
+ #define BUS_16_BIT 0x01
+-#define CCSCBADDR_MAX 0x80
+-#define NUMDSPS 0x14
+-#define SEEOP_EWEN_ADDR 0xc0
+-#define AHD_ANNEXCOL_PER_DEV0 0x04
+-#define DST_MODE_SHIFT 0x04
+
+
+ /* Downloaded Constant Definitions */
++#define SG_SIZEOF 0x04
++#define SG_PREFETCH_ALIGN_MASK 0x02
++#define SG_PREFETCH_CNT_LIMIT 0x01
+ #define CACHELINE_MASK 0x07
+ #define SCB_TRANSFER_SIZE 0x06
+ #define PKT_OVERRUN_BUFOFFSET 0x05
+-#define SG_SIZEOF 0x04
+ #define SG_PREFETCH_ADDR_MASK 0x03
+-#define SG_PREFETCH_ALIGN_MASK 0x02
+-#define SG_PREFETCH_CNT_LIMIT 0x01
+ #define SG_PREFETCH_CNT 0x00
+ #define DOWNLOAD_CONST_COUNT 0x08
+
+
+ /* Exported Labels */
+-#define LABEL_seq_isr 0x28f
+ #define LABEL_timer_isr 0x28b
++#define LABEL_seq_isr 0x28f
+diff --git a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
+index db38a61..c4c8a96 100644
+--- a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
++++ b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
+@@ -8,7 +8,7 @@
+
+ #include "aic79xx_osm.h"
+
+-static ahd_reg_parse_entry_t MODE_PTR_parse_table[] = {
++static const ahd_reg_parse_entry_t MODE_PTR_parse_table[] = {
+ { "SRC_MODE", 0x07, 0x07 },
+ { "DST_MODE", 0x70, 0x70 }
+ };
+@@ -20,7 +20,7 @@ ahd_mode_ptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x00, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t INTSTAT_parse_table[] = {
++static const ahd_reg_parse_entry_t INTSTAT_parse_table[] = {
+ { "SPLTINT", 0x01, 0x01 },
+ { "CMDCMPLT", 0x02, 0x02 },
+ { "SEQINT", 0x04, 0x04 },
+@@ -39,7 +39,7 @@ ahd_intstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x01, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SEQINTCODE_parse_table[] = {
++static const ahd_reg_parse_entry_t SEQINTCODE_parse_table[] = {
+ { "NO_SEQINT", 0x00, 0xff },
+ { "BAD_PHASE", 0x01, 0xff },
+ { "SEND_REJECT", 0x02, 0xff },
+@@ -76,7 +76,7 @@ ahd_seqintcode_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x02, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t CLRINT_parse_table[] = {
++static const ahd_reg_parse_entry_t CLRINT_parse_table[] = {
+ { "CLRSPLTINT", 0x01, 0x01 },
+ { "CLRCMDINT", 0x02, 0x02 },
+ { "CLRSEQINT", 0x04, 0x04 },
+@@ -94,7 +94,7 @@ ahd_clrint_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x03, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t ERROR_parse_table[] = {
++static const ahd_reg_parse_entry_t ERROR_parse_table[] = {
+ { "DSCTMOUT", 0x02, 0x02 },
+ { "ILLOPCODE", 0x04, 0x04 },
+ { "SQPARERR", 0x08, 0x08 },
+@@ -111,24 +111,7 @@ ahd_error_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x04, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t CLRERR_parse_table[] = {
+- { "CLRDSCTMOUT", 0x02, 0x02 },
+- { "CLRILLOPCODE", 0x04, 0x04 },
+- { "CLRSQPARERR", 0x08, 0x08 },
+- { "CLRDPARERR", 0x10, 0x10 },
+- { "CLRMPARERR", 0x20, 0x20 },
+- { "CLRCIOACCESFAIL", 0x40, 0x40 },
+- { "CLRCIOPARERR", 0x80, 0x80 }
-};
-
--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"}
+-int
+-ahd_clrerr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(CLRERR_parse_table, 7, "CLRERR",
+- 0x04, regvalue, cur_col, wrap));
+-}
+-
+-static ahd_reg_parse_entry_t HCNTRL_parse_table[] = {
++static const ahd_reg_parse_entry_t HCNTRL_parse_table[] = {
+ { "CHIPRST", 0x01, 0x01 },
+ { "CHIPRSTACK", 0x01, 0x01 },
+ { "INTEN", 0x02, 0x02 },
+@@ -160,7 +143,7 @@ ahd_hescb_qoff_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x08, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t HS_MAILBOX_parse_table[] = {
++static const ahd_reg_parse_entry_t HS_MAILBOX_parse_table[] = {
+ { "ENINT_COALESCE", 0x40, 0x40 },
+ { "HOST_TQINPOS", 0x80, 0x80 }
+ };
+@@ -172,7 +155,7 @@ ahd_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x0b, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SEQINTSTAT_parse_table[] = {
++static const ahd_reg_parse_entry_t SEQINTSTAT_parse_table[] = {
+ { "SEQ_SPLTINT", 0x01, 0x01 },
+ { "SEQ_PCIINT", 0x02, 0x02 },
+ { "SEQ_SCSIINT", 0x04, 0x04 },
+@@ -187,7 +170,7 @@ ahd_seqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x0c, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = {
++static const ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = {
+ { "CLRSEQ_SPLTINT", 0x01, 0x01 },
+ { "CLRSEQ_PCIINT", 0x02, 0x02 },
+ { "CLRSEQ_SCSIINT", 0x04, 0x04 },
+@@ -230,7 +213,7 @@ ahd_sdscb_qoff_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x14, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t QOFF_CTLSTA_parse_table[] = {
++static const ahd_reg_parse_entry_t QOFF_CTLSTA_parse_table[] = {
+ { "SCB_QSIZE_4", 0x00, 0x0f },
+ { "SCB_QSIZE_8", 0x01, 0x0f },
+ { "SCB_QSIZE_16", 0x02, 0x0f },
+@@ -258,7 +241,7 @@ ahd_qoff_ctlsta_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x16, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t INTCTL_parse_table[] = {
++static const ahd_reg_parse_entry_t INTCTL_parse_table[] = {
+ { "SPLTINTEN", 0x01, 0x01 },
+ { "SEQINTEN", 0x02, 0x02 },
+ { "SCSIINTEN", 0x04, 0x04 },
+@@ -276,7 +259,7 @@ ahd_intctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x18, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t DFCNTRL_parse_table[] = {
++static const ahd_reg_parse_entry_t DFCNTRL_parse_table[] = {
+ { "DIRECTIONEN", 0x01, 0x01 },
+ { "FIFOFLUSH", 0x02, 0x02 },
+ { "FIFOFLUSHACK", 0x02, 0x02 },
+@@ -297,7 +280,7 @@ ahd_dfcntrl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x19, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t DSCOMMAND0_parse_table[] = {
++static const ahd_reg_parse_entry_t DSCOMMAND0_parse_table[] = {
+ { "CIOPARCKEN", 0x01, 0x01 },
+ { "DISABLE_TWATE", 0x02, 0x02 },
+ { "EXTREQLCK", 0x10, 0x10 },
+@@ -313,7 +296,7 @@ ahd_dscommand0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x19, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t DFSTATUS_parse_table[] = {
++static const ahd_reg_parse_entry_t DFSTATUS_parse_table[] = {
+ { "FIFOEMP", 0x01, 0x01 },
+ { "FIFOFULL", 0x02, 0x02 },
+ { "DFTHRESH", 0x04, 0x04 },
+@@ -330,7 +313,7 @@ ahd_dfstatus_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x1a, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SG_CACHE_SHADOW_parse_table[] = {
++static const ahd_reg_parse_entry_t SG_CACHE_SHADOW_parse_table[] = {
+ { "LAST_SEG_DONE", 0x01, 0x01 },
+ { "LAST_SEG", 0x02, 0x02 },
+ { "ODD_SEG", 0x04, 0x04 },
+@@ -344,20 +327,7 @@ ahd_sg_cache_shadow_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x1b, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t ARBCTL_parse_table[] = {
+- { "USE_TIME", 0x07, 0x07 },
+- { "RETRY_SWEN", 0x08, 0x08 },
+- { "RESET_HARB", 0x80, 0x80 }
-};
-
+-int
+-ahd_arbctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(ARBCTL_parse_table, 3, "ARBCTL",
+- 0x1b, regvalue, cur_col, wrap));
+-}
+-
+-static ahd_reg_parse_entry_t SG_CACHE_PRE_parse_table[] = {
++static const ahd_reg_parse_entry_t SG_CACHE_PRE_parse_table[] = {
+ { "LAST_SEG", 0x02, 0x02 },
+ { "ODD_SEG", 0x04, 0x04 },
+ { "SG_ADDR_MASK", 0xf8, 0xf8 }
+@@ -378,20 +348,6 @@ ahd_lqin_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_typeptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "TYPEPTR",
+- 0x20, regvalue, cur_col, wrap));
+-}
-
+-int
+-ahd_tagptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "TAGPTR",
+- 0x21, regvalue, cur_col, wrap));
+-}
-
--char *
--qeth_get_ipa_msg(enum qeth_ipa_return_codes rc)
+-int
+ ahd_lunptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahd_print_register(NULL, 0, "LUNPTR",
+@@ -399,20 +355,6 @@ ahd_lunptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_datalenptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- 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;
+- return (ahd_print_register(NULL, 0, "DATALENPTR",
+- 0x23, regvalue, cur_col, wrap));
+-}
+-
+-int
+-ahd_statlenptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "STATLENPTR",
+- 0x24, regvalue, cur_col, wrap));
+-}
+-
+-int
+ ahd_cmdlenptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahd_print_register(NULL, 0, "CMDLENPTR",
+@@ -448,13 +390,6 @@ ahd_qnextptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_idptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "IDPTR",
+- 0x2a, regvalue, cur_col, wrap));
+-}
+-
+-int
+ ahd_abrtbyteptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahd_print_register(NULL, 0, "ABRTBYTEPTR",
+@@ -468,28 +403,7 @@ ahd_abrtbitptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x2c, regvalue, cur_col, wrap));
+ }
+
+-int
+-ahd_maxcmdbytes_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "MAXCMDBYTES",
+- 0x2d, regvalue, cur_col, wrap));
+-}
+-
+-int
+-ahd_maxcmd2rcv_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "MAXCMD2RCV",
+- 0x2e, regvalue, cur_col, wrap));
+-}
+-
+-int
+-ahd_shortthresh_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "SHORTTHRESH",
+- 0x2f, regvalue, cur_col, wrap));
+-}
+-
+-static ahd_reg_parse_entry_t LUNLEN_parse_table[] = {
++static const ahd_reg_parse_entry_t LUNLEN_parse_table[] = {
+ { "ILUNLEN", 0x0f, 0x0f },
+ { "TLUNLEN", 0xf0, 0xf0 }
+ };
+@@ -522,49 +436,7 @@ ahd_maxcmdcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x33, regvalue, cur_col, wrap));
+ }
+
+-int
+-ahd_lqrsvd01_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "LQRSVD01",
+- 0x34, regvalue, cur_col, wrap));
+-}
+-
+-int
+-ahd_lqrsvd16_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "LQRSVD16",
+- 0x35, regvalue, cur_col, wrap));
-}
-
+-int
+-ahd_lqrsvd17_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "LQRSVD17",
+- 0x36, regvalue, cur_col, wrap));
+-}
-
--struct ipa_cmd_names {
-- enum qeth_ipa_cmds cmd;
-- char *name;
--};
+-int
+-ahd_cmdrsvd0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "CMDRSVD0",
+- 0x37, regvalue, cur_col, wrap));
+-}
-
--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"},
+-static ahd_reg_parse_entry_t LQCTL0_parse_table[] = {
+- { "LQ0INITGCLT", 0x03, 0x03 },
+- { "LQ0TARGCLT", 0x0c, 0x0c },
+- { "LQIINITGCLT", 0x30, 0x30 },
+- { "LQITARGCLT", 0xc0, 0xc0 }
-};
-
--char *
--qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd)
+-int
+-ahd_lqctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- 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;
+- return (ahd_print_register(LQCTL0_parse_table, 4, "LQCTL0",
+- 0x38, regvalue, cur_col, wrap));
-}
-
+-static ahd_reg_parse_entry_t LQCTL1_parse_table[] = {
++static const ahd_reg_parse_entry_t LQCTL1_parse_table[] = {
+ { "ABORTPENDING", 0x01, 0x01 },
+ { "SINGLECMD", 0x02, 0x02 },
+ { "PCI2PCI", 0x04, 0x04 }
+@@ -577,23 +449,7 @@ ahd_lqctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x38, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SCSBIST0_parse_table[] = {
+- { "OSBISTRUN", 0x01, 0x01 },
+- { "OSBISTDONE", 0x02, 0x02 },
+- { "OSBISTERR", 0x04, 0x04 },
+- { "GSBISTRUN", 0x10, 0x10 },
+- { "GSBISTDONE", 0x20, 0x20 },
+- { "GSBISTERR", 0x40, 0x40 }
+-};
-
-diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h
-deleted file mode 100644
-index 6de2da5..0000000
---- a/drivers/s390/net/qeth_mpc.h
-+++ /dev/null
-@@ -1,583 +0,0 @@
--/*
-- * linux/drivers/s390/net/qeth_mpc.h
-- *
-- * Linux on zSeries OSA Express and HiperSockets support
-- *
-- * Copyright 2000,2003 IBM Corporation
-- * Author(s): Utz Bacher <utz.bacher at de.ibm.com>
-- * Thomas Spatzier <tspat at de.ibm.com>
-- * Frank Pavlic <fpavlic at de.ibm.com>
-- *
-- */
--#ifndef __QETH_MPC_H__
--#define __QETH_MPC_H__
+-int
+-ahd_scsbist0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(SCSBIST0_parse_table, 6, "SCSBIST0",
+- 0x39, regvalue, cur_col, wrap));
+-}
-
--#include <asm/qeth.h>
+-static ahd_reg_parse_entry_t LQCTL2_parse_table[] = {
++static const ahd_reg_parse_entry_t LQCTL2_parse_table[] = {
+ { "LQOPAUSE", 0x01, 0x01 },
+ { "LQOTOIDLE", 0x02, 0x02 },
+ { "LQOCONTINUE", 0x04, 0x04 },
+@@ -611,20 +467,7 @@ ahd_lqctl2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x39, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SCSBIST1_parse_table[] = {
+- { "NTBISTRUN", 0x01, 0x01 },
+- { "NTBISTDONE", 0x02, 0x02 },
+- { "NTBISTERR", 0x04, 0x04 }
+-};
-
--#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)
+-int
+-ahd_scsbist1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(SCSBIST1_parse_table, 3, "SCSBIST1",
+- 0x3a, regvalue, cur_col, wrap));
+-}
-
--extern unsigned char IPA_PDU_HEADER[];
--#define QETH_IPA_CMD_DEST_ADDR(buffer) (buffer+0x2c)
+-static ahd_reg_parse_entry_t SCSISEQ0_parse_table[] = {
++static const ahd_reg_parse_entry_t SCSISEQ0_parse_table[] = {
+ { "SCSIRSTO", 0x01, 0x01 },
+ { "FORCEBUSFREE", 0x10, 0x10 },
+ { "ENARBO", 0x20, 0x20 },
+@@ -639,7 +482,7 @@ ahd_scsiseq0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x3a, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SCSISEQ1_parse_table[] = {
++static const ahd_reg_parse_entry_t SCSISEQ1_parse_table[] = {
+ { "ALTSTIM", 0x01, 0x01 },
+ { "ENAUTOATNP", 0x02, 0x02 },
+ { "MANUALP", 0x0c, 0x0c },
+@@ -655,7 +498,7 @@ ahd_scsiseq1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x3b, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SXFRCTL0_parse_table[] = {
++static const ahd_reg_parse_entry_t SXFRCTL0_parse_table[] = {
+ { "SPIOEN", 0x08, 0x08 },
+ { "BIOSCANCELEN", 0x10, 0x10 },
+ { "DFPEXP", 0x40, 0x40 },
+@@ -669,21 +512,7 @@ ahd_sxfrctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x3c, regvalue, cur_col, wrap));
+ }
+
+-int
+-ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "DLCOUNT",
+- 0x3c, regvalue, cur_col, wrap));
+-}
-
--#define IPA_CMD_LENGTH (IPA_PDU_HEADER_SIZE + sizeof(struct qeth_ipa_cmd))
+-int
+-ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "BUSINITID",
+- 0x3c, regvalue, cur_col, wrap));
+-}
-
--#define QETH_SEQ_NO_LENGTH 4
--#define QETH_MPC_TOKEN_LENGTH 4
--#define QETH_MCL_LENGTH 4
--#define OSA_ADDR_LEN 6
+-static ahd_reg_parse_entry_t SXFRCTL1_parse_table[] = {
++static const ahd_reg_parse_entry_t SXFRCTL1_parse_table[] = {
+ { "STPWEN", 0x01, 0x01 },
+ { "ACTNEGEN", 0x02, 0x02 },
+ { "ENSTIMER", 0x04, 0x04 },
+@@ -700,27 +529,7 @@ ahd_sxfrctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x3d, regvalue, cur_col, wrap));
+ }
+
+-int
+-ahd_bustargid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "BUSTARGID",
+- 0x3e, regvalue, cur_col, wrap));
+-}
-
--#define QETH_TIMEOUT (10 * HZ)
--#define QETH_IPA_TIMEOUT (45 * HZ)
--#define QETH_IDX_COMMAND_SEQNO 0xffff0000
--#define SR_INFO_LEN 16
+-static ahd_reg_parse_entry_t SXFRCTL2_parse_table[] = {
+- { "ASU", 0x07, 0x07 },
+- { "CMDDMAEN", 0x08, 0x08 },
+- { "AUTORSTDIS", 0x10, 0x10 }
+-};
-
--#define QETH_CLEAR_CHANNEL_PARM -10
--#define QETH_HALT_CHANNEL_PARM -11
--#define QETH_RCD_PARM -12
+-int
+-ahd_sxfrctl2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(SXFRCTL2_parse_table, 3, "SXFRCTL2",
+- 0x3e, regvalue, cur_col, wrap));
+-}
-
--/*****************************************************************************/
--/* 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
+-static ahd_reg_parse_entry_t DFFSTAT_parse_table[] = {
++static const ahd_reg_parse_entry_t DFFSTAT_parse_table[] = {
+ { "CURRFIFO_0", 0x00, 0x03 },
+ { "CURRFIFO_1", 0x01, 0x03 },
+ { "CURRFIFO_NONE", 0x03, 0x03 },
+@@ -736,7 +545,14 @@ ahd_dffstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x3f, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SCSISIGO_parse_table[] = {
++int
++ahd_multargid_print(u_int regvalue, u_int *cur_col, u_int wrap)
++{
++ return (ahd_print_register(NULL, 0, "MULTARGID",
++ 0x40, regvalue, cur_col, wrap));
++}
++
++static const ahd_reg_parse_entry_t SCSISIGO_parse_table[] = {
+ { "P_DATAOUT", 0x00, 0xe0 },
+ { "P_DATAOUT_DT", 0x20, 0xe0 },
+ { "P_DATAIN", 0x40, 0xe0 },
+@@ -763,14 +579,7 @@ ahd_scsisigo_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x40, regvalue, cur_col, wrap));
+ }
+
+-int
+-ahd_multargid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "MULTARGID",
+- 0x40, regvalue, cur_col, wrap));
+-}
-
--enum qeth_card_types {
-- QETH_CARD_TYPE_UNKNOWN = 0,
-- QETH_CARD_TYPE_OSAE = 10,
-- QETH_CARD_TYPE_IQD = 1234,
-- QETH_CARD_TYPE_OSN = 11,
--};
+-static ahd_reg_parse_entry_t SCSISIGI_parse_table[] = {
++static const ahd_reg_parse_entry_t SCSISIGI_parse_table[] = {
+ { "P_DATAOUT", 0x00, 0xe0 },
+ { "P_DATAOUT_DT", 0x20, 0xe0 },
+ { "P_DATAIN", 0x40, 0xe0 },
+@@ -797,7 +606,7 @@ ahd_scsisigi_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x41, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SCSIPHASE_parse_table[] = {
++static const ahd_reg_parse_entry_t SCSIPHASE_parse_table[] = {
+ { "DATA_OUT_PHASE", 0x01, 0x03 },
+ { "DATA_IN_PHASE", 0x02, 0x03 },
+ { "DATA_PHASE_MASK", 0x03, 0x03 },
+@@ -815,13 +624,6 @@ ahd_scsiphase_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_scsidat0_img_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "SCSIDAT0_IMG",
+- 0x43, regvalue, cur_col, wrap));
+-}
-
--#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,
+-int
+ ahd_scsidat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahd_print_register(NULL, 0, "SCSIDAT",
+@@ -835,7 +637,7 @@ ahd_scsibus_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x46, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t TARGIDIN_parse_table[] = {
++static const ahd_reg_parse_entry_t TARGIDIN_parse_table[] = {
+ { "TARGID", 0x0f, 0x0f },
+ { "CLKOUT", 0x80, 0x80 }
+ };
+@@ -847,7 +649,7 @@ ahd_targidin_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x48, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SELID_parse_table[] = {
++static const ahd_reg_parse_entry_t SELID_parse_table[] = {
+ { "ONEBIT", 0x08, 0x08 },
+ { "SELID_MASK", 0xf0, 0xf0 }
+ };
+@@ -859,7 +661,7 @@ ahd_selid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x49, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t OPTIONMODE_parse_table[] = {
++static const ahd_reg_parse_entry_t OPTIONMODE_parse_table[] = {
+ { "AUTO_MSGOUT_DE", 0x02, 0x02 },
+ { "ENDGFORMCHK", 0x04, 0x04 },
+ { "BUSFREEREV", 0x10, 0x10 },
+@@ -876,7 +678,7 @@ ahd_optionmode_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x4a, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = {
++static const ahd_reg_parse_entry_t SBLKCTL_parse_table[] = {
+ { "SELWIDE", 0x02, 0x02 },
+ { "ENAB20", 0x04, 0x04 },
+ { "ENAB40", 0x08, 0x08 },
+@@ -891,24 +693,7 @@ ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x4a, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t CLRSINT0_parse_table[] = {
+- { "CLRARBDO", 0x01, 0x01 },
+- { "CLRSPIORDY", 0x02, 0x02 },
+- { "CLROVERRUN", 0x04, 0x04 },
+- { "CLRIOERR", 0x08, 0x08 },
+- { "CLRSELINGO", 0x10, 0x10 },
+- { "CLRSELDI", 0x20, 0x20 },
+- { "CLRSELDO", 0x40, 0x40 }
-};
-
--enum qeth_tr_macaddr_modes {
-- QETH_TR_MACADDR_NONCANONICAL = 0,
-- QETH_TR_MACADDR_CANONICAL = 1,
--};
+-int
+-ahd_clrsint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(CLRSINT0_parse_table, 7, "CLRSINT0",
+- 0x4b, regvalue, cur_col, wrap));
+-}
-
--enum qeth_tr_broadcast_modes {
-- QETH_TR_BROADCAST_ALLRINGS = 0,
-- QETH_TR_BROADCAST_LOCAL = 1,
+-static ahd_reg_parse_entry_t SSTAT0_parse_table[] = {
++static const ahd_reg_parse_entry_t SSTAT0_parse_table[] = {
+ { "ARBDO", 0x01, 0x01 },
+ { "SPIORDY", 0x02, 0x02 },
+ { "OVERRUN", 0x04, 0x04 },
+@@ -926,7 +711,7 @@ ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x4b, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SIMODE0_parse_table[] = {
++static const ahd_reg_parse_entry_t SIMODE0_parse_table[] = {
+ { "ENARBDO", 0x01, 0x01 },
+ { "ENSPIORDY", 0x02, 0x02 },
+ { "ENOVERRUN", 0x04, 0x04 },
+@@ -943,24 +728,24 @@ ahd_simode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x4b, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t CLRSINT1_parse_table[] = {
+- { "CLRREQINIT", 0x01, 0x01 },
+- { "CLRSTRB2FAST", 0x02, 0x02 },
+- { "CLRSCSIPERR", 0x04, 0x04 },
+- { "CLRBUSFREE", 0x08, 0x08 },
+- { "CLRSCSIRSTI", 0x20, 0x20 },
+- { "CLRATNO", 0x40, 0x40 },
+- { "CLRSELTIMEO", 0x80, 0x80 }
++static const ahd_reg_parse_entry_t CLRSINT0_parse_table[] = {
++ { "CLRARBDO", 0x01, 0x01 },
++ { "CLRSPIORDY", 0x02, 0x02 },
++ { "CLROVERRUN", 0x04, 0x04 },
++ { "CLRIOERR", 0x08, 0x08 },
++ { "CLRSELINGO", 0x10, 0x10 },
++ { "CLRSELDI", 0x20, 0x20 },
++ { "CLRSELDO", 0x40, 0x40 }
+ };
+
+ int
+-ahd_clrsint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
++ahd_clrsint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+- return (ahd_print_register(CLRSINT1_parse_table, 7, "CLRSINT1",
+- 0x4c, regvalue, cur_col, wrap));
++ return (ahd_print_register(CLRSINT0_parse_table, 7, "CLRSINT0",
++ 0x4b, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SSTAT1_parse_table[] = {
++static const ahd_reg_parse_entry_t SSTAT1_parse_table[] = {
+ { "REQINIT", 0x01, 0x01 },
+ { "STRB2FAST", 0x02, 0x02 },
+ { "SCSIPERR", 0x04, 0x04 },
+@@ -978,7 +763,24 @@ ahd_sstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x4c, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SSTAT2_parse_table[] = {
++static const ahd_reg_parse_entry_t CLRSINT1_parse_table[] = {
++ { "CLRREQINIT", 0x01, 0x01 },
++ { "CLRSTRB2FAST", 0x02, 0x02 },
++ { "CLRSCSIPERR", 0x04, 0x04 },
++ { "CLRBUSFREE", 0x08, 0x08 },
++ { "CLRSCSIRSTI", 0x20, 0x20 },
++ { "CLRATNO", 0x40, 0x40 },
++ { "CLRSELTIMEO", 0x80, 0x80 }
++};
++
++int
++ahd_clrsint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
++{
++ return (ahd_print_register(CLRSINT1_parse_table, 7, "CLRSINT1",
++ 0x4c, regvalue, cur_col, wrap));
++}
++
++static const ahd_reg_parse_entry_t SSTAT2_parse_table[] = {
+ { "BUSFREE_LQO", 0x40, 0xc0 },
+ { "BUSFREE_DFF0", 0x80, 0xc0 },
+ { "BUSFREE_DFF1", 0xc0, 0xc0 },
+@@ -998,20 +800,7 @@ ahd_sstat2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x4d, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SIMODE2_parse_table[] = {
+- { "ENDMADONE", 0x01, 0x01 },
+- { "ENSDONE", 0x02, 0x02 },
+- { "ENWIDE_RES", 0x04, 0x04 }
-};
-
--/* 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
+-int
+-ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2",
+- 0x4d, regvalue, cur_col, wrap));
+-}
-
--/*
-- * 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,
+-static ahd_reg_parse_entry_t CLRSINT2_parse_table[] = {
++static const ahd_reg_parse_entry_t CLRSINT2_parse_table[] = {
+ { "CLRDMADONE", 0x01, 0x01 },
+ { "CLRSDONE", 0x02, 0x02 },
+ { "CLRWIDE_RES", 0x04, 0x04 },
+@@ -1025,7 +814,7 @@ ahd_clrsint2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x4d, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t PERRDIAG_parse_table[] = {
++static const ahd_reg_parse_entry_t PERRDIAG_parse_table[] = {
+ { "DTERR", 0x01, 0x01 },
+ { "DGFORMERR", 0x02, 0x02 },
+ { "CRCERR", 0x04, 0x04 },
+@@ -1064,7 +853,7 @@ ahd_lqostate_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x4f, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t LQISTAT0_parse_table[] = {
++static const ahd_reg_parse_entry_t LQISTAT0_parse_table[] = {
+ { "LQIATNCMD", 0x01, 0x01 },
+ { "LQIATNLQ", 0x02, 0x02 },
+ { "LQIBADLQT", 0x04, 0x04 },
+@@ -1080,23 +869,7 @@ ahd_lqistat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x50, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t CLRLQIINT0_parse_table[] = {
+- { "CLRLQIATNCMD", 0x01, 0x01 },
+- { "CLRLQIATNLQ", 0x02, 0x02 },
+- { "CLRLQIBADLQT", 0x04, 0x04 },
+- { "CLRLQICRCT2", 0x08, 0x08 },
+- { "CLRLQICRCT1", 0x10, 0x10 },
+- { "CLRLQIATNQAS", 0x20, 0x20 }
-};
-
--/* 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
--};
+-int
+-ahd_clrlqiint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(CLRLQIINT0_parse_table, 6, "CLRLQIINT0",
+- 0x50, regvalue, cur_col, wrap));
+-}
-
--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,
--};
+-static ahd_reg_parse_entry_t LQIMODE0_parse_table[] = {
++static const ahd_reg_parse_entry_t LQIMODE0_parse_table[] = {
+ { "ENLQIATNCMD", 0x01, 0x01 },
+ { "ENLQIATNLQ", 0x02, 0x02 },
+ { "ENLQIBADLQT", 0x04, 0x04 },
+@@ -1112,7 +885,23 @@ ahd_lqimode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x50, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t LQIMODE1_parse_table[] = {
++static const ahd_reg_parse_entry_t CLRLQIINT0_parse_table[] = {
++ { "CLRLQIATNCMD", 0x01, 0x01 },
++ { "CLRLQIATNLQ", 0x02, 0x02 },
++ { "CLRLQIBADLQT", 0x04, 0x04 },
++ { "CLRLQICRCT2", 0x08, 0x08 },
++ { "CLRLQICRCT1", 0x10, 0x10 },
++ { "CLRLQIATNQAS", 0x20, 0x20 }
++};
++
++int
++ahd_clrlqiint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
++{
++ return (ahd_print_register(CLRLQIINT0_parse_table, 6, "CLRLQIINT0",
++ 0x50, regvalue, cur_col, wrap));
++}
++
++static const ahd_reg_parse_entry_t LQIMODE1_parse_table[] = {
+ { "ENLQIOVERI_NLQ", 0x01, 0x01 },
+ { "ENLQIOVERI_LQ", 0x02, 0x02 },
+ { "ENLQIBADLQI", 0x04, 0x04 },
+@@ -1130,7 +919,7 @@ ahd_lqimode1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x51, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t LQISTAT1_parse_table[] = {
++static const ahd_reg_parse_entry_t LQISTAT1_parse_table[] = {
+ { "LQIOVERI_NLQ", 0x01, 0x01 },
+ { "LQIOVERI_LQ", 0x02, 0x02 },
+ { "LQIBADLQI", 0x04, 0x04 },
+@@ -1148,7 +937,7 @@ ahd_lqistat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x51, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t CLRLQIINT1_parse_table[] = {
++static const ahd_reg_parse_entry_t CLRLQIINT1_parse_table[] = {
+ { "CLRLQIOVERI_NLQ", 0x01, 0x01 },
+ { "CLRLQIOVERI_LQ", 0x02, 0x02 },
+ { "CLRLQIBADLQI", 0x04, 0x04 },
+@@ -1166,7 +955,7 @@ ahd_clrlqiint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x51, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t LQISTAT2_parse_table[] = {
++static const ahd_reg_parse_entry_t LQISTAT2_parse_table[] = {
+ { "LQIGSAVAIL", 0x01, 0x01 },
+ { "LQISTOPCMD", 0x02, 0x02 },
+ { "LQISTOPLQ", 0x04, 0x04 },
+@@ -1184,7 +973,7 @@ ahd_lqistat2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x52, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SSTAT3_parse_table[] = {
++static const ahd_reg_parse_entry_t SSTAT3_parse_table[] = {
+ { "OSRAMPERR", 0x01, 0x01 },
+ { "NTRAMPERR", 0x02, 0x02 }
+ };
+@@ -1196,7 +985,7 @@ ahd_sstat3_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x53, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SIMODE3_parse_table[] = {
++static const ahd_reg_parse_entry_t SIMODE3_parse_table[] = {
+ { "ENOSRAMPERR", 0x01, 0x01 },
+ { "ENNTRAMPERR", 0x02, 0x02 }
+ };
+@@ -1208,7 +997,7 @@ ahd_simode3_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x53, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t CLRSINT3_parse_table[] = {
++static const ahd_reg_parse_entry_t CLRSINT3_parse_table[] = {
+ { "CLROSRAMPERR", 0x01, 0x01 },
+ { "CLRNTRAMPERR", 0x02, 0x02 }
+ };
+@@ -1220,7 +1009,7 @@ ahd_clrsint3_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x53, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t LQOSTAT0_parse_table[] = {
++static const ahd_reg_parse_entry_t LQOSTAT0_parse_table[] = {
+ { "LQOTCRC", 0x01, 0x01 },
+ { "LQOATNPKT", 0x02, 0x02 },
+ { "LQOATNLQ", 0x04, 0x04 },
+@@ -1235,7 +1024,7 @@ ahd_lqostat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x54, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t CLRLQOINT0_parse_table[] = {
++static const ahd_reg_parse_entry_t CLRLQOINT0_parse_table[] = {
+ { "CLRLQOTCRC", 0x01, 0x01 },
+ { "CLRLQOATNPKT", 0x02, 0x02 },
+ { "CLRLQOATNLQ", 0x04, 0x04 },
+@@ -1250,7 +1039,7 @@ ahd_clrlqoint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x54, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = {
++static const ahd_reg_parse_entry_t LQOMODE0_parse_table[] = {
+ { "ENLQOTCRC", 0x01, 0x01 },
+ { "ENLQOATNPKT", 0x02, 0x02 },
+ { "ENLQOATNLQ", 0x04, 0x04 },
+@@ -1265,7 +1054,7 @@ ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x54, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = {
++static const ahd_reg_parse_entry_t LQOMODE1_parse_table[] = {
+ { "ENLQOPHACHGINPKT", 0x01, 0x01 },
+ { "ENLQOBUSFREE", 0x02, 0x02 },
+ { "ENLQOBADQAS", 0x04, 0x04 },
+@@ -1280,7 +1069,7 @@ ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x55, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t LQOSTAT1_parse_table[] = {
++static const ahd_reg_parse_entry_t LQOSTAT1_parse_table[] = {
+ { "LQOPHACHGINPKT", 0x01, 0x01 },
+ { "LQOBUSFREE", 0x02, 0x02 },
+ { "LQOBADQAS", 0x04, 0x04 },
+@@ -1295,7 +1084,7 @@ ahd_lqostat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x55, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t CLRLQOINT1_parse_table[] = {
++static const ahd_reg_parse_entry_t CLRLQOINT1_parse_table[] = {
+ { "CLRLQOPHACHGINPKT", 0x01, 0x01 },
+ { "CLRLQOBUSFREE", 0x02, 0x02 },
+ { "CLRLQOBADQAS", 0x04, 0x04 },
+@@ -1310,7 +1099,7 @@ ahd_clrlqoint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x55, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t LQOSTAT2_parse_table[] = {
++static const ahd_reg_parse_entry_t LQOSTAT2_parse_table[] = {
+ { "LQOSTOP0", 0x01, 0x01 },
+ { "LQOPHACHGOUTPKT", 0x02, 0x02 },
+ { "LQOWAITFIFO", 0x10, 0x10 },
+@@ -1331,7 +1120,7 @@ ahd_os_space_cnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x56, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SIMODE1_parse_table[] = {
++static const ahd_reg_parse_entry_t SIMODE1_parse_table[] = {
+ { "ENREQINIT", 0x01, 0x01 },
+ { "ENSTRB2FAST", 0x02, 0x02 },
+ { "ENSCSIPERR", 0x04, 0x04 },
+@@ -1356,7 +1145,7 @@ ahd_gsfifo_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x58, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t DFFSXFRCTL_parse_table[] = {
++static const ahd_reg_parse_entry_t DFFSXFRCTL_parse_table[] = {
+ { "RSTCHN", 0x01, 0x01 },
+ { "CLRCHN", 0x02, 0x02 },
+ { "CLRSHCNT", 0x04, 0x04 },
+@@ -1370,15 +1159,17 @@ ahd_dffsxfrctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x5a, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t LQOSCSCTL_parse_table[] = {
++static const ahd_reg_parse_entry_t LQOSCSCTL_parse_table[] = {
+ { "LQONOCHKOVER", 0x01, 0x01 },
++ { "LQONOHOLDLACK", 0x02, 0x02 },
++ { "LQOBUSETDLY", 0x40, 0x40 },
+ { "LQOH2A_VERSION", 0x80, 0x80 }
+ };
+
+ int
+ ahd_lqoscsctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+- return (ahd_print_register(LQOSCSCTL_parse_table, 2, "LQOSCSCTL",
++ return (ahd_print_register(LQOSCSCTL_parse_table, 4, "LQOSCSCTL",
+ 0x5a, regvalue, cur_col, wrap));
+ }
+
+@@ -1389,7 +1180,7 @@ ahd_nextscb_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x5a, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t CLRSEQINTSRC_parse_table[] = {
++static const ahd_reg_parse_entry_t CLRSEQINTSRC_parse_table[] = {
+ { "CLRCFG4TCMD", 0x01, 0x01 },
+ { "CLRCFG4ICMD", 0x02, 0x02 },
+ { "CLRCFG4TSTAT", 0x04, 0x04 },
+@@ -1406,7 +1197,7 @@ ahd_clrseqintsrc_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x5b, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SEQINTSRC_parse_table[] = {
++static const ahd_reg_parse_entry_t SEQINTSRC_parse_table[] = {
+ { "CFG4TCMD", 0x01, 0x01 },
+ { "CFG4ICMD", 0x02, 0x02 },
+ { "CFG4TSTAT", 0x04, 0x04 },
+@@ -1423,14 +1214,7 @@ ahd_seqintsrc_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x5b, regvalue, cur_col, wrap));
+ }
+
+-int
+-ahd_currscb_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "CURRSCB",
+- 0x5c, regvalue, cur_col, wrap));
+-}
-
--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,
+-static ahd_reg_parse_entry_t SEQIMODE_parse_table[] = {
++static const ahd_reg_parse_entry_t SEQIMODE_parse_table[] = {
+ { "ENCFG4TCMD", 0x01, 0x01 },
+ { "ENCFG4ICMD", 0x02, 0x02 },
+ { "ENCFG4TSTAT", 0x04, 0x04 },
+@@ -1447,7 +1231,14 @@ ahd_seqimode_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x5c, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t MDFFSTAT_parse_table[] = {
++int
++ahd_currscb_print(u_int regvalue, u_int *cur_col, u_int wrap)
++{
++ return (ahd_print_register(NULL, 0, "CURRSCB",
++ 0x5c, regvalue, cur_col, wrap));
++}
++
++static const ahd_reg_parse_entry_t MDFFSTAT_parse_table[] = {
+ { "FIFOFREE", 0x01, 0x01 },
+ { "DATAINFIFO", 0x02, 0x02 },
+ { "DLZERO", 0x04, 0x04 },
+@@ -1464,24 +1255,6 @@ ahd_mdffstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x5d, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t CRCCONTROL_parse_table[] = {
+- { "CRCVALCHKEN", 0x40, 0x40 }
-};
-
+-int
+-ahd_crccontrol_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(CRCCONTROL_parse_table, 1, "CRCCONTROL",
+- 0x5d, regvalue, cur_col, wrap));
+-}
-
--/* Return Codes for IPA Commands
-- * according to OSA card Specs */
+-int
+-ahd_dfftag_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "DFFTAG",
+- 0x5e, regvalue, cur_col, wrap));
+-}
-
--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
+ int
+ ahd_lastscb_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+@@ -1489,31 +1262,6 @@ ahd_lastscb_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x5e, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SCSITEST_parse_table[] = {
+- { "SEL_TXPLL_DEBUG", 0x04, 0x04 },
+- { "CNTRTEST", 0x08, 0x08 }
-};
-
--/* 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,
--};
+-int
+-ahd_scsitest_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(SCSITEST_parse_table, 2, "SCSITEST",
+- 0x5e, regvalue, cur_col, wrap));
+-}
-
--/* 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,
+-static ahd_reg_parse_entry_t IOPDNCTL_parse_table[] = {
+- { "PDN_DIFFSENSE", 0x01, 0x01 },
+- { "PDN_IDIST", 0x04, 0x04 },
+- { "DISABLE_OE", 0x80, 0x80 }
-};
-
--/* 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,
--};
+-int
+-ahd_iopdnctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(IOPDNCTL_parse_table, 3, "IOPDNCTL",
+- 0x5f, regvalue, cur_col, wrap));
+-}
-
--/* (SET)DELIP(M) IPA stuff ***************************************************/
--struct qeth_ipacmd_setdelip4 {
-- __u8 ip_addr[4];
-- __u8 mask[4];
-- __u32 flags;
--} __attribute__ ((packed));
+ int
+ ahd_shaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+@@ -1529,13 +1277,6 @@ ahd_negoaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_dgrpcrci_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "DGRPCRCI",
+- 0x60, regvalue, cur_col, wrap));
+-}
-
--struct qeth_ipacmd_setdelip6 {
-- __u8 ip_addr[16];
-- __u8 mask[16];
-- __u32 flags;
--} __attribute__ ((packed));
+-int
+ ahd_negperiod_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahd_print_register(NULL, 0, "NEGPERIOD",
+@@ -1543,20 +1284,13 @@ ahd_negperiod_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_packcrci_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "PACKCRCI",
+- 0x62, regvalue, cur_col, wrap));
+-}
-
--struct qeth_ipacmd_setdelipm {
-- __u8 mac[6];
-- __u8 padding[2];
-- __u8 ip6[12];
-- __u8 ip4[4];
--} __attribute__ ((packed));
+-int
+ ahd_negoffset_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahd_print_register(NULL, 0, "NEGOFFSET",
+ 0x62, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t NEGPPROPTS_parse_table[] = {
++static const ahd_reg_parse_entry_t NEGPPROPTS_parse_table[] = {
+ { "PPROPT_IUT", 0x01, 0x01 },
+ { "PPROPT_DT", 0x02, 0x02 },
+ { "PPROPT_QAS", 0x04, 0x04 },
+@@ -1570,7 +1304,7 @@ ahd_negppropts_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x63, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t NEGCONOPTS_parse_table[] = {
++static const ahd_reg_parse_entry_t NEGCONOPTS_parse_table[] = {
+ { "WIDEXFER", 0x01, 0x01 },
+ { "ENAUTOATNO", 0x02, 0x02 },
+ { "ENAUTOATNI", 0x04, 0x04 },
+@@ -1601,20 +1335,21 @@ ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x66, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SCSCHKN_parse_table[] = {
++static const ahd_reg_parse_entry_t SCSCHKN_parse_table[] = {
+ { "LSTSGCLRDIS", 0x01, 0x01 },
+ { "SHVALIDSTDIS", 0x02, 0x02 },
+ { "DFFACTCLR", 0x04, 0x04 },
+ { "SDONEMSKDIS", 0x08, 0x08 },
+ { "WIDERESEN", 0x10, 0x10 },
+ { "CURRFIFODEF", 0x20, 0x20 },
+- { "STSELSKIDDIS", 0x40, 0x40 }
++ { "STSELSKIDDIS", 0x40, 0x40 },
++ { "BIDICHKDIS", 0x80, 0x80 }
+ };
+
+ int
+ ahd_scschkn_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+- return (ahd_print_register(SCSCHKN_parse_table, 7, "SCSCHKN",
++ return (ahd_print_register(SCSCHKN_parse_table, 8, "SCSCHKN",
+ 0x66, regvalue, cur_col, wrap));
+ }
+
+@@ -1625,23 +1360,6 @@ ahd_iownid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x67, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t PLL960CTL0_parse_table[] = {
+- { "PLL_ENFBM", 0x01, 0x01 },
+- { "PLL_DLPF", 0x02, 0x02 },
+- { "PLL_ENLPF", 0x04, 0x04 },
+- { "PLL_ENLUD", 0x08, 0x08 },
+- { "PLL_NS", 0x30, 0x30 },
+- { "PLL_PWDN", 0x40, 0x40 },
+- { "PLL_VCOSEL", 0x80, 0x80 }
+-};
-
--struct qeth_ipacmd_layer2setdelmac {
-- __u32 mac_length;
-- __u8 mac[6];
--} __attribute__ ((packed));
+-int
+-ahd_pll960ctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(PLL960CTL0_parse_table, 7, "PLL960CTL0",
+- 0x68, regvalue, cur_col, wrap));
+-}
-
--struct qeth_ipacmd_layer2setdelvlan {
-- __u16 vlan_id;
--} __attribute__ ((packed));
+ int
+ ahd_shcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+@@ -1656,33 +1374,6 @@ ahd_townid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x69, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t PLL960CTL1_parse_table[] = {
+- { "PLL_RST", 0x01, 0x01 },
+- { "PLL_CNTCLR", 0x40, 0x40 },
+- { "PLL_CNTEN", 0x80, 0x80 }
+-};
-
+-int
+-ahd_pll960ctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(PLL960CTL1_parse_table, 3, "PLL960CTL1",
+- 0x69, regvalue, cur_col, wrap));
+-}
-
--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));
+-int
+-ahd_pll960cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "PLL960CNT0",
+- 0x6a, regvalue, cur_col, wrap));
+-}
-
--struct qeth_arp_query_data {
-- __u16 request_bits;
-- __u16 reply_bits;
-- __u32 no_entries;
-- char data;
--} __attribute__((packed));
+-int
+-ahd_xsig_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "XSIG",
+- 0x6a, regvalue, cur_col, wrap));
+-}
-
--/* 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;
+ int
+ ahd_seloid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+@@ -1690,57 +1381,6 @@ ahd_seloid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x6b, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t PLL400CTL0_parse_table[] = {
+- { "PLL_ENFBM", 0x01, 0x01 },
+- { "PLL_DLPF", 0x02, 0x02 },
+- { "PLL_ENLPF", 0x04, 0x04 },
+- { "PLL_ENLUD", 0x08, 0x08 },
+- { "PLL_NS", 0x30, 0x30 },
+- { "PLL_PWDN", 0x40, 0x40 },
+- { "PLL_VCOSEL", 0x80, 0x80 }
-};
-
--/* 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));
+-int
+-ahd_pll400ctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(PLL400CTL0_parse_table, 7, "PLL400CTL0",
+- 0x6c, regvalue, cur_col, wrap));
+-}
-
+-int
+-ahd_fairness_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "FAIRNESS",
+- 0x6c, regvalue, cur_col, wrap));
+-}
-
--/* SETRTG IPA Command: ****************************************************/
--struct qeth_set_routing {
-- __u8 type;
+-static ahd_reg_parse_entry_t PLL400CTL1_parse_table[] = {
+- { "PLL_RST", 0x01, 0x01 },
+- { "PLL_CNTCLR", 0x40, 0x40 },
+- { "PLL_CNTEN", 0x80, 0x80 }
-};
-
--/* 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));
+-int
+-ahd_pll400ctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(PLL400CTL1_parse_table, 3, "PLL400CTL1",
+- 0x6d, regvalue, cur_col, wrap));
+-}
-
--struct qeth_change_addr {
-- __u32 cmd;
-- __u32 addr_size;
-- __u32 no_macs;
-- __u8 addr[OSA_ADDR_LEN];
--} __attribute__ ((packed));
+-int
+-ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "UNFAIRNESS",
+- 0x6e, regvalue, cur_col, wrap));
+-}
-
+-int
+-ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "PLL400CNT0",
+- 0x6e, regvalue, cur_col, wrap));
+-}
-
--struct qeth_snmp_cmd {
-- __u8 token[16];
-- __u32 request;
-- __u32 interface;
-- __u32 returncode;
-- __u32 firmwarelevel;
-- __u32 seqno;
-- __u8 data;
--} __attribute__ ((packed));
+ int
+ ahd_haddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+@@ -1748,31 +1388,6 @@ ahd_haddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x70, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t PLLDELAY_parse_table[] = {
+- { "SPLIT_DROP_REQ", 0x80, 0x80 }
+-};
-
--struct qeth_snmp_ureq_hdr {
-- __u32 data_len;
-- __u32 req_len;
-- __u32 reserved1;
-- __u32 reserved2;
--} __attribute__ ((packed));
+-int
+-ahd_plldelay_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(PLLDELAY_parse_table, 1, "PLLDELAY",
+- 0x70, regvalue, cur_col, wrap));
+-}
-
--struct qeth_snmp_ureq {
-- struct qeth_snmp_ureq_hdr hdr;
-- struct qeth_snmp_cmd cmd;
--} __attribute__((packed));
+-int
+-ahd_hodmaadr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "HODMAADR",
+- 0x70, regvalue, cur_col, wrap));
+-}
-
--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));
+-int
+-ahd_hodmacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "HODMACNT",
+- 0x78, regvalue, cur_col, wrap));
+-}
-
--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));
+ int
+ ahd_hcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+@@ -1781,10 +1396,10 @@ ahd_hcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_hodmaen_print(u_int regvalue, u_int *cur_col, u_int wrap)
++ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+- return (ahd_print_register(NULL, 0, "HODMAEN",
+- 0x7a, regvalue, cur_col, wrap));
++ return (ahd_print_register(NULL, 0, "SGHADDR",
++ 0x7c, regvalue, cur_col, wrap));
+ }
+
+ int
+@@ -1795,10 +1410,10 @@ ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
++ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+- return (ahd_print_register(NULL, 0, "SGHADDR",
+- 0x7c, regvalue, cur_col, wrap));
++ return (ahd_print_register(NULL, 0, "SGHCNT",
++ 0x84, regvalue, cur_col, wrap));
+ }
+
+ int
+@@ -1808,14 +1423,7 @@ ahd_scbhcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x84, regvalue, cur_col, wrap));
+ }
+
+-int
+-ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "SGHCNT",
+- 0x84, regvalue, cur_col, wrap));
+-}
-
--/* IPFRAME IPA Command: ***************************************************/
--/* TODO: define in analogy to commands define above */
+-static ahd_reg_parse_entry_t DFF_THRSH_parse_table[] = {
++static const ahd_reg_parse_entry_t DFF_THRSH_parse_table[] = {
+ { "WR_DFTHRSH_MIN", 0x00, 0x70 },
+ { "RD_DFTHRSH_MIN", 0x00, 0x07 },
+ { "RD_DFTHRSH_25", 0x01, 0x07 },
+@@ -1843,209 +1451,7 @@ ahd_dff_thrsh_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x88, regvalue, cur_col, wrap));
+ }
+
+-int
+-ahd_romaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "ROMADDR",
+- 0x8a, regvalue, cur_col, wrap));
+-}
-
--/* ADD_ADDR_ENTRY IPA Command: ********************************************/
--/* TODO: define in analogy to commands define above */
+-static ahd_reg_parse_entry_t ROMCNTRL_parse_table[] = {
+- { "RDY", 0x01, 0x01 },
+- { "REPEAT", 0x02, 0x02 },
+- { "ROMSPD", 0x18, 0x18 },
+- { "ROMOP", 0xe0, 0xe0 }
+-};
-
--/* DELETE_ADDR_ENTRY IPA Command: *****************************************/
--/* TODO: define in analogy to commands define above */
+-int
+-ahd_romcntrl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(ROMCNTRL_parse_table, 4, "ROMCNTRL",
+- 0x8d, regvalue, cur_col, wrap));
+-}
-
--/* CREATE_ADDR IPA Command: ***********************************************/
--struct qeth_create_destroy_address {
-- __u8 unique_id[8];
--} __attribute__ ((packed));
+-int
+-ahd_romdata_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "ROMDATA",
+- 0x8e, regvalue, cur_col, wrap));
+-}
-
--/* REGISTER_LOCAL_ADDR IPA Command: ***************************************/
--/* TODO: define in analogy to commands define above */
+-static ahd_reg_parse_entry_t CMCRXMSG0_parse_table[] = {
+- { "CFNUM", 0x07, 0x07 },
+- { "CDNUM", 0xf8, 0xf8 }
+-};
-
--/* UNREGISTER_LOCAL_ADDR IPA Command: *************************************/
--/* TODO: define in analogy to commands define above */
+-int
+-ahd_cmcrxmsg0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(CMCRXMSG0_parse_table, 2, "CMCRXMSG0",
+- 0x90, regvalue, cur_col, wrap));
+-}
-
--/* 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));
+-static ahd_reg_parse_entry_t ROENABLE_parse_table[] = {
+- { "DCH0ROEN", 0x01, 0x01 },
+- { "DCH1ROEN", 0x02, 0x02 },
+- { "SGROEN", 0x04, 0x04 },
+- { "CMCROEN", 0x08, 0x08 },
+- { "OVLYROEN", 0x10, 0x10 },
+- { "MSIROEN", 0x20, 0x20 }
+-};
-
--/* 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));
+-int
+-ahd_roenable_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(ROENABLE_parse_table, 6, "ROENABLE",
+- 0x90, regvalue, cur_col, wrap));
+-}
-
--/*
-- * 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,
+-static ahd_reg_parse_entry_t OVLYRXMSG0_parse_table[] = {
+- { "CFNUM", 0x07, 0x07 },
+- { "CDNUM", 0xf8, 0xf8 }
-};
-
+-int
+-ahd_ovlyrxmsg0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(OVLYRXMSG0_parse_table, 2, "OVLYRXMSG0",
+- 0x90, regvalue, cur_col, wrap));
+-}
-
--extern char *
--qeth_get_ipa_msg(enum qeth_ipa_return_codes rc);
--extern char *
--qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd);
+-static ahd_reg_parse_entry_t DCHRXMSG0_parse_table[] = {
+- { "CFNUM", 0x07, 0x07 },
+- { "CDNUM", 0xf8, 0xf8 }
+-};
-
--#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
+-int
+-ahd_dchrxmsg0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(DCHRXMSG0_parse_table, 2, "DCHRXMSG0",
+- 0x90, regvalue, cur_col, wrap));
+-}
-
--#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))
+-static ahd_reg_parse_entry_t OVLYRXMSG1_parse_table[] = {
+- { "CBNUM", 0xff, 0xff }
+-};
-
--/*****************************************************************************/
--/* END OF IP Assist related definitions */
--/*****************************************************************************/
+-int
+-ahd_ovlyrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(OVLYRXMSG1_parse_table, 1, "OVLYRXMSG1",
+- 0x91, regvalue, cur_col, wrap));
+-}
-
+-static ahd_reg_parse_entry_t NSENABLE_parse_table[] = {
+- { "DCH0NSEN", 0x01, 0x01 },
+- { "DCH1NSEN", 0x02, 0x02 },
+- { "SGNSEN", 0x04, 0x04 },
+- { "CMCNSEN", 0x08, 0x08 },
+- { "OVLYNSEN", 0x10, 0x10 },
+- { "MSINSEN", 0x20, 0x20 }
+-};
-
--extern unsigned char WRITE_CCW[];
--extern unsigned char READ_CCW[];
+-int
+-ahd_nsenable_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NSENABLE_parse_table, 6, "NSENABLE",
+- 0x91, regvalue, cur_col, wrap));
+-}
-
--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)
+-static ahd_reg_parse_entry_t CMCRXMSG1_parse_table[] = {
+- { "CBNUM", 0xff, 0xff }
+-};
-
--#define QETH_CM_ENABLE_RESP_FILTER_TOKEN(buffer) \
-- (PDU_ENCAPSULATION(buffer)+ 0x13)
+-int
+-ahd_cmcrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(CMCRXMSG1_parse_table, 1, "CMCRXMSG1",
+- 0x91, regvalue, cur_col, wrap));
+-}
-
+-static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = {
+- { "CBNUM", 0xff, 0xff }
+-};
-
--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)
+-int
+-ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1",
+- 0x91, regvalue, cur_col, wrap));
+-}
-
--#define QETH_CM_SETUP_RESP_DEST_ADDR(buffer) \
-- (PDU_ENCAPSULATION(buffer) + 0x1a)
+-static ahd_reg_parse_entry_t DCHRXMSG2_parse_table[] = {
+- { "MINDEX", 0xff, 0xff }
+-};
-
--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)
+-int
+-ahd_dchrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(DCHRXMSG2_parse_table, 1, "DCHRXMSG2",
+- 0x92, regvalue, cur_col, wrap));
+-}
-
--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)
+-static ahd_reg_parse_entry_t CMCRXMSG2_parse_table[] = {
+- { "MINDEX", 0xff, 0xff }
+-};
-
--#define QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(buffer) \
-- (PDU_ENCAPSULATION(buffer)+0x1a)
+-int
+-ahd_cmcrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(CMCRXMSG2_parse_table, 1, "CMCRXMSG2",
+- 0x92, regvalue, cur_col, wrap));
+-}
-
+-int
+-ahd_ost_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "OST",
+- 0x92, regvalue, cur_col, wrap));
+-}
-
--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)
+-static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = {
+- { "MINDEX", 0xff, 0xff }
+-};
-
+-int
+-ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2",
+- 0x92, regvalue, cur_col, wrap));
+-}
-
+-static ahd_reg_parse_entry_t DCHRXMSG3_parse_table[] = {
+- { "MCLASS", 0x0f, 0x0f }
+-};
-
--#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)
+-int
+-ahd_dchrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(DCHRXMSG3_parse_table, 1, "DCHRXMSG3",
+- 0x93, regvalue, cur_col, wrap));
+-}
-
--extern unsigned char IDX_ACTIVATE_READ[];
--extern unsigned char IDX_ACTIVATE_WRITE[];
+-static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = {
+- { "MCLASS", 0x0f, 0x0f }
+-};
-
--#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]
+-int
+-ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3",
+- 0x93, regvalue, cur_col, wrap));
+-}
-
--#define PDU_ENCAPSULATION(buffer) \
-- (buffer + *(buffer + (*(buffer+0x0b)) + \
-- *(buffer + *(buffer+0x0b)+0x11) +0x07))
+-static ahd_reg_parse_entry_t CMCRXMSG3_parse_table[] = {
+- { "MCLASS", 0x0f, 0x0f }
+-};
-
--#define IS_IPA(buffer) \
-- ((buffer) && \
-- ( *(buffer + ((*(buffer+0x0b))+4) )==0xc1) )
+-int
+-ahd_cmcrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(CMCRXMSG3_parse_table, 1, "CMCRXMSG3",
+- 0x93, regvalue, cur_col, wrap));
+-}
-
--#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
+-static ahd_reg_parse_entry_t PCIXCTL_parse_table[] = {
++static const ahd_reg_parse_entry_t PCIXCTL_parse_table[] = {
+ { "CMPABCDIS", 0x01, 0x01 },
+ { "TSCSERREN", 0x02, 0x02 },
+ { "SRSPDPEEN", 0x04, 0x04 },
+@@ -2062,46 +1468,7 @@ ahd_pcixctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x93, regvalue, cur_col, wrap));
+ }
+
+-int
+-ahd_ovlyseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "OVLYSEQBCNT",
+- 0x94, regvalue, cur_col, wrap));
+-}
-
--#endif
-diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c
-deleted file mode 100644
-index 46ecd03..0000000
---- a/drivers/s390/net/qeth_proc.c
-+++ /dev/null
-@@ -1,316 +0,0 @@
--/*
-- *
-- * linux/drivers/s390/net/qeth_fs.c
-- *
-- * Linux on zSeries OSA Express and HiperSockets support
-- * This file contains code related to procfs.
-- *
-- * Copyright 2000,2003 IBM Corporation
-- *
-- * Author(s): Thomas Spatzier <tspat at de.ibm.com>
-- *
-- */
--#include <linux/module.h>
--#include <linux/init.h>
--#include <linux/proc_fs.h>
--#include <linux/seq_file.h>
--#include <linux/list.h>
--#include <linux/rwsem.h>
+-int
+-ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "DCHSEQBCNT",
+- 0x94, regvalue, cur_col, wrap));
+-}
-
--#include "qeth.h"
--#include "qeth_mpc.h"
--#include "qeth_fs.h"
+-int
+-ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "CMCSEQBCNT",
+- 0x94, regvalue, cur_col, wrap));
+-}
-
--/***** /proc/qeth *****/
--#define QETH_PROCFILE_NAME "qeth"
--static struct proc_dir_entry *qeth_procfile;
+-static ahd_reg_parse_entry_t CMCSPLTSTAT0_parse_table[] = {
+- { "RXSPLTRSP", 0x01, 0x01 },
+- { "RXSCEMSG", 0x02, 0x02 },
+- { "RXOVRUN", 0x04, 0x04 },
+- { "CNTNOTCMPLT", 0x08, 0x08 },
+- { "SCDATBUCKET", 0x10, 0x10 },
+- { "SCADERR", 0x20, 0x20 },
+- { "SCBCERR", 0x40, 0x40 },
+- { "STAETERM", 0x80, 0x80 }
+-};
-
--static int
--qeth_procfile_seq_match(struct device *dev, void *data)
+-int
+-ahd_cmcspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- return(dev ? 1 : 0);
+- return (ahd_print_register(CMCSPLTSTAT0_parse_table, 8, "CMCSPLTSTAT0",
+- 0x96, regvalue, cur_col, wrap));
-}
-
--static void *
--qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)
--{
-- struct device *dev = NULL;
-- loff_t nr = 0;
+-static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = {
++static const ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = {
+ { "RXSPLTRSP", 0x01, 0x01 },
+ { "RXSCEMSG", 0x02, 0x02 },
+ { "RXOVRUN", 0x04, 0x04 },
+@@ -2119,47 +1486,7 @@ ahd_dchspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x96, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = {
+- { "RXSPLTRSP", 0x01, 0x01 },
+- { "RXSCEMSG", 0x02, 0x02 },
+- { "RXOVRUN", 0x04, 0x04 },
+- { "CNTNOTCMPLT", 0x08, 0x08 },
+- { "SCDATBUCKET", 0x10, 0x10 },
+- { "SCADERR", 0x20, 0x20 },
+- { "SCBCERR", 0x40, 0x40 },
+- { "STAETERM", 0x80, 0x80 }
+-};
-
-- 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;
+-int
+-ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0",
+- 0x96, regvalue, cur_col, wrap));
-}
-
--static void
--qeth_procfile_seq_stop(struct seq_file *s, void* it)
+-static ahd_reg_parse_entry_t CMCSPLTSTAT1_parse_table[] = {
+- { "RXDATABUCKET", 0x01, 0x01 }
+-};
+-
+-int
+-ahd_cmcspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
+- return (ahd_print_register(CMCSPLTSTAT1_parse_table, 1, "CMCSPLTSTAT1",
+- 0x97, regvalue, cur_col, wrap));
-}
-
--static void *
--qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
--{
-- struct device *prev, *next;
+-static ahd_reg_parse_entry_t OVLYSPLTSTAT1_parse_table[] = {
+- { "RXDATABUCKET", 0x01, 0x01 }
+-};
-
-- 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;
+-int
+-ahd_ovlyspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(OVLYSPLTSTAT1_parse_table, 1, "OVLYSPLTSTAT1",
+- 0x97, regvalue, cur_col, wrap));
-}
-
--static inline const char *
--qeth_get_router_str(struct qeth_card *card, int ipv)
+-static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = {
++static const ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = {
+ { "RXDATABUCKET", 0x01, 0x01 }
+ };
+
+@@ -2170,139 +1497,7 @@ ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x97, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SGRXMSG0_parse_table[] = {
+- { "CFNUM", 0x07, 0x07 },
+- { "CDNUM", 0xf8, 0xf8 }
+-};
+-
+-int
+-ahd_sgrxmsg0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- enum qeth_routing_types routing_type = NO_ROUTER;
+- return (ahd_print_register(SGRXMSG0_parse_table, 2, "SGRXMSG0",
+- 0x98, regvalue, cur_col, wrap));
+-}
-
-- 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 */
-- }
+-static ahd_reg_parse_entry_t SLVSPLTOUTADR0_parse_table[] = {
+- { "LOWER_ADDR", 0x7f, 0x7f }
+-};
-
-- 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";
-- }
+-int
+-ahd_slvspltoutadr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(SLVSPLTOUTADR0_parse_table, 1, "SLVSPLTOUTADR0",
+- 0x98, regvalue, cur_col, wrap));
-}
-
--static int
--qeth_procfile_seq_show(struct seq_file *s, void *it)
+-static ahd_reg_parse_entry_t SGRXMSG1_parse_table[] = {
+- { "CBNUM", 0xff, 0xff }
+-};
+-
+-int
+-ahd_sgrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct device *device;
-- struct qeth_card *card;
-- char tmp[12]; /* for qeth_get_prioq_str */
+- return (ahd_print_register(SGRXMSG1_parse_table, 1, "SGRXMSG1",
+- 0x99, regvalue, cur_col, wrap));
+-}
-
-- 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 ahd_reg_parse_entry_t SLVSPLTOUTADR1_parse_table[] = {
+- { "REQ_FNUM", 0x07, 0x07 },
+- { "REQ_DNUM", 0xf8, 0xf8 }
+-};
+-
+-int
+-ahd_slvspltoutadr1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(SLVSPLTOUTADR1_parse_table, 2, "SLVSPLTOUTADR1",
+- 0x99, regvalue, cur_col, wrap));
-}
-
--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 ahd_reg_parse_entry_t SGRXMSG2_parse_table[] = {
+- { "MINDEX", 0xff, 0xff }
-};
-
--static int
--qeth_procfile_open(struct inode *inode, struct file *file)
+-int
+-ahd_sgrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- return seq_open(file, &qeth_procfile_seq_ops);
+- return (ahd_print_register(SGRXMSG2_parse_table, 1, "SGRXMSG2",
+- 0x9a, regvalue, cur_col, wrap));
-}
-
--static const struct file_operations qeth_procfile_fops = {
-- .owner = THIS_MODULE,
-- .open = qeth_procfile_open,
-- .read = seq_read,
-- .llseek = seq_lseek,
-- .release = seq_release,
+-static ahd_reg_parse_entry_t SLVSPLTOUTADR2_parse_table[] = {
+- { "REQ_BNUM", 0xff, 0xff }
-};
-
--/***** /proc/qeth_perf *****/
--#define QETH_PERF_PROCFILE_NAME "qeth_perf"
--static struct proc_dir_entry *qeth_perf_procfile;
+-int
+-ahd_slvspltoutadr2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(SLVSPLTOUTADR2_parse_table, 1, "SLVSPLTOUTADR2",
+- 0x9a, regvalue, cur_col, wrap));
+-}
-
--static int
--qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
+-static ahd_reg_parse_entry_t SGRXMSG3_parse_table[] = {
+- { "MCLASS", 0x0f, 0x0f }
+-};
+-
+-int
+-ahd_sgrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct device *device;
-- struct qeth_card *card;
+- return (ahd_print_register(SGRXMSG3_parse_table, 1, "SGRXMSG3",
+- 0x9b, regvalue, cur_col, wrap));
+-}
-
+-static ahd_reg_parse_entry_t SLVSPLTOUTADR3_parse_table[] = {
+- { "RLXORD", 0x10, 0x10 },
+- { "TAG_NUM", 0x1f, 0x1f }
+-};
-
-- if (it == SEQ_START_TOKEN)
-- return 0;
+-int
+-ahd_slvspltoutadr3_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(SLVSPLTOUTADR3_parse_table, 2, "SLVSPLTOUTADR3",
+- 0x9b, regvalue, cur_col, wrap));
+-}
-
-- 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;
+-int
+-ahd_sgseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "SGSEQBCNT",
+- 0x9c, regvalue, cur_col, wrap));
-}
-
--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 ahd_reg_parse_entry_t SLVSPLTOUTATTR0_parse_table[] = {
+- { "LOWER_BCNT", 0xff, 0xff }
-};
-
--static int
--qeth_perf_procfile_open(struct inode *inode, struct file *file)
+-int
+-ahd_slvspltoutattr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- return seq_open(file, &qeth_perf_procfile_seq_ops);
+- return (ahd_print_register(SLVSPLTOUTATTR0_parse_table, 1, "SLVSPLTOUTATTR0",
+- 0x9c, regvalue, cur_col, wrap));
-}
-
--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,
+-static ahd_reg_parse_entry_t SLVSPLTOUTATTR1_parse_table[] = {
+- { "CMPLT_FNUM", 0x07, 0x07 },
+- { "CMPLT_DNUM", 0xf8, 0xf8 }
-};
-
--int __init
--qeth_create_procfs_entries(void)
+-int
+-ahd_slvspltoutattr1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- qeth_procfile = create_proc_entry(QETH_PROCFILE_NAME,
-- S_IFREG | 0444, NULL);
-- if (qeth_procfile)
-- qeth_procfile->proc_fops = &qeth_procfile_fops;
+- return (ahd_print_register(SLVSPLTOUTATTR1_parse_table, 2, "SLVSPLTOUTATTR1",
+- 0x9d, regvalue, cur_col, wrap));
+-}
-
-- 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;
+-static ahd_reg_parse_entry_t SLVSPLTOUTATTR2_parse_table[] = {
+- { "CMPLT_BNUM", 0xff, 0xff }
+-};
-
-- if (qeth_procfile &&
-- qeth_perf_procfile)
-- return 0;
-- else
-- return -ENOMEM;
+-int
+-ahd_slvspltoutattr2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(SLVSPLTOUTATTR2_parse_table, 1, "SLVSPLTOUTATTR2",
+- 0x9e, regvalue, cur_col, wrap));
-}
-
--void __exit
--qeth_remove_procfs_entries(void)
+-static ahd_reg_parse_entry_t SGSPLTSTAT0_parse_table[] = {
++static const ahd_reg_parse_entry_t SGSPLTSTAT0_parse_table[] = {
+ { "RXSPLTRSP", 0x01, 0x01 },
+ { "RXSCEMSG", 0x02, 0x02 },
+ { "RXOVRUN", 0x04, 0x04 },
+@@ -2320,7 +1515,7 @@ ahd_sgspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x9e, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = {
++static const ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = {
+ { "RXDATABUCKET", 0x01, 0x01 }
+ };
+
+@@ -2331,19 +1526,7 @@ ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x9f, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SFUNCT_parse_table[] = {
+- { "TEST_NUM", 0x0f, 0x0f },
+- { "TEST_GROUP", 0xf0, 0xf0 }
+-};
+-
+-int
+-ahd_sfunct_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- if (qeth_procfile)
-- remove_proc_entry(QETH_PROCFILE_NAME, NULL);
-- if (qeth_perf_procfile)
-- remove_proc_entry(QETH_PERF_PROCFILE_NAME, NULL);
+- return (ahd_print_register(SFUNCT_parse_table, 2, "SFUNCT",
+- 0x9f, regvalue, cur_col, wrap));
-}
-
-diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
-deleted file mode 100644
-index 2cc3f3a..0000000
---- a/drivers/s390/net/qeth_sys.c
-+++ /dev/null
-@@ -1,1858 +0,0 @@
--/*
-- *
-- * linux/drivers/s390/net/qeth_sys.c
-- *
-- * Linux on zSeries OSA Express and HiperSockets support
-- * This file contains code related to sysfs.
-- *
-- * Copyright 2000,2003 IBM Corporation
-- *
-- * Author(s): Thomas Spatzier <tspat at de.ibm.com>
-- * Frank Pavlic <fpavlic at de.ibm.com>
-- *
-- */
--#include <linux/list.h>
--#include <linux/rwsem.h>
--
--#include <asm/ebcdic.h>
+-static ahd_reg_parse_entry_t DF0PCISTAT_parse_table[] = {
++static const ahd_reg_parse_entry_t DF0PCISTAT_parse_table[] = {
+ { "DPR", 0x01, 0x01 },
+ { "TWATERR", 0x02, 0x02 },
+ { "RDPERR", 0x04, 0x04 },
+@@ -2368,83 +1551,6 @@ ahd_reg0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xa0, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t DF1PCISTAT_parse_table[] = {
+- { "DPR", 0x01, 0x01 },
+- { "TWATERR", 0x02, 0x02 },
+- { "RDPERR", 0x04, 0x04 },
+- { "SCAAPERR", 0x08, 0x08 },
+- { "RTA", 0x10, 0x10 },
+- { "RMA", 0x20, 0x20 },
+- { "SSE", 0x40, 0x40 },
+- { "DPE", 0x80, 0x80 }
+-};
-
--#include "qeth.h"
--#include "qeth_mpc.h"
--#include "qeth_fs.h"
+-int
+-ahd_df1pcistat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(DF1PCISTAT_parse_table, 8, "DF1PCISTAT",
+- 0xa1, regvalue, cur_col, wrap));
+-}
-
--/*****************************************************************************/
--/* */
--/* /sys-fs stuff UNDER DEVELOPMENT !!! */
--/* */
--/*****************************************************************************/
--//low/high watermark
+-static ahd_reg_parse_entry_t SGPCISTAT_parse_table[] = {
+- { "DPR", 0x01, 0x01 },
+- { "RDPERR", 0x04, 0x04 },
+- { "SCAAPERR", 0x08, 0x08 },
+- { "RTA", 0x10, 0x10 },
+- { "RMA", 0x20, 0x20 },
+- { "SSE", 0x40, 0x40 },
+- { "DPE", 0x80, 0x80 }
+-};
-
--static ssize_t
--qeth_dev_state_show(struct device *dev, struct device_attribute *attr, char *buf)
+-int
+-ahd_sgpcistat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct qeth_card *card = dev->driver_data;
-- if (!card)
-- return -EINVAL;
+- return (ahd_print_register(SGPCISTAT_parse_table, 7, "SGPCISTAT",
+- 0xa2, regvalue, cur_col, wrap));
+-}
-
-- 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");
-- }
+-int
+-ahd_reg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "REG1",
+- 0xa2, regvalue, cur_col, wrap));
-}
-
--static DEVICE_ATTR(state, 0444, qeth_dev_state_show, NULL);
+-static ahd_reg_parse_entry_t CMCPCISTAT_parse_table[] = {
+- { "DPR", 0x01, 0x01 },
+- { "TWATERR", 0x02, 0x02 },
+- { "RDPERR", 0x04, 0x04 },
+- { "SCAAPERR", 0x08, 0x08 },
+- { "RTA", 0x10, 0x10 },
+- { "RMA", 0x20, 0x20 },
+- { "SSE", 0x40, 0x40 },
+- { "DPE", 0x80, 0x80 }
+-};
-
--static ssize_t
--qeth_dev_chpid_show(struct device *dev, struct device_attribute *attr, char *buf)
+-int
+-ahd_cmcpcistat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct qeth_card *card = dev->driver_data;
-- if (!card)
-- return -EINVAL;
--
-- return sprintf(buf, "%02X\n", card->info.chpid);
+- return (ahd_print_register(CMCPCISTAT_parse_table, 8, "CMCPCISTAT",
+- 0xa3, regvalue, cur_col, wrap));
-}
-
--static DEVICE_ATTR(chpid, 0444, qeth_dev_chpid_show, NULL);
+-static ahd_reg_parse_entry_t OVLYPCISTAT_parse_table[] = {
+- { "DPR", 0x01, 0x01 },
+- { "RDPERR", 0x04, 0x04 },
+- { "SCAAPERR", 0x08, 0x08 },
+- { "RTA", 0x10, 0x10 },
+- { "RMA", 0x20, 0x20 },
+- { "SSE", 0x40, 0x40 },
+- { "DPE", 0x80, 0x80 }
+-};
-
--static ssize_t
--qeth_dev_if_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+-int
+-ahd_ovlypcistat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct qeth_card *card = dev->driver_data;
-- if (!card)
-- return -EINVAL;
-- return sprintf(buf, "%s\n", QETH_CARD_IFNAME(card));
+- return (ahd_print_register(OVLYPCISTAT_parse_table, 7, "OVLYPCISTAT",
+- 0xa4, regvalue, cur_col, wrap));
-}
-
--static DEVICE_ATTR(if_name, 0444, qeth_dev_if_name_show, NULL);
+ int
+ ahd_reg_isr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+@@ -2452,7 +1558,7 @@ ahd_reg_isr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xa4, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SG_STATE_parse_table[] = {
++static const ahd_reg_parse_entry_t SG_STATE_parse_table[] = {
+ { "SEGS_AVAIL", 0x01, 0x01 },
+ { "LOADING_NEEDED", 0x02, 0x02 },
+ { "FETCH_INPROG", 0x04, 0x04 }
+@@ -2465,23 +1571,7 @@ ahd_sg_state_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xa6, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t MSIPCISTAT_parse_table[] = {
+- { "DPR", 0x01, 0x01 },
+- { "TWATERR", 0x02, 0x02 },
+- { "CLRPENDMSI", 0x08, 0x08 },
+- { "RTA", 0x10, 0x10 },
+- { "RMA", 0x20, 0x20 },
+- { "SSE", 0x40, 0x40 }
+-};
-
--static ssize_t
--qeth_dev_card_type_show(struct device *dev, struct device_attribute *attr, char *buf)
+-int
+-ahd_msipcistat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct qeth_card *card = dev->driver_data;
-- if (!card)
-- return -EINVAL;
--
-- return sprintf(buf, "%s\n", qeth_get_cardname_short(card));
+- return (ahd_print_register(MSIPCISTAT_parse_table, 6, "MSIPCISTAT",
+- 0xa6, regvalue, cur_col, wrap));
-}
-
--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)
+-static ahd_reg_parse_entry_t TARGPCISTAT_parse_table[] = {
++static const ahd_reg_parse_entry_t TARGPCISTAT_parse_table[] = {
+ { "TWATERR", 0x02, 0x02 },
+ { "STA", 0x08, 0x08 },
+ { "SSE", 0x40, 0x40 },
+@@ -2496,27 +1586,13 @@ ahd_targpcistat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_data_count_odd_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct qeth_card *card = dev->driver_data;
-- if (!card)
-- return -EINVAL;
+- return (ahd_print_register(NULL, 0, "DATA_COUNT_ODD",
+- 0xa7, regvalue, cur_col, wrap));
+-}
-
-- return sprintf(buf, "%i\n", card->info.portno);
+-int
+ ahd_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahd_print_register(NULL, 0, "SCBPTR",
+ 0xa8, regvalue, cur_col, wrap));
+ }
+
+-int
+-ahd_ccscbacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "CCSCBACNT",
+- 0xab, regvalue, cur_col, wrap));
-}
-
--static ssize_t
--qeth_dev_portno_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-static ahd_reg_parse_entry_t SCBAUTOPTR_parse_table[] = {
++static const ahd_reg_parse_entry_t SCBAUTOPTR_parse_table[] = {
+ { "SCBPTR_OFF", 0x07, 0x07 },
+ { "SCBPTR_ADDR", 0x38, 0x38 },
+ { "AUSCBPTR_EN", 0x80, 0x80 }
+@@ -2537,36 +1613,13 @@ ahd_ccsgaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct qeth_card *card = dev->driver_data;
-- char *tmp;
-- unsigned int portno;
+- return (ahd_print_register(NULL, 0, "CCSCBADR_BK",
+- 0xac, regvalue, cur_col, wrap));
+-}
-
-- if (!card)
-- return -EINVAL;
+-int
+ ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahd_print_register(NULL, 0, "CCSCBADDR",
+ 0xac, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t CMC_RAMBIST_parse_table[] = {
+- { "CMC_BUFFER_BIST_EN", 0x01, 0x01 },
+- { "CMC_BUFFER_BIST_FAIL",0x02, 0x02 },
+- { "SG_BIST_EN", 0x10, 0x10 },
+- { "SG_BIST_FAIL", 0x20, 0x20 },
+- { "SCBRAMBIST_FAIL", 0x40, 0x40 },
+- { "SG_ELEMENT_SIZE", 0x80, 0x80 }
+-};
-
-- if ((card->state != CARD_STATE_DOWN) &&
-- (card->state != CARD_STATE_RECOVER))
-- return -EPERM;
+-int
+-ahd_cmc_rambist_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(CMC_RAMBIST_parse_table, 6, "CMC_RAMBIST",
+- 0xad, regvalue, cur_col, wrap));
+-}
-
-- portno = simple_strtoul(buf, &tmp, 16);
-- if (portno > MAX_PORTNO){
-- PRINT_WARN("portno 0x%X is out of range\n", portno);
-- return -EINVAL;
-- }
+-static ahd_reg_parse_entry_t CCSCBCTL_parse_table[] = {
++static const ahd_reg_parse_entry_t CCSCBCTL_parse_table[] = {
+ { "CCSCBRESET", 0x01, 0x01 },
+ { "CCSCBDIR", 0x04, 0x04 },
+ { "CCSCBEN", 0x08, 0x08 },
+@@ -2582,7 +1635,7 @@ ahd_ccscbctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xad, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = {
++static const ahd_reg_parse_entry_t CCSGCTL_parse_table[] = {
+ { "CCSGRESET", 0x01, 0x01 },
+ { "SG_FETCH_REQ", 0x02, 0x02 },
+ { "CCSGENACK", 0x08, 0x08 },
+@@ -2606,13 +1659,6 @@ ahd_ccsgram_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_flexadr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "FLEXADR",
+- 0xb0, regvalue, cur_col, wrap));
+-}
-
-- card->info.portno = portno;
-- return count;
+-int
+ ahd_ccscbram_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahd_print_register(NULL, 0, "CCSCBRAM",
+@@ -2620,39 +1666,13 @@ ahd_ccscbram_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_flexcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "FLEXCNT",
+- 0xb3, regvalue, cur_col, wrap));
-}
-
--static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);
+-static ahd_reg_parse_entry_t FLEXDMASTAT_parse_table[] = {
+- { "FLEXDMADONE", 0x01, 0x01 },
+- { "FLEXDMAERR", 0x02, 0x02 }
+-};
-
--static ssize_t
--qeth_dev_portname_show(struct device *dev, struct device_attribute *attr, char *buf)
+-int
+-ahd_flexdmastat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct qeth_card *card = dev->driver_data;
-- char portname[9] = {0, };
+- return (ahd_print_register(FLEXDMASTAT_parse_table, 2, "FLEXDMASTAT",
+- 0xb5, regvalue, cur_col, wrap));
+-}
-
-- if (!card)
-- return -EINVAL;
+-int
+-ahd_flexdata_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "FLEXDATA",
+- 0xb6, regvalue, cur_col, wrap));
+-}
-
-- 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");
+-int
+ ahd_brddat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahd_print_register(NULL, 0, "BRDDAT",
+ 0xb8, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t BRDCTL_parse_table[] = {
++static const ahd_reg_parse_entry_t BRDCTL_parse_table[] = {
+ { "BRDSTB", 0x01, 0x01 },
+ { "BRDRW", 0x02, 0x02 },
+ { "BRDEN", 0x04, 0x04 },
+@@ -2682,7 +1702,7 @@ ahd_seedat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xbc, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SEECTL_parse_table[] = {
++static const ahd_reg_parse_entry_t SEECTL_parse_table[] = {
+ { "SEEOP_ERAL", 0x40, 0x70 },
+ { "SEEOP_WRITE", 0x50, 0x70 },
+ { "SEEOP_READ", 0x60, 0x70 },
+@@ -2702,7 +1722,7 @@ ahd_seectl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xbe, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SEESTAT_parse_table[] = {
++static const ahd_reg_parse_entry_t SEESTAT_parse_table[] = {
+ { "SEESTART", 0x01, 0x01 },
+ { "SEEBUSY", 0x02, 0x02 },
+ { "SEEARBACK", 0x04, 0x04 },
+@@ -2718,34 +1738,7 @@ ahd_seestat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xbe, regvalue, cur_col, wrap));
+ }
+
+-int
+-ahd_scbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "SCBCNT",
+- 0xbf, regvalue, cur_col, wrap));
-}
-
--static ssize_t
--qeth_dev_portname_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-int
+-ahd_dfwaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct qeth_card *card = dev->driver_data;
-- char *tmp;
-- int i;
+- return (ahd_print_register(NULL, 0, "DFWADDR",
+- 0xc0, regvalue, cur_col, wrap));
+-}
-
-- if (!card)
-- return -EINVAL;
+-static ahd_reg_parse_entry_t DSPFLTRCTL_parse_table[] = {
+- { "DSPFCNTSEL", 0x0f, 0x0f },
+- { "EDGESENSE", 0x10, 0x10 },
+- { "FLTRDISABLE", 0x20, 0x20 }
+-};
-
-- if ((card->state != CARD_STATE_DOWN) &&
-- (card->state != CARD_STATE_RECOVER))
-- return -EPERM;
+-int
+-ahd_dspfltrctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(DSPFLTRCTL_parse_table, 3, "DSPFLTRCTL",
+- 0xc0, regvalue, cur_col, wrap));
+-}
-
-- tmp = strsep((char **) &buf, "\n");
-- if ((strlen(tmp) > 8) || (strlen(tmp) == 0))
-- return -EINVAL;
+-static ahd_reg_parse_entry_t DSPDATACTL_parse_table[] = {
++static const ahd_reg_parse_entry_t DSPDATACTL_parse_table[] = {
+ { "XMITOFFSTDIS", 0x02, 0x02 },
+ { "RCVROFFSTDIS", 0x04, 0x04 },
+ { "DESQDIS", 0x10, 0x10 },
+@@ -2760,44 +1753,13 @@ ahd_dspdatactl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_dfraddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "DFRADDR",
+- 0xc2, regvalue, cur_col, wrap));
+-}
-
-- 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);
+-static ahd_reg_parse_entry_t DSPREQCTL_parse_table[] = {
+- { "MANREQDLY", 0x3f, 0x3f },
+- { "MANREQCTL", 0xc0, 0xc0 }
+-};
-
-- return count;
+-int
+-ahd_dspreqctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(DSPREQCTL_parse_table, 2, "DSPREQCTL",
+- 0xc2, regvalue, cur_col, wrap));
-}
-
--static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
-- qeth_dev_portname_store);
+-static ahd_reg_parse_entry_t DSPACKCTL_parse_table[] = {
+- { "MANACKDLY", 0x3f, 0x3f },
+- { "MANACKCTL", 0xc0, 0xc0 }
+-};
-
--static ssize_t
--qeth_dev_checksum_show(struct device *dev, struct device_attribute *attr, char *buf)
+-int
+-ahd_dspackctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct qeth_card *card = dev->driver_data;
+- return (ahd_print_register(DSPACKCTL_parse_table, 2, "DSPACKCTL",
+- 0xc3, regvalue, cur_col, wrap));
+-}
-
-- if (!card)
-- return -EINVAL;
+-int
+ ahd_dfdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahd_print_register(NULL, 0, "DFDAT",
+ 0xc4, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t DSPSELECT_parse_table[] = {
++static const ahd_reg_parse_entry_t DSPSELECT_parse_table[] = {
+ { "DSPSEL", 0x1f, 0x1f },
+ { "AUTOINCEN", 0x80, 0x80 }
+ };
+@@ -2809,7 +1771,7 @@ ahd_dspselect_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xc4, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t WRTBIASCTL_parse_table[] = {
++static const ahd_reg_parse_entry_t WRTBIASCTL_parse_table[] = {
+ { "XMITMANVAL", 0x3f, 0x3f },
+ { "AUTOXBCDIS", 0x80, 0x80 }
+ };
+@@ -2821,91 +1783,7 @@ ahd_wrtbiasctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xc5, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t RCVRBIOSCTL_parse_table[] = {
+- { "RCVRMANVAL", 0x3f, 0x3f },
+- { "AUTORBCDIS", 0x80, 0x80 }
+-};
-
-- return sprintf(buf, "%s checksumming\n", qeth_get_checksum_str(card));
+-int
+-ahd_rcvrbiosctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(RCVRBIOSCTL_parse_table, 2, "RCVRBIOSCTL",
+- 0xc6, regvalue, cur_col, wrap));
-}
-
--static ssize_t
--qeth_dev_checksum_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-int
+-ahd_wrtbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct qeth_card *card = dev->driver_data;
-- char *tmp;
--
-- if (!card)
-- return -EINVAL;
+- return (ahd_print_register(NULL, 0, "WRTBIASCALC",
+- 0xc7, regvalue, cur_col, wrap));
+-}
-
-- if ((card->state != CARD_STATE_DOWN) &&
-- (card->state != CARD_STATE_RECOVER))
-- return -EPERM;
+-int
+-ahd_rcvrbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "RCVRBIASCALC",
+- 0xc8, regvalue, cur_col, wrap));
+-}
-
-- 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;
+-int
+-ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "DFPTRS",
+- 0xc8, regvalue, cur_col, wrap));
-}
-
--static DEVICE_ATTR(checksumming, 0644, qeth_dev_checksum_show,
-- qeth_dev_checksum_store);
+-int
+-ahd_skewcalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "SKEWCALC",
+- 0xc9, regvalue, cur_col, wrap));
+-}
-
--static ssize_t
--qeth_dev_prioqing_show(struct device *dev, struct device_attribute *attr, char *buf)
+-int
+-ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct qeth_card *card = dev->driver_data;
+- return (ahd_print_register(NULL, 0, "DFBKPTR",
+- 0xc9, regvalue, cur_col, wrap));
+-}
-
-- if (!card)
-- return -EINVAL;
+-static ahd_reg_parse_entry_t DFDBCTL_parse_table[] = {
+- { "DFF_RAMBIST_EN", 0x01, 0x01 },
+- { "DFF_RAMBIST_DONE", 0x02, 0x02 },
+- { "DFF_RAMBIST_FAIL", 0x04, 0x04 },
+- { "DFF_DIR_ERR", 0x08, 0x08 },
+- { "DFF_CIO_RD_RDY", 0x10, 0x10 },
+- { "DFF_CIO_WR_RDY", 0x20, 0x20 }
+-};
-
-- 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);
-- }
+-int
+-ahd_dfdbctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(DFDBCTL_parse_table, 6, "DFDBCTL",
+- 0xcb, regvalue, cur_col, wrap));
-}
-
--static ssize_t
--qeth_dev_prioqing_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-int
+-ahd_dfscnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct qeth_card *card = dev->driver_data;
-- char *tmp;
+- return (ahd_print_register(NULL, 0, "DFSCNT",
+- 0xcc, regvalue, cur_col, wrap));
+-}
-
-- if (!card)
-- return -EINVAL;
+-int
+-ahd_dfbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "DFBCNT",
+- 0xce, regvalue, cur_col, wrap));
+-}
-
-- if ((card->state != CARD_STATE_DOWN) &&
-- (card->state != CARD_STATE_RECOVER))
-- return -EPERM;
+-int
+-ahd_ovlyaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "OVLYADDR",
+- 0xd4, regvalue, cur_col, wrap));
+-}
-
-- /* 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;
-- }
+-static ahd_reg_parse_entry_t SEQCTL0_parse_table[] = {
++static const ahd_reg_parse_entry_t SEQCTL0_parse_table[] = {
+ { "LOADRAM", 0x01, 0x01 },
+ { "SEQRESET", 0x02, 0x02 },
+ { "STEP", 0x04, 0x04 },
+@@ -2923,21 +1801,7 @@ ahd_seqctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xd6, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SEQCTL1_parse_table[] = {
+- { "RAMBIST_EN", 0x01, 0x01 },
+- { "RAMBIST_FAIL", 0x02, 0x02 },
+- { "RAMBIST_DONE", 0x04, 0x04 },
+- { "OVRLAY_DATA_CHK", 0x08, 0x08 }
+-};
-
-- 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;
+-int
+-ahd_seqctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(SEQCTL1_parse_table, 4, "SEQCTL1",
+- 0xd7, regvalue, cur_col, wrap));
-}
-
--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)
+-static ahd_reg_parse_entry_t FLAGS_parse_table[] = {
++static const ahd_reg_parse_entry_t FLAGS_parse_table[] = {
+ { "CARRY", 0x01, 0x01 },
+ { "ZERO", 0x02, 0x02 }
+ };
+@@ -2949,7 +1813,7 @@ ahd_flags_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xd8, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SEQINTCTL_parse_table[] = {
++static const ahd_reg_parse_entry_t SEQINTCTL_parse_table[] = {
+ { "IRET", 0x01, 0x01 },
+ { "INTMASK1", 0x02, 0x02 },
+ { "INTMASK2", 0x04, 0x04 },
+@@ -3002,24 +1866,6 @@ ahd_dindex_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct qeth_card *card = dev->driver_data;
+- return (ahd_print_register(NULL, 0, "BRKADDR0",
+- 0xe6, regvalue, cur_col, wrap));
+-}
-
-- if (!card)
-- return -EINVAL;
+-static ahd_reg_parse_entry_t BRKADDR1_parse_table[] = {
+- { "BRKDIS", 0x80, 0x80 }
+-};
-
-- return sprintf(buf, "%i\n", card->qdio.in_buf_pool.buf_count);
+-int
+-ahd_brkaddr1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(BRKADDR1_parse_table, 1, "BRKADDR1",
+- 0xe6, regvalue, cur_col, wrap));
-}
-
--static ssize_t
--qeth_dev_bufcnt_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-int
+ ahd_allones_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahd_print_register(NULL, 0, "ALLONES",
+@@ -3055,13 +1901,6 @@ ahd_dindir_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_function1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- 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;
+- return (ahd_print_register(NULL, 0, "FUNCTION1",
+- 0xf0, regvalue, cur_col, wrap));
+-}
-
-- 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;
+-int
+ ahd_stack_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahd_print_register(NULL, 0, "STACK",
+@@ -3083,13 +1922,6 @@ ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_lastaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "LASTADDR",
+- 0xf6, regvalue, cur_col, wrap));
-}
-
--static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
-- qeth_dev_bufcnt_store);
+-int
+ ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahd_print_register(NULL, 0, "INTVEC2_ADDR",
+@@ -3111,23 +1943,16 @@ ahd_accum_save_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_waiting_scb_tails_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "WAITING_SCB_TAILS",
+- 0x100, regvalue, cur_col, wrap));
+-}
-
--static ssize_t
--qeth_dev_route_show(struct qeth_card *card, struct qeth_routing_info *route,
-- char *buf)
+-int
+-ahd_ahd_pci_config_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
++ahd_sram_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+- return (ahd_print_register(NULL, 0, "AHD_PCI_CONFIG_BASE",
++ return (ahd_print_register(NULL, 0, "SRAM_BASE",
+ 0x100, regvalue, cur_col, wrap));
+ }
+
+ int
+-ahd_sram_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
++ahd_waiting_scb_tails_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+- return (ahd_print_register(NULL, 0, "SRAM_BASE",
++ return (ahd_print_register(NULL, 0, "WAITING_SCB_TAILS",
+ 0x100, regvalue, cur_col, wrap));
+ }
+
+@@ -3215,7 +2040,7 @@ ahd_msg_out_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x137, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t DMAPARAMS_parse_table[] = {
++static const ahd_reg_parse_entry_t DMAPARAMS_parse_table[] = {
+ { "FIFORESET", 0x01, 0x01 },
+ { "FIFOFLUSH", 0x02, 0x02 },
+ { "DIRECTION", 0x04, 0x04 },
+@@ -3235,7 +2060,7 @@ ahd_dmaparams_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x138, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
++static const ahd_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
+ { "NO_DISCONNECT", 0x01, 0x01 },
+ { "SPHASE_PENDING", 0x02, 0x02 },
+ { "DPHASE_PENDING", 0x04, 0x04 },
+@@ -3268,7 +2093,7 @@ ahd_saved_lun_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x13b, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t LASTPHASE_parse_table[] = {
++static const ahd_reg_parse_entry_t LASTPHASE_parse_table[] = {
+ { "P_DATAOUT", 0x00, 0xe0 },
+ { "P_DATAOUT_DT", 0x20, 0xe0 },
+ { "P_DATAIN", 0x40, 0xe0 },
+@@ -3326,7 +2151,7 @@ ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x144, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t ARG_1_parse_table[] = {
++static const ahd_reg_parse_entry_t ARG_1_parse_table[] = {
+ { "CONT_MSG_LOOP_TARG", 0x02, 0x02 },
+ { "CONT_MSG_LOOP_READ", 0x03, 0x03 },
+ { "CONT_MSG_LOOP_WRITE",0x04, 0x04 },
+@@ -3358,7 +2183,7 @@ ahd_last_msg_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x14a, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = {
++static const ahd_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = {
+ { "ALTSTIM", 0x01, 0x01 },
+ { "ENAUTOATNP", 0x02, 0x02 },
+ { "MANUALP", 0x0c, 0x0c },
+@@ -3381,7 +2206,7 @@ ahd_initiator_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x14c, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
++static const ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
+ { "PENDING_MK_MESSAGE", 0x01, 0x01 },
+ { "TARGET_MSG_PENDING", 0x02, 0x02 },
+ { "SELECTOUT_QFROZEN", 0x04, 0x04 }
+@@ -3465,20 +2290,20 @@ ahd_mk_message_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_scb_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
++ahd_scb_residual_datacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+- return (ahd_print_register(NULL, 0, "SCB_BASE",
++ return (ahd_print_register(NULL, 0, "SCB_RESIDUAL_DATACNT",
+ 0x180, regvalue, cur_col, wrap));
+ }
+
+ int
+-ahd_scb_residual_datacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
++ahd_scb_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+- return (ahd_print_register(NULL, 0, "SCB_RESIDUAL_DATACNT",
++ return (ahd_print_register(NULL, 0, "SCB_BASE",
+ 0x180, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SCB_RESIDUAL_SGPTR_parse_table[] = {
++static const ahd_reg_parse_entry_t SCB_RESIDUAL_SGPTR_parse_table[] = {
+ { "SG_LIST_NULL", 0x01, 0x01 },
+ { "SG_OVERRUN_RESID", 0x02, 0x02 },
+ { "SG_ADDR_MASK", 0xf8, 0xf8 }
+@@ -3499,27 +2324,6 @@ ahd_scb_scsi_status_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_scb_target_phases_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- 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");
-- }
+- return (ahd_print_register(NULL, 0, "SCB_TARGET_PHASES",
+- 0x189, regvalue, cur_col, wrap));
-}
-
--static ssize_t
--qeth_dev_route4_show(struct device *dev, struct device_attribute *attr, char *buf)
+-int
+-ahd_scb_target_data_dir_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct qeth_card *card = dev->driver_data;
+- return (ahd_print_register(NULL, 0, "SCB_TARGET_DATA_DIR",
+- 0x18a, regvalue, cur_col, wrap));
+-}
-
-- if (!card)
-- return -EINVAL;
+-int
+-ahd_scb_target_itag_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "SCB_TARGET_ITAG",
+- 0x18b, regvalue, cur_col, wrap));
+-}
-
-- return qeth_dev_route_show(card, &card->options.route4, buf);
+-int
+ ahd_scb_sense_busaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahd_print_register(NULL, 0, "SCB_SENSE_BUSADDR",
+@@ -3533,7 +2337,7 @@ ahd_scb_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x190, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SCB_CONTROL_parse_table[] = {
++static const ahd_reg_parse_entry_t SCB_CONTROL_parse_table[] = {
+ { "SCB_TAG_TYPE", 0x03, 0x03 },
+ { "DISCONNECTED", 0x04, 0x04 },
+ { "STATUS_RCVD", 0x08, 0x08 },
+@@ -3550,7 +2354,7 @@ ahd_scb_control_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x192, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SCB_SCSIID_parse_table[] = {
++static const ahd_reg_parse_entry_t SCB_SCSIID_parse_table[] = {
+ { "OID", 0x0f, 0x0f },
+ { "TID", 0xf0, 0xf0 }
+ };
+@@ -3562,7 +2366,7 @@ ahd_scb_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x193, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SCB_LUN_parse_table[] = {
++static const ahd_reg_parse_entry_t SCB_LUN_parse_table[] = {
+ { "LID", 0xff, 0xff }
+ };
+
+@@ -3573,7 +2377,7 @@ ahd_scb_lun_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x194, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SCB_TASK_ATTRIBUTE_parse_table[] = {
++static const ahd_reg_parse_entry_t SCB_TASK_ATTRIBUTE_parse_table[] = {
+ { "SCB_XFERLEN_ODD", 0x01, 0x01 }
+ };
+
+@@ -3584,7 +2388,7 @@ ahd_scb_task_attribute_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x195, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SCB_CDB_LEN_parse_table[] = {
++static const ahd_reg_parse_entry_t SCB_CDB_LEN_parse_table[] = {
+ { "SCB_CDB_LEN_PTR", 0x80, 0x80 }
+ };
+
+@@ -3609,7 +2413,7 @@ ahd_scb_dataptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x198, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SCB_DATACNT_parse_table[] = {
++static const ahd_reg_parse_entry_t SCB_DATACNT_parse_table[] = {
+ { "SG_HIGH_ADDR_BITS", 0x7f, 0x7f },
+ { "SG_LAST_SEG", 0x80, 0x80 }
+ };
+@@ -3621,7 +2425,7 @@ ahd_scb_datacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x1a0, regvalue, cur_col, wrap));
+ }
+
+-static ahd_reg_parse_entry_t SCB_SGPTR_parse_table[] = {
++static const ahd_reg_parse_entry_t SCB_SGPTR_parse_table[] = {
+ { "SG_LIST_NULL", 0x01, 0x01 },
+ { "SG_FULL_RESID", 0x02, 0x02 },
+ { "SG_STATUS_VALID", 0x04, 0x04 }
+@@ -3656,13 +2460,6 @@ ahd_scb_next2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahd_scb_spare_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahd_print_register(NULL, 0, "SCB_SPARE",
+- 0x1b0, regvalue, cur_col, wrap));
-}
-
--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)
+-int
+ ahd_scb_disconnected_lists_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahd_print_register(NULL, 0, "SCB_DISCONNECTED_LISTS",
+diff --git a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
+index 11bed07..4b51e23 100644
+--- a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
++++ b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
+@@ -5,7 +5,7 @@
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $
+ */
+-static uint8_t seqprog[] = {
++static const uint8_t seqprog[] = {
+ 0xff, 0x02, 0x06, 0x78,
+ 0x00, 0xea, 0x6e, 0x59,
+ 0x01, 0xea, 0x04, 0x30,
+@@ -1027,7 +1027,7 @@ ahd_patch0_func(struct ahd_softc *ahd)
+ return (0);
+ }
+
+-static struct patch {
++static const struct patch {
+ ahd_patch_func_t *patch_func;
+ uint32_t begin :10,
+ skip_instr :10,
+@@ -1166,7 +1166,7 @@ static struct patch {
+ { ahd_patch23_func, 815, 11, 1 }
+ };
+
+-static struct cs {
++static const struct cs {
+ uint16_t begin;
+ uint16_t end;
+ } critical_sections[] = {
+diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h
+index c0344e6..e4e651c 100644
+--- a/drivers/scsi/aic7xxx/aic7xxx.h
++++ b/drivers/scsi/aic7xxx/aic7xxx.h
+@@ -736,7 +736,7 @@ struct ahc_syncrate {
+ #define ST_SXFR 0x010 /* Rate Single Transition Only */
+ #define DT_SXFR 0x040 /* Rate Double Transition Only */
+ uint8_t period; /* Period to send to SCSI target */
+- char *rate;
++ const char *rate;
+ };
+
+ /* Safe and valid period for async negotiations. */
+@@ -1114,7 +1114,7 @@ typedef int (ahc_device_setup_t)(struct ahc_softc *);
+ struct ahc_pci_identity {
+ uint64_t full_id;
+ uint64_t id_mask;
+- char *name;
++ const char *name;
+ ahc_device_setup_t *setup;
+ };
+
+@@ -1133,15 +1133,11 @@ extern const int ahc_num_aic7770_devs;
+
+ /*************************** Function Declarations ****************************/
+ /******************************************************************************/
+-u_int ahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl);
+-void ahc_unbusy_tcl(struct ahc_softc *ahc, u_int tcl);
+-void ahc_busy_tcl(struct ahc_softc *ahc,
+- u_int tcl, u_int busyid);
+
+ /***************************** PCI Front End *********************************/
+-struct ahc_pci_identity *ahc_find_pci_device(ahc_dev_softc_t);
++const struct ahc_pci_identity *ahc_find_pci_device(ahc_dev_softc_t);
+ int ahc_pci_config(struct ahc_softc *,
+- struct ahc_pci_identity *);
++ const struct ahc_pci_identity *);
+ int ahc_pci_test_register_access(struct ahc_softc *);
+ #ifdef CONFIG_PM
+ void ahc_pci_resume(struct ahc_softc *ahc);
+@@ -1155,9 +1151,6 @@ int aic7770_config(struct ahc_softc *ahc,
+
+ /************************** SCB and SCB queue management **********************/
+ int ahc_probe_scbs(struct ahc_softc *);
+-void ahc_run_untagged_queues(struct ahc_softc *ahc);
+-void ahc_run_untagged_queue(struct ahc_softc *ahc,
+- struct scb_tailq *queue);
+ void ahc_qinfifo_requeue_tail(struct ahc_softc *ahc,
+ struct scb *scb);
+ int ahc_match_scb(struct ahc_softc *ahc, struct scb *scb,
+@@ -1178,22 +1171,8 @@ int ahc_resume(struct ahc_softc *ahc);
+ #endif
+ void ahc_set_unit(struct ahc_softc *, int);
+ void ahc_set_name(struct ahc_softc *, char *);
+-void ahc_alloc_scbs(struct ahc_softc *ahc);
+ void ahc_free(struct ahc_softc *ahc);
+ int ahc_reset(struct ahc_softc *ahc, int reinit);
+-void ahc_shutdown(void *arg);
+-
+-/*************************** Interrupt Services *******************************/
+-void ahc_clear_intstat(struct ahc_softc *ahc);
+-void ahc_run_qoutfifo(struct ahc_softc *ahc);
+-#ifdef AHC_TARGET_MODE
+-void ahc_run_tqinfifo(struct ahc_softc *ahc, int paused);
+-#endif
+-void ahc_handle_brkadrint(struct ahc_softc *ahc);
+-void ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat);
+-void ahc_handle_scsiint(struct ahc_softc *ahc,
+- u_int intstat);
+-void ahc_clear_critical_section(struct ahc_softc *ahc);
+
+ /***************************** Error Recovery *********************************/
+ typedef enum {
+@@ -1214,36 +1193,19 @@ int ahc_search_disc_list(struct ahc_softc *ahc, int target,
+ char channel, int lun, u_int tag,
+ int stop_on_first, int remove,
+ int save_state);
+-void ahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb);
+ int ahc_reset_channel(struct ahc_softc *ahc, char channel,
+ int initiate_reset);
+-int ahc_abort_scbs(struct ahc_softc *ahc, int target,
+- char channel, int lun, u_int tag,
+- role_t role, uint32_t status);
+-void ahc_restart(struct ahc_softc *ahc);
+-void ahc_calc_residual(struct ahc_softc *ahc,
+- struct scb *scb);
++
+ /*************************** Utility Functions ********************************/
+-struct ahc_phase_table_entry*
+- ahc_lookup_phase_entry(int phase);
+ void ahc_compile_devinfo(struct ahc_devinfo *devinfo,
+ u_int our_id, u_int target,
+ u_int lun, char channel,
+ role_t role);
+ /************************** Transfer Negotiation ******************************/
+-struct ahc_syncrate* ahc_find_syncrate(struct ahc_softc *ahc, u_int *period,
++const struct ahc_syncrate* ahc_find_syncrate(struct ahc_softc *ahc, u_int *period,
+ u_int *ppr_options, u_int maxsync);
+ u_int ahc_find_period(struct ahc_softc *ahc,
+ u_int scsirate, u_int maxsync);
+-void ahc_validate_offset(struct ahc_softc *ahc,
+- struct ahc_initiator_tinfo *tinfo,
+- struct ahc_syncrate *syncrate,
+- u_int *offset, int wide,
+- role_t role);
+-void ahc_validate_width(struct ahc_softc *ahc,
+- struct ahc_initiator_tinfo *tinfo,
+- u_int *bus_width,
+- role_t role);
+ /*
+ * Negotiation types. These are used to qualify if we should renegotiate
+ * even if our goal and current transport parameters are identical.
+@@ -1263,7 +1225,7 @@ void ahc_set_width(struct ahc_softc *ahc,
+ u_int width, u_int type, int paused);
+ void ahc_set_syncrate(struct ahc_softc *ahc,
+ struct ahc_devinfo *devinfo,
+- struct ahc_syncrate *syncrate,
++ const struct ahc_syncrate *syncrate,
+ u_int period, u_int offset,
+ u_int ppr_options,
+ u_int type, int paused);
+@@ -1305,11 +1267,10 @@ extern uint32_t ahc_debug;
+ #define AHC_SHOW_MASKED_ERRORS 0x1000
+ #define AHC_DEBUG_SEQUENCER 0x2000
+ #endif
+-void ahc_print_scb(struct scb *scb);
+ void ahc_print_devinfo(struct ahc_softc *ahc,
+ struct ahc_devinfo *dev);
+ void ahc_dump_card_state(struct ahc_softc *ahc);
+-int ahc_print_register(ahc_reg_parse_entry_t *table,
++int ahc_print_register(const ahc_reg_parse_entry_t *table,
+ u_int num_entries,
+ const char *name,
+ u_int address,
+diff --git a/drivers/scsi/aic7xxx/aic7xxx.reg b/drivers/scsi/aic7xxx/aic7xxx.reg
+index e196d83..0d2f763 100644
+--- a/drivers/scsi/aic7xxx/aic7xxx.reg
++++ b/drivers/scsi/aic7xxx/aic7xxx.reg
+@@ -238,6 +238,7 @@ register SXFRCTL2 {
+ register OPTIONMODE {
+ address 0x008
+ access_mode RW
++ count 2
+ field AUTORATEEN 0x80
+ field AUTOACKEN 0x40
+ field ATNMGMNTEN 0x20
+@@ -254,6 +255,7 @@ register TARGCRCCNT {
+ address 0x00a
+ size 2
+ access_mode RW
++ count 2
+ }
+
+ /*
+@@ -344,6 +346,7 @@ register SSTAT2 {
+ register SSTAT3 {
+ address 0x00e
+ access_mode RO
++ count 2
+ mask SCSICNT 0xf0
+ mask OFFCNT 0x0f
+ mask U2OFFCNT 0x7f
+@@ -367,6 +370,7 @@ register SCSIID_ULTRA2 {
+ register SIMODE0 {
+ address 0x010
+ access_mode RW
++ count 2
+ field ENSELDO 0x40
+ field ENSELDI 0x20
+ field ENSELINGO 0x10
+@@ -429,6 +433,7 @@ register SHADDR {
+ register SELTIMER {
+ address 0x018
+ access_mode RW
++ count 1
+ field STAGE6 0x20
+ field STAGE5 0x10
+ field STAGE4 0x08
+@@ -467,6 +472,7 @@ register TARGID {
+ address 0x01b
+ size 2
+ access_mode RW
++ count 14
+ }
+
+ /*
+@@ -480,6 +486,7 @@ register TARGID {
+ register SPIOCAP {
+ address 0x01b
+ access_mode RW
++ count 10
+ field SOFT1 0x80
+ field SOFT0 0x40
+ field SOFTCMDEN 0x20
+@@ -492,6 +499,7 @@ register SPIOCAP {
+
+ register BRDCTL {
+ address 0x01d
++ count 11
+ field BRDDAT7 0x80
+ field BRDDAT6 0x40
+ field BRDDAT5 0x20
+@@ -534,6 +542,7 @@ register BRDCTL {
+ */
+ register SEECTL {
+ address 0x01e
++ count 11
+ field EXTARBACK 0x80
+ field EXTARBREQ 0x40
+ field SEEMS 0x20
+@@ -570,6 +579,7 @@ register SBLKCTL {
+ register SEQCTL {
+ address 0x060
+ access_mode RW
++ count 15
+ field PERRORDIS 0x80
+ field PAUSEDIS 0x40
+ field FAILDIS 0x20
+@@ -590,6 +600,7 @@ register SEQCTL {
+ register SEQRAM {
+ address 0x061
+ access_mode RW
++ count 2
+ }
+
+ /*
+@@ -604,6 +615,7 @@ register SEQADDR0 {
+ register SEQADDR1 {
+ address 0x063
+ access_mode RW
++ count 8
+ mask SEQADDR1_MASK 0x01
+ }
+
+@@ -649,6 +661,7 @@ register NONE {
+ register FLAGS {
+ address 0x06b
+ access_mode RO
++ count 18
+ field ZERO 0x02
+ field CARRY 0x01
+ }
+@@ -671,6 +684,7 @@ register FUNCTION1 {
+ register STACK {
+ address 0x06f
+ access_mode RO
++ count 5
+ }
+
+ const STACK_SIZE 4
+@@ -692,6 +706,7 @@ register BCTL {
+ register DSCOMMAND0 {
+ address 0x084
+ access_mode RW
++ count 7
+ field CACHETHEN 0x80 /* Cache Threshold enable */
+ field DPARCKEN 0x40 /* Data Parity Check Enable */
+ field MPARCKEN 0x20 /* Memory Parity Check Enable */
+@@ -717,6 +732,7 @@ register DSCOMMAND1 {
+ register BUSTIME {
+ address 0x085
+ access_mode RW
++ count 2
+ mask BOFF 0xf0
+ mask BON 0x0f
+ }
+@@ -727,6 +743,7 @@ register BUSTIME {
+ register BUSSPD {
+ address 0x086
+ access_mode RW
++ count 2
+ mask DFTHRSH 0xc0
+ mask STBOFF 0x38
+ mask STBON 0x07
+@@ -737,6 +754,7 @@ register BUSSPD {
+ /* aic7850/55/60/70/80/95 only */
+ register DSPCISTATUS {
+ address 0x086
++ count 4
+ mask DFTHRSH_100 0xc0
+ }
+
+@@ -758,6 +776,7 @@ const SEQ_MAILBOX_SHIFT 0
+ register HCNTRL {
+ address 0x087
+ access_mode RW
++ count 14
+ field POWRDN 0x40
+ field SWINT 0x10
+ field IRQMS 0x08
+@@ -869,6 +888,7 @@ register INTSTAT {
+ register ERROR {
+ address 0x092
+ access_mode RO
++ count 26
+ field CIOPARERR 0x80 /* Ultra2 only */
+ field PCIERRSTAT 0x40 /* PCI only */
+ field MPARERR 0x20 /* PCI only */
+@@ -885,6 +905,7 @@ register ERROR {
+ register CLRINT {
+ address 0x092
+ access_mode WO
++ count 24
+ field CLRPARERR 0x10 /* PCI only */
+ field CLRBRKADRINT 0x08
+ field CLRSCSIINT 0x04
+@@ -943,6 +964,7 @@ register DFDAT {
+ register SCBCNT {
+ address 0x09a
+ access_mode RW
++ count 1
+ field SCBAUTO 0x80
+ mask SCBCNT_MASK 0x1f
+ }
+@@ -954,6 +976,7 @@ register SCBCNT {
+ register QINFIFO {
+ address 0x09b
+ access_mode RW
++ count 12
+ }
+
+ /*
+@@ -972,11 +995,13 @@ register QINCNT {
+ register QOUTFIFO {
+ address 0x09d
+ access_mode WO
++ count 7
+ }
+
+ register CRCCONTROL1 {
+ address 0x09d
+ access_mode RW
++ count 3
+ field CRCONSEEN 0x80
+ field CRCVALCHKEN 0x40
+ field CRCENDCHKEN 0x20
+@@ -1013,6 +1038,7 @@ register SCSIPHASE {
+ register SFUNCT {
+ address 0x09f
+ access_mode RW
++ count 4
+ field ALT_MODE 0x80
+ }
+
+@@ -1095,6 +1121,7 @@ scb {
+ }
+ SCB_SCSIOFFSET {
+ size 1
++ count 1
+ }
+ SCB_NEXT {
+ size 1
+@@ -1118,6 +1145,7 @@ const SG_SIZEOF 0x08 /* sizeof(struct ahc_dma) */
+ register SEECTL_2840 {
+ address 0x0c0
+ access_mode RW
++ count 2
+ field CS_2840 0x04
+ field CK_2840 0x02
+ field DO_2840 0x01
+@@ -1126,6 +1154,7 @@ register SEECTL_2840 {
+ register STATUS_2840 {
+ address 0x0c1
+ access_mode RW
++ count 4
+ field EEPROM_TF 0x80
+ mask BIOS_SEL 0x60
+ mask ADSEL 0x1e
+@@ -1161,6 +1190,7 @@ register CCSGCTL {
+
+ register CCSCBCNT {
+ address 0xEF
++ count 1
+ }
+
+ register CCSCBCTL {
+@@ -1187,6 +1217,7 @@ register CCSCBRAM {
+ register SCBBADDR {
+ address 0x0F0
+ access_mode RW
++ count 3
+ }
+
+ register CCSCBPTR {
+@@ -1195,6 +1226,7 @@ register CCSCBPTR {
+
+ register HNSCB_QOFF {
+ address 0x0F4
++ count 4
+ }
+
+ register SNSCB_QOFF {
+@@ -1234,6 +1266,7 @@ register DFF_THRSH {
+ mask WR_DFTHRSH_85 0x50
+ mask WR_DFTHRSH_90 0x60
+ mask WR_DFTHRSH_MAX 0x70
++ count 4
+ }
+
+ register SG_CACHE_PRE {
+@@ -1287,6 +1320,7 @@ scratch_ram {
+ ULTRA_ENB {
+ alias CMDSIZE_TABLE
+ size 2
++ count 2
+ }
+ /*
+ * Bit vector of targets that have disconnection disabled as set by
+@@ -1296,6 +1330,7 @@ scratch_ram {
+ */
+ DISC_DSB {
+ size 2
++ count 6
+ }
+ CMDSIZE_TABLE_TAIL {
+ size 4
+@@ -1323,6 +1358,7 @@ scratch_ram {
+ /* Parameters for DMA Logic */
+ DMAPARAMS {
+ size 1
++ count 12
+ field PRELOADEN 0x80
+ field WIDEODD 0x40
+ field SCSIEN 0x20
+@@ -1436,11 +1472,12 @@ scratch_ram {
+ KERNEL_TQINPOS {
+ size 1
+ }
+- TQINPOS {
++ TQINPOS {
+ size 1
+ }
+ ARG_1 {
+ size 1
++ count 1
+ mask SEND_MSG 0x80
+ mask SEND_SENSE 0x40
+ mask SEND_REJ 0x20
+@@ -1495,6 +1532,7 @@ scratch_ram {
+ size 1
+ field HA_274_EXTENDED_TRANS 0x01
+ alias INITIATOR_TAG
++ count 1
+ }
+
+ SEQ_FLAGS2 {
+@@ -1518,6 +1556,7 @@ scratch_ram {
+ */
+ SCSICONF {
+ size 1
++ count 12
+ field TERM_ENB 0x80
+ field RESET_SCSI 0x40
+ field ENSPCHK 0x20
+@@ -1527,16 +1566,19 @@ scratch_ram {
+ INTDEF {
+ address 0x05c
+ size 1
++ count 1
+ field EDGE_TRIG 0x80
+ mask VECTOR 0x0f
+ }
+ HOSTCONF {
+ address 0x05d
+ size 1
++ count 1
+ }
+ HA_274_BIOSCTRL {
+ address 0x05f
+ size 1
++ count 1
+ mask BIOSMODE 0x30
+ mask BIOSDISABLED 0x30
+ field CHANNEL_B_PRIMARY 0x08
+@@ -1552,6 +1594,7 @@ scratch_ram {
+ */
+ TARG_OFFSET {
+ size 16
++ count 1
+ }
+ }
+
+diff --git a/drivers/scsi/aic7xxx/aic7xxx_93cx6.c b/drivers/scsi/aic7xxx/aic7xxx_93cx6.c
+index 3cb07e1..dd11999 100644
+--- a/drivers/scsi/aic7xxx/aic7xxx_93cx6.c
++++ b/drivers/scsi/aic7xxx/aic7xxx_93cx6.c
+@@ -84,16 +84,16 @@ struct seeprom_cmd {
+ };
+
+ /* Short opcodes for the c46 */
+-static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
+-static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
++static const struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
++static const struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
+
+ /* Long opcodes for the C56/C66 */
+-static struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
+-static struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
++static const struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
++static const struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
+
+ /* Common opcodes */
+-static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}};
+-static struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
++static const struct seeprom_cmd seeprom_write = {3, {1, 0, 1}};
++static const struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
+
+ /*
+ * Wait for the SEERDY to go high; about 800 ns.
+@@ -108,7 +108,7 @@ static struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
+ * Send a START condition and the given command
+ */
+ static void
+-send_seeprom_cmd(struct seeprom_descriptor *sd, struct seeprom_cmd *cmd)
++send_seeprom_cmd(struct seeprom_descriptor *sd, const struct seeprom_cmd *cmd)
+ {
+ uint8_t temp;
+ int i = 0;
+@@ -227,7 +227,7 @@ int
+ ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
+ u_int start_addr, u_int count)
+ {
+- struct seeprom_cmd *ewen, *ewds;
++ const struct seeprom_cmd *ewen, *ewds;
+ uint16_t v;
+ uint8_t temp;
+ int i, k;
+diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c
+index 64e62ce..0ae2b46 100644
+--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
++++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
+@@ -51,8 +51,7 @@
+ #endif
+
+ /***************************** Lookup Tables **********************************/
+-char *ahc_chip_names[] =
-{
-- enum qeth_routing_types old_route_type = route->type;
-- char *tmp;
-- int rc;
++static const char *const ahc_chip_names[] = {
+ "NONE",
+ "aic7770",
+ "aic7850",
+@@ -75,10 +74,10 @@ static const u_int num_chip_names = ARRAY_SIZE(ahc_chip_names);
+ */
+ struct ahc_hard_error_entry {
+ uint8_t errno;
+- char *errmesg;
++ const char *errmesg;
+ };
+
+-static struct ahc_hard_error_entry ahc_hard_errors[] = {
++static const struct ahc_hard_error_entry ahc_hard_errors[] = {
+ { ILLHADDR, "Illegal Host Access" },
+ { ILLSADDR, "Illegal Sequencer Address referrenced" },
+ { ILLOPCODE, "Illegal Opcode in sequencer program" },
+@@ -90,7 +89,7 @@ static struct ahc_hard_error_entry ahc_hard_errors[] = {
+ };
+ static const u_int num_errors = ARRAY_SIZE(ahc_hard_errors);
+
+-static struct ahc_phase_table_entry ahc_phase_table[] =
++static const struct ahc_phase_table_entry ahc_phase_table[] =
+ {
+ { P_DATAOUT, MSG_NOOP, "in Data-out phase" },
+ { P_DATAIN, MSG_INITIATOR_DET_ERR, "in Data-in phase" },
+@@ -115,7 +114,7 @@ static const u_int num_phases = ARRAY_SIZE(ahc_phase_table) - 1;
+ * Provides a mapping of tranfer periods in ns to the proper value to
+ * stick in the scsixfer reg.
+ */
+-static struct ahc_syncrate ahc_syncrates[] =
++static const struct ahc_syncrate ahc_syncrates[] =
+ {
+ /* ultra2 fast/ultra period rate */
+ { 0x42, 0x000, 9, "80.0" },
+@@ -148,7 +147,7 @@ static struct ahc_tmode_tstate*
+ static void ahc_free_tstate(struct ahc_softc *ahc,
+ u_int scsi_id, char channel, int force);
+ #endif
+-static struct ahc_syncrate*
++static const struct ahc_syncrate*
+ ahc_devlimited_syncrate(struct ahc_softc *ahc,
+ struct ahc_initiator_tinfo *,
+ u_int *period,
+@@ -204,9 +203,9 @@ static void ahc_setup_target_msgin(struct ahc_softc *ahc,
+ #endif
+
+ static bus_dmamap_callback_t ahc_dmamap_cb;
+-static void ahc_build_free_scb_list(struct ahc_softc *ahc);
+-static int ahc_init_scbdata(struct ahc_softc *ahc);
+-static void ahc_fini_scbdata(struct ahc_softc *ahc);
++static void ahc_build_free_scb_list(struct ahc_softc *ahc);
++static int ahc_init_scbdata(struct ahc_softc *ahc);
++static void ahc_fini_scbdata(struct ahc_softc *ahc);
+ static void ahc_qinfifo_requeue(struct ahc_softc *ahc,
+ struct scb *prev_scb,
+ struct scb *scb);
+@@ -222,7 +221,7 @@ static void ahc_dumpseq(struct ahc_softc *ahc);
+ #endif
+ static int ahc_loadseq(struct ahc_softc *ahc);
+ static int ahc_check_patch(struct ahc_softc *ahc,
+- struct patch **start_patch,
++ const struct patch **start_patch,
+ u_int start_instr, u_int *skip_addr);
+ static void ahc_download_instr(struct ahc_softc *ahc,
+ u_int instrptr, uint8_t *dconsts);
+@@ -237,11 +236,582 @@ static void ahc_update_scsiid(struct ahc_softc *ahc,
+ static int ahc_handle_target_cmd(struct ahc_softc *ahc,
+ struct target_cmd *cmd);
+ #endif
++
++static u_int ahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl);
++static void ahc_unbusy_tcl(struct ahc_softc *ahc, u_int tcl);
++static void ahc_busy_tcl(struct ahc_softc *ahc,
++ u_int tcl, u_int busyid);
++
++/************************** SCB and SCB queue management **********************/
++static void ahc_run_untagged_queues(struct ahc_softc *ahc);
++static void ahc_run_untagged_queue(struct ahc_softc *ahc,
++ struct scb_tailq *queue);
++
++/****************************** Initialization ********************************/
++static void ahc_alloc_scbs(struct ahc_softc *ahc);
++static void ahc_shutdown(void *arg);
++
++/*************************** Interrupt Services *******************************/
++static void ahc_clear_intstat(struct ahc_softc *ahc);
++static void ahc_run_qoutfifo(struct ahc_softc *ahc);
++#ifdef AHC_TARGET_MODE
++static void ahc_run_tqinfifo(struct ahc_softc *ahc, int paused);
++#endif
++static void ahc_handle_brkadrint(struct ahc_softc *ahc);
++static void ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat);
++static void ahc_handle_scsiint(struct ahc_softc *ahc,
++ u_int intstat);
++static void ahc_clear_critical_section(struct ahc_softc *ahc);
++
++/***************************** Error Recovery *********************************/
++static void ahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb);
++static int ahc_abort_scbs(struct ahc_softc *ahc, int target,
++ char channel, int lun, u_int tag,
++ role_t role, uint32_t status);
++static void ahc_calc_residual(struct ahc_softc *ahc,
++ struct scb *scb);
++
++/*********************** Untagged Transaction Routines ************************/
++static inline void ahc_freeze_untagged_queues(struct ahc_softc *ahc);
++static inline void ahc_release_untagged_queues(struct ahc_softc *ahc);
++
++/*
++ * Block our completion routine from starting the next untagged
++ * transaction for this target or target lun.
++ */
++static inline void
++ahc_freeze_untagged_queues(struct ahc_softc *ahc)
++{
++ if ((ahc->flags & AHC_SCB_BTT) == 0)
++ ahc->untagged_queue_lock++;
++}
++
++/*
++ * Allow the next untagged transaction for this target or target lun
++ * to be executed. We use a counting semaphore to allow the lock
++ * to be acquired recursively. Once the count drops to zero, the
++ * transaction queues will be run.
++ */
++static inline void
++ahc_release_untagged_queues(struct ahc_softc *ahc)
++{
++ if ((ahc->flags & AHC_SCB_BTT) == 0) {
++ ahc->untagged_queue_lock--;
++ if (ahc->untagged_queue_lock == 0)
++ ahc_run_untagged_queues(ahc);
++ }
++}
++
+ /************************* Sequencer Execution Control ************************/
+ /*
+- * Restart the sequencer program from address zero
++ * Work around any chip bugs related to halting sequencer execution.
++ * On Ultra2 controllers, we must clear the CIOBUS stretch signal by
++ * reading a register that will set this signal and deassert it.
++ * Without this workaround, if the chip is paused, by an interrupt or
++ * manual pause while accessing scb ram, accesses to certain registers
++ * will hang the system (infinite pci retries).
++ */
++static void
++ahc_pause_bug_fix(struct ahc_softc *ahc)
++{
++ if ((ahc->features & AHC_ULTRA2) != 0)
++ (void)ahc_inb(ahc, CCSCBCTL);
++}
++
++/*
++ * Determine whether the sequencer has halted code execution.
++ * Returns non-zero status if the sequencer is stopped.
++ */
++int
++ahc_is_paused(struct ahc_softc *ahc)
++{
++ return ((ahc_inb(ahc, HCNTRL) & PAUSE) != 0);
++}
++
++/*
++ * Request that the sequencer stop and wait, indefinitely, for it
++ * to stop. The sequencer will only acknowledge that it is paused
++ * once it has reached an instruction boundary and PAUSEDIS is
++ * cleared in the SEQCTL register. The sequencer may use PAUSEDIS
++ * for critical sections.
++ */
++void
++ahc_pause(struct ahc_softc *ahc)
++{
++ ahc_outb(ahc, HCNTRL, ahc->pause);
++
++ /*
++ * Since the sequencer can disable pausing in a critical section, we
++ * must loop until it actually stops.
++ */
++ while (ahc_is_paused(ahc) == 0)
++ ;
++
++ ahc_pause_bug_fix(ahc);
++}
++
++/*
++ * Allow the sequencer to continue program execution.
++ * We check here to ensure that no additional interrupt
++ * sources that would cause the sequencer to halt have been
++ * asserted. If, for example, a SCSI bus reset is detected
++ * while we are fielding a different, pausing, interrupt type,
++ * we don't want to release the sequencer before going back
++ * into our interrupt handler and dealing with this new
++ * condition.
++ */
++void
++ahc_unpause(struct ahc_softc *ahc)
++{
++ if ((ahc_inb(ahc, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) == 0)
++ ahc_outb(ahc, HCNTRL, ahc->unpause);
++}
++
++/************************** Memory mapping routines ***************************/
++static struct ahc_dma_seg *
++ahc_sg_bus_to_virt(struct scb *scb, uint32_t sg_busaddr)
++{
++ int sg_index;
++
++ sg_index = (sg_busaddr - scb->sg_list_phys)/sizeof(struct ahc_dma_seg);
++ /* sg_list_phys points to entry 1, not 0 */
++ sg_index++;
++
++ return (&scb->sg_list[sg_index]);
++}
++
++static uint32_t
++ahc_sg_virt_to_bus(struct scb *scb, struct ahc_dma_seg *sg)
++{
++ int sg_index;
++
++ /* sg_list_phys points to entry 1, not 0 */
++ sg_index = sg - &scb->sg_list[1];
++
++ return (scb->sg_list_phys + (sg_index * sizeof(*scb->sg_list)));
++}
++
++static uint32_t
++ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index)
++{
++ return (ahc->scb_data->hscb_busaddr
++ + (sizeof(struct hardware_scb) * index));
++}
++
++static void
++ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op)
++{
++ ahc_dmamap_sync(ahc, ahc->scb_data->hscb_dmat,
++ ahc->scb_data->hscb_dmamap,
++ /*offset*/(scb->hscb - ahc->hscbs) * sizeof(*scb->hscb),
++ /*len*/sizeof(*scb->hscb), op);
++}
++
++void
++ahc_sync_sglist(struct ahc_softc *ahc, struct scb *scb, int op)
++{
++ if (scb->sg_count == 0)
++ return;
++
++ ahc_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap,
++ /*offset*/(scb->sg_list - scb->sg_map->sg_vaddr)
++ * sizeof(struct ahc_dma_seg),
++ /*len*/sizeof(struct ahc_dma_seg) * scb->sg_count, op);
++}
++
++#ifdef AHC_TARGET_MODE
++static uint32_t
++ahc_targetcmd_offset(struct ahc_softc *ahc, u_int index)
++{
++ return (((uint8_t *)&ahc->targetcmds[index]) - ahc->qoutfifo);
++}
++#endif
++
++/*********************** Miscelaneous Support Functions ***********************/
++/*
++ * Determine whether the sequencer reported a residual
++ * for this SCB/transaction.
++ */
++static void
++ahc_update_residual(struct ahc_softc *ahc, struct scb *scb)
++{
++ uint32_t sgptr;
++
++ sgptr = ahc_le32toh(scb->hscb->sgptr);
++ if ((sgptr & SG_RESID_VALID) != 0)
++ ahc_calc_residual(ahc, scb);
++}
++
++/*
++ * Return pointers to the transfer negotiation information
++ * for the specified our_id/remote_id pair.
++ */
++struct ahc_initiator_tinfo *
++ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id,
++ u_int remote_id, struct ahc_tmode_tstate **tstate)
++{
++ /*
++ * Transfer data structures are stored from the perspective
++ * of the target role. Since the parameters for a connection
++ * in the initiator role to a given target are the same as
++ * when the roles are reversed, we pretend we are the target.
++ */
++ if (channel == 'B')
++ our_id += 8;
++ *tstate = ahc->enabled_targets[our_id];
++ return (&(*tstate)->transinfo[remote_id]);
++}
++
++uint16_t
++ahc_inw(struct ahc_softc *ahc, u_int port)
++{
++ uint16_t r = ahc_inb(ahc, port+1) << 8;
++ return r | ahc_inb(ahc, port);
++}
++
++void
++ahc_outw(struct ahc_softc *ahc, u_int port, u_int value)
++{
++ ahc_outb(ahc, port, value & 0xFF);
++ ahc_outb(ahc, port+1, (value >> 8) & 0xFF);
++}
++
++uint32_t
++ahc_inl(struct ahc_softc *ahc, u_int port)
++{
++ return ((ahc_inb(ahc, port))
++ | (ahc_inb(ahc, port+1) << 8)
++ | (ahc_inb(ahc, port+2) << 16)
++ | (ahc_inb(ahc, port+3) << 24));
++}
++
++void
++ahc_outl(struct ahc_softc *ahc, u_int port, uint32_t value)
++{
++ ahc_outb(ahc, port, (value) & 0xFF);
++ ahc_outb(ahc, port+1, ((value) >> 8) & 0xFF);
++ ahc_outb(ahc, port+2, ((value) >> 16) & 0xFF);
++ ahc_outb(ahc, port+3, ((value) >> 24) & 0xFF);
++}
++
++uint64_t
++ahc_inq(struct ahc_softc *ahc, u_int port)
++{
++ return ((ahc_inb(ahc, port))
++ | (ahc_inb(ahc, port+1) << 8)
++ | (ahc_inb(ahc, port+2) << 16)
++ | (ahc_inb(ahc, port+3) << 24)
++ | (((uint64_t)ahc_inb(ahc, port+4)) << 32)
++ | (((uint64_t)ahc_inb(ahc, port+5)) << 40)
++ | (((uint64_t)ahc_inb(ahc, port+6)) << 48)
++ | (((uint64_t)ahc_inb(ahc, port+7)) << 56));
++}
++
++void
++ahc_outq(struct ahc_softc *ahc, u_int port, uint64_t value)
++{
++ ahc_outb(ahc, port, value & 0xFF);
++ ahc_outb(ahc, port+1, (value >> 8) & 0xFF);
++ ahc_outb(ahc, port+2, (value >> 16) & 0xFF);
++ ahc_outb(ahc, port+3, (value >> 24) & 0xFF);
++ ahc_outb(ahc, port+4, (value >> 32) & 0xFF);
++ ahc_outb(ahc, port+5, (value >> 40) & 0xFF);
++ ahc_outb(ahc, port+6, (value >> 48) & 0xFF);
++ ahc_outb(ahc, port+7, (value >> 56) & 0xFF);
++}
++
++/*
++ * Get a free scb. If there are none, see if we can allocate a new SCB.
++ */
++struct scb *
++ahc_get_scb(struct ahc_softc *ahc)
++{
++ struct scb *scb;
++
++ if ((scb = SLIST_FIRST(&ahc->scb_data->free_scbs)) == NULL) {
++ ahc_alloc_scbs(ahc);
++ scb = SLIST_FIRST(&ahc->scb_data->free_scbs);
++ if (scb == NULL)
++ return (NULL);
++ }
++ SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links.sle);
++ return (scb);
++}
++
++/*
++ * Return an SCB resource to the free list.
++ */
++void
++ahc_free_scb(struct ahc_softc *ahc, struct scb *scb)
++{
++ struct hardware_scb *hscb;
++
++ hscb = scb->hscb;
++ /* Clean up for the next user */
++ ahc->scb_data->scbindex[hscb->tag] = NULL;
++ scb->flags = SCB_FREE;
++ hscb->control = 0;
++
++ SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle);
++
++ /* Notify the OSM that a resource is now available. */
++ ahc_platform_scb_free(ahc, scb);
++}
++
++struct scb *
++ahc_lookup_scb(struct ahc_softc *ahc, u_int tag)
++{
++ struct scb* scb;
++
++ scb = ahc->scb_data->scbindex[tag];
++ if (scb != NULL)
++ ahc_sync_scb(ahc, scb,
++ BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
++ return (scb);
++}
++
++static void
++ahc_swap_with_next_hscb(struct ahc_softc *ahc, struct scb *scb)
++{
++ struct hardware_scb *q_hscb;
++ u_int saved_tag;
++
++ /*
++ * Our queuing method is a bit tricky. The card
++ * knows in advance which HSCB to download, and we
++ * can't disappoint it. To achieve this, the next
++ * SCB to download is saved off in ahc->next_queued_scb.
++ * When we are called to queue "an arbitrary scb",
++ * we copy the contents of the incoming HSCB to the one
++ * the sequencer knows about, swap HSCB pointers and
++ * finally assign the SCB to the tag indexed location
++ * in the scb_array. This makes sure that we can still
++ * locate the correct SCB by SCB_TAG.
++ */
++ q_hscb = ahc->next_queued_scb->hscb;
++ saved_tag = q_hscb->tag;
++ memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
++ if ((scb->flags & SCB_CDB32_PTR) != 0) {
++ q_hscb->shared_data.cdb_ptr =
++ ahc_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag)
++ + offsetof(struct hardware_scb, cdb32));
++ }
++ q_hscb->tag = saved_tag;
++ q_hscb->next = scb->hscb->tag;
++
++ /* Now swap HSCB pointers. */
++ ahc->next_queued_scb->hscb = scb->hscb;
++ scb->hscb = q_hscb;
++
++ /* Now define the mapping from tag to SCB in the scbindex */
++ ahc->scb_data->scbindex[scb->hscb->tag] = scb;
++}
++
++/*
++ * Tell the sequencer about a new transaction to execute.
+ */
+ void
++ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb)
++{
++ ahc_swap_with_next_hscb(ahc, scb);
++
++ if (scb->hscb->tag == SCB_LIST_NULL
++ || scb->hscb->next == SCB_LIST_NULL)
++ panic("Attempt to queue invalid SCB tag %x:%x\n",
++ scb->hscb->tag, scb->hscb->next);
++
++ /*
++ * Setup data "oddness".
++ */
++ scb->hscb->lun &= LID;
++ if (ahc_get_transfer_length(scb) & 0x1)
++ scb->hscb->lun |= SCB_XFERLEN_ODD;
++
++ /*
++ * Keep a history of SCBs we've downloaded in the qinfifo.
++ */
++ ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag;
++
++ /*
++ * Make sure our data is consistent from the
++ * perspective of the adapter.
++ */
++ ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
++
++ /* Tell the adapter about the newly queued SCB */
++ if ((ahc->features & AHC_QUEUE_REGS) != 0) {
++ ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
++ } else {
++ if ((ahc->features & AHC_AUTOPAUSE) == 0)
++ ahc_pause(ahc);
++ ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext);
++ if ((ahc->features & AHC_AUTOPAUSE) == 0)
++ ahc_unpause(ahc);
++ }
++}
++
++struct scsi_sense_data *
++ahc_get_sense_buf(struct ahc_softc *ahc, struct scb *scb)
++{
++ int offset;
++
++ offset = scb - ahc->scb_data->scbarray;
++ return (&ahc->scb_data->sense[offset]);
++}
++
++static uint32_t
++ahc_get_sense_bufaddr(struct ahc_softc *ahc, struct scb *scb)
++{
++ int offset;
++
++ offset = scb - ahc->scb_data->scbarray;
++ return (ahc->scb_data->sense_busaddr
++ + (offset * sizeof(struct scsi_sense_data)));
++}
++
++/************************** Interrupt Processing ******************************/
++static void
++ahc_sync_qoutfifo(struct ahc_softc *ahc, int op)
++{
++ ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
++ /*offset*/0, /*len*/256, op);
++}
++
++static void
++ahc_sync_tqinfifo(struct ahc_softc *ahc, int op)
++{
++#ifdef AHC_TARGET_MODE
++ if ((ahc->flags & AHC_TARGETROLE) != 0) {
++ ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
++ ahc->shared_data_dmamap,
++ ahc_targetcmd_offset(ahc, 0),
++ sizeof(struct target_cmd) * AHC_TMODE_CMDS,
++ op);
++ }
++#endif
++}
++
++/*
++ * See if the firmware has posted any completed commands
++ * into our in-core command complete fifos.
++ */
++#define AHC_RUN_QOUTFIFO 0x1
++#define AHC_RUN_TQINFIFO 0x2
++static u_int
++ahc_check_cmdcmpltqueues(struct ahc_softc *ahc)
++{
++ u_int retval;
++
++ retval = 0;
++ ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
++ /*offset*/ahc->qoutfifonext, /*len*/1,
++ BUS_DMASYNC_POSTREAD);
++ if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL)
++ retval |= AHC_RUN_QOUTFIFO;
++#ifdef AHC_TARGET_MODE
++ if ((ahc->flags & AHC_TARGETROLE) != 0
++ && (ahc->flags & AHC_TQINFIFO_BLOCKED) == 0) {
++ ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
++ ahc->shared_data_dmamap,
++ ahc_targetcmd_offset(ahc, ahc->tqinfifofnext),
++ /*len*/sizeof(struct target_cmd),
++ BUS_DMASYNC_POSTREAD);
++ if (ahc->targetcmds[ahc->tqinfifonext].cmd_valid != 0)
++ retval |= AHC_RUN_TQINFIFO;
++ }
++#endif
++ return (retval);
++}
++
++/*
++ * Catch an interrupt from the adapter
++ */
++int
++ahc_intr(struct ahc_softc *ahc)
++{
++ u_int intstat;
++
++ if ((ahc->pause & INTEN) == 0) {
++ /*
++ * Our interrupt is not enabled on the chip
++ * and may be disabled for re-entrancy reasons,
++ * so just return. This is likely just a shared
++ * interrupt.
++ */
++ return (0);
++ }
++ /*
++ * Instead of directly reading the interrupt status register,
++ * infer the cause of the interrupt by checking our in-core
++ * completion queues. This avoids a costly PCI bus read in
++ * most cases.
++ */
++ if ((ahc->flags & (AHC_ALL_INTERRUPTS|AHC_EDGE_INTERRUPT)) == 0
++ && (ahc_check_cmdcmpltqueues(ahc) != 0))
++ intstat = CMDCMPLT;
++ else {
++ intstat = ahc_inb(ahc, INTSTAT);
++ }
++
++ if ((intstat & INT_PEND) == 0) {
++#if AHC_PCI_CONFIG > 0
++ if (ahc->unsolicited_ints > 500) {
++ ahc->unsolicited_ints = 0;
++ if ((ahc->chip & AHC_PCI) != 0
++ && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0)
++ ahc->bus_intr(ahc);
++ }
++#endif
++ ahc->unsolicited_ints++;
++ return (0);
++ }
++ ahc->unsolicited_ints = 0;
++
++ if (intstat & CMDCMPLT) {
++ ahc_outb(ahc, CLRINT, CLRCMDINT);
++
++ /*
++ * Ensure that the chip sees that we've cleared
++ * this interrupt before we walk the output fifo.
++ * Otherwise, we may, due to posted bus writes,
++ * clear the interrupt after we finish the scan,
++ * and after the sequencer has added new entries
++ * and asserted the interrupt again.
++ */
++ ahc_flush_device_writes(ahc);
++ ahc_run_qoutfifo(ahc);
++#ifdef AHC_TARGET_MODE
++ if ((ahc->flags & AHC_TARGETROLE) != 0)
++ ahc_run_tqinfifo(ahc, /*paused*/FALSE);
++#endif
++ }
++
++ /*
++ * Handle statuses that may invalidate our cached
++ * copy of INTSTAT separately.
++ */
++ if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0) {
++ /* Hot eject. Do nothing */
++ } else if (intstat & BRKADRINT) {
++ ahc_handle_brkadrint(ahc);
++ } else if ((intstat & (SEQINT|SCSIINT)) != 0) {
++
++ ahc_pause_bug_fix(ahc);
++
++ if ((intstat & SEQINT) != 0)
++ ahc_handle_seqint(ahc, intstat);
++
++ if ((intstat & SCSIINT) != 0)
++ ahc_handle_scsiint(ahc, intstat);
++ }
++ return (1);
++}
++
++/************************* Sequencer Execution Control ************************/
++/*
++ * Restart the sequencer program from address zero
++ */
++static void
+ ahc_restart(struct ahc_softc *ahc)
+ {
+
+@@ -302,7 +872,7 @@ ahc_restart(struct ahc_softc *ahc)
+ }
+
+ /************************* Input/Output Queues ********************************/
+-void
++static void
+ ahc_run_qoutfifo(struct ahc_softc *ahc)
+ {
+ struct scb *scb;
+@@ -349,7 +919,7 @@ ahc_run_qoutfifo(struct ahc_softc *ahc)
+ }
+ }
+
+-void
++static void
+ ahc_run_untagged_queues(struct ahc_softc *ahc)
+ {
+ int i;
+@@ -358,7 +928,7 @@ ahc_run_untagged_queues(struct ahc_softc *ahc)
+ ahc_run_untagged_queue(ahc, &ahc->untagged_queues[i]);
+ }
+
+-void
++static void
+ ahc_run_untagged_queue(struct ahc_softc *ahc, struct scb_tailq *queue)
+ {
+ struct scb *scb;
+@@ -374,7 +944,7 @@ ahc_run_untagged_queue(struct ahc_softc *ahc, struct scb_tailq *queue)
+ }
+
+ /************************* Interrupt Handling *********************************/
+-void
++static void
+ ahc_handle_brkadrint(struct ahc_softc *ahc)
+ {
+ /*
+@@ -403,7 +973,7 @@ ahc_handle_brkadrint(struct ahc_softc *ahc)
+ ahc_shutdown(ahc);
+ }
+
+-void
++static void
+ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
+ {
+ struct scb *scb;
+@@ -954,7 +1524,7 @@ unpause:
+ ahc_unpause(ahc);
+ }
+
+-void
++static void
+ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
+ {
+ u_int scb_index;
+@@ -1407,7 +1977,7 @@ ahc_force_renegotiation(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
+ }
+
+ #define AHC_MAX_STEPS 2000
+-void
++static void
+ ahc_clear_critical_section(struct ahc_softc *ahc)
+ {
+ int stepping;
+@@ -1500,7 +2070,7 @@ ahc_clear_critical_section(struct ahc_softc *ahc)
+ /*
+ * Clear any pending interrupt status.
+ */
+-void
++static void
+ ahc_clear_intstat(struct ahc_softc *ahc)
+ {
+ /* Clear any interrupt conditions this may have caused */
+@@ -1519,7 +2089,8 @@ ahc_clear_intstat(struct ahc_softc *ahc)
+ uint32_t ahc_debug = AHC_DEBUG_OPTS;
+ #endif
+
+-void
++#if 0 /* unused */
++static void
+ ahc_print_scb(struct scb *scb)
+ {
+ int i;
+@@ -1551,6 +2122,7 @@ ahc_print_scb(struct scb *scb)
+ }
+ }
+ }
++#endif
+
+ /************************* Transfer Negotiation *******************************/
+ /*
+@@ -1634,7 +2206,7 @@ ahc_free_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel, int force)
+ * by the capabilities of the bus connectivity of and sync settings for
+ * the target.
+ */
+-struct ahc_syncrate *
++const struct ahc_syncrate *
+ ahc_devlimited_syncrate(struct ahc_softc *ahc,
+ struct ahc_initiator_tinfo *tinfo,
+ u_int *period, u_int *ppr_options, role_t role)
+@@ -1689,11 +2261,11 @@ ahc_devlimited_syncrate(struct ahc_softc *ahc,
+ * Return the period and offset that should be sent to the target
+ * if this was the beginning of an SDTR.
+ */
+-struct ahc_syncrate *
++const struct ahc_syncrate *
+ ahc_find_syncrate(struct ahc_softc *ahc, u_int *period,
+ u_int *ppr_options, u_int maxsync)
+ {
+- struct ahc_syncrate *syncrate;
++ const struct ahc_syncrate *syncrate;
+
+ if ((ahc->features & AHC_DT) == 0)
+ *ppr_options &= ~MSG_EXT_PPR_DT_REQ;
+@@ -1768,7 +2340,7 @@ ahc_find_syncrate(struct ahc_softc *ahc, u_int *period,
+ u_int
+ ahc_find_period(struct ahc_softc *ahc, u_int scsirate, u_int maxsync)
+ {
+- struct ahc_syncrate *syncrate;
++ const struct ahc_syncrate *syncrate;
+
+ if ((ahc->features & AHC_ULTRA2) != 0)
+ scsirate &= SXFR_ULTRA2;
+@@ -1806,10 +2378,10 @@ ahc_find_period(struct ahc_softc *ahc, u_int scsirate, u_int maxsync)
+ * Truncate the given synchronous offset to a value the
+ * current adapter type and syncrate are capable of.
+ */
+-void
++static void
+ ahc_validate_offset(struct ahc_softc *ahc,
+ struct ahc_initiator_tinfo *tinfo,
+- struct ahc_syncrate *syncrate,
++ const struct ahc_syncrate *syncrate,
+ u_int *offset, int wide, role_t role)
+ {
+ u_int maxoffset;
+@@ -1838,7 +2410,7 @@ ahc_validate_offset(struct ahc_softc *ahc,
+ * Truncate the given transfer width parameter to a value the
+ * current adapter type is capable of.
+ */
+-void
++static void
+ ahc_validate_width(struct ahc_softc *ahc, struct ahc_initiator_tinfo *tinfo,
+ u_int *bus_width, role_t role)
+ {
+@@ -1913,7 +2485,7 @@ ahc_update_neg_request(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
+ */
+ void
+ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
+- struct ahc_syncrate *syncrate, u_int period,
++ const struct ahc_syncrate *syncrate, u_int period,
+ u_int offset, u_int ppr_options, u_int type, int paused)
+ {
+ struct ahc_initiator_tinfo *tinfo;
+@@ -2220,11 +2792,11 @@ ahc_fetch_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
+ role);
+ }
+
+-struct ahc_phase_table_entry*
++static const struct ahc_phase_table_entry*
+ ahc_lookup_phase_entry(int phase)
+ {
+- struct ahc_phase_table_entry *entry;
+- struct ahc_phase_table_entry *last_entry;
++ const struct ahc_phase_table_entry *entry;
++ const struct ahc_phase_table_entry *last_entry;
+
+ /*
+ * num_phases doesn't include the default entry which
+@@ -2390,7 +2962,7 @@ ahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
+ */
+ struct ahc_initiator_tinfo *tinfo;
+ struct ahc_tmode_tstate *tstate;
+- struct ahc_syncrate *rate;
++ const struct ahc_syncrate *rate;
+ int dowide;
+ int dosync;
+ int doppr;
+@@ -2655,7 +3227,7 @@ proto_violation_reset:
+ */
+ static void
+ ahc_handle_message_phase(struct ahc_softc *ahc)
+-{
++{
+ struct ahc_devinfo devinfo;
+ u_int bus_phase;
+ int end_session;
+@@ -3056,7 +3628,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
+ switch (ahc->msgin_buf[2]) {
+ case MSG_EXT_SDTR:
+ {
+- struct ahc_syncrate *syncrate;
++ const struct ahc_syncrate *syncrate;
+ u_int period;
+ u_int ppr_options;
+ u_int offset;
+@@ -3231,7 +3803,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
+ }
+ case MSG_EXT_PPR:
+ {
+- struct ahc_syncrate *syncrate;
++ const struct ahc_syncrate *syncrate;
+ u_int period;
+ u_int offset;
+ u_int bus_width;
+@@ -3984,7 +4556,7 @@ ahc_free(struct ahc_softc *ahc)
+ return;
+ }
+
+-void
++static void
+ ahc_shutdown(void *arg)
+ {
+ struct ahc_softc *ahc;
+@@ -4388,7 +4960,7 @@ ahc_fini_scbdata(struct ahc_softc *ahc)
+ free(scb_data->scbarray, M_DEVBUF);
+ }
+
+-void
++static void
+ ahc_alloc_scbs(struct ahc_softc *ahc)
+ {
+ struct scb_data *scb_data;
+@@ -5121,7 +5693,7 @@ ahc_resume(struct ahc_softc *ahc)
+ * Return the untagged transaction id for a given target/channel lun.
+ * Optionally, clear the entry.
+ */
+-u_int
++static u_int
+ ahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl)
+ {
+ u_int scbid;
+@@ -5142,7 +5714,7 @@ ahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl)
+ return (scbid);
+ }
+
+-void
++static void
+ ahc_unbusy_tcl(struct ahc_softc *ahc, u_int tcl)
+ {
+ u_int target_offset;
+@@ -5160,7 +5732,7 @@ ahc_unbusy_tcl(struct ahc_softc *ahc, u_int tcl)
+ }
+ }
+
+-void
++static void
+ ahc_busy_tcl(struct ahc_softc *ahc, u_int tcl, u_int scbid)
+ {
+ u_int target_offset;
+@@ -5215,7 +5787,7 @@ ahc_match_scb(struct ahc_softc *ahc, struct scb *scb, int target,
+ return match;
+ }
+
+-void
++static void
+ ahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb)
+ {
+ int target;
+@@ -5707,7 +6279,7 @@ ahc_add_curscb_to_free_list(struct ahc_softc *ahc)
+ */
+ static u_int
+ ahc_rem_wscb(struct ahc_softc *ahc, u_int scbpos, u_int prev)
+-{
++{
+ u_int curscb, next;
+
+ /*
+@@ -5756,7 +6328,7 @@ ahc_rem_wscb(struct ahc_softc *ahc, u_int scbpos, u_int prev)
+ * been modified from CAM_REQ_INPROG. This routine assumes that the sequencer
+ * is paused before it is called.
+ */
+-int
++static int
+ ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel,
+ int lun, u_int tag, role_t role, uint32_t status)
+ {
+@@ -6078,7 +6650,7 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset)
+ /*
+ * Calculate the residual for a just completed SCB.
+ */
+-void
++static void
+ ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb)
+ {
+ struct hardware_scb *hscb;
+@@ -6279,7 +6851,7 @@ ahc_loadseq(struct ahc_softc *ahc)
+ struct cs cs_table[num_critical_sections];
+ u_int begin_set[num_critical_sections];
+ u_int end_set[num_critical_sections];
+- struct patch *cur_patch;
++ const struct patch *cur_patch;
+ u_int cs_count;
+ u_int cur_cs;
+ u_int i;
+@@ -6384,11 +6956,11 @@ ahc_loadseq(struct ahc_softc *ahc)
+ }
+
+ static int
+-ahc_check_patch(struct ahc_softc *ahc, struct patch **start_patch,
++ahc_check_patch(struct ahc_softc *ahc, const struct patch **start_patch,
+ u_int start_instr, u_int *skip_addr)
+ {
+- struct patch *cur_patch;
+- struct patch *last_patch;
++ const struct patch *cur_patch;
++ const struct patch *last_patch;
+ u_int num_patches;
+
+ num_patches = ARRAY_SIZE(patches);
+@@ -6447,7 +7019,7 @@ ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts)
+ case AIC_OP_JE:
+ case AIC_OP_JZ:
+ {
+- struct patch *cur_patch;
++ const struct patch *cur_patch;
+ int address_offset;
+ u_int address;
+ u_int skip_addr;
+@@ -6545,7 +7117,7 @@ ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts)
+ }
+
+ int
+-ahc_print_register(ahc_reg_parse_entry_t *table, u_int num_entries,
++ahc_print_register(const ahc_reg_parse_entry_t *table, u_int num_entries,
+ const char *name, u_int address, u_int value,
+ u_int *cur_column, u_int wrap_point)
+ {
+@@ -7229,7 +7801,7 @@ ahc_update_scsiid(struct ahc_softc *ahc, u_int targid_mask)
+ ahc_outb(ahc, SCSIID, scsiid);
+ }
+
+-void
++static void
+ ahc_run_tqinfifo(struct ahc_softc *ahc, int paused)
+ {
+ struct target_cmd *cmd;
+diff --git a/drivers/scsi/aic7xxx/aic7xxx_inline.h b/drivers/scsi/aic7xxx/aic7xxx_inline.h
+index cba2f23..09bf2f4 100644
+--- a/drivers/scsi/aic7xxx/aic7xxx_inline.h
++++ b/drivers/scsi/aic7xxx/aic7xxx_inline.h
+@@ -46,179 +46,13 @@
+ #define _AIC7XXX_INLINE_H_
+
+ /************************* Sequencer Execution Control ************************/
+-static __inline void ahc_pause_bug_fix(struct ahc_softc *ahc);
+-static __inline int ahc_is_paused(struct ahc_softc *ahc);
+-static __inline void ahc_pause(struct ahc_softc *ahc);
+-static __inline void ahc_unpause(struct ahc_softc *ahc);
-
-- tmp = strsep((char **) &buf, "\n");
+-/*
+- * Work around any chip bugs related to halting sequencer execution.
+- * On Ultra2 controllers, we must clear the CIOBUS stretch signal by
+- * reading a register that will set this signal and deassert it.
+- * Without this workaround, if the chip is paused, by an interrupt or
+- * manual pause while accessing scb ram, accesses to certain registers
+- * will hang the system (infinite pci retries).
+- */
+-static __inline void
+-ahc_pause_bug_fix(struct ahc_softc *ahc)
+-{
+- if ((ahc->features & AHC_ULTRA2) != 0)
+- (void)ahc_inb(ahc, CCSCBCTL);
+-}
-
-- 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;
+-/*
+- * Determine whether the sequencer has halted code execution.
+- * Returns non-zero status if the sequencer is stopped.
+- */
+-static __inline int
+-ahc_is_paused(struct ahc_softc *ahc)
+-{
+- return ((ahc_inb(ahc, HCNTRL) & PAUSE) != 0);
-}
-
--static ssize_t
--qeth_dev_route4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-/*
+- * Request that the sequencer stop and wait, indefinitely, for it
+- * to stop. The sequencer will only acknowledge that it is paused
+- * once it has reached an instruction boundary and PAUSEDIS is
+- * cleared in the SEQCTL register. The sequencer may use PAUSEDIS
+- * for critical sections.
+- */
+-static __inline void
+-ahc_pause(struct ahc_softc *ahc)
-{
-- struct qeth_card *card = dev->driver_data;
+- ahc_outb(ahc, HCNTRL, ahc->pause);
-
-- if (!card)
-- return -EINVAL;
+- /*
+- * Since the sequencer can disable pausing in a critical section, we
+- * must loop until it actually stops.
+- */
+- while (ahc_is_paused(ahc) == 0)
+- ;
-
-- return qeth_dev_route_store(card, &card->options.route4,
-- QETH_PROT_IPV4, buf, count);
+- ahc_pause_bug_fix(ahc);
-}
-
--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)
+-/*
+- * Allow the sequencer to continue program execution.
+- * We check here to ensure that no additional interrupt
+- * sources that would cause the sequencer to halt have been
+- * asserted. If, for example, a SCSI bus reset is detected
+- * while we are fielding a different, pausing, interrupt type,
+- * we don't want to release the sequencer before going back
+- * into our interrupt handler and dealing with this new
+- * condition.
+- */
+-static __inline void
+-ahc_unpause(struct ahc_softc *ahc)
-{
-- struct qeth_card *card = dev->driver_data;
--
-- if (!card)
-- return -EINVAL;
+- if ((ahc_inb(ahc, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) == 0)
+- ahc_outb(ahc, HCNTRL, ahc->unpause);
+-}
-
-- if (!qeth_is_supported(card, IPA_IPV6))
-- return sprintf(buf, "%s\n", "n/a");
+-/*********************** Untagged Transaction Routines ************************/
+-static __inline void ahc_freeze_untagged_queues(struct ahc_softc *ahc);
+-static __inline void ahc_release_untagged_queues(struct ahc_softc *ahc);
-
-- return qeth_dev_route_show(card, &card->options.route6, buf);
+-/*
+- * Block our completion routine from starting the next untagged
+- * transaction for this target or target lun.
+- */
+-static __inline void
+-ahc_freeze_untagged_queues(struct ahc_softc *ahc)
+-{
+- if ((ahc->flags & AHC_SCB_BTT) == 0)
+- ahc->untagged_queue_lock++;
-}
-
--static ssize_t
--qeth_dev_route6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-/*
+- * Allow the next untagged transaction for this target or target lun
+- * to be executed. We use a counting semaphore to allow the lock
+- * to be acquired recursively. Once the count drops to zero, the
+- * transaction queues will be run.
+- */
+-static __inline void
+-ahc_release_untagged_queues(struct ahc_softc *ahc)
-{
-- 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;
+- if ((ahc->flags & AHC_SCB_BTT) == 0) {
+- ahc->untagged_queue_lock--;
+- if (ahc->untagged_queue_lock == 0)
+- ahc_run_untagged_queues(ahc);
- }
--
-- return qeth_dev_route_store(card, &card->options.route6,
-- QETH_PROT_IPV6, buf, count);
-}
++int ahc_is_paused(struct ahc_softc *ahc);
++void ahc_pause(struct ahc_softc *ahc);
++void ahc_unpause(struct ahc_softc *ahc);
+
+ /************************** Memory mapping routines ***************************/
+-static __inline struct ahc_dma_seg *
+- ahc_sg_bus_to_virt(struct scb *scb,
+- uint32_t sg_busaddr);
+-static __inline uint32_t
+- ahc_sg_virt_to_bus(struct scb *scb,
+- struct ahc_dma_seg *sg);
+-static __inline uint32_t
+- ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index);
+-static __inline void ahc_sync_scb(struct ahc_softc *ahc,
+- struct scb *scb, int op);
+-static __inline void ahc_sync_sglist(struct ahc_softc *ahc,
+- struct scb *scb, int op);
+-static __inline uint32_t
+- ahc_targetcmd_offset(struct ahc_softc *ahc,
+- u_int index);
-
--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)
+-static __inline struct ahc_dma_seg *
+-ahc_sg_bus_to_virt(struct scb *scb, uint32_t sg_busaddr)
-{
-- struct qeth_card *card = dev->driver_data;
+- int sg_index;
-
-- if (!card)
-- return -EINVAL;
+- sg_index = (sg_busaddr - scb->sg_list_phys)/sizeof(struct ahc_dma_seg);
+- /* sg_list_phys points to entry 1, not 0 */
+- sg_index++;
-
-- return sprintf(buf, "%i\n", card->options.add_hhlen);
+- return (&scb->sg_list[sg_index]);
-}
-
--static ssize_t
--qeth_dev_add_hhlen_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-static __inline uint32_t
+-ahc_sg_virt_to_bus(struct scb *scb, struct ahc_dma_seg *sg)
-{
-- 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;
+- int sg_index;
-
-- 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;
+- /* sg_list_phys points to entry 1, not 0 */
+- sg_index = sg - &scb->sg_list[1];
-
-- return count;
+- return (scb->sg_list_phys + (sg_index * sizeof(*scb->sg_list)));
-}
-
--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)
+-static __inline uint32_t
+-ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index)
-{
-- struct qeth_card *card = dev->driver_data;
--
-- if (!card)
-- return -EINVAL;
+- return (ahc->scb_data->hscb_busaddr
+- + (sizeof(struct hardware_scb) * index));
+-}
-
-- return sprintf(buf, "%i\n", card->options.fake_ll? 1:0);
+-static __inline void
+-ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op)
+-{
+- ahc_dmamap_sync(ahc, ahc->scb_data->hscb_dmat,
+- ahc->scb_data->hscb_dmamap,
+- /*offset*/(scb->hscb - ahc->hscbs) * sizeof(*scb->hscb),
+- /*len*/sizeof(*scb->hscb), op);
-}
-
--static ssize_t
--qeth_dev_fake_ll_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-static __inline void
+-ahc_sync_sglist(struct ahc_softc *ahc, struct scb *scb, int op)
-{
-- struct qeth_card *card = dev->driver_data;
-- char *tmp;
-- int i;
+- if (scb->sg_count == 0)
+- return;
-
-- if (!card)
-- return -EINVAL;
+- ahc_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap,
+- /*offset*/(scb->sg_list - scb->sg_map->sg_vaddr)
+- * sizeof(struct ahc_dma_seg),
+- /*len*/sizeof(struct ahc_dma_seg) * scb->sg_count, op);
+-}
+-
+-static __inline uint32_t
+-ahc_targetcmd_offset(struct ahc_softc *ahc, u_int index)
+-{
+- return (((uint8_t *)&ahc->targetcmds[index]) - ahc->qoutfifo);
+-}
++void ahc_sync_sglist(struct ahc_softc *ahc,
++ struct scb *scb, int op);
+
+ /******************************** Debugging ***********************************/
+ static __inline char *ahc_name(struct ahc_softc *ahc);
+@@ -231,420 +65,34 @@ ahc_name(struct ahc_softc *ahc)
+
+ /*********************** Miscellaneous Support Functions ***********************/
+
+-static __inline void ahc_update_residual(struct ahc_softc *ahc,
+- struct scb *scb);
+-static __inline struct ahc_initiator_tinfo *
+- ahc_fetch_transinfo(struct ahc_softc *ahc,
+- char channel, u_int our_id,
+- u_int remote_id,
+- struct ahc_tmode_tstate **tstate);
+-static __inline uint16_t
+- ahc_inw(struct ahc_softc *ahc, u_int port);
+-static __inline void ahc_outw(struct ahc_softc *ahc, u_int port,
+- u_int value);
+-static __inline uint32_t
+- ahc_inl(struct ahc_softc *ahc, u_int port);
+-static __inline void ahc_outl(struct ahc_softc *ahc, u_int port,
+- uint32_t value);
+-static __inline uint64_t
+- ahc_inq(struct ahc_softc *ahc, u_int port);
+-static __inline void ahc_outq(struct ahc_softc *ahc, u_int port,
+- uint64_t value);
+-static __inline struct scb*
+- ahc_get_scb(struct ahc_softc *ahc);
+-static __inline void ahc_free_scb(struct ahc_softc *ahc, struct scb *scb);
+-static __inline void ahc_swap_with_next_hscb(struct ahc_softc *ahc,
+- struct scb *scb);
+-static __inline void ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb);
+-static __inline struct scsi_sense_data *
+- ahc_get_sense_buf(struct ahc_softc *ahc,
+- struct scb *scb);
+-static __inline uint32_t
+- ahc_get_sense_bufaddr(struct ahc_softc *ahc,
+- struct scb *scb);
-
-- if ((card->state != CARD_STATE_DOWN) &&
-- (card->state != CARD_STATE_RECOVER))
-- return -EPERM;
+-/*
+- * Determine whether the sequencer reported a residual
+- * for this SCB/transaction.
+- */
+-static __inline void
+-ahc_update_residual(struct ahc_softc *ahc, struct scb *scb)
+-{
+- uint32_t sgptr;
-
-- 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;
+- sgptr = ahc_le32toh(scb->hscb->sgptr);
+- if ((sgptr & SG_RESID_VALID) != 0)
+- ahc_calc_residual(ahc, scb);
-}
-
--static DEVICE_ATTR(fake_ll, 0644, qeth_dev_fake_ll_show,
-- qeth_dev_fake_ll_store);
+-/*
+- * Return pointers to the transfer negotiation information
+- * for the specified our_id/remote_id pair.
+- */
+-static __inline struct ahc_initiator_tinfo *
+-ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id,
+- u_int remote_id, struct ahc_tmode_tstate **tstate)
+-{
+- /*
+- * Transfer data structures are stored from the perspective
+- * of the target role. Since the parameters for a connection
+- * in the initiator role to a given target are the same as
+- * when the roles are reversed, we pretend we are the target.
+- */
+- if (channel == 'B')
+- our_id += 8;
+- *tstate = ahc->enabled_targets[our_id];
+- return (&(*tstate)->transinfo[remote_id]);
+-}
-
--static ssize_t
--qeth_dev_fake_broadcast_show(struct device *dev, struct device_attribute *attr, char *buf)
+-static __inline uint16_t
+-ahc_inw(struct ahc_softc *ahc, u_int port)
-{
-- struct qeth_card *card = dev->driver_data;
+- uint16_t r = ahc_inb(ahc, port+1) << 8;
+- return r | ahc_inb(ahc, port);
+-}
-
-- if (!card)
-- return -EINVAL;
+-static __inline void
+-ahc_outw(struct ahc_softc *ahc, u_int port, u_int value)
+-{
+- ahc_outb(ahc, port, value & 0xFF);
+- ahc_outb(ahc, port+1, (value >> 8) & 0xFF);
+-}
-
-- return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
+-static __inline uint32_t
+-ahc_inl(struct ahc_softc *ahc, u_int port)
+-{
+- return ((ahc_inb(ahc, port))
+- | (ahc_inb(ahc, port+1) << 8)
+- | (ahc_inb(ahc, port+2) << 16)
+- | (ahc_inb(ahc, port+3) << 24));
-}
-
--static ssize_t
--qeth_dev_fake_broadcast_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-static __inline void
+-ahc_outl(struct ahc_softc *ahc, u_int port, uint32_t value)
-{
-- struct qeth_card *card = dev->driver_data;
-- char *tmp;
-- int i;
+- ahc_outb(ahc, port, (value) & 0xFF);
+- ahc_outb(ahc, port+1, ((value) >> 8) & 0xFF);
+- ahc_outb(ahc, port+2, ((value) >> 16) & 0xFF);
+- ahc_outb(ahc, port+3, ((value) >> 24) & 0xFF);
+-}
-
-- if (!card)
-- return -EINVAL;
+-static __inline uint64_t
+-ahc_inq(struct ahc_softc *ahc, u_int port)
+-{
+- return ((ahc_inb(ahc, port))
+- | (ahc_inb(ahc, port+1) << 8)
+- | (ahc_inb(ahc, port+2) << 16)
+- | (ahc_inb(ahc, port+3) << 24)
+- | (((uint64_t)ahc_inb(ahc, port+4)) << 32)
+- | (((uint64_t)ahc_inb(ahc, port+5)) << 40)
+- | (((uint64_t)ahc_inb(ahc, port+6)) << 48)
+- | (((uint64_t)ahc_inb(ahc, port+7)) << 56));
+-}
-
-- if ((card->state != CARD_STATE_DOWN) &&
-- (card->state != CARD_STATE_RECOVER))
-- return -EPERM;
+-static __inline void
+-ahc_outq(struct ahc_softc *ahc, u_int port, uint64_t value)
+-{
+- ahc_outb(ahc, port, value & 0xFF);
+- ahc_outb(ahc, port+1, (value >> 8) & 0xFF);
+- ahc_outb(ahc, port+2, (value >> 16) & 0xFF);
+- ahc_outb(ahc, port+3, (value >> 24) & 0xFF);
+- ahc_outb(ahc, port+4, (value >> 32) & 0xFF);
+- ahc_outb(ahc, port+5, (value >> 40) & 0xFF);
+- ahc_outb(ahc, port+6, (value >> 48) & 0xFF);
+- ahc_outb(ahc, port+7, (value >> 56) & 0xFF);
+-}
-
-- 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;
+-/*
+- * Get a free scb. If there are none, see if we can allocate a new SCB.
+- */
+-static __inline struct scb *
+-ahc_get_scb(struct ahc_softc *ahc)
+-{
+- struct scb *scb;
+-
+- if ((scb = SLIST_FIRST(&ahc->scb_data->free_scbs)) == NULL) {
+- ahc_alloc_scbs(ahc);
+- scb = SLIST_FIRST(&ahc->scb_data->free_scbs);
+- if (scb == NULL)
+- return (NULL);
- }
-- return count;
+- SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links.sle);
+- return (scb);
-}
-
--static DEVICE_ATTR(fake_broadcast, 0644, qeth_dev_fake_broadcast_show,
-- qeth_dev_fake_broadcast_store);
+-/*
+- * Return an SCB resource to the free list.
+- */
+-static __inline void
+-ahc_free_scb(struct ahc_softc *ahc, struct scb *scb)
+-{
+- struct hardware_scb *hscb;
-
--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;
+- hscb = scb->hscb;
+- /* Clean up for the next user */
+- ahc->scb_data->scbindex[hscb->tag] = NULL;
+- scb->flags = SCB_FREE;
+- hscb->control = 0;
-
-- if (!card)
-- return -EINVAL;
+- SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle);
-
-- if (card->state != CARD_STATE_UP)
-- return -EPERM;
+- /* Notify the OSM that a resource is now available. */
+- ahc_platform_scb_free(ahc, scb);
+-}
-
-- i = simple_strtoul(buf, &tmp, 16);
-- if (i == 1)
-- qeth_schedule_recovery(card);
+-static __inline struct scb *
+-ahc_lookup_scb(struct ahc_softc *ahc, u_int tag)
+-{
+- struct scb* scb;
-
-- return count;
+- scb = ahc->scb_data->scbindex[tag];
+- if (scb != NULL)
+- ahc_sync_scb(ahc, scb,
+- BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+- return (scb);
-}
-
--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)
+-static __inline void
+-ahc_swap_with_next_hscb(struct ahc_softc *ahc, struct scb *scb)
-{
-- struct qeth_card *card = dev->driver_data;
+- struct hardware_scb *q_hscb;
+- u_int saved_tag;
-
-- if (!card)
-- return -EINVAL;
+- /*
+- * Our queuing method is a bit tricky. The card
+- * knows in advance which HSCB to download, and we
+- * can't disappoint it. To achieve this, the next
+- * SCB to download is saved off in ahc->next_queued_scb.
+- * When we are called to queue "an arbitrary scb",
+- * we copy the contents of the incoming HSCB to the one
+- * the sequencer knows about, swap HSCB pointers and
+- * finally assign the SCB to the tag indexed location
+- * in the scb_array. This makes sure that we can still
+- * locate the correct SCB by SCB_TAG.
+- */
+- q_hscb = ahc->next_queued_scb->hscb;
+- saved_tag = q_hscb->tag;
+- memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
+- if ((scb->flags & SCB_CDB32_PTR) != 0) {
+- q_hscb->shared_data.cdb_ptr =
+- ahc_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag)
+- + offsetof(struct hardware_scb, cdb32));
+- }
+- q_hscb->tag = saved_tag;
+- q_hscb->next = scb->hscb->tag;
-
-- if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
-- (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
-- return sprintf(buf, "n/a\n");
+- /* Now swap HSCB pointers. */
+- ahc->next_queued_scb->hscb = scb->hscb;
+- scb->hscb = q_hscb;
-
-- return sprintf(buf, "%s\n", (card->options.broadcast_mode ==
-- QETH_TR_BROADCAST_ALLRINGS)?
-- "all rings":"local");
+- /* Now define the mapping from tag to SCB in the scbindex */
+- ahc->scb_data->scbindex[scb->hscb->tag] = scb;
-}
-
--static ssize_t
--qeth_dev_broadcast_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-/*
+- * Tell the sequencer about a new transaction to execute.
+- */
+-static __inline void
+-ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb)
-{
-- struct qeth_card *card = dev->driver_data;
-- char *tmp;
+- ahc_swap_with_next_hscb(ahc, scb);
-
-- if (!card)
-- return -EINVAL;
+- if (scb->hscb->tag == SCB_LIST_NULL
+- || scb->hscb->next == SCB_LIST_NULL)
+- panic("Attempt to queue invalid SCB tag %x:%x\n",
+- scb->hscb->tag, scb->hscb->next);
-
-- if ((card->state != CARD_STATE_DOWN) &&
-- (card->state != CARD_STATE_RECOVER))
-- return -EPERM;
+- /*
+- * Setup data "oddness".
+- */
+- scb->hscb->lun &= LID;
+- if (ahc_get_transfer_length(scb) & 0x1)
+- scb->hscb->lun |= SCB_XFERLEN_ODD;
-
-- 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;
-- }
+- /*
+- * Keep a history of SCBs we've downloaded in the qinfifo.
+- */
+- ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag;
-
-- tmp = strsep((char **) &buf, "\n");
+- /*
+- * Make sure our data is consistent from the
+- * perspective of the adapter.
+- */
+- ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
-
-- 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;
+- /* Tell the adapter about the newly queued SCB */
+- if ((ahc->features & AHC_QUEUE_REGS) != 0) {
+- ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
- } else {
-- PRINT_WARN("broadcast_mode: invalid mode %s!\n",
-- tmp);
-- return -EINVAL;
+- if ((ahc->features & AHC_AUTOPAUSE) == 0)
+- ahc_pause(ahc);
+- ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext);
+- if ((ahc->features & AHC_AUTOPAUSE) == 0)
+- ahc_unpause(ahc);
- }
-- return count;
-}
-
--static DEVICE_ATTR(broadcast_mode, 0644, qeth_dev_broadcast_mode_show,
-- qeth_dev_broadcast_mode_store);
+-static __inline struct scsi_sense_data *
+-ahc_get_sense_buf(struct ahc_softc *ahc, struct scb *scb)
+-{
+- int offset;
-
--static ssize_t
--qeth_dev_canonical_macaddr_show(struct device *dev, struct device_attribute *attr, char *buf)
+- offset = scb - ahc->scb_data->scbarray;
+- return (&ahc->scb_data->sense[offset]);
+-}
+-
+-static __inline uint32_t
+-ahc_get_sense_bufaddr(struct ahc_softc *ahc, struct scb *scb)
-{
-- struct qeth_card *card = dev->driver_data;
+- int offset;
-
-- if (!card)
-- return -EINVAL;
+- offset = scb - ahc->scb_data->scbarray;
+- return (ahc->scb_data->sense_busaddr
+- + (offset * sizeof(struct scsi_sense_data)));
+-}
++struct ahc_initiator_tinfo *
++ ahc_fetch_transinfo(struct ahc_softc *ahc,
++ char channel, u_int our_id,
++ u_int remote_id,
++ struct ahc_tmode_tstate **tstate);
++uint16_t
++ ahc_inw(struct ahc_softc *ahc, u_int port);
++void ahc_outw(struct ahc_softc *ahc, u_int port,
++ u_int value);
++uint32_t
++ ahc_inl(struct ahc_softc *ahc, u_int port);
++void ahc_outl(struct ahc_softc *ahc, u_int port,
++ uint32_t value);
++uint64_t
++ ahc_inq(struct ahc_softc *ahc, u_int port);
++void ahc_outq(struct ahc_softc *ahc, u_int port,
++ uint64_t value);
++struct scb*
++ ahc_get_scb(struct ahc_softc *ahc);
++void ahc_free_scb(struct ahc_softc *ahc, struct scb *scb);
++struct scb *
++ ahc_lookup_scb(struct ahc_softc *ahc, u_int tag);
++void ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb);
++struct scsi_sense_data *
++ ahc_get_sense_buf(struct ahc_softc *ahc,
++ struct scb *scb);
+
+ /************************** Interrupt Processing ******************************/
+-static __inline void ahc_sync_qoutfifo(struct ahc_softc *ahc, int op);
+-static __inline void ahc_sync_tqinfifo(struct ahc_softc *ahc, int op);
+-static __inline u_int ahc_check_cmdcmpltqueues(struct ahc_softc *ahc);
+-static __inline int ahc_intr(struct ahc_softc *ahc);
+-
+-static __inline void
+-ahc_sync_qoutfifo(struct ahc_softc *ahc, int op)
+-{
+- ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
+- /*offset*/0, /*len*/256, op);
+-}
+-
+-static __inline void
+-ahc_sync_tqinfifo(struct ahc_softc *ahc, int op)
+-{
+-#ifdef AHC_TARGET_MODE
+- if ((ahc->flags & AHC_TARGETROLE) != 0) {
+- ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
+- ahc->shared_data_dmamap,
+- ahc_targetcmd_offset(ahc, 0),
+- sizeof(struct target_cmd) * AHC_TMODE_CMDS,
+- op);
+- }
+-#endif
+-}
-
-- if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
-- (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
-- return sprintf(buf, "n/a\n");
+-/*
+- * See if the firmware has posted any completed commands
+- * into our in-core command complete fifos.
+- */
+-#define AHC_RUN_QOUTFIFO 0x1
+-#define AHC_RUN_TQINFIFO 0x2
+-static __inline u_int
+-ahc_check_cmdcmpltqueues(struct ahc_softc *ahc)
+-{
+- u_int retval;
-
-- return sprintf(buf, "%i\n", (card->options.macaddr_mode ==
-- QETH_TR_MACADDR_CANONICAL)? 1:0);
+- retval = 0;
+- ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
+- /*offset*/ahc->qoutfifonext, /*len*/1,
+- BUS_DMASYNC_POSTREAD);
+- if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL)
+- retval |= AHC_RUN_QOUTFIFO;
+-#ifdef AHC_TARGET_MODE
+- if ((ahc->flags & AHC_TARGETROLE) != 0
+- && (ahc->flags & AHC_TQINFIFO_BLOCKED) == 0) {
+- ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
+- ahc->shared_data_dmamap,
+- ahc_targetcmd_offset(ahc, ahc->tqinfifofnext),
+- /*len*/sizeof(struct target_cmd),
+- BUS_DMASYNC_POSTREAD);
+- if (ahc->targetcmds[ahc->tqinfifonext].cmd_valid != 0)
+- retval |= AHC_RUN_TQINFIFO;
+- }
+-#endif
+- return (retval);
-}
-
--static ssize_t
--qeth_dev_canonical_macaddr_store(struct device *dev, struct device_attribute *attr, const char *buf,
-- size_t count)
+-/*
+- * Catch an interrupt from the adapter
+- */
+-static __inline int
+-ahc_intr(struct ahc_softc *ahc)
-{
-- struct qeth_card *card = dev->driver_data;
-- char *tmp;
-- int i;
+- u_int intstat;
-
-- if (!card)
-- return -EINVAL;
+- if ((ahc->pause & INTEN) == 0) {
+- /*
+- * Our interrupt is not enabled on the chip
+- * and may be disabled for re-entrancy reasons,
+- * so just return. This is likely just a shared
+- * interrupt.
+- */
+- return (0);
+- }
+- /*
+- * Instead of directly reading the interrupt status register,
+- * infer the cause of the interrupt by checking our in-core
+- * completion queues. This avoids a costly PCI bus read in
+- * most cases.
+- */
+- if ((ahc->flags & (AHC_ALL_INTERRUPTS|AHC_EDGE_INTERRUPT)) == 0
+- && (ahc_check_cmdcmpltqueues(ahc) != 0))
+- intstat = CMDCMPLT;
+- else {
+- intstat = ahc_inb(ahc, INTSTAT);
+- }
-
-- if ((card->state != CARD_STATE_DOWN) &&
-- (card->state != CARD_STATE_RECOVER))
-- return -EPERM;
+- if ((intstat & INT_PEND) == 0) {
+-#if AHC_PCI_CONFIG > 0
+- if (ahc->unsolicited_ints > 500) {
+- ahc->unsolicited_ints = 0;
+- if ((ahc->chip & AHC_PCI) != 0
+- && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0)
+- ahc->bus_intr(ahc);
+- }
+-#endif
+- ahc->unsolicited_ints++;
+- return (0);
+- }
+- ahc->unsolicited_ints = 0;
-
-- 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;
+- if (intstat & CMDCMPLT) {
+- ahc_outb(ahc, CLRINT, CLRCMDINT);
+-
+- /*
+- * Ensure that the chip sees that we've cleared
+- * this interrupt before we walk the output fifo.
+- * Otherwise, we may, due to posted bus writes,
+- * clear the interrupt after we finish the scan,
+- * and after the sequencer has added new entries
+- * and asserted the interrupt again.
+- */
+- ahc_flush_device_writes(ahc);
+- ahc_run_qoutfifo(ahc);
+-#ifdef AHC_TARGET_MODE
+- if ((ahc->flags & AHC_TARGETROLE) != 0)
+- ahc_run_tqinfifo(ahc, /*paused*/FALSE);
+-#endif
- }
-
-- 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;
+- /*
+- * Handle statuses that may invalidate our cached
+- * copy of INTSTAT separately.
+- */
+- if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0) {
+- /* Hot eject. Do nothing */
+- } else if (intstat & BRKADRINT) {
+- ahc_handle_brkadrint(ahc);
+- } else if ((intstat & (SEQINT|SCSIINT)) != 0) {
+-
+- ahc_pause_bug_fix(ahc);
+-
+- if ((intstat & SEQINT) != 0)
+- ahc_handle_seqint(ahc, intstat);
+-
+- if ((intstat & SCSIINT) != 0)
+- ahc_handle_scsiint(ahc, intstat);
+- }
+- return (1);
+-}
++int ahc_intr(struct ahc_softc *ahc);
+
+ #endif /* _AIC7XXX_INLINE_H_ */
+diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
+index 282aff6..fd2b978 100644
+--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
++++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
+@@ -388,14 +388,83 @@ static int aic7xxx_setup(char *s);
+ static int ahc_linux_unit;
+
+
++/************************** OS Utility Wrappers *******************************/
++void
++ahc_delay(long usec)
++{
++ /*
++ * udelay on Linux can have problems for
++ * multi-millisecond waits. Wait at most
++ * 1024us per call.
++ */
++ while (usec > 0) {
++ udelay(usec % 1024);
++ usec -= 1024;
++ }
++}
++
++/***************************** Low Level I/O **********************************/
++uint8_t
++ahc_inb(struct ahc_softc * ahc, long port)
++{
++ uint8_t x;
++
++ if (ahc->tag == BUS_SPACE_MEMIO) {
++ x = readb(ahc->bsh.maddr + port);
++ } else {
++ x = inb(ahc->bsh.ioport + port);
++ }
++ mb();
++ return (x);
++}
++
++void
++ahc_outb(struct ahc_softc * ahc, long port, uint8_t val)
++{
++ if (ahc->tag == BUS_SPACE_MEMIO) {
++ writeb(val, ahc->bsh.maddr + port);
++ } else {
++ outb(val, ahc->bsh.ioport + port);
++ }
++ mb();
++}
++
++void
++ahc_outsb(struct ahc_softc * ahc, long port, uint8_t *array, int count)
++{
++ int i;
++
++ /*
++ * There is probably a more efficient way to do this on Linux
++ * but we don't use this for anything speed critical and this
++ * should work.
++ */
++ for (i = 0; i < count; i++)
++ ahc_outb(ahc, port, *array++);
++}
++
++void
++ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int count)
++{
++ int i;
++
++ /*
++ * There is probably a more efficient way to do this on Linux
++ * but we don't use this for anything speed critical and this
++ * should work.
++ */
++ for (i = 0; i < count; i++)
++ *array++ = ahc_inb(ahc, port);
++}
++
+ /********************************* Inlines ************************************/
+-static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*);
++static void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*);
+
+-static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
++static int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
+ struct ahc_dma_seg *sg,
+ dma_addr_t addr, bus_size_t len);
+
+-static __inline void
++static void
+ ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb)
+ {
+ struct scsi_cmnd *cmd;
+@@ -406,7 +475,7 @@ ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb)
+ scsi_dma_unmap(cmd);
+ }
+
+-static __inline int
++static int
+ ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
+ struct ahc_dma_seg *sg, dma_addr_t addr, bus_size_t len)
+ {
+@@ -442,13 +511,11 @@ ahc_linux_info(struct Scsi_Host *host)
+ bp = &buffer[0];
+ ahc = *(struct ahc_softc **)host->hostdata;
+ memset(bp, 0, sizeof(buffer));
+- strcpy(bp, "Adaptec AIC7XXX EISA/VLB/PCI SCSI HBA DRIVER, Rev ");
+- strcat(bp, AIC7XXX_DRIVER_VERSION);
+- strcat(bp, "\n");
+- strcat(bp, " <");
++ strcpy(bp, "Adaptec AIC7XXX EISA/VLB/PCI SCSI HBA DRIVER, Rev " AIC7XXX_DRIVER_VERSION "\n"
++ " <");
+ strcat(bp, ahc->description);
+- strcat(bp, ">\n");
+- strcat(bp, " ");
++ strcat(bp, ">\n"
++ " ");
+ ahc_controller_info(ahc, ahc_info);
+ strcat(bp, ahc_info);
+ strcat(bp, "\n");
+@@ -964,7 +1031,7 @@ aic7xxx_setup(char *s)
+ char *p;
+ char *end;
+
+- static struct {
++ static const struct {
+ const char *name;
+ uint32_t *flag;
+ } options[] = {
+@@ -1398,12 +1465,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 +1537,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;
+@@ -2313,7 +2384,7 @@ static void ahc_linux_set_period(struct scsi_target *starget, int period)
+ unsigned int ppr_options = tinfo->goal.ppr_options;
+ unsigned long flags;
+ unsigned long offset = tinfo->goal.offset;
+- struct ahc_syncrate *syncrate;
++ const struct ahc_syncrate *syncrate;
+
+ if (offset == 0)
+ offset = MAX_OFFSET;
+@@ -2357,7 +2428,7 @@ static void ahc_linux_set_offset(struct scsi_target *starget, int offset)
+ unsigned int ppr_options = 0;
+ unsigned int period = 0;
+ unsigned long flags;
+- struct ahc_syncrate *syncrate = NULL;
++ const struct ahc_syncrate *syncrate = NULL;
+
+ ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+@@ -2387,7 +2458,7 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt)
+ unsigned int period = tinfo->goal.period;
+ unsigned int width = tinfo->goal.width;
+ unsigned long flags;
+- struct ahc_syncrate *syncrate;
++ const struct ahc_syncrate *syncrate;
+
+ if (dt && spi_max_width(starget)) {
+ ppr_options |= MSG_EXT_PPR_DT_REQ;
+diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
+index b48dab4..3f7238d 100644
+--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
++++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
+@@ -365,7 +365,7 @@ struct ahc_platform_data {
+ #define AHC_LINUX_NOIRQ ((uint32_t)~0)
+ uint32_t irq; /* IRQ for this adapter */
+ uint32_t bios_address;
+- uint32_t mem_busaddr; /* Mem Base Addr */
++ resource_size_t mem_busaddr; /* Mem Base Addr */
+ };
+
+ /************************** OS Utility Wrappers *******************************/
+@@ -375,82 +375,16 @@ struct ahc_platform_data {
+ #define malloc(size, type, flags) kmalloc(size, flags)
+ #define free(ptr, type) kfree(ptr)
+
+-static __inline void ahc_delay(long);
+-static __inline void
+-ahc_delay(long usec)
+-{
+- /*
+- * udelay on Linux can have problems for
+- * multi-millisecond waits. Wait at most
+- * 1024us per call.
+- */
+- while (usec > 0) {
+- udelay(usec % 1024);
+- usec -= 1024;
- }
-- return count;
-}
++void ahc_delay(long);
+
+
+ /***************************** Low Level I/O **********************************/
+-static __inline uint8_t ahc_inb(struct ahc_softc * ahc, long port);
+-static __inline void ahc_outb(struct ahc_softc * ahc, long port, uint8_t val);
+-static __inline void ahc_outsb(struct ahc_softc * ahc, long port,
+- uint8_t *, int count);
+-static __inline void ahc_insb(struct ahc_softc * ahc, long port,
+- uint8_t *, int count);
-
--static DEVICE_ATTR(canonical_macaddr, 0644, qeth_dev_canonical_macaddr_show,
-- qeth_dev_canonical_macaddr_store);
+-static __inline uint8_t
+-ahc_inb(struct ahc_softc * ahc, long port)
+-{
+- uint8_t x;
-
--static ssize_t
--qeth_dev_layer2_show(struct device *dev, struct device_attribute *attr, char *buf)
+- if (ahc->tag == BUS_SPACE_MEMIO) {
+- x = readb(ahc->bsh.maddr + port);
+- } else {
+- x = inb(ahc->bsh.ioport + port);
+- }
+- mb();
+- return (x);
+-}
+-
+-static __inline void
+-ahc_outb(struct ahc_softc * ahc, long port, uint8_t val)
-{
-- struct qeth_card *card = dev->driver_data;
+- if (ahc->tag == BUS_SPACE_MEMIO) {
+- writeb(val, ahc->bsh.maddr + port);
+- } else {
+- outb(val, ahc->bsh.ioport + port);
+- }
+- mb();
+-}
-
-- if (!card)
-- return -EINVAL;
+-static __inline void
+-ahc_outsb(struct ahc_softc * ahc, long port, uint8_t *array, int count)
+-{
+- int i;
-
-- return sprintf(buf, "%i\n", card->options.layer2 ? 1:0);
+- /*
+- * There is probably a more efficient way to do this on Linux
+- * but we don't use this for anything speed critical and this
+- * should work.
+- */
+- for (i = 0; i < count; i++)
+- ahc_outb(ahc, port, *array++);
-}
-
--static ssize_t
--qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-static __inline void
+-ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int 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;
-- }
+- /*
+- * There is probably a more efficient way to do this on Linux
+- * but we don't use this for anything speed critical and this
+- * should work.
+- */
+- for (i = 0; i < count; i++)
+- *array++ = ahc_inb(ahc, port);
+-}
++uint8_t ahc_inb(struct ahc_softc * ahc, long port);
++void ahc_outb(struct ahc_softc * ahc, long port, uint8_t val);
++void ahc_outsb(struct ahc_softc * ahc, long port,
++ uint8_t *, int count);
++void ahc_insb(struct ahc_softc * ahc, long port,
++ uint8_t *, int count);
+
+ /**************************** Initialization **********************************/
+ int ahc_linux_register_host(struct ahc_softc *,
+@@ -464,9 +398,6 @@ struct info_str {
+ int pos;
+ };
+
+-void ahc_format_transinfo(struct info_str *info,
+- struct ahc_transinfo *tinfo);
-
-- if (((card->state != CARD_STATE_DOWN) &&
-- (card->state != CARD_STATE_RECOVER)))
-- return -EPERM;
+ /******************************** Locking *************************************/
+ /* Lock protecting internal data structures */
+
+@@ -555,61 +486,12 @@ void ahc_linux_pci_exit(void);
+ int ahc_pci_map_registers(struct ahc_softc *ahc);
+ int ahc_pci_map_int(struct ahc_softc *ahc);
+
+-static __inline uint32_t ahc_pci_read_config(ahc_dev_softc_t pci,
++uint32_t ahc_pci_read_config(ahc_dev_softc_t pci,
+ int reg, int width);
+
+-static __inline uint32_t
+-ahc_pci_read_config(ahc_dev_softc_t pci, int reg, int width)
+-{
+- switch (width) {
+- case 1:
+- {
+- uint8_t retval;
-
-- 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;
+- pci_read_config_byte(pci, reg, &retval);
+- return (retval);
+- }
+- case 2:
+- {
+- uint16_t retval;
+- pci_read_config_word(pci, reg, &retval);
+- return (retval);
+- }
+- case 4:
+- {
+- uint32_t retval;
+- pci_read_config_dword(pci, reg, &retval);
+- return (retval);
+- }
+- default:
+- panic("ahc_pci_read_config: Read size too big");
+- /* NOTREACHED */
+- return (0);
- }
-- return count;
-}
-
--static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
-- qeth_dev_layer2_store);
+-static __inline void ahc_pci_write_config(ahc_dev_softc_t pci,
+- int reg, uint32_t value,
+- int width);
-
--static ssize_t
--qeth_dev_performance_stats_show(struct device *dev, struct device_attribute *attr, char *buf)
+-static __inline void
+-ahc_pci_write_config(ahc_dev_softc_t pci, int reg, uint32_t value, int width)
-{
-- struct qeth_card *card = dev->driver_data;
--
-- if (!card)
-- return -EINVAL;
--
-- return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0);
+- switch (width) {
+- case 1:
+- pci_write_config_byte(pci, reg, value);
+- break;
+- case 2:
+- pci_write_config_word(pci, reg, value);
+- break;
+- case 4:
+- pci_write_config_dword(pci, reg, value);
+- break;
+- default:
+- panic("ahc_pci_write_config: Write size too big");
+- /* NOTREACHED */
+- }
+-}
++void ahc_pci_write_config(ahc_dev_softc_t pci,
++ int reg, uint32_t value,
++ int width);
+
+ static __inline int ahc_get_pci_function(ahc_dev_softc_t);
+ static __inline int
+diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+index 3d3eaef..00f5b98 100644
+--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
++++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+@@ -46,7 +46,7 @@
+ */
+ #define ID(x) ID_C(x, PCI_CLASS_STORAGE_SCSI)
+
+-static struct pci_device_id ahc_linux_pci_id_table[] = {
++static const struct pci_device_id ahc_linux_pci_id_table[] = {
+ /* aic7850 based controllers */
+ ID(ID_AHA_2902_04_10_15_20C_30C),
+ /* aic7860 based controllers */
+@@ -206,7 +206,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ const uint64_t mask_39bit = 0x7FFFFFFFFFULL;
+ struct ahc_softc *ahc;
+ ahc_dev_softc_t pci;
+- struct ahc_pci_identity *entry;
++ const struct ahc_pci_identity *entry;
+ char *name;
+ int error;
+ struct device *dev = &pdev->dev;
+@@ -269,6 +269,57 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ return (0);
+ }
+
++/******************************* PCI Routines *********************************/
++uint32_t
++ahc_pci_read_config(ahc_dev_softc_t pci, int reg, int width)
++{
++ switch (width) {
++ case 1:
++ {
++ uint8_t retval;
++
++ pci_read_config_byte(pci, reg, &retval);
++ return (retval);
++ }
++ case 2:
++ {
++ uint16_t retval;
++ pci_read_config_word(pci, reg, &retval);
++ return (retval);
++ }
++ case 4:
++ {
++ uint32_t retval;
++ pci_read_config_dword(pci, reg, &retval);
++ return (retval);
++ }
++ default:
++ panic("ahc_pci_read_config: Read size too big");
++ /* NOTREACHED */
++ return (0);
++ }
++}
++
++void
++ahc_pci_write_config(ahc_dev_softc_t pci, int reg, uint32_t value, int width)
++{
++ switch (width) {
++ case 1:
++ pci_write_config_byte(pci, reg, value);
++ break;
++ case 2:
++ pci_write_config_word(pci, reg, value);
++ break;
++ case 4:
++ pci_write_config_dword(pci, reg, value);
++ break;
++ default:
++ panic("ahc_pci_write_config: Write size too big");
++ /* NOTREACHED */
++ }
++}
++
++
+ static struct pci_driver aic7xxx_pci_driver = {
+ .name = "aic7xxx",
+ .probe = ahc_linux_pci_dev_probe,
+@@ -293,7 +344,7 @@ ahc_linux_pci_exit(void)
+ }
+
+ static int
+-ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, u_long *base)
++ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, resource_size_t *base)
+ {
+ if (aic7xxx_allow_memio == 0)
+ return (ENOMEM);
+@@ -301,24 +352,24 @@ ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, u_long *base)
+ *base = pci_resource_start(ahc->dev_softc, 0);
+ if (*base == 0)
+ return (ENOMEM);
+- if (request_region(*base, 256, "aic7xxx") == 0)
++ if (!request_region(*base, 256, "aic7xxx"))
+ return (ENOMEM);
+ return (0);
+ }
+
+ static int
+ ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
+- u_long *bus_addr,
++ resource_size_t *bus_addr,
+ uint8_t __iomem **maddr)
+ {
+- u_long start;
++ resource_size_t start;
+ int error;
+
+ error = 0;
+ start = pci_resource_start(ahc->dev_softc, 1);
+ if (start != 0) {
+ *bus_addr = start;
+- if (request_mem_region(start, 0x1000, "aic7xxx") == 0)
++ if (!request_mem_region(start, 0x1000, "aic7xxx"))
+ error = ENOMEM;
+ if (error == 0) {
+ *maddr = ioremap_nocache(start, 256);
+@@ -336,7 +387,7 @@ int
+ ahc_pci_map_registers(struct ahc_softc *ahc)
+ {
+ uint32_t command;
+- u_long base;
++ resource_size_t base;
+ uint8_t __iomem *maddr;
+ int error;
+
+@@ -374,12 +425,12 @@ ahc_pci_map_registers(struct ahc_softc *ahc)
+ } else
+ command |= PCIM_CMD_MEMEN;
+ } else {
+- printf("aic7xxx: PCI%d:%d:%d MEM region 0x%lx "
++ printf("aic7xxx: PCI%d:%d:%d MEM region 0x%llx "
+ "unavailable. Cannot memory map device.\n",
+ ahc_get_pci_bus(ahc->dev_softc),
+ ahc_get_pci_slot(ahc->dev_softc),
+ ahc_get_pci_function(ahc->dev_softc),
+- base);
++ (unsigned long long)base);
+ }
+
+ /*
+@@ -390,15 +441,15 @@ ahc_pci_map_registers(struct ahc_softc *ahc)
+ error = ahc_linux_pci_reserve_io_region(ahc, &base);
+ if (error == 0) {
+ ahc->tag = BUS_SPACE_PIO;
+- ahc->bsh.ioport = base;
++ ahc->bsh.ioport = (u_long)base;
+ command |= PCIM_CMD_PORTEN;
+ } else {
+- printf("aic7xxx: PCI%d:%d:%d IO region 0x%lx[0..255] "
++ printf("aic7xxx: PCI%d:%d:%d IO region 0x%llx[0..255] "
+ "unavailable. Cannot map device.\n",
+ ahc_get_pci_bus(ahc->dev_softc),
+ ahc_get_pci_slot(ahc->dev_softc),
+ ahc_get_pci_function(ahc->dev_softc),
+- base);
++ (unsigned long long)base);
+ }
+ }
+ ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, 4);
+diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
+index 56848f4..c07cb6e 100644
+--- a/drivers/scsi/aic7xxx/aic7xxx_pci.c
++++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c
+@@ -168,8 +168,7 @@ static ahc_device_setup_t ahc_aha394XX_setup;
+ static ahc_device_setup_t ahc_aha494XX_setup;
+ static ahc_device_setup_t ahc_aha398XX_setup;
+
+-static struct ahc_pci_identity ahc_pci_ident_table [] =
+-{
++static const struct ahc_pci_identity ahc_pci_ident_table[] = {
+ /* aic7850 based controllers */
+ {
+ ID_AHA_2902_04_10_15_20C_30C,
+@@ -668,7 +667,7 @@ ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor,
+ return (result);
+ }
+
+-struct ahc_pci_identity *
++const struct ahc_pci_identity *
+ ahc_find_pci_device(ahc_dev_softc_t pci)
+ {
+ uint64_t full_id;
+@@ -676,7 +675,7 @@ ahc_find_pci_device(ahc_dev_softc_t pci)
+ uint16_t vendor;
+ uint16_t subdevice;
+ uint16_t subvendor;
+- struct ahc_pci_identity *entry;
++ const struct ahc_pci_identity *entry;
+ u_int i;
+
+ vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
+@@ -710,7 +709,7 @@ ahc_find_pci_device(ahc_dev_softc_t pci)
+ }
+
+ int
+-ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
++ahc_pci_config(struct ahc_softc *ahc, const struct ahc_pci_identity *entry)
+ {
+ u_int command;
+ u_int our_id;
+diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c
+index 99e5443..e92991a 100644
+--- a/drivers/scsi/aic7xxx/aic7xxx_proc.c
++++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c
+@@ -58,7 +58,7 @@ static int ahc_proc_write_seeprom(struct ahc_softc *ahc,
+ * Table of syncrates that don't follow the "divisible by 4"
+ * rule. This table will be expanded in future SCSI specs.
+ */
+-static struct {
++static const struct {
+ u_int period_factor;
+ u_int period; /* in 100ths of ns */
+ } scsi_syncrates[] = {
+@@ -137,7 +137,7 @@ copy_info(struct info_str *info, char *fmt, ...)
+ return (len);
+ }
+
+-void
++static void
+ ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo)
+ {
+ u_int speed;
+diff --git a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
+index 88bfd76..309a562 100644
+--- a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
++++ b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
+@@ -8,7 +8,7 @@
+
+ #include "aic7xxx_osm.h"
+
+-static ahc_reg_parse_entry_t SCSISEQ_parse_table[] = {
++static const ahc_reg_parse_entry_t SCSISEQ_parse_table[] = {
+ { "SCSIRSTO", 0x01, 0x01 },
+ { "ENAUTOATNP", 0x02, 0x02 },
+ { "ENAUTOATNI", 0x04, 0x04 },
+@@ -26,7 +26,7 @@ ahc_scsiseq_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x00, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SXFRCTL0_parse_table[] = {
++static const ahc_reg_parse_entry_t SXFRCTL0_parse_table[] = {
+ { "CLRCHN", 0x02, 0x02 },
+ { "SCAMEN", 0x04, 0x04 },
+ { "SPIOEN", 0x08, 0x08 },
+@@ -43,7 +43,7 @@ ahc_sxfrctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x01, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SXFRCTL1_parse_table[] = {
++static const ahc_reg_parse_entry_t SXFRCTL1_parse_table[] = {
+ { "STPWEN", 0x01, 0x01 },
+ { "ACTNEGEN", 0x02, 0x02 },
+ { "ENSTIMER", 0x04, 0x04 },
+@@ -60,7 +60,7 @@ ahc_sxfrctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x02, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SCSISIGO_parse_table[] = {
++static const ahc_reg_parse_entry_t SCSISIGO_parse_table[] = {
+ { "ACKO", 0x01, 0x01 },
+ { "REQO", 0x02, 0x02 },
+ { "BSYO", 0x04, 0x04 },
+@@ -85,7 +85,7 @@ ahc_scsisigo_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x03, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SCSISIGI_parse_table[] = {
++static const ahc_reg_parse_entry_t SCSISIGI_parse_table[] = {
+ { "ACKI", 0x01, 0x01 },
+ { "REQI", 0x02, 0x02 },
+ { "BSYI", 0x04, 0x04 },
+@@ -112,7 +112,7 @@ ahc_scsisigi_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x03, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SCSIRATE_parse_table[] = {
++static const ahc_reg_parse_entry_t SCSIRATE_parse_table[] = {
+ { "SINGLE_EDGE", 0x10, 0x10 },
+ { "ENABLE_CRC", 0x40, 0x40 },
+ { "WIDEXFER", 0x80, 0x80 },
+@@ -128,7 +128,7 @@ ahc_scsirate_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x04, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SCSIID_parse_table[] = {
++static const ahc_reg_parse_entry_t SCSIID_parse_table[] = {
+ { "TWIN_CHNLB", 0x80, 0x80 },
+ { "OID", 0x0f, 0x0f },
+ { "TWIN_TID", 0x70, 0x70 },
+@@ -151,20 +151,13 @@ ahc_scsidatl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahc_scsidath_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahc_print_register(NULL, 0, "SCSIDATH",
+- 0x07, regvalue, cur_col, wrap));
-}
-
--static ssize_t
--qeth_dev_performance_stats_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-int
+ ahc_stcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahc_print_register(NULL, 0, "STCNT",
+ 0x08, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t OPTIONMODE_parse_table[] = {
++static const ahc_reg_parse_entry_t OPTIONMODE_parse_table[] = {
+ { "DIS_MSGIN_DUALEDGE", 0x01, 0x01 },
+ { "AUTO_MSGOUT_DE", 0x02, 0x02 },
+ { "SCSIDATL_IMGEN", 0x04, 0x04 },
+@@ -190,7 +183,7 @@ ahc_targcrccnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x0a, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t CLRSINT0_parse_table[] = {
++static const ahc_reg_parse_entry_t CLRSINT0_parse_table[] = {
+ { "CLRSPIORDY", 0x02, 0x02 },
+ { "CLRSWRAP", 0x08, 0x08 },
+ { "CLRIOERR", 0x08, 0x08 },
+@@ -206,7 +199,7 @@ ahc_clrsint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x0b, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SSTAT0_parse_table[] = {
++static const ahc_reg_parse_entry_t SSTAT0_parse_table[] = {
+ { "DMADONE", 0x01, 0x01 },
+ { "SPIORDY", 0x02, 0x02 },
+ { "SDONE", 0x04, 0x04 },
+@@ -225,7 +218,7 @@ ahc_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x0b, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t CLRSINT1_parse_table[] = {
++static const ahc_reg_parse_entry_t CLRSINT1_parse_table[] = {
+ { "CLRREQINIT", 0x01, 0x01 },
+ { "CLRPHASECHG", 0x02, 0x02 },
+ { "CLRSCSIPERR", 0x04, 0x04 },
+@@ -242,7 +235,7 @@ ahc_clrsint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x0c, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SSTAT1_parse_table[] = {
++static const ahc_reg_parse_entry_t SSTAT1_parse_table[] = {
+ { "REQINIT", 0x01, 0x01 },
+ { "PHASECHG", 0x02, 0x02 },
+ { "SCSIPERR", 0x04, 0x04 },
+@@ -260,7 +253,7 @@ ahc_sstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x0c, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SSTAT2_parse_table[] = {
++static const ahc_reg_parse_entry_t SSTAT2_parse_table[] = {
+ { "DUAL_EDGE_ERR", 0x01, 0x01 },
+ { "CRCREQERR", 0x02, 0x02 },
+ { "CRCENDERR", 0x04, 0x04 },
+@@ -278,7 +271,7 @@ ahc_sstat2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x0d, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SSTAT3_parse_table[] = {
++static const ahc_reg_parse_entry_t SSTAT3_parse_table[] = {
+ { "OFFCNT", 0x0f, 0x0f },
+ { "U2OFFCNT", 0x7f, 0x7f },
+ { "SCSICNT", 0xf0, 0xf0 }
+@@ -291,7 +284,7 @@ ahc_sstat3_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x0e, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SCSIID_ULTRA2_parse_table[] = {
++static const ahc_reg_parse_entry_t SCSIID_ULTRA2_parse_table[] = {
+ { "OID", 0x0f, 0x0f },
+ { "TID", 0xf0, 0xf0 }
+ };
+@@ -303,7 +296,7 @@ ahc_scsiid_ultra2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x0f, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SIMODE0_parse_table[] = {
++static const ahc_reg_parse_entry_t SIMODE0_parse_table[] = {
+ { "ENDMADONE", 0x01, 0x01 },
+ { "ENSPIORDY", 0x02, 0x02 },
+ { "ENSDONE", 0x04, 0x04 },
+@@ -321,7 +314,7 @@ ahc_simode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x10, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SIMODE1_parse_table[] = {
++static const ahc_reg_parse_entry_t SIMODE1_parse_table[] = {
+ { "ENREQINIT", 0x01, 0x01 },
+ { "ENPHASECHG", 0x02, 0x02 },
+ { "ENSCSIPERR", 0x04, 0x04 },
+@@ -347,33 +340,13 @@ ahc_scsibusl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahc_scsibush_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct qeth_card *card = dev->driver_data;
-- char *tmp;
-- int i;
+- return (ahc_print_register(NULL, 0, "SCSIBUSH",
+- 0x13, regvalue, cur_col, wrap));
+-}
-
-- if (!card)
-- return -EINVAL;
+-static ahc_reg_parse_entry_t SXFRCTL2_parse_table[] = {
+- { "CMDDMAEN", 0x08, 0x08 },
+- { "AUTORSTDIS", 0x10, 0x10 },
+- { "ASYNC_SETUP", 0x07, 0x07 }
+-};
-
-- 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;
+-int
+-ahc_sxfrctl2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahc_print_register(SXFRCTL2_parse_table, 3, "SXFRCTL2",
+- 0x13, regvalue, cur_col, wrap));
-}
-
--static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show,
-- qeth_dev_performance_stats_store);
+-int
+ ahc_shaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahc_print_register(NULL, 0, "SHADDR",
+ 0x14, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SELTIMER_parse_table[] = {
++static const ahc_reg_parse_entry_t SELTIMER_parse_table[] = {
+ { "STAGE1", 0x01, 0x01 },
+ { "STAGE2", 0x02, 0x02 },
+ { "STAGE3", 0x04, 0x04 },
+@@ -389,7 +362,7 @@ ahc_seltimer_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x18, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SELID_parse_table[] = {
++static const ahc_reg_parse_entry_t SELID_parse_table[] = {
+ { "ONEBIT", 0x08, 0x08 },
+ { "SELID_MASK", 0xf0, 0xf0 }
+ };
+@@ -401,21 +374,6 @@ ahc_selid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x19, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SCAMCTL_parse_table[] = {
+- { "DFLTTID", 0x10, 0x10 },
+- { "ALTSTIM", 0x20, 0x20 },
+- { "CLRSCAMSELID", 0x40, 0x40 },
+- { "ENSCAMSELO", 0x80, 0x80 },
+- { "SCAMLVL", 0x03, 0x03 }
+-};
-
--static ssize_t
--qeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf)
+-int
+-ahc_scamctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct qeth_card *card = dev->driver_data;
+- return (ahc_print_register(SCAMCTL_parse_table, 5, "SCAMCTL",
+- 0x1a, regvalue, cur_col, wrap));
+-}
-
-- if (!card)
-- return -EINVAL;
+ int
+ ahc_targid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+@@ -423,7 +381,7 @@ ahc_targid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x1b, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SPIOCAP_parse_table[] = {
++static const ahc_reg_parse_entry_t SPIOCAP_parse_table[] = {
+ { "SSPIOCPS", 0x01, 0x01 },
+ { "ROM", 0x02, 0x02 },
+ { "EEPROM", 0x04, 0x04 },
+@@ -441,7 +399,7 @@ ahc_spiocap_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x1b, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t BRDCTL_parse_table[] = {
++static const ahc_reg_parse_entry_t BRDCTL_parse_table[] = {
+ { "BRDCTL0", 0x01, 0x01 },
+ { "BRDSTB_ULTRA2", 0x01, 0x01 },
+ { "BRDCTL1", 0x02, 0x02 },
+@@ -464,7 +422,7 @@ ahc_brdctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x1d, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SEECTL_parse_table[] = {
++static const ahc_reg_parse_entry_t SEECTL_parse_table[] = {
+ { "SEEDI", 0x01, 0x01 },
+ { "SEEDO", 0x02, 0x02 },
+ { "SEECK", 0x04, 0x04 },
+@@ -482,7 +440,7 @@ ahc_seectl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x1e, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SBLKCTL_parse_table[] = {
++static const ahc_reg_parse_entry_t SBLKCTL_parse_table[] = {
+ { "XCVR", 0x01, 0x01 },
+ { "SELWIDE", 0x02, 0x02 },
+ { "ENAB20", 0x04, 0x04 },
+@@ -522,13 +480,6 @@ ahc_disc_dsb_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahc_cmdsize_table_tail_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahc_print_register(NULL, 0, "CMDSIZE_TABLE_TAIL",
+- 0x34, regvalue, cur_col, wrap));
+-}
-
-- 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");
-- }
+-int
+ ahc_mwi_residual_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahc_print_register(NULL, 0, "MWI_RESIDUAL",
+@@ -549,7 +500,7 @@ ahc_msg_out_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x3a, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t DMAPARAMS_parse_table[] = {
++static const ahc_reg_parse_entry_t DMAPARAMS_parse_table[] = {
+ { "FIFORESET", 0x01, 0x01 },
+ { "FIFOFLUSH", 0x02, 0x02 },
+ { "DIRECTION", 0x04, 0x04 },
+@@ -569,7 +520,7 @@ ahc_dmaparams_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x3b, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
++static const ahc_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
+ { "NO_DISCONNECT", 0x01, 0x01 },
+ { "SPHASE_PENDING", 0x02, 0x02 },
+ { "DPHASE_PENDING", 0x04, 0x04 },
+@@ -602,7 +553,7 @@ ahc_saved_lun_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x3e, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t LASTPHASE_parse_table[] = {
++static const ahc_reg_parse_entry_t LASTPHASE_parse_table[] = {
+ { "MSGI", 0x20, 0x20 },
+ { "IOI", 0x40, 0x40 },
+ { "CDI", 0x80, 0x80 },
+@@ -645,13 +596,6 @@ ahc_free_scbh_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahc_complete_scbh_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahc_print_register(NULL, 0, "COMPLETE_SCBH",
+- 0x43, regvalue, cur_col, wrap));
-}
-
--static ssize_t
--qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-int
+ ahc_hscb_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahc_print_register(NULL, 0, "HSCB_ADDR",
+@@ -700,7 +644,7 @@ ahc_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x50, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t ARG_1_parse_table[] = {
++static const ahc_reg_parse_entry_t ARG_1_parse_table[] = {
+ { "CONT_TARG_SESSION", 0x02, 0x02 },
+ { "CONT_MSG_LOOP", 0x04, 0x04 },
+ { "EXIT_MSG_LOOP", 0x08, 0x08 },
+@@ -731,7 +675,7 @@ ahc_last_msg_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x53, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = {
++static const ahc_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = {
+ { "ENAUTOATNP", 0x02, 0x02 },
+ { "ENAUTOATNI", 0x04, 0x04 },
+ { "ENAUTOATNO", 0x08, 0x08 },
+@@ -747,7 +691,7 @@ ahc_scsiseq_template_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x54, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t HA_274_BIOSGLOBAL_parse_table[] = {
++static const ahc_reg_parse_entry_t HA_274_BIOSGLOBAL_parse_table[] = {
+ { "HA_274_EXTENDED_TRANS",0x01, 0x01 }
+ };
+
+@@ -758,7 +702,7 @@ ahc_ha_274_biosglobal_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x56, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
++static const ahc_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
+ { "SCB_DMA", 0x01, 0x01 },
+ { "TARGET_MSG_PENDING", 0x02, 0x02 }
+ };
+@@ -770,7 +714,7 @@ ahc_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x57, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SCSICONF_parse_table[] = {
++static const ahc_reg_parse_entry_t SCSICONF_parse_table[] = {
+ { "ENSPCHK", 0x20, 0x20 },
+ { "RESET_SCSI", 0x40, 0x40 },
+ { "TERM_ENB", 0x80, 0x80 },
+@@ -785,7 +729,7 @@ ahc_scsiconf_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x5a, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t INTDEF_parse_table[] = {
++static const ahc_reg_parse_entry_t INTDEF_parse_table[] = {
+ { "EDGE_TRIG", 0x80, 0x80 },
+ { "VECTOR", 0x0f, 0x0f }
+ };
+@@ -804,7 +748,7 @@ ahc_hostconf_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x5d, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t HA_274_BIOSCTRL_parse_table[] = {
++static const ahc_reg_parse_entry_t HA_274_BIOSCTRL_parse_table[] = {
+ { "CHANNEL_B_PRIMARY", 0x08, 0x08 },
+ { "BIOSMODE", 0x30, 0x30 },
+ { "BIOSDISABLED", 0x30, 0x30 }
+@@ -817,7 +761,7 @@ ahc_ha_274_biosctrl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x5f, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SEQCTL_parse_table[] = {
++static const ahc_reg_parse_entry_t SEQCTL_parse_table[] = {
+ { "LOADRAM", 0x01, 0x01 },
+ { "SEQRESET", 0x02, 0x02 },
+ { "STEP", 0x04, 0x04 },
+@@ -849,7 +793,7 @@ ahc_seqaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x62, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SEQADDR1_parse_table[] = {
++static const ahc_reg_parse_entry_t SEQADDR1_parse_table[] = {
+ { "SEQADDR1_MASK", 0x01, 0x01 }
+ };
+
+@@ -902,7 +846,7 @@ ahc_none_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x6a, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t FLAGS_parse_table[] = {
++static const ahc_reg_parse_entry_t FLAGS_parse_table[] = {
+ { "CARRY", 0x01, 0x01 },
+ { "ZERO", 0x02, 0x02 }
+ };
+@@ -929,13 +873,6 @@ ahc_dindir_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahc_function1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-- struct qeth_card *card = dev->driver_data;
-- enum qeth_large_send_types type;
-- int rc = 0;
-- char *tmp;
+- return (ahc_print_register(NULL, 0, "FUNCTION1",
+- 0x6e, regvalue, cur_col, wrap));
+-}
-
-- 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;
+-int
+ ahc_stack_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahc_print_register(NULL, 0, "STACK",
+@@ -956,19 +893,7 @@ ahc_sram_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x70, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t BCTL_parse_table[] = {
+- { "ENABLE", 0x01, 0x01 },
+- { "ACE", 0x08, 0x08 }
+-};
+-
+-int
+-ahc_bctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahc_print_register(BCTL_parse_table, 2, "BCTL",
+- 0x84, regvalue, cur_col, wrap));
-}
-
--static DEVICE_ATTR(large_send, 0644, qeth_dev_large_send_show,
-- qeth_dev_large_send_store);
+-static ahc_reg_parse_entry_t DSCOMMAND0_parse_table[] = {
++static const ahc_reg_parse_entry_t DSCOMMAND0_parse_table[] = {
+ { "CIOPARCKEN", 0x01, 0x01 },
+ { "USCBSIZE32", 0x02, 0x02 },
+ { "RAMPS", 0x04, 0x04 },
+@@ -986,7 +911,7 @@ ahc_dscommand0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x84, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t BUSTIME_parse_table[] = {
++static const ahc_reg_parse_entry_t BUSTIME_parse_table[] = {
+ { "BON", 0x0f, 0x0f },
+ { "BOFF", 0xf0, 0xf0 }
+ };
+@@ -998,7 +923,7 @@ ahc_bustime_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x85, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t DSCOMMAND1_parse_table[] = {
++static const ahc_reg_parse_entry_t DSCOMMAND1_parse_table[] = {
+ { "HADDLDSEL0", 0x01, 0x01 },
+ { "HADDLDSEL1", 0x02, 0x02 },
+ { "DSLATT", 0xfc, 0xfc }
+@@ -1011,7 +936,7 @@ ahc_dscommand1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x85, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t BUSSPD_parse_table[] = {
++static const ahc_reg_parse_entry_t BUSSPD_parse_table[] = {
+ { "STBON", 0x07, 0x07 },
+ { "STBOFF", 0x38, 0x38 },
+ { "DFTHRSH_75", 0x80, 0x80 },
+@@ -1026,7 +951,7 @@ ahc_busspd_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x86, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t HS_MAILBOX_parse_table[] = {
++static const ahc_reg_parse_entry_t HS_MAILBOX_parse_table[] = {
+ { "SEQ_MAILBOX", 0x0f, 0x0f },
+ { "HOST_TQINPOS", 0x80, 0x80 },
+ { "HOST_MAILBOX", 0xf0, 0xf0 }
+@@ -1039,7 +964,7 @@ ahc_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x86, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t DSPCISTATUS_parse_table[] = {
++static const ahc_reg_parse_entry_t DSPCISTATUS_parse_table[] = {
+ { "DFTHRSH_100", 0xc0, 0xc0 }
+ };
+
+@@ -1050,7 +975,7 @@ ahc_dspcistatus_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x86, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t HCNTRL_parse_table[] = {
++static const ahc_reg_parse_entry_t HCNTRL_parse_table[] = {
+ { "CHIPRST", 0x01, 0x01 },
+ { "CHIPRSTACK", 0x01, 0x01 },
+ { "INTEN", 0x02, 0x02 },
+@@ -1088,7 +1013,7 @@ ahc_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x90, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t INTSTAT_parse_table[] = {
++static const ahc_reg_parse_entry_t INTSTAT_parse_table[] = {
+ { "SEQINT", 0x01, 0x01 },
+ { "CMDCMPLT", 0x02, 0x02 },
+ { "SCSIINT", 0x04, 0x04 },
+@@ -1119,7 +1044,7 @@ ahc_intstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x91, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t CLRINT_parse_table[] = {
++static const ahc_reg_parse_entry_t CLRINT_parse_table[] = {
+ { "CLRSEQINT", 0x01, 0x01 },
+ { "CLRCMDINT", 0x02, 0x02 },
+ { "CLRSCSIINT", 0x04, 0x04 },
+@@ -1134,7 +1059,7 @@ ahc_clrint_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x92, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t ERROR_parse_table[] = {
++static const ahc_reg_parse_entry_t ERROR_parse_table[] = {
+ { "ILLHADDR", 0x01, 0x01 },
+ { "ILLSADDR", 0x02, 0x02 },
+ { "ILLOPCODE", 0x04, 0x04 },
+@@ -1152,7 +1077,7 @@ ahc_error_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x92, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t DFCNTRL_parse_table[] = {
++static const ahc_reg_parse_entry_t DFCNTRL_parse_table[] = {
+ { "FIFORESET", 0x01, 0x01 },
+ { "FIFOFLUSH", 0x02, 0x02 },
+ { "DIRECTION", 0x04, 0x04 },
+@@ -1172,7 +1097,7 @@ ahc_dfcntrl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x93, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t DFSTATUS_parse_table[] = {
++static const ahc_reg_parse_entry_t DFSTATUS_parse_table[] = {
+ { "FIFOEMP", 0x01, 0x01 },
+ { "FIFOFULL", 0x02, 0x02 },
+ { "DFTHRESH", 0x04, 0x04 },
+@@ -1198,20 +1123,13 @@ ahc_dfwaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahc_dfraddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahc_print_register(NULL, 0, "DFRADDR",
+- 0x97, regvalue, cur_col, wrap));
+-}
-
--static ssize_t
--qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value )
+-int
+ ahc_dfdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahc_print_register(NULL, 0, "DFDAT",
+ 0x99, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SCBCNT_parse_table[] = {
++static const ahc_reg_parse_entry_t SCBCNT_parse_table[] = {
+ { "SCBAUTO", 0x80, 0x80 },
+ { "SCBCNT_MASK", 0x1f, 0x1f }
+ };
+@@ -1231,20 +1149,13 @@ ahc_qinfifo_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ }
+
+ int
+-ahc_qincnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
+- return (ahc_print_register(NULL, 0, "QINCNT",
+- 0x9c, regvalue, cur_col, wrap));
+-}
-
-- if (!card)
-- return -EINVAL;
+-int
+ ahc_qoutfifo_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ {
+ return (ahc_print_register(NULL, 0, "QOUTFIFO",
+ 0x9d, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t CRCCONTROL1_parse_table[] = {
++static const ahc_reg_parse_entry_t CRCCONTROL1_parse_table[] = {
+ { "TARGCRCCNTEN", 0x04, 0x04 },
+ { "TARGCRCENDEN", 0x08, 0x08 },
+ { "CRCREQCHKEN", 0x10, 0x10 },
+@@ -1260,14 +1171,7 @@ ahc_crccontrol1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x9d, regvalue, cur_col, wrap));
+ }
+
+-int
+-ahc_qoutcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahc_print_register(NULL, 0, "QOUTCNT",
+- 0x9e, regvalue, cur_col, wrap));
+-}
-
-- return sprintf(buf, "%i\n", value);
+-static ahc_reg_parse_entry_t SCSIPHASE_parse_table[] = {
++static const ahc_reg_parse_entry_t SCSIPHASE_parse_table[] = {
+ { "DATA_OUT_PHASE", 0x01, 0x01 },
+ { "DATA_IN_PHASE", 0x02, 0x02 },
+ { "MSG_OUT_PHASE", 0x04, 0x04 },
+@@ -1284,7 +1188,7 @@ ahc_scsiphase_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0x9e, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SFUNCT_parse_table[] = {
++static const ahc_reg_parse_entry_t SFUNCT_parse_table[] = {
+ { "ALT_MODE", 0x80, 0x80 }
+ };
+
+@@ -1351,7 +1255,7 @@ ahc_scb_dataptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xac, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SCB_DATACNT_parse_table[] = {
++static const ahc_reg_parse_entry_t SCB_DATACNT_parse_table[] = {
+ { "SG_LAST_SEG", 0x80, 0x80 },
+ { "SG_HIGH_ADDR_BITS", 0x7f, 0x7f }
+ };
+@@ -1363,7 +1267,7 @@ ahc_scb_datacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xb0, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SCB_SGPTR_parse_table[] = {
++static const ahc_reg_parse_entry_t SCB_SGPTR_parse_table[] = {
+ { "SG_LIST_NULL", 0x01, 0x01 },
+ { "SG_FULL_RESID", 0x02, 0x02 },
+ { "SG_RESID_VALID", 0x04, 0x04 }
+@@ -1376,7 +1280,7 @@ ahc_scb_sgptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xb4, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SCB_CONTROL_parse_table[] = {
++static const ahc_reg_parse_entry_t SCB_CONTROL_parse_table[] = {
+ { "DISCONNECTED", 0x04, 0x04 },
+ { "ULTRAENB", 0x08, 0x08 },
+ { "MK_MESSAGE", 0x10, 0x10 },
+@@ -1394,7 +1298,7 @@ ahc_scb_control_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xb8, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SCB_SCSIID_parse_table[] = {
++static const ahc_reg_parse_entry_t SCB_SCSIID_parse_table[] = {
+ { "TWIN_CHNLB", 0x80, 0x80 },
+ { "OID", 0x0f, 0x0f },
+ { "TWIN_TID", 0x70, 0x70 },
+@@ -1408,7 +1312,7 @@ ahc_scb_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xb9, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SCB_LUN_parse_table[] = {
++static const ahc_reg_parse_entry_t SCB_LUN_parse_table[] = {
+ { "SCB_XFERLEN_ODD", 0x80, 0x80 },
+ { "LID", 0x3f, 0x3f }
+ };
+@@ -1455,14 +1359,7 @@ ahc_scb_next_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xbf, regvalue, cur_col, wrap));
+ }
+
+-int
+-ahc_scb_64_spare_print(u_int regvalue, u_int *cur_col, u_int wrap)
+-{
+- return (ahc_print_register(NULL, 0, "SCB_64_SPARE",
+- 0xc0, regvalue, cur_col, wrap));
-}
-
--static ssize_t
--qeth_dev_blkt_store(struct qeth_card *card, const char *buf, size_t count,
-- int *value, int max_value)
+-static ahc_reg_parse_entry_t SEECTL_2840_parse_table[] = {
++static const ahc_reg_parse_entry_t SEECTL_2840_parse_table[] = {
+ { "DO_2840", 0x01, 0x01 },
+ { "CK_2840", 0x02, 0x02 },
+ { "CS_2840", 0x04, 0x04 }
+@@ -1475,7 +1372,7 @@ ahc_seectl_2840_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xc0, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t STATUS_2840_parse_table[] = {
++static const ahc_reg_parse_entry_t STATUS_2840_parse_table[] = {
+ { "DI_2840", 0x01, 0x01 },
+ { "EEPROM_TF", 0x80, 0x80 },
+ { "ADSEL", 0x1e, 0x1e },
+@@ -1524,7 +1421,7 @@ ahc_ccsgaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xea, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t CCSGCTL_parse_table[] = {
++static const ahc_reg_parse_entry_t CCSGCTL_parse_table[] = {
+ { "CCSGRESET", 0x01, 0x01 },
+ { "SG_FETCH_NEEDED", 0x02, 0x02 },
+ { "CCSGEN", 0x08, 0x08 },
+@@ -1552,7 +1449,7 @@ ahc_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xed, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t CCSCBCTL_parse_table[] = {
++static const ahc_reg_parse_entry_t CCSCBCTL_parse_table[] = {
+ { "CCSCBRESET", 0x01, 0x01 },
+ { "CCSCBDIR", 0x04, 0x04 },
+ { "CCSCBEN", 0x08, 0x08 },
+@@ -1610,7 +1507,7 @@ ahc_sdscb_qoff_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xf8, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t QOFF_CTLSTA_parse_table[] = {
++static const ahc_reg_parse_entry_t QOFF_CTLSTA_parse_table[] = {
+ { "SDSCB_ROLLOVER", 0x10, 0x10 },
+ { "SNSCB_ROLLOVER", 0x20, 0x20 },
+ { "SCB_AVAIL", 0x40, 0x40 },
+@@ -1625,7 +1522,7 @@ ahc_qoff_ctlsta_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xfa, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t DFF_THRSH_parse_table[] = {
++static const ahc_reg_parse_entry_t DFF_THRSH_parse_table[] = {
+ { "RD_DFTHRSH_MIN", 0x00, 0x00 },
+ { "WR_DFTHRSH_MIN", 0x00, 0x00 },
+ { "RD_DFTHRSH_25", 0x01, 0x01 },
+@@ -1653,7 +1550,7 @@ ahc_dff_thrsh_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xfb, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SG_CACHE_SHADOW_parse_table[] = {
++static const ahc_reg_parse_entry_t SG_CACHE_SHADOW_parse_table[] = {
+ { "LAST_SEG_DONE", 0x01, 0x01 },
+ { "LAST_SEG", 0x02, 0x02 },
+ { "SG_ADDR_MASK", 0xf8, 0xf8 }
+@@ -1666,7 +1563,7 @@ ahc_sg_cache_shadow_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ 0xfc, regvalue, cur_col, wrap));
+ }
+
+-static ahc_reg_parse_entry_t SG_CACHE_PRE_parse_table[] = {
++static const ahc_reg_parse_entry_t SG_CACHE_PRE_parse_table[] = {
+ { "LAST_SEG_DONE", 0x01, 0x01 },
+ { "LAST_SEG", 0x02, 0x02 },
+ { "SG_ADDR_MASK", 0xf8, 0xf8 }
+diff --git a/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped b/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
+index 4cee085..07e93fb 100644
+--- a/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
++++ b/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
+@@ -5,7 +5,7 @@
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
+ */
+-static uint8_t seqprog[] = {
++static const uint8_t seqprog[] = {
+ 0xb2, 0x00, 0x00, 0x08,
+ 0xf7, 0x11, 0x22, 0x08,
+ 0x00, 0x65, 0xee, 0x59,
+@@ -1081,7 +1081,7 @@ ahc_patch0_func(struct ahc_softc *ahc)
+ return (0);
+ }
+
+-static struct patch {
++static const struct patch {
+ ahc_patch_func_t *patch_func;
+ uint32_t begin :10,
+ skip_instr :10,
+@@ -1291,7 +1291,7 @@ static struct patch {
+ { ahc_patch4_func, 865, 12, 1 }
+ };
+
+-static struct cs {
++static const struct cs {
+ uint16_t begin;
+ uint16_t end;
+ } critical_sections[] = {
+diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm.c b/drivers/scsi/aic7xxx/aicasm/aicasm.c
+index 9241027..e4a7787 100644
+--- a/drivers/scsi/aic7xxx/aicasm/aicasm.c
++++ b/drivers/scsi/aic7xxx/aicasm/aicasm.c
+@@ -362,7 +362,7 @@ output_code()
+ " *\n"
+ "%s */\n", versions);
+
+- fprintf(ofile, "static uint8_t seqprog[] = {\n");
++ fprintf(ofile, "static const uint8_t seqprog[] = {\n");
+ for (cur_instr = STAILQ_FIRST(&seq_program);
+ cur_instr != NULL;
+ cur_instr = STAILQ_NEXT(cur_instr, links)) {
+@@ -415,7 +415,7 @@ output_code()
+ }
+
+ fprintf(ofile,
+-"static struct patch {\n"
++"static const struct patch {\n"
+ " %spatch_func_t *patch_func;\n"
+ " uint32_t begin :10,\n"
+ " skip_instr :10,\n"
+@@ -435,7 +435,7 @@ output_code()
+ fprintf(ofile, "\n};\n\n");
+
+ fprintf(ofile,
+-"static struct cs {\n"
++"static const struct cs {\n"
+ " uint16_t begin;\n"
+ " uint16_t end;\n"
+ "} critical_sections[] = {\n");
+diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
+index 6066998..81be6a2 100644
+--- a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
++++ b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
+@@ -101,11 +101,12 @@ static void format_3_instr(int opcode, symbol_ref_t *src,
+ expression_t *immed, symbol_ref_t *address);
+ static void test_readable_symbol(symbol_t *symbol);
+ static void test_writable_symbol(symbol_t *symbol);
+-static void type_check(symbol_t *symbol, expression_t *expression, int and_op);
++static void type_check(symbol_ref_t *sym, expression_t *expression, int and_op);
+ static void make_expression(expression_t *immed, int value);
+ static void add_conditional(symbol_t *symbol);
+ static void add_version(const char *verstring);
+ static int is_download_const(expression_t *immed);
++static int is_location_address(symbol_t *symbol);
+ void yyerror(const char *string);
+
+ #define SRAM_SYMNAME "SRAM_BASE"
+@@ -142,6 +143,8 @@ void yyerror(const char *string);
+
+ %token <value> T_ADDRESS
+
++%token T_COUNT
++
+ %token T_ACCESS_MODE
+
+ %token T_MODES
+@@ -192,10 +195,10 @@ void yyerror(const char *string);
+
+ %token <value> T_OR
+
+-/* 16 bit extensions */
+-%token <value> T_OR16 T_AND16 T_XOR16 T_ADD16
+-%token <value> T_ADC16 T_MVI16 T_TEST16 T_CMP16 T_CMPXCHG
+-
++/* 16 bit extensions, not implemented
++ * %token <value> T_OR16 T_AND16 T_XOR16 T_ADD16
++ * %token <value> T_ADC16 T_MVI16 T_TEST16 T_CMP16 T_CMPXCHG
++ */
+ %token T_RET
+
+ %token T_NOP
+@@ -214,7 +217,7 @@ void yyerror(const char *string);
+
+ %type <expression> expression immediate immediate_or_a
+
+-%type <value> export ret f1_opcode f2_opcode f4_opcode jmp_jc_jnc_call jz_jnz je_jne
++%type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne
+
+ %type <value> mode_value mode_list macro_arglist
+
+@@ -313,13 +316,13 @@ reg_definition:
+ stop("Register multiply defined", EX_DATAERR);
+ /* NOTREACHED */
+ }
+- cur_symbol = $1;
++ cur_symbol = $1;
+ cur_symbol->type = cur_symtype;
+ initialize_symbol(cur_symbol);
+ }
+ reg_attribute_list
+ '}'
+- {
++ {
+ /*
+ * Default to allowing everything in for registers
+ * with no bit or mask definitions.
+@@ -349,9 +352,10 @@ reg_attribute_list:
+ | reg_attribute_list reg_attribute
+ ;
+
+-reg_attribute:
++reg_attribute:
+ reg_address
+ | size
++| count
+ | access_mode
+ | modes
+ | field_defn
+@@ -392,6 +396,13 @@ size:
+ }
+ ;
+
++count:
++ T_COUNT T_NUMBER
++ {
++ cur_symbol->count += $2;
++ }
++;
++
+ access_mode:
+ T_ACCESS_MODE T_MODE
+ {
+@@ -641,14 +652,14 @@ expression:
+ &($1.referenced_syms),
+ &($3.referenced_syms));
+ }
+-| expression T_EXPR_LSHIFT expression
++| expression T_EXPR_LSHIFT expression
+ {
+ $$.value = $1.value << $3.value;
+ symlist_merge(&$$.referenced_syms,
+ &$1.referenced_syms,
+ &$3.referenced_syms);
+ }
+-| expression T_EXPR_RSHIFT expression
++| expression T_EXPR_RSHIFT expression
+ {
+ $$.value = $1.value >> $3.value;
+ symlist_merge(&$$.referenced_syms,
+@@ -714,7 +725,7 @@ expression:
+ ;
+
+ constant:
+- T_CONST T_SYMBOL expression
++ T_CONST T_SYMBOL expression
+ {
+ if ($2->type != UNINITIALIZED) {
+ stop("Re-definition of symbol as a constant",
+@@ -800,6 +811,7 @@ scratch_ram:
+ cur_symtype = SRAMLOC;
+ cur_symbol->type = SRAMLOC;
+ initialize_symbol(cur_symbol);
++ cur_symbol->count += 1;
+ }
+ reg_address
+ {
+@@ -831,6 +843,7 @@ scb:
+ initialize_symbol(cur_symbol);
+ /* 64 bytes of SCB space */
+ cur_symbol->info.rinfo->size = 64;
++ cur_symbol->count += 1;
+ }
+ reg_address
+ {
+@@ -1311,14 +1324,18 @@ f2_opcode:
+ | T_ROR { $$ = AIC_OP_ROR; }
+ ;
+
+-f4_opcode:
+- T_OR16 { $$ = AIC_OP_OR16; }
+-| T_AND16 { $$ = AIC_OP_AND16; }
+-| T_XOR16 { $$ = AIC_OP_XOR16; }
+-| T_ADD16 { $$ = AIC_OP_ADD16; }
+-| T_ADC16 { $$ = AIC_OP_ADC16; }
+-| T_MVI16 { $$ = AIC_OP_MVI16; }
+-;
++/*
++ * 16bit opcodes, not used
++ *
++ *f4_opcode:
++ * T_OR16 { $$ = AIC_OP_OR16; }
++ *| T_AND16 { $$ = AIC_OP_AND16; }
++ *| T_XOR16 { $$ = AIC_OP_XOR16; }
++ *| T_ADD16 { $$ = AIC_OP_ADD16; }
++ *| T_ADC16 { $$ = AIC_OP_ADC16; }
++ *| T_MVI16 { $$ = AIC_OP_MVI16; }
++ *;
++ */
+
+ code:
+ f2_opcode destination ',' expression opt_source ret ';'
+@@ -1357,6 +1374,7 @@ code:
+ code:
+ T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';'
+ {
++ type_check(&$2, &$4, AIC_OP_OR);
+ format_3_instr($5, &$2, &$4, &$6);
+ }
+ ;
+@@ -1528,7 +1546,7 @@ initialize_symbol(symbol_t *symbol)
+ sizeof(struct cond_info));
+ break;
+ case MACRO:
+- symbol->info.macroinfo =
++ symbol->info.macroinfo =
+ (struct macro_info *)malloc(sizeof(struct macro_info));
+ if (symbol->info.macroinfo == NULL) {
+ stop("Can't create macro info", EX_SOFTWARE);
+@@ -1552,7 +1570,6 @@ add_macro_arg(const char *argtext, int argnum)
+ struct macro_arg *marg;
+ int i;
+ int retval;
+-
+
+ if (cur_symbol == NULL || cur_symbol->type != MACRO) {
+ stop("Invalid current symbol for adding macro arg",
+@@ -1633,8 +1650,10 @@ format_1_instr(int opcode, symbol_ref_t *dest, expression_t *immed,
+ test_writable_symbol(dest->symbol);
+ test_readable_symbol(src->symbol);
+
+- /* Ensure that immediate makes sense for this destination */
+- type_check(dest->symbol, immed, opcode);
++ if (!is_location_address(dest->symbol)) {
++ /* Ensure that immediate makes sense for this destination */
++ type_check(dest, immed, opcode);
++ }
+
+ /* Allocate sequencer space for the instruction and fill it out */
+ instr = seq_alloc();
+@@ -1766,9 +1785,6 @@ format_3_instr(int opcode, symbol_ref_t *src,
+ /* Test register permissions */
+ test_readable_symbol(src->symbol);
+
+- /* Ensure that immediate makes sense for this source */
+- type_check(src->symbol, immed, opcode);
+-
+ /* Allocate sequencer space for the instruction and fill it out */
+ instr = seq_alloc();
+ f3_instr = &instr->format.format3;
+@@ -1797,7 +1813,6 @@ format_3_instr(int opcode, symbol_ref_t *src,
+ static void
+ test_readable_symbol(symbol_t *symbol)
+ {
+-
+ if ((symbol->info.rinfo->modes & (0x1 << src_mode)) == 0) {
+ snprintf(errbuf, sizeof(errbuf),
+ "Register %s unavailable in source reg mode %d",
+@@ -1815,7 +1830,6 @@ test_readable_symbol(symbol_t *symbol)
+ static void
+ test_writable_symbol(symbol_t *symbol)
+ {
+-
+ if ((symbol->info.rinfo->modes & (0x1 << dst_mode)) == 0) {
+ snprintf(errbuf, sizeof(errbuf),
+ "Register %s unavailable in destination reg mode %d",
+@@ -1831,25 +1845,34 @@ test_writable_symbol(symbol_t *symbol)
+ }
+
+ static void
+-type_check(symbol_t *symbol, expression_t *expression, int opcode)
++type_check(symbol_ref_t *sym, expression_t *expression, int opcode)
+ {
++ symbol_t *symbol = sym->symbol;
+ symbol_node_t *node;
+ int and_op;
++ int8_t value, mask;
+
+ and_op = FALSE;
+- if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || AIC_OP_JZ)
+- and_op = TRUE;
+-
+ /*
+ * Make sure that we aren't attempting to write something
+ * that hasn't been defined. If this is an and operation,
+ * this is a mask, so "undefined" bits are okay.
+ */
+- if (and_op == FALSE
+- && (expression->value & ~symbol->info.rinfo->valid_bitmask) != 0) {
++ if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ ||
++ opcode == AIC_OP_JZ || opcode == AIC_OP_JNE ||
++ opcode == AIC_OP_BMOV)
++ and_op = TRUE;
++
++ /*
++ * Defaulting to 8 bit logic
++ */
++ mask = (int8_t)~symbol->info.rinfo->valid_bitmask;
++ value = (int8_t)expression->value;
++
++ if (and_op == FALSE && (mask & value) != 0 ) {
+ snprintf(errbuf, sizeof(errbuf),
+ "Invalid bit(s) 0x%x in immediate written to %s",
+- expression->value & ~symbol->info.rinfo->valid_bitmask,
++ (mask & value),
+ symbol->name);
+ stop(errbuf, EX_DATAERR);
+ /* NOTREACHED */
+@@ -1959,3 +1982,13 @@ is_download_const(expression_t *immed)
+
+ return (FALSE);
+ }
++
++static int
++is_location_address(symbol_t *sym)
++{
++ if (sym->type == SCBLOC ||
++ sym->type == SRAMLOC)
++ return (TRUE);
++ return (FALSE);
++}
++
+diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l b/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
+index 7c3983f..2c7f02d 100644
+--- a/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
++++ b/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
+@@ -162,6 +162,7 @@ register { return T_REGISTER; }
+ const { yylval.value = FALSE; return T_CONST; }
+ download { return T_DOWNLOAD; }
+ address { return T_ADDRESS; }
++count { return T_COUNT; }
+ access_mode { return T_ACCESS_MODE; }
+ modes { return T_MODES; }
+ RW|RO|WO {
+@@ -228,15 +229,15 @@ ret { return T_RET; }
+ nop { return T_NOP; }
+
+ /* ARP2 16bit extensions */
+-or16 { return T_OR16; }
+-and16 { return T_AND16; }
+-xor16 { return T_XOR16; }
+-add16 { return T_ADD16; }
+-adc16 { return T_ADC16; }
+-mvi16 { return T_MVI16; }
+-test16 { return T_TEST16; }
+-cmp16 { return T_CMP16; }
+-cmpxchg { return T_CMPXCHG; }
++ /* or16 { return T_OR16; } */
++ /* and16 { return T_AND16; }*/
++ /* xor16 { return T_XOR16; }*/
++ /* add16 { return T_ADD16; }*/
++ /* adc16 { return T_ADC16; }*/
++ /* mvi16 { return T_MVI16; }*/
++ /* test16 { return T_TEST16; }*/
++ /* cmp16 { return T_CMP16; }*/
++ /* cmpxchg { return T_CMPXCHG; }*/
+
+ /* Allowed Symbols */
+ \<\< { return T_EXPR_LSHIFT; }
+diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c b/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c
+index f1f448d..fcd3578 100644
+--- a/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c
++++ b/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c
+@@ -77,6 +77,7 @@ symbol_create(char *name)
+ if (new_symbol->name == NULL)
+ stop("Unable to strdup symbol name", EX_SOFTWARE);
+ new_symbol->type = UNINITIALIZED;
++ new_symbol->count = 1;
+ return (new_symbol);
+ }
+
+@@ -198,6 +199,12 @@ symtable_get(char *name)
+ }
+ }
+ memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
++ stored_ptr->count++;
++ data.data = &stored_ptr;
++ if (symtable->put(symtable, &key, &data, /*flags*/0) !=0) {
++ perror("Symtable put failed");
++ exit(EX_SOFTWARE);
++ }
+ return (stored_ptr);
+ }
+
+@@ -256,7 +263,7 @@ symlist_add(symlist_t *symlist, symbol_t *symbol, int how)
+ && (curnode->symbol->info.finfo->value >
+ newnode->symbol->info.finfo->value))))
+ || (!field && (curnode->symbol->info.rinfo->address >
+- newnode->symbol->info.rinfo->address))) {
++ newnode->symbol->info.rinfo->address))) {
+ SLIST_INSERT_HEAD(symlist, newnode, links);
+ return;
+ }
+@@ -271,7 +278,7 @@ symlist_add(symlist_t *symlist, symbol_t *symbol, int how)
+
+ cursymbol = SLIST_NEXT(curnode, links)->symbol;
+ if ((field
+- && (cursymbol->type > symbol->type
++ && (cursymbol->type > symbol->type
+ || (cursymbol->type == symbol->type
+ && (cursymbol->info.finfo->value >
+ symbol->info.finfo->value))))
+@@ -351,7 +358,7 @@ aic_print_reg_dump_types(FILE *ofile)
+ {
+ if (ofile == NULL)
+ return;
+-
++
+ fprintf(ofile,
+ "typedef int (%sreg_print_t)(u_int, u_int *, u_int);\n"
+ "typedef struct %sreg_parse_entry {\n"
+@@ -370,7 +377,7 @@ aic_print_reg_dump_start(FILE *dfile, symbol_node_t *regnode)
+ return;
+
+ fprintf(dfile,
+-"static %sreg_parse_entry_t %s_parse_table[] = {\n",
++"static const %sreg_parse_entry_t %s_parse_table[] = {\n",
+ prefix,
+ regnode->symbol->name);
+ }
+@@ -385,7 +392,7 @@ aic_print_reg_dump_end(FILE *ofile, FILE *dfile,
+ lower_name = strdup(regnode->symbol->name);
+ if (lower_name == NULL)
+ stop("Unable to strdup symbol name", EX_SOFTWARE);
+-
++
+ for (letter = lower_name; *letter != '\0'; letter++)
+ *letter = tolower(*letter);
+
+@@ -472,6 +479,7 @@ symtable_dump(FILE *ofile, FILE *dfile)
+ DBT key;
+ DBT data;
+ int flag;
++ int reg_count = 0, reg_used = 0;
+ u_int i;
+
+ if (symtable == NULL)
+@@ -541,6 +549,9 @@ symtable_dump(FILE *ofile, FILE *dfile)
+ int num_entries;
+
+ num_entries = 0;
++ reg_count++;
++ if (curnode->symbol->count == 1)
++ break;
+ fields = &curnode->symbol->info.rinfo->fields;
+ SLIST_FOREACH(fieldnode, fields, links) {
+ if (num_entries == 0)
+@@ -553,11 +564,14 @@ symtable_dump(FILE *ofile, FILE *dfile)
+ }
+ aic_print_reg_dump_end(ofile, dfile,
+ curnode, num_entries);
++ reg_used++;
+ }
+ default:
+ break;
+ }
+ }
++ fprintf(stderr, "%s: %d of %d register definitions used\n", appname,
++ reg_used, reg_count);
+
+ /* Fold in the masks and bits */
+ while (SLIST_FIRST(&masks) != NULL) {
+@@ -646,7 +660,6 @@ symtable_dump(FILE *ofile, FILE *dfile)
+ free(curnode);
+ }
+
+-
+ fprintf(ofile, "\n\n/* Downloaded Constant Definitions */\n");
+
+ for (i = 0; SLIST_FIRST(&download_constants) != NULL; i++) {
+diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h b/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h
+index afc22e8..05190c1 100644
+--- a/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h
++++ b/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h
+@@ -128,6 +128,7 @@ typedef struct expression_info {
+ typedef struct symbol {
+ char *name;
+ symtype type;
++ int count;
+ union {
+ struct reg_info *rinfo;
+ struct field_info *finfo;
+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)
-{
-- char *tmp;
- 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;
+- }
+-}
-
-- if (!card)
-- return -EINVAL;
+ struct asd_ha_struct;
+ struct asd_ascb;
+
+diff --git a/drivers/scsi/aic94xx/aic94xx_dev.c b/drivers/scsi/aic94xx/aic94xx_dev.c
+index 72042ca..2e2ddec 100644
+--- a/drivers/scsi/aic94xx/aic94xx_dev.c
++++ b/drivers/scsi/aic94xx/aic94xx_dev.c
+@@ -35,7 +35,7 @@
+ #define SET_DDB(_ddb, _ha) set_bit(_ddb, (_ha)->hw_prof.ddb_bitmap)
+ #define CLEAR_DDB(_ddb, _ha) clear_bit(_ddb, (_ha)->hw_prof.ddb_bitmap)
+
+-static inline int asd_get_ddb(struct asd_ha_struct *asd_ha)
++static int asd_get_ddb(struct asd_ha_struct *asd_ha)
+ {
+ int ddb, i;
+
+@@ -71,7 +71,7 @@ out:
+ #define NCQ_DATA_SCB_PTR offsetof(struct asd_ddb_stp_sata_target_port, ncq_data_scb_ptr)
+ #define ITNL_TIMEOUT offsetof(struct asd_ddb_ssp_smp_target_port, itnl_timeout)
+
+-static inline void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb)
++static void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb)
+ {
+ if (!ddb || ddb >= 0xFFFF)
+ return;
+@@ -79,7 +79,7 @@ static inline void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb)
+ CLEAR_DDB(ddb, asd_ha);
+ }
+
+-static inline void asd_set_ddb_type(struct domain_device *dev)
++static void asd_set_ddb_type(struct domain_device *dev)
+ {
+ struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
+ int ddb = (int) (unsigned long) dev->lldd_dev;
+@@ -109,7 +109,7 @@ static int asd_init_sata_tag_ddb(struct domain_device *dev)
+ return 0;
+ }
+
+-static inline int asd_init_sata(struct domain_device *dev)
++static int asd_init_sata(struct domain_device *dev)
+ {
+ struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
+ int ddb = (int) (unsigned long) dev->lldd_dev;
+diff --git a/drivers/scsi/aic94xx/aic94xx_dump.c b/drivers/scsi/aic94xx/aic94xx_dump.c
+index 3d8c4ff..67eeba3 100644
+--- a/drivers/scsi/aic94xx/aic94xx_dump.c
++++ b/drivers/scsi/aic94xx/aic94xx_dump.c
+@@ -738,6 +738,8 @@ static void asd_dump_lseq_state(struct asd_ha_struct *asd_ha, int lseq)
+ PRINT_LMIP_dword(asd_ha, lseq, DEV_PRES_TIMER_TERM_TS);
+ }
+
++#if 0
++
+ /**
+ * asd_dump_ddb_site -- dump a CSEQ DDB site
+ * @asd_ha: pointer to host adapter structure
+@@ -880,6 +882,8 @@ void asd_dump_scb_sites(struct asd_ha_struct *asd_ha)
+ }
+ }
+
++#endif /* 0 */
++
+ /**
+ * ads_dump_seq_state -- dump CSEQ and LSEQ states
+ * @asd_ha: pointer to host adapter structure
+@@ -922,7 +926,9 @@ void asd_dump_frame_rcvd(struct asd_phy *phy,
+ spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
+ }
+
+-static inline void asd_dump_scb(struct asd_ascb *ascb, int ind)
++#if 0
++
++static void asd_dump_scb(struct asd_ascb *ascb, int ind)
+ {
+ asd_printk("scb%d: vaddr: 0x%p, dma_handle: 0x%llx, next: 0x%llx, "
+ "index:%d, opcode:0x%02x\n",
+@@ -956,4 +962,6 @@ void asd_dump_scb_list(struct asd_ascb *ascb, int num)
+ }
+ }
+
++#endif /* 0 */
++
+ #endif /* ASD_DEBUG */
+diff --git a/drivers/scsi/aic94xx/aic94xx_dump.h b/drivers/scsi/aic94xx/aic94xx_dump.h
+index 0c388e7..191a753 100644
+--- a/drivers/scsi/aic94xx/aic94xx_dump.h
++++ b/drivers/scsi/aic94xx/aic94xx_dump.h
+@@ -29,24 +29,15 @@
+
+ #ifdef ASD_DEBUG
+
+-void asd_dump_ddb_0(struct asd_ha_struct *asd_ha);
+-void asd_dump_target_ddb(struct asd_ha_struct *asd_ha, u16 site_no);
+-void asd_dump_scb_sites(struct asd_ha_struct *asd_ha);
+ void asd_dump_seq_state(struct asd_ha_struct *asd_ha, u8 lseq_mask);
+ void asd_dump_frame_rcvd(struct asd_phy *phy,
+ struct done_list_struct *dl);
+-void asd_dump_scb_list(struct asd_ascb *ascb, int num);
+ #else /* ASD_DEBUG */
+
+-static inline void asd_dump_ddb_0(struct asd_ha_struct *asd_ha) { }
+-static inline void asd_dump_target_ddb(struct asd_ha_struct *asd_ha,
+- u16 site_no) { }
+-static inline void asd_dump_scb_sites(struct asd_ha_struct *asd_ha) { }
+ static inline void asd_dump_seq_state(struct asd_ha_struct *asd_ha,
+ u8 lseq_mask) { }
+ static inline void asd_dump_frame_rcvd(struct asd_phy *phy,
+ struct done_list_struct *dl) { }
+-static inline void asd_dump_scb_list(struct asd_ascb *ascb, int num) { }
+ #endif /* ASD_DEBUG */
+
+ #endif /* _AIC94XX_DUMP_H_ */
+diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c
+index 098b5f3..83a7822 100644
+--- a/drivers/scsi/aic94xx/aic94xx_hwi.c
++++ b/drivers/scsi/aic94xx/aic94xx_hwi.c
+@@ -27,6 +27,7 @@
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+ #include <linux/module.h>
++#include <linux/firmware.h>
+
+ #include "aic94xx.h"
+ #include "aic94xx_reg.h"
+@@ -38,16 +39,14 @@ u32 MBAR0_SWB_SIZE;
+
+ /* ---------- Initialization ---------- */
+
+-static void asd_get_user_sas_addr(struct asd_ha_struct *asd_ha)
++static int asd_get_user_sas_addr(struct asd_ha_struct *asd_ha)
+ {
+- extern char sas_addr_str[];
+- /* If the user has specified a WWN it overrides other settings
+- */
+- if (sas_addr_str[0] != '\0')
+- asd_destringify_sas_addr(asd_ha->hw_prof.sas_addr,
+- sas_addr_str);
+- else if (asd_ha->hw_prof.sas_addr[0] != 0)
+- asd_stringify_sas_addr(sas_addr_str, asd_ha->hw_prof.sas_addr);
++ /* adapter came with a sas address */
++ if (asd_ha->hw_prof.sas_addr[0])
++ return 0;
++
++ return sas_request_addr(asd_ha->sas_ha.core.shost,
++ asd_ha->hw_prof.sas_addr);
+ }
+
+ static void asd_propagate_sas_addr(struct asd_ha_struct *asd_ha)
+@@ -251,7 +250,7 @@ static int asd_init_scbs(struct asd_ha_struct *asd_ha)
+ return 0;
+ }
+
+-static inline void asd_get_max_scb_ddb(struct asd_ha_struct *asd_ha)
++static void asd_get_max_scb_ddb(struct asd_ha_struct *asd_ha)
+ {
+ asd_ha->hw_prof.max_scbs = asd_get_cmdctx_size(asd_ha)/ASD_SCB_SIZE;
+ asd_ha->hw_prof.max_ddbs = asd_get_devctx_size(asd_ha)/ASD_DDB_SIZE;
+@@ -657,8 +656,7 @@ int asd_init_hw(struct asd_ha_struct *asd_ha)
+
+ asd_init_ctxmem(asd_ha);
+
+- asd_get_user_sas_addr(asd_ha);
+- if (!asd_ha->hw_prof.sas_addr[0]) {
++ if (asd_get_user_sas_addr(asd_ha)) {
+ asd_printk("No SAS Address provided for %s\n",
+ pci_name(asd_ha->pcidev));
+ err = -ENODEV;
+@@ -773,7 +771,7 @@ static void asd_dl_tasklet_handler(unsigned long data)
+ * asd_process_donelist_isr -- schedule processing of done list entries
+ * @asd_ha: pointer to host adapter structure
+ */
+-static inline void asd_process_donelist_isr(struct asd_ha_struct *asd_ha)
++static void asd_process_donelist_isr(struct asd_ha_struct *asd_ha)
+ {
+ tasklet_schedule(&asd_ha->seq.dl_tasklet);
+ }
+@@ -782,7 +780,7 @@ static inline void asd_process_donelist_isr(struct asd_ha_struct *asd_ha)
+ * asd_com_sas_isr -- process device communication interrupt (COMINT)
+ * @asd_ha: pointer to host adapter structure
+ */
+-static inline void asd_com_sas_isr(struct asd_ha_struct *asd_ha)
++static void asd_com_sas_isr(struct asd_ha_struct *asd_ha)
+ {
+ u32 comstat = asd_read_reg_dword(asd_ha, COMSTAT);
+
+@@ -821,7 +819,7 @@ static inline void asd_com_sas_isr(struct asd_ha_struct *asd_ha)
+ asd_chip_reset(asd_ha);
+ }
+
+-static inline void asd_arp2_err(struct asd_ha_struct *asd_ha, u32 dchstatus)
++static void asd_arp2_err(struct asd_ha_struct *asd_ha, u32 dchstatus)
+ {
+ static const char *halt_code[256] = {
+ "UNEXPECTED_INTERRUPT0",
+@@ -908,7 +906,7 @@ static inline void asd_arp2_err(struct asd_ha_struct *asd_ha, u32 dchstatus)
+ * asd_dch_sas_isr -- process device channel interrupt (DEVINT)
+ * @asd_ha: pointer to host adapter structure
+ */
+-static inline void asd_dch_sas_isr(struct asd_ha_struct *asd_ha)
++static void asd_dch_sas_isr(struct asd_ha_struct *asd_ha)
+ {
+ u32 dchstatus = asd_read_reg_dword(asd_ha, DCHSTATUS);
+
+@@ -923,7 +921,7 @@ static inline void asd_dch_sas_isr(struct asd_ha_struct *asd_ha)
+ * ads_rbi_exsi_isr -- process external system interface interrupt (INITERR)
+ * @asd_ha: pointer to host adapter structure
+ */
+-static inline void asd_rbi_exsi_isr(struct asd_ha_struct *asd_ha)
++static void asd_rbi_exsi_isr(struct asd_ha_struct *asd_ha)
+ {
+ u32 stat0r = asd_read_reg_dword(asd_ha, ASISTAT0R);
+
+@@ -971,7 +969,7 @@ static inline void asd_rbi_exsi_isr(struct asd_ha_struct *asd_ha)
+ *
+ * Asserted on PCIX errors: target abort, etc.
+ */
+-static inline void asd_hst_pcix_isr(struct asd_ha_struct *asd_ha)
++static void asd_hst_pcix_isr(struct asd_ha_struct *asd_ha)
+ {
+ u16 status;
+ u32 pcix_status;
+@@ -1044,8 +1042,8 @@ irqreturn_t asd_hw_isr(int irq, void *dev_id)
+
+ /* ---------- SCB handling ---------- */
+
+-static inline struct asd_ascb *asd_ascb_alloc(struct asd_ha_struct *asd_ha,
+- gfp_t gfp_flags)
++static struct asd_ascb *asd_ascb_alloc(struct asd_ha_struct *asd_ha,
++ gfp_t gfp_flags)
+ {
+ extern struct kmem_cache *asd_ascb_cache;
+ struct asd_seq_data *seq = &asd_ha->seq;
+@@ -1144,8 +1142,8 @@ struct asd_ascb *asd_ascb_alloc_list(struct asd_ha_struct
+ *
+ * LOCKING: called with the pending list lock held.
+ */
+-static inline void asd_swap_head_scb(struct asd_ha_struct *asd_ha,
+- struct asd_ascb *ascb)
++static void asd_swap_head_scb(struct asd_ha_struct *asd_ha,
++ struct asd_ascb *ascb)
+ {
+ struct asd_seq_data *seq = &asd_ha->seq;
+ struct asd_ascb *last = list_entry(ascb->list.prev,
+@@ -1171,7 +1169,7 @@ static inline void asd_swap_head_scb(struct asd_ha_struct *asd_ha,
+ * intended to be called from asd_post_ascb_list(), just prior to
+ * posting the SCBs to the sequencer.
+ */
+-static inline void asd_start_scb_timers(struct list_head *list)
++static void asd_start_scb_timers(struct list_head *list)
+ {
+ struct asd_ascb *ascb;
+ list_for_each_entry(ascb, list, list) {
+diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.h b/drivers/scsi/aic94xx/aic94xx_hwi.h
+index abc7575..8c1c282 100644
+--- a/drivers/scsi/aic94xx/aic94xx_hwi.h
++++ b/drivers/scsi/aic94xx/aic94xx_hwi.h
+@@ -391,8 +391,6 @@ void asd_build_control_phy(struct asd_ascb *ascb, int phy_id, u8 subfunc);
+ void asd_control_led(struct asd_ha_struct *asd_ha, int phy_id, int op);
+ void asd_turn_led(struct asd_ha_struct *asd_ha, int phy_id, int op);
+ int asd_enable_phys(struct asd_ha_struct *asd_ha, const u8 phy_mask);
+-void asd_build_initiate_link_adm_task(struct asd_ascb *ascb, int phy_id,
+- u8 subfunc);
+
+ void asd_ascb_timedout(unsigned long data);
+ int asd_chip_hardrst(struct asd_ha_struct *asd_ha);
+diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
+index 88d1e73..90f5e0a 100644
+--- a/drivers/scsi/aic94xx/aic94xx_init.c
++++ b/drivers/scsi/aic94xx/aic94xx_init.c
+@@ -56,8 +56,6 @@ MODULE_PARM_DESC(collector, "\n"
+ "\tThe aic94xx SAS LLDD supports both modes.\n"
+ "\tDefault: 0 (Direct Mode).\n");
+
+-char sas_addr_str[2*SAS_ADDR_SIZE + 1] = "";
-
-- if ((card->state != CARD_STATE_DOWN) &&
-- (card->state != CARD_STATE_RECOVER))
-- return -EPERM;
+ 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;
-
-- 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;
+- for_each_sequencer(lseq_mask, lseq_mask, lseq) {
+- err = asd_seq_unpause_lseq(asd_ha, lseq);
+- if (err)
+- return err;
- }
-- return count;
+-
+- return err;
-}
-
--static ssize_t
--qeth_dev_blkt_total_show(struct device *dev, struct device_attribute *attr, char *buf)
+ /* ---------- Downloading CSEQ/LSEQ microcode ---------- */
+
+ static int asd_verify_cseq(struct asd_ha_struct *asd_ha, const u8 *_prog,
+diff --git a/drivers/scsi/aic94xx/aic94xx_seq.h b/drivers/scsi/aic94xx/aic94xx_seq.h
+index 2ea6a0d..ad787c5 100644
+--- a/drivers/scsi/aic94xx/aic94xx_seq.h
++++ b/drivers/scsi/aic94xx/aic94xx_seq.h
+@@ -58,10 +58,6 @@ struct sequencer_file_header {
+ } __attribute__((packed));
+
+ #ifdef __KERNEL__
+-int asd_pause_cseq(struct asd_ha_struct *asd_ha);
+-int asd_unpause_cseq(struct asd_ha_struct *asd_ha);
+-int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask);
+-int asd_unpause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask);
+ int asd_init_seqs(struct asd_ha_struct *asd_ha);
+ int asd_start_seqs(struct asd_ha_struct *asd_ha);
+ int asd_release_firmware(void);
+diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c
+index 008df9a..326765c 100644
+--- a/drivers/scsi/aic94xx/aic94xx_task.c
++++ b/drivers/scsi/aic94xx/aic94xx_task.c
+@@ -33,7 +33,7 @@ static void asd_unbuild_ata_ascb(struct asd_ascb *a);
+ static void asd_unbuild_smp_ascb(struct asd_ascb *a);
+ static void asd_unbuild_ssp_ascb(struct asd_ascb *a);
+
+-static inline void asd_can_dequeue(struct asd_ha_struct *asd_ha, int num)
++static void asd_can_dequeue(struct asd_ha_struct *asd_ha, int num)
+ {
+ unsigned long flags;
+
+@@ -51,9 +51,9 @@ static const u8 data_dir_flags[] = {
+ [PCI_DMA_NONE] = DATA_DIR_NONE, /* NO TRANSFER */
+ };
+
+-static inline int asd_map_scatterlist(struct sas_task *task,
+- struct sg_el *sg_arr,
+- gfp_t gfp_flags)
++static int asd_map_scatterlist(struct sas_task *task,
++ struct sg_el *sg_arr,
++ gfp_t gfp_flags)
+ {
+ struct asd_ascb *ascb = task->lldd_task;
+ struct asd_ha_struct *asd_ha = ascb->ha;
+@@ -131,7 +131,7 @@ err_unmap:
+ return res;
+ }
+
+-static inline void asd_unmap_scatterlist(struct asd_ascb *ascb)
++static void asd_unmap_scatterlist(struct asd_ascb *ascb)
+ {
+ struct asd_ha_struct *asd_ha = ascb->ha;
+ struct sas_task *task = ascb->uldd_task;
+@@ -527,7 +527,7 @@ static void asd_unbuild_ssp_ascb(struct asd_ascb *a)
+
+ /* ---------- Execute Task ---------- */
+
+-static inline int asd_can_queue(struct asd_ha_struct *asd_ha, int num)
++static int asd_can_queue(struct asd_ha_struct *asd_ha, int num)
+ {
+ int res = 0;
+ unsigned long flags;
+diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c
+index b9ac8f7..633ff40 100644
+--- a/drivers/scsi/aic94xx/aic94xx_tmf.c
++++ b/drivers/scsi/aic94xx/aic94xx_tmf.c
+@@ -336,7 +336,7 @@ static void asd_tmf_tasklet_complete(struct asd_ascb *ascb,
+ asd_ascb_free(ascb);
+ }
+
+-static inline int asd_clear_nexus(struct sas_task *task)
++static int asd_clear_nexus(struct sas_task *task)
+ {
+ int res = TMF_RESP_FUNC_FAILED;
+ int leftover;
+diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
+index 3288be2..ab646e5 100644
+--- a/drivers/scsi/arcmsr/arcmsr.h
++++ b/drivers/scsi/arcmsr/arcmsr.h
+@@ -44,7 +44,7 @@
+ */
+ #include <linux/interrupt.h>
+
+-struct class_device_attribute;
++struct device_attribute;
+ /*The limit of outstanding scsi command that firmware can handle*/
+ #define ARCMSR_MAX_OUTSTANDING_CMD 256
+ #define ARCMSR_MAX_FREECCB_NUM 320
+@@ -556,6 +556,6 @@ struct SENSE_DATA
+ extern void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *);
+ extern void arcmsr_iop_message_read(struct AdapterControlBlock *);
+ extern struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *);
+-extern struct class_device_attribute *arcmsr_host_attrs[];
++extern struct device_attribute *arcmsr_host_attrs[];
+ extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *);
+ void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb);
+diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c
+index 7d7b0a5..69f8346 100644
+--- a/drivers/scsi/arcmsr/arcmsr_attr.c
++++ b/drivers/scsi/arcmsr/arcmsr_attr.c
+@@ -57,15 +57,15 @@
+ #include <scsi/scsi_transport.h>
+ #include "arcmsr.h"
+
+-struct class_device_attribute *arcmsr_host_attrs[];
++struct device_attribute *arcmsr_host_attrs[];
+
+ static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj,
+ struct bin_attribute *bin,
+ char *buf, loff_t off,
+ size_t count)
+ {
+- struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct device *dev = container_of(kobj,struct device,kobj);
++ struct Scsi_Host *host = class_to_shost(dev);
+ struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
+ uint8_t *pQbuffer,*ptmpQbuffer;
+ int32_t allxfer_len = 0;
+@@ -110,8 +110,8 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct kobject *kobj,
+ char *buf, loff_t off,
+ size_t count)
+ {
+- struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct device *dev = container_of(kobj,struct device,kobj);
++ struct Scsi_Host *host = class_to_shost(dev);
+ struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
+ int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
+ uint8_t *pQbuffer, *ptmpuserbuffer;
+@@ -158,8 +158,8 @@ static ssize_t arcmsr_sysfs_iop_message_clear(struct kobject *kobj,
+ char *buf, loff_t off,
+ size_t count)
+ {
+- struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct device *dev = container_of(kobj,struct device,kobj);
++ struct Scsi_Host *host = class_to_shost(dev);
+ struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
+ uint8_t *pQbuffer;
+
+@@ -220,87 +220,104 @@ int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb)
+ struct Scsi_Host *host = acb->host;
+ int error;
+
+- error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
++ error = sysfs_create_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_read_attr);
+ if (error) {
+ printk(KERN_ERR "arcmsr: alloc sysfs mu_read failed\n");
+ goto error_bin_file_message_read;
+ }
+- error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr);
++ error = sysfs_create_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_write_attr);
+ if (error) {
+ printk(KERN_ERR "arcmsr: alloc sysfs mu_write failed\n");
+ goto error_bin_file_message_write;
+ }
+- error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr);
++ error = sysfs_create_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_clear_attr);
+ if (error) {
+ printk(KERN_ERR "arcmsr: alloc sysfs mu_clear failed\n");
+ goto error_bin_file_message_clear;
+ }
+ return 0;
+ error_bin_file_message_clear:
+- sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr);
++ sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_write_attr);
+ error_bin_file_message_write:
+- sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
++ sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_read_attr);
+ error_bin_file_message_read:
+ return error;
+ }
+
+-void
+-arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb) {
++void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb)
++{
+ struct Scsi_Host *host = acb->host;
+
+- sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr);
+- sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr);
+- sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
++ sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_clear_attr);
++ sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_write_attr);
++ sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_read_attr);
+ }
+
+
+ static ssize_t
+-arcmsr_attr_host_driver_version(struct class_device *cdev, char *buf) {
++arcmsr_attr_host_driver_version(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
+ return snprintf(buf, PAGE_SIZE,
+ "%s\n",
+ ARCMSR_DRIVER_VERSION);
+ }
+
+ static ssize_t
+-arcmsr_attr_host_driver_posted_cmd(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_driver_posted_cmd(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+ return snprintf(buf, PAGE_SIZE,
+ "%4d\n",
+ atomic_read(&acb->ccboutstandingcount));
+ }
+
+ static ssize_t
+-arcmsr_attr_host_driver_reset(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_driver_reset(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+ return snprintf(buf, PAGE_SIZE,
+ "%4d\n",
+ acb->num_resets);
+ }
+
+ static ssize_t
+-arcmsr_attr_host_driver_abort(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_driver_abort(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+ return snprintf(buf, PAGE_SIZE,
+ "%4d\n",
+ acb->num_aborts);
+ }
+
+ static ssize_t
+-arcmsr_attr_host_fw_model(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_model(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+ return snprintf(buf, PAGE_SIZE,
+ "%s\n",
+ acb->firm_model);
+ }
+
+ static ssize_t
+-arcmsr_attr_host_fw_version(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_version(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+
+ return snprintf(buf, PAGE_SIZE,
+ "%s\n",
+@@ -308,9 +325,12 @@ arcmsr_attr_host_fw_version(struct class_device *cdev, char *buf) {
+ }
+
+ static ssize_t
+-arcmsr_attr_host_fw_request_len(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_request_len(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+
+ return snprintf(buf, PAGE_SIZE,
+ "%4d\n",
+@@ -318,9 +338,12 @@ arcmsr_attr_host_fw_request_len(struct class_device *cdev, char *buf) {
+ }
+
+ static ssize_t
+-arcmsr_attr_host_fw_numbers_queue(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_numbers_queue(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+
+ return snprintf(buf, PAGE_SIZE,
+ "%4d\n",
+@@ -328,9 +351,12 @@ arcmsr_attr_host_fw_numbers_queue(struct class_device *cdev, char *buf) {
+ }
+
+ static ssize_t
+-arcmsr_attr_host_fw_sdram_size(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_sdram_size(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+
+ return snprintf(buf, PAGE_SIZE,
+ "%4d\n",
+@@ -338,36 +364,39 @@ arcmsr_attr_host_fw_sdram_size(struct class_device *cdev, char *buf) {
+ }
+
+ static ssize_t
+-arcmsr_attr_host_fw_hd_channels(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_hd_channels(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+
+ return snprintf(buf, PAGE_SIZE,
+ "%4d\n",
+ acb->firm_hd_channels);
+ }
+
+-static CLASS_DEVICE_ATTR(host_driver_version, S_IRUGO, arcmsr_attr_host_driver_version, NULL);
+-static CLASS_DEVICE_ATTR(host_driver_posted_cmd, S_IRUGO, arcmsr_attr_host_driver_posted_cmd, NULL);
+-static CLASS_DEVICE_ATTR(host_driver_reset, S_IRUGO, arcmsr_attr_host_driver_reset, NULL);
+-static CLASS_DEVICE_ATTR(host_driver_abort, S_IRUGO, arcmsr_attr_host_driver_abort, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_model, S_IRUGO, arcmsr_attr_host_fw_model, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_version, S_IRUGO, arcmsr_attr_host_fw_version, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_request_len, S_IRUGO, arcmsr_attr_host_fw_request_len, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_numbers_queue, S_IRUGO, arcmsr_attr_host_fw_numbers_queue, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_sdram_size, S_IRUGO, arcmsr_attr_host_fw_sdram_size, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_hd_channels, S_IRUGO, arcmsr_attr_host_fw_hd_channels, NULL);
+-
+-struct class_device_attribute *arcmsr_host_attrs[] = {
+- &class_device_attr_host_driver_version,
+- &class_device_attr_host_driver_posted_cmd,
+- &class_device_attr_host_driver_reset,
+- &class_device_attr_host_driver_abort,
+- &class_device_attr_host_fw_model,
+- &class_device_attr_host_fw_version,
+- &class_device_attr_host_fw_request_len,
+- &class_device_attr_host_fw_numbers_queue,
+- &class_device_attr_host_fw_sdram_size,
+- &class_device_attr_host_fw_hd_channels,
++static DEVICE_ATTR(host_driver_version, S_IRUGO, arcmsr_attr_host_driver_version, NULL);
++static DEVICE_ATTR(host_driver_posted_cmd, S_IRUGO, arcmsr_attr_host_driver_posted_cmd, NULL);
++static DEVICE_ATTR(host_driver_reset, S_IRUGO, arcmsr_attr_host_driver_reset, NULL);
++static DEVICE_ATTR(host_driver_abort, S_IRUGO, arcmsr_attr_host_driver_abort, NULL);
++static DEVICE_ATTR(host_fw_model, S_IRUGO, arcmsr_attr_host_fw_model, NULL);
++static DEVICE_ATTR(host_fw_version, S_IRUGO, arcmsr_attr_host_fw_version, NULL);
++static DEVICE_ATTR(host_fw_request_len, S_IRUGO, arcmsr_attr_host_fw_request_len, NULL);
++static DEVICE_ATTR(host_fw_numbers_queue, S_IRUGO, arcmsr_attr_host_fw_numbers_queue, NULL);
++static DEVICE_ATTR(host_fw_sdram_size, S_IRUGO, arcmsr_attr_host_fw_sdram_size, NULL);
++static DEVICE_ATTR(host_fw_hd_channels, S_IRUGO, arcmsr_attr_host_fw_hd_channels, NULL);
++
++struct device_attribute *arcmsr_host_attrs[] = {
++ &dev_attr_host_driver_version,
++ &dev_attr_host_driver_posted_cmd,
++ &dev_attr_host_driver_reset,
++ &dev_attr_host_driver_abort,
++ &dev_attr_host_fw_model,
++ &dev_attr_host_fw_version,
++ &dev_attr_host_fw_request_len,
++ &dev_attr_host_fw_numbers_queue,
++ &dev_attr_host_fw_sdram_size,
++ &dev_attr_host_fw_hd_channels,
+ NULL,
+ };
+diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
+index 3bedf24..8e53f02 100644
+--- a/drivers/scsi/arm/acornscsi.c
++++ b/drivers/scsi/arm/acornscsi.c
+@@ -2983,7 +2983,6 @@ static struct scsi_host_template acornscsi_template = {
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = 2,
+- .unchecked_isa_dma = 0,
+ .use_clustering = DISABLE_CLUSTERING,
+ .proc_name = "acornscsi",
+ };
+diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
+index 49d838e..a3398fe 100644
+--- a/drivers/scsi/arm/cumana_1.c
++++ b/drivers/scsi/arm/cumana_1.c
+@@ -222,7 +222,6 @@ static struct scsi_host_template cumanascsi_template = {
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = 2,
+- .unchecked_isa_dma = 0,
+ .use_clustering = DISABLE_CLUSTERING,
+ .proc_name = "CumanaSCSI-1",
+ };
+diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
+index 7aad154..75c84d7 100644
+--- a/drivers/scsi/ch.c
++++ b/drivers/scsi/ch.c
+@@ -113,7 +113,7 @@ static const struct {
+ unsigned char asc;
+ unsigned char ascq;
+ int errno;
+-} err[] = {
++} ch_err[] = {
+ /* Just filled in what looks right. Hav'nt checked any standard paper for
+ these errno assignments, so they may be wrong... */
+ {
+@@ -155,11 +155,11 @@ static int ch_find_errno(struct scsi_sense_hdr *sshdr)
+ /* Check to see if additional sense information is available */
+ if (scsi_sense_valid(sshdr) &&
+ sshdr->asc != 0) {
+- for (i = 0; err[i].errno != 0; i++) {
+- if (err[i].sense == sshdr->sense_key &&
+- err[i].asc == sshdr->asc &&
+- err[i].ascq == sshdr->ascq) {
+- errno = -err[i].errno;
++ for (i = 0; ch_err[i].errno != 0; i++) {
++ if (ch_err[i].sense == sshdr->sense_key &&
++ ch_err[i].asc == sshdr->asc &&
++ ch_err[i].ascq == sshdr->ascq) {
++ errno = -ch_err[i].errno;
+ break;
+ }
+ }
+@@ -721,8 +721,8 @@ static long ch_ioctl(struct file *file,
+ case CHIOGELEM:
+ {
+ struct changer_get_element cge;
+- u_char cmd[12];
+- u_char *buffer;
++ u_char ch_cmd[12];
++ u_char *buffer;
+ unsigned int elem;
+ int result,i;
+
+@@ -739,17 +739,18 @@ static long ch_ioctl(struct file *file,
+ mutex_lock(&ch->lock);
+
+ voltag_retry:
+- memset(cmd,0,sizeof(cmd));
+- cmd[0] = READ_ELEMENT_STATUS;
+- cmd[1] = (ch->device->lun << 5) |
++ memset(ch_cmd, 0, sizeof(ch_cmd));
++ ch_cmd[0] = READ_ELEMENT_STATUS;
++ ch_cmd[1] = (ch->device->lun << 5) |
+ (ch->voltags ? 0x10 : 0) |
+ ch_elem_to_typecode(ch,elem);
+- cmd[2] = (elem >> 8) & 0xff;
+- cmd[3] = elem & 0xff;
+- cmd[5] = 1;
+- cmd[9] = 255;
++ ch_cmd[2] = (elem >> 8) & 0xff;
++ ch_cmd[3] = elem & 0xff;
++ ch_cmd[5] = 1;
++ ch_cmd[9] = 255;
+
+- if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256, DMA_FROM_DEVICE))) {
++ result = ch_do_scsi(ch, ch_cmd, buffer, 256, DMA_FROM_DEVICE);
++ if (!result) {
+ cge.cge_status = buffer[18];
+ cge.cge_flags = 0;
+ if (buffer[18] & CESTATUS_EXCEPT) {
+@@ -880,7 +881,7 @@ static long ch_ioctl_compat(struct file * file,
+ static int ch_probe(struct device *dev)
+ {
+ struct scsi_device *sd = to_scsi_device(dev);
+- struct class_device *class_dev;
++ struct device *class_dev;
+ int minor, ret = -ENOMEM;
+ scsi_changer *ch;
+
+@@ -909,11 +910,11 @@ static int ch_probe(struct device *dev)
+ ch->minor = minor;
+ sprintf(ch->name,"ch%d",ch->minor);
+
+- class_dev = class_device_create(ch_sysfs_class, NULL,
+- MKDEV(SCSI_CHANGER_MAJOR, ch->minor),
+- dev, "s%s", ch->name);
++ class_dev = device_create(ch_sysfs_class, dev,
++ MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
++ "s%s", ch->name);
+ if (IS_ERR(class_dev)) {
+- printk(KERN_WARNING "ch%d: class_device_create failed\n",
++ printk(KERN_WARNING "ch%d: device_create failed\n",
+ ch->minor);
+ ret = PTR_ERR(class_dev);
+ goto remove_idr;
+@@ -944,8 +945,7 @@ static int ch_remove(struct device *dev)
+ idr_remove(&ch_index_idr, ch->minor);
+ spin_unlock(&ch_index_lock);
+
+- class_device_destroy(ch_sysfs_class,
+- MKDEV(SCSI_CHANGER_MAJOR,ch->minor));
++ device_destroy(ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR,ch->minor));
+ kfree(ch->dt);
+ kfree(ch);
+ return 0;
+diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
+index e351db6..075e239 100644
+--- a/drivers/scsi/dc395x.c
++++ b/drivers/scsi/dc395x.c
+@@ -4761,7 +4761,6 @@ static struct scsi_host_template dc395x_driver_template = {
+ .cmd_per_lun = DC395x_MAX_CMD_PER_LUN,
+ .eh_abort_handler = dc395x_eh_abort,
+ .eh_bus_reset_handler = dc395x_eh_bus_reset,
+- .unchecked_isa_dma = 0,
+ .use_clustering = DISABLE_CLUSTERING,
+ };
+
+diff --git a/drivers/scsi/dpt/dpti_i2o.h b/drivers/scsi/dpt/dpti_i2o.h
+index 100b49b..19406ce 100644
+--- a/drivers/scsi/dpt/dpti_i2o.h
++++ b/drivers/scsi/dpt/dpti_i2o.h
+@@ -21,7 +21,6 @@
+
+ #include <linux/i2o-dev.h>
+
+-#include <asm/semaphore.h> /* Needed for MUTEX init macros */
+ #include <linux/version.h>
+ #include <linux/notifier.h>
+ #include <asm/atomic.h>
+diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
+index c9dd839..ac92ac1 100644
+--- a/drivers/scsi/dpt_i2o.c
++++ b/drivers/scsi/dpt_i2o.c
+@@ -153,7 +153,7 @@ static DEFINE_SPINLOCK(adpt_post_wait_lock);
+
+ static u8 adpt_read_blink_led(adpt_hba* host)
+ {
+- if(host->FwDebugBLEDflag_P != 0) {
++ if (host->FwDebugBLEDflag_P) {
+ if( readb(host->FwDebugBLEDflag_P) == 0xbc ){
+ return readb(host->FwDebugBLEDvalue_P);
+ }
+diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
+index 8be3d76..a73a6bb 100644
+--- a/drivers/scsi/eata.c
++++ b/drivers/scsi/eata.c
+@@ -2286,17 +2286,14 @@ static void flush_dev(struct scsi_device *dev, unsigned long cursec,
+ }
+ }
+
+-static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost)
++static irqreturn_t ihdlr(struct Scsi_Host *shost)
+ {
+ struct scsi_cmnd *SCpnt;
+ unsigned int i, k, c, status, tstatus, reg;
+ struct mssp *spp;
+ struct mscp *cpp;
+ struct hostdata *ha = (struct hostdata *)shost->hostdata;
+-
+- if (shost->irq != irq)
+- panic("%s: ihdlr, irq %d, shost->irq %d.\n", ha->board_name, irq,
+- shost->irq);
++ int irq = shost->irq;
+
+ /* Check if this board need to be serviced */
+ if (!(inb(shost->io_port + REG_AUX_STATUS) & IRQ_ASSERTED))
+@@ -2535,7 +2532,7 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost)
+ return IRQ_NONE;
+ }
+
+-static irqreturn_t do_interrupt_handler(int irq, void *shap)
++static irqreturn_t do_interrupt_handler(int dummy, void *shap)
+ {
+ struct Scsi_Host *shost;
+ unsigned int j;
+@@ -2548,7 +2545,7 @@ static irqreturn_t do_interrupt_handler(int irq, void *shap)
+ shost = sh[j];
+
+ spin_lock_irqsave(shost->host_lock, spin_flags);
+- ret = ihdlr(irq, shost);
++ ret = ihdlr(shost);
+ spin_unlock_irqrestore(shost->host_lock, spin_flags);
+ return ret;
+ }
+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/esp_scsi.c b/drivers/scsi/esp_scsi.c
+index bfdee59..a0b6d41 100644
+--- a/drivers/scsi/esp_scsi.c
++++ b/drivers/scsi/esp_scsi.c
+@@ -978,7 +978,7 @@ static int esp_check_spur_intr(struct esp *esp)
+ */
+ if (!esp->ops->dma_error(esp)) {
+ printk(KERN_ERR PFX "esp%d: Spurious irq, "
+- "sreg=%x.\n",
++ "sreg=%02x.\n",
+ esp->host->unique_id, esp->sreg);
+ return -1;
+ }
+@@ -1447,6 +1447,9 @@ static void esp_msgin_sdtr(struct esp *esp, struct esp_target_data *tp)
+ if (offset > 15)
+ goto do_reject;
+
++ if (esp->flags & ESP_FLAG_DISABLE_SYNC)
++ offset = 0;
++
+ if (offset) {
+ int rounded_up, one_clock;
+
+@@ -1697,7 +1700,12 @@ again:
+ else
+ ent->flags &= ~ESP_CMD_FLAG_WRITE;
+
+- dma_len = esp_dma_length_limit(esp, dma_addr, dma_len);
++ if (esp->ops->dma_length_limit)
++ dma_len = esp->ops->dma_length_limit(esp, dma_addr,
++ dma_len);
++ else
++ dma_len = esp_dma_length_limit(esp, dma_addr, dma_len);
++
+ esp->data_dma_len = dma_len;
+
+ if (!dma_len) {
+@@ -1761,7 +1769,6 @@ again:
+ esp_advance_dma(esp, ent, cmd, bytes_sent);
+ esp_event(esp, ESP_EVENT_CHECK_PHASE);
+ goto again;
+- break;
+ }
+
+ case ESP_EVENT_STATUS: {
+@@ -2235,7 +2242,7 @@ static void esp_bootup_reset(struct esp *esp)
+
+ static void esp_set_clock_params(struct esp *esp)
+ {
+- int fmhz;
++ int fhz;
+ u8 ccf;
+
+ /* This is getting messy but it has to be done correctly or else
+@@ -2270,9 +2277,9 @@ static void esp_set_clock_params(struct esp *esp)
+ * This entails the smallest and largest sync period we could ever
+ * handle on this ESP.
+ */
+- fmhz = esp->cfreq;
++ fhz = esp->cfreq;
+
+- ccf = ((fmhz / 1000000) + 4) / 5;
++ ccf = ((fhz / 1000000) + 4) / 5;
+ if (ccf == 1)
+ ccf = 2;
+
+@@ -2281,16 +2288,16 @@ static void esp_set_clock_params(struct esp *esp)
+ * been unable to find the clock-frequency PROM property. All
+ * other machines provide useful values it seems.
+ */
+- if (fmhz <= 5000000 || ccf < 1 || ccf > 8) {
+- fmhz = 20000000;
++ if (fhz <= 5000000 || ccf < 1 || ccf > 8) {
++ fhz = 20000000;
+ ccf = 4;
+ }
+
+ esp->cfact = (ccf == 8 ? 0 : ccf);
+- esp->cfreq = fmhz;
+- esp->ccycle = ESP_MHZ_TO_CYCLE(fmhz);
++ esp->cfreq = fhz;
++ esp->ccycle = ESP_HZ_TO_CYCLE(fhz);
+ esp->ctick = ESP_TICK(ccf, esp->ccycle);
+- esp->neg_defp = ESP_NEG_DEFP(fmhz, ccf);
++ esp->neg_defp = ESP_NEG_DEFP(fhz, ccf);
+ esp->sync_defp = SYNC_DEFP_SLOW;
+ }
+
+@@ -2382,6 +2389,12 @@ static int esp_slave_configure(struct scsi_device *dev)
+ struct esp_target_data *tp = &esp->target[dev->id];
+ int goal_tags, queue_depth;
+
++ if (esp->flags & ESP_FLAG_DISABLE_SYNC) {
++ /* Bypass async domain validation */
++ dev->ppr = 0;
++ dev->sdtr = 0;
++ }
++
+ goal_tags = 0;
+
+ if (dev->tagged_supported) {
+diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
+index d5576d5..bb43a13 100644
+--- a/drivers/scsi/esp_scsi.h
++++ b/drivers/scsi/esp_scsi.h
+@@ -224,7 +224,7 @@
+ #define ESP_TIMEO_CONST 8192
+ #define ESP_NEG_DEFP(mhz, cfact) \
+ ((ESP_BUS_TIMEOUT * ((mhz) / 1000)) / (8192 * (cfact)))
+-#define ESP_MHZ_TO_CYCLE(mhertz) ((1000000000) / ((mhertz) / 1000))
++#define ESP_HZ_TO_CYCLE(hertz) ((1000000000) / ((hertz) / 1000))
+ #define ESP_TICK(ccf, cycle) ((7682 * (ccf) * (cycle) / 1000))
+
+ /* For slow to medium speed input clock rates we shoot for 5mb/s, but for high
+@@ -240,9 +240,9 @@ struct esp_cmd_priv {
+ int num_sg;
+ } u;
+
+- unsigned int cur_residue;
++ int cur_residue;
+ struct scatterlist *cur_sg;
+- unsigned int tot_residue;
++ int tot_residue;
+ };
+ #define ESP_CMD_PRIV(CMD) ((struct esp_cmd_priv *)(&(CMD)->SCp))
+
+@@ -368,6 +368,12 @@ struct esp_driver_ops {
+ */
+ int (*irq_pending)(struct esp *esp);
+
++ /* Return the maximum allowable size of a DMA transfer for a
++ * given buffer.
++ */
++ u32 (*dma_length_limit)(struct esp *esp, u32 dma_addr,
++ u32 dma_len);
++
+ /* Reset the DMA engine entirely. On return, ESP interrupts
+ * should be enabled. Often the interrupt enabling is
+ * controlled in the DMA engine.
+@@ -471,6 +477,7 @@ struct esp {
+ #define ESP_FLAG_DOING_SLOWCMD 0x00000004
+ #define ESP_FLAG_WIDE_CAPABLE 0x00000008
+ #define ESP_FLAG_QUICKIRQ_CHECK 0x00000010
++#define ESP_FLAG_DISABLE_SYNC 0x00000020
+
+ u8 select_state;
+ #define ESP_SELECT_NONE 0x00 /* Not selecting */
+diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
+index 2cd6b49..c33bcb2 100644
+--- a/drivers/scsi/fdomain.c
++++ b/drivers/scsi/fdomain.c
+@@ -1443,7 +1443,7 @@ static int fdomain_16x0_queue(struct scsi_cmnd *SCpnt,
+ current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
+ current_SC->SCp.buffers_residual = scsi_sg_count(current_SC) - 1;
+ } else {
+- current_SC->SCp.ptr = 0;
++ current_SC->SCp.ptr = NULL;
+ current_SC->SCp.this_residual = 0;
+ current_SC->SCp.buffer = NULL;
+ current_SC->SCp.buffers_residual = 0;
+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)
-{
-- struct qeth_card *card = dev->driver_data;
--
-- return qeth_dev_blkt_show(buf, card, card->info.blkt.time_total);
+- return (unsigned)cmd->SCp.this_residual;
-}
-
--
--static ssize_t
--qeth_dev_blkt_total_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-static inline void gdth_set_bufflen(struct scsi_cmnd *cmd, unsigned bufflen)
-{
-- struct qeth_card *card = dev->driver_data;
--
-- return qeth_dev_blkt_store(card, buf, count,
-- &card->info.blkt.time_total,1000);
+- cmd->SCp.this_residual = bufflen;
-}
-
--
--
--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)
+-static inline unsigned gdth_sg_count(struct scsi_cmnd *cmd)
-{
-- struct qeth_card *card = dev->driver_data;
--
-- return qeth_dev_blkt_show(buf, card, card->info.blkt.inter_packet);
+- return (unsigned)cmd->SCp.buffers_residual;
-}
-
--
--static ssize_t
--qeth_dev_blkt_inter_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-static inline void gdth_set_sg_count(struct scsi_cmnd *cmd, unsigned sg_count)
-{
-- struct qeth_card *card = dev->driver_data;
--
-- return qeth_dev_blkt_store(card, buf, count,
-- &card->info.blkt.inter_packet,100);
+- cmd->SCp.buffers_residual = sg_count;
-}
-
--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)
+-static inline struct scatterlist *gdth_sglist(struct scsi_cmnd *cmd)
-{
-- struct qeth_card *card = dev->driver_data;
--
-- return qeth_dev_blkt_show(buf, card,
-- card->info.blkt.inter_packet_jumbo);
+- return cmd->SCp.buffer;
-}
-
--
--static ssize_t
--qeth_dev_blkt_inter_jumbo_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-static inline void gdth_set_sglist(struct scsi_cmnd *cmd,
+- struct scatterlist *sglist)
-{
-- struct qeth_card *card = dev->driver_data;
--
-- return qeth_dev_blkt_store(card, buf, count,
-- &card->info.blkt.inter_packet_jumbo,100);
+- cmd->SCp.buffer = sglist;
-}
-
--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,
--};
+ #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"));
-
--static struct attribute_group qeth_device_blkt_group = {
-- .name = "blkt",
-- .attrs = (struct attribute **)qeth_blkt_device_attrs,
--};
+- 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));
-
--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,
--};
+ 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;
-
--static struct attribute_group qeth_device_attr_group = {
-- .attrs = (struct attribute **)qeth_device_attrs,
--};
+- 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..3690360 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);
+ }
+@@ -199,9 +199,13 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
+ if (!shost->can_queue) {
+ printk(KERN_ERR "%s: can_queue = 0 no longer supported\n",
+ sht->name);
+- goto out;
++ goto fail;
+ }
+
++ error = scsi_setup_command_freelist(shost);
++ if (error)
++ goto fail;
++
+ if (!shost->shost_gendev.parent)
+ shost->shost_gendev.parent = dev ? dev : &platform_bus;
+
+@@ -212,7 +216,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 +227,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,11 +254,13 @@ 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:
++ scsi_destroy_command_freelist(shost);
++ fail:
+ return error;
+ }
+ EXPORT_SYMBOL(scsi_add_host);
+@@ -284,6 +290,11 @@ static void scsi_host_dev_release(struct device *dev)
+ kfree(shost);
+ }
+
++struct device_type scsi_host_type = {
++ .name = "scsi_host",
++ .release = scsi_host_dev_release,
++};
++
+ /**
+ * scsi_host_alloc - register a scsi host adapter instance.
+ * @sht: pointer to scsi host template
+@@ -347,7 +358,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 */
+@@ -377,33 +387,31 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
+ else
+ shost->dma_boundary = 0xffffffff;
+
+- rval = scsi_setup_command_freelist(shost);
+- if (rval)
+- goto fail_kfree;
-
--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,
--};
+ device_initialize(&shost->shost_gendev);
+ snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d",
+ shost->host_no);
+- shost->shost_gendev.release = scsi_host_dev_release;
-
--static struct attribute_group qeth_osn_device_attr_group = {
-- .attrs = (struct attribute **)qeth_osn_device_attrs,
--};
+- 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);
++#ifndef CONFIG_SYSFS_DEPRECATED
++ shost->shost_gendev.bus = &scsi_bus_type;
++#endif
++ shost->shost_gendev.type = &scsi_host_type;
++
++ 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->shost_dev.groups = scsi_sysfs_shost_attr_groups;
+
+ shost->ehandler = kthread_run(scsi_error_handler, shost,
+ "scsi_eh_%d", shost->host_no);
+ if (IS_ERR(shost->ehandler)) {
+ rval = PTR_ERR(shost->ehandler);
+- goto fail_destroy_freelist;
++ goto fail_kfree;
+ }
+
+ scsi_proc_hostdir_add(shost->hostt);
+ return shost;
+
+- fail_destroy_freelist:
+- scsi_destroy_command_freelist(shost);
+ fail_kfree:
+ kfree(shost);
+ return NULL;
+@@ -433,12 +441,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 +459,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));
+
+@@ -497,7 +505,7 @@ void scsi_exit_hosts(void)
+
+ int scsi_is_host_device(const struct device *dev)
+ {
+- return dev->release == scsi_host_dev_release;
++ return dev->type == &scsi_host_type;
+ }
+ EXPORT_SYMBOL(scsi_is_host_device);
+
+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..44d8d51 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;
-
--#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, \
--};
+-/*
+- * 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 */
-
--static int
--qeth_check_layer2(struct qeth_card *card)
+ /*
+ * 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,23 +128,13 @@ 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)
-{
-- if (card->options.layer2)
-- return -EPERM;
-- return 0;
+- while (bcount--)
+- (void) HWIF(drive)->INB(IDE_DATA_REG);
-}
-
--
--static ssize_t
--qeth_dev_ipato_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
+-static void idescsi_output_zeros (ide_drive_t *drive, unsigned int bcount)
-{
-- 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);
+- while (bcount--)
+- HWIF(drive)->OUTB(0, IDE_DATA_REG);
-}
-
--static ssize_t
--qeth_dev_ipato_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ /*
+ * 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)
+ {
++ ide_hwif_t *hwif = drive->hwif;
+ int count;
+ char *buf;
+
+@@ -180,14 +146,12 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne
+ local_irq_save(flags);
+ buf = kmap_atomic(sg_page(pc->sg), KM_IRQ0) +
+ pc->sg->offset;
+- drive->hwif->atapi_input_bytes(drive,
+- buf + pc->b_count, count);
++ hwif->input_data(drive, NULL, buf + pc->b_count, count);
+ kunmap_atomic(buf - pc->sg->offset, KM_IRQ0);
+ local_irq_restore(flags);
+ } else {
+ buf = sg_virt(pc->sg);
+- drive->hwif->atapi_input_bytes(drive,
+- buf + pc->b_count, count);
++ hwif->input_data(drive, NULL, buf + pc->b_count, count);
+ }
+ bcount -= count; pc->b_count += count;
+ if (pc->b_count == pc->sg->length) {
+@@ -200,12 +164,14 @@ 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_pad_transfer(drive, 0, 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)
+ {
++ ide_hwif_t *hwif = drive->hwif;
+ int count;
+ char *buf;
+
+@@ -217,14 +183,12 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign
+ local_irq_save(flags);
+ buf = kmap_atomic(sg_page(pc->sg), KM_IRQ0) +
+ pc->sg->offset;
+- drive->hwif->atapi_output_bytes(drive,
+- buf + pc->b_count, count);
++ hwif->output_data(drive, NULL, buf + pc->b_count, count);
+ kunmap_atomic(buf - pc->sg->offset, KM_IRQ0);
+ local_irq_restore(flags);
+ } else {
+ buf = sg_virt(pc->sg);
+- drive->hwif->atapi_output_bytes(drive,
+- buf + pc->b_count, count);
++ hwif->output_data(drive, NULL, buf + pc->b_count, count);
+ }
+ bcount -= count; pc->b_count += count;
+ if (pc->b_count == pc->sg->length) {
+@@ -237,7 +201,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_pad_transfer(drive, 1, bcount);
+ }
+ }
+
+@@ -246,15 +210,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 +231,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 +252,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->OUTBSYNC(drive, WIN_IDLEIMMEDIATE,
++ hwif->io_ports.command_addr);
+
+ rq->errors++;
+
+@@ -303,7 +271,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 +284,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 +296,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 +341,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 +349,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 +366,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 +376,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,12 +385,13 @@ 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;
+- (void) HWIF(drive)->ide_dma_end(drive);
++ pc->xferred = pc->req_xfer;
++ (void)hwif->dma_ops->dma_end(drive);
+ }
+
+ /* Clear the interrupt */
+@@ -428,42 +400,45 @@ 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.lbah_addr) << 8) |
++ hwif->INB(hwif->io_ports.lbam_addr);
++ ireason = hwif->INB(hwif->io_ports.nsect_addr);
+
+ 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);
++ hwif->input_data(drive, NULL,
++ 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_pad_transfer(drive, 0, bcount - temp);
+ ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
+ return ide_started;
+ }
+@@ -473,23 +448,21 @@ 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,
+- bcount);
++ hwif->input_data(drive, NULL, 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,
+- bcount);
++ hwif->output_data(drive, NULL, 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 +473,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 +482,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.nsect_addr);
+ if ((ireason & CD) == 0 || (ireason & IO)) {
+ printk(KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while "
+ "issuing a packet command\n");
+@@ -518,36 +491,38 @@ static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive)
+ BUG_ON(HWGROUP(drive)->handler != NULL);
+ /* Set the interrupt routine */
+ 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);
+- hwif->dma_start(drive);
++ hwif->output_data(drive, NULL, scsi->pc->c, 12);
++
++ if (pc->flags & PC_FLAG_DMA_OK) {
++ pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
++ hwif->dma_ops->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,32 +541,32 @@ 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;
+- dma = !hwif->dma_setup(drive);
++ dma = !hwif->dma_ops->dma_setup(drive);
+ hwif->sg_mapped = 0;
+ }
+
+ 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 +574,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);
++ ide_execute_pkt_cmd(drive);
+ return idescsi_transfer_pc(drive);
+ }
+ }
+@@ -615,7 +590,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 +749,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 +767,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 +842,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 +892,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 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;
+- struct ipr_sata_port *sata_port = ap->private_data;
+- struct ipr_ioasa_gata *g = &sata_port->ioasa;
-
-- 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;
+- 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;
-}
-
--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);
+-/**
+ * 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;
-}
--
--static ssize_t
--qeth_dev_ipato_invert4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++ 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 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);
+- 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);
-
--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;
+- for (i = 0, xfer_cnt = 0;
+- (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
+- min_cnt = min(count - xfer_cnt, sg[i].length);
-
-- if (qeth_check_layer2(card))
-- return -EPERM;
+- /* 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);
-
-- entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
-- /* add strlen for "/<mask>\n" */
-- entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
-- spin_lock_irqsave(&card->ip_lock, flags);
-- list_for_each_entry(ipatoe, &card->ipato.entries, entry){
-- if (ipatoe->proto != proto)
-- continue;
-- /* String must not be longer than PAGE_SIZE. So we check if
-- * string length gets near PAGE_SIZE. Then we can savely display
-- * the next IPv6 address (worst case, compared to IPv4) */
-- if ((PAGE_SIZE - i) <= entry_len)
-- break;
-- qeth_ipaddr_to_string(proto, ipatoe->addr, addr_str);
-- i += snprintf(buf + i, PAGE_SIZE - i,
-- "%s/%i\n", addr_str, ipatoe->mask_bits);
-- }
-- spin_unlock_irqrestore(&card->ip_lock, flags);
-- i += snprintf(buf + i, PAGE_SIZE - i, "\n");
+- for (i = 0, xfer_cnt = 0;
+- (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
+- min_cnt = min(count - xfer_cnt, sg[i].length);
-
-- return i;
--}
+- /* 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/jazz_esp.c b/drivers/scsi/jazz_esp.c
+index 5d23101..b2d481d 100644
+--- a/drivers/scsi/jazz_esp.c
++++ b/drivers/scsi/jazz_esp.c
+@@ -217,11 +217,15 @@ static int __devexit esp_jazz_remove(struct platform_device *dev)
+ return 0;
+ }
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:jazz_esp");
++
+ static struct platform_driver esp_jazz_driver = {
+ .probe = esp_jazz_probe,
+ .remove = __devexit_p(esp_jazz_remove),
+ .driver = {
+ .name = "jazz_esp",
++ .owner = THIS_MODULE,
+ },
+ };
+
+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;
-
--static ssize_t
--qeth_dev_ipato_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
++ }
+ 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 qeth_card *card = dev->driver_data;
--
-- if (!card)
-- return -EINVAL;
--
-- return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
+- struct domain_device *dev = ap->private_data;
+- memcpy(tf, &dev->sata_dev.tf, sizeof (*tf));
-}
-
--static int
--qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto,
-- u8 *addr, int *mask_bits)
--{
-- const char *start, *end;
-- char *tmp;
-- char buffer[40] = {0, };
--
-- start = buf;
-- /* get address string */
-- end = strchr(start, '/');
-- if (!end || (end - start >= 40)){
-- PRINT_WARN("Invalid format for ipato_addx/delx. "
-- "Use <ip addr>/<mask bits>\n");
-- return -EINVAL;
-- }
-- strncpy(buffer, start, end - start);
-- if (qeth_string_to_ipaddr(buffer, proto, addr)){
-- PRINT_WARN("Invalid IP address format!\n");
-- return -EINVAL;
-- }
-- start = end + 1;
-- *mask_bits = simple_strtoul(start, &tmp, 10);
-- if (!strlen(start) ||
-- (tmp == start) ||
-- (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) {
-- PRINT_WARN("Invalid mask bits for ipato_addx/delx !\n");
-- return -EINVAL;
-- }
-- return 0;
--}
+ static int sas_ata_scr_write(struct ata_port *ap, unsigned int sc_reg_in,
+ u32 val)
+ {
+@@ -348,14 +344,11 @@ static int sas_ata_scr_read(struct ata_port *ap, unsigned int sc_reg_in,
+ }
+
+ static struct ata_port_operations sas_sata_ops = {
+- .check_status = sas_ata_check_status,
+- .check_altstatus = sas_ata_check_status,
+- .dev_select = ata_noop_dev_select,
+ .phy_reset = sas_ata_phy_reset,
+ .post_internal_cmd = sas_ata_post_internal,
+- .tf_read = sas_ata_tf_read,
+ .qc_prep = ata_noop_qc_prep,
+ .qc_issue = sas_ata_qc_issue,
++ .qc_fill_rtf = sas_ata_qc_fill_rtf,
+ .port_start = ata_sas_port_start,
+ .port_stop = ata_sas_port_stop,
+ .scr_read = sas_ata_scr_read,
+@@ -698,7 +691,7 @@ static int sas_discover_sata_dev(struct domain_device *dev)
+ /* incomplete response */
+ SAS_DPRINTK("sending SET FEATURE/PUP_STBY_SPIN_UP to "
+ "dev %llx\n", SAS_ADDR(dev->sas_addr));
+- if (!le16_to_cpu(identify_x[83] & (1<<6)))
++ if (!(identify_x[83] & cpu_to_le16(1<<6)))
+ goto cont1;
+ res = sas_issue_ata_cmd(dev, ATA_SET_FEATURES,
+ ATA_FEATURE_PUP_STBY_SPIN_UP,
+diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
+index 1f82415..601ec5b 100644
+--- a/drivers/scsi/libsas/sas_scsi_host.c
++++ b/drivers/scsi/libsas/sas_scsi_host.c
+@@ -24,6 +24,8 @@
+ */
+
+ #include <linux/kthread.h>
++#include <linux/firmware.h>
++#include <linux/ctype.h>
+
+ #include "sas_internal.h"
+
+@@ -1064,6 +1066,45 @@ void sas_target_destroy(struct scsi_target *starget)
+ return;
+ }
+
++static void sas_parse_addr(u8 *sas_addr, const char *p)
++{
++ int i;
++ for (i = 0; i < SAS_ADDR_SIZE; i++) {
++ u8 h, l;
++ if (!*p)
++ break;
++ h = isdigit(*p) ? *p-'0' : toupper(*p)-'A'+10;
++ p++;
++ l = isdigit(*p) ? *p-'0' : toupper(*p)-'A'+10;
++ p++;
++ sas_addr[i] = (h<<4) | l;
++ }
++}
++
++#define SAS_STRING_ADDR_SIZE 16
++
++int sas_request_addr(struct Scsi_Host *shost, u8 *addr)
++{
++ int res;
++ const struct firmware *fw;
++
++ res = request_firmware(&fw, "sas_addr", &shost->shost_gendev);
++ if (res)
++ return res;
++
++ if (fw->size < SAS_STRING_ADDR_SIZE) {
++ res = -ENODEV;
++ goto out;
++ }
++
++ sas_parse_addr(addr, fw->data);
++
++out:
++ release_firmware(fw);
++ return res;
++}
++EXPORT_SYMBOL_GPL(sas_request_addr);
++
+ EXPORT_SYMBOL_GPL(sas_queuecommand);
+ EXPORT_SYMBOL_GPL(sas_target_alloc);
+ EXPORT_SYMBOL_GPL(sas_slave_configure);
+diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
+index 2ab2d24..ec0b0f6 100644
+--- a/drivers/scsi/lpfc/lpfc.h
++++ b/drivers/scsi/lpfc/lpfc.h
+@@ -23,7 +23,7 @@
+
+ struct lpfc_sli2_slim;
+
+-#define LPFC_MAX_TARGET 256 /* max number of targets supported */
++#define LPFC_MAX_TARGET 4096 /* max number of targets supported */
+ #define LPFC_MAX_DISC_THREADS 64 /* max outstanding discovery els
+ requests */
+ #define LPFC_MAX_NS_RETRY 3 /* Number of retry attempts to contact
+@@ -268,7 +268,6 @@ struct lpfc_vport {
+ #define FC_NLP_MORE 0x40 /* More node to process in node tbl */
+ #define FC_OFFLINE_MODE 0x80 /* Interface is offline for diag */
+ #define FC_FABRIC 0x100 /* We are fabric attached */
+-#define FC_ESTABLISH_LINK 0x200 /* Reestablish Link */
+ #define FC_RSCN_DISCOVERY 0x400 /* Auth all devices after RSCN */
+ #define FC_SCSI_SCAN_TMO 0x4000 /* scsi scan timer running */
+ #define FC_ABORT_DISCOVERY 0x8000 /* we want to abort discovery */
+@@ -433,8 +432,6 @@ struct lpfc_hba {
+
+ uint32_t fc_eventTag; /* event tag for link attention */
+
-
--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;
+- 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..960baaf 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_link_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)
-
-- if (qeth_check_layer2(card))
-- return -EPERM;
-- if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits)))
-- return rc;
+-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(link_state, S_IRUGO, lpfc_link_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_link_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,
-
-- 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;
+- &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_link_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 ((rc = qeth_add_ipato_entry(card, ipatoe))){
-- kfree(ipatoe);
-- return rc;
++ 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;
- }
--
-- 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;
++ 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 {
-- 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");
+- 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);
+ }
+ }
-
-- return i;
--}
-
--static ssize_t
--qeth_dev_vipa_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
+-#if 0
+-void lpfc_fabric_abort_flogi(struct lpfc_hba *phba)
-{
-- struct qeth_card *card = dev->driver_data;
--
-- if (!card)
-- return -EINVAL;
+- LIST_HEAD(completions);
+- struct lpfc_iocbq *tmp_iocb, *piocb;
+- IOCB_t *cmd;
+- struct lpfc_nodelist *ndlp;
-
-- return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
--}
+- spin_lock_irq(&phba->hbalock);
+- list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
+- list) {
-
--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;
+- 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);
- }
-- 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;
+- spin_unlock_irq(&phba->hbalock);
-
-- if (qeth_check_layer2(card))
-- return -EPERM;
+- while (!list_empty(&completions)) {
+- piocb = list_get_first(&completions, struct lpfc_iocbq, list);
+- list_del_init(&piocb->list);
-
-- 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);
+- cmd = &piocb->iocb;
+- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+- (piocb->iocb_cmpl) (phba, piocb, piocb);
- }
-- spin_unlock_irqrestore(&card->ip_lock, flags);
-- i += snprintf(buf + i, PAGE_SIZE - i, "\n");
--
-- return i;
-}
+-#endif /* 0 */
-
--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);
--}
+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);
-
--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;
+ 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;
- }
-- 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)
+ /* 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 qeth_card *card = dev->driver_data;
--
-- if (!card)
-- return -EINVAL;
+- struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+- struct lpfc_nodelist *ndlp;
-
-- return qeth_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
+- spin_lock_irq(shost->host_lock);
+- ndlp = __lpfc_find_node(vport, filter, param);
+- spin_unlock_irq(shost->host_lock);
+- return ndlp;
-}
+-#endif /* 0 */
-
--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)
+ /*
+ * 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)
-{
-- 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);
+- struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+- struct lpfc_nodelist *ndlp;
-
-- 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;
+- spin_lock_irq(shost->host_lock);
+- ndlp = __lpfc_findnode_rpi(vport, rpi);
+- spin_unlock_irq(shost->host_lock);
+- return ndlp;
-}
+-#endif /* 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);
--}
+ /*
+ * 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);
+
-
--/**********************/
--/* DRIVER ATTRIBUTES */
--/**********************/
--static ssize_t
--qeth_driver_group_store(struct device_driver *ddrv, const char *buf,
-- size_t count)
+ /*
+ * 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)
-{
-- const char *start, *end;
-- char bus_ids[3][BUS_ID_SIZE], *argv[3];
+- struct lpfc_hba *phba = (struct lpfc_hba *) ptr;
+- struct lpfc_vport **vports;
+- unsigned long iflag;
- 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;
+- /* 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;
-
--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;
-- }
+ 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);
-
-- signum = simple_strtoul(tmp, &tmp2, 10);
-- if ((signum < 0) || (signum > 32)){
-- PRINT_WARN("Signal number %d is out of range\n", signum);
-- return -EINVAL;
+ 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);
- }
-- if ((rc = qeth_notifier_register(current, signum)))
-- return rc;
--
-- return count;
--}
--
--static DRIVER_ATTR(notifier_register, 0200, NULL,
-- qeth_driver_notifier_register_store);
--
--int
--qeth_create_driver_attributes(void)
--{
-- int rc;
--
-- if ((rc = driver_create_file(&qeth_ccwgroup_driver.driver,
-- &driver_attr_group)))
-- return rc;
-- return driver_create_file(&qeth_ccwgroup_driver.driver,
-- &driver_attr_notifier_register);
--}
--
--void
--qeth_remove_driver_attributes(void)
--{
-- driver_remove_file(&qeth_ccwgroup_driver.driver,
-- &driver_attr_group);
-- driver_remove_file(&qeth_ccwgroup_driver.driver,
-- &driver_attr_notifier_register);
--}
-diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h
-deleted file mode 100644
-index c20e923..0000000
---- a/drivers/s390/net/qeth_tso.h
-+++ /dev/null
-@@ -1,148 +0,0 @@
--/*
-- * linux/drivers/s390/net/qeth_tso.h
-- *
-- * Header file for qeth TCP Segmentation Offload support.
-- *
-- * Copyright 2004 IBM Corporation
-- *
-- * Author(s): Frank Pavlic <fpavlic at de.ibm.com>
-- *
-- */
--#ifndef __QETH_TSO_H__
--#define __QETH_TSO_H__
--
--#include <linux/skbuff.h>
--#include <linux/tcp.h>
--#include <linux/ip.h>
--#include <linux/ipv6.h>
--#include <net/ip6_checksum.h>
--#include "qeth.h"
--#include "qeth_mpc.h"
--
--
--static inline struct qeth_hdr_tso *
--qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb)
--{
-- QETH_DBF_TEXT(trace, 5, "tsoprsk");
-- return qeth_push_skb(card, *skb, sizeof(struct qeth_hdr_tso));
--}
--
--/**
-- * fill header for a TSO packet
-- */
--static inline void
--qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb)
--{
-- struct qeth_hdr_tso *hdr;
-- struct tcphdr *tcph;
-- struct iphdr *iph;
--
-- QETH_DBF_TEXT(trace, 5, "tsofhdr");
--
-- hdr = (struct qeth_hdr_tso *) skb->data;
-- iph = ip_hdr(skb);
-- tcph = tcp_hdr(skb);
-- /*fix header to TSO values ...*/
-- hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO;
-- /*set values which are fix for the first approach ...*/
-- hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso);
-- hdr->ext.imb_hdr_no = 1;
-- hdr->ext.hdr_type = 1;
-- hdr->ext.hdr_version = 1;
-- hdr->ext.hdr_len = 28;
-- /*insert non-fix values */
-- hdr->ext.mss = skb_shinfo(skb)->gso_size;
-- hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
-- hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
-- sizeof(struct qeth_hdr_tso));
--}
--
--/**
-- * change some header values as requested by hardware
-- */
--static inline void
--qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb)
--{
-- struct iphdr *iph = ip_hdr(skb);
-- struct ipv6hdr *ip6h = ipv6_hdr(skb);
-- struct tcphdr *tcph = tcp_hdr(skb);
++ 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);
-
-- 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;
+- 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;
- }
-- /*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;
--}
+
+ 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;
+ }
+ }
+
-
--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;
+ /* 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;
+
-
-- QETH_DBF_TEXT(trace, 5, "tsoprep");
+ mb = &pmbox->mb;
+ status = MBX_SUCCESS;
+
+@@ -2717,14 +2728,14 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+
+ /* Mbox command <mbxCommand> cannot issue */
+ LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+- return MBX_NOT_FINISHED;
++ goto out_not_finished;
+ }
+
+ if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT &&
+ !(readl(phba->HCregaddr) & HC_MBINT_ENA)) {
+ spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+- return MBX_NOT_FINISHED;
++ goto out_not_finished;
+ }
+
+ if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
+@@ -2738,14 +2749,14 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+
+ /* Mbox command <mbxCommand> cannot issue */
+ LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+- return MBX_NOT_FINISHED;
++ goto out_not_finished;
+ }
+
+ if (!(psli->sli_flag & LPFC_SLI2_ACTIVE)) {
+ spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ /* Mbox command <mbxCommand> cannot issue */
+ LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+- return MBX_NOT_FINISHED;
++ goto out_not_finished;
+ }
+
+ /* Another mailbox command is still being processed, queue this
+@@ -2792,7 +2803,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+ spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ /* Mbox command <mbxCommand> cannot issue */
+ LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+- return MBX_NOT_FINISHED;
++ goto out_not_finished;
+ }
+ /* timeout active mbox command */
+ mod_timer(&psli->mbox_tmo, (jiffies +
+@@ -2900,7 +2911,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+ psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+ spin_unlock_irqrestore(&phba->hbalock,
+ drvr_flag);
+- return MBX_NOT_FINISHED;
++ goto out_not_finished;
+ }
+
+ /* Check if we took a mbox interrupt while we were
+@@ -2967,6 +2978,13 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+
+ spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ return status;
++
++out_not_finished:
++ if (processing_queue) {
++ pmbox->mb.mbxStatus = MBX_NOT_FINISHED;
++ lpfc_mbox_cmpl_put(phba, pmbox);
++ }
++ return MBX_NOT_FINISHED;
+ }
+
+ /*
+@@ -3463,26 +3481,21 @@ lpfc_sli_hba_down(struct lpfc_hba *phba)
+ phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
+ spin_unlock(&phba->pport->work_port_lock);
+
++ /* Return any pending or completed mbox cmds */
++ list_splice_init(&phba->sli.mboxq, &completions);
+ if (psli->mbox_active) {
+ list_add_tail(&psli->mbox_active->list, &completions);
+ psli->mbox_active = NULL;
+ psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+ }
-
-- 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;
--}
+- /* 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);
-
--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;
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+
+ while (!list_empty(&completions)) {
+ list_remove_head(&completions, pmb, LPFC_MBOXQ_t, list);
+ pmb->mb.mbxStatus = MBX_NOT_FINISHED;
+- if (pmb->mbox_cmpl) {
++ if (pmb->mbox_cmpl)
+ pmb->mbox_cmpl(phba,pmb);
+- }
+ }
+ return 1;
+ }
+@@ -3613,6 +3626,15 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ irsp->ulpStatus, irsp->un.ulpWord[4]);
+
+ /*
++ * If the iocb is not found in Firmware queue the iocb
++ * might have completed already. Do not free it again.
++ */
++ if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
++ spin_unlock_irq(&phba->hbalock);
++ lpfc_sli_release_iocbq(phba, cmdiocb);
++ return;
++ }
++ /*
+ * make sure we have the right iocbq before taking it
+ * off the txcmplq and try to call completion routine.
+ */
+@@ -4174,6 +4196,7 @@ lpfc_intr_handler(int irq, void *dev_id)
+ phba->pport->stopped = 1;
+ }
+
++ spin_lock(&phba->hbalock);
+ if ((work_ha_copy & HA_MBATT) &&
+ (phba->sli.mbox_active)) {
+ pmb = phba->sli.mbox_active;
+@@ -4184,6 +4207,7 @@ lpfc_intr_handler(int irq, void *dev_id)
+ /* First check out the status word */
+ lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t));
+ if (pmbox->mbxOwner != OWN_HOST) {
++ spin_unlock(&phba->hbalock);
+ /*
+ * Stray Mailbox Interrupt, mbxCommand <cmd>
+ * mbxStatus <status>
+@@ -4199,10 +4223,10 @@ lpfc_intr_handler(int irq, void *dev_id)
+ /* clear mailbox attention bit */
+ work_ha_copy &= ~HA_MBATT;
+ } else {
++ phba->sli.mbox_active = NULL;
++ spin_unlock(&phba->hbalock);
+ phba->last_completion_time = jiffies;
+ del_timer(&phba->sli.mbox_tmo);
-
-- fragno = skb_shinfo(skb)->nr_frags;
-- element = *next_element_to_fill;
-- dlen = 0;
+- 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;
+- }
+- }
-
-- 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:
++ 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_esp.c b/drivers/scsi/mac_esp.c
+new file mode 100644
+index 0000000..cd37bd6
+--- /dev/null
++++ b/drivers/scsi/mac_esp.c
+@@ -0,0 +1,657 @@
++/* mac_esp.c: ESP front-end for Macintosh Quadra systems.
++ *
++ * Adapted from jazz_esp.c and the old mac_esp.c.
++ *
++ * The pseudo DMA algorithm is based on the one used in NetBSD.
++ * See sys/arch/mac68k/obio/esp.c for some background information.
++ *
++ * Copyright (C) 2007-2008 Finn Thain
++ */
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/dma-mapping.h>
++#include <linux/scatterlist.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/nubus.h>
++
++#include <asm/irq.h>
++#include <asm/dma.h>
++
++#include <asm/macints.h>
++#include <asm/macintosh.h>
++
++#include <scsi/scsi_host.h>
++
++#include "esp_scsi.h"
++
++#define DRV_MODULE_NAME "mac_esp"
++#define PFX DRV_MODULE_NAME ": "
++#define DRV_VERSION "1.000"
++#define DRV_MODULE_RELDATE "Sept 15, 2007"
++
++#define MAC_ESP_IO_BASE 0x50F00000
++#define MAC_ESP_REGS_QUADRA (MAC_ESP_IO_BASE + 0x10000)
++#define MAC_ESP_REGS_QUADRA2 (MAC_ESP_IO_BASE + 0xF000)
++#define MAC_ESP_REGS_QUADRA3 (MAC_ESP_IO_BASE + 0x18000)
++#define MAC_ESP_REGS_SPACING 0x402
++#define MAC_ESP_PDMA_REG 0xF9800024
++#define MAC_ESP_PDMA_REG_SPACING 0x4
++#define MAC_ESP_PDMA_IO_OFFSET 0x100
++
++#define esp_read8(REG) mac_esp_read8(esp, REG)
++#define esp_write8(VAL, REG) mac_esp_write8(esp, VAL, REG)
++
++struct mac_esp_priv {
++ struct esp *esp;
++ void __iomem *pdma_regs;
++ void __iomem *pdma_io;
++ int error;
++};
++static struct platform_device *internal_esp, *external_esp;
++
++#define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \
++ platform_get_drvdata((struct platform_device *) \
++ (esp->dev)))
++
++static inline void mac_esp_write8(struct esp *esp, u8 val, unsigned long reg)
++{
++ nubus_writeb(val, esp->regs + reg * 16);
++}
++
++static inline u8 mac_esp_read8(struct esp *esp, unsigned long reg)
++{
++ return nubus_readb(esp->regs + reg * 16);
++}
++
++/* For pseudo DMA and PIO we need the virtual address
++ * so this address mapping is the identity mapping.
++ */
++
++static dma_addr_t mac_esp_map_single(struct esp *esp, void *buf,
++ size_t sz, int dir)
++{
++ return (dma_addr_t)buf;
++}
++
++static int mac_esp_map_sg(struct esp *esp, struct scatterlist *sg,
++ int num_sg, int dir)
++{
++ int i;
++
++ for (i = 0; i < num_sg; i++)
++ sg[i].dma_address = (u32)sg_virt(&sg[i]);
++ return num_sg;
++}
++
++static void mac_esp_unmap_single(struct esp *esp, dma_addr_t addr,
++ size_t sz, int dir)
++{
++ /* Nothing to do. */
++}
++
++static void mac_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
++ int num_sg, int dir)
++{
++ /* Nothing to do. */
++}
++
++static void mac_esp_reset_dma(struct esp *esp)
++{
++ /* Nothing to do. */
++}
++
++static void mac_esp_dma_drain(struct esp *esp)
++{
++ /* Nothing to do. */
++}
++
++static void mac_esp_dma_invalidate(struct esp *esp)
++{
++ /* Nothing to do. */
++}
++
++static int mac_esp_dma_error(struct esp *esp)
++{
++ return MAC_ESP_GET_PRIV(esp)->error;
++}
++
++static inline int mac_esp_wait_for_empty_fifo(struct esp *esp)
++{
++ struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
++ int i = 500000;
++
++ do {
++ if (!(esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES))
++ return 0;
++
++ if (esp_read8(ESP_STATUS) & ESP_STAT_INTR)
++ return 1;
++
++ udelay(2);
++ } while (--i);
++
++ printk(KERN_ERR PFX "FIFO is not empty (sreg %02x)\n",
++ esp_read8(ESP_STATUS));
++ mep->error = 1;
++ return 1;
++}
++
++static inline int mac_esp_wait_for_dreq(struct esp *esp)
++{
++ struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
++ int i = 500000;
++
++ do {
++ if (mep->pdma_regs == NULL) {
++ if (mac_irq_pending(IRQ_MAC_SCSIDRQ))
++ return 0;
++ } else {
++ if (nubus_readl(mep->pdma_regs) & 0x200)
++ return 0;
++ }
++
++ if (esp_read8(ESP_STATUS) & ESP_STAT_INTR)
++ return 1;
++
++ udelay(2);
++ } while (--i);
++
++ printk(KERN_ERR PFX "PDMA timeout (sreg %02x)\n",
++ esp_read8(ESP_STATUS));
++ mep->error = 1;
++ return 1;
++}
++
++#define MAC_ESP_PDMA_LOOP(operands) \
++ asm volatile ( \
++ " tstw %2 \n" \
++ " jbeq 20f \n" \
++ "1: movew " operands " \n" \
++ "2: movew " operands " \n" \
++ "3: movew " operands " \n" \
++ "4: movew " operands " \n" \
++ "5: movew " operands " \n" \
++ "6: movew " operands " \n" \
++ "7: movew " operands " \n" \
++ "8: movew " operands " \n" \
++ "9: movew " operands " \n" \
++ "10: movew " operands " \n" \
++ "11: movew " operands " \n" \
++ "12: movew " operands " \n" \
++ "13: movew " operands " \n" \
++ "14: movew " operands " \n" \
++ "15: movew " operands " \n" \
++ "16: movew " operands " \n" \
++ " subqw #1,%2 \n" \
++ " jbne 1b \n" \
++ "20: tstw %3 \n" \
++ " jbeq 30f \n" \
++ "21: movew " operands " \n" \
++ " subqw #1,%3 \n" \
++ " jbne 21b \n" \
++ "30: tstw %4 \n" \
++ " jbeq 40f \n" \
++ "31: moveb " operands " \n" \
++ "32: nop \n" \
++ "40: \n" \
++ " \n" \
++ " .section __ex_table,\"a\" \n" \
++ " .align 4 \n" \
++ " .long 1b,40b \n" \
++ " .long 2b,40b \n" \
++ " .long 3b,40b \n" \
++ " .long 4b,40b \n" \
++ " .long 5b,40b \n" \
++ " .long 6b,40b \n" \
++ " .long 7b,40b \n" \
++ " .long 8b,40b \n" \
++ " .long 9b,40b \n" \
++ " .long 10b,40b \n" \
++ " .long 11b,40b \n" \
++ " .long 12b,40b \n" \
++ " .long 13b,40b \n" \
++ " .long 14b,40b \n" \
++ " .long 15b,40b \n" \
++ " .long 16b,40b \n" \
++ " .long 21b,40b \n" \
++ " .long 31b,40b \n" \
++ " .long 32b,40b \n" \
++ " .previous \n" \
++ : "+a" (addr) \
++ : "a" (mep->pdma_io), "r" (count32), "r" (count2), "g" (esp_count))
++
++static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count,
++ u32 dma_count, int write, u8 cmd)
++{
++ struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ mep->error = 0;
++
++ if (!write)
++ scsi_esp_cmd(esp, ESP_CMD_FLUSH);
++
++ esp_write8((esp_count >> 0) & 0xFF, ESP_TCLOW);
++ esp_write8((esp_count >> 8) & 0xFF, ESP_TCMED);
++
++ scsi_esp_cmd(esp, cmd);
++
++ do {
++ unsigned int count32 = esp_count >> 5;
++ unsigned int count2 = (esp_count & 0x1F) >> 1;
++ unsigned int start_addr = addr;
++
++ if (mac_esp_wait_for_dreq(esp))
++ break;
++
++ if (write) {
++ MAC_ESP_PDMA_LOOP("%1@,%0 at +");
++
++ esp_count -= addr - start_addr;
++ } else {
++ unsigned int n;
++
++ MAC_ESP_PDMA_LOOP("%0 at +,%1@");
++
++ if (mac_esp_wait_for_empty_fifo(esp))
++ break;
++
++ n = (esp_read8(ESP_TCMED) << 8) + esp_read8(ESP_TCLOW);
++ addr = start_addr + esp_count - n;
++ esp_count = n;
++ }
++ } while (esp_count);
++
++ local_irq_restore(flags);
++}
++
++/*
++ * Programmed IO routines follow.
++ */
++
++static inline int mac_esp_wait_for_fifo(struct esp *esp)
++{
++ int i = 500000;
++
++ do {
++ if (esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES)
++ return 0;
++
++ udelay(2);
++ } while (--i);
++
++ printk(KERN_ERR PFX "FIFO is empty (sreg %02x)\n",
++ esp_read8(ESP_STATUS));
++ return 1;
++}
++
++static inline int mac_esp_wait_for_intr(struct esp *esp)
++{
++ int i = 500000;
++
++ do {
++ esp->sreg = esp_read8(ESP_STATUS);
++ if (esp->sreg & ESP_STAT_INTR)
++ return 0;
++
++ udelay(2);
++ } while (--i);
++
++ printk(KERN_ERR PFX "IRQ timeout (sreg %02x)\n", esp->sreg);
++ return 1;
++}
++
++#define MAC_ESP_PIO_LOOP(operands, reg1) \
++ asm volatile ( \
++ "1: moveb " operands " \n" \
++ " subqw #1,%1 \n" \
++ " jbne 1b \n" \
++ : "+a" (addr), "+r" (reg1) \
++ : "a" (fifo))
++
++#define MAC_ESP_PIO_FILL(operands, reg1) \
++ asm volatile ( \
++ " moveb " operands " \n" \
++ " moveb " operands " \n" \
++ " moveb " operands " \n" \
++ " moveb " operands " \n" \
++ " moveb " operands " \n" \
++ " moveb " operands " \n" \
++ " moveb " operands " \n" \
++ " moveb " operands " \n" \
++ " moveb " operands " \n" \
++ " moveb " operands " \n" \
++ " moveb " operands " \n" \
++ " moveb " operands " \n" \
++ " moveb " operands " \n" \
++ " moveb " operands " \n" \
++ " moveb " operands " \n" \
++ " moveb " operands " \n" \
++ " subqw #8,%1 \n" \
++ " subqw #8,%1 \n" \
++ : "+a" (addr), "+r" (reg1) \
++ : "a" (fifo))
++
++#define MAC_ESP_FIFO_SIZE 16
++
++static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
++ u32 dma_count, int write, u8 cmd)
++{
++ unsigned long flags;
++ struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
++ u8 *fifo = esp->regs + ESP_FDATA * 16;
++
++ local_irq_save(flags);
++
++ cmd &= ~ESP_CMD_DMA;
++ mep->error = 0;
++
++ if (write) {
++ scsi_esp_cmd(esp, cmd);
++
++ if (!mac_esp_wait_for_intr(esp)) {
++ if (mac_esp_wait_for_fifo(esp))
++ esp_count = 0;
++ } else {
++ esp_count = 0;
++ }
++ } else {
++ scsi_esp_cmd(esp, ESP_CMD_FLUSH);
++
++ if (esp_count >= MAC_ESP_FIFO_SIZE)
++ MAC_ESP_PIO_FILL("%0 at +,%2@", esp_count);
++ else
++ MAC_ESP_PIO_LOOP("%0 at +,%2@", esp_count);
++
++ scsi_esp_cmd(esp, cmd);
++ }
++
++ while (esp_count) {
++ unsigned int n;
++
++ if (mac_esp_wait_for_intr(esp)) {
++ mep->error = 1;
++ break;
++ }
++
++ if (esp->sreg & ESP_STAT_SPAM) {
++ printk(KERN_ERR PFX "gross error\n");
++ mep->error = 1;
++ break;
++ }
++
++ n = esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES;
++
++ if (write) {
++ if (n > esp_count)
++ n = esp_count;
++ esp_count -= n;
++
++ MAC_ESP_PIO_LOOP("%2@,%0 at +", n);
++
++ if ((esp->sreg & ESP_STAT_PMASK) == ESP_STATP)
++ break;
++
++ if (esp_count) {
++ esp->ireg = esp_read8(ESP_INTRPT);
++ if (esp->ireg & ESP_INTR_DC)
++ break;
++
++ scsi_esp_cmd(esp, ESP_CMD_TI);
++ }
++ } else {
++ esp->ireg = esp_read8(ESP_INTRPT);
++ if (esp->ireg & ESP_INTR_DC)
++ break;
++
++ n = MAC_ESP_FIFO_SIZE - n;
++ if (n > esp_count)
++ n = esp_count;
++
++ if (n == MAC_ESP_FIFO_SIZE) {
++ MAC_ESP_PIO_FILL("%0 at +,%2@", esp_count);
++ } else {
++ esp_count -= n;
++ MAC_ESP_PIO_LOOP("%0 at +,%2@", n);
++ }
++
++ scsi_esp_cmd(esp, ESP_CMD_TI);
++ }
++ }
++
++ local_irq_restore(flags);
++}
++
++static int mac_esp_irq_pending(struct esp *esp)
++{
++ if (esp_read8(ESP_STATUS) & ESP_STAT_INTR)
++ return 1;
++ return 0;
++}
++
++static u32 mac_esp_dma_length_limit(struct esp *esp, u32 dma_addr, u32 dma_len)
++{
++ return dma_len > 0xFFFF ? 0xFFFF : dma_len;
++}
++
++static struct esp_driver_ops mac_esp_ops = {
++ .esp_write8 = mac_esp_write8,
++ .esp_read8 = mac_esp_read8,
++ .map_single = mac_esp_map_single,
++ .map_sg = mac_esp_map_sg,
++ .unmap_single = mac_esp_unmap_single,
++ .unmap_sg = mac_esp_unmap_sg,
++ .irq_pending = mac_esp_irq_pending,
++ .dma_length_limit = mac_esp_dma_length_limit,
++ .reset_dma = mac_esp_reset_dma,
++ .dma_drain = mac_esp_dma_drain,
++ .dma_invalidate = mac_esp_dma_invalidate,
++ .send_dma_cmd = mac_esp_send_pdma_cmd,
++ .dma_error = mac_esp_dma_error,
++};
++
++static int __devinit esp_mac_probe(struct platform_device *dev)
++{
++ struct scsi_host_template *tpnt = &scsi_esp_template;
++ struct Scsi_Host *host;
++ struct esp *esp;
++ int err;
++ int chips_present;
++ struct mac_esp_priv *mep;
++
++ if (!MACH_IS_MAC)
++ return -ENODEV;
++
++ switch (macintosh_config->scsi_type) {
++ case MAC_SCSI_QUADRA:
++ case MAC_SCSI_QUADRA3:
++ chips_present = 1;
++ break;
++ case MAC_SCSI_QUADRA2:
++ if ((macintosh_config->ident == MAC_MODEL_Q900) ||
++ (macintosh_config->ident == MAC_MODEL_Q950))
++ chips_present = 2;
++ else
++ chips_present = 1;
++ break;
++ default:
++ chips_present = 0;
++ }
++
++ if (dev->id + 1 > chips_present)
++ return -ENODEV;
++
++ host = scsi_host_alloc(tpnt, sizeof(struct esp));
++
++ err = -ENOMEM;
++ if (!host)
++ goto fail;
++
++ host->max_id = 8;
++ host->use_clustering = DISABLE_CLUSTERING;
++ esp = shost_priv(host);
++
++ esp->host = host;
++ esp->dev = dev;
++
++ esp->command_block = kzalloc(16, GFP_KERNEL);
++ if (!esp->command_block)
++ goto fail_unlink;
++ esp->command_block_dma = (dma_addr_t)esp->command_block;
++
++ esp->scsi_id = 7;
++ host->this_id = esp->scsi_id;
++ esp->scsi_id_mask = 1 << esp->scsi_id;
++
++ mep = kzalloc(sizeof(struct mac_esp_priv), GFP_KERNEL);
++ if (!mep)
++ goto fail_free_command_block;
++ mep->esp = esp;
++ platform_set_drvdata(dev, mep);
++
++ switch (macintosh_config->scsi_type) {
++ case MAC_SCSI_QUADRA:
++ esp->cfreq = 16500000;
++ esp->regs = (void __iomem *)MAC_ESP_REGS_QUADRA;
++ mep->pdma_io = esp->regs + MAC_ESP_PDMA_IO_OFFSET;
++ mep->pdma_regs = NULL;
++ break;
++ case MAC_SCSI_QUADRA2:
++ esp->cfreq = 25000000;
++ esp->regs = (void __iomem *)(MAC_ESP_REGS_QUADRA2 +
++ dev->id * MAC_ESP_REGS_SPACING);
++ mep->pdma_io = esp->regs + MAC_ESP_PDMA_IO_OFFSET;
++ mep->pdma_regs = (void __iomem *)(MAC_ESP_PDMA_REG +
++ dev->id * MAC_ESP_PDMA_REG_SPACING);
++ nubus_writel(0x1d1, mep->pdma_regs);
++ break;
++ case MAC_SCSI_QUADRA3:
++ /* These quadras have a real DMA controller (the PSC) but we
++ * don't know how to drive it so we must use PIO instead.
++ */
++ esp->cfreq = 25000000;
++ esp->regs = (void __iomem *)MAC_ESP_REGS_QUADRA3;
++ mep->pdma_io = NULL;
++ mep->pdma_regs = NULL;
++ break;
++ }
++
++ esp->ops = &mac_esp_ops;
++ if (mep->pdma_io == NULL) {
++ printk(KERN_INFO PFX "using PIO for controller %d\n", dev->id);
++ esp_write8(0, ESP_TCLOW);
++ esp_write8(0, ESP_TCMED);
++ esp->flags = ESP_FLAG_DISABLE_SYNC;
++ mac_esp_ops.send_dma_cmd = mac_esp_send_pio_cmd;
++ } else {
++ printk(KERN_INFO PFX "using PDMA for controller %d\n", dev->id);
++ }
++
++ host->irq = IRQ_MAC_SCSI;
++ err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "Mac ESP",
++ esp);
++ if (err < 0)
++ goto fail_free_priv;
++
++ err = scsi_esp_register(esp, &dev->dev);
++ if (err)
++ goto fail_free_irq;
++
++ return 0;
++
++fail_free_irq:
++ free_irq(host->irq, esp);
++fail_free_priv:
++ kfree(mep);
++fail_free_command_block:
++ kfree(esp->command_block);
++fail_unlink:
++ scsi_host_put(host);
++fail:
++ return err;
++}
++
++static int __devexit esp_mac_remove(struct platform_device *dev)
++{
++ struct mac_esp_priv *mep = platform_get_drvdata(dev);
++ struct esp *esp = mep->esp;
++ unsigned int irq = esp->host->irq;
++
++ scsi_esp_unregister(esp);
++
++ free_irq(irq, esp);
++
++ kfree(mep);
++
++ kfree(esp->command_block);
++
++ scsi_host_put(esp->host);
++
++ return 0;
++}
++
++static struct platform_driver esp_mac_driver = {
++ .probe = esp_mac_probe,
++ .remove = __devexit_p(esp_mac_remove),
++ .driver = {
++ .name = DRV_MODULE_NAME,
++ },
++};
++
++static int __init mac_esp_init(void)
++{
++ int err;
++
++ err = platform_driver_register(&esp_mac_driver);
++ if (err)
++ return err;
++
++ internal_esp = platform_device_alloc(DRV_MODULE_NAME, 0);
++ if (internal_esp && platform_device_add(internal_esp)) {
++ platform_device_put(internal_esp);
++ internal_esp = NULL;
++ }
++
++ external_esp = platform_device_alloc(DRV_MODULE_NAME, 1);
++ if (external_esp && platform_device_add(external_esp)) {
++ platform_device_put(external_esp);
++ external_esp = NULL;
++ }
++
++ if (internal_esp || external_esp) {
++ return 0;
++ } else {
++ platform_driver_unregister(&esp_mac_driver);
++ return -ENOMEM;
++ }
++}
++
++static void __exit mac_esp_exit(void)
++{
++ platform_driver_unregister(&esp_mac_driver);
++
++ if (internal_esp) {
++ platform_device_unregister(internal_esp);
++ internal_esp = NULL;
++ }
++ if (external_esp) {
++ platform_device_unregister(external_esp);
++ external_esp = NULL;
++ }
++}
++
++MODULE_DESCRIPTION("Mac ESP SCSI driver");
++MODULE_AUTHOR("Finn Thain <fthain at telegraphics.com.au>");
++MODULE_LICENSE("GPLv2");
++MODULE_VERSION(DRV_VERSION);
++
++module_init(mac_esp_init);
++module_exit(mac_esp_exit);
+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
+ };
- printk(KERN_WARNING"%s: Code does not support more "
- "than two chained crws; please report to "
-- "linux390 at de.ibm.com!\n", __FUNCTION__);
-+ "linux390 at de.ibm.com!\n", __func__);
- ccode = stcrw(&tmp_crw);
- printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, "
- "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
-- __FUNCTION__, tmp_crw.slct, tmp_crw.oflw,
-+ __func__, tmp_crw.slct, tmp_crw.oflw,
- tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc,
- tmp_crw.erc, tmp_crw.rsid);
- printk(KERN_WARNING"%s: This was crw number %x in the "
-- "chain\n", __FUNCTION__, chain);
-+ "chain\n", __func__, chain);
- if (ccode != 0)
- break;
- chain = tmp_crw.chn ? chain + 1 : 0;
-@@ -83,7 +83,7 @@ repeat:
- crw[chain].rsid);
- /* Check for overflows. */
- if (crw[chain].oflw) {
-- pr_debug("%s: crw overflow detected!\n", __FUNCTION__);
-+ pr_debug("%s: crw overflow detected!\n", __func__);
- css_schedule_eval_all();
- chain = 0;
- continue;
-diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h
-index d3ca428..ca681f9 100644
---- a/drivers/s390/s390mach.h
-+++ b/drivers/s390/s390mach.h
-@@ -105,4 +105,8 @@ static inline int stcrw(struct crw *pcrw )
- #define ED_ETR_SYNC 12 /* External damage ETR sync check */
- #define ED_ETR_SWITCH 13 /* External damage ETR switch to local */
+diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
+index b135a1e..18551aa 100644
+--- a/drivers/scsi/megaraid.c
++++ b/drivers/scsi/megaraid.c
+@@ -4996,7 +4996,7 @@ static int __init megaraid_init(void)
+ max_mbox_busy_wait = MBOX_BUSY_WAIT;
-+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)
+ #ifdef CONFIG_PROC_FS
+- mega_proc_dir_entry = proc_mkdir("megaraid", &proc_root);
++ mega_proc_dir_entry = proc_mkdir("megaraid", NULL);
+ if (!mega_proc_dir_entry) {
+ printk(KERN_WARNING
+ "megaraid: failed to create megaraid root\n");
+@@ -5005,7 +5005,7 @@ static int __init megaraid_init(void)
+ error = pci_register_driver(&megaraid_pci_driver);
+ if (error) {
+ #ifdef CONFIG_PROC_FS
+- remove_proc_entry("megaraid", &proc_root);
++ remove_proc_entry("megaraid", NULL);
+ #endif
+ return error;
+ }
+@@ -5035,7 +5035,7 @@ static void __exit megaraid_exit(void)
+ pci_unregister_driver(&megaraid_pci_driver);
- /* initialize debug locks */
+ #ifdef CONFIG_PROC_FS
+- remove_proc_entry("megaraid", &proc_root);
++ remove_proc_entry("megaraid", NULL);
+ #endif
+ }
-- 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);
+diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h
+index fef9ac9..f62ed46 100644
+--- a/drivers/scsi/megaraid/mega_common.h
++++ b/drivers/scsi/megaraid/mega_common.h
+@@ -28,7 +28,6 @@
+ #include <linux/list.h>
+ #include <linux/moduleparam.h>
+ #include <linux/dma-mapping.h>
+-#include <asm/semaphore.h>
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_cmnd.h>
+ #include <scsi/scsi_device.h>
+diff --git a/drivers/scsi/megaraid/megaraid_ioctl.h b/drivers/scsi/megaraid/megaraid_ioctl.h
+index 706fa05..05f6e4e 100644
+--- a/drivers/scsi/megaraid/megaraid_ioctl.h
++++ b/drivers/scsi/megaraid/megaraid_ioctl.h
+@@ -18,7 +18,7 @@
+ #define _MEGARAID_IOCTL_H_
- retval = zfcp_adapter_debug_register(adapter);
- if (retval)
-@@ -1325,10 +1325,10 @@ zfcp_nameserver_enqueue(struct zfcp_adapter *adapter)
+ #include <linux/types.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
- #define ZFCP_LOG_AREA ZFCP_LOG_AREA_FC
+ #include "mbox_defs.h"
--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)
+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 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;
- }
+- 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;
-@@ -1406,10 +1407,10 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
- }
- }
+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,
--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)
+ /**
+ * 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)
{
-+ 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);
- }
+ 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);
--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);
- }
+ 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);
-@@ -1480,12 +1481,12 @@ zfcp_fsf_incoming_els(struct zfcp_fsf_req *fsf_req)
+- max_wait = 10;
++ max_wait = 60;
+ cur_state = MFI_STATE_OPERATIONAL;
+ break;
- 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;
+@@ -1980,7 +1993,8 @@ static int megasas_init_mfi(struct megasas_instance *instance)
-- 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;
+ 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;
-@@ -197,7 +198,7 @@ zfcp_ccw_set_offline(struct ccw_device *ccw_device)
+ memset(kbuff_arr, 0, sizeof(kbuff_arr));
- 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)
+@@ -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);
- 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,
+- 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
- #define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHER
+ /*
+@@ -542,6 +543,10 @@ struct megasas_ctrl_info {
--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);
-+ }
-+}
+ #define MEGASAS_FW_BUSY 1
+
++/* Frame Type */
++#define IO_FRAME 0
++#define PTHRU_FRAME 1
+
-+/* 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;
+ /*
+ * 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);
- 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);
- }
+ 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..ceab4f7 100644
+--- a/drivers/scsi/ncr53c8xx.c
++++ b/drivers/scsi/ncr53c8xx.c
+@@ -8186,7 +8186,7 @@ static void insert_into_waiting_list(struct ncb *np, struct scsi_cmnd *cmd)
+ cmd->next_wcmd = NULL;
+ if (!(wcmd = np->waiting_list)) np->waiting_list = cmd;
+ else {
+- while ((wcmd->next_wcmd) != 0)
++ while (wcmd->next_wcmd)
+ wcmd = (struct scsi_cmnd *) wcmd->next_wcmd;
+ wcmd->next_wcmd = (char *) cmd;
+ }
+@@ -8222,7 +8222,7 @@ static void process_waiting_list(struct ncb *np, int sts)
+ #ifdef DEBUG_WAITING_LIST
+ if (waiting_list) printk("%s: waiting_list=%lx processing sts=%d\n", ncr_name(np), (u_long) waiting_list, sts);
+ #endif
+- while ((wcmd = waiting_list) != 0) {
++ while (wcmd = waiting_list) {
+ waiting_list = (struct scsi_cmnd *) wcmd->next_wcmd;
+ wcmd->next_wcmd = NULL;
+ if (sts == DID_OK) {
+@@ -8243,7 +8243,8 @@ static void process_waiting_list(struct ncb *np, int sts)
--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)
+ #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)
{
-- int len = 0, i;
-+ int i;
+ 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
+ */
-- 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");
-+}
+-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;
-- return len;
-+static void zfcp_dbf_outs(char **buf, const char *s1, const char *s2)
-+{
-+ *buf += sprintf(*buf, "%-24s%s\n", s1, s2);
+ 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;
}
--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, ...)
+-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)
{
- va_list arg;
-- int len = 0;
+- 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;
-- 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");
+ 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;
}
--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)
+-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)
{
-- 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");
+- 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;
}
--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)
+-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 zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)DEBUG_DATA(entry);
-- int len = 0;
-+ struct timespec t;
-+ char *p = out_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 (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;
+ 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;
}
-+/**
-+ * 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)
+-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 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;
+- 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;
- 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 (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;
+ }
- 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;
+-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);
-@@ -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;
+-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;
- 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;
+ 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;
+ }
- 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;
+-CLASS_DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
++DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
- case FSF_QTCB_ABORT_FCP_CMND:
-@@ -230,39 +236,54 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
- break;
- }
+ static struct class *osst_sysfs_class;
-- 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);
- }
+@@ -5678,44 +5687,37 @@ static int osst_sysfs_init(void)
--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)
+ static void osst_sysfs_destroy(dev_t dev)
{
- 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);
+- class_device_destroy(osst_sysfs_class, dev);
++ device_destroy(osst_sysfs_class, dev);
+ }
-- 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));
+ 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;
- 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;
+- 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);
+ }
- 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;
+- 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;
-@@ -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;
+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,
+ }
- 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);
- }
+ 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;
-- 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);
+@@ -642,10 +643,11 @@ SYM53C500_show_pio(struct class_device *cdev, char *buf)
}
--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)
+ 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)
{
-- struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
-+ struct zfcp_hba_dbf_record *r = &adapter->hba_dbf_buf;
- unsigned long flags;
+ 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;
- 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);
+@@ -662,7 +664,7 @@ SYM53C500_store_pio(struct class_device *cdev, const char *buf, size_t count)
+ * SCSI HBA device attributes we want to
+ * make available via sysfs.
+ */
+-static struct class_device_attribute SYM53C500_pio_attr = {
++static struct device_attribute SYM53C500_pio_attr = {
+ .attr = {
+ .name = "fast_pio",
+ .mode = (S_IRUGO | S_IWUSR),
+@@ -671,7 +673,7 @@ static struct class_device_attribute SYM53C500_pio_attr = {
+ .store = SYM53C500_store_pio,
+ };
+
+-static struct class_device_attribute *SYM53C500_shost_attrs[] = {
++static struct device_attribute *SYM53C500_shost_attrs[] = {
+ &SYM53C500_pio_attr,
+ NULL,
+ };
+diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c
+index fad6cb5..ce48e2d 100644
+--- a/drivers/scsi/ps3rom.c
++++ b/drivers/scsi/ps3rom.c
+@@ -26,6 +26,7 @@
+ #include <scsi/scsi_dbg.h>
+ #include <scsi/scsi_device.h>
+ #include <scsi/scsi_host.h>
++#include <scsi/scsi_eh.h>
+
+ #include <asm/lv1call.h>
+ #include <asm/ps3stor.h>
+@@ -90,78 +91,6 @@ static int ps3rom_slave_configure(struct scsi_device *scsi_dev)
+ return 0;
}
--static int
--zfcp_hba_dbf_view_response(char *out_buf,
-- struct zfcp_hba_dbf_record_response *rec)
+-/*
+- * copy data from device into scatter/gather buffer
+- */
+-static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf)
-{
-- int len = 0;
+- int k, req_len, act_len, len, active;
+- void *kaddr;
+- struct scatterlist *sgpnt;
+- unsigned int buflen;
-
-- 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);
+- buflen = scsi_bufflen(cmd);
+- if (!buflen)
+- return 0;
-
-- switch (rec->fsf_command) {
-+static void zfcp_hba_dbf_view_response(char **p,
-+ struct zfcp_hba_dbf_record_response *r)
-+{
-+ struct timespec t;
+- 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;
+
-+ 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);
++ len = scsi_sg_copy_from_buffer(cmd,
++ dev->bounce_buf,
++ dev->bounce_size);
+
-+ 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;
++ 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;
+ }
- 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;
+- 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;
- 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;
+ 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,
+ };
- 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;
+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 @@
- 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;
- }
+ #include <linux/module.h>
--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);
+-#include <linux/version.h>
+ #include <linux/types.h>
+ #include <linux/string.h>
+ #include <linux/errno.h>
+@@ -367,10 +366,6 @@
+ #include <asm/sn/io.h>
+ #endif
+
+-#if LINUX_VERSION_CODE < 0x020600
+-#error "Kernels older than 2.6.0 are no longer supported"
+-#endif
-
-- 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)
+ /*
+ * 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..2876908 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)
{
-- 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);
+ return snprintf(buf, PAGE_SIZE, "%s\n", qla2x00_version_str);
}
--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)
+ 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)
{
-- 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;
+- 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];
-- 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);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+@@ -546,9 +548,10 @@ qla2x00_fw_version_show(struct class_device *cdev, char *buf)
+ }
-- 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);
+ 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;
-- return len;
-+ p += sprintf(p, "\n");
-+ return p - out_buf;
+ if (IS_FWI2_CAPABLE(ha))
+@@ -560,40 +563,45 @@ qla2x00_serial_num_show(struct class_device *cdev, char *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)
+ 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)
{
-- 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);
+- 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);
}
-+/**
-+ * 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)
+ 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)
{
- 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;
+- 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]);
+ }
-- _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);
+ 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);
}
-+/**
-+ * 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)
+ 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)
{
- 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;
+- 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: "");
+ }
-- _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 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 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)
+ static ssize_t
+-qla2x00_state_show(struct class_device *cdev, char *buf)
++qla2x00_link_state_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
{
- 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;
+- 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;
- 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);
+ if (atomic_read(&ha->loop_state) == LOOP_DOWN ||
+@@ -639,9 +648,10 @@ qla2x00_state_show(struct class_device *cdev, char *buf)
}
-+/**
-+ * 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)
+ static ssize_t
+-qla2x00_zio_show(struct class_device *cdev, char *buf)
++qla2x00_zio_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
{
- struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
+- 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;
-- _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);
+ switch (ha->zio_mode) {
+@@ -656,9 +666,10 @@ qla2x00_zio_show(struct class_device *cdev, char *buf)
}
-+/**
-+ * 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)
+ 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)
{
- struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
+- 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;
-- _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);
+@@ -682,18 +693,19 @@ qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count)
}
-+/**
-+ * 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)
+ 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)
{
- 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);
+- 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 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)
+ 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)
{
-- 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;
+- 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;
-- 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);
- }
+@@ -709,9 +721,10 @@ qla2x00_zio_timer_store(struct class_device *cdev, const char *buf,
+ }
-- 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");
+ 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;
-- return len;
-+ return p - out_buf;
+ if (ha->beacon_blink_led)
+@@ -722,10 +735,10 @@ qla2x00_beacon_show(struct class_device *cdev, char *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)
+ 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)
{
- 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);
+- 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;
-- 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);
+@@ -753,84 +766,86 @@ qla2x00_beacon_store(struct class_device *cdev, const char *buf,
}
--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)
+ 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)
{
-- _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);
+- 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]);
}
--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)
+ 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)
{
-- _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);
+- 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]);
}
--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)
+ 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)
{
-- 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);
+- 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 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)
+ 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)
{
-- 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;
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
-- if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
-+ if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
- return 0;
+ 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]);
+ }
-- 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);
+-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(link_state, S_IRUGO, qla2x00_link_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);
+
-+ 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);
++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_link_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;
}
--
-- len += sprintf(out_buf + len, "\n");
--
-- return len;
-+ p += sprintf(p, "\n");
-+ return p - out_buf;
- }
+ fc_host_speed(shost) = speed;
+@@ -900,7 +915,8 @@ qla2x00_get_starget_node_name(struct scsi_target *starget)
+ u64 node_name = 0;
- 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];
+ 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;
- /* 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);
+ 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;
- /* 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;
- }
+ 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,
- #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));
+ .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;
+
-+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));
+ 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;
+
-+struct zfcp_hba_dbf_record_qdio {
-+ u32 status;
-+ u32 qdio_error;
-+ u32 siga_error;
-+ u8 sbal_index;
-+ u8 sbal_count;
-+} __attribute__ ((packed));
++ 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..cbef785 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.
+ */
+@@ -38,78 +38,38 @@ qla2xxx_copy_queues(scsi_qla_host_t *ha, void *ptr)
+ }
+
+ static int
+-qla24xx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram,
+- uint32_t cram_size, uint32_t *ext_mem, void **nxt)
++qla24xx_dump_ram(scsi_qla_host_t *ha, uint32_t addr, uint32_t *ram,
++ uint32_t ram_dwords, void **nxt)
+ {
+ int rval;
+- uint32_t cnt, stat, timer, risc_address, ext_mem_cnt;
+- uint16_t mb[4];
++ uint32_t cnt, stat, timer, dwords, idx;
++ uint16_t mb0;
+ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
++ dma_addr_t dump_dma = ha->gid_list_dma;
++ uint32_t *dump = (uint32_t *)ha->gid_list;
+
+ rval = QLA_SUCCESS;
+- risc_address = ext_mem_cnt = 0;
+- memset(mb, 0, sizeof(mb));
++ mb0 = 0;
+
+- /* Code RAM. */
+- risc_address = 0x20000;
+- WRT_REG_WORD(®->mailbox0, MBC_READ_RAM_EXTENDED);
++ WRT_REG_WORD(®->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED);
+ clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+
+- for (cnt = 0; cnt < cram_size / 4 && rval == QLA_SUCCESS;
+- cnt++, risc_address++) {
+- WRT_REG_WORD(®->mailbox1, LSW(risc_address));
+- WRT_REG_WORD(®->mailbox8, MSW(risc_address));
+- RD_REG_WORD(®->mailbox8);
+- WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT);
++ dwords = GID_LIST_SIZE / 4;
++ for (cnt = 0; cnt < ram_dwords && rval == QLA_SUCCESS;
++ cnt += dwords, addr += dwords) {
++ if (cnt + dwords > ram_dwords)
++ dwords = ram_dwords - cnt;
+
+- for (timer = 6000000; timer; timer--) {
+- /* Check for pending interrupts. */
+- stat = RD_REG_DWORD(®->host_status);
+- if (stat & HSRX_RISC_INT) {
+- stat &= 0xff;
++ WRT_REG_WORD(®->mailbox1, LSW(addr));
++ WRT_REG_WORD(®->mailbox8, MSW(addr));
+
+- if (stat == 0x1 || stat == 0x2 ||
+- stat == 0x10 || stat == 0x11) {
+- set_bit(MBX_INTERRUPT,
+- &ha->mbx_cmd_flags);
+-
+- mb[0] = RD_REG_WORD(®->mailbox0);
+- mb[2] = RD_REG_WORD(®->mailbox2);
+- mb[3] = RD_REG_WORD(®->mailbox3);
++ WRT_REG_WORD(®->mailbox2, MSW(dump_dma));
++ WRT_REG_WORD(®->mailbox3, LSW(dump_dma));
++ WRT_REG_WORD(®->mailbox6, MSW(MSD(dump_dma)));
++ WRT_REG_WORD(®->mailbox7, LSW(MSD(dump_dma)));
+
+- WRT_REG_DWORD(®->hccr,
+- HCCRX_CLR_RISC_INT);
+- RD_REG_DWORD(®->hccr);
+- break;
+- }
+-
+- /* Clear this intr; it wasn't a mailbox intr */
+- WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT);
+- RD_REG_DWORD(®->hccr);
+- }
+- udelay(5);
+- }
+-
+- if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
+- rval = mb[0] & MBS_MASK;
+- code_ram[cnt] = htonl((mb[3] << 16) | mb[2]);
+- } else {
+- rval = QLA_FUNCTION_FAILED;
+- }
+- }
+-
+- if (rval == QLA_SUCCESS) {
+- /* External Memory. */
+- risc_address = 0x100000;
+- ext_mem_cnt = ha->fw_memory_size - 0x100000 + 1;
+- WRT_REG_WORD(®->mailbox0, MBC_READ_RAM_EXTENDED);
+- clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+- }
+- for (cnt = 0; cnt < ext_mem_cnt && rval == QLA_SUCCESS;
+- cnt++, risc_address++) {
+- WRT_REG_WORD(®->mailbox1, LSW(risc_address));
+- WRT_REG_WORD(®->mailbox8, MSW(risc_address));
+- RD_REG_WORD(®->mailbox8);
++ WRT_REG_WORD(®->mailbox4, MSW(dwords));
++ WRT_REG_WORD(®->mailbox5, LSW(dwords));
+ WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT);
+
+ for (timer = 6000000; timer; timer--) {
+@@ -123,9 +83,7 @@ qla24xx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram,
+ set_bit(MBX_INTERRUPT,
+ &ha->mbx_cmd_flags);
+
+- mb[0] = RD_REG_WORD(®->mailbox0);
+- mb[2] = RD_REG_WORD(®->mailbox2);
+- mb[3] = RD_REG_WORD(®->mailbox3);
++ mb0 = RD_REG_WORD(®->mailbox0);
+
+ WRT_REG_DWORD(®->hccr,
+ HCCRX_CLR_RISC_INT);
+@@ -141,17 +99,34 @@ qla24xx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram,
+ }
+
+ if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
+- rval = mb[0] & MBS_MASK;
+- ext_mem[cnt] = htonl((mb[3] << 16) | mb[2]);
++ rval = mb0 & MBS_MASK;
++ for (idx = 0; idx < dwords; idx++)
++ ram[cnt + idx] = swab32(dump[idx]);
+ } else {
+ rval = QLA_FUNCTION_FAILED;
+ }
+ }
+
+- *nxt = rval == QLA_SUCCESS ? &ext_mem[cnt]: NULL;
++ *nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL;
+ return rval;
+ }
+
++static int
++qla24xx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram,
++ uint32_t cram_size, void **nxt)
++{
++ int rval;
+
-+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));
++ /* Code RAM. */
++ rval = qla24xx_dump_ram(ha, 0x20000, code_ram, cram_size / 4, nxt);
++ if (rval != QLA_SUCCESS)
++ return rval;
+
-+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));
++ /* External Memory. */
++ return qla24xx_dump_ram(ha, 0x100000, *nxt,
++ ha->fw_memory_size - 0x100000 + 1, nxt);
++}
+
-+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));
+ static uint32_t *
+ qla24xx_read_window(struct device_reg_24xx __iomem *reg, uint32_t iobase,
+ uint32_t count, uint32_t *buf)
+@@ -239,6 +214,90 @@ qla24xx_soft_reset(scsi_qla_host_t *ha)
+ return rval;
+ }
+
++static int
++qla2xxx_dump_ram(scsi_qla_host_t *ha, uint32_t addr, uint16_t *ram,
++ uint16_t ram_words, void **nxt)
++{
++ int rval;
++ uint32_t cnt, stat, timer, words, idx;
++ uint16_t mb0;
++ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
++ dma_addr_t dump_dma = ha->gid_list_dma;
++ uint16_t *dump = (uint16_t *)ha->gid_list;
++
++ rval = QLA_SUCCESS;
++ mb0 = 0;
++
++ WRT_MAILBOX_REG(ha, reg, 0, MBC_DUMP_RISC_RAM_EXTENDED);
++ clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
++
++ words = GID_LIST_SIZE / 2;
++ for (cnt = 0; cnt < ram_words && rval == QLA_SUCCESS;
++ cnt += words, addr += words) {
++ if (cnt + words > ram_words)
++ words = ram_words - cnt;
++
++ WRT_MAILBOX_REG(ha, reg, 1, LSW(addr));
++ WRT_MAILBOX_REG(ha, reg, 8, MSW(addr));
++
++ WRT_MAILBOX_REG(ha, reg, 2, MSW(dump_dma));
++ WRT_MAILBOX_REG(ha, reg, 3, LSW(dump_dma));
++ WRT_MAILBOX_REG(ha, reg, 6, MSW(MSD(dump_dma)));
++ WRT_MAILBOX_REG(ha, reg, 7, LSW(MSD(dump_dma)));
++
++ WRT_MAILBOX_REG(ha, reg, 4, words);
++ WRT_REG_WORD(®->hccr, HCCR_SET_HOST_INT);
++
++ for (timer = 6000000; timer; timer--) {
++ /* Check for pending interrupts. */
++ stat = RD_REG_DWORD(®->u.isp2300.host_status);
++ if (stat & HSR_RISC_INT) {
++ stat &= 0xff;
++
++ if (stat == 0x1 || stat == 0x2) {
++ set_bit(MBX_INTERRUPT,
++ &ha->mbx_cmd_flags);
++
++ mb0 = RD_MAILBOX_REG(ha, reg, 0);
++
++ /* Release mailbox registers. */
++ WRT_REG_WORD(®->semaphore, 0);
++ WRT_REG_WORD(®->hccr,
++ HCCR_CLR_RISC_INT);
++ RD_REG_WORD(®->hccr);
++ break;
++ } else if (stat == 0x10 || stat == 0x11) {
++ set_bit(MBX_INTERRUPT,
++ &ha->mbx_cmd_flags);
++
++ mb0 = RD_MAILBOX_REG(ha, reg, 0);
++
++ WRT_REG_WORD(®->hccr,
++ HCCR_CLR_RISC_INT);
++ RD_REG_WORD(®->hccr);
++ break;
++ }
+
-+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));
++ /* clear this intr; it wasn't a mailbox intr */
++ WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT);
++ RD_REG_WORD(®->hccr);
++ }
++ udelay(5);
++ }
+
-+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));
++ if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
++ rval = mb0 & MBS_MASK;
++ for (idx = 0; idx < words; idx++)
++ ram[cnt + idx] = swab16(dump[idx]);
++ } else {
++ rval = QLA_FUNCTION_FAILED;
++ }
++ }
+
-+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));
++ *nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL;
++ return rval;
++}
+
-+#endif /* ZFCP_DBF_H */
-diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
-index 9e9f6c1..bda8c77 100644
---- a/drivers/s390/scsi/zfcp_def.h
-+++ b/drivers/s390/scsi/zfcp_def.h
-@@ -47,6 +47,7 @@
- #include <asm/qdio.h>
- #include <asm/debug.h>
- #include <asm/ebcdic.h>
-+#include "zfcp_dbf.h"
- #include "zfcp_fsf.h"
+ static inline void
+ qla2xxx_read_window(struct device_reg_2xxx __iomem *reg, uint32_t count,
+ uint16_t *buf)
+@@ -258,19 +317,14 @@ void
+ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
+ {
+ int rval;
+- uint32_t cnt, timer;
+- uint32_t risc_address;
+- uint16_t mb0, mb2;
++ uint32_t cnt;
+- uint32_t stat;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+ uint16_t __iomem *dmp_reg;
+ unsigned long flags;
+ struct qla2300_fw_dump *fw;
+- uint32_t data_ram_cnt;
++ void *nxt;
+
+- risc_address = data_ram_cnt = 0;
+- mb0 = mb2 = 0;
+ flags = 0;
+
+ if (!hardware_locked)
+@@ -388,185 +442,23 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
+ }
+ }
-@@ -262,167 +263,6 @@ struct fcp_logo {
- } __attribute__((packed));
+- if (rval == QLA_SUCCESS) {
+- /* Get RISC SRAM. */
+- risc_address = 0x800;
+- WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_WORD);
+- clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+- }
+- for (cnt = 0; cnt < sizeof(fw->risc_ram) / 2 && rval == QLA_SUCCESS;
+- cnt++, risc_address++) {
+- WRT_MAILBOX_REG(ha, reg, 1, (uint16_t)risc_address);
+- WRT_REG_WORD(®->hccr, HCCR_SET_HOST_INT);
+-
+- for (timer = 6000000; timer; timer--) {
+- /* Check for pending interrupts. */
+- stat = RD_REG_DWORD(®->u.isp2300.host_status);
+- if (stat & HSR_RISC_INT) {
+- stat &= 0xff;
+-
+- if (stat == 0x1 || stat == 0x2) {
+- set_bit(MBX_INTERRUPT,
+- &ha->mbx_cmd_flags);
+-
+- mb0 = RD_MAILBOX_REG(ha, reg, 0);
+- mb2 = RD_MAILBOX_REG(ha, reg, 2);
+-
+- /* Release mailbox registers. */
+- WRT_REG_WORD(®->semaphore, 0);
+- WRT_REG_WORD(®->hccr,
+- HCCR_CLR_RISC_INT);
+- RD_REG_WORD(®->hccr);
+- break;
+- } else if (stat == 0x10 || stat == 0x11) {
+- set_bit(MBX_INTERRUPT,
+- &ha->mbx_cmd_flags);
+-
+- mb0 = RD_MAILBOX_REG(ha, reg, 0);
+- mb2 = RD_MAILBOX_REG(ha, reg, 2);
+-
+- WRT_REG_WORD(®->hccr,
+- HCCR_CLR_RISC_INT);
+- RD_REG_WORD(®->hccr);
+- break;
+- }
+-
+- /* clear this intr; it wasn't a mailbox intr */
+- WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT);
+- RD_REG_WORD(®->hccr);
+- }
+- udelay(5);
+- }
+-
+- if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
+- rval = mb0 & MBS_MASK;
+- fw->risc_ram[cnt] = htons(mb2);
+- } else {
+- rval = QLA_FUNCTION_FAILED;
+- }
+- }
+-
+- if (rval == QLA_SUCCESS) {
+- /* Get stack SRAM. */
+- risc_address = 0x10000;
+- WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_EXTENDED);
+- clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+- }
+- for (cnt = 0; cnt < sizeof(fw->stack_ram) / 2 && rval == QLA_SUCCESS;
+- cnt++, risc_address++) {
+- WRT_MAILBOX_REG(ha, reg, 1, LSW(risc_address));
+- WRT_MAILBOX_REG(ha, reg, 8, MSW(risc_address));
+- WRT_REG_WORD(®->hccr, HCCR_SET_HOST_INT);
+-
+- for (timer = 6000000; timer; timer--) {
+- /* Check for pending interrupts. */
+- stat = RD_REG_DWORD(®->u.isp2300.host_status);
+- if (stat & HSR_RISC_INT) {
+- stat &= 0xff;
+-
+- if (stat == 0x1 || stat == 0x2) {
+- set_bit(MBX_INTERRUPT,
+- &ha->mbx_cmd_flags);
+-
+- mb0 = RD_MAILBOX_REG(ha, reg, 0);
+- mb2 = RD_MAILBOX_REG(ha, reg, 2);
+-
+- /* Release mailbox registers. */
+- WRT_REG_WORD(®->semaphore, 0);
+- WRT_REG_WORD(®->hccr,
+- HCCR_CLR_RISC_INT);
+- RD_REG_WORD(®->hccr);
+- break;
+- } else if (stat == 0x10 || stat == 0x11) {
+- set_bit(MBX_INTERRUPT,
+- &ha->mbx_cmd_flags);
+-
+- mb0 = RD_MAILBOX_REG(ha, reg, 0);
+- mb2 = RD_MAILBOX_REG(ha, reg, 2);
+-
+- WRT_REG_WORD(®->hccr,
+- HCCR_CLR_RISC_INT);
+- RD_REG_WORD(®->hccr);
+- break;
+- }
+-
+- /* clear this intr; it wasn't a mailbox intr */
+- WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT);
+- RD_REG_WORD(®->hccr);
+- }
+- udelay(5);
+- }
+-
+- if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
+- rval = mb0 & MBS_MASK;
+- fw->stack_ram[cnt] = htons(mb2);
+- } else {
+- rval = QLA_FUNCTION_FAILED;
+- }
+- }
+-
+- if (rval == QLA_SUCCESS) {
+- /* Get data SRAM. */
+- risc_address = 0x11000;
+- data_ram_cnt = ha->fw_memory_size - risc_address + 1;
+- WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_EXTENDED);
+- clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+- }
+- for (cnt = 0; cnt < data_ram_cnt && rval == QLA_SUCCESS;
+- cnt++, risc_address++) {
+- WRT_MAILBOX_REG(ha, reg, 1, LSW(risc_address));
+- WRT_MAILBOX_REG(ha, reg, 8, MSW(risc_address));
+- WRT_REG_WORD(®->hccr, HCCR_SET_HOST_INT);
+-
+- for (timer = 6000000; timer; timer--) {
+- /* Check for pending interrupts. */
+- stat = RD_REG_DWORD(®->u.isp2300.host_status);
+- if (stat & HSR_RISC_INT) {
+- stat &= 0xff;
+-
+- if (stat == 0x1 || stat == 0x2) {
+- set_bit(MBX_INTERRUPT,
+- &ha->mbx_cmd_flags);
+-
+- mb0 = RD_MAILBOX_REG(ha, reg, 0);
+- mb2 = RD_MAILBOX_REG(ha, reg, 2);
+-
+- /* Release mailbox registers. */
+- WRT_REG_WORD(®->semaphore, 0);
+- WRT_REG_WORD(®->hccr,
+- HCCR_CLR_RISC_INT);
+- RD_REG_WORD(®->hccr);
+- break;
+- } else if (stat == 0x10 || stat == 0x11) {
+- set_bit(MBX_INTERRUPT,
+- &ha->mbx_cmd_flags);
+-
+- mb0 = RD_MAILBOX_REG(ha, reg, 0);
+- mb2 = RD_MAILBOX_REG(ha, reg, 2);
+-
+- WRT_REG_WORD(®->hccr,
+- HCCR_CLR_RISC_INT);
+- RD_REG_WORD(®->hccr);
+- break;
+- }
++ /* Get RISC SRAM. */
++ if (rval == QLA_SUCCESS)
++ rval = qla2xxx_dump_ram(ha, 0x800, fw->risc_ram,
++ sizeof(fw->risc_ram) / 2, &nxt);
+
+- /* clear this intr; it wasn't a mailbox intr */
+- WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT);
+- RD_REG_WORD(®->hccr);
+- }
+- udelay(5);
+- }
++ /* Get stack SRAM. */
++ if (rval == QLA_SUCCESS)
++ rval = qla2xxx_dump_ram(ha, 0x10000, fw->stack_ram,
++ sizeof(fw->stack_ram) / 2, &nxt);
+
+- if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
+- rval = mb0 & MBS_MASK;
+- fw->data_ram[cnt] = htons(mb2);
+- } else {
+- rval = QLA_FUNCTION_FAILED;
+- }
+- }
++ /* Get data SRAM. */
++ if (rval == QLA_SUCCESS)
++ rval = qla2xxx_dump_ram(ha, 0x11000, fw->data_ram,
++ ha->fw_memory_size - 0x11000 + 1, &nxt);
- /*
-- * DBF stuff
-- */
--#define ZFCP_DBF_TAG_SIZE 4
+ if (rval == QLA_SUCCESS)
+- qla2xxx_copy_queues(ha, &fw->data_ram[cnt]);
++ qla2xxx_copy_queues(ha, nxt);
+
+ if (rval != QLA_SUCCESS) {
+ qla_printk(KERN_WARNING, ha,
+@@ -1010,7 +902,7 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
+ goto qla24xx_fw_dump_failed_0;
+
+ rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
+- fw->ext_mem, &nxt);
++ &nxt);
+ if (rval != QLA_SUCCESS)
+ goto qla24xx_fw_dump_failed_0;
+
+@@ -1318,7 +1210,7 @@ qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
+ goto qla25xx_fw_dump_failed_0;
+
+ rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
+- fw->ext_mem, &nxt);
++ &nxt);
+ if (rval != QLA_SUCCESS)
+ goto qla25xx_fw_dump_failed_0;
+
+@@ -1410,125 +1302,3 @@ qla2x00_dump_buffer(uint8_t * b, uint32_t size)
+ if (cnt % 16)
+ printk("\n");
+ }
-
--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));
+-/**************************************************************************
+- * 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;
-
--/* FIXME: to be inflated when reworking the erp dbf */
--struct zfcp_erp_dbf_record {
-- u8 dummy[16];
--} __attribute__ ((packed));
+- ha = shost_priv(cmd->device->host);
-
--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));
+- 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);
-
--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));
+- if (!sp)
+- return;
-
--struct zfcp_hba_dbf_record_qdio {
-- u32 status;
-- u32 qdio_error;
-- u32 siga_error;
-- u8 sbal_index;
-- u8 sbal_count;
--} __attribute__ ((packed));
+- printk(" sp flags=0x%x\n", sp->flags);
+-}
-
--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));
+-#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;
-
--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));
+- if (strcmp(string, "") != 0)
+- printk("%s\n",string);
-
--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));
+- 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");
-
--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));
+- 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");
-
--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));
+- 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 */
-/*
- * FC-FS stuff
+- * 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
*/
- #define R_A_TOV 10 /* seconds */
-@@ -539,7 +379,7 @@ struct zfcp_rc_entry {
+diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
+index 3750319..299eccf 100644
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -1,6 +1,6 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+@@ -24,7 +24,8 @@
+ #include <linux/workqueue.h>
+ #include <linux/firmware.h>
+ #include <linux/aer.h>
+-#include <asm/semaphore.h>
++#include <linux/mutex.h>
++#include <linux/semaphore.h>
- /* 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)
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_host.h>
+@@ -192,9 +193,6 @@ typedef struct srb {
- #define ZFCP_LOG(level, fmt, args...) \
-@@ -634,7 +474,6 @@ do { \
- ZFCP_STATUS_PORT_NO_SCSI_ID)
+ uint16_t flags;
- /* 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);
+- /* 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;
--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);
+- unsigned int os_target_id;
-
--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 *);
+ 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
- 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 *);
+ #define NS_N_PORT_TYPE 0x01
+@@ -2063,7 +2060,8 @@ struct isp_operations {
+ void (*disable_intrs) (struct scsi_qla_host *);
- 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);
+ 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 {
-- 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");
+ #define WATCH_INTERVAL 1 /* number of seconds */
- /* 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);
- }
++/* 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;
-@@ -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);
- }
+ atomic_t loop_state;
+@@ -2204,6 +2243,7 @@ typedef struct scsi_qla_host {
+ #define DFLG_NO_CABLE BIT_4
- 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;
+ #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)
-- debug_text_event(adapter->erp_dbf, 5, "a_ro");
- ZFCP_LOG_DEBUG("reopen adapter %s\n",
- zfcp_get_busid_by_adapter(adapter));
+ #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)
-@@ -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);
+ #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))
- 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;
+ #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;
- 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);
++ struct list_head work_list;
++
+ /* Fibre Channel Device List. */
+ struct list_head fcports;
- return retval;
- }
+@@ -2423,8 +2470,6 @@ typedef struct scsi_qla_host {
+ #define MBX_TIMEDOUT BIT_5
+ #define MBX_ACCESS_TIMEDOUT BIT_6
--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;
+- 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;
- retval = zfcp_erp_adapter_reopen(adapter,
- ZFCP_STATUS_COMMON_RUNNING |
- ZFCP_STATUS_COMMON_ERP_FAILED |
-- clear_mask);
-+ clear_mask, id, ref);
++ 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];
- return retval;
- }
++ 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;
--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);
+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..cf19451 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 {
- return retval;
- }
+ uint16_t timeout; /* Command timeout. */
--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;
+- uint8_t lun[8]; /* FCP LUN (BE). */
++ struct scsi_lun lun; /* FCP LUN (BE). */
- retval = zfcp_erp_unit_reopen(unit,
- ZFCP_STATUS_COMMON_RUNNING |
- ZFCP_STATUS_COMMON_ERP_FAILED |
-- clear_mask);
-+ clear_mask, id, ref);
+ 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
+@@ -1024,22 +1036,6 @@ struct mid_db_entry_24xx {
+ uint8_t reserved_1;
+ };
- 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;
+- /*
+- * Virtual Fabric ID type definition.
+- */
+-typedef struct vf_id {
+- uint16_t id : 12;
+- uint16_t priority : 4;
+-} vf_id_t;
-
-- debug_text_event(adapter->erp_dbf, 5, "pf_ro");
-- debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+-/*
+- * Virtual Fabric HopCt type definition.
+- */
+-typedef struct vf_hopct {
+- uint16_t reserved : 8;
+- uint16_t hopct : 8;
+-} vf_hopct_t;
+-
+ /*
+ * Virtual Port Control IOCB
+ */
+@@ -1070,10 +1066,10 @@ struct vp_ctrl_entry_24xx {
- 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;
- }
+ uint8_t vp_idx_map[16];
+ uint16_t flags;
+- struct vf_id id;
++ uint16_t id;
+ uint16_t reserved_4;
+- struct vf_hopct hopct;
+- uint8_t reserved_5[8];
++ uint16_t hopct;
++ uint8_t reserved_5[24];
+ };
- retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED,
-- port->adapter, port, NULL);
-+ port->adapter, port, NULL, id, ref);
+ /*
+@@ -1120,9 +1116,9 @@ struct vp_config_entry_24xx {
+ uint16_t reserved_vp2;
+ uint8_t port_name_idx2[WWN_SIZE];
+ uint8_t node_name_idx2[WWN_SIZE];
+- struct vf_id id;
++ uint16_t id;
+ uint16_t reserved_4;
+- struct vf_hopct hopct;
++ uint16_t hopct;
+ uint8_t reserved_5;
+ };
- 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
+@@ -1174,4 +1170,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..f882706 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.
*/
--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);
+@@ -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 *);
-@@ -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;
+-extern void qla2x00_restart_queues(scsi_qla_host_t *, uint8_t);
-
-- 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;
- }
+-extern void qla2x00_rescan_fcports(scsi_qla_host_t *);
+ extern void qla2x00_update_fcports(scsi_qla_host_t *);
- retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT,
-- port->adapter, port, NULL);
-+ port->adapter, port, NULL, id, ref);
+ 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 *);
- 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.
++extern void qla84xx_put_chip(struct scsi_qla_host *);
++
+ /*
+ * Global Data in qla_os.c source file.
*/
--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)
+@@ -67,6 +66,10 @@ extern int num_hosts;
- 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);
+ 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);
-@@ -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;
+ /*
+ * Global Functions in qla_mid.c source file.
+@@ -151,10 +154,11 @@ qla2x00_issue_iocb(scsi_qla_host_t *, void *, dma_addr_t, size_t);
+ extern int
+ qla2x00_abort_command(scsi_qla_host_t *, srb_t *);
-- 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;
- }
+-#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);
- 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)
+ extern int
+ qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *,
+@@ -220,7 +224,8 @@ qla24xx_get_isp_stats(scsi_qla_host_t *, struct link_statistics *,
+ dma_addr_t);
- 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);
+ 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);
-@@ -687,19 +673,43 @@ zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask)
+ extern int
+ qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
+@@ -246,6 +251,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.
*/
- 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);
- }
+@@ -298,6 +305,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 *);
-+/* 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;
-+}
++extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t,
++ uint16_t, uint16_t);
+
-+/* 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;
-+}
++extern void qla2xxx_get_flash_info(scsi_qla_host_t *);
+
- /**
- * zfcp_erp_adapter_unblock - mark adapter as unblocked, allow scsi requests
+ /*
+ * Global Function Prototypes in qla_dbg.c source file.
*/
- 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);
- }
+@@ -307,7 +319,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 *);
/*
-@@ -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);
- }
-
+ * Global Function Prototypes in qla_gs.c source file.
+@@ -332,8 +343,8 @@ extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *);
/*
-@@ -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;
+ * 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..4cb80b4 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);
-
-- 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;
+-static inline struct sns_cmd_pkt *
+-qla2x00_prep_sns_cmd(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
-
-- 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 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);
+@@ -1589,8 +1583,8 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
+ eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
+ eiter->len = __constant_cpu_to_be16(4 + 4);
+ max_frame_size = IS_FWI2_CAPABLE(ha) ?
+- (uint32_t) icb24->frame_payload_size:
+- (uint32_t) ha->init_cb->frame_payload_size;
++ le16_to_cpu(icb24->frame_payload_size):
++ le16_to_cpu(ha->init_cb->frame_payload_size);
+ eiter->a.max_frame_size = cpu_to_be32(max_frame_size);
+ size += 4 + 4;
- static void
-@@ -783,11 +781,9 @@ zfcp_erp_action_ready(struct zfcp_erp_action *erp_action)
- {
- struct zfcp_adapter *adapter = erp_action->adapter;
+@@ -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..bbbc5a6 100644
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -1,6 +1,6 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+@@ -15,14 +15,6 @@
+ #include <asm/prom.h>
+ #endif
-- debug_text_event(adapter->erp_dbf, 4, "a_ar");
-- debug_event(adapter->erp_dbf, 4, &erp_action->action, sizeof (int));
+-/* 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
-
- 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");
-+ }
- }
+ * QLogic ISP2x00 Hardware Support Function Prototypes.
+ */
+@@ -45,6 +37,9 @@ static int qla2x00_restart_isp(scsi_qla_host_t *);
- /**
-@@ -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));
+ 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);
-@@ -939,10 +922,6 @@ static void
- zfcp_erp_memwait_handler(unsigned long data)
+@@ -500,6 +504,7 @@ qla2x00_reset_chip(scsi_qla_host_t *ha)
+ static inline void
+ qla24xx_reset_risc(scsi_qla_host_t *ha)
{
- 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));
++ 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;
- 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));
+ /* 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));
- 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)
+ 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)
{
-- 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");
- }
+ 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];
- return (retval < 0);
-@@ -1027,6 +995,7 @@ zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
+ rval = QLA_SUCCESS;
- atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status);
- up(&adapter->erp_ready_sem);
-+ zfcp_rec_dbf_event_thread(2, adapter, 1);
+@@ -1275,12 +1286,34 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
+ ha->host_no));
- 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);
+ 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));
-- debug_text_event(adapter->erp_dbf, 5, "a_thki_ok");
--
- return retval;
- }
+@@ -1294,7 +1327,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
+ rval = QLA_FUNCTION_FAILED;
-@@ -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);
+ 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);
- 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);
- }
+ 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);
- 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);
+ DEBUG(printk("scsi(%ld): fw_state=%x curr time=%lx.\n",
+- ha->host_no, fw_state, jiffies));
++ ha->host_no, state[0], jiffies));
- 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;
- }
+ 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");
-@@ -1176,20 +1141,17 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
- element was timed out.
++ if (chksum)
++ qla2xxx_hw_event_log(ha, HW_EVENT_NVRAM_CHKSUM_ERR, 0,
++ MSW(chksum), LSW(chksum));
++
+ /*
+ * Set default initialization control block.
*/
- 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;
+@@ -2165,20 +2202,6 @@ cleanup_allocation:
}
-@@ -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)
+ 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)
{
-- struct zfcp_adapter *adapter = erp_action->adapter;
+ #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);
-
- 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;
+- if (rport->scsi_target_id != -1 &&
+- rport->scsi_target_id < ha->host->max_id)
+- fcport->os_target_id = rport->scsi_target_id;
}
-@@ -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;
+ /*
+@@ -2434,7 +2453,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
- 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;
+ 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)
-- 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");
+ /* 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)
}
- /*
-@@ -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)
+-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)
{
-- zfcp_erp_modify_port_status(port,
-+ zfcp_erp_modify_port_status(port, id, ref,
- ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
+ fc_port_t *fcport;
+@@ -3643,7 +3645,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
+ if (le16_to_cpu(nv->login_timeout) < 4)
+ nv->login_timeout = __constant_cpu_to_le16(4);
+ ha->login_timeout = le16_to_cpu(nv->login_timeout);
+- icb->login_timeout = cpu_to_le16(nv->login_timeout);
++ icb->login_timeout = nv->login_timeout;
- 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));
- }
+ /* Set minimum RATOV to 100 tenths of a second. */
+ ha->r_a_tov = 100;
+@@ -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 @@
/*
-@@ -1393,17 +1336,14 @@ zfcp_erp_port_failed(struct zfcp_port *port)
+ * 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.
*/
- 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));
- }
+-static __inline__ uint16_t qla2x00_debounce_register(volatile uint16_t __iomem *);
/*
-@@ -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;
+ * qla2x00_debounce_register
+ * Debounce register.
+@@ -32,94 +31,12 @@ qla2x00_debounce_register(volatile uint16_t __iomem *addr)
+ return (first);
+ }
-- 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));
+-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);
-
- 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));
+-/**
+- * 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;
-
- 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));
+- 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;
-
- 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));
+- normalized++;
+- }
+- return (normalized);
+-}
-
- 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)
+-static __inline__ void qla2x00_poll(scsi_qla_host_t *);
+ static inline void
+ qla2x00_poll(scsi_qla_host_t *ha)
{
-- debug_text_event(adapter->erp_dbf, 5, "a_stct");
+ 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;
-
- 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));
+- qla2x00_get_firmware_state(ha, &fw_state);
+-}
-
- /* 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;
+-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);
}
--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)
+-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)
{
- 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);
+@@ -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 @@
/*
-@@ -1764,29 +1687,27 @@ zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter,
- * purpose: sets the port and all underlying devices to ERP_FAILED
+ * 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.
*/
--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;
+@@ -11,9 +11,6 @@
- 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);
+ #include <scsi/scsi_tcq.h>
- /* 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);
- }
+-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..5d9a64a 100644
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -1,6 +1,6 @@
/*
-@@ -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
+ * 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.
*/
--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);
+@@ -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);
}
-- 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);
- }
+- spin_unlock_irqrestore(&ha->hardware_lock, flags);
++ spin_unlock(&ha->hardware_lock);
- /*
-@@ -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;
+ 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;
- 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);
+- 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);
- return retval;
- }
+ 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;
--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;
+ /* 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]);
- 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);
++ qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
+ ha->isp_ops->fw_dump(ha, 1);
- 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;
+ 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");
- 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);
++ qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
+ set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+ break;
- 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);
+@@ -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");
-- 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");
++ qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
+ set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+ break;
- 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");
+@@ -408,8 +409,10 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ }
- /*
- * put buffers into response queue,
-@@ -2077,11 +1993,9 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
- /* NOP */
+ set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
++ set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
- 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");
+ ha->flags.management_server_logged_in = 0;
++ qla2x00_post_aen_work(ha, FCH_EVT_LIP, mb[1]);
+ break;
- 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;
+ case MBA_LOOP_UP: /* Loop Up Event */
+@@ -429,12 +432,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);
+@@ -450,8 +455,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+
+ ha->flags.management_server_logged_in = 0;
+ 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 +479,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 */
+@@ -505,6 +510,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
}
-- debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok");
- ZFCP_LOG_DEBUG("Xchange underway\n");
+ set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
++ set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
+
+ ha->flags.gpsc_supported = 1;
+ ha->flags.management_server_logged_in = 0;
+@@ -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;
++ }
++ }
++ }
++ }
/*
-@@ -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)
+ * 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;
- 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");
+ 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;
++ }
++ }
++ }
++ }
- 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;
+ 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)
- switch (erp_action->step) {
+ 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;
-@@ -2298,11 +2210,6 @@ zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
+ /* 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;
}
-- 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;
+ 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)
}
-@@ -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));
+ /**
+- * 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;
-
- return retval;
- }
+- 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;
-@@ -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;
+- 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;
- }
-@@ -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;
++ 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);
}
-- 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));
+- spin_unlock_irqrestore(&ha->hardware_lock, flags);
++ spin_unlock(&ha->hardware_lock);
- 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;
+ 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;
+ }
- 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)
+-/**
+- * 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)
{
- int retval;
-- struct zfcp_adapter *adapter = erp_action->adapter;
-- struct zfcp_port *port = erp_action->port;
+ scsi_qla_host_t *ha;
+ struct device_reg_24xx __iomem *reg;
+- unsigned long flags;
- 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;
+ ha = dev_id;
+ reg = &ha->iobase->isp24;
- 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;
+- spin_lock_irqsave(&ha->hardware_lock, flags);
++ spin_lock(&ha->hardware_lock);
- switch (erp_action->step) {
+ qla24xx_process_response_queue(ha);
+-
+ WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT);
-@@ -2797,10 +2656,6 @@ zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action)
- break;
- }
+- spin_unlock_irqrestore(&ha->hardware_lock, flags);
++ spin_unlock(&ha->hardware_lock);
-- 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;
+ 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;
-@@ -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;
+- 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;
- 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;
++ 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);
- 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;
+ 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);
- 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)
+ 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 retval = 1;
-+ int retval = 1, need = want;
- struct zfcp_erp_action *erp_action = NULL;
-- int stronger_action = 0;
- u32 status = 0;
+ int ret;
+ device_reg_t __iomem *reg = ha->iobase;
+- unsigned long flags;
- /*
-@@ -2944,17 +2773,11 @@ zfcp_erp_action_enqueue(int action,
- &adapter->status))
- return -EIO;
+ /* 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;
-- 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 !!! */
+ 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:
- 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 !!! */
+- if (!IS_QLA24XX(ha) && !IS_QLA2532(ha))
++ if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha))
+ goto skip_msi;
- 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;
+ ret = pci_enable_msi(ha->pdev);
+@@ -1882,7 +1863,7 @@ skip_msi:
+ clear_risc_ints:
- 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;
+ 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);
- /* 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));
+ fail:
+diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
+index bb10358..2100604 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,
}
- /* 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) {
+ mcp->in_mb = MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
- case ZFCP_ERP_ACTION_REOPEN_UNIT:
- zfcp_unit_get(unit);
-@@ -3077,13 +2879,11 @@ zfcp_erp_action_enqueue(int action,
- break;
+@@ -367,7 +367,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr)
+ }
}
-- 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;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
- ++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;
- }
+@@ -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);
-@@ -3108,9 +2911,9 @@ zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
- erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
+ /* 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);
-- 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);
+@@ -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;
+
- 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;
++ qla2xxx_hw_event_log(ha, HW_EVENT_ISP_ERR, 0,
++ LSW(RD_REG_DWORD(®->hccr)),
++ LSW(RD_REG_DWORD(®->istatus)));
++ }
+ }
-- 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;
+ 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;
+ }
-- 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)
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
- static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit)
+@@ -673,9 +681,9 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
+ * Context:
+ * Kernel context.
+ */
+-int
+-qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr,
+- size_t size)
++static int
++qla2x00_issue_iocb_timeout(scsi_qla_host_t *ha, void *buffer,
++ dma_addr_t phys_addr, size_t size, uint32_t tov)
{
-- 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);
+ 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;
}
- 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);
++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);
+
+@@ -768,7 +784,6 @@ qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp)
+ DEBUG2_3_11(printk("qla2x00_abort_command(%ld): failed=%x.\n",
+ ha->host_no, rval));
+ } else {
+- sp->flags |= SRB_ABORT_PENDING;
+ DEBUG11(printk("qla2x00_abort_command(%ld): done.\n",
+ ha->host_no));
+ }
+@@ -776,36 +791,20 @@ qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp)
+ return rval;
}
- static void zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action)
+-#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)
{
-- struct zfcp_adapter *adapter = erp_action->adapter;
+- int rval;
++ int rval, rval2;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+ scsi_qla_host_t *ha;
+
+- if (fcport == NULL)
+- return 0;
-
-- 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);
- }
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
--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;
++ 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 +813,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;
-- 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);
- }
+ 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));
++ }
--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);
- }
+- /* 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;
++}
--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;
++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));
+ }
-- 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);
+ return rval;
}
+-#endif
--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);
- }
+ /*
+ * qla2x00_get_adapter_id
+@@ -871,7 +913,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 +970,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);
--void
--zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
-+void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, u8 id,
-+ void *ref)
+@@ -995,7 +1037,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 +1215,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)
{
- 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;
+ int rval;
+ mbx_cmd_t mc;
+@@ -1184,13 +1226,15 @@ qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr)
-- 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);
- }
+ 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);
--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;
+- /* 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];
-- 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;
+ if (rval != QLA_SUCCESS) {
+ /*EMPTY*/
+@@ -1246,7 +1290,7 @@ qla2x00_get_port_name(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t *name,
}
- 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;
+ 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);
-- 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;
+@@ -1318,7 +1362,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);
- /******************************** 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 *);
+@@ -1424,7 +1468,7 @@ qla24xx_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
+ lg->port_id[0] = al_pa;
+ lg->port_id[1] = area;
+ lg->port_id[2] = domain;
+- lg->vp_index = cpu_to_le16(ha->vp_idx);
++ lg->vp_index = ha->vp_idx;
+ rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0);
+ if (rval != QLA_SUCCESS) {
+ DEBUG2_3_11(printk("%s(%ld): failed to issue Login IOCB "
+@@ -1679,7 +1723,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
+ lg->port_id[0] = al_pa;
+ lg->port_id[1] = area;
+ lg->port_id[2] = domain;
+- lg->vp_index = cpu_to_le16(ha->vp_idx);
++ lg->vp_index = ha->vp_idx;
+ rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0);
+ if (rval != QLA_SUCCESS) {
+ DEBUG2_3_11(printk("%s(%ld): failed to issue Logout IOCB "
+@@ -1743,7 +1787,7 @@ qla2x00_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
+ }
- 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);
+ mcp->in_mb = MBX_1|MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
- extern int zfcp_test_link(struct zfcp_port *);
+@@ -1791,7 +1835,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);
--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 *);
+@@ -1852,7 +1896,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);
- /******************************** 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 *);
+@@ -1896,7 +1940,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);
-@@ -284,37 +284,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
- goto skip_protstatus;
+@@ -2036,7 +2080,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);
-- /* 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) {
+@@ -2082,7 +2126,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);
-@@ -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;
+@@ -2165,7 +2209,6 @@ qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp)
+ rval = QLA_FUNCTION_FAILED;
+ } else {
+ DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
+- sp->flags |= SRB_ABORT_PENDING;
+ }
-@@ -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;
+ dma_pool_free(ha->s_dma_pool, abt, abt_dma);
+@@ -2180,17 +2223,15 @@ struct tsk_mgmt_cmd {
+ } p;
+ };
-@@ -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;
+-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;
- 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;
+- if (fcport == NULL)
+- return 0;
+-
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
-@@ -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;
+ ha = fcport->ha;
+@@ -2207,47 +2248,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));
++ }
-@@ -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;
+ 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;
}
-@@ -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;
+ /* 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));
+ }
-@@ -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);
+-atarget_done:
+ dma_pool_free(pha->s_dma_pool, tsk, tsk_dma);
- out:
-- zfcp_erp_adapter_failed(adapter);
-+ zfcp_erp_adapter_failed(adapter, id, fsf_req);
+ return rval;
}
- /*
-@@ -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;
++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
- 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;
+ int
+@@ -2304,7 +2359,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);
- 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;
+@@ -2372,7 +2427,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 +2456,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 +2496,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 +2532,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 +2580,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);
-@@ -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;
+@@ -2559,7 +2614,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);
- case FSF_STATUS_READ_NOTIFICATION_LOST:
-@@ -998,13 +967,13 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
+@@ -2587,12 +2642,11 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *ha,
+ struct vp_rpt_id_entry_24xx *rptid_entry)
+ {
+ uint8_t vp_idx;
++ uint16_t stat = le16_to_cpu(rptid_entry->vp_idx);
+ scsi_qla_host_t *vha;
- 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;
+ if (rptid_entry->entry_status != 0)
+ return;
+- if (rptid_entry->entry_status != __constant_cpu_to_le16(CS_COMPLETE))
+- return;
- 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;
+ if (rptid_entry->format == 0) {
+ DEBUG15(printk("%s:format 0 : scsi(%ld) number of VPs setup %d,"
+@@ -2602,17 +2656,17 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *ha,
+ rptid_entry->port_id[2], rptid_entry->port_id[1],
+ rptid_entry->port_id[0]));
+ } else if (rptid_entry->format == 1) {
+- vp_idx = LSB(rptid_entry->vp_idx);
++ vp_idx = LSB(stat);
+ DEBUG15(printk("%s:format 1: scsi(%ld): VP[%d] enabled "
+ "- status %d - "
+ "with port id %02x%02x%02x\n",__func__,ha->host_no,
+- vp_idx, MSB(rptid_entry->vp_idx),
++ vp_idx, MSB(stat),
+ rptid_entry->port_id[2], rptid_entry->port_id[1],
+ rptid_entry->port_id[0]));
+ if (vp_idx == 0)
+ return;
- case FSF_STATUS_READ_CFDC_HARDENED:
-@@ -1025,7 +994,6 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
- break;
+- if (MSB(rptid_entry->vp_idx) == 1)
++ if (MSB(stat) == 1)
+ return;
- 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);
- }
+ list_for_each_entry(vha, &ha->vp_list, vp_list)
+@@ -2877,7 +2931,7 @@ qla2x00_dump_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t addr,
}
- 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;
+ mcp->in_mb = MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
- 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;
+@@ -2890,3 +2944,104 @@ qla2x00_dump_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t addr,
- 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;
+ 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;
++
++ do {
++ retry = 0;
++ 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"
-@@ -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;
+@@ -28,8 +16,6 @@
+ #include <scsi/scsicam.h>
+ #include <linux/delay.h>
+
+-void qla2x00_vp_stop_timer(scsi_qla_host_t *);
+-
+ void
+ qla2x00_vp_stop_timer(scsi_qla_host_t *vha)
+ {
+@@ -268,9 +254,17 @@ qla2x00_vp_abort_isp(scsi_qla_host_t *vha)
+ static int
+ qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
+ {
++ scsi_qla_host_t *ha = vha->parent;
++
+ if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) {
+ /* VP acquired. complete port configuration */
+- qla24xx_configure_vp(vha);
++ if (atomic_read(&ha->loop_state) == LOOP_READY) {
++ qla24xx_configure_vp(vha);
++ } else {
++ set_bit(VP_IDX_ACQUIRED, &vha->vp_flags);
++ set_bit(VP_DPC_NEEDED, &ha->dpc_flags);
++ }
++
+ return 0;
}
- 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;
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index 3c1b433..3223fd1 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;
-@@ -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;
+-/*
+- * Ioctl related information.
+- */
+ int num_hosts;
+ int ql2xlogintimeout = 20;
+ module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
+@@ -70,7 +67,7 @@ static void qla2x00_free_device(scsi_qla_host_t *);
-@@ -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;
+ static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha);
-@@ -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;
- }
+-int ql2xfdmienable;
++int ql2xfdmienable=1;
+ module_param(ql2xfdmienable, int, S_IRUGO|S_IRUSR);
+ MODULE_PARM_DESC(ql2xfdmienable,
+ "Enables FDMI registratons "
+@@ -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 *);
-@@ -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;
+ 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 = {
- 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;
+ .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,
-@@ -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;
+@@ -148,6 +146,7 @@ struct scsi_host_template qla24xx_driver_template = {
- atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
- &adapter->status);
+ .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,
-- 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));
- }
+@@ -253,9 +252,9 @@ qla24xx_pci_info_str(struct scsi_qla_host *ha, char *str)
+
+ strcpy(str, "PCIe (");
+ if (lspeed == 1)
+- strcat(str, "2.5Gb/s ");
++ strcat(str, "2.5GT/s ");
+ else if (lspeed == 2)
+- strcat(str, "5.0Gb/s ");
++ strcat(str, "5.0GT/s ");
+ else
+ strcat(str, "<unknown> ");
+ snprintf(lwstr, sizeof(lwstr), "x%d)", lwidth);
+@@ -340,6 +339,8 @@ qla24xx_fw_version_str(struct scsi_qla_host *ha, char *str)
+ strcat(str, "[T10 CRC] ");
+ if (ha->fw_attributes & BIT_5)
+ strcat(str, "[VI] ");
++ if (ha->fw_attributes & BIT_10)
++ strcat(str, "[84XX] ");
+ if (ha->fw_attributes & BIT_13)
+ strcat(str, "[Experimental]");
+ return str;
+@@ -570,8 +571,6 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *ha)
+ else
+ return_status = QLA_FUNCTION_FAILED;
+
+- DEBUG2(printk("%s return_status=%d\n",__func__,return_status));
+-
+ return (return_status);
}
-@@ -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;
+@@ -685,7 +684,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
-@@ -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;
+ DEBUG2(printk("%s(%ld): aborting sp %p from RISC. pid=%ld.\n",
+ __func__, ha->host_no, sp, serial));
+- DEBUG3(qla2x00_print_scsi_cmd(cmd));
- 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;
+ 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;
}
- 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;
++ 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;
+ }
-@@ -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;
++static char *reset_errors[] = {
++ "HBA not online",
++ "HBA not ready",
++ "Task management failed",
++ "Waiting for command completions",
++};
-@@ -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;
- }
+-/**************************************************************************
+-* 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;
-@@ -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;
+ qla2x00_block_error_handler(cmd);
-@@ -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;
+- id = cmd->device->id;
+- lun = cmd->device->lun;
+- serial = cmd->serial_number;
+-
+ if (!fcport)
+- return ret;
++ return FAILED;
-@@ -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;
+- 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;
+
-+ /* 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;
++ 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;
++}
- 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;
- }
+- 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);
-@@ -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;
+- /* 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);
+ }
-@@ -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;
+-/**************************************************************************
+-* 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);
-@@ -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;
+- /*
+- * 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);
+ }
-@@ -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;
+-
+ /**************************************************************************
+ * qla2xxx_eh_bus_reset
+ *
+@@ -953,7 +883,8 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
+ goto eh_bus_reset_done;
-@@ -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);
- }
- }
+ /* 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;
-@@ -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;
- }
+ eh_bus_reset_done:
+@@ -1024,7 +955,8 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
+ clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
-@@ -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;
+ /* 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;
-@@ -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;
+ if (ha->parent)
+@@ -1080,7 +1012,7 @@ qla2x00_loop_reset(scsi_qla_host_t *ha)
+ if (fcport->port_type != FCT_TARGET)
+ continue;
-@@ -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));
+- 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;
-@@ -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;
+@@ -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);
-@@ -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;
+ set_bit(0, (unsigned long *) ha->vp_idx_map);
-@@ -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;
+@@ -1819,6 +1746,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
-@@ -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;
+ qla2x00_dfs_remove(ha);
-@@ -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;
++ qla84xx_put_chip(ha);
++
+ qla2x00_free_sysfs_attr(ha);
-@@ -3951,8 +3764,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
- break;
- }
+ fc_remove_host(ha->host);
+@@ -2206,6 +2135,97 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
+ kfree(ha->nvram);
+ }
+
++static 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;
++}
++
++static 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;
}
-- 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;
++ qla2x00_do_work(ha);
++
+ if (test_and_clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) {
-@@ -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;
+ 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);
-@@ -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;
+- 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)))) {
+
+@@ -2357,7 +2373,7 @@ qla2x00_do_dpc(void *data)
+ } else {
+ fcport->login_retry = 0;
+ }
+- if (fcport->login_retry == 0)
++ if (fcport->login_retry == 0 && status != QLA_SUCCESS)
+ fcport->loop_id = FC_NO_LOOP_ID;
+ }
+ if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))
+@@ -2367,19 +2383,6 @@ qla2x00_do_dpc(void *data)
+ ha->host_no));
}
- 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;
+- if ((test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags)) &&
+- atomic_read(&ha->loop_state) != LOOP_DOWN) {
-
-- 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;
+- 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)) {
- 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);
+ DEBUG(printk("scsi(%ld): qla2x00_loop_resync()\n",
+@@ -2397,18 +2400,6 @@ qla2x00_do_dpc(void *data)
+ ha->host_no));
+ }
-- dbg_tmp[0] = (unsigned long) sbale[0].addr;
-- dbg_tmp[1] = (u64) retval;
-- debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16);
+- if (test_and_clear_bit(FCPORT_RESCAN_NEEDED, &ha->dpc_flags)) {
-
- 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);
+- 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));
+@@ -2607,13 +2599,15 @@ qla2x00_timer(scsi_qla_host_t *ha)
+ start_dpc++;
}
- 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);
++ /* Process any deferred work. */
++ if (!list_empty(&ha->work_list))
++ start_dpc++;
++
+ /* 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 +2659,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 +2809,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 */
-
- spin_lock_irqsave(&adapter->req_list_lock, flags);
- fsf_req = zfcp_reqlist_find(adapter, req_id);
+-#define USE_ABORT_TGT 1 /* Use Abort Target mbx cmd */
+-
+ #define MAX_RETRIES_OF_ISP_ABORT 5
-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;
+ /* Max time to wait for the loop to be in LOOP_READY state */
+ #define MAX_LOOP_TIMEOUT (60 * 5)
- 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;
+-/*
+- * 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
--zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
-+static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
+-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 retval;
-- struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;
-+ struct zfcp_unit *unit = scpnt->device->hostdata;
+- 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;
- if (!unit) {
-- ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n");
-- retval = SUCCESS;
-- goto out;
-+ WARN_ON(1);
-+ return SUCCESS;
+- 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;
}
-- 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 */
+- 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 {
-- ZFCP_LOG_DEBUG("unit reset succeeded (unit=%p)\n",
-- unit);
-- /* avoid 'target reset' */
-- retval = SUCCESS;
-- goto out;
+- rest_addr = 0x1fff;
+- sec_mask = 0x7e000;
- }
-+static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt)
-+{
-+ int retval;
-+ struct zfcp_unit *unit = scpnt->device->hostdata;
++ if (flash_id == 0x8e)
++ ha->fdt_block_size = FLASH_BLK_SIZE_64K;
++ else
++ ha->fdt_block_size = FLASH_BLK_SIZE_32K;
+
-+ if (!unit) {
-+ WARN_ON(1);
-+ return SUCCESS;
+ 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;
}
- 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);
++ 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. */
- 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
++ 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);
- retval = 0;
+ 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,
-- 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;
- }
+ /* 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;
+ }
-- 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;
+- /* 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));
}
-- 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
+- /* 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);
- retval = 0;
+ if (optrom)
+ dma_free_coherent(&ha->pdev->dev,
+@@ -2221,3 +2304,107 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
-- 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;
- }
+ 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..afeae2b 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-k2"
-- 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;
- }
+ #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
-- 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;
- }
+ 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);
-- zfcp_erp_modify_unit_status(unit, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
-- zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED);
-+ zfcp_erp_modify_unit_status(unit, 46, NULL,
-+ ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
-+ zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, 97, NULL);
- zfcp_erp_wait(unit->port->adapter);
- out:
- up(&zfcp_data.config_sema);
-diff --git a/drivers/s390/sysinfo.c b/drivers/s390/sysinfo.c
-index 291ff62..c3e4ab0 100644
---- a/drivers/s390/sysinfo.c
-+++ b/drivers/s390/sysinfo.c
-@@ -11,111 +11,13 @@
- #include <linux/init.h>
- #include <linux/delay.h>
- #include <asm/ebcdic.h>
-+#include <asm/sysinfo.h>
+ 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();
- /* Sigh, math-emu. Don't ask. */
- #include <asm/sfp-util.h>
- #include <math-emu/soft-fp.h>
- #include <math-emu/single.h>
+@@ -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;
--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];
--};
+- /* 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;
-
--static inline int stsi(void *sysinfo, int fc, int sel1, int sel2)
+- 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)
-{
-- register int r0 asm("0") = (fc << 28) | sel1;
-- register int r1 asm("1") = sel2;
+- struct srb *srb;
-
-- 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;
+- 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);
+- }
-}
-
- 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;
- }
+-/**
+ * 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;
-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 */
+- 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;
+ }
- /* 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() */
+@@ -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;
+- }
- /* 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 = {
- };
+ 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,
- /* 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];
+ 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;
+
- 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
++ 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;
}
- tw_dev = (TW_Device_Extension *)host->hostdata;
-- memset(tw_dev, 0, sizeof(TW_Device_Extension));
+- /* Send marker. */
+- ha->marker_needed = 1;
-
- /* 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() */
+- /*
+- * 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;
+ }
- /* 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() */
++ /* 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:
+ }
- /* 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 = {
+ /**
++ * 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];
};
- /* Host attributes initializer */
--static struct class_device_attribute *tw_host_attrs[] = {
-+static struct device_attribute *tw_host_attrs[] = {
- &tw_host_stats_attr,
- NULL,
+ struct raid_component {
+ struct list_head node;
+- struct class_device cdev;
++ struct device dev;
+ int num;
};
-@@ -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);
+@@ -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;
}
-@@ -2294,8 +2287,6 @@ static int __devinit tw_probe(struct pci_dev *pdev, const struct pci_device_id *
+ 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);
}
- tw_dev = (TW_Device_Extension *)host->hostdata;
+ 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)
+ }
-- 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
+ #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)
-+#else
-+#define BusLogic_InitializeProbeInfoList(adapter) \
-+ BusLogic_InitializeProbeInfoListISA(adapter)
- #endif /* CONFIG_PCI */
+ #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);
-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
+ #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);
- /*
-- 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.
- */
+-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);
+ }
-@@ -178,7 +161,7 @@ static int BusLogic_HostAdapterAddressCount[3] = { 0, BusLogic_MultiMasterAddres
- Define macros for testing the Host Adapter Type.
- */
+ 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;
--#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
-+#ifdef CONFIG_SCSI_FLASHPOINT
+ rc = kzalloc(sizeof(*rc), GFP_KERNEL);
+@@ -230,17 +232,16 @@ int raid_component_add(struct raid_template *r,struct device *raid_dev,
+ return -ENOMEM;
- #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 @@
- */
+ 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;
--#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
-+#ifdef CONFIG_SCSI_FLASHPOINT
+@@ -273,9 +274,9 @@ raid_class_attach(struct raid_function_template *ft)
- #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
+ attribute_container_register(&i->r.raid_attrs.ac);
--#else /* CONFIG_SCSI_OMIT_FLASHPOINT */
-+#else /* !CONFIG_SCSI_FLASHPOINT */
+- 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;
- /*
- 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);
+ 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);
--#endif /* CONFIG_SCSI_OMIT_FLASHPOINT */
-+#endif /* CONFIG_SCSI_FLASHPOINT */
-diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
-index b9d3740..7f78e3e 100644
---- a/drivers/scsi/Kconfig
-+++ b/drivers/scsi/Kconfig
-@@ -588,18 +588,20 @@ config SCSI_BUSLOGIC
- <http://www.tldp.org/docs.html#howto>, and the files
- <file:Documentation/scsi/BusLogic.txt> and
- <file:Documentation/scsi/FlashPoint.txt> for more information.
-+ Note that support for FlashPoint is only available for 32-bit
-+ x86 configurations.
+- attribute_container_unregister(&i->r.raid_attrs.ac);
++ BUG_ON(attribute_container_unregister(&i->r.raid_attrs.ac));
- To compile this driver as a module, choose M here: the
- module will be called BusLogic.
+ 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);
--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.
+ /**
++ * 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;
- config SCSI_DMX3191D
- tristate "DMX3191D SCSI support"
-diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
-index 5ac3a3e..07d572f 100644
---- a/drivers/scsi/a2091.c
-+++ b/drivers/scsi/a2091.c
-@@ -179,6 +179,9 @@ int __init a2091_detect(struct scsi_host_template *tpnt)
- DMA(instance)->DAWR = DAWR_A2091;
- regs.SASR = &(DMA(instance)->SASR);
- regs.SCMD = &(DMA(instance)->SCMD);
-+ HDATA(instance)->no_sync = 0xff;
-+ HDATA(instance)->fast = 0;
-+ HDATA(instance)->dma_mode = CTRL_DMA;
- wd33c93_init(instance, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
- request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED, "A2091 SCSI",
- instance);
-diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
-index 3aeec96..8b449d8 100644
---- a/drivers/scsi/a3000.c
-+++ b/drivers/scsi/a3000.c
-@@ -178,6 +178,9 @@ int __init a3000_detect(struct scsi_host_template *tpnt)
- DMA(a3000_host)->DAWR = DAWR_A3000;
- regs.SASR = &(DMA(a3000_host)->SASR);
- regs.SCMD = &(DMA(a3000_host)->SCMD);
-+ HDATA(a3000_host)->no_sync = 0xff;
-+ HDATA(a3000_host)->fast = 0;
-+ HDATA(a3000_host)->dma_mode = CTRL_DMA;
- wd33c93_init(a3000_host, regs, dma_setup, dma_stop, WD33C93_FS_12_15);
- if (request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, "A3000 SCSI",
- a3000_intr))
-diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
-index c05092f..460d402 100644
---- a/drivers/scsi/aacraid/aachba.c
-+++ b/drivers/scsi/aacraid/aachba.c
-@@ -31,7 +31,6 @@
- #include <linux/slab.h>
- #include <linux/completion.h>
- #include <linux/blkdev.h>
--#include <asm/semaphore.h>
- #include <asm/uaccess.h>
- #include <linux/highmem.h> /* For flush_kernel_dcache_page */
+- 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);
-@@ -205,7 +204,7 @@ MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health"
+ 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);
- 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.");
+- 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);
-@@ -379,24 +378,6 @@ int aac_get_containers(struct aac_dev *dev)
- return status;
+ put_device(dev);
+ }
+@@ -301,30 +330,16 @@ void scsi_put_command(struct scsi_cmnd *cmd)
}
+ EXPORT_SYMBOL(scsi_put_command);
--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);
+-/**
+- * 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;
-
-- transfer_len -= offset;
-- if (buf && transfer_len > 0)
-- memcpy(buf + offset, data, transfer_len);
+- spin_lock_init(&shost->free_list_lock);
+- INIT_LIST_HEAD(&shost->free_list);
-
-- flush_kernel_dcache_page(kmap_atomic_to_page(buf - sg->offset));
-- kunmap_atomic(buf - sg->offset, KM_IRQ0);
++ 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;
-
- 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));
- }
+- 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;
+ }
-@@ -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));
- }
+ /**
+@@ -386,17 +486,10 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost)
- 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);
+ 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);
}
- 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;
+-
+- 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);
+ }
- 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);
+ #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));
-- 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]);
+- 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..f6600bf 100644
+--- a/drivers/scsi/scsi_debug.c
++++ b/drivers/scsi/scsi_debug.c
+@@ -39,16 +39,18 @@
+ #include <linux/vmalloc.h>
+ #include <linux/moduleparam.h>
+ #include <linux/scatterlist.h>
+-
+ #include <linux/blkdev.h>
+-#include "scsi.h"
+
-+ 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;
++#include <scsi/scsi.h>
++#include <scsi/scsi_cmnd.h>
++#include <scsi/scsi_device.h>
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsicam.h>
++#include <scsi/scsi_eh.h>
-@@ -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);
+ #include <linux/stat.h>
-@@ -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);
+ #include "scsi_logging.h"
+-#include "scsi_debug.h"
- scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
- scsicmd->scsi_done(scsicmd);
-diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
-index ace0b75..113ca9c 100644
---- a/drivers/scsi/aacraid/aacraid.h
-+++ b/drivers/scsi/aacraid/aacraid.h
-@@ -1850,9 +1850,9 @@ int aac_get_containers(struct aac_dev *dev);
- int aac_scsi_cmd(struct scsi_cmnd *cmd);
- int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg);
- #ifndef shost_to_class
--#define shost_to_class(shost) &shost->shost_classdev
-+#define shost_to_class(shost) &shost->shost_dev
- #endif
--ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf);
-+ssize_t aac_get_serial_number(struct device *dev, char *buf);
- int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg);
- int aac_rx_init(struct aac_dev *dev);
- int aac_rkt_init(struct aac_dev *dev);
-diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
-index abef051..5fd83de 100644
---- a/drivers/scsi/aacraid/commctrl.c
-+++ b/drivers/scsi/aacraid/commctrl.c
-@@ -39,7 +39,7 @@
- #include <linux/blkdev.h>
- #include <linux/delay.h> /* ssleep prototype */
- #include <linux/kthread.h>
--#include <asm/semaphore.h>
-+#include <linux/semaphore.h>
- #include <asm/uaccess.h>
+ #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)
- #include "aacraid.h"
-diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
-index 89cc8b7..294a802 100644
---- a/drivers/scsi/aacraid/comminit.c
-+++ b/drivers/scsi/aacraid/comminit.c
-@@ -39,7 +39,6 @@
- #include <linux/completion.h>
- #include <linux/mm.h>
- #include <scsi/scsi_host.h>
--#include <asm/semaphore.h>
+-static unsigned int sdebug_store_size; /* in bytes */
+ static unsigned int sdebug_store_sectors;
+ static sector_t sdebug_capacity; /* in sectors */
- #include "aacraid.h"
+@@ -165,6 +166,9 @@ static int sdebug_sectors_per; /* sectors per cylinder */
-diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
-index 4743449..ef67816 100644
---- a/drivers/scsi/aacraid/commsup.c
-+++ b/drivers/scsi/aacraid/commsup.c
-@@ -41,11 +41,11 @@
- #include <linux/delay.h>
- #include <linux/kthread.h>
- #include <linux/interrupt.h>
-+#include <linux/semaphore.h>
- #include <scsi/scsi.h>
- #include <scsi/scsi_host.h>
- #include <scsi/scsi_device.h>
- #include <scsi/scsi_cmnd.h>
--#include <asm/semaphore.h>
+ #define SDEBUG_SENSE_LEN 32
- #include "aacraid.h"
++#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];
-@@ -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);
+-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 */
- if (wasfull) {
- switch (qid) {
-diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
-index d1163de..933f208 100644
---- a/drivers/scsi/aacraid/dpcsup.c
-+++ b/drivers/scsi/aacraid/dpcsup.c
-@@ -36,7 +36,7 @@
- #include <linux/slab.h>
- #include <linux/completion.h>
- #include <linux/blkdev.h>
--#include <asm/semaphore.h>
-+#include <linux/semaphore.h>
+ static int num_aborts = 0;
+@@ -238,8 +218,6 @@ static DEFINE_RWLOCK(atomic_rw);
- #include "aacraid.h"
+ static char sdebug_proc_name[] = "scsi_debug";
-diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
-index ae5f74f..c109f63 100644
---- a/drivers/scsi/aacraid/linit.c
-+++ b/drivers/scsi/aacraid/linit.c
-@@ -42,7 +42,6 @@
- #include <linux/syscalls.h>
- #include <linux/delay.h>
- #include <linux/kthread.h>
--#include <asm/semaphore.h>
+-static int sdebug_driver_probe(struct device *);
+-static int sdebug_driver_remove(struct device *);
+ static struct bus_type pseudo_lld_bus;
- #include <scsi/scsi.h>
- #include <scsi/scsi_cmnd.h>
-@@ -755,10 +754,10 @@ static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long
- }
- #endif
+ static 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};
--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;
+-/* 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);
- 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 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 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)
+ static void get_data_transfer_info(unsigned char *cmd,
+ unsigned long long *lba, unsigned int *num)
{
-- 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;
+- 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 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)
+-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)
{
- 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;
+ if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
+@@ -613,81 +343,37 @@ static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only,
}
--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)
+ /* 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)
{
-- 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;
+- 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);
- 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;
+ 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;
}
--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)
+ /* 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)
{
-- 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;
+- 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);
}
--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;
+@@ -1159,6 +845,14 @@ static int resp_start_stop(struct scsi_cmnd * scp,
+ return 0;
}
--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 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 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)
+-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)
{
- return snprintf(buf, PAGE_SIZE, "%d\n",
-- class_to_shost(class_dev)->max_channel);
-+ class_to_shost(device)->max_channel);
+- 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 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)
+-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)
{
- return snprintf(buf, PAGE_SIZE, "%d\n",
-- class_to_shost(class_dev)->max_id);
-+ class_to_shost(device)->max_id);
- }
+ unsigned long iflags;
+- unsigned int block, to_bottom;
+- unsigned long long u;
+- int res;
++ int ret;
--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 (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;
- 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;
+ 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;
}
--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;
- }
+@@ -1987,16 +1653,7 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
+ if (!buf)
+ return ret;
--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,
- };
+- 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));
--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
- };
+ offset = 0;
+ for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) {
+@@ -2045,18 +1702,84 @@ static void timer_intr_handler(unsigned long indx)
+ spin_unlock_irqrestore(&queued_arr_lock, iflags);
+ }
-+ssize_t aac_get_serial_number(struct device *device, char *buf)
+-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)
+{
-+ return aac_show_serial_number(device, &aac_serial_number, buf);
++ 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",
+ sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
+- set_bit(QUEUE_FLAG_BIDI, &sdp->request_queue->queue_flags);
++ queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue);
+ return 0;
+ }
- static const struct file_operations aac_cfg_fops = {
- .owner = THIS_MODULE,
-diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
-index 1f18b83..073208b 100644
---- a/drivers/scsi/aacraid/rx.c
-+++ b/drivers/scsi/aacraid/rx.c
-@@ -39,7 +39,6 @@
- #include <linux/completion.h>
- #include <linux/time.h>
- #include <linux/interrupt.h>
--#include <asm/semaphore.h>
-
- #include <scsi/scsi_host.h>
-
-diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
-index cfc3410..fc1a557 100644
---- a/drivers/scsi/aacraid/sa.c
-+++ b/drivers/scsi/aacraid/sa.c
-@@ -39,7 +39,6 @@
- #include <linux/completion.h>
- #include <linux/time.h>
- #include <linux/interrupt.h>
--#include <asm/semaphore.h>
-
- #include <scsi/scsi_host.h>
+-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;
-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;
+ 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;
+ }
-+ nseg = scsi_dma_map(cmd);
-+ if (nseg < 0)
-+ return SCSI_MLQUEUE_HOST_BUSY;
-+
- ahd_lock(ahd, &flags);
+-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;
- /*
-@@ -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;
+ 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)
}
+ }
-@@ -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;
+-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;
-- 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;
+- 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;
+ }
-+ 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 @@
+-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;
- 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];
+- 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 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 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;
}
--static inline void asd_destringify_sas_addr(u8 *sas_addr, const char *p)
+-/* Returns 1 if found 'cmnd' and deleted its timer. else returns 0 */
+-static int stop_queued_cmnd(struct scsi_cmnd * cmnd)
-{
-- int i;
-- for (i = 0; i < SAS_ADDR_SIZE; i++) {
-- u8 h, l;
-- if (!*p)
+- 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;
-- h = isdigit(*p) ? *p-'0' : *p-'A'+10;
-- p++;
-- l = isdigit(*p) ? *p-'0' : *p-'A'+10;
-- p++;
-- sas_addr[i] = (h<<4) | l;
+- }
- }
+- spin_unlock_irqrestore(&queued_arr_lock, iflags);
+- return (k < SCSI_DEBUG_CANQUEUE) ? 1 : 0;
-}
-
- 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)
+-/* 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)
{
- 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);
+@@ -2313,7 +1956,8 @@ static void __init init_all_queued(void)
+ spin_unlock_irqrestore(&queued_arr_lock, iflags);
}
--static inline void asd_set_ddb_type(struct domain_device *dev)
-+static void asd_set_ddb_type(struct domain_device *dev)
+-static void __init sdebug_build_parts(unsigned char * ramp)
++static void __init sdebug_build_parts(unsigned char *ramp,
++ unsigned long store_size)
{
- 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;
- }
+ 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;
--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);
+ /* 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 0
+ 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;
+
- /**
- * 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)
++ 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);
-+#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 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 inline void asd_dump_scb(struct asd_ascb *ascb, int ind)
-+#if 0
++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 void asd_dump_scb(struct asd_ascb *ascb, int ind)
++static struct device pseudo_primary = {
++ .bus_id = "pseudo_0",
++ .release = pseudo_0_release,
++};
++
+ static int __init scsi_debug_init(void)
{
- 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)
- }
- }
+- unsigned int sz;
++ unsigned long sz;
+ int host_to_add;
+ int k;
+ int ret;
-+#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 @@
+ 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();
- #ifdef ASD_DEBUG
+ /* 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);
+ }
--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 */
+- 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);
--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 */
+ ret = device_register(&pseudo_primary);
+ if (ret < 0) {
+@@ -2922,8 +2558,6 @@ static int __init scsi_debug_init(void)
- #endif /* _AIC94XX_DUMP_H_ */
-diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c
-index 098b5f3..83a7822 100644
---- a/drivers/scsi/aic94xx/aic94xx_hwi.c
-+++ b/drivers/scsi/aic94xx/aic94xx_hwi.c
-@@ -27,6 +27,7 @@
- #include <linux/pci.h>
- #include <linux/delay.h>
- #include <linux/module.h>
-+#include <linux/firmware.h>
+ init_all_queued();
- #include "aic94xx.h"
- #include "aic94xx_reg.h"
-@@ -38,16 +39,14 @@ u32 MBAR0_SWB_SIZE;
+- sdebug_driver_template.proc_name = sdebug_proc_name;
+-
+ host_to_add = scsi_debug_add_host;
+ scsi_debug_add_host = 0;
- /* ---------- Initialization ---------- */
+@@ -2972,30 +2606,6 @@ static void __exit scsi_debug_exit(void)
+ device_initcall(scsi_debug_init);
+ module_exit(scsi_debug_exit);
--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)
+-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)
{
-- 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;
- }
+ 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;
--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)
+ sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL);
+ if (NULL == sdbg_host) {
+@@ -3023,16 +2632,13 @@ static int sdebug_add_adapter(void)
- asd_init_ctxmem(asd_ha);
+ 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);
+ }
-- 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);
+ spin_lock(&sdebug_host_list_lock);
+@@ -3053,9 +2659,8 @@ static int sdebug_add_adapter(void)
+ return error;
-@@ -821,7 +819,7 @@ static inline void asd_com_sas_isr(struct asd_ha_struct *asd_ha)
- asd_chip_reset(asd_ha);
+ 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 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)
++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)
{
- u32 stat0r = asd_read_reg_dword(asd_ha, ASISTAT0R);
+ int error = 0;
+@@ -3120,9 +2982,8 @@ static int sdebug_driver_probe(struct device * dev)
-@@ -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)
+ static int sdebug_driver_remove(struct device * dev)
{
- u16 status;
- u32 pcix_status;
-@@ -1044,8 +1042,8 @@ irqreturn_t asd_hw_isr(int irq, void *dev_id)
-
- /* ---------- SCB handling ---------- */
+- 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;
--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);
+ sdbg_host = to_sdebug_host(dev);
- 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");
+@@ -3134,9 +2995,8 @@ static int sdebug_driver_remove(struct device * dev)
--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 {
- },
- };
+ scsi_remove_host(sdbg_host->shost);
--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;
+- 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 inline void asd_free_escbs(struct asd_ha_struct *asd_ha)
-+static void asd_free_escbs(struct asd_ha_struct *asd_ha)
+-static void sdebug_max_tgts_luns(void)
++static int pseudo_lld_bus_match(struct device *dev,
++ struct device_driver *dev_driver)
{
- 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;
+- 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 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 struct bus_type pseudo_lld_bus = {
++ .name = "pseudo",
++ .match = pseudo_lld_bus_match,
++ .probe = sdebug_driver_probe,
++ .remove = sdebug_driver_remove,
++};
+diff --git a/drivers/scsi/scsi_debug.h b/drivers/scsi/scsi_debug.h
+deleted file mode 100644
+index 965dd5e..0000000
+--- a/drivers/scsi/scsi_debug.h
++++ /dev/null
+@@ -1,24 +0,0 @@
+-#ifndef _SCSI_DEBUG_H
+-
+-#include <linux/types.h>
+-
+-static int scsi_debug_slave_alloc(struct scsi_device *);
+-static int scsi_debug_slave_configure(struct scsi_device *);
+-static void scsi_debug_slave_destroy(struct scsi_device *);
+-static int scsi_debug_queuecommand(struct scsi_cmnd *,
+- void (*done) (struct scsi_cmnd *));
+-static int scsi_debug_ioctl(struct scsi_device *, int, void __user *);
+-static int scsi_debug_biosparam(struct scsi_device *, struct block_device *,
+- sector_t, int[]);
+-static int scsi_debug_abort(struct scsi_cmnd *);
+-static int scsi_debug_bus_reset(struct scsi_cmnd *);
+-static int scsi_debug_device_reset(struct scsi_cmnd *);
+-static int scsi_debug_host_reset(struct scsi_cmnd *);
+-static int scsi_debug_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
+-static const char * scsi_debug_info(struct Scsi_Host *);
+-
+-#define SCSI_DEBUG_CANQUEUE 255 /* needs to be >= 1 */
+-
+-#define SCSI_DEBUG_MAX_CMD_LEN 16
+-
+-#endif
+diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
+index b8de041..a235802 100644
+--- a/drivers/scsi/scsi_devinfo.c
++++ b/drivers/scsi/scsi_devinfo.c
+@@ -449,37 +449,40 @@ int scsi_get_device_flags(struct scsi_device *sdev,
}
--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)
+ #ifdef CONFIG_SCSI_PROC_FS
+-/*
+- * proc_scsi_dev_info_read: dump the scsi_dev_info_list via
+- * /proc/scsi/device_info
+- */
+-static int proc_scsi_devinfo_read(char *buffer, char **start,
+- off_t offset, int length)
++static int devinfo_seq_show(struct seq_file *m, void *v)
{
- if (unlikely(asd_ha->iospace))
- outw(val,
-@@ -54,8 +54,8 @@ static inline void asd_write_word(struct asd_ha_struct *asd_ha,
- wmb();
- }
+- struct scsi_dev_info_list *devinfo;
+- int size, len = 0;
+- off_t begin = 0;
+- off_t pos = 0;
++ struct scsi_dev_info_list *devinfo =
++ list_entry(v, struct scsi_dev_info_list, dev_info_list);
--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,
+- list_for_each_entry(devinfo, &scsi_dev_info_list, dev_info_list) {
+- size = sprintf(buffer + len, "'%.8s' '%.16s' 0x%x\n",
++ seq_printf(m, "'%.8s' '%.16s' 0x%x\n",
+ devinfo->vendor, devinfo->model, devinfo->flags);
+- len += size;
+- pos = begin + len;
+- if (pos < offset) {
+- len = 0;
+- begin = pos;
+- }
+- if (pos > offset + length)
+- goto stop_output;
+- }
++ return 0;
++}
++
++static void * devinfo_seq_start(struct seq_file *m, loff_t *pos)
++{
++ return seq_list_start(&scsi_dev_info_list, *pos);
++}
- /* 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;
+-stop_output:
+- *start = buffer + (offset - begin); /* Start of wanted data */
+- len -= (offset - begin); /* Start slop */
+- if (len > length)
+- len = length; /* Ending slop */
+- return (len);
++static void * devinfo_seq_next(struct seq_file *m, void *v, loff_t *pos)
++{
++ return seq_list_next(v, &scsi_dev_info_list, pos);
++}
++
++static void devinfo_seq_stop(struct seq_file *m, void *v)
++{
++}
++
++static const struct seq_operations scsi_devinfo_seq_ops = {
++ .start = devinfo_seq_start,
++ .next = devinfo_seq_next,
++ .stop = devinfo_seq_stop,
++ .show = devinfo_seq_show,
++};
++
++static int proc_scsi_devinfo_open(struct inode *inode, struct file *file)
++{
++ return seq_open(file, &scsi_devinfo_seq_ops);
}
--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)
+ /*
+@@ -489,11 +492,12 @@ stop_output:
+ * integer value of flag to the scsi device info list.
+ * To use, echo "vendor:model:flag" > /proc/scsi/device_info
+ */
+-static int proc_scsi_devinfo_write(struct file *file, const char __user *buf,
+- unsigned long length, void *data)
++static ssize_t proc_scsi_devinfo_write(struct file *file,
++ const char __user *buf,
++ size_t length, loff_t *ppos)
{
- 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;
- }
+ char *buffer;
+- int err = length;
++ ssize_t err = length;
--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); \
+ if (!buf || length>PAGE_SIZE)
+ return -EINVAL;
+@@ -517,6 +521,15 @@ out:
+ free_page((unsigned long)buffer);
+ return err;
}
++
++static const struct file_operations scsi_devinfo_proc_fops = {
++ .owner = THIS_MODULE,
++ .open = proc_scsi_devinfo_open,
++ .read = seq_read,
++ .write = proc_scsi_devinfo_write,
++ .llseek = seq_lseek,
++ .release = seq_release,
++};
+ #endif /* CONFIG_SCSI_PROC_FS */
--#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); \
- }
+ module_param_string(dev_flags, scsi_dev_flags, sizeof(scsi_dev_flags), 0);
+@@ -577,15 +590,13 @@ int __init scsi_init_devinfo(void)
+ }
- 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)
+ #ifdef CONFIG_SCSI_PROC_FS
+- p = create_proc_entry("scsi/device_info", 0, NULL);
++ p = proc_create("scsi/device_info", 0, NULL, &scsi_devinfo_proc_fops);
+ if (!p) {
+ error = -ENOMEM;
+ goto out;
+ }
--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;
+ p->owner = THIS_MODULE;
+- p->get_info = proc_scsi_devinfo_read;
+- p->write_proc = proc_scsi_devinfo_write;
+ #endif /* CONFIG_SCSI_PROC_FS */
-@@ -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;
+ out:
+diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
+index 045a086..1eaba6c 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 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,
- }
++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;
- /* 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);
+ 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;
}
--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)
+@@ -584,8 +616,9 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
{
- 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);
+ 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);
}
--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:
- ;
+ /**
+@@ -1060,6 +1093,56 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
}
--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)
+ /**
++ * 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,
{
- unsigned long flags;
- struct sas_ha_struct *sas_ha = &ascb->ha->sas_ha;
-@@ -715,7 +714,7 @@ out:
- asd_ascb_free(ascb);
+ 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);
--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)
+@@ -1619,10 +1704,8 @@ void scsi_report_bus_reset(struct Scsi_Host *shost, int channel)
+ struct scsi_device *sdev;
- /* ---------- INITIATE LINK ADM TASK ---------- */
+ __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)
-+#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;
+ __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);
+@@ -1690,6 +1771,7 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
+ unsigned long flags;
+ int rtn;
-+#endif /* 0 */
-+
- /* ---------- SCB timer ---------- */
++ blk_rq_init(NULL, &req);
+ scmd->request = &req;
+ memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout));
- /**
-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;
+@@ -1714,6 +1796,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 +1994,31 @@ int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
+ }
}
-
--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.
+ 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..d545ad1 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -536,6 +536,9 @@ static void scsi_run_queue(struct request_queue *q)
+ !shost->host_blocked && !shost->host_self_blocked &&
+ !((shost->can_queue > 0) &&
+ (shost->host_busy >= shost->can_queue))) {
++
++ int flagset;
++
+ /*
+ * As long as shost is accepting commands and we have
+ * starved queues, call blk_run_queue. scsi_request_fn
+@@ -549,19 +552,20 @@ static void scsi_run_queue(struct request_queue *q)
+ sdev = list_entry(shost->starved_list.next,
+ struct scsi_device, starved_entry);
+ list_del_init(&sdev->starved_entry);
+- spin_unlock_irqrestore(shost->host_lock, flags);
+-
++ spin_unlock(shost->host_lock);
++
++ spin_lock(sdev->request_queue->queue_lock);
++ flagset = test_bit(QUEUE_FLAG_REENTER, &q->queue_flags) &&
++ !test_bit(QUEUE_FLAG_REENTER,
++ &sdev->request_queue->queue_flags);
++ if (flagset)
++ queue_flag_set(QUEUE_FLAG_REENTER, sdev->request_queue);
++ __blk_run_queue(sdev->request_queue);
++ if (flagset)
++ queue_flag_clear(QUEUE_FLAG_REENTER, sdev->request_queue);
++ spin_unlock(sdev->request_queue->queue_lock);
+
+- if (test_bit(QUEUE_FLAG_REENTER, &q->queue_flags) &&
+- !test_and_set_bit(QUEUE_FLAG_REENTER,
+- &sdev->request_queue->queue_flags)) {
+- blk_run_queue(sdev->request_queue);
+- clear_bit(QUEUE_FLAG_REENTER,
+- &sdev->request_queue->queue_flags);
+- } else
+- blk_run_queue(sdev->request_queue);
+-
+- spin_lock_irqsave(shost->host_lock, flags);
++ spin_lock(shost->host_lock);
+ if (unlikely(!list_empty(&sdev->starved_entry)))
+ /*
+ * sdev lost a race, and was put back on the
+@@ -784,7 +788,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.
*/
--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)
+-void scsi_end_bidi_request(struct scsi_cmnd *cmd)
++static void scsi_end_bidi_request(struct scsi_cmnd *cmd)
{
- 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)
- }
-
+ struct request *req = cmd->request;
+ unsigned int dlen = req->data_len;
+@@ -839,7 +843,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 +857,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 +868,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 +890,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ "%d bytes done.\n",
+ req->nr_sectors, good_bytes));
--/**
-- * 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;
--}
+- if (clear_errors)
+- req->errors = 0;
-
- /* ---------- Downloading CSEQ/LSEQ microcode ---------- */
+ /* 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;
- 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));
+ /* good_bytes = 0, or (inclusive) there were leftovers and
+@@ -1587,8 +1589,9 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
- #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);
+ blk_queue_max_segment_size(q, dma_get_max_seg_size(dev));
--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;
++ /* New queue, no concurrency on queue_flags */
+ if (!shost->use_clustering)
+- clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
++ queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q);
+
+ /*
+ * set a reasonable default alignment on word boundaries: the
+diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
+index 3f34e93..b33e725 100644
+--- a/drivers/scsi/scsi_priv.h
++++ b/drivers/scsi/scsi_priv.h
+@@ -121,6 +121,7 @@ extern struct scsi_transport_template blank_transport_template;
+ extern void __scsi_remove_device(struct scsi_device *);
+
+ extern struct bus_type scsi_bus_type;
++extern struct attribute_group *scsi_sysfs_shost_attr_groups[];
+
+ /* scsi_netlink.c */
+ #ifdef CONFIG_SCSI_NETLINK
+diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
+index ed39515..e4a0d2f 100644
+--- a/drivers/scsi/scsi_proc.c
++++ b/drivers/scsi/scsi_proc.c
+@@ -190,10 +190,14 @@ void scsi_proc_host_rm(struct Scsi_Host *shost)
+ */
+ static int proc_print_scsidevice(struct device *dev, void *data)
+ {
+- struct scsi_device *sdev = to_scsi_device(dev);
++ struct scsi_device *sdev;
+ struct seq_file *s = data;
+ int i;
-@@ -51,9 +51,9 @@ static const u8 data_dir_flags[] = {
- [PCI_DMA_NONE] = DATA_DIR_NONE, /* NO TRANSFER */
- };
++ if (!scsi_is_sdev_device(dev))
++ goto out;
++
++ sdev = to_scsi_device(dev);
+ seq_printf(s,
+ "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n Vendor: ",
+ sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
+@@ -230,6 +234,7 @@ static int proc_print_scsidevice(struct device *dev, void *data)
+ else
+ seq_printf(s, "\n");
--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;
++out:
+ return 0;
}
--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);
+@@ -408,6 +413,7 @@ static int proc_scsi_open(struct inode *inode, struct file *file)
}
--static inline int asd_clear_nexus(struct sas_task *task)
-+static int asd_clear_nexus(struct sas_task *task)
- {
- int res = TMF_RESP_FUNC_FAILED;
- int leftover;
-diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
-index 3288be2..ab646e5 100644
---- a/drivers/scsi/arcmsr/arcmsr.h
-+++ b/drivers/scsi/arcmsr/arcmsr.h
-@@ -44,7 +44,7 @@
- */
- #include <linux/interrupt.h>
-
--struct class_device_attribute;
-+struct device_attribute;
- /*The limit of outstanding scsi command that firmware can handle*/
- #define ARCMSR_MAX_OUTSTANDING_CMD 256
- #define ARCMSR_MAX_FREECCB_NUM 320
-@@ -556,6 +556,6 @@ struct SENSE_DATA
- extern void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *);
- extern void arcmsr_iop_message_read(struct AdapterControlBlock *);
- extern struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *);
--extern struct class_device_attribute *arcmsr_host_attrs[];
-+extern struct device_attribute *arcmsr_host_attrs[];
- extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *);
- void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb);
-diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c
-index 7d7b0a5..69f8346 100644
---- a/drivers/scsi/arcmsr/arcmsr_attr.c
-+++ b/drivers/scsi/arcmsr/arcmsr_attr.c
-@@ -57,15 +57,15 @@
- #include <scsi/scsi_transport.h>
- #include "arcmsr.h"
-
--struct class_device_attribute *arcmsr_host_attrs[];
-+struct device_attribute *arcmsr_host_attrs[];
-
- static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj,
- struct bin_attribute *bin,
- char *buf, loff_t off,
- size_t count)
- {
-- struct class_device *cdev = container_of(kobj,struct class_device,kobj);
-- struct Scsi_Host *host = class_to_shost(cdev);
-+ struct device *dev = container_of(kobj,struct device,kobj);
-+ struct Scsi_Host *host = class_to_shost(dev);
- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
- uint8_t *pQbuffer,*ptmpQbuffer;
- int32_t allxfer_len = 0;
-@@ -110,8 +110,8 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct kobject *kobj,
- char *buf, loff_t off,
- size_t count)
- {
-- struct class_device *cdev = container_of(kobj,struct class_device,kobj);
-- struct Scsi_Host *host = class_to_shost(cdev);
-+ struct device *dev = container_of(kobj,struct device,kobj);
-+ struct Scsi_Host *host = class_to_shost(dev);
- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
- int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
- uint8_t *pQbuffer, *ptmpuserbuffer;
-@@ -158,8 +158,8 @@ static ssize_t arcmsr_sysfs_iop_message_clear(struct kobject *kobj,
- char *buf, loff_t off,
- size_t count)
- {
-- struct class_device *cdev = container_of(kobj,struct class_device,kobj);
-- struct Scsi_Host *host = class_to_shost(cdev);
-+ struct device *dev = container_of(kobj,struct device,kobj);
-+ struct Scsi_Host *host = class_to_shost(dev);
- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
- uint8_t *pQbuffer;
+ static const struct file_operations proc_scsi_operations = {
++ .owner = THIS_MODULE,
+ .open = proc_scsi_open,
+ .read = seq_read,
+ .write = proc_scsi_write,
+@@ -426,10 +432,9 @@ int __init scsi_init_procfs(void)
+ if (!proc_scsi)
+ goto err1;
-@@ -220,87 +220,104 @@ int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb)
- struct Scsi_Host *host = acb->host;
- int error;
+- pde = create_proc_entry("scsi/scsi", 0, NULL);
++ pde = proc_create("scsi/scsi", 0, NULL, &proc_scsi_operations);
+ if (!pde)
+ goto err2;
+- pde->proc_fops = &proc_scsi_operations;
-- 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);
- }
+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;
- 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);
- }
+- 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];
- 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));
- }
+ 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)
- 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);
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index e67c14e..a00eee6 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -322,6 +322,21 @@ out:
+ return NULL;
}
- 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)
++static void scsi_target_destroy(struct scsi_target *starget)
+{
-+ 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);
++ struct device *dev = &starget->dev;
++ struct Scsi_Host *shost = dev_to_shost(dev->parent);
++ unsigned long flags;
++
++ transport_destroy_device(dev);
++ spin_lock_irqsave(shost->host_lock, flags);
++ if (shost->hostt->target_destroy)
++ shost->hostt->target_destroy(starget);
++ list_del_init(&starget->siblings);
++ spin_unlock_irqrestore(shost->host_lock, flags);
++ put_device(dev);
++}
++
+ static void scsi_target_dev_release(struct device *dev)
+ {
+ struct device *parent = dev->parent;
+@@ -331,9 +346,14 @@ static void scsi_target_dev_release(struct device *dev)
+ put_device(parent);
}
- 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);
++struct device_type scsi_target_type = {
++ .name = "scsi_target",
++ .release = scsi_target_dev_release,
++};
++
+ int scsi_is_target_device(const struct device *dev)
+ {
+- return dev->release == scsi_target_dev_release;
++ return dev->type == &scsi_target_type;
}
+ EXPORT_SYMBOL(scsi_is_target_device);
- 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;
+@@ -391,14 +411,17 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
+ device_initialize(dev);
+ starget->reap_ref = 1;
+ dev->parent = get_device(parent);
+- dev->release = scsi_target_dev_release;
+ sprintf(dev->bus_id, "target%d:%d:%d",
+ shost->host_no, channel, id);
++#ifndef CONFIG_SYSFS_DEPRECATED
++ dev->bus = &scsi_bus_type;
++#endif
++ dev->type = &scsi_target_type;
+ starget->id = id;
+ starget->channel = channel;
+ INIT_LIST_HEAD(&starget->siblings);
+ INIT_LIST_HEAD(&starget->devices);
+- starget->state = STARGET_RUNNING;
++ starget->state = STARGET_CREATED;
+ starget->scsi_level = SCSI_2;
+ retry:
+ spin_lock_irqsave(shost->host_lock, flags);
+@@ -411,18 +434,6 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ /* allocate and add */
+ transport_setup_device(dev);
+- error = device_add(dev);
+- if (error) {
+- dev_err(dev, "target device_add failed, error %d\n", error);
+- spin_lock_irqsave(shost->host_lock, flags);
+- list_del_init(&starget->siblings);
+- spin_unlock_irqrestore(shost->host_lock, flags);
+- transport_destroy_device(dev);
+- put_device(parent);
+- kfree(starget);
+- return NULL;
+- }
+- transport_add_device(dev);
+ if (shost->hostt->target_alloc) {
+ error = shost->hostt->target_alloc(starget);
+
+@@ -430,9 +441,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
+ dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error);
+ /* don't want scsi_target_reap to do the final
+ * put because it will be under the host lock */
+- get_device(dev);
+- scsi_target_reap(starget);
+- put_device(dev);
++ scsi_target_destroy(starget);
+ return NULL;
+ }
+ }
+@@ -459,18 +468,10 @@ static void scsi_target_reap_usercontext(struct work_struct *work)
+ {
+ struct scsi_target *starget =
+ container_of(work, struct scsi_target, ew.work);
+- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+- unsigned long flags;
- return snprintf(buf, PAGE_SIZE,
- "%s\n",
-@@ -308,9 +325,12 @@ arcmsr_attr_host_fw_version(struct class_device *cdev, char *buf) {
+ transport_remove_device(&starget->dev);
+ device_del(&starget->dev);
+- transport_destroy_device(&starget->dev);
+- spin_lock_irqsave(shost->host_lock, flags);
+- if (shost->hostt->target_destroy)
+- shost->hostt->target_destroy(starget);
+- list_del_init(&starget->siblings);
+- spin_unlock_irqrestore(shost->host_lock, flags);
+- put_device(&starget->dev);
++ scsi_target_destroy(starget);
}
- 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) {
- }
+ /**
+@@ -485,21 +486,25 @@ void scsi_target_reap(struct scsi_target *starget)
+ {
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ unsigned long flags;
++ enum scsi_target_state state;
++ int empty;
- 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;
+ spin_lock_irqsave(shost->host_lock, flags);
++ state = starget->state;
++ empty = --starget->reap_ref == 0 &&
++ list_empty(&starget->devices) ? 1 : 0;
++ spin_unlock_irqrestore(shost->host_lock, flags);
+
+- if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
+- BUG_ON(starget->state == STARGET_DEL);
+- starget->state = STARGET_DEL;
+- spin_unlock_irqrestore(shost->host_lock, flags);
+- execute_in_process_context(scsi_target_reap_usercontext,
+- &starget->ew);
++ if (!empty)
+ return;
- return snprintf(buf, PAGE_SIZE,
- "%4d\n",
-@@ -328,9 +351,12 @@ arcmsr_attr_host_fw_numbers_queue(struct class_device *cdev, char *buf) {
+- }
+- spin_unlock_irqrestore(shost->host_lock, flags);
+-
+- return;
++ BUG_ON(state == STARGET_DEL);
++ starget->state = STARGET_DEL;
++ if (state == STARGET_CREATED)
++ scsi_target_destroy(starget);
++ else
++ execute_in_process_context(scsi_target_reap_usercontext,
++ &starget->ew);
}
- 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) {
- }
+ /**
+@@ -1048,8 +1053,9 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
+ scsi_inq_str(vend, result, 8, 16),
+ scsi_inq_str(mod, result, 16, 32));
+ });
++
+ }
+-
++
+ res = SCSI_SCAN_TARGET_PRESENT;
+ goto out_free_result;
+ }
+@@ -1489,7 +1495,6 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
+ if (scsi_host_scan_allowed(shost))
+ scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
+ mutex_unlock(&shost->scan_mutex);
+- transport_configure_device(&starget->dev);
+ scsi_target_reap(starget);
+ put_device(&starget->dev);
+
+@@ -1570,7 +1575,6 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel,
+ out_reap:
+ /* now determine if the target has any children at all
+ * and if not, nuke it */
+- transport_configure_device(&starget->dev);
+ scsi_target_reap(starget);
- 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;
+ put_device(&starget->dev);
+@@ -1824,7 +1828,7 @@ void scsi_scan_host(struct Scsi_Host *shost)
+ }
- return snprintf(buf, PAGE_SIZE,
- "%4d\n",
- acb->firm_hd_channels);
+ p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no);
+- if (unlikely(IS_ERR(p)))
++ if (IS_ERR(p))
+ do_scan_async(data);
}
+ EXPORT_SYMBOL(scsi_scan_host);
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index ed83cdb..049103f 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -21,6 +21,8 @@
+ #include "scsi_priv.h"
+ #include "scsi_logging.h"
--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);
++static struct device_type scsi_dev_type;
+
-+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;
+ static const struct {
+ enum scsi_device_state value;
+ char *name;
+@@ -119,9 +121,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); \
+ }
-@@ -739,17 +739,18 @@ static long ch_ioctl(struct file *file,
- mutex_lock(&ch->lock);
+@@ -131,7 +134,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);
- 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;
+ #define shost_rd_attr(field, format_string) \
+ shost_rd_attr2(field, field, format_string)
+@@ -140,10 +143,11 @@ shost_rd_attr2(field, field, format_string)
+ * Create the actual show/store functions and data structures.
+ */
-- 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)
+-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_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,
+- 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 +155,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);
-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 @@
+ 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;
- #include <linux/i2o-dev.h>
+ for (i = 0; i < ARRAY_SIZE(shost_states); i++) {
+@@ -177,9 +182,9 @@ store_shost_state(struct class_device *class_dev, const char *buf, size_t count)
+ }
--#include <asm/semaphore.h> /* Needed for MUTEX init macros */
- #include <linux/version.h>
- #include <linux/notifier.h>
- #include <asm/atomic.h>
-diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
-index b5a6092..952505c 100644
---- a/drivers/scsi/eata_pio.c
-+++ b/drivers/scsi/eata_pio.c
-@@ -815,8 +815,6 @@ static int register_pio_HBA(long base, struct get_conf *gc, struct pci_dev *pdev
- else
- hd->primary = 1;
+ 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);
-- 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 @@
+ if (!name)
+@@ -188,7 +193,9 @@ show_shost_state(struct class_device *class_dev, char *buf)
+ return snprintf(buf, 20, "%s\n", name);
+ }
- /* 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,
- };
+-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);
--/*
-- * 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"
+ static ssize_t
+ show_shost_mode(unsigned int mode, char *buf)
+@@ -206,9 +213,11 @@ show_shost_mode(unsigned int mode, char *buf)
+ return len;
+ }
-@@ -591,125 +550,111 @@ static int __init gdth_search_isa(ulong32 bios_adr)
- #endif /* CONFIG_ISA */
+-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;
- #ifdef CONFIG_PCI
--static void gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
-- ushort vendor, ushort dev);
-+static bool gdth_pci_registered;
+ if (supported_mode == MODE_UNKNOWN)
+@@ -218,11 +227,13 @@ static ssize_t show_shost_supported_mode(struct class_device *class_dev, char *b
+ return show_shost_mode(supported_mode, buf);
+ }
--static int __init gdth_search_pci(gdth_pci_str *pcistr)
-+static bool gdth_search_vortex(ushort device)
+-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)
{
-- 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;
+- 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 +241,7 @@ static ssize_t show_shost_active_mode(struct class_device *class_dev, char *buf)
+ return show_shost_mode(shost->active_mode, buf);
}
-+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);
+-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 +251,31 @@ 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 attribute *scsi_sysfs_shost_attrs[] = {
++ &dev_attr_unique_id.attr,
++ &dev_attr_host_busy.attr,
++ &dev_attr_cmd_per_lun.attr,
++ &dev_attr_can_queue.attr,
++ &dev_attr_sg_tablesize.attr,
++ &dev_attr_unchecked_isa_dma.attr,
++ &dev_attr_proc_name.attr,
++ &dev_attr_scan.attr,
++ &dev_attr_hstate.attr,
++ &dev_attr_supported_mode.attr,
++ &dev_attr_active_mode.attr,
++ NULL
++};
+
- /* 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 */
++struct attribute_group scsi_shost_attr_group = {
++ .attrs = scsi_sysfs_shost_attrs,
+};
-+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,
++struct attribute_group *scsi_sysfs_shost_attr_groups[] = {
++ &scsi_shost_attr_group,
+ NULL
};
--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)
+-static void scsi_device_cls_release(struct class_device *class_dev)
++static void scsi_device_cls_release(struct device *class_dev)
{
-- 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);
+ struct scsi_device *sdev;
+
+@@ -320,13 +340,18 @@ 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 */
+ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
+ {
+- struct scsi_device *sdp = to_scsi_device(dev);
++ struct scsi_device *sdp;
+
-+ pci_disable_device(pdev);
-+}
++ if (dev->type != &scsi_dev_type)
++ return 0;
+
-+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));
++ sdp = to_scsi_device(dev);
+ if (sdp->no_uld_attach)
+ return 0;
+ return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
+@@ -342,10 +367,16 @@ static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
-- 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;
+ static int scsi_bus_suspend(struct device * dev, pm_message_t state)
+ {
+- struct device_driver *drv = dev->driver;
+- struct scsi_device *sdev = to_scsi_device(dev);
++ struct device_driver *drv;
++ struct scsi_device *sdev;
+ int err;
+
++ if (dev->type != &scsi_dev_type)
++ return 0;
+
-+ rc = pci_enable_device(pdev);
-+ if (rc)
-+ return rc;
++ drv = dev->driver;
++ sdev = to_scsi_device(dev);
+
-+ if (gdth_ctr_count >= MAXHA)
-+ return -EBUSY;
+ err = scsi_device_quiesce(sdev);
+ if (err)
+ return err;
+@@ -361,10 +392,16 @@ static int scsi_bus_suspend(struct device * dev, pm_message_t state)
- /* 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 int scsi_bus_resume(struct device * dev)
+ {
+- struct device_driver *drv = dev->driver;
+- struct scsi_device *sdev = to_scsi_device(dev);
++ struct device_driver *drv;
++ struct scsi_device *sdev;
+ int err = 0;
--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;
++ if (dev->type != &scsi_dev_type)
++ return 0;
++
++ drv = dev->driver;
++ sdev = to_scsi_device(dev);
++
+ if (drv && drv->resume)
+ err = drv->resume(dev);
-- 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;
+@@ -424,7 +461,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 +486,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 +507,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 +559,8 @@ sdev_show_timeout (struct device *dev, struct device_attribute *attr, char *buf)
}
- #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)
+ 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)
{
- 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)
+ struct scsi_device *sdev;
+ int timeout;
+@@ -531,7 +572,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);
- TRACE(("gdth_init_pci()\n"));
+ 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 +585,9 @@ static void sdev_store_delete_callback(struct device *dev)
+ scsi_remove_device(to_scsi_device(dev));
+ }
-- 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)
- }
+-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;
- /* 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;
+@@ -559,7 +602,8 @@ static ssize_t sdev_store_delete(struct device *dev, struct device_attribute *at
+ static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
-@@ -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)
+ 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)
{
-- 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;
+ int i;
+ struct scsi_device *sdev = to_scsi_device(dev);
+@@ -596,7 +640,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);
-- cpcount = min_t(ushort, count, gdth_bufflen(scp));
-+ cpcount = min_t(ushort, count, scsi_bufflen(scp));
+ 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 +657,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);
- 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;
- }
+ 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 +666,8 @@ static DEVICE_ATTR(iocounterbits, S_IRUGO, show_iostat_counterbits, NULL);
-- 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;
- }
+ #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 +691,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 +700,7 @@ sdev_show_evt_##name(struct device *dev, struct device_attribute *attr, \
-- 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);
+ #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 +753,9 @@ static struct attribute_group *scsi_sdev_attr_groups[] = {
+ NULL
+ };
- 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;
+-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 +780,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);
-- 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);
+-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;
+@@ -761,6 +809,27 @@ static ssize_t sdev_store_queue_type_rw(struct device *dev, struct device_attrib
+ return count;
}
-@@ -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)
++static int scsi_target_add(struct scsi_target *starget)
++{
++ int error;
++
++ if (starget->state != STARGET_CREATED)
++ return 0;
++
++ error = device_add(&starget->dev);
++ if (error) {
++ dev_err(&starget->dev, "target device_add failed, error %d\n", error);
++ get_device(&starget->dev);
++ scsi_target_reap(starget);
++ put_device(&starget->dev);
++ return error;
++ }
++ transport_add_device(&starget->dev);
++ starget->state = STARGET_RUNNING;
++
++ return 0;
++}
++
+ static struct device_attribute sdev_attr_queue_type_rw =
+ __ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field,
+ sdev_store_queue_type_rw);
+@@ -776,23 +845,29 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
{
- 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;
+ struct request_queue *rq = sdev->request_queue;
++ struct scsi_target *starget = sdev->sdev_target;
- 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);
+ if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0)
+ return error;
- error = -ENODEV;
-- if (!gdth_init_pci(&pcistr[ctr],ha))
-+ if (!gdth_init_pci(pdev, pcistr, ha))
- goto out_host_put;
++ error = scsi_target_add(starget);
++ if (error)
++ return error;
++
++ transport_configure_device(&starget->dev);
+ error = device_add(&sdev->sdev_gendev);
+ if (error) {
+ put_device(sdev->sdev_gendev.parent);
+ 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;
+ }
- /* 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);
+- /* 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);
- error = request_irq(ha->irq, gdth_interrupt,
-@@ -5019,7 +4962,7 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
+@@ -814,7 +889,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
+ goto out;
+ }
- 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 = bsg_register_queue(rq, &sdev->sdev_gendev, NULL);
++ error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL, NULL);
-- 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;
+ sdev_printk(KERN_INFO, sdev,
+@@ -858,7 +933,7 @@ void __scsi_remove_device(struct scsi_device *sdev)
+ return;
- out_free_coal_stat:
-@@ -5185,16 +5132,8 @@ static int __init gdth_init(void)
+ 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);
+@@ -951,44 +1026,6 @@ int scsi_register_interface(struct class_interface *intf)
+ }
+ EXPORT_SYMBOL(scsi_register_interface);
- #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);
+-static struct class_device_attribute *class_attr_overridden(
+- struct class_device_attribute **attrs,
+- struct class_device_attribute *attr)
+-{
+- int i;
+-
+- if (!attrs)
+- return NULL;
+- for (i = 0; attrs[i]; i++)
+- if (!strcmp(attrs[i]->attr.name, attr->attr.name))
+- return attrs[i];
+- return NULL;
+-}
+-
+-static int class_attr_add(struct class_device *classdev,
+- struct class_device_attribute *attr)
+-{
+- struct class_device_attribute *base_attr;
+-
+- /*
+- * Spare the caller from having to copy things it's not interested in.
+- */
+- base_attr = class_attr_overridden(scsi_sysfs_shost_attrs, attr);
+- if (base_attr) {
+- /* extend permissions */
+- attr->attr.mode |= base_attr->attr.mode;
+-
+- /* override null show/store with default */
+- if (!attr->show)
+- attr->show = base_attr->show;
+- if (!attr->store)
+- attr->store = base_attr->store;
- }
-+ if (pci_register_driver(&gdth_pci_driver) == 0)
-+ gdth_pci_registered = true;
- #endif /* CONFIG_PCI */
+-
+- return class_device_create_file(classdev, attr);
+-}
+-
+ /**
+ * scsi_sysfs_add_host - add scsi host to subsystem
+ * @shost: scsi host struct to add to subsystem
+@@ -998,25 +1035,16 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost)
+ {
+ int error, i;
- 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
++ /* add host specific attributes */
+ if (shost->hostt->shost_attrs) {
+ for (i = 0; shost->hostt->shost_attrs[i]; i++) {
+- error = class_attr_add(&shost->shost_classdev,
++ error = device_create_file(&shost->shost_dev,
+ shost->hostt->shost_attrs[i]);
+ if (error)
+ return error;
+ }
+ }
-+#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;
+- 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,
+- scsi_sysfs_shost_attrs[i]);
+- if (error)
+- return error;
+- }
+- }
+-
+ transport_register_device(&shost->shost_gendev);
+ transport_configure_device(&shost->shost_gendev);
+ return 0;
+@@ -1041,10 +1069,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..5fd64e7 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)
-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)
+ #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.
*/
- 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 */
+- 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];
--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);
- }
+ 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];
- static struct class shost_class = {
- .name = "scsi_host",
-- .release = scsi_host_cls_release,
-+ .dev_release = scsi_host_cls_release,
+ 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];
};
- /**
-@@ -174,7 +174,7 @@ void scsi_remove_host(struct Scsi_Host *shost)
- spin_unlock_irqrestore(shost->host_lock, flags);
+ #define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t)
- 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);
+ 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);
-- error = class_device_add(&shost->shost_classdev);
-+ error = device_add(&shost->shost_dev);
- if (error)
- goto out_del_gendev;
+ 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)
-@@ -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;
- }
- }
+ #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) \
-@@ -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;
+ #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, \
- 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;
+ #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)
-- 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);
+ #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)
- 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);
+ #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)
--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;
+ #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); \
}
-@@ -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);
+ #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)
-- 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));
+ #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)
-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;
+ #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)
- 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;
+
+ #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 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)
+ 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)
{
- return snprintf(buf, PAGE_SIZE, "%s\n", driver_ver);
+- 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);
--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)
+ /* 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)
{
-- 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);
+ 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);
--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,
- };
+@@ -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 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)
+ 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 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;
+- struct fc_rport *rport = transport_class_to_rport(cdev);
++ struct fc_rport *rport = transport_class_to_rport(dev);
-@@ -1467,7 +1468,7 @@ static ssize_t show_host_srp_version(struct class_device *class_dev, char *buf)
- return len;
+ /* 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);
--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)
+ 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 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;
+- struct fc_rport *rport = transport_class_to_rport(cdev);
++ struct fc_rport *rport = transport_class_to_rport(dev);
-@@ -1487,7 +1489,7 @@ static ssize_t show_host_partition_name(struct class_device *class_dev,
- return len;
+ 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 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)
+ 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)
{
-- 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;
+ int val;
+ char *cp;
+- struct fc_rport *rport = transport_class_to_rport(cdev);
++ struct fc_rport *rport = transport_class_to_rport(dev);
-@@ -1507,7 +1510,7 @@ static ssize_t show_host_partition_number(struct class_device *class_dev,
- return len;
+ 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);
--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;
+@@ -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) \
-@@ -1526,7 +1530,7 @@ static ssize_t show_host_mad_version(struct class_device *class_dev, char *buf)
- return len;
- }
+ #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)
--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,
- };
+ #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)
--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;
+ #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++
-@@ -1544,7 +1549,7 @@ static ssize_t show_host_os_type(struct class_device *class_dev, char *buf)
- return len;
- }
+ #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);
--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,
- };
+ #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) \
--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);
+ #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, \
- /* 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;
- }
+ #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, \
--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,
- };
+ #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)
--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;
- }
+ #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)
--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);
- }
+ #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)
--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);
+ #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); \
}
--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);
- }
+ #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, \
--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);
+ #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)
--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,
- };
+ #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)
-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 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 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;
+ #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)
-- 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 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 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
+ #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++
--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
+ #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 */
- 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);
- }
+ #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 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)
+ 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)
{
- int count;
- char *buf;
-@@ -237,7 +203,7 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign
+- struct fc_vport *vport = transport_class_to_vport(cdev);
++ struct fc_vport *vport = transport_class_to_vport(dev);
- 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);
- }
+ 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);
-@@ -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);
- }
+ fc_private_vport_rd_enum_attr(vport_type, FC_PORTTYPE_MAX_NAMELEN);
--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;
+ 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);
- /* 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)
+ 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)
{
-+ 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]);
+- 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);
- rq->errors++;
+ 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);
-@@ -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)
+@@ -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)
{
- 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;
+- 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);
--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;
+@@ -1246,9 +1264,10 @@ static FC_CLASS_DEVICE_ATTR(vport, vport_disable, S_IWUSR,
- return 0; /* we do not want the ide subsystem to retry */
+ #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)); \
}
-@@ -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);
- }
+ #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)
-@@ -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]);
+ #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)
- 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;
+ #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, \
- /* 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)
+ #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)
{
- 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;
+- struct Scsi_Host *shost = transport_class_to_shost(cdev);
++ struct Scsi_Host *shost = transport_class_to_shost(dev);
-@@ -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;
+ 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 inline int idescsi_set_direction(idescsi_pc_t *pc)
-+static inline int idescsi_set_direction(struct ide_atapi_pc *pc)
+ 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)
{
- 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;
- }
+- 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 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)
+ 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)
{
- ide_hwif_t *hwif = drive->hwif;
- struct scatterlist *sg, *scsi_sg;
- int segments;
+- struct Scsi_Host *shost = transport_class_to_shost(cdev);
++ struct Scsi_Host *shost = transport_class_to_shost(dev);
-- if (!pc->request_transfer || pc->request_transfer % 1024)
-+ if (!pc->req_xfer || pc->req_xfer % 1024)
- return 1;
+ if (fc_host_supported_speeds(shost) == FC_PORTSPEED_UNKNOWN)
+ return snprintf(buf, 20, "unknown\n");
- if (idescsi_set_direction(pc))
-@@ -566,21 +542,21 @@ static int idescsi_map_sg(ide_drive_t *drive, idescsi_pc_t *pc)
- return 0;
+ 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);
--/*
-- * 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);
+@@ -1433,9 +1459,10 @@ fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
+ /* Dynamic Host Attributes */
- 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);
+ 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 (dma)
-- set_bit(PC_DMA_OK, &pc->flags);
-+ pc->flags |= PC_FLAG_DMA_OK;
+ if (i->f->get_host_active_fc4s)
+@@ -1443,13 +1470,14 @@ show_fc_host_active_fc4s (struct class_device *cdev, char *buf)
- 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);
- }
+ return (ssize_t)show_fc_fc4s(buf, fc_host_active_fc4s(shost));
}
-@@ -615,7 +591,8 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r
- #endif /* IDESCSI_DEBUG_LOG */
+-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);
- 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;
+ 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 (!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 (i->f->get_host_speed)
+@@ -1460,7 +1488,7 @@ show_fc_host_speed (struct class_device *cdev, char *buf)
- 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;
+ 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);
-@@ -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;
- }
+@@ -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);
-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;
- }
+ /* Private Host Attributes */
-@@ -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)
+ 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 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 {
+- struct Scsi_Host *shost = transport_class_to_shost(cdev);
++ struct Scsi_Host *shost = transport_class_to_shost(dev);
+ const char *name;
- /**
- * 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)
+ 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)
- /**
- * 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)
+ 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 = 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,
+- 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 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 = {
+-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);
- /**
- * 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)
+ 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 = 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;
+- 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 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 = {
+-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);
- /**
- * 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)
+ 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 = 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)
+- 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)
- /**
- * 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)
+ /* 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 = 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;
+- 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);
-@@ -2653,7 +2658,7 @@ static ssize_t ipr_store_log_level(struct class_device *class_dev,
- return strlen(buf);
+ /* 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 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 = {
+ 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
+ };
- /**
- * 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)
+@@ -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 = 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;
+- 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);
--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)
+@@ -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 = 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)
+- 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);
- /**
- * 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)
+
+@@ -1930,12 +1961,17 @@ fc_timed_out(struct scsi_cmnd *scmd)
+ }
+
+ /*
+- * Must be called with shost->host_lock held
++ * Called by fc_user_scan to locate an rport on the shost that
++ * matches the channel and target id, and invoke scsi_scan_target()
++ * on the rport.
+ */
+-static int fc_user_scan(struct Scsi_Host *shost, uint channel,
+- uint id, uint lun)
++static void
++fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, uint lun)
{
-- 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;
+ struct fc_rport *rport;
++ unsigned long flags;
++
++ spin_lock_irqsave(shost->host_lock, flags);
+
+ list_for_each_entry(rport, &fc_host_rports(shost), peers) {
+ if (rport->scsi_target_id == -1)
+@@ -1944,13 +1980,54 @@ static int fc_user_scan(struct Scsi_Host *shost, uint channel,
+ if (rport->port_state != FC_PORTSTATE_ONLINE)
+ continue;
+
+- if ((channel == SCAN_WILD_CARD || channel == rport->channel) &&
+- (id == SCAN_WILD_CARD || id == rport->scsi_target_id)) {
+- scsi_scan_target(&rport->dev, rport->channel,
+- rport->scsi_target_id, lun, 1);
++ if ((channel == rport->channel) &&
++ (id == rport->scsi_target_id)) {
++ spin_unlock_irqrestore(shost->host_lock, flags);
++ scsi_scan_target(&rport->dev, channel, id, lun, 1);
++ return;
+ }
+ }
+
++ spin_unlock_irqrestore(shost->host_lock, flags);
++}
++
++/*
++ * Called via sysfs scan routines. Necessary, as the FC transport
++ * wants to place all target objects below the rport object. So this
++ * routine must invoke the scsi_scan_target() routine with the rport
++ * object as the parent.
++ */
++static int
++fc_user_scan(struct Scsi_Host *shost, uint channel, uint id, uint lun)
++{
++ uint chlo, chhi;
++ uint tgtlo, tgthi;
++
++ if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||
++ ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) ||
++ ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
++ return -EINVAL;
++
++ if (channel == SCAN_WILD_CARD) {
++ chlo = 0;
++ chhi = shost->max_channel + 1;
++ } else {
++ chlo = channel;
++ chhi = channel + 1;
++ }
++
++ if (id == SCAN_WILD_CARD) {
++ tgtlo = 0;
++ tgthi = shost->max_id;
++ } else {
++ tgtlo = id;
++ tgthi = id + 1;
++ }
++
++ for ( ; chlo < chhi; chlo++)
++ for ( ; tgtlo < tgthi; tgtlo++)
++ fc_user_scan_tgt(shost, chlo, tgtlo, lun);
++
+ return 0;
}
--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 = {
+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;
- /**
- * 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 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 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;
+- struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
++ struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
+ kfree(priv);
}
--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,
+@@ -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,
+ };
- /**
- * 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)
+ 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 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;
+- 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);
--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
+ #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,
};
--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)
+@@ -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 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);
+ 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,
+ }
- 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)
+ 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);
}
- /**
-- * 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;
--}
+-#define iscsi_cdev_to_conn(_cdev) \
+- iscsi_dev_to_conn(_cdev->dev)
-
--/**
- * 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)
+ #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);
- /**
-- * 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;
+-#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);
--/**
-- * 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 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,
- 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)
+ #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); \
+ }
- ENTER;
+@@ -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);
-- 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);
+ #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)
-@@ -7740,7 +7724,7 @@ static int __devinit ipr_probe(struct pci_dev *pdev,
- return rc;
- }
+@@ -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;
-- 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);
+- 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;
- if (rc) {
-@@ -7749,11 +7733,11 @@ static int __devinit ipr_probe(struct pci_dev *pdev,
- return rc;
- }
+- 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;
-- 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);
+ /* 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;
- 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;
+-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);
-- 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 */
+- 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);
-@@ -2385,21 +2385,21 @@ ips_get_bios_version(ips_ha_t * ha, int intr)
- return;
+ return 0;
+diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
+index 43a964d..f4461d3 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)
- /* 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);
+@@ -192,6 +192,16 @@ static void sas_non_host_smp_request(struct request_queue *q)
+ sas_smp_request(q, rphy_to_shost(rphy), rphy);
+ }
- /* 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 */
++static void sas_host_release(struct device *dev)
++{
++ struct Scsi_Host *shost = dev_to_shost(dev);
++ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
++ struct request_queue *q = sas_host->q;
++
++ if (q)
++ blk_cleanup_queue(q);
++}
++
+ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
+ {
+ struct request_queue *q;
+@@ -199,6 +209,7 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
+ struct device *dev;
+ char namebuf[BUS_ID_SIZE];
+ const char *name;
++ void (*release)(struct device *);
- minor = inb(ha->io_addr + IPS_REG_FLDP);
+ if (!to_sas_internal(shost->transportt)->f->smp_handler) {
+ printk("%s can't handle SMP requests\n", shost->hostt->name);
+@@ -209,17 +220,19 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
+ q = blk_init_queue(sas_non_host_smp_request, NULL);
+ dev = &rphy->dev;
+ name = dev->bus_id;
++ release = NULL;
+ } else {
+ q = blk_init_queue(sas_host_smp_request, NULL);
+ dev = &shost->shost_gendev;
+ snprintf(namebuf, sizeof(namebuf),
+ "sas_host%d", shost->host_no);
+ name = namebuf;
++ release = sas_host_release;
+ }
+ if (!q)
+ return -ENOMEM;
- /* 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 */
+- error = bsg_register_queue(q, dev, name);
++ error = bsg_register_queue(q, dev, name, release);
+ if (error) {
+ blk_cleanup_queue(q);
+ return -ENOMEM;
+@@ -235,8 +248,7 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
+ else
+ q->queuedata = shost;
-@@ -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);
+- set_bit(QUEUE_FLAG_BIDI, &q->queue_flags);
-
-- /* 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;
++ queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
+ return 0;
+ }
-- xfer_cnt += min_cnt;
-- }
-+ local_irq_save(flags);
-+ scsi_sg_copy_from_buffer(scmd, data, count);
-+ local_irq_restore(flags);
+@@ -253,7 +265,6 @@ static void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy)
+ return;
+
+ bsg_unregister_queue(q);
+- blk_cleanup_queue(q);
}
- /****************************************************************************/
-@@ -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;
+ /*
+@@ -261,7 +272,7 @@ static void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy)
+ */
-- xfer_cnt += min_cnt;
-- }
-+ local_irq_save(flags);
-+ scsi_sg_copy_to_buffer(scmd, data, count);
-+ local_irq_restore(flags);
+ 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 +291,7 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev,
}
- /****************************************************************************/
-@@ -3696,9 +3664,7 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb)
- scb->cmd.basic_io.sg_count = scb->sg_len;
+ 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);
- 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;
+@@ -356,22 +367,24 @@ EXPORT_SYMBOL(sas_remove_host);
- 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);
+ #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); \
+ }
- /* setup CCCR */
-- outl(cpu_to_le32(0x1010), ha->io_addr + IPS_REG_CCCR);
-+ outl(0x1010, ha->io_addr + IPS_REG_CCCR);
+ #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)
- /* 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;
+ #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 +393,14 @@ show_sas_phy_##name(struct class_device *cdev, char *buf) \
- 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);
+ #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)
- ha->adapt->hw_status_tail = phys_status_start;
+ #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); \
}
-@@ -5332,7 +5296,7 @@ ips_statupd_copperhead(ips_ha_t * ha)
- ha->adapt->hw_status_tail = ha->adapt->hw_status_start;
- }
+@@ -394,10 +408,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 +431,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)
-- outl(cpu_to_le32(ha->adapt->hw_status_tail),
-+ outl(ha->adapt->hw_status_tail,
- ha->io_addr + IPS_REG_SQTR);
+ #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)
- 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);
+ #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 +457,25 @@ show_sas_phy_##field(struct class_device *cdev, char *buf) \
- return (IPS_SUCCESS);
+ #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);
}
-@@ -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);
- }
+-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);
-- 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);
+-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 +487,19 @@ static ssize_t do_sas_phy_enable(struct class_device *cdev,
+ return count;
+ };
- return (IPS_SUCCESS);
+-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 +508,22 @@ static ssize_t store_sas_phy_enable(struct class_device *cdev,
+ return count;
}
-@@ -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 */
+-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);
-@@ -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);
+ return snprintf(buf, 20, "%d", phy->enabled);
+ }
-- 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++) {
+-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);
-- 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 */
+-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 +534,21 @@ static ssize_t do_sas_phy_reset(struct class_device *cdev,
+ return count;
+ };
-@@ -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;
+-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);
-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;
+-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);
- 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++;
+ sas_phy_protocol_attr(identify.initiator_port_protocols,
+ initiator_port_protocols);
+@@ -695,16 +717,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); \
+ }
- 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;
- }
+ #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)
-@@ -558,8 +559,8 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ sas_port_simple_attr(num_phys, num_phys, "%d\n", int);
- 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);
+@@ -1017,23 +1040,25 @@ EXPORT_SYMBOL(sas_port_mark_backlink);
- 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);
+ #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); \
+ }
- /*
- * 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;
+ #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)
- /* 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;
+ #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 +1067,14 @@ show_sas_rphy_##name(struct class_device *cdev, char *buf) \
- flush:
-@@ -1412,9 +1416,8 @@ flush:
- ctask->itt, tcp_ctask->sent, ctask->data_count);
+ #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)
- 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));
+ 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);
-- 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;
+ if (!rphy->identify.device_type)
+ return snprintf(buf, 20, "none\n");
+@@ -1056,13 +1082,14 @@ show_sas_rphy_device_type(struct class_device *cdev, char *buf)
+ rphy->identify.device_type, buf);
}
-+/*
-+ * 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;
+-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);
- 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);
+ 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 +1109,14 @@ show_sas_rphy_enclosure_identifier(struct class_device *cdev, char *buf)
+ return sprintf(buf, "0x%llx\n", (unsigned long long)identifier);
+ }
- 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;
+-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);
- 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);
+ 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 +1131,7 @@ show_sas_rphy_bay_identifier(struct class_device *cdev, char *buf)
+ return sprintf(buf, "%d\n", val);
+ }
- 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;
- }
+-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);
-@@ -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);
+ sas_rphy_protocol_attr(identify.initiator_port_protocols,
+@@ -1161,9 +1189,10 @@ static DECLARE_TRANSPORT_CLASS(sas_end_dev_class,
- 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;
+ #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 +1200,7 @@ show_sas_end_dev_##name(struct class_device *cdev, char *buf) \
- 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);
+ #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)
- 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));
- }
+ sas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int);
+@@ -1185,9 +1214,10 @@ static DECLARE_TRANSPORT_CLASS(sas_expander_class,
-+ 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;
+ #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 +1225,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 *);
+@@ -1282,6 +1312,9 @@ static void sas_expander_release(struct device *dev)
+ struct sas_rphy *rphy = dev_to_rphy(dev);
+ struct sas_expander_device *edev = rphy_to_expander_device(rphy);
+
++ if (rphy->q)
++ blk_cleanup_queue(rphy->q);
++
+ put_device(dev->parent);
+ kfree(edev);
}
+@@ -1291,6 +1324,9 @@ static void sas_end_device_release(struct device *dev)
+ struct sas_rphy *rphy = dev_to_rphy(dev);
+ struct sas_end_device *edev = rphy_to_end_device(rphy);
--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;
++ if (rphy->q)
++ blk_cleanup_queue(rphy->q);
+
-+ memcpy(&qc->result_tf, &dev->sata_dev.tf, sizeof(qc->result_tf));
-+ return true;
+ put_device(dev->parent);
+ kfree(edev);
}
+@@ -1554,14 +1590,14 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
+ */
- 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)
- }
+ #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..75a64a6 100644
+--- a/drivers/scsi/scsi_transport_spi.c
++++ b/drivers/scsi/scsi_transport_spi.c
+@@ -24,6 +24,7 @@
+ #include <linux/workqueue.h>
+ #include <linux/blkdev.h>
+ #include <linux/mutex.h>
++#include <linux/sysfs.h>
+ #include <scsi/scsi.h>
+ #include "scsi_priv.h"
+ #include <scsi/scsi_device.h>
+@@ -158,7 +159,7 @@ static inline enum spi_signal_type spi_signal_to_value(const char *name)
}
--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)
+ static int spi_host_setup(struct transport_container *tc, struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
{
-@@ -348,14 +344,11 @@ static int sas_ata_scr_read(struct ata_port *ap, unsigned int sc_reg_in,
- }
+ struct Scsi_Host *shost = dev_to_shost(dev);
- 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 @@
- */
+@@ -169,7 +170,7 @@ static int spi_host_setup(struct transport_container *tc, struct device *dev,
- #include <linux/kthread.h>
-+#include <linux/firmware.h>
-+#include <linux/ctype.h>
+ static int spi_host_configure(struct transport_container *tc,
+ struct device *dev,
+- struct class_device *cdev);
++ struct device *cdev);
- #include "sas_internal.h"
+ static DECLARE_TRANSPORT_CLASS(spi_host_class,
+ "spi_host",
+@@ -195,11 +196,11 @@ static int spi_host_match(struct attribute_container *cont,
-@@ -1064,6 +1066,45 @@ void sas_target_destroy(struct scsi_target *starget)
- return;
- }
+ static int spi_target_configure(struct transport_container *tc,
+ struct device *dev,
+- struct class_device *cdev);
++ struct device *cdev);
-+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 @@
+ 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 +220,7 @@ static int spi_device_configure(struct transport_container *tc,
- struct lpfc_sli2_slim;
+ 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);
--#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 {
+@@ -248,9 +249,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 +262,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 +279,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 +294,12 @@ show_spi_transport_##field(struct class_device *cdev, char *buf) \
- uint32_t fc_eventTag; /* event tag for link attention */
+ #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 +312,12 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \
--
-- 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[])
- }
+ #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 +335,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);
- 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");
- }
+ #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);
- 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);
+ #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);
- return snprintf(buf, PAGE_SIZE, "%s\n",lpfc_info(host));
+ /* The Parallel SCSI Tranport Attributes: */
+ spi_transport_max_attr(offset, "%d\n");
+@@ -370,14 +376,15 @@ static int child_iter(struct device *dev, void *data)
}
static ssize_t
--lpfc_serialnum_show(struct class_device *cdev, char *buf)
-+lpfc_serialnum_show(struct device *dev, struct device_attribute *attr,
-+ char *buf)
+-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_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 scsi_target *starget = transport_class_to_starget(cdev);
++ struct scsi_target *starget = transport_class_to_starget(dev);
-@@ -90,18 +93,20 @@ lpfc_serialnum_show(struct class_device *cdev, char *buf)
+ 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);
- 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);
+ /* Translate the period into ns according to the current spec
+ * for SDTR/PPR messages */
+@@ -412,7 +419,7 @@ show_spi_transport_period_helper(char *buf, int period)
}
static ssize_t
--lpfc_modeldesc_show(struct class_device *cdev, char *buf)
-+lpfc_modeldesc_show(struct device *dev, struct device_attribute *attr,
-+ char *buf)
+-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)
{
-- 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)
+ int j, picosec, period = -1;
+@@ -449,9 +456,10 @@ store_spi_transport_period_helper(struct class_device *cdev, const 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)
+-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_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)
+- 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 +472,8 @@ show_spi_transport_period(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)
+-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_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)
+ struct scsi_target *starget = transport_class_to_starget(cdev);
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+@@ -487,12 +495,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
--lpfc_vportnum_show(struct class_device *cdev, char *buf)
-+lpfc_vportnum_show(struct device *dev, struct device_attribute *attr,
-+ char *buf)
+-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_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)
+ struct scsi_target *starget = transport_class_to_starget(cdev);
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+@@ -507,8 +516,9 @@ show_spi_transport_min_period(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)
+-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_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)
+ struct scsi_target *starget = transport_class_to_starget(cdev);
+ struct spi_transport_attrs *tp =
+@@ -519,12 +529,14 @@ store_spi_transport_min_period(struct class_device *cdev, const 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)
+
+-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)
{
- 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);
+ struct Scsi_Host *shost = transport_class_to_shost(cdev);
+ struct spi_internal *i = to_spi_internal(shost->transportt);
+@@ -534,10 +546,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
--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)
+-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 = 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 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);
- return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion);
+@@ -549,9 +562,9 @@ static ssize_t store_spi_host_signalling(struct class_device *cdev,
+
+ return count;
}
- static ssize_t
--lpfc_state_show(struct class_device *cdev, char *buf)
-+lpfc_state_show(struct device *dev, struct device_attribute *attr,
-+ char *buf)
+-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 +1347,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 +1357,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 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)
- }
+ 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;
- 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)
+ if (si->f->set_signalling)
+@@ -1362,82 +1375,81 @@ static int spi_host_configure(struct transport_container *tc,
+ * overloads the return by setting 1<<1 if the attribute should
+ * be writeable */
+ #define TARGET_ATTRIBUTE_HELPER(name) \
+- (si->f->show_##name ? 1 : 0) + \
+- (si->f->set_##name ? 2 : 0)
++ (si->f->show_##name ? S_IRUGO : 0) | \
++ (si->f->set_##name ? S_IWUSR : 0)
+
+-static int target_attribute_is_visible(struct kobject *kobj,
+- struct attribute *attr, int i)
++static mode_t target_attribute_is_visible(struct kobject *kobj,
++ struct attribute *attr, int i)
{
-- 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 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);
- return snprintf(buf, PAGE_SIZE, "%d\n",
-@@ -367,9 +379,10 @@ lpfc_selective_reset(struct lpfc_hba *phba)
+- 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)
+- return 1;
++ else if (attr == &dev_attr_revalidate.attr)
++ return S_IWUSR;
+
+ return 0;
}
- 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;
+ 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
+ };
-@@ -385,9 +398,10 @@ lpfc_issue_reset(struct class_device *cdev, const char *buf, size_t count)
- }
+@@ -1448,28 +1460,12 @@ static struct attribute_group target_attribute_group = {
- 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)
+ static int spi_target_configure(struct transport_container *tc,
+ struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
{
-- 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 kobject *kobj = &cdev->kobj;
+- int i;
+- struct attribute *attr;
+- int rc;
+-
+- for (i = 0; (attr = target_attributes[i]) != NULL; i++) {
+- int j = target_attribute_group.is_visible(kobj, attr, i);
+-
+- /* FIXME: as well as returning -EEXIST, which we'd like
+- * 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)
+- rc = sysfs_add_file_to_group(kobj, attr,
+- target_attribute_group.name);
+- /* and make the attribute writeable if we have a set
+- * function */
+- if ((j & 1))
+- rc = sysfs_chmod_file(kobj, attr, attr->mode | S_IWUSR);
+- }
++
++ /* force an update based on parameters read from the device */
++ sysfs_update_group(kobj, &target_attribute_group);
-@@ -395,9 +409,10 @@ lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
+ return 0;
}
+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;
- 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)
- }
+- struct class_device_attribute *host_attrs[SRP_HOST_ATTRS + 1];
++ struct device_attribute *host_attrs[SRP_HOST_ATTRS + 1];
- 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 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 = 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,
- }
+ 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
--lpfc_max_rpi_show(struct class_device *cdev, char *buf)
-+lpfc_max_rpi_show(struct device *dev, struct device_attribute *attr,
+-show_srp_rport_id(struct class_device *cdev, char *buf)
++show_srp_rport_id(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)
+- 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
--lpfc_used_rpi_show(struct class_device *cdev, char *buf)
-+lpfc_used_rpi_show(struct device *dev, struct device_attribute *attr,
-+ char *buf)
+-show_srp_rport_roles(struct class_device *cdev, char *buf)
++show_srp_rport_roles(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)
+- 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 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)
+-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)
{
-- 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)
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index 5fe7aae..01cefbb 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
--lpfc_used_xri_show(struct class_device *cdev, char *buf)
-+lpfc_used_xri_show(struct device *dev, struct device_attribute *attr,
-+ char *buf)
+-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_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)
+- 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
--lpfc_max_vpi_show(struct class_device *cdev, char *buf)
-+lpfc_max_vpi_show(struct device *dev, struct device_attribute *attr,
-+ char *buf)
+-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_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)
+- 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
--lpfc_used_vpi_show(struct class_device *cdev, char *buf)
-+lpfc_used_vpi_show(struct device *dev, struct device_attribute *attr,
+-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_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)
+- 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
--lpfc_npiv_info_show(struct class_device *cdev, char *buf)
-+lpfc_npiv_info_show(struct device *dev, struct device_attribute *attr,
-+ char *buf)
+-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_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 scsi_disk *sdkp = to_scsi_disk(cdev);
++ struct scsi_disk *sdkp = to_scsi_disk(dev);
-@@ -601,9 +624,10 @@ lpfc_npiv_info_show(struct class_device *cdev, char *buf)
+ return snprintf(buf, 20, "%u\n", sdkp->DPOFUA);
}
- static ssize_t
--lpfc_poll_show(struct class_device *cdev, char *buf)
-+lpfc_poll_show(struct device *dev, struct device_attribute *attr,
-+ char *buf)
+-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_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 scsi_disk *sdkp = to_scsi_disk(cdev);
++ struct scsi_disk *sdkp = to_scsi_disk(dev);
+ struct scsi_device *sdp = sdkp->device;
-@@ -611,10 +635,10 @@ lpfc_poll_show(struct class_device *cdev, char *buf)
+ return snprintf(buf, 20, "%u\n", sdp->manage_start_stop);
}
- 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)
+-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_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,
+- struct scsi_disk *sdkp = to_scsi_disk(cdev);
++ struct scsi_disk *sdkp = to_scsi_disk(dev);
- #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) \
+ return snprintf(buf, 40, "%d\n", sdkp->device->allow_restart);
+ }
- #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) \
+-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,
+ };
- #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) \
+ 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;
- #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) \
+ mutex_lock(&sd_ref_mutex);
+- class_device_put(&sdkp->cdev);
++ put_device(&sdkp->dev);
+ scsi_device_put(sdev);
+ mutex_unlock(&sd_ref_mutex);
+ }
+@@ -850,7 +860,6 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
- #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) \
+ static void sd_prepare_flush(struct request_queue *q, struct request *rq)
+ {
+- memset(rq->cmd, 0, sizeof(rq->cmd));
+ rq->cmd_type = REQ_TYPE_BLOCK_PC;
+ rq->timeout = SD_TIMEOUT;
+ rq->cmd[0] = SYNCHRONIZE_CACHE;
+@@ -1663,12 +1672,12 @@ static int sd_probe(struct device *dev)
+ sdp->timeout = SD_MOD_TIMEOUT;
+ }
- #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)
+- 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);
- #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)
+- if (class_device_add(&sdkp->cdev))
++ if (device_add(&sdkp->dev))
+ goto out_put;
- #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)
+ get_device(&sdp->sdev_gendev);
+@@ -1734,13 +1743,13 @@ static int sd_remove(struct device *dev)
+ {
+ struct scsi_disk *sdkp = dev_get_drvdata(dev);
- #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)
+- class_device_del(&sdkp->cdev);
++ device_del(&sdkp->dev);
+ del_gendisk(sdkp->disk);
+ sd_shutdown(dev);
- #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)
+ mutex_lock(&sd_ref_mutex);
+ dev_set_drvdata(dev, NULL);
+- class_device_put(&sdkp->cdev);
++ put_device(&sdkp->dev);
+ mutex_unlock(&sd_ref_mutex);
- #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)
+ return 0;
+@@ -1748,16 +1757,16 @@ static int sd_remove(struct device *dev)
- #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)
+ /**
+ * 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;
- #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);
+- 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);
- static char *lpfc_soft_wwn_key = "C99G71SL8032A";
+ if (sdev->host != sed->shost)
+ return 0;
+@@ -407,10 +407,10 @@ static void ses_match_to_enclosure(struct enclosure_device *edev,
- 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)
+ #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_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;
+- 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 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)
+-static void ses_intf_remove(struct class_device *cdev,
++static void ses_intf_remove(struct device *cdev,
+ struct class_interface *intf)
{
-- 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 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;
-@@ -979,9 +1008,10 @@ lpfc_soft_wwpn_show(struct class_device *cdev, char *buf)
+ 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,
- 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;
+ kfree(edev->component[0].scratch);
+
+- class_device_put(&edev->cdev);
++ put_device(&edev->edev);
+ enclosure_unregister(edev);
}
--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)
+ 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..c9d7f72 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_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)
+- 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;
- 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)
+- 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_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)
+- 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);
- return count;
+ 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);
+@@ -2667,7 +2667,6 @@ sg_proc_init(void)
+ {
+ int k, mask;
+ int num_leaves = ARRAY_SIZE(sg_proc_leaf_arr);
+- struct proc_dir_entry *pdep;
+ struct sg_proc_leaf * leaf;
+
+ sg_proc_sgp = proc_mkdir(sg_proc_sg_dirname, NULL);
+@@ -2676,13 +2675,10 @@ sg_proc_init(void)
+ for (k = 0; k < num_leaves; ++k) {
+ leaf = &sg_proc_leaf_arr[k];
+ mask = leaf->fops->write ? S_IRUGO | S_IWUSR : S_IRUGO;
+- pdep = create_proc_entry(leaf->name, mask, sg_proc_sgp);
+- if (pdep) {
+- leaf->fops->owner = THIS_MODULE,
+- leaf->fops->read = seq_read,
+- leaf->fops->llseek = seq_lseek,
+- pdep->proc_fops = leaf->fops;
+- }
++ leaf->fops->owner = THIS_MODULE;
++ leaf->fops->read = seq_read;
++ leaf->fops->llseek = seq_lseek;
++ proc_create(leaf->name, mask, sg_proc_sgp, leaf->fops);
+ }
+ return 0;
}
--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);
+diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
+index 26cfc56..31fe605 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;
- 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");
+- if (hdata->wh.no_sync == 0xff)
+- hdata->wh.no_sync = 0;
++ wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_MHZ(20));
--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);
+ err = request_irq(irq, sgiwd93_intr, 0, "SGI WD93", host);
+ if (err) {
+@@ -312,7 +313,8 @@ static struct platform_driver sgiwd93_driver = {
+ .probe = sgiwd93_probe,
+ .remove = __devexit_p(sgiwd93_remove),
+ .driver = {
+- .name = "sgiwd93"
++ .name = "sgiwd93",
++ .owner = THIS_MODULE,
+ }
+ };
- 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);
+@@ -332,3 +334,4 @@ module_exit(sgiwd93_module_exit);
+ MODULE_DESCRIPTION("SGI WD33C93 driver");
+ MODULE_AUTHOR("Ralf Baechle <ralf at linux-mips.org>");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:sgiwd93");
+diff --git a/drivers/scsi/sni_53c710.c b/drivers/scsi/sni_53c710.c
+index 0a6b45b..2bbef4c 100644
+--- a/drivers/scsi/sni_53c710.c
++++ b/drivers/scsi/sni_53c710.c
+@@ -53,6 +53,7 @@
+ MODULE_AUTHOR("Thomas Bogendörfer");
+ MODULE_DESCRIPTION("SNI RM 53c710 SCSI Driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:snirm_53c710");
- /*
-@@ -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)
+ #define SNIRM710_CLOCK 32
+
+@@ -136,6 +137,7 @@ static struct platform_driver snirm710_driver = {
+ .remove = __devexit_p(snirm710_driver_remove),
+ .driver = {
+ .name = "snirm_53c710",
++ .owner = THIS_MODULE,
+ },
+ };
+
+diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
+index 0a52d9d..e8db66a 100644
+--- a/drivers/scsi/st.c
++++ b/drivers/scsi/st.c
+@@ -17,7 +17,7 @@
+ Last modified: 18-JAN-1998 Richard Gooch <rgooch at atnf.csiro.au> Devfs support
+ */
+
+-static const char *verstr = "20080221";
++static const char *verstr = "20080224";
+
+ #include <linux/module.h>
+
+@@ -183,6 +183,7 @@ static int modes_defined;
+
+ static struct st_buffer *new_tape_buffer(int, int, int);
+ static int enlarge_buffer(struct st_buffer *, int, int);
++static void clear_buffer(struct st_buffer *);
+ static void normalize_buffer(struct st_buffer *);
+ static int append_to_buffer(const char __user *, struct st_buffer *, int);
+ static int from_buffer(struct st_buffer *, char __user *, int);
+@@ -442,6 +443,7 @@ static void st_sleep_done(void *data, char *sense, int result, int resid)
+
+ memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
+ (STp->buffer)->cmdstat.midlevel_result = SRpnt->result = result;
++ (STp->buffer)->cmdstat.residual = resid;
+ DEB( STp->write_pending = 0; )
+
+ if (SRpnt->waiting)
+@@ -626,7 +628,7 @@ static int cross_eof(struct scsi_tape * STp, int forward)
+
+
+ /* Flush the write buffer (never need to write if variable blocksize). */
+-static int flush_write_buffer(struct scsi_tape * STp)
++static int st_flush_write_buffer(struct scsi_tape * STp)
{
-- 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)
+ 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);
- lpfc_vport_param_store(nodev_tmo)
+ if (STp->block_size == 0)
+ return 0;
+@@ -1159,6 +1161,7 @@ static int st_open(struct inode *inode, struct file *filp)
+ goto err_out;
+ }
--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);
++ (STp->buffer)->cleared = 0;
+ (STp->buffer)->writing = 0;
+ (STp->buffer)->syscall_result = 0;
- /*
- # 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)
+@@ -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
}
- 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;
++/* 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 = dev_get_drvdata(dev);
+ ssize_t l = 0;
+
+ l = snprintf(buf, PAGE_SIZE, "%d\n", STm->defined);
+ return l;
}
- 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);
+-CLASS_DEVICE_ATTR(defined, S_IRUGO, st_defined_show, NULL);
++DEVICE_ATTR(defined, S_IRUGO, st_defined_show, NULL);
- /*
-@@ -1497,7 +1530,7 @@ lpfc_link_speed_init(struct lpfc_hba *phba, int val)
+-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 = dev_get_drvdata(dev);
+ ssize_t l = 0;
+
+ l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_blksize);
+ return l;
}
- 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);
+-CLASS_DEVICE_ATTR(default_blksize, S_IRUGO, st_defblk_show, NULL);
++DEVICE_ATTR(default_blksize, S_IRUGO, st_defblk_show, NULL);
- /*
-@@ -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");
+-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 = dev_get_drvdata(dev);
+ ssize_t l = 0;
+ char *fmt;
--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,
- };
+@@ -4320,24 +4355,67 @@ static ssize_t st_defdensity_show(struct class_device *class_dev, char *buf)
+ return l;
+ }
--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,
- };
+-CLASS_DEVICE_ATTR(default_density, S_IRUGO, st_defdensity_show, NULL);
++DEVICE_ATTR(default_density, S_IRUGO, st_defdensity_show, NULL);
-@@ -1707,9 +1739,8 @@ sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr,
- char *buf, loff_t off, size_t count)
+-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)
{
- 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;
+- struct st_modedef *STm = (struct st_modedef *)class_get_devdata(class_dev);
++ struct st_modedef *STm = 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 = 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 @@
-@@ -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;
+ Copyright 1995-2003 Kai Makisara.
-@@ -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,
+- Last modified: Mon Apr 7 22:49:18 2003 by makisara
++ Last modified: Thu Feb 21 21:47:07 2008 by kai.makisara
+ */
- phba->sysfs_mbox.mbox->vport = vport;
+ #ifndef _ST_OPTIONS_H
+@@ -94,6 +94,10 @@
+ The default is BSD semantics. */
+ #define ST_SYSV 0
-- 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;
++/* 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
-- 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;
+diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
+index 654430e..f308a03 100644
+--- a/drivers/scsi/stex.c
++++ b/drivers/scsi/stex.c
+@@ -33,6 +33,7 @@
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi_tcq.h>
+ #include <scsi/scsi_dbg.h>
++#include <scsi/scsi_eh.h>
-- 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;
+ #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;
- 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)
+
+-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 Scsi_Host *shost = lpfc_shost_from_vport(vport);
+ struct st_frame *p;
+ size_t count = sizeof(struct st_frame);
-- 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);
+ 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,
-@@ -2437,9 +2471,11 @@ lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
+ 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);
+ }
- #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,
+ static void stex_ys_commands(struct st_hba *hba,
+ struct st_ccb *ccb, struct status_msg *resp)
{
- 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;
- }
+- size_t count;
-
-+ 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 (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;
-- 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,
+- 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 = {
- /* 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;
+ #include "scsi_module.c"
- /* 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;
++MODULE_LICENSE("GPL");
+diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
+index 06152c7..7514b3a 100644
+--- a/drivers/scsi/sun3x_esp.c
++++ b/drivers/scsi/sun3x_esp.c
+@@ -294,6 +294,7 @@ static struct platform_driver esp_sun3x_driver = {
+ .remove = __devexit_p(esp_sun3x_remove),
+ .driver = {
+ .name = "sun3x_esp",
++ .owner = THIS_MODULE,
+ },
+ };
- 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);
-+ }
+@@ -314,3 +315,4 @@ MODULE_VERSION(DRV_VERSION);
-+ /* 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,
- }
+ module_init(sun3x_esp_init);
+ module_exit(sun3x_esp_exit);
++MODULE_ALIAS("platform:sun3x_esp");
+diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
+index 35142b5..22a6aae 100644
+--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
++++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
+@@ -1647,7 +1647,7 @@ static void sym_flush_comp_queue(struct sym_hcb *np, int cam_status)
+ SYM_QUEHEAD *qp;
+ struct sym_ccb *cp;
+
+- while ((qp = sym_remque_head(&np->comp_ccbq)) != 0) {
++ while ((qp = sym_remque_head(&np->comp_ccbq)) != NULL) {
+ struct scsi_cmnd *cmd;
+ cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
+ sym_insque_tail(&cp->link_ccbq, &np->busy_ccbq);
+@@ -3168,7 +3168,7 @@ int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int
+ * the COMP queue and put back other ones into
+ * the BUSY queue.
+ */
+- while ((qp = sym_remque_head(&qtmp)) != 0) {
++ while ((qp = sym_remque_head(&qtmp)) != NULL) {
+ struct scsi_cmnd *cmd;
+ cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
+ cmd = cp->cmd;
+@@ -5729,7 +5729,7 @@ void sym_hcb_free(struct sym_hcb *np)
+ sym_mfree_dma(np->dqueue, sizeof(u32)*(MAX_QUEUE*2), "DQUEUE");
+
+ if (np->actccbs) {
+- while ((qp = sym_remque_head(&np->free_ccbq)) != 0) {
++ while ((qp = sym_remque_head(&np->free_ccbq)) != NULL) {
+ cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
+ sym_mfree_dma(cp, sizeof(*cp), "CCB");
+ }
+diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
+index 58d7eee..640333b 100644
+--- a/drivers/scsi/u14-34f.c
++++ b/drivers/scsi/u14-34f.c
+@@ -1715,13 +1715,12 @@ static void flush_dev(struct scsi_device *dev, unsigned long cursec, unsigned in
+
+ }
+
+-static irqreturn_t ihdlr(int irq, unsigned int j) {
++static irqreturn_t ihdlr(unsigned int j)
++{
+ struct scsi_cmnd *SCpnt;
+ unsigned int i, k, c, status, tstatus, reg, ret;
+ struct mscp *spp, *cpp;
+-
+- if (sh[j]->irq != irq)
+- panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq);
++ int irq = sh[j]->irq;
+
+ /* Check if this board need to be serviced */
+ if (!((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED)) goto none;
+@@ -1935,7 +1934,7 @@ static irqreturn_t do_interrupt_handler(int irq, void *shap) {
+ if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return IRQ_NONE;
+
+ spin_lock_irqsave(sh[j]->host_lock, spin_flags);
+- ret = ihdlr(irq, j);
++ ret = ihdlr(j);
+ spin_unlock_irqrestore(sh[j]->host_lock, spin_flags);
+ return ret;
+ }
+diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
+index f385dce..27aa40f 100644
+--- a/drivers/scsi/ultrastor.c
++++ b/drivers/scsi/ultrastor.c
+@@ -951,7 +951,7 @@ static int ultrastor_abort(struct scsi_cmnd *SCpnt)
+ printk("abort: command mismatch, %p != %p\n",
+ config.mscp[mscp_index].SCint, SCpnt);
+ #endif
+- if (config.mscp[mscp_index].SCint == 0)
++ if (config.mscp[mscp_index].SCint == NULL)
+ return FAILED;
+
+ if (config.mscp[mscp_index].SCint != SCpnt) panic("Bad abort");
+@@ -1101,7 +1101,7 @@ static void ultrastor_interrupt(void *dev_id)
+ SCtmp = mscp->SCint;
+ mscp->SCint = NULL;
- phba->fc_stat.elsXmitRetry++;
-- if (ndlp && delay) {
-+ if (ndlp && NLP_CHK_NODE_ACT(ndlp) && delay) {
- phba->fc_stat.elsDelayRetry++;
- ndlp->nlp_retry = cmdiocb->retry;
+- if (SCtmp == 0)
++ if (!SCtmp)
+ {
+ #if ULTRASTOR_DEBUG & (UD_ABORT|UD_INTERRUPT)
+ printk("MSCP %d (%x): no command\n", mscp_index, (unsigned int) mscp);
+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 */
-@@ -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,
- }
+ #ifdef PROC_INTERFACE
+ hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS |
+diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
+index 2b8a410..bbf5bc5 100644
+--- a/drivers/serial/68328serial.c
++++ b/drivers/serial/68328serial.c
+@@ -200,7 +200,7 @@ static void rs_stop(struct tty_struct *tty)
+ local_irq_restore(flags);
+ }
- /* 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;
- }
+-static void rs_put_char(char ch)
++static int rs_put_char(char ch)
+ {
+ int flags, loops = 0;
- 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;
+@@ -214,6 +214,7 @@ static void rs_put_char(char ch)
+ UTX_TXDATA = ch;
+ udelay(5);
+ local_irq_restore(flags);
++ return 1;
+ }
- lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
+ static void rs_start(struct tty_struct *tty)
+@@ -1017,18 +1018,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
+ tty_wait_until_sent(tty, 0);
+ send_break(info, arg ? arg*(100) : 250);
+ return 0;
+- case TIOCGSOFTCAR:
+- error = put_user(C_CLOCAL(tty) ? 1 : 0,
+- (unsigned long *) arg);
+- if (error)
+- return error;
+- return 0;
+- case TIOCSSOFTCAR:
+- get_user(arg, (unsigned long *) arg);
+- tty->termios->c_cflag =
+- ((tty->termios->c_cflag & ~CLOCAL) |
+- (arg ? CLOCAL : 0));
+- return 0;
+ case TIOCGSERIAL:
+ if (access_ok(VERIFY_WRITE, (void *) arg,
+ sizeof(struct serial_struct)))
+@@ -1061,9 +1050,6 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+ {
+ struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
-@@ -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 */
--
+- if (tty->termios->c_cflag == old_termios->c_cflag)
+- return;
-
-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;
+ change_speed(info);
-- 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)
+ if ((old_termios->c_cflag & CRTSCTS) &&
+@@ -1140,8 +1126,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
+ uart->ustcnt &= ~(USTCNT_RXEN | USTCNT_RX_INTR_MASK);
+
+ shutdown(info);
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ rs_flush_buffer(tty);
+
+ tty_ldisc_flush(tty);
+ tty->closing = 0;
+diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
+index 2aa6bfe..d9d4e95 100644
+--- a/drivers/serial/68360serial.c
++++ b/drivers/serial/68360serial.c
+@@ -51,6 +51,7 @@ extern int kgdb_output_string (const char* s, unsigned int count);
- rdata = rport->dd_data;
- ndlp = rdata->pnode;
-- if (!ndlp)
-+ if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
- return;
+ /* #ifdef CONFIG_SERIAL_CONSOLE */ /* This seems to be a post 2.0 thing - mles */
+ #include <linux/console.h>
++#include <linux/jiffies.h>
- 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);
+ /* this defines the index into rs_table for the port to use
+ */
+@@ -994,10 +995,10 @@ static void rs_360_put_char(struct tty_struct *tty, unsigned char ch)
+ volatile QUICC_BD *bdp;
+
+ if (serial_paranoia_check(info, tty->name, "rs_put_char"))
+- return;
++ return 0;
+
+ if (!tty)
+- return;
++ return 0;
+
+ bdp = info->tx_cur;
+ while (bdp->status & BD_SC_READY);
+@@ -1015,6 +1016,7 @@ static void rs_360_put_char(struct tty_struct *tty, unsigned char ch)
+ bdp++;
+
+ info->tx_cur = (QUICC_BD *)bdp;
++ return 1;
-@@ -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);
+@@ -1245,7 +1247,7 @@ static int rs_360_tiocmget(struct tty_struct *tty, struct file *file)
+ #ifdef modem_control
+ unsigned char control, status;
- 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);
+- if (serial_paranoia_check(info, tty->name, __FUNCTION__))
++ if (serial_paranoia_check(info, tty->name, __func__))
+ return -ENODEV;
-- del_timer_sync(&phba->fc_estabtmo);
--
- lpfc_can_disctmo(vport);
+ if (tty->flags & (1 << TTY_IO_ERROR))
+@@ -1276,12 +1278,12 @@ static int rs_360_tiocmset(struct tty_struct *tty, struct file *file,
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ unsigned int arg;
- /* 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 (serial_paranoia_check(info, tty->name, __FUNCTION__))
++ if (serial_paranoia_check(info, tty->name, __func__))
+ return -ENODEV;
-- if (ndlp->nlp_DID == 0) {
-- return 0;
-- }
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
-
- /* 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;
++ /* FIXME: locking on info->mcr */
+ if (set & TIOCM_RTS)
+ info->mcr |= UART_MCR_RTS;
+ if (set & TIOCM_DTR)
+@@ -1435,18 +1437,6 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
+ return retval;
+ end_break(info);
+ return 0;
+- case TIOCGSOFTCAR:
+- /* return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg); */
+- put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg);
+- return 0;
+- case TIOCSSOFTCAR:
+- error = get_user(arg, (unsigned int *) arg);
+- if (error)
+- return error;
+- tty->termios->c_cflag =
+- ((tty->termios->c_cflag & ~CLOCAL) |
+- (arg ? CLOCAL : 0));
+- return 0;
+ #ifdef maybe
+ case TIOCSERGETLSR: /* Get line status register */
+ return get_lsr_info(info, (unsigned int *) arg);
+@@ -1664,8 +1654,7 @@ static void rs_360_close(struct tty_struct *tty, struct file * filp)
+ rs_360_wait_until_sent(tty, info->timeout);
+ }
+ shutdown(info);
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ rs_360_flush_buffer(tty);
+ tty_ldisc_flush(tty);
+ tty->closing = 0;
+ info->event = 0;
+@@ -1716,6 +1705,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)
+ printk("jiff=%lu...", jiffies);
+ #endif
+
++ lock_kernel();
+ /* We go through the loop at least once because we can't tell
+ * exactly when the last character exits the shifter. There can
+ * be at least two characters waiting to be sent after the buffers
+@@ -1729,7 +1719,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)
+ msleep_interruptible(jiffies_to_msecs(char_time));
+ if (signal_pending(current))
+ break;
+- if (timeout && ((orig_jiffies + timeout) < jiffies))
++ if (timeout && (time_after(jiffies, orig_jiffies + timeout)))
+ break;
+ /* The 'tx_cur' is really the next buffer to send. We
+ * have to back up to the previous BD and wait for it
+@@ -1744,6 +1734,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)
+ bdp--;
+ } while (bdp->status & BD_SC_READY);
+ current->state = TASK_RUNNING;
++ unlock_kernel();
+ #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+ printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
+ #endif
+diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
+index 77f7a7f..ea41f26 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)
}
+ }
-- 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;
++#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;
+@@ -1814,6 +1868,7 @@ static int serial8250_startup(struct uart_port *port)
+ }
+
+ if (is_real_interrupt(up->port.irq)) {
++ unsigned char iir1;
+ /*
+ * Test for UARTs that do not reassert THRE when the
+ * transmitter is idle and the interrupt has already
+@@ -1827,7 +1882,7 @@ static int serial8250_startup(struct uart_port *port)
+ wait_for_xmitr(up, UART_LSR_THRE);
+ serial_out_sync(up, UART_IER, UART_IER_THRI);
+ udelay(1); /* allow THRE to set */
+- serial_in(up, UART_IIR);
++ iir1 = serial_in(up, UART_IIR);
+ serial_out(up, UART_IER, 0);
+ serial_out_sync(up, UART_IER, UART_IER_THRI);
+ udelay(1); /* allow a working UART time to re-assert THRE */
+@@ -1840,7 +1895,7 @@ static int serial8250_startup(struct uart_port *port)
+ * If the interrupt is not reasserted, setup a timer to
+ * kick the UART on a regular basis.
+ */
+- if (iir & UART_IIR_NO_INT) {
++ if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) {
+ pr_debug("ttyS%d - using backup timer\n", port->line);
+ up->timer.function = serial8250_backup_timeout;
+ up->timer.data = (unsigned long)up;
+@@ -2174,7 +2229,9 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
+ }
+ serial8250_set_mctrl(&up->port, up->port.mctrl);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+- tty_termios_encode_baud_rate(termios, baud, baud);
++ /* Don't rewrite B0 */
++ if (tty_termios_baud_rate(termios))
++ tty_termios_encode_baud_rate(termios, baud, baud);
}
--#if 0
+ static void
+@@ -2386,6 +2443,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/8250_au1x00.c b/drivers/serial/8250_au1x00.c
+deleted file mode 100644
+index 58015fd..0000000
+--- a/drivers/serial/8250_au1x00.c
++++ /dev/null
+@@ -1,100 +0,0 @@
-/*
-- * Search node lists for a remote port matching filter criteria
-- * Caller needs to hold host_lock before calling this routine.
+- * Serial Device Initialisation for Au1x00
+- *
+- * (C) Copyright Embedded Alley Solutions, Inc 2005
+- * Author: Pantelis Antoniou <pantelis at embeddedalley.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.
- */
--struct lpfc_nodelist *
--lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param)
+-
+-#include <linux/errno.h>
+-#include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <linux/ioport.h>
+-#include <linux/module.h>
+-#include <linux/serial_core.h>
+-#include <linux/signal.h>
+-#include <linux/slab.h>
+-#include <linux/types.h>
+-
+-#include <linux/serial_8250.h>
+-
+-#include <asm/mach-au1x00/au1000.h>
+-
+-#include "8250.h"
+-
+-#define PORT(_base, _irq) \
+- { \
+- .iobase = _base, \
+- .membase = (void __iomem *)_base,\
+- .mapbase = CPHYSADDR(_base), \
+- .irq = _irq, \
+- .uartclk = 0, /* filled */ \
+- .regshift = 2, \
+- .iotype = UPIO_AU, \
+- .flags = UPF_SKIP_TEST \
+- }
+-
+-static struct plat_serial8250_port au1x00_data[] = {
+-#if defined(CONFIG_SOC_AU1000)
+- PORT(UART0_ADDR, AU1000_UART0_INT),
+- PORT(UART1_ADDR, AU1000_UART1_INT),
+- PORT(UART2_ADDR, AU1000_UART2_INT),
+- PORT(UART3_ADDR, AU1000_UART3_INT),
+-#elif defined(CONFIG_SOC_AU1500)
+- PORT(UART0_ADDR, AU1500_UART0_INT),
+- PORT(UART3_ADDR, AU1500_UART3_INT),
+-#elif defined(CONFIG_SOC_AU1100)
+- PORT(UART0_ADDR, AU1100_UART0_INT),
+- PORT(UART1_ADDR, AU1100_UART1_INT),
+- /* The internal UART2 does not exist on the AU1100 processor. */
+- PORT(UART3_ADDR, AU1100_UART3_INT),
+-#elif defined(CONFIG_SOC_AU1550)
+- PORT(UART0_ADDR, AU1550_UART0_INT),
+- PORT(UART1_ADDR, AU1550_UART1_INT),
+- PORT(UART3_ADDR, AU1550_UART3_INT),
+-#elif defined(CONFIG_SOC_AU1200)
+- PORT(UART0_ADDR, AU1200_UART0_INT),
+- PORT(UART1_ADDR, AU1200_UART1_INT),
+-#endif
+- { },
+-};
+-
+-static struct platform_device au1x00_device = {
+- .name = "serial8250",
+- .id = PLAT8250_DEV_AU1X00,
+- .dev = {
+- .platform_data = au1x00_data,
+- },
+-};
+-
+-static int __init au1x00_init(void)
-{
-- struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-- struct lpfc_nodelist *ndlp;
+- int i;
+- unsigned int uartclk;
-
-- spin_lock_irq(shost->host_lock);
-- ndlp = __lpfc_find_node(vport, filter, param);
-- spin_unlock_irq(shost->host_lock);
-- return ndlp;
+- /* get uart clock */
+- uartclk = get_au1x00_uart_baud_base() * 16;
+-
+- /* fill up uartclk */
+- for (i = 0; au1x00_data[i].flags ; i++)
+- au1x00_data[i].uartclk = uartclk;
+-
+- return platform_device_register(&au1x00_device);
-}
--#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)
+-/* XXX: Yes, I know this doesn't yet work. */
+-static void __exit au1x00_exit(void)
-{
-- 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;
+- platform_device_unregister(&au1x00_device);
-}
--#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;
- }
+-module_init(au1x00_init);
+-module_exit(au1x00_exit);
+-
+-MODULE_AUTHOR("Pantelis Antoniou <pantelis at embeddedalley.com>");
+-MODULE_DESCRIPTION("8250 serial probe module for Au1x000 cards");
+-MODULE_LICENSE("GPL");
+diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c
+index 38776e8..cd89870 100644
+--- a/drivers/serial/8250_early.c
++++ b/drivers/serial/8250_early.c
+@@ -156,7 +156,7 @@ static int __init parse_options(struct early_serial8250_device *device,
+ port->membase = ioremap(port->mapbase, 64);
+ if (!port->membase) {
+ printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n",
+- __FUNCTION__,
++ __func__,
+ (unsigned long long)port->mapbase);
+ return -ENOMEM;
+ }
+diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
+index f97224c..6e57382 100644
+--- a/drivers/serial/8250_pci.c
++++ b/drivers/serial/8250_pci.c
+@@ -775,7 +775,7 @@ pci_default_setup(struct serial_private *priv, struct pciserial_board *board,
+ * This list is ordered alphabetically by vendor then device.
+ * Specific entries must come before more generic entries.
+ */
+-static struct pci_serial_quirk pci_serial_quirks[] = {
++static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ /*
+ * ADDI-DATA GmbH communication cards <info at addi-data.com>
+ */
+diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
+index cf627cd..36acbcc 100644
+--- a/drivers/serial/Kconfig
++++ b/drivers/serial/Kconfig
+@@ -262,12 +262,12 @@ config SERIAL_8250_ACORN
+ cards. If unsure, say N.
-@@ -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;
+ config SERIAL_8250_AU1X00
+- bool "AU1X00 serial port support"
++ bool "Au1x00 serial port support"
+ depends on SERIAL_8250 != n && SOC_AU1X00
+ help
+- If you have an Au1x00 board and want to use the serial port, say Y
+- to this option. The driver can handle 1 or 2 serial ports.
+- If unsure, say N.
++ If you have an Au1x00 SOC based board and want to use the serial port,
++ say Y to this option. The driver can handle up to 4 serial ports,
++ depending on the SOC. If unsure, say N.
- /* 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;
+ config SERIAL_8250_RM9K
+ bool "Support for MIPS RM9xxx integrated serial port"
+@@ -961,6 +961,9 @@ config SERIAL_CORE
+ config SERIAL_CORE_CONSOLE
+ bool
-- 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);
++config CONSOLE_POLL
++ bool
+
- 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);
+ config SERIAL_68328
+ bool "68328 serial support"
+ depends on M68328 || M68EZ328 || M68VZ328
+@@ -1352,4 +1355,47 @@ config SERIAL_SC26XX_CONSOLE
+ help
+ Support for Console on SC2681/SC2692 serial ports.
-+ 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;
-+ }
++config SERIAL_BFIN_SPORT
++ tristate "Blackfin SPORT emulate UART (EXPERIMENTAL)"
++ depends on BFIN && EXPERIMENTAL
++ select SERIAL_CORE
++ help
++ Enble support SPORT emulate UART on Blackfin series.
+
- 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;
++ To compile this driver as a module, choose M here: the
++ module will be called bfin_sport_uart.
++
++choice
++ prompt "Baud rate for Blackfin SPORT UART"
++ depends on SERIAL_BFIN_SPORT
++ default SERIAL_SPORT_BAUD_RATE_57600
++ help
++ Choose a baud rate for the SPORT UART, other uart settings are
++ 8 bit, 1 stop bit, no parity, no flow control.
++
++config SERIAL_SPORT_BAUD_RATE_115200
++ bool "115200"
++
++config SERIAL_SPORT_BAUD_RATE_57600
++ bool "57600"
++
++config SERIAL_SPORT_BAUD_RATE_38400
++ bool "38400"
++
++config SERIAL_SPORT_BAUD_RATE_19200
++ bool "19200"
++
++config SERIAL_SPORT_BAUD_RATE_9600
++ bool "9600"
++endchoice
++
++config SPORT_BAUD_RATE
++ int
++ depends on SERIAL_BFIN_SPORT
++ default 115200 if (SERIAL_SPORT_BAUD_RATE_115200)
++ default 57600 if (SERIAL_SPORT_BAUD_RATE_57600)
++ default 38400 if (SERIAL_SPORT_BAUD_RATE_38400)
++ default 19200 if (SERIAL_SPORT_BAUD_RATE_19200)
++ default 9600 if (SERIAL_SPORT_BAUD_RATE_9600)
++
+ endmenu
+diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
+index 640cfe4..0d9c09b 100644
+--- a/drivers/serial/Makefile
++++ b/drivers/serial/Makefile
+@@ -20,7 +20,6 @@ obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o
+ obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o
+ obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
+ obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
+-obj-$(CONFIG_SERIAL_8250_AU1X00) += 8250_au1x00.o
+ obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
+ obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
+ obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
+@@ -28,6 +27,7 @@ obj-$(CONFIG_SERIAL_PXA) += pxa.o
+ obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
+ obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
+ obj-$(CONFIG_SERIAL_BFIN) += bfin_5xx.o
++obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o
+ obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
+ obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
+ obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o
+@@ -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);
}
--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)
++#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)
{
- 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;
+ 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
+ };
- /* 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;
+ static struct uart_amba_port *amba_ports[UART_NR];
+diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
+index 55492fa..c065a70 100644
+--- a/drivers/serial/atmel_serial.c
++++ b/drivers/serial/atmel_serial.c
+@@ -96,7 +96,6 @@
+
+ /* PDC registers */
+ #define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
+-#define UART_GET_TCR(port) __raw_readl((port)->membase + ATMEL_PDC_TCR)
+ #define UART_GET_PTSR(port) __raw_readl((port)->membase + ATMEL_PDC_PTSR)
- 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)
+ #define UART_PUT_RPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RPR)
+diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
+index 46bb47f..8a2f6a1 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;
- pci_set_master(pdev);
+- 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
-- /* 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);
+-#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
-+ /* 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;
-+ }
+- 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)
+ }
- /* 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 (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;
+ }
-- if (lpfc_online(phba) == 0) {
-- mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
-- }
-+ lpfc_online(phba);
+- 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 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);
+ 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);
- 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);
- }
+- 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:
+@@ -766,7 +762,7 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
+ break;
+ default:
+ printk(KERN_ERR "%s: word lengh not supported\n",
+- __FUNCTION__);
++ __func__);
}
-@@ -869,8 +872,11 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
+ if (termios->c_cflag & CSTOPB)
+@@ -806,10 +802,6 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
- 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;
- }
+ UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15);
-- 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);
+- 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;
+ }
- 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);
++/*
++ * 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,
+@@ -1012,7 +1029,7 @@ bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud,
-- 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;
+ *baud = get_sclk() / (16*(dll | dlh << 8));
+ }
+- pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __FUNCTION__, *baud, *parity, *bits);
++ pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __func__, *baud, *parity, *bits);
+ }
+ #endif
- 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];
+@@ -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,
+ };
-+ if (!pnode || !NLP_CHK_NODE_ACT(pnode))
+@@ -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/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c
+new file mode 100644
+index 0000000..aca1240
+--- /dev/null
++++ b/drivers/serial/bfin_sport_uart.c
+@@ -0,0 +1,614 @@
++/*
++ * File: linux/drivers/serial/bfin_sport_uart.c
++ *
++ * Based on: drivers/serial/bfin_5xx.c by Aubrey Li.
++ * Author: Roy Huang <roy.huang at analog.com>
++ *
++ * Created: Nov 22, 2006
++ * Copyright: (c) 2006-2007 Analog Devices Inc.
++ * Description: this driver enable SPORTs on Blackfin emulate UART.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see the file COPYING, or write
++ * to the Free Software Foundation, Inc.,
++ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * This driver and the hardware supported are in term of EE-191 of ADI.
++ * http://www.analog.com/UploadedFiles/Application_Notes/399447663EE191.pdf
++ * This application note describe how to implement a UART on a Sharc DSP,
++ * but this driver is implemented on Blackfin Processor.
++ */
++
++/* After reset, there is a prelude of low level pulse when transmit data first
++ * time. No addtional pulse in following transmit.
++ * According to document:
++ * The SPORTs are ready to start transmitting or receiving data no later than
++ * three serial clock cycles after they are enabled in the SPORTx_TCR1 or
++ * SPORTx_RCR1 register. No serial clock cycles are lost from this point on.
++ * The first internal frame sync will occur one frame sync delay after the
++ * SPORTs are ready. External frame syncs can occur as soon as the SPORT is
++ * ready.
++ */
++
++/* Thanks to Axel Alatalo <axel at rubico.se> for fixing sport rx bug. Sometimes
++ * sport receives data incorrectly. The following is Axel's words.
++ * As EE-191, sport rx samples 3 times of the UART baudrate and takes the
++ * middle smaple of every 3 samples as the data bit. For a 8-N-1 UART setting,
++ * 30 samples will be required for a byte. If transmitter sends a 1/3 bit short
++ * byte due to buadrate drift, then the 30th sample of a byte, this sample is
++ * also the third sample of the stop bit, will happens on the immediately
++ * following start bit which will be thrown away and missed. Thus since parts
++ * of the startbit will be missed and the receiver will begin to drift, the
++ * effect accumulates over time until synchronization is lost.
++ * If only require 2 samples of the stopbit (by sampling in total 29 samples),
++ * then a to short byte as in the case above will be tolerated. Then the 1/3
++ * early startbit will trigger a framesync since the last read is complete
++ * after only 2/3 stopbit and framesync is active during the last 1/3 looking
++ * for a possible early startbit. */
++
++//#define DEBUG
++
++#include <linux/module.h>
++#include <linux/ioport.h>
++#include <linux/init.h>
++#include <linux/console.h>
++#include <linux/sysrq.h>
++#include <linux/platform_device.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/serial_core.h>
++
++#include <asm/delay.h>
++#include <asm/portmux.h>
++
++#include "bfin_sport_uart.h"
++
++unsigned short bfin_uart_pin_req_sport0[] =
++ {P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, \
++ P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0};
++
++unsigned short bfin_uart_pin_req_sport1[] =
++ {P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, \
++ P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0};
++
++#define DRV_NAME "bfin-sport-uart"
++
++struct sport_uart_port {
++ struct uart_port port;
++ char *name;
++
++ int tx_irq;
++ int rx_irq;
++ int err_irq;
++};
++
++static void sport_uart_tx_chars(struct sport_uart_port *up);
++static void sport_stop_tx(struct uart_port *port);
++
++static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value)
++{
++ pr_debug("%s value:%x\n", __FUNCTION__, value);
++ /* Place a Start and Stop bit */
++ __asm__ volatile (
++ "R2 = b#01111111100;\n\t"
++ "R3 = b#10000000001;\n\t"
++ "%0 <<= 2;\n\t"
++ "%0 = %0 & R2;\n\t"
++ "%0 = %0 | R3;\n\t"
++ :"=r"(value)
++ :"0"(value)
++ :"R2", "R3");
++ pr_debug("%s value:%x\n", __FUNCTION__, value);
++
++ SPORT_PUT_TX(up, value);
++}
++
++static inline unsigned int rx_one_byte(struct sport_uart_port *up)
++{
++ unsigned int value, extract;
++
++ value = SPORT_GET_RX32(up);
++ pr_debug("%s value:%x\n", __FUNCTION__, value);
++
++ /* Extract 8 bits data */
++ __asm__ volatile (
++ "R5 = 0;\n\t"
++ "P0 = 8;\n\t"
++ "R1 = 0x1801(Z);\n\t"
++ "R3 = 0x0300(Z);\n\t"
++ "R4 = 0;\n\t"
++ "LSETUP(loop_s, loop_e) LC0 = P0;\nloop_s:\t"
++ "R2 = extract(%1, R1.L)(Z);\n\t"
++ "R2 <<= R4;\n\t"
++ "R5 = R5 | R2;\n\t"
++ "R1 = R1 - R3;\nloop_e:\t"
++ "R4 += 1;\n\t"
++ "%0 = R5;\n\t"
++ :"=r"(extract)
++ :"r"(value)
++ :"P0", "R1", "R2","R3","R4", "R5");
++
++ pr_debug(" extract:%x\n", extract);
++ return extract;
++}
++
++static int sport_uart_setup(struct sport_uart_port *up, int sclk, int baud_rate)
++{
++ int tclkdiv, tfsdiv, rclkdiv;
++
++ /* Set TCR1 and TCR2 */
++ SPORT_PUT_TCR1(up, (LTFS | ITFS | TFSR | TLSBIT | ITCLK));
++ SPORT_PUT_TCR2(up, 10);
++ pr_debug("%s TCR1:%x, TCR2:%x\n", __FUNCTION__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up));
++
++ /* Set RCR1 and RCR2 */
++ SPORT_PUT_RCR1(up, (RCKFE | LARFS | LRFS | RFSR | IRCLK));
++ SPORT_PUT_RCR2(up, 28);
++ pr_debug("%s RCR1:%x, RCR2:%x\n", __FUNCTION__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up));
++
++ tclkdiv = sclk/(2 * baud_rate) - 1;
++ tfsdiv = 12;
++ rclkdiv = sclk/(2 * baud_rate * 3) - 1;
++ SPORT_PUT_TCLKDIV(up, tclkdiv);
++ SPORT_PUT_TFSDIV(up, tfsdiv);
++ SPORT_PUT_RCLKDIV(up, rclkdiv);
++ SSYNC();
++ pr_debug("%s sclk:%d, baud_rate:%d, tclkdiv:%d, tfsdiv:%d, rclkdiv:%d\n",
++ __FUNCTION__, sclk, baud_rate, tclkdiv, tfsdiv, rclkdiv);
++
++ return 0;
++}
++
++static irqreturn_t sport_uart_rx_irq(int irq, void *dev_id)
++{
++ struct sport_uart_port *up = dev_id;
++ struct tty_struct *tty = up->port.info->tty;
++ unsigned int ch;
++
++ do {
++ ch = rx_one_byte(up);
++ up->port.icount.rx++;
++
++ if (uart_handle_sysrq_char(&up->port, ch))
++ ;
++ else
++ tty_insert_flip_char(tty, ch, TTY_NORMAL);
++ } while (SPORT_GET_STAT(up) & RXNE);
++ tty_flip_buffer_push(tty);
++
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t sport_uart_tx_irq(int irq, void *dev_id)
++{
++ sport_uart_tx_chars(dev_id);
++
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t sport_uart_err_irq(int irq, void *dev_id)
++{
++ struct sport_uart_port *up = dev_id;
++ struct tty_struct *tty = up->port.info->tty;
++ unsigned int stat = SPORT_GET_STAT(up);
++
++ /* Overflow in RX FIFO */
++ if (stat & ROVF) {
++ up->port.icount.overrun++;
++ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
++ SPORT_PUT_STAT(up, ROVF); /* Clear ROVF bit */
++ }
++ /* These should not happen */
++ if (stat & (TOVF | TUVF | RUVF)) {
++ printk(KERN_ERR "SPORT Error:%s %s %s\n",
++ (stat & TOVF)?"TX overflow":"",
++ (stat & TUVF)?"TX underflow":"",
++ (stat & RUVF)?"RX underflow":"");
++ SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN);
++ SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN);
++ }
++ SSYNC();
++
++ return IRQ_HANDLED;
++}
++
++/* Reqeust IRQ, Setup clock */
++static int sport_startup(struct uart_port *port)
++{
++ struct sport_uart_port *up = (struct sport_uart_port *)port;
++ char buffer[20];
++ int retval;
++
++ pr_debug("%s enter\n", __FUNCTION__);
++ memset(buffer, 20, '\0');
++ snprintf(buffer, 20, "%s rx", up->name);
++ retval = request_irq(up->rx_irq, sport_uart_rx_irq, IRQF_SAMPLE_RANDOM, buffer, up);
++ if (retval) {
++ printk(KERN_ERR "Unable to request interrupt %s\n", buffer);
++ return retval;
++ }
++
++ snprintf(buffer, 20, "%s tx", up->name);
++ retval = request_irq(up->tx_irq, sport_uart_tx_irq, IRQF_SAMPLE_RANDOM, buffer, up);
++ if (retval) {
++ printk(KERN_ERR "Unable to request interrupt %s\n", buffer);
++ goto fail1;
++ }
++
++ snprintf(buffer, 20, "%s err", up->name);
++ retval = request_irq(up->err_irq, sport_uart_err_irq, IRQF_SAMPLE_RANDOM, buffer, up);
++ if (retval) {
++ printk(KERN_ERR "Unable to request interrupt %s\n", buffer);
++ goto fail2;
++ }
++
++ if (port->line) {
++ if (peripheral_request_list(bfin_uart_pin_req_sport1, DRV_NAME))
++ goto fail3;
++ } else {
++ if (peripheral_request_list(bfin_uart_pin_req_sport0, DRV_NAME))
++ goto fail3;
++ }
++
++ sport_uart_setup(up, get_sclk(), port->uartclk);
++
++ /* Enable receive interrupt */
++ SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) | RSPEN));
++ SSYNC();
++
++ return 0;
++
++
++fail3:
++ printk(KERN_ERR DRV_NAME
++ ": Requesting Peripherals failed\n");
++
++ free_irq(up->err_irq, up);
++fail2:
++ free_irq(up->tx_irq, up);
++fail1:
++ free_irq(up->rx_irq, up);
++
++ return retval;
++
++}
++
++static void sport_uart_tx_chars(struct sport_uart_port *up)
++{
++ struct circ_buf *xmit = &up->port.info->xmit;
++
++ if (SPORT_GET_STAT(up) & TXF)
+ 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 (up->port.x_char) {
++ tx_one_byte(up, up->port.x_char);
++ up->port.icount.tx++;
++ up->port.x_char = 0;
++ return;
++ }
++
++ if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
++ sport_stop_tx(&up->port);
++ return;
++ }
++
++ while(!(SPORT_GET_STAT(up) & TXF) && !uart_circ_empty(xmit)) {
++ tx_one_byte(up, xmit->buf[xmit->tail]);
++ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE -1);
++ up->port.icount.tx++;
++ }
++
++ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
++ uart_write_wakeup(&up->port);
++}
++
++static unsigned int sport_tx_empty(struct uart_port *port)
++{
++ struct sport_uart_port *up = (struct sport_uart_port *)port;
++ unsigned int stat;
++
++ stat = SPORT_GET_STAT(up);
++ pr_debug("%s stat:%04x\n", __FUNCTION__, stat);
++ if (stat & TXHRE) {
++ return TIOCSER_TEMT;
++ } else
++ return 0;
++}
++
++static unsigned int sport_get_mctrl(struct uart_port *port)
++{
++ pr_debug("%s enter\n", __FUNCTION__);
++ return (TIOCM_CTS | TIOCM_CD | TIOCM_DSR);
++}
++
++static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl)
++{
++ pr_debug("%s enter\n", __FUNCTION__);
++}
++
++static void sport_stop_tx(struct uart_port *port)
++{
++ struct sport_uart_port *up = (struct sport_uart_port *)port;
++ unsigned int stat;
++
++ pr_debug("%s enter\n", __FUNCTION__);
++
++ stat = SPORT_GET_STAT(up);
++ while(!(stat & TXHRE)) {
++ udelay(1);
++ stat = SPORT_GET_STAT(up);
++ }
++ /* Although the hold register is empty, last byte is still in shift
++ * register and not sent out yet. If baud rate is lower than default,
++ * delay should be longer. For example, if the baud rate is 9600,
++ * the delay must be at least 2ms by experience */
++ udelay(500);
++
++ SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN));
++ SSYNC();
++
++ return;
++}
++
++static void sport_start_tx(struct uart_port *port)
++{
++ struct sport_uart_port *up = (struct sport_uart_port *)port;
++
++ pr_debug("%s enter\n", __FUNCTION__);
++ /* Write data into SPORT FIFO before enable SPROT to transmit */
++ sport_uart_tx_chars(up);
++
++ /* Enable transmit, then an interrupt will generated */
++ SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN));
++ SSYNC();
++ pr_debug("%s exit\n", __FUNCTION__);
++}
++
++static void sport_stop_rx(struct uart_port *port)
++{
++ struct sport_uart_port *up = (struct sport_uart_port *)port;
++
++ pr_debug("%s enter\n", __FUNCTION__);
++ /* Disable sport to stop rx */
++ SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN));
++ SSYNC();
++}
++
++static void sport_enable_ms(struct uart_port *port)
++{
++ pr_debug("%s enter\n", __FUNCTION__);
++}
++
++static void sport_break_ctl(struct uart_port *port, int break_state)
++{
++ pr_debug("%s enter\n", __FUNCTION__);
++}
++
++static void sport_shutdown(struct uart_port *port)
++{
++ struct sport_uart_port *up = (struct sport_uart_port *)port;
++
++ pr_debug("%s enter\n", __FUNCTION__);
++
++ /* Disable sport */
++ SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN));
++ SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN));
++ SSYNC();
++
++ if (port->line) {
++ peripheral_free_list(bfin_uart_pin_req_sport1);
++ } else {
++ peripheral_free_list(bfin_uart_pin_req_sport0);
++ }
++
++ free_irq(up->rx_irq, up);
++ free_irq(up->tx_irq, up);
++ free_irq(up->err_irq, up);
++}
++
++static void sport_set_termios(struct uart_port *port,
++ struct termios *termios, struct termios *old)
++{
++ pr_debug("%s enter, c_cflag:%08x\n", __FUNCTION__, termios->c_cflag);
++ uart_update_timeout(port, CS8 ,port->uartclk);
++}
++
++static const char *sport_type(struct uart_port *port)
++{
++ struct sport_uart_port *up = (struct sport_uart_port *)port;
++
++ pr_debug("%s enter\n", __FUNCTION__);
++ return up->name;
++}
++
++static void sport_release_port(struct uart_port *port)
++{
++ pr_debug("%s enter\n", __FUNCTION__);
++}
++
++static int sport_request_port(struct uart_port *port)
++{
++ pr_debug("%s enter\n", __FUNCTION__);
++ return 0;
++}
++
++static void sport_config_port(struct uart_port *port, int flags)
++{
++ struct sport_uart_port *up = (struct sport_uart_port *)port;
++
++ pr_debug("%s enter\n", __FUNCTION__);
++ up->port.type = PORT_BFIN_SPORT;
++}
++
++static int sport_verify_port(struct uart_port *port, struct serial_struct *ser)
++{
++ pr_debug("%s enter\n", __FUNCTION__);
++ return 0;
++}
++
++struct uart_ops sport_uart_ops = {
++ .tx_empty = sport_tx_empty,
++ .set_mctrl = sport_set_mctrl,
++ .get_mctrl = sport_get_mctrl,
++ .stop_tx = sport_stop_tx,
++ .start_tx = sport_start_tx,
++ .stop_rx = sport_stop_rx,
++ .enable_ms = sport_enable_ms,
++ .break_ctl = sport_break_ctl,
++ .startup = sport_startup,
++ .shutdown = sport_shutdown,
++ .set_termios = sport_set_termios,
++ .type = sport_type,
++ .release_port = sport_release_port,
++ .request_port = sport_request_port,
++ .config_port = sport_config_port,
++ .verify_port = sport_verify_port,
++};
++
++static struct sport_uart_port sport_uart_ports[] = {
++ { /* SPORT 0 */
++ .name = "SPORT0",
++ .tx_irq = IRQ_SPORT0_TX,
++ .rx_irq = IRQ_SPORT0_RX,
++ .err_irq= IRQ_SPORT0_ERROR,
++ .port = {
++ .type = PORT_BFIN_SPORT,
++ .iotype = UPIO_MEM,
++ .membase = (void __iomem *)SPORT0_TCR1,
++ .mapbase = SPORT0_TCR1,
++ .irq = IRQ_SPORT0_RX,
++ .uartclk = CONFIG_SPORT_BAUD_RATE,
++ .fifosize = 8,
++ .ops = &sport_uart_ops,
++ .line = 0,
++ },
++ }, { /* SPORT 1 */
++ .name = "SPORT1",
++ .tx_irq = IRQ_SPORT1_TX,
++ .rx_irq = IRQ_SPORT1_RX,
++ .err_irq= IRQ_SPORT1_ERROR,
++ .port = {
++ .type = PORT_BFIN_SPORT,
++ .iotype = UPIO_MEM,
++ .membase = (void __iomem *)SPORT1_TCR1,
++ .mapbase = SPORT1_TCR1,
++ .irq = IRQ_SPORT1_RX,
++ .uartclk = CONFIG_SPORT_BAUD_RATE,
++ .fifosize = 8,
++ .ops = &sport_uart_ops,
++ .line = 1,
++ },
++ }
++};
++
++static struct uart_driver sport_uart_reg = {
++ .owner = THIS_MODULE,
++ .driver_name = "SPORT-UART",
++ .dev_name = "ttySS",
++ .major = 204,
++ .minor = 84,
++ .nr = ARRAY_SIZE(sport_uart_ports),
++ .cons = NULL,
++};
++
++static int sport_uart_suspend(struct platform_device *dev, pm_message_t state)
++{
++ struct sport_uart_port *sport = platform_get_drvdata(dev);
++
++ pr_debug("%s enter\n", __FUNCTION__);
++ if (sport)
++ uart_suspend_port(&sport_uart_reg, &sport->port);
++
++ return 0;
++}
++
++static int sport_uart_resume(struct platform_device *dev)
++{
++ struct sport_uart_port *sport = platform_get_drvdata(dev);
++
++ pr_debug("%s enter\n", __FUNCTION__);
++ if (sport)
++ uart_resume_port(&sport_uart_reg, &sport->port);
++
++ return 0;
++}
++
++static int sport_uart_probe(struct platform_device *dev)
++{
++ pr_debug("%s enter\n", __FUNCTION__);
++ sport_uart_ports[dev->id].port.dev = &dev->dev;
++ uart_add_one_port(&sport_uart_reg, &sport_uart_ports[dev->id].port);
++ platform_set_drvdata(dev, &sport_uart_ports[dev->id]);
++
++ return 0;
++}
++
++static int sport_uart_remove(struct platform_device *dev)
++{
++ struct sport_uart_port *sport = platform_get_drvdata(dev);
++
++ pr_debug("%s enter\n", __FUNCTION__);
++ platform_set_drvdata(dev, NULL);
++
++ if (sport)
++ uart_remove_one_port(&sport_uart_reg, &sport->port);
++
++ return 0;
++}
++
++static struct platform_driver sport_uart_driver = {
++ .probe = sport_uart_probe,
++ .remove = sport_uart_remove,
++ .suspend = sport_uart_suspend,
++ .resume = sport_uart_resume,
++ .driver = {
++ .name = DRV_NAME,
++ },
++};
++
++static int __init sport_uart_init(void)
++{
++ int ret;
++
++ pr_debug("%s enter\n", __FUNCTION__);
++ ret = uart_register_driver(&sport_uart_reg);
++ if (ret != 0) {
++ printk(KERN_ERR "Failed to register %s:%d\n",
++ sport_uart_reg.driver_name, ret);
++ return ret;
++ }
++
++ ret = platform_driver_register(&sport_uart_driver);
++ if (ret != 0) {
++ printk(KERN_ERR "Failed to register sport uart driver:%d\n", ret);
++ uart_unregister_driver(&sport_uart_reg);
++ }
++
++
++ pr_debug("%s exit\n", __FUNCTION__);
++ return ret;
++}
++
++static void __exit sport_uart_exit(void)
++{
++ pr_debug("%s enter\n", __FUNCTION__);
++ platform_driver_unregister(&sport_uart_driver);
++ uart_unregister_driver(&sport_uart_reg);
++}
++
++module_init(sport_uart_init);
++module_exit(sport_uart_exit);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/serial/bfin_sport_uart.h b/drivers/serial/bfin_sport_uart.h
+new file mode 100644
+index 0000000..671d41c
+--- /dev/null
++++ b/drivers/serial/bfin_sport_uart.h
+@@ -0,0 +1,63 @@
++/*
++ * File: linux/drivers/serial/bfin_sport_uart.h
++ *
++ * Based on: include/asm-blackfin/mach-533/bfin_serial_5xx.h
++ * Author: Roy Huang <roy.huang>analog.com>
++ *
++ * Created: Nov 22, 2006
++ * Copyright: (C) Analog Device Inc.
++ * Description: this driver enable SPORTs on Blackfin emulate UART.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see the file COPYING, or write
++ * to the Free Software Foundation, Inc.,
++ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++
++#define OFFSET_TCR1 0x00 /* Transmit Configuration 1 Register */
++#define OFFSET_TCR2 0x04 /* Transmit Configuration 2 Register */
++#define OFFSET_TCLKDIV 0x08 /* Transmit Serial Clock Divider Register */
++#define OFFSET_TFSDIV 0x0C /* Transmit Frame Sync Divider Register */
++#define OFFSET_TX 0x10 /* Transmit Data Register */
++#define OFFSET_RX 0x18 /* Receive Data Register */
++#define OFFSET_RCR1 0x20 /* Receive Configuration 1 Register */
++#define OFFSET_RCR2 0x24 /* Receive Configuration 2 Register */
++#define OFFSET_RCLKDIV 0x28 /* Receive Serial Clock Divider Register */
++#define OFFSET_RFSDIV 0x2c /* Receive Frame Sync Divider Register */
++#define OFFSET_STAT 0x30 /* Status Register */
++
++#define SPORT_GET_TCR1(sport) bfin_read16(((sport)->port.membase + OFFSET_TCR1))
++#define SPORT_GET_TCR2(sport) bfin_read16(((sport)->port.membase + OFFSET_TCR2))
++#define SPORT_GET_TCLKDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_TCLKDIV))
++#define SPORT_GET_TFSDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_TFSDIV))
++#define SPORT_GET_TX(sport) bfin_read16(((sport)->port.membase + OFFSET_TX))
++#define SPORT_GET_RX(sport) bfin_read16(((sport)->port.membase + OFFSET_RX))
++#define SPORT_GET_RX32(sport) bfin_read32(((sport)->port.membase + OFFSET_RX))
++#define SPORT_GET_RCR1(sport) bfin_read16(((sport)->port.membase + OFFSET_RCR1))
++#define SPORT_GET_RCR2(sport) bfin_read16(((sport)->port.membase + OFFSET_RCR2))
++#define SPORT_GET_RCLKDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_RCLKDIV))
++#define SPORT_GET_RFSDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_RFSDIV))
++#define SPORT_GET_STAT(sport) bfin_read16(((sport)->port.membase + OFFSET_STAT))
++
++#define SPORT_PUT_TCR1(sport, v) bfin_write16(((sport)->port.membase + OFFSET_TCR1), v)
++#define SPORT_PUT_TCR2(sport, v) bfin_write16(((sport)->port.membase + OFFSET_TCR2), v)
++#define SPORT_PUT_TCLKDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_TCLKDIV), v)
++#define SPORT_PUT_TFSDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_TFSDIV), v)
++#define SPORT_PUT_TX(sport, v) bfin_write16(((sport)->port.membase + OFFSET_TX), v)
++#define SPORT_PUT_RX(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RX), v)
++#define SPORT_PUT_RCR1(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RCR1), v)
++#define SPORT_PUT_RCR2(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RCR2), v)
++#define SPORT_PUT_RCLKDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RCLKDIV), v)
++#define SPORT_PUT_RFSDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RFSDIV), v)
++#define SPORT_PUT_STAT(sport, v) bfin_write16(((sport)->port.membase + OFFSET_STAT), v)
+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];
-- 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;
+ /* 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..a19dc7e 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;
+ }
- 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;
+ 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);
-- if (!rdata->pnode)
-+ if (!rdata->pnode || !NLP_CHK_NODE_ACT(rdata->pnode))
- return FAILED;
+ out_pram:
+- iounmap(pram);
++ cpm_uart_unmap_pram(pinfo, pram);
+ out_mem:
+ iounmap(mem);
+ return ret;
+@@ -1118,7 +1117,7 @@ int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
- 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;
+ line = cpm_uart_id2nr(idx);
+ if(line < 0) {
+- printk(KERN_ERR"%s(): port %d is not registered", __FUNCTION__, idx);
++ printk(KERN_ERR"%s(): port %d is not registered", __func__, idx);
+ return -EINVAL;
}
-@@ -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);
+diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+index 6ea0366..74f1432 100644
+--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
++++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+@@ -45,6 +45,8 @@
+ #include <linux/serial_core.h>
+ #include <linux/kernel.h>
-@@ -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;
++#include <linux/of.h>
++
+ #include "cpm_uart.h"
+
+ /**************************************************************/
+@@ -54,6 +56,18 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
+ {
+ cpm_command(port->command, cmd);
}
-@@ -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;
-+ }
-+ }
++void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port,
++ struct device_node *np)
++{
++ return of_iomap(np, 1);
++}
++
++void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram)
++{
++ iounmap(pram);
++}
++
+ #else
+ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
+ {
+diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+index d9af06a..bb862e2 100644
+--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
++++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+@@ -41,6 +41,9 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/fs_pd.h>
++#ifdef CONFIG_PPC_CPM_NEW_BINDING
++#include <asm/prom.h>
++#endif
- 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;
- }
+ #include <linux/serial_core.h>
+ #include <linux/kernel.h>
+@@ -54,6 +57,55 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
+ {
+ cpm_command(port->command, cmd);
+ }
++
++void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port,
++ struct device_node *np)
++{
++ void __iomem *pram;
++ unsigned long offset;
++ struct resource res;
++ unsigned long len;
++
++ /* Don't remap parameter RAM if it has already been initialized
++ * during console setup.
++ */
++ if (IS_SMC(port) && port->smcup)
++ return port->smcup;
++ else if (!IS_SMC(port) && port->sccup)
++ return port->sccup;
++
++ if (of_address_to_resource(np, 1, &res))
++ return NULL;
++
++ len = 1 + res.end - res.start;
++ pram = ioremap(res.start, len);
++ if (!pram)
++ return NULL;
++
++ if (!IS_SMC(port))
++ return pram;
++
++ if (len != 2) {
++ printk(KERN_WARNING "cpm_uart[%d]: device tree references "
++ "SMC pram, using boot loader/wrapper pram mapping. "
++ "Please fix your device tree to reference the pram "
++ "base register instead.\n",
++ port->port.line);
++ return pram;
++ }
++
++ offset = cpm_dpalloc(PROFF_SMC_SIZE, 64);
++ out_be16(pram, offset);
++ iounmap(pram);
++ return cpm_muram_addr(offset);
++}
++
++void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram)
++{
++ if (!IS_SMC(port))
++ iounmap(pram);
++}
++
+ #else
+ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
+ {
+diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
+index 383c4e6..f9fa237 100644
+--- a/drivers/serial/crisv10.c
++++ b/drivers/serial/crisv10.c
+@@ -1788,7 +1788,7 @@ static unsigned int handle_descr_data(struct e100_serial *info,
+
+ if (info->recv_cnt + recvl > 65536) {
+ printk(KERN_CRIT
+- "%s: Too much pending incoming serial data! Dropping %u bytes.\n", __FUNCTION__, recvl);
++ "%s: Too much pending incoming serial data! Dropping %u bytes.\n", __func__, recvl);
+ return 0;
}
--
- /* 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;
-+ }
+@@ -1801,7 +1801,7 @@ static unsigned int handle_descr_data(struct e100_serial *info,
+ append_recv_buffer(info, buffer);
-- spin_lock_irqsave(&phba->hbalock, drvr_flag);
- psli = &phba->sli;
+ if (!(buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE)))
+- panic("%s: Failed to allocate memory for receive buffer!\n", __FUNCTION__);
++ panic("%s: Failed to allocate memory for receive buffer!\n", __func__);
+
+ descr->buf = virt_to_phys(buffer->buffer);
+
+@@ -1925,7 +1925,7 @@ static int start_recv_dma(struct e100_serial *info)
+ /* Set up the receiving descriptors */
+ for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++) {
+ if (!(buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE)))
+- panic("%s: Failed to allocate memory for receive buffer!\n", __FUNCTION__);
++ panic("%s: Failed to allocate memory for receive buffer!\n", __func__);
+
+ descr[i].ctrl = d_int;
+ descr[i].buf = virt_to_phys(buffer->buffer);
+@@ -3581,6 +3581,9 @@ rs_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+ {
+ struct e100_serial *info = (struct e100_serial *)tty->driver_data;
++ unsigned long flags;
++
++ local_irq_save(flags);
+
+ if (clear & TIOCM_RTS)
+ e100_rts(info, 0);
+@@ -3601,6 +3604,8 @@ rs_tiocmset(struct tty_struct *tty, struct file *file,
+ e100_ri_out(info, 1);
+ if (set & TIOCM_CD)
+ e100_cd_out(info, 1);
++
++ local_irq_restore(flags);
+ return 0;
+ }
+
+@@ -3609,6 +3614,9 @@ rs_tiocmget(struct tty_struct *tty, struct file *file)
+ {
+ struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+ unsigned int result;
++ unsigned long flags;
++
++ local_irq_save(flags);
+
+ result =
+ (!E100_RTS_GET(info) ? TIOCM_RTS : 0)
+@@ -3618,6 +3626,8 @@ rs_tiocmget(struct tty_struct *tty, struct file *file)
+ | (!E100_CD_GET(info) ? TIOCM_CAR : 0)
+ | (!E100_CTS_GET(info) ? TIOCM_CTS : 0);
+
++ local_irq_restore(flags);
++
+ #ifdef SERIAL_DEBUG_IO
+ printk(KERN_DEBUG "ser%i: modem state: %i 0x%08X\n",
+ info->line, result, result);
+@@ -3695,10 +3705,6 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+ {
+ struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+- if (tty->termios->c_cflag == old_termios->c_cflag &&
+- tty->termios->c_iflag == old_termios->c_iflag)
+- return;
-
- mb = &pmbox->mb;
- status = MBX_SUCCESS;
+ change_speed(info);
-@@ -2717,14 +2728,14 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+ /* Handle turning off CRTSCTS */
+@@ -3801,10 +3807,8 @@ rs_close(struct tty_struct *tty, struct file * filp)
+ #endif
- /* Mbox command <mbxCommand> cannot issue */
- LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
-- return MBX_NOT_FINISHED;
-+ goto out_not_finished;
+ shutdown(info);
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
+- if (tty->ldisc.flush_buffer)
+- tty->ldisc.flush_buffer(tty);
++ rs_flush_buffer(tty);
++ tty_ldisc_flush_buffer(tty);
+ tty->closing = 0;
+ info->event = 0;
+ info->tty = 0;
+@@ -3878,6 +3882,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+ * Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO
+ * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k)
+ */
++ lock_kernel();
+ orig_jiffies = jiffies;
+ while (info->xmit.head != info->xmit.tail || /* More in send queue */
+ (*info->ostatusadr & 0x007f) || /* more in FIFO */
+@@ -3894,6 +3899,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+ curr_time_usec - info->last_tx_active_usec;
}
+ set_current_state(TASK_RUNNING);
++ unlock_kernel();
+ }
- 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;
- }
+ /*
+@@ -4513,7 +4519,7 @@ rs_init(void)
- 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)
+ if (request_irq(SERIAL_IRQ_NBR, ser_interrupt,
+ IRQF_SHARED | IRQF_DISABLED, "serial ", driver))
+- panic("%s: Failed to request irq8", __FUNCTION__);
++ panic("%s: Failed to request irq8", __func__);
+
+ #endif
+ #endif /* CONFIG_SVINTO_SIM */
+diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
+index 116211f..0dddd68 100644
+--- a/drivers/serial/dz.c
++++ b/drivers/serial/dz.c
+@@ -819,7 +819,7 @@ static void dz_console_putchar(struct uart_port *uport, int ch)
+ dz_out(dport, DZ_TCR, mask);
+ iob();
+ udelay(2);
+- } while (loops--);
++ } while (--loops);
- /* Mbox command <mbxCommand> cannot issue */
- LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
-- return MBX_NOT_FINISHED;
-+ goto out_not_finished;
- }
+ if (loops) /* Cannot send otherwise. */
+ dz_out(dport, DZ_TDR, ch);
+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
- if (!(psli->sli_flag & LPFC_SLI2_ACTIVE)) {
- spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
- /* Mbox command <mbxCommand> cannot issue */
- LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
-- return MBX_NOT_FINISHED;
-+ goto out_not_finished;
- }
+-#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;
- /* Another mailbox command is still being processed, queue this
-@@ -2792,7 +2803,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
- spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
- /* Mbox command <mbxCommand> cannot issue */
- LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
-- return MBX_NOT_FINISHED;
-+ goto out_not_finished;
- }
- /* timeout active mbox command */
- mod_timer(&psli->mbox_tmo, (jiffies +
-@@ -2900,7 +2911,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
- psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
- spin_unlock_irqrestore(&phba->hbalock,
- drvr_flag);
-- return MBX_NOT_FINISHED;
-+ goto out_not_finished;
- }
+- rx = readl(sport->port.membase + URXD0);
+ spin_lock_irqsave(&sport->port.lock,flags);
- /* 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)
+- do {
++ while (readl(sport->port.membase + USR2) & USR2_RDR) {
+ flg = TTY_NORMAL;
+ sport->port.icount.rx++;
- spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
- return status;
++ rx = readl(sport->port.membase + URXD0);
+
-+out_not_finished:
-+ if (processing_queue) {
-+ pmbox->mb.mbxStatus = MBX_NOT_FINISHED;
-+ lpfc_mbox_cmpl_put(phba, pmbox);
+ 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);
+ }
-+ return MBX_NOT_FINISHED;
+
+ 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;
}
/*
-@@ -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);
+@@ -546,7 +531,7 @@ static int imx_startup(struct uart_port *port)
+ writel(USR1_RTSD, sport->port.membase + USR1);
-+ /* 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);
+ 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);
- 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;
+ 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);
}
-@@ -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;
- }
+ /*
+@@ -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");
-+ spin_lock(&phba->hbalock);
- if ((work_ha_copy & HA_MBATT) &&
- (phba->sli.mbox_active)) {
- pmb = phba->sli.mbox_active;
-@@ -4184,6 +4207,7 @@ lpfc_intr_handler(int irq, void *dev_id)
- /* First check out the status word */
- lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t));
- if (pmbox->mbxOwner != OWN_HOST) {
-+ spin_unlock(&phba->hbalock);
- /*
- * Stray Mailbox Interrupt, mbxCommand <cmd>
- * mbxStatus <status>
-@@ -4199,10 +4223,10 @@ lpfc_intr_handler(int irq, void *dev_id)
- /* clear mailbox attention bit */
- work_ha_copy &= ~HA_MBATT;
- } else {
-+ phba->sli.mbox_active = NULL;
-+ spin_unlock(&phba->hbalock);
- phba->last_completion_time = jiffies;
- del_timer(&phba->sli.mbox_tmo);
--
-- phba->sli.mbox_active = NULL;
- if (pmb->mbox_cmpl) {
- lpfc_sli_pcimem_bcopy(mbox, pmbox,
- MAILBOX_CMD_SIZE);
-@@ -4237,10 +4261,15 @@ lpfc_intr_handler(int irq, void *dev_id)
- pmb->context1 = mp;
- pmb->context2 = ndlp;
- pmb->vport = vport;
-- spin_lock(&phba->hbalock);
-- phba->sli.sli_flag &=
-- ~LPFC_SLI_MBOX_ACTIVE;
-- spin_unlock(&phba->hbalock);
-+ rc = lpfc_sli_issue_mbox(phba,
-+ pmb,
-+ MBX_NOWAIT);
-+ if (rc != MBX_BUSY)
-+ lpfc_printf_log(phba,
-+ KERN_ERR,
-+ LOG_MBOX | LOG_SLI,
-+ "0306 rc should have"
-+ "been MBX_BUSY");
- goto send_current_mbox;
- }
- }
-@@ -4250,25 +4279,20 @@ lpfc_intr_handler(int irq, void *dev_id)
- spin_unlock(&phba->pport->work_port_lock);
- lpfc_mbox_cmpl_put(phba, pmb);
- }
-- }
-+ } else
-+ spin_unlock(&phba->hbalock);
- if ((work_ha_copy & HA_MBATT) &&
- (phba->sli.mbox_active == NULL)) {
--send_next_mbox:
-- spin_lock(&phba->hbalock);
-- phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
-- pmb = lpfc_mbox_get(phba);
-- spin_unlock(&phba->hbalock);
- send_current_mbox:
- /* Process next mailbox command if there is one */
-- if (pmb != NULL) {
-- rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
-- if (rc == MBX_NOT_FINISHED) {
-- pmb->mb.mbxStatus = MBX_NOT_FINISHED;
-- lpfc_mbox_cmpl_put(phba, pmb);
-- goto send_next_mbox;
-- }
-- }
--
-+ do {
-+ rc = lpfc_sli_issue_mbox(phba, NULL,
-+ MBX_NOWAIT);
-+ } while (rc == MBX_NOT_FINISHED);
-+ if (rc != MBX_SUCCESS)
-+ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX |
-+ LOG_SLI, "0349 rc should be "
-+ "MBX_SUCCESS");
- }
+- return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
+- "imx-uart") != NULL ? 0 : -EBUSY;
++ return ret ? 0 : -EBUSY;
+ }
- 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. *
- *******************************************************************/
+ /*
+@@ -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/ioc3_serial.c b/drivers/serial/ioc3_serial.c
+index 168073f..4f1af71 100644
+--- a/drivers/serial/ioc3_serial.c
++++ b/drivers/serial/ioc3_serial.c
+@@ -52,7 +52,7 @@ static unsigned int Submodule_slot;
+ #define DPRINT_CONFIG(_x...) ;
+ //#define DPRINT_CONFIG(_x...) printk _x
+ #define NOT_PROGRESS() ;
+-//#define NOT_PROGRESS() printk("%s : fails %d\n", __FUNCTION__, __LINE__)
++//#define NOT_PROGRESS() printk("%s : fails %d\n", __func__, __LINE__)
+
+ /* number of characters we want to transmit to the lower level at a time */
+ #define MAX_CHARS 256
+@@ -445,7 +445,7 @@ static int inline port_init(struct ioc3_port *port)
+ sbbr_h = &idd->vma->sbbr_h;
+ ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf;
+ DPRINT_CONFIG(("%s: ring_pci_addr 0x%p\n",
+- __FUNCTION__, (void *)ring_pci_addr));
++ __func__, (void *)ring_pci_addr));
+
+ writel((unsigned int)((uint64_t) ring_pci_addr >> 32), sbbr_h);
+ writel((unsigned int)ring_pci_addr | BUF_SIZE_BIT, sbbr_l);
+@@ -593,7 +593,7 @@ config_port(struct ioc3_port *port,
+
+ DPRINT_CONFIG(("%s: line %d baud %d byte_size %d stop %d parenb %d "
+ "parodd %d\n",
+- __FUNCTION__, ((struct uart_port *)port->ip_port)->line,
++ __func__, ((struct uart_port *)port->ip_port)->line,
+ baud, byte_size, stop_bits, parenb, parodd));
--#define LPFC_DRIVER_VERSION "8.2.5"
-+#define LPFC_DRIVER_VERSION "8.2.6"
+ if (set_baud(port, baud))
+@@ -871,14 +871,14 @@ static int ioc3_set_proto(struct ioc3_port *port, int proto)
+ default:
+ case PROTO_RS232:
+ /* Clear the appropriate GIO pin */
+- DPRINT_CONFIG(("%s: rs232\n", __FUNCTION__));
++ DPRINT_CONFIG(("%s: rs232\n", __func__));
+ writel(0, (&port->ip_idd->vma->gppr[0]
+ + hooks->rs422_select_pin));
+ break;
+
+ case PROTO_RS422:
+ /* Set the appropriate GIO pin */
+- DPRINT_CONFIG(("%s: rs422\n", __FUNCTION__));
++ DPRINT_CONFIG(("%s: rs422\n", __func__));
+ writel(1, (&port->ip_idd->vma->gppr[0]
+ + hooks->rs422_select_pin));
+ break;
+@@ -988,7 +988,7 @@ ioc3_change_speed(struct uart_port *the_port,
+ }
+ baud = uart_get_baud_rate(the_port, new_termios, old_termios,
+ MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED);
+- DPRINT_CONFIG(("%s: returned baud %d for line %d\n", __FUNCTION__, baud,
++ DPRINT_CONFIG(("%s: returned baud %d for line %d\n", __func__, baud,
+ the_port->line));
+
+ if (!the_port->fifosize)
+@@ -1026,7 +1026,7 @@ ioc3_change_speed(struct uart_port *the_port,
+ DPRINT_CONFIG(("%s : port 0x%p line %d cflag 0%o "
+ "config_port(baud %d data %d stop %d penable %d "
+ " parity %d), notification 0x%x\n",
+- __FUNCTION__, (void *)port, the_port->line, cflag, baud,
++ __func__, (void *)port, the_port->line, cflag, baud,
+ new_data, new_stop, new_parity_enable, new_parity,
+ the_port->ignore_status_mask));
+
+@@ -1919,7 +1919,7 @@ static inline int ioc3_serial_core_attach( struct ioc3_submodule *is,
+ struct pci_dev *pdev = idd->pdev;
+
+ DPRINT_CONFIG(("%s: attach pdev 0x%p - card_ptr 0x%p\n",
+- __FUNCTION__, pdev, (void *)card_ptr));
++ __func__, pdev, (void *)card_ptr));
- #define LPFC_DRIVER_NAME "lpfc"
+ if (!card_ptr)
+ return -ENODEV;
+@@ -1933,7 +1933,7 @@ static inline int ioc3_serial_core_attach( struct ioc3_submodule *is,
+ port->ip_port = the_port;
-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
- };
+ DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p [%d/%d]\n",
+- __FUNCTION__, (void *)the_port, (void *)port,
++ __func__, (void *)the_port, (void *)port,
+ phys_port, ii));
+
+ /* membase, iobase and mapbase just need to be non-0 */
+@@ -1950,7 +1950,7 @@ static inline int ioc3_serial_core_attach( struct ioc3_submodule *is,
+ if (uart_add_one_port(&ioc3_uart, the_port) < 0) {
+ printk(KERN_WARNING
+ "%s: unable to add port %d bus %d\n",
+- __FUNCTION__, the_port->line, pdev->bus->number);
++ __func__, the_port->line, pdev->bus->number);
+ } else {
+ DPRINT_CONFIG(("IOC3 serial port %d irq %d bus %d\n",
+ the_port->line, the_port->irq, pdev->bus->number));
+@@ -2017,7 +2017,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
+ struct ioc3_port *ports[PORTS_PER_CARD];
+ int phys_port;
+
+- DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, is, idd));
++ DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __func__, is, idd));
+
+ card_ptr = kzalloc(sizeof(struct ioc3_card), GFP_KERNEL);
+ if (!card_ptr) {
+@@ -2067,7 +2067,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
+
+ DPRINT_CONFIG(("%s : Port A ip_serial_regs 0x%p "
+ "ip_uart_regs 0x%p\n",
+- __FUNCTION__,
++ __func__,
+ (void *)port->ip_serial_regs,
+ (void *)port->ip_uart_regs));
+
+@@ -2082,7 +2082,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
+ DPRINT_CONFIG(("%s : Port A ip_cpu_ringbuf 0x%p "
+ "ip_dma_ringbuf 0x%p, ip_inring 0x%p "
+ "ip_outring 0x%p\n",
+- __FUNCTION__,
++ __func__,
+ (void *)port->ip_cpu_ringbuf,
+ (void *)port->ip_dma_ringbuf,
+ (void *)port->ip_inring,
+@@ -2094,7 +2094,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
+
+ DPRINT_CONFIG(("%s : Port B ip_serial_regs 0x%p "
+ "ip_uart_regs 0x%p\n",
+- __FUNCTION__,
++ __func__,
+ (void *)port->ip_serial_regs,
+ (void *)port->ip_uart_regs));
+
+@@ -2108,7 +2108,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
+ DPRINT_CONFIG(("%s : Port B ip_cpu_ringbuf 0x%p "
+ "ip_dma_ringbuf 0x%p, ip_inring 0x%p "
+ "ip_outring 0x%p\n",
+- __FUNCTION__,
++ __func__,
+ (void *)port->ip_cpu_ringbuf,
+ (void *)port->ip_dma_ringbuf,
+ (void *)port->ip_inring,
+@@ -2116,7 +2116,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
+ }
-diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h
-index fef9ac9..f62ed46 100644
---- a/drivers/scsi/megaraid/mega_common.h
-+++ b/drivers/scsi/megaraid/mega_common.h
-@@ -28,7 +28,6 @@
- #include <linux/list.h>
- #include <linux/moduleparam.h>
- #include <linux/dma-mapping.h>
--#include <asm/semaphore.h>
- #include <scsi/scsi.h>
- #include <scsi/scsi_cmnd.h>
- #include <scsi/scsi_device.h>
-diff --git a/drivers/scsi/megaraid/megaraid_ioctl.h b/drivers/scsi/megaraid/megaraid_ioctl.h
-index 706fa05..05f6e4e 100644
---- a/drivers/scsi/megaraid/megaraid_ioctl.h
-+++ b/drivers/scsi/megaraid/megaraid_ioctl.h
-@@ -18,7 +18,7 @@
- #define _MEGARAID_IOCTL_H_
+ DPRINT_CONFIG(("%s : port %d [addr 0x%p] card_ptr 0x%p",
+- __FUNCTION__,
++ __func__,
+ phys_port, (void *)port, (void *)card_ptr));
+ DPRINT_CONFIG((" ip_serial_regs 0x%p ip_uart_regs 0x%p\n",
+ (void *)port->ip_serial_regs,
+@@ -2127,7 +2127,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
- #include <linux/types.h>
--#include <asm/semaphore.h>
-+#include <linux/semaphore.h>
+ DPRINT_CONFIG(("%s: phys_port %d port 0x%p inring 0x%p "
+ "outring 0x%p\n",
+- __FUNCTION__,
++ __func__,
+ phys_port, (void *)port,
+ (void *)port->ip_inring,
+ (void *)port->ip_outring));
+@@ -2170,7 +2170,7 @@ static int __devinit ioc3uart_init(void)
+ if ((ret = uart_register_driver(&ioc3_uart)) < 0) {
+ printk(KERN_WARNING
+ "%s: Couldn't register IOC3 uart serial driver\n",
+- __FUNCTION__);
++ __func__);
+ return ret;
+ }
+ ret = ioc3_register_submodule(&ioc3uart_submodule);
+diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
+index 0c17938..49b8a82 100644
+--- a/drivers/serial/ioc4_serial.c
++++ b/drivers/serial/ioc4_serial.c
+@@ -889,7 +889,7 @@ static int inline port_init(struct ioc4_port *port)
+
+ ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf;
+ DPRINT_CONFIG(("%s: ring_pci_addr 0x%lx\n",
+- __FUNCTION__, ring_pci_addr));
++ __func__, ring_pci_addr));
+
+ writel((unsigned int)((uint64_t)ring_pci_addr >> 32), sbbr_h);
+ writel((unsigned int)ring_pci_addr | IOC4_BUF_SIZE_BIT, sbbr_l);
+@@ -1028,7 +1028,7 @@ static irqreturn_t ioc4_intr(int irq, void *arg)
+ spin_lock_irqsave(&soft->is_ir_lock, flag);
+ printk ("%s : %d : mem 0x%p sio_ir 0x%x sio_ies 0x%x "
+ "other_ir 0x%x other_ies 0x%x mask 0x%x\n",
+- __FUNCTION__, __LINE__,
++ __func__, __LINE__,
+ (void *)mem, readl(&mem->sio_ir.raw),
+ readl(&mem->sio_ies.raw),
+ readl(&mem->other_ir.raw),
+@@ -1155,14 +1155,14 @@ static int inline ioc4_attach_local(struct ioc4_driver_data *idd)
+ (TOTAL_RING_BUF_SIZE - 1)) == 0));
+ DPRINT_CONFIG(("%s : ip_cpu_ringbuf 0x%p "
+ "ip_dma_ringbuf 0x%p\n",
+- __FUNCTION__,
++ __func__,
+ (void *)port->ip_cpu_ringbuf,
+ (void *)port->ip_dma_ringbuf));
+ port->ip_inring = RING(port, RX_0_OR_2);
+ port->ip_outring = RING(port, TX_0_OR_2);
+ }
+ DPRINT_CONFIG(("%s : port %d [addr 0x%p] control 0x%p",
+- __FUNCTION__,
++ __func__,
+ port_number, (void *)port, (void *)control));
+ DPRINT_CONFIG((" ip_serial_regs 0x%p ip_uart_regs 0x%p\n",
+ (void *)port->ip_serial_regs,
+@@ -1173,7 +1173,7 @@ static int inline ioc4_attach_local(struct ioc4_driver_data *idd)
- #include "mbox_defs.h"
+ DPRINT_CONFIG(("%s: port_number %d port 0x%p inring 0x%p "
+ "outring 0x%p\n",
+- __FUNCTION__,
++ __func__,
+ port_number, (void *)port,
+ (void *)port->ip_inring,
+ (void *)port->ip_outring));
+@@ -1317,7 +1317,7 @@ config_port(struct ioc4_port *port,
+ int spiniter = 0;
+
+ DPRINT_CONFIG(("%s: baud %d byte_size %d stop %d parenb %d parodd %d\n",
+- __FUNCTION__, baud, byte_size, stop_bits, parenb, parodd));
++ __func__, baud, byte_size, stop_bits, parenb, parodd));
-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 *);
+ if (set_baud(port, baud))
+ return 1;
+@@ -1725,7 +1725,7 @@ ioc4_change_speed(struct uart_port *the_port,
+ }
+ baud = uart_get_baud_rate(the_port, new_termios, old_termios,
+ MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED);
+- DPRINT_CONFIG(("%s: returned baud %d\n", __FUNCTION__, baud));
++ DPRINT_CONFIG(("%s: returned baud %d\n", __func__, baud));
+
+ /* default is 9600 */
+ if (!baud)
+@@ -1765,7 +1765,7 @@ ioc4_change_speed(struct uart_port *the_port,
+ DPRINT_CONFIG(("%s : port 0x%p cflag 0%o "
+ "config_port(baud %d data %d stop %d p enable %d parity %d),"
+ " notification 0x%x\n",
+- __FUNCTION__, (void *)port, cflag, baud, new_data, new_stop,
++ __func__, (void *)port, cflag, baud, new_data, new_stop,
+ new_parity_enable, new_parity, the_port->ignore_status_mask));
+
+ if ((config_port(port, baud, /* baud */
+@@ -2715,7 +2715,7 @@ ioc4_serial_core_attach(struct pci_dev *pdev, int port_type)
+
+
+ DPRINT_CONFIG(("%s: attach pdev 0x%p - control 0x%p\n",
+- __FUNCTION__, pdev, (void *)control));
++ __func__, pdev, (void *)control));
- static void megaraid_mbox_dpc(unsigned long);
+ if (!control)
+ return -ENODEV;
+@@ -2734,7 +2734,7 @@ ioc4_serial_core_attach(struct pci_dev *pdev, int port_type)
+ port->ip_all_ports[port_type_idx] = the_port;
--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 *);
+ DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p : type %s\n",
+- __FUNCTION__, (void *)the_port,
++ __func__, (void *)the_port,
+ (void *)port,
+ port_type == PROTO_RS232 ? "rs232" : "rs422"));
- 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)
+@@ -2752,7 +2752,7 @@ ioc4_serial_core_attach(struct pci_dev *pdev, int port_type)
+ if (uart_add_one_port(u_driver, the_port) < 0) {
+ printk(KERN_WARNING
+ "%s: unable to add port %d bus %d\n",
+- __FUNCTION__, the_port->line, pdev->bus->number);
++ __func__, the_port->line, pdev->bus->number);
+ } else {
+ DPRINT_CONFIG(
+ ("IOC4 serial port %d irq = %d, bus %d\n",
+@@ -2777,7 +2777,7 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd)
+ int ret = 0;
--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,
- };
+- DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, idd->idd_pdev,
++ DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __func__, idd->idd_pdev,
+ idd->idd_pci_id));
-@@ -4063,9 +4063,10 @@ megaraid_sysfs_get_ldmap(adapter_t *adapter)
- * handle, since we do not interface with applications directly.
+ /* PCI-RT does not bring out serial connections.
+@@ -2806,7 +2806,7 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd)
+ goto out2;
+ }
+ DPRINT_CONFIG(("%s : mem 0x%p, serial 0x%p\n",
+- __FUNCTION__, (void *)idd->idd_misc_regs,
++ __func__, (void *)idd->idd_misc_regs,
+ (void *)serial));
+
+ /* Get memory for the new card */
+@@ -2858,7 +2858,7 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd)
+ } else {
+ printk(KERN_WARNING
+ "%s : request_irq fails for IRQ 0x%x\n ",
+- __FUNCTION__, idd->idd_pdev->irq);
++ __func__, idd->idd_pdev->irq);
+ }
+ ret = ioc4_attach_local(idd);
+ if (ret)
+@@ -2911,13 +2911,13 @@ int ioc4_serial_init(void)
+ if ((ret = uart_register_driver(&ioc4_uart_rs232)) < 0) {
+ printk(KERN_WARNING
+ "%s: Couldn't register rs232 IOC4 serial driver\n",
+- __FUNCTION__);
++ __func__);
+ return ret;
+ }
+ if ((ret = uart_register_driver(&ioc4_uart_rs422)) < 0) {
+ printk(KERN_WARNING
+ "%s: Couldn't register rs422 IOC4 serial driver\n",
+- __FUNCTION__);
++ __func__);
+ return ret;
+ }
+
+diff --git a/drivers/serial/kgdboc.c b/drivers/serial/kgdboc.c
+new file mode 100644
+index 0000000..eadc1ab
+--- /dev/null
++++ b/drivers/serial/kgdboc.c
+@@ -0,0 +1,170 @@
++/*
++ * Based on the same principle as kgdboe using the NETPOLL api, this
++ * driver uses a console polling api to implement a gdb serial inteface
++ * which is multiplexed on a console port.
++ *
++ * Maintainer: Jason Wessel <jason.wessel at windriver.com>
++ *
++ * 2007-2008 (c) Jason Wessel - Wind River Systems, Inc.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++#include <linux/kernel.h>
++#include <linux/ctype.h>
++#include <linux/kgdb.h>
++#include <linux/tty.h>
++
++#define MAX_CONFIG_LEN 40
++
++static struct kgdb_io kgdboc_io_ops;
++
++/* -1 = init not run yet, 0 = unconfigured, 1 = configured. */
++static int configured = -1;
++
++static char config[MAX_CONFIG_LEN];
++static struct kparam_string kps = {
++ .string = config,
++ .maxlen = MAX_CONFIG_LEN,
++};
++
++static struct tty_driver *kgdb_tty_driver;
++static int kgdb_tty_line;
++
++static int kgdboc_option_setup(char *opt)
++{
++ if (strlen(opt) > MAX_CONFIG_LEN) {
++ printk(KERN_ERR "kgdboc: config string too long\n");
++ return -ENOSPC;
++ }
++ strcpy(config, opt);
++
++ return 0;
++}
++
++__setup("kgdboc=", kgdboc_option_setup);
++
++static int configure_kgdboc(void)
++{
++ struct tty_driver *p;
++ int tty_line = 0;
++ int err;
++
++ err = kgdboc_option_setup(config);
++ if (err || !strlen(config) || isspace(config[0]))
++ goto noconfig;
++
++ err = -ENODEV;
++
++ p = tty_find_polling_driver(config, &tty_line);
++ if (!p)
++ goto noconfig;
++
++ kgdb_tty_driver = p;
++ kgdb_tty_line = tty_line;
++
++ err = kgdb_register_io_module(&kgdboc_io_ops);
++ if (err)
++ goto noconfig;
++
++ configured = 1;
++
++ return 0;
++
++noconfig:
++ config[0] = 0;
++ configured = 0;
++
++ return err;
++}
++
++static int __init init_kgdboc(void)
++{
++ /* Already configured? */
++ if (configured == 1)
++ return 0;
++
++ return configure_kgdboc();
++}
++
++static void cleanup_kgdboc(void)
++{
++ if (configured == 1)
++ kgdb_unregister_io_module(&kgdboc_io_ops);
++}
++
++static int kgdboc_get_char(void)
++{
++ return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver,
++ kgdb_tty_line);
++}
++
++static void kgdboc_put_char(u8 chr)
++{
++ kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver,
++ kgdb_tty_line, chr);
++}
++
++static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp)
++{
++ int len = strlen(kmessage);
++
++ if (len >= MAX_CONFIG_LEN) {
++ printk(KERN_ERR "kgdboc: config string too long\n");
++ return -ENOSPC;
++ }
++
++ /* Only copy in the string if the init function has not run yet */
++ if (configured < 0) {
++ strcpy(config, kmessage);
++ return 0;
++ }
++
++ if (kgdb_connected) {
++ printk(KERN_ERR
++ "kgdboc: Cannot reconfigure while KGDB is connected.\n");
++
++ return -EBUSY;
++ }
++
++ strcpy(config, kmessage);
++ /* Chop out \n char as a result of echo */
++ if (config[len - 1] == '\n')
++ config[len - 1] = '\0';
++
++ if (configured == 1)
++ cleanup_kgdboc();
++
++ /* Go and configure with the new params. */
++ return configure_kgdboc();
++}
++
++static void kgdboc_pre_exp_handler(void)
++{
++ /* Increment the module count when the debugger is active */
++ if (!kgdb_connected)
++ try_module_get(THIS_MODULE);
++}
++
++static void kgdboc_post_exp_handler(void)
++{
++ /* decrement the module count when the debugger detaches */
++ if (!kgdb_connected)
++ module_put(THIS_MODULE);
++}
++
++static struct kgdb_io kgdboc_io_ops = {
++ .name = "kgdboc",
++ .read_char = kgdboc_get_char,
++ .write_char = kgdboc_put_char,
++ .pre_exception = kgdboc_pre_exp_handler,
++ .post_exception = kgdboc_post_exp_handler,
++};
++
++module_init(init_kgdboc);
++module_exit(cleanup_kgdboc);
++module_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644);
++MODULE_PARM_DESC(kgdboc, "<serial_device>[,baud]");
++MODULE_DESCRIPTION("KGDB Console TTY Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
+index 99af084..43af40d 100644
+--- a/drivers/serial/mcfserial.c
++++ b/drivers/serial/mcfserial.c
+@@ -40,7 +40,6 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/system.h>
+-#include <asm/semaphore.h>
+ #include <asm/delay.h>
+ #include <asm/coldfire.h>
+ #include <asm/mcfsim.h>
+@@ -1073,18 +1072,6 @@ static int mcfrs_ioctl(struct tty_struct *tty, struct file * file,
+ tty_wait_until_sent(tty, 0);
+ send_break(info, arg ? arg*(HZ/10) : HZ/4);
+ return 0;
+- case TIOCGSOFTCAR:
+- error = put_user(C_CLOCAL(tty) ? 1 : 0,
+- (unsigned long *) arg);
+- if (error)
+- return error;
+- return 0;
+- case TIOCSSOFTCAR:
+- get_user(arg, (unsigned long *) arg);
+- tty->termios->c_cflag =
+- ((tty->termios->c_cflag & ~CLOCAL) |
+- (arg ? CLOCAL : 0));
+- return 0;
+ case TIOCGSERIAL:
+ if (access_ok(VERIFY_WRITE, (void *) arg,
+ sizeof(struct serial_struct)))
+@@ -1223,8 +1210,7 @@ static void mcfrs_close(struct tty_struct *tty, struct file * filp)
+ } else
+ #endif
+ shutdown(info);
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ mcfrs_flush_buffer(tty);
+ tty_ldisc_flush(tty);
+
+ tty->closing = 0;
+@@ -1277,6 +1263,8 @@ mcfrs_wait_until_sent(struct tty_struct *tty, int timeout)
+ * Note: we have to use pretty tight timings here to satisfy
+ * the NIST-PCTS.
+ */
++ lock_kernel();
++
+ fifo_time = (MCF5272_FIFO_SIZE * HZ * 10) / info->baud;
+ char_time = fifo_time / 5;
+ if (char_time == 0)
+@@ -1313,6 +1301,7 @@ mcfrs_wait_until_sent(struct tty_struct *tty, int timeout)
+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
+ break;
+ }
++ unlock_kernel();
+ #else
+ /*
+ * For the other coldfire models, assume all data has been sent
+@@ -1908,7 +1897,7 @@ static struct tty_driver *mcfrs_console_device(struct console *c, int *index)
+ * This is used for console output.
*/
- 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)
+
+-void mcfrs_put_char(char ch)
++int mcfrs_put_char(char ch)
{
-- 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;
+ volatile unsigned char *uartp;
+ unsigned long flags;
+@@ -1932,7 +1921,7 @@ void mcfrs_put_char(char ch)
+ mcfrs_init_console(); /* try and get it back */
+ local_irq_restore(flags);
-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,
+- return;
++ return 1;
+ }
- /**
- * 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)
+diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
+index d93b357..7a3625f 100644
+--- a/drivers/serial/mpc52xx_uart.c
++++ b/drivers/serial/mpc52xx_uart.c
+@@ -1221,8 +1221,8 @@ static struct of_device_id mpc52xx_uart_of_match[] = {
+ #endif
+ #ifdef CONFIG_PPC_MPC512x
+ { .compatible = "fsl,mpc5121-psc-uart", .data = &mpc512x_psc_ops, },
+- {},
+ #endif
++ {},
+ };
+
+ static int __devinit
+diff --git a/drivers/serial/netx-serial.c b/drivers/serial/netx-serial.c
+index 3123ffe..81ac9bb 100644
+--- a/drivers/serial/netx-serial.c
++++ b/drivers/serial/netx-serial.c
+@@ -287,6 +287,7 @@ static void netx_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
- int num_cnt;
- int sge_bytes;
-@@ -504,13 +507,22 @@ static u32 megasas_get_frame_count(u8 sge_count)
- sizeof(struct megasas_sge32);
+ unsigned int val;
- /*
-- * 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;
-+ }
++ /* FIXME: Locking needed ? */
+ if (mctrl & TIOCM_RTS) {
+ val = readl(port->membase + UART_RTS_CR);
+ writel(val | RTS_CR_RTS, port->membase + UART_RTS_CR);
+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;
- 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);
+ 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,
- 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);
+ 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 cmd->frame_count;
+ return 0;
}
-@@ -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);
+diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
+index 4ffa258..2b6a013 100644
+--- a/drivers/serial/s3c2410.c
++++ b/drivers/serial/s3c2410.c
+@@ -1022,6 +1022,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
+ struct uart_port *port = &ourport->port;
+ struct s3c2410_uartcfg *cfg;
+ struct resource *res;
++ int ret;
-- max_wait = 10;
-+ max_wait = 60;
- cur_state = MFI_STATE_OPERATIONAL;
- break;
+ dbg("s3c24xx_serial_init_port: port=%p, platdev=%p\n", port, platdev);
-@@ -1980,7 +1993,8 @@ static int megasas_init_mfi(struct megasas_instance *instance)
+@@ -1064,9 +1065,11 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
- 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;
+ port->mapbase = res->start;
+ port->membase = S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART);
+- port->irq = platform_get_irq(platdev, 0);
+- if (port->irq < 0)
++ ret = platform_get_irq(platdev, 0);
++ if (ret < 0)
+ port->irq = 0;
++ else
++ port->irq = ret;
- memset(kbuff_arr, 0, sizeof(kbuff_arr));
+ ourport->clk = clk_get(&platdev->dev, "uart");
-@@ -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);
+@@ -1093,13 +1096,13 @@ static int s3c24xx_serial_probe(struct platform_device *dev,
+ ourport = &s3c24xx_serial_ports[probe_index];
+ probe_index++;
-- 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
+- dbg("%s: initialising port %p...\n", __FUNCTION__, ourport);
++ dbg("%s: initialising port %p...\n", __func__, ourport);
- /*
-@@ -542,6 +543,10 @@ struct megasas_ctrl_info {
+ ret = s3c24xx_serial_init_port(ourport, info, dev);
+ if (ret < 0)
+ goto probe_err;
- #define MEGASAS_FW_BUSY 1
+- dbg("%s: adding port\n", __FUNCTION__);
++ dbg("%s: adding port\n", __func__);
+ uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
+ platform_set_drvdata(dev, &ourport->port);
+
+@@ -1584,7 +1587,7 @@ static int s3c2412_serial_resetport(struct uart_port *port,
+ unsigned long ucon = rd_regl(port, S3C2410_UCON);
+
+ dbg("%s: port=%p (%08lx), cfg=%p\n",
+- __FUNCTION__, port, port->mapbase, cfg);
++ __func__, port, port->mapbase, cfg);
+
+ /* ensure we don't change the clock settings... */
+
+diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
+index 67b2338..62b3858 100644
+--- a/drivers/serial/sa1100.c
++++ b/drivers/serial/sa1100.c
+@@ -655,7 +655,7 @@ void __init sa1100_register_uart_fns(struct sa1100_port_fns *fns)
+ void __init sa1100_register_uart(int idx, int port)
+ {
+ if (idx >= NR_PORTS) {
+- printk(KERN_ERR "%s: bad index number %d\n", __FUNCTION__, idx);
++ printk(KERN_ERR "%s: bad index number %d\n", __func__, idx);
+ return;
+ }
-+/* 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);
+@@ -682,7 +682,7 @@ void __init sa1100_register_uart(int idx, int port)
+ break;
- 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)
+ default:
+- printk(KERN_ERR "%s: bad port number %d\n", __FUNCTION__, port);
++ printk(KERN_ERR "%s: bad port number %d\n", __func__, port);
+ }
+ }
- #undef next_wcmd
+diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
+index 0f5a179..1e2b9d8 100644
+--- a/drivers/serial/serial_core.c
++++ b/drivers/serial/serial_core.c
+@@ -329,13 +329,15 @@ EXPORT_SYMBOL(uart_update_timeout);
+ * If it's still invalid, we try 9600 baud.
+ *
+ * Update the @termios structure to reflect the baud rate
+- * we're actually going to be using.
++ * we're actually going to be using. Don't do this for the case
++ * where B0 is requested ("hang up").
+ */
+ unsigned int
+ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old, unsigned int min, unsigned int max)
+ {
+ unsigned int try, baud, altbaud = 38400;
++ int hung_up = 0;
+ upf_t flags = port->flags & UPF_SPD_MASK;
--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)
+ if (flags == UPF_SPD_HI)
+@@ -360,8 +362,10 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
+ /*
+ * Special case: B0 rate.
+ */
+- if (baud == 0)
++ if (baud == 0) {
++ hung_up = 1;
+ baud = 9600;
++ }
+
+ if (baud >= min && baud <= max)
+ return baud;
+@@ -373,7 +377,9 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
+ termios->c_cflag &= ~CBAUD;
+ if (old) {
+ baud = tty_termios_baud_rate(old);
+- tty_termios_encode_baud_rate(termios, baud, baud);
++ if (!hung_up)
++ tty_termios_encode_baud_rate(termios,
++ baud, baud);
+ old = NULL;
+ continue;
+ }
+@@ -382,7 +388,8 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
+ * As a last resort, if the quotient is zero,
+ * default to 9600 bps
+ */
+- tty_termios_encode_baud_rate(termios, 9600, 9600);
++ if (!hung_up)
++ tty_termios_encode_baud_rate(termios, 9600, 9600);
+ }
+
+ return 0;
+@@ -415,6 +422,7 @@ uart_get_divisor(struct uart_port *port, unsigned int baud)
+
+ EXPORT_SYMBOL(uart_get_divisor);
+
++/* FIXME: Consistent locking policy */
+ static void
+ uart_change_speed(struct uart_state *state, struct ktermios *old_termios)
{
- 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);
+@@ -447,27 +455,30 @@ uart_change_speed(struct uart_state *state, struct ktermios *old_termios)
+ port->ops->set_termios(port, termios, old_termios);
}
-
--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)
+-static inline void
++static inline int
+ __uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c)
{
-- 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;
+ unsigned long flags;
++ int ret = 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;
- }
+ if (!circ->buf)
+- return;
++ return 0;
--CLASS_DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
-+DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
+ spin_lock_irqsave(&port->lock, flags);
+ if (uart_circ_chars_free(circ) != 0) {
+ circ->buf[circ->head] = c;
+ circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
++ ret = 1;
+ }
+ spin_unlock_irqrestore(&port->lock, flags);
++ return ret;
+ }
--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)
+-static void uart_put_char(struct tty_struct *tty, unsigned char ch)
++static int uart_put_char(struct tty_struct *tty, unsigned char ch)
{
-- 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;
+ struct uart_state *state = tty->driver_data;
- 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;
+- __uart_put_char(state->port, &state->info->xmit, ch);
++ return __uart_put_char(state->port, &state->info->xmit, ch);
}
--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)
+ static void uart_flush_chars(struct tty_struct *tty)
+@@ -521,15 +532,25 @@ uart_write(struct tty_struct *tty, const unsigned char *buf, int count)
+ static int uart_write_room(struct tty_struct *tty)
{
-- 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;
+ struct uart_state *state = tty->driver_data;
++ unsigned long flags;
++ int ret;
- 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;
+- return uart_circ_chars_free(&state->info->xmit);
++ spin_lock_irqsave(&state->port->lock, flags);
++ ret = uart_circ_chars_free(&state->info->xmit);
++ spin_unlock_irqrestore(&state->port->lock, flags);
++ return ret;
}
--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)
+ static int uart_chars_in_buffer(struct tty_struct *tty)
{
-- 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;
+ struct uart_state *state = tty->driver_data;
++ unsigned long flags;
++ int ret;
- 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;
+- return uart_circ_chars_pending(&state->info->xmit);
++ spin_lock_irqsave(&state->port->lock, flags);
++ ret = uart_circ_chars_pending(&state->info->xmit);
++ spin_unlock_irqrestore(&state->port->lock, flags);
++ return ret;
}
--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 void uart_flush_buffer(struct tty_struct *tty)
+@@ -611,6 +632,11 @@ static int uart_get_info(struct uart_state *state,
+ struct serial_struct tmp;
+
+ memset(&tmp, 0, sizeof(tmp));
++
++ /* Ensure the state we copy is consistent and no hardware changes
++ occur as we go */
++ mutex_lock(&state->mutex);
++
+ tmp.type = port->type;
+ tmp.line = port->line;
+ tmp.port = port->iobase;
+@@ -630,6 +656,8 @@ static int uart_get_info(struct uart_state *state,
+ tmp.iomem_reg_shift = port->regshift;
+ tmp.iomem_base = (void *)(unsigned long)port->mapbase;
--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;
++ mutex_unlock(&state->mutex);
++
+ if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+ return -EFAULT;
+ return 0;
+@@ -907,8 +935,6 @@ static void uart_break_ctl(struct tty_struct *tty, int break_state)
+ struct uart_state *state = tty->driver_data;
+ struct uart_port *port = state->port;
- 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;
+- BUG_ON(!kernel_locked());
+-
+ mutex_lock(&state->mutex);
+
+ if (port->type != PORT_UNKNOWN)
+@@ -1052,7 +1078,7 @@ static int uart_get_count(struct uart_state *state,
}
--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);
+ /*
+- * Called via sys_ioctl under the BKL. We can use spin_lock_irq() here.
++ * Called via sys_ioctl. We can use spin_lock_irq() here.
+ */
+ static int
+ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
+@@ -1062,7 +1088,6 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
+ void __user *uarg = (void __user *)arg;
+ int ret = -ENOIOCTLCMD;
--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;
+- BUG_ON(!kernel_locked());
- 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;
+ /*
+ * These ioctls don't rely on the hardware to be present.
+@@ -1133,9 +1158,9 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
+ break;
+ }
+ }
+- out_up:
++out_up:
+ mutex_unlock(&state->mutex);
+- out:
++out:
+ return ret;
}
--CLASS_DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
-+DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
+@@ -1146,7 +1171,6 @@ static void uart_set_termios(struct tty_struct *tty,
+ unsigned long flags;
+ unsigned int cflag = tty->termios->c_cflag;
- static struct class *osst_sysfs_class;
+- BUG_ON(!kernel_locked());
-@@ -5678,44 +5687,37 @@ static int osst_sysfs_init(void)
+ /*
+ * These are the bits that are used to setup various
+@@ -1158,8 +1182,9 @@ static void uart_set_termios(struct tty_struct *tty,
+ if ((cflag ^ old_termios->c_cflag) == 0 &&
+ tty->termios->c_ospeed == old_termios->c_ospeed &&
+ tty->termios->c_ispeed == old_termios->c_ispeed &&
+- RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
++ RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) {
+ return;
++ }
- static void osst_sysfs_destroy(dev_t dev)
- {
-- class_device_destroy(osst_sysfs_class, dev);
-+ device_destroy(osst_sysfs_class, dev);
- }
+ uart_change_speed(state, old_termios);
- 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;
+@@ -1193,7 +1218,6 @@ static void uart_set_termios(struct tty_struct *tty,
+ }
+ spin_unlock_irqrestore(&state->port->lock, flags);
+ }
+-
+ #if 0
+ /*
+ * No need to wake up processes in open wait, since they
+@@ -1309,11 +1333,11 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
+ struct uart_port *port = state->port;
+ unsigned long char_time, expire;
-- 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);
+- BUG_ON(!kernel_locked());
+-
+ if (port->type == PORT_UNKNOWN || port->fifosize == 0)
+ return;
+
++ lock_kernel();
++
+ /*
+ * Set the check interval to be 1/5 of the estimated time to
+ * send a single character, and make it at least 1. The check
+@@ -1359,6 +1383,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
+ break;
}
+ set_current_state(TASK_RUNNING); /* might not be needed */
++ unlock_kernel();
+ }
-- 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;
+ /*
+@@ -1771,7 +1796,7 @@ static int uart_read_proc(char *page, char **start, off_t off,
+ }
+ #endif
-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,
+-#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 +1852,7 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
+ * options. The format of the string is <baud><parity><bits><flow>,
+ * eg: 115200n8r
+ */
+-void __init
++void
+ uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow)
+ {
+ char *s = options;
+@@ -1842,6 +1867,7 @@ uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow)
+ if (*s)
+ *flow = *s;
}
++EXPORT_SYMBOL_GPL(uart_parse_options);
- 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 baud_rates {
+ unsigned int rate;
+@@ -1872,7 +1898,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)
{
-- 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;
+@@ -1924,10 +1950,16 @@ uart_set_options(struct uart_port *port, struct console *co,
+ port->mctrl |= TIOCM_DTR;
-@@ -642,10 +643,11 @@ SYM53C500_show_pio(struct class_device *cdev, char *buf)
+ 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 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;
+ static void uart_change_pm(struct uart_state *state, int pm_state)
+@@ -2065,7 +2097,9 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
+ int ret;
-@@ -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,
- };
+ uart_change_pm(state, 0);
++ spin_lock_irq(&port->lock);
+ ops->set_mctrl(port, 0);
++ spin_unlock_irq(&port->lock);
+ ret = ops->startup(port);
+ if (ret == 0) {
+ uart_change_speed(state, NULL);
+@@ -2182,6 +2216,60 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
+ }
+ }
--static struct class_device_attribute *SYM53C500_shost_attrs[] = {
-+static struct device_attribute *SYM53C500_shost_attrs[] = {
- &SYM53C500_pio_attr,
- NULL,
++#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 +2294,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
};
-diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c
-index fad6cb5..ce48e2d 100644
---- a/drivers/scsi/ps3rom.c
-+++ b/drivers/scsi/ps3rom.c
-@@ -26,6 +26,7 @@
- #include <scsi/scsi_dbg.h>
- #include <scsi/scsi_device.h>
- #include <scsi/scsi_host.h>
-+#include <scsi/scsi_eh.h>
- #include <asm/lv1call.h>
- #include <asm/ps3stor.h>
-@@ -90,78 +91,6 @@ static int ps3rom_slave_configure(struct scsi_device *scsi_dev)
- return 0;
+ /**
+@@ -2356,7 +2449,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..9691061 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);
}
-
--/*
-- * 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
+ #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)
+@@ -850,7 +855,7 @@ static int sci_notifier(struct notifier_block *self,
+
+ printk(KERN_INFO "%s: got a postchange notification "
+ "for cpu %d (old %d, new %d)\n",
+- __FUNCTION__, freqs->cpu, freqs->old, freqs->new);
++ __func__, freqs->cpu, freqs->old, freqs->new);
+ }
+
+ return NOTIFY_OK;
+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).
- */
--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;
--}
+ #include <linux/serial_core.h>
+ #include <asm/io.h>
-
- static int ps3rom_atapi_request(struct ps3_storage_device *dev,
- struct scsi_cmnd *cmd)
+ #include <asm/gpio.h>
+
+ #if defined(CONFIG_H83007) || defined(CONFIG_H83068)
+@@ -102,6 +87,15 @@
+ # define SCSPTR0 SCPDR0
+ # define SCIF_ORER 0x0001 /* overrun error bit */
+ # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
++#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
++# define SCSPTR0 0xa4050160
++# define SCSPTR1 0xa405013e
++# define SCSPTR2 0xa4050160
++# define SCSPTR3 0xa405013e
++# define SCSPTR4 0xa4050128
++# define SCSPTR5 0xa4050128
++# define SCIF_ORER 0x0001 /* overrun error bit */
++# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+ # define SCIF_ONLY
+ #elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
+ # define SCSPTR2 0xffe80020 /* 16 bit SCIF */
+@@ -395,6 +389,11 @@
+ h8_sci_offset, h8_sci_size) \
+ CPU_SCI_FNS(name, h8_sci_offset, h8_sci_size)
+ #define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size)
++#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
++ #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) \
++ CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size)
++ #define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \
++ CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
+ #else
+ #define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
+ sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
+@@ -419,6 +418,18 @@ SCIF_FNS(SCFDR, 0x1c, 16)
+ SCIF_FNS(SCxTDR, 0x20, 8)
+ SCIF_FNS(SCxRDR, 0x24, 8)
+ SCIF_FNS(SCLSR, 0x24, 16)
++#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
++SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16)
++SCIx_FNS(SCBRR, 0x04, 8, 0x04, 8)
++SCIx_FNS(SCSCR, 0x08, 16, 0x08, 16)
++SCIx_FNS(SCxTDR, 0x20, 8, 0x0c, 8)
++SCIx_FNS(SCxSR, 0x14, 16, 0x10, 16)
++SCIx_FNS(SCxRDR, 0x24, 8, 0x14, 8)
++SCIF_FNS(SCTDSR, 0x0c, 8)
++SCIF_FNS(SCFER, 0x10, 16)
++SCIF_FNS(SCFCR, 0x18, 16)
++SCIF_FNS(SCFDR, 0x1c, 16)
++SCIF_FNS(SCLSR, 0x24, 16)
+ #else
+ /* reg SCI/SH3 SCI/SH4 SCIF/SH3 SCIF/SH4 SCI/H8*/
+ /* name off sz off sz off sz off sz off sz*/
+@@ -589,6 +600,23 @@ static inline int sci_rxd_in(struct uart_port *port)
+ return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */
+ return 1;
+ }
++#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
++static inline int sci_rxd_in(struct uart_port *port)
++{
++ if (port->mapbase == 0xffe00000)
++ return ctrl_inb(SCSPTR0) & 0x0008 ? 1 : 0; /* SCIF0 */
++ if (port->mapbase == 0xffe10000)
++ return ctrl_inb(SCSPTR1) & 0x0020 ? 1 : 0; /* SCIF1 */
++ if (port->mapbase == 0xffe20000)
++ return ctrl_inb(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF2 */
++ if (port->mapbase == 0xa4e30000)
++ return ctrl_inb(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF3 */
++ if (port->mapbase == 0xa4e40000)
++ return ctrl_inb(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF4 */
++ if (port->mapbase == 0xa4e50000)
++ return ctrl_inb(SCSPTR5) & 0x0008 ? 1 : 0; /* SCIF5 */
++ return 1;
++}
+ #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
+ static inline int sci_rxd_in(struct uart_port *port)
{
-@@ -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;
+@@ -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/sn_console.c b/drivers/serial/sn_console.c
+index 41fc612..019da2e 100644
+--- a/drivers/serial/sn_console.c
++++ b/drivers/serial/sn_console.c
+@@ -839,7 +839,7 @@ static int __init sn_sal_module_init(void)
+
+ if (uart_add_one_port(&sal_console_uart, &sal_console_port.sc_port) < 0) {
+ /* error - not sure what I'd do - so I'll do nothing */
+- printk(KERN_ERR "%s: unable to add port\n", __FUNCTION__);
++ printk(KERN_ERR "%s: unable to add port\n", __func__);
+ }
- 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);
+ /* when this driver is compiled in, the console initialization
+diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
+index cb2e405..90a20a1 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,
+ };
-- 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);
++static int uart_chip_count;
+ static struct uart_sunzilog_port *sunzilog_port_table;
+ static struct zilog_layout __iomem **sunzilog_chip_regs;
- 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);
+@@ -1230,7 +1231,7 @@ static inline struct console *SUNZILOG_CONSOLE(void)
+ #define SUNZILOG_CONSOLE() (NULL)
+ #endif
+
+-static void __devinit sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channel)
++static void __devinit sunzilog_init_kbdms(struct uart_sunzilog_port *up)
+ {
+ int baud, brg;
+
+@@ -1304,7 +1305,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
+ up->curregs[R7] = 0x7E; /* SDLC Flag */
+ up->curregs[R9] = NV;
+ up->curregs[R7p] = 0x00;
+- sunzilog_init_kbdms(up, up->port.line);
++ sunzilog_init_kbdms(up);
+ /* Only enable interrupts if an ISR handler available */
+ if (up->flags & SUNZILOG_FLAG_ISR_HANDLER)
+ up->curregs[R9] |= MIE;
+@@ -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;
+
-+ scsi_set_resid(cmd, scsi_bufflen(cmd) - len);
+ 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;
}
- cmd->result = DID_OK << 16;
- goto done;
-@@ -404,11 +331,7 @@ static irqreturn_t ps3rom_interrupt(int irq, void *data)
- goto done;
++ 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++;
}
-- 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,
- };
+ dev_set_drvdata(&op->dev, &up[0]);
-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 @@
+- inst++;
+-
+ return 0;
+ }
- #include <linux/module.h>
+@@ -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;
--#include <linux/version.h>
- #include <linux/types.h>
- #include <linux/string.h>
- #include <linux/errno.h>
-@@ -367,10 +366,6 @@
- #include <asm/sn/io.h>
- #endif
+- num_keybms = 0;
+ for_each_node_by_name(dp, "zs") {
+ num_sunzilog++;
+ if (of_find_property(dp, "keyboard", NULL))
+ num_keybms++;
+ }
--#if LINUX_VERSION_CODE < 0x020600
--#error "Kernels older than 2.6.0 are no longer supported"
--#endif
+- uart_count = 0;
+ if (num_sunzilog) {
+- int uart_count;
-
+ err = sunzilog_alloc_tables(num_sunzilog);
+ if (err)
+ goto out;
- /*
- * 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
+- uart_count = (num_sunzilog * 2) - (2 * num_keybms);
++ uart_chip_count = num_sunzilog - num_keybms;
- 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 @@
+- 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/uartlite.c b/drivers/serial/uartlite.c
+index b565d5a..b51c242 100644
+--- a/drivers/serial/uartlite.c
++++ b/drivers/serial/uartlite.c
+@@ -584,7 +584,7 @@ ulite_of_probe(struct of_device *op, const struct of_device_id *match)
+ const unsigned int *id;
+ int irq, rc;
+
+- dev_dbg(&op->dev, "%s(%p, %p)\n", __FUNCTION__, op, match);
++ dev_dbg(&op->dev, "%s(%p, %p)\n", __func__, op, match);
+
+ rc = of_address_to_resource(op->node, 0, &res);
+ if (rc) {
+diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c
+index e0994f0..01917c4 100644
+--- a/drivers/serial/ucc_uart.c
++++ b/drivers/serial/ucc_uart.c
+@@ -215,7 +215,7 @@ static inline dma_addr_t cpu2qe_addr(void *addr, struct uart_qe_port *qe_port)
+ return qe_port->bd_dma_addr + (addr - qe_port->bd_virt);
+
+ /* something nasty happened */
+- printk(KERN_ERR "%s: addr=%p\n", __FUNCTION__, addr);
++ printk(KERN_ERR "%s: addr=%p\n", __func__, addr);
+ BUG();
+ return 0;
+ }
+@@ -234,7 +234,7 @@ static inline void *qe2cpu_addr(dma_addr_t addr, struct uart_qe_port *qe_port)
+ return qe_port->bd_virt + (addr - qe_port->bd_dma_addr);
+
+ /* something nasty happened */
+- printk(KERN_ERR "%s: addr=%x\n", __FUNCTION__, addr);
++ printk(KERN_ERR "%s: addr=%x\n", __func__, addr);
+ BUG();
+ return NULL;
+ }
+@@ -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/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
+index 98ab649..bb6ce6b 100644
+--- a/drivers/serial/vr41xx_siu.c
++++ b/drivers/serial/vr41xx_siu.c
+@@ -1,7 +1,7 @@
/*
- * QLogic Fibre Channel HBA Driver
-- * Copyright (c) 2003-2005 QLogic Corporation
-+ * Copyright (c) 2003-2008 QLogic Corporation
+ * Driver for NEC VR4100 series Serial Interface Unit.
*
- * See LICENSE.qla2xxx for copyright and licensing details.
- */
-@@ -530,15 +530,17 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
- /* Scsi_Host attributes. */
+- * Copyright (C) 2004-2007 Yoichi Yuasa <yoichi_yuasa at tripeaks.co.jp>
++ * Copyright (C) 2004-2008 Yoichi Yuasa <yoichi_yuasa at tripeaks.co.jp>
+ *
+ * Based on drivers/serial/8250.c, by Russell King.
+ *
+@@ -840,6 +840,19 @@ static int __devinit siu_console_init(void)
- 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);
- }
+ console_initcall(siu_console_init);
- 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];
++void __init vr41xx_siu_early_setup(struct uart_port *port)
++{
++ if (port->type == PORT_UNKNOWN)
++ return;
++
++ siu_uart_ports[port->line].line = port->line;
++ siu_uart_ports[port->line].type = port->type;
++ siu_uart_ports[port->line].uartclk = SIU_BAUD_BASE * 16;
++ siu_uart_ports[port->line].mapbase = port->mapbase;
++ siu_uart_ports[port->line].mapbase = port->mapbase;
++ siu_uart_ports[port->line].ops = &siu_uart_ops;
++}
++
+ #define SERIAL_VR41XX_CONSOLE &siu_console
+ #else
+ #define SERIAL_VR41XX_CONSOLE NULL
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index d810789..fae9e8f 100644
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -5,11 +5,9 @@
+ # nobody's needed a slave side API yet. The master-role API is not
+ # fully appropriate there, so it'd need some thought to do well.
+ #
+-menu "SPI support"
+- depends on HAS_IOMEM
+-
+-config SPI
++menuconfig SPI
+ bool "SPI support"
++ depends on HAS_IOMEM
+ help
+ The "Serial Peripheral Interface" is a low level synchronous
+ protocol. Chips that support SPI can have data transfer rates
+@@ -28,9 +26,11 @@ config SPI
+ (half duplex), SSP, SSI, and PSP. This driver framework should
+ work with most such devices and controllers.
+
++if SPI
++
+ config SPI_DEBUG
+ boolean "Debug support for SPI drivers"
+- depends on SPI && DEBUG_KERNEL
++ depends on DEBUG_KERNEL
+ help
+ Say "yes" to enable debug messaging (like dev_dbg and pr_debug),
+ sysfs, and debugfs support in SPI controller and protocol drivers.
+@@ -245,5 +245,4 @@ config SPI_TLE62X0
+
+ # (slave support would go here)
+
+-endmenu # "SPI support"
+-
++endif # SPI
+diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
+index 1749a27..e81d59d 100644
+--- a/drivers/spi/atmel_spi.c
++++ b/drivers/spi/atmel_spi.c
+@@ -497,7 +497,7 @@ static int atmel_spi_setup(struct spi_device *spi)
+ struct atmel_spi *as;
+ u32 scbr, csr;
+ unsigned int bits = spi->bits_per_word;
+- unsigned long bus_hz, sck_hz;
++ unsigned long bus_hz;
+ unsigned int npcs_pin;
+ int ret;
- return snprintf(buf, PAGE_SIZE, "%s\n",
-@@ -546,9 +548,10 @@ qla2x00_fw_version_show(struct class_device *cdev, char *buf)
- }
+@@ -536,14 +536,25 @@ static int atmel_spi_setup(struct spi_device *spi)
+ return -EINVAL;
+ }
- 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;
+- /* speed zero convention is used by some upper layers */
++ /*
++ * Pre-new_1 chips start out at half the peripheral
++ * bus speed.
++ */
+ bus_hz = clk_get_rate(as->clk);
++ if (!as->new_1)
++ bus_hz /= 2;
++
+ if (spi->max_speed_hz) {
+- /* assume div32/fdiv/mbz == 0 */
+- if (!as->new_1)
+- bus_hz /= 2;
+- scbr = ((bus_hz + spi->max_speed_hz - 1)
+- / spi->max_speed_hz);
++ /*
++ * Calculate the lowest divider that satisfies the
++ * constraint, assuming div32/fdiv/mbz == 0.
++ */
++ scbr = DIV_ROUND_UP(bus_hz, spi->max_speed_hz);
++
++ /*
++ * If the resulting divider doesn't fit into the
++ * register bitfield, we can't satisfy the constraint.
++ */
+ if (scbr >= (1 << SPI_SCBR_SIZE)) {
+ dev_dbg(&spi->dev,
+ "setup: %d Hz too slow, scbr %u; min %ld Hz\n",
+@@ -551,8 +562,8 @@ static int atmel_spi_setup(struct spi_device *spi)
+ return -EINVAL;
+ }
+ } else
++ /* speed zero means "as slow as possible" */
+ scbr = 0xff;
+- sck_hz = bus_hz / scbr;
+
+ csr = SPI_BF(SCBR, scbr) | SPI_BF(BITS, bits - 8);
+ if (spi->mode & SPI_CPOL)
+@@ -589,7 +600,7 @@ static int atmel_spi_setup(struct spi_device *spi)
+
+ dev_dbg(&spi->dev,
+ "setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n",
+- sck_hz, bits, spi->mode, spi->chip_select, csr);
++ bus_hz / scbr, bits, spi->mode, spi->chip_select, csr);
- if (IS_FWI2_CAPABLE(ha))
-@@ -560,40 +563,45 @@ qla2x00_serial_num_show(struct class_device *cdev, char *buf)
- }
+ spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
- 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);
- }
+@@ -616,7 +627,7 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
+ return -ESHUTDOWN;
- 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]);
- }
+ list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+- if (!(xfer->tx_buf || xfer->rx_buf)) {
++ if (!(xfer->tx_buf || xfer->rx_buf) && xfer->len) {
+ dev_dbg(&spi->dev, "missing rx or tx buf\n");
+ return -EINVAL;
+ }
+diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c
+index 5f00bd6..d9ae111 100644
+--- a/drivers/spi/omap_uwire.c
++++ b/drivers/spi/omap_uwire.c
+@@ -151,7 +151,7 @@ static int wait_uwire_csr_flag(u16 mask, u16 val, int might_not_catch)
+ if (time_after(jiffies, max_jiffies)) {
+ printk(KERN_ERR "%s: timeout. reg=%#06x "
+ "mask=%#06x val=%#06x\n",
+- __FUNCTION__, w, mask, val);
++ __func__, w, mask, val);
+ return -1;
+ }
+ c++;
+@@ -437,7 +437,7 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
+ }
+ omap_uwire_configure_mode(spi->chip_select, flags);
+ pr_debug("%s: uwire flags %02x, armxor %lu KHz, SCK %lu KHz\n",
+- __FUNCTION__, flags,
++ __func__, flags,
+ clk_get_rate(uwire->ck) / 1000,
+ rate / 1000);
+ status = 0;
+diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
+index 147e26a..654bb58 100644
+--- a/drivers/spi/pxa2xx_spi.c
++++ b/drivers/spi/pxa2xx_spi.c
+@@ -67,8 +67,11 @@ MODULE_ALIAS("platform:pxa2xx-spi");
+ | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
+
+ #define DEFINE_SSP_REG(reg, off) \
+-static inline u32 read_##reg(void *p) { return __raw_readl(p + (off)); } \
+-static inline void write_##reg(u32 v, void *p) { __raw_writel(v, p + (off)); }
++static inline u32 read_##reg(void const __iomem *p) \
++{ return __raw_readl(p + (off)); } \
++\
++static inline void write_##reg(u32 v, void __iomem *p) \
++{ __raw_writel(v, p + (off)); }
+
+ DEFINE_SSP_REG(SSCR0, 0x00)
+ DEFINE_SSP_REG(SSCR1, 0x04)
+@@ -106,7 +109,7 @@ struct driver_data {
+ u32 *null_dma_buf;
+
+ /* SSP register addresses */
+- void *ioaddr;
++ void __iomem *ioaddr;
+ u32 ssdr_physical;
- 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)
+ /* SSP masks*/
+@@ -173,7 +176,7 @@ static int flush(struct driver_data *drv_data)
{
-- 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);
- }
+ unsigned long limit = loops_per_jiffy << 1;
- 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: "");
- }
+- void *reg = drv_data->ioaddr;
++ void __iomem *reg = drv_data->ioaddr;
- 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)
+ do {
+ while (read_SSSR(reg) & SSSR_RNE) {
+@@ -191,7 +194,7 @@ static void null_cs_control(u32 command)
+
+ static int null_writer(struct driver_data *drv_data)
{
-- 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];
+- void *reg = drv_data->ioaddr;
++ void __iomem *reg = drv_data->ioaddr;
+ u8 n_bytes = drv_data->n_bytes;
- return snprintf(buf, PAGE_SIZE, "%s\n",
-@@ -601,9 +609,10 @@ qla2x00_pci_info_show(struct class_device *cdev, char *buf)
- }
+ if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+@@ -206,7 +209,7 @@ static int null_writer(struct driver_data *drv_data)
- static ssize_t
--qla2x00_state_show(struct class_device *cdev, char *buf)
-+qla2x00_state_show(struct device *dev, struct device_attribute *attr,
-+ char *buf)
+ static int null_reader(struct driver_data *drv_data)
{
-- 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;
+- void *reg = drv_data->ioaddr;
++ void __iomem *reg = drv_data->ioaddr;
+ u8 n_bytes = drv_data->n_bytes;
- if (atomic_read(&ha->loop_state) == LOOP_DOWN ||
-@@ -639,9 +648,10 @@ qla2x00_state_show(struct class_device *cdev, char *buf)
- }
+ while ((read_SSSR(reg) & SSSR_RNE)
+@@ -220,7 +223,7 @@ static int null_reader(struct driver_data *drv_data)
- static ssize_t
--qla2x00_zio_show(struct class_device *cdev, char *buf)
-+qla2x00_zio_show(struct device *dev, struct device_attribute *attr,
-+ char *buf)
+ static int u8_writer(struct driver_data *drv_data)
{
-- 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;
+- void *reg = drv_data->ioaddr;
++ void __iomem *reg = drv_data->ioaddr;
- switch (ha->zio_mode) {
-@@ -656,9 +666,10 @@ qla2x00_zio_show(struct class_device *cdev, char *buf)
- }
+ if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+ || (drv_data->tx == drv_data->tx_end))
+@@ -234,7 +237,7 @@ static int u8_writer(struct driver_data *drv_data)
- 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)
+ static int u8_reader(struct driver_data *drv_data)
{
-- 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;
+- void *reg = drv_data->ioaddr;
++ void __iomem *reg = drv_data->ioaddr;
-@@ -682,18 +693,19 @@ qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count)
- }
+ while ((read_SSSR(reg) & SSSR_RNE)
+ && (drv_data->rx < drv_data->rx_end)) {
+@@ -247,7 +250,7 @@ static int u8_reader(struct driver_data *drv_data)
- 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)
+ static int u16_writer(struct driver_data *drv_data)
{
-- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
-+ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+- void *reg = drv_data->ioaddr;
++ void __iomem *reg = drv_data->ioaddr;
- return snprintf(buf, PAGE_SIZE, "%d us\n", ha->zio_timer * 100);
- }
+ if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+ || (drv_data->tx == drv_data->tx_end))
+@@ -261,7 +264,7 @@ static int u16_writer(struct driver_data *drv_data)
- 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)
+ static int u16_reader(struct driver_data *drv_data)
{
-- 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;
+- void *reg = drv_data->ioaddr;
++ void __iomem *reg = drv_data->ioaddr;
-@@ -709,9 +721,10 @@ qla2x00_zio_timer_store(struct class_device *cdev, const char *buf,
- }
+ while ((read_SSSR(reg) & SSSR_RNE)
+ && (drv_data->rx < drv_data->rx_end)) {
+@@ -274,7 +277,7 @@ static int u16_reader(struct driver_data *drv_data)
- static ssize_t
--qla2x00_beacon_show(struct class_device *cdev, char *buf)
-+qla2x00_beacon_show(struct device *dev, struct device_attribute *attr,
-+ char *buf)
+ static int u32_writer(struct driver_data *drv_data)
{
-- 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;
+- void *reg = drv_data->ioaddr;
++ void __iomem *reg = drv_data->ioaddr;
- if (ha->beacon_blink_led)
-@@ -722,10 +735,10 @@ qla2x00_beacon_show(struct class_device *cdev, char *buf)
- }
+ if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+ || (drv_data->tx == drv_data->tx_end))
+@@ -288,7 +291,7 @@ static int u32_writer(struct driver_data *drv_data)
- 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)
+ static int u32_reader(struct driver_data *drv_data)
{
-- 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;
+- void *reg = drv_data->ioaddr;
++ void __iomem *reg = drv_data->ioaddr;
-@@ -753,84 +766,86 @@ qla2x00_beacon_store(struct class_device *cdev, const char *buf,
+ while ((read_SSSR(reg) & SSSR_RNE)
+ && (drv_data->rx < drv_data->rx_end)) {
+@@ -412,7 +415,7 @@ static void giveback(struct driver_data *drv_data)
+ msg->complete(msg->context);
}
- 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)
+-static int wait_ssp_rx_stall(void *ioaddr)
++static int wait_ssp_rx_stall(void const __iomem *ioaddr)
{
-- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
-+ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ unsigned long limit = loops_per_jiffy << 1;
- return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1],
- ha->bios_revision[0]);
+@@ -432,9 +435,9 @@ static int wait_dma_channel_stop(int channel)
+ return limit;
}
- 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)
+-void dma_error_stop(struct driver_data *drv_data, const char *msg)
++static void dma_error_stop(struct driver_data *drv_data, const char *msg)
{
-- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
-+ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+- void *reg = drv_data->ioaddr;
++ void __iomem *reg = drv_data->ioaddr;
- return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1],
- ha->efi_revision[0]);
- }
+ /* Stop and reset */
+ DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+@@ -456,7 +459,7 @@ void dma_error_stop(struct driver_data *drv_data, const char *msg)
- 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)
+ static void dma_transfer_complete(struct driver_data *drv_data)
{
-- 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]);
- }
+- void *reg = drv_data->ioaddr;
++ void __iomem *reg = drv_data->ioaddr;
+ struct spi_message *msg = drv_data->cur_msg;
- 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)
+ /* Clear and disable interrupts on SSP and DMA channels*/
+@@ -536,7 +539,7 @@ static void dma_handler(int channel, void *data)
+ static irqreturn_t dma_transfer(struct driver_data *drv_data)
{
-- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
-+ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ u32 irq_status;
+- void *reg = drv_data->ioaddr;
++ void __iomem *reg = drv_data->ioaddr;
- 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]);
- }
+ irq_status = read_SSSR(reg) & drv_data->mask_sr;
+ if (irq_status & SSSR_ROR) {
+@@ -570,7 +573,7 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
--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,
- };
+ static void int_error_stop(struct driver_data *drv_data, const char* msg)
+ {
+- void *reg = drv_data->ioaddr;
++ void __iomem *reg = drv_data->ioaddr;
+
+ /* Stop and reset SSP */
+ write_SSSR(drv_data->clear_sr, reg);
+@@ -588,7 +591,7 @@ static void int_error_stop(struct driver_data *drv_data, const char* msg)
-@@ -849,20 +864,20 @@ static void
- qla2x00_get_host_speed(struct Scsi_Host *shost)
+ static void int_transfer_complete(struct driver_data *drv_data)
{
- scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost));
-- uint32_t speed = 0;
-+ u32 speed = FC_PORTSPEED_UNKNOWN;
+- void *reg = drv_data->ioaddr;
++ void __iomem *reg = drv_data->ioaddr;
- 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;
+ /* Stop SSP */
+ write_SSSR(drv_data->clear_sr, reg);
+@@ -614,7 +617,7 @@ static void int_transfer_complete(struct driver_data *drv_data)
- 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;
+ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+ {
+- void *reg = drv_data->ioaddr;
++ void __iomem *reg = drv_data->ioaddr;
- 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;
+ u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ?
+ drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
+@@ -675,7 +678,7 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+ static irqreturn_t ssp_int(int irq, void *dev_id)
+ {
+ struct driver_data *drv_data = dev_id;
+- void *reg = drv_data->ioaddr;
++ void __iomem *reg = drv_data->ioaddr;
- 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,
+ if (!drv_data->cur_msg) {
- .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)
+@@ -695,7 +698,8 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
+ return drv_data->transfer_handler(drv_data);
+ }
+
+-int set_dma_burst_and_threshold(struct chip_data *chip, struct spi_device *spi,
++static int set_dma_burst_and_threshold(struct chip_data *chip,
++ struct spi_device *spi,
+ u8 bits_per_word, u32 *burst_code,
+ u32 *threshold)
{
-+ 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;
+@@ -809,7 +813,7 @@ static void pump_transfers(unsigned long data)
+ struct spi_transfer *previous = NULL;
+ struct chip_data *chip = NULL;
+ struct ssp_device *ssp = drv_data->ssp;
+- void *reg = drv_data->ioaddr;
++ void __iomem *reg = drv_data->ioaddr;
+ u32 clk_div = 0;
+ u8 bits = 0;
+ u32 speed = 0;
+@@ -1338,7 +1342,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
+ struct device *dev = &pdev->dev;
+ struct pxa2xx_spi_master *platform_info;
+ struct spi_master *master;
+- struct driver_data *drv_data = 0;
++ struct driver_data *drv_data = NULL;
+ struct ssp_device *ssp;
+ int status = 0;
+
+diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
+index 71e8814..96cc39e 100644
+--- a/drivers/spi/spi_bitbang.c
++++ b/drivers/spi/spi_bitbang.c
+@@ -214,7 +214,7 @@ int spi_bitbang_setup(struct spi_device *spi)
+ return retval;
+
+ dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
+- __FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA),
++ __func__, spi->mode & (SPI_CPOL | SPI_CPHA),
+ spi->bits_per_word, 2 * cs->nsecs);
+
+ /* NOTE we _need_ to call chipselect() early, ideally with adapter
+diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
+index d4ba640..c730d05 100644
+--- a/drivers/spi/spi_imx.c
++++ b/drivers/spi/spi_imx.c
+@@ -270,19 +270,26 @@ struct chip_data {
+
+ static void pump_messages(struct work_struct *work);
+
+-static int flush(struct driver_data *drv_data)
++static void flush(struct driver_data *drv_data)
+ {
+- unsigned long limit = loops_per_jiffy << 1;
+ void __iomem *regs = drv_data->regs;
+- volatile u32 d;
++ u32 control;
+
+ dev_dbg(&drv_data->pdev->dev, "flush\n");
+
-+ 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");
++ /* Wait for end of transaction */
+ do {
+- while (readl(regs + SPI_INT_STATUS) & SPI_STATUS_RR)
+- d = readl(regs + SPI_RXDATA);
+- } while ((readl(regs + SPI_CONTROL) & SPI_CONTROL_XCH) && limit--);
++ control = readl(regs + SPI_CONTROL);
++ } while (control & SPI_CONTROL_XCH);
++
++ /* Release chip select if requested, transfer delays are
++ handled in pump_transfers */
++ if (drv_data->cs_change)
++ drv_data->cs_control(SPI_CS_DEASSERT);
+
+- return limit;
++ /* Disable SPI to flush FIFOs */
++ writel(control & ~SPI_CONTROL_SPIEN, regs + SPI_CONTROL);
++ writel(control, regs + SPI_CONTROL);
}
+
+ static void restore_state(struct driver_data *drv_data)
+@@ -570,6 +577,7 @@ static void giveback(struct spi_message *message, struct driver_data *drv_data)
+ writel(0, regs + SPI_INT_STATUS);
+ writel(0, regs + SPI_DMA);
+
++ /* Unconditioned deselct */
+ drv_data->cs_control(SPI_CS_DEASSERT);
+
+ message->state = NULL;
+@@ -592,13 +600,10 @@ static void dma_err_handler(int channel, void *data, int errcode)
+ /* Disable both rx and tx dma channels */
+ imx_dma_disable(drv_data->rx_channel);
+ imx_dma_disable(drv_data->tx_channel);
-
--/**************************************************************************
-- * 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 (flush(drv_data) == 0)
+- dev_err(&drv_data->pdev->dev,
+- "dma_err_handler - flush failed\n");
-
-- 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 */
+ unmap_dma_buffers(drv_data);
- /*
- * 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)
++ flush(drv_data);
++
+ msg->state = ERROR_STATE;
+ tasklet_schedule(&drv_data->pump_transfers);
+ }
+@@ -612,8 +617,7 @@ static void dma_tx_handler(int channel, void *data)
+ imx_dma_disable(channel);
- #if defined(QL_DEBUG_LEVEL_3)
- #define DEBUG3(x) do {x;} while (0)
-@@ -133,6 +122,12 @@
- #define DEBUG15(x) do {} while (0)
- #endif
+ /* Now waits for TX FIFO empty */
+- writel(readl(drv_data->regs + SPI_INT_STATUS) | SPI_INTEN_TE,
+- drv_data->regs + SPI_INT_STATUS);
++ writel(SPI_INTEN_TE, drv_data->regs + SPI_INT_STATUS);
+ }
-+#if defined(QL_DEBUG_LEVEL_16)
-+#define DEBUG16(x) do {x;} while (0)
-+#else
-+#define DEBUG16(x) do {} while (0)
-+#endif
-+
- /*
- * Firmware Dump structure definition
- */
-diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
-index 3750319..299eccf 100644
---- a/drivers/scsi/qla2xxx/qla_def.h
-+++ b/drivers/scsi/qla2xxx/qla_def.h
-@@ -1,6 +1,6 @@
- /*
- * QLogic Fibre Channel HBA Driver
-- * Copyright (c) 2003-2005 QLogic Corporation
-+ * Copyright (c) 2003-2008 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
- */
-@@ -24,7 +24,8 @@
- #include <linux/workqueue.h>
- #include <linux/firmware.h>
- #include <linux/aer.h>
--#include <asm/semaphore.h>
-+#include <linux/mutex.h>
-+#include <linux/semaphore.h>
+ static irqreturn_t dma_transfer(struct driver_data *drv_data)
+@@ -621,19 +625,18 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
+ u32 status;
+ struct spi_message *msg = drv_data->cur_msg;
+ void __iomem *regs = drv_data->regs;
+- unsigned long limit;
+
+ status = readl(regs + SPI_INT_STATUS);
+
+- if ((status & SPI_INTEN_RO) && (status & SPI_STATUS_RO)) {
++ if ((status & (SPI_INTEN_RO | SPI_STATUS_RO))
++ == (SPI_INTEN_RO | SPI_STATUS_RO)) {
+ writel(status & ~SPI_INTEN, regs + SPI_INT_STATUS);
+
++ imx_dma_disable(drv_data->tx_channel);
+ imx_dma_disable(drv_data->rx_channel);
+ unmap_dma_buffers(drv_data);
+
+- if (flush(drv_data) == 0)
+- dev_err(&drv_data->pdev->dev,
+- "dma_transfer - flush failed\n");
++ flush(drv_data);
+
+ dev_warn(&drv_data->pdev->dev,
+ "dma_transfer - fifo overun\n");
+@@ -649,20 +652,17 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
+
+ if (drv_data->rx) {
+ /* Wait end of transfer before read trailing data */
+- limit = loops_per_jiffy << 1;
+- while ((readl(regs + SPI_CONTROL) & SPI_CONTROL_XCH) &&
+- limit--);
+-
+- if (limit == 0)
+- dev_err(&drv_data->pdev->dev,
+- "dma_transfer - end of tx failed\n");
+- else
+- dev_dbg(&drv_data->pdev->dev,
+- "dma_transfer - end of tx\n");
++ while (readl(regs + SPI_CONTROL) & SPI_CONTROL_XCH)
++ cpu_relax();
- #include <scsi/scsi.h>
- #include <scsi/scsi_host.h>
-@@ -192,9 +193,6 @@ typedef struct srb {
+ imx_dma_disable(drv_data->rx_channel);
+ unmap_dma_buffers(drv_data);
- uint16_t flags;
++ /* Release chip select if requested, transfer delays are
++ handled in pump_transfers() */
++ if (drv_data->cs_change)
++ drv_data->cs_control(SPI_CS_DEASSERT);
++
+ /* Calculate number of trailing data and read them */
+ dev_dbg(&drv_data->pdev->dev,
+ "dma_transfer - test = 0x%08X\n",
+@@ -676,19 +676,12 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
+ /* Write only transfer */
+ unmap_dma_buffers(drv_data);
+
+- if (flush(drv_data) == 0)
+- dev_err(&drv_data->pdev->dev,
+- "dma_transfer - flush failed\n");
++ flush(drv_data);
+ }
+
+ /* End of transfer, update total byte transfered */
+ msg->actual_length += drv_data->len;
+
+- /* Release chip select if requested, transfer delays are
+- handled in pump_transfers() */
+- if (drv_data->cs_change)
+- drv_data->cs_control(SPI_CS_DEASSERT);
+-
+ /* Move to next transfer */
+ msg->state = next_transfer(drv_data);
+
+@@ -711,44 +704,43 @@ static irqreturn_t interrupt_wronly_transfer(struct driver_data *drv_data)
+
+ status = readl(regs + SPI_INT_STATUS);
+
+- while (status & SPI_STATUS_TH) {
++ if (status & SPI_INTEN_TE) {
++ /* TXFIFO Empty Interrupt on the last transfered word */
++ writel(status & ~SPI_INTEN, regs + SPI_INT_STATUS);
+ dev_dbg(&drv_data->pdev->dev,
+- "interrupt_wronly_transfer - status = 0x%08X\n", status);
++ "interrupt_wronly_transfer - end of tx\n");
+
+- /* Pump data */
+- if (write(drv_data)) {
+- writel(readl(regs + SPI_INT_STATUS) & ~SPI_INTEN,
+- regs + SPI_INT_STATUS);
++ flush(drv_data);
+
+- dev_dbg(&drv_data->pdev->dev,
+- "interrupt_wronly_transfer - end of tx\n");
++ /* Update total byte transfered */
++ msg->actual_length += drv_data->len;
+
+- if (flush(drv_data) == 0)
+- dev_err(&drv_data->pdev->dev,
+- "interrupt_wronly_transfer - "
+- "flush failed\n");
++ /* Move to next transfer */
++ msg->state = next_transfer(drv_data);
+
+- /* End of transfer, update total byte transfered */
+- msg->actual_length += drv_data->len;
++ /* Schedule transfer tasklet */
++ tasklet_schedule(&drv_data->pump_transfers);
+
+- /* Release chip select if requested, transfer delays are
+- handled in pump_transfers */
+- if (drv_data->cs_change)
+- drv_data->cs_control(SPI_CS_DEASSERT);
++ return IRQ_HANDLED;
++ } else {
++ while (status & SPI_STATUS_TH) {
++ dev_dbg(&drv_data->pdev->dev,
++ "interrupt_wronly_transfer - status = 0x%08X\n",
++ status);
-- /* 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;
+- /* Move to next transfer */
+- msg->state = next_transfer(drv_data);
++ /* Pump data */
++ if (write(drv_data)) {
++ /* End of TXFIFO writes,
++ now wait until TXFIFO is empty */
++ writel(SPI_INTEN_TE, regs + SPI_INT_STATUS);
++ return IRQ_HANDLED;
++ }
-- unsigned int os_target_id;
+- /* Schedule transfer tasklet */
+- tasklet_schedule(&drv_data->pump_transfers);
++ status = readl(regs + SPI_INT_STATUS);
+
+- return IRQ_HANDLED;
++ /* We did something */
++ handled = IRQ_HANDLED;
+ }
-
- 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
+- status = readl(regs + SPI_INT_STATUS);
+-
+- /* We did something */
+- handled = IRQ_HANDLED;
+ }
- #define NS_N_PORT_TYPE 0x01
-@@ -2063,7 +2060,8 @@ struct isp_operations {
- void (*disable_intrs) (struct scsi_qla_host *);
+ return handled;
+@@ -758,45 +750,31 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+ {
+ struct spi_message *msg = drv_data->cur_msg;
+ void __iomem *regs = drv_data->regs;
+- u32 status;
++ u32 status, control;
+ irqreturn_t handled = IRQ_NONE;
+ unsigned long limit;
+
+ status = readl(regs + SPI_INT_STATUS);
+
+- while (status & (SPI_STATUS_TH | SPI_STATUS_RO)) {
++ if (status & SPI_INTEN_TE) {
++ /* TXFIFO Empty Interrupt on the last transfered word */
++ writel(status & ~SPI_INTEN, regs + SPI_INT_STATUS);
+ dev_dbg(&drv_data->pdev->dev,
+- "interrupt_transfer - status = 0x%08X\n", status);
+-
+- if (status & SPI_STATUS_RO) {
+- writel(readl(regs + SPI_INT_STATUS) & ~SPI_INTEN,
+- regs + SPI_INT_STATUS);
+-
+- dev_warn(&drv_data->pdev->dev,
+- "interrupt_transfer - fifo overun\n"
+- " data not yet written = %d\n"
+- " data not yet read = %d\n",
+- data_to_write(drv_data),
+- data_to_read(drv_data));
+-
+- if (flush(drv_data) == 0)
+- dev_err(&drv_data->pdev->dev,
+- "interrupt_transfer - flush failed\n");
+-
+- msg->state = ERROR_STATE;
+- tasklet_schedule(&drv_data->pump_transfers);
++ "interrupt_transfer - end of tx\n");
- 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 {
+- return IRQ_HANDLED;
+- }
+-
+- /* Pump data */
+- read(drv_data);
+- if (write(drv_data)) {
+- writel(readl(regs + SPI_INT_STATUS) & ~SPI_INTEN,
+- regs + SPI_INT_STATUS);
++ if (msg->state == ERROR_STATE) {
++ /* RXFIFO overrun was detected and message aborted */
++ flush(drv_data);
++ } else {
++ /* Wait for end of transaction */
++ do {
++ control = readl(regs + SPI_CONTROL);
++ } while (control & SPI_CONTROL_XCH);
- #define WATCH_INTERVAL 1 /* number of seconds */
+- dev_dbg(&drv_data->pdev->dev,
+- "interrupt_transfer - end of tx\n");
++ /* Release chip select if requested, transfer delays are
++ handled in pump_transfers */
++ if (drv_data->cs_change)
++ drv_data->cs_control(SPI_CS_DEASSERT);
+
+ /* Read trailing bytes */
+ limit = loops_per_jiffy << 1;
+@@ -810,27 +788,54 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+ dev_dbg(&drv_data->pdev->dev,
+ "interrupt_transfer - end of rx\n");
+
+- /* End of transfer, update total byte transfered */
++ /* Update total byte transfered */
+ msg->actual_length += drv_data->len;
+
+- /* Release chip select if requested, transfer delays are
+- handled in pump_transfers */
+- if (drv_data->cs_change)
+- drv_data->cs_control(SPI_CS_DEASSERT);
+-
+ /* Move to next transfer */
+ msg->state = next_transfer(drv_data);
++ }
+
+- /* Schedule transfer tasklet */
+- tasklet_schedule(&drv_data->pump_transfers);
++ /* Schedule transfer tasklet */
++ tasklet_schedule(&drv_data->pump_transfers);
-+/* 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
+- return IRQ_HANDLED;
+- }
++ return IRQ_HANDLED;
++ } else {
++ while (status & (SPI_STATUS_TH | SPI_STATUS_RO)) {
++ dev_dbg(&drv_data->pdev->dev,
++ "interrupt_transfer - status = 0x%08X\n",
++ status);
+
-+ union {
-+ struct {
-+ enum fc_host_event_code code;
-+ u32 data;
-+ } aen;
-+ struct {
-+ uint16_t code;
-+ uint16_t d1, d2, d3;
-+ } hwe;
-+ } u;
-+};
++ if (status & SPI_STATUS_RO) {
++ /* RXFIFO overrun, abort message end wait
++ until TXFIFO is empty */
++ writel(SPI_INTEN_TE, regs + SPI_INT_STATUS);
++
++ dev_warn(&drv_data->pdev->dev,
++ "interrupt_transfer - fifo overun\n"
++ " data not yet written = %d\n"
++ " data not yet read = %d\n",
++ data_to_write(drv_data),
++ data_to_read(drv_data));
+
-+struct qla_chip_state_84xx {
-+ struct list_head list;
-+ struct kref kref;
++ msg->state = ERROR_STATE;
+
-+ 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;
-+};
++ return IRQ_HANDLED;
++ }
+
+- status = readl(regs + SPI_INT_STATUS);
++ /* Pump data */
++ read(drv_data);
++ if (write(drv_data)) {
++ /* End of TXFIFO writes,
++ now wait until TXFIFO is empty */
++ writel(SPI_INTEN_TE, regs + SPI_INT_STATUS);
++ return IRQ_HANDLED;
++ }
+
+- /* We did something */
+- handled = IRQ_HANDLED;
++ status = readl(regs + SPI_INT_STATUS);
+
- /*
- * 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;
++ /* We did something */
++ handled = IRQ_HANDLED;
++ }
+ }
- atomic_t loop_state;
-@@ -2204,6 +2243,7 @@ typedef struct scsi_qla_host {
- #define DFLG_NO_CABLE BIT_4
+ return handled;
+diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c
+index be15a62..189f706 100644
+--- a/drivers/spi/spi_mpc83xx.c
++++ b/drivers/spi/spi_mpc83xx.c
+@@ -310,7 +310,7 @@ static int mpc83xx_spi_setup(struct spi_device *spi)
+ return retval;
- #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)
+ dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec\n",
+- __FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA),
++ __func__, spi->mode & (SPI_CPOL | SPI_CPHA),
+ spi->bits_per_word, 2 * mpc83xx_spi->nsecs);
+
+ /* NOTE we _need_ to call chipselect() early, ideally with adapter
+diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
+index b7476b8..34bfb7d 100644
+--- a/drivers/spi/spi_s3c24xx.c
++++ b/drivers/spi/spi_s3c24xx.c
+@@ -169,7 +169,7 @@ static int s3c24xx_spi_setup(struct spi_device *spi)
+ }
+
+ dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n",
+- __FUNCTION__, spi->mode, spi->bits_per_word,
++ __func__, spi->mode, spi->bits_per_word,
+ spi->max_speed_hz);
+
+ return 0;
+diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
+index cf6aef3..113a046 100644
+--- a/drivers/spi/xilinx_spi.c
++++ b/drivers/spi/xilinx_spi.c
+@@ -151,13 +151,13 @@ static int xilinx_spi_setup_transfer(struct spi_device *spi,
+ hz = (t) ? t->speed_hz : spi->max_speed_hz;
+ if (bits_per_word != 8) {
+ dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
+- __FUNCTION__, bits_per_word);
++ __func__, bits_per_word);
+ return -EINVAL;
+ }
- #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)
+ if (hz && xspi->speed_hz > hz) {
+ dev_err(&spi->dev, "%s, unsupported clock rate %uHz\n",
+- __FUNCTION__, hz);
++ __func__, hz);
+ return -EINVAL;
+ }
- #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))
+@@ -181,7 +181,7 @@ static int xilinx_spi_setup(struct spi_device *spi)
- #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;
+ if (spi->mode & ~MODEBITS) {
+ dev_err(&spi->dev, "%s, unsupported mode bits %x\n",
+- __FUNCTION__, spi->mode & ~MODEBITS);
++ __func__, spi->mode & ~MODEBITS);
+ return -EINVAL;
+ }
-+ struct list_head work_list;
-+
- /* Fibre Channel Device List. */
- struct list_head fcports;
+@@ -190,7 +190,7 @@ static int xilinx_spi_setup(struct spi_device *spi)
+ return retval;
-@@ -2423,8 +2470,6 @@ typedef struct scsi_qla_host {
- #define MBX_TIMEDOUT BIT_5
- #define MBX_ACCESS_TIMEDOUT BIT_6
+ dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
+- __FUNCTION__, spi->mode & MODEBITS, spi->bits_per_word, 0);
++ __func__, spi->mode & MODEBITS, spi->bits_per_word, 0);
-- 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;
+ return 0;
+ }
+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
-+ 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];
+ If unsure, say N.
-+ 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;
++# Common SPROM support routines
++config SSB_SPROM
++ bool
+
- /* 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;
++# Support for Block-I/O. SELECT this from the driver that needs it.
++config SSB_BLOCKIO
++ bool
++ depends on SSB
+
-+ struct qla_chip_state_84xx *cs84xx;
- } scsi_qla_host_t;
+ 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
-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 {
++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
- uint16_t timeout; /* Command timeout. */
+ # 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
-- uint8_t lun[8]; /* FCP LUN (BE). */
-+ struct scsi_lun lun; /* FCP LUN (BE). */
+ # 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);
+ }
- 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
+-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 @@
+/*
-+ * Flash Error Log Event Codes.
++ * Sonics Silicon Backplane
++ * Broadcom Gigabit Ethernet core driver
++ *
++ * Copyright 2008, Broadcom Corporation
++ * Copyright 2008, Michael Buesch <mb at bu3sch.de>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
+ */
-+#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 ***********************************************************/
++#include <linux/ssb/ssb.h>
++#include <linux/ssb/ssb_driver_gige.h>
++#include <linux/pci.h>
++#include <linux/pci_regs.h>
+
-+/* 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];
++/*
++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); */
+
-+/* 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
++static inline u8 gige_read8(struct ssb_gige *dev, u16 offset)
++{
++ return ssb_read8(dev->dev, offset);
++}
+
-+#define MBC_ISP84XX_RESET 0x3a /* Reset. */
++static inline u16 gige_read16(struct ssb_gige *dev, u16 offset)
++{
++ return ssb_read16(dev->dev, offset);
++}
+
-+#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
++static inline u32 gige_read32(struct ssb_gige *dev, u16 offset)
++{
++ return ssb_read32(dev->dev, offset);
++}
+
-+#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;
++static inline void gige_write8(struct ssb_gige *dev,
++ u16 offset, u8 value)
++{
++ ssb_write8(dev->dev, offset, value);
++}
+
-+ uint32_t handle;
++static inline void gige_write16(struct ssb_gige *dev,
++ u16 offset, u16 value)
++{
++ ssb_write16(dev->dev, offset, value);
++}
+
-+ 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
++static inline void gige_write32(struct ssb_gige *dev,
++ u16 offset, u32 value)
++{
++ ssb_write32(dev->dev, offset, value);
++}
+
-+ uint16_t reserved_1;
++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);
++}
+
-+ uint16_t data_seg_cnt;
-+ uint16_t reserved_2[3];
++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);
++}
+
-+ uint32_t fw_ver;
-+ uint32_t exchange_address;
++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);
++}
+
-+ uint32_t reserved_3[3];
-+ uint32_t fw_size;
-+ uint32_t fw_seq_size;
-+ uint32_t relative_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);
++}
+
-+ uint32_t dseg_address[2];
-+ uint32_t dseg_length;
-+};
++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);
++}
+
-+struct verify_chip_rsp_84xx {
-+ uint8_t entry_type;
-+ uint8_t entry_count;
-+ uint8_t sys_defined;
-+ uint8_t entry_status;
++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);
++}
+
-+ uint32_t handle;
++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;
+
-+ uint16_t comp_status;
-+#define CS_VCS_CHIP_FAILURE 0x3
-+#define CS_VCS_BAD_EXCHANGE 0x8
-+#define CS_VCS_SEQ_COMPLETEi 0x40
++ if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0))
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ if (reg >= 256)
++ return PCIBIOS_DEVICE_NOT_FOUND;
+
-+ uint16_t failure_code;
-+#define VFC_CHECKSUM_ERROR 0x1
-+#define VFC_INVALID_LEN 0x2
-+#define VFC_ALREADY_IN_PROGRESS 0x8
++ 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);
+
-+ uint16_t reserved_1[4];
++ return PCIBIOS_SUCCESSFUL;
++}
+
-+ uint32_t fw_ver;
-+ uint32_t exchange_address;
++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;
+
-+ uint32_t reserved_2[6];
-+};
++ if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0))
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ if (reg >= 256)
++ return PCIBIOS_DEVICE_NOT_FOUND;
+
-+#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;
++ 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);
+
-+ uint32_t handle;
++ return PCIBIOS_SUCCESSFUL;
++}
+
-+ uint16_t options;
-+#define ACO_DUMP_MEMORY 0x0
-+#define ACO_LOAD_MEMORY 0x1
-+#define ACO_CHANGE_CONFIG_PARAM 0x2
-+#define ACO_REQUEST_INFO 0x3
++static int ssb_gige_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
++{
++ struct ssb_gige *dev;
++ u32 base, tmslow, tmshigh;
+
-+ uint16_t reserved1;
++ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
++ if (!dev)
++ return -ENOMEM;
++ dev->dev = sdev;
+
-+ uint16_t dseg_count;
-+ uint16_t reserved2[3];
++ 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;
+
-+ uint32_t parameter1;
-+ uint32_t parameter2;
-+ uint32_t parameter3;
++ 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;
+
-+ uint32_t reserved3[3];
-+ uint32_t total_byte_cnt;
-+ uint32_t reserved4;
++ if (!ssb_device_is_enabled(sdev))
++ ssb_device_enable(sdev, 0);
+
-+ uint32_t dseg_address[2];
-+ uint32_t dseg_length;
-+};
++ /* 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);
+
-+struct access_chip_rsp_84xx {
-+ uint8_t entry_type;
-+ uint8_t entry_count;
-+ uint8_t sys_defined;
-+ uint8_t entry_status;
++ 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;
+
-+ uint32_t handle;
++ /* Enable the memory region. */
++ gige_pcicfg_write16(dev, PCI_COMMAND,
++ gige_pcicfg_read16(dev, PCI_COMMAND)
++ | PCI_COMMAND_MEMORY);
+
-+ uint16_t comp_status;
-+ uint16_t failure_code;
-+ uint32_t residual_count;
++ /* 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);
+
-+ 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 *);
++ /* 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);
+
- /*
- * 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);
++ ssb_set_drvdata(sdev, dev);
++ register_pci_controller(&dev->pci_controller);
+
-+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);
++ return 0;
++}
+
-+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 *);
++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);
+
- /*
- * 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);
++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;
+
-+extern void qla2xxx_get_flash_info(scsi_qla_host_t *);
++ if (pdev->bus->ops != &dev->pci_ops) {
++ /* The PCI device is not on this SSB GigE bridge device. */
++ return -ENODEV;
++ }
+
- /*
- * Global Function Prototypes in qla_dbg.c source file.
- */
-@@ -307,7 +323,6 @@ extern void qla24xx_fw_dump(scsi_qla_host_t *, int);
- extern void qla25xx_fw_dump(scsi_qla_host_t *, int);
- extern void qla2x00_dump_regs(scsi_qla_host_t *);
- extern void qla2x00_dump_buffer(uint8_t *, uint32_t);
--extern void qla2x00_print_scsi_cmd(struct scsi_cmnd *);
-
- /*
- * Global Function Prototypes in qla_gs.c source file.
-@@ -332,8 +347,8 @@ extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *);
- /*
- * Global Function Prototypes in qla_attr.c source file.
- */
--struct class_device_attribute;
--extern struct class_device_attribute *qla2x00_host_attrs[];
-+struct device_attribute;
-+extern struct device_attribute *qla2x00_host_attrs[];
- struct fc_function_template;
- extern struct fc_function_template qla2xxx_transport_functions;
- extern struct fc_function_template qla2xxx_transport_vport_functions;
-diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
-index c180876..750d7ef 100644
---- a/drivers/scsi/qla2xxx/qla_gs.c
-+++ b/drivers/scsi/qla2xxx/qla_gs.c
-@@ -1,17 +1,11 @@
- /*
- * QLogic Fibre Channel HBA Driver
-- * Copyright (c) 2003-2005 QLogic Corporation
-+ * Copyright (c) 2003-2008 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
- */
- #include "qla_def.h"
-
--static inline struct ct_sns_req *
--qla2x00_prep_ct_req(struct ct_sns_req *, uint16_t, uint16_t);
--
--static inline struct sns_cmd_pkt *
--qla2x00_prep_sns_cmd(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
--
- static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);
- static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);
- static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);
-@@ -1538,7 +1532,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
- eiter->a.sup_speed = __constant_cpu_to_be32(
- FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
- FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_8GB);
-- else if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
-+ else if (IS_QLA24XX_TYPE(ha))
- eiter->a.sup_speed = __constant_cpu_to_be32(
- FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
- FDMI_PORT_SPEED_4GB);
-@@ -1847,8 +1841,10 @@ qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list)
- "GPSC")) != QLA_SUCCESS) {
- /* FM command unsupported? */
- if (rval == QLA_INVALID_COMMAND &&
-- ct_rsp->header.reason_code ==
-- CT_REASON_INVALID_COMMAND_CODE) {
-+ (ct_rsp->header.reason_code ==
-+ CT_REASON_INVALID_COMMAND_CODE ||
-+ ct_rsp->header.reason_code ==
-+ CT_REASON_COMMAND_UNSUPPORTED)) {
- DEBUG2(printk("scsi(%ld): GPSC command "
- "unsupported, disabling query...\n",
- ha->host_no));
-diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
-index 364be7d..01e2608 100644
---- a/drivers/scsi/qla2xxx/qla_init.c
-+++ b/drivers/scsi/qla2xxx/qla_init.c
-@@ -1,6 +1,6 @@
- /*
- * QLogic Fibre Channel HBA Driver
-- * Copyright (c) 2003-2005 QLogic Corporation
-+ * Copyright (c) 2003-2008 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
- */
-@@ -15,14 +15,6 @@
- #include <asm/prom.h>
- #endif
-
--/* XXX(hch): this is ugly, but we don't want to pull in exioctl.h */
--#ifndef EXT_IS_LUN_BIT_SET
--#define EXT_IS_LUN_BIT_SET(P,L) \
-- (((P)->mask[L/8] & (0x80 >> (L%8)))?1:0)
--#define EXT_SET_LUN_BIT(P,L) \
-- ((P)->mask[L/8] |= (0x80 >> (L%8)))
--#endif
--
- /*
- * QLogic ISP2x00 Hardware Support Function Prototypes.
- */
-@@ -45,6 +37,9 @@ static int qla2x00_restart_isp(scsi_qla_host_t *);
-
- static int qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev);
-
-+static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *);
-+static int qla84xx_init_chip(scsi_qla_host_t *);
++ /* 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;
+
- /****************************************************************************/
- /* 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);
++ /* 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;
+ }
-+ 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;
++ return ssb_mips_irq(sdev) + 2;
++}
+
-+ /* 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));
++static struct ssb_driver ssb_gige_driver = {
++ .name = "BCM-GigE",
++ .id_table = ssb_gige_tbl,
++ .probe = ssb_gige_probe,
++};
+
- /*
- * Set default initialization control block.
- */
-@@ -2165,20 +2202,6 @@ cleanup_allocation:
- }
++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 void
--qla2x00_probe_for_all_luns(scsi_qla_host_t *ha)
+-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)
-{
-- fc_port_t *fcport;
+- struct resource *res;
+- int pos, size;
+- u32 *base;
-
-- qla2x00_mark_all_devices_lost(ha, 0);
-- list_for_each_entry(fcport, &ha->fcports, list) {
-- if (fcport->port_type != FCT_TARGET)
-- continue;
+- ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
+- pci_name(d));
-
-- qla2x00_update_fcport(ha, fcport);
+- /* 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);
-
--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);
+- return 0;
+-}
-
-- 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)
+-static void __init ssb_fixup_pcibridge(struct pci_dev *dev)
-{
-- int rescan_done;
-- fc_port_t *fcport;
+- u8 lat;
-
-- rescan_done = 0;
-- list_for_each_entry(fcport, &ha->fcports, list) {
-- if ((fcport->flags & FCF_RESCAN_NEEDED) == 0)
-- continue;
+- if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
+- return;
-
-- qla2x00_update_fcport(ha, fcport);
-- fcport->flags &= ~FCF_RESCAN_NEEDED;
+- ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev));
-
-- rescan_done = 1;
+- /* 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;
- }
-- qla2x00_probe_for_all_luns(ha);
+-
+- /* 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);
-
--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;
+-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+-{
+- return ssb_mips_irq(extpci_core->dev) + 2;
+-}
- /* 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);
+ 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,
+ };
- return rval;
- }
-+
-+/* 84XX Support **************************************************************/
-+
-+static LIST_HEAD(qla_cs84xx_list);
-+static DEFINE_MUTEX(qla_cs84xx_mutex);
++static u32 ssb_pcicore_pcibus_iobase = 0x100;
++static u32 ssb_pcicore_pcibus_membase = SSB_PCI_DMA;
+
-+static struct qla_chip_state_84xx *
-+qla84xx_get_chip(struct scsi_qla_host *ha)
++/* 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 qla_chip_state_84xx *cs84xx;
-+
-+ mutex_lock(&qla_cs84xx_mutex);
++ struct resource *res;
++ int pos, size;
++ u32 *base;
+
-+ /* 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;
-+ }
++ if (d->bus->ops != &ssb_pcicore_pciops) {
++ /* This is not a device on the PCI-core bridge. */
++ return -ENODEV;
+ }
+
-+ cs84xx = kzalloc(sizeof(*cs84xx), GFP_KERNEL);
-+ if (!cs84xx)
-+ goto done;
++ ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
++ pci_name(d));
+
-+ kref_init(&cs84xx->kref);
-+ spin_lock_init(&cs84xx->access_lock);
-+ mutex_init(&cs84xx->fw_update_mutex);
-+ cs84xx->bus = ha->pdev->bus;
++ /* 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);
+
-+ list_add_tail(&cs84xx->list, &qla_cs84xx_list);
-+done:
-+ mutex_unlock(&qla_cs84xx_mutex);
-+ return cs84xx;
++ return 0;
+}
+
-+static void
-+__qla84xx_chip_release(struct kref *kref)
++/* Early PCI fixup for a device on the PCI-core bridge. */
++static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev)
+{
-+ 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);
-+}
++ u8 lat;
+
-+void
-+qla84xx_put_chip(struct scsi_qla_host *ha)
-+{
-+ if (ha->cs84xx)
-+ kref_put(&ha->cs84xx->kref, __qla84xx_chip_release);
-+}
++ 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;
+
-+static int
-+qla84xx_init_chip(scsi_qla_host_t *ha)
-+{
-+ int rval;
-+ uint16_t status[2];
++ ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev));
+
-+ mutex_lock(&ha->cs84xx->fw_update_mutex);
++ /* 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;
++ }
+
-+ rval = qla84xx_verify_chip(ha, status);
++ /* Enable PCI bridge BAR1 prefetch and burst */
++ pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3);
+
-+ mutex_unlock(&ha->cs84xx->fw_update_mutex);
++ /* 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);
+
-+ return rval != QLA_SUCCESS || status[0] ? QLA_FUNCTION_FAILED:
-+ QLA_SUCCESS;
++/* 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;
+}
-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)
++
+ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
{
-diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
-index 024c662..5489d50 100644
---- a/drivers/scsi/qla2xxx/qla_iocb.c
-+++ b/drivers/scsi/qla2xxx/qla_iocb.c
-@@ -1,6 +1,6 @@
- /*
- * QLogic Fibre Channel HBA Driver
-- * Copyright (c) 2003-2005 QLogic Corporation
-+ * Copyright (c) 2003-2008 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
- */
-@@ -11,9 +11,6 @@
-
- #include <scsi/scsi_tcq.h>
-
--static inline uint16_t qla2x00_get_cmd_direction(struct scsi_cmnd *cmd);
--static inline cont_entry_t *qla2x00_prep_cont_type0_iocb(scsi_qla_host_t *);
--static inline cont_a64_entry_t *qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *);
- static request_t *qla2x00_req_pkt(scsi_qla_host_t *ha);
- static void qla2x00_isp_cmd(scsi_qla_host_t *ha);
-
-diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
-index f033703..285479b 100644
---- a/drivers/scsi/qla2xxx/qla_isr.c
-+++ b/drivers/scsi/qla2xxx/qla_isr.c
-@@ -1,6 +1,6 @@
- /*
- * QLogic Fibre Channel HBA Driver
-- * Copyright (c) 2003-2005 QLogic Corporation
-+ * Copyright (c) 2003-2008 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
- */
-@@ -14,9 +14,6 @@ static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t);
- static void qla2x00_status_entry(scsi_qla_host_t *, void *);
- static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *);
- static void qla2x00_error_entry(scsi_qla_host_t *, sts_entry_t *);
--static void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *);
--
--static void qla24xx_ms_entry(scsi_qla_host_t *, struct ct_entry_24xx *);
-
- /**
- * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
-@@ -33,7 +30,6 @@ qla2100_intr_handler(int irq, void *dev_id)
- scsi_qla_host_t *ha;
- struct device_reg_2xxx __iomem *reg;
- int status;
-- unsigned long flags;
- unsigned long iter;
- uint16_t hccr;
- uint16_t mb[4];
-@@ -48,7 +44,7 @@ qla2100_intr_handler(int irq, void *dev_id)
- reg = &ha->iobase->isp;
- status = 0;
-
-- spin_lock_irqsave(&ha->hardware_lock, flags);
-+ spin_lock(&ha->hardware_lock);
- for (iter = 50; iter--; ) {
- hccr = RD_REG_WORD(®->hccr);
- if (hccr & HCCR_RISC_PAUSE) {
-@@ -99,7 +95,7 @@ qla2100_intr_handler(int irq, void *dev_id)
- RD_REG_WORD(®->hccr);
- }
- }
-- spin_unlock_irqrestore(&ha->hardware_lock, flags);
-+ spin_unlock(&ha->hardware_lock);
-
- if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
- (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
-@@ -125,7 +121,6 @@ qla2300_intr_handler(int irq, void *dev_id)
- scsi_qla_host_t *ha;
- struct device_reg_2xxx __iomem *reg;
- int status;
-- unsigned long flags;
- unsigned long iter;
- uint32_t stat;
- uint16_t hccr;
-@@ -141,7 +136,7 @@ qla2300_intr_handler(int irq, void *dev_id)
- reg = &ha->iobase->isp;
- status = 0;
+ u32 val;
+@@ -544,15 +562,9 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
+ u32 intvec;
-- 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);
+ 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);
}
-- 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;
+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 @@
- 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;
+ #include <linux/ssb/ssb.h>
+ #include <linux/ssb/ssb_embedded.h>
++#include <linux/ssb/ssb_driver_pci.h>
++#include <linux/ssb/ssb_driver_gige.h>
++#include <linux/pci.h>
- 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;
-+ }
-+ }
-+ }
-+ }
+ #include "ssb_private.h"
- 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)
+@@ -130,3 +133,90 @@ u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value)
+ return res;
+ }
+ EXPORT_SYMBOL(ssb_gpio_polarity);
++
++#ifdef CONFIG_SSB_DRIVER_GIGE
++static int gige_pci_init_callback(struct ssb_bus *bus, unsigned long data)
++{
++ struct pci_dev *pdev = (struct pci_dev *)data;
++ struct ssb_device *dev;
++ unsigned int i;
++ int res;
++
++ for (i = 0; i < bus->nr_devices; i++) {
++ dev = &(bus->devices[i]);
++ if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
++ continue;
++ if (!dev->dev ||
++ !dev->dev->driver ||
++ !device_is_registered(dev->dev))
++ continue;
++ res = ssb_gige_pcibios_plat_dev_init(dev, pdev);
++ if (res >= 0)
++ return res;
++ }
++
++ return -ENODEV;
++}
++#endif /* CONFIG_SSB_DRIVER_GIGE */
++
++int ssb_pcibios_plat_dev_init(struct pci_dev *dev)
++{
++ int err;
++
++ err = ssb_pcicore_plat_dev_init(dev);
++ if (!err)
++ return 0;
++#ifdef CONFIG_SSB_DRIVER_GIGE
++ err = ssb_for_each_bus_call((unsigned long)dev, gige_pci_init_callback);
++ if (err >= 0)
++ return err;
++#endif
++ /* This is not a PCI device on any SSB device. */
++
++ return -ENODEV;
++}
++
++#ifdef CONFIG_SSB_DRIVER_GIGE
++static int gige_map_irq_callback(struct ssb_bus *bus, unsigned long data)
++{
++ const struct pci_dev *pdev = (const struct pci_dev *)data;
++ struct ssb_device *dev;
++ unsigned int i;
++ int res;
++
++ for (i = 0; i < bus->nr_devices; i++) {
++ dev = &(bus->devices[i]);
++ if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
++ continue;
++ if (!dev->dev ||
++ !dev->dev->driver ||
++ !device_is_registered(dev->dev))
++ continue;
++ res = ssb_gige_map_irq(dev, pdev);
++ if (res >= 0)
++ return res;
++ }
++
++ return -ENODEV;
++}
++#endif /* CONFIG_SSB_DRIVER_GIGE */
++
++int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++ int res;
++
++ /* Check if this PCI device is a device on a SSB bus or device
++ * and return the IRQ number for it. */
++
++ res = ssb_pcicore_pcibios_map_irq(dev, slot, pin);
++ if (res >= 0)
++ return res;
++#ifdef CONFIG_SSB_DRIVER_GIGE
++ res = ssb_for_each_bus_call((unsigned long)dev, gige_map_irq_callback);
++ if (res >= 0)
++ return res;
++#endif
++ /* This is not a PCI device on any SSB device. */
++
++ return -ENODEV;
++}
+diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
+index 8003a9e..7cf8851 100644
+--- a/drivers/ssb/main.c
++++ b/drivers/ssb/main.c
+@@ -14,6 +14,7 @@
+ #include <linux/io.h>
+ #include <linux/ssb/ssb.h>
+ #include <linux/ssb/ssb_regs.h>
++#include <linux/ssb/ssb_driver_gige.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/pci.h>
- 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;
+@@ -68,6 +69,44 @@ found:
+ }
+ #endif /* CONFIG_SSB_PCIHOST */
- /* 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;
++#ifdef CONFIG_SSB_PCMCIAHOST
++struct ssb_bus *ssb_pcmcia_dev_to_bus(struct pcmcia_device *pdev)
++{
++ struct ssb_bus *bus;
+
-+ case MBA_ISP84XX_ALERT:
-+ DEBUG2(printk("scsi(%ld): ISP84XX Alert Notification -- "
-+ "%04x %04x %04x\n", ha->host_no, mb[1], mb[2], mb[3]));
++ 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();
+
-+ 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]);
++ 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;
+ }
-+ 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)
++ }
++ 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);
}
- /**
-- * 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)
+-static int ssb_bus_resume(struct ssb_bus *bus)
-{
-- 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");
+- int err;
-
-- set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
-- return;
+- 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);
-
-- 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);
+- return 0;
-}
-
--
--/**
- * 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);
+ 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;
- 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;
+- 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;
}
--/**
-- * 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)
+-static void ssb_bus_suspend(struct ssb_bus *bus, pm_message_t state)
-{
-- 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;
+- ssb_chipco_suspend(&bus->chipco, state);
+- ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0);
-
-- qla2x00_sp_compl(ha, sp);
+- /* 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 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)
+ static int ssb_device_suspend(struct device *dev, pm_message_t state)
{
- 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);
+ struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
+ struct ssb_driver *ssb_drv;
+- struct ssb_bus *bus;
+ int err = 0;
-@@ -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;
+ if (dev->driver) {
+@@ -151,19 +150,46 @@ static int ssb_device_suspend(struct device *dev, pm_message_t state)
+ if (err)
+ goto out;
}
-- 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;
++out:
++ return err;
++}
+
-+ qla2xxx_hw_event_log(ha, HW_EVENT_ISP_ERR, 0,
-+ LSW(RD_REG_DWORD(®->hccr)),
-+ LSW(RD_REG_DWORD(®->istatus)));
-+ }
- }
++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
- 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;
+- 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);
-- 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;
+-out:
+- return err;
++ return 0;
}
++EXPORT_SYMBOL(ssb_bus_resume);
-+int
-+qla2x00_issue_iocb(scsi_qla_host_t *ha, void *buffer, dma_addr_t phys_addr,
-+ size_t size)
+-#ifdef CONFIG_SSB_PCIHOST
++int ssb_bus_suspend(struct ssb_bus *bus)
+{
-+ return qla2x00_issue_iocb_timeout(ha, buffer, phys_addr, size,
-+ MBX_TOV_SECONDS);
++ ssb_chipco_suspend(&bus->chipco);
++ ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0);
++
++ return 0;
+}
++EXPORT_SYMBOL(ssb_bus_suspend);
+
- /*
- * 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);
++#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)
-@@ -776,36 +792,20 @@ qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp)
- return rval;
+ return 0;
}
+-#endif /* CONFIG_SSB_PCIHOST */
++#endif /* CONFIG_SSB_SPROM */
--#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)
+ static void ssb_device_shutdown(struct device *dev)
{
-- int rval;
-+ int rval, rval2;
- mbx_cmd_t mc;
- mbx_cmd_t *mcp = &mc;
- scsi_qla_host_t *ha;
+@@ -378,7 +404,7 @@ void ssb_bus_unregister(struct ssb_bus *bus)
+ list_del(&bus->list);
+ ssb_buses_unlock();
-- if (fcport == NULL)
-- return 0;
--
- DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
+- /* ssb_pcmcia_exit(bus); */
++ ssb_pcmcia_exit(bus);
+ ssb_pci_exit(bus);
+ ssb_iounmap(bus);
+ }
+@@ -508,6 +534,14 @@ error:
+ return err;
+ }
-+ 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;
++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);
+ }
- 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));
++#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;
+ }
-
-- /* 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));
++ 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;
+
-+ return rval;
++ 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 */
+
-+int
-+qla2x00_lun_reset(struct fc_port *fcport, unsigned int l)
++static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
+{
-+ int rval, rval2;
-+ mbx_cmd_t mc;
-+ mbx_cmd_t *mcp = &mc;
-+ scsi_qla_host_t *ha;
++ struct ssb_bus *bus = dev->bus;
+
-+ DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
++ offset += dev->core_index * SSB_CORE_SIZE;
++ writeb(value, bus->mmio + offset);
++}
+
-+ 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;
+ 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);
+ }
-+ 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));
++#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;
+
-+ /* 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);
++ 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
+ };
- 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)
+ 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)
{
- 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;
+ 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;
}
- 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;
+ 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;
}
-- 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;
- };
+@@ -1175,6 +1328,7 @@ fs_initcall(ssb_modinit);
--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)
+ static void __exit ssb_modexit(void)
{
-- int rval;
-+ int rval, rval2;
- struct tsk_mgmt_cmd *tsk;
- dma_addr_t tsk_dma;
- scsi_qla_host_t *ha, *pha;
++ 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;
+ }
-- if (fcport == NULL)
-- return 0;
--
- DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
+-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;
+ }
- 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));
-+ }
+-static void sprom_do_read(struct ssb_bus *bus, u16 *sprom)
++static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
+ {
+ int i;
- 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;
- }
+ for (i = 0; i < bus->sprom_size; i++)
+ sprom[i] = ioread16(bus->mmio + SSB_SPROM_BASE + (i * 2));
++
++ return 0;
+ }
- /* 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));
+ 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;
}
--atarget_done:
- dma_pool_free(pha->s_dma_pool, tsk, tsk_dma);
-
- return rval;
++ 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 */
-+int
-+qla24xx_abort_target(struct fc_port *fcport, unsigned int l)
++static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
+{
-+ return __qla24xx_issue_tmf("Target", TCF_TARGET_RESET, fcport, l);
-+}
++ struct ssb_bus *bus = dev->bus;
+
-+int
-+qla24xx_lun_reset(struct fc_port *fcport, unsigned int l)
-+{
-+ return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l);
++ 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);
+}
+
- #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;
+ 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);
}
-+
-+/* 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)
+
++#ifdef CONFIG_SSB_BLOCKIO
++static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
++ size_t count, u16 offset, u8 reg_width)
+{
-+ 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));
++ struct ssb_bus *bus = dev->bus;
++ void __iomem *addr = bus->mmio + offset;
+
-+ 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;
++ 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);
+ }
+
-+ /* 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]));
++ return;
++error:
++ memset(buffer, 0xFF, count);
++}
++#endif /* CONFIG_SSB_BLOCKIO */
+
-+ 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)));
++static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
++{
++ struct ssb_bus *bus = dev->bus;
+
-+ /* 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);
++ 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);
++}
+
-+verify_done:
-+ dma_pool_free(ha->s_dma_pool, mn, mn_dma);
+ 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 (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));
++ 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);
+ }
-+
-+ return rval;
+}
-diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
-index cf784cd..f2b0497 100644
---- a/drivers/scsi/qla2xxx/qla_mid.c
-+++ b/drivers/scsi/qla2xxx/qla_mid.c
-@@ -1,20 +1,8 @@
- /*
-- * QLOGIC LINUX SOFTWARE
-- *
-- * QLogic ISP2x00 device driver for Linux 2.6.x
-- * Copyright (C) 2003-2005 QLogic Corporation
-- * (www.qlogic.com)
-- *
-- * This program is free software; you can redistribute it and/or modify it
-- * under the terms of the GNU General Public License as published by the
-- * Free Software Foundation; either version 2, or (at your option) any
-- * later version.
-- *
-- * This program is distributed in the hope that it will be useful, but
-- * WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- * General Public License for more details.
-+ * QLogic Fibre Channel HBA Driver
-+ * Copyright (c) 2003-2008 QLogic Corporation
- *
-+ * See LICENSE.qla2xxx for copyright and licensing details.
- */
- #include "qla_def.h"
-
-@@ -28,8 +16,6 @@
- #include <scsi/scsicam.h>
- #include <linux/delay.h>
++#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
+ };
--void qla2x00_vp_stop_timer(scsi_qla_host_t *);
+-static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, u16 size)
+-{
+- int i, pos = 0;
-
- 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)
+- 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)
{
-+ 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)
+ struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
+ struct ssb_bus *bus;
+- u16 *sprom;
+- int err = -ENODEV;
+- ssize_t count = 0;
- strcpy(str, "PCIe (");
- if (lspeed == 1)
-- strcat(str, "2.5Gb/s ");
-+ strcat(str, "2.5GT/s ");
- else if (lspeed == 2)
-- strcat(str, "5.0Gb/s ");
-+ strcat(str, "5.0GT/s ");
- else
- strcat(str, "<unknown> ");
- snprintf(lwstr, sizeof(lwstr), "x%d)", lwidth);
-@@ -340,6 +339,8 @@ qla24xx_fw_version_str(struct scsi_qla_host *ha, char *str)
- strcat(str, "[T10 CRC] ");
- if (ha->fw_attributes & BIT_5)
- strcat(str, "[VI] ");
-+ if (ha->fw_attributes & BIT_10)
-+ strcat(str, "[84XX] ");
- if (ha->fw_attributes & BIT_13)
- strcat(str, "[Experimental]");
- return str;
-@@ -570,8 +571,6 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *ha)
- else
- return_status = QLA_FUNCTION_FAILED;
+ 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;
-- DEBUG2(printk("%s return_status=%d\n",__func__,return_status));
+- /* 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);
-
- return (return_status);
+- 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);
}
-@@ -685,7 +684,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
+ 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;
- DEBUG2(printk("%s(%ld): aborting sp %p from RISC. pid=%ld.\n",
- __func__, ha->host_no, sp, serial));
-- DEBUG3(qla2x00_print_scsi_cmd(cmd));
+ 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;
- 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;
+- /* 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);
}
--/**************************************************************************
--* 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);
+ static DEVICE_ATTR(ssb_sprom, 0600,
+@@ -780,7 +790,7 @@ int ssb_pci_init(struct ssb_bus *bus)
+ return 0;
-- 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);
+ 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;
+
-+ return status;
- }
-
-+static char *reset_errors[] = {
-+ "HBA not online",
-+ "HBA not ready",
-+ "Task management failed",
-+ "Waiting for command completions",
-+};
++ 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)
--/**************************************************************************
--* 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))
+ static int ssb_pcihost_resume(struct pci_dev *dev)
{
- 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;
++ struct ssb_bus *ssb = pci_get_drvdata(dev);
+ int err;
- qla2x00_block_error_handler(cmd);
+ 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;
-- id = cmd->device->id;
-- lun = cmd->device->lun;
-- serial = cmd->serial_number;
--
- if (!fcport)
-- return ret;
-+ return FAILED;
+ return 0;
+ }
+diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
+index 46816cd..24c2a46 100644
+--- a/drivers/ssb/pcmcia.c
++++ b/drivers/ssb/pcmcia.c
+@@ -3,7 +3,7 @@
+ * PCMCIA-Hostbus related functions
+ *
+ * Copyright 2006 Johannes Berg <johannes at sipsolutions.net>
+- * Copyright 2007 Michael Buesch <mb at bu3sch.de>
++ * Copyright 2007-2008 Michael Buesch <mb at bu3sch.de>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+@@ -11,6 +11,7 @@
+ #include <linux/ssb/ssb.h>
+ #include <linux/delay.h>
+ #include <linux/io.h>
++#include <linux/etherdevice.h>
-- 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);
+ #include <pcmcia/cs_types.h>
+ #include <pcmcia/cs.h>
+@@ -26,59 +27,127 @@
+ #define SSB_VERBOSE_PCMCIACORESWITCH_DEBUG 0
-+ 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;
+
++/* 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
+
-+ qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): %s RESET SUCCEEDED.\n",
-+ ha->host_no, cmd->device->id, cmd->device->lun, name);
++/* 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
+
-+ return SUCCESS;
++/* PCMCIA SPROM size. */
++#define SSB_PCMCIA_SPROM_SIZE 256
++#define SSB_PCMCIA_SPROM_SIZE_BYTES (SSB_PCMCIA_SPROM_SIZE * sizeof(u16))
+
-+ 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;
++
++/* 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;
+}
-
-- goto eh_dev_reset_done;
-- }
-+static int
-+qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
++
++/* Read from a PCMCIA configuration register. */
++static int ssb_pcmcia_cfg_read(struct ssb_bus *bus, u8 offset, u8 *value)
+{
-+ 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)
++ 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)
{
-- 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;
+- 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;
- /* 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;
+ 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;
- eh_bus_reset_done:
-@@ -1024,7 +955,8 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
- clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
+ read_addr = 0;
- /* 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;
+- 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;
- if (ha->parent)
-@@ -1080,7 +1012,7 @@ qla2x00_loop_reset(scsi_qla_host_t *ha)
- if (fcport->port_type != FCT_TARGET)
- continue;
+ cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE;
+ if (cur_core == coreidx)
+ break;
-- 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;
++ 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;
}
--/*
-- * 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)
+ 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)
{
-@@ -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);
+ int attempts = 0;
+- conf_reg_t reg;
+- int res;
++ int err;
++ u8 val;
- set_bit(0, (unsigned long *) ha->vp_idx_map);
+ 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;
-@@ -1819,6 +1746,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
++ 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;
+ }
- qla2x00_dfs_remove(ha);
+ 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;
+ }
-+ qla84xx_put_chip(ha);
++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;
+
- 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);
++ 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));
}
-+struct qla_work_evt *
-+qla2x00_alloc_work(struct scsi_qla_host *ha, enum qla_work_type type,
-+ int locked)
++#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 qla_work_evt *e;
++ struct ssb_bus *bus = dev->bus;
++ unsigned long flags;
++ void __iomem *addr = bus->mmio + offset;
++ int err;
+
-+ e = kzalloc(sizeof(struct qla_work_evt), locked ? GFP_ATOMIC:
-+ GFP_KERNEL);
-+ if (!e)
-+ return NULL;
++ 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;
+
-+ INIT_LIST_HEAD(&e->list);
-+ e->type = type;
-+ e->flags = QLA_EVT_FLAG_FREE;
-+ return e;
++ 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 */
+
-+int
-+qla2x00_post_work(struct scsi_qla_host *ha, struct qla_work_evt *e, int locked)
++static void ssb_pcmcia_write8(struct ssb_device *dev, u16 offset, u8 value)
+{
++ struct ssb_bus *bus = dev->bus;
+ unsigned long flags;
++ int err;
+
-+ 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;
++ 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);
+}
+
-+int
-+qla2x00_post_aen_work(struct scsi_qla_host *ha, enum fc_host_event_code code,
-+ u32 data)
+ 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 qla_work_evt *e;
++ struct ssb_bus *bus = dev->bus;
++ unsigned long flags;
++ void __iomem *addr = bus->mmio + offset;
++ int err;
+
-+ e = qla2x00_alloc_work(ha, QLA_EVT_AEN, 1);
-+ if (!e)
-+ return QLA_FUNCTION_FAILED;
++ 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;
+
-+ e->u.aen.code = code;
-+ e->u.aen.data = data;
-+ return qla2x00_post_work(ha, e, 1);
++ 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 */
+
-+int
-+qla2x00_post_hwe_work(struct scsi_qla_host *ha, uint16_t code, uint16_t d1,
-+ uint16_t d2, uint16_t d3)
+ /* Not "static", as it's used in main.c */
+ const struct ssb_bus_ops ssb_pcmcia_ops = {
++ .read8 = ssb_pcmcia_read8,
+ .read16 = ssb_pcmcia_read16,
+ .read32 = ssb_pcmcia_read32,
++ .write8 = ssb_pcmcia_write8,
+ .write16 = ssb_pcmcia_write16,
+ .write32 = ssb_pcmcia_write32,
++#ifdef CONFIG_SSB_BLOCKIO
++ .block_read = ssb_pcmcia_block_read,
++ .block_write = ssb_pcmcia_block_write,
++#endif
+ };
+
+-#include <linux/etherdevice.h>
++static int ssb_pcmcia_sprom_command(struct ssb_bus *bus, u8 command)
+{
-+ struct qla_work_evt *e;
++ unsigned int i;
++ int err;
++ u8 value;
+
-+ e = qla2x00_alloc_work(ha, QLA_EVT_HWE_LOG, 1);
-+ if (!e)
-+ return QLA_FUNCTION_FAILED;
++ 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);
++ }
+
-+ 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);
++ return -ETIMEDOUT;
+}
+
-+static void
-+qla2x00_do_work(struct scsi_qla_host *ha)
++/* offset is the 16bit word offset */
++static int ssb_pcmcia_sprom_read(struct ssb_bus *bus, u16 offset, u16 *value)
+{
-+ struct qla_work_evt *e;
++ int err;
++ u8 lo, hi;
+
-+ 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);
++ offset *= 2; /* Make byte offset */
+
-+ 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);
++ 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;
+ }
-+ if (e->flags & QLA_EVT_FLAG_FREE)
-+ kfree(e);
-+ spin_lock_irq(&ha->hardware_lock);
+ }
-+ spin_unlock_irq(&ha->hardware_lock);
++ 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;
+}
+
- /**************************************************************************
- * 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);
++static int ssb_pcmcia_sprom_check_crc(const u16 *sprom, size_t size)
++{
++ //TODO
++ return 0;
++}
+
- 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)
++#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)
{
-- 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;
+- //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;
+
-+ 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);
++ 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");
+ }
-
-- 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;
++ GOTO_ERROR_ON(tuple.TupleDataLen != ETH_ALEN + 2, "MAC tpl size");
++ memcpy(sprom->il0mac, &tuple.TupleData[2], ETH_ALEN);
+
-+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;
++ /* 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");
++ }
+
- 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;
- }
+ return 0;
++error:
++ ssb_printk(KERN_ERR PFX
++ "PCMCIA: Failed to fetch device invariants: %s\n",
++ error_description);
++ return -ENODEV;
+ }
-+ 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));
+-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 void
-+qla24xx_unprotect_flash(scsi_qla_host_t *ha)
++static ssize_t ssb_pcmcia_attr_sprom_store(struct device *pcmciadev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
+{
-+ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
++ struct pcmcia_device *pdev =
++ container_of(pcmciadev, struct pcmcia_device, dev);
++ struct ssb_bus *bus;
+
- /* 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;
++ bus = ssb_pcmcia_dev_to_bus(pdev);
++ if (!bus)
++ return -ENODEV;
+
- /* 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);
++ return ssb_attr_sprom_store(bus, buf, count,
++ ssb_pcmcia_sprom_check_crc,
++ ssb_pcmcia_sprom_write_all);
+}
+
-+static void
-+qla24xx_protect_flash(scsi_qla_host_t *ha)
++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)
+{
-+ uint32_t cnt;
-+ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
++ u8 val;
++ int err;
+
-+ if (!ha->fdt_wrt_disable)
-+ goto skip_wrt_protect;
++ 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);
+
-+ /* 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);
-+ }
++ return 0;
++}
+
-+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. */
++/* 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;
+}
+
-+static int
-+qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
-+ uint32_t dwords)
++void ssb_pcmcia_exit(struct ssb_bus *bus)
+{
-+ 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;
++ if (bus->bustype != SSB_BUSTYPE_PCMCIA)
++ return;
+
-+ ret = QLA_SUCCESS;
++ device_remove_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
++}
+
-+ /* 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);
-+ }
-+ }
++int ssb_pcmcia_init(struct ssb_bus *bus)
++{
++ int err;
+
-+ rest_addr = (ha->fdt_block_size >> 2) - 1;
-+ sec_mask = 0x80000 - (ha->fdt_block_size >> 2);
++ if (bus->bustype != SSB_BUSTYPE_PCMCIA)
++ return 0;
+
-+ 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)
++ 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 ret;
+ return 0;
+ error:
+- return -ENODEV;
++ ssb_printk(KERN_ERR PFX "Failed to initialize PCMCIA host device\n");
++ return err;
}
+diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c
+new file mode 100644
+index 0000000..3668edb
+--- /dev/null
++++ b/drivers/ssb/sprom.c
+@@ -0,0 +1,133 @@
++/*
++ * Sonics Silicon Backplane
++ * Common SPROM support routines
++ *
++ * Copyright (C) 2005-2008 Michael Buesch <mb at bu3sch.de>
++ * Copyright (C) 2005 Martin Langer <martin-langer at gmx.de>
++ * Copyright (C) 2005 Stefano Brivio <st3 at riseup.net>
++ * Copyright (C) 2005 Danny van Dyk <kugelfang at gentoo.org>
++ * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi at waterwave.ch>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
+
-+static int
-+qla2xxx_hw_event_store(scsi_qla_host_t *ha, uint32_t *fdata)
++#include "ssb_private.h"
++
++
++static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len,
++ size_t sprom_size_words)
+{
-+ uint32_t d[2], faddr;
++ int i, pos = 0;
+
-+ /* 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;
-+ }
++ 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");
+
-+ 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);
++ return pos + 1;
++}
+
-+ 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);
++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;
+
-+ qla24xx_protect_flash(ha);
-+ break;
-+ }
++ 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 QLA_SUCCESS;
++
++ return 0;
+}
+
-+int
-+qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1,
-+ uint16_t d2, uint16_t d3)
++/* 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))
+{
-+#define QMARK(a, b, c, d) \
-+ cpu_to_le32(LSB(a) << 24 | LSB(b) << 16 | LSB(c) << 8 | LSB(d))
++ u16 *sprom;
++ int err = -ENOMEM;
++ ssize_t count = 0;
++ size_t sprom_size_words = bus->sprom_size;
+
-+ int rval;
-+ uint32_t marker[2], fdata[4];
++ sprom = kcalloc(sprom_size_words, sizeof(u16), GFP_KERNEL);
++ if (!sprom)
++ goto out;
+
-+ if (ha->hw_event_start == 0)
-+ return QLA_FUNCTION_FAILED;
++ /* 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);
+
-+ DEBUG2(qla_printk(KERN_WARNING, ha,
-+ "HW event -- code=%x, d1=%x, d2=%x, d3=%x.\n", code, d1, d2, d3));
++ if (!err)
++ count = sprom2hex(sprom, buf, PAGE_SIZE, sprom_size_words);
+
-+ /* 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);
++out_kfree:
++ kfree(sprom);
++out:
++ return err ? err : count;
++}
+
-+ /* 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;
-+ }
-+ }
++/* 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;
+
-+ /* 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));
++ 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;
+ }
+
-+ return rval;
++ /* 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/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
+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);
- 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();
++/* 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);
++
-@@ -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;
+ /* b43_pci_bridge.c */
+ #ifdef CONFIG_SSB_B43_PCI_BRIDGE
+diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
+index 17e71d5..4b62852 100644
+--- a/drivers/thermal/Kconfig
++++ b/drivers/thermal/Kconfig
+@@ -3,7 +3,7 @@
+ #
-- /* 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;
+ menuconfig THERMAL
+- bool "Generic Thermal sysfs driver"
++ tristate "Generic Thermal sysfs driver"
+ help
+ Generic Thermal Sysfs driver offers a generic mechanism for
+ thermal management. Usually it's made up of one or more thermal
+@@ -11,4 +11,4 @@ menuconfig THERMAL
+ Each thermal zone contains its own temperature, trip points,
+ cooling devices.
+ All platforms with ACPI thermal support can use this driver.
+- If you want this support, you should say Y here.
++ If you want this support, you should say Y or M here.
+diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
+index 8ef1232..31108a0 100644
+--- a/drivers/thermal/Makefile
++++ b/drivers/thermal/Makefile
+@@ -2,4 +2,4 @@
+ # Makefile for sensor chip drivers.
+ #
+
+-obj-$(CONFIG_THERMAL) += thermal.o
++obj-$(CONFIG_THERMAL) += thermal_sys.o
+diff --git a/drivers/thermal/thermal.c b/drivers/thermal/thermal.c
+deleted file mode 100644
+index 7f79bbf..0000000
+--- a/drivers/thermal/thermal.c
++++ /dev/null
+@@ -1,736 +0,0 @@
+-/*
+- * thermal.c - Generic Thermal Management Sysfs support.
+- *
+- * Copyright (C) 2008 Intel Corp
+- * Copyright (C) 2008 Zhang Rui <rui.zhang at intel.com>
+- * Copyright (C) 2008 Sujith Thomas <sujith.thomas at intel.com>
+- *
+- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; version 2 of the License.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * General Public License for more details.
+- *
+- * You 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.
+- *
+- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+- */
-
-- ha->marker_needed = 0;
+-#include <linux/module.h>
+-#include <linux/device.h>
+-#include <linux/err.h>
+-#include <linux/kdev_t.h>
+-#include <linux/idr.h>
+-#include <linux/thermal.h>
+-#include <linux/spinlock.h>
+-
+-MODULE_AUTHOR("Zhang Rui")
+-MODULE_DESCRIPTION("Generic thermal management sysfs support");
+-MODULE_LICENSE("GPL");
+-
+-#define PREFIX "Thermal: "
+-
+-struct thermal_cooling_device_instance {
+- int id;
+- char name[THERMAL_NAME_LENGTH];
+- struct thermal_zone_device *tz;
+- struct thermal_cooling_device *cdev;
+- int trip;
+- char attr_name[THERMAL_NAME_LENGTH];
+- struct device_attribute attr;
+- struct list_head node;
+-};
+-
+-static DEFINE_IDR(thermal_tz_idr);
+-static DEFINE_IDR(thermal_cdev_idr);
+-static DEFINE_MUTEX(thermal_idr_lock);
+-
+-static LIST_HEAD(thermal_tz_list);
+-static LIST_HEAD(thermal_cdev_list);
+-static DEFINE_MUTEX(thermal_list_lock);
+-
+-static int get_idr(struct idr *idr, struct mutex *lock, int *id)
+-{
+- int err;
+-
+- again:
+- if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
+- return -ENOMEM;
+-
+- if (lock)
+- mutex_lock(lock);
+- err = idr_get_new(idr, NULL, id);
+- if (lock)
+- mutex_unlock(lock);
+- if (unlikely(err == -EAGAIN))
+- goto again;
+- else if (unlikely(err))
+- return err;
+-
+- *id = *id & MAX_ID_MASK;
+- return 0;
+-}
+-
+-static void release_idr(struct idr *idr, struct mutex *lock, int id)
+-{
+- if (lock)
+- mutex_lock(lock);
+- idr_remove(idr, id);
+- if (lock)
+- mutex_unlock(lock);
+-}
+-
+-/* sys I/F for thermal zone */
+-
+-#define to_thermal_zone(_dev) \
+- container_of(_dev, struct thermal_zone_device, device)
+-
+-static ssize_t
+-type_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct thermal_zone_device *tz = to_thermal_zone(dev);
+-
+- return sprintf(buf, "%s\n", tz->type);
+-}
+-
+-static ssize_t
+-temp_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct thermal_zone_device *tz = to_thermal_zone(dev);
+-
+- if (!tz->ops->get_temp)
+- return -EPERM;
+-
+- return tz->ops->get_temp(tz, buf);
+-}
+-
+-static ssize_t
+-mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct thermal_zone_device *tz = to_thermal_zone(dev);
+-
+- if (!tz->ops->get_mode)
+- return -EPERM;
+-
+- return tz->ops->get_mode(tz, buf);
+-}
+-
+-static ssize_t
+-mode_store(struct device *dev, struct device_attribute *attr,
+- const char *buf, size_t count)
+-{
+- struct thermal_zone_device *tz = to_thermal_zone(dev);
+- int result;
+-
+- if (!tz->ops->set_mode)
+- return -EPERM;
+-
+- result = tz->ops->set_mode(tz, buf);
+- if (result)
+- return result;
+-
+- return count;
+-}
+-
+-static ssize_t
+-trip_point_type_show(struct device *dev, struct device_attribute *attr,
+- char *buf)
+-{
+- struct thermal_zone_device *tz = to_thermal_zone(dev);
+- int trip;
+-
+- if (!tz->ops->get_trip_type)
+- return -EPERM;
+-
+- if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip))
+- return -EINVAL;
+-
+- return tz->ops->get_trip_type(tz, trip, buf);
+-}
+-
+-static ssize_t
+-trip_point_temp_show(struct device *dev, struct device_attribute *attr,
+- char *buf)
+-{
+- struct thermal_zone_device *tz = to_thermal_zone(dev);
+- int trip;
+-
+- if (!tz->ops->get_trip_temp)
+- return -EPERM;
+-
+- if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
+- return -EINVAL;
+-
+- return tz->ops->get_trip_temp(tz, trip, buf);
+-}
+-
+-static DEVICE_ATTR(type, 0444, type_show, NULL);
+-static DEVICE_ATTR(temp, 0444, temp_show, NULL);
+-static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
+-
+-static struct device_attribute trip_point_attrs[] = {
+- __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL),
+- __ATTR(trip_point_0_temp, 0444, trip_point_temp_show, NULL),
+- __ATTR(trip_point_1_type, 0444, trip_point_type_show, NULL),
+- __ATTR(trip_point_1_temp, 0444, trip_point_temp_show, NULL),
+- __ATTR(trip_point_2_type, 0444, trip_point_type_show, NULL),
+- __ATTR(trip_point_2_temp, 0444, trip_point_temp_show, NULL),
+- __ATTR(trip_point_3_type, 0444, trip_point_type_show, NULL),
+- __ATTR(trip_point_3_temp, 0444, trip_point_temp_show, NULL),
+- __ATTR(trip_point_4_type, 0444, trip_point_type_show, NULL),
+- __ATTR(trip_point_4_temp, 0444, trip_point_temp_show, NULL),
+- __ATTR(trip_point_5_type, 0444, trip_point_type_show, NULL),
+- __ATTR(trip_point_5_temp, 0444, trip_point_temp_show, NULL),
+- __ATTR(trip_point_6_type, 0444, trip_point_type_show, NULL),
+- __ATTR(trip_point_6_temp, 0444, trip_point_temp_show, NULL),
+- __ATTR(trip_point_7_type, 0444, trip_point_type_show, NULL),
+- __ATTR(trip_point_7_temp, 0444, trip_point_temp_show, NULL),
+- __ATTR(trip_point_8_type, 0444, trip_point_type_show, NULL),
+- __ATTR(trip_point_8_temp, 0444, trip_point_temp_show, NULL),
+- __ATTR(trip_point_9_type, 0444, trip_point_type_show, NULL),
+- __ATTR(trip_point_9_temp, 0444, trip_point_temp_show, NULL),
+- __ATTR(trip_point_10_type, 0444, trip_point_type_show, NULL),
+- __ATTR(trip_point_10_temp, 0444, trip_point_temp_show, NULL),
+- __ATTR(trip_point_11_type, 0444, trip_point_type_show, NULL),
+- __ATTR(trip_point_11_temp, 0444, trip_point_temp_show, NULL),
+-};
+-
+-#define TRIP_POINT_ATTR_ADD(_dev, _index, result) \
+-do { \
+- result = device_create_file(_dev, \
+- &trip_point_attrs[_index * 2]); \
+- if (result) \
+- break; \
+- result = device_create_file(_dev, \
+- &trip_point_attrs[_index * 2 + 1]); \
+-} while (0)
+-
+-#define TRIP_POINT_ATTR_REMOVE(_dev, _index) \
+-do { \
+- device_remove_file(_dev, &trip_point_attrs[_index * 2]); \
+- device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]); \
+-} while (0)
+-
+-/* sys I/F for cooling device */
+-#define to_cooling_device(_dev) \
+- container_of(_dev, struct thermal_cooling_device, device)
+-
+-static ssize_t
+-thermal_cooling_device_type_show(struct device *dev,
+- struct device_attribute *attr, char *buf)
+-{
+- struct thermal_cooling_device *cdev = to_cooling_device(dev);
+-
+- return sprintf(buf, "%s\n", cdev->type);
+-}
+-
+-static ssize_t
+-thermal_cooling_device_max_state_show(struct device *dev,
+- struct device_attribute *attr, char *buf)
+-{
+- struct thermal_cooling_device *cdev = to_cooling_device(dev);
+-
+- return cdev->ops->get_max_state(cdev, buf);
+-}
+-
+-static ssize_t
+-thermal_cooling_device_cur_state_show(struct device *dev,
+- struct device_attribute *attr, char *buf)
+-{
+- struct thermal_cooling_device *cdev = to_cooling_device(dev);
+-
+- return cdev->ops->get_cur_state(cdev, buf);
+-}
+-
+-static ssize_t
+-thermal_cooling_device_cur_state_store(struct device *dev,
+- struct device_attribute *attr,
+- const char *buf, size_t count)
+-{
+- struct thermal_cooling_device *cdev = to_cooling_device(dev);
+- int state;
+- int result;
+-
+- if (!sscanf(buf, "%d\n", &state))
+- return -EINVAL;
+-
+- if (state < 0)
+- return -EINVAL;
+-
+- result = cdev->ops->set_cur_state(cdev, state);
+- if (result)
+- return result;
+- return count;
+-}
+-
+-static struct device_attribute dev_attr_cdev_type =
+-__ATTR(type, 0444, thermal_cooling_device_type_show, NULL);
+-static DEVICE_ATTR(max_state, 0444,
+- thermal_cooling_device_max_state_show, NULL);
+-static DEVICE_ATTR(cur_state, 0644,
+- thermal_cooling_device_cur_state_show,
+- thermal_cooling_device_cur_state_store);
+-
+-static ssize_t
+-thermal_cooling_device_trip_point_show(struct device *dev,
+- struct device_attribute *attr, char *buf)
+-{
+- struct thermal_cooling_device_instance *instance;
+-
+- instance =
+- container_of(attr, struct thermal_cooling_device_instance, attr);
+-
+- if (instance->trip == THERMAL_TRIPS_NONE)
+- return sprintf(buf, "-1\n");
+- else
+- return sprintf(buf, "%d\n", instance->trip);
+-}
+-
+-/* Device management */
+-
+-/**
+- * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone
+- * @tz: thermal zone device
+- * @trip: indicates which trip point the cooling devices is
+- * associated with in this thermal zone.
+- * @cdev: thermal cooling device
+- *
+- * This function is usually called in the thermal zone device .bind callback.
+- */
+-int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
+- int trip,
+- struct thermal_cooling_device *cdev)
+-{
+- struct thermal_cooling_device_instance *dev;
+- struct thermal_cooling_device_instance *pos;
+- struct thermal_zone_device *pos1;
+- struct thermal_cooling_device *pos2;
+- int result;
+-
+- if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE))
+- return -EINVAL;
+-
+- list_for_each_entry(pos1, &thermal_tz_list, node) {
+- if (pos1 == tz)
+- break;
- }
- 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)
+- list_for_each_entry(pos2, &thermal_cdev_list, node) {
+- if (pos2 == cdev)
+- break;
+- }
+-
+- if (tz != pos1 || cdev != pos2)
+- return -EINVAL;
+-
+- dev =
+- kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL);
+- if (!dev)
+- return -ENOMEM;
+- dev->tz = tz;
+- dev->cdev = cdev;
+- dev->trip = trip;
+- result = get_idr(&tz->idr, &tz->lock, &dev->id);
+- if (result)
+- goto free_mem;
+-
+- sprintf(dev->name, "cdev%d", dev->id);
+- result =
+- sysfs_create_link(&tz->device.kobj, &cdev->device.kobj, dev->name);
+- if (result)
+- goto release_idr;
+-
+- sprintf(dev->attr_name, "cdev%d_trip_point", dev->id);
+- dev->attr.attr.name = dev->attr_name;
+- dev->attr.attr.mode = 0444;
+- dev->attr.show = thermal_cooling_device_trip_point_show;
+- result = device_create_file(&tz->device, &dev->attr);
+- if (result)
+- goto remove_symbol_link;
+-
+- mutex_lock(&tz->lock);
+- list_for_each_entry(pos, &tz->cooling_devices, node)
+- if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
+- result = -EEXIST;
+- break;
+- }
+- if (!result)
+- list_add_tail(&dev->node, &tz->cooling_devices);
+- mutex_unlock(&tz->lock);
+-
+- if (!result)
+- return 0;
+-
+- device_remove_file(&tz->device, &dev->attr);
+- remove_symbol_link:
+- sysfs_remove_link(&tz->device.kobj, dev->name);
+- release_idr:
+- release_idr(&tz->idr, &tz->lock, dev->id);
+- free_mem:
+- kfree(dev);
+- return result;
+-}
+-
+-EXPORT_SYMBOL(thermal_zone_bind_cooling_device);
+-
+-/**
+- * thermal_zone_unbind_cooling_device - unbind a cooling device from a thermal zone
+- * @tz: thermal zone device
+- * @trip: indicates which trip point the cooling devices is
+- * associated with in this thermal zone.
+- * @cdev: thermal cooling device
+- *
+- * This function is usually called in the thermal zone device .unbind callback.
+- */
+-int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
+- int trip,
+- struct thermal_cooling_device *cdev)
-{
-- struct srb *srb;
+- struct thermal_cooling_device_instance *pos, *next;
-
-- 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);
+- mutex_lock(&tz->lock);
+- list_for_each_entry_safe(pos, next, &tz->cooling_devices, node) {
+- if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
+- list_del(&pos->node);
+- mutex_unlock(&tz->lock);
+- goto unbind;
+- }
+- }
+- mutex_unlock(&tz->lock);
+-
+- return -ENODEV;
+-
+- unbind:
+- device_remove_file(&tz->device, &pos->attr);
+- sysfs_remove_link(&tz->device.kobj, pos->name);
+- release_idr(&tz->idr, &tz->lock, pos->id);
+- kfree(pos);
+- return 0;
+-}
+-
+-EXPORT_SYMBOL(thermal_zone_unbind_cooling_device);
+-
+-static void thermal_release(struct device *dev)
+-{
+- struct thermal_zone_device *tz;
+- struct thermal_cooling_device *cdev;
+-
+- if (!strncmp(dev->bus_id, "thermal_zone", sizeof "thermal_zone" - 1)) {
+- tz = to_thermal_zone(dev);
+- kfree(tz);
- } else {
-- DEBUG2(printk("scsi%ld: Invalid ISP SCSI completion handle = "
-- "%d\n", ha->host_no, index));
-- set_bit(DPC_RESET_HA, &ha->dpc_flags);
+- cdev = to_cooling_device(dev);
+- kfree(cdev);
- }
-}
-
+-static struct class thermal_class = {
+- .name = "thermal",
+- .dev_release = thermal_release,
+-};
+-
-/**
- * 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));
+- * thermal_cooling_device_register - register a new thermal cooling device
+- * @type: the thermal cooling device type.
+- * @devdata: device private data.
+- * @ops: standard thermal cooling devices callbacks.
+- */
+-struct thermal_cooling_device *thermal_cooling_device_register(char *type,
+- void *devdata,
+- struct
+- thermal_cooling_device_ops
+- *ops)
+-{
+- struct thermal_cooling_device *cdev;
+- struct thermal_zone_device *pos;
+- int result;
+-
+- if (strlen(type) >= THERMAL_NAME_LENGTH)
+- return ERR_PTR(-EINVAL);
+-
+- if (!ops || !ops->get_max_state || !ops->get_cur_state ||
+- !ops->set_cur_state)
+- return ERR_PTR(-EINVAL);
+-
+- cdev = kzalloc(sizeof(struct thermal_cooling_device), GFP_KERNEL);
+- if (!cdev)
+- return ERR_PTR(-ENOMEM);
+-
+- result = get_idr(&thermal_cdev_idr, &thermal_idr_lock, &cdev->id);
+- if (result) {
+- kfree(cdev);
+- return ERR_PTR(result);
+- }
+-
+- strcpy(cdev->type, type);
+- cdev->ops = ops;
+- cdev->device.class = &thermal_class;
+- cdev->devdata = devdata;
+- sprintf(cdev->device.bus_id, "cooling_device%d", cdev->id);
+- result = device_register(&cdev->device);
+- if (result) {
+- release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
+- kfree(cdev);
+- return ERR_PTR(result);
+- }
+-
+- /* sys I/F */
+- if (type) {
+- result = device_create_file(&cdev->device, &dev_attr_cdev_type);
+- if (result)
+- goto unregister;
+- }
+-
+- result = device_create_file(&cdev->device, &dev_attr_max_state);
+- if (result)
+- goto unregister;
+-
+- result = device_create_file(&cdev->device, &dev_attr_cur_state);
+- if (result)
+- goto unregister;
+-
+- mutex_lock(&thermal_list_lock);
+- list_add(&cdev->node, &thermal_cdev_list);
+- list_for_each_entry(pos, &thermal_tz_list, node) {
+- if (!pos->ops->bind)
+- continue;
+- result = pos->ops->bind(pos, cdev);
+- if (result)
+- break;
+-
+- }
+- mutex_unlock(&thermal_list_lock);
+-
+- if (!result)
+- return cdev;
+-
+- unregister:
+- release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
+- device_unregister(&cdev->device);
+- return ERR_PTR(result);
+-}
+-
+-EXPORT_SYMBOL(thermal_cooling_device_register);
+-
+-/**
+- * thermal_cooling_device_unregister - removes the registered thermal cooling device
+- * @cdev: the thermal cooling device to remove.
+- *
+- * thermal_cooling_device_unregister() must be called when the device is no
+- * longer needed.
+- */
+-void thermal_cooling_device_unregister(struct
+- thermal_cooling_device
+- *cdev)
+-{
+- struct thermal_zone_device *tz;
+- struct thermal_cooling_device *pos = NULL;
+-
+- if (!cdev)
+- return;
+-
+- mutex_lock(&thermal_list_lock);
+- list_for_each_entry(pos, &thermal_cdev_list, node)
+- if (pos == cdev)
+- break;
+- if (pos != cdev) {
+- /* thermal cooling device not found */
+- mutex_unlock(&thermal_list_lock);
- return;
- }
+- list_del(&cdev->node);
+- list_for_each_entry(tz, &thermal_tz_list, node) {
+- if (!tz->ops->unbind)
+- continue;
+- tz->ops->unbind(tz, cdev);
+- }
+- mutex_unlock(&thermal_list_lock);
+- if (cdev->type[0])
+- device_remove_file(&cdev->device, &dev_attr_cdev_type);
+- device_remove_file(&cdev->device, &dev_attr_max_state);
+- device_remove_file(&cdev->device, &dev_attr_cur_state);
-
- 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;
+- release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
+- device_unregister(&cdev->device);
+- return;
+-}
+-
+-EXPORT_SYMBOL(thermal_cooling_device_unregister);
+-
+-/**
+- * thermal_zone_device_register - register a new thermal zone device
+- * @type: the thermal zone device type
+- * @trips: the number of trip points the thermal zone support
+- * @devdata: private device data
+- * @ops: standard thermal zone device callbacks
+- *
+- * thermal_zone_device_unregister() must be called when the device is no
+- * longer needed.
+- */
+-struct thermal_zone_device *thermal_zone_device_register(char *type,
+- int trips,
+- void *devdata, struct
+- thermal_zone_device_ops
+- *ops)
+-{
+- struct thermal_zone_device *tz;
+- struct thermal_cooling_device *pos;
+- int result;
+- int count;
+-
+- if (strlen(type) >= THERMAL_NAME_LENGTH)
+- return ERR_PTR(-EINVAL);
+-
+- if (trips > THERMAL_MAX_TRIPS || trips < 0)
+- return ERR_PTR(-EINVAL);
+-
+- if (!ops || !ops->get_temp)
+- return ERR_PTR(-EINVAL);
+-
+- tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL);
+- if (!tz)
+- return ERR_PTR(-ENOMEM);
+-
+- INIT_LIST_HEAD(&tz->cooling_devices);
+- idr_init(&tz->idr);
+- mutex_init(&tz->lock);
+- result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id);
+- if (result) {
+- kfree(tz);
+- return ERR_PTR(result);
+- }
+-
+- strcpy(tz->type, type);
+- tz->ops = ops;
+- tz->device.class = &thermal_class;
+- tz->devdata = devdata;
+- tz->trips = trips;
+- sprintf(tz->device.bus_id, "thermal_zone%d", tz->id);
+- result = device_register(&tz->device);
+- if (result) {
+- release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
+- kfree(tz);
+- return ERR_PTR(result);
+- }
+-
+- /* sys I/F */
+- if (type) {
+- result = device_create_file(&tz->device, &dev_attr_type);
+- if (result)
+- goto unregister;
+- }
+-
+- result = device_create_file(&tz->device, &dev_attr_temp);
+- if (result)
+- goto unregister;
+-
+- if (ops->get_mode) {
+- result = device_create_file(&tz->device, &dev_attr_mode);
+- if (result)
+- goto unregister;
+- }
+-
+- for (count = 0; count < trips; count++) {
+- TRIP_POINT_ATTR_ADD(&tz->device, count, result);
+- if (result)
+- goto unregister;
+- }
+-
+- mutex_lock(&thermal_list_lock);
+- list_add_tail(&tz->node, &thermal_tz_list);
+- if (ops->bind)
+- list_for_each_entry(pos, &thermal_cdev_list, node) {
+- result = ops->bind(tz, pos);
+- if (result)
- 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
+- mutex_unlock(&thermal_list_lock);
+-
+- if (!result)
+- return tz;
+-
+- unregister:
+- release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
+- device_unregister(&tz->device);
+- return ERR_PTR(result);
+-}
+-
+-EXPORT_SYMBOL(thermal_zone_device_register);
+-
+-/**
+- * thermal_device_unregister - removes the registered thermal zone device
+- * @tz: the thermal zone device to remove
+- */
+-void thermal_zone_device_unregister(struct thermal_zone_device *tz)
+-{
+- struct thermal_cooling_device *cdev;
+- struct thermal_zone_device *pos = NULL;
+- int count;
+-
+- if (!tz)
+- return;
+-
+- mutex_lock(&thermal_list_lock);
+- list_for_each_entry(pos, &thermal_tz_list, node)
+- if (pos == tz)
+- break;
+- if (pos != tz) {
+- /* thermal zone device not found */
+- mutex_unlock(&thermal_list_lock);
+- return;
+- }
+- list_del(&tz->node);
+- if (tz->ops->unbind)
+- list_for_each_entry(cdev, &thermal_cdev_list, node)
+- tz->ops->unbind(tz, cdev);
+- mutex_unlock(&thermal_list_lock);
+-
+- if (tz->type[0])
+- device_remove_file(&tz->device, &dev_attr_type);
+- device_remove_file(&tz->device, &dev_attr_temp);
+- if (tz->ops->get_mode)
+- device_remove_file(&tz->device, &dev_attr_mode);
+-
+- for (count = 0; count < tz->trips; count++)
+- TRIP_POINT_ATTR_REMOVE(&tz->device, count);
+-
+- release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
+- idr_destroy(&tz->idr);
+- mutex_destroy(&tz->lock);
+- device_unregister(&tz->device);
+- return;
+-}
+-
+-EXPORT_SYMBOL(thermal_zone_device_unregister);
+-
+-static int __init thermal_init(void)
+-{
+- int result = 0;
+-
+- result = class_register(&thermal_class);
+- if (result) {
+- idr_destroy(&thermal_tz_idr);
+- idr_destroy(&thermal_cdev_idr);
+- mutex_destroy(&thermal_idr_lock);
+- mutex_destroy(&thermal_list_lock);
+- }
+- return result;
+-}
+-
+-static void __exit thermal_exit(void)
+-{
+- class_unregister(&thermal_class);
+- idr_destroy(&thermal_tz_idr);
+- idr_destroy(&thermal_cdev_idr);
+- mutex_destroy(&thermal_idr_lock);
+- mutex_destroy(&thermal_list_lock);
+-}
+-
+-subsys_initcall(thermal_init);
+-module_exit(thermal_exit);
+diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
+new file mode 100644
+index 0000000..6098787
+--- /dev/null
++++ b/drivers/thermal/thermal_sys.c
+@@ -0,0 +1,899 @@
++/*
++ * thermal.c - Generic Thermal Management Sysfs support.
+ *
-+ * 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;
++ * Copyright (C) 2008 Intel Corp
++ * Copyright (C) 2008 Zhang Rui <rui.zhang at intel.com>
++ * Copyright (C) 2008 Sujith Thomas <sujith.thomas at intel.com>
++ *
++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You 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.
++ *
++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ */
+
-+ 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;
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/err.h>
++#include <linux/kdev_t.h>
++#include <linux/idr.h>
++#include <linux/thermal.h>
++#include <linux/spinlock.h>
+
- 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;
++MODULE_AUTHOR("Zhang Rui");
++MODULE_DESCRIPTION("Generic thermal management sysfs support");
++MODULE_LICENSE("GPL");
+
-+ if (!ddb_entry)
-+ return FAILED;
++#define PREFIX "Thermal: "
+
-+ starget_printk(KERN_INFO, scsi_target(cmd->device),
-+ "WARM TARGET RESET ISSUED.\n");
++struct thermal_cooling_device_instance {
++ int id;
++ char name[THERMAL_NAME_LENGTH];
++ struct thermal_zone_device *tz;
++ struct thermal_cooling_device *cdev;
++ int trip;
++ char attr_name[THERMAL_NAME_LENGTH];
++ struct device_attribute attr;
++ struct list_head node;
++};
+
-+ 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));
++static DEFINE_IDR(thermal_tz_idr);
++static DEFINE_IDR(thermal_cdev_idr);
++static DEFINE_MUTEX(thermal_idr_lock);
++
++static LIST_HEAD(thermal_tz_list);
++static LIST_HEAD(thermal_cdev_list);
++static DEFINE_MUTEX(thermal_list_lock);
+
-+ 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;
-+ }
++static int get_idr(struct idr *idr, struct mutex *lock, int *id)
++{
++ int err;
+
-+ 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;
-+ }
++ again:
++ if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
++ return -ENOMEM;
+
-+ /* 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;
-+ }
++ if (lock)
++ mutex_lock(lock);
++ err = idr_get_new(idr, NULL, id);
++ if (lock)
++ mutex_unlock(lock);
++ if (unlikely(err == -EAGAIN))
++ goto again;
++ else if (unlikely(err))
++ return err;
+
-+ starget_printk(KERN_INFO, scsi_target(cmd->device),
-+ "WARM TARGET RESET SUCCEEDED.\n");
-+ return SUCCESS;
++ *id = *id & MAX_ID_MASK;
++ return 0;
+}
+
-+/**
- * 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)
++static void release_idr(struct idr *idr, struct mutex *lock, int id)
+{
-+ struct scsi_cmnd *cmd;
++ if (lock)
++ mutex_lock(lock);
++ idr_remove(idr, id);
++ if (lock)
++ mutex_unlock(lock);
++}
+
-+ cmd = kmem_cache_alloc(pool->cmd_slab, gfp_mask | pool->gfp_mask);
-+ if (!cmd)
-+ return NULL;
++/* sys I/F for thermal zone */
+
-+ memset(cmd, 0, sizeof(*cmd));
++#define to_thermal_zone(_dev) \
++ container_of(_dev, struct thermal_zone_device, device)
+
-+ 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;
-+ }
++static ssize_t
++type_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct thermal_zone_device *tz = to_thermal_zone(dev);
+
-+ return cmd;
++ return sprintf(buf, "%s\n", tz->type);
+}
+
-+/**
-+ * 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)
++static ssize_t
++temp_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
-+ kmem_cache_free(pool->sense_slab, cmd->sense_buffer);
-+ kmem_cache_free(pool->cmd_slab, cmd);
-+}
++ struct thermal_zone_device *tz = to_thermal_zone(dev);
+
-+/**
- * __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;
++ if (!tz->ops->get_temp)
++ return -EPERM;
++
++ return tz->ops->get_temp(tz, buf);
+}
+
-+static void scsi_put_host_cmd_pool(gfp_t gfp_mask)
++static ssize_t
++mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
-+ 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;
++ struct thermal_zone_device *tz = to_thermal_zone(dev);
++
++ if (!tz->ops->get_mode)
++ return -EPERM;
++
++ return tz->ops->get_mode(tz, buf);
+}
+
-+/**
-+ * 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)
++static ssize_t
++mode_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+{
-+ struct scsi_host_cmd_pool *pool = scsi_get_host_cmd_pool(gfp_mask);
++ struct thermal_zone_device *tz = to_thermal_zone(dev);
++ int result;
+
-+ if (!pool)
-+ return NULL;
++ if (!tz->ops->set_mode)
++ return -EPERM;
+
-+ return scsi_pool_alloc_command(pool, gfp_mask);
++ result = tz->ops->set_mode(tz, buf);
++ if (result)
++ return result;
++
++ return count;
+}
-+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)
++static ssize_t
++trip_point_type_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+{
-+ struct scsi_host_cmd_pool *pool = scsi_get_host_cmd_pool(gfp_mask);
++ struct thermal_zone_device *tz = to_thermal_zone(dev);
++ int trip;
+
-+ /*
-+ * 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);
++ if (!tz->ops->get_trip_type)
++ return -EPERM;
+
-+ 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);
++ if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip))
++ return -EINVAL;
++
++ return tz->ops->get_trip_type(tz, trip, buf);
+}
-+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)
++static ssize_t
++trip_point_temp_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+{
-+ struct scsi_cmnd *cmd;
-+ const gfp_t gfp_mask = shost->unchecked_isa_dma ? GFP_DMA : GFP_KERNEL;
++ struct thermal_zone_device *tz = to_thermal_zone(dev);
++ int trip;
+
-+ spin_lock_init(&shost->free_list_lock);
-+ INIT_LIST_HEAD(&shost->free_list);
++ if (!tz->ops->get_trip_temp)
++ return -EPERM;
+
-+ shost->cmd_pool = scsi_get_host_cmd_pool(gfp_mask);
++ if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
++ return -EINVAL;
+
-+ if (!shost->cmd_pool)
-+ return -ENOMEM;
++ return tz->ops->get_trip_temp(tz, trip, buf);
++}
+
-+ /*
-+ * Get one backup command for this host.
-+ */
-+ cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask);
-+ if (!cmd) {
-+ scsi_put_host_cmd_pool(gfp_mask);
-+ return -ENOMEM;
-+ }
-+ list_add(&cmd->list, &shost->free_list);
-+ return 0;
- }
-
- /**
-@@ -386,17 +486,10 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost)
-
- cmd = list_entry(shost->free_list.next, struct scsi_cmnd, list);
- list_del_init(&cmd->list);
-- kmem_cache_free(shost->cmd_pool->sense_slab,
-- cmd->sense_buffer);
-- kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
-+ scsi_pool_free_command(shost->cmd_pool, cmd);
- }
--
-- mutex_lock(&host_cmd_pool_mutex);
-- if (!--shost->cmd_pool->users) {
-- kmem_cache_destroy(shost->cmd_pool->cmd_slab);
-- kmem_cache_destroy(shost->cmd_pool->sense_slab);
-- }
-- mutex_unlock(&host_cmd_pool_mutex);
-+ shost->cmd_pool = NULL;
-+ scsi_put_host_cmd_pool(shost->unchecked_isa_dma ? GFP_DMA : GFP_KERNEL);
- }
-
- #ifdef CONFIG_SCSI_LOGGING
-@@ -759,7 +852,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
- "Notifying upper driver of completion "
- "(result %x)\n", cmd->result));
-
-- good_bytes = scsi_bufflen(cmd) + cmd->request->extra_len;
-+ good_bytes = scsi_bufflen(cmd);
- if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
- drv = scsi_cmd_to_driver(cmd);
- if (drv->done)
-diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
-index d1777a9..07103c3 100644
---- a/drivers/scsi/scsi_debug.c
-+++ b/drivers/scsi/scsi_debug.c
-@@ -39,16 +39,18 @@
- #include <linux/vmalloc.h>
- #include <linux/moduleparam.h>
- #include <linux/scatterlist.h>
--
- #include <linux/blkdev.h>
--#include "scsi.h"
++static DEVICE_ATTR(type, 0444, type_show, NULL);
++static DEVICE_ATTR(temp, 0444, temp_show, NULL);
++static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
++
++static struct device_attribute trip_point_attrs[] = {
++ __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL),
++ __ATTR(trip_point_0_temp, 0444, trip_point_temp_show, NULL),
++ __ATTR(trip_point_1_type, 0444, trip_point_type_show, NULL),
++ __ATTR(trip_point_1_temp, 0444, trip_point_temp_show, NULL),
++ __ATTR(trip_point_2_type, 0444, trip_point_type_show, NULL),
++ __ATTR(trip_point_2_temp, 0444, trip_point_temp_show, NULL),
++ __ATTR(trip_point_3_type, 0444, trip_point_type_show, NULL),
++ __ATTR(trip_point_3_temp, 0444, trip_point_temp_show, NULL),
++ __ATTR(trip_point_4_type, 0444, trip_point_type_show, NULL),
++ __ATTR(trip_point_4_temp, 0444, trip_point_temp_show, NULL),
++ __ATTR(trip_point_5_type, 0444, trip_point_type_show, NULL),
++ __ATTR(trip_point_5_temp, 0444, trip_point_temp_show, NULL),
++ __ATTR(trip_point_6_type, 0444, trip_point_type_show, NULL),
++ __ATTR(trip_point_6_temp, 0444, trip_point_temp_show, NULL),
++ __ATTR(trip_point_7_type, 0444, trip_point_type_show, NULL),
++ __ATTR(trip_point_7_temp, 0444, trip_point_temp_show, NULL),
++ __ATTR(trip_point_8_type, 0444, trip_point_type_show, NULL),
++ __ATTR(trip_point_8_temp, 0444, trip_point_temp_show, NULL),
++ __ATTR(trip_point_9_type, 0444, trip_point_type_show, NULL),
++ __ATTR(trip_point_9_temp, 0444, trip_point_temp_show, NULL),
++ __ATTR(trip_point_10_type, 0444, trip_point_type_show, NULL),
++ __ATTR(trip_point_10_temp, 0444, trip_point_temp_show, NULL),
++ __ATTR(trip_point_11_type, 0444, trip_point_type_show, NULL),
++ __ATTR(trip_point_11_temp, 0444, trip_point_temp_show, NULL),
++};
++
++#define TRIP_POINT_ATTR_ADD(_dev, _index, result) \
++do { \
++ result = device_create_file(_dev, \
++ &trip_point_attrs[_index * 2]); \
++ if (result) \
++ break; \
++ result = device_create_file(_dev, \
++ &trip_point_attrs[_index * 2 + 1]); \
++} while (0)
+
-+#include <scsi/scsi.h>
-+#include <scsi/scsi_cmnd.h>
-+#include <scsi/scsi_device.h>
- #include <scsi/scsi_host.h>
- #include <scsi/scsicam.h>
-+#include <scsi/scsi_eh.h>
-
- #include <linux/stat.h>
-
- #include "scsi_logging.h"
--#include "scsi_debug.h"
-
- #define SCSI_DEBUG_VERSION "1.81"
- static const char * scsi_debug_version_date = "20070104";
-@@ -146,7 +148,6 @@ static int scsi_debug_cmnd_count = 0;
- #define DEV_READONLY(TGT) (0)
- #define DEV_REMOVEABLE(TGT) (0)
-
--static unsigned int sdebug_store_size; /* in bytes */
- static unsigned int sdebug_store_sectors;
- static sector_t sdebug_capacity; /* in sectors */
-
-@@ -165,6 +166,9 @@ static int sdebug_sectors_per; /* sectors per cylinder */
-
- #define SDEBUG_SENSE_LEN 32
-
-+#define SCSI_DEBUG_CANQUEUE 255
-+#define SCSI_DEBUG_MAX_CMD_LEN 16
++#define TRIP_POINT_ATTR_REMOVE(_dev, _index) \
++do { \
++ device_remove_file(_dev, &trip_point_attrs[_index * 2]); \
++ device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]); \
++} while (0)
+
- 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)
++/* sys I/F for cooling device */
++#define to_cooling_device(_dev) \
++ container_of(_dev, struct thermal_cooling_device, device)
++
++static ssize_t
++thermal_cooling_device_type_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+{
-+ struct sdebug_host_info *sdbg_host;
-+ struct Scsi_Host *hpnt;
++ struct thermal_cooling_device *cdev = to_cooling_device(dev);
+
-+ 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);
++ return sprintf(buf, "%s\n", cdev->type);
+}
+
-+static void mk_sense_buffer(struct sdebug_dev_info *devip, int key,
-+ int asc, int asq)
++static ssize_t
++thermal_cooling_device_max_state_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+{
-+ unsigned char *sbuff;
++ struct thermal_cooling_device *cdev = to_cooling_device(dev);
+
-+ sbuff = devip->sense_buff;
-+ memset(sbuff, 0, SDEBUG_SENSE_LEN);
++ return cdev->ops->get_max_state(cdev, buf);
++}
+
-+ scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq);
++static ssize_t
++thermal_cooling_device_cur_state_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct thermal_cooling_device *cdev = to_cooling_device(dev);
+
-+ 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);
++ return cdev->ops->get_cur_state(cdev, buf);
+}
-
- 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;
++static ssize_t
++thermal_cooling_device_cur_state_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct thermal_cooling_device *cdev = to_cooling_device(dev);
++ int state;
++ int result;
+
-+ *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;
++ if (!sscanf(buf, "%d\n", &state))
++ return -EINVAL;
+
-+ *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;
-- }
++ if (state < 0)
++ return -EINVAL;
+
-+ 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;
++ result = cdev->ops->set_cur_state(cdev, state);
++ if (result)
++ return result;
++ return count;
++}
+
- 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;
++static struct device_attribute dev_attr_cdev_type =
++__ATTR(type, 0444, thermal_cooling_device_type_show, NULL);
++static DEVICE_ATTR(max_state, 0444,
++ thermal_cooling_device_max_state_show, NULL);
++static DEVICE_ATTR(cur_state, 0644,
++ thermal_cooling_device_cur_state_show,
++ thermal_cooling_device_cur_state_store);
+
-+ 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)
++static ssize_t
++thermal_cooling_device_trip_point_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+{
-+ if (scsi_debug_virtual_gb > 0)
-+ return 2048 * 1024 * scsi_debug_virtual_gb;
-+ else
-+ return sdebug_store_sectors;
-+}
++ struct thermal_cooling_device_instance *instance;
+
- #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();
++ instance =
++ container_of(attr, struct thermal_cooling_device_instance, attr);
+
- 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;
++ if (instance->trip == THERMAL_TRIPS_NONE)
++ return sprintf(buf, "-1\n");
++ else
++ return sprintf(buf, "%d\n", instance->trip);
+}
+
-+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;
++/* Device management */
+
-+ ret = func(scmd, fake_storep + (block * SECT_SIZE),
-+ (num - rest) * SECT_SIZE);
-+ if (!ret && rest)
-+ ret = func(scmd, fake_storep, rest * SECT_SIZE);
++#if defined(CONFIG_HWMON) || \
++ (defined(CONFIG_HWMON_MODULE) && defined(CONFIG_THERMAL_MODULE))
++/* hwmon sys I/F */
++#include <linux/hwmon.h>
++static LIST_HEAD(thermal_hwmon_list);
+
-+ return ret;
++static ssize_t
++name_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct thermal_hwmon_device *hwmon = dev->driver_data;
++ return sprintf(buf, "%s\n", hwmon->type);
+}
++static DEVICE_ATTR(name, 0444, name_show, NULL);
+
-+static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
-+ unsigned int num, struct sdebug_dev_info *devip)
++static ssize_t
++temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
-+ unsigned long iflags;
-+ int ret;
-+
-+ ret = check_device_access_params(devip, lba, num);
-+ if (ret)
-+ return ret;
++ struct thermal_hwmon_attr *hwmon_attr
++ = container_of(attr, struct thermal_hwmon_attr, attr);
++ struct thermal_zone_device *tz
++ = container_of(hwmon_attr, struct thermal_zone_device,
++ temp_input);
+
- 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)
++ return tz->ops->get_temp(tz, buf);
++}
+
-+static struct sdebug_dev_info *
-+sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags)
++static ssize_t
++temp_crit_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+{
-+ struct sdebug_dev_info *devip;
++ struct thermal_hwmon_attr *hwmon_attr
++ = container_of(attr, struct thermal_hwmon_attr, attr);
++ struct thermal_zone_device *tz
++ = container_of(hwmon_attr, struct thermal_zone_device,
++ temp_crit);
+
-+ 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;
++ return tz->ops->get_trip_temp(tz, 0, buf);
+}
+
-+static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
++
++static int
++thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
+{
-+ struct sdebug_host_info * sdbg_host;
-+ struct sdebug_dev_info * open_devip = NULL;
-+ struct sdebug_dev_info * devip =
-+ (struct sdebug_dev_info *)sdev->hostdata;
++ struct thermal_hwmon_device *hwmon;
++ int new_hwmon_device = 1;
++ int result;
+
-+ 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;
++ mutex_lock(&thermal_list_lock);
++ list_for_each_entry(hwmon, &thermal_hwmon_list, node)
++ if (!strcmp(hwmon->type, tz->type)) {
++ new_hwmon_device = 0;
++ mutex_unlock(&thermal_list_lock);
++ goto register_sys_interface;
+ }
++ mutex_unlock(&thermal_list_lock);
++
++ hwmon = kzalloc(sizeof(struct thermal_hwmon_device), GFP_KERNEL);
++ if (!hwmon)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&hwmon->tz_list);
++ strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH);
++ hwmon->device = hwmon_device_register(NULL);
++ if (IS_ERR(hwmon->device)) {
++ result = PTR_ERR(hwmon->device);
++ goto free_mem;
+ }
-+ 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;
++ hwmon->device->driver_data = hwmon;
++ result = device_create_file(hwmon->device, &dev_attr_name);
++ if (result)
++ goto unregister_hwmon_device;
++
++ register_sys_interface:
++ tz->hwmon = hwmon;
++ hwmon->count++;
++
++ snprintf(tz->temp_input.name, THERMAL_NAME_LENGTH,
++ "temp%d_input", hwmon->count);
++ tz->temp_input.attr.attr.name = tz->temp_input.name;
++ tz->temp_input.attr.attr.mode = 0444;
++ tz->temp_input.attr.show = temp_input_show;
++ result = device_create_file(hwmon->device, &tz->temp_input.attr);
++ if (result)
++ goto unregister_hwmon_device;
++
++ if (tz->ops->get_crit_temp) {
++ unsigned long temperature;
++ if (!tz->ops->get_crit_temp(tz, &temperature)) {
++ snprintf(tz->temp_crit.name, THERMAL_NAME_LENGTH,
++ "temp%d_crit", hwmon->count);
++ tz->temp_crit.attr.attr.name = tz->temp_crit.name;
++ tz->temp_crit.attr.attr.mode = 0444;
++ tz->temp_crit.attr.show = temp_crit_show;
++ result = device_create_file(hwmon->device,
++ &tz->temp_crit.attr);
++ if (result)
++ goto unregister_hwmon_device;
+ }
+ }
+
-+ 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;
++ mutex_lock(&thermal_list_lock);
++ if (new_hwmon_device)
++ list_add_tail(&hwmon->node, &thermal_hwmon_list);
++ list_add_tail(&tz->hwmon_node, &hwmon->tz_list);
++ mutex_unlock(&thermal_list_lock);
++
++ return 0;
++
++ unregister_hwmon_device:
++ device_remove_file(hwmon->device, &tz->temp_crit.attr);
++ device_remove_file(hwmon->device, &tz->temp_input.attr);
++ if (new_hwmon_device) {
++ device_remove_file(hwmon->device, &dev_attr_name);
++ hwmon_device_unregister(hwmon->device);
+ }
-+ if (sdev->lun == SAM2_WLUN_REPORT_LUNS)
-+ open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff;
++ free_mem:
++ if (new_hwmon_device)
++ kfree(hwmon);
+
-+ return open_devip;
++ return result;
+}
+
-+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;
++static void
++thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
++{
++ struct thermal_hwmon_device *hwmon = tz->hwmon;
+
-+ sdebug_capacity = get_sdebug_capacity();
++ tz->hwmon = NULL;
++ device_remove_file(hwmon->device, &tz->temp_input.attr);
++ device_remove_file(hwmon->device, &tz->temp_crit.attr);
++
++ mutex_lock(&thermal_list_lock);
++ list_del(&tz->hwmon_node);
++ if (!list_empty(&hwmon->tz_list)) {
++ mutex_unlock(&thermal_list_lock);
++ return;
++ }
++ list_del(&hwmon->node);
++ mutex_unlock(&thermal_list_lock);
+
- 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)
++ device_remove_file(hwmon->device, &dev_attr_name);
++ hwmon_device_unregister(hwmon->device);
++ kfree(hwmon);
++}
++#else
++static int
++thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
+{
-+ if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-+ printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n");
++ return 0;
+}
+
-+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)
++static void
++thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
+{
-+ 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;
++}
++#endif
+
-+ 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);
-+ }
++/**
++ * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone
++ * @tz: thermal zone device
++ * @trip: indicates which trip point the cooling devices is
++ * associated with in this thermal zone.
++ * @cdev: thermal cooling device
++ *
++ * This function is usually called in the thermal zone device .bind callback.
++ */
++int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
++ int trip,
++ struct thermal_cooling_device *cdev)
++{
++ struct thermal_cooling_device_instance *dev;
++ struct thermal_cooling_device_instance *pos;
++ struct thermal_zone_device *pos1;
++ struct thermal_cooling_device *pos2;
++ int result;
+
-+ 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 (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE))
++ return -EINVAL;
+
-+ 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 */
++ list_for_each_entry(pos1, &thermal_tz_list, node) {
++ if (pos1 == tz)
++ break;
+ }
-+
-+ 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);
-+ }
++ list_for_each_entry(pos2, &thermal_cdev_list, node) {
++ if (pos2 == cdev)
++ break;
+ }
+
-+ 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;
-+ }
++ if (tz != pos1 || cdev != pos2)
++ return -EINVAL;
+
-+ 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;
++ dev =
++ kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL);
++ if (!dev)
++ return -ENOMEM;
++ dev->tz = tz;
++ dev->cdev = cdev;
++ dev->trip = trip;
++ result = get_idr(&tz->idr, &tz->lock, &dev->id);
++ if (result)
++ goto free_mem;
++
++ sprintf(dev->name, "cdev%d", dev->id);
++ result =
++ sysfs_create_link(&tz->device.kobj, &cdev->device.kobj, dev->name);
++ if (result)
++ goto release_idr;
++
++ sprintf(dev->attr_name, "cdev%d_trip_point", dev->id);
++ dev->attr.attr.name = dev->attr_name;
++ dev->attr.attr.mode = 0444;
++ dev->attr.show = thermal_cooling_device_trip_point_show;
++ result = device_create_file(&tz->device, &dev->attr);
++ if (result)
++ goto remove_symbol_link;
++
++ mutex_lock(&tz->lock);
++ list_for_each_entry(pos, &tz->cooling_devices, node)
++ if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
++ result = -EEXIST;
+ break;
+ }
-+ return schedule_resp(SCpnt, devip, done, errsts,
-+ (delay_override ? 0 : scsi_debug_delay));
++ if (!result)
++ list_add_tail(&dev->node, &tz->cooling_devices);
++ mutex_unlock(&tz->lock);
++
++ if (!result)
++ return 0;
++
++ device_remove_file(&tz->device, &dev->attr);
++ remove_symbol_link:
++ sysfs_remove_link(&tz->device.kobj, dev->name);
++ release_idr:
++ release_idr(&tz->idr, &tz->lock, dev->id);
++ free_mem:
++ kfree(dev);
++ return result;
+}
+
-+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,
-+};
++EXPORT_SYMBOL(thermal_zone_bind_cooling_device);
+
- 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;
- }
++/**
++ * thermal_zone_unbind_cooling_device - unbind a cooling device from a thermal zone
++ * @tz: thermal zone device
++ * @trip: indicates which trip point the cooling devices is
++ * associated with in this thermal zone.
++ * @cdev: thermal cooling device
++ *
++ * This function is usually called in the thermal zone device .unbind callback.
++ */
++int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
++ int trip,
++ struct thermal_cooling_device *cdev)
++{
++ struct thermal_cooling_device_instance *pos, *next;
+
-+static struct bus_type pseudo_lld_bus = {
-+ .name = "pseudo",
-+ .match = pseudo_lld_bus_match,
-+ .probe = sdebug_driver_probe,
-+ .remove = sdebug_driver_remove,
-+};
-diff --git a/drivers/scsi/scsi_debug.h b/drivers/scsi/scsi_debug.h
-deleted file mode 100644
-index 965dd5e..0000000
---- a/drivers/scsi/scsi_debug.h
-+++ /dev/null
-@@ -1,24 +0,0 @@
--#ifndef _SCSI_DEBUG_H
--
--#include <linux/types.h>
--
--static int scsi_debug_slave_alloc(struct scsi_device *);
--static int scsi_debug_slave_configure(struct scsi_device *);
--static void scsi_debug_slave_destroy(struct scsi_device *);
--static int scsi_debug_queuecommand(struct scsi_cmnd *,
-- void (*done) (struct scsi_cmnd *));
--static int scsi_debug_ioctl(struct scsi_device *, int, void __user *);
--static int scsi_debug_biosparam(struct scsi_device *, struct block_device *,
-- sector_t, int[]);
--static int scsi_debug_abort(struct scsi_cmnd *);
--static int scsi_debug_bus_reset(struct scsi_cmnd *);
--static int scsi_debug_device_reset(struct scsi_cmnd *);
--static int scsi_debug_host_reset(struct scsi_cmnd *);
--static int scsi_debug_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
--static const char * scsi_debug_info(struct Scsi_Host *);
--
--#define SCSI_DEBUG_CANQUEUE 255 /* needs to be >= 1 */
--
--#define SCSI_DEBUG_MAX_CMD_LEN 16
--
--#endif
-diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
-index 045a086..221f31e 100644
---- a/drivers/scsi/scsi_error.c
-+++ b/drivers/scsi/scsi_error.c
-@@ -524,6 +524,41 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
- return rtn;
- }
-
-+static void __scsi_report_device_reset(struct scsi_device *sdev, void *data)
++ mutex_lock(&tz->lock);
++ list_for_each_entry_safe(pos, next, &tz->cooling_devices, node) {
++ if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
++ list_del(&pos->node);
++ mutex_unlock(&tz->lock);
++ goto unbind;
++ }
++ }
++ mutex_unlock(&tz->lock);
++
++ return -ENODEV;
++
++ unbind:
++ device_remove_file(&tz->device, &pos->attr);
++ sysfs_remove_link(&tz->device.kobj, pos->name);
++ release_idr(&tz->idr, &tz->lock, pos->id);
++ kfree(pos);
++ return 0;
++}
++
++EXPORT_SYMBOL(thermal_zone_unbind_cooling_device);
++
++static void thermal_release(struct device *dev)
+{
-+ sdev->was_reset = 1;
-+ sdev->expecting_cc_ua = 1;
++ struct thermal_zone_device *tz;
++ struct thermal_cooling_device *cdev;
++
++ if (!strncmp(dev->bus_id, "thermal_zone", sizeof "thermal_zone" - 1)) {
++ tz = to_thermal_zone(dev);
++ kfree(tz);
++ } else {
++ cdev = to_cooling_device(dev);
++ kfree(cdev);
++ }
+}
+
++static struct class thermal_class = {
++ .name = "thermal",
++ .dev_release = thermal_release,
++};
++
+/**
-+ * 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)
++ * thermal_cooling_device_register - register a new thermal cooling device
++ * @type: the thermal cooling device type.
++ * @devdata: device private data.
++ * @ops: standard thermal cooling devices callbacks.
++ */
++struct thermal_cooling_device *thermal_cooling_device_register(char *type,
++ void *devdata,
++ struct
++ thermal_cooling_device_ops
++ *ops)
+{
-+ unsigned long flags;
-+ int rtn;
++ struct thermal_cooling_device *cdev;
++ struct thermal_zone_device *pos;
++ int result;
+
-+ if (!scmd->device->host->hostt->eh_target_reset_handler)
-+ return FAILED;
++ if (strlen(type) >= THERMAL_NAME_LENGTH)
++ return ERR_PTR(-EINVAL);
+
-+ 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);
++ if (!ops || !ops->get_max_state || !ops->get_cur_state ||
++ !ops->set_cur_state)
++ return ERR_PTR(-EINVAL);
++
++ cdev = kzalloc(sizeof(struct thermal_cooling_device), GFP_KERNEL);
++ if (!cdev)
++ return ERR_PTR(-ENOMEM);
++
++ result = get_idr(&thermal_cdev_idr, &thermal_idr_lock, &cdev->id);
++ if (result) {
++ kfree(cdev);
++ return ERR_PTR(result);
+ }
+
-+ return rtn;
++ strcpy(cdev->type, type);
++ cdev->ops = ops;
++ cdev->device.class = &thermal_class;
++ cdev->devdata = devdata;
++ sprintf(cdev->device.bus_id, "cooling_device%d", cdev->id);
++ result = device_register(&cdev->device);
++ if (result) {
++ release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
++ kfree(cdev);
++ return ERR_PTR(result);
++ }
++
++ /* sys I/F */
++ if (type) {
++ result = device_create_file(&cdev->device, &dev_attr_cdev_type);
++ if (result)
++ goto unregister;
++ }
++
++ result = device_create_file(&cdev->device, &dev_attr_max_state);
++ if (result)
++ goto unregister;
++
++ result = device_create_file(&cdev->device, &dev_attr_cur_state);
++ if (result)
++ goto unregister;
++
++ mutex_lock(&thermal_list_lock);
++ list_add(&cdev->node, &thermal_cdev_list);
++ list_for_each_entry(pos, &thermal_tz_list, node) {
++ if (!pos->ops->bind)
++ continue;
++ result = pos->ops->bind(pos, cdev);
++ if (result)
++ break;
++
++ }
++ mutex_unlock(&thermal_list_lock);
++
++ if (!result)
++ return cdev;
++
++ unregister:
++ release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
++ device_unregister(&cdev->device);
++ return ERR_PTR(result);
+}
+
- /**
- * 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.
++EXPORT_SYMBOL(thermal_cooling_device_register);
++
++/**
++ * thermal_cooling_device_unregister - removes the registered thermal cooling device
++ * @cdev: the thermal cooling device to remove.
+ *
-+ * Notes:
-+ * Try a target reset.
++ * thermal_cooling_device_unregister() must be called when the device is no
++ * longer needed.
+ */
-+static int scsi_eh_target_reset(struct Scsi_Host *shost,
-+ struct list_head *work_q,
-+ struct list_head *done_q)
++void thermal_cooling_device_unregister(struct
++ thermal_cooling_device
++ *cdev)
+{
-+ struct scsi_cmnd *scmd, *tgtr_scmd, *next;
-+ unsigned int id;
-+ int rtn;
++ struct thermal_zone_device *tz;
++ struct thermal_cooling_device *pos = NULL;
+
-+ 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;
++ if (!cdev)
++ return;
+
-+ 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));
++ mutex_lock(&thermal_list_lock);
++ list_for_each_entry(pos, &thermal_cdev_list, node)
++ if (pos == cdev)
++ break;
++ if (pos != cdev) {
++ /* thermal cooling device not found */
++ mutex_unlock(&thermal_list_lock);
++ return;
++ }
++ list_del(&cdev->node);
++ list_for_each_entry(tz, &thermal_tz_list, node) {
++ if (!tz->ops->unbind)
++ continue;
++ tz->ops->unbind(tz, cdev);
+ }
++ mutex_unlock(&thermal_list_lock);
++ if (cdev->type[0])
++ device_remove_file(&cdev->device, &dev_attr_cdev_type);
++ device_remove_file(&cdev->device, &dev_attr_max_state);
++ device_remove_file(&cdev->device, &dev_attr_cur_state);
+
-+ return list_empty(work_q);
++ release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
++ device_unregister(&cdev->device);
++ return;
+}
+
++EXPORT_SYMBOL(thermal_cooling_device_unregister);
++
+/**
- * 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)
++ * thermal_zone_device_register - register a new thermal zone device
++ * @type: the thermal zone device type
++ * @trips: the number of trip points the thermal zone support
++ * @devdata: private device data
++ * @ops: standard thermal zone device callbacks
++ *
++ * thermal_zone_device_unregister() must be called when the device is no
++ * longer needed.
++ */
++struct thermal_zone_device *thermal_zone_device_register(char *type,
++ int trips,
++ void *devdata, struct
++ thermal_zone_device_ops
++ *ops)
++{
++ struct thermal_zone_device *tz;
++ struct thermal_cooling_device *pos;
++ int result;
++ int count;
++
++ if (strlen(type) >= THERMAL_NAME_LENGTH)
++ return ERR_PTR(-EINVAL);
++
++ if (trips > THERMAL_MAX_TRIPS || trips < 0)
++ return ERR_PTR(-EINVAL);
++
++ if (!ops || !ops->get_temp)
++ return ERR_PTR(-EINVAL);
++
++ tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL);
++ if (!tz)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&tz->cooling_devices);
++ idr_init(&tz->idr);
++ mutex_init(&tz->lock);
++ result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id);
++ if (result) {
++ kfree(tz);
++ return ERR_PTR(result);
++ }
++
++ strcpy(tz->type, type);
++ tz->ops = ops;
++ tz->device.class = &thermal_class;
++ tz->devdata = devdata;
++ tz->trips = trips;
++ sprintf(tz->device.bus_id, "thermal_zone%d", tz->id);
++ result = device_register(&tz->device);
++ if (result) {
++ release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
++ kfree(tz);
++ return ERR_PTR(result);
++ }
++
++ /* sys I/F */
++ if (type) {
++ result = device_create_file(&tz->device, &dev_attr_type);
++ if (result)
++ goto unregister;
++ }
++
++ result = device_create_file(&tz->device, &dev_attr_temp);
++ if (result)
++ goto unregister;
++
++ if (ops->get_mode) {
++ result = device_create_file(&tz->device, &dev_attr_mode);
++ if (result)
++ goto unregister;
++ }
++
++ for (count = 0; count < trips; count++) {
++ TRIP_POINT_ATTR_ADD(&tz->device, count, result);
++ if (result)
++ goto unregister;
++ }
++
++ result = thermal_add_hwmon_sysfs(tz);
++ if (result)
++ goto unregister;
++
++ mutex_lock(&thermal_list_lock);
++ list_add_tail(&tz->node, &thermal_tz_list);
++ if (ops->bind)
++ list_for_each_entry(pos, &thermal_cdev_list, node) {
++ result = ops->bind(tz, pos);
++ if (result)
+ 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);
++ }
++ mutex_unlock(&thermal_list_lock);
++
++ if (!result)
++ return tz;
++
++ unregister:
++ release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
++ device_unregister(&tz->device);
++ return ERR_PTR(result);
++}
++
++EXPORT_SYMBOL(thermal_zone_device_register);
+
+/**
-+ * 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)
++ * thermal_device_unregister - removes the registered thermal zone device
++ * @tz: the thermal zone device to remove
++ */
++void thermal_zone_device_unregister(struct thermal_zone_device *tz)
+{
-+ 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;
++ struct thermal_cooling_device *cdev;
++ struct thermal_zone_device *pos = NULL;
++ int count;
++
++ if (!tz)
++ return;
++
++ mutex_lock(&thermal_list_lock);
++ list_for_each_entry(pos, &thermal_tz_list, node)
++ if (pos == tz)
++ break;
++ if (pos != tz) {
++ /* thermal zone device not found */
++ mutex_unlock(&thermal_list_lock);
++ return;
+ }
++ list_del(&tz->node);
++ if (tz->ops->unbind)
++ list_for_each_entry(cdev, &thermal_cdev_list, node)
++ tz->ops->unbind(tz, cdev);
++ mutex_unlock(&thermal_list_lock);
++
++ if (tz->type[0])
++ device_remove_file(&tz->device, &dev_attr_type);
++ device_remove_file(&tz->device, &dev_attr_temp);
++ if (tz->ops->get_mode)
++ device_remove_file(&tz->device, &dev_attr_mode);
++
++ for (count = 0; count < tz->trips; count++)
++ TRIP_POINT_ATTR_REMOVE(&tz->device, count);
++
++ thermal_remove_hwmon_sysfs(tz);
++ release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
++ idr_destroy(&tz->idr);
++ mutex_destroy(&tz->lock);
++ device_unregister(&tz->device);
++ return;
+}
-+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;
++
++EXPORT_SYMBOL(thermal_zone_device_unregister);
++
++static int __init thermal_init(void)
++{
++ int result = 0;
++
++ result = class_register(&thermal_class);
++ if (result) {
++ idr_destroy(&thermal_tz_idr);
++ idr_destroy(&thermal_cdev_idr);
++ mutex_destroy(&thermal_idr_lock);
++ mutex_destroy(&thermal_list_lock);
++ }
++ return result;
++}
++
++static void __exit thermal_exit(void)
++{
++ class_unregister(&thermal_class);
++ idr_destroy(&thermal_tz_idr);
++ idr_destroy(&thermal_cdev_idr);
++ mutex_destroy(&thermal_idr_lock);
++ mutex_destroy(&thermal_list_lock);
++}
++
++subsys_initcall(thermal_init);
++module_exit(thermal_exit);
+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
-
- /* 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];
+-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
- 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)
+ If you don't know what to do here, say N.
-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); \
- }
++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.
-@@ -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);
+-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;
- #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.
- */
++ 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;
++ }
--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;
+ listener->dev = idev;
+ listener->event_count = atomic_read(&idev->event);
+ filep->private_data = listener;
- 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);
+ 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;
+ }
- 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;
+- if (ret)
+- kfree(listener);
++ return 0;
++
++err_infoopen:
++
++ kfree(listener);
++err_alloc_listener:
++
++ module_put(idev->owner);
- 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)
+ 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;
- 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);
- }
+- 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;
--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);
+ 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;
+ }
- 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;
- }
+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 @@
--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;
+ #include <asm/io.h>
- 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);
+-#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 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 struct pci_device_id hilscher_pci_ids[] = {
++static struct pci_device_id hilscher_pci_ids[] __devinitdata = {
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_9030,
+diff --git a/drivers/uio/uio_smx.c b/drivers/uio/uio_smx.c
+new file mode 100644
+index 0000000..44054a6
+--- /dev/null
++++ b/drivers/uio/uio_smx.c
+@@ -0,0 +1,140 @@
++/*
++ * UIO SMX Cryptengine driver.
++ *
++ * (C) 2008 Nias Digital P/L <bn at niasdigital.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/device.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/uio_driver.h>
++#include <linux/io.h>
++
++#define DRV_NAME "smx-ce"
++#define DRV_VERSION "0.03"
++
++#define SMX_CSR 0x00000000
++#define SMX_EnD 0x00000001
++#define SMX_RUN 0x00000002
++#define SMX_DRDY 0x00000004
++#define SMX_ERR 0x00000008
++
++static irqreturn_t smx_handler(int irq, struct uio_info *dev_info)
++{
++ void __iomem *csr = dev_info->mem[0].internal_addr + SMX_CSR;
++
++ u32 status = ioread32(csr);
++
++ if (!(status & SMX_DRDY))
++ return IRQ_NONE;
++
++ /* Disable interrupt */
++ iowrite32(status & ~SMX_DRDY, csr);
++ return IRQ_HANDLED;
++}
++
++static int __devinit smx_ce_probe(struct platform_device *dev)
++{
++
++ int ret = -ENODEV;
++ struct uio_info *info;
++ struct resource *regs;
++
++ info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
++ if (!info)
++ return -ENOMEM;
++
++ regs = platform_get_resource(dev, IORESOURCE_MEM, 0);
++ if (!regs) {
++ dev_err(&dev->dev, "No memory resource specified\n");
++ goto out_free;
++ }
++
++ info->mem[0].addr = regs->start;
++ if (!info->mem[0].addr) {
++ dev_err(&dev->dev, "Invalid memory resource\n");
++ goto out_free;
++ }
++
++ info->mem[0].size = regs->end - regs->start + 1;
++ info->mem[0].internal_addr = ioremap(regs->start, info->mem[0].size);
++
++ if (!info->mem[0].internal_addr) {
++ dev_err(&dev->dev, "Can't remap memory address range\n");
++ goto out_free;
++ }
++
++ info->mem[0].memtype = UIO_MEM_PHYS;
++
++ info->name = "smx-ce";
++ info->version = "0.03";
++
++ info->irq = platform_get_irq(dev, 0);
++ if (info->irq < 0) {
++ ret = info->irq;
++ dev_err(&dev->dev, "No (or invalid) IRQ resource specified\n");
++ goto out_unmap;
++ }
++
++ info->irq_flags = IRQF_SHARED;
++ info->handler = smx_handler;
++
++ platform_set_drvdata(dev, info);
++
++ ret = uio_register_device(&dev->dev, info);
++
++ if (ret)
++ goto out_unmap;
++
++ return 0;
++
++out_unmap:
++ iounmap(info->mem[0].internal_addr);
++out_free:
++ kfree(info);
++
++ return ret;
++}
++
++static int __devexit smx_ce_remove(struct platform_device *dev)
++{
++ struct uio_info *info = platform_get_drvdata(dev);
++
++ uio_unregister_device(info);
++ platform_set_drvdata(dev, NULL);
++ iounmap(info->mem[0].internal_addr);
++
++ kfree(info);
++
++ return 0;
++}
++
++static struct platform_driver smx_ce_driver = {
++ .probe = smx_ce_probe,
++ .remove = __devexit_p(smx_ce_remove),
++ .driver = {
++ .name = DRV_NAME,
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init smx_ce_init_module(void)
++{
++ return platform_driver_register(&smx_ce_driver);
++}
++module_init(smx_ce_init_module);
++
++static void __exit smx_ce_exit_module(void)
++{
++ platform_driver_unregister(&smx_ce_driver);
++}
++module_exit(smx_ce_exit_module);
++
++MODULE_LICENSE("GPL v2");
++MODULE_VERSION(DRV_VERSION);
++MODULE_AUTHOR("Ben Nizette <bn at niasdigital.com>");
+diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
+index a51eeed..5ea3093 100644
+--- a/drivers/usb/atm/cxacru.c
++++ b/drivers/usb/atm/cxacru.c
+@@ -38,6 +38,7 @@
+ #include <linux/device.h>
+ #include <linux/firmware.h>
+ #include <linux/mutex.h>
++#include <asm/unaligned.h>
--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);
+ #include "usbatm.h"
- 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);
+@@ -444,7 +445,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 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);
+ static void cxacru_timeout_kill(unsigned long data)
+@@ -573,7 +574,7 @@ static int cxacru_cm_get_array(struct cxacru_data *instance, enum cxacru_cm_requ
+ u32 *data, int size)
+ {
+ int ret, len;
+- u32 *buf;
++ __le32 *buf;
+ int offb, offd;
+ const int stride = CMD_PACKET_SIZE / (4 * 2) - 1;
+ int buflen = ((size - 1) / stride + 1 + size * 2) * 4;
+@@ -837,7 +838,7 @@ static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw,
+ buf[offb++] = l;
+ buf[offb++] = code1;
+ buf[offb++] = code2;
+- *((u32 *) (buf + offb)) = cpu_to_le32(addr);
++ put_unaligned(cpu_to_le32(addr), (__le32 *)(buf + offb));
+ offb += 4;
+ addr += l;
+ if(l)
+@@ -874,8 +875,9 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
+ int off;
+ struct usbatm_data *usbatm = instance->usbatm;
+ struct usb_device *usb_dev = usbatm->usb_dev;
+- u16 signature[] = { usb_dev->descriptor.idVendor, usb_dev->descriptor.idProduct };
+- u32 val;
++ __le16 signature[] = { usb_dev->descriptor.idVendor,
++ usb_dev->descriptor.idProduct };
++ __le32 val;
- 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");
+ dbg("cxacru_upload_firmware");
--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
- };
+@@ -955,7 +957,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
+ /* Load config data (le32), doing one packet at a time */
+ if (cf)
+ for (off = 0; off < cf->size / 4; ) {
+- u32 buf[CMD_PACKET_SIZE / 4 - 1];
++ __le32 buf[CMD_PACKET_SIZE / 4 - 1];
+ int i, len = min_t(int, cf->size / 4 - off, CMD_PACKET_SIZE / 4 / 2 - 1);
+ buf[0] = cpu_to_le32(len);
+ for (i = 0; i < len; i++, off++) {
+diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
+index c5ec1a5..5f71ff3 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)
--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;
+ #define uea_vdbg(usb_dev, format, args...) \
+@@ -94,10 +94,10 @@
+ } while (0)
-@@ -320,7 +329,7 @@ static void scsi_device_dev_release(struct device *dev)
+ #define uea_enters(usb_dev) \
+- uea_vdbg(usb_dev, "entering %s\n", __FUNCTION__)
++ uea_vdbg(usb_dev, "entering %s\n", __func__)
- static struct class sdev_class = {
- .name = "scsi_device",
-- .release = scsi_device_cls_release,
-+ .dev_release = scsi_device_cls_release,
- };
+ #define uea_leaves(usb_dev) \
+- uea_vdbg(usb_dev, "leaving %s\n", __FUNCTION__)
++ uea_vdbg(usb_dev, "leaving %s\n", __func__)
- /* all probing is done in the individual ->probe routines */
-@@ -424,7 +433,8 @@ void scsi_sysfs_unregister(void)
+ #define uea_err(usb_dev, format,args...) \
+ dev_err(&(usb_dev)->dev ,"[UEAGLE-ATM] " format , ##args)
+@@ -305,8 +305,6 @@ enum {
*/
- #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));
- }
+ #define FW_GET_BYTE(p) *((__u8 *) (p))
+-#define FW_GET_WORD(p) le16_to_cpu(get_unaligned((__le16 *) (p)))
+-#define FW_GET_LONG(p) le32_to_cpu(get_unaligned((__le32 *) (p)))
+
+ #define FW_DIR "ueagle-atm/"
+ #define NB_MODEM 4
+@@ -621,7 +619,7 @@ static void uea_upload_pre_firmware(const struct firmware *fw_entry, void *conte
+ if (size < 4)
+ goto err_fw_corrupted;
+
+- crc = FW_GET_LONG(pfw);
++ crc = get_unaligned_le32(pfw);
+ pfw += 4;
+ size -= 4;
+ if (crc32_be(0, pfw, size) != crc)
+@@ -640,7 +638,7 @@ static void uea_upload_pre_firmware(const struct firmware *fw_entry, void *conte
+
+ while (size > 3) {
+ u8 len = FW_GET_BYTE(pfw);
+- u16 add = FW_GET_WORD(pfw + 1);
++ u16 add = get_unaligned_le16(pfw + 1);
+
+ size -= len + 3;
+ if (size < 0)
+@@ -738,7 +736,7 @@ static int check_dsp_e1(u8 *dsp, unsigned int len)
+
+ for (i = 0; i < pagecount; i++) {
+
+- pageoffset = FW_GET_LONG(dsp + p);
++ pageoffset = get_unaligned_le32(dsp + p);
+ p += 4;
--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;
+ if (pageoffset == 0)
+@@ -759,7 +757,7 @@ static int check_dsp_e1(u8 *dsp, unsigned int len)
+ return 1;
-@@ -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);
+ pp += 2; /* skip blockaddr */
+- blocksize = FW_GET_WORD(dsp + pp);
++ blocksize = get_unaligned_le16(dsp + pp);
+ pp += 2;
+
+ /* enough space for block data? */
+@@ -928,7 +926,7 @@ static void uea_load_page_e1(struct work_struct *work)
+ goto bad1;
+
+ p += 4 * pageno;
+- pageoffset = FW_GET_LONG(p);
++ pageoffset = get_unaligned_le32(p);
+
+ if (pageoffset == 0)
+ goto bad1;
+@@ -945,10 +943,10 @@ static void uea_load_page_e1(struct work_struct *work)
+ bi.wOvlOffset = cpu_to_le16(ovl | 0x8000);
+
+ for (i = 0; i < blockcount; i++) {
+- blockaddr = FW_GET_WORD(p);
++ blockaddr = get_unaligned_le16(p);
+ p += 2;
+
+- blocksize = FW_GET_WORD(p);
++ blocksize = get_unaligned_le16(p);
+ p += 2;
+
+ bi.wSize = cpu_to_le16(blocksize);
+@@ -996,7 +994,7 @@ static void __uea_load_page_e4(struct uea_softc *sc, u8 pageno, int boot)
+ blockoffset = sc->dsp_firm->data + le32_to_cpu(blockidx->PageOffset);
+
+ bi.dwSize = cpu_to_be32(blocksize);
+- bi.dwAddress = swab32(blockidx->PageAddress);
++ bi.dwAddress = cpu_to_be32(le32_to_cpu(blockidx->PageAddress));
+
+ uea_dbg(INS_TO_USBDEV(sc),
+ "sending block %u for DSP page %u size %u address %x\n",
+@@ -1040,7 +1038,7 @@ static void uea_load_page_e4(struct work_struct *work)
+ return;
- 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);
+ p = (struct l1_code *) sc->dsp_firm->data;
+- if (pageno >= p->page_header[0].PageNumber) {
++ if (pageno >= le16_to_cpu(p->page_header[0].PageNumber)) {
+ uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n", pageno);
+ return;
+ }
+@@ -1065,7 +1063,7 @@ static void uea_load_page_e4(struct work_struct *work)
+ bi.bPageNumber = 0xff;
+ bi.wReserved = cpu_to_be16(UEA_RESERVED);
+ bi.dwSize = cpu_to_be32(E4_PAGE_BYTES(p->page_header[0].PageSize));
+- bi.dwAddress = swab32(p->page_header[0].PageAddress);
++ bi.dwAddress = cpu_to_be32(le32_to_cpu(p->page_header[0].PageAddress));
+
+ /* send block info through the IDMA pipe */
+ if (uea_idma_write(sc, &bi, E4_BLOCK_INFO_SIZE))
+@@ -1152,9 +1150,9 @@ static int uea_cmv_e1(struct uea_softc *sc,
+ cmv.bDirection = E1_HOSTTOMODEM;
+ cmv.bFunction = function;
+ cmv.wIndex = cpu_to_le16(sc->cmv_dsc.e1.idx);
+- put_unaligned(cpu_to_le32(address), &cmv.dwSymbolicAddress);
++ put_unaligned_le32(address, &cmv.dwSymbolicAddress);
+ cmv.wOffsetAddress = cpu_to_le16(offset);
+- put_unaligned(cpu_to_le32(data >> 16 | data << 16), &cmv.dwData);
++ put_unaligned_le32(data >> 16 | data << 16, &cmv.dwData);
- 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);
+ ret = uea_request(sc, UEA_E1_SET_BLOCK, UEA_MPTX_START, sizeof(cmv), &cmv);
+ if (ret < 0)
+@@ -1646,7 +1644,7 @@ static int request_cmvs(struct uea_softc *sc,
+ if (size < 5)
+ goto err_fw_corrupted;
+
+- crc = FW_GET_LONG(data);
++ crc = get_unaligned_le32(data);
+ data += 4;
+ size -= 4;
+ if (crc32_be(0, data, size) != crc)
+@@ -1696,9 +1694,9 @@ static int uea_send_cmvs_e1(struct uea_softc *sc)
+ "please update your firmware\n");
+
+ for (i = 0; i < len; i++) {
+- ret = uea_write_cmv_e1(sc, FW_GET_LONG(&cmvs_v1[i].address),
+- FW_GET_WORD(&cmvs_v1[i].offset),
+- FW_GET_LONG(&cmvs_v1[i].data));
++ ret = uea_write_cmv_e1(sc, get_unaligned_le32(&cmvs_v1[i].address),
++ get_unaligned_le16(&cmvs_v1[i].offset),
++ get_unaligned_le32(&cmvs_v1[i].data));
+ if (ret < 0)
+ goto out;
+ }
+@@ -1706,9 +1704,9 @@ static int uea_send_cmvs_e1(struct uea_softc *sc)
+ struct uea_cmvs_v2 *cmvs_v2 = cmvs_ptr;
- 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);
+ for (i = 0; i < len; i++) {
+- ret = uea_write_cmv_e1(sc, FW_GET_LONG(&cmvs_v2[i].address),
+- (u16) FW_GET_LONG(&cmvs_v2[i].offset),
+- FW_GET_LONG(&cmvs_v2[i].data));
++ ret = uea_write_cmv_e1(sc, get_unaligned_le32(&cmvs_v2[i].address),
++ (u16) get_unaligned_le32(&cmvs_v2[i].offset),
++ get_unaligned_le32(&cmvs_v2[i].data));
+ if (ret < 0)
+ goto out;
+ }
+@@ -1759,10 +1757,10 @@ static int uea_send_cmvs_e4(struct uea_softc *sc)
- #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, \
+ for (i = 0; i < len; i++) {
+ ret = uea_write_cmv_e4(sc, 1,
+- FW_GET_LONG(&cmvs_v2[i].group),
+- FW_GET_LONG(&cmvs_v2[i].address),
+- FW_GET_LONG(&cmvs_v2[i].offset),
+- FW_GET_LONG(&cmvs_v2[i].data));
++ get_unaligned_le32(&cmvs_v2[i].group),
++ get_unaligned_le32(&cmvs_v2[i].address),
++ get_unaligned_le32(&cmvs_v2[i].offset),
++ get_unaligned_le32(&cmvs_v2[i].data));
+ if (ret < 0)
+ goto out;
+ }
+@@ -1964,7 +1962,7 @@ static void uea_dispatch_cmv_e1(struct uea_softc *sc, struct intr_pkt *intr)
+ if (UEA_CHIP_VERSION(sc) == ADI930
+ && cmv->bFunction == E1_MAKEFUNCTION(2, 2)) {
+ cmv->wIndex = cpu_to_le16(dsc->idx);
+- put_unaligned(cpu_to_le32(dsc->address), &cmv->dwSymbolicAddress);
++ put_unaligned_le32(dsc->address, &cmv->dwSymbolicAddress);
+ cmv->wOffsetAddress = cpu_to_le16(dsc->offset);
+ } else
+ goto bad2;
+@@ -1978,11 +1976,11 @@ static void uea_dispatch_cmv_e1(struct uea_softc *sc, struct intr_pkt *intr)
- #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
- };
+ /* in case of MEMACCESS */
+ if (le16_to_cpu(cmv->wIndex) != dsc->idx ||
+- le32_to_cpu(get_unaligned(&cmv->dwSymbolicAddress)) != dsc->address ||
++ get_unaligned_le32(&cmv->dwSymbolicAddress) != dsc->address ||
+ le16_to_cpu(cmv->wOffsetAddress) != dsc->offset)
+ goto bad2;
+
+- sc->data = le32_to_cpu(get_unaligned(&cmv->dwData));
++ sc->data = get_unaligned_le32(&cmv->dwData);
+ sc->data = sc->data << 16 | sc->data >> 16;
--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);
+ wake_up_cmv_ack(sc);
+diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
+index e717f5b..0722872 100644
+--- a/drivers/usb/atm/usbatm.c
++++ b/drivers/usb/atm/usbatm.c
+@@ -80,6 +80,7 @@
+ #include <linux/stat.h>
+ #include <linux/timer.h>
+ #include <linux/wait.h>
++#include <linux/kthread.h>
--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;
- }
+ #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;
-- /* 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);
+- daemonize(instance->driver->driver_name);
+ allow_signal(SIGTERM);
+- instance->thread_pid = current->pid;
+-
+ complete(&instance->thread_started);
-@@ -858,7 +878,7 @@ void __scsi_remove_device(struct scsi_device *sdev)
- return;
+ 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);
- 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);
+ 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 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)
+ static int usbatm_heavy_init(struct usbatm_data *instance)
{
- int i;
-
-@@ -966,10 +986,10 @@ static struct class_device_attribute *class_attr_overridden(
- return NULL;
- }
+- 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);
+ }
--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;
++ instance->thread = t;
++ wake_up_process(t);
+ wait_for_completion(&instance->thread_started);
- /*
- * 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 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);
-- return class_device_create_file(classdev, attr);
-+ return device_create_file(classdev, attr);
- }
+- instance->thread_pid = -1;
++ instance->thread = NULL;
+ init_completion(&instance->thread_started);
+ init_completion(&instance->thread_exited);
- /**
-@@ -1000,7 +1020,7 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost)
+@@ -1287,8 +1290,8 @@ void usbatm_usb_disconnect(struct usb_interface *intf)
- 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;
+ 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);
-- 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;
+ 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_
-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)
+-#include <asm/semaphore.h>
+ #include <linux/atm.h>
+ #include <linux/atmdev.h>
+ #include <linux/completion.h>
+@@ -176,7 +175,7 @@ struct usbatm_data {
+ int disconnected;
- #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];
+ /* heavy init */
+- int thread_pid;
++ struct task_struct *thread;
+ struct completion thread_started;
+ struct completion thread_exited;
-- 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];
+diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
+index 0147ea3..cefe7f2 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
+ */
- 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];
+ /*
+@@ -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"
- 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];
- };
+@@ -118,7 +119,7 @@ static int acm_wb_alloc(struct acm *acm)
+ int i, wbn;
+ struct acm_wb *wb;
- #define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t)
+- 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 int fc_target_setup(struct transport_container *tc, struct device *dev,
-- struct class_device *cdev)
-+ struct device *cdev)
+-static void acm_wb_free(struct acm *acm, int wbn)
+-{
+- acm->wb[wbn].use = 0;
+-}
+-
+ static int acm_wb_is_avail(struct acm *acm)
{
- 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)
+ 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)
{
- 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)
+ unsigned long flags;
+- int wbn;
- #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) \
+ 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);
+ }
- #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, \
+ /*
+ * 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;
- #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)
+@@ -190,24 +182,24 @@ static int acm_write_start(struct acm *acm)
+ return 0; /* A white lie */
+ }
- #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)
+- wbn = acm->write_current;
+ if (!acm_wb_is_used(acm, wbn)) {
+ spin_unlock_irqrestore(&acm->write_lock, flags);
+ return 0;
+ }
+ wb = &acm->wb[wbn];
- #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)
+- 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;
- #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); \
+- 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;
+ }
- #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++
+@@ -288,7 +280,7 @@ static void acm_ctrl_irq(struct urb *urb)
- #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++
+ case USB_CDC_NOTIFY_SERIAL_STATE:
- #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, \
+- newctrl = le16_to_cpu(get_unaligned((__le16 *) data));
++ newctrl = get_unaligned_le16(data);
- #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++; \
+ if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
+ dbg("calling hangup");
+@@ -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);
}
-@@ -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)
+ /* 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 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);
+- struct acm *acm = (struct acm *)urb->context;
++ struct acm *acm;
++ struct acm_wb *wb = urb->context;
- /* 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;
+ 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);
}
--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);
+@@ -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;
-@@ -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);
+@@ -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);
- 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)
+- 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 fc_rport *rport = transport_class_to_rport(cdev);
-+ struct fc_rport *rport = transport_class_to_rport(dev);
+ 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:
- /* 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);
+ 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;
}
- }
--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);
+ 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;
- 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)
- }
+- 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);
- 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);
+ acm_set_control(acm, acm->ctrlout);
+@@ -1091,7 +1095,8 @@ skip_countries:
- 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);
+ 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);
-@@ -941,9 +949,10 @@ static FC_CLASS_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR,
+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 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 ACM_NW 2
++#define ACM_NW 16
+ #define ACM_NR 16
- #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++
+ struct acm_wb {
+@@ -67,6 +67,8 @@ struct acm_wb {
+ dma_addr_t dmah;
+ int len;
+ int use;
++ struct urb *urb;
++ struct acm *instance;
+ };
- #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);
+ 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"
- #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) \
+ 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
- #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, \
+ If you are unsure about this, say N here.
- #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, \
+-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
- #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)
+ 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.
- #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)
+ 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
- #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)
+ 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.
- #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); \
- }
+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);
+ }
- #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, \
++ /*
++ * 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;
- #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)
+ 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;
- #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)
+- 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,
- #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)
+ 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;
- #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)
+ 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;
- #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 */
+ 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;
- #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++
+ case USBDEVFS_GETDRIVER:
+- snoop(&dev->dev, "%s: GETDRIVER\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: GETDRIVER\n", __func__);
+ ret = proc_getdriver(ps, p);
+ break;
- #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 */
+ case USBDEVFS_CONNECTINFO:
+- snoop(&dev->dev, "%s: CONNECTINFO\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: CONNECTINFO\n", __func__);
+ ret = proc_connectinfo(ps, p);
+ break;
- #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, \
+ case USBDEVFS_SETINTERFACE:
+- snoop(&dev->dev, "%s: SETINTERFACE\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: SETINTERFACE\n", __func__);
+ ret = proc_setintf(ps, p);
+ break;
- #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);
+ case USBDEVFS_SETCONFIGURATION:
+- snoop(&dev->dev, "%s: SETCONFIGURATION\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: SETCONFIGURATION\n", __func__);
+ ret = proc_setconfig(ps, p);
+ break;
- 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);
+ 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
- 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);
+ 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;
- fc_private_vport_rd_enum_attr(vport_type, FC_PORTTYPE_MAX_NAMELEN);
+ case USBDEVFS_REAPURB32:
+- snoop(&dev->dev, "%s: REAPURB32\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: REAPURB32\n", __func__);
+ ret = proc_reapurb_compat(ps, p);
+ break;
- 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);
+ case USBDEVFS_REAPURBNDELAY32:
+- snoop(&dev->dev, "%s: REAPURBDELAY32\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: REAPURBDELAY32\n", __func__);
+ ret = proc_reapurbnonblock_compat(ps, p);
+ break;
- 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);
+ 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
- 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);
+ 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;
-@@ -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);
+ 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;
-@@ -1246,9 +1264,10 @@ static FC_CLASS_DEVICE_ATTR(vport, vport_disable, S_IWUSR,
+ case USBDEVFS_CLAIMINTERFACE:
+- snoop(&dev->dev, "%s: CLAIMINTERFACE\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: CLAIMINTERFACE\n", __func__);
+ ret = proc_claiminterface(ps, p);
+ break;
- #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) \
+ case USBDEVFS_RELEASEINTERFACE:
+- snoop(&dev->dev, "%s: RELEASEINTERFACE\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: RELEASEINTERFACE\n", __func__);
+ ret = proc_releaseinterface(ps, p);
+ break;
- #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, \
+ 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;
- #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, \
+- dev_dbg(dev, "%s\n", __FUNCTION__);
++ dev_dbg(dev, "%s\n", __func__);
- #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)
+ 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;
- #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)
+- dev_dbg(dev, "%s\n", __FUNCTION__);
++ dev_dbg(dev, "%s\n", __func__);
- #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)
+ 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__);
- #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)
+ 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);
- #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++
+ 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;
+ }
- #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++
+@@ -823,11 +821,9 @@ static int usb_resume_device(struct usb_device *udev)
+ status = udriver->resume(udev);
- #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)
+ 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;
+ }
- #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)); \
+@@ -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;
}
- #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)
+@@ -914,7 +910,7 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
+ }
- #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)
+ 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);
- #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, \
+@@ -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)
+ }
- #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++; \
+ done:
+- dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
++ dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
+ return status;
}
-@@ -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);
+@@ -1180,8 +1175,7 @@ static int usb_resume_both(struct usb_device *udev)
+ }
+ } else {
- if (fc_host_supported_classes(shost) == FC_COS_UNSPECIFIED)
- return snprintf(buf, 20, "unspecified\n");
+- /* 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);
+ }
- return get_fc_cos_names(fc_host_supported_classes(shost), buf);
+@@ -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;
}
--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));
+@@ -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);
}
--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)
+ /**
+@@ -1282,7 +1277,7 @@ void usb_try_autosuspend_device(struct usb_device *udev)
{
-- struct Scsi_Host *shost = transport_class_to_shost(cdev);
-+ struct Scsi_Host *shost = transport_class_to_shost(dev);
+ usb_autopm_do_device(udev, 0);
+ dev_vdbg(&udev->dev, "%s: cnt %d\n",
+- __FUNCTION__, udev->pm_usage_cnt);
++ __func__, udev->pm_usage_cnt);
+ }
- if (fc_host_supported_speeds(shost) == FC_PORTSPEED_UNKNOWN)
- return snprintf(buf, 20, "unknown\n");
+ /**
+@@ -1310,7 +1305,7 @@ int usb_autoresume_device(struct usb_device *udev)
- return get_fc_port_speed_names(fc_host_supported_speeds(shost), buf);
+ 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;
}
--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 */
+@@ -1382,7 +1377,7 @@ void usb_autopm_put_interface(struct usb_interface *intf)
- 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);
+ 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);
- if (i->f->get_host_active_fc4s)
-@@ -1443,13 +1470,14 @@ show_fc_host_active_fc4s (struct class_device *cdev, char *buf)
+@@ -1426,7 +1421,7 @@ int usb_autopm_get_interface(struct usb_interface *intf)
- return (ssize_t)show_fc_fc4s(buf, fc_host_active_fc4s(shost));
+ 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;
}
--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);
+ EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
+@@ -1448,7 +1443,7 @@ int usb_autopm_set_interface(struct usb_interface *intf)
- 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);
+ 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 (i->f->get_host_speed)
-@@ -1460,7 +1488,7 @@ show_fc_host_speed (struct class_device *cdev, char *buf)
+ /* 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;
+ }
- 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);
+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;
-@@ -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);
+- 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);
- /* Private Host Attributes */
+- dev->dev.power.power_state = PMSG_ON;
+-
+ clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
- 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;
+- 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] = {
- 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)
+ 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 */
- 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;
- }
+ 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;
--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);
+ might_sleep();
- 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;
+@@ -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;
+ }
-@@ -1544,7 +1573,7 @@ store_fc_private_host_issue_lip(struct class_device *cdev,
- return -ENOENT;
+ /* any errors get returned through the urb completion */
+@@ -915,15 +924,6 @@ static int register_root_hub(struct usb_hcd *hcd)
+ return retval;
}
--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);
+-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);
+-}
+-
- 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)
+@@ -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 */
- /* 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)
+ 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);
- 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);
+ /* called after entering D0 (etc), before resuming the hub */
+- int (*resume) (struct usb_hcd *hcd);
++ int (*pci_resume) (struct usb_hcd *hcd);
- 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);
+ /* 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 */
- /* ignore any data value written to the attribute */
-@@ -1622,31 +1653,31 @@ fc_reset_statistics(struct class_device *cdev, const char *buf,
+ /* force handover of high-speed port to full-speed companion */
+ void (*relinquish_port)(struct usb_hcd *, int);
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 68fc521..eb57fcc 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -23,7 +23,6 @@
+ #include <linux/mutex.h>
+ #include <linux/freezer.h>
- return -ENOENT;
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ #include <asm/byteorder.h>
+
+@@ -31,12 +30,6 @@
+ #include "hcd.h"
+ #include "hub.h"
+
+-#ifdef CONFIG_USB_PERSIST
+-#define USB_PERSIST 1
+-#else
+-#define USB_PERSIST 0
+-#endif
+-
+ /* if we are in debug mode, always announce new devices */
+ #ifdef DEBUG
+ #ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES
+@@ -334,6 +327,27 @@ static int get_port_status(struct usb_device *hdev, int port1,
+ return status;
}
--static 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
- };
++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)
+ }
-@@ -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)
+ /* caller has locked the hub device */
+-static int hub_pre_reset(struct usb_interface *intf)
++static void hub_stop(struct usb_hub *hub)
{
-- 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;
+- 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;
}
--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);
+@@ -911,7 +1007,7 @@ static void hub_disconnect(struct usb_interface *intf)
-@@ -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;
+ /* 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);
}
--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);
++/*
++ * 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;
-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;
+ /* 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)
+ }
+ }
-- 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 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 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)
+ static void usb_stop_pm(struct usb_device *udev)
+@@ -1174,7 +1298,7 @@ void usb_disconnect(struct usb_device **pdev)
+ int i;
--#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)
+ if (!udev) {
+- pr_debug ("%s nodev\n", __FUNCTION__);
++ pr_debug ("%s nodev\n", __func__);
+ return;
+ }
--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);
+@@ -1511,28 +1635,6 @@ out_authorized:
}
-@@ -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)
+-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)
{
-- 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);
+@@ -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);
- #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);
+ 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)
+ }
- 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");
+ clear_bit(port1, hub->busy_bits);
+- if (!hub->hdev->parent && !hub->busy_bits[0])
+- usb_enable_root_hub_irq(hub->hdev->bus);
- 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,
- };
+ if (status == 0)
+ status = finish_port_resume(udev);
+@@ -2001,7 +2100,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ }
+ }
-@@ -119,7 +121,7 @@ static struct attribute_group iscsi_transport_group = {
+- 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 iscsi_setup_host(struct transport_container *tc, struct device *dev,
-- struct class_device *cdev)
-+ struct device *cdev)
+ static int hub_resume(struct usb_interface *intf)
{
- 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,
+- 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 iscsi_remove_host(struct transport_container *tc, struct device *dev,
-- struct class_device *cdev)
-+ struct device *cdev)
+ static int hub_reset_resume(struct usb_interface *intf)
{
- 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);
- }
+ struct usb_hub *hub = usb_get_intfdata(intf);
+- struct usb_device *hdev = hub->hdev;
+- int port1;
--#define iscsi_cdev_to_conn(_cdev) \
-- iscsi_dev_to_conn(_cdev->dev)
++ dev_dbg(&intf->dev, "%s\n", __func__);
+ hub_power_on(hub);
-
- #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); \
+- 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;
}
-@@ -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
+@@ -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.
*/
- #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)
+ void usb_root_hub_lost_power(struct usb_device *rhdev)
{
-- 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));
+@@ -2148,12 +2218,13 @@ static int hub_port_debounce(struct usb_hub *hub, int port1)
+ return portstatus;
}
- 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); \
+-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);
-@@ -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); \
+ #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;
}
-@@ -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;
+@@ -2356,26 +2428,33 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ #undef GET_DESCRIPTOR_BUFSIZE
+ }
-- 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;
+- 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;
++ }
- /* 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;
+ 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;
--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);
+- 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);
-- 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);
+ /* 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;
+ }
- 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)
+@@ -2873,11 +2954,6 @@ static void hub_events(void)
+ hub->activating = 0;
-@@ -261,7 +261,7 @@ static void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy)
- */
+- /* 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 sas_host_setup(struct transport_container *tc, struct device *dev,
-- struct class_device *cdev)
-+ struct device *cdev)
+ static int hub_thread(void *__unused)
{
- 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,
- }
++ /* 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 sas_host_remove(struct transport_container *tc, struct device *dev,
-- struct class_device *cdev)
-+ struct device *cdev)
+-static int config_descriptors_changed(struct usb_device *udev)
++static int descriptors_changed(struct usb_device *udev,
++ struct usb_device_descriptor *old_device_descriptor)
{
- struct Scsi_Host *shost = dev_to_shost(dev);
-
-@@ -356,22 +356,24 @@ EXPORT_SYMBOL(sas_remove_host);
+- 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;
- #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); \
++ /* 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;
}
- #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) \
+ /**
+@@ -3045,7 +3163,7 @@ int usb_reset_device(struct usb_device *udev)
- #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)
+ 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)
- #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)
+ /* 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);
- #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)
+ 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
- #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) \
+ /*
+ * wHubCharacteristics (masks)
+@@ -191,5 +195,6 @@ struct usb_tt_clear {
+ };
- #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)
+ 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..1d253dd 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);
- 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 (!inode) {
+- dbg("%s: could not get inode!",__FUNCTION__);
++ dbg("%s: could not get inode!",__func__);
+ return -ENOMEM;
+ }
- 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);
+ 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;
+ }
+@@ -773,7 +773,7 @@ int __init usbfs_init(void)
+ usb_register_notify(&usbfs_nb);
--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;
- };
+ /* create mount point for usbfs */
+- usbdir = proc_mkdir("usb", proc_bus);
++ usbdir = proc_mkdir("bus/usb", NULL);
--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;
+ return 0;
+ }
+@@ -783,6 +783,6 @@ void usbfs_cleanup(void)
+ usb_unregister_notify(&usbfs_nb);
+ unregister_filesystem(&usb_fs_type);
+ if (usbdir)
+- remove_proc_entry("usb", proc_bus);
++ remove_proc_entry("bus/usb", NULL);
+ }
- 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:
+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;
-@@ -490,20 +497,22 @@ static ssize_t store_sas_phy_enable(struct class_device *cdev,
- return count;
- }
+ buf[0] = 0;
+- tbuf = kmalloc(256, GFP_KERNEL);
++ tbuf = kmalloc(256, GFP_NOIO);
+ if (!tbuf)
+ return -ENOMEM;
--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)
+@@ -1068,7 +1068,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
{
-- struct sas_phy *phy = transport_class_to_phy(cdev);
-+ struct sas_phy *phy = transport_class_to_phy(dev);
+ int i;
- return snprintf(buf, 20, "%d", phy->enabled);
- }
+- 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);
+ }
--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);
+ /* Now that the interfaces are unbound, nobody should
+@@ -1231,7 +1231,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ */
--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;
- };
+ /* 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);
--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);
+@@ -1330,8 +1330,7 @@ int usb_reset_configuration(struct usb_device *dev)
+ struct usb_interface *intf = config->interface[i];
+ struct usb_host_interface *alt;
--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);
+- 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);
- 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); \
+ /* 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);
- #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);
+-#if defined(CONFIG_USB_PERSIST) || defined(CONFIG_USB_SUSPEND)
+-static const char power_group[] = "power";
+-#endif
++#ifdef CONFIG_PM
-@@ -1017,23 +1029,25 @@ EXPORT_SYMBOL(sas_port_mark_backlink);
+-#ifdef CONFIG_USB_PERSIST
++static const char power_group[] = "power";
- #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); \
- }
+ 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);
- #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)
+- /* 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 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 add_persist_attributes(dev) 0
+ #define remove_persist_attributes(dev) do {} while (0)
- #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)
+-#endif /* CONFIG_USB_PERSIST */
++#endif /* CONFIG_PM */
- 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);
+ #ifdef CONFIG_USB_SUSPEND
- 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);
- }
+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;
+ }
--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);
+@@ -590,6 +590,30 @@ void usb_kill_anchored_urbs(struct usb_anchor *anchor)
+ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs);
- 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)
+ /**
++ * 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)
{
-- 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);
+ f->is_active = 1;
+- f->dev.power.power_state.event = PM_EVENT_ON;
}
--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)
+ static inline void mark_quiesced(struct usb_interface *f)
{
-- 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);
+ f->is_active = 0;
+- f->dev.power.power_state.event = PM_EVENT_SUSPEND;
}
--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);
+ 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
- sas_rphy_protocol_attr(identify.initiator_port_protocols,
-@@ -1161,9 +1178,10 @@ static DECLARE_TRANSPORT_CLASS(sas_end_dev_class,
+ 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.
- #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) \
+ 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".
- #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)
+ 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.
- 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,
+ config USB_ATMEL_USBA
+ tristate
+@@ -337,7 +337,7 @@ config USB_AT91
- #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) \
+ 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
- #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)
+ 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".
- 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,
- */
+ 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.
- #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++
++ 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".
- #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)
- }
+diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
+index b663f23..ce337cb 100644
+--- a/drivers/usb/gadget/amd5536udc.c
++++ b/drivers/usb/gadget/amd5536udc.c
+@@ -328,6 +328,7 @@ udc_ep_enable(struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc)
+ u32 tmp;
+ unsigned long iflags;
+ u8 udc_csr_epix;
++ unsigned maxpacket;
+
+ if (!usbep
+ || usbep->name == ep0_string
+@@ -354,9 +355,10 @@ udc_ep_enable(struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc)
+ writel(tmp, &dev->ep[ep->num].regs->ctl);
+
+ /* set max packet size */
++ maxpacket = le16_to_cpu(desc->wMaxPacketSize);
+ tmp = readl(&dev->ep[ep->num].regs->bufout_maxpkt);
+- tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize, UDC_EP_MAX_PKT_SIZE);
+- ep->ep.maxpacket = desc->wMaxPacketSize;
++ tmp = AMD_ADDBITS(tmp, maxpacket, UDC_EP_MAX_PKT_SIZE);
++ ep->ep.maxpacket = maxpacket;
+ writel(tmp, &dev->ep[ep->num].regs->bufout_maxpkt);
+
+ /* IN ep */
+@@ -370,8 +372,8 @@ udc_ep_enable(struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc)
+ /* double buffering: fifo size = 2 x max packet size */
+ tmp = AMD_ADDBITS(
+ tmp,
+- desc->wMaxPacketSize * UDC_EPIN_BUFF_SIZE_MULT
+- / UDC_DWORD_BYTES,
++ maxpacket * UDC_EPIN_BUFF_SIZE_MULT
++ / UDC_DWORD_BYTES,
+ UDC_EPIN_BUFF_SIZE);
+ writel(tmp, &dev->ep[ep->num].regs->bufin_framenum);
+
+@@ -390,7 +392,7 @@ udc_ep_enable(struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc)
+
+ /* set max packet size UDC CSR */
+ tmp = readl(&dev->csr->ne[ep->num - UDC_CSR_EP_OUT_IX_OFS]);
+- tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize,
++ tmp = AMD_ADDBITS(tmp, maxpacket,
+ UDC_CSR_NE_MAX_PKT);
+ writel(tmp, &dev->csr->ne[ep->num - UDC_CSR_EP_OUT_IX_OFS]);
+
+@@ -407,7 +409,7 @@ udc_ep_enable(struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc)
+ /* set ep values */
+ tmp = readl(&dev->csr->ne[udc_csr_epix]);
+ /* max packet */
+- tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize, UDC_CSR_NE_MAX_PKT);
++ tmp = AMD_ADDBITS(tmp, maxpacket, UDC_CSR_NE_MAX_PKT);
+ /* ep number */
+ tmp = AMD_ADDBITS(tmp, desc->bEndpointAddress, UDC_CSR_NE_NUM);
+ /* ep direction */
+@@ -2832,7 +2834,7 @@ __acquires(dev->lock)
+ /* make usb request for gadget driver */
+ memset(&setup_data, 0 , sizeof(union udc_setup_data));
+ setup_data.request.bRequest = USB_REQ_SET_CONFIGURATION;
+- setup_data.request.wValue = dev->cur_config;
++ setup_data.request.wValue = cpu_to_le16(dev->cur_config);
+
+ /* programm the NE registers */
+ for (i = 0; i < UDC_EP_NUM; i++) {
+@@ -2881,8 +2883,8 @@ __acquires(dev->lock)
+ memset(&setup_data, 0 , sizeof(union udc_setup_data));
+ setup_data.request.bRequest = USB_REQ_SET_INTERFACE;
+ setup_data.request.bRequestType = USB_RECIP_INTERFACE;
+- setup_data.request.wValue = dev->cur_alt;
+- setup_data.request.wIndex = dev->cur_intf;
++ setup_data.request.wValue = cpu_to_le16(dev->cur_alt);
++ setup_data.request.wIndex = cpu_to_le16(dev->cur_intf);
+
+ DBG(dev, "SET_INTERFACE interrupt: alt=%d intf=%d\n",
+ dev->cur_alt, dev->cur_intf);
+@@ -3248,6 +3250,8 @@ static int udc_pci_probe(
- 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);
+ /* pci setup */
+ if (pci_enable_device(pdev) < 0) {
++ kfree(dev);
++ dev = 0;
+ retval = -ENODEV;
+ goto finished;
+ }
+@@ -3259,6 +3263,8 @@ static int udc_pci_probe(
-@@ -169,7 +169,7 @@ static int spi_host_setup(struct transport_container *tc, struct device *dev,
+ 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 +3273,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;
+ }
- static int spi_host_configure(struct transport_container *tc,
- struct device *dev,
-- struct class_device *cdev);
-+ struct device *cdev);
+ if (!pdev->irq) {
+ dev_err(&dev->pdev->dev, "irq not set\n");
++ kfree(dev);
++ dev = 0;
+ retval = -ENODEV;
+ goto finished;
+ }
- static DECLARE_TRANSPORT_CLASS(spi_host_class,
- "spi_host",
-@@ -195,11 +195,11 @@ static int spi_host_match(struct attribute_container *cont,
+ 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..274c60a 100644
+--- a/drivers/usb/gadget/at91_udc.c
++++ b/drivers/usb/gadget/at91_udc.c
+@@ -231,6 +231,7 @@ static int proc_udc_open(struct inode *inode, struct file *file)
+ }
- static int spi_target_configure(struct transport_container *tc,
- struct device *dev,
-- struct class_device *cdev);
-+ struct device *cdev);
+ static const struct file_operations proc_ops = {
++ .owner = THIS_MODULE,
+ .open = proc_udc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -239,15 +240,7 @@ static const struct file_operations proc_ops = {
- static int spi_device_configure(struct transport_container *tc,
- struct device *dev,
-- struct class_device *cdev)
-+ struct device *cdev)
+ static void create_debug_file(struct at91_udc *udc)
{
- 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,
+- struct proc_dir_entry *pde;
+-
+- pde = create_proc_entry (debug_filename, 0, NULL);
+- udc->pde = pde;
+- if (pde == NULL)
+- return;
+-
+- pde->proc_fops = &proc_ops;
+- pde->data = udc;
++ udc->pde = proc_create_data(debug_filename, 0, NULL, &proc_ops, udc);
+ }
- 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);
+ static void remove_debug_file(struct at91_udc *udc)
+@@ -389,6 +382,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;
-@@ -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) \
+ /*
+ * TODO: allow for writing two packets to the fifo ... that'll
+@@ -413,6 +407,8 @@ static int write_fifo(struct at91_ep *ep, struct at91_request *req)
+ return 0;
+ }
- #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, \
++ 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 +431,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 +453,7 @@ static void nuke(struct at91_ep *ep, int status)
+ if (list_empty(&ep->queue))
+ return;
- #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);
+- 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 +788,7 @@ static int at91_wakeup(struct usb_gadget *gadget)
+ int status = -EINVAL;
+ unsigned long flags;
- #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);
+- DBG("%s\n", __FUNCTION__ );
++ DBG("%s\n", __func__ );
+ local_irq_save(flags);
- #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);
+ if (!udc->clocked || !udc->suspended)
+diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
+index b0db4c3..e756023 100644
+--- a/drivers/usb/gadget/atmel_usba_udc.c
++++ b/drivers/usb/gadget/atmel_usba_udc.c
+@@ -18,6 +18,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/usb/ch9.h>
+ #include <linux/usb/gadget.h>
++#include <linux/usb/atmel_usba_udc.h>
+ #include <linux/delay.h>
- /* 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)
- }
+ #include <asm/gpio.h>
+@@ -27,6 +28,7 @@
- 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);
+ static struct usba_udc the_udc;
++static struct usba_ep *usba_ep;
- /* 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)
+ #ifdef CONFIG_USB_GADGET_DEBUG_FS
+ #include <linux/debugfs.h>
+@@ -324,53 +326,28 @@ static int vbus_is_present(struct usba_udc *udc)
+ return 1;
}
- static 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)
+-static void copy_to_fifo(void __iomem *fifo, const void *buf, int len)
++#if defined(CONFIG_AVR32)
++
++static void toggle_bias(int is_on)
{
- int j, picosec, period = -1;
-@@ -449,9 +455,10 @@ store_spi_transport_period_helper(struct class_device *cdev, const char *buf,
+- 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 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)
+-static void copy_from_fifo(void *buf, void __iomem *fifo, int len)
++#elif defined(CONFIG_ARCH_AT91)
++
++#include <asm/arch/at91_pmc.h>
++
++static void toggle_bias(int is_on)
{
-- 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)
+- 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));
}
- 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)
++#endif /* CONFIG_ARCH_AT91 */
++
+ static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req)
{
- 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);
+ 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" : "");
- 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)
+- 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;
+ }
- 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,
- }
+- 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,
+ };
--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);
+-#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));
--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)
+ /* 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);
- 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);
+ 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)
+ }
-@@ -549,9 +561,9 @@ static ssize_t store_spi_host_signalling(struct class_device *cdev,
+ 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);
- 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);
+ /* This will also disable the DP pullup */
+- usba_writel(udc, CTRL, 0);
++ toggle_bias(0);
++ usba_writel(udc, CTRL, USBA_DISABLE_MASK);
- #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);
+ driver->unbind(&udc->gadget);
+ udc->gadget.dev.driver = NULL;
+@@ -1908,7 +1863,7 @@ static int __init usba_udc_probe(struct platform_device *pdev)
- static struct attribute *host_attributes[] = {
-- &class_device_attr_signalling.attr,
-+ &dev_attr_signalling.attr,
- NULL
- };
+ 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;
-@@ -1344,12 +1356,12 @@ static struct attribute_group host_attribute_group = {
+ irq = platform_get_irq(pdev, 0);
+@@ -1953,19 +1908,48 @@ static int __init usba_udc_probe(struct platform_device *pdev)
- 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;
+ /* 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);
- 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);
++ 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];
-- 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;
+ 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;
- return 0;
- }
+ 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;
+ }
- 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
- };
+- 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;
-@@ -1448,7 +1459,7 @@ static struct attribute_group target_attribute_group = {
+@@ -2004,7 +1988,7 @@ static int __init usba_udc_probe(struct platform_device *pdev)
+ }
- static int spi_target_configure(struct transport_container *tc,
- struct device *dev,
-- struct class_device *cdev)
-+ struct device *cdev)
+ 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 kobject *kobj = &cdev->kobj;
+ struct usba_udc *udc;
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 usba_platform_data *pdata = pdev->dev.platform_data;
-- struct class_device_attribute *host_attrs[SRP_HOST_ATTRS + 1];
-+ struct device_attribute *host_attrs[SRP_HOST_ATTRS + 1];
+ udc = platform_get_drvdata(pdev);
-- 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;
- };
+- 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);
- #define to_srp_internal(tmpl) container_of(tmpl, struct srp_internal, t)
+@@ -2040,6 +2027,7 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
+ gpio_free(udc->vbus_pin);
- #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)
+ 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 */
- static int srp_host_setup(struct transport_container *tc, struct device *dev,
-- struct class_device *cdev)
-+ struct device *cdev)
+ /* 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..4203619 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 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);
+ struct dummy *dum = platform_get_drvdata(pdev);
- #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"
+- 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);
- 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));
+- 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);
--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 {
- };
+- 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);
- 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)
+- pdev->dev.power.power_state = PMSG_ON;
+ usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+ return 0;
+ }
+@@ -1559,8 +1555,7 @@ hub_descriptor (struct usb_hub_descriptor *desc)
+ memset (desc, 0, sizeof *desc);
+ desc->bDescriptorType = 0x29;
+ desc->bDescLength = 9;
+- desc->wHubCharacteristics = (__force __u16)
+- (__constant_cpu_to_le16 (0x0001));
++ desc->wHubCharacteristics = cpu_to_le16(0x0001);
+ desc->bNbrPorts = 1;
+ desc->bitmap [0] = 0xff;
+ desc->bitmap [1] = 0xff;
+@@ -1711,7 +1706,7 @@ static int dummy_bus_suspend (struct usb_hcd *hcd)
{
-- 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;
+ struct dummy *dum = hcd_to_dummy (hcd);
-@@ -131,7 +133,7 @@ show_srp_rport_roles(struct class_device *cdev, char *buf)
- return sprintf(buf, "%s\n", name ? : "unknown");
- }
+- dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
++ dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
--static CLASS_DEVICE_ATTR(roles, S_IRUGO, show_srp_rport_roles, NULL);
-+static DEVICE_ATTR(roles, S_IRUGO, show_srp_rport_roles, NULL);
+ spin_lock_irq (&dum->lock);
+ dum->rh_state = DUMMY_RH_SUSPENDED;
+@@ -1726,7 +1721,7 @@ static int dummy_bus_resume (struct usb_hcd *hcd)
+ struct dummy *dum = hcd_to_dummy (hcd);
+ int rc = 0;
- 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);
+- dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
++ dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
-@@ -112,11 +112,12 @@ static const char *sd_cache_types[] = {
- "write back, no read (daft)"
- };
+ spin_lock_irq (&dum->lock);
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+@@ -1900,7 +1895,7 @@ static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state)
+ struct dummy *dum;
+ int rc = 0;
--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;
- }
+- dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
++ dev_dbg (&pdev->dev, "%s\n", __func__);
--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)
+ hcd = platform_get_drvdata (pdev);
+ dum = hcd_to_dummy (hcd);
+@@ -1916,7 +1911,7 @@ static int dummy_hcd_resume (struct platform_device *pdev)
{
-- struct scsi_disk *sdkp = to_scsi_disk(cdev);
-+ struct scsi_disk *sdkp = to_scsi_disk(dev);
- struct scsi_device *sdp = sdkp->device;
+ struct usb_hcd *hcd;
- if (!capable(CAP_SYS_ADMIN))
-@@ -177,10 +179,11 @@ static ssize_t sd_store_manage_start_stop(struct class_device *cdev,
- return count;
- }
+- dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
++ dev_dbg (&pdev->dev, "%s\n", __func__);
--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;
+ hcd = platform_get_drvdata (pdev);
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+@@ -1937,69 +1932,57 @@ static struct platform_driver dummy_hcd_driver = {
- 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)
+-/* 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)
{
-- struct scsi_disk *sdkp = to_scsi_disk(cdev);
-+ struct scsi_disk *sdkp = to_scsi_disk(dev);
- int ct = sdkp->RCD + 2*sdkp->WCE;
+- int retval;
++ int retval = -ENOMEM;
- return snprintf(buf, 40, "%s\n", sd_cache_types[ct]);
- }
+ if (usb_disabled ())
+ return -ENODEV;
--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);
+- 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;
- return snprintf(buf, 20, "%u\n", sdkp->DPOFUA);
- }
+- 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;
--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;
+- 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;
- return snprintf(buf, 20, "%u\n", sdp->manage_start_stop);
+-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 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)
+ static void __exit cleanup (void)
{
-- 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);
+- 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 @@
--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;
+ /* we must assign addresses for configurable endpoints (like net2280) */
+-static __devinitdata unsigned epnum;
++static __initdata unsigned epnum;
- 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;
- }
+ // #define MANY_ENDPOINTS
+ #ifdef MANY_ENDPOINTS
+ /* more than 15 configurable endpoints */
+-static __devinitdata unsigned in_epnum;
++static __initdata unsigned in_epnum;
+ #endif
-- 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;
+@@ -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;
+ }
- get_device(&sdp->sdev_gendev);
-@@ -1734,13 +1744,13 @@ static int sd_remove(struct device *dev)
+-static struct usb_ep * __devinit
++static struct usb_ep * __init
+ find_ep (struct usb_gadget *gadget, const char *name)
{
- 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
+ struct usb_ep *ep;
+@@ -228,7 +228,7 @@ find_ep (struct usb_gadget *gadget, const char *name)
*
- * 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)
+ * 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)
{
- 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;
+ struct usb_ep *ep;
-- sdev = to_scsi_device(edev->cdev.dev);
-+ sdev = to_scsi_device(edev->edev.parent);
+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;
- if (sdev->host != sed->shost)
- return 0;
-@@ -407,10 +407,10 @@ static void ses_match_to_enclosure(struct enclosure_device *edev,
+- DEBUG (dev, "%s\n", __FUNCTION__);
++ DEBUG (dev, "%s\n", __func__);
- #define INIT_ALLOC_SIZE 32
+ 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;
--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;
+- DEBUG (dev, "%s, flush old status first\n", __FUNCTION__);
++ DEBUG (dev, "%s, flush old status first\n", __func__);
-- 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;
+ /* 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);
}
--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;
+@@ -2113,7 +2113,7 @@ static int rndis_control_ack (struct net_device *net)
- if (!scsi_device_enclosure(sdev))
- return;
+ static void eth_start (struct eth_dev *dev, gfp_t gfp_flags)
+ {
+- DEBUG (dev, "%s\n", __FUNCTION__);
++ DEBUG (dev, "%s\n", __func__);
-- edev = enclosure_find(cdev->dev);
-+ edev = enclosure_find(cdev->parent);
- if (!edev)
- return;
+ /* 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);
-@@ -649,13 +649,13 @@ static void ses_intf_remove(struct class_device *cdev,
+- 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);
- kfree(edev->component[0].scratch);
+- VDEBUG (dev, "%s\n", __FUNCTION__);
++ VDEBUG (dev, "%s\n", __func__);
+ netif_stop_queue (net);
-- class_device_put(&edev->cdev);
-+ put_device(&edev->edev);
- enclosure_unregister(edev);
+ 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 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 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
--sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
-+sg_add(struct device *cl_dev, struct class_interface *cl_intf)
+-static int __devinit get_ether_addr(const char *str, u8 *dev_addr)
++static int __init get_ether_addr(const char *str, u8 *dev_addr)
{
-- 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)
+ if (str) {
+ unsigned i;
+@@ -2260,7 +2260,7 @@ static int __devinit get_ether_addr(const char *str, u8 *dev_addr)
+ return 1;
+ }
- sdp->cdev = cdev;
- if (sg_sysfs_valid) {
-- struct class_device * sg_class_member;
-+ struct device *sg_class_member;
+-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 {
-- 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);
+ unsigned long atomic_bitflags;
+ #define REGISTERED 0
+-#define CLEAR_BULK_HALTS 1
++#define IGNORE_BULK_OUT 1
+ #define SUSPENDED 2
-- class_set_devdata(cl_dev, sdp);
-+ dev_set_drvdata(cl_dev, sdp);
+ 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;
- return 0;
+ 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)
-@@ -1482,10 +1482,10 @@ out:
- }
+ 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;
- 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);
+ 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;
- 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;
+- /* 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;
-- 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;
+ /* 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));
-- if (hdata->wh.no_sync == 0xff)
-- hdata->wh.no_sync = 0;
-+ wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_MHZ(20));
+- /* 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;
+ }
- err = request_irq(irq, sgiwd93_intr, 0, "SGI WD93", host);
- if (err) {
-diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
-index 0a52d9d..a860c3a 100644
---- a/drivers/scsi/st.c
-+++ b/drivers/scsi/st.c
-@@ -17,7 +17,7 @@
- Last modified: 18-JAN-1998 Richard Gooch <rgooch at atnf.csiro.au> Devfs support
- */
+@@ -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);
--static const char *verstr = "20080221";
-+static const char *verstr = "20080224";
+ 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);
+- }
- #include <linux/module.h>
+ 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 {
-@@ -183,6 +183,7 @@ static int modes_defined;
+ #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..7f4d482 100644
+--- a/drivers/usb/gadget/gmidi.c
++++ b/drivers/usb/gadget/gmidi.c
+@@ -229,7 +229,7 @@ static const struct usb_ac_header_descriptor_1 ac_header_desc = {
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = USB_MS_HEADER,
+ .bcdADC = __constant_cpu_to_le16(0x0100),
+- .wTotalLength = USB_DT_AC_HEADER_SIZE(1),
++ .wTotalLength = __constant_cpu_to_le16(USB_DT_AC_HEADER_SIZE(1)),
+ .bInCollection = 1,
+ .baInterfaceNr = {
+ [0] = GMIDI_MS_INTERFACE,
+@@ -253,9 +253,9 @@ static const struct usb_ms_header_descriptor ms_header_desc = {
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = USB_MS_HEADER,
+ .bcdMSC = __constant_cpu_to_le16(0x0100),
+- .wTotalLength = USB_DT_MS_HEADER_SIZE
++ .wTotalLength = __constant_cpu_to_le16(USB_DT_MS_HEADER_SIZE
+ + 2*USB_DT_MIDI_IN_SIZE
+- + 2*USB_DT_MIDI_OUT_SIZE(1),
++ + 2*USB_DT_MIDI_OUT_SIZE(1)),
+ };
- 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)
+ #define JACK_IN_EMB 1
+@@ -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..be6613a 100644
+--- a/drivers/usb/gadget/goku_udc.c
++++ b/drivers/usb/gadget/goku_udc.c
+@@ -127,7 +127,7 @@ goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
- 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; )
+ /* enabling the no-toggle interrupt mode would need an api hook */
+ mode = 0;
+- max = le16_to_cpu(get_unaligned(&desc->wMaxPacketSize));
++ max = get_unaligned_le16(&desc->wMaxPacketSize);
+ switch (max) {
+ case 64: mode++;
+ case 32: mode++;
+@@ -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;
- if (SRpnt->waiting)
-@@ -626,7 +628,7 @@ static int cross_eof(struct scsi_tape * STp, int forward)
+- 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;
- /* 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);
+- 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)
- if (STp->block_size == 0)
- return 0;
-@@ -1159,6 +1161,7 @@ static int st_open(struct inode *inode, struct file *filp)
- goto err_out;
+ /* 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;
}
-+ (STp->buffer)->cleared = 0;
- (STp->buffer)->writing = 0;
- (STp->buffer)->syscall_result = 0;
+@@ -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;
+ }
-@@ -1211,7 +1214,7 @@ static int st_flush(struct file *filp, fl_owner_t id)
- return 0;
+@@ -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);
- 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;
+ /* 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;
}
-@@ -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;
-+ }
+@@ -1286,7 +1286,7 @@ static void ep0_start(struct goku_udc *dev)
+ struct goku_udc_regs __iomem *regs = dev->regs;
+ unsigned i;
- 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++;
+- 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);
}
- 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
- }
+@@ -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__);
-+/* 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)
+ if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+ driver = NULL;
+@@ -1726,7 +1726,7 @@ static void goku_remove(struct pci_dev *pdev)
{
-@@ -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)
+ struct goku_udc *dev = pci_get_drvdata(pdev);
+- DBG(dev, "%s\n", __FUNCTION__);
++ DBG(dev, "%s\n", __func__);
- /* 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;
+ BUG_ON(dev->driver);
- l = snprintf(buf, PAGE_SIZE, "%d\n", STm->defined);
- return l;
- }
+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:
--CLASS_DEVICE_ATTR(defined, S_IRUGO, st_defined_show, NULL);
-+DEVICE_ATTR(defined, S_IRUGO, st_defined_show, NULL);
+ 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__);
--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;
+ /* 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);
- l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_blksize);
- return l;
+ 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);
}
--CLASS_DEVICE_ATTR(default_blksize, S_IRUGO, st_defblk_show, NULL);
-+DEVICE_ATTR(default_blksize, S_IRUGO, st_defblk_show, NULL);
+@@ -1575,7 +1575,7 @@ static void destroy_ep_files (struct dev_data *dev)
+ {
+ struct list_head *entry, *tmp;
--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)
+- 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 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;
+ struct dev_data *dev = get_gadget_data (gadget);
-@@ -4320,24 +4355,67 @@ static ssize_t st_defdensity_show(struct class_device *class_dev, char *buf)
- return l;
+- 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);
}
--CLASS_DEVICE_ATTR(default_density, S_IRUGO, st_defdensity_show, NULL);
-+DEVICE_ATTR(default_density, S_IRUGO, st_defdensity_show, NULL);
+@@ -1933,7 +1933,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
--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)
+ 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)
{
-- 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;
+- DEBUG("%s, %p\n", __FUNCTION__, dev);
++ DEBUG("%s, %p\n", __func__, dev);
- l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_compression - 1);
- return l;
- }
+ udc_set_address(dev, 0);
--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);
+@@ -285,7 +285,7 @@ static void udc_reinit(struct lh7a40x_udc *dev)
+ {
+ u32 i;
- static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
+- 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 i, rew, error;
- char name[10];
-- struct class_device *st_class_member;
-+ struct device *st_class_member;
+ int ep;
- 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]);
+- DEBUG("%s, %p\n", __FUNCTION__, dev);
++ DEBUG("%s, %p\n", __func__, dev);
-- 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;
+ dev->gadget.speed = USB_SPEED_UNKNOWN;
- 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 */
+@@ -412,7 +412,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+ struct lh7a40x_udc *dev = the_controller;
+ int retval;
-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 @@
+- DEBUG("%s: %s\n", __FUNCTION__, driver->driver.name);
++ DEBUG("%s: %s\n", __func__, driver->driver.name);
- Copyright 1995-2003 Kai Makisara.
+ 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));
+ }
-- Last modified: Mon Apr 7 22:49:18 2003 by makisara
-+ Last modified: Thu Feb 21 21:47:07 2008 by kai.makisara
- */
+- 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;
+ }
- #ifndef _ST_OPTIONS_H
-@@ -94,6 +94,10 @@
- The default is BSD semantics. */
- #define ST_SYSV 0
+@@ -614,7 +614,7 @@ static void done(struct lh7a40x_ep *ep, struct lh7a40x_request *req, int status)
+ unsigned int stopped = ep->stopped;
+ u32 index;
-+/* 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
+- DEBUG("%s, %p\n", __FUNCTION__, ep);
++ DEBUG("%s, %p\n", __func__, ep);
+ list_del_init(&req->queue);
-diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
-index 654430e..f308a03 100644
---- a/drivers/scsi/stex.c
-+++ b/drivers/scsi/stex.c
-@@ -33,6 +33,7 @@
- #include <scsi/scsi_host.h>
- #include <scsi/scsi_tcq.h>
- #include <scsi/scsi_dbg.h>
-+#include <scsi/scsi_eh.h>
+ 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);
- #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;
- }
+ 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);
--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 *))
+ switch (ep) {
+ case 1:
+@@ -690,7 +690,7 @@ void nuke(struct lh7a40x_ep *ep, int status)
{
-+ 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);
- }
+ struct lh7a40x_request *req;
-@@ -426,49 +419,13 @@ static int stex_map_sg(struct st_hba *hba,
- return 0;
- }
+- DEBUG("%s, %p\n", __FUNCTION__, ep);
++ DEBUG("%s, %p\n", __func__, ep);
--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)
+ /* Flush FIFO */
+ flush(ep);
+@@ -734,7 +734,7 @@ static void flush_all(struct lh7a40x_udc *dev)
+ */
+ static void flush(struct lh7a40x_ep *ep)
{
- struct st_frame *p;
- size_t count = sizeof(struct st_frame);
+- DEBUG("%s, %p\n", __FUNCTION__, ep);
++ DEBUG("%s, %p\n", __func__, ep);
- 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;
+ 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);
-- 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);
- }
+ 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);
- 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 (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 (ccb->cmd == NULL)
+ if (!ep->desc) {
+- DEBUG("%s: NO EP DESC\n", __FUNCTION__);
++ DEBUG("%s: NO EP DESC\n", __func__);
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 = {
+@@ -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;
- #include "scsi_module.c"
+- DEBUG("%s: %d\n", __FUNCTION__, ep_idx);
++ DEBUG("%s: %d\n", __func__, ep_idx);
-+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 */
+ usb_set_index(ep_idx);
- #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)
- }
- }
+@@ -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);
-+#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
- };
+ 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)
- 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
+ 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)
-+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);
+ } 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... */
-+#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
- };
+- DEBUG("%s: %d\n", __FUNCTION__, dev->usb_address);
++ DEBUG("%s: %d\n", __func__, dev->usb_address);
- 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 (!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;
-- 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
+- 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;
--#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
+- DEBUG("%s, %p\n", __FUNCTION__, _ep);
++ DEBUG("%s, %p\n", __func__, _ep);
-- 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)
+ 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;
}
- 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;
+@@ -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;
}
-- 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);
- }
+@@ -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;
+ }
- 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);
+ 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;
+ }
-- 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);
+@@ -1061,7 +1061,7 @@ static int lh7a40x_ep_enable(struct usb_ep *_ep,
+ /* Reset halt state (does flush) */
+ lh7a40x_set_halt(_ep, 0);
- return IRQ_HANDLED;
+- DEBUG("%s: enabled %s\n", __FUNCTION__, _ep->name);
++ DEBUG("%s: enabled %s\n", __func__, _ep->name);
+ return 0;
}
-@@ -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;
+
+@@ -1073,11 +1073,11 @@ static int lh7a40x_ep_disable(struct usb_ep *_ep)
+ struct lh7a40x_ep *ep;
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,
+- DEBUG("%s, %p\n", __FUNCTION__, _ep);
++ DEBUG("%s, %p\n", __func__, _ep);
- UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15);
+ 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)
-- 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)
+ 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;
}
-+/*
-+ * 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,
- };
+@@ -1106,7 +1106,7 @@ static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep,
+ {
+ struct lh7a40x_request *req;
-@@ -1261,6 +1278,7 @@ static int __init bfin_serial_init(void)
+- DEBUG("%s, %p\n", __FUNCTION__, ep);
++ DEBUG("%s, %p\n", __func__, ep);
- 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];
+ 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;
- /* 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;
+- DEBUG("%s, %p\n", __FUNCTION__, ep);
++ DEBUG("%s, %p\n", __func__, ep);
-- 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;
- }
+ 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;
- 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);
+- DEBUG("\n\n\n%s, %p\n", __FUNCTION__, _ep);
++ DEBUG("\n\n\n%s, %p\n", __func__, _ep);
- out_pram:
-- iounmap(pram);
-+ cpm_uart_unmap_pram(pinfo, pram);
- out_mem:
- iounmap(mem);
- return ret;
-diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
-index 6ea0366..74f1432 100644
---- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
-+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
-@@ -45,6 +45,8 @@
- #include <linux/serial_core.h>
- #include <linux/kernel.h>
+ 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;
+ }
-+#include <linux/of.h>
-+
- #include "cpm_uart.h"
+ 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;
+ }
- /**************************************************************/
-@@ -54,6 +56,18 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
- {
- cpm_command(port->command, cmd);
- }
-+
-+void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port,
-+ struct device_node *np)
-+{
-+ return of_iomap(np, 1);
-+}
-+
-+void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram)
-+{
-+ iounmap(pram);
-+}
-+
- #else
- void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
- {
-diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
-index d9af06a..bb862e2 100644
---- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
-+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
-@@ -41,6 +41,9 @@
- #include <asm/io.h>
- #include <asm/irq.h>
- #include <asm/fs_pd.h>
-+#ifdef CONFIG_PPC_CPM_NEW_BINDING
-+#include <asm/prom.h>
-+#endif
+ 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;
+ }
- #include <linux/serial_core.h>
- #include <linux/kernel.h>
-@@ -54,6 +57,55 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
- {
- cpm_command(port->command, cmd);
- }
-+
-+void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port,
-+ struct device_node *np)
-+{
-+ void __iomem *pram;
-+ unsigned long offset;
-+ struct resource res;
-+ unsigned long len;
-+
-+ /* Don't remap parameter RAM if it has already been initialized
-+ * during console setup.
-+ */
-+ if (IS_SMC(port) && port->smcup)
-+ return port->smcup;
-+ else if (!IS_SMC(port) && port->sccup)
-+ return port->sccup;
-+
-+ if (of_address_to_resource(np, 1, &res))
-+ return NULL;
-+
-+ len = 1 + res.end - res.start;
-+ pram = ioremap(res.start, len);
-+ if (!pram)
-+ return NULL;
-+
-+ if (!IS_SMC(port))
-+ return pram;
-+
-+ if (len != 2) {
-+ printk(KERN_WARNING "cpm_uart[%d]: device tree references "
-+ "SMC pram, using boot loader/wrapper pram mapping. "
-+ "Please fix your device tree to reference the pram "
-+ "base register instead.\n",
-+ port->port.line);
-+ return pram;
-+ }
-+
-+ offset = cpm_dpalloc(PROFF_SMC_SIZE, 64);
-+ out_be16(pram, offset);
-+ iounmap(pram);
-+ return cpm_muram_addr(offset);
-+}
-+
-+void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram)
-+{
-+ if (!IS_SMC(port))
-+ iounmap(pram);
-+}
-+
- #else
- void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
- {
-diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
-index 16ba9ac..5a375bf 100644
---- a/drivers/serial/imx.c
-+++ b/drivers/serial/imx.c
-@@ -166,15 +166,6 @@
- #define SERIAL_IMX_MAJOR 204
- #define MINOR_START 41
+@@ -1218,7 +1218,7 @@ static int lh7a40x_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+ struct lh7a40x_request *req;
+ unsigned long flags;
--#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;
+- DEBUG("%s, %p\n", __FUNCTION__, _ep);
++ DEBUG("%s, %p\n", __func__, _ep);
-- rx = readl(sport->port.membase + URXD0);
- spin_lock_irqsave(&sport->port.lock,flags);
+ 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)
-- do {
-+ while (readl(sport->port.membase + USR2) & USR2_RDR) {
- flg = TTY_NORMAL;
- sport->port.icount.rx++;
+ 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;
+ }
-+ 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;
- }
+ usb_set_index(ep_index(ep));
- 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;
+- DEBUG("%s, ep %d, val %d\n", __FUNCTION__, ep_index(ep), value);
++ DEBUG("%s, ep %d, val %d\n", __func__, ep_index(ep), value);
-- if( rx & (URXD_PRERR | URXD_OVRRUN | URXD_FRMERR) )
-- goto handle_error;
-+#ifdef SUPPORT_SYSRQ
-+ sport->port.sysrq = 0;
-+#endif
-+ }
+ spin_lock_irqsave(&ep->dev->lock, flags);
-- error_return:
- tty_insert_flip_char(tty, rx, flg);
--
-- ignore_char:
-- rx = readl(sport->port.membase + URXD0);
-- } while(rx & URXD_CHARRDY);
-+ }
+@@ -1325,11 +1325,11 @@ static int lh7a40x_fifo_status(struct usb_ep *_ep)
- 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;
- }
+ ep = container_of(_ep, struct lh7a40x_ep, ep);
+ if (!_ep) {
+- DEBUG("%s, bad ep\n", __FUNCTION__);
++ DEBUG("%s, bad ep\n", __func__);
+ return -ENODEV;
+ }
- /*
-@@ -546,7 +531,7 @@ static int imx_startup(struct uart_port *port)
- writel(USR1_RTSD, sport->port.membase + USR1);
+- DEBUG("%s, %d\n", __FUNCTION__, ep_index(ep));
++ DEBUG("%s, %d\n", __func__, ep_index(ep));
- 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);
+ /* 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)
- 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;
+ 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;
+ }
-- 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);
- }
+@@ -1376,7 +1376,7 @@ static int write_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
- /*
-@@ -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");
+ max = ep_maxpacket(ep);
-- return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
-- "imx-uart") != NULL ? 0 : -EBUSY;
-+ return ret ? 0 : -EBUSY;
- }
+- DEBUG_EP0("%s\n", __FUNCTION__);
++ DEBUG_EP0("%s\n", __func__);
- /*
-@@ -815,7 +810,7 @@ static struct imx_port imx_ports[] = {
- .type = PORT_IMX,
- .iotype = UPIO_MEM,
- .membase = (void *)IMX_UART1_BASE,
-- .mapbase = IMX_UART1_BASE, /* FIXME */
-+ .mapbase = 0x00206000,
- .irq = UART1_MINT_RX,
- .uartclk = 16000000,
- .fifosize = 32,
-@@ -831,7 +826,7 @@ static struct imx_port imx_ports[] = {
- .type = PORT_IMX,
- .iotype = UPIO_MEM,
- .membase = (void *)IMX_UART2_BASE,
-- .mapbase = IMX_UART2_BASE, /* FIXME */
-+ .mapbase = 0x00207000,
- .irq = UART2_MINT_RX,
- .uartclk = 16000000,
- .fifosize = 32,
-diff --git a/drivers/serial/kgdboc.c b/drivers/serial/kgdboc.c
-new file mode 100644
-index 0000000..9cf0332
---- /dev/null
-+++ b/drivers/serial/kgdboc.c
-@@ -0,0 +1,168 @@
-+/*
-+ * Based on the same principle as kgdboe using the NETPOLL api, this
-+ * driver uses a console polling api to implement a gdb serial inteface
-+ * which is multiplexed on a console port.
-+ *
-+ * Maintainer: Jason Wessel <jason.wessel at windriver.com>
-+ *
-+ * 2007-2008 (c) Jason Wessel - Wind River Systems, Inc.
-+ *
-+ * This file is licensed under the terms of the GNU General Public
-+ * License version 2. This program is licensed "as is" without any
-+ * warranty of any kind, whether express or implied.
-+ */
-+#include <linux/kernel.h>
-+#include <linux/ctype.h>
-+#include <linux/kgdb.h>
-+#include <linux/tty.h>
-+
-+#define MAX_CONFIG_LEN 40
-+
-+static struct kgdb_io kgdboc_io_ops;
-+
-+/* -1 = init not run yet, 0 = unconfigured, 1 = configured. */
-+static int configured = -1;
-+
-+static char config[MAX_CONFIG_LEN];
-+static struct kparam_string kps = {
-+ .string = config,
-+ .maxlen = MAX_CONFIG_LEN,
-+};
-+
-+static struct tty_driver *kgdb_tty_driver;
-+static int kgdb_tty_line;
-+
-+static int kgdboc_option_setup(char *opt)
-+{
-+ if (strlen(opt) > MAX_CONFIG_LEN) {
-+ printk(KERN_ERR "kgdboc: config string too long\n");
-+ return -ENOSPC;
-+ }
-+ strcpy(config, opt);
-+
-+ return 0;
-+}
-+
-+__setup("kgdboc=", kgdboc_option_setup);
-+
-+static int configure_kgdboc(void)
-+{
-+ struct tty_driver *p;
-+ int tty_line = 0;
-+ int err;
-+
-+ err = kgdboc_option_setup(config);
-+ if (err || !strlen(config) || isspace(config[0]))
-+ goto noconfig;
-+
-+ err = -ENODEV;
-+
-+ p = tty_find_polling_driver(config, &tty_line);
-+ if (!p)
-+ goto noconfig;
-+
-+ kgdb_tty_driver = p;
-+ kgdb_tty_line = tty_line;
-+
-+ err = kgdb_register_io_module(&kgdboc_io_ops);
-+ if (err)
-+ goto noconfig;
-+
-+ configured = 1;
-+
-+ return 0;
-+
-+noconfig:
-+ config[0] = 0;
-+ configured = 0;
-+
-+ return err;
-+}
-+
-+static int __init init_kgdboc(void)
-+{
-+ /* Already configured? */
-+ if (configured == 1)
-+ return 0;
-+
-+ return configure_kgdboc();
-+}
-+
-+static void cleanup_kgdboc(void)
-+{
-+ if (configured == 1)
-+ kgdb_unregister_io_module(&kgdboc_io_ops);
-+}
-+
-+static int kgdboc_get_char(void)
-+{
-+ return kgdb_tty_driver->poll_get_char(kgdb_tty_driver, kgdb_tty_line);
-+}
-+
-+static void kgdboc_put_char(u8 chr)
-+{
-+ kgdb_tty_driver->poll_put_char(kgdb_tty_driver, kgdb_tty_line, chr);
-+}
-+
-+static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp)
-+{
-+ int len = strlen(kmessage);
-+
-+ if (len >= MAX_CONFIG_LEN) {
-+ printk(KERN_ERR "kgdboc: config string too long\n");
-+ return -ENOSPC;
-+ }
-+
-+ /* Only copy in the string if the init function has not run yet */
-+ if (configured < 0) {
-+ strcpy(config, kmessage);
-+ return 0;
-+ }
-+
-+ if (kgdb_connected) {
-+ printk(KERN_ERR
-+ "kgdboc: Cannot reconfigure while KGDB is connected.\n");
-+
-+ return -EBUSY;
-+ }
-+
-+ strcpy(config, kmessage);
-+ /* Chop out \n char as a result of echo */
-+ if (config[len - 1] == '\n')
-+ config[len - 1] = '\0';
-+
-+ if (configured == 1)
-+ cleanup_kgdboc();
-+
-+ /* Go and configure with the new params. */
-+ return configure_kgdboc();
-+}
-+
-+static void kgdboc_pre_exp_handler(void)
-+{
-+ /* Increment the module count when the debugger is active */
-+ if (!kgdb_connected)
-+ try_module_get(THIS_MODULE);
-+}
-+
-+static void kgdboc_post_exp_handler(void)
-+{
-+ /* decrement the module count when the debugger detaches */
-+ if (!kgdb_connected)
-+ module_put(THIS_MODULE);
-+}
-+
-+static struct kgdb_io kgdboc_io_ops = {
-+ .name = "kgdboc",
-+ .read_char = kgdboc_get_char,
-+ .write_char = kgdboc_put_char,
-+ .pre_exception = kgdboc_pre_exp_handler,
-+ .post_exception = kgdboc_post_exp_handler,
-+};
-+
-+module_init(init_kgdboc);
-+module_exit(cleanup_kgdboc);
-+module_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644);
-+MODULE_PARM_DESC(kgdboc, "<serial_device>[,baud]");
-+MODULE_DESCRIPTION("KGDB Console TTY Driver");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
-index 99af084..ddd3aa5 100644
---- a/drivers/serial/mcfserial.c
-+++ b/drivers/serial/mcfserial.c
-@@ -40,7 +40,6 @@
- #include <asm/io.h>
- #include <asm/irq.h>
- #include <asm/system.h>
--#include <asm/semaphore.h>
- #include <asm/delay.h>
- #include <asm/coldfire.h>
- #include <asm/mcfsim.h>
-diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c
-index c0e50a4..25029c7 100644
---- a/drivers/serial/of_serial.c
-+++ b/drivers/serial/of_serial.c
-@@ -31,7 +31,8 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev,
- struct resource resource;
- struct device_node *np = ofdev->node;
- const unsigned int *clk, *spd;
-- int ret;
-+ const u32 *prop;
-+ int ret, prop_size;
+ count = write_packet(ep, req, max);
- 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,
+@@ -1390,7 +1390,7 @@ static int write_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+ is_last = 1;
+ }
- 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));
+- 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);
- 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
+@@ -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;
--#ifdef CONFIG_SERIAL_CORE_CONSOLE
-+#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
- /*
- * uart_console_write - write a console message to a serial port
- * @port: the port to write the message
-@@ -1827,7 +1827,7 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
- * options. The format of the string is <baud><parity><bits><flow>,
- * eg: 115200n8r
- */
--void __init
-+void
- uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow)
- {
- char *s = options;
-@@ -1842,6 +1842,7 @@ uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow)
- if (*s)
- *flow = *s;
- }
-+EXPORT_SYMBOL_GPL(uart_parse_options);
+- DEBUG_EP0("%s\n", __FUNCTION__);
++ DEBUG_EP0("%s\n", __func__);
- 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)
+ 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)
*/
--int __init
-+int
- uart_set_options(struct uart_port *port, struct console *co,
- int baud, int parity, int bits, int flow)
+ static void udc_set_address(struct lh7a40x_udc *dev, unsigned char address)
{
-@@ -1924,10 +1925,16 @@ uart_set_options(struct uart_port *port, struct console *co,
- port->mctrl |= TIOCM_DTR;
+- 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;
- 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;
+- DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
++ DEBUG_EP0("%s: %x\n", __func__, csr);
- return 0;
- }
-+EXPORT_SYMBOL_GPL(uart_set_options);
- #endif /* CONFIG_SERIAL_CORE_CONSOLE */
+ 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__);
- 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,
+ 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;
}
- }
-+#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
- };
+@@ -1585,17 +1585,17 @@ static int lh7a40x_ep0_in(struct lh7a40x_udc *dev, u32 csr)
- /**
-@@ -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)
+ 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);
}
- sci_out(port, SCFCR, fcr_val);
- }
--
- #elif defined(CONFIG_CPU_SH3)
- /* For SH7705, SH7706, SH7707, SH7709, SH7709A, SH7729 */
- static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
-@@ -384,6 +383,12 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
- sci_out(port, SCFCR, fcr_val);
- }
-+#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
-+static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
-+{
-+ /* Nothing to do here.. */
-+ sci_out(port, SCFCR, 0);
-+}
- #else
- /* For SH7750 */
- static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
-diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
-index 01a9dd7..fa8700a 100644
---- a/drivers/serial/sh-sci.h
-+++ b/drivers/serial/sh-sci.h
-@@ -1,20 +1,5 @@
--/* $Id: sh-sci.h,v 1.4 2004/02/19 16:43:56 lethal Exp $
-- *
-- * linux/drivers/serial/sh-sci.h
-- *
-- * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO)
-- * Copyright (C) 1999, 2000 Niibe Yutaka
-- * Copyright (C) 2000 Greg Banks
-- * Copyright (C) 2002, 2003 Paul Mundt
-- * Modified to support multiple serial ports. Stuart Menefy (May 2000).
-- * Modified to support SH7300(SH-Mobile) SCIF. Takashi Kusuda (Jun 2003).
-- * Modified to support H8/300 Series Yoshinori Sato (Feb 2004).
-- * Removed SH7300 support (Jul 2007).
-- * Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Aug 2007).
-- */
- #include <linux/serial_core.h>
- #include <asm/io.h>
--
- #include <asm/gpio.h>
+ if (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;
- #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;
+- 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);
}
-+#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)
+
+@@ -1970,7 +1970,7 @@ static const struct usb_gadget_ops lh7a40x_udc_ops = {
+
+ static void nop_release(struct device *dev)
{
-@@ -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,
- };
+- DEBUG("%s %s\n", __FUNCTION__, dev->bus_id);
++ DEBUG("%s %s\n", __func__, dev->bus_id);
+ }
-+static int uart_chip_count;
- static struct uart_sunzilog_port *sunzilog_port_table;
- static struct zilog_layout __iomem **sunzilog_chip_regs;
+ 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;
-@@ -1350,16 +1351,22 @@ static int zilog_irq = -1;
+- DEBUG("%s: %p\n", __FUNCTION__, pdev);
++ DEBUG("%s: %p\n", __func__, pdev);
- static int __devinit zs_probe(struct of_device *op, const struct of_device_id *match)
+ spin_lock_init(&dev->lock);
+ dev->dev = &pdev->dev;
+@@ -2098,7 +2098,7 @@ static int lh7a40x_udc_remove(struct platform_device *pdev)
{
-- 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;
+ struct lh7a40x_udc *dev = platform_get_drvdata(pdev);
-+ /* 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++;
- }
+- DEBUG("%s: %p\n", __FUNCTION__, pdev);
++ DEBUG("%s: %p\n", __func__, pdev);
- dev_set_drvdata(&op->dev, &up[0]);
+ if (dev->driver)
+ return -EBUSY;
+@@ -2131,7 +2131,7 @@ static struct platform_driver udc_driver = {
-- inst++;
--
- return 0;
+ 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);
}
-@@ -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;
+diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h
+index 17b792b..f118f00 100644
+--- a/drivers/usb/gadget/m66592-udc.h
++++ b/drivers/usb/gadget/m66592-udc.h
+@@ -485,11 +485,11 @@ struct m66592 {
+ struct m66592_ep *epaddr2ep[16];
-- num_keybms = 0;
- for_each_node_by_name(dp, "zs") {
- num_sunzilog++;
- if (of_find_property(dp, "keyboard", NULL))
- num_keybms++;
- }
+ struct usb_request *ep0_req; /* for internal request */
+- u16 ep0_data; /* for internal request */
++ __le16 ep0_data; /* for internal request */
++ u16 old_vbus;
-- uart_count = 0;
- if (num_sunzilog) {
-- int uart_count;
--
- err = sunzilog_alloc_tables(num_sunzilog);
- if (err)
- goto out;
+ struct timer_list timer;
-- uart_count = (num_sunzilog * 2) - (2 * num_keybms);
-+ uart_chip_count = num_sunzilog - num_keybms;
+- u16 old_vbus;
+ int scount;
-- err = sunserial_register_minors(&sunzilog_reg, uart_count);
-+ err = sunserial_register_minors(&sunzilog_reg,
-+ uart_chip_count * 2);
- if (err)
- goto out_free_tables;
+ 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);
}
-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;
+ }
+-#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..881d74c 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;
}
-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.
+@@ -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;
+ }
-+# 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
+ 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;
+ }
- If unsure, say N
+@@ -249,7 +249,7 @@ static int omap_ep_disable(struct usb_ep *_ep)
+ unsigned long flags;
-+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
+ 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;
+ }
- # 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
+@@ -1265,8 +1265,6 @@ static int can_pullup(struct omap_udc *udc)
- # 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);
+ 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;
+@@ -2506,6 +2504,7 @@ static int proc_udc_open(struct inode *inode, struct file *file)
}
--void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state)
-+void ssb_chipco_suspend(struct ssb_chipcommon *cc)
+ static const struct file_operations proc_ops = {
++ .owner = THIS_MODULE,
+ .open = proc_udc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+@@ -2514,11 +2513,7 @@ static const struct file_operations proc_ops = {
+
+ static void create_proc_file(void)
{
- 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);
+- struct proc_dir_entry *pde;
+-
+- pde = create_proc_entry (proc_filename, 0, NULL);
+- if (pde)
+- pde->proc_fops = &proc_ops;
++ proc_create(proc_filename, 0, NULL, &proc_ops);
}
-+void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value)
-+{
-+ chipco_write32_masked(cc, SSB_CHIPCO_IRQMASK, mask, value);
-+}
-+
-+u32 ssb_chipco_irq_status(struct ssb_chipcommon *cc, u32 mask)
-+{
-+ return chipco_read32(cc, SSB_CHIPCO_IRQSTAT) & mask;
-+}
-+
- u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask)
- {
- return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask;
-diff --git a/drivers/ssb/driver_gige.c b/drivers/ssb/driver_gige.c
-new file mode 100644
-index 0000000..172f904
---- /dev/null
-+++ b/drivers/ssb/driver_gige.c
-@@ -0,0 +1,294 @@
-+/*
-+ * Sonics Silicon Backplane
-+ * Broadcom Gigabit Ethernet core driver
-+ *
-+ * Copyright 2008, Broadcom Corporation
-+ * Copyright 2008, Michael Buesch <mb at bu3sch.de>
-+ *
-+ * Licensed under the GNU/GPL. See COPYING for details.
-+ */
-+
-+#include <linux/ssb/ssb.h>
-+#include <linux/ssb/ssb_driver_gige.h>
-+#include <linux/pci.h>
-+#include <linux/pci_regs.h>
-+
-+
-+/*
-+MODULE_DESCRIPTION("SSB Broadcom Gigabit Ethernet driver");
-+MODULE_AUTHOR("Michael Buesch");
-+MODULE_LICENSE("GPL");
-+*/
-+
-+static const struct ssb_device_id ssb_gige_tbl[] = {
-+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_ETHERNET_GBIT, SSB_ANY_REV),
-+ SSB_DEVTABLE_END
-+};
-+/* MODULE_DEVICE_TABLE(ssb, ssb_gige_tbl); */
-+
-+
-+static inline u8 gige_read8(struct ssb_gige *dev, u16 offset)
-+{
-+ return ssb_read8(dev->dev, offset);
-+}
-+
-+static inline u16 gige_read16(struct ssb_gige *dev, u16 offset)
-+{
-+ return ssb_read16(dev->dev, offset);
-+}
-+
-+static inline u32 gige_read32(struct ssb_gige *dev, u16 offset)
-+{
-+ return ssb_read32(dev->dev, offset);
-+}
-+
-+static inline void gige_write8(struct ssb_gige *dev,
-+ u16 offset, u8 value)
-+{
-+ ssb_write8(dev->dev, offset, value);
-+}
-+
-+static inline void gige_write16(struct ssb_gige *dev,
-+ u16 offset, u16 value)
-+{
-+ ssb_write16(dev->dev, offset, value);
-+}
-+
-+static inline void gige_write32(struct ssb_gige *dev,
-+ u16 offset, u32 value)
-+{
-+ ssb_write32(dev->dev, offset, value);
-+}
-+
-+static inline
-+u8 gige_pcicfg_read8(struct ssb_gige *dev, unsigned int offset)
-+{
-+ BUG_ON(offset >= 256);
-+ return gige_read8(dev, SSB_GIGE_PCICFG + offset);
-+}
-+
-+static inline
-+u16 gige_pcicfg_read16(struct ssb_gige *dev, unsigned int offset)
-+{
-+ BUG_ON(offset >= 256);
-+ return gige_read16(dev, SSB_GIGE_PCICFG + offset);
-+}
-+
-+static inline
-+u32 gige_pcicfg_read32(struct ssb_gige *dev, unsigned int offset)
-+{
-+ BUG_ON(offset >= 256);
-+ return gige_read32(dev, SSB_GIGE_PCICFG + offset);
-+}
-+
-+static inline
-+void gige_pcicfg_write8(struct ssb_gige *dev,
-+ unsigned int offset, u8 value)
-+{
-+ BUG_ON(offset >= 256);
-+ gige_write8(dev, SSB_GIGE_PCICFG + offset, value);
-+}
-+
-+static inline
-+void gige_pcicfg_write16(struct ssb_gige *dev,
-+ unsigned int offset, u16 value)
-+{
-+ BUG_ON(offset >= 256);
-+ gige_write16(dev, SSB_GIGE_PCICFG + offset, value);
-+}
-+
-+static inline
-+void gige_pcicfg_write32(struct ssb_gige *dev,
-+ unsigned int offset, u32 value)
-+{
-+ BUG_ON(offset >= 256);
-+ gige_write32(dev, SSB_GIGE_PCICFG + offset, value);
-+}
-+
-+static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn,
-+ int reg, int size, u32 *val)
-+{
-+ struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
-+ unsigned long flags;
-+
-+ if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0))
-+ return PCIBIOS_DEVICE_NOT_FOUND;
-+ if (reg >= 256)
-+ return PCIBIOS_DEVICE_NOT_FOUND;
-+
-+ spin_lock_irqsave(&dev->lock, flags);
-+ switch (size) {
-+ case 1:
-+ *val = gige_pcicfg_read8(dev, reg);
-+ break;
-+ case 2:
-+ *val = gige_pcicfg_read16(dev, reg);
-+ break;
-+ case 4:
-+ *val = gige_pcicfg_read32(dev, reg);
-+ break;
-+ default:
-+ WARN_ON(1);
-+ }
-+ spin_unlock_irqrestore(&dev->lock, flags);
-+
-+ return PCIBIOS_SUCCESSFUL;
-+}
-+
-+static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn,
-+ int reg, int size, u32 val)
-+{
-+ struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
-+ unsigned long flags;
-+
-+ if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0))
-+ return PCIBIOS_DEVICE_NOT_FOUND;
-+ if (reg >= 256)
-+ return PCIBIOS_DEVICE_NOT_FOUND;
-+
-+ spin_lock_irqsave(&dev->lock, flags);
-+ switch (size) {
-+ case 1:
-+ gige_pcicfg_write8(dev, reg, val);
-+ break;
-+ case 2:
-+ gige_pcicfg_write16(dev, reg, val);
-+ break;
-+ case 4:
-+ gige_pcicfg_write32(dev, reg, val);
-+ break;
-+ default:
-+ WARN_ON(1);
-+ }
-+ spin_unlock_irqrestore(&dev->lock, flags);
-+
-+ return PCIBIOS_SUCCESSFUL;
-+}
-+
-+static int ssb_gige_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
-+{
-+ struct ssb_gige *dev;
-+ u32 base, tmslow, tmshigh;
-+
-+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-+ if (!dev)
-+ return -ENOMEM;
-+ dev->dev = sdev;
-+
-+ spin_lock_init(&dev->lock);
-+ dev->pci_controller.pci_ops = &dev->pci_ops;
-+ dev->pci_controller.io_resource = &dev->io_resource;
-+ dev->pci_controller.mem_resource = &dev->mem_resource;
-+ dev->pci_controller.io_map_base = 0x800;
-+ dev->pci_ops.read = ssb_gige_pci_read_config;
-+ dev->pci_ops.write = ssb_gige_pci_write_config;
-+
-+ dev->io_resource.name = SSB_GIGE_IO_RES_NAME;
-+ dev->io_resource.start = 0x800;
-+ dev->io_resource.end = 0x8FF;
-+ dev->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED;
-+
-+ if (!ssb_device_is_enabled(sdev))
-+ ssb_device_enable(sdev, 0);
-+
-+ /* Setup BAR0. This is a 64k MMIO region. */
-+ base = ssb_admatch_base(ssb_read32(sdev, SSB_ADMATCH1));
-+ gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_0, base);
-+ gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_1, 0);
-+
-+ dev->mem_resource.name = SSB_GIGE_MEM_RES_NAME;
-+ dev->mem_resource.start = base;
-+ dev->mem_resource.end = base + 0x10000 - 1;
-+ dev->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
-+
-+ /* Enable the memory region. */
-+ gige_pcicfg_write16(dev, PCI_COMMAND,
-+ gige_pcicfg_read16(dev, PCI_COMMAND)
-+ | PCI_COMMAND_MEMORY);
-+
-+ /* Write flushing is controlled by the Flush Status Control register.
-+ * We want to flush every register write with a timeout and we want
-+ * to disable the IRQ mask while flushing to avoid concurrency.
-+ * Note that automatic write flushing does _not_ work from
-+ * an IRQ handler. The driver must flush manually by reading a register.
-+ */
-+ gige_write32(dev, SSB_GIGE_SHIM_FLUSHSTAT, 0x00000068);
-+
-+ /* Check if we have an RGMII or GMII PHY-bus.
-+ * On RGMII do not bypass the DLLs */
-+ tmslow = ssb_read32(sdev, SSB_TMSLOW);
-+ tmshigh = ssb_read32(sdev, SSB_TMSHIGH);
-+ if (tmshigh & SSB_GIGE_TMSHIGH_RGMII) {
-+ tmslow &= ~SSB_GIGE_TMSLOW_TXBYPASS;
-+ tmslow &= ~SSB_GIGE_TMSLOW_RXBYPASS;
-+ dev->has_rgmii = 1;
-+ } else {
-+ tmslow |= SSB_GIGE_TMSLOW_TXBYPASS;
-+ tmslow |= SSB_GIGE_TMSLOW_RXBYPASS;
-+ dev->has_rgmii = 0;
-+ }
-+ tmslow |= SSB_GIGE_TMSLOW_DLLEN;
-+ ssb_write32(sdev, SSB_TMSLOW, tmslow);
-+
-+ ssb_set_drvdata(sdev, dev);
-+ register_pci_controller(&dev->pci_controller);
-+
-+ return 0;
-+}
-+
-+bool pdev_is_ssb_gige_core(struct pci_dev *pdev)
-+{
-+ if (!pdev->resource[0].name)
-+ return 0;
-+ return (strcmp(pdev->resource[0].name, SSB_GIGE_MEM_RES_NAME) == 0);
-+}
-+EXPORT_SYMBOL(pdev_is_ssb_gige_core);
+ static void remove_proc_file(void)
+@@ -3061,8 +3056,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;
+ }
+
-+int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
-+ struct pci_dev *pdev)
++ 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 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;
++ struct usb_request *req;
+
-+ /* Fixup interrupt lines. */
-+ pdev->irq = ssb_mips_irq(sdev) + 2;
-+ pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, pdev->irq);
++ while (likely(!list_empty(&dev->rx_reqs))) {
++ int error;
+
-+ return 0;
-+}
++ req = container_of(dev->rx_reqs.next,
++ struct usb_request, list);
++ list_del_init(&req->list);
+
-+int ssb_gige_map_irq(struct ssb_device *sdev,
-+ const struct pci_dev *pdev)
-+{
-+ struct ssb_gige *dev = ssb_get_drvdata(sdev);
++ /* 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;
+
-+ if (pdev->bus->ops != &dev->pci_ops) {
-+ /* The PCI device is not on this SSB GigE bridge device. */
-+ return -ENODEV;
++ 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);
++ }
+ }
-+
-+ 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 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;
--static u32 ssb_pcicore_pcibus_iobase = 0x100;
--static u32 ssb_pcicore_pcibus_membase = SSB_PCI_DMA;
+- while (likely(!list_empty(&dev->rx_reqs))) {
+- int error;
-
--int pcibios_plat_dev_init(struct pci_dev *d)
--{
-- struct resource *res;
-- int pos, size;
-- u32 *base;
+- req = container_of(dev->rx_reqs.next,
+- struct usb_request, list);
+- list_del_init(&req->list);
-
-- ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
-- pci_name(d));
+- /* 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;
-
-- /* 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)
+- 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);
+- }
- }
-- /* 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;
--}
++ setup_rx_reqs(dev);
- 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,
- };
+ 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)
-+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;
-+}
+ 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);
+
- 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;
+ poll_wait(fd, &dev->rx_wait, wait);
+ poll_wait(fd, &dev->tx_wait, wait);
- 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);
- }
+@@ -798,7 +818,8 @@ printer_poll(struct file *fd, poll_table *wait)
+ if (likely(!list_empty(&dev->tx_reqs)))
+ status |= POLLOUT | POLLWRNORM;
-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 @@
+- if (likely(!list_empty(&dev->rx_buffers)))
++ if (likely(dev->current_rx_bytes) ||
++ likely(!list_empty(&dev->rx_buffers)))
+ status |= POLLIN | POLLRDNORM;
- #include <linux/ssb/ssb.h>
- #include <linux/ssb/ssb_embedded.h>
-+#include <linux/ssb/ssb_driver_pci.h>
-+#include <linux/ssb/ssb_driver_gige.h>
-+#include <linux/pci.h>
+ spin_unlock_irqrestore(&dev->lock, flags);
+@@ -894,7 +915,7 @@ static void printer_reset_interface(struct printer_dev *dev)
+ if (dev->interface < 0)
+ return;
- #include "ssb_private.h"
+- DBG(dev, "%s\n", __FUNCTION__);
++ DBG(dev, "%s\n", __func__);
-@@ -130,3 +133,90 @@ u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value)
- return res;
- }
- EXPORT_SYMBOL(ssb_gpio_polarity);
-+
-+#ifdef CONFIG_SSB_DRIVER_GIGE
-+static int gige_pci_init_callback(struct ssb_bus *bus, unsigned long data)
-+{
-+ struct pci_dev *pdev = (struct pci_dev *)data;
-+ struct ssb_device *dev;
-+ unsigned int i;
-+ int res;
-+
-+ for (i = 0; i < bus->nr_devices; i++) {
-+ dev = &(bus->devices[i]);
-+ if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
-+ continue;
-+ if (!dev->dev ||
-+ !dev->dev->driver ||
-+ !device_is_registered(dev->dev))
-+ continue;
-+ res = ssb_gige_pcibios_plat_dev_init(dev, pdev);
-+ if (res >= 0)
-+ return res;
-+ }
-+
-+ return -ENODEV;
-+}
-+#endif /* CONFIG_SSB_DRIVER_GIGE */
-+
-+int ssb_pcibios_plat_dev_init(struct pci_dev *dev)
-+{
-+ int err;
-+
-+ err = ssb_pcicore_plat_dev_init(dev);
-+ if (!err)
-+ return 0;
-+#ifdef CONFIG_SSB_DRIVER_GIGE
-+ err = ssb_for_each_bus_call((unsigned long)dev, gige_pci_init_callback);
-+ if (err >= 0)
-+ return err;
-+#endif
-+ /* This is not a PCI device on any SSB device. */
-+
-+ return -ENODEV;
-+}
-+
-+#ifdef CONFIG_SSB_DRIVER_GIGE
-+static int gige_map_irq_callback(struct ssb_bus *bus, unsigned long data)
-+{
-+ const struct pci_dev *pdev = (const struct pci_dev *)data;
-+ struct ssb_device *dev;
-+ unsigned int i;
-+ int res;
-+
-+ for (i = 0; i < bus->nr_devices; i++) {
-+ dev = &(bus->devices[i]);
-+ if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
-+ continue;
-+ if (!dev->dev ||
-+ !dev->dev->driver ||
-+ !device_is_registered(dev->dev))
-+ continue;
-+ res = ssb_gige_map_irq(dev, pdev);
-+ if (res >= 0)
-+ return res;
-+ }
-+
-+ return -ENODEV;
-+}
-+#endif /* CONFIG_SSB_DRIVER_GIGE */
-+
-+int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-+{
-+ int res;
-+
-+ /* Check if this PCI device is a device on a SSB bus or device
-+ * and return the IRQ number for it. */
-+
-+ res = ssb_pcicore_pcibios_map_irq(dev, slot, pin);
-+ if (res >= 0)
-+ return res;
-+#ifdef CONFIG_SSB_DRIVER_GIGE
-+ res = ssb_for_each_bus_call((unsigned long)dev, gige_map_irq_callback);
-+ if (res >= 0)
-+ return res;
-+#endif
-+ /* This is not a PCI device on any SSB device. */
-+
-+ return -ENODEV;
-+}
-diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
-index 8003a9e..7cf8851 100644
---- a/drivers/ssb/main.c
-+++ b/drivers/ssb/main.c
-@@ -14,6 +14,7 @@
- #include <linux/io.h>
- #include <linux/ssb/ssb.h>
- #include <linux/ssb/ssb_regs.h>
-+#include <linux/ssb/ssb_driver_gige.h>
- #include <linux/dma-mapping.h>
- #include <linux/pci.h>
+ 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");
-@@ -68,6 +69,44 @@ found:
++ wake_up_interruptible(&dev->rx_wait);
+ wake_up_interruptible(&dev->tx_wait);
+ wake_up_interruptible(&dev->tx_flush_wait);
}
- #endif /* CONFIG_SSB_PCIHOST */
+@@ -1262,7 +1284,7 @@ printer_disconnect(struct usb_gadget *gadget)
+ struct printer_dev *dev = get_gadget_data(gadget);
+ unsigned long flags;
-+#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);
- }
+- DBG(dev, "%s\n", __FUNCTION__);
++ DBG(dev, "%s\n", __func__);
--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;
+ spin_lock_irqsave(&dev->lock, flags);
-- 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;
- }
+@@ -1278,7 +1300,7 @@ printer_unbind(struct usb_gadget *gadget)
+ struct usb_request *req;
--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
+- DBG(dev, "%s\n", __FUNCTION__);
++ DBG(dev, "%s\n", __func__);
-- 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;
+ /* 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;
}
-+ ssb_chipco_resume(&bus->chipco);
-+ ssb_bus_may_powerdown(bus);
--out:
-- return err;
-+ return 0;
- }
-+EXPORT_SYMBOL(ssb_bus_resume);
+@@ -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;
+ }
--#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)
+@@ -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;
+ }
- return 0;
- }
--#endif /* CONFIG_SSB_PCIHOST */
-+#endif /* CONFIG_SSB_SPROM */
+ 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;
+ }
- 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();
+@@ -283,7 +283,7 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep)
-- /* ssb_pcmcia_exit(bus); */
-+ ssb_pcmcia_exit(bus);
- ssb_pci_exit(bus);
- ssb_iounmap(bus);
- }
-@@ -508,6 +534,14 @@ error:
- return err;
+ 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 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);
- }
+ 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;
+ }
-+#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);
- }
+ 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;
+ }
-+#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
- };
+ 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;
+ }
- 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;
+@@ -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;
}
- 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;
+ 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;
}
-@@ -1175,6 +1328,7 @@ fs_initcall(ssb_modinit);
+ /* pxa can't report unclaimed bytes from IN fifos */
+@@ -878,7 +878,7 @@ static void pxa2xx_ep_fifo_flush(struct usb_ep *_ep)
- 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;
- }
+ 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;
+ }
--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;
- }
+@@ -1813,7 +1813,7 @@ pxa2xx_udc_irq(int irq, void *_dev)
--static void sprom_do_read(struct ssb_bus *bus, u16 *sprom)
-+static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
+ static void nop_release (struct device *dev)
{
- int i;
-
- for (i = 0; i < bus->sprom_size; i++)
- sprom[i] = ioread16(bus->mmio + SSB_SPROM_BASE + (i * 2));
-+
-+ return 0;
+- DMSG("%s %s\n", __FUNCTION__, dev->bus_id);
++ DMSG("%s %s\n", __func__, dev->bus_id);
}
- 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;
+ /* 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..d0677f5 100644
+--- a/drivers/usb/gadget/rndis.c
++++ b/drivers/usb/gadget/rndis.c
+@@ -183,14 +183,10 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ DBG("query OID %08x value, len %d:\n", OID, buf_len);
+ for (i = 0; i < buf_len; i += 16) {
+ DBG("%03d: %08x %08x %08x %08x\n", i,
+- le32_to_cpu(get_unaligned((__le32 *)
+- &buf[i])),
+- le32_to_cpu(get_unaligned((__le32 *)
+- &buf[i + 4])),
+- le32_to_cpu(get_unaligned((__le32 *)
+- &buf[i + 8])),
+- le32_to_cpu(get_unaligned((__le32 *)
+- &buf[i + 12])));
++ get_unaligned_le32(&buf[i]),
++ get_unaligned_le32(&buf[i + 4]),
++ get_unaligned_le32(&buf[i + 8]),
++ get_unaligned_le32(&buf[i + 12]));
+ }
}
-+ 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 */
+@@ -204,7 +200,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
-+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);
- }
+ /* 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 +210,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
-+#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);
- }
+ /* 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 +223,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
-+#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
- };
+ /* 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 +238,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 +249,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 +261,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 +271,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 +281,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 +289,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 +297,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 +305,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 +320,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 +337,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 +349,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 +362,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 +375,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 +386,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 +396,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 +406,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 +426,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 +442,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 +451,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 +460,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 +469,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 +478,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 +499,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 +508,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 +517,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 +526,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 +535,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 +545,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 +557,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 +569,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 +577,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;
--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;
+ 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;
- 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;
+ /* ieee802.3 statistics OIDs (table 4-4) */
-- /* 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);
- }
+ /* 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 +601,51 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
- 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;
+ /* 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;
- 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;
+ /* 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;
-- /* 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);
- }
+ #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;
- static DEVICE_ATTR(ssb_sprom, 0600,
-@@ -780,7 +790,7 @@ int ssb_pci_init(struct ssb_bus *bus)
- return 0;
+ 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;
- 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)
+ 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;
- static int ssb_pcihost_resume(struct pci_dev *dev)
- {
-+ struct ssb_bus *ssb = pci_get_drvdata(dev);
- int err;
+ 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;
- 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;
+ 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;
- return 0;
- }
-diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
-index 46816cd..24c2a46 100644
---- a/drivers/ssb/pcmcia.c
-+++ b/drivers/ssb/pcmcia.c
-@@ -3,7 +3,7 @@
- * PCMCIA-Hostbus related functions
- *
- * Copyright 2006 Johannes Berg <johannes at sipsolutions.net>
-- * Copyright 2007 Michael Buesch <mb at bu3sch.de>
-+ * Copyright 2007-2008 Michael Buesch <mb at bu3sch.de>
- *
- * Licensed under the GNU/GPL. See COPYING for details.
- */
-@@ -11,6 +11,7 @@
- #include <linux/ssb/ssb.h>
- #include <linux/delay.h>
- #include <linux/io.h>
-+#include <linux/etherdevice.h>
+ 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;
- #include <pcmcia/cs_types.h>
- #include <pcmcia/cs.h>
-@@ -26,59 +27,127 @@
- #define SSB_VERBOSE_PCMCIACORESWITCH_DEBUG 0
+ 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 +653,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,8 +661,8 @@ 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__,
+- le32_to_cpu(get_unaligned((__le32 *)buf)) - 1);
++ DBG("%s: OID_PNP_QUERY_POWER D%d\n", __func__,
++ 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 +673,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
-+/* 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;
+ default:
+ pr_warning("%s: query unknown OID 0x%08X\n",
+- __FUNCTION__, OID);
++ __func__, OID);
+ }
+ if (retval < 0)
+ length = 0;
+@@ -705,14 +701,10 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
+ DBG("set OID %08x value, len %d:\n", OID, buf_len);
+ for (i = 0; i < buf_len; i += 16) {
+ DBG("%03d: %08x %08x %08x %08x\n", i,
+- le32_to_cpu(get_unaligned((__le32 *)
+- &buf[i])),
+- le32_to_cpu(get_unaligned((__le32 *)
+- &buf[i + 4])),
+- le32_to_cpu(get_unaligned((__le32 *)
+- &buf[i + 8])),
+- le32_to_cpu(get_unaligned((__le32 *)
+- &buf[i + 12])));
++ get_unaligned_le32(&buf[i]),
++ get_unaligned_le32(&buf[i + 4]),
++ get_unaligned_le32(&buf[i + 8]),
++ get_unaligned_le32(&buf[i + 12]));
+ }
+ }
- 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;
+@@ -726,10 +718,9 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
+ * PROMISCUOUS, DIRECTED,
+ * MULTICAST, ALL_MULTICAST, BROADCAST
+ */
+- *params->filter = (u16) le32_to_cpu(get_unaligned(
+- (__le32 *)buf));
++ *params->filter = (u16)get_unaligned_le32(buf);
+ DBG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
+- __FUNCTION__, *params->filter);
++ __func__, *params->filter);
- read_addr = 0;
+ /* this call has a significant side effect: it's
+ * what makes the packet flow start and stop, like
+@@ -753,7 +744,7 @@ update_linkstate:
-- 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;
+ 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 +753,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;
+@@ -777,8 +768,8 @@ update_linkstate:
+ * resuming, Windows forces a reset, and then SET_POWER D0.
+ * 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);
++ i = get_unaligned_le32(buf);
++ DBG("%s: OID_PNP_SET_POWER D%d\n", __func__, i - 1);
+ switch (i) {
+ case NdisDeviceStateD0:
+ *params->filter = params->saved_filter;
+@@ -802,7 +793,7 @@ update_linkstate:
- cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE;
- if (cur_core == coreidx)
- break;
+ default:
+ pr_warning("%s: set unknown OID 0x%08X, size %d\n",
+- __FUNCTION__, OID, buf_len);
++ __func__, OID, buf_len);
+ }
-+ 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;
- }
+ return retval;
+@@ -855,7 +846,7 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
+ rndis_query_cmplt_type *resp;
+ rndis_resp_t *r;
- 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;
+- // 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;
- 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;
+ /*
+@@ -908,9 +899,9 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
+ BufOffset = le32_to_cpu (buf->InformationBufferOffset);
-+ 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;
- }
+ #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__);
- 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;
- }
+ for (i = 0; i < BufLength; i++) {
+ DBG("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
+@@ -1064,8 +1055,8 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
+ return -ENOMEM;
-+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));
- }
+ tmp = (__le32 *) buf;
+- MsgType = le32_to_cpu(get_unaligned(tmp++));
+- MsgLength = le32_to_cpu(get_unaligned(tmp++));
++ MsgType = get_unaligned_le32(tmp++);
++ MsgLength = get_unaligned_le32(tmp++);
+
+ if (configNr >= RNDIS_MAX_CONFIGS)
+ return -ENOTSUPP;
+@@ -1080,14 +1071,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);
-+#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);
- }
+ 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 +1096,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
-+#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
- };
+ case REMOTE_NDIS_RESET_MSG:
+ DBG("%s: REMOTE_NDIS_RESET_MSG\n",
+- __FUNCTION__ );
++ __func__ );
+ return rndis_reset_response (configNr,
+ (rndis_reset_msg_type *) buf);
--#include <linux/etherdevice.h>
-+static int ssb_pcmcia_sprom_command(struct ssb_bus *bus, u8 command)
-+{
-+ unsigned int i;
-+ int err;
-+ u8 value;
-+
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROMCTL, command);
-+ if (err)
-+ return err;
-+ for (i = 0; i < 1000; i++) {
-+ err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROMCTL, &value);
-+ if (err)
-+ return err;
-+ if (value & SSB_PCMCIA_SPROMCTL_DONE)
-+ return 0;
-+ udelay(10);
-+ }
-+
-+ return -ETIMEDOUT;
-+}
-+
-+/* offset is the 16bit word offset */
-+static int ssb_pcmcia_sprom_read(struct ssb_bus *bus, u16 offset, u16 *value)
-+{
-+ int err;
-+ u8 lo, hi;
-+
-+ offset *= 2; /* Make byte offset */
-+
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
-+ (offset & 0x00FF));
-+ if (err)
-+ return err;
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
-+ (offset & 0xFF00) >> 8);
-+ if (err)
-+ return err;
-+ err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_READ);
-+ if (err)
-+ return err;
-+ err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATALO, &lo);
-+ if (err)
-+ return err;
-+ err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATAHI, &hi);
-+ if (err)
-+ return err;
-+ *value = (lo | (((u16)hi) << 8));
-+
-+ return 0;
-+}
-+
-+/* offset is the 16bit word offset */
-+static int ssb_pcmcia_sprom_write(struct ssb_bus *bus, u16 offset, u16 value)
-+{
-+ int err;
-+
-+ offset *= 2; /* Make byte offset */
-+
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
-+ (offset & 0x00FF));
-+ if (err)
-+ return err;
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
-+ (offset & 0xFF00) >> 8);
-+ if (err)
-+ return err;
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATALO,
-+ (value & 0x00FF));
-+ if (err)
-+ return err;
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATAHI,
-+ (value & 0xFF00) >> 8);
-+ if (err)
-+ return err;
-+ err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITE);
-+ if (err)
-+ return err;
-+ msleep(20);
-+
-+ return 0;
-+}
-+
-+/* Read the SPROM image. bufsize is in 16bit words. */
-+static int ssb_pcmcia_sprom_read_all(struct ssb_bus *bus, u16 *sprom)
-+{
-+ int err, i;
-+
-+ for (i = 0; i < SSB_PCMCIA_SPROM_SIZE; i++) {
-+ err = ssb_pcmcia_sprom_read(bus, i, &sprom[i]);
-+ if (err)
-+ return err;
-+ }
-+
-+ return 0;
-+}
-+
-+/* Write the SPROM image. size is in 16bit words. */
-+static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom)
-+{
-+ int i, err;
-+ bool failed = 0;
-+ size_t size = SSB_PCMCIA_SPROM_SIZE;
-+
-+ ssb_printk(KERN_NOTICE PFX
-+ "Writing SPROM. Do NOT turn off the power! "
-+ "Please stand by...\n");
-+ err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN);
-+ if (err) {
-+ ssb_printk(KERN_NOTICE PFX
-+ "Could not enable SPROM write access.\n");
-+ return -EBUSY;
-+ }
-+ ssb_printk(KERN_NOTICE PFX "[ 0%%");
-+ msleep(500);
-+ for (i = 0; i < size; i++) {
-+ if (i == size / 4)
-+ ssb_printk("25%%");
-+ else if (i == size / 2)
-+ ssb_printk("50%%");
-+ else if (i == (size * 3) / 4)
-+ ssb_printk("75%%");
-+ else if (i % 2)
-+ ssb_printk(".");
-+ err = ssb_pcmcia_sprom_write(bus, i, sprom[i]);
-+ if (err) {
-+ ssb_printk("\n" KERN_NOTICE PFX
-+ "Failed to write to SPROM.\n");
-+ failed = 1;
-+ break;
-+ }
-+ }
-+ err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS);
-+ if (err) {
-+ ssb_printk("\n" KERN_NOTICE PFX
-+ "Could not disable SPROM write access.\n");
-+ failed = 1;
-+ }
-+ msleep(500);
-+ if (!failed) {
-+ ssb_printk("100%% ]\n");
-+ ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
-+ }
-+
-+ return failed ? -EBUSY : 0;
-+}
-+
-+static int ssb_pcmcia_sprom_check_crc(const u16 *sprom, size_t size)
-+{
-+ //TODO
-+ return 0;
-+}
-+
-+#define GOTO_ERROR_ON(condition, description) do { \
-+ if (unlikely(condition)) { \
-+ error_description = description; \
-+ goto error; \
-+ } \
-+ } while (0)
-+
- int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
- struct ssb_init_invariants *iv)
- {
-- //TODO
-- random_ether_addr(iv->sprom.il0mac);
-+ tuple_t tuple;
-+ int res;
-+ unsigned char buf[32];
-+ struct ssb_sprom *sprom = &iv->sprom;
-+ struct ssb_boardinfo *bi = &iv->boardinfo;
-+ const char *error_description;
-+
-+ memset(sprom, 0xFF, sizeof(*sprom));
-+ sprom->revision = 1;
-+ sprom->boardflags_lo = 0;
-+ sprom->boardflags_hi = 0;
-+
-+ /* First fetch the MAC address. */
-+ memset(&tuple, 0, sizeof(tuple));
-+ tuple.DesiredTuple = CISTPL_FUNCE;
-+ tuple.TupleData = buf;
-+ tuple.TupleDataMax = sizeof(buf);
-+ res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple);
-+ GOTO_ERROR_ON(res != CS_SUCCESS, "MAC first tpl");
-+ res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
-+ GOTO_ERROR_ON(res != CS_SUCCESS, "MAC first tpl data");
-+ while (1) {
-+ GOTO_ERROR_ON(tuple.TupleDataLen < 1, "MAC tpl < 1");
-+ if (tuple.TupleData[0] == CISTPL_FUNCE_LAN_NODE_ID)
-+ break;
-+ res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple);
-+ GOTO_ERROR_ON(res != CS_SUCCESS, "MAC next tpl");
-+ res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
-+ GOTO_ERROR_ON(res != CS_SUCCESS, "MAC next tpl data");
-+ }
-+ GOTO_ERROR_ON(tuple.TupleDataLen != ETH_ALEN + 2, "MAC tpl size");
-+ memcpy(sprom->il0mac, &tuple.TupleData[2], ETH_ALEN);
-+
-+ /* Fetch the vendor specific tuples. */
-+ memset(&tuple, 0, sizeof(tuple));
-+ tuple.DesiredTuple = SSB_PCMCIA_CIS;
-+ tuple.TupleData = buf;
-+ tuple.TupleDataMax = sizeof(buf);
-+ res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple);
-+ GOTO_ERROR_ON(res != CS_SUCCESS, "VEN first tpl");
-+ res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
-+ GOTO_ERROR_ON(res != CS_SUCCESS, "VEN first tpl data");
-+ while (1) {
-+ GOTO_ERROR_ON(tuple.TupleDataLen < 1, "VEN tpl < 1");
-+ switch (tuple.TupleData[0]) {
-+ case SSB_PCMCIA_CIS_ID:
-+ GOTO_ERROR_ON((tuple.TupleDataLen != 5) &&
-+ (tuple.TupleDataLen != 7),
-+ "id tpl size");
-+ bi->vendor = tuple.TupleData[1] |
-+ ((u16)tuple.TupleData[2] << 8);
-+ break;
-+ case SSB_PCMCIA_CIS_BOARDREV:
-+ GOTO_ERROR_ON(tuple.TupleDataLen != 2,
-+ "boardrev tpl size");
-+ sprom->board_rev = tuple.TupleData[1];
-+ break;
-+ case SSB_PCMCIA_CIS_PA:
-+ GOTO_ERROR_ON(tuple.TupleDataLen != 9,
-+ "pa tpl size");
-+ sprom->pa0b0 = tuple.TupleData[1] |
-+ ((u16)tuple.TupleData[2] << 8);
-+ sprom->pa0b1 = tuple.TupleData[3] |
-+ ((u16)tuple.TupleData[4] << 8);
-+ sprom->pa0b2 = tuple.TupleData[5] |
-+ ((u16)tuple.TupleData[6] << 8);
-+ sprom->itssi_a = tuple.TupleData[7];
-+ sprom->itssi_bg = tuple.TupleData[7];
-+ sprom->maxpwr_a = tuple.TupleData[8];
-+ sprom->maxpwr_bg = tuple.TupleData[8];
-+ break;
-+ case SSB_PCMCIA_CIS_OEMNAME:
-+ /* We ignore this. */
-+ break;
-+ case SSB_PCMCIA_CIS_CCODE:
-+ GOTO_ERROR_ON(tuple.TupleDataLen != 2,
-+ "ccode tpl size");
-+ sprom->country_code = tuple.TupleData[1];
-+ break;
-+ case SSB_PCMCIA_CIS_ANTENNA:
-+ GOTO_ERROR_ON(tuple.TupleDataLen != 2,
-+ "ant tpl size");
-+ sprom->ant_available_a = tuple.TupleData[1];
-+ sprom->ant_available_bg = tuple.TupleData[1];
-+ break;
-+ case SSB_PCMCIA_CIS_ANTGAIN:
-+ GOTO_ERROR_ON(tuple.TupleDataLen != 2,
-+ "antg tpl size");
-+ sprom->antenna_gain.ghz24.a0 = tuple.TupleData[1];
-+ sprom->antenna_gain.ghz24.a1 = tuple.TupleData[1];
-+ sprom->antenna_gain.ghz24.a2 = tuple.TupleData[1];
-+ sprom->antenna_gain.ghz24.a3 = tuple.TupleData[1];
-+ sprom->antenna_gain.ghz5.a0 = tuple.TupleData[1];
-+ sprom->antenna_gain.ghz5.a1 = tuple.TupleData[1];
-+ sprom->antenna_gain.ghz5.a2 = tuple.TupleData[1];
-+ sprom->antenna_gain.ghz5.a3 = tuple.TupleData[1];
-+ break;
-+ case SSB_PCMCIA_CIS_BFLAGS:
-+ GOTO_ERROR_ON(tuple.TupleDataLen != 3,
-+ "bfl tpl size");
-+ sprom->boardflags_lo = tuple.TupleData[1] |
-+ ((u16)tuple.TupleData[2] << 8);
-+ break;
-+ case SSB_PCMCIA_CIS_LEDS:
-+ GOTO_ERROR_ON(tuple.TupleDataLen != 5,
-+ "leds tpl size");
-+ sprom->gpio0 = tuple.TupleData[1];
-+ sprom->gpio1 = tuple.TupleData[2];
-+ sprom->gpio2 = tuple.TupleData[3];
-+ sprom->gpio3 = tuple.TupleData[4];
-+ break;
-+ }
-+ res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple);
-+ if (res == CS_NO_MORE_ITEMS)
-+ break;
-+ GOTO_ERROR_ON(res != CS_SUCCESS, "VEN next tpl");
-+ res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
-+ GOTO_ERROR_ON(res != CS_SUCCESS, "VEN next tpl data");
-+ }
-+
- return 0;
-+error:
-+ ssb_printk(KERN_ERR PFX
-+ "PCMCIA: Failed to fetch device invariants: %s\n",
-+ error_description);
-+ return -ENODEV;
- }
+@@ -1113,7 +1104,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 +1115,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 +1150,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 +1161,7 @@ int rndis_register (int (* rndis_control_ack) (struct net_device *))
--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)
+ void rndis_deregister (int configNr)
{
-- conf_reg_t reg;
- int err;
+- DBG("%s: \n", __FUNCTION__ );
++ DBG("%s: \n", __func__ );
- 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;
+ if (configNr >= RNDIS_MAX_CONFIGS) return;
+ rndis_per_dev_params [configNr].used = 0;
+@@ -1182,7 +1173,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;
-- /* 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;
+@@ -1195,7 +1186,7 @@ int rndis_set_param_dev (u8 configNr, struct net_device *dev,
- return 0;
- error:
-- return -ENODEV;
-+ ssb_printk(KERN_ERR PFX "Failed to initialize PCMCIA host device\n");
-+ return err;
- }
-diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c
-new file mode 100644
-index 0000000..3668edb
---- /dev/null
-+++ b/drivers/ssb/sprom.c
-@@ -0,0 +1,133 @@
-+/*
-+ * Sonics Silicon Backplane
-+ * Common SPROM support routines
-+ *
-+ * Copyright (C) 2005-2008 Michael Buesch <mb at bu3sch.de>
-+ * Copyright (C) 2005 Martin Langer <martin-langer at gmx.de>
-+ * Copyright (C) 2005 Stefano Brivio <st3 at riseup.net>
-+ * Copyright (C) 2005 Danny van Dyk <kugelfang at gentoo.org>
-+ * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi at waterwave.ch>
-+ *
-+ * Licensed under the GNU/GPL. See COPYING for details.
-+ */
-+
-+#include "ssb_private.h"
-+
-+
-+static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len,
-+ size_t sprom_size_words)
-+{
-+ int i, pos = 0;
-+
-+ for (i = 0; i < sprom_size_words; i++)
-+ pos += snprintf(buf + pos, buf_len - pos - 1,
-+ "%04X", swab16(sprom[i]) & 0xFFFF);
-+ pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
-+
-+ return pos + 1;
-+}
-+
-+static int hex2sprom(u16 *sprom, const char *dump, size_t len,
-+ size_t sprom_size_words)
-+{
-+ char tmp[5] = { 0 };
-+ int cnt = 0;
-+ unsigned long parsed;
-+
-+ if (len < sprom_size_words * 2)
-+ return -EINVAL;
-+
-+ while (cnt < sprom_size_words) {
-+ memcpy(tmp, dump, 4);
-+ dump += 4;
-+ parsed = simple_strtoul(tmp, NULL, 16);
-+ sprom[cnt++] = swab16((u16)parsed);
-+ }
-+
-+ return 0;
-+}
-+
-+/* Common sprom device-attribute show-handler */
-+ssize_t ssb_attr_sprom_show(struct ssb_bus *bus, char *buf,
-+ int (*sprom_read)(struct ssb_bus *bus, u16 *sprom))
-+{
-+ u16 *sprom;
-+ int err = -ENOMEM;
-+ ssize_t count = 0;
-+ size_t sprom_size_words = bus->sprom_size;
-+
-+ sprom = kcalloc(sprom_size_words, sizeof(u16), GFP_KERNEL);
-+ if (!sprom)
-+ goto out;
-+
-+ /* Use interruptible locking, as the SPROM write might
-+ * be holding the lock for several seconds. So allow userspace
-+ * to cancel operation. */
-+ err = -ERESTARTSYS;
-+ if (mutex_lock_interruptible(&bus->sprom_mutex))
-+ goto out_kfree;
-+ err = sprom_read(bus, sprom);
-+ mutex_unlock(&bus->sprom_mutex);
-+
-+ if (!err)
-+ count = sprom2hex(sprom, buf, PAGE_SIZE, sprom_size_words);
-+
-+out_kfree:
-+ kfree(sprom);
-+out:
-+ return err ? err : count;
-+}
-+
-+/* Common sprom device-attribute store-handler */
-+ssize_t ssb_attr_sprom_store(struct ssb_bus *bus,
-+ const char *buf, size_t count,
-+ int (*sprom_check_crc)(const u16 *sprom, size_t size),
-+ int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom))
-+{
-+ u16 *sprom;
-+ int res = 0, err = -ENOMEM;
-+ size_t sprom_size_words = bus->sprom_size;
-+
-+ sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
-+ if (!sprom)
-+ goto out;
-+ err = hex2sprom(sprom, buf, count, sprom_size_words);
-+ if (err) {
-+ err = -EINVAL;
-+ goto out_kfree;
-+ }
-+ err = sprom_check_crc(sprom, sprom_size_words);
-+ if (err) {
-+ err = -EINVAL;
-+ goto out_kfree;
-+ }
-+
-+ /* Use interruptible locking, as the SPROM write might
-+ * be holding the lock for several seconds. So allow userspace
-+ * to cancel operation. */
-+ err = -ERESTARTSYS;
-+ if (mutex_lock_interruptible(&bus->sprom_mutex))
-+ goto out_kfree;
-+ err = ssb_devices_freeze(bus);
-+ if (err == -EOPNOTSUPP) {
-+ ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. "
-+ "No suspend support. Is CONFIG_PM enabled?\n");
-+ goto out_unlock;
-+ }
-+ if (err) {
-+ ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
-+ goto out_unlock;
-+ }
-+ res = sprom_write(bus, sprom);
-+ err = ssb_devices_thaw(bus);
-+ if (err)
-+ ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
-+out_unlock:
-+ mutex_unlock(&bus->sprom_mutex);
-+out_kfree:
-+ kfree(sprom);
-+out:
-+ if (res)
-+ return res;
-+ return err ? err : count;
-+}
-diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h
-index 21eca2b..ebc32d8 100644
---- a/drivers/ssb/ssb_private.h
-+++ b/drivers/ssb/ssb_private.h
-@@ -81,6 +81,8 @@ extern int ssb_pcmcia_switch_segment(struct ssb_bus *bus,
- u8 seg);
- extern int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
- struct ssb_init_invariants *iv);
-+extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus);
-+extern void ssb_pcmcia_exit(struct ssb_bus *bus);
- extern int ssb_pcmcia_init(struct ssb_bus *bus);
- extern const struct ssb_bus_ops ssb_pcmcia_ops;
- #else /* CONFIG_SSB_PCMCIAHOST */
-@@ -99,6 +101,13 @@ static inline int ssb_pcmcia_switch_segment(struct ssb_bus *bus,
- {
- return 0;
- }
-+static inline int ssb_pcmcia_hardware_setup(struct ssb_bus *bus)
-+{
-+ return 0;
-+}
-+static inline void ssb_pcmcia_exit(struct ssb_bus *bus)
-+{
-+}
- static inline int ssb_pcmcia_init(struct ssb_bus *bus)
+ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
{
- return 0;
-@@ -113,11 +122,26 @@ extern int ssb_bus_scan(struct ssb_bus *bus,
- extern void ssb_iounmap(struct ssb_bus *ssb);
+- DBG("%s:\n", __FUNCTION__ );
++ DBG("%s:\n", __func__ );
+ if (!vendorDescr) return -1;
+ if (configNr >= RNDIS_MAX_CONFIGS) return -1;
+@@ -1207,7 +1198,7 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
-+/* 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);
-+
+ 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;
- /* 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
+ rndis_per_dev_params [configNr].medium = medium;
+@@ -1296,10 +1287,9 @@ int rndis_rm_hdr(struct sk_buff *skb)
+ tmp++;
- If you don't know what to do here, say N.
+ /* DataOffset, DataLength */
+- if (!skb_pull(skb, le32_to_cpu(get_unaligned(tmp++))
+- + 8 /* offset of DataOffset */))
++ if (!skb_pull(skb, get_unaligned_le32(tmp++) + 8))
+ return -EOVERFLOW;
+- skb_trim(skb, le32_to_cpu(get_unaligned(tmp++)));
++ skb_trim(skb, get_unaligned_le32(tmp++));
-+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.
+ return 0;
+ }
+@@ -1403,7 +1393,7 @@ static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
+ #endif /* CONFIG_USB_GADGET_DEBUG_FILES */
--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;
-+ }
+-int __devinit rndis_init (void)
++int __init rndis_init (void)
+ {
+ u8 i;
- listener->dev = idev;
- listener->event_count = atomic_read(&idev->event);
- filep->private_data = listener;
+@@ -1415,7 +1405,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..8d158e5 100644
+--- a/drivers/usb/gadget/serial.c
++++ b/drivers/usb/gadget/serial.c
+@@ -170,7 +170,7 @@ static int gs_open(struct tty_struct *tty, struct file *file);
+ static void gs_close(struct tty_struct *tty, struct file *file);
+ static int gs_write(struct tty_struct *tty,
+ const unsigned char *buf, int count);
+-static void gs_put_char(struct tty_struct *tty, unsigned char ch);
++static int gs_put_char(struct tty_struct *tty, unsigned char ch);
+ static void gs_flush_chars(struct tty_struct *tty);
+ static int gs_write_room(struct tty_struct *tty);
+ static int gs_chars_in_buffer(struct tty_struct *tty);
+@@ -883,14 +883,15 @@ exit:
+ /*
+ * gs_put_char
+ */
+-static void gs_put_char(struct tty_struct *tty, unsigned char ch)
++static int gs_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ unsigned long flags;
+ struct gs_port *port = tty->driver_data;
++ int ret = 0;
- 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 (port == NULL) {
+ pr_err("gs_put_char: NULL port pointer\n");
+- return;
++ return 0;
}
-- if (ret)
-- kfree(listener);
-+ return 0;
-+
-+err_infoopen:
-+
-+ kfree(listener);
-+err_alloc_listener:
-+
-+ module_put(idev->owner);
+ gs_debug("gs_put_char: (%d,%p) char=0x%x, called from %p\n",
+@@ -910,10 +911,11 @@ static void gs_put_char(struct tty_struct *tty, unsigned char ch)
+ goto exit;
+ }
- 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;
+- gs_buf_put(port->port_write_buf, &ch, 1);
++ ret = gs_buf_put(port->port_write_buf, &ch, 1);
-- 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;
+ exit:
+ spin_unlock_irqrestore(&port->port_lock, flags);
++ return ret;
+ }
- 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;
+ /*
+@@ -2163,8 +2165,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/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c
+index 878e428..4154be3 100644
+--- a/drivers/usb/gadget/usbstring.c
++++ b/drivers/usb/gadget/usbstring.c
+@@ -74,7 +74,7 @@ static int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len)
+ goto fail;
+ } else
+ uchar = c;
+- put_unaligned (cpu_to_le16 (uchar), cp++);
++ put_unaligned_le16(uchar, cp++);
+ count++;
+ len--;
}
+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.
-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 @@
+ 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.
- #include <asm/io.h>
++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;
--#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);
++ /* FIXME we only want one one probe() not two */
+ ret = usb_ehci_au1xxx_probe(&ehci_au1xxx_hc_driver, &hcd, pdev);
+ return ret;
}
-
--static struct pci_device_id hilscher_pci_ids[] = {
-+static struct pci_device_id hilscher_pci_ids[] __devinitdata = {
- {
- .vendor = PCI_VENDOR_ID_PLX,
- .device = PCI_DEVICE_ID_PLX_9030,
-diff --git a/drivers/uio/uio_smx.c b/drivers/uio/uio_smx.c
-new file mode 100644
-index 0000000..44054a6
---- /dev/null
-+++ b/drivers/uio/uio_smx.c
-@@ -0,0 +1,140 @@
-+/*
-+ * UIO SMX Cryptengine driver.
-+ *
-+ * (C) 2008 Nias Digital P/L <bn at niasdigital.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+
-+#include <linux/device.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/uio_driver.h>
-+#include <linux/io.h>
-+
-+#define DRV_NAME "smx-ce"
-+#define DRV_VERSION "0.03"
-+
-+#define SMX_CSR 0x00000000
-+#define SMX_EnD 0x00000001
-+#define SMX_RUN 0x00000002
-+#define SMX_DRDY 0x00000004
-+#define SMX_ERR 0x00000008
-+
-+static irqreturn_t smx_handler(int irq, struct uio_info *dev_info)
-+{
-+ void __iomem *csr = dev_info->mem[0].internal_addr + SMX_CSR;
-+
-+ u32 status = ioread32(csr);
-+
-+ if (!(status & SMX_DRDY))
-+ return IRQ_NONE;
-+
-+ /* Disable interrupt */
-+ iowrite32(status & ~SMX_DRDY, csr);
-+ return IRQ_HANDLED;
-+}
-+
-+static int __devinit smx_ce_probe(struct platform_device *dev)
-+{
-+
-+ int ret = -ENODEV;
-+ struct uio_info *info;
-+ struct resource *regs;
-+
-+ info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
-+ if (!info)
-+ return -ENOMEM;
-+
-+ regs = platform_get_resource(dev, IORESOURCE_MEM, 0);
-+ if (!regs) {
-+ dev_err(&dev->dev, "No memory resource specified\n");
-+ goto out_free;
-+ }
-+
-+ info->mem[0].addr = regs->start;
-+ if (!info->mem[0].addr) {
-+ dev_err(&dev->dev, "Invalid memory resource\n");
-+ goto out_free;
-+ }
-+
-+ info->mem[0].size = regs->end - regs->start + 1;
-+ info->mem[0].internal_addr = ioremap(regs->start, info->mem[0].size);
-+
-+ if (!info->mem[0].internal_addr) {
-+ dev_err(&dev->dev, "Can't remap memory address range\n");
-+ goto out_free;
-+ }
-+
-+ info->mem[0].memtype = UIO_MEM_PHYS;
-+
-+ info->name = "smx-ce";
-+ info->version = "0.03";
-+
-+ info->irq = platform_get_irq(dev, 0);
-+ if (info->irq < 0) {
-+ ret = info->irq;
-+ dev_err(&dev->dev, "No (or invalid) IRQ resource specified\n");
-+ goto out_unmap;
-+ }
-+
-+ info->irq_flags = IRQF_SHARED;
-+ info->handler = smx_handler;
-+
-+ platform_set_drvdata(dev, info);
-+
-+ ret = uio_register_device(&dev->dev, info);
-+
-+ if (ret)
-+ goto out_unmap;
-+
-+ return 0;
-+
-+out_unmap:
-+ iounmap(info->mem[0].internal_addr);
-+out_free:
-+ kfree(info);
-+
-+ return ret;
-+}
-+
-+static int __devexit smx_ce_remove(struct platform_device *dev)
-+{
-+ struct uio_info *info = platform_get_drvdata(dev);
-+
-+ uio_unregister_device(info);
-+ platform_set_drvdata(dev, NULL);
-+ iounmap(info->mem[0].internal_addr);
-+
-+ kfree(info);
-+
-+ return 0;
-+}
-+
-+static struct platform_driver smx_ce_driver = {
-+ .probe = smx_ce_probe,
-+ .remove = __devexit_p(smx_ce_remove),
-+ .driver = {
-+ .name = DRV_NAME,
-+ .owner = THIS_MODULE,
-+ },
-+};
-+
-+static int __init smx_ce_init_module(void)
-+{
-+ return platform_driver_register(&smx_ce_driver);
-+}
-+module_init(smx_ce_init_module);
-+
-+static void __exit smx_ce_exit_module(void)
-+{
-+ platform_driver_unregister(&smx_ce_driver);
-+}
-+module_exit(smx_ce_exit_module);
-+
-+MODULE_LICENSE("GPL v2");
-+MODULE_VERSION(DRV_VERSION);
-+MODULE_AUTHOR("Ben Nizette <bn at niasdigital.com>");
-diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
-index a51eeed..d470c72 100644
---- a/drivers/usb/atm/cxacru.c
-+++ b/drivers/usb/atm/cxacru.c
-@@ -444,7 +444,7 @@ CXACRU_ALL_FILES(INIT);
- /* the following three functions are stolen from drivers/usb/core/message.c */
- static void cxacru_blocking_completion(struct urb *urb)
+@@ -245,6 +246,7 @@ static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
{
-- 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)
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
- #define uea_enters(usb_dev) \
-- uea_vdbg(usb_dev, "entering %s\n", __FUNCTION__)
-+ uea_vdbg(usb_dev, "entering %s\n", __func__)
++ /* 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..0f82fdc 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 )
- #define uea_leaves(usb_dev) \
-- uea_vdbg(usb_dev, "leaving %s\n", __FUNCTION__)
-+ uea_vdbg(usb_dev, "leaving %s\n", __func__)
+-#ifdef EHCI_VERBOSE_DEBUG
++#ifdef VERBOSE_DEBUG
+ # define vdbg dbg
+ # define ehci_vdbg ehci_dbg
+ #else
+@@ -398,7 +398,7 @@ static void qh_lines (
+ unsigned size = *sizep;
+ char *next = *nextp;
+ char mark;
+- u32 list_end = EHCI_LIST_END(ehci);
++ __le32 list_end = EHCI_LIST_END(ehci);
- #define uea_err(usb_dev, format,args...) \
- dev_err(&(usb_dev)->dev ,"[UEAGLE-ATM] " format , ##args)
-diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
-index e717f5b..0722872 100644
---- a/drivers/usb/atm/usbatm.c
-+++ b/drivers/usb/atm/usbatm.c
-@@ -80,6 +80,7 @@
- #include <linux/stat.h>
- #include <linux/timer.h>
- #include <linux/wait.h>
-+#include <linux/kthread.h>
+ if (qh->hw_qtd_next == list_end) /* NEC does this */
+ mark = '@';
+@@ -670,7 +670,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
- #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;
+ spin_lock_irqsave (&ehci->lock, flags);
-- daemonize(instance->driver->driver_name);
- allow_signal(SIGTERM);
-- instance->thread_pid = current->pid;
--
- complete(&instance->thread_started);
+- 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
- 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);
+-/* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
- mutex_lock(&instance->serialize);
-- instance->thread_pid = -1;
-+ instance->thread = NULL;
- mutex_unlock(&instance->serialize);
+ /* 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;
- complete_and_exit(&instance->thread_exited, ret);
-@@ -1034,13 +1032,18 @@ static int usbatm_do_heavy_init(void *arg)
++ /* FIXME we only want one one probe() not two */
+ return usb_hcd_fsl_probe(&ehci_fsl_hc_driver, pdev);
+ }
- static int usbatm_heavy_init(struct usbatm_data *instance)
+@@ -338,12 +337,12 @@ static int ehci_fsl_drv_remove(struct platform_device *pdev)
{
-- 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);
+ 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;
-@@ -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);
+-MODULE_ALIAS("fsl-ehci");
++MODULE_ALIAS("platform:fsl-ehci");
-@@ -1287,8 +1290,8 @@ void usbatm_usb_disconnect(struct usb_interface *intf)
+ static struct platform_driver ehci_fsl_driver = {
+ .probe = ehci_fsl_drv_probe,
+@@ -351,5 +350,5 @@ static struct platform_driver ehci_fsl_driver = {
+ .shutdown = usb_hcd_platform_shutdown,
+ .driver = {
+ .name = "fsl-ehci",
+- },
++ },
+ };
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 46ee7f4..369a8a5 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -57,35 +57,6 @@
+ * Special thanks to Intel and VIA for providing host controllers to
+ * test this driver on, and Cypress (including In-System Design) for
+ * providing early devices for those host controllers to talk to!
+- *
+- * HISTORY:
+- *
+- * 2004-05-10 Root hub and PCI suspend/resume support; remote wakeup. (db)
+- * 2004-02-24 Replace pci_* with generic dma_* API calls (dsaxena at plexity.net)
+- * 2003-12-29 Rewritten high speed iso transfer support (by Michal Sojka,
+- * <sojkam at centrum.cz>, updates by DB).
+- *
+- * 2002-11-29 Correct handling for hw async_next register.
+- * 2002-08-06 Handling for bulk and interrupt transfers is mostly shared;
+- * only scheduling is different, no arbitrary limitations.
+- * 2002-07-25 Sanity check PCI reads, mostly for better cardbus support,
+- * clean up HC run state handshaking.
+- * 2002-05-24 Preliminary FS/LS interrupts, using scheduling shortcuts
+- * 2002-05-11 Clear TT errors for FS/LS ctrl/bulk. Fill in some other
+- * missing pieces: enabling 64bit dma, handoff from BIOS/SMM.
+- * 2002-05-07 Some error path cleanups to report better errors; wmb();
+- * use non-CVS version id; better iso bandwidth claim.
+- * 2002-04-19 Control/bulk/interrupt submit no longer uses giveback() on
+- * errors in submit path. Bugfixes to interrupt scheduling/processing.
+- * 2002-03-05 Initial high-speed ISO support; reduce ITD memory; shift
+- * more checking to generic hcd framework (db). Make it work with
+- * Philips EHCI; reduce PCI traffic; shorten IRQ path (Rory Bolt).
+- * 2002-01-14 Minor cleanup; version synch.
+- * 2002-01-08 Fix roothub handoff of FS/LS to companion controllers.
+- * 2002-01-04 Control/Bulk queuing behaves.
+- *
+- * 2001-12-12 Initial patch version for Linux 2.5.1 kernel.
+- * 2001-June Works with usb-storage and NEC EHCI on 2.4
+ */
- 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);
+ #define DRIVER_VERSION "10 Dec 2004"
+@@ -95,7 +66,7 @@
+ static const char hcd_name [] = "ehci_hcd";
- wait_for_completion(&instance->thread_exited);
-diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h
-index ff8551e..e6887c6 100644
---- a/drivers/usb/atm/usbatm.h
-+++ b/drivers/usb/atm/usbatm.h
-@@ -24,7 +24,6 @@
- #ifndef _USBATM_H_
- #define _USBATM_H_
--#include <asm/semaphore.h>
- #include <linux/atm.h>
- #include <linux/atmdev.h>
- #include <linux/completion.h>
-@@ -176,7 +175,7 @@ struct usbatm_data {
- int disconnected;
+-#undef EHCI_VERBOSE_DEBUG
++#undef VERBOSE_DEBUG
+ #undef EHCI_URB_TRACE
- /* heavy init */
-- int thread_pid;
-+ struct task_struct *thread;
- struct completion thread_started;
- struct completion thread_exited;
+ #ifdef DEBUG
+@@ -174,6 +145,16 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
+ return -ETIMEDOUT;
+ }
-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
- */
++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;
+- }
- /*
-@@ -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"
+ /* 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);
-@@ -118,7 +119,7 @@ static int acm_wb_alloc(struct acm *acm)
- int i, wbn;
- struct acm_wb *wb;
+ /* 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);
+ }
-- 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)
- }
+ /*-------------------------------------------------------------------------*/
+@@ -355,17 +331,13 @@ static void ehci_turn_off_all_ports(struct ehci_hcd *ehci)
+ &ehci->regs->port_status[port]);
}
--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.
+-/* 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 acm_write_done(struct acm *acm)
-+static void acm_write_done(struct acm *acm, struct acm_wb *wb)
+-static void
+-ehci_shutdown (struct usb_hcd *hcd)
++static void ehci_silence_controller(struct ehci_hcd *ehci)
{
- unsigned long flags;
-- int wbn;
+- struct ehci_hcd *ehci;
+-
+- ehci = hcd_to_ehci (hcd);
+- (void) ehci_halt (ehci);
++ ehci_halt(ehci);
+ ehci_turn_off_all_ports(ehci);
- 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);
+ /* 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);
}
- /*
- * Poke write.
- */
--static int acm_write_start(struct acm *acm)
-+static int acm_write_start(struct acm *acm, int wbn)
++/* 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 long flags;
-- int wbn;
- struct acm_wb *wb;
- int rc;
+ unsigned port;
+@@ -425,15 +413,15 @@ static void ehci_work (struct ehci_hcd *ehci)
+ timer_action (ehci, TIMER_IO_WATCHDOG);
+ }
-@@ -190,24 +182,24 @@ static int acm_write_start(struct acm *acm)
- return 0; /* A white lie */
- }
++/*
++ * Called when the ehci_hcd module is removed.
++ */
+ static void ehci_stop (struct usb_hcd *hcd)
+ {
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
-- wbn = acm->write_current;
- if (!acm_wb_is_used(acm, wbn)) {
- spin_unlock_irqrestore(&acm->write_lock, flags);
- return 0;
- }
- wb = &acm->wb[wbn];
+ ehci_dbg (ehci, "stop\n");
-- acm->write_ready = 0;
-+ if(acm_wb_is_avail(acm) <= 1)
-+ acm->write_ready = 0;
- spin_unlock_irqrestore(&acm->write_lock, flags);
+- /* 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);
-- 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;
++ ehci_silence_controller(ehci);
+ ehci_reset (ehci);
+- ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ spin_unlock_irq(&ehci->lock);
-- 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;
- }
+- /* let companion controllers work when we aren't */
+- ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+-
+ remove_companion_file(ehci);
+ remove_debug_files (ehci);
-@@ -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);
- }
+@@ -676,7 +661,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ cmd = ehci_readl(ehci, &ehci->regs->command);
+ bh = 0;
- /* 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;
+-#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;
- dbg("Entering acm_write_bulk with status %d", urb->status);
+ /* resume root hub? */
+@@ -738,8 +725,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
-- acm_write_done(acm);
-- acm_write_start(acm);
-+ acm = wb->instance;
-+ acm_write_done(acm, wb);
- if (ACM_READY(acm))
- schedule_work(&acm->work);
+ /* 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;
}
-@@ -489,6 +482,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
- else
- rv = 0;
+@@ -788,8 +773,14 @@ static int ehci_urb_enqueue (
+ INIT_LIST_HEAD (&qtd_list);
-+ set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);
- tty->driver_data = acm;
- acm->tty = tty;
+ 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
-@@ -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);
+-#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..382587c 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -28,7 +28,9 @@
-- 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;
-+ }
+-#ifdef CONFIG_USB_PERSIST
++#define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
+
-+ 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;
- }
++#ifdef CONFIG_PM
- 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;
+ 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;
+ }
-- 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;
+-#else /* CONFIG_USB_PERSIST */
-
- 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);
+-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)
+ }
- 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);
+ /* 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;
-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
+ if (t1 != t2) {
+ ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
+@@ -183,7 +176,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
- struct acm_wb {
-@@ -67,6 +67,8 @@ struct acm_wb {
- dma_addr_t dmah;
- int len;
- int use;
-+ struct urb *urb;
-+ struct acm *instance;
- };
+ /* 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);
- 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"
+ spin_unlock_irq (&ehci->lock);
+-
+- if (!power_okay)
+- ehci_handover_companion_ports(ehci);
++ ehci_handover_companion_ports(ehci);
+ return 0;
+ }
- 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
+@@ -540,13 +530,11 @@ ehci_hub_descriptor (
+ if (HCS_INDICATOR (ehci->hcs_params))
+ temp |= 0x0080; /* per-port indicators (LEDs) */
+ #endif
+- desc->wHubCharacteristics = (__force __u16)cpu_to_le16 (temp);
++ desc->wHubCharacteristics = cpu_to_le16(temp);
+ }
- 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.
+-#define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
-
- config USB_OTG
- bool
- depends on USB && EXPERIMENTAL
-@@ -136,14 +111,16 @@ config USB_OTG
+ static int ehci_hub_control (
+ struct usb_hcd *hcd,
+ u16 typeReq,
+@@ -778,11 +766,11 @@ static int ehci_hub_control (
+ if (temp & PORT_POWER)
+ status |= 1 << USB_PORT_FEAT_POWER;
- 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.
+-#ifndef EHCI_VERBOSE_DEBUG
++#ifndef VERBOSE_DEBUG
+ if (status & ~0xffff) /* only if wPortChange is interesting */
+ #endif
+ dbg_port (ehci, "GetStatus", wIndex + 1, temp);
+- put_unaligned(cpu_to_le32 (status), (__le32 *) buf);
++ put_unaligned_le32(status, buf);
+ break;
+ case SetHubFeature:
+ switch (wValue) {
+@@ -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;
+ }
- 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
+-MODULE_ALIAS("ixp4xx-ehci");
++MODULE_ALIAS("platform:ixp4xx-ehci");
- 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.
+ static struct platform_driver ixp4xx_ehci_driver = {
+ .probe = ixp4xx_ehci_probe,
+ .remove = ixp4xx_ehci_remove,
+ .driver = {
+ .name = "ixp4xx-ehci",
+- .bus = &platform_bus_type
+ },
+ };
+diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
+index e129981..d187d03 100644
+--- a/drivers/usb/host/ehci-orion.c
++++ b/drivers/usb/host/ehci-orion.c
+@@ -11,15 +11,18 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+-#include <asm/arch/orion.h>
++#include <linux/mbus.h>
++#include <asm/plat-orion/ehci-orion.h>
-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);
- }
+ #define rdl(off) __raw_readl(hcd->regs + (off))
+ #define wrl(off, val) __raw_writel((val), hcd->regs + (off))
-+ /*
-+ * 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;
+-#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;
+
-+ 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);
++ for (i = 0; i < 4; i++) {
++ wrl(USB_WINDOW_CTRL(i), 0);
++ wrl(USB_WINDOW_BASE(i), 0);
+ }
+
- /* 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);
++ for (i = 0; i < dram->num_cs; i++) {
++ struct mbus_dram_window *cs = dram->cs + i;
+
-+ /* 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;
++ 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);
++ }
++}
+
- 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,
+ 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;
- 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;
+ /*
++ * (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
- 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;
++ 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;
- 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;
+- 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)
- case USBDEVFS_RESET:
-- snoop(&dev->dev, "%s: RESET\n", __FUNCTION__);
-+ snoop(&dev->dev, "%s: RESET\n", __func__);
- ret = proc_resetdevice(ps);
- break;
+ /* here we "know" root ports should always stay powered */
+ ehci_port_power(ehci, 1);
+- ehci_handover_companion_ports(ehci);
- 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;
+ 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;
- case USBDEVFS_GETDRIVER:
-- snoop(&dev->dev, "%s: GETDRIVER\n", __FUNCTION__);
-+ snoop(&dev->dev, "%s: GETDRIVER\n", __func__);
- ret = proc_getdriver(ps, p);
- break;
++ /* 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);
- case USBDEVFS_CONNECTINFO:
-- snoop(&dev->dev, "%s: CONNECTINFO\n", __FUNCTION__);
-+ snoop(&dev->dev, "%s: CONNECTINFO\n", __func__);
- ret = proc_connectinfo(ps, p);
- break;
++ /* FIXME we only want one one remove() not two */
+ usb_ehci_ppc_soc_remove(hcd, pdev);
+ return 0;
+ }
- case USBDEVFS_SETINTERFACE:
-- snoop(&dev->dev, "%s: SETINTERFACE\n", __FUNCTION__);
-+ snoop(&dev->dev, "%s: SETINTERFACE\n", __func__);
- ret = proc_setintf(ps, p);
- break;
+-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;
+ }
- case USBDEVFS_SETCONFIGURATION:
-- snoop(&dev->dev, "%s: SETCONFIGURATION\n", __FUNCTION__);
-+ snoop(&dev->dev, "%s: SETCONFIGURATION\n", __func__);
- ret = proc_setconfig(ps, p);
- break;
+- dev->core.power.power_state = PMSG_ON;
+ dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */
- 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
+ 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..b85b541 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,9 +284,8 @@ 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);
++ __le32 halt = HALT_BIT(ehci);
- 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;
+ if (unlikely (list_empty (&qh->qtd_list)))
+ return count;
+@@ -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;
- case USBDEVFS_REAPURB32:
-- snoop(&dev->dev, "%s: REAPURB32\n", __FUNCTION__);
-+ snoop(&dev->dev, "%s: REAPURB32\n", __func__);
- ret = proc_reapurb_compat(ps, p);
- break;
+ 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) {
- case USBDEVFS_REAPURBNDELAY32:
-- snoop(&dev->dev, "%s: REAPURBDELAY32\n", __FUNCTION__);
-+ snoop(&dev->dev, "%s: REAPURBDELAY32\n", __func__);
- ret = proc_reapurbnonblock_compat(ps, p);
- break;
++ /* 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;
- 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
+ /* 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;
- case USBDEVFS_DISCARDURB:
-- snoop(&dev->dev, "%s: DISCARDURB\n", __FUNCTION__);
-+ snoop(&dev->dev, "%s: DISCARDURB\n", __func__);
- ret = proc_unlinkurb(ps, p);
- break;
++ /* scan the whole queue for unlinks whenever it stops */
+ } else {
+ stopped = 1;
- case USBDEVFS_REAPURB:
-- snoop(&dev->dev, "%s: REAPURB\n", __FUNCTION__);
-+ snoop(&dev->dev, "%s: REAPURB\n", __func__);
- ret = proc_reapurb(ps, p);
- break;
+- 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;
- case USBDEVFS_REAPURBNDELAY:
-- snoop(&dev->dev, "%s: REAPURBDELAY\n", __FUNCTION__);
-+ snoop(&dev->dev, "%s: REAPURBDELAY\n", __func__);
- ret = proc_reapurbnonblock(ps, p);
- break;
+- /* 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;
+- }
- case USBDEVFS_DISCSIGNAL:
-- snoop(&dev->dev, "%s: DISCSIGNAL\n", __FUNCTION__);
-+ snoop(&dev->dev, "%s: DISCSIGNAL\n", __func__);
- ret = proc_disconnectsignal(ps, p);
- break;
+- /* 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:
+ }
+ }
- case USBDEVFS_CLAIMINTERFACE:
-- snoop(&dev->dev, "%s: CLAIMINTERFACE\n", __FUNCTION__);
-+ snoop(&dev->dev, "%s: CLAIMINTERFACE\n", __func__);
- ret = proc_claiminterface(ps, p);
- break;
+- /* 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;
- case USBDEVFS_RELEASEINTERFACE:
-- snoop(&dev->dev, "%s: RELEASEINTERFACE\n", __FUNCTION__);
-+ snoop(&dev->dev, "%s: RELEASEINTERFACE\n", __func__);
- ret = proc_releaseinterface(ps, p);
- break;
++ /* 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;
- case USBDEVFS_IOCTL:
-- snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
-+ snoop(&dev->dev, "%s: IOCTL\n", __func__);
- ret = proc_ioctl_default(ps, p);
- break;
+@@ -568,8 +594,10 @@ qh_urb_transaction (
+ list_add_tail (&qtd->qtd_list, head);
}
-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__);
+- /* 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);
- 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;
++ /* 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;
+@@ -841,7 +883,7 @@ static struct ehci_qh *qh_append_tds (
+ )
+ {
+ struct ehci_qh *qh = NULL;
+- u32 qh_addr_mask = cpu_to_hc32(ehci, 0x7f);
++ __hc32 qh_addr_mask = cpu_to_hc32(ehci, 0x7f);
-- dev_dbg(dev, "%s\n", __FUNCTION__);
-+ dev_dbg(dev, "%s\n", __func__);
+ qh = (struct ehci_qh *) *ptr;
+ if (unlikely (qh == NULL)) {
+@@ -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;
+- }
- 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__);
+ 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;
+- }
- 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);
+ 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;
++ }
+ }
- 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;
- }
+- 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;
++ }
+ }
-@@ -823,11 +821,9 @@ static int usb_resume_device(struct usb_device *udev)
- status = udriver->resume(udev);
+- 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;
+ }
- 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;
+@@ -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;
}
-@@ -864,7 +860,7 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
- }
+@@ -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;
+ }
- done:
-- dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
-+ dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status);
- return status;
+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);
-@@ -914,7 +910,7 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
- }
+- 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_
- 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);
+ ep93xx_stop_hc(&pdev->dev);
+ hcd->state = HC_STATE_SUSPENDED;
+- pdev->dev.power.power_state = PMSG_SUSPEND;
-@@ -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)
- }
+ return 0;
+ }
+@@ -193,9 +191,8 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
+ ohci->next_statechange = jiffies;
- done:
-- dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
-+ dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
- return status;
+ 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..17dc2ec 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -36,18 +36,6 @@
-@@ -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);
- }
+-/* 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)
-@@ -1193,8 +1187,9 @@ static int usb_resume_both(struct usb_device *udev)
+@@ -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;
}
- 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;
+@@ -326,23 +314,76 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
+ return rc;
}
-@@ -1262,7 +1257,7 @@ void usb_autosuspend_device(struct usb_device *udev)
++/* 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;
- 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);
- }
++ rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC;
+ switch (ohci->hc_control & OHCI_CTRL_HCFS) {
- /**
-@@ -1282,7 +1277,7 @@ void usb_try_autosuspend_device(struct usb_device *udev)
+ 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)
{
- usb_autopm_do_device(udev, 0);
- dev_vdbg(&udev->dev, "%s: cnt %d\n",
-- __FUNCTION__, udev->pm_usage_cnt);
-+ __func__, udev->pm_usage_cnt);
+- 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;
}
- /**
-@@ -1310,7 +1305,7 @@ int usb_autoresume_device(struct usb_device *udev)
+ #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);
- 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;
+ /* 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;
}
+@@ -666,14 +736,14 @@ static int ohci_hub_control (
+ break;
+ case GetHubStatus:
+ temp = roothub_status (ohci) & ~(RH_HS_CRWE | RH_HS_DRWE);
+- put_unaligned(cpu_to_le32 (temp), (__le32 *) buf);
++ put_unaligned_le32(temp, buf);
+ break;
+ case GetPortStatus:
+ if (!wIndex || wIndex > ports)
+ goto error;
+ wIndex--;
+ temp = roothub_portstatus (ohci, wIndex);
+- put_unaligned(cpu_to_le32 (temp), (__le32 *) buf);
++ put_unaligned_le32(temp, buf);
-@@ -1382,7 +1377,7 @@ void usb_autopm_put_interface(struct usb_interface *intf)
+ #ifndef OHCI_VERBOSE_DEBUG
+ if (*(u16*)(buf+2)) /* only if wPortChange is interesting */
+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)
- 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);
+ omap_ohci_clock_power(0);
+ ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+- dev->dev.power.power_state = PMSG_SUSPEND;
+ return 0;
}
- EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
-@@ -1426,7 +1421,7 @@ int usb_autopm_get_interface(struct usb_interface *intf)
+ 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);
- 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;
+ 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;
}
- 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;
+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;
}
- 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;
- }
+-#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
-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;
+ 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;
+ }
- 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;
+@@ -345,9 +306,8 @@ static const struct hc_driver ohci_pci_hc_driver = {
+ .shutdown = ohci_shutdown,
-- 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;
+ #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;
}
-@@ -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->core.power.power_state = PMSG_ON;
+ dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */
-- dev->dev.power.power_state = PMSG_ON;
+ 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);
-
- clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
++ 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);
-- 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] = {
+ /* mask interrupts and disable power */
- 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 */
+@@ -224,24 +224,26 @@ static int ohci_sm501_suspend(struct platform_device *pdev, pm_message_t msg)
- 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;
+ 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;
+ }
- might_sleep();
+ 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);
-@@ -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;
- }
+ 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
- /* any errors get returned through the urb completion */
-@@ -915,15 +924,6 @@ static int register_root_hub(struct usb_hcd *hcd)
- return retval;
+ /*-------------------------------------------------------------------------*/
+@@ -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;
}
--void usb_enable_root_hub_irq (struct usb_bus *bus)
+-#ifdef CONFIG_PM
+-static int ssb_ohci_hcd_suspend(struct usb_hcd *hcd, pm_message_t message)
-{
-- struct usb_hcd *hcd;
+- struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
+- struct ohci_hcd *ohci = &ohcidev->ohci;
+- unsigned long flags;
-
-- 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);
+- 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 = {
-@@ -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 */
+ .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)
- 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);
+ ssb_device_enable(dev, ohcidev->enable_flags);
- /* called after entering D0 (etc), before resuming the hub */
-- int (*resume) (struct usb_hcd *hcd);
-+ int (*pci_resume) (struct usb_hcd *hcd);
++ ohci_finish_controller_resume(hcd);
+ return 0;
+ }
- /* 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 */
+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;
+ }
- /* force handover of high-speed port to full-speed companion */
- void (*relinquish_port)(struct usb_hcd *, int);
-diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
-index 68fc521..eb57fcc 100644
---- a/drivers/usb/core/hub.c
-+++ b/drivers/usb/core/hub.c
-@@ -23,7 +23,6 @@
- #include <linux/mutex.h>
- #include <linux/freezer.h>
+@@ -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;
+ }
--#include <asm/semaphore.h>
- #include <asm/uaccess.h>
- #include <asm/byteorder.h>
+ 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..1666734 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");
-@@ -31,12 +30,6 @@
- #include "hcd.h"
- #include "hub.h"
+-#define DRIVER_VERSION "29 May 2007"
++#define DRIVER_VERSION "10 Apr 2008"
--#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 const char hcd_name[] = "r8a66597_hcd";
-+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)
+ /* 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);
}
- /* caller has locked the hub device */
--static int hub_pre_reset(struct usb_interface *intf)
-+static void hub_stop(struct usb_hub *hub)
+-static int enable_controller(struct r8a66597 *r8a66597)
++static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
{
-- struct usb_hub *hub = usb_get_intfdata(intf);
- struct usb_device *hdev = hub->hdev;
- int i;
+ u16 tmp;
+ int i = 0;
-@@ -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
++#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) */
+
-+#ifdef CONFIG_PM
++ return 0;
++}
+
-+static void hub_restart(struct usb_hub *hub, int type)
++static void r8a66597_clock_disable(struct r8a66597 *r8a66597)
+{
-+ struct usb_device *hdev = hub->hdev;
-+ int port1;
++ 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
++}
+
-+ /* 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;
++static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port)
++{
++ u16 val;
+
-+ 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;
-+ }
++ val = port ? DRPD : DCFM | DRPD;
++ r8a66597_bset(r8a66597, val, get_syscfg_reg(port));
++ r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
+
-+ /* Was the power session lost while we were suspended? */
-+ switch (type) {
-+ case HUB_RESET_RESUME:
-+ portstatus = 0;
-+ portchange = USB_PORT_STAT_C_CONNECTION;
-+ break;
++ 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;
+
-+ case HUB_RESET:
-+ case HUB_RESUME:
-+ status = hub_port_status(hub, port1,
-+ &portstatus, &portchange);
-+ break;
-+ }
++ r8a66597_write(r8a66597, 0, get_intenb_reg(port));
++ r8a66597_write(r8a66597, 0, get_intsts_reg(port));
+
-+ /* 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;
-+ }
++ r8a66597_port_power(r8a66597, port, 0);
+
-+ /* 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);
-+ }
++ do {
++ tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS;
++ udelay(640);
++ } while (tmp == EDGESTS);
+
-+ hub_activate(hub);
++ val = port ? DRPD : DCFM | DRPD;
++ r8a66597_bclr(r8a66597, val, get_syscfg_reg(port));
++ r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
+}
+
-+#endif /* CONFIG_PM */
-+
-+/* caller has locked the hub device */
-+static int hub_pre_reset(struct usb_interface *intf)
++static int enable_controller(struct r8a66597 *r8a66597)
+{
-+ struct usb_hub *hub = usb_get_intfdata(intf);
++ int ret, port;
+
-+ hub_stop(hub);
- return 0;
- }
++ ret = r8a66597_clock_enable(r8a66597);
++ if (ret < 0)
++ return ret;
-@@ -911,7 +1007,7 @@ static void hub_disconnect(struct usb_interface *intf)
+ r8a66597_bset(r8a66597, vif & LDRV, PINCFG);
+- r8a66597_bset(r8a66597, HSE, SYSCFG0);
+- r8a66597_bset(r8a66597, HSE, SYSCFG1);
+ r8a66597_bset(r8a66597, USBE, SYSCFG0);
- /* Disconnect all children and quiesce the hub */
- hub->error = 0;
-- hub_pre_reset(intf);
-+ hub_stop(hub);
+ 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);
- usb_set_intfdata (intf, NULL);
+- 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);
-@@ -1099,21 +1195,42 @@ void usb_set_device_state(struct usb_device *udev,
- spin_unlock_irqrestore(&device_state_lock, flags);
+ 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;
}
-+/*
-+ * 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)
+ static void disable_controller(struct r8a66597 *r8a66597)
{
- int devnum;
- struct usb_bus *bus = udev->bus;
+- u16 tmp;
++ int port;
- /* 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);
+ 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);
-
-- bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);
+- r8a66597_port_power(r8a66597, 0, 0);
+- r8a66597_port_power(r8a66597, 1, 0);
-
-+ 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;
+- do {
+- tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS;
+- udelay(640);
+- } while (tmp == EDGESTS);
- if (!udev) {
-- pr_debug ("%s nodev\n", __FUNCTION__);
-+ pr_debug ("%s nodev\n", __func__);
- return;
- }
+- 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);
-@@ -1511,28 +1635,6 @@ out_authorized:
+- 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);
+ }
--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)
+ /* this function must be called with interrupt disabled */
+ static void pipe_setting(struct r8a66597 *r8a66597, struct r8a66597_td *td)
{
-@@ -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);
+@@ -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;
- if (status == 0)
- status = finish_port_resume(udev);
-@@ -2001,7 +2100,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+@@ -742,6 +779,7 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
+ break;
}
}
-
-- 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;
++#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
}
- 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;
+ /* 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;
}
-@@ -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 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)
}
--static void ep0_reinit(struct usb_device *udev)
-+void usb_ep0_reinit(struct usb_device *udev)
+ /* 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)
{
- usb_disable_endpoint(udev, 0 + USB_DIR_IN);
- usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
- usb_enable_endpoint(udev, &udev->ep0);
+- 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));
}
-+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);
+@@ -918,7 +993,7 @@ static void prepare_setup_packet(struct r8a66597 *r8a66597,
+ struct r8a66597_td *td)
+ {
+ int i;
+- u16 *p = (u16 *)td->urb->setup_packet;
++ __le16 *p = (__le16 *)td->urb->setup_packet;
+ unsigned long setup_addr = USBREQ;
+
+ r8a66597_write(r8a66597, make_devsel(td->address) | td->maxpacket,
+@@ -926,7 +1001,7 @@ static void prepare_setup_packet(struct r8a66597 *r8a66597,
+ r8a66597_write(r8a66597, ~(SIGN | SACK), INTSTS1);
+
+ for (i = 0; i < 4; i++) {
+- r8a66597_write(r8a66597, cpu_to_le16(p[i]), setup_addr);
++ r8a66597_write(r8a66597, le16_to_cpu(p[i]), setup_addr);
+ setup_addr += 2;
+ }
+ r8a66597_write(r8a66597, SUREQ, DCPCTR);
+@@ -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)
}
- 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;
-+ }
++static void r8a66597_root_hub_start_polling(struct r8a66597 *r8a66597)
++{
++ mod_timer(&r8a66597->rh_timer,
++ jiffies + msecs_to_jiffies(R8A66597_RH_POLL_TIME));
++}
+
-+ /* 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;
+ static void start_root_hub_sampling(struct r8a66597 *r8a66597, int port)
+ {
+ struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
-- 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);
+ 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);
+ }
- /* 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;
+ 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);
}
-+ 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 (!(rh->port & (1 << USB_PORT_FEAT_CONNECTION))) {
++ r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port));
++ r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
++ }
+
-+ if (memcmp(&udev->descriptor, old_device_descriptor,
-+ sizeof(*old_device_descriptor)) != 0)
-+ return 1;
+ 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);
+ }
+ }
+ }
-+ /* 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;
++static void r8a66597_interval_timer(unsigned long _r8a66597)
++{
++ struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
++ unsigned long flags;
++ u16 pipenum;
++ struct r8a66597_td *td;
+
-+ 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);
- }
++ spin_lock_irqsave(&r8a66597->lock, flags);
+
- 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;
- }
- }
++ for (pipenum = 0; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
++ if (!(r8a66597->interval_map & (1 << pipenum)))
++ continue;
++ if (timer_pending(&r8a66597->interval_timer[pipenum]))
++ continue;
+
-+ 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;
-+ }
++ td = r8a66597_get_td(r8a66597, pipenum);
++ if (td)
++ start_transfer(r8a66597, td);
+ }
+
- 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;
- }
++ 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;
- 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);
+ 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);
++ }
}
- 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)
+ } else
+ set_td_timer(r8a66597, td);
+@@ -2028,7 +2131,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ case GetPortStatus:
+ if (wIndex > R8A66597_MAX_ROOT_HUB)
+ goto error;
+- *(u32 *)buf = cpu_to_le32(rh->port);
++ *(__le32 *)buf = cpu_to_le32(rh->port);
+ break;
+ case SetPortFeature:
+ if (wIndex > R8A66597_MAX_ROOT_HUB)
+@@ -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)
{
- int i;
+- pdev->dev.power.power_state = state;
+ return 0;
+ }
-- 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);
- }
+ 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);
- /* Now that the interfaces are unbound, nobody should
-@@ -1231,7 +1231,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
- */
+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)
- /* 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);
+ struct r8a66597_pipe_info {
++ unsigned long timer_interval;
+ u16 pipenum;
+ u16 address; /* R8A66597 HCD usb address */
+ u16 epnum;
+@@ -478,9 +488,11 @@ struct r8a66597 {
-@@ -1330,8 +1330,7 @@ int usb_reset_configuration(struct usb_device *dev)
- struct usb_interface *intf = config->interface[i];
- struct usb_host_interface *alt;
+ struct timer_list rh_timer;
+ struct timer_list td_timer[R8A66597_MAX_NUM_PIPE];
++ struct timer_list interval_timer[R8A66597_MAX_NUM_PIPE];
-- 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);
+ unsigned short address_map;
+ unsigned short timeout_map;
++ unsigned short interval_map;
+ unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE];
+ unsigned char dma_map;
- /* 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
+@@ -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;
+
-+ /* 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;
++ 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
-+ /* 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 */
+ len = (len + 1) / 2;
+ insw(r8a66597->reg + offset, buf, len);
++#endif
}
-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);
+ 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;
-- /* 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);
+ len = len / 2;
+@@ -549,6 +592,7 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
+ buf = &buf[len];
+ outb((unsigned char)*buf, fifoaddr);
}
- return rc;
- }
-@@ -238,13 +237,12 @@ static void remove_persist_attributes(struct device *dev)
- &dev_attr_persist.attr,
- power_group);
++#endif
}
--
- #else
-
- #define add_persist_attributes(dev) 0
- #define remove_persist_attributes(dev) do {} while (0)
--#endif /* CONFIG_USB_PERSIST */
-+#endif /* CONFIG_PM */
+ 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;
+ }
- #ifdef CONFIG_USB_SUSPEND
++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..4265752 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)
-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;
+ 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);
+@@ -1102,7 +1100,7 @@ sl811h_hub_descriptor (
+ /* no overcurrent errors detection/handling */
+ temp |= 0x0010;
-@@ -590,6 +590,30 @@ void usb_kill_anchored_urbs(struct usb_anchor *anchor)
- EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs);
+- desc->wHubCharacteristics = (__force __u16)cpu_to_le16(temp);
++ desc->wHubCharacteristics = cpu_to_le16(temp);
- /**
-+ * 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)
+ /* two bitmaps: ports removable, and legacy PortPwrCtrlMask */
+ desc->bitmap[0] = 0 << 1;
+@@ -1337,7 +1335,7 @@ static int
+ sl811h_bus_suspend(struct usb_hcd *hcd)
{
- f->is_active = 1;
-- f->dev.power.power_state.event = PM_EVENT_ON;
+ // SOFs off
+- DBG("%s\n", __FUNCTION__);
++ DBG("%s\n", __func__);
+ return 0;
}
- static inline void mark_quiesced(struct usb_interface *f)
+@@ -1345,7 +1343,7 @@ static int
+ sl811h_bus_resume(struct usb_hcd *hcd)
{
- f->is_active = 0;
-- f->dev.power.power_state.event = PM_EVENT_SUSPEND;
+ // SOFs on
+- DBG("%s\n", __FUNCTION__);
++ DBG("%s\n", __func__);
+ return 0;
}
- 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;
- }
+@@ -1508,15 +1506,7 @@ static const char proc_filename[] = "driver/sl811h";
- 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;
+ static void create_debug_file(struct sl811 *sl811)
+ {
+- struct proc_dir_entry *pde;
+-
+- pde = create_proc_entry(proc_filename, 0, NULL);
+- if (pde == NULL)
+- return;
+-
+- pde->proc_fops = &proc_ops;
+- pde->data = sl811;
+- sl811->pde = pde;
++ sl811->pde = proc_create_data(proc_filename, 0, NULL, &proc_ops, sl811);
+ }
- /*
- * 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;
+ static void remove_debug_file(struct sl811 *sl811)
+@@ -1772,8 +1762,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;
+ }
-+ 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).
+@@ -1786,15 +1774,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.
*/
-- __raw_writesb(dreg, req->req.buf + req->req.actual, count);
-+ __raw_writesb(dreg, buf, count);
- csr &= ~SET_FX;
- csr |= CLR_FX | AT91_UDP_TXPKTRDY;
- __raw_writel(csr, creg);
-@@ -457,7 +460,7 @@ static void nuke(struct at91_ep *ep, int status)
- if (list_empty(&ep->queue))
- return;
-
-- VDBG("%s %s\n", __FUNCTION__, ep->ep.name);
-+ VDBG("%s %s\n", __func__, ep->ep.name);
- while (!list_empty(&ep->queue)) {
- req = list_entry(ep->queue.next, struct at91_request, queue);
- done(ep, req, status);
-@@ -792,7 +795,7 @@ static int at91_wakeup(struct usb_gadget *gadget)
- int status = -EINVAL;
- unsigned long flags;
-
-- DBG("%s\n", __FUNCTION__ );
-+ DBG("%s\n", __func__ );
- local_irq_save(flags);
-
- if (!udc->clocked || !udc->suspended)
-diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
-index b0db4c3..e756023 100644
---- a/drivers/usb/gadget/atmel_usba_udc.c
-+++ b/drivers/usb/gadget/atmel_usba_udc.c
-@@ -18,6 +18,7 @@
- #include <linux/platform_device.h>
- #include <linux/usb/ch9.h>
- #include <linux/usb/gadget.h>
-+#include <linux/usb/atmel_usba_udc.h>
- #include <linux/delay.h>
-
- #include <asm/gpio.h>
-@@ -27,6 +28,7 @@
-
-
- static struct usba_udc the_udc;
-+static struct usba_ep *usba_ep;
+- 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;
+ }
- #ifdef CONFIG_USB_GADGET_DEBUG_FS
- #include <linux/debugfs.h>
-@@ -324,53 +326,28 @@ static int vbus_is_present(struct usba_udc *udc)
- return 1;
+- dev->dev.power.power_state = PMSG_ON;
+ return sl811h_bus_resume(hcd);
}
--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;
-- }
-- }
- }
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index 8e117a7..f293074 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -67,7 +67,7 @@
+ #include "ohci.h"
+ #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
+ #define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \
+- OHCI_INTR_WDH)
++ OHCI_INTR_WDH)
+ MODULE_AUTHOR("Tony Olech - Elan Digital Systems Limited");
+ MODULE_DESCRIPTION("U132 USB Host Controller Driver");
+ MODULE_LICENSE("GPL");
+@@ -77,15 +77,15 @@ INT_MODULE_PARM(testing, 0);
+ static int distrust_firmware = 1;
+ module_param(distrust_firmware, bool, 0);
+ MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
+- "t setup");
++ "t setup");
+ static DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
+ /*
+ * u132_module_lock exists to protect access to global variables
+ *
+ */
+ static struct mutex u132_module_lock;
+-static int u132_exiting = 0;
+-static int u132_instances = 0;
++static int u132_exiting;
++static int u132_instances;
+ static struct list_head u132_static_list;
+ /*
+ * end of the global variables protected by u132_module_lock
+@@ -97,115 +97,115 @@ static struct workqueue_struct *workqueue;
+ #define MAX_U132_ENDPS 100
+ #define MAX_U132_RINGS 4
+ static const char *cc_to_text[16] = {
+- "No Error ",
+- "CRC Error ",
+- "Bit Stuff ",
+- "Data Togg ",
+- "Stall ",
+- "DevNotResp ",
+- "PIDCheck ",
+- "UnExpPID ",
+- "DataOver ",
+- "DataUnder ",
+- "(for hw) ",
+- "(for hw) ",
+- "BufferOver ",
+- "BuffUnder ",
+- "(for HCD) ",
+- "(for HCD) "
++ "No Error ",
++ "CRC Error ",
++ "Bit Stuff ",
++ "Data Togg ",
++ "Stall ",
++ "DevNotResp ",
++ "PIDCheck ",
++ "UnExpPID ",
++ "DataOver ",
++ "DataUnder ",
++ "(for hw) ",
++ "(for hw) ",
++ "BufferOver ",
++ "BuffUnder ",
++ "(for HCD) ",
++ "(for HCD) "
+ };
+ struct u132_port {
+- struct u132 *u132;
+- int reset;
+- int enable;
+- int power;
+- int Status;
++ struct u132 *u132;
++ int reset;
++ int enable;
++ int power;
++ int Status;
+ };
+ struct u132_addr {
+- u8 address;
++ u8 address;
+ };
+ struct u132_udev {
+- struct kref kref;
+- struct usb_device *usb_device;
+- u8 enumeration;
+- u8 udev_number;
+- u8 usb_addr;
+- u8 portnumber;
+- u8 endp_number_in[16];
+- u8 endp_number_out[16];
++ struct kref kref;
++ struct usb_device *usb_device;
++ u8 enumeration;
++ u8 udev_number;
++ u8 usb_addr;
++ u8 portnumber;
++ u8 endp_number_in[16];
++ u8 endp_number_out[16];
+ };
+ #define ENDP_QUEUE_SHIFT 3
+ #define ENDP_QUEUE_SIZE (1<<ENDP_QUEUE_SHIFT)
+ #define ENDP_QUEUE_MASK (ENDP_QUEUE_SIZE-1)
+ struct u132_urbq {
+- struct list_head urb_more;
+- struct urb *urb;
++ struct list_head urb_more;
++ struct urb *urb;
+ };
+ struct u132_spin {
+- spinlock_t slock;
++ spinlock_t slock;
+ };
+ struct u132_endp {
+- struct kref kref;
+- u8 udev_number;
+- u8 endp_number;
+- u8 usb_addr;
+- u8 usb_endp;
+- struct u132 *u132;
+- struct list_head endp_ring;
+- struct u132_ring *ring;
+- unsigned toggle_bits:2;
+- unsigned active:1;
+- unsigned delayed:1;
+- unsigned input:1;
+- unsigned output:1;
+- unsigned pipetype:2;
+- unsigned dequeueing:1;
+- unsigned edset_flush:1;
+- unsigned spare_bits:14;
+- unsigned long jiffies;
+- struct usb_host_endpoint *hep;
+- struct u132_spin queue_lock;
+- u16 queue_size;
+- u16 queue_last;
+- u16 queue_next;
+- struct urb *urb_list[ENDP_QUEUE_SIZE];
+- struct list_head urb_more;
+- struct delayed_work scheduler;
++ struct kref kref;
++ u8 udev_number;
++ u8 endp_number;
++ u8 usb_addr;
++ u8 usb_endp;
++ struct u132 *u132;
++ struct list_head endp_ring;
++ struct u132_ring *ring;
++ unsigned toggle_bits:2;
++ unsigned active:1;
++ unsigned delayed:1;
++ unsigned input:1;
++ unsigned output:1;
++ unsigned pipetype:2;
++ unsigned dequeueing:1;
++ unsigned edset_flush:1;
++ unsigned spare_bits:14;
++ unsigned long jiffies;
++ struct usb_host_endpoint *hep;
++ struct u132_spin queue_lock;
++ u16 queue_size;
++ u16 queue_last;
++ u16 queue_next;
++ struct urb *urb_list[ENDP_QUEUE_SIZE];
++ struct list_head urb_more;
++ struct delayed_work scheduler;
+ };
+ struct u132_ring {
+- unsigned in_use:1;
+- unsigned length:7;
+- u8 number;
+- struct u132 *u132;
+- struct u132_endp *curr_endp;
+- struct delayed_work scheduler;
++ unsigned in_use:1;
++ unsigned length:7;
++ u8 number;
++ struct u132 *u132;
++ struct u132_endp *curr_endp;
++ struct delayed_work scheduler;
+ };
+ struct u132 {
+- struct kref kref;
+- struct list_head u132_list;
+- struct mutex sw_lock;
+- struct semaphore scheduler_lock;
+- struct u132_platform_data *board;
+- struct platform_device *platform_dev;
+- struct u132_ring ring[MAX_U132_RINGS];
+- int sequence_num;
+- int going;
+- int power;
+- int reset;
+- int num_ports;
+- u32 hc_control;
+- u32 hc_fminterval;
+- u32 hc_roothub_status;
+- u32 hc_roothub_a;
+- u32 hc_roothub_portstatus[MAX_ROOT_PORTS];
+- int flags;
+- unsigned long next_statechange;
+- struct delayed_work monitor;
+- int num_endpoints;
+- struct u132_addr addr[MAX_U132_ADDRS];
+- struct u132_udev udev[MAX_U132_UDEVS];
+- struct u132_port port[MAX_U132_PORTS];
+- struct u132_endp *endp[MAX_U132_ENDPS];
++ struct kref kref;
++ struct list_head u132_list;
++ struct mutex sw_lock;
++ struct mutex scheduler_lock;
++ struct u132_platform_data *board;
++ struct platform_device *platform_dev;
++ struct u132_ring ring[MAX_U132_RINGS];
++ int sequence_num;
++ int going;
++ int power;
++ int reset;
++ int num_ports;
++ u32 hc_control;
++ u32 hc_fminterval;
++ u32 hc_roothub_status;
++ u32 hc_roothub_a;
++ u32 hc_roothub_portstatus[MAX_ROOT_PORTS];
++ int flags;
++ unsigned long next_statechange;
++ struct delayed_work monitor;
++ int num_endpoints;
++ struct u132_addr addr[MAX_U132_ADDRS];
++ struct u132_udev udev[MAX_U132_UDEVS];
++ struct u132_port port[MAX_U132_PORTS];
++ struct u132_endp *endp[MAX_U132_ENDPS];
+ };
--static void copy_from_fifo(void *buf, void __iomem *fifo, int len)
-+#elif defined(CONFIG_ARCH_AT91)
-+
-+#include <asm/arch/at91_pmc.h>
-+
-+static void toggle_bias(int is_on)
- {
-- union {
-- unsigned long *w;
-- unsigned char *b;
-- } p;
-- unsigned long tmp;
--
-- DBG(DBG_FIFO, "copy from FIFO (len %d):\n", len);
-- for (p.w = buf; len > 0; len -= 4, p.w++, fifo += 4) {
-- if (len >= 4) {
-- tmp = __raw_readl(fifo);
-- *p.w = tmp;
-- DBG(DBG_FIFO, " -> %08lx\n", tmp);
-- } else {
-- do {
-- tmp = __raw_readb(fifo);
-- *p.b = tmp;
-- DBG(DBG_FIFO, " -> %02lx\n", tmp);
-- fifo++, p.b++;
-- } while (--len);
-- }
-- }
-+ unsigned int uckr = at91_sys_read(AT91_CKGR_UCKR);
-+
-+ if (is_on)
-+ at91_sys_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN);
-+ else
-+ at91_sys_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN));
+ /*
+@@ -213,34 +213,34 @@ struct u132 {
+ * Does anyone have a better way?????
+ */
+ #define ftdi_read_pcimem(pdev, member, data) usb_ftdi_elan_read_pcimem(pdev, \
+- offsetof(struct ohci_regs, member), 0, data);
++ offsetof(struct ohci_regs, member), 0, data);
+ #define ftdi_write_pcimem(pdev, member, data) usb_ftdi_elan_write_pcimem(pdev, \
+- offsetof(struct ohci_regs, member), 0, data);
++ offsetof(struct ohci_regs, member), 0, data);
+ #define u132_read_pcimem(u132, member, data) \
+- usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
+- ohci_regs, member), 0, data);
++ usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
++ ohci_regs, member), 0, data);
+ #define u132_write_pcimem(u132, member, data) \
+- usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
+- ohci_regs, member), 0, data);
++ usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
++ ohci_regs, member), 0, data);
+ static inline struct u132 *udev_to_u132(struct u132_udev *udev)
+ {
+- u8 udev_number = udev->udev_number;
+- return container_of(udev, struct u132, udev[udev_number]);
++ u8 udev_number = udev->udev_number;
++ return container_of(udev, struct u132, udev[udev_number]);
}
-+#endif /* CONFIG_ARCH_AT91 */
-+
- static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req)
+ static inline struct u132 *hcd_to_u132(struct usb_hcd *hcd)
{
- 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;
+- return (struct u132 *)(hcd->hcd_priv);
++ return (struct u132 *)(hcd->hcd_priv);
}
-@@ -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;
+ 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);
+ }
-@@ -2004,7 +1988,7 @@ static int __init usba_udc_probe(struct platform_device *pdev)
- }
+ static inline void u132_disable(struct u132 *u132)
+ {
+- u132_to_hcd(u132)->state = HC_STATE_HALT;
++ u132_to_hcd(u132)->state = HC_STATE_HALT;
+ }
- 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)
+@@ -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 usba_udc *udc;
- int i;
-+ struct usba_platform_data *pdata = pdev->dev.platform_data;
-
- udc = platform_get_drvdata(pdev);
+- 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);
+ }
-- 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);
+ static inline void u132_u132_put_kref(struct u132 *u132)
+ {
+- kref_put(&u132->kref, u132_hcd_delete);
++ kref_put(&u132->kref, u132_hcd_delete);
+ }
-@@ -2040,6 +2027,7 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
- gpio_free(udc->vbus_pin);
+ static inline void u132_u132_init_kref(struct u132 *u132)
+ {
+- kref_init(&u132->kref);
++ kref_init(&u132->kref);
+ }
- 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 */
+ 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;
+ }
- /* 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)
+ static inline void u132_udev_put_kref(struct u132 *u132, struct u132_udev *udev)
{
- struct dummy *dum = platform_get_drvdata(pdev);
+- kref_put(&udev->kref, u132_udev_delete);
++ kref_put(&udev->kref, u132_udev_delete);
+ }
-- 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);
+ static inline void u132_udev_get_kref(struct u132 *u132, struct u132_udev *udev)
+ {
+- kref_get(&udev->kref);
++ kref_get(&udev->kref);
+ }
-- pdev->dev.power.power_state = state;
- usb_hcd_poll_rh_status (dummy_to_hcd (dum));
- return 0;
+ 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);
}
-@@ -909,13 +906,12 @@ static int dummy_udc_resume (struct platform_device *pdev)
+
+ static inline void u132_ring_put_kref(struct u132 *u132, struct u132_ring *ring)
{
- struct dummy *dum = platform_get_drvdata(pdev);
+- kref_put(&u132->kref, u132_hcd_delete);
++ kref_put(&u132->kref, u132_hcd_delete);
+ }
-- 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);
+ 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;
+ }
-- pdev->dev.power.power_state = PMSG_ON;
- usb_hcd_poll_rh_status (dummy_to_hcd (dum));
- return 0;
+ 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;
}
-@@ -1711,7 +1707,7 @@ static int dummy_bus_suspend (struct usb_hcd *hcd)
+
+ static void u132_ring_cancel_work(struct u132 *u132, struct u132_ring *ring)
{
- struct dummy *dum = hcd_to_dummy (hcd);
+- 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);
+ }
-- dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
-+ dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
+ 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);
+ }
- 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;
+ 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);
+ }
-- dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
-+ dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
+ static inline void u132_endp_get_kref(struct u132 *u132, struct u132_endp *endp)
+ {
+- kref_get(&endp->kref);
++ kref_get(&endp->kref);
+ }
- 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;
+ 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);
+ }
-- dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
-+ dev_dbg (&pdev->dev, "%s\n", __func__);
+ 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,
- hcd = platform_get_drvdata (pdev);
- dum = hcd_to_dummy (hcd);
-@@ -1916,7 +1912,7 @@ static int dummy_hcd_resume (struct platform_device *pdev)
+ static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp)
{
- struct usb_hcd *hcd;
+- 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);
+ }
-- dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
-+ dev_dbg (&pdev->dev, "%s\n", __func__);
+ static inline void u132_monitor_put_kref(struct u132 *u132)
+ {
+- kref_put(&u132->kref, u132_hcd_delete);
++ kref_put(&u132->kref, u132_hcd_delete);
+ }
- hcd = platform_get_drvdata (pdev);
- set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-@@ -1937,69 +1933,57 @@ static struct platform_driver dummy_hcd_driver = {
+ 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);
+ }
--/* 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 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 int __init init (void)
+ static void u132_hcd_monitor_work(struct work_struct *work)
{
-- int retval;
-+ int retval = -ENOMEM;
+- 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;
++ }
++ }
+ }
- if (usb_disabled ())
- return -ENODEV;
+ 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;
+ }
-- 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;
+ 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);
+ }
-- 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;
+ 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;
+ }
-- 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;
+ 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);
+ }
--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;
+ 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);
}
- module_init (init);
- static void __exit cleanup (void)
+ 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))
{
-- 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);
+- 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);
}
- 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 @@
+ 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);
+ }
- /* 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
+@@ -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;
++ }
+ }
-@@ -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 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 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;
+ 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;
++ }
+ }
-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;
+ 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;
++ }
+ }
-- DEBUG (dev, "%s\n", __FUNCTION__);
-+ DEBUG (dev, "%s\n", __func__);
+ 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;
++ }
+ }
- 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;
+ 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;
++ }
+ }
-- DEBUG (dev, "%s, flush old status first\n", __FUNCTION__);
-+ DEBUG (dev, "%s, flush old status first\n", __func__);
+ 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;
++ }
+ }
- /* 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);
+ 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;
++ }
}
-@@ -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 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 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 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 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 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;
++ }
}
--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)
+@@ -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 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;
+- 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;
++ }
}
-@@ -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)
+ static void u132_hcd_endp_work_scheduler(struct work_struct *work)
{
- 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);
+- 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
-@@ -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)
+ static void port_power(struct u132 *u132, int pn, int is_on)
{
- 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);
+- u132->port[pn].power = is_on;
++ u132->port[pn].power = is_on;
}
-@@ -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);
+ #endif
- /* Flush FIFO */
- flush(ep);
-@@ -734,7 +734,7 @@ static void flush_all(struct lh7a40x_udc *dev)
- */
- static void flush(struct lh7a40x_ep *ep)
+ static void u132_power(struct u132 *u132, int is_on)
{
-- 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;
+- 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;
++ }
}
-@@ -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)
+ static int u132_periodic_reinit(struct u132 *u132)
{
-- 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);
+- 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;
+ }
- /* 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)
+ static char *hcfs2string(int state)
{
-- 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);
+- 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 "?";
+ }
- /* 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)
+ static int u132_init(struct u132 *u132)
{
- 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);
+- 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;
}
-@@ -1970,7 +1970,7 @@ static const struct usb_gadget_ops lh7a40x_udc_ops = {
- static void nop_release(struct device *dev)
+@@ -1613,280 +1603,278 @@ static int u132_init(struct u132 *u132)
+ */
+ static int u132_run(struct u132 *u132)
{
-- DEBUG("%s %s\n", __FUNCTION__, dev->bus_id);
-+ DEBUG("%s %s\n", __func__, dev->bus_id);
+- 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 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)
+ static void u132_hcd_stop(struct usb_hcd *hcd)
{
-- 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);
+- 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);
++ }
}
-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);
- }
+ 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;
++ }
}
--#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)
+ static int u132_hcd_reset(struct usb_hcd *hcd)
{
-- 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;
+- 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;
++ }
}
-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)
+ 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);
- /* 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;
+- if (!endp) {
+- return -ENOMEM;
+- }
++ if (!endp)
++ return -ENOMEM;
- /* 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);
- }
+ 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,
-@@ -494,6 +499,39 @@ printer_close(struct inode *inode, struct file *fd)
- return 0;
+ 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;
}
-+/* This function must be called with interrupts turned off. */
-+static void
-+setup_rx_reqs(struct printer_dev *dev)
+ 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)
+{
-+ 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;
++ 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(&req->list, &dev->rx_reqs_active);
++ list_add_tail(&urbq->urb_more, &endp->urb_more);
++ urbq->urb = urb;
+ }
+ }
-+}
-+
- 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);
++ return 0;
}
-@@ -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;
- }
+ 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);
- 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;
- }
+- if (!endp) {
+- return -ENOMEM;
+- }
++ if (!endp)
++ return -ENOMEM;
-@@ -283,7 +283,7 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep)
+ 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,
- 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);
+ 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
-@@ -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);
+ 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;
}
- /* 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)
+ 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)
{
-- DBG("%s:\n", __FUNCTION__ );
-+ DBG("%s:\n", __func__ );
- if (!vendorDescr) return -1;
- if (configNr >= RNDIS_MAX_CONFIGS) return -1;
+- 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);
-@@ -1207,7 +1207,7 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
+- if (!endp) {
+- return -ENOMEM;
+- }
++ if (!endp)
++ return -ENOMEM;
- 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;
+ 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,
- 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 */
+ 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;
++ }
+ }
--int __devinit rndis_init (void)
-+int __init rndis_init (void)
+ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+ gfp_t mem_flags)
{
- 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);
+- 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(&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;
+- 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);
++ }
++ }
}
-@@ -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;
+ 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;
}
- */
--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
+ 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;
--/* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
+- 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);
- /* 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;
+ 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;
-+ /* FIXME we only want one one probe() not two */
- return usb_hcd_fsl_probe(&ehci_fsl_hc_driver, pdev);
+ 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;
++ }
++ }
}
-@@ -338,12 +337,12 @@ static int ehci_fsl_drv_remove(struct platform_device *pdev)
+ static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
{
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
+- 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);
++ }
++ }
+ }
-+ /* FIXME we only want one one remove() not two */
- usb_hcd_fsl_remove(hcd, pdev);
--
- return 0;
+ 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);
++ }
}
--MODULE_ALIAS("fsl-ehci");
-+MODULE_ALIAS("platform:fsl-ehci");
+ 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 struct platform_driver ehci_fsl_driver = {
- .probe = ehci_fsl_drv_probe,
-@@ -351,5 +350,5 @@ static struct platform_driver ehci_fsl_driver = {
- .shutdown = usb_hcd_platform_shutdown,
- .driver = {
- .name = "fsl-ehci",
-- },
-+ },
- };
-diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
-index 46ee7f4..369a8a5 100644
---- a/drivers/usb/host/ehci-hcd.c
-+++ b/drivers/usb/host/ehci-hcd.c
-@@ -57,35 +57,6 @@
- * Special thanks to Intel and VIA for providing host controllers to
- * test this driver on, and Cypress (including In-System Design) for
- * providing early devices for those host controllers to talk to!
-- *
-- * HISTORY:
-- *
-- * 2004-05-10 Root hub and PCI suspend/resume support; remote wakeup. (db)
-- * 2004-02-24 Replace pci_* with generic dma_* API calls (dsaxena at plexity.net)
-- * 2003-12-29 Rewritten high speed iso transfer support (by Michal Sojka,
-- * <sojkam at centrum.cz>, updates by DB).
-- *
-- * 2002-11-29 Correct handling for hw async_next register.
-- * 2002-08-06 Handling for bulk and interrupt transfers is mostly shared;
-- * only scheduling is different, no arbitrary limitations.
-- * 2002-07-25 Sanity check PCI reads, mostly for better cardbus support,
-- * clean up HC run state handshaking.
-- * 2002-05-24 Preliminary FS/LS interrupts, using scheduling shortcuts
-- * 2002-05-11 Clear TT errors for FS/LS ctrl/bulk. Fill in some other
-- * missing pieces: enabling 64bit dma, handoff from BIOS/SMM.
-- * 2002-05-07 Some error path cleanups to report better errors; wmb();
-- * use non-CVS version id; better iso bandwidth claim.
-- * 2002-04-19 Control/bulk/interrupt submit no longer uses giveback() on
-- * errors in submit path. Bugfixes to interrupt scheduling/processing.
-- * 2002-03-05 Initial high-speed ISO support; reduce ITD memory; shift
-- * more checking to generic hcd framework (db). Make it work with
-- * Philips EHCI; reduce PCI traffic; shorten IRQ path (Rory Bolt).
-- * 2002-01-14 Minor cleanup; version synch.
-- * 2002-01-08 Fix roothub handoff of FS/LS to companion controllers.
-- * 2002-01-04 Control/Bulk queuing behaves.
-- *
-- * 2001-12-12 Initial patch version for Linux 2.5.1 kernel.
-- * 2001-June Works with usb-storage and NEC EHCI on 2.4
- */
+ 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;
+ }
- #define DRIVER_VERSION "10 Dec 2004"
-@@ -95,7 +66,7 @@
- static const char hcd_name [] = "ehci_hcd";
+ 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;
++ }
+ }
--#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;
+@@ -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 handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr,
-+ u32 mask, u32 done, int usec)
+ 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)
+{
-+ 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);
++ 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;
++ }
++ }
}
- /*-------------------------------------------------------------------------*/
-@@ -355,17 +331,13 @@ static void ehci_turn_off_all_ports(struct ehci_hcd *ehci)
- &ehci->regs->port_status[port]);
+ 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;
++ }
}
--/* 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);
+ /* 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;
++ }
}
-+/* 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)
+ 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 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);
++ 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;
++ }
}
-+/*
-+ * Called when the ehci_hcd module is removed.
-+ */
- static void ehci_stop (struct usb_hcd *hcd)
+ static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num)
{
- 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);
+- 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;
+-}
-
- /* 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);
+-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;
+ }
-+ 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);
+ #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;
+-}
-
- 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;
+-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;
}
-@@ -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
+ 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;
+ }
--#ifdef CONFIG_ARCH_ORION
-+#ifdef CONFIG_PLAT_ORION
- #include "ehci-orion.c"
- #define PLATFORM_DRIVER ehci_orion_driver
+ #else
+-#define u132_hcd_suspend NULL
+-#define u132_hcd_resume NULL
+ #define u132_bus_suspend NULL
+ #define u132_bus_resume NULL
#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 @@
+ 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;
+ }
--#ifdef CONFIG_USB_PERSIST
-+#define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
+ 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;
+
-+#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;
++ while (o-- > 0)
++ udev->endp_number_out[o] = 0;
++
++ }
++ while (endps-- > 0)
++ u132->endp[endps] = NULL;
++
++ mutex_unlock(&u132->sw_lock);
++ return;
}
--#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)
+ static int __devinit u132_probe(struct platform_device *pdev)
{
- 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;
+- 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;
++ }
++ }
}
-@@ -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;
+@@ -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;
--#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);
+ switch (state.event) {
+ case PM_EVENT_FREEZE:
+- retval = u132_bus_suspend(hcd);
++ retval = u132_bus_suspend(hcd);
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;
+ 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;
++ }
}
--MODULE_ALIAS("ixp4xx-ehci");
-+MODULE_ALIAS("platform:ixp4xx-ehci");
+ 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;
++ }
+ }
- static struct platform_driver ixp4xx_ehci_driver = {
- .probe = ixp4xx_ehci_probe,
- .remove = ixp4xx_ehci_remove,
- .driver = {
- .name = "ixp4xx-ehci",
-- .bus = &platform_bus_type
- },
+ #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,
++ },
};
-diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
-index e129981..d187d03 100644
---- a/drivers/usb/host/ehci-orion.c
-+++ b/drivers/usb/host/ehci-orion.c
-@@ -11,15 +11,18 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
--#include <asm/arch/orion.h>
-+#include <linux/mbus.h>
-+#include <asm/plat-orion/ehci-orion.h>
-
- #define rdl(off) __raw_readl(hcd->regs + (off))
- #define wrl(off, val) __raw_writel((val), hcd->regs + (off))
+ 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;
+ }
--#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)
+ module_init(u132_hcd_init);
+ static void __exit u132_hcd_exit(void)
{
-+ 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;
+- 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);
+ }
- /*
-+ * (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;
+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 (!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)
+- /* 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;
- /* here we "know" root ports should always stay powered */
- ehci_port_power(ehci, 1);
-- ehci_handover_companion_ports(ehci);
+ 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");
- 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;
+ uhci_get_current_frame_number(uhci);
-+ /* 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)
+@@ -342,7 +335,7 @@ __releases(uhci->lock)
+ __acquires(uhci->lock)
{
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ 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)" : "");
-+ /* FIXME we only want one one remove() not two */
- usb_ehci_ppc_soc_remove(hcd, pdev);
- return 0;
+@@ -737,12 +730,12 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
+ return rc;
}
--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;
- }
+-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->core.power.power_state = PMSG_ON;
- dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */
+- dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
++ dev_dbg(uhci_dev(uhci), "%s\n", __func__);
- 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);
+ spin_lock_irq(&uhci->lock);
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
+@@ -774,11 +767,11 @@ done:
+ return rc;
+ }
-@@ -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;
+-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);
- 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) {
+- dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
++ dev_dbg(uhci_dev(uhci), "%s\n", __func__);
-+ /* 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;
+ /* 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);
- /* 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;
+ 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
-+ /* scan the whole queue for unlinks whenever it stops */
- } else {
- stopped = 1;
+ 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 )
-- 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;
+ #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,
-- /* 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;
-- }
+ new_desc->usb_dev = dev;
+ new_desc->usb_intf = intf;
+- init_MUTEX(&new_desc->lock);
-- /* 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:
- }
- }
+ /* 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;
-- /* 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;
+ struct Scsi_Host * host;
+- struct semaphore lock;
-+ /* 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;
+ 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.
-@@ -568,8 +594,10 @@ qh_urb_transaction (
- list_add_tail (&qtd->qtd_list, head);
- }
+ 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.
-- /* 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);
+ 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.
-+ /* 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;
-- }
+ config USB_RIO500
+- tristate "USB Diamond Rio500 support (EXPERIMENTAL)"
+- depends on USB && EXPERIMENTAL
++ tristate "USB Diamond Rio500 support"
++ depends on USB
+ help
+ Say Y here if you want to connect a USB Rio500 mp3 player to your
+ computer's USB port. Please read <file:Documentation/usb/rio.txt>
+@@ -64,8 +64,8 @@ config USB_RIO500
+ module will be called rio500.
- 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;
-- }
+ 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.
- 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;
-+ }
- }
+ 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;
-- 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;
-+ }
- }
+- dbg(2," %s : enter", __FUNCTION__);
++ dbg(2," %s : enter", __func__);
-- 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;
+ if (dev->udev == NULL) {
+- dbg(1," %s : udev is null", __FUNCTION__);
++ dbg(1," %s : udev is null", __func__);
+ goto exit;
}
-@@ -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;
+@@ -172,12 +172,12 @@ static void adu_abort_transfers(struct adu_device *dev)
+ spin_unlock_irqrestore(&dev->buflock, flags);
- 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;
+ exit:
+- dbg(2," %s : leave", __FUNCTION__);
++ dbg(2," %s : leave", __func__);
}
-@@ -1672,8 +1663,7 @@ static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
- */
- static int isp116x_resume(struct platform_device *dev)
+ static void adu_delete(struct adu_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;
- }
+- dbg(2, "%s enter", __FUNCTION__);
++ dbg(2, "%s enter", __func__);
-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();
+ /* 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);
-+ ohci_finish_controller_resume(hcd);
- return 0;
+- dbg(2, "%s : leave", __FUNCTION__);
++ dbg(2, "%s : leave", __func__);
}
- #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_
+ 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;
- ep93xx_stop_hc(&pdev->dev);
- hcd->state = HC_STATE_SUSPENDED;
-- pdev->dev.power.power_state = PMSG_SUSPEND;
+- 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);
- return 0;
- }
-@@ -193,9 +191,8 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
- ohci->next_statechange = jiffies;
+ 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);
- ep93xx_start_hc(&pdev->dev);
-- pdev->dev.power.power_state = PMSG_ON;
-- usb_hcd_resume_root_hub(hcd);
+ 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__);
+ }
+ }
-+ ohci_finish_controller_resume(hcd);
- return 0;
+@@ -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);
}
- #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)
+ 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;
-@@ -103,11 +91,11 @@ __acquires(ohci->lock)
- finish_unlinks (ohci, ohci_frame_no(ohci));
+- 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);
- /* 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;
+ 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:
-@@ -326,23 +314,76 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
- return rc;
+- 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);
}
-+/* 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) {
+ 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;
- 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;
- }
+- dbg(2,"%s : enter", __FUNCTION__);
++ dbg(2,"%s : enter", __func__);
- #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);
+ subminor = iminor(inode);
- /* 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);
- }
+ 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;
+ }
-+ /* 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.
-+ */
+ 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)
+ }
- 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)
+ ++dev->open_count;
+- dbg(2,"%s : open count %d", __FUNCTION__, dev->open_count);
++ dbg(2,"%s : open count %d", __func__, dev->open_count);
- omap_ohci_clock_power(0);
- ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
-- dev->dev.power.power_state = PMSG_SUSPEND;
- return 0;
+ /* 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 int ohci_omap_resume(struct platform_device *dev)
+ static void adu_release_internal(struct adu_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;
- }
+- dbg(2," %s : enter", __FUNCTION__);
++ dbg(2," %s : enter", __func__);
--#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
+ /* 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;
+ }
- 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;
+- dbg(2," %s : leave", __FUNCTION__);
++ dbg(2," %s : leave", __func__);
}
-@@ -345,9 +306,8 @@ static const struct hc_driver ohci_pci_hc_driver = {
- .shutdown = ohci_shutdown,
+ 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;
- #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
+- dbg(2," %s : enter", __FUNCTION__);
++ dbg(2," %s : enter", __func__);
- /*
-@@ -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;
+ if (file == NULL) {
+- dbg(1," %s : file is NULL", __FUNCTION__);
++ dbg(1," %s : file is NULL", __func__);
+ retval = -ENODEV;
+ goto exit;
}
-- 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_
+ 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 */
- pxa27x_stop_hc(&pdev->dev);
- hcd->state = HC_STATE_SUSPENDED;
-- pdev->dev.power.power_state = PMSG_SUSPEND;
+ 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)
- return 0;
+ 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;
}
-@@ -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);
+@@ -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);
- /* mask interrupts and disable power */
+- dbg(2," %s : enter, count = %Zd, file=%p", __FUNCTION__, count, file);
++ dbg(2," %s : enter, count = %Zd, file=%p", __func__, count, file);
-@@ -224,24 +224,26 @@ static int ohci_sm501_suspend(struct platform_device *pdev, pm_message_t msg)
+ dev = file->private_data;
+- dbg(2," %s : dev=%p", __FUNCTION__, dev);
++ dbg(2," %s : dev=%p", __func__, dev);
- 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;
- }
+ 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,
- 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);
+ /* 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;
+ }
- if (time_before(jiffies, ohci->next_statechange))
- msleep(5);
- ohci->next_statechange = jiffies;
+ 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);
- 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
+ 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);
- /*-------------------------------------------------------------------------*/
-@@ -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;
- }
+@@ -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);
--#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,
+ if (timeout <= 0) {
+- dbg(2," %s : timeout", __FUNCTION__);
++ dbg(2," %s : timeout", __func__);
+ retval = bytes_read ? bytes_read : -ETIMEDOUT;
+ goto exit;
+ }
--#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 = {
+ 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);
- .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)
+- dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
++ dbg(2," %s : leave, return value %d", __func__, retval);
+ return retval;
+ }
- ssb_device_enable(dev, ohcidev->enable_flags);
+@@ -565,7 +565,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
+ unsigned long flags;
+ int retval;
-+ ohci_finish_controller_resume(hcd);
- return 0;
- }
+- dbg(2," %s : enter, count = %Zd", __FUNCTION__, count);
++ dbg(2," %s : enter, count = %Zd", __func__, count);
-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;
- }
+ dev = file->private_data;
-@@ -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;
- }
+@@ -582,7 +582,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
- 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;
+ /* 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;
}
- 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"
+@@ -595,13 +595,13 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
- static const char hcd_name[] = "r8a66597_hcd";
+ 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;
+ }
- /* 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
+- 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);
- 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);
- }
+ /* 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);
--static int enable_controller(struct r8a66597 *r8a66597)
-+static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
- {
- u16 tmp;
- int i = 0;
+ 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;
-+#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));
-+}
+ exit_onqueue:
+@@ -706,7 +706,7 @@ static int adu_probe(struct usb_interface *interface,
+ int out_end_size;
+ int i;
-- 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;
+- dbg(2," %s : enter", __FUNCTION__);
++ dbg(2," %s : enter", __func__);
- r8a66597_bset(r8a66597, vif & LDRV, PINCFG);
-- r8a66597_bset(r8a66597, HSE, SYSCFG0);
-- r8a66597_bset(r8a66597, HSE, SYSCFG1);
- r8a66597_bset(r8a66597, USBE, SYSCFG0);
+ 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);
- 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);
+ /* 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);
-- 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);
+ return retval;
- 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);
+@@ -847,7 +847,7 @@ static void adu_disconnect(struct usb_interface *interface)
+ struct adu_device *dev;
+ int minor;
- return 0;
- }
+- dbg(2," %s : enter", __FUNCTION__);
++ dbg(2," %s : enter", __func__);
- static void disable_controller(struct r8a66597 *r8a66597)
- {
-- u16 tmp;
-+ int port;
+ dev = usb_get_intfdata(interface);
- 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);
+@@ -861,7 +861,7 @@ static void adu_disconnect(struct usb_interface *interface)
+ usb_set_intfdata(interface, NULL);
-- 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);
+ /* 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);
-- 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);
- }
+@@ -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));
- 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);
+- dbg(2," %s : leave", __FUNCTION__);
++ dbg(2," %s : leave", __func__);
}
--
--
- /* 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)
+ /* usb specific object needed to register this driver with the usb subsystem */
+@@ -885,7 +885,7 @@ static int __init adu_init(void)
{
-+#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
- int i;
- struct r8a66597_pipe_info *info = &pipe->info;
+ int result;
-@@ -742,6 +779,7 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
- break;
- }
- }
-+#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
- }
+- dbg(2," %s : enter", __FUNCTION__);
++ dbg(2," %s : enter", __func__);
- /* 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;
- }
+ /* 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");
-+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)
+ exit:
+- dbg(2," %s : leave, return value %d", __FUNCTION__, result);
++ dbg(2," %s : leave, return value %d", __func__, result);
+
+ return result;
}
- /* 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)
+ static void __exit adu_exit(void)
{
-- 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)
- }
+- 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__);
}
-+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];
+ module_init(adu_init);
+diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
+index 1cb56f2..a076c24 100644
+--- a/drivers/usb/misc/appledisplay.c
++++ b/drivers/usb/misc/appledisplay.c
+@@ -29,7 +29,6 @@
+ #include <linux/timer.h>
+ #include <linux/workqueue.h>
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
- 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);
- }
+ #define APPLE_VENDOR_ID 0x05AC
- 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);
+@@ -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;
}
-+ 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);
- }
+@@ -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);
}
}
-+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)
+diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
+index df7e1ec..0939386 100644
+--- a/drivers/usb/misc/auerswald.c
++++ b/drivers/usb/misc/auerswald.c
+@@ -31,6 +31,7 @@
+ #include <linux/init.h>
+ #include <linux/wait.h>
+ #include <linux/usb.h>
++#include <linux/mutex.h>
+
+ /*-------------------------------------------------------------------*/
+ /* Debug support */
+@@ -232,7 +233,7 @@ typedef struct auerscon
+ /* USB device context */
+ typedef struct
{
- struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
-@@ -1763,10 +1859,17 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd,
- urb->hcpriv = td;
+- 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;
- 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)
+ /* 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)
{
-- pdev->dev.power.power_state = state;
- return 0;
- }
+- 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");
- static int r8a66597_resume(struct platform_device *pdev)
+@@ -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)
{
-- 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);
+- 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;
}
- 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)
+@@ -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);
+ }
- struct r8a66597_pipe_info {
-+ unsigned long timer_interval;
- u16 pipenum;
- u16 address; /* R8A66597 HCD usb address */
- u16 epnum;
-@@ -478,9 +488,11 @@ struct r8a66597 {
+ /* 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;
+ }
- struct timer_list rh_timer;
- struct timer_list td_timer[R8A66597_MAX_NUM_PIPE];
-+ struct timer_list interval_timer[R8A66597_MAX_NUM_PIPE];
+@@ -1389,8 +1390,8 @@ static int auerchar_open (struct inode *inode, struct file *file)
+ }
- unsigned short address_map;
- unsigned short timeout_map;
-+ unsigned short interval_map;
- unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE];
- unsigned char dma_map;
+ /* 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);
-@@ -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
+ /* 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");
- 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;
+ /* 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;
+ }
- len = len / 2;
-@@ -549,6 +592,7 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
- buf = &buf[len];
- outb((unsigned char)*buf, fifoaddr);
+ /* Check for removal */
+ if (!cp->usbdev) {
+- up(&cp->mutex);
+- up(&ccp->mutex);
++ mutex_unlock(&cp->mutex);
++ mutex_unlock(&ccp->mutex);
+ return -ENODEV;
}
-+#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;
+@@ -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;
}
-+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)
+@@ -1574,18 +1575,18 @@ static ssize_t auerchar_read (struct file *file, char __user *buf, size_t count,
+ return 0;
- 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;
+ /* 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;
}
- 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;
- }
+ /* 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;
+ }
-@@ -1772,8 +1770,6 @@ sl811h_suspend(struct platform_device *dev, pm_message_t state)
- port_power(sl811, 0);
- break;
+@@ -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;
+ }
}
-- if (retval == 0)
-- dev->dev.power.power_state = state;
- return retval;
- }
+@@ -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 */
+ }
-@@ -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;
+ /* 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;
}
-- dev->dev.power.power_state = PMSG_ON;
- return sl811h_bus_resume(hcd);
- }
+ /* Anything left to read? */
+ if ((ccp->scontext.id == AUH_UNASSIGNED) || ccp->removed) {
+- up (&ccp->readmutex);
++ mutex_unlock(&ccp->readmutex);
+ return -EIO;
+ }
-diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
-index 8e117a7..f293074 100644
---- a/drivers/usb/host/u132-hcd.c
-+++ b/drivers/usb/host/u132-hcd.c
-@@ -67,7 +67,7 @@
- #include "ohci.h"
- #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
- #define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \
-- OHCI_INTR_WDH)
-+ OHCI_INTR_WDH)
- MODULE_AUTHOR("Tony Olech - Elan Digital Systems Limited");
- MODULE_DESCRIPTION("U132 USB Host Controller Driver");
- MODULE_LICENSE("GPL");
-@@ -77,15 +77,15 @@ INT_MODULE_PARM(testing, 0);
- static int distrust_firmware = 1;
- module_param(distrust_firmware, bool, 0);
- MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
-- "t setup");
-+ "t setup");
- static DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
- /*
- * u132_module_lock exists to protect access to global variables
- *
- */
- static struct mutex u132_module_lock;
--static int u132_exiting = 0;
--static int u132_instances = 0;
-+static int u132_exiting;
-+static int u132_instances;
- static struct list_head u132_static_list;
- /*
- * end of the global variables protected by u132_module_lock
-@@ -97,115 +97,115 @@ static struct workqueue_struct *workqueue;
- #define MAX_U132_ENDPS 100
- #define MAX_U132_RINGS 4
- static const char *cc_to_text[16] = {
-- "No Error ",
-- "CRC Error ",
-- "Bit Stuff ",
-- "Data Togg ",
-- "Stall ",
-- "DevNotResp ",
-- "PIDCheck ",
-- "UnExpPID ",
-- "DataOver ",
-- "DataUnder ",
-- "(for hw) ",
-- "(for hw) ",
-- "BufferOver ",
-- "BuffUnder ",
-- "(for HCD) ",
-- "(for HCD) "
-+ "No Error ",
-+ "CRC Error ",
-+ "Bit Stuff ",
-+ "Data Togg ",
-+ "Stall ",
-+ "DevNotResp ",
-+ "PIDCheck ",
-+ "UnExpPID ",
-+ "DataOver ",
-+ "DataUnder ",
-+ "(for hw) ",
-+ "(for hw) ",
-+ "BufferOver ",
-+ "BuffUnder ",
-+ "(for HCD) ",
-+ "(for HCD) "
- };
- struct u132_port {
-- struct u132 *u132;
-- int reset;
-- int enable;
-- int power;
-- int Status;
-+ struct u132 *u132;
-+ int reset;
-+ int enable;
-+ int power;
-+ int Status;
- };
- struct u132_addr {
-- u8 address;
-+ u8 address;
- };
- struct u132_udev {
-- struct kref kref;
-- struct usb_device *usb_device;
-- u8 enumeration;
-- u8 udev_number;
-- u8 usb_addr;
-- u8 portnumber;
-- u8 endp_number_in[16];
-- u8 endp_number_out[16];
-+ struct kref kref;
-+ struct usb_device *usb_device;
-+ u8 enumeration;
-+ u8 udev_number;
-+ u8 usb_addr;
-+ u8 portnumber;
-+ u8 endp_number_in[16];
-+ u8 endp_number_out[16];
- };
- #define ENDP_QUEUE_SHIFT 3
- #define ENDP_QUEUE_SIZE (1<<ENDP_QUEUE_SHIFT)
- #define ENDP_QUEUE_MASK (ENDP_QUEUE_SIZE-1)
- struct u132_urbq {
-- struct list_head urb_more;
-- struct urb *urb;
-+ struct list_head urb_more;
-+ struct urb *urb;
- };
- struct u132_spin {
-- spinlock_t slock;
-+ spinlock_t slock;
- };
- struct u132_endp {
-- struct kref kref;
-- u8 udev_number;
-- u8 endp_number;
-- u8 usb_addr;
-- u8 usb_endp;
-- struct u132 *u132;
-- struct list_head endp_ring;
-- struct u132_ring *ring;
-- unsigned toggle_bits:2;
-- unsigned active:1;
-- unsigned delayed:1;
-- unsigned input:1;
-- unsigned output:1;
-- unsigned pipetype:2;
-- unsigned dequeueing:1;
-- unsigned edset_flush:1;
-- unsigned spare_bits:14;
-- unsigned long jiffies;
-- struct usb_host_endpoint *hep;
-- struct u132_spin queue_lock;
-- u16 queue_size;
-- u16 queue_last;
-- u16 queue_next;
-- struct urb *urb_list[ENDP_QUEUE_SIZE];
-- struct list_head urb_more;
-- struct delayed_work scheduler;
-+ struct kref kref;
-+ u8 udev_number;
-+ u8 endp_number;
-+ u8 usb_addr;
-+ u8 usb_endp;
-+ struct u132 *u132;
-+ struct list_head endp_ring;
-+ struct u132_ring *ring;
-+ unsigned toggle_bits:2;
-+ unsigned active:1;
-+ unsigned delayed:1;
-+ unsigned input:1;
-+ unsigned output:1;
-+ unsigned pipetype:2;
-+ unsigned dequeueing:1;
-+ unsigned edset_flush:1;
-+ unsigned spare_bits:14;
-+ unsigned long jiffies;
-+ struct usb_host_endpoint *hep;
-+ struct u132_spin queue_lock;
-+ u16 queue_size;
-+ u16 queue_last;
-+ u16 queue_next;
-+ struct urb *urb_list[ENDP_QUEUE_SIZE];
-+ struct list_head urb_more;
-+ struct delayed_work scheduler;
- };
- struct u132_ring {
-- unsigned in_use:1;
-- unsigned length:7;
-- u8 number;
-- struct u132 *u132;
-- struct u132_endp *curr_endp;
-- struct delayed_work scheduler;
-+ unsigned in_use:1;
-+ unsigned length:7;
-+ u8 number;
-+ struct u132 *u132;
-+ struct u132_endp *curr_endp;
-+ struct delayed_work scheduler;
- };
- struct u132 {
-- struct kref kref;
-- struct list_head u132_list;
-- struct mutex sw_lock;
-- struct semaphore scheduler_lock;
-- struct u132_platform_data *board;
-- struct platform_device *platform_dev;
-- struct u132_ring ring[MAX_U132_RINGS];
-- int sequence_num;
-- int going;
-- int power;
-- int reset;
-- int num_ports;
-- u32 hc_control;
-- u32 hc_fminterval;
-- u32 hc_roothub_status;
-- u32 hc_roothub_a;
-- u32 hc_roothub_portstatus[MAX_ROOT_PORTS];
-- int flags;
-- unsigned long next_statechange;
-- struct delayed_work monitor;
-- int num_endpoints;
-- struct u132_addr addr[MAX_U132_ADDRS];
-- struct u132_udev udev[MAX_U132_UDEVS];
-- struct u132_port port[MAX_U132_PORTS];
-- struct u132_endp *endp[MAX_U132_ENDPS];
-+ struct kref kref;
-+ struct list_head u132_list;
-+ struct mutex sw_lock;
-+ struct mutex scheduler_lock;
-+ struct u132_platform_data *board;
-+ struct platform_device *platform_dev;
-+ struct u132_ring ring[MAX_U132_RINGS];
-+ int sequence_num;
-+ int going;
-+ int power;
-+ int reset;
-+ int num_ports;
-+ u32 hc_control;
-+ u32 hc_fminterval;
-+ u32 hc_roothub_status;
-+ u32 hc_roothub_a;
-+ u32 hc_roothub_portstatus[MAX_ROOT_PORTS];
-+ int flags;
-+ unsigned long next_statechange;
-+ struct delayed_work monitor;
-+ int num_endpoints;
-+ struct u132_addr addr[MAX_U132_ADDRS];
-+ struct u132_udev udev[MAX_U132_UDEVS];
-+ struct u132_port port[MAX_U132_PORTS];
-+ struct u132_endp *endp[MAX_U132_ENDPS];
- };
+- if (down_interruptible (&ccp->mutex)) {
+- up (&ccp->readmutex);
++ if (mutex_lock_interruptible(&ccp->mutex)) {
++ mutex_unlock(&ccp->readmutex);
+ return -ERESTARTSYS;
+ }
- /*
-@@ -213,34 +213,34 @@ struct u132 {
- * Does anyone have a better way?????
- */
- #define ftdi_read_pcimem(pdev, member, data) usb_ftdi_elan_read_pcimem(pdev, \
-- offsetof(struct ohci_regs, member), 0, data);
-+ offsetof(struct ohci_regs, member), 0, data);
- #define ftdi_write_pcimem(pdev, member, data) usb_ftdi_elan_write_pcimem(pdev, \
-- offsetof(struct ohci_regs, member), 0, data);
-+ offsetof(struct ohci_regs, member), 0, data);
- #define u132_read_pcimem(u132, member, data) \
-- usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
-- ohci_regs, member), 0, data);
-+ usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
-+ ohci_regs, member), 0, data);
- #define u132_write_pcimem(u132, member, data) \
-- usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
-- ohci_regs, member), 0, data);
-+ usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
-+ ohci_regs, member), 0, data);
- static inline struct u132 *udev_to_u132(struct u132_udev *udev)
- {
-- u8 udev_number = udev->udev_number;
-- return container_of(udev, struct u132, udev[udev_number]);
-+ u8 udev_number = udev->udev_number;
-+ return container_of(udev, struct u132, udev[udev_number]);
- }
+@@ -1707,27 +1708,27 @@ static ssize_t auerchar_write (struct file *file, const char __user *buf, size_t
- static inline struct u132 *hcd_to_u132(struct usb_hcd *hcd)
- {
-- return (struct u132 *)(hcd->hcd_priv);
-+ return (struct u132 *)(hcd->hcd_priv);
- }
+ write_again:
+ /* get the mutex */
+- if (down_interruptible (&ccp->mutex))
++ if (mutex_lock_interruptible(&ccp->mutex))
+ return -ERESTARTSYS;
- 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);
- }
+ /* Can we expect to write something? */
+ if (ccp->scontext.id == AUH_UNASSIGNED) {
+- up (&ccp->mutex);
++ mutex_unlock(&ccp->mutex);
+ return -EIO;
+ }
- static inline void u132_disable(struct u132 *u132)
- {
-- u132_to_hcd(u132)->state = HC_STATE_HALT;
-+ u132_to_hcd(u132)->state = HC_STATE_HALT;
- }
+ 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);
-@@ -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);
- }
+ /* 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;
+ }
- static inline void u132_u132_put_kref(struct u132 *u132)
- {
-- kref_put(&u132->kref, u132_hcd_delete);
-+ kref_put(&u132->kref, u132_hcd_delete);
+@@ -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");
- static inline void u132_u132_init_kref(struct u132 *u132)
- {
-- kref_init(&u132->kref);
-+ kref_init(&u132->kref);
- }
+- 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);
- 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;
- }
+ return 0;
+@@ -1917,7 +1918,7 @@ static int auerswald_probe (struct usb_interface *intf,
+ }
- 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);
- }
+ /* 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);
- static inline void u132_udev_get_kref(struct u132 *u132, struct u132_udev *udev)
- {
-- kref_get(&udev->kref);
-+ kref_get(&udev->kref);
- }
+- down (&cp->mutex);
++ mutex_lock(&cp->mutex);
+ info ("device /dev/%s now disconnecting", cp->name);
- 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);
- }
+ /* Stop the interrupt endpoint */
+@@ -2057,16 +2058,18 @@ static void auerswald_disconnect (struct usb_interface *intf)
- 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);
- }
+ 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 u132_ring_requeue_work(struct u132 *u132, struct u132_ring *ring,
-- unsigned int delta)
-+ unsigned int delta)
+ static void ftdi_elan_write_bulk_callback(struct urb *urb)
{
-- 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;
- }
+- struct usb_ftdi *ftdi = (struct usb_ftdi *)urb->context;
++ struct usb_ftdi *ftdi = urb->context;
+ int status = urb->status;
- static void u132_ring_queue_work(struct u132 *u132, struct u132_ring *ring,
-- unsigned int delta)
-+ unsigned int delta)
+ 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)
{
-- kref_get(&u132->kref);
-- u132_ring_requeue_work(u132, ring, delta);
-- return;
-+ kref_get(&u132->kref);
-+ u132_ring_requeue_work(u132, ring, delta);
-+ return;
- }
+- 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);
- 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);
- }
+@@ -230,7 +230,7 @@ static void iowarrior_write_callback(struct urb *urb)
+ struct iowarrior *dev;
+ int status = urb->status;
- 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);
- }
+- 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)
- static inline void u132_endp_get_kref(struct u132 *u132, struct u132_endp *endp)
- {
-- kref_get(&endp->kref);
-+ kref_get(&endp->kref);
- }
+ 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);
- 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);
- }
+ 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)
- 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,
+ if (!interface) {
+ err("%s - error, can't find device for minor %d\n",
+- __FUNCTION__, subminor);
++ __func__, subminor);
+ return -ENODEV;
+ }
- 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);
- }
+@@ -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);
- static inline void u132_monitor_put_kref(struct u132 *u132)
+ if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
+ retval = -EFAULT;
+diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
+index 6664043..9370326 100644
+--- a/drivers/usb/misc/legousbtower.c
++++ b/drivers/usb/misc/legousbtower.c
+@@ -31,7 +31,7 @@
+ * - imported into lejos project
+ * - changed wake_up to wake_up_interruptible
+ * - changed to use lego0 rather than tower0
+- * - changed dbg() to use __func__ rather than deprecated __FUNCTION__
++ * - changed dbg() to use __func__ rather than deprecated __func__
+ * 2003-01-12 - 0.53 david (david at csse.uwa.edu.au)
+ * - changed read and write to write everything or
+ * timeout (from a patch by Chris Riesen and Brett Thaeler driver)
+@@ -49,7 +49,7 @@
+ * - added poll
+ * - forbid seeking
+ * - added nonblocking I/O
+- * - changed back __func__ to __FUNCTION__
++ * - changed back __func__ to __func__
+ * - read and log tower firmware version
+ * - reset tower on probe, avoids failure of first write
+ * 2004-03-09 - 0.7 Juergen Stuber <starblue at users.sourceforge.net>
+@@ -309,7 +309,7 @@ static inline void lego_usb_tower_debug_data (int level, const char *function, i
+ */
+ static inline void tower_delete (struct lego_usb_tower *dev)
{
-- kref_put(&u132->kref, u132_hcd_delete);
-+ kref_put(&u132->kref, u132_hcd_delete);
- }
+- dbg(2, "%s: enter", __FUNCTION__);
++ dbg(2, "%s: enter", __func__);
- 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)
+ tower_abort_transfers (dev);
- 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);
- }
+@@ -321,7 +321,7 @@ static inline void tower_delete (struct lego_usb_tower *dev)
+ kfree (dev->interrupt_out_buffer);
+ kfree (dev);
- 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;
+- dbg(2, "%s: leave", __FUNCTION__);
++ dbg(2, "%s: leave", __func__);
}
- 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;
- }
+@@ -337,7 +337,7 @@ static int tower_open (struct inode *inode, struct file *file)
+ struct tower_reset_reply reset_reply;
+ int result;
- 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);
- }
+- dbg(2, "%s: enter", __FUNCTION__);
++ dbg(2, "%s: enter", __func__);
- 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;
- }
+ nonseekable_open(inode, file);
+ subminor = iminor(inode);
+@@ -346,7 +346,7 @@ static int tower_open (struct inode *inode, struct file *file)
- 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);
- }
+ 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);
- 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);
- }
+ exit:
+- dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval);
++ dbg(2, "%s: leave, return value %d ", __func__, retval);
- 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);
+ return retval;
}
+@@ -437,12 +437,12 @@ static int tower_release (struct inode *inode, struct file *file)
+ struct lego_usb_tower *dev;
+ int retval = 0;
- 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);
- }
+- dbg(2, "%s: enter", __FUNCTION__);
++ dbg(2, "%s: enter", __func__);
+ dev = (struct lego_usb_tower *)file->private_data;
-@@ -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;
-+ }
- }
+ 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)
+ }
- 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;
-+ }
+ 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;
}
- 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;
-+ }
+@@ -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__);
}
- 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;
-+ }
+
+@@ -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;
- 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;
-+ }
+- 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;
}
- 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;
-+ }
+@@ -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;
- 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;
-+ }
+- 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);
}
- 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;
-+ }
+
+@@ -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);
}
- 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;
-+ }
+
+@@ -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__);
}
- 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;
-+ }
+
+@@ -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__);
- 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;
-+ }
+ /* deregister this driver with the USB subsystem */
+ usb_deregister (&tower_driver);
+
+- dbg(2, "%s: leave", __FUNCTION__);
++ dbg(2, "%s: leave", __func__);
}
- 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;
-+ }
+ 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
+-
/*
-@@ -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)
+ * 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)
{
-- 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;
-+ }
+ /* 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;
}
- static void u132_hcd_endp_work_scheduler(struct work_struct *work)
+-#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)
{
-- 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;
-+ }
-+ }
-+ }
+ 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;
}
- #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;
- }
+diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
+index c1e65df..2cffec8 100644
+--- a/drivers/usb/serial/Kconfig
++++ b/drivers/usb/serial/Kconfig
+@@ -20,8 +20,8 @@ menuconfig USB_SERIAL
+ if USB_SERIAL
+
+ config USB_SERIAL_CONSOLE
+- bool "USB Serial Console device support (EXPERIMENTAL)"
+- depends on USB_SERIAL=y && EXPERIMENTAL
++ bool "USB Serial Console device support"
++ depends on USB_SERIAL=y
+ ---help---
+ If you say Y here, it will be possible to use a USB to serial
+ converter port as the system console (the system console is the
+@@ -44,13 +44,11 @@ config USB_SERIAL_CONSOLE
+
+ config USB_EZUSB
+ bool "Functions for loading firmware on EZUSB chips"
+- depends on USB_SERIAL
+ help
+ Say Y here if you need EZUSB device support.
+
+ config USB_SERIAL_GENERIC
+ bool "USB Generic Serial Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to use the generic USB serial driver. Please
+ read <file:Documentation/usb/usb-serial.txt> for more information on
+@@ -59,8 +57,7 @@ config USB_SERIAL_GENERIC
+ properly.
+
+ config USB_SERIAL_AIRCABLE
+- tristate "USB AIRcable Bluetooth Dongle Driver (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB AIRcable Bluetooth Dongle Driver"
+ help
+ Say Y here if you want to use USB AIRcable Bluetooth Dongle.
+
+@@ -69,7 +66,6 @@ config USB_SERIAL_AIRCABLE
+
+ config USB_SERIAL_AIRPRIME
+ tristate "USB AirPrime CDMA Wireless Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to use a AirPrime CDMA Wireless PC card.
+
+@@ -77,8 +73,7 @@ config USB_SERIAL_AIRPRIME
+ module will be called airprime.
+
+ config USB_SERIAL_ARK3116
+- tristate "USB ARK Micro 3116 USB Serial Driver (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB ARK Micro 3116 USB Serial Driver"
+ help
+ Say Y here if you want to use a ARK Micro 3116 USB to Serial
+ device.
+@@ -88,7 +83,6 @@ config USB_SERIAL_ARK3116
+
+ config USB_SERIAL_BELKIN
+ tristate "USB Belkin and Peracom Single Port Serial Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to use a Belkin USB Serial single port
+ adaptor (F5U103 is one of the model numbers) or the Peracom single
+@@ -99,7 +93,6 @@ config USB_SERIAL_BELKIN
+
+ config USB_SERIAL_CH341
+ tristate "USB Winchiphead CH341 Single Port Serial Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to use a Winchiphead CH341 single port
+ USB to serial adapter.
+@@ -109,7 +102,6 @@ config USB_SERIAL_CH341
+
+ config USB_SERIAL_WHITEHEAT
+ tristate "USB ConnectTech WhiteHEAT Serial Driver"
+- depends on USB_SERIAL
+ select USB_EZUSB
+ help
+ Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
+@@ -120,7 +112,6 @@ config USB_SERIAL_WHITEHEAT
+
+ config USB_SERIAL_DIGI_ACCELEPORT
+ tristate "USB Digi International AccelePort USB Serial Driver"
+- depends on USB_SERIAL
+ ---help---
+ Say Y here if you want to use Digi AccelePort USB 2 or 4 devices,
+ 2 port (plus parallel port) and 4 port USB serial converters. The
+@@ -135,7 +126,6 @@ config USB_SERIAL_DIGI_ACCELEPORT
+
+ config USB_SERIAL_CP2101
+ tristate "USB CP2101 UART Bridge Controller"
+- depends on USB_SERIAL && EXPERIMENTAL
+ help
+ Say Y here if you want to use a CP2101/CP2102 based USB to RS232
+ converter.
+@@ -145,7 +135,6 @@ config USB_SERIAL_CP2101
+
+ config USB_SERIAL_CYPRESS_M8
+ tristate "USB Cypress M8 USB Serial Driver"
+- depends on USB_SERIAL && EXPERIMENTAL
+ help
+ Say Y here if you want to use a device that contains the Cypress
+ USB to Serial microcontroller, such as the DeLorme Earthmate GPS.
+@@ -160,7 +149,6 @@ config USB_SERIAL_CYPRESS_M8
+
+ config USB_SERIAL_EMPEG
+ tristate "USB Empeg empeg-car Mark I/II Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to connect to your Empeg empeg-car Mark I/II
+ mp3 player via USB. The driver uses a single ttyUSB{0,1,2,...}
+@@ -171,8 +159,7 @@ config USB_SERIAL_EMPEG
+ module will be called empeg.
+
+ config USB_SERIAL_FTDI_SIO
+- tristate "USB FTDI Single Port Serial Driver (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB FTDI Single Port Serial Driver"
+ ---help---
+ Say Y here if you want to use a FTDI SIO single port USB to serial
+ converter device. The implementation I have is called the USC-1000.
+@@ -186,7 +173,6 @@ config USB_SERIAL_FTDI_SIO
+
+ config USB_SERIAL_FUNSOFT
+ tristate "USB Fundamental Software Dongle Driver"
+- depends on USB_SERIAL
+ ---help---
+ Say Y here if you want to use the Fundamental Software dongle.
+
+@@ -195,7 +181,6 @@ config USB_SERIAL_FUNSOFT
+
+ config USB_SERIAL_VISOR
+ tristate "USB Handspring Visor / Palm m50x / Sony Clie Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to connect to your HandSpring Visor, Palm
+ m500 or m505 through its USB docking station. See
+@@ -207,7 +192,6 @@ config USB_SERIAL_VISOR
+
+ config USB_SERIAL_IPAQ
+ tristate "USB PocketPC PDA Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to connect to your Compaq iPAQ, HP Jornada
+ or any other PDA running Windows CE 3.0 or PocketPC 2002
+@@ -218,8 +202,7 @@ config USB_SERIAL_IPAQ
+ module will be called ipaq.
+
+ config USB_SERIAL_IR
+- tristate "USB IR Dongle Serial Driver (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB IR Dongle Serial Driver"
+ help
+ Say Y here if you want to enable simple serial support for USB IrDA
+ devices. This is useful if you do not want to use the full IrDA
+@@ -230,7 +213,6 @@ config USB_SERIAL_IR
+
+ config USB_SERIAL_EDGEPORT
+ tristate "USB Inside Out Edgeport Serial Driver"
+- depends on USB_SERIAL
+ ---help---
+ Say Y here if you want to use any of the following devices from
+ Inside Out Networks (Digi):
+@@ -256,7 +238,6 @@ config USB_SERIAL_EDGEPORT
+
+ config USB_SERIAL_EDGEPORT_TI
+ tristate "USB Inside Out Edgeport Serial Driver (TI devices)"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to use any of the devices from Inside Out
+ Networks (Digi) that are not supported by the io_edgeport driver.
+@@ -267,7 +248,6 @@ config USB_SERIAL_EDGEPORT_TI
+
+ config USB_SERIAL_GARMIN
+ tristate "USB Garmin GPS driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to connect to your Garmin GPS.
+ Should work with most Garmin GPS devices which have a native USB port.
+@@ -279,8 +259,7 @@ config USB_SERIAL_GARMIN
+ module will be called garmin_gps.
+
+ config USB_SERIAL_IPW
+- tristate "USB IPWireless (3G UMTS TDD) Driver (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB IPWireless (3G UMTS TDD) Driver"
+ help
+ Say Y here if you want to use a IPWireless USB modem such as
+ the ones supplied by Axity3G/Sentech South Africa.
+@@ -289,8 +268,7 @@ config USB_SERIAL_IPW
+ module will be called ipw.
+
+ config USB_SERIAL_IUU
+- tristate "USB Infinity USB Unlimited Phoenix Driver (Experimental)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB Infinity USB Unlimited Phoenix Driver"
+ help
+ Say Y here if you want to use a IUU in phoenix mode and get
+ an extra ttyUSBx device. More information available on
+@@ -301,7 +279,6 @@ config USB_SERIAL_IUU
+
+ config USB_SERIAL_KEYSPAN_PDA
+ tristate "USB Keyspan PDA Single Port Serial Driver"
+- depends on USB_SERIAL
+ select USB_EZUSB
+ help
+ Say Y here if you want to use a Keyspan PDA single port USB to
+@@ -405,8 +381,7 @@ config USB_SERIAL_KEYSPAN_USA49WLC
+ Say Y here to include firmware for the USA-49WLC converter.
+
+ config USB_SERIAL_KLSI
+- tristate "USB KL5KUSB105 (Palmconnect) Driver (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB KL5KUSB105 (Palmconnect) Driver"
+ ---help---
+ Say Y here if you want to use a KL5KUSB105 - based single port
+ serial adapter. The most widely known -- and currently the only
+@@ -422,7 +397,6 @@ config USB_SERIAL_KLSI
+
+ config USB_SERIAL_KOBIL_SCT
+ tristate "USB KOBIL chipcard reader"
+- depends on USB_SERIAL
+ ---help---
+ Say Y here if you want to use one of the following KOBIL USB chipcard
+ readers:
+@@ -440,7 +414,6 @@ config USB_SERIAL_KOBIL_SCT
+
+ config USB_SERIAL_MCT_U232
+ tristate "USB MCT Single Port Serial Driver"
+- depends on USB_SERIAL
+ ---help---
+ Say Y here if you want to use a USB Serial single port adapter from
+ Magic Control Technology Corp. (U232 is one of the model numbers).
+@@ -453,7 +426,6 @@ config USB_SERIAL_MCT_U232
+
+ config USB_SERIAL_MOS7720
+ tristate "USB Moschip 7720 Serial Driver"
+- depends on USB_SERIAL
+ ---help---
+ Say Y here if you want to use USB Serial single and double
+ port adapters from Moschip Semiconductor Tech.
+@@ -463,7 +435,6 @@ config USB_SERIAL_MOS7720
+
+ config USB_SERIAL_MOS7840
+ tristate "USB Moschip 7840/7820 USB Serial Driver"
+- depends on USB_SERIAL
+ ---help---
+ Say Y here if you want to use a MCS7840 Quad-Serial or MCS7820
+ Dual-Serial port device from MosChip Semiconductor.
+@@ -478,14 +449,12 @@ config USB_SERIAL_MOS7840
+
+ config USB_SERIAL_NAVMAN
+ tristate "USB Navman GPS device"
+- depends on USB_SERIAL
+ help
+ To compile this driver as a module, choose M here: the
+ module will be called navman.
+
+ config USB_SERIAL_PL2303
+ tristate "USB Prolific 2303 Single Port Serial Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to use the PL2303 USB Serial single port
+ adapter from Prolific.
+@@ -494,8 +463,7 @@ config USB_SERIAL_PL2303
+ module will be called pl2303.
+
+ config USB_SERIAL_OTI6858
+- tristate "USB Ours Technology Inc. OTi-6858 USB To RS232 Bridge Controller (EXPERIMENTAL)"
+- depends on USB_SERIAL
++ tristate "USB Ours Technology Inc. OTi-6858 USB To RS232 Bridge Controller"
+ help
+ Say Y here if you want to use the OTi-6858 single port USB to serial
+ converter device.
+@@ -503,9 +471,17 @@ config USB_SERIAL_OTI6858
+ To compile this driver as a module, choose M here: the
+ module will be called oti6858.
+
++config USB_SERIAL_SPCP8X5
++ tristate "USB SPCP8x5 USB To Serial Driver"
++ help
++ Say Y here if you want to use the spcp8x5 converter chip. This is
++ commonly found in some Z-Wave USB devices.
++
++ To compile this driver as a module, choose M here: the
++ module will be called spcp8x5.
++
+ config USB_SERIAL_HP4X
+ tristate "USB HP4x Calculators support"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to use an Hewlett-Packard 4x Calculator.
+
+@@ -513,8 +489,7 @@ config USB_SERIAL_HP4X
+ module will be called hp4x.
+
+ config USB_SERIAL_SAFE
+- tristate "USB Safe Serial (Encapsulated) Driver (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB Safe Serial (Encapsulated) Driver"
+
+ config USB_SERIAL_SAFE_PADDED
+ bool "USB Secure Encapsulated Driver - Padded"
+@@ -522,7 +497,6 @@ config USB_SERIAL_SAFE_PADDED
+
+ config USB_SERIAL_SIERRAWIRELESS
+ tristate "USB Sierra Wireless Driver"
+- depends on USB_SERIAL
+ help
+ Say M here if you want to use a Sierra Wireless device (if
+ using an PC 5220 or AC580 please use the Airprime driver
+@@ -533,7 +507,6 @@ config USB_SERIAL_SIERRAWIRELESS
+
+ config USB_SERIAL_TI
+ tristate "USB TI 3410/5052 Serial Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to use the TI USB 3410 or 5052
+ serial devices.
+@@ -542,8 +515,7 @@ config USB_SERIAL_TI
+ module will be called ti_usb_3410_5052.
+
+ config USB_SERIAL_CYBERJACK
+- tristate "USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB REINER SCT cyberJack pinpad/e-com chipcard reader"
+ ---help---
+ Say Y here if you want to use a cyberJack pinpad/e-com USB chipcard
+ reader. This is an interface to ISO 7816 compatible contact-based
+@@ -556,7 +528,6 @@ config USB_SERIAL_CYBERJACK
+
+ config USB_SERIAL_XIRCOM
+ tristate "USB Xircom / Entregra Single Port Serial Driver"
+- depends on USB_SERIAL
+ select USB_EZUSB
+ help
+ Say Y here if you want to use a Xircom or Entregra single port USB to
+@@ -568,7 +539,6 @@ config USB_SERIAL_XIRCOM
+
+ config USB_SERIAL_OPTION
+ tristate "USB driver for GSM and CDMA modems"
+- depends on USB_SERIAL
+ help
+ Say Y here if you have a GSM or CDMA modem that's connected to USB.
+
+@@ -586,8 +556,7 @@ config USB_SERIAL_OPTION
+ it might be accessible via the FTDI_SIO driver.
+
+ config USB_SERIAL_OMNINET
+- tristate "USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB ZyXEL omni.net LCD Plus Driver"
+ help
+ Say Y here if you want to use a ZyXEL omni.net LCD ISDN TA.
+
+@@ -596,7 +565,6 @@ config USB_SERIAL_OMNINET
+
+ config USB_SERIAL_DEBUG
+ tristate "USB Debugging Device"
+- depends on USB_SERIAL
+ help
+ Say Y here if you have a USB debugging device used to receive
+ debugging data from another machine. The most common of these
+diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
+index 0db109a..7568595 100644
+--- a/drivers/usb/serial/Makefile
++++ b/drivers/usb/serial/Makefile
+@@ -30,8 +30,8 @@ obj-$(CONFIG_USB_SERIAL_GARMIN) += garmin_gps.o
+ obj-$(CONFIG_USB_SERIAL_HP4X) += hp4x.o
+ obj-$(CONFIG_USB_SERIAL_IPAQ) += ipaq.o
+ obj-$(CONFIG_USB_SERIAL_IPW) += ipw.o
+-obj-$(CONFIG_USB_SERIAL_IUU) += iuu_phoenix.o
+ obj-$(CONFIG_USB_SERIAL_IR) += ir-usb.o
++obj-$(CONFIG_USB_SERIAL_IUU) += iuu_phoenix.o
+ obj-$(CONFIG_USB_SERIAL_KEYSPAN) += keyspan.o
+ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += keyspan_pda.o
+ obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o
+@@ -46,6 +46,7 @@ obj-$(CONFIG_USB_SERIAL_OTI6858) += oti6858.o
+ obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o
+ obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o
+ obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o
++obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o
+ obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o
+ obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o
+ obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o
+diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
+index 1cd29cd..9b1bb34 100644
+--- a/drivers/usb/serial/aircable.c
++++ b/drivers/usb/serial/aircable.c
+@@ -209,8 +209,8 @@ static void aircable_send(struct usb_serial_port *port)
+ int count, result;
+ struct aircable_private *priv = usb_get_serial_port_data(port);
+ unsigned char* buf;
+- u16 *dbuf;
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ __le16 *dbuf;
++ dbg("%s - port %d", __func__, port->number);
+ if (port->write_urb_busy)
+ return;
+
+@@ -220,14 +220,14 @@ 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;
+ }
+
+ buf[0] = TX_HEADER_0;
+ buf[1] = TX_HEADER_1;
+- dbuf = (u16 *)&buf[2];
++ dbuf = (__le16 *)&buf[2];
+ *dbuf = cpu_to_le16((u16)count);
+ serial_buf_get(priv->tx_buf,buf + HCI_HEADER_LENGTH, MAX_HCI_FRAMESIZE);
- #endif
+@@ -236,7 +236,7 @@ static void aircable_send(struct usb_serial_port *port)
- 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;
-+ }
- }
+ 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;
+ }
- 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;
- }
+@@ -275,7 +275,7 @@ static void aircable_read(struct work_struct *work)
- 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 "?";
- }
+ if (!tty) {
+ schedule_work(&priv->rx_work);
+- err("%s - No tty available", __FUNCTION__);
++ err("%s - No tty available", __func__);
+ 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;
- }
+@@ -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;
+ }
-@@ -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;
- }
+@@ -332,7 +332,7 @@ static int aircable_attach (struct usb_serial *serial)
- 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);
-+ }
- }
+ 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);
- 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;
-+ }
- }
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- 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;
-+ }
- }
+ 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;
- 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);
+- dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
++ dbg("%s - port %d, %d bytes", __func__, port->number, count);
-- if (!endp) {
-- return -ENOMEM;
-- }
-+ if (!endp)
-+ return -ENOMEM;
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, source);
++ usb_serial_debug_data(debug, &port->dev, __func__, count, source);
- 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,
+ if (!count){
+- dbg("%s - write request of 0 bytes", __FUNCTION__);
++ dbg("%s - write request of 0 bytes", __func__);
+ return count;
+ }
- 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;
- }
+@@ -414,7 +414,7 @@ static void aircable_write_bulk_callback(struct urb *urb)
+ int status = urb->status;
+ int result;
- 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;
+- 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;
}
- 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)
+@@ -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)
{
-- 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);
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
-- if (!endp) {
-- return -ENOMEM;
-- }
-+ if (!endp)
-+ return -ENOMEM;
+ 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,
- 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,
+ config = 0;
- 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;
- }
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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;
- }
+ 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;
+ }
- 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)
+@@ -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)
{
-- 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);
+ int retval = 0;
-- if (!endp) {
-- return -ENOMEM;
-- }
-+ if (!endp)
-+ return -ENOMEM;
+- dbg("%s port %d", __FUNCTION__, port->number);
++ dbg("%s port %d", __func__, port->number);
- 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,
+ /*Start reading from the device*/
+ /* TODO: Look at possibility of submitting multiple URBs to device to
+@@ -240,7 +237,7 @@ exit:
- 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 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);
- 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;
-+ }
- }
+ /* 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 int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
- gfp_t mem_flags)
+ static void belkin_sa_read_int_callback (struct urb *urb)
{
-- 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);
-+ }
-+ }
+- 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 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 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,
- 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;
+ 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;
+ }
-- 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;
+@@ -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;
}
-- 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;
+@@ -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;
+ }
- 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;
-+ }
-+ }
- }
+@@ -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;
+ }
- 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);
-+ }
-+ }
- }
+@@ -293,11 +293,11 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp)
+ struct usb_serial *serial = port->serial;
+ int result;
- 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);
-+ }
- }
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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;
-+ }
- }
+ if (cp2101_set_config_single(port, CP2101_UART, UART_ENABLE)) {
+ dev_err(&port->dev, "%s - Unable to enable UART\n",
+- __FUNCTION__);
++ __func__);
+ return -EPROTO;
+ }
- 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;
- }
+@@ -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;
+ }
- static int u132_roothub_status(struct u132 *u132, __le32 *desc)
+@@ -329,7 +329,7 @@ static void cp2101_cleanup (struct usb_serial_port *port)
{
-- 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;
- }
+ struct usb_serial *serial = port->serial;
- 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;
-+ }
- }
+- 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)
-@@ -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)
+ static void cp2101_close (struct usb_serial_port *port, struct file * filp)
{
-- 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;
- }
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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;
-+ }
-+ }
- }
+ /* 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);
- 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;
-+ }
- }
+@@ -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);
- /* the virtual root hub timer IRQ checks for hub status*/
- static int u132_hub_status_data(struct usb_hcd *hcd, char *buf)
+ 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,
{
-- 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;
-+ }
- }
+ int control = 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;
-+ }
- }
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num)
+ 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)
{
-- 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;
- }
+ int control, result;
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- #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)
+ 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)
{
-- 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;
+ 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;
- static int u132_bus_resume(struct usb_hcd *hcd)
+- 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)
{
-- 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;
- }
+ int i;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- #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,
- };
+- 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;
- /*
-@@ -3051,148 +2995,152 @@ static struct hc_driver u132_hc_driver = {
- */
- static int __devexit u132_remove(struct platform_device *pdev)
+- 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)
{
-- 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
+- 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;
- }
+ }
- 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;
- }
+ 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
- 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;
-+ }
-+ }
- }
+ 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;
+ }
-@@ -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;
+ /* Copy data */
+ memcpy (priv->wrbuf+priv->wrfilled, buf, count);
- 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;
-+ }
- }
+- 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;
- 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;
-+ }
- }
+ 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;
- #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;
- }
+- 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);
- module_init(u132_hcd_init);
- static void __exit u132_hcd_exit(void)
+ 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 )
{
-- 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);
++ /* FIXME: .... */
+ return CYBERJACK_LOCAL_BUF_SIZE;
}
-
-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)
+ static void cyberjack_read_int_callback( struct urb *urb )
{
- int auto_stop;
- int int_enable, egsm_enable;
-+ struct usb_device *rhdev = uhci_to_hcd(uhci)->self.root_hub;
+- 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;
- 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)" : ""));
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-- /* 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;
+ /* the urb might have been killed. */
+ if (status)
+ return;
- 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");
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
- uhci_get_current_frame_number(uhci);
+ /* 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;
-@@ -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)" : "");
+ /* 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;
-@@ -737,12 +730,12 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
- return rc;
- }
+- dbg("%s - rdtodo: %d", __FUNCTION__, priv->rdtodo);
++ dbg("%s - rdtodo: %d", __func__, priv->rdtodo);
--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;
+ spin_unlock(&priv->lock);
-- dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
-+ dev_dbg(uhci_dev(uhci), "%s\n", __func__);
+@@ -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__);
+ }
+ }
- spin_lock_irq(&uhci->lock);
- if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
-@@ -774,11 +767,11 @@ done:
- return rc;
+@@ -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 int uhci_resume(struct usb_hcd *hcd)
-+static int uhci_pci_resume(struct usb_hcd *hcd)
+ static void cyberjack_read_bulk_callback (struct urb *urb)
{
- struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-
-- dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
-+ dev_dbg(uhci_dev(uhci), "%s\n", __func__);
+- 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;
- /* 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);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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
+- 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;
+ }
- 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 )
+ 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)
- #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,
+ spin_unlock(&priv->lock);
- new_desc->usb_dev = dev;
- new_desc->usb_intf = intf;
-- init_MUTEX(&new_desc->lock);
+- dbg("%s - rdtodo: %d", __FUNCTION__, todo);
++ dbg("%s - rdtodo: %d", __func__, todo);
- /* 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;
+ /* 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__);
+ }
+ }
- struct Scsi_Host * host;
-- struct semaphore lock;
+ 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;
- 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.
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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.
+ port->write_urb_busy = 0;
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
- 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.
+@@ -430,7 +428,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
+ if( priv->wrfilled ) {
+ int length, blksize, result;
- config USB_RIO500
-- tristate "USB Diamond Rio500 support (EXPERIMENTAL)"
-- depends on USB && EXPERIMENTAL
-+ tristate "USB Diamond Rio500 support"
-+ depends on USB
- help
- Say Y here if you want to connect a USB Rio500 mp3 player to your
- computer's USB port. Please read <file:Documentation/usb/rio.txt>
-@@ -64,8 +64,8 @@ config USB_RIO500
- module will be called rio500.
+- dbg("%s - transmitting data (frame n)", __FUNCTION__);
++ dbg("%s - transmitting data (frame n)", __func__);
- 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.
+ 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;
+ }
- 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("%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);
-- dbg(2," %s : enter", __FUNCTION__);
-+ dbg(2," %s : enter", __func__);
+ blksize = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
- if (dev->udev == NULL) {
-- dbg(1," %s : udev is null", __FUNCTION__);
-+ dbg(1," %s : udev is null", __func__);
- goto exit;
+ 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;
+ }
}
-@@ -172,12 +172,12 @@ static void adu_abort_transfers(struct adu_device *dev)
- spin_unlock_irqrestore(&dev->buflock, flags);
+diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
+index 779d078..0230d3c 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,
+ };
- exit:
-- dbg(2," %s : leave", __FUNCTION__);
-+ dbg(2," %s : leave", __func__);
- }
++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 void adu_delete(struct adu_device *dev)
+
++static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate)
++{
++ struct cypress_private *priv;
++ priv = usb_get_serial_port_data(port);
++
++ /*
++ * The general purpose firmware for the Cypress M8 allows for
++ * a maximum speed of 57600bps (I have no idea whether DeLorme
++ * chose to use the general purpose firmware or not), if you
++ * need to modify this speed setting for your own project
++ * please add your own chiptype and modify the code likewise.
++ * The Cypress HID->COM device will work successfully up to
++ * 115200bps (but the actual throughput is around 3kBps).
++ */
++ if (port->serial->dev->speed == USB_SPEED_LOW) {
++ /*
++ * Mike Isely <isely at pobox.com> 2-Feb-2008: The
++ * Cypress app note that describes this mechanism
++ * states the the low-speed part can't handle more
++ * than 800 bytes/sec, in which case 4800 baud is the
++ * safest speed for a part like that.
++ */
++ if (new_rate > 4800) {
++ dbg("%s - failed setting baud rate, device incapable "
++ "speed %d", __func__, new_rate);
++ return -1;
++ }
++ }
++ switch (priv->chiptype) {
++ case CT_EARTHMATE:
++ if (new_rate <= 600) {
++ /* 300 and 600 baud rates are supported under
++ * the generic firmware, but are not used with
++ * NMEA and SiRF protocols */
++ dbg("%s - failed setting baud rate, unsupported speed "
++ "of %d on Earthmate GPS", __func__, new_rate);
++ return -1;
++ }
++ break;
++ default:
++ break;
++ }
++ return new_rate;
++}
++
++
+ /* This function can either set or retrieve the current serial line settings */
+-static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_mask, int data_bits, int stop_bits,
++static int cypress_serial_control (struct usb_serial_port *port, speed_t baud_rate, int data_bits, int stop_bits,
+ int parity_enable, int parity_type, int reset, int cypress_request_type)
{
-- dbg(2, "%s enter", __FUNCTION__);
-+ dbg(2, "%s enter", __func__);
+ int new_baudrate = 0, retval = 0, tries = 0;
+ struct cypress_private *priv;
+- __u8 feature_buffer[8];
++ __u8 feature_buffer[5];
+ unsigned long flags;
- /* 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("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ priv = usb_get_serial_port_data(port);
-- dbg(2, "%s : leave", __FUNCTION__);
-+ dbg(2, "%s : leave", __func__);
- }
+@@ -302,58 +339,23 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
- 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;
+ 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;
-- 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);
+@@ -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);
- 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);
+ if (tries++ >= 3)
+ break;
- 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__);
- }
- }
+- } while (retval != 8 && retval != -ENODEV);
++ } while (retval != sizeof(feature_buffer) &&
++ retval != -ENODEV);
-@@ -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);
- }
+- 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));
- 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;
+ 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;
-- 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);
+- } while (retval != 5 && retval != -ENODEV);
++ } while (retval != sizeof(feature_buffer) &&
++ retval != -ENODEV);
- if (status != 0) {
- if ((status != -ENOENT) &&
- (status != -ECONNRESET)) {
- dbg(1, " %s :nonzero status received: %d",
-- __FUNCTION__, status);
-+ __func__, status);
- }
- goto exit;
+- 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);
+ }
}
-@@ -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);
+@@ -447,51 +463,6 @@ static void cypress_set_dead(struct usb_serial_port *port)
}
- 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__);
+-/* 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];
- subminor = iminor(inode);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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;
+ 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];
- 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)
+- 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;
}
- ++dev->open_count;
-- dbg(2,"%s : open count %d", __FUNCTION__, dev->open_count);
-+ dbg(2,"%s : open count %d", __func__, dev->open_count);
+- 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 != cpu_to_le16(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;
++ }
- /* 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;
- }
+ return 0;
+ } /* cypress_earthmate_startup */
+@@ -565,10 +559,10 @@ static int cypress_hidcom_startup (struct usb_serial *serial)
+ {
+ struct cypress_private *priv;
- static void adu_release_internal(struct adu_device *dev)
+- 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)
{
-- dbg(2," %s : enter", __FUNCTION__);
-+ dbg(2," %s : enter", __func__);
+ struct cypress_private *priv;
- /* 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("%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(2," %s : leave", __FUNCTION__);
-+ dbg(2," %s : leave", __func__);
- }
+- dbg ("%s - port %d", __FUNCTION__, serial->port[0]->number);
++ dbg ("%s - port %d", __func__, serial->port[0]->number);
- 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;
+ /* all open ports are closed at this point */
-- dbg(2," %s : enter", __FUNCTION__);
-+ dbg(2," %s : enter", __func__);
+@@ -624,7 +618,7 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
+ unsigned long flags;
+ int result = 0;
- if (file == NULL) {
-- dbg(1," %s : file is NULL", __FUNCTION__);
-+ dbg(1," %s : file is NULL", __func__);
- retval = -ENODEV;
- goto exit;
- }
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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;
+ 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);
}
-@@ -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;
+@@ -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);
}
-@@ -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;
- }
+@@ -688,7 +682,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
+ long timeout;
+ wait_queue_t wait;
-@@ -405,10 +405,10 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
+- 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;
- DECLARE_WAITQUEUE(wait, current);
+
+- dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
++ dbg("%s - port %d, %d bytes", __func__, port->number, count);
-- dbg(2," %s : enter, count = %Zd, file=%p", __FUNCTION__, count, file);
-+ dbg(2," %s : enter, count = %Zd, file=%p", __func__, count, file);
+ /* 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;
- dev = file->private_data;
-- dbg(2," %s : dev=%p", __FUNCTION__, dev);
-+ dbg(2," %s : dev=%p", __func__, dev);
+- 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);
- 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,
+ 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;
+ }
- /* 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;
+ 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;
}
- 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);
+- 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;
+ }
- 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);
+- dbg("%s - count is %d", __FUNCTION__, count);
++ dbg("%s - count is %d", __func__, count);
-@@ -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);
+ 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);
- if (timeout <= 0) {
-- dbg(2," %s : timeout", __FUNCTION__);
-+ dbg(2," %s : timeout", __func__);
- retval = bytes_read ? bytes_read : -ETIMEDOUT;
- goto exit;
- }
+ 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;
- 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("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-- dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
-+ dbg(2," %s : leave, return value %d", __func__, retval);
- return retval;
+ 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;
}
-@@ -565,7 +565,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
+@@ -909,7 +902,7 @@ static int cypress_tiocmget (struct usb_serial_port *port, struct file *file)
+ unsigned int result = 0;
unsigned long flags;
- int retval;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-- dbg(2," %s : enter, count = %Zd", __FUNCTION__, count);
-+ dbg(2," %s : enter, count = %Zd", __func__, count);
+ 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);
- dev = file->private_data;
+- dbg("%s - result = %x", __FUNCTION__, result);
++ dbg("%s - result = %x", __func__, result);
-@@ -582,7 +582,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
+ 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);
- /* 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;
- }
+ 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);
-@@ -595,13 +595,13 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
+- priv->cmd_ctrl = 1;
+ return cypress_write(port, NULL, 0);
+ }
- 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;
- }
+@@ -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(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);
+- dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
++ dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
- /* 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);
+ 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;
+ }
- 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;
+- 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);
- exit_onqueue:
-@@ -706,7 +706,7 @@ static int adu_probe(struct usb_interface *interface,
- int out_end_size;
- int i;
+ 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(2," %s : enter", __FUNCTION__);
-+ dbg(2," %s : enter", __func__);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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);
+ tty = port->tty;
+- if ((!tty) || (!tty->termios)) {
+- dbg("%s - no tty structures", __FUNCTION__);
+- return;
+- }
- /* 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);
+ 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);
- return retval;
++ /* Unsupported features need clearing */
++ tty->termios->c_cflag &= ~(CMSPAR|CRTSCTS);
++
+ cflag = tty->termios->c_cflag;
+ iflag = tty->termios->c_iflag;
-@@ -847,7 +847,7 @@ static void adu_disconnect(struct usb_interface *interface)
- struct adu_device *dev;
- int minor;
+ /* 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);
++ }
-- dbg(2," %s : enter", __FUNCTION__);
-+ dbg(2," %s : enter", __func__);
+ /* 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);
- dev = usb_get_intfdata(interface);
+ 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);
-@@ -861,7 +861,7 @@ static void adu_disconnect(struct usb_interface *interface)
- usb_set_intfdata(interface, NULL);
+- 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);
- /* 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);
+ /* 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;
-@@ -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("%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(2," %s : leave", __FUNCTION__);
-+ dbg(2," %s : leave", __func__);
+- dbg("%s - returns %d", __FUNCTION__, chars);
++ dbg("%s - returns %d", __func__, chars);
+ return chars;
}
- /* usb specific object needed to register this driver with the usb subsystem */
-@@ -885,7 +885,7 @@ static int __init adu_init(void)
- {
- int result;
+@@ -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(2," %s : enter", __FUNCTION__);
-+ dbg(2," %s : enter", __func__);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- /* 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");
+ 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;
- exit:
-- dbg(2," %s : leave, return value %d", __FUNCTION__, result);
-+ dbg(2," %s : leave, return value %d", __func__, result);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- return result;
- }
+ 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 __exit adu_exit(void)
+ static void cypress_read_int_callback(struct urb *urb)
{
-- dbg(2," %s : enter", __FUNCTION__);
-+ dbg(2," %s : enter", __func__);
- /* deregister this driver with the USB subsystem */
- usb_deregister(&adu_driver);
-- dbg(2," %s : leave", __FUNCTION__);
-+ dbg(2," %s : leave", __func__);
- }
-
- module_init(adu_init);
-diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
-index 1cb56f2..a076c24 100644
---- a/drivers/usb/misc/appledisplay.c
-+++ b/drivers/usb/misc/appledisplay.c
-@@ -29,7 +29,6 @@
- #include <linux/timer.h>
- #include <linux/workqueue.h>
- #include <asm/atomic.h>
--#include <asm/semaphore.h>
+- 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;
- #define APPLE_VENDOR_ID 0x05AC
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-@@ -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;
+ switch (status) {
+ case 0: /* success */
+@@ -1302,14 +1237,14 @@ static void cypress_read_int_callback(struct urb *urb)
default:
- dbg("%s - nonzero urb status received: %d",
+ /* something ugly is going on... */
+ dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n",
- __FUNCTION__, status);
+ __func__, status);
- goto exit;
+ cypress_set_dead(port);
+ return;
}
-@@ -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);
+ 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;
}
- }
-diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
-index df7e1ec..0939386 100644
---- a/drivers/usb/misc/auerswald.c
-+++ b/drivers/usb/misc/auerswald.c
-@@ -31,6 +31,7 @@
- #include <linux/init.h>
- #include <linux/wait.h>
- #include <linux/usb.h>
-+#include <linux/mutex.h>
+ 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;
++ }
- /*-------------------------------------------------------------------*/
- /* 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;
+- usb_serial_debug_data (debug, &port->dev, __FUNCTION__,
++ usb_serial_debug_data (debug, &port->dev, __func__,
+ urb->actual_length, data);
- /* get pointer to element and to chain */
-- pauerchainelement_t acep = (pauerchainelement_t) urb->context;
-+ pauerchainelement_t acep = urb->context;
- pauerchain_t acp = acep->chain;
+ 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);
- /* 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)
+@@ -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)
{
-- 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)
+- 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)
{
-- 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");
+ int retval;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ retval = usb_serial_register(&cypress_earthmate_device);
+ if (retval)
+@@ -1699,7 +1634,7 @@ failed_em_register:
-@@ -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)
+ static void __exit cypress_exit (void)
{
-- 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;
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
-@@ -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;
+ 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..04a56f3 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;
-- dbg ("%s called", __FUNCTION__);
-+ dbg ("%s called", __func__);
+ }
+@@ -746,7 +740,7 @@ static int digi_write_inb_command(struct usb_serial_port *port,
- 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);
+ 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;
- 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);
+@@ -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 with result %d",
-- __FUNCTION__, ret);
-+ __func__, 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)
+@@ -1427,8 +1421,7 @@ static void digi_close(struct usb_serial_port *port, struct file *filp)
+ tty_wait_until_sent(tty, DIGI_CLOSE_TIMEOUT);
+
+ /* flush driver and line discipline buffers */
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
++ tty_driver_flush_buffer(tty);
+ tty_ldisc_flush(tty);
+
+ if (port->serial->dev) {
+@@ -1521,7 +1514,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 +1604,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 +1615,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 +1645,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 +1663,7 @@ static void digi_read_bulk_callback(struct urb *urb)
+ static int digi_read_inb_callback(struct urb *urb)
+ {
- /* 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;
+- 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 +1683,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 +1732,9 @@ static int digi_read_inb_callback(struct urb *urb)
+ spin_unlock(&priv->dp_port_lock);
-@@ -1389,8 +1390,8 @@ static int auerchar_open (struct inode *inode, struct file *file)
- }
+ 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);
- /* 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);
+ return(throttled ? 1 : 0);
- /* 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);
+@@ -1760,7 +1753,7 @@ static int digi_read_inb_callback(struct urb *urb)
+ static int digi_read_oob_callback(struct urb *urb)
+ {
- /* 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");
+- 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;
- /* 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;
- }
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- /* Check for removal */
- if (!cp->usbdev) {
-- up(&cp->mutex);
-- up(&ccp->mutex);
-+ mutex_unlock(&cp->mutex);
-+ mutex_unlock(&ccp->mutex);
- return -ENODEV;
- }
+ /* 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);
-@@ -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;
+ 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)
-@@ -1574,18 +1575,18 @@ static ssize_t auerchar_read (struct file *file, char __user *buf, size_t count,
- return 0;
+ 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);
- /* get the mutex */
-- if (down_interruptible (&ccp->mutex))
-+ if (mutex_lock_interruptible(&ccp->mutex))
- return -ERESTARTSYS;
+ /* 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;
- /* Can we expect to read something? */
- if (ccp->scontext.id == AUH_UNASSIGNED) {
-- up (&ccp->mutex);
-+ mutex_unlock(&ccp->mutex);
- return -EIO;
- }
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- /* 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;
- }
+ while (count > 0) {
-@@ -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:
+@@ -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;
}
- /* return with number of bytes read */
- if (count) {
-- up (&ccp->readmutex);
-- up (&ccp->mutex);
-+ mutex_unlock(&ccp->readmutex);
-+ mutex_unlock(&ccp->mutex);
- return count;
+
+ 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;
+ }
}
- }
-@@ -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 */
- }
+@@ -238,7 +235,7 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
- /* 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;
- }
+ memcpy (urb->transfer_buffer, current_position, transfer_size);
- /* Anything left to read? */
- if ((ccp->scontext.id == AUH_UNASSIGNED) || ccp->removed) {
-- up (&ccp->readmutex);
-+ mutex_unlock(&ccp->readmutex);
- return -EIO;
- }
+- 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);
-- if (down_interruptible (&ccp->mutex)) {
-- up (&ccp->readmutex);
-+ if (mutex_lock_interruptible(&ccp->mutex)) {
-+ mutex_unlock(&ccp->readmutex);
- return -ERESTARTSYS;
- }
+ /* 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;
-@@ -1707,27 +1708,27 @@ static ssize_t auerchar_write (struct file *file, const char __user *buf, size_t
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- write_again:
- /* get the mutex */
-- if (down_interruptible (&ccp->mutex))
-+ if (mutex_lock_interruptible(&ccp->mutex))
- return -ERESTARTSYS;
+ spin_lock_irqsave (&write_urb_pool_lock, flags);
- /* Can we expect to write something? */
- if (ccp->scontext.id == AUH_UNASSIGNED) {
-- up (&ccp->mutex);
-+ mutex_unlock(&ccp->mutex);
- return -EIO;
- }
+@@ -291,7 +288,7 @@ static int empeg_write_room (struct usb_serial_port *port)
- 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:
+ spin_unlock_irqrestore (&write_urb_pool_lock, flags);
- /* are there any buffers left? */
- if (!bp) {
-- up (&cp->mutex);
-- up (&ccp->mutex);
-+ mutex_unlock(&cp->mutex);
-+ mutex_unlock(&ccp->mutex);
+- dbg("%s - returns %d", __FUNCTION__, room);
++ dbg("%s - returns %d", __func__, room);
- /* 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;
- }
+ return (room);
-@@ -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");
+@@ -304,7 +301,7 @@ static int empeg_chars_in_buffer (struct usb_serial_port *port)
+ int i;
+ int chars = 0;
-- 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);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- return 0;
-@@ -1917,7 +1918,7 @@ static int auerswald_probe (struct usb_interface *intf,
- }
+ spin_lock_irqsave (&write_urb_pool_lock, flags);
- /* 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);
+@@ -317,7 +314,7 @@ static int empeg_chars_in_buffer (struct usb_serial_port *port)
-- down (&cp->mutex);
-+ mutex_lock(&cp->mutex);
- info ("device /dev/%s now disconnecting", cp->name);
+ spin_unlock_irqrestore (&write_urb_pool_lock, flags);
- /* Stop the interrupt endpoint */
-@@ -2057,16 +2058,18 @@ static void auerswald_disconnect (struct usb_interface *intf)
+- dbg("%s - returns %d", __FUNCTION__, chars);
++ dbg("%s - returns %d", __func__, chars);
- 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,
+ return (chars);
- 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;
+@@ -329,11 +326,11 @@ static void empeg_write_bulk_callback (struct urb *urb)
+ struct usb_serial_port *port = 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);
+- 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;
+ }
-@@ -230,7 +230,7 @@ static void iowarrior_write_callback(struct urb *urb)
- struct iowarrior *dev;
+@@ -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;
-- 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)
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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;
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
}
-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)
+- 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 (!interface) {
- err("%s - error, can't find device for minor %d\n",
-- __FUNCTION__, subminor);
-+ __func__, subminor);
- return -ENODEV;
- }
+ tty = port->tty;
-@@ -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);
+@@ -382,7 +379,7 @@ static void empeg_read_bulk_callback (struct urb *urb)
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
- if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
- retval = -EFAULT;
-diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
-index 6664043..9370326 100644
---- a/drivers/usb/misc/legousbtower.c
-+++ b/drivers/usb/misc/legousbtower.c
-@@ -31,7 +31,7 @@
- * - imported into lejos project
- * - changed wake_up to wake_up_interruptible
- * - changed to use lego0 rather than tower0
-- * - changed dbg() to use __func__ rather than deprecated __FUNCTION__
-+ * - changed dbg() to use __func__ rather than deprecated __func__
- * 2003-01-12 - 0.53 david (david at csse.uwa.edu.au)
- * - changed read and write to write everything or
- * timeout (from a patch by Chris Riesen and Brett Thaeler driver)
-@@ -49,7 +49,7 @@
- * - added poll
- * - forbid seeking
- * - added nonblocking I/O
-- * - changed back __func__ to __FUNCTION__
-+ * - changed back __func__ to __func__
- * - read and log tower firmware version
- * - reset tower on probe, avoids failure of first write
- * 2004-03-09 - 0.7 Juergen Stuber <starblue at users.sourceforge.net>
-@@ -309,7 +309,7 @@ static inline void lego_usb_tower_debug_data (int level, const char *function, i
- */
- static inline void tower_delete (struct lego_usb_tower *dev)
- {
-- dbg(2, "%s: enter", __FUNCTION__);
-+ dbg(2, "%s: enter", __func__);
+ 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);
- tower_abort_transfers (dev);
+ return;
-@@ -321,7 +321,7 @@ static inline void tower_delete (struct lego_usb_tower *dev)
- kfree (dev->interrupt_out_buffer);
- kfree (dev);
+@@ -391,7 +388,7 @@ static void empeg_read_bulk_callback (struct urb *urb)
-- dbg(2, "%s: leave", __FUNCTION__);
-+ dbg(2, "%s: leave", __func__);
+ 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);
}
-
-@@ -337,7 +337,7 @@ static int tower_open (struct inode *inode, struct file *file)
- struct tower_reset_reply reset_reply;
+@@ -400,14 +397,14 @@ static void empeg_unthrottle (struct usb_serial_port *port)
+ {
int result;
-- dbg(2, "%s: enter", __FUNCTION__);
-+ dbg(2, "%s: enter", __func__);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- nonseekable_open(inode, file);
- subminor = iminor(inode);
-@@ -346,7 +346,7 @@ static int tower_open (struct inode *inode, struct file *file)
+ port->read_urb->dev = port->serial->dev;
- if (!interface) {
- err ("%s - error, can't find device for minor %d",
-- __FUNCTION__, subminor);
-+ __func__, subminor);
- retval = -ENODEV;
- goto exit;
+ 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;
}
-@@ -424,7 +424,7 @@ unlock_exit:
- mutex_unlock(&dev->lock);
+- dbg("%s - reset config", __FUNCTION__);
++ dbg("%s - reset config", __func__);
+ r = usb_reset_configuration (serial->dev);
- exit:
-- dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval);
-+ dbg(2, "%s: leave, return value %d ", __func__, retval);
+ /* continue on with initialization */
+@@ -435,13 +432,13 @@ static int empeg_startup (struct usb_serial *serial)
- return retval;
+ static void empeg_shutdown (struct usb_serial *serial)
+ {
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
}
-@@ -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;
+ 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);
- if (dev == NULL) {
-- dbg(1, "%s: object is NULL", __FUNCTION__);
-+ dbg(1, "%s: object is NULL", __func__);
- retval = -ENODEV;
- goto exit_nolock;
+ 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;
+ }
}
-@@ -454,7 +454,7 @@ static int tower_release (struct inode *inode, struct file *file)
+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;
}
- 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;
+ 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;
}
-@@ -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;
+ 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;
}
-@@ -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__);
+diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
+index 3abb3c8..c7329f4 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 (dev == NULL) {
-- dbg(1, "%s: dev is null", __FUNCTION__);
-+ dbg(1, "%s: dev is null", __func__);
- goto exit;
+ 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 */
}
-@@ -509,7 +509,7 @@ static void tower_abort_transfers (struct lego_usb_tower *dev)
- usb_kill_urb(dev->interrupt_out_urb);
+ buf = kmalloc(1, GFP_NOIO);
+- if (!buf) {
++ if (!buf)
+ return -ENOMEM;
+- }
- exit:
-- dbg(2, "%s: leave", __FUNCTION__);
-+ dbg(2, "%s: leave", __func__);
- }
+ 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);
-@@ -542,7 +542,7 @@ static unsigned int tower_poll (struct file *file, poll_table *wait)
- struct lego_usb_tower *dev;
- unsigned int mask = 0;
+ /* 2. Observe async-compatible custom_divisor hack, update baudrate if needed */
-- dbg(2, "%s: enter", __FUNCTION__);
-+ dbg(2, "%s: enter", __func__);
+@@ -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);
+ }
- dev = file->private_data;
+ /* 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)
-@@ -557,7 +557,7 @@ static unsigned int tower_poll (struct file *file, poll_table *wait)
- mask |= POLLOUT | POLLWRNORM;
+ 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]);
}
-- dbg(2, "%s: leave, mask = %d", __FUNCTION__, mask);
-+ dbg(2, "%s: leave, mask = %d", __func__, mask);
+@@ -804,7 +801,7 @@ static void ftdi_determine_type(struct usb_serial_port *port)
- 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;
+ 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(2, "%s: enter, count = %Zd", __FUNCTION__, count);
-+ dbg(2, "%s: enter, count = %Zd", __func__, count);
- dev = (struct lego_usb_tower *)file->private_data;
+- dbg("%s",__FUNCTION__);
++ dbg("%s",__func__);
-@@ -602,7 +602,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
+ 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;
- /* 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;
- }
+- dbg("%s: setting latency timer = %i", __FUNCTION__, v);
++ dbg("%s: setting latency timer = %i", __func__, v);
-@@ -658,7 +658,7 @@ unlock_exit:
- mutex_unlock(&dev->lock);
+ 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;
- exit:
-- dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
-+ dbg(2, "%s: leave, return value %d", __func__, retval);
- return retval;
- }
+- dbg("%s: setting event char = %i", __FUNCTION__, v);
++ dbg("%s: setting event char = %i", __func__, v);
-@@ -672,7 +672,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
- size_t bytes_to_write;
+ 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(2, "%s: enter, count = %Zd", __FUNCTION__, count);
-+ dbg(2, "%s: enter, count = %Zd", __func__, count);
+- dbg("%s",__FUNCTION__);
++ dbg("%s",__func__);
- dev = (struct lego_usb_tower *)file->private_data;
+ /* 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);
-@@ -691,7 +691,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
+- dbg("%s",__FUNCTION__);
++ dbg("%s",__func__);
- /* 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;
- }
+ /* 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);
-@@ -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);
+- dbg("%s",__FUNCTION__);
++ dbg("%s",__func__);
- if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write)) {
- retval = -EFAULT;
-@@ -742,7 +742,7 @@ unlock_exit:
- mutex_unlock(&dev->lock);
+ 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;
+ }
- exit:
-- dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
-+ dbg(2, "%s: leave, return value %d", __func__, retval);
+@@ -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__);
- return retval;
- }
-@@ -753,13 +753,13 @@ exit:
- */
- static void tower_interrupt_in_callback (struct urb *urb)
+ 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)
{
-- 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("%s",__FUNCTION__);
++ dbg("%s",__func__);
-- dbg(4, "%s: enter, status %d", __FUNCTION__, status);
-+ dbg(4, "%s: enter, status %d", __func__, status);
+ 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;
-- 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);
+- dbg("%s",__FUNCTION__);
++ dbg("%s",__func__);
- 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);
- }
- }
+ if (interface == udev->actconfig->interface[0]) {
+ info("Ignoring serial port reserved for JTAG");
+@@ -1107,7 +1104,7 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
+ struct usb_endpoint_descriptor *ep_desc = &ep->desc;
-@@ -800,8 +800,8 @@ exit:
- dev->interrupt_in_done = 1;
- wake_up_interruptible (&dev->read_wait);
+ if (ep->enabled && ep_desc->wMaxPacketSize == 0) {
+- ep_desc->wMaxPacketSize = 0x40;
++ ep_desc->wMaxPacketSize = cpu_to_le16(0x40);
+ info("Fixing invalid wMaxPacketSize on read pipe");
+ }
-- 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);
+@@ -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__);
}
-
-@@ -810,25 +810,25 @@ exit:
- */
- static void tower_interrupt_out_callback (struct urb *urb)
+ static int ftdi_sio_port_remove(struct usb_serial_port *port)
{
-- struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context;
-+ struct lego_usb_tower *dev = urb->context;
- int status = urb->status;
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
-- 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);
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- /* 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);
- }
+ remove_sysfs_attrs(port);
- dev->interrupt_out_busy = 0;
- wake_up_interruptible(&dev->write_wait);
+@@ -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 */
-- 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);
- }
+- 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);
-@@ -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__);
+ 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];
- if (udev == NULL) {
- info ("udev is NULL.");
-@@ -978,7 +978,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
+- 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;
- 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);
+- dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count);
++ dbg("%s port %d, %d bytes", __func__, port->number, count);
- return retval;
+ 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,
-@@ -998,7 +998,7 @@ static void tower_disconnect (struct usb_interface *interface)
- struct lego_usb_tower *dev;
- int minor;
+ 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;
+ }
-- dbg(2, "%s: enter", __FUNCTION__);
-+ dbg(2, "%s: enter", __func__);
+ 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);
+ }
- dev = usb_get_intfdata (interface);
- mutex_lock(&open_disc_mutex);
-@@ -1023,7 +1023,7 @@ static void tower_disconnect (struct usb_interface *interface)
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size, buffer);
++ usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, buffer);
- info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));
+ /* 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,
-- dbg(2, "%s: leave", __FUNCTION__);
-+ dbg(2, "%s: leave", __func__);
- }
+ 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);
-@@ -1036,7 +1036,7 @@ static int __init lego_usb_tower_init(void)
- int result;
- int retval = 0;
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-- dbg(2, "%s: enter", __FUNCTION__);
-+ dbg(2, "%s: enter", __func__);
+ if (status) {
+ dbg("nonzero write bulk status received: %d", status);
+@@ -1398,7 +1395,7 @@ static void ftdi_write_bulk_callback (struct urb *urb)
- /* 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);
+ 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;
- exit:
-- dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
-+ dbg(2, "%s: leave, return value %d", __func__, retval);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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__);
+ 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;
- /* deregister this driver with the USB subsystem */
- usb_deregister (&tower_driver);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-- dbg(2, "%s: leave", __FUNCTION__);
-+ dbg(2, "%s: leave", __func__);
- }
+ 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)
- 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)
+ 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;
- 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;
+ 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 );
}
-@@ -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;
- }
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-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)
+ if (port->open_count <= 0)
+ return;
- 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;
+ tty = port->tty;
+ if (!tty) {
+- dbg("%s - bad tty pointer - exiting",__FUNCTION__);
++ dbg("%s - bad tty pointer - exiting",__func__);
+ return;
}
-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;
+ 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;
}
-@@ -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;
+ if (urb != port->read_urb) {
+- err("%s - Not my urb!", __FUNCTION__);
++ err("%s - Not my urb!", __func__);
}
-@@ -259,7 +259,7 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id)
+ if (status) {
+@@ -1506,7 +1503,7 @@ static void ftdi_read_bulk_callback (struct urb *urb)
- 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;
+ /* 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;
}
-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;
+
+ 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;
}
-@@ -185,7 +185,7 @@ static void lcd_write_bulk_callback(struct urb *urb)
- struct usb_lcd *dev;
- int status = urb->status;
+ urb = port->read_urb;
+ if (!urb) {
+- dbg("%s - bad read_urb pointer - exiting", __FUNCTION__);
++ dbg("%s - bad read_urb pointer - exiting", __func__);
+ return;
+ }
-- dev = (struct usb_lcd *)urb->context;
-+ dev = urb->context;
+ data = urb->transfer_buffer;
- /* 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);
+ 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)
- /* 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;
+ 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);
}
-
-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);
+ 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);
+
}
- 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);
+@@ -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);
}
- }
-@@ -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;
+ /* 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;
}
-- 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;
+
+@@ -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__);
}
-- 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;
+ /* 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;
-- 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
- #
+- 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)
- 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;
+ 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);
}
--#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;
- }
+@@ -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);
--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,
- };
+- dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
++ dbg("%s cmd 0x%04x", __func__, cmd);
--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;
- }
+ /* 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);
--#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,
- };
+ 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;
- 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)
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- /*
- */
--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)
- {
+ 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;
- 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)
+- 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)
{
-+ struct snap *sp = file->private_data;
-+ file->private_data = NULL;
-+ kfree(sp);
- return 0;
- }
+ int retval;
-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
+- 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)
+ {
- 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
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- 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.
+ 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,
+ };
- config USB_SERIAL_GENERIC
- bool "USB Generic Serial Driver"
-- depends on USB_SERIAL
- help
- Say Y here if you want to use the generic USB serial driver. Please
- read <file:Documentation/usb/usb-serial.txt> for more information on
-@@ -59,8 +57,7 @@ config USB_SERIAL_GENERIC
- properly.
+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) {
- 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.
+ usb_serial_debug_data(debug, &port->dev,
+- __FUNCTION__, actual_length, data);
++ __func__, actual_length, data);
-@@ -69,7 +66,6 @@ config USB_SERIAL_AIRCABLE
+ 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;
- 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.
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
-@@ -77,8 +73,7 @@ config USB_SERIAL_AIRPRIME
- module will be called airprime.
+ 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;
- 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
+- dbg("%s - pkt-id: 0x%X.", __FUNCTION__, 0xFF & pkt_id);
++ dbg("%s - pkt-id: 0x%X.", __func__, 0xFF & pkt_id);
- 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
+ *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];
- 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
+ usb_serial_debug_data(debug, &garmin_data_p->port->dev,
+- __FUNCTION__, count-GSP_INITIAL_OFFSET, recpkt);
++ __func__, count-GSP_INITIAL_OFFSET, recpkt);
- 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
+ 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;
+ }
- 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
+@@ -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;
+ }
- 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
+@@ -454,7 +454,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
- 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
+ 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;
+ }
- 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.
+@@ -519,7 +519,7 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
+ spin_unlock_irqrestore(&garmin_data_p->lock, flags);
- 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
+ dbg("%s - dle=%d skip=%d size=%d count=%d",
+- __FUNCTION__, dleSeen, skip, size, count);
++ __func__, dleSeen, skip, size, count);
- 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.
+ if (size == 0) {
+ size = GSP_INITIAL_OFFSET;
+@@ -578,7 +578,7 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
+ }
-@@ -195,7 +181,6 @@ config USB_SERIAL_FUNSOFT
+ 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;
- 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
+- dbg("%s - state %d - %d bytes.", __FUNCTION__,
++ dbg("%s - state %d - %d bytes.", __func__,
+ garmin_data_p->state, count);
- 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.
+ k = garmin_data_p->outsize;
+@@ -658,13 +658,13 @@ static int gsp_send(struct garmin_data * garmin_data_p,
+ return 0;
+ }
- 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
+- dbg("%s - %d bytes in buffer, %d bytes in pkt.", __FUNCTION__,
++ dbg("%s - %d bytes in buffer, %d bytes in pkt.", __func__,
+ k, i);
- 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
+ /* garmin_data_p->outbuffer now contains a complete packet */
- 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
+ usb_serial_debug_data(debug, &garmin_data_p->port->dev,
+- __FUNCTION__, k, garmin_data_p->outbuffer);
++ __func__, k, garmin_data_p->outbuffer);
- 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.
+ garmin_data_p->outsize = 0;
- 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.
+@@ -749,7 +749,7 @@ static void gsp_next_packet(struct garmin_data * garmin_data_p)
+ struct garmin_packet *pkt = NULL;
- 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
+ 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);
+ }
- 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.
+ 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);
- 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
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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
+ /*
+ * 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);
- 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
+- 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);
- 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
+@@ -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;
- 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
+ if (port) {
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
- 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.
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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.
+ 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)
- 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.
+ 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;
-+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.
+- dbg("%s - port %d, state %d", __FUNCTION__, port->number,
++ dbg("%s - port %d, state %d", __func__, port->number,
+ garmin_data_p->state);
-@@ -513,8 +489,7 @@ config USB_SERIAL_HP4X
- module will be called hp4x.
+ spin_lock_irqsave(&garmin_data_p->lock, flags);
+@@ -1110,7 +1110,7 @@ static int garmin_write_bulk (struct usb_serial_port *port,
- config USB_SERIAL_SAFE
-- tristate "USB Safe Serial (Encapsulated) Driver (EXPERIMENTAL)"
-- depends on USB_SERIAL && EXPERIMENTAL
-+ tristate "USB Safe Serial (Encapsulated) Driver"
+ memcpy (buffer, buf, count);
- config USB_SERIAL_SAFE_PADDED
- bool "USB Secure Encapsulated Driver - Padded"
-@@ -522,7 +497,6 @@ config USB_SERIAL_SAFE_PADDED
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
++ usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
- 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
+ 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;
+ }
- 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.
+@@ -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;
- 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
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buf);
++ usb_serial_debug_data(debug, &port->dev, __func__, count, buf);
- 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
+ /* 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)) {
- 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.
+ dbg("%s - processing private request %d",
+- __FUNCTION__, pktid);
++ __func__, pktid);
-@@ -586,8 +556,7 @@ config USB_SERIAL_OPTION
- it might be accessible via the FTDI_SIO driver.
+ // 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;
- 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.
+ 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;
-@@ -596,7 +565,6 @@ config USB_SERIAL_OMNINET
+ 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;
- 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)
+
+ if (!serial) {
+- dbg("%s - bad serial pointer, exiting", __FUNCTION__);
++ dbg("%s - bad serial pointer, exiting", __func__);
return;
+ }
-@@ -220,7 +220,7 @@ static void aircable_send(struct usb_serial_port *port)
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
- 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);
+ 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;
}
-@@ -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, __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;
- }
+ urb->actual_length, urb->transfer_buffer);
-@@ -275,7 +275,7 @@ static void aircable_read(struct work_struct *work)
+ if (urb->actual_length == sizeof(GARMIN_BULK_IN_AVAIL_REPLY) &&
+ 0 == memcmp(data, GARMIN_BULK_IN_AVAIL_REPLY,
+ sizeof(GARMIN_BULK_IN_AVAIL_REPLY))) {
- if (!tty) {
- schedule_work(&priv->rx_work);
-- err("%s - No tty available", __FUNCTION__);
-+ err("%s - No tty available", __func__);
- return ;
+- 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);
}
-@@ -286,7 +286,7 @@ static void aircable_read(struct work_struct *work)
+ 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);
+ }
- tty_prepare_flip_string(tty, &data, count);
- if (!data){
-- err("%s- kzalloc(%d) failed.", __FUNCTION__, count);
-+ err("%s- kzalloc(%d) failed.", __func__, count);
- return;
+
+@@ -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);
}
+ }
-@@ -332,7 +332,7 @@ static int aircable_attach (struct usb_serial *serial)
+@@ -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;
- 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));
+- 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;
}
-@@ -366,7 +366,7 @@ static void aircable_shutdown(struct usb_serial *serial)
+ 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 aircable_private *priv = usb_get_serial_port_data(port);
+ struct garmin_data * garmin_data_p = 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;
+ 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, %d bytes", __FUNCTION__, port->number, count);
-+ dbg("%s - port %d, %d bytes", __func__, port->number, count);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, source);
-+ usb_serial_debug_data(debug, &port->dev, __func__, count, source);
+ /* 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);
+ }
- if (!count){
+ 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 count;
+ return (0);
}
-@@ -414,7 +414,7 @@ static void aircable_write_bulk_callback(struct urb *urb)
- int status = urb->status;
- int result;
+@@ -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 *
-- dbg("%s - urb status: %d", __FUNCTION__ , status);
-+ dbg("%s - urb status: %d", __func__ , status);
+ 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);
- /* 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);
+ /* 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;
- 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;
+ } 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);
- 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;
++ /* FIXME: Locking */
+ if (serial->num_bulk_out) {
+ if (!(port->write_urb_busy))
+ room = port->bulk_out_size;
}
-- 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);
- }
+- dbg("%s - returns %d", __FUNCTION__, room);
+- return (room);
++ dbg("%s - returns %d", __func__, room);
++ return room;
+ }
- 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;
+ 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);
- 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;
++ /* FIXME: Locking */
+ if (serial->num_bulk_out) {
+ if (port->write_urb_busy)
+ chars = port->write_urb->transfer_buffer_length;
+ }
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg("%s - returns %d", __FUNCTION__, chars);
++ dbg("%s - returns %d", __func__, chars);
+ return (chars);
+ }
- 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;
+@@ -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);
+ }
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ /* 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)
- if (port->number != 0)
- return 0;
-@@ -83,14 +83,14 @@ static void airprime_read_bulk_callback(struct urb *urb)
- int result;
+ 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 (status) {
+ 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);
- 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;
- }
+ /* 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);
-@@ -112,14 +112,14 @@ static void airprime_write_bulk_callback(struct urb *urb)
+ 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;
- 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)
+ port->write_urb_busy = 0;
+ 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;
+ 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);
- priv->rts_state = 0;
- priv->dtr_state = 0;
-@@ -242,12 +242,12 @@ static int airprime_write(struct usb_serial_port *port,
- unsigned char *buffer;
+ /* 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;
- 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);
+ /* 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;
-- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
-+ usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- 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 = {
+ /* 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 = {
},
- .usb_driver = &airprime_driver,
.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,
- .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__);
+ .num_ports = 1,
+ };
- 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,
+diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
+index 3428ccc..06b52f4 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;
- config = 0;
+- dbg("%s - USB String ID = %d", __FUNCTION__, Id );
++ dbg("%s - USB String ID = %d", __func__, Id );
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ 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);
- 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;
- }
+ kfree(pStringDesc);
+- dbg("%s - USB String %s", __FUNCTION__, string);
++ dbg("%s - USB String %s", __func__, string);
+ return strlen(string);
+ }
-@@ -323,7 +324,7 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp)
- char *buf;
- int result = 0;
+@@ -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 - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg("%s - USB String ID = %d", __FUNCTION__, Id );
++ dbg("%s - USB String ID = %d", __func__, Id );
- 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;
+ if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) {
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);
+@@ -537,7 +537,7 @@ static int get_epic_descriptor(struct edgeport_serial *ep)
+ sizeof(struct edge_compatibility_descriptor),
+ 300);
- /*Start reading from the device*/
- /* TODO: Look at possibility of submitting multiple URBs to device to
-@@ -240,7 +237,7 @@ exit:
+- dbg("%s result = %d", __FUNCTION__, result);
++ dbg("%s result = %d", __func__, result);
- static void belkin_sa_close (struct usb_serial_port *port, struct file *filp)
+ 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)
{
-- dbg("%s port %d", __FUNCTION__, port->number);
-+ dbg("%s port %d", __func__, port->number);
+- 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;
- /* 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)
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- 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)
+ 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",
@@ -709757,5857 +936286,5935 @@
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);
+ // 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);
- /* 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);
+ 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);
+ }
}
- 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;
-
+@@ -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__);
- 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;
-
+ 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__);
- 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;
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ }
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
+ 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;
- 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", __FUNCTION__);
++ dbg("%s", __func__);
-- dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
-+ dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
+ 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));
- if (!port->open_count) {
-- dbg ("%s - port not opened", __FUNCTION__);
-+ dbg ("%s - port not opened", __func__);
+
+ /* 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;
}
-@@ -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);
+@@ -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);
}
- 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;
+ }
+
+@@ -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);
- 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,
+ 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)
- 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;
+ 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);
-@@ -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;
+ 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;
-@@ -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__);
+ if (!edge_port->write_urb) {
+- dbg("%s - no memory", __FUNCTION__);
++ dbg("%s - no memory", __func__);
+ edge_close (port, filp);
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;
+- 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)
-@@ -293,11 +293,11 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp)
- struct usb_serial *serial = port->serial;
- int result;
+ // 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;
- if (cp2101_set_config_single(port, CP2101_UART, UART_ENABLE)) {
- dev_err(&port->dev, "%s - Unable to enable UART\n",
-- __FUNCTION__);
-+ __func__);
- return -EPROTO;
+- 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);
}
-@@ -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;
- }
+@@ -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;
-@@ -329,7 +329,7 @@ static void cp2101_cleanup (struct usb_serial_port *port)
- {
- struct usb_serial *serial = port->serial;
+- 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 (serial->dev) {
- /* shutdown any bulk reads that might be going on */
-@@ -342,10 +342,10 @@ static void cp2101_cleanup (struct usb_serial_port *port)
+ 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));
- 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);
+- 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);
- /* 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);
+ /* 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;
+ }
-@@ -367,10 +367,10 @@ static void cp2101_get_termios (struct usb_serial_port *port)
- int baud;
- int bits;
+@@ -1169,11 +1169,11 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ 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);
- if (!port->tty || !port->tty->termios) {
-- dbg("%s - no tty structures", __FUNCTION__);
-+ dbg("%s - no tty structures", __func__);
- return;
+ /* 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;
}
-@@ -379,7 +379,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
- if (baud)
- baud = BAUD_RATE_GEN_FREQ / baud;
+@@ -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;
+ }
-- dbg("%s - baud rate = %d", __FUNCTION__, baud);
-+ dbg("%s - baud rate = %d", __func__, baud);
+@@ -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
+ }
- 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)
+ 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]);
- 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)
+ /* 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;
- 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;
+ /* 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);
-@@ -500,10 +500,10 @@ static void cp2101_set_termios (struct usb_serial_port *port,
- int baud=0, bits;
- unsigned int modem_ctl[4];
+ 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 (!port->tty || !port->tty->termios) {
-- dbg("%s - no tty structures", __FUNCTION__);
-+ dbg("%s - no tty structures", __func__);
- return;
+ if (!edge_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return -EINVAL;
}
- 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]);
+@@ -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);
- 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 - returns %d", __FUNCTION__, room);
++ dbg("%s - returns %d", __func__, room);
+ return room;
+ }
- 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);
+@@ -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;
}
-@@ -655,7 +655,7 @@ static int cp2101_tiocmset (struct usb_serial_port *port, struct file *file,
- {
- int control = 0;
+
+@@ -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 (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;
- }
+ if (edge_port == NULL)
+ return;
-- dbg("%s - control = 0x%.4x", __FUNCTION__, control);
-+ dbg("%s - control = 0x%.4x", __func__, control);
+ if (!edge_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
+ }
- return cp2101_set_config(port, CP2101_CONTROL, &control, 2);
+ tty = port->tty;
+ if (!tty) {
+- dbg ("%s - no tty available", __FUNCTION__);
++ dbg ("%s - no tty available", __func__);
+ return;
+ }
-@@ -684,7 +684,7 @@ static int cp2101_tiocmget (struct usb_serial_port *port, struct file *file)
- {
- int control, result;
+@@ -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);
- cp2101_get_config(port, CP2101_CONTROL, &control, 1);
+ if (edge_port == NULL)
+ return;
-@@ -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);
+ if (!edge_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
+ }
-- dbg("%s - control = 0x%.2x", __FUNCTION__, control);
-+ dbg("%s - control = 0x%.2x", __func__, control);
+ tty = port->tty;
+ if (!tty) {
+- dbg ("%s - no tty available", __FUNCTION__);
++ dbg ("%s - no tty available", __func__);
+ return;
+ }
- return result;
- }
-@@ -704,12 +704,12 @@ static void cp2101_break_ctl (struct usb_serial_port *port, int break_state)
- {
- int state;
+@@ -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 (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;
+ if (edge_port == NULL)
+ return;
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ if (!edge_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
+ }
- /* 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__);
+@@ -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
- return( 0 );
-@@ -152,9 +149,9 @@ static void cyberjack_shutdown (struct usb_serial *serial)
- {
- int i;
-
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ result = tty->read_cnt;
-- 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(%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);
-- 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)
+ 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;
- 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;
+ 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__);
+ }
+ }
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+@@ -1799,14 +1799,14 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha
+ __u16 lastBufferLength;
+ __u16 rxLen;
- if (count == 0) {
-- dbg("%s - write request of 0 bytes", __FUNCTION__);
-- return (0);
-+ dbg("%s - write request of 0 bytes", __func__);
-+ return 0;
- }
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- 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
+ lastBufferLength = bufferLength + 1;
- spin_lock_irqsave(&priv->lock, flags);
+ 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;
-- 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;
- }
+- 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);
- /* Copy data */
- memcpy (priv->wrbuf+priv->wrfilled, buf, count);
+ // 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);
-- 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;
+- 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);
- 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);
+ //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;
}
-@@ -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;
+- dbg("%s - port %d", __FUNCTION__, edge_serial->rxPort);
++ dbg("%s - port %d", __func__, edge_serial->rxPort);
- 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;
+ 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);
-- 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);
+ /* 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;
- 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;
- }
- }
+ 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);
-@@ -297,27 +294,28 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
+ // 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;
- static int cyberjack_write_room( struct usb_serial_port *port )
- {
-+ /* FIXME: .... */
- return CYBERJACK_LOCAL_BUF_SIZE;
- }
+ default:
+- dbg("%s - Unrecognized IOSP status code %u\n", __FUNCTION__, code);
++ dbg("%s - Unrecognized IOSP status code %u\n", __func__, code);
+ break;
+ }
- static void cyberjack_read_int_callback( struct urb *urb )
+@@ -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 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;
+ struct async_icount *icount;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg("%s %02x", __FUNCTION__, newMsr);
++ dbg("%s %02x", __func__, newMsr);
- /* the urb might have been killed. */
- if (status)
- return;
+ 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;
-- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
-+ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+- dbg("%s - %02x", __FUNCTION__, newLsr);
++ dbg("%s - %02x", __func__, newLsr);
- /* 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;
+ edge_port->shadowLSR = lsr;
- /* 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;
+@@ -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 - rdtodo: %d", __FUNCTION__, priv->rdtodo);
-+ dbg("%s - rdtodo: %d", __func__, priv->rdtodo);
+- dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
++ dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
- spin_unlock(&priv->lock);
+ 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;
+ }
-@@ -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__);
+@@ -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;
-@@ -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__);
- }
+-// dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
++// dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
- 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;
+ 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;
+ }
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+@@ -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;
-- 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;
- }
+- dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
++ dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
- tty = port->tty;
- if (!tty) {
-- dbg("%s - ignoring since device not open\n", __FUNCTION__);
-+ dbg("%s - ignoring since device not open\n", __func__);
- return;
+ 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;
}
- if (urb->actual_length) {
-@@ -397,30 +395,30 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
- spin_unlock(&priv->lock);
+@@ -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 - rdtodo: %d", __FUNCTION__, todo);
-+ dbg("%s - rdtodo: %d", __func__, todo);
+- dbg("%s - %d, %d", __FUNCTION__, command, param);
++ dbg("%s - %d, %d", __func__, command, param);
- /* 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__);
+ 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;
}
- }
- 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;
+@@ -2304,7 +2304,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
+ struct urb *urb;
+ int timeout;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- usb_serial_debug_data(debug, &edge_port->port->dev, __FUNCTION__, length, buffer);
++ usb_serial_debug_data(debug, &edge_port->port->dev, __func__, length, buffer);
- port->write_urb_busy = 0;
- if (status) {
- dbg("%s - nonzero write bulk status received: %d",
-- __FUNCTION__, status);
-+ __func__, status);
- return;
- }
+ /* 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;
-@@ -430,7 +428,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
- if( priv->wrfilled ) {
- int length, blksize, result;
+ 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));
-- dbg("%s - transmitting data (frame n)", __FUNCTION__);
-+ dbg("%s - transmitting data (frame n)", __func__);
+ 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
- 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;
- }
+ 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
-- 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 (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;
+ }
- blksize = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
+- dbg("%s - port = %d, baud = %d", __FUNCTION__, edge_port->port->number, baudRate);
++ dbg("%s - port = %d, baud = %d", __func__, edge_port->port->number, baudRate);
- 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;
- }
+ 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;
}
-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,
- };
+ // 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;
-+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 = {
- *****************************************************************************/
+- dbg("%s - %d", __FUNCTION__, baudrate);
++ dbg("%s - %d", __func__, baudrate);
-+static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate)
-+{
-+ struct cypress_private *priv;
-+ priv = usb_get_serial_port_data(port);
-+
-+ /*
-+ * The general purpose firmware for the Cypress M8 allows for
-+ * a maximum speed of 57600bps (I have no idea whether DeLorme
-+ * chose to use the general purpose firmware or not), if you
-+ * need to modify this speed setting for your own project
-+ * please add your own chiptype and modify the code likewise.
-+ * The Cypress HID->COM device will work successfully up to
-+ * 115200bps (but the actual throughput is around 3kBps).
-+ */
-+ if (port->serial->dev->speed == USB_SPEED_LOW) {
-+ /*
-+ * Mike Isely <isely at pobox.com> 2-Feb-2008: The
-+ * Cypress app note that describes this mechanism
-+ * states the the low-speed part can't handle more
-+ * than 800 bytes/sec, in which case 4800 baud is the
-+ * safest speed for a part like that.
-+ */
-+ if (new_rate > 4800) {
-+ dbg("%s - failed setting baud rate, device incapable "
-+ "speed %d", __func__, new_rate);
-+ return -1;
-+ }
-+ }
-+ switch (priv->chiptype) {
-+ case CT_EARTHMATE:
-+ if (new_rate <= 600) {
-+ /* 300 and 600 baud rates are supported under
-+ * the generic firmware, but are not used with
-+ * NMEA and SiRF protocols */
-+ dbg("%s - failed setting baud rate, unsupported speed "
-+ "of %d on Earthmate GPS", __func__, new_rate);
-+ return -1;
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+ return new_rate;
-+}
-+
-+
- /* This function can either set or retrieve the current serial line settings */
--static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_mask, int data_bits, int stop_bits,
-+static int cypress_serial_control (struct usb_serial_port *port, speed_t baud_rate, int data_bits, int stop_bits,
- int parity_enable, int parity_type, int reset, int cypress_request_type)
- {
- int new_baudrate = 0, retval = 0, tries = 0;
- struct cypress_private *priv;
-- __u8 feature_buffer[8];
-+ __u8 feature_buffer[5];
- unsigned long flags;
+ 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)
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
-
- priv = usb_get_serial_port_data(port);
+ *divisor = custom;
-@@ -302,58 +339,23 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
+- dbg("%s - Baud %d = %d\n", __FUNCTION__, baudrate, custom);
++ dbg("%s - Baud %d = %d\n", __func__, baudrate, custom);
+ return 0;
+ }
- 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;
+@@ -2452,7 +2452,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
+ unsigned long cmdLen = 0;
+ int status;
-@@ -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);
+- 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 (tries++ >= 3)
- break;
+ 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;
-- } while (retval != 8 && retval != -ENODEV);
-+ } while (retval != sizeof(feature_buffer) &&
-+ retval != -ENODEV);
+- dbg("%s - port %d", __FUNCTION__, edge_port->port->number);
++ dbg("%s - port %d", __func__, edge_port->port->number);
-- 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));
+ if (!edge_port->open &&
+ !edge_port->openPending) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
+ }
- 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;
+ tty = edge_port->port->tty;
+ if ((!tty) ||
+ (!tty->termios)) {
+- dbg("%s - no tty structures", __FUNCTION__);
++ dbg("%s - no tty structures", __func__);
+ return;
+ }
-- } while (retval != 5 && retval != -ENODEV);
-+ } while (retval != sizeof(feature_buffer) &&
-+ retval != -ENODEV);
+ cflag = tty->termios->c_cflag;
-- 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;
+ 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 {
-@@ -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);
+ 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__);
}
-@@ -447,51 +463,6 @@ static void cypress_set_dead(struct usb_serial_port *port)
- }
+ 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__);
+ }
--/* 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];
+ /* 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__);
+ }
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ /* 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__);
+ }
- 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);
+ /* 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__);
+ }
}
- 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__);
+@@ -2645,7 +2645,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ baud = 9600;
+ }
- 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;
+- 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);
}
-- 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;
-+ }
+- dbg("%s - time 1 %ld", __FUNCTION__, jiffies);
++ dbg("%s - time 1 %ld", __func__, jiffies);
- return 0;
- } /* cypress_earthmate_startup */
-@@ -565,10 +559,10 @@ static int cypress_hidcom_startup (struct usb_serial *serial)
- {
- struct cypress_private *priv;
+ /* 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", __FUNCTION__);
-+ dbg("%s", __func__);
+- dbg("%s - time 2 %ld", __FUNCTION__, jiffies);
++ dbg("%s - time 2 %ld", __func__, jiffies);
- 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;
+ /* 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);
+@@ -2993,7 +2993,7 @@ static int edge_startup (struct usb_serial *serial)
+ usb_fill_bulk_urb(edge_serial->read_urb, dev,
+ usb_rcvbulkpipe(dev, endpoint->bEndpointAddress),
+ edge_serial->bulk_in_buffer,
+- endpoint->wMaxPacketSize,
++ le16_to_cpu(endpoint->wMaxPacketSize),
+ edge_bulk_in_callback,
+ edge_serial);
+ bulk_in_found = true;
+@@ -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);
}
-@@ -584,10 +578,10 @@ static int cypress_ca42v2_startup (struct usb_serial *serial)
- {
- struct cypress_private *priv;
+ 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__);
- 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;
+ /* stop reads and writes on all ports */
+ for (i=0; i < serial->num_ports; ++i) {
+diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
+index 6d30087..2ec8589 100644
+--- a/drivers/usb/serial/io_tables.h
++++ b/drivers/usb/serial/io_tables.h
+@@ -111,9 +111,6 @@ static struct usb_serial_driver edgeport_2port_device = {
+ .description = "Edgeport 2 port adapter",
+ .usb_driver = &io_driver,
+ .id_table = edgeport_2port_id_table,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 2,
+ .open = edge_open,
+ .close = edge_close,
+@@ -142,9 +139,6 @@ static struct usb_serial_driver edgeport_4port_device = {
+ .description = "Edgeport 4 port adapter",
+ .usb_driver = &io_driver,
+ .id_table = edgeport_4port_id_table,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 4,
+ .open = edge_open,
+ .close = edge_close,
+@@ -173,9 +167,6 @@ static struct usb_serial_driver edgeport_8port_device = {
+ .description = "Edgeport 8 port adapter",
+ .usb_driver = &io_driver,
+ .id_table = edgeport_8port_id_table,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 8,
+ .open = edge_open,
+ .close = edge_close,
+@@ -203,9 +194,6 @@ static struct usb_serial_driver epic_device = {
+ },
+ .description = "EPiC device",
+ .id_table = Epic_port_id_table,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = edge_open,
+ .close = edge_close,
+diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
+index cd34059..05e4fa7 100644
+--- a/drivers/usb/serial/io_ti.c
++++ b/drivers/usb/serial/io_ti.c
+@@ -38,7 +38,6 @@
+ #include <linux/serial.h>
+ #include <linux/ioctl.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <linux/usb.h>
+ #include <linux/usb/serial.h>
+
+@@ -291,7 +290,7 @@ static int TIReadVendorRequestSync (struct usb_device *dev,
+ return status;
+ if (status != size) {
+ dbg ("%s - wanted to write %d, but only wrote %d",
+- __FUNCTION__, size, status);
++ __func__, size, status);
+ return -ECOMM;
}
-@@ -603,7 +597,7 @@ static void cypress_shutdown (struct usb_serial *serial)
+ 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)
{
- 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;
+ int port_number = port->number - port->serial->minor;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg ("%s - port %d, mask %x", __FUNCTION__, port_number, mask);
++ dbg ("%s - port %d, mask %x", __func__, port_number, mask);
- 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);
+ 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);
- 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__);
+ /* 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;
- cypress_set_termios(port, &priv->tmp_termios);
+ 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
- /* 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);
- }
+ if (status) {
+- dbg ("%s - ERROR %x", __FUNCTION__, status);
++ dbg ("%s - ERROR %x", __func__, status);
+ return status;
+ }
-@@ -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 (read_length > 1) {
+- usb_serial_debug_data(debug, &dev->dev, __FUNCTION__,
++ usb_serial_debug_data(debug, &dev->dev, __func__,
+ read_length, buffer);
+ }
- 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);
+@@ -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;
+ }
}
-@@ -688,7 +682,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
- long timeout;
- wait_queue_t wait;
+- 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);
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ serial->TiReadI2C = 1;
- /* 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);
+@@ -473,8 +472,8 @@ static int TIWriteBootMemory (struct edgeport_serial *serial, int start_address,
+ return status;
+ }
-- dbg("%s - stopping urbs", __FUNCTION__);
-+ dbg("%s - stopping urbs", __func__);
- usb_kill_urb (port->interrupt_in_urb);
- usb_kill_urb (port->interrupt_out_urb);
+- 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);
-@@ -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);
+ return status;
+ }
+@@ -495,8 +494,8 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
+ if (write_length > length)
+ write_length = length;
- /* 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 - 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);
-- 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;
+ /* 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;
}
-@@ -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;
- }
+@@ -522,8 +521,8 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
+ else
+ write_length = length;
- if (priv->line_control & CONTROL_RESET)
-@@ -825,7 +816,7 @@ static void cypress_send(struct usb_serial_port *port)
+- 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);
- 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;
- }
+ /* 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)
-- 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;
+ 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;
}
-- dbg("%s - count is %d", __FUNCTION__, count);
-+ dbg("%s - count is %d", __func__, count);
+@@ -580,7 +579,7 @@ static int TIIsTxActive (struct edgeport_port *port)
+ if (status)
+ goto exit_is_tx_active;
- 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);
+- dbg ("%s - XByteCount 0x%X", __FUNCTION__, oedb->XByteCount);
++ dbg ("%s - XByteCount 0x%X", __func__, oedb->XByteCount);
- 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;
+ /* and the LSR */
+ status = TIReadRam (port->port->serial->dev,
+@@ -590,7 +589,7 @@ static int TIIsTxActive (struct edgeport_port *port)
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ 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)
- spin_lock_irqsave(&priv->lock, flags);
- room = cypress_buf_space_avail(priv->buf);
- spin_unlock_irqrestore(&priv->lock, flags);
+ /* 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 );
-- dbg("%s - returns %d", __FUNCTION__, room);
-+ dbg("%s - returns %d", __func__, room);
- return room;
+ 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)));
}
-@@ -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);
+ 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.
- 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 - 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);
-- dbg("%s - result = %x", __FUNCTION__, result);
-+ dbg("%s - result = %x", __func__, result);
+ 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;
+ }
- 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);
+@@ -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)
- 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);
+ 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;
-- priv->cmd_ctrl = 1;
- return cypress_write(port, NULL, 0);
- }
+ 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)
-@@ -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);
+ 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 - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
-+ dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
+- dbg ("%s Type = 0x%x", __FUNCTION__, rom_desc->Type);
++ dbg ("%s Type = 0x%x", __func__, rom_desc->Type);
- 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;
+ // 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);
-- 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);
+ 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 );
- 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;
+ exit:
+ kfree (rom_desc);
+@@ -903,7 +902,7 @@ static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev)
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ 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;
+ }
- tty = port->tty;
-- if ((!tty) || (!tty->termios)) {
-- dbg("%s - no tty structures", __FUNCTION__);
-- return;
-- }
+- 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)
- 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;
+ 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;
}
- 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;
+@@ -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;
- /* 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);
-+ }
+- dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN DOWNLOAD MODE>>>>>>>>>>", __FUNCTION__);
++ dbg("%s - RUNNING IN DOWNLOAD MODE", __func__);
- /* 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;
+ status = TiValidateI2cImage (serial);
+ if (status) {
+- dbg ("%s - <<<<<<<<<<<<<<<DOWNLOAD MODE -- BAD I2C >>>>>>>>>>",
+- __FUNCTION__);
++ dbg("%s - DOWNLOAD MODE -- BAD I2C", __func__);
+ return status;
}
- } 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);
+
+@@ -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)
- 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);
+ // 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)
-- 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);
+ 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;
- /* 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 - Found Type FIRMWARE (Type 2) record", __FUNCTION__);
++ dbg ("%s - Found Type FIRMWARE (Type 2) record", __func__);
-- 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);
+ 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 - returns %d", __FUNCTION__, chars);
-+ dbg("%s - returns %d", __func__, chars);
- return chars;
- }
+ 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)
+ }
-@@ -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;
+ 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 - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg ("%s - HARDWARE RESET", __FUNCTION__);
++ dbg ("%s - HARDWARE RESET", __func__);
- 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;
+ // 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 - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg ( "%s - HARDWARE RESET return %d", __FUNCTION__, status);
++ dbg ( "%s - HARDWARE RESET return %d", __func__, status);
- 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)
+ /* return an error on purpose. */
+ kfree (firmware_version);
+@@ -1246,7 +1244,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
- 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;
+ 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__);
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ // 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);
- 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;
- }
+ 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);
- 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)
+- dbg ("%s - Start firmware update", __FUNCTION__);
++ dbg ("%s - Start firmware update", __func__);
- tty = port->tty;
- if (!tty) {
-- dbg("%s - bad tty pointer - exiting", __FUNCTION__);
-+ dbg("%s - bad tty pointer - exiting", __func__);
- return;
- }
+ // 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
- 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;
-+ }
+- dbg ("%s - Update complete 0x%x", __FUNCTION__, status);
++ dbg ("%s - Update complete 0x%x", __func__, status);
+ if (status) {
+- dev_err (dev, "%s - UMPC_COPY_DNLD_TO_I2C failed\n", __FUNCTION__);
++ dev_err (dev, "%s - UMPC_COPY_DNLD_TO_I2C failed\n", __func__);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return status;
+@@ -1346,8 +1344,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ /********************************************************************/
+ /* Boot Mode */
+ /********************************************************************/
+- dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN BOOT MODE>>>>>>>>>>>>>>>",
+- __FUNCTION__);
++ dbg("%s - RUNNING IN BOOT MODE", __func__);
-- usb_serial_debug_data (debug, &port->dev, __FUNCTION__,
-+ usb_serial_debug_data (debug, &port->dev, __func__,
- urb->actual_length, data);
+ // 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;
- 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;
+ 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;
}
- 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);
+@@ -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)
-@@ -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);
+ // 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;
}
-@@ -1426,12 +1361,12 @@ continue_read:
+
+@@ -1441,20 +1438,20 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ header->CheckSum = cs;
- static void cypress_write_int_callback(struct urb *urb)
+ // Download the operational code
+- dbg ("%s - Downloading operational code image (TI UMP)", __FUNCTION__);
++ dbg ("%s - Downloading operational code image (TI UMP)", __func__);
+ status = TIDownloadCodeImage (serial, buffer, buffer_size);
+
+ kfree (buffer);
+
+ if (status) {
+- dbg ("%s - Error downloading operational code image", __FUNCTION__);
++ dbg ("%s - Error downloading operational code image", __func__);
+ return status;
+ }
+
+ // Device will reboot
+ serial->product_info.TiMode = TI_MODE_TRANSITIONING;
+
+- dbg ("%s - Download successful -- Device rebooting...", __FUNCTION__);
++ dbg ("%s - Download successful -- Device rebooting...", __func__);
+
+ /* return an error on purpose */
+ return -ENODEV;
+@@ -1462,7 +1459,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+
+ StayInBootMode:
+ // Eprom is invalid or blank stay in boot mode
+- dbg ("%s - <<<<<<<<<<<<<<<STAYING IN BOOT MODE>>>>>>>>>>>>", __FUNCTION__);
++ dbg("%s - STAYING IN BOOT MODE", __func__);
+ serial->product_info.TiMode = TI_MODE_BOOT;
+
+ return 0;
+@@ -1473,7 +1470,7 @@ static int TISetDtr (struct edgeport_port *port)
{
-- 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;
+ int port_number = port->port->number - port->port->serial->minor;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+ port->shadow_mcr |= MCR_DTR;
- 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)
+ return TIWriteCommandSync (port->port->serial->dev,
+@@ -1488,7 +1485,7 @@ static int TIClearDtr (struct edgeport_port *port)
{
- int retval;
-
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
-
- retval = usb_serial_register(&cypress_earthmate_device);
- if (retval)
-@@ -1699,7 +1634,7 @@ failed_em_register:
+ int port_number = port->port->number - port->port->serial->minor;
- static void __exit cypress_exit (void)
+- 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)
{
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ int port_number = port->port->number - port->port->serial->minor;
- 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;
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+ port->shadow_mcr |= MCR_RTS;
- }
-@@ -746,7 +740,7 @@ static int digi_write_inb_command(struct usb_serial_port *port,
+ 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;
- 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;
- }
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+ port->shadow_mcr &= ~MCR_RTS;
-@@ -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;
- }
+ 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;
-@@ -903,7 +897,7 @@ static void digi_rx_unthrottle(struct usb_serial_port *port)
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
- 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 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__);
-@@ -1113,7 +1107,7 @@ static int digi_tiocmget(struct usb_serial_port *port, struct file *file)
- unsigned int val;
- unsigned long flags;
+ 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: TOP: port=%d", __FUNCTION__, priv->dp_port_num);
-+ dbg("%s: TOP: port=%d", __func__, priv->dp_port_num);
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
- 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;
+ 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: TOP: port=%d", __FUNCTION__, priv->dp_port_num);
-+ dbg("%s: TOP: port=%d", __func__, priv->dp_port_num);
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
- 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;
+ 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;
-@@ -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)
+- 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;
-- 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",
+- 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;
}
-@@ -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);
- }
+ 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;
+ }
- 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;
+ 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;
+
}
-@@ -1611,7 +1605,7 @@ static void digi_shutdown(struct usb_serial *serial)
+@@ -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 digi_read_bulk_callback(struct urb *urb)
+ static void edge_bulk_in_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",
+- 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;
- }
- 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;
+ default:
+ dev_err (&urb->dev->dev,"%s - nonzero read bulk status received: %d\n",
+- __FUNCTION__, status);
++ __func__, status);
}
- /* do not resubmit urb if it has any status error */
+ if (status == -EPIPE)
+ goto exit;
+
if (status) {
- err("%s: nonzero read bulk status: status=%d, port=%d",
-- __FUNCTION__, status, priv->dp_port_num);
-+ __func__, status, priv->dp_port_num);
+- dev_err(&urb->dev->dev,"%s - stopping read!\n", __FUNCTION__);
++ dev_err(&urb->dev->dev,"%s - stopping read!\n", __func__);
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)
- {
+@@ -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)
-- 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);
+ 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 (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);
+ 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);
+ }
- return(throttled ? 1 : 0);
+ 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
-@@ -1760,7 +1754,7 @@ static int digi_read_inb_callback(struct urb *urb)
- static int digi_read_oob_callback(struct urb *urb)
+ 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 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;
+ 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);
+- 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);
+ edge_port->ep_write_urb_in_use = 0;
- 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);
+@@ -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);
+ }
- return result;
- }
-@@ -183,7 +180,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
+ /* 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;
- 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;
+ if (edge_port == NULL)
+ return -ENODEV;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- if (port->tty)
+- port->tty->low_latency = low_latency;
++ port->tty->low_latency = low_latency;
- while (count > 0) {
+ 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)
+ }
-@@ -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);
+ 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);
- if (urb == NULL) {
-- dbg("%s - no more free urbs", __FUNCTION__);
-+ dbg("%s - no more free urbs", __func__);
- goto exit;
- }
+ dev = port->serial->dev;
- 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,
+@@ -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));
- memcpy (urb->transfer_buffer, current_position, transfer_size);
+- dbg ("%s - Sending UMPC_OPEN_PORT", __FUNCTION__);
++ dbg ("%s - Sending UMPC_OPEN_PORT", __func__);
-- 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);
+ /* 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;
+ }
- /* 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;
+@@ -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;
+ }
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ /* 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;
+ }
- spin_lock_irqsave (&write_urb_pool_lock, flags);
+@@ -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;
+ }
-@@ -291,7 +288,7 @@ static int empeg_write_room (struct usb_serial_port *port)
+@@ -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;
+ }
- spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+ ++edge_serial->num_ports_open;
-- dbg("%s - returns %d", __FUNCTION__, room);
-+ dbg("%s - returns %d", __func__, room);
+- dbg("%s - exited", __FUNCTION__);
++ dbg("%s - exited", __func__);
- return (room);
+ goto release_es_lock;
-@@ -304,7 +301,7 @@ static int empeg_chars_in_buffer (struct usb_serial_port *port)
- int i;
- int chars = 0;
+@@ -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)
- 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);
+ /* 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;
- return (chars);
+- dbg("%s - exited", __FUNCTION__);
++ dbg("%s - exited", __func__);
+ }
-@@ -329,11 +326,11 @@ static void empeg_write_bulk_callback (struct urb *urb)
- struct usb_serial_port *port = urb->context;
- int status = urb->status;
+ 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 (status) {
- dbg("%s - nonzero write bulk status received: %d",
-- __FUNCTION__, status);
-+ __func__, status);
- return;
+ if (count == 0) {
+- dbg("%s - write request of 0 bytes", __FUNCTION__);
++ dbg("%s - write request of 0 bytes", __func__);
+ return 0;
}
-@@ -343,21 +340,21 @@ static void empeg_write_bulk_callback (struct urb *urb)
+@@ -2185,7 +2181,7 @@ static void edge_send(struct usb_serial_port *port)
+ unsigned long flags;
- 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;
+ spin_lock_irqsave(&edge_port->ep_lock, flags);
-@@ -382,7 +379,7 @@ static void empeg_read_bulk_callback (struct urb *urb)
- result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+@@ -2207,7 +2203,7 @@ static void edge_send(struct usb_serial_port *port)
- 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);
+ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
- return;
+- 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);
-@@ -391,7 +388,7 @@ static void empeg_read_bulk_callback (struct urb *urb)
+ /* 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;
- 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);
+
+ 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;
}
-@@ -400,14 +397,14 @@ static void empeg_unthrottle (struct usb_serial_port *port)
- {
- int result;
+@@ -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);
- 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);
+ 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);
- return;
+- dbg ("%s - returns %d", __FUNCTION__, chars);
++ dbg ("%s - returns %d", __func__, chars);
+ return chars;
}
-@@ -417,14 +414,14 @@ static int empeg_startup (struct usb_serial *serial)
- {
- int r;
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+@@ -2283,14 +2279,14 @@ static void edge_throttle (struct usb_serial_port *port)
+ struct tty_struct *tty;
+ int status;
- 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);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- /* continue on with initialization */
-@@ -435,13 +432,13 @@ static int empeg_startup (struct usb_serial *serial)
+ if (edge_port == NULL)
+ return;
- static void empeg_shutdown (struct usb_serial *serial)
- {
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
- }
+ 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);
+ }
+ }
- 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);
+@@ -2316,14 +2312,14 @@ static void edge_unthrottle (struct usb_serial_port *port)
+ struct tty_struct *tty;
+ int status;
- 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;
- }
+ if (edge_port == NULL)
+ return;
+
+ tty = port->tty;
+ if (!tty) {
+- dbg ("%s - no tty available", __FUNCTION__);
++ dbg ("%s - no tty available", __func__);
+ return;
}
-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;
+@@ -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);
+ }
}
- 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;
+@@ -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);
}
- 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;
}
+@@ -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;
-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 */
- }
+- dbg("%s - port %d", __FUNCTION__, edge_port->port->number);
++ dbg("%s - port %d", __func__, edge_port->port->number);
- buf = kmalloc(1, GFP_NOIO);
-- if (!buf) {
-+ if (!buf)
- return -ENOMEM;
-- }
+ tty = edge_port->port->tty;
- 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;
+ 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;
}
- 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);
+@@ -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;
}
- /* 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);
+@@ -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 {
-- 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)
+ 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 (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]);
+ 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__);
}
-@@ -804,7 +801,7 @@ static void ftdi_determine_type(struct usb_serial_port *port)
+ /* 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__);
+ }
- 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__);
+ /* 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__);
}
- } 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;
+ }
+@@ -2503,7 +2499,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
-- dbg("%s",__FUNCTION__);
-+ dbg("%s",__func__);
+ /* FIXME: Recompute actual baud from divisor here */
- 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 - baud rate = %d, wBaudRate = %d", __FUNCTION__, baud, config->wBaudRate);
++ dbg ("%s - baud rate = %d, wBaudRate = %d", __func__, baud, config->wBaudRate);
-- dbg("%s: setting latency timer = %i", __FUNCTION__, v);
-+ dbg("%s: setting latency timer = %i", __func__, v);
+ 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);
+ }
- 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;
+ kfree (config);
+@@ -2542,12 +2538,12 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
-- dbg("%s: setting event char = %i", __FUNCTION__, v);
-+ dbg("%s: setting event char = %i", __func__, v);
+ cflag = tty->termios->c_cflag;
- 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 - 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",__FUNCTION__);
-+ dbg("%s",__func__);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- /* 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)
+ if (edge_port == NULL)
+ return;
+@@ -2562,9 +2558,11 @@ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsig
{
- struct ftdi_private *priv = usb_get_serial_port_data(port);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ unsigned int mcr;
++ unsigned long flags;
-- dbg("%s",__FUNCTION__);
-+ dbg("%s",__func__);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- /* 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);
++ 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);
-- dbg("%s",__FUNCTION__);
-+ dbg("%s",__func__);
+ TIRestoreMCR (edge_port, mcr);
- 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;
- }
+@@ -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;
-@@ -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__);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
++
++ spin_lock_irqsave(&edge_port->ep_lock, flags);
- 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__);
+ 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 */
- 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__);
+- dbg("%s -- %x", __FUNCTION__, result);
++ dbg("%s -- %x", __func__, result);
++ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
- 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__);
+ 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;
- 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 - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
++ dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ 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;
- 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);
+ 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;
- 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];
+ case TIOCSSERIAL:
+- dbg("%s - (%d) TIOCSSERIAL", __FUNCTION__, port->number);
++ dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
+ break;
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ 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;
- 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;
+ 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 port %d, %d bytes", __FUNCTION__, port->number, count);
-+ dbg("%s port %d, %d bytes", __func__, port->number, count);
+- dbg ("%s - state = %d", __FUNCTION__, break_state);
++ dbg ("%s - state = %d", __func__, break_state);
- 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;
+ /* 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)
}
- 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;
+ if (status) {
+ dbg ("%s - error %d sending break set/clear command.",
+- __FUNCTION__, status);
++ __func__, status);
}
+ }
- 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);
+@@ -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;
-- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size, buffer);
-+ usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, buffer);
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
- /* 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,
+ 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);
- 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: 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);
-- 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);
+ }
+@@ -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);
- if (status) {
- dbg("nonzero write bulk status received: %d", status);
-@@ -1398,7 +1395,7 @@ static void ftdi_write_bulk_callback (struct urb *urb)
+ 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)
+ }
- 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 (!retries && result) {
+- err("%s - failed doing control urb, error %d", __FUNCTION__,
++ err("%s - failed doing control urb, error %d", __func__,
+ result);
+ goto error;
}
- /* 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));
+@@ -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;
}
- 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);
+@@ -703,7 +700,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
- 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;
+ 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)
- 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)
+ 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;
- 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__);
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
return;
}
- if (urb != port->read_urb) {
-- err("%s - Not my urb!", __FUNCTION__);
-+ err("%s - Not my urb!", __func__);
- }
+- 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) {
-@@ -1506,7 +1503,7 @@ static void ftdi_read_bulk_callback (struct urb *urb)
+ 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;
+ }
- /* 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;
+@@ -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);
- if (port->open_count <= 0)
- return;
+ 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;
- tty = port->tty;
- if (!tty) {
-- dbg("%s - bad tty pointer - exiting",__FUNCTION__);
-+ dbg("%s - bad tty pointer - exiting",__func__);
- return;
+ if (priv->free_len <= 0) {
+- dbg("%s - we're stuffed", __FUNCTION__);
++ dbg("%s - we're stuffed", __func__);
+ return -EAGAIN;
}
- 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;
+@@ -811,12 +808,12 @@ static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *bu
}
-
- urb = port->read_urb;
- if (!urb) {
-- dbg("%s - bad read_urb pointer - exiting", __FUNCTION__);
-+ dbg("%s - bad read_urb pointer - exiting", __func__);
- return;
+ spin_unlock_irqrestore(&write_list_lock, flags);
+ if (pkt == NULL) {
+- dbg("%s - we're stuffed", __FUNCTION__);
++ dbg("%s - we're stuffed", __func__);
+ return -EAGAIN;
}
- data = urb->transfer_buffer;
+ 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);
- 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]);
+ 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);
}
-@@ -1594,17 +1591,17 @@ static void ftdi_process_read (struct work_struct *work)
+ } else {
+ spin_unlock_irqrestore(&write_list_lock, flags);
+@@ -872,17 +869,17 @@ static void ipaq_write_gather(struct usb_serial_port *port)
- 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;
- }
+ 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;
- 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;
- }
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-@@ -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__);
- }
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
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);
- }
+@@ -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);
- 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 - freelen %d", __FUNCTION__, priv->free_len);
++ dbg("%s - freelen %d", __func__, priv->free_len);
+ return priv->free_len;
+ }
-- 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);
+@@ -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;
}
-@@ -1763,18 +1760,18 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
- unsigned char vstop;
- unsigned char vstart;
+@@ -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)
- /* 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);
- }
+ static void ipaq_shutdown(struct usb_serial *serial)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ }
- /* 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;
- }
+ 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;
-@@ -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__);
- }
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- /* 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;
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
-- 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)
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
- 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);
+ 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;
}
-@@ -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);
+@@ -206,7 +206,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
+ u8 *buf_flow_init;
+ int result;
-- dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
-+ dbg("%s cmd 0x%04x", __func__, cmd);
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- /* 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);
+ 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)
- 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;
+ /* --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));
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ /*--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);
- 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;
+ /*--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);
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ /*--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)
- 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)
- {
+ /*--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);
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ /*--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;
- 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,
- };
+ if (tty_hung_up_p(filp)) {
+- dbg("%s: tty_hung_up_p ...", __FUNCTION__);
++ dbg("%s: tty_hung_up_p ...", __func__);
+ return;
+ }
-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) {
+ /*--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);
- usb_serial_debug_data(debug, &port->dev,
-- __FUNCTION__, actual_length, data);
-+ __func__, actual_length, data);
+ /*--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)
- 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;
+
+ /*--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__);
- 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;
+ port->write_urb_busy = 0;
-- dbg("%s - pkt-id: 0x%X.", __FUNCTION__, 0xFF & pkt_id);
-+ dbg("%s - pkt-id: 0x%X.", __func__, 0xFF & pkt_id);
+ if (status)
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
- *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_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;
- usb_serial_debug_data(debug, &garmin_data_p->port->dev,
-- __FUNCTION__, count-GSP_INITIAL_OFFSET, recpkt);
-+ __func__, count-GSP_INITIAL_OFFSET, recpkt);
+- dbg("%s: TOP: count=%d, in_interrupt=%ld", __FUNCTION__,
++ dbg("%s: TOP: count=%d, in_interrupt=%ld", __func__,
+ count, in_interrupt() );
- 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;
+ if (count == 0) {
+- dbg("%s - write request of 0 bytes", __FUNCTION__);
++ dbg("%s - write request of 0 bytes", __func__);
+ return 0;
}
-@@ -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;
+ 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);
-@@ -454,7 +454,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
+- dbg("%s count now:%d", __FUNCTION__, count);
++ dbg("%s count now:%d", __func__, 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;
+ 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;
}
-@@ -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);
+- dbg("%s returning %d", __FUNCTION__, count);
++ dbg("%s returning %d", __func__, count);
+ return count;
+ }
- k = garmin_data_p->outsize;
-@@ -658,13 +658,13 @@ static int gsp_send(struct garmin_data * garmin_data_p,
- return 0;
+@@ -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 - %d bytes in buffer, %d bytes in pkt.", __FUNCTION__,
-+ dbg("%s - %d bytes in buffer, %d bytes in pkt.", __func__,
- k, i);
+ 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;
- /* garmin_data_p->outbuffer now contains a complete packet */
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- usb_serial_debug_data(debug, &garmin_data_p->port->dev,
-- __FUNCTION__, k, garmin_data_p->outbuffer);
-+ __func__, k, garmin_data_p->outbuffer);
+ 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)
- garmin_data_p->outsize = 0;
+ 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);
-@@ -749,7 +749,7 @@ static void gsp_next_packet(struct garmin_data * garmin_data_p)
- struct garmin_packet *pkt = NULL;
+ return result;
+ }
- 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);
+ 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;
- 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;
- }
+- dbg("%s - port = %d, count = %d", __FUNCTION__, port->number, count);
++ dbg("%s - port = %d, count = %d", __func__, port->number, count);
-@@ -926,18 +926,18 @@ static int garmin_init_session(struct usb_serial_port *port)
- if (status == 0) {
- usb_kill_urb (port->interrupt_in_urb);
+ if (!port->tty) {
+- dev_err (&port->dev, "%s - no tty???\n", __FUNCTION__);
++ dev_err (&port->dev, "%s - no tty???\n", __func__);
+ return 0;
+ }
-- 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);
+@@ -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;
- 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);
+@@ -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);
- /*
- * 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);
+ port->write_urb_busy = 0;
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
-- 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);
+ usb_serial_debug_data (
+ debug,
+ &port->dev,
+- __FUNCTION__,
++ __func__,
+ urb->actual_length,
+ urb->transfer_buffer);
-@@ -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)
+@@ -420,16 +417,16 @@ static void ir_write_bulk_callback (struct urb *urb)
+
+ static void ir_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 tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+ int result;
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);
-- 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;
+ }
- 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)
+@@ -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);
- 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;
+@@ -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);
-- dbg("%s - port %d, state %d", __FUNCTION__, port->number,
-+ dbg("%s - port %d, state %d", __func__, port->number,
- garmin_data_p->state);
+ break ;
- spin_lock_irqsave(&garmin_data_p->lock, flags);
-@@ -1110,7 +1110,7 @@ static int garmin_write_bulk (struct usb_serial_port *port,
+ default:
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__,
++ __func__,
+ status);
+ break ;
- memcpy (buffer, buf, count);
+@@ -502,7 +499,7 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
+ speed_t baud;
+ int ir_baud;
-- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
-+ usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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;
+ 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;
+ }
-@@ -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;
+@@ -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;
-- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buf);
-+ usb_serial_debug_data(debug, &port->dev, __func__, count, buf);
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- /* 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)) {
+ 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 - processing private request %d",
-- __FUNCTION__, pktid);
-+ __func__, pktid);
+- dbg("%s - priv is not anymore in port structure", __FUNCTION__);
++ dbg("%s - priv is not anymore in port structure", __func__);
+ kfree(priv);
- // 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;
+- dbg("%s priv is now kfree", __FUNCTION__);
++ dbg("%s priv is now kfree", __func__);
+ }
+ }
- 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;
+@@ -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;
- 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,
+- 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)
{
- 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 ) {
+ 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;
+ }
-@@ -1286,28 +1286,28 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
- static void garmin_read_bulk_callback (struct urb *urb)
+ static void iuu_rxcmd(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;
- }
+ int result;
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
- if (status) {
- dbg("%s - nonzero read bulk status received: %d",
-- __FUNCTION__, status);
-+ __func__, status);
+ 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__);
- 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);
+ /* Prepare the reset sequence */
-@@ -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)
+@@ -232,19 +240,19 @@ static int iuu_reset(struct usb_serial_port *port, u8 wt)
+ */
+ static void iuu_update_status_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);
+ 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;
}
-- 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__);
+ 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)
- if (0 == (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
+ 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__);
-@@ -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 - 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 - start-of-session reply seen - serial %u.",
-- __FUNCTION__, garmin_data_p->serial_num);
-+ __func__, garmin_data_p->serial_num);
- }
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
- 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);
- }
+ 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__);
-@@ -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);
+ /* send the data out the bulk 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;
+@@ -309,9 +317,9 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
+ count, &actual, HZ * 1);
-- 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);
+ 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;
-@@ -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 - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ /* send the data out the bulk port */
- 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;
+@@ -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__);
}
- 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__);
+ return status;
+@@ -350,7 +358,7 @@ static int iuu_led(struct usb_serial_port *port, unsigned int R,
+ if (!buf)
+ return -ENOMEM;
- 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 - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ 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;
+ }
- /* 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);
- }
+@@ -384,7 +392,7 @@ static void iuu_rgbf_fill_buffer(u8 *buf, u8 r1, u8 r2, u8 g1, u8 g2, u8 b1,
- return result;
-@@ -159,7 +156,7 @@ static void generic_cleanup (struct usb_serial_port *port)
+ static void iuu_led_activity_on(struct urb *urb)
{
- 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)
+- 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)
- void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp)
+ static void iuu_led_activity_off(struct urb *urb)
{
-- 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 *
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
int result;
- unsigned char *data;
+ 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 - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
- if (count == 0) {
-- dbg("%s - write request of 0 bytes", __FUNCTION__);
-+ dbg("%s - write request of 0 bytes", __func__);
- return (0);
- }
+ 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)
-@@ -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;
+ status = bulk_immediate(port, (u8 *) priv->buf, Count);
+ if (status != 0) {
+- dbg("%s - write error ", __FUNCTION__);
++ dbg("%s - write error ", __func__);
+ return status;
}
- port->write_urb_busy = 1;
-@@ -230,7 +227,7 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
+ } else if (frq == 3579000) {
+@@ -562,7 +570,7 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq)
- 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);
+ 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;
+ }
- /* 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;
+@@ -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 - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
-+ /* FIXME: Locking */
- if (serial->num_bulk_out) {
- if (!(port->write_urb_busy))
- room = port->bulk_out_size;
- }
+ 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;
+ }
-- dbg("%s - returns %d", __FUNCTION__, room);
-- return (room);
-+ dbg("%s - returns %d", __func__, room);
-+ return room;
- }
+ 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;
+ }
- 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;
+ 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;
+ }
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ 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);
-+ /* FIXME: Locking */
- if (serial->num_bulk_out) {
- if (port->write_urb_busy)
- chars = port->write_urb->transfer_buffer_length;
+ 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 - returns %d", __FUNCTION__, chars);
-+ dbg("%s - returns %d", __func__, chars);
- return (chars);
- }
+- 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__);
-@@ -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);
- }
+ *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__);
- /* 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)
+ 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)
- void usb_serial_generic_read_bulk_callback (struct urb *urb)
+ 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;
- int status = urb->status;
- unsigned long flags;
+ priv->poll++;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
- if (unlikely(status != 0)) {
- dbg("%s - nonzero read bulk status received: %d",
-- __FUNCTION__, status);
-+ __func__, status);
+ 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__);
-- 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 (urb->actual_length == 1 && data != NULL)
+ len = (int) data[0];
- /* 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);
+ 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)
- void usb_serial_generic_write_bulk_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 status = urb->status;
+ int result;
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++ dbg("%s - urb->status = %d", __func__, urb->status);
- port->write_urb_busy = 0;
- if (status) {
- dbg("%s - nonzero write bulk status received: %d",
-- __FUNCTION__, status);
-+ __func__, status);
+ if (urb->status) {
+- dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++ dbg("%s - urb->status = %d", __func__, urb->status);
+ /* error stop all */
return;
}
--
- usb_serial_port_softint(port);
+@@ -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;
}
- 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);
+@@ -812,13 +820,13 @@ static int iuu_uart_on(struct usb_serial_port *port)
- /* 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;
+ 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);
- /* 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;
+ 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", __FUNCTION__);
-+ dbg("%s", __func__);
+- 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);
- /* 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,
- };
+@@ -1127,7 +1135,7 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp)
-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;
+ iuu_uart_flush(port);
-- dbg("%s - USB String ID = %d", __FUNCTION__, Id );
-+ dbg("%s - USB String ID = %d", __func__, Id );
+- dbg("%s - initialization done", __FUNCTION__);
++ dbg("%s - initialization done", __func__);
- 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);
+ 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)
- kfree(pStringDesc);
-- dbg("%s - USB String %s", __FUNCTION__, string);
-+ dbg("%s - USB String %s", __func__, string);
- return strlen(string);
+ 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);
-@@ -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;
+ static void keyspan_rx_throttle (struct usb_serial_port *port)
+ {
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+ }
-- 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);
+ static void keyspan_rx_unthrottle (struct usb_serial_port *port)
+ {
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+ }
-- 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)
+@@ -258,7 +258,7 @@ static void keyspan_break_ctl (struct usb_serial_port *port, int break_state)
{
-- 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;
+ struct keyspan_port_private *p_priv;
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+- 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;
- }
+ p_priv = usb_get_serial_port_data(port);
- // 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);
+@@ -280,7 +280,7 @@ static void keyspan_set_termios (struct usb_serial_port *port,
+ unsigned int cflag;
+ struct tty_struct *tty = port->tty;
- 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);
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- 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;
+ 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);
- /* 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);
+ 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;
+ }
- /* 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);
- }
- }
+- 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);
-@@ -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;
+ 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__);
+- 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;
- }
+ endpoint = usb_pipeendpoint(urb->pipe);
- 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;
+ if (status) {
+ dbg("%s - nonzero status: %x on endpoint %d.",
+- __FUNCTION__, status, endpoint);
++ __func__, status, endpoint);
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;
+- 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);
}
- } 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;
+ return;
+ }
+@@ -490,9 +490,9 @@ static void usa2x_outdat_callback(struct urb *urb)
+ struct usb_serial_port *port;
+ struct keyspan_port_private *p_priv;
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+- 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 (status) {
- dbg("%s - nonzero write bulk status received: %d",
-- __FUNCTION__, status);
-+ __func__, status);
- }
+ if (port->open_count)
+ usb_serial_port_softint(port);
+@@ -500,7 +500,7 @@ static void usa2x_outdat_callback(struct urb *urb)
- 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)
+ static void usa26_inack_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__);
+
+ }
-- 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;
- 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));
+- 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;
- /* clean up the transfer buffer */
-@@ -799,7 +799,7 @@ static void edge_bulk_out_cmd_callback (struct urb *urb)
- usb_free_urb (urb);
+- serial = (struct usb_serial *) urb->context;
++ serial = urb->context;
if (status) {
-- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, status);
-+ dbg("%s - nonzero write bulk status received: %d", __func__, status);
+- dbg("%s - nonzero status: %x", __FUNCTION__, status);
++ dbg("%s - nonzero status: %x", __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);
- }
+ 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;
}
-
-@@ -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)
+@@ -543,7 +543,7 @@ static void usa26_instat_callback(struct urb *urb)
- 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 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
- 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;
+@@ -552,7 +552,7 @@ static void usa26_instat_callback(struct urb *urb)
- if (!edge_port->write_urb) {
-- dbg("%s - no memory", __FUNCTION__);
-+ dbg("%s - no memory", __func__);
- edge_close (port, filp);
- return -ENOMEM;
+ /* 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: ;
+ }
-- 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;
+ static void usa26_glocont_callback(struct urb *urb)
+ {
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
}
-@@ -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__);
+@@ -597,9 +597,9 @@ static void usa28_indat_callback(struct urb *urb)
+ struct keyspan_port_private *p_priv;
+ int status = urb->status;
- // 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)
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
- // Is the Edgeport Buffer empty?
- if (lastCount == 0) {
-- dbg("%s - TX Buffer Empty", __FUNCTION__);
-+ dbg("%s - TX Buffer Empty", __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;
}
-@@ -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__);
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
+ p_priv = usb_get_serial_port_data(port);
+ data = urb->transfer_buffer;
- if (lastCount == fifo->count) {
- // No activity.. count down.
- loop--;
- if (loop == 0) {
-- dbg("%s - TIMEOUT", __FUNCTION__);
-+ dbg("%s - TIMEOUT", __func__);
- return;
+@@ -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);
}
- } 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);
- }
+ p_priv->in_flip ^= 1;
-@@ -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;
+@@ -639,7 +639,7 @@ static void usa28_indat_callback(struct urb *urb)
-- dbg("%s exited", __FUNCTION__);
-+ dbg("%s exited", __func__);
- }
+ static void usa28_inack_callback(struct urb *urb)
+ {
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+ }
- /*****************************************************************************
-@@ -1139,7 +1139,7 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
- int secondhalf;
- unsigned long flags;
+ 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;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
+ p_priv = usb_get_serial_port_data(port);
- 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));
+ 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;
-- 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);
+- serial = (struct usb_serial *) urb->context;
++ serial = urb->context;
- /* 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;
+ if (status) {
+- dbg("%s - nonzero status: %x", __FUNCTION__, status);
++ dbg("%s - nonzero status: %x", __func__, status);
+ return;
}
-@@ -1169,11 +1169,11 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
+ 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;
+ }
- 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);
+- /*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)
- /* 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]);
+ /* 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: ;
+ }
- // 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;
+ static void usa28_glocont_callback(struct urb *urb)
+ {
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+ }
- 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);
+@@ -731,15 +731,15 @@ static void usa49_glocont_callback(struct urb *urb)
+ struct keyspan_port_private *p_priv;
+ int i;
-- 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);
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
- return copySize;
- }
-@@ -1232,14 +1232,14 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
- int secondhalf;
- unsigned long flags;
+- 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);
-- dbg("%s(%d)", __FUNCTION__, edge_port->port->number);
-+ dbg("%s(%d)", __func__, edge_port->port->number);
+ 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;
- spin_lock_irqsave(&edge_port->ep_lock, flags);
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
- 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;
- }
+- serial = (struct usb_serial *) urb->context;
++ serial = urb->context;
-@@ -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;
+ if (status) {
+- dbg("%s - nonzero status: %x", __FUNCTION__, status);
++ dbg("%s - nonzero status: %x", __func__, status);
+ return;
}
-@@ -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 (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;
}
- 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]);
+- /*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)
- /* 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;
+ /* 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;
- /* revert the credits as something bad happened. */
- edge_port->txCredits += count;
- edge_port->icount.tx -= 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);
}
-- 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: ;
+ }
- 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;
+ static void usa49_inack_callback(struct urb *urb)
+ {
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+ }
-- 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;
- if (edge_port == NULL)
- return -ENODEV;
- if (edge_port->closePending)
- return -ENODEV;
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ endpoint = usb_pipeendpoint(urb->pipe);
- if (!edge_port->open) {
-- dbg("%s - port not opened", __FUNCTION__);
-+ dbg("%s - port not opened", __func__);
- return -EINVAL;
+ if (status) {
+- dbg("%s - nonzero status: %x on endpoint %d.", __FUNCTION__,
++ dbg("%s - nonzero status: %x on endpoint %d.", __func__,
+ status, endpoint);
+ return;
}
-
-@@ -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;
+
+- 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);
+ }
}
-@@ -1376,7 +1376,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
- int num_chars;
- unsigned long flags;
+@@ -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__);
+- 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;
+ serial = urb->context;
- if (!edge_port->open) {
-- dbg("%s - port not opened", __FUNCTION__);
-+ dbg("%s - port not opened", __func__);
- return -EINVAL;
+ if (status) {
+- dbg("%s - nonzero status: %x", __FUNCTION__, status);
++ dbg("%s - nonzero status: %x", __func__, status);
+ return;
}
-@@ -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);
- }
+@@ -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)
- return num_chars;
-@@ -1410,19 +1410,19 @@ static void edge_throttle (struct usb_serial_port *port)
- struct tty_struct *tty;
- int status;
+ 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);
+ }
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ /* 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__);
+ }
- if (edge_port == NULL)
- return;
+ 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;
- if (!edge_port->open) {
-- dbg("%s - port not opened", __FUNCTION__);
-+ dbg("%s - port not opened", __func__);
- return;
- }
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
- tty = port->tty;
- if (!tty) {
-- dbg ("%s - no tty available", __FUNCTION__);
-+ dbg ("%s - no tty available", __func__);
+ endpoint = usb_pipeendpoint(urb->pipe);
+
+ if (status) {
+ dbg("%s - nonzero status: %x on endpoint %d.",
+- __FUNCTION__, status, endpoint);
++ __func__, status, endpoint);
return;
}
-@@ -1459,19 +1459,19 @@ static void edge_unthrottle (struct usb_serial_port *port)
- struct tty_struct *tty;
- int status;
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
+ p_priv = usb_get_serial_port_data(port);
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ 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;
- if (edge_port == NULL)
- return;
+- serial = (struct usb_serial *) urb->context;
++ serial = urb->context;
- if (!edge_port->open) {
-- dbg("%s - port not opened", __FUNCTION__);
-+ dbg("%s - port not opened", __func__);
+ 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;
+ }
- tty = port->tty;
- if (!tty) {
-- dbg ("%s - no tty available", __FUNCTION__);
-+ dbg ("%s - no tty available", __func__);
- return;
+@@ -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;
-@@ -1509,18 +1509,18 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
- unsigned int cflag;
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
+ p_priv = usb_get_serial_port_data(port);
- 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);
+ 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 - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
- if (edge_port == NULL)
- return;
+ serial = urb->context;
- if (!edge_port->open) {
-- dbg("%s - port not opened", __FUNCTION__);
-+ dbg("%s - port not opened", __func__);
+ if (status) {
+- dbg("%s - nonzero status: %x", __FUNCTION__, status);
++ dbg("%s - nonzero status: %x", __func__, status);
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;
+ 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;
}
- 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;
+@@ -1125,7 +1125,7 @@ static void usa67_instat_callback(struct urb *urb)
-- 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;
+ /* 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;
+ }
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+@@ -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);
+ }
- 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;
+ 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 - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
- 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 */
+ 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 -- %x", __FUNCTION__, result);
-+ dbg("%s -- %x", __func__, result);
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ p_priv = usb_get_serial_port_data(port);
+ d_details = p_priv->device_details;
- return result;
++ /* 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;
}
-@@ -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;
+ static int keyspan_chars_in_buffer (struct usb_serial_port *port)
+ {
+- return (0);
++ 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;
+@@ -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;
- 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 - port%d.", __FUNCTION__, port->number);
++ dbg("%s - port%d.", __func__, port->number);
-- 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;
+ /* 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);
-- 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__);
+ 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);
}
}
-@@ -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__);
+@@ -1289,7 +1290,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
+ //mdelay(100);
+ //keyspan_set_termios(port, NULL);
- lastBufferLength = bufferLength + 1;
+- return (0);
++ return 0;
+ }
- 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;
+ 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 - Hdr1=%02X Hdr2=%02X", __FUNCTION__, edge_serial->rxHeader1, edge_serial->rxHeader2);
-+ dbg("%s - Hdr1=%02X Hdr2=%02X", __func__, edge_serial->rxHeader1, edge_serial->rxHeader2);
+- 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)
+ }
- // 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);
+ /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
+- dbg("%s - urb in progress", __FUNCTION__);
++ dbg("%s - urb in progress", __func__);
+ }*/
-- 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);
+ 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 */
- //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 - 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;
}
-- dbg("%s - port %d", __FUNCTION__, edge_serial->rxPort);
-+ dbg("%s - port %d", __func__, edge_serial->rxPort);
+@@ -1588,7 +1589,7 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
+ struct callbacks *cback;
+ int endp;
- 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;
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
- 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);
+ 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);
- /* 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;
+ /* 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);
- 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);
+ /* 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;
- // 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;
+- dbg ("%s - %d.", __FUNCTION__, baud_rate);
++ dbg ("%s - %d.", __func__, baud_rate);
- default:
-- dbg("%s - Unrecognized IOSP status code %u\n", __FUNCTION__, code);
-+ dbg("%s - Unrecognized IOSP status code %u\n", __func__, code);
- break;
+ /* 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) */
-@@ -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);
+- dbg ("%s - %d.", __FUNCTION__, baud_rate);
++ dbg ("%s - %d.", __func__, baud_rate);
- 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;
+ /* 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);
+ }
-- dbg("%s - %02x", __FUNCTION__, newLsr);
-+ dbg("%s - %02x", __func__, newLsr);
+@@ -1864,7 +1865,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
+ struct urb *this_urb;
+ int device_port, err;
- edge_port->shadowLSR = lsr;
+- dbg ("%s reset=%d", __FUNCTION__, reset_port);
++ dbg ("%s reset=%d", __func__, reset_port);
-@@ -2136,11 +2136,11 @@ static int sram_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u
- __u16 current_length;
- unsigned char *transfer_buffer;
+ 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 - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
-+ dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
+- dbg("%s - endpoint %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe));
++ dbg("%s - endpoint %d", __func__, usb_pipeendpoint(this_urb->pipe));
- 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;
+ /* 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;
}
-@@ -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);
+@@ -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,
- 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;
+ 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
-@@ -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;
+- return (0);
++ return 0;
+ }
-- dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
-+ dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
+ 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;
- 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;
- }
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
-@@ -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;
+ 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,
-- dbg("%s - %d, %d", __FUNCTION__, command, param);
-+ dbg("%s - %d, %d", __func__, command, param);
+ /* 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;
+ }
- 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;
+@@ -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,
-@@ -2304,7 +2304,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
- struct urb *urb;
- int timeout;
+ 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
-- usb_serial_debug_data(debug, &edge_port->port->dev, __FUNCTION__, length, buffer);
-+ usb_serial_debug_data(debug, &edge_port->port->dev, __func__, length, buffer);
+- return (0);
++ return 0;
+ }
- /* 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;
+ 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;
- 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));
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
- 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
+ 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;
- 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
+- 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);
- 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;
+ /* 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;
}
-- dbg("%s - port = %d, baud = %d", __FUNCTION__, edge_port->port->number, baudRate);
-+ dbg("%s - port = %d, baud = %d", __func__, edge_port->port->number, baudRate);
+@@ -2171,7 +2172,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
+ p_priv->resend_cont = reset_port + 1;
- 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;
+ if (this_urb->status == -EINPROGRESS) {
+- /* dbg ("%s - already writing", __FUNCTION__); */
++ /* dbg ("%s - already writing", __func__); */
+ mdelay(5);
+ return(-1);
}
-
- // 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;
+@@ -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;
}
- currCmd = cmdBuffer;
-@@ -2414,7 +2414,7 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor)
- __u16 custom;
+ 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;
+ }
-- dbg("%s - %d", __FUNCTION__, baudrate);
-+ dbg("%s - %d", __func__, baudrate);
+ 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;
- 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)
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
- *divisor = custom;
+ 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,
-- dbg("%s - Baud %d = %d\n", __FUNCTION__, baudrate, custom);
-+ dbg("%s - Baud %d = %d\n", __func__, baudrate, custom);
- return 0;
+ /* 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;
}
-@@ -2452,7 +2452,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
- unsigned long cmdLen = 0;
- int status;
+@@ -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,
-- 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);
+ 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;
+ }
- 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;
+ 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 - port %d", __FUNCTION__, edge_port->port->number);
-+ dbg("%s - port %d", __func__, edge_port->port->number);
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
- if (!edge_port->open &&
- !edge_port->openPending) {
-- dbg("%s - port not opened", __FUNCTION__);
-+ dbg("%s - port not opened", __func__);
- return;
- }
+ 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,
- tty = edge_port->port->tty;
- if ((!tty) ||
- (!tty->termios)) {
-- dbg("%s - no tty structures", __FUNCTION__);
-+ dbg("%s - no tty structures", __func__);
- return;
+ /* 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;
}
-
- 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;
+@@ -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,
- 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__);
- }
+ 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;
+ }
- 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__);
- }
+ 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;
- /* 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__);
- }
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __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__);
- }
+ 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;
- /* 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__);
- }
- }
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
-@@ -2645,7 +2645,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
- baud = 9600;
+ 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;
}
-- 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__);
+ /* 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;
}
- 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);
+@@ -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);
}
- return response;
+ 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;
}
-@@ -3032,7 +3032,7 @@ static void edge_shutdown (struct usb_serial *serial)
- struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
- int i;
+
+ 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__);
- /* 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 = {
+ 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 = "EPiC device",
- .id_table = Epic_port_id_table,
-- .num_interrupt_in = 1,
-- .num_bulk_in = 1,
-- .num_bulk_out = 1,
+ .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,
- .open = edge_open,
- .close = edge_close,
-diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
-index cd34059..05e4fa7 100644
---- a/drivers/usb/serial/io_ti.c
-+++ b/drivers/usb/serial/io_ti.c
-@@ -38,7 +38,6 @@
- #include <linux/serial.h>
- #include <linux/ioctl.h>
- #include <asm/uaccess.h>
--#include <asm/semaphore.h>
- #include <linux/usb.h>
- #include <linux/usb/serial.h>
+ .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);
+ }
-@@ -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)
+
+ static void keyspan_pda_rx_interrupt (struct urb *urb)
{
- int port_number = port->number - port->serial->minor;
+- 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;
+ }
-- dbg ("%s - port %d, mask %x", __FUNCTION__, port_number, mask);
-+ dbg ("%s - port %d, mask %x", __func__, port_number, mask);
+@@ -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);
+ }
- 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;
+@@ -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:
- 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
+ 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;
- if (status) {
-- dbg ("%s - ERROR %x", __FUNCTION__, status);
-+ dbg ("%s - ERROR %x", __func__, status);
- return status;
- }
+ 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;
- if (read_length > 1) {
-- usb_serial_debug_data(debug, &dev->dev, __FUNCTION__,
-+ usb_serial_debug_data(debug, &dev->dev, __func__,
- read_length, buffer);
- }
+ priv = usb_get_serial_port_data(port);
-@@ -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;
- }
- }
+ /* 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;
+ }
-- 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;
+@@ -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;
+ }
-@@ -473,8 +472,8 @@ static int TIWriteBootMemory (struct edgeport_serial *serial, int start_address,
- return status;
+@@ -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;
}
-- 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);
+@@ -779,7 +784,7 @@ static int keyspan_pda_startup (struct usb_serial *serial)
- return status;
+ static void keyspan_pda_shutdown (struct usb_serial *serial)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ kfree(usb_get_serial_port_data(serial->port[0]));
}
-@@ -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;
- }
+@@ -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..f328948 100644
+--- a/drivers/usb/serial/kl5kusb105.c
++++ b/drivers/usb/serial/kl5kusb105.c
+@@ -54,6 +54,7 @@
+ #include <linux/tty_flip.h>
+ #include <linux/module.h>
+ #include <asm/uaccess.h>
++#include <asm/unaligned.h>
+ #include <linux/usb.h>
+ #include <linux/usb/serial.h>
+ #include "kl5kusb105.h"
+@@ -126,9 +127,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 +192,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 +223,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
+ __u8 status_buf[KLSI_STATUSBUF_LEN] = { -1,-1};
+ __u16 status;
-@@ -522,8 +521,8 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
- else
- write_length = length;
+- 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,
+@@ -238,9 +236,9 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
+ if (rc < 0)
+ err("Reading line status failed (error = %d)", rc);
+ else {
+- status = le16_to_cpu(*(u16 *)status_buf);
++ status = le16_to_cpu(get_unaligned((__le16 *)status_buf));
-- 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);
+- info("%s - read status %x %x", __FUNCTION__,
++ info("%s - read status %x %x", __func__,
+ status_buf[0], status_buf[1]);
- /* 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;
+ *line_state_p = klsi_105_status2linestate(status);
+@@ -268,7 +266,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;
}
-
-@@ -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);
+@@ -298,7 +296,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 +326,7 @@ static void klsi_105_shutdown (struct usb_serial *serial)
+ {
+ int i;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- /* and the LSR */
- status = TIReadRam (port->port->serial->dev,
-@@ -590,7 +589,7 @@ static int TIIsTxActive (struct edgeport_port *port)
+ /* stop reads and writes on all ports */
+ for (i=0; i < serial->num_ports; ++i) {
+@@ -373,7 +371,7 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
+ struct klsi_105_port_settings cfg;
+ unsigned long flags;
- 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)
+- dbg("%s port %d", __FUNCTION__, port->number);
++ dbg("%s port %d", __func__, port->number);
- /* 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 );
+ /* force low_latency on so that our tty_push actually forces
+ * the data through
+@@ -419,7 +417,7 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
- 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)));
- }
+ 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 +435,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__);
- 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.
+ 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 +457,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 - 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);
+- dbg("%s port %d", __FUNCTION__, port->number);
++ dbg("%s port %d", __func__, port->number);
- 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;
- }
+ mutex_lock(&port->serial->disc_mutex);
+ if (!port->serial->disconnected) {
+@@ -502,7 +500,7 @@ static int klsi_105_write (struct usb_serial_port *port,
+ int result, size;
+ int bytes_sent=0;
-@@ -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)
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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;
+ while (count > 0) {
+ /* try to find a free urb (write 0 bytes if none) */
+@@ -514,21 +512,21 @@ static int klsi_105_write (struct usb_serial_port *port,
+ for (i=0; i<NUM_URBS; i++) {
+ if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
+ urb = priv->write_urb_pool[i];
+- dbg("%s - using pool URB %d", __FUNCTION__, i);
++ dbg("%s - using pool URB %d", __func__, i);
+ break;
+ }
+ }
+ spin_unlock_irqrestore (&priv->lock, flags);
- if (*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 (urb==NULL) {
+- dbg("%s - no more free urbs", __FUNCTION__);
++ dbg("%s - no more free urbs", __func__);
+ goto exit;
+ }
- 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;
+ 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 +552,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 +568,13 @@ exit:
-- dbg ("%s Type = 0x%x", __FUNCTION__, rom_desc->Type);
-+ dbg ("%s Type = 0x%x", __func__, rom_desc->Type);
+ 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;
- // Skip type 2 record
- ttype = rom_desc->Type & 0x0f;
-@@ -846,13 +845,13 @@ static int TIReadManufDescriptor (struct edgeport_serial *serial, __u8 *buffer)
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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;
+ if (status) {
+- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
++ dbg("%s - nonzero write bulk status received: %d", __func__,
+ status);
+ return;
}
- start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_ION, rom_desc);
+@@ -603,7 +601,7 @@ static int klsi_105_chars_in_buffer (struct usb_serial_port *port)
- 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 );
+ spin_unlock_irqrestore (&priv->lock, flags);
- exit:
- kfree (rom_desc);
-@@ -903,7 +902,7 @@ static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev)
+- dbg("%s - returns %d", __FUNCTION__, chars);
++ dbg("%s - returns %d", __func__, chars);
+ return (chars);
+ }
- 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;
- }
+@@ -623,7 +621,7 @@ static int klsi_105_write_room (struct usb_serial_port *port)
-- 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)
+ spin_unlock_irqrestore (&priv->lock, flags);
- 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;
- }
+- dbg("%s - returns %d", __FUNCTION__, room);
++ dbg("%s - returns %d", __func__, room);
+ return (room);
+ }
-@@ -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;
+@@ -631,18 +629,18 @@ static int klsi_105_write_room (struct usb_serial_port *port)
-- dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN DOWNLOAD MODE>>>>>>>>>>", __FUNCTION__);
-+ dbg("%s - RUNNING IN DOWNLOAD MODE", __func__);
+ 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;
- status = TiValidateI2cImage (serial);
- if (status) {
-- dbg ("%s - <<<<<<<<<<<<<<<DOWNLOAD MODE -- BAD I2C >>>>>>>>>>",
-- __FUNCTION__);
-+ dbg("%s - DOWNLOAD MODE -- BAD I2C", __func__);
- return status;
- }
-
-@@ -1101,7 +1099,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
- */
- ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL);
- if (!ti_manuf_desc) {
-- dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
-+ dev_err (dev, "%s - out of memory.\n", __func__);
- return -ENOMEM;
- }
- status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc);
-@@ -1112,7 +1110,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- // 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)
+ /* 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 +650,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 +667,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);
- 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;
+ 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 +695,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 */
-- 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);
+@@ -705,12 +703,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 +718,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 +733,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 +762,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);
- 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 ((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 +813,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;
- 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;
- }
+@@ -837,6 +842,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 +869,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 ("%s - HARDWARE RESET", __FUNCTION__);
-+ dbg ("%s - HARDWARE RESET", __func__);
+- dbg("%sstate=%d", __FUNCTION__, break_state);
++ dbg("%sstate=%d", __func__, break_state);
- // 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
+ if (break_state)
+ lcr |= MCT_U232_SET_BREAK;
+@@ -877,7 +884,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__);
-- dbg ( "%s - HARDWARE RESET return %d", __FUNCTION__, status);
-+ dbg ( "%s - HARDWARE RESET return %d", __func__, status);
+ rc = klsi_105_get_line_state(port, &line_state);
+ if (rc < 0) {
+@@ -889,7 +896,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;
+ }
- /* return an error on purpose. */
- kfree (firmware_version);
-@@ -1246,7 +1244,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+@@ -898,7 +905,7 @@ static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
+ {
+ int retval = -EINVAL;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- 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__);
+ /* if this ever gets implemented, it should be done something like this:
+ struct usb_serial *serial = port->serial;
+@@ -924,7 +931,7 @@ static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
- // 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);
+ 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);
+ }
- 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);
+@@ -932,12 +939,12 @@ static void klsi_105_unthrottle (struct usb_serial_port *port)
+ {
+ int result;
-- dbg ("%s - Start firmware update", __FUNCTION__);
-+ dbg ("%s - Start firmware update", __func__);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- // 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
+ 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);
+ }
-- dbg ("%s - Update complete 0x%x", __FUNCTION__, status);
-+ dbg ("%s - Update complete 0x%x", __func__, status);
- if (status) {
-- dev_err (dev, "%s - UMPC_COPY_DNLD_TO_I2C failed\n", __FUNCTION__);
-+ dev_err (dev, "%s - UMPC_COPY_DNLD_TO_I2C failed\n", __func__);
- kfree (rom_desc);
- kfree (ti_manuf_desc);
- return status;
-@@ -1346,8 +1344,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
- /********************************************************************/
- /* Boot Mode */
- /********************************************************************/
-- dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN BOOT MODE>>>>>>>>>>>>>>>",
-- __FUNCTION__);
-+ dbg("%s - RUNNING IN BOOT MODE", __func__);
+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;
+ };
- // 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)
+@@ -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;
- // Registry variable set?
- if (TIStayInBootMode) {
-- dbg ("%s - TIStayInBootMode", __FUNCTION__);
-+ dbg ("%s - TIStayInBootMode", __func__);
- goto StayInBootMode;
+ 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);
-@@ -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)
+ 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;
- // 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__);
+- 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;
}
-
-@@ -1441,20 +1438,20 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
- header->CheckSum = cs;
+@@ -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] );
- // 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);
+ 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 (buffer);
+ kfree(transfer_buffer);
+@@ -339,7 +332,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
- if (status) {
-- dbg ("%s - Error downloading operational code image", __FUNCTION__);
-+ dbg ("%s - Error downloading operational code image", __func__);
- return status;
- }
+ 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);
- // Device will reboot
- serial->product_info.TiMode = TI_MODE_TRANSITIONING;
+ 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 - Download successful -- Device rebooting...", __FUNCTION__);
-+ dbg ("%s - Download successful -- Device rebooting...", __func__);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- /* return an error on purpose */
- return -ENODEV;
-@@ -1462,7 +1459,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ if (status) {
+ dbg("%s - port %d Read int status not zero: %d",
+- __FUNCTION__, port->number, status);
++ __func__, port->number, status);
+ return;
+ }
- StayInBootMode:
- // Eprom is invalid or blank stay in boot mode
-- dbg ("%s - <<<<<<<<<<<<<<<STAYING IN BOOT MODE>>>>>>>>>>>>", __FUNCTION__);
-+ dbg("%s - STAYING IN BOOT MODE", __func__);
- serial->product_info.TiMode = TI_MODE_BOOT;
+@@ -393,7 +386,7 @@ static void kobil_read_int_callback(struct urb *urb)
+ port->interrupt_in_urb->dev = port->serial->dev;
- return 0;
-@@ -1473,7 +1470,7 @@ static int TISetDtr (struct edgeport_port *port)
- {
- int port_number = port->port->number - port->port->serial->minor;
+ 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);
+ }
-- 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;
+@@ -411,21 +404,21 @@ static int kobil_write (struct usb_serial_port *port,
+ struct kobil_private * priv;
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
- port->shadow_mcr &= ~MCR_DTR;
+ 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;
+ }
- 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;
+ priv = usb_get_serial_port_data(port);
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
- port->shadow_mcr |= MCR_RTS;
+ 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;
+ }
- 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;
+ // Copy data to buffer
+ memcpy (priv->buf + priv->filled, buf, count);
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
- port->shadow_mcr &= ~MCR_RTS;
+- 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);
- 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;
+ priv->filled = priv->filled + count;
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
+@@ -457,7 +450,7 @@ static int kobil_write (struct usb_serial_port *port,
- 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;
+ 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;
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
+ 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,
- return TIWriteCommandSync (port->port->serial->dev,
- UMPC_SET_CLR_LOOPBACK,
-@@ -1561,7 +1558,7 @@ static int TISetBreak (struct edgeport_port *port)
+ static int kobil_write_room (struct usb_serial_port *port)
{
- int port_number = port->port->number - port->port->serial->minor;
-
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
+- //dbg("%s - port %d", __FUNCTION__, port->number);
++ //dbg("%s - port %d", __func__, port->number);
+ return 8;
+ }
- 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;
+@@ -522,16 +515,13 @@ static int kobil_tiocmget(struct usb_serial_port *port, struct file *file)
+ KOBIL_TIMEOUT);
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
+ 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]);
- 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;
++ result = 0;
++ if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0)
++ result = TIOCM_DSR;
+ kfree(transfer_buffer);
+- return priv->line_state;
++ return result;
+ }
-- dbg ("%s - %x", __FUNCTION__, mcr);
-+ dbg ("%s - %x", __func__, mcr);
+ 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;
- 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;
++ /* 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,
-- dbg ("%s - %02x", __FUNCTION__, msr);
-+ dbg ("%s - %02x", __func__, msr);
+ 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__);
- 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));
+ 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 - %02x", __FUNCTION__, new_lsr);
-+ dbg ("%s - %02x", __func__, new_lsr);
+- dbg("%s port %d", __FUNCTION__, port->number);
++ dbg("%s port %d", __func__, port->number);
- edge_port->shadow_lsr = lsr;
+ /* 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);
-@@ -1713,7 +1710,7 @@ static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8
+ 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 edge_interrupt_callback (struct urb *urb)
+ static void mct_u232_read_int_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)
+- 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",
@@ -715615,11261 +942222,20285 @@
+ __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);
+ dbg("%s - nonzero urb status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
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__);
+ if (!serial) {
+- dbg("%s - bad serial pointer, exiting", __FUNCTION__);
++ dbg("%s - bad serial pointer, exiting", __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:
+- 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)
- 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);
- }
+ err ("%s - usb_submit_urb failed with result %d",
+- __FUNCTION__, retval);
++ __func__, retval);
+ } /* mct_u232_read_int_callback */
- if (status == -EPIPE)
- goto exit;
+ 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,
- if (status) {
-- dev_err(&urb->dev->dev,"%s - stopping read!\n", __FUNCTION__);
-+ dev_err(&urb->dev->dev,"%s - stopping read!\n", __func__);
- return;
+ /* 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));
-@@ -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)
+ 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;
- 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);
+- dbg("%sstate=%d", __FUNCTION__, break_state);
++ dbg("%sstate=%d", __func__, break_state);
- 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);
- }
+ 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__);
- 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
+ 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__);
- static void edge_bulk_out_callback (struct urb *urb)
+ 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)
{
-- 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);
+- dbg("%scmd=0x%x", __FUNCTION__, cmd);
++ dbg("%scmd=0x%x", __func__, cmd);
- edge_port->ep_write_urb_in_use = 0;
+ /* 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;
-@@ -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);
+- 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;
- /* 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;
-
+ tty = port->tty;
- dbg("%s - port %d", __FUNCTION__, port->number);
+ dbg("%s - port %d", __func__, port->number);
- if (edge_port == NULL)
- return -ENODEV;
+ 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;
-- if (port->tty)
-- port->tty->low_latency = low_latency;
-+ port->tty->low_latency = low_latency;
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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)
+ 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;
+ }
- 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);
+@@ -214,7 +214,7 @@ static void mos7720_bulk_in_callback(struct urb *urb)
- dev = port->serial->dev;
+ port = mos7720_port->port;
-@@ -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("Entering...%s", __FUNCTION__);
++ dbg("Entering...%s", __func__);
-- dbg ("%s - Sending UMPC_OPEN_PORT", __FUNCTION__);
-+ dbg ("%s - Sending UMPC_OPEN_PORT", __func__);
+ data = urb->transfer_buffer;
- /* 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;
+@@ -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);
}
-@@ -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;
- }
+ /* 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);
- /* 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;
- }
+ /* 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;
-@@ -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;
- }
+- dbg("%s:entering ...........", __FUNCTION__);
++ dbg("%s:entering ...........", __func__);
-@@ -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;
+ mos7720_port = usb_get_serial_port_data(port);
+ if (mos7720_port == NULL) {
+- dbg("%s:leaving ...........", __FUNCTION__);
++ dbg("%s:leaving ...........", __func__);
+ return -ENODEV;
}
- ++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;
+@@ -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;
+ }
-@@ -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);
+@@ -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;
- spin_lock_irqsave(&edge_port->ep_lock, flags);
+- dbg("Leaving %s", __FUNCTION__);
++ dbg("Leaving %s", __func__);
+ }
-@@ -2207,7 +2203,7 @@ static void edge_send(struct usb_serial_port *port)
+ 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;
- spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+- dbg("Entering %s", __FUNCTION__);
++ dbg("Entering %s", __func__);
-- 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);
+ serial = port->serial;
- /* 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)
+@@ -627,20 +627,21 @@ static int mos7720_write_room(struct usb_serial_port *port)
int room = 0;
- unsigned long flags;
+ int i;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg("%s:entering ...........", __FUNCTION__);
++ dbg("%s:entering ...........", __func__);
- if (edge_port == NULL)
+ mos7720_port = usb_get_serial_port_data(port);
+ if (mos7720_port == NULL) {
+- dbg("%s:leaving ...........", __FUNCTION__);
++ dbg("%s:leaving ...........", __func__);
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);
+ }
+
++ /* 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;
}
-@@ -2262,7 +2258,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
- int chars = 0;
- unsigned long flags;
+@@ -657,7 +658,7 @@ static int mos7720_write(struct usb_serial_port *port,
+ struct urb *urb;
+ const unsigned char *current_position = data;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg("%s:entering ...........", __FUNCTION__);
++ dbg("%s:entering ...........", __func__);
- 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);
+ serial = port->serial;
-- dbg ("%s - returns %d", __FUNCTION__, chars);
-+ dbg ("%s - returns %d", __func__, chars);
- return chars;
- }
+@@ -679,7 +680,7 @@ static int mos7720_write(struct usb_serial_port *port,
+ }
-@@ -2283,14 +2279,14 @@ static void edge_throttle (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", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg("%s- port %d\n", __FUNCTION__, port->number);
++ dbg("%s- port %d\n", __func__, port->number);
- if (edge_port == NULL)
+ 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__);
+- 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);
+@@ -773,15 +774,15 @@ static void mos7720_unthrottle(struct usb_serial_port *port)
+ return;
- if (edge_port == NULL)
+ 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__);
+- 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);
- }
- }
+@@ -922,7 +923,7 @@ static int calc_baud_rate_divisor(int baudrate, int *divisor)
+ __u16 round;
-@@ -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 - %d", __FUNCTION__, baudrate);
++ dbg("%s - %d", __func__, baudrate);
-- dbg("%s - port %d", __FUNCTION__, edge_port->port->number);
-+ dbg("%s - port %d", __func__, edge_port->port->number);
+ 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;
- tty = edge_port->port->tty;
+- dbg("%s: Entering ..........", __FUNCTION__);
++ dbg("%s: Entering ..........", __func__);
- 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;
+ 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;
}
-@@ -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;
+@@ -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;
}
-@@ -2434,32 +2430,32 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ 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) {
- config->wFlags |= UMP_MASK_UART_FLAGS_PARITY;
- config->bParity = UMP_UART_ODDPARITY;
+ lParity = UART_LCR_PARITY;
- dbg("%s - parity = odd", __FUNCTION__);
+ dbg("%s - parity = odd", __func__);
} else {
- config->wFlags |= UMP_MASK_UART_FLAGS_PARITY;
- config->bParity = UMP_UART_EVENPARITY;
+ lParity = (UART_LCR_EPAR | UART_LCR_PARITY);
- 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 & CMSPAR)
+@@ -1094,10 +1095,10 @@ static void change_port_settings(struct moschip_port *mos7720_port,
+ /* Change the Stop bit */
if (cflag & CSTOPB) {
- config->bStopBits = UMP_UART_STOPBIT2;
+ lStop = UART_LCR_STOP;
- dbg("%s - stop bits = 2", __FUNCTION__);
+ dbg("%s - stop bits = 2", __func__);
} else {
- config->bStopBits = UMP_UART_STOPBIT1;
+ lStop = 0x00;
- 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__);
- }
+ #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;
}
-@@ -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", __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,
-- 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);
+ if (!mos7720_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
}
- kfree (config);
-@@ -2542,12 +2538,12 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
+@@ -1225,15 +1226,15 @@ static void mos7720_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, 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);
+- dbg("%s - cflag %08x iflag %08x", __FUNCTION__,
++ dbg("%s - cflag %08x iflag %08x", __func__,
+ tty->termios->c_cflag,
+ RELEVANT_IFLAG(tty->termios->c_iflag));
- 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 - 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);
-+ 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;
+ /* 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,
- edge_port->shadow_mcr = mcr;
-+ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+ count = mos7720_chars_in_buffer(mos7720_port->port);
+ if (count == 0) {
+- dbg("%s -- Empty", __FUNCTION__);
++ dbg("%s -- Empty", __func__);
+ result = TIOCSER_TEMT;
+ }
- TIRestoreMCR (edge_port, mcr);
+@@ -1296,7 +1297,7 @@ static int get_number_bytes_avail(struct moschip_port *mos7720_port,
-@@ -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;
+ result = tty->read_cnt;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
-+
-+ spin_lock_irqsave(&edge_port->ep_lock, flags);
+- 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;
- 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 */
+@@ -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);
-+ 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;
+ 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:
-- 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 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(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(mos7720_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);
- break;
+ 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 TIOCSSERIAL:
-- dbg("%s - (%d) TIOCSSERIAL", __FUNCTION__, port->number);
-+ dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
- break;
+ 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 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 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 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;
+ case TIOCSSERIAL:
+- dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCSSERIAL", __func__, port->number);
+ break;
-- dbg ("%s - state = %d", __FUNCTION__, break_state);
-+ dbg ("%s - state = %d", __func__, break_state);
+ 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;
- /* 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);
- }
- }
+- 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;
-@@ -2735,7 +2738,7 @@ static int edge_startup (struct usb_serial *serial)
+- 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 */
- 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__);
+ 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;
}
- 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__);
+@@ -1533,7 +1534,7 @@ static int mos7720_startup(struct usb_serial *serial)
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,
+ 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 = 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)
+ .open = mos7720_open,
+ .close = mos7720_close,
+@@ -1620,7 +1618,7 @@ static int __init moschip7720_init(void)
{
- struct ipaq_private *priv = usb_get_serial_port_data(port);
+ int retval;
-- 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)
+- dbg("%s: Entering ..........", __FUNCTION__);
++ dbg("%s: Entering ..........", __func__);
- static void ipaq_read_bulk_callback(struct urb *urb)
+ /* 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 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);
+ struct async_icount *icount;
- 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)
+- dbg("%s - %02x", __FUNCTION__, new_lsr);
++ dbg("%s - %02x", __func__, new_lsr);
- 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;
+ 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;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- mos7840_port = (struct moschip_port *)urb->context;
++ mos7840_port = urb->context;
- if (status) {
- dbg("%s - nonzero write bulk status received: %d",
-- __FUNCTION__, status);
-+ __func__, status);
+ 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;
}
-@@ -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;
+- 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);
}
-
-- 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__);
+@@ -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;
- /*--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);
+- serial = (struct usb_serial *)urb->context;
++ serial = urb->context;
- usb_serial_port_softint(port);
+ /* 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);
+ }
}
-@@ -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;
+@@ -685,19 +685,19 @@ static void mos7840_bulk_in_callback(struct urb *urb)
+ return;
}
- 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;
+- mos7840_port = (struct moschip_port *)urb->context;
++ mos7840_port = urb->context;
+ if (!mos7840_port) {
+ dbg("%s", "NULL mos7840_port pointer \n");
+ return;
}
- 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;
+ 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;
}
-- dbg("%s returning %d", __FUNCTION__, count);
-+ dbg("%s returning %d", __func__, count);
- return count;
- }
+- 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;
-@@ -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;
+- 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 (desc->bDescriptorType != USB_DT_IRDA) {
-- dbg("%s - bad class descriptor type", __FUNCTION__);
-+ dbg("%s - bad class descriptor type", __func__);
- goto error;
+
+- 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;
}
-
-@@ -251,7 +248,7 @@ static int ir_startup (struct usb_serial *serial)
+@@ -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;
}
- 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;
+ serial = port->serial;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- 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);
+ }
- 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)
+@@ -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);
+ }
- 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;
+@@ -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)
}
- 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);
+ }
+ spin_unlock_irqrestore(&mos7840_port->pool_lock,flags);
+- dbg("%s - returns %d", __FUNCTION__, chars);
++ dbg("%s - returns %d", __func__, chars);
+ return chars;
- return result;
}
+@@ -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)
- 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\n", "mos7840_close:entering...");
-- dbg("%s - port = %d, count = %d", __FUNCTION__, port->number, count);
-+ dbg("%s - port = %d, count = %d", __func__, port->number, count);
+- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++ if (mos7840_port_paranoia_check(port, __func__)) {
+ dbg("%s", "Port Paranoia failed \n");
+ return;
+ }
- if (!port->tty) {
-- dev_err (&port->dev, "%s - no tty???\n", __FUNCTION__);
-+ dev_err (&port->dev, "%s - no tty???\n", __func__);
- return 0;
+- 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;
}
-@@ -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;
+- 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;
}
- 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
+ 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);
- 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;
+ if (urb == NULL) {
+- dbg("%s - no more free urbs", __FUNCTION__);
++ dbg("%s - no more free urbs", __func__);
+ goto exit;
+ }
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+@@ -1521,7 +1521,7 @@ static int mos7840_write(struct usb_serial_port *port,
+ kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
- port->write_urb_busy = 0;
+ 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) {
- dbg("%s - nonzero write bulk status received: %d",
+ 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)
- usb_serial_debug_data (
- debug,
- &port->dev,
-- __FUNCTION__,
-+ __func__,
- urb->actual_length,
- urb->transfer_buffer);
+ tty = port->tty;
+ if (!tty) {
+- dbg("%s - no tty available", __FUNCTION__);
++ dbg("%s - no tty available", __func__);
+ return;
+ }
-@@ -420,16 +417,16 @@ static void ir_write_bulk_callback (struct urb *urb)
+@@ -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);
- 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;
+- 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;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ if (!mos7840_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
+ }
- if (!port->open_count) {
-- dbg("%s - port closed.", __FUNCTION__);
-+ dbg("%s - port closed.", __func__);
+@@ -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;
}
-@@ -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);
+@@ -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);
-@@ -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);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- break ;
+ 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);
- default:
- dbg("%s - nonzero read bulk status received: %d",
-- __FUNCTION__,
-+ __func__,
- status);
- break ;
+- dbg("%s - 0x%04X", __FUNCTION__, result);
++ dbg("%s - 0x%04X", __func__, result);
-@@ -502,7 +499,7 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
- speed_t baud;
- int ir_baud;
+ 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);
- 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);
+ mos7840_port = mos7840_get_port_private(port);
- /* 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;
- }
+ if (mos7840_port == NULL)
+ return -ENODEV;
-@@ -109,7 +109,7 @@ static int iuu_startup(struct usb_serial *serial)
++ /* 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)
{
- 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 - %d", __FUNCTION__, baudRate);
++ dbg("%s - %d", __func__, baudRate);
-- dbg("%s - priv is not anymore in port structure", __FUNCTION__);
-+ dbg("%s - priv is not anymore in port structure", __func__);
- kfree(priv);
+ 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;
-- dbg("%s priv is now kfree", __FUNCTION__);
-+ dbg("%s priv is now kfree", __func__);
+ 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;
}
- }
-@@ -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;
+- 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,
-- 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;
+ number = mos7840_port->port->number - mos7840_port->port->serial->minor;
- 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;
- }
+- 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 */
-@@ -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;
- }
+ 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,
- 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__);
+ port = (struct usb_serial_port *)mos7840_port->port;
- if (urb->status) {
-- dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
-+ dbg("%s - urb->status = %d", __func__, urb->status);
- /* error stop all */
+- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++ if (mos7840_port_paranoia_check(port, __func__)) {
+ dbg("%s", "Invalid port \n");
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 */
+- if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {
++ if (mos7840_serial_paranoia_check(port->serial, __func__)) {
+ dbg("%s", "Invalid Serial \n");
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;
+ serial = port->serial;
-- dbg("%s - enter", __FUNCTION__);
-+ dbg("%s - enter", __func__);
+- dbg("%s - port %d", __FUNCTION__, mos7840_port->port->number);
++ dbg("%s - port %d", __func__, mos7840_port->port->number);
- /* send the data out the bulk port */
+ if (!mos7840_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
+ }
-@@ -309,9 +317,9 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
- count, &actual, HZ * 1);
+@@ -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__);
+ }
- 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__);
+- dbg("%s - parity = none", __FUNCTION__);
++ dbg("%s - parity = none", __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);
+ 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 {
-- dbg("%s - read OK !", __FUNCTION__);
-+ dbg("%s - read OK !", __func__);
+ lStop = LCR_STOP_1;
+- dbg("%s - stop bits = 1", __FUNCTION__);
++ dbg("%s - stop bits = 1", __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,
+ /* Update the LCR with the correct value */
+@@ -2100,7 +2101,7 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
+ baud = 9600;
+ }
- 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)
+- dbg("%s - baud rate = %d", __FUNCTION__, baud);
++ dbg("%s - baud rate = %d", __func__, baud);
+ status = mos7840_send_cmd_write_baud_rate(mos7840_port, baud);
- 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;
+ /* 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;
+ }
-- dbg("%s - enter", __FUNCTION__);
-+ dbg("%s - enter", __func__);
+ serial = port->serial;
- 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)
+- 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;
- 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)
+ if (!mos7840_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
+ }
- 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;
- }
+@@ -2168,11 +2169,11 @@ static void mos7840_set_termios(struct usb_serial_port *port,
-@@ -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);
+ cflag = tty->termios->c_cflag;
-- dbg("%s - enter", __FUNCTION__);
-+ dbg("%s - enter", __func__);
+- 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);
- 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;
- }
+ /* change the port settings to the new ones specified */
- 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;
- }
+@@ -2213,7 +2214,7 @@ static int mos7840_get_lsr_info(struct moschip_port *mos7840_port,
- 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;
- }
- }
+ count = mos7840_chars_in_buffer(mos7840_port->port);
+ if (count == 0) {
+- dbg("%s -- Empty", __FUNCTION__);
++ dbg("%s -- Empty", __func__);
+ result = TIOCSER_TEMT;
}
-- 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);
+@@ -2240,7 +2241,7 @@ static int mos7840_set_modem_info(struct moschip_port *mos7840_port,
+ return -1;
- 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;
+ 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 - %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__);
+- dbg("%s -- %x", __FUNCTION__, result);
++ dbg("%s -- %x", __func__, result);
- *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);
+ 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;
}
- 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__);
+@@ -2383,39 +2384,39 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
- 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)
+ tty = mos7840_port->port->tty;
- 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 - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
++ dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
-- dbg("%s - enter", __FUNCTION__);
-+ dbg("%s - enter", __func__);
+ switch (cmd) {
+ /* return number of bytes available */
- 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__);
+ 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;
- if (urb->actual_length == 1 && data != NULL)
- len = (int) data[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;
- 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)
+ case TIOCMGET:
+- dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCMGET", __func__, port->number);
+ return mos7840_get_modem_info(mos7840_port, argp);
- 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__);
+ case TIOCGSERIAL:
+- dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCGSERIAL", __func__, port->number);
+ return mos7840_get_serial_info(mos7840_port, argp);
- if (count > 256)
- return -ENOMEM;
-@@ -773,14 +781,14 @@ static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf,
+ case TIOCSSERIAL:
+- dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCSSERIAL", __func__, port->number);
+ break;
- 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__);
+ 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 - urb->status = %d", __FUNCTION__, urb->status);
-+ dbg("%s - urb->status = %d", __func__, urb->status);
+- 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.
+ */
- if (urb->status) {
-- dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
-+ dbg("%s - urb->status = %d", __func__, urb->status);
- /* error stop all */
+ #include <linux/kernel.h>
+@@ -49,15 +53,15 @@ static void navman_read_int_callback(struct urb *urb)
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+- __FUNCTION__, status);
++ __func__, status);
return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ goto exit;
}
-@@ -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)
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
- 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)
+ 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);
+ }
- status = bulk_immediate(port, buf, 1);
- if (status != IUU_OPERATION_OK)
-- dbg("%s - uart_off error", __FUNCTION__);
-+ dbg("%s - uart_off error", __func__);
+ static int navman_open(struct usb_serial_port *port, struct file *filp)
+ {
+ int result = 0;
- kfree(buf);
- return status;
-@@ -930,7 +938,7 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud,
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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;
+ 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;
}
-@@ -952,7 +960,7 @@ static void iuu_close(struct usb_serial_port *port, struct file *filp)
- if (!serial)
- return;
+ 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);
- 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);
+ 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);
-@@ -1127,7 +1135,7 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp)
+ /*
+ * 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;
+ }
- iuu_uart_flush(port);
+ 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)
-- dbg("%s - initialization done", __FUNCTION__);
-+ dbg("%s - initialization done", __func__);
+ 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;
- 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)
+- 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) {
- 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__);
+- err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
++ err("%s - failed submitting read urb, error %d", __func__, result);
}
+
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);
+@@ -186,7 +183,7 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
- static void keyspan_rx_throttle (struct usb_serial_port *port)
+ 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 keyspan_rx_unthrottle (struct usb_serial_port *port)
+ 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;
+ }
-@@ -258,7 +258,7 @@ static void keyspan_break_ctl (struct usb_serial_port *port, int break_state)
- {
- struct keyspan_port_private *p_priv;
+@@ -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);
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ return;
+ }
+@@ -251,17 +248,17 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
- p_priv = usb_get_serial_port_data(port);
+ int result;
-@@ -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 - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ if (count == 0) {
+- dbg("%s - write request of 0 bytes", __FUNCTION__);
++ dbg("%s - write request of 0 bytes", __func__);
+ return (0);
+ }
- 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,
+ 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;
}
-
- 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);
+ wport->write_urb_busy = 1;
+@@ -271,7 +268,7 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
- 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;
- }
+ memcpy (wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, 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);
+- 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);
- 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;
+ 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;
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
+@@ -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];
- endpoint = usb_pipeendpoint(urb->pipe);
+- 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 status: %x on endpoint %d.",
-- __FUNCTION__, status, endpoint);
-+ __func__, status, endpoint);
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
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;
+@@ -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__);
-- 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]);
+ 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.
+ */
- if (port->open_count)
- usb_serial_port_softint(port);
-@@ -500,7 +500,7 @@ static void usa2x_outdat_callback(struct urb *urb)
+-#define DRIVER_VERSION "v0.7.1"
++#define DRIVER_VERSION "v0.7.2"
+ #define DRIVER_AUTHOR "Matthias Urlichs <smurf at smurf.noris.de>"
+ #define DRIVER_DESC "USB Driver for GSM modems"
- static void usa26_inack_callback(struct urb *urb)
+@@ -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__);
-
+- 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);
+ static void option_rx_unthrottle(struct usb_serial_port *port)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ }
- 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);
- }
+ 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__);
}
-@@ -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;
+ 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,
- 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;
- }
+ portdata = usb_get_serial_port_data(port);
-@@ -543,7 +543,7 @@ static void usa26_instat_callback(struct urb *urb)
++ /* 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,
- #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
+ portdata = usb_get_serial_port_data(port);
-@@ -552,7 +552,7 @@ static void usa26_instat_callback(struct urb *urb)
+- dbg("%s: write (%d chars)", __FUNCTION__, count);
++ dbg("%s: write (%d chars)", __func__, count);
- /* 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);
+ 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,
}
- exit: ;
- }
- static void usa26_glocont_callback(struct urb *urb)
- {
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
-
+ count -= left;
+- dbg("%s: wrote (did %d)", __FUNCTION__, count);
++ dbg("%s: wrote (did %d)", __func__, count);
+ return count;
}
-@@ -597,9 +597,9 @@ static void usa28_indat_callback(struct urb *urb)
- struct keyspan_port_private *p_priv;
+@@ -544,14 +542,14 @@ static void option_indat_callback(struct urb *urb)
+ unsigned char *data = urb->transfer_buffer;
int status = urb->status;
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
+- 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;
- 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;
+ 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__);
}
-- port = (struct usb_serial_port *) urb->context;
-+ port = urb->context;
- p_priv = usb_get_serial_port_data(port);
- data = urb->transfer_buffer;
+ /* 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;
-@@ -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;
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
-@@ -639,7 +639,7 @@ static void usa28_indat_callback(struct urb *urb)
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
- static void usa28_inack_callback(struct urb *urb)
+ usb_serial_port_softint(port);
+
+@@ -599,19 +597,19 @@ static void option_instat_callback(struct urb *urb)
{
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
- }
+ 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;
- 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;
+- 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);
-- port = (struct usb_serial_port *) urb->context;
-+ port = urb->context;
- p_priv = usb_get_serial_port_data(port);
+ if (status == 0) {
+ struct usb_ctrlrequest *req_pkt =
+ (struct usb_ctrlrequest *)urb->transfer_buffer;
- 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;
+ 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));
-- serial = (struct usb_serial *) urb->context;
-+ serial = urb->context;
+- dbg("%s: signal x%x", __FUNCTION__, signals);
++ dbg("%s: signal x%x", __func__, signals);
- if (status) {
-- dbg("%s - nonzero status: %x", __FUNCTION__, status);
-+ dbg("%s - nonzero status: %x", __func__, status);
- return;
- }
+ 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);
- 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;
+ /* 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);
}
+ }
-- /*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)
+@@ -658,13 +656,14 @@ static int option_write_room(struct usb_serial_port *port)
- /* 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);
+ 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;
}
- exit: ;
- }
- static void usa28_glocont_callback(struct urb *urb)
- {
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
+- 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)
-@@ -731,15 +731,15 @@ static void usa49_glocont_callback(struct urb *urb)
- struct keyspan_port_private *p_priv;
- int i;
+ 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;
+ }
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
+@@ -695,7 +696,7 @@ static int option_open(struct usb_serial_port *port, struct file *filp)
-- 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);
+ portdata = 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__);
-- 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;
-- serial = (struct usb_serial *) urb->context;
-+ serial = urb->context;
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ portdata = usb_get_serial_port_data(port);
- if (status) {
-- dbg("%s - nonzero status: %x", __FUNCTION__, status);
-+ dbg("%s - nonzero status: %x", __func__, status);
- return;
- }
+ portdata->rts_state = 0;
+@@ -782,7 +783,7 @@ static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
- 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;
+ 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;
}
-- /*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)
+@@ -801,7 +802,7 @@ static void option_setup_urbs(struct usb_serial *serial)
+ struct usb_serial_port *port;
+ struct option_port_private *portdata;
- /* 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;
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- 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);
+ 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)
}
- exit: ;
}
- static void usa49_inack_callback(struct urb *urb)
++
++/** 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)
{
-- 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;
+ 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__);
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
+ portdata = usb_get_serial_port_data(port);
- endpoint = usb_pipeendpoint(urb->pipe);
+@@ -844,7 +848,7 @@ static int option_send_setup(struct usb_serial_port *port)
- if (status) {
-- dbg("%s - nonzero status: %x on endpoint %d.", __FUNCTION__,
-+ dbg("%s - nonzero status: %x on endpoint %d.", __func__,
- status, endpoint);
- return;
+ 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);
}
-- 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;
+ 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__);
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- serial = urb->context;
+ /* 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);
+ }
- if (status) {
-- dbg("%s - nonzero status: %x", __FUNCTION__, status);
-+ dbg("%s - nonzero status: %x", __func__, status);
- return;
+@@ -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);
}
-@@ -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)
+ 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;
- 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);
- }
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- /* 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__);
- }
+ /* 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..a9625c1 100644
+--- a/drivers/usb/serial/oti6858.c
++++ b/drivers/usb/serial/oti6858.c
+@@ -98,7 +98,7 @@ struct oti6858_buf {
- 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;
+ /* format of the control packet */
+ struct oti6858_control_pkt {
+- u16 divisor; /* baud rate = 96000000 / (16 * divisor), LE */
++ __le16 divisor; /* baud rate = 96000000 / (16 * divisor), LE */
+ #define OTI6858_MAX_BAUD_RATE 3000000
+ u8 frame_fmt;
+ #define FMT_STOP_BITS_MASK 0xc0
+@@ -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,
+@@ -214,7 +211,7 @@ struct oti6858_private {
+ struct delayed_work delayed_write_work;
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
+ struct {
+- u16 divisor;
++ __le16 divisor;
+ u8 frame_fmt;
+ u8 control;
+ } pending_setup;
+@@ -238,10 +235,10 @@ static void setup_line(struct work_struct *work)
+ unsigned long flags;
+ int result;
- endpoint = usb_pipeendpoint(urb->pipe);
+- dbg("%s(port = %d)", __FUNCTION__, port->number);
++ dbg("%s(port = %d)", __func__, port->number);
- if (status) {
- dbg("%s - nonzero status: %x on endpoint %d.",
-- __FUNCTION__, status, endpoint);
-+ __func__, status, endpoint);
+ 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);
-- port = (struct usb_serial_port *) urb->context;
-+ port = urb->context;
- p_priv = usb_get_serial_port_data(port);
+ 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);
- 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;
+- 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);
+ }
}
-@@ -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;
+@@ -306,7 +303,7 @@ void send_data(struct work_struct *work)
+ unsigned long flags;
+ unsigned char allow;
- if (status) {
-- dbg("%s - nonzero status: %x", __FUNCTION__, status);
-+ dbg("%s - nonzero status: %x", __func__, status);
+- 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;
}
- 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;
+@@ -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;
}
-@@ -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;
+@@ -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;
-- port = (struct usb_serial_port *) urb->context;
-+ port = urb->context;
- p_priv = usb_get_serial_port_data(port);
+- dbg("%s(port = %d, count = %d)", __FUNCTION__, port->number, count);
++ dbg("%s(port = %d, count = %d)", __func__, port->number, count);
- 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;
+ 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", __FUNCTION__);
-+ dbg ("%s", __func__);
+- dbg("%s(port = %d)", __FUNCTION__, port->number);
++ dbg("%s(port = %d)", __func__, port->number);
- serial = urb->context;
+ 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;
- if (status) {
-- dbg("%s - nonzero status: %x", __FUNCTION__, status);
-+ dbg("%s - nonzero status: %x", __func__, status);
- return;
- }
+- dbg("%s(port = %d)", __FUNCTION__, port->number);
++ dbg("%s(port = %d)", __func__, port->number);
- 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;
- }
+ spin_lock_irqsave(&priv->lock, flags);
+ chars = oti6858_buf_data_avail(priv->buf);
+@@ -453,13 +450,13 @@ static void oti6858_set_termios(struct usb_serial_port *port,
+ unsigned long flags;
+ unsigned int cflag;
+ u8 frame_fmt, control;
+- u16 divisor;
++ __le16 divisor;
+ int br;
-@@ -1125,7 +1125,7 @@ static void usa67_instat_callback(struct urb *urb)
+- dbg("%s(port = %d)", __FUNCTION__, port->number);
++ dbg("%s(port = %d)", __func__, port->number);
- /* 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);
+ if (!port->tty || !port->tty->termios) {
+- dbg("%s(): no tty structures", __FUNCTION__);
++ dbg("%s(): no tty structures", __func__);
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);
- }
+@@ -508,11 +505,12 @@ static void oti6858_set_termios(struct usb_serial_port *port,
+ divisor = 0;
+ } else {
+ int real_br;
++ int new_divisor;
+ br = min(br, OTI6858_MAX_BAUD_RATE);
+
+- divisor = (96000000 + 8 * br) / (16 * br);
+- real_br = 96000000 / (16 * divisor);
+- divisor = cpu_to_le16(divisor);
++ new_divisor = (96000000 + 8 * br) / (16 * br);
++ real_br = 96000000 / (16 * new_divisor);
++ divisor = cpu_to_le16(new_divisor);
+ tty_encode_baud_rate(port->tty, real_br, real_br);
+ }
- 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;
+@@ -575,7 +573,7 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
+ unsigned long flags;
+ int result;
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
+- dbg("%s(port = %d)", __FUNCTION__, port->number);
++ dbg("%s(port = %d)", __func__, port->number);
- 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);
+ usb_clear_halt(serial->dev, port->write_urb->pipe);
+ usb_clear_halt(serial->dev, port->read_urb->pipe);
+@@ -584,7 +582,7 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
+ return 0;
- 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;
+ 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;
+ }
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
- p_priv = usb_get_serial_port_data(port);
- d_details = p_priv->device_details;
+@@ -613,12 +611,12 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
+ spin_unlock_irqrestore(&priv->lock, flags);
+ kfree(buf);
-+ /* 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);
+- 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;
}
-- return (0);
-+ return 0;
- }
+@@ -637,14 +635,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);
- static int keyspan_chars_in_buffer (struct usb_serial_port *port)
- {
-- return (0);
-+ return 0;
- }
+ /* 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 +655,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 +676,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__);
-@@ -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;
+ /* cancel scheduled setup */
+ cancel_delayed_work(&priv->delayed_setup_work);
+@@ -686,7 +684,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
+ flush_scheduled_work();
-- 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);
+ usb_kill_urb(port->interrupt_in_urb);
+@@ -709,7 +707,7 @@ static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
+ u8 control;
- /* 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);
+ dbg("%s(port = %d, set = 0x%08x, clear = 0x%08x)",
+- __FUNCTION__, port->number, set, clear);
++ __func__, port->number, set, clear);
- 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);
- }
- }
+ if (!usb_get_intfdata(port->serial->interface))
+ return -ENODEV;
+@@ -741,7 +739,7 @@ static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file)
+ unsigned pin_state;
+ unsigned result = 0;
-@@ -1289,7 +1290,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
- //mdelay(100);
- //keyspan_set_termios(port, NULL);
+- dbg("%s(port = %d)", __FUNCTION__, port->number);
++ dbg("%s(port = %d)", __func__, port->number);
-- return (0);
-+ return 0;
+ if (!usb_get_intfdata(port->serial->interface))
+ return -ENODEV;
+@@ -764,7 +762,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 +809,9 @@ static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
+ unsigned int x;
- 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(port = %d, cmd = 0x%04x, arg = 0x%08lx)",
+- __FUNCTION__, port->number, cmd, arg);
++ __func__, port->number, cmd, arg);
-- 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)
+ switch (cmd) {
+- case TCFLSH:
+- /* FIXME */
+- return 0;
+-
+ case TIOCMBIS:
+ if (copy_from_user(&x, user_arg, sizeof(x)))
+ return -EFAULT;
+@@ -829,11 +823,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;
}
- /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
-- dbg("%s - urb in progress", __FUNCTION__);
-+ dbg("%s - urb in progress", __func__);
- }*/
+@@ -844,10 +838,10 @@ static void oti6858_break_ctl(struct usb_serial_port *port, int break_state)
+ {
+ int state;
- 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(port = %d)", __FUNCTION__, port->number);
++ dbg("%s(port = %d)", __func__, port->number);
-- 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;
- }
+ state = (break_state == 0) ? 0 : 1;
+- dbg("%s(): turning break %s", __FUNCTION__, state ? "on" : "off");
++ dbg("%s(): turning break %s", __func__, state ? "on" : "off");
-@@ -1588,7 +1589,7 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
- struct callbacks *cback;
- int endp;
+ /* FIXME */
+ /*
+@@ -855,7 +849,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__);
+ */
+ }
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
+@@ -864,7 +858,7 @@ static void oti6858_shutdown(struct usb_serial *serial)
+ struct oti6858_private *priv;
+ int i;
- 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);
+- dbg("%s()", __FUNCTION__);
++ dbg("%s()", __func__);
- /* 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);
+ for (i = 0; i < serial->num_ports; ++i) {
+ priv = usb_get_serial_port_data(serial->port[i]);
+@@ -878,13 +872,13 @@ static void oti6858_shutdown(struct usb_serial *serial)
- /* 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;
+ 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 - %d.", __FUNCTION__, baud_rate);
-+ dbg ("%s - %d.", __func__, baud_rate);
+ dbg("%s(port = %d, status = %d)",
+- __FUNCTION__, port->number, status);
++ __func__, port->number, status);
- /* 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); */
+ switch (status) {
+ case 0:
+@@ -895,11 +889,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;
}
- 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);
+@@ -916,7 +910,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 +925,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 +954,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 +973,20 @@ static void oti6858_read_int_callback(struct urb *urb)
+ if (resubmit) {
+ int result;
- /* 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(): 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);
+ }
}
-- 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;
+ 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 +995,7 @@ static void oti6858_read_bulk_callback(struct urb *urb)
+ int result;
-- dbg("%s - endpoint %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe));
-+ dbg("%s - endpoint %d", __func__, usb_pipeendpoint(this_urb->pipe));
+ dbg("%s(port = %d, status = %d)",
+- __FUNCTION__, port->number, status);
++ __func__, port->number, status);
- /* 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;
- }
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->flags.read_urb_in_use = 0;
+@@ -1009,20 +1003,20 @@ static void oti6858_read_bulk_callback(struct urb *urb)
-@@ -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);
+ 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;
}
-@@ -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));
+@@ -1038,20 +1032,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);
+ }
}
- #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__);
+ 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;
- 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,
+ dbg("%s(port = %d, status = %d)",
+- __FUNCTION__, port->number, status);
++ __func__, port->number, status);
- /* 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;
- }
+ switch (status) {
+ case 0:
+@@ -1062,21 +1056,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__);
-@@ -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,
+ 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 +1080,11 @@ static void oti6858_write_bulk_callback(struct urb *urb)
- 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);
+ // 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);
}
- #endif
+ }
-- return (0);
-+ return 0;
+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;
}
- 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;
+@@ -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", __FUNCTION__);
-+ dbg ("%s", __func__);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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;
+ spin_lock_irqsave(&priv->lock, flags);
-- 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);
+@@ -441,7 +441,7 @@ static void pl2303_send(struct usb_serial_port *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;
- }
+ spin_unlock_irqrestore(&priv->lock, flags);
-@@ -2171,7 +2172,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
- p_priv->resend_cont = reset_port + 1;
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count,
++ usb_serial_debug_data(debug, &port->dev, __func__, count,
+ port->write_urb->transfer_buffer);
- 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));
+ 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
}
- #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;
+@@ -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", __FUNCTION__);
-+ dbg ("%s", __func__);
+- dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
++ dbg("%s - port %d, %d bytes", __func__, port->number, count);
- 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,
+ if (!count)
+ return count;
+@@ -483,13 +483,13 @@ static int pl2303_write_room(struct usb_serial_port *port)
+ int room = 0;
+ unsigned long flags;
- /* 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;
- }
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-@@ -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,
+ spin_lock_irqsave(&priv->lock, flags);
+ room = pl2303_buf_space_avail(priv->buf);
+ spin_unlock_irqrestore(&priv->lock, flags);
- 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;
+- dbg("%s - returns %d", __FUNCTION__, room);
++ dbg("%s - returns %d", __func__, room);
+ return room;
}
- 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__);
+@@ -499,13 +499,13 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port)
+ int chars = 0;
+ unsigned long flags;
- 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,
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- /* 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,
+ spin_lock_irqsave(&priv->lock, flags);
+ chars = pl2303_buf_data_avail(priv->buf);
+ spin_unlock_irqrestore(&priv->lock, flags);
- 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;
+- dbg("%s - returns %d", __FUNCTION__, chars);
++ dbg("%s - returns %d", __func__, chars);
+ return chars;
}
- 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;
+@@ -521,7 +521,7 @@ static void pl2303_set_termios(struct usb_serial_port *port,
+ int i;
+ u8 control;
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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;
+ spin_lock_irqsave(&priv->lock, flags);
+ if (!priv->termios_initialized) {
+@@ -545,7 +545,9 @@ static void pl2303_set_termios(struct usb_serial_port *port,
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ 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;
+ }
- 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;
+@@ -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]);
}
- /* 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;
+ 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__);
}
-@@ -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);
+ 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__);
}
- 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);
+ } else {
+ buf[5] = 0;
+- dbg("%s - parity = none", __FUNCTION__);
++ dbg("%s - parity = none", __func__);
}
-
-- 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;
+ 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", __FUNCTION__);
-+ dbg("%s", __func__);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- s_priv = usb_get_serial_data(serial);
+ /* 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);
-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);
- }
+ /* 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);
- 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;
- }
+ 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)
-@@ -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);
- }
+ //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;
+ }
-@@ -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:
+- 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;
- 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;
+- dbg("%s (%d)", __FUNCTION__, port->number);
++ dbg("%s (%d)", __func__, port->number);
- 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;
+ 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);
- priv = usb_get_serial_port_data(port);
+- dbg("%s - result = %x", __FUNCTION__, result);
++ dbg("%s - result = %x", __func__, result);
- /* 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;
+ 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);
-@@ -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;
+ default:
+- dbg("%s not supported = 0x%04x", __FUNCTION__, cmd);
++ dbg("%s not supported = 0x%04x", __func__, cmd);
+ break;
}
-@@ -779,7 +784,7 @@ static int keyspan_pda_startup (struct usb_serial *serial)
+@@ -874,19 +876,19 @@ static void pl2303_break_ctl(struct usb_serial_port *port, int break_state)
+ u16 state;
+ int result;
- 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;
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-- 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);
+ 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");
-- info("%s - read status %x %x", __FUNCTION__,
-+ info("%s - read status %x %x", __func__,
- status_buf[0], status_buf[1]);
+ 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);
+ }
- *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)
- {
+ 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__);
- /* 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;
+ 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,
-- dbg("%s port %d", __FUNCTION__, port->number);
-+ dbg("%s port %d", __func__, port->number);
+ 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;
- /* 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)
+- dbg("%s (%d)", __FUNCTION__, port->number);
++ dbg("%s (%d)", __func__, port->number);
- 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;
+ 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;
}
-@@ -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;
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, urb->transfer_buffer);
-- dbg("%s port %d", __FUNCTION__, port->number);
-+ dbg("%s port %d", __func__, port->number);
+ 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);
+ }
- 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;
+ 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);
- while (count > 0) {
- /* try to find a free urb (write 0 bytes if none) */
-@@ -514,21 +511,21 @@ static int klsi_105_write (struct usb_serial_port *port,
- for (i=0; i<NUM_URBS; i++) {
- if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
- urb = priv->write_urb_pool[i];
-- dbg("%s - using pool URB %d", __FUNCTION__, i);
-+ dbg("%s - using pool URB %d", __func__, i);
- break;
- }
+ 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;
}
- 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 (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;
+ }
- 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 */
+- 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) {
-- 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:
+ if (result)
+ dev_err(&urb->dev->dev, "%s - failed resubmitting"
+- " read urb, error %d\n", __FUNCTION__, result);
++ " read urb, error %d\n", __func__, result);
+ }
- static void klsi_105_write_bulk_callback ( struct urb *urb)
+ 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 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);
- if (status) {
+ 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);
- return;
+ 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;
}
-@@ -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)
+@@ -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 klsi_105_read_bulk_callback (struct urb *urb)
+ 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;
- struct klsi_105_private *priv = usb_get_serial_port_data(port);
- struct tty_struct *tty;
+- 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 rc;
+ unsigned char length = urb->actual_length;
+- int i;
+ int result;
int status = urb->status;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
- /* 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);
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __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
+@@ -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);
}
--
-- 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
+ } 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);
}
-+ 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;
+@@ -259,7 +250,8 @@ static void safe_read_bulk_callback (struct urb *urb)
+ safe_read_bulk_callback, port);
-@@ -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;
+ 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 */
+ }
+ }
-- dbg("%sstate=%d", __FUNCTION__, break_state);
-+ dbg("%sstate=%d", __func__, break_state);
+@@ -274,25 +266,25 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i
+ count);
- 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__);
+ if (!port->write_urb) {
+- dbg ("%s - write urb NULL", __FUNCTION__);
+- return (0);
++ dbg ("%s - write urb NULL", __func__);
++ return 0;
+ }
- 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;
- }
+ dbg ("safe_write write_urb: %d transfer_buffer_length",
+ port->write_urb->transfer_buffer_length);
-@@ -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 (!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;
+ }
- /* 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,
+- 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);
- 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);
+ return (count);
}
-@@ -932,12 +938,12 @@ static void klsi_105_unthrottle (struct usb_serial_port *port)
+ static int safe_write_room (struct usb_serial_port *port)
{
- int result;
+- int room = 0; // Default: no room
++ int room = 0; /* Default: no room */
++ unsigned long flags;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
- 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);
++ 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;
}
-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,
+ 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_interrupt_out = NUM_DONT_CARE,
-- .num_bulk_in = 0,
-- .num_bulk_out = 0,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
.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;
- };
+ .write = safe_write,
+ .write_room = safe_write_room,
+diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
+index ed67881..29074c1 100644
+--- a/drivers/usb/serial/sierra.c
++++ b/drivers/usb/serial/sierra.c
+@@ -1,7 +1,7 @@
+ /*
+ USB Driver for Sierra Wireless
+- Copyright (C) 2006, 2007, 2008 Kevin Lloyd <linux at sierrawireless.com>
++ Copyright (C) 2006, 2007, 2008 Kevin Lloyd <klloyd at sierrawireless.com>
-@@ -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;
+ IMPORTANT DISCLAIMER: This driver is not commercially supported by
+ Sierra Wireless. Use at your own risk.
+@@ -14,8 +14,8 @@
+ Whom based his on the Keyspan driver by Hugh Blemings <hugh at blemings.org>
+ */
- 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)
+-#define DRIVER_VERSION "v.1.2.8"
+-#define DRIVER_AUTHOR "Kevin Lloyd <linux at sierrawireless.com>"
++#define DRIVER_VERSION "v.1.2.9c"
++#define DRIVER_AUTHOR "Kevin Lloyd <klloyd at sierrawireless.com>"
+ #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
+
+ #include <linux/kernel.h>
+@@ -31,7 +31,6 @@
+ #define SWIMS_USB_REQUEST_SetPower 0x00
+ #define SWIMS_USB_REQUEST_SetNmea 0x07
+ #define SWIMS_USB_REQUEST_SetMode 0x0B
+-#define SWIMS_USB_REQUEST_TYPE_VSC_SET 0x40
+ #define SWIMS_SET_MODE_Modem 0x0001
+
+ /* per port private data */
+@@ -55,7 +54,7 @@ static int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
+ dev_dbg(&udev->dev, "%s", "SET POWER STATE\n");
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ SWIMS_USB_REQUEST_SetPower, /* __u8 request */
+- SWIMS_USB_REQUEST_TYPE_VSC_SET, /* __u8 request type */
++ USB_TYPE_VENDOR, /* __u8 request type */
+ swiState, /* __u16 value */
+ 0, /* __u16 index */
+ NULL, /* void *data */
+@@ -70,7 +69,7 @@ static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSWocMode)
+ dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH\n");
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ SWIMS_USB_REQUEST_SetMode, /* __u8 request */
+- SWIMS_USB_REQUEST_TYPE_VSC_SET, /* __u8 request type */
++ USB_TYPE_VENDOR, /* __u8 request type */
+ eSWocMode, /* __u16 value */
+ 0x0000, /* __u16 index */
+ NULL, /* void *data */
+@@ -85,7 +84,7 @@ static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable)
+ dev_dbg(&udev->dev, "%s", "NMEA Enable sent\n");
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ SWIMS_USB_REQUEST_SetNmea, /* __u8 request */
+- SWIMS_USB_REQUEST_TYPE_VSC_SET, /* __u8 request type */
++ USB_TYPE_VENDOR, /* __u8 request type */
+ enable, /* __u16 value */
+ 0x0000, /* __u16 index */
+ NULL, /* void *data */
+@@ -109,6 +108,26 @@ static int sierra_calc_num_ports(struct usb_serial *serial)
+ return result;
+ }
+
++static int sierra_calc_interface(struct usb_serial *serial)
++{
++ int interface;
++ struct usb_interface *p_interface;
++ struct usb_host_interface *p_host_interface;
++
++ /* Get the interface structure pointer from the serial struct */
++ p_interface = serial->interface;
++
++ /* Get a pointer to the host interface structure */
++ p_host_interface = p_interface->cur_altsetting;
++
++ /* read the interface descriptor for this active altsetting
++ * to find out the interface number we are on
++ */
++ interface = p_host_interface->desc.bInterfaceNumber;
++
++ return interface;
++}
++
+ static int sierra_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
{
- int i;
-- dbg("%s - port %d", __FUNCTION__, serial->port[0]->number);
-+ dbg("%s - port %d", __func__, serial->port[0]->number);
+@@ -124,6 +143,22 @@ static int sierra_probe(struct usb_serial *serial,
+ ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+ udev = serial->dev;
- 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;
++ /* 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 */
-- 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;
+ { 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 */
- // 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] );
+ { 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;
- 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);
- }
+- 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)
- kfree(transfer_buffer);
-@@ -339,7 +332,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
+ static void sierra_rx_throttle(struct usb_serial_port *port)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ }
- static void kobil_close (struct usb_serial_port *port, struct file *filp)
+ static void sierra_rx_unthrottle(struct usb_serial_port *port)
{
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ }
- if (port->write_urb) {
- usb_kill_urb(port->write_urb);
-@@ -359,11 +352,11 @@ static void kobil_read_int_callback(struct urb *urb)
+ 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;
- // char *dbg_data;
+ unsigned long flags;
- 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;
- }
+ /* free up the transfer buffer, as usb_free_urb() does not do this */
+ kfree(urb->transfer_buffer);
-@@ -393,7 +386,7 @@ static void kobil_read_int_callback(struct urb *urb)
- port->interrupt_in_urb->dev = port->serial->dev;
+ if (status)
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
- 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);
- }
+ 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);
-@@ -411,21 +404,21 @@ static int kobil_write (struct usb_serial_port *port,
- struct kobil_private * priv;
+- dbg("%s: write (%d chars)", __FUNCTION__, count);
++ dbg("%s: write (%d chars)", __func__, count);
- 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);
+ 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,
- 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);
+ memcpy(buffer, 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);
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
++ usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
- priv->filled = priv->filled + count;
+ 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;
-@@ -457,7 +450,7 @@ static int kobil_write (struct usb_serial_port *port,
+- dbg("%s: %p", __FUNCTION__, urb);
++ dbg("%s: %p", __func__, urb);
- 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;
+ endpoint = usb_pipeendpoint(urb->pipe);
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
- 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);
+ 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__);
}
- }
- 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)
+ /* Resubmit urb so we continue receiving */
+@@ -447,19 +487,19 @@ static void sierra_instat_callback(struct urb *urb)
{
-- //dbg("%s - port %d", __FUNCTION__, port->number);
-+ //dbg("%s - port %d", __func__, port->number);
- return 8;
- }
+ 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;
-@@ -522,16 +515,13 @@ static int kobil_tiocmget(struct usb_serial_port *port, struct file *file)
- KOBIL_TIMEOUT);
+- 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);
- 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]);
+ if (status == 0) {
+ struct usb_ctrlrequest *req_pkt =
+ (struct usb_ctrlrequest *)urb->transfer_buffer;
-+ result = 0;
-+ if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0)
-+ result = TIOCM_DSR;
- kfree(transfer_buffer);
-- return priv->line_state;
-+ return result;
- }
+ 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));
- 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;
+- dbg("%s: signal x%x", __FUNCTION__, signals);
++ dbg("%s: signal x%x", __func__, signals);
-+ /* 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,
+ 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);
- 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);
+ /* 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);
}
-- 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)
+@@ -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;
- 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;
- }
+- 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;
+ /* 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)
-- 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);
+ 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);
/*
- * 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;
+ * 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)
-- dbg("%sstate=%d", __FUNCTION__, break_state);
-+ dbg("%sstate=%d", __func__, break_state);
+ portdata = usb_get_serial_port_data(port);
- 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;
-
+ /* 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);
- 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;
+ portdata->rts_state = 0;
+@@ -620,7 +662,7 @@ static int sierra_startup(struct usb_serial *serial)
+ int i;
+ int j;
- 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;
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- tty = port->tty;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ /* 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;
- 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", __FUNCTION__);
++ dbg("%s", __func__);
-- dbg("%s - port %d", __FUNCTION__, port->number);
+ 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..55b2570
+--- /dev/null
++++ b/drivers/usb/serial/spcp8x5.c
+@@ -0,0 +1,1073 @@
++/*
++ * spcp8x5 USB to serial adaptor driver
++ *
++ * Copyright (C) 2006 Linxb (xubin.lin at worldplus.com.cn)
++ * Copyright (C) 2006 S1 Corp.
++ *
++ * Original driver for 2.6.10 pl2303 driver by
++ * Greg Kroah-Hartman (greg at kroah.com)
++ * Changes for 2.6.20 by Harald Klein <hari at vt100.at>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ *
++ */
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/tty.h>
++#include <linux/tty_driver.h>
++#include <linux/tty_flip.h>
++#include <linux/module.h>
++#include <linux/spinlock.h>
++#include <linux/usb.h>
++#include <linux/usb/serial.h>
++
++
++/* Version Information */
++#define DRIVER_VERSION "v0.04"
++#define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver"
++
++static int debug;
++
++#define SPCP8x5_007_VID 0x04FC
++#define SPCP8x5_007_PID 0x0201
++#define SPCP8x5_008_VID 0x04fc
++#define SPCP8x5_008_PID 0x0235
++#define SPCP8x5_PHILIPS_VID 0x0471
++#define SPCP8x5_PHILIPS_PID 0x081e
++#define SPCP8x5_INTERMATIC_VID 0x04FC
++#define SPCP8x5_INTERMATIC_PID 0x0204
++#define SPCP8x5_835_VID 0x04fc
++#define SPCP8x5_835_PID 0x0231
++
++static struct usb_device_id id_table [] = {
++ { USB_DEVICE(SPCP8x5_PHILIPS_VID , SPCP8x5_PHILIPS_PID)},
++ { USB_DEVICE(SPCP8x5_INTERMATIC_VID, SPCP8x5_INTERMATIC_PID)},
++ { USB_DEVICE(SPCP8x5_835_VID, SPCP8x5_835_PID)},
++ { USB_DEVICE(SPCP8x5_008_VID, SPCP8x5_008_PID)},
++ { USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID)},
++ { } /* Terminating entry */
++};
++MODULE_DEVICE_TABLE(usb, id_table);
++
++struct spcp8x5_usb_ctrl_arg {
++ u8 type;
++ u8 cmd;
++ u8 cmd_type;
++ u16 value;
++ u16 index;
++ u16 length;
++};
++
++/* wait 30s before close */
++#define SPCP8x5_CLOSING_WAIT (30*HZ)
++
++#define SPCP8x5_BUF_SIZE 1024
++
++
++/* spcp8x5 spec register define */
++#define MCR_CONTROL_LINE_RTS 0x02
++#define MCR_CONTROL_LINE_DTR 0x01
++#define MCR_DTR 0x01
++#define MCR_RTS 0x02
++
++#define MSR_STATUS_LINE_DCD 0x80
++#define MSR_STATUS_LINE_RI 0x40
++#define MSR_STATUS_LINE_DSR 0x20
++#define MSR_STATUS_LINE_CTS 0x10
++
++/* verdor command here , we should define myself */
++#define SET_DEFAULT 0x40
++#define SET_DEFAULT_TYPE 0x20
++
++#define SET_UART_FORMAT 0x40
++#define SET_UART_FORMAT_TYPE 0x21
++#define SET_UART_FORMAT_SIZE_5 0x00
++#define SET_UART_FORMAT_SIZE_6 0x01
++#define SET_UART_FORMAT_SIZE_7 0x02
++#define SET_UART_FORMAT_SIZE_8 0x03
++#define SET_UART_FORMAT_STOP_1 0x00
++#define SET_UART_FORMAT_STOP_2 0x04
++#define SET_UART_FORMAT_PAR_NONE 0x00
++#define SET_UART_FORMAT_PAR_ODD 0x10
++#define SET_UART_FORMAT_PAR_EVEN 0x30
++#define SET_UART_FORMAT_PAR_MASK 0xD0
++#define SET_UART_FORMAT_PAR_SPACE 0x90
++
++#define GET_UART_STATUS_TYPE 0xc0
++#define GET_UART_STATUS 0x22
++#define GET_UART_STATUS_MSR 0x06
++
++#define SET_UART_STATUS 0x40
++#define SET_UART_STATUS_TYPE 0x23
++#define SET_UART_STATUS_MCR 0x0004
++#define SET_UART_STATUS_MCR_DTR 0x01
++#define SET_UART_STATUS_MCR_RTS 0x02
++#define SET_UART_STATUS_MCR_LOOP 0x10
++
++#define SET_WORKING_MODE 0x40
++#define SET_WORKING_MODE_TYPE 0x24
++#define SET_WORKING_MODE_U2C 0x00
++#define SET_WORKING_MODE_RS485 0x01
++#define SET_WORKING_MODE_PDMA 0x02
++#define SET_WORKING_MODE_SPP 0x03
++
++#define SET_FLOWCTL_CHAR 0x40
++#define SET_FLOWCTL_CHAR_TYPE 0x25
++
++#define GET_VERSION 0xc0
++#define GET_VERSION_TYPE 0x26
++
++#define SET_REGISTER 0x40
++#define SET_REGISTER_TYPE 0x27
++
++#define GET_REGISTER 0xc0
++#define GET_REGISTER_TYPE 0x28
++
++#define SET_RAM 0x40
++#define SET_RAM_TYPE 0x31
++
++#define GET_RAM 0xc0
++#define GET_RAM_TYPE 0x32
++
++/* how come ??? */
++#define UART_STATE 0x08
++#define UART_STATE_TRANSIENT_MASK 0x74
++#define UART_DCD 0x01
++#define UART_DSR 0x02
++#define UART_BREAK_ERROR 0x04
++#define UART_RING 0x08
++#define UART_FRAME_ERROR 0x10
++#define UART_PARITY_ERROR 0x20
++#define UART_OVERRUN_ERROR 0x40
++#define UART_CTS 0x80
++
++enum spcp8x5_type {
++ SPCP825_007_TYPE,
++ SPCP825_008_TYPE,
++ SPCP825_PHILIP_TYPE,
++ SPCP825_INTERMATIC_TYPE,
++ SPCP835_TYPE,
++};
++
++/* 1st in 1st out buffer 4 driver */
++struct ringbuf {
++ unsigned int buf_size;
++ char *buf_buf;
++ char *buf_get;
++ char *buf_put;
++};
++
++/* alloc the ring buf and alloc the buffer itself */
++static inline struct ringbuf *alloc_ringbuf(unsigned int size)
++{
++ struct ringbuf *pb;
++
++ if (size == 0)
++ return NULL;
++
++ pb = kmalloc(sizeof(*pb), GFP_KERNEL);
++ if (pb == NULL)
++ return NULL;
++
++ pb->buf_buf = kmalloc(size, GFP_KERNEL);
++ if (pb->buf_buf == NULL) {
++ kfree(pb);
++ return NULL;
++ }
++
++ pb->buf_size = size;
++ pb->buf_get = pb->buf_put = pb->buf_buf;
++
++ return pb;
++}
++
++/* free the ring buf and the buffer itself */
++static inline void free_ringbuf(struct ringbuf *pb)
++{
++ if (pb != NULL) {
++ kfree(pb->buf_buf);
++ kfree(pb);
++ }
++}
++
++/* clear pipo , juest repoint the pointer here */
++static inline void clear_ringbuf(struct ringbuf *pb)
++{
++ if (pb != NULL)
++ pb->buf_get = pb->buf_put;
++}
++
++/* get the number of data in the pipo */
++static inline unsigned int ringbuf_avail_data(struct ringbuf *pb)
++{
++ if (pb == NULL)
++ return 0;
++ return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
++}
++
++/* get the number of space in the pipo */
++static inline unsigned int ringbuf_avail_space(struct ringbuf *pb)
++{
++ if (pb == NULL)
++ return 0;
++ return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
++}
++
++/* put count data into pipo */
++static unsigned int put_ringbuf(struct ringbuf *pb, const char *buf,
++ unsigned int count)
++{
++ unsigned int len;
++
++ if (pb == NULL)
++ return 0;
++
++ len = ringbuf_avail_space(pb);
++ if (count > len)
++ count = len;
++
++ if (count == 0)
++ return 0;
++
++ len = pb->buf_buf + pb->buf_size - pb->buf_put;
++ if (count > len) {
++ memcpy(pb->buf_put, buf, len);
++ memcpy(pb->buf_buf, buf+len, count - len);
++ pb->buf_put = pb->buf_buf + count - len;
++ } else {
++ memcpy(pb->buf_put, buf, count);
++ if (count < len)
++ pb->buf_put += count;
++ else /* count == len */
++ pb->buf_put = pb->buf_buf;
++ }
++ return count;
++}
++
++/* get count data from pipo */
++static unsigned int get_ringbuf(struct ringbuf *pb, char *buf,
++ unsigned int count)
++{
++ unsigned int len;
++
++ if (pb == NULL || buf == NULL)
++ return 0;
++
++ len = ringbuf_avail_data(pb);
++ if (count > len)
++ count = len;
++
++ if (count == 0)
++ return 0;
++
++ len = pb->buf_buf + pb->buf_size - pb->buf_get;
++ if (count > len) {
++ memcpy(buf, pb->buf_get, len);
++ memcpy(buf+len, pb->buf_buf, count - len);
++ pb->buf_get = pb->buf_buf + count - len;
++ } else {
++ memcpy(buf, pb->buf_get, count);
++ if (count < len)
++ pb->buf_get += count;
++ else /* count == len */
++ pb->buf_get = pb->buf_buf;
++ }
++
++ return count;
++}
++
++static struct usb_driver spcp8x5_driver = {
++ .name = "spcp8x5",
++ .probe = usb_serial_probe,
++ .disconnect = usb_serial_disconnect,
++ .id_table = id_table,
++ .no_dynamic_id = 1,
++};
++
++
++struct spcp8x5_private {
++ spinlock_t lock;
++ struct ringbuf *buf;
++ int write_urb_in_use;
++ enum spcp8x5_type type;
++ wait_queue_head_t delta_msr_wait;
++ u8 line_control;
++ u8 line_status;
++ u8 termios_initialized;
++};
++
++/* desc : when device plug in,this function would be called.
++ * thanks to usb_serial subsystem,then do almost every things for us. And what
++ * we should do just alloc the buffer */
++static int spcp8x5_startup(struct usb_serial *serial)
++{
++ struct spcp8x5_private *priv;
++ int i;
++ enum spcp8x5_type type = SPCP825_007_TYPE;
++ u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
++
++ if (product == 0x0201)
++ type = SPCP825_007_TYPE;
++ else if (product == 0x0231)
++ type = SPCP835_TYPE;
++ else if (product == 0x0235)
++ type = SPCP825_008_TYPE;
++ else if (product == 0x0204)
++ type = SPCP825_INTERMATIC_TYPE;
++ else if (product == 0x0471 &&
++ serial->dev->descriptor.idVendor == cpu_to_le16(0x081e))
++ type = SPCP825_PHILIP_TYPE;
++ dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type);
++
++ for (i = 0; i < serial->num_ports; ++i) {
++ priv = kzalloc(sizeof(struct spcp8x5_private), GFP_KERNEL);
++ if (!priv)
++ goto cleanup;
++
++ spin_lock_init(&priv->lock);
++ priv->buf = alloc_ringbuf(SPCP8x5_BUF_SIZE);
++ if (priv->buf == NULL)
++ goto cleanup2;
++
++ init_waitqueue_head(&priv->delta_msr_wait);
++ priv->type = type;
++ usb_set_serial_port_data(serial->port[i] , priv);
++
++ }
++
++ return 0;
++
++cleanup2:
++ kfree(priv);
++cleanup:
++ for (--i; i >= 0; --i) {
++ priv = usb_get_serial_port_data(serial->port[i]);
++ free_ringbuf(priv->buf);
++ kfree(priv);
++ usb_set_serial_port_data(serial->port[i] , NULL);
++ }
++ return -ENOMEM;
++}
++
++/* call when the device plug out. free all the memory alloced by probe */
++static void spcp8x5_shutdown(struct usb_serial *serial)
++{
++ int i;
++ struct spcp8x5_private *priv;
++
++ for (i = 0; i < serial->num_ports; i++) {
++ priv = usb_get_serial_port_data(serial->port[i]);
++ if (priv) {
++ free_ringbuf(priv->buf);
++ kfree(priv);
++ usb_set_serial_port_data(serial->port[i] , NULL);
++ }
++ }
++}
++
++/* set the modem control line of the device.
++ * NOTE spcp825-007 not supported this */
++static int spcp8x5_set_ctrlLine(struct usb_device *dev, u8 value,
++ enum spcp8x5_type type)
++{
++ int retval;
++ u8 mcr = 0 ;
++
++ if (type == SPCP825_007_TYPE)
++ return -EPERM;
++
++ mcr = (unsigned short)value;
++ retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
++ SET_UART_STATUS_TYPE, SET_UART_STATUS,
++ mcr, 0x04, NULL, 0, 100);
++ if (retval != 0)
++ dev_dbg(&dev->dev, "usb_control_msg return %#x\n", retval);
++ return retval;
++}
++
++/* get the modem status register of the device
++ * NOTE spcp825-007 not supported this */
++static int spcp8x5_get_msr(struct usb_device *dev, u8 *status,
++ enum spcp8x5_type type)
++{
++ u8 *status_buffer;
++ int ret;
++
++ /* I return Permited not support here but seem inval device
++ * is more fix */
++ if (type == SPCP825_007_TYPE)
++ return -EPERM;
++ if (status == NULL)
++ return -EINVAL;
++
++ status_buffer = kmalloc(1, GFP_KERNEL);
++ if (!status_buffer)
++ return -ENOMEM;
++ status_buffer[0] = status[0];
++
++ ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
++ GET_UART_STATUS, GET_UART_STATUS_TYPE,
++ 0, GET_UART_STATUS_MSR, status_buffer, 1, 100);
++ if (ret < 0)
++ dev_dbg(&dev->dev, "Get MSR = 0x%p failed (error = %d)",
++ status_buffer, ret);
++
++ dev_dbg(&dev->dev, "0xc0:0x22:0:6 %d - 0x%p ", ret, status_buffer);
++ status[0] = status_buffer[0];
++ kfree(status_buffer);
++
++ return ret;
++}
++
++/* select the work mode.
++ * NOTE this function not supported by spcp825-007 */
++static void spcp8x5_set_workMode(struct usb_device *dev, u16 value,
++ u16 index, enum spcp8x5_type type)
++{
++ int ret;
++
++ /* I return Permited not support here but seem inval device
++ * is more fix */
++ if (type == SPCP825_007_TYPE)
++ return;
++
++ ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
++ SET_WORKING_MODE_TYPE, SET_WORKING_MODE,
++ value, index, NULL, 0, 100);
++ dev_dbg(&dev->dev, "value = %#x , index = %#x\n", value, index);
++ if (ret < 0)
++ dev_dbg(&dev->dev,
++ "RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret);
++}
++
++/* close the serial port. We should wait for data sending to device 1st and
++ * then kill all urb. */
++static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
++{
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ unsigned long flags;
++ unsigned int c_cflag;
++ int bps;
++ long timeout;
++ wait_queue_t wait;
++ int result;
++
+ dbg("%s - port %d", __func__, port->number);
++
++ /* wait for data to drain from the buffer */
++ spin_lock_irqsave(&priv->lock, flags);
++ timeout = SPCP8x5_CLOSING_WAIT;
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&port->tty->write_wait, &wait);
++ for (;;) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (ringbuf_avail_data(priv->buf) == 0 ||
++ timeout == 0 || signal_pending(current))
++ break;
++ spin_unlock_irqrestore(&priv->lock, flags);
++ timeout = schedule_timeout(timeout);
++ spin_lock_irqsave(&priv->lock, flags);
++ }
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&port->tty->write_wait, &wait);
++
++ /* clear out any remaining data in the buffer */
++ clear_ringbuf(priv->buf);
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ /* wait for characters to drain from the device (this is long enough
++ * for the entire all byte spcp8x5 hardware buffer to drain with no
++ * flow control for data rates of 1200 bps or more, for lower rates we
++ * should really know how much data is in the buffer to compute a delay
++ * that is not unnecessarily long) */
++ bps = tty_get_baud_rate(port->tty);
++ if (bps > 1200)
++ timeout = max((HZ*2560) / bps, HZ/10);
++ else
++ timeout = 2*HZ;
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(timeout);
++
++ /* clear control lines */
++ if (port->tty) {
++ c_cflag = port->tty->termios->c_cflag;
++ if (c_cflag & HUPCL) {
++ spin_lock_irqsave(&priv->lock, flags);
++ priv->line_control = 0;
++ spin_unlock_irqrestore(&priv->lock, flags);
++ spcp8x5_set_ctrlLine(port->serial->dev, 0 , priv->type);
++ }
++ }
++
++ /* kill urb */
++ if (port->write_urb != NULL) {
++ result = usb_unlink_urb(port->write_urb);
++ if (result)
++ dev_dbg(&port->dev,
++ "usb_unlink_urb(write_urb) = %d\n", result);
++ }
++ result = usb_unlink_urb(port->read_urb);
++ if (result)
++ dev_dbg(&port->dev, "usb_unlink_urb(read_urb) = %d\n", result);
++}
++
++/* set the serial param for transfer. we should check if we really need to
++ * transfer. then if be set flow contorl we should do this too. */
++static void spcp8x5_set_termios(struct usb_serial_port *port,
++ struct ktermios *old_termios)
++{
++ struct usb_serial *serial = port->serial;
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ unsigned long flags;
++ unsigned int cflag = port->tty->termios->c_cflag;
++ unsigned int old_cflag = old_termios->c_cflag;
++ unsigned short uartdata;
++ unsigned char buf[2] = {0, 0};
++ int baud;
++ int i;
++ u8 control;
++
++ if ((!port->tty) || (!port->tty->termios))
++ return;
++
++ /* for the 1st time call this function */
++ spin_lock_irqsave(&priv->lock, flags);
++ if (!priv->termios_initialized) {
++ *(port->tty->termios) = tty_std_termios;
++ port->tty->termios->c_cflag = B115200 | CS8 | CREAD |
++ HUPCL | CLOCAL;
++ priv->termios_initialized = 1;
++ }
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ /* check that they really want us to change something */
++ if (!tty_termios_hw_change(port->tty->termios, old_termios))
++ return;
++
++ /* set DTR/RTS active */
++ spin_lock_irqsave(&priv->lock, flags);
++ control = priv->line_control;
++ if ((old_cflag & CBAUD) == B0) {
++ priv->line_control |= MCR_DTR;
++ if (!(old_cflag & CRTSCTS))
++ priv->line_control |= MCR_RTS;
++ }
++ if (control != priv->line_control) {
++ control = priv->line_control;
++ spin_unlock_irqrestore(&priv->lock, flags);
++ spcp8x5_set_ctrlLine(serial->dev, control , priv->type);
++ } else {
++ spin_unlock_irqrestore(&priv->lock, flags);
++ }
++
++ /* Set Baud Rate */
++ baud = tty_get_baud_rate(port->tty);;
++ switch (baud) {
++ case 300: buf[0] = 0x00; break;
++ case 600: buf[0] = 0x01; break;
++ case 1200: buf[0] = 0x02; break;
++ case 2400: buf[0] = 0x03; break;
++ case 4800: buf[0] = 0x04; break;
++ case 9600: buf[0] = 0x05; break;
++ case 19200: buf[0] = 0x07; break;
++ case 38400: buf[0] = 0x09; break;
++ case 57600: buf[0] = 0x0a; break;
++ case 115200: buf[0] = 0x0b; break;
++ case 230400: buf[0] = 0x0c; break;
++ case 460800: buf[0] = 0x0d; break;
++ case 921600: buf[0] = 0x0e; break;
++/* case 1200000: buf[0] = 0x0f; break; */
++/* case 2400000: buf[0] = 0x10; break; */
++ case 3000000: buf[0] = 0x11; break;
++/* case 6000000: buf[0] = 0x12; break; */
++ case 0:
++ case 1000000:
++ buf[0] = 0x0b; break;
++ default:
++ err("spcp825 driver does not support the baudrate "
++ "requested, using default of 9600.");
++ }
++
++ /* Set Data Length : 00:5bit, 01:6bit, 10:7bit, 11:8bit */
++ if (cflag & CSIZE) {
++ switch (cflag & CSIZE) {
++ case CS5:
++ buf[1] |= SET_UART_FORMAT_SIZE_5;
++ break;
++ case CS6:
++ buf[1] |= SET_UART_FORMAT_SIZE_6;
++ break;
++ case CS7:
++ buf[1] |= SET_UART_FORMAT_SIZE_7;
++ break;
++ default:
++ case CS8:
++ buf[1] |= SET_UART_FORMAT_SIZE_8;
++ break;
++ }
++ }
++
++ /* Set Stop bit2 : 0:1bit 1:2bit */
++ buf[1] |= (cflag & CSTOPB) ? SET_UART_FORMAT_STOP_2 :
++ SET_UART_FORMAT_STOP_1;
++
++ /* Set Parity bit3-4 01:Odd 11:Even */
++ if (cflag & PARENB) {
++ buf[1] |= (cflag & PARODD) ?
++ SET_UART_FORMAT_PAR_ODD : SET_UART_FORMAT_PAR_EVEN ;
++ } else
++ buf[1] |= SET_UART_FORMAT_PAR_NONE;
++
++ uartdata = buf[0] | buf[1]<<8;
++
++ i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++ SET_UART_FORMAT_TYPE, SET_UART_FORMAT,
++ uartdata, 0, NULL, 0, 100);
++ if (i < 0)
++ err("Set UART format %#x failed (error = %d)", uartdata, i);
++ dbg("0x21:0x40:0:0 %d\n", i);
++
++ if (cflag & CRTSCTS) {
++ /* enable hardware flow control */
++ spcp8x5_set_workMode(serial->dev, 0x000a,
++ SET_WORKING_MODE_U2C, priv->type);
++ }
++ return;
++}
++
++/* open the serial port. do some usb system call. set termios and get the line
++ * status of the device. then submit the read urb */
++static int spcp8x5_open(struct usb_serial_port *port, struct file *filp)
++{
++ struct ktermios tmp_termios;
++ struct usb_serial *serial = port->serial;
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ int ret;
++ unsigned long flags;
++ u8 status = 0x30;
++ /* status 0x30 means DSR and CTS = 1 other CDC RI and delta = 0 */
++
++ dbg("%s - port %d", __func__, port->number);
++
++ usb_clear_halt(serial->dev, port->write_urb->pipe);
++ usb_clear_halt(serial->dev, port->read_urb->pipe);
++
++ ret = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++ 0x09, 0x00,
++ 0x01, 0x00, NULL, 0x00, 100);
++ if (ret)
++ return ret;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ if (port->tty->termios->c_cflag & CBAUD)
++ priv->line_control = MCR_DTR | MCR_RTS;
++ else
++ priv->line_control = 0;
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
++
++ /* Setup termios */
++ if (port->tty)
++ spcp8x5_set_termios(port, &tmp_termios);
++
++ spcp8x5_get_msr(serial->dev, &status, priv->type);
++
++ /* may be we should update uart status here but now we did not do */
++ spin_lock_irqsave(&priv->lock, flags);
++ priv->line_status = status & 0xf0 ;
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ /* FIXME: need to assert RTS and DTR if CRTSCTS off */
++
++ dbg("%s - submitting read urb", __func__);
++ port->read_urb->dev = serial->dev;
++ ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
++ if (ret) {
++ spcp8x5_close(port, NULL);
++ return -EPROTO;
++ }
++ return 0;
++}
++
++/* bulk read call back function. check the status of the urb. if transfer
++ * failed return. then update the status and the tty send data to tty subsys.
++ * submit urb again.
++ */
++static void spcp8x5_read_bulk_callback(struct urb *urb)
++{
++ struct usb_serial_port *port = urb->context;
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ struct tty_struct *tty;
++ unsigned char *data = urb->transfer_buffer;
++ unsigned long flags;
++ int i;
++ int result;
++ u8 status = 0;
++ char tty_flag;
++
++ dev_dbg(&port->dev, "start, urb->status = %d, "
++ "urb->actual_length = %d\n,", urb->status, urb->actual_length);
++
++ /* check the urb status */
++ if (urb->status) {
++ if (!port->open_count)
++ return;
++ if (urb->status == -EPROTO) {
++ /* spcp8x5 mysteriously fails with -EPROTO */
++ /* reschedule the read */
++ urb->status = 0;
++ urb->dev = port->serial->dev;
++ result = usb_submit_urb(urb , GFP_ATOMIC);
++ if (result)
++ dev_dbg(&port->dev,
++ "failed submitting read urb %d\n",
++ result);
++ return;
++ }
++ dev_dbg(&port->dev, "unable to handle the error, exiting.\n");
++ return;
++ }
++
++ /* get tty_flag from status */
++ tty_flag = TTY_NORMAL;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ status = priv->line_status;
++ priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
++ spin_unlock_irqrestore(&priv->lock, flags);
++ /* wake up the wait for termios */
++ wake_up_interruptible(&priv->delta_msr_wait);
++
++ /* break takes precedence over parity, which takes precedence over
++ * framing errors */
++ if (status & UART_BREAK_ERROR)
++ tty_flag = TTY_BREAK;
++ else if (status & UART_PARITY_ERROR)
++ tty_flag = TTY_PARITY;
++ else if (status & UART_FRAME_ERROR)
++ tty_flag = TTY_FRAME;
++ dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);
++
++ tty = port->tty;
++ if (tty && urb->actual_length) {
++ tty_buffer_request_room(tty, urb->actual_length + 1);
++ /* overrun is special, not associated with a char */
++ if (status & UART_OVERRUN_ERROR)
++ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
++ for (i = 0; i < urb->actual_length; ++i)
++ tty_insert_flip_char(tty, data[i], tty_flag);
++ tty_flip_buffer_push(tty);
++ }
++
++ /* Schedule the next read _if_ we are still open */
++ if (port->open_count) {
++ urb->dev = port->serial->dev;
++ result = usb_submit_urb(urb , GFP_ATOMIC);
++ if (result)
++ dev_dbg(&port->dev, "failed submitting read urb %d\n",
++ result);
++ }
++
++ return;
++}
++
++/* get data from ring buffer and then write to usb bus */
++static void spcp8x5_send(struct usb_serial_port *port)
++{
++ int count, result;
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->lock, flags);
++
++ if (priv->write_urb_in_use) {
++ dev_dbg(&port->dev, "write urb still used\n");
++ spin_unlock_irqrestore(&priv->lock, flags);
++ return;
++ }
++
++ /* send the 1st urb for writting */
++ memset(port->write_urb->transfer_buffer , 0x00 , port->bulk_out_size);
++ count = get_ringbuf(priv->buf, port->write_urb->transfer_buffer,
++ port->bulk_out_size);
++
++ if (count == 0) {
++ spin_unlock_irqrestore(&priv->lock, flags);
++ return;
++ }
++
++ /* update the urb status */
++ priv->write_urb_in_use = 1;
++
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ port->write_urb->transfer_buffer_length = count;
++ port->write_urb->dev = port->serial->dev;
++
++ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
++ if (result) {
++ dev_dbg(&port->dev, "failed submitting write urb, error %d\n",
++ result);
++ priv->write_urb_in_use = 0;
++ /* TODO: reschedule spcp8x5_send */
++ }
++
++
++ schedule_work(&port->work);
++}
++
++/* this is the call back function for write urb. NOTE we should not sleep in
++ * this routine. check the urb return code and then submit the write urb again
++ * to hold the write loop */
++static void spcp8x5_write_bulk_callback(struct urb *urb)
++{
++ struct usb_serial_port *port = urb->context;
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ int result;
++
++ switch (urb->status) {
++ case 0:
++ /* success */
++ break;
++ case -ECONNRESET:
++ case -ENOENT:
++ case -ESHUTDOWN:
++ /* this urb is terminated, clean up */
++ dev_dbg(&port->dev, "urb shutting down with status: %d\n",
++ urb->status);
++ priv->write_urb_in_use = 0;
++ return;
++ default:
++ /* error in the urb, so we have to resubmit it */
++ dbg("%s - Overflow in write", __func__);
++ dbg("%s - nonzero write bulk status received: %d",
++ __func__, urb->status);
++ port->write_urb->transfer_buffer_length = 1;
++ port->write_urb->dev = port->serial->dev;
++ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
++ if (result)
++ dev_dbg(&port->dev,
++ "failed resubmitting write urb %d\n", result);
++ else
++ return;
++ }
++
++ priv->write_urb_in_use = 0;
++
++ /* send any buffered data */
++ spcp8x5_send(port);
++}
++
++/* write data to ring buffer. and then start the write transfer */
++static int spcp8x5_write(struct usb_serial_port *port,
++ const unsigned char *buf, int count)
++{
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ unsigned long flags;
++
++ dev_dbg(&port->dev, "%d bytes\n", count);
++
++ if (!count)
++ return count;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ count = put_ringbuf(priv->buf, buf, count);
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ spcp8x5_send(port);
++
++ return count;
++}
++
++static int spcp8x5_wait_modem_info(struct usb_serial_port *port,
++ unsigned int arg)
++{
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ unsigned long flags;
++ unsigned int prevstatus;
++ unsigned int status;
++ unsigned int changed;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ prevstatus = priv->line_status;
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ while (1) {
++ /* wake up in bulk read */
++ interruptible_sleep_on(&priv->delta_msr_wait);
++
++ /* see if a signal did it */
++ if (signal_pending(current))
++ return -ERESTARTSYS;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ status = priv->line_status;
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ changed = prevstatus^status;
++
++ if (((arg & TIOCM_RNG) && (changed & MSR_STATUS_LINE_RI)) ||
++ ((arg & TIOCM_DSR) && (changed & MSR_STATUS_LINE_DSR)) ||
++ ((arg & TIOCM_CD) && (changed & MSR_STATUS_LINE_DCD)) ||
++ ((arg & TIOCM_CTS) && (changed & MSR_STATUS_LINE_CTS)))
++ return 0;
++
++ prevstatus = status;
++ }
++ /* NOTREACHED */
++ return 0;
++}
++
++static int spcp8x5_ioctl(struct usb_serial_port *port, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
++
++ switch (cmd) {
++ case TIOCMIWAIT:
++ dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
++ return spcp8x5_wait_modem_info(port, arg);
++
++ default:
++ dbg("%s not supported = 0x%04x", __func__, cmd);
++ break;
++ }
++
++ return -ENOIOCTLCMD;
++}
++
++static int spcp8x5_tiocmset(struct usb_serial_port *port, struct file *file,
++ unsigned int set, unsigned int clear)
++{
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ unsigned long flags;
++ u8 control;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ if (set & TIOCM_RTS)
++ priv->line_control |= MCR_RTS;
++ if (set & TIOCM_DTR)
++ priv->line_control |= MCR_DTR;
++ if (clear & TIOCM_RTS)
++ priv->line_control &= ~MCR_RTS;
++ if (clear & TIOCM_DTR)
++ priv->line_control &= ~MCR_DTR;
++ control = priv->line_control;
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
++}
++
++static int spcp8x5_tiocmget(struct usb_serial_port *port, struct file *file)
++{
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ unsigned long flags;
++ unsigned int mcr;
++ unsigned int status;
++ unsigned int result;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ mcr = priv->line_control;
++ status = priv->line_status;
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)
++ | ((mcr & MCR_RTS) ? TIOCM_RTS : 0)
++ | ((status & MSR_STATUS_LINE_CTS) ? TIOCM_CTS : 0)
++ | ((status & MSR_STATUS_LINE_DSR) ? TIOCM_DSR : 0)
++ | ((status & MSR_STATUS_LINE_RI) ? TIOCM_RI : 0)
++ | ((status & MSR_STATUS_LINE_DCD) ? TIOCM_CD : 0);
++
++ return result;
++}
++
++/* get the avail space room in ring buffer */
++static int spcp8x5_write_room(struct usb_serial_port *port)
++{
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ int room = 0;
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ room = ringbuf_avail_space(priv->buf);
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ return room;
++}
++
++/* get the number of avail data in write ring buffer */
++static int spcp8x5_chars_in_buffer(struct usb_serial_port *port)
++{
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ int chars = 0;
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ chars = ringbuf_avail_data(priv->buf);
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ return chars;
++}
++
++/* All of the device info needed for the spcp8x5 SIO serial converter */
++static struct usb_serial_driver spcp8x5_device = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "SPCP8x5",
++ },
++ .id_table = id_table,
++ .num_ports = 1,
++ .open = spcp8x5_open,
++ .close = spcp8x5_close,
++ .write = spcp8x5_write,
++ .set_termios = spcp8x5_set_termios,
++ .ioctl = spcp8x5_ioctl,
++ .tiocmget = spcp8x5_tiocmget,
++ .tiocmset = spcp8x5_tiocmset,
++ .write_room = spcp8x5_write_room,
++ .read_bulk_callback = spcp8x5_read_bulk_callback,
++ .write_bulk_callback = spcp8x5_write_bulk_callback,
++ .chars_in_buffer = spcp8x5_chars_in_buffer,
++ .attach = spcp8x5_startup,
++ .shutdown = spcp8x5_shutdown,
++};
++
++static int __init spcp8x5_init(void)
++{
++ int retval;
++ retval = usb_serial_register(&spcp8x5_device);
++ if (retval)
++ goto failed_usb_serial_register;
++ retval = usb_register(&spcp8x5_driver);
++ if (retval)
++ goto failed_usb_register;
++ info(DRIVER_DESC " " DRIVER_VERSION);
++ return 0;
++failed_usb_register:
++ usb_serial_deregister(&spcp8x5_device);
++failed_usb_serial_register:
++ return retval;
++}
++
++static void __exit spcp8x5_exit(void)
++{
++ usb_deregister(&spcp8x5_driver);
++ usb_serial_deregister(&spcp8x5_device);
++}
++
++module_init(spcp8x5_init);
++module_exit(spcp8x5_exit);
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_VERSION(DRIVER_VERSION);
++MODULE_LICENSE("GPL");
++
++module_param(debug, bool, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(debug, "Debug enabled or not");
+diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
+index e3d241f..a1c8aef 100644
+--- a/drivers/usb/serial/ti_usb_3410_5052.c
++++ b/drivers/usb/serial/ti_usb_3410_5052.c
+@@ -82,7 +82,6 @@
+ #include <linux/circ_buf.h>
+ #include <linux/mutex.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <linux/usb.h>
+ #include <linux/usb/serial.h>
- 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;
+@@ -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("Entering...%s", __FUNCTION__);
-+ dbg("Entering...%s", __func__);
- data = urb->transfer_buffer;
+ 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);
-@@ -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);
+ /* 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");
- /* 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);
+ /* 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;
- /* 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", __FUNCTION__);
++ dbg("%s", __func__);
-- dbg("%s:entering ...........", __FUNCTION__);
-+ dbg("%s:entering ...........", __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));
- mos7720_port = usb_get_serial_port_data(port);
- if (mos7720_port == NULL) {
-- dbg("%s:leaving ...........", __FUNCTION__);
-+ dbg("%s:leaving ...........", __func__);
+- 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)
-@@ -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;
+ /* 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;
+ }
}
-- 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__);
+ ti_set_termios(port, port->tty->termios);
- mos7720_port = usb_get_serial_port_data(port);
- if (mos7720_port == NULL) {
-- dbg("%s:leaving ...........", __FUNCTION__);
-+ dbg("%s:leaving ...........", __func__);
- return -ENODEV;
+- 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;
}
-+ /* 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 - 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 - 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 - 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;
+ }
-- dbg("%s:entering ...........", __FUNCTION__);
-+ dbg("%s:entering ...........", __func__);
+@@ -620,27 +613,27 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
- serial = port->serial;
+ ti_set_termios(port, port->tty->termios);
-@@ -679,7 +680,7 @@ static int mos7720_write(struct usb_serial_port *port,
+- 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;
}
- if (urb == NULL) {
-- dbg("%s - no more free urbs", __FUNCTION__);
-+ dbg("%s - no more free urbs", __func__);
- goto exit;
+- 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;
}
-@@ -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;
- }
+ /* 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;
}
- 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);
+@@ -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) {
- err("%s - usb_submit_urb(write bulk) failed with status = %d",
-- __FUNCTION__, status);
-+ __func__, status);
- bytes_sent = status;
- goto exit;
+- 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;
}
-@@ -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);
+@@ -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;
+ }
-@@ -736,11 +737,11 @@ static void mos7720_throttle(struct usb_serial_port *port)
- return;
- }
+@@ -677,7 +670,7 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
+ int status;
+ int do_unlock;
-- dbg("%s: Entering ..........", __FUNCTION__);
-+ dbg("%s: Entering ..........", __func__);
+- 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)
- tty = port->tty;
- if (!tty) {
-- dbg("%s - no tty available", __FUNCTION__);
-+ dbg("%s - no tty available", __func__);
- return;
- }
+ port_number = port->number - port->serial->minor;
-@@ -773,15 +774,15 @@ static void mos7720_unthrottle(struct usb_serial_port *port)
- return;
+- 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 (!mos7720_port->open) {
-- dbg("%s - port not opened", __FUNCTION__);
-+ dbg("%s - port not opened", __func__);
- return;
- }
+ /* 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: Entering ..........", __FUNCTION__);
-+ dbg("%s: Entering ..........", __func__);
+- dbg("%s - exit", __FUNCTION__);
++ dbg("%s - exit", __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;
+@@ -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);
-- dbg("%s - %d", __FUNCTION__, baudrate);
-+ dbg("%s - %d", __func__, baudrate);
+ if (count == 0) {
+- dbg("%s - write request of 0 bytes", __FUNCTION__);
++ dbg("%s - write request of 0 bytes", __func__);
+ return 0;
+ }
- 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;
+@@ -747,7 +740,7 @@ static int ti_write_room(struct usb_serial_port *port)
+ int room = 0;
+ unsigned long flags;
-- dbg("%s: Entering ..........", __FUNCTION__);
-+ dbg("%s: Entering ..........", __func__);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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);
+ 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);
- /* 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;
- }
+- dbg("%s - returns %d", __FUNCTION__, room);
++ dbg("%s - returns %d", __func__, room);
+ return room;
+ }
-@@ -1034,16 +1035,16 @@ static void change_port_settings(struct moschip_port *mos7720_port,
- serial = port->serial;
- port_number = port->number - port->serial->minor;
+@@ -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 (!mos7720_port->open) {
-- dbg("%s - port not opened", __FUNCTION__);
-+ dbg("%s - port not opened", __func__);
- return;
- }
-
- tty = mos7720_port->port->tty;
+ 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: Entering ..........", __FUNCTION__);
-+ dbg("%s: Entering ..........", __func__);
+- dbg("%s - returns %d", __FUNCTION__, chars);
++ dbg("%s - returns %d", __func__, chars);
+ return chars;
+ }
- 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__);
- }
+@@ -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;
- } else {
-- dbg("%s - parity = none", __FUNCTION__);
-+ dbg("%s - parity = none", __func__);
- }
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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__);
- }
+ if (tport == NULL)
+ return;
- #define LCR_BITS_MASK 0x03 /* Mask for bits/char field */
-@@ -1171,7 +1172,7 @@ static void change_port_settings(struct moschip_port *mos7720_port,
+ tty = port->tty;
+ if (!tty) {
+- dbg("%s - no tty", __FUNCTION__);
++ dbg("%s - no tty", __func__);
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,
+@@ -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 (!mos7720_port->open) {
-- dbg("%s - port not opened", __FUNCTION__);
-+ dbg("%s - port not opened", __func__);
+ if (tport == NULL)
+ return;
+
+ tty = port->tty;
+ if (!tty) {
+- dbg("%s - no tty", __FUNCTION__);
++ dbg("%s - no tty", __func__);
return;
}
-@@ -1225,15 +1226,15 @@ static void mos7720_set_termios(struct usb_serial_port *port,
+ 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);
+ }
+ }
- cflag = tty->termios->c_cflag;
+@@ -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 - cflag %08x iflag %08x", __FUNCTION__,
-+ dbg("%s - cflag %08x iflag %08x", __func__,
- tty->termios->c_cflag,
- RELEVANT_IFLAG(tty->termios->c_iflag));
+- dbg("%s - port %d, cmd = 0x%04X", __FUNCTION__, port->number, cmd);
++ dbg("%s - port %d, cmd = 0x%04X", __func__, port->number, cmd);
-- 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));
+ 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);
- /* 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,
+ cflag = tty->termios->c_cflag;
+ iflag = tty->termios->c_iflag;
- count = mos7720_chars_in_buffer(mos7720_port->port);
- if (count == 0) {
-- dbg("%s -- Empty", __FUNCTION__);
-+ dbg("%s -- Empty", __func__);
- result = TIOCSER_TEMT;
+- 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;
}
-@@ -1296,7 +1297,7 @@ static int get_number_bytes_avail(struct moschip_port *mos7720_port,
+@@ -992,7 +985,7 @@ static void ti_set_termios(struct usb_serial_port *port,
+ tty_encode_baud_rate(tty, baud, baud);
- result = tty->read_cnt;
+ 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);
-- 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;
+ 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);
-@@ -1374,7 +1375,7 @@ static int get_modem_info(struct moschip_port *mos7720_port,
- | ((msr & UART_MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */
+ /* 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 -- %x", __FUNCTION__, result);
-+ dbg("%s -- %x", __func__, result);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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)
+ if (tport == 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);
++ spin_lock_irqsave(&tport->tp_lock, flags);
+ msr = tport->tp_msr;
+ mcr = tport->tp_shadow_mcr;
++ spin_unlock_irqrestore(&tport->tp_lock, flags);
- 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;
+ 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);
- 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;
+- dbg("%s - 0x%04X", __FUNCTION__, result);
++ dbg("%s - 0x%04X", __func__, result);
- 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);
+ 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;
- 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);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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);
+ if (tport == NULL)
+ return -ENODEV;
- case TIOCSSERIAL:
-- dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number);
-+ dbg("%s (%d) TIOCSSERIAL", __func__, port->number);
- break;
++ spin_lock_irqsave(&tport->tp_lock, flags);
+ mcr = tport->tp_shadow_mcr;
- 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;
+ 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);
-- 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;
+ 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: Entering ..........", __FUNCTION__);
-+ dbg("%s: Entering ..........", __func__);
+- dbg("%s - state = %d", __FUNCTION__, break_state);
++ dbg("%s - state = %d", __func__, break_state);
- 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;
- }
+ 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);
-@@ -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;
+ if (status)
+- dbg("%s - error setting break, %d", __FUNCTION__, status);
++ dbg("%s - error setting break, %d", __func__, status);
+ }
-- 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)
+ static void ti_interrupt_callback(struct urb *urb)
{
- 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;
+- 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;
-- mos7840_port = (struct moschip_port *)urb->context;
-+ mos7840_port = urb->context;
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
switch (status) {
case 0:
-@@ -459,21 +459,21 @@ static void mos7840_control_callback(struct urb *urb)
+@@ -1120,33 +1119,33 @@ static void ti_interrupt_callback(struct urb *urb)
+ case -ECONNRESET:
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);
+- dbg("%s - urb shutting down, %d", __FUNCTION__, status);
++ dbg("%s - urb shutting down, %d", __func__, status);
+ tdev->td_urb_error = 1;
return;
default:
-- dbg("%s - nonzero urb status received: %d", __FUNCTION__,
-+ dbg("%s - nonzero urb status received: %d", __func__,
- status);
+ dev_err(dev, "%s - nonzero urb status, %d\n",
+- __FUNCTION__, status);
++ __func__, status);
+ tdev->td_urb_error = 1;
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);
+ if (length != 2) {
+- dbg("%s - bad packet size, %d", __FUNCTION__, length);
++ dbg("%s - bad packet size, %d", __func__, length);
+ goto exit;
}
- }
-@@ -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);
+ 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;
}
-@@ -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;
+ port_number = TI_GET_PORT_FROM_CODE(data[0]);
+ function = TI_GET_FUNC_FROM_CODE(data[0]);
- /* 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);
- }
- }
+- 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]);
-@@ -685,19 +685,19 @@ static void mos7840_bulk_in_callback(struct urb *urb)
- return;
+ 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;
}
-- mos7840_port = (struct moschip_port *)urb->context;
-+ mos7840_port = urb->context;
- if (!mos7840_port) {
- dbg("%s", "NULL mos7840_port pointer \n");
- return;
- }
+@@ -1158,17 +1157,17 @@ static void ti_interrupt_callback(struct urb *urb)
- 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;
+ 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;
}
-- 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)
+@@ -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 i;
+ int retval = 0;
-- 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)
+- 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 (mos7840_port_paranoia_check(mos7840_port->port, __FUNCTION__)) {
-+ if (mos7840_port_paranoia_check(mos7840_port->port, __func__)) {
- dbg("%s", "Port Paranoia failed \n");
+ if (status) {
+- dev_err(dev, "%s - stopping read!\n", __FUNCTION__);
++ dev_err(dev, "%s - stopping read!\n", __func__);
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;
- }
+ 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);
- serial = port->serial;
+ 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);
+ }
-- 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);
- }
+ 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;
-@@ -1116,7 +1116,7 @@ static int mos7840_chars_in_buffer(struct usb_serial_port *port)
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- dbg("%s \n", " mos7840_chars_in_buffer:entering ...........");
+ tport->tp_write_urb_in_use = 0;
-- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
-+ if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Invalid port \n");
- return -1;
+@@ -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);
}
-@@ -1134,7 +1134,7 @@ static int mos7840_chars_in_buffer(struct usb_serial_port *port)
+@@ -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;
}
- }
- spin_unlock_irqrestore(&mos7840_port->pool_lock,flags);
-- dbg("%s - returns %d", __FUNCTION__, chars);
-+ dbg("%s - returns %d", __func__, chars);
- return chars;
+@@ -1308,7 +1307,7 @@ static void ti_send(struct ti_port *tport)
+ unsigned long flags;
- }
-@@ -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...");
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
-+ if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Port Paranoia failed \n");
- return;
- }
+ spin_lock_irqsave(&tport->tp_lock, flags);
-- 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");
+@@ -1330,7 +1329,7 @@ static void ti_send(struct ti_port *tport)
-- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
-+ if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Port Paranoia failed \n");
- return;
- }
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
-- 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)
+- 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);
- dbg("%s \n", " mos7840_write_room:entering ...........");
+ 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)
-- 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);
+ 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)
- room = (room == 0) ? 0 : room - URB_TRANSFER_BUFFER_SIZE + 1;
-- dbg("%s - returns %d", __FUNCTION__, room);
-+ dbg("%s - returns %d", __func__, room);
- return room;
+ 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;
}
-@@ -1480,13 +1480,13 @@ static int mos7840_write(struct usb_serial_port *port,
- status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
- #endif
+@@ -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;
-- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
-+ if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Port Paranoia failed \n");
- return -1;
- }
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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;
+ 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;
}
-@@ -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;
+ 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;
}
-@@ -1521,7 +1521,7 @@ static int mos7840_write(struct usb_serial_port *port,
- kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+- dbg("%s - lsr 0x%02X", __FUNCTION__, data->bLSR);
++ dbg("%s - lsr 0x%02X", __func__, data->bLSR);
- 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)
+ 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;
- int status;
+ unsigned long flags;
-- 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)
+- dbg("%s - msr 0x%02X", __FUNCTION__, msr);
++ dbg("%s - msr 0x%02X", __func__, msr);
- tty = port->tty;
- if (!tty) {
-- dbg("%s - no tty available", __FUNCTION__);
-+ dbg("%s - no tty available", __func__);
- return;
- }
+ 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;
-@@ -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);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-- 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;
+ spin_lock_irq(&tport->tp_lock);
- if (!mos7840_port->open) {
-- dbg("%s - port not opened", __FUNCTION__);
-+ dbg("%s - port not opened", __func__);
- return;
+@@ -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;
}
-@@ -1651,7 +1651,7 @@ static void mos7840_unthrottle(struct usb_serial_port *port)
+@@ -1647,7 +1649,7 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
+ (__u8 *)data, size);
- tty = port->tty;
- if (!tty) {
-- dbg("%s - no tty available", __FUNCTION__);
-+ dbg("%s - no tty available", __func__);
- return;
+ 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 +1688,7 @@ static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file)
- int status = 0;
- mos7840_port = mos7840_get_port_private(port);
+@@ -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 - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- 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 (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);
+ 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 - 0x%04X", __FUNCTION__, result);
-+ dbg("%s - 0x%04X", __func__, result);
+- dbg("%s - download successful", __FUNCTION__);
++ dbg("%s - download successful", __func__);
- return result;
+ return 0;
}
-@@ -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);
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 2138ba8..0cb0d77 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;
- mos7840_port = mos7840_get_port_private(port);
+- dbg("%s %d", __FUNCTION__, num_ports);
++ dbg("%s %d", __func__, num_ports);
- if (mos7840_port == NULL)
- return -ENODEV;
+ *minor = 0;
+ mutex_lock(&table_lock);
+@@ -101,7 +101,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
-+ /* 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)
+ *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 - %d", __FUNCTION__, baudRate);
-+ dbg("%s - %d", __func__, baudRate);
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- 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;
+ if (serial == NULL)
+ return;
+@@ -135,7 +135,7 @@ static void destroy_serial(struct kref *kref)
- 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;
- }
+ serial = to_usb_serial(kref);
-- 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,
+- dbg("%s - %s", __FUNCTION__, serial->type->description);
++ dbg("%s - %s", __func__, serial->type->description);
- number = mos7840_port->port->number - mos7840_port->port->serial->minor;
+ serial->type->shutdown(serial);
-- 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 */
+@@ -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__);
- 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,
+ /* 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;
- port = (struct usb_serial_port *)mos7840_port->port;
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
-+ if (mos7840_port_paranoia_check(port, __func__)) {
- dbg("%s", "Invalid port \n");
- return;
- }
+ mutex_lock(&port->mutex);
-- if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {
-+ if (mos7840_serial_paranoia_check(port->serial, __func__)) {
- dbg("%s", "Invalid Serial \n");
- return;
- }
+@@ -296,16 +296,14 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int
+ struct usb_serial_port *port = tty->driver_data;
+ int retval = -ENODEV;
- serial = port->serial;
+- if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
++ if (port->serial->dev->state == USB_STATE_NOTATTACHED)
+ goto exit;
-- dbg("%s - port %d", __FUNCTION__, mos7840_port->port->number);
-+ dbg("%s - port %d", __func__, mos7840_port->port->number);
+- dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
++ dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
- if (!mos7840_port->open) {
+- if (!port->open_count) {
+- retval = -EINVAL;
- dbg("%s - port not opened", __FUNCTION__);
-+ dbg("%s - port not opened", __func__);
- return;
- }
+- goto exit;
+- }
++ /* open_count is managed under the mutex lock for the tty so cannot
++ drop to zero until after the last close completes */
++ WARN_ON(!port->open_count);
+
+ /* pass on to the driver specific version of this function */
+ retval = port->serial->type->write(port, buf, count);
+@@ -317,61 +315,28 @@ exit:
+ static int serial_write_room (struct tty_struct *tty)
+ {
+ struct usb_serial_port *port = tty->driver_data;
+- int retval = -ENODEV;
+-
+- if (!port)
+- goto exit;
+-
+- dbg("%s - port %d", __FUNCTION__, port->number);
+-
+- if (!port->open_count) {
+- dbg("%s - port not open", __FUNCTION__);
+- goto exit;
+- }
+-
++ dbg("%s - port %d", __func__, port->number);
++ WARN_ON(!port->open_count);
+ /* pass on to the driver specific version of this function */
+- retval = port->serial->type->write_room(port);
+-
+-exit:
+- return retval;
++ return port->serial->type->write_room(port);
+ }
-@@ -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__);
- }
+ static int serial_chars_in_buffer (struct tty_struct *tty)
+ {
+ struct usb_serial_port *port = tty->driver_data;
+- int retval = -ENODEV;
+-
+- if (!port)
+- goto exit;
+-
+- dbg("%s = port %d", __FUNCTION__, port->number);
+-
+- if (!port->open_count) {
+- dbg("%s - port not open", __FUNCTION__);
+- goto exit;
+- }
++ dbg("%s = port %d", __func__, port->number);
- } else {
-- dbg("%s - parity = none", __FUNCTION__);
-+ dbg("%s - parity = none", __func__);
- }
++ WARN_ON(!port->open_count);
+ /* pass on to the driver specific version of this function */
+- retval = port->serial->type->chars_in_buffer(port);
+-
+-exit:
+- return retval;
++ return port->serial->type->chars_in_buffer(port);
+ }
- 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__);
- }
+ static void serial_throttle (struct tty_struct * tty)
+ {
+ struct usb_serial_port *port = tty->driver_data;
++ dbg("%s - port %d", __func__, port->number);
- /* Update the LCR with the correct value */
-@@ -2100,7 +2101,7 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
- baud = 9600;
- }
+- if (!port)
+- return;
+-
+- dbg("%s - port %d", __FUNCTION__, port->number);
+-
+- if (!port->open_count) {
+- dbg ("%s - port not open", __FUNCTION__);
+- return;
+- }
+-
++ WARN_ON(!port->open_count);
+ /* pass on to the driver specific version of this function */
+ if (port->serial->type->throttle)
+ port->serial->type->throttle(port);
+@@ -380,17 +345,9 @@ static void serial_throttle (struct tty_struct * tty)
+ static void serial_unthrottle (struct tty_struct * tty)
+ {
+ struct usb_serial_port *port = tty->driver_data;
++ dbg("%s - port %d", __func__, port->number);
-- dbg("%s - baud rate = %d", __FUNCTION__, baud);
-+ dbg("%s - baud rate = %d", __func__, baud);
- status = mos7840_send_cmd_write_baud_rate(mos7840_port, baud);
+- if (!port)
+- return;
+-
+- dbg("%s - port %d", __FUNCTION__, port->number);
+-
+- if (!port->open_count) {
+- dbg("%s - port not open", __FUNCTION__);
+- return;
+- }
+-
++ WARN_ON(!port->open_count);
+ /* pass on to the driver specific version of this function */
+ if (port->serial->type->unthrottle)
+ port->serial->type->unthrottle(port);
+@@ -401,40 +358,27 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in
+ struct usb_serial_port *port = tty->driver_data;
+ int retval = -ENODEV;
- /* 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;
- }
+- 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);
- serial = port->serial;
+- if (!port->open_count) {
+- dbg ("%s - port not open", __FUNCTION__);
+- goto exit;
+- }
++ WARN_ON(!port->open_count);
-- 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;
+ /* pass on to the driver specific version of this function if it is available */
+- if (port->serial->type->ioctl)
++ if (port->serial->type->ioctl) {
++ lock_kernel();
+ retval = port->serial->type->ioctl(port, file, cmd, arg);
++ unlock_kernel();
++ }
+ else
+ retval = -ENOIOCTLCMD;
+-
+-exit:
+ return retval;
+ }
- if (!mos7840_port->open) {
-- dbg("%s - port not opened", __FUNCTION__);
-+ dbg("%s - port not opened", __func__);
- return;
- }
+ static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
+ {
+ struct usb_serial_port *port = tty->driver_data;
++ dbg("%s - port %d", __func__, port->number);
-@@ -2168,11 +2169,11 @@ static void mos7840_set_termios(struct usb_serial_port *port,
+- if (!port)
+- return;
+-
+- dbg("%s - port %d", __FUNCTION__, port->number);
+-
+- if (!port->open_count) {
+- dbg("%s - port not open", __FUNCTION__);
+- return;
+- }
+-
++ WARN_ON(!port->open_count);
+ /* pass on to the driver specific version of this function if it is available */
+ if (port->serial->type->set_termios)
+ port->serial->type->set_termios(port, old);
+@@ -446,19 +390,15 @@ static void serial_break (struct tty_struct *tty, int break_state)
+ {
+ struct usb_serial_port *port = tty->driver_data;
- cflag = tty->termios->c_cflag;
+- if (!port)
+- return;
+-
+- dbg("%s - port %d", __FUNCTION__, port->number);
+-
+- if (!port->open_count) {
+- dbg("%s - port not open", __FUNCTION__);
+- return;
+- }
++ dbg("%s - port %d", __func__, port->number);
-- 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));
++ WARN_ON(!port->open_count);
+ /* pass on to the driver specific version of this function if it is available */
+- if (port->serial->type->break_ctl)
++ if (port->serial->type->break_ctl) {
++ lock_kernel();
+ 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 +409,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);
+@@ -512,19 +452,11 @@ static int serial_tiocmget (struct tty_struct *tty, struct file *file)
+ {
+ struct usb_serial_port *port = tty->driver_data;
+
+- if (!port)
+- return -ENODEV;
+-
- dbg("%s - port %d", __FUNCTION__, port->number);
+-
+- if (!port->open_count) {
+- dbg("%s - port not open", __FUNCTION__);
+- return -ENODEV;
+- }
+ dbg("%s - port %d", __func__, port->number);
- /* change the port settings to the new ones specified */
++ WARN_ON(!port->open_count);
+ if (port->serial->type->tiocmget)
+ return port->serial->type->tiocmget(port, file);
+-
+ return -EINVAL;
+ }
-@@ -2213,7 +2214,7 @@ static int mos7840_get_lsr_info(struct moschip_port *mos7840_port,
+@@ -533,19 +465,11 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file,
+ {
+ struct usb_serial_port *port = tty->driver_data;
- count = mos7840_chars_in_buffer(mos7840_port->port);
- if (count == 0) {
-- dbg("%s -- Empty", __FUNCTION__);
-+ dbg("%s -- Empty", __func__);
- result = TIOCSER_TEMT;
- }
+- if (!port)
+- return -ENODEV;
+-
+- dbg("%s - port %d", __FUNCTION__, port->number);
+-
+- if (!port->open_count) {
+- dbg("%s - port not open", __FUNCTION__);
+- return -ENODEV;
+- }
++ dbg("%s - port %d", __func__, port->number);
-@@ -2240,7 +2241,7 @@ static int mos7840_set_modem_info(struct moschip_port *mos7840_port,
- return -1;
++ WARN_ON(!port->open_count);
+ if (port->serial->type->tiocmset)
+ return port->serial->type->tiocmset(port, file, set, clear);
+-
+ return -EINVAL;
+ }
- 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 */
+@@ -565,7 +489,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 -- %x", __FUNCTION__, result);
-+ dbg("%s -- %x", __func__, result);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (!port)
+ return;
+@@ -581,7 +505,7 @@ static void port_release(struct device *dev)
+ {
+ struct usb_serial_port *port = to_usb_serial_port(dev);
- 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;
+- dbg ("%s - %s", __FUNCTION__, dev->bus_id);
++ dbg ("%s - %s", __func__, dev->bus_id);
+ port_free(port);
+ }
-- 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,
+@@ -627,7 +551,7 @@ static struct usb_serial * create_serial (struct usb_device *dev,
- tty = mos7840_port->port->tty;
+ 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 +646,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;
+ }
-- dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
-+ dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
+@@ -854,22 +778,6 @@ int usb_serial_probe(struct usb_interface *interface,
+ serial->num_interrupt_in = num_interrupt_in;
+ serial->num_interrupt_out = num_interrupt_out;
- switch (cmd) {
- /* return number of bytes available */
+-#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 +791,7 @@ int usb_serial_probe(struct usb_interface *interface,
+ serial->num_port_pointers = max_endpoints;
+ unlock_kernel();
- 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;
+- 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 +939,7 @@ int usb_serial_probe(struct usb_interface *interface,
+ port->dev.release = &port_release;
- 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;
+ 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 +998,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
+ struct usb_serial_port *port;
- case TIOCMGET:
-- dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number);
-+ dbg("%s (%d) TIOCMGET", __func__, port->number);
- return mos7840_get_modem_info(mos7840_port, argp);
+ usb_serial_console_disconnect(serial);
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
- case TIOCGSERIAL:
-- dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number);
-+ dbg("%s (%d) TIOCGSERIAL", __func__, port->number);
- return mos7840_get_serial_info(mos7840_port, argp);
+ mutex_lock(&serial->disc_mutex);
+ usb_set_intfdata (interface, NULL);
+@@ -1174,7 +1082,7 @@ static int __init usb_serial_init(void)
- case TIOCSSERIAL:
-- dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number);
-+ dbg("%s (%d) TIOCSSERIAL", __func__, port->number);
- break;
+ 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;
+ }
- 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;
+@@ -1188,24 +1096,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;
+ }
-- 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.
- */
+ /* 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;
+ }
- #include <linux/kernel.h>
-@@ -49,15 +53,15 @@ static void navman_read_int_callback(struct urb *urb)
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
-- __FUNCTION__, status);
-+ __func__, status);
- return;
- default:
- dbg("%s - nonzero urb status received: %d",
-- __FUNCTION__, status);
-+ __func__, status);
- goto exit;
+ /* 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;
}
-- usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
-+ usb_serial_debug_data(debug, &port->dev, __func__,
- urb->actual_length, data);
+@@ -1223,7 +1133,7 @@ exit_reg_driver:
+ bus_unregister(&usb_serial_bus_type);
- 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);
+ 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,
+ };
- static int navman_open(struct usb_serial_port *port, struct file *filp)
- {
+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",
+ 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;
- 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);
+
+ /* 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;
- 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;
- }
+ 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,
- 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)
+ memcpy (buffer, buf, count);
- 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;
+- 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);
- 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);
+ /*
+ * 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)
- 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)
+ 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);
- usb_kill_urb(port->read_urb);
- }
-@@ -197,18 +194,18 @@ static void omninet_close (struct usb_serial_port *port, struct file * filp)
+ /*
+ * 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 omninet_read_bulk_callback (struct urb *urb)
+ 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;
- unsigned char *data = urb->transfer_buffer;
- struct omninet_header *header = (struct omninet_header *) &data[0];
+- 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;
- int i;
- int result;
+ 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 read bulk status received: %d",
+ if (status)
+ dbg("%s - nonzero write 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
+ spin_lock_irqsave(&priv->lock, flags);
+ --priv->outstanding_urbs;
+@@ -509,7 +502,7 @@ static void visor_write_bulk_callback (struct urb *urb)
- int result;
+ 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 (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;
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
}
- 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;
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
-- dbg("%s - returns %d", __FUNCTION__, room);
-+ dbg("%s - returns %d", __func__, room);
+ 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)
- 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)
+ static void visor_read_int_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;
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
int status = urb->status;
+ int result;
-- 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",
+@@ -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;
}
-@@ -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__);
+@@ -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);
- 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.
- */
+ 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);
+ }
--#define DRIVER_VERSION "v0.7.1"
-+#define DRIVER_VERSION "v0.7.2"
- #define DRIVER_AUTHOR "Matthias Urlichs <smurf at smurf.noris.de>"
- #define DRIVER_DESC "USB Driver for GSM modems"
+ 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;
-@@ -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);
+- 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;
- 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)
- {
+ 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__);
- }
- static void option_break_ctl(struct usb_serial_port *port, int break_state)
- {
- /* Unfortunately, I don't know how to send a break */
+ 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__);
- }
- static void option_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
- {
+ 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__);
- /* 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);
+ /*
+ * 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;
+ }
-+ /* 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,
+@@ -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;
+ }
- portdata = usb_get_serial_port_data(port);
+@@ -863,7 +856,7 @@ static int treo_attach (struct usb_serial *serial)
+ (serial->num_interrupt_in == 0))
+ goto generic_startup;
-- dbg("%s: write (%d chars)", __FUNCTION__, count);
-+ dbg("%s: write (%d chars)", __func__, count);
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- 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);
+ /*
+ * It appears that Treos and Kyoceras want to use the
+@@ -894,7 +887,7 @@ generic_startup:
-- dbg("%s: endpoint %d buf %d", __FUNCTION__,
-+ dbg("%s: endpoint %d buf %d", __func__,
- usb_pipeendpoint(this_urb->pipe), i);
+ static int clie_5_attach (struct usb_serial *serial)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- /* send the data */
-@@ -531,7 +529,7 @@ static int option_write(struct usb_serial_port *port,
- }
+ /* 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;
- count -= left;
-- dbg("%s: wrote (did %d)", __FUNCTION__, count);
-+ dbg("%s: wrote (did %d)", __func__, count);
- return count;
- }
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
-@@ -544,14 +542,14 @@ static void option_indat_callback(struct urb *urb)
- unsigned char *data = urb->transfer_buffer;
- int status = urb->status;
+ 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)
-- dbg("%s: %p", __FUNCTION__, urb);
-+ dbg("%s: %p", __func__, urb);
+ 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);
- endpoint = usb_pipeendpoint(urb->pipe);
-- port = (struct usb_serial_port *) urb->context;
-+ port = urb->context;
+ return -ENOIOCTLCMD;
+ }
+diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
+index 38726ef..f07e8a4 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);
- 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__);
+@@ -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;
}
-
- /* 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);
+ ++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;
}
- }
- return;
-@@ -579,9 +577,9 @@ static void option_outdat_callback(struct urb *urb)
- struct option_port_private *portdata;
+ ++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__);
-- 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;
+ /* 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", __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);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- if (status == 0) {
- struct usb_ctrlrequest *req_pkt =
- (struct usb_ctrlrequest *)urb->transfer_buffer;
+ 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;
+ }
- 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));
+ exit:
+- dbg("%s - exit, retval = %d", __FUNCTION__, retval);
++ dbg("%s - exit, retval = %d", __func__, retval);
+ return retval;
+ }
-- dbg("%s: signal x%x", __FUNCTION__, signals);
-+ dbg("%s: signal x%x", __func__, signals);
+@@ -657,7 +651,7 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
+ struct list_head *tmp;
+ struct list_head *tmp2;
- 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);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- /* 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);
+ mutex_lock(&port->serial->disc_mutex);
+ /* filp is NULL when called from usb_serial_disconnect */
+@@ -679,15 +673,13 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
}
- }
+ */
-@@ -658,13 +656,14 @@ static int option_write_room(struct usb_serial_port *port)
+- if (port->tty->driver->flush_buffer)
+- port->tty->driver->flush_buffer(port->tty);
++ tty_driver_flush_buffer(port->tty);
+ tty_ldisc_flush(port->tty);
- portdata = usb_get_serial_port_data(port);
+ firm_report_tx_done(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;
- }
+ firm_close(port);
-- dbg("%s: %d", __FUNCTION__, data_len);
-+ dbg("%s: %d", __func__, data_len);
- return data_len;
- }
+-printk(KERN_ERR"Before processing rx_urbs_submitted.\n");
+ /* shutdown our bulk reads and writes */
+ mutex_lock(&info->deathwarrant);
+ spin_lock_irq(&info->lock);
+@@ -732,10 +724,10 @@ static int whiteheat_write(struct usb_serial_port *port, const unsigned char *bu
+ unsigned long flags;
+ struct list_head *tmp;
-@@ -679,10 +678,12 @@ static int option_chars_in_buffer(struct usb_serial_port *port)
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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;
+ if (count == 0) {
+- dbg("%s - write request of 0 bytes", __FUNCTION__);
++ dbg("%s - write request of 0 bytes", __func__);
+ return (0);
}
-- 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)
+@@ -754,13 +746,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);
- portdata = usb_get_serial_port_data(port);
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, bytes, urb->transfer_buffer);
++ usb_serial_debug_data(debug, &port->dev, __func__, bytes, urb->transfer_buffer);
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ 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 +778,7 @@ static int whiteheat_write_room(struct usb_serial_port *port)
+ int room = 0;
+ unsigned long flags;
- /* 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 - 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 +786,7 @@ static int whiteheat_write_room(struct usb_serial_port *port)
+ spin_unlock_irqrestore(&info->lock, flags);
+ room *= port->bulk_out_size;
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
- portdata = usb_get_serial_port_data(port);
+- dbg("%s - returns %d", __FUNCTION__, room);
++ dbg("%s - returns %d", __func__, room);
+ return (room);
+ }
- portdata->rts_state = 0;
-@@ -782,7 +783,7 @@ static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
+@@ -804,7 +796,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;
- 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;
- }
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-@@ -801,7 +802,7 @@ static void option_setup_urbs(struct usb_serial *serial)
- struct usb_serial_port *port;
- struct option_port_private *portdata;
+ firm_get_dtr_rts(port);
+ if (info->mcr & UART_MCR_DTR)
+@@ -821,7 +813,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", __FUNCTION__);
-+ dbg("%s", __func__);
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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)
- }
- }
+ if (set & TIOCM_RTS)
+ info->mcr |= UART_MCR_RTS;
+@@ -844,7 +836,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;
-+
-+/** 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)
+- 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 +878,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)
{
- 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__);
+- dbg("%s -port %d", __FUNCTION__, port->number);
++ dbg("%s -port %d", __func__, port->number);
+ firm_setup_port(port);
+ }
- portdata = usb_get_serial_port_data(port);
+@@ -904,7 +896,7 @@ static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
+ int chars = 0;
+ unsigned long flags;
-@@ -844,7 +848,7 @@ static int option_send_setup(struct usb_serial_port *port)
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
- 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);
+ spin_lock_irqsave(&info->lock, flags);
+ list_for_each(tmp, &info->tx_urbs_submitted) {
+@@ -913,7 +905,7 @@ static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
}
+ spin_unlock_irqrestore(&info->lock, flags);
- return 0;
-@@ -857,7 +861,7 @@ static int option_startup(struct usb_serial *serial)
- struct option_port_private *portdata;
- u8 *buffer;
+- dbg ("%s - returns %d", __FUNCTION__, chars);
++ dbg ("%s - returns %d", __func__, chars);
+ return chars;
+ }
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+@@ -923,7 +915,7 @@ static void whiteheat_throttle (struct usb_serial_port *port)
+ struct whiteheat_private *info = usb_get_serial_port_data(port);
+ unsigned long flags;
- /* 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);
- }
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-@@ -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);
- }
+ spin_lock_irqsave(&info->lock, flags);
+ info->flags |= THROTTLED;
+@@ -939,7 +931,7 @@ static void whiteheat_unthrottle (struct usb_serial_port *port)
+ int actually_throttled;
+ unsigned long flags;
- 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 - 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 +952,7 @@ static void command_port_write_callback(struct urb *urb)
+ {
+ int status = urb->status;
- 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;
+ if (status) {
+ dbg("nonzero urb status: %d", status);
+@@ -971,28 +963,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(port = %d)", __FUNCTION__, port->number);
-+ dbg("%s(port = %d)", __func__, port->number);
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
- 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));
+ 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;
-@@ -256,7 +253,7 @@ static void setup_line(struct work_struct *work)
- 100);
+ }
+ 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;
+ }
- 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);
+- 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);
-- 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);
+ if (data[0] == WHITEHEAT_CMD_COMPLETE) {
+ command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
+@@ -1002,38 +994,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);
}
-@@ -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);
+ 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;
- 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 - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
-- 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);
- }
+ 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;
}
-@@ -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;
+ list_del(&wrap->list);
+@@ -1041,14 +1033,14 @@ static void whiteheat_read_callback(struct urb *urb)
-- 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);
+ spin_lock(&info->lock);
+ list_add(&wrap->list, &info->rx_urbs_free);
+ spin_unlock(&info->lock);
+ return;
+ }
- 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;
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
-- dbg("%s(port = %d)", __FUNCTION__, port->number);
-+ dbg("%s(port = %d)", __func__, port->number);
+ spin_lock(&info->lock);
+ list_add_tail(&wrap->list, &info->rx_urb_q);
+@@ -1065,18 +1057,18 @@ static void whiteheat_read_callback(struct urb *urb)
- 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;
+ 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);
+- 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__);
+ 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 +1076,7 @@ static void whiteheat_write_callback(struct urb *urb)
-@@ -575,7 +572,7 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
- unsigned long flags;
- int result;
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
-- dbg("%s(port = %d)", __FUNCTION__, port->number);
-+ dbg("%s(port = %d)", __func__, port->number);
+@@ -1104,7 +1096,7 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d
+ int retval = 0;
+ int t;
- 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;
+- dbg("%s - command %d", __FUNCTION__, command);
++ dbg("%s - command %d", __func__, command);
- 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;
+ command_port = port->serial->port[COMMAND_PORT];
+ command_info = usb_get_serial_port_data(command_port);
+@@ -1118,7 +1110,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;
}
-@@ -613,12 +610,12 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
- spin_unlock_irqrestore(&priv->lock, flags);
- kfree(buf);
+@@ -1129,19 +1121,19 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d
+ usb_kill_urb(command_port->write_urb);
-- 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;
+ if (command_info->command_finished == false) {
+- dbg("%s - command timed out.", __FUNCTION__);
++ dbg("%s - command timed out.", __func__);
+ retval = -ETIMEDOUT;
+ goto exit;
}
-@@ -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)
+ if (command_info->command_finished == WHITEHEAT_CMD_FAILURE) {
+- dbg("%s - command failed.", __FUNCTION__);
++ dbg("%s - command failed.", __func__);
+ retval = -EIO;
+ goto exit;
}
- 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;
+ 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 +1178,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 +1194,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);
- dbg("%s(port = %d, set = 0x%08x, clear = 0x%08x)",
-- __FUNCTION__, port->number, set, clear);
-+ __func__, port->number, set, clear);
+ /* 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);
- 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;
+ /* 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 +1219,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);
-- dbg("%s(port = %d)", __FUNCTION__, port->number);
-+ dbg("%s(port = %d)", __func__, port->number);
+ /* 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);
- 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;
+ /* fixme: should set validated settings */
+ tty_encode_baud_rate(port->tty, port_settings.baud, port_settings.baud);
+@@ -1318,7 +1310,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 +1446,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.
-- dbg("%s() = 0x%08x", __FUNCTION__, result);
-+ dbg("%s() = 0x%08x", __func__, result);
+ config USB_STORAGE_DATAFAB
+- bool "Datafab Compact Flash Reader support (EXPERIMENTAL)"
+- depends on USB_STORAGE && EXPERIMENTAL
++ bool "Datafab Compact Flash Reader support"
++ depends on USB_STORAGE
+ help
+ Support for certain Datafab CompactFlash readers.
+ Datafab has a web page at <http://www.datafabusa.com/>.
+@@ -69,8 +69,8 @@ config USB_STORAGE_DPCM
+ There is a web page at <http://www.ziocorp.com/products/>.
- return result;
- }
-@@ -811,13 +808,9 @@ static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
- unsigned int x;
+ 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
- dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)",
-- __FUNCTION__, port->number, cmd, arg);
-+ __func__, port->number, cmd, arg);
+ 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.
- 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);
+ 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.
- case TIOCMIWAIT:
-- dbg("%s(): TIOCMIWAIT", __FUNCTION__);
-+ dbg("%s(): TIOCMIWAIT", __func__);
- return wait_modem_info(port, arg);
+ 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.
- default:
-- dbg("%s(): 0x%04x not supported", __FUNCTION__, cmd);
-+ dbg("%s(): 0x%04x not supported", __func__, cmd);
- break;
- }
+ 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.
-@@ -844,10 +837,10 @@ static void oti6858_break_ctl(struct usb_serial_port *port, int break_state)
- {
- int state;
+ 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.
-- dbg("%s(port = %d)", __FUNCTION__, port->number);
-+ dbg("%s(port = %d)", __func__, port->number);
++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
- state = (break_state == 0) ? 0 : 1;
-- dbg("%s(): turning break %s", __FUNCTION__, state ? "on" : "off");
-+ dbg("%s(): turning break %s", __func__, state ? "on" : "off");
+ usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \
+ initializers.o $(usb-storage-obj-y)
+diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c
+new file mode 100644
+index 0000000..d88824b
+--- /dev/null
++++ b/drivers/usb/storage/cypress_atacb.c
+@@ -0,0 +1,200 @@
++/*
++ * Support for emulating SAT (ata pass through) on devices based
++ * on the Cypress USB/ATA bridge supporting ATACB.
++ *
++ * Copyright (c) 2008 Matthieu Castet (castet.matthieu at free.fr)
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <scsi/scsi.h>
++#include <scsi/scsi_cmnd.h>
++#include <scsi/scsi_eh.h>
++#include <linux/ata.h>
++
++#include "usb.h"
++#include "protocol.h"
++#include "scsiglue.h"
++#include "debug.h"
++
++/*
++ * ATACB is a protocol used on cypress usb<->ata bridge to
++ * send raw ATA command over mass storage
++ * There is a ATACB2 protocol that support LBA48 on newer chip.
++ * More info that be found on cy7c68310_8.pdf and cy7c68300c_8.pdf
++ * datasheet from cypress.com.
++ */
++void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
++{
++ unsigned char save_cmnd[MAX_COMMAND_SIZE];
++
++ if (likely(srb->cmnd[0] != ATA_16 && srb->cmnd[0] != ATA_12)) {
++ usb_stor_transparent_scsi_command(srb, us);
++ return;
++ }
++
++ memcpy(save_cmnd, srb->cmnd, sizeof(save_cmnd));
++ memset(srb->cmnd, 0, sizeof(srb->cmnd));
++
++ /* check if we support the command */
++ if (save_cmnd[1] >> 5) /* MULTIPLE_COUNT */
++ goto invalid_fld;
++ /* check protocol */
++ switch((save_cmnd[1] >> 1) & 0xf) {
++ case 3: /*no DATA */
++ case 4: /* PIO in */
++ case 5: /* PIO out */
++ break;
++ default:
++ goto invalid_fld;
++ }
++
++ /* first build the ATACB command */
++ srb->cmd_len = 16;
++
++ srb->cmnd[0] = 0x24; /* bVSCBSignature : vendor-specific command
++ this value can change, but most(all ?) manufacturers
++ keep the cypress default : 0x24 */
++ srb->cmnd[1] = 0x24; /* bVSCBSubCommand : 0x24 for ATACB */
++
++ srb->cmnd[3] = 0xff - 1; /* features, sector count, lba low, lba med
++ lba high, device, command are valid */
++ srb->cmnd[4] = 1; /* TransferBlockCount : 512 */
++
++ if (save_cmnd[0] == ATA_16) {
++ srb->cmnd[ 6] = save_cmnd[ 4]; /* features */
++ srb->cmnd[ 7] = save_cmnd[ 6]; /* sector count */
++ srb->cmnd[ 8] = save_cmnd[ 8]; /* lba low */
++ srb->cmnd[ 9] = save_cmnd[10]; /* lba med */
++ srb->cmnd[10] = save_cmnd[12]; /* lba high */
++ srb->cmnd[11] = save_cmnd[13]; /* device */
++ srb->cmnd[12] = save_cmnd[14]; /* command */
++
++ if (save_cmnd[1] & 0x01) {/* extended bit set for LBA48 */
++ /* this could be supported by atacb2 */
++ if (save_cmnd[3] || save_cmnd[5] || save_cmnd[7] || save_cmnd[9]
++ || save_cmnd[11])
++ goto invalid_fld;
++ }
++ }
++ else { /* ATA12 */
++ srb->cmnd[ 6] = save_cmnd[3]; /* features */
++ srb->cmnd[ 7] = save_cmnd[4]; /* sector count */
++ srb->cmnd[ 8] = save_cmnd[5]; /* lba low */
++ srb->cmnd[ 9] = save_cmnd[6]; /* lba med */
++ srb->cmnd[10] = save_cmnd[7]; /* lba high */
++ srb->cmnd[11] = save_cmnd[8]; /* device */
++ srb->cmnd[12] = save_cmnd[9]; /* command */
++
++ }
++ /* Filter SET_FEATURES - XFER MODE command */
++ if ((srb->cmnd[12] == ATA_CMD_SET_FEATURES)
++ && (srb->cmnd[6] == SETFEATURES_XFER))
++ goto invalid_fld;
++
++ if (srb->cmnd[12] == ATA_CMD_ID_ATA || srb->cmnd[12] == ATA_CMD_ID_ATAPI)
++ srb->cmnd[2] |= (1<<7); /* set IdentifyPacketDevice for these cmds */
++
++
++ usb_stor_transparent_scsi_command(srb, us);
++
++ /* if the device doesn't support ATACB
++ */
++ if (srb->result == SAM_STAT_CHECK_CONDITION &&
++ memcmp(srb->sense_buffer, usb_stor_sense_invalidCDB,
++ sizeof(usb_stor_sense_invalidCDB)) == 0) {
++ US_DEBUGP("cypress atacb not supported ???\n");
++ goto end;
++ }
++
++ /* if ck_cond flags is set, and there wasn't critical error,
++ * build the special sense
++ */
++ if ((srb->result != (DID_ERROR << 16) &&
++ srb->result != (DID_ABORT << 16)) &&
++ save_cmnd[2] & 0x20) {
++ struct scsi_eh_save ses;
++ unsigned char regs[8];
++ unsigned char *sb = srb->sense_buffer;
++ unsigned char *desc = sb + 8;
++ int tmp_result;
++
++ /* build the command for
++ * reading the ATA registers */
++ scsi_eh_prep_cmnd(srb, &ses, NULL, 0, 0);
++ srb->sdb.length = sizeof(regs);
++ sg_init_one(&ses.sense_sgl, regs, srb->sdb.length);
++ srb->sdb.table.sgl = &ses.sense_sgl;
++ srb->sc_data_direction = DMA_FROM_DEVICE;
++ srb->sdb.table.nents = 1;
++ /* we use the same command as before, but we set
++ * the read taskfile bit, for not executing atacb command,
++ * but reading register selected in srb->cmnd[4]
++ */
++ srb->cmnd[2] = 1;
++
++ usb_stor_transparent_scsi_command(srb, us);
++ tmp_result = srb->result;
++ scsi_eh_restore_cmnd(srb, &ses);
++ /* we fail to get registers, report invalid command */
++ if (tmp_result != SAM_STAT_GOOD)
++ goto invalid_fld;
++
++ /* build the sense */
++ memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
++
++ /* set sk, asc for a good command */
++ sb[1] = RECOVERED_ERROR;
++ sb[2] = 0; /* ATA PASS THROUGH INFORMATION AVAILABLE */
++ sb[3] = 0x1D;
++
++ /* XXX we should generate sk, asc, ascq from status and error
++ * regs
++ * (see 11.1 Error translation ATA device error to SCSI error map)
++ * and ata_to_sense_error from libata.
++ */
++
++ /* Sense data is current and format is descriptor. */
++ sb[0] = 0x72;
++ desc[0] = 0x09; /* ATA_RETURN_DESCRIPTOR */
++
++ /* set length of additional sense data */
++ sb[7] = 14;
++ desc[1] = 12;
++
++ /* Copy registers into sense buffer. */
++ desc[ 2] = 0x00;
++ desc[ 3] = regs[1]; /* features */
++ desc[ 5] = regs[2]; /* sector count */
++ desc[ 7] = regs[3]; /* lba low */
++ desc[ 9] = regs[4]; /* lba med */
++ desc[11] = regs[5]; /* lba high */
++ desc[12] = regs[6]; /* device */
++ desc[13] = regs[7]; /* command */
++
++ srb->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
++ }
++ goto end;
++invalid_fld:
++ srb->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
++
++ memcpy(srb->sense_buffer,
++ usb_stor_sense_invalidCDB,
++ sizeof(usb_stor_sense_invalidCDB));
++end:
++ memcpy(srb->cmnd, save_cmnd, sizeof(save_cmnd));
++ if (srb->cmnd[0] == ATA_12)
++ srb->cmd_len = 12;
++}
+diff --git a/drivers/usb/storage/cypress_atacb.h b/drivers/usb/storage/cypress_atacb.h
+new file mode 100644
+index 0000000..fbada89
+--- /dev/null
++++ b/drivers/usb/storage/cypress_atacb.h
+@@ -0,0 +1,25 @@
++/*
++ * Support for emulating SAT (ata pass through) on devices based
++ * on the Cypress USB/ATA bridge supporting ATACB.
++ *
++ * Copyright (c) 2008 Matthieu Castet (castet.matthieu at free.fr)
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef _CYPRESS_ATACB_H_
++#define _CYPRESS_ATACB_H_
++extern void cypress_atacb_passthrough(struct scsi_cmnd*, struct us_data*);
++#endif
+diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
+index 55b9520..a28d491 100644
+--- a/drivers/usb/storage/libusual.c
++++ b/drivers/usb/storage/libusual.c
+@@ -9,6 +9,7 @@
+ #include <linux/usb_usual.h>
+ #include <linux/vmalloc.h>
+ #include <linux/kthread.h>
++#include <linux/mutex.h>
- /* 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)
+@@ -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 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;
+-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);
- dbg("%s(port = %d, status = %d)",
-- __FUNCTION__, port->number, status);
-+ __func__, port->number, status);
+@@ -178,10 +179,7 @@ static int usu_probe_thread(void *arg)
+ int rc;
+ unsigned long flags;
- 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;
+- /* 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);
-@@ -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;
+ complete_and_exit(&usu_end_notify, 0);
+ }
+@@ -204,10 +203,9 @@ static int __init usb_usual_init(void)
+ {
+ int rc;
--// 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);
- }
- }
+- 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;
}
- static void oti6858_read_bulk_callback(struct urb *urb)
+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 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;
+ struct us_data *us = host_to_us(sdev->host);
++ struct usb_host_endpoint *bulk_in_ep;
- dbg("%s(port = %d, status = %d)",
-- __FUNCTION__, port->number, status);
-+ __func__, port->number, status);
+ /*
+ * 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 */
- 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)
+ /*
+ * 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;
- 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;
- }
+ /* 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);
-@@ -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);
- }
+- 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;
}
- }
- static void oti6858_write_bulk_callback(struct urb *urb)
+@@ -260,7 +262,7 @@ static int command_abort(struct scsi_cmnd *srb)
{
-- 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;
+ struct us_data *us = host_to_us(srb->device->host);
- dbg("%s(port = %d, status = %d)",
-- __FUNCTION__, port->number, status);
-+ __func__, port->number, status);
+- US_DEBUGP("%s called\n", __FUNCTION__);
++ US_DEBUGP("%s called\n", __func__);
- 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__);
+ /* 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;
- 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)
+- US_DEBUGP("%s called\n", __FUNCTION__);
++ US_DEBUGP("%s called\n", __func__);
- // 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);
- }
- }
+ /* 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;
-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;
+- 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;
-@@ -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;
+ complete(urb_done_ptr);
+ }
+@@ -198,7 +198,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
+ int status;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
+- __FUNCTION__, request, requesttype,
++ __func__, request, requesttype,
+ value, index, size);
- spin_lock_irqsave(&priv->lock, flags);
+ /* 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);
-@@ -441,7 +441,7 @@ static void pl2303_send(struct usb_serial_port *port)
+- US_DEBUGP("%s: result = %d\n", __FUNCTION__, result);
++ US_DEBUGP("%s: result = %d\n", __func__, result);
+ return result;
+ }
- spin_unlock_irqrestore(&priv->lock, flags);
+@@ -332,7 +332,7 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
+ int result;
-- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count,
-+ usb_serial_debug_data(debug, &port->dev, __func__, count,
- port->write_urb->transfer_buffer);
+ US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
+- __FUNCTION__, request, requesttype,
++ __func__, request, requesttype,
+ value, index, size);
- 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;
+ /* 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;
-- dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
-+ dbg("%s - port %d, %d bytes", __func__, port->number, count);
+- US_DEBUGP("%s: xfer %u bytes\n", __FUNCTION__, length);
++ US_DEBUGP("%s: xfer %u bytes\n", __func__, length);
- if (!count)
- return count;
-@@ -483,13 +483,13 @@ static int pl2303_write_room(struct usb_serial_port *port)
- int room = 0;
- unsigned long flags;
+ /* 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;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- US_DEBUGP("%s: xfer %u bytes\n", __FUNCTION__, length);
++ US_DEBUGP("%s: xfer %u bytes\n", __func__, length);
- spin_lock_irqsave(&priv->lock, flags);
- room = pl2303_buf_space_avail(priv->buf);
- spin_unlock_irqrestore(&priv->lock, flags);
+ /* 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;
-- dbg("%s - returns %d", __FUNCTION__, room);
-+ dbg("%s - returns %d", __func__, room);
- return room;
- }
+ /* 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);
-@@ -499,13 +499,13 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port)
- int chars = 0;
- unsigned long flags;
+ /* 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__);
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ /* 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,
- spin_lock_irqsave(&priv->lock, flags);
- chars = pl2303_buf_data_avail(priv->buf);
- spin_unlock_irqrestore(&priv->lock, flags);
+ int usb_stor_CB_reset(struct us_data *us)
+ {
+- US_DEBUGP("%s called\n", __FUNCTION__);
++ US_DEBUGP("%s called\n", __func__);
-- dbg("%s - returns %d", __FUNCTION__, chars);
-+ dbg("%s - returns %d", __func__, chars);
- return chars;
- }
+ 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__);
-@@ -521,7 +521,7 @@ static void pl2303_set_termios(struct usb_serial_port *port,
- int i;
- u8 control;
+ 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),
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
++#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
- spin_lock_irqsave(&priv->lock, flags);
- if (!priv->termios_initialized) {
-@@ -545,7 +545,9 @@ static void pl2303_set_termios(struct usb_serial_port *port,
+ /* Some informational data */
+ MODULE_AUTHOR("Matthew Dharm <mdharm-usb at one-eyed-alien.net>");
+@@ -187,7 +190,7 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message)
+ /* Wait until no command is running */
+ mutex_lock(&us->dev_mutex);
- 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;
- }
+- US_DEBUGP("%s\n", __FUNCTION__);
++ US_DEBUGP("%s\n", __func__);
+ if (us->suspend_resume_hook)
+ (us->suspend_resume_hook)(us, US_SUSPEND);
-@@ -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]);
- }
+@@ -204,7 +207,7 @@ static int storage_resume(struct usb_interface *iface)
- 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__);
- }
+ mutex_lock(&us->dev_mutex);
- 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__);
- }
+- US_DEBUGP("%s\n", __FUNCTION__);
++ US_DEBUGP("%s\n", __func__);
+ if (us->suspend_resume_hook)
+ (us->suspend_resume_hook)(us, US_RESUME);
- 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;
+@@ -216,7 +219,7 @@ static int storage_reset_resume(struct usb_interface *iface)
+ {
+ struct us_data *us = usb_get_intfdata(iface);
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- US_DEBUGP("%s\n", __FUNCTION__);
++ US_DEBUGP("%s\n", __func__);
- /* 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);
+ /* 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);
- /* 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;
+- US_DEBUGP("%s\n", __FUNCTION__);
++ US_DEBUGP("%s\n", __func__);
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ /* 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);
- 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)
+- US_DEBUGP("%s\n", __FUNCTION__);
++ US_DEBUGP("%s\n", __func__);
- //FIXME: need to assert RTS and DTR if CRTSCTS off
+ /* 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__);
-- 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;
- }
+ /* 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
-- 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;
++#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;
}
-@@ -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);
+@@ -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__);
- 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)
+ /* 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)
{
-- dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd);
-+ dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
+- US_DEBUGP("-- %s\n", __FUNCTION__);
++ US_DEBUGP("-- %s\n", __func__);
- switch (cmd) {
- case TIOCMIWAIT:
-- dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);
-+ dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
- return wait_modem_info(port, arg);
+ kfree(us->sensebuf);
- default:
-- dbg("%s not supported = 0x%04x", __FUNCTION__, cmd);
-+ dbg("%s not supported = 0x%04x", __func__, cmd);
- break;
+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;
-@@ -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);
+- dev = (struct usb_skel *)urb->context;
++ dev = urb->context;
- 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");
+ /* 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);
- 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);
- }
+ 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;
+ }
- 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;
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index 1bd5fb3..bb1dada 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -139,6 +139,30 @@ config FB_SYS_IMAGEBLIT
+ blitting. This is used by drivers that don't provide their own
+ (accelerated) version and the framebuffer is in system RAM.
+
++menuconfig FB_FOREIGN_ENDIAN
++ bool "Framebuffer foreign endianness support"
++ depends on FB
++ ---help---
++ This menu will let you enable support for the framebuffers with
++ non-native endianness (e.g. Little-Endian framebuffer on a
++ Big-Endian machine). Most probably you don't have such hardware,
++ so it's safe to say "n" here.
++
++choice
++ prompt "Choice endianness support"
++ depends on FB_FOREIGN_ENDIAN
++
++config FB_BOTH_ENDIAN
++ bool "Support for Big- and Little-Endian framebuffers"
++
++config FB_BIG_ENDIAN
++ bool "Support for Big-Endian framebuffers only"
++
++config FB_LITTLE_ENDIAN
++ bool "Support for Little-Endian framebuffers only"
++
++endchoice
++
+ config FB_SYS_FOPS
+ tristate
+ depends on FB
+@@ -149,6 +173,16 @@ config FB_DEFERRED_IO
+ depends on FB
+ default y
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
++config FB_METRONOME
++ tristate
++ depends on FB
++ depends on FB_DEFERRED_IO
++
++config FB_HECUBA
++ tristate
++ depends on FB
++ depends on FB_DEFERRED_IO
++
+ config FB_SVGALIB
+ tristate
+ depends on FB
+@@ -546,7 +580,7 @@ config FB_VGA16
- 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,
+ config FB_BF54X_LQ043
+ tristate "SHARP LQ043 TFT LCD (BF548 EZKIT)"
+- depends on FB && (BF54x)
++ depends on FB && (BF54x) && !BF542
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+@@ -674,20 +708,18 @@ config FB_IMAC
+ help
+ This is the frame buffer device driver for the Intel-based Macintosh
- 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;
+-config FB_HECUBA
+- tristate "Hecuba board support"
++config FB_N411
++ tristate "N411 Apollo/Hecuba devkit support"
+ depends on FB && X86 && MMU
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ select FB_DEFERRED_IO
++ select FB_HECUBA
+ help
+- This enables support for the Hecuba board. This driver was tested
+- with an E-Ink 800x600 display and x86 SBCs through a 16 bit GPIO
+- interface (8 bit data, 4 bit control). If you anticipate using
+- this driver, say Y or M; otherwise say N. You must specify the
+- GPIO IO address to be used for setting control and data.
++ This enables support for the Apollo display controller in its
++ Hecuba form using the n411 devkit.
+
+ config FB_HGA
+ tristate "Hercules mono graphics support"
+@@ -1087,7 +1119,7 @@ config FB_CARILLO_RANCH
+ This driver supports the LE80578 (Carillo Ranch) board
+
+ config FB_INTEL
+- tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G support (EXPERIMENTAL)"
++ tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support (EXPERIMENTAL)"
+ depends on FB && EXPERIMENTAL && PCI && X86
+ select AGP
+ select AGP_INTEL
+@@ -1097,7 +1129,7 @@ config FB_INTEL
+ select FB_CFB_IMAGEBLIT
+ help
+ This driver supports the on-board graphics built in to the Intel
+- 830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM chipsets.
++ 830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets.
+ Say Y if you have and plan to use such a board.
-- dbg("%s (%d)", __FUNCTION__, port->number);
-+ dbg("%s (%d)", __func__, port->number);
+ If you say Y here and want DDC/I2C support you must first say Y to
+@@ -1742,6 +1774,11 @@ config FB_PXA
- 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;
- }
+ If unsure, say N.
-- usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
-+ usb_serial_debug_data(debug, &port->dev, __func__,
- urb->actual_length, urb->transfer_buffer);
++config FB_PXA_SMARTPANEL
++ bool "PXA Smartpanel LCD support"
++ default n
++ depends on FB_PXA
++
+ config FB_PXA_PARAMETERS
+ bool "PXA LCD command line parameters"
+ default n
+@@ -1779,6 +1816,16 @@ config FB_MBX_DEBUG
- 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);
- }
+ If unsure, say N.
- 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;
++config FB_FSL_DIU
++ tristate "Freescale DIU framebuffer support"
++ depends on FB && FSL_SOC
++ select FB_CFB_FILLRECT
++ select FB_CFB_COPYAREA
++ select FB_CFB_IMAGEBLIT
++ select PPC_LIB_RHEAP
++ ---help---
++ Framebuffer driver for the Freescale SoC DIU
++
+ config FB_W100
+ tristate "W100 frame buffer support"
+ depends on FB && PXA_SHARPSL
+@@ -1893,19 +1940,18 @@ config FB_XILINX
+ framebuffer. ML300 carries a 640*480 LCD display on the board,
+ ML403 uses a standard DB15 VGA connector.
+
+-config FB_METRONOME
+- tristate "Metronome display controller support"
++config FB_AM200EPD
++ tristate "AM-200 E-Ink EPD devkit support"
+ depends on FB && ARCH_PXA && MMU
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ select FB_DEFERRED_IO
++ select FB_METRONOME
+ help
+- This enables support for the Metronome display controller. Tested
+- with an E-Ink 800x600 display and Gumstix Connex through an AMLCD
+- interface. Please read <file:Documentation/fb/metronomefb.txt>
+- for more information.
++ This enables support for the Metronome display controller used on
++ the E-Ink AM-200 EPD devkit.
+
+ config FB_VIRTUAL
+ tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
+@@ -1930,6 +1976,20 @@ config FB_VIRTUAL
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ If unsure, say N.
- 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;
- }
++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"
-- usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
-+ usb_serial_debug_data(debug, &port->dev, __func__,
- urb->actual_length, data);
+ source "drivers/video/backlight/Kconfig"
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index 11c0e5e..04bca35 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -29,6 +29,7 @@ obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
- /* 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);
+ # Hardware specific drivers go first
+ obj-$(CONFIG_FB_AMIGA) += amifb.o c2p.o
++obj-$(CONFIG_FB_AM200EPD) += am200epd.o
+ obj-$(CONFIG_FB_ARC) += arcfb.o
+ obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
+ obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
+@@ -107,6 +108,7 @@ obj-$(CONFIG_FB_METRONOME) += metronomefb.o
+ obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
+ obj-$(CONFIG_FB_IMX) += imxfb.o
+ obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
++obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o
+ obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/
+ obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/
+ obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
+@@ -114,6 +116,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
- 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);
- }
+ # Platform or fallback drivers go here
+ obj-$(CONFIG_FB_UVESA) += uvesafb.o
+diff --git a/drivers/video/am200epd.c b/drivers/video/am200epd.c
+new file mode 100644
+index 0000000..51e26c1
+--- /dev/null
++++ b/drivers/video/am200epd.c
+@@ -0,0 +1,295 @@
++/*
++ * linux/drivers/video/am200epd.c -- Platform device for AM200 EPD kit
++ *
++ * Copyright (C) 2008, Jaya Kumar
++ *
++ * 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.
++ *
++ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
++ *
++ * This work was made possible by help and equipment support from E-Ink
++ * Corporation. http://support.eink.com/community
++ *
++ * This driver is written to be used with the Metronome display controller.
++ * on the AM200 EPD prototype kit/development kit with an E-Ink 800x600
++ * Vizplex EPD on a Gumstix board using the Lyre interface board.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/fb.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/list.h>
++#include <linux/uaccess.h>
++#include <linux/irq.h>
++
++#include <video/metronomefb.h>
++
++#include <asm/arch/pxa-regs.h>
++
++/* register offsets for gpio control */
++#define LED_GPIO_PIN 51
++#define STDBY_GPIO_PIN 48
++#define RST_GPIO_PIN 49
++#define RDY_GPIO_PIN 32
++#define ERR_GPIO_PIN 17
++#define PCBPWR_GPIO_PIN 16
++
++#define AF_SEL_GPIO_N 0x3
++#define GAFR0_U_OFFSET(pin) ((pin - 16) * 2)
++#define GAFR1_L_OFFSET(pin) ((pin - 32) * 2)
++#define GAFR1_U_OFFSET(pin) ((pin - 48) * 2)
++#define GPDR1_OFFSET(pin) (pin - 32)
++#define GPCR1_OFFSET(pin) (pin - 32)
++#define GPSR1_OFFSET(pin) (pin - 32)
++#define GPCR0_OFFSET(pin) (pin)
++#define GPSR0_OFFSET(pin) (pin)
++
++static void am200_set_gpio_output(int pin, int val)
++{
++ u8 index;
++
++ index = pin >> 4;
++
++ switch (index) {
++ case 1:
++ if (val)
++ GPSR0 |= (1 << GPSR0_OFFSET(pin));
++ else
++ GPCR0 |= (1 << GPCR0_OFFSET(pin));
++ break;
++ case 2:
++ break;
++ case 3:
++ if (val)
++ GPSR1 |= (1 << GPSR1_OFFSET(pin));
++ else
++ GPCR1 |= (1 << GPCR1_OFFSET(pin));
++ break;
++ default:
++ printk(KERN_ERR "unimplemented\n");
++ }
++}
++
++static void __devinit am200_init_gpio_pin(int pin, int dir)
++{
++ u8 index;
++ /* dir 0 is output, 1 is input
++ - do 2 things here:
++ - set gpio alternate function to standard gpio
++ - set gpio direction to input or output */
++
++ index = pin >> 4;
++ switch (index) {
++ case 1:
++ GAFR0_U &= ~(AF_SEL_GPIO_N << GAFR0_U_OFFSET(pin));
++
++ if (dir)
++ GPDR0 &= ~(1 << pin);
++ else
++ GPDR0 |= (1 << pin);
++ break;
++ case 2:
++ GAFR1_L &= ~(AF_SEL_GPIO_N << GAFR1_L_OFFSET(pin));
++
++ if (dir)
++ GPDR1 &= ~(1 << GPDR1_OFFSET(pin));
++ else
++ GPDR1 |= (1 << GPDR1_OFFSET(pin));
++ break;
++ case 3:
++ GAFR1_U &= ~(AF_SEL_GPIO_N << GAFR1_U_OFFSET(pin));
++
++ if (dir)
++ GPDR1 &= ~(1 << GPDR1_OFFSET(pin));
++ else
++ GPDR1 |= (1 << GPDR1_OFFSET(pin));
++ break;
++ default:
++ printk(KERN_ERR "unimplemented\n");
++ }
++}
++
++static void am200_init_gpio_regs(struct metronomefb_par *par)
++{
++ am200_init_gpio_pin(LED_GPIO_PIN, 0);
++ am200_set_gpio_output(LED_GPIO_PIN, 0);
++
++ am200_init_gpio_pin(STDBY_GPIO_PIN, 0);
++ am200_set_gpio_output(STDBY_GPIO_PIN, 0);
++
++ am200_init_gpio_pin(RST_GPIO_PIN, 0);
++ am200_set_gpio_output(RST_GPIO_PIN, 0);
++
++ am200_init_gpio_pin(RDY_GPIO_PIN, 1);
++
++ am200_init_gpio_pin(ERR_GPIO_PIN, 1);
++
++ am200_init_gpio_pin(PCBPWR_GPIO_PIN, 0);
++ am200_set_gpio_output(PCBPWR_GPIO_PIN, 0);
++}
++
++static void am200_disable_lcd_controller(struct metronomefb_par *par)
++{
++ LCSR = 0xffffffff; /* Clear LCD Status Register */
++ LCCR0 |= LCCR0_DIS; /* Disable LCD Controller */
++
++ /* we reset and just wait for things to settle */
++ msleep(200);
++}
++
++static void am200_enable_lcd_controller(struct metronomefb_par *par)
++{
++ LCSR = 0xffffffff;
++ FDADR0 = par->metromem_desc_dma;
++ LCCR0 |= LCCR0_ENB;
++}
++
++static void am200_init_lcdc_regs(struct metronomefb_par *par)
++{
++ /* here we do:
++ - disable the lcd controller
++ - setup lcd control registers
++ - setup dma descriptor
++ - reenable lcd controller
++ */
++
++ /* disable the lcd controller */
++ am200_disable_lcd_controller(par);
++
++ /* setup lcd control registers */
++ LCCR0 = LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | LCCR0_PAS
++ | LCCR0_QDM | LCCR0_BM | LCCR0_OUM;
++
++ LCCR1 = (par->info->var.xres/2 - 1) /* pixels per line */
++ | (27 << 10) /* hsync pulse width - 1 */
++ | (33 << 16) /* eol pixel count */
++ | (33 << 24); /* bol pixel count */
++
++ LCCR2 = (par->info->var.yres - 1) /* lines per panel */
++ | (24 << 10) /* vsync pulse width - 1 */
++ | (2 << 16) /* eof pixel count */
++ | (0 << 24); /* bof pixel count */
++
++ LCCR3 = 2 /* pixel clock divisor */
++ | (24 << 8) /* AC Bias pin freq */
++ | LCCR3_16BPP /* BPP */
++ | LCCR3_PCP; /* PCP falling edge */
++
++}
++
++static void am200_post_dma_setup(struct metronomefb_par *par)
++{
++ par->metromem_desc->mFDADR0 = par->metromem_desc_dma;
++ par->metromem_desc->mFSADR0 = par->metromem_dma;
++ par->metromem_desc->mFIDR0 = 0;
++ par->metromem_desc->mLDCMD0 = par->info->var.xres
++ * par->info->var.yres;
++ am200_enable_lcd_controller(par);
++}
++
++static void am200_free_irq(struct fb_info *info)
++{
++ free_irq(IRQ_GPIO(RDY_GPIO_PIN), info);
++}
++
++static irqreturn_t am200_handle_irq(int irq, void *dev_id)
++{
++ struct fb_info *info = dev_id;
++ struct metronomefb_par *par = info->par;
++
++ wake_up_interruptible(&par->waitq);
++ return IRQ_HANDLED;
++}
++
++static int am200_setup_irq(struct fb_info *info)
++{
++ int retval;
++
++ retval = request_irq(IRQ_GPIO(RDY_GPIO_PIN), am200_handle_irq,
++ IRQF_DISABLED, "AM200", info);
++ if (retval) {
++ printk(KERN_ERR "am200epd: request_irq failed: %d\n", retval);
++ return retval;
++ }
++
++ return set_irq_type(IRQ_GPIO(RDY_GPIO_PIN), IRQT_FALLING);
++}
++
++static void am200_set_rst(struct metronomefb_par *par, int state)
++{
++ am200_set_gpio_output(RST_GPIO_PIN, state);
++}
++
++static void am200_set_stdby(struct metronomefb_par *par, int state)
++{
++ am200_set_gpio_output(STDBY_GPIO_PIN, state);
++}
++
++static int am200_wait_event(struct metronomefb_par *par)
++{
++ return wait_event_timeout(par->waitq, (GPLR1 & 0x01), HZ);
++}
++
++static int am200_wait_event_intr(struct metronomefb_par *par)
++{
++ return wait_event_interruptible_timeout(par->waitq, (GPLR1 & 0x01), HZ);
++}
++
++static struct metronome_board am200_board = {
++ .owner = THIS_MODULE,
++ .free_irq = am200_free_irq,
++ .setup_irq = am200_setup_irq,
++ .init_gpio_regs = am200_init_gpio_regs,
++ .init_lcdc_regs = am200_init_lcdc_regs,
++ .post_dma_setup = am200_post_dma_setup,
++ .set_rst = am200_set_rst,
++ .set_stdby = am200_set_stdby,
++ .met_wait_event = am200_wait_event,
++ .met_wait_event_intr = am200_wait_event_intr,
++};
++
++static struct platform_device *am200_device;
++
++static int __init am200_init(void)
++{
++ int ret;
++
++ /* request our platform independent driver */
++ request_module("metronomefb");
++
++ am200_device = platform_device_alloc("metronomefb", -1);
++ if (!am200_device)
++ return -ENOMEM;
++
++ platform_device_add_data(am200_device, &am200_board,
++ sizeof(am200_board));
++
++ /* this _add binds metronomefb to am200. metronomefb refcounts am200 */
++ ret = platform_device_add(am200_device);
++
++ if (ret)
++ platform_device_put(am200_device);
++
++ return ret;
++}
++
++static void __exit am200_exit(void)
++{
++ platform_device_unregister(am200_device);
++}
++
++module_init(am200_init);
++module_exit(am200_exit);
++
++MODULE_DESCRIPTION("board driver for am200 metronome epd kit");
++MODULE_AUTHOR("Jaya Kumar");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
+index 4c9ec3f..e6492c1 100644
+--- a/drivers/video/amifb.c
++++ b/drivers/video/amifb.c
+@@ -96,7 +96,7 @@
+ #endif
- return;
-@@ -1066,12 +1068,12 @@ static void pl2303_read_bulk_callback(struct urb *urb)
+ #ifdef DEBUG
+-# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
++# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
+ #else
+ # define DPRINTK(fmt, args...)
+ #endif
+diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c
+index 8a1b07c..5001bd4 100644
+--- a/drivers/video/arkfb.c
++++ b/drivers/video/arkfb.c
+@@ -101,7 +101,7 @@ static const struct svga_timing_regs ark_timing_regs = {
- 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;
+ /* Module parameters */
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+-static char *mode = "640x480-8 at 60";
++static char *mode_option __devinitdata = "640x480-8 at 60";
- 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)
+ #ifdef CONFIG_MTRR
+ static int mtrr = 1;
+@@ -111,8 +111,10 @@ MODULE_AUTHOR("(c) 2007 Ondrej Zajicek <santiago at crfreenet.org>");
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("fbdev driver for ARK 2000PV");
- 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;
+-module_param(mode, charp, 0444);
+-MODULE_PARM_DESC(mode, "Default video mode ('640x480-8 at 60', etc)");
++module_param(mode_option, charp, 0444);
++MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8 at 60', etc)");
++module_param_named(mode, mode_option, charp, 0444);
++MODULE_PARM_DESC(mode, "Default video mode ('640x480-8 at 60', etc) (deprecated)");
+
+ #ifdef CONFIG_MTRR
+ module_param(mtrr, int, 0444);
+@@ -941,7 +943,7 @@ static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_
+ }
+
+ /* Allocate and fill driver data structure */
+- info = framebuffer_alloc(sizeof(struct arkfb_info), NULL);
++ info = framebuffer_alloc(sizeof(struct arkfb_info), &(dev->dev));
+ if (! info) {
+ dev_err(&(dev->dev), "cannot allocate memory\n");
+ return -ENOMEM;
+@@ -956,20 +958,20 @@ static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_
+ /* Prepare PCI device */
+ rc = pci_enable_device(dev);
+ if (rc < 0) {
+- dev_err(&(dev->dev), "cannot enable PCI device\n");
++ dev_err(info->dev, "cannot enable PCI device\n");
+ goto err_enable_device;
+ }
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
+ rc = pci_request_regions(dev, "arkfb");
+ if (rc < 0) {
+- dev_err(&(dev->dev), "cannot reserve framebuffer region\n");
++ dev_err(info->dev, "cannot reserve framebuffer region\n");
+ goto err_request_regions;
+ }
- if (status) {
- dbg("%s - nonzero read bulk status received: %d",
-- __FUNCTION__, status);
-+ __func__, status);
- return;
+ par->dac = ics5342_init(ark_dac_read_regs, ark_dac_write_regs, info);
+ if (! par->dac) {
+ rc = -ENOMEM;
+- dev_err(&(dev->dev), "RAMDAC initialization failed\n");
++ dev_err(info->dev, "RAMDAC initialization failed\n");
+ goto err_dac;
}
-@@ -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);
+@@ -980,7 +982,7 @@ static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_
+ info->screen_base = pci_iomap(dev, 0, 0);
+ if (! info->screen_base) {
+ rc = -ENOMEM;
+- dev_err(&(dev->dev), "iomap for framebuffer failed\n");
++ dev_err(info->dev, "iomap for framebuffer failed\n");
+ goto err_iomap;
}
-@@ -259,7 +250,8 @@ static void safe_read_bulk_callback (struct urb *urb)
- safe_read_bulk_callback, port);
+@@ -999,22 +1001,22 @@ static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_
+ info->pseudo_palette = (void*) (par->pseudo_palette);
+
+ /* Prepare startup mode */
+- rc = fb_find_mode(&(info->var), info, mode, NULL, 0, NULL, 8);
++ rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
+ if (! ((rc == 1) || (rc == 2))) {
+ rc = -EINVAL;
+- dev_err(&(dev->dev), "mode %s not found\n", mode);
++ dev_err(info->dev, "mode %s not found\n", mode_option);
+ goto err_find_mode;
+ }
- 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 */
+ rc = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (rc < 0) {
+- dev_err(&(dev->dev), "cannot allocate colormap\n");
++ dev_err(info->dev, "cannot allocate colormap\n");
+ goto err_alloc_cmap;
}
- }
-@@ -274,25 +266,25 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i
- count);
+ rc = register_framebuffer(info);
+ if (rc < 0) {
+- dev_err(&(dev->dev), "cannot register framebugger\n");
++ dev_err(info->dev, "cannot register framebugger\n");
+ goto err_reg_fb;
+ }
+
+@@ -1088,7 +1090,7 @@ static int ark_pci_suspend (struct pci_dev* dev, pm_message_t state)
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct arkfb_info *par = info->par;
+
+- dev_info(&(dev->dev), "suspend\n");
++ dev_info(info->dev, "suspend\n");
+
+ acquire_console_sem();
+ mutex_lock(&(par->open_lock));
+@@ -1119,7 +1121,7 @@ static int ark_pci_resume (struct pci_dev* dev)
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct arkfb_info *par = info->par;
+
+- dev_info(&(dev->dev), "resume\n");
++ dev_info(info->dev, "resume\n");
+
+ acquire_console_sem();
+ mutex_lock(&(par->open_lock));
+@@ -1190,7 +1192,7 @@ static int __init arkfb_init(void)
+ return -ENODEV;
- if (!port->write_urb) {
-- dbg ("%s - write urb NULL", __FUNCTION__);
-- return (0);
-+ dbg ("%s - write urb NULL", __func__);
-+ return 0;
+ if (option && *option)
+- mode = option;
++ mode_option = option;
+ #endif
+
+ pr_debug("arkfb: initializing\n");
+diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
+index 5d4fbaa..dff3547 100644
+--- a/drivers/video/atafb.c
++++ b/drivers/video/atafb.c
+@@ -1270,7 +1270,7 @@ again:
+
+ gstart = (prescale / 2 + plen * left_margin) / prescale;
+ /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
+- gend1 = gstart + ((xres + align - 1) / align) * align * plen / prescale;
++ gend1 = gstart + roundup(xres, align) * plen / prescale;
+ /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
+ gend2 = gstart + xres * plen / prescale;
+ par->HHT = plen * (left_margin + xres + right_margin) /
+diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
+index fc65c02..8ffdf35 100644
+--- a/drivers/video/atmel_lcdfb.c
++++ b/drivers/video/atmel_lcdfb.c
+@@ -31,7 +31,8 @@
+ #define ATMEL_LCDC_CVAL_DEFAULT 0xc8
+ #define ATMEL_LCDC_DMA_BURST_LEN 8
+
+-#if defined(CONFIG_ARCH_AT91SAM9263) || defined(CONFIG_ARCH_AT91CAP9)
++#if defined(CONFIG_ARCH_AT91SAM9263) || defined(CONFIG_ARCH_AT91CAP9) || \
++ defined(CONFIG_ARCH_AT91SAM9RL)
+ #define ATMEL_LCDC_FIFO_SIZE 2048
+ #else
+ #define ATMEL_LCDC_FIFO_SIZE 512
+@@ -250,6 +251,8 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
+ return -ENOMEM;
}
- dbg ("safe_write write_urb: %d transfer_buffer_length",
- port->write_urb->transfer_buffer_length);
++ memset(info->screen_base, 0, info->fix.smem_len);
++
+ return 0;
+ }
- 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;
- }
+@@ -336,19 +339,35 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
+ break;
+ case 15:
+ case 16:
+- var->red.offset = 0;
++ if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
++ /* RGB:565 mode */
++ var->red.offset = 11;
++ var->blue.offset = 0;
++ var->green.length = 6;
++ } else {
++ /* BGR:555 mode */
++ var->red.offset = 0;
++ var->blue.offset = 10;
++ var->green.length = 5;
++ }
+ var->green.offset = 5;
+- var->blue.offset = 10;
+- var->red.length = var->green.length = var->blue.length = 5;
++ var->red.length = var->blue.length = 5;
+ break;
+ case 32:
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ /* fall through */
+ case 24:
+- var->red.offset = 0;
++ if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
++ /* RGB:888 mode */
++ var->red.offset = 16;
++ var->blue.offset = 0;
++ } else {
++ /* BGR:888 mode */
++ var->red.offset = 0;
++ var->blue.offset = 16;
++ }
+ var->green.offset = 8;
+- var->blue.offset = 16;
+ var->red.length = var->green.length = var->blue.length = 8;
+ break;
+ default:
+@@ -634,7 +653,6 @@ static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
+ struct fb_info *info = sinfo->info;
+ int ret = 0;
-- 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);
+- memset_io(info->screen_base, 0, info->fix.smem_len);
+ info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW;
- return (count);
+ dev_info(info->device,
+@@ -696,6 +714,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
+ sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control;
+ sinfo->guard_time = pdata_sinfo->guard_time;
+ sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight;
++ sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode;
+ } else {
+ dev_err(dev, "cannot get default configuration\n");
+ goto free_info;
+@@ -764,6 +783,11 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
+ info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+ if (!info->screen_base)
+ goto release_intmem;
++
++ /*
++ * Don't clear the framebuffer -- someone may have set
++ * up a splash image.
++ */
+ } else {
+ /* alocate memory buffer */
+ ret = atmel_lcdfb_alloc_video_memory(sinfo);
+@@ -903,10 +927,42 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
+ return 0;
}
- 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;
++#ifdef CONFIG_PM
++
++static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)
++{
++ struct fb_info *info = platform_get_drvdata(pdev);
++ struct atmel_lcdfb_info *sinfo = info->par;
++
++ sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
++ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);
++ if (sinfo->atmel_lcdfb_power_control)
++ sinfo->atmel_lcdfb_power_control(0);
++ atmel_lcdfb_stop_clock(sinfo);
++ return 0;
++}
++
++static int atmel_lcdfb_resume(struct platform_device *pdev)
++{
++ struct fb_info *info = platform_get_drvdata(pdev);
++ struct atmel_lcdfb_info *sinfo = info->par;
++
++ atmel_lcdfb_start_clock(sinfo);
++ if (sinfo->atmel_lcdfb_power_control)
++ sinfo->atmel_lcdfb_power_control(1);
++ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon);
++ return 0;
++}
++
++#else
++#define atmel_lcdfb_suspend NULL
++#define atmel_lcdfb_resume NULL
++#endif
++
+ static struct platform_driver atmel_lcdfb_driver = {
+ .remove = __exit_p(atmel_lcdfb_remove),
+-
+-// FIXME need suspend, resume
++ .suspend = atmel_lcdfb_suspend,
++ .resume = atmel_lcdfb_resume,
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
+ .driver = {
+ .name = "atmel_lcdfb",
+diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
+index cbd3308..24ee96c 100644
+--- a/drivers/video/aty/aty128fb.c
++++ b/drivers/video/aty/aty128fb.c
+@@ -91,7 +91,7 @@
+ #undef DEBUG
-+ 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);
+ #ifdef DEBUG
+-#define DBG(fmt, args...) printk(KERN_DEBUG "aty128fb: %s " fmt, __FUNCTION__, ##args);
++#define DBG(fmt, args...) printk(KERN_DEBUG "aty128fb: %s " fmt, __func__, ##args);
+ #else
+ #define DBG(fmt, args...)
+ #endif
+@@ -1885,7 +1885,7 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i
- if (room) {
- dbg ("safe_write_room returns %d", room);
- }
+ /* range check to make sure */
+ if (ent->driver_data < ARRAY_SIZE(r128_family))
+- strncat(video_card, r128_family[ent->driver_data], sizeof(video_card));
++ strlcat(video_card, r128_family[ent->driver_data], sizeof(video_card));
+
+ printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev);
+
+diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
+index 62f9c6e..e4bcf53 100644
+--- a/drivers/video/aty/atyfb_base.c
++++ b/drivers/video/aty/atyfb_base.c
+@@ -2621,10 +2621,13 @@ static int __devinit aty_init(struct fb_info *info)
+ #endif /* CONFIG_FB_ATY_CT */
+ info->var = var;
+
+- fb_alloc_cmap(&info->cmap, 256, 0);
++ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
++ goto aty_init_exit;
+
+- if (register_framebuffer(info) < 0)
++ if (register_framebuffer(info) < 0) {
++ fb_dealloc_cmap(&info->cmap);
+ goto aty_init_exit;
++ }
+
+ fb_list = info;
+
+diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c
+index cc9e977..c50c7cf 100644
+--- a/drivers/video/aty/mach64_ct.c
++++ b/drivers/video/aty/mach64_ct.c
+@@ -197,7 +197,7 @@ static int aty_dsp_gt(const struct fb_info *info, u32 bpp, struct pll_ct *pll)
+ pll->dsp_config = (dsp_precision << 20) | (pll->dsp_loop_latency << 16) | dsp_xclks;
+ #ifdef DEBUG
+ printk("atyfb(%s): dsp_config 0x%08x, dsp_on_off 0x%08x\n",
+- __FUNCTION__, pll->dsp_config, pll->dsp_on_off);
++ __func__, pll->dsp_config, pll->dsp_on_off);
+ #endif
+ return 0;
+ }
+@@ -225,7 +225,7 @@ static int aty_valid_pll_ct(const struct fb_info *info, u32 vclk_per, struct pll
+ (par->ref_clk_per * pll->pll_ref_div);
+ #ifdef DEBUG
+ printk("atyfb(%s): pllvclk=%d MHz, vclk=%d MHz\n",
+- __FUNCTION__, pllvclk, pllvclk / pll->vclk_post_div_real);
++ __func__, pllvclk, pllvclk / pll->vclk_post_div_real);
+ #endif
+ pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
-- return (room);
-+ return room;
+@@ -269,7 +269,7 @@ static u32 aty_pll_to_var_ct(const struct fb_info *info, const union aty_pll *pl
+ }
+ #endif
+ #ifdef DEBUG
+- printk("atyfb(%s): calculated 0x%08X(%i)\n", __FUNCTION__, ret, ret);
++ printk("atyfb(%s): calculated 0x%08X(%i)\n", __func__, ret, ret);
+ #endif
+ return ret;
}
+@@ -284,11 +284,11 @@ void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll)
+ #ifdef DEBUG
+ printk("atyfb(%s): about to program:\n"
+ "pll_ext_cntl=0x%02x pll_gen_cntl=0x%02x pll_vclk_cntl=0x%02x\n",
+- __FUNCTION__,
++ __func__,
+ pll->ct.pll_ext_cntl, pll->ct.pll_gen_cntl, pll->ct.pll_vclk_cntl);
- 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
+ printk("atyfb(%s): setting clock %lu for FeedBackDivider %i, ReferenceDivider %i, PostDivider %i(%i)\n",
+- __FUNCTION__,
++ __func__,
+ par->clk_wr_offset, pll->ct.vclk_fb_div,
+ pll->ct.pll_ref_div, pll->ct.vclk_post_div, pll->ct.vclk_post_div_real);
+ #endif
+@@ -428,7 +428,7 @@ static int __devinit aty_init_pll_ct(const struct fb_info *info,
-- Copyright (C) 2006, 2007, 2008 Kevin Lloyd <linux at sierrawireless.com>
-+ Copyright (C) 2006, 2007, 2008 Kevin Lloyd <klloyd at sierrawireless.com>
+ #ifdef DEBUG
+ printk("atyfb(%s): mclk_fb_mult=%d, xclk_post_div=%d\n",
+- __FUNCTION__, pll->ct.mclk_fb_mult, pll->ct.xclk_post_div);
++ __func__, pll->ct.mclk_fb_mult, pll->ct.xclk_post_div);
+ #endif
- IMPORTANT DISCLAIMER: This driver is not commercially supported by
- Sierra Wireless. Use at your own risk.
-@@ -14,8 +14,8 @@
- Whom based his on the Keyspan driver by Hugh Blemings <hugh at blemings.org>
- */
+ memcntl = aty_ld_le32(MEM_CNTL, par);
+@@ -540,7 +540,7 @@ static int __devinit aty_init_pll_ct(const struct fb_info *info,
+ pllmclk = (1000000 * pll->ct.mclk_fb_mult * pll->ct.mclk_fb_div) /
+ (par->ref_clk_per * pll->ct.pll_ref_div);
+ printk("atyfb(%s): pllmclk=%d MHz, xclk=%d MHz\n",
+- __FUNCTION__, pllmclk, pllmclk / pll->ct.xclk_post_div_real);
++ __func__, pllmclk, pllmclk / pll->ct.xclk_post_div_real);
+ #endif
--#define DRIVER_VERSION "v.1.2.8"
--#define DRIVER_AUTHOR "Kevin Lloyd <linux at sierrawireless.com>"
-+#define DRIVER_VERSION "v.1.2.9c"
-+#define DRIVER_AUTHOR "Kevin Lloyd <klloyd at sierrawireless.com>"
- #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
+ if (M64_HAS(SDRAM_MAGIC_PLL) && (par->ram_type >= SDRAM))
+@@ -581,7 +581,7 @@ static int __devinit aty_init_pll_ct(const struct fb_info *info,
+ pllsclk = (1000000 * 2 * pll->ct.sclk_fb_div) /
+ (par->ref_clk_per * pll->ct.pll_ref_div);
+ printk("atyfb(%s): use sclk, pllsclk=%d MHz, sclk=mclk=%d MHz\n",
+- __FUNCTION__, pllsclk, pllsclk / sclk_post_div_real);
++ __func__, pllsclk, pllsclk / sclk_post_div_real);
+ #endif
+ }
- #include <linux/kernel.h>
-@@ -31,7 +31,6 @@
- #define SWIMS_USB_REQUEST_SetPower 0x00
- #define SWIMS_USB_REQUEST_SetNmea 0x07
- #define SWIMS_USB_REQUEST_SetMode 0x0B
--#define SWIMS_USB_REQUEST_TYPE_VSC_SET 0x40
- #define SWIMS_SET_MODE_Modem 0x0001
+diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
+index 62867cb..72cd0d2 100644
+--- a/drivers/video/aty/radeon_base.c
++++ b/drivers/video/aty/radeon_base.c
+@@ -52,11 +52,14 @@
- /* 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;
- }
+ #define RADEON_VERSION "0.2.0"
-+static int sierra_calc_interface(struct usb_serial *serial)
-+{
-+ int interface;
-+ struct usb_interface *p_interface;
-+ struct usb_host_interface *p_host_interface;
++#include "radeonfb.h"
+
-+ /* 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;
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/string.h>
++#include <linux/ctype.h>
+ #include <linux/mm.h>
+ #include <linux/slab.h>
+ #include <linux/delay.h>
+@@ -91,7 +94,6 @@
+
+ #include "../edid.h" // MOVE THAT TO include/video
+ #include "ati_ids.h"
+-#include "radeonfb.h"
+
+ #define MAX_MAPPED_VRAM (2048*2048*4)
+ #define MIN_MAPPED_VRAM (1024*768*1)
+@@ -1488,7 +1490,7 @@ static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs
+ freq = rinfo->pll.ppll_max;
+ if (freq*12 < rinfo->pll.ppll_min)
+ freq = rinfo->pll.ppll_min / 12;
+- RTRACE("freq = %lu, PLL min = %u, PLL max = %u\n",
++ pr_debug("freq = %lu, PLL min = %u, PLL max = %u\n",
+ freq, rinfo->pll.ppll_min, rinfo->pll.ppll_max);
+
+ for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
+@@ -1509,7 +1511,7 @@ static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs
+ post_div = &post_divs[post_div->bitvalue];
+ pll_output_freq = post_div->divider * freq;
+ }
+- RTRACE("ref_div = %d, ref_clk = %d, output_freq = %d\n",
++ pr_debug("ref_div = %d, ref_clk = %d, output_freq = %d\n",
+ rinfo->pll.ref_div, rinfo->pll.ref_clk,
+ pll_output_freq);
+
+@@ -1519,7 +1521,7 @@ static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs
+ post_div = &post_divs[post_div->bitvalue];
+ pll_output_freq = post_div->divider * freq;
+ }
+- RTRACE("ref_div = %d, ref_clk = %d, output_freq = %d\n",
++ pr_debug("ref_div = %d, ref_clk = %d, output_freq = %d\n",
+ rinfo->pll.ref_div, rinfo->pll.ref_clk,
+ pll_output_freq);
+
+@@ -1528,9 +1530,9 @@ static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs
+ regs->ppll_ref_div = rinfo->pll.ref_div;
+ regs->ppll_div_3 = fb_div | (post_div->bitvalue << 16);
+
+- RTRACE("post div = 0x%x\n", post_div->bitvalue);
+- RTRACE("fb_div = 0x%x\n", fb_div);
+- RTRACE("ppll_div_3 = 0x%x\n", regs->ppll_div_3);
++ pr_debug("post div = 0x%x\n", post_div->bitvalue);
++ pr_debug("fb_div = 0x%x\n", fb_div);
++ pr_debug("ppll_div_3 = 0x%x\n", regs->ppll_div_3);
+ }
+
+ static int radeonfb_set_par(struct fb_info *info)
+@@ -1602,9 +1604,9 @@ static int radeonfb_set_par(struct fb_info *info)
+ dotClock = 1000000000 / pixClock;
+ freq = dotClock / 10; /* x100 */
+
+- RTRACE("hStart = %d, hEnd = %d, hTotal = %d\n",
++ pr_debug("hStart = %d, hEnd = %d, hTotal = %d\n",
+ hSyncStart, hSyncEnd, hTotal);
+- RTRACE("vStart = %d, vEnd = %d, vTotal = %d\n",
++ pr_debug("vStart = %d, vEnd = %d, vTotal = %d\n",
+ vSyncStart, vSyncEnd, vTotal);
+
+ hsync_wid = (hSyncEnd - hSyncStart) / 8;
+@@ -1713,16 +1715,16 @@ static int radeonfb_set_par(struct fb_info *info)
+ newmode->surf_info[i] = 0;
+ }
+
+- RTRACE("h_total_disp = 0x%x\t hsync_strt_wid = 0x%x\n",
++ pr_debug("h_total_disp = 0x%x\t hsync_strt_wid = 0x%x\n",
+ newmode->crtc_h_total_disp, newmode->crtc_h_sync_strt_wid);
+- RTRACE("v_total_disp = 0x%x\t vsync_strt_wid = 0x%x\n",
++ pr_debug("v_total_disp = 0x%x\t vsync_strt_wid = 0x%x\n",
+ newmode->crtc_v_total_disp, newmode->crtc_v_sync_strt_wid);
+
+ rinfo->bpp = mode->bits_per_pixel;
+ rinfo->depth = depth;
+
+- RTRACE("pixclock = %lu\n", (unsigned long)pixClock);
+- RTRACE("freq = %lu\n", (unsigned long)freq);
++ pr_debug("pixclock = %lu\n", (unsigned long)pixClock);
++ pr_debug("freq = %lu\n", (unsigned long)freq);
+
+ /* We use PPLL_DIV_3 */
+ newmode->clk_cntl_index = 0x300;
+@@ -1986,7 +1988,7 @@ static void fixup_memory_mappings(struct radeonfb_info *rinfo)
+ if (rinfo->has_CRTC2)
+ OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl);
+
+- RTRACE("aper_base: %08x MC_FB_LOC to: %08x, MC_AGP_LOC to: %08x\n",
++ pr_debug("aper_base: %08x MC_FB_LOC to: %08x, MC_AGP_LOC to: %08x\n",
+ aper_base,
+ ((aper_base + aper_size - 1) & 0xffff0000) | (aper_base >> 16),
+ 0xffff0000 | (agp_base >> 16));
+@@ -2083,7 +2085,7 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo)
+ * ToDo: identify these cases
+ */
+
+- RTRACE("radeonfb (%s): Found %ldk of %s %d bits wide videoram\n",
++ pr_debug("radeonfb (%s): Found %ldk of %s %d bits wide videoram\n",
+ pci_name(rinfo->pdev),
+ rinfo->video_ram / 1024,
+ rinfo->vram_ddr ? "DDR" : "SDRAM",
+@@ -2158,8 +2160,9 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
+ struct fb_info *info;
+ struct radeonfb_info *rinfo;
+ int ret;
++ unsigned char c1, c2;
+
+- RTRACE("radeonfb_pci_register BEGIN\n");
++ pr_debug("radeonfb_pci_register BEGIN\n");
+
+ /* Enable device in PCI config */
+ ret = pci_enable_device(pdev);
+@@ -2185,9 +2188,15 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
+ rinfo->lvds_timer.function = radeon_lvds_timer_func;
+ rinfo->lvds_timer.data = (unsigned long)rinfo;
+
+- strcpy(rinfo->name, "ATI Radeon XX ");
+- rinfo->name[11] = ent->device >> 8;
+- rinfo->name[12] = ent->device & 0xFF;
++ c1 = ent->device >> 8;
++ c2 = ent->device & 0xff;
++ if (isprint(c1) && isprint(c2))
++ snprintf(rinfo->name, sizeof(rinfo->name),
++ "ATI Radeon %x \"%c%c\"", ent->device & 0xffff, c1, c2);
++ else
++ snprintf(rinfo->name, sizeof(rinfo->name),
++ "ATI Radeon %x", ent->device & 0xffff);
+
-+ /* read the interface descriptor for this active altsetting
-+ * to find out the interface number we are on
-+ */
-+ interface = p_host_interface->desc.bInterfaceNumber;
+ rinfo->family = ent->driver_data & CHIP_FAMILY_MASK;
+ rinfo->chipset = pdev->device;
+ rinfo->has_CRTC2 = (ent->driver_data & CHIP_HAS_CRTC2) != 0;
+@@ -2278,7 +2287,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
+ goto err_unmap_rom;
+ }
+
+- RTRACE("radeonfb (%s): mapped %ldk videoram\n", pci_name(rinfo->pdev),
++ pr_debug("radeonfb (%s): mapped %ldk videoram\n", pci_name(rinfo->pdev),
+ rinfo->mapped_vram/1024);
+
+ /*
+@@ -2373,7 +2382,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
+
+ if (rinfo->bios_seg)
+ radeon_unmap_ROM(rinfo, pdev);
+- RTRACE("radeonfb_pci_register END\n");
++ pr_debug("radeonfb_pci_register END\n");
+
+ return 0;
+ err_unmap_fb:
+diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
+index 7db9de6..f9e7c29 100644
+--- a/drivers/video/aty/radeon_i2c.c
++++ b/drivers/video/aty/radeon_i2c.c
+@@ -1,3 +1,5 @@
++#include "radeonfb.h"
+
-+ return interface;
-+}
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/delay.h>
+@@ -11,7 +13,6 @@
+ #include <asm/io.h>
+
+ #include <video/radeon.h>
+-#include "radeonfb.h"
+ #include "../edid.h"
+
+ static void radeon_gpio_setscl(void* data, int state)
+@@ -77,7 +78,7 @@ static int radeon_setup_i2c_bus(struct radeon_i2c_chan *chan, const char *name)
+ chan->algo.setscl = radeon_gpio_setscl;
+ chan->algo.getsda = radeon_gpio_getsda;
+ chan->algo.getscl = radeon_gpio_getscl;
+- chan->algo.udelay = 40;
++ chan->algo.udelay = 10;
+ chan->algo.timeout = 20;
+ chan->algo.data = chan;
+
+@@ -148,21 +149,21 @@ int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn,
+ if (out_edid)
+ *out_edid = edid;
+ if (!edid) {
+- RTRACE("radeonfb: I2C (port %d) ... not found\n", conn);
++ pr_debug("radeonfb: I2C (port %d) ... not found\n", conn);
+ return MT_NONE;
+ }
+ if (edid[0x14] & 0x80) {
+ /* Fix detection using BIOS tables */
+ if (rinfo->is_mobility /*&& conn == ddc_dvi*/ &&
+ (INREG(LVDS_GEN_CNTL) & LVDS_ON)) {
+- RTRACE("radeonfb: I2C (port %d) ... found LVDS panel\n", conn);
++ pr_debug("radeonfb: I2C (port %d) ... found LVDS panel\n", conn);
+ return MT_LCD;
+ } else {
+- RTRACE("radeonfb: I2C (port %d) ... found TMDS panel\n", conn);
++ pr_debug("radeonfb: I2C (port %d) ... found TMDS panel\n", conn);
+ return MT_DFP;
+ }
+ }
+- RTRACE("radeonfb: I2C (port %d) ... found CRT display\n", conn);
++ pr_debug("radeonfb: I2C (port %d) ... found CRT display\n", conn);
+ return MT_CRT;
+ }
+
+diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
+index 2030ed8..b4d4b88 100644
+--- a/drivers/video/aty/radeon_monitor.c
++++ b/drivers/video/aty/radeon_monitor.c
+@@ -69,11 +69,11 @@ static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_
+ u8 *tmp;
+ int i, mt = MT_NONE;
+
+- RTRACE("analyzing OF properties...\n");
++ pr_debug("analyzing OF properties...\n");
+ pmt = of_get_property(dp, "display-type", NULL);
+ if (!pmt)
+ return MT_NONE;
+- RTRACE("display-type: %s\n", pmt);
++ pr_debug("display-type: %s\n", pmt);
+ /* OF says "LCD" for DFP as well, we discriminate from the caller of this
+ * function
+ */
+@@ -117,7 +117,7 @@ static int __devinit radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_
+ {
+ struct device_node *dp;
+
+- RTRACE("radeon_probe_OF_head\n");
++ pr_debug("radeon_probe_OF_head\n");
+
+ dp = rinfo->of_node;
+ while (dp == NULL)
+@@ -135,7 +135,7 @@ static int __devinit radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_
+ if (!pname)
+ return MT_NONE;
+ len = strlen(pname);
+- RTRACE("head: %s (letter: %c, head_no: %d)\n",
++ pr_debug("head: %s (letter: %c, head_no: %d)\n",
+ pname, pname[len-1], head_no);
+ if (pname[len-1] == 'A' && head_no == 0) {
+ int mt = radeon_parse_montype_prop(dp, out_EDID, 0);
+@@ -185,7 +185,7 @@ static int __devinit radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo)
+ rinfo->panel_info.xres, rinfo->panel_info.yres);
+
+ rinfo->panel_info.pwr_delay = BIOS_IN16(tmp + 44);
+- RTRACE("BIOS provided panel power delay: %d\n", rinfo->panel_info.pwr_delay);
++ pr_debug("BIOS provided panel power delay: %d\n", rinfo->panel_info.pwr_delay);
+ if (rinfo->panel_info.pwr_delay > 2000 || rinfo->panel_info.pwr_delay <= 0)
+ rinfo->panel_info.pwr_delay = 2000;
+
+@@ -199,16 +199,16 @@ static int __devinit radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo)
+ rinfo->panel_info.fbk_divider > 3) {
+ rinfo->panel_info.use_bios_dividers = 1;
+ printk(KERN_INFO "radeondb: BIOS provided dividers will be used\n");
+- RTRACE("ref_divider = %x\n", rinfo->panel_info.ref_divider);
+- RTRACE("post_divider = %x\n", rinfo->panel_info.post_divider);
+- RTRACE("fbk_divider = %x\n", rinfo->panel_info.fbk_divider);
++ pr_debug("ref_divider = %x\n", rinfo->panel_info.ref_divider);
++ pr_debug("post_divider = %x\n", rinfo->panel_info.post_divider);
++ pr_debug("fbk_divider = %x\n", rinfo->panel_info.fbk_divider);
+ }
+- RTRACE("Scanning BIOS table ...\n");
++ pr_debug("Scanning BIOS table ...\n");
+ for(i=0; i<32; i++) {
+ tmp0 = BIOS_IN16(tmp+64+i*2);
+ if (tmp0 == 0)
+ break;
+- RTRACE(" %d x %d\n", BIOS_IN16(tmp0), BIOS_IN16(tmp0+2));
++ pr_debug(" %d x %d\n", BIOS_IN16(tmp0), BIOS_IN16(tmp0+2));
+ if ((BIOS_IN16(tmp0) == rinfo->panel_info.xres) &&
+ (BIOS_IN16(tmp0+2) == rinfo->panel_info.yres)) {
+ rinfo->panel_info.hblank = (BIOS_IN16(tmp0+17) - BIOS_IN16(tmp0+19)) * 8;
+@@ -227,19 +227,19 @@ static int __devinit radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo)
+ /* Mark panel infos valid */
+ rinfo->panel_info.valid = 1;
+
+- RTRACE("Found panel in BIOS table:\n");
+- RTRACE(" hblank: %d\n", rinfo->panel_info.hblank);
+- RTRACE(" hOver_plus: %d\n", rinfo->panel_info.hOver_plus);
+- RTRACE(" hSync_width: %d\n", rinfo->panel_info.hSync_width);
+- RTRACE(" vblank: %d\n", rinfo->panel_info.vblank);
+- RTRACE(" vOver_plus: %d\n", rinfo->panel_info.vOver_plus);
+- RTRACE(" vSync_width: %d\n", rinfo->panel_info.vSync_width);
+- RTRACE(" clock: %d\n", rinfo->panel_info.clock);
++ pr_debug("Found panel in BIOS table:\n");
++ pr_debug(" hblank: %d\n", rinfo->panel_info.hblank);
++ pr_debug(" hOver_plus: %d\n", rinfo->panel_info.hOver_plus);
++ pr_debug(" hSync_width: %d\n", rinfo->panel_info.hSync_width);
++ pr_debug(" vblank: %d\n", rinfo->panel_info.vblank);
++ pr_debug(" vOver_plus: %d\n", rinfo->panel_info.vOver_plus);
++ pr_debug(" vSync_width: %d\n", rinfo->panel_info.vSync_width);
++ pr_debug(" clock: %d\n", rinfo->panel_info.clock);
+
+ return 1;
+ }
+ }
+- RTRACE("Didn't find panel in BIOS table !\n");
++ pr_debug("Didn't find panel in BIOS table !\n");
+
+ return 0;
+ }
+@@ -271,18 +271,18 @@ static void __devinit radeon_parse_connector_info(struct radeonfb_info *rinfo)
+ * DEBUG is enabled
+ */
+ chips = BIOS_IN8(offset++) >> 4;
+- RTRACE("%d chips in connector info\n", chips);
++ pr_debug("%d chips in connector info\n", chips);
+ for (i = 0; i < chips; i++) {
+ tmp = BIOS_IN8(offset++);
+ connectors = tmp & 0x0f;
+- RTRACE(" - chip %d has %d connectors\n", tmp >> 4, connectors);
++ pr_debug(" - chip %d has %d connectors\n", tmp >> 4, connectors);
+ for (conn = 0; ; conn++) {
+ tmp = BIOS_IN16(offset);
+ if (tmp == 0)
+ break;
+ offset += 2;
+ type = (tmp >> 12) & 0x0f;
+- RTRACE(" * connector %d of type %d (%s) : %04x\n",
++ pr_debug(" * connector %d of type %d (%s) : %04x\n",
+ conn, type, __conn_type_table[type], tmp);
+ }
+ }
+@@ -449,7 +449,7 @@ void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
+ * a layout for each card ?
+ */
+
+- RTRACE("Using specified monitor layout: %s", monitor_layout);
++ pr_debug("Using specified monitor layout: %s", monitor_layout);
+ #ifdef CONFIG_FB_RADEON_I2C
+ if (!ignore_edid) {
+ if (rinfo->mon1_type != MT_NONE)
+@@ -479,9 +479,9 @@ void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
+ * Auto-detecting display type (well... trying to ...)
+ */
+
+- RTRACE("Starting monitor auto detection...\n");
++ pr_debug("Starting monitor auto detection...\n");
+
+-#if DEBUG && defined(CONFIG_FB_RADEON_I2C)
++#if defined(DEBUG) && defined(CONFIG_FB_RADEON_I2C)
+ {
+ u8 *EDIDs[4] = { NULL, NULL, NULL, NULL };
+ int mon_types[4] = {MT_NONE, MT_NONE, MT_NONE, MT_NONE};
+@@ -756,7 +756,7 @@ void __devinit radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_
+ if (!rinfo->panel_info.use_bios_dividers && rinfo->mon1_type != MT_CRT
+ && rinfo->mon1_EDID) {
+ struct fb_var_screeninfo var;
+- RTRACE("Parsing EDID data for panel info\n");
++ pr_debug("Parsing EDID data for panel info\n");
+ if (fb_parse_edid(rinfo->mon1_EDID, &var) == 0) {
+ if (var.xres >= rinfo->panel_info.xres &&
+ var.yres >= rinfo->panel_info.yres)
+@@ -776,7 +776,7 @@ void __devinit radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_
+ if (rinfo->mon1_type != MT_CRT && rinfo->panel_info.valid) {
+ struct fb_var_screeninfo *var = &info->var;
+
+- RTRACE("Setting up default mode based on panel info\n");
++ pr_debug("Setting up default mode based on panel info\n");
+ var->xres = rinfo->panel_info.xres;
+ var->yres = rinfo->panel_info.yres;
+ var->xres_virtual = rinfo->panel_info.xres;
+@@ -824,7 +824,7 @@ void __devinit radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_
+ int dbsize;
+ char modename[32];
+
+- RTRACE("Guessing panel info...\n");
++ pr_debug("Guessing panel info...\n");
+ if (rinfo->panel_info.xres == 0 || rinfo->panel_info.yres == 0) {
+ u32 tmp = INREG(FP_HORZ_STRETCH) & HORZ_PANEL_SIZE;
+ rinfo->panel_info.xres = ((tmp >> HORZ_PANEL_SHIFT) + 1) * 8;
+diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
+index 5eac1ce..c347e38 100644
+--- a/drivers/video/aty/radeonfb.h
++++ b/drivers/video/aty/radeonfb.h
+@@ -1,6 +1,10 @@
+ #ifndef __RADEONFB_H__
+ #define __RADEONFB_H__
+
++#ifdef CONFIG_FB_RADEON_DEBUG
++#define DEBUG 1
++#endif
+
- static int sierra_probe(struct usb_serial *serial,
- const struct usb_device_id *id)
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+@@ -365,22 +369,6 @@ struct radeonfb_info {
+
+
+ /*
+- * Debugging stuffs
+- */
+-#ifdef CONFIG_FB_RADEON_DEBUG
+-#define DEBUG 1
+-#else
+-#define DEBUG 0
+-#endif
+-
+-#if DEBUG
+-#define RTRACE printk
+-#else
+-#define RTRACE if(0) printk
+-#endif
+-
+-
+-/*
+ * IO macros
+ */
+
+diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
+index eefba3d..49834a6 100644
+--- a/drivers/video/bf54x-lq043fb.c
++++ b/drivers/video/bf54x-lq043fb.c
+@@ -336,7 +336,7 @@ static int bfin_bf54x_fb_check_var(struct fb_var_screeninfo *var,
{
-@@ -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 */
+ if (var->bits_per_pixel != LCD_BPP) {
+- pr_debug("%s: depth not supported: %u BPP\n", __FUNCTION__,
++ pr_debug("%s: depth not supported: %u BPP\n", __func__,
+ var->bits_per_pixel);
+ return -EINVAL;
+ }
+@@ -345,7 +345,7 @@ static int bfin_bf54x_fb_check_var(struct fb_var_screeninfo *var,
+ info->var.xres_virtual != var->xres_virtual ||
+ info->var.yres_virtual != var->yres_virtual) {
+ pr_debug("%s: Resolution not supported: X%u x Y%u \n",
+- __FUNCTION__, var->xres, var->yres);
++ __func__, var->xres, var->yres);
+ return -EINVAL;
+ }
- { 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 */
+@@ -355,7 +355,7 @@ static int bfin_bf54x_fb_check_var(struct fb_var_screeninfo *var,
- { 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;
+ if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
+ pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
+- __FUNCTION__, var->yres_virtual);
++ __func__, var->yres_virtual);
+ return -ENOMEM;
+ }
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+@@ -652,7 +652,7 @@ static int __init bfin_bf54x_probe(struct platform_device *pdev)
+ goto out7;
+ }
- portdata = usb_get_serial_port_data(port);
+- if (request_irq(info->irq, (void *)bfin_bf54x_irq_error, IRQF_DISABLED,
++ if (request_irq(info->irq, bfin_bf54x_irq_error, IRQF_DISABLED,
+ "PPI ERROR", info) < 0) {
+ printk(KERN_ERR DRIVER_NAME
+ ": unable to request PPI ERROR IRQ\n");
+diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
+index 833b10c..275d9da 100644
+--- a/drivers/video/bw2.c
++++ b/drivers/video/bw2.c
+@@ -339,7 +339,7 @@ static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *
-@@ -246,24 +286,24 @@ static int sierra_send_setup(struct usb_serial_port *port)
+ dev_set_drvdata(&op->dev, info);
- static void sierra_rx_throttle(struct usb_serial_port *port)
- {
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
- }
+- printk("%s: bwtwo at %lx:%lx\n",
++ printk(KERN_INFO "%s: bwtwo at %lx:%lx\n",
+ dp->full_name, par->which_io, par->physbase);
- static void sierra_rx_unthrottle(struct usb_serial_port *port)
+ return 0;
+@@ -399,10 +399,9 @@ static int __init bw2_init(void)
+
+ static void __exit bw2_exit(void)
{
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+- return of_unregister_driver(&bw2_driver);
++ of_unregister_driver(&bw2_driver);
}
- static void sierra_break_ctl(struct usb_serial_port *port, int break_state)
+-
+ module_init(bw2_init);
+ module_exit(bw2_exit);
+
+diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c
+index b07e419..df03f37 100644
+--- a/drivers/video/cfbcopyarea.c
++++ b/drivers/video/cfbcopyarea.c
+@@ -44,15 +44,16 @@
+ */
+
+ static void
+-bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src,
+- int src_idx, int bits, unsigned n, u32 bswapmask)
++bitcpy(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
++ const unsigned long __iomem *src, int src_idx, int bits,
++ unsigned n, u32 bswapmask)
+ {
+ unsigned long first, last;
+ int const shift = dst_idx-src_idx;
+ int left, right;
+
+- first = fb_shifted_pixels_mask_long(dst_idx, bswapmask);
+- last = ~fb_shifted_pixels_mask_long((dst_idx+n) % bits, bswapmask);
++ first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
++ last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
+
+ if (!shift) {
+ // Same alignment for source and dest
+@@ -202,8 +203,9 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src
+ */
+
+ static void
+-bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src,
+- int src_idx, int bits, unsigned n, u32 bswapmask)
++bitcpy_rev(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
++ const unsigned long __iomem *src, int src_idx, int bits,
++ unsigned n, u32 bswapmask)
{
- /* Unfortunately, I don't know how to send a break */
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
- }
+ unsigned long first, last;
+ int shift;
+@@ -221,8 +223,9 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem
- static void sierra_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+ shift = dst_idx-src_idx;
+
+- first = fb_shifted_pixels_mask_long(bits - 1 - dst_idx, bswapmask);
+- last = ~fb_shifted_pixels_mask_long(bits - 1 - ((dst_idx-n) % bits), bswapmask);
++ first = fb_shifted_pixels_mask_long(p, bits - 1 - dst_idx, bswapmask);
++ last = ~fb_shifted_pixels_mask_long(p, bits - 1 - ((dst_idx-n) % bits),
++ bswapmask);
+
+ if (!shift) {
+ // Same alignment for source and dest
+@@ -404,7 +407,7 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+ dst_idx &= (bytes - 1);
+ src += src_idx >> (ffs(bits) - 1);
+ src_idx &= (bytes - 1);
+- bitcpy_rev(dst, dst_idx, src, src_idx, bits,
++ bitcpy_rev(p, dst, dst_idx, src, src_idx, bits,
+ width*p->var.bits_per_pixel, bswapmask);
+ }
+ } else {
+@@ -413,7 +416,7 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+ dst_idx &= (bytes - 1);
+ src += src_idx >> (ffs(bits) - 1);
+ src_idx &= (bytes - 1);
+- bitcpy(dst, dst_idx, src, src_idx, bits,
++ bitcpy(p, dst, dst_idx, src, src_idx, bits,
+ width*p->var.bits_per_pixel, bswapmask);
+ dst_idx += bits_per_line;
+ src_idx += bits_per_line;
+diff --git a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c
+index 23d70a1..64b3576 100644
+--- a/drivers/video/cfbfillrect.c
++++ b/drivers/video/cfbfillrect.c
+@@ -36,16 +36,16 @@
+ */
+
+ static void
+-bitfill_aligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
+- unsigned n, int bits, u32 bswapmask)
++bitfill_aligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
++ unsigned long pat, unsigned n, int bits, u32 bswapmask)
{
-- 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;
+ unsigned long first, last;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ if (!n)
+ return;
- /* free up the transfer buffer, as usb_free_urb() does not do this */
- kfree(urb->transfer_buffer);
+- first = fb_shifted_pixels_mask_long(dst_idx, bswapmask);
+- last = ~fb_shifted_pixels_mask_long((dst_idx+n) % bits, bswapmask);
++ first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
++ last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
+
+ if (dst_idx+n <= bits) {
+ // Single word
+@@ -93,16 +93,16 @@ bitfill_aligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
+ */
- if (status)
- dbg("%s - nonzero write bulk status received: %d",
-- __FUNCTION__, status);
-+ __func__, status);
+ static void
+-bitfill_unaligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
+- int left, int right, unsigned n, int bits)
++bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
++ unsigned long pat, int left, int right, unsigned n, int bits)
+ {
+ unsigned long first, last;
- spin_lock_irqsave(&portdata->lock, flags);
- --portdata->outstanding_urbs;
-@@ -346,12 +386,12 @@ static int sierra_write(struct usb_serial_port *port,
+ if (!n)
+ return;
- portdata = usb_get_serial_port_data(port);
+- first = FB_SHIFT_HIGH(~0UL, dst_idx);
+- last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
++ first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
++ last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
+
+ if (dst_idx+n <= bits) {
+ // Single word
+@@ -147,8 +147,9 @@ bitfill_unaligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
+ * Aligned pattern invert using 32/64-bit memory accesses
+ */
+ static void
+-bitfill_aligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
+- unsigned n, int bits, u32 bswapmask)
++bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst,
++ int dst_idx, unsigned long pat, unsigned n, int bits,
++ u32 bswapmask)
+ {
+ unsigned long val = pat, dat;
+ unsigned long first, last;
+@@ -156,8 +157,8 @@ bitfill_aligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
+ if (!n)
+ return;
-- dbg("%s: write (%d chars)", __FUNCTION__, count);
-+ dbg("%s: write (%d chars)", __func__, count);
+- first = fb_shifted_pixels_mask_long(dst_idx, bswapmask);
+- last = ~fb_shifted_pixels_mask_long((dst_idx+n) % bits, bswapmask);
++ first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
++ last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
+
+ if (dst_idx+n <= bits) {
+ // Single word
+@@ -217,16 +218,17 @@ bitfill_aligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
+ */
- 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,
+ static void
+-bitfill_unaligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
+- int left, int right, unsigned n, int bits)
++bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst,
++ int dst_idx, unsigned long pat, int left, int right,
++ unsigned n, int bits)
+ {
+ unsigned long first, last, dat;
- memcpy(buffer, buf, count);
+ if (!n)
+ return;
-- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
-+ usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
+- first = FB_SHIFT_HIGH(~0UL, dst_idx);
+- last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
++ first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
++ last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
+
+ if (dst_idx+n <= bits) {
+ // Single word
+@@ -306,7 +308,8 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+ p->fbops->fb_sync(p);
+ if (!left) {
+ u32 bswapmask = fb_compute_bswapmask(p);
+- void (*fill_op32)(unsigned long __iomem *dst, int dst_idx,
++ void (*fill_op32)(struct fb_info *p,
++ unsigned long __iomem *dst, int dst_idx,
+ unsigned long pat, unsigned n, int bits,
+ u32 bswapmask) = NULL;
+
+@@ -325,16 +328,17 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+ while (height--) {
+ dst += dst_idx >> (ffs(bits) - 1);
+ dst_idx &= (bits - 1);
+- fill_op32(dst, dst_idx, pat, width*bpp, bits, bswapmask);
++ fill_op32(p, dst, dst_idx, pat, width*bpp, bits,
++ bswapmask);
+ dst_idx += p->fix.line_length*8;
+ }
+ } else {
+ int right;
+ int r;
+ int rot = (left-dst_idx) % bpp;
+- void (*fill_op)(unsigned long __iomem *dst, int dst_idx,
+- unsigned long pat, int left, int right,
+- unsigned n, int bits) = NULL;
++ void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst,
++ int dst_idx, unsigned long pat, int left,
++ int right, unsigned n, int bits) = NULL;
+
+ /* rotate pattern to correct start position */
+ pat = pat << rot | pat >> (bpp-rot);
+@@ -355,7 +359,7 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+ while (height--) {
+ dst += dst_idx >> (ffs(bits) - 1);
+ dst_idx &= (bits - 1);
+- fill_op(dst, dst_idx, pat, left, right,
++ fill_op(p, dst, dst_idx, pat, left, right,
+ width*bpp, bits);
+ r = (p->fix.line_length*8) % bpp;
+ pat = pat << (bpp-r) | pat >> r;
+diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c
+index f598907..baed57d 100644
+--- a/drivers/video/cfbimgblt.c
++++ b/drivers/video/cfbimgblt.c
+@@ -38,35 +38,31 @@
+ #define DEBUG
- 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;
+ #ifdef DEBUG
+-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__FUNCTION__,## args)
++#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__func__,## args)
+ #else
+ #define DPRINTK(fmt, args...)
+ #endif
-- dbg("%s: %p", __FUNCTION__, urb);
-+ dbg("%s: %p", __func__, urb);
+-static const u32 cfb_tab8[] = {
+-#if defined(__BIG_ENDIAN)
++static const u32 cfb_tab8_be[] = {
+ 0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
+ 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
+ 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
+ 0xffff0000,0xffff00ff,0xffffff00,0xffffffff
+-#elif defined(__LITTLE_ENDIAN)
++};
++
++static const u32 cfb_tab8_le[] = {
+ 0x00000000,0xff000000,0x00ff0000,0xffff0000,
+ 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00,
+ 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff,
+ 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff
+-#else
+-#error FIXME: No endianness??
+-#endif
+ };
- endpoint = usb_pipeendpoint(urb->pipe);
-- port = (struct usb_serial_port *) urb->context;
-+ port = urb->context;
+-static const u32 cfb_tab16[] = {
+-#if defined(__BIG_ENDIAN)
++static const u32 cfb_tab16_be[] = {
+ 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
+-#elif defined(__LITTLE_ENDIAN)
++};
++
++static const u32 cfb_tab16_le[] = {
+ 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
+-#else
+-#error FIXME: No endianness??
+-#endif
+ };
- 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__);
+ static const u32 cfb_tab32[] = {
+@@ -98,7 +94,8 @@ static inline void color_imageblit(const struct fb_image *image,
+ val = 0;
+
+ if (start_index) {
+- u32 start_mask = ~fb_shifted_pixels_mask_u32(start_index, bswapmask);
++ u32 start_mask = ~fb_shifted_pixels_mask_u32(p,
++ start_index, bswapmask);
+ val = FB_READL(dst) & start_mask;
+ shift = start_index;
}
+@@ -108,20 +105,21 @@ static inline void color_imageblit(const struct fb_image *image,
+ color = palette[*src];
+ else
+ color = *src;
+- color <<= FB_LEFT_POS(bpp);
+- val |= FB_SHIFT_HIGH(color, shift ^ bswapmask);
++ color <<= FB_LEFT_POS(p, bpp);
++ val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask);
+ if (shift >= null_bits) {
+ FB_WRITEL(val, dst++);
+
+ val = (shift == null_bits) ? 0 :
+- FB_SHIFT_LOW(color, 32 - shift);
++ FB_SHIFT_LOW(p, color, 32 - shift);
+ }
+ shift += bpp;
+ shift &= (32 - 1);
+ src++;
+ }
+ if (shift) {
+- u32 end_mask = fb_shifted_pixels_mask_u32(shift, bswapmask);
++ u32 end_mask = fb_shifted_pixels_mask_u32(p, shift,
++ bswapmask);
+
+ FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
+ }
+@@ -152,8 +150,8 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
+ u32 bswapmask = fb_compute_bswapmask(p);
+
+ dst2 = (u32 __iomem *) dst1;
+- fgcolor <<= FB_LEFT_POS(bpp);
+- bgcolor <<= FB_LEFT_POS(bpp);
++ fgcolor <<= FB_LEFT_POS(p, bpp);
++ bgcolor <<= FB_LEFT_POS(p, bpp);
+
+ for (i = image->height; i--; ) {
+ shift = val = 0;
+@@ -164,7 +162,8 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
+
+ /* write leading bits */
+ if (start_index) {
+- u32 start_mask = ~fb_shifted_pixels_mask_u32(start_index, bswapmask);
++ u32 start_mask = ~fb_shifted_pixels_mask_u32(p,
++ start_index, bswapmask);
+ val = FB_READL(dst) & start_mask;
+ shift = start_index;
+ }
+@@ -172,13 +171,13 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
+ while (j--) {
+ l--;
+ color = (*s & (1 << l)) ? fgcolor : bgcolor;
+- val |= FB_SHIFT_HIGH(color, shift ^ bswapmask);
++ val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask);
+
+ /* Did the bitshift spill bits to the next long? */
+ if (shift >= null_bits) {
+ FB_WRITEL(val, dst++);
+ val = (shift == null_bits) ? 0 :
+- FB_SHIFT_LOW(color,32 - shift);
++ FB_SHIFT_LOW(p, color, 32 - shift);
+ }
+ shift += bpp;
+ shift &= (32 - 1);
+@@ -187,7 +186,8 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
+
+ /* write trailing bits */
+ if (shift) {
+- u32 end_mask = fb_shifted_pixels_mask_u32(shift, bswapmask);
++ u32 end_mask = fb_shifted_pixels_mask_u32(p, shift,
++ bswapmask);
+
+ FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
+ }
+@@ -223,13 +223,13 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info *
+ u32 __iomem *dst;
+ const u32 *tab = NULL;
+ int i, j, k;
+-
++
+ switch (bpp) {
+ case 8:
+- tab = cfb_tab8;
++ tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le;
+ break;
+ case 16:
+- tab = cfb_tab16;
++ tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;
+ break;
+ case 32:
+ default:
+diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
+index fdc9f43..0db0fec 100644
+--- a/drivers/video/cg14.c
++++ b/drivers/video/cg14.c
+@@ -556,7 +556,7 @@ static int __devinit cg14_probe(struct of_device *op, const struct of_device_id
+
+ dev_set_drvdata(&op->dev, info);
+
+- printk("%s: cgfourteen at %lx:%lx, %dMB\n",
++ printk(KERN_INFO "%s: cgfourteen at %lx:%lx, %dMB\n",
+ dp->full_name,
+ par->iospace, par->physbase,
+ par->ramsize >> 20);
+@@ -605,7 +605,7 @@ static struct of_platform_driver cg14_driver = {
+ .remove = __devexit_p(cg14_remove),
+ };
- /* Resubmit urb so we continue receiving */
-@@ -447,19 +487,19 @@ static void sierra_instat_callback(struct urb *urb)
+-int __init cg14_init(void)
++static int __init cg14_init(void)
{
- 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;
+ if (fb_get_options("cg14fb", NULL))
+ return -ENODEV;
+@@ -613,7 +613,7 @@ int __init cg14_init(void)
+ return of_register_driver(&cg14_driver, &of_bus_type);
+ }
-- 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);
+-void __exit cg14_exit(void)
++static void __exit cg14_exit(void)
+ {
+ of_unregister_driver(&cg14_driver);
+ }
+diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
+index a5c7fb3..010ea53 100644
+--- a/drivers/video/cg3.c
++++ b/drivers/video/cg3.c
+@@ -419,7 +419,7 @@ static int __devinit cg3_probe(struct of_device *op,
- if (status == 0) {
- struct usb_ctrlrequest *req_pkt =
- (struct usb_ctrlrequest *)urb->transfer_buffer;
+ dev_set_drvdata(&op->dev, info);
- 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));
+- printk("%s: cg3 at %lx:%lx\n",
++ printk(KERN_INFO "%s: cg3 at %lx:%lx\n",
+ dp->full_name, par->which_io, par->physbase);
-- dbg("%s: signal x%x", __FUNCTION__, signals);
-+ dbg("%s: signal x%x", __func__, signals);
+ return 0;
+diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
+index 549891d..fc90db6 100644
+--- a/drivers/video/cg6.c
++++ b/drivers/video/cg6.c
+@@ -781,7 +781,7 @@ static int __devinit cg6_probe(struct of_device *op,
- 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);
+ dev_set_drvdata(&op->dev, info);
- /* 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);
+- printk("%s: CGsix [%s] at %lx:%lx\n",
++ printk(KERN_INFO "%s: CGsix [%s] at %lx:%lx\n",
+ dp->full_name, info->fix.id,
+ par->which_io, par->physbase);
+
+diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
+index f7e2d5a..35ac9d9 100644
+--- a/drivers/video/cirrusfb.c
++++ b/drivers/video/cirrusfb.c
+@@ -81,7 +81,7 @@
+ /* debug output */
+ #ifdef CIRRUSFB_DEBUG
+ #define DPRINTK(fmt, args...) \
+- printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
++ printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
+ #else
+ #define DPRINTK(fmt, args...)
+ #endif
+@@ -91,7 +91,7 @@
+ #define assert(expr) \
+ if (!(expr)) { \
+ printk("Assertion failed! %s,%s,%s,line=%d\n", \
+- #expr, __FILE__, __FUNCTION__, __LINE__); \
++ #expr, __FILE__, __func__, __LINE__); \
}
- }
+ #else
+ #define assert(expr)
+@@ -3117,7 +3117,7 @@ static void bestclock(long freq, long *best, long *nom,
+ }
+ }
+ }
+- d = ((143181 * n) + f - 1) / f;
++ d = DIV_ROUND_UP(143181 * n, f);
+ if ((d >= 7) && (d <= 63)) {
+ if (d > 31)
+ d = (d / 2) * 2;
+diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c
+index 17b5267..9f8a389 100644
+--- a/drivers/video/clps711xfb.c
++++ b/drivers/video/clps711xfb.c
+@@ -381,7 +381,7 @@ int __init clps711xfb_init(void)
+
+ /* Register the /proc entries. */
+ clps7111fb_backlight_proc_entry = create_proc_entry("backlight", 0444,
+- &proc_root);
++ NULL);
+ if (clps7111fb_backlight_proc_entry == NULL) {
+ printk("Couldn't create the /proc entry for the backlight.\n");
+ return -EINVAL;
+diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
+index 0222824..ad31983 100644
+--- a/drivers/video/console/fbcon.c
++++ b/drivers/video/console/fbcon.c
+@@ -92,7 +92,7 @@
+ #include "fbcon.h"
+
+ #ifdef FBCONDEBUG
+-# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
++# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
+ #else
+ # define DPRINTK(fmt, args...)
+ #endif
+@@ -620,8 +620,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
+ if (fb_get_color_depth(&info->var, &info->fix) == 1)
+ erase &= ~0x400;
+ logo_height = fb_prepare_logo(info, ops->rotate);
+- logo_lines = (logo_height + vc->vc_font.height - 1) /
+- vc->vc_font.height;
++ logo_lines = DIV_ROUND_UP(logo_height, vc->vc_font.height);
+ q = (unsigned short *) (vc->vc_origin +
+ vc->vc_size_row * rows);
+ step = logo_lines * cols;
+@@ -1882,7 +1881,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
+ scr_memsetw((unsigned short *) (vc->vc_origin +
+ vc->vc_size_row *
+ (b - count)),
+- vc->vc_video_erase_char,
++ vc->vc_scrl_erase_char,
+ vc->vc_size_row * count);
+ return 1;
+ break;
+@@ -1954,7 +1953,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
+ scr_memsetw((unsigned short *) (vc->vc_origin +
+ vc->vc_size_row *
+ (b - count)),
+- vc->vc_video_erase_char,
++ vc->vc_scrl_erase_char,
+ vc->vc_size_row * count);
+ return 1;
+ }
+@@ -1973,7 +1972,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
+ scr_memsetw((unsigned short *) (vc->vc_origin +
+ vc->vc_size_row *
+ t),
+- vc->vc_video_erase_char,
++ vc->vc_scrl_erase_char,
+ vc->vc_size_row * count);
+ return 1;
+ break;
+@@ -2043,7 +2042,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
+ scr_memsetw((unsigned short *) (vc->vc_origin +
+ vc->vc_size_row *
+ t),
+- vc->vc_video_erase_char,
++ vc->vc_scrl_erase_char,
+ vc->vc_size_row * count);
+ return 1;
+ }
+diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
+index 3706307..0135e03 100644
+--- a/drivers/video/console/fbcon.h
++++ b/drivers/video/console/fbcon.h
+@@ -104,10 +104,14 @@ struct fbcon_ops {
+ #define attr_blink(s) \
+ ((s) & 0x8000)
+
+-#define mono_col(info) \
+- (~(0xfff << (max((info)->var.green.length, \
+- max((info)->var.red.length, \
+- (info)->var.blue.length)))) & 0xff)
++
++static inline int mono_col(const struct fb_info *info)
++{
++ __u32 max_len;
++ max_len = max(info->var.green.length, info->var.red.length);
++ max_len = max(info->var.blue.length, max_len);
++ return ~(0xfff << (max_len & 0xff));
++}
-@@ -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;
+ static inline int attr_col_ec(int shift, struct vc_data *vc,
+ struct fb_info *info, int is_fg)
+diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
+index bd8d995..38a296b 100644
+--- a/drivers/video/console/mdacon.c
++++ b/drivers/video/console/mdacon.c
+@@ -531,7 +531,7 @@ static void mdacon_cursor(struct vc_data *c, int mode)
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
+ {
+- u16 eattr = mda_convert_attr(c->vc_video_erase_char);
++ u16 eattr = mda_convert_attr(c->vc_scrl_erase_char);
- /* 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__);
+ if (!lines)
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);
+diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
+index 67a682d..a11cc2f 100644
+--- a/drivers/video/console/sticon.c
++++ b/drivers/video/console/sticon.c
+@@ -170,12 +170,12 @@ static int sticon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
+ switch (dir) {
+ case SM_UP:
+ sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols);
+- sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_video_erase_char);
++ sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_scrl_erase_char);
+ break;
+
+ case SM_DOWN:
+ sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols);
+- sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_video_erase_char);
++ sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_scrl_erase_char);
+ break;
+ }
- /*
- * 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;
+diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
+index 6df29a6..bd1f57b 100644
+--- a/drivers/video/console/vgacon.c
++++ b/drivers/video/console/vgacon.c
+@@ -1350,7 +1350,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
+ } else
+ c->vc_origin += delta;
+ scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size -
+- delta), c->vc_video_erase_char,
++ delta), c->vc_scrl_erase_char,
+ delta);
+ } else {
+ if (oldo - delta < vga_vram_base) {
+@@ -1363,7 +1363,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
+ } else
+ c->vc_origin -= delta;
+ c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
+- scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
++ scr_memsetw((u16 *) (c->vc_origin), c->vc_scrl_erase_char,
+ delta);
+ }
+ c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
+diff --git a/drivers/video/fb_draw.h b/drivers/video/fb_draw.h
+index a2a0618..1db6221 100644
+--- a/drivers/video/fb_draw.h
++++ b/drivers/video/fb_draw.h
+@@ -94,41 +94,44 @@ static inline unsigned long fb_rev_pixels_in_long(unsigned long val,
+ return val;
}
-@@ -540,7 +582,7 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
- portdata = usb_get_serial_port_data(port);
+-static inline u32 fb_shifted_pixels_mask_u32(u32 index, u32 bswapmask)
++static inline u32 fb_shifted_pixels_mask_u32(struct fb_info *p, u32 index,
++ u32 bswapmask)
+ {
+ u32 mask;
+
+ if (!bswapmask) {
+- mask = FB_SHIFT_HIGH(~(u32)0, index);
++ mask = FB_SHIFT_HIGH(p, ~(u32)0, index);
+ } else {
+- mask = 0xff << FB_LEFT_POS(8);
+- mask = FB_SHIFT_LOW(mask, index & (bswapmask)) & mask;
+- mask = FB_SHIFT_HIGH(mask, index & ~(bswapmask));
++ mask = 0xff << FB_LEFT_POS(p, 8);
++ mask = FB_SHIFT_LOW(p, mask, index & (bswapmask)) & mask;
++ mask = FB_SHIFT_HIGH(p, mask, index & ~(bswapmask));
+ #if defined(__i386__) || defined(__x86_64__)
+ /* Shift argument is limited to 0 - 31 on x86 based CPU's */
+ if(index + bswapmask < 32)
+ #endif
+- mask |= FB_SHIFT_HIGH(~(u32)0,
++ mask |= FB_SHIFT_HIGH(p, ~(u32)0,
+ (index + bswapmask) & ~(bswapmask));
+ }
+ return mask;
+ }
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+-static inline unsigned long fb_shifted_pixels_mask_long(u32 index, u32 bswapmask)
++static inline unsigned long fb_shifted_pixels_mask_long(struct fb_info *p,
++ u32 index,
++ u32 bswapmask)
+ {
+ unsigned long mask;
+
+ if (!bswapmask) {
+- mask = FB_SHIFT_HIGH(~0UL, index);
++ mask = FB_SHIFT_HIGH(p, ~0UL, index);
+ } else {
+- mask = 0xff << FB_LEFT_POS(8);
+- mask = FB_SHIFT_LOW(mask, index & (bswapmask)) & mask;
+- mask = FB_SHIFT_HIGH(mask, index & ~(bswapmask));
++ mask = 0xff << FB_LEFT_POS(p, 8);
++ mask = FB_SHIFT_LOW(p, mask, index & (bswapmask)) & mask;
++ mask = FB_SHIFT_HIGH(p, mask, index & ~(bswapmask));
+ #if defined(__i386__) || defined(__x86_64__)
+ /* Shift argument is limited to 0 - 31 on x86 based CPU's */
+ if(index + bswapmask < BITS_PER_LONG)
+ #endif
+- mask |= FB_SHIFT_HIGH(~0UL,
++ mask |= FB_SHIFT_HIGH(p, ~0UL,
+ (index + bswapmask) & ~(bswapmask));
+ }
+ return mask;
+@@ -158,8 +161,8 @@ static inline unsigned long fb_rev_pixels_in_long(unsigned long val,
+ return val;
+ }
- /* 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;
+-#define fb_shifted_pixels_mask_u32(i, b) FB_SHIFT_HIGH(~(u32)0, (i))
+-#define fb_shifted_pixels_mask_long(i, b) FB_SHIFT_HIGH(~0UL, (i))
++#define fb_shifted_pixels_mask_u32(p, i, b) FB_SHIFT_HIGH((p), ~(u32)0, (i))
++#define fb_shifted_pixels_mask_long(p, i, b) FB_SHIFT_HIGH((p), ~0UL, (i))
+ #define fb_compute_bswapmask(...) 0
+
+ #endif /* CONFIG_FB_CFB_REV_PIXELS_IN_BYTE */
+diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
+index 01072f4..776f7fc 100644
+--- a/drivers/video/fbmem.c
++++ b/drivers/video/fbmem.c
+@@ -26,6 +26,7 @@
+ #include <linux/init.h>
+ #include <linux/linux_logo.h>
+ #include <linux/proc_fs.h>
++#include <linux/seq_file.h>
+ #include <linux/console.h>
+ #ifdef CONFIG_KMOD
+ #include <linux/kmod.h>
+@@ -632,27 +633,51 @@ int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; }
+ int fb_show_logo(struct fb_info *info, int rotate) { return 0; }
+ #endif /* CONFIG_LOGO */
+
+-static int fbmem_read_proc(char *buf, char **start, off_t offset,
+- int len, int *eof, void *private)
++static void *fb_seq_start(struct seq_file *m, loff_t *pos)
+ {
+- struct fb_info **fi;
+- int clen;
+-
+- clen = 0;
+- for (fi = registered_fb; fi < ®istered_fb[FB_MAX] && clen < 4000;
+- fi++)
+- if (*fi)
+- clen += sprintf(buf + clen, "%d %s\n",
+- (*fi)->node,
+- (*fi)->fix.id);
+- *start = buf + offset;
+- if (clen > offset)
+- clen -= offset;
+- else
+- clen = 0;
+- return clen < len ? clen : len;
++ return (*pos < FB_MAX) ? pos : NULL;
++}
++
++static void *fb_seq_next(struct seq_file *m, void *v, loff_t *pos)
++{
++ (*pos)++;
++ return (*pos < FB_MAX) ? pos : NULL;
++}
++
++static void fb_seq_stop(struct seq_file *m, void *v)
++{
++}
++
++static int fb_seq_show(struct seq_file *m, void *v)
++{
++ int i = *(loff_t *)v;
++ struct fb_info *fi = registered_fb[i];
++
++ if (fi)
++ seq_printf(m, "%d %s\n", fi->node, fi->fix.id);
++ return 0;
++}
++
++static const struct seq_operations proc_fb_seq_ops = {
++ .start = fb_seq_start,
++ .next = fb_seq_next,
++ .stop = fb_seq_stop,
++ .show = fb_seq_show,
++};
++
++static int proc_fb_open(struct inode *inode, struct file *file)
++{
++ return seq_open(file, &proc_fb_seq_ops);
+ }
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
- portdata = usb_get_serial_port_data(port);
++static const struct file_operations fb_proc_fops = {
++ .owner = THIS_MODULE,
++ .open = proc_fb_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = seq_release,
++};
++
+ static ssize_t
+ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+ {
+@@ -1057,7 +1082,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ case FBIOPUT_CON2FBMAP:
+ if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
+ return - EFAULT;
+- if (con2fb.console < 0 || con2fb.console > MAX_NR_CONSOLES)
++ if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
+ return -EINVAL;
+ if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
+ return -EINVAL;
+@@ -1352,6 +1377,32 @@ static const struct file_operations fb_fops = {
- portdata->rts_state = 0;
-@@ -620,7 +662,7 @@ static int sierra_startup(struct usb_serial *serial)
- int i;
- int j;
+ struct class *fb_class;
+ EXPORT_SYMBOL(fb_class);
++
++static int fb_check_foreignness(struct fb_info *fi)
++{
++ const bool foreign_endian = fi->flags & FBINFO_FOREIGN_ENDIAN;
++
++ fi->flags &= ~FBINFO_FOREIGN_ENDIAN;
++
++#ifdef __BIG_ENDIAN
++ fi->flags |= foreign_endian ? 0 : FBINFO_BE_MATH;
++#else
++ fi->flags |= foreign_endian ? FBINFO_BE_MATH : 0;
++#endif /* __BIG_ENDIAN */
++
++ if (fi->flags & FBINFO_BE_MATH && !fb_be_math(fi)) {
++ pr_err("%s: enable CONFIG_FB_BIG_ENDIAN to "
++ "support this framebuffer\n", fi->fix.id);
++ return -ENOSYS;
++ } else if (!(fi->flags & FBINFO_BE_MATH) && fb_be_math(fi)) {
++ pr_err("%s: enable CONFIG_FB_LITTLE_ENDIAN to "
++ "support this framebuffer\n", fi->fix.id);
++ return -ENOSYS;
++ }
++
++ return 0;
++}
++
+ /**
+ * register_framebuffer - registers a frame buffer device
+ * @fb_info: frame buffer info structure
+@@ -1371,6 +1422,10 @@ register_framebuffer(struct fb_info *fb_info)
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ if (num_registered_fb == FB_MAX)
+ return -ENXIO;
++
++ if (fb_check_foreignness(fb_info))
++ return -ENOSYS;
++
+ num_registered_fb++;
+ for (i = 0 ; i < FB_MAX; i++)
+ if (!registered_fb[i])
+@@ -1503,7 +1558,7 @@ void fb_set_suspend(struct fb_info *info, int state)
+ static int __init
+ fbmem_init(void)
+ {
+- create_proc_read_entry("fb", 0, NULL, fbmem_read_proc, NULL);
++ proc_create("fb", 0, NULL, &fb_proc_fops);
- /* 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;
+ if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
+ printk("unable to get major %d for fb devs\n", FB_MAJOR);
+diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
+index d7e2488..93dca3e 100644
+--- a/drivers/video/ffb.c
++++ b/drivers/video/ffb.c
+@@ -32,7 +32,6 @@
+ static int ffb_setcolreg(unsigned, unsigned, unsigned, unsigned,
+ unsigned, struct fb_info *);
+ static int ffb_blank(int, struct fb_info *);
+-static void ffb_init_fix(struct fb_info *);
+
+ static void ffb_imageblit(struct fb_info *, const struct fb_image *);
+ static void ffb_fillrect(struct fb_info *, const struct fb_fillrect *);
+@@ -1001,7 +1000,7 @@ static int __devinit ffb_probe(struct of_device *op,
+
+ dev_set_drvdata(&op->dev, info);
+
+- printk("%s: %s at %016lx, type %d, "
++ printk(KERN_INFO "%s: %s at %016lx, type %d, "
+ "DAC pnum[%x] rev[%d] manuf_rev[%d]\n",
+ dp->full_name,
+ ((par->flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),
+@@ -1062,7 +1061,7 @@ static struct of_platform_driver ffb_driver = {
+ .remove = __devexit_p(ffb_remove),
+ };
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+-int __init ffb_init(void)
++static int __init ffb_init(void)
+ {
+ if (fb_get_options("ffb", NULL))
+ return -ENODEV;
+@@ -1070,7 +1069,7 @@ int __init ffb_init(void)
+ return of_register_driver(&ffb_driver, &of_bus_type);
+ }
- 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
+-void __exit ffb_exit(void)
++static void __exit ffb_exit(void)
+ {
+ of_unregister_driver(&ffb_driver);
+ }
+diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
new file mode 100644
-index 0000000..2282d62
+index 0000000..b50bb03
--- /dev/null
-+++ b/drivers/usb/serial/spcp8x5.c
-@@ -0,0 +1,1072 @@
++++ b/drivers/video/fsl-diu-fb.c
+@@ -0,0 +1,1721 @@
+/*
-+ * spcp8x5 USB to serial adaptor driver
++ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
-+ * Copyright (C) 2006 Linxb (xubin.lin at worldplus.com.cn)
-+ * Copyright (C) 2006 S1 Corp.
++ * Freescale DIU Frame Buffer device driver
+ *
-+ * Original driver for 2.6.10 pl2303 driver by
-+ * Greg Kroah-Hartman (greg at kroah.com)
-+ * Changes for 2.6.20 by Harald Klein <hari at vt100.at>
++ * Authors: Hongjun Chen <hong-jun.chen at freescale.com>
++ * Paul Widmer <paul.widmer at freescale.com>
++ * Srikanth Srinivasan <srikanth.srinivasan at freescale.com>
++ * York Sun <yorksun at freescale.com>
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
++ * Based on imxfb.c Copyright (C) 2004 S.Hauer, 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 the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
+ *
+ */
++
++#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
-+#include <linux/init.h>
++#include <linux/string.h>
+#include <linux/slab.h>
-+#include <linux/tty.h>
-+#include <linux/tty_driver.h>
-+#include <linux/tty_flip.h>
-+#include <linux/module.h>
-+#include <linux/spinlock.h>
-+#include <linux/usb.h>
-+#include <linux/usb/serial.h>
++#include <linux/fb.h>
++#include <linux/init.h>
++#include <linux/dma-mapping.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/clk.h>
++#include <linux/uaccess.h>
++#include <linux/vmalloc.h>
+
++#include <linux/of_platform.h>
+
-+/* Version Information */
-+#define DRIVER_VERSION "v0.04"
-+#define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver"
++#include <sysdev/fsl_soc.h>
++#include "fsl-diu-fb.h"
+
-+static int debug;
++/*
++ * These parameters give default parameters
++ * for video output 1024x768,
++ * FIXME - change timing to proper amounts
++ * hsync 31.5kHz, vsync 60Hz
++ */
++static struct fb_videomode __devinitdata fsl_diu_default_mode = {
++ .refresh = 60,
++ .xres = 1024,
++ .yres = 768,
++ .pixclock = 15385,
++ .left_margin = 160,
++ .right_margin = 24,
++ .upper_margin = 29,
++ .lower_margin = 3,
++ .hsync_len = 136,
++ .vsync_len = 6,
++ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++ .vmode = FB_VMODE_NONINTERLACED
++};
+
-+#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 fb_videomode __devinitdata fsl_diu_mode_db[] = {
++ {
++ .name = "1024x768-60",
++ .refresh = 60,
++ .xres = 1024,
++ .yres = 768,
++ .pixclock = 15385,
++ .left_margin = 160,
++ .right_margin = 24,
++ .upper_margin = 29,
++ .lower_margin = 3,
++ .hsync_len = 136,
++ .vsync_len = 6,
++ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++ .vmode = FB_VMODE_NONINTERLACED
++ },
++ {
++ .name = "1024x768-70",
++ .refresh = 70,
++ .xres = 1024,
++ .yres = 768,
++ .pixclock = 16886,
++ .left_margin = 3,
++ .right_margin = 3,
++ .upper_margin = 2,
++ .lower_margin = 2,
++ .hsync_len = 40,
++ .vsync_len = 18,
++ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++ .vmode = FB_VMODE_NONINTERLACED
++ },
++ {
++ .name = "1024x768-75",
++ .refresh = 75,
++ .xres = 1024,
++ .yres = 768,
++ .pixclock = 15009,
++ .left_margin = 3,
++ .right_margin = 3,
++ .upper_margin = 2,
++ .lower_margin = 2,
++ .hsync_len = 80,
++ .vsync_len = 32,
++ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++ .vmode = FB_VMODE_NONINTERLACED
++ },
++ {
++ .name = "1280x1024-60",
++ .refresh = 60,
++ .xres = 1280,
++ .yres = 1024,
++ .pixclock = 9375,
++ .left_margin = 38,
++ .right_margin = 128,
++ .upper_margin = 2,
++ .lower_margin = 7,
++ .hsync_len = 216,
++ .vsync_len = 37,
++ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++ .vmode = FB_VMODE_NONINTERLACED
++ },
++ {
++ .name = "1280x1024-70",
++ .refresh = 70,
++ .xres = 1280,
++ .yres = 1024,
++ .pixclock = 9380,
++ .left_margin = 6,
++ .right_margin = 6,
++ .upper_margin = 4,
++ .lower_margin = 4,
++ .hsync_len = 60,
++ .vsync_len = 94,
++ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++ .vmode = FB_VMODE_NONINTERLACED
++ },
++ {
++ .name = "1280x1024-75",
++ .refresh = 75,
++ .xres = 1280,
++ .yres = 1024,
++ .pixclock = 9380,
++ .left_margin = 6,
++ .right_margin = 6,
++ .upper_margin = 4,
++ .lower_margin = 4,
++ .hsync_len = 60,
++ .vsync_len = 15,
++ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++ .vmode = FB_VMODE_NONINTERLACED
++ },
++ {
++ .name = "320x240", /* for AOI only */
++ .refresh = 60,
++ .xres = 320,
++ .yres = 240,
++ .pixclock = 15385,
++ .left_margin = 0,
++ .right_margin = 0,
++ .upper_margin = 0,
++ .lower_margin = 0,
++ .hsync_len = 0,
++ .vsync_len = 0,
++ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++ .vmode = FB_VMODE_NONINTERLACED
++ },
++ {
++ .name = "1280x480-60",
++ .refresh = 60,
++ .xres = 1280,
++ .yres = 480,
++ .pixclock = 18939,
++ .left_margin = 353,
++ .right_margin = 47,
++ .upper_margin = 39,
++ .lower_margin = 4,
++ .hsync_len = 8,
++ .vsync_len = 2,
++ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++ .vmode = FB_VMODE_NONINTERLACED
++ },
++};
+
-+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 */
++static char *fb_mode = "1024x768-32 at 60";
++static unsigned long default_bpp = 32;
++static int monitor_port;
++
++#if defined(CONFIG_NOT_COHERENT_CACHE)
++static u8 *coherence_data;
++static size_t coherence_data_size;
++static unsigned int d_cache_line_size;
++#endif
++
++static DEFINE_SPINLOCK(diu_lock);
++
++struct fsl_diu_data {
++ struct fb_info *fsl_diu_info[FSL_AOI_NUM - 1];
++ /*FSL_AOI_NUM has one dummy AOI */
++ struct device_attribute dev_attr;
++ struct diu_ad *dummy_ad;
++ void *dummy_aoi_virt;
++ unsigned int irq;
++ int fb_enabled;
++ int monitor_port;
+};
-+MODULE_DEVICE_TABLE(usb, id_table);
+
-+struct spcp8x5_usb_ctrl_arg {
-+ u8 type;
-+ u8 cmd;
-+ u8 cmd_type;
-+ u16 value;
-+ u16 index;
-+ u16 length;
++struct mfb_info {
++ int index;
++ int type;
++ char *id;
++ int registered;
++ int blank;
++ unsigned long pseudo_palette[16];
++ struct diu_ad *ad;
++ int cursor_reset;
++ unsigned char g_alpha;
++ unsigned int count;
++ int x_aoi_d; /* aoi display x offset to physical screen */
++ int y_aoi_d; /* aoi display y offset to physical screen */
++ struct fsl_diu_data *parent;
+};
+
-+/* wait 30s before close */
-+#define SPCP8x5_CLOSING_WAIT (30*HZ)
+
-+#define SPCP8x5_BUF_SIZE 1024
++static struct mfb_info mfb_template[] = {
++ { /* AOI 0 for plane 0 */
++ .index = 0,
++ .type = MFB_TYPE_OUTPUT,
++ .id = "Panel0",
++ .registered = 0,
++ .count = 0,
++ .x_aoi_d = 0,
++ .y_aoi_d = 0,
++ },
++ { /* AOI 0 for plane 1 */
++ .index = 1,
++ .type = MFB_TYPE_OUTPUT,
++ .id = "Panel1 AOI0",
++ .registered = 0,
++ .g_alpha = 0xff,
++ .count = 0,
++ .x_aoi_d = 0,
++ .y_aoi_d = 0,
++ },
++ { /* AOI 1 for plane 1 */
++ .index = 2,
++ .type = MFB_TYPE_OUTPUT,
++ .id = "Panel1 AOI1",
++ .registered = 0,
++ .g_alpha = 0xff,
++ .count = 0,
++ .x_aoi_d = 0,
++ .y_aoi_d = 480,
++ },
++ { /* AOI 0 for plane 2 */
++ .index = 3,
++ .type = MFB_TYPE_OUTPUT,
++ .id = "Panel2 AOI0",
++ .registered = 0,
++ .g_alpha = 0xff,
++ .count = 0,
++ .x_aoi_d = 640,
++ .y_aoi_d = 0,
++ },
++ { /* AOI 1 for plane 2 */
++ .index = 4,
++ .type = MFB_TYPE_OUTPUT,
++ .id = "Panel2 AOI1",
++ .registered = 0,
++ .g_alpha = 0xff,
++ .count = 0,
++ .x_aoi_d = 640,
++ .y_aoi_d = 480,
++ },
++};
+
++static struct diu_hw dr = {
++ .mode = MFB_MODE1,
++ .reg_lock = __SPIN_LOCK_UNLOCKED(diu_hw.reg_lock),
++};
+
-+/* spcp8x5 spec register define */
-+#define MCR_CONTROL_LINE_RTS 0x02
-+#define MCR_CONTROL_LINE_DTR 0x01
-+#define MCR_DTR 0x01
-+#define MCR_RTS 0x02
++static struct diu_pool pool;
+
-+#define MSR_STATUS_LINE_DCD 0x80
-+#define MSR_STATUS_LINE_RI 0x40
-+#define MSR_STATUS_LINE_DSR 0x20
-+#define MSR_STATUS_LINE_CTS 0x10
++/* To allocate memory for framebuffer. First try __get_free_pages(). If it
++ * fails, try rh_alloc. The reason is __get_free_pages() cannot allocate
++ * very large memory (more than 4MB). We don't want to allocate all memory
++ * in rheap since small memory allocation/deallocation will fragment the
++ * rheap and make the furture large allocation fail.
++ */
+
-+/* verdor command here , we should define myself */
-+#define SET_DEFAULT 0x40
-+#define SET_DEFAULT_TYPE 0x20
++void *fsl_diu_alloc(unsigned long size, phys_addr_t *phys)
++{
++ void *virt;
+
-+#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
++ pr_debug("size=%lu\n", size);
+
-+#define GET_UART_STATUS_TYPE 0xc0
-+#define GET_UART_STATUS 0x22
-+#define GET_UART_STATUS_MSR 0x06
++ virt = (void *)__get_free_pages(GFP_DMA | __GFP_ZERO, get_order(size));
++ if (virt) {
++ *phys = virt_to_phys(virt);
++ pr_debug("virt %p, phys=%llx\n", virt, (uint64_t) *phys);
++ return virt;
++ }
++ if (!diu_ops.diu_mem) {
++ printk(KERN_INFO "%s: no diu_mem."
++ " To reserve more memory, put 'diufb=15M' "
++ "in the command line\n", __func__);
++ return NULL;
++ }
+
-+#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
++ virt = (void *)rh_alloc(&diu_ops.diu_rh_info, size, "DIU");
++ if (virt) {
++ *phys = virt_to_bus(virt);
++ memset(virt, 0, size);
++ }
+
-+#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
++ pr_debug("rh virt=%p phys=%lx\n", virt, *phys);
+
-+#define SET_FLOWCTL_CHAR 0x40
-+#define SET_FLOWCTL_CHAR_TYPE 0x25
++ return virt;
++}
+
-+#define GET_VERSION 0xc0
-+#define GET_VERSION_TYPE 0x26
++void fsl_diu_free(void *p, unsigned long size)
++{
++ pr_debug("p=%p size=%lu\n", p, size);
+
-+#define SET_REGISTER 0x40
-+#define SET_REGISTER_TYPE 0x27
++ if (!p)
++ return;
+
-+#define GET_REGISTER 0xc0
-+#define GET_REGISTER_TYPE 0x28
++ if ((p >= diu_ops.diu_mem) &&
++ (p < (diu_ops.diu_mem + diu_ops.diu_size))) {
++ pr_debug("rh\n");
++ rh_free(&diu_ops.diu_rh_info, (unsigned long) p);
++ } else {
++ pr_debug("dma\n");
++ free_pages((unsigned long)p, get_order(size));
++ }
++}
+
-+#define SET_RAM 0x40
-+#define SET_RAM_TYPE 0x31
++static int fsl_diu_enable_panel(struct fb_info *info)
++{
++ struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
++ struct diu *hw = dr.diu_reg;
++ struct diu_ad *ad = mfbi->ad;
++ struct fsl_diu_data *machine_data = mfbi->parent;
++ int res = 0;
+
-+#define GET_RAM 0xc0
-+#define GET_RAM_TYPE 0x32
++ pr_debug("enable_panel index %d\n", mfbi->index);
++ if (mfbi->type != MFB_TYPE_OFF) {
++ switch (mfbi->index) {
++ case 0: /* plane 0 */
++ if (hw->desc[0] != ad->paddr)
++ out_be32(&hw->desc[0], ad->paddr);
++ break;
++ case 1: /* plane 1 AOI 0 */
++ cmfbi = machine_data->fsl_diu_info[2]->par;
++ if (hw->desc[1] != ad->paddr) { /* AOI0 closed */
++ if (cmfbi->count > 0) /* AOI1 open */
++ ad->next_ad =
++ cpu_to_le32(cmfbi->ad->paddr);
++ else
++ ad->next_ad = 0;
++ out_be32(&hw->desc[1], ad->paddr);
++ }
++ break;
++ case 3: /* plane 2 AOI 0 */
++ cmfbi = machine_data->fsl_diu_info[4]->par;
++ if (hw->desc[2] != ad->paddr) { /* AOI0 closed */
++ if (cmfbi->count > 0) /* AOI1 open */
++ ad->next_ad =
++ cpu_to_le32(cmfbi->ad->paddr);
++ else
++ ad->next_ad = 0;
++ out_be32(&hw->desc[2], ad->paddr);
++ }
++ break;
++ case 2: /* plane 1 AOI 1 */
++ pmfbi = machine_data->fsl_diu_info[1]->par;
++ ad->next_ad = 0;
++ if (hw->desc[1] == machine_data->dummy_ad->paddr)
++ out_be32(&hw->desc[1], ad->paddr);
++ else /* AOI0 open */
++ pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
++ break;
++ case 4: /* plane 2 AOI 1 */
++ pmfbi = machine_data->fsl_diu_info[3]->par;
++ ad->next_ad = 0;
++ if (hw->desc[2] == machine_data->dummy_ad->paddr)
++ out_be32(&hw->desc[2], ad->paddr);
++ else /* AOI0 was open */
++ pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
++ break;
++ default:
++ res = -EINVAL;
++ break;
++ }
++ } else
++ res = -EINVAL;
++ return res;
++}
+
-+/* 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
++static int fsl_diu_disable_panel(struct fb_info *info)
++{
++ struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
++ struct diu *hw = dr.diu_reg;
++ struct diu_ad *ad = mfbi->ad;
++ struct fsl_diu_data *machine_data = mfbi->parent;
++ int res = 0;
+
-+enum spcp8x5_type {
-+ SPCP825_007_TYPE,
-+ SPCP825_008_TYPE,
-+ SPCP825_PHILIP_TYPE,
-+ SPCP825_INTERMATIC_TYPE,
-+ SPCP835_TYPE,
-+};
++ switch (mfbi->index) {
++ case 0: /* plane 0 */
++ if (hw->desc[0] != machine_data->dummy_ad->paddr)
++ out_be32(&hw->desc[0],
++ machine_data->dummy_ad->paddr);
++ break;
++ case 1: /* plane 1 AOI 0 */
++ cmfbi = machine_data->fsl_diu_info[2]->par;
++ if (cmfbi->count > 0) /* AOI1 is open */
++ out_be32(&hw->desc[1], cmfbi->ad->paddr);
++ /* move AOI1 to the first */
++ else /* AOI1 was closed */
++ out_be32(&hw->desc[1],
++ machine_data->dummy_ad->paddr);
++ /* close AOI 0 */
++ break;
++ case 3: /* plane 2 AOI 0 */
++ cmfbi = machine_data->fsl_diu_info[4]->par;
++ if (cmfbi->count > 0) /* AOI1 is open */
++ out_be32(&hw->desc[2], cmfbi->ad->paddr);
++ /* move AOI1 to the first */
++ else /* AOI1 was closed */
++ out_be32(&hw->desc[2],
++ machine_data->dummy_ad->paddr);
++ /* close AOI 0 */
++ break;
++ case 2: /* plane 1 AOI 1 */
++ pmfbi = machine_data->fsl_diu_info[1]->par;
++ if (hw->desc[1] != ad->paddr) {
++ /* AOI1 is not the first in the chain */
++ if (pmfbi->count > 0)
++ /* AOI0 is open, must be the first */
++ pmfbi->ad->next_ad = 0;
++ } else /* AOI1 is the first in the chain */
++ out_be32(&hw->desc[1], machine_data->dummy_ad->paddr);
++ /* close AOI 1 */
++ break;
++ case 4: /* plane 2 AOI 1 */
++ pmfbi = machine_data->fsl_diu_info[3]->par;
++ if (hw->desc[2] != ad->paddr) {
++ /* AOI1 is not the first in the chain */
++ if (pmfbi->count > 0)
++ /* AOI0 is open, must be the first */
++ pmfbi->ad->next_ad = 0;
++ } else /* AOI1 is the first in the chain */
++ out_be32(&hw->desc[2], machine_data->dummy_ad->paddr);
++ /* close AOI 1 */
++ break;
++ default:
++ res = -EINVAL;
++ break;
++ }
+
-+/* 1st in 1st out buffer 4 driver */
-+struct ringbuf {
-+ unsigned int buf_size;
-+ char *buf_buf;
-+ char *buf_get;
-+ char *buf_put;
-+};
++ return res;
++}
+
-+/* alloc the ring buf and alloc the buffer itself */
-+static inline struct ringbuf *alloc_ringbuf(unsigned int size)
++static void enable_lcdc(struct fb_info *info)
+{
-+ struct ringbuf *pb;
++ struct diu *hw = dr.diu_reg;
++ struct mfb_info *mfbi = info->par;
++ struct fsl_diu_data *machine_data = mfbi->parent;
+
-+ if (size == 0)
-+ return NULL;
++ if (!machine_data->fb_enabled) {
++ out_be32(&hw->diu_mode, dr.mode);
++ machine_data->fb_enabled++;
++ }
++}
+
-+ pb = kmalloc(sizeof(*pb), GFP_KERNEL);
-+ if (pb == NULL)
-+ return NULL;
++static void disable_lcdc(struct fb_info *info)
++{
++ struct diu *hw = dr.diu_reg;
++ struct mfb_info *mfbi = info->par;
++ struct fsl_diu_data *machine_data = mfbi->parent;
+
-+ pb->buf_buf = kmalloc(size, GFP_KERNEL);
-+ if (pb->buf_buf == NULL) {
-+ kfree(pb);
-+ return NULL;
++ if (machine_data->fb_enabled) {
++ out_be32(&hw->diu_mode, 0);
++ machine_data->fb_enabled = 0;
+ }
++}
+
-+ pb->buf_size = size;
-+ pb->buf_get = pb->buf_put = pb->buf_buf;
++static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
++ struct fb_info *info)
++{
++ struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par;
++ struct fsl_diu_data *machine_data = mfbi->parent;
++ int available_height, upper_aoi_bottom, index = mfbi->index;
++ int lower_aoi_is_open, upper_aoi_is_open;
++ __u32 base_plane_width, base_plane_height, upper_aoi_height;
+
-+ return pb;
++ base_plane_width = machine_data->fsl_diu_info[0]->var.xres;
++ base_plane_height = machine_data->fsl_diu_info[0]->var.yres;
++
++ switch (index) {
++ case 0:
++ if (mfbi->x_aoi_d != 0)
++ mfbi->x_aoi_d = 0;
++ if (mfbi->y_aoi_d != 0)
++ mfbi->y_aoi_d = 0;
++ break;
++ case 1: /* AOI 0 */
++ case 3:
++ lower_aoi_mfbi = machine_data->fsl_diu_info[index+1]->par;
++ lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0;
++ if (var->xres > base_plane_width)
++ var->xres = base_plane_width;
++ if ((mfbi->x_aoi_d + var->xres) > base_plane_width)
++ mfbi->x_aoi_d = base_plane_width - var->xres;
++
++ if (lower_aoi_is_open)
++ available_height = lower_aoi_mfbi->y_aoi_d;
++ else
++ available_height = base_plane_height;
++ if (var->yres > available_height)
++ var->yres = available_height;
++ if ((mfbi->y_aoi_d + var->yres) > available_height)
++ mfbi->y_aoi_d = available_height - var->yres;
++ break;
++ case 2: /* AOI 1 */
++ case 4:
++ upper_aoi_mfbi = machine_data->fsl_diu_info[index-1]->par;
++ upper_aoi_height =
++ machine_data->fsl_diu_info[index-1]->var.yres;
++ upper_aoi_bottom = upper_aoi_mfbi->y_aoi_d + upper_aoi_height;
++ upper_aoi_is_open = upper_aoi_mfbi->count > 0 ? 1 : 0;
++ if (var->xres > base_plane_width)
++ var->xres = base_plane_width;
++ if ((mfbi->x_aoi_d + var->xres) > base_plane_width)
++ mfbi->x_aoi_d = base_plane_width - var->xres;
++ if (mfbi->y_aoi_d < 0)
++ mfbi->y_aoi_d = 0;
++ if (upper_aoi_is_open) {
++ if (mfbi->y_aoi_d < upper_aoi_bottom)
++ mfbi->y_aoi_d = upper_aoi_bottom;
++ available_height = base_plane_height
++ - upper_aoi_bottom;
++ } else
++ available_height = base_plane_height;
++ if (var->yres > available_height)
++ var->yres = available_height;
++ if ((mfbi->y_aoi_d + var->yres) > base_plane_height)
++ mfbi->y_aoi_d = base_plane_height - var->yres;
++ break;
++ }
+}
++/*
++ * Checks to see if the hardware supports the state requested by var passed
++ * in. This function does not alter the hardware state! If the var passed in
++ * is slightly off by what the hardware can support then we alter the var
++ * PASSED in to what we can do. If the hardware doesn't support mode change
++ * a -EINVAL will be returned by the upper layers.
++ */
++static int fsl_diu_check_var(struct fb_var_screeninfo *var,
++ struct fb_info *info)
++{
++ unsigned long htotal, vtotal;
+
-+/* free the ring buf and the buffer itself */
-+static inline void free_ringbuf(struct ringbuf *pb)
++ pr_debug("check_var xres: %d\n", var->xres);
++ pr_debug("check_var yres: %d\n", var->yres);
++
++ if (var->xres_virtual < var->xres)
++ var->xres_virtual = var->xres;
++ if (var->yres_virtual < var->yres)
++ var->yres_virtual = var->yres;
++
++ if (var->xoffset < 0)
++ var->xoffset = 0;
++
++ if (var->yoffset < 0)
++ var->yoffset = 0;
++
++ if (var->xoffset + info->var.xres > info->var.xres_virtual)
++ var->xoffset = info->var.xres_virtual - info->var.xres;
++
++ if (var->yoffset + info->var.yres > info->var.yres_virtual)
++ var->yoffset = info->var.yres_virtual - info->var.yres;
++
++ if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) &&
++ (var->bits_per_pixel != 16))
++ var->bits_per_pixel = default_bpp;
++
++ switch (var->bits_per_pixel) {
++ case 16:
++ var->red.length = 5;
++ var->red.offset = 11;
++ var->red.msb_right = 0;
++
++ var->green.length = 6;
++ var->green.offset = 5;
++ var->green.msb_right = 0;
++
++ var->blue.length = 5;
++ var->blue.offset = 0;
++ var->blue.msb_right = 0;
++
++ var->transp.length = 0;
++ var->transp.offset = 0;
++ var->transp.msb_right = 0;
++ break;
++ case 24:
++ var->red.length = 8;
++ var->red.offset = 0;
++ var->red.msb_right = 0;
++
++ var->green.length = 8;
++ var->green.offset = 8;
++ var->green.msb_right = 0;
++
++ var->blue.length = 8;
++ var->blue.offset = 16;
++ var->blue.msb_right = 0;
++
++ var->transp.length = 0;
++ var->transp.offset = 0;
++ var->transp.msb_right = 0;
++ break;
++ case 32:
++ var->red.length = 8;
++ var->red.offset = 16;
++ var->red.msb_right = 0;
++
++ var->green.length = 8;
++ var->green.offset = 8;
++ var->green.msb_right = 0;
++
++ var->blue.length = 8;
++ var->blue.offset = 0;
++ var->blue.msb_right = 0;
++
++ var->transp.length = 8;
++ var->transp.offset = 24;
++ var->transp.msb_right = 0;
++
++ break;
++ }
++ /* If the pixclock is below the minimum spec'd value then set to
++ * refresh rate for 60Hz since this is supported by most monitors.
++ * Refer to Documentation/fb/ for calculations.
++ */
++ if ((var->pixclock < MIN_PIX_CLK) || (var->pixclock > MAX_PIX_CLK)) {
++ htotal = var->xres + var->right_margin + var->hsync_len +
++ var->left_margin;
++ vtotal = var->yres + var->lower_margin + var->vsync_len +
++ var->upper_margin;
++ var->pixclock = (vtotal * htotal * 6UL) / 100UL;
++ var->pixclock = KHZ2PICOS(var->pixclock);
++ pr_debug("pixclock set for 60Hz refresh = %u ps\n",
++ var->pixclock);
++ }
++
++ var->height = -1;
++ var->width = -1;
++ var->grayscale = 0;
++
++ /* Copy nonstd field to/from sync for fbset usage */
++ var->sync |= var->nonstd;
++ var->nonstd |= var->sync;
++
++ adjust_aoi_size_position(var, info);
++ return 0;
++}
++
++static void set_fix(struct fb_info *info)
+{
-+ if (pb != NULL) {
-+ kfree(pb->buf_buf);
-+ kfree(pb);
++ struct fb_fix_screeninfo *fix = &info->fix;
++ struct fb_var_screeninfo *var = &info->var;
++ struct mfb_info *mfbi = info->par;
++
++ strncpy(fix->id, mfbi->id, strlen(mfbi->id));
++ fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
++ fix->type = FB_TYPE_PACKED_PIXELS;
++ fix->accel = FB_ACCEL_NONE;
++ fix->visual = FB_VISUAL_TRUECOLOR;
++ fix->xpanstep = 1;
++ fix->ypanstep = 1;
++}
++
++static void update_lcdc(struct fb_info *info)
++{
++ struct fb_var_screeninfo *var = &info->var;
++ struct mfb_info *mfbi = info->par;
++ struct fsl_diu_data *machine_data = mfbi->parent;
++ struct diu *hw;
++ int i, j;
++ char __iomem *cursor_base, *gamma_table_base;
++
++ u32 temp;
++
++ hw = dr.diu_reg;
++
++ if (mfbi->type == MFB_TYPE_OFF) {
++ fsl_diu_disable_panel(info);
++ return;
+ }
++
++ diu_ops.set_monitor_port(machine_data->monitor_port);
++ gamma_table_base = pool.gamma.vaddr;
++ cursor_base = pool.cursor.vaddr;
++ /* Prep for DIU init - gamma table, cursor table */
++
++ for (i = 0; i <= 2; i++)
++ for (j = 0; j <= 255; j++)
++ *gamma_table_base++ = j;
++
++ diu_ops.set_gamma_table(machine_data->monitor_port, pool.gamma.vaddr);
++
++ pr_debug("update-lcdc: HW - %p\n Disabling DIU\n", hw);
++ disable_lcdc(info);
++
++ /* Program DIU registers */
++
++ out_be32(&hw->gamma, pool.gamma.paddr);
++ out_be32(&hw->cursor, pool.cursor.paddr);
++
++ out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */
++ out_be32(&hw->bgnd_wb, 0); /* BGND_WB */
++ out_be32(&hw->disp_size, (var->yres << 16 | var->xres));
++ /* DISP SIZE */
++ pr_debug("DIU xres: %d\n", var->xres);
++ pr_debug("DIU yres: %d\n", var->yres);
++
++ out_be32(&hw->wb_size, 0); /* WB SIZE */
++ out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */
++
++ /* Horizontal and vertical configuration register */
++ temp = var->left_margin << 22 | /* BP_H */
++ var->hsync_len << 11 | /* PW_H */
++ var->right_margin; /* FP_H */
++
++ out_be32(&hw->hsyn_para, temp);
++
++ temp = var->upper_margin << 22 | /* BP_V */
++ var->vsync_len << 11 | /* PW_V */
++ var->lower_margin; /* FP_V */
++
++ out_be32(&hw->vsyn_para, temp);
++
++ pr_debug("DIU right_margin - %d\n", var->right_margin);
++ pr_debug("DIU left_margin - %d\n", var->left_margin);
++ pr_debug("DIU hsync_len - %d\n", var->hsync_len);
++ pr_debug("DIU upper_margin - %d\n", var->upper_margin);
++ pr_debug("DIU lower_margin - %d\n", var->lower_margin);
++ pr_debug("DIU vsync_len - %d\n", var->vsync_len);
++ pr_debug("DIU HSYNC - 0x%08x\n", hw->hsyn_para);
++ pr_debug("DIU VSYNC - 0x%08x\n", hw->vsyn_para);
++
++ diu_ops.set_pixel_clock(var->pixclock);
++
++ out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */
++ out_be32(&hw->thresholds, 0x00037800); /* The Thresholds */
++ out_be32(&hw->int_status, 0); /* INTERRUPT STATUS */
++ out_be32(&hw->plut, 0x01F5F666);
++
++ /* Enable the DIU */
++ enable_lcdc(info);
+}
+
-+/* clear pipo , juest repoint the pointer here */
-+static inline void clear_ringbuf(struct ringbuf *pb)
++static int map_video_memory(struct fb_info *info)
+{
-+ if (pb != NULL)
-+ pb->buf_get = pb->buf_put;
++ phys_addr_t phys;
++
++ pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual);
++ pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual);
++ pr_debug("info->fix.line_length = %d\n", info->fix.line_length);
++
++ info->fix.smem_len = info->fix.line_length * info->var.yres_virtual;
++ pr_debug("MAP_VIDEO_MEMORY: smem_len = %d\n", info->fix.smem_len);
++ info->screen_base = fsl_diu_alloc(info->fix.smem_len, &phys);
++ if (info->screen_base == 0) {
++ printk(KERN_ERR "Unable to allocate fb memory\n");
++ return -ENOMEM;
++ }
++ info->fix.smem_start = (unsigned long) phys;
++ info->screen_size = info->fix.smem_len;
++
++ pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n",
++ info->fix.smem_start,
++ info->fix.smem_len);
++ pr_debug("screen base %p\n", info->screen_base);
++
++ return 0;
+}
+
-+/* get the number of data in the pipo */
-+static inline unsigned int ringbuf_avail_data(struct ringbuf *pb)
++static void unmap_video_memory(struct fb_info *info)
+{
-+ if (pb == NULL)
-+ return 0;
-+ return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
++ fsl_diu_free(info->screen_base, info->fix.smem_len);
++ info->screen_base = 0;
++ info->fix.smem_start = 0;
++ info->fix.smem_len = 0;
+}
+
-+/* get the number of space in the pipo */
-+static inline unsigned int ringbuf_avail_space(struct ringbuf *pb)
++/*
++ * Using the fb_var_screeninfo in fb_info we set the resolution of this
++ * particular framebuffer. This function alters the fb_fix_screeninfo stored
++ * in fb_info. It does not alter var in fb_info since we are using that
++ * data. This means we depend on the data in var inside fb_info to be
++ * supported by the hardware. fsl_diu_check_var is always called before
++ * fsl_diu_set_par to ensure this.
++ */
++static int fsl_diu_set_par(struct fb_info *info)
+{
-+ if (pb == NULL)
-+ return 0;
-+ return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
++ unsigned long len;
++ struct fb_var_screeninfo *var = &info->var;
++ struct mfb_info *mfbi = info->par;
++ struct fsl_diu_data *machine_data = mfbi->parent;
++ struct diu_ad *ad = mfbi->ad;
++ struct diu *hw;
++
++ hw = dr.diu_reg;
++
++ set_fix(info);
++ mfbi->cursor_reset = 1;
++
++ len = info->var.yres_virtual * info->fix.line_length;
++ /* Alloc & dealloc each time resolution/bpp change */
++ if (len != info->fix.smem_len) {
++ if (info->fix.smem_start)
++ unmap_video_memory(info);
++ pr_debug("SET PAR: smem_len = %d\n", info->fix.smem_len);
++
++ /* Memory allocation for framebuffer */
++ if (map_video_memory(info)) {
++ printk(KERN_ERR "Unable to allocate fb memory 1\n");
++ return -ENOMEM;
++ }
++ }
++
++ ad->pix_fmt =
++ diu_ops.get_pixel_format(var->bits_per_pixel,
++ machine_data->monitor_port);
++ ad->addr = cpu_to_le32(info->fix.smem_start);
++ ad->src_size_g_alpha = cpu_to_le32((var->yres << 12) |
++ var->xres) | mfbi->g_alpha;
++ /* fix me. AOI should not be greater than display size */
++ ad->aoi_size = cpu_to_le32((var->yres << 16) | var->xres);
++ ad->offset_xyi = 0;
++ ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d);
++
++ /* Disable chroma keying function */
++ ad->ckmax_r = 0;
++ ad->ckmax_g = 0;
++ ad->ckmax_b = 0;
++
++ ad->ckmin_r = 255;
++ ad->ckmin_g = 255;
++ ad->ckmin_b = 255;
++
++ if (mfbi->index == 0)
++ update_lcdc(info);
++ return 0;
+}
+
-+/* put count data into pipo */
-+static unsigned int put_ringbuf(struct ringbuf *pb, const char *buf,
-+ unsigned int count)
++static inline __u32 CNVT_TOHW(__u32 val, __u32 width)
+{
-+ unsigned int len;
++ return ((val<<width) + 0x7FFF - val)>>16;
++}
+
-+ if (pb == NULL)
-+ return 0;
++/*
++ * Set a single color register. The values supplied have a 16 bit magnitude
++ * which needs to be scaled in this function for the hardware. Things to take
++ * into consideration are how many color registers, if any, are supported with
++ * the current color visual. With truecolor mode no color palettes are
++ * supported. Here a psuedo palette is created which we store the value in
++ * pseudo_palette in struct fb_info. For pseudocolor mode we have a limited
++ * color palette.
++ */
++static int fsl_diu_setcolreg(unsigned regno, unsigned red, unsigned green,
++ unsigned blue, unsigned transp, struct fb_info *info)
++{
++ int ret = 1;
+
-+ len = ringbuf_avail_space(pb);
-+ if (count > len)
-+ count = len;
++ /*
++ * If greyscale is true, then we convert the RGB value
++ * to greyscale no matter what visual we are using.
++ */
++ if (info->var.grayscale)
++ red = green = blue = (19595 * red + 38470 * green +
++ 7471 * blue) >> 16;
++ switch (info->fix.visual) {
++ case FB_VISUAL_TRUECOLOR:
++ /*
++ * 16-bit True Colour. We encode the RGB value
++ * according to the RGB bitfield information.
++ */
++ if (regno < 16) {
++ u32 *pal = info->pseudo_palette;
++ u32 v;
++
++ 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);
++
++ v = (red << info->var.red.offset) |
++ (green << info->var.green.offset) |
++ (blue << info->var.blue.offset) |
++ (transp << info->var.transp.offset);
+
-+ if (count == 0)
-+ return 0;
++ pal[regno] = v;
++ ret = 0;
++ }
++ break;
++ case FB_VISUAL_STATIC_PSEUDOCOLOR:
++ case FB_VISUAL_PSEUDOCOLOR:
++ break;
++ }
+
-+ 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 ret;
++}
++
++/*
++ * Pan (or wrap, depending on the `vmode' field) the display using the
++ * 'xoffset' and 'yoffset' fields of the 'var' structure. If the values
++ * don't fit, return -EINVAL.
++ */
++static int fsl_diu_pan_display(struct fb_var_screeninfo *var,
++ struct fb_info *info)
++{
++ if ((info->var.xoffset == var->xoffset) &&
++ (info->var.yoffset == var->yoffset))
++ return 0; /* No change, do nothing */
++
++ if (var->xoffset < 0 || var->yoffset < 0
++ || var->xoffset + info->var.xres > info->var.xres_virtual
++ || var->yoffset + info->var.yres > info->var.yres_virtual)
++ return -EINVAL;
++
++ info->var.xoffset = var->xoffset;
++ info->var.yoffset = var->yoffset;
++
++ if (var->vmode & FB_VMODE_YWRAP)
++ info->var.vmode |= FB_VMODE_YWRAP;
++ else
++ info->var.vmode &= ~FB_VMODE_YWRAP;
++
++ return 0;
++}
++
++/*
++ * Blank the screen if blank_mode != 0, else unblank. Return 0 if blanking
++ * succeeded, != 0 if un-/blanking failed.
++ * blank_mode == 2: suspend vsync
++ * blank_mode == 3: suspend hsync
++ * blank_mode == 4: powerdown
++ */
++static int fsl_diu_blank(int blank_mode, struct fb_info *info)
++{
++ struct mfb_info *mfbi = info->par;
++
++ mfbi->blank = blank_mode;
++
++ switch (blank_mode) {
++ case FB_BLANK_VSYNC_SUSPEND:
++ case FB_BLANK_HSYNC_SUSPEND:
++ /* FIXME: fixes to enable_panel and enable lcdc needed */
++ case FB_BLANK_NORMAL:
++ /* fsl_diu_disable_panel(info);*/
++ break;
++ case FB_BLANK_POWERDOWN:
++ /* disable_lcdc(info); */
++ break;
++ case FB_BLANK_UNBLANK:
++ /* fsl_diu_enable_panel(info);*/
++ break;
+ }
-+ return count;
++
++ return 0;
+}
+
-+/* get count data from pipo */
-+static unsigned int get_ringbuf(struct ringbuf *pb, char *buf,
-+ unsigned int count)
++static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
++ unsigned long arg)
+{
-+ unsigned int len;
++ struct mfb_info *mfbi = info->par;
++ struct diu_ad *ad = mfbi->ad;
++ struct mfb_chroma_key ck;
++ unsigned char global_alpha;
++ struct aoi_display_offset aoi_d;
++ __u32 pix_fmt;
++ void __user *buf = (void __user *)arg;
+
-+ if (pb == NULL || buf == NULL)
-+ return 0;
++ if (!arg)
++ return -EINVAL;
++ switch (cmd) {
++ case MFB_SET_PIXFMT:
++ if (copy_from_user(&pix_fmt, buf, sizeof(pix_fmt)))
++ return -EFAULT;
++ ad->pix_fmt = pix_fmt;
++ pr_debug("Set pixel format to 0x%08x\n", ad->pix_fmt);
++ break;
++ case MFB_GET_PIXFMT:
++ pix_fmt = ad->pix_fmt;
++ if (copy_to_user(buf, &pix_fmt, sizeof(pix_fmt)))
++ return -EFAULT;
++ pr_debug("get pixel format 0x%08x\n", ad->pix_fmt);
++ break;
++ case MFB_SET_AOID:
++ if (copy_from_user(&aoi_d, buf, sizeof(aoi_d)))
++ return -EFAULT;
++ mfbi->x_aoi_d = aoi_d.x_aoi_d;
++ mfbi->y_aoi_d = aoi_d.y_aoi_d;
++ pr_debug("set AOI display offset of index %d to (%d,%d)\n",
++ mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d);
++ fsl_diu_check_var(&info->var, info);
++ fsl_diu_set_par(info);
++ break;
++ case MFB_GET_AOID:
++ aoi_d.x_aoi_d = mfbi->x_aoi_d;
++ aoi_d.y_aoi_d = mfbi->y_aoi_d;
++ if (copy_to_user(buf, &aoi_d, sizeof(aoi_d)))
++ return -EFAULT;
++ pr_debug("get AOI display offset of index %d (%d,%d)\n",
++ mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d);
++ break;
++ case MFB_GET_ALPHA:
++ global_alpha = mfbi->g_alpha;
++ if (copy_to_user(buf, &global_alpha, sizeof(global_alpha)))
++ return -EFAULT;
++ pr_debug("get global alpha of index %d\n", mfbi->index);
++ break;
++ case MFB_SET_ALPHA:
++ /* set panel information */
++ if (copy_from_user(&global_alpha, buf, sizeof(global_alpha)))
++ return -EFAULT;
++ ad->src_size_g_alpha = (ad->src_size_g_alpha & (~0xff)) |
++ (global_alpha & 0xff);
++ mfbi->g_alpha = global_alpha;
++ pr_debug("set global alpha for index %d\n", mfbi->index);
++ break;
++ case MFB_SET_CHROMA_KEY:
++ /* set panel winformation */
++ if (copy_from_user(&ck, buf, sizeof(ck)))
++ return -EFAULT;
+
-+ len = ringbuf_avail_data(pb);
-+ if (count > len)
-+ count = len;
++ if (ck.enable &&
++ (ck.red_max < ck.red_min ||
++ ck.green_max < ck.green_min ||
++ ck.blue_max < ck.blue_min))
++ return -EINVAL;
+
-+ if (count == 0)
-+ return 0;
++ if (!ck.enable) {
++ ad->ckmax_r = 0;
++ ad->ckmax_g = 0;
++ ad->ckmax_b = 0;
++ ad->ckmin_r = 255;
++ ad->ckmin_g = 255;
++ ad->ckmin_b = 255;
++ } else {
++ ad->ckmax_r = ck.red_max;
++ ad->ckmax_g = ck.green_max;
++ ad->ckmax_b = ck.blue_max;
++ ad->ckmin_r = ck.red_min;
++ ad->ckmin_g = ck.green_min;
++ ad->ckmin_b = ck.blue_min;
++ }
++ pr_debug("set chroma key\n");
++ break;
++ case FBIOGET_GWINFO:
++ if (mfbi->type == MFB_TYPE_OFF)
++ return -ENODEV;
++ /* get graphic window information */
++ if (copy_to_user(buf, ad, sizeof(*ad)))
++ return -EFAULT;
++ break;
++ case FBIOGET_HWCINFO:
++ pr_debug("FBIOGET_HWCINFO:0x%08x\n", FBIOGET_HWCINFO);
++ break;
++ case FBIOPUT_MODEINFO:
++ pr_debug("FBIOPUT_MODEINFO:0x%08x\n", FBIOPUT_MODEINFO);
++ break;
++ case FBIOGET_DISPINFO:
++ pr_debug("FBIOGET_DISPINFO:0x%08x\n", FBIOGET_DISPINFO);
++ break;
+
-+ 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;
++ default:
++ printk(KERN_ERR "Unknown ioctl command (0x%08X)\n", cmd);
++ return -ENOIOCTLCMD;
+ }
+
-+ return count;
++ return 0;
+}
+
-+static struct usb_driver spcp8x5_driver = {
-+ .name = "spcp8x5",
-+ .probe = usb_serial_probe,
-+ .disconnect = usb_serial_disconnect,
-+ .id_table = id_table,
-+ .no_dynamic_id = 1,
-+};
++/* turn on fb if count == 1
++ */
++static int fsl_diu_open(struct fb_info *info, int user)
++{
++ struct mfb_info *mfbi = info->par;
++ int res = 0;
+
++ spin_lock(&diu_lock);
++ mfbi->count++;
++ if (mfbi->count == 1) {
++ pr_debug("open plane index %d\n", mfbi->index);
++ fsl_diu_check_var(&info->var, info);
++ res = fsl_diu_set_par(info);
++ if (res < 0)
++ mfbi->count--;
++ else {
++ res = fsl_diu_enable_panel(info);
++ if (res < 0)
++ mfbi->count--;
++ }
++ }
+
-+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;
++ spin_unlock(&diu_lock);
++ return res;
++}
++
++/* turn off fb if count == 0
++ */
++static int fsl_diu_release(struct fb_info *info, int user)
++{
++ struct mfb_info *mfbi = info->par;
++ int res = 0;
++
++ spin_lock(&diu_lock);
++ mfbi->count--;
++ if (mfbi->count == 0) {
++ pr_debug("release plane index %d\n", mfbi->index);
++ res = fsl_diu_disable_panel(info);
++ if (res < 0)
++ mfbi->count++;
++ }
++ spin_unlock(&diu_lock);
++ return res;
++}
++
++static struct fb_ops fsl_diu_ops = {
++ .owner = THIS_MODULE,
++ .fb_check_var = fsl_diu_check_var,
++ .fb_set_par = fsl_diu_set_par,
++ .fb_setcolreg = fsl_diu_setcolreg,
++ .fb_blank = fsl_diu_blank,
++ .fb_pan_display = fsl_diu_pan_display,
++ .fb_fillrect = cfb_fillrect,
++ .fb_copyarea = cfb_copyarea,
++ .fb_imageblit = cfb_imageblit,
++ .fb_ioctl = fsl_diu_ioctl,
++ .fb_open = fsl_diu_open,
++ .fb_release = fsl_diu_release,
+};
+
-+/* 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)
++static int init_fbinfo(struct fb_info *info)
+{
-+ struct spcp8x5_private *priv;
-+ int i;
-+ enum spcp8x5_type type = SPCP825_007_TYPE;
++ struct mfb_info *mfbi = info->par;
+
-+ 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);
++ info->device = NULL;
++ info->var.activate = FB_ACTIVATE_NOW;
++ info->fbops = &fsl_diu_ops;
++ info->flags = FBINFO_FLAG_DEFAULT;
++ info->pseudo_palette = &mfbi->pseudo_palette;
+
-+ for (i = 0; i < serial->num_ports; ++i) {
-+ priv = kzalloc(sizeof(struct spcp8x5_private), GFP_KERNEL);
-+ if (!priv)
-+ goto cleanup;
++ /* Allocate colormap */
++ fb_alloc_cmap(&info->cmap, 16, 0);
++ return 0;
++}
+
-+ spin_lock_init(&priv->lock);
-+ priv->buf = alloc_ringbuf(SPCP8x5_BUF_SIZE);
-+ if (priv->buf == NULL)
-+ goto cleanup2;
++static int install_fb(struct fb_info *info)
++{
++ int rc;
++ struct mfb_info *mfbi = info->par;
++ const char *aoi_mode, *init_aoi_mode = "320x240";
+
-+ init_waitqueue_head(&priv->delta_msr_wait);
-+ priv->type = type;
-+ usb_set_serial_port_data(serial->port[i] , priv);
++ if (init_fbinfo(info))
++ return -EINVAL;
++
++ if (mfbi->index == 0) /* plane 0 */
++ aoi_mode = fb_mode;
++ else
++ aoi_mode = init_aoi_mode;
++ pr_debug("mode used = %s\n", aoi_mode);
++ rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db,
++ ARRAY_SIZE(fsl_diu_mode_db), &fsl_diu_default_mode, default_bpp);
+
++ switch (rc) {
++ case 1:
++ pr_debug("using mode specified in @mode\n");
++ break;
++ case 2:
++ pr_debug("using mode specified in @mode "
++ "with ignored refresh rate\n");
++ break;
++ case 3:
++ pr_debug("using mode default mode\n");
++ break;
++ case 4:
++ pr_debug("using mode from list\n");
++ break;
++ default:
++ pr_debug("rc = %d\n", rc);
++ pr_debug("failed to find mode\n");
++ return -EINVAL;
++ break;
+ }
+
-+ return 0;
++ pr_debug("xres_virtual %d\n", info->var.xres_virtual);
++ pr_debug("bits_per_pixel %d\n", info->var.bits_per_pixel);
+
-+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);
++ pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual);
++ pr_debug("info->fix.line_length = %d\n", info->fix.line_length);
++
++ if (mfbi->type == MFB_TYPE_OFF)
++ mfbi->blank = FB_BLANK_NORMAL;
++ else
++ mfbi->blank = FB_BLANK_UNBLANK;
++
++ if (fsl_diu_check_var(&info->var, info)) {
++ printk(KERN_ERR "fb_check_var failed");
++ fb_dealloc_cmap(&info->cmap);
++ return -EINVAL;
+ }
-+ return -ENOMEM;
++
++ if (fsl_diu_set_par(info)) {
++ printk(KERN_ERR "fb_set_par failed");
++ fb_dealloc_cmap(&info->cmap);
++ return -EINVAL;
++ }
++
++ if (register_framebuffer(info) < 0) {
++ printk(KERN_ERR "register_framebuffer failed");
++ unmap_video_memory(info);
++ fb_dealloc_cmap(&info->cmap);
++ return -EINVAL;
++ }
++
++ mfbi->registered = 1;
++ printk(KERN_INFO "fb%d: %s fb device registered successfully.\n",
++ info->node, info->fix.id);
++
++ return 0;
+}
+
-+/* call when the device plug out. free all the memory alloced by probe */
-+static void spcp8x5_shutdown(struct usb_serial *serial)
++static void __exit uninstall_fb(struct fb_info *info)
+{
-+ int i;
-+ struct spcp8x5_private *priv;
++ struct mfb_info *mfbi = info->par;
+
-+ 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);
++ if (!mfbi->registered)
++ return;
++
++ unregister_framebuffer(info);
++ unmap_video_memory(info);
++ if (&info->cmap)
++ fb_dealloc_cmap(&info->cmap);
++
++ mfbi->registered = 0;
++}
++
++static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
++{
++ struct diu *hw = dr.diu_reg;
++ unsigned int status = in_be32(&hw->int_status);
++
++ if (status) {
++ /* This is the workaround for underrun */
++ if (status & INT_UNDRUN) {
++ out_be32(&hw->diu_mode, 0);
++ pr_debug("Err: DIU occurs underrun!\n");
++ udelay(1);
++ out_be32(&hw->diu_mode, 1);
++ }
++#if defined(CONFIG_NOT_COHERENT_CACHE)
++ else if (status & INT_VSYNC) {
++ unsigned int i;
++ for (i = 0; i < coherence_data_size;
++ i += d_cache_line_size)
++ __asm__ __volatile__ (
++ "dcbz 0, %[input]"
++ ::[input]"r"(&coherence_data[i]));
+ }
++#endif
++ return IRQ_HANDLED;
+ }
++ return IRQ_NONE;
+}
+
-+/* 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)
++static int request_irq_local(int irq)
+{
-+ int retval;
-+ u8 mcr = 0 ;
++ unsigned long status, ints;
++ struct diu *hw;
++ int ret;
+
-+ if (type == SPCP825_007_TYPE)
-+ return -EPERM;
++ hw = dr.diu_reg;
+
-+ 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;
++ /* Read to clear the status */
++ status = in_be32(&hw->int_status);
++
++ ret = request_irq(irq, fsl_diu_isr, 0, "diu", 0);
++ if (ret)
++ pr_info("Request diu IRQ failed.\n");
++ else {
++ ints = INT_PARERR | INT_LS_BF_VS;
++#if !defined(CONFIG_NOT_COHERENT_CACHE)
++ ints |= INT_VSYNC;
++#endif
++ if (dr.mode == MFB_MODE2 || dr.mode == MFB_MODE3)
++ ints |= INT_VSYNC_WB;
++
++ /* Read to clear the status */
++ status = in_be32(&hw->int_status);
++ out_be32(&hw->int_mask, ints);
++ }
++ return ret;
+}
+
-+/* 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)
++static void free_irq_local(int irq)
+{
-+ u8 *status_buffer;
-+ int ret;
++ struct diu *hw = dr.diu_reg;
+
-+ /* 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;
++ /* Disable all LCDC interrupt */
++ out_be32(&hw->int_mask, 0x1f);
+
-+ status_buffer = kmalloc(1, GFP_KERNEL);
-+ if (!status_buffer)
-+ return -ENOMEM;
-+ status_buffer[0] = status[0];
++ free_irq(irq, 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);
++#ifdef CONFIG_PM
++/*
++ * Power management hooks. Note that we won't be called from IRQ context,
++ * unlike the blank functions above, so we may sleep.
++ */
++static int fsl_diu_suspend(struct of_device *dev, pm_message_t state)
++{
++ struct fsl_diu_data *machine_data;
+
-+ dev_dbg(&dev->dev, "0xc0:0x22:0:6 %d - 0x%p ", ret, status_buffer);
-+ status[0] = status_buffer[0];
-+ kfree(status_buffer);
++ machine_data = dev_get_drvdata(&ofdev->dev);
++ disable_lcdc(machine_data->fsl_diu_info[0]);
+
-+ return ret;
++ return 0;
+}
+
-+/* 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)
++static int fsl_diu_resume(struct of_device *dev)
+{
-+ int ret;
++ struct fsl_diu_data *machine_data;
+
-+ /* I return Permited not support here but seem inval device
-+ * is more fix */
-+ if (type == SPCP825_007_TYPE)
-+ return;
++ machine_data = dev_get_drvdata(&ofdev->dev);
++ enable_lcdc(machine_data->fsl_diu_info[0]);
+
-+ 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);
++ return 0;
+}
+
-+/* 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)
++#else
++#define fsl_diu_suspend NULL
++#define fsl_diu_resume NULL
++#endif /* CONFIG_PM */
++
++/* Align to 64-bit(8-byte), 32-byte, etc. */
++static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
+{
-+ 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;
++ u32 offset, ssize;
++ u32 mask;
++ dma_addr_t paddr = 0;
+
-+ dbg("%s - port %d", __func__, port->number);
++ ssize = size + bytes_align;
++ buf->vaddr = dma_alloc_coherent(0, ssize, &paddr, GFP_DMA | __GFP_ZERO);
++ if (!buf->vaddr)
++ return -ENOMEM;
+
-+ /* 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);
++ buf->paddr = (__u32) paddr;
+
-+ /* clear out any remaining data in the buffer */
-+ clear_ringbuf(priv->buf);
-+ spin_unlock_irqrestore(&priv->lock, flags);
++ mask = bytes_align - 1;
++ offset = (u32)buf->paddr & mask;
++ if (offset) {
++ buf->offset = bytes_align - offset;
++ buf->paddr = (u32)buf->paddr + offset;
++ } else
++ buf->offset = 0;
++ return 0;
++}
+
-+ /* 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);
++static void free_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
++{
++ dma_free_coherent(0, size + bytes_align,
++ buf->vaddr, (buf->paddr - buf->offset));
++ return;
++}
+
-+ /* 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);
-+ }
-+ }
++static ssize_t store_monitor(struct device *device,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ int old_monitor_port;
++ unsigned long val;
++ struct fsl_diu_data *machine_data =
++ container_of(attr, struct fsl_diu_data, dev_attr);
+
-+ /* 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);
++ if (strict_strtoul(buf, 10, &val))
++ return 0;
++
++ old_monitor_port = machine_data->monitor_port;
++ machine_data->monitor_port = diu_ops.set_sysfs_monitor_port(val);
++
++ if (old_monitor_port != machine_data->monitor_port) {
++ /* All AOIs need adjust pixel format
++ * fsl_diu_set_par only change the pixsel format here
++ * unlikely to fail. */
++ fsl_diu_set_par(machine_data->fsl_diu_info[0]);
++ fsl_diu_set_par(machine_data->fsl_diu_info[1]);
++ fsl_diu_set_par(machine_data->fsl_diu_info[2]);
++ fsl_diu_set_par(machine_data->fsl_diu_info[3]);
++ fsl_diu_set_par(machine_data->fsl_diu_info[4]);
+ }
-+ result = usb_unlink_urb(port->read_urb);
-+ if (result)
-+ dev_dbg(&port->dev, "usb_unlink_urb(read_urb) = %d\n", result);
++ return count;
+}
+
-+/* 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)
++static ssize_t show_monitor(struct device *device,
++ struct device_attribute *attr, char *buf)
+{
-+ 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;
++ struct fsl_diu_data *machine_data =
++ container_of(attr, struct fsl_diu_data, dev_attr);
++ return diu_ops.show_monitor_port(machine_data->monitor_port, buf);
++}
+
-+ if ((!port->tty) || (!port->tty->termios))
-+ return;
++static int fsl_diu_probe(struct of_device *ofdev,
++ const struct of_device_id *match)
++{
++ struct device_node *np = ofdev->node;
++ struct mfb_info *mfbi;
++ phys_addr_t dummy_ad_addr;
++ int ret, i, error = 0;
++ struct resource res;
++ struct fsl_diu_data *machine_data;
+
-+ /* 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;
++ machine_data = kzalloc(sizeof(struct fsl_diu_data), GFP_KERNEL);
++ if (!machine_data)
++ return -ENOMEM;
++
++ for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) {
++ machine_data->fsl_diu_info[i] =
++ framebuffer_alloc(sizeof(struct mfb_info), &ofdev->dev);
++ if (!machine_data->fsl_diu_info[i]) {
++ dev_err(&ofdev->dev, "cannot allocate memory\n");
++ ret = -ENOMEM;
++ goto error2;
++ }
++ mfbi = machine_data->fsl_diu_info[i]->par;
++ memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
++ mfbi->parent = machine_data;
+ }
-+ 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;
++ ret = of_address_to_resource(np, 0, &res);
++ if (ret) {
++ dev_err(&ofdev->dev, "could not obtain DIU address\n");
++ goto error;
++ }
++ if (!res.start) {
++ dev_err(&ofdev->dev, "invalid DIU address\n");
++ goto error;
++ }
++ dev_dbg(&ofdev->dev, "%s, res.start: 0x%08x\n", __func__, res.start);
+
-+ /* 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;
++ dr.diu_reg = ioremap(res.start, sizeof(struct diu));
++ if (!dr.diu_reg) {
++ dev_err(&ofdev->dev, "Err: can't map DIU registers!\n");
++ ret = -EFAULT;
++ goto error2;
+ }
-+ 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);
++
++ out_be32(&dr.diu_reg->diu_mode, 0); /* disable DIU anyway*/
++
++ /* Get the IRQ of the DIU */
++ machine_data->irq = irq_of_parse_and_map(np, 0);
++
++ if (!machine_data->irq) {
++ dev_err(&ofdev->dev, "could not get DIU IRQ\n");
++ ret = -EINVAL;
++ goto error;
+ }
++ machine_data->monitor_port = monitor_port;
+
-+ /* 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.");
++ /* Area descriptor memory pool aligns to 64-bit boundary */
++ if (allocate_buf(&pool.ad, sizeof(struct diu_ad) * FSL_AOI_NUM, 8))
++ return -ENOMEM;
++
++ /* Get memory for Gamma Table - 32-byte aligned memory */
++ if (allocate_buf(&pool.gamma, 768, 32)) {
++ ret = -ENOMEM;
++ goto error;
+ }
+
-+ /* 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;
++ /* For performance, cursor bitmap buffer aligns to 32-byte boundary */
++ if (allocate_buf(&pool.cursor, MAX_CURS * MAX_CURS * 2, 32)) {
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ i = ARRAY_SIZE(machine_data->fsl_diu_info);
++ machine_data->dummy_ad = (struct diu_ad *)
++ ((u32)pool.ad.vaddr + pool.ad.offset) + i;
++ machine_data->dummy_ad->paddr = pool.ad.paddr +
++ i * sizeof(struct diu_ad);
++ machine_data->dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr);
++ if (!machine_data->dummy_aoi_virt) {
++ ret = -ENOMEM;
++ goto error;
++ }
++ machine_data->dummy_ad->addr = cpu_to_le32(dummy_ad_addr);
++ machine_data->dummy_ad->pix_fmt = 0x88882317;
++ machine_data->dummy_ad->src_size_g_alpha = cpu_to_le32((4 << 12) | 4);
++ machine_data->dummy_ad->aoi_size = cpu_to_le32((4 << 16) | 2);
++ machine_data->dummy_ad->offset_xyi = 0;
++ machine_data->dummy_ad->offset_xyd = 0;
++ machine_data->dummy_ad->next_ad = 0;
++
++ out_be32(&dr.diu_reg->desc[0], machine_data->dummy_ad->paddr);
++ out_be32(&dr.diu_reg->desc[1], machine_data->dummy_ad->paddr);
++ out_be32(&dr.diu_reg->desc[2], machine_data->dummy_ad->paddr);
++
++ for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) {
++ machine_data->fsl_diu_info[i]->fix.smem_start = 0;
++ mfbi = machine_data->fsl_diu_info[i]->par;
++ mfbi->ad = (struct diu_ad *)((u32)pool.ad.vaddr
++ + pool.ad.offset) + i;
++ mfbi->ad->paddr = pool.ad.paddr + i * sizeof(struct diu_ad);
++ ret = install_fb(machine_data->fsl_diu_info[i]);
++ if (ret) {
++ dev_err(&ofdev->dev,
++ "Failed to register framebuffer %d\n",
++ i);
++ goto error;
+ }
+ }
+
-+ /* Set Stop bit2 : 0:1bit 1:2bit */
-+ buf[1] |= (cflag & CSTOPB) ? SET_UART_FORMAT_STOP_2 :
-+ SET_UART_FORMAT_STOP_1;
++ if (request_irq_local(machine_data->irq)) {
++ dev_err(machine_data->fsl_diu_info[0]->dev,
++ "could not request irq for diu.");
++ goto error;
++ }
+
-+ /* 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;
++ machine_data->dev_attr.attr.name = "monitor";
++ machine_data->dev_attr.attr.mode = S_IRUGO|S_IWUSR;
++ machine_data->dev_attr.show = show_monitor;
++ machine_data->dev_attr.store = store_monitor;
++ error = device_create_file(machine_data->fsl_diu_info[0]->dev,
++ &machine_data->dev_attr);
++ if (error) {
++ dev_err(machine_data->fsl_diu_info[0]->dev,
++ "could not create sysfs %s file\n",
++ machine_data->dev_attr.attr.name);
++ }
+
-+ uartdata = buf[0] | buf[1]<<8;
++ dev_set_drvdata(&ofdev->dev, machine_data);
++ return 0;
+
-+ 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);
++error:
++ for (i = ARRAY_SIZE(machine_data->fsl_diu_info);
++ i > 0; i--)
++ uninstall_fb(machine_data->fsl_diu_info[i - 1]);
++ if (pool.ad.vaddr)
++ free_buf(&pool.ad, sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
++ if (pool.gamma.vaddr)
++ free_buf(&pool.gamma, 768, 32);
++ if (pool.cursor.vaddr)
++ free_buf(&pool.cursor, MAX_CURS * MAX_CURS * 2, 32);
++ if (machine_data->dummy_aoi_virt)
++ fsl_diu_free(machine_data->dummy_aoi_virt, 64);
++ iounmap(dr.diu_reg);
++
++error2:
++ for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
++ if (machine_data->fsl_diu_info[i])
++ framebuffer_release(machine_data->fsl_diu_info[i]);
++ kfree(machine_data);
+
-+ if (cflag & CRTSCTS) {
-+ /* enable hardware flow control */
-+ spcp8x5_set_workMode(serial->dev, 0x000a,
-+ SET_WORKING_MODE_U2C, priv->type);
-+ }
-+ return;
++ return ret;
+}
+
-+/* 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)
++
++static int fsl_diu_remove(struct of_device *ofdev)
+{
-+ 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 */
++ struct fsl_diu_data *machine_data;
++ int i;
+
-+ dbg("%s - port %d", __func__, port->number);
++ machine_data = dev_get_drvdata(&ofdev->dev);
++ disable_lcdc(machine_data->fsl_diu_info[0]);
++ free_irq_local(machine_data->irq);
++ for (i = ARRAY_SIZE(machine_data->fsl_diu_info); i > 0; i--)
++ uninstall_fb(machine_data->fsl_diu_info[i - 1]);
++ if (pool.ad.vaddr)
++ free_buf(&pool.ad, sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
++ if (pool.gamma.vaddr)
++ free_buf(&pool.gamma, 768, 32);
++ if (pool.cursor.vaddr)
++ free_buf(&pool.cursor, MAX_CURS * MAX_CURS * 2, 32);
++ if (machine_data->dummy_aoi_virt)
++ fsl_diu_free(machine_data->dummy_aoi_virt, 64);
++ iounmap(dr.diu_reg);
++ for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
++ if (machine_data->fsl_diu_info[i])
++ framebuffer_release(machine_data->fsl_diu_info[i]);
++ kfree(machine_data);
+
-+ usb_clear_halt(serial->dev, port->write_urb->pipe);
-+ usb_clear_halt(serial->dev, port->read_urb->pipe);
++ return 0;
++}
+
-+ ret = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-+ 0x09, 0x00,
-+ 0x01, 0x00, NULL, 0x00, 100);
-+ if (ret)
-+ return ret;
++#ifndef MODULE
++static int __init fsl_diu_setup(char *options)
++{
++ char *opt;
++ unsigned long val;
+
-+ 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);
++ if (!options || !*options)
++ return 0;
+
-+ spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
++ while ((opt = strsep(&options, ",")) != NULL) {
++ if (!*opt)
++ continue;
++ if (!strncmp(opt, "monitor=", 8)) {
++ if (!strict_strtoul(opt + 8, 10, &val) && (val <= 2))
++ monitor_port = val;
++ } else if (!strncmp(opt, "bpp=", 4)) {
++ if (!strict_strtoul(opt + 4, 10, &val))
++ default_bpp = val;
++ } else
++ fb_mode = opt;
++ }
+
-+ /* Setup termios */
-+ if (port->tty)
-+ spcp8x5_set_termios(port, &tmp_termios);
++ return 0;
++}
++#endif
+
-+ spcp8x5_get_msr(serial->dev, &status, priv->type);
++static struct of_device_id fsl_diu_match[] = {
++ {
++ .compatible = "fsl,diu",
++ },
++ {}
++};
++MODULE_DEVICE_TABLE(of, fsl_diu_match);
+
-+ /* 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);
++static struct of_platform_driver fsl_diu_driver = {
++ .owner = THIS_MODULE,
++ .name = "fsl_diu",
++ .match_table = fsl_diu_match,
++ .probe = fsl_diu_probe,
++ .remove = fsl_diu_remove,
++ .suspend = fsl_diu_suspend,
++ .resume = fsl_diu_resume,
++};
+
-+ /* FIXME: need to assert RTS and DTR if CRTSCTS off */
++static int __init fsl_diu_init(void)
++{
++#ifdef CONFIG_NOT_COHERENT_CACHE
++ struct device_node *np;
++ const u32 *prop;
++#endif
++ int ret;
++#ifndef MODULE
++ char *option;
+
-+ dbg("%s - submitting read urb", __func__);
-+ port->read_urb->dev = serial->dev;
-+ ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
++ /*
++ * For kernel boot options (in 'video=xxxfb:<options>' format)
++ */
++ if (fb_get_options("fslfb", &option))
++ return -ENODEV;
++ fsl_diu_setup(option);
++#endif
++ printk(KERN_INFO "Freescale DIU driver\n");
++
++#ifdef CONFIG_NOT_COHERENT_CACHE
++ np = of_find_node_by_type(NULL, "cpu");
++ if (!np) {
++ printk(KERN_ERR "Err: can't find device node 'cpu'\n");
++ return -ENODEV;
++ }
++
++ prop = of_get_property(np, "d-cache-size", NULL);
++ if (prop == NULL)
++ return -ENODEV;
++
++ /* Freescale PLRU requires 13/8 times the cache size to do a proper
++ displacement flush
++ */
++ coherence_data_size = *prop * 13;
++ coherence_data_size /= 8;
++
++ prop = of_get_property(np, "d-cache-line-size", NULL);
++ if (prop == NULL)
++ return -ENODEV;
++ d_cache_line_size = *prop;
++
++ of_node_put(np);
++ coherence_data = vmalloc(coherence_data_size);
++ if (!coherence_data)
++ return -ENOMEM;
++#endif
++ ret = of_register_platform_driver(&fsl_diu_driver);
+ if (ret) {
-+ spcp8x5_close(port, NULL);
-+ return -EPROTO;
++ printk(KERN_ERR
++ "fsl-diu: failed to register platform driver\n");
++#if defined(CONFIG_NOT_COHERENT_CACHE)
++ vfree(coherence_data);
++#endif
++ iounmap(dr.diu_reg);
+ }
-+ return 0;
++ return ret;
+}
+
-+/* 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)
++static void __exit fsl_diu_exit(void)
+{
-+ 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;
++ of_unregister_platform_driver(&fsl_diu_driver);
++#if defined(CONFIG_NOT_COHERENT_CACHE)
++ vfree(coherence_data);
++#endif
++}
+
-+ dev_dbg(&port->dev, "start, urb->status = %d, "
-+ "urb->actual_length = %d\n,", urb->status, urb->actual_length);
++module_init(fsl_diu_init);
++module_exit(fsl_diu_exit);
+
-+ /* 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;
-+ }
++MODULE_AUTHOR("York Sun <yorksun at freescale.com>");
++MODULE_DESCRIPTION("Freescale DIU framebuffer driver");
++MODULE_LICENSE("GPL");
+
-+ /* get tty_flag from status */
-+ tty_flag = TTY_NORMAL;
++module_param_named(mode, fb_mode, charp, 0);
++MODULE_PARM_DESC(mode,
++ "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
++module_param_named(bpp, default_bpp, ulong, 0);
++MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode");
++module_param_named(monitor, monitor_port, int, 0);
++MODULE_PARM_DESC(monitor,
++ "Specify the monitor port (0, 1 or 2) if supported by the platform");
+
-+ 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);
+diff --git a/drivers/video/fsl-diu-fb.h b/drivers/video/fsl-diu-fb.h
+new file mode 100644
+index 0000000..fc295d7
+--- /dev/null
++++ b/drivers/video/fsl-diu-fb.h
+@@ -0,0 +1,223 @@
++/*
++ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
++ *
++ * Freescale DIU Frame Buffer device driver
++ *
++ * Authors: Hongjun Chen <hong-jun.chen at freescale.com>
++ * Paul Widmer <paul.widmer at freescale.com>
++ * Srikanth Srinivasan <srikanth.srinivasan at freescale.com>
++ * York Sun <yorksun at freescale.com>
++ *
++ * Based on imxfb.c Copyright (C) 2004 S.Hauer, 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 the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ */
+
-+ /* 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);
++#ifndef __FSL_DIU_FB_H__
++#define __FSL_DIU_FB_H__
+
-+ 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);
-+ }
++/* Arbitrary threshold to determine the allocation method
++ * See mpc8610fb_set_par(), map_video_memory(), and unmap_video_memory()
++ */
++#define MEM_ALLOC_THRESHOLD (1024*768*4+32)
++/* Minimum value that the pixel clock can be set to in pico seconds
++ * This is determined by platform clock/3 where the minimum platform
++ * clock is 533MHz. This gives 5629 pico seconds.
++ */
++#define MIN_PIX_CLK 5629
++#define MAX_PIX_CLK 96096
+
-+ /* 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);
++#include <linux/types.h>
++
++struct mfb_alpha {
++ int enable;
++ int alpha;
++};
++
++struct mfb_chroma_key {
++ int enable;
++ __u8 red_max;
++ __u8 green_max;
++ __u8 blue_max;
++ __u8 red_min;
++ __u8 green_min;
++ __u8 blue_min;
++};
++
++struct aoi_display_offset {
++ int x_aoi_d;
++ int y_aoi_d;
++};
++
++#define MFB_SET_CHROMA_KEY _IOW('M', 1, struct mfb_chroma_key)
++#define MFB_WAIT_FOR_VSYNC _IOW('F', 0x20, u_int32_t)
++#define MFB_SET_BRIGHTNESS _IOW('M', 3, __u8)
++
++#define MFB_SET_ALPHA 0x80014d00
++#define MFB_GET_ALPHA 0x40014d00
++#define MFB_SET_AOID 0x80084d04
++#define MFB_GET_AOID 0x40084d04
++#define MFB_SET_PIXFMT 0x80014d08
++#define MFB_GET_PIXFMT 0x40014d08
++
++#define FBIOGET_GWINFO 0x46E0
++#define FBIOPUT_GWINFO 0x46E1
++
++#ifdef __KERNEL__
++#include <linux/spinlock.h>
++
++/*
++ * These are the fields of area descriptor(in DDR memory) for every plane
++ */
++struct diu_ad {
++ /* Word 0(32-bit) in DDR memory */
++/* __u16 comp; */
++/* __u16 pixel_s:2; */
++/* __u16 pallete:1; */
++/* __u16 red_c:2; */
++/* __u16 green_c:2; */
++/* __u16 blue_c:2; */
++/* __u16 alpha_c:3; */
++/* __u16 byte_f:1; */
++/* __u16 res0:3; */
++
++ __be32 pix_fmt; /* hard coding pixel format */
++
++ /* Word 1(32-bit) in DDR memory */
++ __le32 addr;
++
++ /* Word 2(32-bit) in DDR memory */
++/* __u32 delta_xs:11; */
++/* __u32 res1:1; */
++/* __u32 delta_ys:11; */
++/* __u32 res2:1; */
++/* __u32 g_alpha:8; */
++ __le32 src_size_g_alpha;
++
++ /* Word 3(32-bit) in DDR memory */
++/* __u32 delta_xi:11; */
++/* __u32 res3:5; */
++/* __u32 delta_yi:11; */
++/* __u32 res4:3; */
++/* __u32 flip:2; */
++ __le32 aoi_size;
++
++ /* Word 4(32-bit) in DDR memory */
++ /*__u32 offset_xi:11;
++ __u32 res5:5;
++ __u32 offset_yi:11;
++ __u32 res6:5;
++ */
++ __le32 offset_xyi;
++
++ /* Word 5(32-bit) in DDR memory */
++ /*__u32 offset_xd:11;
++ __u32 res7:5;
++ __u32 offset_yd:11;
++ __u32 res8:5; */
++ __le32 offset_xyd;
++
++
++ /* Word 6(32-bit) in DDR memory */
++ __u8 ckmax_r;
++ __u8 ckmax_g;
++ __u8 ckmax_b;
++ __u8 res9;
++
++ /* Word 7(32-bit) in DDR memory */
++ __u8 ckmin_r;
++ __u8 ckmin_g;
++ __u8 ckmin_b;
++ __u8 res10;
++/* __u32 res10:8; */
++
++ /* Word 8(32-bit) in DDR memory */
++ __le32 next_ad;
++
++ /* Word 9(32-bit) in DDR memory, just for 64-bit aligned */
++ __u32 paddr;
++} __attribute__ ((packed));
++
++/* DIU register map */
++struct diu {
++ __be32 desc[3];
++ __be32 gamma;
++ __be32 pallete;
++ __be32 cursor;
++ __be32 curs_pos;
++ __be32 diu_mode;
++ __be32 bgnd;
++ __be32 bgnd_wb;
++ __be32 disp_size;
++ __be32 wb_size;
++ __be32 wb_mem_addr;
++ __be32 hsyn_para;
++ __be32 vsyn_para;
++ __be32 syn_pol;
++ __be32 thresholds;
++ __be32 int_status;
++ __be32 int_mask;
++ __be32 colorbar[8];
++ __be32 filling;
++ __be32 plut;
++} __attribute__ ((packed));
++
++struct diu_hw {
++ struct diu *diu_reg;
++ spinlock_t reg_lock;
++
++ __u32 mode; /* DIU operation mode */
++};
++
++struct diu_addr {
++ __u8 __iomem *vaddr; /* Virtual address */
++ dma_addr_t paddr; /* Physical address */
++ __u32 offset;
++};
++
++struct diu_pool {
++ struct diu_addr ad;
++ struct diu_addr gamma;
++ struct diu_addr pallete;
++ struct diu_addr cursor;
++};
++
++#define FSL_DIU_BASE_OFFSET 0x2C000 /* Offset of DIU */
++#define INT_LCDC 64 /* DIU interrupt number */
++
++#define FSL_AOI_NUM 6 /* 5 AOIs and one dummy AOI */
++ /* 1 for plane 0, 2 for plane 1&2 each */
++
++/* Minimum X and Y resolutions */
++#define MIN_XRES 64
++#define MIN_YRES 64
++
++/* HW cursor parameters */
++#define MAX_CURS 32
++
++/* Modes of operation of DIU */
++#define MFB_MODE0 0 /* DIU off */
++#define MFB_MODE1 1 /* All three planes output to display */
++#define MFB_MODE2 2 /* Plane 1 to display, planes 2+3 written back*/
++#define MFB_MODE3 3 /* All three planes written back to memory */
++#define MFB_MODE4 4 /* Color bar generation */
++
++/* INT_STATUS/INT_MASK field descriptions */
++#define INT_VSYNC 0x01 /* Vsync interrupt */
++#define INT_VSYNC_WB 0x02 /* Vsync interrupt for write back operation */
++#define INT_UNDRUN 0x04 /* Under run exception interrupt */
++#define INT_PARERR 0x08 /* Display parameters error interrupt */
++#define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */
++
++/* Panels'operation modes */
++#define MFB_TYPE_OUTPUT 0 /* Panel output to display */
++#define MFB_TYPE_OFF 1 /* Panel off */
++#define MFB_TYPE_WB 2 /* Panel written back to memory */
++#define MFB_TYPE_TEST 3 /* Panel generate color bar */
++
++#endif /* __KERNEL__ */
++#endif /* __FSL_DIU_FB_H__ */
+diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig
+index 7608429..c5d8ba4 100644
+--- a/drivers/video/geode/Kconfig
++++ b/drivers/video/geode/Kconfig
+@@ -38,26 +38,6 @@ config FB_GEODE_GX
+
+ If unsure, say N.
+
+-config FB_GEODE_GX_SET_FBSIZE
+- bool "Manually specify the Geode GX framebuffer size"
+- depends on FB_GEODE_GX
+- default n
+- ---help---
+- If you want to manually specify the size of your GX framebuffer,
+- say Y here, otherwise say N to dynamically probe it.
+-
+- Say N unless you know what you are doing.
+-
+-config FB_GEODE_GX_FBSIZE
+- hex "Size of the GX framebuffer, in bytes"
+- depends on FB_GEODE_GX_SET_FBSIZE
+- default "0x1600000"
+- ---help---
+- Specify the size of the GX framebuffer. Normally, you will
+- want this to be MB aligned. Common values are 0x80000 (8MB)
+- and 0x1600000 (16MB). Don't change this unless you know what
+- you are doing
+-
+ config FB_GEODE_GX1
+ tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)"
+ depends on FB && FB_GEODE && EXPERIMENTAL
+diff --git a/drivers/video/geode/Makefile b/drivers/video/geode/Makefile
+index 957304b..5c98da1 100644
+--- a/drivers/video/geode/Makefile
++++ b/drivers/video/geode/Makefile
+@@ -5,5 +5,5 @@ obj-$(CONFIG_FB_GEODE_GX) += gxfb.o
+ obj-$(CONFIG_FB_GEODE_LX) += lxfb.o
+
+ gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o
+-gxfb-objs := gxfb_core.o display_gx.o video_gx.o
++gxfb-objs := gxfb_core.o display_gx.o video_gx.o suspend_gx.o
+ lxfb-objs := lxfb_core.o lxfb_ops.o
+diff --git a/drivers/video/geode/display_gx.c b/drivers/video/geode/display_gx.c
+index 0f16e4b..e759895 100644
+--- a/drivers/video/geode/display_gx.c
++++ b/drivers/video/geode/display_gx.c
+@@ -17,31 +17,40 @@
+ #include <asm/io.h>
+ #include <asm/div64.h>
+ #include <asm/delay.h>
++#include <asm/geode.h>
+
+-#include "geodefb.h"
+-#include "display_gx.h"
++#include "gxfb.h"
+
+-#ifdef CONFIG_FB_GEODE_GX_SET_FBSIZE
+-unsigned int gx_frame_buffer_size(void)
+-{
+- return CONFIG_FB_GEODE_GX_FBSIZE;
+-}
+-#else
+ unsigned int gx_frame_buffer_size(void)
+ {
+ unsigned int val;
+
+- /* FB size is reported by a virtual register */
++ if (!geode_has_vsa2()) {
++ uint32_t hi, lo;
++
++ /* The number of pages is (PMAX - PMIN)+1 */
++ rdmsr(MSR_GLIU_P2D_RO0, lo, hi);
++
++ /* PMAX */
++ val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20);
++ /* PMIN */
++ val -= (lo & 0x000fffff);
++ val += 1;
++
++ /* The page size is 4k */
++ return (val << 12);
+ }
+
-+ return;
-+}
++ /* FB size can be obtained from the VSA II */
+ /* Virtual register class = 0x02 */
+ /* VG_MEM_SIZE(512Kb units) = 0x00 */
+
+- outw(0xFC53, 0xAC1C);
+- outw(0x0200, 0xAC1C);
++ outw(VSA_VR_UNLOCK, VSA_VRC_INDEX);
++ outw(VSA_VR_MEM_SIZE, VSA_VRC_INDEX);
+
+- val = (unsigned int)(inw(0xAC1E)) & 0xFFl;
++ val = (unsigned int)(inw(VSA_VRC_DATA)) & 0xFFl;
+ return (val << 19);
+ }
+-#endif
+
+ int gx_line_delta(int xres, int bpp)
+ {
+@@ -49,75 +58,76 @@ int gx_line_delta(int xres, int bpp)
+ return (xres * (bpp >> 3) + 7) & ~0x7;
+ }
+
+-static void gx_set_mode(struct fb_info *info)
++void gx_set_mode(struct fb_info *info)
+ {
+- struct geodefb_par *par = info->par;
++ struct gxfb_par *par = info->par;
+ u32 gcfg, dcfg;
+ int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal;
+ int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
+
+ /* Unlock the display controller registers. */
+- readl(par->dc_regs + DC_UNLOCK);
+- writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
++ write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
+
+- gcfg = readl(par->dc_regs + DC_GENERAL_CFG);
+- dcfg = readl(par->dc_regs + DC_DISPLAY_CFG);
++ gcfg = read_dc(par, DC_GENERAL_CFG);
++ dcfg = read_dc(par, DC_DISPLAY_CFG);
+
+ /* Disable the timing generator. */
+- dcfg &= ~(DC_DCFG_TGEN);
+- writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
++ dcfg &= ~DC_DISPLAY_CFG_TGEN;
++ write_dc(par, DC_DISPLAY_CFG, dcfg);
+
+ /* Wait for pending memory requests before disabling the FIFO load. */
+ udelay(100);
+
+ /* Disable FIFO load and compression. */
+- gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
+- writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
++ gcfg &= ~(DC_GENERAL_CFG_DFLE | DC_GENERAL_CFG_CMPE |
++ DC_GENERAL_CFG_DECE);
++ write_dc(par, DC_GENERAL_CFG, gcfg);
+
+ /* Setup DCLK and its divisor. */
+- par->vid_ops->set_dclk(info);
++ gx_set_dclk_frequency(info);
+
+ /*
+ * Setup new mode.
+ */
+
+ /* Clear all unused feature bits. */
+- gcfg &= DC_GCFG_YUVM | DC_GCFG_VDSE;
++ gcfg &= DC_GENERAL_CFG_YUVM | DC_GENERAL_CFG_VDSE;
+ dcfg = 0;
+
+ /* Set FIFO priority (default 6/5) and enable. */
+ /* FIXME: increase fifo priority for 1280x1024 and higher modes? */
+- gcfg |= (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE;
++ gcfg |= (6 << DC_GENERAL_CFG_DFHPEL_SHIFT) |
++ (5 << DC_GENERAL_CFG_DFHPSL_SHIFT) | DC_GENERAL_CFG_DFLE;
+
+ /* Framebuffer start offset. */
+- writel(0, par->dc_regs + DC_FB_ST_OFFSET);
++ write_dc(par, DC_FB_ST_OFFSET, 0);
+
+ /* Line delta and line buffer length. */
+- writel(info->fix.line_length >> 3, par->dc_regs + DC_GFX_PITCH);
+- writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
+- par->dc_regs + DC_LINE_SIZE);
++ write_dc(par, DC_GFX_PITCH, info->fix.line_length >> 3);
++ write_dc(par, DC_LINE_SIZE,
++ ((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2);
+
+
+ /* Enable graphics and video data and unmask address lines. */
+- dcfg |= DC_DCFG_GDEN | DC_DCFG_VDEN | DC_DCFG_A20M | DC_DCFG_A18M;
++ dcfg |= DC_DISPLAY_CFG_GDEN | DC_DISPLAY_CFG_VDEN |
++ DC_DISPLAY_CFG_A20M | DC_DISPLAY_CFG_A18M;
+
+ /* Set pixel format. */
+ switch (info->var.bits_per_pixel) {
+ case 8:
+- dcfg |= DC_DCFG_DISP_MODE_8BPP;
++ dcfg |= DC_DISPLAY_CFG_DISP_MODE_8BPP;
+ break;
+ case 16:
+- dcfg |= DC_DCFG_DISP_MODE_16BPP;
+- dcfg |= DC_DCFG_16BPP_MODE_565;
++ dcfg |= DC_DISPLAY_CFG_DISP_MODE_16BPP;
+ break;
+ case 32:
+- dcfg |= DC_DCFG_DISP_MODE_24BPP;
+- dcfg |= DC_DCFG_PALB;
++ dcfg |= DC_DISPLAY_CFG_DISP_MODE_24BPP;
++ dcfg |= DC_DISPLAY_CFG_PALB;
+ break;
+ }
+
+ /* Enable timing generator. */
+- dcfg |= DC_DCFG_TGEN;
++ dcfg |= DC_DISPLAY_CFG_TGEN;
+
+ /* Horizontal and vertical timings. */
+ hactive = info->var.xres;
+@@ -134,28 +144,34 @@ static void gx_set_mode(struct fb_info *info)
+ vblankend = vsyncend + info->var.upper_margin;
+ vtotal = vblankend;
+
+- writel((hactive - 1) | ((htotal - 1) << 16), par->dc_regs + DC_H_ACTIVE_TIMING);
+- writel((hblankstart - 1) | ((hblankend - 1) << 16), par->dc_regs + DC_H_BLANK_TIMING);
+- writel((hsyncstart - 1) | ((hsyncend - 1) << 16), par->dc_regs + DC_H_SYNC_TIMING);
++ write_dc(par, DC_H_ACTIVE_TIMING, (hactive - 1) |
++ ((htotal - 1) << 16));
++ write_dc(par, DC_H_BLANK_TIMING, (hblankstart - 1) |
++ ((hblankend - 1) << 16));
++ write_dc(par, DC_H_SYNC_TIMING, (hsyncstart - 1) |
++ ((hsyncend - 1) << 16));
+
+- writel((vactive - 1) | ((vtotal - 1) << 16), par->dc_regs + DC_V_ACTIVE_TIMING);
+- writel((vblankstart - 1) | ((vblankend - 1) << 16), par->dc_regs + DC_V_BLANK_TIMING);
+- writel((vsyncstart - 1) | ((vsyncend - 1) << 16), par->dc_regs + DC_V_SYNC_TIMING);
++ write_dc(par, DC_V_ACTIVE_TIMING, (vactive - 1) |
++ ((vtotal - 1) << 16));
++ write_dc(par, DC_V_BLANK_TIMING, (vblankstart - 1) |
++ ((vblankend - 1) << 16));
++ write_dc(par, DC_V_SYNC_TIMING, (vsyncstart - 1) |
++ ((vsyncend - 1) << 16));
+
+ /* Write final register values. */
+- writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
+- writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
++ write_dc(par, DC_DISPLAY_CFG, dcfg);
++ write_dc(par, DC_GENERAL_CFG, gcfg);
+
+- par->vid_ops->configure_display(info);
++ gx_configure_display(info);
+
+ /* Relock display controller registers */
+- writel(0, par->dc_regs + DC_UNLOCK);
++ write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
+ }
+
+-static void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno,
+- unsigned red, unsigned green, unsigned blue)
++void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno,
++ unsigned red, unsigned green, unsigned blue)
+ {
+- struct geodefb_par *par = info->par;
++ struct gxfb_par *par = info->par;
+ int val;
+
+ /* Hardware palette is in RGB 8-8-8 format. */
+@@ -163,11 +179,6 @@ static void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno,
+ val |= (green) & 0x00ff00;
+ val |= (blue >> 8) & 0x0000ff;
+
+- writel(regno, par->dc_regs + DC_PAL_ADDRESS);
+- writel(val, par->dc_regs + DC_PAL_DATA);
++ write_dc(par, DC_PAL_ADDRESS, regno);
++ write_dc(par, DC_PAL_DATA, val);
+ }
+-
+-struct geode_dc_ops gx_dc_ops = {
+- .set_mode = gx_set_mode,
+- .set_palette_reg = gx_set_hw_palette_reg,
+-};
+diff --git a/drivers/video/geode/display_gx.h b/drivers/video/geode/display_gx.h
+deleted file mode 100644
+index 0af33f3..0000000
+--- a/drivers/video/geode/display_gx.h
++++ /dev/null
+@@ -1,101 +0,0 @@
+-/*
+- * Geode GX display controller
+- *
+- * Copyright (C) 2006 Arcom Control Systems Ltd.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- */
+-#ifndef __DISPLAY_GX_H__
+-#define __DISPLAY_GX_H__
+-
+-unsigned int gx_frame_buffer_size(void);
+-int gx_line_delta(int xres, int bpp);
+-
+-extern struct geode_dc_ops gx_dc_ops;
+-
+-/* MSR that tells us if a TFT or CRT is attached */
+-#define GLD_MSR_CONFIG 0xC0002001
+-#define GLD_MSR_CONFIG_DM_FP 0x40
+-
+-/* Display controller registers */
+-
+-#define DC_UNLOCK 0x00
+-# define DC_UNLOCK_CODE 0x00004758
+-
+-#define DC_GENERAL_CFG 0x04
+-# define DC_GCFG_DFLE 0x00000001
+-# define DC_GCFG_CURE 0x00000002
+-# define DC_GCFG_ICNE 0x00000004
+-# define DC_GCFG_VIDE 0x00000008
+-# define DC_GCFG_CMPE 0x00000020
+-# define DC_GCFG_DECE 0x00000040
+-# define DC_GCFG_VGAE 0x00000080
+-# define DC_GCFG_DFHPSL_MASK 0x00000F00
+-# define DC_GCFG_DFHPSL_POS 8
+-# define DC_GCFG_DFHPEL_MASK 0x0000F000
+-# define DC_GCFG_DFHPEL_POS 12
+-# define DC_GCFG_STFM 0x00010000
+-# define DC_GCFG_FDTY 0x00020000
+-# define DC_GCFG_VGAFT 0x00040000
+-# define DC_GCFG_VDSE 0x00080000
+-# define DC_GCFG_YUVM 0x00100000
+-# define DC_GCFG_VFSL 0x00800000
+-# define DC_GCFG_SIGE 0x01000000
+-# define DC_GCFG_SGRE 0x02000000
+-# define DC_GCFG_SGFR 0x04000000
+-# define DC_GCFG_CRC_MODE 0x08000000
+-# define DC_GCFG_DIAG 0x10000000
+-# define DC_GCFG_CFRW 0x20000000
+-
+-#define DC_DISPLAY_CFG 0x08
+-# define DC_DCFG_TGEN 0x00000001
+-# define DC_DCFG_GDEN 0x00000008
+-# define DC_DCFG_VDEN 0x00000010
+-# define DC_DCFG_TRUP 0x00000040
+-# define DC_DCFG_DISP_MODE_MASK 0x00000300
+-# define DC_DCFG_DISP_MODE_8BPP 0x00000000
+-# define DC_DCFG_DISP_MODE_16BPP 0x00000100
+-# define DC_DCFG_DISP_MODE_24BPP 0x00000200
+-# define DC_DCFG_16BPP_MODE_MASK 0x00000c00
+-# define DC_DCFG_16BPP_MODE_565 0x00000000
+-# define DC_DCFG_16BPP_MODE_555 0x00000100
+-# define DC_DCFG_16BPP_MODE_444 0x00000200
+-# define DC_DCFG_DCEN 0x00080000
+-# define DC_DCFG_PALB 0x02000000
+-# define DC_DCFG_FRLK 0x04000000
+-# define DC_DCFG_VISL 0x08000000
+-# define DC_DCFG_FRSL 0x20000000
+-# define DC_DCFG_A18M 0x40000000
+-# define DC_DCFG_A20M 0x80000000
+-
+-#define DC_FB_ST_OFFSET 0x10
+-
+-#define DC_LINE_SIZE 0x30
+-# define DC_LINE_SIZE_FB_LINE_SIZE_MASK 0x000007ff
+-# define DC_LINE_SIZE_FB_LINE_SIZE_POS 0
+-# define DC_LINE_SIZE_CB_LINE_SIZE_MASK 0x007f0000
+-# define DC_LINE_SIZE_CB_LINE_SIZE_POS 16
+-# define DC_LINE_SIZE_VID_LINE_SIZE_MASK 0xff000000
+-# define DC_LINE_SIZE_VID_LINE_SIZE_POS 24
+-
+-#define DC_GFX_PITCH 0x34
+-# define DC_GFX_PITCH_FB_PITCH_MASK 0x0000ffff
+-# define DC_GFX_PITCH_FB_PITCH_POS 0
+-# define DC_GFX_PITCH_CB_PITCH_MASK 0xffff0000
+-# define DC_GFX_PITCH_CB_PITCH_POS 16
+-
+-#define DC_H_ACTIVE_TIMING 0x40
+-#define DC_H_BLANK_TIMING 0x44
+-#define DC_H_SYNC_TIMING 0x48
+-#define DC_V_ACTIVE_TIMING 0x50
+-#define DC_V_BLANK_TIMING 0x54
+-#define DC_V_SYNC_TIMING 0x58
+-
+-#define DC_PAL_ADDRESS 0x70
+-#define DC_PAL_DATA 0x74
+-
+-#define DC_GLIU0_MEM_OFFSET 0x84
+-#endif /* !__DISPLAY_GX1_H__ */
+diff --git a/drivers/video/geode/gxfb.h b/drivers/video/geode/gxfb.h
+new file mode 100644
+index 0000000..16a96f8
+--- /dev/null
++++ b/drivers/video/geode/gxfb.h
+@@ -0,0 +1,358 @@
++/*
++ * Copyright (C) 2008 Andres Salomon <dilinger at debian.org>
++ *
++ * Geode GX2 header 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 of the License, or
++ * (at your option) any later version.
++ */
++#ifndef _GXFB_H_
++#define _GXFB_H_
++
++#include <linux/io.h>
++
++#define GP_REG_COUNT (0x50 / 4)
++#define DC_REG_COUNT (0x90 / 4)
++#define VP_REG_COUNT (0x138 / 8)
++#define FP_REG_COUNT (0x68 / 8)
++
++#define DC_PAL_COUNT 0x104
++
++struct gxfb_par {
++ int enable_crt;
++ void __iomem *dc_regs;
++ void __iomem *vid_regs;
++ void __iomem *gp_regs;
++#ifdef CONFIG_PM
++ int powered_down;
++
++ /* register state, for power management functionality */
++ struct {
++ uint64_t padsel;
++ uint64_t dotpll;
++ } msr;
++
++ uint32_t gp[GP_REG_COUNT];
++ uint32_t dc[DC_REG_COUNT];
++ uint64_t vp[VP_REG_COUNT];
++ uint64_t fp[FP_REG_COUNT];
++
++ uint32_t pal[DC_PAL_COUNT];
++#endif
++};
++
++unsigned int gx_frame_buffer_size(void);
++int gx_line_delta(int xres, int bpp);
++void gx_set_mode(struct fb_info *info);
++void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno,
++ unsigned red, unsigned green, unsigned blue);
++
++void gx_set_dclk_frequency(struct fb_info *info);
++void gx_configure_display(struct fb_info *info);
++int gx_blank_display(struct fb_info *info, int blank_mode);
++
++#ifdef CONFIG_PM
++int gx_powerdown(struct fb_info *info);
++int gx_powerup(struct fb_info *info);
++#endif
++
++
++/* Graphics Processor registers (table 6-23 from the data book) */
++enum gp_registers {
++ GP_DST_OFFSET = 0,
++ GP_SRC_OFFSET,
++ GP_STRIDE,
++ GP_WID_HEIGHT,
++
++ GP_SRC_COLOR_FG,
++ GP_SRC_COLOR_BG,
++ GP_PAT_COLOR_0,
++ GP_PAT_COLOR_1,
++
++ GP_PAT_COLOR_2,
++ GP_PAT_COLOR_3,
++ GP_PAT_COLOR_4,
++ GP_PAT_COLOR_5,
++
++ GP_PAT_DATA_0,
++ GP_PAT_DATA_1,
++ GP_RASTER_MODE,
++ GP_VECTOR_MODE,
++
++ GP_BLT_MODE,
++ GP_BLT_STATUS,
++ GP_HST_SRC,
++ GP_BASE_OFFSET, /* 0x4c */
++};
++
++#define GP_BLT_STATUS_BLT_PENDING (1 << 2)
++#define GP_BLT_STATUS_BLT_BUSY (1 << 0)
++
++
++/* Display Controller registers (table 6-38 from the data book) */
++enum dc_registers {
++ DC_UNLOCK = 0,
++ DC_GENERAL_CFG,
++ DC_DISPLAY_CFG,
++ DC_RSVD_0,
++
++ DC_FB_ST_OFFSET,
++ DC_CB_ST_OFFSET,
++ DC_CURS_ST_OFFSET,
++ DC_ICON_ST_OFFSET,
++
++ DC_VID_Y_ST_OFFSET,
++ DC_VID_U_ST_OFFSET,
++ DC_VID_V_ST_OFFSET,
++ DC_RSVD_1,
++
++ DC_LINE_SIZE,
++ DC_GFX_PITCH,
++ DC_VID_YUV_PITCH,
++ DC_RSVD_2,
++
++ DC_H_ACTIVE_TIMING,
++ DC_H_BLANK_TIMING,
++ DC_H_SYNC_TIMING,
++ DC_RSVD_3,
++
++ DC_V_ACTIVE_TIMING,
++ DC_V_BLANK_TIMING,
++ DC_V_SYNC_TIMING,
++ DC_RSVD_4,
++
++ DC_CURSOR_X,
++ DC_CURSOR_Y,
++ DC_ICON_X,
++ DC_LINE_CNT,
++
++ DC_PAL_ADDRESS,
++ DC_PAL_DATA,
++ DC_DFIFO_DIAG,
++ DC_CFIFO_DIAG,
++
++ DC_VID_DS_DELTA,
++ DC_GLIU0_MEM_OFFSET,
++ DC_RSVD_5,
++ DC_DV_ACC, /* 0x8c */
++};
++
++#define DC_UNLOCK_LOCK 0x00000000
++#define DC_UNLOCK_UNLOCK 0x00004758 /* magic value */
++
++#define DC_GENERAL_CFG_YUVM (1 << 20)
++#define DC_GENERAL_CFG_VDSE (1 << 19)
++#define DC_GENERAL_CFG_DFHPEL_SHIFT 12
++#define DC_GENERAL_CFG_DFHPSL_SHIFT 8
++#define DC_GENERAL_CFG_DECE (1 << 6)
++#define DC_GENERAL_CFG_CMPE (1 << 5)
++#define DC_GENERAL_CFG_VIDE (1 << 3)
++#define DC_GENERAL_CFG_ICNE (1 << 2)
++#define DC_GENERAL_CFG_CURE (1 << 1)
++#define DC_GENERAL_CFG_DFLE (1 << 0)
++
++#define DC_DISPLAY_CFG_A20M (1 << 31)
++#define DC_DISPLAY_CFG_A18M (1 << 30)
++#define DC_DISPLAY_CFG_PALB (1 << 25)
++#define DC_DISPLAY_CFG_DISP_MODE_24BPP (1 << 9)
++#define DC_DISPLAY_CFG_DISP_MODE_16BPP (1 << 8)
++#define DC_DISPLAY_CFG_DISP_MODE_8BPP (0)
++#define DC_DISPLAY_CFG_VDEN (1 << 4)
++#define DC_DISPLAY_CFG_GDEN (1 << 3)
++#define DC_DISPLAY_CFG_TGEN (1 << 0)
++
++
++/*
++ * Video Processor registers (table 6-54).
++ * There is space for 64 bit values, but we never use more than the
++ * lower 32 bits. The actual register save/restore code only bothers
++ * to restore those 32 bits.
++ */
++enum vp_registers {
++ VP_VCFG = 0,
++ VP_DCFG,
++
++ VP_VX,
++ VP_VY,
++
++ VP_VS,
++ VP_VCK,
++
++ VP_VCM,
++ VP_GAR,
++
++ VP_GDR,
++ VP_RSVD_0,
++
++ VP_MISC,
++ VP_CCS,
++
++ VP_RSVD_1,
++ VP_RSVD_2,
++
++ VP_RSVD_3,
++ VP_VDC,
+
-+/* 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;
++ VP_VCO,
++ VP_CRC,
+
-+ spin_lock_irqsave(&priv->lock, flags);
++ VP_CRC32,
++ VP_VDE,
+
-+ if (priv->write_urb_in_use) {
-+ dev_dbg(&port->dev, "write urb still used\n");
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+ return;
-+ }
++ VP_CCK,
++ VP_CCM,
+
-+ /* 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);
++ VP_CC1,
++ VP_CC2,
+
-+ if (count == 0) {
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+ return;
-+ }
++ VP_A1X,
++ VP_A1Y,
+
-+ /* update the urb status */
-+ priv->write_urb_in_use = 1;
++ VP_A1C,
++ VP_A1T,
+
-+ spin_unlock_irqrestore(&priv->lock, flags);
++ VP_A2X,
++ VP_A2Y,
+
-+ port->write_urb->transfer_buffer_length = count;
-+ port->write_urb->dev = port->serial->dev;
++ VP_A2C,
++ VP_A2T,
+
-+ 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 */
-+ }
++ VP_A3X,
++ VP_A3Y,
+
++ VP_A3C,
++ VP_A3T,
+
-+ schedule_work(&port->work);
-+}
++ VP_VRR,
++ VP_AWT,
+
-+/* 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;
++ VP_VTM, /* 0x130 */
++};
+
-+ 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;
-+ }
++#define VP_VCFG_VID_EN (1 << 0)
+
-+ priv->write_urb_in_use = 0;
++#define VP_DCFG_DAC_VREF (1 << 26)
++#define VP_DCFG_GV_GAM (1 << 21)
++#define VP_DCFG_VG_CK (1 << 20)
++#define VP_DCFG_CRT_SYNC_SKW_DEFAULT (1 << 16)
++#define VP_DCFG_CRT_SYNC_SKW ((1 << 14) | (1 << 15) | (1 << 16))
++#define VP_DCFG_CRT_VSYNC_POL (1 << 9)
++#define VP_DCFG_CRT_HSYNC_POL (1 << 8)
++#define VP_DCFG_FP_DATA_EN (1 << 7) /* undocumented */
++#define VP_DCFG_FP_PWR_EN (1 << 6) /* undocumented */
++#define VP_DCFG_DAC_BL_EN (1 << 3)
++#define VP_DCFG_VSYNC_EN (1 << 2)
++#define VP_DCFG_HSYNC_EN (1 << 1)
++#define VP_DCFG_CRT_EN (1 << 0)
+
-+ /* send any buffered data */
-+ spcp8x5_send(port);
-+}
++#define VP_MISC_GAM_EN (1 << 0)
++#define VP_MISC_DACPWRDN (1 << 10)
++#define VP_MISC_APWRDN (1 << 11)
+
-+/* 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);
++/*
++ * Flat Panel registers (table 6-55).
++ * Also 64 bit registers; see above note about 32-bit handling.
++ */
+
-+ if (!count)
-+ return count;
++/* we're actually in the VP register space, starting at address 0x400 */
++#define VP_FP_START 0x400
+
-+ spin_lock_irqsave(&priv->lock, flags);
-+ count = put_ringbuf(priv->buf, buf, count);
-+ spin_unlock_irqrestore(&priv->lock, flags);
++enum fp_registers {
++ FP_PT1 = 0,
++ FP_PT2,
+
-+ spcp8x5_send(port);
++ FP_PM,
++ FP_DFC,
+
-+ return count;
-+}
++ FP_BLFSR,
++ FP_RLFSR,
+
-+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;
++ FP_FMI,
++ FP_FMD,
+
-+ spin_lock_irqsave(&priv->lock, flags);
-+ prevstatus = priv->line_status;
-+ spin_unlock_irqrestore(&priv->lock, flags);
++ FP_RSVD_0,
++ FP_DCA,
+
-+ while (1) {
-+ /* wake up in bulk read */
-+ interruptible_sleep_on(&priv->delta_msr_wait);
++ FP_DMD,
++ FP_CRC,
+
-+ /* see if a signal did it */
-+ if (signal_pending(current))
-+ return -ERESTARTSYS;
++ FP_FBB, /* 0x460 */
++};
+
-+ spin_lock_irqsave(&priv->lock, flags);
-+ status = priv->line_status;
-+ spin_unlock_irqrestore(&priv->lock, flags);
++#define FP_PT1_VSIZE_SHIFT 16 /* undocumented? */
++#define FP_PT1_VSIZE_MASK 0x7FF0000 /* undocumented? */
+
-+ changed = prevstatus^status;
++#define FP_PT2_HSP (1 << 22)
++#define FP_PT2_VSP (1 << 23)
+
-+ 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;
++#define FP_PM_P (1 << 24) /* panel power on */
++#define FP_PM_PANEL_PWR_UP (1 << 3) /* r/o */
++#define FP_PM_PANEL_PWR_DOWN (1 << 2) /* r/o */
++#define FP_PM_PANEL_OFF (1 << 1) /* r/o */
++#define FP_PM_PANEL_ON (1 << 0) /* r/o */
+
-+ prevstatus = status;
-+ }
-+ /* NOTREACHED */
-+ return 0;
-+}
++#define FP_DFC_NFI ((1 << 4) | (1 << 5) | (1 << 6))
+
-+static int spcp8x5_ioctl(struct usb_serial_port *port, struct file *file,
-+ unsigned int cmd, unsigned long arg)
++
++/* register access functions */
++
++static inline uint32_t read_gp(struct gxfb_par *par, int reg)
+{
-+ dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
++ return readl(par->gp_regs + 4*reg);
++}
+
-+ switch (cmd) {
-+ case TIOCMIWAIT:
-+ dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
-+ return spcp8x5_wait_modem_info(port, arg);
++static inline void write_gp(struct gxfb_par *par, int reg, uint32_t val)
++{
++ writel(val, par->gp_regs + 4*reg);
++}
+
-+ default:
-+ dbg("%s not supported = 0x%04x", __func__, cmd);
-+ break;
-+ }
++static inline uint32_t read_dc(struct gxfb_par *par, int reg)
++{
++ return readl(par->dc_regs + 4*reg);
++}
+
-+ return -ENOIOCTLCMD;
++static inline void write_dc(struct gxfb_par *par, int reg, uint32_t val)
++{
++ writel(val, par->dc_regs + 4*reg);
+}
+
-+static int spcp8x5_tiocmset(struct usb_serial_port *port, struct file *file,
-+ unsigned int set, unsigned int clear)
++static inline uint32_t read_vp(struct gxfb_par *par, int reg)
+{
-+ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
-+ unsigned long flags;
-+ u8 control;
++ return readl(par->vid_regs + 8*reg);
++}
+
-+ 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);
++static inline void write_vp(struct gxfb_par *par, int reg, uint32_t val)
++{
++ writel(val, par->vid_regs + 8*reg);
++}
+
-+ return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
++static inline uint32_t read_fp(struct gxfb_par *par, int reg)
++{
++ return readl(par->vid_regs + 8*reg + VP_FP_START);
+}
+
-+static int spcp8x5_tiocmget(struct usb_serial_port *port, struct file *file)
++static inline void write_fp(struct gxfb_par *par, int reg, uint32_t val)
+{
-+ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
-+ unsigned long flags;
-+ unsigned int mcr;
-+ unsigned int status;
-+ unsigned int result;
++ writel(val, par->vid_regs + 8*reg + VP_FP_START);
++}
+
-+ 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);
++/* MSRs are defined in asm/geode.h; their bitfields are here */
+
-+ return result;
-+}
++#define MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 (1 << 3)
++#define MSR_GLCP_SYS_RSTPLL_DOTPREMULT2 (1 << 2)
++#define MSR_GLCP_SYS_RSTPLL_DOTPREDIV2 (1 << 1)
+
-+/* 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;
++#define MSR_GLCP_DOTPLL_LOCK (1 << 25) /* r/o */
++#define MSR_GLCP_DOTPLL_BYPASS (1 << 15)
++#define MSR_GLCP_DOTPLL_DOTRESET (1 << 0)
+
-+ spin_lock_irqsave(&priv->lock, flags);
-+ room = ringbuf_avail_space(priv->buf);
-+ spin_unlock_irqrestore(&priv->lock, flags);
++#define MSR_GX_MSR_PADSEL_MASK 0x3FFFFFFF /* undocumented? */
++#define MSR_GX_MSR_PADSEL_TFT 0x1FFFFFFF /* undocumented? */
+
-+ return room;
++#define MSR_GX_GLD_MSR_CONFIG_FP (1 << 3)
++
++#endif
+diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c
+index cf841ef..de2b8f9 100644
+--- a/drivers/video/geode/gxfb_core.c
++++ b/drivers/video/geode/gxfb_core.c
+@@ -28,17 +28,20 @@
+ #include <linux/slab.h>
+ #include <linux/delay.h>
+ #include <linux/fb.h>
++#include <linux/console.h>
++#include <linux/suspend.h>
+ #include <linux/init.h>
+ #include <linux/pci.h>
++#include <asm/geode.h>
+
+-#include "geodefb.h"
+-#include "display_gx.h"
+-#include "video_gx.h"
++#include "gxfb.h"
+
+ static char *mode_option;
++static int vram;
++static int vt_switch;
+
+ /* Modes relevant to the GX (taken from modedb.c) */
+-static const struct fb_videomode gx_modedb[] __initdata = {
++static struct fb_videomode gx_modedb[] __initdata = {
+ /* 640x480-60 VESA */
+ { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+@@ -105,6 +108,35 @@ static const struct fb_videomode gx_modedb[] __initdata = {
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ };
+
++#ifdef CONFIG_OLPC
++#include <asm/olpc.h>
++
++static struct fb_videomode gx_dcon_modedb[] __initdata = {
++ /* The only mode the DCON has is 1200x900 */
++ { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
++ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++ FB_VMODE_NONINTERLACED, 0 }
++};
++
++static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
++{
++ if (olpc_has_dcon()) {
++ *modedb = (struct fb_videomode *) gx_dcon_modedb;
++ *size = ARRAY_SIZE(gx_dcon_modedb);
++ } else {
++ *modedb = (struct fb_videomode *) gx_modedb;
++ *size = ARRAY_SIZE(gx_modedb);
++ }
+}
+
-+/* get the number of avail data in write ring buffer */
-+static int spcp8x5_chars_in_buffer(struct usb_serial_port *port)
++#else
++static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+{
-+ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
-+ int chars = 0;
-+ unsigned long flags;
++ *modedb = (struct fb_videomode *) gx_modedb;
++ *size = ARRAY_SIZE(gx_modedb);
++}
++#endif
+
-+ spin_lock_irqsave(&priv->lock, flags);
-+ chars = ringbuf_avail_data(priv->buf);
-+ spin_unlock_irqrestore(&priv->lock, flags);
+ static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+ {
+ if (var->xres > 1600 || var->yres > 1200)
+@@ -139,8 +171,6 @@ static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+
+ static int gxfb_set_par(struct fb_info *info)
+ {
+- struct geodefb_par *par = info->par;
+-
+ if (info->var.bits_per_pixel > 8) {
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ fb_dealloc_cmap(&info->cmap);
+@@ -151,7 +181,7 @@ static int gxfb_set_par(struct fb_info *info)
+
+ info->fix.line_length = gx_line_delta(info->var.xres, info->var.bits_per_pixel);
+
+- par->dc_ops->set_mode(info);
++ gx_set_mode(info);
+
+ return 0;
+ }
+@@ -167,8 +197,6 @@ static int gxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+ {
+- struct geodefb_par *par = info->par;
+-
+ if (info->var.grayscale) {
+ /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+@@ -191,7 +219,7 @@ static int gxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ if (regno >= 256)
+ return -EINVAL;
+
+- par->dc_ops->set_palette_reg(info, regno, red, green, blue);
++ gx_set_hw_palette_reg(info, regno, red, green, blue);
+ }
+
+ return 0;
+@@ -199,15 +227,12 @@ static int gxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+
+ static int gxfb_blank(int blank_mode, struct fb_info *info)
+ {
+- struct geodefb_par *par = info->par;
+-
+- return par->vid_ops->blank_display(info, blank_mode);
++ return gx_blank_display(info, blank_mode);
+ }
+
+ static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
+ {
+- struct geodefb_par *par = info->par;
+- int fb_len;
++ struct gxfb_par *par = info->par;
+ int ret;
+
+ ret = pci_enable_device(dev);
+@@ -229,24 +254,31 @@ static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *de
+ if (!par->dc_regs)
+ return -ENOMEM;
+
+- ret = pci_request_region(dev, 0, "gxfb (framebuffer)");
++ ret = pci_request_region(dev, 1, "gxfb (graphics processor)");
+ if (ret < 0)
+ return ret;
+- if ((fb_len = gx_frame_buffer_size()) < 0)
++ par->gp_regs = ioremap(pci_resource_start(dev, 1),
++ pci_resource_len(dev, 1));
+
-+ return chars;
-+}
++ if (!par->gp_regs)
+ return -ENOMEM;
+
-+/* 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,
-+};
++ ret = pci_request_region(dev, 0, "gxfb (framebuffer)");
++ if (ret < 0)
++ return ret;
+
-+static int __init spcp8x5_init(void)
+ info->fix.smem_start = pci_resource_start(dev, 0);
+- info->fix.smem_len = fb_len;
++ info->fix.smem_len = vram ? vram : gx_frame_buffer_size();
+ info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+ if (!info->screen_base)
+ return -ENOMEM;
+
+- /* Set the 16MB aligned base address of the graphics memory region
++ /* Set the 16MiB aligned base address of the graphics memory region
+ * in the display controller */
+
+- writel(info->fix.smem_start & 0xFF000000,
+- par->dc_regs + DC_GLIU0_MEM_OFFSET);
++ write_dc(par, DC_GLIU0_MEM_OFFSET, info->fix.smem_start & 0xFF000000);
+
+- dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n",
++ dev_info(&dev->dev, "%d KiB of video memory at 0x%lx\n",
+ info->fix.smem_len / 1024, info->fix.smem_start);
+
+ return 0;
+@@ -266,11 +298,12 @@ static struct fb_ops gxfb_ops = {
+
+ static struct fb_info * __init gxfb_init_fbinfo(struct device *dev)
+ {
+- struct geodefb_par *par;
++ struct gxfb_par *par;
+ struct fb_info *info;
+
+ /* Alloc enough space for the pseudo palette. */
+- info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, dev);
++ info = framebuffer_alloc(sizeof(struct gxfb_par) + sizeof(u32) * 16,
++ dev);
+ if (!info)
+ return NULL;
+
+@@ -296,29 +329,64 @@ static struct fb_info * __init gxfb_init_fbinfo(struct device *dev)
+ info->flags = FBINFO_DEFAULT;
+ info->node = -1;
+
+- info->pseudo_palette = (void *)par + sizeof(struct geodefb_par);
++ info->pseudo_palette = (void *)par + sizeof(struct gxfb_par);
+
+ info->var.grayscale = 0;
+
+ return info;
+ }
+
++#ifdef CONFIG_PM
++static int gxfb_suspend(struct pci_dev *pdev, pm_message_t state)
+{
-+ 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);
++ struct fb_info *info = pci_get_drvdata(pdev);
++
++ if (state.event == PM_EVENT_SUSPEND) {
++ acquire_console_sem();
++ gx_powerdown(info);
++ fb_set_suspend(info, 1);
++ release_console_sem();
++ }
++
++ /* there's no point in setting PCI states; we emulate PCI, so
++ * we don't end up getting power savings anyways */
++
+ return 0;
-+failed_usb_register:
-+ usb_serial_deregister(&spcp8x5_device);
-+failed_usb_serial_register:
-+ return retval;
+}
+
-+static void __exit spcp8x5_exit(void)
++static int gxfb_resume(struct pci_dev *pdev)
+{
-+ usb_deregister(&spcp8x5_driver);
-+ usb_serial_deregister(&spcp8x5_device);
-+}
++ struct fb_info *info = pci_get_drvdata(pdev);
++ int ret;
+
-+module_init(spcp8x5_init);
-+module_exit(spcp8x5_exit);
++ acquire_console_sem();
++ ret = gx_powerup(info);
++ if (ret) {
++ printk(KERN_ERR "gxfb: power up failed!\n");
++ return ret;
++ }
+
-+MODULE_DESCRIPTION(DRIVER_DESC);
-+MODULE_VERSION(DRIVER_VERSION);
-+MODULE_LICENSE("GPL");
++ fb_set_suspend(info, 0);
++ release_console_sem();
++ return 0;
++}
++#endif
+
-+module_param(debug, bool, S_IRUGO | S_IWUSR);
-+MODULE_PARM_DESC(debug, "Debug enabled or not");
-diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
-index e3d241f..a1c8aef 100644
---- a/drivers/usb/serial/ti_usb_3410_5052.c
-+++ b/drivers/usb/serial/ti_usb_3410_5052.c
-@@ -82,7 +82,6 @@
- #include <linux/circ_buf.h>
- #include <linux/mutex.h>
- #include <asm/uaccess.h>
--#include <asm/semaphore.h>
- #include <linux/usb.h>
- #include <linux/usb/serial.h>
+ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+- struct geodefb_par *par;
++ struct gxfb_par *par;
+ struct fb_info *info;
+ int ret;
+ unsigned long val;
-@@ -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)
++ struct fb_videomode *modedb_ptr;
++ unsigned int modedb_size;
++
+ info = gxfb_init_fbinfo(&pdev->dev);
+ if (!info)
+ return -ENOMEM;
+ par = info->par;
+- /* GX display controller and GX video device. */
+- par->dc_ops = &gx_dc_ops;
+- par->vid_ops = &gx_vid_ops;
+-
+ if ((ret = gxfb_map_video_memory(info, pdev)) < 0) {
+ dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n");
+ goto err;
+@@ -326,15 +394,16 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
- 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);
+ /* Figure out if this is a TFT or CRT part */
- /* 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;
+- rdmsrl(GLD_MSR_CONFIG, val);
++ rdmsrl(MSR_GX_GLD_MSR_CONFIG, val);
+
+- if ((val & GLD_MSR_CONFIG_DM_FP) == GLD_MSR_CONFIG_DM_FP)
++ if ((val & MSR_GX_GLD_MSR_CONFIG_FP) == MSR_GX_GLD_MSR_CONFIG_FP)
+ par->enable_crt = 0;
+ else
+ par->enable_crt = 1;
+
++ get_modedb(&modedb_ptr, &modedb_size);
+ ret = fb_find_mode(&info->var, info, mode_option,
+- gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16);
++ modedb_ptr, modedb_size, NULL, 16);
+ if (ret == 0 || ret == 4) {
+ dev_err(&pdev->dev, "could not find valid video mode\n");
+ ret = -EINVAL;
+@@ -348,6 +417,8 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
+ gxfb_check_var(&info->var, info);
+ gxfb_set_par(info);
+
++ pm_set_vt_switch(vt_switch);
++
+ if (register_framebuffer(info) < 0) {
+ ret = -EINVAL;
+ goto err;
+@@ -369,6 +440,10 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
+ iounmap(par->dc_regs);
+ pci_release_region(pdev, 2);
}
- 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 (par->gp_regs) {
++ iounmap(par->gp_regs);
++ pci_release_region(pdev, 1);
++ }
- /* 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;
+ if (info)
+ framebuffer_release(info);
+@@ -378,7 +453,7 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
+ static void gxfb_remove(struct pci_dev *pdev)
+ {
+ struct fb_info *info = pci_get_drvdata(pdev);
+- struct geodefb_par *par = info->par;
++ struct gxfb_par *par = info->par;
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ unregister_framebuffer(info);
- 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));
+@@ -391,15 +466,16 @@ static void gxfb_remove(struct pci_dev *pdev)
+ iounmap(par->dc_regs);
+ pci_release_region(pdev, 2);
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
++ iounmap(par->gp_regs);
++ pci_release_region(pdev, 1);
++
+ pci_set_drvdata(pdev, NULL);
- if (tport == NULL)
- return -ENODEV;
-@@ -564,10 +557,10 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
+ framebuffer_release(info);
+ }
- /* 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;
- }
- }
+ static struct pci_device_id gxfb_id_table[] = {
+- { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO,
+- PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+- 0xff0000, 0 },
++ { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO) },
+ { 0, }
+ };
- ti_set_termios(port, port->tty->termios);
+@@ -410,6 +486,10 @@ static struct pci_driver gxfb_driver = {
+ .id_table = gxfb_id_table,
+ .probe = gxfb_probe,
+ .remove = gxfb_remove,
++#ifdef CONFIG_PM
++ .suspend = gxfb_suspend,
++ .resume = gxfb_resume,
++#endif
+ };
-- 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;
- }
+ #ifndef MODULE
+@@ -456,5 +536,11 @@ module_exit(gxfb_cleanup);
+ module_param(mode_option, charp, 0);
+ MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])");
-- 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;
- }
++module_param(vram, int, 0);
++MODULE_PARM_DESC(vram, "video memory size");
++
++module_param(vt_switch, int, 0);
++MODULE_PARM_DESC(vt_switch, "enable VT switch during suspend/resume");
++
+ MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX");
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h
+index ca13c48..3b9416f 100644
+--- a/drivers/video/geode/lxfb.h
++++ b/drivers/video/geode/lxfb.h
+@@ -3,17 +3,46 @@
-- 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;
- }
+ #include <linux/fb.h>
-@@ -620,27 +613,27 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
++#define GP_REG_COUNT (0x7c / 4)
++#define DC_REG_COUNT (0xf0 / 4)
++#define VP_REG_COUNT (0x158 / 8)
++#define FP_REG_COUNT (0x60 / 8)
++
++#define DC_PAL_COUNT 0x104
++#define DC_HFILT_COUNT 0x100
++#define DC_VFILT_COUNT 0x100
++#define VP_COEFF_SIZE 0x1000
++
+ #define OUTPUT_CRT 0x01
+ #define OUTPUT_PANEL 0x02
+
+ struct lxfb_par {
+ int output;
+- int panel_width;
+- int panel_height;
+
+ void __iomem *gp_regs;
+ void __iomem *dc_regs;
+- void __iomem *df_regs;
++ void __iomem *vp_regs;
++#ifdef CONFIG_PM
++ int powered_down;
++
++ /* register state, for power mgmt functionality */
++ struct {
++ uint64_t padsel;
++ uint64_t dotpll;
++ uint64_t dfglcfg;
++ uint64_t dcspare;
++ } msr;
++
++ uint32_t gp[GP_REG_COUNT];
++ uint32_t dc[DC_REG_COUNT];
++ uint64_t vp[VP_REG_COUNT];
++ uint64_t fp[FP_REG_COUNT];
++
++ uint32_t pal[DC_PAL_COUNT];
++ uint32_t hcoeff[DC_HFILT_COUNT * 2];
++ uint32_t vcoeff[DC_VFILT_COUNT];
++ uint32_t vp_coeff[VP_COEFF_SIZE / 4];
++#endif
+ };
- ti_set_termios(port, port->tty->termios);
+ static inline unsigned int lx_get_pitch(unsigned int xres, int bpp)
+@@ -29,171 +58,383 @@ int lx_blank_display(struct fb_info *, int);
+ void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int,
+ unsigned int, unsigned int);
-- 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;
- }
+-/* MSRS */
++#ifdef CONFIG_PM
++int lx_powerdown(struct fb_info *info);
++int lx_powerup(struct fb_info *info);
++#endif
++
++
++/* Graphics Processor registers (table 6-29 from the data book) */
++enum gp_registers {
++ GP_DST_OFFSET = 0,
++ GP_SRC_OFFSET,
++ GP_STRIDE,
++ GP_WID_HEIGHT,
++
++ GP_SRC_COLOR_FG,
++ GP_SRC_COLOR_BG,
++ GP_PAT_COLOR_0,
++ GP_PAT_COLOR_1,
++
++ GP_PAT_COLOR_2,
++ GP_PAT_COLOR_3,
++ GP_PAT_COLOR_4,
++ GP_PAT_COLOR_5,
++
++ GP_PAT_DATA_0,
++ GP_PAT_DATA_1,
++ GP_RASTER_MODE,
++ GP_VECTOR_MODE,
++
++ GP_BLT_MODE,
++ GP_BLT_STATUS,
++ GP_HST_SRC,
++ GP_BASE_OFFSET,
++
++ GP_CMD_TOP,
++ GP_CMD_BOT,
++ GP_CMD_READ,
++ GP_CMD_WRITE,
++
++ GP_CH3_OFFSET,
++ GP_CH3_MODE_STR,
++ GP_CH3_WIDHI,
++ GP_CH3_HSRC,
++
++ GP_LUT_INDEX,
++ GP_LUT_DATA,
++ GP_INT_CNTRL, /* 0x78 */
++};
++
++#define GP_BLT_STATUS_CE (1 << 4) /* cmd buf empty */
++#define GP_BLT_STATUS_PB (1 << 0) /* primative busy */
++
++
++/* Display Controller registers (table 6-47 from the data book) */
++enum dc_registers {
++ DC_UNLOCK = 0,
++ DC_GENERAL_CFG,
++ DC_DISPLAY_CFG,
++ DC_ARB_CFG,
++
++ DC_FB_ST_OFFSET,
++ DC_CB_ST_OFFSET,
++ DC_CURS_ST_OFFSET,
++ DC_RSVD_0,
++
++ DC_VID_Y_ST_OFFSET,
++ DC_VID_U_ST_OFFSET,
++ DC_VID_V_ST_OFFSET,
++ DC_DV_TOP,
++
++ DC_LINE_SIZE,
++ DC_GFX_PITCH,
++ DC_VID_YUV_PITCH,
++ DC_RSVD_1,
++
++ DC_H_ACTIVE_TIMING,
++ DC_H_BLANK_TIMING,
++ DC_H_SYNC_TIMING,
++ DC_RSVD_2,
++
++ DC_V_ACTIVE_TIMING,
++ DC_V_BLANK_TIMING,
++ DC_V_SYNC_TIMING,
++ DC_FB_ACTIVE,
++
++ DC_CURSOR_X,
++ DC_CURSOR_Y,
++ DC_RSVD_3,
++ DC_LINE_CNT,
++
++ DC_PAL_ADDRESS,
++ DC_PAL_DATA,
++ DC_DFIFO_DIAG,
++ DC_CFIFO_DIAG,
++
++ DC_VID_DS_DELTA,
++ DC_GLIU0_MEM_OFFSET,
++ DC_DV_CTL,
++ DC_DV_ACCESS,
++
++ DC_GFX_SCALE,
++ DC_IRQ_FILT_CTL,
++ DC_FILT_COEFF1,
++ DC_FILT_COEFF2,
++
++ DC_VBI_EVEN_CTL,
++ DC_VBI_ODD_CTL,
++ DC_VBI_HOR,
++ DC_VBI_LN_ODD,
++
++ DC_VBI_LN_EVEN,
++ DC_VBI_PITCH,
++ DC_CLR_KEY,
++ DC_CLR_KEY_MASK,
++
++ DC_CLR_KEY_X,
++ DC_CLR_KEY_Y,
++ DC_IRQ,
++ DC_RSVD_4,
++
++ DC_RSVD_5,
++ DC_GENLK_CTL,
++ DC_VID_EVEN_Y_ST_OFFSET,
++ DC_VID_EVEN_U_ST_OFFSET,
++
++ DC_VID_EVEN_V_ST_OFFSET,
++ DC_V_ACTIVE_EVEN_TIMING,
++ DC_V_BLANK_EVEN_TIMING,
++ DC_V_SYNC_EVEN_TIMING, /* 0xec */
++};
++
++#define DC_UNLOCK_LOCK 0x00000000
++#define DC_UNLOCK_UNLOCK 0x00004758 /* magic value */
++
++#define DC_GENERAL_CFG_FDTY (1 << 17)
++#define DC_GENERAL_CFG_DFHPEL_SHIFT (12)
++#define DC_GENERAL_CFG_DFHPSL_SHIFT (8)
++#define DC_GENERAL_CFG_VGAE (1 << 7)
++#define DC_GENERAL_CFG_DECE (1 << 6)
++#define DC_GENERAL_CFG_CMPE (1 << 5)
++#define DC_GENERAL_CFG_VIDE (1 << 3)
++#define DC_GENERAL_CFG_DFLE (1 << 0)
++
++#define DC_DISPLAY_CFG_VISL (1 << 27)
++#define DC_DISPLAY_CFG_PALB (1 << 25)
++#define DC_DISPLAY_CFG_DCEN (1 << 24)
++#define DC_DISPLAY_CFG_DISP_MODE_24BPP (1 << 9)
++#define DC_DISPLAY_CFG_DISP_MODE_16BPP (1 << 8)
++#define DC_DISPLAY_CFG_DISP_MODE_8BPP (0)
++#define DC_DISPLAY_CFG_TRUP (1 << 6)
++#define DC_DISPLAY_CFG_VDEN (1 << 4)
++#define DC_DISPLAY_CFG_GDEN (1 << 3)
++#define DC_DISPLAY_CFG_TGEN (1 << 0)
++
++#define DC_DV_TOP_DV_TOP_EN (1 << 0)
+
+-#define MSR_LX_GLD_CONFIG 0x48002001
+-#define MSR_LX_GLCP_DOTPLL 0x4c000015
+-#define MSR_LX_DF_PADSEL 0x48002011
+-#define MSR_LX_DC_SPARE 0x80000011
+-#define MSR_LX_DF_GLCONFIG 0x48002001
++#define DC_DV_CTL_DV_LINE_SIZE ((1 << 10) | (1 << 11))
++#define DC_DV_CTL_DV_LINE_SIZE_1K (0)
++#define DC_DV_CTL_DV_LINE_SIZE_2K (1 << 10)
++#define DC_DV_CTL_DV_LINE_SIZE_4K (1 << 11)
++#define DC_DV_CTL_DV_LINE_SIZE_8K ((1 << 10) | (1 << 11))
++#define DC_DV_CTL_CLEAR_DV_RAM (1 << 0)
+
+-#define MSR_LX_GLIU0_P2D_RO0 0x10000029
++#define DC_IRQ_FILT_CTL_H_FILT_SEL (1 << 10)
+
+-#define GLCP_DOTPLL_RESET (1 << 0)
+-#define GLCP_DOTPLL_BYPASS (1 << 15)
+-#define GLCP_DOTPLL_HALFPIX (1 << 24)
+-#define GLCP_DOTPLL_LOCK (1 << 25)
++#define DC_CLR_KEY_CLR_KEY_EN (1 << 24)
+
+-#define DF_CONFIG_OUTPUT_MASK 0x38
+-#define DF_OUTPUT_PANEL 0x08
+-#define DF_OUTPUT_CRT 0x00
+-#define DF_SIMULTANEOUS_CRT_AND_FP (1 << 15)
++#define DC_IRQ_VIP_VSYNC_IRQ_STATUS (1 << 21) /* undocumented? */
++#define DC_IRQ_STATUS (1 << 20) /* undocumented? */
++#define DC_IRQ_VIP_VSYNC_LOSS_IRQ_MASK (1 << 1)
++#define DC_IRQ_MASK (1 << 0)
+
+-#define DF_DEFAULT_TFT_PAD_SEL_LOW 0xDFFFFFFF
+-#define DF_DEFAULT_TFT_PAD_SEL_HIGH 0x0000003F
++#define DC_GENLK_CTL_FLICK_SEL_MASK (0x0F << 28)
++#define DC_GENLK_CTL_ALPHA_FLICK_EN (1 << 25)
++#define DC_GENLK_CTL_FLICK_EN (1 << 24)
++#define DC_GENLK_CTL_GENLK_EN (1 << 18)
+
+-#define DC_SPARE_DISABLE_CFIFO_HGO 0x00000800
+-#define DC_SPARE_VFIFO_ARB_SELECT 0x00000400
+-#define DC_SPARE_WM_LPEN_OVRD 0x00000200
+-#define DC_SPARE_LOAD_WM_LPEN_MASK 0x00000100
+-#define DC_SPARE_DISABLE_INIT_VID_PRI 0x00000080
+-#define DC_SPARE_DISABLE_VFIFO_WM 0x00000040
+-#define DC_SPARE_DISABLE_CWD_CHECK 0x00000020
+-#define DC_SPARE_PIX8_PAN_FIX 0x00000010
+-#define DC_SPARE_FIRST_REQ_MASK 0x00000002
+
+-/* Registers */
++/*
++ * Video Processor registers (table 6-71).
++ * There is space for 64 bit values, but we never use more than the
++ * lower 32 bits. The actual register save/restore code only bothers
++ * to restore those 32 bits.
++ */
++enum vp_registers {
++ VP_VCFG = 0,
++ VP_DCFG,
+
+-#define DC_UNLOCK 0x00
+-#define DC_UNLOCK_CODE 0x4758
++ VP_VX,
++ VP_VY,
+
+-#define DC_GENERAL_CFG 0x04
+-#define DC_GCFG_DFLE (1 << 0)
+-#define DC_GCFG_VIDE (1 << 3)
+-#define DC_GCFG_VGAE (1 << 7)
+-#define DC_GCFG_CMPE (1 << 5)
+-#define DC_GCFG_DECE (1 << 6)
+-#define DC_GCFG_FDTY (1 << 17)
++ VP_SCL,
++ VP_VCK,
+
+-#define DC_DISPLAY_CFG 0x08
+-#define DC_DCFG_TGEN (1 << 0)
+-#define DC_DCFG_GDEN (1 << 3)
+-#define DC_DCFG_VDEN (1 << 4)
+-#define DC_DCFG_TRUP (1 << 6)
+-#define DC_DCFG_DCEN (1 << 24)
+-#define DC_DCFG_PALB (1 << 25)
+-#define DC_DCFG_VISL (1 << 27)
++ VP_VCM,
++ VP_PAR,
+
+-#define DC_DCFG_16BPP 0x0
++ VP_PDR,
++ VP_SLR,
+
+-#define DC_DCFG_DISP_MODE_MASK 0x00000300
+-#define DC_DCFG_DISP_MODE_8BPP 0x00000000
+-#define DC_DCFG_DISP_MODE_16BPP 0x00000100
+-#define DC_DCFG_DISP_MODE_24BPP 0x00000200
+-#define DC_DCFG_DISP_MODE_32BPP 0x00000300
++ VP_MISC,
++ VP_CCS,
+
++ VP_VYS,
++ VP_VXS,
+
+-#define DC_ARB_CFG 0x0C
++ VP_RSVD_0,
++ VP_VDC,
+
+-#define DC_FB_START 0x10
+-#define DC_CB_START 0x14
+-#define DC_CURSOR_START 0x18
++ VP_RSVD_1,
++ VP_CRC,
+
+-#define DC_DV_TOP 0x2C
+-#define DC_DV_TOP_ENABLE (1 << 0)
++ VP_CRC32,
++ VP_VDE,
+
+-#define DC_LINE_SIZE 0x30
+-#define DC_GRAPHICS_PITCH 0x34
+-#define DC_H_ACTIVE_TIMING 0x40
+-#define DC_H_BLANK_TIMING 0x44
+-#define DC_H_SYNC_TIMING 0x48
+-#define DC_V_ACTIVE_TIMING 0x50
+-#define DC_V_BLANK_TIMING 0x54
+-#define DC_V_SYNC_TIMING 0x58
+-#define DC_FB_ACTIVE 0x5C
++ VP_CCK,
++ VP_CCM,
+
+-#define DC_PAL_ADDRESS 0x70
+-#define DC_PAL_DATA 0x74
++ VP_CC1,
++ VP_CC2,
+
+-#define DC_PHY_MEM_OFFSET 0x84
++ VP_A1X,
++ VP_A1Y,
+
+-#define DC_DV_CTL 0x88
+-#define DC_DV_LINE_SIZE_MASK 0x00000C00
+-#define DC_DV_LINE_SIZE_1024 0x00000000
+-#define DC_DV_LINE_SIZE_2048 0x00000400
+-#define DC_DV_LINE_SIZE_4096 0x00000800
+-#define DC_DV_LINE_SIZE_8192 0x00000C00
++ VP_A1C,
++ VP_A1T,
+
++ VP_A2X,
++ VP_A2Y,
+
+-#define DC_GFX_SCALE 0x90
+-#define DC_IRQ_FILT_CTL 0x94
++ VP_A2C,
++ VP_A2T,
+
++ VP_A3X,
++ VP_A3Y,
+
+-#define DC_IRQ 0xC8
+-#define DC_IRQ_MASK (1 << 0)
+-#define DC_VSYNC_IRQ_MASK (1 << 1)
+-#define DC_IRQ_STATUS (1 << 20)
+-#define DC_VSYNC_IRQ_STATUS (1 << 21)
++ VP_A3C,
++ VP_A3T,
+
+-#define DC_GENLCK_CTRL 0xD4
+-#define DC_GENLCK_ENABLE (1 << 18)
+-#define DC_GC_ALPHA_FLICK_ENABLE (1 << 25)
+-#define DC_GC_FLICKER_FILTER_ENABLE (1 << 24)
+-#define DC_GC_FLICKER_FILTER_MASK (0x0F << 28)
++ VP_VRR,
++ VP_AWT,
+
+-#define DC_COLOR_KEY 0xB8
+-#define DC_CLR_KEY_ENABLE (1 << 24)
++ VP_VTM,
++ VP_VYE,
+
++ VP_A1YE,
++ VP_A2YE,
+
+-#define DC3_DV_LINE_SIZE_MASK 0x00000C00
+-#define DC3_DV_LINE_SIZE_1024 0x00000000
+-#define DC3_DV_LINE_SIZE_2048 0x00000400
+-#define DC3_DV_LINE_SIZE_4096 0x00000800
+-#define DC3_DV_LINE_SIZE_8192 0x00000C00
++ VP_A3YE, /* 0x150 */
+
+-#define DF_VIDEO_CFG 0x0
+-#define DF_VCFG_VID_EN (1 << 0)
++ VP_VCR = 0x1000, /* 0x1000 - 0x1fff */
++};
++
++#define VP_VCFG_VID_EN (1 << 0)
++
++#define VP_DCFG_GV_GAM (1 << 21)
++#define VP_DCFG_PWR_SEQ_DELAY ((1 << 17) | (1 << 18) | (1 << 19))
++#define VP_DCFG_PWR_SEQ_DELAY_DEFAULT (1 << 19) /* undocumented */
++#define VP_DCFG_CRT_SYNC_SKW ((1 << 14) | (1 << 15) | (1 << 16))
++#define VP_DCFG_CRT_SYNC_SKW_DEFAULT (1 << 16)
++#define VP_DCFG_CRT_VSYNC_POL (1 << 9)
++#define VP_DCFG_CRT_HSYNC_POL (1 << 8)
++#define VP_DCFG_DAC_BL_EN (1 << 3)
++#define VP_DCFG_VSYNC_EN (1 << 2)
++#define VP_DCFG_HSYNC_EN (1 << 1)
++#define VP_DCFG_CRT_EN (1 << 0)
++
++#define VP_MISC_APWRDN (1 << 11)
++#define VP_MISC_DACPWRDN (1 << 10)
++#define VP_MISC_BYP_BOTH (1 << 0)
++
++
++/*
++ * Flat Panel registers (table 6-71).
++ * Also 64 bit registers; see above note about 32-bit handling.
++ */
++
++/* we're actually in the VP register space, starting at address 0x400 */
++#define VP_FP_START 0x400
+
+-#define DF_DISPLAY_CFG 0x08
++enum fp_registers {
++ FP_PT1 = 0,
++ FP_PT2,
++
++ FP_PM,
++ FP_DFC,
++
++ FP_RSVD_0,
++ FP_RSVD_1,
++
++ FP_RSVD_2,
++ FP_RSVD_3,
++
++ FP_RSVD_4,
++ FP_DCA,
++
++ FP_DMD,
++ FP_CRC, /* 0x458 */
++};
+
+-#define DF_DCFG_CRT_EN (1 << 0)
+-#define DF_DCFG_HSYNC_EN (1 << 1)
+-#define DF_DCFG_VSYNC_EN (1 << 2)
+-#define DF_DCFG_DAC_BL_EN (1 << 3)
+-#define DF_DCFG_CRT_HSYNC_POL (1 << 8)
+-#define DF_DCFG_CRT_VSYNC_POL (1 << 9)
+-#define DF_DCFG_GV_PAL_BYP (1 << 21)
++#define FP_PT2_SCRC (1 << 27) /* shfclk free */
+
+-#define DF_DCFG_CRT_SYNC_SKW_INIT 0x10000
+-#define DF_DCFG_CRT_SYNC_SKW_MASK 0x1c000
++#define FP_PM_P (1 << 24) /* panel power ctl */
++#define FP_PM_PANEL_PWR_UP (1 << 3) /* r/o */
++#define FP_PM_PANEL_PWR_DOWN (1 << 2) /* r/o */
++#define FP_PM_PANEL_OFF (1 << 1) /* r/o */
++#define FP_PM_PANEL_ON (1 << 0) /* r/o */
+
+-#define DF_DCFG_PWR_SEQ_DLY_INIT 0x80000
+-#define DF_DCFG_PWR_SEQ_DLY_MASK 0xe0000
++#define FP_DFC_BC ((1 << 4) | (1 << 5) | (1 << 6))
+
+-#define DF_MISC 0x50
+
+-#define DF_MISC_GAM_BYPASS (1 << 0)
+-#define DF_MISC_DAC_PWRDN (1 << 10)
+-#define DF_MISC_A_PWRDN (1 << 11)
++/* register access functions */
++
++static inline uint32_t read_gp(struct lxfb_par *par, int reg)
++{
++ return readl(par->gp_regs + 4*reg);
++}
++
++static inline void write_gp(struct lxfb_par *par, int reg, uint32_t val)
++{
++ writel(val, par->gp_regs + 4*reg);
++}
++
++static inline uint32_t read_dc(struct lxfb_par *par, int reg)
++{
++ return readl(par->dc_regs + 4*reg);
++}
++
++static inline void write_dc(struct lxfb_par *par, int reg, uint32_t val)
++{
++ writel(val, par->dc_regs + 4*reg);
++}
++
++static inline uint32_t read_vp(struct lxfb_par *par, int reg)
++{
++ return readl(par->vp_regs + 8*reg);
++}
++
++static inline void write_vp(struct lxfb_par *par, int reg, uint32_t val)
++{
++ writel(val, par->vp_regs + 8*reg);
++}
++
++static inline uint32_t read_fp(struct lxfb_par *par, int reg)
++{
++ return readl(par->vp_regs + 8*reg + VP_FP_START);
++}
++
++static inline void write_fp(struct lxfb_par *par, int reg, uint32_t val)
++{
++ writel(val, par->vp_regs + 8*reg + VP_FP_START);
++}
++
+
+-#define DF_PAR 0x38
+-#define DF_PDR 0x40
+-#define DF_ALPHA_CONTROL_1 0xD8
+-#define DF_VIDEO_REQUEST 0x120
++/* MSRs are defined in asm/geode.h; their bitfields are here */
+
+-#define DF_PANEL_TIM1 0x400
+-#define DF_DEFAULT_TFT_PMTIM1 0x0
++#define MSR_GLCP_DOTPLL_LOCK (1 << 25) /* r/o */
++#define MSR_GLCP_DOTPLL_HALFPIX (1 << 24)
++#define MSR_GLCP_DOTPLL_BYPASS (1 << 15)
++#define MSR_GLCP_DOTPLL_DOTRESET (1 << 0)
+
+-#define DF_PANEL_TIM2 0x408
+-#define DF_DEFAULT_TFT_PMTIM2 0x08000000
++/* note: this is actually the VP's GLD_MSR_CONFIG */
++#define MSR_LX_GLD_MSR_CONFIG_FMT ((1 << 3) | (1 << 4) | (1 << 5))
++#define MSR_LX_GLD_MSR_CONFIG_FMT_FP (1 << 3)
++#define MSR_LX_GLD_MSR_CONFIG_FMT_CRT (0)
++#define MSR_LX_GLD_MSR_CONFIG_FPC (1 << 15) /* FP *and* CRT */
+
+-#define DF_FP_PM 0x410
+-#define DF_FP_PM_P (1 << 24)
++#define MSR_LX_MSR_PADSEL_TFT_SEL_LOW 0xDFFFFFFF /* ??? */
++#define MSR_LX_MSR_PADSEL_TFT_SEL_HIGH 0x0000003F /* ??? */
+
+-#define DF_DITHER_CONTROL 0x418
+-#define DF_DEFAULT_TFT_DITHCTL 0x00000070
+-#define GP_BLT_STATUS 0x44
+-#define GP_BS_BLT_BUSY (1 << 0)
+-#define GP_BS_CB_EMPTY (1 << 4)
++#define MSR_LX_SPARE_MSR_DIS_CFIFO_HGO (1 << 11) /* undocumented */
++#define MSR_LX_SPARE_MSR_VFIFO_ARB_SEL (1 << 10) /* undocumented */
++#define MSR_LX_SPARE_MSR_WM_LPEN_OVRD (1 << 9) /* undocumented */
++#define MSR_LX_SPARE_MSR_LOAD_WM_LPEN_M (1 << 8) /* undocumented */
++#define MSR_LX_SPARE_MSR_DIS_INIT_V_PRI (1 << 7) /* undocumented */
++#define MSR_LX_SPARE_MSR_DIS_VIFO_WM (1 << 6)
++#define MSR_LX_SPARE_MSR_DIS_CWD_CHECK (1 << 5) /* undocumented */
++#define MSR_LX_SPARE_MSR_PIX8_PAN_FIX (1 << 4) /* undocumented */
++#define MSR_LX_SPARE_MSR_FIRST_REQ_MASK (1 << 1) /* undocumented */
+
+ #endif
+diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c
+index eb6b881..2cd9b74 100644
+--- a/drivers/video/geode/lxfb_core.c
++++ b/drivers/video/geode/lxfb_core.c
+@@ -17,6 +17,7 @@
+ #include <linux/console.h>
+ #include <linux/mm.h>
+ #include <linux/slab.h>
++#include <linux/suspend.h>
+ #include <linux/delay.h>
+ #include <linux/fb.h>
+ #include <linux/init.h>
+@@ -27,14 +28,15 @@
-- 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;
- }
+ static char *mode_option;
+ static int noclear, nopanel, nocrt;
+-static int fbsize;
++static int vram;
++static int vt_switch;
- /* 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;
- }
+ /* Most of these modes are sorted in ascending order, but
+ * since the first entry in this table is the "default" mode,
+ * we try to make it something sane - 640x480-60 is sane
+ */
-@@ -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;
- }
+-static const struct fb_videomode geode_modedb[] __initdata = {
++static struct fb_videomode geode_modedb[] __initdata = {
+ /* 640x480-60 */
+ { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+@@ -215,6 +217,35 @@ static const struct fb_videomode geode_modedb[] __initdata = {
+ 0, FB_VMODE_NONINTERLACED, 0 },
+ };
-@@ -677,7 +670,7 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
- int status;
- int do_unlock;
++#ifdef CONFIG_OLPC
++#include <asm/olpc.h>
++
++static struct fb_videomode olpc_dcon_modedb[] __initdata = {
++ /* The only mode the DCON has is 1200x900 */
++ { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
++ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++ FB_VMODE_NONINTERLACED, 0 }
++};
++
++static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
++{
++ if (olpc_has_dcon()) {
++ *modedb = (struct fb_videomode *) olpc_dcon_modedb;
++ *size = ARRAY_SIZE(olpc_dcon_modedb);
++ } else {
++ *modedb = (struct fb_videomode *) geode_modedb;
++ *size = ARRAY_SIZE(geode_modedb);
++ }
++}
++
++#else
++static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
++{
++ *modedb = (struct fb_videomode *) geode_modedb;
++ *size = ARRAY_SIZE(geode_modedb);
++}
++#endif
++
+ static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+ {
+ if (var->xres > 1920 || var->yres > 1440)
+@@ -333,13 +364,13 @@ static int __init lxfb_map_video_memory(struct fb_info *info,
+ if (ret)
+ return ret;
-- 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)
+- ret = pci_request_region(dev, 3, "lxfb-vip");
++ ret = pci_request_region(dev, 3, "lxfb-vp");
- port_number = port->number - port->serial->minor;
+ if (ret)
+ return ret;
-- 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);
+ info->fix.smem_start = pci_resource_start(dev, 0);
+- info->fix.smem_len = fbsize ? fbsize : lx_framebuffer_size();
++ info->fix.smem_len = vram ? vram : lx_framebuffer_size();
- /* 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);
+ info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
-- dbg("%s - exit", __FUNCTION__);
-+ dbg("%s - exit", __func__);
+@@ -360,18 +391,15 @@ static int __init lxfb_map_video_memory(struct fb_info *info,
+ if (par->dc_regs == NULL)
+ return ret;
+
+- par->df_regs = ioremap(pci_resource_start(dev, 3),
++ par->vp_regs = ioremap(pci_resource_start(dev, 3),
+ pci_resource_len(dev, 3));
+
+- if (par->df_regs == NULL)
++ if (par->vp_regs == NULL)
+ return ret;
+
+- writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
+-
+- writel(info->fix.smem_start & 0xFF000000,
+- par->dc_regs + DC_PHY_MEM_OFFSET);
+-
+- writel(0, par->dc_regs + DC_UNLOCK);
++ write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
++ write_dc(par, DC_GLIU0_MEM_OFFSET, info->fix.smem_start & 0xFF000000);
++ write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
+
+ dev_info(&dev->dev, "%d KB of video memory at 0x%lx\n",
+ info->fix.smem_len / 1024, info->fix.smem_start);
+@@ -431,6 +459,45 @@ static struct fb_info * __init lxfb_init_fbinfo(struct device *dev)
+ return info;
}
++#ifdef CONFIG_PM
++static int lxfb_suspend(struct pci_dev *pdev, pm_message_t state)
++{
++ struct fb_info *info = pci_get_drvdata(pdev);
++
++ if (state.event == PM_EVENT_SUSPEND) {
++ acquire_console_sem();
++ lx_powerdown(info);
++ fb_set_suspend(info, 1);
++ release_console_sem();
++ }
++
++ /* there's no point in setting PCI states; we emulate PCI, so
++ * we don't end up getting power savings anyways */
++
++ return 0;
++}
++
++static int lxfb_resume(struct pci_dev *pdev)
++{
++ struct fb_info *info = pci_get_drvdata(pdev);
++ int ret;
++
++ acquire_console_sem();
++ ret = lx_powerup(info);
++ if (ret) {
++ printk(KERN_ERR "lxfb: power up failed!\n");
++ return ret;
++ }
++
++ fb_set_suspend(info, 0);
++ release_console_sem();
++ return 0;
++}
++#else
++#define lxfb_suspend NULL
++#define lxfb_resume NULL
++#endif
++
+ static int __init lxfb_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+ {
+@@ -439,7 +506,7 @@ static int __init lxfb_probe(struct pci_dev *pdev,
+ int ret;
-@@ -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;
+ struct fb_videomode *modedb_ptr;
+- int modedb_size;
++ unsigned int modedb_size;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ info = lxfb_init_fbinfo(&pdev->dev);
- if (count == 0) {
-- dbg("%s - write request of 0 bytes", __FUNCTION__);
-+ dbg("%s - write request of 0 bytes", __func__);
- return 0;
- }
+@@ -464,9 +531,7 @@ static int __init lxfb_probe(struct pci_dev *pdev,
-@@ -747,7 +740,7 @@ static int ti_write_room(struct usb_serial_port *port)
- int room = 0;
- unsigned long flags;
+ /* Set up the mode database */
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- modedb_ptr = (struct fb_videomode *) geode_modedb;
+- modedb_size = ARRAY_SIZE(geode_modedb);
+-
++ get_modedb(&modedb_ptr, &modedb_size);
+ ret = fb_find_mode(&info->var, info, mode_option,
+ modedb_ptr, modedb_size, NULL, 16);
- 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);
+@@ -487,6 +552,8 @@ static int __init lxfb_probe(struct pci_dev *pdev,
+ lxfb_check_var(&info->var, info);
+ lxfb_set_par(info);
-- dbg("%s - returns %d", __FUNCTION__, room);
-+ dbg("%s - returns %d", __func__, room);
- return room;
- }
++ pm_set_vt_switch(vt_switch);
++
+ if (register_framebuffer(info) < 0) {
+ ret = -EINVAL;
+ goto err;
+@@ -510,8 +577,8 @@ err:
+ iounmap(par->dc_regs);
+ pci_release_region(pdev, 2);
+ }
+- if (par->df_regs) {
+- iounmap(par->df_regs);
++ if (par->vp_regs) {
++ iounmap(par->vp_regs);
+ pci_release_region(pdev, 3);
+ }
+
+@@ -537,7 +604,7 @@ static void lxfb_remove(struct pci_dev *pdev)
+ iounmap(par->dc_regs);
+ pci_release_region(pdev, 2);
+
+- iounmap(par->df_regs);
++ iounmap(par->vp_regs);
+ pci_release_region(pdev, 3);
-@@ -767,7 +760,7 @@ static int ti_chars_in_buffer(struct usb_serial_port *port)
- int chars = 0;
- unsigned long flags;
+ pci_set_drvdata(pdev, NULL);
+@@ -556,6 +623,8 @@ static struct pci_driver lxfb_driver = {
+ .id_table = lxfb_id_table,
+ .probe = lxfb_probe,
+ .remove = lxfb_remove,
++ .suspend = lxfb_suspend,
++ .resume = lxfb_resume,
+ };
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ #ifndef MODULE
+@@ -570,9 +639,7 @@ static int __init lxfb_setup(char *options)
+ if (!*opt)
+ continue;
- 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);
+- if (!strncmp(opt, "fbsize:", 7))
+- fbsize = simple_strtoul(opt+7, NULL, 0);
+- else if (!strcmp(opt, "noclear"))
++ if (!strcmp(opt, "noclear"))
+ noclear = 1;
+ else if (!strcmp(opt, "nopanel"))
+ nopanel = 1;
+@@ -609,8 +676,11 @@ module_exit(lxfb_cleanup);
+ module_param(mode_option, charp, 0);
+ MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])");
+
+-module_param(fbsize, int, 0);
+-MODULE_PARM_DESC(fbsize, "video memory size");
++module_param(vram, int, 0);
++MODULE_PARM_DESC(vram, "video memory size");
++
++module_param(vt_switch, int, 0);
++MODULE_PARM_DESC(vt_switch, "enable VT switch during suspend/resume");
-- dbg("%s - returns %d", __FUNCTION__, chars);
-+ dbg("%s - returns %d", __func__, chars);
- return chars;
- }
+ MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode LX");
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/geode/lxfb_ops.c
+index 4fbc99b..cd9d4cc 100644
+--- a/drivers/video/geode/lxfb_ops.c
++++ b/drivers/video/geode/lxfb_ops.c
+@@ -13,6 +13,7 @@
+ #include <linux/fb.h>
+ #include <linux/uaccess.h>
+ #include <linux/delay.h>
++#include <asm/geode.h>
-@@ -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;
+ #include "lxfb.h"
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+@@ -34,35 +35,85 @@ static const struct {
+ unsigned int pllval;
+ unsigned int freq;
+ } pll_table[] = {
+- { 0x000031AC, 24923 },
+- { 0x0000215D, 25175 },
+- { 0x00001087, 27000 },
+- { 0x0000216C, 28322 },
+- { 0x0000218D, 28560 },
+- { 0x000010C9, 31200 },
+- { 0x00003147, 31500 },
+- { 0x000010A7, 33032 },
+- { 0x00002159, 35112 },
+- { 0x00004249, 35500 },
+- { 0x00000057, 36000 },
+- { 0x0000219A, 37889 },
+- { 0x00002158, 39168 },
+- { 0x00000045, 40000 },
+- { 0x00000089, 43163 },
+- { 0x000010E7, 44900 },
+- { 0x00002136, 45720 },
+- { 0x00003207, 49500 },
+- { 0x00002187, 50000 },
+- { 0x00004286, 56250 },
+- { 0x000010E5, 60065 },
+- { 0x00004214, 65000 },
+- { 0x00001105, 68179 },
+- { 0x000031E4, 74250 },
+- { 0x00003183, 75000 },
+- { 0x00004284, 78750 },
+- { 0x00001104, 81600 },
+- { 0x00006363, 94500 },
+- { 0x00005303, 97520 },
++ { 0x000131AC, 6231 },
++ { 0x0001215D, 6294 },
++ { 0x00011087, 6750 },
++ { 0x0001216C, 7081 },
++ { 0x0001218D, 7140 },
++ { 0x000110C9, 7800 },
++ { 0x00013147, 7875 },
++ { 0x000110A7, 8258 },
++ { 0x00012159, 8778 },
++ { 0x00014249, 8875 },
++ { 0x00010057, 9000 },
++ { 0x0001219A, 9472 },
++ { 0x00012158, 9792 },
++ { 0x00010045, 10000 },
++ { 0x00010089, 10791 },
++ { 0x000110E7, 11225 },
++ { 0x00012136, 11430 },
++ { 0x00013207, 12375 },
++ { 0x00012187, 12500 },
++ { 0x00014286, 14063 },
++ { 0x000110E5, 15016 },
++ { 0x00014214, 16250 },
++ { 0x00011105, 17045 },
++ { 0x000131E4, 18563 },
++ { 0x00013183, 18750 },
++ { 0x00014284, 19688 },
++ { 0x00011104, 20400 },
++ { 0x00016363, 23625 },
++ { 0x00015303, 24380 },
++ { 0x000031AC, 24923 },
++ { 0x0000215D, 25175 },
++ { 0x00001087, 27000 },
++ { 0x0000216C, 28322 },
++ { 0x0000218D, 28560 },
++ { 0x00010041, 29913 },
++ { 0x000010C9, 31200 },
++ { 0x00003147, 31500 },
++ { 0x000141A1, 32400 },
++ { 0x000010A7, 33032 },
++ { 0x00012182, 33375 },
++ { 0x000141B1, 33750 },
++ { 0x00002159, 35112 },
++ { 0x00004249, 35500 },
++ { 0x00000057, 36000 },
++ { 0x000141E1, 37125 },
++ { 0x0000219A, 37889 },
++ { 0x00002158, 39168 },
++ { 0x00000045, 40000 },
++ { 0x000131A1, 40500 },
++ { 0x00010061, 42301 },
++ { 0x00000089, 43163 },
++ { 0x00012151, 43875 },
++ { 0x000010E7, 44900 },
++ { 0x00002136, 45720 },
++ { 0x000152E1, 47250 },
++ { 0x00010071, 48000 },
++ { 0x00003207, 49500 },
++ { 0x00002187, 50000 },
++ { 0x00014291, 50625 },
++ { 0x00011101, 51188 },
++ { 0x00017481, 54563 },
++ { 0x00004286, 56250 },
++ { 0x00014170, 57375 },
++ { 0x00016210, 58500 },
++ { 0x000010E5, 60065 },
++ { 0x00013140, 62796 },
++ { 0x00004214, 65000 },
++ { 0x00016250, 65250 },
++ { 0x00001105, 68179 },
++ { 0x000141C0, 69600 },
++ { 0x00015220, 70160 },
++ { 0x00010050, 72000 },
++ { 0x000031E4, 74250 },
++ { 0x00003183, 75000 },
++ { 0x00004284, 78750 },
++ { 0x00012130, 80052 },
++ { 0x00001104, 81600 },
++ { 0x00006363, 94500 },
++ { 0x00005303, 97520 },
+ { 0x00002183, 100187 },
+ { 0x00002122, 101420 },
+ { 0x00001081, 108000 },
+@@ -101,16 +152,16 @@ static void lx_set_dotpll(u32 pllval)
+ u32 dotpll_lo, dotpll_hi;
+ int i;
- if (tport == NULL)
- return;
+- rdmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
++ rdmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
- tty = port->tty;
- if (!tty) {
-- dbg("%s - no tty", __FUNCTION__);
-+ dbg("%s - no tty", __func__);
+- if ((dotpll_lo & GLCP_DOTPLL_LOCK) && (dotpll_hi == pllval))
++ if ((dotpll_lo & MSR_GLCP_DOTPLL_LOCK) && (dotpll_hi == pllval))
return;
+
+ dotpll_hi = pllval;
+- dotpll_lo &= ~(GLCP_DOTPLL_BYPASS | GLCP_DOTPLL_HALFPIX);
+- dotpll_lo |= GLCP_DOTPLL_RESET;
++ dotpll_lo &= ~(MSR_GLCP_DOTPLL_BYPASS | MSR_GLCP_DOTPLL_HALFPIX);
++ dotpll_lo |= MSR_GLCP_DOTPLL_DOTRESET;
+
+- wrmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
++ wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
+
+ /* Wait 100us for the PLL to lock */
+
+@@ -119,15 +170,15 @@ static void lx_set_dotpll(u32 pllval)
+ /* Now, loop for the lock bit */
+
+ for (i = 0; i < 1000; i++) {
+- rdmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
+- if (dotpll_lo & GLCP_DOTPLL_LOCK)
++ rdmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
++ if (dotpll_lo & MSR_GLCP_DOTPLL_LOCK)
+ break;
}
-@@ -809,21 +802,21 @@ static void ti_unthrottle(struct usb_serial_port *port)
- struct tty_struct *tty;
- int status;
+ /* Clear the reset bit */
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- dotpll_lo &= ~GLCP_DOTPLL_RESET;
+- wrmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
++ dotpll_lo &= ~MSR_GLCP_DOTPLL_DOTRESET;
++ wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
+ }
- if (tport == NULL)
- return;
+ /* Set the clock based on the frequency specified by the current mode */
+@@ -137,7 +188,7 @@ static void lx_set_clock(struct fb_info *info)
+ unsigned int diff, min, best = 0;
+ unsigned int freq, i;
- tty = port->tty;
- if (!tty) {
-- dbg("%s - no tty", __FUNCTION__);
-+ dbg("%s - no tty", __func__);
- return;
- }
+- freq = (unsigned int) (0x3b9aca00 / info->var.pixclock);
++ freq = (unsigned int) (1000000000 / info->var.pixclock);
- 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);
+ min = abs(pll_table[0].freq - freq);
+
+@@ -149,7 +200,7 @@ static void lx_set_clock(struct fb_info *info)
+ }
}
+
+- lx_set_dotpll(pll_table[best].pllval & 0x7FFF);
++ lx_set_dotpll(pll_table[best].pllval & 0x00017FFF);
}
-@@ -835,24 +828,24 @@ static int ti_ioctl(struct usb_serial_port *port, struct file *file,
- struct async_icount cnow;
- struct async_icount cprev;
+ static void lx_graphics_disable(struct fb_info *info)
+@@ -159,63 +210,62 @@ static void lx_graphics_disable(struct fb_info *info)
-- dbg("%s - port %d, cmd = 0x%04X", __FUNCTION__, port->number, cmd);
-+ dbg("%s - port %d, cmd = 0x%04X", __func__, port->number, cmd);
+ /* Note: This assumes that the video is in a quitet state */
- if (tport == NULL)
- return -ENODEV;
+- writel(0, par->df_regs + DF_ALPHA_CONTROL_1);
+- writel(0, par->df_regs + DF_ALPHA_CONTROL_1 + 32);
+- writel(0, par->df_regs + DF_ALPHA_CONTROL_1 + 64);
++ write_vp(par, VP_A1T, 0);
++ write_vp(par, VP_A2T, 0);
++ write_vp(par, VP_A3T, 0);
- 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;
+ /* Turn off the VGA and video enable */
+- val = readl (par->dc_regs + DC_GENERAL_CFG) &
+- ~(DC_GCFG_VGAE | DC_GCFG_VIDE);
++ val = read_dc(par, DC_GENERAL_CFG) & ~(DC_GENERAL_CFG_VGAE |
++ DC_GENERAL_CFG_VIDE);
- 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;
+- writel(val, par->dc_regs + DC_GENERAL_CFG);
++ write_dc(par, DC_GENERAL_CFG, val);
- 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;
+- val = readl(par->df_regs + DF_VIDEO_CFG) & ~DF_VCFG_VID_EN;
+- writel(val, par->df_regs + DF_VIDEO_CFG);
++ val = read_vp(par, VP_VCFG) & ~VP_VCFG_VID_EN;
++ write_vp(par, VP_VCFG, val);
- 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;
+- writel( DC_IRQ_MASK | DC_VSYNC_IRQ_MASK |
+- DC_IRQ_STATUS | DC_VSYNC_IRQ_STATUS,
+- par->dc_regs + DC_IRQ);
++ write_dc(par, DC_IRQ, DC_IRQ_MASK | DC_IRQ_VIP_VSYNC_LOSS_IRQ_MASK |
++ DC_IRQ_STATUS | DC_IRQ_VIP_VSYNC_IRQ_STATUS);
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- val = readl(par->dc_regs + DC_GENLCK_CTRL) & ~DC_GENLCK_ENABLE;
+- writel(val, par->dc_regs + DC_GENLCK_CTRL);
++ val = read_dc(par, DC_GENLK_CTL) & ~DC_GENLK_CTL_GENLK_EN;
++ write_dc(par, DC_GENLK_CTL, val);
- cflag = tty->termios->c_cflag;
- iflag = tty->termios->c_iflag;
+- val = readl(par->dc_regs + DC_COLOR_KEY) & ~DC_CLR_KEY_ENABLE;
+- writel(val & ~DC_CLR_KEY_ENABLE, par->dc_regs + DC_COLOR_KEY);
++ val = read_dc(par, DC_CLR_KEY);
++ write_dc(par, DC_CLR_KEY, val & ~DC_CLR_KEY_CLR_KEY_EN);
-- 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);
+- /* We don't actually blank the panel, due to the long latency
+- involved with bringing it back */
++ /* turn off the panel */
++ write_fp(par, FP_PM, read_fp(par, FP_PM) & ~FP_PM_P);
- if (tport == NULL)
- return;
+- val = readl(par->df_regs + DF_MISC) | DF_MISC_DAC_PWRDN;
+- writel(val, par->df_regs + DF_MISC);
++ val = read_vp(par, VP_MISC) | VP_MISC_DACPWRDN;
++ write_vp(par, VP_MISC, val);
- 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;
- }
+ /* Turn off the display */
-@@ -992,7 +985,7 @@ static void ti_set_termios(struct usb_serial_port *port,
- tty_encode_baud_rate(tty, baud, baud);
+- val = readl(par->df_regs + DF_DISPLAY_CFG);
+- writel(val & ~(DF_DCFG_CRT_EN | DF_DCFG_HSYNC_EN | DF_DCFG_VSYNC_EN |
+- DF_DCFG_DAC_BL_EN), par->df_regs + DF_DISPLAY_CFG);
++ val = read_vp(par, VP_DCFG);
++ write_vp(par, VP_DCFG, val & ~(VP_DCFG_CRT_EN | VP_DCFG_HSYNC_EN |
++ VP_DCFG_VSYNC_EN | VP_DCFG_DAC_BL_EN));
- 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);
+- gcfg = readl(par->dc_regs + DC_GENERAL_CFG);
+- gcfg &= ~(DC_GCFG_CMPE | DC_GCFG_DECE);
+- writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
++ gcfg = read_dc(par, DC_GENERAL_CFG);
++ gcfg &= ~(DC_GENERAL_CFG_CMPE | DC_GENERAL_CFG_DECE);
++ write_dc(par, DC_GENERAL_CFG, gcfg);
- 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);
+ /* Turn off the TGEN */
+- val = readl(par->dc_regs + DC_DISPLAY_CFG);
+- val &= ~DC_DCFG_TGEN;
+- writel(val, par->dc_regs + DC_DISPLAY_CFG);
++ val = read_dc(par, DC_DISPLAY_CFG);
++ val &= ~DC_DISPLAY_CFG_TGEN;
++ write_dc(par, DC_DISPLAY_CFG, val);
- /* 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);
+ /* Wait 1000 usecs to ensure that the TGEN is clear */
+ udelay(1000);
- kfree(config);
+ /* Turn off the FIFO loader */
+
+- gcfg &= ~DC_GCFG_DFLE;
+- writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
++ gcfg &= ~DC_GENERAL_CFG_DFLE;
++ write_dc(par, DC_GENERAL_CFG, gcfg);
+
+ /* Lastly, wait for the GP to go idle */
+
+ do {
+- val = readl(par->gp_regs + GP_BLT_STATUS);
+- } while ((val & GP_BS_BLT_BUSY) || !(val & GP_BS_CB_EMPTY));
++ val = read_gp(par, GP_BLT_STATUS);
++ } while ((val & GP_BLT_STATUS_PB) || !(val & GP_BLT_STATUS_CE));
}
-@@ -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);
+ static void lx_graphics_enable(struct fb_info *info)
+@@ -224,80 +274,85 @@ static void lx_graphics_enable(struct fb_info *info)
+ u32 temp, config;
- if (tport == NULL)
- return -ENODEV;
+ /* Set the video request register */
+- writel(0, par->df_regs + DF_VIDEO_REQUEST);
++ write_vp(par, VP_VRR, 0);
-+ spin_lock_irqsave(&tport->tp_lock, flags);
- msr = tport->tp_msr;
- mcr = tport->tp_shadow_mcr;
-+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+ /* Set up the polarities */
- 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);
+- config = readl(par->df_regs + DF_DISPLAY_CFG);
++ config = read_vp(par, VP_DCFG);
-- dbg("%s - 0x%04X", __FUNCTION__, result);
-+ dbg("%s - 0x%04X", __func__, result);
+- config &= ~(DF_DCFG_CRT_SYNC_SKW_MASK | DF_DCFG_PWR_SEQ_DLY_MASK |
+- DF_DCFG_CRT_HSYNC_POL | DF_DCFG_CRT_VSYNC_POL);
++ config &= ~(VP_DCFG_CRT_SYNC_SKW | VP_DCFG_PWR_SEQ_DELAY |
++ VP_DCFG_CRT_HSYNC_POL | VP_DCFG_CRT_VSYNC_POL);
- 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;
+- config |= (DF_DCFG_CRT_SYNC_SKW_INIT | DF_DCFG_PWR_SEQ_DLY_INIT |
+- DF_DCFG_GV_PAL_BYP);
++ config |= (VP_DCFG_CRT_SYNC_SKW_DEFAULT | VP_DCFG_PWR_SEQ_DELAY_DEFAULT
++ | VP_DCFG_GV_GAM);
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+- config |= DF_DCFG_CRT_HSYNC_POL;
++ config |= VP_DCFG_CRT_HSYNC_POL;
- if (tport == NULL)
- return -ENODEV;
+ if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+- config |= DF_DCFG_CRT_VSYNC_POL;
++ config |= VP_DCFG_CRT_VSYNC_POL;
-+ spin_lock_irqsave(&tport->tp_lock, flags);
- mcr = tport->tp_shadow_mcr;
+ if (par->output & OUTPUT_PANEL) {
+ u32 msrlo, msrhi;
- 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);
+- writel(DF_DEFAULT_TFT_PMTIM1,
+- par->df_regs + DF_PANEL_TIM1);
+- writel(DF_DEFAULT_TFT_PMTIM2,
+- par->df_regs + DF_PANEL_TIM2);
+- writel(DF_DEFAULT_TFT_DITHCTL,
+- par->df_regs + DF_DITHER_CONTROL);
++ write_fp(par, FP_PT1, 0);
++ write_fp(par, FP_PT2, FP_PT2_SCRC);
++ write_fp(par, FP_DFC, FP_DFC_BC);
- return ti_set_mcr(tport, mcr);
+- msrlo = DF_DEFAULT_TFT_PAD_SEL_LOW;
+- msrhi = DF_DEFAULT_TFT_PAD_SEL_HIGH;
++ msrlo = MSR_LX_MSR_PADSEL_TFT_SEL_LOW;
++ msrhi = MSR_LX_MSR_PADSEL_TFT_SEL_HIGH;
+
+- wrmsr(MSR_LX_DF_PADSEL, msrlo, msrhi);
++ wrmsr(MSR_LX_MSR_PADSEL, msrlo, msrhi);
+ }
+
+ if (par->output & OUTPUT_CRT) {
+- config |= DF_DCFG_CRT_EN | DF_DCFG_HSYNC_EN |
+- DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN;
++ config |= VP_DCFG_CRT_EN | VP_DCFG_HSYNC_EN |
++ VP_DCFG_VSYNC_EN | VP_DCFG_DAC_BL_EN;
+ }
+
+- writel(config, par->df_regs + DF_DISPLAY_CFG);
++ write_vp(par, VP_DCFG, config);
+
+ /* Turn the CRT dacs back on */
+
+ if (par->output & OUTPUT_CRT) {
+- temp = readl(par->df_regs + DF_MISC);
+- temp &= ~(DF_MISC_DAC_PWRDN | DF_MISC_A_PWRDN);
+- writel(temp, par->df_regs + DF_MISC);
++ temp = read_vp(par, VP_MISC);
++ temp &= ~(VP_MISC_DACPWRDN | VP_MISC_APWRDN);
++ write_vp(par, VP_MISC, temp);
+ }
+
+ /* Turn the panel on (if it isn't already) */
+-
+- if (par->output & OUTPUT_PANEL) {
+- temp = readl(par->df_regs + DF_FP_PM);
+-
+- if (!(temp & 0x09))
+- writel(temp | DF_FP_PM_P, par->df_regs + DF_FP_PM);
+- }
+-
+- temp = readl(par->df_regs + DF_MISC);
+- temp = readl(par->df_regs + DF_DISPLAY_CFG);
++ if (par->output & OUTPUT_PANEL)
++ write_fp(par, FP_PM, read_fp(par, FP_PM) | FP_PM_P);
}
-@@ -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);
+ unsigned int lx_framebuffer_size(void)
+ {
+ unsigned int val;
- 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 (!geode_has_vsa2()) {
++ uint32_t hi, lo;
++
++ /* The number of pages is (PMAX - PMIN)+1 */
++ rdmsr(MSR_GLIU_P2D_RO0, lo, hi);
++
++ /* PMAX */
++ val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20);
++ /* PMIN */
++ val -= (lo & 0x000fffff);
++ val += 1;
++
++ /* The page size is 4k */
++ return (val << 12);
++ }
++
+ /* The frame buffer size is reported by a VSM in VSA II */
+ /* Virtual Register Class = 0x02 */
+ /* VG_MEM_SIZE (1MB units) = 0x00 */
- if (status)
-- dbg("%s - error setting break, %d", __FUNCTION__, status);
-+ dbg("%s - error setting break, %d", __func__, status);
+- outw(0xFC53, 0xAC1C);
+- outw(0x0200, 0xAC1C);
++ outw(VSA_VR_UNLOCK, VSA_VRC_INDEX);
++ outw(VSA_VR_MEM_SIZE, VSA_VRC_INDEX);
+
+- val = (unsigned int)(inw(0xAC1E)) & 0xFE;
++ val = (unsigned int)(inw(VSA_VRC_DATA)) & 0xFE;
+ return (val << 20);
}
+@@ -313,7 +368,7 @@ void lx_set_mode(struct fb_info *info)
+ int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
- 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;
+ /* Unlock the DC registers */
+- writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
++ write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ lx_graphics_disable(info);
- 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;
- }
+@@ -321,102 +376,104 @@ void lx_set_mode(struct fb_info *info)
- if (length != 2) {
-- dbg("%s - bad packet size, %d", __FUNCTION__, length);
-+ dbg("%s - bad packet size, %d", __func__, length);
- goto exit;
- }
+ /* Set output mode */
- 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;
- }
+- rdmsrl(MSR_LX_DF_GLCONFIG, msrval);
+- msrval &= ~DF_CONFIG_OUTPUT_MASK;
++ rdmsrl(MSR_LX_GLD_MSR_CONFIG, msrval);
++ msrval &= ~MSR_LX_GLD_MSR_CONFIG_FMT;
- port_number = TI_GET_PORT_FROM_CODE(data[0]);
- function = TI_GET_FUNC_FROM_CODE(data[0]);
+ if (par->output & OUTPUT_PANEL) {
+- msrval |= DF_OUTPUT_PANEL;
++ msrval |= MSR_LX_GLD_MSR_CONFIG_FMT_FP;
-- 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 (par->output & OUTPUT_CRT)
+- msrval |= DF_SIMULTANEOUS_CRT_AND_FP;
++ msrval |= MSR_LX_GLD_MSR_CONFIG_FPC;
+ else
+- msrval &= ~DF_SIMULTANEOUS_CRT_AND_FP;
+- } else {
+- msrval |= DF_OUTPUT_CRT;
+- }
++ msrval &= ~MSR_LX_GLD_MSR_CONFIG_FPC;
++ } else
++ msrval |= MSR_LX_GLD_MSR_CONFIG_FMT_CRT;
- 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;
- }
+- wrmsrl(MSR_LX_DF_GLCONFIG, msrval);
++ wrmsrl(MSR_LX_GLD_MSR_CONFIG, msrval);
-@@ -1158,17 +1157,17 @@ static void ti_interrupt_callback(struct urb *urb)
+ /* Clear the various buffers */
+ /* FIXME: Adjust for panning here */
- 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]);
+- writel(0, par->dc_regs + DC_FB_START);
+- writel(0, par->dc_regs + DC_CB_START);
+- writel(0, par->dc_regs + DC_CURSOR_START);
++ write_dc(par, DC_FB_ST_OFFSET, 0);
++ write_dc(par, DC_CB_ST_OFFSET, 0);
++ write_dc(par, DC_CURS_ST_OFFSET, 0);
+
+ /* FIXME: Add support for interlacing */
+ /* FIXME: Add support for scaling */
+
+- val = readl(par->dc_regs + DC_GENLCK_CTRL);
+- val &= ~(DC_GC_ALPHA_FLICK_ENABLE |
+- DC_GC_FLICKER_FILTER_ENABLE | DC_GC_FLICKER_FILTER_MASK);
++ val = read_dc(par, DC_GENLK_CTL);
++ val &= ~(DC_GENLK_CTL_ALPHA_FLICK_EN | DC_GENLK_CTL_FLICK_EN |
++ DC_GENLK_CTL_FLICK_SEL_MASK);
+
+ /* Default scaling params */
+
+- writel((0x4000 << 16) | 0x4000, par->dc_regs + DC_GFX_SCALE);
+- writel(0, par->dc_regs + DC_IRQ_FILT_CTL);
+- writel(val, par->dc_regs + DC_GENLCK_CTRL);
++ write_dc(par, DC_GFX_SCALE, (0x4000 << 16) | 0x4000);
++ write_dc(par, DC_IRQ_FILT_CTL, 0);
++ write_dc(par, DC_GENLK_CTL, val);
+
+ /* FIXME: Support compression */
+
+ if (info->fix.line_length > 4096)
+- dv = DC_DV_LINE_SIZE_8192;
++ dv = DC_DV_CTL_DV_LINE_SIZE_8K;
+ else if (info->fix.line_length > 2048)
+- dv = DC_DV_LINE_SIZE_4096;
++ dv = DC_DV_CTL_DV_LINE_SIZE_4K;
+ else if (info->fix.line_length > 1024)
+- dv = DC_DV_LINE_SIZE_2048;
++ dv = DC_DV_CTL_DV_LINE_SIZE_2K;
+ else
+- dv = DC_DV_LINE_SIZE_1024;
++ dv = DC_DV_CTL_DV_LINE_SIZE_1K;
+
+ max = info->fix.line_length * info->var.yres;
+ max = (max + 0x3FF) & 0xFFFFFC00;
+
+- writel(max | DC_DV_TOP_ENABLE, par->dc_regs + DC_DV_TOP);
++ write_dc(par, DC_DV_TOP, max | DC_DV_TOP_DV_TOP_EN);
+
+- val = readl(par->dc_regs + DC_DV_CTL) & ~DC_DV_LINE_SIZE_MASK;
+- writel(val | dv, par->dc_regs + DC_DV_CTL);
++ val = read_dc(par, DC_DV_CTL) & ~DC_DV_CTL_DV_LINE_SIZE;
++ write_dc(par, DC_DV_CTL, val | dv);
+
+ size = info->var.xres * (info->var.bits_per_pixel >> 3);
+
+- writel(info->fix.line_length >> 3, par->dc_regs + DC_GRAPHICS_PITCH);
+- writel((size + 7) >> 3, par->dc_regs + DC_LINE_SIZE);
++ write_dc(par, DC_GFX_PITCH, info->fix.line_length >> 3);
++ write_dc(par, DC_LINE_SIZE, (size + 7) >> 3);
+
+ /* Set default watermark values */
+
+- rdmsrl(MSR_LX_DC_SPARE, msrval);
+-
+- msrval &= ~(DC_SPARE_DISABLE_CFIFO_HGO | DC_SPARE_VFIFO_ARB_SELECT |
+- DC_SPARE_LOAD_WM_LPEN_MASK | DC_SPARE_WM_LPEN_OVRD |
+- DC_SPARE_DISABLE_INIT_VID_PRI | DC_SPARE_DISABLE_VFIFO_WM);
+- msrval |= DC_SPARE_DISABLE_VFIFO_WM | DC_SPARE_DISABLE_INIT_VID_PRI;
+- wrmsrl(MSR_LX_DC_SPARE, msrval);
+-
+- gcfg = DC_GCFG_DFLE; /* Display fifo enable */
+- gcfg |= 0xB600; /* Set default priority */
+- gcfg |= DC_GCFG_FDTY; /* Set the frame dirty mode */
+-
+- dcfg = DC_DCFG_VDEN; /* Enable video data */
+- dcfg |= DC_DCFG_GDEN; /* Enable graphics */
+- dcfg |= DC_DCFG_TGEN; /* Turn on the timing generator */
+- dcfg |= DC_DCFG_TRUP; /* Update timings immediately */
+- dcfg |= DC_DCFG_PALB; /* Palette bypass in > 8 bpp modes */
+- dcfg |= DC_DCFG_VISL;
+- dcfg |= DC_DCFG_DCEN; /* Always center the display */
++ rdmsrl(MSR_LX_SPARE_MSR, msrval);
++
++ msrval &= ~(MSR_LX_SPARE_MSR_DIS_CFIFO_HGO
++ | MSR_LX_SPARE_MSR_VFIFO_ARB_SEL
++ | MSR_LX_SPARE_MSR_LOAD_WM_LPEN_M
++ | MSR_LX_SPARE_MSR_WM_LPEN_OVRD);
++ msrval |= MSR_LX_SPARE_MSR_DIS_VIFO_WM |
++ MSR_LX_SPARE_MSR_DIS_INIT_V_PRI;
++ wrmsrl(MSR_LX_SPARE_MSR, msrval);
++
++ gcfg = DC_GENERAL_CFG_DFLE; /* Display fifo enable */
++ gcfg |= (0x6 << DC_GENERAL_CFG_DFHPSL_SHIFT) | /* default priority */
++ (0xb << DC_GENERAL_CFG_DFHPEL_SHIFT);
++ gcfg |= DC_GENERAL_CFG_FDTY; /* Set the frame dirty mode */
++
++ dcfg = DC_DISPLAY_CFG_VDEN; /* Enable video data */
++ dcfg |= DC_DISPLAY_CFG_GDEN; /* Enable graphics */
++ dcfg |= DC_DISPLAY_CFG_TGEN; /* Turn on the timing generator */
++ dcfg |= DC_DISPLAY_CFG_TRUP; /* Update timings immediately */
++ dcfg |= DC_DISPLAY_CFG_PALB; /* Palette bypass in > 8 bpp modes */
++ dcfg |= DC_DISPLAY_CFG_VISL;
++ dcfg |= DC_DISPLAY_CFG_DCEN; /* Always center the display */
+
+ /* Set the current BPP mode */
+
+ switch (info->var.bits_per_pixel) {
+ case 8:
+- dcfg |= DC_DCFG_DISP_MODE_8BPP;
++ dcfg |= DC_DISPLAY_CFG_DISP_MODE_8BPP;
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);
+ case 16:
+- dcfg |= DC_DCFG_DISP_MODE_16BPP | DC_DCFG_16BPP;
++ dcfg |= DC_DISPLAY_CFG_DISP_MODE_16BPP;
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]);
+ case 32:
+ case 24:
+- dcfg |= DC_DCFG_DISP_MODE_24BPP;
++ dcfg |= DC_DISPLAY_CFG_DISP_MODE_24BPP;
+ break;
+ }
+
+@@ -436,35 +493,31 @@ void lx_set_mode(struct fb_info *info)
+ vblankend = vsyncend + info->var.upper_margin;
+ vtotal = vblankend;
+
+- writel((hactive - 1) | ((htotal - 1) << 16),
+- par->dc_regs + DC_H_ACTIVE_TIMING);
+- writel((hblankstart - 1) | ((hblankend - 1) << 16),
+- par->dc_regs + DC_H_BLANK_TIMING);
+- writel((hsyncstart - 1) | ((hsyncend - 1) << 16),
+- par->dc_regs + DC_H_SYNC_TIMING);
+-
+- writel((vactive - 1) | ((vtotal - 1) << 16),
+- par->dc_regs + DC_V_ACTIVE_TIMING);
++ write_dc(par, DC_H_ACTIVE_TIMING, (hactive - 1) | ((htotal - 1) << 16));
++ write_dc(par, DC_H_BLANK_TIMING,
++ (hblankstart - 1) | ((hblankend - 1) << 16));
++ write_dc(par, DC_H_SYNC_TIMING,
++ (hsyncstart - 1) | ((hsyncend - 1) << 16));
+
+- writel((vblankstart - 1) | ((vblankend - 1) << 16),
+- par->dc_regs + DC_V_BLANK_TIMING);
++ write_dc(par, DC_V_ACTIVE_TIMING, (vactive - 1) | ((vtotal - 1) << 16));
++ write_dc(par, DC_V_BLANK_TIMING,
++ (vblankstart - 1) | ((vblankend - 1) << 16));
++ write_dc(par, DC_V_SYNC_TIMING,
++ (vsyncstart - 1) | ((vsyncend - 1) << 16));
+
+- writel((vsyncstart - 1) | ((vsyncend - 1) << 16),
+- par->dc_regs + DC_V_SYNC_TIMING);
+-
+- writel( (info->var.xres - 1) << 16 | (info->var.yres - 1),
+- par->dc_regs + DC_FB_ACTIVE);
++ write_dc(par, DC_FB_ACTIVE,
++ (info->var.xres - 1) << 16 | (info->var.yres - 1));
+
+ /* And re-enable the graphics output */
+ lx_graphics_enable(info);
+
+ /* Write the two main configuration registers */
+- writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
+- writel(0, par->dc_regs + DC_ARB_CFG);
+- writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
++ write_dc(par, DC_DISPLAY_CFG, dcfg);
++ write_dc(par, DC_ARB_CFG, 0);
++ write_dc(par, DC_GENERAL_CFG, gcfg);
+
+ /* Lock the DC registers */
+- writel(0, par->dc_regs + DC_UNLOCK);
++ write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
+ }
+
+ void lx_set_palette_reg(struct fb_info *info, unsigned regno,
+@@ -479,58 +532,310 @@ void lx_set_palette_reg(struct fb_info *info, unsigned regno,
+ val |= (green) & 0x00ff00;
+ val |= (blue >> 8) & 0x0000ff;
+
+- writel(regno, par->dc_regs + DC_PAL_ADDRESS);
+- writel(val, par->dc_regs + DC_PAL_DATA);
++ write_dc(par, DC_PAL_ADDRESS, regno);
++ write_dc(par, DC_PAL_DATA, val);
+ }
+
+ int lx_blank_display(struct fb_info *info, int blank_mode)
+ {
+ struct lxfb_par *par = info->par;
+ u32 dcfg, fp_pm;
+- int blank, hsync, vsync;
++ int blank, hsync, vsync, crt;
+
+ /* CRT power saving modes. */
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+- blank = 0; hsync = 1; vsync = 1;
++ blank = 0; hsync = 1; vsync = 1; crt = 1;
+ break;
+ case FB_BLANK_NORMAL:
+- blank = 1; hsync = 1; vsync = 1;
++ blank = 1; hsync = 1; vsync = 1; crt = 1;
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+- blank = 1; hsync = 1; vsync = 0;
++ blank = 1; hsync = 1; vsync = 0; crt = 1;
+ break;
+ case FB_BLANK_HSYNC_SUSPEND:
+- blank = 1; hsync = 0; vsync = 1;
++ blank = 1; hsync = 0; vsync = 1; crt = 1;
+ break;
+ case FB_BLANK_POWERDOWN:
+- blank = 1; hsync = 0; vsync = 0;
++ blank = 1; hsync = 0; vsync = 0; crt = 0;
break;
+ default:
+ return -EINVAL;
}
-@@ -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);
+- dcfg = readl(par->df_regs + DF_DISPLAY_CFG);
+- dcfg &= ~(DF_DCFG_DAC_BL_EN
+- | DF_DCFG_HSYNC_EN | DF_DCFG_VSYNC_EN);
++ dcfg = read_vp(par, VP_DCFG);
++ dcfg &= ~(VP_DCFG_DAC_BL_EN | VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN |
++ VP_DCFG_CRT_EN);
+ if (!blank)
+- dcfg |= DF_DCFG_DAC_BL_EN;
++ dcfg |= VP_DCFG_DAC_BL_EN;
+ if (hsync)
+- dcfg |= DF_DCFG_HSYNC_EN;
++ dcfg |= VP_DCFG_HSYNC_EN;
+ if (vsync)
+- dcfg |= DF_DCFG_VSYNC_EN;
+- writel(dcfg, par->df_regs + DF_DISPLAY_CFG);
++ dcfg |= VP_DCFG_VSYNC_EN;
++ if (crt)
++ dcfg |= VP_DCFG_CRT_EN;
++ write_vp(par, VP_DCFG, dcfg);
+
+ /* Power on/off flat panel */
+
+ if (par->output & OUTPUT_PANEL) {
+- fp_pm = readl(par->df_regs + DF_FP_PM);
++ fp_pm = read_fp(par, FP_PM);
+ if (blank_mode == FB_BLANK_POWERDOWN)
+- fp_pm &= ~DF_FP_PM_P;
++ fp_pm &= ~FP_PM_P;
+ else
+- fp_pm |= DF_FP_PM_P;
+- writel(fp_pm, par->df_regs + DF_FP_PM);
++ fp_pm |= FP_PM_P;
++ write_fp(par, FP_PM, fp_pm);
+ }
+
+ return 0;
}
++
++#ifdef CONFIG_PM
++
++static void lx_save_regs(struct lxfb_par *par)
++{
++ uint32_t filt;
++ int i;
++
++ /* wait for the BLT engine to stop being busy */
++ do {
++ i = read_gp(par, GP_BLT_STATUS);
++ } while ((i & GP_BLT_STATUS_PB) || !(i & GP_BLT_STATUS_CE));
++
++ /* save MSRs */
++ rdmsrl(MSR_LX_MSR_PADSEL, par->msr.padsel);
++ rdmsrl(MSR_GLCP_DOTPLL, par->msr.dotpll);
++ rdmsrl(MSR_LX_GLD_MSR_CONFIG, par->msr.dfglcfg);
++ rdmsrl(MSR_LX_SPARE_MSR, par->msr.dcspare);
++
++ write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
++
++ /* save registers */
++ memcpy(par->gp, par->gp_regs, sizeof(par->gp));
++ memcpy(par->dc, par->dc_regs, sizeof(par->dc));
++ memcpy(par->vp, par->vp_regs, sizeof(par->vp));
++ memcpy(par->fp, par->vp_regs + VP_FP_START, sizeof(par->fp));
++
++ /* save the palette */
++ write_dc(par, DC_PAL_ADDRESS, 0);
++ for (i = 0; i < ARRAY_SIZE(par->pal); i++)
++ par->pal[i] = read_dc(par, DC_PAL_DATA);
++
++ /* save the horizontal filter coefficients */
++ filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL;
++ for (i = 0; i < ARRAY_SIZE(par->hcoeff); i += 2) {
++ write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);
++ par->hcoeff[i] = read_dc(par, DC_FILT_COEFF1);
++ par->hcoeff[i + 1] = read_dc(par, DC_FILT_COEFF2);
++ }
++
++ /* save the vertical filter coefficients */
++ filt &= ~DC_IRQ_FILT_CTL_H_FILT_SEL;
++ for (i = 0; i < ARRAY_SIZE(par->vcoeff); i++) {
++ write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);
++ par->vcoeff[i] = read_dc(par, DC_FILT_COEFF1);
++ }
++
++ /* save video coeff ram */
++ memcpy(par->vp_coeff, par->vp_regs + VP_VCR, sizeof(par->vp_coeff));
++}
++
++static void lx_restore_gfx_proc(struct lxfb_par *par)
++{
++ int i;
++
++ /* a bunch of registers require GP_RASTER_MODE to be set first */
++ write_gp(par, GP_RASTER_MODE, par->gp[GP_RASTER_MODE]);
++
++ for (i = 0; i < ARRAY_SIZE(par->gp); i++) {
++ switch (i) {
++ case GP_RASTER_MODE:
++ case GP_VECTOR_MODE:
++ case GP_BLT_MODE:
++ case GP_BLT_STATUS:
++ case GP_HST_SRC:
++ /* FIXME: restore LUT data */
++ case GP_LUT_INDEX:
++ case GP_LUT_DATA:
++ /* don't restore these registers */
++ break;
++
++ default:
++ write_gp(par, i, par->gp[i]);
++ }
++ }
++}
++
++static void lx_restore_display_ctlr(struct lxfb_par *par)
++{
++ uint32_t filt;
++ int i;
++
++ wrmsrl(MSR_LX_SPARE_MSR, par->msr.dcspare);
++
++ for (i = 0; i < ARRAY_SIZE(par->dc); i++) {
++ switch (i) {
++ case DC_UNLOCK:
++ /* unlock the DC; runs first */
++ write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
++ break;
++
++ case DC_GENERAL_CFG:
++ case DC_DISPLAY_CFG:
++ /* disable all while restoring */
++ write_dc(par, i, 0);
++ break;
++
++ case DC_DV_CTL:
++ /* set all ram to dirty */
++ write_dc(par, i, par->dc[i] | DC_DV_CTL_CLEAR_DV_RAM);
++
++ case DC_RSVD_1:
++ case DC_RSVD_2:
++ case DC_RSVD_3:
++ case DC_LINE_CNT:
++ case DC_PAL_ADDRESS:
++ case DC_PAL_DATA:
++ case DC_DFIFO_DIAG:
++ case DC_CFIFO_DIAG:
++ case DC_FILT_COEFF1:
++ case DC_FILT_COEFF2:
++ case DC_RSVD_4:
++ case DC_RSVD_5:
++ /* don't restore these registers */
++ break;
++
++ default:
++ write_dc(par, i, par->dc[i]);
++ }
++ }
++
++ /* restore the palette */
++ write_dc(par, DC_PAL_ADDRESS, 0);
++ for (i = 0; i < ARRAY_SIZE(par->pal); i++)
++ write_dc(par, DC_PAL_DATA, par->pal[i]);
++
++ /* restore the horizontal filter coefficients */
++ filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL;
++ for (i = 0; i < ARRAY_SIZE(par->hcoeff); i += 2) {
++ write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);
++ write_dc(par, DC_FILT_COEFF1, par->hcoeff[i]);
++ write_dc(par, DC_FILT_COEFF2, par->hcoeff[i + 1]);
++ }
++
++ /* restore the vertical filter coefficients */
++ filt &= ~DC_IRQ_FILT_CTL_H_FILT_SEL;
++ for (i = 0; i < ARRAY_SIZE(par->vcoeff); i++) {
++ write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);
++ write_dc(par, DC_FILT_COEFF1, par->vcoeff[i]);
++ }
++}
++
++static void lx_restore_video_proc(struct lxfb_par *par)
++{
++ int i;
++
++ wrmsrl(MSR_LX_GLD_MSR_CONFIG, par->msr.dfglcfg);
++ wrmsrl(MSR_LX_MSR_PADSEL, par->msr.padsel);
++
++ for (i = 0; i < ARRAY_SIZE(par->vp); i++) {
++ switch (i) {
++ case VP_VCFG:
++ case VP_DCFG:
++ case VP_PAR:
++ case VP_PDR:
++ case VP_CCS:
++ case VP_RSVD_0:
++ /* case VP_VDC: */ /* why should this not be restored? */
++ case VP_RSVD_1:
++ case VP_CRC32:
++ /* don't restore these registers */
++ break;
++
++ default:
++ write_vp(par, i, par->vp[i]);
++ }
++ }
++
++ /* restore video coeff ram */
++ memcpy(par->vp_regs + VP_VCR, par->vp_coeff, sizeof(par->vp_coeff));
++}
++
++static void lx_restore_regs(struct lxfb_par *par)
++{
++ int i;
++
++ lx_set_dotpll((u32) (par->msr.dotpll >> 32));
++ lx_restore_gfx_proc(par);
++ lx_restore_display_ctlr(par);
++ lx_restore_video_proc(par);
++
++ /* Flat Panel */
++ for (i = 0; i < ARRAY_SIZE(par->fp); i++) {
++ switch (i) {
++ case FP_PM:
++ case FP_RSVD_0:
++ case FP_RSVD_1:
++ case FP_RSVD_2:
++ case FP_RSVD_3:
++ case FP_RSVD_4:
++ /* don't restore these registers */
++ break;
++
++ default:
++ write_fp(par, i, par->fp[i]);
++ }
++ }
++
++ /* control the panel */
++ if (par->fp[FP_PM] & FP_PM_P) {
++ /* power on the panel if not already power{ed,ing} on */
++ if (!(read_fp(par, FP_PM) &
++ (FP_PM_PANEL_ON|FP_PM_PANEL_PWR_UP)))
++ write_fp(par, FP_PM, par->fp[FP_PM]);
++ } else {
++ /* power down the panel if not already power{ed,ing} down */
++ if (!(read_fp(par, FP_PM) &
++ (FP_PM_PANEL_OFF|FP_PM_PANEL_PWR_DOWN)))
++ write_fp(par, FP_PM, par->fp[FP_PM]);
++ }
++
++ /* turn everything on */
++ write_vp(par, VP_VCFG, par->vp[VP_VCFG]);
++ write_vp(par, VP_DCFG, par->vp[VP_DCFG]);
++ write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG]);
++ /* do this last; it will enable the FIFO load */
++ write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG]);
++
++ /* lock the door behind us */
++ write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
++}
++
++int lx_powerdown(struct fb_info *info)
++{
++ struct lxfb_par *par = info->par;
++
++ if (par->powered_down)
++ return 0;
++
++ lx_save_regs(par);
++ lx_graphics_disable(info);
++
++ par->powered_down = 1;
++ return 0;
++}
++
++int lx_powerup(struct fb_info *info)
++{
++ struct lxfb_par *par = info->par;
++
++ if (!par->powered_down)
++ return 0;
++
++ lx_restore_regs(par);
++
++ par->powered_down = 0;
++ return 0;
++}
++
++#endif
+diff --git a/drivers/video/geode/suspend_gx.c b/drivers/video/geode/suspend_gx.c
+new file mode 100644
+index 0000000..9aff32e
+--- /dev/null
++++ b/drivers/video/geode/suspend_gx.c
+@@ -0,0 +1,267 @@
++/*
++ * Copyright (C) 2007 Advanced Micro Devices, Inc.
++ * Copyright (C) 2008 Andres Salomon <dilinger at debian.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++#include <linux/fb.h>
++#include <asm/io.h>
++#include <asm/msr.h>
++#include <asm/geode.h>
++#include <asm/delay.h>
++
++#include "gxfb.h"
++
++#ifdef CONFIG_PM
++
++static void gx_save_regs(struct gxfb_par *par)
++{
++ int i;
++
++ /* wait for the BLT engine to stop being busy */
++ do {
++ i = read_gp(par, GP_BLT_STATUS);
++ } while (i & (GP_BLT_STATUS_BLT_PENDING | GP_BLT_STATUS_BLT_BUSY));
++
++ /* save MSRs */
++ rdmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel);
++ rdmsrl(MSR_GLCP_DOTPLL, par->msr.dotpll);
++
++ write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
++
++ /* save registers */
++ memcpy(par->gp, par->gp_regs, sizeof(par->gp));
++ memcpy(par->dc, par->dc_regs, sizeof(par->dc));
++ memcpy(par->vp, par->vid_regs, sizeof(par->vp));
++ memcpy(par->fp, par->vid_regs + VP_FP_START, sizeof(par->fp));
++
++ /* save the palette */
++ write_dc(par, DC_PAL_ADDRESS, 0);
++ for (i = 0; i < ARRAY_SIZE(par->pal); i++)
++ par->pal[i] = read_dc(par, DC_PAL_DATA);
++}
++
++static void gx_set_dotpll(uint32_t dotpll_hi)
++{
++ uint32_t dotpll_lo;
++ int i;
++
++ rdmsrl(MSR_GLCP_DOTPLL, dotpll_lo);
++ dotpll_lo |= MSR_GLCP_DOTPLL_DOTRESET;
++ dotpll_lo &= ~MSR_GLCP_DOTPLL_BYPASS;
++ wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
++
++ /* wait for the PLL to lock */
++ for (i = 0; i < 200; i++) {
++ rdmsrl(MSR_GLCP_DOTPLL, dotpll_lo);
++ if (dotpll_lo & MSR_GLCP_DOTPLL_LOCK)
++ break;
++ udelay(1);
++ }
++
++ /* PLL set, unlock */
++ dotpll_lo &= ~MSR_GLCP_DOTPLL_DOTRESET;
++ wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
++}
++
++static void gx_restore_gfx_proc(struct gxfb_par *par)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(par->gp); i++) {
++ switch (i) {
++ case GP_VECTOR_MODE:
++ case GP_BLT_MODE:
++ case GP_BLT_STATUS:
++ case GP_HST_SRC:
++ /* don't restore these registers */
++ break;
++ default:
++ write_gp(par, i, par->gp[i]);
++ }
++ }
++}
++
++static void gx_restore_display_ctlr(struct gxfb_par *par)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(par->dc); i++) {
++ switch (i) {
++ case DC_UNLOCK:
++ /* unlock the DC; runs first */
++ write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
++ break;
++
++ case DC_GENERAL_CFG:
++ /* write without the enables */
++ write_dc(par, i, par->dc[i] & ~(DC_GENERAL_CFG_VIDE |
++ DC_GENERAL_CFG_ICNE |
++ DC_GENERAL_CFG_CURE |
++ DC_GENERAL_CFG_DFLE));
++ break;
++
++ case DC_DISPLAY_CFG:
++ /* write without the enables */
++ write_dc(par, i, par->dc[i] & ~(DC_DISPLAY_CFG_VDEN |
++ DC_DISPLAY_CFG_GDEN |
++ DC_DISPLAY_CFG_TGEN));
++ break;
++
++ case DC_RSVD_0:
++ case DC_RSVD_1:
++ case DC_RSVD_2:
++ case DC_RSVD_3:
++ case DC_RSVD_4:
++ case DC_LINE_CNT:
++ case DC_PAL_ADDRESS:
++ case DC_PAL_DATA:
++ case DC_DFIFO_DIAG:
++ case DC_CFIFO_DIAG:
++ case DC_RSVD_5:
++ /* don't restore these registers */
++ break;
++ default:
++ write_dc(par, i, par->dc[i]);
++ }
++ }
++
++ /* restore the palette */
++ write_dc(par, DC_PAL_ADDRESS, 0);
++ for (i = 0; i < ARRAY_SIZE(par->pal); i++)
++ write_dc(par, DC_PAL_DATA, par->pal[i]);
++}
++
++static void gx_restore_video_proc(struct gxfb_par *par)
++{
++ int i;
++
++ wrmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel);
++
++ for (i = 0; i < ARRAY_SIZE(par->vp); i++) {
++ switch (i) {
++ case VP_VCFG:
++ /* don't enable video yet */
++ write_vp(par, i, par->vp[i] & ~VP_VCFG_VID_EN);
++ break;
++
++ case VP_DCFG:
++ /* don't enable CRT yet */
++ write_vp(par, i, par->vp[i] &
++ ~(VP_DCFG_DAC_BL_EN | VP_DCFG_VSYNC_EN |
++ VP_DCFG_HSYNC_EN | VP_DCFG_CRT_EN));
++ break;
++
++ case VP_GAR:
++ case VP_GDR:
++ case VP_RSVD_0:
++ case VP_RSVD_1:
++ case VP_RSVD_2:
++ case VP_RSVD_3:
++ case VP_CRC32:
++ case VP_AWT:
++ case VP_VTM:
++ /* don't restore these registers */
++ break;
++ default:
++ write_vp(par, i, par->vp[i]);
++ }
++ }
++}
++
++static void gx_restore_regs(struct gxfb_par *par)
++{
++ int i;
++
++ gx_set_dotpll((uint32_t) (par->msr.dotpll >> 32));
++ gx_restore_gfx_proc(par);
++ gx_restore_display_ctlr(par);
++ gx_restore_video_proc(par);
++
++ /* Flat Panel */
++ for (i = 0; i < ARRAY_SIZE(par->fp); i++) {
++ if (i != FP_PM && i != FP_RSVD_0)
++ write_fp(par, i, par->fp[i]);
++ }
++}
++
++static void gx_disable_graphics(struct gxfb_par *par)
++{
++ /* shut down the engine */
++ write_vp(par, VP_VCFG, par->vp[VP_VCFG] & ~VP_VCFG_VID_EN);
++ write_vp(par, VP_DCFG, par->vp[VP_DCFG] & ~(VP_DCFG_DAC_BL_EN |
++ VP_DCFG_VSYNC_EN | VP_DCFG_HSYNC_EN | VP_DCFG_CRT_EN));
++
++ /* turn off the flat panel */
++ write_fp(par, FP_PM, par->fp[FP_PM] & ~FP_PM_P);
++
++
++ /* turn off display */
++ write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
++ write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG] &
++ ~(DC_GENERAL_CFG_VIDE | DC_GENERAL_CFG_ICNE |
++ DC_GENERAL_CFG_CURE | DC_GENERAL_CFG_DFLE));
++ write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG] &
++ ~(DC_DISPLAY_CFG_VDEN | DC_DISPLAY_CFG_GDEN |
++ DC_DISPLAY_CFG_TGEN));
++ write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
++}
++
++static void gx_enable_graphics(struct gxfb_par *par)
++{
++ uint32_t fp;
++
++ fp = read_fp(par, FP_PM);
++ if (par->fp[FP_PM] & FP_PM_P) {
++ /* power on the panel if not already power{ed,ing} on */
++ if (!(fp & (FP_PM_PANEL_ON|FP_PM_PANEL_PWR_UP)))
++ write_fp(par, FP_PM, par->fp[FP_PM]);
++ } else {
++ /* power down the panel if not already power{ed,ing} down */
++ if (!(fp & (FP_PM_PANEL_OFF|FP_PM_PANEL_PWR_DOWN)))
++ write_fp(par, FP_PM, par->fp[FP_PM]);
++ }
++
++ /* turn everything on */
++ write_vp(par, VP_VCFG, par->vp[VP_VCFG]);
++ write_vp(par, VP_DCFG, par->vp[VP_DCFG]);
++ write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG]);
++ /* do this last; it will enable the FIFO load */
++ write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG]);
++
++ /* lock the door behind us */
++ write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
++}
++
++int gx_powerdown(struct fb_info *info)
++{
++ struct gxfb_par *par = info->par;
++
++ if (par->powered_down)
++ return 0;
++
++ gx_save_regs(par);
++ gx_disable_graphics(par);
++
++ par->powered_down = 1;
++ return 0;
++}
++
++int gx_powerup(struct fb_info *info)
++{
++ struct gxfb_par *par = info->par;
++
++ if (!par->powered_down)
++ return 0;
++
++ gx_restore_regs(par);
++ gx_enable_graphics(par);
++
++ par->powered_down = 0;
++ return 0;
++}
++
++#endif
+diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c
+index febf09c..b8d52a8 100644
+--- a/drivers/video/geode/video_gx.c
++++ b/drivers/video/geode/video_gx.c
+@@ -16,9 +16,9 @@
+ #include <asm/io.h>
+ #include <asm/delay.h>
+ #include <asm/msr.h>
++#include <asm/geode.h>
+-#include "geodefb.h"
+-#include "video_gx.h"
++#include "gxfb.h"
- static void ti_bulk_in_callback(struct urb *urb)
+
+ /*
+@@ -117,7 +117,7 @@ static const struct gx_pll_entry gx_pll_table_14MHz[] = {
+ { 4357, 0, 0x0000057D }, /* 229.5000 */
+ };
+
+-static void gx_set_dclk_frequency(struct fb_info *info)
++void gx_set_dclk_frequency(struct fb_info *info)
{
-- 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;
+ const struct gx_pll_entry *pll_table;
+ int pll_table_len;
+@@ -178,110 +178,116 @@ static void gx_set_dclk_frequency(struct fb_info *info)
+ static void
+ gx_configure_tft(struct fb_info *info)
+ {
+- struct geodefb_par *par = info->par;
++ struct gxfb_par *par = info->par;
+ unsigned long val;
+ unsigned long fp;
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ /* Set up the DF pad select MSR */
- 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;
+- rdmsrl(GX_VP_MSR_PAD_SELECT, val);
+- val &= ~GX_VP_PAD_SELECT_MASK;
+- val |= GX_VP_PAD_SELECT_TFT;
+- wrmsrl(GX_VP_MSR_PAD_SELECT, val);
++ rdmsrl(MSR_GX_MSR_PADSEL, val);
++ val &= ~MSR_GX_MSR_PADSEL_MASK;
++ val |= MSR_GX_MSR_PADSEL_TFT;
++ wrmsrl(MSR_GX_MSR_PADSEL, val);
+
+ /* Turn off the panel */
+
+- fp = readl(par->vid_regs + GX_FP_PM);
+- fp &= ~GX_FP_PM_P;
+- writel(fp, par->vid_regs + GX_FP_PM);
++ fp = read_fp(par, FP_PM);
++ fp &= ~FP_PM_P;
++ write_fp(par, FP_PM, fp);
+
+ /* Set timing 1 */
+
+- fp = readl(par->vid_regs + GX_FP_PT1);
+- fp &= GX_FP_PT1_VSIZE_MASK;
+- fp |= info->var.yres << GX_FP_PT1_VSIZE_SHIFT;
+- writel(fp, par->vid_regs + GX_FP_PT1);
++ fp = read_fp(par, FP_PT1);
++ fp &= FP_PT1_VSIZE_MASK;
++ fp |= info->var.yres << FP_PT1_VSIZE_SHIFT;
++ write_fp(par, FP_PT1, fp);
+
+ /* Timing 2 */
+ /* Set bits that are always on for TFT */
+
+ fp = 0x0F100000;
+
+- /* Add sync polarity */
++ /* Configure sync polarity */
+
+ if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
+- fp |= GX_FP_PT2_VSP;
++ fp |= FP_PT2_VSP;
+
+ if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
+- fp |= GX_FP_PT2_HSP;
++ fp |= FP_PT2_HSP;
+
+- writel(fp, par->vid_regs + GX_FP_PT2);
++ write_fp(par, FP_PT2, fp);
+
+ /* Set the dither control */
+- writel(0x70, par->vid_regs + GX_FP_DFC);
++ write_fp(par, FP_DFC, FP_DFC_NFI);
+
+ /* Enable the FP data and power (in case the BIOS didn't) */
+
+- fp = readl(par->vid_regs + GX_DCFG);
+- fp |= GX_DCFG_FP_PWR_EN | GX_DCFG_FP_DATA_EN;
+- writel(fp, par->vid_regs + GX_DCFG);
++ fp = read_vp(par, VP_DCFG);
++ fp |= VP_DCFG_FP_PWR_EN | VP_DCFG_FP_DATA_EN;
++ write_vp(par, VP_DCFG, fp);
+
+ /* Unblank the panel */
+
+- fp = readl(par->vid_regs + GX_FP_PM);
+- fp |= GX_FP_PM_P;
+- writel(fp, par->vid_regs + GX_FP_PM);
++ fp = read_fp(par, FP_PM);
++ fp |= FP_PM_P;
++ write_fp(par, FP_PM, fp);
+ }
+
+-static void gx_configure_display(struct fb_info *info)
++void gx_configure_display(struct fb_info *info)
+ {
+- struct geodefb_par *par = info->par;
++ struct gxfb_par *par = info->par;
+ u32 dcfg, misc;
+
+- /* Set up the MISC register */
+-
+- misc = readl(par->vid_regs + GX_MISC);
+-
+- /* Power up the DAC */
+- misc &= ~(GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN);
+-
+- /* Disable gamma correction */
+- misc |= GX_MISC_GAM_EN;
+-
+- writel(misc, par->vid_regs + GX_MISC);
+-
+ /* Write the display configuration */
+- dcfg = readl(par->vid_regs + GX_DCFG);
++ dcfg = read_vp(par, VP_DCFG);
+
+ /* Disable hsync and vsync */
+- dcfg &= ~(GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
+- writel(dcfg, par->vid_regs + GX_DCFG);
++ dcfg &= ~(VP_DCFG_VSYNC_EN | VP_DCFG_HSYNC_EN);
++ write_vp(par, VP_DCFG, dcfg);
+
+ /* Clear bits from existing mode. */
+- dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK
+- | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL
+- | GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
++ dcfg &= ~(VP_DCFG_CRT_SYNC_SKW
++ | VP_DCFG_CRT_HSYNC_POL | VP_DCFG_CRT_VSYNC_POL
++ | VP_DCFG_VSYNC_EN | VP_DCFG_HSYNC_EN);
+
+ /* Set default sync skew. */
+- dcfg |= GX_DCFG_CRT_SYNC_SKW_DFLT;
++ dcfg |= VP_DCFG_CRT_SYNC_SKW_DEFAULT;
+
+ /* Enable hsync and vsync. */
+- dcfg |= GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN;
++ dcfg |= VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN;
+
+- /* Sync polarities. */
+- if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+- dcfg |= GX_DCFG_CRT_HSYNC_POL;
+- if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+- dcfg |= GX_DCFG_CRT_VSYNC_POL;
++ misc = read_vp(par, VP_MISC);
++
++ /* Disable gamma correction */
++ misc |= VP_MISC_GAM_EN;
++
++ if (par->enable_crt) {
++
++ /* Power up the CRT DACs */
++ misc &= ~(VP_MISC_APWRDN | VP_MISC_DACPWRDN);
++ write_vp(par, VP_MISC, misc);
++
++ /* Only change the sync polarities if we are running
++ * in CRT mode. The FP polarities will be handled in
++ * gxfb_configure_tft */
++ if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
++ dcfg |= VP_DCFG_CRT_HSYNC_POL;
++ if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
++ dcfg |= VP_DCFG_CRT_VSYNC_POL;
++ } else {
++ /* Power down the CRT DACs if in FP mode */
++ misc |= (VP_MISC_APWRDN | VP_MISC_DACPWRDN);
++ write_vp(par, VP_MISC, misc);
++ }
- if (status) {
-- dev_err(dev, "%s - stopping read!\n", __FUNCTION__);
-+ dev_err(dev, "%s - stopping read!\n", __func__);
- return;
- }
+ /* Enable the display logic */
+ /* Set up the DACS to blank normally */
- 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);
+- dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN;
++ dcfg |= VP_DCFG_CRT_EN | VP_DCFG_DAC_BL_EN;
- 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);
- }
+ /* Enable the external DAC VREF? */
+- writel(dcfg, par->vid_regs + GX_DCFG);
++ write_vp(par, VP_DCFG, dcfg);
- 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;
+ /* Set up the flat panel (if it is enabled) */
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+@@ -289,59 +295,55 @@ static void gx_configure_display(struct fb_info *info)
+ gx_configure_tft(info);
+ }
- tport->tp_write_urb_in_use = 0;
+-static int gx_blank_display(struct fb_info *info, int blank_mode)
++int gx_blank_display(struct fb_info *info, int blank_mode)
+ {
+- struct geodefb_par *par = info->par;
++ struct gxfb_par *par = info->par;
+ u32 dcfg, fp_pm;
+- int blank, hsync, vsync;
++ int blank, hsync, vsync, crt;
-@@ -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;
+ /* CRT power saving modes. */
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+- blank = 0; hsync = 1; vsync = 1;
++ blank = 0; hsync = 1; vsync = 1; crt = 1;
+ break;
+ case FB_BLANK_NORMAL:
+- blank = 1; hsync = 1; vsync = 1;
++ blank = 1; hsync = 1; vsync = 1; crt = 1;
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+- blank = 1; hsync = 1; vsync = 0;
++ blank = 1; hsync = 1; vsync = 0; crt = 1;
+ break;
+ case FB_BLANK_HSYNC_SUSPEND:
+- blank = 1; hsync = 0; vsync = 1;
++ blank = 1; hsync = 0; vsync = 1; crt = 1;
+ break;
+ case FB_BLANK_POWERDOWN:
+- blank = 1; hsync = 0; vsync = 0;
++ blank = 1; hsync = 0; vsync = 0; crt = 0;
+ break;
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);
+ return -EINVAL;
}
-@@ -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;
+- dcfg = readl(par->vid_regs + GX_DCFG);
+- dcfg &= ~(GX_DCFG_DAC_BL_EN
+- | GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN);
++ dcfg = read_vp(par, VP_DCFG);
++ dcfg &= ~(VP_DCFG_DAC_BL_EN | VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN |
++ VP_DCFG_CRT_EN);
+ if (!blank)
+- dcfg |= GX_DCFG_DAC_BL_EN;
++ dcfg |= VP_DCFG_DAC_BL_EN;
+ if (hsync)
+- dcfg |= GX_DCFG_HSYNC_EN;
++ dcfg |= VP_DCFG_HSYNC_EN;
+ if (vsync)
+- dcfg |= GX_DCFG_VSYNC_EN;
+- writel(dcfg, par->vid_regs + GX_DCFG);
++ dcfg |= VP_DCFG_VSYNC_EN;
++ if (crt)
++ dcfg |= VP_DCFG_CRT_EN;
++ write_vp(par, VP_DCFG, dcfg);
+
+ /* Power on/off flat panel. */
+
+ if (par->enable_crt == 0) {
+- fp_pm = readl(par->vid_regs + GX_FP_PM);
++ fp_pm = read_fp(par, FP_PM);
+ if (blank_mode == FB_BLANK_POWERDOWN)
+- fp_pm &= ~GX_FP_PM_P;
++ fp_pm &= ~FP_PM_P;
+ else
+- fp_pm |= GX_FP_PM_P;
+- writel(fp_pm, par->vid_regs + GX_FP_PM);
++ fp_pm |= FP_PM_P;
++ write_fp(par, FP_PM, fp_pm);
+ }
+
+ return 0;
+ }
+-
+-struct geode_vid_ops gx_vid_ops = {
+- .set_dclk = gx_set_dclk_frequency,
+- .configure_display = gx_configure_display,
+- .blank_display = gx_blank_display,
+-};
+diff --git a/drivers/video/geode/video_gx.h b/drivers/video/geode/video_gx.h
+deleted file mode 100644
+index ce28d8f..0000000
+--- a/drivers/video/geode/video_gx.h
++++ /dev/null
+@@ -1,72 +0,0 @@
+-/*
+- * Geode GX video device
+- *
+- * Copyright (C) 2006 Arcom Control Systems Ltd.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- */
+-#ifndef __VIDEO_GX_H__
+-#define __VIDEO_GX_H__
+-
+-extern struct geode_vid_ops gx_vid_ops;
+-
+-/* GX Flatpanel control MSR */
+-#define GX_VP_MSR_PAD_SELECT 0xC0002011
+-#define GX_VP_PAD_SELECT_MASK 0x3FFFFFFF
+-#define GX_VP_PAD_SELECT_TFT 0x1FFFFFFF
+-
+-/* Geode GX video processor registers */
+-
+-#define GX_DCFG 0x0008
+-# define GX_DCFG_CRT_EN 0x00000001
+-# define GX_DCFG_HSYNC_EN 0x00000002
+-# define GX_DCFG_VSYNC_EN 0x00000004
+-# define GX_DCFG_DAC_BL_EN 0x00000008
+-# define GX_DCFG_FP_PWR_EN 0x00000040
+-# define GX_DCFG_FP_DATA_EN 0x00000080
+-# define GX_DCFG_CRT_HSYNC_POL 0x00000100
+-# define GX_DCFG_CRT_VSYNC_POL 0x00000200
+-# define GX_DCFG_CRT_SYNC_SKW_MASK 0x0001C000
+-# define GX_DCFG_CRT_SYNC_SKW_DFLT 0x00010000
+-# define GX_DCFG_VG_CK 0x00100000
+-# define GX_DCFG_GV_GAM 0x00200000
+-# define GX_DCFG_DAC_VREF 0x04000000
+-
+-/* Geode GX MISC video configuration */
+-
+-#define GX_MISC 0x50
+-#define GX_MISC_GAM_EN 0x00000001
+-#define GX_MISC_DAC_PWRDN 0x00000400
+-#define GX_MISC_A_PWRDN 0x00000800
+-
+-/* Geode GX flat panel display control registers */
+-
+-#define GX_FP_PT1 0x0400
+-#define GX_FP_PT1_VSIZE_MASK 0x7FF0000
+-#define GX_FP_PT1_VSIZE_SHIFT 16
+-
+-#define GX_FP_PT2 0x408
+-#define GX_FP_PT2_VSP (1 << 23)
+-#define GX_FP_PT2_HSP (1 << 22)
+-
+-#define GX_FP_PM 0x410
+-# define GX_FP_PM_P 0x01000000
+-
+-#define GX_FP_DFC 0x418
+-
+-/* Geode GX clock control MSRs */
+-
+-#define MSR_GLCP_SYS_RSTPLL 0x4c000014
+-# define MSR_GLCP_SYS_RSTPLL_DOTPREDIV2 (0x0000000000000002ull)
+-# define MSR_GLCP_SYS_RSTPLL_DOTPREMULT2 (0x0000000000000004ull)
+-# define MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 (0x0000000000000008ull)
+-
+-#define MSR_GLCP_DOTPLL 0x4c000015
+-# define MSR_GLCP_DOTPLL_DOTRESET (0x0000000000000001ull)
+-# define MSR_GLCP_DOTPLL_BYPASS (0x0000000000008000ull)
+-# define MSR_GLCP_DOTPLL_LOCK (0x0000000002000000ull)
+-
+-#endif /* !__VIDEO_GX_H__ */
+diff --git a/drivers/video/gxt4500.c b/drivers/video/gxt4500.c
+index e92337b..5645577 100644
+--- a/drivers/video/gxt4500.c
++++ b/drivers/video/gxt4500.c
+@@ -238,7 +238,7 @@ static int calc_pll(int period_ps, struct gxt4500_par *par)
+ for (pdiv1 = 1; pdiv1 <= 8; ++pdiv1) {
+ for (pdiv2 = 1; pdiv2 <= pdiv1; ++pdiv2) {
+ postdiv = pdiv1 * pdiv2;
+- pll_period = (period_ps + postdiv - 1) / postdiv;
++ pll_period = DIV_ROUND_UP(period_ps, postdiv);
+ /* keep pll in range 350..600 MHz */
+ if (pll_period < 1666 || pll_period > 2857)
+ continue;
+diff --git a/drivers/video/hecubafb.c b/drivers/video/hecubafb.c
+index 94e0df8..0b4bffb 100644
+--- a/drivers/video/hecubafb.c
++++ b/drivers/video/hecubafb.c
+@@ -1,5 +1,5 @@
+ /*
+- * linux/drivers/video/hecubafb.c -- FB driver for Hecuba controller
++ * linux/drivers/video/hecubafb.c -- FB driver for Hecuba/Apollo controller
+ *
+ * Copyright (C) 2006, Jaya Kumar
+ * This work was sponsored by CIS(M) Sdn Bhd
+@@ -17,18 +17,13 @@
+ * values. There are other commands that the display is capable of,
+ * beyond the 5 used here but they are more complex.
+ *
+- * This driver is written to be used with the Hecuba display controller
+- * board, and tested with the EInk 800x600 display in 1 bit mode.
+- * The interface between Hecuba and the host is TTL based GPIO. The
+- * GPIO requirements are 8 writable data lines and 6 lines for control.
+- * Only 4 of the controls are actually used here but 6 for future use.
+- * The driver requires the IO addresses for data and control GPIO at
+- * load time. It is also possible to use this display with a standard
+- * PC parallel port.
++ * This driver is written to be used with the Hecuba display architecture.
++ * The actual display chip is called Apollo and the interface electronics
++ * it needs is called Hecuba.
+ *
+- * General notes:
+- * - User must set hecubafb_enable=1 to enable it
+- * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR c2io_addr=0xIOADDR
++ * It is intended to be architecture independent. A board specific driver
++ * must be used to perform all the physical IO interactions. An example
++ * is provided as n411.c
+ *
+ */
+@@ -47,34 +42,12 @@
+ #include <linux/list.h>
+ #include <linux/uaccess.h>
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+-/* Apollo controller specific defines */
+-#define APOLLO_START_NEW_IMG 0xA0
+-#define APOLLO_STOP_IMG_DATA 0xA1
+-#define APOLLO_DISPLAY_IMG 0xA2
+-#define APOLLO_ERASE_DISPLAY 0xA3
+-#define APOLLO_INIT_DISPLAY 0xA4
+-
+-/* Hecuba interface specific defines */
+-/* WUP is inverted, CD is inverted, DS is inverted */
+-#define HCB_NWUP_BIT 0x01
+-#define HCB_NDS_BIT 0x02
+-#define HCB_RW_BIT 0x04
+-#define HCB_NCD_BIT 0x08
+-#define HCB_ACK_BIT 0x80
++#include <video/hecubafb.h>
+
+ /* Display specific information */
+ #define DPY_W 600
+ #define DPY_H 800
+
+-struct hecubafb_par {
+- unsigned long dio_addr;
+- unsigned long cio_addr;
+- unsigned long c2io_addr;
+- unsigned char ctl;
+- struct fb_info *info;
+- unsigned int irq;
+-};
+-
+ static struct fb_fix_screeninfo hecubafb_fix __devinitdata = {
+ .id = "hecubafb",
+ .type = FB_TYPE_PACKED_PIXELS,
+@@ -82,6 +55,7 @@ static struct fb_fix_screeninfo hecubafb_fix __devinitdata = {
+ .xpanstep = 0,
+ .ypanstep = 0,
+ .ywrapstep = 0,
++ .line_length = DPY_W,
+ .accel = FB_ACCEL_NONE,
+ };
- spin_lock_irqsave(&tport->tp_lock, flags);
+@@ -94,136 +68,51 @@ static struct fb_var_screeninfo hecubafb_var __devinitdata = {
+ .nonstd = 1,
+ };
-@@ -1330,7 +1329,7 @@ static void ti_send(struct ti_port *tport)
+-static unsigned long dio_addr;
+-static unsigned long cio_addr;
+-static unsigned long c2io_addr;
+-static unsigned long splashval;
+-static unsigned int nosplash;
+-static unsigned int hecubafb_enable;
+-static unsigned int irq;
+-
+-static DECLARE_WAIT_QUEUE_HEAD(hecubafb_waitq);
+-
+-static void hcb_set_ctl(struct hecubafb_par *par)
+-{
+- outb(par->ctl, par->cio_addr);
+-}
+-
+-static unsigned char hcb_get_ctl(struct hecubafb_par *par)
+-{
+- return inb(par->c2io_addr);
+-}
+-
+-static void hcb_set_data(struct hecubafb_par *par, unsigned char value)
+-{
+- outb(value, par->dio_addr);
+-}
+-
+-static int __devinit apollo_init_control(struct hecubafb_par *par)
+-{
+- unsigned char ctl;
+- /* for init, we want the following setup to be set:
+- WUP = lo
+- ACK = hi
+- DS = hi
+- RW = hi
+- CD = lo
+- */
+-
+- /* write WUP to lo, DS to hi, RW to hi, CD to lo */
+- par->ctl = HCB_NWUP_BIT | HCB_RW_BIT | HCB_NCD_BIT ;
+- par->ctl &= ~HCB_NDS_BIT;
+- hcb_set_ctl(par);
+-
+- /* check ACK is not lo */
+- ctl = hcb_get_ctl(par);
+- if ((ctl & HCB_ACK_BIT)) {
+- printk(KERN_ERR "Fail because ACK is already low\n");
+- return -ENXIO;
+- }
+-
+- return 0;
+-}
+-
+-static void hcb_wait_for_ack(struct hecubafb_par *par)
+-{
+-
+- int timeout;
+- unsigned char ctl;
+-
+- timeout=500;
+- do {
+- ctl = hcb_get_ctl(par);
+- if ((ctl & HCB_ACK_BIT))
+- return;
+- udelay(1);
+- } while (timeout--);
+- printk(KERN_ERR "timed out waiting for ack\n");
+-}
+-
+-static void hcb_wait_for_ack_clear(struct hecubafb_par *par)
+-{
+-
+- int timeout;
+- unsigned char ctl;
+-
+- timeout=500;
+- do {
+- ctl = hcb_get_ctl(par);
+- if (!(ctl & HCB_ACK_BIT))
+- return;
+- udelay(1);
+- } while (timeout--);
+- printk(KERN_ERR "timed out waiting for clear\n");
+-}
++/* main hecubafb functions */
- spin_unlock_irqrestore(&tport->tp_lock, flags);
+ static void apollo_send_data(struct hecubafb_par *par, unsigned char data)
+ {
+ /* set data */
+- hcb_set_data(par, data);
++ par->board->set_data(par, data);
-- 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 DS low */
+- par->ctl |= HCB_NDS_BIT;
+- hcb_set_ctl(par);
++ par->board->set_ctl(par, HCB_DS_BIT, 0);
- 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)
+- hcb_wait_for_ack(par);
++ /* wait for ack */
++ par->board->wait_for_ack(par, 0);
- 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)
+ /* set DS hi */
+- par->ctl &= ~(HCB_NDS_BIT);
+- hcb_set_ctl(par);
++ par->board->set_ctl(par, HCB_DS_BIT, 1);
- static int ti_set_mcr(struct ti_port *tport, unsigned int mcr)
- {
-+ unsigned long flags;
- int status;
+- hcb_wait_for_ack_clear(par);
++ /* wait for ack to clear */
++ par->board->wait_for_ack(par, 1);
+ }
- 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);
+ static void apollo_send_command(struct hecubafb_par *par, unsigned char data)
+ {
+ /* command so set CD to high */
+- par->ctl &= ~(HCB_NCD_BIT);
+- hcb_set_ctl(par);
++ par->board->set_ctl(par, HCB_CD_BIT, 1);
-+ spin_lock_irqsave(&tport->tp_lock, flags);
- if (!status)
- tport->tp_shadow_mcr = mcr;
-+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+ /* actually strobe with command */
+ apollo_send_data(par, data);
- return status;
+ /* clear CD back to low */
+- par->ctl |= (HCB_NCD_BIT);
+- hcb_set_ctl(par);
++ par->board->set_ctl(par, HCB_CD_BIT, 0);
}
-@@ -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);
+-/* main hecubafb functions */
+-
+ static void hecubafb_dpy_update(struct hecubafb_par *par)
+ {
+ int i;
+ unsigned char *buf = (unsigned char __force *)par->info->screen_base;
- 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;
- }
+- apollo_send_command(par, 0xA0);
++ apollo_send_command(par, APOLLO_START_NEW_IMG);
- 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;
+ for (i=0; i < (DPY_W*DPY_H/8); i++) {
+ apollo_send_data(par, *(buf++));
}
-- dbg("%s - lsr 0x%02X", __FUNCTION__, data->bLSR);
-+ dbg("%s - lsr 0x%02X", __func__, data->bLSR);
+- apollo_send_command(par, 0xA1);
+- apollo_send_command(par, 0xA2);
++ apollo_send_command(par, APOLLO_STOP_IMG_DATA);
++ apollo_send_command(par, APOLLO_DISPLAY_IMG);
+ }
- tport->tp_lsr = data->bLSR;
+ /* this is called back from the deferred io workqueue */
+@@ -270,41 +159,43 @@ static void hecubafb_imageblit(struct fb_info *info,
+ static ssize_t hecubafb_write(struct fb_info *info, const char __user *buf,
+ size_t count, loff_t *ppos)
+ {
+- unsigned long p;
+- int err=-EINVAL;
+- struct hecubafb_par *par;
+- unsigned int xres;
+- unsigned int fbmemlength;
++ struct hecubafb_par *par = info->par;
++ unsigned long p = *ppos;
++ void *dst;
++ int err = 0;
++ unsigned long total_size;
-@@ -1456,7 +1458,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
- struct tty_struct *tty;
- unsigned long flags;
+- p = *ppos;
+- par = info->par;
+- xres = info->var.xres;
+- fbmemlength = (xres * info->var.yres)/8;
++ if (info->state != FBINFO_STATE_RUNNING)
++ return -EPERM;
-- dbg("%s - msr 0x%02X", __FUNCTION__, msr);
-+ dbg("%s - msr 0x%02X", __func__, msr);
+- if (p > fbmemlength)
+- return -ENOSPC;
++ total_size = info->fix.smem_len;
- 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;
+- err = 0;
+- if ((count + p) > fbmemlength) {
+- count = fbmemlength - p;
+- err = -ENOSPC;
++ if (p > total_size)
++ return -EFBIG;
++
++ if (count > total_size) {
++ err = -EFBIG;
++ count = total_size;
+ }
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- if (count) {
+- char *base_addr;
++ if (count + p > total_size) {
++ if (!err)
++ err = -ENOSPC;
- spin_lock_irq(&tport->tp_lock);
+- base_addr = (char __force *)info->screen_base;
+- count -= copy_from_user(base_addr + p, buf, count);
+- *ppos += count;
+- err = -EFAULT;
++ count = total_size - p;
+ }
-@@ -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;
+- hecubafb_dpy_update(par);
++ dst = (void __force *) (info->screen_base + p);
++
++ if (copy_from_user(dst, buf, count))
++ err = -EFAULT;
-- 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);
+- if (count)
+- return count;
++ if (!err)
++ *ppos += count;
- 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;
- }
+- return err;
++ hecubafb_dpy_update(par);
++
++ return (err) ? err : count;
+ }
-@@ -1647,7 +1649,7 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
- (__u8 *)data, size);
+ static struct fb_ops hecubafb_ops = {
+@@ -324,11 +215,21 @@ static struct fb_deferred_io hecubafb_defio = {
+ static int __devinit hecubafb_probe(struct platform_device *dev)
+ {
+ struct fb_info *info;
++ struct hecuba_board *board;
+ int retval = -ENOMEM;
+ int videomemorysize;
+ unsigned char *videomemory;
+ struct hecubafb_par *par;
+
++ /* pick up board specific routines */
++ board = dev->dev.platform_data;
++ if (!board)
++ return -EINVAL;
++
++ /* try to count device specific driver, if can't, platform recalls */
++ if (!try_module_get(board->owner))
++ return -ENODEV;
++
+ videomemorysize = (DPY_W*DPY_H)/8;
- if (status < 0)
-- dev_err(dev, "%s - failed, %d\n", __FUNCTION__, status);
-+ dev_err(dev, "%s - failed, %d\n", __func__, status);
+ if (!(videomemory = vmalloc(videomemorysize)))
+@@ -338,9 +239,9 @@ static int __devinit hecubafb_probe(struct platform_device *dev)
- kfree(data);
+ info = framebuffer_alloc(sizeof(struct hecubafb_par), &dev->dev);
+ if (!info)
+- goto err;
++ goto err_fballoc;
-@@ -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;
- }
+- info->screen_base = (char __iomem *) videomemory;
++ info->screen_base = (char __force __iomem *)videomemory;
+ info->fbops = &hecubafb_ops;
+
+ info->var = hecubafb_var;
+@@ -348,14 +249,10 @@ static int __devinit hecubafb_probe(struct platform_device *dev)
+ info->fix.smem_len = videomemorysize;
+ par = info->par;
+ par->info = info;
++ par->board = board;
++ par->send_command = apollo_send_command;
++ par->send_data = apollo_send_data;
-@@ -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;
+- if (!dio_addr || !cio_addr || !c2io_addr) {
+- printk(KERN_WARNING "no IO addresses supplied\n");
+- goto err1;
+- }
+- par->dio_addr = dio_addr;
+- par->cio_addr = cio_addr;
+- par->c2io_addr = c2io_addr;
+ info->flags = FBINFO_FLAG_DEFAULT;
-- 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);
+ info->fbdefio = &hecubafb_defio;
+@@ -363,7 +260,7 @@ static int __devinit hecubafb_probe(struct platform_device *dev)
- 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;
- }
+ retval = register_framebuffer(info);
+ if (retval < 0)
+- goto err1;
++ goto err_fbreg;
+ platform_set_drvdata(dev, info);
-- dbg("%s - download successful", __FUNCTION__);
-+ dbg("%s - download successful", __func__);
+ printk(KERN_INFO
+@@ -371,25 +268,16 @@ static int __devinit hecubafb_probe(struct platform_device *dev)
+ info->node, videomemorysize >> 10);
+
+ /* this inits the dpy */
+- apollo_init_control(par);
+-
+- apollo_send_command(par, APOLLO_INIT_DISPLAY);
+- apollo_send_data(par, 0x81);
+-
+- /* have to wait while display resets */
+- udelay(1000);
+-
+- /* if we were told to splash the screen, we just clear it */
+- if (!nosplash) {
+- apollo_send_command(par, APOLLO_ERASE_DISPLAY);
+- apollo_send_data(par, splashval);
+- }
++ retval = par->board->init(par);
++ if (retval < 0)
++ goto err_fbreg;
return 0;
+-err1:
++err_fbreg:
+ framebuffer_release(info);
+-err:
++err_fballoc:
+ vfree(videomemory);
++ module_put(board->owner);
+ return retval;
}
-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);
+@@ -398,9 +286,13 @@ static int __devexit hecubafb_remove(struct platform_device *dev)
+ struct fb_info *info = platform_get_drvdata(dev);
- *minor = 0;
- mutex_lock(&table_lock);
-@@ -101,7 +101,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
+ if (info) {
++ struct hecubafb_par *par = info->par;
+ fb_deferred_io_cleanup(info);
+ unregister_framebuffer(info);
+ vfree((void __force *)info->screen_base);
++ if (par->board->remove)
++ par->board->remove(par);
++ module_put(par->board->owner);
+ framebuffer_release(info);
+ }
+ return 0;
+@@ -410,62 +302,24 @@ static struct platform_driver hecubafb_driver = {
+ .probe = hecubafb_probe,
+ .remove = hecubafb_remove,
+ .driver = {
++ .owner = THIS_MODULE,
+ .name = "hecubafb",
+ },
+ };
- *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)
+-static struct platform_device *hecubafb_device;
+-
+ static int __init hecubafb_init(void)
{
- int i;
+- int ret;
+-
+- if (!hecubafb_enable) {
+- printk(KERN_ERR "Use hecubafb_enable to enable the device\n");
+- return -ENXIO;
+- }
+-
+- ret = platform_driver_register(&hecubafb_driver);
+- if (!ret) {
+- hecubafb_device = platform_device_alloc("hecubafb", 0);
+- if (hecubafb_device)
+- ret = platform_device_add(hecubafb_device);
+- else
+- ret = -ENOMEM;
+-
+- if (ret) {
+- platform_device_put(hecubafb_device);
+- platform_driver_unregister(&hecubafb_driver);
+- }
+- }
+- return ret;
+-
++ return platform_driver_register(&hecubafb_driver);
+ }
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ static void __exit hecubafb_exit(void)
+ {
+- platform_device_unregister(hecubafb_device);
+ platform_driver_unregister(&hecubafb_driver);
+ }
- if (serial == NULL)
- return;
-@@ -135,7 +135,7 @@ static void destroy_serial(struct kref *kref)
+-module_param(nosplash, uint, 0);
+-MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
+-module_param(hecubafb_enable, uint, 0);
+-MODULE_PARM_DESC(hecubafb_enable, "Enable communication with Hecuba board");
+-module_param(dio_addr, ulong, 0);
+-MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
+-module_param(cio_addr, ulong, 0);
+-MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
+-module_param(c2io_addr, ulong, 0);
+-MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
+-module_param(splashval, ulong, 0);
+-MODULE_PARM_DESC(splashval, "Splash pattern: 0x00 is black, 0x01 is white");
+-module_param(irq, uint, 0);
+-MODULE_PARM_DESC(irq, "IRQ for the Hecuba board");
+-
+ module_init(hecubafb_init);
+ module_exit(hecubafb_exit);
+
+-MODULE_DESCRIPTION("fbdev driver for Hecuba board");
++MODULE_DESCRIPTION("fbdev driver for Hecuba/Apollo controller");
+ MODULE_AUTHOR("Jaya Kumar");
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
+index 3ab91bf..15d50b9 100644
+--- a/drivers/video/imsttfb.c
++++ b/drivers/video/imsttfb.c
+@@ -1151,8 +1151,10 @@ imsttfb_load_cursor_image(struct imstt_par *par, int width, int height, __u8 fgc
+ par->cmap_regs[TVPCRDAT] = 0xff; eieio();
+ }
+ par->cmap_regs[TVPCADRW] = 0x00; eieio();
+- for (x = 0; x < 12; x++)
+- par->cmap_regs[TVPCDATA] = fgc; eieio();
++ for (x = 0; x < 12; x++) {
++ par->cmap_regs[TVPCDATA] = fgc;
++ eieio();
++ }
+ }
+ return 1;
+ }
+@@ -1476,7 +1478,7 @@ imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+
+ dp = pci_device_to_OF_node(pdev);
+ if(dp)
+- printk(KERN_INFO "%s: OF name %s\n",__FUNCTION__, dp->name);
++ printk(KERN_INFO "%s: OF name %s\n",__func__, dp->name);
+ else
+ printk(KERN_ERR "imsttfb: no OF node for pci device\n");
+ #endif /* CONFIG_PPC_OF */
+diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
+index 1160955..94e4d3a 100644
+--- a/drivers/video/imxfb.c
++++ b/drivers/video/imxfb.c
+@@ -415,7 +415,7 @@ static void imxfb_setup_gpio(struct imxfb_info *fbi)
+ static int imxfb_suspend(struct platform_device *dev, pm_message_t state)
+ {
+ struct imxfb_info *fbi = platform_get_drvdata(dev);
+- pr_debug("%s\n",__FUNCTION__);
++ pr_debug("%s\n",__func__);
+
+ imxfb_disable_controller(fbi);
+ return 0;
+@@ -424,7 +424,7 @@ static int imxfb_suspend(struct platform_device *dev, pm_message_t state)
+ static int imxfb_resume(struct platform_device *dev)
+ {
+ struct imxfb_info *fbi = platform_get_drvdata(dev);
+- pr_debug("%s\n",__FUNCTION__);
++ pr_debug("%s\n",__func__);
+
+ imxfb_enable_controller(fbi);
+ return 0;
+@@ -440,7 +440,7 @@ static int __init imxfb_init_fbinfo(struct device *dev)
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct imxfb_info *fbi = info->par;
+
+- pr_debug("%s\n",__FUNCTION__);
++ pr_debug("%s\n",__func__);
+
+ info->pseudo_palette = kmalloc( sizeof(u32) * 16, GFP_KERNEL);
+ if (!info->pseudo_palette)
+diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
+index 8367961..3325fbd 100644
+--- a/drivers/video/intelfb/intelfb.h
++++ b/drivers/video/intelfb/intelfb.h
+@@ -12,9 +12,9 @@
+ #endif
- serial = to_usb_serial(kref);
+ /*** Version/name ***/
+-#define INTELFB_VERSION "0.9.4"
++#define INTELFB_VERSION "0.9.5"
+ #define INTELFB_MODULE_NAME "intelfb"
+-#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM"
++#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM"
+
+
+ /*** Debug/feature defines ***/
+@@ -58,6 +58,8 @@
+ #define PCI_DEVICE_ID_INTEL_915GM 0x2592
+ #define PCI_DEVICE_ID_INTEL_945G 0x2772
+ #define PCI_DEVICE_ID_INTEL_945GM 0x27A2
++#define PCI_DEVICE_ID_INTEL_965G 0x29A2
++#define PCI_DEVICE_ID_INTEL_965GM 0x2A02
+
+ /* Size of MMIO region */
+ #define INTEL_REG_SIZE 0x80000
+@@ -158,6 +160,8 @@ enum intel_chips {
+ INTEL_915GM,
+ INTEL_945G,
+ INTEL_945GM,
++ INTEL_965G,
++ INTEL_965GM,
+ };
+
+ struct intelfb_hwstate {
+@@ -358,7 +362,9 @@ struct intelfb_info {
+ #define IS_I9XX(dinfo) (((dinfo)->chipset == INTEL_915G) || \
+ ((dinfo)->chipset == INTEL_915GM) || \
+ ((dinfo)->chipset == INTEL_945G) || \
+- ((dinfo)->chipset==INTEL_945GM))
++ ((dinfo)->chipset == INTEL_945GM) || \
++ ((dinfo)->chipset == INTEL_965G) || \
++ ((dinfo)->chipset == INTEL_965GM))
+
+ #ifndef FBIO_WAITFORVSYNC
+ #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
+diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c
+index 94c08bb..ca95f09 100644
+--- a/drivers/video/intelfb/intelfb_i2c.c
++++ b/drivers/video/intelfb/intelfb_i2c.c
+@@ -169,6 +169,8 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
+ /* has some LVDS + tv-out */
+ case INTEL_945G:
+ case INTEL_945GM:
++ case INTEL_965G:
++ case INTEL_965GM:
+ /* SDVO ports have a single control bus - 2 devices */
+ dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
+ intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
+diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
+index 481d58f..e44303f 100644
+--- a/drivers/video/intelfb/intelfbdrv.c
++++ b/drivers/video/intelfb/intelfbdrv.c
+@@ -2,7 +2,7 @@
+ * intelfb
+ *
+ * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/
+- * 945G/945GM integrated graphics chips.
++ * 945G/945GM/965G/965GM integrated graphics chips.
+ *
+ * Copyright © 2002, 2003 David Dawes <dawes at xfree86.org>
+ * 2004 Sylvain Meyer
+@@ -99,6 +99,9 @@
+ * Add vram option to reserve more memory than stolen by BIOS
+ * Fix intelfbhw_pan_display typo
+ * Add __initdata annotations
++ *
++ * 04/2008 - Version 0.9.5
++ * Add support for 965G/965GM. (Maik Broemme <mbroemme at plusserver.de>)
+ */
-- dbg("%s - %s", __FUNCTION__, serial->type->description);
-+ dbg("%s - %s", __func__, serial->type->description);
+ #include <linux/module.h>
+@@ -180,6 +183,8 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = {
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GM },
++ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965G },
++ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965GM },
+ { 0, }
+ };
- serial->type->shutdown(serial);
+@@ -549,7 +554,10 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev,
+ if ((ent->device == PCI_DEVICE_ID_INTEL_915G) ||
+ (ent->device == PCI_DEVICE_ID_INTEL_915GM) ||
+ (ent->device == PCI_DEVICE_ID_INTEL_945G) ||
+- (ent->device == PCI_DEVICE_ID_INTEL_945GM)) {
++ (ent->device == PCI_DEVICE_ID_INTEL_945GM) ||
++ (ent->device == PCI_DEVICE_ID_INTEL_965G) ||
++ (ent->device == PCI_DEVICE_ID_INTEL_965GM)) {
++
+ aperture_bar = 2;
+ mmio_bar = 0;
+ }
+diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
+index fa1fff5..8e6d6a4 100644
+--- a/drivers/video/intelfb/intelfbhw.c
++++ b/drivers/video/intelfb/intelfbhw.c
+@@ -143,6 +143,18 @@ int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
+ dinfo->mobile = 1;
+ dinfo->pll_index = PLLS_I9xx;
+ return 0;
++ case PCI_DEVICE_ID_INTEL_965G:
++ dinfo->name = "Intel(R) 965G";
++ dinfo->chipset = INTEL_965G;
++ dinfo->mobile = 0;
++ dinfo->pll_index = PLLS_I9xx;
++ return 0;
++ case PCI_DEVICE_ID_INTEL_965GM:
++ dinfo->name = "Intel(R) 965GM";
++ dinfo->chipset = INTEL_965GM;
++ dinfo->mobile = 1;
++ dinfo->pll_index = PLLS_I9xx;
++ return 0;
+ default:
+ return 1;
+ }
+@@ -174,7 +186,9 @@ int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
+ case PCI_DEVICE_ID_INTEL_915GM:
+ case PCI_DEVICE_ID_INTEL_945G:
+ case PCI_DEVICE_ID_INTEL_945GM:
+- /* 915 and 945 chipsets support a 256MB aperture.
++ case PCI_DEVICE_ID_INTEL_965G:
++ case PCI_DEVICE_ID_INTEL_965GM:
++ /* 915, 945 and 965 chipsets support a 256MB aperture.
+ Aperture size is determined by inspected the
+ base address of the aperture. */
+ if (pci_resource_start(pdev, 2) & 0x08000000)
+diff --git a/drivers/video/leo.c b/drivers/video/leo.c
+index 45b9a5d..f3160fc 100644
+--- a/drivers/video/leo.c
++++ b/drivers/video/leo.c
+@@ -614,7 +614,7 @@ static int __devinit leo_probe(struct of_device *op, const struct of_device_id *
+
+ dev_set_drvdata(&op->dev, info);
+
+- printk("%s: leo at %lx:%lx\n",
++ printk(KERN_INFO "%s: leo at %lx:%lx\n",
+ dp->full_name,
+ par->which_io, par->physbase);
+
+diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c
+index c4b570b..0ce3b0a 100644
+--- a/drivers/video/matrox/matroxfb_DAC1064.c
++++ b/drivers/video/matrox/matroxfb_DAC1064.c
+@@ -37,7 +37,7 @@ static void DAC1064_calcclock(CPMINFO unsigned int freq, unsigned int fmax, unsi
+ unsigned int fvco;
+ unsigned int p;
-@@ -187,7 +187,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
- unsigned int portNumber;
- int retval;
+- DBG(__FUNCTION__)
++ DBG(__func__)
-- 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;
+ /* only for devices older than G450 */
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+@@ -83,7 +83,7 @@ static const unsigned char MGA1064_DAC[] = {
+ static void DAC1064_setpclk(WPMINFO unsigned long fout) {
+ unsigned int m, n, p;
+
+- DBG(__FUNCTION__)
++ DBG(__func__)
+
+ DAC1064_calcclock(PMINFO fout, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p);
+ ACCESS_FBINFO(hw).DACclk[0] = m;
+@@ -95,7 +95,7 @@ static void DAC1064_setmclk(WPMINFO int oscinfo, unsigned long fmem) {
+ u_int32_t mx;
+ struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
+
+- DBG(__FUNCTION__)
++ DBG(__func__)
+
+ if (ACCESS_FBINFO(devflags.noinit)) {
+ /* read MCLK and give up... */
+@@ -338,7 +338,7 @@ void DAC1064_global_restore(WPMINFO2) {
+ static int DAC1064_init_1(WPMINFO struct my_timming* m) {
+ struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
+
+- DBG(__FUNCTION__)
++ DBG(__func__)
+
+ memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs));
+ switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) {
+@@ -374,7 +374,7 @@ static int DAC1064_init_1(WPMINFO struct my_timming* m) {
+ static int DAC1064_init_2(WPMINFO struct my_timming* m) {
+ struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
- mutex_lock(&port->mutex);
+- DBG(__FUNCTION__)
++ DBG(__func__)
-@@ -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;
+ if (ACCESS_FBINFO(fbcon).var.bits_per_pixel > 16) { /* 256 entries */
+ int i;
+@@ -418,7 +418,7 @@ static void DAC1064_restore_1(WPMINFO2) {
-- dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
-+ dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
+ CRITFLAGS
- if (!port->open_count) {
- retval = -EINVAL;
-- dbg("%s - port not opened", __FUNCTION__);
-+ dbg("%s - port not opened", __func__);
- goto exit;
- }
+- DBG(__FUNCTION__)
++ DBG(__func__)
-@@ -322,10 +322,10 @@ static int serial_write_room (struct tty_struct *tty)
- if (!port)
- goto exit;
+ CRITBEGIN
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+@@ -448,7 +448,7 @@ static void DAC1064_restore_2(WPMINFO2) {
+ unsigned int i;
+ #endif
- if (!port->open_count) {
-- dbg("%s - port not open", __FUNCTION__);
-+ dbg("%s - port not open", __func__);
- goto exit;
- }
+- DBG(__FUNCTION__)
++ DBG(__func__)
-@@ -344,10 +344,10 @@ static int serial_chars_in_buffer (struct tty_struct *tty)
- if (!port)
- goto exit;
+ #ifdef DEBUG
+ dprintk(KERN_DEBUG "DAC1064regs ");
+@@ -521,7 +521,7 @@ static struct matrox_altout g450out = {
+ static int MGA1064_init(WPMINFO struct my_timming* m) {
+ struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
-- dbg("%s = port %d", __FUNCTION__, port->number);
-+ dbg("%s = port %d", __func__, port->number);
+- DBG(__FUNCTION__)
++ DBG(__func__)
- if (!port->open_count) {
-- dbg("%s - port not open", __FUNCTION__);
-+ dbg("%s - port not open", __func__);
- goto exit;
- }
+ if (DAC1064_init_1(PMINFO m)) return 1;
+ if (matroxfb_vgaHWinit(PMINFO m)) return 1;
+@@ -543,7 +543,7 @@ static int MGA1064_init(WPMINFO struct my_timming* m) {
+ static int MGAG100_init(WPMINFO struct my_timming* m) {
+ struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
-@@ -365,10 +365,10 @@ static void serial_throttle (struct tty_struct * tty)
- if (!port)
- return;
+- DBG(__FUNCTION__)
++ DBG(__func__)
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ if (DAC1064_init_1(PMINFO m)) return 1;
+ hw->MXoptionReg &= ~0x2000;
+@@ -565,7 +565,7 @@ static int MGAG100_init(WPMINFO struct my_timming* m) {
+ #ifdef CONFIG_FB_MATROX_MYSTIQUE
+ static void MGA1064_ramdac_init(WPMINFO2) {
- if (!port->open_count) {
-- dbg ("%s - port not open", __FUNCTION__);
-+ dbg ("%s - port not open", __func__);
- return;
- }
+- DBG(__FUNCTION__)
++ DBG(__func__)
-@@ -384,10 +384,10 @@ static void serial_unthrottle (struct tty_struct * tty)
- if (!port)
- return;
+ /* ACCESS_FBINFO(features.DAC1064.vco_freq_min) = 120000; */
+ ACCESS_FBINFO(features.pll.vco_freq_min) = 62000;
+@@ -594,7 +594,7 @@ static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p) {
+ int selClk;
+ int clk;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- DBG(__FUNCTION__)
++ DBG(__func__)
- if (!port->open_count) {
-- dbg("%s - port not open", __FUNCTION__);
-+ dbg("%s - port not open", __func__);
- return;
- }
+ outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS |
+ M1064_XPIXCLKCTRL_PLL_UP);
+@@ -636,7 +636,7 @@ static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p) {
+ static void MGAG100_setPixClock(CPMINFO int flags, int freq) {
+ unsigned int m, n, p;
-@@ -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;
+- DBG(__FUNCTION__)
++ DBG(__func__)
-+ lock_kernel();
- if (!port)
- goto exit;
+ DAC1064_calcclock(PMINFO freq, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p);
+ MGAG100_progPixClock(PMINFO flags, m, n, p);
+@@ -650,7 +650,7 @@ static int MGA1064_preinit(WPMINFO2) {
+ 2048, 0};
+ struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
-- dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
-+ dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
+- DBG(__FUNCTION__)
++ DBG(__func__)
-+ /* 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;
- }
+ /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */
+ ACCESS_FBINFO(capable.text) = 1;
+@@ -683,7 +683,7 @@ static int MGA1064_preinit(WPMINFO2) {
-@@ -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;
- }
+ static void MGA1064_reset(WPMINFO2) {
-@@ -428,10 +430,10 @@ static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
- if (!port)
- return;
+- DBG(__FUNCTION__);
++ DBG(__func__);
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ MGA1064_ramdac_init(PMINFO2);
+ }
+@@ -819,7 +819,7 @@ static int MGAG100_preinit(WPMINFO2) {
+ u_int32_t q;
+ #endif
- if (!port->open_count) {
-- dbg("%s - port not open", __FUNCTION__);
-+ dbg("%s - port not open", __func__);
- return;
- }
+- DBG(__FUNCTION__)
++ DBG(__func__)
-@@ -446,19 +448,24 @@ static void serial_break (struct tty_struct *tty, int break_state)
- {
- struct usb_serial_port *port = tty->driver_data;
+ /* there are some instabilities if in_div > 19 && vco < 61000 */
+ if (ACCESS_FBINFO(devflags.g450dac)) {
+@@ -956,7 +956,7 @@ static void MGAG100_reset(WPMINFO2) {
+ u_int8_t b;
+ struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
-- if (!port)
-+ lock_kernel();
-+ if (!port) {
-+ unlock_kernel();
- return;
-+ }
+- DBG(__FUNCTION__)
++ DBG(__func__)
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ {
+ #ifdef G100_BROKEN_IBM_82351
+@@ -1015,7 +1015,7 @@ static void MGA1064_restore(WPMINFO2) {
- if (!port->open_count) {
-- dbg("%s - port not open", __FUNCTION__);
-+ dbg("%s - port not open", __func__);
-+ unlock_kernel();
- return;
- }
+ CRITFLAGS
- /* 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();
- }
+- DBG(__FUNCTION__)
++ DBG(__func__)
- 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];
+ CRITBEGIN
-- 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;
+@@ -1041,7 +1041,7 @@ static void MGAG100_restore(WPMINFO2) {
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ CRITFLAGS
- if (!port->open_count) {
-- dbg("%s - port not open", __FUNCTION__);
-+ dbg("%s - port not open", __func__);
- return -ENODEV;
- }
+- DBG(__FUNCTION__)
++ DBG(__func__)
-@@ -536,10 +543,10 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file,
- if (!port)
- return -ENODEV;
+ CRITBEGIN
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c
+index 9445cdb..1352482 100644
+--- a/drivers/video/matrox/matroxfb_Ti3026.c
++++ b/drivers/video/matrox/matroxfb_Ti3026.c
+@@ -283,7 +283,7 @@ static int Ti3026_calcclock(CPMINFO unsigned int freq, unsigned int fmax, int* i
+ unsigned int fvco;
+ unsigned int lin, lfeed, lpost;
- if (!port->open_count) {
-- dbg("%s - port not open", __FUNCTION__);
-+ dbg("%s - port not open", __func__);
- return -ENODEV;
- }
+- DBG(__FUNCTION__)
++ DBG(__func__)
-@@ -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;
+ fvco = PLL_calcclock(PMINFO freq, fmax, &lin, &lfeed, &lpost);
+ fvco >>= (*post = lpost);
+@@ -297,7 +297,7 @@ static int Ti3026_setpclk(WPMINFO int clk) {
+ unsigned int pixfeed, pixin, pixpost;
+ struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
-- 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(__FUNCTION__)
++ DBG(__func__)
-- dbg ("%s - %s", __FUNCTION__, dev->bus_id);
-+ dbg ("%s - %s", __func__, dev->bus_id);
- port_free(port);
- }
+ f_pll = Ti3026_calcclock(PMINFO clk, ACCESS_FBINFO(max_pixel_clock), &pixin, &pixfeed, &pixpost);
-@@ -627,7 +634,7 @@ static struct usb_serial * create_serial (struct usb_device *dev,
+@@ -365,7 +365,7 @@ static int Ti3026_init(WPMINFO struct my_timming* m) {
+ u_int8_t muxctrl = isInterleave(MINFO) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT;
+ struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
- 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;
- }
+- DBG(__FUNCTION__)
++ DBG(__func__)
-@@ -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;
+ memcpy(hw->DACreg, MGADACbpp32, sizeof(hw->DACreg));
+ switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) {
+@@ -440,7 +440,7 @@ static void ti3026_setMCLK(WPMINFO int fout){
+ unsigned int rfhcnt, mclk_ctl;
+ int tmout;
--#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(__FUNCTION__)
++ DBG(__func__)
-- 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;
+ f_pll = Ti3026_calcclock(PMINFO fout, ACCESS_FBINFO(max_pixel_clock), &mclk_n, &mclk_m, &mclk_p);
- 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;
+@@ -534,7 +534,7 @@ static void ti3026_setMCLK(WPMINFO int fout){
- usb_serial_console_disconnect(serial);
-- dbg ("%s", __FUNCTION__);
-+ dbg ("%s", __func__);
+ static void ti3026_ramdac_init(WPMINFO2) {
- mutex_lock(&serial->disc_mutex);
- usb_set_intfdata (interface, NULL);
-@@ -1174,7 +1165,7 @@ static int __init usb_serial_init(void)
+- DBG(__FUNCTION__)
++ DBG(__func__)
- 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;
- }
+ ACCESS_FBINFO(features.pll.vco_freq_min) = 110000;
+ ACCESS_FBINFO(features.pll.ref_freq) = 114545;
+@@ -554,7 +554,7 @@ static void Ti3026_restore(WPMINFO2) {
+ struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
+ CRITFLAGS
-@@ -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;
- }
+- DBG(__FUNCTION__)
++ DBG(__func__)
- /* 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;
- }
+ #ifdef DEBUG
+ dprintk(KERN_INFO "EXTVGA regs: ");
+@@ -662,7 +662,7 @@ static void Ti3026_restore(WPMINFO2) {
- /* 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;
- }
+ static void Ti3026_reset(WPMINFO2) {
-@@ -1223,7 +1216,7 @@ exit_reg_driver:
- bus_unregister(&usb_serial_bus_type);
+- DBG(__FUNCTION__)
++ DBG(__func__)
- 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;
+ ti3026_ramdac_init(PMINFO2);
}
-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,
- };
+@@ -680,7 +680,7 @@ static int Ti3026_preinit(WPMINFO2) {
+ 2048, 0};
+ struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
-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(__FUNCTION__)
++ DBG(__func__)
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ ACCESS_FBINFO(millenium) = 1;
+ ACCESS_FBINFO(milleniumII) = (ACCESS_FBINFO(pcidev)->device != PCI_DEVICE_ID_MATROX_MIL);
+diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c
+index 3660d26..9c3aeee 100644
+--- a/drivers/video/matrox/matroxfb_accel.c
++++ b/drivers/video/matrox/matroxfb_accel.c
+@@ -113,7 +113,7 @@ void matrox_cfbX_init(WPMINFO2) {
+ u_int32_t mopmode;
+ int accel;
- 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(__FUNCTION__)
++ DBG(__func__)
-- 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;
+ mpitch = ACCESS_FBINFO(fbcon).var.xres_virtual;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+@@ -199,7 +199,7 @@ static void matrox_accel_bmove(WPMINFO int vxres, int sy, int sx, int dy, int dx
+ int start, end;
+ CRITFLAGS
- 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,
+- DBG(__FUNCTION__)
++ DBG(__func__)
- memcpy (buffer, buf, count);
+ CRITBEGIN
-- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
-+ usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
+@@ -235,7 +235,7 @@ static void matrox_accel_bmove_lin(WPMINFO int vxres, int sy, int sx, int dy, in
+ int start, end;
+ CRITFLAGS
- 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(__FUNCTION__)
++ DBG(__func__)
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ CRITBEGIN
- /*
- * 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)
+@@ -287,7 +287,7 @@ static void matroxfb_accel_clear(WPMINFO u_int32_t color, int sy, int sx, int he
+ int width) {
+ CRITFLAGS
- 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);
+- DBG(__FUNCTION__)
++ DBG(__func__)
- /*
- * 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)
+ CRITBEGIN
- 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);
+@@ -315,7 +315,7 @@ static void matroxfb_cfb4_clear(WPMINFO u_int32_t bgx, int sy, int sx, int heigh
+ int whattodo;
+ CRITFLAGS
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- DBG(__FUNCTION__)
++ DBG(__func__)
- if (status)
- dbg("%s - nonzero write bulk status received: %d",
-- __FUNCTION__, status);
-+ __func__, status);
+ CRITBEGIN
- spin_lock_irqsave(&priv->lock, flags);
- --priv->outstanding_urbs;
-@@ -509,7 +502,7 @@ static void visor_write_bulk_callback (struct urb *urb)
+@@ -388,7 +388,7 @@ static void matroxfb_1bpp_imageblit(WPMINFO u_int32_t fgx, u_int32_t bgx,
+ int easy;
+ CRITFLAGS
- 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_HEAVY(__FUNCTION__);
++ DBG_HEAVY(__func__);
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ step = (width + 7) >> 3;
+ charcell = height * step;
+@@ -469,7 +469,7 @@ static void matroxfb_1bpp_imageblit(WPMINFO u_int32_t fgx, u_int32_t bgx,
+ static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image) {
+ MINFO_FROM_INFO(info);
- if (status) {
- dbg("%s - nonzero read bulk status received: %d",
-- __FUNCTION__, status);
-+ __func__, status);
- return;
- }
+- DBG_HEAVY(__FUNCTION__);
++ DBG_HEAVY(__func__);
-- 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 (image->depth == 1) {
+ u_int32_t fgx, bgx;
+diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
+index b25972a..54e82f3 100644
+--- a/drivers/video/matrox/matroxfb_base.c
++++ b/drivers/video/matrox/matroxfb_base.c
+@@ -312,7 +312,7 @@ static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
- 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)
+ CRITFLAGS
- 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;
+- DBG(__FUNCTION__)
++ DBG(__func__)
-@@ -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);
+ if (ACCESS_FBINFO(dead))
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);
+@@ -392,7 +392,7 @@ static int matroxfb_open(struct fb_info *info, int user)
+ {
+ MINFO_FROM_INFO(info);
- 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);
- }
+- DBG_LOOP(__FUNCTION__)
++ DBG_LOOP(__func__)
- 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;
+ if (ACCESS_FBINFO(dead)) {
+ return -ENXIO;
+@@ -408,7 +408,7 @@ static int matroxfb_release(struct fb_info *info, int user)
+ {
+ MINFO_FROM_INFO(info);
-- 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_LOOP(__FUNCTION__)
++ DBG_LOOP(__func__)
-- 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);
- }
+ if (user) {
+ if (0 == --ACCESS_FBINFO(userusecount)) {
+@@ -425,7 +425,7 @@ static int matroxfb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info* info) {
+ MINFO_FROM_INFO(info);
- 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(__FUNCTION__)
++ DBG(__func__)
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ matrox_pan_var(PMINFO var);
+ return 0;
+@@ -434,7 +434,7 @@ static int matroxfb_pan_display(struct fb_var_screeninfo *var,
+ static int matroxfb_get_final_bppShift(CPMINFO int bpp) {
+ int bppshft2;
- 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;
- }
+- DBG(__FUNCTION__)
++ DBG(__func__)
-@@ -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;
+ bppshft2 = bpp;
+ if (!bppshft2) {
+@@ -451,7 +451,7 @@ static int matroxfb_test_and_set_rounding(CPMINFO int xres, int bpp) {
+ int over;
+ int rounding;
- 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(__FUNCTION__)
++ DBG(__func__)
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ switch (bpp) {
+ case 0: return xres;
+@@ -482,7 +482,7 @@ static int matroxfb_pitch_adjust(CPMINFO int xres, int bpp) {
+ const int* width;
+ int xres_new;
- 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);
+- DBG(__FUNCTION__)
++ DBG(__func__)
- 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);
+ if (!bpp) return xres;
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+@@ -504,7 +504,7 @@ static int matroxfb_pitch_adjust(CPMINFO int xres, int bpp) {
- 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;
+ static int matroxfb_get_cmap_len(struct fb_var_screeninfo *var) {
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+- DBG(__FUNCTION__)
++ DBG(__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;
- }
+ switch (var->bits_per_pixel) {
+ case 4:
+@@ -548,7 +548,7 @@ static int matroxfb_decode_var(CPMINFO struct fb_var_screeninfo *var, int *visua
+ unsigned int vramlen;
+ unsigned int memlen;
-@@ -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;
- }
+- DBG(__FUNCTION__)
++ DBG(__func__)
-@@ -863,7 +856,7 @@ static int treo_attach (struct usb_serial *serial)
- (serial->num_interrupt_in == 0))
- goto generic_startup;
+ switch (bpp) {
+ case 4: if (!ACCESS_FBINFO(capable.cfb4)) return -EINVAL;
+@@ -648,7 +648,7 @@ static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ struct matrox_fb_info* minfo = container_of(fb_info, struct matrox_fb_info, fbcon);
+ #endif
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+- DBG(__FUNCTION__)
++ DBG(__func__)
/*
- * It appears that Treos and Kyoceras want to use the
-@@ -894,7 +887,7 @@ generic_startup:
+ * Set a single color register. The values supplied are
+@@ -707,7 +707,7 @@ static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ static void matroxfb_init_fix(WPMINFO2)
+ {
+ struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix;
+- DBG(__FUNCTION__)
++ DBG(__func__)
- static int clie_5_attach (struct usb_serial *serial)
+ strcpy(fix->id,"MATROX");
+
+@@ -722,7 +722,7 @@ static void matroxfb_init_fix(WPMINFO2)
+ static void matroxfb_update_fix(WPMINFO2)
{
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix;
+- DBG(__FUNCTION__)
++ DBG(__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;
+ fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes);
+ fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes);
+@@ -753,7 +753,7 @@ static int matroxfb_set_par(struct fb_info *info)
+ struct fb_var_screeninfo *var;
+ MINFO_FROM_INFO(info);
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+- DBG(__FUNCTION__)
++ DBG(__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)
+ if (ACCESS_FBINFO(dead)) {
+ return -ENXIO;
+@@ -876,7 +876,7 @@ static int matroxfb_ioctl(struct fb_info *info,
+ void __user *argp = (void __user *)arg;
+ MINFO_FROM_INFO(info);
- 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);
+- DBG(__FUNCTION__)
++ DBG(__func__)
- 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);
+ if (ACCESS_FBINFO(dead)) {
+ return -ENXIO;
+@@ -1175,7 +1175,7 @@ static int matroxfb_blank(int blank, struct fb_info *info)
+ CRITFLAGS
+ MINFO_FROM_INFO(info);
-@@ -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(__FUNCTION__)
++ DBG(__func__)
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ if (ACCESS_FBINFO(dead))
+ return 1;
+@@ -1287,7 +1287,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
+ unsigned char bytes[32];
+ unsigned char* tmp;
+
+- DBG(__FUNCTION__)
++ DBG(__func__)
+
+ vm = ACCESS_FBINFO(video.vbase);
+ maxSize &= ~0x1FFFFF; /* must be X*2MB (really it must be 2 or X*4MB) */
+@@ -1593,7 +1593,7 @@ static int initMatrox2(WPMINFO struct board* b){
+ { },
+ };
- /* 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(__FUNCTION__)
++ DBG(__func__)
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ /* set default values... */
+ vesafb_defined.accel_flags = FB_ACCELF_TEXT;
+@@ -2006,7 +2006,7 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
+ #ifndef CONFIG_FB_MATROX_MULTIHEAD
+ static int registered = 0;
+ #endif
+- DBG(__FUNCTION__)
++ DBG(__func__)
+
+ svid = pdev->subsystem_vendor;
+ sid = pdev->subsystem_device;
+@@ -2301,7 +2301,7 @@ static void __exit matrox_done(void) {
+ static int __init matroxfb_setup(char *options) {
+ char *this_opt;
- 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;
- }
+- DBG(__FUNCTION__)
++ DBG(__func__)
- exit:
-- dbg("%s - exit, retval = %d", __FUNCTION__, retval);
-+ dbg("%s - exit, retval = %d", __func__, retval);
- return retval;
- }
+ if (!options || !*options)
+ return 0;
+@@ -2444,7 +2444,7 @@ static int __init matroxfb_init(void)
+ char *option = NULL;
+ int err = 0;
-@@ -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(__FUNCTION__)
++ DBG(__func__)
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ if (fb_get_options("matroxfb", &option))
+ return -ENODEV;
+@@ -2556,7 +2556,7 @@ MODULE_PARM_DESC(cmode, "Specify the video depth that should be used (8bit defau
- 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;
+ int __init init_module(void){
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- DBG(__FUNCTION__)
++ DBG(__func__)
- if (count == 0) {
-- dbg("%s - write request of 0 bytes", __FUNCTION__);
-+ dbg("%s - write request of 0 bytes", __func__);
- return (0);
- }
+ if (disabled)
+ return -ENXIO;
+diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
+index a6ab5b6..7ac4c5f 100644
+--- a/drivers/video/matrox/matroxfb_crtc2.c
++++ b/drivers/video/matrox/matroxfb_crtc2.c
+@@ -420,7 +420,7 @@ static int matroxfb_dh_ioctl(struct fb_info *info,
+ #define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
+ MINFO_FROM(m2info->primary_dev);
-@@ -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);
+- DBG(__FUNCTION__)
++ DBG(__func__)
-- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, bytes, urb->transfer_buffer);
-+ usb_serial_debug_data(debug, &port->dev, __func__, bytes, urb->transfer_buffer);
+ switch (cmd) {
+ case FBIOGET_VBLANK:
+diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
+index 0cd58f8..89da27b 100644
+--- a/drivers/video/matrox/matroxfb_maven.c
++++ b/drivers/video/matrox/matroxfb_maven.c
+@@ -220,7 +220,7 @@ static int matroxfb_PLL_mavenclock(const struct matrox_pll_features2* pll,
+ unsigned int scrlen;
+ unsigned int fmax;
+
+- DBG(__FUNCTION__)
++ DBG(__func__)
+
+ scrlen = htotal * (vtotal - 1);
+ fwant = htotal * vtotal;
+diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c
+index ab7fb50..5b5f072 100644
+--- a/drivers/video/matrox/matroxfb_misc.c
++++ b/drivers/video/matrox/matroxfb_misc.c
+@@ -90,13 +90,13 @@
+ #include <linux/matroxfb.h>
+
+ void matroxfb_DAC_out(CPMINFO int reg, int val) {
+- DBG_REG(__FUNCTION__)
++ DBG_REG(__func__)
+ mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
+ mga_outb(M_RAMDAC_BASE+M_X_DATAREG, val);
+ }
+
+ int matroxfb_DAC_in(CPMINFO int reg) {
+- DBG_REG(__FUNCTION__)
++ DBG_REG(__func__)
+ mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
+ return mga_inb(M_RAMDAC_BASE+M_X_DATAREG);
+ }
+@@ -104,7 +104,7 @@ int matroxfb_DAC_in(CPMINFO int reg) {
+ void matroxfb_var2my(struct fb_var_screeninfo* var, struct my_timming* mt) {
+ unsigned int pixclock = var->pixclock;
+
+- DBG(__FUNCTION__)
++ DBG(__func__)
+
+ if (!pixclock) pixclock = 10000; /* 10ns = 100MHz */
+ mt->pixclock = 1000000000 / pixclock;
+@@ -131,7 +131,7 @@ int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int f
+ unsigned int fwant;
+ unsigned int p;
- 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(__FUNCTION__)
++ DBG(__func__)
-- 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;
+ fwant = freq;
-- dbg("%s - returns %d", __FUNCTION__, room);
-+ dbg("%s - returns %d", __func__, room);
- return (room);
- }
+@@ -192,7 +192,7 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) {
+ int i;
+ struct matrox_hw_state * const hw = &ACCESS_FBINFO(hw);
-@@ -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(__FUNCTION__)
++ DBG(__func__)
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ hw->SEQ[0] = 0x00;
+ hw->SEQ[1] = 0x01; /* or 0x09 */
+@@ -336,7 +336,7 @@ void matroxfb_vgaHWrestore(WPMINFO2) {
+ struct matrox_hw_state * const hw = &ACCESS_FBINFO(hw);
+ CRITFLAGS
+
+- DBG(__FUNCTION__)
++ DBG(__func__)
+
+ dprintk(KERN_INFO "MiscOutReg: %02X\n", hw->MiscOutReg);
+ dprintk(KERN_INFO "SEQ regs: ");
+@@ -522,8 +522,6 @@ static void parse_bios(unsigned char __iomem* vbios, struct matrox_bios* bd) {
+ #endif
+ }
+
+-#define get_u16(x) (le16_to_cpu(get_unaligned((__u16*)(x))))
+-#define get_u32(x) (le32_to_cpu(get_unaligned((__u32*)(x))))
+ static int parse_pins1(WPMINFO const struct matrox_bios* bd) {
+ unsigned int maxdac;
+
+@@ -532,11 +530,12 @@ static int parse_pins1(WPMINFO const struct matrox_bios* bd) {
+ case 1: maxdac = 220000; break;
+ default: maxdac = 240000; break;
+ }
+- if (get_u16(bd->pins + 24)) {
+- maxdac = get_u16(bd->pins + 24) * 10;
++ if (get_unaligned_le16(bd->pins + 24)) {
++ maxdac = get_unaligned_le16(bd->pins + 24) * 10;
+ }
+ MINFO->limits.pixel.vcomax = maxdac;
+- MINFO->values.pll.system = get_u16(bd->pins + 28) ? get_u16(bd->pins + 28) * 10 : 50000;
++ MINFO->values.pll.system = get_unaligned_le16(bd->pins + 28) ?
++ get_unaligned_le16(bd->pins + 28) * 10 : 50000;
+ /* ignore 4MB, 8MB, module clocks */
+ MINFO->features.pll.ref_freq = 14318;
+ MINFO->values.reg.mctlwtst = 0x00030101;
+@@ -575,7 +574,8 @@ static void default_pins2(WPMINFO2) {
+ static int parse_pins3(WPMINFO const struct matrox_bios* bd) {
+ MINFO->limits.pixel.vcomax =
+ MINFO->limits.system.vcomax = (bd->pins[36] == 0xFF) ? 230000 : ((bd->pins[36] + 100) * 1000);
+- MINFO->values.reg.mctlwtst = get_u32(bd->pins + 48) == 0xFFFFFFFF ? 0x01250A21 : get_u32(bd->pins + 48);
++ MINFO->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 48) == 0xFFFFFFFF ?
++ 0x01250A21 : get_unaligned_le32(bd->pins + 48);
+ /* memory config */
+ MINFO->values.reg.memrdbk = ((bd->pins[57] << 21) & 0x1E000000) |
+ ((bd->pins[57] << 22) & 0x00C00000) |
+@@ -601,7 +601,7 @@ static void default_pins3(WPMINFO2) {
+ static int parse_pins4(WPMINFO const struct matrox_bios* bd) {
+ MINFO->limits.pixel.vcomax = (bd->pins[ 39] == 0xFF) ? 230000 : bd->pins[ 39] * 4000;
+ MINFO->limits.system.vcomax = (bd->pins[ 38] == 0xFF) ? MINFO->limits.pixel.vcomax : bd->pins[ 38] * 4000;
+- MINFO->values.reg.mctlwtst = get_u32(bd->pins + 71);
++ MINFO->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 71);
+ MINFO->values.reg.memrdbk = ((bd->pins[87] << 21) & 0x1E000000) |
+ ((bd->pins[87] << 22) & 0x00C00000) |
+ ((bd->pins[86] << 1) & 0x000001E0) |
+@@ -609,7 +609,7 @@ static int parse_pins4(WPMINFO const struct matrox_bios* bd) {
+ MINFO->values.reg.opt = ((bd->pins[53] << 15) & 0x00400000) |
+ ((bd->pins[53] << 22) & 0x10000000) |
+ ((bd->pins[53] << 7) & 0x00001C00);
+- MINFO->values.reg.opt3 = get_u32(bd->pins + 67);
++ MINFO->values.reg.opt3 = get_unaligned_le32(bd->pins + 67);
+ MINFO->values.pll.system = (bd->pins[ 65] == 0xFF) ? 200000 : bd->pins[ 65] * 4000;
+ MINFO->features.pll.ref_freq = (bd->pins[ 92] & 0x01) ? 14318 : 27000;
+ return 0;
+@@ -640,12 +640,12 @@ static int parse_pins5(WPMINFO const struct matrox_bios* bd) {
+ MINFO->limits.video.vcomin = (bd->pins[122] == 0xFF) ? MINFO->limits.system.vcomin : bd->pins[122] * mult;
+ MINFO->values.pll.system =
+ MINFO->values.pll.video = (bd->pins[ 92] == 0xFF) ? 284000 : bd->pins[ 92] * 4000;
+- MINFO->values.reg.opt = get_u32(bd->pins+ 48);
+- MINFO->values.reg.opt2 = get_u32(bd->pins+ 52);
+- MINFO->values.reg.opt3 = get_u32(bd->pins+ 94);
+- MINFO->values.reg.mctlwtst = get_u32(bd->pins+ 98);
+- MINFO->values.reg.memmisc = get_u32(bd->pins+102);
+- MINFO->values.reg.memrdbk = get_u32(bd->pins+106);
++ MINFO->values.reg.opt = get_unaligned_le32(bd->pins + 48);
++ MINFO->values.reg.opt2 = get_unaligned_le32(bd->pins + 52);
++ MINFO->values.reg.opt3 = get_unaligned_le32(bd->pins + 94);
++ MINFO->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 98);
++ MINFO->values.reg.memmisc = get_unaligned_le32(bd->pins + 102);
++ MINFO->values.reg.memrdbk = get_unaligned_le32(bd->pins + 106);
+ MINFO->features.pll.ref_freq = (bd->pins[110] & 0x01) ? 14318 : 27000;
+ MINFO->values.memory.ddr = (bd->pins[114] & 0x60) == 0x20;
+ MINFO->values.memory.dll = (bd->pins[115] & 0x02) != 0;
+diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c
+index e9a89fd..cc4c038 100644
+--- a/drivers/video/metronomefb.c
++++ b/drivers/video/metronomefb.c
+@@ -13,12 +13,10 @@
+ * Corporation. http://support.eink.com/community
+ *
+ * This driver is written to be used with the Metronome display controller.
+- * It was tested with an E-Ink 800x600 Vizplex EPD on a Gumstix Connex board
+- * using the Lyre interface board.
++ * It is intended to be architecture independent. A board specific driver
++ * must be used to perform all the physical IO interactions. An example
++ * is provided as am200epd.c
+ *
+- * General notes:
+- * - User must set metronomefb_enable=1 to enable it.
+- * - See Documentation/fb/metronomefb.txt for how metronome works.
+ */
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+@@ -38,9 +36,11 @@
+ #include <linux/uaccess.h>
+ #include <linux/irq.h>
- 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,
+-#include <asm/arch/pxa-regs.h>
++#include <video/metronomefb.h>
++
+ #include <asm/unaligned.h>
+
++
+ #define DEBUG 1
+ #ifdef DEBUG
+ #define DPRINTK(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a)
+@@ -53,35 +53,6 @@
+ #define DPY_W 832
+ #define DPY_H 622
+
+-struct metromem_desc {
+- u32 mFDADR0;
+- u32 mFSADR0;
+- u32 mFIDR0;
+- u32 mLDCMD0;
+-};
+-
+-struct metromem_cmd {
+- u16 opcode;
+- u16 args[((64-2)/2)];
+- u16 csum;
+-};
+-
+-struct metronomefb_par {
+- unsigned char *metromem;
+- struct metromem_desc *metromem_desc;
+- struct metromem_cmd *metromem_cmd;
+- unsigned char *metromem_wfm;
+- unsigned char *metromem_img;
+- u16 *metromem_img_csum;
+- u16 *csum_table;
+- int metromemsize;
+- dma_addr_t metromem_dma;
+- dma_addr_t metromem_desc_dma;
+- struct fb_info *info;
+- wait_queue_head_t waitq;
+- u8 frame_count;
+-};
+-
+ /* frame differs from image. frame includes non-visible pixels */
+ struct epd_frame {
+ int fw; /* frame width */
+@@ -120,8 +91,7 @@ static struct fb_var_screeninfo metronomefb_var __devinitdata = {
+ .transp = { 0, 0, 0 },
+ };
+
+-static unsigned int metronomefb_enable;
+-
++/* the waveform structure that is coming from userspace firmware */
+ struct waveform_hdr {
+ u8 stuff[32];
+
+@@ -236,8 +206,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
+ }
+
+ /* check waveform mode table address checksum */
+- wmta = le32_to_cpu(get_unaligned((__le32 *) wfm_hdr->wmta));
+- wmta &= 0x00FFFFFF;
++ wmta = get_unaligned_le32(wfm_hdr->wmta) & 0x00FFFFFF;
+ cksum_idx = wmta + m*4 + 3;
+ if (cksum_idx > size)
+ return -EINVAL;
+@@ -249,8 +218,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
+ }
+
+ /* check waveform temperature table address checksum */
+- tta = le32_to_cpu(get_unaligned((int *) (mem + wmta + m*4)));
+- tta &= 0x00FFFFFF;
++ tta = get_unaligned_le32(mem + wmta + m * 4) & 0x00FFFFFF;
+ cksum_idx = tta + trn*4 + 3;
+ if (cksum_idx > size)
+ return -EINVAL;
+@@ -263,8 +231,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
+
+ /* here we do the real work of putting the waveform into the
+ metromem buffer. this does runlength decoding of the waveform */
+- wfm_idx = le32_to_cpu(get_unaligned((__le32 *) (mem + tta + trn*4)));
+- wfm_idx &= 0x00FFFFFF;
++ wfm_idx = get_unaligned_le32(mem + tta + trn * 4) & 0x00FFFFFF;
+ owfm_idx = wfm_idx;
+ if (wfm_idx > size)
+ return -EINVAL;
+@@ -301,165 +268,6 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
+ return 0;
+ }
+
+-/* register offsets for gpio control */
+-#define LED_GPIO_PIN 51
+-#define STDBY_GPIO_PIN 48
+-#define RST_GPIO_PIN 49
+-#define RDY_GPIO_PIN 32
+-#define ERR_GPIO_PIN 17
+-#define PCBPWR_GPIO_PIN 16
+-
+-#define AF_SEL_GPIO_N 0x3
+-#define GAFR0_U_OFFSET(pin) ((pin - 16) * 2)
+-#define GAFR1_L_OFFSET(pin) ((pin - 32) * 2)
+-#define GAFR1_U_OFFSET(pin) ((pin - 48) * 2)
+-#define GPDR1_OFFSET(pin) (pin - 32)
+-#define GPCR1_OFFSET(pin) (pin - 32)
+-#define GPSR1_OFFSET(pin) (pin - 32)
+-#define GPCR0_OFFSET(pin) (pin)
+-#define GPSR0_OFFSET(pin) (pin)
+-
+-static void metronome_set_gpio_output(int pin, int val)
+-{
+- u8 index;
+-
+- index = pin >> 4;
+-
+- switch (index) {
+- case 1:
+- if (val)
+- GPSR0 |= (1 << GPSR0_OFFSET(pin));
+- else
+- GPCR0 |= (1 << GPCR0_OFFSET(pin));
+- break;
+- case 2:
+- break;
+- case 3:
+- if (val)
+- GPSR1 |= (1 << GPSR1_OFFSET(pin));
+- else
+- GPCR1 |= (1 << GPCR1_OFFSET(pin));
+- break;
+- default:
+- printk(KERN_ERR "unimplemented\n");
+- }
+-}
+-
+-static void __devinit metronome_init_gpio_pin(int pin, int dir)
+-{
+- u8 index;
+- /* dir 0 is output, 1 is input
+- - do 2 things here:
+- - set gpio alternate function to standard gpio
+- - set gpio direction to input or output */
+-
+- index = pin >> 4;
+- switch (index) {
+- case 1:
+- GAFR0_U &= ~(AF_SEL_GPIO_N << GAFR0_U_OFFSET(pin));
+-
+- if (dir)
+- GPDR0 &= ~(1 << pin);
+- else
+- GPDR0 |= (1 << pin);
+- break;
+- case 2:
+- GAFR1_L &= ~(AF_SEL_GPIO_N << GAFR1_L_OFFSET(pin));
+-
+- if (dir)
+- GPDR1 &= ~(1 << GPDR1_OFFSET(pin));
+- else
+- GPDR1 |= (1 << GPDR1_OFFSET(pin));
+- break;
+- case 3:
+- GAFR1_U &= ~(AF_SEL_GPIO_N << GAFR1_U_OFFSET(pin));
+-
+- if (dir)
+- GPDR1 &= ~(1 << GPDR1_OFFSET(pin));
+- else
+- GPDR1 |= (1 << GPDR1_OFFSET(pin));
+- break;
+- default:
+- printk(KERN_ERR "unimplemented\n");
+- }
+-}
+-
+-static void __devinit metronome_init_gpio_regs(void)
+-{
+- metronome_init_gpio_pin(LED_GPIO_PIN, 0);
+- metronome_set_gpio_output(LED_GPIO_PIN, 0);
+-
+- metronome_init_gpio_pin(STDBY_GPIO_PIN, 0);
+- metronome_set_gpio_output(STDBY_GPIO_PIN, 0);
+-
+- metronome_init_gpio_pin(RST_GPIO_PIN, 0);
+- metronome_set_gpio_output(RST_GPIO_PIN, 0);
+-
+- metronome_init_gpio_pin(RDY_GPIO_PIN, 1);
+-
+- metronome_init_gpio_pin(ERR_GPIO_PIN, 1);
+-
+- metronome_init_gpio_pin(PCBPWR_GPIO_PIN, 0);
+- metronome_set_gpio_output(PCBPWR_GPIO_PIN, 0);
+-}
+-
+-static void metronome_disable_lcd_controller(struct metronomefb_par *par)
+-{
+- LCSR = 0xffffffff; /* Clear LCD Status Register */
+- LCCR0 |= LCCR0_DIS; /* Disable LCD Controller */
+-
+- /* we reset and just wait for things to settle */
+- msleep(200);
+-}
+-
+-static void metronome_enable_lcd_controller(struct metronomefb_par *par)
+-{
+- LCSR = 0xffffffff;
+- FDADR0 = par->metromem_desc_dma;
+- LCCR0 |= LCCR0_ENB;
+-}
+-
+-static void __devinit metronome_init_lcdc_regs(struct metronomefb_par *par)
+-{
+- /* here we do:
+- - disable the lcd controller
+- - setup lcd control registers
+- - setup dma descriptor
+- - reenable lcd controller
+- */
+-
+- /* disable the lcd controller */
+- metronome_disable_lcd_controller(par);
+-
+- /* setup lcd control registers */
+- LCCR0 = LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | LCCR0_PAS
+- | LCCR0_QDM | LCCR0_BM | LCCR0_OUM;
+-
+- LCCR1 = (epd_frame_table[0].fw/2 - 1) /* pixels per line */
+- | (27 << 10) /* hsync pulse width - 1 */
+- | (33 << 16) /* eol pixel count */
+- | (33 << 24); /* bol pixel count */
+-
+- LCCR2 = (epd_frame_table[0].fh - 1) /* lines per panel */
+- | (24 << 10) /* vsync pulse width - 1 */
+- | (2 << 16) /* eof pixel count */
+- | (0 << 24); /* bof pixel count */
+-
+- LCCR3 = 2 /* pixel clock divisor */
+- | (24 << 8) /* AC Bias pin freq */
+- | LCCR3_16BPP /* BPP */
+- | LCCR3_PCP; /* PCP falling edge */
+-
+- /* setup dma descriptor */
+- par->metromem_desc->mFDADR0 = par->metromem_desc_dma;
+- par->metromem_desc->mFSADR0 = par->metromem_dma;
+- par->metromem_desc->mFIDR0 = 0;
+- par->metromem_desc->mLDCMD0 = epd_frame_table[0].fw
+- * epd_frame_table[0].fh;
+- /* reenable lcd controller */
+- metronome_enable_lcd_controller(par);
+-}
+-
+ static int metronome_display_cmd(struct metronomefb_par *par)
{
- struct whiteheat_private *info = usb_get_serial_port_data(port);
+ int i;
+@@ -493,8 +301,7 @@ static int metronome_display_cmd(struct metronomefb_par *par)
+ par->metromem_cmd->csum = cs;
+ par->metromem_cmd->opcode = opcode; /* display cmd */
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- i = wait_event_interruptible_timeout(par->waitq, (GPLR1 & 0x01), HZ);
+- return i;
++ return par->board->met_wait_event_intr(par);
+ }
- 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;
+ static int __devinit metronome_powerup_cmd(struct metronomefb_par *par)
+@@ -518,13 +325,12 @@ static int __devinit metronome_powerup_cmd(struct metronomefb_par *par)
+ par->metromem_cmd->csum = cs;
-- dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
-+ dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
+ msleep(1);
+- metronome_set_gpio_output(RST_GPIO_PIN, 1);
++ par->board->set_rst(par, 1);
- switch (cmd) {
- case TIOCGSERIAL:
-@@ -886,7 +880,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
+ msleep(1);
+- metronome_set_gpio_output(STDBY_GPIO_PIN, 1);
++ par->board->set_stdby(par, 1);
- 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);
+- i = wait_event_timeout(par->waitq, (GPLR1 & 0x01), HZ);
+- return i;
++ return par->board->met_wait_event(par);
}
-@@ -904,7 +898,7 @@ static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
- int chars = 0;
- unsigned long flags;
+ static int __devinit metronome_config_cmd(struct metronomefb_par *par)
+@@ -569,8 +375,7 @@ static int __devinit metronome_config_cmd(struct metronomefb_par *par)
+ par->metromem_cmd->csum = cs;
+ par->metromem_cmd->opcode = 0xCC10; /* config cmd */
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- i = wait_event_timeout(par->waitq, (GPLR1 & 0x01), HZ);
+- return i;
++ return par->board->met_wait_event(par);
+ }
- 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);
+ static int __devinit metronome_init_cmd(struct metronomefb_par *par)
+@@ -596,16 +401,19 @@ static int __devinit metronome_init_cmd(struct metronomefb_par *par)
+ par->metromem_cmd->csum = cs;
+ par->metromem_cmd->opcode = 0xCC20; /* init cmd */
-- dbg ("%s - returns %d", __FUNCTION__, chars);
-+ dbg ("%s - returns %d", __func__, chars);
- return chars;
+- i = wait_event_timeout(par->waitq, (GPLR1 & 0x01), HZ);
+- return i;
++ return par->board->met_wait_event(par);
}
-@@ -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;
+ static int __devinit metronome_init_regs(struct metronomefb_par *par)
+ {
+ int res;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+- metronome_init_gpio_regs();
+- metronome_init_lcdc_regs(par);
++ par->board->init_gpio_regs(par);
++
++ par->board->init_lcdc_regs(par);
++
++ /* now that lcd is setup, setup dma descriptor */
++ par->board->post_dma_setup(par);
- 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;
+ res = metronome_powerup_cmd(par);
+ if (res)
+@@ -616,8 +424,6 @@ static int __devinit metronome_init_regs(struct metronomefb_par *par)
+ return res;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ res = metronome_init_cmd(par);
+- if (res)
+- return res;
- 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)
+ return res;
+ }
+@@ -632,7 +438,7 @@ static void metronomefb_dpy_update(struct metronomefb_par *par)
+
+ cksum = calc_img_cksum((u16 *) par->metromem_img,
+ (epd_frame_table[0].fw * DPY_H)/2);
+- *((u16 *) (par->metromem_img) +
++ *((u16 *)(par->metromem_img) +
+ (epd_frame_table[0].fw * DPY_H)/2) = cksum;
+ metronome_display_cmd(par);
+ }
+@@ -641,8 +447,8 @@ static u16 metronomefb_dpy_update_page(struct metronomefb_par *par, int index)
{
- int status = urb->status;
+ int i;
+ u16 csum = 0;
+- u16 *buf = (u16 __force *) (par->info->screen_base + index);
+- u16 *img = (u16 *) (par->metromem_img + index);
++ u16 *buf = (u16 __force *)(par->info->screen_base + index);
++ u16 *img = (u16 *)(par->metromem_img + index);
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+ /* swizzle from vm to metromem and recalc cksum at the same time*/
+ for (i = 0; i < PAGE_SIZE/2; i++) {
+@@ -678,7 +484,7 @@ static void metronomefb_fillrect(struct fb_info *info,
+ {
+ struct metronomefb_par *par = info->par;
- if (status) {
- dbg("nonzero urb status: %d", status);
-@@ -971,28 +965,28 @@ static void command_port_write_callback(struct urb *urb)
+- cfb_fillrect(info, rect);
++ sys_fillrect(info, rect);
+ metronomefb_dpy_update(par);
+ }
- static void command_port_read_callback(struct urb *urb)
+@@ -687,7 +493,7 @@ static void metronomefb_copyarea(struct fb_info *info,
{
-- 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;
+ struct metronomefb_par *par = info->par;
-- dbg("%s", __FUNCTION__);
-+ dbg("%s", __func__);
+- cfb_copyarea(info, area);
++ sys_copyarea(info, area);
+ metronomefb_dpy_update(par);
+ }
- 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;
- }
+@@ -696,7 +502,7 @@ static void metronomefb_imageblit(struct fb_info *info,
+ {
+ struct metronomefb_par *par = info->par;
-- 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);
+- cfb_imageblit(info, image);
++ sys_imageblit(info, image);
+ metronomefb_dpy_update(par);
+ }
- 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__);
+@@ -733,7 +539,7 @@ static ssize_t metronomefb_write(struct fb_info *info, const char __user *buf,
+ count = total_size - p;
}
-
- /* 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);
- }
+- dst = (void __force *) (info->screen_base + p);
++ dst = (void __force *)(info->screen_base + p);
- static void whiteheat_read_callback(struct urb *urb)
+ if (copy_from_user(dst, buf, count))
+ err = -EFAULT;
+@@ -759,18 +565,10 @@ static struct fb_deferred_io metronomefb_defio = {
+ .deferred_io = metronomefb_dpy_deferred_io,
+ };
+
+-static irqreturn_t metronome_handle_irq(int irq, void *dev_id)
+-{
+- struct fb_info *info = dev_id;
+- struct metronomefb_par *par = info->par;
+-
+- wake_up_interruptible(&par->waitq);
+- return IRQ_HANDLED;
+-}
+-
+ static int __devinit metronomefb_probe(struct platform_device *dev)
{
-- 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;
+ struct fb_info *info;
++ struct metronome_board *board;
+ int retval = -ENOMEM;
+ int videomemorysize;
+ unsigned char *videomemory;
+@@ -779,17 +577,26 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
+ int cmd_size, wfm_size, img_size, padding_size, totalsize;
+ int i;
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
++ /* pick up board specific routines */
++ board = dev->dev.platform_data;
++ if (!board)
++ return -EINVAL;
++
++ /* try to count device specific driver, if can't, platform recalls */
++ if (!try_module_get(board->owner))
++ return -ENODEV;
++
+ /* we have two blocks of memory.
+ info->screen_base which is vm, and is the fb used by apps.
+ par->metromem which is physically contiguous memory and
+ contains the display controller commands, waveform,
+ processed image data and padding. this is the data pulled
+- by the pxa255's LCD controller and pushed to Metronome */
++ by the device's LCD controller and pushed to Metronome */
+
+ videomemorysize = (DPY_W*DPY_H);
+ videomemory = vmalloc(videomemorysize);
+ if (!videomemory)
+- return retval;
++ return -ENOMEM;
- 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)
+ memset(videomemory, 0, videomemorysize);
- 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;
+@@ -797,7 +604,7 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
+ if (!info)
+ goto err_vfree;
+
+- info->screen_base = (char __iomem *) videomemory;
++ info->screen_base = (char __force __iomem *)videomemory;
+ info->fbops = &metronomefb_ops;
+
+ info->var = metronomefb_var;
+@@ -805,6 +612,7 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
+ info->fix.smem_len = videomemorysize;
+ par = info->par;
+ par->info = info;
++ par->board = board;
+ init_waitqueue_head(&par->waitq);
+
+ /* this table caches per page csum values. */
+@@ -849,11 +657,10 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
+ par->metromem_desc_dma = par->metromem_dma + cmd_size + wfm_size
+ + img_size + padding_size;
+
+- /* load the waveform in. assume mode 3, temp 31 for now */
+- /* a) request the waveform file from userspace
++ /* load the waveform in. assume mode 3, temp 31 for now
++ a) request the waveform file from userspace
+ b) process waveform and decode into metromem */
+-
+- retval = request_firmware(&fw_entry, "waveform.wbf", &dev->dev);
++ retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
+ if (retval < 0) {
+ printk(KERN_ERR "metronomefb: couldn't get waveform\n");
+ goto err_dma_free;
+@@ -861,19 +668,14 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
+
+ retval = load_waveform((u8 *) fw_entry->data, fw_entry->size,
+ par->metromem_wfm, 3, 31, &par->frame_count);
++ release_firmware(fw_entry);
+ if (retval < 0) {
+ printk(KERN_ERR "metronomefb: couldn't process waveform\n");
+- goto err_ld_wfm;
++ goto err_dma_free;
}
+- release_firmware(fw_entry);
-- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
-+ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+- retval = request_irq(IRQ_GPIO(RDY_GPIO_PIN), metronome_handle_irq,
+- IRQF_DISABLED, "Metronome", info);
+- if (retval) {
+- dev_err(&dev->dev, "request_irq failed: %d\n", retval);
+- goto err_ld_wfm;
+- }
+- set_irq_type(IRQ_GPIO(RDY_GPIO_PIN), IRQT_FALLING);
++ if (board->setup_irq(info))
++ goto err_dma_free;
- 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)
+ retval = metronome_init_regs(par);
+ if (retval < 0)
+@@ -913,9 +715,7 @@ err_cmap:
+ err_fb_rel:
+ framebuffer_release(info);
+ err_free_irq:
+- free_irq(IRQ_GPIO(RDY_GPIO_PIN), info);
+-err_ld_wfm:
+- release_firmware(fw_entry);
++ board->free_irq(info);
+ err_dma_free:
+ dma_free_writecombine(&dev->dev, par->metromemsize, par->metromem,
+ par->metromem_dma);
+@@ -923,6 +723,7 @@ err_csum_table:
+ vfree(par->csum_table);
+ err_vfree:
+ vfree(videomemory);
++ module_put(board->owner);
+ return retval;
+ }
- static void whiteheat_write_callback(struct urb *urb)
+@@ -939,7 +740,8 @@ static int __devexit metronomefb_remove(struct platform_device *dev)
+ vfree(par->csum_table);
+ unregister_framebuffer(info);
+ vfree((void __force *)info->screen_base);
+- free_irq(IRQ_GPIO(RDY_GPIO_PIN), info);
++ par->board->free_irq(info);
++ module_put(par->board->owner);
+ framebuffer_release(info);
+ }
+ return 0;
+@@ -949,48 +751,21 @@ static struct platform_driver metronomefb_driver = {
+ .probe = metronomefb_probe,
+ .remove = metronomefb_remove,
+ .driver = {
++ .owner = THIS_MODULE,
+ .name = "metronomefb",
+ },
+ };
+
+-static struct platform_device *metronomefb_device;
+-
+ static int __init metronomefb_init(void)
{
-- 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;
+- int ret;
+-
+- if (!metronomefb_enable) {
+- printk(KERN_ERR
+- "Use metronomefb_enable to enable the device\n");
+- return -ENXIO;
+- }
+-
+- ret = platform_driver_register(&metronomefb_driver);
+- if (!ret) {
+- metronomefb_device = platform_device_alloc("metronomefb", 0);
+- if (metronomefb_device)
+- ret = platform_device_add(metronomefb_device);
+- else
+- ret = -ENOMEM;
+-
+- if (ret) {
+- platform_device_put(metronomefb_device);
+- platform_driver_unregister(&metronomefb_driver);
+- }
+- }
+- return ret;
+-
++ return platform_driver_register(&metronomefb_driver);
+ }
-- dbg("%s - port %d", __FUNCTION__, port->number);
-+ dbg("%s - port %d", __func__, port->number);
+ static void __exit metronomefb_exit(void)
+ {
+- platform_device_unregister(metronomefb_device);
+ platform_driver_unregister(&metronomefb_driver);
+ }
- 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;
+-module_param(metronomefb_enable, uint, 0);
+-MODULE_PARM_DESC(metronomefb_enable, "Enable communication with Metronome");
+-
+ module_init(metronomefb_init);
+ module_exit(metronomefb_exit);
+
+diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
+index 08d0725..4735621 100644
+--- a/drivers/video/modedb.c
++++ b/drivers/video/modedb.c
+@@ -22,7 +22,7 @@
+ ((v).xres == (x) && (v).yres == (y))
+
+ #ifdef DEBUG
+-#define DPRINTK(fmt, args...) printk("modedb %s: " fmt, __FUNCTION__ , ## args)
++#define DPRINTK(fmt, args...) printk("modedb %s: " fmt, __func__ , ## args)
+ #else
+ #define DPRINTK(fmt, args...)
+ #endif
+@@ -522,7 +522,7 @@ int fb_find_mode(struct fb_var_screeninfo *var,
+ int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
+ unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
+ int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
+- u32 best, diff;
++ u32 best, diff, tdiff;
+
+ for (i = namelen-1; i >= 0; i--) {
+ switch (name[i]) {
+@@ -651,19 +651,27 @@ done:
+ return (refresh_specified) ? 2 : 1;
+ }
+
+- diff = xres + yres;
++ diff = 2 * (xres + yres);
+ best = -1;
+ DPRINTK("Trying best-fit modes\n");
+ for (i = 0; i < dbsize; i++) {
+- if (xres <= db[i].xres && yres <= db[i].yres) {
+ DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres);
+ if (!fb_try_mode(var, info, &db[i], bpp)) {
+- if (diff > (db[i].xres - xres) + (db[i].yres - yres)) {
+- diff = (db[i].xres - xres) + (db[i].yres - yres);
+- best = i;
+- }
++ tdiff = abs(db[i].xres - xres) +
++ abs(db[i].yres - yres);
++
++ /*
++ * Penalize modes with resolutions smaller
++ * than requested.
++ */
++ if (xres > db[i].xres || yres > db[i].yres)
++ tdiff += xres + yres;
++
++ if (diff > tdiff) {
++ diff = tdiff;
++ best = i;
++ }
+ }
+- }
}
- list_move(&wrap->list, &info->tx_urbs_free);
-@@ -1084,7 +1078,7 @@ static void whiteheat_write_callback(struct urb *urb)
+ if (best != -1) {
+ fb_try_mode(var, info, &db[best], bpp);
+diff --git a/drivers/video/n411.c b/drivers/video/n411.c
+new file mode 100644
+index 0000000..935830f
+--- /dev/null
++++ b/drivers/video/n411.c
+@@ -0,0 +1,202 @@
++/*
++ * linux/drivers/video/n411.c -- Platform device for N411 EPD kit
++ *
++ * Copyright (C) 2008, Jaya Kumar
++ *
++ * 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.
++ *
++ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
++ *
++ * This driver is written to be used with the Hecuba display controller
++ * board, and tested with the EInk 800x600 display in 1 bit mode.
++ * The interface between Hecuba and the host is TTL based GPIO. The
++ * GPIO requirements are 8 writable data lines and 6 lines for control.
++ * Only 4 of the controls are actually used here but 6 for future use.
++ * The driver requires the IO addresses for data and control GPIO at
++ * load time. It is also possible to use this display with a standard
++ * PC parallel port.
++ *
++ * General notes:
++ * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR c2io_addr=0xIOADDR
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/fb.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/list.h>
++#include <linux/uaccess.h>
++#include <linux/irq.h>
++
++#include <video/hecubafb.h>
++
++static unsigned long dio_addr;
++static unsigned long cio_addr;
++static unsigned long c2io_addr;
++static unsigned long splashval;
++static unsigned int nosplash;
++static unsigned char ctl;
++
++static void n411_set_ctl(struct hecubafb_par *par, unsigned char bit, unsigned
++ char state)
++{
++ switch (bit) {
++ case HCB_CD_BIT:
++ if (state)
++ ctl &= ~(HCB_CD_BIT);
++ else
++ ctl |= HCB_CD_BIT;
++ break;
++ case HCB_DS_BIT:
++ if (state)
++ ctl &= ~(HCB_DS_BIT);
++ else
++ ctl |= HCB_DS_BIT;
++ break;
++ }
++ outb(ctl, cio_addr);
++}
++
++static unsigned char n411_get_ctl(struct hecubafb_par *par)
++{
++ return inb(c2io_addr);
++}
++
++static void n411_set_data(struct hecubafb_par *par, unsigned char value)
++{
++ outb(value, dio_addr);
++}
++
++static void n411_wait_for_ack(struct hecubafb_par *par, int clear)
++{
++ int timeout;
++ unsigned char tmp;
++
++ timeout = 500;
++ do {
++ tmp = n411_get_ctl(par);
++ if ((tmp & HCB_ACK_BIT) && (!clear))
++ return;
++ else if (!(tmp & HCB_ACK_BIT) && (clear))
++ return;
++ udelay(1);
++ } while (timeout--);
++ printk(KERN_ERR "timed out waiting for ack\n");
++}
++
++static int n411_init_control(struct hecubafb_par *par)
++{
++ unsigned char tmp;
++ /* for init, we want the following setup to be set:
++ WUP = lo
++ ACK = hi
++ DS = hi
++ RW = hi
++ CD = lo
++ */
++
++ /* write WUP to lo, DS to hi, RW to hi, CD to lo */
++ ctl = HCB_WUP_BIT | HCB_RW_BIT | HCB_CD_BIT ;
++ n411_set_ctl(par, HCB_DS_BIT, 1);
++
++ /* check ACK is not lo */
++ tmp = n411_get_ctl(par);
++ if (tmp & HCB_ACK_BIT) {
++ printk(KERN_ERR "Fail because ACK is already low\n");
++ return -ENXIO;
++ }
++
++ return 0;
++}
++
++
++static int n411_init_board(struct hecubafb_par *par)
++{
++ int retval;
++
++ retval = n411_init_control(par);
++ if (retval)
++ return retval;
++
++ par->send_command(par, APOLLO_INIT_DISPLAY);
++ par->send_data(par, 0x81);
++
++ /* have to wait while display resets */
++ udelay(1000);
++
++ /* if we were told to splash the screen, we just clear it */
++ if (!nosplash) {
++ par->send_command(par, APOLLO_ERASE_DISPLAY);
++ par->send_data(par, splashval);
++ }
++
++ return 0;
++}
++
++static struct hecuba_board n411_board = {
++ .owner = THIS_MODULE,
++ .init = n411_init_board,
++ .set_ctl = n411_set_ctl,
++ .set_data = n411_set_data,
++ .wait_for_ack = n411_wait_for_ack,
++};
++
++static struct platform_device *n411_device;
++static int __init n411_init(void)
++{
++ int ret;
++ if (!dio_addr || !cio_addr || !c2io_addr) {
++ printk(KERN_WARNING "no IO addresses supplied\n");
++ return -EINVAL;
++ }
++
++ /* request our platform independent driver */
++ request_module("hecubafb");
++
++ n411_device = platform_device_alloc("hecubafb", -1);
++ if (!n411_device)
++ return -ENOMEM;
++
++ platform_device_add_data(n411_device, &n411_board, sizeof(n411_board));
++
++ /* this _add binds hecubafb to n411. hecubafb refcounts n411 */
++ ret = platform_device_add(n411_device);
++
++ if (ret)
++ platform_device_put(n411_device);
++
++ return ret;
++
++}
++
++static void __exit n411_exit(void)
++{
++ platform_device_unregister(n411_device);
++}
++
++module_init(n411_init);
++module_exit(n411_exit);
++
++module_param(nosplash, uint, 0);
++MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
++module_param(dio_addr, ulong, 0);
++MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
++module_param(cio_addr, ulong, 0);
++MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
++module_param(c2io_addr, ulong, 0);
++MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
++module_param(splashval, ulong, 0);
++MODULE_PARM_DESC(splashval, "Splash pattern: 0x00 is black, 0x01 is white");
++
++MODULE_DESCRIPTION("board driver for n411 hecuba/apollo epd kit");
++MODULE_AUTHOR("Jaya Kumar");
++MODULE_LICENSE("GPL");
++
+diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c
+index d1a1054..ed20a98 100644
+--- a/drivers/video/nvidia/nv_hw.c
++++ b/drivers/video/nvidia/nv_hw.c
+@@ -129,7 +129,7 @@ typedef struct {
+ int nvclk_khz;
+ char mem_page_miss;
+ char mem_latency;
+- int memory_type;
++ u32 memory_type;
+ int memory_width;
+ char enable_video;
+ char gr_during_vid;
+@@ -719,7 +719,7 @@ static void nForceUpdateArbitrationSettings(unsigned VClk,
+ memctrl >>= 16;
+
+ if ((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) {
+- int dimm[3];
++ u32 dimm[3];
+
+ dev = pci_get_bus_and_slot(0, 2);
+ pci_read_config_dword(dev, 0x40, &dimm[0]);
+diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
+index 82579d3..d9627b5 100644
+--- a/drivers/video/nvidia/nv_setup.c
++++ b/drivers/video/nvidia/nv_setup.c
+@@ -265,12 +265,12 @@ static void nv10GetConfig(struct nvidia_par *par)
+
+ dev = pci_get_bus_and_slot(0, 1);
+ if ((par->Chipset & 0xffff) == 0x01a0) {
+- int amt = 0;
++ u32 amt;
+
+ pci_read_config_dword(dev, 0x7c, &amt);
+ par->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024;
+ } else if ((par->Chipset & 0xffff) == 0x01f0) {
+- int amt = 0;
++ u32 amt;
+
+ pci_read_config_dword(dev, 0x84, &amt);
+ par->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024;
+diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
+index 596652d..9dbb5a5 100644
+--- a/drivers/video/nvidia/nvidia.c
++++ b/drivers/video/nvidia/nvidia.c
+@@ -43,14 +43,14 @@
+ #define NVTRACE if (0) printk
+ #endif
- if (status) {
- dbg("%s - nonzero write bulk status received: %d",
-- __FUNCTION__, status);
-+ __func__, status);
- return;
+-#define NVTRACE_ENTER(...) NVTRACE("%s START\n", __FUNCTION__)
+-#define NVTRACE_LEAVE(...) NVTRACE("%s END\n", __FUNCTION__)
++#define NVTRACE_ENTER(...) NVTRACE("%s START\n", __func__)
++#define NVTRACE_LEAVE(...) NVTRACE("%s END\n", __func__)
+
+ #ifdef CONFIG_FB_NVIDIA_DEBUG
+ #define assert(expr) \
+ if (!(expr)) { \
+ printk( "Assertion failed! %s,%s,%s,line=%d\n",\
+- #expr,__FILE__,__FUNCTION__,__LINE__); \
++ #expr,__FILE__,__func__,__LINE__); \
+ BUG(); \
}
+ #else
+@@ -1559,7 +1559,6 @@ static int __devinit nvidiafb_init(void)
-@@ -1104,7 +1098,7 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d
- int retval = 0;
- int t;
+ module_init(nvidiafb_init);
-- dbg("%s - command %d", __FUNCTION__, command);
-+ dbg("%s - command %d", __func__, command);
+-#ifdef MODULE
+ static void __exit nvidiafb_exit(void)
+ {
+ pci_unregister_driver(&nvidiafb_driver);
+@@ -1615,5 +1614,3 @@ MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) "
+ MODULE_AUTHOR("Antonino Daplas");
+ MODULE_DESCRIPTION("Framebuffer driver for nVidia graphics chipset");
+ MODULE_LICENSE("GPL");
+-#endif /* MODULE */
+-
+diff --git a/drivers/video/offb.c b/drivers/video/offb.c
+index 452433d..d7b3dcc 100644
+--- a/drivers/video/offb.c
++++ b/drivers/video/offb.c
+@@ -248,7 +248,7 @@ static void __iomem *offb_map_reg(struct device_node *np, int index,
+ static void __init offb_init_fb(const char *name, const char *full_name,
+ int width, int height, int depth,
+ int pitch, unsigned long address,
+- struct device_node *dp)
++ int foreign_endian, struct device_node *dp)
+ {
+ unsigned long res_size = pitch * height * (depth + 7) / 8;
+ struct offb_par *par = &default_par;
+@@ -397,7 +397,7 @@ static void __init offb_init_fb(const char *name, const char *full_name,
+ info->screen_base = ioremap(address, fix->smem_len);
+ info->par = par;
+ info->pseudo_palette = (void *) (info + 1);
+- info->flags = FBINFO_DEFAULT;
++ info->flags = FBINFO_DEFAULT | foreign_endian;
+
+ fb_alloc_cmap(&info->cmap, 256, 0);
+
+@@ -424,6 +424,15 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node)
+ u64 rstart, address = OF_BAD_ADDR;
+ const u32 *pp, *addrp, *up;
+ u64 asize;
++ int foreign_endian = 0;
++
++#ifdef __BIG_ENDIAN
++ if (of_get_property(dp, "little-endian", NULL))
++ foreign_endian = FBINFO_FOREIGN_ENDIAN;
++#else
++ if (of_get_property(dp, "big-endian", NULL))
++ foreign_endian = FBINFO_FOREIGN_ENDIAN;
++#endif
- 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;
+ pp = of_get_property(dp, "linux,bootx-depth", &len);
+ if (pp == NULL)
+@@ -509,7 +518,7 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node)
+ offb_init_fb(no_real_node ? "bootx" : dp->name,
+ no_real_node ? "display" : dp->full_name,
+ width, height, depth, pitch, address,
+- no_real_node ? NULL : dp);
++ foreign_endian, no_real_node ? NULL : dp);
}
+ }
-@@ -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);
+diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
+index 5849606..c95874f 100644
+--- a/drivers/video/p9100.c
++++ b/drivers/video/p9100.c
+@@ -310,7 +310,7 @@ static int __devinit p9100_probe(struct of_device *op, const struct of_device_id
+
+ dev_set_drvdata(&op->dev, info);
+
+- printk("%s: p9100 at %lx:%lx\n",
++ printk(KERN_INFO "%s: p9100 at %lx:%lx\n",
+ dp->full_name,
+ par->which_io, par->physbase);
+
+diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
+index 30181b5..3f1ca2a 100644
+--- a/drivers/video/pm2fb.c
++++ b/drivers/video/pm2fb.c
+@@ -56,7 +56,7 @@
+ #undef PM2FB_MASTER_DEBUG
+ #ifdef PM2FB_MASTER_DEBUG
+ #define DPRINTK(a, b...) \
+- printk(KERN_DEBUG "pm2fb: %s: " a, __FUNCTION__ , ## b)
++ printk(KERN_DEBUG "pm2fb: %s: " a, __func__ , ## b)
+ #else
+ #define DPRINTK(a, b...)
+ #endif
+@@ -67,7 +67,7 @@
+ * Driver data
+ */
+ static int hwcursor = 1;
+-static char *mode __devinitdata;
++static char *mode_option __devinitdata;
- if (command_info->command_finished == false) {
-- dbg("%s - command timed out.", __FUNCTION__);
-+ dbg("%s - command timed out.", __func__);
- retval = -ETIMEDOUT;
- goto exit;
+ /*
+ * The XFree GLINT driver will (I think to implement hardware cursor
+@@ -1680,17 +1680,19 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
+ info->pixmap.scan_align = 1;
}
- if (command_info->command_finished == WHITEHEAT_CMD_FAILURE) {
-- dbg("%s - command failed.", __FUNCTION__);
-+ dbg("%s - command failed.", __func__);
- retval = -EIO;
- goto exit;
- }
+- if (!mode)
+- mode = "640x480 at 60";
++ if (!mode_option)
++ mode_option = "640x480 at 60";
- 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;
+- err = fb_find_mode(&info->var, info, mode, NULL, 0, NULL, 8);
++ err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
+ if (!err || err == 4)
+ info->var = pm2fb_var;
+
+- if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
++ retval = fb_alloc_cmap(&info->cmap, 256, 0);
++ if (retval < 0)
+ goto err_exit_both;
+
+- if (register_framebuffer(info) < 0)
++ retval = register_framebuffer(info);
++ if (retval < 0)
+ goto err_exit_all;
+
+ printk(KERN_INFO "fb%d: %s frame buffer device, memory = %dK.\n",
+@@ -1797,7 +1799,7 @@ static int __init pm2fb_setup(char *options)
+ else if (!strncmp(this_opt, "noaccel", 7))
+ noaccel = 1;
+ else
+- mode = this_opt;
++ mode_option = this_opt;
}
-- 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);
+ return 0;
+ }
+@@ -1833,8 +1835,10 @@ static void __exit pm2fb_exit(void)
+ #ifdef MODULE
+ module_exit(pm2fb_exit);
- /* 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);
+-module_param(mode, charp, 0);
+-MODULE_PARM_DESC(mode, "Preferred video mode e.g. '648x480-8 at 60'");
++module_param(mode_option, charp, 0);
++MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8 at 60'");
++module_param_named(mode, mode_option, charp, 0);
++MODULE_PARM_DESC(mode, "Initial video mode e.g. '648x480-8 at 60' (deprecated)");
+ module_param(lowhsync, bool, 0);
+ MODULE_PARM_DESC(lowhsync, "Force horizontal sync low regardless of mode");
+ module_param(lowvsync, bool, 0);
+diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
+index 5dba8cd..68089d1 100644
+--- a/drivers/video/pm3fb.c
++++ b/drivers/video/pm3fb.c
+@@ -45,7 +45,7 @@
+ #undef PM3FB_MASTER_DEBUG
+ #ifdef PM3FB_MASTER_DEBUG
+ #define DPRINTK(a, b...) \
+- printk(KERN_DEBUG "pm3fb: %s: " a, __FUNCTION__ , ## b)
++ printk(KERN_DEBUG "pm3fb: %s: " a, __func__ , ## b)
+ #else
+ #define DPRINTK(a, b...)
+ #endif
+@@ -1571,6 +1571,8 @@ module_exit(pm3fb_exit);
+ #endif
+ module_init(pm3fb_init);
- /* 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);
++module_param(mode_option, charp, 0);
++MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8 at 60'");
+ module_param(noaccel, bool, 0);
+ MODULE_PARM_DESC(noaccel, "Disable acceleration");
+ module_param(hwcursor, int, 0644);
+diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
+index 97facb1..3ab6e3d 100644
+--- a/drivers/video/pxafb.c
++++ b/drivers/video/pxafb.c
+@@ -39,12 +39,16 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/clk.h>
+ #include <linux/err.h>
++#include <linux/completion.h>
++#include <linux/kthread.h>
++#include <linux/freezer.h>
- /* 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);
+ #include <asm/hardware.h>
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/div64.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/bitfield.h>
+ #include <asm/arch/pxafb.h>
- /* 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;
- }
+@@ -56,19 +60,31 @@
+ #include "pxafb.h"
+
+ /* Bits which should not be set in machine configuration structures */
+-#define LCCR0_INVALID_CONFIG_MASK (LCCR0_OUM|LCCR0_BM|LCCR0_QDM|LCCR0_DIS|LCCR0_EFM|LCCR0_IUM|LCCR0_SFM|LCCR0_LDM|LCCR0_ENB)
+-#define LCCR3_INVALID_CONFIG_MASK (LCCR3_HSP|LCCR3_VSP|LCCR3_PCD|LCCR3_BPP)
++#define LCCR0_INVALID_CONFIG_MASK (LCCR0_OUM | LCCR0_BM | LCCR0_QDM |\
++ LCCR0_DIS | LCCR0_EFM | LCCR0_IUM |\
++ LCCR0_SFM | LCCR0_LDM | LCCR0_ENB)
++
++#define LCCR3_INVALID_CONFIG_MASK (LCCR3_HSP | LCCR3_VSP |\
++ LCCR3_PCD | LCCR3_BPP)
+
+ static void (*pxafb_backlight_power)(int);
+ static void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
+
+-static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *);
++static int pxafb_activate_var(struct fb_var_screeninfo *var,
++ struct pxafb_info *);
+ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state);
+
+-#ifdef CONFIG_FB_PXA_PARAMETERS
+-#define PXAFB_OPTIONS_SIZE 256
+-static char g_options[PXAFB_OPTIONS_SIZE] __devinitdata = "";
+-#endif
++static inline unsigned long
++lcd_readl(struct pxafb_info *fbi, unsigned int off)
++{
++ return __raw_readl(fbi->mmio_base + off);
++}
++
++static inline void
++lcd_writel(struct pxafb_info *fbi, unsigned int off, unsigned long val)
++{
++ __raw_writel(val, fbi->mmio_base + off);
++}
+
+ static inline void pxafb_schedule_work(struct pxafb_info *fbi, u_int state)
+ {
+@@ -78,10 +94,12 @@ static inline void pxafb_schedule_work(struct pxafb_info *fbi, u_int state)
+ /*
+ * We need to handle two requests being made at the same time.
+ * There are two important cases:
+- * 1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE)
+- * We must perform the unblanking, which will do our REENABLE for us.
+- * 2. When we are blanking, but immediately unblank before we have
+- * blanked. We do the "REENABLE" thing here as well, just to be sure.
++ * 1. When we are changing VT (C_REENABLE) while unblanking
++ * (C_ENABLE) We must perform the unblanking, which will
++ * do our REENABLE for us.
++ * 2. When we are blanking, but immediately unblank before
++ * we have blanked. We do the "REENABLE" thing here as
++ * well, just to be sure.
+ */
+ if (fbi->task_state == C_ENABLE && state == C_REENABLE)
+ state = (u_int) -1;
+@@ -128,13 +146,13 @@ pxafb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
+ val = ((red << 8) & 0x00f80000);
+ val |= ((green >> 0) & 0x0000fc00);
+ val |= ((blue >> 8) & 0x000000f8);
+- ((u32*)(fbi->palette_cpu))[regno] = val;
++ ((u32 *)(fbi->palette_cpu))[regno] = val;
+ break;
+ case LCCR4_PAL_FOR_2:
+ val = ((red << 8) & 0x00fc0000);
+ val |= ((green >> 0) & 0x0000fc00);
+ val |= ((blue >> 8) & 0x000000fc);
+- ((u32*)(fbi->palette_cpu))[regno] = val;
++ ((u32 *)(fbi->palette_cpu))[regno] = val;
+ break;
}
-@@ -1454,7 +1448,7 @@ static void rx_data_softint(struct work_struct *work)
- urb->dev = port->serial->dev;
- result = usb_submit_urb(urb, GFP_ATOMIC);
- if (result) {
-- err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
-+ err("%s - failed resubmitting read urb, error %d", __func__, result);
- spin_lock_irqsave(&info->lock, flags);
- list_add(tmp, &info->rx_urbs_free);
- continue;
-diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
-index 7e53333..0f6d234 100644
---- a/drivers/usb/storage/Kconfig
-+++ b/drivers/usb/storage/Kconfig
-@@ -32,8 +32,8 @@ config USB_STORAGE_DEBUG
- verbose debugging messages.
- config USB_STORAGE_DATAFAB
-- bool "Datafab Compact Flash Reader support (EXPERIMENTAL)"
-- depends on USB_STORAGE && EXPERIMENTAL
-+ bool "Datafab Compact Flash Reader support"
-+ depends on USB_STORAGE
- help
- Support for certain Datafab CompactFlash readers.
- Datafab has a web page at <http://www.datafabusa.com/>.
-@@ -69,8 +69,8 @@ config USB_STORAGE_DPCM
- There is a web page at <http://www.ziocorp.com/products/>.
+@@ -202,15 +220,15 @@ pxafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ */
+ static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var)
+ {
+- int ret = 0;
+- switch (var->bits_per_pixel) {
+- case 1: ret = LCCR3_1BPP; break;
+- case 2: ret = LCCR3_2BPP; break;
+- case 4: ret = LCCR3_4BPP; break;
+- case 8: ret = LCCR3_8BPP; break;
+- case 16: ret = LCCR3_16BPP; break;
+- }
+- return ret;
++ int ret = 0;
++ switch (var->bits_per_pixel) {
++ case 1: ret = LCCR3_1BPP; break;
++ case 2: ret = LCCR3_2BPP; break;
++ case 4: ret = LCCR3_4BPP; break;
++ case 8: ret = LCCR3_8BPP; break;
++ case 16: ret = LCCR3_16BPP; break;
++ }
++ return ret;
+ }
- 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
+ #ifdef CONFIG_CPU_FREQ
+@@ -222,31 +240,32 @@ static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var)
+ */
+ static unsigned int pxafb_display_dma_period(struct fb_var_screeninfo *var)
+ {
+- /*
+- * Period = pixclock * bits_per_byte * bytes_per_transfer
+- * / memory_bits_per_pixel;
+- */
+- return var->pixclock * 8 * 16 / var->bits_per_pixel;
++ /*
++ * Period = pixclock * bits_per_byte * bytes_per_transfer
++ * / memory_bits_per_pixel;
++ */
++ return var->pixclock * 8 * 16 / var->bits_per_pixel;
+ }
+-
+-extern unsigned int get_clk_frequency_khz(int info);
+ #endif
- 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.
+ /*
+ * Select the smallest mode that allows the desired resolution to be
+ * displayed. If desired parameters can be rounded up.
+ */
+-static struct pxafb_mode_info *pxafb_getmode(struct pxafb_mach_info *mach, struct fb_var_screeninfo *var)
++static struct pxafb_mode_info *pxafb_getmode(struct pxafb_mach_info *mach,
++ struct fb_var_screeninfo *var)
+ {
+ struct pxafb_mode_info *mode = NULL;
+ struct pxafb_mode_info *modelist = mach->modes;
+ unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
+ unsigned int i;
- 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.
+- for (i = 0 ; i < mach->num_modes ; i++) {
+- if (modelist[i].xres >= var->xres && modelist[i].yres >= var->yres &&
+- modelist[i].xres < best_x && modelist[i].yres < best_y &&
+- modelist[i].bpp >= var->bits_per_pixel ) {
++ for (i = 0; i < mach->num_modes; i++) {
++ if (modelist[i].xres >= var->xres &&
++ modelist[i].yres >= var->yres &&
++ modelist[i].xres < best_x &&
++ modelist[i].yres < best_y &&
++ modelist[i].bpp >= var->bits_per_pixel) {
+ best_x = modelist[i].xres;
+ best_y = modelist[i].yres;
+ mode = &modelist[i];
+@@ -256,7 +275,8 @@ static struct pxafb_mode_info *pxafb_getmode(struct pxafb_mach_info *mach, struc
+ return mode;
+ }
- 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.
+-static void pxafb_setmode(struct fb_var_screeninfo *var, struct pxafb_mode_info *mode)
++static void pxafb_setmode(struct fb_var_screeninfo *var,
++ struct pxafb_mode_info *mode)
+ {
+ var->xres = mode->xres;
+ var->yres = mode->yres;
+@@ -314,19 +334,20 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+ var->yres_virtual =
+ max(var->yres_virtual, var->yres);
- 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.
+- /*
++ /*
+ * Setup the RGB parameters for this display.
+ *
+ * The pixel packing format is described on page 7-11 of the
+ * PXA2XX Developer's Manual.
+- */
++ */
+ if (var->bits_per_pixel == 16) {
+ var->red.offset = 11; var->red.length = 5;
+ var->green.offset = 5; var->green.length = 6;
+ var->blue.offset = 0; var->blue.length = 5;
+ var->transp.offset = var->transp.length = 0;
+ } else {
+- var->red.offset = var->green.offset = var->blue.offset = var->transp.offset = 0;
++ var->red.offset = var->green.offset = 0;
++ var->blue.offset = var->transp.offset = 0;
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+@@ -344,8 +365,7 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
- 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.
+ static inline void pxafb_set_truecolor(u_int is_true_color)
+ {
+- pr_debug("pxafb: true_color = %d\n", is_true_color);
+- // do your machine-specific setup if needed
++ /* do your machine-specific setup if needed */
+ }
-+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).
+ /*
+@@ -356,9 +376,6 @@ static int pxafb_set_par(struct fb_info *info)
+ {
+ struct pxafb_info *fbi = (struct pxafb_info *)info;
+ struct fb_var_screeninfo *var = &info->var;
+- unsigned long palette_mem_size;
+-
+- pr_debug("pxafb: set_par\n");
+
+ if (var->bits_per_pixel == 16)
+ fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+@@ -378,17 +395,10 @@ static int pxafb_set_par(struct fb_info *info)
+ if (var->bits_per_pixel == 16)
+ fbi->palette_size = 0;
+ else
+- fbi->palette_size = var->bits_per_pixel == 1 ? 4 : 1 << var->bits_per_pixel;
+-
+- if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
+- palette_mem_size = fbi->palette_size * sizeof(u16);
+- else
+- palette_mem_size = fbi->palette_size * sizeof(u32);
+-
+- pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size);
++ fbi->palette_size = var->bits_per_pixel == 1 ?
++ 4 : 1 << var->bits_per_pixel;
+
+- fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
+- fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
++ fbi->palette_cpu = (u16 *)&fbi->dma_buff->palette[0];
+
+ /*
+ * Set (any) board control register to handle new color depth
+@@ -406,36 +416,6 @@ static int pxafb_set_par(struct fb_info *info)
+ }
+
+ /*
+- * Formal definition of the VESA spec:
+- * On
+- * This refers to the state of the display when it is in full operation
+- * Stand-By
+- * This defines an optional operating state of minimal power reduction with
+- * the shortest recovery time
+- * Suspend
+- * This refers to a level of power management in which substantial power
+- * reduction is achieved by the display. The display can have a longer
+- * recovery time from this state than from the Stand-by state
+- * Off
+- * This indicates that the display is consuming the lowest level of power
+- * and is non-operational. Recovery from this state may optionally require
+- * the user to manually power on the monitor
+- *
+- * Now, the fbdev driver adds an additional state, (blank), where they
+- * turn off the video (maybe by colormap tricks), but don't mess with the
+- * video itself: think of it semantically between on and Stand-By.
+- *
+- * So here's what we should do in our fbdev blank routine:
+- *
+- * VESA_NO_BLANKING (mode 0) Video on, front/back light on
+- * VESA_VSYNC_SUSPEND (mode 1) Video on, front/back light off
+- * VESA_HSYNC_SUSPEND (mode 2) Video on, front/back light off
+- * VESA_POWERDOWN (mode 3) Video off, front/back light off
+- *
+- * This will match the matrox implementation.
+- */
+-
+-/*
+ * pxafb_blank():
+ * Blank the display by setting all palette values to zero. Note, the
+ * 16 bpp mode does not really use the palette, so this will not
+@@ -446,8 +426,6 @@ static int pxafb_blank(int blank, struct fb_info *info)
+ struct pxafb_info *fbi = (struct pxafb_info *)info;
+ int i;
+
+- pr_debug("pxafb: blank=%d\n", blank);
+-
+ switch (blank) {
+ case FB_BLANK_POWERDOWN:
+ case FB_BLANK_VSYNC_SUSPEND:
+@@ -459,11 +437,11 @@ static int pxafb_blank(int blank, struct fb_info *info)
+ pxafb_setpalettereg(i, 0, 0, 0, 0, info);
+
+ pxafb_schedule_work(fbi, C_DISABLE);
+- //TODO if (pxafb_blank_helper) pxafb_blank_helper(blank);
++ /* TODO if (pxafb_blank_helper) pxafb_blank_helper(blank); */
+ break;
+
+ case FB_BLANK_UNBLANK:
+- //TODO if (pxafb_blank_helper) pxafb_blank_helper(blank);
++ /* TODO if (pxafb_blank_helper) pxafb_blank_helper(blank); */
+ if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
+ fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+ fb_set_cmap(&fbi->fb.cmap, info);
+@@ -479,7 +457,7 @@ static int pxafb_mmap(struct fb_info *info,
+ unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
+
+ if (off < info->fix.smem_len) {
+- vma->vm_pgoff += 1;
++ vma->vm_pgoff += fbi->video_offset / PAGE_SIZE;
+ return dma_mmap_writecombine(fbi->dev, vma, fbi->map_cpu,
+ fbi->map_dma, fbi->map_size);
+ }
+@@ -528,7 +506,8 @@ static struct fb_ops pxafb_ops = {
+ *
+ * Factoring the 10^4 and 10^-12 out gives 10^-8 == 1 / 100000000 as used below.
+ */
+-static inline unsigned int get_pcd(struct pxafb_info *fbi, unsigned int pixclock)
++static inline unsigned int get_pcd(struct pxafb_info *fbi,
++ unsigned int pixclock)
+ {
+ unsigned long long pcd;
+
+@@ -554,7 +533,7 @@ static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd)
+ unsigned long htime;
+
+ if ((pcd == 0) || (fbi->fb.var.hsync_len == 0)) {
+- fbi->hsync_time=0;
++ fbi->hsync_time = 0;
+ return;
+ }
+
+@@ -575,71 +554,231 @@ unsigned long pxafb_get_hsync_time(struct device *dev)
+ }
+ EXPORT_SYMBOL(pxafb_get_hsync_time);
+
+-/*
+- * pxafb_activate_var():
+- * Configures LCD Controller based on entries in var parameter. Settings are
+- * only written to the controller if changes were made.
+- */
+-static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *fbi)
++static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal,
++ unsigned int offset, size_t size)
+ {
+- struct pxafb_lcd_reg new_regs;
+- u_long flags;
+- u_int lines_per_panel, pcd = get_pcd(fbi, var->pixclock);
++ struct pxafb_dma_descriptor *dma_desc, *pal_desc;
++ unsigned int dma_desc_off, pal_desc_off;
+
+- pr_debug("pxafb: Configuring PXA LCD\n");
++ if (dma < 0 || dma >= DMA_MAX)
++ return -EINVAL;
+
+- pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
+- var->xres, var->hsync_len,
+- var->left_margin, var->right_margin);
+- pr_debug("var: yres=%d vslen=%d um=%d bm=%d\n",
+- var->yres, var->vsync_len,
+- var->upper_margin, var->lower_margin);
+- pr_debug("var: pixclock=%d pcd=%d\n", var->pixclock, pcd);
++ dma_desc = &fbi->dma_buff->dma_desc[dma];
++ dma_desc_off = offsetof(struct pxafb_dma_buff, dma_desc[dma]);
+
+-#if DEBUG_VAR
+- if (var->xres < 16 || var->xres > 1024)
+- printk(KERN_ERR "%s: invalid xres %d\n",
+- fbi->fb.fix.id, var->xres);
+- switch(var->bits_per_pixel) {
+- case 1:
+- case 2:
+- case 4:
+- case 8:
+- case 16:
+- break;
+- default:
+- printk(KERN_ERR "%s: invalid bit depth %d\n",
+- fbi->fb.fix.id, var->bits_per_pixel);
+- break;
++ dma_desc->fsadr = fbi->screen_dma + offset;
++ dma_desc->fidr = 0;
++ dma_desc->ldcmd = size;
++
++ if (pal < 0 || pal >= PAL_MAX) {
++ dma_desc->fdadr = fbi->dma_buff_phys + dma_desc_off;
++ fbi->fdadr[dma] = fbi->dma_buff_phys + dma_desc_off;
++ } else {
++ pal_desc = &fbi->dma_buff->pal_desc[dma];
++ pal_desc_off = offsetof(struct pxafb_dma_buff, dma_desc[pal]);
+
-+ If you say no here your device will still work with the standard usb
-+ mass storage class.
++ pal_desc->fsadr = fbi->dma_buff_phys + pal * PALETTE_SIZE;
++ pal_desc->fidr = 0;
+
- 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
++ if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
++ pal_desc->ldcmd = fbi->palette_size * sizeof(u16);
++ else
++ pal_desc->ldcmd = fbi->palette_size * sizeof(u32);
++
++ pal_desc->ldcmd |= LDCMD_PAL;
++
++ /* flip back and forth between palette and frame buffer */
++ pal_desc->fdadr = fbi->dma_buff_phys + dma_desc_off;
++ dma_desc->fdadr = fbi->dma_buff_phys + pal_desc_off;
++ fbi->fdadr[dma] = fbi->dma_buff_phys + dma_desc_off;
+ }
+- if (var->hsync_len < 1 || var->hsync_len > 64)
+- printk(KERN_ERR "%s: invalid hsync_len %d\n",
+- fbi->fb.fix.id, var->hsync_len);
+- if (var->left_margin < 1 || var->left_margin > 255)
+- printk(KERN_ERR "%s: invalid left_margin %d\n",
+- fbi->fb.fix.id, var->left_margin);
+- if (var->right_margin < 1 || var->right_margin > 255)
+- printk(KERN_ERR "%s: invalid right_margin %d\n",
+- fbi->fb.fix.id, var->right_margin);
+- if (var->yres < 1 || var->yres > 1024)
+- printk(KERN_ERR "%s: invalid yres %d\n",
+- fbi->fb.fix.id, var->yres);
+- if (var->vsync_len < 1 || var->vsync_len > 64)
+- printk(KERN_ERR "%s: invalid vsync_len %d\n",
+- fbi->fb.fix.id, var->vsync_len);
+- if (var->upper_margin < 0 || var->upper_margin > 255)
+- printk(KERN_ERR "%s: invalid upper_margin %d\n",
+- fbi->fb.fix.id, var->upper_margin);
+- if (var->lower_margin < 0 || var->lower_margin > 255)
+- printk(KERN_ERR "%s: invalid lower_margin %d\n",
+- fbi->fb.fix.id, var->lower_margin);
+-#endif
- usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \
- initializers.o $(usb-storage-obj-y)
-diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c
-new file mode 100644
-index 0000000..d88824b
---- /dev/null
-+++ b/drivers/usb/storage/cypress_atacb.c
-@@ -0,0 +1,200 @@
-+/*
-+ * Support for emulating SAT (ata pass through) on devices based
-+ * on the Cypress USB/ATA bridge supporting ATACB.
-+ *
-+ * Copyright (c) 2008 Matthieu Castet (castet.matthieu at free.fr)
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2, or (at your option) any
-+ * later version.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along
-+ * with this program; if not, write to the Free Software Foundation, Inc.,
-+ * 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
+- new_regs.lccr0 = fbi->lccr0 |
+- (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM |
+- LCCR0_QDM | LCCR0_BM | LCCR0_OUM);
++ return 0;
++}
+
-+#include <scsi/scsi.h>
-+#include <scsi/scsi_cmnd.h>
-+#include <scsi/scsi_eh.h>
-+#include <linux/ata.h>
++#ifdef CONFIG_FB_PXA_SMARTPANEL
++static int setup_smart_dma(struct pxafb_info *fbi)
++{
++ struct pxafb_dma_descriptor *dma_desc;
++ unsigned long dma_desc_off, cmd_buff_off;
+
-+#include "usb.h"
-+#include "protocol.h"
-+#include "scsiglue.h"
-+#include "debug.h"
++ dma_desc = &fbi->dma_buff->dma_desc[DMA_CMD];
++ dma_desc_off = offsetof(struct pxafb_dma_buff, dma_desc[DMA_CMD]);
++ cmd_buff_off = offsetof(struct pxafb_dma_buff, cmd_buff);
+
-+/*
-+ * 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)
++ dma_desc->fdadr = fbi->dma_buff_phys + dma_desc_off;
++ dma_desc->fsadr = fbi->dma_buff_phys + cmd_buff_off;
++ dma_desc->fidr = 0;
++ dma_desc->ldcmd = fbi->n_smart_cmds * sizeof(uint16_t);
++
++ fbi->fdadr[DMA_CMD] = dma_desc->fdadr;
++ return 0;
++}
++
++int pxafb_smart_flush(struct fb_info *info)
+{
-+ unsigned char save_cmnd[MAX_COMMAND_SIZE];
++ struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb);
++ uint32_t prsr;
++ int ret = 0;
+
-+ if (likely(srb->cmnd[0] != ATA_16 && srb->cmnd[0] != ATA_12)) {
-+ usb_stor_transparent_scsi_command(srb, us);
-+ return;
-+ }
++ /* disable controller until all registers are set up */
++ lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
+
-+ memcpy(save_cmnd, srb->cmnd, sizeof(save_cmnd));
-+ memset(srb->cmnd, 0, sizeof(srb->cmnd));
++ /* 1. make it an even number of commands to align on 32-bit boundary
++ * 2. add the interrupt command to the end of the chain so we can
++ * keep track of the end of the transfer
++ */
+
-+ /* 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;
-+ }
++ while (fbi->n_smart_cmds & 1)
++ fbi->smart_cmds[fbi->n_smart_cmds++] = SMART_CMD_NOOP;
+
-+ /* first build the ATACB command */
-+ srb->cmd_len = 16;
++ fbi->smart_cmds[fbi->n_smart_cmds++] = SMART_CMD_INTERRUPT;
++ fbi->smart_cmds[fbi->n_smart_cmds++] = SMART_CMD_WAIT_FOR_VSYNC;
++ setup_smart_dma(fbi);
+
-+ 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 */
++ /* continue to execute next command */
++ prsr = lcd_readl(fbi, PRSR) | PRSR_ST_OK | PRSR_CON_NT;
++ lcd_writel(fbi, PRSR, prsr);
+
-+ srb->cmnd[3] = 0xff - 1; /* features, sector count, lba low, lba med
-+ lba high, device, command are valid */
-+ srb->cmnd[4] = 1; /* TransferBlockCount : 512 */
++ /* stop the processor in case it executed "wait for sync" cmd */
++ lcd_writel(fbi, CMDCR, 0x0001);
+
-+ 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 */
++ /* don't send interrupts for fifo underruns on channel 6 */
++ lcd_writel(fbi, LCCR5, LCCR5_IUM(6));
+
-+ 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 */
++ lcd_writel(fbi, LCCR1, fbi->reg_lccr1);
++ lcd_writel(fbi, LCCR2, fbi->reg_lccr2);
++ lcd_writel(fbi, LCCR3, fbi->reg_lccr3);
++ lcd_writel(fbi, FDADR0, fbi->fdadr[0]);
++ lcd_writel(fbi, FDADR6, fbi->fdadr[6]);
++
++ /* begin sending */
++ lcd_writel(fbi, LCCR0, fbi->reg_lccr0 | LCCR0_ENB);
+
++ if (wait_for_completion_timeout(&fbi->command_done, HZ/2) == 0) {
++ pr_warning("%s: timeout waiting for command done\n",
++ __func__);
++ ret = -ETIMEDOUT;
+ }
-+ /* 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 */
++ /* quick disable */
++ prsr = lcd_readl(fbi, PRSR) & ~(PRSR_ST_OK | PRSR_CON_NT);
++ lcd_writel(fbi, PRSR, prsr);
++ lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
++ lcd_writel(fbi, FDADR6, 0);
++ fbi->n_smart_cmds = 0;
++ return ret;
++}
+
++int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int n_cmds)
++{
++ int i;
++ struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb);
+
-+ usb_stor_transparent_scsi_command(srb, us);
++ /* leave 2 commands for INTERRUPT and WAIT_FOR_SYNC */
++ for (i = 0; i < n_cmds; i++) {
++ if (fbi->n_smart_cmds == CMD_BUFF_SIZE - 8)
++ pxafb_smart_flush(info);
+
-+ /* 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;
++ fbi->smart_cmds[fbi->n_smart_cmds++] = *cmds++;
+ }
+
-+ /* 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;
++ return 0;
++}
+
-+ /* 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;
++static unsigned int __smart_timing(unsigned time_ns, unsigned long lcd_clk)
++{
++ unsigned int t = (time_ns * (lcd_clk / 1000000) / 1000);
++ return (t == 0) ? 1 : t;
++}
+
-+ 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;
++static void setup_smart_timing(struct pxafb_info *fbi,
++ struct fb_var_screeninfo *var)
++{
++ struct pxafb_mach_info *inf = fbi->dev->platform_data;
++ struct pxafb_mode_info *mode = &inf->modes[0];
++ unsigned long lclk = clk_get_rate(fbi->clk);
++ unsigned t1, t2, t3, t4;
+
-+ /* build the sense */
-+ memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
++ t1 = max(mode->a0csrd_set_hld, mode->a0cswr_set_hld);
++ t2 = max(mode->rd_pulse_width, mode->wr_pulse_width);
++ t3 = mode->op_hold_time;
++ t4 = mode->cmd_inh_time;
+
-+ /* set sk, asc for a good command */
-+ sb[1] = RECOVERED_ERROR;
-+ sb[2] = 0; /* ATA PASS THROUGH INFORMATION AVAILABLE */
-+ sb[3] = 0x1D;
++ fbi->reg_lccr1 =
++ LCCR1_DisWdth(var->xres) |
++ LCCR1_BegLnDel(__smart_timing(t1, lclk)) |
++ LCCR1_EndLnDel(__smart_timing(t2, lclk)) |
++ LCCR1_HorSnchWdth(__smart_timing(t3, lclk));
+
-+ /* 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.
-+ */
++ fbi->reg_lccr2 = LCCR2_DisHght(var->yres);
++ fbi->reg_lccr3 = LCCR3_PixClkDiv(__smart_timing(t4, lclk));
+
-+ /* Sense data is current and format is descriptor. */
-+ sb[0] = 0x72;
-+ desc[0] = 0x09; /* ATA_RETURN_DESCRIPTOR */
++ /* FIXME: make this configurable */
++ fbi->reg_cmdcr = 1;
++}
+
-+ /* set length of additional sense data */
-+ sb[7] = 14;
-+ desc[1] = 12;
++static int pxafb_smart_thread(void *arg)
++{
++ struct pxafb_info *fbi = arg;
++ struct pxafb_mach_info *inf = fbi->dev->platform_data;
+
-+ /* 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 */
++ if (!fbi || !inf->smart_update) {
++ pr_err("%s: not properly initialized, thread terminated\n",
++ __func__);
++ return -EINVAL;
++ }
+
+- new_regs.lccr1 =
++ pr_debug("%s(): task starting\n", __func__);
+
-+ srb->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
++ set_freezable();
++ while (!kthread_should_stop()) {
++
++ if (try_to_freeze())
++ continue;
++
++ if (fbi->state == C_ENABLE) {
++ inf->smart_update(&fbi->fb);
++ complete(&fbi->refresh_done);
++ }
++
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(30 * HZ / 1000);
+ }
-+ 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;
++ pr_debug("%s(): task ending\n", __func__);
++ return 0;
+}
-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 @@
++
++static int pxafb_smart_init(struct pxafb_info *fbi)
++{
++ fbi->smart_thread = kthread_run(pxafb_smart_thread, fbi,
++ "lcd_refresh");
++ if (IS_ERR(fbi->smart_thread)) {
++ printk(KERN_ERR "%s: unable to create kernel thread\n",
++ __func__);
++ return PTR_ERR(fbi->smart_thread);
++ }
++ return 0;
++}
++#else
++int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int n_cmds)
++{
++ return 0;
++}
++
++int pxafb_smart_flush(struct fb_info *info)
++{
++ return 0;
++}
++#endif /* CONFIG_FB_SMART_PANEL */
++
++static void setup_parallel_timing(struct pxafb_info *fbi,
++ struct fb_var_screeninfo *var)
++{
++ unsigned int lines_per_panel, pcd = get_pcd(fbi, var->pixclock);
++
++ fbi->reg_lccr1 =
+ LCCR1_DisWdth(var->xres) +
+ LCCR1_HorSnchWdth(var->hsync_len) +
+ LCCR1_BegLnDel(var->left_margin) +
+@@ -653,110 +792,118 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
+ if ((fbi->lccr0 & LCCR0_SDS) == LCCR0_Dual)
+ lines_per_panel /= 2;
+
+- new_regs.lccr2 =
++ fbi->reg_lccr2 =
+ LCCR2_DisHght(lines_per_panel) +
+ LCCR2_VrtSnchWdth(var->vsync_len) +
+ LCCR2_BegFrmDel(var->upper_margin) +
+ LCCR2_EndFrmDel(var->lower_margin);
+
+- new_regs.lccr3 = fbi->lccr3 |
+- pxafb_bpp_to_lccr3(var) |
+- (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
+- (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL);
++ fbi->reg_lccr3 = fbi->lccr3 |
++ (var->sync & FB_SYNC_HOR_HIGH_ACT ?
++ LCCR3_HorSnchH : LCCR3_HorSnchL) |
++ (var->sync & FB_SYNC_VERT_HIGH_ACT ?
++ LCCR3_VrtSnchH : LCCR3_VrtSnchL);
++
++ if (pcd) {
++ fbi->reg_lccr3 |= LCCR3_PixClkDiv(pcd);
++ set_hsync_time(fbi, pcd);
++ }
++}
+
+- if (pcd)
+- new_regs.lccr3 |= LCCR3_PixClkDiv(pcd);
+/*
-+ * Support for emulating SAT (ata pass through) on devices based
-+ * on the Cypress USB/ATA bridge supporting ATACB.
-+ *
-+ * Copyright (c) 2008 Matthieu Castet (castet.matthieu at free.fr)
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2, or (at your option) any
-+ * later version.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along
-+ * with this program; if not, write to the Free Software Foundation, Inc.,
-+ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ * pxafb_activate_var():
++ * Configures LCD Controller based on entries in var parameter.
++ * Settings are only written to the controller if changes were made.
+ */
++static int pxafb_activate_var(struct fb_var_screeninfo *var,
++ struct pxafb_info *fbi)
++{
++ u_long flags;
++ size_t nbytes;
+
+- pr_debug("nlccr0 = 0x%08x\n", new_regs.lccr0);
+- pr_debug("nlccr1 = 0x%08x\n", new_regs.lccr1);
+- pr_debug("nlccr2 = 0x%08x\n", new_regs.lccr2);
+- pr_debug("nlccr3 = 0x%08x\n", new_regs.lccr3);
++#if DEBUG_VAR
++ if (!(fbi->lccr0 & LCCR0_LCDT)) {
++ if (var->xres < 16 || var->xres > 1024)
++ printk(KERN_ERR "%s: invalid xres %d\n",
++ fbi->fb.fix.id, var->xres);
++ switch (var->bits_per_pixel) {
++ case 1:
++ case 2:
++ case 4:
++ case 8:
++ case 16:
++ break;
++ default:
++ printk(KERN_ERR "%s: invalid bit depth %d\n",
++ fbi->fb.fix.id, var->bits_per_pixel);
++ break;
++ }
+
++ if (var->hsync_len < 1 || var->hsync_len > 64)
++ printk(KERN_ERR "%s: invalid hsync_len %d\n",
++ fbi->fb.fix.id, var->hsync_len);
++ if (var->left_margin < 1 || var->left_margin > 255)
++ printk(KERN_ERR "%s: invalid left_margin %d\n",
++ fbi->fb.fix.id, var->left_margin);
++ if (var->right_margin < 1 || var->right_margin > 255)
++ printk(KERN_ERR "%s: invalid right_margin %d\n",
++ fbi->fb.fix.id, var->right_margin);
++ if (var->yres < 1 || var->yres > 1024)
++ printk(KERN_ERR "%s: invalid yres %d\n",
++ fbi->fb.fix.id, var->yres);
++ if (var->vsync_len < 1 || var->vsync_len > 64)
++ printk(KERN_ERR "%s: invalid vsync_len %d\n",
++ fbi->fb.fix.id, var->vsync_len);
++ if (var->upper_margin < 0 || var->upper_margin > 255)
++ printk(KERN_ERR "%s: invalid upper_margin %d\n",
++ fbi->fb.fix.id, var->upper_margin);
++ if (var->lower_margin < 0 || var->lower_margin > 255)
++ printk(KERN_ERR "%s: invalid lower_margin %d\n",
++ fbi->fb.fix.id, var->lower_margin);
++ }
++#endif
+ /* Update shadow copy atomically */
+ local_irq_save(flags);
+
+- /* setup dma descriptors */
+- fbi->dmadesc_fblow_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 3*16);
+- fbi->dmadesc_fbhigh_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 2*16);
+- fbi->dmadesc_palette_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 1*16);
+-
+- fbi->dmadesc_fblow_dma = fbi->palette_dma - 3*16;
+- fbi->dmadesc_fbhigh_dma = fbi->palette_dma - 2*16;
+- fbi->dmadesc_palette_dma = fbi->palette_dma - 1*16;
+-
+-#define BYTES_PER_PANEL (lines_per_panel * fbi->fb.fix.line_length)
+-
+- /* populate descriptors */
+- fbi->dmadesc_fblow_cpu->fdadr = fbi->dmadesc_fblow_dma;
+- fbi->dmadesc_fblow_cpu->fsadr = fbi->screen_dma + BYTES_PER_PANEL;
+- fbi->dmadesc_fblow_cpu->fidr = 0;
+- fbi->dmadesc_fblow_cpu->ldcmd = BYTES_PER_PANEL;
++#ifdef CONFIG_FB_PXA_SMARTPANEL
++ if (fbi->lccr0 & LCCR0_LCDT)
++ setup_smart_timing(fbi, var);
++ else
++#endif
++ setup_parallel_timing(fbi, var);
+
+- fbi->fdadr1 = fbi->dmadesc_fblow_dma; /* only used in dual-panel mode */
++ fbi->reg_lccr0 = fbi->lccr0 |
++ (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM |
++ LCCR0_QDM | LCCR0_BM | LCCR0_OUM);
+
+- fbi->dmadesc_fbhigh_cpu->fsadr = fbi->screen_dma;
+- fbi->dmadesc_fbhigh_cpu->fidr = 0;
+- fbi->dmadesc_fbhigh_cpu->ldcmd = BYTES_PER_PANEL;
++ fbi->reg_lccr3 |= pxafb_bpp_to_lccr3(var);
+
+- fbi->dmadesc_palette_cpu->fsadr = fbi->palette_dma;
+- fbi->dmadesc_palette_cpu->fidr = 0;
+- if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
+- fbi->dmadesc_palette_cpu->ldcmd = fbi->palette_size *
+- sizeof(u16);
+- else
+- fbi->dmadesc_palette_cpu->ldcmd = fbi->palette_size *
+- sizeof(u32);
+- fbi->dmadesc_palette_cpu->ldcmd |= LDCMD_PAL;
++ nbytes = var->yres * fbi->fb.fix.line_length;
+
+- if (var->bits_per_pixel == 16) {
+- /* palette shouldn't be loaded in true-color mode */
+- fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_fbhigh_dma;
+- fbi->fdadr0 = fbi->dmadesc_fbhigh_dma; /* no pal just fbhigh */
+- /* init it to something, even though we won't be using it */
+- fbi->dmadesc_palette_cpu->fdadr = fbi->dmadesc_palette_dma;
+- } else {
+- fbi->dmadesc_palette_cpu->fdadr = fbi->dmadesc_fbhigh_dma;
+- fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_palette_dma;
+- fbi->fdadr0 = fbi->dmadesc_palette_dma; /* flips back and forth between pal and fbhigh */
++ if ((fbi->lccr0 & LCCR0_SDS) == LCCR0_Dual) {
++ nbytes = nbytes / 2;
++ setup_frame_dma(fbi, DMA_LOWER, PAL_NONE, nbytes, nbytes);
+ }
+
+-#if 0
+- pr_debug("fbi->dmadesc_fblow_cpu = 0x%p\n", fbi->dmadesc_fblow_cpu);
+- pr_debug("fbi->dmadesc_fbhigh_cpu = 0x%p\n", fbi->dmadesc_fbhigh_cpu);
+- pr_debug("fbi->dmadesc_palette_cpu = 0x%p\n", fbi->dmadesc_palette_cpu);
+- pr_debug("fbi->dmadesc_fblow_dma = 0x%x\n", fbi->dmadesc_fblow_dma);
+- pr_debug("fbi->dmadesc_fbhigh_dma = 0x%x\n", fbi->dmadesc_fbhigh_dma);
+- pr_debug("fbi->dmadesc_palette_dma = 0x%x\n", fbi->dmadesc_palette_dma);
+-
+- pr_debug("fbi->dmadesc_fblow_cpu->fdadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fdadr);
+- pr_debug("fbi->dmadesc_fbhigh_cpu->fdadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fdadr);
+- pr_debug("fbi->dmadesc_palette_cpu->fdadr = 0x%x\n", fbi->dmadesc_palette_cpu->fdadr);
+-
+- pr_debug("fbi->dmadesc_fblow_cpu->fsadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fsadr);
+- pr_debug("fbi->dmadesc_fbhigh_cpu->fsadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fsadr);
+- pr_debug("fbi->dmadesc_palette_cpu->fsadr = 0x%x\n", fbi->dmadesc_palette_cpu->fsadr);
+-
+- pr_debug("fbi->dmadesc_fblow_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fblow_cpu->ldcmd);
+- pr_debug("fbi->dmadesc_fbhigh_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fbhigh_cpu->ldcmd);
+- pr_debug("fbi->dmadesc_palette_cpu->ldcmd = 0x%x\n", fbi->dmadesc_palette_cpu->ldcmd);
+-#endif
++ if ((var->bits_per_pixel >= 16) || (fbi->lccr0 & LCCR0_LCDT))
++ setup_frame_dma(fbi, DMA_BASE, PAL_NONE, 0, nbytes);
++ else
++ setup_frame_dma(fbi, DMA_BASE, PAL_BASE, 0, nbytes);
+
+- fbi->reg_lccr0 = new_regs.lccr0;
+- fbi->reg_lccr1 = new_regs.lccr1;
+- fbi->reg_lccr2 = new_regs.lccr2;
+- fbi->reg_lccr3 = new_regs.lccr3;
+- fbi->reg_lccr4 = LCCR4 & (~LCCR4_PAL_FOR_MASK);
++ fbi->reg_lccr4 = lcd_readl(fbi, LCCR4) & ~LCCR4_PAL_FOR_MASK;
+ fbi->reg_lccr4 |= (fbi->lccr4 & LCCR4_PAL_FOR_MASK);
+- set_hsync_time(fbi, pcd);
+ local_irq_restore(flags);
+
+ /*
+ * Only update the registers if the controller is enabled
+ * and something has changed.
+ */
+- if ((LCCR0 != fbi->reg_lccr0) || (LCCR1 != fbi->reg_lccr1) ||
+- (LCCR2 != fbi->reg_lccr2) || (LCCR3 != fbi->reg_lccr3) ||
+- (FDADR0 != fbi->fdadr0) || (FDADR1 != fbi->fdadr1))
++ if ((lcd_readl(fbi, LCCR0) != fbi->reg_lccr0) ||
++ (lcd_readl(fbi, LCCR1) != fbi->reg_lccr1) ||
++ (lcd_readl(fbi, LCCR2) != fbi->reg_lccr2) ||
++ (lcd_readl(fbi, LCCR3) != fbi->reg_lccr3) ||
++ (lcd_readl(fbi, FDADR0) != fbi->fdadr[0]) ||
++ (lcd_readl(fbi, FDADR1) != fbi->fdadr[1]))
+ pxafb_schedule_work(fbi, C_REENABLE);
+
+ return 0;
+@@ -772,8 +919,8 @@ static inline void __pxafb_backlight_power(struct pxafb_info *fbi, int on)
+ {
+ pr_debug("pxafb: backlight o%s\n", on ? "n" : "ff");
+
+- if (pxafb_backlight_power)
+- pxafb_backlight_power(on);
++ if (pxafb_backlight_power)
++ pxafb_backlight_power(on);
+ }
+
+ static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on)
+@@ -787,11 +934,11 @@ static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on)
+ static void pxafb_setup_gpio(struct pxafb_info *fbi)
+ {
+ int gpio, ldd_bits;
+- unsigned int lccr0 = fbi->lccr0;
++ unsigned int lccr0 = fbi->lccr0;
+
+ /*
+ * setup is based on type of panel supported
+- */
++ */
+
+ /* 4 bit interface */
+ if ((lccr0 & LCCR0_CMS) == LCCR0_Mono &&
+@@ -800,21 +947,25 @@ static void pxafb_setup_gpio(struct pxafb_info *fbi)
+ ldd_bits = 4;
+
+ /* 8 bit interface */
+- else if (((lccr0 & LCCR0_CMS) == LCCR0_Mono &&
+- ((lccr0 & LCCR0_SDS) == LCCR0_Dual || (lccr0 & LCCR0_DPD) == LCCR0_8PixMono)) ||
+- ((lccr0 & LCCR0_CMS) == LCCR0_Color &&
+- (lccr0 & LCCR0_PAS) == LCCR0_Pas && (lccr0 & LCCR0_SDS) == LCCR0_Sngl))
++ else if (((lccr0 & LCCR0_CMS) == LCCR0_Mono &&
++ ((lccr0 & LCCR0_SDS) == LCCR0_Dual ||
++ (lccr0 & LCCR0_DPD) == LCCR0_8PixMono)) ||
++ ((lccr0 & LCCR0_CMS) == LCCR0_Color &&
++ (lccr0 & LCCR0_PAS) == LCCR0_Pas &&
++ (lccr0 & LCCR0_SDS) == LCCR0_Sngl))
+ ldd_bits = 8;
+
+ /* 16 bit interface */
+ else if ((lccr0 & LCCR0_CMS) == LCCR0_Color &&
+- ((lccr0 & LCCR0_SDS) == LCCR0_Dual || (lccr0 & LCCR0_PAS) == LCCR0_Act))
++ ((lccr0 & LCCR0_SDS) == LCCR0_Dual ||
++ (lccr0 & LCCR0_PAS) == LCCR0_Act))
+ ldd_bits = 16;
+
+ else {
+- printk(KERN_ERR "pxafb_setup_gpio: unable to determine bits per pixel\n");
++ printk(KERN_ERR "pxafb_setup_gpio: unable to determine "
++ "bits per pixel\n");
+ return;
+- }
++ }
+
+ for (gpio = 58; ldd_bits; gpio++, ldd_bits--)
+ pxa_gpio_mode(gpio | GPIO_ALT_FN_2_OUT);
+@@ -827,8 +978,8 @@ static void pxafb_setup_gpio(struct pxafb_info *fbi)
+ static void pxafb_enable_controller(struct pxafb_info *fbi)
+ {
+ pr_debug("pxafb: Enabling LCD controller\n");
+- pr_debug("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr0);
+- pr_debug("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr1);
++ pr_debug("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr[0]);
++ pr_debug("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr[1]);
+ pr_debug("reg_lccr0 0x%08x\n", (unsigned int) fbi->reg_lccr0);
+ pr_debug("reg_lccr1 0x%08x\n", (unsigned int) fbi->reg_lccr1);
+ pr_debug("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2);
+@@ -837,40 +988,40 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
+ /* enable LCD controller clock */
+ clk_enable(fbi->clk);
+
++ if (fbi->lccr0 & LCCR0_LCDT)
++ return;
+
-+#ifndef _CYPRESS_ATACB_H_
-+#define _CYPRESS_ATACB_H_
-+extern void cypress_atacb_passthrough(struct scsi_cmnd*, struct us_data*);
+ /* Sequence from 11.7.10 */
+- LCCR3 = fbi->reg_lccr3;
+- LCCR2 = fbi->reg_lccr2;
+- LCCR1 = fbi->reg_lccr1;
+- LCCR0 = fbi->reg_lccr0 & ~LCCR0_ENB;
+-
+- FDADR0 = fbi->fdadr0;
+- FDADR1 = fbi->fdadr1;
+- LCCR0 |= LCCR0_ENB;
+-
+- pr_debug("FDADR0 0x%08x\n", (unsigned int) FDADR0);
+- pr_debug("FDADR1 0x%08x\n", (unsigned int) FDADR1);
+- pr_debug("LCCR0 0x%08x\n", (unsigned int) LCCR0);
+- pr_debug("LCCR1 0x%08x\n", (unsigned int) LCCR1);
+- pr_debug("LCCR2 0x%08x\n", (unsigned int) LCCR2);
+- pr_debug("LCCR3 0x%08x\n", (unsigned int) LCCR3);
+- pr_debug("LCCR4 0x%08x\n", (unsigned int) LCCR4);
++ lcd_writel(fbi, LCCR3, fbi->reg_lccr3);
++ lcd_writel(fbi, LCCR2, fbi->reg_lccr2);
++ lcd_writel(fbi, LCCR1, fbi->reg_lccr1);
++ lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
++
++ lcd_writel(fbi, FDADR0, fbi->fdadr[0]);
++ lcd_writel(fbi, FDADR1, fbi->fdadr[1]);
++ lcd_writel(fbi, LCCR0, fbi->reg_lccr0 | LCCR0_ENB);
+ }
+
+ static void pxafb_disable_controller(struct pxafb_info *fbi)
+ {
+- DECLARE_WAITQUEUE(wait, current);
++ uint32_t lccr0;
+
+- pr_debug("pxafb: disabling LCD controller\n");
++#ifdef CONFIG_FB_PXA_SMARTPANEL
++ if (fbi->lccr0 & LCCR0_LCDT) {
++ wait_for_completion_timeout(&fbi->refresh_done,
++ 200 * HZ / 1000);
++ return;
++ }
+#endif
-diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
-index 55b9520..a28d491 100644
---- a/drivers/usb/storage/libusual.c
-+++ b/drivers/usb/storage/libusual.c
-@@ -9,6 +9,7 @@
- #include <linux/usb_usual.h>
- #include <linux/vmalloc.h>
- #include <linux/kthread.h>
-+#include <linux/mutex.h>
- /*
+- set_current_state(TASK_UNINTERRUPTIBLE);
+- add_wait_queue(&fbi->ctrlr_wait, &wait);
++ /* Clear LCD Status Register */
++ lcd_writel(fbi, LCSR, 0xffffffff);
+
+- LCSR = 0xffffffff; /* Clear LCD Status Register */
+- LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */
+- LCCR0 |= LCCR0_DIS; /* Disable LCD Controller */
++ lccr0 = lcd_readl(fbi, LCCR0) & ~LCCR0_LDM;
++ lcd_writel(fbi, LCCR0, lccr0);
++ lcd_writel(fbi, LCCR0, lccr0 | LCCR0_DIS);
+
+- schedule_timeout(200 * HZ / 1000);
+- remove_wait_queue(&fbi->ctrlr_wait, &wait);
++ wait_for_completion_timeout(&fbi->disable_done, 200 * HZ / 1000);
+
+ /* disable LCD controller clock */
+ clk_disable(fbi->clk);
+@@ -882,14 +1033,20 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
+ static irqreturn_t pxafb_handle_irq(int irq, void *dev_id)
+ {
+ struct pxafb_info *fbi = dev_id;
+- unsigned int lcsr = LCSR;
++ unsigned int lccr0, lcsr = lcd_readl(fbi, LCSR);
+
+ if (lcsr & LCSR_LDD) {
+- LCCR0 |= LCCR0_LDM;
+- wake_up(&fbi->ctrlr_wait);
++ lccr0 = lcd_readl(fbi, LCCR0);
++ lcd_writel(fbi, LCCR0, lccr0 | LCCR0_LDM);
++ complete(&fbi->disable_done);
+ }
+
+- LCSR = lcsr;
++#ifdef CONFIG_FB_PXA_SMARTPANEL
++ if (lcsr & LCSR_CMD_INT)
++ complete(&fbi->command_done);
++#endif
++
++ lcd_writel(fbi, LCSR, lcsr);
+ return IRQ_HANDLED;
+ }
+
+@@ -920,7 +1077,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
+ */
+ if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {
+ fbi->state = state;
+- //TODO __pxafb_lcd_power(fbi, 0);
++ /* TODO __pxafb_lcd_power(fbi, 0); */
+ pxafb_disable_controller(fbi);
+ }
+ break;
+@@ -947,7 +1104,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
+ if (old_state == C_DISABLE_CLKCHANGE) {
+ fbi->state = C_ENABLE;
+ pxafb_enable_controller(fbi);
+- //TODO __pxafb_lcd_power(fbi, 1);
++ /* TODO __pxafb_lcd_power(fbi, 1); */
+ }
+ break;
+
+@@ -1018,7 +1175,7 @@ static int
+ pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
+ {
+ struct pxafb_info *fbi = TO_INF(nb, freq_transition);
+- //TODO struct cpufreq_freqs *f = data;
++ /* TODO struct cpufreq_freqs *f = data; */
+ u_int pcd;
+
+ switch (val) {
+@@ -1029,7 +1186,8 @@ pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
+ case CPUFREQ_POSTCHANGE:
+ pcd = get_pcd(fbi, fbi->fb.var.pixclock);
+ set_hsync_time(fbi, pcd);
+- fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
++ fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) |
++ LCCR3_PixClkDiv(pcd);
+ set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
+ break;
+ }
+@@ -1049,18 +1207,8 @@ pxafb_freq_policy(struct notifier_block *nb, unsigned long val, void *data)
+ pr_debug("min dma period: %d ps, "
+ "new clock %d kHz\n", pxafb_display_dma_period(var),
+ policy->max);
+- // TODO: fill in min/max values
+- break;
+-#if 0
+- case CPUFREQ_NOTIFY:
+- printk(KERN_ERR "%s: got CPUFREQ_NOTIFY\n", __FUNCTION__);
+- do {} while(0);
+- /* todo: panic if min/max values aren't fulfilled
+- * [can't really happen unless there's a bug in the
+- * CPU policy verification process *
+- */
++ /* TODO: fill in min/max values */
+ break;
+-#endif
+ }
+ return 0;
+ }
+@@ -1101,21 +1249,21 @@ static int pxafb_resume(struct platform_device *dev)
*/
-@@ -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 int __init pxafb_map_video_memory(struct pxafb_info *fbi)
+ {
+- u_long palette_mem_size;
+-
+ /*
+ * We reserve one page for the palette, plus the size
+ * of the framebuffer.
+ */
+- fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
++ fbi->video_offset = PAGE_ALIGN(sizeof(struct pxafb_dma_buff));
++ fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + fbi->video_offset);
+ fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
+ &fbi->map_dma, GFP_KERNEL);
--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);
+ if (fbi->map_cpu) {
+ /* prevent initial garbage on screen */
+ memset(fbi->map_cpu, 0, fbi->map_size);
+- fbi->fb.screen_base = fbi->map_cpu + PAGE_SIZE;
+- fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
++ fbi->fb.screen_base = fbi->map_cpu + fbi->video_offset;
++ fbi->screen_dma = fbi->map_dma + fbi->video_offset;
++
+ /*
+ * FIXME: this is actually the wrong thing to place in
+ * smem_start. But fbdev suffers from the problem that
+@@ -1125,27 +1273,86 @@ static int __init pxafb_map_video_memory(struct pxafb_info *fbi)
+ fbi->fb.fix.smem_start = fbi->screen_dma;
+ fbi->palette_size = fbi->fb.var.bits_per_pixel == 8 ? 256 : 16;
-@@ -178,10 +179,7 @@ static int usu_probe_thread(void *arg)
- int rc;
- unsigned long flags;
+- if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
+- palette_mem_size = fbi->palette_size * sizeof(u16);
+- else
+- palette_mem_size = fbi->palette_size * sizeof(u32);
++ fbi->dma_buff = (void *) fbi->map_cpu;
++ fbi->dma_buff_phys = fbi->map_dma;
++ fbi->palette_cpu = (u16 *) fbi->dma_buff->palette;
-- /* A completion does not work here because it's counted. */
-- down(&usu_init_notify);
-- up(&usu_init_notify);
+- pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size);
-
-+ 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)
+- fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
+- fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
++#ifdef CONFIG_FB_PXA_SMARTPANEL
++ fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff;
++ fbi->n_smart_cmds = 0;
++#endif
}
- st->fls &= ~USU_MOD_FL_THREAD;
- spin_unlock_irqrestore(&usu_lock, flags);
-+ mutex_unlock(&usu_probe_mutex);
- complete_and_exit(&usu_end_notify, 0);
+ return fbi->map_cpu ? 0 : -ENOMEM;
}
-@@ -204,10 +203,9 @@ static int __init usb_usual_init(void)
+
++static void pxafb_decode_mode_info(struct pxafb_info *fbi,
++ struct pxafb_mode_info *modes,
++ unsigned int num_modes)
++{
++ unsigned int i, smemlen;
++
++ pxafb_setmode(&fbi->fb.var, &modes[0]);
++
++ for (i = 0; i < num_modes; i++) {
++ smemlen = modes[i].xres * modes[i].yres * modes[i].bpp / 8;
++ if (smemlen > fbi->fb.fix.smem_len)
++ fbi->fb.fix.smem_len = smemlen;
++ }
++}
++
++static int pxafb_decode_mach_info(struct pxafb_info *fbi,
++ struct pxafb_mach_info *inf)
++{
++ unsigned int lcd_conn = inf->lcd_conn;
++
++ fbi->cmap_inverse = inf->cmap_inverse;
++ fbi->cmap_static = inf->cmap_static;
++
++ switch (lcd_conn & 0xf) {
++ case LCD_TYPE_MONO_STN:
++ fbi->lccr0 = LCCR0_CMS;
++ break;
++ case LCD_TYPE_MONO_DSTN:
++ fbi->lccr0 = LCCR0_CMS | LCCR0_SDS;
++ break;
++ case LCD_TYPE_COLOR_STN:
++ fbi->lccr0 = 0;
++ break;
++ case LCD_TYPE_COLOR_DSTN:
++ fbi->lccr0 = LCCR0_SDS;
++ break;
++ case LCD_TYPE_COLOR_TFT:
++ fbi->lccr0 = LCCR0_PAS;
++ break;
++ case LCD_TYPE_SMART_PANEL:
++ fbi->lccr0 = LCCR0_LCDT | LCCR0_PAS;
++ break;
++ default:
++ /* fall back to backward compatibility way */
++ fbi->lccr0 = inf->lccr0;
++ fbi->lccr3 = inf->lccr3;
++ fbi->lccr4 = inf->lccr4;
++ return -EINVAL;
++ }
++
++ if (lcd_conn == LCD_MONO_STN_8BPP)
++ fbi->lccr0 |= LCCR0_DPD;
++
++ fbi->lccr3 = LCCR3_Acb((inf->lcd_conn >> 10) & 0xff);
++ fbi->lccr3 |= (lcd_conn & LCD_BIAS_ACTIVE_LOW) ? LCCR3_OEP : 0;
++ fbi->lccr3 |= (lcd_conn & LCD_PCLK_EDGE_FALL) ? LCCR3_PCP : 0;
++
++ pxafb_decode_mode_info(fbi, inf->modes, inf->num_modes);
++ return 0;
++}
++
+ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
{
- int rc;
+ struct pxafb_info *fbi;
+ void *addr;
+ struct pxafb_mach_info *inf = dev->platform_data;
+ struct pxafb_mode_info *mode = inf->modes;
+- int i, smemlen;
+
+ /* Alloc the pxafb_info and pseudo_palette in one step */
+ fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL);
+@@ -1185,187 +1392,233 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
+ addr = addr + sizeof(struct pxafb_info);
+ fbi->fb.pseudo_palette = addr;
+
+- pxafb_setmode(&fbi->fb.var, mode);
++ fbi->state = C_STARTUP;
++ fbi->task_state = (u_char)-1;
+
+- fbi->cmap_inverse = inf->cmap_inverse;
+- fbi->cmap_static = inf->cmap_static;
+-
+- fbi->lccr0 = inf->lccr0;
+- fbi->lccr3 = inf->lccr3;
+- fbi->lccr4 = inf->lccr4;
+- fbi->state = C_STARTUP;
+- fbi->task_state = (u_char)-1;
+-
+- for (i = 0; i < inf->num_modes; i++) {
+- smemlen = mode[i].xres * mode[i].yres * mode[i].bpp / 8;
+- if (smemlen > fbi->fb.fix.smem_len)
+- fbi->fb.fix.smem_len = smemlen;
+- }
++ pxafb_decode_mach_info(fbi, inf);
+
+ init_waitqueue_head(&fbi->ctrlr_wait);
+ INIT_WORK(&fbi->task, pxafb_task);
+ init_MUTEX(&fbi->ctrlr_sem);
++ init_completion(&fbi->disable_done);
++#ifdef CONFIG_FB_PXA_SMARTPANEL
++ init_completion(&fbi->command_done);
++ init_completion(&fbi->refresh_done);
++#endif
+
+ return fbi;
+ }
+
+ #ifdef CONFIG_FB_PXA_PARAMETERS
+-static int __init pxafb_parse_options(struct device *dev, char *options)
++static int __init parse_opt_mode(struct device *dev, const char *this_opt)
++{
++ struct pxafb_mach_info *inf = dev->platform_data;
++
++ const char *name = this_opt+5;
++ unsigned int namelen = strlen(name);
++ int res_specified = 0, bpp_specified = 0;
++ unsigned int xres = 0, yres = 0, bpp = 0;
++ int yres_specified = 0;
++ int i;
++ for (i = namelen-1; i >= 0; i--) {
++ switch (name[i]) {
++ case '-':
++ namelen = i;
++ if (!bpp_specified && !yres_specified) {
++ bpp = simple_strtoul(&name[i+1], NULL, 0);
++ bpp_specified = 1;
++ } else
++ goto done;
++ break;
++ case 'x':
++ if (!yres_specified) {
++ yres = simple_strtoul(&name[i+1], NULL, 0);
++ yres_specified = 1;
++ } else
++ goto done;
++ break;
++ case '0' ... '9':
++ break;
++ default:
++ goto done;
++ }
++ }
++ if (i < 0 && yres_specified) {
++ xres = simple_strtoul(name, NULL, 0);
++ res_specified = 1;
++ }
++done:
++ if (res_specified) {
++ dev_info(dev, "overriding resolution: %dx%d\n", xres, yres);
++ inf->modes[0].xres = xres; inf->modes[0].yres = yres;
++ }
++ if (bpp_specified)
++ switch (bpp) {
++ case 1:
++ case 2:
++ case 4:
++ case 8:
++ case 16:
++ inf->modes[0].bpp = bpp;
++ dev_info(dev, "overriding bit depth: %d\n", bpp);
++ break;
++ default:
++ dev_err(dev, "Depth %d is not valid\n", bpp);
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int __init parse_opt(struct device *dev, char *this_opt)
+ {
+ struct pxafb_mach_info *inf = dev->platform_data;
++ struct pxafb_mode_info *mode = &inf->modes[0];
++ char s[64];
++
++ s[0] = '\0';
++
++ if (!strncmp(this_opt, "mode:", 5)) {
++ return parse_opt_mode(dev, this_opt);
++ } else if (!strncmp(this_opt, "pixclock:", 9)) {
++ mode->pixclock = simple_strtoul(this_opt+9, NULL, 0);
++ sprintf(s, "pixclock: %ld\n", mode->pixclock);
++ } else if (!strncmp(this_opt, "left:", 5)) {
++ mode->left_margin = simple_strtoul(this_opt+5, NULL, 0);
++ sprintf(s, "left: %u\n", mode->left_margin);
++ } else if (!strncmp(this_opt, "right:", 6)) {
++ mode->right_margin = simple_strtoul(this_opt+6, NULL, 0);
++ sprintf(s, "right: %u\n", mode->right_margin);
++ } else if (!strncmp(this_opt, "upper:", 6)) {
++ mode->upper_margin = simple_strtoul(this_opt+6, NULL, 0);
++ sprintf(s, "upper: %u\n", mode->upper_margin);
++ } else if (!strncmp(this_opt, "lower:", 6)) {
++ mode->lower_margin = simple_strtoul(this_opt+6, NULL, 0);
++ sprintf(s, "lower: %u\n", mode->lower_margin);
++ } else if (!strncmp(this_opt, "hsynclen:", 9)) {
++ mode->hsync_len = simple_strtoul(this_opt+9, NULL, 0);
++ sprintf(s, "hsynclen: %u\n", mode->hsync_len);
++ } else if (!strncmp(this_opt, "vsynclen:", 9)) {
++ mode->vsync_len = simple_strtoul(this_opt+9, NULL, 0);
++ sprintf(s, "vsynclen: %u\n", mode->vsync_len);
++ } else if (!strncmp(this_opt, "hsync:", 6)) {
++ if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
++ sprintf(s, "hsync: Active Low\n");
++ mode->sync &= ~FB_SYNC_HOR_HIGH_ACT;
++ } else {
++ sprintf(s, "hsync: Active High\n");
++ mode->sync |= FB_SYNC_HOR_HIGH_ACT;
++ }
++ } else if (!strncmp(this_opt, "vsync:", 6)) {
++ if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
++ sprintf(s, "vsync: Active Low\n");
++ mode->sync &= ~FB_SYNC_VERT_HIGH_ACT;
++ } else {
++ sprintf(s, "vsync: Active High\n");
++ mode->sync |= FB_SYNC_VERT_HIGH_ACT;
++ }
++ } else if (!strncmp(this_opt, "dpc:", 4)) {
++ if (simple_strtoul(this_opt+4, NULL, 0) == 0) {
++ sprintf(s, "double pixel clock: false\n");
++ inf->lccr3 &= ~LCCR3_DPC;
++ } else {
++ sprintf(s, "double pixel clock: true\n");
++ inf->lccr3 |= LCCR3_DPC;
++ }
++ } else if (!strncmp(this_opt, "outputen:", 9)) {
++ if (simple_strtoul(this_opt+9, NULL, 0) == 0) {
++ sprintf(s, "output enable: active low\n");
++ inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnL;
++ } else {
++ sprintf(s, "output enable: active high\n");
++ inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnH;
++ }
++ } else if (!strncmp(this_opt, "pixclockpol:", 12)) {
++ if (simple_strtoul(this_opt+12, NULL, 0) == 0) {
++ sprintf(s, "pixel clock polarity: falling edge\n");
++ inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixFlEdg;
++ } else {
++ sprintf(s, "pixel clock polarity: rising edge\n");
++ inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixRsEdg;
++ }
++ } else if (!strncmp(this_opt, "color", 5)) {
++ inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Color;
++ } else if (!strncmp(this_opt, "mono", 4)) {
++ inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Mono;
++ } else if (!strncmp(this_opt, "active", 6)) {
++ inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Act;
++ } else if (!strncmp(this_opt, "passive", 7)) {
++ inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Pas;
++ } else if (!strncmp(this_opt, "single", 6)) {
++ inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Sngl;
++ } else if (!strncmp(this_opt, "dual", 4)) {
++ inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Dual;
++ } else if (!strncmp(this_opt, "4pix", 4)) {
++ inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_4PixMono;
++ } else if (!strncmp(this_opt, "8pix", 4)) {
++ inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_8PixMono;
++ } else {
++ dev_err(dev, "unknown option: %s\n", this_opt);
++ return -EINVAL;
++ }
++
++ if (s[0] != '\0')
++ dev_info(dev, "override %s", s);
++
++ return 0;
++}
++
++static int __init pxafb_parse_options(struct device *dev, char *options)
++{
+ char *this_opt;
++ int ret;
-- 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;
+- if (!options || !*options)
+- return 0;
++ if (!options || !*options)
++ return 0;
+
+ dev_dbg(dev, "options are \"%s\"\n", options ? options : "null");
+
+ /* could be made table driven or similar?... */
+- while ((this_opt = strsep(&options, ",")) != NULL) {
+- if (!strncmp(this_opt, "mode:", 5)) {
+- const char *name = this_opt+5;
+- unsigned int namelen = strlen(name);
+- int res_specified = 0, bpp_specified = 0;
+- unsigned int xres = 0, yres = 0, bpp = 0;
+- int yres_specified = 0;
+- int i;
+- for (i = namelen-1; i >= 0; i--) {
+- switch (name[i]) {
+- case '-':
+- namelen = i;
+- if (!bpp_specified && !yres_specified) {
+- bpp = simple_strtoul(&name[i+1], NULL, 0);
+- bpp_specified = 1;
+- } else
+- goto done;
+- break;
+- case 'x':
+- if (!yres_specified) {
+- yres = simple_strtoul(&name[i+1], NULL, 0);
+- yres_specified = 1;
+- } else
+- goto done;
+- break;
+- case '0' ... '9':
+- break;
+- default:
+- goto done;
+- }
+- }
+- if (i < 0 && yres_specified) {
+- xres = simple_strtoul(name, NULL, 0);
+- res_specified = 1;
+- }
+- done:
+- if (res_specified) {
+- dev_info(dev, "overriding resolution: %dx%d\n", xres, yres);
+- inf->modes[0].xres = xres; inf->modes[0].yres = yres;
+- }
+- if (bpp_specified)
+- switch (bpp) {
+- case 1:
+- case 2:
+- case 4:
+- case 8:
+- case 16:
+- inf->modes[0].bpp = bpp;
+- dev_info(dev, "overriding bit depth: %d\n", bpp);
+- break;
+- default:
+- dev_err(dev, "Depth %d is not valid\n", bpp);
+- }
+- } else if (!strncmp(this_opt, "pixclock:", 9)) {
+- inf->modes[0].pixclock = simple_strtoul(this_opt+9, NULL, 0);
+- dev_info(dev, "override pixclock: %ld\n", inf->modes[0].pixclock);
+- } else if (!strncmp(this_opt, "left:", 5)) {
+- inf->modes[0].left_margin = simple_strtoul(this_opt+5, NULL, 0);
+- dev_info(dev, "override left: %u\n", inf->modes[0].left_margin);
+- } else if (!strncmp(this_opt, "right:", 6)) {
+- inf->modes[0].right_margin = simple_strtoul(this_opt+6, NULL, 0);
+- dev_info(dev, "override right: %u\n", inf->modes[0].right_margin);
+- } else if (!strncmp(this_opt, "upper:", 6)) {
+- inf->modes[0].upper_margin = simple_strtoul(this_opt+6, NULL, 0);
+- dev_info(dev, "override upper: %u\n", inf->modes[0].upper_margin);
+- } else if (!strncmp(this_opt, "lower:", 6)) {
+- inf->modes[0].lower_margin = simple_strtoul(this_opt+6, NULL, 0);
+- dev_info(dev, "override lower: %u\n", inf->modes[0].lower_margin);
+- } else if (!strncmp(this_opt, "hsynclen:", 9)) {
+- inf->modes[0].hsync_len = simple_strtoul(this_opt+9, NULL, 0);
+- dev_info(dev, "override hsynclen: %u\n", inf->modes[0].hsync_len);
+- } else if (!strncmp(this_opt, "vsynclen:", 9)) {
+- inf->modes[0].vsync_len = simple_strtoul(this_opt+9, NULL, 0);
+- dev_info(dev, "override vsynclen: %u\n", inf->modes[0].vsync_len);
+- } else if (!strncmp(this_opt, "hsync:", 6)) {
+- if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
+- dev_info(dev, "override hsync: Active Low\n");
+- inf->modes[0].sync &= ~FB_SYNC_HOR_HIGH_ACT;
+- } else {
+- dev_info(dev, "override hsync: Active High\n");
+- inf->modes[0].sync |= FB_SYNC_HOR_HIGH_ACT;
+- }
+- } else if (!strncmp(this_opt, "vsync:", 6)) {
+- if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
+- dev_info(dev, "override vsync: Active Low\n");
+- inf->modes[0].sync &= ~FB_SYNC_VERT_HIGH_ACT;
+- } else {
+- dev_info(dev, "override vsync: Active High\n");
+- inf->modes[0].sync |= FB_SYNC_VERT_HIGH_ACT;
+- }
+- } else if (!strncmp(this_opt, "dpc:", 4)) {
+- if (simple_strtoul(this_opt+4, NULL, 0) == 0) {
+- dev_info(dev, "override double pixel clock: false\n");
+- inf->lccr3 &= ~LCCR3_DPC;
+- } else {
+- dev_info(dev, "override double pixel clock: true\n");
+- inf->lccr3 |= LCCR3_DPC;
+- }
+- } else if (!strncmp(this_opt, "outputen:", 9)) {
+- if (simple_strtoul(this_opt+9, NULL, 0) == 0) {
+- dev_info(dev, "override output enable: active low\n");
+- inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnL;
+- } else {
+- dev_info(dev, "override output enable: active high\n");
+- inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnH;
+- }
+- } else if (!strncmp(this_opt, "pixclockpol:", 12)) {
+- if (simple_strtoul(this_opt+12, NULL, 0) == 0) {
+- dev_info(dev, "override pixel clock polarity: falling edge\n");
+- inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixFlEdg;
+- } else {
+- dev_info(dev, "override pixel clock polarity: rising edge\n");
+- inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixRsEdg;
+- }
+- } else if (!strncmp(this_opt, "color", 5)) {
+- inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Color;
+- } else if (!strncmp(this_opt, "mono", 4)) {
+- inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Mono;
+- } else if (!strncmp(this_opt, "active", 6)) {
+- inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Act;
+- } else if (!strncmp(this_opt, "passive", 7)) {
+- inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Pas;
+- } else if (!strncmp(this_opt, "single", 6)) {
+- inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Sngl;
+- } else if (!strncmp(this_opt, "dual", 4)) {
+- inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Dual;
+- } else if (!strncmp(this_opt, "4pix", 4)) {
+- inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_4PixMono;
+- } else if (!strncmp(this_opt, "8pix", 4)) {
+- inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_8PixMono;
+- } else {
+- dev_err(dev, "unknown option: %s\n", this_opt);
+- return -EINVAL;
+- }
+- }
+- return 0;
++ while ((this_opt = strsep(&options, ",")) != NULL) {
++ ret = parse_opt(dev, this_opt);
++ if (ret)
++ return ret;
++ }
++ return 0;
++}
++
++static char g_options[256] __devinitdata = "";
+
++#ifndef CONFIG_MODULES
++static int __devinit pxafb_setup_options(void)
++{
++ char *options = NULL;
++
++ if (fb_get_options("pxafb", &options))
++ return -ENODEV;
++
++ if (options)
++ strlcpy(g_options, options, sizeof(g_options));
++
++ return 0;
}
++#else
++#define pxafb_setup_options() (0)
++
++module_param_string(options, g_options, sizeof(g_options), 0);
++MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
++#endif
++
++#else
++#define pxafb_parse_options(...) (0)
++#define pxafb_setup_options() (0)
+ #endif
-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)
+ static int __init pxafb_probe(struct platform_device *dev)
{
- struct us_data *us = host_to_us(sdev->host);
-+ struct usb_host_endpoint *bulk_in_ep;
+ struct pxafb_info *fbi;
+ struct pxafb_mach_info *inf;
+- int ret;
++ struct resource *r;
++ int irq, ret;
- /*
- * 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 */
+ dev_dbg(&dev->dev, "pxafb_probe\n");
- /*
- * 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;
+@@ -1375,38 +1628,45 @@ static int __init pxafb_probe(struct platform_device *dev)
+ if (!inf)
+ goto failed;
- /* 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);
+-#ifdef CONFIG_FB_PXA_PARAMETERS
+ ret = pxafb_parse_options(&dev->dev, g_options);
+ if (ret < 0)
+ goto failed;
+-#endif
-- US_DEBUGP("%s called\n", __FUNCTION__);
-+ US_DEBUGP("%s called\n", __func__);
+ #ifdef DEBUG_VAR
+- /* Check for various illegal bit-combinations. Currently only
++ /* Check for various illegal bit-combinations. Currently only
+ * a warning is given. */
+
+- if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK)
+- dev_warn(&dev->dev, "machine LCCR0 setting contains illegal bits: %08x\n",
+- inf->lccr0 & LCCR0_INVALID_CONFIG_MASK);
+- if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK)
+- dev_warn(&dev->dev, "machine LCCR3 setting contains illegal bits: %08x\n",
+- inf->lccr3 & LCCR3_INVALID_CONFIG_MASK);
+- if (inf->lccr0 & LCCR0_DPD &&
++ if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK)
++ dev_warn(&dev->dev, "machine LCCR0 setting contains "
++ "illegal bits: %08x\n",
++ inf->lccr0 & LCCR0_INVALID_CONFIG_MASK);
++ if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK)
++ dev_warn(&dev->dev, "machine LCCR3 setting contains "
++ "illegal bits: %08x\n",
++ inf->lccr3 & LCCR3_INVALID_CONFIG_MASK);
++ if (inf->lccr0 & LCCR0_DPD &&
+ ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas ||
+ (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl ||
+ (inf->lccr0 & LCCR0_CMS) != LCCR0_Mono))
+- dev_warn(&dev->dev, "Double Pixel Data (DPD) mode is only valid in passive mono"
+- " single panel mode\n");
+- if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act &&
++ dev_warn(&dev->dev, "Double Pixel Data (DPD) mode is "
++ "only valid in passive mono"
++ " single panel mode\n");
++ if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act &&
+ (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual)
+- dev_warn(&dev->dev, "Dual panel only valid in passive mode\n");
+- if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas &&
+- (inf->modes->upper_margin || inf->modes->lower_margin))
+- dev_warn(&dev->dev, "Upper and lower margins must be 0 in passive mode\n");
++ dev_warn(&dev->dev, "Dual panel only valid in passive mode\n");
++ if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas &&
++ (inf->modes->upper_margin || inf->modes->lower_margin))
++ dev_warn(&dev->dev, "Upper and lower margins must be 0 in "
++ "passive mode\n");
+ #endif
+
+- dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n",inf->modes->xres, inf->modes->yres, inf->modes->bpp);
+- if (inf->modes->xres == 0 || inf->modes->yres == 0 || inf->modes->bpp == 0) {
++ dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n",
++ inf->modes->xres,
++ inf->modes->yres,
++ inf->modes->bpp);
++ if (inf->modes->xres == 0 ||
++ inf->modes->yres == 0 ||
++ inf->modes->bpp == 0) {
+ dev_err(&dev->dev, "Invalid resolution or bit depth\n");
+ ret = -EINVAL;
+ goto failed;
+@@ -1415,26 +1675,62 @@ static int __init pxafb_probe(struct platform_device *dev)
+ pxafb_lcd_power = inf->pxafb_lcd_power;
+ fbi = pxafb_init_fbinfo(&dev->dev);
+ if (!fbi) {
++ /* only reason for pxafb_init_fbinfo to fail is kmalloc */
+ dev_err(&dev->dev, "Failed to initialize framebuffer device\n");
+- ret = -ENOMEM; // only reason for pxafb_init_fbinfo to fail is kmalloc
++ ret = -ENOMEM;
+ goto failed;
+ }
- /* 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;
++ r = platform_get_resource(dev, IORESOURCE_MEM, 0);
++ if (r == NULL) {
++ dev_err(&dev->dev, "no I/O memory resource defined\n");
++ ret = -ENODEV;
++ goto failed;
++ }
++
++ r = request_mem_region(r->start, r->end - r->start + 1, dev->name);
++ if (r == NULL) {
++ dev_err(&dev->dev, "failed to request I/O memory\n");
++ ret = -EBUSY;
++ goto failed;
++ }
++
++ fbi->mmio_base = ioremap(r->start, r->end - r->start + 1);
++ if (fbi->mmio_base == NULL) {
++ dev_err(&dev->dev, "failed to map I/O memory\n");
++ ret = -EBUSY;
++ goto failed_free_res;
++ }
++
+ /* Initialize video memory */
+ ret = pxafb_map_video_memory(fbi);
+ if (ret) {
+ dev_err(&dev->dev, "Failed to allocate video RAM: %d\n", ret);
+ ret = -ENOMEM;
+- goto failed;
++ goto failed_free_io;
++ }
++
++ irq = platform_get_irq(dev, 0);
++ if (irq < 0) {
++ dev_err(&dev->dev, "no IRQ defined\n");
++ ret = -ENODEV;
++ goto failed_free_mem;
}
-@@ -260,7 +262,7 @@ static int command_abort(struct scsi_cmnd *srb)
- {
- struct us_data *us = host_to_us(srb->device->host);
+- ret = request_irq(IRQ_LCD, pxafb_handle_irq, IRQF_DISABLED, "LCD", fbi);
++ ret = request_irq(irq, pxafb_handle_irq, IRQF_DISABLED, "LCD", fbi);
+ if (ret) {
+ dev_err(&dev->dev, "request_irq failed: %d\n", ret);
+ ret = -EBUSY;
+- goto failed;
++ goto failed_free_mem;
+ }
-- US_DEBUGP("%s called\n", __FUNCTION__);
-+ US_DEBUGP("%s called\n", __func__);
++#ifdef CONFIG_FB_PXA_SMARTPANEL
++ ret = pxafb_smart_init(fbi);
++ if (ret) {
++ dev_err(&dev->dev, "failed to initialize smartpanel\n");
++ goto failed_free_irq;
++ }
++#endif
+ /*
+ * This makes sure that our colour bitfield
+ * descriptors are correctly initialised.
+@@ -1446,19 +1742,18 @@ static int __init pxafb_probe(struct platform_device *dev)
- /* 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;
+ ret = register_framebuffer(&fbi->fb);
+ if (ret < 0) {
+- dev_err(&dev->dev, "Failed to register framebuffer device: %d\n", ret);
+- goto failed;
++ dev_err(&dev->dev,
++ "Failed to register framebuffer device: %d\n", ret);
++ goto failed_free_irq;
+ }
-- US_DEBUGP("%s called\n", __FUNCTION__);
-+ US_DEBUGP("%s called\n", __func__);
+-#ifdef CONFIG_PM
+- // TODO
+-#endif
+-
+ #ifdef CONFIG_CPU_FREQ
+ fbi->freq_transition.notifier_call = pxafb_freq_transition;
+ fbi->freq_policy.notifier_call = pxafb_freq_policy;
+- cpufreq_register_notifier(&fbi->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);
+- cpufreq_register_notifier(&fbi->freq_policy, CPUFREQ_POLICY_NOTIFIER);
++ cpufreq_register_notifier(&fbi->freq_transition,
++ CPUFREQ_TRANSITION_NOTIFIER);
++ cpufreq_register_notifier(&fbi->freq_policy,
++ CPUFREQ_POLICY_NOTIFIER);
+ #endif
- /* 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;
+ /*
+@@ -1468,6 +1763,15 @@ static int __init pxafb_probe(struct platform_device *dev)
-- 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)
+ return 0;
+
++failed_free_irq:
++ free_irq(irq, fbi);
++failed_free_res:
++ release_mem_region(r->start, r->end - r->start + 1);
++failed_free_io:
++ iounmap(fbi->mmio_base);
++failed_free_mem:
++ dma_free_writecombine(&dev->dev, fbi->map_size,
++ fbi->map_cpu, fbi->map_dma);
+ failed:
+ platform_set_drvdata(dev, NULL);
+ kfree(fbi);
+@@ -1476,40 +1780,18 @@ failed:
+
+ static struct platform_driver pxafb_driver = {
+ .probe = pxafb_probe,
+-#ifdef CONFIG_PM
+ .suspend = pxafb_suspend,
+ .resume = pxafb_resume,
+-#endif
+ .driver = {
+ .name = "pxa2xx-fb",
+ },
+ };
+
+-#ifndef MODULE
+-static int __devinit pxafb_setup(char *options)
+-{
+-# ifdef CONFIG_FB_PXA_PARAMETERS
+- if (options)
+- strlcpy(g_options, options, sizeof(g_options));
+-# endif
+- return 0;
+-}
+-#else
+-# ifdef CONFIG_FB_PXA_PARAMETERS
+-module_param_string(options, g_options, sizeof(g_options), 0);
+-MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
+-# endif
+-#endif
+-
+ static int __devinit pxafb_init(void)
{
-- struct completion *urb_done_ptr = (struct completion *)urb->context;
-+ struct completion *urb_done_ptr = urb->context;
+-#ifndef MODULE
+- char *option = NULL;
++ if (pxafb_setup_options())
++ return -EINVAL;
- complete(urb_done_ptr);
+- if (fb_get_options("pxafb", &option))
+- return -ENODEV;
+- pxafb_setup(option);
+-#endif
+ return platform_driver_register(&pxafb_driver);
}
-@@ -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);
+diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h
+index d920b8a..8238dc8 100644
+--- a/drivers/video/pxafb.h
++++ b/drivers/video/pxafb.h
+@@ -21,14 +21,6 @@
+ * for more details.
+ */
- /* 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);
+-/* Shadows for LCD controller registers */
+-struct pxafb_lcd_reg {
+- unsigned int lccr0;
+- unsigned int lccr1;
+- unsigned int lccr2;
+- unsigned int lccr3;
+-};
+-
+ /* PXA LCD DMA descriptor */
+ struct pxafb_dma_descriptor {
+ unsigned int fdadr;
+@@ -37,11 +29,49 @@ struct pxafb_dma_descriptor {
+ unsigned int ldcmd;
+ };
-- US_DEBUGP("%s: result = %d\n", __FUNCTION__, result);
-+ US_DEBUGP("%s: result = %d\n", __func__, result);
- return result;
++enum {
++ PAL_NONE = -1,
++ PAL_BASE = 0,
++ PAL_OV1 = 1,
++ PAL_OV2 = 2,
++ PAL_MAX,
++};
++
++enum {
++ DMA_BASE = 0,
++ DMA_UPPER = 0,
++ DMA_LOWER = 1,
++ DMA_OV1 = 1,
++ DMA_OV2_Y = 2,
++ DMA_OV2_Cb = 3,
++ DMA_OV2_Cr = 4,
++ DMA_CURSOR = 5,
++ DMA_CMD = 6,
++ DMA_MAX,
++};
++
++/* maximum palette size - 256 entries, each 4 bytes long */
++#define PALETTE_SIZE (256 * 4)
++#define CMD_BUFF_SIZE (1024 * 50)
++
++struct pxafb_dma_buff {
++ unsigned char palette[PAL_MAX * PALETTE_SIZE];
++ uint16_t cmd_buff[CMD_BUFF_SIZE];
++ struct pxafb_dma_descriptor pal_desc[PAL_MAX];
++ struct pxafb_dma_descriptor dma_desc[DMA_MAX];
++};
++
+ struct pxafb_info {
+ struct fb_info fb;
+ struct device *dev;
+ struct clk *clk;
+
++ void __iomem *mmio_base;
++
++ struct pxafb_dma_buff *dma_buff;
++ dma_addr_t dma_buff_phys;
++ dma_addr_t fdadr[DMA_MAX];
++
+ /*
+ * These are the addresses we mapped
+ * the framebuffer memory region to.
+@@ -55,19 +85,8 @@ struct pxafb_info {
+ u_char * screen_cpu; /* virtual address of frame buffer */
+ dma_addr_t screen_dma; /* physical address of frame buffer */
+ u16 * palette_cpu; /* virtual address of palette memory */
+- dma_addr_t palette_dma; /* physical address of palette memory */
+ u_int palette_size;
+-
+- /* DMA descriptors */
+- struct pxafb_dma_descriptor * dmadesc_fblow_cpu;
+- dma_addr_t dmadesc_fblow_dma;
+- struct pxafb_dma_descriptor * dmadesc_fbhigh_cpu;
+- dma_addr_t dmadesc_fbhigh_dma;
+- struct pxafb_dma_descriptor * dmadesc_palette_cpu;
+- dma_addr_t dmadesc_palette_dma;
+-
+- dma_addr_t fdadr0;
+- dma_addr_t fdadr1;
++ ssize_t video_offset;
+
+ u_int lccr0;
+ u_int lccr3;
+@@ -81,6 +100,7 @@ struct pxafb_info {
+ u_int reg_lccr2;
+ u_int reg_lccr3;
+ u_int reg_lccr4;
++ u_int reg_cmdcr;
+
+ unsigned long hsync_time;
+
+@@ -90,6 +110,16 @@ struct pxafb_info {
+ wait_queue_head_t ctrlr_wait;
+ struct work_struct task;
+
++ struct completion disable_done;
++
++#ifdef CONFIG_FB_PXA_SMARTPANEL
++ uint16_t *smart_cmds;
++ size_t n_smart_cmds;
++ struct completion command_done;
++ struct completion refresh_done;
++ struct task_struct *smart_thread;
++#endif
++
+ #ifdef CONFIG_CPU_FREQ
+ struct notifier_block freq_transition;
+ struct notifier_block freq_policy;
+diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
+index 5c47968..d94c57f 100644
+--- a/drivers/video/riva/fbdev.c
++++ b/drivers/video/riva/fbdev.c
+@@ -56,10 +56,6 @@
+ #include "rivafb.h"
+ #include "nvreg.h"
+
+-#ifndef CONFIG_PCI /* sanity check */
+-#error This driver requires PCI support.
+-#endif
+-
+ /* version number of this driver */
+ #define RIVAFB_VERSION "0.9.5b"
+
+@@ -74,14 +70,14 @@
+ #define NVTRACE if(0) printk
+ #endif
+
+-#define NVTRACE_ENTER(...) NVTRACE("%s START\n", __FUNCTION__)
+-#define NVTRACE_LEAVE(...) NVTRACE("%s END\n", __FUNCTION__)
++#define NVTRACE_ENTER(...) NVTRACE("%s START\n", __func__)
++#define NVTRACE_LEAVE(...) NVTRACE("%s END\n", __func__)
+
+ #ifdef CONFIG_FB_RIVA_DEBUG
+ #define assert(expr) \
+ if(!(expr)) { \
+ printk( "Assertion failed! %s,%s,%s,line=%d\n",\
+- #expr,__FILE__,__FUNCTION__,__LINE__); \
++ #expr,__FILE__,__func__,__LINE__); \
+ BUG(); \
+ }
+ #else
+@@ -2213,14 +2209,12 @@ static int __devinit rivafb_init(void)
+
+ module_init(rivafb_init);
+
+-#ifdef MODULE
+ static void __exit rivafb_exit(void)
+ {
+ pci_unregister_driver(&rivafb_driver);
}
-@@ -332,7 +332,7 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
- int result;
+ module_exit(rivafb_exit);
+-#endif /* MODULE */
- US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
-- __FUNCTION__, request, requesttype,
-+ __func__, request, requesttype,
- value, index, size);
+ module_param(noaccel, bool, 0);
+ MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
+diff --git a/drivers/video/riva/nv_driver.c b/drivers/video/riva/nv_driver.c
+index a110268..f3694cf 100644
+--- a/drivers/video/riva/nv_driver.c
++++ b/drivers/video/riva/nv_driver.c
+@@ -41,11 +41,6 @@
+ #include "rivafb.h"
+ #include "nvreg.h"
- /* 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;
+-
+-#ifndef CONFIG_PCI /* sanity check */
+-#error This driver requires PCI support.
+-#endif
+-
+ #define PFX "rivafb: "
-- US_DEBUGP("%s: xfer %u bytes\n", __FUNCTION__, length);
-+ US_DEBUGP("%s: xfer %u bytes\n", __func__, length);
+ static inline unsigned char MISCin(struct riva_par *par)
+@@ -163,7 +158,7 @@ unsigned long riva_get_memlen(struct riva_par *par)
+ unsigned long memlen = 0;
+ unsigned int chipset = par->Chipset;
+ struct pci_dev* dev;
+- int amt;
++ u32 amt;
- /* 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,
+ switch (chip->Architecture) {
+ case NV_ARCH_03:
+diff --git a/drivers/video/riva/riva_hw.c b/drivers/video/riva/riva_hw.c
+index 1330770..78fdbf5 100644
+--- a/drivers/video/riva/riva_hw.c
++++ b/drivers/video/riva/riva_hw.c
+@@ -231,7 +231,7 @@ typedef struct {
+ int nvclk_khz;
+ char mem_page_miss;
+ char mem_latency;
+- int memory_type;
++ u32 memory_type;
+ int memory_width;
+ char enable_video;
+ char gr_during_vid;
+@@ -2107,7 +2107,7 @@ static void nv10GetConfig
+ )
{
- int result;
+ struct pci_dev* dev;
+- int amt;
++ u32 amt;
-- US_DEBUGP("%s: xfer %u bytes\n", __FUNCTION__, length);
-+ US_DEBUGP("%s: xfer %u bytes\n", __func__, length);
+ #ifdef __BIG_ENDIAN
+ /* turn on big endian register access */
+diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
+index 71fa6ed..13b38cb 100644
+--- a/drivers/video/s3c2410fb.c
++++ b/drivers/video/s3c2410fb.c
+@@ -430,9 +430,9 @@ static void s3c2410fb_activate_var(struct fb_info *info)
+ struct fb_var_screeninfo *var = &info->var;
+ int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock) / 2;
+
+- dprintk("%s: var->xres = %d\n", __FUNCTION__, var->xres);
+- dprintk("%s: var->yres = %d\n", __FUNCTION__, var->yres);
+- dprintk("%s: var->bpp = %d\n", __FUNCTION__, var->bits_per_pixel);
++ dprintk("%s: var->xres = %d\n", __func__, var->xres);
++ dprintk("%s: var->yres = %d\n", __func__, var->yres);
++ dprintk("%s: var->bpp = %d\n", __func__, var->bits_per_pixel);
+
+ if (type == S3C2410_LCDCON1_TFT) {
+ s3c2410fb_calculate_tft_lcd_regs(info, &fbi->regs);
+diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
+index 7d53bc2..2972f11 100644
+--- a/drivers/video/s3fb.c
++++ b/drivers/video/s3fb.c
+@@ -132,10 +132,10 @@ static const struct svga_timing_regs s3_timing_regs = {
+ /* Module parameters */
- /* 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);
+-static char *mode = "640x480-8 at 60";
++static char *mode_option __devinitdata = "640x480-8 at 60";
- /* 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__);
+ #ifdef CONFIG_MTRR
+-static int mtrr = 1;
++static int mtrr __devinitdata = 1;
+ #endif
- /* 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,
+ static int fasttext = 1;
+@@ -145,8 +145,10 @@ MODULE_AUTHOR("(c) 2006-2007 Ondrej Zajicek <santiago at crfreenet.org>");
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("fbdev driver for S3 Trio/Virge");
- int usb_stor_CB_reset(struct us_data *us)
- {
-- US_DEBUGP("%s called\n", __FUNCTION__);
-+ US_DEBUGP("%s called\n", __func__);
+-module_param(mode, charp, 0444);
+-MODULE_PARM_DESC(mode, "Default video mode ('640x480-8 at 60', etc)");
++module_param(mode_option, charp, 0444);
++MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8 at 60', etc)");
++module_param_named(mode, mode_option, charp, 0444);
++MODULE_PARM_DESC(mode, "Default video mode ('640x480-8 at 60', etc) (deprecated)");
+
+ #ifdef CONFIG_MTRR
+ module_param(mtrr, int, 0444);
+@@ -886,7 +888,7 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
+ }
+
+ /* Allocate and fill driver data structure */
+- info = framebuffer_alloc(sizeof(struct s3fb_info), NULL);
++ info = framebuffer_alloc(sizeof(struct s3fb_info), &(dev->dev));
+ if (!info) {
+ dev_err(&(dev->dev), "cannot allocate memory\n");
+ return -ENOMEM;
+@@ -901,13 +903,13 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
+ /* Prepare PCI device */
+ rc = pci_enable_device(dev);
+ if (rc < 0) {
+- dev_err(&(dev->dev), "cannot enable PCI device\n");
++ dev_err(info->dev, "cannot enable PCI device\n");
+ goto err_enable_device;
+ }
- 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__);
+ rc = pci_request_regions(dev, "s3fb");
+ if (rc < 0) {
+- dev_err(&(dev->dev), "cannot reserve framebuffer region\n");
++ dev_err(info->dev, "cannot reserve framebuffer region\n");
+ goto err_request_regions;
+ }
- 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),
+@@ -919,7 +921,7 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
+ info->screen_base = pci_iomap(dev, 0, 0);
+ if (! info->screen_base) {
+ rc = -ENOMEM;
+- dev_err(&(dev->dev), "iomap for framebuffer failed\n");
++ dev_err(info->dev, "iomap for framebuffer failed\n");
+ goto err_iomap;
+ }
-+#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
+@@ -960,22 +962,22 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
+ info->pseudo_palette = (void*) (par->pseudo_palette);
+
+ /* Prepare startup mode */
+- rc = fb_find_mode(&(info->var), info, mode, NULL, 0, NULL, 8);
++ rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
+ if (! ((rc == 1) || (rc == 2))) {
+ rc = -EINVAL;
+- dev_err(&(dev->dev), "mode %s not found\n", mode);
++ dev_err(info->dev, "mode %s not found\n", mode_option);
+ goto err_find_mode;
+ }
- /* Some informational data */
- MODULE_AUTHOR("Matthew Dharm <mdharm-usb at one-eyed-alien.net>");
-@@ -187,7 +190,7 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message)
- /* Wait until no command is running */
- mutex_lock(&us->dev_mutex);
+ rc = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (rc < 0) {
+- dev_err(&(dev->dev), "cannot allocate colormap\n");
++ dev_err(info->dev, "cannot allocate colormap\n");
+ goto err_alloc_cmap;
+ }
-- US_DEBUGP("%s\n", __FUNCTION__);
-+ US_DEBUGP("%s\n", __func__);
- if (us->suspend_resume_hook)
- (us->suspend_resume_hook)(us, US_SUSPEND);
+ rc = register_framebuffer(info);
+ if (rc < 0) {
+- dev_err(&(dev->dev), "cannot register framebuffer\n");
++ dev_err(info->dev, "cannot register framebuffer\n");
+ goto err_reg_fb;
+ }
+
+@@ -1051,7 +1053,7 @@ static int s3_pci_suspend(struct pci_dev* dev, pm_message_t state)
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct s3fb_info *par = info->par;
+
+- dev_info(&(dev->dev), "suspend\n");
++ dev_info(info->dev, "suspend\n");
+
+ acquire_console_sem();
+ mutex_lock(&(par->open_lock));
+@@ -1083,7 +1085,7 @@ static int s3_pci_resume(struct pci_dev* dev)
+ struct s3fb_info *par = info->par;
+ int err;
-@@ -204,7 +207,7 @@ static int storage_resume(struct usb_interface *iface)
+- dev_info(&(dev->dev), "resume\n");
++ dev_info(info->dev, "resume\n");
- mutex_lock(&us->dev_mutex);
+ acquire_console_sem();
+ mutex_lock(&(par->open_lock));
+@@ -1100,7 +1102,7 @@ static int s3_pci_resume(struct pci_dev* dev)
+ if (err) {
+ mutex_unlock(&(par->open_lock));
+ release_console_sem();
+- dev_err(&(dev->dev), "error %d enabling device for resume\n", err);
++ dev_err(info->dev, "error %d enabling device for resume\n", err);
+ return err;
+ }
+ pci_set_master(dev);
+@@ -1168,7 +1170,7 @@ static int __init s3fb_setup(char *options)
+ else if (!strncmp(opt, "fasttext:", 9))
+ fasttext = simple_strtoul(opt + 9, NULL, 0);
+ else
+- mode = opt;
++ mode_option = opt;
+ }
-- US_DEBUGP("%s\n", __FUNCTION__);
-+ US_DEBUGP("%s\n", __func__);
- if (us->suspend_resume_hook)
- (us->suspend_resume_hook)(us, US_RESUME);
+ return 0;
+diff --git a/drivers/video/sa1100fb.h b/drivers/video/sa1100fb.h
+index 48066ef..f465b27 100644
+--- a/drivers/video/sa1100fb.h
++++ b/drivers/video/sa1100fb.h
+@@ -132,7 +132,7 @@ struct sa1100fb_info {
+ * Debug macros
+ */
+ #if DEBUG
+-# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
++# define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ## args)
+ #else
+ # define DPRINTK(fmt, args...)
+ #endif
+diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
+index 35c1ce6..783d4ad 100644
+--- a/drivers/video/savage/savagefb-i2c.c
++++ b/drivers/video/savage/savagefb-i2c.c
+@@ -140,7 +140,7 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
+ chan->adapter.id = I2C_HW_B_SAVAGE;
+ chan->adapter.algo_data = &chan->algo;
+ chan->adapter.dev.parent = &chan->par->pcidev->dev;
+- chan->algo.udelay = 40;
++ chan->algo.udelay = 10;
+ chan->algo.timeout = 20;
+ chan->algo.data = chan;
+
+diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
+index 9b05da6..a14e822 100644
+--- a/drivers/video/sis/sis.h
++++ b/drivers/video/sis/sis.h
+@@ -55,7 +55,7 @@
+ #undef SISFBDEBUG
+
+ #ifdef SISFBDEBUG
+-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
++#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
+ #define TWDEBUG(x) printk(KERN_INFO x "\n");
+ #else
+ #define DPRINTK(fmt, args...)
+diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
+index 97784f9..5b11a00 100644
+--- a/drivers/video/sstfb.c
++++ b/drivers/video/sstfb.c
+@@ -1006,7 +1006,7 @@ static int sst_set_pll_att_ti(struct fb_info *info,
+ break;
+ default:
+ dprintk("%s: wrong clock code '%d'\n",
+- __FUNCTION__, clock);
++ __func__, clock);
+ return 0;
+ }
+ udelay(300);
+@@ -1048,7 +1048,7 @@ static int sst_set_pll_ics(struct fb_info *info,
+ break;
+ default:
+ dprintk("%s: wrong clock code '%d'\n",
+- __FUNCTION__, clock);
++ __func__, clock);
+ return 0;
+ }
+ udelay(300);
+@@ -1079,7 +1079,7 @@ static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp)
+ sst_dac_write(DACREG_RMR, (cr0 & 0x0f) | DACREG_CR0_16BPP);
+ break;
+ default:
+- dprintk("%s: bad depth '%u'\n", __FUNCTION__, bpp);
++ dprintk("%s: bad depth '%u'\n", __func__, bpp);
+ break;
+ }
+ }
+@@ -1093,7 +1093,7 @@ static void sst_set_vidmod_ics(struct fb_info *info, const int bpp)
+ sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_16BPP);
+ break;
+ default:
+- dprintk("%s: bad depth '%u'\n", __FUNCTION__, bpp);
++ dprintk("%s: bad depth '%u'\n", __func__, bpp);
+ break;
+ }
+ }
+@@ -1133,7 +1133,7 @@ static int __devinit sst_detect_dactype(struct fb_info *info, struct sstfb_par *
+ }
+ if (!ret)
+ return 0;
+- f_dprintk("%s found %s\n", __FUNCTION__, dacs[i].name);
++ f_dprintk("%s found %s\n", __func__, dacs[i].name);
+ par->dac_sw = dacs[i];
+ return 1;
+ }
+diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
+index f98be30..598d35e 100644
+--- a/drivers/video/stifb.c
++++ b/drivers/video/stifb.c
+@@ -164,11 +164,11 @@ static int __initdata stifb_bpp_pref[MAX_STI_ROMS];
+ # define DEBUG_ON() debug_on=1
+ # define WRITE_BYTE(value,fb,reg) do { if (debug_on) \
+ printk(KERN_DEBUG "%30s: WRITE_BYTE(0x%06x) = 0x%02x (old=0x%02x)\n", \
+- __FUNCTION__, reg, value, READ_BYTE(fb,reg)); \
++ __func__, reg, value, READ_BYTE(fb,reg)); \
+ gsc_writeb((value),(fb)->info.fix.mmio_start + (reg)); } while (0)
+ # define WRITE_WORD(value,fb,reg) do { if (debug_on) \
+ printk(KERN_DEBUG "%30s: WRITE_WORD(0x%06x) = 0x%08x (old=0x%08x)\n", \
+- __FUNCTION__, reg, value, READ_WORD(fb,reg)); \
++ __func__, reg, value, READ_WORD(fb,reg)); \
+ gsc_writel((value),(fb)->info.fix.mmio_start + (reg)); } while (0)
+ #endif /* DEBUG_STIFB_REGS */
+
+diff --git a/drivers/video/syscopyarea.c b/drivers/video/syscopyarea.c
+index 37af10a..a352d5f 100644
+--- a/drivers/video/syscopyarea.c
++++ b/drivers/video/syscopyarea.c
+@@ -26,15 +26,15 @@
+ */
-@@ -216,7 +219,7 @@ static int storage_reset_resume(struct usb_interface *iface)
+ static void
+-bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
+- int src_idx, int bits, unsigned n)
++bitcpy(struct fb_info *p, unsigned long *dst, int dst_idx,
++ const unsigned long *src, int src_idx, int bits, unsigned n)
+ {
+ unsigned long first, last;
+ int const shift = dst_idx-src_idx;
+ int left, right;
+
+- first = FB_SHIFT_HIGH(~0UL, dst_idx);
+- last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
++ first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
++ last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
+
+ if (!shift) {
+ /* Same alignment for source and dest */
+@@ -167,8 +167,8 @@ bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
+ */
+
+ static void
+-bitcpy_rev(unsigned long *dst, int dst_idx, const unsigned long *src,
+- int src_idx, int bits, unsigned n)
++bitcpy_rev(struct fb_info *p, unsigned long *dst, int dst_idx,
++ const unsigned long *src, int src_idx, int bits, unsigned n)
{
- struct us_data *us = usb_get_intfdata(iface);
+ unsigned long first, last;
+ int shift;
+@@ -186,8 +186,8 @@ bitcpy_rev(unsigned long *dst, int dst_idx, const unsigned long *src,
-- US_DEBUGP("%s\n", __FUNCTION__);
-+ US_DEBUGP("%s\n", __func__);
+ shift = dst_idx-src_idx;
- /* 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)
+- first = FB_SHIFT_LOW(~0UL, bits - 1 - dst_idx);
+- last = ~(FB_SHIFT_LOW(~0UL, bits - 1 - ((dst_idx-n) % bits)));
++ first = FB_SHIFT_LOW(p, ~0UL, bits - 1 - dst_idx);
++ last = ~(FB_SHIFT_LOW(p, ~0UL, bits - 1 - ((dst_idx-n) % bits)));
+
+ if (!shift) {
+ /* Same alignment for source and dest */
+@@ -353,7 +353,7 @@ void sys_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+ dst_idx &= (bytes - 1);
+ src += src_idx >> (ffs(bits) - 1);
+ src_idx &= (bytes - 1);
+- bitcpy_rev(dst, dst_idx, src, src_idx, bits,
++ bitcpy_rev(p, dst, dst_idx, src, src_idx, bits,
+ width*p->var.bits_per_pixel);
+ }
+ } else {
+@@ -362,7 +362,7 @@ void sys_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+ dst_idx &= (bytes - 1);
+ src += src_idx >> (ffs(bits) - 1);
+ src_idx &= (bytes - 1);
+- bitcpy(dst, dst_idx, src, src_idx, bits,
++ bitcpy(p, dst, dst_idx, src, src_idx, bits,
+ width*p->var.bits_per_pixel);
+ dst_idx += bits_per_line;
+ src_idx += bits_per_line;
+diff --git a/drivers/video/sysfillrect.c b/drivers/video/sysfillrect.c
+index a261e9e..f94d6b6 100644
+--- a/drivers/video/sysfillrect.c
++++ b/drivers/video/sysfillrect.c
+@@ -22,16 +22,16 @@
+ */
+
+ static void
+-bitfill_aligned(unsigned long *dst, int dst_idx, unsigned long pat,
+- unsigned n, int bits)
++bitfill_aligned(struct fb_info *p, unsigned long *dst, int dst_idx,
++ unsigned long pat, unsigned n, int bits)
{
- struct us_data *us = usb_get_intfdata(iface);
+ unsigned long first, last;
-- US_DEBUGP("%s\n", __FUNCTION__);
-+ US_DEBUGP("%s\n", __func__);
+ if (!n)
+ return;
- /* 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)
+- first = FB_SHIFT_HIGH(~0UL, dst_idx);
+- last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
++ first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
++ last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
+
+ if (dst_idx+n <= bits) {
+ /* Single word */
+@@ -78,16 +78,16 @@ bitfill_aligned(unsigned long *dst, int dst_idx, unsigned long pat,
+ */
+
+ static void
+-bitfill_unaligned(unsigned long *dst, int dst_idx, unsigned long pat,
+- int left, int right, unsigned n, int bits)
++bitfill_unaligned(struct fb_info *p, unsigned long *dst, int dst_idx,
++ unsigned long pat, int left, int right, unsigned n, int bits)
{
- struct us_data *us = usb_get_intfdata(iface);
+ unsigned long first, last;
-- US_DEBUGP("%s\n", __FUNCTION__);
-+ US_DEBUGP("%s\n", __func__);
+ if (!n)
+ return;
- /* 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)
+- first = FB_SHIFT_HIGH(~0UL, dst_idx);
+- last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
++ first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
++ last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
+
+ if (dst_idx+n <= bits) {
+ /* Single word */
+@@ -132,8 +132,8 @@ bitfill_unaligned(unsigned long *dst, int dst_idx, unsigned long pat,
+ * Aligned pattern invert using 32/64-bit memory accesses
+ */
+ static void
+-bitfill_aligned_rev(unsigned long *dst, int dst_idx, unsigned long pat,
+- unsigned n, int bits)
++bitfill_aligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx,
++ unsigned long pat, unsigned n, int bits)
+ {
+ unsigned long val = pat;
+ unsigned long first, last;
+@@ -141,8 +141,8 @@ bitfill_aligned_rev(unsigned long *dst, int dst_idx, unsigned long pat,
+ if (!n)
+ return;
+
+- first = FB_SHIFT_HIGH(~0UL, dst_idx);
+- last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
++ first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
++ last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
+
+ if (dst_idx+n <= bits) {
+ /* Single word */
+@@ -188,16 +188,17 @@ bitfill_aligned_rev(unsigned long *dst, int dst_idx, unsigned long pat,
+ */
+
+ static void
+-bitfill_unaligned_rev(unsigned long *dst, int dst_idx, unsigned long pat,
+- int left, int right, unsigned n, int bits)
++bitfill_unaligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx,
++ unsigned long pat, int left, int right, unsigned n,
++ int bits)
{
-- US_DEBUGP("-- %s\n", __FUNCTION__);
-+ US_DEBUGP("-- %s\n", __func__);
+ unsigned long first, last;
- /* 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;
+ if (!n)
+ return;
+
+- first = FB_SHIFT_HIGH(~0UL, dst_idx);
+- last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
++ first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
++ last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
+
+ if (dst_idx+n <= bits) {
+ /* Single word */
+@@ -267,9 +268,9 @@ void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+ if (p->fbops->fb_sync)
+ p->fbops->fb_sync(p);
+ if (!left) {
+- void (*fill_op32)(unsigned long *dst, int dst_idx,
+- unsigned long pat, unsigned n, int bits) =
+- NULL;
++ void (*fill_op32)(struct fb_info *p, unsigned long *dst,
++ int dst_idx, unsigned long pat, unsigned n,
++ int bits) = NULL;
+
+ switch (rect->rop) {
+ case ROP_XOR:
+@@ -287,16 +288,16 @@ void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+ while (height--) {
+ dst += dst_idx >> (ffs(bits) - 1);
+ dst_idx &= (bits - 1);
+- fill_op32(dst, dst_idx, pat, width*bpp, bits);
++ fill_op32(p, dst, dst_idx, pat, width*bpp, bits);
+ dst_idx += p->fix.line_length*8;
+ }
+ } else {
+ int right;
+ int r;
+ int rot = (left-dst_idx) % bpp;
+- void (*fill_op)(unsigned long *dst, int dst_idx,
+- unsigned long pat, int left, int right,
+- unsigned n, int bits) = NULL;
++ void (*fill_op)(struct fb_info *p, unsigned long *dst,
++ int dst_idx, unsigned long pat, int left,
++ int right, unsigned n, int bits) = NULL;
+
+ /* rotate pattern to correct start position */
+ pat = pat << rot | pat >> (bpp-rot);
+@@ -318,7 +319,7 @@ void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+ while (height--) {
+ dst += dst_idx >> (ffs(bits) - 1);
+ dst_idx &= (bits - 1);
+- fill_op(dst, dst_idx, pat, left, right,
++ fill_op(p, dst, dst_idx, pat, left, right,
+ width*bpp, bits);
+ r = (p->fix.line_length*8) % bpp;
+ pat = pat << (bpp-r) | pat >> r;
+diff --git a/drivers/video/sysimgblt.c b/drivers/video/sysimgblt.c
+index bd7e7e9..186c6f6 100644
+--- a/drivers/video/sysimgblt.c
++++ b/drivers/video/sysimgblt.c
+@@ -18,35 +18,31 @@
+ #define DEBUG
+
+ #ifdef DEBUG
+-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__FUNCTION__,## args)
++#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__func__,## args)
+ #else
+ #define DPRINTK(fmt, args...)
#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
+-static const u32 cfb_tab8[] = {
+-#if defined(__BIG_ENDIAN)
++static const u32 cfb_tab8_be[] = {
+ 0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
+ 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
+ 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
+ 0xffff0000,0xffff00ff,0xffffff00,0xffffffff
+-#elif defined(__LITTLE_ENDIAN)
++};
++
++static const u32 cfb_tab8_le[] = {
+ 0x00000000,0xff000000,0x00ff0000,0xffff0000,
+ 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00,
+ 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff,
+ 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff
+-#else
+-#error FIXME: No endianness??
+-#endif
+ };
+
+-static const u32 cfb_tab16[] = {
+-#if defined(__BIG_ENDIAN)
++static const u32 cfb_tab16_be[] = {
+ 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
+-#elif defined(__LITTLE_ENDIAN)
++};
+
++static const u32 cfb_tab16_le[] = {
+ 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
+-#else
+-#error FIXME: No endianness??
+-#endif
+ };
+
+ static const u32 cfb_tab32[] = {
+@@ -72,7 +68,7 @@ static void color_imageblit(const struct fb_image *image, struct fb_info *p,
+ val = 0;
+
+ if (start_index) {
+- u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0,
++ u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0,
+ start_index));
+ val = *dst & start_mask;
+ shift = start_index;
+@@ -83,20 +79,20 @@ static void color_imageblit(const struct fb_image *image, struct fb_info *p,
+ color = palette[*src];
+ else
+ color = *src;
+- color <<= FB_LEFT_POS(bpp);
+- val |= FB_SHIFT_HIGH(color, shift);
++ color <<= FB_LEFT_POS(p, bpp);
++ val |= FB_SHIFT_HIGH(p, color, shift);
+ if (shift >= null_bits) {
+ *dst++ = val;
+
+ val = (shift == null_bits) ? 0 :
+- FB_SHIFT_LOW(color, 32 - shift);
++ FB_SHIFT_LOW(p, color, 32 - shift);
+ }
+ shift += bpp;
+ shift &= (32 - 1);
+ src++;
+ }
+ if (shift) {
+- u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift);
++ u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift);
+
+ *dst &= end_mask;
+ *dst |= val;
+@@ -125,8 +121,8 @@ static void slow_imageblit(const struct fb_image *image, struct fb_info *p,
+ u32 i, j, l;
+
+ dst2 = dst1;
+- fgcolor <<= FB_LEFT_POS(bpp);
+- bgcolor <<= FB_LEFT_POS(bpp);
++ fgcolor <<= FB_LEFT_POS(p, bpp);
++ bgcolor <<= FB_LEFT_POS(p, bpp);
+
+ for (i = image->height; i--; ) {
+ shift = val = 0;
+@@ -137,7 +133,8 @@ static void slow_imageblit(const struct fb_image *image, struct fb_info *p,
+
+ /* write leading bits */
+ if (start_index) {
+- u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0,start_index));
++ u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0,
++ start_index));
+ val = *dst & start_mask;
+ shift = start_index;
+ }
+@@ -145,13 +142,13 @@ static void slow_imageblit(const struct fb_image *image, struct fb_info *p,
+ while (j--) {
+ l--;
+ color = (*s & (1 << l)) ? fgcolor : bgcolor;
+- val |= FB_SHIFT_HIGH(color, shift);
++ val |= FB_SHIFT_HIGH(p, color, shift);
+
+ /* Did the bitshift spill bits to the next long? */
+ if (shift >= null_bits) {
+ *dst++ = val;
+ val = (shift == null_bits) ? 0 :
+- FB_SHIFT_LOW(color,32 - shift);
++ FB_SHIFT_LOW(p, color, 32 - shift);
+ }
+ shift += bpp;
+ shift &= (32 - 1);
+@@ -160,7 +157,7 @@ static void slow_imageblit(const struct fb_image *image, struct fb_info *p,
+
+ /* write trailing bits */
+ if (shift) {
+- u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift);
++ u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift);
+
+ *dst &= end_mask;
+ *dst |= val;
+@@ -199,10 +196,10 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p,
+
+ switch (bpp) {
+ case 8:
+- tab = cfb_tab8;
++ tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le;
+ break;
+ case 16:
+- tab = cfb_tab16;
++ tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;
+ break;
+ case 32:
default:
- return -EIO;
+diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
+index e5a9ddb..a717743 100644
+--- a/drivers/video/tcx.c
++++ b/drivers/video/tcx.c
+@@ -419,7 +419,7 @@ static int __devinit tcx_init_one(struct of_device *op)
+ par->mmap_map[6].size = SBUS_MMAP_EMPTY;
}
-@@ -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)
+
+- par->physbase = 0;
++ par->physbase = op->resource[0].start;
+ par->which_io = op->resource[0].flags & IORESOURCE_BITS;
+
+ for (i = 0; i < TCX_MMAP_ENTRIES; i++) {
+@@ -470,10 +470,10 @@ static int __devinit tcx_init_one(struct of_device *op)
+
+ dev_set_drvdata(&op->dev, info);
+
+- printk("%s: TCX at %lx:%lx, %s\n",
++ printk(KERN_INFO "%s: TCX at %lx:%lx, %s\n",
+ dp->full_name,
+ par->which_io,
+- op->resource[0].start,
++ par->physbase,
+ par->lowdepth ? "8-bit only" : "24-bit depth");
+
+ return 0;
+@@ -527,7 +527,7 @@ static struct of_platform_driver tcx_driver = {
+ .remove = __devexit_p(tcx_remove),
+ };
+
+-int __init tcx_init(void)
++static int __init tcx_init(void)
{
-- US_DEBUGP("-- %s\n", __FUNCTION__);
-+ US_DEBUGP("-- %s\n", __func__);
+ if (fb_get_options("tcxfb", NULL))
+ return -ENODEV;
+@@ -535,7 +535,7 @@ int __init tcx_init(void)
+ return of_register_driver(&tcx_driver, &of_bus_type);
+ }
- /* 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)
+-void __exit tcx_exit(void)
++static void __exit tcx_exit(void)
{
-- US_DEBUGP("-- %s\n", __FUNCTION__);
-+ US_DEBUGP("-- %s\n", __func__);
+ of_unregister_driver(&tcx_driver);
+ }
+diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
+index 71e179e..ea9f19d 100644
+--- a/drivers/video/tdfxfb.c
++++ b/drivers/video/tdfxfb.c
+@@ -70,7 +70,7 @@
- kfree(us->sensebuf);
+ #include <video/tdfx.h>
-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;
+-#define DPRINTK(a, b...) pr_debug("fb: %s: " a, __FUNCTION__ , ## b)
++#define DPRINTK(a, b...) pr_debug("fb: %s: " a, __func__ , ## b)
+
+ #ifdef CONFIG_MTRR
+ #include <asm/mtrr.h>
+diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
+index 0a4e07d..bd54cd0 100644
+--- a/drivers/video/tridentfb.c
++++ b/drivers/video/tridentfb.c
+@@ -58,7 +58,7 @@ static int displaytype;
+ /* defaults which are normally overriden by user values */
+
+ /* video mode */
+-static char *mode = "640x480";
++static char *mode_option __devinitdata = "640x480";
+ static int bpp = 8;
+
+ static int noaccel;
+@@ -73,7 +73,10 @@ static int memsize;
+ static int memdiff;
+ static int nativex;
+
+-module_param(mode, charp, 0);
++module_param(mode_option, charp, 0);
++MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8 at 60'");
++module_param_named(mode, mode_option, charp, 0);
++MODULE_PARM_DESC(mode, "Initial video mode e.g. '648x480-8 at 60' (deprecated)");
+ module_param(bpp, int, 0);
+ module_param(center, int, 0);
+ module_param(stretch, int, 0);
+@@ -1297,7 +1300,8 @@ static int __devinit trident_pci_probe(struct pci_dev * dev,
+ #endif
+ fb_info.pseudo_palette = pseudo_pal;
+
+- if (!fb_find_mode(&default_var, &fb_info, mode, NULL, 0, NULL, bpp)) {
++ if (!fb_find_mode(&default_var, &fb_info,
++ mode_option, NULL, 0, NULL, bpp)) {
+ err = -EINVAL;
+ goto out_unmap2;
}
-@@ -212,7 +212,7 @@ static void skel_write_bulk_callback(struct urb *urb)
+@@ -1385,7 +1389,7 @@ static struct pci_driver tridentfb_pci_driver = {
+ * video=trident:800x600,bpp=16,noaccel
+ */
+ #ifndef MODULE
+-static int tridentfb_setup(char *options)
++static int __init tridentfb_setup(char *options)
{
- struct usb_skel *dev;
+ char *opt;
+ if (!options || !*options)
+@@ -1412,7 +1416,7 @@ static int tridentfb_setup(char *options)
+ else if (!strncmp(opt, "nativex=", 8))
+ nativex = simple_strtoul(opt + 8, NULL, 0);
+ else
+- mode = opt;
++ mode_option = opt;
+ }
+ return 0;
+ }
+diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
+index 9336165..cdbb56e 100644
+--- a/drivers/video/uvesafb.c
++++ b/drivers/video/uvesafb.c
+@@ -181,7 +181,8 @@ static int uvesafb_exec(struct uvesafb_ktask *task)
+ /* If all slots are taken -- bail out. */
+ if (uvfb_tasks[seq]) {
+ mutex_unlock(&uvfb_lock);
+- return -EBUSY;
++ err = -EBUSY;
++ goto out;
+ }
-- dev = (struct usb_skel *)urb->context;
-+ dev = urb->context;
+ /* Save a pointer to the kernel part of the task struct. */
+@@ -205,7 +206,6 @@ static int uvesafb_exec(struct uvesafb_ktask *task)
+ err = cn_netlink_send(m, 0, gfp_any());
+ }
+ }
+- kfree(m);
+
+ if (!err && !(task->t.flags & TF_EXIT))
+ err = !wait_for_completion_timeout(task->done,
+@@ -218,7 +218,8 @@ static int uvesafb_exec(struct uvesafb_ktask *task)
+ seq++;
+ if (seq >= UVESAFB_TASKS_MAX)
+ seq = 0;
+-
++out:
++ kfree(m);
+ return err;
+ }
- /* 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);
+@@ -885,7 +886,7 @@ static int __devinit uvesafb_vbe_init_mode(struct fb_info *info)
+ }
- 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;
+ /* fb_find_mode() failed */
+- if (i == 0 || i >= 3) {
++ if (i == 0) {
+ info->var.xres = 640;
+ info->var.yres = 480;
+ mode = (struct fb_videomode *)
+diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c
+index 2aa71eb..c18f188 100644
+--- a/drivers/video/vermilion/vermilion.c
++++ b/drivers/video/vermilion/vermilion.c
+@@ -112,8 +112,9 @@ static int vmlfb_alloc_vram_area(struct vram_area *va, unsigned max_order,
+
+ /*
+ * It seems like __get_free_pages only ups the usage count
+- * of the first page. This doesn't work with nopage mapping, so
+- * up the usage count once more.
++ * of the first page. This doesn't work with fault mapping, so
++ * up the usage count once more (XXX: should use split_page or
++ * compound page).
+ */
+
+ memset((void *)va->logical, 0x00, va->size);
+diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c
+index 4c3a633..536ab11 100644
+--- a/drivers/video/vt8623fb.c
++++ b/drivers/video/vt8623fb.c
+@@ -100,7 +100,7 @@ static struct svga_timing_regs vt8623_timing_regs = {
+
+ /* Module parameters */
+
+-static char *mode = "640x480-8 at 60";
++static char *mode_option = "640x480-8 at 60";
+
+ #ifdef CONFIG_MTRR
+ static int mtrr = 1;
+@@ -110,8 +110,10 @@ MODULE_AUTHOR("(c) 2006 Ondrej Zajicek <santiago at crfreenet.org>");
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("fbdev driver for integrated graphics core in VIA VT8623 [CLE266]");
+
+-module_param(mode, charp, 0644);
+-MODULE_PARM_DESC(mode, "Default video mode ('640x480-8 at 60', etc)");
++module_param(mode_option, charp, 0644);
++MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8 at 60', etc)");
++module_param_named(mode, mode_option, charp, 0);
++MODULE_PARM_DESC(mode, "Default video mode e.g. '648x480-8 at 60' (deprecated)");
+
+ #ifdef CONFIG_MTRR
+ module_param(mtrr, int, 0444);
+@@ -434,6 +436,10 @@ static int vt8623fb_set_par(struct fb_info *info)
+ svga_wcrt_multi(vt8623_offset_regs, offset_value);
+ svga_wseq_multi(vt8623_fetch_count_regs, fetch_value);
+
++ /* Clear H/V Skew */
++ svga_wcrt_mask(0x03, 0x00, 0x60);
++ svga_wcrt_mask(0x05, 0x00, 0x60);
++
+ if (info->var.vmode & FB_VMODE_DOUBLE)
+ svga_wcrt_mask(0x09, 0x80, 0x80);
+ else
+@@ -655,7 +661,7 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi
+ }
+
+ /* Allocate and fill driver data structure */
+- info = framebuffer_alloc(sizeof(struct vt8623fb_info), NULL);
++ info = framebuffer_alloc(sizeof(struct vt8623fb_info), &(dev->dev));
+ if (! info) {
+ dev_err(&(dev->dev), "cannot allocate memory\n");
+ return -ENOMEM;
+@@ -671,13 +677,13 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi
+
+ rc = pci_enable_device(dev);
+ if (rc < 0) {
+- dev_err(&(dev->dev), "cannot enable PCI device\n");
++ dev_err(info->dev, "cannot enable PCI device\n");
+ goto err_enable_device;
+ }
+
+ rc = pci_request_regions(dev, "vt8623fb");
+ if (rc < 0) {
+- dev_err(&(dev->dev), "cannot reserve framebuffer region\n");
++ dev_err(info->dev, "cannot reserve framebuffer region\n");
+ goto err_request_regions;
+ }
+
+@@ -690,14 +696,14 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi
+ info->screen_base = pci_iomap(dev, 0, 0);
+ if (! info->screen_base) {
+ rc = -ENOMEM;
+- dev_err(&(dev->dev), "iomap for framebuffer failed\n");
++ dev_err(info->dev, "iomap for framebuffer failed\n");
+ goto err_iomap_1;
+ }
+
+ par->mmio_base = pci_iomap(dev, 1, 0);
+ if (! par->mmio_base) {
+ rc = -ENOMEM;
+- dev_err(&(dev->dev), "iomap for MMIO failed\n");
++ dev_err(info->dev, "iomap for MMIO failed\n");
+ goto err_iomap_2;
}
-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
+@@ -708,7 +714,7 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi
+ if ((16 <= memsize1) && (memsize1 <= 64) && (memsize1 == memsize2))
+ info->screen_size = memsize1 << 20;
+ else {
+- dev_err(&(dev->dev), "memory size detection failed (%x %x), suppose 16 MB\n", memsize1, memsize2);
++ dev_err(info->dev, "memory size detection failed (%x %x), suppose 16 MB\n", memsize1, memsize2);
+ info->screen_size = 16 << 20;
+ }
- If unsure, say N.
+@@ -722,22 +728,22 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi
-+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"
+ /* Prepare startup mode */
- 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
+- rc = fb_find_mode(&(info->var), info, mode, NULL, 0, NULL, 8);
++ rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
+ if (! ((rc == 1) || (rc == 2))) {
+ rc = -EINVAL;
+- dev_err(&(dev->dev), "mode %s not found\n", mode);
++ dev_err(info->dev, "mode %s not found\n", mode_option);
+ goto err_find_mode;
+ }
- # Platform or fallback drivers go here
- obj-$(CONFIG_FB_UVESA) += uvesafb.o
-diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
-index 97facb1..7576519 100644
---- a/drivers/video/pxafb.c
-+++ b/drivers/video/pxafb.c
-@@ -45,6 +45,7 @@
- #include <asm/irq.h>
- #include <asm/div64.h>
- #include <asm/arch/pxa-regs.h>
-+#include <asm/arch/pxa2xx-gpio.h>
- #include <asm/arch/bitfield.h>
- #include <asm/arch/pxafb.h>
+ rc = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (rc < 0) {
+- dev_err(&(dev->dev), "cannot allocate colormap\n");
++ dev_err(info->dev, "cannot allocate colormap\n");
+ goto err_alloc_cmap;
+ }
+
+ rc = register_framebuffer(info);
+ if (rc < 0) {
+- dev_err(&(dev->dev), "cannot register framebugger\n");
++ dev_err(info->dev, "cannot register framebugger\n");
+ goto err_reg_fb;
+ }
+
+@@ -811,7 +817,7 @@ static int vt8623_pci_suspend(struct pci_dev* dev, pm_message_t state)
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct vt8623fb_info *par = info->par;
+
+- dev_info(&(dev->dev), "suspend\n");
++ dev_info(info->dev, "suspend\n");
+
+ acquire_console_sem();
+ mutex_lock(&(par->open_lock));
+@@ -842,7 +848,7 @@ static int vt8623_pci_resume(struct pci_dev* dev)
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct vt8623fb_info *par = info->par;
+
+- dev_info(&(dev->dev), "resume\n");
++ dev_info(info->dev, "resume\n");
+
+ acquire_console_sem();
+ mutex_lock(&(par->open_lock));
+@@ -913,7 +919,7 @@ static int __init vt8623fb_init(void)
+ return -ENODEV;
+ if (option && *option)
+- mode = option;
++ mode_option = option;
+ #endif
+
+ pr_debug("vt8623fb: initializing\n");
+diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
+index 003c49a..30469bf 100644
+--- a/drivers/video/w100fb.c
++++ b/drivers/video/w100fb.c
+@@ -765,8 +765,10 @@ int __init w100fb_probe(struct platform_device *pdev)
+ printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
+ return 0;
+ out:
+- fb_dealloc_cmap(&info->cmap);
+- kfree(info->pseudo_palette);
++ if (info) {
++ fb_dealloc_cmap(&info->cmap);
++ kfree(info->pseudo_palette);
++ }
+ if (remapped_fbuf != NULL)
+ iounmap(remapped_fbuf);
+ if (remapped_regs != NULL)
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
new file mode 100644
index 0000000..619a6f8
@@ -727149,4747 +962780,13991 @@
+ 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->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/w1/w1_log.h b/drivers/w1/w1_log.h
+index fe6bdf4..e6ab7cf 100644
+--- a/drivers/w1/w1_log.h
++++ b/drivers/w1/w1_log.h
+@@ -30,7 +30,7 @@
+ # 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/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c
+index 32ccd7c..35cddff 100644
+--- a/drivers/watchdog/sc1200wdt.c
++++ b/drivers/watchdog/sc1200wdt.c
+@@ -38,8 +38,8 @@
+ #include <linux/init.h>
+ #include <linux/pnp.h>
+ #include <linux/fs.h>
++#include <linux/semaphore.h>
+
+-#include <asm/semaphore.h>
+ #include <asm/io.h>
+ #include <asm/uaccess.h>
+
+diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
+new file mode 100644
+index 0000000..4b75a16
+--- /dev/null
++++ b/drivers/xen/Kconfig
+@@ -0,0 +1,19 @@
++config XEN_BALLOON
++ bool "Xen memory balloon driver"
++ depends on XEN
++ default y
++ help
++ The balloon driver allows the Xen domain to request more memory from
++ the system to expand the domain's memory allocation, or alternatively
++ return unneeded memory to the system.
++
++config XEN_SCRUB_PAGES
++ bool "Scrub pages before returning them to system"
++ depends on XEN_BALLOON
++ default y
++ help
++ Scrub pages before returning them to the system for reuse by
++ other domains. This makes sure that any confidential data
++ is not accidentally visible to other domains. Is it more
++ secure, but slightly less efficient.
++ If in doubt, say yes.
+diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
+index 56592f0..37af04f 100644
+--- a/drivers/xen/Makefile
++++ b/drivers/xen/Makefile
+@@ -1,2 +1,4 @@
+-obj-y += grant-table.o
++obj-y += grant-table.o features.o events.o
+ obj-y += xenbus/
++obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
++obj-$(CONFIG_XEN_BALLOON) += balloon.o
+diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
+new file mode 100644
+index 0000000..ab25ba6
+--- /dev/null
++++ b/drivers/xen/balloon.c
+@@ -0,0 +1,712 @@
++/******************************************************************************
++ * balloon.c
++ *
++ * Xen balloon driver - enables returning/claiming memory to/from Xen.
++ *
++ * Copyright (c) 2003, B Dragovic
++ * Copyright (c) 2003-2004, M Williamson, K Fraser
++ * Copyright (c) 2005 Dan M. Smith, IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/mm.h>
++#include <linux/bootmem.h>
++#include <linux/pagemap.h>
++#include <linux/highmem.h>
++#include <linux/mutex.h>
++#include <linux/highmem.h>
++#include <linux/list.h>
++#include <linux/sysdev.h>
++
++#include <asm/xen/hypervisor.h>
++#include <asm/page.h>
++#include <asm/pgalloc.h>
++#include <asm/pgtable.h>
++#include <asm/uaccess.h>
++#include <asm/tlb.h>
++
++#include <xen/interface/memory.h>
++#include <xen/balloon.h>
++#include <xen/xenbus.h>
++#include <xen/features.h>
++#include <xen/page.h>
++
++#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
++
++#define BALLOON_CLASS_NAME "memory"
++
++struct balloon_stats {
++ /* We aim for 'current allocation' == 'target allocation'. */
++ unsigned long current_pages;
++ unsigned long target_pages;
++ /* We may hit the hard limit in Xen. If we do then we remember it. */
++ unsigned long hard_limit;
++ /*
++ * Drivers may alter the memory reservation independently, but they
++ * must inform the balloon driver so we avoid hitting the hard limit.
++ */
++ unsigned long driver_pages;
++ /* Number of pages in high- and low-memory balloons. */
++ unsigned long balloon_low;
++ unsigned long balloon_high;
++};
++
++static DEFINE_MUTEX(balloon_mutex);
++
++static struct sys_device balloon_sysdev;
++
++static int register_balloon(struct sys_device *sysdev);
++
++/*
++ * Protects atomic reservation decrease/increase against concurrent increases.
++ * Also protects non-atomic updates of current_pages and driver_pages, and
++ * balloon lists.
++ */
++static DEFINE_SPINLOCK(balloon_lock);
++
++static struct balloon_stats balloon_stats;
++
++/* We increase/decrease in batches which fit in a page */
++static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
++
++/* VM /proc information for memory */
++extern unsigned long totalram_pages;
++
++#ifdef CONFIG_HIGHMEM
++extern unsigned long totalhigh_pages;
++#define inc_totalhigh_pages() (totalhigh_pages++)
++#define dec_totalhigh_pages() (totalhigh_pages--)
++#else
++#define inc_totalhigh_pages() do {} while(0)
++#define dec_totalhigh_pages() do {} while(0)
++#endif
++
++/* List of ballooned pages, threaded through the mem_map array. */
++static LIST_HEAD(ballooned_pages);
++
++/* Main work function, always executed in process context. */
++static void balloon_process(struct work_struct *work);
++static DECLARE_WORK(balloon_worker, balloon_process);
++static struct timer_list balloon_timer;
++
++/* When ballooning out (allocating memory to return to Xen) we don't really
++ want the kernel to try too hard since that can trigger the oom killer. */
++#define GFP_BALLOON \
++ (GFP_HIGHUSER | __GFP_NOWARN | __GFP_NORETRY | __GFP_NOMEMALLOC)
++
++static void scrub_page(struct page *page)
++{
++#ifdef CONFIG_XEN_SCRUB_PAGES
++ if (PageHighMem(page)) {
++ void *v = kmap(page);
++ clear_page(v);
++ kunmap(v);
++ } else {
++ void *v = page_address(page);
++ clear_page(v);
++ }
++#endif
++}
++
++/* balloon_append: add the given page to the balloon. */
++static void balloon_append(struct page *page)
++{
++ /* Lowmem is re-populated first, so highmem pages go at list tail. */
++ if (PageHighMem(page)) {
++ list_add_tail(&page->lru, &ballooned_pages);
++ balloon_stats.balloon_high++;
++ dec_totalhigh_pages();
++ } else {
++ list_add(&page->lru, &ballooned_pages);
++ balloon_stats.balloon_low++;
++ }
++}
++
++/* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
++static struct page *balloon_retrieve(void)
++{
++ struct page *page;
++
++ if (list_empty(&ballooned_pages))
++ return NULL;
++
++ page = list_entry(ballooned_pages.next, struct page, lru);
++ list_del(&page->lru);
++
++ if (PageHighMem(page)) {
++ balloon_stats.balloon_high--;
++ inc_totalhigh_pages();
++ }
++ else
++ balloon_stats.balloon_low--;
++
++ return page;
++}
++
++static struct page *balloon_first_page(void)
++{
++ if (list_empty(&ballooned_pages))
++ return NULL;
++ return list_entry(ballooned_pages.next, struct page, lru);
++}
++
++static struct page *balloon_next_page(struct page *page)
++{
++ struct list_head *next = page->lru.next;
++ if (next == &ballooned_pages)
++ return NULL;
++ return list_entry(next, struct page, lru);
++}
++
++static void balloon_alarm(unsigned long unused)
++{
++ schedule_work(&balloon_worker);
++}
++
++static unsigned long current_target(void)
++{
++ unsigned long target = min(balloon_stats.target_pages, balloon_stats.hard_limit);
++
++ target = min(target,
++ balloon_stats.current_pages +
++ balloon_stats.balloon_low +
++ balloon_stats.balloon_high);
++
++ return target;
++}
++
++static int increase_reservation(unsigned long nr_pages)
++{
++ unsigned long pfn, i, flags;
++ struct page *page;
++ long rc;
++ struct xen_memory_reservation reservation = {
++ .address_bits = 0,
++ .extent_order = 0,
++ .domid = DOMID_SELF
++ };
++
++ if (nr_pages > ARRAY_SIZE(frame_list))
++ nr_pages = ARRAY_SIZE(frame_list);
++
++ spin_lock_irqsave(&balloon_lock, flags);
++
++ page = balloon_first_page();
++ for (i = 0; i < nr_pages; i++) {
++ BUG_ON(page == NULL);
++ frame_list[i] = page_to_pfn(page);;
++ page = balloon_next_page(page);
++ }
++
++ reservation.extent_start = (unsigned long)frame_list;
++ reservation.nr_extents = nr_pages;
++ rc = HYPERVISOR_memory_op(
++ XENMEM_populate_physmap, &reservation);
++ if (rc < nr_pages) {
++ if (rc > 0) {
++ int ret;
++
++ /* We hit the Xen hard limit: reprobe. */
++ reservation.nr_extents = rc;
++ ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
++ &reservation);
++ BUG_ON(ret != rc);
++ }
++ if (rc >= 0)
++ balloon_stats.hard_limit = (balloon_stats.current_pages + rc -
++ balloon_stats.driver_pages);
++ goto out;
++ }
++
++ for (i = 0; i < nr_pages; i++) {
++ page = balloon_retrieve();
++ BUG_ON(page == NULL);
++
++ pfn = page_to_pfn(page);
++ BUG_ON(!xen_feature(XENFEAT_auto_translated_physmap) &&
++ phys_to_machine_mapping_valid(pfn));
++
++ set_phys_to_machine(pfn, frame_list[i]);
++
++ /* Link back into the page tables if not highmem. */
++ if (pfn < max_low_pfn) {
++ int ret;
++ ret = HYPERVISOR_update_va_mapping(
++ (unsigned long)__va(pfn << PAGE_SHIFT),
++ mfn_pte(frame_list[i], PAGE_KERNEL),
++ 0);
++ BUG_ON(ret);
++ }
++
++ /* Relinquish the page back to the allocator. */
++ ClearPageReserved(page);
++ init_page_count(page);
++ __free_page(page);
++ }
++
++ balloon_stats.current_pages += nr_pages;
++ totalram_pages = balloon_stats.current_pages;
++
++ out:
++ spin_unlock_irqrestore(&balloon_lock, flags);
++
++ return 0;
++}
++
++static int decrease_reservation(unsigned long nr_pages)
++{
++ unsigned long pfn, i, flags;
++ struct page *page;
++ int need_sleep = 0;
++ int ret;
++ struct xen_memory_reservation reservation = {
++ .address_bits = 0,
++ .extent_order = 0,
++ .domid = DOMID_SELF
++ };
++
++ if (nr_pages > ARRAY_SIZE(frame_list))
++ nr_pages = ARRAY_SIZE(frame_list);
++
++ for (i = 0; i < nr_pages; i++) {
++ if ((page = alloc_page(GFP_BALLOON)) == NULL) {
++ nr_pages = i;
++ need_sleep = 1;
++ break;
++ }
++
++ pfn = page_to_pfn(page);
++ frame_list[i] = pfn_to_mfn(pfn);
++
++ scrub_page(page);
++ }
++
++ /* Ensure that ballooned highmem pages don't have kmaps. */
++ kmap_flush_unused();
++ flush_tlb_all();
++
++ spin_lock_irqsave(&balloon_lock, flags);
++
++ /* No more mappings: invalidate P2M and add to balloon. */
++ for (i = 0; i < nr_pages; i++) {
++ pfn = mfn_to_pfn(frame_list[i]);
++ set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
++ balloon_append(pfn_to_page(pfn));
++ }
++
++ reservation.extent_start = (unsigned long)frame_list;
++ reservation.nr_extents = nr_pages;
++ ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
++ BUG_ON(ret != nr_pages);
++
++ balloon_stats.current_pages -= nr_pages;
++ totalram_pages = balloon_stats.current_pages;
++
++ spin_unlock_irqrestore(&balloon_lock, flags);
++
++ return need_sleep;
++}
++
++/*
++ * We avoid multiple worker processes conflicting via the balloon mutex.
++ * We may of course race updates of the target counts (which are protected
++ * by the balloon lock), or with changes to the Xen hard limit, but we will
++ * recover from these in time.
++ */
++static void balloon_process(struct work_struct *work)
++{
++ int need_sleep = 0;
++ long credit;
++
++ mutex_lock(&balloon_mutex);
++
++ do {
++ credit = current_target() - balloon_stats.current_pages;
++ if (credit > 0)
++ need_sleep = (increase_reservation(credit) != 0);
++ if (credit < 0)
++ need_sleep = (decrease_reservation(-credit) != 0);
++
++#ifndef CONFIG_PREEMPT
++ if (need_resched())
++ schedule();
++#endif
++ } while ((credit != 0) && !need_sleep);
++
++ /* Schedule more work if there is some still to be done. */
++ if (current_target() != balloon_stats.current_pages)
++ mod_timer(&balloon_timer, jiffies + HZ);
++
++ mutex_unlock(&balloon_mutex);
++}
++
++/* Resets the Xen limit, sets new target, and kicks off processing. */
++void balloon_set_new_target(unsigned long target)
++{
++ /* No need for lock. Not read-modify-write updates. */
++ balloon_stats.hard_limit = ~0UL;
++ balloon_stats.target_pages = target;
++ schedule_work(&balloon_worker);
++}
++
++static struct xenbus_watch target_watch =
++{
++ .node = "memory/target"
++};
++
++/* React to a change in the target key */
++static void watch_target(struct xenbus_watch *watch,
++ const char **vec, unsigned int len)
++{
++ unsigned long long new_target;
++ int err;
++
++ err = xenbus_scanf(XBT_NIL, "memory", "target", "%llu", &new_target);
++ if (err != 1) {
++ /* This is ok (for domain0 at least) - so just return */
++ return;
++ }
++
++ /* The given memory/target value is in KiB, so it needs converting to
++ * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10.
++ */
++ balloon_set_new_target(new_target >> (PAGE_SHIFT - 10));
++}
++
++static int balloon_init_watcher(struct notifier_block *notifier,
++ unsigned long event,
++ void *data)
++{
++ int err;
++
++ err = register_xenbus_watch(&target_watch);
++ if (err)
++ printk(KERN_ERR "Failed to set balloon watcher\n");
++
++ return NOTIFY_DONE;
++}
++
++static struct notifier_block xenstore_notifier;
++
++static int __init balloon_init(void)
++{
++ unsigned long pfn;
++ struct page *page;
++
++ if (!is_running_on_xen())
++ return -ENODEV;
++
++ pr_info("xen_balloon: Initialising balloon driver.\n");
++
++ balloon_stats.current_pages = min(xen_start_info->nr_pages, max_pfn);
++ totalram_pages = balloon_stats.current_pages;
++ balloon_stats.target_pages = balloon_stats.current_pages;
++ balloon_stats.balloon_low = 0;
++ balloon_stats.balloon_high = 0;
++ balloon_stats.driver_pages = 0UL;
++ balloon_stats.hard_limit = ~0UL;
++
++ init_timer(&balloon_timer);
++ balloon_timer.data = 0;
++ balloon_timer.function = balloon_alarm;
++
++ register_balloon(&balloon_sysdev);
++
++ /* Initialise the balloon with excess memory space. */
++ for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
++ page = pfn_to_page(pfn);
++ if (!PageReserved(page))
++ balloon_append(page);
++ }
++
++ target_watch.callback = watch_target;
++ xenstore_notifier.notifier_call = balloon_init_watcher;
++
++ register_xenstore_notifier(&xenstore_notifier);
++
++ return 0;
++}
++
++subsys_initcall(balloon_init);
++
++static void balloon_exit(void)
++{
++ /* XXX - release balloon here */
++ return;
++}
++
++module_exit(balloon_exit);
++
++static void balloon_update_driver_allowance(long delta)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&balloon_lock, flags);
++ balloon_stats.driver_pages += delta;
++ spin_unlock_irqrestore(&balloon_lock, flags);
++}
++
++static int dealloc_pte_fn(
++ pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
++{
++ unsigned long mfn = pte_mfn(*pte);
++ int ret;
++ struct xen_memory_reservation reservation = {
++ .nr_extents = 1,
++ .extent_order = 0,
++ .domid = DOMID_SELF
++ };
++ reservation.extent_start = (unsigned long)&mfn;
++ set_pte_at(&init_mm, addr, pte, __pte_ma(0ull));
++ set_phys_to_machine(__pa(addr) >> PAGE_SHIFT, INVALID_P2M_ENTRY);
++ ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
++ BUG_ON(ret != 1);
++ return 0;
++}
++
++static struct page **alloc_empty_pages_and_pagevec(int nr_pages)
++{
++ unsigned long vaddr, flags;
++ struct page *page, **pagevec;
++ int i, ret;
++
++ pagevec = kmalloc(sizeof(page) * nr_pages, GFP_KERNEL);
++ if (pagevec == NULL)
++ return NULL;
++
++ for (i = 0; i < nr_pages; i++) {
++ page = pagevec[i] = alloc_page(GFP_KERNEL);
++ if (page == NULL)
++ goto err;
++
++ vaddr = (unsigned long)page_address(page);
++
++ scrub_page(page);
++
++ spin_lock_irqsave(&balloon_lock, flags);
++
++ if (xen_feature(XENFEAT_auto_translated_physmap)) {
++ unsigned long gmfn = page_to_pfn(page);
++ struct xen_memory_reservation reservation = {
++ .nr_extents = 1,
++ .extent_order = 0,
++ .domid = DOMID_SELF
++ };
++ reservation.extent_start = (unsigned long)&gmfn;
++ ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
++ &reservation);
++ if (ret == 1)
++ ret = 0; /* success */
++ } else {
++ ret = apply_to_page_range(&init_mm, vaddr, PAGE_SIZE,
++ dealloc_pte_fn, NULL);
++ }
++
++ if (ret != 0) {
++ spin_unlock_irqrestore(&balloon_lock, flags);
++ __free_page(page);
++ goto err;
++ }
++
++ totalram_pages = --balloon_stats.current_pages;
++
++ spin_unlock_irqrestore(&balloon_lock, flags);
++ }
++
++ out:
++ schedule_work(&balloon_worker);
++ flush_tlb_all();
++ return pagevec;
++
++ err:
++ spin_lock_irqsave(&balloon_lock, flags);
++ while (--i >= 0)
++ balloon_append(pagevec[i]);
++ spin_unlock_irqrestore(&balloon_lock, flags);
++ kfree(pagevec);
++ pagevec = NULL;
++ goto out;
++}
++
++static void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages)
++{
++ unsigned long flags;
++ int i;
++
++ if (pagevec == NULL)
++ return;
++
++ spin_lock_irqsave(&balloon_lock, flags);
++ for (i = 0; i < nr_pages; i++) {
++ BUG_ON(page_count(pagevec[i]) != 1);
++ balloon_append(pagevec[i]);
++ }
++ spin_unlock_irqrestore(&balloon_lock, flags);
++
++ kfree(pagevec);
++
++ schedule_work(&balloon_worker);
++}
++
++static void balloon_release_driver_page(struct page *page)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&balloon_lock, flags);
++ balloon_append(page);
++ balloon_stats.driver_pages--;
++ spin_unlock_irqrestore(&balloon_lock, flags);
++
++ schedule_work(&balloon_worker);
++}
++
++
++#define BALLOON_SHOW(name, format, args...) \
++ static ssize_t show_##name(struct sys_device *dev, \
++ char *buf) \
++ { \
++ return sprintf(buf, format, ##args); \
++ } \
++ static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL)
++
++BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages));
++BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low));
++BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high));
++BALLOON_SHOW(hard_limit_kb,
++ (balloon_stats.hard_limit!=~0UL) ? "%lu\n" : "???\n",
++ (balloon_stats.hard_limit!=~0UL) ? PAGES2KB(balloon_stats.hard_limit) : 0);
++BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages));
++
++static ssize_t show_target_kb(struct sys_device *dev, char *buf)
++{
++ return sprintf(buf, "%lu\n", PAGES2KB(balloon_stats.target_pages));
++}
++
++static ssize_t store_target_kb(struct sys_device *dev,
++ const char *buf,
++ size_t count)
++{
++ char memstring[64], *endchar;
++ unsigned long long target_bytes;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ if (count <= 1)
++ return -EBADMSG; /* runt */
++ if (count > sizeof(memstring))
++ return -EFBIG; /* too long */
++ strcpy(memstring, buf);
++
++ target_bytes = memparse(memstring, &endchar);
++ balloon_set_new_target(target_bytes >> PAGE_SHIFT);
++
++ return count;
++}
++
++static SYSDEV_ATTR(target_kb, S_IRUGO | S_IWUSR,
++ show_target_kb, store_target_kb);
++
++static struct sysdev_attribute *balloon_attrs[] = {
++ &attr_target_kb,
++};
++
++static struct attribute *balloon_info_attrs[] = {
++ &attr_current_kb.attr,
++ &attr_low_kb.attr,
++ &attr_high_kb.attr,
++ &attr_hard_limit_kb.attr,
++ &attr_driver_kb.attr,
++ NULL
++};
++
++static struct attribute_group balloon_info_group = {
++ .name = "info",
++ .attrs = balloon_info_attrs,
++};
++
++static struct sysdev_class balloon_sysdev_class = {
++ .name = BALLOON_CLASS_NAME,
++};
++
++static int register_balloon(struct sys_device *sysdev)
++{
++ int i, error;
++
++ error = sysdev_class_register(&balloon_sysdev_class);
++ if (error)
++ return error;
++
++ sysdev->id = 0;
++ sysdev->cls = &balloon_sysdev_class;
++
++ error = sysdev_register(sysdev);
++ if (error) {
++ sysdev_class_unregister(&balloon_sysdev_class);
++ return error;
++ }
++
++ for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++) {
++ error = sysdev_create_file(sysdev, balloon_attrs[i]);
++ if (error)
++ goto fail;
++ }
++
++ error = sysfs_create_group(&sysdev->kobj, &balloon_info_group);
++ if (error)
++ goto fail;
++
++ return 0;
++
++ fail:
++ while (--i >= 0)
++ sysdev_remove_file(sysdev, balloon_attrs[i]);
++ sysdev_unregister(sysdev);
++ sysdev_class_unregister(&balloon_sysdev_class);
++ return error;
++}
++
++static void unregister_balloon(struct sys_device *sysdev)
++{
++ int i;
++
++ sysfs_remove_group(&sysdev->kobj, &balloon_info_group);
++ for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++)
++ sysdev_remove_file(sysdev, balloon_attrs[i]);
++ sysdev_unregister(sysdev);
++ sysdev_class_unregister(&balloon_sysdev_class);
++}
++
++static void balloon_sysfs_exit(void)
++{
++ unregister_balloon(&balloon_sysdev);
++}
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/xen/events.c b/drivers/xen/events.c
+new file mode 100644
+index 0000000..4f0f22b
+--- /dev/null
++++ b/drivers/xen/events.c
+@@ -0,0 +1,674 @@
++/*
++ * Xen event channels
++ *
++ * Xen models interrupts with abstract event channels. Because each
++ * domain gets 1024 event channels, but NR_IRQ is not that large, we
++ * must dynamically map irqs<->event channels. The event channels
++ * interface with the rest of the kernel by defining a xen interrupt
++ * chip. When an event is recieved, it is mapped to an irq and sent
++ * through the normal interrupt processing path.
++ *
++ * There are four kinds of events which can be mapped to an event
++ * channel:
++ *
++ * 1. Inter-domain notifications. This includes all the virtual
++ * device events, since they're driven by front-ends in another domain
++ * (typically dom0).
++ * 2. VIRQs, typically used for timers. These are per-cpu events.
++ * 3. IPIs.
++ * 4. Hardware interrupts. Not supported at present.
++ *
++ * Jeremy Fitzhardinge <jeremy at xensource.com>, XenSource Inc, 2007
++ */
++
++#include <linux/linkage.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/module.h>
++#include <linux/string.h>
++
++#include <asm/ptrace.h>
++#include <asm/irq.h>
++#include <asm/sync_bitops.h>
++#include <asm/xen/hypercall.h>
++#include <asm/xen/hypervisor.h>
++
++#include <xen/xen-ops.h>
++#include <xen/events.h>
++#include <xen/interface/xen.h>
++#include <xen/interface/event_channel.h>
++
++/*
++ * This lock protects updates to the following mapping and reference-count
++ * arrays. The lock does not need to be acquired to read the mapping tables.
++ */
++static DEFINE_SPINLOCK(irq_mapping_update_lock);
++
++/* IRQ <-> VIRQ mapping. */
++static DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1};
++
++/* IRQ <-> IPI mapping */
++static DEFINE_PER_CPU(int, ipi_to_irq[XEN_NR_IPIS]) = {[0 ... XEN_NR_IPIS-1] = -1};
++
++/* Packed IRQ information: binding type, sub-type index, and event channel. */
++struct packed_irq
++{
++ unsigned short evtchn;
++ unsigned char index;
++ unsigned char type;
++};
++
++static struct packed_irq irq_info[NR_IRQS];
++
++/* Binding types. */
++enum {
++ IRQT_UNBOUND,
++ IRQT_PIRQ,
++ IRQT_VIRQ,
++ IRQT_IPI,
++ IRQT_EVTCHN
++};
++
++/* Convenient shorthand for packed representation of an unbound IRQ. */
++#define IRQ_UNBOUND mk_irq_info(IRQT_UNBOUND, 0, 0)
++
++static int evtchn_to_irq[NR_EVENT_CHANNELS] = {
++ [0 ... NR_EVENT_CHANNELS-1] = -1
++};
++static unsigned long cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/BITS_PER_LONG];
++static u8 cpu_evtchn[NR_EVENT_CHANNELS];
++
++/* Reference counts for bindings to IRQs. */
++static int irq_bindcount[NR_IRQS];
++
++/* Xen will never allocate port zero for any purpose. */
++#define VALID_EVTCHN(chn) ((chn) != 0)
++
++/*
++ * Force a proper event-channel callback from Xen after clearing the
++ * callback mask. We do this in a very simple manner, by making a call
++ * down into Xen. The pending flag will be checked by Xen on return.
++ */
++void force_evtchn_callback(void)
++{
++ (void)HYPERVISOR_xen_version(0, NULL);
++}
++EXPORT_SYMBOL_GPL(force_evtchn_callback);
++
++static struct irq_chip xen_dynamic_chip;
++
++/* Constructor for packed IRQ information. */
++static inline struct packed_irq mk_irq_info(u32 type, u32 index, u32 evtchn)
++{
++ return (struct packed_irq) { evtchn, index, type };
++}
++
++/*
++ * Accessors for packed IRQ information.
++ */
++static inline unsigned int evtchn_from_irq(int irq)
++{
++ return irq_info[irq].evtchn;
++}
++
++static inline unsigned int index_from_irq(int irq)
++{
++ return irq_info[irq].index;
++}
++
++static inline unsigned int type_from_irq(int irq)
++{
++ return irq_info[irq].type;
++}
++
++static inline unsigned long active_evtchns(unsigned int cpu,
++ struct shared_info *sh,
++ unsigned int idx)
++{
++ return (sh->evtchn_pending[idx] &
++ cpu_evtchn_mask[cpu][idx] &
++ ~sh->evtchn_mask[idx]);
++}
++
++static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
++{
++ int irq = evtchn_to_irq[chn];
++
++ BUG_ON(irq == -1);
++#ifdef CONFIG_SMP
++ irq_desc[irq].affinity = cpumask_of_cpu(cpu);
++#endif
++
++ __clear_bit(chn, cpu_evtchn_mask[cpu_evtchn[chn]]);
++ __set_bit(chn, cpu_evtchn_mask[cpu]);
++
++ cpu_evtchn[chn] = cpu;
++}
++
++static void init_evtchn_cpu_bindings(void)
++{
++#ifdef CONFIG_SMP
++ int i;
++ /* By default all event channels notify CPU#0. */
++ for (i = 0; i < NR_IRQS; i++)
++ irq_desc[i].affinity = cpumask_of_cpu(0);
++#endif
++
++ memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
++ memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0]));
++}
++
++static inline unsigned int cpu_from_evtchn(unsigned int evtchn)
++{
++ return cpu_evtchn[evtchn];
++}
++
++static inline void clear_evtchn(int port)
++{
++ struct shared_info *s = HYPERVISOR_shared_info;
++ sync_clear_bit(port, &s->evtchn_pending[0]);
++}
++
++static inline void set_evtchn(int port)
++{
++ struct shared_info *s = HYPERVISOR_shared_info;
++ sync_set_bit(port, &s->evtchn_pending[0]);
++}
++
++
++/**
++ * notify_remote_via_irq - send event to remote end of event channel via irq
++ * @irq: irq of event channel to send event to
++ *
++ * Unlike notify_remote_via_evtchn(), this is safe to use across
++ * save/restore. Notifications on a broken connection are silently
++ * dropped.
++ */
++void notify_remote_via_irq(int irq)
++{
++ int evtchn = evtchn_from_irq(irq);
++
++ if (VALID_EVTCHN(evtchn))
++ notify_remote_via_evtchn(evtchn);
++}
++EXPORT_SYMBOL_GPL(notify_remote_via_irq);
++
++static void mask_evtchn(int port)
++{
++ struct shared_info *s = HYPERVISOR_shared_info;
++ sync_set_bit(port, &s->evtchn_mask[0]);
++}
++
++static void unmask_evtchn(int port)
++{
++ struct shared_info *s = HYPERVISOR_shared_info;
++ unsigned int cpu = get_cpu();
++
++ BUG_ON(!irqs_disabled());
++
++ /* Slow path (hypercall) if this is a non-local port. */
++ if (unlikely(cpu != cpu_from_evtchn(port))) {
++ struct evtchn_unmask unmask = { .port = port };
++ (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask);
++ } else {
++ struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
++
++ sync_clear_bit(port, &s->evtchn_mask[0]);
++
++ /*
++ * The following is basically the equivalent of
++ * 'hw_resend_irq'. Just like a real IO-APIC we 'lose
++ * the interrupt edge' if the channel is masked.
++ */
++ if (sync_test_bit(port, &s->evtchn_pending[0]) &&
++ !sync_test_and_set_bit(port / BITS_PER_LONG,
++ &vcpu_info->evtchn_pending_sel))
++ vcpu_info->evtchn_upcall_pending = 1;
++ }
++
++ put_cpu();
++}
++
++static int find_unbound_irq(void)
++{
++ int irq;
++
++ /* Only allocate from dynirq range */
++ for (irq = 0; irq < NR_IRQS; irq++)
++ if (irq_bindcount[irq] == 0)
++ break;
++
++ if (irq == NR_IRQS)
++ panic("No available IRQ to bind to: increase NR_IRQS!\n");
++
++ return irq;
++}
++
++int bind_evtchn_to_irq(unsigned int evtchn)
++{
++ int irq;
++
++ spin_lock(&irq_mapping_update_lock);
++
++ irq = evtchn_to_irq[evtchn];
++
++ if (irq == -1) {
++ irq = find_unbound_irq();
++
++ dynamic_irq_init(irq);
++ set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
++ handle_level_irq, "event");
++
++ evtchn_to_irq[evtchn] = irq;
++ irq_info[irq] = mk_irq_info(IRQT_EVTCHN, 0, evtchn);
++ }
++
++ irq_bindcount[irq]++;
++
++ spin_unlock(&irq_mapping_update_lock);
++
++ return irq;
++}
++EXPORT_SYMBOL_GPL(bind_evtchn_to_irq);
++
++static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
++{
++ struct evtchn_bind_ipi bind_ipi;
++ int evtchn, irq;
++
++ spin_lock(&irq_mapping_update_lock);
++
++ irq = per_cpu(ipi_to_irq, cpu)[ipi];
++ if (irq == -1) {
++ irq = find_unbound_irq();
++ if (irq < 0)
++ goto out;
++
++ dynamic_irq_init(irq);
++ set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
++ handle_level_irq, "ipi");
++
++ bind_ipi.vcpu = cpu;
++ if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
++ &bind_ipi) != 0)
++ BUG();
++ evtchn = bind_ipi.port;
++
++ evtchn_to_irq[evtchn] = irq;
++ irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
++
++ per_cpu(ipi_to_irq, cpu)[ipi] = irq;
++
++ bind_evtchn_to_cpu(evtchn, cpu);
++ }
++
++ irq_bindcount[irq]++;
++
++ out:
++ spin_unlock(&irq_mapping_update_lock);
++ return irq;
++}
++
++
++static int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
++{
++ struct evtchn_bind_virq bind_virq;
++ int evtchn, irq;
++
++ spin_lock(&irq_mapping_update_lock);
++
++ irq = per_cpu(virq_to_irq, cpu)[virq];
++
++ if (irq == -1) {
++ bind_virq.virq = virq;
++ bind_virq.vcpu = cpu;
++ if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
++ &bind_virq) != 0)
++ BUG();
++ evtchn = bind_virq.port;
++
++ irq = find_unbound_irq();
++
++ dynamic_irq_init(irq);
++ set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
++ handle_level_irq, "virq");
++
++ evtchn_to_irq[evtchn] = irq;
++ irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
++
++ per_cpu(virq_to_irq, cpu)[virq] = irq;
++
++ bind_evtchn_to_cpu(evtchn, cpu);
++ }
++
++ irq_bindcount[irq]++;
++
++ spin_unlock(&irq_mapping_update_lock);
++
++ return irq;
++}
++
++static void unbind_from_irq(unsigned int irq)
++{
++ struct evtchn_close close;
++ int evtchn = evtchn_from_irq(irq);
++
++ spin_lock(&irq_mapping_update_lock);
++
++ if (VALID_EVTCHN(evtchn) && (--irq_bindcount[irq] == 0)) {
++ close.port = evtchn;
++ if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
++ BUG();
++
++ switch (type_from_irq(irq)) {
++ case IRQT_VIRQ:
++ per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
++ [index_from_irq(irq)] = -1;
++ break;
++ default:
++ break;
++ }
++
++ /* Closed ports are implicitly re-bound to VCPU0. */
++ bind_evtchn_to_cpu(evtchn, 0);
++
++ evtchn_to_irq[evtchn] = -1;
++ irq_info[irq] = IRQ_UNBOUND;
++
++ dynamic_irq_init(irq);
++ }
++
++ spin_unlock(&irq_mapping_update_lock);
++}
++
++int bind_evtchn_to_irqhandler(unsigned int evtchn,
++ irq_handler_t handler,
++ unsigned long irqflags,
++ const char *devname, void *dev_id)
++{
++ unsigned int irq;
++ int retval;
++
++ irq = bind_evtchn_to_irq(evtchn);
++ retval = request_irq(irq, handler, irqflags, devname, dev_id);
++ if (retval != 0) {
++ unbind_from_irq(irq);
++ return retval;
++ }
++
++ return irq;
++}
++EXPORT_SYMBOL_GPL(bind_evtchn_to_irqhandler);
++
++int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
++ irq_handler_t handler,
++ unsigned long irqflags, const char *devname, void *dev_id)
++{
++ unsigned int irq;
++ int retval;
++
++ irq = bind_virq_to_irq(virq, cpu);
++ retval = request_irq(irq, handler, irqflags, devname, dev_id);
++ if (retval != 0) {
++ unbind_from_irq(irq);
++ return retval;
++ }
++
++ return irq;
++}
++EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler);
++
++int bind_ipi_to_irqhandler(enum ipi_vector ipi,
++ unsigned int cpu,
++ irq_handler_t handler,
++ unsigned long irqflags,
++ const char *devname,
++ void *dev_id)
++{
++ int irq, retval;
++
++ irq = bind_ipi_to_irq(ipi, cpu);
++ if (irq < 0)
++ return irq;
++
++ retval = request_irq(irq, handler, irqflags, devname, dev_id);
++ if (retval != 0) {
++ unbind_from_irq(irq);
++ return retval;
++ }
++
++ return irq;
++}
++
++void unbind_from_irqhandler(unsigned int irq, void *dev_id)
++{
++ free_irq(irq, dev_id);
++ unbind_from_irq(irq);
++}
++EXPORT_SYMBOL_GPL(unbind_from_irqhandler);
++
++void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector)
++{
++ int irq = per_cpu(ipi_to_irq, cpu)[vector];
++ BUG_ON(irq < 0);
++ notify_remote_via_irq(irq);
++}
++
++irqreturn_t xen_debug_interrupt(int irq, void *dev_id)
++{
++ struct shared_info *sh = HYPERVISOR_shared_info;
++ int cpu = smp_processor_id();
++ int i;
++ unsigned long flags;
++ static DEFINE_SPINLOCK(debug_lock);
++
++ spin_lock_irqsave(&debug_lock, flags);
++
++ printk("vcpu %d\n ", cpu);
++
++ for_each_online_cpu(i) {
++ struct vcpu_info *v = per_cpu(xen_vcpu, i);
++ printk("%d: masked=%d pending=%d event_sel %08lx\n ", i,
++ (get_irq_regs() && i == cpu) ? xen_irqs_disabled(get_irq_regs()) : v->evtchn_upcall_mask,
++ v->evtchn_upcall_pending,
++ v->evtchn_pending_sel);
++ }
++ printk("pending:\n ");
++ for(i = ARRAY_SIZE(sh->evtchn_pending)-1; i >= 0; i--)
++ printk("%08lx%s", sh->evtchn_pending[i],
++ i % 8 == 0 ? "\n " : " ");
++ printk("\nmasks:\n ");
++ for(i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--)
++ printk("%08lx%s", sh->evtchn_mask[i],
++ i % 8 == 0 ? "\n " : " ");
++
++ printk("\nunmasked:\n ");
++ for(i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--)
++ printk("%08lx%s", sh->evtchn_pending[i] & ~sh->evtchn_mask[i],
++ i % 8 == 0 ? "\n " : " ");
++
++ printk("\npending list:\n");
++ for(i = 0; i < NR_EVENT_CHANNELS; i++) {
++ if (sync_test_bit(i, sh->evtchn_pending)) {
++ printk(" %d: event %d -> irq %d\n",
++ cpu_evtchn[i], i,
++ evtchn_to_irq[i]);
++ }
++ }
++
++ spin_unlock_irqrestore(&debug_lock, flags);
++
++ return IRQ_HANDLED;
++}
++
++
++/*
++ * Search the CPUs pending events bitmasks. For each one found, map
++ * the event number to an irq, and feed it into do_IRQ() for
++ * handling.
++ *
++ * Xen uses a two-level bitmap to speed searching. The first level is
++ * a bitset of words which contain pending event bits. The second
++ * level is a bitset of pending events themselves.
++ */
++void xen_evtchn_do_upcall(struct pt_regs *regs)
++{
++ int cpu = get_cpu();
++ struct shared_info *s = HYPERVISOR_shared_info;
++ struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
++ static DEFINE_PER_CPU(unsigned, nesting_count);
++ unsigned count;
++
++ do {
++ unsigned long pending_words;
++
++ vcpu_info->evtchn_upcall_pending = 0;
++
++ if (__get_cpu_var(nesting_count)++)
++ goto out;
++
++#ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
++ /* Clear master flag /before/ clearing selector flag. */
++ rmb();
++#endif
++ pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0);
++ while (pending_words != 0) {
++ unsigned long pending_bits;
++ int word_idx = __ffs(pending_words);
++ pending_words &= ~(1UL << word_idx);
++
++ while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) {
++ int bit_idx = __ffs(pending_bits);
++ int port = (word_idx * BITS_PER_LONG) + bit_idx;
++ int irq = evtchn_to_irq[port];
++
++ if (irq != -1)
++ xen_do_IRQ(irq, regs);
++ }
++ }
++
++ BUG_ON(!irqs_disabled());
++
++ count = __get_cpu_var(nesting_count);
++ __get_cpu_var(nesting_count) = 0;
++ } while(count != 1);
++
++out:
++ put_cpu();
++}
++
++/* Rebind an evtchn so that it gets delivered to a specific cpu */
++static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
++{
++ struct evtchn_bind_vcpu bind_vcpu;
++ int evtchn = evtchn_from_irq(irq);
++
++ if (!VALID_EVTCHN(evtchn))
++ return;
++
++ /* Send future instances of this interrupt to other vcpu. */
++ bind_vcpu.port = evtchn;
++ bind_vcpu.vcpu = tcpu;
++
++ /*
++ * If this fails, it usually just indicates that we're dealing with a
++ * virq or IPI channel, which don't actually need to be rebound. Ignore
++ * it, but don't do the xenlinux-level rebind in that case.
++ */
++ if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
++ bind_evtchn_to_cpu(evtchn, tcpu);
++}
++
++
++static void set_affinity_irq(unsigned irq, cpumask_t dest)
++{
++ unsigned tcpu = first_cpu(dest);
++ rebind_irq_to_cpu(irq, tcpu);
++}
++
++int resend_irq_on_evtchn(unsigned int irq)
++{
++ int masked, evtchn = evtchn_from_irq(irq);
++ struct shared_info *s = HYPERVISOR_shared_info;
++
++ if (!VALID_EVTCHN(evtchn))
++ return 1;
++
++ masked = sync_test_and_set_bit(evtchn, s->evtchn_mask);
++ sync_set_bit(evtchn, s->evtchn_pending);
++ if (!masked)
++ unmask_evtchn(evtchn);
++
++ return 1;
++}
++
++static void enable_dynirq(unsigned int irq)
++{
++ int evtchn = evtchn_from_irq(irq);
++
++ if (VALID_EVTCHN(evtchn))
++ unmask_evtchn(evtchn);
++}
++
++static void disable_dynirq(unsigned int irq)
++{
++ int evtchn = evtchn_from_irq(irq);
++
++ if (VALID_EVTCHN(evtchn))
++ mask_evtchn(evtchn);
++}
++
++static void ack_dynirq(unsigned int irq)
++{
++ int evtchn = evtchn_from_irq(irq);
++
++ move_native_irq(irq);
++
++ if (VALID_EVTCHN(evtchn))
++ clear_evtchn(evtchn);
++}
++
++static int retrigger_dynirq(unsigned int irq)
++{
++ int evtchn = evtchn_from_irq(irq);
++ struct shared_info *sh = HYPERVISOR_shared_info;
++ int ret = 0;
++
++ if (VALID_EVTCHN(evtchn)) {
++ int masked;
++
++ masked = sync_test_and_set_bit(evtchn, sh->evtchn_mask);
++ sync_set_bit(evtchn, sh->evtchn_pending);
++ if (!masked)
++ unmask_evtchn(evtchn);
++ ret = 1;
++ }
++
++ return ret;
++}
++
++static struct irq_chip xen_dynamic_chip __read_mostly = {
++ .name = "xen-dyn",
++ .mask = disable_dynirq,
++ .unmask = enable_dynirq,
++ .ack = ack_dynirq,
++ .set_affinity = set_affinity_irq,
++ .retrigger = retrigger_dynirq,
++};
++
++void __init xen_init_IRQ(void)
++{
++ int i;
++
++ init_evtchn_cpu_bindings();
++
++ /* No event channels are 'live' right now. */
++ for (i = 0; i < NR_EVENT_CHANNELS; i++)
++ mask_evtchn(i);
++
++ /* Dynamic IRQ space is currently unbound. Zero the refcnts. */
++ for (i = 0; i < NR_IRQS; i++)
++ irq_bindcount[i] = 0;
++
++ irq_ctx_init(smp_processor_id());
++}
+diff --git a/drivers/xen/features.c b/drivers/xen/features.c
+new file mode 100644
+index 0000000..0707714
+--- /dev/null
++++ b/drivers/xen/features.c
+@@ -0,0 +1,29 @@
++/******************************************************************************
++ * features.c
++ *
++ * Xen feature flags.
++ *
++ * Copyright (c) 2006, Ian Campbell, XenSource Inc.
++ */
++#include <linux/types.h>
++#include <linux/cache.h>
++#include <linux/module.h>
++#include <asm/xen/hypervisor.h>
++#include <xen/features.h>
++
++u8 xen_features[XENFEAT_NR_SUBMAPS * 32] __read_mostly;
++EXPORT_SYMBOL_GPL(xen_features);
++
++void xen_setup_features(void)
++{
++ struct xen_feature_info fi;
++ int i, j;
++
++ for (i = 0; i < XENFEAT_NR_SUBMAPS; i++) {
++ fi.submap_idx = i;
++ if (HYPERVISOR_xen_version(XENVER_get_features, &fi) < 0)
++ break;
++ for (j = 0; j < 32; j++)
++ xen_features[i * 32 + j] = !!(fi.submap & 1<<j);
++ }
++}
+diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
+index d85dc6d..52b6b41 100644
+--- a/drivers/xen/grant-table.c
++++ b/drivers/xen/grant-table.c
+@@ -439,24 +439,6 @@ static inline unsigned int max_nr_grant_frames(void)
+ return xen_max;
+ }
+
+-static int map_pte_fn(pte_t *pte, struct page *pmd_page,
+- unsigned long addr, void *data)
+-{
+- unsigned long **frames = (unsigned long **)data;
+-
+- set_pte_at(&init_mm, addr, pte, mfn_pte((*frames)[0], PAGE_KERNEL));
+- (*frames)++;
+- return 0;
+-}
+-
+-static int unmap_pte_fn(pte_t *pte, struct page *pmd_page,
+- unsigned long addr, void *data)
+-{
+-
+- set_pte_at(&init_mm, addr, pte, __pte(0));
+- return 0;
+-}
+-
+ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+ {
+ struct gnttab_setup_table setup;
+@@ -470,7 +452,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+
+ setup.dom = DOMID_SELF;
+ setup.nr_frames = nr_gframes;
+- setup.frame_list = frames;
++ set_xen_guest_handle(setup.frame_list, frames);
+
+ rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
+ if (rc == -ENOSYS) {
+@@ -480,17 +462,9 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+
+ BUG_ON(rc || setup.status);
+
+- if (shared == NULL) {
+- struct vm_struct *area;
+- area = alloc_vm_area(PAGE_SIZE * max_nr_grant_frames());
+- BUG_ON(area == NULL);
+- shared = area->addr;
+- }
+- rc = apply_to_page_range(&init_mm, (unsigned long)shared,
+- PAGE_SIZE * nr_gframes,
+- map_pte_fn, &frames);
++ rc = arch_gnttab_map_shared(frames, nr_gframes, max_nr_grant_frames(),
++ &shared);
+ BUG_ON(rc);
+- frames -= nr_gframes; /* adjust after map_pte_fn() */
+
+ kfree(frames);
+
+@@ -506,10 +480,7 @@ static int gnttab_resume(void)
+
+ static int gnttab_suspend(void)
+ {
+- apply_to_page_range(&init_mm, (unsigned long)shared,
+- PAGE_SIZE * nr_grant_frames,
+- unmap_pte_fn, NULL);
+-
++ arch_gnttab_unmap_shared(shared, nr_grant_frames);
+ return 0;
+ }
+
+diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
+index 9fd2f70..0f86b0f 100644
+--- a/drivers/xen/xenbus/xenbus_client.c
++++ b/drivers/xen/xenbus/xenbus_client.c
+@@ -399,7 +399,7 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
+
+ *vaddr = NULL;
+
+- area = alloc_vm_area(PAGE_SIZE);
++ area = xen_alloc_vm_area(PAGE_SIZE);
+ if (!area)
+ return -ENOMEM;
+
+@@ -409,7 +409,7 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
+ BUG();
+
+ if (op.status != GNTST_okay) {
+- free_vm_area(area);
++ xen_free_vm_area(area);
+ xenbus_dev_fatal(dev, op.status,
+ "mapping in shared page %d from domain %d",
+ gnt_ref, dev->otherend_id);
+@@ -508,7 +508,7 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
+ BUG();
+
+ if (op.status == GNTST_okay)
+- free_vm_area(area);
++ xen_free_vm_area(area);
+ else
+ xenbus_dev_error(dev, op.status,
+ "unmapping page at handle %d error %d",
+diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
+index 4750de3..57ceb53 100644
+--- a/drivers/xen/xenbus/xenbus_probe.c
++++ b/drivers/xen/xenbus/xenbus_probe.c
+@@ -88,6 +88,16 @@ int xenbus_match(struct device *_dev, struct device_driver *_drv)
+ return match_device(drv->ids, to_xenbus_device(_dev)) != NULL;
+ }
+
++static int xenbus_uevent(struct device *_dev, struct kobj_uevent_env *env)
++{
++ struct xenbus_device *dev = to_xenbus_device(_dev);
++
++ if (add_uevent_var(env, "MODALIAS=xen:%s", dev->devicetype))
++ return -ENOMEM;
++
++ return 0;
++}
++
+ /* device/<type>/<id> => <type>-<id> */
+ static int frontend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
+ {
+@@ -166,6 +176,7 @@ static struct xen_bus_type xenbus_frontend = {
+ .bus = {
+ .name = "xen",
+ .match = xenbus_match,
++ .uevent = xenbus_uevent,
+ .probe = xenbus_dev_probe,
+ .remove = xenbus_dev_remove,
+ .shutdown = xenbus_dev_shutdown,
+@@ -438,6 +449,12 @@ static ssize_t xendev_show_devtype(struct device *dev,
+ }
+ DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL);
+
++static ssize_t xendev_show_modalias(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ return sprintf(buf, "xen:%s\n", to_xenbus_device(dev)->devicetype);
++}
++DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL);
+
+ int xenbus_probe_node(struct xen_bus_type *bus,
+ const char *type,
+@@ -492,10 +509,16 @@ int xenbus_probe_node(struct xen_bus_type *bus,
+
+ err = device_create_file(&xendev->dev, &dev_attr_devtype);
+ if (err)
+- goto fail_remove_file;
++ goto fail_remove_nodename;
++
++ err = device_create_file(&xendev->dev, &dev_attr_modalias);
++ if (err)
++ goto fail_remove_devtype;
+
+ return 0;
+-fail_remove_file:
++fail_remove_devtype:
++ device_remove_file(&xendev->dev, &dev_attr_devtype);
++fail_remove_nodename:
+ device_remove_file(&xendev->dev, &dev_attr_nodename);
+ fail_unregister:
+ device_unregister(&xendev->dev);
+@@ -846,6 +869,7 @@ static int is_disconnected_device(struct device *dev, void *data)
+ {
+ struct xenbus_device *xendev = to_xenbus_device(dev);
+ struct device_driver *drv = data;
++ struct xenbus_driver *xendrv;
+
+ /*
+ * A device with no driver will never connect. We care only about
+@@ -858,7 +882,9 @@ static int is_disconnected_device(struct device *dev, void *data)
+ if (drv && (dev->driver != drv))
+ return 0;
+
+- return (xendev->state != XenbusStateConnected);
++ xendrv = to_xenbus_driver(dev->driver);
++ return (xendev->state != XenbusStateConnected ||
++ (xendrv->is_ready && !xendrv->is_ready(xendev)));
+ }
+
+ static int exists_disconnected_device(struct device_driver *drv)
+diff --git a/drivers/xen/xencomm.c b/drivers/xen/xencomm.c
+new file mode 100644
+index 0000000..797cb4e
+--- /dev/null
++++ b/drivers/xen/xencomm.c
+@@ -0,0 +1,232 @@
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * Copyright (C) IBM Corp. 2006
++ *
++ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ */
++
++#include <linux/gfp.h>
++#include <linux/mm.h>
++#include <asm/page.h>
++#include <xen/xencomm.h>
++#include <xen/interface/xen.h>
++#ifdef __ia64__
++#include <asm/xen/xencomm.h> /* for is_kern_addr() */
++#endif
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++static int xencomm_init(struct xencomm_desc *desc,
++ void *buffer, unsigned long bytes)
++{
++ unsigned long recorded = 0;
++ int i = 0;
++
++ while ((recorded < bytes) && (i < desc->nr_addrs)) {
++ unsigned long vaddr = (unsigned long)buffer + recorded;
++ unsigned long paddr;
++ int offset;
++ int chunksz;
++
++ offset = vaddr % PAGE_SIZE; /* handle partial pages */
++ chunksz = min(PAGE_SIZE - offset, bytes - recorded);
++
++ paddr = xencomm_vtop(vaddr);
++ if (paddr == ~0UL) {
++ printk(KERN_DEBUG "%s: couldn't translate vaddr %lx\n",
++ __func__, vaddr);
++ return -EINVAL;
++ }
+
-+ info->nr_pages = (xenfb_mem_len + PAGE_SIZE - 1) >> PAGE_SHIFT;
++ desc->address[i++] = paddr;
++ recorded += chunksz;
++ }
+
-+ info->mfns = vmalloc(sizeof(unsigned long) * info->nr_pages);
-+ if (!info->mfns)
-+ goto error_nomem;
++ if (recorded < bytes) {
++ printk(KERN_DEBUG
++ "%s: could only translate %ld of %ld bytes\n",
++ __func__, recorded, bytes);
++ return -ENOSPC;
++ }
+
-+ /* set up shared page */
-+ info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
-+ if (!info->page)
-+ goto error_nomem;
++ /* mark remaining addresses invalid (just for safety) */
++ while (i < desc->nr_addrs)
++ desc->address[i++] = XENCOMM_INVALID;
+
-+ xenfb_init_shared_page(info);
++ desc->magic = XENCOMM_MAGIC;
+
-+ /* abusing framebuffer_alloc() to allocate pseudo_palette */
-+ fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL);
-+ if (fb_info == NULL)
-+ goto error_nomem;
++ return 0;
++}
+
-+ /* complete the abuse: */
-+ fb_info->pseudo_palette = fb_info->par;
-+ fb_info->par = info;
++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;
+
-+ fb_info->screen_base = info->fb;
++ /*
++ * 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;
+
-+ 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;
++ desc->nr_addrs =
++ ((PAGE_SIZE << order) - sizeof(struct xencomm_desc)) /
++ sizeof(*desc->address);
++ } else {
++ desc = kmalloc(size, gfp_mask);
++ if (desc == NULL)
++ return NULL;
+
-+ 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};
++ desc->nr_addrs = nr_addrs;
++ }
++ return desc;
++}
+
-+ fb_info->var.activate = FB_ACTIVATE_NOW;
-+ fb_info->var.height = -1;
-+ fb_info->var.width = -1;
-+ fb_info->var.vmode = FB_VMODE_NONINTERLACED;
++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));
++ }
++}
+
-+ 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;
++static int xencomm_create(void *buffer, unsigned long bytes,
++ struct xencomm_desc **ret, gfp_t gfp_mask)
++{
++ struct xencomm_desc *desc;
++ int rc;
+
-+ fb_info->flags = FBINFO_FLAG_DEFAULT;
++ pr_debug("%s: %p[%ld]\n", __func__, buffer, bytes);
+
-+ 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;
++ if (bytes == 0) {
++ /* don't create a descriptor; Xen recognizes NULL. */
++ BUG_ON(buffer != NULL);
++ *ret = NULL;
++ return 0;
+ }
+
-+ fb_info->fbdefio = &xenfb_defio;
-+ fb_deferred_io_init(fb_info);
++ BUG_ON(buffer == NULL); /* 'bytes' is non-zero */
+
-+ 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;
++ desc = xencomm_alloc(gfp_mask, buffer, bytes);
++ if (!desc) {
++ printk(KERN_DEBUG "%s failure\n", "xencomm_alloc");
++ return -ENOMEM;
+ }
-+ info->fb_info = fb_info;
+
-+ ret = xenfb_connect_backend(dev, info);
-+ if (ret < 0)
-+ goto error;
++ 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;
-+
-+ 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)
++/* check if memory address is within VMALLOC region */
++static int is_phys_contiguous(unsigned long addr)
+{
-+ struct xenfb_info *info = dev->dev.driver_data;
++ if (!is_kernel_addr(addr))
++ return 0;
+
-+ xenfb_disconnect_backend(info);
-+ xenfb_init_shared_page(info);
-+ return xenfb_connect_backend(dev, info);
++ return (addr < VMALLOC_START) || (addr >= VMALLOC_END);
+}
+
-+static int xenfb_remove(struct xenbus_device *dev)
++static struct xencomm_handle *xencomm_create_inline(void *ptr)
+{
-+ struct xenfb_info *info = dev->dev.driver_data;
++ unsigned long paddr;
+
-+ 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);
++ BUG_ON(!is_phys_contiguous((unsigned long)ptr));
+
-+ return 0;
++ paddr = (unsigned long)xencomm_pa(ptr);
++ BUG_ON(paddr & XENCOMM_INLINE_FLAG);
++ return (struct xencomm_handle *)(paddr | XENCOMM_INLINE_FLAG);
+}
+
-+static unsigned long vmalloc_to_mfn(void *address)
++/* "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)
+{
-+ return pfn_to_mfn(vmalloc_to_pfn(address));
-+}
++ int rc = 0;
++ struct xencomm_desc *desc;
++ BUG_ON(((unsigned long)xc_desc) % sizeof(*xc_desc) != 0);
+
-+static void xenfb_init_shared_page(struct xenfb_info *info)
-+{
-+ int i;
++ desc = (void *)xc_desc;
+
-+ for (i = 0; i < info->nr_pages; i++)
-+ info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE);
++ desc->nr_addrs = XENCOMM_MINI_ADDRS;
+
-+ 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;
++ rc = xencomm_init(desc, buffer, bytes);
++ if (!rc)
++ *ret = desc;
++
++ return rc;
+}
+
-+static int xenfb_connect_backend(struct xenbus_device *dev,
-+ struct xenfb_info *info)
++struct xencomm_handle *xencomm_map(void *ptr, unsigned long bytes)
+{
-+ 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;
++ int rc;
++ struct xencomm_desc *desc;
+
-+ 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;
-+ }
++ if (is_phys_contiguous((unsigned long)ptr))
++ return xencomm_create_inline(ptr);
+
-+ xenbus_switch_state(dev, XenbusStateInitialised);
-+ return 0;
++ rc = xencomm_create(ptr, bytes, &desc, GFP_KERNEL);
+
-+ error_xenbus:
-+ xenbus_transaction_end(xbt, 1);
-+ xenbus_dev_fatal(dev, ret, "writing xenstore");
-+ return ret;
-+}
++ if (rc || desc == NULL)
++ return NULL;
+
-+static void xenfb_disconnect_backend(struct xenfb_info *info)
-+{
-+ if (info->irq >= 0)
-+ unbind_from_irqhandler(info->irq, info);
-+ info->irq = -1;
++ return xencomm_pa(desc);
+}
+
-+static void xenfb_backend_changed(struct xenbus_device *dev,
-+ enum xenbus_state backend_state)
++struct xencomm_handle *__xencomm_map_no_alloc(void *ptr, unsigned long bytes,
++ struct xencomm_mini *xc_desc)
+{
-+ struct xenfb_info *info = dev->dev.driver_data;
-+ int val;
-+
-+ switch (backend_state) {
-+ case XenbusStateInitialising:
-+ case XenbusStateInitialised:
-+ case XenbusStateUnknown:
-+ case XenbusStateClosed:
-+ break;
++ int rc;
++ struct xencomm_desc *desc = NULL;
+
-+ case XenbusStateInitWait:
-+InitWait:
-+ xenbus_switch_state(dev, XenbusStateConnected);
-+ break;
++ if (is_phys_contiguous((unsigned long)ptr))
++ return xencomm_create_inline(ptr);
+
-+ 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 */
++ rc = xencomm_create_mini(ptr, bytes, xc_desc,
++ &desc);
+
-+ if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-+ "request-update", "%d", &val) < 0)
-+ val = 0;
-+ if (val)
-+ info->update_wanted = 1;
-+ break;
++ if (rc)
++ return NULL;
+
-+ case XenbusStateClosing:
-+ xenbus_frontend_closed(dev);
-+ break;
-+ }
++ return xencomm_pa(desc);
++}
+diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c
+index 2ce4ceb..099b6fb 100644
+--- a/drivers/zorro/proc.c
++++ b/drivers/zorro/proc.c
+@@ -13,6 +13,7 @@
+ #include <linux/types.h>
+ #include <linux/zorro.h>
+ #include <linux/proc_fs.h>
++#include <linux/seq_file.h>
+ #include <linux/init.h>
+ #include <linux/smp_lock.h>
+ #include <asm/uaccess.h>
+@@ -76,36 +77,58 @@ proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t *
+ }
+
+ static const struct file_operations proc_bus_zorro_operations = {
++ .owner = THIS_MODULE,
+ .llseek = proc_bus_zorro_lseek,
+ .read = proc_bus_zorro_read,
+ };
+
+-static int
+-get_zorro_dev_info(char *buf, char **start, off_t pos, int count)
++static void * zorro_seq_start(struct seq_file *m, loff_t *pos)
+ {
+- u_int slot;
+- off_t at = 0;
+- int len, cnt;
+-
+- for (slot = cnt = 0; slot < zorro_num_autocon && count > cnt; slot++) {
+- struct zorro_dev *z = &zorro_autocon[slot];
+- len = sprintf(buf, "%02x\t%08x\t%08lx\t%08lx\t%02x\n", slot,
+- z->id, (unsigned long)zorro_resource_start(z),
+- (unsigned long)zorro_resource_len(z),
+- z->rom.er_Type);
+- at += len;
+- if (at >= pos) {
+- if (!*start) {
+- *start = buf + (pos - (at - len));
+- cnt = at - pos;
+- } else
+- cnt += len;
+- buf += len;
+- }
+- }
+- return (count > cnt) ? cnt : count;
++ return (*pos < zorro_num_autocon) ? pos : NULL;
+}
+
-+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)
++static void * zorro_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
-+ if (!is_running_on_xen())
-+ return -ENODEV;
-+
-+ /* Nothing to do if running in dom0. */
-+ if (is_initial_xendomain())
-+ return -ENODEV;
++ (*pos)++;
++ return (*pos < zorro_num_autocon) ? pos : NULL;
++}
+
-+ return xenbus_register_frontend(&xenfb);
++static void zorro_seq_stop(struct seq_file *m, void *v)
++{
+}
+
-+static void __exit xenfb_cleanup(void)
++static int zorro_seq_show(struct seq_file *m, void *v)
+{
-+ xenbus_unregister_driver(&xenfb);
++ u_int slot = *(loff_t *)v;
++ struct zorro_dev *z = &zorro_autocon[slot];
++
++ seq_printf(m, "%02x\t%08x\t%08lx\t%08lx\t%02x\n", slot, z->id,
++ (unsigned long)zorro_resource_start(z),
++ (unsigned long)zorro_resource_len(z),
++ z->rom.er_Type);
++ return 0;
+}
+
-+module_init(xenfb_init);
-+module_exit(xenfb_cleanup);
++static const struct seq_operations zorro_devices_seq_ops = {
++ .start = zorro_seq_start,
++ .next = zorro_seq_next,
++ .stop = zorro_seq_stop,
++ .show = zorro_seq_show,
++};
+
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c
-index 32ccd7c..35cddff 100644
---- a/drivers/watchdog/sc1200wdt.c
-+++ b/drivers/watchdog/sc1200wdt.c
-@@ -38,8 +38,8 @@
- #include <linux/init.h>
- #include <linux/pnp.h>
- #include <linux/fs.h>
-+#include <linux/semaphore.h>
++static int zorro_devices_proc_open(struct inode *inode, struct file *file)
++{
++ return seq_open(file, &zorro_devices_seq_ops);
+ }
+
++static const struct file_operations zorro_devices_proc_fops = {
++ .owner = THIS_MODULE,
++ .open = zorro_devices_proc_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = seq_release,
++};
++
+ static struct proc_dir_entry *proc_bus_zorro_dir;
+ static int __init zorro_proc_attach_device(u_int slot)
+@@ -114,11 +137,11 @@ static int __init zorro_proc_attach_device(u_int slot)
+ char name[4];
+
+ sprintf(name, "%02x", slot);
+- entry = create_proc_entry(name, 0, proc_bus_zorro_dir);
++ entry = proc_create_data(name, 0, proc_bus_zorro_dir,
++ &proc_bus_zorro_operations,
++ &zorro_autocon[slot]);
+ if (!entry)
+ return -ENOMEM;
+- entry->proc_fops = &proc_bus_zorro_operations;
+- entry->data = &zorro_autocon[slot];
+ entry->size = sizeof(struct zorro_dev);
+ return 0;
+ }
+@@ -128,9 +151,9 @@ static int __init zorro_proc_init(void)
+ u_int slot;
+
+ if (MACH_IS_AMIGA && AMIGAHW_PRESENT(ZORRO)) {
+- proc_bus_zorro_dir = proc_mkdir("zorro", proc_bus);
+- create_proc_info_entry("devices", 0, proc_bus_zorro_dir,
+- get_zorro_dev_info);
++ proc_bus_zorro_dir = proc_mkdir("bus/zorro", NULL);
++ proc_create("devices", 0, proc_bus_zorro_dir,
++ &zorro_devices_proc_fops);
+ for (slot = 0; slot < zorro_num_autocon; slot++)
+ zorro_proc_attach_device(slot);
+ }
+diff --git a/fs/9p/fid.c b/fs/9p/fid.c
+index dfebdbe..3031e32 100644
+--- a/fs/9p/fid.c
++++ b/fs/9p/fid.c
+@@ -26,7 +26,6 @@
+ #include <linux/fs.h>
+ #include <linux/sched.h>
+ #include <linux/idr.h>
-#include <asm/semaphore.h>
- #include <asm/io.h>
- #include <asm/uaccess.h>
+ #include <net/9p/9p.h>
+ #include <net/9p/client.h>
-diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
-new file mode 100644
-index 0000000..4b75a16
---- /dev/null
-+++ b/drivers/xen/Kconfig
-@@ -0,0 +1,19 @@
-+config XEN_BALLOON
-+ bool "Xen memory balloon driver"
-+ depends on XEN
+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..cf12c40 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -411,7 +411,7 @@ config JFS_STATISTICS
+ to be made available to the user in the /proc/fs/jfs/ directory.
+
+ config FS_POSIX_ACL
+-# Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs)
++# Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs/nfs4)
+ #
+ # NOTE: you can implement Posix ACLs without these helpers (XFS does).
+ # Never use this symbol for ifdefs.
+@@ -444,6 +444,32 @@ config OCFS2_FS
+ For more information on OCFS2, see the file
+ <file:Documentation/filesystems/ocfs2.txt>.
+
++config OCFS2_FS_O2CB
++ tristate "O2CB Kernelspace Clustering"
++ depends on OCFS2_FS
+ default y
+ help
-+ 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.
++ 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.
+
-+config XEN_SCRUB_PAGES
-+ bool "Scrub pages before returning them to system"
-+ depends on XEN_BALLOON
++ 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
-+ 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.
-+ */
++ 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.
+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+#include <linux/mm.h>
-+#include <linux/bootmem.h>
-+#include <linux/pagemap.h>
-+#include <linux/highmem.h>
-+#include <linux/mutex.h>
-+#include <linux/highmem.h>
-+#include <linux/list.h>
-+#include <linux/sysdev.h>
++ It is safe to say Y, as the clustering method is run-time
++ selectable.
+
-+#include <asm/xen/hypervisor.h>
-+#include <asm/page.h>
-+#include <asm/pgalloc.h>
-+#include <asm/pgtable.h>
-+#include <asm/uaccess.h>
-+#include <asm/tlb.h>
+ 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
+@@ -978,7 +1005,8 @@ config TMPFS_POSIX_ACL
+
+ config HUGETLBFS
+ bool "HugeTLB file system support"
+- depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || BROKEN
++ depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || \
++ (S390 && 64BIT) || BROKEN
+ help
+ hugetlbfs is a filesystem backing for HugeTLB pages, based on
+ ramfs. For architectures that support it, say Y here and read
+@@ -1637,105 +1665,86 @@ config NFS_V4
+
+ If unsure, say N.
+
+-config NFS_DIRECTIO
+- bool "Allow direct I/O on NFS files"
+- depends on NFS_FS
+- help
+- This option enables applications to perform uncached I/O on files
+- in NFS file systems using the O_DIRECT open() flag. When O_DIRECT
+- is set for a file, its data is not cached in the system's page
+- cache. Data is moved to and from user-level application buffers
+- directly. Unlike local disk-based file systems, NFS O_DIRECT has
+- no alignment restrictions.
+-
+- Unless your program is designed to use O_DIRECT properly, you are
+- much better off allowing the NFS client to manage data caching for
+- you. Misusing O_DIRECT can cause poor server performance or network
+- storms. This kernel build option defaults OFF to avoid exposing
+- system administrators unwittingly to a potentially hazardous
+- feature.
+-
+- For more details on NFS O_DIRECT, see fs/nfs/direct.c.
+-
+- If unsure, say N. This reduces the size of the NFS client, and
+- causes open() to return EINVAL if a file residing in NFS is
+- opened with the O_DIRECT flag.
+-
+ config NFSD
+ tristate "NFS server support"
+ depends on INET
+ select LOCKD
+ select SUNRPC
+ select EXPORTFS
+- select NFSD_V2_ACL if NFSD_V3_ACL
+ select NFS_ACL_SUPPORT if NFSD_V2_ACL
+- select NFSD_TCP if NFSD_V4
+- select CRYPTO_MD5 if NFSD_V4
+- select CRYPTO if NFSD_V4
+- select FS_POSIX_ACL if NFSD_V4
+- select PROC_FS if NFSD_V4
+- select PROC_FS if SUNRPC_GSS
+- help
+- If you want your Linux box to act as an NFS *server*, so that other
+- computers on your local network which support NFS can access certain
+- directories on your box transparently, you have two options: you can
+- use the self-contained user space program nfsd, in which case you
+- should say N here, or you can say Y and use the kernel based NFS
+- server. The advantage of the kernel based solution is that it is
+- faster.
+-
+- In either case, you will need support software; the respective
+- locations are given in the file <file:Documentation/Changes> in the
+- NFS section.
+-
+- If you say Y here, you will get support for version 2 of the NFS
+- protocol (NFSv2). If you also want NFSv3, say Y to the next question
+- as well.
+-
+- Please read the NFS-HOWTO, available from
+- <http://www.tldp.org/docs.html#howto>.
+-
+- To compile the NFS server support as a module, choose M here: the
+- module will be called nfsd. If unsure, say N.
++ help
++ Choose Y here if you want to allow other computers to access
++ files residing on this system using Sun's Network File System
++ protocol. To compile the NFS server support as a module,
++ choose M here: the module will be called nfsd.
+
-+#include <xen/interface/memory.h>
-+#include <xen/balloon.h>
-+#include <xen/xenbus.h>
-+#include <xen/features.h>
-+#include <xen/page.h>
++ You may choose to use a user-space NFS server instead, in which
++ case you can choose N here.
+
-+#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
++ 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.
+
-+#define BALLOON_CLASS_NAME "memory"
++ 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.
+
-+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;
-+};
++ 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).
+
-+static DEFINE_MUTEX(balloon_mutex);
++ 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.
+
-+static struct sys_device balloon_sysdev;
++ 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.
+
-+static int register_balloon(struct sys_device *sysdev);
++ To store ACLs on your NFS server, you also need to enable ACL-
++ related CONFIG options for your local file systems of choice.
+
-+/*
-+ * 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);
++ 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/.
+
-+static struct balloon_stats balloon_stats;
++ If unsure, say N.
+
+ config ROOT_NFS
+ bool "Root file system on NFS"
+@@ -1781,15 +1790,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.
+
-+/* We increase/decrease in batches which fit in a page */
-+static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
++ To compile RPC client RDMA transport support as a module,
++ choose M here: the module will be called xprtrdma.
+
-+/* VM /proc information for memory */
-+extern unsigned long totalram_pages;
++ 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).
+
-+#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
++ 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 +1830,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 +1850,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..55e8ee1 100644
+--- a/fs/Kconfig.binfmt
++++ b/fs/Kconfig.binfmt
+@@ -41,7 +41,7 @@ config BINFMT_ELF_FDPIC
+ It is also possible to run FDPIC ELF binaries on MMU linux also.
+
+ config BINFMT_FLAT
+- tristate "Kernel support for flat binaries"
++ bool "Kernel support for flat binaries"
+ depends on !MMU
+ help
+ Support uClinux FLAT format binaries.
+@@ -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/adfs/adfs.h b/fs/adfs/adfs.h
+index 936f2af..8311575 100644
+--- a/fs/adfs/adfs.h
++++ b/fs/adfs/adfs.h
+@@ -75,7 +75,7 @@ extern unsigned int adfs_map_free(struct super_block *sb);
+ /* Misc */
+ void __adfs_error(struct super_block *sb, const char *function,
+ const char *fmt, ...);
+-#define adfs_error(sb, fmt...) __adfs_error(sb, __FUNCTION__, fmt)
++#define adfs_error(sb, fmt...) __adfs_error(sb, __func__, fmt)
+
+ /* super.c */
+
+diff --git a/fs/adfs/dir_f.c b/fs/adfs/dir_f.c
+index b9b2b27..ea7df21 100644
+--- a/fs/adfs/dir_f.c
++++ b/fs/adfs/dir_f.c
+@@ -122,9 +122,9 @@ adfs_dir_checkbyte(const struct adfs_dir *dir)
+ ptr.ptr8 = bufoff(bh, i);
+ end.ptr8 = ptr.ptr8 + last - i;
+
+- do
++ do {
+ dircheck = *ptr.ptr8++ ^ ror13(dircheck);
+- while (ptr.ptr8 < end.ptr8);
++ } while (ptr.ptr8 < end.ptr8);
+ }
+
+ /*
+diff --git a/fs/affs/file.c b/fs/affs/file.c
+index 6e0c939..1a4f092 100644
+--- a/fs/affs/file.c
++++ b/fs/affs/file.c
+@@ -325,8 +325,7 @@ affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_resul
+ pr_debug("AFFS: get_block(%u, %lu)\n", (u32)inode->i_ino, (unsigned long)block);
+
+
+- if (block > (sector_t)0x7fffffffUL)
+- BUG();
++ BUG_ON(block > (sector_t)0x7fffffffUL);
+
+ if (block >= AFFS_I(inode)->i_blkcnt) {
+ if (block > AFFS_I(inode)->i_blkcnt || !create)
+@@ -493,8 +492,7 @@ affs_do_readpage_ofs(struct file *file, struct page *page, unsigned from, unsign
+ u32 tmp;
+
+ pr_debug("AFFS: read_page(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to);
+- if (from > to || to > PAGE_CACHE_SIZE)
+- BUG();
++ BUG_ON(from > to || to > PAGE_CACHE_SIZE);
+ kmap(page);
+ data = page_address(page);
+ bsize = AFFS_SB(sb)->s_data_blksize;
+@@ -507,8 +505,7 @@ affs_do_readpage_ofs(struct file *file, struct page *page, unsigned from, unsign
+ if (IS_ERR(bh))
+ return PTR_ERR(bh);
+ tmp = min(bsize - boff, to - from);
+- if (from + tmp > to || tmp > bsize)
+- BUG();
++ BUG_ON(from + tmp > to || tmp > bsize);
+ memcpy(data + from, AFFS_DATA(bh) + boff, tmp);
+ affs_brelse(bh);
+ bidx++;
+@@ -540,10 +537,9 @@ affs_extent_file_ofs(struct inode *inode, u32 newsize)
+ if (IS_ERR(bh))
+ return PTR_ERR(bh);
+ tmp = min(bsize - boff, newsize - size);
+- if (boff + tmp > bsize || tmp > bsize)
+- BUG();
++ BUG_ON(boff + tmp > bsize || tmp > bsize);
+ memset(AFFS_DATA(bh) + boff, 0, tmp);
+- AFFS_DATA_HEAD(bh)->size = cpu_to_be32(be32_to_cpu(AFFS_DATA_HEAD(bh)->size) + tmp);
++ be32_add_cpu(&AFFS_DATA_HEAD(bh)->size, tmp);
+ affs_fix_checksum(sb, bh);
+ mark_buffer_dirty_inode(bh, inode);
+ size += tmp;
+@@ -560,8 +556,7 @@ affs_extent_file_ofs(struct inode *inode, u32 newsize)
+ if (IS_ERR(bh))
+ goto out;
+ tmp = min(bsize, newsize - size);
+- if (tmp > bsize)
+- BUG();
++ BUG_ON(tmp > bsize);
+ AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
+ AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
+ AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
+@@ -683,10 +678,9 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
+ if (IS_ERR(bh))
+ return PTR_ERR(bh);
+ tmp = min(bsize - boff, to - from);
+- if (boff + tmp > bsize || tmp > bsize)
+- BUG();
++ BUG_ON(boff + tmp > bsize || tmp > bsize);
+ memcpy(AFFS_DATA(bh) + boff, data + from, tmp);
+- AFFS_DATA_HEAD(bh)->size = cpu_to_be32(be32_to_cpu(AFFS_DATA_HEAD(bh)->size) + tmp);
++ be32_add_cpu(&AFFS_DATA_HEAD(bh)->size, tmp);
+ affs_fix_checksum(sb, bh);
+ mark_buffer_dirty_inode(bh, inode);
+ written += tmp;
+@@ -732,8 +726,7 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
+ if (IS_ERR(bh))
+ goto out;
+ tmp = min(bsize, to - from);
+- if (tmp > bsize)
+- BUG();
++ BUG_ON(tmp > bsize);
+ memcpy(AFFS_DATA(bh), data + from, tmp);
+ if (buffer_new(bh)) {
+ AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
+diff --git a/fs/affs/super.c b/fs/affs/super.c
+index d2dc047..01d25d5 100644
+--- a/fs/affs/super.c
++++ b/fs/affs/super.c
+@@ -199,7 +199,6 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s
+ case Opt_prefix:
+ /* Free any previous prefix */
+ kfree(*prefix);
+- *prefix = NULL;
+ *prefix = match_strdup(&args[0]);
+ if (!*prefix)
+ return 0;
+@@ -233,6 +232,8 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s
+ break;
+ case Opt_volume: {
+ char *vol = match_strdup(&args[0]);
++ if (!vol)
++ return 0;
+ strlcpy(volume, vol, 32);
+ kfree(vol);
+ break;
+diff --git a/fs/afs/afs_cm.h b/fs/afs/afs_cm.h
+index 7b4d4fa..255f5dd 100644
+--- a/fs/afs/afs_cm.h
++++ b/fs/afs/afs_cm.h
+@@ -24,7 +24,8 @@ enum AFS_CM_Operations {
+ CBGetXStatsVersion = 209, /* get version of extended statistics */
+ CBGetXStats = 210, /* get contents of extended statistics data */
+ CBInitCallBackState3 = 213, /* initialise callback state, version 3 */
+- CBGetCapabilities = 65538, /* get client capabilities */
++ CBProbeUuid = 214, /* check the client hasn't rebooted */
++ CBTellMeAboutYourself = 65538, /* get client capabilities */
+ };
+
+ #define AFS_CAP_ERROR_TRANSLATION 0x1
+diff --git a/fs/afs/cell.c b/fs/afs/cell.c
+index 584bb0f..5e1df14 100644
+--- a/fs/afs/cell.c
++++ b/fs/afs/cell.c
+@@ -20,7 +20,7 @@
+ DECLARE_RWSEM(afs_proc_cells_sem);
+ LIST_HEAD(afs_proc_cells);
+
+-static struct list_head afs_cells = LIST_HEAD_INIT(afs_cells);
++static LIST_HEAD(afs_cells);
+ static DEFINE_RWLOCK(afs_cells_lock);
+ static DECLARE_RWSEM(afs_cells_sem); /* add/remove serialisation */
+ static DECLARE_WAIT_QUEUE_HEAD(afs_cells_freeable_wq);
+diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
+index 47b71c8..eb76548 100644
+--- a/fs/afs/cmservice.c
++++ b/fs/afs/cmservice.c
+@@ -26,8 +26,9 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *,
+ struct sk_buff *, bool);
+ static int afs_deliver_cb_probe(struct afs_call *, struct sk_buff *, bool);
+ static int afs_deliver_cb_callback(struct afs_call *, struct sk_buff *, bool);
+-static int afs_deliver_cb_get_capabilities(struct afs_call *, struct sk_buff *,
+- bool);
++static int afs_deliver_cb_probe_uuid(struct afs_call *, struct sk_buff *, bool);
++static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *,
++ struct sk_buff *, bool);
+ static void afs_cm_destructor(struct afs_call *);
+
+ /*
+@@ -71,11 +72,21 @@ static const struct afs_call_type afs_SRXCBProbe = {
+ };
+
+ /*
+- * CB.GetCapabilities operation type
++ * CB.ProbeUuid operation type
+ */
+-static const struct afs_call_type afs_SRXCBGetCapabilites = {
+- .name = "CB.GetCapabilities",
+- .deliver = afs_deliver_cb_get_capabilities,
++static const struct afs_call_type afs_SRXCBProbeUuid = {
++ .name = "CB.ProbeUuid",
++ .deliver = afs_deliver_cb_probe_uuid,
++ .abort_to_error = afs_abort_to_error,
++ .destructor = afs_cm_destructor,
++};
+
-+/* List of ballooned pages, threaded through the mem_map array. */
-+static LIST_HEAD(ballooned_pages);
++/*
++ * CB.TellMeAboutYourself operation type
++ */
++static const struct afs_call_type afs_SRXCBTellMeAboutYourself = {
++ .name = "CB.TellMeAboutYourself",
++ .deliver = afs_deliver_cb_tell_me_about_yourself,
+ .abort_to_error = afs_abort_to_error,
+ .destructor = afs_cm_destructor,
+ };
+@@ -103,8 +114,8 @@ bool afs_cm_incoming_call(struct afs_call *call)
+ case CBProbe:
+ call->type = &afs_SRXCBProbe;
+ return true;
+- case CBGetCapabilities:
+- call->type = &afs_SRXCBGetCapabilites;
++ case CBTellMeAboutYourself:
++ call->type = &afs_SRXCBTellMeAboutYourself;
+ return true;
+ default:
+ return false;
+@@ -393,9 +404,105 @@ static int afs_deliver_cb_probe(struct afs_call *call, struct sk_buff *skb,
+ }
+
+ /*
++ * allow the fileserver to quickly find out if the fileserver has been rebooted
++ */
++static void SRXAFSCB_ProbeUuid(struct work_struct *work)
++{
++ struct afs_call *call = container_of(work, struct afs_call, work);
++ struct afs_uuid *r = call->request;
+
-+/* 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;
++ struct {
++ __be32 match;
++ } reply;
+
-+/* 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)
++ _enter("");
+
-+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++;
-+ }
++ if (memcmp(r, &afs_uuid, sizeof(afs_uuid)) == 0)
++ reply.match = htonl(0);
++ else
++ reply.match = htonl(1);
++
++ afs_send_simple_reply(call, &reply, sizeof(reply));
++ _leave("");
+}
+
-+/* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
-+static struct page *balloon_retrieve(void)
++/*
++ * deliver request data to a CB.ProbeUuid call
++ */
++static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb,
++ bool last)
+{
-+ struct page *page;
++ struct afs_uuid *r;
++ unsigned loop;
++ __be32 *b;
++ int ret;
+
-+ if (list_empty(&ballooned_pages))
-+ return NULL;
++ _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
+
-+ page = list_entry(ballooned_pages.next, struct page, lru);
-+ list_del(&page->lru);
++ if (skb->len > 0)
++ return -EBADMSG;
++ if (!last)
++ return 0;
+
-+ if (PageHighMem(page)) {
-+ balloon_stats.balloon_high--;
-+ inc_totalhigh_pages();
++ switch (call->unmarshall) {
++ case 0:
++ call->offset = 0;
++ call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL);
++ if (!call->buffer)
++ return -ENOMEM;
++ call->unmarshall++;
++
++ case 1:
++ _debug("extract UUID");
++ ret = afs_extract_data(call, skb, last, call->buffer,
++ 11 * sizeof(__be32));
++ switch (ret) {
++ case 0: break;
++ case -EAGAIN: return 0;
++ default: return ret;
++ }
++
++ _debug("unmarshall UUID");
++ call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL);
++ if (!call->request)
++ return -ENOMEM;
++
++ b = call->buffer;
++ r = call->request;
++ r->time_low = ntohl(b[0]);
++ r->time_mid = ntohl(b[1]);
++ r->time_hi_and_version = ntohl(b[2]);
++ r->clock_seq_hi_and_reserved = ntohl(b[3]);
++ r->clock_seq_low = ntohl(b[4]);
++
++ for (loop = 0; loop < 6; loop++)
++ r->node[loop] = ntohl(b[loop + 5]);
++
++ call->offset = 0;
++ call->unmarshall++;
++
++ case 2:
++ _debug("trailer");
++ if (skb->len != 0)
++ return -EBADMSG;
++ break;
+ }
-+ else
-+ balloon_stats.balloon_low--;
+
-+ return page;
-+}
++ if (!last)
++ return 0;
+
-+static struct page *balloon_first_page(void)
-+{
-+ if (list_empty(&ballooned_pages))
-+ return NULL;
-+ return list_entry(ballooned_pages.next, struct page, lru);
-+}
++ call->state = AFS_CALL_REPLYING;
+
-+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);
++ INIT_WORK(&call->work, SRXAFSCB_ProbeUuid);
++ schedule_work(&call->work);
++ return 0;
+}
+
-+static void balloon_alarm(unsigned long unused)
-+{
-+ schedule_work(&balloon_worker);
-+}
++/*
+ * allow the fileserver to ask about the cache manager's capabilities
+ */
+-static void SRXAFSCB_GetCapabilities(struct work_struct *work)
++static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work)
+ {
+ struct afs_interface *ifs;
+ struct afs_call *call = container_of(work, struct afs_call, work);
+@@ -456,10 +563,10 @@ static void SRXAFSCB_GetCapabilities(struct work_struct *work)
+ }
+
+ /*
+- * deliver request data to a CB.GetCapabilities call
++ * deliver request data to a CB.TellMeAboutYourself call
+ */
+-static int afs_deliver_cb_get_capabilities(struct afs_call *call,
+- struct sk_buff *skb, bool last)
++static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call,
++ struct sk_buff *skb, bool last)
+ {
+ _enter(",{%u},%d", skb->len, last);
+
+@@ -471,7 +578,7 @@ static int afs_deliver_cb_get_capabilities(struct afs_call *call,
+ /* no unmarshalling required */
+ call->state = AFS_CALL_REPLYING;
+
+- INIT_WORK(&call->work, SRXAFSCB_GetCapabilities);
++ INIT_WORK(&call->work, SRXAFSCB_TellMeAboutYourself);
+ schedule_work(&call->work);
+ return 0;
+ }
+diff --git a/fs/afs/dir.c b/fs/afs/dir.c
+index b58af8f..dfda03d 100644
+--- a/fs/afs/dir.c
++++ b/fs/afs/dir.c
+@@ -140,7 +140,7 @@ static inline void afs_dir_check_page(struct inode *dir, struct page *page)
+
+ if (page->index == 0 && qty != ntohs(dbuf->blocks[0].pagehdr.npages)) {
+ printk("kAFS: %s(%lu): wrong number of dir blocks %d!=%hu\n",
+- __FUNCTION__, dir->i_ino, qty,
++ __func__, dir->i_ino, qty,
+ ntohs(dbuf->blocks[0].pagehdr.npages));
+ goto error;
+ }
+@@ -159,7 +159,7 @@ static inline void afs_dir_check_page(struct inode *dir, struct page *page)
+ for (tmp = 0; tmp < qty; tmp++) {
+ if (dbuf->blocks[tmp].pagehdr.magic != AFS_DIR_MAGIC) {
+ printk("kAFS: %s(%lu): bad magic %d/%d is %04hx\n",
+- __FUNCTION__, dir->i_ino, tmp, qty,
++ __func__, dir->i_ino, tmp, qty,
+ ntohs(dbuf->blocks[tmp].pagehdr.magic));
+ goto error;
+ }
+diff --git a/fs/afs/internal.h b/fs/afs/internal.h
+index eec41c7..7102824 100644
+--- a/fs/afs/internal.h
++++ b/fs/afs/internal.h
+@@ -757,8 +757,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__)
+
+
+@@ -791,8 +791,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__)
+ #endif
+
+diff --git a/fs/afs/proc.c b/fs/afs/proc.c
+index 846c761..9f7d1ae 100644
+--- a/fs/afs/proc.c
++++ b/fs/afs/proc.c
+@@ -41,6 +41,7 @@ static const struct file_operations afs_proc_cells_fops = {
+ .write = afs_proc_cells_write,
+ .llseek = seq_lseek,
+ .release = seq_release,
++ .owner = THIS_MODULE,
+ };
+
+ static int afs_proc_rootcell_open(struct inode *inode, struct file *file);
+@@ -56,7 +57,8 @@ static const struct file_operations afs_proc_rootcell_fops = {
+ .read = afs_proc_rootcell_read,
+ .write = afs_proc_rootcell_write,
+ .llseek = no_llseek,
+- .release = afs_proc_rootcell_release
++ .release = afs_proc_rootcell_release,
++ .owner = THIS_MODULE,
+ };
+
+ static int afs_proc_cell_volumes_open(struct inode *inode, struct file *file);
+@@ -80,6 +82,7 @@ static const struct file_operations afs_proc_cell_volumes_fops = {
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = afs_proc_cell_volumes_release,
++ .owner = THIS_MODULE,
+ };
+
+ static int afs_proc_cell_vlservers_open(struct inode *inode,
+@@ -104,6 +107,7 @@ static const struct file_operations afs_proc_cell_vlservers_fops = {
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = afs_proc_cell_vlservers_release,
++ .owner = THIS_MODULE,
+ };
+
+ static int afs_proc_cell_servers_open(struct inode *inode, struct file *file);
+@@ -127,6 +131,7 @@ static const struct file_operations afs_proc_cell_servers_fops = {
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = afs_proc_cell_servers_release,
++ .owner = THIS_MODULE,
+ };
+
+ /*
+@@ -143,17 +148,13 @@ int afs_proc_init(void)
+ goto error_dir;
+ proc_afs->owner = THIS_MODULE;
+
+- p = create_proc_entry("cells", 0, proc_afs);
++ p = proc_create("cells", 0, proc_afs, &afs_proc_cells_fops);
+ if (!p)
+ goto error_cells;
+- p->proc_fops = &afs_proc_cells_fops;
+- p->owner = THIS_MODULE;
+
+- p = create_proc_entry("rootcell", 0, proc_afs);
++ p = proc_create("rootcell", 0, proc_afs, &afs_proc_rootcell_fops);
+ if (!p)
+ goto error_rootcell;
+- p->proc_fops = &afs_proc_rootcell_fops;
+- p->owner = THIS_MODULE;
+
+ _leave(" = 0");
+ return 0;
+@@ -395,26 +396,20 @@ int afs_proc_cell_setup(struct afs_cell *cell)
+ if (!cell->proc_dir)
+ goto error_dir;
+
+- p = create_proc_entry("servers", 0, cell->proc_dir);
++ p = proc_create_data("servers", 0, cell->proc_dir,
++ &afs_proc_cell_servers_fops, cell);
+ if (!p)
+ goto error_servers;
+- p->proc_fops = &afs_proc_cell_servers_fops;
+- p->owner = THIS_MODULE;
+- p->data = cell;
+
+- p = create_proc_entry("vlservers", 0, cell->proc_dir);
++ p = proc_create_data("vlservers", 0, cell->proc_dir,
++ &afs_proc_cell_vlservers_fops, cell);
+ if (!p)
+ goto error_vlservers;
+- p->proc_fops = &afs_proc_cell_vlservers_fops;
+- p->owner = THIS_MODULE;
+- p->data = cell;
+
+- p = create_proc_entry("volumes", 0, cell->proc_dir);
++ p = proc_create_data("volumes", 0, cell->proc_dir,
++ &afs_proc_cell_volumes_fops, cell);
+ if (!p)
+ goto error_volumes;
+- p->proc_fops = &afs_proc_cell_volumes_fops;
+- p->owner = THIS_MODULE;
+- p->data = cell;
+
+ _leave(" = 0");
+ return 0;
+diff --git a/fs/aio.c b/fs/aio.c
+index 2283686..b5253e7 100644
+--- a/fs/aio.c
++++ b/fs/aio.c
+@@ -191,6 +191,43 @@ static int aio_setup_ring(struct kioctx *ctx)
+ kunmap_atomic((void *)((unsigned long)__event & PAGE_MASK), km); \
+ } while(0)
+
+
-+static unsigned long current_target(void)
++/* __put_ioctx
++ * Called when the last user of an aio context has gone away,
++ * and the struct needs to be freed.
++ */
++static void __put_ioctx(struct kioctx *ctx)
+{
-+ unsigned long target = min(balloon_stats.target_pages, balloon_stats.hard_limit);
++ unsigned nr_events = ctx->max_reqs;
+
-+ target = min(target,
-+ balloon_stats.current_pages +
-+ balloon_stats.balloon_low +
-+ balloon_stats.balloon_high);
++ BUG_ON(ctx->reqs_active);
+
-+ return target;
++ cancel_delayed_work(&ctx->wq);
++ cancel_work_sync(&ctx->wq.work);
++ aio_free_ring(ctx);
++ mmdrop(ctx->mm);
++ ctx->mm = NULL;
++ pr_debug("__put_ioctx: freeing %p\n", ctx);
++ kmem_cache_free(kioctx_cachep, ctx);
++
++ if (nr_events) {
++ spin_lock(&aio_nr_lock);
++ BUG_ON(aio_nr - nr_events > aio_nr);
++ aio_nr -= nr_events;
++ spin_unlock(&aio_nr_lock);
++ }
+}
+
-+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
-+ };
++#define get_ioctx(kioctx) do { \
++ BUG_ON(atomic_read(&(kioctx)->users) <= 0); \
++ atomic_inc(&(kioctx)->users); \
++} while (0)
++#define put_ioctx(kioctx) do { \
++ BUG_ON(atomic_read(&(kioctx)->users) <= 0); \
++ if (unlikely(atomic_dec_and_test(&(kioctx)->users))) \
++ __put_ioctx(kioctx); \
++} while (0)
+
-+ if (nr_pages > ARRAY_SIZE(frame_list))
-+ nr_pages = ARRAY_SIZE(frame_list);
+ /* ioctx_alloc
+ * Allocates and initializes an ioctx. Returns an ERR_PTR if it failed.
+ */
+@@ -240,7 +277,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
+ if (ctx->max_reqs == 0)
+ goto out_cleanup;
+
+- /* now link into global list. kludge. FIXME */
++ /* now link into global list. */
+ write_lock(&mm->ioctx_list_lock);
+ ctx->next = mm->ioctx_list;
+ mm->ioctx_list = ctx;
+@@ -361,32 +398,6 @@ void exit_aio(struct mm_struct *mm)
+ }
+ }
+
+-/* __put_ioctx
+- * Called when the last user of an aio context has gone away,
+- * and the struct needs to be freed.
+- */
+-void __put_ioctx(struct kioctx *ctx)
+-{
+- unsigned nr_events = ctx->max_reqs;
+-
+- BUG_ON(ctx->reqs_active);
+-
+- cancel_delayed_work(&ctx->wq);
+- cancel_work_sync(&ctx->wq.work);
+- aio_free_ring(ctx);
+- mmdrop(ctx->mm);
+- ctx->mm = NULL;
+- pr_debug("__put_ioctx: freeing %p\n", ctx);
+- kmem_cache_free(kioctx_cachep, ctx);
+-
+- if (nr_events) {
+- spin_lock(&aio_nr_lock);
+- BUG_ON(aio_nr - nr_events > aio_nr);
+- aio_nr -= nr_events;
+- spin_unlock(&aio_nr_lock);
+- }
+-}
+-
+ /* aio_get_req
+ * Allocate a slot for an aio request. Increments the users count
+ * of the kioctx so that the kioctx stays around until all requests are
+@@ -542,10 +553,7 @@ int aio_put_req(struct kiocb *req)
+ return ret;
+ }
+
+-/* Lookup an ioctx id. ioctx_list is lockless for reads.
+- * FIXME: this is O(n) and is only suitable for development.
+- */
+-struct kioctx *lookup_ioctx(unsigned long ctx_id)
++static struct kioctx *lookup_ioctx(unsigned long ctx_id)
+ {
+ struct kioctx *ioctx;
+ struct mm_struct *mm;
+@@ -1070,9 +1078,7 @@ static void timeout_func(unsigned long data)
+
+ static inline void init_timeout(struct aio_timeout *to)
+ {
+- init_timer(&to->timer);
+- to->timer.data = (unsigned long)to;
+- to->timer.function = timeout_func;
++ setup_timer_on_stack(&to->timer, timeout_func, (unsigned long) to);
+ to->timed_out = 0;
+ to->p = current;
+ }
+@@ -1166,7 +1172,10 @@ retry:
+ break;
+ if (min_nr <= i)
+ break;
+- ret = 0;
++ if (unlikely(ctx->dead)) {
++ ret = -EINVAL;
++ break;
++ }
+ if (to.timed_out) /* Only check after read evt */
+ break;
+ /* Try to only show up in io wait if there are ops
+@@ -1202,6 +1211,7 @@ retry:
+ if (timeout)
+ clear_timeout(&to);
+ out:
++ destroy_timer_on_stack(&to.timer);
+ return i ? i : ret;
+ }
+
+@@ -1231,6 +1241,13 @@ static void io_destroy(struct kioctx *ioctx)
+
+ aio_cancel_all(ioctx);
+ wait_for_all_aios(ioctx);
+
-+ spin_lock_irqsave(&balloon_lock, flags);
++ /*
++ * Wake up any waiters. The setting of ctx->dead must be seen
++ * by other CPUs at this point. Right now, we rely on the
++ * locking done by the above calls to ensure this consistency.
++ */
++ wake_up(&ioctx->wait);
+ put_ioctx(ioctx); /* once for the lookup */
+ }
+
+@@ -1542,7 +1559,7 @@ static int aio_wake_function(wait_queue_t *wait, unsigned mode,
+ return 1;
+ }
+
+-int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
++static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
+ struct iocb *iocb)
+ {
+ struct kiocb *req;
+@@ -1583,7 +1600,7 @@ int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
+ * event using the eventfd_signal() function.
+ */
+ req->ki_eventfd = eventfd_fget((int) iocb->aio_resfd);
+- if (unlikely(IS_ERR(req->ki_eventfd))) {
++ if (IS_ERR(req->ki_eventfd)) {
+ ret = PTR_ERR(req->ki_eventfd);
+ goto out_put_req;
+ }
+diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
+index 2d4ae40..c3d352d 100644
+--- a/fs/autofs4/autofs_i.h
++++ b/fs/autofs4/autofs_i.h
+@@ -35,7 +35,7 @@
+ /* #define DEBUG */
+
+ #ifdef DEBUG
+-#define DPRINTK(fmt,args...) do { printk(KERN_DEBUG "pid %d: %s: " fmt "\n" , current->pid , __FUNCTION__ , ##args); } while(0)
++#define DPRINTK(fmt,args...) do { printk(KERN_DEBUG "pid %d: %s: " fmt "\n" , current->pid , __func__ , ##args); } while(0)
+ #else
+ #define DPRINTK(fmt,args...) do {} while(0)
+ #endif
+diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
+index a54a946..aa4c5ff 100644
+--- a/fs/autofs4/root.c
++++ b/fs/autofs4/root.c
+@@ -533,9 +533,9 @@ static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct
+ goto next;
+
+ if (d_unhashed(dentry)) {
+- struct autofs_info *ino = autofs4_dentry_ino(dentry);
+ struct inode *inode = dentry->d_inode;
+
++ ino = autofs4_dentry_ino(dentry);
+ list_del_init(&ino->rehash);
+ dget(dentry);
+ /*
+diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
+index 82123ff..e8717de 100644
+--- a/fs/befs/linuxvfs.c
++++ b/fs/befs/linuxvfs.c
+@@ -489,9 +489,9 @@ static void befs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
+ {
+ befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
+ if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
+- char *p = nd_get_link(nd);
+- if (!IS_ERR(p))
+- kfree(p);
++ char *link = nd_get_link(nd);
++ if (!IS_ERR(link))
++ kfree(link);
+ }
+ }
+
+diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h
+index 71faf4d..70f5d3a 100644
+--- a/fs/bfs/bfs.h
++++ b/fs/bfs/bfs.h
+@@ -42,7 +42,7 @@ static inline struct bfs_inode_info *BFS_I(struct inode *inode)
+
+
+ #define printf(format, args...) \
+- printk(KERN_ERR "BFS-fs: %s(): " format, __FUNCTION__, ## args)
++ printk(KERN_ERR "BFS-fs: %s(): " format, __func__, ## args)
+
+ /* inode.c */
+ extern struct inode *bfs_iget(struct super_block *sb, unsigned long ino);
+diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
+index a1bb224..ba4cddb 100644
+--- a/fs/binfmt_aout.c
++++ b/fs/binfmt_aout.c
+@@ -372,21 +372,17 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+
+ flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data);
+ } else {
+- static unsigned long error_time, error_time2;
+ if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
+- (N_MAGIC(ex) != NMAGIC) && (jiffies-error_time2) > 5*HZ)
++ (N_MAGIC(ex) != NMAGIC) && printk_ratelimit())
+ {
+ printk(KERN_NOTICE "executable not page aligned\n");
+- error_time2 = jiffies;
+ }
+
+- if ((fd_offset & ~PAGE_MASK) != 0 &&
+- (jiffies-error_time) > 5*HZ)
++ if ((fd_offset & ~PAGE_MASK) != 0 && printk_ratelimit())
+ {
+ printk(KERN_WARNING
+ "fd_offset is not page aligned. Please convert program: %s\n",
+ bprm->file->f_path.dentry->d_name.name);
+- error_time = jiffies;
+ }
+
+ if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
+@@ -495,15 +491,13 @@ static int load_aout_library(struct file *file)
+ start_addr = ex.a_entry & 0xfffff000;
+
+ if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
+- static unsigned long error_time;
+ loff_t pos = N_TXTOFF(ex);
+
+- if ((jiffies-error_time) > 5*HZ)
++ if (printk_ratelimit())
+ {
+ printk(KERN_WARNING
+ "N_TXTOFF is not page aligned. Please convert library: %s\n",
+ file->f_path.dentry->d_name.name);
+- error_time = jiffies;
+ }
+ down_write(¤t->mm->mmap_sem);
+ do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
+diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
+index 5e1a4fb..b25707f 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;
+@@ -1276,26 +1255,23 @@ static int writenote(struct memelfnote *men, struct file *file,
+ static void fill_elf_header(struct elfhdr *elf, int segs,
+ u16 machine, u32 flags, u8 osabi)
+ {
++ memset(elf, 0, sizeof(*elf));
++
+ memcpy(elf->e_ident, ELFMAG, SELFMAG);
+ elf->e_ident[EI_CLASS] = ELF_CLASS;
+ elf->e_ident[EI_DATA] = ELF_DATA;
+ elf->e_ident[EI_VERSION] = EV_CURRENT;
+ elf->e_ident[EI_OSABI] = ELF_OSABI;
+- memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
+
+ elf->e_type = ET_CORE;
+ elf->e_machine = machine;
+ elf->e_version = EV_CURRENT;
+- elf->e_entry = 0;
+ elf->e_phoff = sizeof(struct elfhdr);
+- elf->e_shoff = 0;
+ elf->e_flags = flags;
+ elf->e_ehsize = sizeof(struct elfhdr);
+ elf->e_phentsize = sizeof(struct elf_phdr);
+ elf->e_phnum = segs;
+- elf->e_shentsize = 0;
+- elf->e_shnum = 0;
+- elf->e_shstrndx = 0;
+
-+ 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);
+ return;
+ }
+
+@@ -1746,26 +1722,25 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
+
+ info->thread_status_size = 0;
+ if (signr) {
+- struct elf_thread_status *tmp;
++ struct elf_thread_status *ets;
+ rcu_read_lock();
+ do_each_thread(g, p)
+ if (current->mm == p->mm && current != p) {
+- tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC);
+- if (!tmp) {
++ ets = kzalloc(sizeof(*ets), GFP_ATOMIC);
++ if (!ets) {
+ rcu_read_unlock();
+ return 0;
+ }
+- tmp->thread = p;
+- list_add(&tmp->list, &info->thread_list);
++ ets->thread = p;
++ list_add(&ets->list, &info->thread_list);
+ }
+ while_each_thread(g, p);
+ rcu_read_unlock();
+ list_for_each(t, &info->thread_list) {
+- struct elf_thread_status *tmp;
+ int sz;
+
+- tmp = list_entry(t, struct elf_thread_status, list);
+- sz = elf_dump_thread_status(signr, tmp);
++ ets = list_entry(t, struct elf_thread_status, list);
++ sz = elf_dump_thread_status(signr, ets);
+ info->thread_status_size += sz;
+ }
+ }
+@@ -2021,10 +1996,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un
+
+ for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) {
+ struct page *page;
+- struct vm_area_struct *vma;
++ struct vm_area_struct *tmp_vma;
+
+ if (get_user_pages(current, current->mm, addr, 1, 0, 1,
+- &page, &vma) <= 0) {
++ &page, &tmp_vma) <= 0) {
+ DUMP_SEEK(PAGE_SIZE);
+ } else {
+ if (page == ZERO_PAGE(0)) {
+@@ -2034,7 +2009,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un
+ }
+ } else {
+ void *kaddr;
+- flush_cache_page(vma, addr,
++ flush_cache_page(tmp_vma, addr,
+ page_to_pfn(page));
+ kaddr = kmap(page);
+ if ((size += PAGE_SIZE) > limit ||
+diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
+index 32649f2..ddd35d8 100644
+--- a/fs/binfmt_elf_fdpic.c
++++ b/fs/binfmt_elf_fdpic.c
+@@ -136,8 +136,8 @@ static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params,
+
+ retval = kernel_read(file, params->hdr.e_phoff,
+ (char *) params->phdrs, size);
+- if (retval < 0)
+- return retval;
++ if (unlikely(retval != size))
++ return retval < 0 ? retval : -ENOEXEC;
+
+ /* determine stack size for this binary */
+ phdr = params->phdrs;
+@@ -218,8 +218,11 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
+ phdr->p_offset,
+ interpreter_name,
+ phdr->p_filesz);
+- if (retval < 0)
++ if (unlikely(retval != phdr->p_filesz)) {
++ if (retval >= 0)
++ retval = -ENOEXEC;
+ goto error;
++ }
+
+ retval = -ENOENT;
+ if (interpreter_name[phdr->p_filesz - 1] != '\0')
+@@ -245,8 +248,11 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
+
+ retval = kernel_read(interpreter, 0, bprm->buf,
+ BINPRM_BUF_SIZE);
+- if (retval < 0)
++ if (unlikely(retval != BINPRM_BUF_SIZE)) {
++ if (retval >= 0)
++ retval = -ENOEXEC;
+ goto error;
++ }
+
+ interp_params.hdr = *((struct elfhdr *) bprm->buf);
+ break;
+diff --git a/fs/binfmt_em86.c b/fs/binfmt_em86.c
+index f95ae97..f9c88d0 100644
+--- a/fs/binfmt_em86.c
++++ b/fs/binfmt_em86.c
+@@ -43,7 +43,7 @@ static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
+ return -ENOEXEC;
+ }
+
+- bprm->sh_bang++; /* Well, the bang-shell is implicit... */
++ bprm->sh_bang = 1; /* Well, the bang-shell is implicit... */
+ allow_write_access(bprm->file);
+ fput(bprm->file);
+ bprm->file = NULL;
+diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
+index 0498b18..3b40d45 100644
+--- a/fs/binfmt_flat.c
++++ b/fs/binfmt_flat.c
+@@ -531,7 +531,8 @@ static int load_flat_file(struct linux_binprm * bprm,
+ DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
+
+ down_write(¤t->mm->mmap_sem);
+- textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_PRIVATE, 0);
++ textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
++ MAP_PRIVATE|MAP_EXECUTABLE, 0);
+ up_write(¤t->mm->mmap_sem);
+ if (!textpos || textpos >= (unsigned long) -4096) {
+ if (!textpos)
+@@ -932,14 +933,8 @@ static int __init init_flat_binfmt(void)
+ return register_binfmt(&flat_format);
+ }
+
+-static void __exit exit_flat_binfmt(void)
+-{
+- unregister_binfmt(&flat_format);
+-}
+-
+ /****************************************************************************/
+
+ core_initcall(init_flat_binfmt);
+-module_exit(exit_flat_binfmt);
+
+ /****************************************************************************/
+diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
+index b53c7e5..7191306 100644
+--- a/fs/binfmt_misc.c
++++ b/fs/binfmt_misc.c
+@@ -110,12 +110,17 @@ 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)
+ goto _ret;
+
++ retval = -ENOEXEC;
++ if (bprm->misc_bang)
++ goto _ret;
++
++ bprm->misc_bang = 1;
++
+ /* to keep locking time low, we copy the interpreter string */
+ read_lock(&entries_lock);
+ fmt = check_file(bprm);
+@@ -133,21 +138,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 +202,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 +209,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_script.c b/fs/binfmt_script.c
+index ab33939..9e3963f 100644
+--- a/fs/binfmt_script.c
++++ b/fs/binfmt_script.c
+@@ -29,7 +29,7 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
+ * Sorta complicated, but hopefully it will work. -TYT
+ */
+
+- bprm->sh_bang++;
++ bprm->sh_bang = 1;
+ allow_write_access(bprm->file);
+ fput(bprm->file);
+ bprm->file = NULL;
+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..799f86d 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;
+ }
+
-+ 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;
++ 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;
+
-+ /* 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;
-+ }
++ __bio_for_each_segment(bvec, bio, i, 0) {
++ char *bv_addr = page_address(bvec->bv_page);
++ unsigned int bv_len = bvec->bv_len;
+
-+ for (i = 0; i < nr_pages; i++) {
-+ page = balloon_retrieve();
-+ BUG_ON(page == NULL);
++ while (bv_len && iov_idx < iov_count) {
++ unsigned int bytes;
++ char *iov_addr;
+
-+ pfn = page_to_pfn(page);
-+ BUG_ON(!xen_feature(XENFEAT_auto_translated_physmap) &&
-+ phys_to_machine_mapping_valid(pfn));
++ bytes = min_t(unsigned int,
++ iov[iov_idx].iov_len - iov_off, bv_len);
++ iov_addr = iov[iov_idx].iov_base + iov_off;
+
-+ set_phys_to_machine(pfn, frame_list[i]);
++ 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);
+
-+ /* 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);
-+ }
++ if (ret)
++ ret = -EFAULT;
++ }
+
-+ /* Relinquish the page back to the allocator. */
-+ ClearPageReserved(page);
-+ init_page_count(page);
-+ __free_page(page);
-+ }
++ bv_len -= bytes;
++ bv_addr += bytes;
++ iov_addr += bytes;
++ iov_off += bytes;
+
-+ balloon_stats.current_pages += nr_pages;
-+ totalram_pages = balloon_stats.current_pages;
++ if (iov[iov_idx].iov_len == iov_off) {
++ iov_idx++;
++ iov_off = 0;
++ }
++ }
+
-+ out:
-+ spin_unlock_irqrestore(&balloon_lock, flags);
++ if (uncopy)
++ __free_page(bvec->bv_page);
++ }
+
-+ return 0;
++ return ret;
+}
+
-+static int decrease_reservation(unsigned long nr_pages)
-+{
-+ unsigned long pfn, i, flags;
-+ struct page *page;
-+ int need_sleep = 0;
+ /**
+ * 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;
-+ 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;
-+ }
+
+- __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;
+
-+ pfn = page_to_pfn(page);
-+ frame_list[i] = pfn_to_mfn(pfn);
++ uaddr = (unsigned long)iov[i].iov_base;
++ end = (uaddr + iov[i].iov_len + PAGE_SIZE - 1) >> PAGE_SHIFT;
++ start = uaddr >> PAGE_SHIFT;
+
-+ scrub_page(page);
++ nr_pages += end - start;
++ len += iov[i].iov_len;
+ }
+
-+ /* Ensure that ballooned highmem pages don't have kmaps. */
-+ kmap_flush_unused();
-+ flush_tlb_all();
++ 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;
+
-+ spin_lock_irqsave(&balloon_lock, flags);
++ iov.iov_base = (void __user *)uaddr;
++ iov.iov_len = len;
+
-+ /* 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));
-+ }
++ return bio_copy_user_iov(q, &iov, 1, write_to_vm);
++}
+
-+ 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);
+ static struct bio *__bio_map_user_iov(struct request_queue *q,
+ struct block_device *bdev,
+ struct sg_iovec *iov, int iov_count,
+@@ -861,6 +937,95 @@ struct bio *bio_map_kern(struct request_queue *q, void *data, unsigned int len,
+ return ERR_PTR(-EINVAL);
+ }
+
++static void bio_copy_kern_endio(struct bio *bio, int err)
++{
++ struct bio_vec *bvec;
++ const int read = bio_data_dir(bio) == READ;
++ char *p = bio->bi_private;
++ int i;
+
-+ balloon_stats.current_pages -= nr_pages;
-+ totalram_pages = balloon_stats.current_pages;
++ __bio_for_each_segment(bvec, bio, i, 0) {
++ char *addr = page_address(bvec->bv_page);
+
-+ spin_unlock_irqrestore(&balloon_lock, flags);
++ if (read && !err)
++ memcpy(p, addr, bvec->bv_len);
+
-+ return need_sleep;
++ __free_page(bvec->bv_page);
++ p += bvec->bv_len;
++ }
++
++ bio_put(bio);
+}
+
-+/*
-+ * 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.
++/**
++ * bio_copy_kern - copy kernel address into bio
++ * @q: the struct request_queue for the bio
++ * @data: pointer to buffer to copy
++ * @len: length in bytes
++ * @gfp_mask: allocation flags for bio and page allocation
++ *
++ * copy the kernel address into a bio suitable for io to a block
++ * device. Returns an error pointer in case of error.
+ */
-+static void balloon_process(struct work_struct *work)
++struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len,
++ gfp_t gfp_mask, int reading)
+{
-+ int need_sleep = 0;
-+ long credit;
++ unsigned long kaddr = (unsigned long)data;
++ unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
++ unsigned long start = kaddr >> PAGE_SHIFT;
++ const int nr_pages = end - start;
++ struct bio *bio;
++ struct bio_vec *bvec;
++ int i, ret;
+
-+ mutex_lock(&balloon_mutex);
++ bio = bio_alloc(gfp_mask, nr_pages);
++ if (!bio)
++ return ERR_PTR(-ENOMEM);
+
-+ 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);
++ while (len) {
++ struct page *page;
++ unsigned int bytes = PAGE_SIZE;
+
-+#ifndef CONFIG_PREEMPT
-+ if (need_resched())
-+ schedule();
-+#endif
-+ } while ((credit != 0) && !need_sleep);
++ if (bytes > len)
++ bytes = len;
+
-+ /* Schedule more work if there is some still to be done. */
-+ if (current_target() != balloon_stats.current_pages)
-+ mod_timer(&balloon_timer, jiffies + HZ);
++ page = alloc_page(q->bounce_gfp | gfp_mask);
++ if (!page) {
++ ret = -ENOMEM;
++ goto cleanup;
++ }
+
-+ mutex_unlock(&balloon_mutex);
-+}
++ if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes) {
++ ret = -EINVAL;
++ goto cleanup;
++ }
+
-+/* 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);
-+}
++ len -= bytes;
++ }
+
-+static struct xenbus_watch target_watch =
-+{
-+ .node = "memory/target"
-+};
++ if (!reading) {
++ void *p = data;
+
-+/* 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;
++ bio_for_each_segment(bvec, bio, i) {
++ char *addr = page_address(bvec->bv_page);
+
-+ err = xenbus_scanf(XBT_NIL, "memory", "target", "%llu", &new_target);
-+ if (err != 1) {
-+ /* This is ok (for domain0 at least) - so just return */
-+ return;
++ memcpy(addr, p, bvec->bv_len);
++ p += bvec->bv_len;
++ }
+ }
+
-+ /* 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));
++ bio->bi_private = data;
++ bio->bi_end_io = bio_copy_kern_endio;
++ return bio;
++cleanup:
++ bio_for_each_segment(bvec, bio, i)
++ __free_page(bvec->bv_page);
++
++ bio_put(bio);
++
++ return ERR_PTR(ret);
+}
+
-+static int balloon_init_watcher(struct notifier_block *notifier,
-+ unsigned long event,
-+ void *data)
-+{
-+ int err;
+ /*
+ * bio_set_pages_dirty() and bio_check_pages_dirty() are support functions
+ * for performing direct-IO in BIOs.
+@@ -1197,6 +1362,7 @@ EXPORT_SYMBOL(bio_get_nr_vecs);
+ EXPORT_SYMBOL(bio_map_user);
+ EXPORT_SYMBOL(bio_unmap_user);
+ EXPORT_SYMBOL(bio_map_kern);
++EXPORT_SYMBOL(bio_copy_kern);
+ EXPORT_SYMBOL(bio_pair_release);
+ EXPORT_SYMBOL(bio_split);
+ EXPORT_SYMBOL(bio_split_pool);
+diff --git a/fs/buffer.c b/fs/buffer.c
+index 39ff144..a073f3f 100644
+--- a/fs/buffer.c
++++ b/fs/buffer.c
+@@ -360,16 +360,19 @@ void invalidate_bdev(struct block_device *bdev)
+ */
+ static void free_more_memory(void)
+ {
+- struct zone **zones;
+- pg_data_t *pgdat;
++ struct zone *zone;
++ int nid;
+
+ wakeup_pdflush(1024);
+ yield();
+
+- for_each_online_pgdat(pgdat) {
+- zones = pgdat->node_zonelists[gfp_zone(GFP_NOFS)].zones;
+- if (*zones)
+- try_to_free_pages(zones, 0, GFP_NOFS);
++ for_each_online_node(nid) {
++ (void)first_zones_zonelist(node_zonelist(nid, GFP_NOFS),
++ gfp_zone(GFP_NOFS), NULL,
++ &zone);
++ if (zone)
++ try_to_free_pages(node_zonelist(nid, GFP_NOFS), 0,
++ GFP_NOFS);
+ }
+ }
+
+@@ -1098,7 +1101,7 @@ grow_buffers(struct block_device *bdev, sector_t block, int size)
+
+ printk(KERN_ERR "%s: requested out-of-range block %llu for "
+ "device %s\n",
+- __FUNCTION__, (unsigned long long)block,
++ __func__, (unsigned long long)block,
+ bdevname(bdev, b));
+ return -EIO;
+ }
+@@ -2208,8 +2211,8 @@ out:
+ return err;
+ }
+
+-int cont_expand_zero(struct file *file, struct address_space *mapping,
+- loff_t pos, loff_t *bytes)
++static int cont_expand_zero(struct file *file, struct address_space *mapping,
++ loff_t pos, loff_t *bytes)
+ {
+ struct inode *inode = mapping->host;
+ unsigned blocksize = 1 << inode->i_blkbits;
+@@ -2243,6 +2246,8 @@ int cont_expand_zero(struct file *file, struct address_space *mapping,
+ goto out;
+ BUG_ON(err != len);
+ err = 0;
+
-+ err = register_xenbus_watch(&target_watch);
-+ if (err)
-+ printk(KERN_ERR "Failed to set balloon watcher\n");
++ balance_dirty_pages_ratelimited(mapping);
+ }
+
+ /* page covers the boundary, find the boundary offset */
+@@ -2323,23 +2328,6 @@ int block_commit_write(struct page *page, unsigned from, unsigned to)
+ return 0;
+ }
+
+-int generic_commit_write(struct file *file, struct page *page,
+- unsigned from, unsigned to)
+-{
+- struct inode *inode = page->mapping->host;
+- loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+- __block_commit_write(inode,page,from,to);
+- /*
+- * No need to use i_size_read() here, the i_size
+- * cannot change under us because we hold i_mutex.
+- */
+- if (pos > inode->i_size) {
+- i_size_write(inode, pos);
+- mark_inode_dirty(inode);
+- }
+- return 0;
+-}
+-
+ /*
+ * block_page_mkwrite() is not allowed to change the file size as it gets
+ * called from a page fault handler when a page is first dirtied. Hence we must
+@@ -3180,8 +3168,7 @@ static void recalc_bh_state(void)
+
+ struct buffer_head *alloc_buffer_head(gfp_t gfp_flags)
+ {
+- struct buffer_head *ret = kmem_cache_alloc(bh_cachep,
+- set_migrateflags(gfp_flags, __GFP_RECLAIMABLE));
++ struct buffer_head *ret = kmem_cache_alloc(bh_cachep, gfp_flags);
+ if (ret) {
+ INIT_LIST_HEAD(&ret->b_assoc_buffers);
+ get_cpu_var(bh_accounting).nr++;
+@@ -3311,7 +3298,6 @@ EXPORT_SYMBOL(end_buffer_write_sync);
+ EXPORT_SYMBOL(file_fsync);
+ EXPORT_SYMBOL(fsync_bdev);
+ EXPORT_SYMBOL(generic_block_bmap);
+-EXPORT_SYMBOL(generic_commit_write);
+ EXPORT_SYMBOL(generic_cont_expand_simple);
+ EXPORT_SYMBOL(init_buffer);
+ EXPORT_SYMBOL(invalidate_bdev);
+diff --git a/fs/char_dev.c b/fs/char_dev.c
+index 038674a..68e510b 100644
+--- a/fs/char_dev.c
++++ b/fs/char_dev.c
+@@ -55,7 +55,6 @@ static struct char_device_struct {
+ unsigned int baseminor;
+ int minorct;
+ char name[64];
+- struct file_operations *fops;
+ struct cdev *cdev; /* will die */
+ } *chrdevs[CHRDEV_MAJOR_HASH_SIZE];
+
+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.
+
-+ return NOTIFY_DONE;
-+}
++Please see
++ http://protocolfreedom.org/ and
++ http://samba.org/samba/PFIF/
++for more details.
+
-+static struct notifier_block xenstore_notifier;
+
+ For questions or bug reports please contact:
+ sfrench at samba.org (sfrench at us.ibm.com)
+diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
+index 0228ed0..cc950f6 100644
+--- a/fs/cifs/cifs_debug.c
++++ b/fs/cifs/cifs_debug.c
+@@ -468,7 +468,7 @@ cifs_proc_init(void)
+ {
+ struct proc_dir_entry *pde;
+
+- proc_fs_cifs = proc_mkdir("cifs", proc_root_fs);
++ proc_fs_cifs = proc_mkdir("fs/cifs", NULL);
+ if (proc_fs_cifs == NULL)
+ return;
+
+@@ -559,7 +559,7 @@ cifs_proc_clean(void)
+ remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
+ remove_proc_entry("Experimental", proc_fs_cifs);
+ remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
+- remove_proc_entry("cifs", proc_root_fs);
++ remove_proc_entry("fs/cifs", NULL);
+ }
+
+ static int
+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 int __init balloon_init(void)
++static void cifs_dfs_expire_automounts(struct work_struct *work)
+{
-+ unsigned long pfn;
-+ struct page *page;
-+
-+ if (!is_running_on_xen())
-+ return -ENODEV;
++ struct list_head *list = &cifs_dfs_automount_list;
+
-+ pr_info("xen_balloon: Initialising balloon driver.\n");
++ mark_mounts_for_expiry(list);
++ if (!list_empty(list))
++ schedule_delayed_work(&cifs_dfs_automount_task,
++ cifs_dfs_mountpoint_expiry_timeout);
++}
+
+-void dfs_shrink_umount_helper(struct vfsmount *vfsmnt)
++void cifs_dfs_release_automount_timer(void)
+ {
+- mark_mounts_for_expiry(&cifs_dfs_automount_list);
+- mark_mounts_for_expiry(&cifs_dfs_automount_list);
++ BUG_ON(!list_empty(&cifs_dfs_automount_list));
++ cancel_delayed_work(&cifs_dfs_automount_task);
++ flush_scheduled_work();
+ }
+
+ /**
+@@ -261,10 +273,11 @@ static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd,
+ err = do_add_mount(newmnt, nd, nd->path.mnt->mnt_flags, mntlist);
+ switch (err) {
+ case 0:
+- dput(nd->path.dentry);
+- mntput(nd->path.mnt);
++ path_put(&nd->path);
+ nd->path.mnt = newmnt;
+ nd->path.dentry = dget(newmnt->mnt_root);
++ schedule_delayed_work(&cifs_dfs_automount_task,
++ cifs_dfs_mountpoint_expiry_timeout);
+ break;
+ case -EBUSY:
+ /* someone else made a mount here whilst we were busy */
+diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
+index 1cb5b0a..e99d4fa 100644
+--- a/fs/cifs/cifsacl.c
++++ b/fs/cifs/cifsacl.c
+@@ -516,7 +516,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
+
+ /* Convert permission bits from mode to equivalent CIFS ACL */
+ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
+- int acl_len, struct inode *inode, __u64 nmode)
++ struct inode *inode, __u64 nmode)
+ {
+ int rc = 0;
+ __u32 dacloffset;
+@@ -692,14 +692,14 @@ void acl_to_uid_mode(struct inode *inode, const char *path, const __u16 *pfid)
+ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
+ {
+ int rc = 0;
+- __u32 acllen = 0;
++ __u32 secdesclen = 0;
+ struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
+ struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
+
+ cFYI(DBG2, ("set ACL from mode for %s", path));
+
+ /* Get the security descriptor */
+- pntsd = get_cifs_acl(&acllen, inode, path, NULL);
++ pntsd = get_cifs_acl(&secdesclen, inode, path, NULL);
+
+ /* Add three ACEs for owner, group, everyone getting rid of
+ other ACEs as chmod disables ACEs and set the security descriptor */
+@@ -709,20 +709,22 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
+ set security descriptor request security descriptor
+ parameters, and secuirty descriptor itself */
+
+- pnntsd = kmalloc(acllen, GFP_KERNEL);
++ secdesclen = secdesclen < DEFSECDESCLEN ?
++ DEFSECDESCLEN : secdesclen;
++ pnntsd = kmalloc(secdesclen, GFP_KERNEL);
+ if (!pnntsd) {
+ cERROR(1, ("Unable to allocate security descriptor"));
+ kfree(pntsd);
+ return (-ENOMEM);
+ }
+
+- rc = build_sec_desc(pntsd, pnntsd, acllen, inode, nmode);
++ rc = build_sec_desc(pntsd, pnntsd, inode, nmode);
+
+ cFYI(DBG2, ("build_sec_desc rc: %d", rc));
+
+ if (!rc) {
+ /* Set the security descriptor */
+- rc = set_cifs_acl(pnntsd, acllen, inode, path);
++ rc = set_cifs_acl(pnntsd, secdesclen, inode, path);
+ cFYI(DBG2, ("set_cifs_acl rc: %d", rc));
+ }
+
+diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
+index 93a7c34..6c8096c 100644
+--- a/fs/cifs/cifsacl.h
++++ b/fs/cifs/cifsacl.h
+@@ -27,6 +27,7 @@
+ #define NUM_SUBAUTHS 5 /* number of sub authority fields */
+ #define NUM_WK_SIDS 7 /* number of well known sids */
+ #define SIDNAMELENGTH 20 /* long enough for the ones we care about */
++#define DEFSECDESCLEN 192 /* sec desc len contaiting a dacl with three aces */
+
+ #define READ_BIT 0x4
+ #define WRITE_BIT 0x2
+diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
+index a04b17e..39c2cbd 100644
+--- a/fs/cifs/cifsfs.c
++++ b/fs/cifs/cifsfs.c
+@@ -466,16 +466,11 @@ static struct quotactl_ops cifs_quotactl_ops = {
+ };
+ #endif
+
+-static void cifs_umount_begin(struct vfsmount *vfsmnt, int flags)
++static void cifs_umount_begin(struct super_block *sb)
+ {
+- struct cifs_sb_info *cifs_sb;
++ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifsTconInfo *tcon;
+
+- dfs_shrink_umount_helper(vfsmnt);
+-
+- if (!(flags & MNT_FORCE))
+- return;
+- cifs_sb = CIFS_SB(vfsmnt->mnt_sb);
+ if (cifs_sb == NULL)
+ return;
+
+@@ -1100,6 +1095,7 @@ exit_cifs(void)
+ cFYI(DBG2, ("exit_cifs"));
+ cifs_proc_clean();
+ #ifdef CONFIG_CIFS_DFS_UPCALL
++ cifs_dfs_release_automount_timer();
+ unregister_key_type(&key_type_dns_resolver);
+ #endif
+ #ifdef CONFIG_CIFS_UPCALL
+diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
+index 6897830..e1dd9f3 100644
+--- a/fs/cifs/cifsfs.h
++++ b/fs/cifs/cifsfs.h
+@@ -62,11 +62,9 @@ extern int cifs_setattr(struct dentry *, struct iattr *);
+
+ extern const struct inode_operations cifs_file_inode_ops;
+ extern const struct inode_operations cifs_symlink_inode_ops;
+-extern struct list_head cifs_dfs_automount_list;
+ extern struct inode_operations cifs_dfs_referral_inode_operations;
+
+
+-
+ /* Functions related to files and directories */
+ extern const struct file_operations cifs_file_ops;
+ extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */
+diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
+index 47f7950..9f49c2f 100644
+--- a/fs/cifs/cifspdu.h
++++ b/fs/cifs/cifspdu.h
+@@ -1,7 +1,7 @@
+ /*
+ * fs/cifs/cifspdu.h
+ *
+- * Copyright (c) International Business Machines Corp., 2002,2007
++ * Copyright (c) International Business Machines Corp., 2002,2008
+ * Author(s): Steve French (sfrench at us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+@@ -163,7 +163,10 @@
+ path names in response */
+ #define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
+ #define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
++#define SMBFLG2_COMPRESSED (8)
++#define SMBFLG2_SECURITY_SIGNATURE_REQUIRED (0x10)
+ #define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
++#define SMBFLG2_REPARSE_PATH (0x400)
+ #define SMBFLG2_EXT_SEC cpu_to_le16(0x800)
+ #define SMBFLG2_DFS cpu_to_le16(0x1000)
+ #define SMBFLG2_PAGING_IO cpu_to_le16(0x2000)
+@@ -305,7 +308,7 @@
+ #define FILE_SHARE_DELETE 0x00000004
+ #define FILE_SHARE_ALL 0x00000007
+
+-/* CreateDisposition flags */
++/* CreateDisposition flags, similar to CreateAction as well */
+ #define FILE_SUPERSEDE 0x00000000
+ #define FILE_OPEN 0x00000001
+ #define FILE_CREATE 0x00000002
+@@ -317,15 +320,25 @@
+ #define CREATE_NOT_FILE 0x00000001 /* if set must not be file */
+ #define CREATE_WRITE_THROUGH 0x00000002
+ #define CREATE_SEQUENTIAL 0x00000004
+-#define CREATE_SYNC_ALERT 0x00000010
+-#define CREATE_ASYNC_ALERT 0x00000020
++#define CREATE_NO_BUFFER 0x00000008 /* should not buffer on srv */
++#define CREATE_SYNC_ALERT 0x00000010 /* MBZ */
++#define CREATE_ASYNC_ALERT 0x00000020 /* MBZ */
+ #define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */
++#define CREATE_TREE_CONNECTION 0x00000080 /* should be zero */
++#define CREATE_COMPLETE_IF_OPLK 0x00000100 /* should be zero */
+ #define CREATE_NO_EA_KNOWLEDGE 0x00000200
+-#define CREATE_EIGHT_DOT_THREE 0x00000400
++#define CREATE_EIGHT_DOT_THREE 0x00000400 /* doc says this is obsolete
++ open for recovery flag - should
++ be zero */
+ #define CREATE_RANDOM_ACCESS 0x00000800
+ #define CREATE_DELETE_ON_CLOSE 0x00001000
+ #define CREATE_OPEN_BY_ID 0x00002000
++#define CREATE_OPEN_BACKUP_INTN 0x00004000
++#define CREATE_NO_COMPRESSION 0x00008000
++#define CREATE_RESERVE_OPFILTER 0x00100000 /* should be zero */
+ #define OPEN_REPARSE_POINT 0x00200000
++#define OPEN_NO_RECALL 0x00400000
++#define OPEN_FREE_SPACE_QUERY 0x00800000 /* should be zero */
+ #define CREATE_OPTIONS_MASK 0x007FFFFF
+ #define CREATE_OPTION_SPECIAL 0x20000000 /* system. NB not sent over wire */
+
+@@ -470,7 +483,7 @@ typedef struct lanman_neg_rsp {
+
+ typedef struct negotiate_rsp {
+ struct smb_hdr hdr; /* wct = 17 */
+- __le16 DialectIndex;
++ __le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
+ __u8 SecurityMode;
+ __le16 MaxMpxCount;
+ __le16 MaxNumberVcs;
+@@ -516,10 +529,11 @@ typedef struct negotiate_rsp {
+ #define CAP_INFOLEVEL_PASSTHRU 0x00002000
+ #define CAP_LARGE_READ_X 0x00004000
+ #define CAP_LARGE_WRITE_X 0x00008000
++#define CAP_LWIO 0x00010000 /* support fctl_srv_req_resume_key */
+ #define CAP_UNIX 0x00800000
+-#define CAP_RESERVED 0x02000000
+-#define CAP_BULK_TRANSFER 0x20000000
+-#define CAP_COMPRESSED_DATA 0x40000000
++#define CAP_COMPRESSED_DATA 0x02000000
++#define CAP_DYNAMIC_REAUTH 0x20000000
++#define CAP_PERSISTENT_HANDLES 0x40000000
+ #define CAP_EXTENDED_SECURITY 0x80000000
+
+ typedef union smb_com_session_setup_andx {
+@@ -668,9 +682,7 @@ typedef struct smb_com_tconx_req {
+ } __attribute__((packed)) TCONX_REQ;
+
+ typedef struct smb_com_tconx_rsp {
+- struct smb_hdr hdr; /* wct = 3 note that Win2000 has sent wct = 7
+- in some cases on responses. Four unspecified
+- words followed OptionalSupport */
++ struct smb_hdr hdr; /* wct = 3 , not extended response */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+@@ -680,13 +692,48 @@ typedef struct smb_com_tconx_rsp {
+ /* STRING NativeFileSystem */
+ } __attribute__((packed)) TCONX_RSP;
+
++typedef struct smb_com_tconx_rsp_ext {
++ struct smb_hdr hdr; /* wct = 7, extended response */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __le16 AndXOffset;
++ __le16 OptionalSupport; /* see below */
++ __le32 MaximalShareAccessRights;
++ __le32 GuestMaximalShareAccessRights;
++ __u16 ByteCount;
++ unsigned char Service[1]; /* always ASCII, not Unicode */
++ /* STRING NativeFileSystem */
++} __attribute__((packed)) TCONX_RSP_EXT;
+
-+ 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;
+ /* tree connect Flags */
+ #define DISCONNECT_TID 0x0001
++#define TCON_EXTENDED_SIGNATURES 0x0004
+ #define TCON_EXTENDED_SECINFO 0x0008
+
-+ register_balloon(&balloon_sysdev);
+ /* 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
+
-+ /* 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);
-+ }
++#define SMB_UNIQUE_FILE_NAME 0x0010
++#define SMB_EXTENDED_SIGNATURES 0x0020
+
-+ target_watch.callback = watch_target;
-+ xenstore_notifier.notifier_call = balloon_init_watcher;
++/* 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
+
-+ register_xenstore_notifier(&xenstore_notifier);
+ 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;
+
-+ return 0;
-+}
+
-+subsys_initcall(balloon_init);
+ /* 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);
+ }
+
+
-+static void balloon_exit(void)
++void DeleteTconOplockQEntries(struct cifsTconInfo *tcon)
+{
-+ /* XXX - release balloon here */
-+ return;
-+}
-+
-+module_exit(balloon_exit);
++ struct oplock_q_entry *temp;
+
-+static void balloon_update_driver_allowance(long delta)
-+{
-+ unsigned long flags;
++ if (tcon == NULL)
++ return;
+
-+ spin_lock_irqsave(&balloon_lock, flags);
-+ balloon_stats.driver_pages += delta;
-+ spin_unlock_irqrestore(&balloon_lock, flags);
++ 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);
+}
+
-+static int dealloc_pte_fn(
-+ pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
+ int
+ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
+ unsigned int smb_buf_length, struct sockaddr *sin)
+diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
+index 95a5425..e1c8548 100644
+--- a/fs/coda/coda_linux.c
++++ b/fs/coda/coda_linux.c
+@@ -134,7 +134,7 @@ void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
+ unsigned int valid;
+
+ /* clean out */
+- vattr->va_mode = (umode_t) -1;
++ vattr->va_mode = -1;
+ vattr->va_uid = (vuid_t) -1;
+ vattr->va_gid = (vgid_t) -1;
+ vattr->va_size = (off_t) -1;
+diff --git a/fs/coda/dir.c b/fs/coda/dir.c
+index f89ff08..3d2580e 100644
+--- a/fs/coda/dir.c
++++ b/fs/coda/dir.c
+@@ -345,7 +345,7 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de,
+ }
+
+ /* destruction routines: unlink, rmdir */
+-int coda_unlink(struct inode *dir, struct dentry *de)
++static int coda_unlink(struct inode *dir, struct dentry *de)
+ {
+ int error;
+ const char *name = de->d_name.name;
+@@ -365,7 +365,7 @@ int coda_unlink(struct inode *dir, struct dentry *de)
+ return 0;
+ }
+
+-int coda_rmdir(struct inode *dir, struct dentry *de)
++static int coda_rmdir(struct inode *dir, struct dentry *de)
+ {
+ const char *name = de->d_name.name;
+ int len = de->d_name.len;
+@@ -424,7 +424,7 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
+
+
+ /* file operations for directories */
+-int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
++static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
+ {
+ struct coda_file_info *cfi;
+ struct file *host_file;
+diff --git a/fs/compat.c b/fs/compat.c
+index 2ce4456..139dc93 100644
+--- a/fs/compat.c
++++ b/fs/compat.c
+@@ -1634,7 +1634,7 @@ sticky:
+ return ret;
+ }
+
+-#ifdef TIF_RESTORE_SIGMASK
++#ifdef HAVE_SET_RESTORE_SIGMASK
+ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
+ compat_ulong_t __user *outp, compat_ulong_t __user *exp,
+ struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,
+@@ -1720,7 +1720,7 @@ sticky:
+ if (sigmask) {
+ memcpy(¤t->saved_sigmask, &sigsaved,
+ sizeof(sigsaved));
+- set_thread_flag(TIF_RESTORE_SIGMASK);
++ set_restore_sigmask();
+ }
+ } else if (sigmask)
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+@@ -1791,7 +1791,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
+ if (sigmask) {
+ memcpy(¤t->saved_sigmask, &sigsaved,
+ sizeof(sigsaved));
+- set_thread_flag(TIF_RESTORE_SIGMASK);
++ set_restore_sigmask();
+ }
+ ret = -ERESTARTNOHAND;
+ } else if (sigmask)
+@@ -1825,7 +1825,7 @@ sticky:
+
+ return ret;
+ }
+-#endif /* TIF_RESTORE_SIGMASK */
++#endif /* HAVE_SET_RESTORE_SIGMASK */
+
+ #if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
+ /* Stuff for NFS server syscalls... */
+@@ -2080,7 +2080,7 @@ long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2)
+
+ #ifdef CONFIG_EPOLL
+
+-#ifdef TIF_RESTORE_SIGMASK
++#ifdef HAVE_SET_RESTORE_SIGMASK
+ asmlinkage long compat_sys_epoll_pwait(int epfd,
+ struct compat_epoll_event __user *events,
+ int maxevents, int timeout,
+@@ -2117,14 +2117,14 @@ asmlinkage long compat_sys_epoll_pwait(int epfd,
+ if (err == -EINTR) {
+ memcpy(¤t->saved_sigmask, &sigsaved,
+ sizeof(sigsaved));
+- set_thread_flag(TIF_RESTORE_SIGMASK);
++ set_restore_sigmask();
+ } else
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+ }
+
+ return err;
+ }
+-#endif /* TIF_RESTORE_SIGMASK */
++#endif /* HAVE_SET_RESTORE_SIGMASK */
+
+ #endif /* CONFIG_EPOLL */
+
+diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
+index c6e72ae..97dba0d 100644
+--- a/fs/compat_ioctl.c
++++ b/fs/compat_ioctl.c
+@@ -1046,14 +1046,14 @@ static int vt_check(struct file *file)
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct vc_data *vc;
+
+- if (file->f_op->ioctl != tty_ioctl)
++ if (file->f_op->unlocked_ioctl != tty_ioctl)
+ return -EINVAL;
+
+ tty = (struct tty_struct *)file->private_data;
+ if (tty_paranoia_check(tty, inode, "tty_ioctl"))
+ return -EINVAL;
+
+- if (tty->driver->ioctl != vt_ioctl)
++ if (tty->ops->ioctl != vt_ioctl)
+ return -EINVAL;
+
+ vc = (struct vc_data *)tty->driver_data;
+diff --git a/fs/configfs/file.c b/fs/configfs/file.c
+index 397cb50..2b6cb23 100644
+--- a/fs/configfs/file.c
++++ b/fs/configfs/file.c
+@@ -115,7 +115,7 @@ configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *pp
+ goto out;
+ }
+ pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
+- __FUNCTION__, count, *ppos, buffer->page);
++ __func__, count, *ppos, buffer->page);
+ retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
+ buffer->count);
+ out:
+diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
+index 4c1ebff..b9a1d81 100644
+--- a/fs/configfs/inode.c
++++ b/fs/configfs/inode.c
+@@ -47,7 +47,7 @@ static const struct address_space_operations configfs_aops = {
+
+ static struct backing_dev_info configfs_backing_dev_info = {
+ .ra_pages = 0, /* No readahead */
+- .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
++ .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK,
+ };
+
+ static const struct inode_operations configfs_inode_operations ={
+diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
+index de3b31d..8421cea 100644
+--- a/fs/configfs/mount.c
++++ b/fs/configfs/mount.c
+@@ -92,7 +92,7 @@ static int configfs_fill_super(struct super_block *sb, void *data, int silent)
+
+ root = d_alloc_root(inode);
+ if (!root) {
+- pr_debug("%s: could not get root dentry!\n",__FUNCTION__);
++ pr_debug("%s: could not get root dentry!\n",__func__);
+ iput(inode);
+ return -ENOMEM;
+ }
+diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c
+index 78929ea..2a731ef 100644
+--- a/fs/configfs/symlink.c
++++ b/fs/configfs/symlink.c
+@@ -210,13 +210,13 @@ static int configfs_get_target_path(struct config_item * item, struct config_ite
+ if (size > PATH_MAX)
+ return -ENAMETOOLONG;
+
+- pr_debug("%s: depth = %d, size = %d\n", __FUNCTION__, depth, size);
++ pr_debug("%s: depth = %d, size = %d\n", __func__, depth, size);
+
+ for (s = path; depth--; s += 3)
+ strcpy(s,"../");
+
+ fill_item_path(target, path, size);
+- pr_debug("%s: path = '%s'\n", __FUNCTION__, path);
++ pr_debug("%s: path = '%s'\n", __func__, path);
+
+ return 0;
+ }
+diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
+index 350680f..0c3b618 100644
+--- a/fs/cramfs/inode.c
++++ b/fs/cramfs/inode.c
+@@ -23,7 +23,6 @@
+ #include <linux/buffer_head.h>
+ #include <linux/vfs.h>
+ #include <linux/mutex.h>
+-#include <asm/semaphore.h>
+
+ #include <asm/uaccess.h>
+
+diff --git a/fs/dcache.c b/fs/dcache.c
+index 4345577..3ee588d 100644
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -1746,12 +1746,21 @@ shouldnt_be_hashed:
+ goto shouldnt_be_hashed;
+ }
+
++static int prepend(char **buffer, int *buflen, const char *str,
++ int namelen)
+{
-+ 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);
++ *buflen -= namelen;
++ if (*buflen < 0)
++ return -ENAMETOOLONG;
++ *buffer -= namelen;
++ memcpy(*buffer, str, namelen);
+ 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);
+ /**
+ * 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)
+
-+ scrub_page(page);
++ 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_irqsave(&balloon_lock, flags);
++ 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 = '/';
+
-+ 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);
-+ }
++ for (;;) {
++ struct dentry *parent;
++ if (IS_ROOT(dentry))
++ break;
+
-+ if (ret != 0) {
-+ spin_unlock_irqrestore(&balloon_lock, flags);
-+ __free_page(page);
-+ goto err;
-+ }
++ parent = dentry->d_parent;
++ prefetch(parent);
+
-+ totalram_pages = --balloon_stats.current_pages;
++ if ((prepend(&end, &buflen, dentry->d_name.name,
++ dentry->d_name.len) != 0) ||
++ (prepend(&end, &buflen, "/", 1) != 0))
++ goto Elong;
+
-+ spin_unlock_irqrestore(&balloon_lock, flags);
++ retval = end;
++ dentry = parent;
+ }
-+
-+ 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;
++ spin_unlock(&dcache_lock);
++ return retval;
++Elong:
++ spin_unlock(&dcache_lock);
++ return ERR_PTR(-ENAMETOOLONG);
+}
+
-+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);
-+}
++/*
+ * 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/debugfs/file.c b/fs/debugfs/file.c
+index fddffe4..159a5ef 100644
+--- a/fs/debugfs/file.c
++++ b/fs/debugfs/file.c
+@@ -9,7 +9,7 @@
+ * 2 as published by the Free Software Foundation.
+ *
+ * debugfs is for people to use instead of /proc or /sys.
+- * See Documentation/DocBook/kernel-api for more details.
++ * See Documentation/DocBook/filesystems for more details.
+ *
+ */
+
+diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
+index f120e12..285b64a 100644
+--- a/fs/devpts/inode.c
++++ b/fs/devpts/inode.c
+@@ -17,6 +17,8 @@
+ #include <linux/namei.h>
+ #include <linux/mount.h>
+ #include <linux/tty.h>
++#include <linux/mutex.h>
++#include <linux/idr.h>
+ #include <linux/devpts_fs.h>
+ #include <linux/parser.h>
+ #include <linux/fsnotify.h>
+@@ -26,6 +28,10 @@
+
+ #define DEVPTS_DEFAULT_MODE 0600
+
++extern int pty_limit; /* Config limit on Unix98 ptys */
++static DEFINE_IDR(allocated_ptys);
++static DEFINE_MUTEX(allocated_ptys_lock);
+
-+static void balloon_release_driver_page(struct page *page)
+ static struct vfsmount *devpts_mnt;
+ static struct dentry *devpts_root;
+
+@@ -171,9 +177,44 @@ static struct dentry *get_node(int num)
+ return lookup_one_len(s, root, sprintf(s, "%d", num));
+ }
+
++int devpts_new_index(void)
+{
-+ 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);
-+}
-+
++ int index;
++ int idr_ret;
+
-+#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)
++retry:
++ if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) {
++ return -ENOMEM;
++ }
+
-+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));
++ mutex_lock(&allocated_ptys_lock);
++ idr_ret = idr_get_new(&allocated_ptys, NULL, &index);
++ if (idr_ret < 0) {
++ mutex_unlock(&allocated_ptys_lock);
++ if (idr_ret == -EAGAIN)
++ goto retry;
++ return -EIO;
++ }
+
-+static ssize_t show_target_kb(struct sys_device *dev, char *buf)
-+{
-+ return sprintf(buf, "%lu\n", PAGES2KB(balloon_stats.target_pages));
++ if (index >= pty_limit) {
++ idr_remove(&allocated_ptys, index);
++ mutex_unlock(&allocated_ptys_lock);
++ return -EIO;
++ }
++ mutex_unlock(&allocated_ptys_lock);
++ return index;
+}
+
-+static ssize_t store_target_kb(struct sys_device *dev,
-+ const char *buf,
-+ size_t count)
++void devpts_kill_index(int idx)
+{
-+ 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;
++ mutex_lock(&allocated_ptys_lock);
++ idr_remove(&allocated_ptys, idx);
++ mutex_unlock(&allocated_ptys_lock);
+}
+
-+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,
-+};
+ int devpts_pty_new(struct tty_struct *tty)
+ {
+- int number = tty->index;
++ int number = tty->index; /* tty layer puts index from devpts_new_index() in here */
+ struct tty_driver *driver = tty->driver;
+ dev_t device = MKDEV(driver->major, driver->minor_start+number);
+ struct dentry *dentry;
+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;
+
-+static int register_balloon(struct sys_device *sysdev)
-+{
-+ int i, error;
++ 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++;
++ }
+
-+ error = sysdev_class_register(&balloon_sysdev_class);
-+ if (error)
-+ return error;
++ if (ids_count != i)
++ printk(KERN_ERR "dlm: bad nodeid count %d %d\n", ids_count, i);
+
-+ sysdev->id = 0;
-+ sysdev->cls = &balloon_sysdev_class;
++ if (!new_count)
++ goto out_ids;
+
-+ error = sysdev_register(sysdev);
-+ if (error) {
-+ sysdev_class_unregister(&balloon_sysdev_class);
-+ return error;
++ new = kcalloc(new_count, sizeof(int), GFP_KERNEL);
++ if (!new) {
++ kfree(ids);
++ rv = -ENOMEM;
++ goto out;
+ }
-+
-+ for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++) {
-+ error = sysdev_create_file(sysdev, balloon_attrs[i]);
-+ if (error)
-+ goto fail;
+
+- 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;
++ }
+ }
-+
-+ error = sysfs_create_group(&sysdev->kobj, &balloon_info_group);
++ *new_count_out = new_count;
++ *new_out = new;
+
++ out_ids:
++ *ids_count_out = ids_count;
+ *ids_out = ids;
+ out:
+ mutex_unlock(&sp->members_lock);
+diff --git a/fs/dlm/config.h b/fs/dlm/config.h
+index a3170fe..4f1d6fc 100644
+--- a/fs/dlm/config.h
++++ b/fs/dlm/config.h
+@@ -35,7 +35,8 @@ extern struct dlm_config_info dlm_config;
+ int dlm_config_init(void);
+ void dlm_config_exit(void);
+ int dlm_node_weight(char *lsname, int nodeid);
+-int dlm_nodeid_list(char *lsname, int **ids_out);
++int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out,
++ int **new_out, int *new_count_out);
+ int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr);
+ int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid);
+ int dlm_our_nodeid(void);
+diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
+index d30ea8b..5a7ac33 100644
+--- a/fs/dlm/dlm_internal.h
++++ b/fs/dlm/dlm_internal.h
+@@ -37,14 +37,11 @@
+ #include <linux/jhash.h>
+ #include <linux/miscdevice.h>
+ #include <linux/mutex.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/dlm.h>
+ #include "config.h"
+
+-#define DLM_LOCKSPACE_LEN 64
+-
+ /* Size of the temp buffer midcomms allocates on the stack.
+ We try to make this large enough so most messages fit.
+ FIXME: should sctp make this unnecessary? */
+@@ -133,8 +130,10 @@ struct dlm_member {
+
+ struct dlm_recover {
+ struct list_head list;
+- int *nodeids;
++ int *nodeids; /* nodeids of all members */
+ int node_count;
++ int *new; /* nodeids of new members */
++ int new_count;
+ uint64_t seq;
+ };
+
+@@ -580,6 +579,8 @@ static inline int dlm_no_directory(struct dlm_ls *ls)
+ int dlm_netlink_init(void);
+ void dlm_netlink_exit(void);
+ void dlm_timeout_warn(struct dlm_lkb *lkb);
++int dlm_plock_init(void);
++void dlm_plock_exit(void);
+
+ #ifdef CONFIG_DLM_DEBUG
+ int dlm_register_debugfs(void);
+diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
+index 8f250ac..2d3d102 100644
+--- a/fs/dlm/lock.c
++++ b/fs/dlm/lock.c
+@@ -165,7 +165,7 @@ void dlm_print_lkb(struct dlm_lkb *lkb)
+ lkb->lkb_grmode, lkb->lkb_wait_type, lkb->lkb_ast_type);
+ }
+
+-void dlm_print_rsb(struct dlm_rsb *r)
++static void dlm_print_rsb(struct dlm_rsb *r)
+ {
+ printk(KERN_ERR "rsb: nodeid %d flags %lx first %x rlc %d name %s\n",
+ r->res_nodeid, r->res_flags, r->res_first_lkid,
+@@ -1956,8 +1956,7 @@ static void confirm_master(struct dlm_rsb *r, int error)
+ list_del_init(&lkb->lkb_rsb_lookup);
+ r->res_first_lkid = lkb->lkb_id;
+ _request_lock(r, lkb);
+- } else
+- r->res_nodeid = -1;
++ }
+ break;
+
+ default:
+diff --git a/fs/dlm/lock.h b/fs/dlm/lock.h
+index 05d9c82..88e93c8 100644
+--- a/fs/dlm/lock.h
++++ b/fs/dlm/lock.h
+@@ -13,7 +13,6 @@
+ #ifndef __LOCK_DOT_H__
+ #define __LOCK_DOT_H__
+
+-void dlm_print_rsb(struct dlm_rsb *r);
+ void dlm_dump_rsb(struct dlm_rsb *r);
+ void dlm_print_lkb(struct dlm_lkb *lkb);
+ void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms);
+diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
+index b64e55e..499e167 100644
+--- a/fs/dlm/lockspace.c
++++ b/fs/dlm/lockspace.c
+@@ -200,7 +200,7 @@ int __init dlm_lockspace_init(void)
+
+ dlm_kset = kset_create_and_add("dlm", NULL, kernel_kobj);
+ if (!dlm_kset) {
+- printk(KERN_WARNING "%s: can not create kset\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: can not create kset\n", __func__);
+ return -ENOMEM;
+ }
+ return 0;
+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 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;
-+}
++ goto out_netlink;
+
-+static void unregister_balloon(struct sys_device *sysdev)
-+{
-+ int i;
+ 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. */
+
-+ 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);
-+}
++ 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]);
+
-+static void balloon_sysfs_exit(void)
-+{
-+ unregister_balloon(&balloon_sysdev);
-+}
++ 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++;
++ }
+
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/xen/events.c b/drivers/xen/events.c
+ /* 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..4f0f22b
+index 0000000..d6d6e37
--- /dev/null
-+++ b/drivers/xen/events.c
-@@ -0,0 +1,674 @@
++++ b/fs/dlm/plock.c
+@@ -0,0 +1,439 @@
+/*
-+ * 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.
++ * Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved.
+ *
-+ * Jeremy Fitzhardinge <jeremy at xensource.com>, XenSource Inc, 2007
-+ */
-+
-+#include <linux/linkage.h>
-+#include <linux/interrupt.h>
-+#include <linux/irq.h>
-+#include <linux/module.h>
-+#include <linux/string.h>
-+
-+#include <asm/ptrace.h>
-+#include <asm/irq.h>
-+#include <asm/sync_bitops.h>
-+#include <asm/xen/hypercall.h>
-+#include <asm/xen/hypervisor.h>
-+
-+#include <xen/xen-ops.h>
-+#include <xen/events.h>
-+#include <xen/interface/xen.h>
-+#include <xen/interface/event_channel.h>
-+
-+/*
-+ * This lock protects updates to the following mapping and reference-count
-+ * arrays. The lock does not need to be acquired to read the mapping tables.
++ * 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.
+ */
-+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};
++#include <linux/fs.h>
++#include <linux/miscdevice.h>
++#include <linux/poll.h>
++#include <linux/dlm.h>
++#include <linux/dlm_plock.h>
+
-+/* Packed IRQ information: binding type, sub-type index, and event channel. */
-+struct packed_irq
-+{
-+ unsigned short evtchn;
-+ unsigned char index;
-+ unsigned char type;
-+};
++#include "dlm_internal.h"
++#include "lockspace.h"
+
-+static struct packed_irq irq_info[NR_IRQS];
++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;
+
-+/* Binding types. */
-+enum {
-+ IRQT_UNBOUND,
-+ IRQT_PIRQ,
-+ IRQT_VIRQ,
-+ IRQT_IPI,
-+ IRQT_EVTCHN
++struct plock_op {
++ struct list_head list;
++ int done;
++ struct dlm_plock_info info;
+};
+
-+/* 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
++struct plock_xop {
++ struct plock_op xop;
++ void *callback;
++ void *fl;
++ void *file;
++ struct file_lock flc;
+};
-+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)
++static inline void set_version(struct dlm_plock_info *info)
+{
-+ return irq_info[irq].index;
++ info->version[0] = DLM_PLOCK_VERSION_MAJOR;
++ info->version[1] = DLM_PLOCK_VERSION_MINOR;
++ info->version[2] = DLM_PLOCK_VERSION_PATCH;
+}
+
-+static inline unsigned int type_from_irq(int irq)
++static int check_version(struct dlm_plock_info *info)
+{
-+ return irq_info[irq].type;
++ 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 inline unsigned long active_evtchns(unsigned int cpu,
-+ struct shared_info *sh,
-+ unsigned int idx)
++static void send_op(struct plock_op *op)
+{
-+ return (sh->evtchn_pending[idx] &
-+ cpu_evtchn_mask[cpu][idx] &
-+ ~sh->evtchn_mask[idx]);
++ 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);
+}
+
-+static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
++int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
++ int cmd, struct file_lock *fl)
+{
-+ 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;
-+}
++ struct dlm_ls *ls;
++ struct plock_op *op;
++ struct plock_xop *xop;
++ int rv;
+
-+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
++ ls = dlm_find_lockspace_local(lockspace);
++ if (!ls)
++ return -EINVAL;
+
-+ memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
-+ memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0]));
-+}
++ xop = kzalloc(sizeof(*xop), GFP_KERNEL);
++ if (!xop) {
++ rv = -ENOMEM;
++ goto out;
++ }
+
-+static inline unsigned int cpu_from_evtchn(unsigned int evtchn)
-+{
-+ return cpu_evtchn[evtchn];
-+}
++ 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;
++ }
+
-+static inline void clear_evtchn(int port)
-+{
-+ struct shared_info *s = HYPERVISOR_shared_info;
-+ sync_clear_bit(port, &s->evtchn_pending[0]);
-+}
++ send_op(op);
+
-+static inline void set_evtchn(int port)
-+{
-+ struct shared_info *s = HYPERVISOR_shared_info;
-+ sync_set_bit(port, &s->evtchn_pending[0]);
-+}
++ 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);
+
-+/**
-+ * 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);
++ rv = op->info.rv;
+
-+ if (VALID_EVTCHN(evtchn))
-+ notify_remote_via_evtchn(evtchn);
-+}
-+EXPORT_SYMBOL_GPL(notify_remote_via_irq);
++ if (!rv) {
++ if (posix_lock_file_wait(file, fl) < 0)
++ log_error(ls, "dlm_posix_lock: vfs lock error %llx",
++ (unsigned long long)number);
++ }
+
-+static void mask_evtchn(int port)
-+{
-+ struct shared_info *s = HYPERVISOR_shared_info;
-+ sync_set_bit(port, &s->evtchn_mask[0]);
++ kfree(xop);
++out:
++ dlm_put_lockspace(ls);
++ return rv;
+}
++EXPORT_SYMBOL_GPL(dlm_posix_lock);
+
-+static void unmask_evtchn(int port)
++/* Returns failure iff a succesful lock operation should be canceled */
++static int dlm_plock_callback(struct plock_op *op)
+{
-+ struct shared_info *s = HYPERVISOR_shared_info;
-+ unsigned int cpu = get_cpu();
++ 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;
+
-+ BUG_ON(!irqs_disabled());
++ 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);
+
-+ /* 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);
++ /* check if the following 2 are still valid or make a copy */
++ file = xop->file;
++ flc = &xop->flc;
++ fl = xop->fl;
++ notify = xop->callback;
+
-+ sync_clear_bit(port, &s->evtchn_mask[0]);
++ 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)) {
+ /*
-+ * 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.
++ * 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.
+ */
-+ 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;
++ log_print("dlm_plock_callback: vfs lock error %llx file %p fl %p",
++ (unsigned long long)op->info.number, file, fl);
+ }
+
-+ 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);
++ 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;
+ }
+
-+ irq_bindcount[irq]++;
-+
-+ spin_unlock(&irq_mapping_update_lock);
-+
-+ return irq;
++out:
++ kfree(xop);
++ return rv;
+}
-+EXPORT_SYMBOL_GPL(bind_evtchn_to_irq);
+
-+static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
++int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
++ struct file_lock *fl)
+{
-+ 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);
++ struct dlm_ls *ls;
++ struct plock_op *op;
++ int rv;
+
-+ per_cpu(ipi_to_irq, cpu)[ipi] = irq;
++ ls = dlm_find_lockspace_local(lockspace);
++ if (!ls)
++ return -EINVAL;
+
-+ bind_evtchn_to_cpu(evtchn, cpu);
++ op = kzalloc(sizeof(*op), GFP_KERNEL);
++ if (!op) {
++ rv = -ENOMEM;
++ goto out;
+ }
+
-+ 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");
++ if (posix_lock_file_wait(file, fl) < 0)
++ log_error(ls, "dlm_posix_unlock: vfs unlock error %llx",
++ (unsigned long long)number);
+
-+ evtchn_to_irq[evtchn] = irq;
-+ irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
++ 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;
+
-+ per_cpu(virq_to_irq, cpu)[virq] = irq;
++ send_op(op);
++ wait_event(recv_wq, (op->done != 0));
+
-+ bind_evtchn_to_cpu(evtchn, cpu);
++ 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);
+
-+ irq_bindcount[irq]++;
++ rv = op->info.rv;
+
-+ spin_unlock(&irq_mapping_update_lock);
++ if (rv == -ENOENT)
++ rv = 0;
+
-+ return irq;
++ kfree(op);
++out:
++ dlm_put_lockspace(ls);
++ return rv;
+}
++EXPORT_SYMBOL_GPL(dlm_posix_unlock);
+
-+static void unbind_from_irq(unsigned int irq)
++int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file,
++ struct file_lock *fl)
+{
-+ 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);
++ struct dlm_ls *ls;
++ struct plock_op *op;
++ int rv;
+
-+ evtchn_to_irq[evtchn] = -1;
-+ irq_info[irq] = IRQ_UNBOUND;
++ ls = dlm_find_lockspace_local(lockspace);
++ if (!ls)
++ return -EINVAL;
+
-+ dynamic_irq_init(irq);
++ op = kzalloc(sizeof(*op), GFP_KERNEL);
++ if (!op) {
++ rv = -ENOMEM;
++ goto out;
+ }
+
-+ spin_unlock(&irq_mapping_update_lock);
-+}
++ 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;
+
-+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;
++ send_op(op);
++ wait_event(recv_wq, (op->done != 0));
+
-+ irq = bind_evtchn_to_irq(evtchn);
-+ retval = request_irq(irq, handler, irqflags, devname, dev_id);
-+ if (retval != 0) {
-+ unbind_from_irq(irq);
-+ return retval;
++ 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);
+
-+ return irq;
-+}
-+EXPORT_SYMBOL_GPL(bind_evtchn_to_irqhandler);
++ /* info.rv from userspace is 1 for conflict, 0 for no-conflict,
++ -ENOENT if there are no locks on the file */
+
-+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;
++ rv = op->info.rv;
+
-+ 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;
++ 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;
+ }
+
-+ return irq;
++ kfree(op);
++out:
++ dlm_put_lockspace(ls);
++ return rv;
+}
-+EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler);
++EXPORT_SYMBOL_GPL(dlm_posix_get);
+
-+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)
++/* 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)
+{
-+ int irq, retval;
++ struct dlm_plock_info info;
++ struct plock_op *op = NULL;
+
-+ irq = bind_ipi_to_irq(ipi, cpu);
-+ if (irq < 0)
-+ return irq;
++ if (count < sizeof(info))
++ return -EINVAL;
+
-+ retval = request_irq(irq, handler, irqflags, devname, dev_id);
-+ if (retval != 0) {
-+ unbind_from_irq(irq);
-+ return retval;
++ 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);
+
-+ 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);
++ if (!op)
++ return -EAGAIN;
+
-+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);
++ if (copy_to_user(u, &info, sizeof(info)))
++ return -EFAULT;
++ return sizeof(info);
+}
+
-+irqreturn_t xen_debug_interrupt(int irq, void *dev_id)
++/* 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 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);
++ struct dlm_plock_info info;
++ struct plock_op *op;
++ int found = 0;
+
-+ printk("vcpu %d\n ", cpu);
++ if (count != sizeof(info))
++ return -EINVAL;
+
-+ 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 " : " ");
++ if (copy_from_user(&info, u, sizeof(info)))
++ return -EFAULT;
+
-+ 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 " : " ");
++ if (check_version(&info))
++ return -EINVAL;
+
-+ 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_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);
+
-+ 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();
++ 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;
+}
+
-+/* Rebind an evtchn so that it gets delivered to a specific cpu */
-+static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
++static unsigned int dev_poll(struct file *file, poll_table *wait)
+{
-+ struct evtchn_bind_vcpu bind_vcpu;
-+ int evtchn = evtchn_from_irq(irq);
++ unsigned int mask = 0;
+
-+ if (!VALID_EVTCHN(evtchn))
-+ return;
++ poll_wait(file, &send_wq, wait);
+
-+ /* Send future instances of this interrupt to other vcpu. */
-+ bind_vcpu.port = evtchn;
-+ bind_vcpu.vcpu = tcpu;
++ spin_lock(&ops_lock);
++ if (!list_empty(&send_list))
++ mask = POLLIN | POLLRDNORM;
++ spin_unlock(&ops_lock);
+
-+ /*
-+ * 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);
++ return mask;
+}
+
++static const struct file_operations dev_fops = {
++ .read = dev_read,
++ .write = dev_write,
++ .poll = dev_poll,
++ .owner = THIS_MODULE
++};
+
-+static void set_affinity_irq(unsigned irq, cpumask_t dest)
-+{
-+ unsigned tcpu = first_cpu(dest);
-+ rebind_irq_to_cpu(irq, tcpu);
-+}
++static struct miscdevice plock_dev_misc = {
++ .minor = MISC_DYNAMIC_MINOR,
++ .name = DLM_PLOCK_MISC_NAME,
++ .fops = &dev_fops
++};
+
-+int resend_irq_on_evtchn(unsigned int irq)
++int dlm_plock_init(void)
+{
-+ int masked, evtchn = evtchn_from_irq(irq);
-+ struct shared_info *s = HYPERVISOR_shared_info;
-+
-+ if (!VALID_EVTCHN(evtchn))
-+ return 1;
++ int rv;
+
-+ masked = sync_test_and_set_bit(evtchn, s->evtchn_mask);
-+ sync_set_bit(evtchn, s->evtchn_pending);
-+ if (!masked)
-+ unmask_evtchn(evtchn);
++ 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);
+
-+ return 1;
++ rv = misc_register(&plock_dev_misc);
++ if (rv)
++ log_print("dlm_plock_init: misc_register failed %d", rv);
++ return rv;
+}
+
-+static void enable_dynirq(unsigned int irq)
++void dlm_plock_exit(void)
+{
-+ int evtchn = evtchn_from_irq(irq);
-+
-+ if (VALID_EVTCHN(evtchn))
-+ unmask_evtchn(evtchn);
++ if (misc_deregister(&plock_dev_misc) < 0)
++ log_print("dlm_plock_exit: misc_deregister failed");
+}
+
-+static void disable_dynirq(unsigned int irq)
-+{
-+ int evtchn = evtchn_from_irq(irq);
-+
-+ if (VALID_EVTCHN(evtchn))
-+ mask_evtchn(evtchn);
-+}
+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/dnotify.c b/fs/dnotify.c
+index 28d01ed..eaecc4c 100644
+--- a/fs/dnotify.c
++++ b/fs/dnotify.c
+@@ -20,6 +20,7 @@
+ #include <linux/init.h>
+ #include <linux/spinlock.h>
+ #include <linux/slab.h>
++#include <linux/file.h>
+
+ int dir_notify_enable __read_mostly = 1;
+
+@@ -66,6 +67,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
+ struct dnotify_struct **prev;
+ struct inode *inode;
+ fl_owner_t id = current->files;
++ struct file *f;
+ int error = 0;
+
+ if ((arg & ~DN_MULTISHOT) == 0) {
+@@ -92,6 +94,15 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
+ prev = &odn->dn_next;
+ }
+
++ rcu_read_lock();
++ f = fcheck(fd);
++ rcu_read_unlock();
++ /* we'd lost the race with close(), sod off silently */
++ /* note that inode->i_lock prevents reordering problems
++ * between accesses to descriptor table and ->i_dnotify */
++ if (f != filp)
++ goto out_free;
+
-+static void ack_dynirq(unsigned int irq)
+ error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
+ if (error)
+ goto out_free;
+diff --git a/fs/dquot.c b/fs/dquot.c
+index 41b9dbd..dfba162 100644
+--- a/fs/dquot.c
++++ b/fs/dquot.c
+@@ -289,7 +289,15 @@ static void wait_on_dquot(struct dquot *dquot)
+ mutex_unlock(&dquot->dq_lock);
+ }
+
+-#define mark_dquot_dirty(dquot) ((dquot)->dq_sb->dq_op->mark_dirty(dquot))
++static inline int dquot_dirty(struct dquot *dquot)
+{
-+ int evtchn = evtchn_from_irq(irq);
-+
-+ move_native_irq(irq);
-+
-+ if (VALID_EVTCHN(evtchn))
-+ clear_evtchn(evtchn);
++ return test_bit(DQ_MOD_B, &dquot->dq_flags);
+}
+
-+static int retrigger_dynirq(unsigned int irq)
++static inline int mark_dquot_dirty(struct dquot *dquot)
+{
-+ 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;
++ return dquot->dq_sb->dq_op->mark_dirty(dquot);
+}
+
+ int dquot_mark_dquot_dirty(struct dquot *dquot)
+ {
+@@ -1441,31 +1449,43 @@ static inline void set_enable_flags(struct quota_info *dqopt, int type)
+ switch (type) {
+ case USRQUOTA:
+ dqopt->flags |= DQUOT_USR_ENABLED;
++ dqopt->flags &= ~DQUOT_USR_SUSPENDED;
+ break;
+ case GRPQUOTA:
+ dqopt->flags |= DQUOT_GRP_ENABLED;
++ dqopt->flags &= ~DQUOT_GRP_SUSPENDED;
+ break;
+ }
+ }
+
+-static inline void reset_enable_flags(struct quota_info *dqopt, int type)
++static inline void reset_enable_flags(struct quota_info *dqopt, int type,
++ int remount)
+ {
+ switch (type) {
+ case USRQUOTA:
+ dqopt->flags &= ~DQUOT_USR_ENABLED;
++ if (remount)
++ dqopt->flags |= DQUOT_USR_SUSPENDED;
++ else
++ dqopt->flags &= ~DQUOT_USR_SUSPENDED;
+ break;
+ case GRPQUOTA:
+ dqopt->flags &= ~DQUOT_GRP_ENABLED;
++ if (remount)
++ dqopt->flags |= DQUOT_GRP_SUSPENDED;
++ else
++ dqopt->flags &= ~DQUOT_GRP_SUSPENDED;
+ break;
+ }
+ }
+
+
-+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)
+ /*
+ * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
+ */
+-int vfs_quota_off(struct super_block *sb, int type)
++int vfs_quota_off(struct super_block *sb, int type, int remount)
+ {
+- int cnt;
++ int cnt, ret = 0;
+ struct quota_info *dqopt = sb_dqopt(sb);
+ struct inode *toputinode[MAXQUOTAS];
+
+@@ -1475,9 +1495,17 @@ int vfs_quota_off(struct super_block *sb, int type)
+ toputinode[cnt] = NULL;
+ if (type != -1 && cnt != type)
+ continue;
++ /* If we keep inodes of quota files after remount and quotaoff
++ * is called, drop kept inodes. */
++ if (!remount && sb_has_quota_suspended(sb, cnt)) {
++ iput(dqopt->files[cnt]);
++ dqopt->files[cnt] = NULL;
++ reset_enable_flags(dqopt, cnt, 0);
++ continue;
++ }
+ if (!sb_has_quota_enabled(sb, cnt))
+ continue;
+- reset_enable_flags(dqopt, cnt);
++ reset_enable_flags(dqopt, cnt, remount);
+
+ /* Note: these are blocking operations */
+ drop_dquot_ref(sb, cnt);
+@@ -1493,7 +1521,8 @@ int vfs_quota_off(struct super_block *sb, int type)
+ put_quota_format(dqopt->info[cnt].dqi_format);
+
+ toputinode[cnt] = dqopt->files[cnt];
+- dqopt->files[cnt] = NULL;
++ if (!remount)
++ dqopt->files[cnt] = NULL;
+ dqopt->info[cnt].dqi_flags = 0;
+ dqopt->info[cnt].dqi_igrace = 0;
+ dqopt->info[cnt].dqi_bgrace = 0;
+@@ -1523,12 +1552,19 @@ int vfs_quota_off(struct super_block *sb, int type)
+ mutex_unlock(&toputinode[cnt]->i_mutex);
+ mark_inode_dirty(toputinode[cnt]);
+ }
+- iput(toputinode[cnt]);
+ mutex_unlock(&dqopt->dqonoff_mutex);
++ /* On remount RO, we keep the inode pointer so that we
++ * can reenable quota on the subsequent remount RW.
++ * But we have better not keep inode pointer when there
++ * is pending delete on the quota file... */
++ if (!remount)
++ iput(toputinode[cnt]);
++ else if (!toputinode[cnt]->i_nlink)
++ ret = -EBUSY;
+ }
+ if (sb->s_bdev)
+ invalidate_bdev(sb->s_bdev);
+- return 0;
++ return ret;
+ }
+
+ /*
+@@ -1566,7 +1602,8 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
+ invalidate_bdev(sb->s_bdev);
+ mutex_lock(&inode->i_mutex);
+ mutex_lock(&dqopt->dqonoff_mutex);
+- if (sb_has_quota_enabled(sb, type)) {
++ if (sb_has_quota_enabled(sb, type) ||
++ sb_has_quota_suspended(sb, type)) {
+ error = -EBUSY;
+ goto out_lock;
+ }
+@@ -1589,6 +1626,7 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
+
+ dqopt->ops[type] = fmt->qf_ops;
+ dqopt->info[type].dqi_format = fmt;
++ dqopt->info[type].dqi_fmt_id = format_id;
+ INIT_LIST_HEAD(&dqopt->info[type].dqi_dirty_list);
+ mutex_lock(&dqopt->dqio_mutex);
+ if ((error = dqopt->ops[type]->read_file_info(sb, type)) < 0) {
+@@ -1624,12 +1662,41 @@ out_fmt:
+ return error;
+ }
+
++/* Reenable quotas on remount RW */
++static int vfs_quota_on_remount(struct super_block *sb, int type)
+{
-+ int i;
++ struct quota_info *dqopt = sb_dqopt(sb);
++ struct inode *inode;
++ int ret;
+
-+ init_evtchn_cpu_bindings();
++ mutex_lock(&dqopt->dqonoff_mutex);
++ if (!sb_has_quota_suspended(sb, type)) {
++ mutex_unlock(&dqopt->dqonoff_mutex);
++ return 0;
++ }
++ BUG_ON(sb_has_quota_enabled(sb, type));
+
-+ /* No event channels are 'live' right now. */
-+ for (i = 0; i < NR_EVENT_CHANNELS; i++)
-+ mask_evtchn(i);
++ inode = dqopt->files[type];
++ dqopt->files[type] = NULL;
++ reset_enable_flags(dqopt, type, 0);
++ mutex_unlock(&dqopt->dqonoff_mutex);
+
-+ /* Dynamic IRQ space is currently unbound. Zero the refcnts. */
-+ for (i = 0; i < NR_IRQS; i++)
-+ irq_bindcount[i] = 0;
++ ret = vfs_quota_on_inode(inode, type, dqopt->info[type].dqi_fmt_id);
++ iput(inode);
+
-+ irq_ctx_init(smp_processor_id());
++ return ret;
+}
-diff --git a/drivers/xen/features.c b/drivers/xen/features.c
-new file mode 100644
-index 0000000..0707714
---- /dev/null
-+++ b/drivers/xen/features.c
-@@ -0,0 +1,29 @@
-+/******************************************************************************
-+ * features.c
-+ *
-+ * Xen feature flags.
-+ *
-+ * Copyright (c) 2006, Ian Campbell, XenSource Inc.
-+ */
-+#include <linux/types.h>
-+#include <linux/cache.h>
-+#include <linux/module.h>
-+#include <asm/xen/hypervisor.h>
-+#include <xen/features.h>
+
-+u8 xen_features[XENFEAT_NR_SUBMAPS * 32] __read_mostly;
-+EXPORT_SYMBOL_GPL(xen_features);
+ /* Actual function called from quotactl() */
+-int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)
++int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path,
++ int remount)
+ {
+ struct nameidata nd;
+ int error;
+
++ if (remount)
++ return vfs_quota_on_remount(sb, type);
+
-+void xen_setup_features(void)
-+{
-+ struct xen_feature_info fi;
-+ int i, j;
+ error = path_lookup(path, LOOKUP_FOLLOW, &nd);
+ if (error < 0)
+ return error;
+@@ -1709,10 +1776,19 @@ int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d
+ }
+
+ /* Generic routine for setting common part of quota structure */
+-static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
++static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
+ {
+ struct mem_dqblk *dm = &dquot->dq_dqb;
+ int check_blim = 0, check_ilim = 0;
++ struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type];
++
++ if ((di->dqb_valid & QIF_BLIMITS &&
++ (di->dqb_bhardlimit > dqi->dqi_maxblimit ||
++ di->dqb_bsoftlimit > dqi->dqi_maxblimit)) ||
++ (di->dqb_valid & QIF_ILIMITS &&
++ (di->dqb_ihardlimit > dqi->dqi_maxilimit ||
++ di->dqb_isoftlimit > dqi->dqi_maxilimit)))
++ return -ERANGE;
+
+ spin_lock(&dq_data_lock);
+ if (di->dqb_valid & QIF_SPACE) {
+@@ -1744,7 +1820,7 @@ static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
+ clear_bit(DQ_BLKS_B, &dquot->dq_flags);
+ }
+ else if (!(di->dqb_valid & QIF_BTIME)) /* Set grace only if user hasn't provided his own... */
+- dm->dqb_btime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_bgrace;
++ dm->dqb_btime = get_seconds() + dqi->dqi_bgrace;
+ }
+ if (check_ilim) {
+ if (!dm->dqb_isoftlimit || dm->dqb_curinodes < dm->dqb_isoftlimit) {
+@@ -1752,7 +1828,7 @@ static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
+ clear_bit(DQ_INODES_B, &dquot->dq_flags);
+ }
+ else if (!(di->dqb_valid & QIF_ITIME)) /* Set grace only if user hasn't provided his own... */
+- dm->dqb_itime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace;
++ dm->dqb_itime = get_seconds() + dqi->dqi_igrace;
+ }
+ if (dm->dqb_bhardlimit || dm->dqb_bsoftlimit || dm->dqb_ihardlimit || dm->dqb_isoftlimit)
+ clear_bit(DQ_FAKE_B, &dquot->dq_flags);
+@@ -1760,21 +1836,24 @@ static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
+ set_bit(DQ_FAKE_B, &dquot->dq_flags);
+ spin_unlock(&dq_data_lock);
+ mark_dquot_dirty(dquot);
+
-+ for (i = 0; i < XENFEAT_NR_SUBMAPS; i++) {
-+ fi.submap_idx = i;
-+ if (HYPERVISOR_xen_version(XENVER_get_features, &fi) < 0)
-+ break;
-+ for (j = 0; j < 32; j++)
-+ xen_features[i * 32 + j] = !!(fi.submap & 1<<j);
-+ }
-+}
-diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
-index d85dc6d..52b6b41 100644
---- a/drivers/xen/grant-table.c
-+++ b/drivers/xen/grant-table.c
-@@ -439,24 +439,6 @@ static inline unsigned int max_nr_grant_frames(void)
- return xen_max;
++ return 0;
}
--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));
+ int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di)
+ {
+ struct dquot *dquot;
++ int rc;
+
+ mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
+ if (!(dquot = dqget(sb, id, type))) {
+ mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
+ return -ESRCH;
+ }
+- do_set_dqblk(dquot, di);
++ rc = do_set_dqblk(dquot, di);
+ dqput(dquot);
+ mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
- return 0;
--}
--
- static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
++ return rc;
+ }
+
+ /* Generic routine for getting common part of quota file information */
+diff --git a/fs/drop_caches.c b/fs/drop_caches.c
+index 59375ef..3e5637f 100644
+--- a/fs/drop_caches.c
++++ b/fs/drop_caches.c
+@@ -14,18 +14,26 @@ int sysctl_drop_caches;
+
+ static void drop_pagecache_sb(struct super_block *sb)
+ {
+- struct inode *inode;
++ struct inode *inode, *toput_inode = NULL;
+
+ spin_lock(&inode_lock);
+ list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
+ if (inode->i_state & (I_FREEING|I_WILL_FREE))
+ continue;
++ if (inode->i_mapping->nrpages == 0)
++ continue;
++ __iget(inode);
++ spin_unlock(&inode_lock);
+ __invalidate_mapping_pages(inode->i_mapping, 0, -1, true);
++ iput(toput_inode);
++ toput_inode = inode;
++ spin_lock(&inode_lock);
+ }
+ spin_unlock(&inode_lock);
++ iput(toput_inode);
+ }
+
+-void drop_pagecache(void)
++static void drop_pagecache(void)
{
- struct gnttab_setup_table setup;
-@@ -470,7 +452,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+ struct super_block *sb;
- setup.dom = DOMID_SELF;
- setup.nr_frames = nr_gframes;
-- setup.frame_list = frames;
-+ set_xen_guest_handle(setup.frame_list, frames);
+@@ -45,7 +53,7 @@ restart:
+ spin_unlock(&sb_lock);
+ }
- rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
- if (rc == -ENOSYS) {
-@@ -480,17 +462,9 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+-void drop_slab(void)
++static void drop_slab(void)
+ {
+ int nr_objects;
- BUG_ON(rc || setup.status);
+diff --git a/fs/ecryptfs/Makefile b/fs/ecryptfs/Makefile
+index 7688570..1e34a7f 100644
+--- a/fs/ecryptfs/Makefile
++++ b/fs/ecryptfs/Makefile
+@@ -4,4 +4,4 @@
-- if (shared == NULL) {
-- struct vm_struct *area;
-- area = alloc_vm_area(PAGE_SIZE * max_nr_grant_frames());
-- BUG_ON(area == NULL);
-- shared = area->addr;
-- }
-- rc = apply_to_page_range(&init_mm, (unsigned long)shared,
-- PAGE_SIZE * nr_gframes,
-- map_pte_fn, &frames);
-+ rc = arch_gnttab_map_shared(frames, nr_gframes, max_nr_grant_frames(),
-+ &shared);
- BUG_ON(rc);
-- frames -= nr_gframes; /* adjust after map_pte_fn() */
+ obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
- kfree(frames);
+-ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o netlink.o debug.o
++ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o netlink.o miscdev.o debug.o
+diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
+index a066e10..cd62d75 100644
+--- a/fs/ecryptfs/crypto.c
++++ b/fs/ecryptfs/crypto.c
+@@ -119,21 +119,21 @@ static int ecryptfs_calculate_md5(char *dst,
+ if (rc) {
+ printk(KERN_ERR
+ "%s: Error initializing crypto hash; rc = [%d]\n",
+- __FUNCTION__, rc);
++ __func__, rc);
+ goto out;
+ }
+ rc = crypto_hash_update(&desc, &sg, len);
+ if (rc) {
+ printk(KERN_ERR
+ "%s: Error updating crypto hash; rc = [%d]\n",
+- __FUNCTION__, rc);
++ __func__, rc);
+ goto out;
+ }
+ rc = crypto_hash_final(&desc, dst);
+ if (rc) {
+ printk(KERN_ERR
+ "%s: Error finalizing crypto hash; rc = [%d]\n",
+- __FUNCTION__, rc);
++ __func__, rc);
+ goto out;
+ }
+ out:
+@@ -437,7 +437,7 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page,
+ if (rc < 0) {
+ printk(KERN_ERR "%s: Error attempting to encrypt page with "
+ "page->index = [%ld], extent_offset = [%ld]; "
+- "rc = [%d]\n", __FUNCTION__, page->index, extent_offset,
++ "rc = [%d]\n", __func__, page->index, extent_offset,
+ rc);
+ goto out;
+ }
+@@ -487,7 +487,7 @@ int ecryptfs_encrypt_page(struct page *page)
+ 0, PAGE_CACHE_SIZE);
+ if (rc)
+ printk(KERN_ERR "%s: Error attempting to copy "
+- "page at index [%ld]\n", __FUNCTION__,
++ "page at index [%ld]\n", __func__,
+ page->index);
+ goto out;
+ }
+@@ -508,7 +508,7 @@ int ecryptfs_encrypt_page(struct page *page)
+ extent_offset);
+ if (rc) {
+ printk(KERN_ERR "%s: Error encrypting extent; "
+- "rc = [%d]\n", __FUNCTION__, rc);
++ "rc = [%d]\n", __func__, rc);
+ goto out;
+ }
+ ecryptfs_lower_offset_for_extent(
+@@ -569,7 +569,7 @@ static int ecryptfs_decrypt_extent(struct page *page,
+ if (rc < 0) {
+ printk(KERN_ERR "%s: Error attempting to decrypt to page with "
+ "page->index = [%ld], extent_offset = [%ld]; "
+- "rc = [%d]\n", __FUNCTION__, page->index, extent_offset,
++ "rc = [%d]\n", __func__, page->index, extent_offset,
+ rc);
+ goto out;
+ }
+@@ -622,7 +622,7 @@ int ecryptfs_decrypt_page(struct page *page)
+ ecryptfs_inode);
+ if (rc)
+ printk(KERN_ERR "%s: Error attempting to copy "
+- "page at index [%ld]\n", __FUNCTION__,
++ "page at index [%ld]\n", __func__,
+ page->index);
+ goto out;
+ }
+@@ -656,7 +656,7 @@ int ecryptfs_decrypt_page(struct page *page)
+ extent_offset);
+ if (rc) {
+ printk(KERN_ERR "%s: Error encrypting extent; "
+- "rc = [%d]\n", __FUNCTION__, rc);
++ "rc = [%d]\n", __func__, rc);
+ goto out;
+ }
+ }
+@@ -1215,7 +1215,7 @@ int ecryptfs_read_and_validate_header_region(char *data,
+ ecryptfs_inode);
+ if (rc) {
+ printk(KERN_ERR "%s: Error reading header region; rc = [%d]\n",
+- __FUNCTION__, rc);
++ __func__, rc);
+ goto out;
+ }
+ if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES)) {
+@@ -1246,7 +1246,6 @@ ecryptfs_write_header_metadata(char *virt,
+ (*written) = 6;
+ }
-@@ -506,10 +480,7 @@ static int gnttab_resume(void)
+-struct kmem_cache *ecryptfs_header_cache_0;
+ struct kmem_cache *ecryptfs_header_cache_1;
+ struct kmem_cache *ecryptfs_header_cache_2;
- 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;
+@@ -1320,7 +1319,7 @@ ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat,
+ 0, crypt_stat->num_header_bytes_at_front);
+ if (rc)
+ printk(KERN_ERR "%s: Error attempting to write header "
+- "information to lower file; rc = [%d]\n", __FUNCTION__,
++ "information to lower file; rc = [%d]\n", __func__,
+ rc);
+ return rc;
}
+@@ -1365,14 +1364,14 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)
+ }
+ } else {
+ printk(KERN_WARNING "%s: Encrypted flag not set\n",
+- __FUNCTION__);
++ __func__);
+ rc = -EINVAL;
+ goto out;
+ }
+ /* Released in this function */
+ virt = kzalloc(crypt_stat->num_header_bytes_at_front, GFP_KERNEL);
+ if (!virt) {
+- printk(KERN_ERR "%s: Out of memory\n", __FUNCTION__);
++ printk(KERN_ERR "%s: Out of memory\n", __func__);
+ rc = -ENOMEM;
+ goto out;
+ }
+@@ -1380,7 +1379,7 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)
+ ecryptfs_dentry);
+ if (unlikely(rc)) {
+ printk(KERN_ERR "%s: Error whilst writing headers; rc = [%d]\n",
+- __FUNCTION__, rc);
++ __func__, rc);
+ goto out_free;
+ }
+ if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
+@@ -1391,7 +1390,7 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)
+ ecryptfs_dentry, virt);
+ if (rc) {
+ printk(KERN_ERR "%s: Error writing metadata out to lower file; "
+- "rc = [%d]\n", __FUNCTION__, rc);
++ "rc = [%d]\n", __func__, rc);
+ goto out_free;
+ }
+ out_free:
+@@ -1585,7 +1584,7 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
+ if (!page_virt) {
+ rc = -ENOMEM;
+ printk(KERN_ERR "%s: Unable to allocate page_virt\n",
+- __FUNCTION__);
++ __func__);
+ goto out;
+ }
+ rc = ecryptfs_read_lower(page_virt, 0, crypt_stat->extent_size,
+diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
+index 5007f78..951ee33 100644
+--- a/fs/ecryptfs/ecryptfs_kernel.h
++++ b/fs/ecryptfs/ecryptfs_kernel.h
+@@ -4,7 +4,7 @@
+ *
+ * Copyright (C) 1997-2003 Erez Zadok
+ * Copyright (C) 2001-2003 Stony Brook University
+- * Copyright (C) 2004-2007 International Business Machines Corp.
++ * Copyright (C) 2004-2008 International Business Machines Corp.
+ * Author(s): Michael A. Halcrow <mahalcro at us.ibm.com>
+ * Trevor S. Highland <trevor.highland at gmail.com>
+ * Tyler Hicks <tyhicks at ou.edu>
+@@ -34,6 +34,7 @@
+ #include <linux/namei.h>
+ #include <linux/scatterlist.h>
+ #include <linux/hash.h>
++#include <linux/nsproxy.h>
-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)
+ /* Version verification for shared data structures w/ userspace */
+ #define ECRYPTFS_VERSION_MAJOR 0x00
+@@ -49,11 +50,13 @@
+ #define ECRYPTFS_VERSIONING_POLICY 0x00000008
+ #define ECRYPTFS_VERSIONING_XATTR 0x00000010
+ #define ECRYPTFS_VERSIONING_MULTKEY 0x00000020
++#define ECRYPTFS_VERSIONING_DEVMISC 0x00000040
+ #define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \
+ | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \
+ | ECRYPTFS_VERSIONING_PUBKEY \
+ | ECRYPTFS_VERSIONING_XATTR \
+- | ECRYPTFS_VERSIONING_MULTKEY)
++ | ECRYPTFS_VERSIONING_MULTKEY \
++ | ECRYPTFS_VERSIONING_DEVMISC)
+ #define ECRYPTFS_MAX_PASSWORD_LENGTH 64
+ #define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH
+ #define ECRYPTFS_SALT_SIZE 8
+@@ -73,17 +76,14 @@
+ #define ECRYPTFS_DEFAULT_MSG_CTX_ELEMS 32
+ #define ECRYPTFS_DEFAULT_SEND_TIMEOUT HZ
+ #define ECRYPTFS_MAX_MSG_CTX_TTL (HZ*3)
+-#define ECRYPTFS_NLMSG_HELO 100
+-#define ECRYPTFS_NLMSG_QUIT 101
+-#define ECRYPTFS_NLMSG_REQUEST 102
+-#define ECRYPTFS_NLMSG_RESPONSE 103
+ #define ECRYPTFS_MAX_PKI_NAME_BYTES 16
+ #define ECRYPTFS_DEFAULT_NUM_USERS 4
+ #define ECRYPTFS_MAX_NUM_USERS 32768
+ #define ECRYPTFS_TRANSPORT_NETLINK 0
+ #define ECRYPTFS_TRANSPORT_CONNECTOR 1
+ #define ECRYPTFS_TRANSPORT_RELAYFS 2
+-#define ECRYPTFS_DEFAULT_TRANSPORT ECRYPTFS_TRANSPORT_NETLINK
++#define ECRYPTFS_TRANSPORT_MISCDEV 3
++#define ECRYPTFS_DEFAULT_TRANSPORT ECRYPTFS_TRANSPORT_MISCDEV
+ #define ECRYPTFS_XATTR_NAME "user.ecryptfs"
+
+ #define RFC2440_CIPHER_DES3_EDE 0x02
+@@ -366,32 +366,63 @@ struct ecryptfs_auth_tok_list_item {
+ };
+
+ struct ecryptfs_message {
++ /* Can never be greater than ecryptfs_message_buf_len */
++ /* Used to find the parent msg_ctx */
++ /* Inherits from msg_ctx->index */
+ u32 index;
+ u32 data_len;
+ u8 data[];
+ };
- *vaddr = NULL;
+ struct ecryptfs_msg_ctx {
+-#define ECRYPTFS_MSG_CTX_STATE_FREE 0x0001
+-#define ECRYPTFS_MSG_CTX_STATE_PENDING 0x0002
+-#define ECRYPTFS_MSG_CTX_STATE_DONE 0x0003
+- u32 state;
+- unsigned int index;
+- unsigned int counter;
++#define ECRYPTFS_MSG_CTX_STATE_FREE 0x01
++#define ECRYPTFS_MSG_CTX_STATE_PENDING 0x02
++#define ECRYPTFS_MSG_CTX_STATE_DONE 0x03
++#define ECRYPTFS_MSG_CTX_STATE_NO_REPLY 0x04
++ u8 state;
++#define ECRYPTFS_MSG_HELO 100
++#define ECRYPTFS_MSG_QUIT 101
++#define ECRYPTFS_MSG_REQUEST 102
++#define ECRYPTFS_MSG_RESPONSE 103
++ u8 type;
++ u32 index;
++ /* Counter converts to a sequence number. Each message sent
++ * out for which we expect a response has an associated
++ * sequence number. The response must have the same sequence
++ * number as the counter for the msg_stc for the message to be
++ * valid. */
++ u32 counter;
++ size_t msg_size;
+ struct ecryptfs_message *msg;
+ struct task_struct *task;
+ struct list_head node;
++ struct list_head daemon_out_list;
+ struct mutex mux;
+ };
-- area = alloc_vm_area(PAGE_SIZE);
-+ area = xen_alloc_vm_area(PAGE_SIZE);
- if (!area)
- return -ENOMEM;
+ extern unsigned int ecryptfs_transport;
-@@ -409,7 +409,7 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
- BUG();
+-struct ecryptfs_daemon_id {
+- pid_t pid;
+- uid_t uid;
+- struct hlist_node id_chain;
++struct ecryptfs_daemon;
++
++struct ecryptfs_daemon {
++#define ECRYPTFS_DAEMON_IN_READ 0x00000001
++#define ECRYPTFS_DAEMON_IN_POLL 0x00000002
++#define ECRYPTFS_DAEMON_ZOMBIE 0x00000004
++#define ECRYPTFS_DAEMON_MISCDEV_OPEN 0x00000008
++ u32 flags;
++ u32 num_queued_msg_ctx;
++ struct pid *pid;
++ uid_t euid;
++ struct user_namespace *user_ns;
++ struct task_struct *task;
++ struct mutex mux;
++ struct list_head msg_ctx_out_queue;
++ wait_queue_head_t wait;
++ struct hlist_node euid_chain;
+ };
- 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();
++extern struct mutex ecryptfs_daemon_hash_mux;
++
+ static inline struct ecryptfs_file_info *
+ ecryptfs_file_to_private(struct file *file)
+ {
+@@ -500,7 +531,7 @@ ecryptfs_set_dentry_lower_mnt(struct dentry *dentry, struct vfsmount *lower_mnt)
+ }
+
+ #define ecryptfs_printk(type, fmt, arg...) \
+- __ecryptfs_printk(type "%s: " fmt, __FUNCTION__, ## arg);
++ __ecryptfs_printk(type "%s: " fmt, __func__, ## arg);
+ void __ecryptfs_printk(const char *fmt, ...);
+
+ extern const struct file_operations ecryptfs_main_fops;
+@@ -581,10 +612,13 @@ int
+ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
+ size_t size, int flags);
+ int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode);
+-int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid);
+-int ecryptfs_process_quit(uid_t uid, pid_t pid);
+-int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid,
+- pid_t pid, u32 seq);
++int ecryptfs_process_helo(unsigned int transport, uid_t euid,
++ struct user_namespace *user_ns, struct pid *pid);
++int ecryptfs_process_quit(uid_t euid, struct user_namespace *user_ns,
++ struct pid *pid);
++int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
++ struct user_namespace *user_ns, struct pid *pid,
++ u32 seq);
+ int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
+ struct ecryptfs_msg_ctx **msg_ctx);
+ int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx,
+@@ -593,14 +627,14 @@ int ecryptfs_init_messaging(unsigned int transport);
+ void ecryptfs_release_messaging(unsigned int transport);
+
+ int ecryptfs_send_netlink(char *data, int data_len,
+- struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type,
+- u16 msg_flags, pid_t daemon_pid);
++ struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
++ u16 msg_flags, struct pid *daemon_pid);
+ int ecryptfs_init_netlink(void);
+ void ecryptfs_release_netlink(void);
+
+ int ecryptfs_send_connector(char *data, int data_len,
+- struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type,
+- u16 msg_flags, pid_t daemon_pid);
++ struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
++ u16 msg_flags, struct pid *daemon_pid);
+ int ecryptfs_init_connector(void);
+ void ecryptfs_release_connector(void);
+ void
+@@ -642,5 +676,21 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,
+ size_t offset_in_page, size_t size,
+ struct inode *ecryptfs_inode);
+ struct page *ecryptfs_get_locked_page(struct file *file, loff_t index);
++int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon);
++int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon, uid_t euid,
++ struct user_namespace *user_ns);
++int ecryptfs_parse_packet_length(unsigned char *data, size_t *size,
++ size_t *length_size);
++int ecryptfs_write_packet_length(char *dest, size_t size,
++ size_t *packet_size_length);
++int ecryptfs_init_ecryptfs_miscdev(void);
++void ecryptfs_destroy_ecryptfs_miscdev(void);
++int ecryptfs_send_miscdev(char *data, size_t data_size,
++ struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
++ u16 msg_flags, struct ecryptfs_daemon *daemon);
++void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx);
++int
++ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid,
++ struct user_namespace *user_ns, struct pid *pid);
- 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;
+ #endif /* #ifndef ECRYPTFS_KERNEL_H */
+diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
+index 2b8f5ed..2258b8f 100644
+--- a/fs/ecryptfs/file.c
++++ b/fs/ecryptfs/file.c
+@@ -195,7 +195,9 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
+ file, ecryptfs_inode_to_private(inode)->lower_file);
+ if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
+ ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
++ mutex_lock(&crypt_stat->cs_mutex);
+ crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
++ mutex_unlock(&crypt_stat->cs_mutex);
+ rc = 0;
+ goto out;
+ }
+diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
+index e238611..0a13973 100644
+--- a/fs/ecryptfs/inode.c
++++ b/fs/ecryptfs/inode.c
+@@ -111,7 +111,7 @@ ecryptfs_do_create(struct inode *directory_inode,
+
+ lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
+ lower_dir_dentry = lock_parent(lower_dentry);
+- if (unlikely(IS_ERR(lower_dir_dentry))) {
++ if (IS_ERR(lower_dir_dentry)) {
+ ecryptfs_printk(KERN_ERR, "Error locking directory of "
+ "dentry\n");
+ rc = PTR_ERR(lower_dir_dentry);
+@@ -121,7 +121,7 @@ ecryptfs_do_create(struct inode *directory_inode,
+ ecryptfs_dentry, mode, nd);
+ if (rc) {
+ printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
+- "rc = [%d]\n", __FUNCTION__, rc);
++ "rc = [%d]\n", __func__, rc);
+ goto out_lock;
+ }
+ rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry,
+@@ -908,7 +908,9 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
+ ia->ia_valid &= ~ATTR_MODE;
+
++ mutex_lock(&lower_dentry->d_inode->i_mutex);
+ rc = notify_change(lower_dentry, ia);
++ mutex_unlock(&lower_dentry->d_inode->i_mutex);
+ out:
+ fsstack_copy_attr_all(inode, lower_inode, NULL);
+ return rc;
+diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
+index 682b1b2..e82b457 100644
+--- a/fs/ecryptfs/keystore.c
++++ b/fs/ecryptfs/keystore.c
+@@ -65,7 +65,7 @@ static int process_request_key_err(long err_code)
}
-+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;
-+}
+ /**
+- * parse_packet_length
++ * ecryptfs_parse_packet_length
+ * @data: Pointer to memory containing length at offset
+ * @size: This function writes the decoded size to this memory
+ * address; zero on error
+@@ -73,8 +73,8 @@ static int process_request_key_err(long err_code)
+ *
+ * Returns zero on success; non-zero on error
+ */
+-static int parse_packet_length(unsigned char *data, size_t *size,
+- size_t *length_size)
++int ecryptfs_parse_packet_length(unsigned char *data, size_t *size,
++ size_t *length_size)
+ {
+ int rc = 0;
+
+@@ -105,7 +105,7 @@ out:
+ }
+
+ /**
+- * write_packet_length
++ * ecryptfs_write_packet_length
+ * @dest: The byte array target into which to write the length. Must
+ * have at least 5 bytes allocated.
+ * @size: The length to write.
+@@ -114,8 +114,8 @@ out:
+ *
+ * Returns zero on success; non-zero on error.
+ */
+-static int write_packet_length(char *dest, size_t size,
+- size_t *packet_size_length)
++int ecryptfs_write_packet_length(char *dest, size_t size,
++ size_t *packet_size_length)
+ {
+ int rc = 0;
+
+@@ -162,8 +162,8 @@ write_tag_64_packet(char *signature, struct ecryptfs_session_key *session_key,
+ goto out;
+ }
+ message[i++] = ECRYPTFS_TAG_64_PACKET_TYPE;
+- rc = write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX,
+- &packet_size_len);
++ rc = ecryptfs_write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX,
++ &packet_size_len);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet "
+ "header; cannot generate packet length\n");
+@@ -172,8 +172,9 @@ write_tag_64_packet(char *signature, struct ecryptfs_session_key *session_key,
+ i += packet_size_len;
+ memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX);
+ i += ECRYPTFS_SIG_SIZE_HEX;
+- rc = write_packet_length(&message[i], session_key->encrypted_key_size,
+- &packet_size_len);
++ rc = ecryptfs_write_packet_length(&message[i],
++ session_key->encrypted_key_size,
++ &packet_size_len);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet "
+ "header; cannot generate packet length\n");
+@@ -225,7 +226,7 @@ parse_tag_65_packet(struct ecryptfs_session_key *session_key, u8 *cipher_code,
+ rc = -EIO;
+ goto out;
+ }
+- rc = parse_packet_length(&data[i], &m_size, &data_len);
++ rc = ecryptfs_parse_packet_length(&data[i], &m_size, &data_len);
+ if (rc) {
+ ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
+ "rc = [%d]\n", rc);
+@@ -304,8 +305,8 @@ write_tag_66_packet(char *signature, u8 cipher_code,
+ goto out;
+ }
+ message[i++] = ECRYPTFS_TAG_66_PACKET_TYPE;
+- rc = write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX,
+- &packet_size_len);
++ rc = ecryptfs_write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX,
++ &packet_size_len);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet "
+ "header; cannot generate packet length\n");
+@@ -315,8 +316,8 @@ write_tag_66_packet(char *signature, u8 cipher_code,
+ memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX);
+ i += ECRYPTFS_SIG_SIZE_HEX;
+ /* The encrypted key includes 1 byte cipher code and 2 byte checksum */
+- rc = write_packet_length(&message[i], crypt_stat->key_size + 3,
+- &packet_size_len);
++ rc = ecryptfs_write_packet_length(&message[i], crypt_stat->key_size + 3,
++ &packet_size_len);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet "
+ "header; cannot generate packet length\n");
+@@ -357,20 +358,25 @@ parse_tag_67_packet(struct ecryptfs_key_record *key_rec,
+ /* verify that everything through the encrypted FEK size is present */
+ if (message_len < 4) {
+ rc = -EIO;
++ printk(KERN_ERR "%s: message_len is [%Zd]; minimum acceptable "
++ "message length is [%d]\n", __func__, message_len, 4);
+ goto out;
+ }
+ if (data[i++] != ECRYPTFS_TAG_67_PACKET_TYPE) {
+- ecryptfs_printk(KERN_ERR, "Type should be ECRYPTFS_TAG_67\n");
+ rc = -EIO;
++ printk(KERN_ERR "%s: Type should be ECRYPTFS_TAG_67\n",
++ __func__);
+ goto out;
+ }
+ if (data[i++]) {
+- ecryptfs_printk(KERN_ERR, "Status indicator has non zero value"
+- " [%d]\n", data[i-1]);
+ rc = -EIO;
++ printk(KERN_ERR "%s: Status indicator has non zero "
++ "value [%d]\n", __func__, data[i-1]);
+
- /* device/<type>/<id> => <type>-<id> */
- static int frontend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
+ goto out;
+ }
+- rc = parse_packet_length(&data[i], &key_rec->enc_key_size, &data_len);
++ rc = ecryptfs_parse_packet_length(&data[i], &key_rec->enc_key_size,
++ &data_len);
+ if (rc) {
+ ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
+ "rc = [%d]\n", rc);
+@@ -378,17 +384,17 @@ parse_tag_67_packet(struct ecryptfs_key_record *key_rec,
+ }
+ i += data_len;
+ if (message_len < (i + key_rec->enc_key_size)) {
+- ecryptfs_printk(KERN_ERR, "message_len [%d]; max len is [%d]\n",
+- message_len, (i + key_rec->enc_key_size));
+ rc = -EIO;
++ printk(KERN_ERR "%s: message_len [%Zd]; max len is [%Zd]\n",
++ __func__, message_len, (i + key_rec->enc_key_size));
+ goto out;
+ }
+ if (key_rec->enc_key_size > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {
+- ecryptfs_printk(KERN_ERR, "Encrypted key_size [%d] larger than "
+- "the maximum key size [%d]\n",
+- key_rec->enc_key_size,
+- ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES);
+ rc = -EIO;
++ printk(KERN_ERR "%s: Encrypted key_size [%Zd] larger than "
++ "the maximum key size [%d]\n", __func__,
++ key_rec->enc_key_size,
++ ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES);
+ goto out;
+ }
+ memcpy(key_rec->enc_key, &data[i], key_rec->enc_key_size);
+@@ -445,7 +451,7 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
+ rc = write_tag_64_packet(auth_tok_sig, &(auth_tok->session_key),
+ &netlink_message, &netlink_message_length);
+ if (rc) {
+- ecryptfs_printk(KERN_ERR, "Failed to write tag 64 packet");
++ ecryptfs_printk(KERN_ERR, "Failed to write tag 64 packet\n");
+ goto out;
+ }
+ rc = ecryptfs_send_message(ecryptfs_transport, netlink_message,
+@@ -570,8 +576,8 @@ parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat,
+ goto out;
+ }
+ (*new_auth_tok) = &auth_tok_list_item->auth_tok;
+- rc = parse_packet_length(&data[(*packet_size)], &body_size,
+- &length_size);
++ rc = ecryptfs_parse_packet_length(&data[(*packet_size)], &body_size,
++ &length_size);
+ if (rc) {
+ printk(KERN_WARNING "Error parsing packet length; "
+ "rc = [%d]\n", rc);
+@@ -704,8 +710,8 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
+ goto out;
+ }
+ (*new_auth_tok) = &auth_tok_list_item->auth_tok;
+- rc = parse_packet_length(&data[(*packet_size)], &body_size,
+- &length_size);
++ rc = ecryptfs_parse_packet_length(&data[(*packet_size)], &body_size,
++ &length_size);
+ if (rc) {
+ printk(KERN_WARNING "Error parsing packet length; rc = [%d]\n",
+ rc);
+@@ -852,8 +858,8 @@ parse_tag_11_packet(unsigned char *data, unsigned char *contents,
+ rc = -EINVAL;
+ goto out;
+ }
+- rc = parse_packet_length(&data[(*packet_size)], &body_size,
+- &length_size);
++ rc = ecryptfs_parse_packet_length(&data[(*packet_size)], &body_size,
++ &length_size);
+ if (rc) {
+ printk(KERN_WARNING "Invalid tag 11 packet format\n");
+ goto out;
+@@ -1405,8 +1411,8 @@ write_tag_1_packet(char *dest, size_t *remaining_bytes,
+ auth_tok->token.private_key.key_size;
+ rc = pki_encrypt_session_key(auth_tok, crypt_stat, key_rec);
+ if (rc) {
+- ecryptfs_printk(KERN_ERR, "Failed to encrypt session key "
+- "via a pki");
++ printk(KERN_ERR "Failed to encrypt session key via a key "
++ "module; rc = [%d]\n", rc);
+ goto out;
+ }
+ if (ecryptfs_verbosity > 0) {
+@@ -1430,8 +1436,9 @@ encrypted_session_key_set:
+ goto out;
+ }
+ dest[(*packet_size)++] = ECRYPTFS_TAG_1_PACKET_TYPE;
+- rc = write_packet_length(&dest[(*packet_size)], (max_packet_size - 4),
+- &packet_size_length);
++ rc = ecryptfs_write_packet_length(&dest[(*packet_size)],
++ (max_packet_size - 4),
++ &packet_size_length);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error generating tag 1 packet "
+ "header; cannot generate packet length\n");
+@@ -1489,8 +1496,9 @@ write_tag_11_packet(char *dest, size_t *remaining_bytes, char *contents,
+ goto out;
+ }
+ dest[(*packet_length)++] = ECRYPTFS_TAG_11_PACKET_TYPE;
+- rc = write_packet_length(&dest[(*packet_length)],
+- (max_packet_size - 4), &packet_size_length);
++ rc = ecryptfs_write_packet_length(&dest[(*packet_length)],
++ (max_packet_size - 4),
++ &packet_size_length);
+ if (rc) {
+ printk(KERN_ERR "Error generating tag 11 packet header; cannot "
+ "generate packet length. rc = [%d]\n", rc);
+@@ -1682,8 +1690,9 @@ encrypted_session_key_set:
+ dest[(*packet_size)++] = ECRYPTFS_TAG_3_PACKET_TYPE;
+ /* Chop off the Tag 3 identifier(1) and Tag 3 packet size(3)
+ * to get the number of octets in the actual Tag 3 packet */
+- rc = write_packet_length(&dest[(*packet_size)], (max_packet_size - 4),
+- &packet_size_length);
++ rc = ecryptfs_write_packet_length(&dest[(*packet_size)],
++ (max_packet_size - 4),
++ &packet_size_length);
+ if (rc) {
+ printk(KERN_ERR "Error generating tag 3 packet header; cannot "
+ "generate packet length. rc = [%d]\n", rc);
+diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
+index d25ac95..d603631 100644
+--- a/fs/ecryptfs/main.c
++++ b/fs/ecryptfs/main.c
+@@ -219,7 +219,7 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to initialize the "
+ "persistent file for the dentry with name [%s]; "
+- "rc = [%d]\n", __FUNCTION__, dentry->d_name.name, rc);
++ "rc = [%d]\n", __func__, dentry->d_name.name, rc);
+ goto out;
+ }
+ out:
+diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c
+index 9cc2aec..1b5c200 100644
+--- a/fs/ecryptfs/messaging.c
++++ b/fs/ecryptfs/messaging.c
+@@ -1,7 +1,7 @@
+ /**
+ * eCryptfs: Linux filesystem encryption layer
+ *
+- * Copyright (C) 2004-2006 International Business Machines Corp.
++ * Copyright (C) 2004-2008 International Business Machines Corp.
+ * Author(s): Michael A. Halcrow <mhalcrow at us.ibm.com>
+ * Tyler Hicks <tyhicks at ou.edu>
+ *
+@@ -20,19 +20,21 @@
+ * 02111-1307, USA.
+ */
+ #include <linux/sched.h>
++#include <linux/user_namespace.h>
++#include <linux/nsproxy.h>
+ #include "ecryptfs_kernel.h"
+
+ static LIST_HEAD(ecryptfs_msg_ctx_free_list);
+ static LIST_HEAD(ecryptfs_msg_ctx_alloc_list);
+ static struct mutex ecryptfs_msg_ctx_lists_mux;
+
+-static struct hlist_head *ecryptfs_daemon_id_hash;
+-static struct mutex ecryptfs_daemon_id_hash_mux;
++static struct hlist_head *ecryptfs_daemon_hash;
++struct mutex ecryptfs_daemon_hash_mux;
+ static int ecryptfs_hash_buckets;
+ #define ecryptfs_uid_hash(uid) \
+ hash_long((unsigned long)uid, ecryptfs_hash_buckets)
+
+-static unsigned int ecryptfs_msg_counter;
++static u32 ecryptfs_msg_counter;
+ static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr;
+
+ /**
+@@ -40,9 +42,10 @@ static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr;
+ * @msg_ctx: The context that was acquired from the free list
+ *
+ * Acquires a context element from the free list and locks the mutex
+- * on the context. Returns zero on success; non-zero on error or upon
+- * failure to acquire a free context element. Be sure to lock the
+- * list mutex before calling.
++ * on the context. Sets the msg_ctx task to current. Returns zero on
++ * success; non-zero on error or upon failure to acquire a free
++ * context element. Must be called with ecryptfs_msg_ctx_lists_mux
++ * held.
+ */
+ static int ecryptfs_acquire_free_msg_ctx(struct ecryptfs_msg_ctx **msg_ctx)
{
-@@ -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,
+@@ -50,11 +53,11 @@ static int ecryptfs_acquire_free_msg_ctx(struct ecryptfs_msg_ctx **msg_ctx)
+ int rc;
+
+ if (list_empty(&ecryptfs_msg_ctx_free_list)) {
+- ecryptfs_printk(KERN_WARNING, "The eCryptfs free "
+- "context list is empty. It may be helpful to "
+- "specify the ecryptfs_message_buf_len "
+- "parameter to be greater than the current "
+- "value of [%d]\n", ecryptfs_message_buf_len);
++ printk(KERN_WARNING "%s: The eCryptfs free "
++ "context list is empty. It may be helpful to "
++ "specify the ecryptfs_message_buf_len "
++ "parameter to be greater than the current "
++ "value of [%d]\n", __func__, ecryptfs_message_buf_len);
+ rc = -ENOMEM;
+ goto out;
+ }
+@@ -75,8 +78,7 @@ out:
+ * ecryptfs_msg_ctx_free_to_alloc
+ * @msg_ctx: The context to move from the free list to the alloc list
+ *
+- * Be sure to lock the list mutex and the context mutex before
+- * calling.
++ * Must be called with ecryptfs_msg_ctx_lists_mux held.
+ */
+ static void ecryptfs_msg_ctx_free_to_alloc(struct ecryptfs_msg_ctx *msg_ctx)
+ {
+@@ -89,36 +91,39 @@ static void ecryptfs_msg_ctx_free_to_alloc(struct ecryptfs_msg_ctx *msg_ctx)
+ * ecryptfs_msg_ctx_alloc_to_free
+ * @msg_ctx: The context to move from the alloc list to the free list
+ *
+- * Be sure to lock the list mutex and the context mutex before
+- * calling.
++ * Must be called with ecryptfs_msg_ctx_lists_mux held.
+ */
+-static void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx)
++void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx)
+ {
+ list_move(&(msg_ctx->node), &ecryptfs_msg_ctx_free_list);
+ if (msg_ctx->msg)
+ kfree(msg_ctx->msg);
++ msg_ctx->msg = NULL;
+ msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_FREE;
}
- 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);
+ /**
+- * ecryptfs_find_daemon_id
+- * @uid: The user id which maps to the desired daemon id
+- * @id: If return value is zero, points to the desired daemon id
+- * pointer
++ * ecryptfs_find_daemon_by_euid
++ * @euid: The effective user id which maps to the desired daemon id
++ * @user_ns: The namespace in which @euid applies
++ * @daemon: If return value is zero, points to the desired daemon pointer
+ *
+- * Search the hash list for the given user id. Returns zero if the
+- * user id exists in the list; non-zero otherwise. The daemon id hash
+- * mutex should be held before calling this function.
++ * Must be called with ecryptfs_daemon_hash_mux held.
++ *
++ * Search the hash list for the given user id.
++ *
++ * Returns zero if the user id exists in the list; non-zero otherwise.
+ */
+-static int ecryptfs_find_daemon_id(uid_t uid, struct ecryptfs_daemon_id **id)
++int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon, uid_t euid,
++ struct user_namespace *user_ns)
+ {
+ struct hlist_node *elem;
+ int rc;
+
+- hlist_for_each_entry(*id, elem,
+- &ecryptfs_daemon_id_hash[ecryptfs_uid_hash(uid)],
+- id_chain) {
+- if ((*id)->uid == uid) {
++ hlist_for_each_entry(*daemon, elem,
++ &ecryptfs_daemon_hash[ecryptfs_uid_hash(euid)],
++ euid_chain) {
++ if ((*daemon)->euid == euid && (*daemon)->user_ns == user_ns) {
+ rc = 0;
+ goto out;
+ }
+@@ -128,181 +133,325 @@ out:
+ return rc;
+ }
+
+-static int ecryptfs_send_raw_message(unsigned int transport, u16 msg_type,
+- pid_t pid)
++static int
++ecryptfs_send_message_locked(unsigned int transport, char *data, int data_len,
++ u8 msg_type, struct ecryptfs_msg_ctx **msg_ctx);
++
++/**
++ * ecryptfs_send_raw_message
++ * @transport: Transport type
++ * @msg_type: Message type
++ * @daemon: Daemon struct for recipient of message
++ *
++ * A raw message is one that does not include an ecryptfs_message
++ * struct. It simply has a type.
++ *
++ * Must be called with ecryptfs_daemon_hash_mux held.
++ *
++ * Returns zero on success; non-zero otherwise
++ */
++static int ecryptfs_send_raw_message(unsigned int transport, u8 msg_type,
++ struct ecryptfs_daemon *daemon)
+ {
++ struct ecryptfs_msg_ctx *msg_ctx;
+ int rc;
+
+ switch(transport) {
+ case ECRYPTFS_TRANSPORT_NETLINK:
+- rc = ecryptfs_send_netlink(NULL, 0, NULL, msg_type, 0, pid);
++ rc = ecryptfs_send_netlink(NULL, 0, NULL, msg_type, 0,
++ daemon->pid);
++ break;
++ case ECRYPTFS_TRANSPORT_MISCDEV:
++ rc = ecryptfs_send_message_locked(transport, NULL, 0, msg_type,
++ &msg_ctx);
++ if (rc) {
++ printk(KERN_ERR "%s: Error whilst attempting to send "
++ "message via procfs; rc = [%d]\n", __func__, rc);
++ goto out;
++ }
++ /* Raw messages are logically context-free (e.g., no
++ * reply is expected), so we set the state of the
++ * ecryptfs_msg_ctx object to indicate that it should
++ * be freed as soon as the transport sends out the message. */
++ mutex_lock(&msg_ctx->mux);
++ msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_NO_REPLY;
++ mutex_unlock(&msg_ctx->mux);
+ break;
+ case ECRYPTFS_TRANSPORT_CONNECTOR:
+ case ECRYPTFS_TRANSPORT_RELAYFS:
+ default:
+ rc = -ENOSYS;
+ }
++out:
++ return rc;
+}
-+DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL);
++
++/**
++ * ecryptfs_spawn_daemon - Create and initialize a new daemon struct
++ * @daemon: Pointer to set to newly allocated daemon struct
++ * @euid: Effective user id for the daemon
++ * @user_ns: The namespace in which @euid applies
++ * @pid: Process id for the daemon
++ *
++ * Must be called ceremoniously while in possession of
++ * ecryptfs_sacred_daemon_hash_mux
++ *
++ * Returns zero on success; non-zero otherwise
++ */
++int
++ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid,
++ struct user_namespace *user_ns, struct pid *pid)
++{
++ int rc = 0;
++
++ (*daemon) = kzalloc(sizeof(**daemon), GFP_KERNEL);
++ if (!(*daemon)) {
++ rc = -ENOMEM;
++ printk(KERN_ERR "%s: Failed to allocate [%Zd] bytes of "
++ "GFP_KERNEL memory\n", __func__, sizeof(**daemon));
++ goto out;
++ }
++ (*daemon)->euid = euid;
++ (*daemon)->user_ns = get_user_ns(user_ns);
++ (*daemon)->pid = get_pid(pid);
++ (*daemon)->task = current;
++ mutex_init(&(*daemon)->mux);
++ INIT_LIST_HEAD(&(*daemon)->msg_ctx_out_queue);
++ init_waitqueue_head(&(*daemon)->wait);
++ (*daemon)->num_queued_msg_ctx = 0;
++ hlist_add_head(&(*daemon)->euid_chain,
++ &ecryptfs_daemon_hash[ecryptfs_uid_hash(euid)]);
++out:
+ return rc;
+ }
- 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,
+ /**
+ * ecryptfs_process_helo
+ * @transport: The underlying transport (netlink, etc.)
+- * @uid: The user ID owner of the message
++ * @euid: The user ID owner of the message
++ * @user_ns: The namespace in which @euid applies
+ * @pid: The process ID for the userspace program that sent the
+ * message
+ *
+- * Adds the uid and pid values to the daemon id hash. If a uid
++ * Adds the euid and pid values to the daemon euid hash. If an euid
+ * already has a daemon pid registered, the daemon will be
+- * unregistered before the new daemon id is put into the hash list.
+- * Returns zero after adding a new daemon id to the hash list;
++ * unregistered before the new daemon is put into the hash list.
++ * Returns zero after adding a new daemon to the hash list;
+ * non-zero otherwise.
+ */
+-int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid)
++int ecryptfs_process_helo(unsigned int transport, uid_t euid,
++ struct user_namespace *user_ns, struct pid *pid)
+ {
+- struct ecryptfs_daemon_id *new_id;
+- struct ecryptfs_daemon_id *old_id;
++ struct ecryptfs_daemon *new_daemon;
++ struct ecryptfs_daemon *old_daemon;
+ int rc;
- err = device_create_file(&xendev->dev, &dev_attr_devtype);
- if (err)
-- goto fail_remove_file;
-+ goto fail_remove_nodename;
+- mutex_lock(&ecryptfs_daemon_id_hash_mux);
+- new_id = kmalloc(sizeof(*new_id), GFP_KERNEL);
+- if (!new_id) {
+- rc = -ENOMEM;
+- ecryptfs_printk(KERN_ERR, "Failed to allocate memory; unable "
+- "to register daemon [%d] for user [%d]\n",
+- pid, uid);
+- goto unlock;
+- }
+- if (!ecryptfs_find_daemon_id(uid, &old_id)) {
++ mutex_lock(&ecryptfs_daemon_hash_mux);
++ rc = ecryptfs_find_daemon_by_euid(&old_daemon, euid, user_ns);
++ if (rc != 0) {
+ printk(KERN_WARNING "Received request from user [%d] "
+- "to register daemon [%d]; unregistering daemon "
+- "[%d]\n", uid, pid, old_id->pid);
+- hlist_del(&old_id->id_chain);
+- rc = ecryptfs_send_raw_message(transport, ECRYPTFS_NLMSG_QUIT,
+- old_id->pid);
++ "to register daemon [0x%p]; unregistering daemon "
++ "[0x%p]\n", euid, pid, old_daemon->pid);
++ rc = ecryptfs_send_raw_message(transport, ECRYPTFS_MSG_QUIT,
++ old_daemon);
+ if (rc)
+ printk(KERN_WARNING "Failed to send QUIT "
+- "message to daemon [%d]; rc = [%d]\n",
+- old_id->pid, rc);
+- kfree(old_id);
++ "message to daemon [0x%p]; rc = [%d]\n",
++ old_daemon->pid, rc);
++ hlist_del(&old_daemon->euid_chain);
++ kfree(old_daemon);
+ }
+- new_id->uid = uid;
+- new_id->pid = pid;
+- hlist_add_head(&new_id->id_chain,
+- &ecryptfs_daemon_id_hash[ecryptfs_uid_hash(uid)]);
+- rc = 0;
+-unlock:
+- mutex_unlock(&ecryptfs_daemon_id_hash_mux);
++ rc = ecryptfs_spawn_daemon(&new_daemon, euid, user_ns, pid);
++ if (rc)
++ printk(KERN_ERR "%s: The gods are displeased with this attempt "
++ "to create a new daemon object for euid [%d]; pid "
++ "[0x%p]; rc = [%d]\n", __func__, euid, pid, rc);
++ mutex_unlock(&ecryptfs_daemon_hash_mux);
++ return rc;
++}
+
-+ err = device_create_file(&xendev->dev, &dev_attr_modalias);
-+ if (err)
-+ goto fail_remove_devtype;
++/**
++ * ecryptfs_exorcise_daemon - Destroy the daemon struct
++ *
++ * Must be called ceremoniously while in possession of
++ * ecryptfs_daemon_hash_mux and the daemon's own mux.
++ */
++int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon)
++{
++ struct ecryptfs_msg_ctx *msg_ctx, *msg_ctx_tmp;
++ int rc = 0;
++
++ mutex_lock(&daemon->mux);
++ if ((daemon->flags & ECRYPTFS_DAEMON_IN_READ)
++ || (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)) {
++ rc = -EBUSY;
++ printk(KERN_WARNING "%s: Attempt to destroy daemon with pid "
++ "[0x%p], but it is in the midst of a read or a poll\n",
++ __func__, daemon->pid);
++ mutex_unlock(&daemon->mux);
++ goto out;
++ }
++ list_for_each_entry_safe(msg_ctx, msg_ctx_tmp,
++ &daemon->msg_ctx_out_queue, daemon_out_list) {
++ list_del(&msg_ctx->daemon_out_list);
++ daemon->num_queued_msg_ctx--;
++ printk(KERN_WARNING "%s: Warning: dropping message that is in "
++ "the out queue of a dying daemon\n", __func__);
++ ecryptfs_msg_ctx_alloc_to_free(msg_ctx);
++ }
++ hlist_del(&daemon->euid_chain);
++ if (daemon->task)
++ wake_up_process(daemon->task);
++ if (daemon->pid)
++ put_pid(daemon->pid);
++ if (daemon->user_ns)
++ put_user_ns(daemon->user_ns);
++ mutex_unlock(&daemon->mux);
++ memset(daemon, 0, sizeof(*daemon));
++ kfree(daemon);
++out:
+ return rc;
+ }
- 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)
+ /**
+ * ecryptfs_process_quit
+- * @uid: The user ID owner of the message
++ * @euid: The user ID owner of the message
++ * @user_ns: The namespace in which @euid applies
+ * @pid: The process ID for the userspace program that sent the
+ * message
+ *
+- * Deletes the corresponding daemon id for the given uid and pid, if
++ * Deletes the corresponding daemon for the given euid and pid, if
+ * it is the registered that is requesting the deletion. Returns zero
+- * after deleting the desired daemon id; non-zero otherwise.
++ * after deleting the desired daemon; non-zero otherwise.
+ */
+-int ecryptfs_process_quit(uid_t uid, pid_t pid)
++int ecryptfs_process_quit(uid_t euid, struct user_namespace *user_ns,
++ struct pid *pid)
{
- struct xenbus_device *xendev = to_xenbus_device(dev);
- struct device_driver *drv = data;
-+ struct xenbus_driver *xendrv;
+- struct ecryptfs_daemon_id *id;
++ struct ecryptfs_daemon *daemon;
+ int rc;
- /*
- * 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;
+- mutex_lock(&ecryptfs_daemon_id_hash_mux);
+- if (ecryptfs_find_daemon_id(uid, &id)) {
++ mutex_lock(&ecryptfs_daemon_hash_mux);
++ rc = ecryptfs_find_daemon_by_euid(&daemon, euid, user_ns);
++ if (rc || !daemon) {
+ rc = -EINVAL;
+- ecryptfs_printk(KERN_ERR, "Received request from user [%d] to "
+- "unregister unrecognized daemon [%d]\n", uid,
+- pid);
+- goto unlock;
++ printk(KERN_ERR "Received request from user [%d] to "
++ "unregister unrecognized daemon [0x%p]\n", euid, pid);
++ goto out_unlock;
+ }
+- if (id->pid != pid) {
+- rc = -EINVAL;
+- ecryptfs_printk(KERN_WARNING, "Received request from user [%d] "
+- "with pid [%d] to unregister daemon [%d]\n",
+- uid, pid, id->pid);
+- goto unlock;
+- }
+- hlist_del(&id->id_chain);
+- kfree(id);
+- rc = 0;
+-unlock:
+- mutex_unlock(&ecryptfs_daemon_id_hash_mux);
++ rc = ecryptfs_exorcise_daemon(daemon);
++out_unlock:
++ mutex_unlock(&ecryptfs_daemon_hash_mux);
+ return rc;
+ }
-- return (xendev->state != XenbusStateConnected);
-+ xendrv = to_xenbus_driver(dev->driver);
-+ return (xendev->state != XenbusStateConnected ||
-+ (xendrv->is_ready && !xendrv->is_ready(xendev)));
+ /**
+ * ecryptfs_process_reponse
+ * @msg: The ecryptfs message received; the caller should sanity check
+- * msg->data_len
++ * msg->data_len and free the memory
+ * @pid: The process ID of the userspace application that sent the
+ * message
+- * @seq: The sequence number of the message
++ * @seq: The sequence number of the message; must match the sequence
++ * number for the existing message context waiting for this
++ * response
++ *
++ * Processes a response message after sending an operation request to
++ * userspace. Some other process is awaiting this response. Before
++ * sending out its first communications, the other process allocated a
++ * msg_ctx from the ecryptfs_msg_ctx_arr at a particular index. The
++ * response message contains this index so that we can copy over the
++ * response message into the msg_ctx that the process holds a
++ * reference to. The other process is going to wake up, check to see
++ * that msg_ctx->state == ECRYPTFS_MSG_CTX_STATE_DONE, and then
++ * proceed to read off and process the response message. Returns zero
++ * upon delivery to desired context element; non-zero upon delivery
++ * failure or error.
+ *
+- * Processes a response message after sending a operation request to
+- * userspace. Returns zero upon delivery to desired context element;
+- * non-zero upon delivery failure or error.
++ * Returns zero on success; non-zero otherwise
+ */
+-int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid,
+- pid_t pid, u32 seq)
++int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
++ struct user_namespace *user_ns, struct pid *pid,
++ u32 seq)
+ {
+- struct ecryptfs_daemon_id *id;
++ struct ecryptfs_daemon *daemon;
+ struct ecryptfs_msg_ctx *msg_ctx;
+- int msg_size;
++ size_t msg_size;
++ struct nsproxy *nsproxy;
++ struct user_namespace *current_user_ns;
+ int rc;
+
+ if (msg->index >= ecryptfs_message_buf_len) {
+ rc = -EINVAL;
+- ecryptfs_printk(KERN_ERR, "Attempt to reference "
+- "context buffer at index [%d]; maximum "
+- "allowable is [%d]\n", msg->index,
+- (ecryptfs_message_buf_len - 1));
++ printk(KERN_ERR "%s: Attempt to reference "
++ "context buffer at index [%d]; maximum "
++ "allowable is [%d]\n", __func__, msg->index,
++ (ecryptfs_message_buf_len - 1));
+ goto out;
+ }
+ msg_ctx = &ecryptfs_msg_ctx_arr[msg->index];
+ mutex_lock(&msg_ctx->mux);
+- if (ecryptfs_find_daemon_id(msg_ctx->task->euid, &id)) {
++ mutex_lock(&ecryptfs_daemon_hash_mux);
++ rcu_read_lock();
++ nsproxy = task_nsproxy(msg_ctx->task);
++ if (nsproxy == NULL) {
+ rc = -EBADMSG;
+- ecryptfs_printk(KERN_WARNING, "User [%d] received a "
+- "message response from process [%d] but does "
+- "not have a registered daemon\n",
+- msg_ctx->task->euid, pid);
++ printk(KERN_ERR "%s: Receiving process is a zombie. Dropping "
++ "message.\n", __func__);
++ rcu_read_unlock();
++ mutex_unlock(&ecryptfs_daemon_hash_mux);
+ goto wake_up;
+ }
+- if (msg_ctx->task->euid != uid) {
++ current_user_ns = nsproxy->user_ns;
++ rc = ecryptfs_find_daemon_by_euid(&daemon, msg_ctx->task->euid,
++ current_user_ns);
++ rcu_read_unlock();
++ mutex_unlock(&ecryptfs_daemon_hash_mux);
++ if (rc) {
++ rc = -EBADMSG;
++ printk(KERN_WARNING "%s: User [%d] received a "
++ "message response from process [0x%p] but does "
++ "not have a registered daemon\n", __func__,
++ msg_ctx->task->euid, pid);
++ goto wake_up;
++ }
++ if (msg_ctx->task->euid != euid) {
+ rc = -EBADMSG;
+- ecryptfs_printk(KERN_WARNING, "Received message from user "
+- "[%d]; expected message from user [%d]\n",
+- uid, msg_ctx->task->euid);
++ printk(KERN_WARNING "%s: Received message from user "
++ "[%d]; expected message from user [%d]\n", __func__,
++ euid, msg_ctx->task->euid);
+ goto unlock;
+ }
+- if (id->pid != pid) {
++ if (current_user_ns != user_ns) {
+ rc = -EBADMSG;
+- ecryptfs_printk(KERN_ERR, "User [%d] received a "
+- "message response from an unrecognized "
+- "process [%d]\n", msg_ctx->task->euid, pid);
++ printk(KERN_WARNING "%s: Received message from user_ns "
++ "[0x%p]; expected message from user_ns [0x%p]\n",
++ __func__, user_ns, nsproxy->user_ns);
++ goto unlock;
++ }
++ if (daemon->pid != pid) {
++ rc = -EBADMSG;
++ printk(KERN_ERR "%s: User [%d] sent a message response "
++ "from an unrecognized process [0x%p]\n",
++ __func__, msg_ctx->task->euid, pid);
+ goto unlock;
+ }
+ if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) {
+ rc = -EINVAL;
+- ecryptfs_printk(KERN_WARNING, "Desired context element is not "
+- "pending a response\n");
++ printk(KERN_WARNING "%s: Desired context element is not "
++ "pending a response\n", __func__);
+ goto unlock;
+ } else if (msg_ctx->counter != seq) {
+ rc = -EINVAL;
+- ecryptfs_printk(KERN_WARNING, "Invalid message sequence; "
+- "expected [%d]; received [%d]\n",
+- msg_ctx->counter, seq);
++ printk(KERN_WARNING "%s: Invalid message sequence; "
++ "expected [%d]; received [%d]\n", __func__,
++ msg_ctx->counter, seq);
+ goto unlock;
+ }
+- msg_size = sizeof(*msg) + msg->data_len;
++ msg_size = (sizeof(*msg) + msg->data_len);
+ msg_ctx->msg = kmalloc(msg_size, GFP_KERNEL);
+ if (!msg_ctx->msg) {
+ rc = -ENOMEM;
+- ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n");
++ printk(KERN_ERR "%s: Failed to allocate [%Zd] bytes of "
++ "GFP_KERNEL memory\n", __func__, msg_size);
+ goto unlock;
+ }
+ memcpy(msg_ctx->msg, msg, msg_size);
+@@ -317,34 +466,38 @@ out:
}
- static int exists_disconnected_device(struct device_driver *drv)
-diff --git a/drivers/xen/xencomm.c b/drivers/xen/xencomm.c
+ /**
+- * ecryptfs_send_message
++ * ecryptfs_send_message_locked
+ * @transport: The transport over which to send the message (i.e.,
+ * netlink)
+ * @data: The data to send
+ * @data_len: The length of data
+ * @msg_ctx: The message context allocated for the send
++ *
++ * Must be called with ecryptfs_daemon_hash_mux held.
++ *
++ * Returns zero on success; non-zero otherwise
+ */
+-int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
+- struct ecryptfs_msg_ctx **msg_ctx)
++static int
++ecryptfs_send_message_locked(unsigned int transport, char *data, int data_len,
++ u8 msg_type, struct ecryptfs_msg_ctx **msg_ctx)
+ {
+- struct ecryptfs_daemon_id *id;
++ struct ecryptfs_daemon *daemon;
+ int rc;
+
+- mutex_lock(&ecryptfs_daemon_id_hash_mux);
+- if (ecryptfs_find_daemon_id(current->euid, &id)) {
+- mutex_unlock(&ecryptfs_daemon_id_hash_mux);
++ rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
++ current->nsproxy->user_ns);
++ if (rc || !daemon) {
+ rc = -ENOTCONN;
+- ecryptfs_printk(KERN_ERR, "User [%d] does not have a daemon "
+- "registered\n", current->euid);
++ printk(KERN_ERR "%s: User [%d] does not have a daemon "
++ "registered\n", __func__, current->euid);
+ goto out;
+ }
+- mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+ mutex_lock(&ecryptfs_msg_ctx_lists_mux);
+ rc = ecryptfs_acquire_free_msg_ctx(msg_ctx);
+ if (rc) {
+ mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+- ecryptfs_printk(KERN_WARNING, "Could not claim a free "
+- "context element\n");
++ printk(KERN_WARNING "%s: Could not claim a free "
++ "context element\n", __func__);
+ goto out;
+ }
+ ecryptfs_msg_ctx_free_to_alloc(*msg_ctx);
+@@ -352,23 +505,50 @@ int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
+ mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+ switch (transport) {
+ case ECRYPTFS_TRANSPORT_NETLINK:
+- rc = ecryptfs_send_netlink(data, data_len, *msg_ctx,
+- ECRYPTFS_NLMSG_REQUEST, 0, id->pid);
++ rc = ecryptfs_send_netlink(data, data_len, *msg_ctx, msg_type,
++ 0, daemon->pid);
++ break;
++ case ECRYPTFS_TRANSPORT_MISCDEV:
++ rc = ecryptfs_send_miscdev(data, data_len, *msg_ctx, msg_type,
++ 0, daemon);
+ break;
+ case ECRYPTFS_TRANSPORT_CONNECTOR:
+ case ECRYPTFS_TRANSPORT_RELAYFS:
+ default:
+ rc = -ENOSYS;
+ }
+- if (rc) {
+- printk(KERN_ERR "Error attempting to send message to userspace "
+- "daemon; rc = [%d]\n", rc);
+- }
++ if (rc)
++ printk(KERN_ERR "%s: Error attempting to send message to "
++ "userspace daemon; rc = [%d]\n", __func__, rc);
+ out:
+ return rc;
+ }
+
+ /**
++ * ecryptfs_send_message
++ * @transport: The transport over which to send the message (i.e.,
++ * netlink)
++ * @data: The data to send
++ * @data_len: The length of data
++ * @msg_ctx: The message context allocated for the send
++ *
++ * Grabs ecryptfs_daemon_hash_mux.
++ *
++ * Returns zero on success; non-zero otherwise
++ */
++int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
++ struct ecryptfs_msg_ctx **msg_ctx)
++{
++ int rc;
++
++ mutex_lock(&ecryptfs_daemon_hash_mux);
++ rc = ecryptfs_send_message_locked(transport, data, data_len,
++ ECRYPTFS_MSG_REQUEST, msg_ctx);
++ mutex_unlock(&ecryptfs_daemon_hash_mux);
++ return rc;
++}
++
++/**
+ * ecryptfs_wait_for_response
+ * @msg_ctx: The context that was assigned when sending a message
+ * @msg: The incoming message from userspace; not set if rc != 0
+@@ -377,7 +557,7 @@ out:
+ * of time exceeds ecryptfs_message_wait_timeout. If zero is
+ * returned, msg will point to a valid message from userspace; a
+ * non-zero value is returned upon failure to receive a message or an
+- * error occurs.
++ * error occurs. Callee must free @msg on success.
+ */
+ int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx,
+ struct ecryptfs_message **msg)
+@@ -413,32 +593,32 @@ int ecryptfs_init_messaging(unsigned int transport)
+
+ if (ecryptfs_number_of_users > ECRYPTFS_MAX_NUM_USERS) {
+ ecryptfs_number_of_users = ECRYPTFS_MAX_NUM_USERS;
+- ecryptfs_printk(KERN_WARNING, "Specified number of users is "
+- "too large, defaulting to [%d] users\n",
+- ecryptfs_number_of_users);
++ printk(KERN_WARNING "%s: Specified number of users is "
++ "too large, defaulting to [%d] users\n", __func__,
++ ecryptfs_number_of_users);
+ }
+- mutex_init(&ecryptfs_daemon_id_hash_mux);
+- mutex_lock(&ecryptfs_daemon_id_hash_mux);
++ mutex_init(&ecryptfs_daemon_hash_mux);
++ mutex_lock(&ecryptfs_daemon_hash_mux);
+ ecryptfs_hash_buckets = 1;
+ while (ecryptfs_number_of_users >> ecryptfs_hash_buckets)
+ ecryptfs_hash_buckets++;
+- ecryptfs_daemon_id_hash = kmalloc(sizeof(struct hlist_head)
+- * ecryptfs_hash_buckets, GFP_KERNEL);
+- if (!ecryptfs_daemon_id_hash) {
++ ecryptfs_daemon_hash = kmalloc((sizeof(struct hlist_head)
++ * ecryptfs_hash_buckets), GFP_KERNEL);
++ if (!ecryptfs_daemon_hash) {
+ rc = -ENOMEM;
+- ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n");
+- mutex_unlock(&ecryptfs_daemon_id_hash_mux);
++ printk(KERN_ERR "%s: Failed to allocate memory\n", __func__);
++ mutex_unlock(&ecryptfs_daemon_hash_mux);
+ goto out;
+ }
+ for (i = 0; i < ecryptfs_hash_buckets; i++)
+- INIT_HLIST_HEAD(&ecryptfs_daemon_id_hash[i]);
+- mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+-
++ INIT_HLIST_HEAD(&ecryptfs_daemon_hash[i]);
++ mutex_unlock(&ecryptfs_daemon_hash_mux);
+ ecryptfs_msg_ctx_arr = kmalloc((sizeof(struct ecryptfs_msg_ctx)
+- * ecryptfs_message_buf_len), GFP_KERNEL);
++ * ecryptfs_message_buf_len),
++ GFP_KERNEL);
+ if (!ecryptfs_msg_ctx_arr) {
+ rc = -ENOMEM;
+- ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n");
++ printk(KERN_ERR "%s: Failed to allocate memory\n", __func__);
+ goto out;
+ }
+ mutex_init(&ecryptfs_msg_ctx_lists_mux);
+@@ -446,6 +626,7 @@ int ecryptfs_init_messaging(unsigned int transport)
+ ecryptfs_msg_counter = 0;
+ for (i = 0; i < ecryptfs_message_buf_len; i++) {
+ INIT_LIST_HEAD(&ecryptfs_msg_ctx_arr[i].node);
++ INIT_LIST_HEAD(&ecryptfs_msg_ctx_arr[i].daemon_out_list);
+ mutex_init(&ecryptfs_msg_ctx_arr[i].mux);
+ mutex_lock(&ecryptfs_msg_ctx_arr[i].mux);
+ ecryptfs_msg_ctx_arr[i].index = i;
+@@ -464,6 +645,11 @@ int ecryptfs_init_messaging(unsigned int transport)
+ if (rc)
+ ecryptfs_release_messaging(transport);
+ break;
++ case ECRYPTFS_TRANSPORT_MISCDEV:
++ rc = ecryptfs_init_ecryptfs_miscdev();
++ if (rc)
++ ecryptfs_release_messaging(transport);
++ break;
+ case ECRYPTFS_TRANSPORT_CONNECTOR:
+ case ECRYPTFS_TRANSPORT_RELAYFS:
+ default:
+@@ -488,27 +674,37 @@ void ecryptfs_release_messaging(unsigned int transport)
+ kfree(ecryptfs_msg_ctx_arr);
+ mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+ }
+- if (ecryptfs_daemon_id_hash) {
++ if (ecryptfs_daemon_hash) {
+ struct hlist_node *elem;
+- struct ecryptfs_daemon_id *id;
++ struct ecryptfs_daemon *daemon;
+ int i;
+
+- mutex_lock(&ecryptfs_daemon_id_hash_mux);
++ mutex_lock(&ecryptfs_daemon_hash_mux);
+ for (i = 0; i < ecryptfs_hash_buckets; i++) {
+- hlist_for_each_entry(id, elem,
+- &ecryptfs_daemon_id_hash[i],
+- id_chain) {
+- hlist_del(elem);
+- kfree(id);
++ int rc;
++
++ hlist_for_each_entry(daemon, elem,
++ &ecryptfs_daemon_hash[i],
++ euid_chain) {
++ rc = ecryptfs_exorcise_daemon(daemon);
++ if (rc)
++ printk(KERN_ERR "%s: Error whilst "
++ "attempting to destroy daemon; "
++ "rc = [%d]. Dazed and confused, "
++ "but trying to continue.\n",
++ __func__, rc);
+ }
+ }
+- kfree(ecryptfs_daemon_id_hash);
+- mutex_unlock(&ecryptfs_daemon_id_hash_mux);
++ kfree(ecryptfs_daemon_hash);
++ mutex_unlock(&ecryptfs_daemon_hash_mux);
+ }
+ switch(transport) {
+ case ECRYPTFS_TRANSPORT_NETLINK:
+ ecryptfs_release_netlink();
+ break;
++ case ECRYPTFS_TRANSPORT_MISCDEV:
++ ecryptfs_destroy_ecryptfs_miscdev();
++ break;
+ case ECRYPTFS_TRANSPORT_CONNECTOR:
+ case ECRYPTFS_TRANSPORT_RELAYFS:
+ default:
+diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
new file mode 100644
-index 0000000..797cb4e
+index 0000000..788995e
--- /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.
++++ b/fs/ecryptfs/miscdev.c
+@@ -0,0 +1,598 @@
++/**
++ * eCryptfs: Linux filesystem encryption layer
+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT 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) 2008 International Business Machines Corp.
++ * Author(s): Michael A. Halcrow <mhalcrow at us.ibm.com>
+ *
-+ * You 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
++ * 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.
+ *
-+ * Copyright (C) IBM Corp. 2006
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
+ *
-+ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++ * 02111-1307, USA.
+ */
+
-+#include <linux/gfp.h>
-+#include <linux/mm.h>
-+#include <asm/page.h>
-+#include <xen/xencomm.h>
-+#include <xen/interface/xen.h>
-+#ifdef __ia64__
-+#include <asm/xen/xencomm.h> /* for is_kern_addr() */
-+#endif
++#include <linux/fs.h>
++#include <linux/hash.h>
++#include <linux/random.h>
++#include <linux/miscdevice.h>
++#include <linux/poll.h>
++#include <linux/wait.h>
++#include <linux/module.h>
++#include "ecryptfs_kernel.h"
+
-+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
-+#include <xen/platform-compat.h>
-+#endif
++static atomic_t ecryptfs_num_miscdev_opens;
+
-+static int xencomm_init(struct xencomm_desc *desc,
-+ void *buffer, unsigned long bytes)
++/**
++ * ecryptfs_miscdev_poll
++ * @file: dev file (ignored)
++ * @pt: dev poll table (ignored)
++ *
++ * Returns the poll mask
++ */
++static unsigned int
++ecryptfs_miscdev_poll(struct file *file, poll_table *pt)
+{
-+ unsigned long recorded = 0;
-+ int i = 0;
++ struct ecryptfs_daemon *daemon;
++ unsigned int mask = 0;
++ int rc;
+
-+ while ((recorded < bytes) && (i < desc->nr_addrs)) {
-+ unsigned long vaddr = (unsigned long)buffer + recorded;
-+ unsigned long paddr;
-+ int offset;
-+ int chunksz;
++ mutex_lock(&ecryptfs_daemon_hash_mux);
++ /* TODO: Just use file->private_data? */
++ rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
++ current->nsproxy->user_ns);
++ BUG_ON(rc || !daemon);
++ mutex_lock(&daemon->mux);
++ mutex_unlock(&ecryptfs_daemon_hash_mux);
++ if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
++ printk(KERN_WARNING "%s: Attempt to poll on zombified "
++ "daemon\n", __func__);
++ goto out_unlock_daemon;
++ }
++ if (daemon->flags & ECRYPTFS_DAEMON_IN_READ)
++ goto out_unlock_daemon;
++ if (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)
++ goto out_unlock_daemon;
++ daemon->flags |= ECRYPTFS_DAEMON_IN_POLL;
++ mutex_unlock(&daemon->mux);
++ poll_wait(file, &daemon->wait, pt);
++ mutex_lock(&daemon->mux);
++ if (!list_empty(&daemon->msg_ctx_out_queue))
++ mask |= POLLIN | POLLRDNORM;
++out_unlock_daemon:
++ daemon->flags &= ~ECRYPTFS_DAEMON_IN_POLL;
++ mutex_unlock(&daemon->mux);
++ return mask;
++}
+
-+ offset = vaddr % PAGE_SIZE; /* handle partial pages */
-+ chunksz = min(PAGE_SIZE - offset, bytes - recorded);
++/**
++ * ecryptfs_miscdev_open
++ * @inode: inode of miscdev handle (ignored)
++ * @file: file for miscdev handle (ignored)
++ *
++ * Returns zero on success; non-zero otherwise
++ */
++static int
++ecryptfs_miscdev_open(struct inode *inode, struct file *file)
++{
++ struct ecryptfs_daemon *daemon = NULL;
++ int rc;
+
-+ paddr = xencomm_vtop(vaddr);
-+ if (paddr == ~0UL) {
-+ printk(KERN_DEBUG "%s: couldn't translate vaddr %lx\n",
-+ __func__, vaddr);
-+ return -EINVAL;
++ mutex_lock(&ecryptfs_daemon_hash_mux);
++ rc = try_module_get(THIS_MODULE);
++ if (rc == 0) {
++ rc = -EIO;
++ printk(KERN_ERR "%s: Error attempting to increment module use "
++ "count; rc = [%d]\n", __func__, rc);
++ goto out_unlock_daemon_list;
++ }
++ rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
++ current->nsproxy->user_ns);
++ if (rc || !daemon) {
++ rc = ecryptfs_spawn_daemon(&daemon, current->euid,
++ current->nsproxy->user_ns,
++ task_pid(current));
++ if (rc) {
++ printk(KERN_ERR "%s: Error attempting to spawn daemon; "
++ "rc = [%d]\n", __func__, rc);
++ goto out_module_put_unlock_daemon_list;
+ }
-+
-+ 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;
++ mutex_lock(&daemon->mux);
++ if (daemon->pid != task_pid(current)) {
++ rc = -EINVAL;
++ printk(KERN_ERR "%s: pid [0x%p] has registered with euid [%d], "
++ "but pid [0x%p] has attempted to open the handle "
++ "instead\n", __func__, daemon->pid, daemon->euid,
++ task_pid(current));
++ goto out_unlock_daemon;
+ }
-+
-+ /* mark remaining addresses invalid (just for safety) */
-+ while (i < desc->nr_addrs)
-+ desc->address[i++] = XENCOMM_INVALID;
-+
-+ desc->magic = XENCOMM_MAGIC;
-+
-+ return 0;
++ if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) {
++ rc = -EBUSY;
++ printk(KERN_ERR "%s: Miscellaneous device handle may only be "
++ "opened once per daemon; pid [0x%p] already has this "
++ "handle open\n", __func__, daemon->pid);
++ goto out_unlock_daemon;
++ }
++ daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN;
++ atomic_inc(&ecryptfs_num_miscdev_opens);
++out_unlock_daemon:
++ mutex_unlock(&daemon->mux);
++out_module_put_unlock_daemon_list:
++ if (rc)
++ module_put(THIS_MODULE);
++out_unlock_daemon_list:
++ mutex_unlock(&ecryptfs_daemon_hash_mux);
++ return rc;
+}
+
-+static struct xencomm_desc *xencomm_alloc(gfp_t gfp_mask,
-+ void *buffer, unsigned long bytes)
++/**
++ * ecryptfs_miscdev_release
++ * @inode: inode of fs/ecryptfs/euid handle (ignored)
++ * @file: file for fs/ecryptfs/euid handle (ignored)
++ *
++ * This keeps the daemon registered until the daemon sends another
++ * ioctl to fs/ecryptfs/ctl or until the kernel module unregisters.
++ *
++ * Returns zero on success; non-zero otherwise
++ */
++static int
++ecryptfs_miscdev_release(struct inode *inode, struct file *file)
+{
-+ 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;
++ struct ecryptfs_daemon *daemon = NULL;
++ int rc;
+
-+ desc->nr_addrs = nr_addrs;
++ mutex_lock(&ecryptfs_daemon_hash_mux);
++ rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
++ current->nsproxy->user_ns);
++ BUG_ON(rc || !daemon);
++ mutex_lock(&daemon->mux);
++ BUG_ON(daemon->pid != task_pid(current));
++ BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN));
++ daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN;
++ atomic_dec(&ecryptfs_num_miscdev_opens);
++ mutex_unlock(&daemon->mux);
++ rc = ecryptfs_exorcise_daemon(daemon);
++ if (rc) {
++ printk(KERN_CRIT "%s: Fatal error whilst attempting to "
++ "shut down daemon; rc = [%d]. Please report this "
++ "bug.\n", __func__, rc);
++ BUG();
+ }
-+ return desc;
++ module_put(THIS_MODULE);
++ mutex_unlock(&ecryptfs_daemon_hash_mux);
++ return rc;
+}
+
-+void xencomm_free(struct xencomm_handle *desc)
++/**
++ * ecryptfs_send_miscdev
++ * @data: Data to send to daemon; may be NULL
++ * @data_size: Amount of data to send to daemon
++ * @msg_ctx: Message context, which is used to handle the reply. If
++ * this is NULL, then we do not expect a reply.
++ * @msg_type: Type of message
++ * @msg_flags: Flags for message
++ * @daemon: eCryptfs daemon object
++ *
++ * Add msg_ctx to queue and then, if it exists, notify the blocked
++ * miscdevess about the data being available. Must be called with
++ * ecryptfs_daemon_hash_mux held.
++ *
++ * Returns zero on success; non-zero otherwise
++ */
++int ecryptfs_send_miscdev(char *data, size_t data_size,
++ struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
++ u16 msg_flags, struct ecryptfs_daemon *daemon)
+{
-+ 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));
-+ }
++ int rc = 0;
++
++ mutex_lock(&msg_ctx->mux);
++ if (data) {
++ msg_ctx->msg = kmalloc((sizeof(*msg_ctx->msg) + data_size),
++ GFP_KERNEL);
++ if (!msg_ctx->msg) {
++ rc = -ENOMEM;
++ printk(KERN_ERR "%s: Out of memory whilst attempting "
++ "to kmalloc(%Zd, GFP_KERNEL)\n", __func__,
++ (sizeof(*msg_ctx->msg) + data_size));
++ goto out_unlock;
++ }
++ } else
++ msg_ctx->msg = NULL;
++ msg_ctx->msg->index = msg_ctx->index;
++ msg_ctx->msg->data_len = data_size;
++ msg_ctx->type = msg_type;
++ if (data) {
++ memcpy(msg_ctx->msg->data, data, data_size);
++ msg_ctx->msg_size = (sizeof(*msg_ctx->msg) + data_size);
++ } else
++ msg_ctx->msg_size = 0;
++ mutex_lock(&daemon->mux);
++ list_add_tail(&msg_ctx->daemon_out_list, &daemon->msg_ctx_out_queue);
++ daemon->num_queued_msg_ctx++;
++ wake_up_interruptible(&daemon->wait);
++ mutex_unlock(&daemon->mux);
++out_unlock:
++ mutex_unlock(&msg_ctx->mux);
++ return rc;
+}
+
-+static int xencomm_create(void *buffer, unsigned long bytes,
-+ struct xencomm_desc **ret, gfp_t gfp_mask)
++/**
++ * ecryptfs_miscdev_read - format and send message from queue
++ * @file: fs/ecryptfs/euid miscdevfs handle (ignored)
++ * @buf: User buffer into which to copy the next message on the daemon queue
++ * @count: Amount of space available in @buf
++ * @ppos: Offset in file (ignored)
++ *
++ * Pulls the most recent message from the daemon queue, formats it for
++ * being sent via a miscdevfs handle, and copies it into @buf
++ *
++ * Returns the number of bytes copied into the user buffer
++ */
++static ssize_t
++ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
++ loff_t *ppos)
+{
-+ struct xencomm_desc *desc;
++ struct ecryptfs_daemon *daemon;
++ struct ecryptfs_msg_ctx *msg_ctx;
++ size_t packet_length_size;
++ u32 counter_nbo;
++ char packet_length[3];
++ size_t i;
++ size_t total_length;
+ 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;
++ mutex_lock(&ecryptfs_daemon_hash_mux);
++ /* TODO: Just use file->private_data? */
++ rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
++ current->nsproxy->user_ns);
++ BUG_ON(rc || !daemon);
++ mutex_lock(&daemon->mux);
++ if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
++ rc = 0;
++ printk(KERN_WARNING "%s: Attempt to read from zombified "
++ "daemon\n", __func__);
++ goto out_unlock_daemon;
+ }
-+
-+ 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;
++ if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) {
++ rc = 0;
++ goto out_unlock_daemon;
+ }
-+
-+ 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;
++ /* This daemon will not go away so long as this flag is set */
++ daemon->flags |= ECRYPTFS_DAEMON_IN_READ;
++ mutex_unlock(&ecryptfs_daemon_hash_mux);
++check_list:
++ if (list_empty(&daemon->msg_ctx_out_queue)) {
++ mutex_unlock(&daemon->mux);
++ rc = wait_event_interruptible(
++ daemon->wait, !list_empty(&daemon->msg_ctx_out_queue));
++ mutex_lock(&daemon->mux);
++ if (rc < 0) {
++ rc = 0;
++ goto out_unlock_daemon;
++ }
+ }
-+
-+ *ret = desc;
-+ return 0;
++ if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
++ rc = 0;
++ goto out_unlock_daemon;
++ }
++ if (list_empty(&daemon->msg_ctx_out_queue)) {
++ /* Something else jumped in since the
++ * wait_event_interruptable() and removed the
++ * message from the queue; try again */
++ goto check_list;
++ }
++ BUG_ON(current->euid != daemon->euid);
++ BUG_ON(current->nsproxy->user_ns != daemon->user_ns);
++ BUG_ON(task_pid(current) != daemon->pid);
++ msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,
++ struct ecryptfs_msg_ctx, daemon_out_list);
++ BUG_ON(!msg_ctx);
++ mutex_lock(&msg_ctx->mux);
++ if (msg_ctx->msg) {
++ rc = ecryptfs_write_packet_length(packet_length,
++ msg_ctx->msg_size,
++ &packet_length_size);
++ if (rc) {
++ rc = 0;
++ printk(KERN_WARNING "%s: Error writing packet length; "
++ "rc = [%d]\n", __func__, rc);
++ goto out_unlock_msg_ctx;
++ }
++ } else {
++ packet_length_size = 0;
++ msg_ctx->msg_size = 0;
++ }
++ /* miscdevfs packet format:
++ * Octet 0: Type
++ * Octets 1-4: network byte order msg_ctx->counter
++ * Octets 5-N0: Size of struct ecryptfs_message to follow
++ * Octets N0-N1: struct ecryptfs_message (including data)
++ *
++ * Octets 5-N1 not written if the packet type does not
++ * include a message */
++ total_length = (1 + 4 + packet_length_size + msg_ctx->msg_size);
++ if (count < total_length) {
++ rc = 0;
++ printk(KERN_WARNING "%s: Only given user buffer of "
++ "size [%Zd], but we need [%Zd] to read the "
++ "pending message\n", __func__, count, total_length);
++ goto out_unlock_msg_ctx;
++ }
++ i = 0;
++ buf[i++] = msg_ctx->type;
++ counter_nbo = cpu_to_be32(msg_ctx->counter);
++ memcpy(&buf[i], (char *)&counter_nbo, 4);
++ i += 4;
++ if (msg_ctx->msg) {
++ memcpy(&buf[i], packet_length, packet_length_size);
++ i += packet_length_size;
++ rc = copy_to_user(&buf[i], msg_ctx->msg, msg_ctx->msg_size);
++ if (rc) {
++ printk(KERN_ERR "%s: copy_to_user returned error "
++ "[%d]\n", __func__, rc);
++ goto out_unlock_msg_ctx;
++ }
++ i += msg_ctx->msg_size;
++ }
++ rc = i;
++ list_del(&msg_ctx->daemon_out_list);
++ kfree(msg_ctx->msg);
++ msg_ctx->msg = NULL;
++ /* We do not expect a reply from the userspace daemon for any
++ * message type other than ECRYPTFS_MSG_REQUEST */
++ if (msg_ctx->type != ECRYPTFS_MSG_REQUEST)
++ ecryptfs_msg_ctx_alloc_to_free(msg_ctx);
++out_unlock_msg_ctx:
++ mutex_unlock(&msg_ctx->mux);
++out_unlock_daemon:
++ daemon->flags &= ~ECRYPTFS_DAEMON_IN_READ;
++ mutex_unlock(&daemon->mux);
++ return rc;
+}
+
-+/* check if memory address is within VMALLOC region */
-+static int is_phys_contiguous(unsigned long addr)
++/**
++ * ecryptfs_miscdev_helo
++ * @euid: effective user id of miscdevess sending helo packet
++ * @user_ns: The namespace in which @euid applies
++ * @pid: miscdevess id of miscdevess sending helo packet
++ *
++ * Returns zero on success; non-zero otherwise
++ */
++static int ecryptfs_miscdev_helo(uid_t euid, struct user_namespace *user_ns,
++ struct pid *pid)
+{
-+ if (!is_kernel_addr(addr))
-+ return 0;
++ int rc;
+
-+ return (addr < VMALLOC_START) || (addr >= VMALLOC_END);
++ rc = ecryptfs_process_helo(ECRYPTFS_TRANSPORT_MISCDEV, euid, user_ns,
++ pid);
++ if (rc)
++ printk(KERN_WARNING "Error processing HELO; rc = [%d]\n", rc);
++ return rc;
+}
+
-+static struct xencomm_handle *xencomm_create_inline(void *ptr)
++/**
++ * ecryptfs_miscdev_quit
++ * @euid: effective user id of miscdevess sending quit packet
++ * @user_ns: The namespace in which @euid applies
++ * @pid: miscdevess id of miscdevess sending quit packet
++ *
++ * Returns zero on success; non-zero otherwise
++ */
++static int ecryptfs_miscdev_quit(uid_t euid, struct user_namespace *user_ns,
++ struct pid *pid)
+{
-+ unsigned long paddr;
-+
-+ BUG_ON(!is_phys_contiguous((unsigned long)ptr));
++ int rc;
+
-+ paddr = (unsigned long)xencomm_pa(ptr);
-+ BUG_ON(paddr & XENCOMM_INLINE_FLAG);
-+ return (struct xencomm_handle *)(paddr | XENCOMM_INLINE_FLAG);
++ rc = ecryptfs_process_quit(euid, user_ns, pid);
++ if (rc)
++ printk(KERN_WARNING
++ "Error processing QUIT message; rc = [%d]\n", rc);
++ return rc;
+}
+
-+/* "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)
++/**
++ * ecryptfs_miscdev_response - miscdevess response to message previously sent to daemon
++ * @data: Bytes comprising struct ecryptfs_message
++ * @data_size: sizeof(struct ecryptfs_message) + data len
++ * @euid: Effective user id of miscdevess sending the miscdev response
++ * @user_ns: The namespace in which @euid applies
++ * @pid: Miscdevess id of miscdevess sending the miscdev response
++ * @seq: Sequence number for miscdev response packet
++ *
++ * Returns zero on success; non-zero otherwise
++ */
++static int ecryptfs_miscdev_response(char *data, size_t data_size,
++ uid_t euid, struct user_namespace *user_ns,
++ struct pid *pid, u32 seq)
+{
-+ 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;
++ struct ecryptfs_message *msg = (struct ecryptfs_message *)data;
++ int rc;
+
++ if ((sizeof(*msg) + msg->data_len) != data_size) {
++ printk(KERN_WARNING "%s: (sizeof(*msg) + msg->data_len) = "
++ "[%Zd]; data_size = [%Zd]. Invalid packet.\n", __func__,
++ (sizeof(*msg) + msg->data_len), data_size);
++ rc = -EINVAL;
++ goto out;
++ }
++ rc = ecryptfs_process_response(msg, euid, user_ns, pid, seq);
++ if (rc)
++ printk(KERN_ERR
++ "Error processing response message; rc = [%d]\n", rc);
++out:
+ return rc;
+}
+
-+struct xencomm_handle *xencomm_map(void *ptr, unsigned long bytes)
++/**
++ * ecryptfs_miscdev_write - handle write to daemon miscdev handle
++ * @file: File for misc dev handle (ignored)
++ * @buf: Buffer containing user data
++ * @count: Amount of data in @buf
++ * @ppos: Pointer to offset in file (ignored)
++ *
++ * miscdevfs packet format:
++ * Octet 0: Type
++ * Octets 1-4: network byte order msg_ctx->counter (0's for non-response)
++ * Octets 5-N0: Size of struct ecryptfs_message to follow
++ * Octets N0-N1: struct ecryptfs_message (including data)
++ *
++ * Returns the number of bytes read from @buf
++ */
++static ssize_t
++ecryptfs_miscdev_write(struct file *file, const char __user *buf,
++ size_t count, loff_t *ppos)
+{
++ u32 counter_nbo, seq;
++ size_t packet_size, packet_size_length, i;
++ ssize_t sz = 0;
++ char *data;
+ int rc;
-+ struct xencomm_desc *desc;
+
-+ if (is_phys_contiguous((unsigned long)ptr))
-+ return xencomm_create_inline(ptr);
++ if (count == 0)
++ goto out;
++ data = kmalloc(count, GFP_KERNEL);
++ if (!data) {
++ printk(KERN_ERR "%s: Out of memory whilst attempting to "
++ "kmalloc([%Zd], GFP_KERNEL)\n", __func__, count);
++ goto out;
++ }
++ rc = copy_from_user(data, buf, count);
++ if (rc) {
++ printk(KERN_ERR "%s: copy_from_user returned error [%d]\n",
++ __func__, rc);
++ goto out_free;
++ }
++ sz = count;
++ i = 0;
++ switch (data[i++]) {
++ case ECRYPTFS_MSG_RESPONSE:
++ if (count < (1 + 4 + 1 + sizeof(struct ecryptfs_message))) {
++ printk(KERN_WARNING "%s: Minimum acceptable packet "
++ "size is [%Zd], but amount of data written is "
++ "only [%Zd]. Discarding response packet.\n",
++ __func__,
++ (1 + 4 + 1 + sizeof(struct ecryptfs_message)),
++ count);
++ goto out_free;
++ }
++ memcpy((char *)&counter_nbo, &data[i], 4);
++ seq = be32_to_cpu(counter_nbo);
++ i += 4;
++ rc = ecryptfs_parse_packet_length(&data[i], &packet_size,
++ &packet_size_length);
++ if (rc) {
++ printk(KERN_WARNING "%s: Error parsing packet length; "
++ "rc = [%d]\n", __func__, rc);
++ goto out_free;
++ }
++ i += packet_size_length;
++ if ((1 + 4 + packet_size_length + packet_size) != count) {
++ printk(KERN_WARNING "%s: (1 + packet_size_length([%Zd])"
++ " + packet_size([%Zd]))([%Zd]) != "
++ "count([%Zd]). Invalid packet format.\n",
++ __func__, packet_size_length, packet_size,
++ (1 + packet_size_length + packet_size), count);
++ goto out_free;
++ }
++ rc = ecryptfs_miscdev_response(&data[i], packet_size,
++ current->euid,
++ current->nsproxy->user_ns,
++ task_pid(current), seq);
++ if (rc)
++ printk(KERN_WARNING "%s: Failed to deliver miscdev "
++ "response to requesting operation; rc = [%d]\n",
++ __func__, rc);
++ break;
++ case ECRYPTFS_MSG_HELO:
++ rc = ecryptfs_miscdev_helo(current->euid,
++ current->nsproxy->user_ns,
++ task_pid(current));
++ if (rc) {
++ printk(KERN_ERR "%s: Error attempting to process "
++ "helo from pid [0x%p]; rc = [%d]\n", __func__,
++ task_pid(current), rc);
++ goto out_free;
++ }
++ break;
++ case ECRYPTFS_MSG_QUIT:
++ rc = ecryptfs_miscdev_quit(current->euid,
++ current->nsproxy->user_ns,
++ task_pid(current));
++ if (rc) {
++ printk(KERN_ERR "%s: Error attempting to process "
++ "quit from pid [0x%p]; rc = [%d]\n", __func__,
++ task_pid(current), rc);
++ goto out_free;
++ }
++ break;
++ default:
++ ecryptfs_printk(KERN_WARNING, "Dropping miscdev "
++ "message of unrecognized type [%d]\n",
++ data[0]);
++ break;
++ }
++out_free:
++ kfree(data);
++out:
++ return sz;
++}
+
-+ rc = xencomm_create(ptr, bytes, &desc, GFP_KERNEL);
+
-+ if (rc || desc == NULL)
-+ return NULL;
++static const struct file_operations ecryptfs_miscdev_fops = {
++ .open = ecryptfs_miscdev_open,
++ .poll = ecryptfs_miscdev_poll,
++ .read = ecryptfs_miscdev_read,
++ .write = ecryptfs_miscdev_write,
++ .release = ecryptfs_miscdev_release,
++};
+
-+ return xencomm_pa(desc);
-+}
++static struct miscdevice ecryptfs_miscdev = {
++ .minor = MISC_DYNAMIC_MINOR,
++ .name = "ecryptfs",
++ .fops = &ecryptfs_miscdev_fops
++};
+
-+struct xencomm_handle *__xencomm_map_no_alloc(void *ptr, unsigned long bytes,
-+ struct xencomm_mini *xc_desc)
++/**
++ * ecryptfs_init_ecryptfs_miscdev
++ *
++ * Messages sent to the userspace daemon from the kernel are placed on
++ * a queue associated with the daemon. The next read against the
++ * miscdev handle by that daemon will return the oldest message placed
++ * on the message queue for the daemon.
++ *
++ * Returns zero on success; non-zero otherwise
++ */
++int ecryptfs_init_ecryptfs_miscdev(void)
+{
+ 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);
+
++ atomic_set(&ecryptfs_num_miscdev_opens, 0);
++ mutex_lock(&ecryptfs_daemon_hash_mux);
++ rc = misc_register(&ecryptfs_miscdev);
+ if (rc)
-+ return NULL;
-+
-+ return xencomm_pa(desc);
++ printk(KERN_ERR "%s: Failed to register miscellaneous device "
++ "for communications with userspace daemons; rc = [%d]\n",
++ __func__, rc);
++ mutex_unlock(&ecryptfs_daemon_hash_mux);
++ return rc;
+}
-diff --git a/fs/9p/fid.c b/fs/9p/fid.c
-index dfebdbe..3031e32 100644
---- a/fs/9p/fid.c
-+++ b/fs/9p/fid.c
-@@ -26,7 +26,6 @@
- #include <linux/fs.h>
- #include <linux/sched.h>
- #include <linux/idr.h>
--#include <asm/semaphore.h>
- #include <net/9p/9p.h>
- #include <net/9p/client.h>
++
++/**
++ * ecryptfs_destroy_ecryptfs_miscdev
++ *
++ * All of the daemons must be exorcised prior to calling this
++ * function.
++ */
++void ecryptfs_destroy_ecryptfs_miscdev(void)
++{
++ BUG_ON(atomic_read(&ecryptfs_num_miscdev_opens) != 0);
++ misc_deregister(&ecryptfs_miscdev);
++}
+diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
+index 6df1deb..2b6fe1e 100644
+--- a/fs/ecryptfs/mmap.c
++++ b/fs/ecryptfs/mmap.c
+@@ -153,7 +153,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
+ flush_dcache_page(page);
+ if (rc) {
+ printk(KERN_ERR "%s: Error reading xattr "
+- "region; rc = [%d]\n", __FUNCTION__, rc);
++ "region; rc = [%d]\n", __func__, rc);
+ goto out;
+ }
+ } else {
+@@ -169,7 +169,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to read "
+ "extent at offset [%lld] in the lower "
+- "file; rc = [%d]\n", __FUNCTION__,
++ "file; rc = [%d]\n", __func__,
+ lower_offset, rc);
+ goto out;
+ }
+@@ -212,7 +212,7 @@ static int ecryptfs_readpage(struct file *file, struct page *page)
+ "the encrypted content from the lower "
+ "file whilst inserting the metadata "
+ "from the xattr into the header; rc = "
+- "[%d]\n", __FUNCTION__, rc);
++ "[%d]\n", __func__, rc);
+ goto out;
+ }
-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)
+@@ -293,7 +293,7 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
+ if (rc) {
+ printk(KERN_ERR "%s: Error attemping to read "
+ "lower page segment; rc = [%d]\n",
+- __FUNCTION__, rc);
++ __func__, rc);
+ ClearPageUptodate(page);
+ goto out;
+ } else
+@@ -308,7 +308,7 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
+ "from the lower file whilst "
+ "inserting the metadata from "
+ "the xattr into the header; rc "
+- "= [%d]\n", __FUNCTION__, rc);
++ "= [%d]\n", __func__, rc);
+ ClearPageUptodate(page);
+ goto out;
+ }
+@@ -320,7 +320,7 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
+ if (rc) {
+ printk(KERN_ERR "%s: Error reading "
+ "page; rc = [%d]\n",
+- __FUNCTION__, rc);
++ __func__, rc);
+ ClearPageUptodate(page);
+ goto out;
+ }
+@@ -331,7 +331,7 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
+ if (rc) {
+ printk(KERN_ERR "%s: Error decrypting page "
+ "at index [%ld]; rc = [%d]\n",
+- __FUNCTION__, page->index, rc);
++ __func__, page->index, rc);
+ ClearPageUptodate(page);
+ goto out;
+ }
+@@ -348,7 +348,7 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
+ if (rc) {
+ printk(KERN_ERR "%s: Error on attempt to "
+ "truncate to (higher) offset [%lld];"
+- " rc = [%d]\n", __FUNCTION__,
++ " rc = [%d]\n", __func__,
+ prev_page_end_size, rc);
+ goto out;
+ }
+@@ -389,7 +389,7 @@ static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode)
+ kfree(file_size_virt);
+ if (rc)
+ printk(KERN_ERR "%s: Error writing file size to header; "
+- "rc = [%d]\n", __FUNCTION__, rc);
++ "rc = [%d]\n", __func__, rc);
+ out:
+ return rc;
}
-
- static void
--v9fs_umount_begin(struct vfsmount *vfsmnt, int flags)
-+v9fs_umount_begin(struct super_block *sb)
+diff --git a/fs/ecryptfs/netlink.c b/fs/ecryptfs/netlink.c
+index f638a69..e0abad6 100644
+--- a/fs/ecryptfs/netlink.c
++++ b/fs/ecryptfs/netlink.c
+@@ -44,8 +44,8 @@ static struct sock *ecryptfs_nl_sock;
+ * upon sending the message; non-zero upon error.
+ */
+ int ecryptfs_send_netlink(char *data, int data_len,
+- struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type,
+- u16 msg_flags, pid_t daemon_pid)
++ struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
++ u16 msg_flags, struct pid *daemon_pid)
{
-- struct v9fs_session_info *v9ses = vfsmnt->mnt_sb->s_fs_info;
-+ struct v9fs_session_info *v9ses = sb->s_fs_info;
-
-- if (flags & MNT_FORCE)
-- v9fs_session_cancel(v9ses);
-+ v9fs_session_cancel(v9ses);
- }
-
- static const struct super_operations v9fs_super_ops = {
-diff --git a/fs/Kconfig b/fs/Kconfig
-index c509123..2e43d46 100644
---- a/fs/Kconfig
-+++ b/fs/Kconfig
-@@ -411,7 +411,7 @@ config JFS_STATISTICS
- to be made available to the user in the /proc/fs/jfs/ directory.
-
- config FS_POSIX_ACL
--# Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs)
-+# Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs/nfs4)
- #
- # NOTE: you can implement Posix ACLs without these helpers (XFS does).
- # Never use this symbol for ifdefs.
-@@ -444,6 +444,32 @@ config OCFS2_FS
- For more information on OCFS2, see the file
- <file:Documentation/filesystems/ocfs2.txt>.
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+@@ -60,7 +60,7 @@ int ecryptfs_send_netlink(char *data, int data_len,
+ ecryptfs_printk(KERN_ERR, "Failed to allocate socket buffer\n");
+ goto out;
+ }
+- nlh = NLMSG_PUT(skb, daemon_pid, msg_ctx ? msg_ctx->counter : 0,
++ nlh = NLMSG_PUT(skb, pid_nr(daemon_pid), msg_ctx ? msg_ctx->counter : 0,
+ msg_type, payload_len);
+ nlh->nlmsg_flags = msg_flags;
+ if (msg_ctx && payload_len) {
+@@ -69,7 +69,7 @@ int ecryptfs_send_netlink(char *data, int data_len,
+ msg->data_len = data_len;
+ memcpy(msg->data, data, data_len);
+ }
+- rc = netlink_unicast(ecryptfs_nl_sock, skb, daemon_pid, 0);
++ rc = netlink_unicast(ecryptfs_nl_sock, skb, pid_nr(daemon_pid), 0);
+ if (rc < 0) {
+ ecryptfs_printk(KERN_ERR, "Failed to send eCryptfs netlink "
+ "message; rc = [%d]\n", rc);
+@@ -99,6 +99,7 @@ static int ecryptfs_process_nl_response(struct sk_buff *skb)
+ {
+ struct nlmsghdr *nlh = nlmsg_hdr(skb);
+ struct ecryptfs_message *msg = NLMSG_DATA(nlh);
++ struct pid *pid;
+ int rc;
-+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
+ if (skb->len - NLMSG_HDRLEN - sizeof(*msg) != msg->data_len) {
+@@ -107,8 +108,10 @@ static int ecryptfs_process_nl_response(struct sk_buff *skb)
+ "incorrectly specified data length\n");
+ goto out;
+ }
+- rc = ecryptfs_process_response(msg, NETLINK_CREDS(skb)->uid,
+- NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq);
++ pid = find_get_pid(NETLINK_CREDS(skb)->pid);
++ rc = ecryptfs_process_response(msg, NETLINK_CREDS(skb)->uid, NULL,
++ pid, nlh->nlmsg_seq);
++ put_pid(pid);
+ if (rc)
+ printk(KERN_ERR
+ "Error processing response message; rc = [%d]\n", rc);
+@@ -126,11 +129,13 @@ out:
+ */
+ static int ecryptfs_process_nl_helo(struct sk_buff *skb)
+ {
++ struct pid *pid;
+ int rc;
- 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
++ pid = find_get_pid(NETLINK_CREDS(skb)->pid);
+ rc = ecryptfs_process_helo(ECRYPTFS_TRANSPORT_NETLINK,
+- NETLINK_CREDS(skb)->uid,
+- NETLINK_CREDS(skb)->pid);
++ NETLINK_CREDS(skb)->uid, NULL, pid);
++ put_pid(pid);
+ if (rc)
+ printk(KERN_WARNING "Error processing HELO; rc = [%d]\n", rc);
+ return rc;
+@@ -147,10 +152,12 @@ static int ecryptfs_process_nl_helo(struct sk_buff *skb)
+ */
+ static int ecryptfs_process_nl_quit(struct sk_buff *skb)
+ {
++ struct pid *pid;
+ int rc;
- If unsure, say N.
+- rc = ecryptfs_process_quit(NETLINK_CREDS(skb)->uid,
+- NETLINK_CREDS(skb)->pid);
++ pid = find_get_pid(NETLINK_CREDS(skb)->pid);
++ rc = ecryptfs_process_quit(NETLINK_CREDS(skb)->uid, NULL, pid);
++ put_pid(pid);
+ if (rc)
+ printk(KERN_WARNING
+ "Error processing QUIT message; rc = [%d]\n", rc);
+@@ -176,20 +183,20 @@ static void ecryptfs_receive_nl_message(struct sk_buff *skb)
+ goto free;
+ }
+ switch (nlh->nlmsg_type) {
+- case ECRYPTFS_NLMSG_RESPONSE:
++ case ECRYPTFS_MSG_RESPONSE:
+ if (ecryptfs_process_nl_response(skb)) {
+ ecryptfs_printk(KERN_WARNING, "Failed to "
+ "deliver netlink response to "
+ "requesting operation\n");
+ }
+ break;
+- case ECRYPTFS_NLMSG_HELO:
++ case ECRYPTFS_MSG_HELO:
+ if (ecryptfs_process_nl_helo(skb)) {
+ ecryptfs_printk(KERN_WARNING, "Failed to "
+ "fulfill HELO request\n");
+ }
+ break;
+- case ECRYPTFS_NLMSG_QUIT:
++ case ECRYPTFS_MSG_QUIT:
+ if (ecryptfs_process_nl_quit(skb)) {
+ ecryptfs_printk(KERN_WARNING, "Failed to "
+ "fulfill QUIT request\n");
+diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
+index 0c49286..ebf5515 100644
+--- a/fs/ecryptfs/read_write.c
++++ b/fs/ecryptfs/read_write.c
+@@ -55,7 +55,7 @@ int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
+ set_fs(fs_save);
+ if (octets_written < 0) {
+ printk(KERN_ERR "%s: octets_written = [%td]; "
+- "expected [%td]\n", __FUNCTION__, octets_written, size);
++ "expected [%td]\n", __func__, octets_written, size);
+ rc = -EINVAL;
+ }
+ mutex_unlock(&inode_info->lower_file_mutex);
+@@ -153,7 +153,7 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
+ rc = PTR_ERR(ecryptfs_page);
+ printk(KERN_ERR "%s: Error getting page at "
+ "index [%ld] from eCryptfs inode "
+- "mapping; rc = [%d]\n", __FUNCTION__,
++ "mapping; rc = [%d]\n", __func__,
+ ecryptfs_page_idx, rc);
+ goto out;
+ }
+@@ -165,7 +165,7 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
+ if (rc) {
+ printk(KERN_ERR "%s: Error decrypting "
+ "page; rc = [%d]\n",
+- __FUNCTION__, rc);
++ __func__, rc);
+ ClearPageUptodate(ecryptfs_page);
+ page_cache_release(ecryptfs_page);
+ goto out;
+@@ -202,7 +202,7 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
+ page_cache_release(ecryptfs_page);
+ if (rc) {
+ printk(KERN_ERR "%s: Error encrypting "
+- "page; rc = [%d]\n", __FUNCTION__, rc);
++ "page; rc = [%d]\n", __func__, rc);
+ goto out;
+ }
+ pos += num_bytes;
+@@ -254,7 +254,7 @@ int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
+ set_fs(fs_save);
+ if (octets_read < 0) {
+ printk(KERN_ERR "%s: octets_read = [%td]; "
+- "expected [%td]\n", __FUNCTION__, octets_read, size);
++ "expected [%td]\n", __func__, octets_read, size);
+ rc = -EINVAL;
+ }
+ mutex_unlock(&inode_info->lower_file_mutex);
+@@ -327,7 +327,7 @@ int ecryptfs_read(char *data, loff_t offset, size_t size,
+ printk(KERN_ERR "%s: Attempt to read data past the end of the "
+ "file; offset = [%lld]; size = [%td]; "
+ "ecryptfs_file_size = [%lld]\n",
+- __FUNCTION__, offset, size, ecryptfs_file_size);
++ __func__, offset, size, ecryptfs_file_size);
+ goto out;
+ }
+ pos = offset;
+@@ -345,14 +345,14 @@ int ecryptfs_read(char *data, loff_t offset, size_t size,
+ rc = PTR_ERR(ecryptfs_page);
+ printk(KERN_ERR "%s: Error getting page at "
+ "index [%ld] from eCryptfs inode "
+- "mapping; rc = [%d]\n", __FUNCTION__,
++ "mapping; rc = [%d]\n", __func__,
+ ecryptfs_page_idx, rc);
+ goto out;
+ }
+ rc = ecryptfs_decrypt_page(ecryptfs_page);
+ if (rc) {
+ printk(KERN_ERR "%s: Error decrypting "
+- "page; rc = [%d]\n", __FUNCTION__, rc);
++ "page; rc = [%d]\n", __func__, rc);
+ ClearPageUptodate(ecryptfs_page);
+ page_cache_release(ecryptfs_page);
+ goto out;
+diff --git a/fs/eventpoll.c b/fs/eventpoll.c
+index a415f42..221086f 100644
+--- a/fs/eventpoll.c
++++ b/fs/eventpoll.c
+@@ -257,25 +257,6 @@ static inline int ep_cmp_ffd(struct epoll_filefd *p1,
+ (p1->file < p2->file ? -1 : p1->fd - p2->fd));
+ }
--config NFS_DIRECTIO
-- bool "Allow direct I/O on NFS files"
-- depends on NFS_FS
-- help
-- This option enables applications to perform uncached I/O on files
-- in NFS file systems using the O_DIRECT open() flag. When O_DIRECT
-- is set for a file, its data is not cached in the system's page
-- cache. Data is moved to and from user-level application buffers
-- directly. Unlike local disk-based file systems, NFS O_DIRECT has
-- no alignment restrictions.
--
-- Unless your program is designed to use O_DIRECT properly, you are
-- much better off allowing the NFS client to manage data caching for
-- you. Misusing O_DIRECT can cause poor server performance or network
-- storms. This kernel build option defaults OFF to avoid exposing
-- system administrators unwittingly to a potentially hazardous
-- feature.
--
-- For more details on NFS O_DIRECT, see fs/nfs/direct.c.
--
-- If unsure, say N. This reduces the size of the NFS client, and
-- causes open() to return EINVAL if a file residing in NFS is
-- opened with the O_DIRECT flag.
--
- config NFSD
- tristate "NFS server support"
- depends on INET
- select LOCKD
- select SUNRPC
- select EXPORTFS
-- select NFSD_V2_ACL if NFSD_V3_ACL
- select NFS_ACL_SUPPORT if NFSD_V2_ACL
-- select NFSD_TCP if NFSD_V4
-- select CRYPTO_MD5 if NFSD_V4
-- select CRYPTO if NFSD_V4
-- select FS_POSIX_ACL if NFSD_V4
-- select PROC_FS if NFSD_V4
-- select PROC_FS if SUNRPC_GSS
-- help
-- If you want your Linux box to act as an NFS *server*, so that other
-- computers on your local network which support NFS can access certain
-- directories on your box transparently, you have two options: you can
-- use the self-contained user space program nfsd, in which case you
-- should say N here, or you can say Y and use the kernel based NFS
-- server. The advantage of the kernel based solution is that it is
-- faster.
--
-- In either case, you will need support software; the respective
-- locations are given in the file <file:Documentation/Changes> in the
-- NFS section.
+-/* Special initialization for the RB tree node to detect linkage */
+-static inline void ep_rb_initnode(struct rb_node *n)
+-{
+- rb_set_parent(n, n);
+-}
-
-- 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.
+-/* Removes a node from the RB tree and marks it for a fast is-linked check */
+-static inline void ep_rb_erase(struct rb_node *n, struct rb_root *r)
+-{
+- rb_erase(n, r);
+- rb_set_parent(n, n);
+-}
-
-- Please read the NFS-HOWTO, available from
-- <http://www.tldp.org/docs.html#howto>.
+-/* Fast check to verify that the item is linked to the main RB tree */
+-static inline int ep_rb_linked(struct rb_node *n)
+-{
+- return rb_parent(n) != n;
+-}
-
-- 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.
+ /* Tells us if the item is currently linked */
+ static inline int ep_is_linked(struct list_head *p)
+ {
+@@ -283,13 +264,13 @@ static inline int ep_is_linked(struct list_head *p)
+ }
- 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.
+ /* Get the "struct epitem" from a wait queue pointer */
+-static inline struct epitem * ep_item_from_wait(wait_queue_t *p)
++static inline struct epitem *ep_item_from_wait(wait_queue_t *p)
+ {
+ return container_of(p, struct eppoll_entry, wait)->base;
+ }
- 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).
+ /* Get the "struct epitem" from an epoll queue wrapper */
+-static inline struct epitem * ep_item_from_epqueue(poll_table *p)
++static inline struct epitem *ep_item_from_epqueue(poll_table *p)
+ {
+ return container_of(p, struct ep_pqueue, pt)->epi;
+ }
+@@ -411,8 +392,7 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
+ list_del_init(&epi->fllink);
+ spin_unlock(&file->f_ep_lock);
--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.
+- if (ep_rb_linked(&epi->rbn))
+- ep_rb_erase(&epi->rbn, &ep->rbr);
++ rb_erase(&epi->rbn, &ep->rbr);
- 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.
+ spin_lock_irqsave(&ep->lock, flags);
+ if (ep_is_linked(&epi->rdllink))
+@@ -728,7 +708,6 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
+ goto error_return;
- 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.
+ /* Item initialization follow here ... */
+- ep_rb_initnode(&epi->rbn);
+ INIT_LIST_HEAD(&epi->rdllink);
+ INIT_LIST_HEAD(&epi->fllink);
+ INIT_LIST_HEAD(&epi->pwqlist);
+@@ -1262,7 +1241,7 @@ error_return:
+ return error;
+ }
- 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).
+-#ifdef TIF_RESTORE_SIGMASK
++#ifdef HAVE_SET_RESTORE_SIGMASK
-- 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.
+ /*
+ * Implement the event wait interface for the eventpoll file. It is the kernel
+@@ -1300,7 +1279,7 @@ asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events,
+ if (error == -EINTR) {
+ memcpy(¤t->saved_sigmask, &sigsaved,
+ sizeof(sigsaved));
+- set_thread_flag(TIF_RESTORE_SIGMASK);
++ set_restore_sigmask();
+ } else
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+ }
+@@ -1308,7 +1287,7 @@ asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events,
+ return error;
+ }
- If unsure, say N.
+-#endif /* #ifdef TIF_RESTORE_SIGMASK */
++#endif /* HAVE_SET_RESTORE_SIGMASK */
-@@ -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).
+ static int __init eventpoll_init(void)
+ {
+@@ -1330,4 +1309,3 @@ static int __init eventpoll_init(void)
+ return 0;
+ }
+ fs_initcall(eventpoll_init);
+-
+diff --git a/fs/exec.c b/fs/exec.c
+index 54a0a55..9f9f931 100644
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -735,6 +735,7 @@ static int exec_mmap(struct mm_struct *mm)
+ tsk->active_mm = mm;
+ activate_mm(active_mm, mm);
+ task_unlock(tsk);
++ mm_update_next_owner(mm);
+ arch_pick_mmap_layout(mm);
+ if (old_mm) {
+ up_read(&old_mm->mmap_sem);
+@@ -765,9 +766,7 @@ static int de_thread(struct task_struct *tsk)
-- 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/.
+ /*
+ * Kill all other threads in the thread group.
+- * We must hold tasklist_lock to call zap_other_threads.
+ */
+- read_lock(&tasklist_lock);
+ spin_lock_irq(lock);
+ if (signal_group_exit(sig)) {
+ /*
+@@ -775,21 +774,10 @@ static int de_thread(struct task_struct *tsk)
+ * return so that the signal is processed.
+ */
+ spin_unlock_irq(lock);
+- read_unlock(&tasklist_lock);
+ return -EAGAIN;
+ }
+-
+- /*
+- * child_reaper ignores SIGKILL, change it now.
+- * Reparenting needs write_lock on tasklist_lock,
+- * so it is safe to do it under read_lock.
+- */
+- if (unlikely(tsk->group_leader == task_child_reaper(tsk)))
+- task_active_pid_ns(tsk)->child_reaper = tsk;
+-
+ sig->group_exit_task = tsk;
+ zap_other_threads(tsk);
+- read_unlock(&tasklist_lock);
+
+ /* Account for the thread group leader hanging around: */
+ count = thread_group_leader(tsk) ? 1 : 2;
+@@ -810,7 +798,7 @@ static int de_thread(struct task_struct *tsk)
+ if (!thread_group_leader(tsk)) {
+ leader = tsk->group_leader;
- If unsure, say N.
+- sig->notify_count = -1;
++ sig->notify_count = -1; /* for exit_notify() */
+ for (;;) {
+ write_lock_irq(&tasklist_lock);
+ if (likely(leader->exit_state))
+@@ -820,6 +808,8 @@ static int de_thread(struct task_struct *tsk)
+ schedule();
+ }
-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;
++ if (unlikely(task_child_reaper(tsk) == leader))
++ task_active_pid_ns(tsk)->child_reaper = tsk;
+ /*
+ * The only record we have of the real-time age of a
+ * process, regardless of execs it's done, is start_time.
+@@ -953,7 +943,6 @@ int flush_old_exec(struct linux_binprm * bprm)
+ {
+ char * name;
+ int i, ch, retval;
- 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);
+ char tcomm[sizeof(current->comm)];
-@@ -728,12 +716,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+ /*
+@@ -964,27 +953,18 @@ int flush_old_exec(struct linux_binprm * bprm)
if (retval)
- goto out_free_dentry;
+ goto out;
-- /* 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;
+- /*
+- * 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;
++ set_mm_exe_file(bprm->mm, bprm->file);
++
+ /*
+ * Release all of the old mmap stuff
+ */
+ retval = exec_mmap(bprm->mm);
+ if (retval)
+- goto mmap_failed;
++ goto out;
- retval = -ENOEXEC;
- if (!enabled)
-@@ -133,21 +132,13 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+ bprm->mm = NULL; /* We're using it now */
- if (fmt->flags & MISC_FMT_OPEN_BINARY) {
+ /* This is the point of no return */
+- put_files_struct(files);
+-
+ current->sas_ss_sp = current->sas_ss_size = 0;
-- 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);
+ if (current->euid == current->uid && current->egid == current->gid)
+@@ -1034,8 +1014,6 @@ int flush_old_exec(struct linux_binprm * bprm)
-@@ -205,10 +196,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
- if (retval < 0)
- goto _error;
+ return 0;
-- if (files) {
-- put_files_struct(files);
-- files = NULL;
-- }
- _ret:
+-mmap_failed:
+- reset_files_struct(current, files);
+ out:
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;
}
+@@ -1282,13 +1260,17 @@ int do_execve(char * filename,
+ {
+ struct linux_binprm *bprm;
+ struct file *file;
+- unsigned long env_p;
++ struct files_struct *displaced;
+ int retval;
-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;
++ 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;
- /* 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;
- }
+ file = open_exec(filename);
+ retval = PTR_ERR(file);
+@@ -1330,11 +1312,9 @@ int do_execve(char * filename,
+ if (retval < 0)
+ goto out;
-- 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();
+- env_p = bprm->p;
+ retval = copy_strings(bprm->argc, argv, bprm);
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,
+ goto out;
+- bprm->argv_len = env_p - bprm->p;
- struct bio_map_data {
- struct bio_vec *iovecs;
-- void __user *userptr;
-+ int nr_sgvecs;
-+ struct sg_iovec *sgvecs;
- };
+ retval = search_binary_handler(bprm,regs);
+ if (retval >= 0) {
+@@ -1343,6 +1323,8 @@ int do_execve(char * filename,
+ security_bprm_free(bprm);
+ acct_update_integrals(current);
+ kfree(bprm);
++ if (displaced)
++ put_files_struct(displaced);
+ return retval;
+ }
--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;
- }
+@@ -1363,6 +1345,9 @@ out_file:
+ out_kfree:
+ kfree(bprm);
- static void bio_free_map_data(struct bio_map_data *bmd)
- {
- kfree(bmd->iovecs);
-+ kfree(bmd->sgvecs);
- kfree(bmd);
++out_files:
++ if (displaced)
++ reset_files_struct(displaced);
+ out_ret:
+ return retval;
}
+diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
+index 109ab5e..cc91227 100644
+--- a/fs/exportfs/expfs.c
++++ b/fs/exportfs/expfs.c
+@@ -150,12 +150,12 @@ reconnect_path(struct vfsmount *mnt, struct dentry *target_dir)
+ if (IS_ERR(ppd)) {
+ err = PTR_ERR(ppd);
+ dprintk("%s: get_parent of %ld failed, err %d\n",
+- __FUNCTION__, pd->d_inode->i_ino, err);
++ __func__, pd->d_inode->i_ino, err);
+ dput(pd);
+ break;
+ }
--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);
+- dprintk("%s: find name of %lu in %lu\n", __FUNCTION__,
++ dprintk("%s: find name of %lu in %lu\n", __func__,
+ pd->d_inode->i_ino, ppd->d_inode->i_ino);
+ err = exportfs_get_name(mnt, ppd, nbuf, pd);
+ if (err) {
+@@ -168,14 +168,14 @@ reconnect_path(struct vfsmount *mnt, struct dentry *target_dir)
+ continue;
+ break;
+ }
+- dprintk("%s: found name: %s\n", __FUNCTION__, nbuf);
++ dprintk("%s: found name: %s\n", __func__, nbuf);
+ mutex_lock(&ppd->d_inode->i_mutex);
+ npd = lookup_one_len(nbuf, ppd, strlen(nbuf));
+ mutex_unlock(&ppd->d_inode->i_mutex);
+ if (IS_ERR(npd)) {
+ err = PTR_ERR(npd);
+ dprintk("%s: lookup failed: %d\n",
+- __FUNCTION__, err);
++ __func__, err);
+ dput(ppd);
+ dput(pd);
+ break;
+@@ -188,7 +188,7 @@ reconnect_path(struct vfsmount *mnt, struct dentry *target_dir)
+ if (npd == pd)
+ noprogress = 0;
+ else
+- printk("%s: npd != pd\n", __FUNCTION__);
++ printk("%s: npd != pd\n", __func__);
+ dput(npd);
+ dput(ppd);
+ if (IS_ROOT(pd)) {
+diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
+index e7b2baf..10bb02c 100644
+--- a/fs/ext2/balloc.c
++++ b/fs/ext2/balloc.c
+@@ -106,7 +106,7 @@ static int ext2_valid_block_bitmap(struct super_block *sb,
+ return 1;
-@@ -467,13 +472,71 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs)
- return NULL;
+ err_out:
+- ext2_error(sb, __FUNCTION__,
++ ext2_error(sb, __func__,
+ "Invalid block bitmap - "
+ "block_group = %d, block = %lu",
+ block_group, bitmap_blk);
+@@ -132,7 +132,7 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
+ bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
+ bh = sb_getblk(sb, bitmap_blk);
+ if (unlikely(!bh)) {
+- ext2_error(sb, __FUNCTION__,
++ ext2_error(sb, __func__,
+ "Cannot read block bitmap - "
+ "block_group = %d, block_bitmap = %u",
+ block_group, le32_to_cpu(desc->bg_block_bitmap));
+@@ -143,17 +143,18 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
- 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;
+ if (bh_submit_read(bh) < 0) {
+ brelse(bh);
+- ext2_error(sb, __FUNCTION__,
++ ext2_error(sb, __func__,
+ "Cannot read block bitmap - "
+ "block_group = %d, block_bitmap = %u",
+ block_group, le32_to_cpu(desc->bg_block_bitmap));
+ return NULL;
+ }
+- if (!ext2_valid_block_bitmap(sb, desc, block_group, bh)) {
+- brelse(bh);
+- return NULL;
+- }
-+ kfree(bmd->iovecs);
- kfree(bmd);
- return NULL;
++ ext2_valid_block_bitmap(sb, desc, block_group, bh);
++ /*
++ * file system mounted not to panic on error, continue with corrupt
++ * bitmap
++ */
+ return bh;
}
-+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;
+@@ -245,11 +246,10 @@ restart:
+ prev = rsv;
+ }
+ printk("Window map complete.\n");
+- if (bad)
+- BUG();
++ BUG_ON(bad);
}
-
- /**
-- * 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;
+ #define rsv_window_dump(root, verbose) \
+- __rsv_window_dump((root), (verbose), __FUNCTION__)
++ __rsv_window_dump((root), (verbose), __func__)
+ #else
+ #define rsv_window_dump(root, verbose) do {} while (0)
+ #endif
+@@ -548,7 +548,7 @@ do_more:
+ for (i = 0, group_freed = 0; i < count; i++) {
+ if (!ext2_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
+ bit + i, bitmap_bh->b_data)) {
+- ext2_error(sb, __FUNCTION__,
++ ext2_error(sb, __func__,
+ "bit already cleared for block %lu", block + i);
+ } else {
+ group_freed++;
+@@ -1381,7 +1381,12 @@ allocated:
+ "Allocating block in system zone - "
+ "blocks from "E2FSBLK", length %lu",
+ ret_block, num);
+- goto out;
++ /*
++ * ext2_try_to_allocate marked the blocks we allocated as in
++ * use. So we may want to selectively mark some of the blocks
++ * as free
++ */
++ goto retry_alloc;
}
-- 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);
+ performed_allocation = 1;
+diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
+index 8dededd..a78c6b4 100644
+--- a/fs/ext2/dir.c
++++ b/fs/ext2/dir.c
+@@ -41,8 +41,8 @@ static inline __le16 ext2_rec_len_to_disk(unsigned len)
+ {
+ if (len == (1 << 16))
+ return cpu_to_le16(EXT2_MAX_REC_LEN);
+- else if (len > (1 << 16))
+- BUG();
++ else
++ BUG_ON(len > (1 << 16));
+ return cpu_to_le16(len);
}
-+/**
-+ * 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.
+@@ -295,11 +295,11 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
+ struct page *page = ext2_get_page(inode, n);
- 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.
-+
+ if (IS_ERR(page)) {
+- ext2_error(sb, __FUNCTION__,
++ ext2_error(sb, __func__,
+ "bad page in #%lu",
+ inode->i_ino);
+ filp->f_pos += PAGE_CACHE_SIZE - offset;
+- return -EIO;
++ return PTR_ERR(page);
+ }
+ kaddr = page_address(page);
+ if (unlikely(need_revalidate)) {
+@@ -314,7 +314,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
+ limit = kaddr + ext2_last_byte(inode, n) - EXT2_DIR_REC_LEN(1);
+ for ( ;(char*)de <= limit; de = ext2_next_entry(de)) {
+ if (de->rec_len == 0) {
+- ext2_error(sb, __FUNCTION__,
++ ext2_error(sb, __func__,
+ "zero-length directory entry");
+ ext2_put_page(page);
+ return -EIO;
+@@ -381,7 +381,7 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
+ kaddr += ext2_last_byte(dir, n) - reclen;
+ while ((char *) de <= kaddr) {
+ if (de->rec_len == 0) {
+- ext2_error(dir->i_sb, __FUNCTION__,
++ ext2_error(dir->i_sb, __func__,
+ "zero-length directory entry");
+ ext2_put_page(page);
+ goto out;
+@@ -396,7 +396,7 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
+ n = 0;
+ /* next page is past the blocks we've got */
+ if (unlikely(n > (dir->i_blocks >> (PAGE_CACHE_SHIFT - 9)))) {
+- ext2_error(dir->i_sb, __FUNCTION__,
++ ext2_error(dir->i_sb, __func__,
+ "dir %lu size %lld exceeds block count %llu",
+ dir->i_ino, dir->i_size,
+ (unsigned long long)dir->i_blocks);
+@@ -506,7 +506,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode)
+ goto got_it;
+ }
+ if (de->rec_len == 0) {
+- ext2_error(dir->i_sb, __FUNCTION__,
++ ext2_error(dir->i_sb, __func__,
+ "zero-length directory entry");
+ err = -EIO;
+ goto out_unlock;
+@@ -578,7 +578,7 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page )
- For questions or bug reports please contact:
- sfrench at samba.org (sfrench at us.ibm.com)
-diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
-index 56c9240..95024c0 100644
---- a/fs/cifs/cifs_dfs_ref.c
-+++ b/fs/cifs/cifs_dfs_ref.c
-@@ -23,16 +23,28 @@
- #include "dns_resolve.h"
- #include "cifs_debug.h"
+ while ((char*)de < (char*)dir) {
+ if (de->rec_len == 0) {
+- ext2_error(inode->i_sb, __FUNCTION__,
++ ext2_error(inode->i_sb, __func__,
+ "zero-length directory entry");
+ err = -EIO;
+ goto out;
+@@ -670,7 +670,7 @@ int ext2_empty_dir (struct inode * inode)
--LIST_HEAD(cifs_dfs_automount_list);
-+static LIST_HEAD(cifs_dfs_automount_list);
+ while ((char *)de <= kaddr) {
+ if (de->rec_len == 0) {
+- ext2_error(inode->i_sb, __FUNCTION__,
++ ext2_error(inode->i_sb, __func__,
+ "zero-length directory entry");
+ printk("kaddr=%p, de=%p\n", kaddr, de);
+ goto not_empty;
+diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
+index 5deb8b7..f597413 100644
+--- a/fs/ext2/ialloc.c
++++ b/fs/ext2/ialloc.c
+@@ -75,11 +75,9 @@ static void ext2_release_inode(struct super_block *sb, int group, int dir)
+ }
--/*
-- * 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);
-+}
+ spin_lock(sb_bgl_lock(EXT2_SB(sb), group));
+- desc->bg_free_inodes_count =
+- cpu_to_le16(le16_to_cpu(desc->bg_free_inodes_count) + 1);
++ le16_add_cpu(&desc->bg_free_inodes_count, 1);
+ if (dir)
+- desc->bg_used_dirs_count =
+- cpu_to_le16(le16_to_cpu(desc->bg_used_dirs_count) - 1);
++ le16_add_cpu(&desc->bg_used_dirs_count, -1);
+ spin_unlock(sb_bgl_lock(EXT2_SB(sb), group));
+ if (dir)
+ percpu_counter_dec(&EXT2_SB(sb)->s_dirs_counter);
+@@ -253,7 +251,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).
+@@ -539,13 +537,11 @@ got:
+ percpu_counter_inc(&sbi->s_dirs_counter);
--void dfs_shrink_umount_helper(struct vfsmount *vfsmnt)
-+void cifs_dfs_release_automount_timer(void)
+ spin_lock(sb_bgl_lock(sbi, group));
+- gdp->bg_free_inodes_count =
+- cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
++ le16_add_cpu(&gdp->bg_free_inodes_count, -1);
+ if (S_ISDIR(mode)) {
+ if (sbi->s_debts[group] < 255)
+ sbi->s_debts[group]++;
+- gdp->bg_used_dirs_count =
+- cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1);
++ le16_add_cpu(&gdp->bg_used_dirs_count, 1);
+ } else {
+ if (sbi->s_debts[group])
+ sbi->s_debts[group]--;
+diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
+index c620068..384fc0d 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.
+@@ -254,13 +254,13 @@ no_block:
+ * Caller must make sure that @ind is valid and will stay that way.
+ */
+
+-static unsigned long ext2_find_near(struct inode *inode, Indirect *ind)
++static ext2_fsblk_t ext2_find_near(struct inode *inode, Indirect *ind)
{
-- 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();
+ struct ext2_inode_info *ei = EXT2_I(inode);
+ __le32 *start = ind->bh ? (__le32 *) ind->bh->b_data : ei->i_data;
+ __le32 *p;
+- unsigned long bg_start;
+- unsigned long colour;
++ ext2_fsblk_t bg_start;
++ ext2_fsblk_t colour;
+
+ /* Try to find previous block */
+ for (p = ind->p - 1; p >= start; p--)
+@@ -275,15 +275,14 @@ static unsigned long ext2_find_near(struct inode *inode, Indirect *ind)
+ * It is going to be refered from inode itself? OK, just put it into
+ * the same cylinder group then.
+ */
+- bg_start = (ei->i_block_group * EXT2_BLOCKS_PER_GROUP(inode->i_sb)) +
+- le32_to_cpu(EXT2_SB(inode->i_sb)->s_es->s_first_data_block);
++ bg_start = ext2_group_first_block_no(inode->i_sb, ei->i_block_group);
+ colour = (current->pid % 16) *
+ (EXT2_BLOCKS_PER_GROUP(inode->i_sb) / 16);
+ return bg_start + colour;
}
/**
-@@ -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,
+- * 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
+@@ -291,8 +290,8 @@ static unsigned long ext2_find_near(struct inode *inode, Indirect *ind)
+ * Returns preferred place for a block (the goal).
+ */
- /* 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)
+-static inline int ext2_find_goal(struct inode *inode, long block,
+- Indirect *partial)
++static inline ext2_fsblk_t ext2_find_goal(struct inode *inode, long block,
++ Indirect *partial)
{
- 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 */
+ struct ext2_block_alloc_info *block_i;
- cFYI(DBG2, ("set ACL from mode for %s", path));
+@@ -796,7 +795,7 @@ const struct address_space_operations ext2_aops = {
- /* Get the security descriptor */
-- pntsd = get_cifs_acl(&acllen, inode, path, NULL);
-+ pntsd = get_cifs_acl(&secdesclen, inode, path, NULL);
+ const struct address_space_operations ext2_aops_xip = {
+ .bmap = ext2_bmap,
+- .get_xip_page = ext2_get_xip_page,
++ .get_xip_mem = ext2_get_xip_mem,
+ };
- /* 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 */
+ const struct address_space_operations ext2_nobh_aops = {
+diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
+index b8ea11f..de876fa 100644
+--- a/fs/ext2/ioctl.c
++++ b/fs/ext2/ioctl.c
+@@ -12,6 +12,7 @@
+ #include <linux/time.h>
+ #include <linux/sched.h>
+ #include <linux/compat.h>
++#include <linux/mount.h>
+ #include <linux/smp_lock.h>
+ #include <asm/current.h>
+ #include <asm/uaccess.h>
+@@ -23,6 +24,7 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ struct ext2_inode_info *ei = EXT2_I(inode);
+ unsigned int flags;
+ unsigned short rsv_window_size;
++ int ret;
-- 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);
- }
+ ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg);
-- rc = build_sec_desc(pntsd, pnntsd, acllen, inode, nmode);
-+ rc = build_sec_desc(pntsd, pnntsd, inode, nmode);
+@@ -34,14 +36,19 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ case EXT2_IOC_SETFLAGS: {
+ unsigned int oldflags;
- cFYI(DBG2, ("build_sec_desc rc: %d", rc));
+- if (IS_RDONLY(inode))
+- return -EROFS;
++ ret = mnt_want_write(filp->f_path.mnt);
++ if (ret)
++ return ret;
- 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));
+- 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;
-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 */
+@@ -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;
+ }
+ }
- #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
+@@ -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;
--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;
+@@ -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/ext2/super.c b/fs/ext2/super.c
+index 088b011..ef50cbc 100644
+--- a/fs/ext2/super.c
++++ b/fs/ext2/super.c
+@@ -51,8 +51,7 @@ void ext2_error (struct super_block * sb, const char * function,
-- dfs_shrink_umount_helper(vfsmnt);
--
-- if (!(flags & MNT_FORCE))
-- return;
-- cifs_sb = CIFS_SB(vfsmnt->mnt_sb);
- if (cifs_sb == NULL)
+ if (!(sb->s_flags & MS_RDONLY)) {
+ sbi->s_mount_state |= EXT2_ERROR_FS;
+- es->s_state =
+- cpu_to_le16(le16_to_cpu(es->s_state) | EXT2_ERROR_FS);
++ es->s_state |= cpu_to_le16(EXT2_ERROR_FS);
+ ext2_sync_super(sb, es);
+ }
+
+@@ -90,7 +89,7 @@ void ext2_update_dynamic_rev(struct super_block *sb)
+ if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV)
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 *);
+- ext2_warning(sb, __FUNCTION__,
++ ext2_warning(sb, __func__,
+ "updating to rev %d because of new feature flag, "
+ "running e2fsck is recommended",
+ EXT2_DYNAMIC_REV);
+@@ -604,7 +603,7 @@ static int ext2_setup_super (struct super_block * sb,
+ "running e2fsck is recommended\n");
+ if (!le16_to_cpu(es->s_max_mnt_count))
+ es->s_max_mnt_count = cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT);
+- es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);
++ le16_add_cpu(&es->s_mnt_count, 1);
+ ext2_write_super(sb);
+ if (test_opt (sb, DEBUG))
+ printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, "
+@@ -622,13 +621,13 @@ static int ext2_check_descriptors(struct super_block *sb)
+ {
+ int i;
+ struct ext2_sb_info *sbi = EXT2_SB(sb);
+- unsigned long first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
+- unsigned long last_block;
+
+ ext2_debug ("Checking group descriptors");
+
+ for (i = 0; i < sbi->s_groups_count; i++) {
+ struct ext2_group_desc *gdp = ext2_get_group_desc(sb, i, NULL);
++ ext2_fsblk_t first_block = ext2_group_first_block_no(sb, i);
++ ext2_fsblk_t last_block;
+
+ if (i == sbi->s_groups_count - 1)
+ last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1;
+@@ -664,7 +663,6 @@ static int ext2_check_descriptors(struct super_block *sb)
+ i, (unsigned long) le32_to_cpu(gdp->bg_inode_table));
+ return 0;
+ }
+- first_block += EXT2_BLOCKS_PER_GROUP(sb);
+ }
+ return 1;
+ }
+@@ -721,10 +719,9 @@ static unsigned long descriptor_loc(struct super_block *sb,
+ int nr)
+ {
+ struct ext2_sb_info *sbi = EXT2_SB(sb);
+- unsigned long bg, first_data_block, first_meta_bg;
++ unsigned long bg, first_meta_bg;
+ int has_super = 0;
+
+- first_data_block = le32_to_cpu(sbi->s_es->s_first_data_block);
+ first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg);
- 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;
+ if (!EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_META_BG) ||
+@@ -733,7 +730,8 @@ static unsigned long descriptor_loc(struct super_block *sb,
+ bg = sbi->s_desc_per_block * nr;
+ if (ext2_bg_has_super(sb, bg))
+ has_super = 1;
+- return (first_data_block + has_super + (bg * sbi->s_blocks_per_group));
++
++ return ext2_group_first_block_no(sb, bg) + has_super;
+ }
+
+ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
+@@ -1062,7 +1060,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
+ goto failed_mount3;
+ }
+ if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL))
+- ext2_warning(sb, __FUNCTION__,
++ ext2_warning(sb, __func__,
+ "mounting ext3 filesystem as ext2");
+ ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY);
+ return 0;
+@@ -1126,10 +1124,9 @@ void ext2_write_super (struct super_block * sb)
+ if (!(sb->s_flags & MS_RDONLY)) {
+ es = EXT2_SB(sb)->s_es;
+- if (le16_to_cpu(es->s_state) & EXT2_VALID_FS) {
++ if (es->s_state & cpu_to_le16(EXT2_VALID_FS)) {
+ ext2_debug ("setting valid to 0\n");
+- es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) &
+- ~EXT2_VALID_FS);
++ es->s_state &= cpu_to_le16(~EXT2_VALID_FS);
+ es->s_free_blocks_count = cpu_to_le32(ext2_count_free_blocks(sb));
+ es->s_free_inodes_count = cpu_to_le32(ext2_count_free_inodes(sb));
+ es->s_mtime = cpu_to_le32(get_seconds());
+@@ -1180,7 +1177,7 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
+ if (((sbi->s_mount_opt & EXT2_MOUNT_XIP) !=
+ (old_mount_opt & EXT2_MOUNT_XIP)) &&
+ invalidate_inodes(sb))
+- ext2_warning(sb, __FUNCTION__, "busy inodes while remounting "\
++ ext2_warning(sb, __func__, "busy inodes while remounting "\
+ "xip remain in cache (no functional problem)");
+ if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
+ return 0;
+diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
+index a99d46f..987a526 100644
+--- a/fs/ext2/xattr.c
++++ b/fs/ext2/xattr.c
+@@ -646,8 +646,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
+ unlock_buffer(new_bh);
+ goto cleanup;
+ }
+- HDR(new_bh)->h_refcount = cpu_to_le32(1 +
+- le32_to_cpu(HDR(new_bh)->h_refcount));
++ le32_add_cpu(&HDR(new_bh)->h_refcount, 1);
+ ea_bdebug(new_bh, "refcount now=%d",
+ le32_to_cpu(HDR(new_bh)->h_refcount));
+ }
+@@ -660,10 +659,8 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
+ ext2_xattr_cache_insert(new_bh);
+ } else {
+ /* We need to allocate a new block */
+- int goal = le32_to_cpu(EXT2_SB(sb)->s_es->
+- s_first_data_block) +
+- EXT2_I(inode)->i_block_group *
+- EXT2_BLOCKS_PER_GROUP(sb);
++ ext2_fsblk_t goal = ext2_group_first_block_no(sb,
++ EXT2_I(inode)->i_block_group);
+ int block = ext2_new_block(inode, goal, &error);
+ if (error)
+ goto cleanup;
+@@ -731,8 +728,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
+ bforget(old_bh);
+ } else {
+ /* Decrement the refcount only. */
+- HDR(old_bh)->h_refcount = cpu_to_le32(
+- le32_to_cpu(HDR(old_bh)->h_refcount) - 1);
++ le32_add_cpu(&HDR(old_bh)->h_refcount, -1);
+ if (ce)
+ mb_cache_entry_release(ce);
+ DQUOT_FREE_BLOCK(inode, 1);
+@@ -789,8 +785,7 @@ ext2_xattr_delete_inode(struct inode *inode)
+ bforget(bh);
+ unlock_buffer(bh);
+ } else {
+- HDR(bh)->h_refcount = cpu_to_le32(
+- le32_to_cpu(HDR(bh)->h_refcount) - 1);
++ le32_add_cpu(&HDR(bh)->h_refcount, -1);
+ if (ce)
+ mb_cache_entry_release(ce);
+ ea_bdebug(bh, "refcount now=%d",
+diff --git a/fs/ext2/xip.c b/fs/ext2/xip.c
+index ca7f003..4fb94c2 100644
+--- a/fs/ext2/xip.c
++++ b/fs/ext2/xip.c
+@@ -15,24 +15,28 @@
+ #include "xip.h"
--
- /* Functions related to files and directories */
- extern const struct file_operations cifs_file_ops;
- extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */
-diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
-index 47f7950..9f49c2f 100644
---- a/fs/cifs/cifspdu.h
-+++ b/fs/cifs/cifspdu.h
-@@ -1,7 +1,7 @@
- /*
- * fs/cifs/cifspdu.h
- *
-- * Copyright (c) International Business Machines Corp., 2002,2007
-+ * Copyright (c) International Business Machines Corp., 2002,2008
- * Author(s): Steve French (sfrench at us.ibm.com)
- *
- * This library is free software; you can redistribute it and/or modify
-@@ -163,7 +163,10 @@
- path names in response */
- #define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
- #define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
-+#define SMBFLG2_COMPRESSED (8)
-+#define SMBFLG2_SECURITY_SIGNATURE_REQUIRED (0x10)
- #define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
-+#define SMBFLG2_REPARSE_PATH (0x400)
- #define SMBFLG2_EXT_SEC cpu_to_le16(0x800)
- #define SMBFLG2_DFS cpu_to_le16(0x1000)
- #define SMBFLG2_PAGING_IO cpu_to_le16(0x2000)
-@@ -305,7 +308,7 @@
- #define FILE_SHARE_DELETE 0x00000004
- #define FILE_SHARE_ALL 0x00000007
+ static inline int
+-__inode_direct_access(struct inode *inode, sector_t sector,
+- unsigned long *data)
++__inode_direct_access(struct inode *inode, sector_t block,
++ void **kaddr, unsigned long *pfn)
+ {
+- BUG_ON(!inode->i_sb->s_bdev->bd_disk->fops->direct_access);
+- return inode->i_sb->s_bdev->bd_disk->fops
+- ->direct_access(inode->i_sb->s_bdev,sector,data);
++ struct block_device *bdev = inode->i_sb->s_bdev;
++ struct block_device_operations *ops = bdev->bd_disk->fops;
++ sector_t sector;
++
++ sector = block * (PAGE_SIZE / 512); /* ext2 block to bdev sector */
++
++ BUG_ON(!ops->direct_access);
++ return ops->direct_access(bdev, sector, kaddr, pfn);
+ }
--/* 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 */
+ static inline int
+-__ext2_get_sector(struct inode *inode, sector_t offset, int create,
++__ext2_get_block(struct inode *inode, pgoff_t pgoff, int create,
+ sector_t *result)
+ {
+ struct buffer_head tmp;
+ int rc;
-@@ -470,7 +483,7 @@ typedef struct lanman_neg_rsp {
+ memset(&tmp, 0, sizeof(struct buffer_head));
+- rc = ext2_get_block(inode, offset/ (PAGE_SIZE/512), &tmp,
+- create);
++ rc = ext2_get_block(inode, pgoff, &tmp, create);
+ *result = tmp.b_blocknr;
- 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
+ /* did we get a sparse block (hole in the file)? */
+@@ -45,15 +49,15 @@ __ext2_get_sector(struct inode *inode, sector_t offset, int create,
+ }
- typedef union smb_com_session_setup_andx {
-@@ -668,9 +682,7 @@ typedef struct smb_com_tconx_req {
- } __attribute__((packed)) TCONX_REQ;
+ int
+-ext2_clear_xip_target(struct inode *inode, int block)
++ext2_clear_xip_target(struct inode *inode, sector_t block)
+ {
+- sector_t sector = block * (PAGE_SIZE/512);
+- unsigned long data;
++ void *kaddr;
++ unsigned long pfn;
+ int rc;
- 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;
+- rc = __inode_direct_access(inode, sector, &data);
++ rc = __inode_direct_access(inode, block, &kaddr, &pfn);
+ if (!rc)
+- clear_page((void*)data);
++ clear_page(kaddr);
+ return rc;
+ }
-+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
-+ *
-+ */
+@@ -64,30 +68,23 @@ void ext2_xip_verify_sb(struct super_block *sb)
+ if ((sbi->s_mount_opt & EXT2_MOUNT_XIP) &&
+ !sb->s_bdev->bd_disk->fops->direct_access) {
+ sbi->s_mount_opt &= (~EXT2_MOUNT_XIP);
+- ext2_warning(sb, __FUNCTION__,
++ ext2_warning(sb, __func__,
+ "ignoring xip option - not supported by bdev");
+ }
+ }
- 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
+-struct page *
+-ext2_get_xip_page(struct address_space *mapping, sector_t offset,
+- int create)
++int ext2_get_xip_mem(struct address_space *mapping, pgoff_t pgoff, int create,
++ void **kmem, unsigned long *pfn)
+ {
+ int rc;
+- unsigned long data;
+- sector_t sector;
++ sector_t block;
-+/* 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;
+ /* first, retrieve the sector number */
+- rc = __ext2_get_sector(mapping->host, offset, create, §or);
++ rc = __ext2_get_block(mapping->host, pgoff, create, &block);
+ if (rc)
+- goto error;
++ return rc;
-+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
+ /* retrieve address of the target data */
+- rc = __inode_direct_access
+- (mapping->host, sector * (PAGE_SIZE/512), &data);
+- if (!rc)
+- return virt_to_page(data);
-
-+#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);
+- error:
+- return ERR_PTR(rc);
++ rc = __inode_direct_access(mapping->host, block, kmem, pfn);
++ return rc;
+ }
+diff --git a/fs/ext2/xip.h b/fs/ext2/xip.h
+index aa85331..18b34d2 100644
+--- a/fs/ext2/xip.h
++++ b/fs/ext2/xip.h
+@@ -7,19 +7,20 @@
+
+ #ifdef CONFIG_EXT2_FS_XIP
+ extern void ext2_xip_verify_sb (struct super_block *);
+-extern int ext2_clear_xip_target (struct inode *, int);
++extern int ext2_clear_xip_target (struct inode *, sector_t);
+
+ static inline int ext2_use_xip (struct super_block *sb)
+ {
+ struct ext2_sb_info *sbi = EXT2_SB(sb);
+ return (sbi->s_mount_opt & EXT2_MOUNT_XIP);
+ }
+-struct page* ext2_get_xip_page (struct address_space *, sector_t, int);
+-#define mapping_is_xip(map) unlikely(map->a_ops->get_xip_page)
++int ext2_get_xip_mem(struct address_space *, pgoff_t, int,
++ void **, unsigned long *);
++#define mapping_is_xip(map) unlikely(map->a_ops->get_xip_mem)
+ #else
+ #define mapping_is_xip(map) 0
+ #define ext2_xip_verify_sb(sb) do { } while (0)
+ #define ext2_use_xip(sb) 0
+ #define ext2_clear_xip_target(inode, chain) 0
+-#define ext2_get_xip_page NULL
++#define ext2_get_xip_mem NULL
+ #endif
+diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
+index da0cb2c..92fd033 100644
+--- a/fs/ext3/balloc.c
++++ b/fs/ext3/balloc.c
+@@ -117,7 +117,7 @@ static int ext3_valid_block_bitmap(struct super_block *sb,
+ return 1;
-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 */);
-+ }
+ err_out:
+- ext3_error(sb, __FUNCTION__,
++ ext3_error(sb, __func__,
+ "Invalid block bitmap - "
+ "block_group = %d, block = %lu",
+ block_group, bitmap_blk);
+@@ -147,7 +147,7 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
+ bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
+ bh = sb_getblk(sb, bitmap_blk);
+ if (unlikely(!bh)) {
+- ext3_error(sb, __FUNCTION__,
++ ext3_error(sb, __func__,
+ "Cannot read block bitmap - "
+ "block_group = %d, block_bitmap = %u",
+ block_group, le32_to_cpu(desc->bg_block_bitmap));
+@@ -158,16 +158,17 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
- 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 */);
-+ }
+ if (bh_submit_read(bh) < 0) {
+ brelse(bh);
+- ext3_error(sb, __FUNCTION__,
++ ext3_error(sb, __func__,
+ "Cannot read block bitmap - "
+ "block_group = %d, block_bitmap = %u",
+ block_group, le32_to_cpu(desc->bg_block_bitmap));
+ return NULL;
+ }
+- if (!ext3_valid_block_bitmap(sb, desc, block_group, bh)) {
+- brelse(bh);
+- return NULL;
+- }
++ ext3_valid_block_bitmap(sb, desc, block_group, bh);
++ /*
++ * file system mounted not to panic on error, continue with corrupt
++ * bitmap
++ */
+ return bh;
+ }
+ /*
+@@ -232,11 +233,10 @@ restart:
+ prev = rsv;
+ }
+ printk("Window map complete.\n");
+- if (bad)
+- BUG();
++ BUG_ON(bad);
+ }
+ #define rsv_window_dump(root, verbose) \
+- __rsv_window_dump((root), (verbose), __FUNCTION__)
++ __rsv_window_dump((root), (verbose), __func__)
+ #else
+ #define rsv_window_dump(root, verbose) do {} while (0)
+ #endif
+@@ -618,7 +618,7 @@ do_more:
+ if (!ext3_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
+ bit + i, bitmap_bh->b_data)) {
+ jbd_unlock_bh_state(bitmap_bh);
+- ext3_error(sb, __FUNCTION__,
++ ext3_error(sb, __func__,
+ "bit already cleared for block "E3FSBLK,
+ block + i);
+ jbd_lock_bh_state(bitmap_bh);
+@@ -1642,7 +1642,11 @@ allocated:
+ "Allocating block in system zone - "
+ "blocks from "E3FSBLK", length %lu",
+ ret_block, num);
+- goto out;
++ /*
++ * claim_block() marked the blocks we allocated as in use. So we
++ * may want to selectively mark some of the blocks as free.
++ */
++ goto retry_alloc;
+ }
- 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;
+ performed_allocation = 1;
+@@ -1668,7 +1672,7 @@ allocated:
+ if (ext3_test_bit(grp_alloc_blk+i,
+ bh2jh(bitmap_bh)->b_committed_data)) {
+ printk("%s: block was unexpectedly set in "
+- "b_committed_data\n", __FUNCTION__);
++ "b_committed_data\n", __func__);
+ }
}
-+ 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);
+ }
+diff --git a/fs/ext3/ext3_jbd.c b/fs/ext3/ext3_jbd.c
+index e1f91fd..d401f14 100644
+--- a/fs/ext3/ext3_jbd.c
++++ b/fs/ext3/ext3_jbd.c
+@@ -9,7 +9,7 @@ int __ext3_journal_get_undo_access(const char *where, handle_t *handle,
+ {
+ int err = journal_get_undo_access(handle, bh);
+ if (err)
+- ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
++ ext3_journal_abort_handle(where, __func__, bh, handle,err);
+ return err;
}
--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)
+@@ -18,7 +18,7 @@ int __ext3_journal_get_write_access(const char *where, handle_t *handle,
{
- 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));
+ int err = journal_get_write_access(handle, bh);
+ if (err)
+- ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
++ ext3_journal_abort_handle(where, __func__, bh, handle,err);
+ return err;
+ }
-- full_path = cifs_get_search_path(pTcon, search_path);
-+ full_path = cifs_get_search_path(cifs_sb, search_path);
+@@ -27,7 +27,7 @@ int __ext3_journal_forget(const char *where, handle_t *handle,
+ {
+ int err = journal_forget(handle, bh);
+ if (err)
+- ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
++ ext3_journal_abort_handle(where, __func__, bh, handle,err);
+ return err;
+ }
- 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;
+@@ -36,7 +36,7 @@ int __ext3_journal_revoke(const char *where, handle_t *handle,
+ {
+ int err = journal_revoke(handle, blocknr, bh);
+ if (err)
+- ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
++ ext3_journal_abort_handle(where, __func__, bh, handle,err);
+ return err;
+ }
-- full_path = cifs_get_search_path(pTcon, search_path);
-+ full_path = cifs_get_search_path(cifs_sb, search_path);
+@@ -45,7 +45,7 @@ int __ext3_journal_get_create_access(const char *where,
+ {
+ int err = journal_get_create_access(handle, bh);
+ if (err)
+- ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
++ ext3_journal_abort_handle(where, __func__, bh, handle,err);
+ return err;
+ }
- 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);
+@@ -54,6 +54,6 @@ int __ext3_journal_dirty_metadata(const char *where,
+ {
+ int err = journal_dirty_metadata(handle, bh);
+ if (err)
+- ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
++ ext3_journal_abort_handle(where, __func__, bh, handle,err);
+ return err;
}
+diff --git a/fs/ext3/fsync.c b/fs/ext3/fsync.c
+index a588e23..d336341 100644
+--- a/fs/ext3/fsync.c
++++ b/fs/ext3/fsync.c
+@@ -72,6 +72,9 @@ int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync)
+ goto out;
+ }
++ if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
++ goto out;
+
-+void DeleteTconOplockQEntries(struct cifsTconInfo *tcon)
-+{
-+ struct oplock_q_entry *temp;
-+
-+ if (tcon == NULL)
-+ return;
-+
-+ spin_lock(&GlobalMid_Lock);
-+ list_for_each_entry(temp, &GlobalOplock_Q, qhead) {
-+ if ((temp->tcon) && (temp->tcon == tcon)) {
-+ list_del(&temp->qhead);
-+ kmem_cache_free(cifs_oplock_cachep, temp);
-+ }
-+ }
-+ spin_unlock(&GlobalMid_Lock);
-+}
-+
- int
- smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
- unsigned int smb_buf_length, struct sockaddr *sin)
-diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
-index 350680f..0c3b618 100644
---- a/fs/cramfs/inode.c
-+++ b/fs/cramfs/inode.c
-@@ -23,7 +23,6 @@
- #include <linux/buffer_head.h>
- #include <linux/vfs.h>
- #include <linux/mutex.h>
--#include <asm/semaphore.h>
-
- #include <asm/uaccess.h>
+ /*
+ * The VFS has written the file data. If the inode is unaltered
+ * then we need not start a commit.
+diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
+index 4f4020c..7712682 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).
+@@ -644,7 +644,7 @@ struct inode *ext3_orphan_get(struct super_block *sb, unsigned long ino)
-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;
+ /* Error cases - e2fsck has already cleaned up for us */
+ if (ino > max_ino) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "bad orphan ino %lu! e2fsck was run?", ino);
+ goto error;
+ }
+@@ -653,7 +653,7 @@ struct inode *ext3_orphan_get(struct super_block *sb, unsigned long ino)
+ bit = (ino - 1) % EXT3_INODES_PER_GROUP(sb);
+ bitmap_bh = read_inode_bitmap(sb, block_group);
+ if (!bitmap_bh) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "inode bitmap error for orphan %lu", ino);
+ goto error;
+ }
+@@ -678,7 +678,7 @@ iget_failed:
+ err = PTR_ERR(inode);
+ inode = NULL;
+ bad_orphan:
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "bad orphan inode %lu! e2fsck was run?", ino);
+ printk(KERN_NOTICE "ext3_test_bit(bit=%d, block=%llu) = %d\n",
+ bit, (unsigned long long)bitmap_bh->b_blocknr,
+diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
+index eb95670..6ae4ecf 100644
+--- a/fs/ext3/inode.c
++++ b/fs/ext3/inode.c
+@@ -95,7 +95,7 @@ int ext3_forget(handle_t *handle, int is_metadata, struct inode *inode,
+ BUFFER_TRACE(bh, "call ext3_journal_revoke");
+ err = ext3_journal_revoke(handle, blocknr, bh);
+ if (err)
+- ext3_abort(inode->i_sb, __FUNCTION__,
++ ext3_abort(inode->i_sb, __func__,
+ "error %d when attempting revoke", err);
+ BUFFER_TRACE(bh, "exit");
+ return err;
+@@ -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)
}
-+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.
+- * 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
*
- * "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).
+- * Normally this function find the prefered place for block allocation,
++ * Normally this function find the preferred place for block allocation,
+ * returns it.
*/
--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;
+@@ -1190,7 +1190,7 @@ int ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
+ {
+ int err = journal_dirty_data(handle, bh);
+ if (err)
+- ext3_journal_abort_handle(__FUNCTION__, __FUNCTION__,
++ ext3_journal_abort_handle(__func__, __func__,
+ bh, handle, err);
+ return err;
+ }
+@@ -1261,10 +1261,11 @@ static int ext3_ordered_write_end(struct file *file,
+ new_i_size = pos + copied;
+ if (new_i_size > EXT3_I(inode)->i_disksize)
+ EXT3_I(inode)->i_disksize = new_i_size;
+- copied = ext3_generic_write_end(file, mapping, pos, len, copied,
++ ret2 = ext3_generic_write_end(file, mapping, pos, len, copied,
+ page, fsdata);
+- if (copied < 0)
+- ret = copied;
++ copied = ret2;
++ if (ret2 < 0)
++ ret = ret2;
}
-@@ -1818,12 +1823,12 @@ static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
- return retval;
+ ret2 = ext3_journal_stop(handle);
+ if (!ret)
+@@ -1289,10 +1290,11 @@ static int ext3_writeback_write_end(struct file *file,
+ if (new_i_size > EXT3_I(inode)->i_disksize)
+ EXT3_I(inode)->i_disksize = new_i_size;
+
+- copied = ext3_generic_write_end(file, mapping, pos, len, copied,
++ ret2 = ext3_generic_write_end(file, mapping, pos, len, copied,
+ page, fsdata);
+- if (copied < 0)
+- ret = copied;
++ copied = ret2;
++ if (ret2 < 0)
++ ret = ret2;
- 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)
+ ret2 = ext3_journal_stop(handle);
+ if (!ret)
+@@ -2454,11 +2456,10 @@ out_stop:
+ static ext3_fsblk_t ext3_get_inode_block(struct super_block *sb,
+ unsigned long ino, struct ext3_iloc *iloc)
{
- char *res;
- struct path root;
-+ struct path tmp;
+- unsigned long desc, group_desc, block_group;
++ unsigned long block_group;
+ unsigned long offset;
+ ext3_fsblk_t block;
+- struct buffer_head *bh;
+- struct ext3_group_desc * gdp;
++ struct ext3_group_desc *gdp;
+
+ if (!ext3_valid_inum(sb, ino)) {
+ /*
+@@ -2470,27 +2471,15 @@ static ext3_fsblk_t ext3_get_inode_block(struct super_block *sb,
+ }
+ block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb);
+- if (block_group >= EXT3_SB(sb)->s_groups_count) {
+- ext3_error(sb,"ext3_get_inode_block","group >= groups count");
+- return 0;
+- }
+- smp_rmb();
+- group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(sb);
+- desc = block_group & (EXT3_DESC_PER_BLOCK(sb) - 1);
+- bh = EXT3_SB(sb)->s_group_desc[group_desc];
+- if (!bh) {
+- ext3_error (sb, "ext3_get_inode_block",
+- "Descriptor not loaded");
++ gdp = ext3_get_group_desc(sb, block_group, NULL);
++ if (!gdp)
+ return 0;
+- }
+-
+- gdp = (struct ext3_group_desc *)bh->b_data;
/*
- * We have various synthetic filesystems that never get mounted. On
-@@ -1859,10 +1865,11 @@ char *d_path(struct path *path, char *buf, int buflen)
+ * Figure out the offset within the block group inode table
+ */
+ offset = ((ino - 1) % EXT3_INODES_PER_GROUP(sb)) *
+ EXT3_INODE_SIZE(sb);
+- block = le32_to_cpu(gdp[desc].bg_inode_table) +
++ block = le32_to_cpu(gdp->bg_inode_table) +
+ (offset >> EXT3_BLOCK_SIZE_BITS(sb));
+
+ iloc->block_group = block_group;
+@@ -3214,7 +3203,7 @@ void ext3_dirty_inode(struct inode *inode)
+ current_handle->h_transaction != handle->h_transaction) {
+ /* This task has a transaction open against a different fs */
+ printk(KERN_EMERG "%s: transactions do not match!\n",
+- __FUNCTION__);
++ __func__);
+ } else {
+ jbd_debug(5, "marking dirty. outer handle=%p\n",
+ current_handle);
+diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
+index 023a070..0d0c701 100644
+--- a/fs/ext3/ioctl.c
++++ b/fs/ext3/ioctl.c
+@@ -12,6 +12,7 @@
+ #include <linux/capability.h>
+ #include <linux/ext3_fs.h>
+ #include <linux/ext3_jbd.h>
++#include <linux/mount.h>
+ #include <linux/time.h>
+ #include <linux/compat.h>
+ #include <linux/smp_lock.h>
+@@ -38,14 +39,19 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ unsigned int oldflags;
+ unsigned int jflag;
- 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,
- }
+- if (IS_RDONLY(inode))
+- return -EROFS;
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
- /*
-+ * 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)
+- if (!is_owner_or_cap(inode))
+- return -EACCES;
++ if (!is_owner_or_cap(inode)) {
++ err = -EACCES;
++ goto flags_out;
++ }
- 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);
+- if (get_user(flags, (int __user *) arg))
+- return -EFAULT;
++ if (get_user(flags, (int __user *) arg)) {
++ err = -EFAULT;
++ goto flags_out;
++ }
- 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;
+ 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;
-- cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE);
-+ cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE);
- spin_unlock(&dcache_lock);
+@@ -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;
+ }
+ }
- 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 {
- };
+@@ -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;
+ }
+ }
- 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;
- };
+@@ -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:
- 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() */
+ 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;
- mutex_lock(&sp->members_lock);
- list_add(&nd->list, &sp->members);
-@@ -805,12 +807,13 @@ static void put_comm(struct comm *cm)
- }
+ if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
+ return -ENOTTY;
- /* 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;
+- if (IS_RDONLY(inode))
+- return -EROFS;
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
- sp = get_space(lsname);
- if (!sp)
-@@ -818,23 +821,50 @@ int dlm_nodeid_list(char *lsname, int **ids_out)
+- if (!is_owner_or_cap(inode))
+- return -EACCES;
++ if (!is_owner_or_cap(inode)) {
++ err = -EACCES;
++ goto setrsvsz_out;
++ }
- mutex_lock(&sp->members_lock);
- if (!sp->members_count) {
-- rv = 0;
-+ rv = -EINVAL;
-+ printk(KERN_ERR "dlm: zero members_count\n");
- goto 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;
++ }
-- 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;
+ 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;
-- 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 (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 (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;
++ if (get_user(n_blocks_count, (__u32 __user *)arg)) {
++ err = -EFAULT;
++ goto group_extend_out;
+ }
-+ }
-+ *new_count_out = new_count;
-+ *new_out = new;
+ 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;
-+ out_ids:
-+ *ids_count_out = ids_count;
- *ids_out = ids;
- out:
- mutex_unlock(&sp->members_lock);
-diff --git a/fs/dlm/config.h b/fs/dlm/config.h
-index a3170fe..4f1d6fc 100644
---- a/fs/dlm/config.h
-+++ b/fs/dlm/config.h
-@@ -35,7 +35,8 @@ extern struct dlm_config_info dlm_config;
- int dlm_config_init(void);
- void dlm_config_exit(void);
- int dlm_node_weight(char *lsname, int nodeid);
--int dlm_nodeid_list(char *lsname, int **ids_out);
-+int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out,
-+ int **new_out, int *new_count_out);
- int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr);
- int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid);
- int dlm_our_nodeid(void);
-diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
-index d30ea8b..5a7ac33 100644
---- a/fs/dlm/dlm_internal.h
-+++ b/fs/dlm/dlm_internal.h
-@@ -37,14 +37,11 @@
- #include <linux/jhash.h>
- #include <linux/miscdevice.h>
- #include <linux/mutex.h>
--#include <asm/semaphore.h>
- #include <asm/uaccess.h>
+- if (IS_RDONLY(inode))
+- return -EROFS;
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
- #include <linux/dlm.h>
- #include "config.h"
+ if (copy_from_user(&input, (struct ext3_new_group_input __user *)arg,
+- sizeof(input)))
+- return -EFAULT;
++ sizeof(input))) {
++ err = -EFAULT;
++ goto group_add_out;
++ }
--#define DLM_LOCKSPACE_LEN 64
+ 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);
-
- /* 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 {
++group_add_out:
++ mnt_drop_write(filp->f_path.mnt);
+ return err;
+ }
- 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;
- };
+diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
+index dec3e0d..0b8cf80 100644
+--- a/fs/ext3/namei.c
++++ b/fs/ext3/namei.c
+@@ -57,10 +57,15 @@ static struct buffer_head *ext3_append(handle_t *handle,
+
+ *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
+
+- if ((bh = ext3_bread(handle, inode, *block, 1, err))) {
++ bh = ext3_bread(handle, inode, *block, 1, err);
++ if (bh) {
+ inode->i_size += inode->i_sb->s_blocksize;
+ EXT3_I(inode)->i_disksize = inode->i_size;
+- ext3_journal_get_write_access(handle,bh);
++ *err = ext3_journal_get_write_access(handle, bh);
++ if (*err) {
++ brelse(bh);
++ bh = NULL;
++ }
+ }
+ return bh;
+ }
+@@ -356,7 +361,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
+ if (root->info.hash_version != DX_HASH_TEA &&
+ root->info.hash_version != DX_HASH_HALF_MD4 &&
+ root->info.hash_version != DX_HASH_LEGACY) {
+- ext3_warning(dir->i_sb, __FUNCTION__,
++ ext3_warning(dir->i_sb, __func__,
+ "Unrecognised inode hash code %d",
+ root->info.hash_version);
+ brelse(bh);
+@@ -370,7 +375,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
+ hash = hinfo->hash;
-@@ -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);
+ if (root->info.unused_flags & 1) {
+- ext3_warning(dir->i_sb, __FUNCTION__,
++ ext3_warning(dir->i_sb, __func__,
+ "Unimplemented inode hash flags: %#06x",
+ root->info.unused_flags);
+ brelse(bh);
+@@ -379,7 +384,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
+ }
- #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);
- }
+ if ((indirect = root->info.indirect_levels) > 1) {
+- ext3_warning(dir->i_sb, __FUNCTION__,
++ ext3_warning(dir->i_sb, __func__,
+ "Unimplemented inode hash depth: %#06x",
+ root->info.indirect_levels);
+ brelse(bh);
+@@ -392,7 +397,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
--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;
+ if (dx_get_limit(entries) != dx_root_limit(dir,
+ root->info.info_length)) {
+- ext3_warning(dir->i_sb, __FUNCTION__,
++ ext3_warning(dir->i_sb, __func__,
+ "dx entry: limit != root limit");
+ brelse(bh);
+ *err = ERR_BAD_DX_DIR;
+@@ -404,7 +409,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
+ {
+ count = dx_get_count(entries);
+ if (!count || count > dx_get_limit(entries)) {
+- ext3_warning(dir->i_sb, __FUNCTION__,
++ ext3_warning(dir->i_sb, __func__,
+ "dx entry: no count or count > limit");
+ brelse(bh);
+ *err = ERR_BAD_DX_DIR;
+@@ -449,7 +454,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
+ goto fail2;
+ at = entries = ((struct dx_node *) bh->b_data)->entries;
+ if (dx_get_limit(entries) != dx_node_limit (dir)) {
+- ext3_warning(dir->i_sb, __FUNCTION__,
++ ext3_warning(dir->i_sb, __func__,
+ "dx entry: limit != node limit");
+ brelse(bh);
+ *err = ERR_BAD_DX_DIR;
+@@ -465,7 +470,7 @@ fail2:
+ }
+ fail:
+ if (*err == ERR_BAD_DX_DIR)
+- ext3_warning(dir->i_sb, __FUNCTION__,
++ ext3_warning(dir->i_sb, __func__,
+ "Corrupt dir inode %ld, running e2fsck is "
+ "recommended.", dir->i_ino);
+ return NULL;
+@@ -913,7 +918,7 @@ restart:
+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh)) {
+ /* read error, skip block & hope for the best */
+- ext3_error(sb, __FUNCTION__, "reading directory #%lu "
++ ext3_error(sb, __func__, "reading directory #%lu "
+ "offset %lu", dir->i_ino, block);
+ brelse(bh);
+ goto next;
+@@ -1005,7 +1010,7 @@ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
+ retval = ext3_htree_next_block(dir, hash, frame,
+ frames, NULL);
+ if (retval < 0) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "error reading index page in directory #%lu",
+ dir->i_ino);
+ *err = retval;
+@@ -1530,7 +1535,7 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
+
+ if (levels && (dx_get_count(frames->entries) ==
+ dx_get_limit(frames->entries))) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "Directory index full!");
+ err = -ENOSPC;
+ goto cleanup;
+@@ -1832,11 +1837,11 @@ static int empty_dir (struct inode * inode)
+ if (inode->i_size < EXT3_DIR_REC_LEN(1) + EXT3_DIR_REC_LEN(2) ||
+ !(bh = ext3_bread (NULL, inode, 0, 0, &err))) {
+ if (err)
+- ext3_error(inode->i_sb, __FUNCTION__,
++ ext3_error(inode->i_sb, __func__,
+ "error %d reading directory #%lu offset 0",
+ err, inode->i_ino);
+ else
+- ext3_warning(inode->i_sb, __FUNCTION__,
++ ext3_warning(inode->i_sb, __func__,
+ "bad directory (dir #%lu) - no data block",
+ inode->i_ino);
+ return 1;
+@@ -1865,7 +1870,7 @@ static int empty_dir (struct inode * inode)
+ offset >> EXT3_BLOCK_SIZE_BITS(sb), 0, &err);
+ if (!bh) {
+ if (err)
+- ext3_error(sb, __FUNCTION__,
++ ext3_error(sb, __func__,
+ "error %d reading directory"
+ " #%lu offset %lu",
+ err, inode->i_ino, offset);
+@@ -2318,6 +2323,8 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
+ EXT3_FEATURE_INCOMPAT_FILETYPE))
+ new_de->file_type = old_de->file_type;
+ new_dir->i_version++;
++ new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME_SEC;
++ ext3_mark_inode_dirty(handle, new_dir);
+ BUFFER_TRACE(new_bh, "call ext3_journal_dirty_metadata");
+ ext3_journal_dirty_metadata(handle, new_bh);
+ brelse(new_bh);
+diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c
+index 0e97b6e..28cfd0b 100644
+--- a/fs/ext3/resize.c
++++ b/fs/ext3/resize.c
+@@ -48,60 +48,60 @@ static int verify_group_input(struct super_block *sb,
+ free_blocks_count, input->reserved_blocks);
+
+ if (group != sbi->s_groups_count)
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "Cannot add at group %u (only %lu groups)",
+ input->group, sbi->s_groups_count);
+ else if ((start - le32_to_cpu(es->s_first_data_block)) %
+ EXT3_BLOCKS_PER_GROUP(sb))
+- ext3_warning(sb, __FUNCTION__, "Last group not full");
++ ext3_warning(sb, __func__, "Last group not full");
+ else if (input->reserved_blocks > input->blocks_count / 5)
+- ext3_warning(sb, __FUNCTION__, "Reserved blocks too high (%u)",
++ ext3_warning(sb, __func__, "Reserved blocks too high (%u)",
+ input->reserved_blocks);
+ else if (free_blocks_count < 0)
+- ext3_warning(sb, __FUNCTION__, "Bad blocks count %u",
++ ext3_warning(sb, __func__, "Bad blocks count %u",
+ input->blocks_count);
+ else if (!(bh = sb_bread(sb, end - 1)))
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "Cannot read last block ("E3FSBLK")",
+ end - 1);
+ else if (outside(input->block_bitmap, start, end))
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "Block bitmap not in group (block %u)",
+ input->block_bitmap);
+ else if (outside(input->inode_bitmap, start, end))
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "Inode bitmap not in group (block %u)",
+ input->inode_bitmap);
+ else if (outside(input->inode_table, start, end) ||
+ outside(itend - 1, start, end))
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "Inode table not in group (blocks %u-"E3FSBLK")",
+ input->inode_table, itend - 1);
+ else if (input->inode_bitmap == input->block_bitmap)
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "Block bitmap same as inode bitmap (%u)",
+ input->block_bitmap);
+ else if (inside(input->block_bitmap, input->inode_table, itend))
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "Block bitmap (%u) in inode table (%u-"E3FSBLK")",
+ input->block_bitmap, input->inode_table, itend-1);
+ else if (inside(input->inode_bitmap, input->inode_table, itend))
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "Inode bitmap (%u) in inode table (%u-"E3FSBLK")",
+ input->inode_bitmap, input->inode_table, itend-1);
+ else if (inside(input->block_bitmap, start, metaend))
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "Block bitmap (%u) in GDT table"
+ " ("E3FSBLK"-"E3FSBLK")",
+ input->block_bitmap, start, metaend - 1);
+ else if (inside(input->inode_bitmap, start, metaend))
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "Inode bitmap (%u) in GDT table"
+ " ("E3FSBLK"-"E3FSBLK")",
+ input->inode_bitmap, start, metaend - 1);
+ else if (inside(input->inode_table, start, metaend) ||
+ inside(itend - 1, start, metaend))
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "Inode table (%u-"E3FSBLK") overlaps"
+ "GDT table ("E3FSBLK"-"E3FSBLK")",
+ input->inode_table, itend - 1, start, metaend - 1);
+@@ -386,7 +386,7 @@ static int verify_reserved_gdb(struct super_block *sb,
+
+ while ((grp = ext3_list_backups(sb, &three, &five, &seven)) < end) {
+ if (le32_to_cpu(*p++) != grp * EXT3_BLOCKS_PER_GROUP(sb) + blk){
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "reserved GDT "E3FSBLK
+ " missing grp %d ("E3FSBLK")",
+ blk, grp,
+@@ -440,7 +440,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ */
+ if (EXT3_SB(sb)->s_sbh->b_blocknr !=
+ le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "won't resize using backup superblock at %llu",
+ (unsigned long long)EXT3_SB(sb)->s_sbh->b_blocknr);
+ return -EPERM;
+@@ -464,7 +464,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
- 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__
+ data = (__le32 *)dind->b_data;
+ if (le32_to_cpu(data[gdb_num % EXT3_ADDR_PER_BLOCK(sb)]) != gdblock) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "new group %u GDT block "E3FSBLK" not reserved",
+ input->group, gdblock);
+ err = -EINVAL;
+@@ -488,7 +488,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ GFP_NOFS);
+ if (!n_group_desc) {
+ err = -ENOMEM;
+- ext3_warning (sb, __FUNCTION__,
++ ext3_warning (sb, __func__,
+ "not enough memory for %lu groups", gdb_num + 1);
+ goto exit_inode;
+ }
+@@ -586,7 +586,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
+ /* Get each reserved primary GDT block and verify it holds backups */
+ for (res = 0; res < reserved_gdb; res++, blk++) {
+ if (le32_to_cpu(*data) != blk) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "reserved block "E3FSBLK
+ " not at offset %ld",
+ blk,
+@@ -730,7 +730,7 @@ static void update_backups(struct super_block *sb,
+ */
+ exit_err:
+ if (err) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "can't update backup for group %d (err %d), "
+ "forcing fsck on next reboot", group, err);
+ sbi->s_mount_state &= ~EXT3_VALID_FS;
+@@ -770,33 +770,33 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
+
+ if (gdb_off == 0 && !EXT3_HAS_RO_COMPAT_FEATURE(sb,
+ EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "Can't resize non-sparse filesystem further");
+ return -EPERM;
+ }
--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;
+ if (le32_to_cpu(es->s_blocks_count) + input->blocks_count <
+ le32_to_cpu(es->s_blocks_count)) {
+- ext3_warning(sb, __FUNCTION__, "blocks_count overflow\n");
++ ext3_warning(sb, __func__, "blocks_count overflow\n");
+ return -EINVAL;
+ }
-+ error = dlm_plock_init();
-+ if (error)
-+ goto out_netlink;
-+
- printk("DLM (built %s %s) installed\n", __DATE__, __TIME__);
+ if (le32_to_cpu(es->s_inodes_count) + EXT3_INODES_PER_GROUP(sb) <
+ le32_to_cpu(es->s_inodes_count)) {
+- ext3_warning(sb, __FUNCTION__, "inodes_count overflow\n");
++ ext3_warning(sb, __func__, "inodes_count overflow\n");
+ return -EINVAL;
+ }
- return 0;
+ if (reserved_gdb || gdb_off == 0) {
+ if (!EXT3_HAS_COMPAT_FEATURE(sb,
+ EXT3_FEATURE_COMPAT_RESIZE_INODE)){
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "No reserved GDT blocks, can't resize");
+ return -EPERM;
+ }
+ inode = ext3_iget(sb, EXT3_RESIZE_INO);
+ if (IS_ERR(inode)) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "Error opening resize inode");
+ return PTR_ERR(inode);
+ }
+@@ -825,7 +825,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
+
+ lock_super(sb);
+ if (input->group != sbi->s_groups_count) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "multiple resizers run on filesystem!");
+ err = -EBUSY;
+ goto exit_journal;
+@@ -988,13 +988,13 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
+ " too large to resize to %lu blocks safely\n",
+ sb->s_id, n_blocks_count);
+ if (sizeof(sector_t) < 8)
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "CONFIG_LBD not enabled\n");
+ return -EINVAL;
+ }
-+ out_netlink:
-+ dlm_netlink_exit();
- out_user:
- dlm_user_exit();
- out_debug:
-@@ -66,6 +72,7 @@ static int __init init_dlm(void)
+ if (n_blocks_count < o_blocks_count) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "can't shrink FS - resize aborted");
+ return -EBUSY;
+ }
+@@ -1004,7 +1004,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
+ EXT3_BLOCKS_PER_GROUP(sb);
- 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)
+ if (last == 0) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "need to use ext2online to resize further");
+ return -EPERM;
+ }
+@@ -1012,7 +1012,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
+ add = EXT3_BLOCKS_PER_GROUP(sb) - last;
+
+ if (o_blocks_count + add < o_blocks_count) {
+- ext3_warning(sb, __FUNCTION__, "blocks_count overflow");
++ ext3_warning(sb, __func__, "blocks_count overflow");
+ return -EINVAL;
+ }
+
+@@ -1020,7 +1020,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
+ add = n_blocks_count - o_blocks_count;
+
+ if (o_blocks_count + add < n_blocks_count)
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "will only finish group ("E3FSBLK
+ " blocks, %u new)",
+ o_blocks_count + add, add);
+@@ -1028,7 +1028,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
+ /* See if the device is actually as big as what was requested */
+ bh = sb_bread(sb, o_blocks_count + add -1);
+ if (!bh) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "can't read last block, resize aborted");
+ return -ENOSPC;
+ }
+@@ -1040,22 +1040,23 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
+ handle = ext3_journal_start_sb(sb, 3);
+ if (IS_ERR(handle)) {
+ err = PTR_ERR(handle);
+- ext3_warning(sb, __FUNCTION__, "error %d on journal start",err);
++ ext3_warning(sb, __func__, "error %d on journal start",err);
+ goto exit_put;
+ }
+
+ lock_super(sb);
+ if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "multiple resizers run on filesystem!");
+ unlock_super(sb);
++ ext3_journal_stop(handle);
+ err = -EBUSY;
+ goto exit_put;
+ }
+
+ if ((err = ext3_journal_get_write_access(handle,
+ EXT3_SB(sb)->s_sbh))) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "error %d on journal write access", err);
+ unlock_super(sb);
+ ext3_journal_stop(handle);
+diff --git a/fs/ext3/super.c b/fs/ext3/super.c
+index ad53606..fe3119a 100644
+--- a/fs/ext3/super.c
++++ b/fs/ext3/super.c
+@@ -84,7 +84,7 @@ handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks)
+ * take the FS itself readonly cleanly. */
+ journal = EXT3_SB(sb)->s_journal;
+ if (is_journal_aborted(journal)) {
+- ext3_abort(sb, __FUNCTION__,
++ ext3_abort(sb, __func__,
+ "Detected aborted journal");
+ return ERR_PTR(-EROFS);
+ }
+@@ -304,7 +304,7 @@ void ext3_update_dynamic_rev(struct super_block *sb)
+ if (le32_to_cpu(es->s_rev_level) > EXT3_GOOD_OLD_REV)
+ return;
+
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "updating to rev %d because of new feature flag, "
+ "running e2fsck is recommended",
+ EXT3_DYNAMIC_REV);
+@@ -685,7 +685,8 @@ static int ext3_acquire_dquot(struct dquot *dquot);
+ static int ext3_release_dquot(struct dquot *dquot);
+ static int ext3_mark_dquot_dirty(struct dquot *dquot);
+ static int ext3_write_info(struct super_block *sb, int type);
+-static int ext3_quota_on(struct super_block *sb, int type, int format_id, char *path);
++static int ext3_quota_on(struct super_block *sb, int type, int format_id,
++ char *path, int remount);
+ static int ext3_quota_on_mount(struct super_block *sb, int type);
+ static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
+ size_t len, loff_t off);
+@@ -1096,6 +1097,9 @@ clear_qf_name:
+ case Opt_quota:
+ case Opt_usrquota:
+ case Opt_grpquota:
++ printk(KERN_ERR
++ "EXT3-fs: quota options not supported.\n");
++ break;
+ case Opt_usrjquota:
+ case Opt_grpjquota:
+ case Opt_offusrjquota:
+@@ -1103,7 +1107,7 @@ clear_qf_name:
+ case Opt_jqfmt_vfsold:
+ case Opt_jqfmt_vfsv0:
+ printk(KERN_ERR
+- "EXT3-fs: journalled quota options not "
++ "EXT3-fs: journaled quota options not "
+ "supported.\n");
+ break;
+ case Opt_noquota:
+@@ -1218,7 +1222,7 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,
+ inconsistencies, to force a fsck at reboot. But for
+ a plain journaled filesystem we can keep it set as
+ valid forever! :) */
+- es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT3_VALID_FS);
++ es->s_state &= cpu_to_le16(~EXT3_VALID_FS);
+ #endif
+ if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
+ es->s_max_mnt_count = cpu_to_le16(EXT3_DFL_MAX_MNT_COUNT);
+@@ -1253,14 +1257,14 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,
+ static int ext3_check_descriptors(struct super_block *sb)
+ {
+ struct ext3_sb_info *sbi = EXT3_SB(sb);
+- ext3_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
+- ext3_fsblk_t last_block;
+ int i;
+
+ ext3_debug ("Checking group descriptors");
+
+ for (i = 0; i < sbi->s_groups_count; i++) {
+ struct ext3_group_desc *gdp = ext3_get_group_desc(sb, i, NULL);
++ ext3_fsblk_t first_block = ext3_group_first_block_no(sb, i);
++ ext3_fsblk_t last_block;
+
+ if (i == sbi->s_groups_count - 1)
+ last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1;
+@@ -1299,7 +1303,6 @@ static int ext3_check_descriptors(struct super_block *sb)
+ le32_to_cpu(gdp->bg_inode_table));
+ return 0;
}
+- first_block += EXT3_BLOCKS_PER_GROUP(sb);
}
-+ /* 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++;
+ sbi->s_es->s_free_blocks_count=cpu_to_le32(ext3_count_free_blocks(sb));
+@@ -1387,7 +1390,7 @@ static void ext3_orphan_cleanup (struct super_block * sb,
+ if (inode->i_nlink) {
+ printk(KERN_DEBUG
+ "%s: truncating inode %lu to %Ld bytes\n",
+- __FUNCTION__, inode->i_ino, inode->i_size);
++ __func__, inode->i_ino, inode->i_size);
+ jbd_debug(2, "truncating inode %lu to %Ld bytes\n",
+ inode->i_ino, inode->i_size);
+ ext3_truncate(inode);
+@@ -1395,7 +1398,7 @@ static void ext3_orphan_cleanup (struct super_block * sb,
+ } else {
+ printk(KERN_DEBUG
+ "%s: deleting unreferenced inode %lu\n",
+- __FUNCTION__, inode->i_ino);
++ __func__, inode->i_ino);
+ jbd_debug(2, "deleting unreferenced inode %lu\n",
+ inode->i_ino);
+ nr_orphans++;
+@@ -1415,7 +1418,7 @@ static void ext3_orphan_cleanup (struct super_block * sb,
+ /* Turn quotas off */
+ for (i = 0; i < MAXQUOTAS; i++) {
+ if (sb_dqopt(sb)->files[i])
+- vfs_quota_off(sb, i);
++ vfs_quota_off(sb, i, 0);
+ }
+ #endif
+ sb->s_flags = s_flags; /* Restore MS_RDONLY status */
+@@ -2298,9 +2301,9 @@ static void ext3_clear_journal_err(struct super_block * sb,
+ char nbuf[16];
+
+ errstr = ext3_decode_error(sb, j_errno, nbuf);
+- ext3_warning(sb, __FUNCTION__, "Filesystem error recorded "
++ ext3_warning(sb, __func__, "Filesystem error recorded "
+ "from previous mount: %s", errstr);
+- ext3_warning(sb, __FUNCTION__, "Marking fs in need of "
++ ext3_warning(sb, __func__, "Marking fs in need of "
+ "filesystem check.");
+
+ EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
+@@ -2427,7 +2430,7 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
+ }
+
+ if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
+- ext3_abort(sb, __FUNCTION__, "Abort forced by user");
++ ext3_abort(sb, __func__, "Abort forced by user");
+
+ sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
+ ((sbi->s_mount_opt & EXT3_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
+@@ -2639,8 +2642,14 @@ static int ext3_dquot_drop(struct inode *inode)
+
+ /* We may delete quota structure so we need to reserve enough blocks */
+ handle = ext3_journal_start(inode, 2*EXT3_QUOTA_DEL_BLOCKS(inode->i_sb));
+- if (IS_ERR(handle))
++ if (IS_ERR(handle)) {
++ /*
++ * We call dquot_drop() anyway to at least release references
++ * to quota structures so that umount does not hang.
++ */
++ dquot_drop(inode);
+ return PTR_ERR(handle);
+ }
-+
- /* 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)
+ ret = dquot_drop(inode);
+ err = ext3_journal_stop(handle);
+ if (!ret)
+@@ -2743,17 +2752,17 @@ static int ext3_quota_on_mount(struct super_block *sb, int type)
+ * Standard function to be called on quota_on
+ */
+ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
+- char *path)
++ char *path, int remount)
{
- 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;
+ int err;
+ struct nameidata nd;
- rv = kzalloc(sizeof(struct dlm_recover), GFP_KERNEL);
- if (!rv)
- return -ENOMEM;
+ if (!test_opt(sb, QUOTA))
+ return -EINVAL;
+- /* Not journalling quota? */
+- if (!EXT3_SB(sb)->s_qf_names[USRQUOTA] &&
+- !EXT3_SB(sb)->s_qf_names[GRPQUOTA])
+- return vfs_quota_on(sb, type, format_id, path);
++ /* Not journalling quota or remount? */
++ if ((!EXT3_SB(sb)->s_qf_names[USRQUOTA] &&
++ !EXT3_SB(sb)->s_qf_names[GRPQUOTA]) || remount)
++ return vfs_quota_on(sb, type, format_id, path, remount);
+ err = path_lookup(path, LOOKUP_FOLLOW, &nd);
+ if (err)
+ return err;
+@@ -2762,13 +2771,13 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
+ path_put(&nd.path);
+ return -EXDEV;
+ }
+- /* Quotafile not of fs root? */
++ /* Quotafile not in fs root? */
+ if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
+ printk(KERN_WARNING
+ "EXT3-fs: Quota file not on filesystem root. "
+ "Journalled quota will not work.\n");
+ path_put(&nd.path);
+- return vfs_quota_on(sb, type, format_id, path);
++ return vfs_quota_on(sb, type, format_id, path, remount);
+ }
-- 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;
+ /* Read data from quotafile - avoid pagecache and such because we cannot afford
+diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
+index 4285654..d4a4f0e 100644
+--- a/fs/ext3/xattr.c
++++ b/fs/ext3/xattr.c
+@@ -99,6 +99,8 @@ static struct buffer_head *ext3_xattr_cache_find(struct inode *,
+ struct mb_cache_entry **);
+ static void ext3_xattr_rehash(struct ext3_xattr_header *,
+ struct ext3_xattr_entry *);
++static int ext3_xattr_list(struct inode *inode, char *buffer,
++ size_t buffer_size);
+
+ static struct mb_cache *ext3_xattr_cache;
+
+@@ -232,7 +234,7 @@ ext3_xattr_block_get(struct inode *inode, int name_index, const char *name,
+ ea_bdebug(bh, "b_count=%d, refcount=%d",
+ atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
+ if (ext3_xattr_check_block(bh)) {
+-bad_block: ext3_error(inode->i_sb, __FUNCTION__,
++bad_block: ext3_error(inode->i_sb, __func__,
+ "inode %lu: bad block "E3FSBLK, inode->i_ino,
+ EXT3_I(inode)->i_file_acl);
+ error = -EIO;
+@@ -374,7 +376,7 @@ ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
+ ea_bdebug(bh, "b_count=%d, refcount=%d",
+ atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
+ if (ext3_xattr_check_block(bh)) {
+- ext3_error(inode->i_sb, __FUNCTION__,
++ ext3_error(inode->i_sb, __func__,
+ "inode %lu: bad block "E3FSBLK, inode->i_ino,
+ EXT3_I(inode)->i_file_acl);
+ error = -EIO;
+@@ -427,7 +429,7 @@ cleanup:
+ * Returns a negative error number on failure, or the number of bytes
+ * used / required on success.
+ */
+-int
++static int
+ ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
+ {
+ int i_error, b_error;
+@@ -649,7 +651,7 @@ ext3_xattr_block_find(struct inode *inode, struct ext3_xattr_info *i,
+ atomic_read(&(bs->bh->b_count)),
+ le32_to_cpu(BHDR(bs->bh)->h_refcount));
+ if (ext3_xattr_check_block(bs->bh)) {
+- ext3_error(sb, __FUNCTION__,
++ ext3_error(sb, __func__,
+ "inode %lu: bad block "E3FSBLK, inode->i_ino,
+ EXT3_I(inode)->i_file_acl);
+ error = -EIO;
+@@ -797,10 +799,8 @@ inserted:
+ get_bh(new_bh);
+ } else {
+ /* We need to allocate a new block */
+- ext3_fsblk_t goal = le32_to_cpu(
+- EXT3_SB(sb)->s_es->s_first_data_block) +
+- (ext3_fsblk_t)EXT3_I(inode)->i_block_group *
+- EXT3_BLOCKS_PER_GROUP(sb);
++ ext3_fsblk_t goal = ext3_group_first_block_no(sb,
++ EXT3_I(inode)->i_block_group);
+ ext3_fsblk_t block = ext3_new_block(handle, inode,
+ goal, &error);
+ if (error)
+@@ -852,7 +852,7 @@ cleanup_dquot:
+ goto cleanup;
- spin_lock(&ls->ls_recover_lock);
-@@ -337,14 +355,19 @@ int dlm_ls_start(struct dlm_ls *ls)
+ bad_block:
+- ext3_error(inode->i_sb, __FUNCTION__,
++ ext3_error(inode->i_sb, __func__,
+ "inode %lu: bad block "E3FSBLK, inode->i_ino,
+ EXT3_I(inode)->i_file_acl);
+ goto cleanup;
+@@ -1081,14 +1081,14 @@ ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
+ goto cleanup;
+ bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
+ if (!bh) {
+- ext3_error(inode->i_sb, __FUNCTION__,
++ ext3_error(inode->i_sb, __func__,
+ "inode %lu: block "E3FSBLK" read error", inode->i_ino,
+ EXT3_I(inode)->i_file_acl);
+ goto cleanup;
}
+ if (BHDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
+ BHDR(bh)->h_blocks != cpu_to_le32(1)) {
+- ext3_error(inode->i_sb, __FUNCTION__,
++ ext3_error(inode->i_sb, __func__,
+ "inode %lu: bad block "E3FSBLK, inode->i_ino,
+ EXT3_I(inode)->i_file_acl);
+ goto cleanup;
+@@ -1215,7 +1215,7 @@ again:
+ }
+ bh = sb_bread(inode->i_sb, ce->e_block);
+ if (!bh) {
+- ext3_error(inode->i_sb, __FUNCTION__,
++ ext3_error(inode->i_sb, __func__,
+ "inode %lu: block %lu read error",
+ inode->i_ino, (unsigned long) ce->e_block);
+ } else if (le32_to_cpu(BHDR(bh)->h_refcount) >=
+diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h
+index 6b1ae1c..148a4df 100644
+--- a/fs/ext3/xattr.h
++++ b/fs/ext3/xattr.h
+@@ -67,7 +67,6 @@ extern struct xattr_handler ext3_xattr_security_handler;
+ extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
+
+ extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
+-extern int ext3_xattr_list(struct inode *, char *, size_t);
+ extern int ext3_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
+ extern int ext3_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int);
- 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);
+@@ -89,12 +88,6 @@ ext3_xattr_get(struct inode *inode, int name_index, const char *name,
+ }
- 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);
+ static inline int
+-ext3_xattr_list(struct inode *inode, void *buffer, size_t size)
+-{
+- return -EOPNOTSUPP;
+-}
+-
+-static inline int
+ ext3_xattr_set(struct inode *inode, int name_index, const char *name,
+ const void *value, size_t size, int flags)
+ {
+diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
+index a8bae8c..3c8dab8 100644
+--- a/fs/ext4/acl.c
++++ b/fs/ext4/acl.c
+@@ -9,8 +9,8 @@
+ #include <linux/slab.h>
+ #include <linux/capability.h>
+ #include <linux/fs.h>
+-#include <linux/ext4_jbd2.h>
+-#include <linux/ext4_fs.h>
++#include "ext4_jbd2.h"
++#include "ext4.h"
+ #include "xattr.h"
+ #include "acl.h"
+
+@@ -37,7 +37,7 @@ ext4_acl_from_disk(const void *value, size_t size)
+ return ERR_PTR(-EINVAL);
+ if (count == 0)
+ return NULL;
+- acl = posix_acl_alloc(count, GFP_KERNEL);
++ acl = posix_acl_alloc(count, GFP_NOFS);
+ if (!acl)
+ return ERR_PTR(-ENOMEM);
+ for (n=0; n < count; n++) {
+@@ -91,7 +91,7 @@ ext4_acl_to_disk(const struct posix_acl *acl, size_t *size)
+
+ *size = ext4_acl_size(acl->a_count);
+ ext_acl = kmalloc(sizeof(ext4_acl_header) + acl->a_count *
+- sizeof(ext4_acl_entry), GFP_KERNEL);
++ sizeof(ext4_acl_entry), GFP_NOFS);
+ if (!ext_acl)
+ return ERR_PTR(-ENOMEM);
+ ext_acl->a_version = cpu_to_le32(EXT4_ACL_VERSION);
+@@ -187,7 +187,7 @@ ext4_get_acl(struct inode *inode, int type)
}
+ retval = ext4_xattr_get(inode, name_index, "", NULL, 0);
+ if (retval > 0) {
+- value = kmalloc(retval, GFP_KERNEL);
++ value = kmalloc(retval, GFP_NOFS);
+ if (!value)
+ return ERR_PTR(-ENOMEM);
+ retval = ext4_xattr_get(inode, name_index, "", value, retval);
+@@ -335,7 +335,7 @@ ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
+ if (error)
+ goto cleanup;
+ }
+- clone = posix_acl_clone(acl, GFP_KERNEL);
++ clone = posix_acl_clone(acl, GFP_NOFS);
+ error = -ENOMEM;
+ if (!clone)
+ goto cleanup;
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 0737e05..da99437 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -15,12 +15,12 @@
+ #include <linux/capability.h>
+ #include <linux/fs.h>
+ #include <linux/jbd2.h>
+-#include <linux/ext4_fs.h>
+-#include <linux/ext4_jbd2.h>
+ #include <linux/quotaops.h>
+ #include <linux/buffer_head.h>
+-
++#include "ext4.h"
++#include "ext4_jbd2.h"
+ #include "group.h"
++
+ /*
+ * balloc.c contains the blocks allocation and deallocation routines
+ */
+@@ -48,7 +48,6 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
+ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ ext4_group_t block_group, struct ext4_group_desc *gdp)
+ {
+- unsigned long start;
+ int bit, bit_max;
+ unsigned free_blocks, group_blocks;
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
+@@ -59,7 +58,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ /* If checksum is bad mark all blocks used to prevent allocation
+ * essentially implementing a per-group read-only flag. */
+ if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
+- ext4_error(sb, __FUNCTION__,
++ ext4_error(sb, __func__,
+ "Checksum bad for group %lu\n", block_group);
+ gdp->bg_free_blocks_count = 0;
+ gdp->bg_free_inodes_count = 0;
+@@ -106,11 +105,12 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ free_blocks = group_blocks - bit_max;
+
+ if (bh) {
++ ext4_fsblk_t start;
++
+ for (bit = 0; bit < bit_max; bit++)
+ ext4_set_bit(bit, bh->b_data);
+
+- start = block_group * EXT4_BLOCKS_PER_GROUP(sb) +
+- le32_to_cpu(sbi->s_es->s_first_data_block);
++ start = ext4_group_first_block_no(sb, block_group);
+
+ /* Set bits for block and inode bitmaps, and inode table */
+ ext4_set_bit(ext4_block_bitmap(sb, gdp) - start, bh->b_data);
+@@ -235,7 +235,7 @@ static int ext4_valid_block_bitmap(struct super_block *sb,
+ return 1;
-@@ -354,6 +377,7 @@ int dlm_ls_start(struct dlm_ls *ls)
- fail:
- kfree(rv);
- kfree(ids);
-+ kfree(new);
- return error;
+ err_out:
+- ext4_error(sb, __FUNCTION__,
++ ext4_error(sb, __func__,
+ "Invalid block bitmap - "
+ "block_group = %d, block = %llu",
+ block_group, bitmap_blk);
+@@ -264,7 +264,7 @@ read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
+ bitmap_blk = ext4_block_bitmap(sb, desc);
+ bh = sb_getblk(sb, bitmap_blk);
+ if (unlikely(!bh)) {
+- ext4_error(sb, __FUNCTION__,
++ ext4_error(sb, __func__,
+ "Cannot read block bitmap - "
+ "block_group = %d, block_bitmap = %llu",
+ (int)block_group, (unsigned long long)bitmap_blk);
+@@ -281,7 +281,7 @@ read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
+ }
+ if (bh_submit_read(bh) < 0) {
+ put_bh(bh);
+- ext4_error(sb, __FUNCTION__,
++ ext4_error(sb, __func__,
+ "Cannot read block bitmap - "
+ "block_group = %d, block_bitmap = %llu",
+ (int)block_group, (unsigned long long)bitmap_blk);
+@@ -360,7 +360,7 @@ restart:
+ BUG();
}
+ #define rsv_window_dump(root, verbose) \
+- __rsv_window_dump((root), (verbose), __FUNCTION__)
++ __rsv_window_dump((root), (verbose), __func__)
+ #else
+ #define rsv_window_dump(root, verbose) do {} while (0)
+ #endif
+@@ -740,7 +740,7 @@ do_more:
+ if (!ext4_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
+ bit + i, bitmap_bh->b_data)) {
+ jbd_unlock_bh_state(bitmap_bh);
+- ext4_error(sb, __FUNCTION__,
++ ext4_error(sb, __func__,
+ "bit already cleared for block %llu",
+ (ext4_fsblk_t)(block + i));
+ jbd_lock_bh_state(bitmap_bh);
+@@ -752,9 +752,7 @@ do_more:
+ jbd_unlock_bh_state(bitmap_bh);
+
+ spin_lock(sb_bgl_lock(sbi, block_group));
+- desc->bg_free_blocks_count =
+- cpu_to_le16(le16_to_cpu(desc->bg_free_blocks_count) +
+- group_freed);
++ le16_add_cpu(&desc->bg_free_blocks_count, group_freed);
+ desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc);
+ spin_unlock(sb_bgl_lock(sbi, block_group));
+ percpu_counter_add(&sbi->s_freeblocks_counter, count);
+@@ -1798,7 +1796,7 @@ allocated:
+ if (ext4_test_bit(grp_alloc_blk+i,
+ bh2jh(bitmap_bh)->b_committed_data)) {
+ printk("%s: block was unexpectedly set in "
+- "b_committed_data\n", __FUNCTION__);
++ "b_committed_data\n", __func__);
+ }
+ }
+ }
+@@ -1823,8 +1821,7 @@ allocated:
+ spin_lock(sb_bgl_lock(sbi, group_no));
+ if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))
+ gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
+- gdp->bg_free_blocks_count =
+- cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)-num);
++ le16_add_cpu(&gdp->bg_free_blocks_count, -num);
+ gdp->bg_checksum = ext4_group_desc_csum(sbi, group_no, gdp);
+ spin_unlock(sb_bgl_lock(sbi, group_no));
+ percpu_counter_sub(&sbi->s_freeblocks_counter, num);
+diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c
+index 420554f..d37ea67 100644
+--- a/fs/ext4/bitmap.c
++++ b/fs/ext4/bitmap.c
+@@ -9,7 +9,7 @@
-diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c
+ #include <linux/buffer_head.h>
+ #include <linux/jbd2.h>
+-#include <linux/ext4_fs.h>
++#include "ext4.h"
+
+ #ifdef EXT4FS_DEBUG
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 2c23bad..2bf0331 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -23,10 +23,10 @@
+
+ #include <linux/fs.h>
+ #include <linux/jbd2.h>
+-#include <linux/ext4_fs.h>
+ #include <linux/buffer_head.h>
+ #include <linux/slab.h>
+ #include <linux/rbtree.h>
++#include "ext4.h"
+
+ static unsigned char ext4_filetype_table[] = {
+ DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
+@@ -42,7 +42,7 @@ const struct file_operations ext4_dir_operations = {
+ .llseek = generic_file_llseek,
+ .read = generic_read_dir,
+ .readdir = ext4_readdir, /* we take BKL. needed?*/
+- .ioctl = ext4_ioctl, /* BKL held */
++ .unlocked_ioctl = ext4_ioctl,
+ #ifdef CONFIG_COMPAT
+ .compat_ioctl = ext4_compat_ioctl,
+ #endif
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
new file mode 100644
-index 0000000..d6d6e37
+index 0000000..8158083
--- /dev/null
-+++ b/fs/dlm/plock.c
-@@ -0,0 +1,439 @@
++++ b/fs/ext4/ext4.h
+@@ -0,0 +1,1205 @@
+/*
-+ * Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved.
++ * ext4.h
+ *
-+ * 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.
++ * Copyright (C) 1992, 1993, 1994, 1995
++ * Remy Card (card at masi.ibp.fr)
++ * Laboratoire MASI - Institut Blaise Pascal
++ * Universite Pierre et Marie Curie (Paris VI)
++ *
++ * from
++ *
++ * linux/include/linux/minix_fs.h
++ *
++ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/poll.h>
-+#include <linux/dlm.h>
-+#include <linux/dlm_plock.h>
++#ifndef _EXT4_H
++#define _EXT4_H
+
-+#include "dlm_internal.h"
-+#include "lockspace.h"
++#include <linux/types.h>
++#include <linux/blkdev.h>
++#include <linux/magic.h>
++#include "ext4_i.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;
++/*
++ * The second extended filesystem constants/structures
++ */
+
-+struct plock_op {
-+ struct list_head list;
-+ int done;
-+ struct dlm_plock_info info;
++/*
++ * Define EXT4FS_DEBUG to produce debug messages
++ */
++#undef EXT4FS_DEBUG
++
++/*
++ * Define EXT4_RESERVATION to reserve data blocks for expanding files
++ */
++#define EXT4_DEFAULT_RESERVE_BLOCKS 8
++/*max window size: 1024(direct blocks) + 3([t,d]indirect blocks) */
++#define EXT4_MAX_RESERVE_BLOCKS 1027
++#define EXT4_RESERVE_WINDOW_NOT_ALLOCATED 0
++
++/*
++ * Debug code
++ */
++#ifdef EXT4FS_DEBUG
++#define ext4_debug(f, a...) \
++ do { \
++ printk (KERN_DEBUG "EXT4-fs DEBUG (%s, %d): %s:", \
++ __FILE__, __LINE__, __FUNCTION__); \
++ printk (KERN_DEBUG f, ## a); \
++ } while (0)
++#else
++#define ext4_debug(f, a...) do {} while (0)
++#endif
++
++#define EXT4_MULTIBLOCK_ALLOCATOR 1
++
++/* prefer goal again. length */
++#define EXT4_MB_HINT_MERGE 1
++/* blocks already reserved */
++#define EXT4_MB_HINT_RESERVED 2
++/* metadata is being allocated */
++#define EXT4_MB_HINT_METADATA 4
++/* first blocks in the file */
++#define EXT4_MB_HINT_FIRST 8
++/* search for the best chunk */
++#define EXT4_MB_HINT_BEST 16
++/* data is being allocated */
++#define EXT4_MB_HINT_DATA 32
++/* don't preallocate (for tails) */
++#define EXT4_MB_HINT_NOPREALLOC 64
++/* allocate for locality group */
++#define EXT4_MB_HINT_GROUP_ALLOC 128
++/* allocate goal blocks or none */
++#define EXT4_MB_HINT_GOAL_ONLY 256
++/* goal is meaningful */
++#define EXT4_MB_HINT_TRY_GOAL 512
++
++struct ext4_allocation_request {
++ /* target inode for block we're allocating */
++ struct inode *inode;
++ /* logical block in target inode */
++ ext4_lblk_t logical;
++ /* phys. target (a hint) */
++ ext4_fsblk_t goal;
++ /* the closest logical allocated block to the left */
++ ext4_lblk_t lleft;
++ /* phys. block for ^^^ */
++ ext4_fsblk_t pleft;
++ /* the closest logical allocated block to the right */
++ ext4_lblk_t lright;
++ /* phys. block for ^^^ */
++ ext4_fsblk_t pright;
++ /* how many blocks we want to allocate */
++ unsigned long len;
++ /* flags. see above EXT4_MB_HINT_* */
++ unsigned long flags;
+};
+
-+struct plock_xop {
-+ struct plock_op xop;
-+ void *callback;
-+ void *fl;
-+ void *file;
-+ struct file_lock flc;
++/*
++ * Special inodes numbers
++ */
++#define EXT4_BAD_INO 1 /* Bad blocks inode */
++#define EXT4_ROOT_INO 2 /* Root inode */
++#define EXT4_BOOT_LOADER_INO 5 /* Boot loader inode */
++#define EXT4_UNDEL_DIR_INO 6 /* Undelete directory inode */
++#define EXT4_RESIZE_INO 7 /* Reserved group descriptors inode */
++#define EXT4_JOURNAL_INO 8 /* Journal inode */
++
++/* First non-reserved inode for old ext4 filesystems */
++#define EXT4_GOOD_OLD_FIRST_INO 11
++
++/*
++ * Maximal count of links to a file
++ */
++#define EXT4_LINK_MAX 65000
++
++/*
++ * Macro-instructions used to manage several block sizes
++ */
++#define EXT4_MIN_BLOCK_SIZE 1024
++#define EXT4_MAX_BLOCK_SIZE 65536
++#define EXT4_MIN_BLOCK_LOG_SIZE 10
++#ifdef __KERNEL__
++# define EXT4_BLOCK_SIZE(s) ((s)->s_blocksize)
++#else
++# define EXT4_BLOCK_SIZE(s) (EXT4_MIN_BLOCK_SIZE << (s)->s_log_block_size)
++#endif
++#define EXT4_ADDR_PER_BLOCK(s) (EXT4_BLOCK_SIZE(s) / sizeof (__u32))
++#ifdef __KERNEL__
++# define EXT4_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
++#else
++# define EXT4_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
++#endif
++#ifdef __KERNEL__
++#define EXT4_ADDR_PER_BLOCK_BITS(s) (EXT4_SB(s)->s_addr_per_block_bits)
++#define EXT4_INODE_SIZE(s) (EXT4_SB(s)->s_inode_size)
++#define EXT4_FIRST_INO(s) (EXT4_SB(s)->s_first_ino)
++#else
++#define EXT4_INODE_SIZE(s) (((s)->s_rev_level == EXT4_GOOD_OLD_REV) ? \
++ EXT4_GOOD_OLD_INODE_SIZE : \
++ (s)->s_inode_size)
++#define EXT4_FIRST_INO(s) (((s)->s_rev_level == EXT4_GOOD_OLD_REV) ? \
++ EXT4_GOOD_OLD_FIRST_INO : \
++ (s)->s_first_ino)
++#endif
++#define EXT4_BLOCK_ALIGN(size, blkbits) ALIGN((size), (1 << (blkbits)))
++
++/*
++ * Structure of a blocks group descriptor
++ */
++struct ext4_group_desc
++{
++ __le32 bg_block_bitmap_lo; /* Blocks bitmap block */
++ __le32 bg_inode_bitmap_lo; /* Inodes bitmap block */
++ __le32 bg_inode_table_lo; /* Inodes table block */
++ __le16 bg_free_blocks_count; /* Free blocks count */
++ __le16 bg_free_inodes_count; /* Free inodes count */
++ __le16 bg_used_dirs_count; /* Directories count */
++ __le16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */
++ __u32 bg_reserved[2]; /* Likely block/inode bitmap checksum */
++ __le16 bg_itable_unused; /* Unused inodes count */
++ __le16 bg_checksum; /* crc16(sb_uuid+group+desc) */
++ __le32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */
++ __le32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */
++ __le32 bg_inode_table_hi; /* Inodes table block MSB */
++ __le16 bg_free_blocks_count_hi;/* Free blocks count MSB */
++ __le16 bg_free_inodes_count_hi;/* Free inodes count MSB */
++ __le16 bg_used_dirs_count_hi; /* Directories count MSB */
++ __le16 bg_itable_unused_hi; /* Unused inodes count MSB */
++ __u32 bg_reserved2[3];
++};
++
++#define EXT4_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not in use */
++#define EXT4_BG_BLOCK_UNINIT 0x0002 /* Block bitmap not in use */
++#define EXT4_BG_INODE_ZEROED 0x0004 /* On-disk itable initialized to zero */
++
++#ifdef __KERNEL__
++#include "ext4_sb.h"
++#endif
++/*
++ * Macro-instructions used to manage group descriptors
++ */
++#define EXT4_MIN_DESC_SIZE 32
++#define EXT4_MIN_DESC_SIZE_64BIT 64
++#define EXT4_MAX_DESC_SIZE EXT4_MIN_BLOCK_SIZE
++#define EXT4_DESC_SIZE(s) (EXT4_SB(s)->s_desc_size)
++#ifdef __KERNEL__
++# define EXT4_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_blocks_per_group)
++# define EXT4_DESC_PER_BLOCK(s) (EXT4_SB(s)->s_desc_per_block)
++# define EXT4_INODES_PER_GROUP(s) (EXT4_SB(s)->s_inodes_per_group)
++# define EXT4_DESC_PER_BLOCK_BITS(s) (EXT4_SB(s)->s_desc_per_block_bits)
++#else
++# define EXT4_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group)
++# define EXT4_DESC_PER_BLOCK(s) (EXT4_BLOCK_SIZE(s) / EXT4_DESC_SIZE(s))
++# define EXT4_INODES_PER_GROUP(s) ((s)->s_inodes_per_group)
++#endif
++
++/*
++ * Constants relative to the data blocks
++ */
++#define EXT4_NDIR_BLOCKS 12
++#define EXT4_IND_BLOCK EXT4_NDIR_BLOCKS
++#define EXT4_DIND_BLOCK (EXT4_IND_BLOCK + 1)
++#define EXT4_TIND_BLOCK (EXT4_DIND_BLOCK + 1)
++#define EXT4_N_BLOCKS (EXT4_TIND_BLOCK + 1)
++
++/*
++ * Inode flags
++ */
++#define EXT4_SECRM_FL 0x00000001 /* Secure deletion */
++#define EXT4_UNRM_FL 0x00000002 /* Undelete */
++#define EXT4_COMPR_FL 0x00000004 /* Compress file */
++#define EXT4_SYNC_FL 0x00000008 /* Synchronous updates */
++#define EXT4_IMMUTABLE_FL 0x00000010 /* Immutable file */
++#define EXT4_APPEND_FL 0x00000020 /* writes to file may only append */
++#define EXT4_NODUMP_FL 0x00000040 /* do not dump file */
++#define EXT4_NOATIME_FL 0x00000080 /* do not update atime */
++/* Reserved for compression usage... */
++#define EXT4_DIRTY_FL 0x00000100
++#define EXT4_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
++#define EXT4_NOCOMPR_FL 0x00000400 /* Don't compress */
++#define EXT4_ECOMPR_FL 0x00000800 /* Compression error */
++/* End compression flags --- maybe not all used */
++#define EXT4_INDEX_FL 0x00001000 /* hash-indexed directory */
++#define EXT4_IMAGIC_FL 0x00002000 /* AFS directory */
++#define EXT4_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
++#define EXT4_NOTAIL_FL 0x00008000 /* file tail should not be merged */
++#define EXT4_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */
++#define EXT4_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
++#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */
++#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
++#define EXT4_EXT_MIGRATE 0x00100000 /* Inode is migrating */
++#define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */
++
++#define EXT4_FL_USER_VISIBLE 0x000BDFFF /* User visible flags */
++#define EXT4_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */
++
++/*
++ * Inode dynamic state flags
++ */
++#define EXT4_STATE_JDATA 0x00000001 /* journaled data exists */
++#define EXT4_STATE_NEW 0x00000002 /* inode is newly created */
++#define EXT4_STATE_XATTR 0x00000004 /* has in-inode xattrs */
++#define EXT4_STATE_NO_EXPAND 0x00000008 /* No space for expansion */
++
++/* Used to pass group descriptor data when online resize is done */
++struct ext4_new_group_input {
++ __u32 group; /* Group number for this data */
++ __u64 block_bitmap; /* Absolute block number of block bitmap */
++ __u64 inode_bitmap; /* Absolute block number of inode bitmap */
++ __u64 inode_table; /* Absolute block number of inode table start */
++ __u32 blocks_count; /* Total number of blocks in this group */
++ __u16 reserved_blocks; /* Number of reserved blocks in this group */
++ __u16 unused;
+};
+
++/* The struct ext4_new_group_input in kernel space, with free_blocks_count */
++struct ext4_new_group_data {
++ __u32 group;
++ __u64 block_bitmap;
++ __u64 inode_bitmap;
++ __u64 inode_table;
++ __u32 blocks_count;
++ __u16 reserved_blocks;
++ __u16 unused;
++ __u32 free_blocks_count;
++};
+
-+static inline void set_version(struct dlm_plock_info *info)
++/*
++ * Following is used by preallocation code to tell get_blocks() that we
++ * want uninitialzed extents.
++ */
++#define EXT4_CREATE_UNINITIALIZED_EXT 2
++
++/*
++ * ioctl commands
++ */
++#define EXT4_IOC_GETFLAGS FS_IOC_GETFLAGS
++#define EXT4_IOC_SETFLAGS FS_IOC_SETFLAGS
++#define EXT4_IOC_GETVERSION _IOR('f', 3, long)
++#define EXT4_IOC_SETVERSION _IOW('f', 4, long)
++#define EXT4_IOC_GROUP_EXTEND _IOW('f', 7, unsigned long)
++#define EXT4_IOC_GROUP_ADD _IOW('f', 8,struct ext4_new_group_input)
++#define EXT4_IOC_GETVERSION_OLD FS_IOC_GETVERSION
++#define EXT4_IOC_SETVERSION_OLD FS_IOC_SETVERSION
++#ifdef CONFIG_JBD2_DEBUG
++#define EXT4_IOC_WAIT_FOR_READONLY _IOR('f', 99, long)
++#endif
++#define EXT4_IOC_GETRSVSZ _IOR('f', 5, long)
++#define EXT4_IOC_SETRSVSZ _IOW('f', 6, long)
++#define EXT4_IOC_MIGRATE _IO('f', 7)
++
++/*
++ * ioctl commands in 32 bit emulation
++ */
++#define EXT4_IOC32_GETFLAGS FS_IOC32_GETFLAGS
++#define EXT4_IOC32_SETFLAGS FS_IOC32_SETFLAGS
++#define EXT4_IOC32_GETVERSION _IOR('f', 3, int)
++#define EXT4_IOC32_SETVERSION _IOW('f', 4, int)
++#define EXT4_IOC32_GETRSVSZ _IOR('f', 5, int)
++#define EXT4_IOC32_SETRSVSZ _IOW('f', 6, int)
++#define EXT4_IOC32_GROUP_EXTEND _IOW('f', 7, unsigned int)
++#ifdef CONFIG_JBD2_DEBUG
++#define EXT4_IOC32_WAIT_FOR_READONLY _IOR('f', 99, int)
++#endif
++#define EXT4_IOC32_GETVERSION_OLD FS_IOC32_GETVERSION
++#define EXT4_IOC32_SETVERSION_OLD FS_IOC32_SETVERSION
++
++
++/*
++ * Mount options
++ */
++struct ext4_mount_options {
++ unsigned long s_mount_opt;
++ uid_t s_resuid;
++ gid_t s_resgid;
++ unsigned long s_commit_interval;
++#ifdef CONFIG_QUOTA
++ int s_jquota_fmt;
++ char *s_qf_names[MAXQUOTAS];
++#endif
++};
++
++/*
++ * Structure of an inode on the disk
++ */
++struct ext4_inode {
++ __le16 i_mode; /* File mode */
++ __le16 i_uid; /* Low 16 bits of Owner Uid */
++ __le32 i_size_lo; /* Size in bytes */
++ __le32 i_atime; /* Access time */
++ __le32 i_ctime; /* Inode Change time */
++ __le32 i_mtime; /* Modification time */
++ __le32 i_dtime; /* Deletion Time */
++ __le16 i_gid; /* Low 16 bits of Group Id */
++ __le16 i_links_count; /* Links count */
++ __le32 i_blocks_lo; /* Blocks count */
++ __le32 i_flags; /* File flags */
++ union {
++ struct {
++ __le32 l_i_version;
++ } linux1;
++ struct {
++ __u32 h_i_translator;
++ } hurd1;
++ struct {
++ __u32 m_i_reserved1;
++ } masix1;
++ } osd1; /* OS dependent 1 */
++ __le32 i_block[EXT4_N_BLOCKS];/* Pointers to blocks */
++ __le32 i_generation; /* File version (for NFS) */
++ __le32 i_file_acl_lo; /* File ACL */
++ __le32 i_size_high;
++ __le32 i_obso_faddr; /* Obsoleted fragment address */
++ union {
++ struct {
++ __le16 l_i_blocks_high; /* were l_i_reserved1 */
++ __le16 l_i_file_acl_high;
++ __le16 l_i_uid_high; /* these 2 fields */
++ __le16 l_i_gid_high; /* were reserved2[0] */
++ __u32 l_i_reserved2;
++ } linux2;
++ struct {
++ __le16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
++ __u16 h_i_mode_high;
++ __u16 h_i_uid_high;
++ __u16 h_i_gid_high;
++ __u32 h_i_author;
++ } hurd2;
++ struct {
++ __le16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
++ __le16 m_i_file_acl_high;
++ __u32 m_i_reserved2[2];
++ } masix2;
++ } osd2; /* OS dependent 2 */
++ __le16 i_extra_isize;
++ __le16 i_pad1;
++ __le32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */
++ __le32 i_mtime_extra; /* extra Modification time(nsec << 2 | epoch) */
++ __le32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */
++ __le32 i_crtime; /* File Creation time */
++ __le32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */
++ __le32 i_version_hi; /* high 32 bits for 64-bit version */
++};
++
++
++#define EXT4_EPOCH_BITS 2
++#define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
++#define EXT4_NSEC_MASK (~0UL << EXT4_EPOCH_BITS)
++
++/*
++ * Extended fields will fit into an inode if the filesystem was formatted
++ * with large inodes (-I 256 or larger) and there are not currently any EAs
++ * consuming all of the available space. For new inodes we always reserve
++ * enough space for the kernel's known extended fields, but for inodes
++ * created with an old kernel this might not have been the case. None of
++ * the extended inode fields is critical for correct filesystem operation.
++ * This macro checks if a certain field fits in the inode. Note that
++ * inode-size = GOOD_OLD_INODE_SIZE + i_extra_isize
++ */
++#define EXT4_FITS_IN_INODE(ext4_inode, einode, field) \
++ ((offsetof(typeof(*ext4_inode), field) + \
++ sizeof((ext4_inode)->field)) \
++ <= (EXT4_GOOD_OLD_INODE_SIZE + \
++ (einode)->i_extra_isize)) \
++
++static inline __le32 ext4_encode_extra_time(struct timespec *time)
++{
++ return cpu_to_le32((sizeof(time->tv_sec) > 4 ?
++ time->tv_sec >> 32 : 0) |
++ ((time->tv_nsec << 2) & EXT4_NSEC_MASK));
++}
++
++static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
++{
++ if (sizeof(time->tv_sec) > 4)
++ time->tv_sec |= (__u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK)
++ << 32;
++ time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> 2;
++}
++
++#define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \
++do { \
++ (raw_inode)->xtime = cpu_to_le32((inode)->xtime.tv_sec); \
++ if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) \
++ (raw_inode)->xtime ## _extra = \
++ ext4_encode_extra_time(&(inode)->xtime); \
++} while (0)
++
++#define EXT4_EINODE_SET_XTIME(xtime, einode, raw_inode) \
++do { \
++ if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \
++ (raw_inode)->xtime = cpu_to_le32((einode)->xtime.tv_sec); \
++ if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra)) \
++ (raw_inode)->xtime ## _extra = \
++ ext4_encode_extra_time(&(einode)->xtime); \
++} while (0)
++
++#define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode) \
++do { \
++ (inode)->xtime.tv_sec = (signed)le32_to_cpu((raw_inode)->xtime); \
++ if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) \
++ ext4_decode_extra_time(&(inode)->xtime, \
++ raw_inode->xtime ## _extra); \
++} while (0)
++
++#define EXT4_EINODE_GET_XTIME(xtime, einode, raw_inode) \
++do { \
++ if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \
++ (einode)->xtime.tv_sec = \
++ (signed)le32_to_cpu((raw_inode)->xtime); \
++ if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra)) \
++ ext4_decode_extra_time(&(einode)->xtime, \
++ raw_inode->xtime ## _extra); \
++} while (0)
++
++#define i_disk_version osd1.linux1.l_i_version
++
++#if defined(__KERNEL__) || defined(__linux__)
++#define i_reserved1 osd1.linux1.l_i_reserved1
++#define i_file_acl_high osd2.linux2.l_i_file_acl_high
++#define i_blocks_high osd2.linux2.l_i_blocks_high
++#define i_uid_low i_uid
++#define i_gid_low i_gid
++#define i_uid_high osd2.linux2.l_i_uid_high
++#define i_gid_high osd2.linux2.l_i_gid_high
++#define i_reserved2 osd2.linux2.l_i_reserved2
++
++#elif defined(__GNU__)
++
++#define i_translator osd1.hurd1.h_i_translator
++#define i_uid_high osd2.hurd2.h_i_uid_high
++#define i_gid_high osd2.hurd2.h_i_gid_high
++#define i_author osd2.hurd2.h_i_author
++
++#elif defined(__masix__)
++
++#define i_reserved1 osd1.masix1.m_i_reserved1
++#define i_file_acl_high osd2.masix2.m_i_file_acl_high
++#define i_reserved2 osd2.masix2.m_i_reserved2
++
++#endif /* defined(__KERNEL__) || defined(__linux__) */
++
++/*
++ * File system states
++ */
++#define EXT4_VALID_FS 0x0001 /* Unmounted cleanly */
++#define EXT4_ERROR_FS 0x0002 /* Errors detected */
++#define EXT4_ORPHAN_FS 0x0004 /* Orphans being recovered */
++
++/*
++ * Misc. filesystem flags
++ */
++#define EXT2_FLAGS_SIGNED_HASH 0x0001 /* Signed dirhash in use */
++#define EXT2_FLAGS_UNSIGNED_HASH 0x0002 /* Unsigned dirhash in use */
++#define EXT2_FLAGS_TEST_FILESYS 0x0004 /* to test development code */
++
++/*
++ * Mount flags
++ */
++#define EXT4_MOUNT_CHECK 0x00001 /* Do mount-time checks */
++#define EXT4_MOUNT_OLDALLOC 0x00002 /* Don't use the new Orlov allocator */
++#define EXT4_MOUNT_GRPID 0x00004 /* Create files with directory's group */
++#define EXT4_MOUNT_DEBUG 0x00008 /* Some debugging messages */
++#define EXT4_MOUNT_ERRORS_CONT 0x00010 /* Continue on errors */
++#define EXT4_MOUNT_ERRORS_RO 0x00020 /* Remount fs ro on errors */
++#define EXT4_MOUNT_ERRORS_PANIC 0x00040 /* Panic on errors */
++#define EXT4_MOUNT_MINIX_DF 0x00080 /* Mimics the Minix statfs */
++#define EXT4_MOUNT_NOLOAD 0x00100 /* Don't use existing journal*/
++#define EXT4_MOUNT_ABORT 0x00200 /* Fatal error detected */
++#define EXT4_MOUNT_DATA_FLAGS 0x00C00 /* Mode for data writes: */
++#define EXT4_MOUNT_JOURNAL_DATA 0x00400 /* Write data to journal */
++#define EXT4_MOUNT_ORDERED_DATA 0x00800 /* Flush data before commit */
++#define EXT4_MOUNT_WRITEBACK_DATA 0x00C00 /* No data ordering */
++#define EXT4_MOUNT_UPDATE_JOURNAL 0x01000 /* Update the journal format */
++#define EXT4_MOUNT_NO_UID32 0x02000 /* Disable 32-bit UIDs */
++#define EXT4_MOUNT_XATTR_USER 0x04000 /* Extended user attributes */
++#define EXT4_MOUNT_POSIX_ACL 0x08000 /* POSIX Access Control Lists */
++#define EXT4_MOUNT_RESERVATION 0x10000 /* Preallocation */
++#define EXT4_MOUNT_BARRIER 0x20000 /* Use block barriers */
++#define EXT4_MOUNT_NOBH 0x40000 /* No bufferheads */
++#define EXT4_MOUNT_QUOTA 0x80000 /* Some quota option set */
++#define EXT4_MOUNT_USRQUOTA 0x100000 /* "old" user quota */
++#define EXT4_MOUNT_GRPQUOTA 0x200000 /* "old" group quota */
++#define EXT4_MOUNT_EXTENTS 0x400000 /* Extents support */
++#define EXT4_MOUNT_JOURNAL_CHECKSUM 0x800000 /* Journal checksums */
++#define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */
++#define EXT4_MOUNT_I_VERSION 0x2000000 /* i_version support */
++#define EXT4_MOUNT_MBALLOC 0x4000000 /* Buddy allocation support */
++/* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */
++#ifndef _LINUX_EXT2_FS_H
++#define clear_opt(o, opt) o &= ~EXT4_MOUNT_##opt
++#define set_opt(o, opt) o |= EXT4_MOUNT_##opt
++#define test_opt(sb, opt) (EXT4_SB(sb)->s_mount_opt & \
++ EXT4_MOUNT_##opt)
++#else
++#define EXT2_MOUNT_NOLOAD EXT4_MOUNT_NOLOAD
++#define EXT2_MOUNT_ABORT EXT4_MOUNT_ABORT
++#define EXT2_MOUNT_DATA_FLAGS EXT4_MOUNT_DATA_FLAGS
++#endif
++
++#define ext4_set_bit ext2_set_bit
++#define ext4_set_bit_atomic ext2_set_bit_atomic
++#define ext4_clear_bit ext2_clear_bit
++#define ext4_clear_bit_atomic ext2_clear_bit_atomic
++#define ext4_test_bit ext2_test_bit
++#define ext4_find_first_zero_bit ext2_find_first_zero_bit
++#define ext4_find_next_zero_bit ext2_find_next_zero_bit
++#define ext4_find_next_bit ext2_find_next_bit
++
++/*
++ * Maximal mount counts between two filesystem checks
++ */
++#define EXT4_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
++#define EXT4_DFL_CHECKINTERVAL 0 /* Don't use interval check */
++
++/*
++ * Behaviour when detecting errors
++ */
++#define EXT4_ERRORS_CONTINUE 1 /* Continue execution */
++#define EXT4_ERRORS_RO 2 /* Remount fs read-only */
++#define EXT4_ERRORS_PANIC 3 /* Panic */
++#define EXT4_ERRORS_DEFAULT EXT4_ERRORS_CONTINUE
++
++/*
++ * Structure of the super block
++ */
++struct ext4_super_block {
++/*00*/ __le32 s_inodes_count; /* Inodes count */
++ __le32 s_blocks_count_lo; /* Blocks count */
++ __le32 s_r_blocks_count_lo; /* Reserved blocks count */
++ __le32 s_free_blocks_count_lo; /* Free blocks count */
++/*10*/ __le32 s_free_inodes_count; /* Free inodes count */
++ __le32 s_first_data_block; /* First Data Block */
++ __le32 s_log_block_size; /* Block size */
++ __le32 s_obso_log_frag_size; /* Obsoleted fragment size */
++/*20*/ __le32 s_blocks_per_group; /* # Blocks per group */
++ __le32 s_obso_frags_per_group; /* Obsoleted fragments per group */
++ __le32 s_inodes_per_group; /* # Inodes per group */
++ __le32 s_mtime; /* Mount time */
++/*30*/ __le32 s_wtime; /* Write time */
++ __le16 s_mnt_count; /* Mount count */
++ __le16 s_max_mnt_count; /* Maximal mount count */
++ __le16 s_magic; /* Magic signature */
++ __le16 s_state; /* File system state */
++ __le16 s_errors; /* Behaviour when detecting errors */
++ __le16 s_minor_rev_level; /* minor revision level */
++/*40*/ __le32 s_lastcheck; /* time of last check */
++ __le32 s_checkinterval; /* max. time between checks */
++ __le32 s_creator_os; /* OS */
++ __le32 s_rev_level; /* Revision level */
++/*50*/ __le16 s_def_resuid; /* Default uid for reserved blocks */
++ __le16 s_def_resgid; /* Default gid for reserved blocks */
++ /*
++ * These fields are for EXT4_DYNAMIC_REV superblocks only.
++ *
++ * Note: the difference between the compatible feature set and
++ * the incompatible feature set is that if there is a bit set
++ * in the incompatible feature set that the kernel doesn't
++ * know about, it should refuse to mount the filesystem.
++ *
++ * e2fsck's requirements are more strict; if it doesn't know
++ * about a feature in either the compatible or incompatible
++ * feature set, it must abort and not try to meddle with
++ * things it doesn't understand...
++ */
++ __le32 s_first_ino; /* First non-reserved inode */
++ __le16 s_inode_size; /* size of inode structure */
++ __le16 s_block_group_nr; /* block group # of this superblock */
++ __le32 s_feature_compat; /* compatible feature set */
++/*60*/ __le32 s_feature_incompat; /* incompatible feature set */
++ __le32 s_feature_ro_compat; /* readonly-compatible feature set */
++/*68*/ __u8 s_uuid[16]; /* 128-bit uuid for volume */
++/*78*/ char s_volume_name[16]; /* volume name */
++/*88*/ char s_last_mounted[64]; /* directory where last mounted */
++/*C8*/ __le32 s_algorithm_usage_bitmap; /* For compression */
++ /*
++ * Performance hints. Directory preallocation should only
++ * happen if the EXT4_FEATURE_COMPAT_DIR_PREALLOC flag is on.
++ */
++ __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
++ __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
++ __le16 s_reserved_gdt_blocks; /* Per group desc for online growth */
++ /*
++ * Journaling support valid if EXT4_FEATURE_COMPAT_HAS_JOURNAL set.
++ */
++/*D0*/ __u8 s_journal_uuid[16]; /* uuid of journal superblock */
++/*E0*/ __le32 s_journal_inum; /* inode number of journal file */
++ __le32 s_journal_dev; /* device number of journal file */
++ __le32 s_last_orphan; /* start of list of inodes to delete */
++ __le32 s_hash_seed[4]; /* HTREE hash seed */
++ __u8 s_def_hash_version; /* Default hash version to use */
++ __u8 s_reserved_char_pad;
++ __le16 s_desc_size; /* size of group descriptor */
++/*100*/ __le32 s_default_mount_opts;
++ __le32 s_first_meta_bg; /* First metablock block group */
++ __le32 s_mkfs_time; /* When the filesystem was created */
++ __le32 s_jnl_blocks[17]; /* Backup of the journal inode */
++ /* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */
++/*150*/ __le32 s_blocks_count_hi; /* Blocks count */
++ __le32 s_r_blocks_count_hi; /* Reserved blocks count */
++ __le32 s_free_blocks_count_hi; /* Free blocks count */
++ __le16 s_min_extra_isize; /* All inodes have at least # bytes */
++ __le16 s_want_extra_isize; /* New inodes should reserve # bytes */
++ __le32 s_flags; /* Miscellaneous flags */
++ __le16 s_raid_stride; /* RAID stride */
++ __le16 s_mmp_interval; /* # seconds to wait in MMP checking */
++ __le64 s_mmp_block; /* Block for multi-mount protection */
++ __le32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/
++ __u32 s_reserved[163]; /* Padding to the end of the block */
++};
++
++#ifdef __KERNEL__
++static inline struct ext4_sb_info * EXT4_SB(struct super_block *sb)
+{
-+ info->version[0] = DLM_PLOCK_VERSION_MAJOR;
-+ info->version[1] = DLM_PLOCK_VERSION_MINOR;
-+ info->version[2] = DLM_PLOCK_VERSION_PATCH;
++ return sb->s_fs_info;
+}
-+
-+static int check_version(struct dlm_plock_info *info)
++static inline struct ext4_inode_info *EXT4_I(struct inode *inode)
+{
-+ 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;
++ return container_of(inode, struct ext4_inode_info, vfs_inode);
+}
+
-+static void send_op(struct plock_op *op)
++static inline struct timespec ext4_current_time(struct inode *inode)
+{
-+ 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);
++ return (inode->i_sb->s_time_gran < NSEC_PER_SEC) ?
++ current_fs_time(inode->i_sb) : CURRENT_TIME_SEC;
+}
+
-+int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
-+ int cmd, struct file_lock *fl)
++
++static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
+{
-+ struct dlm_ls *ls;
-+ struct plock_op *op;
-+ struct plock_xop *xop;
-+ int rv;
++ return ino == EXT4_ROOT_INO ||
++ ino == EXT4_JOURNAL_INO ||
++ ino == EXT4_RESIZE_INO ||
++ (ino >= EXT4_FIRST_INO(sb) &&
++ ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
++}
++#else
++/* Assume that user mode programs are passing in an ext4fs superblock, not
++ * a kernel struct super_block. This will allow us to call the feature-test
++ * macros from user land. */
++#define EXT4_SB(sb) (sb)
++#endif
+
-+ ls = dlm_find_lockspace_local(lockspace);
-+ if (!ls)
-+ return -EINVAL;
++#define NEXT_ORPHAN(inode) EXT4_I(inode)->i_dtime
+
-+ xop = kzalloc(sizeof(*xop), GFP_KERNEL);
-+ if (!xop) {
-+ rv = -ENOMEM;
-+ goto out;
-+ }
++/*
++ * Codes for operating systems
++ */
++#define EXT4_OS_LINUX 0
++#define EXT4_OS_HURD 1
++#define EXT4_OS_MASIX 2
++#define EXT4_OS_FREEBSD 3
++#define EXT4_OS_LITES 4
+
-+ 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;
-+ }
++/*
++ * Revision levels
++ */
++#define EXT4_GOOD_OLD_REV 0 /* The good old (original) format */
++#define EXT4_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
+
-+ send_op(op);
++#define EXT4_CURRENT_REV EXT4_GOOD_OLD_REV
++#define EXT4_MAX_SUPP_REV EXT4_DYNAMIC_REV
+
-+ if (xop->callback == NULL)
-+ wait_event(recv_wq, (op->done != 0));
-+ else {
-+ rv = -EINPROGRESS;
-+ goto out;
-+ }
++#define EXT4_GOOD_OLD_INODE_SIZE 128
+
-+ 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);
++/*
++ * Feature set definitions
++ */
+
-+ rv = op->info.rv;
++#define EXT4_HAS_COMPAT_FEATURE(sb,mask) \
++ ( EXT4_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask) )
++#define EXT4_HAS_RO_COMPAT_FEATURE(sb,mask) \
++ ( EXT4_SB(sb)->s_es->s_feature_ro_compat & cpu_to_le32(mask) )
++#define EXT4_HAS_INCOMPAT_FEATURE(sb,mask) \
++ ( EXT4_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask) )
++#define EXT4_SET_COMPAT_FEATURE(sb,mask) \
++ EXT4_SB(sb)->s_es->s_feature_compat |= cpu_to_le32(mask)
++#define EXT4_SET_RO_COMPAT_FEATURE(sb,mask) \
++ EXT4_SB(sb)->s_es->s_feature_ro_compat |= cpu_to_le32(mask)
++#define EXT4_SET_INCOMPAT_FEATURE(sb,mask) \
++ EXT4_SB(sb)->s_es->s_feature_incompat |= cpu_to_le32(mask)
++#define EXT4_CLEAR_COMPAT_FEATURE(sb,mask) \
++ EXT4_SB(sb)->s_es->s_feature_compat &= ~cpu_to_le32(mask)
++#define EXT4_CLEAR_RO_COMPAT_FEATURE(sb,mask) \
++ EXT4_SB(sb)->s_es->s_feature_ro_compat &= ~cpu_to_le32(mask)
++#define EXT4_CLEAR_INCOMPAT_FEATURE(sb,mask) \
++ EXT4_SB(sb)->s_es->s_feature_incompat &= ~cpu_to_le32(mask)
+
-+ if (!rv) {
-+ if (posix_lock_file_wait(file, fl) < 0)
-+ log_error(ls, "dlm_posix_lock: vfs lock error %llx",
-+ (unsigned long long)number);
-+ }
++#define EXT4_FEATURE_COMPAT_DIR_PREALLOC 0x0001
++#define EXT4_FEATURE_COMPAT_IMAGIC_INODES 0x0002
++#define EXT4_FEATURE_COMPAT_HAS_JOURNAL 0x0004
++#define EXT4_FEATURE_COMPAT_EXT_ATTR 0x0008
++#define EXT4_FEATURE_COMPAT_RESIZE_INODE 0x0010
++#define EXT4_FEATURE_COMPAT_DIR_INDEX 0x0020
+
-+ kfree(xop);
-+out:
-+ dlm_put_lockspace(ls);
-+ return rv;
-+}
-+EXPORT_SYMBOL_GPL(dlm_posix_lock);
++#define EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
++#define EXT4_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
++#define EXT4_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
++#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008
++#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
++#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020
++#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
+
-+/* 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;
++#define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001
++#define EXT4_FEATURE_INCOMPAT_FILETYPE 0x0002
++#define EXT4_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
++#define EXT4_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
++#define EXT4_FEATURE_INCOMPAT_META_BG 0x0010
++#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
++#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
++#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
++#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
+
-+ 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);
++#define EXT4_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
++#define EXT4_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \
++ EXT4_FEATURE_INCOMPAT_RECOVER| \
++ EXT4_FEATURE_INCOMPAT_META_BG| \
++ EXT4_FEATURE_INCOMPAT_EXTENTS| \
++ EXT4_FEATURE_INCOMPAT_64BIT| \
++ EXT4_FEATURE_INCOMPAT_FLEX_BG)
++#define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
++ EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
++ EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \
++ EXT4_FEATURE_RO_COMPAT_DIR_NLINK | \
++ EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE | \
++ EXT4_FEATURE_RO_COMPAT_BTREE_DIR |\
++ EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
+
-+ /* check if the following 2 are still valid or make a copy */
-+ file = xop->file;
-+ flc = &xop->flc;
-+ fl = xop->fl;
-+ notify = xop->callback;
++/*
++ * Default values for user and/or group using reserved blocks
++ */
++#define EXT4_DEF_RESUID 0
++#define EXT4_DEF_RESGID 0
+
-+ if (op->info.rv) {
-+ notify(flc, NULL, op->info.rv);
-+ goto out;
-+ }
++/*
++ * Default mount options
++ */
++#define EXT4_DEFM_DEBUG 0x0001
++#define EXT4_DEFM_BSDGROUPS 0x0002
++#define EXT4_DEFM_XATTR_USER 0x0004
++#define EXT4_DEFM_ACL 0x0008
++#define EXT4_DEFM_UID16 0x0010
++#define EXT4_DEFM_JMODE 0x0060
++#define EXT4_DEFM_JMODE_DATA 0x0020
++#define EXT4_DEFM_JMODE_ORDERED 0x0040
++#define EXT4_DEFM_JMODE_WBACK 0x0060
+
-+ /* 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);
-+ }
++/*
++ * Structure of a directory entry
++ */
++#define EXT4_NAME_LEN 255
+
-+ 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;
-+ }
++struct ext4_dir_entry {
++ __le32 inode; /* Inode number */
++ __le16 rec_len; /* Directory entry length */
++ __le16 name_len; /* Name length */
++ char name[EXT4_NAME_LEN]; /* File name */
++};
+
-+out:
-+ kfree(xop);
-+ return rv;
++/*
++ * The new version of the directory entry. Since EXT4 structures are
++ * stored in intel byte order, and the name_len field could never be
++ * bigger than 255 chars, it's safe to reclaim the extra byte for the
++ * file_type field.
++ */
++struct ext4_dir_entry_2 {
++ __le32 inode; /* Inode number */
++ __le16 rec_len; /* Directory entry length */
++ __u8 name_len; /* Name length */
++ __u8 file_type;
++ char name[EXT4_NAME_LEN]; /* File name */
++};
++
++/*
++ * Ext4 directory file types. Only the low 3 bits are used. The
++ * other bits are reserved for now.
++ */
++#define EXT4_FT_UNKNOWN 0
++#define EXT4_FT_REG_FILE 1
++#define EXT4_FT_DIR 2
++#define EXT4_FT_CHRDEV 3
++#define EXT4_FT_BLKDEV 4
++#define EXT4_FT_FIFO 5
++#define EXT4_FT_SOCK 6
++#define EXT4_FT_SYMLINK 7
++
++#define EXT4_FT_MAX 8
++
++/*
++ * EXT4_DIR_PAD defines the directory entries boundaries
++ *
++ * NOTE: It must be a multiple of 4
++ */
++#define EXT4_DIR_PAD 4
++#define EXT4_DIR_ROUND (EXT4_DIR_PAD - 1)
++#define EXT4_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT4_DIR_ROUND) & \
++ ~EXT4_DIR_ROUND)
++#define EXT4_MAX_REC_LEN ((1<<16)-1)
++
++static inline unsigned ext4_rec_len_from_disk(__le16 dlen)
++{
++ unsigned len = le16_to_cpu(dlen);
++
++ if (len == EXT4_MAX_REC_LEN)
++ return 1 << 16;
++ return len;
+}
+
-+int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
-+ struct file_lock *fl)
++static inline __le16 ext4_rec_len_to_disk(unsigned len)
+{
-+ struct dlm_ls *ls;
-+ struct plock_op *op;
-+ int rv;
++ if (len == (1 << 16))
++ return cpu_to_le16(EXT4_MAX_REC_LEN);
++ else if (len > (1 << 16))
++ BUG();
++ return cpu_to_le16(len);
++}
+
-+ ls = dlm_find_lockspace_local(lockspace);
-+ if (!ls)
-+ return -EINVAL;
++/*
++ * Hash Tree Directory indexing
++ * (c) Daniel Phillips, 2001
++ */
+
-+ op = kzalloc(sizeof(*op), GFP_KERNEL);
-+ if (!op) {
-+ rv = -ENOMEM;
-+ goto out;
-+ }
++#define is_dx(dir) (EXT4_HAS_COMPAT_FEATURE(dir->i_sb, \
++ EXT4_FEATURE_COMPAT_DIR_INDEX) && \
++ (EXT4_I(dir)->i_flags & EXT4_INDEX_FL))
++#define EXT4_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT4_LINK_MAX)
++#define EXT4_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1)
+
-+ if (posix_lock_file_wait(file, fl) < 0)
-+ log_error(ls, "dlm_posix_unlock: vfs unlock error %llx",
-+ (unsigned long long)number);
++/* Legal values for the dx_root hash_version field: */
+
-+ 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;
++#define DX_HASH_LEGACY 0
++#define DX_HASH_HALF_MD4 1
++#define DX_HASH_TEA 2
+
-+ send_op(op);
-+ wait_event(recv_wq, (op->done != 0));
++#ifdef __KERNEL__
+
-+ 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);
++/* hash info structure used by the directory hash */
++struct dx_hash_info
++{
++ u32 hash;
++ u32 minor_hash;
++ int hash_version;
++ u32 *seed;
++};
+
-+ rv = op->info.rv;
++#define EXT4_HTREE_EOF 0x7fffffff
+
-+ if (rv == -ENOENT)
-+ rv = 0;
++/*
++ * Control parameters used by ext4_htree_next_block
++ */
++#define HASH_NB_ALWAYS 1
+
-+ kfree(op);
-+out:
-+ dlm_put_lockspace(ls);
-+ return rv;
++
++/*
++ * Describe an inode's exact location on disk and in memory
++ */
++struct ext4_iloc
++{
++ struct buffer_head *bh;
++ unsigned long offset;
++ ext4_group_t block_group;
++};
++
++static inline struct ext4_inode *ext4_raw_inode(struct ext4_iloc *iloc)
++{
++ return (struct ext4_inode *) (iloc->bh->b_data + iloc->offset);
+}
-+EXPORT_SYMBOL_GPL(dlm_posix_unlock);
+
-+int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file,
-+ struct file_lock *fl)
++/*
++ * This structure is stuffed into the struct file's private_data field
++ * for directories. It is where we put information so that we can do
++ * readdir operations in hash tree order.
++ */
++struct dir_private_info {
++ struct rb_root root;
++ struct rb_node *curr_node;
++ struct fname *extra_fname;
++ loff_t last_pos;
++ __u32 curr_hash;
++ __u32 curr_minor_hash;
++ __u32 next_hash;
++};
++
++/* calculate the first block number of the group */
++static inline ext4_fsblk_t
++ext4_group_first_block_no(struct super_block *sb, ext4_group_t group_no)
++{
++ return group_no * (ext4_fsblk_t)EXT4_BLOCKS_PER_GROUP(sb) +
++ le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
++}
++
++/*
++ * Special error return code only used by dx_probe() and its callers.
++ */
++#define ERR_BAD_DX_DIR -75000
++
++void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
++ unsigned long *blockgrpp, ext4_grpblk_t *offsetp);
++
++/*
++ * Function prototypes
++ */
++
++/*
++ * Ok, these declarations are also in <linux/kernel.h> but none of the
++ * ext4 source programs needs to include it so they are duplicated here.
++ */
++# define NORET_TYPE /**/
++# define ATTRIB_NORET __attribute__((noreturn))
++# define NORET_AND noreturn,
++
++/* balloc.c */
++extern unsigned int ext4_block_group(struct super_block *sb,
++ ext4_fsblk_t blocknr);
++extern ext4_grpblk_t ext4_block_group_offset(struct super_block *sb,
++ ext4_fsblk_t blocknr);
++extern int ext4_bg_has_super(struct super_block *sb, ext4_group_t group);
++extern unsigned long ext4_bg_num_gdb(struct super_block *sb,
++ ext4_group_t group);
++extern ext4_fsblk_t ext4_new_block (handle_t *handle, struct inode *inode,
++ ext4_fsblk_t goal, int *errp);
++extern ext4_fsblk_t ext4_new_blocks (handle_t *handle, struct inode *inode,
++ ext4_fsblk_t goal, unsigned long *count, int *errp);
++extern ext4_fsblk_t ext4_new_blocks_old(handle_t *handle, struct inode *inode,
++ ext4_fsblk_t goal, unsigned long *count, int *errp);
++extern void ext4_free_blocks (handle_t *handle, struct inode *inode,
++ ext4_fsblk_t block, unsigned long count, int metadata);
++extern void ext4_free_blocks_sb (handle_t *handle, struct super_block *sb,
++ ext4_fsblk_t block, unsigned long count,
++ unsigned long *pdquot_freed_blocks);
++extern ext4_fsblk_t ext4_count_free_blocks (struct super_block *);
++extern void ext4_check_blocks_bitmap (struct super_block *);
++extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
++ ext4_group_t block_group,
++ struct buffer_head ** bh);
++extern int ext4_should_retry_alloc(struct super_block *sb, int *retries);
++extern void ext4_init_block_alloc_info(struct inode *);
++extern void ext4_rsv_window_add(struct super_block *sb, struct ext4_reserve_window_node *rsv);
++
++/* dir.c */
++extern int ext4_check_dir_entry(const char *, struct inode *,
++ struct ext4_dir_entry_2 *,
++ struct buffer_head *, unsigned long);
++extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
++ __u32 minor_hash,
++ struct ext4_dir_entry_2 *dirent);
++extern void ext4_htree_free_dir_info(struct dir_private_info *p);
++
++/* fsync.c */
++extern int ext4_sync_file (struct file *, struct dentry *, int);
++
++/* hash.c */
++extern int ext4fs_dirhash(const char *name, int len, struct
++ dx_hash_info *hinfo);
++
++/* ialloc.c */
++extern struct inode * ext4_new_inode (handle_t *, struct inode *, int);
++extern void ext4_free_inode (handle_t *, struct inode *);
++extern struct inode * ext4_orphan_get (struct super_block *, unsigned long);
++extern unsigned long ext4_count_free_inodes (struct super_block *);
++extern unsigned long ext4_count_dirs (struct super_block *);
++extern void ext4_check_inodes_bitmap (struct super_block *);
++extern unsigned long ext4_count_free (struct buffer_head *, unsigned);
++
++/* mballoc.c */
++extern long ext4_mb_stats;
++extern long ext4_mb_max_to_scan;
++extern int ext4_mb_init(struct super_block *, int);
++extern int ext4_mb_release(struct super_block *);
++extern ext4_fsblk_t ext4_mb_new_blocks(handle_t *,
++ struct ext4_allocation_request *, int *);
++extern int ext4_mb_reserve_blocks(struct super_block *, int);
++extern void ext4_mb_discard_inode_preallocations(struct inode *);
++extern int __init init_ext4_mballoc(void);
++extern void exit_ext4_mballoc(void);
++extern void ext4_mb_free_blocks(handle_t *, struct inode *,
++ unsigned long, unsigned long, int, unsigned long *);
++
++
++/* inode.c */
++int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
++ struct buffer_head *bh, ext4_fsblk_t blocknr);
++struct buffer_head *ext4_getblk(handle_t *, struct inode *,
++ ext4_lblk_t, int, int *);
++struct buffer_head *ext4_bread(handle_t *, struct inode *,
++ ext4_lblk_t, int, int *);
++int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
++ ext4_lblk_t iblock, unsigned long maxblocks,
++ struct buffer_head *bh_result,
++ int create, int extend_disksize);
++
++extern struct inode *ext4_iget(struct super_block *, unsigned long);
++extern int ext4_write_inode (struct inode *, int);
++extern int ext4_setattr (struct dentry *, struct iattr *);
++extern void ext4_delete_inode (struct inode *);
++extern int ext4_sync_inode (handle_t *, struct inode *);
++extern void ext4_discard_reservation (struct inode *);
++extern void ext4_dirty_inode(struct inode *);
++extern int ext4_change_inode_journal_flag(struct inode *, int);
++extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *);
++extern void ext4_truncate (struct inode *);
++extern void ext4_set_inode_flags(struct inode *);
++extern void ext4_get_inode_flags(struct ext4_inode_info *);
++extern void ext4_set_aops(struct inode *inode);
++extern int ext4_writepage_trans_blocks(struct inode *);
++extern int ext4_block_truncate_page(handle_t *handle, struct page *page,
++ struct address_space *mapping, loff_t from);
++
++/* ioctl.c */
++extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
++extern long ext4_compat_ioctl (struct file *, unsigned int, unsigned long);
++
++/* migrate.c */
++extern int ext4_ext_migrate(struct inode *, struct file *, unsigned int,
++ unsigned long);
++/* namei.c */
++extern int ext4_orphan_add(handle_t *, struct inode *);
++extern int ext4_orphan_del(handle_t *, struct inode *);
++extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
++ __u32 start_minor_hash, __u32 *next_hash);
++
++/* resize.c */
++extern int ext4_group_add(struct super_block *sb,
++ struct ext4_new_group_data *input);
++extern int ext4_group_extend(struct super_block *sb,
++ struct ext4_super_block *es,
++ ext4_fsblk_t n_blocks_count);
++
++/* super.c */
++extern void ext4_error (struct super_block *, const char *, const char *, ...)
++ __attribute__ ((format (printf, 3, 4)));
++extern void __ext4_std_error (struct super_block *, const char *, int);
++extern void ext4_abort (struct super_block *, const char *, const char *, ...)
++ __attribute__ ((format (printf, 3, 4)));
++extern void ext4_warning (struct super_block *, const char *, const char *, ...)
++ __attribute__ ((format (printf, 3, 4)));
++extern void ext4_update_dynamic_rev (struct super_block *sb);
++extern int ext4_update_compat_feature(handle_t *handle, struct super_block *sb,
++ __u32 compat);
++extern int ext4_update_rocompat_feature(handle_t *handle,
++ struct super_block *sb, __u32 rocompat);
++extern int ext4_update_incompat_feature(handle_t *handle,
++ struct super_block *sb, __u32 incompat);
++extern ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
++ struct ext4_group_desc *bg);
++extern ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
++ struct ext4_group_desc *bg);
++extern ext4_fsblk_t ext4_inode_table(struct super_block *sb,
++ struct ext4_group_desc *bg);
++extern void ext4_block_bitmap_set(struct super_block *sb,
++ struct ext4_group_desc *bg, ext4_fsblk_t blk);
++extern void ext4_inode_bitmap_set(struct super_block *sb,
++ struct ext4_group_desc *bg, ext4_fsblk_t blk);
++extern void ext4_inode_table_set(struct super_block *sb,
++ struct ext4_group_desc *bg, ext4_fsblk_t blk);
++
++static inline ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
++{
++ return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) |
++ le32_to_cpu(es->s_blocks_count_lo);
++}
++
++static inline ext4_fsblk_t ext4_r_blocks_count(struct ext4_super_block *es)
++{
++ return ((ext4_fsblk_t)le32_to_cpu(es->s_r_blocks_count_hi) << 32) |
++ le32_to_cpu(es->s_r_blocks_count_lo);
++}
++
++static inline ext4_fsblk_t ext4_free_blocks_count(struct ext4_super_block *es)
++{
++ return ((ext4_fsblk_t)le32_to_cpu(es->s_free_blocks_count_hi) << 32) |
++ le32_to_cpu(es->s_free_blocks_count_lo);
++}
++
++static inline void ext4_blocks_count_set(struct ext4_super_block *es,
++ ext4_fsblk_t blk)
++{
++ es->s_blocks_count_lo = cpu_to_le32((u32)blk);
++ es->s_blocks_count_hi = cpu_to_le32(blk >> 32);
++}
++
++static inline void ext4_free_blocks_count_set(struct ext4_super_block *es,
++ ext4_fsblk_t blk)
++{
++ es->s_free_blocks_count_lo = cpu_to_le32((u32)blk);
++ es->s_free_blocks_count_hi = cpu_to_le32(blk >> 32);
++}
++
++static inline void ext4_r_blocks_count_set(struct ext4_super_block *es,
++ ext4_fsblk_t blk)
++{
++ es->s_r_blocks_count_lo = cpu_to_le32((u32)blk);
++ es->s_r_blocks_count_hi = cpu_to_le32(blk >> 32);
++}
++
++static inline loff_t ext4_isize(struct ext4_inode *raw_inode)
+{
-+ struct dlm_ls *ls;
-+ struct plock_op *op;
-+ int rv;
++ return ((loff_t)le32_to_cpu(raw_inode->i_size_high) << 32) |
++ le32_to_cpu(raw_inode->i_size_lo);
++}
+
-+ ls = dlm_find_lockspace_local(lockspace);
-+ if (!ls)
-+ return -EINVAL;
++static inline void ext4_isize_set(struct ext4_inode *raw_inode, loff_t i_size)
++{
++ raw_inode->i_size_lo = cpu_to_le32(i_size);
++ raw_inode->i_size_high = cpu_to_le32(i_size >> 32);
++}
+
-+ op = kzalloc(sizeof(*op), GFP_KERNEL);
-+ if (!op) {
-+ rv = -ENOMEM;
-+ goto out;
-+ }
++static inline
++struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
++ ext4_group_t group)
++{
++ struct ext4_group_info ***grp_info;
++ long indexv, indexh;
++ grp_info = EXT4_SB(sb)->s_group_info;
++ indexv = group >> (EXT4_DESC_PER_BLOCK_BITS(sb));
++ indexh = group & ((EXT4_DESC_PER_BLOCK(sb)) - 1);
++ return grp_info[indexv][indexh];
++}
+
-+ 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));
++#define ext4_std_error(sb, errno) \
++do { \
++ if ((errno)) \
++ __ext4_std_error((sb), __FUNCTION__, (errno)); \
++} while (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);
++/*
++ * Inodes and files operations
++ */
+
-+ /* info.rv from userspace is 1 for conflict, 0 for no-conflict,
-+ -ENOENT if there are no locks on the file */
++/* dir.c */
++extern const struct file_operations ext4_dir_operations;
+
-+ rv = op->info.rv;
++/* file.c */
++extern const struct inode_operations ext4_file_inode_operations;
++extern const struct file_operations ext4_file_operations;
++
++/* namei.c */
++extern const struct inode_operations ext4_dir_inode_operations;
++extern const struct inode_operations ext4_special_inode_operations;
++
++/* symlink.c */
++extern const struct inode_operations ext4_symlink_inode_operations;
++extern const struct inode_operations ext4_fast_symlink_inode_operations;
++
++/* extents.c */
++extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
++extern int ext4_ext_writepage_trans_blocks(struct inode *, int);
++extern int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
++ ext4_lblk_t iblock,
++ unsigned long max_blocks, struct buffer_head *bh_result,
++ int create, int extend_disksize);
++extern void ext4_ext_truncate(struct inode *, struct page *);
++extern void ext4_ext_init(struct super_block *);
++extern void ext4_ext_release(struct super_block *);
++extern long ext4_fallocate(struct inode *inode, int mode, loff_t offset,
++ loff_t len);
++extern int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode,
++ sector_t block, unsigned long max_blocks,
++ struct buffer_head *bh, int create,
++ int extend_disksize);
++#endif /* __KERNEL__ */
+
-+ 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;
-+ }
++#endif /* _EXT4_H */
+diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
+new file mode 100644
+index 0000000..75333b5
+--- /dev/null
++++ b/fs/ext4/ext4_extents.h
+@@ -0,0 +1,232 @@
++/*
++ * Copyright (c) 2003-2006, Cluster File Systems, Inc, info at clusterfs.com
++ * Written by Alex Tomas <alex at clusterfs.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public Licens
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
++ */
+
-+ kfree(op);
-+out:
-+ dlm_put_lockspace(ls);
-+ return rv;
++#ifndef _EXT4_EXTENTS
++#define _EXT4_EXTENTS
++
++#include "ext4.h"
++
++/*
++ * With AGGRESSIVE_TEST defined, the capacity of index/leaf blocks
++ * becomes very small, so index split, in-depth growing and
++ * other hard changes happen much more often.
++ * This is for debug purposes only.
++ */
++#define AGGRESSIVE_TEST_
++
++/*
++ * With EXTENTS_STATS defined, the number of blocks and extents
++ * are collected in the truncate path. They'll be shown at
++ * umount time.
++ */
++#define EXTENTS_STATS__
++
++/*
++ * If CHECK_BINSEARCH is defined, then the results of the binary search
++ * will also be checked by linear search.
++ */
++#define CHECK_BINSEARCH__
++
++/*
++ * If EXT_DEBUG is defined you can use the 'extdebug' mount option
++ * to get lots of info about what's going on.
++ */
++#define EXT_DEBUG__
++#ifdef EXT_DEBUG
++#define ext_debug(a...) printk(a)
++#else
++#define ext_debug(a...)
++#endif
++
++/*
++ * If EXT_STATS is defined then stats numbers are collected.
++ * These number will be displayed at umount time.
++ */
++#define EXT_STATS_
++
++
++/*
++ * ext4_inode has i_block array (60 bytes total).
++ * The first 12 bytes store ext4_extent_header;
++ * the remainder stores an array of ext4_extent.
++ */
++
++/*
++ * This is the extent on-disk structure.
++ * It's used at the bottom of the tree.
++ */
++struct ext4_extent {
++ __le32 ee_block; /* first logical block extent covers */
++ __le16 ee_len; /* number of blocks covered by extent */
++ __le16 ee_start_hi; /* high 16 bits of physical block */
++ __le32 ee_start_lo; /* low 32 bits of physical block */
++};
++
++/*
++ * This is index on-disk structure.
++ * It's used at all the levels except the bottom.
++ */
++struct ext4_extent_idx {
++ __le32 ei_block; /* index covers logical blocks from 'block' */
++ __le32 ei_leaf_lo; /* pointer to the physical block of the next *
++ * level. leaf or next index could be there */
++ __le16 ei_leaf_hi; /* high 16 bits of physical block */
++ __u16 ei_unused;
++};
++
++/*
++ * Each block (leaves and indexes), even inode-stored has header.
++ */
++struct ext4_extent_header {
++ __le16 eh_magic; /* probably will support different formats */
++ __le16 eh_entries; /* number of valid entries */
++ __le16 eh_max; /* capacity of store in entries */
++ __le16 eh_depth; /* has tree real underlying blocks? */
++ __le32 eh_generation; /* generation of the tree */
++};
++
++#define EXT4_EXT_MAGIC cpu_to_le16(0xf30a)
++
++/*
++ * Array of ext4_ext_path contains path to some extent.
++ * Creation/lookup routines use it for traversal/splitting/etc.
++ * Truncate uses it to simulate recursive walking.
++ */
++struct ext4_ext_path {
++ ext4_fsblk_t p_block;
++ __u16 p_depth;
++ struct ext4_extent *p_ext;
++ struct ext4_extent_idx *p_idx;
++ struct ext4_extent_header *p_hdr;
++ struct buffer_head *p_bh;
++};
++
++/*
++ * structure for external API
++ */
++
++#define EXT4_EXT_CACHE_NO 0
++#define EXT4_EXT_CACHE_GAP 1
++#define EXT4_EXT_CACHE_EXTENT 2
++
++
++#define EXT_MAX_BLOCK 0xffffffff
++
++/*
++ * EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an
++ * initialized extent. This is 2^15 and not (2^16 - 1), since we use the
++ * MSB of ee_len field in the extent datastructure to signify if this
++ * particular extent is an initialized extent or an uninitialized (i.e.
++ * preallocated).
++ * EXT_UNINIT_MAX_LEN is the maximum number of blocks we can have in an
++ * uninitialized extent.
++ * If ee_len is <= 0x8000, it is an initialized extent. Otherwise, it is an
++ * uninitialized one. In other words, if MSB of ee_len is set, it is an
++ * uninitialized extent with only one special scenario when ee_len = 0x8000.
++ * In this case we can not have an uninitialized extent of zero length and
++ * thus we make it as a special case of initialized extent with 0x8000 length.
++ * This way we get better extent-to-group alignment for initialized extents.
++ * Hence, the maximum number of blocks we can have in an *initialized*
++ * extent is 2^15 (32768) and in an *uninitialized* extent is 2^15-1 (32767).
++ */
++#define EXT_INIT_MAX_LEN (1UL << 15)
++#define EXT_UNINIT_MAX_LEN (EXT_INIT_MAX_LEN - 1)
++
++
++#define EXT_FIRST_EXTENT(__hdr__) \
++ ((struct ext4_extent *) (((char *) (__hdr__)) + \
++ sizeof(struct ext4_extent_header)))
++#define EXT_FIRST_INDEX(__hdr__) \
++ ((struct ext4_extent_idx *) (((char *) (__hdr__)) + \
++ sizeof(struct ext4_extent_header)))
++#define EXT_HAS_FREE_INDEX(__path__) \
++ (le16_to_cpu((__path__)->p_hdr->eh_entries) \
++ < le16_to_cpu((__path__)->p_hdr->eh_max))
++#define EXT_LAST_EXTENT(__hdr__) \
++ (EXT_FIRST_EXTENT((__hdr__)) + le16_to_cpu((__hdr__)->eh_entries) - 1)
++#define EXT_LAST_INDEX(__hdr__) \
++ (EXT_FIRST_INDEX((__hdr__)) + le16_to_cpu((__hdr__)->eh_entries) - 1)
++#define EXT_MAX_EXTENT(__hdr__) \
++ (EXT_FIRST_EXTENT((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)
++#define EXT_MAX_INDEX(__hdr__) \
++ (EXT_FIRST_INDEX((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)
++
++static inline struct ext4_extent_header *ext_inode_hdr(struct inode *inode)
++{
++ return (struct ext4_extent_header *) EXT4_I(inode)->i_data;
+}
-+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)
++static inline struct ext4_extent_header *ext_block_hdr(struct buffer_head *bh)
+{
-+ struct dlm_plock_info info;
-+ struct plock_op *op = NULL;
++ return (struct ext4_extent_header *) bh->b_data;
++}
+
-+ if (count < sizeof(info))
-+ return -EINVAL;
++static inline unsigned short ext_depth(struct inode *inode)
++{
++ return le16_to_cpu(ext_inode_hdr(inode)->eh_depth);
++}
+
-+ 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);
++static inline void ext4_ext_tree_changed(struct inode *inode)
++{
++ EXT4_I(inode)->i_ext_generation++;
++}
+
-+ if (!op)
-+ return -EAGAIN;
++static inline void
++ext4_ext_invalidate_cache(struct inode *inode)
++{
++ EXT4_I(inode)->i_cached_extent.ec_type = EXT4_EXT_CACHE_NO;
++}
+
-+ if (copy_to_user(u, &info, sizeof(info)))
-+ return -EFAULT;
-+ return sizeof(info);
++static inline void ext4_ext_mark_uninitialized(struct ext4_extent *ext)
++{
++ /* We can not have an uninitialized extent of zero length! */
++ BUG_ON((le16_to_cpu(ext->ee_len) & ~EXT_INIT_MAX_LEN) == 0);
++ ext->ee_len |= cpu_to_le16(EXT_INIT_MAX_LEN);
+}
+
-+/* 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)
++static inline int ext4_ext_is_uninitialized(struct ext4_extent *ext)
+{
-+ struct dlm_plock_info info;
-+ struct plock_op *op;
-+ int found = 0;
++ /* Extent with ee_len of 0x8000 is treated as an initialized extent */
++ return (le16_to_cpu(ext->ee_len) > EXT_INIT_MAX_LEN);
++}
+
-+ if (count != sizeof(info))
-+ return -EINVAL;
++static inline int ext4_ext_get_actual_len(struct ext4_extent *ext)
++{
++ return (le16_to_cpu(ext->ee_len) <= EXT_INIT_MAX_LEN ?
++ le16_to_cpu(ext->ee_len) :
++ (le16_to_cpu(ext->ee_len) - EXT_INIT_MAX_LEN));
++}
++
++extern ext4_fsblk_t idx_pblock(struct ext4_extent_idx *);
++extern void ext4_ext_store_pblock(struct ext4_extent *, ext4_fsblk_t);
++extern int ext4_extent_tree_init(handle_t *, struct inode *);
++extern int ext4_ext_calc_credits_for_insert(struct inode *, struct ext4_ext_path *);
++extern int ext4_ext_try_to_merge(struct inode *inode,
++ struct ext4_ext_path *path,
++ struct ext4_extent *);
++extern unsigned int ext4_ext_check_overlap(struct inode *, struct ext4_extent *, struct ext4_ext_path *);
++extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *);
++extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
++ struct ext4_ext_path *);
++extern int ext4_ext_search_left(struct inode *, struct ext4_ext_path *,
++ ext4_lblk_t *, ext4_fsblk_t *);
++extern int ext4_ext_search_right(struct inode *, struct ext4_ext_path *,
++ ext4_lblk_t *, ext4_fsblk_t *);
++extern void ext4_ext_drop_refs(struct ext4_ext_path *);
++#endif /* _EXT4_EXTENTS */
++
+diff --git a/fs/ext4/ext4_i.h b/fs/ext4/ext4_i.h
+new file mode 100644
+index 0000000..26a4ae2
+--- /dev/null
++++ b/fs/ext4/ext4_i.h
+@@ -0,0 +1,167 @@
++/*
++ * ext4_i.h
++ *
++ * Copyright (C) 1992, 1993, 1994, 1995
++ * Remy Card (card at masi.ibp.fr)
++ * Laboratoire MASI - Institut Blaise Pascal
++ * Universite Pierre et Marie Curie (Paris VI)
++ *
++ * from
++ *
++ * linux/include/linux/minix_fs_i.h
++ *
++ * Copyright (C) 1991, 1992 Linus Torvalds
++ */
++
++#ifndef _EXT4_I
++#define _EXT4_I
++
++#include <linux/rwsem.h>
++#include <linux/rbtree.h>
++#include <linux/seqlock.h>
++#include <linux/mutex.h>
++
++/* data type for block offset of block group */
++typedef int ext4_grpblk_t;
++
++/* data type for filesystem-wide blocks number */
++typedef unsigned long long ext4_fsblk_t;
++
++/* data type for file logical block number */
++typedef __u32 ext4_lblk_t;
++
++/* data type for block group number */
++typedef unsigned long ext4_group_t;
++
++struct ext4_reserve_window {
++ ext4_fsblk_t _rsv_start; /* First byte reserved */
++ ext4_fsblk_t _rsv_end; /* Last byte reserved or 0 */
++};
++
++struct ext4_reserve_window_node {
++ struct rb_node rsv_node;
++ __u32 rsv_goal_size;
++ __u32 rsv_alloc_hit;
++ struct ext4_reserve_window rsv_window;
++};
++
++struct ext4_block_alloc_info {
++ /* information about reservation window */
++ struct ext4_reserve_window_node rsv_window_node;
++ /*
++ * was i_next_alloc_block in ext4_inode_info
++ * is the logical (file-relative) number of the
++ * most-recently-allocated block in this file.
++ * We use this for detecting linearly ascending allocation requests.
++ */
++ ext4_lblk_t last_alloc_logical_block;
++ /*
++ * Was i_next_alloc_goal in ext4_inode_info
++ * is the *physical* companion to i_next_alloc_block.
++ * it the physical block number of the block which was most-recentl
++ * allocated to this file. This give us the goal (target) for the next
++ * allocation when we detect linearly ascending requests.
++ */
++ ext4_fsblk_t last_alloc_physical_block;
++};
++
++#define rsv_start rsv_window._rsv_start
++#define rsv_end rsv_window._rsv_end
++
++/*
++ * storage for cached extent
++ */
++struct ext4_ext_cache {
++ ext4_fsblk_t ec_start;
++ ext4_lblk_t ec_block;
++ __u32 ec_len; /* must be 32bit to return holes */
++ __u32 ec_type;
++};
++
++/*
++ * third extended file system inode data in memory
++ */
++struct ext4_inode_info {
++ __le32 i_data[15]; /* unconverted */
++ __u32 i_flags;
++ ext4_fsblk_t i_file_acl;
++ __u32 i_dtime;
++
++ /*
++ * i_block_group is the number of the block group which contains
++ * this file's inode. Constant across the lifetime of the inode,
++ * it is ued for making block allocation decisions - we try to
++ * place a file's data blocks near its inode block, and new inodes
++ * near to their parent directory's inode.
++ */
++ ext4_group_t i_block_group;
++ __u32 i_state; /* Dynamic state flags for ext4 */
++
++ /* block reservation info */
++ struct ext4_block_alloc_info *i_block_alloc_info;
++
++ ext4_lblk_t i_dir_start_lookup;
++#ifdef CONFIG_EXT4DEV_FS_XATTR
++ /*
++ * Extended attributes can be read independently of the main file
++ * data. Taking i_mutex even when reading would cause contention
++ * between readers of EAs and writers of regular file data, so
++ * instead we synchronize on xattr_sem when reading or changing
++ * EAs.
++ */
++ struct rw_semaphore xattr_sem;
++#endif
++#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
++ struct posix_acl *i_acl;
++ struct posix_acl *i_default_acl;
++#endif
++
++ struct list_head i_orphan; /* unlinked but open inodes */
++
++ /*
++ * i_disksize keeps track of what the inode size is ON DISK, not
++ * in memory. During truncate, i_size is set to the new size by
++ * the VFS prior to calling ext4_truncate(), but the filesystem won't
++ * set i_disksize to 0 until the truncate is actually under way.
++ *
++ * The intent is that i_disksize always represents the blocks which
++ * are used by this file. This allows recovery to restart truncate
++ * on orphans if we crash during truncate. We actually write i_disksize
++ * into the on-disk inode when writing inodes out, instead of i_size.
++ *
++ * The only time when i_disksize and i_size may be different is when
++ * a truncate is in progress. The only things which change i_disksize
++ * are ext4_get_block (growth) and ext4_truncate (shrinkth).
++ */
++ loff_t i_disksize;
++
++ /* on-disk additional length */
++ __u16 i_extra_isize;
++
++ /*
++ * i_data_sem is for serialising ext4_truncate() against
++ * ext4_getblock(). In the 2.4 ext2 design, great chunks of inode's
++ * data tree are chopped off during truncate. We can't do that in
++ * ext4 because whenever we perform intermediate commits during
++ * truncate, the inode and all the metadata blocks *must* be in a
++ * consistent state which allows truncation of the orphans to restart
++ * during recovery. Hence we must fix the get_block-vs-truncate race
++ * by other means, so we have i_data_sem.
++ */
++ struct rw_semaphore i_data_sem;
++ struct inode vfs_inode;
++
++ unsigned long i_ext_generation;
++ struct ext4_ext_cache i_cached_extent;
++ /*
++ * File creation time. Its function is same as that of
++ * struct timespec i_{a,c,m}time in the generic inode.
++ */
++ struct timespec i_crtime;
++
++ /* mballoc */
++ struct list_head i_prealloc_list;
++ spinlock_t i_prealloc_lock;
++};
++
++#endif /* _EXT4_I */
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index d6afe4e..c75384b 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -2,14 +2,14 @@
+ * Interface between ext4 and JBD
+ */
+
+-#include <linux/ext4_jbd2.h>
++#include "ext4_jbd2.h"
+
+ int __ext4_journal_get_undo_access(const char *where, handle_t *handle,
+ struct buffer_head *bh)
+ {
+ int err = jbd2_journal_get_undo_access(handle, bh);
+ if (err)
+- ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
++ ext4_journal_abort_handle(where, __func__, bh, handle, err);
+ return err;
+ }
+
+@@ -18,7 +18,7 @@ int __ext4_journal_get_write_access(const char *where, handle_t *handle,
+ {
+ int err = jbd2_journal_get_write_access(handle, bh);
+ if (err)
+- ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
++ ext4_journal_abort_handle(where, __func__, bh, handle, err);
+ return err;
+ }
+
+@@ -27,7 +27,7 @@ int __ext4_journal_forget(const char *where, handle_t *handle,
+ {
+ int err = jbd2_journal_forget(handle, bh);
+ if (err)
+- ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
++ ext4_journal_abort_handle(where, __func__, bh, handle, err);
+ return err;
+ }
+
+@@ -36,7 +36,7 @@ int __ext4_journal_revoke(const char *where, handle_t *handle,
+ {
+ int err = jbd2_journal_revoke(handle, blocknr, bh);
+ if (err)
+- ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
++ ext4_journal_abort_handle(where, __func__, bh, handle, err);
+ return err;
+ }
+
+@@ -45,7 +45,7 @@ int __ext4_journal_get_create_access(const char *where,
+ {
+ int err = jbd2_journal_get_create_access(handle, bh);
+ if (err)
+- ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
++ ext4_journal_abort_handle(where, __func__, bh, handle, err);
+ return err;
+ }
+
+@@ -54,6 +54,6 @@ int __ext4_journal_dirty_metadata(const char *where,
+ {
+ int err = jbd2_journal_dirty_metadata(handle, bh);
+ if (err)
+- ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
++ ext4_journal_abort_handle(where, __func__, bh, handle, err);
+ return err;
+ }
+diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
+new file mode 100644
+index 0000000..9255a7d
+--- /dev/null
++++ b/fs/ext4/ext4_jbd2.h
+@@ -0,0 +1,231 @@
++/*
++ * ext4_jbd2.h
++ *
++ * Written by Stephen C. Tweedie <sct at redhat.com>, 1999
++ *
++ * Copyright 1998--1999 Red Hat corp --- 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, or at your
++ * option, any later version, incorporated herein by reference.
++ *
++ * Ext4-specific journaling extensions.
++ */
++
++#ifndef _EXT4_JBD2_H
++#define _EXT4_JBD2_H
++
++#include <linux/fs.h>
++#include <linux/jbd2.h>
++#include "ext4.h"
++
++#define EXT4_JOURNAL(inode) (EXT4_SB((inode)->i_sb)->s_journal)
++
++/* Define the number of blocks we need to account to a transaction to
++ * modify one block of data.
++ *
++ * We may have to touch one inode, one bitmap buffer, up to three
++ * indirection blocks, the group and superblock summaries, and the data
++ * block to complete the transaction.
++ *
++ * For extents-enabled fs we may have to allocate and modify up to
++ * 5 levels of tree + root which are stored in the inode. */
++
++#define EXT4_SINGLEDATA_TRANS_BLOCKS(sb) \
++ (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS) \
++ || test_opt(sb, EXTENTS) ? 27U : 8U)
++
++/* Extended attribute operations touch at most two data buffers,
++ * two bitmap buffers, and two group summaries, in addition to the inode
++ * and the superblock, which are already accounted for. */
++
++#define EXT4_XATTR_TRANS_BLOCKS 6U
++
++/* Define the minimum size for a transaction which modifies data. This
++ * needs to take into account the fact that we may end up modifying two
++ * quota files too (one for the group, one for the user quota). The
++ * superblock only gets updated once, of course, so don't bother
++ * counting that again for the quota updates. */
++
++#define EXT4_DATA_TRANS_BLOCKS(sb) (EXT4_SINGLEDATA_TRANS_BLOCKS(sb) + \
++ EXT4_XATTR_TRANS_BLOCKS - 2 + \
++ 2*EXT4_QUOTA_TRANS_BLOCKS(sb))
++
++/* Delete operations potentially hit one directory's namespace plus an
++ * entire inode, plus arbitrary amounts of bitmap/indirection data. Be
++ * generous. We can grow the delete transaction later if necessary. */
++
++#define EXT4_DELETE_TRANS_BLOCKS(sb) (2 * EXT4_DATA_TRANS_BLOCKS(sb) + 64)
++
++/* Define an arbitrary limit for the amount of data we will anticipate
++ * writing to any given transaction. For unbounded transactions such as
++ * write(2) and truncate(2) we can write more than this, but we always
++ * start off at the maximum transaction size and grow the transaction
++ * optimistically as we go. */
++
++#define EXT4_MAX_TRANS_DATA 64U
++
++/* We break up a large truncate or write transaction once the handle's
++ * buffer credits gets this low, we need either to extend the
++ * transaction or to start a new one. Reserve enough space here for
++ * inode, bitmap, superblock, group and indirection updates for at least
++ * one block, plus two quota updates. Quota allocations are not
++ * needed. */
++
++#define EXT4_RESERVE_TRANS_BLOCKS 12U
++
++#define EXT4_INDEX_EXTRA_TRANS_BLOCKS 8
++
++#ifdef CONFIG_QUOTA
++/* Amount of blocks needed for quota update - we know that the structure was
++ * allocated so we need to update only inode+data */
++#define EXT4_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 2 : 0)
++/* Amount of blocks needed for quota insert/delete - we do some block writes
++ * but inode, sb and group updates are done only once */
++#define EXT4_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\
++ (EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_INIT_REWRITE) : 0)
++#define EXT4_QUOTA_DEL_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_DEL_ALLOC*\
++ (EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_DEL_REWRITE) : 0)
++#else
++#define EXT4_QUOTA_TRANS_BLOCKS(sb) 0
++#define EXT4_QUOTA_INIT_BLOCKS(sb) 0
++#define EXT4_QUOTA_DEL_BLOCKS(sb) 0
++#endif
++
++int
++ext4_mark_iloc_dirty(handle_t *handle,
++ struct inode *inode,
++ struct ext4_iloc *iloc);
++
++/*
++ * On success, We end up with an outstanding reference count against
++ * iloc->bh. This _must_ be cleaned up later.
++ */
++
++int ext4_reserve_inode_write(handle_t *handle, struct inode *inode,
++ struct ext4_iloc *iloc);
++
++int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode);
++
++/*
++ * Wrapper functions with which ext4 calls into JBD. The intent here is
++ * to allow these to be turned into appropriate stubs so ext4 can control
++ * ext2 filesystems, so ext2+ext4 systems only nee one fs. This work hasn't
++ * been done yet.
++ */
++
++static inline void ext4_journal_release_buffer(handle_t *handle,
++ struct buffer_head *bh)
++{
++ jbd2_journal_release_buffer(handle, bh);
++}
++
++void ext4_journal_abort_handle(const char *caller, const char *err_fn,
++ struct buffer_head *bh, handle_t *handle, int err);
++
++int __ext4_journal_get_undo_access(const char *where, handle_t *handle,
++ struct buffer_head *bh);
++
++int __ext4_journal_get_write_access(const char *where, handle_t *handle,
++ struct buffer_head *bh);
++
++int __ext4_journal_forget(const char *where, handle_t *handle,
++ struct buffer_head *bh);
++
++int __ext4_journal_revoke(const char *where, handle_t *handle,
++ ext4_fsblk_t blocknr, struct buffer_head *bh);
++
++int __ext4_journal_get_create_access(const char *where,
++ handle_t *handle, struct buffer_head *bh);
++
++int __ext4_journal_dirty_metadata(const char *where,
++ handle_t *handle, struct buffer_head *bh);
+
-+ if (copy_from_user(&info, u, sizeof(info)))
-+ return -EFAULT;
++#define ext4_journal_get_undo_access(handle, bh) \
++ __ext4_journal_get_undo_access(__FUNCTION__, (handle), (bh))
++#define ext4_journal_get_write_access(handle, bh) \
++ __ext4_journal_get_write_access(__FUNCTION__, (handle), (bh))
++#define ext4_journal_revoke(handle, blocknr, bh) \
++ __ext4_journal_revoke(__FUNCTION__, (handle), (blocknr), (bh))
++#define ext4_journal_get_create_access(handle, bh) \
++ __ext4_journal_get_create_access(__FUNCTION__, (handle), (bh))
++#define ext4_journal_dirty_metadata(handle, bh) \
++ __ext4_journal_dirty_metadata(__FUNCTION__, (handle), (bh))
++#define ext4_journal_forget(handle, bh) \
++ __ext4_journal_forget(__FUNCTION__, (handle), (bh))
+
-+ if (check_version(&info))
-+ return -EINVAL;
++int ext4_journal_dirty_data(handle_t *handle, struct buffer_head *bh);
+
-+ 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);
++handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks);
++int __ext4_journal_stop(const char *where, handle_t *handle);
+
-+ 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 inline handle_t *ext4_journal_start(struct inode *inode, int nblocks)
++{
++ return ext4_journal_start_sb(inode->i_sb, nblocks);
+}
+
-+static unsigned int dev_poll(struct file *file, poll_table *wait)
++#define ext4_journal_stop(handle) \
++ __ext4_journal_stop(__FUNCTION__, (handle))
++
++static inline handle_t *ext4_journal_current_handle(void)
+{
-+ unsigned int mask = 0;
++ return journal_current_handle();
++}
+
-+ poll_wait(file, &send_wq, wait);
++static inline int ext4_journal_extend(handle_t *handle, int nblocks)
++{
++ return jbd2_journal_extend(handle, nblocks);
++}
+
-+ spin_lock(&ops_lock);
-+ if (!list_empty(&send_list))
-+ mask = POLLIN | POLLRDNORM;
-+ spin_unlock(&ops_lock);
++static inline int ext4_journal_restart(handle_t *handle, int nblocks)
++{
++ return jbd2_journal_restart(handle, nblocks);
++}
+
-+ return mask;
++static inline int ext4_journal_blocks_per_page(struct inode *inode)
++{
++ return jbd2_journal_blocks_per_page(inode);
+}
+
-+static const struct file_operations dev_fops = {
-+ .read = dev_read,
-+ .write = dev_write,
-+ .poll = dev_poll,
-+ .owner = THIS_MODULE
-+};
++static inline int ext4_journal_force_commit(journal_t *journal)
++{
++ return jbd2_journal_force_commit(journal);
++}
+
-+static struct miscdevice plock_dev_misc = {
-+ .minor = MISC_DYNAMIC_MINOR,
-+ .name = DLM_PLOCK_MISC_NAME,
-+ .fops = &dev_fops
-+};
++/* super.c */
++int ext4_force_commit(struct super_block *sb);
+
-+int dlm_plock_init(void)
++static inline int ext4_should_journal_data(struct inode *inode)
+{
-+ 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);
++ if (!S_ISREG(inode->i_mode))
++ return 1;
++ if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
++ return 1;
++ if (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL)
++ return 1;
++ return 0;
++}
+
-+ rv = misc_register(&plock_dev_misc);
-+ if (rv)
-+ log_print("dlm_plock_init: misc_register failed %d", rv);
-+ return rv;
++static inline int ext4_should_order_data(struct inode *inode)
++{
++ if (!S_ISREG(inode->i_mode))
++ return 0;
++ if (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL)
++ return 0;
++ if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
++ return 1;
++ return 0;
+}
+
-+void dlm_plock_exit(void)
++static inline int ext4_should_writeback_data(struct inode *inode)
+{
-+ if (misc_deregister(&plock_dev_misc) < 0)
-+ log_print("dlm_plock_exit: misc_deregister failed");
++ if (!S_ISREG(inode->i_mode))
++ return 0;
++ if (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL)
++ return 0;
++ if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
++ return 1;
++ return 0;
+}
+
-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)];
++#endif /* _EXT4_JBD2_H */
+diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
+new file mode 100644
+index 0000000..5802e69
+--- /dev/null
++++ b/fs/ext4/ext4_sb.h
+@@ -0,0 +1,148 @@
++/*
++ * ext4_sb.h
++ *
++ * Copyright (C) 1992, 1993, 1994, 1995
++ * Remy Card (card at masi.ibp.fr)
++ * Laboratoire MASI - Institut Blaise Pascal
++ * Universite Pierre et Marie Curie (Paris VI)
++ *
++ * from
++ *
++ * linux/include/linux/minix_fs_sb.h
++ *
++ * Copyright (C) 1991, 1992 Linus Torvalds
++ */
++
++#ifndef _EXT4_SB
++#define _EXT4_SB
++
++#ifdef __KERNEL__
++#include <linux/timer.h>
++#include <linux/wait.h>
++#include <linux/blockgroup_lock.h>
++#include <linux/percpu_counter.h>
++#endif
++#include <linux/rbtree.h>
++
++/*
++ * third extended-fs super-block data in memory
++ */
++struct ext4_sb_info {
++ unsigned long s_desc_size; /* Size of a group descriptor in bytes */
++ unsigned long s_inodes_per_block;/* Number of inodes per block */
++ unsigned long s_blocks_per_group;/* Number of blocks in a group */
++ unsigned long s_inodes_per_group;/* Number of inodes in a group */
++ unsigned long s_itb_per_group; /* Number of inode table blocks per group */
++ unsigned long s_gdb_count; /* Number of group descriptor blocks */
++ unsigned long s_desc_per_block; /* Number of group descriptors per block */
++ ext4_group_t s_groups_count; /* Number of groups in the fs */
++ unsigned long s_overhead_last; /* Last calculated overhead */
++ unsigned long s_blocks_last; /* Last seen block count */
++ loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */
++ struct buffer_head * s_sbh; /* Buffer containing the super block */
++ struct ext4_super_block * s_es; /* Pointer to the super block in the buffer */
++ struct buffer_head ** s_group_desc;
++ unsigned long s_mount_opt;
++ ext4_fsblk_t s_sb_block;
++ uid_t s_resuid;
++ gid_t s_resgid;
++ unsigned short s_mount_state;
++ unsigned short s_pad;
++ int s_addr_per_block_bits;
++ int s_desc_per_block_bits;
++ int s_inode_size;
++ int s_first_ino;
++ spinlock_t s_next_gen_lock;
++ u32 s_next_generation;
++ u32 s_hash_seed[4];
++ int s_def_hash_version;
++ struct percpu_counter s_freeblocks_counter;
++ struct percpu_counter s_freeinodes_counter;
++ struct percpu_counter s_dirs_counter;
++ struct blockgroup_lock s_blockgroup_lock;
++
++ /* root of the per fs reservation window tree */
++ spinlock_t s_rsv_window_lock;
++ struct rb_root s_rsv_window_root;
++ struct ext4_reserve_window_node s_rsv_window_head;
++
++ /* Journaling */
++ struct inode * s_journal_inode;
++ struct journal_s * s_journal;
++ struct list_head s_orphan;
++ unsigned long s_commit_interval;
++ struct block_device *journal_bdev;
++#ifdef CONFIG_JBD2_DEBUG
++ struct timer_list turn_ro_timer; /* For turning read-only (crash simulation) */
++ wait_queue_head_t ro_wait_queue; /* For people waiting for the fs to go read-only */
++#endif
++#ifdef CONFIG_QUOTA
++ char *s_qf_names[MAXQUOTAS]; /* Names of quota files with journalled quota */
++ int s_jquota_fmt; /* Format of quota to use */
++#endif
++ unsigned int s_want_extra_isize; /* New inodes should reserve # bytes */
++
++#ifdef EXTENTS_STATS
++ /* ext4 extents stats */
++ unsigned long s_ext_min;
++ unsigned long s_ext_max;
++ unsigned long s_depth_max;
++ spinlock_t s_ext_stats_lock;
++ unsigned long s_ext_blocks;
++ unsigned long s_ext_extents;
++#endif
++
++ /* for buddy allocator */
++ struct ext4_group_info ***s_group_info;
++ struct inode *s_buddy_cache;
++ long s_blocks_reserved;
++ spinlock_t s_reserve_lock;
++ struct list_head s_active_transaction;
++ struct list_head s_closed_transaction;
++ struct list_head s_committed_transaction;
++ spinlock_t s_md_lock;
++ tid_t s_last_transaction;
++ unsigned short *s_mb_offsets, *s_mb_maxs;
++
++ /* tunables */
++ unsigned long s_stripe;
++ unsigned long s_mb_stream_request;
++ unsigned long s_mb_max_to_scan;
++ unsigned long s_mb_min_to_scan;
++ unsigned long s_mb_stats;
++ unsigned long s_mb_order2_reqs;
++ unsigned long s_mb_group_prealloc;
++ /* where last allocation was done - for stream allocation */
++ unsigned long s_mb_last_group;
++ unsigned long s_mb_last_start;
++
++ /* history to debug policy */
++ struct ext4_mb_history *s_mb_history;
++ int s_mb_history_cur;
++ int s_mb_history_max;
++ int s_mb_history_num;
++ struct proc_dir_entry *s_mb_proc;
++ spinlock_t s_mb_history_lock;
++ int s_mb_history_filter;
++
++ /* stats for buddy allocator */
++ spinlock_t s_mb_pa_lock;
++ atomic_t s_bal_reqs; /* number of reqs with len > 1 */
++ atomic_t s_bal_success; /* we found long enough chunks */
++ atomic_t s_bal_allocated; /* in blocks */
++ atomic_t s_bal_ex_scanned; /* total extents scanned */
++ atomic_t s_bal_goals; /* goal hits */
++ atomic_t s_bal_breaks; /* too long searches */
++ atomic_t s_bal_2orders; /* 2^order hits */
++ spinlock_t s_bal_lock;
++ unsigned long s_mb_buddies_generated;
++ unsigned long long s_mb_generation_time;
++ atomic_t s_mb_lost_chunks;
++ atomic_t s_mb_preallocated;
++ atomic_t s_mb_discarded;
++
++ /* locality groups */
++ struct ext4_locality_group *s_locality_groups;
++};
++
++#endif /* _EXT4_SB */
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 9ae6e67..47929c4 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -32,7 +32,6 @@
+ #include <linux/module.h>
+ #include <linux/fs.h>
+ #include <linux/time.h>
+-#include <linux/ext4_jbd2.h>
+ #include <linux/jbd2.h>
+ #include <linux/highuid.h>
+ #include <linux/pagemap.h>
+@@ -40,8 +39,9 @@
+ #include <linux/string.h>
+ #include <linux/slab.h>
+ #include <linux/falloc.h>
+-#include <linux/ext4_fs_extents.h>
+ #include <asm/uaccess.h>
++#include "ext4_jbd2.h"
++#include "ext4_extents.h"
- /*
-@@ -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;
+ /*
+@@ -308,7 +308,7 @@ corrupted:
+ }
- bprm->mm = NULL; /* We're using it now */
+ #define ext4_ext_check_header(inode, eh, depth) \
+- __ext4_ext_check_header(__FUNCTION__, inode, eh, depth)
++ __ext4_ext_check_header(__func__, inode, eh, depth)
- /* This is the point of no return */
-- put_files_struct(files);
--
- current->sas_ss_sp = current->sas_ss_size = 0;
+ #ifdef EXT_DEBUG
+ static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path)
+@@ -614,7 +614,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
- if (current->euid == current->uid && current->egid == current->gid)
-@@ -1034,8 +1022,6 @@ int flush_old_exec(struct linux_binprm * bprm)
+ ix->ei_block = cpu_to_le32(logical);
+ ext4_idx_store_pblock(ix, ptr);
+- curp->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(curp->p_hdr->eh_entries)+1);
++ le16_add_cpu(&curp->p_hdr->eh_entries, 1);
- return 0;
+ BUG_ON(le16_to_cpu(curp->p_hdr->eh_entries)
+ > le16_to_cpu(curp->p_hdr->eh_max));
+@@ -736,7 +736,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
+ }
+ if (m) {
+ memmove(ex, path[depth].p_ext-m, sizeof(struct ext4_extent)*m);
+- neh->eh_entries = cpu_to_le16(le16_to_cpu(neh->eh_entries)+m);
++ le16_add_cpu(&neh->eh_entries, m);
+ }
--mmap_failed:
-- reset_files_struct(current, files);
- out:
- return retval;
+ set_buffer_uptodate(bh);
+@@ -753,8 +753,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
+ err = ext4_ext_get_access(handle, inode, path + depth);
+ if (err)
+ goto cleanup;
+- path[depth].p_hdr->eh_entries =
+- cpu_to_le16(le16_to_cpu(path[depth].p_hdr->eh_entries)-m);
++ le16_add_cpu(&path[depth].p_hdr->eh_entries, -m);
+ err = ext4_ext_dirty(handle, inode, path + depth);
+ if (err)
+ goto cleanup;
+@@ -817,8 +816,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
+ if (m) {
+ memmove(++fidx, path[i].p_idx - m,
+ sizeof(struct ext4_extent_idx) * m);
+- neh->eh_entries =
+- cpu_to_le16(le16_to_cpu(neh->eh_entries) + m);
++ le16_add_cpu(&neh->eh_entries, m);
+ }
+ set_buffer_uptodate(bh);
+ unlock_buffer(bh);
+@@ -834,7 +832,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
+ err = ext4_ext_get_access(handle, inode, path + i);
+ if (err)
+ goto cleanup;
+- path[i].p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(path[i].p_hdr->eh_entries)-m);
++ le16_add_cpu(&path[i].p_hdr->eh_entries, -m);
+ err = ext4_ext_dirty(handle, inode, path + i);
+ if (err)
+ goto cleanup;
+@@ -1369,7 +1367,7 @@ int ext4_ext_try_to_merge(struct inode *inode,
+ * sizeof(struct ext4_extent);
+ memmove(ex + 1, ex + 2, len);
+ }
+- eh->eh_entries = cpu_to_le16(le16_to_cpu(eh->eh_entries) - 1);
++ le16_add_cpu(&eh->eh_entries, -1);
+ merge_done = 1;
+ WARN_ON(eh->eh_entries == 0);
+ if (!eh->eh_entries)
+@@ -1560,7 +1558,7 @@ has_space:
+ path[depth].p_ext = nearex;
+ }
+
+- eh->eh_entries = cpu_to_le16(le16_to_cpu(eh->eh_entries)+1);
++ le16_add_cpu(&eh->eh_entries, 1);
+ nearex = path[depth].p_ext;
+ nearex->ee_block = newext->ee_block;
+ ext4_ext_store_pblock(nearex, ext_pblock(newext));
+@@ -1699,7 +1697,7 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
+ err = ext4_ext_get_access(handle, inode, path);
+ if (err)
+ return err;
+- path->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(path->p_hdr->eh_entries)-1);
++ le16_add_cpu(&path->p_hdr->eh_entries, -1);
+ err = ext4_ext_dirty(handle, inode, path);
+ if (err)
+ return err;
+@@ -1902,7 +1900,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
+ if (num == 0) {
+ /* this extent is removed; mark slot entirely unused */
+ ext4_ext_store_pblock(ex, 0);
+- eh->eh_entries = cpu_to_le16(le16_to_cpu(eh->eh_entries)-1);
++ le16_add_cpu(&eh->eh_entries, -1);
+ }
+
+ ex->ee_block = cpu_to_le32(block);
+@@ -1979,7 +1977,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start)
+ * We start scanning from right side, freeing all the blocks
+ * after i_size and walking into the tree depth-wise.
+ */
+- path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), GFP_KERNEL);
++ path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), GFP_NOFS);
+ if (path == NULL) {
+ ext4_journal_stop(handle);
+ return -ENOMEM;
+@@ -2138,6 +2136,82 @@ void ext4_ext_release(struct super_block *sb)
+ #endif
}
-@@ -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;
++static void bi_complete(struct bio *bio, int error)
++{
++ complete((struct completion *)bio->bi_private);
++}
+
- retval = -ENOMEM;
- bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
- if (!bprm)
-- goto out_ret;
-+ goto out_files;
++/* FIXME!! we need to try to merge to left or right after zero-out */
++static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
++{
++ int ret = -EIO;
++ struct bio *bio;
++ int blkbits, blocksize;
++ sector_t ee_pblock;
++ struct completion event;
++ unsigned int ee_len, len, done, offset;
++
++
++ blkbits = inode->i_blkbits;
++ blocksize = inode->i_sb->s_blocksize;
++ ee_len = ext4_ext_get_actual_len(ex);
++ ee_pblock = ext_pblock(ex);
++
++ /* convert ee_pblock to 512 byte sectors */
++ ee_pblock = ee_pblock << (blkbits - 9);
++
++ while (ee_len > 0) {
++
++ if (ee_len > BIO_MAX_PAGES)
++ len = BIO_MAX_PAGES;
++ else
++ len = ee_len;
++
++ bio = bio_alloc(GFP_NOIO, len);
++ if (!bio)
++ return -ENOMEM;
++ bio->bi_sector = ee_pblock;
++ bio->bi_bdev = inode->i_sb->s_bdev;
++
++ done = 0;
++ offset = 0;
++ while (done < len) {
++ ret = bio_add_page(bio, ZERO_PAGE(0),
++ blocksize, offset);
++ if (ret != blocksize) {
++ /*
++ * We can't add any more pages because of
++ * hardware limitations. Start a new bio.
++ */
++ break;
++ }
++ done++;
++ offset += blocksize;
++ if (offset >= PAGE_CACHE_SIZE)
++ offset = 0;
++ }
++
++ init_completion(&event);
++ bio->bi_private = &event;
++ bio->bi_end_io = bi_complete;
++ submit_bio(WRITE, bio);
++ wait_for_completion(&event);
++
++ if (test_bit(BIO_UPTODATE, &bio->bi_flags))
++ ret = 0;
++ else {
++ ret = -EIO;
++ break;
++ }
++ bio_put(bio);
++ ee_len -= done;
++ ee_pblock += done << (blkbits - 9);
++ }
++ return ret;
++}
++
++#define EXT4_EXT_ZERO_LEN 7
++
+ /*
+ * This function is called by ext4_ext_get_blocks() if someone tries to write
+ * to an uninitialized extent. It may result in splitting the uninitialized
+@@ -2154,7 +2228,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ ext4_lblk_t iblock,
+ unsigned long max_blocks)
+ {
+- struct ext4_extent *ex, newex;
++ struct ext4_extent *ex, newex, orig_ex;
+ struct ext4_extent *ex1 = NULL;
+ struct ext4_extent *ex2 = NULL;
+ struct ext4_extent *ex3 = NULL;
+@@ -2173,10 +2247,26 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ allocated = ee_len - (iblock - ee_block);
+ newblock = iblock - ee_block + ext_pblock(ex);
+ ex2 = ex;
++ orig_ex.ee_block = ex->ee_block;
++ orig_ex.ee_len = cpu_to_le16(ee_len);
++ ext4_ext_store_pblock(&orig_ex, ext_pblock(ex));
- 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;
+ err = ext4_ext_get_access(handle, inode, path + depth);
+ if (err)
+ goto out;
++ /* If extent has less than 2*EXT4_EXT_ZERO_LEN zerout directly */
++ if (ee_len <= 2*EXT4_EXT_ZERO_LEN) {
++ err = ext4_ext_zeroout(inode, &orig_ex);
++ if (err)
++ goto fix_extent_len;
++ /* update the extent length and mark as initialized */
++ ex->ee_block = orig_ex.ee_block;
++ ex->ee_len = orig_ex.ee_len;
++ ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
++ ext4_ext_dirty(handle, inode, path + depth);
++ /* zeroed the full extent */
++ return allocated;
++ }
+
+ /* ex1: ee_block to iblock - 1 : uninitialized */
+ if (iblock > ee_block) {
+@@ -2195,19 +2285,103 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ /* ex3: to ee_block + ee_len : uninitialised */
+ if (allocated > max_blocks) {
+ unsigned int newdepth;
++ /* If extent has less than EXT4_EXT_ZERO_LEN zerout directly */
++ if (allocated <= EXT4_EXT_ZERO_LEN) {
++ /* Mark first half uninitialized.
++ * Mark second half initialized and zero out the
++ * initialized extent
++ */
++ ex->ee_block = orig_ex.ee_block;
++ ex->ee_len = cpu_to_le16(ee_len - allocated);
++ ext4_ext_mark_uninitialized(ex);
++ ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
++ ext4_ext_dirty(handle, inode, path + depth);
++
++ ex3 = &newex;
++ ex3->ee_block = cpu_to_le32(iblock);
++ ext4_ext_store_pblock(ex3, newblock);
++ ex3->ee_len = cpu_to_le16(allocated);
++ err = ext4_ext_insert_extent(handle, inode, path, ex3);
++ if (err == -ENOSPC) {
++ err = ext4_ext_zeroout(inode, &orig_ex);
++ if (err)
++ goto fix_extent_len;
++ ex->ee_block = orig_ex.ee_block;
++ ex->ee_len = orig_ex.ee_len;
++ ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
++ ext4_ext_dirty(handle, inode, path + depth);
++ /* zeroed the full extent */
++ return allocated;
++
++ } else if (err)
++ goto fix_extent_len;
++
++ /*
++ * We need to zero out the second half because
++ * an fallocate request can update file size and
++ * converting the second half to initialized extent
++ * implies that we can leak some junk data to user
++ * space.
++ */
++ err = ext4_ext_zeroout(inode, ex3);
++ if (err) {
++ /*
++ * We should actually mark the
++ * second half as uninit and return error
++ * Insert would have changed the extent
++ */
++ depth = ext_depth(inode);
++ ext4_ext_drop_refs(path);
++ path = ext4_ext_find_extent(inode,
++ iblock, path);
++ if (IS_ERR(path)) {
++ err = PTR_ERR(path);
++ return err;
++ }
++ ex = path[depth].p_ext;
++ err = ext4_ext_get_access(handle, inode,
++ path + depth);
++ if (err)
++ return err;
++ ext4_ext_mark_uninitialized(ex);
++ ext4_ext_dirty(handle, inode, path + depth);
++ return err;
++ }
++
++ /* zeroed the second half */
++ return allocated;
++ }
+ ex3 = &newex;
+ ex3->ee_block = cpu_to_le32(iblock + max_blocks);
+ ext4_ext_store_pblock(ex3, newblock + max_blocks);
+ ex3->ee_len = cpu_to_le16(allocated - max_blocks);
+ ext4_ext_mark_uninitialized(ex3);
+ err = ext4_ext_insert_extent(handle, inode, path, ex3);
+- if (err)
+- goto out;
++ if (err == -ENOSPC) {
++ err = ext4_ext_zeroout(inode, &orig_ex);
++ if (err)
++ goto fix_extent_len;
++ /* update the extent length and mark as initialized */
++ ex->ee_block = orig_ex.ee_block;
++ ex->ee_len = orig_ex.ee_len;
++ ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
++ ext4_ext_dirty(handle, inode, path + depth);
++ /* zeroed the full extent */
++ return allocated;
++
++ } else if (err)
++ goto fix_extent_len;
+ /*
+ * The depth, and hence eh & ex might change
+ * as part of the insert above.
+ */
+ newdepth = ext_depth(inode);
++ /*
++ * update the extent length after successfull insert of the
++ * split extent
++ */
++ orig_ex.ee_len = cpu_to_le16(ee_len -
++ ext4_ext_get_actual_len(ex3));
+ if (newdepth != depth) {
+ depth = newdepth;
+ ext4_ext_drop_refs(path);
+@@ -2226,6 +2400,24 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ goto out;
+ }
+ allocated = max_blocks;
++
++ /* If extent has less than EXT4_EXT_ZERO_LEN and we are trying
++ * to insert a extent in the middle zerout directly
++ * otherwise give the extent a chance to merge to left
++ */
++ if (le16_to_cpu(orig_ex.ee_len) <= EXT4_EXT_ZERO_LEN &&
++ iblock != ee_block) {
++ err = ext4_ext_zeroout(inode, &orig_ex);
++ if (err)
++ goto fix_extent_len;
++ /* update the extent length and mark as initialized */
++ ex->ee_block = orig_ex.ee_block;
++ ex->ee_len = orig_ex.ee_len;
++ ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
++ ext4_ext_dirty(handle, inode, path + depth);
++ /* zero out the first half */
++ return allocated;
++ }
}
-
-@@ -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)
+ /*
+ * If there was a change of depth as part of the
+@@ -2282,8 +2474,29 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ goto out;
+ insert:
+ err = ext4_ext_insert_extent(handle, inode, path, &newex);
++ if (err == -ENOSPC) {
++ err = ext4_ext_zeroout(inode, &orig_ex);
++ if (err)
++ goto fix_extent_len;
++ /* update the extent length and mark as initialized */
++ ex->ee_block = orig_ex.ee_block;
++ ex->ee_len = orig_ex.ee_len;
++ ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
++ ext4_ext_dirty(handle, inode, path + depth);
++ /* zero out the first half */
++ return allocated;
++ } else if (err)
++ goto fix_extent_len;
+ out:
+ return err ? err : allocated;
++
++fix_extent_len:
++ ex->ee_block = orig_ex.ee_block;
++ ex->ee_len = orig_ex.ee_len;
++ ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
++ ext4_ext_mark_uninitialized(ex);
++ ext4_ext_dirty(handle, inode, path + depth);
++ return err;
}
- /**
-- * ext2_find_goal - find a prefered place for allocation.
-+ * ext2_find_goal - find a preferred place for allocation.
- * @inode: owner
- * @block: block we want
- * @partial: pointer to the last triple within a chain
-diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
-index b8ea11f..de876fa 100644
---- a/fs/ext2/ioctl.c
-+++ b/fs/ext2/ioctl.c
-@@ -12,6 +12,7 @@
- #include <linux/time.h>
- #include <linux/sched.h>
- #include <linux/compat.h>
-+#include <linux/mount.h>
- #include <linux/smp_lock.h>
- #include <asm/current.h>
- #include <asm/uaccess.h>
-@@ -23,6 +24,7 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
- struct ext2_inode_info *ei = EXT2_I(inode);
- unsigned int flags;
- unsigned short rsv_window_size;
-+ int ret;
-
- ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg);
+ /*
+@@ -2393,8 +2606,20 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ }
+ if (create == EXT4_CREATE_UNINITIALIZED_EXT)
+ goto out;
+- if (!create)
++ if (!create) {
++ /*
++ * We have blocks reserved already. We
++ * return allocated blocks so that delalloc
++ * won't do block reservation for us. But
++ * the buffer head will be unmapped so that
++ * a read from the block returns 0s.
++ */
++ if (allocated > max_blocks)
++ allocated = max_blocks;
++ /* mark the buffer unwritten */
++ __set_bit(BH_Unwritten, &bh_result->b_state);
+ goto out2;
++ }
-@@ -34,14 +36,19 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
- case EXT2_IOC_SETFLAGS: {
- unsigned int oldflags;
+ ret = ext4_ext_convert_to_initialized(handle, inode,
+ path, iblock,
+@@ -2584,6 +2809,8 @@ out_stop:
+ ext4_orphan_del(handle, inode);
-- if (IS_RDONLY(inode))
-- return -EROFS;
-+ ret = mnt_want_write(filp->f_path.mnt);
-+ if (ret)
-+ return ret;
+ up_write(&EXT4_I(inode)->i_data_sem);
++ inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
++ ext4_mark_inode_dirty(handle, inode);
+ ext4_journal_stop(handle);
+ }
-- if (!is_owner_or_cap(inode))
-- return -EACCES;
-+ if (!is_owner_or_cap(inode)) {
-+ ret = -EACCES;
-+ goto setflags_out;
-+ }
+@@ -2608,6 +2835,28 @@ int ext4_ext_writepage_trans_blocks(struct inode *inode, int num)
+ return needed;
+ }
-- if (get_user(flags, (int __user *) arg))
-- return -EFAULT;
-+ if (get_user(flags, (int __user *) arg)) {
-+ ret = -EFAULT;
-+ goto setflags_out;
-+ }
++static void ext4_falloc_update_inode(struct inode *inode,
++ int mode, loff_t new_size, int update_ctime)
++{
++ struct timespec now;
++
++ if (update_ctime) {
++ now = current_fs_time(inode->i_sb);
++ if (!timespec_equal(&inode->i_ctime, &now))
++ inode->i_ctime = now;
++ }
++ /*
++ * Update only when preallocation was requested beyond
++ * the file size.
++ */
++ if (!(mode & FALLOC_FL_KEEP_SIZE) &&
++ new_size > i_size_read(inode)) {
++ i_size_write(inode, new_size);
++ EXT4_I(inode)->i_disksize = new_size;
++ }
++
++}
++
+ /*
+ * preallocate space for a file. This implements ext4's fallocate inode
+ * operation, which gets called from sys_fallocate system call.
+@@ -2619,8 +2868,8 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
+ {
+ handle_t *handle;
+ ext4_lblk_t block;
++ loff_t new_size;
+ unsigned long max_blocks;
+- ext4_fsblk_t nblocks = 0;
+ int ret = 0;
+ int ret2 = 0;
+ int retries = 0;
+@@ -2639,9 +2888,12 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
+ return -ENODEV;
- 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;
+ block = offset >> blkbits;
++ /*
++ * We can't just convert len to max_blocks because
++ * If blocksize = 4096 offset = 3072 and len = 2048
++ */
+ max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits)
+- - block;
+-
++ - block;
+ /*
+ * credits to insert 1 extent into extent tree + buffers to be able to
+ * modify 1 super block, 1 block bitmap and 1 group descriptor.
+@@ -2657,7 +2909,6 @@ retry:
+ ret = PTR_ERR(handle);
+ break;
}
- 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;
- }
+-
+ ret = ext4_get_blocks_wrap(handle, inode, block,
+ max_blocks, &map_bh,
+ EXT4_CREATE_UNINITIALIZED_EXT, 0);
+@@ -2673,61 +2924,24 @@ retry:
+ ret2 = ext4_journal_stop(handle);
+ break;
}
+- if (ret > 0) {
+- /* check wrap through sign-bit/zero here */
+- if ((block + ret) < 0 || (block + ret) < block) {
+- ret = -EIO;
+- ext4_mark_inode_dirty(handle, inode);
+- ret2 = ext4_journal_stop(handle);
+- break;
+- }
+- if (buffer_new(&map_bh) && ((block + ret) >
+- (EXT4_BLOCK_ALIGN(i_size_read(inode), blkbits)
+- >> blkbits)))
+- nblocks = nblocks + ret;
+- }
+-
+- /* Update ctime if new blocks get allocated */
+- if (nblocks) {
+- struct timespec now;
+-
+- now = current_fs_time(inode->i_sb);
+- if (!timespec_equal(&inode->i_ctime, &now))
+- inode->i_ctime = now;
+- }
++ if ((block + ret) >= (EXT4_BLOCK_ALIGN(offset + len,
++ blkbits) >> blkbits))
++ new_size = offset + len;
++ else
++ new_size = (block + ret) << blkbits;
-@@ -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;
++ ext4_falloc_update_inode(inode, mode, new_size,
++ buffer_new(&map_bh));
+ ext4_mark_inode_dirty(handle, inode);
+ ret2 = ext4_journal_stop(handle);
+ if (ret2)
+ break;
}
- 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 (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
++ if (ret == -ENOSPC &&
++ ext4_should_retry_alloc(inode->i_sb, &retries)) {
++ ret = 0;
+ goto retry;
+-
+- /*
+- * Time to update the file size.
+- * Update only when preallocation was requested beyond the file size.
+- */
+- if (!(mode & FALLOC_FL_KEEP_SIZE) &&
+- (offset + len) > i_size_read(inode)) {
+- if (ret > 0) {
+- /*
+- * if no error, we assume preallocation succeeded
+- * completely
+- */
+- i_size_write(inode, offset + len);
+- EXT4_I(inode)->i_disksize = i_size_read(inode);
+- } else if (ret < 0 && nblocks) {
+- /* Handle partial allocation scenario */
+- loff_t newsize;
+-
+- newsize = (nblocks << blkbits) + i_size_read(inode);
+- i_size_write(inode, EXT4_BLOCK_ALIGN(newsize, blkbits));
+- EXT4_I(inode)->i_disksize = i_size_read(inode);
+- }
+ }
+-
+ mutex_unlock(&inode->i_mutex);
+ return ret > 0 ? ret2 : ret;
+ }
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index ac35ec5..4159be6 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -21,8 +21,8 @@
+ #include <linux/time.h>
+ #include <linux/fs.h>
+ #include <linux/jbd2.h>
+-#include <linux/ext4_fs.h>
+-#include <linux/ext4_jbd2.h>
++#include "ext4.h"
++#include "ext4_jbd2.h"
+ #include "xattr.h"
+ #include "acl.h"
+
+@@ -129,7 +129,7 @@ const struct file_operations ext4_file_operations = {
+ .write = do_sync_write,
+ .aio_read = generic_file_aio_read,
+ .aio_write = ext4_file_write,
+- .ioctl = ext4_ioctl,
++ .unlocked_ioctl = ext4_ioctl,
+ #ifdef CONFIG_COMPAT
+ .compat_ioctl = ext4_compat_ioctl,
+ #endif
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index 8d50879..1c8ba48 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -27,8 +27,8 @@
+ #include <linux/sched.h>
+ #include <linux/writeback.h>
+ #include <linux/jbd2.h>
+-#include <linux/ext4_fs.h>
+-#include <linux/ext4_jbd2.h>
++#include "ext4.h"
++#include "ext4_jbd2.h"
- if (get_user(rsv_window_size, (int __user *)arg))
- return -EFAULT;
+ /*
+ * akpm: A new design for ext4_sync_file().
+@@ -72,6 +72,9 @@ int ext4_sync_file(struct file * file, struct dentry *dentry, int datasync)
+ goto out;
+ }
-+ ret = mnt_want_write(filp->f_path.mnt);
-+ if (ret)
-+ return ret;
++ if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
++ goto out;
+
- if (rsv_window_size > EXT2_MAX_RESERVE_BLOCKS)
- rsv_window_size = EXT2_MAX_RESERVE_BLOCKS;
+ /*
+ * The VFS has written the file data. If the inode is unaltered
+ * then we need not start a commit.
+diff --git a/fs/ext4/hash.c b/fs/ext4/hash.c
+index 1555024..1d6329d 100644
+--- a/fs/ext4/hash.c
++++ b/fs/ext4/hash.c
+@@ -11,8 +11,8 @@
-@@ -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)
+ #include <linux/fs.h>
+ #include <linux/jbd2.h>
+-#include <linux/ext4_fs.h>
+ #include <linux/cryptohash.h>
++#include "ext4.h"
+
+ #define DELTA 0x9E3779B9
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 8036b9b..c6efbab 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -15,8 +15,6 @@
+ #include <linux/time.h>
+ #include <linux/fs.h>
+ #include <linux/jbd2.h>
+-#include <linux/ext4_fs.h>
+-#include <linux/ext4_jbd2.h>
+ #include <linux/stat.h>
+ #include <linux/string.h>
+ #include <linux/quotaops.h>
+@@ -25,7 +23,8 @@
+ #include <linux/bitops.h>
+ #include <linux/blkdev.h>
+ #include <asm/byteorder.h>
+-
++#include "ext4.h"
++#include "ext4_jbd2.h"
+ #include "xattr.h"
+ #include "acl.h"
+ #include "group.h"
+@@ -75,7 +74,7 @@ unsigned ext4_init_inode_bitmap(struct super_block *sb, struct buffer_head *bh,
+ /* If checksum is bad mark all blocks and inodes use to prevent
+ * allocation, essentially implementing a per-group read-only flag. */
+ if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
+- ext4_error(sb, __FUNCTION__, "Checksum bad for group %lu\n",
++ ext4_error(sb, __func__, "Checksum bad for group %lu\n",
+ block_group);
+ gdp->bg_free_blocks_count = 0;
+ gdp->bg_free_inodes_count = 0;
+@@ -223,11 +222,9 @@ void ext4_free_inode (handle_t *handle, struct inode * inode)
+
+ if (gdp) {
+ spin_lock(sb_bgl_lock(sbi, block_group));
+- gdp->bg_free_inodes_count = cpu_to_le16(
+- le16_to_cpu(gdp->bg_free_inodes_count) + 1);
++ le16_add_cpu(&gdp->bg_free_inodes_count, 1);
+ if (is_directory)
+- gdp->bg_used_dirs_count = cpu_to_le16(
+- le16_to_cpu(gdp->bg_used_dirs_count) - 1);
++ le16_add_cpu(&gdp->bg_used_dirs_count, -1);
+ gdp->bg_checksum = ext4_group_desc_csum(sbi,
+ block_group, gdp);
+ spin_unlock(sb_bgl_lock(sbi, block_group));
+@@ -305,7 +302,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).
@@ -731898,11 +976773,119 @@
* 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:
+@@ -588,7 +585,7 @@ got:
+ ino++;
+ if ((group == 0 && ino < EXT4_FIRST_INO(sb)) ||
+ ino > EXT4_INODES_PER_GROUP(sb)) {
+- ext4_error(sb, __FUNCTION__,
++ ext4_error(sb, __func__,
+ "reserved inode or inode > inodes count - "
+ "block_group = %lu, inode=%lu", group,
+ ino + group * EXT4_INODES_PER_GROUP(sb));
+@@ -664,11 +661,9 @@ got:
+ cpu_to_le16(EXT4_INODES_PER_GROUP(sb) - ino);
+ }
+
+- gdp->bg_free_inodes_count =
+- cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
++ le16_add_cpu(&gdp->bg_free_inodes_count, -1);
+ if (S_ISDIR(mode)) {
+- gdp->bg_used_dirs_count =
+- cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1);
++ le16_add_cpu(&gdp->bg_used_dirs_count, 1);
+ }
+ gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp);
+ spin_unlock(sb_bgl_lock(sbi, group));
+@@ -744,23 +739,24 @@ got:
+ if (err)
+ goto fail_free_drop;
+
+- err = ext4_mark_inode_dirty(handle, inode);
+- if (err) {
+- ext4_std_error(sb, err);
+- goto fail_free_drop;
+- }
+ if (test_opt(sb, EXTENTS)) {
+- /* set extent flag only for directory and file */
+- if (S_ISDIR(mode) || S_ISREG(mode)) {
++ /* set extent flag only for diretory, file and normal symlink*/
++ if (S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) {
+ EXT4_I(inode)->i_flags |= EXT4_EXTENTS_FL;
+ ext4_ext_tree_init(handle, inode);
+ err = ext4_update_incompat_feature(handle, sb,
+ EXT4_FEATURE_INCOMPAT_EXTENTS);
+ if (err)
+- goto fail;
++ goto fail_free_drop;
+ }
+ }
+
++ err = ext4_mark_inode_dirty(handle, inode);
++ if (err) {
++ ext4_std_error(sb, err);
++ goto fail_free_drop;
++ }
++
+ ext4_debug("allocating inode %lu\n", inode->i_ino);
+ goto really_out;
+ fail:
+@@ -796,7 +792,7 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
+
+ /* Error cases - e2fsck has already cleaned up for us */
+ if (ino > max_ino) {
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "bad orphan ino %lu! e2fsck was run?", ino);
+ goto error;
+ }
+@@ -805,7 +801,7 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
+ bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb);
+ bitmap_bh = read_inode_bitmap(sb, block_group);
+ if (!bitmap_bh) {
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "inode bitmap error for orphan %lu", ino);
+ goto error;
+ }
+@@ -830,7 +826,7 @@ iget_failed:
+ err = PTR_ERR(inode);
+ inode = NULL;
+ bad_orphan:
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "bad orphan inode %lu! e2fsck was run?", ino);
+ printk(KERN_NOTICE "ext4_test_bit(bit=%d, block=%llu) = %d\n",
+ bit, (unsigned long long)bitmap_bh->b_blocknr,
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 945cbf6..8d97077 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -25,7 +25,6 @@
+ #include <linux/module.h>
+ #include <linux/fs.h>
+ #include <linux/time.h>
+-#include <linux/ext4_jbd2.h>
+ #include <linux/jbd2.h>
+ #include <linux/highuid.h>
+ #include <linux/pagemap.h>
+@@ -36,6 +35,7 @@
+ #include <linux/mpage.h>
+ #include <linux/uio.h>
+ #include <linux/bio.h>
++#include "ext4_jbd2.h"
+ #include "xattr.h"
+ #include "acl.h"
+
+@@ -93,7 +93,7 @@ int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
+ BUFFER_TRACE(bh, "call ext4_journal_revoke");
+ err = ext4_journal_revoke(handle, blocknr, bh);
+ if (err)
+- ext4_abort(inode->i_sb, __FUNCTION__,
++ ext4_abort(inode->i_sb, __func__,
+ "error %d when attempting revoke", err);
+ BUFFER_TRACE(bh, "exit");
+ return err;
+@@ -382,7 +382,7 @@ no_block:
* @inode: owner
* @ind: descriptor of indirect block.
*
@@ -731911,12 +976894,12 @@
* 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)
+@@ -432,12 +432,12 @@ static ext4_fsblk_t ext4_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.
+- * 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
@@ -731925,95 +976908,244 @@
+ * 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,
+@@ -985,6 +985,16 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block,
+ } else {
+ retval = ext4_get_blocks_handle(handle, inode, block,
+ max_blocks, bh, create, extend_disksize);
++
++ if (retval > 0 && buffer_new(bh)) {
++ /*
++ * We allocated new blocks which will result in
++ * i_data's format changing. Force the migrate
++ * to fail by clearing migrate flags
++ */
++ EXT4_I(inode)->i_flags = EXT4_I(inode)->i_flags &
++ ~EXT4_EXT_MIGRATE;
++ }
+ }
+ up_write((&EXT4_I(inode)->i_data_sem));
+ return retval;
+@@ -1230,7 +1240,7 @@ int ext4_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
+ {
+ int err = jbd2_journal_dirty_data(handle, bh);
+ if (err)
+- ext4_journal_abort_handle(__FUNCTION__, __FUNCTION__,
++ ext4_journal_abort_handle(__func__, __func__,
+ bh, handle, err);
+ return err;
+ }
+@@ -1301,10 +1311,11 @@ static int ext4_ordered_write_end(struct file *file,
+ new_i_size = pos + copied;
+ if (new_i_size > EXT4_I(inode)->i_disksize)
+ EXT4_I(inode)->i_disksize = new_i_size;
+- copied = ext4_generic_write_end(file, mapping, pos, len, copied,
++ ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
+ page, fsdata);
+- if (copied < 0)
+- ret = copied;
++ copied = ret2;
++ if (ret2 < 0)
++ ret = ret2;
+ }
+ ret2 = ext4_journal_stop(handle);
+ if (!ret)
+@@ -1329,10 +1340,11 @@ static int ext4_writeback_write_end(struct file *file,
+ if (new_i_size > EXT4_I(inode)->i_disksize)
+ EXT4_I(inode)->i_disksize = new_i_size;
+
+- copied = ext4_generic_write_end(file, mapping, pos, len, copied,
++ ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
+ page, fsdata);
+- if (copied < 0)
+- ret = copied;
++ copied = ret2;
++ if (ret2 < 0)
++ ret = ret2;
-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 @@
+ ret2 = ext4_journal_stop(handle);
+ if (!ret)
+@@ -2501,12 +2513,10 @@ out_stop:
+ static ext4_fsblk_t ext4_get_inode_block(struct super_block *sb,
+ unsigned long ino, struct ext4_iloc *iloc)
+ {
+- unsigned long desc, group_desc;
+ ext4_group_t block_group;
+ unsigned long offset;
+ ext4_fsblk_t block;
+- struct buffer_head *bh;
+- struct ext4_group_desc * gdp;
++ struct ext4_group_desc *gdp;
+
+ if (!ext4_valid_inum(sb, ino)) {
+ /*
+@@ -2518,22 +2528,10 @@ static ext4_fsblk_t ext4_get_inode_block(struct super_block *sb,
+ }
+
+ block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
+- if (block_group >= EXT4_SB(sb)->s_groups_count) {
+- ext4_error(sb,"ext4_get_inode_block","group >= groups count");
++ gdp = ext4_get_group_desc(sb, block_group, NULL);
++ if (!gdp)
+ return 0;
+- }
+- smp_rmb();
+- group_desc = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb);
+- desc = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1);
+- bh = EXT4_SB(sb)->s_group_desc[group_desc];
+- if (!bh) {
+- ext4_error (sb, "ext4_get_inode_block",
+- "Descriptor not loaded");
+- return 0;
+- }
+
+- gdp = (struct ext4_group_desc *)((__u8 *)bh->b_data +
+- desc * EXT4_DESC_SIZE(sb));
+ /*
+ * Figure out the offset within the block group inode table
+ */
+@@ -2976,7 +2974,8 @@ static int ext4_do_update_inode(handle_t *handle,
+ if (ext4_inode_blocks_set(handle, raw_inode, ei))
+ goto out_brelse;
+ raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
+- raw_inode->i_flags = cpu_to_le32(ei->i_flags);
++ /* clear the migrate flag in the raw_inode */
++ raw_inode->i_flags = cpu_to_le32(ei->i_flags & ~EXT4_EXT_MIGRATE);
+ if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
+ cpu_to_le32(EXT4_OS_HURD))
+ raw_inode->i_file_acl_high =
+@@ -3374,7 +3373,7 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode)
+ EXT4_I(inode)->i_state |= EXT4_STATE_NO_EXPAND;
+ if (mnt_count !=
+ le16_to_cpu(sbi->s_es->s_mnt_count)) {
+- ext4_warning(inode->i_sb, __FUNCTION__,
++ ext4_warning(inode->i_sb, __func__,
+ "Unable to expand inode %lu. Delete"
+ " some EAs or run e2fsck.",
+ inode->i_ino);
+@@ -3415,7 +3414,7 @@ void ext4_dirty_inode(struct inode *inode)
+ current_handle->h_transaction != handle->h_transaction) {
+ /* This task has a transaction open against a different fs */
+ printk(KERN_EMERG "%s: transactions do not match!\n",
+- __FUNCTION__);
++ __func__);
+ } else {
+ jbd_debug(5, "marking dirty. outer handle=%p\n",
+ current_handle);
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 2ed7c37..7a6c2f1 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -10,16 +10,17 @@
+ #include <linux/fs.h>
+ #include <linux/jbd2.h>
#include <linux/capability.h>
- #include <linux/ext3_fs.h>
- #include <linux/ext3_jbd.h>
-+#include <linux/mount.h>
+-#include <linux/ext4_fs.h>
+-#include <linux/ext4_jbd2.h>
#include <linux/time.h>
#include <linux/compat.h>
#include <linux/smp_lock.h>
-@@ -38,14 +39,19 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
++#include <linux/mount.h>
+ #include <asm/uaccess.h>
++#include "ext4_jbd2.h"
++#include "ext4.h"
+
+-int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+- unsigned long arg)
++long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ {
++ struct inode *inode = filp->f_dentry->d_inode;
+ struct ext4_inode_info *ei = EXT4_I(inode);
+ unsigned int flags;
+ unsigned short rsv_window_size;
+@@ -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 (!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,
+ 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);
+- if (IS_NOQUOTA(inode)) {
+- mutex_unlock(&inode->i_mutex);
- return -EPERM;
-+ err = -EPERM;
+- }
++ if (IS_NOQUOTA(inode))
+ 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);
+ /* 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;
-+ err = -EPERM;
+- }
++ if (!capable(CAP_LINUX_IMMUTABLE))
+ 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);
+ /*
+@@ -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;
-+ err = -EPERM;
+- }
++ if (!capable(CAP_SYS_RESOURCE))
+ 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);
+-
+ handle = ext4_journal_start(inode, 1);
if (IS_ERR(handle)) {
- mutex_unlock(&inode->i_mutex);
+- 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);
+@@ -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 EXT3_IOC_GETVERSION:
-@@ -129,14 +141,18 @@ flags_err:
+ case EXT4_IOC_GETVERSION:
+@@ -129,14 +126,20 @@ flags_err:
if (!is_owner_or_cap(inode))
return -EPERM;
@@ -732021,7 +977153,7 @@
- return -EROFS;
- if (get_user(generation, (int __user *) arg))
- return -EFAULT;
--
++
+ err = mnt_want_write(filp->f_path.mnt);
+ if (err)
+ return err;
@@ -732029,29 +977161,30 @@
+ err = -EFAULT;
+ goto setversion_out;
+ }
- handle = ext3_journal_start(inode, 1);
+
+ 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 = ext3_reserve_inode_write(handle, inode, &iloc);
+ err = ext4_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);
+ inode->i_ctime = ext4_current_time(inode);
+@@ -144,6 +147,8 @@ flags_err:
+ err = ext4_mark_iloc_dirty(handle, inode, &iloc);
}
- ext3_journal_stop(handle);
+ ext4_journal_stop(handle);
+setversion_out:
+ mnt_drop_write(filp->f_path.mnt);
return err;
}
- #ifdef CONFIG_JBD_DEBUG
-@@ -179,18 +197,24 @@ flags_err:
+ #ifdef CONFIG_JBD2_DEBUG
+@@ -179,19 +184,21 @@ flags_err:
}
return -ENOTTY;
- case EXT3_IOC_SETRSVSZ: {
+ case EXT4_IOC_SETRSVSZ: {
+ int err;
if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
@@ -732059,540 +977192,4564 @@
- 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;
-- 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:
+@@ -208,6 +215,7 @@ flags_err:
rsv->rsv_goal_size = rsv_window_size;
}
- mutex_unlock(&ei->truncate_mutex);
-- return 0;
-+setrsvsz_out:
+ up_write(&ei->i_data_sem);
+ mnt_drop_write(filp->f_path.mnt);
-+ return err;
+ return 0;
}
- case EXT3_IOC_GROUP_EXTEND: {
- ext3_fsblk_t n_blocks_count;
-@@ -218,17 +244,20 @@ flags_err:
+ 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;
+ 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:
++
+ 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;
}
- case EXT3_IOC_GROUP_ADD: {
-@@ -239,18 +268,22 @@ flags_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;
-
- 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:
++
+ 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/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)
+@@ -265,9 +277,6 @@ flags_err:
+ #ifdef CONFIG_COMPAT
+ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+- struct inode *inode = file->f_path.dentry->d_inode;
+- int ret;
+-
+ /* These are just misnamed, they actually get/put from/to user an int */
+ switch (cmd) {
+ case EXT4_IOC32_GETFLAGS:
+@@ -307,9 +316,6 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ default:
+ return -ENOIOCTLCMD;
+ }
+- lock_kernel();
+- ret = ext4_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
+- unlock_kernel();
+- return ret;
++ return ext4_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
}
+ #endif
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index ef97f19..fbec2ef 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -21,21 +21,7 @@
+ * mballoc.c contains the multiblocks allocation routines
+ */
- /**
-- * 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
+-#include <linux/time.h>
+-#include <linux/fs.h>
+-#include <linux/namei.h>
+-#include <linux/ext4_jbd2.h>
+-#include <linux/ext4_fs.h>
+-#include <linux/quotaops.h>
+-#include <linux/buffer_head.h>
+-#include <linux/module.h>
+-#include <linux/swap.h>
+-#include <linux/proc_fs.h>
+-#include <linux/pagemap.h>
+-#include <linux/seq_file.h>
+-#include <linux/version.h>
+-#include "group.h"
+-
++#include "mballoc.h"
+ /*
+ * MUSTDO:
+ * - test ext4_ext_search_left() and ext4_ext_search_right()
+@@ -345,288 +331,6 @@
*
-- * Normally this function find the prefered place for block allocation,
-+ * Normally this function find the preferred place for block allocation,
- * returns it.
*/
- static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block,
-diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
-index 2ed7c37..25b13ed 100644
---- a/fs/ext4/ioctl.c
-+++ b/fs/ext4/ioctl.c
-@@ -15,6 +15,7 @@
- #include <linux/time.h>
- #include <linux/compat.h>
- #include <linux/smp_lock.h>
-+#include <linux/mount.h>
- #include <asm/uaccess.h>
- int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
-@@ -38,24 +39,25 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
- unsigned int oldflags;
- unsigned int jflag;
+-/*
+- * with AGGRESSIVE_CHECK allocator runs consistency checks over
+- * structures. these checks slow things down a lot
+- */
+-#define AGGRESSIVE_CHECK__
+-
+-/*
+- * with DOUBLE_CHECK defined mballoc creates persistent in-core
+- * bitmaps, maintains and uses them to check for double allocations
+- */
+-#define DOUBLE_CHECK__
+-
+-/*
+- */
+-#define MB_DEBUG__
+-#ifdef MB_DEBUG
+-#define mb_debug(fmt, a...) printk(fmt, ##a)
+-#else
+-#define mb_debug(fmt, a...)
+-#endif
+-
+-/*
+- * with EXT4_MB_HISTORY mballoc stores last N allocations in memory
+- * and you can monitor it in /proc/fs/ext4/<dev>/mb_history
+- */
+-#define EXT4_MB_HISTORY
+-#define EXT4_MB_HISTORY_ALLOC 1 /* allocation */
+-#define EXT4_MB_HISTORY_PREALLOC 2 /* preallocated blocks used */
+-#define EXT4_MB_HISTORY_DISCARD 4 /* preallocation discarded */
+-#define EXT4_MB_HISTORY_FREE 8 /* free */
+-
+-#define EXT4_MB_HISTORY_DEFAULT (EXT4_MB_HISTORY_ALLOC | \
+- EXT4_MB_HISTORY_PREALLOC)
+-
+-/*
+- * How long mballoc can look for a best extent (in found extents)
+- */
+-#define MB_DEFAULT_MAX_TO_SCAN 200
+-
+-/*
+- * How long mballoc must look for a best extent
+- */
+-#define MB_DEFAULT_MIN_TO_SCAN 10
+-
+-/*
+- * How many groups mballoc will scan looking for the best chunk
+- */
+-#define MB_DEFAULT_MAX_GROUPS_TO_SCAN 5
+-
+-/*
+- * with 'ext4_mb_stats' allocator will collect stats that will be
+- * shown at umount. The collecting costs though!
+- */
+-#define MB_DEFAULT_STATS 1
+-
+-/*
+- * files smaller than MB_DEFAULT_STREAM_THRESHOLD are served
+- * by the stream allocator, which purpose is to pack requests
+- * as close each to other as possible to produce smooth I/O traffic
+- * We use locality group prealloc space for stream request.
+- * We can tune the same via /proc/fs/ext4/<parition>/stream_req
+- */
+-#define MB_DEFAULT_STREAM_THRESHOLD 16 /* 64K */
+-
+-/*
+- * for which requests use 2^N search using buddies
+- */
+-#define MB_DEFAULT_ORDER2_REQS 2
+-
+-/*
+- * default group prealloc size 512 blocks
+- */
+-#define MB_DEFAULT_GROUP_PREALLOC 512
+-
+-static struct kmem_cache *ext4_pspace_cachep;
+-static struct kmem_cache *ext4_ac_cachep;
+-
+-#ifdef EXT4_BB_MAX_BLOCKS
+-#undef EXT4_BB_MAX_BLOCKS
+-#endif
+-#define EXT4_BB_MAX_BLOCKS 30
+-
+-struct ext4_free_metadata {
+- ext4_group_t group;
+- unsigned short num;
+- ext4_grpblk_t blocks[EXT4_BB_MAX_BLOCKS];
+- struct list_head list;
+-};
+-
+-struct ext4_group_info {
+- unsigned long bb_state;
+- unsigned long bb_tid;
+- struct ext4_free_metadata *bb_md_cur;
+- unsigned short bb_first_free;
+- unsigned short bb_free;
+- unsigned short bb_fragments;
+- struct list_head bb_prealloc_list;
+-#ifdef DOUBLE_CHECK
+- void *bb_bitmap;
+-#endif
+- unsigned short bb_counters[];
+-};
+-
+-#define EXT4_GROUP_INFO_NEED_INIT_BIT 0
+-#define EXT4_GROUP_INFO_LOCKED_BIT 1
+-
+-#define EXT4_MB_GRP_NEED_INIT(grp) \
+- (test_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &((grp)->bb_state)))
+-
+-
+-struct ext4_prealloc_space {
+- struct list_head pa_inode_list;
+- struct list_head pa_group_list;
+- union {
+- struct list_head pa_tmp_list;
+- struct rcu_head pa_rcu;
+- } u;
+- spinlock_t pa_lock;
+- atomic_t pa_count;
+- unsigned pa_deleted;
+- ext4_fsblk_t pa_pstart; /* phys. block */
+- ext4_lblk_t pa_lstart; /* log. block */
+- unsigned short pa_len; /* len of preallocated chunk */
+- unsigned short pa_free; /* how many blocks are free */
+- unsigned short pa_linear; /* consumed in one direction
+- * strictly, for grp prealloc */
+- spinlock_t *pa_obj_lock;
+- struct inode *pa_inode; /* hack, for history only */
+-};
+-
+-
+-struct ext4_free_extent {
+- ext4_lblk_t fe_logical;
+- ext4_grpblk_t fe_start;
+- ext4_group_t fe_group;
+- int fe_len;
+-};
+-
+-/*
+- * Locality group:
+- * we try to group all related changes together
+- * so that writeback can flush/allocate them together as well
+- */
+-struct ext4_locality_group {
+- /* for allocator */
+- struct mutex lg_mutex; /* to serialize allocates */
+- struct list_head lg_prealloc_list;/* list of preallocations */
+- spinlock_t lg_prealloc_lock;
+-};
+-
+-struct ext4_allocation_context {
+- struct inode *ac_inode;
+- struct super_block *ac_sb;
+-
+- /* original request */
+- struct ext4_free_extent ac_o_ex;
+-
+- /* goal request (after normalization) */
+- struct ext4_free_extent ac_g_ex;
+-
+- /* the best found extent */
+- struct ext4_free_extent ac_b_ex;
+-
+- /* copy of the bext found extent taken before preallocation efforts */
+- struct ext4_free_extent ac_f_ex;
+-
+- /* number of iterations done. we have to track to limit searching */
+- unsigned long ac_ex_scanned;
+- __u16 ac_groups_scanned;
+- __u16 ac_found;
+- __u16 ac_tail;
+- __u16 ac_buddy;
+- __u16 ac_flags; /* allocation hints */
+- __u8 ac_status;
+- __u8 ac_criteria;
+- __u8 ac_repeats;
+- __u8 ac_2order; /* if request is to allocate 2^N blocks and
+- * N > 0, the field stores N, otherwise 0 */
+- __u8 ac_op; /* operation, for history only */
+- struct page *ac_bitmap_page;
+- struct page *ac_buddy_page;
+- struct ext4_prealloc_space *ac_pa;
+- struct ext4_locality_group *ac_lg;
+-};
+-
+-#define AC_STATUS_CONTINUE 1
+-#define AC_STATUS_FOUND 2
+-#define AC_STATUS_BREAK 3
+-
+-struct ext4_mb_history {
+- struct ext4_free_extent orig; /* orig allocation */
+- struct ext4_free_extent goal; /* goal allocation */
+- struct ext4_free_extent result; /* result allocation */
+- unsigned pid;
+- unsigned ino;
+- __u16 found; /* how many extents have been found */
+- __u16 groups; /* how many groups have been scanned */
+- __u16 tail; /* what tail broke some buddy */
+- __u16 buddy; /* buddy the tail ^^^ broke */
+- __u16 flags;
+- __u8 cr:3; /* which phase the result extent was found at */
+- __u8 op:4;
+- __u8 merged:1;
+-};
+-
+-struct ext4_buddy {
+- struct page *bd_buddy_page;
+- void *bd_buddy;
+- struct page *bd_bitmap_page;
+- void *bd_bitmap;
+- struct ext4_group_info *bd_info;
+- struct super_block *bd_sb;
+- __u16 bd_blkbits;
+- ext4_group_t bd_group;
+-};
+-#define EXT4_MB_BITMAP(e4b) ((e4b)->bd_bitmap)
+-#define EXT4_MB_BUDDY(e4b) ((e4b)->bd_buddy)
+-
+-#ifndef EXT4_MB_HISTORY
+-static inline void ext4_mb_store_history(struct ext4_allocation_context *ac)
+-{
+- return;
+-}
+-#else
+-static void ext4_mb_store_history(struct ext4_allocation_context *ac);
+-#endif
+-
+-#define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1)
+-
+-static struct proc_dir_entry *proc_root_ext4;
+-struct buffer_head *read_block_bitmap(struct super_block *, ext4_group_t);
+-ext4_fsblk_t ext4_new_blocks_old(handle_t *handle, struct inode *inode,
+- ext4_fsblk_t goal, unsigned long *count, int *errp);
+-
+-static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
+- ext4_group_t group);
+-static void ext4_mb_poll_new_transaction(struct super_block *, handle_t *);
+-static void ext4_mb_free_committed_blocks(struct super_block *);
+-static void ext4_mb_return_to_preallocation(struct inode *inode,
+- struct ext4_buddy *e4b, sector_t block,
+- int count);
+-static void ext4_mb_put_pa(struct ext4_allocation_context *,
+- struct super_block *, struct ext4_prealloc_space *pa);
+-static int ext4_mb_init_per_dev_proc(struct super_block *sb);
+-static int ext4_mb_destroy_per_dev_proc(struct super_block *sb);
+-
+-
+-static inline void ext4_lock_group(struct super_block *sb, ext4_group_t group)
+-{
+- struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
+-
+- bit_spin_lock(EXT4_GROUP_INFO_LOCKED_BIT, &(grinfo->bb_state));
+-}
+-
+-static inline void ext4_unlock_group(struct super_block *sb,
+- ext4_group_t group)
+-{
+- struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
+-
+- bit_spin_unlock(EXT4_GROUP_INFO_LOCKED_BIT, &(grinfo->bb_state));
+-}
+-
+-static inline int ext4_is_group_locked(struct super_block *sb,
+- ext4_group_t group)
+-{
+- struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
+-
+- return bit_spin_is_locked(EXT4_GROUP_INFO_LOCKED_BIT,
+- &(grinfo->bb_state));
+-}
+-
+-static ext4_fsblk_t ext4_grp_offs_to_block(struct super_block *sb,
+- struct ext4_free_extent *fex)
+-{
+- ext4_fsblk_t block;
+-
+- block = (ext4_fsblk_t) fex->fe_group * EXT4_BLOCKS_PER_GROUP(sb)
+- + fex->fe_start
+- + le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
+- return block;
+-}
+-
+ static inline void *mb_correct_addr_and_bit(int *bit, void *addr)
+ {
+ #if BITS_PER_LONG == 64
+@@ -736,7 +440,7 @@ static void mb_free_blocks_double(struct inode *inode, struct ext4_buddy *e4b,
+ blocknr +=
+ le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
+
+- ext4_error(sb, __FUNCTION__, "double-free of inode"
++ ext4_error(sb, __func__, "double-free of inode"
+ " %lu's block %llu(bit %u in group %lu)\n",
+ inode ? inode->i_ino : 0, blocknr,
+ first + i, e4b->bd_group);
+@@ -898,17 +602,17 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file,
+ list_for_each(cur, &grp->bb_prealloc_list) {
+ ext4_group_t groupnr;
+ struct ext4_prealloc_space *pa;
+- pa = list_entry(cur, struct ext4_prealloc_space, group_list);
+- ext4_get_group_no_and_offset(sb, pa->pstart, &groupnr, &k);
++ pa = list_entry(cur, struct ext4_prealloc_space, pa_group_list);
++ ext4_get_group_no_and_offset(sb, pa->pa_pstart, &groupnr, &k);
+ MB_CHECK_ASSERT(groupnr == e4b->bd_group);
+- for (i = 0; i < pa->len; i++)
++ for (i = 0; i < pa->pa_len; i++)
+ MB_CHECK_ASSERT(mb_test_bit(k + i, buddy));
+ }
+ return 0;
+ }
+ #undef MB_CHECK_ASSERT
+ #define mb_check_buddy(e4b) __mb_check_buddy(e4b, \
+- __FILE__, __FUNCTION__, __LINE__)
++ __FILE__, __func__, __LINE__)
+ #else
+ #define mb_check_buddy(e4b)
+ #endif
+@@ -982,7 +686,7 @@ static void ext4_mb_generate_buddy(struct super_block *sb,
+ grp->bb_fragments = fragments;
-- if (IS_RDONLY(inode))
-- return -EROFS;
+ if (free != grp->bb_free) {
+- ext4_error(sb, __FUNCTION__,
++ ext4_error(sb, __func__,
+ "EXT4-fs: group %lu: %u blocks in bitmap, %u in gd\n",
+ group, free, grp->bb_free);
+ /*
+@@ -1168,8 +872,9 @@ out:
+ return err;
+ }
+
+-static int ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
+- struct ext4_buddy *e4b)
++static noinline_for_stack int
++ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
++ struct ext4_buddy *e4b)
+ {
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
+ struct inode *inode = sbi->s_buddy_cache;
+@@ -1367,7 +1072,7 @@ static int mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
+ blocknr +=
+ le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
+
+- ext4_error(sb, __FUNCTION__, "double-free of inode"
++ ext4_error(sb, __func__, "double-free of inode"
+ " %lu's block %llu(bit %u in group %lu)\n",
+ inode ? inode->i_ino : 0, blocknr, block,
+ e4b->bd_group);
+@@ -1848,7 +1553,7 @@ static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
+ * free blocks even though group info says we
+ * we have free blocks
+ */
+- ext4_error(sb, __FUNCTION__, "%d free blocks as per "
++ ext4_error(sb, __func__, "%d free blocks as per "
+ "group info. But bitmap says 0\n",
+ free);
+ break;
+@@ -1857,7 +1562,7 @@ static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
+ mb_find_extent(e4b, 0, i, ac->ac_g_ex.fe_len, &ex);
+ BUG_ON(ex.fe_len <= 0);
+ if (free < ex.fe_len) {
+- ext4_error(sb, __FUNCTION__, "%d free blocks as per "
++ ext4_error(sb, __func__, "%d free blocks as per "
+ "group info. But got %d blocks\n",
+ free, ex.fe_len);
+ /*
+@@ -1965,7 +1670,8 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
+ return 0;
+ }
+
+-static int ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
++static noinline_for_stack int
++ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
+ {
+ ext4_group_t group;
+ ext4_group_t i;
+@@ -2449,17 +2155,10 @@ static void ext4_mb_history_init(struct super_block *sb)
+ int i;
+
+ if (sbi->s_mb_proc != NULL) {
+- struct proc_dir_entry *p;
+- p = create_proc_entry("mb_history", S_IRUGO, sbi->s_mb_proc);
+- if (p) {
+- p->proc_fops = &ext4_mb_seq_history_fops;
+- p->data = sb;
+- }
+- p = create_proc_entry("mb_groups", S_IRUGO, sbi->s_mb_proc);
+- if (p) {
+- p->proc_fops = &ext4_mb_seq_groups_fops;
+- p->data = sb;
+- }
++ proc_create_data("mb_history", S_IRUGO, sbi->s_mb_proc,
++ &ext4_mb_seq_history_fops, sb);
++ proc_create_data("mb_groups", S_IRUGO, sbi->s_mb_proc,
++ &ext4_mb_seq_groups_fops, sb);
+ }
+
+ sbi->s_mb_history_max = 1000;
+@@ -2472,7 +2171,8 @@ static void ext4_mb_history_init(struct super_block *sb)
+ /* if we can't allocate history, then we simple won't use it */
+ }
+
+-static void ext4_mb_store_history(struct ext4_allocation_context *ac)
++static noinline_for_stack void
++ext4_mb_store_history(struct ext4_allocation_context *ac)
+ {
+ struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
+ struct ext4_mb_history h;
+@@ -2572,13 +2272,13 @@ static int ext4_mb_init_backend(struct super_block *sb)
+ meta_group_info[j] = kzalloc(len, GFP_KERNEL);
+ if (meta_group_info[j] == NULL) {
+ printk(KERN_ERR "EXT4-fs: can't allocate buddy mem\n");
+- i--;
+ goto err_freebuddy;
+ }
+ desc = ext4_get_group_desc(sb, i, NULL);
+ if (desc == NULL) {
+ printk(KERN_ERR
+ "EXT4-fs: can't read descriptor %lu\n", i);
++ i++;
+ goto err_freebuddy;
+ }
+ memset(meta_group_info[j], 0, len);
+@@ -2618,13 +2318,11 @@ static int ext4_mb_init_backend(struct super_block *sb)
+ return 0;
+
+ err_freebuddy:
+- while (i >= 0) {
++ while (i-- > 0)
+ kfree(ext4_get_group_info(sb, i));
+- i--;
+- }
+ i = num_meta_group_infos;
+ err_freemeta:
+- while (--i >= 0)
++ while (i-- > 0)
+ kfree(sbi->s_group_info[i]);
+ iput(sbi->s_buddy_cache);
+ err_freesgi:
+@@ -2808,7 +2506,8 @@ int ext4_mb_release(struct super_block *sb)
+ return 0;
+ }
+
+-static void ext4_mb_free_committed_blocks(struct super_block *sb)
++static noinline_for_stack void
++ext4_mb_free_committed_blocks(struct super_block *sb)
+ {
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
+ int err;
+@@ -2867,7 +2566,6 @@ static void ext4_mb_free_committed_blocks(struct super_block *sb)
+ mb_debug("freed %u blocks in %u structures\n", count, count2);
+ }
+
+-#define EXT4_ROOT "ext4"
+ #define EXT4_MB_STATS_NAME "stats"
+ #define EXT4_MB_MAX_TO_SCAN_NAME "max_to_scan"
+ #define EXT4_MB_MIN_TO_SCAN_NAME "min_to_scan"
+@@ -3007,9 +2705,9 @@ int __init init_ext4_mballoc(void)
+ return -ENOMEM;
+ }
+ #ifdef CONFIG_PROC_FS
+- proc_root_ext4 = proc_mkdir(EXT4_ROOT, proc_root_fs);
++ proc_root_ext4 = proc_mkdir("fs/ext4", NULL);
+ if (proc_root_ext4 == NULL)
+- printk(KERN_ERR "EXT4-fs: Unable to create %s\n", EXT4_ROOT);
++ printk(KERN_ERR "EXT4-fs: Unable to create fs/ext4\n");
+ #endif
+ return 0;
+ }
+@@ -3020,7 +2718,7 @@ void exit_ext4_mballoc(void)
+ kmem_cache_destroy(ext4_pspace_cachep);
+ kmem_cache_destroy(ext4_ac_cachep);
+ #ifdef CONFIG_PROC_FS
+- remove_proc_entry(EXT4_ROOT, proc_root_fs);
++ remove_proc_entry("fs/ext4", NULL);
+ #endif
+ }
+
+@@ -3029,7 +2727,8 @@ void exit_ext4_mballoc(void)
+ * Check quota and mark choosed space (ac->ac_b_ex) non-free in bitmaps
+ * Returns 0 if success or error code
+ */
+-static int ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
++static noinline_for_stack int
++ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ handle_t *handle)
+ {
+ struct buffer_head *bitmap_bh = NULL;
+@@ -3078,7 +2777,7 @@ static int ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ in_range(block, ext4_inode_table(sb, gdp),
+ EXT4_SB(sb)->s_itb_per_group)) {
+
+- ext4_error(sb, __FUNCTION__,
++ ext4_error(sb, __func__,
+ "Allocating block in system zone - block = %llu",
+ block);
+ }
+@@ -3102,9 +2801,7 @@ static int ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ ac->ac_b_ex.fe_group,
+ gdp));
+ }
+- gdp->bg_free_blocks_count =
+- cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)
+- - ac->ac_b_ex.fe_len);
++ le16_add_cpu(&gdp->bg_free_blocks_count, -ac->ac_b_ex.fe_len);
+ gdp->bg_checksum = ext4_group_desc_csum(sbi, ac->ac_b_ex.fe_group, gdp);
+ spin_unlock(sb_bgl_lock(sbi, ac->ac_b_ex.fe_group));
+ percpu_counter_sub(&sbi->s_freeblocks_counter, ac->ac_b_ex.fe_len);
+@@ -3138,7 +2835,7 @@ static void ext4_mb_normalize_group_request(struct ext4_allocation_context *ac)
+ ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_stripe;
+ else
+ ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_mb_group_prealloc;
+- mb_debug("#%u: goal %lu blocks for locality group\n",
++ mb_debug("#%u: goal %u blocks for locality group\n",
+ current->pid, ac->ac_g_ex.fe_len);
+ }
+
+@@ -3146,15 +2843,16 @@ static void ext4_mb_normalize_group_request(struct ext4_allocation_context *ac)
+ * Normalization means making request better in terms of
+ * size and alignment
+ */
+-static void ext4_mb_normalize_request(struct ext4_allocation_context *ac,
++static noinline_for_stack void
++ext4_mb_normalize_request(struct ext4_allocation_context *ac,
+ struct ext4_allocation_request *ar)
+ {
+ int bsbits, max;
+ ext4_lblk_t end;
+- struct list_head *cur;
+ loff_t size, orig_size, start_off;
+ ext4_lblk_t start, orig_start;
+ struct ext4_inode_info *ei = EXT4_I(ac->ac_inode);
++ struct ext4_prealloc_space *pa;
+
+ /* do normalize only data requests, metadata requests
+ do not need preallocation */
+@@ -3240,12 +2938,9 @@ static void ext4_mb_normalize_request(struct ext4_allocation_context *ac,
+
+ /* check we don't cross already preallocated blocks */
+ rcu_read_lock();
+- list_for_each_rcu(cur, &ei->i_prealloc_list) {
+- struct ext4_prealloc_space *pa;
++ list_for_each_entry_rcu(pa, &ei->i_prealloc_list, pa_inode_list) {
+ unsigned long pa_end;
+
+- pa = list_entry(cur, struct ext4_prealloc_space, pa_inode_list);
-
- if (!is_owner_or_cap(inode))
- return -EACCES;
+ if (pa->pa_deleted)
+ continue;
+ spin_lock(&pa->pa_lock);
+@@ -3287,10 +2982,8 @@ static void ext4_mb_normalize_request(struct ext4_allocation_context *ac,
- if (get_user(flags, (int __user *) arg))
- return -EFAULT;
+ /* XXX: extra loop to check we really don't overlap preallocations */
+ rcu_read_lock();
+- list_for_each_rcu(cur, &ei->i_prealloc_list) {
+- struct ext4_prealloc_space *pa;
++ list_for_each_entry_rcu(pa, &ei->i_prealloc_list, pa_inode_list) {
+ unsigned long pa_end;
+- pa = list_entry(cur, struct ext4_prealloc_space, pa_inode_list);
+ spin_lock(&pa->pa_lock);
+ if (pa->pa_deleted == 0) {
+ pa_end = pa->pa_lstart + pa->pa_len;
+@@ -3382,7 +3075,7 @@ static void ext4_mb_use_inode_pa(struct ext4_allocation_context *ac,
+ BUG_ON(pa->pa_free < len);
+ pa->pa_free -= len;
-+ err = mnt_want_write(filp->f_path.mnt);
-+ if (err)
-+ return err;
+- mb_debug("use %llu/%lu from inode pa %p\n", start, len, pa);
++ mb_debug("use %llu/%u from inode pa %p\n", start, len, pa);
+ }
+
+ /*
+@@ -3412,12 +3105,12 @@ static void ext4_mb_use_group_pa(struct ext4_allocation_context *ac,
+ /*
+ * search goal blocks in preallocated space
+ */
+-static int ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
++static noinline_for_stack int
++ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
+ {
+ struct ext4_inode_info *ei = EXT4_I(ac->ac_inode);
+ struct ext4_locality_group *lg;
+ struct ext4_prealloc_space *pa;
+- struct list_head *cur;
+
+ /* only data can be preallocated */
+ if (!(ac->ac_flags & EXT4_MB_HINT_DATA))
+@@ -3425,8 +3118,7 @@ static int ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
+
+ /* first, try per-file preallocation */
+ rcu_read_lock();
+- list_for_each_rcu(cur, &ei->i_prealloc_list) {
+- pa = list_entry(cur, struct ext4_prealloc_space, pa_inode_list);
++ list_for_each_entry_rcu(pa, &ei->i_prealloc_list, pa_inode_list) {
+
+ /* all fields in this condition don't change,
+ * so we can skip locking for them */
+@@ -3458,8 +3150,7 @@ static int ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
+ return 0;
+
+ rcu_read_lock();
+- list_for_each_rcu(cur, &lg->lg_prealloc_list) {
+- pa = list_entry(cur, struct ext4_prealloc_space, pa_inode_list);
++ list_for_each_entry_rcu(pa, &lg->lg_prealloc_list, pa_inode_list) {
+ spin_lock(&pa->pa_lock);
+ if (pa->pa_deleted == 0 && pa->pa_free >= ac->ac_o_ex.fe_len) {
+ atomic_inc(&pa->pa_count);
+@@ -3579,7 +3270,8 @@ static void ext4_mb_put_pa(struct ext4_allocation_context *ac,
+ /*
+ * creates new preallocated space for given inode
+ */
+-static int ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
++static noinline_for_stack int
++ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
+ {
+ struct super_block *sb = ac->ac_sb;
+ struct ext4_prealloc_space *pa;
+@@ -3666,7 +3358,8 @@ static int ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
+ /*
+ * creates new preallocated space for locality group inodes belongs to
+ */
+-static int ext4_mb_new_group_pa(struct ext4_allocation_context *ac)
++static noinline_for_stack int
++ext4_mb_new_group_pa(struct ext4_allocation_context *ac)
+ {
+ struct super_block *sb = ac->ac_sb;
+ struct ext4_locality_group *lg;
+@@ -3739,11 +3432,11 @@ static int ext4_mb_new_preallocation(struct ext4_allocation_context *ac)
+ * the caller MUST hold group/inode locks.
+ * TODO: optimize the case when there are no in-core structures yet
+ */
+-static int ext4_mb_release_inode_pa(struct ext4_buddy *e4b,
+- struct buffer_head *bitmap_bh,
+- struct ext4_prealloc_space *pa)
++static noinline_for_stack int
++ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
++ struct ext4_prealloc_space *pa,
++ struct ext4_allocation_context *ac)
+ {
+- struct ext4_allocation_context *ac;
+ struct super_block *sb = e4b->bd_sb;
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
+ unsigned long end;
+@@ -3759,8 +3452,6 @@ static int ext4_mb_release_inode_pa(struct ext4_buddy *e4b,
+ BUG_ON(group != e4b->bd_group && pa->pa_len != 0);
+ end = bit + pa->pa_len;
+
+- ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
+-
+ if (ac) {
+ ac->ac_sb = sb;
+ ac->ac_inode = pa->pa_inode;
+@@ -3797,7 +3488,7 @@ static int ext4_mb_release_inode_pa(struct ext4_buddy *e4b,
+ pa, (unsigned long) pa->pa_lstart,
+ (unsigned long) pa->pa_pstart,
+ (unsigned long) pa->pa_len);
+- ext4_error(sb, __FUNCTION__, "free %u, pa_free %u\n",
++ ext4_error(sb, __func__, "free %u, pa_free %u\n",
+ free, pa->pa_free);
+ /*
+ * pa is already deleted so we use the value obtained
+@@ -3805,22 +3496,19 @@ static int ext4_mb_release_inode_pa(struct ext4_buddy *e4b,
+ */
+ }
+ atomic_add(free, &sbi->s_mb_discarded);
+- if (ac)
+- kmem_cache_free(ext4_ac_cachep, ac);
+
+ return err;
+ }
+
+-static int ext4_mb_release_group_pa(struct ext4_buddy *e4b,
+- struct ext4_prealloc_space *pa)
++static noinline_for_stack int
++ext4_mb_release_group_pa(struct ext4_buddy *e4b,
++ struct ext4_prealloc_space *pa,
++ struct ext4_allocation_context *ac)
+ {
+- struct ext4_allocation_context *ac;
+ struct super_block *sb = e4b->bd_sb;
+ ext4_group_t group;
+ ext4_grpblk_t bit;
+
+- ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
+-
+ if (ac)
+ ac->ac_op = EXT4_MB_HISTORY_DISCARD;
+
+@@ -3838,7 +3526,6 @@ static int ext4_mb_release_group_pa(struct ext4_buddy *e4b,
+ ac->ac_b_ex.fe_len = pa->pa_len;
+ ac->ac_b_ex.fe_logical = 0;
+ ext4_mb_store_history(ac);
+- kmem_cache_free(ext4_ac_cachep, ac);
+ }
+
+ return 0;
+@@ -3853,12 +3540,14 @@ static int ext4_mb_release_group_pa(struct ext4_buddy *e4b,
+ * - how many do we discard
+ * 1) how many requested
+ */
+-static int ext4_mb_discard_group_preallocations(struct super_block *sb,
++static noinline_for_stack int
++ext4_mb_discard_group_preallocations(struct super_block *sb,
+ ext4_group_t group, int needed)
+ {
+ struct ext4_group_info *grp = ext4_get_group_info(sb, group);
+ struct buffer_head *bitmap_bh = NULL;
+ struct ext4_prealloc_space *pa, *tmp;
++ struct ext4_allocation_context *ac;
+ struct list_head list;
+ struct ext4_buddy e4b;
+ int err;
+@@ -3886,6 +3575,7 @@ static int ext4_mb_discard_group_preallocations(struct super_block *sb,
+ grp = ext4_get_group_info(sb, group);
+ INIT_LIST_HEAD(&list);
+
++ ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
+ repeat:
+ ext4_lock_group(sb, group);
+ list_for_each_entry_safe(pa, tmp,
+@@ -3940,9 +3630,9 @@ repeat:
+ spin_unlock(pa->pa_obj_lock);
+
+ if (pa->pa_linear)
+- ext4_mb_release_group_pa(&e4b, pa);
++ ext4_mb_release_group_pa(&e4b, pa, ac);
+ else
+- ext4_mb_release_inode_pa(&e4b, bitmap_bh, pa);
++ ext4_mb_release_inode_pa(&e4b, bitmap_bh, pa, ac);
+
+ list_del(&pa->u.pa_tmp_list);
+ call_rcu(&(pa)->u.pa_rcu, ext4_mb_pa_callback);
+@@ -3950,6 +3640,8 @@ repeat:
+
+ out:
+ ext4_unlock_group(sb, group);
++ if (ac)
++ kmem_cache_free(ext4_ac_cachep, ac);
+ ext4_mb_release_desc(&e4b);
+ put_bh(bitmap_bh);
+ return free;
+@@ -3970,6 +3662,7 @@ void ext4_mb_discard_inode_preallocations(struct inode *inode)
+ struct super_block *sb = inode->i_sb;
+ struct buffer_head *bitmap_bh = NULL;
+ struct ext4_prealloc_space *pa, *tmp;
++ struct ext4_allocation_context *ac;
+ ext4_group_t group = 0;
+ struct list_head list;
+ struct ext4_buddy e4b;
+@@ -3984,6 +3677,7 @@ void ext4_mb_discard_inode_preallocations(struct inode *inode)
+
+ INIT_LIST_HEAD(&list);
+
++ ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
+ repeat:
+ /* first, collect all pa's in the inode */
+ spin_lock(&ei->i_prealloc_lock);
+@@ -4048,7 +3742,7 @@ repeat:
+
+ ext4_lock_group(sb, group);
+ list_del(&pa->pa_group_list);
+- ext4_mb_release_inode_pa(&e4b, bitmap_bh, pa);
++ ext4_mb_release_inode_pa(&e4b, bitmap_bh, pa, ac);
+ ext4_unlock_group(sb, group);
+
+ ext4_mb_release_desc(&e4b);
+@@ -4057,6 +3751,8 @@ repeat:
+ list_del(&pa->u.pa_tmp_list);
+ call_rcu(&(pa)->u.pa_rcu, ext4_mb_pa_callback);
+ }
++ if (ac)
++ kmem_cache_free(ext4_ac_cachep, ac);
+ }
+
+ /*
+@@ -4116,7 +3812,7 @@ static void ext4_mb_show_ac(struct ext4_allocation_context *ac)
+ printk(KERN_ERR "PA:%lu:%d:%u \n", i,
+ start, pa->pa_len);
+ }
+- ext4_lock_group(sb, i);
++ ext4_unlock_group(sb, i);
+
+ if (grp->bb_free == 0)
+ continue;
+@@ -4175,7 +3871,8 @@ static void ext4_mb_group_or_file(struct ext4_allocation_context *ac)
+ mutex_lock(&ac->ac_lg->lg_mutex);
+ }
+
+-static int ext4_mb_initialize_context(struct ext4_allocation_context *ac,
++static noinline_for_stack int
++ext4_mb_initialize_context(struct ext4_allocation_context *ac,
+ struct ext4_allocation_request *ar)
+ {
+ struct super_block *sb = ar->inode->i_sb;
+@@ -4406,7 +4103,8 @@ static void ext4_mb_poll_new_transaction(struct super_block *sb,
+ ext4_mb_free_committed_blocks(sb);
+ }
+
+-static int ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
++static noinline_for_stack int
++ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
+ ext4_group_t group, ext4_grpblk_t block, int count)
+ {
+ struct ext4_group_info *db = e4b->bd_info;
+@@ -4497,7 +4195,7 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
+ if (block < le32_to_cpu(es->s_first_data_block) ||
+ block + count < block ||
+ block + count > ext4_blocks_count(es)) {
+- ext4_error(sb, __FUNCTION__,
++ ext4_error(sb, __func__,
+ "Freeing blocks not in datazone - "
+ "block = %lu, count = %lu", block, count);
+ goto error_return;
+@@ -4538,7 +4236,7 @@ do_more:
+ in_range(block + count - 1, ext4_inode_table(sb, gdp),
+ EXT4_SB(sb)->s_itb_per_group)) {
+
+- ext4_error(sb, __FUNCTION__,
++ ext4_error(sb, __func__,
+ "Freeing blocks in system zone - "
+ "Block = %lu, count = %lu", block, count);
+ }
+@@ -4596,8 +4294,7 @@ do_more:
+ }
+
+ spin_lock(sb_bgl_lock(sbi, block_group));
+- gdp->bg_free_blocks_count =
+- cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
++ le16_add_cpu(&gdp->bg_free_blocks_count, count);
+ gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp);
+ spin_unlock(sb_bgl_lock(sbi, block_group));
+ percpu_counter_add(&sbi->s_freeblocks_counter, count);
+diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
+new file mode 100644
+index 0000000..bfe6add
+--- /dev/null
++++ b/fs/ext4/mballoc.h
+@@ -0,0 +1,304 @@
++/*
++ * fs/ext4/mballoc.h
++ *
++ * Written by: Alex Tomas <alex at clusterfs.com>
++ *
++ */
++#ifndef _EXT4_MBALLOC_H
++#define _EXT4_MBALLOC_H
+
- if (!S_ISDIR(inode->i_mode))
- flags &= ~EXT4_DIRSYNC_FL;
++#include <linux/time.h>
++#include <linux/fs.h>
++#include <linux/namei.h>
++#include <linux/quotaops.h>
++#include <linux/buffer_head.h>
++#include <linux/module.h>
++#include <linux/swap.h>
++#include <linux/proc_fs.h>
++#include <linux/pagemap.h>
++#include <linux/seq_file.h>
++#include <linux/version.h>
++#include "ext4_jbd2.h"
++#include "ext4.h"
++#include "group.h"
++
++/*
++ * with AGGRESSIVE_CHECK allocator runs consistency checks over
++ * structures. these checks slow things down a lot
++ */
++#define AGGRESSIVE_CHECK__
++
++/*
++ * with DOUBLE_CHECK defined mballoc creates persistent in-core
++ * bitmaps, maintains and uses them to check for double allocations
++ */
++#define DOUBLE_CHECK__
++
++/*
++ */
++#define MB_DEBUG__
++#ifdef MB_DEBUG
++#define mb_debug(fmt, a...) printk(fmt, ##a)
++#else
++#define mb_debug(fmt, a...)
++#endif
++
++/*
++ * with EXT4_MB_HISTORY mballoc stores last N allocations in memory
++ * and you can monitor it in /proc/fs/ext4/<dev>/mb_history
++ */
++#define EXT4_MB_HISTORY
++#define EXT4_MB_HISTORY_ALLOC 1 /* allocation */
++#define EXT4_MB_HISTORY_PREALLOC 2 /* preallocated blocks used */
++#define EXT4_MB_HISTORY_DISCARD 4 /* preallocation discarded */
++#define EXT4_MB_HISTORY_FREE 8 /* free */
++
++#define EXT4_MB_HISTORY_DEFAULT (EXT4_MB_HISTORY_ALLOC | \
++ EXT4_MB_HISTORY_PREALLOC)
++
++/*
++ * How long mballoc can look for a best extent (in found extents)
++ */
++#define MB_DEFAULT_MAX_TO_SCAN 200
++
++/*
++ * How long mballoc must look for a best extent
++ */
++#define MB_DEFAULT_MIN_TO_SCAN 10
++
++/*
++ * How many groups mballoc will scan looking for the best chunk
++ */
++#define MB_DEFAULT_MAX_GROUPS_TO_SCAN 5
++
++/*
++ * with 'ext4_mb_stats' allocator will collect stats that will be
++ * shown at umount. The collecting costs though!
++ */
++#define MB_DEFAULT_STATS 1
++
++/*
++ * files smaller than MB_DEFAULT_STREAM_THRESHOLD are served
++ * by the stream allocator, which purpose is to pack requests
++ * as close each to other as possible to produce smooth I/O traffic
++ * We use locality group prealloc space for stream request.
++ * We can tune the same via /proc/fs/ext4/<parition>/stream_req
++ */
++#define MB_DEFAULT_STREAM_THRESHOLD 16 /* 64K */
++
++/*
++ * for which requests use 2^N search using buddies
++ */
++#define MB_DEFAULT_ORDER2_REQS 2
++
++/*
++ * default group prealloc size 512 blocks
++ */
++#define MB_DEFAULT_GROUP_PREALLOC 512
++
++static struct kmem_cache *ext4_pspace_cachep;
++static struct kmem_cache *ext4_ac_cachep;
++
++#ifdef EXT4_BB_MAX_BLOCKS
++#undef EXT4_BB_MAX_BLOCKS
++#endif
++#define EXT4_BB_MAX_BLOCKS 30
++
++struct ext4_free_metadata {
++ ext4_group_t group;
++ unsigned short num;
++ ext4_grpblk_t blocks[EXT4_BB_MAX_BLOCKS];
++ struct list_head list;
++};
++
++struct ext4_group_info {
++ unsigned long bb_state;
++ unsigned long bb_tid;
++ struct ext4_free_metadata *bb_md_cur;
++ unsigned short bb_first_free;
++ unsigned short bb_free;
++ unsigned short bb_fragments;
++ struct list_head bb_prealloc_list;
++#ifdef DOUBLE_CHECK
++ void *bb_bitmap;
++#endif
++ unsigned short bb_counters[];
++};
++
++#define EXT4_GROUP_INFO_NEED_INIT_BIT 0
++#define EXT4_GROUP_INFO_LOCKED_BIT 1
++
++#define EXT4_MB_GRP_NEED_INIT(grp) \
++ (test_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &((grp)->bb_state)))
++
++
++struct ext4_prealloc_space {
++ struct list_head pa_inode_list;
++ struct list_head pa_group_list;
++ union {
++ struct list_head pa_tmp_list;
++ struct rcu_head pa_rcu;
++ } u;
++ spinlock_t pa_lock;
++ atomic_t pa_count;
++ unsigned pa_deleted;
++ ext4_fsblk_t pa_pstart; /* phys. block */
++ ext4_lblk_t pa_lstart; /* log. block */
++ unsigned short pa_len; /* len of preallocated chunk */
++ unsigned short pa_free; /* how many blocks are free */
++ unsigned short pa_linear; /* consumed in one direction
++ * strictly, for grp prealloc */
++ spinlock_t *pa_obj_lock;
++ struct inode *pa_inode; /* hack, for history only */
++};
++
++
++struct ext4_free_extent {
++ ext4_lblk_t fe_logical;
++ ext4_grpblk_t fe_start;
++ ext4_group_t fe_group;
++ int fe_len;
++};
++
++/*
++ * Locality group:
++ * we try to group all related changes together
++ * so that writeback can flush/allocate them together as well
++ */
++struct ext4_locality_group {
++ /* for allocator */
++ struct mutex lg_mutex; /* to serialize allocates */
++ struct list_head lg_prealloc_list;/* list of preallocations */
++ spinlock_t lg_prealloc_lock;
++};
++
++struct ext4_allocation_context {
++ struct inode *ac_inode;
++ struct super_block *ac_sb;
++
++ /* original request */
++ struct ext4_free_extent ac_o_ex;
++
++ /* goal request (after normalization) */
++ struct ext4_free_extent ac_g_ex;
++
++ /* the best found extent */
++ struct ext4_free_extent ac_b_ex;
++
++ /* copy of the bext found extent taken before preallocation efforts */
++ struct ext4_free_extent ac_f_ex;
++
++ /* number of iterations done. we have to track to limit searching */
++ unsigned long ac_ex_scanned;
++ __u16 ac_groups_scanned;
++ __u16 ac_found;
++ __u16 ac_tail;
++ __u16 ac_buddy;
++ __u16 ac_flags; /* allocation hints */
++ __u8 ac_status;
++ __u8 ac_criteria;
++ __u8 ac_repeats;
++ __u8 ac_2order; /* if request is to allocate 2^N blocks and
++ * N > 0, the field stores N, otherwise 0 */
++ __u8 ac_op; /* operation, for history only */
++ struct page *ac_bitmap_page;
++ struct page *ac_buddy_page;
++ struct ext4_prealloc_space *ac_pa;
++ struct ext4_locality_group *ac_lg;
++};
++
++#define AC_STATUS_CONTINUE 1
++#define AC_STATUS_FOUND 2
++#define AC_STATUS_BREAK 3
++
++struct ext4_mb_history {
++ struct ext4_free_extent orig; /* orig allocation */
++ struct ext4_free_extent goal; /* goal allocation */
++ struct ext4_free_extent result; /* result allocation */
++ unsigned pid;
++ unsigned ino;
++ __u16 found; /* how many extents have been found */
++ __u16 groups; /* how many groups have been scanned */
++ __u16 tail; /* what tail broke some buddy */
++ __u16 buddy; /* buddy the tail ^^^ broke */
++ __u16 flags;
++ __u8 cr:3; /* which phase the result extent was found at */
++ __u8 op:4;
++ __u8 merged:1;
++};
++
++struct ext4_buddy {
++ struct page *bd_buddy_page;
++ void *bd_buddy;
++ struct page *bd_bitmap_page;
++ void *bd_bitmap;
++ struct ext4_group_info *bd_info;
++ struct super_block *bd_sb;
++ __u16 bd_blkbits;
++ ext4_group_t bd_group;
++};
++#define EXT4_MB_BITMAP(e4b) ((e4b)->bd_bitmap)
++#define EXT4_MB_BUDDY(e4b) ((e4b)->bd_buddy)
++
++#ifndef EXT4_MB_HISTORY
++static inline void ext4_mb_store_history(struct ext4_allocation_context *ac)
++{
++ return;
++}
++#else
++static void ext4_mb_store_history(struct ext4_allocation_context *ac);
++#endif
++
++#define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1)
++
++static struct proc_dir_entry *proc_root_ext4;
++struct buffer_head *read_block_bitmap(struct super_block *, ext4_group_t);
++
++static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
++ ext4_group_t group);
++static void ext4_mb_poll_new_transaction(struct super_block *, handle_t *);
++static void ext4_mb_free_committed_blocks(struct super_block *);
++static void ext4_mb_return_to_preallocation(struct inode *inode,
++ struct ext4_buddy *e4b, sector_t block,
++ int count);
++static void ext4_mb_put_pa(struct ext4_allocation_context *,
++ struct super_block *, struct ext4_prealloc_space *pa);
++static int ext4_mb_init_per_dev_proc(struct super_block *sb);
++static int ext4_mb_destroy_per_dev_proc(struct super_block *sb);
++
++
++static inline void ext4_lock_group(struct super_block *sb, ext4_group_t group)
++{
++ struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
++
++ bit_spin_lock(EXT4_GROUP_INFO_LOCKED_BIT, &(grinfo->bb_state));
++}
++
++static inline void ext4_unlock_group(struct super_block *sb,
++ ext4_group_t group)
++{
++ struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
++
++ bit_spin_unlock(EXT4_GROUP_INFO_LOCKED_BIT, &(grinfo->bb_state));
++}
++
++static inline int ext4_is_group_locked(struct super_block *sb,
++ ext4_group_t group)
++{
++ struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
++
++ return bit_spin_is_locked(EXT4_GROUP_INFO_LOCKED_BIT,
++ &(grinfo->bb_state));
++}
++
++static ext4_fsblk_t ext4_grp_offs_to_block(struct super_block *sb,
++ struct ext4_free_extent *fex)
++{
++ ext4_fsblk_t block;
++
++ block = (ext4_fsblk_t) fex->fe_group * EXT4_BLOCKS_PER_GROUP(sb)
++ + fex->fe_start
++ + le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
++ return block;
++}
++#endif
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index 5c1e27d..b9e077b 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -13,8 +13,8 @@
+ */
-+ 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;
+ #include <linux/module.h>
+-#include <linux/ext4_jbd2.h>
+-#include <linux/ext4_fs_extents.h>
++#include "ext4_jbd2.h"
++#include "ext4_extents.h"
+
+ /*
+ * The contiguous blocks details which can be
+@@ -327,7 +327,7 @@ static int free_ind_block(handle_t *handle, struct inode *inode, __le32 *i_data)
+ }
+
+ static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode,
+- struct inode *tmp_inode)
++ struct inode *tmp_inode)
+ {
+ int retval;
+ __le32 i_data[3];
+@@ -339,7 +339,7 @@ static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode,
+ * i_data field of the original inode
+ */
+ retval = ext4_journal_extend(handle, 1);
+- if (retval != 0) {
++ if (retval) {
+ retval = ext4_journal_restart(handle, 1);
+ if (retval)
+ goto err_out;
+@@ -351,6 +351,18 @@ static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode,
+
+ down_write(&EXT4_I(inode)->i_data_sem);
+ /*
++ * if EXT4_EXT_MIGRATE is cleared a block allocation
++ * happened after we started the migrate. We need to
++ * fail the migrate
++ */
++ if (!(EXT4_I(inode)->i_flags & EXT4_EXT_MIGRATE)) {
++ retval = -EAGAIN;
++ up_write(&EXT4_I(inode)->i_data_sem);
++ goto err_out;
++ } else
++ EXT4_I(inode)->i_flags = EXT4_I(inode)->i_flags &
++ ~EXT4_EXT_MIGRATE;
++ /*
+ * We have the extent map build with the tmp inode.
+ * Now copy the i_data across
+ */
+@@ -508,6 +520,17 @@ int ext4_ext_migrate(struct inode *inode, struct file *filp,
+ * switch the inode format to prevent read.
+ */
+ mutex_lock(&(inode->i_mutex));
++ /*
++ * Even though we take i_mutex we can still cause block allocation
++ * via mmap write to holes. If we have allocated new blocks we fail
++ * migrate. New block allocation will clear EXT4_EXT_MIGRATE flag.
++ * The flag is updated with i_data_sem held to prevent racing with
++ * block allocation.
++ */
++ down_read((&EXT4_I(inode)->i_data_sem));
++ EXT4_I(inode)->i_flags = EXT4_I(inode)->i_flags | EXT4_EXT_MIGRATE;
++ up_read((&EXT4_I(inode)->i_data_sem));
+
- oldflags = ei->i_flags;
+ handle = ext4_journal_start(inode, 1);
- /* 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
+ ei = EXT4_I(inode);
+@@ -559,9 +582,15 @@ err_out:
+ * tmp_inode
*/
- 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;
+ free_ext_block(handle, tmp_inode);
+- else
+- retval = ext4_ext_swap_inode_data(handle, inode,
+- tmp_inode);
++ else {
++ retval = ext4_ext_swap_inode_data(handle, inode, tmp_inode);
++ if (retval)
++ /*
++ * if we fail to swap inode data free the extent
++ * details of the tmp inode
++ */
++ free_ext_block(handle, tmp_inode);
++ }
+
+ /* We mark the tmp_inode dirty via ext4_ext_tree_init. */
+ if (ext4_journal_extend(handle, 1) != 0)
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 28aa2ed..ab16bea 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -28,14 +28,14 @@
+ #include <linux/pagemap.h>
+ #include <linux/jbd2.h>
+ #include <linux/time.h>
+-#include <linux/ext4_fs.h>
+-#include <linux/ext4_jbd2.h>
+ #include <linux/fcntl.h>
+ #include <linux/stat.h>
+ #include <linux/string.h>
+ #include <linux/quotaops.h>
+ #include <linux/buffer_head.h>
+ #include <linux/bio.h>
++#include "ext4.h"
++#include "ext4_jbd2.h"
+
+ #include "namei.h"
+ #include "xattr.h"
+@@ -57,10 +57,15 @@ static struct buffer_head *ext4_append(handle_t *handle,
+
+ *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
+
+- if ((bh = ext4_bread(handle, inode, *block, 1, err))) {
++ bh = ext4_bread(handle, inode, *block, 1, err);
++ if (bh) {
+ inode->i_size += inode->i_sb->s_blocksize;
+ EXT4_I(inode)->i_disksize = inode->i_size;
+- ext4_journal_get_write_access(handle,bh);
++ *err = ext4_journal_get_write_access(handle, bh);
++ if (*err) {
++ brelse(bh);
++ bh = NULL;
++ }
+ }
+ return bh;
+ }
+@@ -348,7 +353,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
+ if (root->info.hash_version != DX_HASH_TEA &&
+ root->info.hash_version != DX_HASH_HALF_MD4 &&
+ root->info.hash_version != DX_HASH_LEGACY) {
+- ext4_warning(dir->i_sb, __FUNCTION__,
++ ext4_warning(dir->i_sb, __func__,
+ "Unrecognised inode hash code %d",
+ root->info.hash_version);
+ brelse(bh);
+@@ -362,7 +367,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
+ hash = hinfo->hash;
+
+ if (root->info.unused_flags & 1) {
+- ext4_warning(dir->i_sb, __FUNCTION__,
++ ext4_warning(dir->i_sb, __func__,
+ "Unimplemented inode hash flags: %#06x",
+ root->info.unused_flags);
+ brelse(bh);
+@@ -371,7 +376,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
+ }
+
+ if ((indirect = root->info.indirect_levels) > 1) {
+- ext4_warning(dir->i_sb, __FUNCTION__,
++ ext4_warning(dir->i_sb, __func__,
+ "Unimplemented inode hash depth: %#06x",
+ root->info.indirect_levels);
+ brelse(bh);
+@@ -384,7 +389,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
+
+ if (dx_get_limit(entries) != dx_root_limit(dir,
+ root->info.info_length)) {
+- ext4_warning(dir->i_sb, __FUNCTION__,
++ ext4_warning(dir->i_sb, __func__,
+ "dx entry: limit != root limit");
+ brelse(bh);
+ *err = ERR_BAD_DX_DIR;
+@@ -396,7 +401,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
+ {
+ count = dx_get_count(entries);
+ if (!count || count > dx_get_limit(entries)) {
+- ext4_warning(dir->i_sb, __FUNCTION__,
++ ext4_warning(dir->i_sb, __func__,
+ "dx entry: no count or count > limit");
+ brelse(bh);
+ *err = ERR_BAD_DX_DIR;
+@@ -441,7 +446,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
+ goto fail2;
+ at = entries = ((struct dx_node *) bh->b_data)->entries;
+ if (dx_get_limit(entries) != dx_node_limit (dir)) {
+- ext4_warning(dir->i_sb, __FUNCTION__,
++ ext4_warning(dir->i_sb, __func__,
+ "dx entry: limit != node limit");
+ brelse(bh);
+ *err = ERR_BAD_DX_DIR;
+@@ -457,7 +462,7 @@ fail2:
+ }
+ fail:
+ if (*err == ERR_BAD_DX_DIR)
+- ext4_warning(dir->i_sb, __FUNCTION__,
++ ext4_warning(dir->i_sb, __func__,
+ "Corrupt dir inode %ld, running e2fsck is "
+ "recommended.", dir->i_ino);
+ return NULL;
+@@ -914,7 +919,7 @@ restart:
+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh)) {
+ /* read error, skip block & hope for the best */
+- ext4_error(sb, __FUNCTION__, "reading directory #%lu "
++ ext4_error(sb, __func__, "reading directory #%lu "
+ "offset %lu", dir->i_ino,
+ (unsigned long)block);
+ brelse(bh);
+@@ -1007,7 +1012,7 @@ static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry,
+ retval = ext4_htree_next_block(dir, hash, frame,
+ frames, NULL);
+ if (retval < 0) {
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "error reading index page in directory #%lu",
+ dir->i_ino);
+ *err = retval;
+@@ -1532,7 +1537,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+
+ if (levels && (dx_get_count(frames->entries) ==
+ dx_get_limit(frames->entries))) {
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "Directory index full!");
+ err = -ENOSPC;
+ goto cleanup;
+@@ -1860,11 +1865,11 @@ static int empty_dir (struct inode * inode)
+ if (inode->i_size < EXT4_DIR_REC_LEN(1) + EXT4_DIR_REC_LEN(2) ||
+ !(bh = ext4_bread (NULL, inode, 0, 0, &err))) {
+ if (err)
+- ext4_error(inode->i_sb, __FUNCTION__,
++ ext4_error(inode->i_sb, __func__,
+ "error %d reading directory #%lu offset 0",
+ err, inode->i_ino);
+ else
+- ext4_warning(inode->i_sb, __FUNCTION__,
++ ext4_warning(inode->i_sb, __func__,
+ "bad directory (dir #%lu) - no data block",
+ inode->i_ino);
+ return 1;
+@@ -1893,7 +1898,7 @@ static int empty_dir (struct inode * inode)
+ offset >> EXT4_BLOCK_SIZE_BITS(sb), 0, &err);
+ if (!bh) {
+ if (err)
+- ext4_error(sb, __FUNCTION__,
++ ext4_error(sb, __func__,
+ "error %d reading directory"
+ " #%lu offset %lu",
+ err, inode->i_ino, offset);
+@@ -2217,6 +2222,8 @@ retry:
+ goto out_stop;
}
+ } else {
++ /* clear the extent format for fast symlink */
++ EXT4_I(inode)->i_flags &= ~EXT4_EXTENTS_FL;
+ inode->i_op = &ext4_fast_symlink_inode_operations;
+ memcpy((char*)&EXT4_I(inode)->i_data,symname,l);
+ inode->i_size = l-1;
+@@ -2347,6 +2354,9 @@ static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
+ EXT4_FEATURE_INCOMPAT_FILETYPE))
+ new_de->file_type = old_de->file_type;
+ new_dir->i_version++;
++ new_dir->i_ctime = new_dir->i_mtime =
++ ext4_current_time(new_dir);
++ ext4_mark_inode_dirty(handle, new_dir);
+ BUFFER_TRACE(new_bh, "call ext4_journal_dirty_metadata");
+ ext4_journal_dirty_metadata(handle, new_bh);
+ brelse(new_bh);
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index e29efa0..9f086a6 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -11,11 +11,10 @@
- /*
-@@ -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;
+ #define EXT4FS_DEBUG
+
+-#include <linux/ext4_jbd2.h>
+-
+ #include <linux/errno.h>
+ #include <linux/slab.h>
+
++#include "ext4_jbd2.h"
+ #include "group.h"
+
+ #define outside(b, first, last) ((b) < (first) || (b) >= (last))
+@@ -50,63 +49,63 @@ static int verify_group_input(struct super_block *sb,
+
+ ext4_get_group_no_and_offset(sb, start, NULL, &offset);
+ if (group != sbi->s_groups_count)
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "Cannot add at group %u (only %lu groups)",
+ input->group, sbi->s_groups_count);
+ else if (offset != 0)
+- ext4_warning(sb, __FUNCTION__, "Last group not full");
++ ext4_warning(sb, __func__, "Last group not full");
+ else if (input->reserved_blocks > input->blocks_count / 5)
+- ext4_warning(sb, __FUNCTION__, "Reserved blocks too high (%u)",
++ ext4_warning(sb, __func__, "Reserved blocks too high (%u)",
+ input->reserved_blocks);
+ else if (free_blocks_count < 0)
+- ext4_warning(sb, __FUNCTION__, "Bad blocks count %u",
++ ext4_warning(sb, __func__, "Bad blocks count %u",
+ input->blocks_count);
+ else if (!(bh = sb_bread(sb, end - 1)))
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "Cannot read last block (%llu)",
+ end - 1);
+ else if (outside(input->block_bitmap, start, end))
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "Block bitmap not in group (block %llu)",
+ (unsigned long long)input->block_bitmap);
+ else if (outside(input->inode_bitmap, start, end))
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "Inode bitmap not in group (block %llu)",
+ (unsigned long long)input->inode_bitmap);
+ else if (outside(input->inode_table, start, end) ||
+ outside(itend - 1, start, end))
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "Inode table not in group (blocks %llu-%llu)",
+ (unsigned long long)input->inode_table, itend - 1);
+ else if (input->inode_bitmap == input->block_bitmap)
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "Block bitmap same as inode bitmap (%llu)",
+ (unsigned long long)input->block_bitmap);
+ else if (inside(input->block_bitmap, input->inode_table, itend))
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "Block bitmap (%llu) in inode table (%llu-%llu)",
+ (unsigned long long)input->block_bitmap,
+ (unsigned long long)input->inode_table, itend - 1);
+ else if (inside(input->inode_bitmap, input->inode_table, itend))
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "Inode bitmap (%llu) in inode table (%llu-%llu)",
+ (unsigned long long)input->inode_bitmap,
+ (unsigned long long)input->inode_table, itend - 1);
+ else if (inside(input->block_bitmap, start, metaend))
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "Block bitmap (%llu) in GDT table"
+ " (%llu-%llu)",
+ (unsigned long long)input->block_bitmap,
+ start, metaend - 1);
+ else if (inside(input->inode_bitmap, start, metaend))
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "Inode bitmap (%llu) in GDT table"
+ " (%llu-%llu)",
+ (unsigned long long)input->inode_bitmap,
+ start, metaend - 1);
+ else if (inside(input->inode_table, start, metaend) ||
+ inside(itend - 1, start, metaend))
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "Inode table (%llu-%llu) overlaps"
+ "GDT table (%llu-%llu)",
+ (unsigned long long)input->inode_table,
+@@ -368,7 +367,7 @@ static int verify_reserved_gdb(struct super_block *sb,
+ while ((grp = ext4_list_backups(sb, &three, &five, &seven)) < end) {
+ if (le32_to_cpu(*p++) !=
+ grp * EXT4_BLOCKS_PER_GROUP(sb) + blk){
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "reserved GDT %llu"
+ " missing grp %d (%llu)",
+ blk, grp,
+@@ -424,7 +423,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ */
+ if (EXT4_SB(sb)->s_sbh->b_blocknr !=
+ le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) {
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "won't resize using backup superblock at %llu",
+ (unsigned long long)EXT4_SB(sb)->s_sbh->b_blocknr);
+ return -EPERM;
+@@ -448,7 +447,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+
+ data = (__le32 *)dind->b_data;
+ if (le32_to_cpu(data[gdb_num % EXT4_ADDR_PER_BLOCK(sb)]) != gdblock) {
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "new group %u GDT block %llu not reserved",
+ input->group, gdblock);
+ err = -EINVAL;
+@@ -469,10 +468,10 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ goto exit_dindj;
+
+ n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *),
+- GFP_KERNEL);
++ GFP_NOFS);
+ if (!n_group_desc) {
+ err = -ENOMEM;
+- ext4_warning (sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "not enough memory for %lu groups", gdb_num + 1);
+ goto exit_inode;
+ }
+@@ -502,8 +501,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ EXT4_SB(sb)->s_gdb_count++;
+ kfree(o_group_desc);
+
+- es->s_reserved_gdt_blocks =
+- cpu_to_le16(le16_to_cpu(es->s_reserved_gdt_blocks) - 1);
++ le16_add_cpu(&es->s_reserved_gdt_blocks, -1);
+ ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh);
+
+ return 0;
+@@ -553,7 +551,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
+ int res, i;
+ int err;
+
+- primary = kmalloc(reserved_gdb * sizeof(*primary), GFP_KERNEL);
++ primary = kmalloc(reserved_gdb * sizeof(*primary), GFP_NOFS);
+ if (!primary)
+ return -ENOMEM;
+
+@@ -571,7 +569,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
+ /* Get each reserved primary GDT block and verify it holds backups */
+ for (res = 0; res < reserved_gdb; res++, blk++) {
+ if (le32_to_cpu(*data) != blk) {
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "reserved block %llu"
+ " not at offset %ld",
+ blk,
+@@ -715,7 +713,7 @@ static void update_backups(struct super_block *sb,
+ */
+ exit_err:
+ if (err) {
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "can't update backup for group %lu (err %d), "
+ "forcing fsck on next reboot", group, err);
+ sbi->s_mount_state &= ~EXT4_VALID_FS;
+@@ -755,33 +753,33 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+
+ if (gdb_off == 0 && !EXT4_HAS_RO_COMPAT_FEATURE(sb,
+ EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "Can't resize non-sparse filesystem further");
+ return -EPERM;
+ }
+
+ if (ext4_blocks_count(es) + input->blocks_count <
+ ext4_blocks_count(es)) {
+- ext4_warning(sb, __FUNCTION__, "blocks_count overflow\n");
++ ext4_warning(sb, __func__, "blocks_count overflow\n");
+ return -EINVAL;
+ }
+
+ if (le32_to_cpu(es->s_inodes_count) + EXT4_INODES_PER_GROUP(sb) <
+ le32_to_cpu(es->s_inodes_count)) {
+- ext4_warning(sb, __FUNCTION__, "inodes_count overflow\n");
++ ext4_warning(sb, __func__, "inodes_count overflow\n");
+ return -EINVAL;
+ }
+
+ if (reserved_gdb || gdb_off == 0) {
+ if (!EXT4_HAS_COMPAT_FEATURE(sb,
+ EXT4_FEATURE_COMPAT_RESIZE_INODE)){
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "No reserved GDT blocks, can't resize");
+ return -EPERM;
}
+ inode = ext4_iget(sb, EXT4_RESIZE_INO);
+ if (IS_ERR(inode)) {
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "Error opening resize inode");
+ return PTR_ERR(inode);
+ }
+@@ -810,7 +808,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+
+ lock_super(sb);
+ if (input->group != sbi->s_groups_count) {
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "multiple resizers run on filesystem!");
+ err = -EBUSY;
+ goto exit_journal;
+@@ -877,8 +875,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ */
+ ext4_blocks_count_set(es, ext4_blocks_count(es) +
+ input->blocks_count);
+- es->s_inodes_count = cpu_to_le32(le32_to_cpu(es->s_inodes_count) +
+- EXT4_INODES_PER_GROUP(sb));
++ le32_add_cpu(&es->s_inodes_count, EXT4_INODES_PER_GROUP(sb));
+
+ /*
+ * We need to protect s_groups_count against other CPUs seeing
+@@ -977,13 +974,13 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+ " too large to resize to %llu blocks safely\n",
+ sb->s_id, n_blocks_count);
+ if (sizeof(sector_t) < 8)
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "CONFIG_LBD not enabled\n");
+ return -EINVAL;
+ }
+
+ if (n_blocks_count < o_blocks_count) {
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "can't shrink FS - resize aborted");
+ return -EBUSY;
+ }
+@@ -992,7 +989,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+ ext4_get_group_no_and_offset(sb, o_blocks_count, NULL, &last);
+
+ if (last == 0) {
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "need to use ext2online to resize further");
+ return -EPERM;
+ }
+@@ -1000,7 +997,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+ add = EXT4_BLOCKS_PER_GROUP(sb) - last;
+
+ if (o_blocks_count + add < o_blocks_count) {
+- ext4_warning(sb, __FUNCTION__, "blocks_count overflow");
++ ext4_warning(sb, __func__, "blocks_count overflow");
+ return -EINVAL;
+ }
+
+@@ -1008,7 +1005,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+ add = n_blocks_count - o_blocks_count;
+
+ if (o_blocks_count + add < n_blocks_count)
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "will only finish group (%llu"
+ " blocks, %u new)",
+ o_blocks_count + add, add);
+@@ -1016,7 +1013,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+ /* See if the device is actually as big as what was requested */
+ bh = sb_bread(sb, o_blocks_count + add -1);
+ if (!bh) {
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "can't read last block, resize aborted");
+ return -ENOSPC;
+ }
+@@ -1028,13 +1025,13 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+ handle = ext4_journal_start_sb(sb, 3);
+ if (IS_ERR(handle)) {
+ err = PTR_ERR(handle);
+- ext4_warning(sb, __FUNCTION__, "error %d on journal start",err);
++ ext4_warning(sb, __func__, "error %d on journal start", err);
+ goto exit_put;
+ }
+
+ lock_super(sb);
+ if (o_blocks_count != ext4_blocks_count(es)) {
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "multiple resizers run on filesystem!");
+ unlock_super(sb);
+ ext4_journal_stop(handle);
+@@ -1044,7 +1041,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+ if ((err = ext4_journal_get_write_access(handle,
+ EXT4_SB(sb)->s_sbh))) {
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "error %d on journal write access", err);
+ unlock_super(sb);
+ ext4_journal_stop(handle);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 13383ba..52dd067 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -21,8 +21,6 @@
+ #include <linux/fs.h>
+ #include <linux/time.h>
+ #include <linux/jbd2.h>
+-#include <linux/ext4_fs.h>
+-#include <linux/ext4_jbd2.h>
+ #include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/blkdev.h>
+@@ -38,9 +36,10 @@
+ #include <linux/seq_file.h>
+ #include <linux/log2.h>
+ #include <linux/crc16.h>
-
- 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;
+ #include <asm/uaccess.h>
+
++#include "ext4.h"
++#include "ext4_jbd2.h"
+ #include "xattr.h"
+ #include "acl.h"
+ #include "namei.h"
+@@ -135,7 +134,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
+ * take the FS itself readonly cleanly. */
+ journal = EXT4_SB(sb)->s_journal;
+ if (is_journal_aborted(journal)) {
+- ext4_abort(sb, __FUNCTION__,
++ ext4_abort(sb, __func__,
+ "Detected aborted journal");
+ return ERR_PTR(-EROFS);
+ }
+@@ -355,7 +354,7 @@ void ext4_update_dynamic_rev(struct super_block *sb)
+ if (le32_to_cpu(es->s_rev_level) > EXT4_GOOD_OLD_REV)
+ return;
+
+- ext4_warning(sb, __FUNCTION__,
++ ext4_warning(sb, __func__,
+ "updating to rev %d because of new feature flag, "
+ "running e2fsck is recommended",
+ EXT4_DYNAMIC_REV);
+@@ -813,7 +812,8 @@ static int ext4_acquire_dquot(struct dquot *dquot);
+ static int ext4_release_dquot(struct dquot *dquot);
+ static int ext4_mark_dquot_dirty(struct dquot *dquot);
+ static int ext4_write_info(struct super_block *sb, int type);
+-static int ext4_quota_on(struct super_block *sb, int type, int format_id, char *path);
++static int ext4_quota_on(struct super_block *sb, int type, int format_id,
++ char *path, int remount);
+ static int ext4_quota_on_mount(struct super_block *sb, int type);
+ static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
+ size_t len, loff_t off);
+@@ -944,8 +944,8 @@ static match_table_t tokens = {
+ {Opt_mballoc, "mballoc"},
+ {Opt_nomballoc, "nomballoc"},
+ {Opt_stripe, "stripe=%u"},
+- {Opt_err, NULL},
+ {Opt_resize, "resize"},
++ {Opt_err, NULL},
+ };
+
+ static ext4_fsblk_t get_sb_block(void **data)
+@@ -1387,11 +1387,11 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
+ * a plain journaled filesystem we can keep it set as
+ * valid forever! :)
+ */
+- es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT4_VALID_FS);
++ es->s_state &= cpu_to_le16(~EXT4_VALID_FS);
+ #endif
+ if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
+ es->s_max_mnt_count = cpu_to_le16(EXT4_DFL_MAX_MNT_COUNT);
+- es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);
++ le16_add_cpu(&es->s_mnt_count, 1);
+ es->s_mtime = cpu_to_le32(get_seconds());
+ ext4_update_dynamic_rev(sb);
+ EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+@@ -1484,36 +1484,33 @@ static int ext4_check_descriptors(struct super_block *sb)
+ block_bitmap = ext4_block_bitmap(sb, gdp);
+ if (block_bitmap < first_block || block_bitmap > last_block)
+ {
+- ext4_error (sb, "ext4_check_descriptors",
+- "Block bitmap for group %lu"
+- " not in group (block %llu)!",
+- i, block_bitmap);
++ printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
++ "Block bitmap for group %lu not in group "
++ "(block %llu)!", i, block_bitmap);
+ return 0;
+ }
+ inode_bitmap = ext4_inode_bitmap(sb, gdp);
+ if (inode_bitmap < first_block || inode_bitmap > last_block)
+ {
+- ext4_error (sb, "ext4_check_descriptors",
+- "Inode bitmap for group %lu"
+- " not in group (block %llu)!",
+- i, inode_bitmap);
++ printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
++ "Inode bitmap for group %lu not in group "
++ "(block %llu)!", i, inode_bitmap);
+ return 0;
+ }
+ inode_table = ext4_inode_table(sb, gdp);
+ if (inode_table < first_block ||
+ inode_table + sbi->s_itb_per_group - 1 > last_block)
+ {
+- ext4_error (sb, "ext4_check_descriptors",
+- "Inode table for group %lu"
+- " not in group (block %llu)!",
+- i, inode_table);
++ printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
++ "Inode table for group %lu not in group "
++ "(block %llu)!", i, inode_table);
+ return 0;
+ }
+ if (!ext4_group_desc_csum_verify(sbi, i, gdp)) {
+- ext4_error(sb, __FUNCTION__,
+- "Checksum for group %lu failed (%u!=%u)\n",
+- i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
+- gdp)), le16_to_cpu(gdp->bg_checksum));
++ printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
++ "Checksum for group %lu failed (%u!=%u)\n",
++ i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
++ gdp)), le16_to_cpu(gdp->bg_checksum));
+ return 0;
+ }
+ if (!flexbg_flag)
+@@ -1593,8 +1590,8 @@ static void ext4_orphan_cleanup (struct super_block * sb,
+ while (es->s_last_orphan) {
+ struct inode *inode;
+
+- if (!(inode =
+- ext4_orphan_get(sb, le32_to_cpu(es->s_last_orphan)))) {
++ inode = ext4_orphan_get(sb, le32_to_cpu(es->s_last_orphan));
++ if (IS_ERR(inode)) {
+ es->s_last_orphan = 0;
+ break;
}
+@@ -1604,7 +1601,7 @@ static void ext4_orphan_cleanup (struct super_block * sb,
+ if (inode->i_nlink) {
+ printk(KERN_DEBUG
+ "%s: truncating inode %lu to %Ld bytes\n",
+- __FUNCTION__, inode->i_ino, inode->i_size);
++ __func__, inode->i_ino, inode->i_size);
+ jbd_debug(2, "truncating inode %lu to %Ld bytes\n",
+ inode->i_ino, inode->i_size);
+ ext4_truncate(inode);
+@@ -1612,7 +1609,7 @@ static void ext4_orphan_cleanup (struct super_block * sb,
+ } else {
+ printk(KERN_DEBUG
+ "%s: deleting unreferenced inode %lu\n",
+- __FUNCTION__, inode->i_ino);
++ __func__, inode->i_ino);
+ jbd_debug(2, "deleting unreferenced inode %lu\n",
+ inode->i_ino);
+ nr_orphans++;
+@@ -1632,7 +1629,7 @@ static void ext4_orphan_cleanup (struct super_block * sb,
+ /* Turn quotas off */
+ for (i = 0; i < MAXQUOTAS; i++) {
+ if (sb_dqopt(sb)->files[i])
+- vfs_quota_off(sb, i);
++ vfs_quota_off(sb, i, 0);
+ }
+ #endif
+ sb->s_flags = s_flags; /* Restore MS_RDONLY status */
+@@ -2698,9 +2695,9 @@ static void ext4_clear_journal_err(struct super_block * sb,
+ char nbuf[16];
+
+ errstr = ext4_decode_error(sb, j_errno, nbuf);
+- ext4_warning(sb, __FUNCTION__, "Filesystem error recorded "
++ ext4_warning(sb, __func__, "Filesystem error recorded "
+ "from previous mount: %s", errstr);
+- ext4_warning(sb, __FUNCTION__, "Marking fs in need of "
++ ext4_warning(sb, __func__, "Marking fs in need of "
+ "filesystem check.");
+
+ EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+@@ -2827,7 +2824,7 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data)
+ }
+
+ if (sbi->s_mount_opt & EXT4_MOUNT_ABORT)
+- ext4_abort(sb, __FUNCTION__, "Abort forced by user");
++ ext4_abort(sb, __func__, "Abort forced by user");
+
+ sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
+ ((sbi->s_mount_opt & EXT4_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
+@@ -3039,8 +3036,14 @@ static int ext4_dquot_drop(struct inode *inode)
+
+ /* We may delete quota structure so we need to reserve enough blocks */
+ handle = ext4_journal_start(inode, 2*EXT4_QUOTA_DEL_BLOCKS(inode->i_sb));
+- if (IS_ERR(handle))
++ if (IS_ERR(handle)) {
++ /*
++ * We call dquot_drop() anyway to at least release references
++ * to quota structures so that umount does not hang.
++ */
++ dquot_drop(inode);
+ return PTR_ERR(handle);
++ }
+ ret = dquot_drop(inode);
+ err = ext4_journal_stop(handle);
+ if (!ret)
+@@ -3143,7 +3146,7 @@ static int ext4_quota_on_mount(struct super_block *sb, int type)
+ * Standard function to be called on quota_on
+ */
+ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
+- char *path)
++ char *path, int remount)
+ {
+ int err;
+ struct nameidata nd;
+@@ -3151,9 +3154,9 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
+ if (!test_opt(sb, QUOTA))
+ return -EINVAL;
+ /* Not journalling quota? */
+- if (!EXT4_SB(sb)->s_qf_names[USRQUOTA] &&
+- !EXT4_SB(sb)->s_qf_names[GRPQUOTA])
+- return vfs_quota_on(sb, type, format_id, path);
++ if ((!EXT4_SB(sb)->s_qf_names[USRQUOTA] &&
++ !EXT4_SB(sb)->s_qf_names[GRPQUOTA]) || remount)
++ return vfs_quota_on(sb, type, format_id, path, remount);
+ err = path_lookup(path, LOOKUP_FOLLOW, &nd);
+ if (err)
+ return err;
+@@ -3168,7 +3171,7 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
+ "EXT4-fs: Quota file not on filesystem root. "
+ "Journalled quota will not work.\n");
+ path_put(&nd.path);
+- return vfs_quota_on(sb, type, format_id, path);
++ return vfs_quota_on(sb, type, format_id, path, remount);
+ }
+
+ /* Read data from quotafile - avoid pagecache and such because we cannot afford
+diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
+index e6f9da4..e917864 100644
+--- a/fs/ext4/symlink.c
++++ b/fs/ext4/symlink.c
+@@ -19,8 +19,8 @@
+
+ #include <linux/fs.h>
+ #include <linux/jbd2.h>
+-#include <linux/ext4_fs.h>
+ #include <linux/namei.h>
++#include "ext4.h"
+ #include "xattr.h"
+
+ static void * ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index e9054c1..3fbc2c6 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -53,11 +53,11 @@
+ #include <linux/init.h>
+ #include <linux/fs.h>
+ #include <linux/slab.h>
+-#include <linux/ext4_jbd2.h>
+-#include <linux/ext4_fs.h>
+ #include <linux/mbcache.h>
+ #include <linux/quotaops.h>
+ #include <linux/rwsem.h>
++#include "ext4_jbd2.h"
++#include "ext4.h"
+ #include "xattr.h"
+ #include "acl.h"
+
+@@ -92,6 +92,8 @@ static struct buffer_head *ext4_xattr_cache_find(struct inode *,
+ struct mb_cache_entry **);
+ static void ext4_xattr_rehash(struct ext4_xattr_header *,
+ struct ext4_xattr_entry *);
++static int ext4_xattr_list(struct inode *inode, char *buffer,
++ size_t buffer_size);
+
+ static struct mb_cache *ext4_xattr_cache;
+
+@@ -225,7 +227,7 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
+ ea_bdebug(bh, "b_count=%d, refcount=%d",
+ atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
+ if (ext4_xattr_check_block(bh)) {
+-bad_block: ext4_error(inode->i_sb, __FUNCTION__,
++bad_block: ext4_error(inode->i_sb, __func__,
+ "inode %lu: bad block %llu", inode->i_ino,
+ EXT4_I(inode)->i_file_acl);
+ error = -EIO;
+@@ -367,7 +369,7 @@ ext4_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
+ ea_bdebug(bh, "b_count=%d, refcount=%d",
+ atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
+ if (ext4_xattr_check_block(bh)) {
+- ext4_error(inode->i_sb, __FUNCTION__,
++ ext4_error(inode->i_sb, __func__,
+ "inode %lu: bad block %llu", inode->i_ino,
+ EXT4_I(inode)->i_file_acl);
+ error = -EIO;
+@@ -420,7 +422,7 @@ cleanup:
+ * Returns a negative error number on failure, or the number of bytes
+ * used / required on success.
+ */
+-int
++static int
+ ext4_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
+ {
+ int i_error, b_error;
+@@ -484,8 +486,7 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
+ get_bh(bh);
+ ext4_forget(handle, 1, inode, bh, bh->b_blocknr);
+ } else {
+- BHDR(bh)->h_refcount = cpu_to_le32(
+- le32_to_cpu(BHDR(bh)->h_refcount) - 1);
++ le32_add_cpu(&BHDR(bh)->h_refcount, -1);
+ error = ext4_journal_dirty_metadata(handle, bh);
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;
+@@ -660,7 +661,7 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
+ atomic_read(&(bs->bh->b_count)),
+ le32_to_cpu(BHDR(bs->bh)->h_refcount));
+ if (ext4_xattr_check_block(bs->bh)) {
+- ext4_error(sb, __FUNCTION__,
++ ext4_error(sb, __func__,
+ "inode %lu: bad block %llu", inode->i_ino,
+ EXT4_I(inode)->i_file_acl);
+ error = -EIO;
+@@ -738,7 +739,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ ce = NULL;
+ }
+ ea_bdebug(bs->bh, "cloning");
+- s->base = kmalloc(bs->bh->b_size, GFP_KERNEL);
++ s->base = kmalloc(bs->bh->b_size, GFP_NOFS);
+ error = -ENOMEM;
+ if (s->base == NULL)
+ goto cleanup;
+@@ -750,7 +751,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ }
+ } else {
+ /* Allocate a buffer where we construct the new block. */
+- s->base = kzalloc(sb->s_blocksize, GFP_KERNEL);
++ s->base = kzalloc(sb->s_blocksize, GFP_NOFS);
+ /* assert(header == s->base) */
+ error = -ENOMEM;
+ if (s->base == NULL)
+@@ -789,8 +790,7 @@ inserted:
+ if (error)
+ goto cleanup_dquot;
+ lock_buffer(new_bh);
+- BHDR(new_bh)->h_refcount = cpu_to_le32(1 +
+- le32_to_cpu(BHDR(new_bh)->h_refcount));
++ le32_add_cpu(&BHDR(new_bh)->h_refcount, 1);
+ ea_bdebug(new_bh, "reusing; refcount now=%d",
+ le32_to_cpu(BHDR(new_bh)->h_refcount));
+ unlock_buffer(new_bh);
+@@ -808,10 +808,8 @@ inserted:
+ get_bh(new_bh);
+ } else {
+ /* We need to allocate a new block */
+- ext4_fsblk_t goal = le32_to_cpu(
+- EXT4_SB(sb)->s_es->s_first_data_block) +
+- (ext4_fsblk_t)EXT4_I(inode)->i_block_group *
+- EXT4_BLOCKS_PER_GROUP(sb);
++ ext4_fsblk_t goal = ext4_group_first_block_no(sb,
++ EXT4_I(inode)->i_block_group);
+ ext4_fsblk_t block = ext4_new_block(handle, inode,
+ goal, &error);
+ if (error)
+@@ -863,7 +861,7 @@ cleanup_dquot:
+ goto cleanup;
+
+ bad_block:
+- ext4_error(inode->i_sb, __FUNCTION__,
++ ext4_error(inode->i_sb, __func__,
+ "inode %lu: bad block %llu", inode->i_ino,
+ EXT4_I(inode)->i_file_acl);
+ goto cleanup;
+@@ -1166,7 +1164,7 @@ retry:
+ if (!bh)
+ goto cleanup;
+ if (ext4_xattr_check_block(bh)) {
+- ext4_error(inode->i_sb, __FUNCTION__,
++ ext4_error(inode->i_sb, __func__,
+ "inode %lu: bad block %llu", inode->i_ino,
+ EXT4_I(inode)->i_file_acl);
+ error = -EIO;
+@@ -1341,14 +1339,14 @@ ext4_xattr_delete_inode(handle_t *handle, struct inode *inode)
+ goto cleanup;
+ bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
+ if (!bh) {
+- ext4_error(inode->i_sb, __FUNCTION__,
++ ext4_error(inode->i_sb, __func__,
+ "inode %lu: block %llu read error", inode->i_ino,
+ EXT4_I(inode)->i_file_acl);
+ goto cleanup;
+ }
+ if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
+ BHDR(bh)->h_blocks != cpu_to_le32(1)) {
+- ext4_error(inode->i_sb, __FUNCTION__,
++ ext4_error(inode->i_sb, __func__,
+ "inode %lu: bad block %llu", inode->i_ino,
+ EXT4_I(inode)->i_file_acl);
+ goto cleanup;
+@@ -1475,7 +1473,7 @@ again:
+ }
+ bh = sb_bread(inode->i_sb, ce->e_block);
+ if (!bh) {
+- ext4_error(inode->i_sb, __FUNCTION__,
++ ext4_error(inode->i_sb, __func__,
+ "inode %lu: block %lu read error",
+ inode->i_ino, (unsigned long) ce->e_block);
+ } else if (le32_to_cpu(BHDR(bh)->h_refcount) >=
+diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
+index d7f5d6a..5992fe9 100644
+--- a/fs/ext4/xattr.h
++++ b/fs/ext4/xattr.h
+@@ -74,7 +74,6 @@ extern struct xattr_handler ext4_xattr_security_handler;
+ extern ssize_t ext4_listxattr(struct dentry *, char *, size_t);
+
+ extern int ext4_xattr_get(struct inode *, int, const char *, void *, size_t);
+-extern int ext4_xattr_list(struct inode *, char *, size_t);
+ extern int ext4_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
+ extern int ext4_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int);
+
+@@ -99,12 +98,6 @@ ext4_xattr_get(struct inode *inode, int name_index, const char *name,
+ }
+
+ static inline int
+-ext4_xattr_list(struct inode *inode, void *buffer, size_t size)
+-{
+- return -EOPNOTSUPP;
+-}
+-
+-static inline int
+ ext4_xattr_set(struct inode *inode, int name_index, const char *name,
+ const void *value, size_t size, int flags)
+ {
+diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c
+index f17eaf2..ca5f89f 100644
+--- a/fs/ext4/xattr_security.c
++++ b/fs/ext4/xattr_security.c
+@@ -6,9 +6,9 @@
+ #include <linux/module.h>
+ #include <linux/string.h>
+ #include <linux/fs.h>
+-#include <linux/ext4_jbd2.h>
+-#include <linux/ext4_fs.h>
+ #include <linux/security.h>
++#include "ext4_jbd2.h"
++#include "ext4.h"
+ #include "xattr.h"
+
+ static size_t
+diff --git a/fs/ext4/xattr_trusted.c b/fs/ext4/xattr_trusted.c
+index e0f05ac..fff3338 100644
+--- a/fs/ext4/xattr_trusted.c
++++ b/fs/ext4/xattr_trusted.c
+@@ -9,8 +9,8 @@
+ #include <linux/string.h>
+ #include <linux/capability.h>
+ #include <linux/fs.h>
+-#include <linux/ext4_jbd2.h>
+-#include <linux/ext4_fs.h>
++#include "ext4_jbd2.h"
++#include "ext4.h"
+ #include "xattr.h"
+
+ #define XATTR_TRUSTED_PREFIX "trusted."
+diff --git a/fs/ext4/xattr_user.c b/fs/ext4/xattr_user.c
+index 7ed3d8e..67be723 100644
+--- a/fs/ext4/xattr_user.c
++++ b/fs/ext4/xattr_user.c
+@@ -8,8 +8,8 @@
+ #include <linux/module.h>
+ #include <linux/string.h>
+ #include <linux/fs.h>
+-#include <linux/ext4_jbd2.h>
+-#include <linux/ext4_fs.h>
++#include "ext4_jbd2.h"
++#include "ext4.h"
+ #include "xattr.h"
+
+ #define XATTR_USER_PREFIX "user."
+diff --git a/fs/fat/cache.c b/fs/fat/cache.c
+index 639b3b4..fda2547 100644
+--- a/fs/fat/cache.c
++++ b/fs/fat/cache.c
+@@ -242,7 +242,7 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
+ /* prevent the infinite loop of cluster chain */
+ if (*fclus > limit) {
+ fat_fs_panic(sb, "%s: detected the cluster chain loop"
+- " (i_pos %lld)", __FUNCTION__,
++ " (i_pos %lld)", __func__,
+ MSDOS_I(inode)->i_pos);
+ nr = -EIO;
+ goto out;
+@@ -253,7 +253,7 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
+ goto out;
+ else if (nr == FAT_ENT_FREE) {
+ fat_fs_panic(sb, "%s: invalid cluster chain"
+- " (i_pos %lld)", __FUNCTION__,
++ " (i_pos %lld)", __func__,
+ MSDOS_I(inode)->i_pos);
+ nr = -EIO;
+ goto out;
+@@ -286,7 +286,7 @@ static int fat_bmap_cluster(struct inode *inode, int cluster)
+ return ret;
+ else if (ret == FAT_ENT_EOF) {
+ fat_fs_panic(sb, "%s: request beyond EOF (i_pos %lld)",
+- __FUNCTION__, MSDOS_I(inode)->i_pos);
++ __func__, MSDOS_I(inode)->i_pos);
+ return -EIO;
+ }
+ return dclus;
+diff --git a/fs/fat/dir.c b/fs/fat/dir.c
+index 72cbcd6..486725e 100644
+--- a/fs/fat/dir.c
++++ b/fs/fat/dir.c
+@@ -124,8 +124,8 @@ static inline int fat_get_entry(struct inode *dir, loff_t *pos,
+ * but ignore that right now.
+ * Ahem... Stack smashing in ring 0 isn't fun. Fixed.
+ */
+-static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int uni_xlate,
+- struct nls_table *nls)
++static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int len,
++ int uni_xlate, struct nls_table *nls)
+ {
+ wchar_t *ip, ec;
+ unsigned char *op, nc;
+@@ -135,10 +135,11 @@ static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int uni_xlate,
+ ip = uni;
+ op = ascii;
+
+- while (*ip) {
++ while (*ip && ((len - NLS_MAX_CHARSET_SIZE) > 0)) {
+ ec = *ip++;
+ if ( (charlen = nls->uni2char(ec, op, NLS_MAX_CHARSET_SIZE)) > 0) {
+ op += charlen;
++ len -= charlen;
+ } else {
+ if (uni_xlate == 1) {
+ *op = ':';
+@@ -149,16 +150,19 @@ static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int uni_xlate,
+ ec >>= 4;
+ }
+ op += 5;
++ len -= 5;
+ } else {
+ *op++ = '?';
++ len--;
+ }
+ }
+- /* We have some slack there, so it's OK */
+- if (op>ascii+256) {
+- op = ascii + 256;
+- break;
+- }
+ }
++
++ if (unlikely(*ip)) {
++ printk(KERN_WARNING "FAT: filename was truncated while "
++ "converting.");
++ }
++
+ *op = 0;
+ return (op - ascii);
+ }
+@@ -243,7 +247,7 @@ static int fat_parse_long(struct inode *dir, loff_t *pos,
+ unsigned char id, slot, slots, alias_checksum;
+
+ if (!*unicode) {
+- *unicode = (wchar_t *)__get_free_page(GFP_KERNEL);
++ *unicode = __getname();
+ if (!*unicode) {
+ brelse(*bh);
+ return -ENOMEM;
+@@ -311,9 +315,11 @@ int fat_search_long(struct inode *inode, const unsigned char *name,
+ struct nls_table *nls_io = sbi->nls_io;
+ struct nls_table *nls_disk = sbi->nls_disk;
+ wchar_t bufuname[14];
+- unsigned char xlate_len, nr_slots;
++ unsigned char nr_slots;
++ int xlate_len;
+ wchar_t *unicode = NULL;
+- unsigned char work[MSDOS_NAME], bufname[260]; /* 256 + 4 */
++ unsigned char work[MSDOS_NAME];
++ unsigned char *bufname = NULL;
+ int uni_xlate = sbi->options.unicode_xlate;
+ int utf8 = sbi->options.utf8;
+ int anycase = (sbi->options.name_check != 's');
+@@ -321,6 +327,10 @@ int fat_search_long(struct inode *inode, const unsigned char *name,
+ loff_t cpos = 0;
+ int chl, i, j, last_u, err;
+
++ bufname = __getname();
++ if (!bufname)
++ return -ENOMEM;
++
+ err = -ENOENT;
+ while(1) {
+ if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
+@@ -386,8 +396,8 @@ parse_record:
+
+ bufuname[last_u] = 0x0000;
+ xlate_len = utf8
+- ?utf8_wcstombs(bufname, bufuname, sizeof(bufname))
+- :uni16_to_x8(bufname, bufuname, uni_xlate, nls_io);
++ ?utf8_wcstombs(bufname, bufuname, PATH_MAX)
++ :uni16_to_x8(bufname, bufuname, PATH_MAX, uni_xlate, nls_io);
+ if (xlate_len == name_len)
+ if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
+ (anycase && !nls_strnicmp(nls_io, name, bufname,
+@@ -396,8 +406,8 @@ parse_record:
+
+ if (nr_slots) {
+ xlate_len = utf8
+- ?utf8_wcstombs(bufname, unicode, sizeof(bufname))
+- :uni16_to_x8(bufname, unicode, uni_xlate, nls_io);
++ ?utf8_wcstombs(bufname, unicode, PATH_MAX)
++ :uni16_to_x8(bufname, unicode, PATH_MAX, uni_xlate, nls_io);
+ if (xlate_len != name_len)
+ continue;
+ if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
+@@ -416,8 +426,10 @@ Found:
+ sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de);
+ err = 0;
+ EODir:
++ if (bufname)
++ __putname(bufname);
+ if (unicode)
+- free_page((unsigned long)unicode);
++ __putname(unicode);
+
+ return err;
+ }
+@@ -598,7 +610,7 @@ parse_record:
+ if (isvfat) {
+ bufuname[j] = 0x0000;
+ i = utf8 ? utf8_wcstombs(bufname, bufuname, sizeof(bufname))
+- : uni16_to_x8(bufname, bufuname, uni_xlate, nls_io);
++ : uni16_to_x8(bufname, bufuname, sizeof(bufname), uni_xlate, nls_io);
+ }
+
+ fill_name = bufname;
+@@ -607,10 +619,10 @@ parse_record:
+ /* convert the unicode long name. 261 is maximum size
+ * of unicode buffer. (13 * slots + nul) */
+ void *longname = unicode + 261;
+- int buf_size = PAGE_SIZE - (261 * sizeof(unicode[0]));
++ int buf_size = PATH_MAX - (261 * sizeof(unicode[0]));
+ int long_len = utf8
+ ? utf8_wcstombs(longname, unicode, buf_size)
+- : uni16_to_x8(longname, unicode, uni_xlate, nls_io);
++ : uni16_to_x8(longname, unicode, buf_size, uni_xlate, nls_io);
+
+ if (!both) {
+ fill_name = longname;
+@@ -640,7 +652,7 @@ EODir:
+ FillFailed:
+ brelse(bh);
+ if (unicode)
+- free_page((unsigned long)unicode);
++ __putname(unicode);
+ out:
+ unlock_kernel();
+ return ret;
+diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
+index 5fb3669..302e95c 100644
+--- a/fs/fat/fatent.c
++++ b/fs/fat/fatent.c
+@@ -450,7 +450,8 @@ int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster)
+ BUG_ON(nr_cluster > (MAX_BUF_PER_PAGE / 2)); /* fixed limit */
+
+ lock_fat(sbi);
+- if (sbi->free_clusters != -1 && sbi->free_clusters < nr_cluster) {
++ if (sbi->free_clusters != -1 && sbi->free_clus_valid &&
++ sbi->free_clusters < nr_cluster) {
+ unlock_fat(sbi);
+ return -ENOSPC;
+ }
+@@ -504,6 +505,7 @@ int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster)
+
+ /* Couldn't allocate the free entries */
+ sbi->free_clusters = 0;
++ sbi->free_clus_valid = 1;
+ sb->s_dirt = 1;
+ err = -ENOSPC;
+
+@@ -544,7 +546,7 @@ int fat_free_clusters(struct inode *inode, int cluster)
+ goto error;
+ } else if (cluster == FAT_ENT_FREE) {
+ fat_fs_panic(sb, "%s: deleting FAT entry beyond EOF",
+- __FUNCTION__);
++ __func__);
+ err = -EIO;
+ goto error;
+ }
+@@ -583,8 +585,6 @@ error:
+ brelse(bhs[i]);
+ unlock_fat(sbi);
+
+- fat_clusters_flush(sb);
+-
+ return err;
+ }
+
+@@ -615,7 +615,7 @@ int fat_count_free_clusters(struct super_block *sb)
+ int err = 0, free;
+
+ lock_fat(sbi);
+- if (sbi->free_clusters != -1)
++ if (sbi->free_clusters != -1 && sbi->free_clus_valid)
+ goto out;
+
+ reada_blocks = FAT_READA_SIZE >> sb->s_blocksize_bits;
+@@ -643,6 +643,7 @@ int fat_count_free_clusters(struct super_block *sb)
+ } while (fat_ent_next(sbi, &fatent));
+ }
+ sbi->free_clusters = free;
++ sbi->free_clus_valid = 1;
+ sb->s_dirt = 1;
+ fatent_brelse(&fatent);
+ out:
+diff --git a/fs/fat/file.c b/fs/fat/file.c
+index c614175..27cc116 100644
+--- a/fs/fat/file.c
++++ b/fs/fat/file.c
+@@ -8,6 +8,7 @@
+
+ #include <linux/capability.h>
+ #include <linux/module.h>
++#include <linux/mount.h>
+ #include <linux/time.h>
+ #include <linux/msdos_fs.h>
+ #include <linux/smp_lock.h>
+@@ -46,10 +47,9 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
+
+ mutex_lock(&inode->i_mutex);
+
+- if (IS_RDONLY(inode)) {
+- err = -EROFS;
+- goto up;
- }
++ err = mnt_want_write(filp->f_path.mnt);
+ if (err)
-+ goto flags_out;
++ goto up_no_drop_write;
- if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL))
- err = ext4_change_inode_journal_flag(inode, jflag);
-+flags_out:
- mutex_unlock(&inode->i_mutex);
+ /*
+ * 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;
}
- case EXT4_IOC_GETVERSION:
-@@ -129,14 +126,20 @@ flags_err:
+@@ -155,104 +157,6 @@ out:
+ return err;
+ }
- if (!is_owner_or_cap(inode))
- return -EPERM;
-- if (IS_RDONLY(inode))
-- return -EROFS;
-- if (get_user(generation, (int __user *) arg))
-- return -EFAULT;
+-static int check_mode(const struct msdos_sb_info *sbi, mode_t mode)
+-{
+- mode_t req = mode & ~S_IFMT;
+-
+- /*
+- * Of the r and x bits, all (subject to umask) must be present. Of the
+- * w bits, either all (subject to umask) or none must be present.
+- */
+-
+- if (S_ISREG(mode)) {
+- req &= ~sbi->options.fs_fmask;
+-
+- if ((req & (S_IRUGO | S_IXUGO)) !=
+- ((S_IRUGO | S_IXUGO) & ~sbi->options.fs_fmask))
+- return -EPERM;
+-
+- if ((req & S_IWUGO) != 0 &&
+- (req & S_IWUGO) != (S_IWUGO & ~sbi->options.fs_fmask))
+- return -EPERM;
+- } else if (S_ISDIR(mode)) {
+- req &= ~sbi->options.fs_dmask;
+-
+- if ((req & (S_IRUGO | S_IXUGO)) !=
+- ((S_IRUGO | S_IXUGO) & ~sbi->options.fs_dmask))
+- return -EPERM;
+-
+- if ((req & S_IWUGO) != 0 &&
+- (req & S_IWUGO) != (S_IWUGO & ~sbi->options.fs_dmask))
+- return -EPERM;
+- } else {
+- return -EPERM;
+- }
+-
+- return 0;
+-}
+-
+-int fat_notify_change(struct dentry *dentry, struct iattr *attr)
+-{
+- struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
+- struct inode *inode = dentry->d_inode;
+- int mask, error = 0;
+-
+- lock_kernel();
+-
+- /*
+- * Expand the file. Since inode_setattr() updates ->i_size
+- * before calling the ->truncate(), but FAT needs to fill the
+- * hole before it.
+- */
+- if (attr->ia_valid & ATTR_SIZE) {
+- if (attr->ia_size > inode->i_size) {
+- error = fat_cont_expand(inode, attr->ia_size);
+- if (error || attr->ia_valid == ATTR_SIZE)
+- goto out;
+- attr->ia_valid &= ~ATTR_SIZE;
+- }
+- }
+-
+- error = inode_change_ok(inode, attr);
+- if (error) {
+- if (sbi->options.quiet)
+- error = 0;
+- goto out;
+- }
+- if (((attr->ia_valid & ATTR_UID) &&
+- (attr->ia_uid != sbi->options.fs_uid)) ||
+- ((attr->ia_valid & ATTR_GID) &&
+- (attr->ia_gid != sbi->options.fs_gid)))
+- error = -EPERM;
+-
+- if (error) {
+- if (sbi->options.quiet)
+- error = 0;
+- goto out;
+- }
+-
+- if (attr->ia_valid & ATTR_MODE) {
+- error = check_mode(sbi, attr->ia_mode);
+- if (error != 0 && !sbi->options.quiet)
+- goto out;
+- }
+-
+- error = inode_setattr(inode, attr);
+- if (error)
+- goto out;
+-
+- if (S_ISDIR(inode->i_mode))
+- mask = sbi->options.fs_dmask;
+- else
+- mask = sbi->options.fs_fmask;
+- inode->i_mode &= S_IFMT | (S_IRWXUGO & ~mask);
+-out:
+- unlock_kernel();
+- return error;
+-}
+-
+-EXPORT_SYMBOL_GPL(fat_notify_change);
+-
+ /* Free all clusters after the skip'th cluster. */
+ static int fat_free(struct inode *inode, int skip)
+ {
+@@ -304,7 +208,7 @@ static int fat_free(struct inode *inode, int skip)
+ } else if (ret == FAT_ENT_FREE) {
+ fat_fs_panic(sb,
+ "%s: invalid cluster chain (i_pos %lld)",
+- __FUNCTION__, MSDOS_I(inode)->i_pos);
++ __func__, MSDOS_I(inode)->i_pos);
+ ret = -EIO;
+ } else if (ret > 0) {
+ err = fat_ent_write(inode, &fatent, FAT_ENT_EOF, wait);
+@@ -353,8 +257,112 @@ int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+ }
+ EXPORT_SYMBOL_GPL(fat_getattr);
+
++static int fat_check_mode(const struct msdos_sb_info *sbi, struct inode *inode,
++ mode_t mode)
++{
++ mode_t mask, req = mode & ~S_IFMT;
++
++ if (S_ISREG(mode))
++ mask = sbi->options.fs_fmask;
++ else
++ mask = sbi->options.fs_dmask;
++
++ /*
++ * Of the r and x bits, all (subject to umask) must be present. Of the
++ * w bits, either all (subject to umask) or none must be present.
++ */
++ req &= ~mask;
++ if ((req & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO)))
++ return -EPERM;
++ if ((req & S_IWUGO) && ((req & S_IWUGO) != (S_IWUGO & ~mask)))
++ return -EPERM;
++
++ return 0;
++}
++
++static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode)
++{
++ mode_t allow_utime = sbi->options.allow_utime;
++
++ if (current->fsuid != inode->i_uid) {
++ if (in_group_p(inode->i_gid))
++ allow_utime >>= 3;
++ if (allow_utime & MAY_WRITE)
++ return 1;
++ }
++
++ /* use a default check */
++ return 0;
++}
++
++int fat_setattr(struct dentry *dentry, struct iattr *attr)
++{
++ struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
++ struct inode *inode = dentry->d_inode;
++ int mask, error = 0;
++ unsigned int ia_valid;
++
++ lock_kernel();
++
++ /*
++ * Expand the file. Since inode_setattr() updates ->i_size
++ * before calling the ->truncate(), but FAT needs to fill the
++ * hole before it.
++ */
++ if (attr->ia_valid & ATTR_SIZE) {
++ if (attr->ia_size > inode->i_size) {
++ error = fat_cont_expand(inode, attr->ia_size);
++ if (error || attr->ia_valid == ATTR_SIZE)
++ goto out;
++ attr->ia_valid &= ~ATTR_SIZE;
++ }
++ }
++
++ /* Check for setting the inode time. */
++ ia_valid = attr->ia_valid;
++ if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
++ if (fat_allow_set_time(sbi, inode))
++ attr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET);
++ }
++
++ error = inode_change_ok(inode, attr);
++ attr->ia_valid = ia_valid;
++ if (error) {
++ if (sbi->options.quiet)
++ error = 0;
++ goto out;
++ }
++ if (((attr->ia_valid & ATTR_UID) &&
++ (attr->ia_uid != sbi->options.fs_uid)) ||
++ ((attr->ia_valid & ATTR_GID) &&
++ (attr->ia_gid != sbi->options.fs_gid)) ||
++ ((attr->ia_valid & ATTR_MODE) &&
++ fat_check_mode(sbi, inode, attr->ia_mode) < 0))
++ error = -EPERM;
++
++ if (error) {
++ if (sbi->options.quiet)
++ error = 0;
++ goto out;
++ }
++
++ error = inode_setattr(inode, attr);
++ if (error)
++ goto out;
++
++ if (S_ISDIR(inode->i_mode))
++ mask = sbi->options.fs_dmask;
++ else
++ mask = sbi->options.fs_fmask;
++ inode->i_mode &= S_IFMT | (S_IRWXUGO & ~mask);
++out:
++ unlock_kernel();
++ return error;
++}
++EXPORT_SYMBOL_GPL(fat_setattr);
++
+ const struct inode_operations fat_file_inode_operations = {
+ .truncate = fat_truncate,
+- .setattr = fat_notify_change,
++ .setattr = fat_setattr,
+ .getattr = fat_getattr,
+ };
+diff --git a/fs/fat/inode.c b/fs/fat/inode.c
+index 53f3cf6..4e0a3dd 100644
+--- a/fs/fat/inode.c
++++ b/fs/fat/inode.c
+@@ -433,11 +433,8 @@ EXPORT_SYMBOL_GPL(fat_build_inode);
+ static void fat_delete_inode(struct inode *inode)
+ {
+ truncate_inode_pages(&inode->i_data, 0);
+-
+- if (!is_bad_inode(inode)) {
+- inode->i_size = 0;
+- fat_truncate(inode);
+- }
++ inode->i_size = 0;
++ fat_truncate(inode);
+ clear_inode(inode);
+ }
+
+@@ -445,8 +442,6 @@ static void fat_clear_inode(struct inode *inode)
+ {
+ struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+
+- if (is_bad_inode(inode))
+- return;
+ lock_kernel();
+ spin_lock(&sbi->inode_hash_lock);
+ fat_cache_inval_inode(inode);
+@@ -542,7 +537,7 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf)
+ struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
+
+ /* If the count of free cluster is still unknown, counts it here. */
+- if (sbi->free_clusters == -1) {
++ if (sbi->free_clusters == -1 || !sbi->free_clus_valid) {
+ int err = fat_count_free_clusters(dentry->d_sb);
+ if (err)
+ return err;
+@@ -790,6 +785,8 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
+ seq_printf(m, ",gid=%u", opts->fs_gid);
+ seq_printf(m, ",fmask=%04o", opts->fs_fmask);
+ seq_printf(m, ",dmask=%04o", opts->fs_dmask);
++ if (opts->allow_utime)
++ seq_printf(m, ",allow_utime=%04o", opts->allow_utime);
+ if (sbi->nls_disk)
+ seq_printf(m, ",codepage=%s", sbi->nls_disk->charset);
+ if (isvfat) {
+@@ -845,9 +842,9 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
+
+ enum {
+ Opt_check_n, Opt_check_r, Opt_check_s, Opt_uid, Opt_gid,
+- Opt_umask, Opt_dmask, Opt_fmask, Opt_codepage, Opt_usefree, Opt_nocase,
+- Opt_quiet, Opt_showexec, Opt_debug, Opt_immutable,
+- Opt_dots, Opt_nodots,
++ Opt_umask, Opt_dmask, Opt_fmask, Opt_allow_utime, Opt_codepage,
++ Opt_usefree, Opt_nocase, Opt_quiet, Opt_showexec, Opt_debug,
++ Opt_immutable, Opt_dots, Opt_nodots,
+ Opt_charset, Opt_shortname_lower, Opt_shortname_win95,
+ Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
+ Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
+@@ -866,6 +863,7 @@ static match_table_t fat_tokens = {
+ {Opt_umask, "umask=%o"},
+ {Opt_dmask, "dmask=%o"},
+ {Opt_fmask, "fmask=%o"},
++ {Opt_allow_utime, "allow_utime=%o"},
+ {Opt_codepage, "codepage=%u"},
+ {Opt_usefree, "usefree"},
+ {Opt_nocase, "nocase"},
+@@ -937,6 +935,7 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
+ opts->fs_uid = current->uid;
+ opts->fs_gid = current->gid;
+ opts->fs_fmask = opts->fs_dmask = current->fs->umask;
++ opts->allow_utime = -1;
+ opts->codepage = fat_default_codepage;
+ opts->iocharset = fat_default_iocharset;
+ if (is_vfat)
+@@ -1024,6 +1023,11 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
+ return 0;
+ opts->fs_fmask = option;
+ break;
++ case Opt_allow_utime:
++ if (match_octal(&args[0], &option))
++ return 0;
++ opts->allow_utime = option & (S_IWGRP | S_IWOTH);
++ break;
+ case Opt_codepage:
+ if (match_int(&args[0], &option))
+ return 0;
+@@ -1106,6 +1110,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
+ " for FAT filesystems, filesystem will be case sensitive!\n");
+ }
+
++ /* If user doesn't specify allow_utime, it's initialized from dmask. */
++ if (opts->allow_utime == (unsigned short)-1)
++ opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH);
+ if (opts->unicode_xlate)
+ opts->utf8 = 0;
+
+@@ -1208,18 +1215,17 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
+ */
+
+ media = b->media;
+- if (!FAT_VALID_MEDIA(media)) {
++ if (!fat_valid_media(media)) {
+ if (!silent)
+ printk(KERN_ERR "FAT: invalid media value (0x%02x)\n",
+ media);
+ brelse(bh);
+ goto out_invalid;
+ }
+- logical_sector_size =
+- le16_to_cpu(get_unaligned((__le16 *)&b->sector_size));
++ logical_sector_size = get_unaligned_le16(&b->sector_size);
+ if (!is_power_of_2(logical_sector_size)
+ || (logical_sector_size < 512)
+- || (PAGE_CACHE_SIZE < logical_sector_size)) {
++ || (logical_sector_size > 4096)) {
+ if (!silent)
+ printk(KERN_ERR "FAT: bogus logical sector size %u\n",
+ logical_sector_size);
+@@ -1267,6 +1273,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
+ sbi->fat_length = le16_to_cpu(b->fat_length);
+ sbi->root_cluster = 0;
+ sbi->free_clusters = -1; /* Don't know yet */
++ sbi->free_clus_valid = 0;
+ sbi->prev_free = FAT_START_ENT;
+
+ if (!sbi->fat_length && b->fat32_length) {
+@@ -1302,8 +1309,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
+ sbi->fsinfo_sector);
+ } else {
+ if (sbi->options.usefree)
+- sbi->free_clusters =
+- le32_to_cpu(fsinfo->free_clusters);
++ sbi->free_clus_valid = 1;
++ sbi->free_clusters = le32_to_cpu(fsinfo->free_clusters);
+ sbi->prev_free = le32_to_cpu(fsinfo->next_cluster);
+ }
+
+@@ -1314,8 +1321,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
+ sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1;
+
+ sbi->dir_start = sbi->fat_start + sbi->fats * sbi->fat_length;
+- sbi->dir_entries =
+- le16_to_cpu(get_unaligned((__le16 *)&b->dir_entries));
++ sbi->dir_entries = get_unaligned_le16(&b->dir_entries);
+ if (sbi->dir_entries & (sbi->dir_per_block - 1)) {
+ if (!silent)
+ printk(KERN_ERR "FAT: bogus directroy-entries per block"
+@@ -1327,7 +1333,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
+ rootdir_sectors = sbi->dir_entries
+ * sizeof(struct msdos_dir_entry) / sb->s_blocksize;
+ sbi->data_start = sbi->dir_start + rootdir_sectors;
+- total_sectors = le16_to_cpu(get_unaligned((__le16 *)&b->sectors));
++ total_sectors = get_unaligned_le16(&b->sectors);
+ if (total_sectors == 0)
+ total_sectors = le32_to_cpu(b->total_sect);
+
+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/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
+index 2b46064..50ab5ee 100644
+--- a/fs/freevxfs/vxfs_extern.h
++++ b/fs/freevxfs/vxfs_extern.h
+@@ -50,7 +50,11 @@ extern daddr_t vxfs_bmap1(struct inode *, long);
+ /* vxfs_fshead.c */
+ extern int vxfs_read_fshead(struct super_block *);
+
++/* vxfs_immed.c */
++extern const struct inode_operations vxfs_immed_symlink_iops;
++
+ /* vxfs_inode.c */
++extern const struct address_space_operations vxfs_immed_aops;
+ extern struct kmem_cache *vxfs_inode_cachep;
+ extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t);
+ extern struct inode * vxfs_get_fake_inode(struct super_block *,
+@@ -69,6 +73,7 @@ extern const struct file_operations vxfs_dir_operations;
+ extern int vxfs_read_olt(struct super_block *, u_long);
+
+ /* vxfs_subr.c */
++extern const struct address_space_operations vxfs_aops;
+ extern struct page * vxfs_get_page(struct address_space *, u_long);
+ extern void vxfs_put_page(struct page *);
+ extern struct buffer_head * vxfs_bread(struct inode *, int);
+diff --git a/fs/freevxfs/vxfs_immed.c b/fs/freevxfs/vxfs_immed.c
+index 8a5959a..c36aeaf 100644
+--- a/fs/freevxfs/vxfs_immed.c
++++ b/fs/freevxfs/vxfs_immed.c
+@@ -35,6 +35,7 @@
+ #include <linux/namei.h>
+
+ #include "vxfs.h"
++#include "vxfs_extern.h"
+ #include "vxfs_inode.h"
+
+
+diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
+index ad88d23..9f3f2ce 100644
+--- a/fs/freevxfs/vxfs_inode.c
++++ b/fs/freevxfs/vxfs_inode.c
+@@ -41,11 +41,6 @@
+ #include "vxfs_extern.h"
+
+
+-extern const struct address_space_operations vxfs_aops;
+-extern const struct address_space_operations vxfs_immed_aops;
+-
+-extern const struct inode_operations vxfs_immed_symlink_iops;
+-
+ struct kmem_cache *vxfs_inode_cachep;
+
+
+diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
+index 0655767..ae45f77 100644
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -25,6 +25,45 @@
+ #include <linux/buffer_head.h>
+ #include "internal.h"
+
++
++/**
++ * writeback_acquire - attempt to get exclusive writeback access to a device
++ * @bdi: the device's backing_dev_info structure
++ *
++ * It is a waste of resources to have more than one pdflush thread blocked on
++ * a single request queue. Exclusion at the request_queue level is obtained
++ * via a flag in the request_queue's backing_dev_info.state.
++ *
++ * Non-request_queue-backed address_spaces will share default_backing_dev_info,
++ * unless they implement their own. Which is somewhat inefficient, as this
++ * may prevent concurrent writeback against multiple devices.
++ */
++static int writeback_acquire(struct backing_dev_info *bdi)
++{
++ return !test_and_set_bit(BDI_pdflush, &bdi->state);
++}
++
++/**
++ * writeback_in_progress - determine whether there is writeback in progress
++ * @bdi: the device's backing_dev_info structure.
++ *
++ * Determine whether there is writeback in progress against a backing device.
++ */
++int writeback_in_progress(struct backing_dev_info *bdi)
++{
++ return test_bit(BDI_pdflush, &bdi->state);
++}
++
++/**
++ * writeback_release - relinquish exclusive writeback access against a device.
++ * @bdi: the device's backing_dev_info structure
++ */
++static void writeback_release(struct backing_dev_info *bdi)
++{
++ BUG_ON(!writeback_in_progress(bdi));
++ clear_bit(BDI_pdflush, &bdi->state);
++}
++
+ /**
+ * __mark_inode_dirty - internal function
+ * @inode: inode to mark
+@@ -747,43 +786,4 @@ int generic_osync_inode(struct inode *inode, struct address_space *mapping, int
+
+ return err;
+ }
+-
+ EXPORT_SYMBOL(generic_osync_inode);
+-
+-/**
+- * writeback_acquire - attempt to get exclusive writeback access to a device
+- * @bdi: the device's backing_dev_info structure
+- *
+- * It is a waste of resources to have more than one pdflush thread blocked on
+- * a single request queue. Exclusion at the request_queue level is obtained
+- * via a flag in the request_queue's backing_dev_info.state.
+- *
+- * Non-request_queue-backed address_spaces will share default_backing_dev_info,
+- * unless they implement their own. Which is somewhat inefficient, as this
+- * may prevent concurrent writeback against multiple devices.
+- */
+-int writeback_acquire(struct backing_dev_info *bdi)
+-{
+- return !test_and_set_bit(BDI_pdflush, &bdi->state);
+-}
+-
+-/**
+- * writeback_in_progress - determine whether there is writeback in progress
+- * @bdi: the device's backing_dev_info structure.
+- *
+- * Determine whether there is writeback in progress against a backing device.
+- */
+-int writeback_in_progress(struct backing_dev_info *bdi)
+-{
+- return test_bit(BDI_pdflush, &bdi->state);
+-}
+-
+-/**
+- * writeback_release - relinquish exclusive writeback access against a device.
+- * @bdi: the device's backing_dev_info structure
+- */
+-void writeback_release(struct backing_dev_info *bdi)
+-{
+- BUG_ON(!writeback_in_progress(bdi));
+- clear_bit(BDI_pdflush, &bdi->state);
+-}
+diff --git a/fs/fuse/control.c b/fs/fuse/control.c
+index 105d4a2..4f3cab3 100644
+--- a/fs/fuse/control.c
++++ b/fs/fuse/control.c
+@@ -117,7 +117,7 @@ int fuse_ctl_add_conn(struct fuse_conn *fc)
+
+ parent = fuse_control_sb->s_root;
+ inc_nlink(parent->d_inode);
+- sprintf(name, "%llu", (unsigned long long) fc->id);
++ sprintf(name, "%u", fc->dev);
+ parent = fuse_ctl_add_dentry(parent, fc, name, S_IFDIR | 0500, 2,
+ &simple_dir_inode_operations,
+ &simple_dir_operations);
+diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
+index af63980..87250b6 100644
+--- a/fs/fuse/dev.c
++++ b/fs/fuse/dev.c
+@@ -47,6 +47,14 @@ struct fuse_req *fuse_request_alloc(void)
+ return req;
+ }
+
++struct fuse_req *fuse_request_alloc_nofs(void)
++{
++ struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, GFP_NOFS);
++ if (req)
++ fuse_request_init(req);
++ return req;
++}
++
+ void fuse_request_free(struct fuse_req *req)
+ {
+ kmem_cache_free(fuse_req_cachep, req);
+@@ -291,6 +299,7 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
+
+ static void wait_answer_interruptible(struct fuse_conn *fc,
+ struct fuse_req *req)
++ __releases(fc->lock) __acquires(fc->lock)
+ {
+ if (signal_pending(current))
+ return;
+@@ -307,8 +316,8 @@ static void queue_interrupt(struct fuse_conn *fc, struct fuse_req *req)
+ kill_fasync(&fc->fasync, SIGIO, POLL_IN);
+ }
+
+-/* Called with fc->lock held. Releases, and then reacquires it. */
+ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
++ __releases(fc->lock) __acquires(fc->lock)
+ {
+ if (!fc->no_interrupt) {
+ /* Any signal may interrupt this */
+@@ -430,6 +439,17 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req)
+ }
+
+ /*
++ * Called under fc->lock
++ *
++ * fc->connected must have been checked previously
++ */
++void request_send_background_locked(struct fuse_conn *fc, struct fuse_req *req)
++{
++ req->isreply = 1;
++ request_send_nowait_locked(fc, req);
++}
++
++/*
+ * Lock the request. Up to the next unlock_request() there mustn't be
+ * anything that could cause a page-fault. If the request was already
+ * aborted bail out.
+@@ -968,6 +988,7 @@ static void end_requests(struct fuse_conn *fc, struct list_head *head)
+ * locked).
+ */
+ static void end_io_requests(struct fuse_conn *fc)
++ __releases(fc->lock) __acquires(fc->lock)
+ {
+ while (!list_empty(&fc->io)) {
+ struct fuse_req *req =
+diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
+index c4807b3..2060bf0 100644
+--- a/fs/fuse/dir.c
++++ b/fs/fuse/dir.c
+@@ -132,7 +132,7 @@ static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
+ req->out.args[0].value = outarg;
+ }
+
+-static u64 fuse_get_attr_version(struct fuse_conn *fc)
++u64 fuse_get_attr_version(struct fuse_conn *fc)
+ {
+ u64 curr_version;
+
+@@ -1107,6 +1107,50 @@ static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
+ }
+
+ /*
++ * Prevent concurrent writepages on inode
++ *
++ * This is done by adding a negative bias to the inode write counter
++ * and waiting for all pending writes to finish.
++ */
++void fuse_set_nowrite(struct inode *inode)
++{
++ struct fuse_conn *fc = get_fuse_conn(inode);
++ struct fuse_inode *fi = get_fuse_inode(inode);
++
++ BUG_ON(!mutex_is_locked(&inode->i_mutex));
++
++ spin_lock(&fc->lock);
++ BUG_ON(fi->writectr < 0);
++ fi->writectr += FUSE_NOWRITE;
++ spin_unlock(&fc->lock);
++ wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
++}
++
++/*
++ * Allow writepages on inode
++ *
++ * Remove the bias from the writecounter and send any queued
++ * writepages.
++ */
++static void __fuse_release_nowrite(struct inode *inode)
++{
++ struct fuse_inode *fi = get_fuse_inode(inode);
++
++ BUG_ON(fi->writectr != FUSE_NOWRITE);
++ fi->writectr = 0;
++ fuse_flush_writepages(inode);
++}
++
++void fuse_release_nowrite(struct inode *inode)
++{
++ struct fuse_conn *fc = get_fuse_conn(inode);
++
++ spin_lock(&fc->lock);
++ __fuse_release_nowrite(inode);
++ spin_unlock(&fc->lock);
++}
++
++/*
+ * Set attributes, and at the same time refresh them.
+ *
+ * Truncation is slightly complicated, because the 'truncate' request
+@@ -1122,6 +1166,8 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
+ struct fuse_req *req;
+ struct fuse_setattr_in inarg;
+ struct fuse_attr_out outarg;
++ bool is_truncate = false;
++ loff_t oldsize;
+ int err;
+
+ if (!fuse_allow_task(fc, current))
+@@ -1145,12 +1191,16 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
+ send_sig(SIGXFSZ, current, 0);
+ return -EFBIG;
+ }
++ is_truncate = true;
+ }
+
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
+
++ if (is_truncate)
++ fuse_set_nowrite(inode);
++
+ memset(&inarg, 0, sizeof(inarg));
+ memset(&outarg, 0, sizeof(outarg));
+ iattr_to_fattr(attr, &inarg);
+@@ -1181,16 +1231,44 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
+ if (err) {
+ if (err == -EINTR)
+ fuse_invalidate_attr(inode);
+- return err;
++ goto error;
+ }
+
+ if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
+ make_bad_inode(inode);
+- return -EIO;
++ err = -EIO;
++ goto error;
++ }
++
++ spin_lock(&fc->lock);
++ fuse_change_attributes_common(inode, &outarg.attr,
++ attr_timeout(&outarg));
++ oldsize = inode->i_size;
++ i_size_write(inode, outarg.attr.size);
++
++ if (is_truncate) {
++ /* NOTE: this may release/reacquire fc->lock */
++ __fuse_release_nowrite(inode);
++ }
++ spin_unlock(&fc->lock);
++
++ /*
++ * Only call invalidate_inode_pages2() after removing
++ * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
++ */
++ if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
++ if (outarg.attr.size < oldsize)
++ fuse_truncate(inode->i_mapping, outarg.attr.size);
++ invalidate_inode_pages2(inode->i_mapping);
+ }
+
+- fuse_change_attributes(inode, &outarg.attr, attr_timeout(&outarg), 0);
+ return 0;
++
++error:
++ if (is_truncate)
++ fuse_release_nowrite(inode);
++
++ return err;
+ }
+
+ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
+diff --git a/fs/fuse/file.c b/fs/fuse/file.c
+index 676b0bc..9ced35b 100644
+--- a/fs/fuse/file.c
++++ b/fs/fuse/file.c
+@@ -210,6 +210,49 @@ u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
+ return (u64) v0 + ((u64) v1 << 32);
+ }
+
++/*
++ * Check if page is under writeback
++ *
++ * This is currently done by walking the list of writepage requests
++ * for the inode, which can be pretty inefficient.
++ */
++static bool fuse_page_is_writeback(struct inode *inode, pgoff_t index)
++{
++ struct fuse_conn *fc = get_fuse_conn(inode);
++ struct fuse_inode *fi = get_fuse_inode(inode);
++ struct fuse_req *req;
++ bool found = false;
++
++ spin_lock(&fc->lock);
++ list_for_each_entry(req, &fi->writepages, writepages_entry) {
++ pgoff_t curr_index;
++
++ BUG_ON(req->inode != inode);
++ curr_index = req->misc.write.in.offset >> PAGE_CACHE_SHIFT;
++ if (curr_index == index) {
++ found = true;
++ break;
++ }
++ }
++ spin_unlock(&fc->lock);
++
++ return found;
++}
++
++/*
++ * Wait for page writeback to be completed.
++ *
++ * Since fuse doesn't rely on the VM writeback tracking, this has to
++ * use some other means.
++ */
++static int fuse_wait_on_page_writeback(struct inode *inode, pgoff_t index)
++{
++ struct fuse_inode *fi = get_fuse_inode(inode);
++
++ wait_event(fi->page_waitq, !fuse_page_is_writeback(inode, index));
++ return 0;
++}
++
+ static int fuse_flush(struct file *file, fl_owner_t id)
+ {
+ struct inode *inode = file->f_path.dentry->d_inode;
+@@ -245,6 +288,21 @@ static int fuse_flush(struct file *file, fl_owner_t id)
+ return err;
+ }
+
++/*
++ * Wait for all pending writepages on the inode to finish.
++ *
++ * This is currently done by blocking further writes with FUSE_NOWRITE
++ * and waiting for all sent writes to complete.
++ *
++ * This must be called under i_mutex, otherwise the FUSE_NOWRITE usage
++ * could conflict with truncation.
++ */
++static void fuse_sync_writes(struct inode *inode)
++{
++ fuse_set_nowrite(inode);
++ fuse_release_nowrite(inode);
++}
++
+ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
+ int isdir)
+ {
+@@ -261,6 +319,17 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
+ if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
+ return 0;
+
++ /*
++ * Start writeback against all dirty pages of the inode, then
++ * wait for all outstanding writes, before sending the FSYNC
++ * request.
++ */
++ err = write_inode_now(inode, 0);
++ if (err)
++ return err;
++
++ fuse_sync_writes(inode);
++
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
+@@ -294,7 +363,7 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
+ void fuse_read_fill(struct fuse_req *req, struct file *file,
+ struct inode *inode, loff_t pos, size_t count, int opcode)
+ {
+- struct fuse_read_in *inarg = &req->misc.read_in;
++ struct fuse_read_in *inarg = &req->misc.read.in;
+ struct fuse_file *ff = file->private_data;
+
+ inarg->fh = ff->fh;
+@@ -320,7 +389,7 @@ static size_t fuse_send_read(struct fuse_req *req, struct file *file,
+
+ fuse_read_fill(req, file, inode, pos, count, FUSE_READ);
+ if (owner != NULL) {
+- struct fuse_read_in *inarg = &req->misc.read_in;
++ struct fuse_read_in *inarg = &req->misc.read.in;
+
+ inarg->read_flags |= FUSE_READ_LOCKOWNER;
+ inarg->lock_owner = fuse_lock_owner_id(fc, owner);
+@@ -329,31 +398,66 @@ static size_t fuse_send_read(struct fuse_req *req, struct file *file,
+ return req->out.args[0].size;
+ }
+
++static void fuse_read_update_size(struct inode *inode, loff_t size,
++ u64 attr_ver)
++{
++ struct fuse_conn *fc = get_fuse_conn(inode);
++ struct fuse_inode *fi = get_fuse_inode(inode);
++
++ spin_lock(&fc->lock);
++ if (attr_ver == fi->attr_version && size < inode->i_size) {
++ fi->attr_version = ++fc->attr_version;
++ i_size_write(inode, size);
++ }
++ spin_unlock(&fc->lock);
++}
++
+ static int fuse_readpage(struct file *file, struct page *page)
+ {
+ struct inode *inode = page->mapping->host;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_req *req;
++ size_t num_read;
++ loff_t pos = page_offset(page);
++ size_t count = PAGE_CACHE_SIZE;
++ u64 attr_ver;
+ int err;
+
+ err = -EIO;
+ if (is_bad_inode(inode))
+ goto out;
+
++ /*
++ * Page writeback can extend beyond the liftime of the
++ * page-cache page, so make sure we read a properly synced
++ * page.
++ */
++ fuse_wait_on_page_writeback(inode, page->index);
++
+ req = fuse_get_req(fc);
+ err = PTR_ERR(req);
+ if (IS_ERR(req))
+ goto out;
+
++ attr_ver = fuse_get_attr_version(fc);
++
+ req->out.page_zeroing = 1;
+ req->num_pages = 1;
+ req->pages[0] = page;
+- fuse_send_read(req, file, inode, page_offset(page), PAGE_CACHE_SIZE,
+- NULL);
++ num_read = fuse_send_read(req, file, inode, pos, count, NULL);
+ err = req->out.h.error;
+ fuse_put_request(fc, req);
+- if (!err)
++
++ if (!err) {
++ /*
++ * Short read means EOF. If file size is larger, truncate it
++ */
++ if (num_read < count)
++ fuse_read_update_size(inode, pos + num_read, attr_ver);
++
+ SetPageUptodate(page);
++ }
++
+ fuse_invalidate_attr(inode); /* atime changed */
+ out:
+ unlock_page(page);
+@@ -363,8 +467,19 @@ static int fuse_readpage(struct file *file, struct page *page)
+ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)
+ {
+ int i;
++ size_t count = req->misc.read.in.size;
++ size_t num_read = req->out.args[0].size;
++ struct inode *inode = req->pages[0]->mapping->host;
++
++ /*
++ * Short read means EOF. If file size is larger, truncate it
++ */
++ if (!req->out.h.error && num_read < count) {
++ loff_t pos = page_offset(req->pages[0]) + num_read;
++ fuse_read_update_size(inode, pos, req->misc.read.attr_ver);
++ }
+
+- fuse_invalidate_attr(req->pages[0]->mapping->host); /* atime changed */
++ fuse_invalidate_attr(inode); /* atime changed */
+
+ for (i = 0; i < req->num_pages; i++) {
+ struct page *page = req->pages[i];
+@@ -387,6 +502,7 @@ static void fuse_send_readpages(struct fuse_req *req, struct file *file,
+ size_t count = req->num_pages << PAGE_CACHE_SHIFT;
+ req->out.page_zeroing = 1;
+ fuse_read_fill(req, file, inode, pos, count, FUSE_READ);
++ req->misc.read.attr_ver = fuse_get_attr_version(fc);
+ if (fc->async_read) {
+ struct fuse_file *ff = file->private_data;
+ req->ff = fuse_file_get(ff);
+@@ -411,6 +527,8 @@ static int fuse_readpages_fill(void *_data, struct page *page)
+ struct inode *inode = data->inode;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+
++ fuse_wait_on_page_writeback(inode, page->index);
++
+ if (req->num_pages &&
+ (req->num_pages == FUSE_MAX_PAGES_PER_REQ ||
+ (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read ||
+@@ -477,11 +595,10 @@ static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ }
+
+ static void fuse_write_fill(struct fuse_req *req, struct file *file,
+- struct inode *inode, loff_t pos, size_t count,
+- int writepage)
++ struct fuse_file *ff, struct inode *inode,
++ loff_t pos, size_t count, int writepage)
+ {
+ struct fuse_conn *fc = get_fuse_conn(inode);
+- struct fuse_file *ff = file->private_data;
+ struct fuse_write_in *inarg = &req->misc.write.in;
+ struct fuse_write_out *outarg = &req->misc.write.out;
+
+@@ -490,7 +607,7 @@ static void fuse_write_fill(struct fuse_req *req, struct file *file,
+ inarg->offset = pos;
+ inarg->size = count;
+ inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0;
+- inarg->flags = file->f_flags;
++ inarg->flags = file ? file->f_flags : 0;
+ req->in.h.opcode = FUSE_WRITE;
+ req->in.h.nodeid = get_node_id(inode);
+ req->in.argpages = 1;
+@@ -511,7 +628,7 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file,
+ fl_owner_t owner)
+ {
+ struct fuse_conn *fc = get_fuse_conn(inode);
+- fuse_write_fill(req, file, inode, pos, count, 0);
++ fuse_write_fill(req, file, file->private_data, inode, pos, count, 0);
+ if (owner != NULL) {
+ struct fuse_write_in *inarg = &req->misc.write.in;
+ inarg->write_flags |= FUSE_WRITE_LOCKOWNER;
+@@ -533,19 +650,36 @@ static int fuse_write_begin(struct file *file, struct address_space *mapping,
+ return 0;
+ }
+
++static void fuse_write_update_size(struct inode *inode, loff_t pos)
++{
++ struct fuse_conn *fc = get_fuse_conn(inode);
++ struct fuse_inode *fi = get_fuse_inode(inode);
++
++ spin_lock(&fc->lock);
++ fi->attr_version = ++fc->attr_version;
++ if (pos > inode->i_size)
++ i_size_write(inode, pos);
++ spin_unlock(&fc->lock);
++}
++
+ static int fuse_buffered_write(struct file *file, struct inode *inode,
+ loff_t pos, unsigned count, struct page *page)
+ {
+ int err;
+ size_t nres;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+- struct fuse_inode *fi = get_fuse_inode(inode);
+ unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
+ struct fuse_req *req;
+
+ if (is_bad_inode(inode))
+ return -EIO;
+
++ /*
++ * Make sure writepages on the same page are not mixed up with
++ * plain writes.
++ */
++ fuse_wait_on_page_writeback(inode, page->index);
++
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
+@@ -560,12 +694,7 @@ static int fuse_buffered_write(struct file *file, struct inode *inode,
+ err = -EIO;
+ if (!err) {
+ pos += nres;
+- spin_lock(&fc->lock);
+- fi->attr_version = ++fc->attr_version;
+- if (pos > inode->i_size)
+- i_size_write(inode, pos);
+- spin_unlock(&fc->lock);
+-
++ fuse_write_update_size(inode, pos);
+ if (count == PAGE_CACHE_SIZE)
+ SetPageUptodate(page);
+ }
+@@ -588,6 +717,198 @@ static int fuse_write_end(struct file *file, struct address_space *mapping,
+ return res;
+ }
+
++static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file,
++ struct inode *inode, loff_t pos,
++ size_t count)
++{
++ size_t res;
++ unsigned offset;
++ unsigned i;
++
++ for (i = 0; i < req->num_pages; i++)
++ fuse_wait_on_page_writeback(inode, req->pages[i]->index);
++
++ res = fuse_send_write(req, file, inode, pos, count, NULL);
++
++ offset = req->page_offset;
++ count = res;
++ for (i = 0; i < req->num_pages; i++) {
++ struct page *page = req->pages[i];
++
++ if (!req->out.h.error && !offset && count >= PAGE_CACHE_SIZE)
++ SetPageUptodate(page);
++
++ if (count > PAGE_CACHE_SIZE - offset)
++ count -= PAGE_CACHE_SIZE - offset;
++ else
++ count = 0;
++ offset = 0;
++
++ unlock_page(page);
++ page_cache_release(page);
++ }
++
++ return res;
++}
++
++static ssize_t fuse_fill_write_pages(struct fuse_req *req,
++ struct address_space *mapping,
++ struct iov_iter *ii, loff_t pos)
++{
++ struct fuse_conn *fc = get_fuse_conn(mapping->host);
++ unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
++ size_t count = 0;
++ int err;
++
++ req->page_offset = offset;
++
++ do {
++ size_t tmp;
++ struct page *page;
++ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
++ size_t bytes = min_t(size_t, PAGE_CACHE_SIZE - offset,
++ iov_iter_count(ii));
++
++ bytes = min_t(size_t, bytes, fc->max_write - count);
++
++ again:
++ err = -EFAULT;
++ if (iov_iter_fault_in_readable(ii, bytes))
++ break;
+
-+ err = mnt_want_write(filp->f_path.mnt);
-+ if (err)
-+ return err;
-+ if (get_user(generation, (int __user *) arg)) {
-+ err = -EFAULT;
-+ goto setversion_out;
++ err = -ENOMEM;
++ page = __grab_cache_page(mapping, index);
++ if (!page)
++ break;
++
++ pagefault_disable();
++ tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes);
++ pagefault_enable();
++ flush_dcache_page(page);
++
++ if (!tmp) {
++ unlock_page(page);
++ page_cache_release(page);
++ bytes = min(bytes, iov_iter_single_seg_count(ii));
++ goto again;
+ }
-
- 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 = 0;
++ req->pages[req->num_pages] = page;
++ req->num_pages++;
++
++ iov_iter_advance(ii, tmp);
++ count += tmp;
++ pos += tmp;
++ offset += tmp;
++ if (offset == PAGE_CACHE_SIZE)
++ offset = 0;
++
++ } while (iov_iter_count(ii) && count < fc->max_write &&
++ req->num_pages < FUSE_MAX_PAGES_PER_REQ && offset == 0);
++
++ return count > 0 ? count : err;
++}
++
++static ssize_t fuse_perform_write(struct file *file,
++ struct address_space *mapping,
++ struct iov_iter *ii, loff_t pos)
++{
++ struct inode *inode = mapping->host;
++ struct fuse_conn *fc = get_fuse_conn(inode);
++ int err = 0;
++ ssize_t res = 0;
++
++ if (is_bad_inode(inode))
++ return -EIO;
++
++ do {
++ struct fuse_req *req;
++ ssize_t count;
++
++ req = fuse_get_req(fc);
++ if (IS_ERR(req)) {
++ err = PTR_ERR(req);
++ break;
+ }
- 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);
++
++ count = fuse_fill_write_pages(req, mapping, ii, pos);
++ if (count <= 0) {
++ err = count;
++ } else {
++ size_t num_written;
++
++ num_written = fuse_send_write_pages(req, file, inode,
++ pos, count);
++ err = req->out.h.error;
++ if (!err) {
++ res += num_written;
++ pos += num_written;
++
++ /* break out of the loop on short write */
++ if (num_written != count)
++ err = -EIO;
++ }
++ }
++ fuse_put_request(fc, req);
++ } while (!err && iov_iter_count(ii));
++
++ if (res > 0)
++ fuse_write_update_size(inode, pos);
++
++ fuse_invalidate_attr(inode);
++
++ return res > 0 ? res : err;
++}
++
++static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
++ unsigned long nr_segs, loff_t pos)
++{
++ struct file *file = iocb->ki_filp;
++ struct address_space *mapping = file->f_mapping;
++ size_t count = 0;
++ ssize_t written = 0;
++ struct inode *inode = mapping->host;
++ ssize_t err;
++ struct iov_iter i;
++
++ WARN_ON(iocb->ki_pos != pos);
++
++ err = generic_segment_checks(iov, &nr_segs, &count, VERIFY_READ);
++ if (err)
++ return err;
++
++ mutex_lock(&inode->i_mutex);
++ vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
++
++ /* We can write back this queue in page reclaim */
++ current->backing_dev_info = mapping->backing_dev_info;
++
++ err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
++ if (err)
++ goto out;
++
++ if (count == 0)
++ goto out;
++
++ err = remove_suid(file->f_path.dentry);
++ if (err)
++ goto out;
++
++ file_update_time(file);
++
++ iov_iter_init(&i, iov, nr_segs, count, 0);
++ written = fuse_perform_write(file, mapping, &i, pos);
++ if (written >= 0)
++ iocb->ki_pos = pos + written;
++
++out:
++ current->backing_dev_info = NULL;
++ mutex_unlock(&inode->i_mutex);
++
++ return written ? written : err;
++}
++
+ static void fuse_release_user_pages(struct fuse_req *req, int write)
+ {
+ unsigned i;
+@@ -645,14 +966,15 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
+
+ while (count) {
+ size_t nres;
+- size_t nbytes = min(count, nmax);
+- int err = fuse_get_user_pages(req, buf, nbytes, !write);
++ size_t nbytes_limit = min(count, nmax);
++ size_t nbytes;
++ int err = fuse_get_user_pages(req, buf, nbytes_limit, !write);
+ if (err) {
+ res = err;
+ break;
}
- ext4_journal_stop(handle);
-+setversion_out:
-+ mnt_drop_write(filp->f_path.mnt);
- return err;
+ nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset;
+- nbytes = min(count, nbytes);
++ nbytes = min(nbytes_limit, nbytes);
+ if (write)
+ nres = fuse_send_write(req, file, inode, pos, nbytes,
+ current->files);
+@@ -683,12 +1005,8 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
+ }
+ fuse_put_request(fc, req);
+ if (res > 0) {
+- if (write) {
+- spin_lock(&fc->lock);
+- if (pos > inode->i_size)
+- i_size_write(inode, pos);
+- spin_unlock(&fc->lock);
+- }
++ if (write)
++ fuse_write_update_size(inode, pos);
+ *ppos = pos;
}
- #ifdef CONFIG_JBD2_DEBUG
-@@ -179,19 +184,21 @@ flags_err:
- }
- return -ENOTTY;
- case EXT4_IOC_SETRSVSZ: {
-+ int err;
+ fuse_invalidate_attr(inode);
+@@ -716,21 +1034,225 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
+ return res;
+ }
- if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
- return -ENOTTY;
+-static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
++static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req)
+ {
+- if ((vma->vm_flags & VM_SHARED)) {
+- if ((vma->vm_flags & VM_WRITE))
+- return -ENODEV;
+- else
+- vma->vm_flags &= ~VM_MAYWRITE;
++ __free_page(req->pages[0]);
++ fuse_file_put(req->ff);
++ fuse_put_request(fc, req);
++}
++
++static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req)
++{
++ struct inode *inode = req->inode;
++ struct fuse_inode *fi = get_fuse_inode(inode);
++ struct backing_dev_info *bdi = inode->i_mapping->backing_dev_info;
++
++ list_del(&req->writepages_entry);
++ dec_bdi_stat(bdi, BDI_WRITEBACK);
++ dec_zone_page_state(req->pages[0], NR_WRITEBACK_TEMP);
++ bdi_writeout_inc(bdi);
++ wake_up(&fi->page_waitq);
++}
++
++/* Called under fc->lock, may release and reacquire it */
++static void fuse_send_writepage(struct fuse_conn *fc, struct fuse_req *req)
++{
++ struct fuse_inode *fi = get_fuse_inode(req->inode);
++ loff_t size = i_size_read(req->inode);
++ struct fuse_write_in *inarg = &req->misc.write.in;
++
++ if (!fc->connected)
++ goto out_free;
++
++ if (inarg->offset + PAGE_CACHE_SIZE <= size) {
++ inarg->size = PAGE_CACHE_SIZE;
++ } else if (inarg->offset < size) {
++ inarg->size = size & (PAGE_CACHE_SIZE - 1);
++ } else {
++ /* Got truncated off completely */
++ goto out_free;
++ }
++
++ req->in.args[1].size = inarg->size;
++ fi->writectr++;
++ request_send_background_locked(fc, req);
++ return;
++
++ out_free:
++ fuse_writepage_finish(fc, req);
++ spin_unlock(&fc->lock);
++ fuse_writepage_free(fc, req);
++ spin_lock(&fc->lock);
++}
++
++/*
++ * If fi->writectr is positive (no truncate or fsync going on) send
++ * all queued writepage requests.
++ *
++ * Called with fc->lock
++ */
++void fuse_flush_writepages(struct inode *inode)
++{
++ struct fuse_conn *fc = get_fuse_conn(inode);
++ struct fuse_inode *fi = get_fuse_inode(inode);
++ struct fuse_req *req;
++
++ while (fi->writectr >= 0 && !list_empty(&fi->queued_writes)) {
++ req = list_entry(fi->queued_writes.next, struct fuse_req, list);
++ list_del_init(&req->list);
++ fuse_send_writepage(fc, req);
++ }
++}
++
++static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_req *req)
++{
++ struct inode *inode = req->inode;
++ struct fuse_inode *fi = get_fuse_inode(inode);
++
++ mapping_set_error(inode->i_mapping, req->out.h.error);
++ spin_lock(&fc->lock);
++ fi->writectr--;
++ fuse_writepage_finish(fc, req);
++ spin_unlock(&fc->lock);
++ fuse_writepage_free(fc, req);
++}
++
++static int fuse_writepage_locked(struct page *page)
++{
++ struct address_space *mapping = page->mapping;
++ struct inode *inode = mapping->host;
++ struct fuse_conn *fc = get_fuse_conn(inode);
++ struct fuse_inode *fi = get_fuse_inode(inode);
++ struct fuse_req *req;
++ struct fuse_file *ff;
++ struct page *tmp_page;
++
++ set_page_writeback(page);
++
++ req = fuse_request_alloc_nofs();
++ if (!req)
++ goto err;
++
++ tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
++ if (!tmp_page)
++ goto err_free;
++
++ spin_lock(&fc->lock);
++ BUG_ON(list_empty(&fi->write_files));
++ ff = list_entry(fi->write_files.next, struct fuse_file, write_entry);
++ req->ff = fuse_file_get(ff);
++ spin_unlock(&fc->lock);
++
++ fuse_write_fill(req, NULL, ff, inode, page_offset(page), 0, 1);
++
++ copy_highpage(tmp_page, page);
++ req->num_pages = 1;
++ req->pages[0] = tmp_page;
++ req->page_offset = 0;
++ req->end = fuse_writepage_end;
++ req->inode = inode;
++
++ inc_bdi_stat(mapping->backing_dev_info, BDI_WRITEBACK);
++ inc_zone_page_state(tmp_page, NR_WRITEBACK_TEMP);
++ end_page_writeback(page);
++
++ spin_lock(&fc->lock);
++ list_add(&req->writepages_entry, &fi->writepages);
++ list_add_tail(&req->list, &fi->queued_writes);
++ fuse_flush_writepages(inode);
++ spin_unlock(&fc->lock);
++
++ return 0;
++
++err_free:
++ fuse_request_free(req);
++err:
++ end_page_writeback(page);
++ return -ENOMEM;
++}
++
++static int fuse_writepage(struct page *page, struct writeback_control *wbc)
++{
++ int err;
++
++ err = fuse_writepage_locked(page);
++ unlock_page(page);
++
++ return err;
++}
++
++static int fuse_launder_page(struct page *page)
++{
++ int err = 0;
++ if (clear_page_dirty_for_io(page)) {
++ struct inode *inode = page->mapping->host;
++ err = fuse_writepage_locked(page);
++ if (!err)
++ fuse_wait_on_page_writeback(inode, page->index);
+ }
+- return generic_file_mmap(file, vma);
++ return err;
+ }
-- if (IS_RDONLY(inode))
-- return -EROFS;
--
- if (!is_owner_or_cap(inode))
- return -EACCES;
+-static int fuse_set_page_dirty(struct page *page)
++/*
++ * Write back dirty pages now, because there may not be any suitable
++ * open files later
++ */
++static void fuse_vma_close(struct vm_area_struct *vma)
+ {
+- printk("fuse_set_page_dirty: should not happen\n");
+- dump_stack();
++ filemap_write_and_wait(vma->vm_file->f_mapping);
++}
++
++/*
++ * Wait for writeback against this page to complete before allowing it
++ * to be marked dirty again, and hence written back again, possibly
++ * before the previous writepage completed.
++ *
++ * Block here, instead of in ->writepage(), so that the userspace fs
++ * can only block processes actually operating on the filesystem.
++ *
++ * Otherwise unprivileged userspace fs would be able to block
++ * unrelated:
++ *
++ * - page migration
++ * - sync(2)
++ * - try_to_free_pages() with order > PAGE_ALLOC_COSTLY_ORDER
++ */
++static int fuse_page_mkwrite(struct vm_area_struct *vma, struct page *page)
++{
++ /*
++ * Don't use page->mapping as it may become NULL from a
++ * concurrent truncate.
++ */
++ struct inode *inode = vma->vm_file->f_mapping->host;
++
++ fuse_wait_on_page_writeback(inode, page->index);
++ return 0;
++}
++
++static struct vm_operations_struct fuse_file_vm_ops = {
++ .close = fuse_vma_close,
++ .fault = filemap_fault,
++ .page_mkwrite = fuse_page_mkwrite,
++};
++
++static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) {
++ struct inode *inode = file->f_dentry->d_inode;
++ struct fuse_conn *fc = get_fuse_conn(inode);
++ struct fuse_inode *fi = get_fuse_inode(inode);
++ struct fuse_file *ff = file->private_data;
++ /*
++ * file may be written through mmap, so chain it onto the
++ * inodes's write_file list
++ */
++ spin_lock(&fc->lock);
++ if (list_empty(&ff->write_entry))
++ list_add(&ff->write_entry, &fi->write_files);
++ spin_unlock(&fc->lock);
++ }
++ file_accessed(file);
++ vma->vm_ops = &fuse_file_vm_ops;
+ return 0;
+ }
- if (get_user(rsv_window_size, (int __user *)arg))
- return -EFAULT;
+@@ -909,12 +1431,37 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
+ return err ? 0 : outarg.block;
+ }
-+ err = mnt_want_write(filp->f_path.mnt);
-+ if (err)
-+ return err;
++static loff_t fuse_file_llseek(struct file *file, loff_t offset, int origin)
++{
++ loff_t retval;
++ struct inode *inode = file->f_path.dentry->d_inode;
+
- 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;
++ mutex_lock(&inode->i_mutex);
++ switch (origin) {
++ case SEEK_END:
++ offset += i_size_read(inode);
++ break;
++ case SEEK_CUR:
++ offset += file->f_pos;
++ }
++ retval = -EINVAL;
++ if (offset >= 0 && offset <= inode->i_sb->s_maxbytes) {
++ if (offset != file->f_pos) {
++ file->f_pos = offset;
++ file->f_version = 0;
++ }
++ retval = offset;
++ }
++ mutex_unlock(&inode->i_mutex);
++ return retval;
++}
++
+ static const struct file_operations fuse_file_operations = {
+- .llseek = generic_file_llseek,
++ .llseek = fuse_file_llseek,
+ .read = do_sync_read,
+ .aio_read = fuse_file_aio_read,
+ .write = do_sync_write,
+- .aio_write = generic_file_aio_write,
++ .aio_write = fuse_file_aio_write,
+ .mmap = fuse_file_mmap,
+ .open = fuse_open,
+ .flush = fuse_flush,
+@@ -926,7 +1473,7 @@ static const struct file_operations fuse_file_operations = {
+ };
+
+ static const struct file_operations fuse_direct_io_file_operations = {
+- .llseek = generic_file_llseek,
++ .llseek = fuse_file_llseek,
+ .read = fuse_direct_read,
+ .write = fuse_direct_write,
+ .open = fuse_open,
+@@ -940,10 +1487,12 @@ static const struct file_operations fuse_direct_io_file_operations = {
+
+ static const struct address_space_operations fuse_file_aops = {
+ .readpage = fuse_readpage,
++ .writepage = fuse_writepage,
++ .launder_page = fuse_launder_page,
+ .write_begin = fuse_write_begin,
+ .write_end = fuse_write_end,
+ .readpages = fuse_readpages,
+- .set_page_dirty = fuse_set_page_dirty,
++ .set_page_dirty = __set_page_dirty_nobuffers,
+ .bmap = fuse_bmap,
+ };
+
+diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
+index 67aaf6e..dadffa2 100644
+--- a/fs/fuse/fuse_i.h
++++ b/fs/fuse/fuse_i.h
+@@ -15,6 +15,7 @@
+ #include <linux/mm.h>
+ #include <linux/backing-dev.h>
+ #include <linux/mutex.h>
++#include <linux/rwsem.h>
-- if (IS_RDONLY(inode))
-- return -EROFS;
--
- if (get_user(n_blocks_count, (__u32 __user *)arg))
- return -EFAULT;
+ /** Max number of pages that can be used in a single read request */
+ #define FUSE_MAX_PAGES_PER_REQ 32
+@@ -25,6 +26,9 @@
+ /** Congestion starts at 75% of maximum */
+ #define FUSE_CONGESTION_THRESHOLD (FUSE_MAX_BACKGROUND * 75 / 100)
-+ err = mnt_want_write(filp->f_path.mnt);
-+ if (err)
-+ return err;
++/** Bias for fi->writectr, meaning new writepages must not be sent */
++#define FUSE_NOWRITE INT_MIN
+
- 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;
+ /** It could be as large as PATH_MAX, but would that have any uses? */
+ #define FUSE_NAME_MAX 1024
-- if (IS_RDONLY(inode))
-- return -EROFS;
--
- if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg,
- sizeof(input)))
- return -EFAULT;
+@@ -73,6 +77,19 @@ struct fuse_inode {
-+ err = mnt_want_write(filp->f_path.mnt);
-+ if (err)
-+ return err;
+ /** Files usable in writepage. Protected by fc->lock */
+ struct list_head write_files;
+
- 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 @@
++ /** Writepages pending on truncate or fsync */
++ struct list_head queued_writes;
++
++ /** Number of sent writes, a negative bias (FUSE_NOWRITE)
++ * means more writes are blocked */
++ int writectr;
++
++ /** Waitq for writepage completion */
++ wait_queue_head_t page_waitq;
++
++ /** List of writepage requestst (pending or sent) */
++ struct list_head writepages;
+ };
- #include <linux/capability.h>
- #include <linux/module.h>
-+#include <linux/mount.h>
- #include <linux/time.h>
- #include <linux/msdos_fs.h>
- #include <linux/smp_lock.h>
-@@ -46,10 +47,9 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
+ /** FUSE specific file data */
+@@ -222,7 +239,10 @@ struct fuse_req {
+ } release;
+ struct fuse_init_in init_in;
+ struct fuse_init_out init_out;
+- struct fuse_read_in read_in;
++ struct {
++ struct fuse_read_in in;
++ u64 attr_ver;
++ } read;
+ struct {
+ struct fuse_write_in in;
+ struct fuse_write_out out;
+@@ -242,6 +262,12 @@ struct fuse_req {
+ /** File used in the request (or NULL) */
+ struct fuse_file *ff;
- mutex_lock(&inode->i_mutex);
++ /** Inode used in the request or NULL */
++ struct inode *inode;
++
++ /** Link on fi->writepages */
++ struct list_head writepages_entry;
++
+ /** Request completion callback */
+ void (*end)(struct fuse_conn *, struct fuse_req *);
-- if (IS_RDONLY(inode)) {
-- err = -EROFS;
-- goto up;
-- }
-+ err = mnt_want_write(filp->f_path.mnt);
-+ if (err)
-+ goto up_no_drop_write;
+@@ -390,8 +416,8 @@ struct fuse_conn {
+ /** Entry on the fuse_conn_list */
+ struct list_head entry;
- /*
- * ATTR_VOLUME and ATTR_DIR cannot be changed; this also
-@@ -105,7 +105,9 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
+- /** Unique ID */
+- u64 id;
++ /** Device ID from super block */
++ dev_t dev;
- 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.
+ /** Dentries in the control filesystem */
+ struct dentry *ctl_dentry[FUSE_CTL_NUM_DENTRIES];
+@@ -438,7 +464,7 @@ extern const struct file_operations fuse_dev_operations;
+ /**
+ * Get a filled in inode
*/
+-struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
++struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
+ int generation, struct fuse_attr *attr,
+ u64 attr_valid, u64 attr_version);
+
+@@ -446,7 +472,7 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
+ * Send FORGET command
+ */
+ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
+- unsigned long nodeid, u64 nlookup);
++ u64 nodeid, u64 nlookup);
--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;
+ /**
+ * Initialize READ or READDIR request
+@@ -504,6 +530,11 @@ void fuse_init_symlink(struct inode *inode);
+ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
+ u64 attr_valid, u64 attr_version);
-+ spin_lock(&files->file_lock);
++void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
++ u64 attr_valid);
+
- error = -EINVAL;
- if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
- goto out;
-@@ -97,42 +99,28 @@ repeat:
- if (error)
- goto repeat;
++void fuse_truncate(struct address_space *mapping, loff_t offset);
++
+ /**
+ * Initialize the client device
+ */
+@@ -522,6 +553,8 @@ void fuse_ctl_cleanup(void);
+ */
+ struct fuse_req *fuse_request_alloc(void);
-- /*
-- * 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;
++struct fuse_req *fuse_request_alloc_nofs(void);
++
+ /**
+ * Free a request
+ */
+@@ -558,6 +591,8 @@ void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req);
+ */
+ void request_send_background(struct fuse_conn *fc, struct fuse_req *req);
-+ 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;
--
++void request_send_background_locked(struct fuse_conn *fc, struct fuse_req *req);
+
- out:
-+ spin_unlock(&files->file_lock);
- return error;
- }
+ /* Abort all requests */
+ void fuse_abort_conn(struct fuse_conn *fc);
- 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);
-- }
+@@ -600,3 +635,10 @@ u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id);
- 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);
+ int fuse_update_attributes(struct inode *inode, struct kstat *stat,
+ struct file *file, bool *refreshed);
++
++void fuse_flush_writepages(struct inode *inode);
++
++void fuse_set_nowrite(struct inode *inode);
++void fuse_release_nowrite(struct inode *inode);
++
++u64 fuse_get_attr_version(struct fuse_conn *fc);
+diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
+index 033f7bd..79b6158 100644
+--- a/fs/fuse/inode.c
++++ b/fs/fuse/inode.c
+@@ -59,7 +59,11 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
+ fi->nodeid = 0;
+ fi->nlookup = 0;
+ fi->attr_version = 0;
++ fi->writectr = 0;
+ INIT_LIST_HEAD(&fi->write_files);
++ INIT_LIST_HEAD(&fi->queued_writes);
++ INIT_LIST_HEAD(&fi->writepages);
++ init_waitqueue_head(&fi->page_waitq);
+ fi->forget_req = fuse_request_alloc();
+ if (!fi->forget_req) {
+ kmem_cache_free(fuse_inode_cachep, inode);
+@@ -73,13 +77,14 @@ static void fuse_destroy_inode(struct inode *inode)
+ {
+ struct fuse_inode *fi = get_fuse_inode(inode);
+ BUG_ON(!list_empty(&fi->write_files));
++ BUG_ON(!list_empty(&fi->queued_writes));
+ if (fi->forget_req)
+ fuse_request_free(fi->forget_req);
+ kmem_cache_free(fuse_inode_cachep, inode);
+ }
+
+ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
+- unsigned long nodeid, u64 nlookup)
++ u64 nodeid, u64 nlookup)
+ {
+ struct fuse_forget_in *inarg = &req->misc.forget_in;
+ inarg->nlookup = nlookup;
+@@ -109,7 +114,7 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data)
+ return 0;
}
-@@ -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;
+-static void fuse_truncate(struct address_space *mapping, loff_t offset)
++void fuse_truncate(struct address_space *mapping, loff_t offset)
+ {
+ /* See vmtruncate() */
+ unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
+@@ -117,19 +122,12 @@ static void fuse_truncate(struct address_space *mapping, loff_t offset)
+ unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
}
- EXPORT_SYMBOL(init_file);
-@@ -211,6 +224,31 @@ void fput(struct file *file)
- EXPORT_SYMBOL(fput);
+-
+-void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
+- u64 attr_valid, u64 attr_version)
++void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
++ u64 attr_valid)
+ {
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_inode *fi = get_fuse_inode(inode);
+- loff_t oldsize;
+
+- spin_lock(&fc->lock);
+- if (attr_version != 0 && fi->attr_version > attr_version) {
+- spin_unlock(&fc->lock);
+- return;
+- }
+ fi->attr_version = ++fc->attr_version;
+ fi->i_time = attr_valid;
-+/**
-+ * 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;
+@@ -159,6 +157,22 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
+ fi->orig_i_mode = inode->i_mode;
+ if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
+ inode->i_mode &= ~S_ISVTX;
++}
+
-+ put_write_access(inode);
++void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
++ u64 attr_valid, u64 attr_version)
++{
++ struct fuse_conn *fc = get_fuse_conn(inode);
++ struct fuse_inode *fi = get_fuse_inode(inode);
++ loff_t oldsize;
+
-+ if (special_file(inode->i_mode))
-+ return;
-+ if (file_check_writeable(file) != 0)
++ spin_lock(&fc->lock);
++ if (attr_version != 0 && fi->attr_version > attr_version) {
++ spin_unlock(&fc->lock);
+ 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,
++ fuse_change_attributes_common(inode, attr, attr_valid);
+
+ oldsize = inode->i_size;
+ i_size_write(inode, attr->size);
+@@ -193,7 +207,7 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
+
+ static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
+ {
+- unsigned long nodeid = *(unsigned long *) _nodeidp;
++ u64 nodeid = *(u64 *) _nodeidp;
+ if (get_node_id(inode) == nodeid)
+ return 1;
+ else
+@@ -202,12 +216,12 @@ static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
+
+ static int fuse_inode_set(struct inode *inode, void *_nodeidp)
+ {
+- unsigned long nodeid = *(unsigned long *) _nodeidp;
++ u64 nodeid = *(u64 *) _nodeidp;
+ get_fuse_inode(inode)->nodeid = nodeid;
+ return 0;
+ }
+
+-struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
++struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
+ int generation, struct fuse_attr *attr,
+ u64 attr_valid, u64 attr_version)
+ {
+@@ -242,10 +256,9 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
return inode;
}
@@ -732605,6 +981762,109 @@
}
static void fuse_send_destroy(struct fuse_conn *fc)
+@@ -448,7 +461,7 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
+ return 0;
+ }
+
+-static struct fuse_conn *new_conn(void)
++static struct fuse_conn *new_conn(struct super_block *sb)
+ {
+ struct fuse_conn *fc;
+ int err;
+@@ -469,19 +482,41 @@ static struct fuse_conn *new_conn(void)
+ atomic_set(&fc->num_waiting, 0);
+ fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
+ fc->bdi.unplug_io_fn = default_unplug_io_fn;
++ /* fuse does it's own writeback accounting */
++ fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB;
++ fc->dev = sb->s_dev;
+ err = bdi_init(&fc->bdi);
+- if (err) {
+- kfree(fc);
+- fc = NULL;
+- goto out;
+- }
++ if (err)
++ goto error_kfree;
++ err = bdi_register_dev(&fc->bdi, fc->dev);
++ if (err)
++ goto error_bdi_destroy;
++ /*
++ * For a single fuse filesystem use max 1% of dirty +
++ * writeback threshold.
++ *
++ * This gives about 1M of write buffer for memory maps on a
++ * machine with 1G and 10% dirty_ratio, which should be more
++ * than enough.
++ *
++ * Privileged users can raise it by writing to
++ *
++ * /sys/class/bdi/<bdi>/max_ratio
++ */
++ bdi_set_max_ratio(&fc->bdi, 1);
+ fc->reqctr = 0;
+ fc->blocked = 1;
+ fc->attr_version = 1;
+ get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
+ }
+-out:
+ return fc;
++
++error_bdi_destroy:
++ bdi_destroy(&fc->bdi);
++error_kfree:
++ mutex_destroy(&fc->inst_mutex);
++ kfree(fc);
++ return NULL;
+ }
+
+ void fuse_conn_put(struct fuse_conn *fc)
+@@ -549,6 +584,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
+ fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages);
+ fc->minor = arg->minor;
+ fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
++ fc->max_write = min_t(unsigned, 4096, fc->max_write);
+ fc->conn_init = 1;
+ }
+ fuse_put_request(fc, req);
+@@ -579,12 +615,6 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
+ request_send_background(fc, req);
+ }
+
+-static u64 conn_id(void)
+-{
+- static u64 ctr = 1;
+- return ctr++;
+-}
+-
+ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
+ {
+ struct fuse_conn *fc;
+@@ -622,14 +652,14 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
+ if (file->f_op != &fuse_dev_operations)
+ return -EINVAL;
+
+- fc = new_conn();
++ fc = new_conn(sb);
+ if (!fc)
+ return -ENOMEM;
+
+ fc->flags = d.flags;
+ fc->user_id = d.user_id;
+ fc->group_id = d.group_id;
+- fc->max_read = d.max_read;
++ fc->max_read = min_t(unsigned, 4096, d.max_read);
+
+ /* Used by get_root_inode() */
+ sb->s_fs_info = fc;
+@@ -660,7 +690,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
+ if (file->private_data)
+ goto err_unlock;
+
+- fc->id = conn_id();
+ err = fuse_ctl_add_conn(fc);
+ if (err)
+ goto err_unlock;
diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig
index de8e64c..7f7947e 100644
--- a/fs/gfs2/Kconfig
@@ -735734,7 +984994,7 @@
-}
-
diff --git a/fs/gfs2/locking/dlm/sysfs.c b/fs/gfs2/locking/dlm/sysfs.c
-index a87b098..8479da4 100644
+index a87b098..a4ff271 100644
--- a/fs/gfs2/locking/dlm/sysfs.c
+++ b/fs/gfs2/locking/dlm/sysfs.c
@@ -12,8 +12,6 @@
@@ -735746,6 +985006,15 @@
static ssize_t proto_name_show(struct gdlm_ls *ls, char *buf)
{
return sprintf(buf, "%s\n", gdlm_ops.lm_proto_name);
+@@ -214,7 +212,7 @@ int gdlm_sysfs_init(void)
+ {
+ gdlm_kset = kset_create_and_add("lock_dlm", NULL, kernel_kobj);
+ if (!gdlm_kset) {
+- printk(KERN_WARNING "%s: can not create kset\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: can not create kset\n", __func__);
+ return -ENOMEM;
+ }
+ return 0;
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
@@ -735943,7 +985212,7 @@
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
+index ac772b6..f55394e 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -1,6 +1,6 @@
@@ -735983,6 +985252,15 @@
if (ret < 0)
return ret;
+@@ -441,7 +438,7 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
+ int error;
+
+ /*
+- * Due to the order of unstuffing files and ->nopage(), we can be
++ * Due to the order of unstuffing files and ->fault(), we can be
+ * asked for a zero page in the case of a stuffed file being extended,
+ * so we need to supply one here. It doesn't happen often.
+ */
@@ -510,23 +507,26 @@ static int __gfs2_readpage(void *file, struct page *page)
static int gfs2_readpage(struct file *file, struct page *page)
{
@@ -737540,10 +986818,85 @@
* 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
+index 28938a4..7f48576 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__);
+@@ -41,7 +41,7 @@ int gfs2_assert_withdraw_i(struct gfs2_sbd *sdp, char *assertion,
+
+ #define gfs2_assert_withdraw(sdp, assertion) \
+ ((likely(assertion)) ? 0 : gfs2_assert_withdraw_i((sdp), #assertion, \
+- __FUNCTION__, __FILE__, __LINE__))
++ __func__, __FILE__, __LINE__))
+
+
+ int gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion,
+@@ -49,28 +49,28 @@ int gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion,
+
+ #define gfs2_assert_warn(sdp, assertion) \
+ ((likely(assertion)) ? 0 : gfs2_assert_warn_i((sdp), #assertion, \
+- __FUNCTION__, __FILE__, __LINE__))
++ __func__, __FILE__, __LINE__))
+
+
+ int gfs2_consist_i(struct gfs2_sbd *sdp, int cluster_wide,
+ const char *function, char *file, unsigned int line);
+
+ #define gfs2_consist(sdp) \
+-gfs2_consist_i((sdp), 0, __FUNCTION__, __FILE__, __LINE__)
++gfs2_consist_i((sdp), 0, __func__, __FILE__, __LINE__)
+
+
+ int gfs2_consist_inode_i(struct gfs2_inode *ip, int cluster_wide,
+ const char *function, char *file, unsigned int line);
+
+ #define gfs2_consist_inode(ip) \
+-gfs2_consist_inode_i((ip), 0, __FUNCTION__, __FILE__, __LINE__)
++gfs2_consist_inode_i((ip), 0, __func__, __FILE__, __LINE__)
+
+
+ int gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd, int cluster_wide,
+ const char *function, char *file, unsigned int line);
+
+ #define gfs2_consist_rgrpd(rgd) \
+-gfs2_consist_rgrpd_i((rgd), 0, __FUNCTION__, __FILE__, __LINE__)
++gfs2_consist_rgrpd_i((rgd), 0, __func__, __FILE__, __LINE__)
+
+
+ int gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
+@@ -91,7 +91,7 @@ static inline int gfs2_meta_check_i(struct gfs2_sbd *sdp,
+ }
+
+ #define gfs2_meta_check(sdp, bh) \
+-gfs2_meta_check_i((sdp), (bh), __FUNCTION__, __FILE__, __LINE__)
++gfs2_meta_check_i((sdp), (bh), __func__, __FILE__, __LINE__)
+
+
+ int gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
+@@ -118,7 +118,7 @@ static inline int gfs2_metatype_check_i(struct gfs2_sbd *sdp,
+ }
+
+ #define gfs2_metatype_check(sdp, bh, type) \
+-gfs2_metatype_check_i((sdp), (bh), (type), __FUNCTION__, __FILE__, __LINE__)
++gfs2_metatype_check_i((sdp), (bh), (type), __func__, __FILE__, __LINE__)
+
+ static inline void gfs2_metatype_set(struct buffer_head *bh, u16 type,
+ u16 format)
+@@ -134,19 +134,20 @@ int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function,
+ char *file, unsigned int line);
+
+ #define gfs2_io_error(sdp) \
+-gfs2_io_error_i((sdp), __FUNCTION__, __FILE__, __LINE__);
++gfs2_io_error_i((sdp), __func__, __FILE__, __LINE__);
+
+
+ int gfs2_io_error_bh_i(struct gfs2_sbd *sdp, struct buffer_head *bh,
+ const char *function, char *file, unsigned int line);
+
+ #define gfs2_io_error_bh(sdp, bh) \
+-gfs2_io_error_bh_i((sdp), (bh), __FUNCTION__, __FILE__, __LINE__);
++gfs2_io_error_bh_i((sdp), (bh), __func__, __FILE__, __LINE__);
+
+
extern struct kmem_cache *gfs2_glock_cachep;
extern struct kmem_cache *gfs2_inode_cachep;
extern struct kmem_cache *gfs2_bufdata_cachep;
@@ -737559,6 +986912,142 @@
#endif /* __UTIL_DOT_H__ */
+diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
+index 24cf6fc..f6621a7 100644
+--- a/fs/hfs/btree.c
++++ b/fs/hfs/btree.c
+@@ -208,7 +208,9 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
+ struct hfs_bnode *node, *next_node;
+ struct page **pagep;
+ u32 nidx, idx;
+- u16 off, len;
++ unsigned off;
++ u16 off16;
++ u16 len;
+ u8 *data, byte, m;
+ int i;
+
+@@ -235,7 +237,8 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
+ node = hfs_bnode_find(tree, nidx);
+ if (IS_ERR(node))
+ return node;
+- len = hfs_brec_lenoff(node, 2, &off);
++ len = hfs_brec_lenoff(node, 2, &off16);
++ off = off16;
+
+ off += node->page_offset;
+ pagep = node->page + (off >> PAGE_CACHE_SHIFT);
+@@ -280,7 +283,8 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
+ return next_node;
+ node = next_node;
+
+- len = hfs_brec_lenoff(node, 0, &off);
++ len = hfs_brec_lenoff(node, 0, &off16);
++ off = off16;
+ off += node->page_offset;
+ pagep = node->page + (off >> PAGE_CACHE_SHIFT);
+ data = kmap(*pagep);
+diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c
+index b4651e1..36ca2e1 100644
+--- a/fs/hfs/mdb.c
++++ b/fs/hfs/mdb.c
+@@ -215,7 +215,7 @@ int hfs_mdb_get(struct super_block *sb)
+ attrib &= cpu_to_be16(~HFS_SB_ATTRIB_UNMNT);
+ attrib |= cpu_to_be16(HFS_SB_ATTRIB_INCNSTNT);
+ mdb->drAtrb = attrib;
+- mdb->drWrCnt = cpu_to_be32(be32_to_cpu(mdb->drWrCnt) + 1);
++ be32_add_cpu(&mdb->drWrCnt, 1);
+ mdb->drLsMod = hfs_mtime();
+
+ mark_buffer_dirty(HFS_SB(sb)->mdb_bh);
+diff --git a/fs/hfs/super.c b/fs/hfs/super.c
+index 32de44e..8cf6797 100644
+--- a/fs/hfs/super.c
++++ b/fs/hfs/super.c
+@@ -297,7 +297,8 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
+ return 0;
+ }
+ p = match_strdup(&args[0]);
+- hsb->nls_disk = load_nls(p);
++ if (p)
++ hsb->nls_disk = load_nls(p);
+ if (!hsb->nls_disk) {
+ printk(KERN_ERR "hfs: unable to load codepage \"%s\"\n", p);
+ kfree(p);
+@@ -311,7 +312,8 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
+ return 0;
+ }
+ p = match_strdup(&args[0]);
+- hsb->nls_io = load_nls(p);
++ if (p)
++ hsb->nls_io = load_nls(p);
+ if (!hsb->nls_io) {
+ printk(KERN_ERR "hfs: unable to load iocharset \"%s\"\n", p);
+ kfree(p);
+diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
+index bb54336..e49fcee 100644
+--- a/fs/hfsplus/btree.c
++++ b/fs/hfsplus/btree.c
+@@ -184,7 +184,9 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
+ struct hfs_bnode *node, *next_node;
+ struct page **pagep;
+ u32 nidx, idx;
+- u16 off, len;
++ unsigned off;
++ u16 off16;
++ u16 len;
+ u8 *data, byte, m;
+ int i;
+
+@@ -211,7 +213,8 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
+ node = hfs_bnode_find(tree, nidx);
+ if (IS_ERR(node))
+ return node;
+- len = hfs_brec_lenoff(node, 2, &off);
++ len = hfs_brec_lenoff(node, 2, &off16);
++ off = off16;
+
+ off += node->page_offset;
+ pagep = node->page + (off >> PAGE_CACHE_SHIFT);
+@@ -256,7 +259,8 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
+ return next_node;
+ node = next_node;
+
+- len = hfs_brec_lenoff(node, 0, &off);
++ len = hfs_brec_lenoff(node, 0, &off16);
++ off = off16;
+ off += node->page_offset;
+ pagep = node->page + (off >> PAGE_CACHE_SHIFT);
+ data = kmap(*pagep);
+diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
+index d72d0a8..9e59537 100644
+--- a/fs/hfsplus/hfsplus_fs.h
++++ b/fs/hfsplus/hfsplus_fs.h
+@@ -311,6 +311,10 @@ int hfsplus_delete_cat(u32, struct inode *, struct qstr *);
+ int hfsplus_rename_cat(u32, struct inode *, struct qstr *,
+ struct inode *, struct qstr *);
+
++/* dir.c */
++extern const struct inode_operations hfsplus_dir_inode_operations;
++extern const struct file_operations hfsplus_dir_operations;
++
+ /* extents.c */
+ int hfsplus_ext_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
+ void hfsplus_ext_write_extent(struct inode *);
+diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
+index 37744cf..d53b2af 100644
+--- a/fs/hfsplus/inode.c
++++ b/fs/hfsplus/inode.c
+@@ -278,9 +278,6 @@ static int hfsplus_file_release(struct inode *inode, struct file *file)
+ return 0;
+ }
+
+-extern const struct inode_operations hfsplus_dir_inode_operations;
+-extern struct file_operations hfsplus_dir_operations;
+-
+ static const struct inode_operations hfsplus_file_inode_operations = {
+ .lookup = hfsplus_file_lookup,
+ .truncate = hfsplus_file_truncate,
diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
index b60c0af..f457d2c 100644
--- a/fs/hfsplus/ioctl.c
@@ -737629,11 +987118,102 @@
}
default:
return -ENOTTY;
+diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c
+index dc64fac..9997cbf 100644
+--- a/fs/hfsplus/options.c
++++ b/fs/hfsplus/options.c
+@@ -132,7 +132,8 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi)
+ return 0;
+ }
+ p = match_strdup(&args[0]);
+- sbi->nls = load_nls(p);
++ if (p)
++ sbi->nls = load_nls(p);
+ if (!sbi->nls) {
+ printk(KERN_ERR "hfs: unable to load nls mapping \"%s\"\n", p);
+ kfree(p);
+diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
+index b0f9ad3..ce97a54 100644
+--- a/fs/hfsplus/super.c
++++ b/fs/hfsplus/super.c
+@@ -357,7 +357,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
+ printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only.\n");
+ sb->s_flags |= MS_RDONLY;
+ } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) {
+- printk(KERN_WARNING "hfs: write access to a jounaled filesystem is not supported, "
++ printk(KERN_WARNING "hfs: write access to a journaled filesystem is not supported, "
+ "use the force option at your own risk, mounting read-only.\n");
+ sb->s_flags |= MS_RDONLY;
+ }
+@@ -423,7 +423,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
+ */
+ vhdr->last_mount_vers = cpu_to_be32(HFSP_MOUNT_VERSION);
+ vhdr->modify_date = hfsp_now2mt();
+- vhdr->write_count = cpu_to_be32(be32_to_cpu(vhdr->write_count) + 1);
++ be32_add_cpu(&vhdr->write_count, 1);
+ vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT);
+ vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT);
+ mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh);
+diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
+index 72cab78..175d08e 100644
+--- a/fs/hfsplus/wrapper.c
++++ b/fs/hfsplus/wrapper.c
+@@ -47,7 +47,7 @@ static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd)
+ return 0;
+ wd->ablk_start = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ABLKSTART));
+
+- extent = be32_to_cpu(get_unaligned((__be32 *)(bufptr + HFSP_WRAPOFF_EMBEDEXT)));
++ extent = get_unaligned_be32(bufptr + HFSP_WRAPOFF_EMBEDEXT);
+ wd->embed_start = (extent >> 16) & 0xFFFF;
+ wd->embed_count = extent & 0xFFFF;
+
+diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
+index 6846785..aeabf80 100644
+--- a/fs/hugetlbfs/inode.c
++++ b/fs/hugetlbfs/inode.c
+@@ -45,7 +45,7 @@ static const struct inode_operations hugetlbfs_inode_operations;
+
+ static struct backing_dev_info hugetlbfs_backing_dev_info = {
+ .ra_pages = 0, /* No readahead */
+- .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
++ .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK,
+ };
+
+ int sysctl_hugetlb_shm_group;
+@@ -504,7 +504,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid,
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ INIT_LIST_HEAD(&inode->i_mapping->private_list);
+ info = HUGETLBFS_I(inode);
+- mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, NULL);
++ mpol_shared_policy_init(&info->policy, NULL);
+ switch (mode & S_IFMT) {
+ default:
+ init_special_inode(inode, mode, dev);
diff --git a/fs/inode.c b/fs/inode.c
-index 53245ff..27ee1af 100644
+index 53245ff..bf64781 100644
--- a/fs/inode.c
+++ b/fs/inode.c
-@@ -1199,42 +1199,37 @@ void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
+@@ -495,8 +495,7 @@ static struct inode * find_inode(struct super_block * sb, struct hlist_head *hea
+ struct inode * inode = NULL;
+
+ repeat:
+- hlist_for_each (node, head) {
+- inode = hlist_entry(node, struct inode, i_hash);
++ hlist_for_each_entry(inode, node, head, i_hash) {
+ if (inode->i_sb != sb)
+ continue;
+ if (!test(inode, data))
+@@ -520,8 +519,7 @@ static struct inode * find_inode_fast(struct super_block * sb, struct hlist_head
+ struct inode * inode = NULL;
+
+ repeat:
+- hlist_for_each (node, head) {
+- inode = hlist_entry(node, struct inode, i_hash);
++ hlist_for_each_entry(inode, node, head, i_hash) {
+ if (inode->i_ino != ino)
+ continue;
+ if (inode->i_sb != sb)
+@@ -1199,42 +1197,37 @@ void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
struct inode *inode = dentry->d_inode;
struct timespec now;
@@ -737696,7 +987276,7 @@
}
EXPORT_SYMBOL(touch_atime);
-@@ -1255,10 +1250,13 @@ void file_update_time(struct file *file)
+@@ -1255,10 +1248,13 @@ void file_update_time(struct file *file)
struct inode *inode = file->f_path.dentry->d_inode;
struct timespec now;
int sync_it = 0;
@@ -737711,7 +987291,7 @@
return;
now = current_fs_time(inode->i_sb);
-@@ -1279,6 +1277,7 @@ void file_update_time(struct file *file)
+@@ -1279,6 +1275,7 @@ void file_update_time(struct file *file)
if (sync_it)
mark_inode_dirty_sync(inode);
@@ -737719,6 +987299,19 @@
}
EXPORT_SYMBOL(file_update_time);
+diff --git a/fs/inotify_user.c b/fs/inotify_user.c
+index 7b94a1e..6676c06 100644
+--- a/fs/inotify_user.c
++++ b/fs/inotify_user.c
+@@ -598,7 +598,7 @@ asmlinkage long sys_inotify_init(void)
+ }
+
+ ih = inotify_init(&inotify_user_ops);
+- if (unlikely(IS_ERR(ih))) {
++ if (IS_ERR(ih)) {
+ ret = PTR_ERR(ih);
+ goto out_free_dev;
+ }
diff --git a/fs/internal.h b/fs/internal.h
index 392e8cc..80aa9a0 100644
--- a/fs/internal.h
@@ -737738,6 +987331,873 @@
+extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
+
+extern void __init mnt_init(void);
+diff --git a/fs/ioctl.c b/fs/ioctl.c
+index f32fbde..7db32b3 100644
+--- a/fs/ioctl.c
++++ b/fs/ioctl.c
+@@ -28,8 +28,8 @@
+ *
+ * Returns 0 on success, -errno on error.
+ */
+-long vfs_ioctl(struct file *filp, unsigned int cmd,
+- unsigned long arg)
++static long vfs_ioctl(struct file *filp, unsigned int cmd,
++ unsigned long arg)
+ {
+ int error = -ENOTTY;
+
+diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
+index 1ba407c..2f0dc5a 100644
+--- a/fs/isofs/dir.c
++++ b/fs/isofs/dir.c
+@@ -145,6 +145,14 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
+ }
+ de = tmpde;
+ }
++ /* Basic sanity check, whether name doesn't exceed dir entry */
++ if (de_len < de->name_len[0] +
++ sizeof(struct iso_directory_record)) {
++ printk(KERN_NOTICE "iso9660: Corrupted directory entry"
++ " in block %lu of inode %lu\n", block,
++ inode->i_ino);
++ return -EIO;
++ }
+
+ if (first_de) {
+ isofs_normalize_block_and_offset(de,
+diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
+index d1bdf8a..ccbf72f 100644
+--- a/fs/isofs/isofs.h
++++ b/fs/isofs/isofs.h
+@@ -78,29 +78,29 @@ static inline int isonum_712(char *p)
+ }
+ static inline unsigned int isonum_721(char *p)
+ {
+- return le16_to_cpu(get_unaligned((__le16 *)p));
++ return get_unaligned_le16(p);
+ }
+ static inline unsigned int isonum_722(char *p)
+ {
+- return be16_to_cpu(get_unaligned((__le16 *)p));
++ return get_unaligned_be16(p);
+ }
+ static inline unsigned int isonum_723(char *p)
+ {
+ /* Ignore bigendian datum due to broken mastering programs */
+- return le16_to_cpu(get_unaligned((__le16 *)p));
++ return get_unaligned_le16(p);
+ }
+ static inline unsigned int isonum_731(char *p)
+ {
+- return le32_to_cpu(get_unaligned((__le32 *)p));
++ return get_unaligned_le32(p);
+ }
+ static inline unsigned int isonum_732(char *p)
+ {
+- return be32_to_cpu(get_unaligned((__le32 *)p));
++ return get_unaligned_be32(p);
+ }
+ static inline unsigned int isonum_733(char *p)
+ {
+ /* Ignore bigendian datum due to broken mastering programs */
+- return le32_to_cpu(get_unaligned((__le32 *)p));
++ return get_unaligned_le32(p);
+ }
+ extern int iso_date(char *, int);
+
+diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
+index 344b247..8299889 100644
+--- a/fs/isofs/namei.c
++++ b/fs/isofs/namei.c
+@@ -111,6 +111,13 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
+
+ dlen = de->name_len[0];
+ dpnt = de->name;
++ /* Basic sanity check, whether name doesn't exceed dir entry */
++ if (de_len < dlen + sizeof(struct iso_directory_record)) {
++ printk(KERN_NOTICE "iso9660: Corrupted directory entry"
++ " in block %lu of inode %lu\n", block,
++ dir->i_ino);
++ return 0;
++ }
+
+ if (sbi->s_rock &&
+ ((i = get_rock_ridge_filename(de, tmpname, dir)))) {
+diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
+index a38c718..cd931ef 100644
+--- a/fs/jbd/commit.c
++++ b/fs/jbd/commit.c
+@@ -407,22 +407,6 @@ void journal_commit_transaction(journal_t *journal)
+ jbd_debug (3, "JBD: commit phase 2\n");
+
+ /*
+- * First, drop modified flag: all accesses to the buffers
+- * will be tracked for a new trasaction only -bzzz
+- */
+- spin_lock(&journal->j_list_lock);
+- if (commit_transaction->t_buffers) {
+- new_jh = jh = commit_transaction->t_buffers->b_tnext;
+- do {
+- J_ASSERT_JH(new_jh, new_jh->b_modified == 1 ||
+- new_jh->b_modified == 0);
+- new_jh->b_modified = 0;
+- new_jh = new_jh->b_tnext;
+- } while (new_jh != jh);
+- }
+- spin_unlock(&journal->j_list_lock);
+-
+- /*
+ * Now start flushing things to disk, in the order they appear
+ * on the transaction lists. Data blocks go first.
+ */
+@@ -488,6 +472,9 @@ void journal_commit_transaction(journal_t *journal)
+ */
+ commit_transaction->t_state = T_COMMIT;
+
++ J_ASSERT(commit_transaction->t_nr_buffers <=
++ commit_transaction->t_outstanding_credits);
++
+ descriptor = NULL;
+ bufs = 0;
+ while (commit_transaction->t_buffers) {
+diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
+index 0e081d5..b99c3b3 100644
+--- a/fs/jbd/journal.c
++++ b/fs/jbd/journal.c
+@@ -534,7 +534,7 @@ int log_wait_commit(journal_t *journal, tid_t tid)
+ if (!tid_geq(journal->j_commit_request, tid)) {
+ printk(KERN_EMERG
+ "%s: error: j_commit_request=%d, tid=%d\n",
+- __FUNCTION__, journal->j_commit_request, tid);
++ __func__, journal->j_commit_request, tid);
+ }
+ spin_unlock(&journal->j_state_lock);
+ #endif
+@@ -599,7 +599,7 @@ int journal_bmap(journal_t *journal, unsigned long blocknr,
+
+ printk(KERN_ALERT "%s: journal block not found "
+ "at offset %lu on %s\n",
+- __FUNCTION__,
++ __func__,
+ blocknr,
+ bdevname(journal->j_dev, b));
+ err = -EIO;
+@@ -728,7 +728,7 @@ journal_t * journal_init_dev(struct block_device *bdev,
+ journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
+ if (!journal->j_wbuf) {
+ printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
+- __FUNCTION__);
++ __func__);
+ kfree(journal);
+ journal = NULL;
+ goto out;
+@@ -782,7 +782,7 @@ journal_t * journal_init_inode (struct inode *inode)
+ journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
+ if (!journal->j_wbuf) {
+ printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
+- __FUNCTION__);
++ __func__);
+ kfree(journal);
+ return NULL;
+ }
+@@ -791,7 +791,7 @@ journal_t * journal_init_inode (struct inode *inode)
+ /* If that failed, give up */
+ if (err) {
+ printk(KERN_ERR "%s: Cannnot locate journal superblock\n",
+- __FUNCTION__);
++ __func__);
+ kfree(journal);
+ return NULL;
+ }
+@@ -877,7 +877,7 @@ int journal_create(journal_t *journal)
+ */
+ printk(KERN_EMERG
+ "%s: creation of journal on external device!\n",
+- __FUNCTION__);
++ __func__);
+ BUG();
+ }
+
+@@ -1657,7 +1657,7 @@ static struct journal_head *journal_alloc_journal_head(void)
+ jbd_debug(1, "out of memory for journal_head\n");
+ if (time_after(jiffies, last_warning + 5*HZ)) {
+ printk(KERN_NOTICE "ENOMEM in %s, retrying.\n",
+- __FUNCTION__);
++ __func__);
+ last_warning = jiffies;
+ }
+ while (ret == NULL) {
+@@ -1794,13 +1794,13 @@ static void __journal_remove_journal_head(struct buffer_head *bh)
+ if (jh->b_frozen_data) {
+ printk(KERN_WARNING "%s: freeing "
+ "b_frozen_data\n",
+- __FUNCTION__);
++ __func__);
+ jbd_free(jh->b_frozen_data, bh->b_size);
+ }
+ if (jh->b_committed_data) {
+ printk(KERN_WARNING "%s: freeing "
+ "b_committed_data\n",
+- __FUNCTION__);
++ __func__);
+ jbd_free(jh->b_committed_data, bh->b_size);
+ }
+ bh->b_private = NULL;
+diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c
+index d5f8eee..1bb43e9 100644
+--- a/fs/jbd/revoke.c
++++ b/fs/jbd/revoke.c
+@@ -138,7 +138,7 @@ repeat:
+ oom:
+ if (!journal_oom_retry)
+ return -ENOMEM;
+- jbd_debug(1, "ENOMEM in %s, retrying\n", __FUNCTION__);
++ jbd_debug(1, "ENOMEM in %s, retrying\n", __func__);
+ yield();
+ goto repeat;
+ }
+diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
+index 2c9e8f5..67ff202 100644
+--- a/fs/jbd/transaction.c
++++ b/fs/jbd/transaction.c
+@@ -609,6 +609,12 @@ repeat:
+ goto done;
+
+ /*
++ * this is the first time this transaction is touching this buffer,
++ * reset the modified flag
++ */
++ jh->b_modified = 0;
++
++ /*
+ * If there is already a copy-out version of this buffer, then we don't
+ * need to make another one
+ */
+@@ -681,7 +687,7 @@ repeat:
+ if (!frozen_buffer) {
+ printk(KERN_EMERG
+ "%s: OOM for frozen_buffer\n",
+- __FUNCTION__);
++ __func__);
+ JBUFFER_TRACE(jh, "oom!");
+ error = -ENOMEM;
+ jbd_lock_bh_state(bh);
+@@ -820,9 +826,16 @@ int journal_get_create_access(handle_t *handle, struct buffer_head *bh)
+
+ if (jh->b_transaction == NULL) {
+ jh->b_transaction = transaction;
++
++ /* first access by this transaction */
++ jh->b_modified = 0;
++
+ JBUFFER_TRACE(jh, "file as BJ_Reserved");
+ __journal_file_buffer(jh, transaction, BJ_Reserved);
+ } else if (jh->b_transaction == journal->j_committing_transaction) {
++ /* first access by this transaction */
++ jh->b_modified = 0;
++
+ JBUFFER_TRACE(jh, "set next transaction");
+ jh->b_next_transaction = transaction;
+ }
+@@ -891,7 +904,7 @@ repeat:
+ committed_data = jbd_alloc(jh2bh(jh)->b_size, GFP_NOFS);
+ if (!committed_data) {
+ printk(KERN_EMERG "%s: No memory for committed data\n",
+- __FUNCTION__);
++ __func__);
+ err = -ENOMEM;
+ goto out;
+ }
+@@ -1222,6 +1235,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
+ struct journal_head *jh;
+ int drop_reserve = 0;
+ int err = 0;
++ int was_modified = 0;
+
+ BUFFER_TRACE(bh, "entry");
+
+@@ -1240,6 +1254,9 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
+ goto not_jbd;
+ }
+
++ /* keep track of wether or not this transaction modified us */
++ was_modified = jh->b_modified;
++
+ /*
+ * The buffer's going from the transaction, we must drop
+ * all references -bzzz
+@@ -1257,7 +1274,12 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
+
+ JBUFFER_TRACE(jh, "belongs to current transaction: unfile");
+
+- drop_reserve = 1;
++ /*
++ * we only want to drop a reference if this transaction
++ * modified the buffer
++ */
++ if (was_modified)
++ drop_reserve = 1;
+
+ /*
+ * We are no longer going to journal this buffer.
+@@ -1297,7 +1319,13 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
+ if (jh->b_next_transaction) {
+ J_ASSERT(jh->b_next_transaction == transaction);
+ jh->b_next_transaction = NULL;
+- drop_reserve = 1;
++
++ /*
++ * only drop a reference if this transaction modified
++ * the buffer
++ */
++ if (was_modified)
++ drop_reserve = 1;
+ }
+ }
+
+@@ -2069,7 +2097,7 @@ void __journal_refile_buffer(struct journal_head *jh)
+ jh->b_transaction = jh->b_next_transaction;
+ jh->b_next_transaction = NULL;
+ __journal_file_buffer(jh, jh->b_transaction,
+- was_dirty ? BJ_Metadata : BJ_Reserved);
++ jh->b_modified ? BJ_Metadata : BJ_Reserved);
+ J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING);
+
+ if (was_dirty)
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index a817308..e013978 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -520,22 +520,6 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ jbd_debug (3, "JBD: commit phase 2\n");
+
+ /*
+- * First, drop modified flag: all accesses to the buffers
+- * will be tracked for a new trasaction only -bzzz
+- */
+- spin_lock(&journal->j_list_lock);
+- if (commit_transaction->t_buffers) {
+- new_jh = jh = commit_transaction->t_buffers->b_tnext;
+- do {
+- J_ASSERT_JH(new_jh, new_jh->b_modified == 1 ||
+- new_jh->b_modified == 0);
+- new_jh->b_modified = 0;
+- new_jh = new_jh->b_tnext;
+- } while (new_jh != jh);
+- }
+- spin_unlock(&journal->j_list_lock);
+-
+- /*
+ * Now start flushing things to disk, in the order they appear
+ * on the transaction lists. Data blocks go first.
+ */
+@@ -584,6 +568,9 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ stats.u.run.rs_blocks = commit_transaction->t_outstanding_credits;
+ stats.u.run.rs_blocks_logged = 0;
+
++ J_ASSERT(commit_transaction->t_nr_buffers <=
++ commit_transaction->t_outstanding_credits);
++
+ descriptor = NULL;
+ bufs = 0;
+ while (commit_transaction->t_buffers) {
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 954cff0..53632e3 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -534,7 +534,7 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
+ if (!tid_geq(journal->j_commit_request, tid)) {
+ printk(KERN_EMERG
+ "%s: error: j_commit_request=%d, tid=%d\n",
+- __FUNCTION__, journal->j_commit_request, tid);
++ __func__, journal->j_commit_request, tid);
+ }
+ spin_unlock(&journal->j_state_lock);
+ #endif
+@@ -599,7 +599,7 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr,
+
+ printk(KERN_ALERT "%s: journal block not found "
+ "at offset %lu on %s\n",
+- __FUNCTION__,
++ __func__,
+ blocknr,
+ bdevname(journal->j_dev, b));
+ err = -EIO;
+@@ -904,19 +904,10 @@ static void jbd2_stats_proc_init(journal_t *journal)
+ snprintf(name, sizeof(name) - 1, "%s", bdevname(journal->j_dev, name));
+ journal->j_proc_entry = proc_mkdir(name, proc_jbd2_stats);
+ if (journal->j_proc_entry) {
+- struct proc_dir_entry *p;
+- p = create_proc_entry("history", S_IRUGO,
+- journal->j_proc_entry);
+- if (p) {
+- p->proc_fops = &jbd2_seq_history_fops;
+- p->data = journal;
+- p = create_proc_entry("info", S_IRUGO,
+- journal->j_proc_entry);
+- if (p) {
+- p->proc_fops = &jbd2_seq_info_fops;
+- p->data = journal;
+- }
+- }
++ proc_create_data("history", S_IRUGO, journal->j_proc_entry,
++ &jbd2_seq_history_fops, journal);
++ proc_create_data("info", S_IRUGO, journal->j_proc_entry,
++ &jbd2_seq_info_fops, journal);
+ }
+ }
+
+@@ -1006,13 +997,14 @@ fail:
+ */
+
+ /**
+- * journal_t * jbd2_journal_init_dev() - creates an initialises a journal structure
++ * journal_t * jbd2_journal_init_dev() - creates and initialises a journal structure
+ * @bdev: Block device on which to create the journal
+ * @fs_dev: Device which hold journalled filesystem for this journal.
+ * @start: Block nr Start of journal.
+ * @len: Length of the journal in blocks.
+ * @blocksize: blocksize of journalling device
+- * @returns: a newly created journal_t *
++ *
++ * Returns: a newly created journal_t *
+ *
+ * jbd2_journal_init_dev creates a journal which maps a fixed contiguous
+ * range of blocks on an arbitrary block device.
+@@ -1036,7 +1028,7 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev,
+ journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
+ if (!journal->j_wbuf) {
+ printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
+- __FUNCTION__);
++ __func__);
+ kfree(journal);
+ journal = NULL;
+ goto out;
+@@ -1092,7 +1084,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode)
+ journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
+ if (!journal->j_wbuf) {
+ printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
+- __FUNCTION__);
++ __func__);
+ kfree(journal);
+ return NULL;
+ }
+@@ -1101,7 +1093,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode)
+ /* If that failed, give up */
+ if (err) {
+ printk(KERN_ERR "%s: Cannnot locate journal superblock\n",
+- __FUNCTION__);
++ __func__);
+ kfree(journal);
+ return NULL;
+ }
+@@ -1187,7 +1179,7 @@ int jbd2_journal_create(journal_t *journal)
+ */
+ printk(KERN_EMERG
+ "%s: creation of journal on external device!\n",
+- __FUNCTION__);
++ __func__);
+ BUG();
+ }
+
+@@ -1985,9 +1977,10 @@ static int journal_init_jbd2_journal_head_cache(void)
+
+ static void jbd2_journal_destroy_jbd2_journal_head_cache(void)
+ {
+- J_ASSERT(jbd2_journal_head_cache != NULL);
+- kmem_cache_destroy(jbd2_journal_head_cache);
+- jbd2_journal_head_cache = NULL;
++ if (jbd2_journal_head_cache) {
++ kmem_cache_destroy(jbd2_journal_head_cache);
++ jbd2_journal_head_cache = NULL;
++ }
+ }
+
+ /*
+@@ -2006,7 +1999,7 @@ static struct journal_head *journal_alloc_journal_head(void)
+ jbd_debug(1, "out of memory for journal_head\n");
+ if (time_after(jiffies, last_warning + 5*HZ)) {
+ printk(KERN_NOTICE "ENOMEM in %s, retrying.\n",
+- __FUNCTION__);
++ __func__);
+ last_warning = jiffies;
+ }
+ while (!ret) {
+@@ -2143,13 +2136,13 @@ static void __journal_remove_journal_head(struct buffer_head *bh)
+ if (jh->b_frozen_data) {
+ printk(KERN_WARNING "%s: freeing "
+ "b_frozen_data\n",
+- __FUNCTION__);
++ __func__);
+ jbd2_free(jh->b_frozen_data, bh->b_size);
+ }
+ if (jh->b_committed_data) {
+ printk(KERN_WARNING "%s: freeing "
+ "b_committed_data\n",
+- __FUNCTION__);
++ __func__);
+ jbd2_free(jh->b_committed_data, bh->b_size);
+ }
+ bh->b_private = NULL;
+@@ -2314,10 +2307,12 @@ static int __init journal_init(void)
+ BUILD_BUG_ON(sizeof(struct journal_superblock_s) != 1024);
+
+ ret = journal_init_caches();
+- if (ret != 0)
++ if (ret == 0) {
++ jbd2_create_debugfs_entry();
++ jbd2_create_jbd_stats_proc_entry();
++ } else {
+ jbd2_journal_destroy_caches();
+- jbd2_create_debugfs_entry();
+- jbd2_create_jbd_stats_proc_entry();
++ }
+ return ret;
+ }
+
+diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
+index 2e1453a..257ff26 100644
+--- a/fs/jbd2/revoke.c
++++ b/fs/jbd2/revoke.c
+@@ -139,7 +139,7 @@ repeat:
+ oom:
+ if (!journal_oom_retry)
+ return -ENOMEM;
+- jbd_debug(1, "ENOMEM in %s, retrying\n", __FUNCTION__);
++ jbd_debug(1, "ENOMEM in %s, retrying\n", __func__);
+ yield();
+ goto repeat;
+ }
+@@ -167,138 +167,121 @@ static struct jbd2_revoke_record_s *find_revoke_record(journal_t *journal,
+ return NULL;
+ }
+
++void jbd2_journal_destroy_revoke_caches(void)
++{
++ if (jbd2_revoke_record_cache) {
++ kmem_cache_destroy(jbd2_revoke_record_cache);
++ jbd2_revoke_record_cache = NULL;
++ }
++ if (jbd2_revoke_table_cache) {
++ kmem_cache_destroy(jbd2_revoke_table_cache);
++ jbd2_revoke_table_cache = NULL;
++ }
++}
++
+ int __init jbd2_journal_init_revoke_caches(void)
+ {
++ J_ASSERT(!jbd2_revoke_record_cache);
++ J_ASSERT(!jbd2_revoke_table_cache);
++
+ jbd2_revoke_record_cache = kmem_cache_create("jbd2_revoke_record",
+ sizeof(struct jbd2_revoke_record_s),
+ 0,
+ SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY,
+ NULL);
+ if (!jbd2_revoke_record_cache)
+- return -ENOMEM;
++ goto record_cache_failure;
+
+ jbd2_revoke_table_cache = kmem_cache_create("jbd2_revoke_table",
+ sizeof(struct jbd2_revoke_table_s),
+ 0, SLAB_TEMPORARY, NULL);
+- if (!jbd2_revoke_table_cache) {
+- kmem_cache_destroy(jbd2_revoke_record_cache);
+- jbd2_revoke_record_cache = NULL;
+- return -ENOMEM;
+- }
++ if (!jbd2_revoke_table_cache)
++ goto table_cache_failure;
+ return 0;
++table_cache_failure:
++ jbd2_journal_destroy_revoke_caches();
++record_cache_failure:
++ return -ENOMEM;
+ }
+
+-void jbd2_journal_destroy_revoke_caches(void)
++static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size)
+ {
+- kmem_cache_destroy(jbd2_revoke_record_cache);
+- jbd2_revoke_record_cache = NULL;
+- kmem_cache_destroy(jbd2_revoke_table_cache);
+- jbd2_revoke_table_cache = NULL;
+-}
+-
+-/* Initialise the revoke table for a given journal to a given size. */
+-
+-int jbd2_journal_init_revoke(journal_t *journal, int hash_size)
+-{
+- int shift, tmp;
++ int shift = 0;
++ int tmp = hash_size;
++ struct jbd2_revoke_table_s *table;
+
+- J_ASSERT (journal->j_revoke_table[0] == NULL);
++ table = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL);
++ if (!table)
++ goto out;
+
+- shift = 0;
+- tmp = hash_size;
+ while((tmp >>= 1UL) != 0UL)
+ shift++;
+
+- journal->j_revoke_table[0] = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL);
+- if (!journal->j_revoke_table[0])
+- return -ENOMEM;
+- journal->j_revoke = journal->j_revoke_table[0];
+-
+- /* Check that the hash_size is a power of two */
+- J_ASSERT(is_power_of_2(hash_size));
+-
+- journal->j_revoke->hash_size = hash_size;
+-
+- journal->j_revoke->hash_shift = shift;
+-
+- journal->j_revoke->hash_table =
++ table->hash_size = hash_size;
++ table->hash_shift = shift;
++ table->hash_table =
+ kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
+- if (!journal->j_revoke->hash_table) {
+- kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]);
+- journal->j_revoke = NULL;
+- return -ENOMEM;
++ if (!table->hash_table) {
++ kmem_cache_free(jbd2_revoke_table_cache, table);
++ table = NULL;
++ goto out;
+ }
+
+ for (tmp = 0; tmp < hash_size; tmp++)
+- INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
++ INIT_LIST_HEAD(&table->hash_table[tmp]);
+
+- journal->j_revoke_table[1] = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL);
+- if (!journal->j_revoke_table[1]) {
+- kfree(journal->j_revoke_table[0]->hash_table);
+- kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]);
+- return -ENOMEM;
++out:
++ return table;
++}
++
++static void jbd2_journal_destroy_revoke_table(struct jbd2_revoke_table_s *table)
++{
++ int i;
++ struct list_head *hash_list;
++
++ for (i = 0; i < table->hash_size; i++) {
++ hash_list = &table->hash_table[i];
++ J_ASSERT(list_empty(hash_list));
+ }
+
+- journal->j_revoke = journal->j_revoke_table[1];
++ kfree(table->hash_table);
++ kmem_cache_free(jbd2_revoke_table_cache, table);
++}
+
+- /* Check that the hash_size is a power of two */
++/* Initialise the revoke table for a given journal to a given size. */
++int jbd2_journal_init_revoke(journal_t *journal, int hash_size)
++{
++ J_ASSERT(journal->j_revoke_table[0] == NULL);
+ J_ASSERT(is_power_of_2(hash_size));
+
+- journal->j_revoke->hash_size = hash_size;
+-
+- journal->j_revoke->hash_shift = shift;
++ journal->j_revoke_table[0] = jbd2_journal_init_revoke_table(hash_size);
++ if (!journal->j_revoke_table[0])
++ goto fail0;
+
+- journal->j_revoke->hash_table =
+- kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
+- if (!journal->j_revoke->hash_table) {
+- kfree(journal->j_revoke_table[0]->hash_table);
+- kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]);
+- kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[1]);
+- journal->j_revoke = NULL;
+- return -ENOMEM;
+- }
++ journal->j_revoke_table[1] = jbd2_journal_init_revoke_table(hash_size);
++ if (!journal->j_revoke_table[1])
++ goto fail1;
+
+- for (tmp = 0; tmp < hash_size; tmp++)
+- INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
++ journal->j_revoke = journal->j_revoke_table[1];
+
+ spin_lock_init(&journal->j_revoke_lock);
+
+ return 0;
+-}
+
+-/* Destoy a journal's revoke table. The table must already be empty! */
++fail1:
++ jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]);
++fail0:
++ return -ENOMEM;
++}
+
++/* Destroy a journal's revoke table. The table must already be empty! */
+ void jbd2_journal_destroy_revoke(journal_t *journal)
+ {
+- struct jbd2_revoke_table_s *table;
+- struct list_head *hash_list;
+- int i;
+-
+- table = journal->j_revoke_table[0];
+- if (!table)
+- return;
+-
+- for (i=0; i<table->hash_size; i++) {
+- hash_list = &table->hash_table[i];
+- J_ASSERT (list_empty(hash_list));
+- }
+-
+- kfree(table->hash_table);
+- kmem_cache_free(jbd2_revoke_table_cache, table);
+- journal->j_revoke = NULL;
+-
+- table = journal->j_revoke_table[1];
+- if (!table)
+- return;
+-
+- for (i=0; i<table->hash_size; i++) {
+- hash_list = &table->hash_table[i];
+- J_ASSERT (list_empty(hash_list));
+- }
+-
+- kfree(table->hash_table);
+- kmem_cache_free(jbd2_revoke_table_cache, table);
+ journal->j_revoke = NULL;
++ if (journal->j_revoke_table[0])
++ jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]);
++ if (journal->j_revoke_table[1])
++ jbd2_journal_destroy_revoke_table(journal->j_revoke_table[1]);
+ }
+
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index b9b0b6f..d6e006e 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -618,6 +618,12 @@ repeat:
+ goto done;
+
+ /*
++ * this is the first time this transaction is touching this buffer,
++ * reset the modified flag
++ */
++ jh->b_modified = 0;
++
++ /*
+ * If there is already a copy-out version of this buffer, then we don't
+ * need to make another one
+ */
+@@ -690,7 +696,7 @@ repeat:
+ if (!frozen_buffer) {
+ printk(KERN_EMERG
+ "%s: OOM for frozen_buffer\n",
+- __FUNCTION__);
++ __func__);
+ JBUFFER_TRACE(jh, "oom!");
+ error = -ENOMEM;
+ jbd_lock_bh_state(bh);
+@@ -829,9 +835,16 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh)
+
+ if (jh->b_transaction == NULL) {
+ jh->b_transaction = transaction;
++
++ /* first access by this transaction */
++ jh->b_modified = 0;
++
+ JBUFFER_TRACE(jh, "file as BJ_Reserved");
+ __jbd2_journal_file_buffer(jh, transaction, BJ_Reserved);
+ } else if (jh->b_transaction == journal->j_committing_transaction) {
++ /* first access by this transaction */
++ jh->b_modified = 0;
++
+ JBUFFER_TRACE(jh, "set next transaction");
+ jh->b_next_transaction = transaction;
+ }
+@@ -901,7 +914,7 @@ repeat:
+ committed_data = jbd2_alloc(jh2bh(jh)->b_size, GFP_NOFS);
+ if (!committed_data) {
+ printk(KERN_EMERG "%s: No memory for committed data\n",
+- __FUNCTION__);
++ __func__);
+ err = -ENOMEM;
+ goto out;
+ }
+@@ -1230,6 +1243,7 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
+ struct journal_head *jh;
+ int drop_reserve = 0;
+ int err = 0;
++ int was_modified = 0;
+
+ BUFFER_TRACE(bh, "entry");
+
+@@ -1248,6 +1262,9 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
+ goto not_jbd;
+ }
+
++ /* keep track of wether or not this transaction modified us */
++ was_modified = jh->b_modified;
++
+ /*
+ * The buffer's going from the transaction, we must drop
+ * all references -bzzz
+@@ -1265,7 +1282,12 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
+
+ JBUFFER_TRACE(jh, "belongs to current transaction: unfile");
+
+- drop_reserve = 1;
++ /*
++ * we only want to drop a reference if this transaction
++ * modified the buffer
++ */
++ if (was_modified)
++ drop_reserve = 1;
+
+ /*
+ * We are no longer going to journal this buffer.
+@@ -1305,7 +1327,13 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
+ if (jh->b_next_transaction) {
+ J_ASSERT(jh->b_next_transaction == transaction);
+ jh->b_next_transaction = NULL;
+- drop_reserve = 1;
++
++ /*
++ * only drop a reference if this transaction modified
++ * the buffer
++ */
++ if (was_modified)
++ drop_reserve = 1;
+ }
+ }
+
+@@ -1434,7 +1462,8 @@ int jbd2_journal_stop(handle_t *handle)
+ return err;
+ }
+
+-/**int jbd2_journal_force_commit() - force any uncommitted transactions
++/**
++ * int jbd2_journal_force_commit() - force any uncommitted transactions
+ * @journal: journal to force
+ *
+ * For synchronous operations: force any uncommitted transactions
+@@ -2077,7 +2106,7 @@ void __jbd2_journal_refile_buffer(struct journal_head *jh)
+ jh->b_transaction = jh->b_next_transaction;
+ jh->b_next_transaction = NULL;
+ __jbd2_journal_file_buffer(jh, jh->b_transaction,
+- was_dirty ? BJ_Metadata : BJ_Reserved);
++ jh->b_modified ? BJ_Metadata : BJ_Reserved);
+ J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING);
+
+ if (was_dirty)
diff --git a/fs/jffs2/README.Locking b/fs/jffs2/README.Locking
index d14d5a4..3ea3655 100644
--- a/fs/jffs2/README.Locking
@@ -738032,7 +988492,7 @@
void
diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h
-index 4130ada..9645275 100644
+index 4130ada..a113ecc 100644
--- a/fs/jffs2/debug.h
+++ b/fs/jffs2/debug.h
@@ -38,6 +38,7 @@
@@ -738043,6 +988503,39 @@
#define JFFS2_DBG_MEMALLOC_MESSAGES
#endif
+@@ -81,28 +82,28 @@
+ do { \
+ printk(JFFS2_ERR_MSG_PREFIX \
+ " (%d) %s: " fmt, task_pid_nr(current), \
+- __FUNCTION__ , ##__VA_ARGS__); \
++ __func__ , ##__VA_ARGS__); \
+ } while(0)
+
+ #define JFFS2_WARNING(fmt, ...) \
+ do { \
+ printk(JFFS2_WARN_MSG_PREFIX \
+ " (%d) %s: " fmt, task_pid_nr(current), \
+- __FUNCTION__ , ##__VA_ARGS__); \
++ __func__ , ##__VA_ARGS__); \
+ } while(0)
+
+ #define JFFS2_NOTICE(fmt, ...) \
+ do { \
+ printk(JFFS2_NOTICE_MSG_PREFIX \
+ " (%d) %s: " fmt, task_pid_nr(current), \
+- __FUNCTION__ , ##__VA_ARGS__); \
++ __func__ , ##__VA_ARGS__); \
+ } while(0)
+
+ #define JFFS2_DEBUG(fmt, ...) \
+ do { \
+ printk(JFFS2_DBG_MSG_PREFIX \
+ " (%d) %s: " fmt, task_pid_nr(current), \
+- __FUNCTION__ , ##__VA_ARGS__); \
++ __func__ , ##__VA_ARGS__); \
+ } while(0)
+
+ /*
@@ -115,6 +116,11 @@
#else
#define dbg_readinode(fmt, ...)
@@ -739580,6 +990073,28 @@
return 0;
}
+diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
+index e486659..574cb75 100644
+--- a/fs/jffs2/xattr.c
++++ b/fs/jffs2/xattr.c
+@@ -82,7 +82,7 @@ static int is_xattr_datum_unchecked(struct jffs2_sb_info *c, struct jffs2_xattr_
+ static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+ {
+ /* must be called under down_write(xattr_sem) */
+- D1(dbg_xattr("%s: xid=%u, version=%u\n", __FUNCTION__, xd->xid, xd->version));
++ D1(dbg_xattr("%s: xid=%u, version=%u\n", __func__, xd->xid, xd->version));
+ if (xd->xname) {
+ c->xdatum_mem_usage -= (xd->name_len + 1 + xd->value_len);
+ kfree(xd->xname);
+@@ -1252,7 +1252,7 @@ int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_
+ rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE);
+ if (rc) {
+ JFFS2_WARNING("%s: jffs2_reserve_space_gc() = %d, request = %u\n",
+- __FUNCTION__, rc, totlen);
++ __func__, rc, totlen);
+ rc = rc ? rc : -EBADFD;
+ goto out;
+ }
diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
index a1f8e37..afe222b 100644
--- a/fs/jfs/ioctl.c
@@ -739653,6 +990168,28 @@
}
default:
return -ENOTTY;
+diff --git a/fs/jfs/jfs_debug.c b/fs/jfs/jfs_debug.c
+index 887f575..bf6ab19 100644
+--- a/fs/jfs/jfs_debug.c
++++ b/fs/jfs/jfs_debug.c
+@@ -89,7 +89,7 @@ void jfs_proc_init(void)
+ {
+ int i;
+
+- if (!(base = proc_mkdir("jfs", proc_root_fs)))
++ if (!(base = proc_mkdir("fs/jfs", NULL)))
+ return;
+ base->owner = THIS_MODULE;
+
+@@ -109,7 +109,7 @@ void jfs_proc_clean(void)
+ if (base) {
+ for (i = 0; i < NPROCENT; i++)
+ remove_proc_entry(Entries[i].name, base);
+- remove_proc_entry("jfs", proc_root_fs);
++ remove_proc_entry("fs/jfs", NULL);
+ }
+ }
+
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index e198506..2bc7d8a 100644
--- a/fs/jfs/jfs_dmap.c
@@ -739843,7 +990380,7 @@
(ulong) parent->bn, index);
}
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
-index b6b74a6..40b16f2 100644
+index b6b74a6..5df517b 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -155,8 +155,6 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req)
@@ -740099,7 +990636,8 @@
- 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__);
+- printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __func__);
up_read(&host->h_rwsem);
+ fl->fl_flags = fl_flags;
+ status = 0;
@@ -740863,7 +991401,7 @@
module_init(init_nlm);
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
-index fe9bdb4..4d81553 100644
+index fe9bdb4..81aca85 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -29,6 +29,7 @@
@@ -740893,6 +991431,15 @@
}
}
+@@ -752,7 +752,7 @@ nlmsvc_grant_blocked(struct nlm_block *block)
+ return;
+ default:
+ printk(KERN_WARNING "lockd: unexpected error %d in %s!\n",
+- -error, __FUNCTION__);
++ -error, __func__);
+ nlmsvc_insert_block(block, 10 * HZ);
+ nlmsvc_release_block(block);
+ return;
@@ -887,7 +887,7 @@ nlmsvc_retry_blocked(void)
unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
struct nlm_block *block;
@@ -741148,11 +991695,52 @@
int error;
locks_init_lock(&fl);
+diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
+index 30f7d0a..05ff4f1 100644
+--- a/fs/msdos/namei.c
++++ b/fs/msdos/namei.c
+@@ -609,7 +609,7 @@ error_inode:
+ if (corrupt < 0) {
+ fat_fs_panic(new_dir->i_sb,
+ "%s: Filesystem corrupted (i_pos %lld)",
+- __FUNCTION__, sinfo.i_pos);
++ __func__, sinfo.i_pos);
+ }
+ goto out;
+ }
+@@ -653,7 +653,7 @@ static const struct inode_operations msdos_dir_inode_operations = {
+ .mkdir = msdos_mkdir,
+ .rmdir = msdos_rmdir,
+ .rename = msdos_rename,
+- .setattr = fat_notify_change,
++ .setattr = fat_setattr,
+ .getattr = fat_getattr,
+ };
+
diff --git a/fs/namei.c b/fs/namei.c
-index 8cf9bb9..e179f71 100644
+index 8cf9bb9..32fd965 100644
--- a/fs/namei.c
+++ b/fs/namei.c
-@@ -1623,8 +1623,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
+@@ -30,6 +30,7 @@
+ #include <linux/capability.h>
+ #include <linux/file.h>
+ #include <linux/fcntl.h>
++#include <linux/device_cgroup.h>
+ #include <asm/namei.h>
+ #include <asm/uaccess.h>
+
+@@ -281,6 +282,10 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
+ if (retval)
+ return retval;
+
++ retval = devcgroup_inode_permission(inode, mask);
++ if (retval)
++ return retval;
++
+ return security_inode_permission(inode, mask, nd);
+ }
+
+@@ -1623,8 +1628,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
return -EACCES;
flag &= ~O_TRUNC;
@@ -741162,7 +991750,7 @@
error = vfs_permission(nd, acc_mode);
if (error)
-@@ -1677,7 +1676,12 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
+@@ -1677,7 +1681,12 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
return 0;
}
@@ -741176,7 +991764,7 @@
int flag, int mode)
{
int error;
-@@ -1696,26 +1700,56 @@ static int open_namei_create(struct nameidata *nd, struct path *path,
+@@ -1696,26 +1705,56 @@ static int open_namei_create(struct nameidata *nd, struct path *path,
}
/*
@@ -741246,7 +991834,7 @@
acc_mode = ACC_MODE(flag);
-@@ -1733,18 +1767,19 @@ int open_namei(int dfd, const char *pathname, int flag,
+@@ -1733,18 +1772,19 @@ int open_namei(int dfd, const char *pathname, int flag,
*/
if (!(flag & O_CREAT)) {
error = path_lookup_open(dfd, pathname, lookup_flags(flag),
@@ -741270,7 +991858,7 @@
/*
* 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,
+@@ -1752,14 +1792,14 @@ int open_namei(int dfd, const char *pathname, int flag,
* will not do.
*/
error = -EISDIR;
@@ -741290,7 +991878,7 @@
do_last:
error = PTR_ERR(path.dentry);
-@@ -1768,18 +1803,31 @@ do_last:
+@@ -1768,18 +1808,31 @@ do_last:
goto exit;
}
@@ -741328,7 +991916,7 @@
}
/*
-@@ -1804,23 +1852,52 @@ do_last:
+@@ -1804,23 +1857,52 @@ do_last:
if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link)
goto do_link;
@@ -741390,7 +991978,7 @@
do_link:
error = -ELOOP;
-@@ -1836,43 +1913,60 @@ do_link:
+@@ -1836,43 +1918,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.
*/
@@ -741466,7 +992054,18 @@
* 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)
+@@ -1934,6 +2033,10 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+ if (!dir->i_op || !dir->i_op->mknod)
+ return -EPERM;
+
++ error = devcgroup_inode_mknod(mode, dev);
++ if (error)
++ return error;
++
+ error = security_inode_mknod(dir, dentry, mode, dev);
+ if (error)
+ return error;
+@@ -1945,6 +2048,23 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
return error;
}
@@ -741490,7 +992089,7 @@
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,
+@@ -1963,12 +2083,19 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
if (error)
goto out;
dentry = lookup_create(&nd, 0);
@@ -741514,7 +992113,7 @@
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,
+@@ -1979,14 +2106,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;
@@ -741533,7 +992132,7 @@
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)
+@@ -2044,7 +2168,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;
@@ -741546,7 +992145,7 @@
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)
+@@ -2151,7 +2280,12 @@ static long do_rmdir(int dfd, const char __user *pathname)
error = PTR_ERR(dentry);
if (IS_ERR(dentry))
goto exit2;
@@ -741559,7 +992158,7 @@
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)
+@@ -2232,7 +2366,11 @@ static long do_unlinkat(int dfd, const char __user *pathname)
inode = dentry->d_inode;
if (inode)
atomic_inc(&inode->i_count);
@@ -741571,7 +992170,7 @@
exit2:
dput(dentry);
}
-@@ -2313,7 +2442,12 @@ asmlinkage long sys_symlinkat(const char __user *oldname,
+@@ -2313,7 +2451,12 @@ asmlinkage long sys_symlinkat(const char __user *oldname,
if (IS_ERR(dentry))
goto out_unlock;
@@ -741584,7 +992183,7 @@
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,
+@@ -2408,7 +2551,12 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
error = PTR_ERR(new_dentry);
if (IS_ERR(new_dentry))
goto out_unlock;
@@ -741597,7 +992196,7 @@
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,
+@@ -2634,8 +2782,12 @@ static int do_rename(int olddfd, const char *oldname,
if (new_dentry == trap)
goto exit5;
@@ -741611,18 +992210,21 @@
dput(new_dentry);
exit4:
diff --git a/fs/namespace.c b/fs/namespace.c
-index 94f026e..f48f981 100644
+index 94f026e..4fc302c 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
-@@ -17,6 +17,7 @@
- #include <linux/quotaops.h>
+@@ -14,9 +14,9 @@
+ #include <linux/smp_lock.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+-#include <linux/quotaops.h>
#include <linux/acct.h>
#include <linux/capability.h>
+#include <linux/cpumask.h>
#include <linux/module.h>
#include <linux/sysfs.h>
#include <linux/seq_file.h>
-@@ -26,6 +27,7 @@
+@@ -26,6 +26,7 @@
#include <linux/mount.h>
#include <linux/ramfs.h>
#include <linux/log2.h>
@@ -741630,7 +992232,7 @@
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include "pnode.h"
-@@ -38,6 +40,8 @@
+@@ -38,6 +39,8 @@
__cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
static int event;
@@ -741639,7 +992241,7 @@
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)
+@@ -55,10 +58,65 @@ static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
return tmp & (HASH_SIZE - 1);
}
@@ -741705,7 +992307,7 @@
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)
+@@ -68,6 +126,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);
@@ -741713,7 +992315,7 @@
if (name) {
int size = strlen(name) + 1;
char *newname = kmalloc(size, GFP_KERNEL);
-@@ -80,6 +140,263 @@ struct vfsmount *alloc_vfsmnt(const char *name)
+@@ -80,6 +139,263 @@ struct vfsmount *alloc_vfsmnt(const char *name)
return mnt;
}
@@ -741977,7 +992579,7 @@
int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb)
{
mnt->mnt_sb = sb;
-@@ -92,6 +409,7 @@ EXPORT_SYMBOL(simple_set_mnt);
+@@ -92,6 +408,7 @@ EXPORT_SYMBOL(simple_set_mnt);
void free_vfsmnt(struct vfsmount *mnt)
{
kfree(mnt->mnt_devname);
@@ -741985,7 +992587,7 @@
kmem_cache_free(mnt_cache, mnt);
}
-@@ -238,6 +556,17 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
+@@ -238,6 +555,17 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
struct vfsmount *mnt = alloc_vfsmnt(old->mnt_devname);
if (mnt) {
@@ -742003,7 +992605,7 @@
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,
+@@ -267,11 +595,44 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
}
}
return mnt;
@@ -742048,7 +992650,7 @@
dput(mnt->mnt_root);
free_vfsmnt(mnt);
deactivate_super(sb);
-@@ -362,20 +724,21 @@ void save_mount_options(struct super_block *sb, char *options)
+@@ -362,20 +723,21 @@ void save_mount_options(struct super_block *sb, char *options)
}
EXPORT_SYMBOL(save_mount_options);
@@ -742074,7 +992676,7 @@
}
static void m_stop(struct seq_file *m, void *v)
-@@ -383,20 +746,30 @@ static void m_stop(struct seq_file *m, void *v)
+@@ -383,20 +745,30 @@ static void m_stop(struct seq_file *m, void *v)
up_read(&namespace_sem);
}
@@ -742113,7 +992715,7 @@
{ MNT_NOSUID, ",nosuid" },
{ MNT_NODEV, ",nodev" },
{ MNT_NOEXEC, ",noexec" },
-@@ -405,40 +778,108 @@ static int show_vfsmnt(struct seq_file *m, void *v)
+@@ -405,40 +777,108 @@ static int show_vfsmnt(struct seq_file *m, void *v)
{ MNT_RELATIME, ",relatime" },
{ 0, NULL }
};
@@ -742238,7 +992840,7 @@
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)
+@@ -459,7 +899,7 @@ static int show_vfsstat(struct seq_file *m, void *v)
/* file system type */
seq_puts(m, "with fstype ");
@@ -742247,7 +992849,7 @@
/* optional statistics */
if (mnt->mnt_sb->s_op->show_stats) {
-@@ -471,12 +912,13 @@ static int show_vfsstat(struct seq_file *m, void *v)
+@@ -471,12 +911,13 @@ static int show_vfsstat(struct seq_file *m, void *v)
return err;
}
@@ -742262,7 +992864,7 @@
/**
* may_umount_tree - check if a mount tree is busy
-@@ -619,10 +1061,11 @@ static int do_umount(struct vfsmount *mnt, int flags)
+@@ -619,10 +1060,11 @@ static int do_umount(struct vfsmount *mnt, int flags)
* about for the moment.
*/
@@ -742278,7 +992880,42 @@
/*
* No sense to grab the lock for this test, but test itself looks
-@@ -801,23 +1244,50 @@ Enomem:
+@@ -641,7 +1083,6 @@ static int do_umount(struct vfsmount *mnt, int flags)
+ down_write(&sb->s_umount);
+ if (!(sb->s_flags & MS_RDONLY)) {
+ lock_kernel();
+- DQUOT_OFF(sb);
+ retval = do_remount_sb(sb, MS_RDONLY, NULL, 0);
+ unlock_kernel();
+ }
+@@ -735,17 +1176,6 @@ static int mount_is_safe(struct nameidata *nd)
+ #endif
+ }
+
+-static int lives_below_in_same_fs(struct dentry *d, struct dentry *dentry)
+-{
+- while (1) {
+- if (d == dentry)
+- return 1;
+- if (d == NULL || d == d->d_parent)
+- return 0;
+- d = d->d_parent;
+- }
+-}
+-
+ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
+ int flag)
+ {
+@@ -762,7 +1192,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
+
+ p = mnt;
+ list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) {
+- if (!lives_below_in_same_fs(r->mnt_mountpoint, dentry))
++ if (!is_subdir(r->mnt_mountpoint, dentry))
+ continue;
+
+ for (s = r; s; s = next_mnt(s, r)) {
+@@ -801,23 +1231,50 @@ Enomem:
struct vfsmount *collect_mounts(struct vfsmount *mnt, struct dentry *dentry)
{
struct vfsmount *tree;
@@ -742333,7 +992970,7 @@
/*
* @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,
+@@ -888,9 +1345,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;
@@ -742352,7 +992989,7 @@
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,
+@@ -913,34 +1377,40 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt,
}
spin_unlock(&vfsmount_lock);
return 0;
@@ -742402,7 +993039,7 @@
return err;
}
-@@ -953,6 +1436,7 @@ static noinline int do_change_type(struct nameidata *nd, int flag)
+@@ -953,6 +1423,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;
@@ -742410,7 +993047,7 @@
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
-@@ -961,12 +1445,20 @@ static noinline int do_change_type(struct nameidata *nd, int flag)
+@@ -961,12 +1432,20 @@ static noinline int do_change_type(struct nameidata *nd, int flag)
return -EINVAL;
down_write(&namespace_sem);
@@ -742432,7 +993069,7 @@
}
/*
-@@ -1004,7 +1496,7 @@ static noinline int do_loopback(struct nameidata *nd, char *old_name,
+@@ -1004,7 +1483,7 @@ static noinline int do_loopback(struct nameidata *nd, char *old_name,
if (!mnt)
goto out;
@@ -742441,7 +993078,7 @@
if (err) {
LIST_HEAD(umount_list);
spin_lock(&vfsmount_lock);
-@@ -1019,6 +1511,23 @@ out:
+@@ -1019,6 +1498,23 @@ out:
return err;
}
@@ -742465,7 +993102,7 @@
/*
* 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,
+@@ -1041,7 +1537,10 @@ static noinline int do_remount(struct nameidata *nd, int flags, int mnt_flags,
return -EINVAL;
down_write(&sb->s_umount);
@@ -742477,7 +993114,7 @@
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,
+@@ -1191,7 +1690,7 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd,
goto unlock;
newmnt->mnt_flags = mnt_flags;
@@ -742486,7 +993123,7 @@
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,
+@@ -1425,6 +1924,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;
@@ -742495,7 +993132,7 @@
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,
+@@ -1434,7 +1935,8 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
if (retval)
return retval;
@@ -742505,7 +993142,7 @@
if (retval)
goto dput_out;
-@@ -1674,15 +2189,13 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
+@@ -1674,15 +2176,13 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
const char __user * put_old)
{
struct vfsmount *tmp;
@@ -742523,7 +993160,7 @@
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,
+@@ -1695,14 +2195,14 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
if (error)
goto out1;
@@ -742540,7 +993177,7 @@
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,
+@@ -1710,9 +2210,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) ||
@@ -742552,7 +993189,7 @@
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,
+@@ -1722,13 +2222,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;
@@ -742570,7 +993207,7 @@
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,
+@@ -1750,27 +2250,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);
@@ -742603,8 +993240,38 @@
return error;
out3:
spin_unlock(&vfsmount_lock);
+@@ -1830,10 +2329,10 @@ void __init mnt_init(void)
+ err = sysfs_init();
+ if (err)
+ printk(KERN_WARNING "%s: sysfs_init error: %d\n",
+- __FUNCTION__, err);
++ __func__, err);
+ fs_kobj = kobject_create_and_add("fs", NULL);
+ if (!fs_kobj)
+- printk(KERN_WARNING "%s: kobj create error\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: kobj create error\n", __func__);
+ init_rootfs();
+ init_mount_tree();
+ }
+diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
+index fbbb9f7..2e5ab12 100644
+--- a/fs/ncpfs/inode.c
++++ b/fs/ncpfs/inode.c
+@@ -107,12 +107,6 @@ static const struct super_operations ncp_sops =
+ .show_options = ncp_show_options,
+ };
+
+-extern struct dentry_operations ncp_root_dentry_operations;
+-#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
+-extern const struct address_space_operations ncp_symlink_aops;
+-extern int ncp_symlink(struct inode*, struct dentry*, const char*);
+-#endif
+-
+ /*
+ * Fill in the ncpfs-specific information in the inode.
+ */
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
-index c67b4bd..ad8f167 100644
+index c67b4bd..3a97c95 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -14,6 +14,7 @@
@@ -742624,7 +993291,48 @@
unsigned int cmd, unsigned long arg)
{
struct ncp_server *server = NCP_SERVER(inode);
-@@ -822,6 +823,57 @@ outrel:
+@@ -388,11 +389,11 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
+ struct dentry* dentry = inode->i_sb->s_root;
+
+ if (dentry) {
+- struct inode* inode = dentry->d_inode;
++ struct inode* s_inode = dentry->d_inode;
+
+- if (inode) {
+- sr.volNumber = NCP_FINFO(inode)->volNumber;
+- sr.dirEntNum = NCP_FINFO(inode)->dirEntNum;
++ if (s_inode) {
++ sr.volNumber = NCP_FINFO(s_inode)->volNumber;
++ sr.dirEntNum = NCP_FINFO(s_inode)->dirEntNum;
+ sr.namespace = server->name_space[sr.volNumber];
+ } else
+ DPRINTK("ncpfs: s_root->d_inode==NULL\n");
+@@ -438,12 +439,12 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
+ dentry = inode->i_sb->s_root;
+ server->root_setuped = 1;
+ if (dentry) {
+- struct inode* inode = dentry->d_inode;
++ struct inode* s_inode = dentry->d_inode;
+
+ if (inode) {
+- NCP_FINFO(inode)->volNumber = vnum;
+- NCP_FINFO(inode)->dirEntNum = de;
+- NCP_FINFO(inode)->DosDirNum = dosde;
++ NCP_FINFO(s_inode)->volNumber = vnum;
++ NCP_FINFO(s_inode)->dirEntNum = de;
++ NCP_FINFO(s_inode)->DosDirNum = dosde;
+ } else
+ DPRINTK("ncpfs: s_root->d_inode==NULL\n");
+ } else
+@@ -518,7 +519,6 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
+ }
+ {
+ struct ncp_lock_ioctl rqdata;
+- int result;
+
+ if (copy_from_user(&rqdata, argp, sizeof(rqdata)))
+ return -EFAULT;
+@@ -822,6 +822,57 @@ outrel:
return -EINVAL;
}
@@ -742682,6 +993390,100 @@
#ifdef CONFIG_COMPAT
long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
+diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
+index df6d60b..97645f1 100644
+--- a/fs/ncpfs/ncplib_kernel.c
++++ b/fs/ncpfs/ncplib_kernel.c
+@@ -102,48 +102,47 @@ static inline void ncp_init_request_s(struct ncp_server *server, int subfunction
+ }
+
+ static inline char *
+- ncp_reply_data(struct ncp_server *server, int offset)
++ncp_reply_data(struct ncp_server *server, int offset)
+ {
+ return &(server->packet[sizeof(struct ncp_reply_header) + offset]);
+ }
+
+-static inline __u8 BVAL(void* data)
++static inline u8 BVAL(void *data)
+ {
+- return get_unaligned((__u8*)data);
++ return *(u8 *)data;
+ }
+
+-static __u8
+- ncp_reply_byte(struct ncp_server *server, int offset)
++static u8 ncp_reply_byte(struct ncp_server *server, int offset)
+ {
+- return get_unaligned((__u8 *) ncp_reply_data(server, offset));
++ return *(u8 *)ncp_reply_data(server, offset);
+ }
+
+-static inline __u16 WVAL_LH(void* data)
++static inline u16 WVAL_LH(void *data)
+ {
+- return le16_to_cpu(get_unaligned((__le16*)data));
++ return get_unaligned_le16(data);
+ }
+
+-static __u16
+- ncp_reply_le16(struct ncp_server *server, int offset)
++static u16
++ncp_reply_le16(struct ncp_server *server, int offset)
+ {
+- return le16_to_cpu(get_unaligned((__le16 *) ncp_reply_data(server, offset)));
++ return get_unaligned_le16(ncp_reply_data(server, offset));
+ }
+
+-static __u16
+- ncp_reply_be16(struct ncp_server *server, int offset)
++static u16
++ncp_reply_be16(struct ncp_server *server, int offset)
+ {
+- return be16_to_cpu(get_unaligned((__be16 *) ncp_reply_data(server, offset)));
++ return get_unaligned_be16(ncp_reply_data(server, offset));
+ }
+
+-static inline __u32 DVAL_LH(void* data)
++static inline u32 DVAL_LH(void *data)
+ {
+- return le32_to_cpu(get_unaligned((__le32*)data));
++ return get_unaligned_le32(data);
+ }
+
+ static __le32
+- ncp_reply_dword(struct ncp_server *server, int offset)
++ncp_reply_dword(struct ncp_server *server, int offset)
+ {
+- return get_unaligned((__le32 *) ncp_reply_data(server, offset));
++ return get_unaligned((__le32 *)ncp_reply_data(server, offset));
+ }
+
+ static inline __u32 ncp_reply_dword_lh(struct ncp_server* server, int offset) {
+@@ -1006,8 +1005,8 @@ ncp_read_bounce(struct ncp_server *server, const char *file_id,
+ result = ncp_request2(server, 72, bounce, bufsize);
+ ncp_unlock_server(server);
+ if (!result) {
+- int len = be16_to_cpu(get_unaligned((__be16*)((char*)bounce +
+- sizeof(struct ncp_reply_header))));
++ int len = get_unaligned_be16((char *)bounce +
++ sizeof(struct ncp_reply_header));
+ result = -EIO;
+ if (len <= to_read) {
+ char* source;
+diff --git a/fs/ncpfs/ncpsign_kernel.c b/fs/ncpfs/ncpsign_kernel.c
+index 749a18d..7c0b5c2 100644
+--- a/fs/ncpfs/ncpsign_kernel.c
++++ b/fs/ncpfs/ncpsign_kernel.c
+@@ -55,7 +55,7 @@ static void nwsign(char *r_data1, char *r_data2, char *outdata) {
+ unsigned int w0,w1,w2,w3;
+ static int rbit[4]={0, 2, 1, 3};
+ #ifdef __i386__
+- unsigned int *data2=(int *)r_data2;
++ unsigned int *data2=(unsigned int *)r_data2;
+ #else
+ unsigned int data2[16];
+ for (i=0;i<16;i++)
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index df0f41e..ac6170c 100644
--- a/fs/nfs/Makefile
@@ -742871,7 +993673,7 @@
unlock_kernel();
}
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
-index c5c0175..f2f3b28 100644
+index c5c0175..89ac5bb 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -112,6 +112,7 @@ struct nfs_client_initdata {
@@ -742943,6 +993745,71 @@
error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]);
error:
+@@ -1298,6 +1321,7 @@ static const struct file_operations nfs_server_list_fops = {
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
++ .owner = THIS_MODULE,
+ };
+
+ static int nfs_volume_list_open(struct inode *inode, struct file *file);
+@@ -1318,6 +1342,7 @@ static const struct file_operations nfs_volume_list_fops = {
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
++ .owner = THIS_MODULE,
+ };
+
+ /*
+@@ -1477,33 +1502,29 @@ int __init nfs_fs_proc_init(void)
+ {
+ struct proc_dir_entry *p;
+
+- proc_fs_nfs = proc_mkdir("nfsfs", proc_root_fs);
++ proc_fs_nfs = proc_mkdir("fs/nfsfs", NULL);
+ if (!proc_fs_nfs)
+ goto error_0;
+
+ proc_fs_nfs->owner = THIS_MODULE;
+
+ /* a file of servers with which we're dealing */
+- p = create_proc_entry("servers", S_IFREG|S_IRUGO, proc_fs_nfs);
++ p = proc_create("servers", S_IFREG|S_IRUGO,
++ proc_fs_nfs, &nfs_server_list_fops);
+ if (!p)
+ goto error_1;
+
+- p->proc_fops = &nfs_server_list_fops;
+- p->owner = THIS_MODULE;
+-
+ /* a file of volumes that we have mounted */
+- p = create_proc_entry("volumes", S_IFREG|S_IRUGO, proc_fs_nfs);
++ p = proc_create("volumes", S_IFREG|S_IRUGO,
++ proc_fs_nfs, &nfs_volume_list_fops);
+ if (!p)
+ goto error_2;
+-
+- p->proc_fops = &nfs_volume_list_fops;
+- p->owner = THIS_MODULE;
+ return 0;
+
+ error_2:
+ remove_proc_entry("servers", proc_fs_nfs);
+ error_1:
+- remove_proc_entry("nfsfs", proc_root_fs);
++ remove_proc_entry("fs/nfsfs", NULL);
+ error_0:
+ return -ENOMEM;
+ }
+@@ -1515,7 +1536,7 @@ void nfs_fs_proc_exit(void)
+ {
+ remove_proc_entry("volumes", proc_fs_nfs);
+ remove_proc_entry("servers", proc_fs_nfs);
+- remove_proc_entry("nfsfs", proc_root_fs);
++ remove_proc_entry("fs/nfsfs", NULL);
+ }
+
+ #endif /* CONFIG_PROC_FS */
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 6cea747..f288b3e 100644
--- a/fs/nfs/dir.c
@@ -744743,7 +995610,7 @@
/*
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
-index f921902..fa220dc 100644
+index f921902..7226a50 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -198,7 +198,7 @@ static match_table_t nfs_secflavor_tokens = {
@@ -744991,7 +995858,49 @@
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)
+@@ -1505,6 +1575,11 @@ static int nfs_compare_super(struct super_block *sb, void *data)
+ return nfs_compare_mount_options(sb, server, mntflags);
+ }
+
++static int nfs_bdi_register(struct nfs_server *server)
++{
++ return bdi_register_dev(&server->backing_dev_info, server->s_dev);
++}
++
+ static int nfs_get_sb(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
+ {
+@@ -1547,6 +1622,10 @@ static int nfs_get_sb(struct file_system_type *fs_type,
+ if (s->s_fs_info != server) {
+ nfs_free_server(server);
+ server = NULL;
++ } else {
++ error = nfs_bdi_register(server);
++ if (error)
++ goto error_splat_super;
+ }
+
+ if (!s->s_root) {
+@@ -1594,6 +1673,7 @@ static void nfs_kill_super(struct super_block *s)
+ {
+ struct nfs_server *server = NFS_SB(s);
+
++ bdi_unregister(&server->backing_dev_info);
+ kill_anon_super(s);
+ nfs_free_server(server);
+ }
+@@ -1638,6 +1718,10 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
+ if (s->s_fs_info != server) {
+ nfs_free_server(server);
+ server = NULL;
++ } else {
++ error = nfs_bdi_register(server);
++ if (error)
++ goto error_splat_super;
+ }
+
+ if (!s->s_root) {
+@@ -1706,28 +1790,6 @@ static void nfs4_fill_super(struct super_block *sb)
}
/*
@@ -745020,7 +995929,7 @@
* Validate NFSv4 mount options
*/
static int nfs4_validate_mount_data(void *options,
-@@ -1751,6 +1799,7 @@ static int nfs4_validate_mount_data(void *options,
+@@ -1751,6 +1813,7 @@ static int nfs4_validate_mount_data(void *options,
args->acregmax = 60;
args->acdirmin = 30;
args->acdirmax = 60;
@@ -745028,7 +995937,7 @@
args->nfs_server.protocol = XPRT_TRANSPORT_TCP;
switch (data->version) {
-@@ -1767,9 +1816,6 @@ static int nfs4_validate_mount_data(void *options,
+@@ -1767,9 +1830,6 @@ static int nfs4_validate_mount_data(void *options,
&args->nfs_server.address))
goto out_no_address;
@@ -745038,7 +995947,7 @@
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,
+@@ -1827,9 +1887,6 @@ static int nfs4_validate_mount_data(void *options,
&args->nfs_server.address))
return -EINVAL;
@@ -745048,7 +995957,7 @@
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,
+@@ -1852,12 +1909,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);
@@ -745065,7 +995974,7 @@
dprintk("NFS: MNTPATH: '%s'\n", args->nfs_server.export_path);
-@@ -1879,6 +1926,10 @@ out_inval_auth:
+@@ -1879,6 +1940,10 @@ out_inval_auth:
data->auth_flavourlen);
return -EINVAL;
@@ -745076,6 +995985,39 @@
out_no_address:
dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
return -EINVAL;
+@@ -1933,6 +1998,10 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
+ if (s->s_fs_info != server) {
+ nfs_free_server(server);
+ server = NULL;
++ } else {
++ error = nfs_bdi_register(server);
++ if (error)
++ goto error_splat_super;
+ }
+
+ if (!s->s_root) {
+@@ -2019,6 +2088,10 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
+ if (s->s_fs_info != server) {
+ nfs_free_server(server);
+ server = NULL;
++ } else {
++ error = nfs_bdi_register(server);
++ if (error)
++ goto error_splat_super;
+ }
+
+ if (!s->s_root) {
+@@ -2098,6 +2171,10 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
+ if (s->s_fs_info != server) {
+ nfs_free_server(server);
+ server = NULL;
++ } else {
++ error = nfs_bdi_register(server);
++ if (error)
++ goto error_splat_super;
+ }
+
+ if (!s->s_root) {
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index 83e865a..412738d 100644
--- a/fs/nfs/symlink.c
@@ -745679,9 +996621,27 @@
auth_domain_put(dom);
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
-index aae2b29..562abf3 100644
+index aae2b29..0b3ffa9 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
+@@ -104,7 +104,7 @@ xdr_writemem(__be32 *p, const void *ptr, int nbytes)
+ } while (0)
+ #define RESERVE_SPACE(nbytes) do { \
+ p = xdr_reserve_space(xdr, nbytes); \
+- if (!p) dprintk("NFSD: RESERVE_SPACE(%d) failed in function %s\n", (int) (nbytes), __FUNCTION__); \
++ if (!p) dprintk("NFSD: RESERVE_SPACE(%d) failed in function %s\n", (int) (nbytes), __func__); \
+ BUG_ON(!p); \
+ } while (0)
+
+@@ -134,7 +134,7 @@ xdr_error: \
+ p = xdr_inline_decode(xdr, nbytes); \
+ if (!p) { \
+ dprintk("NFSD: %s: reply buffer overflowed in line %d.\n", \
+- __FUNCTION__, __LINE__); \
++ __func__, __LINE__); \
+ return -EIO; \
+ } \
+ } while (0)
@@ -344,6 +344,21 @@ static struct rpc_version * nfs_cb_version[] = {
&nfs_cb_version4,
};
@@ -746103,7 +997063,7 @@
else if (d_mountpoint(dentry)) {
int err;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
-index 8516137..42f3820 100644
+index 8516137..5ac00c4 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -22,6 +22,7 @@
@@ -746161,7 +997121,15 @@
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)
+@@ -160,6 +169,7 @@ static const struct file_operations exports_operations = {
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
++ .owner = THIS_MODULE,
+ };
+
+ /*----------------------------------------------------------------------------*/
+@@ -222,6 +232,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;
@@ -746169,7 +997137,7 @@
if (size < sizeof(*data))
return -EINVAL;
-@@ -236,7 +246,11 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size)
+@@ -236,7 +247,11 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size)
res = (struct knfsd_fh*)buf;
exp_readlock();
@@ -746182,7 +997150,7 @@
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)
+@@ -257,6 +272,7 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
int err = 0;
struct knfsd_fh fh;
char *res;
@@ -746190,7 +997158,7 @@
if (size < sizeof(*data))
return -EINVAL;
-@@ -271,7 +286,11 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
+@@ -271,7 +287,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();
@@ -746203,7 +997171,7 @@
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)
+@@ -288,6 +308,58 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
return err;
}
@@ -746262,7 +997230,7 @@
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)
+@@ -347,8 +419,6 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
return mesg - buf;
}
@@ -746271,7 +997239,7 @@
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)
+@@ -371,10 +441,6 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
return strlen(buf);
}
@@ -746282,7 +997250,7 @@
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)
+@@ -696,6 +762,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},
@@ -746293,6 +997261,18 @@
[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},
+@@ -732,10 +802,9 @@ static int create_proc_exports_entry(void)
+ entry = proc_mkdir("fs/nfs", NULL);
+ if (!entry)
+ return -ENOMEM;
+- entry = create_proc_entry("fs/nfs/exports", 0, NULL);
++ entry = proc_create("exports", 0, entry, &exports_operations);
+ if (!entry)
+ return -ENOMEM;
+- entry->proc_fops = &exports_operations;
+ return 0;
+ }
+ #else /* CONFIG_PROC_FS */
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 3e6b3f4..100ae56 100644
--- a/fs/nfsd/nfsfh.c
@@ -746869,6 +997849,63 @@
getout:
kfree(value);
+diff --git a/fs/ntfs/debug.h b/fs/ntfs/debug.h
+index 8ac37c3..5e6724c 100644
+--- a/fs/ntfs/debug.h
++++ b/fs/ntfs/debug.h
+@@ -45,7 +45,7 @@ static void ntfs_debug(const char *f, ...);
+ extern void __ntfs_debug (const char *file, int line, const char *function,
+ const char *format, ...) __attribute__ ((format (printf, 4, 5)));
+ #define ntfs_debug(f, a...) \
+- __ntfs_debug(__FILE__, __LINE__, __FUNCTION__, f, ##a)
++ __ntfs_debug(__FILE__, __LINE__, __func__, f, ##a)
+
+ extern void ntfs_debug_dump_runlist(const runlist_element *rl);
+
+@@ -58,10 +58,10 @@ extern void ntfs_debug_dump_runlist(const runlist_element *rl);
+
+ extern void __ntfs_warning(const char *function, const struct super_block *sb,
+ const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
+-#define ntfs_warning(sb, f, a...) __ntfs_warning(__FUNCTION__, sb, f, ##a)
++#define ntfs_warning(sb, f, a...) __ntfs_warning(__func__, sb, f, ##a)
+
+ extern void __ntfs_error(const char *function, const struct super_block *sb,
+ const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
+-#define ntfs_error(sb, f, a...) __ntfs_error(__FUNCTION__, sb, f, ##a)
++#define ntfs_error(sb, f, a...) __ntfs_error(__func__, sb, f, ##a)
+
+ #endif /* _LINUX_NTFS_DEBUG_H */
+diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
+index 2ad5c8b..790defb 100644
+--- a/fs/ntfs/mft.c
++++ b/fs/ntfs/mft.c
+@@ -1191,7 +1191,7 @@ static int ntfs_mft_bitmap_find_and_alloc_free_rec_nolock(ntfs_volume *vol,
+ if (size) {
+ page = ntfs_map_page(mftbmp_mapping,
+ ofs >> PAGE_CACHE_SHIFT);
+- if (unlikely(IS_ERR(page))) {
++ if (IS_ERR(page)) {
+ ntfs_error(vol->sb, "Failed to read mft "
+ "bitmap, aborting.");
+ return PTR_ERR(page);
+@@ -2118,7 +2118,7 @@ static int ntfs_mft_record_format(const ntfs_volume *vol, const s64 mft_no)
+ }
+ /* Read, map, and pin the page containing the mft record. */
+ page = ntfs_map_page(mft_vi->i_mapping, index);
+- if (unlikely(IS_ERR(page))) {
++ if (IS_ERR(page)) {
+ ntfs_error(vol->sb, "Failed to map page containing mft record "
+ "to format 0x%llx.", (long long)mft_no);
+ return PTR_ERR(page);
+@@ -2519,7 +2519,7 @@ mft_rec_already_initialized:
+ ofs = (bit << vol->mft_record_size_bits) & ~PAGE_CACHE_MASK;
+ /* Read, map, and pin the page containing the mft record. */
+ page = ntfs_map_page(vol->mft_ino->i_mapping, index);
+- if (unlikely(IS_ERR(page))) {
++ if (IS_ERR(page)) {
+ ntfs_error(vol->sb, "Failed to map page containing allocated "
+ "mft record 0x%llx.", (long long)bit);
+ err = PTR_ERR(page);
diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile
index 4d4ce48..f6956de 100644
--- a/fs/ocfs2/Makefile
@@ -749923,6 +1000960,19 @@
dlm_destroy_mle_cache();
}
+diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
+index 61a000f..e48aba6 100644
+--- a/fs/ocfs2/dlm/dlmfs.c
++++ b/fs/ocfs2/dlm/dlmfs.c
+@@ -327,7 +327,7 @@ clear_fields:
+
+ static struct backing_dev_info dlmfs_backing_dev_info = {
+ .ra_pages = 0, /* No readahead */
+- .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
++ .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK,
+ };
+
+ static struct inode *dlmfs_get_root_inode(struct super_block *sb)
diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c
index 52578d9..83a9f29 100644
--- a/fs/ocfs2/dlm/dlmlock.c
@@ -756070,7 +1007120,7 @@
kfree(osb->osb_orphan_wipes);
/* FIXME
diff --git a/fs/open.c b/fs/open.c
-index 3fa4e4f..b70e766 100644
+index 3fa4e4f..7af1f05 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)
@@ -756292,6 +1007342,15 @@
}
f->f_mapping = inode->i_mapping;
+@@ -774,7 +837,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
+ if (f->f_flags & O_DIRECT) {
+ if (!f->f_mapping->a_ops ||
+ ((!f->f_mapping->a_ops->direct_IO) &&
+- (!f->f_mapping->a_ops->get_xip_page))) {
++ (!f->f_mapping->a_ops->get_xip_mem))) {
+ fput(f);
+ f = ERR_PTR(-EINVAL);
+ }
@@ -784,8 +847,19 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
cleanup_all:
@@ -756372,6 +1007431,72 @@
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/partitions/ldm.c b/fs/partitions/ldm.c
+index e7dd1d4..0fdda2e 100644
+--- a/fs/partitions/ldm.c
++++ b/fs/partitions/ldm.c
+@@ -41,12 +41,12 @@
+ #ifndef CONFIG_LDM_DEBUG
+ #define ldm_debug(...) do {} while (0)
+ #else
+-#define ldm_debug(f, a...) _ldm_printk (KERN_DEBUG, __FUNCTION__, f, ##a)
++#define ldm_debug(f, a...) _ldm_printk (KERN_DEBUG, __func__, f, ##a)
+ #endif
+
+-#define ldm_crit(f, a...) _ldm_printk (KERN_CRIT, __FUNCTION__, f, ##a)
+-#define ldm_error(f, a...) _ldm_printk (KERN_ERR, __FUNCTION__, f, ##a)
+-#define ldm_info(f, a...) _ldm_printk (KERN_INFO, __FUNCTION__, f, ##a)
++#define ldm_crit(f, a...) _ldm_printk (KERN_CRIT, __func__, f, ##a)
++#define ldm_error(f, a...) _ldm_printk (KERN_ERR, __func__, f, ##a)
++#define ldm_info(f, a...) _ldm_printk (KERN_INFO, __func__, f, ##a)
+
+ __attribute__ ((format (printf, 3, 4)))
+ static void _ldm_printk (const char *level, const char *function,
+diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
+index 5567ec0..7965118 100644
+--- a/fs/partitions/msdos.c
++++ b/fs/partitions/msdos.c
+@@ -18,7 +18,7 @@
+ *
+ * Re-organised Feb 1998 Russell King
+ */
+-
++#include <linux/msdos_fs.h>
+
+ #include "check.h"
+ #include "msdos.h"
+@@ -419,6 +419,7 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
+ Sector sect;
+ unsigned char *data;
+ struct partition *p;
++ struct fat_boot_sector *fb;
+ int slot;
+
+ data = read_dev_sector(bdev, 0, §);
+@@ -444,8 +445,21 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
+ p = (struct partition *) (data + 0x1be);
+ for (slot = 1; slot <= 4; slot++, p++) {
+ if (p->boot_ind != 0 && p->boot_ind != 0x80) {
+- put_dev_sector(sect);
+- return 0;
++ /*
++ * Even without a valid boot inidicator value
++ * its still possible this is valid FAT filesystem
++ * without a partition table.
++ */
++ fb = (struct fat_boot_sector *) data;
++ if (slot == 1 && fb->reserved && fb->fats
++ && fat_valid_media(fb->media)) {
++ printk("\n");
++ put_dev_sector(sect);
++ return 1;
++ } else {
++ put_dev_sector(sect);
++ return 0;
++ }
+ }
+ }
+
diff --git a/fs/pipe.c b/fs/pipe.c
index 8be381b..f73492b 100644
--- a/fs/pipe.c
@@ -756498,11 +1007623,78 @@
+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/array.c b/fs/proc/array.c
+index 07d6c48..c135cbd 100644
+--- a/fs/proc/array.c
++++ b/fs/proc/array.c
+@@ -425,12 +425,13 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
+ cutime = cstime = utime = stime = cputime_zero;
+ cgtime = gtime = cputime_zero;
+
+- rcu_read_lock();
+ if (lock_task_sighand(task, &flags)) {
+ struct signal_struct *sig = task->signal;
+
+ if (sig->tty) {
+- tty_pgrp = pid_nr_ns(sig->tty->pgrp, ns);
++ struct pid *pgrp = tty_get_pgrp(sig->tty);
++ tty_pgrp = pid_nr_ns(pgrp, ns);
++ put_pid(pgrp);
+ tty_nr = new_encode_dev(tty_devnum(sig->tty));
+ }
+
+@@ -469,7 +470,6 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
+
+ unlock_task_sighand(task, &flags);
+ }
+- rcu_read_unlock();
+
+ if (!whole || num_threads < 2)
+ wchan = get_wchan(task);
diff --git a/fs/proc/base.c b/fs/proc/base.c
-index 81d7d14..c5e412a 100644
+index 81d7d14..fcf02f2 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
-@@ -502,17 +502,14 @@ static const struct inode_operations proc_def_inode_operations = {
+@@ -195,12 +195,32 @@ static int proc_root_link(struct inode *inode, struct path *path)
+ return result;
+ }
+
+-#define MAY_PTRACE(task) \
+- (task == current || \
+- (task->parent == current && \
+- (task->ptrace & PT_PTRACED) && \
+- (task_is_stopped_or_traced(task)) && \
+- security_ptrace(current,task) == 0))
++/*
++ * Return zero if current may access user memory in @task, -error if not.
++ */
++static int check_mem_permission(struct task_struct *task)
++{
++ /*
++ * A task can always look at itself, in case it chooses
++ * to use system calls instead of load instructions.
++ */
++ if (task == current)
++ return 0;
++
++ /*
++ * If current is actively ptrace'ing, and would also be
++ * permitted to freshly attach with ptrace now, permit it.
++ */
++ if (task->parent == current && (task->ptrace & PT_PTRACED) &&
++ task_is_stopped_or_traced(task) &&
++ ptrace_may_attach(task))
++ return 0;
++
++ /*
++ * Noone else is allowed.
++ */
++ return -EPERM;
++}
+
+ struct mm_struct *mm_for_maps(struct task_struct *task)
+ {
+@@ -502,17 +522,14 @@ static const struct inode_operations proc_def_inode_operations = {
.setattr = proc_setattr,
};
@@ -756524,7 +1007716,7 @@
struct proc_mounts *p;
int ret = -EINVAL;
-@@ -525,40 +522,61 @@ static int mounts_open(struct inode *inode, struct file *file)
+@@ -525,40 +542,61 @@ static int mounts_open(struct inode *inode, struct file *file)
get_mnt_ns(ns);
}
rcu_read_unlock();
@@ -756606,7 +1007798,7 @@
unsigned res = 0;
poll_wait(file, &ns->poll, wait);
-@@ -573,6 +591,11 @@ static unsigned mounts_poll(struct file *file, poll_table *wait)
+@@ -573,6 +611,11 @@ static unsigned mounts_poll(struct file *file, poll_table *wait)
return res;
}
@@ -756618,7 +1007810,7 @@
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 = {
+@@ -581,38 +624,22 @@ static const struct file_operations proc_mounts_operations = {
.poll = mounts_poll,
};
@@ -756670,7 +1007862,116 @@
}
static const struct file_operations proc_mountstats_operations = {
-@@ -1626,7 +1633,6 @@ static int proc_readfd_common(struct file * filp, void * dirent,
+@@ -715,7 +742,7 @@ static ssize_t mem_read(struct file * file, char __user * buf,
+ if (!task)
+ goto out_no_task;
+
+- if (!MAY_PTRACE(task) || !ptrace_may_attach(task))
++ if (check_mem_permission(task))
+ goto out;
+
+ ret = -ENOMEM;
+@@ -741,7 +768,7 @@ static ssize_t mem_read(struct file * file, char __user * buf,
+
+ this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+ retval = access_process_vm(task, src, page, this_len, 0);
+- if (!retval || !MAY_PTRACE(task) || !ptrace_may_attach(task)) {
++ if (!retval || check_mem_permission(task)) {
+ if (!ret)
+ ret = -EIO;
+ break;
+@@ -785,7 +812,7 @@ static ssize_t mem_write(struct file * file, const char __user *buf,
+ if (!task)
+ goto out_no_task;
+
+- if (!MAY_PTRACE(task) || !ptrace_may_attach(task))
++ if (check_mem_permission(task))
+ goto out;
+
+ copied = -ENOMEM;
+@@ -1174,6 +1201,81 @@ static const struct file_operations proc_pid_sched_operations = {
+
+ #endif
+
++/*
++ * We added or removed a vma mapping the executable. The vmas are only mapped
++ * during exec and are not mapped with the mmap system call.
++ * Callers must hold down_write() on the mm's mmap_sem for these
++ */
++void added_exe_file_vma(struct mm_struct *mm)
++{
++ mm->num_exe_file_vmas++;
++}
++
++void removed_exe_file_vma(struct mm_struct *mm)
++{
++ mm->num_exe_file_vmas--;
++ if ((mm->num_exe_file_vmas == 0) && mm->exe_file){
++ fput(mm->exe_file);
++ mm->exe_file = NULL;
++ }
++
++}
++
++void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)
++{
++ if (new_exe_file)
++ get_file(new_exe_file);
++ if (mm->exe_file)
++ fput(mm->exe_file);
++ mm->exe_file = new_exe_file;
++ mm->num_exe_file_vmas = 0;
++}
++
++struct file *get_mm_exe_file(struct mm_struct *mm)
++{
++ struct file *exe_file;
++
++ /* We need mmap_sem to protect against races with removal of
++ * VM_EXECUTABLE vmas */
++ down_read(&mm->mmap_sem);
++ exe_file = mm->exe_file;
++ if (exe_file)
++ get_file(exe_file);
++ up_read(&mm->mmap_sem);
++ return exe_file;
++}
++
++void dup_mm_exe_file(struct mm_struct *oldmm, struct mm_struct *newmm)
++{
++ /* It's safe to write the exe_file pointer without exe_file_lock because
++ * this is called during fork when the task is not yet in /proc */
++ newmm->exe_file = get_mm_exe_file(oldmm);
++}
++
++static int proc_exe_link(struct inode *inode, struct path *exe_path)
++{
++ struct task_struct *task;
++ struct mm_struct *mm;
++ struct file *exe_file;
++
++ task = get_proc_task(inode);
++ if (!task)
++ return -ENOENT;
++ mm = get_task_mm(task);
++ put_task_struct(task);
++ if (!mm)
++ return -ENOENT;
++ exe_file = get_mm_exe_file(mm);
++ mmput(mm);
++ if (exe_file) {
++ *exe_path = exe_file->f_path;
++ path_get(&exe_file->f_path);
++ fput(exe_file);
++ return 0;
++ } else
++ return -ENOENT;
++}
++
+ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
+ {
+ struct inode *inode = dentry->d_inode;
+@@ -1626,7 +1728,6 @@ static int proc_readfd_common(struct file * filp, void * dirent,
unsigned int fd, ino;
int retval;
struct files_struct * files;
@@ -756678,7 +1007979,7 @@
retval = -ENOENT;
if (!p)
-@@ -1649,9 +1655,8 @@ static int proc_readfd_common(struct file * filp, void * dirent,
+@@ -1649,9 +1750,8 @@ static int proc_readfd_common(struct file * filp, void * dirent,
if (!files)
goto out;
rcu_read_lock();
@@ -756689,7 +1007990,7 @@
fd++, filp->f_pos++) {
char name[PROC_NUMBUF];
int len;
-@@ -2311,6 +2316,7 @@ static const struct pid_entry tgid_base_stuff[] = {
+@@ -2311,6 +2411,7 @@ static const struct pid_entry tgid_base_stuff[] = {
LNK("root", root),
LNK("exe", exe),
REG("mounts", S_IRUGO, mounts),
@@ -756697,7 +1007998,7 @@
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[] = {
+@@ -2643,6 +2744,7 @@ static const struct pid_entry tid_base_stuff[] = {
LNK("root", root),
LNK("exe", exe),
REG("mounts", S_IRUGO, mounts),
@@ -756705,6 +1008006,510 @@
#ifdef CONFIG_PROC_PAGE_MONITOR
REG("clear_refs", S_IWUSR, clear_refs),
REG("smaps", S_IRUGO, smaps),
+diff --git a/fs/proc/generic.c b/fs/proc/generic.c
+index a36ad3c..9d53b39 100644
+--- a/fs/proc/generic.c
++++ b/fs/proc/generic.c
+@@ -69,12 +69,7 @@ proc_file_read(struct file *file, char __user *buf, size_t nbytes,
+ count = min_t(size_t, PROC_BLOCK_SIZE, nbytes);
+
+ start = NULL;
+- if (dp->get_info) {
+- /* Handle old net routines */
+- n = dp->get_info(page, &start, *ppos, count);
+- if (n < count)
+- eof = 1;
+- } else if (dp->read_proc) {
++ if (dp->read_proc) {
+ /*
+ * How to be a proc read function
+ * ------------------------------
+@@ -277,8 +272,11 @@ static int xlate_proc_name(const char *name,
+ int len;
+ int rtn = 0;
+
++ de = *ret;
++ if (!de)
++ de = &proc_root;
++
+ spin_lock(&proc_subdir_lock);
+- de = &proc_root;
+ while (1) {
+ next = strchr(cp, '/');
+ if (!next)
+@@ -385,20 +383,18 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,
+
+ lock_kernel();
+ spin_lock(&proc_subdir_lock);
+- if (de) {
+- for (de = de->subdir; de ; de = de->next) {
+- if (de->namelen != dentry->d_name.len)
+- continue;
+- if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
+- unsigned int ino;
++ for (de = de->subdir; de ; de = de->next) {
++ if (de->namelen != dentry->d_name.len)
++ continue;
++ if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
++ unsigned int ino;
+
+- ino = de->low_ino;
+- de_get(de);
+- spin_unlock(&proc_subdir_lock);
+- error = -EINVAL;
+- inode = proc_get_inode(dir->i_sb, ino, de);
+- goto out_unlock;
+- }
++ ino = de->low_ino;
++ de_get(de);
++ spin_unlock(&proc_subdir_lock);
++ error = -EINVAL;
++ inode = proc_get_inode(dir->i_sb, ino, de);
++ goto out_unlock;
+ }
+ }
+ spin_unlock(&proc_subdir_lock);
+@@ -410,7 +406,8 @@ out_unlock:
+ d_add(dentry, inode);
+ return NULL;
+ }
+- de_put(de);
++ if (de)
++ de_put(de);
+ return ERR_PTR(error);
+ }
+
+@@ -440,10 +437,6 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent,
+ lock_kernel();
+
+ ino = inode->i_ino;
+- if (!de) {
+- ret = -EINVAL;
+- goto out;
+- }
+ i = filp->f_pos;
+ switch (i) {
+ case 0:
+@@ -582,7 +575,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
+ /* make sure name is valid */
+ if (!name || !strlen(name)) goto out;
+
+- if (!(*parent) && xlate_proc_name(name, parent, &fn) != 0)
++ if (xlate_proc_name(name, parent, &fn) != 0)
+ goto out;
+
+ /* At this point there must not be any '/' characters beyond *fn */
+@@ -682,9 +675,10 @@ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
+ return ent;
+ }
+
+-struct proc_dir_entry *proc_create(const char *name, mode_t mode,
+- struct proc_dir_entry *parent,
+- const struct file_operations *proc_fops)
++struct proc_dir_entry *proc_create_data(const char *name, mode_t mode,
++ struct proc_dir_entry *parent,
++ const struct file_operations *proc_fops,
++ void *data)
+ {
+ struct proc_dir_entry *pde;
+ nlink_t nlink;
+@@ -705,6 +699,7 @@ struct proc_dir_entry *proc_create(const char *name, mode_t mode,
+ if (!pde)
+ goto out;
+ pde->proc_fops = proc_fops;
++ pde->data = data;
+ if (proc_register(parent, pde) < 0)
+ goto out_free;
+ return pde;
+@@ -734,55 +729,58 @@ void free_proc_entry(struct proc_dir_entry *de)
+ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
+ {
+ struct proc_dir_entry **p;
+- struct proc_dir_entry *de;
++ struct proc_dir_entry *de = NULL;
+ const char *fn = name;
+ int len;
+
+- if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
+- goto out;
++ if (xlate_proc_name(name, &parent, &fn) != 0)
++ return;
+ len = strlen(fn);
+
+ spin_lock(&proc_subdir_lock);
+ for (p = &parent->subdir; *p; p=&(*p)->next ) {
+- if (!proc_match(len, fn, *p))
+- continue;
+- de = *p;
+- *p = de->next;
+- de->next = NULL;
+-
+- spin_lock(&de->pde_unload_lock);
+- /*
+- * Stop accepting new callers into module. If you're
+- * dynamically allocating ->proc_fops, save a pointer somewhere.
+- */
+- de->proc_fops = NULL;
+- /* Wait until all existing callers into module are done. */
+- if (de->pde_users > 0) {
+- DECLARE_COMPLETION_ONSTACK(c);
+-
+- if (!de->pde_unload_completion)
+- de->pde_unload_completion = &c;
+-
+- spin_unlock(&de->pde_unload_lock);
+- spin_unlock(&proc_subdir_lock);
++ if (proc_match(len, fn, *p)) {
++ de = *p;
++ *p = de->next;
++ de->next = NULL;
++ break;
++ }
++ }
++ spin_unlock(&proc_subdir_lock);
++ if (!de)
++ return;
+
+- wait_for_completion(de->pde_unload_completion);
++ spin_lock(&de->pde_unload_lock);
++ /*
++ * Stop accepting new callers into module. If you're
++ * dynamically allocating ->proc_fops, save a pointer somewhere.
++ */
++ de->proc_fops = NULL;
++ /* Wait until all existing callers into module are done. */
++ if (de->pde_users > 0) {
++ DECLARE_COMPLETION_ONSTACK(c);
++
++ if (!de->pde_unload_completion)
++ de->pde_unload_completion = &c;
+
+- spin_lock(&proc_subdir_lock);
+- goto continue_removing;
+- }
+ spin_unlock(&de->pde_unload_lock);
+
++ wait_for_completion(de->pde_unload_completion);
++
++ goto continue_removing;
++ }
++ spin_unlock(&de->pde_unload_lock);
++
+ continue_removing:
+- if (S_ISDIR(de->mode))
+- parent->nlink--;
+- de->nlink = 0;
+- WARN_ON(de->subdir);
+- if (atomic_dec_and_test(&de->count))
+- free_proc_entry(de);
+- break;
++ if (S_ISDIR(de->mode))
++ parent->nlink--;
++ de->nlink = 0;
++ if (de->subdir) {
++ printk(KERN_WARNING "%s: removing non-empty directory "
++ "'%s/%s', leaking at least '%s'\n", __func__,
++ de->parent->name, de->name, de->subdir->name);
++ WARN_ON(1);
+ }
+- spin_unlock(&proc_subdir_lock);
+-out:
+- return;
++ if (atomic_dec_and_test(&de->count))
++ free_proc_entry(de);
+ }
+diff --git a/fs/proc/inode.c b/fs/proc/inode.c
+index 82b3a1b..6f4e8dc 100644
+--- a/fs/proc/inode.c
++++ b/fs/proc/inode.c
+@@ -25,8 +25,7 @@
+
+ struct proc_dir_entry *de_get(struct proc_dir_entry *de)
+ {
+- if (de)
+- atomic_inc(&de->count);
++ atomic_inc(&de->count);
+ return de;
+ }
+
+@@ -35,18 +34,16 @@ struct proc_dir_entry *de_get(struct proc_dir_entry *de)
+ */
+ void de_put(struct proc_dir_entry *de)
+ {
+- if (de) {
+- lock_kernel();
+- if (!atomic_read(&de->count)) {
+- printk("de_put: entry %s already free!\n", de->name);
+- unlock_kernel();
+- return;
+- }
+-
+- if (atomic_dec_and_test(&de->count))
+- free_proc_entry(de);
++ lock_kernel();
++ if (!atomic_read(&de->count)) {
++ printk("de_put: entry %s already free!\n", de->name);
+ unlock_kernel();
++ return;
+ }
++
++ if (atomic_dec_and_test(&de->count))
++ free_proc_entry(de);
++ unlock_kernel();
+ }
+
+ /*
+@@ -392,7 +389,7 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
+ {
+ struct inode * inode;
+
+- if (de != NULL && !try_module_get(de->owner))
++ if (!try_module_get(de->owner))
+ goto out_mod;
+
+ inode = iget_locked(sb, ino);
+@@ -402,30 +399,29 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
+ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ PROC_I(inode)->fd = 0;
+ PROC_I(inode)->pde = de;
+- if (de) {
+- if (de->mode) {
+- inode->i_mode = de->mode;
+- inode->i_uid = de->uid;
+- inode->i_gid = de->gid;
+- }
+- if (de->size)
+- inode->i_size = de->size;
+- if (de->nlink)
+- inode->i_nlink = de->nlink;
+- if (de->proc_iops)
+- inode->i_op = de->proc_iops;
+- if (de->proc_fops) {
+- if (S_ISREG(inode->i_mode)) {
++
++ if (de->mode) {
++ inode->i_mode = de->mode;
++ inode->i_uid = de->uid;
++ inode->i_gid = de->gid;
++ }
++ if (de->size)
++ inode->i_size = de->size;
++ if (de->nlink)
++ inode->i_nlink = de->nlink;
++ if (de->proc_iops)
++ inode->i_op = de->proc_iops;
++ if (de->proc_fops) {
++ if (S_ISREG(inode->i_mode)) {
+ #ifdef CONFIG_COMPAT
+- if (!de->proc_fops->compat_ioctl)
+- inode->i_fop =
+- &proc_reg_file_ops_no_compat;
+- else
++ if (!de->proc_fops->compat_ioctl)
++ inode->i_fop =
++ &proc_reg_file_ops_no_compat;
++ else
+ #endif
+- inode->i_fop = &proc_reg_file_ops;
+- } else {
+- inode->i_fop = de->proc_fops;
+- }
++ inode->i_fop = &proc_reg_file_ops;
++ } else {
++ inode->i_fop = de->proc_fops;
+ }
+ }
+ unlock_new_inode(inode);
+@@ -433,8 +429,7 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
+ return inode;
+
+ out_ino:
+- if (de != NULL)
+- module_put(de->owner);
++ module_put(de->owner);
+ out_mod:
+ return NULL;
+ }
+diff --git a/fs/proc/internal.h b/fs/proc/internal.h
+index bc72f5c..28cbca8 100644
+--- a/fs/proc/internal.h
++++ b/fs/proc/internal.h
+@@ -11,6 +11,7 @@
+
+ #include <linux/proc_fs.h>
+
++extern struct proc_dir_entry proc_root;
+ #ifdef CONFIG_PROC_SYSCTL
+ extern int proc_sys_init(void);
+ #else
+@@ -46,9 +47,6 @@ extern int nommu_vma_show(struct seq_file *, struct vm_area_struct *);
+
+ extern int maps_protect;
+
+-extern void create_seq_entry(char *name, mode_t mode,
+- const struct file_operations *f);
+-extern int proc_exe_link(struct inode *, struct path *);
+ extern int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns,
+ struct pid *pid, struct task_struct *task);
+ extern int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns,
+diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c
+index 941e951..79ecd28 100644
+--- a/fs/proc/nommu.c
++++ b/fs/proc/nommu.c
+@@ -137,7 +137,7 @@ static const struct file_operations proc_nommu_vma_list_operations = {
+
+ static int __init proc_nommu_init(void)
+ {
+- create_seq_entry("maps", S_IRUGO, &proc_nommu_vma_list_operations);
++ proc_create("maps", S_IRUGO, NULL, &proc_nommu_vma_list_operations);
+ return 0;
+ }
+
+diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
+index 2d56397..74a323d 100644
+--- a/fs/proc/proc_misc.c
++++ b/fs/proc/proc_misc.c
+@@ -179,6 +179,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
+ "PageTables: %8lu kB\n"
+ "NFS_Unstable: %8lu kB\n"
+ "Bounce: %8lu kB\n"
++ "WritebackTmp: %8lu kB\n"
+ "CommitLimit: %8lu kB\n"
+ "Committed_AS: %8lu kB\n"
+ "VmallocTotal: %8lu kB\n"
+@@ -210,6 +211,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
+ K(global_page_state(NR_PAGETABLE)),
+ K(global_page_state(NR_UNSTABLE_NFS)),
+ K(global_page_state(NR_BOUNCE)),
++ K(global_page_state(NR_WRITEBACK_TEMP)),
+ K(allowed),
+ K(committed),
+ (unsigned long)VMALLOC_TOTAL >> 10,
+@@ -456,6 +458,20 @@ static const struct file_operations proc_slabstats_operations = {
+ #endif
+ #endif
+
++#ifdef CONFIG_MMU
++static int vmalloc_open(struct inode *inode, struct file *file)
++{
++ return seq_open(file, &vmalloc_op);
++}
++
++static const struct file_operations proc_vmalloc_operations = {
++ .open = vmalloc_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = seq_release,
++};
++#endif
++
+ static int show_stat(struct seq_file *p, void *v)
+ {
+ int i;
+@@ -812,14 +828,6 @@ static struct file_operations proc_kpageflags_operations = {
+
+ struct proc_dir_entry *proc_root_kcore;
+
+-void create_seq_entry(char *name, mode_t mode, const struct file_operations *f)
+-{
+- struct proc_dir_entry *entry;
+- entry = create_proc_entry(name, mode, NULL);
+- if (entry)
+- entry->proc_fops = f;
+-}
+-
+ void __init proc_misc_init(void)
+ {
+ static struct {
+@@ -848,63 +856,52 @@ void __init proc_misc_init(void)
+
+ /* And now for trickier ones */
+ #ifdef CONFIG_PRINTK
+- {
+- struct proc_dir_entry *entry;
+- entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
+- if (entry)
+- entry->proc_fops = &proc_kmsg_operations;
+- }
++ proc_create("kmsg", S_IRUSR, NULL, &proc_kmsg_operations);
+ #endif
+- create_seq_entry("locks", 0, &proc_locks_operations);
+- create_seq_entry("devices", 0, &proc_devinfo_operations);
+- create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
++ proc_create("locks", 0, NULL, &proc_locks_operations);
++ proc_create("devices", 0, NULL, &proc_devinfo_operations);
++ proc_create("cpuinfo", 0, NULL, &proc_cpuinfo_operations);
+ #ifdef CONFIG_BLOCK
+- create_seq_entry("partitions", 0, &proc_partitions_operations);
++ proc_create("partitions", 0, NULL, &proc_partitions_operations);
+ #endif
+- create_seq_entry("stat", 0, &proc_stat_operations);
+- create_seq_entry("interrupts", 0, &proc_interrupts_operations);
++ proc_create("stat", 0, NULL, &proc_stat_operations);
++ proc_create("interrupts", 0, NULL, &proc_interrupts_operations);
+ #ifdef CONFIG_SLABINFO
+- create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
++ proc_create("slabinfo",S_IWUSR|S_IRUGO,NULL,&proc_slabinfo_operations);
+ #ifdef CONFIG_DEBUG_SLAB_LEAK
+- create_seq_entry("slab_allocators", 0 ,&proc_slabstats_operations);
++ proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations);
++#endif
+ #endif
++#ifdef CONFIG_MMU
++ proc_create("vmallocinfo", S_IRUSR, NULL, &proc_vmalloc_operations);
+ #endif
+- create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
+- create_seq_entry("pagetypeinfo", S_IRUGO, &pagetypeinfo_file_ops);
+- create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
+- create_seq_entry("zoneinfo",S_IRUGO, &proc_zoneinfo_file_operations);
++ proc_create("buddyinfo", S_IRUGO, NULL, &fragmentation_file_operations);
++ proc_create("pagetypeinfo", S_IRUGO, NULL, &pagetypeinfo_file_ops);
++ proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
++ proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
+ #ifdef CONFIG_BLOCK
+- create_seq_entry("diskstats", 0, &proc_diskstats_operations);
++ proc_create("diskstats", 0, NULL, &proc_diskstats_operations);
+ #endif
+ #ifdef CONFIG_MODULES
+- create_seq_entry("modules", 0, &proc_modules_operations);
++ proc_create("modules", 0, NULL, &proc_modules_operations);
+ #endif
+ #ifdef CONFIG_SCHEDSTATS
+- create_seq_entry("schedstat", 0, &proc_schedstat_operations);
++ proc_create("schedstat", 0, NULL, &proc_schedstat_operations);
+ #endif
+ #ifdef CONFIG_PROC_KCORE
+- proc_root_kcore = create_proc_entry("kcore", S_IRUSR, NULL);
+- if (proc_root_kcore) {
+- proc_root_kcore->proc_fops = &proc_kcore_operations;
++ proc_root_kcore = proc_create("kcore", S_IRUSR, NULL, &proc_kcore_operations);
++ if (proc_root_kcore)
+ proc_root_kcore->size =
+ (size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
+- }
+ #endif
+ #ifdef CONFIG_PROC_PAGE_MONITOR
+- create_seq_entry("kpagecount", S_IRUSR, &proc_kpagecount_operations);
+- create_seq_entry("kpageflags", S_IRUSR, &proc_kpageflags_operations);
++ proc_create("kpagecount", S_IRUSR, NULL, &proc_kpagecount_operations);
++ proc_create("kpageflags", S_IRUSR, NULL, &proc_kpageflags_operations);
+ #endif
+ #ifdef CONFIG_PROC_VMCORE
+- proc_vmcore = create_proc_entry("vmcore", S_IRUSR, NULL);
+- if (proc_vmcore)
+- proc_vmcore->proc_fops = &proc_vmcore_operations;
++ proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &proc_vmcore_operations);
+ #endif
+ #ifdef CONFIG_MAGIC_SYSRQ
+- {
+- struct proc_dir_entry *entry;
+- entry = create_proc_entry("sysrq-trigger", S_IWUSR, NULL);
+- if (entry)
+- entry->proc_fops = &proc_sysrq_trigger_operations;
+- }
++ proc_create("sysrq-trigger", S_IWUSR, NULL, &proc_sysrq_trigger_operations);
+ #endif
+ }
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index 4caa5f7..13cd783 100644
--- a/fs/proc/proc_net.c
@@ -756733,6 +1008538,537 @@
seq_release_private(ino, f);
return 0;
}
+diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
+index 614c34b..5acc001 100644
+--- a/fs/proc/proc_sysctl.c
++++ b/fs/proc/proc_sysctl.c
+@@ -165,8 +165,8 @@ out:
+ return err;
+ }
+
+-static ssize_t proc_sys_read(struct file *filp, char __user *buf,
+- size_t count, loff_t *ppos)
++static ssize_t proc_sys_call_handler(struct file *filp, void __user *buf,
++ size_t count, loff_t *ppos, int write)
+ {
+ struct dentry *dentry = filp->f_dentry;
+ struct ctl_table_header *head;
+@@ -190,12 +190,12 @@ static ssize_t proc_sys_read(struct file *filp, char __user *buf,
+ * and won't be until we finish.
+ */
+ error = -EPERM;
+- if (sysctl_perm(table, MAY_READ))
++ if (sysctl_perm(head->root, table, write ? MAY_WRITE : MAY_READ))
+ goto out;
+
+ /* careful: calling conventions are nasty here */
+ res = count;
+- error = table->proc_handler(table, 0, filp, buf, &res, ppos);
++ error = table->proc_handler(table, write, filp, buf, &res, ppos);
+ if (!error)
+ error = res;
+ out:
+@@ -204,44 +204,16 @@ out:
+ return error;
+ }
+
+-static ssize_t proc_sys_write(struct file *filp, const char __user *buf,
++static ssize_t proc_sys_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *ppos)
+ {
+- struct dentry *dentry = filp->f_dentry;
+- struct ctl_table_header *head;
+- struct ctl_table *table;
+- ssize_t error;
+- size_t res;
+-
+- table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
+- /* Has the sysctl entry disappeared on us? */
+- error = -ENOENT;
+- if (!table)
+- goto out;
+-
+- /* Has the sysctl entry been replaced by a directory? */
+- error = -EISDIR;
+- if (!table->proc_handler)
+- goto out;
+-
+- /*
+- * At this point we know that the sysctl was not unregistered
+- * and won't be until we finish.
+- */
+- error = -EPERM;
+- if (sysctl_perm(table, MAY_WRITE))
+- goto out;
+-
+- /* careful: calling conventions are nasty here */
+- res = count;
+- error = table->proc_handler(table, 1, filp, (char __user *)buf,
+- &res, ppos);
+- if (!error)
+- error = res;
+-out:
+- sysctl_head_finish(head);
++ return proc_sys_call_handler(filp, (void __user *)buf, count, ppos, 0);
++}
+
+- return error;
++static ssize_t proc_sys_write(struct file *filp, const char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ return proc_sys_call_handler(filp, (void __user *)buf, count, ppos, 1);
+ }
+
+
+@@ -416,7 +388,7 @@ static int proc_sys_permission(struct inode *inode, int mask, struct nameidata *
+ goto out;
+
+ /* Use the permissions on the sysctl table entry */
+- error = sysctl_perm(table, mask);
++ error = sysctl_perm(head->root, table, mask);
+ out:
+ sysctl_head_finish(head);
+ return error;
+diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
+index 49816e0..21f490f 100644
+--- a/fs/proc/proc_tty.c
++++ b/fs/proc/proc_tty.c
+@@ -5,7 +5,7 @@
+ */
+
+ #include <asm/uaccess.h>
+-
++#include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/errno.h>
+ #include <linux/time.h>
+@@ -136,39 +136,54 @@ static const struct file_operations proc_tty_drivers_operations = {
+ .release = seq_release,
+ };
+
+-/*
+- * This is the handler for /proc/tty/ldiscs
+- */
+-static int tty_ldiscs_read_proc(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
++static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
+ {
+- int i;
+- int len = 0;
+- off_t begin = 0;
++ return (*pos < NR_LDISCS) ? pos : NULL;
++}
++
++static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos)
++{
++ (*pos)++;
++ return (*pos < NR_LDISCS) ? pos : NULL;
++}
++
++static void tty_ldiscs_seq_stop(struct seq_file *m, void *v)
++{
++}
++
++static int tty_ldiscs_seq_show(struct seq_file *m, void *v)
++{
++ int i = *(loff_t *)v;
+ struct tty_ldisc *ld;
+
+- for (i=0; i < NR_LDISCS; i++) {
+- ld = tty_ldisc_get(i);
+- if (ld == NULL)
+- continue;
+- len += sprintf(page+len, "%-10s %2d\n",
+- ld->name ? ld->name : "???", i);
+- tty_ldisc_put(i);
+- if (len+begin > off+count)
+- break;
+- if (len+begin < off) {
+- begin += len;
+- len = 0;
+- }
+- }
+- if (i >= NR_LDISCS)
+- *eof = 1;
+- if (off >= len+begin)
++ ld = tty_ldisc_get(i);
++ if (ld == NULL)
+ return 0;
+- *start = page + (off-begin);
+- return ((count < begin+len-off) ? count : begin+len-off);
++ seq_printf(m, "%-10s %2d\n", ld->name ? ld->name : "???", i);
++ tty_ldisc_put(i);
++ return 0;
++}
++
++static const struct seq_operations tty_ldiscs_seq_ops = {
++ .start = tty_ldiscs_seq_start,
++ .next = tty_ldiscs_seq_next,
++ .stop = tty_ldiscs_seq_stop,
++ .show = tty_ldiscs_seq_show,
++};
++
++static int proc_tty_ldiscs_open(struct inode *inode, struct file *file)
++{
++ return seq_open(file, &tty_ldiscs_seq_ops);
+ }
+
++static const struct file_operations tty_ldiscs_proc_fops = {
++ .owner = THIS_MODULE,
++ .open = proc_tty_ldiscs_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = seq_release,
++};
++
+ /*
+ * This function is called by tty_register_driver() to handle
+ * registering the driver's /proc handler into /proc/tty/driver/<foo>
+@@ -177,16 +192,14 @@ void proc_tty_register_driver(struct tty_driver *driver)
+ {
+ struct proc_dir_entry *ent;
+
+- if ((!driver->read_proc && !driver->write_proc) ||
+- !driver->driver_name ||
++ if (!driver->ops->read_proc || !driver->driver_name ||
+ driver->proc_entry)
+ return;
+
+ ent = create_proc_entry(driver->driver_name, 0, proc_tty_driver);
+ if (!ent)
+ return;
+- ent->read_proc = driver->read_proc;
+- ent->write_proc = driver->write_proc;
++ ent->read_proc = driver->ops->read_proc;
+ ent->owner = driver->owner;
+ ent->data = driver;
+
+@@ -214,7 +227,6 @@ void proc_tty_unregister_driver(struct tty_driver *driver)
+ */
+ void __init proc_tty_init(void)
+ {
+- struct proc_dir_entry *entry;
+ if (!proc_mkdir("tty", NULL))
+ return;
+ proc_tty_ldisc = proc_mkdir("tty/ldisc", NULL);
+@@ -224,10 +236,7 @@ void __init proc_tty_init(void)
+ * password lengths and inter-keystroke timings during password
+ * entry.
+ */
+- proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR | S_IXUSR, NULL);
+-
+- create_proc_read_entry("tty/ldiscs", 0, NULL, tty_ldiscs_read_proc, NULL);
+- entry = create_proc_entry("tty/drivers", 0, NULL);
+- if (entry)
+- entry->proc_fops = &proc_tty_drivers_operations;
++ proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR|S_IXUSR, NULL);
++ proc_create("tty/ldiscs", 0, NULL, &tty_ldiscs_proc_fops);
++ proc_create("tty/drivers", 0, NULL, &proc_tty_drivers_operations);
+ }
+diff --git a/fs/proc/root.c b/fs/proc/root.c
+index ef0fb57..9511753 100644
+--- a/fs/proc/root.c
++++ b/fs/proc/root.c
+@@ -22,8 +22,6 @@
+
+ #include "internal.h"
+
+-struct proc_dir_entry *proc_bus, *proc_root_fs, *proc_root_driver;
+-
+ static int proc_test_super(struct super_block *sb, void *data)
+ {
+ return sb->s_fs_info == data;
+@@ -126,8 +124,8 @@ void __init proc_root_init(void)
+ #ifdef CONFIG_SYSVIPC
+ proc_mkdir("sysvipc", NULL);
+ #endif
+- proc_root_fs = proc_mkdir("fs", NULL);
+- proc_root_driver = proc_mkdir("driver", NULL);
++ proc_mkdir("fs", NULL);
++ proc_mkdir("driver", NULL);
+ proc_mkdir("fs/nfsd", NULL); /* somewhere for the nfsd filesystem to be mounted */
+ #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
+ /* just give it a mountpoint */
+@@ -137,7 +135,7 @@ void __init proc_root_init(void)
+ #ifdef CONFIG_PROC_DEVICETREE
+ proc_device_tree_init();
+ #endif
+- proc_bus = proc_mkdir("bus", NULL);
++ proc_mkdir("bus", NULL);
+ proc_sys_init();
+ }
+
+@@ -232,9 +230,5 @@ void pid_ns_release_proc(struct pid_namespace *ns)
+ EXPORT_SYMBOL(proc_symlink);
+ EXPORT_SYMBOL(proc_mkdir);
+ EXPORT_SYMBOL(create_proc_entry);
+-EXPORT_SYMBOL(proc_create);
++EXPORT_SYMBOL(proc_create_data);
+ EXPORT_SYMBOL(remove_proc_entry);
+-EXPORT_SYMBOL(proc_root);
+-EXPORT_SYMBOL(proc_root_fs);
+-EXPORT_SYMBOL(proc_bus);
+-EXPORT_SYMBOL(proc_root_driver);
+diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
+index 9dfb5ff..e2b8e76 100644
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -75,40 +75,6 @@ int task_statm(struct mm_struct *mm, int *shared, int *text,
+ return mm->total_vm;
+ }
+
+-int proc_exe_link(struct inode *inode, struct path *path)
+-{
+- struct vm_area_struct * vma;
+- int result = -ENOENT;
+- struct task_struct *task = get_proc_task(inode);
+- struct mm_struct * mm = NULL;
+-
+- if (task) {
+- mm = get_task_mm(task);
+- put_task_struct(task);
+- }
+- if (!mm)
+- goto out;
+- down_read(&mm->mmap_sem);
+-
+- vma = mm->mmap;
+- while (vma) {
+- if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
+- break;
+- vma = vma->vm_next;
+- }
+-
+- if (vma) {
+- *path = vma->vm_file->f_path;
+- path_get(&vma->vm_file->f_path);
+- result = 0;
+- }
+-
+- up_read(&mm->mmap_sem);
+- mmput(mm);
+-out:
+- return result;
+-}
+-
+ static void pad_len_spaces(struct seq_file *m, int len)
+ {
+ len = 25 + sizeof(void*) * 6 - len;
+@@ -338,8 +304,7 @@ const struct file_operations proc_maps_operations = {
+ #define PSS_SHIFT 12
+
+ #ifdef CONFIG_PROC_PAGE_MONITOR
+-struct mem_size_stats
+-{
++struct mem_size_stats {
+ struct vm_area_struct *vma;
+ unsigned long resident;
+ unsigned long shared_clean;
+@@ -347,6 +312,7 @@ struct mem_size_stats
+ unsigned long private_clean;
+ unsigned long private_dirty;
+ unsigned long referenced;
++ unsigned long swap;
+ u64 pss;
+ };
+
+@@ -363,6 +329,12 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
+ pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
+ for (; addr != end; pte++, addr += PAGE_SIZE) {
+ ptent = *pte;
++
++ if (is_swap_pte(ptent)) {
++ mss->swap += PAGE_SIZE;
++ continue;
++ }
++
+ if (!pte_present(ptent))
+ continue;
+
+@@ -421,7 +393,8 @@ static int show_smap(struct seq_file *m, void *v)
+ "Shared_Dirty: %8lu kB\n"
+ "Private_Clean: %8lu kB\n"
+ "Private_Dirty: %8lu kB\n"
+- "Referenced: %8lu kB\n",
++ "Referenced: %8lu kB\n"
++ "Swap: %8lu kB\n",
+ (vma->vm_end - vma->vm_start) >> 10,
+ mss.resident >> 10,
+ (unsigned long)(mss.pss >> (10 + PSS_SHIFT)),
+@@ -429,7 +402,8 @@ static int show_smap(struct seq_file *m, void *v)
+ mss.shared_dirty >> 10,
+ mss.private_clean >> 10,
+ mss.private_dirty >> 10,
+- mss.referenced >> 10);
++ mss.referenced >> 10,
++ mss.swap >> 10);
+
+ return ret;
+ }
+@@ -579,7 +553,7 @@ static int pagemap_pte_hole(unsigned long start, unsigned long end,
+ return err;
+ }
+
+-u64 swap_pte_to_pagemap_entry(pte_t pte)
++static u64 swap_pte_to_pagemap_entry(pte_t pte)
+ {
+ swp_entry_t e = pte_to_swp_entry(pte);
+ return swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT);
+diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
+index 8011528..4b733f1 100644
+--- a/fs/proc/task_nommu.c
++++ b/fs/proc/task_nommu.c
+@@ -103,40 +103,6 @@ int task_statm(struct mm_struct *mm, int *shared, int *text,
+ return size;
+ }
+
+-int proc_exe_link(struct inode *inode, struct path *path)
+-{
+- struct vm_list_struct *vml;
+- struct vm_area_struct *vma;
+- struct task_struct *task = get_proc_task(inode);
+- struct mm_struct *mm = get_task_mm(task);
+- int result = -ENOENT;
+-
+- if (!mm)
+- goto out;
+- down_read(&mm->mmap_sem);
+-
+- vml = mm->context.vmlist;
+- vma = NULL;
+- while (vml) {
+- if ((vml->vma->vm_flags & VM_EXECUTABLE) && vml->vma->vm_file) {
+- vma = vml->vma;
+- break;
+- }
+- vml = vml->next;
+- }
+-
+- if (vma) {
+- *path = vma->vm_file->f_path;
+- path_get(&vma->vm_file->f_path);
+- result = 0;
+- }
+-
+- up_read(&mm->mmap_sem);
+- mmput(mm);
+-out:
+- return result;
+-}
+-
+ /*
+ * display mapping lines for a particular process's /proc/pid/maps
+ */
+diff --git a/fs/quota.c b/fs/quota.c
+index 84f28dd..db1cc9f 100644
+--- a/fs/quota.c
++++ b/fs/quota.c
+@@ -69,7 +69,6 @@ static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid
+ switch (cmd) {
+ case Q_GETFMT:
+ case Q_GETINFO:
+- case Q_QUOTAOFF:
+ case Q_SETINFO:
+ case Q_SETQUOTA:
+ case Q_GETQUOTA:
+@@ -229,12 +228,12 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void
+
+ if (IS_ERR(pathname = getname(addr)))
+ return PTR_ERR(pathname);
+- ret = sb->s_qcop->quota_on(sb, type, id, pathname);
++ ret = sb->s_qcop->quota_on(sb, type, id, pathname, 0);
+ putname(pathname);
+ return ret;
+ }
+ case Q_QUOTAOFF:
+- return sb->s_qcop->quota_off(sb, type);
++ return sb->s_qcop->quota_off(sb, type, 0);
+
+ case Q_GETFMT: {
+ __u32 fmt;
+diff --git a/fs/quota_v1.c b/fs/quota_v1.c
+index f3841f2..a6cf926 100644
+--- a/fs/quota_v1.c
++++ b/fs/quota_v1.c
+@@ -139,6 +139,9 @@ static int v1_read_file_info(struct super_block *sb, int type)
+ goto out;
+ }
+ ret = 0;
++ /* limits are stored as unsigned 32-bit data */
++ dqopt->info[type].dqi_maxblimit = 0xffffffff;
++ dqopt->info[type].dqi_maxilimit = 0xffffffff;
+ dqopt->info[type].dqi_igrace = dqblk.dqb_itime ? dqblk.dqb_itime : MAX_IQ_TIME;
+ dqopt->info[type].dqi_bgrace = dqblk.dqb_btime ? dqblk.dqb_btime : MAX_DQ_TIME;
+ out:
+diff --git a/fs/quota_v2.c b/fs/quota_v2.c
+index c519a58..234ada9 100644
+--- a/fs/quota_v2.c
++++ b/fs/quota_v2.c
+@@ -59,6 +59,9 @@ static int v2_read_file_info(struct super_block *sb, int type)
+ sb->s_id);
+ return -1;
+ }
++ /* limits are stored as unsigned 32-bit data */
++ info->dqi_maxblimit = 0xffffffff;
++ info->dqi_maxilimit = 0xffffffff;
+ info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
+ info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
+ info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
+@@ -303,7 +306,7 @@ static uint find_free_dqentry(struct dquot *dquot, int *err)
+ printk(KERN_ERR "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk);
+ goto out_buf;
+ }
+- dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries)+1);
++ le16_add_cpu(&dh->dqdh_entries, 1);
+ memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
+ /* Find free structure in block */
+ for (i = 0; i < V2_DQSTRINBLK && memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)); i++);
+@@ -445,7 +448,7 @@ static int free_dqentry(struct dquot *dquot, uint blk)
+ goto out_buf;
+ }
+ dh = (struct v2_disk_dqdbheader *)buf;
+- dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries)-1);
++ le16_add_cpu(&dh->dqdh_entries, -1);
+ if (!le16_to_cpu(dh->dqdh_entries)) { /* Block got free? */
+ if ((ret = remove_free_dqentry(sb, type, buf, blk)) < 0 ||
+ (ret = put_free_dqblk(sb, type, buf, blk)) < 0) {
+diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c
+index b41a514..9590b90 100644
+--- a/fs/ramfs/file-mmu.c
++++ b/fs/ramfs/file-mmu.c
+@@ -26,6 +26,9 @@
+
+ #include <linux/fs.h>
+ #include <linux/mm.h>
++#include <linux/ramfs.h>
++
++#include "internal.h"
+
+ const struct address_space_operations ramfs_aops = {
+ .readpage = simple_readpage,
+diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
+index 8428d5b..b131234 100644
+--- a/fs/ramfs/inode.c
++++ b/fs/ramfs/inode.c
+@@ -44,7 +44,7 @@ static const struct inode_operations ramfs_dir_inode_operations;
+
+ static struct backing_dev_info ramfs_backing_dev_info = {
+ .ra_pages = 0, /* No readahead */
+- .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK |
++ .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK |
+ BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY |
+ BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP,
+ };
+diff --git a/fs/ramfs/internal.h b/fs/ramfs/internal.h
+index af7cc07..6b33063 100644
+--- a/fs/ramfs/internal.h
++++ b/fs/ramfs/internal.h
+@@ -11,5 +11,4 @@
+
+
+ extern const struct address_space_operations ramfs_aops;
+-extern const struct file_operations ramfs_file_operations;
+ extern const struct inode_operations ramfs_file_inode_operations;
diff --git a/fs/read_write.c b/fs/read_write.c
index 49a9871..f0d1240 100644
--- a/fs/read_write.c
@@ -756764,8 +1009100,89 @@
lock_kernel();
switch (origin) {
+diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
+index f491ceb..4646caa 100644
+--- a/fs/reiserfs/bitmap.c
++++ b/fs/reiserfs/bitmap.c
+@@ -479,7 +479,7 @@ static void __discard_prealloc(struct reiserfs_transaction_handle *th,
+ if (ei->i_prealloc_count < 0)
+ reiserfs_warning(th->t_super,
+ "zam-4001:%s: inode has negative prealloc blocks count.",
+- __FUNCTION__);
++ __func__);
+ #endif
+ while (ei->i_prealloc_count > 0) {
+ reiserfs_free_prealloc_block(th, inode, ei->i_prealloc_block);
+@@ -517,7 +517,7 @@ void reiserfs_discard_all_prealloc(struct reiserfs_transaction_handle *th)
+ if (!ei->i_prealloc_count) {
+ reiserfs_warning(th->t_super,
+ "zam-4001:%s: inode is in prealloc list but has no preallocated blocks.",
+- __FUNCTION__);
++ __func__);
+ }
+ #endif
+ __discard_prealloc(th, ei);
+@@ -632,7 +632,7 @@ int reiserfs_parse_alloc_options(struct super_block *s, char *options)
+ }
+
+ reiserfs_warning(s, "zam-4001: %s : unknown option - %s",
+- __FUNCTION__, this_char);
++ __func__, this_char);
+ return 1;
+ }
+
+@@ -1254,7 +1254,7 @@ struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb,
+ bh = sb_bread(sb, block);
+ if (bh == NULL)
+ reiserfs_warning(sb, "sh-2029: %s: bitmap block (#%u) "
+- "reading failed", __FUNCTION__, block);
++ "reading failed", __func__, block);
+ else {
+ if (buffer_locked(bh)) {
+ PROC_INFO_INC(sb, scan_bitmap.wait);
+diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c
+index 7ee4208..2f87f5b 100644
+--- a/fs/reiserfs/do_balan.c
++++ b/fs/reiserfs/do_balan.c
+@@ -1464,29 +1464,29 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h
+ } else
+ /* item falls wholly into S_new[i] */
+ {
+- int ret_val;
++ int leaf_mi;
+ struct item_head *pasted;
+
+ #ifdef CONFIG_REISERFS_CHECK
+- struct item_head *ih =
++ struct item_head *ih_check =
+ B_N_PITEM_HEAD(tbS0, item_pos);
+
+- if (!is_direntry_le_ih(ih)
+- && (pos_in_item != ih_item_len(ih)
++ if (!is_direntry_le_ih(ih_check)
++ && (pos_in_item != ih_item_len(ih_check)
+ || tb->insert_size[0] <= 0))
+ reiserfs_panic(tb->tb_sb,
+ "PAP-12235: balance_leaf: pos_in_item must be equal to ih_item_len");
+ #endif /* CONFIG_REISERFS_CHECK */
+
+- ret_val =
++ leaf_mi =
+ leaf_move_items(LEAF_FROM_S_TO_SNEW,
+ tb, snum[i],
+ sbytes[i],
+ S_new[i]);
+
+- RFALSE(ret_val,
++ RFALSE(leaf_mi,
+ "PAP-12240: unexpected value returned by leaf_move_items (%d)",
+- ret_val);
++ leaf_mi);
+
+ /* paste into item */
+ bi.tb = tb;
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
-index e0f0f09..74363a7 100644
+index e0f0f09..8303320 100644
--- a/fs/reiserfs/ioctl.c
+++ b/fs/reiserfs/ioctl.c
@@ -4,6 +4,7 @@
@@ -756776,7 +1009193,16 @@
#include <linux/reiserfs_fs.h>
#include <linux/time.h>
#include <asm/uaccess.h>
-@@ -25,6 +26,7 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+@@ -11,8 +12,6 @@
+ #include <linux/smp_lock.h>
+ #include <linux/compat.h>
+
+-static int reiserfs_unpack(struct inode *inode, struct file *filp);
+-
+ /*
+ ** reiserfs_ioctl - handler for ioctl for inode
+ ** supported commands:
+@@ -25,6 +24,7 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
unsigned int flags;
@@ -756784,22 +1009210,22 @@
switch (cmd) {
case REISERFS_IOC_UNPACK:
-@@ -48,50 +50,67 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+@@ -48,50 +48,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;
--
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
+
- /* Is it quota file? Do not allow user to mess with it. */
- if (IS_NOQUOTA(inode))
- return -EPERM;
@@ -756874,8 +1009300,17 @@
default:
return -ENOTTY;
}
+@@ -140,7 +157,7 @@ int reiserfs_prepare_write(struct file *f, struct page *page,
+ ** Function try to convert tail from direct item into indirect.
+ ** It set up nopack attribute in the REISERFS_I(inode)->nopack
+ */
+-static int reiserfs_unpack(struct inode *inode, struct file *filp)
++int reiserfs_unpack(struct inode *inode, struct file *filp)
+ {
+ int retval = 0;
+ int index;
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
-index bb05a3e..060eb3f 100644
+index bb05a3e..e396b2f 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -38,7 +38,7 @@
@@ -756887,6 +1009322,338 @@
#include <linux/vmalloc.h>
#include <linux/reiserfs_fs.h>
+@@ -1187,7 +1187,7 @@ static int flush_commit_list(struct super_block *s,
+
+ if (retval)
+ reiserfs_abort(s, retval, "Journal write error in %s",
+- __FUNCTION__);
++ __func__);
+ put_fs_excl();
+ return retval;
+ }
+@@ -1534,7 +1534,7 @@ static int flush_journal_list(struct super_block *s,
+ reiserfs_warning(s,
+ "clm-2082: Unable to flush buffer %llu in %s",
+ (unsigned long long)saved_bh->
+- b_blocknr, __FUNCTION__);
++ b_blocknr, __func__);
+ }
+ free_cnode:
+ last = cn;
+@@ -1586,7 +1586,7 @@ static int flush_journal_list(struct super_block *s,
+ if (err)
+ reiserfs_abort(s, -EIO,
+ "Write error while pushing transaction to disk in %s",
+- __FUNCTION__);
++ __func__);
+ flush_older_and_return:
+
+ /* before we can update the journal header block, we _must_ flush all
+@@ -1616,7 +1616,7 @@ static int flush_journal_list(struct super_block *s,
+ if (err)
+ reiserfs_abort(s, -EIO,
+ "Write error while updating journal header in %s",
+- __FUNCTION__);
++ __func__);
+ }
+ remove_all_from_journal_list(s, jl, 0);
+ list_del_init(&jl->j_list);
+@@ -2574,11 +2574,9 @@ static int release_journal_dev(struct super_block *super,
+
+ result = 0;
+
+- if (journal->j_dev_file != NULL) {
+- result = filp_close(journal->j_dev_file, NULL);
+- journal->j_dev_file = NULL;
+- journal->j_dev_bd = NULL;
+- } else if (journal->j_dev_bd != NULL) {
++ if (journal->j_dev_bd != NULL) {
++ if (journal->j_dev_bd->bd_dev != super->s_dev)
++ bd_release(journal->j_dev_bd);
+ result = blkdev_put(journal->j_dev_bd);
+ journal->j_dev_bd = NULL;
+ }
+@@ -2603,7 +2601,6 @@ static int journal_init_dev(struct super_block *super,
+ result = 0;
+
+ journal->j_dev_bd = NULL;
+- journal->j_dev_file = NULL;
+ jdev = SB_ONDISK_JOURNAL_DEVICE(super) ?
+ new_decode_dev(SB_ONDISK_JOURNAL_DEVICE(super)) : super->s_dev;
+
+@@ -2620,35 +2617,34 @@ static int journal_init_dev(struct super_block *super,
+ "cannot init journal device '%s': %i",
+ __bdevname(jdev, b), result);
+ return result;
+- } else if (jdev != super->s_dev)
++ } else if (jdev != super->s_dev) {
++ result = bd_claim(journal->j_dev_bd, journal);
++ if (result) {
++ blkdev_put(journal->j_dev_bd);
++ return result;
++ }
++
+ set_blocksize(journal->j_dev_bd, super->s_blocksize);
++ }
++
+ return 0;
+ }
+
+- journal->j_dev_file = filp_open(jdev_name, 0, 0);
+- if (!IS_ERR(journal->j_dev_file)) {
+- struct inode *jdev_inode = journal->j_dev_file->f_mapping->host;
+- if (!S_ISBLK(jdev_inode->i_mode)) {
+- reiserfs_warning(super, "journal_init_dev: '%s' is "
+- "not a block device", jdev_name);
+- result = -ENOTBLK;
+- release_journal_dev(super, journal);
+- } else {
+- /* ok */
+- journal->j_dev_bd = I_BDEV(jdev_inode);
+- set_blocksize(journal->j_dev_bd, super->s_blocksize);
+- reiserfs_info(super,
+- "journal_init_dev: journal device: %s\n",
+- bdevname(journal->j_dev_bd, b));
+- }
+- } else {
+- result = PTR_ERR(journal->j_dev_file);
+- journal->j_dev_file = NULL;
++ journal->j_dev_bd = open_bdev_excl(jdev_name, 0, journal);
++ if (IS_ERR(journal->j_dev_bd)) {
++ result = PTR_ERR(journal->j_dev_bd);
++ journal->j_dev_bd = NULL;
+ reiserfs_warning(super,
+ "journal_init_dev: Cannot open '%s': %i",
+ jdev_name, result);
++ return result;
+ }
+- return result;
++
++ set_blocksize(journal->j_dev_bd, super->s_blocksize);
++ reiserfs_info(super,
++ "journal_init_dev: journal device: %s\n",
++ bdevname(journal->j_dev_bd, b));
++ return 0;
+ }
+
+ /**
+@@ -4316,5 +4312,5 @@ static void __reiserfs_journal_abort_soft(struct super_block *sb, int errno)
+
+ void reiserfs_journal_abort(struct super_block *sb, int errno)
+ {
+- return __reiserfs_journal_abort_soft(sb, errno);
++ __reiserfs_journal_abort_soft(sb, errno);
+ }
+diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
+index 8867533..c1add28 100644
+--- a/fs/reiserfs/namei.c
++++ b/fs/reiserfs/namei.c
+@@ -301,7 +301,7 @@ static int reiserfs_find_entry(struct inode *dir, const char *name, int namelen,
+ path_to_entry, de);
+ if (retval == IO_ERROR) {
+ reiserfs_warning(dir->i_sb, "zam-7001: io error in %s",
+- __FUNCTION__);
++ __func__);
+ return IO_ERROR;
+ }
+
+@@ -496,7 +496,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th,
+ reiserfs_warning(dir->i_sb,
+ "zam-7002:%s: \"reiserfs_find_entry\" "
+ "has returned unexpected value (%d)",
+- __FUNCTION__, retval);
++ __func__, retval);
+ }
+
+ return -EEXIST;
+@@ -907,7 +907,7 @@ static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry)
+
+ if (inode->i_nlink != 2 && inode->i_nlink != 1)
+ reiserfs_warning(inode->i_sb, "%s: empty directory has nlink "
+- "!= 2 (%d)", __FUNCTION__, inode->i_nlink);
++ "!= 2 (%d)", __func__, inode->i_nlink);
+
+ clear_nlink(inode);
+ inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
+@@ -984,7 +984,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
+
+ if (!inode->i_nlink) {
+ reiserfs_warning(inode->i_sb, "%s: deleting nonexistent file "
+- "(%s:%lu), %d", __FUNCTION__,
++ "(%s:%lu), %d", __func__,
+ reiserfs_bdevname(inode->i_sb), inode->i_ino,
+ inode->i_nlink);
+ inode->i_nlink = 1;
+diff --git a/fs/reiserfs/objectid.c b/fs/reiserfs/objectid.c
+index 65feba4..ea0cf8c 100644
+--- a/fs/reiserfs/objectid.c
++++ b/fs/reiserfs/objectid.c
+@@ -61,7 +61,7 @@ __u32 reiserfs_get_unused_objectid(struct reiserfs_transaction_handle *th)
+ /* comment needed -Hans */
+ unused_objectid = le32_to_cpu(map[1]);
+ if (unused_objectid == U32_MAX) {
+- reiserfs_warning(s, "%s: no more object ids", __FUNCTION__);
++ reiserfs_warning(s, "%s: no more object ids", __func__);
+ reiserfs_restore_prepared_buffer(s, SB_BUFFER_WITH_SB(s));
+ return 0;
+ }
+@@ -114,7 +114,7 @@ void reiserfs_release_objectid(struct reiserfs_transaction_handle *th,
+ if (objectid_to_release == le32_to_cpu(map[i])) {
+ /* This incrementation unallocates the objectid. */
+ //map[i]++;
+- map[i] = cpu_to_le32(le32_to_cpu(map[i]) + 1);
++ le32_add_cpu(&map[i], 1);
+
+ /* Did we unallocate the last member of an odd sequence, and can shrink oids? */
+ if (map[i] == map[i + 1]) {
+@@ -138,8 +138,7 @@ void reiserfs_release_objectid(struct reiserfs_transaction_handle *th,
+ /* size of objectid map is not changed */
+ if (objectid_to_release + 1 == le32_to_cpu(map[i + 1])) {
+ //objectid_map[i+1]--;
+- map[i + 1] =
+- cpu_to_le32(le32_to_cpu(map[i + 1]) - 1);
++ le32_add_cpu(&map[i + 1], -1);
+ return;
+ }
+
+diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
+index 8f86c52..b9dbeec 100644
+--- a/fs/reiserfs/procfs.c
++++ b/fs/reiserfs/procfs.c
+@@ -467,6 +467,7 @@ static const struct file_operations r_file_operations = {
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
++ .owner = THIS_MODULE,
+ };
+
+ static struct proc_dir_entry *proc_info_root = NULL;
+@@ -475,12 +476,8 @@ static const char proc_info_root_name[] = "fs/reiserfs";
+ static void add_file(struct super_block *sb, char *name,
+ int (*func) (struct seq_file *, struct super_block *))
+ {
+- struct proc_dir_entry *de;
+- de = create_proc_entry(name, 0, REISERFS_SB(sb)->procdir);
+- if (de) {
+- de->data = func;
+- de->proc_fops = &r_file_operations;
+- }
++ proc_create_data(name, 0, REISERFS_SB(sb)->procdir,
++ &r_file_operations, func);
+ }
+
+ int reiserfs_proc_info_init(struct super_block *sb)
+diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
+index d2db241..abbc64d 100644
+--- a/fs/reiserfs/stree.c
++++ b/fs/reiserfs/stree.c
+@@ -1419,8 +1419,7 @@ int reiserfs_delete_object(struct reiserfs_transaction_handle *th,
+
+ inode_generation =
+ &REISERFS_SB(th->t_super)->s_rs->s_inode_generation;
+- *inode_generation =
+- cpu_to_le32(le32_to_cpu(*inode_generation) + 1);
++ le32_add_cpu(inode_generation, 1);
+ }
+ /* USE_INODE_GENERATION_COUNTER */
+ #endif
+diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
+index 393cc22..ed424d7 100644
+--- a/fs/reiserfs/super.c
++++ b/fs/reiserfs/super.c
+@@ -304,7 +304,7 @@ static int finish_unfinished(struct super_block *s)
+ /* Turn quotas off */
+ for (i = 0; i < MAXQUOTAS; i++) {
+ if (sb_dqopt(s)->files[i])
+- vfs_quota_off_mount(s, i);
++ vfs_quota_off(s, i, 0);
+ }
+ if (ms_active_set)
+ /* Restore the flag back */
+@@ -634,7 +634,7 @@ static int reiserfs_acquire_dquot(struct dquot *);
+ static int reiserfs_release_dquot(struct dquot *);
+ static int reiserfs_mark_dquot_dirty(struct dquot *);
+ static int reiserfs_write_info(struct super_block *, int);
+-static int reiserfs_quota_on(struct super_block *, int, int, char *);
++static int reiserfs_quota_on(struct super_block *, int, int, char *, int);
+
+ static struct dquot_operations reiserfs_quota_operations = {
+ .initialize = reiserfs_dquot_initialize,
+@@ -1890,8 +1890,14 @@ static int reiserfs_dquot_drop(struct inode *inode)
+ ret =
+ journal_begin(&th, inode->i_sb,
+ 2 * REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb));
+- if (ret)
++ if (ret) {
++ /*
++ * We call dquot_drop() anyway to at least release references
++ * to quota structures so that umount does not hang.
++ */
++ dquot_drop(inode);
+ goto out;
++ }
+ ret = dquot_drop(inode);
+ err =
+ journal_end(&th, inode->i_sb,
+@@ -2015,13 +2021,17 @@ static int reiserfs_quota_on_mount(struct super_block *sb, int type)
+ * Standard function to be called on quota_on
+ */
+ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
+- char *path)
++ char *path, int remount)
+ {
+ int err;
+ struct nameidata nd;
++ struct inode *inode;
+
+ if (!(REISERFS_SB(sb)->s_mount_opt & (1 << REISERFS_QUOTA)))
+ return -EINVAL;
++ /* No more checks needed? Path and format_id are bogus anyway... */
++ if (remount)
++ return vfs_quota_on(sb, type, format_id, path, 1);
+ err = path_lookup(path, LOOKUP_FOLLOW, &nd);
+ if (err)
+ return err;
+@@ -2030,18 +2040,24 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
+ path_put(&nd.path);
+ return -EXDEV;
+ }
++ inode = nd.path.dentry->d_inode;
+ /* We must not pack tails for quota files on reiserfs for quota IO to work */
+- if (!(REISERFS_I(nd.path.dentry->d_inode)->i_flags & i_nopack_mask)) {
+- reiserfs_warning(sb,
+- "reiserfs: Quota file must have tail packing disabled.");
+- path_put(&nd.path);
+- return -EINVAL;
++ if (!(REISERFS_I(inode)->i_flags & i_nopack_mask)) {
++ err = reiserfs_unpack(inode, NULL);
++ if (err) {
++ reiserfs_warning(sb,
++ "reiserfs: Unpacking tail of quota file failed"
++ " (%d). Cannot turn on quotas.", err);
++ path_put(&nd.path);
++ return -EINVAL;
++ }
++ mark_inode_dirty(inode);
+ }
+ /* Not journalling quota? No more tests needed... */
+ if (!REISERFS_SB(sb)->s_qf_names[USRQUOTA] &&
+ !REISERFS_SB(sb)->s_qf_names[GRPQUOTA]) {
+ path_put(&nd.path);
+- return vfs_quota_on(sb, type, format_id, path);
++ return vfs_quota_on(sb, type, format_id, path, 0);
+ }
+ /* Quotafile not of fs root? */
+ if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
+@@ -2049,7 +2065,7 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
+ "reiserfs: Quota file not on filesystem root. "
+ "Journalled quota will not work.");
+ path_put(&nd.path);
+- return vfs_quota_on(sb, type, format_id, path);
++ return vfs_quota_on(sb, type, format_id, path, 0);
+ }
+
+ /* Read data from quotafile - avoid pagecache and such because we cannot afford
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 344b9b9..d7c4935 100644
--- a/fs/reiserfs/xattr.c
@@ -756900,7 +1009667,7 @@
#define FL_READONLY 128
#define FL_DIR_SEM_HELD 256
diff --git a/fs/select.c b/fs/select.c
-index 5633fe9..00f58c5 100644
+index 5633fe9..2c29214 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -260,7 +260,7 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout)
@@ -756912,6 +1009679,57 @@
retval = table.error;
break;
}
+@@ -425,7 +425,7 @@ sticky:
+ return ret;
+ }
+
+-#ifdef TIF_RESTORE_SIGMASK
++#ifdef HAVE_SET_RESTORE_SIGMASK
+ asmlinkage long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp,
+ fd_set __user *exp, struct timespec __user *tsp,
+ const sigset_t __user *sigmask, size_t sigsetsize)
+@@ -498,7 +498,7 @@ sticky:
+ if (sigmask) {
+ memcpy(¤t->saved_sigmask, &sigsaved,
+ sizeof(sigsaved));
+- set_thread_flag(TIF_RESTORE_SIGMASK);
++ set_restore_sigmask();
+ }
+ } else if (sigmask)
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+@@ -528,7 +528,7 @@ asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp,
+
+ return sys_pselect7(n, inp, outp, exp, tsp, up, sigsetsize);
+ }
+-#endif /* TIF_RESTORE_SIGMASK */
++#endif /* HAVE_SET_RESTORE_SIGMASK */
+
+ struct poll_list {
+ struct poll_list *next;
+@@ -759,7 +759,7 @@ asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,
+ return ret;
+ }
+
+-#ifdef TIF_RESTORE_SIGMASK
++#ifdef HAVE_SET_RESTORE_SIGMASK
+ asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
+ struct timespec __user *tsp, const sigset_t __user *sigmask,
+ size_t sigsetsize)
+@@ -805,7 +805,7 @@ asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
+ if (sigmask) {
+ memcpy(¤t->saved_sigmask, &sigsaved,
+ sizeof(sigsaved));
+- set_thread_flag(TIF_RESTORE_SIGMASK);
++ set_restore_sigmask();
+ }
+ ret = -ERESTARTNOHAND;
+ } else if (sigmask)
+@@ -839,4 +839,4 @@ asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
+
+ return ret;
+ }
+-#endif /* TIF_RESTORE_SIGMASK */
++#endif /* HAVE_SET_RESTORE_SIGMASK */
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 8537702..3f54dbd 100644
--- a/fs/seq_file.c
@@ -757087,8 +1009905,51 @@
static void *single_start(struct seq_file *p, loff_t *pos)
{
return NULL + (*pos == 0);
+diff --git a/fs/smbfs/smb_debug.h b/fs/smbfs/smb_debug.h
+index 734972b..fc4b1a5 100644
+--- a/fs/smbfs/smb_debug.h
++++ b/fs/smbfs/smb_debug.h
+@@ -11,14 +11,14 @@
+ * these are normally enabled.
+ */
+ #ifdef SMBFS_PARANOIA
+-# define PARANOIA(f, a...) printk(KERN_NOTICE "%s: " f, __FUNCTION__ , ## a)
++# define PARANOIA(f, a...) printk(KERN_NOTICE "%s: " f, __func__ , ## a)
+ #else
+ # define PARANOIA(f, a...) do { ; } while(0)
+ #endif
+
+ /* lots of debug messages */
+ #ifdef SMBFS_DEBUG_VERBOSE
+-# define VERBOSE(f, a...) printk(KERN_DEBUG "%s: " f, __FUNCTION__ , ## a)
++# define VERBOSE(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a)
+ #else
+ # define VERBOSE(f, a...) do { ; } while(0)
+ #endif
+@@ -28,7 +28,7 @@
+ * too common name.
+ */
+ #ifdef SMBFS_DEBUG
+-#define DEBUG1(f, a...) printk(KERN_DEBUG "%s: " f, __FUNCTION__ , ## a)
++#define DEBUG1(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a)
+ #else
+ #define DEBUG1(f, a...) do { ; } while(0)
+ #endif
+diff --git a/fs/splice.c b/fs/splice.c
+index eeb1a86..633f58e 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -1075,7 +1075,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
+
+ ret = splice_direct_to_actor(in, &sd, direct_splice_actor);
+ if (ret > 0)
+- *ppos += ret;
++ *ppos = sd.pos;
+
+ return ret;
+ }
diff --git a/fs/super.c b/fs/super.c
-index 09008db..4798350 100644
+index 09008db..453877c 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -37,7 +37,9 @@
@@ -757101,6 +1009962,24 @@
LIST_HEAD(super_blocks);
+@@ -115,7 +117,7 @@ static inline void destroy_super(struct super_block *s)
+ * Drop a superblock's refcount. Returns non-zero if the superblock was
+ * destroyed. The caller must hold sb_lock.
+ */
+-int __put_super(struct super_block *sb)
++static int __put_super(struct super_block *sb)
+ {
+ int ret = 0;
+
+@@ -177,7 +179,7 @@ void deactivate_super(struct super_block *s)
+ if (atomic_dec_and_lock(&s->s_active, &sb_lock)) {
+ s->s_count -= S_BIAS-1;
+ spin_unlock(&sb_lock);
+- DQUOT_OFF(s);
++ DQUOT_OFF(s, 0);
+ down_write(&s->s_umount);
+ fs->kill_sb(s);
+ put_filesystem(fs);
@@ -567,10 +569,29 @@ static void mark_files_ro(struct super_block *sb)
{
struct file *f;
@@ -757133,6 +1010012,49 @@
}
file_list_unlock();
}
+@@ -587,6 +608,7 @@ static void mark_files_ro(struct super_block *sb)
+ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
+ {
+ int retval;
++ int remount_rw;
+
+ #ifdef CONFIG_BLOCK
+ if (!(flags & MS_RDONLY) && bdev_read_only(sb->s_bdev))
+@@ -604,8 +626,11 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
+ mark_files_ro(sb);
+ else if (!fs_may_remount_ro(sb))
+ return -EBUSY;
+- DQUOT_OFF(sb);
++ retval = DQUOT_OFF(sb, 1);
++ if (retval < 0 && retval != -ENOSYS)
++ return -EBUSY;
+ }
++ remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY);
+
+ if (sb->s_op->remount_fs) {
+ lock_super(sb);
+@@ -615,6 +640,8 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
+ return retval;
+ }
+ sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
++ if (remount_rw)
++ DQUOT_ON_REMOUNT(sb);
+ return 0;
+ }
+
+diff --git a/fs/sync.c b/fs/sync.c
+index 7cd005e..228e17b 100644
+--- a/fs/sync.c
++++ b/fs/sync.c
+@@ -64,7 +64,7 @@ int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
+ /* sync the superblock to buffers */
+ sb = inode->i_sb;
+ lock_super(sb);
+- if (sb->s_op->write_super)
++ if (sb->s_dirt && sb->s_op->write_super)
+ sb->s_op->write_super(sb);
+ unlock_super(sb);
+
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 4948d9b..a1c3a1f 100644
--- a/fs/sysfs/dir.c
@@ -757146,7 +1010068,7 @@
DEFINE_MUTEX(sysfs_mutex);
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
-index baa663e..ade9a7e 100644
+index baa663e..e7735f6 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -13,6 +13,7 @@
@@ -757157,7 +1010079,7 @@
#include <linux/namei.h>
#include <linux/poll.h>
#include <linux/list.h>
-@@ -128,7 +129,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+@@ -128,13 +129,13 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
ssize_t retval = 0;
mutex_lock(&buffer->mutex);
@@ -757166,6 +1010088,13 @@
retval = fill_read_buffer(file->f_path.dentry,buffer);
if (retval)
goto out;
+ }
+ pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
+- __FUNCTION__, count, *ppos, buffer->page);
++ __func__, count, *ppos, buffer->page);
+ retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
+ buffer->count);
+ 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.
@@ -757176,6 +1010105,200 @@
* 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
+@@ -477,11 +477,10 @@ const struct file_operations sysfs_file_operations = {
+ .poll = sysfs_poll,
+ };
+
+-
+-int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
+- int type)
++int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,
++ const struct attribute *attr, int type, mode_t amode)
+ {
+- umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
++ umode_t mode = (amode & S_IALLUGO) | S_IFREG;
+ struct sysfs_addrm_cxt acxt;
+ struct sysfs_dirent *sd;
+ int rc;
+@@ -502,6 +501,13 @@ int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
+ }
+
+
++int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
++ int type)
++{
++ return sysfs_add_file_mode(dir_sd, attr, type, attr->mode);
++}
++
++
+ /**
+ * sysfs_create_file - create an attribute file for an object.
+ * @kobj: object we're creating for.
+diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
+index 4779049..eeba384 100644
+--- a/fs/sysfs/group.c
++++ b/fs/sysfs/group.c
+@@ -23,35 +23,50 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
+ int i;
+
+ for (i = 0, attr = grp->attrs; *attr; i++, attr++)
+- if (!grp->is_visible ||
+- grp->is_visible(kobj, *attr, i))
+- sysfs_hash_and_remove(dir_sd, (*attr)->name);
++ sysfs_hash_and_remove(dir_sd, (*attr)->name);
+ }
+
+ static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
+- const struct attribute_group *grp)
++ const struct attribute_group *grp, int update)
+ {
+ struct attribute *const* attr;
+ int error = 0, i;
+
+- for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++)
+- if (!grp->is_visible ||
+- grp->is_visible(kobj, *attr, i))
+- error |=
+- sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
++ for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) {
++ mode_t mode = 0;
++
++ /* in update mode, we're changing the permissions or
++ * visibility. Do this by first removing then
++ * re-adding (if required) the file */
++ if (update)
++ sysfs_hash_and_remove(dir_sd, (*attr)->name);
++ if (grp->is_visible) {
++ mode = grp->is_visible(kobj, *attr, i);
++ if (!mode)
++ continue;
++ }
++ error = sysfs_add_file_mode(dir_sd, *attr, SYSFS_KOBJ_ATTR,
++ (*attr)->mode | mode);
++ if (unlikely(error))
++ break;
++ }
+ if (error)
+ remove_files(dir_sd, kobj, grp);
+ return error;
+ }
+
+
+-int sysfs_create_group(struct kobject * kobj,
+- const struct attribute_group * grp)
++static int internal_create_group(struct kobject *kobj, int update,
++ const struct attribute_group *grp)
+ {
+ struct sysfs_dirent *sd;
+ int error;
+
+- BUG_ON(!kobj || !kobj->sd);
++ BUG_ON(!kobj || (!update && !kobj->sd));
++
++ /* Updates may happen before the object has been instantiated */
++ if (unlikely(update && !kobj->sd))
++ return -EINVAL;
+
+ if (grp->name) {
+ error = sysfs_create_subdir(kobj, grp->name, &sd);
+@@ -60,7 +75,7 @@ int sysfs_create_group(struct kobject * kobj,
+ } else
+ sd = kobj->sd;
+ sysfs_get(sd);
+- error = create_files(sd, kobj, grp);
++ error = create_files(sd, kobj, grp, update);
+ if (error) {
+ if (grp->name)
+ sysfs_remove_subdir(sd);
+@@ -69,6 +84,47 @@ int sysfs_create_group(struct kobject * kobj,
+ return error;
+ }
+
++/**
++ * sysfs_create_group - given a directory kobject, create an attribute group
++ * @kobj: The kobject to create the group on
++ * @grp: The attribute group to create
++ *
++ * This function creates a group for the first time. It will explicitly
++ * warn and error if any of the attribute files being created already exist.
++ *
++ * Returns 0 on success or error.
++ */
++int sysfs_create_group(struct kobject *kobj,
++ const struct attribute_group *grp)
++{
++ return internal_create_group(kobj, 0, grp);
++}
++
++/**
++ * sysfs_update_group - given a directory kobject, create an attribute group
++ * @kobj: The kobject to create the group on
++ * @grp: The attribute group to create
++ *
++ * This function updates an attribute group. Unlike
++ * sysfs_create_group(), it will explicitly not warn or error if any
++ * of the attribute files being created already exist. Furthermore,
++ * if the visibility of the files has changed through the is_visible()
++ * callback, it will update the permissions and add or remove the
++ * relevant files.
++ *
++ * The primary use for this function is to call it after making a change
++ * that affects group visibility.
++ *
++ * Returns 0 on success or error.
++ */
++int sysfs_update_group(struct kobject *kobj,
++ const struct attribute_group *grp)
++{
++ return internal_create_group(kobj, 1, grp);
++}
++
++
++
+ void sysfs_remove_group(struct kobject * kobj,
+ const struct attribute_group * grp)
+ {
+@@ -95,4 +151,5 @@ void sysfs_remove_group(struct kobject * kobj,
+
+
+ EXPORT_SYMBOL_GPL(sysfs_create_group);
++EXPORT_SYMBOL_GPL(sysfs_update_group);
+ EXPORT_SYMBOL_GPL(sysfs_remove_group);
+diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
+index d9262f7..eb53c63 100644
+--- a/fs/sysfs/inode.c
++++ b/fs/sysfs/inode.c
+@@ -30,7 +30,7 @@ static const struct address_space_operations sysfs_aops = {
+
+ static struct backing_dev_info sysfs_backing_dev_info = {
+ .ra_pages = 0, /* No readahead */
+- .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
++ .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK,
+ };
+
+ static const struct inode_operations sysfs_inode_operations ={
+@@ -59,6 +59,8 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
+ if (error)
+ return error;
+
++ iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */
++
+ error = inode_setattr(inode, iattr);
+ if (error)
+ return error;
+diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
+index 7416826..14f0023 100644
+--- a/fs/sysfs/mount.c
++++ b/fs/sysfs/mount.c
+@@ -61,7 +61,7 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
+ /* instantiate and link root dentry */
+ root = d_alloc_root(inode);
+ if (!root) {
+- pr_debug("%s: could not get root dentry!\n",__FUNCTION__);
++ pr_debug("%s: could not get root dentry!\n",__func__);
+ iput(inode);
+ return -ENOMEM;
+ }
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 5f66c44..817f596 100644
--- a/fs/sysfs/symlink.c
@@ -757196,6 +1010319,59 @@
}
static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
+diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
+index ff17f8d..ce4e15f 100644
+--- a/fs/sysfs/sysfs.h
++++ b/fs/sysfs/sysfs.h
+@@ -154,6 +154,8 @@ extern const struct file_operations sysfs_file_operations;
+ int sysfs_add_file(struct sysfs_dirent *dir_sd,
+ const struct attribute *attr, int type);
+
++int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,
++ const struct attribute *attr, int type, mode_t amode);
+ /*
+ * bin.c
+ */
+diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
+index 42d51d1..38ebe3f 100644
+--- a/fs/sysv/sysv.h
++++ b/fs/sysv/sysv.h
+@@ -217,9 +217,9 @@ static inline __fs32 fs32_add(struct sysv_sb_info *sbi, __fs32 *n, int d)
+ if (sbi->s_bytesex == BYTESEX_PDP)
+ *(__u32*)n = PDP_swab(PDP_swab(*(__u32*)n)+d);
+ else if (sbi->s_bytesex == BYTESEX_LE)
+- *(__le32*)n = cpu_to_le32(le32_to_cpu(*(__le32*)n)+d);
++ le32_add_cpu((__le32 *)n, d);
+ else
+- *(__be32*)n = cpu_to_be32(be32_to_cpu(*(__be32*)n)+d);
++ be32_add_cpu((__be32 *)n, d);
+ return *n;
+ }
+
+@@ -242,9 +242,9 @@ static inline __fs16 cpu_to_fs16(struct sysv_sb_info *sbi, __u16 n)
+ static inline __fs16 fs16_add(struct sysv_sb_info *sbi, __fs16 *n, int d)
+ {
+ if (sbi->s_bytesex != BYTESEX_BE)
+- *(__le16*)n = cpu_to_le16(le16_to_cpu(*(__le16 *)n)+d);
++ le16_add_cpu((__le16 *)n, d);
+ else
+- *(__be16*)n = cpu_to_be16(be16_to_cpu(*(__be16 *)n)+d);
++ be16_add_cpu((__be16 *)n, d);
+ return *n;
+ }
+
+diff --git a/fs/timerfd.c b/fs/timerfd.c
+index 10c80b5..5400524 100644
+--- a/fs/timerfd.c
++++ b/fs/timerfd.c
+@@ -20,6 +20,7 @@
+ #include <linux/hrtimer.h>
+ #include <linux/anon_inodes.h>
+ #include <linux/timerfd.h>
++#include <linux/syscalls.h>
+
+ struct timerfd_ctx {
+ struct hrtimer tmr;
diff --git a/fs/udf/Makefile b/fs/udf/Makefile
index be845e7..0d4503f 100644
--- a/fs/udf/Makefile
@@ -758187,7 +1011363,7 @@
}
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
-index 112a5fb..ba5537d 100644
+index 112a5fb..2b34c8c 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -31,6 +31,7 @@
@@ -758584,6 +1011760,28 @@
iinfo = UDF_I(inode);
inode->i_mode = S_IFLNK | S_IRWXUGO;
inode->i_data.a_ops = &udf_symlink_aops;
+@@ -957,7 +890,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
+
+ if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
+ kernel_lb_addr eloc;
+- uint32_t elen;
++ uint32_t bsize;
+
+ block = udf_new_block(inode->i_sb, inode,
+ iinfo->i_location.partitionReferenceNum,
+@@ -970,9 +903,9 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
+ eloc.logicalBlockNum = block;
+ eloc.partitionReferenceNum =
+ iinfo->i_location.partitionReferenceNum;
+- elen = inode->i_sb->s_blocksize;
+- iinfo->i_lenExtents = elen;
+- udf_add_aext(inode, &epos, eloc, elen, 0);
++ bsize = inode->i_sb->s_blocksize;
++ iinfo->i_lenExtents = bsize;
++ udf_add_aext(inode, &epos, eloc, bsize, 0);
+ brelse(epos.bh);
+
+ block = udf_get_pblock(inode->i_sb, block,
@@ -1089,6 +1022,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
err = 0;
@@ -758699,7 +1011897,7 @@
+ return retblk;
+}
diff --git a/fs/udf/super.c b/fs/udf/super.c
-index f3ac4ab..b564fc1 100644
+index f3ac4ab..9fb18a3 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -55,9 +55,10 @@
@@ -758739,6 +1011937,15 @@
struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi)
{
+@@ -242,7 +240,7 @@ static int udf_sb_alloc_partition_maps(struct super_block *sb, u32 count)
+ sbi->s_partmaps = kcalloc(count, sizeof(struct udf_part_map),
+ GFP_KERNEL);
+ if (!sbi->s_partmaps) {
+- udf_error(sb, __FUNCTION__,
++ udf_error(sb, __func__,
+ "Unable to allocate space for %d partition maps",
+ count);
+ sbi->s_partitions = 0;
@@ -587,48 +585,10 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
return 0;
}
@@ -759241,6 +1012448,15 @@
}
static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)
+@@ -1047,7 +1086,7 @@ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)
+ bitmap = vmalloc(size); /* TODO: get rid of vmalloc */
+
+ if (bitmap == NULL) {
+- udf_error(sb, __FUNCTION__,
++ udf_error(sb, __func__,
+ "Unable to allocate space for bitmap "
+ "and %d buffer_head pointers", nr_groups);
+ return NULL;
@@ -1059,134 +1098,241 @@ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)
return bitmap;
}
@@ -761006,6 +1014222,198 @@
newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12];
newName[newIndex++] = hexChar[(valueCRC & 0x0f00) >> 8];
newName[newIndex++] = hexChar[(valueCRC & 0x00f0) >> 4];
+diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
+index 1e7598f..0d9ada1 100644
+--- a/fs/ufs/balloc.c
++++ b/fs/ufs/balloc.c
+@@ -277,7 +277,7 @@ static void ufs_change_blocknr(struct inode *inode, sector_t beg,
+ if (!page)/* it was truncated */
+ continue;
+ if (IS_ERR(page)) {/* or EIO */
+- ufs_error(inode->i_sb, __FUNCTION__,
++ ufs_error(inode->i_sb, __func__,
+ "read of page %llu failed\n",
+ (unsigned long long)index);
+ continue;
+@@ -308,7 +308,7 @@ static void ufs_change_blocknr(struct inode *inode, sector_t beg,
+ ll_rw_block(READ, 1, &bh);
+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh)) {
+- ufs_error(inode->i_sb, __FUNCTION__,
++ ufs_error(inode->i_sb, __func__,
+ "read of block failed\n");
+ break;
+ }
+diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
+index ef563fc..df0bef1 100644
+--- a/fs/ufs/dir.c
++++ b/fs/ufs/dir.c
+@@ -179,7 +179,7 @@ bad_entry:
+ goto fail;
+ Eend:
+ p = (struct ufs_dir_entry *)(kaddr + offs);
+- ufs_error(sb, __FUNCTION__,
++ ufs_error(sb, __func__,
+ "entry in directory #%lu spans the page boundary"
+ "offset=%lu",
+ dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs);
+@@ -284,7 +284,7 @@ struct ufs_dir_entry *ufs_find_entry(struct inode *dir, struct dentry *dentry,
+ kaddr += ufs_last_byte(dir, n) - reclen;
+ while ((char *) de <= kaddr) {
+ if (de->d_reclen == 0) {
+- ufs_error(dir->i_sb, __FUNCTION__,
++ ufs_error(dir->i_sb, __func__,
+ "zero-length directory entry");
+ ufs_put_page(page);
+ goto out;
+@@ -356,7 +356,7 @@ int ufs_add_link(struct dentry *dentry, struct inode *inode)
+ goto got_it;
+ }
+ if (de->d_reclen == 0) {
+- ufs_error(dir->i_sb, __FUNCTION__,
++ ufs_error(dir->i_sb, __func__,
+ "zero-length directory entry");
+ err = -EIO;
+ goto out_unlock;
+@@ -456,7 +456,7 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ struct page *page = ufs_get_page(inode, n);
+
+ if (IS_ERR(page)) {
+- ufs_error(sb, __FUNCTION__,
++ ufs_error(sb, __func__,
+ "bad page in #%lu",
+ inode->i_ino);
+ filp->f_pos += PAGE_CACHE_SIZE - offset;
+@@ -475,7 +475,7 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ limit = kaddr + ufs_last_byte(inode, n) - UFS_DIR_REC_LEN(1);
+ for ( ;(char*)de <= limit; de = ufs_next_entry(sb, de)) {
+ if (de->d_reclen == 0) {
+- ufs_error(sb, __FUNCTION__,
++ ufs_error(sb, __func__,
+ "zero-length directory entry");
+ ufs_put_page(page);
+ return -EIO;
+@@ -536,7 +536,7 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir,
+
+ while ((char*)de < (char*)dir) {
+ if (de->d_reclen == 0) {
+- ufs_error(inode->i_sb, __FUNCTION__,
++ ufs_error(inode->i_sb, __func__,
+ "zero-length directory entry");
+ err = -EIO;
+ goto out;
+@@ -633,7 +633,7 @@ int ufs_empty_dir(struct inode * inode)
+
+ while ((char *)de <= kaddr) {
+ if (de->d_reclen == 0) {
+- ufs_error(inode->i_sb, __FUNCTION__,
++ ufs_error(inode->i_sb, __func__,
+ "zero-length directory entry: "
+ "kaddr=%p, de=%p\n", kaddr, de);
+ goto not_empty;
+diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
+index 5446b88..39f8778 100644
+--- a/fs/ufs/inode.c
++++ b/fs/ufs/inode.c
+@@ -929,7 +929,7 @@ void ufs_delete_inode (struct inode * inode)
+ old_i_size = inode->i_size;
+ inode->i_size = 0;
+ if (inode->i_blocks && ufs_truncate(inode, old_i_size))
+- ufs_warning(inode->i_sb, __FUNCTION__, "ufs_truncate failed\n");
++ ufs_warning(inode->i_sb, __func__, "ufs_truncate failed\n");
+ ufs_free_inode (inode);
+ unlock_kernel();
+ return;
+diff --git a/fs/ufs/swab.h b/fs/ufs/swab.h
+index 1683d2b..8d974c4 100644
+--- a/fs/ufs/swab.h
++++ b/fs/ufs/swab.h
+@@ -40,25 +40,7 @@ cpu_to_fs64(struct super_block *sbp, u64 n)
+ return (__force __fs64)cpu_to_be64(n);
+ }
+
+-static __inline u32
+-fs64_add(struct super_block *sbp, u32 *n, int d)
+-{
+- if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
+- return *n = cpu_to_le64(le64_to_cpu(*n)+d);
+- else
+- return *n = cpu_to_be64(be64_to_cpu(*n)+d);
+-}
+-
+-static __inline u32
+-fs64_sub(struct super_block *sbp, u32 *n, int d)
+-{
+- if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
+- return *n = cpu_to_le64(le64_to_cpu(*n)-d);
+- else
+- return *n = cpu_to_be64(be64_to_cpu(*n)-d);
+-}
+-
+-static __inline u32
++static inline u32
+ fs32_to_cpu(struct super_block *sbp, __fs32 n)
+ {
+ if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
+@@ -80,18 +62,18 @@ static inline void
+ fs32_add(struct super_block *sbp, __fs32 *n, int d)
+ {
+ if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
+- *(__le32 *)n = cpu_to_le32(le32_to_cpu(*(__le32 *)n)+d);
++ le32_add_cpu((__le32 *)n, d);
+ else
+- *(__be32 *)n = cpu_to_be32(be32_to_cpu(*(__be32 *)n)+d);
++ be32_add_cpu((__be32 *)n, d);
+ }
+
+ static inline void
+ fs32_sub(struct super_block *sbp, __fs32 *n, int d)
+ {
+ if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
+- *(__le32 *)n = cpu_to_le32(le32_to_cpu(*(__le32 *)n)-d);
++ le32_add_cpu((__le32 *)n, -d);
+ else
+- *(__be32 *)n = cpu_to_be32(be32_to_cpu(*(__be32 *)n)-d);
++ be32_add_cpu((__be32 *)n, -d);
+ }
+
+ static inline u16
+@@ -116,18 +98,18 @@ static inline void
+ fs16_add(struct super_block *sbp, __fs16 *n, int d)
+ {
+ if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
+- *(__le16 *)n = cpu_to_le16(le16_to_cpu(*(__le16 *)n)+d);
++ le16_add_cpu((__le16 *)n, d);
+ else
+- *(__be16 *)n = cpu_to_be16(be16_to_cpu(*(__be16 *)n)+d);
++ be16_add_cpu((__be16 *)n, d);
+ }
+
+ static inline void
+ fs16_sub(struct super_block *sbp, __fs16 *n, int d)
+ {
+ if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
+- *(__le16 *)n = cpu_to_le16(le16_to_cpu(*(__le16 *)n)-d);
++ le16_add_cpu((__le16 *)n, -d);
+ else
+- *(__be16 *)n = cpu_to_be16(be16_to_cpu(*(__be16 *)n)-d);
++ be16_add_cpu((__be16 *)n, -d);
+ }
+
+ #endif /* _UFS_SWAB_H */
+diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h
+index fcb9231..244a1aa 100644
+--- a/fs/ufs/ufs.h
++++ b/fs/ufs/ufs.h
+@@ -66,7 +66,7 @@ struct ufs_inode_info {
+ #ifdef CONFIG_UFS_DEBUG
+ # define UFSD(f, a...) { \
+ printk ("UFSD (%s, %d): %s:", \
+- __FILE__, __LINE__, __FUNCTION__); \
++ __FILE__, __LINE__, __func__); \
+ printk (f, ## a); \
+ }
+ #else
diff --git a/fs/utimes.c b/fs/utimes.c
index b18da9c..a2bef77 100644
--- a/fs/utimes.c
@@ -761086,8 +1014494,132 @@
dput_and_out:
if (f)
fput(f);
+diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
+index cd450be..a352272 100644
+--- a/fs/vfat/namei.c
++++ b/fs/vfat/namei.c
+@@ -176,15 +176,10 @@ static inline int vfat_is_used_badchars(const wchar_t *s, int len)
+ for (i = 0; i < len; i++)
+ if (vfat_bad_char(s[i]))
+ return -EINVAL;
+- return 0;
+-}
+
+-static int vfat_valid_longname(const unsigned char *name, unsigned int len)
+-{
+- if (name[len - 1] == ' ')
++ if (s[i - 1] == ' ') /* last character cannot be space */
+ return -EINVAL;
+- if (len >= 256)
+- return -ENAMETOOLONG;
++
+ return 0;
+ }
+
+@@ -477,7 +472,7 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname,
+ if (utf8) {
+ int name_len = strlen(name);
+
+- *outlen = utf8_mbstowcs((wchar_t *)outname, name, PAGE_SIZE);
++ *outlen = utf8_mbstowcs((wchar_t *)outname, name, PATH_MAX);
+
+ /*
+ * We stripped '.'s before and set len appropriately,
+@@ -485,11 +480,14 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname,
+ */
+ *outlen -= (name_len - len);
+
++ if (*outlen > 255)
++ return -ENAMETOOLONG;
++
+ op = &outname[*outlen * sizeof(wchar_t)];
+ } else {
+ if (nls) {
+ for (i = 0, ip = name, op = outname, *outlen = 0;
+- i < len && *outlen <= 260;
++ i < len && *outlen <= 255;
+ *outlen += 1)
+ {
+ if (escape && (*ip == ':')) {
+@@ -525,18 +523,20 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname,
+ op += 2;
+ }
+ }
++ if (i < len)
++ return -ENAMETOOLONG;
+ } else {
+ for (i = 0, ip = name, op = outname, *outlen = 0;
+- i < len && *outlen <= 260;
++ i < len && *outlen <= 255;
+ i++, *outlen += 1)
+ {
+ *op++ = *ip++;
+ *op++ = 0;
+ }
++ if (i < len)
++ return -ENAMETOOLONG;
+ }
+ }
+- if (*outlen > 260)
+- return -ENAMETOOLONG;
+
+ *longlen = *outlen;
+ if (*outlen % 13) {
+@@ -565,7 +565,6 @@ static int vfat_build_slots(struct inode *dir, const unsigned char *name,
+ struct fat_mount_options *opts = &sbi->options;
+ struct msdos_dir_slot *ps;
+ struct msdos_dir_entry *de;
+- unsigned long page;
+ unsigned char cksum, lcase;
+ unsigned char msdos_name[MSDOS_NAME];
+ wchar_t *uname;
+@@ -574,15 +573,11 @@ static int vfat_build_slots(struct inode *dir, const unsigned char *name,
+ loff_t offset;
+
+ *nr_slots = 0;
+- err = vfat_valid_longname(name, len);
+- if (err)
+- return err;
+
+- page = __get_free_page(GFP_KERNEL);
+- if (!page)
++ uname = __getname();
++ if (!uname)
+ return -ENOMEM;
+
+- uname = (wchar_t *)page;
+ err = xlate_to_uni(name, len, (unsigned char *)uname, &ulen, &usize,
+ opts->unicode_xlate, opts->utf8, sbi->nls_io);
+ if (err)
+@@ -634,7 +629,7 @@ shortname:
+ de->starthi = cpu_to_le16(cluster >> 16);
+ de->size = 0;
+ out_free:
+- free_page(page);
++ __putname(uname);
+ return err;
+ }
+
+@@ -991,7 +986,7 @@ error_inode:
+ if (corrupt < 0) {
+ fat_fs_panic(new_dir->i_sb,
+ "%s: Filesystem corrupted (i_pos %lld)",
+- __FUNCTION__, sinfo.i_pos);
++ __func__, sinfo.i_pos);
+ }
+ goto out;
+ }
+@@ -1003,7 +998,7 @@ static const struct inode_operations vfat_dir_inode_operations = {
+ .mkdir = vfat_mkdir,
+ .rmdir = vfat_rmdir,
+ .rename = vfat_rename,
+- .setattr = fat_notify_change,
++ .setattr = fat_setattr,
+ .getattr = fat_getattr,
+ };
+
diff --git a/fs/xattr.c b/fs/xattr.c
-index 3acab16..89a942f 100644
+index 3acab16..4706a8b 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -11,6 +11,7 @@
@@ -761107,7 +1014639,54 @@
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
return -EPERM;
}
-@@ -262,7 +261,11 @@ sys_setxattr(char __user *path, char __user *name, void __user *value,
+@@ -68,7 +67,7 @@ xattr_permission(struct inode *inode, const char *name, int mask)
+ }
+
+ int
+-vfs_setxattr(struct dentry *dentry, char *name, void *value,
++vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
+ size_t size, int flags)
+ {
+ struct inode *inode = dentry->d_inode;
+@@ -132,7 +131,7 @@ out_noalloc:
+ EXPORT_SYMBOL_GPL(xattr_getsecurity);
+
+ ssize_t
+-vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
++vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
+ {
+ struct inode *inode = dentry->d_inode;
+ int error;
+@@ -188,7 +187,7 @@ vfs_listxattr(struct dentry *d, char *list, size_t size)
+ EXPORT_SYMBOL_GPL(vfs_listxattr);
+
+ int
+-vfs_removexattr(struct dentry *dentry, char *name)
++vfs_removexattr(struct dentry *dentry, const char *name)
+ {
+ struct inode *inode = dentry->d_inode;
+ int error;
+@@ -219,7 +218,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
+ * Extended attribute SET operations
+ */
+ static long
+-setxattr(struct dentry *d, char __user *name, void __user *value,
++setxattr(struct dentry *d, const char __user *name, const void __user *value,
+ size_t size, int flags)
+ {
+ int error;
+@@ -253,8 +252,8 @@ setxattr(struct dentry *d, char __user *name, void __user *value,
+ }
+
+ asmlinkage long
+-sys_setxattr(char __user *path, char __user *name, void __user *value,
+- size_t size, int flags)
++sys_setxattr(const char __user *path, const char __user *name,
++ const void __user *value, size_t size, int flags)
+ {
+ struct nameidata nd;
+ int error;
+@@ -262,14 +261,18 @@ sys_setxattr(char __user *path, char __user *name, void __user *value,
error = user_path_walk(path, &nd);
if (error)
return error;
@@ -761120,7 +1014699,16 @@
path_put(&nd.path);
return error;
}
-@@ -277,7 +280,11 @@ sys_lsetxattr(char __user *path, char __user *name, void __user *value,
+
+ asmlinkage long
+-sys_lsetxattr(char __user *path, char __user *name, void __user *value,
+- size_t size, int flags)
++sys_lsetxattr(const char __user *path, const char __user *name,
++ const void __user *value, size_t size, int flags)
+ {
+ struct nameidata nd;
+ int error;
+@@ -277,13 +280,17 @@ sys_lsetxattr(char __user *path, char __user *name, void __user *value,
error = user_path_walk_link(path, &nd);
if (error)
return error;
@@ -761133,6 +1014721,13 @@
path_put(&nd.path);
return error;
}
+
+ asmlinkage long
+-sys_fsetxattr(int fd, char __user *name, void __user *value,
++sys_fsetxattr(int fd, const char __user *name, const void __user *value,
+ size_t size, int flags)
+ {
+ struct file *f;
@@ -295,7 +302,11 @@ sys_fsetxattr(int fd, char __user *name, void __user *value,
return error;
dentry = f->f_path.dentry;
@@ -761146,7 +1014741,82 @@
fput(f);
return error;
}
-@@ -482,7 +493,11 @@ sys_removexattr(char __user *path, char __user *name)
+@@ -304,7 +315,8 @@ sys_fsetxattr(int fd, char __user *name, void __user *value,
+ * Extended attribute GET operations
+ */
+ static ssize_t
+-getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
++getxattr(struct dentry *d, const char __user *name, void __user *value,
++ size_t size)
+ {
+ ssize_t error;
+ void *kvalue = NULL;
+@@ -338,8 +350,8 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
+ }
+
+ asmlinkage ssize_t
+-sys_getxattr(char __user *path, char __user *name, void __user *value,
+- size_t size)
++sys_getxattr(const char __user *path, const char __user *name,
++ void __user *value, size_t size)
+ {
+ struct nameidata nd;
+ ssize_t error;
+@@ -353,7 +365,7 @@ sys_getxattr(char __user *path, char __user *name, void __user *value,
+ }
+
+ asmlinkage ssize_t
+-sys_lgetxattr(char __user *path, char __user *name, void __user *value,
++sys_lgetxattr(const char __user *path, const char __user *name, void __user *value,
+ size_t size)
+ {
+ struct nameidata nd;
+@@ -368,7 +380,7 @@ sys_lgetxattr(char __user *path, char __user *name, void __user *value,
+ }
+
+ asmlinkage ssize_t
+-sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size)
++sys_fgetxattr(int fd, const char __user *name, void __user *value, size_t size)
+ {
+ struct file *f;
+ ssize_t error = -EBADF;
+@@ -413,7 +425,7 @@ listxattr(struct dentry *d, char __user *list, size_t size)
+ }
+
+ asmlinkage ssize_t
+-sys_listxattr(char __user *path, char __user *list, size_t size)
++sys_listxattr(const char __user *path, char __user *list, size_t size)
+ {
+ struct nameidata nd;
+ ssize_t error;
+@@ -427,7 +439,7 @@ sys_listxattr(char __user *path, char __user *list, size_t size)
+ }
+
+ asmlinkage ssize_t
+-sys_llistxattr(char __user *path, char __user *list, size_t size)
++sys_llistxattr(const char __user *path, char __user *list, size_t size)
+ {
+ struct nameidata nd;
+ ssize_t error;
+@@ -459,7 +471,7 @@ sys_flistxattr(int fd, char __user *list, size_t size)
+ * Extended attribute REMOVE operations
+ */
+ static long
+-removexattr(struct dentry *d, char __user *name)
++removexattr(struct dentry *d, const char __user *name)
+ {
+ int error;
+ char kname[XATTR_NAME_MAX + 1];
+@@ -474,7 +486,7 @@ removexattr(struct dentry *d, char __user *name)
+ }
+
+ asmlinkage long
+-sys_removexattr(char __user *path, char __user *name)
++sys_removexattr(const char __user *path, const char __user *name)
+ {
+ struct nameidata nd;
+ int error;
+@@ -482,13 +494,17 @@ sys_removexattr(char __user *path, char __user *name)
error = user_path_walk(path, &nd);
if (error)
return error;
@@ -761159,7 +1014829,14 @@
path_put(&nd.path);
return error;
}
-@@ -496,7 +511,11 @@ sys_lremovexattr(char __user *path, char __user *name)
+
+ asmlinkage long
+-sys_lremovexattr(char __user *path, char __user *name)
++sys_lremovexattr(const char __user *path, const char __user *name)
+ {
+ struct nameidata nd;
+ int error;
+@@ -496,13 +512,17 @@ sys_lremovexattr(char __user *path, char __user *name)
error = user_path_walk_link(path, &nd);
if (error)
return error;
@@ -761172,7 +1014849,14 @@
path_put(&nd.path);
return error;
}
-@@ -513,7 +532,11 @@ sys_fremovexattr(int fd, char __user *name)
+
+ asmlinkage long
+-sys_fremovexattr(int fd, char __user *name)
++sys_fremovexattr(int fd, const char __user *name)
+ {
+ struct file *f;
+ struct dentry *dentry;
+@@ -513,7 +533,11 @@ sys_fremovexattr(int fd, char __user *name)
return error;
dentry = f->f_path.dentry;
audit_inode(NULL, dentry);
@@ -761186,7 +1014870,7 @@
return error;
}
diff --git a/fs/xfs/Kconfig b/fs/xfs/Kconfig
-index 35115bc..524021f 100644
+index 35115bc..3f53dd1 100644
--- a/fs/xfs/Kconfig
+++ b/fs/xfs/Kconfig
@@ -35,18 +35,6 @@ config XFS_QUOTA
@@ -761208,6 +1014892,23 @@
config XFS_POSIX_ACL
bool "XFS POSIX ACL support"
depends on XFS_FS
+@@ -76,3 +64,16 @@ config XFS_RT
+ See the xfs man page in section 5 for additional information.
+
+ If unsure, say N.
++
++config XFS_DEBUG
++ bool "XFS Debugging support (EXPERIMENTAL)"
++ depends on XFS_FS && EXPERIMENTAL
++ help
++ Say Y here to get an XFS build with many debugging features,
++ including ASSERT checks, function wrappers around macros,
++ and extra sanity-checking functions in various code paths.
++
++ Note that the resulting code will be HUGE and SLOW, and probably
++ not useful unless you are debugging a particular problem.
++
++ Say N unless you are an XFS developer, or you play one on TV.
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
@@ -761239,6 +1014940,115 @@
congestion_wait(WRITE, HZ/50);
} while (1);
}
+diff --git a/fs/xfs/linux-2.6/mrlock.h b/fs/xfs/linux-2.6/mrlock.h
+index c110bb0..ff6a198 100644
+--- a/fs/xfs/linux-2.6/mrlock.h
++++ b/fs/xfs/linux-2.6/mrlock.h
+@@ -20,29 +20,24 @@
+
+ #include <linux/rwsem.h>
+
+-enum { MR_NONE, MR_ACCESS, MR_UPDATE };
+-
+ typedef struct {
+ struct rw_semaphore mr_lock;
++#ifdef DEBUG
+ int mr_writer;
++#endif
+ } mrlock_t;
+
++#ifdef DEBUG
+ #define mrinit(mrp, name) \
+ do { (mrp)->mr_writer = 0; init_rwsem(&(mrp)->mr_lock); } while (0)
++#else
++#define mrinit(mrp, name) \
++ do { init_rwsem(&(mrp)->mr_lock); } while (0)
++#endif
++
+ #define mrlock_init(mrp, t,n,s) mrinit(mrp, n)
+ #define mrfree(mrp) do { } while (0)
+
+-static inline void mraccess(mrlock_t *mrp)
+-{
+- down_read(&mrp->mr_lock);
+-}
+-
+-static inline void mrupdate(mrlock_t *mrp)
+-{
+- down_write(&mrp->mr_lock);
+- mrp->mr_writer = 1;
+-}
+-
+ static inline void mraccess_nested(mrlock_t *mrp, int subclass)
+ {
+ down_read_nested(&mrp->mr_lock, subclass);
+@@ -51,10 +46,11 @@ static inline void mraccess_nested(mrlock_t *mrp, int subclass)
+ static inline void mrupdate_nested(mrlock_t *mrp, int subclass)
+ {
+ down_write_nested(&mrp->mr_lock, subclass);
++#ifdef DEBUG
+ mrp->mr_writer = 1;
++#endif
+ }
+
+-
+ static inline int mrtryaccess(mrlock_t *mrp)
+ {
+ return down_read_trylock(&mrp->mr_lock);
+@@ -64,39 +60,31 @@ static inline int mrtryupdate(mrlock_t *mrp)
+ {
+ if (!down_write_trylock(&mrp->mr_lock))
+ return 0;
++#ifdef DEBUG
+ mrp->mr_writer = 1;
++#endif
+ return 1;
+ }
+
+-static inline void mrunlock(mrlock_t *mrp)
++static inline void mrunlock_excl(mrlock_t *mrp)
+ {
+- if (mrp->mr_writer) {
+- mrp->mr_writer = 0;
+- up_write(&mrp->mr_lock);
+- } else {
+- up_read(&mrp->mr_lock);
+- }
++#ifdef DEBUG
++ mrp->mr_writer = 0;
++#endif
++ up_write(&mrp->mr_lock);
+ }
+
+-static inline void mrdemote(mrlock_t *mrp)
++static inline void mrunlock_shared(mrlock_t *mrp)
+ {
+- mrp->mr_writer = 0;
+- downgrade_write(&mrp->mr_lock);
++ up_read(&mrp->mr_lock);
+ }
+
+-#ifdef DEBUG
+-/*
+- * Debug-only routine, without some platform-specific asm code, we can
+- * now only answer requests regarding whether we hold the lock for write
+- * (reader state is outside our visibility, we only track writer state).
+- * Note: means !ismrlocked would give false positives, so don't do that.
+- */
+-static inline int ismrlocked(mrlock_t *mrp, int type)
++static inline void mrdemote(mrlock_t *mrp)
+ {
+- if (mrp && type == MR_UPDATE)
+- return mrp->mr_writer;
+- return 1;
+-}
++#ifdef DEBUG
++ mrp->mr_writer = 0;
+ #endif
++ downgrade_write(&mrp->mr_lock);
++}
+
+ #endif /* __XFS_SUPPORT_MRLOCK_H__ */
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
@@ -761285,7 +1015095,7 @@
}
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
-index e347bfd..52f6846 100644
+index e347bfd..5105015 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(
@@ -761315,6 +1015125,15 @@
goto fail_free_mem;
}
+@@ -886,7 +886,7 @@ int
+ xfs_buf_lock_value(
+ xfs_buf_t *bp)
+ {
+- return atomic_read(&bp->b_sema.count);
++ return bp->b_sema.count;
+ }
+ #endif
+
@@ -1060,7 +1060,7 @@ xfs_buf_iostart(
bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_ASYNC);
bp->b_flags |= flags & (XBF_DELWRI | XBF_ASYNC);
@@ -761360,7 +1015179,7 @@
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
+index ca4f66c..c672b32 100644
--- a/fs/xfs/linux-2.6/xfs_export.c
+++ b/fs/xfs/linux-2.6/xfs_export.c
@@ -22,6 +22,7 @@
@@ -761389,6 +1015208,15 @@
fileid_type = FILEID_INO32_GEN;
else
fileid_type = FILEID_INO32_GEN_PARENT;
+@@ -134,7 +133,7 @@ xfs_nfs_get_inode(
+ if (!ip)
+ return ERR_PTR(-EIO);
+
+- if (!ip->i_d.di_mode || ip->i_d.di_gen != generation) {
++ if (ip->i_d.di_gen != generation) {
+ xfs_iput_new(ip, XFS_ILOCK_SHARED);
+ return ERR_PTR(-ENOENT);
+ }
@@ -213,17 +212,16 @@ xfs_fs_get_parent(
struct dentry *child)
{
@@ -761412,15 +1015240,91 @@
}
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
+index edab1ff..65e78c1 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);
+@@ -43,9 +43,6 @@
+ #include <linux/smp_lock.h>
+ static struct vm_operations_struct xfs_file_vm_ops;
+-#ifdef CONFIG_XFS_DMAPI
+-static struct vm_operations_struct xfs_dmapi_file_vm_ops;
+-#endif
+
+ STATIC_INLINE ssize_t
+ __xfs_file_read(
+@@ -202,22 +199,6 @@ xfs_file_fsync(
+ (xfs_off_t)0, (xfs_off_t)-1);
+ }
+
+-#ifdef CONFIG_XFS_DMAPI
+-STATIC int
+-xfs_vm_fault(
+- struct vm_area_struct *vma,
+- struct vm_fault *vmf)
+-{
+- struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+- bhv_vnode_t *vp = vn_from_inode(inode);
+-
+- ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI);
+- if (XFS_SEND_MMAP(XFS_VFSTOM(vp->v_vfsp), vma, 0))
+- return VM_FAULT_SIGBUS;
+- return filemap_fault(vma, vmf);
+-}
+-#endif /* CONFIG_XFS_DMAPI */
+-
+ /*
+ * Unfortunately we can't just use the clean and simple readdir implementation
+ * below, because nfs might call back into ->lookup from the filldir callback
+@@ -386,11 +367,6 @@ xfs_file_mmap(
+ vma->vm_ops = &xfs_file_vm_ops;
+ vma->vm_flags |= VM_CAN_NONLINEAR;
+
+-#ifdef CONFIG_XFS_DMAPI
+- if (XFS_M(filp->f_path.dentry->d_inode->i_sb)->m_flags & XFS_MOUNT_DMAPI)
+- vma->vm_ops = &xfs_dmapi_file_vm_ops;
+-#endif /* CONFIG_XFS_DMAPI */
+-
+ file_accessed(filp);
+ return 0;
+ }
+@@ -437,52 +413,6 @@ xfs_file_ioctl_invis(
+ return error;
+ }
+
+-#ifdef CONFIG_XFS_DMAPI
+-#ifdef HAVE_VMOP_MPROTECT
+-STATIC int
+-xfs_vm_mprotect(
+- struct vm_area_struct *vma,
+- unsigned int newflags)
+-{
+- struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+- struct xfs_mount *mp = XFS_M(inode->i_sb);
+- int error = 0;
+-
+- if (mp->m_flags & XFS_MOUNT_DMAPI) {
+- if ((vma->vm_flags & VM_MAYSHARE) &&
+- (newflags & VM_WRITE) && !(vma->vm_flags & VM_WRITE))
+- error = XFS_SEND_MMAP(mp, vma, VM_WRITE);
+- }
+- return error;
+-}
+-#endif /* HAVE_VMOP_MPROTECT */
+-#endif /* CONFIG_XFS_DMAPI */
+-
+-#ifdef HAVE_FOP_OPEN_EXEC
+-/* If the user is attempting to execute a file that is offline then
+- * we have to trigger a DMAPI READ event before the file is marked as busy
+- * otherwise the invisible I/O will not be able to write to the file to bring
+- * it back online.
+- */
+-STATIC int
+-xfs_file_open_exec(
+- struct inode *inode)
+-{
+- struct xfs_mount *mp = XFS_M(inode->i_sb);
+-
- 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);
@@ -761430,12 +1015334,27 @@
- }
- }
-
-+ 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 */
+- return 0;
+-}
+-#endif /* HAVE_FOP_OPEN_EXEC */
+-
+ /*
+ * mmap()d file has taken write protection fault and is being made
+ * writable. We can set the page state up correctly for a writable
+@@ -551,13 +481,3 @@ static struct vm_operations_struct xfs_file_vm_ops = {
+ .fault = filemap_fault,
+ .page_mkwrite = xfs_vm_page_mkwrite,
+ };
+-
+-#ifdef CONFIG_XFS_DMAPI
+-static struct vm_operations_struct xfs_dmapi_file_vm_ops = {
+- .fault = xfs_vm_fault,
+- .page_mkwrite = xfs_vm_page_mkwrite,
+-#ifdef HAVE_VMOP_MPROTECT
+- .mprotect = xfs_vm_mprotect,
+-#endif
+-};
+-#endif /* CONFIG_XFS_DMAPI */
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
@@ -761517,9 +1015436,35 @@
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
+index f34bd01..a42ba9d 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
+@@ -238,7 +238,7 @@ xfs_vget_fsop_handlereq(
+ return error;
+ if (ip == NULL)
+ return XFS_ERROR(EIO);
+- if (ip->i_d.di_mode == 0 || ip->i_d.di_gen != igen) {
++ if (ip->i_d.di_gen != igen) {
+ xfs_iput_new(ip, XFS_ILOCK_SHARED);
+ return XFS_ERROR(ENOENT);
+ }
+@@ -505,14 +505,14 @@ xfs_attrmulti_attr_get(
+ {
+ char *kbuf;
+ int error = EFAULT;
+-
++
+ if (*len > XATTR_SIZE_MAX)
+ return EINVAL;
+ kbuf = kmalloc(*len, GFP_KERNEL);
+ if (!kbuf)
+ return ENOMEM;
+
+- error = xfs_attr_get(XFS_I(inode), name, kbuf, (int *)len, flags, NULL);
++ error = xfs_attr_get(XFS_I(inode), name, kbuf, (int *)len, flags);
+ if (error)
+ goto out_kfree;
+
@@ -535,8 +535,6 @@ xfs_attrmulti_attr_set(
char *kbuf;
int error = EFAULT;
@@ -761529,6 +1015474,15 @@
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
return EPERM;
if (len > XATTR_SIZE_MAX)
+@@ -548,7 +546,7 @@ xfs_attrmulti_attr_set(
+
+ if (copy_from_user(kbuf, ubuf, len))
+ goto out_kfree;
+-
++
+ error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags);
+
+ out_kfree:
@@ -562,8 +560,6 @@ xfs_attrmulti_attr_remove(
char *name,
__uint32_t flags)
@@ -762286,7 +1016240,7 @@
+ }
+}
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
-index cc4abd3..a1237da 100644
+index cc4abd3..2bf287e 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -62,12 +62,11 @@ void
@@ -762673,7 +1016627,7 @@
if (likely(!error)) {
xfs_validate_fields(inode);
xfs_validate_fields(dir);
-@@ -494,12 +503,15 @@ xfs_vn_rename(
+@@ -494,12 +503,16 @@ xfs_vn_rename(
struct dentry *ndentry)
{
struct inode *new_inode = ndentry->d_inode;
@@ -762688,11 +1016642,12 @@
- 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);
++ XFS_I(ndir), &nname, new_inode ?
++ XFS_I(new_inode) : NULL);
if (likely(!error)) {
if (new_inode)
xfs_validate_fields(new_inode);
-@@ -700,11 +712,19 @@ xfs_vn_setattr(
+@@ -700,11 +713,19 @@ xfs_vn_setattr(
return -error;
}
@@ -762714,19 +1016669,28 @@
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
+index 3ca39c4..4edc469 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
-@@ -99,7 +99,6 @@
+@@ -75,6 +75,7 @@
+ #include <linux/delay.h>
+ #include <linux/log2.h>
+ #include <linux/spinlock.h>
++#include <linux/random.h>
+
+ #include <asm/page.h>
+ #include <asm/div64.h>
+@@ -99,8 +100,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 */
+-#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 */
+ #else
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
-index 1663533..1ebd800 100644
+index 1663533..5e3b575 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -51,6 +51,7 @@
@@ -762815,7 +1016779,88 @@
if (error) {
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
return -error;
-@@ -573,14 +571,12 @@ xfs_write(
+@@ -396,7 +394,7 @@ xfs_zero_last_block(
+ int error = 0;
+ xfs_bmbt_irec_t imap;
+
+- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0);
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+
+ zero_offset = XFS_B_FSB_OFFSET(mp, isize);
+ if (zero_offset == 0) {
+@@ -427,14 +425,14 @@ xfs_zero_last_block(
+ * out sync. We need to drop the ilock while we do this so we
+ * don't deadlock when the buffer cache calls back to us.
+ */
+- xfs_iunlock(ip, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD);
++ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+
+ zero_len = mp->m_sb.sb_blocksize - zero_offset;
+ if (isize + zero_len > offset)
+ zero_len = offset - isize;
+ error = xfs_iozero(ip, isize, zero_len);
+
+- xfs_ilock(ip, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
++ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ ASSERT(error >= 0);
+ return error;
+ }
+@@ -467,8 +465,7 @@ xfs_zero_eof(
+ int error = 0;
+ xfs_bmbt_irec_t imap;
+
+- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
+- ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
+ ASSERT(offset > isize);
+
+ /*
+@@ -477,8 +474,7 @@ xfs_zero_eof(
+ */
+ error = xfs_zero_last_block(ip, offset, isize);
+ if (error) {
+- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
+- ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
+ return error;
+ }
+
+@@ -509,8 +505,7 @@ xfs_zero_eof(
+ error = xfs_bmapi(NULL, ip, start_zero_fsb, zero_count_fsb,
+ 0, NULL, 0, &imap, &nimaps, NULL, NULL);
+ if (error) {
+- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
+- ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
+ return error;
+ }
+ ASSERT(nimaps > 0);
+@@ -534,7 +529,7 @@ xfs_zero_eof(
+ * Drop the inode lock while we're doing the I/O.
+ * We'll still have the iolock to protect us.
+ */
+- xfs_iunlock(ip, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
++ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+
+ zero_off = XFS_FSB_TO_B(mp, start_zero_fsb);
+ zero_len = XFS_FSB_TO_B(mp, imap.br_blockcount);
+@@ -550,13 +545,13 @@ xfs_zero_eof(
+ start_zero_fsb = imap.br_startoff + imap.br_blockcount;
+ ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
+
+- xfs_ilock(ip, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
++ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ }
+
+ return 0;
+
+ out_lock:
+- xfs_ilock(ip, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
++ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ ASSERT(error >= 0);
+ return error;
+ }
+@@ -573,14 +568,12 @@ xfs_write(
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
@@ -762830,7 +1016875,7 @@
size_t ocount = 0, count;
loff_t pos;
int need_i_mutex;
-@@ -607,11 +603,9 @@ xfs_write(
+@@ -607,11 +600,9 @@ xfs_write(
relock:
if (ioflags & IO_ISDIRECT) {
iolock = XFS_IOLOCK_SHARED;
@@ -762842,7 +1016887,7 @@
need_i_mutex = 1;
mutex_lock(&inode->i_mutex);
}
-@@ -634,9 +628,8 @@ start:
+@@ -634,9 +625,8 @@ start:
dmflags |= DM_FLAGS_IMUX;
xfs_iunlock(xip, XFS_ILOCK_EXCL);
@@ -762854,7 +1016899,7 @@
if (error) {
goto out_unlock_internal;
}
-@@ -664,10 +657,9 @@ start:
+@@ -664,10 +654,9 @@ start:
return XFS_ERROR(-EINVAL);
}
@@ -762866,7 +1016911,7 @@
need_i_mutex = 1;
mutex_lock(&inode->i_mutex);
xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
-@@ -679,10 +671,16 @@ start:
+@@ -679,10 +668,16 @@ start:
if (new_size > xip->i_size)
xip->i_new_size = new_size;
@@ -762884,7 +1016929,7 @@
}
/*
-@@ -727,7 +725,7 @@ retry:
+@@ -727,7 +722,7 @@ retry:
current->backing_dev_info = mapping->backing_dev_info;
if ((ioflags & IO_ISDIRECT)) {
@@ -762893,7 +1016938,7 @@
WARN_ON(need_i_mutex == 0);
xfs_inval_cached_trace(xip, pos, -1,
(pos & PAGE_CACHE_MASK), -1);
-@@ -744,7 +742,6 @@ retry:
+@@ -744,7 +739,6 @@ retry:
mutex_unlock(&inode->i_mutex);
iolock = XFS_IOLOCK_SHARED;
@@ -762901,7 +1016946,7 @@
need_i_mutex = 0;
}
-@@ -781,15 +778,15 @@ retry:
+@@ -781,15 +775,15 @@ retry:
if (ret == -ENOSPC &&
DM_EVENT_ENABLED(xip, DM_EVENT_NOSPACE) && !(ioflags & IO_INVIS)) {
@@ -762921,7 +1016966,7 @@
if (error)
goto out_unlock_internal;
pos = xip->i_size;
-@@ -817,7 +814,8 @@ retry:
+@@ -817,7 +811,8 @@ retry:
/* Handle various SYNC-type writes */
if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
int error2;
@@ -762931,7 +1016976,7 @@
if (need_i_mutex)
mutex_unlock(&inode->i_mutex);
error2 = sync_page_range(inode, mapping, pos, ret);
-@@ -825,7 +823,7 @@ retry:
+@@ -825,7 +820,7 @@ retry:
error = error2;
if (need_i_mutex)
mutex_lock(&inode->i_mutex);
@@ -762940,7 +1016985,7 @@
error2 = xfs_write_sync_logforce(mp, xip);
if (!error)
error = error2;
-@@ -846,7 +844,7 @@ retry:
+@@ -846,7 +841,7 @@ retry:
xip->i_d.di_size = xip->i_size;
xfs_iunlock(xip, XFS_ILOCK_EXCL);
}
@@ -762949,7 +1016994,7 @@
out_unlock_mutex:
if (need_i_mutex)
mutex_unlock(&inode->i_mutex);
-@@ -884,28 +882,23 @@ xfs_bdstrat_cb(struct xfs_buf *bp)
+@@ -884,28 +879,23 @@ xfs_bdstrat_cb(struct xfs_buf *bp)
}
/*
@@ -762985,10 +1017030,18 @@
/*
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
-index e200253..e1d498b 100644
+index e200253..e6be37d 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 *,
+@@ -50,7 +50,6 @@ struct xfs_iomap;
+ #define XFS_INVAL_CACHED 18
+ #define XFS_DIORD_ENTER 19
+ #define XFS_DIOWR_ENTER 20
+-#define XFS_SENDFILE_ENTER 21
+ #define XFS_WRITEPAGE_ENTER 22
+ #define XFS_RELEASEPAGE_ENTER 23
+ #define XFS_INVALIDPAGE_ENTER 24
+@@ -68,7 +67,8 @@ extern void xfs_inval_cached_trace(struct xfs_inode *,
#define xfs_inval_cached_trace(ip, offset, len, first, last)
#endif
@@ -763014,7 +1017067,7 @@
#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
+index 8831d95..742b2c7 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(
@@ -763046,6 +1017099,15 @@
mp->m_sync_seq++;
wake_up(&mp->m_wait_single_sync_task);
}
+@@ -1181,7 +1181,7 @@ xfs_fs_statfs(
+ statp->f_fsid.val[0] = (u32)id;
+ statp->f_fsid.val[1] = (u32)(id >> 32);
+
+- xfs_icsb_sync_counters_flags(mp, XFS_ICSB_LAZY_COUNT);
++ xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
+
+ spin_lock(&mp->m_sb_lock);
+ statp->f_bsize = sbp->sb_blocksize;
@@ -1306,7 +1306,7 @@ xfs_fs_fill_super(
void *data,
int silent)
@@ -763123,10 +1017185,10 @@
/*
* 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
+index b5ea418..9d73cb5 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;
+@@ -23,16 +23,8 @@ struct bhv_vattr;
struct xfs_iomap;
struct attrlist_cursor_kern;
@@ -763134,8 +1017196,16 @@
-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)
+-#define VN_ISLNK(vp) S_ISLNK((vp)->i_mode)
+-#define VN_ISREG(vp) S_ISREG((vp)->i_mode)
+-#define VN_ISDIR(vp) S_ISDIR((vp)->i_mode)
+-#define VN_ISCHR(vp) S_ISCHR((vp)->i_mode)
+-#define VN_ISBLK(vp) S_ISBLK((vp)->i_mode)
+-
+ /*
+ * Vnode to Linux inode mapping.
+ */
+@@ -46,18 +38,6 @@ static inline struct inode *vn_to_inode(bhv_vnode_t *vnode)
}
/*
@@ -763154,7 +1017224,7 @@
* 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 {
+@@ -73,12 +53,9 @@ typedef enum bhv_vrwlock {
#define IO_INVIS 0x00020 /* don't update inode timestamps */
/*
@@ -763168,7 +1017238,32 @@
/*
* Flush/Invalidate options for vop_toss/flush/flushinval_pages.
-@@ -226,13 +209,6 @@ static inline bhv_vnode_t *vn_grab(bhv_vnode_t *vp)
+@@ -168,24 +145,6 @@ typedef struct bhv_vattr {
+ XFS_AT_TYPE|XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_VCODE|\
+ XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|XFS_AT_GENCOUNT)
+
+-/*
+- * Modes.
+- */
+-#define VSUID S_ISUID /* set user id on execution */
+-#define VSGID S_ISGID /* set group id on execution */
+-#define VSVTX S_ISVTX /* save swapped text even after use */
+-#define VREAD S_IRUSR /* read, write, execute permissions */
+-#define VWRITE S_IWUSR
+-#define VEXEC S_IXUSR
+-
+-#define MODEMASK S_IALLUGO /* mode bits plus permission bits */
+-
+-/*
+- * Check whether mandatory file locking is enabled.
+- */
+-#define MANDLOCK(vp, mode) \
+- (VN_ISREG(vp) && ((mode) & (VSGID|(VEXEC>>3))) == VSGID)
+-
+ extern void vn_init(void);
+ extern int vn_revalidate(bhv_vnode_t *);
+
+@@ -226,13 +185,6 @@ static inline bhv_vnode_t *vn_grab(bhv_vnode_t *vp)
}
/*
@@ -763182,7 +1017277,7 @@
* 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 *);
+@@ -303,9 +255,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) \
@@ -763195,9 +1017290,27 @@
_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
+index 665babc..85df328 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
+@@ -933,7 +933,7 @@ xfs_qm_dqget(
+ type == XFS_DQ_PROJ ||
+ type == XFS_DQ_GROUP);
+ if (ip) {
+- ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+ if (type == XFS_DQ_USER)
+ ASSERT(ip->i_udquot == NULL);
+ else
+@@ -1088,7 +1088,7 @@ xfs_qm_dqget(
+ xfs_qm_mplist_unlock(mp);
+ XFS_DQ_HASH_UNLOCK(h);
+ dqret:
+- ASSERT((ip == NULL) || XFS_ISLOCKED_INODE_EXCL(ip));
++ ASSERT((ip == NULL) || xfs_isilocked(ip, XFS_ILOCK_EXCL));
+ xfs_dqtrace_entry(dqp, "DQGET DONE");
+ *O_dqpp = dqp;
+ return (0);
@@ -1291,7 +1291,7 @@ xfs_qm_dqflush(
if (flags & XFS_QMOPT_DELWRI) {
xfs_bdwrite(mp, bp);
@@ -763302,7 +1017415,7 @@
xfs_buf_relse(bp);
}
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
-index 8e9c5ae..40ea564 100644
+index 8e9c5ae..d31cce1 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -304,8 +304,11 @@ xfs_qm_unmount_quotadestroy(
@@ -763378,7 +1017491,71 @@
}
/*
-@@ -1438,7 +1438,7 @@ xfs_qm_qino_alloc(
+@@ -670,7 +670,7 @@ xfs_qm_dqattach_one(
+ xfs_dquot_t *dqp;
+ int error;
+
+- ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+ error = 0;
+ /*
+ * See if we already have it in the inode itself. IO_idqpp is
+@@ -874,7 +874,7 @@ xfs_qm_dqattach(
+ return 0;
+
+ ASSERT((flags & XFS_QMOPT_ILOCKED) == 0 ||
+- XFS_ISLOCKED_INODE_EXCL(ip));
++ xfs_isilocked(ip, XFS_ILOCK_EXCL));
+
+ if (! (flags & XFS_QMOPT_ILOCKED))
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+@@ -888,7 +888,8 @@ xfs_qm_dqattach(
+ goto done;
+ nquotas++;
+ }
+- ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
++
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+ if (XFS_IS_OQUOTA_ON(mp)) {
+ error = XFS_IS_GQUOTA_ON(mp) ?
+ xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
+@@ -913,7 +914,7 @@ xfs_qm_dqattach(
+ * This WON'T, in general, result in a thrash.
+ */
+ if (nquotas == 2) {
+- ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+ ASSERT(ip->i_udquot);
+ ASSERT(ip->i_gdquot);
+
+@@ -956,7 +957,7 @@ xfs_qm_dqattach(
+
+ #ifdef QUOTADEBUG
+ else
+- ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+ #endif
+ return error;
+ }
+@@ -1291,7 +1292,7 @@ xfs_qm_dqget_noattach(
+ xfs_mount_t *mp;
+ xfs_dquot_t *udqp, *gdqp;
+
+- ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+ mp = ip->i_mount;
+ udqp = NULL;
+ gdqp = NULL;
+@@ -1392,7 +1393,7 @@ xfs_qm_qino_alloc(
+ * Keep an extra reference to this quota inode. This inode is
+ * locked exclusively and joined to the transaction already.
+ */
+- ASSERT(XFS_ISLOCKED_INODE_EXCL(*ip));
++ ASSERT(xfs_isilocked(*ip, XFS_ILOCK_EXCL));
+ VN_HOLD(XFS_ITOV((*ip)));
+
+ /*
+@@ -1438,7 +1439,7 @@ xfs_qm_qino_alloc(
}
@@ -763387,7 +1017564,7 @@
xfs_qm_reset_dqcounts(
xfs_mount_t *mp,
xfs_buf_t *bp,
-@@ -1478,8 +1478,6 @@ xfs_qm_reset_dqcounts(
+@@ -1478,8 +1479,6 @@ xfs_qm_reset_dqcounts(
ddq->d_rtbwarns = 0;
ddq = (xfs_disk_dquot_t *) ((xfs_dqblk_t *)ddq + 1);
}
@@ -763396,7 +1017573,7 @@
}
STATIC int
-@@ -1520,7 +1518,7 @@ xfs_qm_dqiter_bufs(
+@@ -1520,7 +1519,7 @@ xfs_qm_dqiter_bufs(
if (error)
break;
@@ -763405,7 +1017582,20 @@
xfs_bdwrite(mp, bp);
/*
* goto the next block.
-@@ -1810,7 +1808,7 @@ xfs_qm_dqusage_adjust(
+@@ -1739,12 +1738,6 @@ xfs_qm_dqusage_adjust(
+ return error;
+ }
+
+- if (ip->i_d.di_mode == 0) {
+- xfs_iput_new(ip, XFS_ILOCK_EXCL);
+- *res = BULKSTAT_RV_NOTHING;
+- return XFS_ERROR(ENOENT);
+- }
+-
+ /*
+ * Obtain the locked dquots. In case of an error (eg. allocation
+ * fails for ENOSPC), we return the negative of the error number
+@@ -1810,7 +1803,7 @@ xfs_qm_dqusage_adjust(
* Now release the inode. This will send it to 'inactive', and
* possibly even free blocks.
*/
@@ -763414,7 +1017604,7 @@
/*
* Goto next inode.
-@@ -1880,6 +1878,14 @@ xfs_qm_quotacheck(
+@@ -1880,6 +1873,14 @@ xfs_qm_quotacheck(
} while (! done);
/*
@@ -763429,7 +1017619,7 @@
* 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(
+@@ -1890,11 +1891,6 @@ xfs_qm_quotacheck(
xfs_qm_dqpurge_all(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_QUOTAOFF);
goto error_return;
}
@@ -763441,7 +1017631,7 @@
/*
* We didn't log anything, because if we crashed, we'll have to
-@@ -1926,7 +1927,10 @@ xfs_qm_quotacheck(
+@@ -1926,7 +1922,10 @@ xfs_qm_quotacheck(
ASSERT(mp->m_quotainfo != NULL);
ASSERT(xfs_Gqm != NULL);
xfs_qm_destroy_quotainfo(mp);
@@ -763453,7 +1017643,7 @@
} else {
cmn_err(CE_NOTE, "XFS quotacheck %s: Done.", mp->m_fsname);
}
-@@ -1968,7 +1972,7 @@ xfs_qm_init_quotainos(
+@@ -1968,7 +1967,7 @@ xfs_qm_init_quotainos(
if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
0, 0, &gip, 0))) {
if (uip)
@@ -763462,7 +1017652,7 @@
return XFS_ERROR(error);
}
}
-@@ -1999,7 +2003,7 @@ xfs_qm_init_quotainos(
+@@ -1999,7 +1998,7 @@ xfs_qm_init_quotainos(
sbflags | XFS_SB_GQUOTINO, flags);
if (error) {
if (uip)
@@ -763471,7 +1017661,7 @@
return XFS_ERROR(error);
}
-@@ -2093,12 +2097,17 @@ xfs_qm_shake_freelist(
+@@ -2093,12 +2092,17 @@ xfs_qm_shake_freelist(
* dirty dquots.
*/
if (XFS_DQ_IS_DIRTY(dqp)) {
@@ -763490,7 +1017680,7 @@
xfs_dqunlock(dqp); /* dqflush unlocks dqflock */
dqp = dqp->dq_flnext;
continue;
-@@ -2265,12 +2274,17 @@ xfs_qm_dqreclaim_one(void)
+@@ -2265,12 +2269,17 @@ xfs_qm_dqreclaim_one(void)
* dirty dquots.
*/
if (XFS_DQ_IS_DIRTY(dqp)) {
@@ -763509,7 +1017699,7 @@
xfs_dqunlock(dqp); /* dqflush unlocks dqflock */
continue;
}
-@@ -2378,9 +2392,9 @@ xfs_qm_write_sb_changes(
+@@ -2378,9 +2387,9 @@ xfs_qm_write_sb_changes(
}
xfs_mod_sb(tp, flags);
@@ -763521,6 +1017711,33 @@
}
+@@ -2549,7 +2558,7 @@ xfs_qm_vop_chown(
+ uint bfield = XFS_IS_REALTIME_INODE(ip) ?
+ XFS_TRANS_DQ_RTBCOUNT : XFS_TRANS_DQ_BCOUNT;
+
+- ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+ ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
+
+ /* old dquot */
+@@ -2593,7 +2602,7 @@ xfs_qm_vop_chown_reserve(
+ uint delblks, blkflags, prjflags = 0;
+ xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq;
+
+- ASSERT(XFS_ISLOCKED_INODE(ip));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
+ mp = ip->i_mount;
+ ASSERT(XFS_IS_QUOTA_RUNNING(mp));
+
+@@ -2703,7 +2712,7 @@ xfs_qm_vop_dqattach_and_dqmod_newinode(
+ if (!XFS_IS_QUOTA_ON(tp->t_mountp))
+ return;
+
+- ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+ ASSERT(XFS_IS_QUOTA_RUNNING(tp->t_mountp));
+
+ if (udqp) {
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
@@ -763550,7 +1017767,7 @@
#endif
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
-index d2b8be7..8342823 100644
+index d2b8be7..768a3b2 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(
@@ -763665,16 +1017882,71 @@
+ 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
+ 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
+@@ -1358,12 +1366,6 @@ xfs_qm_internalqcheck_adjust(
+ return (error);
+ }
+
+- if (ip->i_d.di_mode == 0) {
+- xfs_iput_new(ip, lock_flags);
+- *res = BULKSTAT_RV_NOTHING;
+- return XFS_ERROR(ENOENT);
+- }
+-
+ /*
+ * This inode can have blocks after eof which can get released
+ * when we send it to inactive. Since we don't check the dquot
+diff --git a/fs/xfs/quota/xfs_quota_priv.h b/fs/xfs/quota/xfs_quota_priv.h
+index a8b85e2..5e4a40b 100644
+--- a/fs/xfs/quota/xfs_quota_priv.h
++++ b/fs/xfs/quota/xfs_quota_priv.h
+@@ -27,11 +27,6 @@
+ /* Number of dquots that fit in to a dquot block */
+ #define XFS_QM_DQPERBLK(mp) ((mp)->m_quotainfo->qi_dqperchunk)
+
+-#define XFS_ISLOCKED_INODE(ip) (ismrlocked(&(ip)->i_lock, \
+- MR_UPDATE | MR_ACCESS) != 0)
+-#define XFS_ISLOCKED_INODE_EXCL(ip) (ismrlocked(&(ip)->i_lock, \
+- MR_UPDATE) != 0)
+-
+ #define XFS_DQ_IS_ADDEDTO_TRX(t, d) ((d)->q_transp == (t))
+
+ #define XFS_QI_MPLRECLAIMS(mp) ((mp)->m_quotainfo->qi_dqreclaims)
+diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
+index f441f83..9961138 100644
+--- a/fs/xfs/quota/xfs_trans_dquot.c
++++ b/fs/xfs/quota/xfs_trans_dquot.c
+@@ -834,7 +834,7 @@ xfs_trans_reserve_quota_nblks(
+ ASSERT(ip->i_ino != mp->m_sb.sb_uquotino);
+ ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);
+
+- ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+ ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
+ ASSERT((flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
+ XFS_TRANS_DQ_RES_RTBLKS ||
+diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h
+index 855da04..75845f9 100644
+--- a/fs/xfs/support/debug.h
++++ b/fs/xfs/support/debug.h
+@@ -49,8 +49,6 @@ extern void assfail(char *expr, char *f, int l);
+
+ #else /* DEBUG */
+
+-#include <linux/random.h>
+-
+ #define ASSERT(expr) \
+ (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
+
diff --git a/fs/xfs/support/ktrace.c b/fs/xfs/support/ktrace.c
index 129067c..0b75d30 100644
--- a/fs/xfs/support/ktrace.c
@@ -763797,24 +1018069,38 @@
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
+index 7272fe3..ebee3a4 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
-@@ -307,12 +307,13 @@ xfs_acl_vset(
+@@ -72,7 +72,7 @@ xfs_acl_vhasacl_default(
+ {
+ int error;
+
+- if (!VN_ISDIR(vp))
++ if (!S_ISDIR(vp->i_mode))
+ return 0;
+ xfs_acl_get_attr(vp, NULL, _ACL_TYPE_DEFAULT, ATTR_KERNOVAL, &error);
+ return (error == 0);
+@@ -238,15 +238,8 @@ xfs_acl_vget(
+ error = EINVAL;
+ goto out;
+ }
+- if (kind == _ACL_TYPE_ACCESS) {
+- bhv_vattr_t va;
+-
+- va.va_mask = XFS_AT_MODE;
+- error = xfs_getattr(xfs_vtoi(vp), &va, 0);
+- if (error)
+- goto out;
+- xfs_acl_sync_mode(va.va_mode, xfs_acl);
+- }
++ if (kind == _ACL_TYPE_ACCESS)
++ xfs_acl_sync_mode(xfs_vtoi(vp)->i_d.di_mode, xfs_acl);
+ error = -posix_acl_xfs_to_xattr(xfs_acl, ext_acl, size);
+ }
+ out:
+@@ -307,12 +300,13 @@ xfs_acl_vset(
VN_HOLD(vp);
error = xfs_acl_allow_set(vp, kind);
@@ -763832,7 +1018118,7 @@
/*
* If we have more than std unix permissions, set up the actual attr.
-@@ -323,7 +324,7 @@ xfs_acl_vset(
+@@ -323,7 +317,7 @@ xfs_acl_vset(
if (!basicperms) {
xfs_acl_set_attr(vp, xfs_acl, kind, &error);
} else {
@@ -763841,7 +1018127,87 @@
}
out:
-@@ -707,7 +708,9 @@ xfs_acl_inherit(
+@@ -340,14 +334,15 @@ xfs_acl_iaccess(
+ {
+ xfs_acl_t *acl;
+ int rval;
++ struct xfs_name acl_name = {SGI_ACL_FILE, SGI_ACL_FILE_SIZE};
+
+ if (!(_ACL_ALLOC(acl)))
+ return -1;
+
+ /* If the file has no ACL return -1. */
+ rval = sizeof(xfs_acl_t);
+- if (xfs_attr_fetch(ip, SGI_ACL_FILE, SGI_ACL_FILE_SIZE,
+- (char *)acl, &rval, ATTR_ROOT | ATTR_KERNACCESS, cr)) {
++ if (xfs_attr_fetch(ip, &acl_name, (char *)acl, &rval,
++ ATTR_ROOT | ATTR_KERNACCESS)) {
+ _ACL_FREE(acl);
+ return -1;
+ }
+@@ -372,23 +367,15 @@ xfs_acl_allow_set(
+ bhv_vnode_t *vp,
+ int kind)
+ {
+- xfs_inode_t *ip = xfs_vtoi(vp);
+- bhv_vattr_t va;
+- int error;
+-
+ if (vp->i_flags & (S_IMMUTABLE|S_APPEND))
+ return EPERM;
+- if (kind == _ACL_TYPE_DEFAULT && !VN_ISDIR(vp))
++ if (kind == _ACL_TYPE_DEFAULT && !S_ISDIR(vp->i_mode))
+ return ENOTDIR;
+ if (vp->i_sb->s_flags & MS_RDONLY)
+ return EROFS;
+- va.va_mask = XFS_AT_UID;
+- error = xfs_getattr(ip, &va, 0);
+- if (error)
+- return error;
+- if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
++ if (xfs_vtoi(vp)->i_d.di_uid != current->fsuid && !capable(CAP_FOWNER))
+ return EPERM;
+- return error;
++ return 0;
+ }
+
+ /*
+@@ -593,7 +580,7 @@ xfs_acl_get_attr(
+ *error = xfs_attr_get(xfs_vtoi(vp),
+ kind == _ACL_TYPE_ACCESS ?
+ SGI_ACL_FILE : SGI_ACL_DEFAULT,
+- (char *)aclp, &len, flags, sys_cred);
++ (char *)aclp, &len, flags);
+ if (*error || (flags & ATTR_KERNOVAL))
+ return;
+ xfs_acl_get_endian(aclp);
+@@ -642,7 +629,6 @@ xfs_acl_vtoacl(
+ xfs_acl_t *access_acl,
+ xfs_acl_t *default_acl)
+ {
+- bhv_vattr_t va;
+ int error = 0;
+
+ if (access_acl) {
+@@ -651,16 +637,10 @@ xfs_acl_vtoacl(
+ * be obtained for some reason, invalidate the access ACL.
+ */
+ xfs_acl_get_attr(vp, access_acl, _ACL_TYPE_ACCESS, 0, &error);
+- if (!error) {
+- /* Got the ACL, need the mode... */
+- va.va_mask = XFS_AT_MODE;
+- error = xfs_getattr(xfs_vtoi(vp), &va, 0);
+- }
+-
+ if (error)
+ access_acl->acl_cnt = XFS_ACL_NOT_PRESENT;
+ else /* We have a good ACL and the file mode, synchronize. */
+- xfs_acl_sync_mode(va.va_mode, access_acl);
++ xfs_acl_sync_mode(xfs_vtoi(vp)->i_d.di_mode, access_acl);
+ }
+
+ if (default_acl) {
+@@ -707,7 +687,9 @@ xfs_acl_inherit(
memcpy(cacl, pdaclp, sizeof(xfs_acl_t));
xfs_acl_filter_mode(mode, cacl);
@@ -763852,7 +1018218,12 @@
/*
* Set the Default and Access ACL on the file. The mode is already
-@@ -720,6 +723,7 @@ xfs_acl_inherit(
+@@ -716,10 +698,11 @@ xfs_acl_inherit(
+ * If the new file is a directory, its default ACL is a copy of
+ * the containing directory's default ACL.
+ */
+- if (VN_ISDIR(vp))
++ if (S_ISDIR(vp->i_mode))
xfs_acl_set_attr(vp, pdaclp, _ACL_TYPE_DEFAULT, &error);
if (!error && !basicperms)
xfs_acl_set_attr(vp, cacl, _ACL_TYPE_ACCESS, &error);
@@ -763860,6 +1018231,28 @@
_ACL_FREE(cacl);
return error;
}
+@@ -740,7 +723,7 @@ xfs_acl_setmode(
+ bhv_vattr_t va;
+ xfs_acl_entry_t *ap;
+ xfs_acl_entry_t *gap = NULL;
+- int i, error, nomask = 1;
++ int i, nomask = 1;
+
+ *basicperms = 1;
+
+@@ -752,11 +735,7 @@ xfs_acl_setmode(
+ * mode. The m:: bits take precedence over the g:: bits.
+ */
+ va.va_mask = XFS_AT_MODE;
+- error = xfs_getattr(xfs_vtoi(vp), &va, 0);
+- if (error)
+- return error;
+-
+- va.va_mask = XFS_AT_MODE;
++ va.va_mode = xfs_vtoi(vp)->i_d.di_mode;
+ va.va_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO);
+ ap = acl->acl_entry;
+ for (i = 0; i < acl->acl_cnt; ++i) {
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index bdbfbbe..1956f83 100644
--- a/fs/xfs/xfs_alloc.c
@@ -764029,10 +1018422,218 @@
- return n;
}
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
-index e58f321..36d781e 100644
+index e58f321..df151a8 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
-@@ -2647,14 +2647,6 @@ attr_trusted_capable(
+@@ -101,14 +101,28 @@ STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args);
+ ktrace_t *xfs_attr_trace_buf;
+ #endif
+
++STATIC int
++xfs_attr_name_to_xname(
++ struct xfs_name *xname,
++ const char *aname)
++{
++ if (!aname)
++ return EINVAL;
++ xname->name = aname;
++ xname->len = strlen(aname);
++ if (xname->len >= MAXNAMELEN)
++ return EFAULT; /* match IRIX behaviour */
++
++ return 0;
++}
+
+ /*========================================================================
+ * Overall external interface routines.
+ *========================================================================*/
+
+ int
+-xfs_attr_fetch(xfs_inode_t *ip, const char *name, int namelen,
+- char *value, int *valuelenp, int flags, struct cred *cred)
++xfs_attr_fetch(xfs_inode_t *ip, struct xfs_name *name,
++ char *value, int *valuelenp, int flags)
+ {
+ xfs_da_args_t args;
+ int error;
+@@ -122,8 +136,8 @@ xfs_attr_fetch(xfs_inode_t *ip, const char *name, int namelen,
+ * Fill in the arg structure for this request.
+ */
+ memset((char *)&args, 0, sizeof(args));
+- args.name = name;
+- args.namelen = namelen;
++ args.name = name->name;
++ args.namelen = name->len;
+ args.value = value;
+ args.valuelen = *valuelenp;
+ args.flags = flags;
+@@ -162,31 +176,29 @@ xfs_attr_get(
+ const char *name,
+ char *value,
+ int *valuelenp,
+- int flags,
+- cred_t *cred)
++ int flags)
+ {
+- int error, namelen;
++ int error;
++ struct xfs_name xname;
+
+ XFS_STATS_INC(xs_attr_get);
+
+- if (!name)
+- return(EINVAL);
+- namelen = strlen(name);
+- if (namelen >= MAXNAMELEN)
+- return(EFAULT); /* match IRIX behaviour */
+-
+ if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+ return(EIO);
+
++ error = xfs_attr_name_to_xname(&xname, name);
++ if (error)
++ return error;
++
+ xfs_ilock(ip, XFS_ILOCK_SHARED);
+- error = xfs_attr_fetch(ip, name, namelen, value, valuelenp, flags, cred);
++ error = xfs_attr_fetch(ip, &xname, value, valuelenp, flags);
+ xfs_iunlock(ip, XFS_ILOCK_SHARED);
+ return(error);
+ }
+
+-int
+-xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
+- char *value, int valuelen, int flags)
++STATIC int
++xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
++ char *value, int valuelen, int flags)
+ {
+ xfs_da_args_t args;
+ xfs_fsblock_t firstblock;
+@@ -209,7 +221,7 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
+ */
+ if (XFS_IFORK_Q(dp) == 0) {
+ int sf_size = sizeof(xfs_attr_sf_hdr_t) +
+- XFS_ATTR_SF_ENTSIZE_BYNAME(namelen, valuelen);
++ XFS_ATTR_SF_ENTSIZE_BYNAME(name->len, valuelen);
+
+ if ((error = xfs_bmap_add_attrfork(dp, sf_size, rsvd)))
+ return(error);
+@@ -219,8 +231,8 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
+ * Fill in the arg structure for this request.
+ */
+ memset((char *)&args, 0, sizeof(args));
+- args.name = name;
+- args.namelen = namelen;
++ args.name = name->name;
++ args.namelen = name->len;
+ args.value = value;
+ args.valuelen = valuelen;
+ args.flags = flags;
+@@ -236,7 +248,7 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
+ * Determine space new attribute will use, and if it would be
+ * "local" or "remote" (note: local != inline).
+ */
+- size = xfs_attr_leaf_newentsize(namelen, valuelen,
++ size = xfs_attr_leaf_newentsize(name->len, valuelen,
+ mp->m_sb.sb_blocksize, &local);
+
+ nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
+@@ -429,26 +441,27 @@ xfs_attr_set(
+ int valuelen,
+ int flags)
+ {
+- int namelen;
+-
+- namelen = strlen(name);
+- if (namelen >= MAXNAMELEN)
+- return EFAULT; /* match IRIX behaviour */
++ int error;
++ struct xfs_name xname;
+
+ XFS_STATS_INC(xs_attr_set);
+
+ if (XFS_FORCED_SHUTDOWN(dp->i_mount))
+ return (EIO);
+
+- return xfs_attr_set_int(dp, name, namelen, value, valuelen, flags);
++ error = xfs_attr_name_to_xname(&xname, name);
++ if (error)
++ return error;
++
++ return xfs_attr_set_int(dp, &xname, value, valuelen, flags);
+ }
+
+ /*
+ * Generic handler routine to remove a name from an attribute list.
+ * Transitions attribute list from Btree to shortform as necessary.
+ */
+-int
+-xfs_attr_remove_int(xfs_inode_t *dp, const char *name, int namelen, int flags)
++STATIC int
++xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
+ {
+ xfs_da_args_t args;
+ xfs_fsblock_t firstblock;
+@@ -460,8 +473,8 @@ xfs_attr_remove_int(xfs_inode_t *dp, const char *name, int namelen, int flags)
+ * Fill in the arg structure for this request.
+ */
+ memset((char *)&args, 0, sizeof(args));
+- args.name = name;
+- args.namelen = namelen;
++ args.name = name->name;
++ args.namelen = name->len;
+ args.flags = flags;
+ args.hashval = xfs_da_hashname(args.name, args.namelen);
+ args.dp = dp;
+@@ -575,17 +588,18 @@ xfs_attr_remove(
+ const char *name,
+ int flags)
+ {
+- int namelen;
+-
+- namelen = strlen(name);
+- if (namelen >= MAXNAMELEN)
+- return EFAULT; /* match IRIX behaviour */
++ int error;
++ struct xfs_name xname;
+
+ XFS_STATS_INC(xs_attr_remove);
+
+ if (XFS_FORCED_SHUTDOWN(dp->i_mount))
+ return (EIO);
+
++ error = xfs_attr_name_to_xname(&xname, name);
++ if (error)
++ return error;
++
+ xfs_ilock(dp, XFS_ILOCK_SHARED);
+ if (XFS_IFORK_Q(dp) == 0 ||
+ (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
+@@ -595,10 +609,10 @@ xfs_attr_remove(
+ }
+ xfs_iunlock(dp, XFS_ILOCK_SHARED);
+
+- return xfs_attr_remove_int(dp, name, namelen, flags);
++ return xfs_attr_remove_int(dp, &xname, flags);
+ }
+
+-int /* error */
++STATIC int
+ xfs_attr_list_int(xfs_attr_list_context_t *context)
+ {
+ int error;
+@@ -2522,8 +2536,7 @@ attr_generic_get(
+ {
+ int error, asize = size;
+
+- error = xfs_attr_get(xfs_vtoi(vp), name, data,
+- &asize, xflags, NULL);
++ error = xfs_attr_get(xfs_vtoi(vp), name, data, &asize, xflags);
+ if (!error)
+ return asize;
+ return -error;
+@@ -2647,14 +2660,6 @@ attr_trusted_capable(
}
STATIC int
@@ -764047,7 +1018648,7 @@
attr_system_set(
bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
{
-@@ -2724,7 +2716,7 @@ struct attrnames attr_secure = {
+@@ -2724,7 +2729,7 @@ struct attrnames attr_secure = {
.attr_get = attr_generic_get,
.attr_set = attr_generic_set,
.attr_remove = attr_generic_remove,
@@ -764056,6 +1018657,26 @@
};
struct attrnames attr_user = {
+diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h
+index 786eba3..6cfc938 100644
+--- a/fs/xfs/xfs_attr.h
++++ b/fs/xfs/xfs_attr.h
+@@ -158,14 +158,10 @@ struct xfs_da_args;
+ /*
+ * Overall external interface routines.
+ */
+-int xfs_attr_set_int(struct xfs_inode *, const char *, int, char *, int, int);
+-int xfs_attr_remove_int(struct xfs_inode *, const char *, int, int);
+-int xfs_attr_list_int(struct xfs_attr_list_context *);
+ int xfs_attr_inactive(struct xfs_inode *dp);
+
+ int xfs_attr_shortform_getvalue(struct xfs_da_args *);
+-int xfs_attr_fetch(struct xfs_inode *, const char *, int,
+- char *, int *, int, struct cred *);
++int xfs_attr_fetch(struct xfs_inode *, struct xfs_name *, char *, int *, int);
+ int xfs_attr_rmtval_get(struct xfs_da_args *args);
+
+ #endif /* __XFS_ATTR_H__ */
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
@@ -764070,7 +1018691,7 @@
}
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
-index 2def273..eb198c0 100644
+index 2def273..53c259f 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -323,13 +323,13 @@ xfs_bmap_trace_pre_update(
@@ -764108,7 +1018729,15 @@
}
STATIC int
-@@ -4154,16 +4153,21 @@ xfs_bmap_compute_maxlevels(
+@@ -4075,7 +4074,6 @@ xfs_bmap_add_attrfork(
+ error2:
+ xfs_bmap_cancel(&flist);
+ error1:
+- ASSERT(ismrlocked(&ip->i_lock,MR_UPDATE));
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ error0:
+ xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
+@@ -4154,16 +4152,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).
@@ -764135,7 +1018764,7 @@
}
maxrootrecs = (int)XFS_BTREE_BLOCK_MAXRECS(sz, xfs_bmdr, 0);
minleafrecs = mp->m_bmap_dmnr[0];
-@@ -5772,7 +5776,6 @@ xfs_getbmap(
+@@ -5772,7 +5775,6 @@ xfs_getbmap(
int error; /* return value */
__int64_t fixlen; /* length for -1 case */
int i; /* extent number */
@@ -764143,7 +1018772,7 @@
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(
+@@ -5789,7 +5791,6 @@ xfs_getbmap(
int bmapi_flags; /* flags for xfs_bmapi */
__int32_t oflags; /* getbmapx bmv_oflags field */
@@ -764151,7 +1018780,7 @@
mp = ip->i_mount;
whichfork = interface & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK;
-@@ -5811,7 +5813,7 @@ xfs_getbmap(
+@@ -5811,7 +5812,7 @@ xfs_getbmap(
if ((interface & BMV_IF_NO_DMAPI_READ) == 0 &&
DM_EVENT_ENABLED(ip, DM_EVENT_READ) &&
whichfork == XFS_DATA_FORK) {
@@ -764160,7 +1018789,7 @@
if (error)
return XFS_ERROR(error);
}
-@@ -5869,6 +5871,10 @@ xfs_getbmap(
+@@ -5869,6 +5870,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);
@@ -764171,7 +1018800,7 @@
}
ASSERT(whichfork == XFS_ATTR_FORK || ip->i_delayed_blks == 0);
-@@ -6162,10 +6168,10 @@ xfs_check_block(
+@@ -6162,10 +6167,10 @@ xfs_check_block(
}
if (*thispa == *pp) {
cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld",
@@ -764184,7 +1018813,7 @@
}
}
}
-@@ -6192,7 +6198,7 @@ xfs_bmap_check_leaf_extents(
+@@ -6192,7 +6197,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 */
@@ -764193,7 +1018822,7 @@
xfs_bmbt_rec_t *nextp; /* pointer to next extent */
int bp_release = 0;
-@@ -6262,7 +6268,6 @@ xfs_bmap_check_leaf_extents(
+@@ -6262,7 +6267,6 @@ xfs_bmap_check_leaf_extents(
/*
* Loop over all leaf nodes checking that all extents are in the right order.
*/
@@ -764201,7 +1018830,7 @@
for (;;) {
xfs_fsblock_t nextbno;
xfs_extnum_t num_recs;
-@@ -6283,18 +6288,16 @@ xfs_bmap_check_leaf_extents(
+@@ -6283,18 +6287,16 @@ xfs_bmap_check_leaf_extents(
*/
ep = XFS_BTREE_REC_ADDR(xfs_bmbt, block, 1);
@@ -764225,7 +1018854,7 @@
i += num_recs;
if (bp_release) {
bp_release = 0;
-@@ -6325,13 +6328,13 @@ xfs_bmap_check_leaf_extents(
+@@ -6325,13 +6327,13 @@ xfs_bmap_check_leaf_extents(
return;
error0:
@@ -764385,6 +1019014,28 @@
} else {
xfs_buf_relse(bp);
}
+diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
+index 3f53fad..5f3647c 100644
+--- a/fs/xfs/xfs_dfrag.c
++++ b/fs/xfs/xfs_dfrag.c
+@@ -162,7 +162,7 @@ xfs_swap_extents(
+ ips[1] = ip;
+ }
+
+- xfs_lock_inodes(ips, 2, 0, lock_flags);
++ xfs_lock_inodes(ips, 2, lock_flags);
+ locked = 1;
+
+ /* Verify that both files have the same format */
+@@ -265,7 +265,7 @@ xfs_swap_extents(
+ locked = 0;
+ goto error0;
+ }
+- xfs_lock_inodes(ips, 2, 0, XFS_ILOCK_EXCL);
++ xfs_lock_inodes(ips, 2, XFS_ILOCK_EXCL);
+
+ /*
+ * Count the number of extended attribute blocks
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index e92e73f..7cb2652 100644
--- a/fs/xfs/xfs_dir2.c
@@ -764591,8 +1019242,50 @@
(__psunsigned_t)a0, (__psunsigned_t)a1, \
(__psunsigned_t)a2, (__psunsigned_t)a3, \
(__psunsigned_t)a4, (__psunsigned_t)a5)
+diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
+index d3a0f53..381ebda 100644
+--- a/fs/xfs/xfs_fsops.c
++++ b/fs/xfs/xfs_fsops.c
+@@ -462,7 +462,7 @@ xfs_fs_counts(
+ xfs_mount_t *mp,
+ xfs_fsop_counts_t *cnt)
+ {
+- xfs_icsb_sync_counters_flags(mp, XFS_ICSB_LAZY_COUNT);
++ xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
+ spin_lock(&mp->m_sb_lock);
+ cnt->freedata = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
+ cnt->freertx = mp->m_sb.sb_frextents;
+@@ -524,7 +524,7 @@ xfs_reserve_blocks(
+ */
+ retry:
+ spin_lock(&mp->m_sb_lock);
+- xfs_icsb_sync_counters_flags(mp, XFS_ICSB_SB_LOCKED);
++ xfs_icsb_sync_counters_locked(mp, 0);
+
+ /*
+ * If our previous reservation was larger than the current value,
+@@ -552,11 +552,8 @@ retry:
+ mp->m_resblks += free;
+ mp->m_resblks_avail += free;
+ fdblks_delta = -free;
+- mp->m_sb.sb_fdblocks = XFS_ALLOC_SET_ASIDE(mp);
+ } else {
+ fdblks_delta = -delta;
+- mp->m_sb.sb_fdblocks =
+- lcounter + XFS_ALLOC_SET_ASIDE(mp);
+ mp->m_resblks = request;
+ mp->m_resblks_avail += delta;
+ }
+@@ -587,7 +584,6 @@ out:
+ if (error == ENOSPC)
+ goto retry;
+ }
+-
+ return 0;
+ }
+
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
-index 5a146cb..a64dfbd 100644
+index 5a146cb..aad8c5d 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -107,6 +107,16 @@ xfs_ialloc_log_di(
@@ -764612,7 +1019305,15 @@
/*
* Allocate new inodes in the allocation group specified by agbp.
-@@ -167,10 +177,24 @@ xfs_ialloc_ag_alloc(
+@@ -137,6 +147,7 @@ xfs_ialloc_ag_alloc(
+ int version; /* inode version number to use */
+ int isaligned = 0; /* inode allocation at stripe unit */
+ /* boundary */
++ unsigned int gen;
+
+ args.tp = tp;
+ args.mp = tp->t_mountp;
+@@ -167,10 +178,24 @@ xfs_ialloc_ag_alloc(
args.mod = args.total = args.wasdel = args.isfl =
args.userdata = args.minalignslop = 0;
args.prod = 1;
@@ -764639,7 +1019340,7 @@
args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1;
if ((error = xfs_alloc_vextent(&args)))
return error;
-@@ -191,13 +215,8 @@ xfs_ialloc_ag_alloc(
+@@ -191,13 +216,8 @@ xfs_ialloc_ag_alloc(
ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN));
args.alignment = args.mp->m_dalign;
isaligned = 1;
@@ -764655,7 +1019356,7 @@
/*
* 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(
+@@ -230,12 +250,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);
@@ -764669,8 +1019370,31 @@
if ((error = xfs_alloc_vextent(&args)))
return error;
}
+@@ -276,6 +291,14 @@ xfs_ialloc_ag_alloc(
+ else
+ version = XFS_DINODE_VERSION_1;
+
++ /*
++ * Seed the new inode cluster with a random generation number. This
++ * prevents short-term reuse of generation numbers if a chunk is
++ * freed and then immediately reallocated. We use random numbers
++ * rather than a linear progression to prevent the next generation
++ * number from being easily guessable.
++ */
++ gen = random32();
+ for (j = 0; j < nbufs; j++) {
+ /*
+ * Get the block.
+@@ -295,6 +318,7 @@ xfs_ialloc_ag_alloc(
+ free = XFS_MAKE_IPTR(args.mp, fbuf, i);
+ free->di_core.di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
+ free->di_core.di_version = version;
++ free->di_core.di_gen = cpu_to_be32(gen);
+ free->di_next_unlinked = cpu_to_be32(NULLAGINO);
+ xfs_ialloc_log_di(tp, fbuf, i,
+ XFS_DI_CORE_BITS | XFS_DI_NEXT_UNLINKED);
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
-index 8e09b71..e657c51 100644
+index 8e09b71..b07604b 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -78,7 +78,6 @@ xfs_iget_core(
@@ -764764,8 +1019488,227 @@
* Remove from mount's inode list.
*/
XFS_MOUNT_ILOCK(mp);
+@@ -636,8 +593,9 @@ xfs_iunlock_map_shared(
+ * XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL
+ */
+ void
+-xfs_ilock(xfs_inode_t *ip,
+- uint lock_flags)
++xfs_ilock(
++ xfs_inode_t *ip,
++ uint lock_flags)
+ {
+ /*
+ * You can't set both SHARED and EXCL for the same lock,
+@@ -650,16 +608,16 @@ xfs_ilock(xfs_inode_t *ip,
+ (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
+ ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
+
+- if (lock_flags & XFS_IOLOCK_EXCL) {
++ if (lock_flags & XFS_IOLOCK_EXCL)
+ mrupdate_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags));
+- } else if (lock_flags & XFS_IOLOCK_SHARED) {
++ else if (lock_flags & XFS_IOLOCK_SHARED)
+ mraccess_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags));
+- }
+- if (lock_flags & XFS_ILOCK_EXCL) {
++
++ if (lock_flags & XFS_ILOCK_EXCL)
+ mrupdate_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags));
+- } else if (lock_flags & XFS_ILOCK_SHARED) {
++ else if (lock_flags & XFS_ILOCK_SHARED)
+ mraccess_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags));
+- }
++
+ xfs_ilock_trace(ip, 1, lock_flags, (inst_t *)__return_address);
+ }
+
+@@ -674,15 +632,12 @@ xfs_ilock(xfs_inode_t *ip,
+ * lock_flags -- this parameter indicates the inode's locks to be
+ * to be locked. See the comment for xfs_ilock() for a list
+ * of valid values.
+- *
+ */
+ int
+-xfs_ilock_nowait(xfs_inode_t *ip,
+- uint lock_flags)
++xfs_ilock_nowait(
++ xfs_inode_t *ip,
++ uint lock_flags)
+ {
+- int iolocked;
+- int ilocked;
+-
+ /*
+ * You can't set both SHARED and EXCL for the same lock,
+ * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
+@@ -694,37 +649,30 @@ xfs_ilock_nowait(xfs_inode_t *ip,
+ (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
+ ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
+
+- iolocked = 0;
+ if (lock_flags & XFS_IOLOCK_EXCL) {
+- iolocked = mrtryupdate(&ip->i_iolock);
+- if (!iolocked) {
+- return 0;
+- }
++ if (!mrtryupdate(&ip->i_iolock))
++ goto out;
+ } else if (lock_flags & XFS_IOLOCK_SHARED) {
+- iolocked = mrtryaccess(&ip->i_iolock);
+- if (!iolocked) {
+- return 0;
+- }
++ if (!mrtryaccess(&ip->i_iolock))
++ goto out;
+ }
+ if (lock_flags & XFS_ILOCK_EXCL) {
+- ilocked = mrtryupdate(&ip->i_lock);
+- if (!ilocked) {
+- if (iolocked) {
+- mrunlock(&ip->i_iolock);
+- }
+- return 0;
+- }
++ if (!mrtryupdate(&ip->i_lock))
++ goto out_undo_iolock;
+ } else if (lock_flags & XFS_ILOCK_SHARED) {
+- ilocked = mrtryaccess(&ip->i_lock);
+- if (!ilocked) {
+- if (iolocked) {
+- mrunlock(&ip->i_iolock);
+- }
+- return 0;
+- }
++ if (!mrtryaccess(&ip->i_lock))
++ goto out_undo_iolock;
+ }
+ xfs_ilock_trace(ip, 2, lock_flags, (inst_t *)__return_address);
+ return 1;
++
++ out_undo_iolock:
++ if (lock_flags & XFS_IOLOCK_EXCL)
++ mrunlock_excl(&ip->i_iolock);
++ else if (lock_flags & XFS_IOLOCK_SHARED)
++ mrunlock_shared(&ip->i_iolock);
++ out:
++ return 0;
+ }
+
+ /*
+@@ -740,8 +688,9 @@ xfs_ilock_nowait(xfs_inode_t *ip,
+ *
+ */
+ void
+-xfs_iunlock(xfs_inode_t *ip,
+- uint lock_flags)
++xfs_iunlock(
++ xfs_inode_t *ip,
++ uint lock_flags)
+ {
+ /*
+ * You can't set both SHARED and EXCL for the same lock,
+@@ -756,31 +705,25 @@ xfs_iunlock(xfs_inode_t *ip,
+ XFS_LOCK_DEP_MASK)) == 0);
+ ASSERT(lock_flags != 0);
+
+- if (lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) {
+- ASSERT(!(lock_flags & XFS_IOLOCK_SHARED) ||
+- (ismrlocked(&ip->i_iolock, MR_ACCESS)));
+- ASSERT(!(lock_flags & XFS_IOLOCK_EXCL) ||
+- (ismrlocked(&ip->i_iolock, MR_UPDATE)));
+- mrunlock(&ip->i_iolock);
+- }
++ if (lock_flags & XFS_IOLOCK_EXCL)
++ mrunlock_excl(&ip->i_iolock);
++ else if (lock_flags & XFS_IOLOCK_SHARED)
++ mrunlock_shared(&ip->i_iolock);
+
+- if (lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) {
+- ASSERT(!(lock_flags & XFS_ILOCK_SHARED) ||
+- (ismrlocked(&ip->i_lock, MR_ACCESS)));
+- ASSERT(!(lock_flags & XFS_ILOCK_EXCL) ||
+- (ismrlocked(&ip->i_lock, MR_UPDATE)));
+- mrunlock(&ip->i_lock);
++ if (lock_flags & XFS_ILOCK_EXCL)
++ mrunlock_excl(&ip->i_lock);
++ else if (lock_flags & XFS_ILOCK_SHARED)
++ mrunlock_shared(&ip->i_lock);
+
++ if ((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) &&
++ !(lock_flags & XFS_IUNLOCK_NONOTIFY) && ip->i_itemp) {
+ /*
+ * Let the AIL know that this item has been unlocked in case
+ * it is in the AIL and anyone is waiting on it. Don't do
+ * this if the caller has asked us not to.
+ */
+- if (!(lock_flags & XFS_IUNLOCK_NONOTIFY) &&
+- ip->i_itemp != NULL) {
+- xfs_trans_unlocked_item(ip->i_mount,
+- (xfs_log_item_t*)(ip->i_itemp));
+- }
++ xfs_trans_unlocked_item(ip->i_mount,
++ (xfs_log_item_t*)(ip->i_itemp));
+ }
+ xfs_ilock_trace(ip, 3, lock_flags, (inst_t *)__return_address);
+ }
+@@ -790,21 +733,47 @@ xfs_iunlock(xfs_inode_t *ip,
+ * if it is being demoted.
+ */
+ void
+-xfs_ilock_demote(xfs_inode_t *ip,
+- uint lock_flags)
++xfs_ilock_demote(
++ xfs_inode_t *ip,
++ uint lock_flags)
+ {
+ ASSERT(lock_flags & (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL));
+ ASSERT((lock_flags & ~(XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL)) == 0);
+
+- if (lock_flags & XFS_ILOCK_EXCL) {
+- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
++ if (lock_flags & XFS_ILOCK_EXCL)
+ mrdemote(&ip->i_lock);
+- }
+- if (lock_flags & XFS_IOLOCK_EXCL) {
+- ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE));
++ if (lock_flags & XFS_IOLOCK_EXCL)
+ mrdemote(&ip->i_iolock);
++}
++
++#ifdef DEBUG
++/*
++ * Debug-only routine, without additional rw_semaphore APIs, we can
++ * now only answer requests regarding whether we hold the lock for write
++ * (reader state is outside our visibility, we only track writer state).
++ *
++ * Note: this means !xfs_isilocked would give false positives, so don't do that.
++ */
++int
++xfs_isilocked(
++ xfs_inode_t *ip,
++ uint lock_flags)
++{
++ if ((lock_flags & (XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)) ==
++ XFS_ILOCK_EXCL) {
++ if (!ip->i_lock.mr_writer)
++ return 0;
++ }
++
++ if ((lock_flags & (XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)) ==
++ XFS_IOLOCK_EXCL) {
++ if (!ip->i_iolock.mr_writer)
++ return 0;
+ }
++
++ return 1;
+ }
++#endif
+
+ /*
+ * The following three routines simply manage the i_flock
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
-index f43a6e0..ca12acb 100644
+index f43a6e0..cf0bb9c 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -55,7 +55,6 @@
@@ -765088,6 +1020031,24 @@
if (error) {
kmem_zone_free(xfs_inode_zone, ip);
return error;
+@@ -1345,7 +1291,7 @@ xfs_file_last_byte(
+ xfs_fileoff_t size_last_block;
+ int error;
+
+- ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE | MR_ACCESS));
++ ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED));
+
+ mp = ip->i_mount;
+ /*
+@@ -1456,7 +1402,7 @@ xfs_itruncate_start(
+ bhv_vnode_t *vp;
+ int error = 0;
+
+- ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE) != 0);
++ ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
+ ASSERT((new_size == 0) || (new_size <= ip->i_size));
+ ASSERT((flags == XFS_ITRUNC_DEFINITE) ||
+ (flags == XFS_ITRUNC_MAYBE));
@@ -1518,51 +1464,50 @@ xfs_itruncate_start(
}
@@ -765178,7 +1020139,17 @@
*/
int
xfs_itruncate_finish(
-@@ -1741,65 +1686,51 @@ xfs_itruncate_finish(
+@@ -1583,8 +1528,7 @@ xfs_itruncate_finish(
+ xfs_bmap_free_t free_list;
+ int error;
+
+- ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE) != 0);
+- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0);
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
+ ASSERT((new_size == 0) || (new_size <= ip->i_size));
+ ASSERT(*tp != NULL);
+ ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
+@@ -1741,65 +1685,51 @@ xfs_itruncate_finish(
*/
error = xfs_bmap_finish(tp, &free_list, &committed);
ntp = *tp;
@@ -765271,7 +1020242,27 @@
}
/*
* Only update the size in the case of the data fork, but
-@@ -1967,7 +1898,7 @@ xfs_iunlink(
+@@ -1849,8 +1779,7 @@ xfs_igrow_start(
+ xfs_fsize_t new_size,
+ cred_t *credp)
+ {
+- ASSERT(ismrlocked(&(ip->i_lock), MR_UPDATE) != 0);
+- ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE) != 0);
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
+ ASSERT(new_size > ip->i_size);
+
+ /*
+@@ -1878,8 +1807,7 @@ xfs_igrow_finish(
+ xfs_fsize_t new_size,
+ int change_flag)
+ {
+- ASSERT(ismrlocked(&(ip->i_lock), MR_UPDATE) != 0);
+- ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE) != 0);
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
+ ASSERT(ip->i_transp == tp);
+ ASSERT(new_size > ip->i_size);
+
+@@ -1967,7 +1895,7 @@ xfs_iunlink(
* Here we put the head pointer into our next pointer,
* and then we fall through to point the head at us.
*/
@@ -765280,7 +1020271,7 @@
if (error)
return error;
-@@ -2075,7 +2006,7 @@ xfs_iunlink_remove(
+@@ -2075,7 +2003,7 @@ xfs_iunlink_remove(
* of dealing with the buffer when there is no need to
* change it.
*/
@@ -765289,7 +1020280,7 @@
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(
+@@ -2137,7 +2065,7 @@ xfs_iunlink_remove(
* Now last_ibp points to the buffer previous to us on
* the unlinked list. Pull us from the list.
*/
@@ -765298,7 +1020289,7 @@
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(
+@@ -2172,13 +2100,6 @@ xfs_iunlink_remove(
return 0;
}
@@ -765312,7 +1020303,16 @@
STATIC void
xfs_ifree_cluster(
xfs_inode_t *free_ip,
-@@ -2400,7 +2324,7 @@ xfs_ifree(
+@@ -2363,7 +2284,7 @@ xfs_ifree(
+ xfs_dinode_t *dip;
+ xfs_buf_t *ibp;
+
+- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+ ASSERT(ip->i_transp == tp);
+ ASSERT(ip->i_d.di_nlink == 0);
+ ASSERT(ip->i_d.di_nextents == 0);
+@@ -2400,7 +2321,7 @@ xfs_ifree(
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
@@ -765321,7 +1020321,7 @@
if (error)
return error;
-@@ -2678,14 +2602,31 @@ xfs_imap(
+@@ -2678,14 +2599,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);
@@ -765355,7 +1020355,16 @@
return 0;
}
-@@ -2826,38 +2767,41 @@ xfs_iunpin(
+@@ -2805,7 +2743,7 @@ void
+ xfs_ipin(
+ xfs_inode_t *ip)
+ {
+- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+
+ atomic_inc(&ip->i_pincount);
+ }
+@@ -2826,38 +2764,41 @@ xfs_iunpin(
}
/*
@@ -765380,9 +1020389,10 @@
- xfs_lsn_t lsn;
+ xfs_inode_log_item_t *iip = ip->i_itemp;
- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE | MR_ACCESS));
+- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE | MR_ACCESS));
-
- if (atomic_read(&ip->i_pincount) == 0) {
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
+ if (atomic_read(&ip->i_pincount) == 0)
return;
- }
@@ -765420,7 +1020430,16 @@
}
-@@ -2932,7 +2876,7 @@ xfs_iextents_copy(
+@@ -2885,7 +2826,7 @@ xfs_iextents_copy(
+ xfs_fsblock_t start_block;
+
+ ifp = XFS_IFORK_PTR(ip, whichfork);
+- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
+ ASSERT(ifp->if_bytes > 0);
+
+ nrecs = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
+@@ -2932,7 +2873,7 @@ xfs_iextents_copy(
* format indicates the current state of the fork.
*/
/*ARGSUSED*/
@@ -765429,7 +1020448,7 @@
xfs_iflush_fork(
xfs_inode_t *ip,
xfs_dinode_t *dip,
-@@ -2953,16 +2897,16 @@ xfs_iflush_fork(
+@@ -2953,16 +2894,16 @@ xfs_iflush_fork(
static const short extflag[2] =
{ XFS_ILOG_DEXT, XFS_ILOG_AEXT };
@@ -765450,7 +1020469,7 @@
}
cp = XFS_DFORK_PTR(dip, whichfork);
mp = ip->i_mount;
-@@ -3023,8 +2967,145 @@ xfs_iflush_fork(
+@@ -3023,8 +2964,145 @@ xfs_iflush_fork(
ASSERT(0);
break;
}
@@ -765596,7 +1020615,7 @@
}
/*
-@@ -3046,11 +3127,7 @@ xfs_iflush(
+@@ -3046,16 +3124,12 @@ xfs_iflush(
xfs_dinode_t *dip;
xfs_mount_t *mp;
int error;
@@ -765609,7 +1020628,13 @@
enum { INT_DELWRI = (1 << 0), INT_ASYNC = (1 << 1) };
XFS_STATS_INC(xs_iflush_count);
-@@ -3067,8 +3144,7 @@ xfs_iflush(
+
+- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
+ ASSERT(issemalocked(&(ip->i_flock)));
+ ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
+ ip->i_d.di_nextents > ip->i_df.if_ext_max);
+@@ -3067,8 +3141,7 @@ xfs_iflush(
* If the inode isn't dirty, then just release the inode
* flush lock and do nothing.
*/
@@ -765619,7 +1020644,7 @@
ASSERT((iip != NULL) ?
!(iip->ili_item.li_flags & XFS_LI_IN_AIL) : 1);
xfs_ifunlock(ip);
-@@ -3076,11 +3152,21 @@ xfs_iflush(
+@@ -3076,11 +3149,21 @@ xfs_iflush(
}
/*
@@ -765645,7 +1020670,7 @@
xfs_iunpin_wait(ip);
/*
-@@ -3097,15 +3183,6 @@ xfs_iflush(
+@@ -3097,15 +3180,6 @@ xfs_iflush(
}
/*
@@ -765661,7 +1020686,7 @@
* 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(
+@@ -3121,6 +3195,7 @@ xfs_iflush(
case XFS_IFLUSH_DELWRI_ELSE_SYNC:
flags = 0;
break;
@@ -765669,7 +1020694,7 @@
case XFS_IFLUSH_ASYNC:
case XFS_IFLUSH_DELWRI_ELSE_ASYNC:
flags = INT_ASYNC;
-@@ -3140,6 +3218,7 @@ xfs_iflush(
+@@ -3140,6 +3215,7 @@ xfs_iflush(
case XFS_IFLUSH_DELWRI:
flags = INT_DELWRI;
break;
@@ -765677,7 +1020702,7 @@
case XFS_IFLUSH_ASYNC:
flags = INT_ASYNC;
break;
-@@ -3154,94 +3233,41 @@ xfs_iflush(
+@@ -3154,94 +3230,41 @@ xfs_iflush(
}
/*
@@ -765793,7 +1020818,7 @@
} else {
error = xfs_bwrite(mp, bp);
}
-@@ -3250,52 +3276,11 @@ xfs_iflush(
+@@ -3250,52 +3273,11 @@ xfs_iflush(
corrupt_out:
xfs_buf_relse(bp);
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
@@ -765847,7 +1020872,16 @@
return XFS_ERROR(EFSCORRUPTED);
}
-@@ -3325,8 +3310,7 @@ xfs_iflush_int(
+@@ -3312,7 +3294,7 @@ xfs_iflush_int(
+ int first;
+ #endif
+
+- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
+ ASSERT(issemalocked(&(ip->i_flock)));
+ ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
+ ip->i_d.di_nextents > ip->i_df.if_ext_max);
+@@ -3325,8 +3307,7 @@ xfs_iflush_int(
* If the inode isn't dirty, then just release the inode
* flush lock and do nothing.
*/
@@ -765857,7 +1020891,7 @@
xfs_ifunlock(ip);
return 0;
}
-@@ -3459,16 +3443,9 @@ xfs_iflush_int(
+@@ -3459,16 +3440,9 @@ xfs_iflush_int(
}
}
@@ -765878,7 +1020912,7 @@
/*
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
-index bfcd72c..93c3769 100644
+index bfcd72c..0a999fe 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -133,19 +133,6 @@ typedef struct dm_attrs_s {
@@ -765921,7 +1020955,29 @@
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)
+@@ -405,20 +386,9 @@ xfs_iflags_test_and_clear(xfs_inode_t *ip, unsigned short flags)
+ #define XFS_ILOCK_EXCL (1<<2)
+ #define XFS_ILOCK_SHARED (1<<3)
+ #define XFS_IUNLOCK_NONOTIFY (1<<4)
+-/* #define XFS_IOLOCK_NESTED (1<<5) */
+-#define XFS_EXTENT_TOKEN_RD (1<<6)
+-#define XFS_SIZE_TOKEN_RD (1<<7)
+-#define XFS_EXTSIZE_RD (XFS_EXTENT_TOKEN_RD|XFS_SIZE_TOKEN_RD)
+-#define XFS_WILLLEND (1<<8) /* Always acquire tokens for lending */
+-#define XFS_EXTENT_TOKEN_WR (XFS_EXTENT_TOKEN_RD | XFS_WILLLEND)
+-#define XFS_SIZE_TOKEN_WR (XFS_SIZE_TOKEN_RD | XFS_WILLLEND)
+-#define XFS_EXTSIZE_WR (XFS_EXTSIZE_RD | XFS_WILLLEND)
+-/* TODO:XFS_SIZE_TOKEN_WANT (1<<9) */
+
+ #define XFS_LOCK_MASK (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED \
+- | XFS_ILOCK_EXCL | XFS_ILOCK_SHARED \
+- | XFS_EXTENT_TOKEN_RD | XFS_SIZE_TOKEN_RD \
+- | XFS_WILLLEND)
++ | XFS_ILOCK_EXCL | XFS_ILOCK_SHARED)
+
+ /*
+ * Flags for lockdep annotations.
+@@ -461,6 +431,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
@@ -765929,7 +1020985,15 @@
/*
* Flags for xfs_itruncate_start().
-@@ -515,7 +497,7 @@ int xfs_finish_reclaim_all(struct xfs_mount *, int);
+@@ -501,6 +472,7 @@ void xfs_ilock(xfs_inode_t *, uint);
+ int xfs_ilock_nowait(xfs_inode_t *, uint);
+ void xfs_iunlock(xfs_inode_t *, uint);
+ void xfs_ilock_demote(xfs_inode_t *, uint);
++int xfs_isilocked(xfs_inode_t *, uint);
+ void xfs_iflock(xfs_inode_t *);
+ int xfs_iflock_nowait(xfs_inode_t *);
+ uint xfs_ilock_map_shared(xfs_inode_t *);
+@@ -515,7 +487,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 **,
@@ -765938,7 +1021002,16 @@
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 *);
+@@ -552,7 +524,7 @@ int xfs_iflush(xfs_inode_t *, uint);
+ void xfs_iflush_all(struct xfs_mount *);
+ void xfs_ichgtime(xfs_inode_t *, int);
+ xfs_fsize_t xfs_file_last_byte(xfs_inode_t *);
+-void xfs_lock_inodes(xfs_inode_t **, int, int, uint);
++void xfs_lock_inodes(xfs_inode_t **, int, uint);
+
+ void xfs_synchronize_atime(xfs_inode_t *);
+ void xfs_mark_inode_dirty_sync(xfs_inode_t *);
+@@ -597,7 +569,6 @@ void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
#define xfs_inobp_check(mp, bp)
#endif /* DEBUG */
@@ -765947,7 +1021020,7 @@
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
+index 2c775b4..167b33f 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -40,6 +40,7 @@
@@ -765958,6 +1021031,41 @@
kmem_zone_t *xfs_ili_zone; /* inode log item zone */
+@@ -546,7 +547,7 @@ STATIC void
+ xfs_inode_item_pin(
+ xfs_inode_log_item_t *iip)
+ {
+- ASSERT(ismrlocked(&(iip->ili_inode->i_lock), MR_UPDATE));
++ ASSERT(xfs_isilocked(iip->ili_inode, XFS_ILOCK_EXCL));
+ xfs_ipin(iip->ili_inode);
+ }
+
+@@ -663,13 +664,13 @@ xfs_inode_item_unlock(
+
+ ASSERT(iip != NULL);
+ ASSERT(iip->ili_inode->i_itemp != NULL);
+- ASSERT(ismrlocked(&(iip->ili_inode->i_lock), MR_UPDATE));
++ ASSERT(xfs_isilocked(iip->ili_inode, XFS_ILOCK_EXCL));
+ ASSERT((!(iip->ili_inode->i_itemp->ili_flags &
+ XFS_ILI_IOLOCKED_EXCL)) ||
+- ismrlocked(&(iip->ili_inode->i_iolock), MR_UPDATE));
++ xfs_isilocked(iip->ili_inode, XFS_IOLOCK_EXCL));
+ ASSERT((!(iip->ili_inode->i_itemp->ili_flags &
+ XFS_ILI_IOLOCKED_SHARED)) ||
+- ismrlocked(&(iip->ili_inode->i_iolock), MR_ACCESS));
++ xfs_isilocked(iip->ili_inode, XFS_IOLOCK_SHARED));
+ /*
+ * Clear the transaction pointer in the inode.
+ */
+@@ -768,7 +769,7 @@ xfs_inode_item_pushbuf(
+
+ ip = iip->ili_inode;
+
+- ASSERT(ismrlocked(&(ip->i_lock), MR_ACCESS));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED));
+
+ /*
+ * The ili_pushbuf_flag keeps others from
@@ -813,7 +814,12 @@ xfs_inode_item_pushbuf(
XFS_LOG_FORCE);
}
@@ -765972,6 +1021080,15 @@
} else {
xfs_buf_relse(bp);
}
+@@ -851,7 +857,7 @@ xfs_inode_item_push(
+
+ ip = iip->ili_inode;
+
+- ASSERT(ismrlocked(&(ip->i_lock), MR_ACCESS));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED));
+ ASSERT(issemalocked(&(ip->i_flock)));
+ /*
+ * Since we were able to lock the inode's flush lock and
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
@@ -765992,10 +1021109,56 @@
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
+index fde37f8..7edcde6 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
-@@ -802,8 +802,11 @@ xfs_iomap_write_allocate(
+@@ -196,14 +196,14 @@ xfs_iomap(
+ break;
+ case BMAPI_WRITE:
+ xfs_iomap_enter_trace(XFS_IOMAP_WRITE_ENTER, ip, offset, count);
+- lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR;
++ lockmode = XFS_ILOCK_EXCL;
+ if (flags & BMAPI_IGNSTATE)
+ bmapi_flags |= XFS_BMAPI_IGSTATE|XFS_BMAPI_ENTIRE;
+ xfs_ilock(ip, lockmode);
+ break;
+ case BMAPI_ALLOCATE:
+ xfs_iomap_enter_trace(XFS_IOMAP_ALLOC_ENTER, ip, offset, count);
+- lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD;
++ lockmode = XFS_ILOCK_SHARED;
+ bmapi_flags = XFS_BMAPI_ENTIRE;
+
+ /* Attempt non-blocking lock */
+@@ -523,8 +523,7 @@ xfs_iomap_write_direct(
+ goto error_out;
+ }
+
+- if (unlikely(!imap.br_startblock &&
+- !(XFS_IS_REALTIME_INODE(ip)))) {
++ if (!(imap.br_startblock || XFS_IS_REALTIME_INODE(ip))) {
+ error = xfs_cmn_err_fsblock_zero(ip, &imap);
+ goto error_out;
+ }
+@@ -624,7 +623,7 @@ xfs_iomap_write_delay(
+ int prealloc, fsynced = 0;
+ int error;
+
+- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0);
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+
+ /*
+ * Make sure that the dquots are there. This doesn't hold
+@@ -686,8 +685,7 @@ retry:
+ goto retry;
+ }
+
+- if (unlikely(!imap[0].br_startblock &&
+- !(XFS_IS_REALTIME_INODE(ip))))
++ if (!(imap[0].br_startblock || XFS_IS_REALTIME_INODE(ip)))
+ return xfs_cmn_err_fsblock_zero(ip, &imap[0]);
+
+ *ret_imap = imap[0];
+@@ -802,8 +800,11 @@ xfs_iomap_write_allocate(
*/
nimaps = 1;
end_fsb = XFS_B_TO_FSB(mp, ip->i_size);
@@ -766009,11 +1021172,50 @@
last_block = XFS_FILEOFF_MAX(last_block, end_fsb);
if ((map_start_fsb + count_fsb) > last_block) {
count_fsb = last_block - map_start_fsb;
+@@ -835,9 +836,9 @@ xfs_iomap_write_allocate(
+ * See if we were able to allocate an extent that
+ * covers at least part of the callers request
+ */
+- if (unlikely(!imap.br_startblock &&
+- XFS_IS_REALTIME_INODE(ip)))
++ if (!(imap.br_startblock || XFS_IS_REALTIME_INODE(ip)))
+ return xfs_cmn_err_fsblock_zero(ip, &imap);
++
+ if ((offset_fsb >= imap.br_startoff) &&
+ (offset_fsb < (imap.br_startoff +
+ imap.br_blockcount))) {
+@@ -931,8 +932,7 @@ xfs_iomap_write_unwritten(
+ if (error)
+ return XFS_ERROR(error);
+
+- if (unlikely(!imap.br_startblock &&
+- !(XFS_IS_REALTIME_INODE(ip))))
++ if (!(imap.br_startblock || XFS_IS_REALTIME_INODE(ip)))
+ return xfs_cmn_err_fsblock_zero(ip, &imap);
+
+ if ((numblks_fsb = imap.br_blockcount) == 0) {
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
-index f615e04..eb85bde 100644
+index f615e04..419de15 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
-@@ -129,7 +129,7 @@ xfs_bulkstat_one_iget(
+@@ -71,11 +71,6 @@ xfs_bulkstat_one_iget(
+
+ ASSERT(ip != NULL);
+ ASSERT(ip->i_blkno != (xfs_daddr_t)0);
+- if (ip->i_d.di_mode == 0) {
+- *stat = BULKSTAT_RV_NOTHING;
+- error = XFS_ERROR(ENOENT);
+- goto out_iput;
+- }
+
+ vp = XFS_ITOV(ip);
+ dic = &ip->i_d;
+@@ -124,12 +119,11 @@ xfs_bulkstat_one_iget(
+ break;
+ }
+
+- out_iput:
+ xfs_iput(ip, XFS_ILOCK_SHARED);
return error;
}
@@ -766022,7 +1021224,7 @@
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(
+@@ -198,8 +192,6 @@ xfs_bulkstat_one_dinode(
buf->bs_blocks = be64_to_cpu(dic->di_nblocks);
break;
}
@@ -766031,7 +1021233,7 @@
}
STATIC int
-@@ -614,7 +612,8 @@ xfs_bulkstat(
+@@ -614,7 +606,8 @@ xfs_bulkstat(
xfs_buf_relse(bp);
error = xfs_itobp(mp, NULL, ip,
&dip, &bp, bno,
@@ -767101,7 +1022303,7 @@
* 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
+index 8ed164e..da39884 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -43,8 +43,9 @@
@@ -767115,8 +1022317,15 @@
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 *);
+@@ -53,17 +54,18 @@ STATIC void xfs_unmountfs_wait(xfs_mount_t *);
+ #ifdef HAVE_PERCPU_SB
+ STATIC void xfs_icsb_destroy_counters(xfs_mount_t *);
+ STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t,
+- int, int);
+-STATIC void xfs_icsb_sync_counters(xfs_mount_t *);
++ int);
++STATIC void xfs_icsb_balance_counter_locked(xfs_mount_t *, xfs_sb_field_t,
++ int);
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);
@@ -767124,7 +1022333,15 @@
#else
-@@ -956,7 +957,6 @@ xfs_mountfs(
+ #define xfs_icsb_destroy_counters(mp) do { } while (0)
+-#define xfs_icsb_balance_counter(mp, a, b, c) do { } while (0)
+-#define xfs_icsb_sync_counters(mp) do { } while (0)
++#define xfs_icsb_balance_counter(mp, a, b) do { } while (0)
++#define xfs_icsb_balance_counter_locked(mp, a, b) do { } while (0)
+ #define xfs_icsb_modify_counters(mp, a, b, c) do { } while (0)
+
+ #endif
+@@ -956,7 +958,6 @@ xfs_mountfs(
{
xfs_sb_t *sbp = &(mp->m_sb);
xfs_inode_t *rip;
@@ -767132,7 +1022349,7 @@
__uint64_t resblks;
__int64_t update_flags = 0LL;
uint quotamount, quotaflags;
-@@ -964,11 +964,6 @@ xfs_mountfs(
+@@ -964,11 +965,6 @@ xfs_mountfs(
int uuid_mounted = 0;
int error = 0;
@@ -767144,7 +1022361,7 @@
xfs_mount_common(mp, sbp);
/*
-@@ -1163,7 +1158,6 @@ xfs_mountfs(
+@@ -1163,7 +1159,6 @@ xfs_mountfs(
}
ASSERT(rip != NULL);
@@ -767152,7 +1022369,7 @@
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(
+@@ -1195,8 +1190,13 @@ xfs_mountfs(
/*
* If fs is not mounted readonly, then update the superblock changes.
*/
@@ -767168,7 +1022385,7 @@
/*
* Initialise the XFS quota management subsystem for this mount
-@@ -1233,12 +1232,15 @@ xfs_mountfs(
+@@ -1233,12 +1233,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
@@ -767186,7 +1022403,7 @@
return 0;
-@@ -1246,7 +1248,7 @@ xfs_mountfs(
+@@ -1246,7 +1249,7 @@ xfs_mountfs(
/*
* Free up the root inode.
*/
@@ -767195,7 +1022412,7 @@
error3:
xfs_log_unmount_dealloc(mp);
error2:
-@@ -1274,6 +1276,7 @@ int
+@@ -1274,6 +1277,7 @@ int
xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
{
__uint64_t resblks;
@@ -767203,7 +1022420,7 @@
/*
* We can potentially deadlock here if we have an inode cluster
-@@ -1317,9 +1320,15 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
+@@ -1317,9 +1321,15 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
* value does not matter....
*/
resblks = 0;
@@ -767221,7 +1022438,16 @@
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(
+@@ -1391,7 +1401,7 @@ xfs_log_sbcount(
+ if (!xfs_fs_writable(mp))
+ return 0;
+
+- xfs_icsb_sync_counters(mp);
++ xfs_icsb_sync_counters(mp, 0);
+
+ /*
+ * we don't need to do this if we are updating the superblock
+@@ -1411,9 +1421,8 @@ xfs_log_sbcount(
xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS);
if (sync)
xfs_trans_set_sync(tp);
@@ -767233,7 +1022459,7 @@
}
STATIC void
-@@ -1462,7 +1470,6 @@ xfs_unmountfs_writesb(xfs_mount_t *mp)
+@@ -1462,7 +1471,6 @@ xfs_unmountfs_writesb(xfs_mount_t *mp)
XFS_BUF_UNASYNC(sbp);
ASSERT(XFS_BUF_TARGET(sbp) == mp->m_ddev_targp);
xfsbdstrat(mp, sbp);
@@ -767241,7 +1022467,7 @@
error = xfs_iowait(sbp);
if (error)
xfs_ioerror_alert("xfs_unmountfs_writesb",
-@@ -1911,24 +1918,27 @@ xfs_uuid_unmount(
+@@ -1911,24 +1919,27 @@ xfs_uuid_unmount(
* be altered by the mount options, as well as any potential sb_features2
* fixup. Only the first superblock is updated.
*/
@@ -767274,7 +1022500,49 @@
}
-@@ -2189,7 +2199,7 @@ xfs_icsb_counter_disabled(
+@@ -2016,9 +2027,9 @@ xfs_icsb_cpu_notify(
+ case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
+ xfs_icsb_lock(mp);
+- xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0, 0);
+- xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0, 0);
+- xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0, 0);
++ xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
++ xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
++ xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
+ xfs_icsb_unlock(mp);
+ break;
+ case CPU_DEAD:
+@@ -2038,12 +2049,9 @@ xfs_icsb_cpu_notify(
+
+ memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
+
+- xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT,
+- XFS_ICSB_SB_LOCKED, 0);
+- xfs_icsb_balance_counter(mp, XFS_SBS_IFREE,
+- XFS_ICSB_SB_LOCKED, 0);
+- xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS,
+- XFS_ICSB_SB_LOCKED, 0);
++ xfs_icsb_balance_counter_locked(mp, XFS_SBS_ICOUNT, 0);
++ xfs_icsb_balance_counter_locked(mp, XFS_SBS_IFREE, 0);
++ xfs_icsb_balance_counter_locked(mp, XFS_SBS_FDBLOCKS, 0);
+ spin_unlock(&mp->m_sb_lock);
+ xfs_icsb_unlock(mp);
+ break;
+@@ -2095,9 +2103,9 @@ xfs_icsb_reinit_counters(
+ * initial balance kicks us off correctly
+ */
+ mp->m_icsb_counters = -1;
+- xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0, 0);
+- xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0, 0);
+- xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0, 0);
++ xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
++ xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
++ xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
+ xfs_icsb_unlock(mp);
+ }
+
+@@ -2189,7 +2197,7 @@ xfs_icsb_counter_disabled(
return test_bit(field, &mp->m_icsb_counters);
}
@@ -767283,7 +1022551,7 @@
xfs_icsb_disable_counter(
xfs_mount_t *mp,
xfs_sb_field_t field)
-@@ -2207,7 +2217,7 @@ xfs_icsb_disable_counter(
+@@ -2207,13 +2215,13 @@ xfs_icsb_disable_counter(
* the m_icsb_mutex.
*/
if (xfs_icsb_counter_disabled(mp, field))
@@ -767292,7 +1022560,14 @@
xfs_icsb_lock_all_counters(mp);
if (!test_and_set_bit(field, &mp->m_icsb_counters)) {
-@@ -2230,8 +2240,6 @@ xfs_icsb_disable_counter(
+ /* drain back to superblock */
+
+- xfs_icsb_count(mp, &cnt, XFS_ICSB_SB_LOCKED|XFS_ICSB_LAZY_COUNT);
++ xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT);
+ switch(field) {
+ case XFS_SBS_ICOUNT:
+ mp->m_sb.sb_icount = cnt.icsb_icount;
+@@ -2230,8 +2238,6 @@ xfs_icsb_disable_counter(
}
xfs_icsb_unlock_all_counters(mp);
@@ -767301,8 +1022576,137 @@
}
STATIC void
+@@ -2270,38 +2276,33 @@ xfs_icsb_enable_counter(
+ }
+
+ void
+-xfs_icsb_sync_counters_flags(
++xfs_icsb_sync_counters_locked(
+ xfs_mount_t *mp,
+ int flags)
+ {
+ xfs_icsb_cnts_t cnt;
+
+- /* Pass 1: lock all counters */
+- if ((flags & XFS_ICSB_SB_LOCKED) == 0)
+- spin_lock(&mp->m_sb_lock);
+-
+ xfs_icsb_count(mp, &cnt, flags);
+
+- /* Step 3: update mp->m_sb fields */
+ if (!xfs_icsb_counter_disabled(mp, XFS_SBS_ICOUNT))
+ mp->m_sb.sb_icount = cnt.icsb_icount;
+ if (!xfs_icsb_counter_disabled(mp, XFS_SBS_IFREE))
+ mp->m_sb.sb_ifree = cnt.icsb_ifree;
+ if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
+ mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
+-
+- if ((flags & XFS_ICSB_SB_LOCKED) == 0)
+- spin_unlock(&mp->m_sb_lock);
+ }
+
+ /*
+ * Accurate update of per-cpu counters to incore superblock
+ */
+-STATIC void
++void
+ xfs_icsb_sync_counters(
+- xfs_mount_t *mp)
++ xfs_mount_t *mp,
++ int flags)
+ {
+- xfs_icsb_sync_counters_flags(mp, 0);
++ spin_lock(&mp->m_sb_lock);
++ xfs_icsb_sync_counters_locked(mp, flags);
++ spin_unlock(&mp->m_sb_lock);
+ }
+
+ /*
+@@ -2324,19 +2325,15 @@ xfs_icsb_sync_counters(
+ #define XFS_ICSB_FDBLK_CNTR_REENABLE(mp) \
+ (uint64_t)(512 + XFS_ALLOC_SET_ASIDE(mp))
+ STATIC void
+-xfs_icsb_balance_counter(
++xfs_icsb_balance_counter_locked(
+ xfs_mount_t *mp,
+ xfs_sb_field_t field,
+- int flags,
+ int min_per_cpu)
+ {
+ uint64_t count, resid;
+ int weight = num_online_cpus();
+ uint64_t min = (uint64_t)min_per_cpu;
+
+- if (!(flags & XFS_ICSB_SB_LOCKED))
+- spin_lock(&mp->m_sb_lock);
+-
+ /* disable counter and sync counter */
+ xfs_icsb_disable_counter(mp, field);
+
+@@ -2346,19 +2343,19 @@ xfs_icsb_balance_counter(
+ count = mp->m_sb.sb_icount;
+ resid = do_div(count, weight);
+ if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
+- goto out;
++ return;
+ break;
+ case XFS_SBS_IFREE:
+ count = mp->m_sb.sb_ifree;
+ resid = do_div(count, weight);
+ if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
+- goto out;
++ return;
+ break;
+ case XFS_SBS_FDBLOCKS:
+ count = mp->m_sb.sb_fdblocks;
+ resid = do_div(count, weight);
+ if (count < max(min, XFS_ICSB_FDBLK_CNTR_REENABLE(mp)))
+- goto out;
++ return;
+ break;
+ default:
+ BUG();
+@@ -2367,9 +2364,17 @@ xfs_icsb_balance_counter(
+ }
+
+ xfs_icsb_enable_counter(mp, field, count, resid);
+-out:
+- if (!(flags & XFS_ICSB_SB_LOCKED))
+- spin_unlock(&mp->m_sb_lock);
++}
++
++STATIC void
++xfs_icsb_balance_counter(
++ xfs_mount_t *mp,
++ xfs_sb_field_t fields,
++ int min_per_cpu)
++{
++ spin_lock(&mp->m_sb_lock);
++ xfs_icsb_balance_counter_locked(mp, fields, min_per_cpu);
++ spin_unlock(&mp->m_sb_lock);
+ }
+
+ STATIC int
+@@ -2476,7 +2481,7 @@ slow_path:
+ * we are done.
+ */
+ if (ret != ENOSPC)
+- xfs_icsb_balance_counter(mp, field, 0, 0);
++ xfs_icsb_balance_counter(mp, field, 0);
+ xfs_icsb_unlock(mp);
+ return ret;
+
+@@ -2500,7 +2505,7 @@ balance_counter:
+ * will either succeed through the fast path or slow path without
+ * another balance operation being required.
+ */
+- xfs_icsb_balance_counter(mp, field, 0, delta);
++ xfs_icsb_balance_counter(mp, field, delta);
+ xfs_icsb_unlock(mp);
+ goto again;
+ }
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
-index 1d8a472..1ed5751 100644
+index 1d8a472..63e0693 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -66,17 +66,17 @@ struct xfs_mru_cache;
@@ -767357,7 +1022761,25 @@
/*
-@@ -220,7 +220,7 @@ extern void xfs_icsb_sync_counters_flags(struct xfs_mount *, int);
+@@ -206,21 +206,22 @@ typedef struct xfs_icsb_cnts {
+
+ #define XFS_ICSB_FLAG_LOCK (1 << 0) /* counter lock bit */
+
+-#define XFS_ICSB_SB_LOCKED (1 << 0) /* sb already locked */
+ #define XFS_ICSB_LAZY_COUNT (1 << 1) /* accuracy not needed */
+
+ extern int xfs_icsb_init_counters(struct xfs_mount *);
+ extern void xfs_icsb_reinit_counters(struct xfs_mount *);
+-extern void xfs_icsb_sync_counters_flags(struct xfs_mount *, int);
++extern void xfs_icsb_sync_counters(struct xfs_mount *, int);
++extern void xfs_icsb_sync_counters_locked(struct xfs_mount *, int);
+
+ #else
+ #define xfs_icsb_init_counters(mp) (0)
+ #define xfs_icsb_reinit_counters(mp) do { } while (0)
+-#define xfs_icsb_sync_counters_flags(mp, flags) do { } while (0)
++#define xfs_icsb_sync_counters(mp, flags) do { } while (0)
++#define xfs_icsb_sync_counters_locked(mp, flags) do { } while (0)
#endif
typedef struct xfs_ail {
@@ -767366,7 +1022788,7 @@
uint xa_gen;
struct task_struct *xa_task;
xfs_lsn_t xa_target;
-@@ -401,7 +401,7 @@ typedef struct xfs_mount {
+@@ -401,7 +402,7 @@ typedef struct xfs_mount {
/*
* Allow large block sizes to be reported to userspace programs if the
@@ -767376,7 +1022798,7 @@
* 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
+index 7eb157a..d8063e1 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -36,7 +36,6 @@
@@ -767387,21 +1022809,54 @@
#include "xfs_utils.h"
#include "xfs_trans_space.h"
#include "xfs_vnodeops.h"
-@@ -84,25 +83,23 @@ int xfs_rename_skip, xfs_rename_nskip;
+@@ -56,94 +55,32 @@ xfs_rename_unlock4(
+
+ xfs_iunlock(i_tab[0], lock_mode);
+ for (i = 1; i < 4; i++) {
+- if (i_tab[i] == NULL) {
++ if (i_tab[i] == NULL)
+ break;
+- }
++
+ /*
+ * Watch out for duplicate entries in the table.
+ */
+- if (i_tab[i] != i_tab[i-1]) {
++ if (i_tab[i] != i_tab[i-1])
+ xfs_iunlock(i_tab[i], lock_mode);
+- }
+ }
+ }
+
+-#ifdef DEBUG
+-int xfs_rename_skip, xfs_rename_nskip;
+-#endif
+-
+ /*
+- * The following routine will acquire the locks required for a rename
+- * operation. The code understands the semantics of renames and will
+- * validate that name1 exists under dp1 & that name2 may or may not
+- * exist under dp2.
+- *
+- * We are renaming dp1/name1 to dp2/name2.
+- *
+- * Return ENOENT if dp1 does not exist, other lookup errors, or 0 for success.
++ * Enter all inodes for a rename transaction into a sorted array.
*/
- STATIC int
- xfs_lock_for_rename(
+-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
++STATIC void
++xfs_sort_for_rename(
+ 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
++ xfs_inode_t *ip2, /* in: 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 */
@@ -767409,62 +1022864,113 @@
+ int *num_inodes) /* out: number of inodes in array */
{
- xfs_inode_t *ip1, *ip2, *temp;
-+ xfs_inode_t *ip2 = NULL;
+- xfs_ino_t inum1, inum2;
+- int error;
+ xfs_inode_t *temp;
- xfs_ino_t inum1, inum2;
- int error;
int i, j;
- uint lock_mode;
- int diff_dirs = (dp1 != dp2);
-
+- 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);
+- /*
+- * First, find out the current inums of the entries so that we
+- * can determine the initial locking order. We'll have to
+- * sanity check stuff after all the locks have been acquired
+- * 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;
-
+-
+- inum1 = ip1->i_ino;
+-
- ASSERT(ip1);
- xfs_itrace_ref(ip1);
-
- /*
- * Unlock dp1 and lock dp2 if they are different.
- */
+- /*
+- * 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);
+- }
-
- 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(
+- if (error == ENOENT) { /* target does not need to exist. */
+- inum2 = 0;
+- } else if (error) {
+- /*
+- * If dp2 and dp1 are the same, the next line unlocks dp1.
+- * Got it?
+- */
+- xfs_iunlock_map_shared(dp2, lock_mode);
+- IRELE (ip1);
+- return error;
+- } else {
+- xfs_itrace_ref(ip2);
+- }
+
+ /*
+ * i_tab contains a list of pointers to inodes. We initialize
+@@ -155,20 +92,20 @@ xfs_lock_for_rename(
+ i_tab[0] = dp1;
+ i_tab[1] = dp2;
+ i_tab[2] = ip1;
+- if (inum2 == 0) {
+- *num_inodes = 3;
+- i_tab[3] = NULL;
+- } else {
++ if (ip2) {
*num_inodes = 4;
i_tab[3] = ip2;
++ } else {
++ *num_inodes = 3;
++ i_tab[3] = NULL;
}
-+ *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);
+ * most 4 elements to sort, so this is adequate.)
+ */
+- for (i=0; i < *num_inodes; i++) {
+- for (j=1; j < *num_inodes; j++) {
++ for (i = 0; i < *num_inodes; i++) {
++ for (j = 1; j < *num_inodes; j++) {
+ if (i_tab[j]->i_ino < i_tab[j-1]->i_ino) {
+ temp = i_tab[j];
+ i_tab[j] = i_tab[j-1];
+@@ -176,45 +113,6 @@ xfs_lock_for_rename(
+ }
+ }
}
-
+-
+- /*
+- * We have dp2 locked. If it isn't first, unlock it.
+- * If it is first, tell xfs_lock_inodes so it can skip it
+- * when locking. if dp1 == dp2, xfs_lock_inodes will skip both
+- * since they are equal. xfs_lock_inodes needs all these inodes
+- * so that it can unlock and retry if there might be a dead-lock
+- * potential with the log.
+- */
+-
+- if (i_tab[0] == dp2 && lock_mode == XFS_ILOCK_SHARED) {
+-#ifdef DEBUG
+- xfs_rename_skip++;
+-#endif
+- xfs_lock_inodes(i_tab, *num_inodes, 1, XFS_ILOCK_SHARED);
+- } else {
+-#ifdef DEBUG
+- xfs_rename_nskip++;
+-#endif
+- xfs_iunlock_map_shared(dp2, lock_mode);
+- xfs_lock_inodes(i_tab, *num_inodes, 0, XFS_ILOCK_SHARED);
+- }
+-
- /*
- * Set the return value. Null out any unused entries in i_tab.
- */
@@ -767480,10 +1022986,11 @@
- for (;i < 4; i++) {
- i_tab[i] = NULL;
- }
- return 0;
+- return 0;
}
-@@ -223,13 +199,13 @@ xfs_lock_for_rename(
+ /*
+@@ -223,13 +121,13 @@ xfs_lock_for_rename(
int
xfs_rename(
xfs_inode_t *src_dp,
@@ -767493,18 +1023000,23 @@
+ struct xfs_name *src_name,
+ xfs_inode_t *src_ip,
+ xfs_inode_t *target_dp,
-+ struct xfs_name *target_name)
++ struct xfs_name *target_name,
++ xfs_inode_t *target_ip)
{
- bhv_vnode_t *src_dir_vp = XFS_ITOV(src_dp);
- xfs_trans_t *tp;
+- xfs_trans_t *tp;
- xfs_inode_t *target_dp, *src_ip, *target_ip;
-+ xfs_inode_t *target_ip;
++ xfs_trans_t *tp = NULL;
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(
+@@ -239,99 +137,45 @@ xfs_rename(
+ int cancel_flags;
+ int committed;
+ xfs_inode_t *inodes[4];
+- int target_ip_dropped = 0; /* dropped target_ip link? */
int spaceres;
- int target_link_zero = 0;
+- int target_link_zero = 0;
int num_inodes;
- char *src_name = VNAME(src_vname);
- char *target_name = VNAME(target_vname);
@@ -767534,22 +1023046,75 @@
+ target_dp, DM_RIGHT_NULL,
+ src_name->name, target_name->name,
0, 0, 0);
- if (error) {
+- if (error) {
++ if (error)
return error;
-@@ -282,10 +245,8 @@ xfs_rename(
- * does not exist in the source directory.
- */
- tp = NULL;
+- }
+ }
+ /* Return through std_return after this point. */
+
+- /*
+- * Lock all the participating inodes. Depending upon whether
+- * the target_name exists in the target directory, and
+- * whether the target directory is the same as the source
+- * directory, we can lock from 2 to 4 inodes.
+- * xfs_lock_for_rename() will return ENOENT if src_name
+- * 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) {
+- if (error) {
+- /*
+- * We have nothing locked, no inode references, and
+- * no transaction, so just get out.
+- */
+- goto std_return;
+- }
+-
+- ASSERT(src_ip != NULL);
++ new_parent = (src_dp != target_dp);
++ src_is_directory = ((src_ip->i_d.di_mode & S_IFMT) == S_IFDIR);
+
+- if ((src_ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
++ if (src_is_directory) {
/*
- * We have nothing locked, no inode references, and
-@@ -331,7 +292,7 @@ xfs_rename(
+ * Check for link count overflow on target_dp
+ */
+- if (target_ip == NULL && (src_dp != target_dp) &&
++ if (target_ip == NULL && new_parent &&
+ target_dp->i_d.di_nlink >= XFS_MAXLINK) {
+ error = XFS_ERROR(EMLINK);
+- xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
+- goto rele_return;
++ goto std_return;
+ }
+ }
+
+- /*
+- * If we are using project inheritance, we only allow renames
+- * into our tree when the project IDs are the same; else the
+- * tree quota mechanism would be circumvented.
+- */
+- if (unlikely((target_dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
+- (target_dp->i_d.di_projid != src_ip->i_d.di_projid))) {
+- error = XFS_ERROR(EXDEV);
+- xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
+- goto rele_return;
+- }
+-
+- new_parent = (src_dp != target_dp);
+- src_is_directory = ((src_ip->i_d.di_mode & S_IFMT) == S_IFDIR);
+-
+- /*
+- * Drop the locks on our inodes so that we can start the transaction.
+- */
+- xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
++ xfs_sort_for_rename(src_dp, target_dp, src_ip, target_ip,
++ inodes, &num_inodes);
+
XFS_BMAP_INIT(&free_list, &first_block);
tp = xfs_trans_alloc(mp, XFS_TRANS_RENAME);
cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
@@ -767558,20 +1023123,78 @@
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(
+@@ -341,7 +185,7 @@ xfs_rename(
+ }
+ if (error) {
+ xfs_trans_cancel(tp, 0);
+- goto rele_return;
++ goto std_return;
+ }
+
+ /*
+@@ -349,13 +193,29 @@ xfs_rename(
+ */
+ if ((error = XFS_QM_DQVOPRENAME(mp, inodes))) {
+ xfs_trans_cancel(tp, cancel_flags);
+- goto rele_return;
++ goto std_return;
+ }
+
+ /*
+- * Reacquire the inode locks we dropped above.
++ * Lock all the participating inodes. Depending upon whether
++ * the target_name exists in the target directory, and
++ * whether the target directory is the same as the source
++ * directory, we can lock from 2 to 4 inodes.
+ */
+- xfs_lock_inodes(inodes, num_inodes, 0, XFS_ILOCK_EXCL);
++ xfs_lock_inodes(inodes, num_inodes, XFS_ILOCK_EXCL);
++
++ /*
++ * If we are using project inheritance, we only allow renames
++ * into our tree when the project IDs are the same; else the
++ * tree quota mechanism would be circumvented.
++ */
++ if (unlikely((target_dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
++ (target_dp->i_d.di_projid != src_ip->i_d.di_projid))) {
++ error = XFS_ERROR(EXDEV);
++ xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
++ xfs_trans_cancel(tp, cancel_flags);
++ goto std_return;
++ }
+
+ /*
+ * Join all the inodes to the transaction. From this point on,
+@@ -365,19 +225,19 @@ 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 ((src_ip != src_dp) && (src_ip != target_dp)) {
+- xfs_trans_ijoin(tp, src_ip, XFS_ILOCK_EXCL);
+- }
+- if ((target_ip != NULL) &&
+- (target_ip != src_ip) &&
+- (target_ip != src_dp) &&
+- (target_ip != target_dp)) {
++
++ IHOLD(src_ip);
++ xfs_trans_ijoin(tp, src_ip, XFS_ILOCK_EXCL);
++
++ if (target_ip) {
++ IHOLD(target_ip);
+ xfs_trans_ijoin(tp, target_ip, XFS_ILOCK_EXCL);
+ }
+
+@@ -389,9 +249,8 @@ xfs_rename(
* If there's no space reservation, check the entry will
* fit before actually inserting it.
*/
@@ -767583,7 +1023206,7 @@
goto error_return;
/*
* If target does not exist and the rename crosses
-@@ -399,8 +359,8 @@ xfs_rename(
+@@ -399,8 +258,8 @@ xfs_rename(
* to account for the ".." reference from the new entry.
*/
error = xfs_dir_createname(tp, target_dp, target_name,
@@ -767594,7 +1023217,7 @@
if (error == ENOSPC)
goto error_return;
if (error)
-@@ -439,7 +399,7 @@ xfs_rename(
+@@ -439,7 +298,7 @@ xfs_rename(
* name at the destination directory, remove it first.
*/
error = xfs_dir_replace(tp, target_dp, target_name,
@@ -767603,7 +1023226,26 @@
&first_block, &free_list, spaceres);
if (error)
goto abort_return;
-@@ -476,7 +436,8 @@ xfs_rename(
+@@ -452,7 +311,6 @@ xfs_rename(
+ error = xfs_droplink(tp, target_ip);
+ if (error)
+ goto abort_return;
+- target_ip_dropped = 1;
+
+ if (src_is_directory) {
+ /*
+@@ -462,10 +320,6 @@ xfs_rename(
+ if (error)
+ goto abort_return;
+ }
+-
+- /* Do this test while we still hold the locks */
+- target_link_zero = (target_ip)->i_d.di_nlink==0;
+-
+ } /* target_ip != NULL */
+
+ /*
+@@ -476,7 +330,8 @@ xfs_rename(
* Rewrite the ".." entry to point to the new
* directory.
*/
@@ -767613,7 +1023255,7 @@
&first_block, &free_list, spaceres);
ASSERT(error != EEXIST);
if (error)
-@@ -512,8 +473,8 @@ xfs_rename(
+@@ -512,8 +367,8 @@ xfs_rename(
goto abort_return;
}
@@ -767624,19 +1023266,72 @@
if (error)
goto abort_return;
xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
-@@ -580,10 +541,8 @@ xfs_rename(
+@@ -531,15 +386,6 @@ xfs_rename(
+ }
+
+ /*
+- * If there was a target inode, take an extra reference on
+- * it here so that it doesn't go to xfs_inactive() from
+- * within the commit.
+- */
+- if (target_ip != NULL) {
+- IHOLD(target_ip);
+- }
+-
+- /*
+ * If this is a synchronous mount, make sure that the
+ * rename transaction goes to disk before returning to
+ * the user.
+@@ -548,30 +394,11 @@ xfs_rename(
+ xfs_trans_set_sync(tp);
+ }
+
+- /*
+- * Take refs. for vop_link_removed calls below. No need to worry
+- * about directory refs. because the caller holds them.
+- *
+- * Do holds before the xfs_bmap_finish since it might rele them down
+- * to zero.
+- */
+-
+- if (target_ip_dropped)
+- IHOLD(target_ip);
+- IHOLD(src_ip);
+-
+ error = xfs_bmap_finish(&tp, &free_list, &committed);
+ if (error) {
+ xfs_bmap_cancel(&free_list);
+ xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
+ XFS_TRANS_ABORT));
+- if (target_ip != NULL) {
+- IRELE(target_ip);
+- }
+- if (target_ip_dropped) {
+- IRELE(target_ip);
+- }
+- IRELE(src_ip);
+ goto std_return;
+ }
+
+@@ -580,17 +407,6 @@ 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);
+- IRELE(target_ip);
- }
- /*
- * Let interposed file systems know about removed links.
- */
-@@ -598,9 +557,9 @@ std_return:
+- /*
+- * Let interposed file systems know about removed links.
+- */
+- if (target_ip_dropped)
+- IRELE(target_ip);
+-
+- IRELE(src_ip);
+
+ /* Fall through to std_return with error = 0 or errno from
+ * xfs_trans_commit */
+@@ -598,9 +414,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,
@@ -767649,6 +1023344,18 @@
0, error, 0);
}
return error;
+@@ -612,11 +428,4 @@ std_return:
+ xfs_bmap_cancel(&free_list);
+ xfs_trans_cancel(tp, cancel_flags);
+ goto std_return;
+-
+- rele_return:
+- IRELE(src_ip);
+- if (target_ip != NULL) {
+- IRELE(target_ip);
+- }
+- goto std_return;
+ }
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 47082c0..a0dc6e5 100644
--- a/fs/xfs/xfs_rtalloc.c
@@ -768212,6 +1023919,54 @@
*/
if (tp->t_flags & XFS_TRANS_DIRTY)
xfs_force_shutdown(tp->t_mountp,
+diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
+index b8db1d5..4c70bf5 100644
+--- a/fs/xfs/xfs_trans_inode.c
++++ b/fs/xfs/xfs_trans_inode.c
+@@ -111,13 +111,13 @@ xfs_trans_iget(
+ */
+ ASSERT(ip->i_itemp != NULL);
+ ASSERT(lock_flags & XFS_ILOCK_EXCL);
+- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+ ASSERT((!(lock_flags & XFS_IOLOCK_EXCL)) ||
+- ismrlocked(&ip->i_iolock, MR_UPDATE));
++ xfs_isilocked(ip, XFS_IOLOCK_EXCL));
+ ASSERT((!(lock_flags & XFS_IOLOCK_EXCL)) ||
+ (ip->i_itemp->ili_flags & XFS_ILI_IOLOCKED_EXCL));
+ ASSERT((!(lock_flags & XFS_IOLOCK_SHARED)) ||
+- ismrlocked(&ip->i_iolock, (MR_UPDATE | MR_ACCESS)));
++ xfs_isilocked(ip, XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED));
+ ASSERT((!(lock_flags & XFS_IOLOCK_SHARED)) ||
+ (ip->i_itemp->ili_flags & XFS_ILI_IOLOCKED_ANY));
+
+@@ -185,7 +185,7 @@ xfs_trans_ijoin(
+ xfs_inode_log_item_t *iip;
+
+ ASSERT(ip->i_transp == NULL);
+- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+ ASSERT(lock_flags & XFS_ILOCK_EXCL);
+ if (ip->i_itemp == NULL)
+ xfs_inode_item_init(ip, ip->i_mount);
+@@ -232,7 +232,7 @@ xfs_trans_ihold(
+ {
+ ASSERT(ip->i_transp == tp);
+ ASSERT(ip->i_itemp != NULL);
+- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+
+ ip->i_itemp->ili_flags |= XFS_ILI_HOLD;
+ }
+@@ -257,7 +257,7 @@ xfs_trans_log_inode(
+
+ ASSERT(ip->i_transp == tp);
+ ASSERT(ip->i_itemp != NULL);
+- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+
+ lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)(ip->i_itemp));
+ ASSERT(lidp != NULL);
diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h
index 5c89be4..0f51916 100644
--- a/fs/xfs/xfs_types.h
@@ -768227,10 +1023982,10 @@
+
#endif /* __XFS_TYPES_H__ */
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
-index 18a85e7..2b8dc7e 100644
+index 18a85e7..98e5f11 100644
--- a/fs/xfs/xfs_utils.c
+++ b/fs/xfs/xfs_utils.c
-@@ -40,34 +40,12 @@
+@@ -40,71 +40,6 @@
#include "xfs_itable.h"
#include "xfs_utils.h"
@@ -768256,30 +1024011,66 @@
- VN_HOLD(vp);
- return 0;
-}
-
- int
- xfs_dir_lookup_int(
- xfs_inode_t *dp,
- uint lock_mode,
+-
+-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)
+- xfs_ino_t *inum,
+- xfs_inode_t **ipp)
+-{
+- int error;
+-
+- xfs_itrace_entry(dp);
+-
+- error = xfs_dir_lookup(NULL, dp, VNAME(dentry), VNAMELEN(dentry), inum);
+- if (!error) {
+- /*
+- * Unlock the directory. We do this because we can't
+- * hold the directory lock while doing the vn_get()
+- * in xfs_iget(). Doing so could cause us to hold
+- * a lock while waiting for the inode to finish
+- * being inactive while it's waiting for a log
+- * reservation in the inactive routine.
+- */
+- xfs_iunlock(dp, lock_mode);
+- error = xfs_iget(dp->i_mount, NULL, *inum, 0, 0, ipp, 0);
+- xfs_ilock(dp, lock_mode);
+-
+- if (error) {
+- *ipp = NULL;
+- } else if ((*ipp)->i_d.di_mode == 0) {
+- /*
+- * The inode has been freed. Something is
+- * wrong so just get out of here.
+- */
+- xfs_iunlock(dp, lock_mode);
+- xfs_iput_new(*ipp, 0);
+- *ipp = NULL;
+- xfs_ilock(dp, lock_mode);
+- error = XFS_ERROR(ENOENT);
+- }
+- }
+- return error;
+-}
+
+ /*
+ * Allocates a new inode from disk and return a pointer to the
+@@ -332,7 +267,7 @@ xfs_bump_ino_vers2(
{
-@@ -75,7 +53,7 @@ xfs_dir_lookup_int(
+ xfs_mount_t *mp;
- xfs_itrace_entry(dp);
+- ASSERT(ismrlocked (&ip->i_lock, MR_UPDATE));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+ ASSERT(ip->i_d.di_version == XFS_DINODE_VERSION_1);
-- 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
+ ip->i_d.di_version = XFS_DINODE_VERSION_2;
diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h
-index f857fcc..175b126 100644
+index f857fcc..f316cb8 100644
--- a/fs/xfs/xfs_utils.h
+++ b/fs/xfs/xfs_utils.h
-@@ -21,15 +21,14 @@
+@@ -21,15 +21,12 @@
#define IRELE(ip) VN_RELE(XFS_ITOV(ip))
#define IHOLD(ip) VN_HOLD(XFS_ITOV(ip))
@@ -768288,8 +1024079,6 @@
- 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,
@@ -768303,7 +1024092,7 @@
#endif /* __XFS_UTILS_H__ */
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
-index 7094caf..fc48158 100644
+index 7094caf..30bacd8 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -43,7 +43,6 @@
@@ -768367,15 +1024156,16 @@
xfs_filestream_uninit();
xfs_mru_cache_uninit();
xfs_acl_zone_destroy(xfs_acl_zone);
-@@ -189,7 +186,6 @@ xfs_cleanup(void)
+@@ -189,7 +186,7 @@ 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);
++ kmem_zone_destroy(xfs_log_ticket_zone);
}
/*
-@@ -573,7 +569,7 @@ xfs_unmount(
+@@ -573,7 +570,7 @@ xfs_unmount(
#ifdef HAVE_DMAPI
if (mp->m_flags & XFS_MOUNT_DMAPI) {
error = XFS_SEND_PREUNMOUNT(mp,
@@ -768384,7 +1024174,7 @@
NULL, NULL, 0, 0,
(mp->m_dmevmask & (1<<DM_EVENT_PREUNMOUNT))?
0:DM_FLAGS_UNWANTED);
-@@ -584,11 +580,6 @@ xfs_unmount(
+@@ -584,11 +581,6 @@ xfs_unmount(
0 : DM_FLAGS_UNWANTED;
}
#endif
@@ -768396,7 +1024186,7 @@
/*
* Blow away any referenced inode in the filestreams cache.
-@@ -607,7 +598,7 @@ xfs_unmount(
+@@ -607,7 +599,7 @@ xfs_unmount(
/*
* Drop the reference count
*/
@@ -768405,7 +1024195,7 @@
/*
* If we're forcing a shutdown, typically because of a media error,
-@@ -629,7 +620,7 @@ out:
+@@ -629,7 +621,7 @@ out:
/* Note: mp structure must still exist for
* XFS_SEND_UNMOUNT() call.
*/
@@ -768414,7 +1024204,7 @@
DM_RIGHT_NULL, 0, error, unmount_event_flags);
}
if (xfs_unmountfs_needed) {
-@@ -646,13 +637,12 @@ out:
+@@ -646,13 +638,12 @@ out:
return XFS_ERROR(error);
}
@@ -768429,7 +1024219,7 @@
xfs_flush_buftarg(mp->m_ddev_targp, 0);
xfs_finish_reclaim_all(mp, 0);
-@@ -671,8 +661,6 @@ xfs_quiesce_fs(
+@@ -671,8 +662,6 @@ xfs_quiesce_fs(
count++;
}
} while (count < 2);
@@ -768438,7 +1024228,7 @@
}
/*
-@@ -684,6 +672,8 @@ void
+@@ -684,6 +673,8 @@ void
xfs_attr_quiesce(
xfs_mount_t *mp)
{
@@ -768447,7 +1024237,7 @@
/* wait for all modifications to complete */
while (atomic_read(&mp->m_active_trans) > 0)
delay(100);
-@@ -694,7 +684,11 @@ xfs_attr_quiesce(
+@@ -694,7 +685,11 @@ xfs_attr_quiesce(
ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
/* Push the superblock and write an unmount record */
@@ -768460,7 +1024250,7 @@
xfs_log_unmount_write(mp);
xfs_unmountfs_writesb(mp);
}
-@@ -790,8 +784,8 @@ xfs_unmount_flush(
+@@ -790,8 +785,8 @@ xfs_unmount_flush(
goto fscorrupt_out2;
if (rbmip) {
@@ -768471,7 +1024261,7 @@
}
xfs_iunlock(rip, XFS_ILOCK_EXCL);
-@@ -1169,10 +1163,10 @@ xfs_sync_inodes(
+@@ -1169,10 +1164,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
@@ -768484,7 +1024274,7 @@
* we have to go for the mount lock again in the
* inactive code.
*/
-@@ -1180,7 +1174,7 @@ xfs_sync_inodes(
+@@ -1180,7 +1175,7 @@ xfs_sync_inodes(
IPOINTER_INSERT(ip, mp);
}
@@ -768493,7 +1024283,7 @@
vnode_refed = B_FALSE;
}
-@@ -1323,30 +1317,8 @@ xfs_syncsub(
+@@ -1323,30 +1318,8 @@ xfs_syncsub(
}
/*
@@ -768525,7 +1024315,7 @@
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
+index 64c5953..70702a6 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -48,7 +48,6 @@
@@ -768536,7 +1024326,156 @@
#include "xfs_trans_space.h"
#include "xfs_log_priv.h"
#include "xfs_filestream.h"
-@@ -327,7 +326,7 @@ xfs_setattr(
+@@ -77,132 +76,6 @@ xfs_open(
+ }
+
+ /*
+- * xfs_getattr
+- */
+-int
+-xfs_getattr(
+- xfs_inode_t *ip,
+- bhv_vattr_t *vap,
+- int flags)
+-{
+- bhv_vnode_t *vp = XFS_ITOV(ip);
+- xfs_mount_t *mp = ip->i_mount;
+-
+- xfs_itrace_entry(ip);
+-
+- if (XFS_FORCED_SHUTDOWN(mp))
+- return XFS_ERROR(EIO);
+-
+- if (!(flags & ATTR_LAZY))
+- xfs_ilock(ip, XFS_ILOCK_SHARED);
+-
+- vap->va_size = XFS_ISIZE(ip);
+- if (vap->va_mask == XFS_AT_SIZE)
+- goto all_done;
+-
+- vap->va_nblocks =
+- XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks);
+- vap->va_nodeid = ip->i_ino;
+-#if XFS_BIG_INUMS
+- vap->va_nodeid += mp->m_inoadd;
+-#endif
+- vap->va_nlink = ip->i_d.di_nlink;
+-
+- /*
+- * Quick exit for non-stat callers
+- */
+- if ((vap->va_mask &
+- ~(XFS_AT_SIZE|XFS_AT_FSID|XFS_AT_NODEID|
+- XFS_AT_NLINK|XFS_AT_BLKSIZE)) == 0)
+- goto all_done;
+-
+- /*
+- * Copy from in-core inode.
+- */
+- vap->va_mode = ip->i_d.di_mode;
+- vap->va_uid = ip->i_d.di_uid;
+- vap->va_gid = ip->i_d.di_gid;
+- vap->va_projid = ip->i_d.di_projid;
+-
+- /*
+- * Check vnode type block/char vs. everything else.
+- */
+- switch (ip->i_d.di_mode & S_IFMT) {
+- case S_IFBLK:
+- case S_IFCHR:
+- vap->va_rdev = ip->i_df.if_u2.if_rdev;
+- vap->va_blocksize = BLKDEV_IOSIZE;
+- break;
+- default:
+- vap->va_rdev = 0;
+-
+- if (!(XFS_IS_REALTIME_INODE(ip))) {
+- vap->va_blocksize = xfs_preferred_iosize(mp);
+- } else {
+-
+- /*
+- * If the file blocks are being allocated from a
+- * realtime partition, then return the inode's
+- * realtime extent size or the realtime volume's
+- * extent size.
+- */
+- vap->va_blocksize =
+- xfs_get_extsz_hint(ip) << mp->m_sb.sb_blocklog;
+- }
+- break;
+- }
+-
+- vn_atime_to_timespec(vp, &vap->va_atime);
+- vap->va_mtime.tv_sec = ip->i_d.di_mtime.t_sec;
+- vap->va_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;
+- vap->va_ctime.tv_sec = ip->i_d.di_ctime.t_sec;
+- vap->va_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec;
+-
+- /*
+- * Exit for stat callers. See if any of the rest of the fields
+- * to be filled in are needed.
+- */
+- if ((vap->va_mask &
+- (XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|
+- XFS_AT_GENCOUNT|XFS_AT_VCODE)) == 0)
+- goto all_done;
+-
+- /*
+- * Convert di_flags to xflags.
+- */
+- vap->va_xflags = xfs_ip2xflags(ip);
+-
+- /*
+- * Exit for inode revalidate. See if any of the rest of
+- * the fields to be filled in are needed.
+- */
+- if ((vap->va_mask &
+- (XFS_AT_EXTSIZE|XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|
+- XFS_AT_GENCOUNT|XFS_AT_VCODE)) == 0)
+- goto all_done;
+-
+- vap->va_extsize = ip->i_d.di_extsize << mp->m_sb.sb_blocklog;
+- vap->va_nextents =
+- (ip->i_df.if_flags & XFS_IFEXTENTS) ?
+- ip->i_df.if_bytes / sizeof(xfs_bmbt_rec_t) :
+- ip->i_d.di_nextents;
+- if (ip->i_afp)
+- vap->va_anextents =
+- (ip->i_afp->if_flags & XFS_IFEXTENTS) ?
+- ip->i_afp->if_bytes / sizeof(xfs_bmbt_rec_t) :
+- ip->i_d.di_anextents;
+- else
+- vap->va_anextents = 0;
+- vap->va_gen = ip->i_d.di_gen;
+-
+- all_done:
+- if (!(flags & ATTR_LAZY))
+- xfs_iunlock(ip, XFS_ILOCK_SHARED);
+- return 0;
+-}
+-
+-
+-/*
+ * xfs_setattr
+ */
+ int
+@@ -212,7 +85,6 @@ xfs_setattr(
+ int flags,
+ cred_t *credp)
+ {
+- bhv_vnode_t *vp = XFS_ITOV(ip);
+ xfs_mount_t *mp = ip->i_mount;
+ xfs_trans_t *tp;
+ int mask;
+@@ -223,7 +95,6 @@ xfs_setattr(
+ gid_t gid=0, igid=0;
+ int timeflags = 0;
+ xfs_prid_t projid=0, iprojid=0;
+- int mandlock_before, mandlock_after;
+ struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2;
+ int file_owner;
+ int need_iolock = 1;
+@@ -327,7 +198,7 @@ xfs_setattr(
if (DM_EVENT_ENABLED(ip, DM_EVENT_TRUNCATE) &&
!(flags & ATTR_DMI)) {
int dmflags = AT_DELAY_FLAG(flags) | DM_SEM_FLAG_WR;
@@ -768545,7 +1024484,36 @@
vap->va_size, 0, dmflags, NULL);
if (code) {
lock_flags = 0;
-@@ -634,6 +633,15 @@ xfs_setattr(
+@@ -384,7 +255,7 @@ xfs_setattr(
+ m |= S_ISGID;
+ #if 0
+ /* Linux allows this, Irix doesn't. */
+- if ((vap->va_mode & S_ISVTX) && !VN_ISDIR(vp))
++ if ((vap->va_mode & S_ISVTX) && !S_ISDIR(ip->i_d.di_mode))
+ m |= S_ISVTX;
+ #endif
+ if (m && !capable(CAP_FSETID))
+@@ -462,10 +333,10 @@ xfs_setattr(
+ goto error_return;
+ }
+
+- if (VN_ISDIR(vp)) {
++ if (S_ISDIR(ip->i_d.di_mode)) {
+ code = XFS_ERROR(EISDIR);
+ goto error_return;
+- } else if (!VN_ISREG(vp)) {
++ } else if (!S_ISREG(ip->i_d.di_mode)) {
+ code = XFS_ERROR(EINVAL);
+ goto error_return;
+ }
+@@ -627,13 +498,19 @@ xfs_setattr(
+ xfs_trans_ihold(tp, ip);
+ }
+
+- /* determine whether mandatory locking mode changes */
+- mandlock_before = MANDLOCK(vp, ip->i_d.di_mode);
+-
+ /*
* Truncate file. Must have write permission and not be a directory.
*/
if (mask & XFS_AT_SIZE) {
@@ -768561,7 +1024529,7 @@
if (vap->va_size > ip->i_size) {
xfs_igrow_finish(tp, ip, vap->va_size,
!(flags & ATTR_DMI));
-@@ -662,10 +670,6 @@ xfs_setattr(
+@@ -662,10 +539,6 @@ xfs_setattr(
*/
xfs_iflags_set(ip, XFS_ITRUNCATED);
}
@@ -768572,7 +1024540,21 @@
}
/*
-@@ -877,7 +881,7 @@ xfs_setattr(
+@@ -854,13 +727,6 @@ xfs_setattr(
+ code = xfs_trans_commit(tp, commit_flags);
+ }
+
+- /*
+- * If the (regular) file's mandatory locking mode changed, then
+- * notify the vnode. We do this under the inode lock to prevent
+- * racing calls to vop_vnode_change.
+- */
+- mandlock_after = MANDLOCK(vp, ip->i_d.di_mode);
+-
+ xfs_iunlock(ip, lock_flags);
+
+ /*
+@@ -877,7 +743,7 @@ xfs_setattr(
if (DM_EVENT_ENABLED(ip, DM_EVENT_ATTRIBUTE) &&
!(flags & ATTR_DMI)) {
@@ -768581,7 +1024563,12 @@
NULL, DM_RIGHT_NULL, NULL, NULL,
0, 0, AT_DELAY_FLAG(flags));
}
-@@ -1443,28 +1447,22 @@ xfs_inactive_attrs(
+@@ -1439,32 +1305,26 @@ xfs_inactive_attrs(
+ int error;
+ xfs_mount_t *mp;
+
+- ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE));
++ ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
tp = *tpp;
mp = ip->i_mount;
ASSERT(ip->i_d.di_forkoff != 0);
@@ -768617,7 +1024604,7 @@
xfs_ilock(ip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
-@@ -1475,6 +1473,14 @@ xfs_inactive_attrs(
+@@ -1475,6 +1335,14 @@ xfs_inactive_attrs(
*tpp = tp;
return 0;
@@ -768632,7 +1024619,16 @@
}
int
-@@ -1520,12 +1526,6 @@ xfs_release(
+@@ -1485,7 +1353,7 @@ xfs_release(
+ xfs_mount_t *mp = ip->i_mount;
+ int error;
+
+- if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0))
++ if (!S_ISREG(ip->i_d.di_mode) || (ip->i_d.di_mode == 0))
+ return 0;
+
+ /* If this is a read-only mount, don't do this (would generate I/O) */
+@@ -1520,12 +1388,6 @@ xfs_release(
xfs_flush_pages(ip, 0, -1, XFS_B_ASYNC, FI_NONE);
}
@@ -768645,7 +1024641,7 @@
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(
+@@ -1588,9 +1450,8 @@ xfs_inactive(
mp = ip->i_mount;
@@ -768657,7 +1024653,7 @@
error = 0;
-@@ -1744,11 +1743,18 @@ xfs_inactive(
+@@ -1744,11 +1605,18 @@ xfs_inactive(
XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, XFS_TRANS_DQ_ICOUNT, -1);
/*
@@ -768680,7 +1024676,7 @@
}
/*
* Release the dquots held by inode, if any.
-@@ -1765,8 +1771,8 @@ xfs_inactive(
+@@ -1765,11 +1633,10 @@ xfs_inactive(
int
xfs_lookup(
xfs_inode_t *dp,
@@ -768689,21 +1024685,39 @@
+ struct xfs_name *name,
+ xfs_inode_t **ipp)
{
- xfs_inode_t *ip;
- xfs_ino_t e_inum;
-@@ -1779,9 +1785,9 @@ xfs_lookup(
+- xfs_inode_t *ip;
+- xfs_ino_t e_inum;
++ xfs_ino_t inum;
+ int error;
+ uint lock_mode;
+
+@@ -1779,31 +1646,37 @@ 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) {
+- if (!error) {
- *vpp = XFS_ITOV(ip);
-+ *ipp = ip;
- xfs_itrace_ref(ip);
- }
+- xfs_itrace_ref(ip);
+- }
++ error = xfs_dir_lookup(NULL, dp, name, &inum);
xfs_iunlock_map_shared(dp, lock_mode);
-@@ -1791,19 +1797,16 @@ xfs_lookup(
++
++ if (error)
++ goto out;
++
++ error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp, 0);
++ if (error)
++ goto out;
++
++ xfs_itrace_ref(*ipp);
++ return 0;
++
++ out:
++ *ipp = NULL;
+ return error;
+ }
+
int
xfs_create(
xfs_inode_t *dp,
@@ -768727,7 +1024741,7 @@
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(
+@@ -1813,17 +1686,14 @@ xfs_create(
xfs_prid_t prid;
struct xfs_dquot *udqp, *gdqp;
uint resblks;
@@ -768748,7 +1024762,7 @@
mode, 0, 0);
if (error)
-@@ -1855,7 +1855,7 @@ xfs_create(
+@@ -1855,7 +1725,7 @@ xfs_create(
tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE);
cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
@@ -768757,7 +1024771,7 @@
/*
* 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(
+@@ -1888,7 +1758,8 @@ xfs_create(
if (error)
goto error_return;
@@ -768767,7 +1024781,16 @@
goto error_return;
error = xfs_dir_ialloc(&tp, dp, mode, 1,
rdev, credp, prid, resblks > 0,
-@@ -1914,11 +1915,11 @@ xfs_create(
+@@ -1905,7 +1776,7 @@ xfs_create(
+ * It is locked (and joined to the transaction).
+ */
+
+- ASSERT(ismrlocked (&ip->i_lock, MR_UPDATE));
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+
+ /*
+ * Now we join the directory inode to the transaction. We do not do it
+@@ -1914,11 +1785,11 @@ xfs_create(
* the transaction cancel unlocking dp so don't do it explicitly in the
* error path.
*/
@@ -768781,7 +1024804,7 @@
&first_block, &free_list, resblks ?
resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
if (error) {
-@@ -1952,7 +1953,6 @@ xfs_create(
+@@ -1952,7 +1823,6 @@ xfs_create(
* vnode to the caller, we bump the vnode ref count now.
*/
IHOLD(ip);
@@ -768789,7 +1024812,7 @@
error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error) {
-@@ -1970,17 +1970,17 @@ xfs_create(
+@@ -1970,17 +1840,17 @@ xfs_create(
XFS_QM_DQRELE(mp, udqp);
XFS_QM_DQRELE(mp, gdqp);
@@ -768812,7 +1024835,40 @@
mode, error, 0);
}
return error;
-@@ -2272,46 +2272,32 @@ int remove_which_error_return = 0;
+@@ -2112,7 +1982,7 @@ again:
+
+ ips[0] = ip;
+ ips[1] = dp;
+- xfs_lock_inodes(ips, 2, 0, XFS_ILOCK_EXCL);
++ xfs_lock_inodes(ips, 2, XFS_ILOCK_EXCL);
+ }
+ /* else e_inum == dp->i_ino */
+ /* This can happen if we're asked to lock /x/..
+@@ -2160,7 +2030,6 @@ void
+ xfs_lock_inodes(
+ xfs_inode_t **ips,
+ int inodes,
+- int first_locked,
+ uint lock_mode)
+ {
+ int attempts = 0, i, j, try_lock;
+@@ -2168,13 +2037,8 @@ xfs_lock_inodes(
+
+ ASSERT(ips && (inodes >= 2)); /* we need at least two */
+
+- if (first_locked) {
+- try_lock = 1;
+- i = 1;
+- } else {
+- try_lock = 0;
+- i = 0;
+- }
++ try_lock = 0;
++ i = 0;
+
+ again:
+ for (; i < inodes; i++) {
+@@ -2272,75 +2136,40 @@ int remove_which_error_return = 0;
int
xfs_remove(
xfs_inode_t *dp,
@@ -768861,13 +1024917,18 @@
- /* 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.
- */
+- /*
+- * We need to get a reference to ip before we get our log
+- * reservation. The reason for this is that we cannot call
+- * xfs_iget for an inode for which we do not have a reference
+- * once we've acquired a log reservation. This is because the
+- * inode we are trying to get might be in xfs_inactive going
+- * for a log reservation. Since we'll have to wait for the
+- * inactive code to complete before returning from xfs_iget,
+- * we need to make sure that we don't have log space reserved
+- * 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__);
@@ -768875,35 +1024936,106 @@
- }
-
- dm_di_mode = ip->i_d.di_mode;
-+ IHOLD(ip);
-
+-
xfs_itrace_entry(ip);
xfs_itrace_ref(ip);
-@@ -2398,7 +2378,7 @@ xfs_remove(
+
+ error = XFS_QM_DQATTACH(mp, dp, 0);
+- if (!error && dp != ip)
++ if (!error)
+ error = XFS_QM_DQATTACH(mp, ip, 0);
+ if (error) {
+ REMOVE_DEBUG_TRACE(__LINE__);
+- IRELE(ip);
+ goto std_return;
+ }
+
+@@ -2367,7 +2196,6 @@ xfs_remove(
+ ASSERT(error != ENOSPC);
+ REMOVE_DEBUG_TRACE(__LINE__);
+ xfs_trans_cancel(tp, 0);
+- IRELE(ip);
+ return error;
+ }
+
+@@ -2375,7 +2203,6 @@ xfs_remove(
+ if (error) {
+ REMOVE_DEBUG_TRACE(__LINE__);
+ xfs_trans_cancel(tp, cancel_flags);
+- IRELE(ip);
+ goto std_return;
+ }
+
+@@ -2383,23 +2210,18 @@ xfs_remove(
+ * At this point, we've gotten both the directory and the entry
+ * inodes locked.
+ */
++ IHOLD(ip);
+ xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
+- if (dp != ip) {
+- /*
+- * Increment vnode ref count only in this case since
+- * there's an extra vnode reference in the case where
+- * dp == ip.
+- */
+- IHOLD(dp);
+- xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+- }
++
++ IHOLD(dp);
++ xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+
+ /*
* 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,
+- &first_block, &free_list, 0);
+ error = xfs_dir_removename(tp, dp, name, ip->i_ino,
- &first_block, &free_list, 0);
++ &first_block, &free_list, resblks);
if (error) {
ASSERT(error != ENOENT);
-@@ -2449,14 +2429,6 @@ xfs_remove(
- }
+ REMOVE_DEBUG_TRACE(__LINE__);
+@@ -2422,12 +2244,6 @@ xfs_remove(
+ link_zero = (ip)->i_d.di_nlink==0;
/*
+- * Take an extra ref on the inode so that it doesn't
+- * go to xfs_inactive() from within the commit.
+- */
+- IHOLD(ip);
+-
+- /*
+ * If this is a synchronous mount, make sure that the
+ * remove transaction goes to disk before returning to
+ * the user.
+@@ -2443,18 +2259,8 @@ xfs_remove(
+ }
+
+ error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+- if (error) {
+- IRELE(ip);
++ if (error)
+ goto std_return;
+- }
+-
+- /*
- * 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(
+@@ -2466,15 +2272,14 @@ xfs_remove(
+ xfs_filestream_deassociate(ip);
+
+ xfs_itrace_exit(ip);
+- IRELE(ip);
+
+ /* Fall through to std_return with error = 0 */
std_return:
if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
@@ -768915,7 +1025047,7 @@
}
return error;
-@@ -2495,14 +2467,6 @@ xfs_remove(
+@@ -2495,28 +2300,16 @@ xfs_remove(
cancel_flags |= XFS_TRANS_ABORT;
xfs_trans_cancel(tp, cancel_flags);
@@ -768927,10 +1025059,11 @@
- */
- xfs_refcache_purge_ip(ip);
-
- IRELE(ip);
-
+- IRELE(ip);
+-
goto std_return;
-@@ -2511,12 +2475,10 @@ xfs_remove(
+ }
+
int
xfs_link(
xfs_inode_t *tdp,
@@ -768945,7 +1025078,7 @@
xfs_trans_t *tp;
xfs_inode_t *ips[2];
int error;
-@@ -2525,23 +2487,20 @@ xfs_link(
+@@ -2525,23 +2318,20 @@ xfs_link(
int cancel_flags;
int committed;
int resblks;
@@ -768974,7 +1025107,7 @@
if (error)
return error;
}
-@@ -2556,7 +2515,7 @@ xfs_link(
+@@ -2556,7 +2346,7 @@ xfs_link(
tp = xfs_trans_alloc(mp, XFS_TRANS_LINK);
cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
@@ -768983,7 +1025116,15 @@
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(
+@@ -2577,15 +2367,15 @@ xfs_link(
+ ips[1] = sip;
+ }
+
+- xfs_lock_inodes(ips, 2, 0, XFS_ILOCK_EXCL);
++ xfs_lock_inodes(ips, 2, XFS_ILOCK_EXCL);
+
+ /*
+ * Increment vnode ref counts since xfs_trans_commit &
* xfs_trans_cancel will both unlock the inodes and
* decrement the associated ref counts.
*/
@@ -768994,7 +1025135,7 @@
xfs_trans_ijoin(tp, sip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, tdp, XFS_ILOCK_EXCL);
-@@ -2608,15 +2567,14 @@ xfs_link(
+@@ -2608,15 +2398,14 @@ xfs_link(
goto error_return;
}
@@ -769014,7 +1025155,7 @@
if (error)
goto abort_return;
xfs_ichgtime(tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
-@@ -2650,9 +2608,9 @@ xfs_link(
+@@ -2650,9 +2439,9 @@ xfs_link(
std_return:
if (DM_EVENT_ENABLED(sip, DM_EVENT_POSTLINK)) {
(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTLINK,
@@ -769027,7 +1025168,7 @@
}
return error;
-@@ -2669,17 +2627,13 @@ std_return:
+@@ -2669,17 +2458,13 @@ std_return:
int
xfs_mkdir(
xfs_inode_t *dp,
@@ -769047,7 +1025188,7 @@
xfs_trans_t *tp;
int cancel_flags;
int error;
-@@ -2700,8 +2654,8 @@ xfs_mkdir(
+@@ -2700,8 +2485,8 @@ xfs_mkdir(
if (DM_EVENT_ENABLED(dp, DM_EVENT_CREATE)) {
error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE,
@@ -769058,7 +1025199,7 @@
mode, 0, 0);
if (error)
return error;
-@@ -2730,7 +2684,7 @@ xfs_mkdir(
+@@ -2730,7 +2515,7 @@ xfs_mkdir(
tp = xfs_trans_alloc(mp, XFS_TRANS_MKDIR);
cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
@@ -769067,7 +1025208,7 @@
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(
+@@ -2762,8 +2547,8 @@ xfs_mkdir(
if (error)
goto error_return;
@@ -769078,7 +1025219,7 @@
goto error_return;
/*
* create the directory inode.
-@@ -2786,15 +2740,15 @@ xfs_mkdir(
+@@ -2786,15 +2571,15 @@ xfs_mkdir(
* from here on will result in the transaction cancel
* unlocking dp so don't do it explicitly in the error path.
*/
@@ -769098,7 +1025239,7 @@
if (error) {
ASSERT(error != ENOSPC);
goto error1;
-@@ -2817,11 +2771,9 @@ xfs_mkdir(
+@@ -2817,11 +2602,9 @@ xfs_mkdir(
if (error)
goto error2;
@@ -769111,7 +1025252,7 @@
IHOLD(cdp);
/*
-@@ -2858,10 +2810,10 @@ std_return:
+@@ -2858,10 +2641,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,
@@ -769125,7 +1025266,7 @@
mode, error, 0);
}
return error;
-@@ -2885,20 +2837,17 @@ std_return:
+@@ -2885,20 +2668,16 @@ std_return:
int
xfs_rmdir(
xfs_inode_t *dp,
@@ -769133,7 +1025274,7 @@
+ struct xfs_name *name,
+ xfs_inode_t *cdp)
{
- bhv_vnode_t *dir_vp = XFS_ITOV(dp);
+- bhv_vnode_t *dir_vp = XFS_ITOV(dp);
- char *name = VNAME(dentry);
- int namelen = VNAMELEN(dentry);
xfs_mount_t *mp = dp->i_mount;
@@ -769148,7 +1025289,7 @@
int last_cdp_link;
uint resblks;
-@@ -2907,24 +2856,15 @@ xfs_rmdir(
+@@ -2907,52 +2686,22 @@ xfs_rmdir(
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
@@ -769173,13 +1025314,18 @@
-
- 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.
- */
+- /*
+- * We need to get a reference to cdp before we get our log
+- * reservation. The reason for this is that we cannot call
+- * xfs_iget for an inode for which we do not have a reference
+- * once we've acquired a log reservation. This is because the
+- * inode we are trying to get might be in xfs_inactive going
+- * for a log reservation. Since we'll have to wait for the
+- * inactive code to complete before returning from xfs_iget,
+- * we need to make sure that we don't have log space reserved
+- * 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__);
@@ -769187,11 +1025333,52 @@
- }
- 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(
+ */
+ error = XFS_QM_DQATTACH(mp, dp, 0);
+- if (!error && dp != cdp)
++ if (!error)
+ error = XFS_QM_DQATTACH(mp, cdp, 0);
+ if (error) {
+- IRELE(cdp);
+ REMOVE_DEBUG_TRACE(__LINE__);
+ goto std_return;
+ }
+@@ -2979,7 +2728,6 @@ xfs_rmdir(
+ if (error) {
+ ASSERT(error != ENOSPC);
+ cancel_flags = 0;
+- IRELE(cdp);
+ goto error_return;
+ }
+ XFS_BMAP_INIT(&free_list, &first_block);
+@@ -2993,21 +2741,13 @@ xfs_rmdir(
+ error = xfs_lock_dir_and_entry(dp, cdp);
+ if (error) {
+ xfs_trans_cancel(tp, cancel_flags);
+- IRELE(cdp);
+ goto std_return;
+ }
+
++ IHOLD(dp);
+ xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
+- if (dp != cdp) {
+- /*
+- * Only increment the parent directory vnode count if
+- * we didn't bump it in looking up cdp. The only time
+- * we don't bump it is when we're looking up ".".
+- */
+- VN_HOLD(dir_vp);
+- }
+
+- xfs_itrace_ref(cdp);
++ IHOLD(cdp);
+ xfs_trans_ijoin(tp, cdp, XFS_ILOCK_EXCL);
+
+ ASSERT(cdp->i_d.di_nlink >= 2);
+@@ -3020,7 +2760,7 @@ xfs_rmdir(
goto error_return;
}
@@ -769200,7 +1025387,38 @@
&first_block, &free_list, resblks);
if (error)
goto error1;
-@@ -3098,9 +3032,9 @@ xfs_rmdir(
+@@ -3061,12 +2801,6 @@ xfs_rmdir(
+ last_cdp_link = (cdp)->i_d.di_nlink==0;
+
+ /*
+- * Take an extra ref on the child vnode so that it
+- * does not go to xfs_inactive() from within the commit.
+- */
+- IHOLD(cdp);
+-
+- /*
+ * If this is a synchronous mount, make sure that the
+ * rmdir transaction goes to disk before returning to
+ * the user.
+@@ -3080,27 +2814,23 @@ xfs_rmdir(
+ xfs_bmap_cancel(&free_list);
+ xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
+ XFS_TRANS_ABORT));
+- IRELE(cdp);
+ goto std_return;
+ }
+
+ error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+ if (error) {
+- IRELE(cdp);
+ goto std_return;
+ }
+
+
+- IRELE(cdp);
+-
+ /* Fall through to std_return with error = 0 or the errno
+ * from xfs_trans_commit. */
std_return:
if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
@@ -769212,7 +1025430,7 @@
error, 0);
}
return error;
-@@ -3118,13 +3052,12 @@ xfs_rmdir(
+@@ -3118,13 +2848,12 @@ xfs_rmdir(
int
xfs_symlink(
xfs_inode_t *dp,
@@ -769229,7 +1025447,7 @@
xfs_mount_t *mp = dp->i_mount;
xfs_trans_t *tp;
xfs_inode_t *ip;
-@@ -3140,17 +3073,15 @@ xfs_symlink(
+@@ -3140,17 +2869,15 @@ xfs_symlink(
int nmaps;
xfs_bmbt_irec_t mval[SYMLINK_MAPS];
xfs_daddr_t d;
@@ -769249,7 +1025467,7 @@
error = 0;
ip = NULL;
tp = NULL;
-@@ -3160,44 +3091,17 @@ xfs_symlink(
+@@ -3160,44 +2887,17 @@ xfs_symlink(
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
@@ -769296,7 +1025514,7 @@
if (error)
return error;
}
-@@ -3229,7 +3133,7 @@ xfs_symlink(
+@@ -3229,7 +2929,7 @@ xfs_symlink(
fs_blocks = 0;
else
fs_blocks = XFS_B_TO_FSB(mp, pathlen);
@@ -769305,7 +1025523,7 @@
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(
+@@ -3263,8 +2963,8 @@ xfs_symlink(
/*
* Check for ability to enter directory entry, if no space reserved.
*/
@@ -769316,7 +1025534,7 @@
goto error_return;
/*
* Initialize the bmap freelist prior to calling either
-@@ -3289,7 +3193,7 @@ xfs_symlink(
+@@ -3289,7 +2989,7 @@ xfs_symlink(
* transaction cancel unlocking dp so don't do it explicitly in the
* error path.
*/
@@ -769325,7 +1025543,7 @@
xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
unlock_dp_on_error = B_FALSE;
-@@ -3356,8 +3260,8 @@ xfs_symlink(
+@@ -3356,8 +3056,8 @@ xfs_symlink(
/*
* Create the directory entry for the symlink.
*/
@@ -769336,7 +1025554,7 @@
if (error)
goto error1;
xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
-@@ -3399,19 +3303,14 @@ xfs_symlink(
+@@ -3399,19 +3099,14 @@ xfs_symlink(
std_return:
if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTSYMLINK)) {
(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTSYMLINK,
@@ -769362,7 +1025580,7 @@
return error;
error2:
-@@ -3431,60 +3330,11 @@ std_return:
+@@ -3431,60 +3126,11 @@ std_return:
}
int
@@ -769423,7 +1025641,7 @@
int error = 0;
if (XFS_FORCED_SHUTDOWN(mp))
-@@ -3494,33 +3344,9 @@ xfs_inode_flush(
+@@ -3494,33 +3140,9 @@ xfs_inode_flush(
* Bypass inodes which have already been cleaned by
* the inode flush clustering code inside xfs_iflush
*/
@@ -769458,7 +1025676,7 @@
/*
* 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(
+@@ -3528,30 +3150,22 @@ xfs_inode_flush(
* blocking on inodes inside another operation right
* now, they get caught later by xfs_sync.
*/
@@ -769501,7 +1025719,7 @@
return error;
}
-@@ -3694,12 +3512,12 @@ xfs_finish_reclaim(
+@@ -3694,12 +3308,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.
*/
@@ -769519,7 +1025737,7 @@
if (ip->i_update_core ||
((ip->i_itemp != NULL) &&
(ip->i_itemp->ili_format.ilf_fields != 0))) {
-@@ -3719,17 +3537,11 @@ xfs_finish_reclaim(
+@@ -3719,17 +3333,11 @@ xfs_finish_reclaim(
ASSERT(ip->i_update_core == 0);
ASSERT(ip->i_itemp == NULL ||
ip->i_itemp->ili_format.ilf_fields == 0);
@@ -769540,7 +1025758,7 @@
reclaim:
xfs_ireclaim(ip);
return 0;
-@@ -3845,9 +3657,8 @@ xfs_alloc_file_space(
+@@ -3845,9 +3453,8 @@ xfs_alloc_file_space(
end_dmi_offset = offset+len;
if (end_dmi_offset > ip->i_size)
end_dmi_offset = ip->i_size;
@@ -769552,7 +1025770,7 @@
if (error)
return error;
}
-@@ -3956,8 +3767,8 @@ dmapi_enospc_check:
+@@ -3956,8 +3563,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,
@@ -769563,7 +1025781,7 @@
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(
+@@ -4021,7 +3628,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);
@@ -769573,7 +1025791,7 @@
xfs_ioerror_alert("xfs_zero_remaining_bytes(read)",
mp, bp, XFS_BUF_ADDR(bp));
break;
-@@ -4033,7 +3845,8 @@ xfs_zero_remaining_bytes(
+@@ -4033,7 +3641,8 @@ xfs_zero_remaining_bytes(
XFS_BUF_UNREAD(bp);
XFS_BUF_WRITE(bp);
xfsbdstrat(mp, bp);
@@ -769583,7 +1025801,7 @@
xfs_ioerror_alert("xfs_zero_remaining_bytes(write)",
mp, bp, XFS_BUF_ADDR(bp));
break;
-@@ -4102,7 +3915,7 @@ xfs_free_file_space(
+@@ -4102,7 +3711,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;
@@ -769593,10 +1025811,18 @@
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
+index 4e3970f..8abe8f1 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,
+@@ -15,7 +15,6 @@ struct xfs_iomap;
+
+
+ int xfs_open(struct xfs_inode *ip);
+-int xfs_getattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags);
+ int xfs_setattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags,
+ struct cred *credp);
+ int xfs_readlink(struct xfs_inode *ip, char *link);
+@@ -23,33 +22,34 @@ 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);
@@ -769641,10 +1025867,1873 @@
- 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);
++ struct xfs_name *target_name, struct xfs_inode *target_ip);
int xfs_attr_get(struct xfs_inode *ip, const char *name, char *value,
- int *valuelenp, int flags, cred_t *cred);
+- int *valuelenp, int flags, cred_t *cred);
++ int *valuelenp, int flags);
int xfs_attr_set(struct xfs_inode *dp, const char *name, char *value,
+ int valuelen, int flags);
+ int xfs_attr_remove(struct xfs_inode *dp, const char *name, int flags);
+@@ -60,9 +60,6 @@ int xfs_ioctl(struct xfs_inode *ip, struct file *filp,
+ ssize_t xfs_read(struct xfs_inode *ip, struct kiocb *iocb,
+ const struct iovec *iovp, unsigned int segs,
+ loff_t *offset, int ioflags);
+-ssize_t xfs_sendfile(struct xfs_inode *ip, struct file *filp,
+- loff_t *offset, int ioflags, size_t count,
+- read_actor_t actor, void *target);
+ ssize_t xfs_splice_read(struct xfs_inode *ip, struct file *infilp,
+ loff_t *ppos, struct pipe_inode_info *pipe, size_t count,
+ int flags, int ioflags);
+diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
+index 422f29c..28fe8ba 100644
+--- a/include/acpi/acconfig.h
++++ b/include/acpi/acconfig.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -63,7 +63,7 @@
+
+ /* Current ACPICA subsystem version in YYYYMMDD format */
+
+-#define ACPI_CA_VERSION 0x20070126
++#define ACPI_CA_VERSION 0x20080321
+
+ /*
+ * OS name, used for the _OS object. The _OS object is essentially obsolete,
+@@ -150,6 +150,17 @@
+ #define ACPI_OBJ_NUM_OPERANDS 8
+ #define ACPI_OBJ_MAX_OPERAND 7
+
++/* Number of elements in the Result Stack frame, can be an arbitrary value */
++
++#define ACPI_RESULTS_FRAME_OBJ_NUM 8
++
++/*
++ * Maximal number of elements the Result Stack can contain,
++ * it may be an arbitray value not exceeding the types of
++ * result_size and result_count (now u8).
++ */
++#define ACPI_RESULTS_OBJ_NUM_MAX 255
++
+ /* Names within the namespace are 4 bytes long */
+
+ #define ACPI_NAME_SIZE 4
+diff --git a/include/acpi/acdebug.h b/include/acpi/acdebug.h
+index d626bb1..c5a1b50 100644
+--- a/include/acpi/acdebug.h
++++ b/include/acpi/acdebug.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h
+index 389d772..788f887 100644
+--- a/include/acpi/acdisasm.h
++++ b/include/acpi/acdisasm.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -97,19 +97,23 @@ typedef const struct acpi_dmtable_info {
+ #define ACPI_DMT_CHKSUM 20
+ #define ACPI_DMT_SPACEID 21
+ #define ACPI_DMT_GAS 22
+-#define ACPI_DMT_DMAR 23
+-#define ACPI_DMT_MADT 24
+-#define ACPI_DMT_SRAT 25
+-#define ACPI_DMT_EXIT 26
+-#define ACPI_DMT_SIG 27
++#define ACPI_DMT_ASF 23
++#define ACPI_DMT_DMAR 24
++#define ACPI_DMT_HEST 25
++#define ACPI_DMT_HESTNTFY 26
++#define ACPI_DMT_HESTNTYP 27
++#define ACPI_DMT_MADT 28
++#define ACPI_DMT_SRAT 29
++#define ACPI_DMT_EXIT 30
++#define ACPI_DMT_SIG 31
+
+ typedef
+-void (*ACPI_TABLE_HANDLER) (struct acpi_table_header * table);
++void (*acpi_dmtable_handler) (struct acpi_table_header * table);
+
+ struct acpi_dmtable_data {
+ char *signature;
+ struct acpi_dmtable_info *table_info;
+- ACPI_TABLE_HANDLER table_handler;
++ acpi_dmtable_handler table_handler;
+ char *name;
+ };
+
+@@ -149,6 +153,7 @@ extern struct acpi_dmtable_info acpi_dm_table_info_asf3[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_asf4[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_asf_hdr[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_boot[];
++extern struct acpi_dmtable_info acpi_dm_table_info_bert[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_cpep[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_cpep0[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_dbgp[];
+@@ -158,11 +163,17 @@ extern struct acpi_dmtable_info acpi_dm_table_info_dmar_scope[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_dmar0[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_dmar1[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_ecdt[];
++extern struct acpi_dmtable_info acpi_dm_table_info_einj[];
++extern struct acpi_dmtable_info acpi_dm_table_info_einj0[];
++extern struct acpi_dmtable_info acpi_dm_table_info_erst[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_facs[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_fadt1[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_fadt2[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_gas[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_header[];
++extern struct acpi_dmtable_info acpi_dm_table_info_hest[];
++extern struct acpi_dmtable_info acpi_dm_table_info_hest9[];
++extern struct acpi_dmtable_info acpi_dm_table_info_hest_notify[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_hpet[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_madt[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_madt0[];
+@@ -180,6 +191,7 @@ extern struct acpi_dmtable_info acpi_dm_table_info_mcfg0[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_rsdp1[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_rsdp2[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_sbst[];
++extern struct acpi_dmtable_info acpi_dm_table_info_slic[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_slit[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_spcr[];
+ extern struct acpi_dmtable_info acpi_dm_table_info_spmi[];
+@@ -194,7 +206,7 @@ extern struct acpi_dmtable_info acpi_dm_table_info_wdrt[];
+ */
+ void acpi_dm_dump_data_table(struct acpi_table_header *table);
+
+-void
++acpi_status
+ acpi_dm_dump_table(u32 table_length,
+ u32 table_offset,
+ void *table,
+@@ -213,9 +225,13 @@ void acpi_dm_dump_cpep(struct acpi_table_header *table);
+
+ void acpi_dm_dump_dmar(struct acpi_table_header *table);
+
++void acpi_dm_dump_einj(struct acpi_table_header *table);
++
++void acpi_dm_dump_erst(struct acpi_table_header *table);
++
+ void acpi_dm_dump_fadt(struct acpi_table_header *table);
+
+-void acpi_dm_dump_srat(struct acpi_table_header *table);
++void acpi_dm_dump_hest(struct acpi_table_header *table);
+
+ void acpi_dm_dump_mcfg(struct acpi_table_header *table);
+
+@@ -227,6 +243,8 @@ void acpi_dm_dump_rsdt(struct acpi_table_header *table);
+
+ void acpi_dm_dump_slit(struct acpi_table_header *table);
+
++void acpi_dm_dump_srat(struct acpi_table_header *table);
++
+ void acpi_dm_dump_xsdt(struct acpi_table_header *table);
+
+ /*
+diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h
+index 7f690bb..910f018 100644
+--- a/include/acpi/acdispat.h
++++ b/include/acpi/acdispat.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -53,6 +53,9 @@
+ acpi_status
+ acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc);
+
++acpi_status
++acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc);
++
+ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *rgn_desc);
+
+ acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc);
+@@ -68,10 +71,18 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op);
+
+ acpi_status
++acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
++ union acpi_parse_object *op);
++
++acpi_status
+ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ union acpi_operand_object *obj_desc);
+
++acpi_status
++acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,
++ union acpi_parse_object *op);
++
+ acpi_status acpi_ds_initialize_region(acpi_handle obj_handle);
+
+ /*
+@@ -269,6 +280,8 @@ acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state);
+
+ void acpi_ds_clear_operands(struct acpi_walk_state *walk_state);
+
++acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state);
++
+ /*
+ * dswscope - Scope Stack manipulation
+ */
+@@ -303,7 +316,7 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
+ u32 aml_length,
+ struct acpi_evaluate_info *info, u8 pass_number);
+
+-acpi_status
++void
+ acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
+ struct acpi_walk_state *walk_state);
+
+@@ -316,21 +329,11 @@ void
+ acpi_ds_push_walk_state(struct acpi_walk_state *walk_state,
+ struct acpi_thread_state *thread);
+
+-acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state);
+-
+-acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *walk_state);
+-
+ acpi_status acpi_ds_result_stack_clear(struct acpi_walk_state *walk_state);
+
+ struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state
+ *thread);
+
+-#ifdef ACPI_FUTURE_USAGE
+-acpi_status
+-acpi_ds_result_remove(union acpi_operand_object **object,
+- u32 index, struct acpi_walk_state *walk_state);
+-#endif
+-
+ acpi_status
+ acpi_ds_result_pop(union acpi_operand_object **object,
+ struct acpi_walk_state *walk_state);
+@@ -339,8 +342,4 @@ acpi_status
+ acpi_ds_result_push(union acpi_operand_object *object,
+ struct acpi_walk_state *walk_state);
+
+-acpi_status
+-acpi_ds_result_pop_from_bottom(union acpi_operand_object **object,
+- struct acpi_walk_state *walk_state);
+-
+ #endif /* _ACDISPAT_H_ */
+diff --git a/include/acpi/acevents.h b/include/acpi/acevents.h
+index d23cdf3..d5d099b 100644
+--- a/include/acpi/acevents.h
++++ b/include/acpi/acevents.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h
+index b73f18a..1f59117 100644
+--- a/include/acpi/acexcep.h
++++ b/include/acpi/acexcep.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h
+index 47a1fd8..74ad971 100644
+--- a/include/acpi/acglobal.h
++++ b/include/acpi/acglobal.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -170,10 +170,14 @@ ACPI_EXTERN u8 acpi_gbl_integer_nybble_width;
+ ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[ACPI_NUM_MUTEX];
+
+ /*
+- * Global lock semaphore works in conjunction with the actual HW global lock
++ * Global lock mutex is an actual AML mutex object
++ * Global lock semaphore works in conjunction with the HW global lock
+ */
+-ACPI_EXTERN acpi_mutex acpi_gbl_global_lock_mutex;
++ACPI_EXTERN union acpi_operand_object *acpi_gbl_global_lock_mutex;
+ ACPI_EXTERN acpi_semaphore acpi_gbl_global_lock_semaphore;
++ACPI_EXTERN u16 acpi_gbl_global_lock_handle;
++ACPI_EXTERN u8 acpi_gbl_global_lock_acquired;
++ACPI_EXTERN u8 acpi_gbl_global_lock_present;
+
+ /*
+ * Spinlocks are used for interfaces that can be possibly called at
+@@ -213,27 +217,33 @@ ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_device_notify;
+ ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_system_notify;
+ ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler;
+ ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler;
++ACPI_EXTERN acpi_tbl_handler acpi_gbl_table_handler;
++ACPI_EXTERN void *acpi_gbl_table_handler_context;
+ ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk;
+
++/* Owner ID support */
++
++ACPI_EXTERN u32 acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS];
++ACPI_EXTERN u8 acpi_gbl_last_owner_id_index;
++ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset;
++
+ /* Misc */
+
+ ACPI_EXTERN u32 acpi_gbl_original_mode;
+ ACPI_EXTERN u32 acpi_gbl_rsdp_original_location;
+ ACPI_EXTERN u32 acpi_gbl_ns_lookup_count;
+ ACPI_EXTERN u32 acpi_gbl_ps_find_count;
+-ACPI_EXTERN u32 acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS];
+ ACPI_EXTERN u16 acpi_gbl_pm1_enable_register_save;
+-ACPI_EXTERN u16 acpi_gbl_global_lock_handle;
+-ACPI_EXTERN u8 acpi_gbl_last_owner_id_index;
+-ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset;
+ ACPI_EXTERN u8 acpi_gbl_debugger_configuration;
+-ACPI_EXTERN u8 acpi_gbl_global_lock_acquired;
+ ACPI_EXTERN u8 acpi_gbl_step_to_next_call;
+ ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present;
+-ACPI_EXTERN u8 acpi_gbl_global_lock_present;
+ ACPI_EXTERN u8 acpi_gbl_events_initialized;
+ ACPI_EXTERN u8 acpi_gbl_system_awake_and_running;
+
++#ifndef DEFINE_ACPI_GLOBALS
++
++/* Other miscellaneous */
++
+ extern u8 acpi_gbl_shutdown;
+ extern u32 acpi_gbl_startup_flags;
+ extern const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT];
+@@ -241,6 +251,8 @@ extern const char *acpi_gbl_highest_dstate_names[4];
+ extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES];
+ extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS];
+
++#endif
++
+ /* Exception codes */
+
+ extern char const *acpi_gbl_exception_names_env[];
+@@ -255,8 +267,6 @@ extern char const *acpi_gbl_exception_names_ctrl[];
+ *
+ ****************************************************************************/
+
+-#define NUM_NS_TYPES ACPI_TYPE_INVALID+1
+-
+ #if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
+ #define NUM_PREDEFINED_NAMES 10
+ #else
+@@ -267,7 +277,7 @@ ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct;
+ ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node;
+ ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device;
+
+-extern const u8 acpi_gbl_ns_properties[NUM_NS_TYPES];
++extern const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES];
+ extern const struct acpi_predefined_names
+ acpi_gbl_pre_defined_names[NUM_PREDEFINED_NAMES];
+
+@@ -275,8 +285,8 @@ extern const struct acpi_predefined_names
+ ACPI_EXTERN u32 acpi_gbl_current_node_count;
+ ACPI_EXTERN u32 acpi_gbl_current_node_size;
+ ACPI_EXTERN u32 acpi_gbl_max_concurrent_node_count;
+-ACPI_EXTERN acpi_size acpi_gbl_entry_stack_pointer;
+-ACPI_EXTERN acpi_size acpi_gbl_lowest_stack_pointer;
++ACPI_EXTERN acpi_size *acpi_gbl_entry_stack_pointer;
++ACPI_EXTERN acpi_size *acpi_gbl_lowest_stack_pointer;
+ ACPI_EXTERN u32 acpi_gbl_deepest_nesting;
+ #endif
+
+diff --git a/include/acpi/achware.h b/include/acpi/achware.h
+index 4053df9..d4fb9bb 100644
+--- a/include/acpi/achware.h
++++ b/include/acpi/achware.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h
+index ce7c9d6..e249ce5 100644
+--- a/include/acpi/acinterp.h
++++ b/include/acpi/acinterp.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -215,8 +215,6 @@ acpi_ex_create_region(u8 * aml_start,
+ u32 aml_length,
+ u8 region_space, struct acpi_walk_state *walk_state);
+
+-acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state);
+-
+ acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state);
+
+ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state);
+@@ -248,9 +246,16 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
+ struct acpi_walk_state *walk_state);
+
+ acpi_status
++acpi_ex_acquire_mutex_object(u16 timeout,
++ union acpi_operand_object *obj_desc,
++ acpi_thread_id thread_id);
++
++acpi_status
+ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
+ struct acpi_walk_state *walk_state);
+
++acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc);
++
+ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread);
+
+ void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc);
+@@ -455,9 +460,9 @@ void acpi_ex_relinquish_interpreter(void);
+
+ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc);
+
+-u8 acpi_ex_acquire_global_lock(u32 rule);
++void acpi_ex_acquire_global_lock(u32 rule);
+
+-void acpi_ex_release_global_lock(u8 locked);
++void acpi_ex_release_global_lock(u32 rule);
+
+ void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string);
+
+diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h
+index 202cd42..c5cdc32 100644
+--- a/include/acpi/aclocal.h
++++ b/include/acpi/aclocal.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -522,9 +522,8 @@ struct acpi_thread_state {
+ * AML arguments
+ */
+ struct acpi_result_values {
+- ACPI_STATE_COMMON u8 num_results;
+- u8 last_insert;
+- union acpi_operand_object *obj_desc[ACPI_OBJ_NUM_OPERANDS];
++ ACPI_STATE_COMMON
++ union acpi_operand_object *obj_desc[ACPI_RESULTS_FRAME_OBJ_NUM];
+ };
+
+ typedef
+@@ -604,6 +603,7 @@ union acpi_parse_value {
+ union acpi_parse_object *next; /* Next op */\
+ struct acpi_namespace_node *node; /* For use by interpreter */\
+ union acpi_parse_value value; /* Value or args associated with the opcode */\
++ u8 arg_list_length; /* Number of elements in the arg list */\
+ ACPI_DISASM_ONLY_MEMBERS (\
+ u8 disasm_flags; /* Used during AML disassembly */\
+ u8 disasm_opcode; /* Subtype used for disassembly */\
+@@ -696,6 +696,8 @@ struct acpi_parse_state {
+ #define ACPI_PARSEOP_NAMED 0x02
+ #define ACPI_PARSEOP_DEFERRED 0x04
+ #define ACPI_PARSEOP_BYTELIST 0x08
++#define ACPI_PARSEOP_IN_STACK 0x10
++#define ACPI_PARSEOP_TARGET 0x20
+ #define ACPI_PARSEOP_IN_CACHE 0x80
+
+ /* Parse object disasm_flags */
+diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h
+index 99d171c..fb41a3b 100644
+--- a/include/acpi/acmacros.h
++++ b/include/acpi/acmacros.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -61,30 +61,6 @@
+
+ #define ACPI_ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
+
+-#ifdef ACPI_NO_INTEGER64_SUPPORT
+-/*
+- * acpi_integer is 32-bits, no 64-bit support on this platform
+- */
+-#define ACPI_LODWORD(l) ((u32)(l))
+-#define ACPI_HIDWORD(l) ((u32)(0))
+-
+-#else
+-
+-/*
+- * Full 64-bit address/integer on both 32-bit and 64-bit platforms
+- */
+-#define ACPI_LODWORD(l) ((u32)(u64)(l))
+-#define ACPI_HIDWORD(l) ((u32)(((*(struct uint64_struct *)(void *)(&l))).hi))
+-#endif
+-
+-/*
+- * printf() format helpers
+- */
+-
+-/* Split 64-bit integer into two 32-bit values. Use with %8.8_x%8.8_x */
+-
+-#define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i),ACPI_LODWORD(i)
+-
+ /*
+ * Extract data using a pointer. Any more than a byte and we
+ * get into potential aligment issues -- see the STORE macros below.
+@@ -122,6 +98,31 @@
+ #endif
+
+ /*
++ * Full 64-bit integer must be available on both 32-bit and 64-bit platforms
++ */
++struct acpi_integer_overlay {
++ u32 lo_dword;
++ u32 hi_dword;
++};
++
++#define ACPI_LODWORD(integer) (ACPI_CAST_PTR (struct acpi_integer_overlay, &integer)->lo_dword)
++#define ACPI_HIDWORD(integer) (ACPI_CAST_PTR (struct acpi_integer_overlay, &integer)->hi_dword)
++
++/*
++ * printf() format helpers
++ */
++
++/* Split 64-bit integer into two 32-bit values. Use with %8.8_x%8.8_x */
++
++#define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i),ACPI_LODWORD(i)
++
++#if ACPI_MACHINE_WIDTH == 64
++#define ACPI_FORMAT_NATIVE_UINT(i) ACPI_FORMAT_UINT64(i)
++#else
++#define ACPI_FORMAT_NATIVE_UINT(i) 0, (i)
++#endif
++
++/*
+ * Macros for moving data around to/from buffers that are possibly unaligned.
+ * If the hardware supports the transfer of unaligned data, just do the store.
+ * Otherwise, we have to move one byte at a time.
+@@ -137,29 +138,29 @@
+
+ /* These macros reverse the bytes during the move, converting little-endian to big endian */
+
+- /* Big Endian <== Little Endian */
+- /* Hi...Lo Lo...Hi */
++ /* Big Endian <== Little Endian */
++ /* Hi...Lo Lo...Hi */
+ /* 16-bit source, 16/32/64 destination */
+
+ #define ACPI_MOVE_16_TO_16(d,s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[1];\
+- (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];}
++ (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];}
+
+ #define ACPI_MOVE_16_TO_32(d,s) {(*(u32 *)(void *)(d))=0;\
+- ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
+- ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
++ ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
++ ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
+
+ #define ACPI_MOVE_16_TO_64(d,s) {(*(u64 *)(void *)(d))=0;\
+- ((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\
+- ((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];}
++ ((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\
++ ((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];}
+
+ /* 32-bit source, 16/32/64 destination */
+
+ #define ACPI_MOVE_32_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
+
+ #define ACPI_MOVE_32_TO_32(d,s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[3];\
+- (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\
+- (( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
+- (( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
++ (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\
++ (( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
++ (( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
+
+ #define ACPI_MOVE_32_TO_64(d,s) {(*(u64 *)(void *)(d))=0;\
+ ((u8 *)(void *)(d))[4] = ((u8 *)(void *)(s))[3];\
+diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h
+index 34bfae8..c1343a9 100644
+--- a/include/acpi/acnames.h
++++ b/include/acpi/acnames.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/include/acpi/acnamesp.h b/include/acpi/acnamesp.h
+index 5ef38a6..713b309 100644
+--- a/include/acpi/acnamesp.h
++++ b/include/acpi/acnamesp.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -113,7 +113,8 @@ acpi_ns_parse_table(acpi_native_uint table_index,
+
+ acpi_status
+ acpi_ns_one_complete_parse(acpi_native_uint pass_number,
+- acpi_native_uint table_index);
++ acpi_native_uint table_index,
++ struct acpi_namespace_node *start_node);
+
+ /*
+ * nsaccess - Top-level namespace access
+diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h
+index 7e1211a..e9657da 100644
+--- a/include/acpi/acobject.h
++++ b/include/acpi/acobject.h
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -155,8 +155,9 @@ struct acpi_object_event {
+ struct acpi_object_mutex {
+ ACPI_OBJECT_COMMON_HEADER u8 sync_level; /* 0-15, specified in Mutex() call */
+ u16 acquisition_depth; /* Allow multiple Acquires, same thread */
+- struct acpi_thread_state *owner_thread; /* Current owner of the mutex */
+ acpi_mutex os_mutex; /* Actual OS synchronization object */
++ acpi_thread_id thread_id; /* Current owner of the mutex */
++ struct acpi_thread_state *owner_thread; /* Current owner of the mutex */
+ union acpi_operand_object *prev; /* Link for list of acquired mutexes */
+ union acpi_operand_object *next; /* Link for list of acquired mutexes */
+ struct acpi_namespace_node *node; /* Containing namespace node */
+diff --git a/include/acpi/acopcode.h b/include/acpi/acopcode.h
+index e6f76a2..dfdf633 100644
+--- a/include/acpi/acopcode.h
++++ b/include/acpi/acopcode.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -233,7 +233,7 @@
+ #define ARGI_CREATE_WORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
+ #define ARGI_DATA_REGION_OP ARGI_LIST3 (ARGI_STRING, ARGI_STRING, ARGI_STRING)
+ #define ARGI_DEBUG_OP ARG_NONE
+-#define ARGI_DECREMENT_OP ARGI_LIST1 (ARGI_INTEGER_REF)
++#define ARGI_DECREMENT_OP ARGI_LIST1 (ARGI_TARGETREF)
+ #define ARGI_DEREF_OF_OP ARGI_LIST1 (ARGI_REF_OR_STRING)
+ #define ARGI_DEVICE_OP ARGI_INVALID_OPCODE
+ #define ARGI_DIVIDE_OP ARGI_LIST4 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF, ARGI_TARGETREF)
+@@ -246,7 +246,7 @@
+ #define ARGI_FIND_SET_RIGHT_BIT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF)
+ #define ARGI_FROM_BCD_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_FIXED_TARGET)
+ #define ARGI_IF_OP ARGI_INVALID_OPCODE
+-#define ARGI_INCREMENT_OP ARGI_LIST1 (ARGI_INTEGER_REF)
++#define ARGI_INCREMENT_OP ARGI_LIST1 (ARGI_TARGETREF)
+ #define ARGI_INDEX_FIELD_OP ARGI_INVALID_OPCODE
+ #define ARGI_INDEX_OP ARGI_LIST3 (ARGI_COMPLEXOBJ, ARGI_INTEGER, ARGI_TARGETREF)
+ #define ARGI_LAND_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER)
+diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h
+index c090a8b..e17873d 100644
+--- a/include/acpi/acoutput.h
++++ b/include/acpi/acoutput.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/include/acpi/acparser.h b/include/acpi/acparser.h
+index 85c358e..23ee0fb 100644
+--- a/include/acpi/acparser.h
++++ b/include/acpi/acparser.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -109,6 +109,8 @@ const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode);
+
+ char *acpi_ps_get_opcode_name(u16 opcode);
+
++u8 acpi_ps_get_argument_count(u32 op_type);
++
+ /*
+ * psparse - top level parsing routines
+ */
+diff --git a/include/acpi/acpi.h b/include/acpi/acpi.h
+index 2e5f00d..c515ef6 100644
+--- a/include/acpi/acpi.h
++++ b/include/acpi/acpi.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
+index 4839f2a..d4a560d 100644
+--- a/include/acpi/acpiosxf.h
++++ b/include/acpi/acpiosxf.h
+@@ -8,7 +8,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
+index d970f7f..2c3806e 100644
+--- a/include/acpi/acpixf.h
++++ b/include/acpi/acpixf.h
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -119,6 +119,11 @@ acpi_status
+ acpi_get_table_by_index(acpi_native_uint table_index,
+ struct acpi_table_header **out_table);
+
++acpi_status
++acpi_install_table_handler(acpi_tbl_handler handler, void *context);
++
++acpi_status acpi_remove_table_handler(acpi_tbl_handler handler);
++
+ /*
+ * Namespace and name interfaces
+ */
+diff --git a/include/acpi/acresrc.h b/include/acpi/acresrc.h
+index 9486ab2..eef5bd7 100644
+--- a/include/acpi/acresrc.h
++++ b/include/acpi/acresrc.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -94,6 +94,7 @@ typedef const struct acpi_rsconvert_info {
+ #define ACPI_RSC_BITMASK16 18
+ #define ACPI_RSC_EXIT_NE 19
+ #define ACPI_RSC_EXIT_LE 20
++#define ACPI_RSC_EXIT_EQ 21
+
+ /* Resource Conversion sub-opcodes */
+
+diff --git a/include/acpi/acstruct.h b/include/acpi/acstruct.h
+index 8848265..a907c67 100644
+--- a/include/acpi/acstruct.h
++++ b/include/acpi/acstruct.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -80,12 +80,15 @@ struct acpi_walk_state {
+ u16 opcode; /* Current AML opcode */
+ u8 next_op_info; /* Info about next_op */
+ u8 num_operands; /* Stack pointer for Operands[] array */
++ u8 operand_index; /* Index into operand stack, to be used by acpi_ds_obj_stack_push */
+ acpi_owner_id owner_id; /* Owner of objects created during the walk */
+ u8 last_predicate; /* Result of last predicate */
+ u8 current_result;
+ u8 return_used;
+ u8 scope_depth;
+ u8 pass_number; /* Parse pass during table load */
++ u8 result_size; /* Total elements for the result stack */
++ u8 result_count; /* Current number of occupied elements of result stack */
+ u32 aml_offset;
+ u32 arg_types;
+ u32 method_breakpoint; /* For single stepping */
+diff --git a/include/acpi/actables.h b/include/acpi/actables.h
+index 2b9f46f..4b36a55 100644
+--- a/include/acpi/actables.h
++++ b/include/acpi/actables.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h
+index 955adfb..1ebbe88 100644
+--- a/include/acpi/actbl.h
++++ b/include/acpi/actbl.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h
+index a1b1b2e..9af239b 100644
+--- a/include/acpi/actbl1.h
++++ b/include/acpi/actbl1.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -58,20 +58,28 @@
+ * it more difficult to inadvertently type in the wrong signature.
+ */
+ #define ACPI_SIG_ASF "ASF!" /* Alert Standard Format table */
++#define ACPI_SIG_BERT "BERT" /* Boot Error Record Table */
+ #define ACPI_SIG_BOOT "BOOT" /* Simple Boot Flag Table */
+ #define ACPI_SIG_CPEP "CPEP" /* Corrected Platform Error Polling table */
+ #define ACPI_SIG_DBGP "DBGP" /* Debug Port table */
+ #define ACPI_SIG_DMAR "DMAR" /* DMA Remapping table */
+ #define ACPI_SIG_ECDT "ECDT" /* Embedded Controller Boot Resources Table */
++#define ACPI_SIG_EINJ "EINJ" /* Error Injection table */
++#define ACPI_SIG_ERST "ERST" /* Error Record Serialization Table */
++#define ACPI_SIG_HEST "HEST" /* Hardware Error Source Table */
+ #define ACPI_SIG_HPET "HPET" /* High Precision Event Timer table */
++#define ACPI_SIG_IBFT "IBFT" /* i_sCSI Boot Firmware Table */
+ #define ACPI_SIG_MADT "APIC" /* Multiple APIC Description Table */
+ #define ACPI_SIG_MCFG "MCFG" /* PCI Memory Mapped Configuration table */
+ #define ACPI_SIG_SBST "SBST" /* Smart Battery Specification Table */
++#define ACPI_SIG_SLIC "SLIC" /* Software Licensing Description Table */
+ #define ACPI_SIG_SLIT "SLIT" /* System Locality Distance Information Table */
+ #define ACPI_SIG_SPCR "SPCR" /* Serial Port Console Redirection table */
+ #define ACPI_SIG_SPMI "SPMI" /* Server Platform Management Interface table */
+ #define ACPI_SIG_SRAT "SRAT" /* System Resource Affinity Table */
+ #define ACPI_SIG_TCPA "TCPA" /* Trusted Computing Platform Alliance table */
++#define ACPI_SIG_UEFI "UEFI" /* Uefi Boot Optimization Table */
++#define ACPI_SIG_WDAT "WDAT" /* Watchdog Action Table */
+ #define ACPI_SIG_WDRT "WDRT" /* Watchdog Resource Table */
+
+ /*
+@@ -86,13 +94,25 @@
+ * portable, so do not use any other bitfield types.
+ */
+
+-/* Common Sub-table header (used in MADT, SRAT, etc.) */
++/* Common Subtable header (used in MADT, SRAT, etc.) */
+
+ struct acpi_subtable_header {
+ u8 type;
+ u8 length;
+ };
+
++/* Common Subtable header for WHEA tables (EINJ, ERST, WDAT) */
++
++struct acpi_whea_header {
++ u8 action;
++ u8 instruction;
++ u8 flags;
++ u8 reserved;
++ struct acpi_generic_address register_region;
++ u64 value; /* Value used with Read/Write register */
++ u64 mask; /* Bitmask required for this register instruction */
++};
++
+ /*******************************************************************************
+ *
+ * ASF - Alert Standard Format table (Signature "ASF!")
+@@ -204,6 +224,35 @@ struct acpi_asf_address {
+
+ /*******************************************************************************
+ *
++ * BERT - Boot Error Record Table
++ *
++ ******************************************************************************/
++
++struct acpi_table_bert {
++ struct acpi_table_header header; /* Common ACPI table header */
++ u32 region_length; /* Length of the boot error region */
++ u64 address; /* Physical addresss of the error region */
++};
++
++/* Boot Error Region */
++
++struct acpi_bert_region {
++ u32 block_status;
++ u32 raw_data_offset;
++ u32 raw_data_length;
++ u32 data_length;
++ u32 error_severity;
++};
++
++/* block_status Flags */
++
++#define ACPI_BERT_UNCORRECTABLE (1)
++#define ACPI_BERT_CORRECTABLE (2)
++#define ACPI_BERT_MULTIPLE_UNCORRECTABLE (4)
++#define ACPI_BERT_MULTIPLE_CORRECTABLE (8)
++
++/*******************************************************************************
++ *
+ * BOOT - Simple Boot Flag Table
+ *
+ ******************************************************************************/
+@@ -350,6 +399,352 @@ struct acpi_table_ecdt {
+
+ /*******************************************************************************
+ *
++ * EINJ - Error Injection Table
++ *
++ ******************************************************************************/
++
++struct acpi_table_einj {
++ struct acpi_table_header header; /* Common ACPI table header */
++ u32 header_length;
++ u32 reserved;
++ u32 entries;
++};
++
++/* EINJ Injection Instruction Entries (actions) */
++
++struct acpi_einj_entry {
++ struct acpi_whea_header whea_header; /* Common header for WHEA tables */
++};
++
++/* Values for Action field above */
++
++enum acpi_einj_actions {
++ ACPI_EINJ_BEGIN_OPERATION = 0,
++ ACPI_EINJ_GET_TRIGGER_TABLE = 1,
++ ACPI_EINJ_SET_ERROR_TYPE = 2,
++ ACPI_EINJ_GET_ERROR_TYPE = 3,
++ ACPI_EINJ_END_OPERATION = 4,
++ ACPI_EINJ_EXECUTE_OPERATION = 5,
++ ACPI_EINJ_CHECK_BUSY_STATUS = 6,
++ ACPI_EINJ_GET_COMMAND_STATUS = 7,
++ ACPI_EINJ_ACTION_RESERVED = 8, /* 8 and greater are reserved */
++ ACPI_EINJ_TRIGGER_ERROR = 0xFF /* Except for this value */
++};
++
++/* Values for Instruction field above */
++
++enum acpi_einj_instructions {
++ ACPI_EINJ_READ_REGISTER = 0,
++ ACPI_EINJ_READ_REGISTER_VALUE = 1,
++ ACPI_EINJ_WRITE_REGISTER = 2,
++ ACPI_EINJ_WRITE_REGISTER_VALUE = 3,
++ ACPI_EINJ_NOOP = 4,
++ ACPI_EINJ_INSTRUCTION_RESERVED = 5 /* 5 and greater are reserved */
++};
++
++/* EINJ Trigger Error Action Table */
++
++struct acpi_einj_trigger {
++ u32 header_size;
++ u32 revision;
++ u32 table_size;
++ u32 entry_count;
++};
++
++/*******************************************************************************
++ *
++ * ERST - Error Record Serialization Table
++ *
++ ******************************************************************************/
++
++struct acpi_table_erst {
++ struct acpi_table_header header; /* Common ACPI table header */
++ u32 header_length;
++ u32 reserved;
++ u32 entries;
++};
++
++/* ERST Serialization Entries (actions) */
++
++struct acpi_erst_entry {
++ struct acpi_whea_header whea_header; /* Common header for WHEA tables */
++};
++
++/* Values for Action field above */
++
++enum acpi_erst_actions {
++ ACPI_ERST_BEGIN_WRITE_OPERATION = 0,
++ ACPI_ERST_BEGIN_READ_OPERATION = 1,
++ ACPI_ERST_BETGIN_CLEAR_OPERATION = 2,
++ ACPI_ERST_END_OPERATION = 3,
++ ACPI_ERST_SET_RECORD_OFFSET = 4,
++ ACPI_ERST_EXECUTE_OPERATION = 5,
++ ACPI_ERST_CHECK_BUSY_STATUS = 6,
++ ACPI_ERST_GET_COMMAND_STATUS = 7,
++ ACPI_ERST_GET_RECORD_IDENTIFIER = 8,
++ ACPI_ERST_SET_RECORD_IDENTIFIER = 9,
++ ACPI_ERST_GET_RECORD_COUNT = 10,
++ ACPI_ERST_BEGIN_DUMMY_WRIITE = 11,
++ ACPI_ERST_NOT_USED = 12,
++ ACPI_ERST_GET_ERROR_RANGE = 13,
++ ACPI_ERST_GET_ERROR_LENGTH = 14,
++ ACPI_ERST_GET_ERROR_ATTRIBUTES = 15,
++ ACPI_ERST_ACTION_RESERVED = 16 /* 16 and greater are reserved */
++};
++
++/* Values for Instruction field above */
++
++enum acpi_erst_instructions {
++ ACPI_ERST_READ_REGISTER = 0,
++ ACPI_ERST_READ_REGISTER_VALUE = 1,
++ ACPI_ERST_WRITE_REGISTER = 2,
++ ACPI_ERST_WRITE_REGISTER_VALUE = 3,
++ ACPI_ERST_NOOP = 4,
++ ACPI_ERST_LOAD_VAR1 = 5,
++ ACPI_ERST_LOAD_VAR2 = 6,
++ ACPI_ERST_STORE_VAR1 = 7,
++ ACPI_ERST_ADD = 8,
++ ACPI_ERST_SUBTRACT = 9,
++ ACPI_ERST_ADD_VALUE = 10,
++ ACPI_ERST_SUBTRACT_VALUE = 11,
++ ACPI_ERST_STALL = 12,
++ ACPI_ERST_STALL_WHILE_TRUE = 13,
++ ACPI_ERST_SKIP_NEXT_IF_TRUE = 14,
++ ACPI_ERST_GOTO = 15,
++ ACPI_ERST_SET_SRC_ADDRESS_BASE = 16,
++ ACPI_ERST_SET_DST_ADDRESS_BASE = 17,
++ ACPI_ERST_MOVE_DATA = 18,
++ ACPI_ERST_INSTRUCTION_RESERVED = 19 /* 19 and greater are reserved */
++};
++
++/*******************************************************************************
++ *
++ * HEST - Hardware Error Source Table
++ *
++ ******************************************************************************/
++
++struct acpi_table_hest {
++ struct acpi_table_header header; /* Common ACPI table header */
++ u32 error_source_count;
++};
++
++/* HEST subtable header */
++
++struct acpi_hest_header {
++ u16 type;
++};
++
++/* Values for Type field above for subtables */
++
++enum acpi_hest_types {
++ ACPI_HEST_TYPE_XPF_MACHINE_CHECK = 0,
++ ACPI_HEST_TYPE_XPF_CORRECTED_MACHINE_CHECK = 1,
++ ACPI_HEST_TYPE_XPF_UNUSED = 2,
++ ACPI_HEST_TYPE_XPF_NON_MASKABLE_INTERRUPT = 3,
++ ACPI_HEST_TYPE_IPF_CORRECTED_MACHINE_CHECK = 4,
++ ACPI_HEST_TYPE_IPF_CORRECTED_PLATFORM_ERROR = 5,
++ ACPI_HEST_TYPE_AER_ROOT_PORT = 6,
++ ACPI_HEST_TYPE_AER_ENDPOINT = 7,
++ ACPI_HEST_TYPE_AER_BRIDGE = 8,
++ ACPI_HEST_TYPE_GENERIC_HARDWARE_ERROR_SOURCE = 9,
++ ACPI_HEST_TYPE_RESERVED = 10 /* 10 and greater are reserved */
++};
++
++/*
++ * HEST Sub-subtables
++ */
++
++/* XPF Machine Check Error Bank */
++
++struct acpi_hest_xpf_error_bank {
++ u8 bank_number;
++ u8 clear_status_on_init;
++ u8 status_format;
++ u8 config_write_enable;
++ u32 control_register;
++ u64 control_init_data;
++ u32 status_register;
++ u32 address_register;
++ u32 misc_register;
++};
++
++/* Generic Error Status */
++
++struct acpi_hest_generic_status {
++ u32 block_status;
++ u32 raw_data_offset;
++ u32 raw_data_length;
++ u32 data_length;
++ u32 error_severity;
++};
++
++/* Generic Error Data */
++
++struct acpi_hest_generic_data {
++ u8 section_type[16];
++ u32 error_severity;
++ u16 revision;
++ u8 validation_bits;
++ u8 flags;
++ u32 error_data_length;
++ u8 fru_id[16];
++ u8 fru_text[20];
++};
++
++/* Common HEST structure for PCI/AER types below (6,7,8) */
++
++struct acpi_hest_aer_common {
++ u16 source_id;
++ u16 config_write_enable;
++ u8 flags;
++ u8 enabled;
++ u32 records_to_pre_allocate;
++ u32 max_sections_per_record;
++ u32 bus;
++ u16 device;
++ u16 function;
++ u16 device_control;
++ u16 reserved;
++ u32 uncorrectable_error_mask;
++ u32 uncorrectable_error_severity;
++ u32 correctable_error_mask;
++ u32 advanced_error_cababilities;
++};
++
++/* Hardware Error Notification */
++
++struct acpi_hest_notify {
++ u8 type;
++ u8 length;
++ u16 config_write_enable;
++ u32 poll_interval;
++ u32 vector;
++ u32 polling_threshold_value;
++ u32 polling_threshold_window;
++ u32 error_threshold_value;
++ u32 error_threshold_window;
++};
++
++/* Values for Notify Type field above */
++
++enum acpi_hest_notify_types {
++ ACPI_HEST_NOTIFY_POLLED = 0,
++ ACPI_HEST_NOTIFY_EXTERNAL = 1,
++ ACPI_HEST_NOTIFY_LOCAL = 2,
++ ACPI_HEST_NOTIFY_SCI = 3,
++ ACPI_HEST_NOTIFY_NMI = 4,
++ ACPI_HEST_NOTIFY_RESERVED = 5 /* 5 and greater are reserved */
++};
++
++/*
++ * HEST subtables
++ *
++ * From WHEA Design Document, 16 May 2007.
++ * Note: There is no subtable type 2 in this version of the document,
++ * and there are two different subtable type 3s.
++ */
++
++ /* 0: XPF Machine Check Exception */
++
++struct acpi_hest_xpf_machine_check {
++ struct acpi_hest_header header;
++ u16 source_id;
++ u16 config_write_enable;
++ u8 flags;
++ u8 reserved1;
++ u32 records_to_pre_allocate;
++ u32 max_sections_per_record;
++ u64 global_capability_data;
++ u64 global_control_data;
++ u8 num_hardware_banks;
++ u8 reserved2[7];
++};
++
++/* 1: XPF Corrected Machine Check */
++
++struct acpi_table_hest_xpf_corrected {
++ struct acpi_hest_header header;
++ u16 source_id;
++ u16 config_write_enable;
++ u8 flags;
++ u8 enabled;
++ u32 records_to_pre_allocate;
++ u32 max_sections_per_record;
++ struct acpi_hest_notify notify;
++ u8 num_hardware_banks;
++ u8 reserved[3];
++};
++
++/* 3: XPF Non-Maskable Interrupt */
++
++struct acpi_hest_xpf_nmi {
++ struct acpi_hest_header header;
++ u16 source_id;
++ u32 reserved;
++ u32 records_to_pre_allocate;
++ u32 max_sections_per_record;
++ u32 max_raw_data_length;
++};
++
++/* 4: IPF Corrected Machine Check */
++
++struct acpi_hest_ipf_corrected {
++ struct acpi_hest_header header;
++ u8 enabled;
++ u8 reserved;
++};
++
++/* 5: IPF Corrected Platform Error */
++
++struct acpi_hest_ipf_corrected_platform {
++ struct acpi_hest_header header;
++ u8 enabled;
++ u8 reserved;
++};
++
++/* 6: PCI Express Root Port AER */
++
++struct acpi_hest_aer_root {
++ struct acpi_hest_header header;
++ struct acpi_hest_aer_common aer;
++ u32 root_error_command;
++};
++
++/* 7: PCI Express AER (AER Endpoint) */
++
++struct acpi_hest_aer {
++ struct acpi_hest_header header;
++ struct acpi_hest_aer_common aer;
++};
++
++/* 8: PCI Express/PCI-X Bridge AER */
++
++struct acpi_hest_aer_bridge {
++ struct acpi_hest_header header;
++ struct acpi_hest_aer_common aer;
++ u32 secondary_uncorrectable_error_mask;
++ u32 secondary_uncorrectable_error_severity;
++ u32 secondary_advanced_capabilities;
++};
++
++/* 9: Generic Hardware Error Source */
++
++struct acpi_hest_generic {
++ struct acpi_hest_header header;
++ u16 source_id;
++ u16 related_source_id;
++ u8 config_write_enable;
++ u8 enabled;
++ u32 records_to_pre_allocate;
++ u32 max_sections_per_record;
++ u32 max_raw_data_length;
++ struct acpi_generic_address error_status_address;
++ struct acpi_hest_notify notify;
++ u32 error_status_block_length;
++};
++
++/*******************************************************************************
++ *
+ * HPET - High Precision Event Timer table
+ *
+ ******************************************************************************/
+@@ -373,6 +768,96 @@ struct acpi_table_hpet {
+
+ /*******************************************************************************
+ *
++ * IBFT - Boot Firmware Table
++ *
++ ******************************************************************************/
++
++struct acpi_table_ibft {
++ struct acpi_table_header header; /* Common ACPI table header */
++ u8 reserved[12];
++};
++
++/* IBFT common subtable header */
++
++struct acpi_ibft_header {
++ u8 type;
++ u8 version;
++ u16 length;
++ u8 index;
++ u8 flags;
++};
++
++/* Values for Type field above */
++
++enum acpi_ibft_type {
++ ACPI_IBFT_TYPE_NOT_USED = 0,
++ ACPI_IBFT_TYPE_CONTROL = 1,
++ ACPI_IBFT_TYPE_INITIATOR = 2,
++ ACPI_IBFT_TYPE_NIC = 3,
++ ACPI_IBFT_TYPE_TARGET = 4,
++ ACPI_IBFT_TYPE_EXTENSIONS = 5,
++ ACPI_IBFT_TYPE_RESERVED = 6 /* 6 and greater are reserved */
++};
++
++/* IBFT subtables */
++
++struct acpi_ibft_control {
++ struct acpi_ibft_header header;
++ u16 extensions;
++ u16 initiator_offset;
++ u16 nic0_offset;
++ u16 target0_offset;
++ u16 nic1_offset;
++ u16 target1_offset;
++};
++
++struct acpi_ibft_initiator {
++ struct acpi_ibft_header header;
++ u8 sns_server[16];
++ u8 slp_server[16];
++ u8 primary_server[16];
++ u8 secondary_server[16];
++ u16 name_length;
++ u16 name_offset;
++};
++
++struct acpi_ibft_nic {
++ struct acpi_ibft_header header;
++ u8 ip_address[16];
++ u8 subnet_mask_prefix;
++ u8 origin;
++ u8 gateway[16];
++ u8 primary_dns[16];
++ u8 secondary_dns[16];
++ u8 dhcp[16];
++ u16 vlan;
++ u8 mac_address[6];
++ u16 pci_address;
++ u16 name_length;
++ u16 name_offset;
++};
++
++struct acpi_ibft_target {
++ struct acpi_ibft_header header;
++ u8 target_ip_address[16];
++ u16 target_ip_socket;
++ u8 target_boot_lun[8];
++ u8 chap_type;
++ u8 nic_association;
++ u16 target_name_length;
++ u16 target_name_offset;
++ u16 chap_name_length;
++ u16 chap_name_offset;
++ u16 chap_secret_length;
++ u16 chap_secret_offset;
++ u16 reverse_chap_name_length;
++ u16 reverse_chap_name_offset;
++ u16 reverse_chap_secret_length;
++ u16 reverse_chap_secret_offset;
++};
++
++/*******************************************************************************
++ *
+ * MADT - Multiple APIC Description Table
+ *
+ ******************************************************************************/
+@@ -697,6 +1182,78 @@ struct acpi_table_tcpa {
+
+ /*******************************************************************************
+ *
++ * UEFI - UEFI Boot optimization Table
++ *
++ ******************************************************************************/
++
++struct acpi_table_uefi {
++ struct acpi_table_header header; /* Common ACPI table header */
++ u8 identifier[16]; /* UUID identifier */
++ u16 data_offset; /* Offset of remaining data in table */
++ u8 data;
++};
++
++/*******************************************************************************
++ *
++ * WDAT - Watchdog Action Table
++ *
++ ******************************************************************************/
++
++struct acpi_table_wdat {
++ struct acpi_table_header header; /* Common ACPI table header */
++ u32 header_length; /* Watchdog Header Length */
++ u16 pci_segment; /* PCI Segment number */
++ u8 pci_bus; /* PCI Bus number */
++ u8 pci_device; /* PCI Device number */
++ u8 pci_function; /* PCI Function number */
++ u8 reserved[3];
++ u32 timer_period; /* Period of one timer count (msec) */
++ u32 max_count; /* Maximum counter value supported */
++ u32 min_count; /* Minimum counter value */
++ u8 flags;
++ u8 reserved2[3];
++ u32 entries; /* Number of watchdog entries that follow */
++};
++
++/* WDAT Instruction Entries (actions) */
++
++struct acpi_wdat_entry {
++ struct acpi_whea_header whea_header; /* Common header for WHEA tables */
++};
++
++/* Values for Action field above */
++
++enum acpi_wdat_actions {
++ ACPI_WDAT_RESET = 1,
++ ACPI_WDAT_GET_CURRENT_COUNTDOWN = 4,
++ ACPI_WDAT_GET_COUNTDOWN = 5,
++ ACPI_WDAT_SET_COUNTDOWN = 6,
++ ACPI_WDAT_GET_RUNNING_STATE = 8,
++ ACPI_WDAT_SET_RUNNING_STATE = 9,
++ ACPI_WDAT_GET_STOPPED_STATE = 10,
++ ACPI_WDAT_SET_STOPPED_STATE = 11,
++ ACPI_WDAT_GET_REBOOT = 16,
++ ACPI_WDAT_SET_REBOOT = 17,
++ ACPI_WDAT_GET_SHUTDOWN = 18,
++ ACPI_WDAT_SET_SHUTDOWN = 19,
++ ACPI_WDAT_GET_STATUS = 32,
++ ACPI_WDAT_SET_STATUS = 33,
++ ACPI_WDAT_ACTION_RESERVED = 34 /* 34 and greater are reserved */
++};
++
++/* Values for Instruction field above */
++
++enum acpi_wdat_instructions {
++ ACPI_WDAT_READ_VALUE = 0,
++ ACPI_WDAT_READ_COUNTDOWN = 1,
++ ACPI_WDAT_WRITE_VALUE = 2,
++ ACPI_WDAT_WRITE_COUNTDOWN = 3,
++ ACPI_WDAT_INSTRUCTION_RESERVED = 4, /* 4 and greater are reserved */
++ ACPI_WDAT_PRESERVE_REGISTER = 0x80 /* Except for this value */
++};
++
++/*******************************************************************************
++ *
+ * WDRT - Watchdog Resource Table
+ *
+ ******************************************************************************/
+diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
+index e73a389..dfea2d4 100644
+--- a/include/acpi/actypes.h
++++ b/include/acpi/actypes.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -323,27 +323,11 @@ struct uint32_struct {
+ #define acpi_semaphore void *
+
+ /*
+- * Acpi integer width. In ACPI version 1, integers are
+- * 32 bits. In ACPI version 2, integers are 64 bits.
+- * Note that this pertains to the ACPI integer type only, not
+- * other integers used in the implementation of the ACPI CA
++ * Acpi integer width. In ACPI version 1, integers are 32 bits. In ACPI
++ * version 2, integers are 64 bits. Note that this pertains to the ACPI integer
++ * type only, not other integers used in the implementation of the ACPI CA
+ * subsystem.
+ */
+-#ifdef ACPI_NO_INTEGER64_SUPPORT
+-
+-/* 32-bit integers only, no 64-bit support */
+-
+-typedef u32 acpi_integer;
+-#define ACPI_INTEGER_MAX ACPI_UINT32_MAX
+-#define ACPI_INTEGER_BIT_SIZE 32
+-#define ACPI_MAX_DECIMAL_DIGITS 10 /* 2^32 = 4,294,967,296 */
+-
+-#define ACPI_USE_NATIVE_DIVIDE /* Use compiler native 32-bit divide */
+-
+-#else
+-
+-/* 64-bit integers */
+-
+ typedef unsigned long long acpi_integer;
+ #define ACPI_INTEGER_MAX ACPI_UINT64_MAX
+ #define ACPI_INTEGER_BIT_SIZE 64
+@@ -352,7 +336,6 @@ typedef unsigned long long acpi_integer;
+ #if ACPI_MACHINE_WIDTH == 64
+ #define ACPI_USE_NATIVE_DIVIDE /* Use compiler native 64-bit divide */
+ #endif
+-#endif
+
+ #define ACPI_MAX64_DECIMAL_DIGITS 20
+ #define ACPI_MAX32_DECIMAL_DIGITS 10
+@@ -419,14 +402,20 @@ typedef unsigned long long acpi_integer;
+ /*
+ * Standard notify values
+ */
+-#define ACPI_NOTIFY_BUS_CHECK (u8) 0
+-#define ACPI_NOTIFY_DEVICE_CHECK (u8) 1
+-#define ACPI_NOTIFY_DEVICE_WAKE (u8) 2
+-#define ACPI_NOTIFY_EJECT_REQUEST (u8) 3
+-#define ACPI_NOTIFY_DEVICE_CHECK_LIGHT (u8) 4
+-#define ACPI_NOTIFY_FREQUENCY_MISMATCH (u8) 5
+-#define ACPI_NOTIFY_BUS_MODE_MISMATCH (u8) 6
+-#define ACPI_NOTIFY_POWER_FAULT (u8) 7
++#define ACPI_NOTIFY_BUS_CHECK (u8) 0x00
++#define ACPI_NOTIFY_DEVICE_CHECK (u8) 0x01
++#define ACPI_NOTIFY_DEVICE_WAKE (u8) 0x02
++#define ACPI_NOTIFY_EJECT_REQUEST (u8) 0x03
++#define ACPI_NOTIFY_DEVICE_CHECK_LIGHT (u8) 0x04
++#define ACPI_NOTIFY_FREQUENCY_MISMATCH (u8) 0x05
++#define ACPI_NOTIFY_BUS_MODE_MISMATCH (u8) 0x06
++#define ACPI_NOTIFY_POWER_FAULT (u8) 0x07
++#define ACPI_NOTIFY_CAPABILITIES_CHECK (u8) 0x08
++#define ACPI_NOTIFY_DEVICE_PLD_CHECK (u8) 0x09
++#define ACPI_NOTIFY_RESERVED (u8) 0x0A
++#define ACPI_NOTIFY_LOCALITY_UPDATE (u8) 0x0B
++
++#define ACPI_NOTIFY_MAX 0x0B
+
+ /*
+ * Types associated with ACPI names and objects. The first group of
+@@ -494,6 +483,8 @@ typedef u32 acpi_object_type;
+ #define ACPI_TYPE_INVALID 0x1E
+ #define ACPI_TYPE_NOT_FOUND 0xFF
+
++#define ACPI_NUM_NS_TYPES (ACPI_TYPE_INVALID + 1)
++
+ /*
+ * All I/O
+ */
+@@ -599,7 +590,7 @@ typedef u32 acpi_event_status;
+
+ #define ACPI_SYSTEM_NOTIFY 0x1
+ #define ACPI_DEVICE_NOTIFY 0x2
+-#define ACPI_ALL_NOTIFY 0x3
++#define ACPI_ALL_NOTIFY (ACPI_SYSTEM_NOTIFY | ACPI_DEVICE_NOTIFY)
+ #define ACPI_MAX_NOTIFY_HANDLER_TYPE 0x3
+
+ #define ACPI_MAX_SYS_NOTIFY 0x7f
+@@ -654,46 +645,51 @@ typedef u8 acpi_adr_space_type;
+ /*
+ * External ACPI object definition
+ */
++
++/*
++ * Note: Type == ACPI_TYPE_ANY (0) is used to indicate a NULL package element
++ * or an unresolved named reference.
++ */
+ union acpi_object {
+ acpi_object_type type; /* See definition of acpi_ns_type for values */
+ struct {
+- acpi_object_type type;
++ acpi_object_type type; /* ACPI_TYPE_INTEGER */
+ acpi_integer value; /* The actual number */
+ } integer;
+
+ struct {
+- acpi_object_type type;
++ acpi_object_type type; /* ACPI_TYPE_STRING */
+ u32 length; /* # of bytes in string, excluding trailing null */
+ char *pointer; /* points to the string value */
+ } string;
+
+ struct {
+- acpi_object_type type;
++ acpi_object_type type; /* ACPI_TYPE_BUFFER */
+ u32 length; /* # of bytes in buffer */
+ u8 *pointer; /* points to the buffer */
+ } buffer;
+
+ struct {
+- acpi_object_type type;
+- u32 fill1;
+- acpi_handle handle; /* object reference */
+- } reference;
+-
+- struct {
+- acpi_object_type type;
++ acpi_object_type type; /* ACPI_TYPE_PACKAGE */
+ u32 count; /* # of elements in package */
+ union acpi_object *elements; /* Pointer to an array of ACPI_OBJECTs */
+ } package;
+
+ struct {
+- acpi_object_type type;
++ acpi_object_type type; /* ACPI_TYPE_LOCAL_REFERENCE */
++ acpi_object_type actual_type; /* Type associated with the Handle */
++ acpi_handle handle; /* object reference */
++ } reference;
++
++ struct {
++ acpi_object_type type; /* ACPI_TYPE_PROCESSOR */
+ u32 proc_id;
+ acpi_io_address pblk_address;
+ u32 pblk_length;
+ } processor;
+
+ struct {
+- acpi_object_type type;
++ acpi_object_type type; /* ACPI_TYPE_POWER */
+ u32 system_level;
+ u32 resource_order;
+ } power_resource;
+@@ -747,6 +743,12 @@ struct acpi_system_info {
+ u32 debug_layer;
+ };
+
++/* Table Event Types */
++
++#define ACPI_TABLE_EVENT_LOAD 0x0
++#define ACPI_TABLE_EVENT_UNLOAD 0x1
++#define ACPI_NUM_TABLE_EVENTS 2
++
+ /*
+ * Types specific to the OS service interfaces
+ */
+@@ -776,6 +778,11 @@ acpi_status(*acpi_exception_handler) (acpi_status aml_status,
+ u16 opcode,
+ u32 aml_offset, void *context);
+
++/* Table Event handler (Load, load_table etc) and types */
++
++typedef
++acpi_status(*acpi_tbl_handler) (u32 event, void *table, void *context);
++
+ /* Address Spaces (For Operation Regions) */
+
+ typedef
+@@ -990,6 +997,7 @@ struct acpi_vendor_uuid {
+ * Structures used to describe device resources
+ */
+ struct acpi_resource_irq {
++ u8 descriptor_length;
+ u8 triggering;
+ u8 polarity;
+ u8 sharable;
+@@ -1006,6 +1014,7 @@ struct acpi_resource_dma {
+ };
+
+ struct acpi_resource_start_dependent {
++ u8 descriptor_length;
+ u8 compatibility_priority;
+ u8 performance_robustness;
+ };
+diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h
+index a291854..b42cadf 100644
+--- a/include/acpi/acutils.h
++++ b/include/acpi/acutils.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -116,6 +116,8 @@ void acpi_ut_init_globals(void);
+
+ char *acpi_ut_get_mutex_name(u32 mutex_id);
+
++const char *acpi_ut_get_notify_name(u32 notify_value);
++
+ #endif
+
+ char *acpi_ut_get_type_name(acpi_object_type type);
+diff --git a/include/acpi/amlcode.h b/include/acpi/amlcode.h
+index da53a4e..ff851c5 100644
+--- a/include/acpi/amlcode.h
++++ b/include/acpi/amlcode.h
+@@ -7,7 +7,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/include/acpi/amlresrc.h b/include/acpi/amlresrc.h
+index f7d5412..7b070e4 100644
+--- a/include/acpi/amlresrc.h
++++ b/include/acpi/amlresrc.h
+@@ -6,7 +6,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h
+index c785485..fcd2572 100644
+--- a/include/acpi/platform/acenv.h
++++ b/include/acpi/platform/acenv.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/include/acpi/platform/acgcc.h b/include/acpi/platform/acgcc.h
+index 3bb5049..8996dba 100644
+--- a/include/acpi/platform/acgcc.h
++++ b/include/acpi/platform/acgcc.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
+index 6ed15a0..9af4645 100644
+--- a/include/acpi/platform/aclinux.h
++++ b/include/acpi/platform/aclinux.h
+@@ -5,7 +5,7 @@
+ *****************************************************************************/
+
+ /*
+- * Copyright (C) 2000 - 2007, R. Byron Moore
++ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+diff --git a/include/asm-alpha/bitops.h b/include/asm-alpha/bitops.h
+index 9e19a70..15f3ae2 100644
+--- a/include/asm-alpha/bitops.h
++++ b/include/asm-alpha/bitops.h
+@@ -388,6 +388,11 @@ static inline int fls64(unsigned long x)
+ }
+ #endif
+
++static inline unsigned long __fls(unsigned long x)
++{
++ return fls64(x) - 1;
++}
++
+ static inline int fls(int x)
+ {
+ return fls64((unsigned int) x);
+diff --git a/include/asm-alpha/bug.h b/include/asm-alpha/bug.h
+index 39a3e2a..695a5ee 100644
+--- a/include/asm-alpha/bug.h
++++ b/include/asm-alpha/bug.h
+@@ -1,14 +1,24 @@
+ #ifndef _ALPHA_BUG_H
+ #define _ALPHA_BUG_H
+
++#include <linux/linkage.h>
++
+ #ifdef CONFIG_BUG
+ #include <asm/pal.h>
+
+ /* ??? Would be nice to use .gprel32 here, but we can't be sure that the
+ function loaded the GP, so this could fail in modules. */
+-#define BUG() \
+- __asm__ __volatile__("call_pal %0 # bugchk\n\t"".long %1\n\t.8byte %2" \
+- : : "i" (PAL_bugchk), "i"(__LINE__), "i"(__FILE__))
++static inline void ATTRIB_NORET __BUG(const char *file, int line)
++{
++ __asm__ __volatile__(
++ "call_pal %0 # bugchk\n\t"
++ ".long %1\n\t.8byte %2"
++ : : "i" (PAL_bugchk), "i"(line), "i"(file));
++ for ( ; ; )
++ ;
++}
++
++#define BUG() __BUG(__FILE__, __LINE__)
+
+ #define HAVE_ARCH_BUG
+ #endif
+diff --git a/include/asm-alpha/byteorder.h b/include/asm-alpha/byteorder.h
+index 7af2b8d..58e958f 100644
+--- a/include/asm-alpha/byteorder.h
++++ b/include/asm-alpha/byteorder.h
+@@ -7,7 +7,7 @@
+
+ #ifdef __GNUC__
+
+-static __inline __attribute_const__ __u32 __arch__swab32(__u32 x)
++static inline __attribute_const__ __u32 __arch__swab32(__u32 x)
+ {
+ /*
+ * Unfortunately, we can't use the 6 instruction sequence
diff --git a/include/asm-alpha/ide.h b/include/asm-alpha/ide.h
index b7bf68d..f44129a 100644
--- a/include/asm-alpha/ide.h
@@ -769674,6 +1027763,26 @@
#include <asm-generic/ide_iops.h>
#endif /* __KERNEL__ */
+diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
+index 99037b0..05ce5fb 100644
+--- a/include/asm-alpha/pgtable.h
++++ b/include/asm-alpha/pgtable.h
+@@ -268,6 +268,7 @@ extern inline int pte_write(pte_t pte) { return !(pte_val(pte) & _PAGE_FOW); }
+ extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
+ extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+ extern inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
++extern inline int pte_special(pte_t pte) { return 0; }
+
+ extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) |= _PAGE_FOW; return pte; }
+ extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~(__DIRTY_BITS); return pte; }
+@@ -275,6 +276,7 @@ extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~(__ACCESS_BITS); ret
+ extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) &= ~_PAGE_FOW; return pte; }
+ extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= __DIRTY_BITS; return pte; }
+ extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= __ACCESS_BITS; return pte; }
++extern inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+
+ #define PAGE_DIR_OFFSET(tsk,address) pgd_offset((tsk),(address))
+
diff --git a/include/asm-alpha/semaphore.h b/include/asm-alpha/semaphore.h
index f1e9278..d9b2034 100644
--- a/include/asm-alpha/semaphore.h
@@ -769843,6 +1027952,26 @@
+# include <asm-generic/topology.h>
#endif /* _ASM_ALPHA_TOPOLOGY_H */
+diff --git a/include/asm-alpha/unaligned.h b/include/asm-alpha/unaligned.h
+index a1d7284..3787c60 100644
+--- a/include/asm-alpha/unaligned.h
++++ b/include/asm-alpha/unaligned.h
+@@ -1,6 +1,11 @@
+-#ifndef __ALPHA_UNALIGNED_H
+-#define __ALPHA_UNALIGNED_H
++#ifndef _ASM_ALPHA_UNALIGNED_H
++#define _ASM_ALPHA_UNALIGNED_H
+
+-#include <asm-generic/unaligned.h>
++#include <linux/unaligned/le_struct.h>
++#include <linux/unaligned/be_byteshift.h>
++#include <linux/unaligned/generic.h>
+
+-#endif
++#define get_unaligned __get_unaligned_le
++#define put_unaligned __put_unaligned_le
++
++#endif /* _ASM_ALPHA_UNALIGNED_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
@@ -773431,10 +1031560,10 @@
+#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
+index 0000000..50f8c88
--- /dev/null
+++ b/include/asm-arm/arch-orion5x/io.h
-@@ -0,0 +1,68 @@
+@@ -0,0 +1,67 @@
+/*
+ * include/asm-arm/arch-orion5x/io.h
+ *
@@ -773457,11 +1031586,10 @@
+__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);
++ unsigned long offs = paddr - ORION5X_REGS_PHYS_BASE;
++ if (mtype == MT_DEVICE && size && offs < ORION5X_REGS_SIZE &&
++ size <= ORION5X_REGS_SIZE && offs + size <= ORION5X_REGS_SIZE) {
++ retval = (void __iomem *)ORION5X_REGS_VIRT_BASE + offs;
+ } else {
+ retval = __arm_ioremap(paddr, size, mtype);
+ }
@@ -774036,7 +1032164,7 @@
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
+index c562b97..b6c8fe3 100644
--- a/include/asm-arm/arch-pxa/irqs.h
+++ b/include/asm-arm/arch-pxa/irqs.h
@@ -181,7 +181,8 @@
@@ -774049,21 +1032177,39 @@
#define NR_IRQS (IRQ_BOARD_END)
#else
#define NR_IRQS (IRQ_BOARD_START)
+@@ -238,7 +239,7 @@
+ /* ITE8152 irqs */
+ /* add IT8152 IRQs beyond BOARD_END */
+ #ifdef CONFIG_PCI_HOST_ITE8152
+-#define IT8152_IRQ(x) (IRQ_GPIO(IRQ_BOARD_END) + 1 + (x))
++#define IT8152_IRQ(x) (IRQ_BOARD_END + (x))
+
+ /* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */
+ #define IT8152_LD_IRQ_COUNT 9
+@@ -252,6 +253,9 @@
+
+ #define IT8152_LAST_IRQ IT8152_LD_IRQ(IT8152_LD_IRQ_COUNT - 1)
+
++#if NR_IRQS < (IT8152_LAST_IRQ+1)
+ #undef NR_IRQS
+ #define NR_IRQS (IT8152_LAST_IRQ+1)
+ #endif
++
++#endif /* CONFIG_PCI_HOST_ITE8152 */
diff --git a/include/asm-arm/arch-pxa/magician.h b/include/asm-arm/arch-pxa/magician.h
-index 337f51f..b34fd56 100644
+index 337f51f..169b374 100644
--- a/include/asm-arm/arch-pxa/magician.h
+++ b/include/asm-arm/arch-pxa/magician.h
-@@ -12,7 +12,8 @@
+@@ -12,7 +12,7 @@
#ifndef _MAGICIAN_H_
#define _MAGICIAN_H_
-#include <asm/arch/pxa-regs.h>
+#include <asm/arch/irqs.h>
-+#include <asm/arch/pxa2xx-gpio.h>
/*
* PXA GPIOs
-@@ -34,6 +35,7 @@
+@@ -34,6 +34,7 @@
#define GPIO48_MAGICIAN_UNKNOWN 48
#define GPIO56_MAGICIAN_UNKNOWN 56
#define GPIO57_MAGICIAN_CAM_RESET 57
@@ -774071,22 +1032217,56 @@
#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)
+@@ -62,50 +63,55 @@
+ #define GPIO120_MAGICIAN_UNKNOWN 120
-+/*
+ /*
+- * PXA GPIO alternate function mode & direction
+ * CPLD IRQs
-+ */
-+
+ */
+
+-#define GPIO0_MAGICIAN_KEY_POWER_MD (0 | GPIO_IN)
+-#define GPIO9_MAGICIAN_UNKNOWN_MD (9 | GPIO_IN)
+-#define GPIO10_MAGICIAN_GSM_IRQ_MD (10 | GPIO_IN)
+-#define GPIO11_MAGICIAN_GSM_OUT1_MD (11 | GPIO_OUT)
+-#define GPIO13_MAGICIAN_CPLD_IRQ_MD (13 | GPIO_IN)
+-#define GPIO18_MAGICIAN_UNKNOWN_MD (18 | GPIO_OUT)
+-#define GPIO22_MAGICIAN_VIBRA_EN_MD (22 | GPIO_OUT)
+-#define GPIO26_MAGICIAN_GSM_POWER_MD (26 | GPIO_OUT)
+-#define GPIO27_MAGICIAN_USBC_PUEN_MD (27 | GPIO_OUT)
+-#define GPIO30_MAGICIAN_nCHARGE_EN_MD (30 | GPIO_OUT)
+-#define GPIO37_MAGICIAN_KEY_HANGUP_MD (37 | GPIO_OUT)
+-#define GPIO38_MAGICIAN_KEY_CONTACTS_MD (38 | GPIO_OUT)
+-#define GPIO40_MAGICIAN_GSM_OUT2_MD (40 | GPIO_OUT)
+-#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 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)
+-#define GPIO90_MAGICIAN_KEY_CALENDAR_MD (90 | GPIO_OUT)
+-#define GPIO91_MAGICIAN_KEY_CAMERA_MD (91 | GPIO_OUT)
+-#define GPIO93_MAGICIAN_KEY_UP_MD (93 | GPIO_IN)
+-#define GPIO94_MAGICIAN_KEY_DOWN_MD (94 | GPIO_IN)
+-#define GPIO95_MAGICIAN_KEY_LEFT_MD (95 | GPIO_IN)
+-#define GPIO96_MAGICIAN_KEY_RIGHT_MD (96 | GPIO_IN)
+-#define GPIO97_MAGICIAN_KEY_ENTER_MD (97 | GPIO_IN)
+-#define GPIO98_MAGICIAN_KEY_RECORD_MD (98 | GPIO_IN)
+-#define GPIO99_MAGICIAN_HEADPHONE_IN_MD (99 | GPIO_IN)
+-#define GPIO100_MAGICIAN_KEY_VOL_UP_MD (100 | GPIO_IN)
+-#define GPIO101_MAGICIAN_KEY_VOL_DOWN_MD (101 | GPIO_IN)
+-#define GPIO102_MAGICIAN_KEY_PHONE_MD (102 | GPIO_IN)
+-#define GPIO103_MAGICIAN_LED_KP_MD (103 | GPIO_OUT)
+-#define GPIO104_MAGICIAN_LCD_POWER_1_MD (104 | GPIO_OUT)
+-#define GPIO105_MAGICIAN_LCD_POWER_2_MD (105 | GPIO_OUT)
+-#define GPIO106_MAGICIAN_LCD_POWER_3_MD (106 | GPIO_OUT)
+-#define GPIO107_MAGICIAN_DS1WM_IRQ_MD (107 | GPIO_IN)
+-#define GPIO108_MAGICIAN_GSM_READY_MD (108 | GPIO_IN)
+-#define GPIO114_MAGICIAN_UNKNOWN_MD (114 | GPIO_OUT)
+-#define GPIO115_MAGICIAN_nPEN_IRQ_MD (115 | GPIO_IN)
+-#define GPIO116_MAGICIAN_nCAM_EN_MD (116 | GPIO_OUT)
+-#define GPIO119_MAGICIAN_UNKNOWN_MD (119 | GPIO_OUT)
+-#define GPIO120_MAGICIAN_UNKNOWN_MD (120 | GPIO_OUT)
+#define IRQ_MAGICIAN_SD (IRQ_BOARD_START + 0)
+#define IRQ_MAGICIAN_EP (IRQ_BOARD_START + 1)
+#define IRQ_MAGICIAN_BT (IRQ_BOARD_START + 2)
@@ -774134,7 +1032314,7 @@
+#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
@@ -774880,7 +1033060,7 @@
+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
+index 2357a73..4b2ea1e 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -1129,6 +1129,11 @@
@@ -775176,8 +1033356,206 @@
/*
* Power Manager
*/
-@@ -1866,62 +1604,6 @@
-
+@@ -1668,260 +1406,8 @@
+ #define OSCC_OON (1 << 1) /* 32.768kHz OON (write-once only bit) */
+ #define OSCC_OOK (1 << 0) /* 32.768kHz OOK (read-only bit) */
+
+-
+-/*
+- * LCD
+- */
+-
+-#define LCCR0 __REG(0x44000000) /* LCD Controller Control Register 0 */
+-#define LCCR1 __REG(0x44000004) /* LCD Controller Control Register 1 */
+-#define LCCR2 __REG(0x44000008) /* LCD Controller Control Register 2 */
+-#define LCCR3 __REG(0x4400000C) /* LCD Controller Control Register 3 */
+-#define LCCR4 __REG(0x44000010) /* LCD Controller Control Register 3 */
+-#define DFBR0 __REG(0x44000020) /* DMA Channel 0 Frame Branch Register */
+-#define DFBR1 __REG(0x44000024) /* DMA Channel 1 Frame Branch Register */
+-#define LCSR __REG(0x44000038) /* LCD Controller Status Register */
+-#define LIIDR __REG(0x4400003C) /* LCD Controller Interrupt ID Register */
+-#define TMEDRGBR __REG(0x44000040) /* TMED RGB Seed Register */
+-#define TMEDCR __REG(0x44000044) /* TMED Control Register */
+-
+-#define LCCR3_1BPP (0 << 24)
+-#define LCCR3_2BPP (1 << 24)
+-#define LCCR3_4BPP (2 << 24)
+-#define LCCR3_8BPP (3 << 24)
+-#define LCCR3_16BPP (4 << 24)
+-
+-#define LCCR3_PDFOR_0 (0 << 30)
+-#define LCCR3_PDFOR_1 (1 << 30)
+-#define LCCR3_PDFOR_2 (2 << 30)
+-#define LCCR3_PDFOR_3 (3 << 30)
+-
+-#define LCCR4_PAL_FOR_0 (0 << 15)
+-#define LCCR4_PAL_FOR_1 (1 << 15)
+-#define LCCR4_PAL_FOR_2 (2 << 15)
+-#define LCCR4_PAL_FOR_MASK (3 << 15)
+-
+-#define FDADR0 __REG(0x44000200) /* DMA Channel 0 Frame Descriptor Address Register */
+-#define FSADR0 __REG(0x44000204) /* DMA Channel 0 Frame Source Address Register */
+-#define FIDR0 __REG(0x44000208) /* DMA Channel 0 Frame ID Register */
+-#define LDCMD0 __REG(0x4400020C) /* DMA Channel 0 Command Register */
+-#define FDADR1 __REG(0x44000210) /* DMA Channel 1 Frame Descriptor Address Register */
+-#define FSADR1 __REG(0x44000214) /* DMA Channel 1 Frame Source Address Register */
+-#define FIDR1 __REG(0x44000218) /* DMA Channel 1 Frame ID Register */
+-#define LDCMD1 __REG(0x4400021C) /* DMA Channel 1 Command Register */
+-
+-#define LCCR0_ENB (1 << 0) /* LCD Controller enable */
+-#define LCCR0_CMS (1 << 1) /* Color/Monochrome Display Select */
+-#define LCCR0_Color (LCCR0_CMS*0) /* Color display */
+-#define LCCR0_Mono (LCCR0_CMS*1) /* Monochrome display */
+-#define LCCR0_SDS (1 << 2) /* Single/Dual Panel Display */
+- /* Select */
+-#define LCCR0_Sngl (LCCR0_SDS*0) /* Single panel display */
+-#define LCCR0_Dual (LCCR0_SDS*1) /* Dual panel display */
+-
+-#define LCCR0_LDM (1 << 3) /* LCD Disable Done Mask */
+-#define LCCR0_SFM (1 << 4) /* Start of frame mask */
+-#define LCCR0_IUM (1 << 5) /* Input FIFO underrun mask */
+-#define LCCR0_EFM (1 << 6) /* End of Frame mask */
+-#define LCCR0_PAS (1 << 7) /* Passive/Active display Select */
+-#define LCCR0_Pas (LCCR0_PAS*0) /* Passive display (STN) */
+-#define LCCR0_Act (LCCR0_PAS*1) /* Active display (TFT) */
+-#define LCCR0_DPD (1 << 9) /* Double Pixel Data (monochrome */
+- /* display mode) */
+-#define LCCR0_4PixMono (LCCR0_DPD*0) /* 4-Pixel/clock Monochrome */
+- /* display */
+-#define LCCR0_8PixMono (LCCR0_DPD*1) /* 8-Pixel/clock Monochrome */
+- /* display */
+-#define LCCR0_DIS (1 << 10) /* LCD Disable */
+-#define LCCR0_QDM (1 << 11) /* LCD Quick Disable mask */
+-#define LCCR0_PDD (0xff << 12) /* Palette DMA request delay */
+-#define LCCR0_PDD_S 12
+-#define LCCR0_BM (1 << 20) /* Branch mask */
+-#define LCCR0_OUM (1 << 21) /* Output FIFO underrun mask */
+-#define LCCR0_LCDT (1 << 22) /* LCD panel type */
+-#define LCCR0_RDSTM (1 << 23) /* Read status interrupt mask */
+-#define LCCR0_CMDIM (1 << 24) /* Command interrupt mask */
+-#define LCCR0_OUC (1 << 25) /* Overlay Underlay control bit */
+-#define LCCR0_LDDALT (1 << 26) /* LDD alternate mapping control */
+-
+-#define LCCR1_PPL Fld (10, 0) /* Pixels Per Line - 1 */
+-#define LCCR1_DisWdth(Pixel) /* Display Width [1..800 pix.] */ \
+- (((Pixel) - 1) << FShft (LCCR1_PPL))
+-
+-#define LCCR1_HSW Fld (6, 10) /* Horizontal Synchronization */
+-#define LCCR1_HorSnchWdth(Tpix) /* Horizontal Synchronization */ \
+- /* pulse Width [1..64 Tpix] */ \
+- (((Tpix) - 1) << FShft (LCCR1_HSW))
+-
+-#define LCCR1_ELW Fld (8, 16) /* End-of-Line pixel clock Wait */
+- /* count - 1 [Tpix] */
+-#define LCCR1_EndLnDel(Tpix) /* End-of-Line Delay */ \
+- /* [1..256 Tpix] */ \
+- (((Tpix) - 1) << FShft (LCCR1_ELW))
+-
+-#define LCCR1_BLW Fld (8, 24) /* Beginning-of-Line pixel clock */
+- /* Wait count - 1 [Tpix] */
+-#define LCCR1_BegLnDel(Tpix) /* Beginning-of-Line Delay */ \
+- /* [1..256 Tpix] */ \
+- (((Tpix) - 1) << FShft (LCCR1_BLW))
+-
+-
+-#define LCCR2_LPP Fld (10, 0) /* Line Per Panel - 1 */
+-#define LCCR2_DisHght(Line) /* Display Height [1..1024 lines] */ \
+- (((Line) - 1) << FShft (LCCR2_LPP))
+-
+-#define LCCR2_VSW Fld (6, 10) /* Vertical Synchronization pulse */
+- /* Width - 1 [Tln] (L_FCLK) */
+-#define LCCR2_VrtSnchWdth(Tln) /* Vertical Synchronization pulse */ \
+- /* Width [1..64 Tln] */ \
+- (((Tln) - 1) << FShft (LCCR2_VSW))
+-
+-#define LCCR2_EFW Fld (8, 16) /* End-of-Frame line clock Wait */
+- /* count [Tln] */
+-#define LCCR2_EndFrmDel(Tln) /* End-of-Frame Delay */ \
+- /* [0..255 Tln] */ \
+- ((Tln) << FShft (LCCR2_EFW))
+-
+-#define LCCR2_BFW Fld (8, 24) /* Beginning-of-Frame line clock */
+- /* Wait count [Tln] */
+-#define LCCR2_BegFrmDel(Tln) /* Beginning-of-Frame Delay */ \
+- /* [0..255 Tln] */ \
+- ((Tln) << FShft (LCCR2_BFW))
+-
+-#if 0
+-#define LCCR3_PCD (0xff) /* Pixel clock divisor */
+-#define LCCR3_ACB (0xff << 8) /* AC Bias pin frequency */
+-#define LCCR3_ACB_S 8
+-#endif
+-
+-#define LCCR3_API (0xf << 16) /* AC Bias pin trasitions per interrupt */
+-#define LCCR3_API_S 16
+-#define LCCR3_VSP (1 << 20) /* vertical sync polarity */
+-#define LCCR3_HSP (1 << 21) /* horizontal sync polarity */
+-#define LCCR3_PCP (1 << 22) /* Pixel Clock Polarity (L_PCLK) */
+-#define LCCR3_PixRsEdg (LCCR3_PCP*0) /* Pixel clock Rising-Edge */
+-#define LCCR3_PixFlEdg (LCCR3_PCP*1) /* Pixel clock Falling-Edge */
+-
+-#define LCCR3_OEP (1 << 23) /* Output Enable Polarity (L_BIAS, */
+- /* active display mode) */
+-#define LCCR3_OutEnH (LCCR3_OEP*0) /* Output Enable active High */
+-#define LCCR3_OutEnL (LCCR3_OEP*1) /* Output Enable active Low */
+-
+-#if 0
+-#define LCCR3_BPP (7 << 24) /* bits per pixel */
+-#define LCCR3_BPP_S 24
+-#endif
+-#define LCCR3_DPC (1 << 27) /* double pixel clock mode */
+-
+-
+-#define LCCR3_PCD Fld (8, 0) /* Pixel Clock Divisor */
+-#define LCCR3_PixClkDiv(Div) /* Pixel Clock Divisor */ \
+- (((Div) << FShft (LCCR3_PCD)))
+-
+-
+-#define LCCR3_BPP Fld (3, 24) /* Bit Per Pixel */
+-#define LCCR3_Bpp(Bpp) /* Bit Per Pixel */ \
+- (((Bpp) << FShft (LCCR3_BPP)))
+-
+-#define LCCR3_ACB Fld (8, 8) /* AC Bias */
+-#define LCCR3_Acb(Acb) /* BAC Bias */ \
+- (((Acb) << FShft (LCCR3_ACB)))
+-
+-#define LCCR3_HorSnchH (LCCR3_HSP*0) /* Horizontal Synchronization */
+- /* pulse active High */
+-#define LCCR3_HorSnchL (LCCR3_HSP*1) /* Horizontal Synchronization */
+-
+-#define LCCR3_VrtSnchH (LCCR3_VSP*0) /* Vertical Synchronization pulse */
+- /* active High */
+-#define LCCR3_VrtSnchL (LCCR3_VSP*1) /* Vertical Synchronization pulse */
+- /* active Low */
+-
+-#define LCSR_LDD (1 << 0) /* LCD Disable Done */
+-#define LCSR_SOF (1 << 1) /* Start of frame */
+-#define LCSR_BER (1 << 2) /* Bus error */
+-#define LCSR_ABC (1 << 3) /* AC Bias count */
+-#define LCSR_IUL (1 << 4) /* input FIFO underrun Lower panel */
+-#define LCSR_IUU (1 << 5) /* input FIFO underrun Upper panel */
+-#define LCSR_OU (1 << 6) /* output FIFO underrun */
+-#define LCSR_QD (1 << 7) /* quick disable */
+-#define LCSR_EOF (1 << 8) /* end of frame */
+-#define LCSR_BS (1 << 9) /* branch status */
+-#define LCSR_SINT (1 << 10) /* subsequent interrupt */
+-
+-#define LDCMD_PAL (1 << 26) /* instructs DMA to load palette buffer */
+-
+-#define LCSR_LDD (1 << 0) /* LCD Disable Done */
+-#define LCSR_SOF (1 << 1) /* Start of frame */
+-#define LCSR_BER (1 << 2) /* Bus error */
+-#define LCSR_ABC (1 << 3) /* AC Bias count */
+-#define LCSR_IUL (1 << 4) /* input FIFO underrun Lower panel */
+-#define LCSR_IUU (1 << 5) /* input FIFO underrun Upper panel */
+-#define LCSR_OU (1 << 6) /* output FIFO underrun */
+-#define LCSR_QD (1 << 7) /* quick disable */
+-#define LCSR_EOF (1 << 8) /* end of frame */
+-#define LCSR_BS (1 << 9) /* branch status */
+-#define LCSR_SINT (1 << 10) /* subsequent interrupt */
+-
+-#define LDCMD_PAL (1 << 26) /* instructs DMA to load palette buffer */
+-
#ifdef CONFIG_PXA27x
-/*
@@ -775239,7 +1033617,7 @@
/* Camera Interface */
#define CICR0 __REG(0x50000000)
#define CICR1 __REG(0x50000004)
-@@ -1953,7 +1635,7 @@
+@@ -1953,7 +1439,7 @@
#define CICR0_FOM (1 << 0) /* FIFO-overrun mask */
#define CICR1_TBIT (1 << 31) /* Transparency bit */
@@ -775666,6 +1034044,306 @@
+ unsigned int nr_parts;
+};
+#endif /* __ASM_ARCH_PXA3XX_NAND_H */
+diff --git a/include/asm-arm/arch-pxa/pxafb.h b/include/asm-arm/arch-pxa/pxafb.h
+index ea2336a..bbd2239 100644
+--- a/include/asm-arm/arch-pxa/pxafb.h
++++ b/include/asm-arm/arch-pxa/pxafb.h
+@@ -13,6 +13,50 @@
+ */
+
+ #include <linux/fb.h>
++#include <asm/arch/regs-lcd.h>
++
++/*
++ * Supported LCD connections
++ *
++ * bits 0 - 3: for LCD panel type:
++ *
++ * STN - for passive matrix
++ * DSTN - for dual scan passive matrix
++ * TFT - for active matrix
++ *
++ * bits 4 - 9 : for bus width
++ * bits 10-17 : for AC Bias Pin Frequency
++ * bit 18 : for output enable polarity
++ * bit 19 : for pixel clock edge
++ */
++#define LCD_CONN_TYPE(_x) ((_x) & 0x0f)
++#define LCD_CONN_WIDTH(_x) (((_x) >> 4) & 0x1f)
++
++#define LCD_TYPE_UNKNOWN 0
++#define LCD_TYPE_MONO_STN 1
++#define LCD_TYPE_MONO_DSTN 2
++#define LCD_TYPE_COLOR_STN 3
++#define LCD_TYPE_COLOR_DSTN 4
++#define LCD_TYPE_COLOR_TFT 5
++#define LCD_TYPE_SMART_PANEL 6
++#define LCD_TYPE_MAX 7
++
++#define LCD_MONO_STN_4BPP ((4 << 4) | LCD_TYPE_MONO_STN)
++#define LCD_MONO_STN_8BPP ((8 << 4) | LCD_TYPE_MONO_STN)
++#define LCD_MONO_DSTN_8BPP ((8 << 4) | LCD_TYPE_MONO_DSTN)
++#define LCD_COLOR_STN_8BPP ((8 << 4) | LCD_TYPE_COLOR_STN)
++#define LCD_COLOR_DSTN_16BPP ((16 << 4) | LCD_TYPE_COLOR_DSTN)
++#define LCD_COLOR_TFT_16BPP ((16 << 4) | LCD_TYPE_COLOR_TFT)
++#define LCD_COLOR_TFT_18BPP ((18 << 4) | LCD_TYPE_COLOR_TFT)
++#define LCD_SMART_PANEL_8BPP ((8 << 4) | LCD_TYPE_SMART_PANEL)
++#define LCD_SMART_PANEL_16BPP ((16 << 4) | LCD_TYPE_SMART_PANEL)
++#define LCD_SMART_PANEL_18BPP ((18 << 4) | LCD_TYPE_SMART_PANEL)
++
++#define LCD_AC_BIAS_FREQ(x) (((x) & 0xff) << 10)
++#define LCD_BIAS_ACTIVE_HIGH (0 << 17)
++#define LCD_BIAS_ACTIVE_LOW (1 << 17)
++#define LCD_PCLK_EDGE_RISE (0 << 18)
++#define LCD_PCLK_EDGE_FALL (1 << 18)
+
+ /*
+ * This structure describes the machine which we are running on.
+@@ -26,6 +70,10 @@ struct pxafb_mode_info {
+ u_short yres;
+
+ u_char bpp;
++ u_int cmap_greyscale:1,
++ unused:31;
++
++ /* Parallel Mode Timing */
+ u_char hsync_len;
+ u_char left_margin;
+ u_char right_margin;
+@@ -35,14 +83,28 @@ struct pxafb_mode_info {
+ u_char lower_margin;
+ u_char sync;
+
+- u_int cmap_greyscale:1,
+- unused:31;
++ /* Smart Panel Mode Timing - see PXA27x DM 7.4.15.0.3 for details
++ * Note:
++ * 1. all parameters in nanosecond (ns)
++ * 2. a0cs{rd,wr}_set_hld are controlled by the same register bits
++ * in pxa27x and pxa3xx, initialize them to the same value or
++ * the larger one will be used
++ * 3. same to {rd,wr}_pulse_width
++ */
++ unsigned a0csrd_set_hld; /* A0 and CS Setup/Hold Time before/after L_FCLK_RD */
++ unsigned a0cswr_set_hld; /* A0 and CS Setup/Hold Time before/after L_PCLK_WR */
++ unsigned wr_pulse_width; /* L_PCLK_WR pulse width */
++ unsigned rd_pulse_width; /* L_FCLK_RD pulse width */
++ unsigned cmd_inh_time; /* Command Inhibit time between two writes */
++ unsigned op_hold_time; /* Output Hold time from L_FCLK_RD negation */
+ };
+
+ struct pxafb_mach_info {
+ struct pxafb_mode_info *modes;
+ unsigned int num_modes;
+
++ unsigned int lcd_conn;
++
+ u_int fixed_modes:1,
+ cmap_inverse:1,
+ cmap_static:1,
+@@ -78,8 +140,11 @@ struct pxafb_mach_info {
+ u_int lccr4;
+ void (*pxafb_backlight_power)(int);
+ void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
+-
++ void (*smart_update)(struct fb_info *);
+ };
+ void set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info);
+ void set_pxa_fb_parent(struct device *parent_dev);
+ unsigned long pxafb_get_hsync_time(struct device *dev);
++
++extern int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int);
++extern int pxafb_smart_flush(struct fb_info *info);
+diff --git a/include/asm-arm/arch-pxa/regs-lcd.h b/include/asm-arm/arch-pxa/regs-lcd.h
+new file mode 100644
+index 0000000..f762493
+--- /dev/null
++++ b/include/asm-arm/arch-pxa/regs-lcd.h
+@@ -0,0 +1,171 @@
++#ifndef __ASM_ARCH_REGS_LCD_H
++#define __ASM_ARCH_REGS_LCD_H
++/*
++ * LCD Controller Registers and Bits Definitions
++ */
++#define LCCR0 (0x000) /* LCD Controller Control Register 0 */
++#define LCCR1 (0x004) /* LCD Controller Control Register 1 */
++#define LCCR2 (0x008) /* LCD Controller Control Register 2 */
++#define LCCR3 (0x00C) /* LCD Controller Control Register 3 */
++#define LCCR4 (0x010) /* LCD Controller Control Register 4 */
++#define LCCR5 (0x014) /* LCD Controller Control Register 5 */
++#define DFBR0 (0x020) /* DMA Channel 0 Frame Branch Register */
++#define DFBR1 (0x024) /* DMA Channel 1 Frame Branch Register */
++#define LCSR (0x038) /* LCD Controller Status Register */
++#define LIIDR (0x03C) /* LCD Controller Interrupt ID Register */
++#define TMEDRGBR (0x040) /* TMED RGB Seed Register */
++#define TMEDCR (0x044) /* TMED Control Register */
++
++#define CMDCR (0x100) /* Command Control Register */
++#define PRSR (0x104) /* Panel Read Status Register */
++
++#define LCCR3_1BPP (0 << 24)
++#define LCCR3_2BPP (1 << 24)
++#define LCCR3_4BPP (2 << 24)
++#define LCCR3_8BPP (3 << 24)
++#define LCCR3_16BPP (4 << 24)
++
++#define LCCR3_PDFOR_0 (0 << 30)
++#define LCCR3_PDFOR_1 (1 << 30)
++#define LCCR3_PDFOR_2 (2 << 30)
++#define LCCR3_PDFOR_3 (3 << 30)
++
++#define LCCR4_PAL_FOR_0 (0 << 15)
++#define LCCR4_PAL_FOR_1 (1 << 15)
++#define LCCR4_PAL_FOR_2 (2 << 15)
++#define LCCR4_PAL_FOR_MASK (3 << 15)
++
++#define FDADR0 (0x200) /* DMA Channel 0 Frame Descriptor Address Register */
++#define FSADR0 (0x204) /* DMA Channel 0 Frame Source Address Register */
++#define FIDR0 (0x208) /* DMA Channel 0 Frame ID Register */
++#define LDCMD0 (0x20C) /* DMA Channel 0 Command Register */
++#define FDADR1 (0x210) /* DMA Channel 1 Frame Descriptor Address Register */
++#define FSADR1 (0x214) /* DMA Channel 1 Frame Source Address Register */
++#define FIDR1 (0x218) /* DMA Channel 1 Frame ID Register */
++#define LDCMD1 (0x21C) /* DMA Channel 1 Command Register */
++#define FDADR6 (0x260) /* DMA Channel 6 Frame Descriptor Address Register */
++#define FSADR6 (0x264) /* DMA Channel 6 Frame Source Address Register */
++#define FIDR6 (0x268) /* DMA Channel 6 Frame ID Register */
++
++#define LCCR0_ENB (1 << 0) /* LCD Controller enable */
++#define LCCR0_CMS (1 << 1) /* Color/Monochrome Display Select */
++#define LCCR0_Color (LCCR0_CMS*0) /* Color display */
++#define LCCR0_Mono (LCCR0_CMS*1) /* Monochrome display */
++#define LCCR0_SDS (1 << 2) /* Single/Dual Panel Display Select */
++#define LCCR0_Sngl (LCCR0_SDS*0) /* Single panel display */
++#define LCCR0_Dual (LCCR0_SDS*1) /* Dual panel display */
++
++#define LCCR0_LDM (1 << 3) /* LCD Disable Done Mask */
++#define LCCR0_SFM (1 << 4) /* Start of frame mask */
++#define LCCR0_IUM (1 << 5) /* Input FIFO underrun mask */
++#define LCCR0_EFM (1 << 6) /* End of Frame mask */
++#define LCCR0_PAS (1 << 7) /* Passive/Active display Select */
++#define LCCR0_Pas (LCCR0_PAS*0) /* Passive display (STN) */
++#define LCCR0_Act (LCCR0_PAS*1) /* Active display (TFT) */
++#define LCCR0_DPD (1 << 9) /* Double Pixel Data (monochrome) */
++#define LCCR0_4PixMono (LCCR0_DPD*0) /* 4-Pixel/clock Monochrome display */
++#define LCCR0_8PixMono (LCCR0_DPD*1) /* 8-Pixel/clock Monochrome display */
++#define LCCR0_DIS (1 << 10) /* LCD Disable */
++#define LCCR0_QDM (1 << 11) /* LCD Quick Disable mask */
++#define LCCR0_PDD (0xff << 12) /* Palette DMA request delay */
++#define LCCR0_PDD_S 12
++#define LCCR0_BM (1 << 20) /* Branch mask */
++#define LCCR0_OUM (1 << 21) /* Output FIFO underrun mask */
++#define LCCR0_LCDT (1 << 22) /* LCD panel type */
++#define LCCR0_RDSTM (1 << 23) /* Read status interrupt mask */
++#define LCCR0_CMDIM (1 << 24) /* Command interrupt mask */
++#define LCCR0_OUC (1 << 25) /* Overlay Underlay control bit */
++#define LCCR0_LDDALT (1 << 26) /* LDD alternate mapping control */
++
++#define LCCR1_PPL Fld (10, 0) /* Pixels Per Line - 1 */
++#define LCCR1_DisWdth(Pixel) (((Pixel) - 1) << FShft (LCCR1_PPL))
++
++#define LCCR1_HSW Fld (6, 10) /* Horizontal Synchronization */
++#define LCCR1_HorSnchWdth(Tpix) (((Tpix) - 1) << FShft (LCCR1_HSW))
++
++#define LCCR1_ELW Fld (8, 16) /* End-of-Line pixel clock Wait - 1 */
++#define LCCR1_EndLnDel(Tpix) (((Tpix) - 1) << FShft (LCCR1_ELW))
++
++#define LCCR1_BLW Fld (8, 24) /* Beginning-of-Line pixel clock */
++#define LCCR1_BegLnDel(Tpix) (((Tpix) - 1) << FShft (LCCR1_BLW))
++
++#define LCCR2_LPP Fld (10, 0) /* Line Per Panel - 1 */
++#define LCCR2_DisHght(Line) (((Line) - 1) << FShft (LCCR2_LPP))
++
++#define LCCR2_VSW Fld (6, 10) /* Vertical Synchronization pulse - 1 */
++#define LCCR2_VrtSnchWdth(Tln) (((Tln) - 1) << FShft (LCCR2_VSW))
++
++#define LCCR2_EFW Fld (8, 16) /* End-of-Frame line clock Wait */
++#define LCCR2_EndFrmDel(Tln) ((Tln) << FShft (LCCR2_EFW))
++
++#define LCCR2_BFW Fld (8, 24) /* Beginning-of-Frame line clock */
++#define LCCR2_BegFrmDel(Tln) ((Tln) << FShft (LCCR2_BFW))
++
++#define LCCR3_API (0xf << 16) /* AC Bias pin trasitions per interrupt */
++#define LCCR3_API_S 16
++#define LCCR3_VSP (1 << 20) /* vertical sync polarity */
++#define LCCR3_HSP (1 << 21) /* horizontal sync polarity */
++#define LCCR3_PCP (1 << 22) /* Pixel Clock Polarity (L_PCLK) */
++#define LCCR3_PixRsEdg (LCCR3_PCP*0) /* Pixel clock Rising-Edge */
++#define LCCR3_PixFlEdg (LCCR3_PCP*1) /* Pixel clock Falling-Edge */
++
++#define LCCR3_OEP (1 << 23) /* Output Enable Polarity */
++#define LCCR3_OutEnH (LCCR3_OEP*0) /* Output Enable active High */
++#define LCCR3_OutEnL (LCCR3_OEP*1) /* Output Enable active Low */
++
++#define LCCR3_DPC (1 << 27) /* double pixel clock mode */
++#define LCCR3_PCD Fld (8, 0) /* Pixel Clock Divisor */
++#define LCCR3_PixClkDiv(Div) (((Div) << FShft (LCCR3_PCD)))
++
++#define LCCR3_BPP Fld (3, 24) /* Bit Per Pixel */
++#define LCCR3_Bpp(Bpp) (((Bpp) << FShft (LCCR3_BPP)))
++
++#define LCCR3_ACB Fld (8, 8) /* AC Bias */
++#define LCCR3_Acb(Acb) (((Acb) << FShft (LCCR3_ACB)))
++
++#define LCCR3_HorSnchH (LCCR3_HSP*0) /* HSP Active High */
++#define LCCR3_HorSnchL (LCCR3_HSP*1) /* HSP Active Low */
++
++#define LCCR3_VrtSnchH (LCCR3_VSP*0) /* VSP Active High */
++#define LCCR3_VrtSnchL (LCCR3_VSP*1) /* VSP Active Low */
++
++#define LCCR5_IUM(x) (1 << ((x) + 23)) /* input underrun mask */
++#define LCCR5_BSM(x) (1 << ((x) + 15)) /* branch mask */
++#define LCCR5_EOFM(x) (1 << ((x) + 7)) /* end of frame mask */
++#define LCCR5_SOFM(x) (1 << ((x) + 0)) /* start of frame mask */
++
++#define LCSR_LDD (1 << 0) /* LCD Disable Done */
++#define LCSR_SOF (1 << 1) /* Start of frame */
++#define LCSR_BER (1 << 2) /* Bus error */
++#define LCSR_ABC (1 << 3) /* AC Bias count */
++#define LCSR_IUL (1 << 4) /* input FIFO underrun Lower panel */
++#define LCSR_IUU (1 << 5) /* input FIFO underrun Upper panel */
++#define LCSR_OU (1 << 6) /* output FIFO underrun */
++#define LCSR_QD (1 << 7) /* quick disable */
++#define LCSR_EOF (1 << 8) /* end of frame */
++#define LCSR_BS (1 << 9) /* branch status */
++#define LCSR_SINT (1 << 10) /* subsequent interrupt */
++#define LCSR_RD_ST (1 << 11) /* read status */
++#define LCSR_CMD_INT (1 << 12) /* command interrupt */
++
++#define LDCMD_PAL (1 << 26) /* instructs DMA to load palette buffer */
++
++/* smartpanel related */
++#define PRSR_DATA(x) ((x) & 0xff) /* Panel Data */
++#define PRSR_A0 (1 << 8) /* Read Data Source */
++#define PRSR_ST_OK (1 << 9) /* Status OK */
++#define PRSR_CON_NT (1 << 10) /* Continue to Next Command */
++
++#define SMART_CMD_A0 (0x1 << 8)
++#define SMART_CMD_READ_STATUS_REG (0x0 << 9)
++#define SMART_CMD_READ_FRAME_BUFFER ((0x0 << 9) | SMART_CMD_A0)
++#define SMART_CMD_WRITE_COMMAND (0x1 << 9)
++#define SMART_CMD_WRITE_DATA ((0x1 << 9) | SMART_CMD_A0)
++#define SMART_CMD_WRITE_FRAME ((0x2 << 9) | SMART_CMD_A0)
++#define SMART_CMD_WAIT_FOR_VSYNC (0x3 << 9)
++#define SMART_CMD_NOOP (0x4 << 9)
++#define SMART_CMD_INTERRUPT (0x5 << 9)
++
++#define SMART_CMD(x) (SMART_CMD_WRITE_COMMAND | ((x) & 0xff))
++#define SMART_DAT(x) (SMART_CMD_WRITE_DATA | ((x) & 0xff))
++#endif /* __ASM_ARCH_REGS_LCD_H */
+diff --git a/include/asm-arm/arch-pxa/system.h b/include/asm-arm/arch-pxa/system.h
+index 1d56a3e..a758a71 100644
+--- a/include/asm-arm/arch-pxa/system.h
++++ b/include/asm-arm/arch-pxa/system.h
+@@ -22,6 +22,8 @@ static inline void arch_idle(void)
+
+ static inline void arch_reset(char mode)
+ {
++ RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
++
+ if (mode == 's') {
+ /* Jump into ROM at address 0 */
+ cpu_reset(0);
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
@@ -776597,6 +1035275,26 @@
static inline unsigned gpio_to_irq(unsigned gpio)
{
+diff --git a/include/asm-arm/arch-sa1100/ide.h b/include/asm-arm/arch-sa1100/ide.h
+index 98b10bc..b14cbda 100644
+--- a/include/asm-arm/arch-sa1100/ide.h
++++ b/include/asm-arm/arch-sa1100/ide.h
+@@ -37,12 +37,12 @@ static inline void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+
+ memset(hw, 0, sizeof(*hw));
+
+- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+- hw->io_ports[i] = reg;
++ for (i = 0; i <= 7; i++) {
++ hw->io_ports_array[i] = reg;
+ reg += regincr;
+ }
+
+- hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
++ hw->io_ports.ctl_addr = ctrl_port;
+
+ if (irq)
+ *irq = 0;
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
@@ -776948,6 +1035646,46 @@
#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/page.h b/include/asm-arm/page.h
+index c86f68e..5c22b01 100644
+--- a/include/asm-arm/page.h
++++ b/include/asm-arm/page.h
+@@ -71,6 +71,14 @@
+ # endif
+ #endif
+
++#ifdef CONFIG_CPU_COPY_FEROCEON
++# ifdef _USER
++# define MULTI_USER 1
++# else
++# define _USER feroceon
++# endif
++#endif
++
+ #ifdef CONFIG_CPU_SA1100
+ # ifdef _USER
+ # define MULTI_USER 1
+diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
+index 5e01824..5571c13 100644
+--- a/include/asm-arm/pgtable.h
++++ b/include/asm-arm/pgtable.h
+@@ -260,6 +260,7 @@ extern struct page *empty_zero_page;
+ #define pte_write(pte) (pte_val(pte) & L_PTE_WRITE)
+ #define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY)
+ #define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG)
++#define pte_special(pte) (0)
+
+ /*
+ * The following only works if pte_present() is not true.
+@@ -280,6 +281,8 @@ PTE_BIT_FUNC(mkdirty, |= L_PTE_DIRTY);
+ PTE_BIT_FUNC(mkold, &= ~L_PTE_YOUNG);
+ PTE_BIT_FUNC(mkyoung, |= L_PTE_YOUNG);
+
++static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
++
+ /*
+ * Mark the prot value as uncacheable and unbufferable.
+ */
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
@@ -777338,6 +1036076,193 @@
struct restart_block restart_block;
};
+diff --git a/include/asm-arm/unaligned.h b/include/asm-arm/unaligned.h
+index 5db03cf..44593a8 100644
+--- a/include/asm-arm/unaligned.h
++++ b/include/asm-arm/unaligned.h
+@@ -1,171 +1,9 @@
+-#ifndef __ASM_ARM_UNALIGNED_H
+-#define __ASM_ARM_UNALIGNED_H
++#ifndef _ASM_ARM_UNALIGNED_H
++#define _ASM_ARM_UNALIGNED_H
+
+-#include <asm/types.h>
+-
+-extern int __bug_unaligned_x(const void *ptr);
+-
+-/*
+- * What is the most efficient way of loading/storing an unaligned value?
+- *
+- * That is the subject of this file. Efficiency here is defined as
+- * minimum code size with minimum register usage for the common cases.
+- * It is currently not believed that long longs are common, so we
+- * trade efficiency for the chars, shorts and longs against the long
+- * longs.
+- *
+- * Current stats with gcc 2.7.2.2 for these functions:
+- *
+- * ptrsize get: code regs put: code regs
+- * 1 1 1 1 2
+- * 2 3 2 3 2
+- * 4 7 3 7 3
+- * 8 20 6 16 6
+- *
+- * gcc 2.95.1 seems to code differently:
+- *
+- * ptrsize get: code regs put: code regs
+- * 1 1 1 1 2
+- * 2 3 2 3 2
+- * 4 7 4 7 4
+- * 8 19 8 15 6
+- *
+- * which may or may not be more efficient (depending upon whether
+- * you can afford the extra registers). Hopefully the gcc 2.95
+- * is inteligent enough to decide if it is better to use the
+- * extra register, but evidence so far seems to suggest otherwise.
+- *
+- * Unfortunately, gcc is not able to optimise the high word
+- * out of long long >> 32, or the low word from long long << 32
+- */
+-
+-#define __get_unaligned_2_le(__p) \
+- (unsigned int)(__p[0] | __p[1] << 8)
+-
+-#define __get_unaligned_2_be(__p) \
+- (unsigned int)(__p[0] << 8 | __p[1])
+-
+-#define __get_unaligned_4_le(__p) \
+- (unsigned int)(__p[0] | __p[1] << 8 | __p[2] << 16 | __p[3] << 24)
+-
+-#define __get_unaligned_4_be(__p) \
+- (unsigned int)(__p[0] << 24 | __p[1] << 16 | __p[2] << 8 | __p[3])
+-
+-#define __get_unaligned_8_le(__p) \
+- ((unsigned long long)__get_unaligned_4_le((__p+4)) << 32 | \
+- __get_unaligned_4_le(__p))
+-
+-#define __get_unaligned_8_be(__p) \
+- ((unsigned long long)__get_unaligned_4_be(__p) << 32 | \
+- __get_unaligned_4_be((__p+4)))
+-
+-#define __get_unaligned_le(ptr) \
+- ((__force typeof(*(ptr)))({ \
+- const __u8 *__p = (const __u8 *)(ptr); \
+- __builtin_choose_expr(sizeof(*(ptr)) == 1, *__p, \
+- __builtin_choose_expr(sizeof(*(ptr)) == 2, __get_unaligned_2_le(__p), \
+- __builtin_choose_expr(sizeof(*(ptr)) == 4, __get_unaligned_4_le(__p), \
+- __builtin_choose_expr(sizeof(*(ptr)) == 8, __get_unaligned_8_le(__p), \
+- (void)__bug_unaligned_x(__p))))); \
+- }))
+-
+-#define __get_unaligned_be(ptr) \
+- ((__force typeof(*(ptr)))({ \
+- const __u8 *__p = (const __u8 *)(ptr); \
+- __builtin_choose_expr(sizeof(*(ptr)) == 1, *__p, \
+- __builtin_choose_expr(sizeof(*(ptr)) == 2, __get_unaligned_2_be(__p), \
+- __builtin_choose_expr(sizeof(*(ptr)) == 4, __get_unaligned_4_be(__p), \
+- __builtin_choose_expr(sizeof(*(ptr)) == 8, __get_unaligned_8_be(__p), \
+- (void)__bug_unaligned_x(__p))))); \
+- }))
+-
+-
+-static inline void __put_unaligned_2_le(__u32 __v, register __u8 *__p)
+-{
+- *__p++ = __v;
+- *__p++ = __v >> 8;
+-}
+-
+-static inline void __put_unaligned_2_be(__u32 __v, register __u8 *__p)
+-{
+- *__p++ = __v >> 8;
+- *__p++ = __v;
+-}
+-
+-static inline void __put_unaligned_4_le(__u32 __v, register __u8 *__p)
+-{
+- __put_unaligned_2_le(__v >> 16, __p + 2);
+- __put_unaligned_2_le(__v, __p);
+-}
+-
+-static inline void __put_unaligned_4_be(__u32 __v, register __u8 *__p)
+-{
+- __put_unaligned_2_be(__v >> 16, __p);
+- __put_unaligned_2_be(__v, __p + 2);
+-}
+-
+-static inline void __put_unaligned_8_le(const unsigned long long __v, register __u8 *__p)
+-{
+- /*
+- * tradeoff: 8 bytes of stack for all unaligned puts (2
+- * instructions), or an extra register in the long long
+- * case - go for the extra register.
+- */
+- __put_unaligned_4_le(__v >> 32, __p+4);
+- __put_unaligned_4_le(__v, __p);
+-}
+-
+-static inline void __put_unaligned_8_be(const unsigned long long __v, register __u8 *__p)
+-{
+- /*
+- * tradeoff: 8 bytes of stack for all unaligned puts (2
+- * instructions), or an extra register in the long long
+- * case - go for the extra register.
+- */
+- __put_unaligned_4_be(__v >> 32, __p);
+- __put_unaligned_4_be(__v, __p+4);
+-}
+-
+-/*
+- * Try to store an unaligned value as efficiently as possible.
+- */
+-#define __put_unaligned_le(val,ptr) \
+- ({ \
+- (void)sizeof(*(ptr) = (val)); \
+- switch (sizeof(*(ptr))) { \
+- case 1: \
+- *(ptr) = (val); \
+- break; \
+- case 2: __put_unaligned_2_le((__force u16)(val),(__u8 *)(ptr)); \
+- break; \
+- case 4: __put_unaligned_4_le((__force u32)(val),(__u8 *)(ptr)); \
+- break; \
+- case 8: __put_unaligned_8_le((__force u64)(val),(__u8 *)(ptr)); \
+- break; \
+- default: __bug_unaligned_x(ptr); \
+- break; \
+- } \
+- (void) 0; \
+- })
+-
+-#define __put_unaligned_be(val,ptr) \
+- ({ \
+- (void)sizeof(*(ptr) = (val)); \
+- switch (sizeof(*(ptr))) { \
+- case 1: \
+- *(ptr) = (val); \
+- break; \
+- case 2: __put_unaligned_2_be((__force u16)(val),(__u8 *)(ptr)); \
+- break; \
+- case 4: __put_unaligned_4_be((__force u32)(val),(__u8 *)(ptr)); \
+- break; \
+- case 8: __put_unaligned_8_be((__force u64)(val),(__u8 *)(ptr)); \
+- break; \
+- default: __bug_unaligned_x(ptr); \
+- break; \
+- } \
+- (void) 0; \
+- })
++#include <linux/unaligned/le_byteshift.h>
++#include <linux/unaligned/be_byteshift.h>
++#include <linux/unaligned/generic.h>
+
+ /*
+ * Select endianness
+@@ -178,4 +16,4 @@ static inline void __put_unaligned_8_be(const unsigned long long __v, register _
+ #define put_unaligned __put_unaligned_be
+ #endif
+
+-#endif
++#endif /* _ASM_ARM_UNALIGNED_H */
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index 88e868b..7c57008 100644
--- a/include/asm-arm/unistd.h
@@ -777744,6 +1036669,32 @@
#define PAGE_MASK (~(PAGE_SIZE-1))
#define PTE_MASK PAGE_MASK
+diff --git a/include/asm-avr32/pgtable.h b/include/asm-avr32/pgtable.h
+index 3ae7b54..c0e5e29 100644
+--- a/include/asm-avr32/pgtable.h
++++ b/include/asm-avr32/pgtable.h
+@@ -212,6 +212,10 @@ static inline int pte_young(pte_t pte)
+ {
+ return pte_val(pte) & _PAGE_ACCESSED;
+ }
++static inline int pte_special(pte_t pte)
++{
++ return 0;
++}
+
+ /*
+ * The following only work if pte_present() is not true.
+@@ -252,6 +256,10 @@ static inline pte_t pte_mkyoung(pte_t pte)
+ set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED));
+ return pte;
+ }
++static inline pte_t pte_mkspecial(pte_t pte)
++{
++ return pte;
++}
+
+ #define pmd_none(x) (!pmd_val(x))
+ #define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
diff --git a/include/asm-avr32/semaphore.h b/include/asm-avr32/semaphore.h
index feaf1d4..d9b2034 100644
--- a/include/asm-avr32/semaphore.h
@@ -777877,6 +1036828,32 @@
+#define BASE_BAUD (1843200 / 16)
+
+#endif /* _ASM_SERIAL_H */
+diff --git a/include/asm-avr32/unaligned.h b/include/asm-avr32/unaligned.h
+index 36f5fd4..0418772 100644
+--- a/include/asm-avr32/unaligned.h
++++ b/include/asm-avr32/unaligned.h
+@@ -1,5 +1,5 @@
+-#ifndef __ASM_AVR32_UNALIGNED_H
+-#define __ASM_AVR32_UNALIGNED_H
++#ifndef _ASM_AVR32_UNALIGNED_H
++#define _ASM_AVR32_UNALIGNED_H
+
+ /*
+ * AVR32 can handle some unaligned accesses, depending on the
+@@ -11,6 +11,11 @@
+ * optimize word loads in general.
+ */
+
+-#include <asm-generic/unaligned.h>
++#include <linux/unaligned/be_struct.h>
++#include <linux/unaligned/le_byteshift.h>
++#include <linux/unaligned/generic.h>
+
+-#endif /* __ASM_AVR32_UNALIGNED_H */
++#define get_unaligned __get_unaligned_be
++#define put_unaligned __put_unaligned_be
++
++#endif /* _ASM_AVR32_UNALIGNED_H */
diff --git a/include/asm-avr32/xor.h b/include/asm-avr32/xor.h
new file mode 100644
index 0000000..99c87aa
@@ -781893,6 +1040870,26 @@
_err = __get_user_bad(); \
break; \
} \
+diff --git a/include/asm-blackfin/unaligned.h b/include/asm-blackfin/unaligned.h
+index 10081dc..fd8a1d6 100644
+--- a/include/asm-blackfin/unaligned.h
++++ b/include/asm-blackfin/unaligned.h
+@@ -1,6 +1,11 @@
+-#ifndef __BFIN_UNALIGNED_H
+-#define __BFIN_UNALIGNED_H
++#ifndef _ASM_BLACKFIN_UNALIGNED_H
++#define _ASM_BLACKFIN_UNALIGNED_H
+
+-#include <asm-generic/unaligned.h>
++#include <linux/unaligned/le_struct.h>
++#include <linux/unaligned/be_byteshift.h>
++#include <linux/unaligned/generic.h>
+
+-#endif /* __BFIN_UNALIGNED_H */
++#define get_unaligned __get_unaligned_le
++#define put_unaligned __put_unaligned_le
++
++#endif /* _ASM_BLACKFIN_UNALIGNED_H */
diff --git a/include/asm-blackfin/unistd.h b/include/asm-blackfin/unistd.h
index c18a399..42955d0 100644
--- a/include/asm-blackfin/unistd.h
@@ -781937,6 +1040934,66 @@
#define __NR_kexec_load 284
#define __NR_waitid 285
#define __NR_add_key 286
+diff --git a/include/asm-cris/arch-v10/ide.h b/include/asm-cris/arch-v10/ide.h
+index ea34e0d..5366e62 100644
+--- a/include/asm-cris/arch-v10/ide.h
++++ b/include/asm-cris/arch-v10/ide.h
+@@ -59,22 +59,19 @@ static inline void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, u
+ int i;
+
+ /* fill in ports for ATA addresses 0 to 7 */
+-
+- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+- hw->io_ports[i] = data_port |
++ for (i = 0; i <= 7; i++) {
++ hw->io_ports_array[i] = data_port |
+ IO_FIELD(R_ATA_CTRL_DATA, addr, i) |
+ IO_STATE(R_ATA_CTRL_DATA, cs0, active);
+ }
+
+ /* the IDE control register is at ATA address 6, with CS1 active instead of CS0 */
+-
+- hw->io_ports[IDE_CONTROL_OFFSET] = data_port |
++ hw->io_ports.ctl_addr = data_port |
+ IO_FIELD(R_ATA_CTRL_DATA, addr, 6) |
+ IO_STATE(R_ATA_CTRL_DATA, cs1, active);
+
+ /* whats this for ? */
+-
+- hw->io_ports[IDE_IRQ_OFFSET] = 0;
++ hw->io_ports.irq_addr = 0;
+ }
+
+ static inline void ide_init_default_hwifs(void)
+diff --git a/include/asm-cris/pgtable.h b/include/asm-cris/pgtable.h
+index a260757..829e7a7 100644
+--- a/include/asm-cris/pgtable.h
++++ b/include/asm-cris/pgtable.h
+@@ -115,6 +115,7 @@ static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WR
+ static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; }
+ static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+ static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
++static inline int pte_special(pte_t pte) { return 0; }
+
+ static inline pte_t pte_wrprotect(pte_t pte)
+ {
+@@ -162,6 +163,7 @@ static inline pte_t pte_mkyoung(pte_t pte)
+ }
+ return pte;
+ }
++static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+
+ /*
+ * Conversion functions: convert a page and protection to a page entry,
+@@ -229,7 +231,7 @@ static inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
+ #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+
+ /* to find an entry in a page-table-directory */
+-static inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
++static inline pgd_t * pgd_offset(const struct mm_struct *mm, unsigned long address)
+ {
+ return mm->pgd + pgd_index(address);
+ }
diff --git a/include/asm-cris/semaphore-helper.h b/include/asm-cris/semaphore-helper.h
deleted file mode 100644
index 27bfeca..0000000
@@ -782160,6 +1041217,54 @@
-
-#endif
+#include <linux/semaphore.h>
+diff --git a/include/asm-cris/unaligned.h b/include/asm-cris/unaligned.h
+index 7fbbb39..7b3f3fe 100644
+--- a/include/asm-cris/unaligned.h
++++ b/include/asm-cris/unaligned.h
+@@ -1,16 +1,13 @@
+-#ifndef __CRIS_UNALIGNED_H
+-#define __CRIS_UNALIGNED_H
++#ifndef _ASM_CRIS_UNALIGNED_H
++#define _ASM_CRIS_UNALIGNED_H
+
+ /*
+ * CRIS can do unaligned accesses itself.
+- *
+- * The strange macros are there to make sure these can't
+- * be misused in a way that makes them not work on other
+- * architectures where unaligned accesses aren't as simple.
+ */
++#include <linux/unaligned/access_ok.h>
++#include <linux/unaligned/generic.h>
+
+-#define get_unaligned(ptr) (*(ptr))
++#define get_unaligned __get_unaligned_le
++#define put_unaligned __put_unaligned_le
+
+-#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
+-
+-#endif
++#endif /* _ASM_CRIS_UNALIGNED_H */
+diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h
+index 4e21904..83c51ab 100644
+--- a/include/asm-frv/pgtable.h
++++ b/include/asm-frv/pgtable.h
+@@ -380,6 +380,7 @@ static inline pmd_t *pmd_offset(pud_t *dir, unsigned long address)
+ static inline int pte_dirty(pte_t pte) { return (pte).pte & _PAGE_DIRTY; }
+ static inline int pte_young(pte_t pte) { return (pte).pte & _PAGE_ACCESSED; }
+ static inline int pte_write(pte_t pte) { return !((pte).pte & _PAGE_WP); }
++static inline int pte_special(pte_t pte) { return 0; }
+
+ static inline pte_t pte_mkclean(pte_t pte) { (pte).pte &= ~_PAGE_DIRTY; return pte; }
+ static inline pte_t pte_mkold(pte_t pte) { (pte).pte &= ~_PAGE_ACCESSED; return pte; }
+@@ -387,6 +388,7 @@ static inline pte_t pte_wrprotect(pte_t pte) { (pte).pte |= _PAGE_WP; return pte
+ static inline pte_t pte_mkdirty(pte_t pte) { (pte).pte |= _PAGE_DIRTY; return pte; }
+ static inline pte_t pte_mkyoung(pte_t pte) { (pte).pte |= _PAGE_ACCESSED; return pte; }
+ static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte &= ~_PAGE_WP; return pte; }
++static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+
+ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
+ {
diff --git a/include/asm-frv/semaphore.h b/include/asm-frv/semaphore.h
index d7aaa19..d9b2034 100644
--- a/include/asm-frv/semaphore.h
@@ -782353,6 +1041458,461 @@
-#endif /* CONFIG_NUMA */
-
#endif /* _ASM_TOPOLOGY_H */
+diff --git a/include/asm-frv/unaligned.h b/include/asm-frv/unaligned.h
+index dc8e9c9..64ccc73 100644
+--- a/include/asm-frv/unaligned.h
++++ b/include/asm-frv/unaligned.h
+@@ -9,194 +9,14 @@
+ * 2 of the License, or (at your option) any later version.
+ */
+
+-#ifndef _ASM_UNALIGNED_H
+-#define _ASM_UNALIGNED_H
++#ifndef _ASM_FRV_UNALIGNED_H
++#define _ASM_FRV_UNALIGNED_H
+
++#include <linux/unaligned/le_byteshift.h>
++#include <linux/unaligned/be_byteshift.h>
++#include <linux/unaligned/generic.h>
+
+-/*
+- * Unaligned accesses on uClinux can't be performed in a fault handler - the
+- * CPU detects them as imprecise exceptions making this impossible.
+- *
+- * With the FR451, however, they are precise, and so we used to fix them up in
+- * the memory access fault handler. However, instruction bundling make this
+- * impractical. So, now we fall back to using memcpy.
+- */
+-#ifdef CONFIG_MMU
+-
+-/*
+- * The asm statement in the macros below is a way to get GCC to copy a
+- * value from one variable to another without having any clue it's
+- * actually doing so, so that it won't have any idea that the values
+- * in the two variables are related.
+- */
+-
+-#define get_unaligned(ptr) ({ \
+- typeof((*(ptr))) __x; \
+- void *__ptrcopy; \
+- asm("" : "=r" (__ptrcopy) : "0" (ptr)); \
+- memcpy(&__x, __ptrcopy, sizeof(*(ptr))); \
+- __x; \
+-})
+-
+-#define put_unaligned(val, ptr) ({ \
+- typeof((*(ptr))) __x = (val); \
+- void *__ptrcopy; \
+- asm("" : "=r" (__ptrcopy) : "0" (ptr)); \
+- memcpy(__ptrcopy, &__x, sizeof(*(ptr))); \
+-})
+-
+-extern int handle_misalignment(unsigned long esr0, unsigned long ear0, unsigned long epcr0);
+-
+-#else
+-
+-#define get_unaligned(ptr) \
+-({ \
+- typeof(*(ptr)) x; \
+- const char *__p = (const char *) (ptr); \
+- \
+- switch (sizeof(x)) { \
+- case 1: \
+- x = *(ptr); \
+- break; \
+- case 2: \
+- { \
+- uint8_t a; \
+- asm(" ldub%I2 %M2,%0 \n" \
+- " ldub%I3.p %M3,%1 \n" \
+- " slli %0,#8,%0 \n" \
+- " or %0,%1,%0 \n" \
+- : "=&r"(x), "=&r"(a) \
+- : "m"(__p[0]), "m"(__p[1]) \
+- ); \
+- break; \
+- } \
+- \
+- case 4: \
+- { \
+- uint8_t a; \
+- asm(" ldub%I2 %M2,%0 \n" \
+- " ldub%I3.p %M3,%1 \n" \
+- " slli %0,#8,%0 \n" \
+- " or %0,%1,%0 \n" \
+- " ldub%I4.p %M4,%1 \n" \
+- " slli %0,#8,%0 \n" \
+- " or %0,%1,%0 \n" \
+- " ldub%I5.p %M5,%1 \n" \
+- " slli %0,#8,%0 \n" \
+- " or %0,%1,%0 \n" \
+- : "=&r"(x), "=&r"(a) \
+- : "m"(__p[0]), "m"(__p[1]), "m"(__p[2]), "m"(__p[3]) \
+- ); \
+- break; \
+- } \
+- \
+- case 8: \
+- { \
+- union { uint64_t x; u32 y[2]; } z; \
+- uint8_t a; \
+- asm(" ldub%I3 %M3,%0 \n" \
+- " ldub%I4.p %M4,%2 \n" \
+- " slli %0,#8,%0 \n" \
+- " or %0,%2,%0 \n" \
+- " ldub%I5.p %M5,%2 \n" \
+- " slli %0,#8,%0 \n" \
+- " or %0,%2,%0 \n" \
+- " ldub%I6.p %M6,%2 \n" \
+- " slli %0,#8,%0 \n" \
+- " or %0,%2,%0 \n" \
+- " ldub%I7 %M7,%1 \n" \
+- " ldub%I8.p %M8,%2 \n" \
+- " slli %1,#8,%1 \n" \
+- " or %1,%2,%1 \n" \
+- " ldub%I9.p %M9,%2 \n" \
+- " slli %1,#8,%1 \n" \
+- " or %1,%2,%1 \n" \
+- " ldub%I10.p %M10,%2 \n" \
+- " slli %1,#8,%1 \n" \
+- " or %1,%2,%1 \n" \
+- : "=&r"(z.y[0]), "=&r"(z.y[1]), "=&r"(a) \
+- : "m"(__p[0]), "m"(__p[1]), "m"(__p[2]), "m"(__p[3]), \
+- "m"(__p[4]), "m"(__p[5]), "m"(__p[6]), "m"(__p[7]) \
+- ); \
+- x = z.x; \
+- break; \
+- } \
+- \
+- default: \
+- x = 0; \
+- BUG(); \
+- break; \
+- } \
+- \
+- x; \
+-})
+-
+-#define put_unaligned(val, ptr) \
+-do { \
+- char *__p = (char *) (ptr); \
+- int x; \
+- \
+- switch (sizeof(*ptr)) { \
+- case 2: \
+- { \
+- asm(" stb%I1.p %0,%M1 \n" \
+- " srli %0,#8,%0 \n" \
+- " stb%I2 %0,%M2 \n" \
+- : "=r"(x), "=m"(__p[1]), "=m"(__p[0]) \
+- : "0"(val) \
+- ); \
+- break; \
+- } \
+- \
+- case 4: \
+- { \
+- asm(" stb%I1.p %0,%M1 \n" \
+- " srli %0,#8,%0 \n" \
+- " stb%I2.p %0,%M2 \n" \
+- " srli %0,#8,%0 \n" \
+- " stb%I3.p %0,%M3 \n" \
+- " srli %0,#8,%0 \n" \
+- " stb%I4 %0,%M4 \n" \
+- : "=r"(x), "=m"(__p[3]), "=m"(__p[2]), "=m"(__p[1]), "=m"(__p[0]) \
+- : "0"(val) \
+- ); \
+- break; \
+- } \
+- \
+- case 8: \
+- { \
+- uint32_t __high, __low; \
+- __high = (uint64_t)val >> 32; \
+- __low = val & 0xffffffff; \
+- asm(" stb%I2.p %0,%M2 \n" \
+- " srli %0,#8,%0 \n" \
+- " stb%I3.p %0,%M3 \n" \
+- " srli %0,#8,%0 \n" \
+- " stb%I4.p %0,%M4 \n" \
+- " srli %0,#8,%0 \n" \
+- " stb%I5.p %0,%M5 \n" \
+- " srli %0,#8,%0 \n" \
+- " stb%I6.p %1,%M6 \n" \
+- " srli %1,#8,%1 \n" \
+- " stb%I7.p %1,%M7 \n" \
+- " srli %1,#8,%1 \n" \
+- " stb%I8.p %1,%M8 \n" \
+- " srli %1,#8,%1 \n" \
+- " stb%I9 %1,%M9 \n" \
+- : "=&r"(__low), "=&r"(__high), "=m"(__p[7]), "=m"(__p[6]), \
+- "=m"(__p[5]), "=m"(__p[4]), "=m"(__p[3]), "=m"(__p[2]), \
+- "=m"(__p[1]), "=m"(__p[0]) \
+- : "0"(__low), "1"(__high) \
+- ); \
+- break; \
+- } \
+- \
+- default: \
+- *(ptr) = (val); \
+- break; \
+- } \
+-} while(0)
+-
+-#endif
++#define get_unaligned __get_unaligned_be
++#define put_unaligned __put_unaligned_be
+
+-#endif
++#endif /* _ASM_FRV_UNALIGNED_H */
+diff --git a/include/asm-generic/bitops.h b/include/asm-generic/bitops.h
+index 15e6f25..c9f369c 100644
+--- a/include/asm-generic/bitops.h
++++ b/include/asm-generic/bitops.h
+@@ -17,8 +17,6 @@
+ #include <asm-generic/bitops/fls64.h>
+ #include <asm-generic/bitops/find.h>
+
+-#ifdef __KERNEL__
+-
+ #ifndef _LINUX_BITOPS_H
+ #error only <linux/bitops.h> can be included directly
+ #endif
+@@ -32,6 +30,4 @@
+ #include <asm-generic/bitops/ext2-atomic.h>
+ #include <asm-generic/bitops/minix.h>
+
+-#endif /* __KERNEL__ */
+-
+ #endif /* _ASM_GENERIC_BITOPS_H */
+diff --git a/include/asm-generic/bitops/__fls.h b/include/asm-generic/bitops/__fls.h
+new file mode 100644
+index 0000000..be24465
+--- /dev/null
++++ b/include/asm-generic/bitops/__fls.h
+@@ -0,0 +1,43 @@
++#ifndef _ASM_GENERIC_BITOPS___FLS_H_
++#define _ASM_GENERIC_BITOPS___FLS_H_
++
++#include <asm/types.h>
++
++/**
++ * __fls - find last (most-significant) set bit in a long word
++ * @word: the word to search
++ *
++ * Undefined if no set bit exists, so code should check against 0 first.
++ */
++static inline unsigned long __fls(unsigned long word)
++{
++ int num = BITS_PER_LONG - 1;
++
++#if BITS_PER_LONG == 64
++ if (!(word & (~0ul << 32))) {
++ num -= 32;
++ word <<= 32;
++ }
++#endif
++ if (!(word & (~0ul << (BITS_PER_LONG-16)))) {
++ num -= 16;
++ word <<= 16;
++ }
++ if (!(word & (~0ul << (BITS_PER_LONG-8)))) {
++ num -= 8;
++ word <<= 8;
++ }
++ if (!(word & (~0ul << (BITS_PER_LONG-4)))) {
++ num -= 4;
++ word <<= 4;
++ }
++ if (!(word & (~0ul << (BITS_PER_LONG-2)))) {
++ num -= 2;
++ word <<= 2;
++ }
++ if (!(word & (~0ul << (BITS_PER_LONG-1))))
++ num -= 1;
++ return num;
++}
++
++#endif /* _ASM_GENERIC_BITOPS___FLS_H_ */
+diff --git a/include/asm-generic/bitops/find.h b/include/asm-generic/bitops/find.h
+index 72a51e5..1914e97 100644
+--- a/include/asm-generic/bitops/find.h
++++ b/include/asm-generic/bitops/find.h
+@@ -1,11 +1,13 @@
+ #ifndef _ASM_GENERIC_BITOPS_FIND_H_
+ #define _ASM_GENERIC_BITOPS_FIND_H_
+
++#ifndef CONFIG_GENERIC_FIND_NEXT_BIT
+ extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
+ size, unsigned long offset);
+
+ extern unsigned long find_next_zero_bit(const unsigned long *addr, unsigned
+ long size, unsigned long offset);
++#endif
+
+ #define find_first_bit(addr, size) find_next_bit((addr), (size), 0)
+ #define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
+diff --git a/include/asm-generic/bitops/fls64.h b/include/asm-generic/bitops/fls64.h
+index 1b6b17c..86d403f 100644
+--- a/include/asm-generic/bitops/fls64.h
++++ b/include/asm-generic/bitops/fls64.h
+@@ -3,6 +3,18 @@
+
+ #include <asm/types.h>
+
++/**
++ * fls64 - find last set bit in a 64-bit word
++ * @x: the word to search
++ *
++ * This is defined in a similar way as the libc and compiler builtin
++ * ffsll, but returns the position of the most significant set bit.
++ *
++ * fls64(value) returns 0 if value is 0 or the position of the last
++ * set bit if value is nonzero. The last (most significant) bit is
++ * at position 64.
++ */
++#if BITS_PER_LONG == 32
+ static inline int fls64(__u64 x)
+ {
+ __u32 h = x >> 32;
+@@ -10,5 +22,15 @@ static inline int fls64(__u64 x)
+ return fls(h) + 32;
+ return fls(x);
+ }
++#elif BITS_PER_LONG == 64
++static inline int fls64(__u64 x)
++{
++ if (x == 0)
++ return 0;
++ return __fls(x) + 1;
++}
++#else
++#error BITS_PER_LONG not 32 or 64
++#endif
+
+ #endif /* _ASM_GENERIC_BITOPS_FLS64_H_ */
+diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h
+index f422df0..3c2344f 100644
+--- a/include/asm-generic/futex.h
++++ b/include/asm-generic/futex.h
+@@ -1,11 +1,9 @@
+ #ifndef _ASM_GENERIC_FUTEX_H
+ #define _ASM_GENERIC_FUTEX_H
+
+-#ifdef __KERNEL__
+-
+ #include <linux/futex.h>
++#include <linux/uaccess.h>
+ #include <asm/errno.h>
+-#include <asm/uaccess.h>
+
+ static inline int
+ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+@@ -56,4 +54,3 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+ }
+
+ #endif
+-#endif
+diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
+index f29a502..ecf675a 100644
+--- a/include/asm-generic/gpio.h
++++ b/include/asm-generic/gpio.h
+@@ -16,7 +16,14 @@
+ #define ARCH_NR_GPIOS 256
+ #endif
+
++static inline int gpio_is_valid(int number)
++{
++ /* only some non-negative numbers are valid */
++ return ((unsigned)number) < ARCH_NR_GPIOS;
++}
++
+ struct seq_file;
++struct module;
+
+ /**
+ * struct gpio_chip - abstract a GPIO controller
+@@ -48,6 +55,7 @@ struct seq_file;
+ */
+ struct gpio_chip {
+ char *label;
++ struct module *owner;
+
+ int (*direction_input)(struct gpio_chip *chip,
+ unsigned offset);
+@@ -66,6 +74,7 @@ struct gpio_chip {
+
+ extern const char *gpiochip_is_requested(struct gpio_chip *chip,
+ unsigned offset);
++extern int __init __must_check gpiochip_reserve(int start, int ngpio);
+
+ /* add/remove chips */
+ extern int gpiochip_add(struct gpio_chip *chip);
+@@ -97,6 +106,12 @@ extern int __gpio_cansleep(unsigned gpio);
+
+ #else
+
++static inline int gpio_is_valid(int number)
++{
++ /* only non-negative numbers are valid */
++ return number >= 0;
++}
++
+ /* platforms that don't directly support access to GPIOs through I2C, SPI,
+ * or other blocking infrastructure can use these wrappers.
+ */
+diff --git a/include/asm-generic/ioctl.h b/include/asm-generic/ioctl.h
+index cd02729..8641813 100644
+--- a/include/asm-generic/ioctl.h
++++ b/include/asm-generic/ioctl.h
+@@ -21,8 +21,19 @@
+ */
+ #define _IOC_NRBITS 8
+ #define _IOC_TYPEBITS 8
+-#define _IOC_SIZEBITS 14
+-#define _IOC_DIRBITS 2
++
++/*
++ * Let any architecture override either of the following before
++ * including this file.
++ */
++
++#ifndef _IOC_SIZEBITS
++# define _IOC_SIZEBITS 14
++#endif
++
++#ifndef _IOC_DIRBITS
++# define _IOC_DIRBITS 2
++#endif
+
+ #define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
+ #define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1)
+@@ -35,11 +46,21 @@
+ #define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+ /*
+- * Direction bits.
++ * Direction bits, which any architecture can choose to override
++ * before including this file.
+ */
+-#define _IOC_NONE 0U
+-#define _IOC_WRITE 1U
+-#define _IOC_READ 2U
++
++#ifndef _IOC_NONE
++# define _IOC_NONE 0U
++#endif
++
++#ifndef _IOC_WRITE
++# define _IOC_WRITE 1U
++#endif
++
++#ifndef _IOC_READ
++# define _IOC_READ 2U
++#endif
+
+ #define _IOC(dir,type,nr,size) \
+ (((dir) << _IOC_DIRSHIFT) | \
diff --git a/include/asm-generic/iomap.h b/include/asm-generic/iomap.h
index 67dc84c..76b0cc5 100644
--- a/include/asm-generic/iomap.h
@@ -782368,6 +1041928,63 @@
/* 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/memory_model.h b/include/asm-generic/memory_model.h
+index 52226e1..ae060c6 100644
+--- a/include/asm-generic/memory_model.h
++++ b/include/asm-generic/memory_model.h
+@@ -1,7 +1,6 @@
+ #ifndef __ASM_MEMORY_MODEL_H
+ #define __ASM_MEMORY_MODEL_H
+
+-#ifdef __KERNEL__
+ #ifndef __ASSEMBLY__
+
+ #if defined(CONFIG_FLATMEM)
+@@ -81,6 +80,5 @@ extern unsigned long page_to_pfn(struct page *page);
+ #endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */
+
+ #endif /* __ASSEMBLY__ */
+-#endif /* __KERNEL__ */
+
+ #endif
+diff --git a/include/asm-generic/page.h b/include/asm-generic/page.h
+index a96b5d9..14db733 100644
+--- a/include/asm-generic/page.h
++++ b/include/asm-generic/page.h
+@@ -1,7 +1,6 @@
+ #ifndef _ASM_GENERIC_PAGE_H
+ #define _ASM_GENERIC_PAGE_H
+
+-#ifdef __KERNEL__
+ #ifndef __ASSEMBLY__
+
+ #include <linux/compiler.h>
+@@ -21,6 +20,5 @@ static __inline__ __attribute_const__ int get_order(unsigned long size)
+ }
+
+ #endif /* __ASSEMBLY__ */
+-#endif /* __KERNEL__ */
+
+ #endif /* _ASM_GENERIC_PAGE_H */
+diff --git a/include/asm-generic/rtc.h b/include/asm-generic/rtc.h
+index dd1bed8..be4af00 100644
+--- a/include/asm-generic/rtc.h
++++ b/include/asm-generic/rtc.h
+@@ -12,8 +12,6 @@
+ #ifndef __ASM_RTC_H__
+ #define __ASM_RTC_H__
+
+-#ifdef __KERNEL__
+-
+ #include <linux/mc146818rtc.h>
+ #include <linux/rtc.h>
+ #include <linux/bcd.h>
+@@ -213,5 +211,4 @@ static inline int set_rtc_pll(struct rtc_pll_info *pll)
+ return -EINVAL;
+ }
+
+-#endif /* __KERNEL__ */
+ #endif /* __ASM_RTC_H__ */
diff --git a/include/asm-generic/topology.h b/include/asm-generic/topology.h
index 342a2a0..a6aea79 100644
--- a/include/asm-generic/topology.h
@@ -782398,6 +1042015,136 @@
+#endif
+
#endif /* _ASM_GENERIC_TOPOLOGY_H */
+diff --git a/include/asm-generic/unaligned.h b/include/asm-generic/unaligned.h
+deleted file mode 100644
+index 2fe1b2e..0000000
+--- a/include/asm-generic/unaligned.h
++++ /dev/null
+@@ -1,124 +0,0 @@
+-#ifndef _ASM_GENERIC_UNALIGNED_H_
+-#define _ASM_GENERIC_UNALIGNED_H_
+-
+-/*
+- * For the benefit of those who are trying to port Linux to another
+- * architecture, here are some C-language equivalents.
+- *
+- * This is based almost entirely upon Richard Henderson's
+- * asm-alpha/unaligned.h implementation. Some comments were
+- * taken from David Mosberger's asm-ia64/unaligned.h header.
+- */
+-
+-#include <linux/types.h>
+-
+-/*
+- * The main single-value unaligned transfer routines.
+- */
+-#define get_unaligned(ptr) \
+- __get_unaligned((ptr), sizeof(*(ptr)))
+-#define put_unaligned(x,ptr) \
+- ((void)sizeof(*(ptr)=(x)),\
+- __put_unaligned((__force __u64)(x), (ptr), sizeof(*(ptr))))
+-
+-/*
+- * This function doesn't actually exist. The idea is that when
+- * someone uses the macros below with an unsupported size (datatype),
+- * the linker will alert us to the problem via an unresolved reference
+- * error.
+- */
+-extern void bad_unaligned_access_length(void) __attribute__((noreturn));
+-
+-struct __una_u64 { __u64 x __attribute__((packed)); };
+-struct __una_u32 { __u32 x __attribute__((packed)); };
+-struct __una_u16 { __u16 x __attribute__((packed)); };
+-
+-/*
+- * Elemental unaligned loads
+- */
+-
+-static inline __u64 __uldq(const __u64 *addr)
+-{
+- const struct __una_u64 *ptr = (const struct __una_u64 *) addr;
+- return ptr->x;
+-}
+-
+-static inline __u32 __uldl(const __u32 *addr)
+-{
+- const struct __una_u32 *ptr = (const struct __una_u32 *) addr;
+- return ptr->x;
+-}
+-
+-static inline __u16 __uldw(const __u16 *addr)
+-{
+- const struct __una_u16 *ptr = (const struct __una_u16 *) addr;
+- return ptr->x;
+-}
+-
+-/*
+- * Elemental unaligned stores
+- */
+-
+-static inline void __ustq(__u64 val, __u64 *addr)
+-{
+- struct __una_u64 *ptr = (struct __una_u64 *) addr;
+- ptr->x = val;
+-}
+-
+-static inline void __ustl(__u32 val, __u32 *addr)
+-{
+- struct __una_u32 *ptr = (struct __una_u32 *) addr;
+- ptr->x = val;
+-}
+-
+-static inline void __ustw(__u16 val, __u16 *addr)
+-{
+- struct __una_u16 *ptr = (struct __una_u16 *) addr;
+- ptr->x = val;
+-}
+-
+-#define __get_unaligned(ptr, size) ({ \
+- const void *__gu_p = ptr; \
+- __u64 __val; \
+- switch (size) { \
+- case 1: \
+- __val = *(const __u8 *)__gu_p; \
+- break; \
+- case 2: \
+- __val = __uldw(__gu_p); \
+- break; \
+- case 4: \
+- __val = __uldl(__gu_p); \
+- break; \
+- case 8: \
+- __val = __uldq(__gu_p); \
+- break; \
+- default: \
+- bad_unaligned_access_length(); \
+- }; \
+- (__force __typeof__(*(ptr)))__val; \
+-})
+-
+-#define __put_unaligned(val, ptr, size) \
+-({ \
+- void *__gu_p = ptr; \
+- switch (size) { \
+- case 1: \
+- *(__u8 *)__gu_p = (__force __u8)val; \
+- break; \
+- case 2: \
+- __ustw((__force __u16)val, __gu_p); \
+- break; \
+- case 4: \
+- __ustl((__force __u32)val, __gu_p); \
+- break; \
+- case 8: \
+- __ustq(val, __gu_p); \
+- break; \
+- default: \
+- bad_unaligned_access_length(); \
+- }; \
+- (void)0; \
+-})
+-
+-#endif /* _ASM_GENERIC_UNALIGNED_H */
diff --git a/include/asm-h8300/semaphore-helper.h b/include/asm-h8300/semaphore-helper.h
deleted file mode 100644
index 4fea36b..0000000
@@ -782685,6 +1042432,34 @@
-
-#endif
+#include <linux/semaphore.h>
+diff --git a/include/asm-h8300/unaligned.h b/include/asm-h8300/unaligned.h
+index ffb67f4..b8d06c7 100644
+--- a/include/asm-h8300/unaligned.h
++++ b/include/asm-h8300/unaligned.h
+@@ -1,15 +1,11 @@
+-#ifndef __H8300_UNALIGNED_H
+-#define __H8300_UNALIGNED_H
++#ifndef _ASM_H8300_UNALIGNED_H
++#define _ASM_H8300_UNALIGNED_H
+
++#include <linux/unaligned/be_memmove.h>
++#include <linux/unaligned/le_byteshift.h>
++#include <linux/unaligned/generic.h>
+
+-/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
++#define get_unaligned __get_unaligned_be
++#define put_unaligned __put_unaligned_be
+
+-#define get_unaligned(ptr) \
+- ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
+-
+-#define put_unaligned(val, ptr) \
+- ({ __typeof__(*(ptr)) __tmp = (val); \
+- memmove((ptr), &__tmp, sizeof(*(ptr))); \
+- (void)0; })
+-
+-#endif
++#endif /* _ASM_H8300_UNALIGNED_H */
diff --git a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h
index cd1cc39..fcfad32 100644
--- a/include/asm-ia64/acpi.h
@@ -782744,6 +1042519,33 @@
#endif /*__KERNEL__*/
#endif /*_ASM_ACPI_H*/
+diff --git a/include/asm-ia64/bitops.h b/include/asm-ia64/bitops.h
+index 953d3df..e2ca800 100644
+--- a/include/asm-ia64/bitops.h
++++ b/include/asm-ia64/bitops.h
+@@ -407,6 +407,22 @@ fls (int t)
+ return ia64_popcnt(x);
+ }
+
++/*
++ * Find the last (most significant) bit set. Undefined for x==0.
++ * Bits are numbered from 0..63 (e.g., __fls(9) == 3).
++ */
++static inline unsigned long
++__fls (unsigned long x)
++{
++ x |= x >> 1;
++ x |= x >> 2;
++ x |= x >> 4;
++ x |= x >> 8;
++ x |= x >> 16;
++ x |= x >> 32;
++ return ia64_popcnt(x) - 1;
++}
++
+ #include <asm-generic/bitops/fls64.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
@@ -782859,6 +1042661,45 @@
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
#endif /* __IA64_CPUTIME_H */
+diff --git a/include/asm-ia64/dma-mapping.h b/include/asm-ia64/dma-mapping.h
+index f1735a2..9f0df9b 100644
+--- a/include/asm-ia64/dma-mapping.h
++++ b/include/asm-ia64/dma-mapping.h
+@@ -23,10 +23,30 @@ dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr,
+ {
+ dma_free_coherent(dev, size, cpu_addr, dma_handle);
+ }
+-#define dma_map_single platform_dma_map_single
+-#define dma_map_sg platform_dma_map_sg
+-#define dma_unmap_single platform_dma_unmap_single
+-#define dma_unmap_sg platform_dma_unmap_sg
++#define dma_map_single_attrs platform_dma_map_single_attrs
++static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
++ size_t size, int dir)
++{
++ return dma_map_single_attrs(dev, cpu_addr, size, dir, NULL);
++}
++#define dma_map_sg_attrs platform_dma_map_sg_attrs
++static inline int dma_map_sg(struct device *dev, struct scatterlist *sgl,
++ int nents, int dir)
++{
++ return dma_map_sg_attrs(dev, sgl, nents, dir, NULL);
++}
++#define dma_unmap_single_attrs platform_dma_unmap_single_attrs
++static inline void dma_unmap_single(struct device *dev, dma_addr_t cpu_addr,
++ size_t size, int dir)
++{
++ return dma_unmap_single_attrs(dev, cpu_addr, size, dir, NULL);
++}
++#define dma_unmap_sg_attrs platform_dma_unmap_sg_attrs
++static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
++ int nents, int dir)
++{
++ return dma_unmap_sg_attrs(dev, sgl, nents, dir, NULL);
++}
+ #define dma_sync_single_for_cpu platform_dma_sync_single_for_cpu
+ #define dma_sync_sg_for_cpu platform_dma_sync_sg_for_cpu
+ #define dma_sync_single_for_device platform_dma_sync_single_for_device
diff --git a/include/asm-ia64/elf.h b/include/asm-ia64/elf.h
index f8e83ec..5e0c1a6 100644
--- a/include/asm-ia64/elf.h
@@ -782915,6 +1042756,136 @@
#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/futex.h b/include/asm-ia64/futex.h
+index 8a98a26..c7f0f06 100644
+--- a/include/asm-ia64/futex.h
++++ b/include/asm-ia64/futex.h
+@@ -2,9 +2,9 @@
+ #define _ASM_FUTEX_H
+
+ #include <linux/futex.h>
++#include <linux/uaccess.h>
+ #include <asm/errno.h>
+ #include <asm/system.h>
+-#include <asm/uaccess.h>
+
+ #define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \
+ do { \
+diff --git a/include/asm-ia64/gcc_intrin.h b/include/asm-ia64/gcc_intrin.h
+index de2ed2c..2fe292c 100644
+--- a/include/asm-ia64/gcc_intrin.h
++++ b/include/asm-ia64/gcc_intrin.h
+@@ -21,6 +21,10 @@
+
+ #define ia64_invala_fr(regnum) asm volatile ("invala.e f%0" :: "i"(regnum))
+
++#define ia64_flushrs() asm volatile ("flushrs;;":::"memory")
++
++#define ia64_loadrs() asm volatile ("loadrs;;":::"memory")
++
+ extern void ia64_bad_param_for_setreg (void);
+ extern void ia64_bad_param_for_getreg (void);
+
+@@ -517,6 +521,14 @@ do { \
+ #define ia64_ptrd(addr, size) \
+ asm volatile ("ptr.d %0,%1" :: "r"(addr), "r"(size) : "memory")
+
++#define ia64_ttag(addr) \
++({ \
++ __u64 ia64_intri_res; \
++ asm volatile ("ttag %0=%1" : "=r"(ia64_intri_res) : "r" (addr)); \
++ ia64_intri_res; \
++})
++
++
+ /* Values for lfhint in ia64_lfetch and ia64_lfetch_fault */
+
+ #define ia64_lfhint_none 0
+diff --git a/include/asm-ia64/hugetlb.h b/include/asm-ia64/hugetlb.h
+new file mode 100644
+index 0000000..f28a970
+--- /dev/null
++++ b/include/asm-ia64/hugetlb.h
+@@ -0,0 +1,79 @@
++#ifndef _ASM_IA64_HUGETLB_H
++#define _ASM_IA64_HUGETLB_H
++
++#include <asm/page.h>
++
++
++void hugetlb_free_pgd_range(struct mmu_gather **tlb, unsigned long addr,
++ unsigned long end, unsigned long floor,
++ unsigned long ceiling);
++
++int prepare_hugepage_range(unsigned long addr, unsigned long len);
++
++static inline int is_hugepage_only_range(struct mm_struct *mm,
++ unsigned long addr,
++ unsigned long len)
++{
++ return (REGION_NUMBER(addr) == RGN_HPAGE ||
++ REGION_NUMBER((addr)+(len)-1) == RGN_HPAGE);
++}
++
++static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm)
++{
++}
++
++static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
++ pte_t *ptep, pte_t pte)
++{
++ set_pte_at(mm, addr, ptep, pte);
++}
++
++static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
++ unsigned long addr, pte_t *ptep)
++{
++ return ptep_get_and_clear(mm, addr, ptep);
++}
++
++static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
++ unsigned long addr, pte_t *ptep)
++{
++}
++
++static inline int huge_pte_none(pte_t pte)
++{
++ return pte_none(pte);
++}
++
++static inline pte_t huge_pte_wrprotect(pte_t pte)
++{
++ return pte_wrprotect(pte);
++}
++
++static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
++ unsigned long addr, pte_t *ptep)
++{
++ ptep_set_wrprotect(mm, addr, ptep);
++}
++
++static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
++ unsigned long addr, pte_t *ptep,
++ pte_t pte, int dirty)
++{
++ return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
++}
++
++static inline pte_t huge_ptep_get(pte_t *ptep)
++{
++ return *ptep;
++}
++
++static inline int arch_prepare_hugepage(struct page *page)
++{
++ return 0;
++}
++
++static inline void arch_release_hugepage(struct page *page)
++{
++}
++
++#endif /* _ASM_IA64_HUGETLB_H */
diff --git a/include/asm-ia64/ide.h b/include/asm-ia64/ide.h
index 1ccf238..8fa3f8c 100644
--- a/include/asm-ia64/ide.h
@@ -782980,9 +1042951,998 @@
+#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
+ /* Processor status register bits: */
+ #define IA64_PSR_BE_BIT 1
+ #define IA64_PSR_UP_BIT 2
+diff --git a/include/asm-ia64/kvm.h b/include/asm-ia64/kvm.h
+index 030d29b..eb2d355 100644
+--- a/include/asm-ia64/kvm.h
++++ b/include/asm-ia64/kvm.h
+@@ -1,6 +1,205 @@
+-#ifndef __LINUX_KVM_IA64_H
+-#define __LINUX_KVM_IA64_H
++#ifndef __ASM_IA64_KVM_H
++#define __ASM_IA64_KVM_H
+
+-/* ia64 does not support KVM */
++/*
++ * asm-ia64/kvm.h: kvm structure definitions for ia64
++ *
++ * Copyright (C) 2007 Xiantao Zhang <xiantao.zhang at intel.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You 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 <asm/types.h>
++#include <asm/fpu.h>
++
++#include <linux/ioctl.h>
++
++/* Architectural interrupt line count. */
++#define KVM_NR_INTERRUPTS 256
++
++#define KVM_IOAPIC_NUM_PINS 24
++
++struct kvm_ioapic_state {
++ __u64 base_address;
++ __u32 ioregsel;
++ __u32 id;
++ __u32 irr;
++ __u32 pad;
++ union {
++ __u64 bits;
++ struct {
++ __u8 vector;
++ __u8 delivery_mode:3;
++ __u8 dest_mode:1;
++ __u8 delivery_status:1;
++ __u8 polarity:1;
++ __u8 remote_irr:1;
++ __u8 trig_mode:1;
++ __u8 mask:1;
++ __u8 reserve:7;
++ __u8 reserved[4];
++ __u8 dest_id;
++ } fields;
++ } redirtbl[KVM_IOAPIC_NUM_PINS];
++};
++
++#define KVM_IRQCHIP_PIC_MASTER 0
++#define KVM_IRQCHIP_PIC_SLAVE 1
++#define KVM_IRQCHIP_IOAPIC 2
++
++#define KVM_CONTEXT_SIZE 8*1024
++
++union context {
++ /* 8K size */
++ char dummy[KVM_CONTEXT_SIZE];
++ struct {
++ unsigned long psr;
++ unsigned long pr;
++ unsigned long caller_unat;
++ unsigned long pad;
++ unsigned long gr[32];
++ unsigned long ar[128];
++ unsigned long br[8];
++ unsigned long cr[128];
++ unsigned long rr[8];
++ unsigned long ibr[8];
++ unsigned long dbr[8];
++ unsigned long pkr[8];
++ struct ia64_fpreg fr[128];
++ };
++};
++
++struct thash_data {
++ union {
++ struct {
++ unsigned long p : 1; /* 0 */
++ unsigned long rv1 : 1; /* 1 */
++ unsigned long ma : 3; /* 2-4 */
++ unsigned long a : 1; /* 5 */
++ unsigned long d : 1; /* 6 */
++ unsigned long pl : 2; /* 7-8 */
++ unsigned long ar : 3; /* 9-11 */
++ unsigned long ppn : 38; /* 12-49 */
++ unsigned long rv2 : 2; /* 50-51 */
++ unsigned long ed : 1; /* 52 */
++ unsigned long ig1 : 11; /* 53-63 */
++ };
++ struct {
++ unsigned long __rv1 : 53; /* 0-52 */
++ unsigned long contiguous : 1; /*53 */
++ unsigned long tc : 1; /* 54 TR or TC */
++ unsigned long cl : 1;
++ /* 55 I side or D side cache line */
++ unsigned long len : 4; /* 56-59 */
++ unsigned long io : 1; /* 60 entry is for io or not */
++ unsigned long nomap : 1;
++ /* 61 entry cann't be inserted into machine TLB.*/
++ unsigned long checked : 1;
++ /* 62 for VTLB/VHPT sanity check */
++ unsigned long invalid : 1;
++ /* 63 invalid entry */
++ };
++ unsigned long page_flags;
++ }; /* same for VHPT and TLB */
++
++ union {
++ struct {
++ unsigned long rv3 : 2;
++ unsigned long ps : 6;
++ unsigned long key : 24;
++ unsigned long rv4 : 32;
++ };
++ unsigned long itir;
++ };
++ union {
++ struct {
++ unsigned long ig2 : 12;
++ unsigned long vpn : 49;
++ unsigned long vrn : 3;
++ };
++ unsigned long ifa;
++ unsigned long vadr;
++ struct {
++ unsigned long tag : 63;
++ unsigned long ti : 1;
++ };
++ unsigned long etag;
++ };
++ union {
++ struct thash_data *next;
++ unsigned long rid;
++ unsigned long gpaddr;
++ };
++};
++
++#define NITRS 8
++#define NDTRS 8
++
++struct saved_vpd {
++ unsigned long vhpi;
++ unsigned long vgr[16];
++ unsigned long vbgr[16];
++ unsigned long vnat;
++ unsigned long vbnat;
++ unsigned long vcpuid[5];
++ unsigned long vpsr;
++ unsigned long vpr;
++ unsigned long vcr[128];
++};
++
++struct kvm_regs {
++ char *saved_guest;
++ char *saved_stack;
++ struct saved_vpd vpd;
++ /*Arch-regs*/
++ int mp_state;
++ unsigned long vmm_rr;
++ /* TR and TC. */
++ struct thash_data itrs[NITRS];
++ struct thash_data dtrs[NDTRS];
++ /* Bit is set if there is a tr/tc for the region. */
++ unsigned char itr_regions;
++ unsigned char dtr_regions;
++ unsigned char tc_regions;
++
++ char irq_check;
++ unsigned long saved_itc;
++ unsigned long itc_check;
++ unsigned long timer_check;
++ unsigned long timer_pending;
++ unsigned long last_itc;
++
++ unsigned long vrr[8];
++ unsigned long ibr[8];
++ unsigned long dbr[8];
++ unsigned long insvc[4]; /* Interrupt in service. */
++ unsigned long xtp;
++
++ unsigned long metaphysical_rr0; /* from kvm_arch (so is pinned) */
++ unsigned long metaphysical_rr4; /* from kvm_arch (so is pinned) */
++ unsigned long metaphysical_saved_rr0; /* from kvm_arch */
++ unsigned long metaphysical_saved_rr4; /* from kvm_arch */
++ unsigned long fp_psr; /*used for lazy float register */
++ unsigned long saved_gp;
++ /*for phycial emulation */
++};
++
++struct kvm_sregs {
++};
++
++struct kvm_fpu {
++};
+
+ #endif
+diff --git a/include/asm-ia64/kvm_host.h b/include/asm-ia64/kvm_host.h
+new file mode 100644
+index 0000000..c082c20
+--- /dev/null
++++ b/include/asm-ia64/kvm_host.h
+@@ -0,0 +1,524 @@
++/*
++ * kvm_host.h: used for kvm module, and hold ia64-specific sections.
++ *
++ * Copyright (C) 2007, Intel Corporation.
++ *
++ * Xiantao Zhang <xiantao.zhang at intel.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You 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_KVM_HOST_H
++#define __ASM_KVM_HOST_H
++
++
++#include <linux/types.h>
++#include <linux/mm.h>
++#include <linux/kvm.h>
++#include <linux/kvm_para.h>
++#include <linux/kvm_types.h>
++
++#include <asm/pal.h>
++#include <asm/sal.h>
++
++#define KVM_MAX_VCPUS 4
++#define KVM_MEMORY_SLOTS 32
++/* memory slots that does not exposed to userspace */
++#define KVM_PRIVATE_MEM_SLOTS 4
++
++
++/* define exit reasons from vmm to kvm*/
++#define EXIT_REASON_VM_PANIC 0
++#define EXIT_REASON_MMIO_INSTRUCTION 1
++#define EXIT_REASON_PAL_CALL 2
++#define EXIT_REASON_SAL_CALL 3
++#define EXIT_REASON_SWITCH_RR6 4
++#define EXIT_REASON_VM_DESTROY 5
++#define EXIT_REASON_EXTERNAL_INTERRUPT 6
++#define EXIT_REASON_IPI 7
++#define EXIT_REASON_PTC_G 8
++
++/*Define vmm address space and vm data space.*/
++#define KVM_VMM_SIZE (16UL<<20)
++#define KVM_VMM_SHIFT 24
++#define KVM_VMM_BASE 0xD000000000000000UL
++#define VMM_SIZE (8UL<<20)
++
++/*
++ * Define vm_buffer, used by PAL Services, base address.
++ * Note: vmbuffer is in the VMM-BLOCK, the size must be < 8M
++ */
++#define KVM_VM_BUFFER_BASE (KVM_VMM_BASE + VMM_SIZE)
++#define KVM_VM_BUFFER_SIZE (8UL<<20)
++
++/*Define Virtual machine data layout.*/
++#define KVM_VM_DATA_SHIFT 24
++#define KVM_VM_DATA_SIZE (1UL << KVM_VM_DATA_SHIFT)
++#define KVM_VM_DATA_BASE (KVM_VMM_BASE + KVM_VMM_SIZE)
++
++
++#define KVM_P2M_BASE KVM_VM_DATA_BASE
++#define KVM_P2M_OFS 0
++#define KVM_P2M_SIZE (8UL << 20)
++
++#define KVM_VHPT_BASE (KVM_P2M_BASE + KVM_P2M_SIZE)
++#define KVM_VHPT_OFS KVM_P2M_SIZE
++#define KVM_VHPT_BLOCK_SIZE (2UL << 20)
++#define VHPT_SHIFT 18
++#define VHPT_SIZE (1UL << VHPT_SHIFT)
++#define VHPT_NUM_ENTRIES (1<<(VHPT_SHIFT-5))
++
++#define KVM_VTLB_BASE (KVM_VHPT_BASE+KVM_VHPT_BLOCK_SIZE)
++#define KVM_VTLB_OFS (KVM_VHPT_OFS+KVM_VHPT_BLOCK_SIZE)
++#define KVM_VTLB_BLOCK_SIZE (1UL<<20)
++#define VTLB_SHIFT 17
++#define VTLB_SIZE (1UL<<VTLB_SHIFT)
++#define VTLB_NUM_ENTRIES (1<<(VTLB_SHIFT-5))
++
++#define KVM_VPD_BASE (KVM_VTLB_BASE+KVM_VTLB_BLOCK_SIZE)
++#define KVM_VPD_OFS (KVM_VTLB_OFS+KVM_VTLB_BLOCK_SIZE)
++#define KVM_VPD_BLOCK_SIZE (2UL<<20)
++#define VPD_SHIFT 16
++#define VPD_SIZE (1UL<<VPD_SHIFT)
++
++#define KVM_VCPU_BASE (KVM_VPD_BASE+KVM_VPD_BLOCK_SIZE)
++#define KVM_VCPU_OFS (KVM_VPD_OFS+KVM_VPD_BLOCK_SIZE)
++#define KVM_VCPU_BLOCK_SIZE (2UL<<20)
++#define VCPU_SHIFT 18
++#define VCPU_SIZE (1UL<<VCPU_SHIFT)
++#define MAX_VCPU_NUM KVM_VCPU_BLOCK_SIZE/VCPU_SIZE
++
++#define KVM_VM_BASE (KVM_VCPU_BASE+KVM_VCPU_BLOCK_SIZE)
++#define KVM_VM_OFS (KVM_VCPU_OFS+KVM_VCPU_BLOCK_SIZE)
++#define KVM_VM_BLOCK_SIZE (1UL<<19)
++
++#define KVM_MEM_DIRTY_LOG_BASE (KVM_VM_BASE+KVM_VM_BLOCK_SIZE)
++#define KVM_MEM_DIRTY_LOG_OFS (KVM_VM_OFS+KVM_VM_BLOCK_SIZE)
++#define KVM_MEM_DIRTY_LOG_SIZE (1UL<<19)
++
++/* Get vpd, vhpt, tlb, vcpu, base*/
++#define VPD_ADDR(n) (KVM_VPD_BASE+n*VPD_SIZE)
++#define VHPT_ADDR(n) (KVM_VHPT_BASE+n*VHPT_SIZE)
++#define VTLB_ADDR(n) (KVM_VTLB_BASE+n*VTLB_SIZE)
++#define VCPU_ADDR(n) (KVM_VCPU_BASE+n*VCPU_SIZE)
++
++/*IO section definitions*/
++#define IOREQ_READ 1
++#define IOREQ_WRITE 0
++
++#define STATE_IOREQ_NONE 0
++#define STATE_IOREQ_READY 1
++#define STATE_IOREQ_INPROCESS 2
++#define STATE_IORESP_READY 3
++
++/*Guest Physical address layout.*/
++#define GPFN_MEM (0UL << 60) /* Guest pfn is normal mem */
++#define GPFN_FRAME_BUFFER (1UL << 60) /* VGA framebuffer */
++#define GPFN_LOW_MMIO (2UL << 60) /* Low MMIO range */
++#define GPFN_PIB (3UL << 60) /* PIB base */
++#define GPFN_IOSAPIC (4UL << 60) /* IOSAPIC base */
++#define GPFN_LEGACY_IO (5UL << 60) /* Legacy I/O base */
++#define GPFN_GFW (6UL << 60) /* Guest Firmware */
++#define GPFN_HIGH_MMIO (7UL << 60) /* High MMIO range */
++
++#define GPFN_IO_MASK (7UL << 60) /* Guest pfn is I/O type */
++#define GPFN_INV_MASK (1UL << 63) /* Guest pfn is invalid */
++#define INVALID_MFN (~0UL)
++#define MEM_G (1UL << 30)
++#define MEM_M (1UL << 20)
++#define MMIO_START (3 * MEM_G)
++#define MMIO_SIZE (512 * MEM_M)
++#define VGA_IO_START 0xA0000UL
++#define VGA_IO_SIZE 0x20000
++#define LEGACY_IO_START (MMIO_START + MMIO_SIZE)
++#define LEGACY_IO_SIZE (64 * MEM_M)
++#define IO_SAPIC_START 0xfec00000UL
++#define IO_SAPIC_SIZE 0x100000
++#define PIB_START 0xfee00000UL
++#define PIB_SIZE 0x200000
++#define GFW_START (4 * MEM_G - 16 * MEM_M)
++#define GFW_SIZE (16 * MEM_M)
++
++/*Deliver mode, defined for ioapic.c*/
++#define dest_Fixed IOSAPIC_FIXED
++#define dest_LowestPrio IOSAPIC_LOWEST_PRIORITY
++
++#define NMI_VECTOR 2
++#define ExtINT_VECTOR 0
++#define NULL_VECTOR (-1)
++#define IA64_SPURIOUS_INT_VECTOR 0x0f
++
++#define VCPU_LID(v) (((u64)(v)->vcpu_id) << 24)
++
++/*
++ *Delivery mode
++ */
++#define SAPIC_DELIV_SHIFT 8
++#define SAPIC_FIXED 0x0
++#define SAPIC_LOWEST_PRIORITY 0x1
++#define SAPIC_PMI 0x2
++#define SAPIC_NMI 0x4
++#define SAPIC_INIT 0x5
++#define SAPIC_EXTINT 0x7
++
++/*
++ * vcpu->requests bit members for arch
++ */
++#define KVM_REQ_PTC_G 32
++#define KVM_REQ_RESUME 33
++
++#define KVM_PAGES_PER_HPAGE 1
++
++struct kvm;
++struct kvm_vcpu;
++struct kvm_guest_debug{
++};
++
++struct kvm_mmio_req {
++ uint64_t addr; /* physical address */
++ uint64_t size; /* size in bytes */
++ uint64_t data; /* data (or paddr of data) */
++ uint8_t state:4;
++ uint8_t dir:1; /* 1=read, 0=write */
++};
++
++/*Pal data struct */
++struct kvm_pal_call{
++ /*In area*/
++ uint64_t gr28;
++ uint64_t gr29;
++ uint64_t gr30;
++ uint64_t gr31;
++ /*Out area*/
++ struct ia64_pal_retval ret;
++};
++
++/* Sal data structure */
++struct kvm_sal_call{
++ /*In area*/
++ uint64_t in0;
++ uint64_t in1;
++ uint64_t in2;
++ uint64_t in3;
++ uint64_t in4;
++ uint64_t in5;
++ uint64_t in6;
++ uint64_t in7;
++ struct sal_ret_values ret;
++};
++
++/*Guest change rr6*/
++struct kvm_switch_rr6 {
++ uint64_t old_rr;
++ uint64_t new_rr;
++};
++
++union ia64_ipi_a{
++ unsigned long val;
++ struct {
++ unsigned long rv : 3;
++ unsigned long ir : 1;
++ unsigned long eid : 8;
++ unsigned long id : 8;
++ unsigned long ib_base : 44;
++ };
++};
++
++union ia64_ipi_d {
++ unsigned long val;
++ struct {
++ unsigned long vector : 8;
++ unsigned long dm : 3;
++ unsigned long ig : 53;
++ };
++};
++
++/*ipi check exit data*/
++struct kvm_ipi_data{
++ union ia64_ipi_a addr;
++ union ia64_ipi_d data;
++};
++
++/*global purge data*/
++struct kvm_ptc_g {
++ unsigned long vaddr;
++ unsigned long rr;
++ unsigned long ps;
++ struct kvm_vcpu *vcpu;
++};
++
++/*Exit control data */
++struct exit_ctl_data{
++ uint32_t exit_reason;
++ uint32_t vm_status;
++ union {
++ struct kvm_mmio_req ioreq;
++ struct kvm_pal_call pal_data;
++ struct kvm_sal_call sal_data;
++ struct kvm_switch_rr6 rr_data;
++ struct kvm_ipi_data ipi_data;
++ struct kvm_ptc_g ptc_g_data;
++ } u;
++};
++
++union pte_flags {
++ unsigned long val;
++ struct {
++ unsigned long p : 1; /*0 */
++ unsigned long : 1; /* 1 */
++ unsigned long ma : 3; /* 2-4 */
++ unsigned long a : 1; /* 5 */
++ unsigned long d : 1; /* 6 */
++ unsigned long pl : 2; /* 7-8 */
++ unsigned long ar : 3; /* 9-11 */
++ unsigned long ppn : 38; /* 12-49 */
++ unsigned long : 2; /* 50-51 */
++ unsigned long ed : 1; /* 52 */
++ };
++};
++
++union ia64_pta {
++ unsigned long val;
++ struct {
++ unsigned long ve : 1;
++ unsigned long reserved0 : 1;
++ unsigned long size : 6;
++ unsigned long vf : 1;
++ unsigned long reserved1 : 6;
++ unsigned long base : 49;
++ };
++};
++
++struct thash_cb {
++ /* THASH base information */
++ struct thash_data *hash; /* hash table pointer */
++ union ia64_pta pta;
++ int num;
++};
++
++struct kvm_vcpu_stat {
++};
++
++struct kvm_vcpu_arch {
++ int launched;
++ int last_exit;
++ int last_run_cpu;
++ int vmm_tr_slot;
++ int vm_tr_slot;
++
++#define KVM_MP_STATE_RUNNABLE 0
++#define KVM_MP_STATE_UNINITIALIZED 1
++#define KVM_MP_STATE_INIT_RECEIVED 2
++#define KVM_MP_STATE_HALTED 3
++ int mp_state;
++
++#define MAX_PTC_G_NUM 3
++ int ptc_g_count;
++ struct kvm_ptc_g ptc_g_data[MAX_PTC_G_NUM];
++
++ /*halt timer to wake up sleepy vcpus*/
++ struct hrtimer hlt_timer;
++ long ht_active;
++
++ struct kvm_lapic *apic; /* kernel irqchip context */
++ struct vpd *vpd;
++
++ /* Exit data for vmm_transition*/
++ struct exit_ctl_data exit_data;
++
++ cpumask_t cache_coherent_map;
++
++ unsigned long vmm_rr;
++ unsigned long host_rr6;
++ unsigned long psbits[8];
++ unsigned long cr_iipa;
++ unsigned long cr_isr;
++ unsigned long vsa_base;
++ unsigned long dirty_log_lock_pa;
++ unsigned long __gp;
++ /* TR and TC. */
++ struct thash_data itrs[NITRS];
++ struct thash_data dtrs[NDTRS];
++ /* Bit is set if there is a tr/tc for the region. */
++ unsigned char itr_regions;
++ unsigned char dtr_regions;
++ unsigned char tc_regions;
++ /* purge all */
++ unsigned long ptce_base;
++ unsigned long ptce_count[2];
++ unsigned long ptce_stride[2];
++ /* itc/itm */
++ unsigned long last_itc;
++ long itc_offset;
++ unsigned long itc_check;
++ unsigned long timer_check;
++ unsigned long timer_pending;
++
++ unsigned long vrr[8];
++ unsigned long ibr[8];
++ unsigned long dbr[8];
++ unsigned long insvc[4]; /* Interrupt in service. */
++ unsigned long xtp;
++
++ unsigned long metaphysical_rr0; /* from kvm_arch (so is pinned) */
++ unsigned long metaphysical_rr4; /* from kvm_arch (so is pinned) */
++ unsigned long metaphysical_saved_rr0; /* from kvm_arch */
++ unsigned long metaphysical_saved_rr4; /* from kvm_arch */
++ unsigned long fp_psr; /*used for lazy float register */
++ unsigned long saved_gp;
++ /*for phycial emulation */
++ int mode_flags;
++ struct thash_cb vtlb;
++ struct thash_cb vhpt;
++ char irq_check;
++ char irq_new_pending;
++
++ unsigned long opcode;
++ unsigned long cause;
++ union context host;
++ union context guest;
++};
++
++struct kvm_vm_stat {
++ u64 remote_tlb_flush;
++};
++
++struct kvm_sal_data {
++ unsigned long boot_ip;
++ unsigned long boot_gp;
++};
++
++struct kvm_arch {
++ unsigned long vm_base;
++ unsigned long metaphysical_rr0;
++ unsigned long metaphysical_rr4;
++ unsigned long vmm_init_rr;
++ unsigned long vhpt_base;
++ unsigned long vtlb_base;
++ unsigned long vpd_base;
++ spinlock_t dirty_log_lock;
++ struct kvm_ioapic *vioapic;
++ struct kvm_vm_stat stat;
++ struct kvm_sal_data rdv_sal_data;
++};
++
++union cpuid3_t {
++ u64 value;
++ struct {
++ u64 number : 8;
++ u64 revision : 8;
++ u64 model : 8;
++ u64 family : 8;
++ u64 archrev : 8;
++ u64 rv : 24;
++ };
++};
++
++struct kvm_pt_regs {
++ /* The following registers are saved by SAVE_MIN: */
++ unsigned long b6; /* scratch */
++ unsigned long b7; /* scratch */
++
++ unsigned long ar_csd; /* used by cmp8xchg16 (scratch) */
++ unsigned long ar_ssd; /* reserved for future use (scratch) */
++
++ unsigned long r8; /* scratch (return value register 0) */
++ unsigned long r9; /* scratch (return value register 1) */
++ unsigned long r10; /* scratch (return value register 2) */
++ unsigned long r11; /* scratch (return value register 3) */
++
++ unsigned long cr_ipsr; /* interrupted task's psr */
++ unsigned long cr_iip; /* interrupted task's instruction pointer */
++ unsigned long cr_ifs; /* interrupted task's function state */
++
++ unsigned long ar_unat; /* interrupted task's NaT register (preserved) */
++ unsigned long ar_pfs; /* prev function state */
++ unsigned long ar_rsc; /* RSE configuration */
++ /* The following two are valid only if cr_ipsr.cpl > 0: */
++ unsigned long ar_rnat; /* RSE NaT */
++ unsigned long ar_bspstore; /* RSE bspstore */
++
++ unsigned long pr; /* 64 predicate registers (1 bit each) */
++ unsigned long b0; /* return pointer (bp) */
++ unsigned long loadrs; /* size of dirty partition << 16 */
++
++ unsigned long r1; /* the gp pointer */
++ unsigned long r12; /* interrupted task's memory stack pointer */
++ unsigned long r13; /* thread pointer */
++
++ unsigned long ar_fpsr; /* floating point status (preserved) */
++ unsigned long r15; /* scratch */
++
++ /* The remaining registers are NOT saved for system calls. */
++ unsigned long r14; /* scratch */
++ unsigned long r2; /* scratch */
++ unsigned long r3; /* scratch */
++ unsigned long r16; /* scratch */
++ unsigned long r17; /* scratch */
++ unsigned long r18; /* scratch */
++ unsigned long r19; /* scratch */
++ unsigned long r20; /* scratch */
++ unsigned long r21; /* scratch */
++ unsigned long r22; /* scratch */
++ unsigned long r23; /* scratch */
++ unsigned long r24; /* scratch */
++ unsigned long r25; /* scratch */
++ unsigned long r26; /* scratch */
++ unsigned long r27; /* scratch */
++ unsigned long r28; /* scratch */
++ unsigned long r29; /* scratch */
++ unsigned long r30; /* scratch */
++ unsigned long r31; /* scratch */
++ unsigned long ar_ccv; /* compare/exchange value (scratch) */
++
++ /*
++ * Floating point registers that the kernel considers scratch:
++ */
++ struct ia64_fpreg f6; /* scratch */
++ struct ia64_fpreg f7; /* scratch */
++ struct ia64_fpreg f8; /* scratch */
++ struct ia64_fpreg f9; /* scratch */
++ struct ia64_fpreg f10; /* scratch */
++ struct ia64_fpreg f11; /* scratch */
++
++ unsigned long r4; /* preserved */
++ unsigned long r5; /* preserved */
++ unsigned long r6; /* preserved */
++ unsigned long r7; /* preserved */
++ unsigned long eml_unat; /* used for emulating instruction */
++ unsigned long pad0; /* alignment pad */
++};
++
++static inline struct kvm_pt_regs *vcpu_regs(struct kvm_vcpu *v)
++{
++ return (struct kvm_pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1;
++}
++
++typedef int kvm_vmm_entry(void);
++typedef void kvm_tramp_entry(union context *host, union context *guest);
++
++struct kvm_vmm_info{
++ struct module *module;
++ kvm_vmm_entry *vmm_entry;
++ kvm_tramp_entry *tramp_entry;
++ unsigned long vmm_ivt;
++};
++
++int kvm_highest_pending_irq(struct kvm_vcpu *vcpu);
++int kvm_emulate_halt(struct kvm_vcpu *vcpu);
++int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run);
++void kvm_sal_emul(struct kvm_vcpu *vcpu);
++
++#endif
+diff --git a/include/asm-ia64/kvm_para.h b/include/asm-ia64/kvm_para.h
+new file mode 100644
+index 0000000..9f9796b
+--- /dev/null
++++ b/include/asm-ia64/kvm_para.h
+@@ -0,0 +1,29 @@
++#ifndef __IA64_KVM_PARA_H
++#define __IA64_KVM_PARA_H
++
++/*
++ * asm-ia64/kvm_para.h
++ *
++ * Copyright (C) 2007 Xiantao Zhang <xiantao.zhang at intel.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You 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.
++ *
++ */
++
++static inline unsigned int kvm_arch_para_features(void)
++{
++ return 0;
++}
++
++#endif
+diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
+index c201a20..9f020eb 100644
+--- a/include/asm-ia64/machvec.h
++++ b/include/asm-ia64/machvec.h
+@@ -22,6 +22,7 @@ struct pci_bus;
+ struct task_struct;
+ struct pci_dev;
+ struct msi_desc;
++struct dma_attrs;
+
+ typedef void ia64_mv_setup_t (char **);
+ typedef void ia64_mv_cpu_init_t (void);
+@@ -56,6 +57,11 @@ typedef void ia64_mv_dma_sync_sg_for_device (struct device *, struct scatterlist
+ typedef int ia64_mv_dma_mapping_error (dma_addr_t dma_addr);
+ typedef int ia64_mv_dma_supported (struct device *, u64);
+
++typedef dma_addr_t ia64_mv_dma_map_single_attrs (struct device *, void *, size_t, int, struct dma_attrs *);
++typedef void ia64_mv_dma_unmap_single_attrs (struct device *, dma_addr_t, size_t, int, struct dma_attrs *);
++typedef int ia64_mv_dma_map_sg_attrs (struct device *, struct scatterlist *, int, int, struct dma_attrs *);
++typedef void ia64_mv_dma_unmap_sg_attrs (struct device *, struct scatterlist *, int, int, struct dma_attrs *);
++
+ /*
+ * WARNING: The legacy I/O space is _architected_. Platforms are
+ * expected to follow this architected model (see Section 10.7 in the
+@@ -136,10 +142,10 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *);
+ # define platform_dma_init ia64_mv.dma_init
+ # define platform_dma_alloc_coherent ia64_mv.dma_alloc_coherent
+ # define platform_dma_free_coherent ia64_mv.dma_free_coherent
+-# define platform_dma_map_single ia64_mv.dma_map_single
+-# define platform_dma_unmap_single ia64_mv.dma_unmap_single
+-# define platform_dma_map_sg ia64_mv.dma_map_sg
+-# define platform_dma_unmap_sg ia64_mv.dma_unmap_sg
++# define platform_dma_map_single_attrs ia64_mv.dma_map_single_attrs
++# define platform_dma_unmap_single_attrs ia64_mv.dma_unmap_single_attrs
++# define platform_dma_map_sg_attrs ia64_mv.dma_map_sg_attrs
++# define platform_dma_unmap_sg_attrs ia64_mv.dma_unmap_sg_attrs
+ # define platform_dma_sync_single_for_cpu ia64_mv.dma_sync_single_for_cpu
+ # define platform_dma_sync_sg_for_cpu ia64_mv.dma_sync_sg_for_cpu
+ # define platform_dma_sync_single_for_device ia64_mv.dma_sync_single_for_device
+@@ -190,10 +196,10 @@ struct ia64_machine_vector {
+ ia64_mv_dma_init *dma_init;
+ ia64_mv_dma_alloc_coherent *dma_alloc_coherent;
+ ia64_mv_dma_free_coherent *dma_free_coherent;
+- ia64_mv_dma_map_single *dma_map_single;
+- ia64_mv_dma_unmap_single *dma_unmap_single;
+- ia64_mv_dma_map_sg *dma_map_sg;
+- ia64_mv_dma_unmap_sg *dma_unmap_sg;
++ ia64_mv_dma_map_single_attrs *dma_map_single_attrs;
++ ia64_mv_dma_unmap_single_attrs *dma_unmap_single_attrs;
++ ia64_mv_dma_map_sg_attrs *dma_map_sg_attrs;
++ ia64_mv_dma_unmap_sg_attrs *dma_unmap_sg_attrs;
+ ia64_mv_dma_sync_single_for_cpu *dma_sync_single_for_cpu;
+ ia64_mv_dma_sync_sg_for_cpu *dma_sync_sg_for_cpu;
+ ia64_mv_dma_sync_single_for_device *dma_sync_single_for_device;
+@@ -240,10 +246,10 @@ struct ia64_machine_vector {
+ platform_dma_init, \
+ platform_dma_alloc_coherent, \
+ platform_dma_free_coherent, \
+- platform_dma_map_single, \
+- platform_dma_unmap_single, \
+- platform_dma_map_sg, \
+- platform_dma_unmap_sg, \
++ platform_dma_map_single_attrs, \
++ platform_dma_unmap_single_attrs, \
++ platform_dma_map_sg_attrs, \
++ platform_dma_unmap_sg_attrs, \
+ platform_dma_sync_single_for_cpu, \
+ platform_dma_sync_sg_for_cpu, \
+ platform_dma_sync_single_for_device, \
+@@ -292,9 +298,13 @@ extern ia64_mv_dma_init swiotlb_init;
+ extern ia64_mv_dma_alloc_coherent swiotlb_alloc_coherent;
+ extern ia64_mv_dma_free_coherent swiotlb_free_coherent;
+ extern ia64_mv_dma_map_single swiotlb_map_single;
++extern ia64_mv_dma_map_single_attrs swiotlb_map_single_attrs;
+ extern ia64_mv_dma_unmap_single swiotlb_unmap_single;
++extern ia64_mv_dma_unmap_single_attrs swiotlb_unmap_single_attrs;
+ extern ia64_mv_dma_map_sg swiotlb_map_sg;
++extern ia64_mv_dma_map_sg_attrs swiotlb_map_sg_attrs;
+ extern ia64_mv_dma_unmap_sg swiotlb_unmap_sg;
++extern ia64_mv_dma_unmap_sg_attrs swiotlb_unmap_sg_attrs;
+ extern ia64_mv_dma_sync_single_for_cpu swiotlb_sync_single_for_cpu;
+ extern ia64_mv_dma_sync_sg_for_cpu swiotlb_sync_sg_for_cpu;
+ extern ia64_mv_dma_sync_single_for_device swiotlb_sync_single_for_device;
+@@ -340,17 +350,17 @@ extern ia64_mv_dma_supported swiotlb_dma_supported;
+ #ifndef platform_dma_free_coherent
+ # define platform_dma_free_coherent swiotlb_free_coherent
+ #endif
+-#ifndef platform_dma_map_single
+-# define platform_dma_map_single swiotlb_map_single
++#ifndef platform_dma_map_single_attrs
++# define platform_dma_map_single_attrs swiotlb_map_single_attrs
+ #endif
+-#ifndef platform_dma_unmap_single
+-# define platform_dma_unmap_single swiotlb_unmap_single
++#ifndef platform_dma_unmap_single_attrs
++# define platform_dma_unmap_single_attrs swiotlb_unmap_single_attrs
+ #endif
+-#ifndef platform_dma_map_sg
+-# define platform_dma_map_sg swiotlb_map_sg
++#ifndef platform_dma_map_sg_attrs
++# define platform_dma_map_sg_attrs swiotlb_map_sg_attrs
+ #endif
+-#ifndef platform_dma_unmap_sg
+-# define platform_dma_unmap_sg swiotlb_unmap_sg
++#ifndef platform_dma_unmap_sg_attrs
++# define platform_dma_unmap_sg_attrs swiotlb_unmap_sg_attrs
+ #endif
+ #ifndef platform_dma_sync_single_for_cpu
+ # define platform_dma_sync_single_for_cpu swiotlb_sync_single_for_cpu
+diff --git a/include/asm-ia64/machvec_hpzx1.h b/include/asm-ia64/machvec_hpzx1.h
+index e90daf9..2f57f51 100644
+--- a/include/asm-ia64/machvec_hpzx1.h
++++ b/include/asm-ia64/machvec_hpzx1.h
+@@ -4,10 +4,10 @@
+ extern ia64_mv_setup_t dig_setup;
+ extern ia64_mv_dma_alloc_coherent sba_alloc_coherent;
+ extern ia64_mv_dma_free_coherent sba_free_coherent;
+-extern ia64_mv_dma_map_single sba_map_single;
+-extern ia64_mv_dma_unmap_single sba_unmap_single;
+-extern ia64_mv_dma_map_sg sba_map_sg;
+-extern ia64_mv_dma_unmap_sg sba_unmap_sg;
++extern ia64_mv_dma_map_single_attrs sba_map_single_attrs;
++extern ia64_mv_dma_unmap_single_attrs sba_unmap_single_attrs;
++extern ia64_mv_dma_map_sg_attrs sba_map_sg_attrs;
++extern ia64_mv_dma_unmap_sg_attrs sba_unmap_sg_attrs;
+ extern ia64_mv_dma_supported sba_dma_supported;
+ extern ia64_mv_dma_mapping_error sba_dma_mapping_error;
+
+@@ -23,10 +23,10 @@ extern ia64_mv_dma_mapping_error sba_dma_mapping_error;
+ #define platform_dma_init machvec_noop
+ #define platform_dma_alloc_coherent sba_alloc_coherent
+ #define platform_dma_free_coherent sba_free_coherent
+-#define platform_dma_map_single sba_map_single
+-#define platform_dma_unmap_single sba_unmap_single
+-#define platform_dma_map_sg sba_map_sg
+-#define platform_dma_unmap_sg sba_unmap_sg
++#define platform_dma_map_single_attrs sba_map_single_attrs
++#define platform_dma_unmap_single_attrs sba_unmap_single_attrs
++#define platform_dma_map_sg_attrs sba_map_sg_attrs
++#define platform_dma_unmap_sg_attrs sba_unmap_sg_attrs
+ #define platform_dma_sync_single_for_cpu machvec_dma_sync_single
+ #define platform_dma_sync_sg_for_cpu machvec_dma_sync_sg
+ #define platform_dma_sync_single_for_device machvec_dma_sync_single
+diff --git a/include/asm-ia64/machvec_hpzx1_swiotlb.h b/include/asm-ia64/machvec_hpzx1_swiotlb.h
+index f00a34a..a842cdd 100644
+--- a/include/asm-ia64/machvec_hpzx1_swiotlb.h
++++ b/include/asm-ia64/machvec_hpzx1_swiotlb.h
+@@ -4,10 +4,10 @@
+ extern ia64_mv_setup_t dig_setup;
+ extern ia64_mv_dma_alloc_coherent hwsw_alloc_coherent;
+ extern ia64_mv_dma_free_coherent hwsw_free_coherent;
+-extern ia64_mv_dma_map_single hwsw_map_single;
+-extern ia64_mv_dma_unmap_single hwsw_unmap_single;
+-extern ia64_mv_dma_map_sg hwsw_map_sg;
+-extern ia64_mv_dma_unmap_sg hwsw_unmap_sg;
++extern ia64_mv_dma_map_single_attrs hwsw_map_single_attrs;
++extern ia64_mv_dma_unmap_single_attrs hwsw_unmap_single_attrs;
++extern ia64_mv_dma_map_sg_attrs hwsw_map_sg_attrs;
++extern ia64_mv_dma_unmap_sg_attrs hwsw_unmap_sg_attrs;
+ extern ia64_mv_dma_supported hwsw_dma_supported;
+ extern ia64_mv_dma_mapping_error hwsw_dma_mapping_error;
+ extern ia64_mv_dma_sync_single_for_cpu hwsw_sync_single_for_cpu;
+@@ -28,10 +28,10 @@ extern ia64_mv_dma_sync_sg_for_device hwsw_sync_sg_for_device;
+ #define platform_dma_init machvec_noop
+ #define platform_dma_alloc_coherent hwsw_alloc_coherent
+ #define platform_dma_free_coherent hwsw_free_coherent
+-#define platform_dma_map_single hwsw_map_single
+-#define platform_dma_unmap_single hwsw_unmap_single
+-#define platform_dma_map_sg hwsw_map_sg
+-#define platform_dma_unmap_sg hwsw_unmap_sg
++#define platform_dma_map_single_attrs hwsw_map_single_attrs
++#define platform_dma_unmap_single_attrs hwsw_unmap_single_attrs
++#define platform_dma_map_sg_attrs hwsw_map_sg_attrs
++#define platform_dma_unmap_sg_attrs hwsw_unmap_sg_attrs
+ #define platform_dma_supported hwsw_dma_supported
+ #define platform_dma_mapping_error hwsw_dma_mapping_error
+ #define platform_dma_sync_single_for_cpu hwsw_sync_single_for_cpu
+diff --git a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h
+index 61439a7..781308e 100644
+--- a/include/asm-ia64/machvec_sn2.h
++++ b/include/asm-ia64/machvec_sn2.h
+@@ -57,10 +57,10 @@ extern ia64_mv_readl_t __sn_readl_relaxed;
+ extern ia64_mv_readq_t __sn_readq_relaxed;
+ extern ia64_mv_dma_alloc_coherent sn_dma_alloc_coherent;
+ extern ia64_mv_dma_free_coherent sn_dma_free_coherent;
+-extern ia64_mv_dma_map_single sn_dma_map_single;
+-extern ia64_mv_dma_unmap_single sn_dma_unmap_single;
+-extern ia64_mv_dma_map_sg sn_dma_map_sg;
+-extern ia64_mv_dma_unmap_sg sn_dma_unmap_sg;
++extern ia64_mv_dma_map_single_attrs sn_dma_map_single_attrs;
++extern ia64_mv_dma_unmap_single_attrs sn_dma_unmap_single_attrs;
++extern ia64_mv_dma_map_sg_attrs sn_dma_map_sg_attrs;
++extern ia64_mv_dma_unmap_sg_attrs sn_dma_unmap_sg_attrs;
+ extern ia64_mv_dma_sync_single_for_cpu sn_dma_sync_single_for_cpu;
+ extern ia64_mv_dma_sync_sg_for_cpu sn_dma_sync_sg_for_cpu;
+ extern ia64_mv_dma_sync_single_for_device sn_dma_sync_single_for_device;
+@@ -113,10 +113,10 @@ extern ia64_mv_pci_fixup_bus_t sn_pci_fixup_bus;
+ #define platform_dma_init machvec_noop
+ #define platform_dma_alloc_coherent sn_dma_alloc_coherent
+ #define platform_dma_free_coherent sn_dma_free_coherent
+-#define platform_dma_map_single sn_dma_map_single
+-#define platform_dma_unmap_single sn_dma_unmap_single
+-#define platform_dma_map_sg sn_dma_map_sg
+-#define platform_dma_unmap_sg sn_dma_unmap_sg
++#define platform_dma_map_single_attrs sn_dma_map_single_attrs
++#define platform_dma_unmap_single_attrs sn_dma_unmap_single_attrs
++#define platform_dma_map_sg_attrs sn_dma_map_sg_attrs
++#define platform_dma_unmap_sg_attrs sn_dma_unmap_sg_attrs
+ #define platform_dma_sync_single_for_cpu sn_dma_sync_single_for_cpu
+ #define platform_dma_sync_sg_for_cpu sn_dma_sync_sg_for_cpu
+ #define platform_dma_sync_single_for_device sn_dma_sync_single_for_device
diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h
index f1663aa..18a4321 100644
--- a/include/asm-ia64/mca.h
@@ -783029,6 +1043989,30 @@
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/page.h b/include/asm-ia64/page.h
+index 4999a6c..36f3932 100644
+--- a/include/asm-ia64/page.h
++++ b/include/asm-ia64/page.h
+@@ -54,9 +54,6 @@
+ # define HPAGE_MASK (~(HPAGE_SIZE - 1))
+
+ # define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+-# define ARCH_HAS_HUGEPAGE_ONLY_RANGE
+-# define ARCH_HAS_PREPARE_HUGEPAGE_RANGE
+-# define ARCH_HAS_HUGETLB_FREE_PGD_RANGE
+ #endif /* CONFIG_HUGETLB_PAGE */
+
+ #ifdef __ASSEMBLY__
+@@ -153,9 +150,6 @@ typedef union ia64_va {
+ # define htlbpage_to_page(x) (((unsigned long) REGION_NUMBER(x) << 61) \
+ | (REGION_OFFSET(x) >> (HPAGE_SHIFT-PAGE_SHIFT)))
+ # define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+-# define is_hugepage_only_range(mm, addr, len) \
+- (REGION_NUMBER(addr) == RGN_HPAGE || \
+- REGION_NUMBER((addr)+(len)-1) == RGN_HPAGE)
+ extern unsigned int hpage_shift;
+ #endif
+
diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h
index 8a695d3..67b0290 100644
--- a/include/asm-ia64/pal.h
@@ -783173,10 +1044157,27 @@
u64 piv_val;
struct {
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
-index e6204f1..ed70862 100644
+index e6204f1..7a9bff4 100644
--- a/include/asm-ia64/pgtable.h
+++ b/include/asm-ia64/pgtable.h
-@@ -371,7 +371,7 @@ pgd_index (unsigned long address)
+@@ -302,6 +302,8 @@ ia64_phys_addr_valid (unsigned long addr)
+ #define pte_dirty(pte) ((pte_val(pte) & _PAGE_D) != 0)
+ #define pte_young(pte) ((pte_val(pte) & _PAGE_A) != 0)
+ #define pte_file(pte) ((pte_val(pte) & _PAGE_FILE) != 0)
++#define pte_special(pte) 0
++
+ /*
+ * Note: we convert AR_RWX to AR_RX and AR_RW to AR_R by clearing the 2nd bit in the
+ * access rights:
+@@ -313,6 +315,7 @@ ia64_phys_addr_valid (unsigned long addr)
+ #define pte_mkclean(pte) (__pte(pte_val(pte) & ~_PAGE_D))
+ #define pte_mkdirty(pte) (__pte(pte_val(pte) | _PAGE_D))
+ #define pte_mkhuge(pte) (__pte(pte_val(pte)))
++#define pte_mkspecial(pte) (pte)
+
+ /*
+ * Because ia64's Icache and Dcache is not coherent (on a cpu), we need to
+@@ -371,7 +374,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*
@@ -783185,6 +1044186,80 @@
{
return mm->pgd + pgd_index(address);
}
+diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
+index 741f7ec..6aff126 100644
+--- a/include/asm-ia64/processor.h
++++ b/include/asm-ia64/processor.h
+@@ -119,6 +119,69 @@ struct ia64_psr {
+ __u64 reserved4 : 19;
+ };
+
++union ia64_isr {
++ __u64 val;
++ struct {
++ __u64 code : 16;
++ __u64 vector : 8;
++ __u64 reserved1 : 8;
++ __u64 x : 1;
++ __u64 w : 1;
++ __u64 r : 1;
++ __u64 na : 1;
++ __u64 sp : 1;
++ __u64 rs : 1;
++ __u64 ir : 1;
++ __u64 ni : 1;
++ __u64 so : 1;
++ __u64 ei : 2;
++ __u64 ed : 1;
++ __u64 reserved2 : 20;
++ };
++};
++
++union ia64_lid {
++ __u64 val;
++ struct {
++ __u64 rv : 16;
++ __u64 eid : 8;
++ __u64 id : 8;
++ __u64 ig : 32;
++ };
++};
++
++union ia64_tpr {
++ __u64 val;
++ struct {
++ __u64 ig0 : 4;
++ __u64 mic : 4;
++ __u64 rsv : 8;
++ __u64 mmi : 1;
++ __u64 ig1 : 47;
++ };
++};
++
++union ia64_itir {
++ __u64 val;
++ struct {
++ __u64 rv3 : 2; /* 0-1 */
++ __u64 ps : 6; /* 2-7 */
++ __u64 key : 24; /* 8-31 */
++ __u64 rv4 : 32; /* 32-63 */
++ };
++};
++
++union ia64_rr {
++ __u64 val;
++ struct {
++ __u64 ve : 1; /* enable hw walker */
++ __u64 reserved0: 1; /* reserved */
++ __u64 ps : 6; /* log page size */
++ __u64 rid : 24; /* region id */
++ __u64 reserved1: 32; /* reserved */
++ };
++};
++
+ /*
+ * CPU type, hardware bug flags, and per-CPU state. Frequently used
+ * state comes earlier:
diff --git a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h
index f4904db..89594b4 100644
--- a/include/asm-ia64/sal.h
@@ -785120,9 +1046195,42 @@
-#endif /* _ASM_IA64_SN_XPC_H */
-
diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h
-index 595112b..dff8128 100644
+index 595112b..26e250b 100644
--- a/include/asm-ia64/system.h
+++ b/include/asm-ia64/system.h
+@@ -146,23 +146,23 @@ do { \
+
+ # define local_irq_save(x) \
+ do { \
+- unsigned long psr; \
++ unsigned long __psr; \
+ \
+- __local_irq_save(psr); \
+- if (psr & IA64_PSR_I) \
++ __local_irq_save(__psr); \
++ if (__psr & IA64_PSR_I) \
+ __save_ip(); \
+- (x) = psr; \
++ (x) = __psr; \
+ } while (0)
+
+-# define local_irq_disable() do { unsigned long x; local_irq_save(x); } while (0)
++# define local_irq_disable() do { unsigned long __x; local_irq_save(__x); } while (0)
+
+ # define local_irq_restore(x) \
+ do { \
+- unsigned long old_psr, psr = (x); \
++ unsigned long __old_psr, __psr = (x); \
+ \
+- local_save_flags(old_psr); \
+- __local_irq_restore(psr); \
+- if ((old_psr & IA64_PSR_I) && !(psr & IA64_PSR_I)) \
++ local_save_flags(__old_psr); \
++ __local_irq_restore(__psr); \
++ if ((__old_psr & IA64_PSR_I) && !(__psr & IA64_PSR_I)) \
+ __save_ip(); \
+ } while (0)
+
@@ -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);
@@ -785157,7 +1046265,7 @@
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
-index 93d83cb..6da8069 100644
+index 93d83cb..f30e055 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -31,6 +31,12 @@ struct thread_info {
@@ -785191,6 +1046299,32 @@
#define end_of_stack(p) (unsigned long *)((void *)(p) + IA64_RBS_OFFSET)
#define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
+@@ -87,7 +101,6 @@ extern void tsk_clear_notify_resume(struct task_struct *tsk);
+ #define TIF_SYSCALL_TRACE 2 /* syscall trace active */
+ #define TIF_SYSCALL_AUDIT 3 /* syscall auditing active */
+ #define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */
+-#define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */
+ #define TIF_NOTIFY_RESUME 6 /* resumption notification requested */
+ #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
+ #define TIF_MEMDIE 17
+@@ -95,6 +108,7 @@ extern void tsk_clear_notify_resume(struct task_struct *tsk);
+ #define TIF_DB_DISABLED 19 /* debug trap disabled for fsyscall */
+ #define TIF_FREEZE 20 /* is freezing for suspend */
+ #define TIF_RESTORE_RSE 21 /* user RBS is newer than kernel RBS */
++#define TIF_RESTORE_SIGMASK 22 /* restore signal mask in do_signal() */
+
+ #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
+ #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
+@@ -112,8 +126,7 @@ extern void tsk_clear_notify_resume(struct task_struct *tsk);
+
+ /* "work to do on user-return" bits */
+ #define TIF_ALLWORK_MASK (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SYSCALL_AUDIT|\
+- _TIF_NEED_RESCHED| _TIF_SYSCALL_TRACE|\
+- _TIF_RESTORE_SIGMASK)
++ _TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE)
+ /* like TIF_ALLWORK_BITS but sans TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT */
+ #define TIF_WORK_MASK (TIF_ALLWORK_MASK&~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT))
+
diff --git a/include/asm-ia64/tlb.h b/include/asm-ia64/tlb.h
index 26edcb7..20d8a39 100644
--- a/include/asm-ia64/tlb.h
@@ -785241,7 +1046375,7 @@
/*
* 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
+index 2d67b72..32863b3 100644
--- a/include/asm-ia64/topology.h
+++ b/include/asm-ia64/topology.h
@@ -93,7 +93,7 @@ void build_cpu_to_node_map(void);
@@ -785253,10 +1046387,12 @@
.wake_idx = 1, \
.forkexec_idx = 1, \
.flags = SD_LOAD_BALANCE \
-@@ -116,6 +116,11 @@ void build_cpu_to_node_map(void);
+@@ -116,6 +116,13 @@ void build_cpu_to_node_map(void);
#define smt_capable() (smp_num_siblings > 1)
#endif
++extern void arch_fix_phys_package_id(int num, u32 slot);
++
+#define pcibus_to_cpumask(bus) (pcibus_to_node(bus) == -1 ? \
+ CPU_MASK_ALL : \
+ node_to_cpumask(pcibus_to_node(bus)) \
@@ -785265,6 +1046401,42 @@
#include <asm-generic/topology.h>
#endif /* _ASM_IA64_TOPOLOGY_H */
+diff --git a/include/asm-ia64/unaligned.h b/include/asm-ia64/unaligned.h
+index bb85598..7bddc7f 100644
+--- a/include/asm-ia64/unaligned.h
++++ b/include/asm-ia64/unaligned.h
+@@ -1,6 +1,11 @@
+ #ifndef _ASM_IA64_UNALIGNED_H
+ #define _ASM_IA64_UNALIGNED_H
+
+-#include <asm-generic/unaligned.h>
++#include <linux/unaligned/le_struct.h>
++#include <linux/unaligned/be_byteshift.h>
++#include <linux/unaligned/generic.h>
++
++#define get_unaligned __get_unaligned_le
++#define put_unaligned __put_unaligned_le
+
+ #endif /* _ASM_IA64_UNALIGNED_H */
+diff --git a/include/asm-ia64/uncached.h b/include/asm-ia64/uncached.h
+index b82d923..13d7e65 100644
+--- a/include/asm-ia64/uncached.h
++++ b/include/asm-ia64/uncached.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (C) 2001-2005 Silicon Graphics, Inc. All rights reserved.
++ * Copyright (C) 2001-2008 Silicon Graphics, Inc. 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
+@@ -8,5 +8,5 @@
+ * Prototypes for the uncached page allocator
+ */
+
+-extern unsigned long uncached_alloc_page(int nid);
+-extern void uncached_free_page(unsigned long);
++extern unsigned long uncached_alloc_page(int starting_nid, int n_pages);
++extern void uncached_free_page(unsigned long uc_addr, int n_pages);
diff --git a/include/asm-m32r/ide.h b/include/asm-m32r/ide.h
index 5d2044e..1e7f647 100644
--- a/include/asm-m32r/ide.h
@@ -785293,6 +1046465,34 @@
#include <asm-generic/ide_iops.h>
#endif /* __KERNEL__ */
+diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h
+index 8650538..e6359c5 100644
+--- a/include/asm-m32r/pgtable.h
++++ b/include/asm-m32r/pgtable.h
+@@ -214,6 +214,11 @@ static inline int pte_file(pte_t pte)
+ return pte_val(pte) & _PAGE_FILE;
+ }
+
++static inline int pte_special(pte_t pte)
++{
++ return 0;
++}
++
+ static inline pte_t pte_mkclean(pte_t pte)
+ {
+ pte_val(pte) &= ~_PAGE_DIRTY;
+@@ -250,6 +255,11 @@ static inline pte_t pte_mkwrite(pte_t pte)
+ return pte;
+ }
+
++static inline pte_t pte_mkspecial(pte_t pte)
++{
++ return pte;
++}
++
+ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
+ {
+ return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
diff --git a/include/asm-m32r/semaphore.h b/include/asm-m32r/semaphore.h
index b5bf95a..d9b2034 100644
--- a/include/asm-m32r/semaphore.h
@@ -785443,6 +1046643,63 @@
-
-#endif /* _ASM_M32R_SEMAPHORE_H */
+#include <linux/semaphore.h>
+diff --git a/include/asm-m32r/unaligned.h b/include/asm-m32r/unaligned.h
+index fccc180..377eb20 100644
+--- a/include/asm-m32r/unaligned.h
++++ b/include/asm-m32r/unaligned.h
+@@ -1,19 +1,18 @@
+ #ifndef _ASM_M32R_UNALIGNED_H
+ #define _ASM_M32R_UNALIGNED_H
+
+-/*
+- * For the benefit of those who are trying to port Linux to another
+- * architecture, here are some C-language equivalents.
+- */
+-
+-#include <asm/string.h>
+-
+-#define get_unaligned(ptr) \
+- ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
+-
+-#define put_unaligned(val, ptr) \
+- ({ __typeof__(*(ptr)) __tmp = (val); \
+- memmove((ptr), &__tmp, sizeof(*(ptr))); \
+- (void)0; })
++#if defined(__LITTLE_ENDIAN__)
++# include <linux/unaligned/le_memmove.h>
++# include <linux/unaligned/be_byteshift.h>
++# include <linux/unaligned/generic.h>
++# define get_unaligned __get_unaligned_le
++# define put_unaligned __put_unaligned_le
++#else
++# include <linux/unaligned/be_memmove.h>
++# include <linux/unaligned/le_byteshift.h>
++# include <linux/unaligned/generic.h>
++# define get_unaligned __get_unaligned_be
++# define put_unaligned __put_unaligned_be
++#endif
+
+ #endif /* _ASM_M32R_UNALIGNED_H */
+diff --git a/include/asm-m68k/motorola_pgtable.h b/include/asm-m68k/motorola_pgtable.h
+index 13135d4..8e9a8a7 100644
+--- a/include/asm-m68k/motorola_pgtable.h
++++ b/include/asm-m68k/motorola_pgtable.h
+@@ -168,6 +168,7 @@ static inline int pte_write(pte_t pte) { return !(pte_val(pte) & _PAGE_RONLY);
+ 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_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
++static inline int pte_special(pte_t pte) { return 0; }
+
+ static inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) |= _PAGE_RONLY; return pte; }
+ static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
+@@ -185,6 +186,7 @@ static inline pte_t pte_mkcache(pte_t pte)
+ pte_val(pte) = (pte_val(pte) & _CACHEMASK040) | m68k_supervisor_cachemode;
+ return pte;
+ }
++static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+
+ #define PAGE_DIR_OFFSET(tsk,address) pgd_offset((tsk),(address))
+
diff --git a/include/asm-m68k/semaphore-helper.h b/include/asm-m68k/semaphore-helper.h
deleted file mode 100644
index eef30ba..0000000
@@ -785760,6 +1047017,54 @@
-
-#endif
+#include <linux/semaphore.h>
+diff --git a/include/asm-m68k/sun3_pgtable.h b/include/asm-m68k/sun3_pgtable.h
+index b766fc2..f847ec7 100644
+--- a/include/asm-m68k/sun3_pgtable.h
++++ b/include/asm-m68k/sun3_pgtable.h
+@@ -169,6 +169,7 @@ static inline int pte_write(pte_t pte) { return pte_val(pte) & SUN3_PAGE_WRITEA
+ static inline int pte_dirty(pte_t pte) { return pte_val(pte) & SUN3_PAGE_MODIFIED; }
+ static inline int pte_young(pte_t pte) { return pte_val(pte) & SUN3_PAGE_ACCESSED; }
+ static inline int pte_file(pte_t pte) { return pte_val(pte) & SUN3_PAGE_ACCESSED; }
++static inline int pte_special(pte_t pte) { return 0; }
+
+ static inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~SUN3_PAGE_WRITEABLE; return pte; }
+ static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~SUN3_PAGE_MODIFIED; return pte; }
+@@ -181,6 +182,7 @@ static inline pte_t pte_mknocache(pte_t pte) { pte_val(pte) |= SUN3_PAGE_NOCACHE
+ //static inline pte_t pte_mkcache(pte_t pte) { pte_val(pte) &= SUN3_PAGE_NOCACHE; return pte; }
+ // until then, use:
+ static inline pte_t pte_mkcache(pte_t pte) { return pte; }
++static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+
+ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+ extern pgd_t kernel_pg_dir[PTRS_PER_PGD];
+diff --git a/include/asm-m68k/unaligned.h b/include/asm-m68k/unaligned.h
+index 804cb3f..77698f2 100644
+--- a/include/asm-m68k/unaligned.h
++++ b/include/asm-m68k/unaligned.h
+@@ -1,16 +1,13 @@
+-#ifndef __M68K_UNALIGNED_H
+-#define __M68K_UNALIGNED_H
++#ifndef _ASM_M68K_UNALIGNED_H
++#define _ASM_M68K_UNALIGNED_H
+
+ /*
+ * The m68k can do unaligned accesses itself.
+- *
+- * The strange macros are there to make sure these can't
+- * be misused in a way that makes them not work on other
+- * architectures where unaligned accesses aren't as simple.
+ */
++#include <linux/unaligned/access_ok.h>
++#include <linux/unaligned/generic.h>
+
+-#define get_unaligned(ptr) (*(ptr))
++#define get_unaligned __get_unaligned_be
++#define put_unaligned __put_unaligned_be
+
+-#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
+-
+-#endif
++#endif /* _ASM_M68K_UNALIGNED_H */
diff --git a/include/asm-m68knommu/semaphore-helper.h b/include/asm-m68knommu/semaphore-helper.h
deleted file mode 100644
index 43da7bc..0000000
@@ -786007,6 +1047312,1021 @@
-
-#endif
+#include <linux/semaphore.h>
+diff --git a/include/asm-m68knommu/unaligned.h b/include/asm-m68knommu/unaligned.h
+index 869e9dd..eb1ea4c 100644
+--- a/include/asm-m68knommu/unaligned.h
++++ b/include/asm-m68knommu/unaligned.h
+@@ -1,23 +1,25 @@
+-#ifndef __M68K_UNALIGNED_H
+-#define __M68K_UNALIGNED_H
++#ifndef _ASM_M68KNOMMU_UNALIGNED_H
++#define _ASM_M68KNOMMU_UNALIGNED_H
+
+
+ #ifdef CONFIG_COLDFIRE
++#include <linux/unaligned/be_struct.h>
++#include <linux/unaligned/le_byteshift.h>
++#include <linux/unaligned/generic.h>
+
+-#include <asm-generic/unaligned.h>
++#define get_unaligned __get_unaligned_be
++#define put_unaligned __put_unaligned_be
+
+ #else
+ /*
+ * The m68k can do unaligned accesses itself.
+- *
+- * The strange macros are there to make sure these can't
+- * be misused in a way that makes them not work on other
+- * architectures where unaligned accesses aren't as simple.
+ */
++#include <linux/unaligned/access_ok.h>
++#include <linux/unaligned/generic.h>
+
+-#define get_unaligned(ptr) (*(ptr))
+-#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
++#define get_unaligned __get_unaligned_be
++#define put_unaligned __put_unaligned_be
+
+ #endif
+
+-#endif
++#endif /* _ASM_M68KNOMMU_UNALIGNED_H */
+diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
+index ec75ce4..c2bd126 100644
+--- a/include/asm-mips/bitops.h
++++ b/include/asm-mips/bitops.h
+@@ -591,6 +591,11 @@ static inline int __ilog2(unsigned long x)
+ return 63 - lz;
+ }
+
++static inline unsigned long __fls(unsigned long x)
++{
++ return __ilog2(x);
++}
++
+ #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+
+ /*
+diff --git a/include/asm-mips/cmp.h b/include/asm-mips/cmp.h
+new file mode 100644
+index 0000000..89a73fb
+--- /dev/null
++++ b/include/asm-mips/cmp.h
+@@ -0,0 +1,18 @@
++#ifndef _ASM_CMP_H
++#define _ASM_CMP_H
++
++/*
++ * Definitions for CMP multitasking on MIPS cores
++ */
++struct task_struct;
++
++extern void cmp_smp_setup(void);
++extern void cmp_smp_finish(void);
++extern void cmp_boot_secondary(int cpu, struct task_struct *t);
++extern void cmp_init_secondary(void);
++extern void cmp_cpus_done(void);
++extern void cmp_prepare_cpus(unsigned int max_cpus);
++
++/* This is platform specific */
++extern void cmp_send_ipi(int cpu, unsigned int action);
++#endif /* _ASM_CMP_H */
+diff --git a/include/asm-mips/cpu.h b/include/asm-mips/cpu.h
+index bf5bbc7..1c35cac 100644
+--- a/include/asm-mips/cpu.h
++++ b/include/asm-mips/cpu.h
+@@ -29,7 +29,7 @@
+ #define PRID_COMP_ALCHEMY 0x030000
+ #define PRID_COMP_SIBYTE 0x040000
+ #define PRID_COMP_SANDCRAFT 0x050000
+-#define PRID_COMP_PHILIPS 0x060000
++#define PRID_COMP_NXP 0x060000
+ #define PRID_COMP_TOSHIBA 0x070000
+ #define PRID_COMP_LSI 0x080000
+ #define PRID_COMP_LEXRA 0x0b0000
+@@ -89,6 +89,7 @@
+ #define PRID_IMP_34K 0x9500
+ #define PRID_IMP_24KE 0x9600
+ #define PRID_IMP_74K 0x9700
++#define PRID_IMP_1004K 0x9900
+ #define PRID_IMP_LOONGSON1 0x4200
+ #define PRID_IMP_LOONGSON2 0x6300
+
+@@ -194,9 +195,9 @@ enum cpu_type_enum {
+ /*
+ * MIPS32 class processors
+ */
+- CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_74K, CPU_AU1000,
+- CPU_AU1100, CPU_AU1200, CPU_AU1210, CPU_AU1250, CPU_AU1500, CPU_AU1550,
+- CPU_PR4450, CPU_BCM3302, CPU_BCM4710,
++ CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K,
++ CPU_AU1000, CPU_AU1100, CPU_AU1200, CPU_AU1210, CPU_AU1250, CPU_AU1500,
++ CPU_AU1550, CPU_PR4450, CPU_BCM3302, CPU_BCM4710,
+
+ /*
+ * MIPS64 class processors
+diff --git a/include/asm-mips/dec/ioasic.h b/include/asm-mips/dec/ioasic.h
+index 486a5b0..98badd6 100644
+--- a/include/asm-mips/dec/ioasic.h
++++ b/include/asm-mips/dec/ioasic.h
+@@ -33,4 +33,6 @@ static inline u32 ioasic_read(unsigned int reg)
+
+ extern void init_ioasic_irqs(int base);
+
++extern void dec_ioasic_clocksource_init(void);
++
+ #endif /* __ASM_DEC_IOASIC_H */
+diff --git a/include/asm-mips/ds1287.h b/include/asm-mips/ds1287.h
+new file mode 100644
+index 0000000..ba1702e
+--- /dev/null
++++ b/include/asm-mips/ds1287.h
+@@ -0,0 +1,27 @@
++/*
++ * DS1287 timer functions.
++ *
++ * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa at tripeaks.co.jp>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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_DS1287_H
++#define __ASM_DS1287_H
++
++extern int ds1287_timer_state(void);
++extern void ds1287_set_base_clock(unsigned int clock);
++extern int ds1287_clockevent_init(int irq);
++
++#endif
+diff --git a/include/asm-mips/futex.h b/include/asm-mips/futex.h
+index 17f082c..b9cce90 100644
+--- a/include/asm-mips/futex.h
++++ b/include/asm-mips/futex.h
+@@ -11,9 +11,9 @@
+ #ifdef __KERNEL__
+
+ #include <linux/futex.h>
++#include <linux/uaccess.h>
+ #include <asm/barrier.h>
+ #include <asm/errno.h>
+-#include <asm/uaccess.h>
+ #include <asm/war.h>
+
+ #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
+diff --git a/include/asm-mips/gcmpregs.h b/include/asm-mips/gcmpregs.h
+new file mode 100644
+index 0000000..d74a8a4
+--- /dev/null
++++ b/include/asm-mips/gcmpregs.h
+@@ -0,0 +1,117 @@
++/*
++ * 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) 2000, 07 MIPS Technologies, Inc.
++ *
++ * Multiprocessor Subsystem Register Definitions
++ *
++ */
++#ifndef _ASM_GCMPREGS_H
++#define _ASM_GCMPREGS_H
++
++
++/* Offsets to major blocks within GCMP from GCMP base */
++#define GCMP_GCB_OFS 0x0000 /* Global Control Block */
++#define GCMP_CLCB_OFS 0x2000 /* Core Local Control Block */
++#define GCMP_COCB_OFS 0x4000 /* Core Other Control Block */
++#define GCMP_GDB_OFS 0x8000 /* Global Debug Block */
++
++/* Offsets to individual GCMP registers from GCMP base */
++#define GCMPOFS(block, tag, reg) (GCMP_##block##_OFS + GCMP_##tag##_##reg##_OFS)
++
++#define GCMPGCBOFS(reg) GCMPOFS(GCB, GCB, reg)
++#define GCMPCLCBOFS(reg) GCMPOFS(CLCB, CCB, reg)
++#define GCMPCOCBOFS(reg) GCMPOFS(COCB, CCB, reg)
++#define GCMPGDBOFS(reg) GCMPOFS(GDB, GDB, reg)
++
++/* GCMP register access */
++#define GCMPGCB(reg) REGP(_gcmp_base, GCMPGCBOFS(reg))
++#define GCMPCLCB(reg) REGP(_gcmp_base, GCMPCLCBOFS(reg))
++#define GCMPCOCB(reg) REGP(_gcmp_base, GCMPCOCBOFS(reg))
++#define GCMPGDB(reg) REGP(_gcmp_base, GCMPGDBOFS(reg))
++
++/* Mask generation */
++#define GCMPMSK(block, reg, bits) (MSK(bits)<<GCMP_##block##_##reg##_SHF)
++#define GCMPGCBMSK(reg, bits) GCMPMSK(GCB, reg, bits)
++#define GCMPCCBMSK(reg, bits) GCMPMSK(CCB, reg, bits)
++#define GCMPGDBMSK(reg, bits) GCMPMSK(GDB, reg, bits)
++
++/* GCB registers */
++#define GCMP_GCB_GC_OFS 0x0000 /* Global Config Register */
++#define GCMP_GCB_GC_NUMIOCU_SHF 8
++#define GCMP_GCB_GC_NUMIOCU_MSK GCMPGCBMSK(GC_NUMIOCU, 4)
++#define GCMP_GCB_GC_NUMCORES_SHF 0
++#define GCMP_GCB_GC_NUMCORES_MSK GCMPGCBMSK(GC_NUMCORES, 8)
++#define GCMP_GCB_GCMPB_OFS 0x0008 /* Global GCMP Base */
++#define GCMP_GCB_GCMPB_GCMPBASE_SHF 15
++#define GCMP_GCB_GCMPB_GCMPBASE_MSK GCMPGCBMSK(GCMPB_GCMPBASE, 17)
++#define GCMP_GCB_GCMPB_CMDEFTGT_SHF 0
++#define GCMP_GCB_GCMPB_CMDEFTGT_MSK GCMPGCBMSK(GCMPB_CMDEFTGT, 2)
++#define GCMP_GCB_GCMPB_CMDEFTGT_MEM 0
++#define GCMP_GCB_GCMPB_CMDEFTGT_MEM1 1
++#define GCMP_GCB_GCMPB_CMDEFTGT_IOCU1 2
++#define GCMP_GCB_GCMPB_CMDEFTGT_IOCU2 3
++#define GCMP_GCB_CCMC_OFS 0x0010 /* Global CM Control */
++#define GCMP_GCB_GCSRAP_OFS 0x0020 /* Global CSR Access Privilege */
++#define GCMP_GCB_GCSRAP_CMACCESS_SHF 0
++#define GCMP_GCB_GCSRAP_CMACCESS_MSK GCMPGCBMSK(GCSRAP_CMACCESS, 8)
++#define GCMP_GCB_GCMPREV_OFS 0x0030 /* GCMP Revision Register */
++#define GCMP_GCB_GCMEM_OFS 0x0040 /* Global CM Error Mask */
++#define GCMP_GCB_GCMEC_OFS 0x0048 /* Global CM Error Cause */
++#define GCMP_GCB_GMEC_ERROR_TYPE_SHF 27
++#define GCMP_GCB_GMEC_ERROR_TYPE_MSK GCMPGCBMSK(GMEC_ERROR_TYPE, 5)
++#define GCMP_GCB_GMEC_ERROR_INFO_SHF 0
++#define GCMP_GCB_GMEC_ERROR_INFO_MSK GCMPGCBMSK(GMEC_ERROR_INFO, 27)
++#define GCMP_GCB_GCMEA_OFS 0x0050 /* Global CM Error Address */
++#define GCMP_GCB_GCMEO_OFS 0x0058 /* Global CM Error Multiple */
++#define GCMP_GCB_GMEO_ERROR_2ND_SHF 0
++#define GCMP_GCB_GMEO_ERROR_2ND_MSK GCMPGCBMSK(GMEO_ERROR_2ND, 5)
++#define GCMP_GCB_GICBA_OFS 0x0080 /* Global Interrupt Controller Base Address */
++#define GCMP_GCB_GICBA_BASE_SHF 17
++#define GCMP_GCB_GICBA_BASE_MSK GCMPGCBMSK(GICBA_BASE, 15)
++#define GCMP_GCB_GICBA_EN_SHF 0
++#define GCMP_GCB_GICBA_EN_MSK GCMPGCBMSK(GICBA_EN, 1)
++
++/* GCB Regions */
++#define GCMP_GCB_CMxBASE_OFS(n) (0x0090+16*(n)) /* Global Region[0-3] Base Address */
++#define GCMP_GCB_CMxBASE_BASE_SHF 16
++#define GCMP_GCB_CMxBASE_BASE_MSK GCMPGCBMSK(CMxBASE_BASE, 16)
++#define GCMP_GCB_CMxMASK_OFS(n) (0x0098+16*(n)) /* Global Region[0-3] Address Mask */
++#define GCMP_GCB_CMxMASK_MASK_SHF 16
++#define GCMP_GCB_CMxMASK_MASK_MSK GCMPGCBMSK(CMxMASK_MASK, 16)
++#define GCMP_GCB_CMxMASK_CMREGTGT_SHF 0
++#define GCMP_GCB_CMxMASK_CMREGTGT_MSK GCMPGCBMSK(CMxMASK_CMREGTGT, 2)
++#define GCMP_GCB_CMxMASK_CMREGTGT_MEM 0
++#define GCMP_GCB_CMxMASK_CMREGTGT_MEM1 1
++#define GCMP_GCB_CMxMASK_CMREGTGT_IOCU1 2
++#define GCMP_GCB_CMxMASK_CMREGTGT_IOCU2 3
++
++
++/* Core local/Core other control block registers */
++#define GCMP_CCB_RESETR_OFS 0x0000 /* Reset Release */
++#define GCMP_CCB_RESETR_INRESET_SHF 0
++#define GCMP_CCB_RESETR_INRESET_MSK GCMPCCBMSK(RESETR_INRESET, 16)
++#define GCMP_CCB_COHCTL_OFS 0x0008 /* Coherence Control */
++#define GCMP_CCB_COHCTL_DOMAIN_SHF 0
++#define GCMP_CCB_COHCTL_DOMAIN_MSK GCMPCCBMSK(COHCTL_DOMAIN, 8)
++#define GCMP_CCB_CFG_OFS 0x0010 /* Config */
++#define GCMP_CCB_CFG_IOCUTYPE_SHF 10
++#define GCMP_CCB_CFG_IOCUTYPE_MSK GCMPCCBMSK(CFG_IOCUTYPE, 2)
++#define GCMP_CCB_CFG_IOCUTYPE_CPU 0
++#define GCMP_CCB_CFG_IOCUTYPE_NCIOCU 1
++#define GCMP_CCB_CFG_IOCUTYPE_CIOCU 2
++#define GCMP_CCB_CFG_NUMVPE_SHF 0
++#define GCMP_CCB_CFG_NUMVPE_MSK GCMPCCBMSK(CFG_NUMVPE, 10)
++#define GCMP_CCB_OTHER_OFS 0x0018 /* Other Address */
++#define GCMP_CCB_OTHER_CORENUM_SHF 16
++#define GCMP_CCB_OTHER_CORENUM_MSK GCMPCCBMSK(OTHER_CORENUM, 16)
++#define GCMP_CCB_RESETBASE_OFS 0x0020 /* Reset Exception Base */
++#define GCMP_CCB_RESETBASE_BEV_SHF 12
++#define GCMP_CCB_RESETBASE_BEV_MSK GCMPCCBMSK(RESETBASE_BEV, 20)
++#define GCMP_CCB_ID_OFS 0x0028 /* Identification */
++#define GCMP_CCB_DINTGROUP_OFS 0x0030 /* DINT Group Participate */
++#define GCMP_CCB_DBGGROUP_OFS 0x0100 /* DebugBreak Group */
++
++#endif /* _ASM_GCMPREGS_H */
+diff --git a/include/asm-mips/gic.h b/include/asm-mips/gic.h
+new file mode 100644
+index 0000000..01b2f92
+--- /dev/null
++++ b/include/asm-mips/gic.h
+@@ -0,0 +1,487 @@
++/*
++ * 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) 2000, 07 MIPS Technologies, Inc.
++ *
++ * GIC Register Definitions
++ *
++ */
++#ifndef _ASM_GICREGS_H
++#define _ASM_GICREGS_H
++
++#undef GICISBYTELITTLEENDIAN
++#define GICISWORDLITTLEENDIAN
++
++/* Constants */
++#define GIC_POL_POS 1
++#define GIC_POL_NEG 0
++#define GIC_TRIG_EDGE 1
++#define GIC_TRIG_LEVEL 0
++
++#define GIC_NUM_INTRS 32
++
++#define MSK(n) ((1 << (n)) - 1)
++#define REG32(addr) (*(volatile unsigned int *) (addr))
++#define REG(base, offs) REG32((unsigned int)(base) + offs##_##OFS)
++#define REGP(base, phys) REG32((unsigned int)(base) + (phys))
++
++/* Accessors */
++#define GIC_REG(segment, offset) \
++ REG32(_gic_base + segment##_##SECTION_OFS + offset##_##OFS)
++#define GIC_REG_ADDR(segment, offset) \
++ REG32(_gic_base + segment##_##SECTION_OFS + offset)
++
++#define GIC_ABS_REG(segment, offset) \
++ (_gic_base + segment##_##SECTION_OFS + offset##_##OFS)
++#define GIC_REG_ABS_ADDR(segment, offset) \
++ (_gic_base + segment##_##SECTION_OFS + offset)
++
++#ifdef GICISBYTELITTLEENDIAN
++#define GICREAD(reg, data) (data) = (reg), (data) = le32_to_cpu(data)
++#define GICWRITE(reg, data) (reg) = cpu_to_le32(data)
++#define GICBIS(reg, bits) \
++ ({unsigned int data; \
++ GICREAD(reg, data); \
++ data |= bits; \
++ GICWRITE(reg, data); \
++ })
++
++#else
++#define GICREAD(reg, data) (data) = (reg)
++#define GICWRITE(reg, data) (reg) = (data)
++#define GICBIS(reg, bits) (reg) |= (bits)
++#endif
++
++
++/* GIC Address Space */
++#define SHARED_SECTION_OFS 0x0000
++#define SHARED_SECTION_SIZE 0x8000
++#define VPE_LOCAL_SECTION_OFS 0x8000
++#define VPE_LOCAL_SECTION_SIZE 0x4000
++#define VPE_OTHER_SECTION_OFS 0xc000
++#define VPE_OTHER_SECTION_SIZE 0x4000
++#define USM_VISIBLE_SECTION_OFS 0x10000
++#define USM_VISIBLE_SECTION_SIZE 0x10000
++
++/* Register Map for Shared Section */
++#if defined(CONFIG_CPU_LITTLE_ENDIAN) || defined(GICISWORDLITTLEENDIAN)
++
++#define GIC_SH_CONFIG_OFS 0x0000
++
++/* Shared Global Counter */
++#define GIC_SH_COUNTER_31_00_OFS 0x0010
++#define GIC_SH_COUNTER_63_32_OFS 0x0014
++
++/* Interrupt Polarity */
++#define GIC_SH_POL_31_0_OFS 0x0100
++#define GIC_SH_POL_63_32_OFS 0x0104
++#define GIC_SH_POL_95_64_OFS 0x0108
++#define GIC_SH_POL_127_96_OFS 0x010c
++#define GIC_SH_POL_159_128_OFS 0x0110
++#define GIC_SH_POL_191_160_OFS 0x0114
++#define GIC_SH_POL_223_192_OFS 0x0118
++#define GIC_SH_POL_255_224_OFS 0x011c
++
++/* Edge/Level Triggering */
++#define GIC_SH_TRIG_31_0_OFS 0x0180
++#define GIC_SH_TRIG_63_32_OFS 0x0184
++#define GIC_SH_TRIG_95_64_OFS 0x0188
++#define GIC_SH_TRIG_127_96_OFS 0x018c
++#define GIC_SH_TRIG_159_128_OFS 0x0190
++#define GIC_SH_TRIG_191_160_OFS 0x0194
++#define GIC_SH_TRIG_223_192_OFS 0x0198
++#define GIC_SH_TRIG_255_224_OFS 0x019c
++
++/* Dual Edge Triggering */
++#define GIC_SH_DUAL_31_0_OFS 0x0200
++#define GIC_SH_DUAL_63_32_OFS 0x0204
++#define GIC_SH_DUAL_95_64_OFS 0x0208
++#define GIC_SH_DUAL_127_96_OFS 0x020c
++#define GIC_SH_DUAL_159_128_OFS 0x0210
++#define GIC_SH_DUAL_191_160_OFS 0x0214
++#define GIC_SH_DUAL_223_192_OFS 0x0218
++#define GIC_SH_DUAL_255_224_OFS 0x021c
++
++/* Set/Clear corresponding bit in Edge Detect Register */
++#define GIC_SH_WEDGE_OFS 0x0280
++
++/* Reset Mask - Disables Interrupt */
++#define GIC_SH_RMASK_31_0_OFS 0x0300
++#define GIC_SH_RMASK_63_32_OFS 0x0304
++#define GIC_SH_RMASK_95_64_OFS 0x0308
++#define GIC_SH_RMASK_127_96_OFS 0x030c
++#define GIC_SH_RMASK_159_128_OFS 0x0310
++#define GIC_SH_RMASK_191_160_OFS 0x0314
++#define GIC_SH_RMASK_223_192_OFS 0x0318
++#define GIC_SH_RMASK_255_224_OFS 0x031c
++
++/* Set Mask (WO) - Enables Interrupt */
++#define GIC_SH_SMASK_31_0_OFS 0x0380
++#define GIC_SH_SMASK_63_32_OFS 0x0384
++#define GIC_SH_SMASK_95_64_OFS 0x0388
++#define GIC_SH_SMASK_127_96_OFS 0x038c
++#define GIC_SH_SMASK_159_128_OFS 0x0390
++#define GIC_SH_SMASK_191_160_OFS 0x0394
++#define GIC_SH_SMASK_223_192_OFS 0x0398
++#define GIC_SH_SMASK_255_224_OFS 0x039c
++
++/* Global Interrupt Mask Register (RO) - Bit Set == Interrupt enabled */
++#define GIC_SH_MASK_31_0_OFS 0x0400
++#define GIC_SH_MASK_63_32_OFS 0x0404
++#define GIC_SH_MASK_95_64_OFS 0x0408
++#define GIC_SH_MASK_127_96_OFS 0x040c
++#define GIC_SH_MASK_159_128_OFS 0x0410
++#define GIC_SH_MASK_191_160_OFS 0x0414
++#define GIC_SH_MASK_223_192_OFS 0x0418
++#define GIC_SH_MASK_255_224_OFS 0x041c
++
++/* Pending Global Interrupts (RO) */
++#define GIC_SH_PEND_31_0_OFS 0x0480
++#define GIC_SH_PEND_63_32_OFS 0x0484
++#define GIC_SH_PEND_95_64_OFS 0x0488
++#define GIC_SH_PEND_127_96_OFS 0x048c
++#define GIC_SH_PEND_159_128_OFS 0x0490
++#define GIC_SH_PEND_191_160_OFS 0x0494
++#define GIC_SH_PEND_223_192_OFS 0x0498
++#define GIC_SH_PEND_255_224_OFS 0x049c
++
++#define GIC_SH_INTR_MAP_TO_PIN_BASE_OFS 0x0500
++
++/* Maps Interrupt X to a Pin */
++#define GIC_SH_MAP_TO_PIN(intr) \
++ (GIC_SH_INTR_MAP_TO_PIN_BASE_OFS + (4 * intr))
++
++#define GIC_SH_INTR_MAP_TO_VPE_BASE_OFS 0x2000
++
++/* Maps Interrupt X to a VPE */
++#define GIC_SH_MAP_TO_VPE_REG_OFF(intr, vpe) \
++ (GIC_SH_INTR_MAP_TO_VPE_BASE_OFS + (32 * (intr)) + (((vpe) / 32) * 4))
++#define GIC_SH_MAP_TO_VPE_REG_BIT(vpe) (1 << ((vpe) % 32))
++
++/* Polarity : Reset Value is always 0 */
++#define GIC_SH_SET_POLARITY_OFS 0x0100
++#define GIC_SET_POLARITY(intr, pol) \
++ GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + (((intr) / 32) * 4)), (pol) << ((intr) % 32))
++
++/* Triggering : Reset Value is always 0 */
++#define GIC_SH_SET_TRIGGER_OFS 0x0180
++#define GIC_SET_TRIGGER(intr, trig) \
++ GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + (((intr) / 32) * 4)), (trig) << ((intr) % 32))
++
++/* Mask manipulation */
++#define GIC_SH_SMASK_OFS 0x0380
++#define GIC_SET_INTR_MASK(intr, val) \
++ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_SMASK_OFS + (((intr) / 32) * 4)), ((val) << ((intr) % 32)))
++
++#define GIC_SH_RMASK_OFS 0x0300
++#define GIC_CLR_INTR_MASK(intr, val) \
++ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + (((intr) / 32) * 4)), ((val) << ((intr) % 32)))
++
++/* Register Map for Local Section */
++#define GIC_VPE_CTL_OFS 0x0000
++#define GIC_VPE_PEND_OFS 0x0004
++#define GIC_VPE_MASK_OFS 0x0008
++#define GIC_VPE_RMASK_OFS 0x000c
++#define GIC_VPE_SMASK_OFS 0x0010
++#define GIC_VPE_WD_MAP_OFS 0x0040
++#define GIC_VPE_COMPARE_MAP_OFS 0x0044
++#define GIC_VPE_TIMER_MAP_OFS 0x0048
++#define GIC_VPE_PERFCTR_MAP_OFS 0x0050
++#define GIC_VPE_SWINT0_MAP_OFS 0x0054
++#define GIC_VPE_SWINT1_MAP_OFS 0x0058
++#define GIC_VPE_OTHER_ADDR_OFS 0x0080
++#define GIC_VPE_WD_CONFIG0_OFS 0x0090
++#define GIC_VPE_WD_COUNT0_OFS 0x0094
++#define GIC_VPE_WD_INITIAL0_OFS 0x0098
++#define GIC_VPE_COMPARE_LO_OFS 0x00a0
++#define GIC_VPE_COMPARE_HI 0x00a4
++
++#define GIC_VPE_EIC_SHADOW_SET_BASE 0x0100
++#define GIC_VPE_EIC_SS(intr) \
++ (GIC_EIC_SHADOW_SET_BASE + (4 * intr))
++
++#define GIC_VPE_EIC_VEC_BASE 0x0800
++#define GIC_VPE_EIC_VEC(intr) \
++ (GIC_VPE_EIC_VEC_BASE + (4 * intr))
++
++#define GIC_VPE_TENABLE_NMI_OFS 0x1000
++#define GIC_VPE_TENABLE_YQ_OFS 0x1004
++#define GIC_VPE_TENABLE_INT_31_0_OFS 0x1080
++#define GIC_VPE_TENABLE_INT_63_32_OFS 0x1084
++
++/* User Mode Visible Section Register Map */
++#define GIC_UMV_SH_COUNTER_31_00_OFS 0x0000
++#define GIC_UMV_SH_COUNTER_63_32_OFS 0x0004
++
++#else /* CONFIG_CPU_BIG_ENDIAN */
++
++#define GIC_SH_CONFIG_OFS 0x0000
++
++/* Shared Global Counter */
++#define GIC_SH_COUNTER_31_00_OFS 0x0014
++#define GIC_SH_COUNTER_63_32_OFS 0x0010
++
++/* Interrupt Polarity */
++#define GIC_SH_POL_31_0_OFS 0x0104
++#define GIC_SH_POL_63_32_OFS 0x0100
++#define GIC_SH_POL_95_64_OFS 0x010c
++#define GIC_SH_POL_127_96_OFS 0x0108
++#define GIC_SH_POL_159_128_OFS 0x0114
++#define GIC_SH_POL_191_160_OFS 0x0110
++#define GIC_SH_POL_223_192_OFS 0x011c
++#define GIC_SH_POL_255_224_OFS 0x0118
++
++/* Edge/Level Triggering */
++#define GIC_SH_TRIG_31_0_OFS 0x0184
++#define GIC_SH_TRIG_63_32_OFS 0x0180
++#define GIC_SH_TRIG_95_64_OFS 0x018c
++#define GIC_SH_TRIG_127_96_OFS 0x0188
++#define GIC_SH_TRIG_159_128_OFS 0x0194
++#define GIC_SH_TRIG_191_160_OFS 0x0190
++#define GIC_SH_TRIG_223_192_OFS 0x019c
++#define GIC_SH_TRIG_255_224_OFS 0x0198
++
++/* Dual Edge Triggering */
++#define GIC_SH_DUAL_31_0_OFS 0x0204
++#define GIC_SH_DUAL_63_32_OFS 0x0200
++#define GIC_SH_DUAL_95_64_OFS 0x020c
++#define GIC_SH_DUAL_127_96_OFS 0x0208
++#define GIC_SH_DUAL_159_128_OFS 0x0214
++#define GIC_SH_DUAL_191_160_OFS 0x0210
++#define GIC_SH_DUAL_223_192_OFS 0x021c
++#define GIC_SH_DUAL_255_224_OFS 0x0218
++
++/* Set/Clear corresponding bit in Edge Detect Register */
++#define GIC_SH_WEDGE_OFS 0x0280
++
++/* Reset Mask - Disables Interrupt */
++#define GIC_SH_RMASK_31_0_OFS 0x0304
++#define GIC_SH_RMASK_63_32_OFS 0x0300
++#define GIC_SH_RMASK_95_64_OFS 0x030c
++#define GIC_SH_RMASK_127_96_OFS 0x0308
++#define GIC_SH_RMASK_159_128_OFS 0x0314
++#define GIC_SH_RMASK_191_160_OFS 0x0310
++#define GIC_SH_RMASK_223_192_OFS 0x031c
++#define GIC_SH_RMASK_255_224_OFS 0x0318
++
++/* Set Mask (WO) - Enables Interrupt */
++#define GIC_SH_SMASK_31_0_OFS 0x0384
++#define GIC_SH_SMASK_63_32_OFS 0x0380
++#define GIC_SH_SMASK_95_64_OFS 0x038c
++#define GIC_SH_SMASK_127_96_OFS 0x0388
++#define GIC_SH_SMASK_159_128_OFS 0x0394
++#define GIC_SH_SMASK_191_160_OFS 0x0390
++#define GIC_SH_SMASK_223_192_OFS 0x039c
++#define GIC_SH_SMASK_255_224_OFS 0x0398
++
++/* Global Interrupt Mask Register (RO) - Bit Set == Interrupt enabled */
++#define GIC_SH_MASK_31_0_OFS 0x0404
++#define GIC_SH_MASK_63_32_OFS 0x0400
++#define GIC_SH_MASK_95_64_OFS 0x040c
++#define GIC_SH_MASK_127_96_OFS 0x0408
++#define GIC_SH_MASK_159_128_OFS 0x0414
++#define GIC_SH_MASK_191_160_OFS 0x0410
++#define GIC_SH_MASK_223_192_OFS 0x041c
++#define GIC_SH_MASK_255_224_OFS 0x0418
++
++/* Pending Global Interrupts (RO) */
++#define GIC_SH_PEND_31_0_OFS 0x0484
++#define GIC_SH_PEND_63_32_OFS 0x0480
++#define GIC_SH_PEND_95_64_OFS 0x048c
++#define GIC_SH_PEND_127_96_OFS 0x0488
++#define GIC_SH_PEND_159_128_OFS 0x0494
++#define GIC_SH_PEND_191_160_OFS 0x0490
++#define GIC_SH_PEND_223_192_OFS 0x049c
++#define GIC_SH_PEND_255_224_OFS 0x0498
++
++#define GIC_SH_INTR_MAP_TO_PIN_BASE_OFS 0x0500
++
++/* Maps Interrupt X to a Pin */
++#define GIC_SH_MAP_TO_PIN(intr) \
++ (GIC_SH_INTR_MAP_TO_PIN_BASE_OFS + (4 * intr))
++
++#define GIC_SH_INTR_MAP_TO_VPE_BASE_OFS 0x2004
++
++/*
++ * Maps Interrupt X to a VPE. This is more complex than the LE case, as
++ * odd and even registers need to be transposed. It does work - trust me!
++ */
++#define GIC_SH_MAP_TO_VPE_REG_OFF(intr, vpe) \
++ (GIC_SH_INTR_MAP_TO_VPE_BASE_OFS + (32 * (intr)) + \
++ (((((vpe) / 32) ^ 1) - 1) * 4))
++#define GIC_SH_MAP_TO_VPE_REG_BIT(vpe) (1 << ((vpe) % 32))
++
++/* Polarity */
++#define GIC_SH_SET_POLARITY_OFS 0x0100
++#define GIC_SET_POLARITY(intr, pol) \
++ GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), (pol) << ((intr) % 32))
++
++/* Triggering */
++#define GIC_SH_SET_TRIGGER_OFS 0x0180
++#define GIC_SET_TRIGGER(intr, trig) \
++ GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), (trig) << ((intr) % 32))
++
++/* Mask manipulation */
++#define GIC_SH_SMASK_OFS 0x0380
++#define GIC_SET_INTR_MASK(intr, val) \
++ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_SMASK_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), ((val) << ((intr) % 32)))
++
++#define GIC_SH_RMASK_OFS 0x0300
++#define GIC_CLR_INTR_MASK(intr, val) \
++ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), ((val) << ((intr) % 32))
++
++/* Register Map for Local Section */
++#define GIC_VPE_CTL_OFS 0x0000
++#define GIC_VPE_PEND_OFS 0x0004
++#define GIC_VPE_MASK_OFS 0x0008
++#define GIC_VPE_RMASK_OFS 0x000c
++#define GIC_VPE_SMASK_OFS 0x0010
++#define GIC_VPE_WD_MAP_OFS 0x0040
++#define GIC_VPE_COMPARE_MAP_OFS 0x0044
++#define GIC_VPE_TIMER_MAP_OFS 0x0048
++#define GIC_VPE_PERFCTR_MAP_OFS 0x0050
++#define GIC_VPE_SWINT0_MAP_OFS 0x0054
++#define GIC_VPE_SWINT1_MAP_OFS 0x0058
++#define GIC_VPE_OTHER_ADDR_OFS 0x0080
++#define GIC_VPE_WD_CONFIG0_OFS 0x0090
++#define GIC_VPE_WD_COUNT0_OFS 0x0094
++#define GIC_VPE_WD_INITIAL0_OFS 0x0098
++#define GIC_VPE_COMPARE_LO_OFS 0x00a4
++#define GIC_VPE_COMPARE_HI_OFS 0x00a0
++
++#define GIC_VPE_EIC_SHADOW_SET_BASE 0x0100
++#define GIC_VPE_EIC_SS(intr) \
++ (GIC_EIC_SHADOW_SET_BASE + (4 * intr))
++
++#define GIC_VPE_EIC_VEC_BASE 0x0800
++#define GIC_VPE_EIC_VEC(intr) \
++ (GIC_VPE_EIC_VEC_BASE + (4 * intr))
++
++#define GIC_VPE_TENABLE_NMI_OFS 0x1000
++#define GIC_VPE_TENABLE_YQ_OFS 0x1004
++#define GIC_VPE_TENABLE_INT_31_0_OFS 0x1080
++#define GIC_VPE_TENABLE_INT_63_32_OFS 0x1084
++
++/* User Mode Visible Section Register Map */
++#define GIC_UMV_SH_COUNTER_31_00_OFS 0x0004
++#define GIC_UMV_SH_COUNTER_63_32_OFS 0x0000
++
++#endif /* !LE */
++
++/* Masks */
++#define GIC_SH_CONFIG_COUNTSTOP_SHF 28
++#define GIC_SH_CONFIG_COUNTSTOP_MSK (MSK(1) << GIC_SH_CONFIG_COUNTSTOP_SHF)
++
++#define GIC_SH_CONFIG_COUNTBITS_SHF 24
++#define GIC_SH_CONFIG_COUNTBITS_MSK (MSK(4) << GIC_SH_CONFIG_COUNTBITS_SHF)
++
++#define GIC_SH_CONFIG_NUMINTRS_SHF 16
++#define GIC_SH_CONFIG_NUMINTRS_MSK (MSK(8) << GIC_SH_CONFIG_NUMINTRS_SHF)
++
++#define GIC_SH_CONFIG_NUMVPES_SHF 0
++#define GIC_SH_CONFIG_NUMVPES_MSK (MSK(8) << GIC_SH_CONFIG_NUMVPES_SHF)
++
++#define GIC_SH_WEDGE_SET(intr) (intr | (0x1 << 31))
++#define GIC_SH_WEDGE_CLR(intr) (intr & ~(0x1 << 31))
++
++#define GIC_MAP_TO_PIN_SHF 31
++#define GIC_MAP_TO_PIN_MSK (MSK(1) << GIC_MAP_TO_PIN_SHF)
++#define GIC_MAP_TO_NMI_SHF 30
++#define GIC_MAP_TO_NMI_MSK (MSK(1) << GIC_MAP_TO_NMI_SHF)
++#define GIC_MAP_TO_YQ_SHF 29
++#define GIC_MAP_TO_YQ_MSK (MSK(1) << GIC_MAP_TO_YQ_SHF)
++#define GIC_MAP_SHF 0
++#define GIC_MAP_MSK (MSK(6) << GIC_MAP_SHF)
++
++/* GIC_VPE_CTL Masks */
++#define GIC_VPE_CTL_PERFCNT_RTBL_SHF 2
++#define GIC_VPE_CTL_PERFCNT_RTBL_MSK (MSK(1) << GIC_VPE_CTL_PERFCNT_RTBL_SHF)
++#define GIC_VPE_CTL_TIMER_RTBL_SHF 1
++#define GIC_VPE_CTL_TIMER_RTBL_MSK (MSK(1) << GIC_VPE_CTL_TIMER_RTBL_SHF)
++#define GIC_VPE_CTL_EIC_MODE_SHF 0
++#define GIC_VPE_CTL_EIC_MODE_MSK (MSK(1) << GIC_VPE_CTL_EIC_MODE_SHF)
++
++/* GIC_VPE_PEND Masks */
++#define GIC_VPE_PEND_WD_SHF 0
++#define GIC_VPE_PEND_WD_MSK (MSK(1) << GIC_VPE_PEND_WD_SHF)
++#define GIC_VPE_PEND_CMP_SHF 1
++#define GIC_VPE_PEND_CMP_MSK (MSK(1) << GIC_VPE_PEND_CMP_SHF)
++#define GIC_VPE_PEND_TIMER_SHF 2
++#define GIC_VPE_PEND_TIMER_MSK (MSK(1) << GIC_VPE_PEND_TIMER_SHF)
++#define GIC_VPE_PEND_PERFCOUNT_SHF 3
++#define GIC_VPE_PEND_PERFCOUNT_MSK (MSK(1) << GIC_VPE_PEND_PERFCOUNT_SHF)
++#define GIC_VPE_PEND_SWINT0_SHF 4
++#define GIC_VPE_PEND_SWINT0_MSK (MSK(1) << GIC_VPE_PEND_SWINT0_SHF)
++#define GIC_VPE_PEND_SWINT1_SHF 5
++#define GIC_VPE_PEND_SWINT1_MSK (MSK(1) << GIC_VPE_PEND_SWINT1_SHF)
++
++/* GIC_VPE_RMASK Masks */
++#define GIC_VPE_RMASK_WD_SHF 0
++#define GIC_VPE_RMASK_WD_MSK (MSK(1) << GIC_VPE_RMASK_WD_SHF)
++#define GIC_VPE_RMASK_CMP_SHF 1
++#define GIC_VPE_RMASK_CMP_MSK (MSK(1) << GIC_VPE_RMASK_CMP_SHF)
++#define GIC_VPE_RMASK_TIMER_SHF 2
++#define GIC_VPE_RMASK_TIMER_MSK (MSK(1) << GIC_VPE_RMASK_TIMER_SHF)
++#define GIC_VPE_RMASK_PERFCNT_SHF 3
++#define GIC_VPE_RMASK_PERFCNT_MSK (MSK(1) << GIC_VPE_RMASK_PERFCNT_SHF)
++#define GIC_VPE_RMASK_SWINT0_SHF 4
++#define GIC_VPE_RMASK_SWINT0_MSK (MSK(1) << GIC_VPE_RMASK_SWINT0_SHF)
++#define GIC_VPE_RMASK_SWINT1_SHF 5
++#define GIC_VPE_RMASK_SWINT1_MSK (MSK(1) << GIC_VPE_RMASK_SWINT1_SHF)
++
++/* GIC_VPE_SMASK Masks */
++#define GIC_VPE_SMASK_WD_SHF 0
++#define GIC_VPE_SMASK_WD_MSK (MSK(1) << GIC_VPE_SMASK_WD_SHF)
++#define GIC_VPE_SMASK_CMP_SHF 1
++#define GIC_VPE_SMASK_CMP_MSK (MSK(1) << GIC_VPE_SMASK_CMP_SHF)
++#define GIC_VPE_SMASK_TIMER_SHF 2
++#define GIC_VPE_SMASK_TIMER_MSK (MSK(1) << GIC_VPE_SMASK_TIMER_SHF)
++#define GIC_VPE_SMASK_PERFCNT_SHF 3
++#define GIC_VPE_SMASK_PERFCNT_MSK (MSK(1) << GIC_VPE_SMASK_PERFCNT_SHF)
++#define GIC_VPE_SMASK_SWINT0_SHF 4
++#define GIC_VPE_SMASK_SWINT0_MSK (MSK(1) << GIC_VPE_SMASK_SWINT0_SHF)
++#define GIC_VPE_SMASK_SWINT1_SHF 5
++#define GIC_VPE_SMASK_SWINT1_MSK (MSK(1) << GIC_VPE_SMASK_SWINT1_SHF)
++
++/*
++ * Set the Mapping of Interrupt X to a VPE.
++ */
++#define GIC_SH_MAP_TO_VPE_SMASK(intr, vpe) \
++ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_VPE_REG_OFF(intr, vpe)), \
++ GIC_SH_MAP_TO_VPE_REG_BIT(vpe))
++
++struct gic_pcpu_mask {
++ DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS);
++};
++
++struct gic_pending_regs {
++ DECLARE_BITMAP(pending, GIC_NUM_INTRS);
++};
++
++struct gic_intrmask_regs {
++ DECLARE_BITMAP(intrmask, GIC_NUM_INTRS);
++};
++
++/*
++ * Interrupt Meta-data specification. The ipiflag helps
++ * in building ipi_map.
++ */
++struct gic_intr_map {
++ unsigned int intrnum; /* Ext Intr Num */
++ unsigned int cpunum; /* Directed to this CPU */
++ unsigned int pin; /* Directed to this Pin */
++ unsigned int polarity; /* Polarity : +/- */
++ unsigned int trigtype; /* Trigger : Edge/Levl */
++ unsigned int ipiflag; /* Is used for IPI ? */
++};
++
++extern void gic_init(unsigned long gic_base_addr,
++ unsigned long gic_addrspace_size, struct gic_intr_map *intrmap,
++ unsigned int intrmap_size, unsigned int irqbase);
++
++extern unsigned int gic_get_int(void);
++extern void gic_send_ipi(unsigned int intr);
++
++#endif /* _ASM_GICREGS_H */
+diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
+index e62058b..f18d281 100644
+--- a/include/asm-mips/io.h
++++ b/include/asm-mips/io.h
+@@ -273,7 +273,7 @@ static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size,
+ * memory-like regions on I/O busses.
+ */
+ #define ioremap_cachable(offset, size) \
+- __ioremap_mode((offset), (size), PAGE_CACHABLE_DEFAULT)
++ __ioremap_mode((offset), (size), _page_cachable_default)
+
+ /*
+ * These two are MIPS specific ioremap variant. ioremap_cacheable_cow
+diff --git a/include/asm-mips/jmr3927/jmr3927.h b/include/asm-mips/jmr3927/jmr3927.h
+index 81602c8..a162268 100644
+--- a/include/asm-mips/jmr3927/jmr3927.h
++++ b/include/asm-mips/jmr3927/jmr3927.h
+@@ -99,8 +99,8 @@
+ #define jmr3927_led_and_set(n/*0-16*/) jmr3927_ioc_reg_out((~(n)) & jmr3927_ioc_reg_in(JMR3927_IOC_LED_ADDR), JMR3927_IOC_LED_ADDR)
+
+ /* DIPSW4 macro */
+-#define jmr3927_dipsw1() ((tx3927_pioptr->din & (1 << 11)) == 0)
+-#define jmr3927_dipsw2() ((tx3927_pioptr->din & (1 << 10)) == 0)
++#define jmr3927_dipsw1() (gpio_get_value(11) == 0)
++#define jmr3927_dipsw2() (gpio_get_value(10) == 0)
+ #define jmr3927_dipsw3() ((jmr3927_ioc_reg_in(JMR3927_IOC_DIPSW_ADDR) & 2) == 0)
+ #define jmr3927_dipsw4() ((jmr3927_ioc_reg_in(JMR3927_IOC_DIPSW_ADDR) & 1) == 0)
+
+diff --git a/include/asm-mips/jmr3927/tx3927.h b/include/asm-mips/jmr3927/tx3927.h
+index 338f998..fb58033 100644
+--- a/include/asm-mips/jmr3927/tx3927.h
++++ b/include/asm-mips/jmr3927/tx3927.h
+@@ -314,6 +314,6 @@ struct tx3927_ccfg_reg {
+ #define tx3927_ccfgptr ((struct tx3927_ccfg_reg *)TX3927_CCFG_REG)
+ #define tx3927_tmrptr(ch) ((struct txx927_tmr_reg *)TX3927_TMR_REG(ch))
+ #define tx3927_sioptr(ch) ((struct txx927_sio_reg *)TX3927_SIO_REG(ch))
+-#define tx3927_pioptr ((struct txx927_pio_reg *)TX3927_PIO_REG)
++#define tx3927_pioptr ((struct txx9_pio_reg __iomem *)TX3927_PIO_REG)
+
+ #endif /* __ASM_TX3927_H */
+diff --git a/include/asm-mips/jmr3927/txx927.h b/include/asm-mips/jmr3927/txx927.h
+index 0474fe8..25dcf2f 100644
+--- a/include/asm-mips/jmr3927/txx927.h
++++ b/include/asm-mips/jmr3927/txx927.h
+@@ -22,18 +22,6 @@ struct txx927_sio_reg {
+ volatile unsigned long rfifo;
+ };
+
+-struct txx927_pio_reg {
+- volatile unsigned long dout;
+- volatile unsigned long din;
+- volatile unsigned long dir;
+- volatile unsigned long od;
+- volatile unsigned long flag[2];
+- volatile unsigned long pol;
+- volatile unsigned long intc;
+- volatile unsigned long maskcpu;
+- volatile unsigned long maskext;
+-};
+-
+ /*
+ * SIO
+ */
+diff --git a/include/asm-mips/mach-au1x00/au1000.h b/include/asm-mips/mach-au1x00/au1000.h
+index 5bb57bf..a055551 100644
+--- a/include/asm-mips/mach-au1x00/au1000.h
++++ b/include/asm-mips/mach-au1x00/au1000.h
+@@ -3,9 +3,8 @@
+ * BRIEF MODULE DESCRIPTION
+ * Include file for Alchemy Semiconductor's Au1k CPU.
+ *
+- * Copyright 2000,2001 MontaVista Software Inc.
+- * Author: MontaVista Software, Inc.
+- * ppopov at mvista.com or source at mvista.com
++ * Copyright 2000-2001, 2006-2008 MontaVista Software Inc.
++ * Author: MontaVista Software, Inc. <source at mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+@@ -117,13 +116,6 @@ extern struct au1xxx_irqmap au1xxx_irq_map[];
+
+ #endif /* !defined (_LANGUAGE_ASSEMBLY) */
+
+-#ifdef CONFIG_PM
+-/* no CP0 timer irq */
+-#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
+-#else
+-#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
+-#endif
+-
+ /*
+ * SDRAM Register Offsets
+ */
+@@ -1693,20 +1685,6 @@ enum soc_au1200_ints {
+ #define IOMEM_RESOURCE_START 0x10000000
+ #define IOMEM_RESOURCE_END 0xffffffff
+
+- /*
+- * Borrowed from the PPC arch:
+- * The following macro is used to lookup irqs in a standard table
+- * format for those PPC systems that do not already have PCI
+- * interrupts properly routed.
+- */
+- /* FIXME - double check this from asm-ppc/pci-bridge.h */
+-#define PCI_IRQ_TABLE_LOOKUP \
+- ({ long _ctl_ = -1; \
+- if (idsel >= min_idsel && idsel <= max_idsel && pin <= irqs_per_slot) \
+- _ctl_ = pci_irq_table[idsel - min_idsel][pin-1]; \
+- _ctl_; })
+-
+-
+ #else /* Au1000 and Au1100 and Au1200 */
+
+ /* don't allow any legacy ports probing */
+diff --git a/include/asm-mips/mach-au1x00/au1xxx_ide.h b/include/asm-mips/mach-au1x00/au1xxx_ide.h
+index 89655c0..b493a5e 100644
+--- a/include/asm-mips/mach-au1x00/au1xxx_ide.h
++++ b/include/asm-mips/mach-au1x00/au1xxx_ide.h
+@@ -70,7 +70,6 @@ typedef struct
+ ide_hwif_t *hwif;
+ #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+ ide_drive_t *drive;
+- u8 white_list, black_list;
+ struct dbdma_cmd *dma_table_cpu;
+ dma_addr_t dma_table_dma;
+ #endif
+@@ -81,47 +80,6 @@ typedef struct
+ #endif
+ } _auide_hwif;
+
+-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+-/* HD white list */
+-static const struct drive_list_entry dma_white_list [] = {
+-/*
+- * Hitachi
+- */
+- { "HITACHI_DK14FA-20" , NULL },
+- { "HTS726060M9AT00" , NULL },
+-/*
+- * Maxtor
+- */
+- { "Maxtor 6E040L0" , NULL },
+- { "Maxtor 6Y080P0" , NULL },
+- { "Maxtor 6Y160P0" , NULL },
+-/*
+- * Seagate
+- */
+- { "ST3120026A" , NULL },
+- { "ST320014A" , NULL },
+- { "ST94011A" , NULL },
+- { "ST340016A" , NULL },
+-/*
+- * Western Digital
+- */
+- { "WDC WD400UE-00HCT0" , NULL },
+- { "WDC WD400JB-00JJC0" , NULL },
+- { NULL , NULL }
+-};
+-
+-/* HD black list */
+-static const struct drive_list_entry dma_black_list [] = {
+-/*
+- * Western Digital
+- */
+- { "WDC WD100EB-00CGH0" , NULL },
+- { "WDC WD200BB-00AUA1" , NULL },
+- { "WDC AC24300L" , NULL },
+- { NULL , NULL }
+-};
+-#endif
+-
+ /*******************************************************************************
+ * PIO Mode timing calculation : *
+ * *
+diff --git a/include/asm-mips/mach-db1x00/db1200.h b/include/asm-mips/mach-db1x00/db1200.h
+index d2e28e6..eedd048 100644
+--- a/include/asm-mips/mach-db1x00/db1200.h
++++ b/include/asm-mips/mach-db1x00/db1200.h
+@@ -169,15 +169,15 @@ static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
+ #define BCSR_INT_SD0INSERT 0x1000
+ #define BCSR_INT_SD0EJECT 0x2000
+
+-#define AU1XXX_SMC91111_PHYS_ADDR (0x19000300)
+-#define AU1XXX_SMC91111_IRQ DB1200_ETH_INT
+-
+-#define AU1XXX_ATA_PHYS_ADDR (0x18800000)
+-#define AU1XXX_ATA_REG_OFFSET (5)
+-#define AU1XXX_ATA_PHYS_LEN (16 << AU1XXX_ATA_REG_OFFSET)
+-#define AU1XXX_ATA_INT DB1200_IDE_INT
+-#define AU1XXX_ATA_DDMA_REQ DSCR_CMD0_DMA_REQ1;
+-#define AU1XXX_ATA_RQSIZE 128
++#define SMC91C111_PHYS_ADDR 0x19000300
++#define SMC91C111_INT DB1200_ETH_INT
++
++#define IDE_PHYS_ADDR 0x18800000
++#define IDE_REG_SHIFT 5
++#define IDE_PHYS_LEN (16 << IDE_REG_SHIFT)
++#define IDE_INT DB1200_IDE_INT
++#define IDE_DDMA_REQ DSCR_CMD0_DMA_REQ1
++#define IDE_RQSIZE 128
+
+ #define NAND_PHYS_ADDR 0x20000000
+
+diff --git a/include/asm-mips/mach-generic/gpio.h b/include/asm-mips/mach-generic/gpio.h
+index 6eaf5ef..e6b376b 100644
+--- a/include/asm-mips/mach-generic/gpio.h
++++ b/include/asm-mips/mach-generic/gpio.h
+@@ -1,12 +1,18 @@
+ #ifndef __ASM_MACH_GENERIC_GPIO_H
+ #define __ASM_MACH_GENERIC_GPIO_H
+
++#ifdef CONFIG_HAVE_GPIO_LIB
++#define gpio_get_value __gpio_get_value
++#define gpio_set_value __gpio_set_value
++#define gpio_cansleep __gpio_cansleep
++#else
+ int gpio_request(unsigned gpio, const char *label);
+ 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);
++#endif
+ int gpio_to_irq(unsigned gpio);
+ int irq_to_gpio(unsigned irq);
+
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
@@ -786035,6 +1048355,566 @@
/* MIPS port and memory-mapped I/O string operations. */
static inline void __ide_flush_prologue(void)
{
+diff --git a/include/asm-mips/mach-ip27/topology.h b/include/asm-mips/mach-ip27/topology.h
+index 372291f..7785bec 100644
+--- a/include/asm-mips/mach-ip27/topology.h
++++ b/include/asm-mips/mach-ip27/topology.h
+@@ -54,4 +54,6 @@ extern unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES];
+ .nr_balance_failed = 0, \
+ }
+
++#include <asm-generic/topology.h>
++
+ #endif /* _ASM_MACH_TOPOLOGY_H */
+diff --git a/include/asm-mips/mach-pb1x00/pb1200.h b/include/asm-mips/mach-pb1x00/pb1200.h
+index edaa489..e2c6bca 100644
+--- a/include/asm-mips/mach-pb1x00/pb1200.h
++++ b/include/asm-mips/mach-pb1x00/pb1200.h
+@@ -182,15 +182,15 @@ static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
+ #define SET_VCC_VPP(VCC, VPP, SLOT)\
+ ((((VCC)<<2) | ((VPP)<<0)) << ((SLOT)*8))
+
+-#define AU1XXX_SMC91111_PHYS_ADDR (0x0D000300)
+-#define AU1XXX_SMC91111_IRQ PB1200_ETH_INT
+-
+-#define AU1XXX_ATA_PHYS_ADDR (0x0C800000)
+-#define AU1XXX_ATA_REG_OFFSET (5)
+-#define AU1XXX_ATA_PHYS_LEN (16 << AU1XXX_ATA_REG_OFFSET)
+-#define AU1XXX_ATA_INT PB1200_IDE_INT
+-#define AU1XXX_ATA_DDMA_REQ DSCR_CMD0_DMA_REQ1;
+-#define AU1XXX_ATA_RQSIZE 128
++#define SMC91C111_PHYS_ADDR 0x0D000300
++#define SMC91C111_INT PB1200_ETH_INT
++
++#define IDE_PHYS_ADDR 0x0C800000
++#define IDE_REG_SHIFT 5
++#define IDE_PHYS_LEN (16 << IDE_REG_SHIFT)
++#define IDE_INT PB1200_IDE_INT
++#define IDE_DDMA_REQ DSCR_CMD0_DMA_REQ1
++#define IDE_RQSIZE 128
+
+ #define NAND_PHYS_ADDR 0x1C000000
+
+diff --git a/include/asm-mips/mips-boards/generic.h b/include/asm-mips/mips-boards/generic.h
+index 1c39d33..33407be 100644
+--- a/include/asm-mips/mips-boards/generic.h
++++ b/include/asm-mips/mips-boards/generic.h
+@@ -68,6 +68,7 @@
+ #define MIPS_REVISION_CORID_CORE_FPGA3 9
+ #define MIPS_REVISION_CORID_CORE_24K 10
+ #define MIPS_REVISION_CORID_CORE_FPGA4 11
++#define MIPS_REVISION_CORID_CORE_FPGA5 12
+
+ /**** Artificial corid defines ****/
+ /*
+diff --git a/include/asm-mips/mips-boards/launch.h b/include/asm-mips/mips-boards/launch.h
+new file mode 100644
+index 0000000..d8ae7f9
+--- /dev/null
++++ b/include/asm-mips/mips-boards/launch.h
+@@ -0,0 +1,35 @@
++/*
++ *
++ */
++
++#ifndef _ASSEMBLER_
++
++struct cpulaunch {
++ unsigned long pc;
++ unsigned long gp;
++ unsigned long sp;
++ unsigned long a0;
++ unsigned long _pad[3]; /* pad to cache line size to avoid thrashing */
++ unsigned long flags;
++};
++
++#else
++
++#define LOG2CPULAUNCH 5
++#define LAUNCH_PC 0
++#define LAUNCH_GP 4
++#define LAUNCH_SP 8
++#define LAUNCH_A0 12
++#define LAUNCH_FLAGS 28
++
++#endif
++
++#define LAUNCH_FREADY 1
++#define LAUNCH_FGO 2
++#define LAUNCH_FGONE 4
++
++#define CPULAUNCH 0x00000f00
++#define NCPULAUNCH 8
++
++/* Polling period in count cycles for secondary CPU's */
++#define LAUNCHPERIOD 10000
+diff --git a/include/asm-mips/mips-boards/malta.h b/include/asm-mips/mips-boards/malta.h
+index 93bf4e5..c189157 100644
+--- a/include/asm-mips/mips-boards/malta.h
++++ b/include/asm-mips/mips-boards/malta.h
+@@ -52,6 +52,29 @@ static inline unsigned long get_msc_port_base(unsigned long reg)
+ }
+
+ /*
++ * GCMP Specific definitions
++ */
++#define GCMP_BASE_ADDR 0x1fbf8000
++#define GCMP_ADDRSPACE_SZ (256 * 1024)
++
++/*
++ * GIC Specific definitions
++ */
++#define GIC_BASE_ADDR 0x1bdc0000
++#define GIC_ADDRSPACE_SZ (128 * 1024)
++
++/*
++ * MSC01 BIU Specific definitions
++ * FIXME : These should be elsewhere ?
++ */
++#define MSC01_BIU_REG_BASE 0x1bc80000
++#define MSC01_BIU_ADDRSPACE_SZ (256 * 1024)
++#define MSC01_SC_CFG_OFS 0x0110
++#define MSC01_SC_CFG_GICPRES_MSK 0x00000004
++#define MSC01_SC_CFG_GICPRES_SHF 2
++#define MSC01_SC_CFG_GICENA_SHF 3
++
++/*
+ * Malta RTC-device indirect register access.
+ */
+ #define MALTA_RTC_ADR_REG 0x70
+diff --git a/include/asm-mips/mips-boards/maltaint.h b/include/asm-mips/mips-boards/maltaint.h
+index 7461318..cea872f 100644
+--- a/include/asm-mips/mips-boards/maltaint.h
++++ b/include/asm-mips/mips-boards/maltaint.h
+@@ -39,7 +39,9 @@
+ #define MIPSCPU_INT_I8259A MIPSCPU_INT_MB0
+ #define MIPSCPU_INT_MB1 3
+ #define MIPSCPU_INT_SMI MIPSCPU_INT_MB1
++#define MIPSCPU_INT_IPI0 MIPSCPU_INT_MB1 /* GIC IPI */
+ #define MIPSCPU_INT_MB2 4
++#define MIPSCPU_INT_IPI1 MIPSCPU_INT_MB2 /* GIC IPI */
+ #define MIPSCPU_INT_MB3 5
+ #define MIPSCPU_INT_COREHI MIPSCPU_INT_MB3
+ #define MIPSCPU_INT_MB4 6
+@@ -76,6 +78,31 @@
+ #define MSC01E_INT_PERFCTR 10
+ #define MSC01E_INT_CPUCTR 11
+
++/* GIC's Nomenclature for Core Interrupt Pins on the Malta */
++#define GIC_CPU_INT0 0 /* Core Interrupt 2 */
++#define GIC_CPU_INT1 1 /* . */
++#define GIC_CPU_INT2 2 /* . */
++#define GIC_CPU_INT3 3 /* . */
++#define GIC_CPU_INT4 4 /* . */
++#define GIC_CPU_INT5 5 /* Core Interrupt 5 */
++
++#define GIC_EXT_INTR(x) x
++
++/* Dummy data */
++#define X 0xdead
++
++/* External Interrupts used for IPI */
++#define GIC_IPI_EXT_INTR_RESCHED_VPE0 16
++#define GIC_IPI_EXT_INTR_CALLFNC_VPE0 17
++#define GIC_IPI_EXT_INTR_RESCHED_VPE1 18
++#define GIC_IPI_EXT_INTR_CALLFNC_VPE1 19
++#define GIC_IPI_EXT_INTR_RESCHED_VPE2 20
++#define GIC_IPI_EXT_INTR_CALLFNC_VPE2 21
++#define GIC_IPI_EXT_INTR_RESCHED_VPE3 22
++#define GIC_IPI_EXT_INTR_CALLFNC_VPE3 23
++
++#define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8)
++
+ #ifndef __ASSEMBLY__
+ extern void maltaint_init(void);
+ #endif
+diff --git a/include/asm-mips/mips-boards/maltasmp.h b/include/asm-mips/mips-boards/maltasmp.h
+new file mode 100644
+index 0000000..8d7e955
+--- /dev/null
++++ b/include/asm-mips/mips-boards/maltasmp.h
+@@ -0,0 +1,36 @@
++/*
++ * There are several SMP models supported
++ * SMTC is mutually exclusive to other options (atm)
++ */
++#if defined(CONFIG_MIPS_MT_SMTC)
++#define malta_smtc 1
++#define malta_cmp 0
++#define malta_smvp 0
++#else
++#define malta_smtc 0
++#if defined(CONFIG_MIPS_CMP)
++extern int gcmp_present;
++#define malta_cmp gcmp_present
++#else
++#define malta_cmp 0
++#endif
++/* FIXME: should become COMFIG_MIPS_MT_SMVP */
++#if defined(CONFIG_MIPS_MT_SMP)
++#define malta_smvp 1
++#else
++#define malta_smvp 0
++#endif
++#endif
++
++#include <asm/mipsregs.h>
++#include <asm/mipsmtregs.h>
++
++/* malta_smtc */
++#include <asm/smtc.h>
++#include <asm/smtc_ipi.h>
++
++/* malta_cmp */
++#include <asm/cmp.h>
++
++/* malta_smvp */
++#include <asm/smvp.h>
+diff --git a/include/asm-mips/mipsmtregs.h b/include/asm-mips/mipsmtregs.h
+index 5a2f8a3..c9420aa 100644
+--- a/include/asm-mips/mipsmtregs.h
++++ b/include/asm-mips/mipsmtregs.h
+@@ -197,8 +197,8 @@ static inline void __raw_evpe(void)
+ " .set pop \n");
+ }
+
+-/* Enable multiMT if previous suggested it should be.
+- EMT_ENABLE to force */
++/* Enable virtual processor execution if previous suggested it should be.
++ EVPE_ENABLE to force */
+
+ #define EVPE_ENABLE MVPCONTROL_EVP
+
+@@ -238,8 +238,8 @@ static inline void __raw_emt(void)
+ " .set reorder");
+ }
+
+-/* enable multiVPE if previous suggested it should be.
+- EVPE_ENABLE to force */
++/* enable multi-threaded execution if previous suggested it should be.
++ EMT_ENABLE to force */
+
+ #define EMT_ENABLE VPECONTROL_TE
+
+diff --git a/include/asm-mips/pgtable-32.h b/include/asm-mips/pgtable-32.h
+index ceefe02..4396e9f 100644
+--- a/include/asm-mips/pgtable-32.h
++++ b/include/asm-mips/pgtable-32.h
+@@ -107,7 +107,7 @@ static inline void pmd_clear(pmd_t *pmdp)
+ pmd_val(*pmdp) = ((unsigned long) invalid_pte_table);
+ }
+
+-#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
++#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+ #define pte_page(x) pfn_to_page(pte_pfn(x))
+ #define pte_pfn(x) ((unsigned long)((x).pte_high >> 6))
+ static inline pte_t
+@@ -130,7 +130,7 @@ pfn_pte(unsigned long pfn, pgprot_t prot)
+ #define pte_pfn(x) ((unsigned long)((x).pte >> PAGE_SHIFT))
+ #define pfn_pte(pfn, prot) __pte(((unsigned long long)(pfn) << PAGE_SHIFT) | pgprot_val(prot))
+ #endif
+-#endif /* defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1) */
++#endif /* defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) */
+
+ #define __pgd_offset(address) pgd_index(address)
+ #define __pud_offset(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
+diff --git a/include/asm-mips/pgtable-bits.h b/include/asm-mips/pgtable-bits.h
+index 7494ba9..60e2f93 100644
+--- a/include/asm-mips/pgtable-bits.h
++++ b/include/asm-mips/pgtable-bits.h
+@@ -32,14 +32,14 @@
+ * unpredictable things. The code (when it is written) to deal with
+ * this problem will be in the update_mmu_cache() code for the r4k.
+ */
+-#if defined(CONFIG_CPU_MIPS32_R1) && defined(CONFIG_64BIT_PHYS_ADDR)
++#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+
+ #define _PAGE_PRESENT (1<<6) /* implemented in software */
+ #define _PAGE_READ (1<<7) /* implemented in software */
+ #define _PAGE_WRITE (1<<8) /* implemented in software */
+ #define _PAGE_ACCESSED (1<<9) /* implemented in software */
+ #define _PAGE_MODIFIED (1<<10) /* implemented in software */
+-#define _PAGE_FILE (1<<10) /* set:pagecache unset:swap */
++#define _PAGE_FILE (1<<10) /* set:pagecache unset:swap */
+
+ #define _PAGE_R4KBUG (1<<0) /* workaround for r4k bug */
+ #define _PAGE_GLOBAL (1<<0)
+@@ -47,15 +47,9 @@
+ #define _PAGE_SILENT_READ (1<<1) /* synonym */
+ #define _PAGE_DIRTY (1<<2) /* The MIPS dirty bit */
+ #define _PAGE_SILENT_WRITE (1<<2)
++#define _CACHE_SHIFT 3
+ #define _CACHE_MASK (7<<3)
+
+-/* MIPS32 defines only values 2 and 3. The rest are implementation
+- * dependent.
+- */
+-#define _CACHE_UNCACHED (2<<3)
+-#define _CACHE_CACHABLE_NONCOHERENT (3<<3)
+-#define _CACHE_CACHABLE_COW (3<<3) /* Au1x */
+-
+ #else
+
+ #define _PAGE_PRESENT (1<<0) /* implemented in software */
+@@ -74,75 +68,72 @@
+ #define _PAGE_SILENT_WRITE (1<<10)
+ #define _CACHE_UNCACHED (1<<11)
+ #define _CACHE_MASK (1<<11)
+-#define _CACHE_CACHABLE_NONCOHERENT 0
+
+ #else
++
+ #define _PAGE_R4KBUG (1<<5) /* workaround for r4k bug */
+ #define _PAGE_GLOBAL (1<<6)
+ #define _PAGE_VALID (1<<7)
+ #define _PAGE_SILENT_READ (1<<7) /* synonym */
+ #define _PAGE_DIRTY (1<<8) /* The MIPS dirty bit */
+ #define _PAGE_SILENT_WRITE (1<<8)
++#define _CACHE_SHIFT 9
+ #define _CACHE_MASK (7<<9)
+
+-#ifdef CONFIG_CPU_SB1
++#endif
++#endif /* defined(CONFIG_64BIT_PHYS_ADDR && defined(CONFIG_CPU_MIPS32) */
++
++
++/*
++ * Cache attributes
++ */
++#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
++
++#define _CACHE_CACHABLE_NONCOHERENT 0
++
++#elif defined(CONFIG_CPU_SB1)
+
+ /* No penalty for being coherent on the SB1, so just
+ use it for "noncoherent" spaces, too. Shouldn't hurt. */
+
+-#define _CACHE_UNCACHED (2<<9)
+-#define _CACHE_CACHABLE_COW (5<<9)
+-#define _CACHE_CACHABLE_NONCOHERENT (5<<9)
+-#define _CACHE_UNCACHED_ACCELERATED (7<<9)
++#define _CACHE_UNCACHED (2<<_CACHE_SHIFT)
++#define _CACHE_CACHABLE_COW (5<<_CACHE_SHIFT)
++#define _CACHE_CACHABLE_NONCOHERENT (5<<_CACHE_SHIFT)
++#define _CACHE_UNCACHED_ACCELERATED (7<<_CACHE_SHIFT)
+
+ #elif defined(CONFIG_CPU_RM9000)
+
+-#define _CACHE_WT (0 << 9)
+-#define _CACHE_WTWA (1 << 9)
+-#define _CACHE_UC_B (2 << 9)
+-#define _CACHE_WB (3 << 9)
+-#define _CACHE_CWBEA (4 << 9)
+-#define _CACHE_CWB (5 << 9)
+-#define _CACHE_UCNB (6 << 9)
+-#define _CACHE_FPC (7 << 9)
++#define _CACHE_WT (0<<_CACHE_SHIFT)
++#define _CACHE_WTWA (1<<_CACHE_SHIFT)
++#define _CACHE_UC_B (2<<_CACHE_SHIFT)
++#define _CACHE_WB (3<<_CACHE_SHIFT)
++#define _CACHE_CWBEA (4<<_CACHE_SHIFT)
++#define _CACHE_CWB (5<<_CACHE_SHIFT)
++#define _CACHE_UCNB (6<<_CACHE_SHIFT)
++#define _CACHE_FPC (7<<_CACHE_SHIFT)
+
+-#define _CACHE_UNCACHED _CACHE_UC_B
+-#define _CACHE_CACHABLE_NONCOHERENT _CACHE_WB
++#define _CACHE_UNCACHED _CACHE_UC_B
++#define _CACHE_CACHABLE_NONCOHERENT _CACHE_WB
+
+ #else
+
+-#define _CACHE_CACHABLE_NO_WA (0<<9) /* R4600 only */
+-#define _CACHE_CACHABLE_WA (1<<9) /* R4600 only */
+-#define _CACHE_UNCACHED (2<<9) /* R4[0246]00 */
+-#define _CACHE_CACHABLE_NONCOHERENT (3<<9) /* R4[0246]00 */
+-#define _CACHE_CACHABLE_CE (4<<9) /* R4[04]00MC only */
+-#define _CACHE_CACHABLE_COW (5<<9) /* R4[04]00MC only */
+-#define _CACHE_CACHABLE_CUW (6<<9) /* R4[04]00MC only */
+-#define _CACHE_UNCACHED_ACCELERATED (7<<9) /* R10000 only */
++#define _CACHE_CACHABLE_NO_WA (0<<_CACHE_SHIFT) /* R4600 only */
++#define _CACHE_CACHABLE_WA (1<<_CACHE_SHIFT) /* R4600 only */
++#define _CACHE_UNCACHED (2<<_CACHE_SHIFT) /* R4[0246]00 */
++#define _CACHE_CACHABLE_NONCOHERENT (3<<_CACHE_SHIFT) /* R4[0246]00 */
++#define _CACHE_CACHABLE_CE (4<<_CACHE_SHIFT) /* R4[04]00MC only */
++#define _CACHE_CACHABLE_COW (5<<_CACHE_SHIFT) /* R4[04]00MC only */
++#define _CACHE_CACHABLE_COHERENT (5<<_CACHE_SHIFT) /* MIPS32R2 CMP */
++#define _CACHE_CACHABLE_CUW (6<<_CACHE_SHIFT) /* R4[04]00MC only */
++#define _CACHE_UNCACHED_ACCELERATED (7<<_CACHE_SHIFT) /* R10000 only */
+
+ #endif
+-#endif
+-#endif /* defined(CONFIG_CPU_MIPS32_R1) && defined(CONFIG_64BIT_PHYS_ADDR) */
+
+ #define __READABLE (_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED)
+ #define __WRITEABLE (_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED)
+
+ #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_MODIFIED | _CACHE_MASK)
+
+-#ifdef CONFIG_MIPS_UNCACHED
+-#define PAGE_CACHABLE_DEFAULT _CACHE_UNCACHED
+-#elif defined(CONFIG_DMA_NONCOHERENT)
+-#define PAGE_CACHABLE_DEFAULT _CACHE_CACHABLE_NONCOHERENT
+-#elif defined(CONFIG_CPU_RM9000)
+-#define PAGE_CACHABLE_DEFAULT _CACHE_CWB
+-#else
+-#define PAGE_CACHABLE_DEFAULT _CACHE_CACHABLE_COW
+-#endif
+-
+-#if defined(CONFIG_CPU_MIPS32_R1) && defined(CONFIG_64BIT_PHYS_ADDR)
+-#define CONF_CM_DEFAULT (PAGE_CACHABLE_DEFAULT >> 3)
+-#else
+-#define CONF_CM_DEFAULT (PAGE_CACHABLE_DEFAULT >> 9)
+-#endif
++#define CONF_CM_DEFAULT (PAGE_CACHABLE_DEFAULT>>_CACHE_SHIFT)
+
+ #endif /* _ASM_PGTABLE_BITS_H */
+diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
+index 17a7703..2f597ee 100644
+--- a/include/asm-mips/pgtable.h
++++ b/include/asm-mips/pgtable.h
+@@ -23,15 +23,15 @@ struct vm_area_struct;
+
+ #define PAGE_NONE __pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT)
+ #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
+- PAGE_CACHABLE_DEFAULT)
++ _page_cachable_default)
+ #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_READ | \
+- PAGE_CACHABLE_DEFAULT)
++ _page_cachable_default)
+ #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_READ | \
+- PAGE_CACHABLE_DEFAULT)
++ _page_cachable_default)
+ #define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
+- _PAGE_GLOBAL | PAGE_CACHABLE_DEFAULT)
++ _PAGE_GLOBAL | _page_cachable_default)
+ #define PAGE_USERIO __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
+- PAGE_CACHABLE_DEFAULT)
++ _page_cachable_default)
+ #define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | \
+ __WRITEABLE | _PAGE_GLOBAL | _CACHE_UNCACHED)
+
+@@ -40,23 +40,30 @@ struct vm_area_struct;
+ * read. Also, write permissions imply read permissions. This is the closest
+ * we can get by reasonable means..
+ */
+-#define __P000 PAGE_NONE
+-#define __P001 PAGE_READONLY
+-#define __P010 PAGE_COPY
+-#define __P011 PAGE_COPY
+-#define __P100 PAGE_READONLY
+-#define __P101 PAGE_READONLY
+-#define __P110 PAGE_COPY
+-#define __P111 PAGE_COPY
+-
+-#define __S000 PAGE_NONE
+-#define __S001 PAGE_READONLY
+-#define __S010 PAGE_SHARED
+-#define __S011 PAGE_SHARED
+-#define __S100 PAGE_READONLY
+-#define __S101 PAGE_READONLY
+-#define __S110 PAGE_SHARED
+-#define __S111 PAGE_SHARED
++
++/*
++ * Dummy values to fill the table in mmap.c
++ * The real values will be generated at runtime
++ */
++#define __P000 __pgprot(0)
++#define __P001 __pgprot(0)
++#define __P010 __pgprot(0)
++#define __P011 __pgprot(0)
++#define __P100 __pgprot(0)
++#define __P101 __pgprot(0)
++#define __P110 __pgprot(0)
++#define __P111 __pgprot(0)
++
++#define __S000 __pgprot(0)
++#define __S001 __pgprot(0)
++#define __S010 __pgprot(0)
++#define __S011 __pgprot(0)
++#define __S100 __pgprot(0)
++#define __S101 __pgprot(0)
++#define __S110 __pgprot(0)
++#define __S111 __pgprot(0)
++
++extern unsigned long _page_cachable_default;
+
+ /*
+ * ZERO_PAGE is a global shared page that is always zero; used
+@@ -79,7 +86,7 @@ extern void paging_init(void);
+ #define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
+ #define pmd_page_vaddr(pmd) pmd_val(pmd)
+
+-#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
++#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+
+ #define pte_none(pte) (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL))
+ #define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT)
+@@ -182,7 +189,7 @@ extern pgd_t swapper_pg_dir[];
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+-#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
++#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+ static inline int pte_write(pte_t pte) { return pte.pte_low & _PAGE_WRITE; }
+ static inline int pte_dirty(pte_t pte) { return pte.pte_low & _PAGE_MODIFIED; }
+ static inline int pte_young(pte_t pte) { return pte.pte_low & _PAGE_ACCESSED; }
+@@ -285,6 +292,8 @@ static inline pte_t pte_mkyoung(pte_t pte)
+ return pte;
+ }
+ #endif
++static inline int pte_special(pte_t pte) { return 0; }
++static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+
+ /*
+ * Macro to make mark a page protection value as "uncacheable". Note
+@@ -309,7 +318,7 @@ static inline pgprot_t pgprot_noncached(pgprot_t _prot)
+ */
+ #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
+
+-#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
++#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+ {
+ pte.pte_low &= _PAGE_CHG_MASK;
+diff --git a/include/asm-mips/r4k-timer.h b/include/asm-mips/r4k-timer.h
+new file mode 100644
+index 0000000..a37d12b
+--- /dev/null
++++ b/include/asm-mips/r4k-timer.h
+@@ -0,0 +1,30 @@
++/*
++ * 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) 2008 by Ralf Baechle (ralf at linux-mips.org)
++ */
++#ifndef __ASM_R4K_TYPES_H
++#define __ASM_R4K_TYPES_H
++
++#include <linux/compiler.h>
++
++#ifdef CONFIG_SYNC_R4K
++
++extern void synchronise_count_master(void);
++extern void synchronise_count_slave(void);
++
++#else
++
++static inline void synchronise_count_master(void)
++{
++}
++
++static inline void synchronise_count_slave(void)
++{
++}
++
++#endif
++
++#endif /* __ASM_R4K_TYPES_H */
diff --git a/include/asm-mips/semaphore.h b/include/asm-mips/semaphore.h
index fdf8042..d9b2034 100644
--- a/include/asm-mips/semaphore.h
@@ -786149,6 +1049029,418 @@
-
-#endif /* __ASM_SEMAPHORE_H */
+#include <linux/semaphore.h>
+diff --git a/include/asm-mips/smp-ops.h b/include/asm-mips/smp-ops.h
+index b17fdfb..43c207e 100644
+--- a/include/asm-mips/smp-ops.h
++++ b/include/asm-mips/smp-ops.h
+@@ -51,6 +51,7 @@ static inline void register_smp_ops(struct plat_smp_ops *ops)
+ #endif /* !CONFIG_SMP */
+
+ extern struct plat_smp_ops up_smp_ops;
++extern struct plat_smp_ops cmp_smp_ops;
+ extern struct plat_smp_ops vsmp_smp_ops;
+
+ #endif /* __ASM_SMP_OPS_H */
+diff --git a/include/asm-mips/smtc.h b/include/asm-mips/smtc.h
+index ff3e893..3639b28 100644
+--- a/include/asm-mips/smtc.h
++++ b/include/asm-mips/smtc.h
+@@ -44,6 +44,7 @@ extern int mipsmt_build_cpu_map(int startslot);
+ extern void mipsmt_prepare_cpus(void);
+ extern void smtc_smp_finish(void);
+ extern void smtc_boot_secondary(int cpu, struct task_struct *t);
++extern void smtc_cpus_done(void);
+
+ /*
+ * Sharing the TLB between multiple VPEs means that the
+diff --git a/include/asm-mips/smvp.h b/include/asm-mips/smvp.h
+new file mode 100644
+index 0000000..0d0e80a
+--- /dev/null
++++ b/include/asm-mips/smvp.h
+@@ -0,0 +1,19 @@
++#ifndef _ASM_SMVP_H
++#define _ASM_SMVP_H
++
++/*
++ * Definitions for SMVP multitasking on MIPS MT cores
++ */
++struct task_struct;
++
++extern void smvp_smp_setup(void);
++extern void smvp_smp_finish(void);
++extern void smvp_boot_secondary(int cpu, struct task_struct *t);
++extern void smvp_init_secondary(void);
++extern void smvp_smp_finish(void);
++extern void smvp_cpus_done(void);
++extern void smvp_prepare_cpus(unsigned int max_cpus);
++
++/* This is platform specific */
++extern void smvp_send_ipi(int cpu, unsigned int action);
++#endif /* _ASM_SMVP_H */
+diff --git a/include/asm-mips/traps.h b/include/asm-mips/traps.h
+index d02e019..e5dbde6 100644
+--- a/include/asm-mips/traps.h
++++ b/include/asm-mips/traps.h
+@@ -23,5 +23,7 @@ extern int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
+
+ extern void (*board_nmi_handler_setup)(void);
+ extern void (*board_ejtag_handler_setup)(void);
++extern void (*board_bind_eic_interrupt)(int irq, int regset);
++extern void (*board_watchpoint_handler)(struct pt_regs *regs);
+
+ #endif /* _ASM_TRAPS_H */
+diff --git a/include/asm-mips/tx4938/rbtx4938.h b/include/asm-mips/tx4938/rbtx4938.h
+index b180488..dfed7be 100644
+--- a/include/asm-mips/tx4938/rbtx4938.h
++++ b/include/asm-mips/tx4938/rbtx4938.h
+@@ -67,44 +67,26 @@
+ #define RBTX4938_INTF_MODEM (1 << RBTX4938_INTB_MODEM)
+ #define RBTX4938_INTF_SWINT (1 << RBTX4938_INTB_SWINT)
+
+-#define rbtx4938_fpga_rev_ptr \
+- ((volatile unsigned char *)RBTX4938_FPGA_REV_ADDR)
+-#define rbtx4938_led_ptr \
+- ((volatile unsigned char *)RBTX4938_LED_ADDR)
+-#define rbtx4938_dipsw_ptr \
+- ((volatile unsigned char *)RBTX4938_DIPSW_ADDR)
+-#define rbtx4938_bdipsw_ptr \
+- ((volatile unsigned char *)RBTX4938_BDIPSW_ADDR)
+-#define rbtx4938_imask_ptr \
+- ((volatile unsigned char *)RBTX4938_IMASK_ADDR)
+-#define rbtx4938_imask2_ptr \
+- ((volatile unsigned char *)RBTX4938_IMASK2_ADDR)
+-#define rbtx4938_intpol_ptr \
+- ((volatile unsigned char *)RBTX4938_INTPOL_ADDR)
+-#define rbtx4938_istat_ptr \
+- ((volatile unsigned char *)RBTX4938_ISTAT_ADDR)
+-#define rbtx4938_istat2_ptr \
+- ((volatile unsigned char *)RBTX4938_ISTAT2_ADDR)
+-#define rbtx4938_imstat_ptr \
+- ((volatile unsigned char *)RBTX4938_IMSTAT_ADDR)
+-#define rbtx4938_imstat2_ptr \
+- ((volatile unsigned char *)RBTX4938_IMSTAT2_ADDR)
+-#define rbtx4938_softint_ptr \
+- ((volatile unsigned char *)RBTX4938_SOFTINT_ADDR)
+-#define rbtx4938_piosel_ptr \
+- ((volatile unsigned char *)RBTX4938_PIOSEL_ADDR)
+-#define rbtx4938_spics_ptr \
+- ((volatile unsigned char *)RBTX4938_SPICS_ADDR)
+-#define rbtx4938_sfpwr_ptr \
+- ((volatile unsigned char *)RBTX4938_SFPWR_ADDR)
+-#define rbtx4938_sfvol_ptr \
+- ((volatile unsigned char *)RBTX4938_SFVOL_ADDR)
+-#define rbtx4938_softreset_ptr \
+- ((volatile unsigned char *)RBTX4938_SOFTRESET_ADDR)
+-#define rbtx4938_softresetlock_ptr \
+- ((volatile unsigned char *)RBTX4938_SOFTRESETLOCK_ADDR)
+-#define rbtx4938_pcireset_ptr \
+- ((volatile unsigned char *)RBTX4938_PCIRESET_ADDR)
++#define rbtx4938_fpga_rev_addr ((__u8 __iomem *)RBTX4938_FPGA_REV_ADDR)
++#define rbtx4938_led_addr ((__u8 __iomem *)RBTX4938_LED_ADDR)
++#define rbtx4938_dipsw_addr ((__u8 __iomem *)RBTX4938_DIPSW_ADDR)
++#define rbtx4938_bdipsw_addr ((__u8 __iomem *)RBTX4938_BDIPSW_ADDR)
++#define rbtx4938_imask_addr ((__u8 __iomem *)RBTX4938_IMASK_ADDR)
++#define rbtx4938_imask2_addr ((__u8 __iomem *)RBTX4938_IMASK2_ADDR)
++#define rbtx4938_intpol_addr ((__u8 __iomem *)RBTX4938_INTPOL_ADDR)
++#define rbtx4938_istat_addr ((__u8 __iomem *)RBTX4938_ISTAT_ADDR)
++#define rbtx4938_istat2_addr ((__u8 __iomem *)RBTX4938_ISTAT2_ADDR)
++#define rbtx4938_imstat_addr ((__u8 __iomem *)RBTX4938_IMSTAT_ADDR)
++#define rbtx4938_imstat2_addr ((__u8 __iomem *)RBTX4938_IMSTAT2_ADDR)
++#define rbtx4938_softint_addr ((__u8 __iomem *)RBTX4938_SOFTINT_ADDR)
++#define rbtx4938_piosel_addr ((__u8 __iomem *)RBTX4938_PIOSEL_ADDR)
++#define rbtx4938_spics_addr ((__u8 __iomem *)RBTX4938_SPICS_ADDR)
++#define rbtx4938_sfpwr_addr ((__u8 __iomem *)RBTX4938_SFPWR_ADDR)
++#define rbtx4938_sfvol_addr ((__u8 __iomem *)RBTX4938_SFVOL_ADDR)
++#define rbtx4938_softreset_addr ((__u8 __iomem *)RBTX4938_SOFTRESET_ADDR)
++#define rbtx4938_softresetlock_addr \
++ ((__u8 __iomem *)RBTX4938_SOFTRESETLOCK_ADDR)
++#define rbtx4938_pcireset_addr ((__u8 __iomem *)RBTX4938_PCIRESET_ADDR)
+
+ /*
+ * IRQ mappings
+diff --git a/include/asm-mips/tx4938/tx4938.h b/include/asm-mips/tx4938/tx4938.h
+index f7c448b..e8807f5 100644
+--- a/include/asm-mips/tx4938/tx4938.h
++++ b/include/asm-mips/tx4938/tx4938.h
+@@ -13,8 +13,6 @@
+ #ifndef __ASM_TX_BOARDS_TX4938_H
+ #define __ASM_TX_BOARDS_TX4938_H
+
+-#include <asm/tx4938/tx4938_mips.h>
+-
+ #define tx4938_read_nfmc(addr) (*(volatile unsigned int *)(addr))
+ #define tx4938_write_nfmc(b, addr) (*(volatile unsigned int *)(addr)) = (b)
+
+@@ -54,28 +52,6 @@
+ #define TX4938_ACLC_REG (TX4938_REG_BASE + 0xf700)
+ #define TX4938_SPI_REG (TX4938_REG_BASE + 0xf800)
+
+-#ifndef _LANGUAGE_ASSEMBLY
+-#include <asm/byteorder.h>
+-
+-#define TX4938_MKA(x) ((u32)( ((u32)(TX4938_REG_BASE)) | ((u32)(x)) ))
+-
+-#define TX4938_RD08( reg ) (*(vu08*)(reg))
+-#define TX4938_WR08( reg, val ) ((*(vu08*)(reg))=(val))
+-
+-#define TX4938_RD16( reg ) (*(vu16*)(reg))
+-#define TX4938_WR16( reg, val ) ((*(vu16*)(reg))=(val))
+-
+-#define TX4938_RD32( reg ) (*(vu32*)(reg))
+-#define TX4938_WR32( reg, val ) ((*(vu32*)(reg))=(val))
+-
+-#define TX4938_RD64( reg ) (*(vu64*)(reg))
+-#define TX4938_WR64( reg, val ) ((*(vu64*)(reg))=(val))
+-
+-#define TX4938_RD( reg ) TX4938_RD32( reg )
+-#define TX4938_WR( reg, val ) TX4938_WR32( reg, val )
+-
+-#endif /* !__ASSEMBLY__ */
+-
+ #ifdef __ASSEMBLY__
+ #define _CONST64(c) c
+ #else
+@@ -261,18 +237,6 @@ struct tx4938_sio_reg {
+ volatile unsigned long rfifo;
+ };
+
+-struct tx4938_pio_reg {
+- volatile unsigned long dout;
+- volatile unsigned long din;
+- volatile unsigned long dir;
+- volatile unsigned long od;
+- volatile unsigned long flag[2];
+- volatile unsigned long pol;
+- volatile unsigned long intc;
+- volatile unsigned long maskcpu;
+- volatile unsigned long maskext;
+-};
+-
+ struct tx4938_ndfmc_reg {
+ endian_def_l2(unused0, dtr);
+ endian_def_l2(unused1, mcr);
+@@ -642,7 +606,7 @@ struct tx4938_ccfg_reg {
+ #define tx4938_pcic1ptr ((struct tx4938_pcic_reg *)TX4938_PCIC1_REG)
+ #define tx4938_ccfgptr ((struct tx4938_ccfg_reg *)TX4938_CCFG_REG)
+ #define tx4938_sioptr(ch) ((struct tx4938_sio_reg *)TX4938_SIO_REG(ch))
+-#define tx4938_pioptr ((struct tx4938_pio_reg *)TX4938_PIO_REG)
++#define tx4938_pioptr ((struct txx9_pio_reg __iomem *)TX4938_PIO_REG)
+ #define tx4938_aclcptr ((struct tx4938_aclc_reg *)TX4938_ACLC_REG)
+ #define tx4938_spiptr ((struct tx4938_spi_reg *)TX4938_SPI_REG)
+ #define tx4938_sramcptr ((struct tx4938_sramc_reg *)TX4938_SRAMC_REG)
+diff --git a/include/asm-mips/tx4938/tx4938_mips.h b/include/asm-mips/tx4938/tx4938_mips.h
+deleted file mode 100644
+index f346ff5..0000000
+--- a/include/asm-mips/tx4938/tx4938_mips.h
++++ /dev/null
+@@ -1,54 +0,0 @@
+-/*
+- * linux/include/asm-mips/tx4938/tx4938_mips.h
+- * Generic bitmask definitions
+- *
+- * 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.
+- *
+- * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani at mvista.com)
+- */
+-
+-#ifndef TX4938_TX4938_MIPS_H
+-#define TX4938_TX4938_MIPS_H
+-#ifndef __ASSEMBLY__
+-
+-#define reg_rd08(r) ((u8 )(*((vu8 *)(r))))
+-#define reg_rd16(r) ((u16)(*((vu16*)(r))))
+-#define reg_rd32(r) ((u32)(*((vu32*)(r))))
+-#define reg_rd64(r) ((u64)(*((vu64*)(r))))
+-
+-#define reg_wr08(r, v) ((*((vu8 *)(r)))=((u8 )(v)))
+-#define reg_wr16(r, v) ((*((vu16*)(r)))=((u16)(v)))
+-#define reg_wr32(r, v) ((*((vu32*)(r)))=((u32)(v)))
+-#define reg_wr64(r, v) ((*((vu64*)(r)))=((u64)(v)))
+-
+-typedef volatile __signed char vs8;
+-typedef volatile unsigned char vu8;
+-
+-typedef volatile __signed short vs16;
+-typedef volatile unsigned short vu16;
+-
+-typedef volatile __signed int vs32;
+-typedef volatile unsigned int vu32;
+-
+-typedef s8 s08;
+-typedef vs8 vs08;
+-
+-typedef u8 u08;
+-typedef vu8 vu08;
+-
+-#if (_MIPS_SZLONG == 64)
+-
+-typedef volatile __signed__ long vs64;
+-typedef volatile unsigned long vu64;
+-
+-#else
+-
+-typedef volatile __signed__ long long vs64;
+-typedef volatile unsigned long long vu64;
+-
+-#endif
+-#endif
+-#endif
+diff --git a/include/asm-mips/txx9pio.h b/include/asm-mips/txx9pio.h
+new file mode 100644
+index 0000000..3d6fa9f
+--- /dev/null
++++ b/include/asm-mips/txx9pio.h
+@@ -0,0 +1,29 @@
++/*
++ * include/asm-mips/txx9pio.h
++ * TX39/TX49 PIO controller definitions.
++ *
++ * 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_TXX9PIO_H
++#define __ASM_TXX9PIO_H
++
++#include <linux/types.h>
++
++struct txx9_pio_reg {
++ __u32 dout;
++ __u32 din;
++ __u32 dir;
++ __u32 od;
++ __u32 flag[2];
++ __u32 pol;
++ __u32 intc;
++ __u32 maskcpu;
++ __u32 maskext;
++};
++
++int txx9_gpio_init(unsigned long baseaddr,
++ unsigned int base, unsigned int num);
++
++#endif /* __ASM_TXX9PIO_H */
+diff --git a/include/asm-mips/unaligned.h b/include/asm-mips/unaligned.h
+index 3249049..7924049 100644
+--- a/include/asm-mips/unaligned.h
++++ b/include/asm-mips/unaligned.h
+@@ -5,25 +5,24 @@
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf at linux-mips.org)
+ */
+-#ifndef __ASM_GENERIC_UNALIGNED_H
+-#define __ASM_GENERIC_UNALIGNED_H
++#ifndef _ASM_MIPS_UNALIGNED_H
++#define _ASM_MIPS_UNALIGNED_H
+
+ #include <linux/compiler.h>
++#if defined(__MIPSEB__)
++# include <linux/unaligned/be_struct.h>
++# include <linux/unaligned/le_byteshift.h>
++# include <linux/unaligned/generic.h>
++# define get_unaligned __get_unaligned_be
++# define put_unaligned __put_unaligned_be
++#elif defined(__MIPSEL__)
++# include <linux/unaligned/le_struct.h>
++# include <linux/unaligned/be_byteshift.h>
++# include <linux/unaligned/generic.h>
++# define get_unaligned __get_unaligned_le
++# define put_unaligned __put_unaligned_le
++#else
++# error "MIPS, but neither __MIPSEB__, nor __MIPSEL__???"
++#endif
+
+-#define get_unaligned(ptr) \
+-({ \
+- struct __packed { \
+- typeof(*(ptr)) __v; \
+- } *__p = (void *) (ptr); \
+- __p->__v; \
+-})
+-
+-#define put_unaligned(val, ptr) \
+-do { \
+- struct __packed { \
+- typeof(*(ptr)) __v; \
+- } *__p = (void *) (ptr); \
+- __p->__v = (val); \
+-} while(0)
+-
+-#endif /* __ASM_GENERIC_UNALIGNED_H */
++#endif /* _ASM_MIPS_UNALIGNED_H */
+diff --git a/include/asm-mips/vr41xx/siu.h b/include/asm-mips/vr41xx/siu.h
+index 98cdb40..da9f6e3 100644
+--- a/include/asm-mips/vr41xx/siu.h
++++ b/include/asm-mips/vr41xx/siu.h
+@@ -1,7 +1,7 @@
+ /*
+ * Include file for NEC VR4100 series Serial Interface Unit.
+ *
+- * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa at tripeaks.co.jp>
++ * Copyright (C) 2005-2008 Yoichi Yuasa <yoichi_yuasa at tripeaks.co.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -49,4 +49,10 @@ typedef enum {
+
+ extern void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed);
+
++#ifdef CONFIG_SERIAL_VR41XX_CONSOLE
++extern void vr41xx_siu_early_setup(struct uart_port *port);
++#else
++static inline void vr41xx_siu_early_setup(struct uart_port *port) {}
++#endif
++
+ #endif /* __NEC_VR41XX_SIU_H */
+diff --git a/include/asm-mips/vr41xx/vr41xx.h b/include/asm-mips/vr41xx/vr41xx.h
+index 88b492f..22be649 100644
+--- a/include/asm-mips/vr41xx/vr41xx.h
++++ b/include/asm-mips/vr41xx/vr41xx.h
+@@ -7,7 +7,7 @@
+ * Copyright (C) 2001, 2002 Paul Mundt
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ * Copyright (C) 2002 TimeSys Corp.
+- * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa at tripeaks.co.jp>
++ * Copyright (C) 2003-2008 Yoichi Yuasa <yoichi_yuasa at tripeaks.co.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+@@ -143,4 +143,10 @@ extern void vr41xx_disable_csiint(uint16_t mask);
+ extern void vr41xx_enable_bcuint(void);
+ extern void vr41xx_disable_bcuint(void);
+
++#ifdef CONFIG_SERIAL_VR41XX_CONSOLE
++extern void vr41xx_siu_setup(void);
++#else
++static inline void vr41xx_siu_setup(void) {}
++#endif
++
+ #endif /* __NEC_VR41XX_H */
+diff --git a/include/asm-mn10300/pgtable.h b/include/asm-mn10300/pgtable.h
+index 375c494..6dc30fc 100644
+--- a/include/asm-mn10300/pgtable.h
++++ b/include/asm-mn10300/pgtable.h
+@@ -224,6 +224,7 @@ static inline int pte_read(pte_t pte) { return pte_val(pte) & __PAGE_PROT_USER;
+ 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_PROT_WRITE; }
++static inline int pte_special(pte_t pte){ return 0; }
+
+ /*
+ * The following only works if pte_present() is not true.
+@@ -265,6 +266,8 @@ static inline pte_t pte_mkwrite(pte_t pte)
+ return pte;
+ }
+
++static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
++
+ #define pte_ERROR(e) \
+ printk(KERN_ERR "%s:%d: bad pte %08lx.\n", \
+ __FILE__, __LINE__, pte_val(e))
diff --git a/include/asm-mn10300/semaphore.h b/include/asm-mn10300/semaphore.h
index 5a9e1ad..d9b2034 100644
--- a/include/asm-mn10300/semaphore.h
@@ -786324,6 +1049616,173 @@
-
-#endif
+#include <linux/semaphore.h>
+diff --git a/include/asm-mn10300/unaligned.h b/include/asm-mn10300/unaligned.h
+index cad3afb..0df6713 100644
+--- a/include/asm-mn10300/unaligned.h
++++ b/include/asm-mn10300/unaligned.h
+@@ -8,129 +8,13 @@
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+-#ifndef _ASM_UNALIGNED_H
+-#define _ASM_UNALIGNED_H
++#ifndef _ASM_MN10300_UNALIGNED_H
++#define _ASM_MN10300_UNALIGNED_H
+
+-#include <asm/types.h>
++#include <linux/unaligned/access_ok.h>
++#include <linux/unaligned/generic.h>
+
+-#if 0
+-extern int __bug_unaligned_x(void *ptr);
++#define get_unaligned __get_unaligned_le
++#define put_unaligned __put_unaligned_le
+
+-/*
+- * What is the most efficient way of loading/storing an unaligned value?
+- *
+- * That is the subject of this file. Efficiency here is defined as
+- * minimum code size with minimum register usage for the common cases.
+- * It is currently not believed that long longs are common, so we
+- * trade efficiency for the chars, shorts and longs against the long
+- * longs.
+- *
+- * Current stats with gcc 2.7.2.2 for these functions:
+- *
+- * ptrsize get: code regs put: code regs
+- * 1 1 1 1 2
+- * 2 3 2 3 2
+- * 4 7 3 7 3
+- * 8 20 6 16 6
+- *
+- * gcc 2.95.1 seems to code differently:
+- *
+- * ptrsize get: code regs put: code regs
+- * 1 1 1 1 2
+- * 2 3 2 3 2
+- * 4 7 4 7 4
+- * 8 19 8 15 6
+- *
+- * which may or may not be more efficient (depending upon whether
+- * you can afford the extra registers). Hopefully the gcc 2.95
+- * is inteligent enough to decide if it is better to use the
+- * extra register, but evidence so far seems to suggest otherwise.
+- *
+- * Unfortunately, gcc is not able to optimise the high word
+- * out of long long >> 32, or the low word from long long << 32
+- */
+-
+-#define __get_unaligned_2(__p) \
+- (__p[0] | __p[1] << 8)
+-
+-#define __get_unaligned_4(__p) \
+- (__p[0] | __p[1] << 8 | __p[2] << 16 | __p[3] << 24)
+-
+-#define get_unaligned(ptr) \
+-({ \
+- unsigned int __v1, __v2; \
+- __typeof__(*(ptr)) __v; \
+- __u8 *__p = (__u8 *)(ptr); \
+- \
+- switch (sizeof(*(ptr))) { \
+- case 1: __v = *(ptr); break; \
+- case 2: __v = __get_unaligned_2(__p); break; \
+- case 4: __v = __get_unaligned_4(__p); break; \
+- case 8: \
+- __v2 = __get_unaligned_4((__p+4)); \
+- __v1 = __get_unaligned_4(__p); \
+- __v = ((unsigned long long)__v2 << 32 | __v1); \
+- break; \
+- default: __v = __bug_unaligned_x(__p); break; \
+- } \
+- __v; \
+-})
+-
+-
+-static inline void __put_unaligned_2(__u32 __v, register __u8 *__p)
+-{
+- *__p++ = __v;
+- *__p++ = __v >> 8;
+-}
+-
+-static inline void __put_unaligned_4(__u32 __v, register __u8 *__p)
+-{
+- __put_unaligned_2(__v >> 16, __p + 2);
+- __put_unaligned_2(__v, __p);
+-}
+-
+-static inline void __put_unaligned_8(const unsigned long long __v, __u8 *__p)
+-{
+- /*
+- * tradeoff: 8 bytes of stack for all unaligned puts (2
+- * instructions), or an extra register in the long long
+- * case - go for the extra register.
+- */
+- __put_unaligned_4(__v >> 32, __p + 4);
+- __put_unaligned_4(__v, __p);
+-}
+-
+-/*
+- * Try to store an unaligned value as efficiently as possible.
+- */
+-#define put_unaligned(val, ptr) \
+- ({ \
+- switch (sizeof(*(ptr))) { \
+- case 1: \
+- *(ptr) = (val); \
+- break; \
+- case 2: \
+- __put_unaligned_2((val), (__u8 *)(ptr)); \
+- break; \
+- case 4: \
+- __put_unaligned_4((val), (__u8 *)(ptr)); \
+- break; \
+- case 8: \
+- __put_unaligned_8((val), (__u8 *)(ptr)); \
+- break; \
+- default: \
+- __bug_unaligned_x(ptr); \
+- break; \
+- } \
+- (void) 0; \
+- })
+-
+-
+-#else
+-
+-#define get_unaligned(ptr) (*(ptr))
+-#define put_unaligned(val, ptr) ({ *(ptr) = (val); (void) 0; })
+-
+-#endif
+-
+-#endif
++#endif /* _ASM_MN10300_UNALIGNED_H */
+diff --git a/include/asm-parisc/bitops.h b/include/asm-parisc/bitops.h
+index f8eebcb..7a6ea10 100644
+--- a/include/asm-parisc/bitops.h
++++ b/include/asm-parisc/bitops.h
+@@ -210,6 +210,7 @@ static __inline__ int fls(int x)
+ return ret;
+ }
+
++#include <asm-generic/bitops/__fls.h>
+ #include <asm-generic/bitops/fls64.h>
+ #include <asm-generic/bitops/hweight.h>
+ #include <asm-generic/bitops/lock.h>
+diff --git a/include/asm-parisc/futex.h b/include/asm-parisc/futex.h
+index fdc6d05..0c705c3 100644
+--- a/include/asm-parisc/futex.h
++++ b/include/asm-parisc/futex.h
+@@ -4,8 +4,8 @@
+ #ifdef __KERNEL__
+
+ #include <linux/futex.h>
++#include <linux/uaccess.h>
+ #include <asm/errno.h>
+-#include <asm/uaccess.h>
+
+ static inline int
+ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
diff --git a/include/asm-parisc/ide.h b/include/asm-parisc/ide.h
index be8760f..db0c944 100644
--- a/include/asm-parisc/ide.h
@@ -786337,6 +1049796,26 @@
#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/pgtable.h b/include/asm-parisc/pgtable.h
+index dc86adb..470a4b8 100644
+--- a/include/asm-parisc/pgtable.h
++++ b/include/asm-parisc/pgtable.h
+@@ -323,6 +323,7 @@ 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_WRITE; }
+ static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
++static inline int pte_special(pte_t pte) { return 0; }
+
+ static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
+ static inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+@@ -330,6 +331,7 @@ static inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_WRITE; ret
+ static inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
+ static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+ static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; return pte; }
++static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+
+ /*
+ * Conversion functions: convert a page and protection to a page entry,
diff --git a/include/asm-parisc/semaphore-helper.h b/include/asm-parisc/semaphore-helper.h
deleted file mode 100644
index 387f7c1..0000000
@@ -786583,6 +1050062,31 @@
-
-#endif /* _ASM_PARISC_SEMAPHORE_H */
+#include <linux/semaphore.h>
+diff --git a/include/asm-parisc/unaligned.h b/include/asm-parisc/unaligned.h
+index 53c9058..dfc5d33 100644
+--- a/include/asm-parisc/unaligned.h
++++ b/include/asm-parisc/unaligned.h
+@@ -1,7 +1,11 @@
+-#ifndef _ASM_PARISC_UNALIGNED_H_
+-#define _ASM_PARISC_UNALIGNED_H_
++#ifndef _ASM_PARISC_UNALIGNED_H
++#define _ASM_PARISC_UNALIGNED_H
+
+-#include <asm-generic/unaligned.h>
++#include <linux/unaligned/be_struct.h>
++#include <linux/unaligned/le_byteshift.h>
++#include <linux/unaligned/generic.h>
++#define get_unaligned __get_unaligned_be
++#define put_unaligned __put_unaligned_be
+
+ #ifdef __KERNEL__
+ struct pt_regs;
+@@ -9,4 +13,4 @@ void handle_unaligned(struct pt_regs *regs);
+ int check_unaligned(struct pt_regs *regs);
+ #endif
+
+-#endif /* _ASM_PARISC_UNALIGNED_H_ */
++#endif /* _ASM_PARISC_UNALIGNED_H */
diff --git a/include/asm-powerpc/Kbuild b/include/asm-powerpc/Kbuild
index 5f640e5..7381916 100644
--- a/include/asm-powerpc/Kbuild
@@ -786620,33 +1050124,21 @@
struct mschunks_map {
diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h
-index 220d9a7..a99a749 100644
+index 220d9a7..897eade 100644
--- a/include/asm-powerpc/bitops.h
+++ b/include/asm-powerpc/bitops.h
-@@ -312,24 +312,26 @@ static __inline__ int fls(unsigned int x)
+@@ -312,24 +312,31 @@ 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)
+-#include <asm-generic/bitops/fls64.h>
+
+-#include <asm-generic/bitops/hweight.h>
++static __inline__ unsigned long __fls(unsigned long x)
+{
-+ int lz;
-+
-+ asm ("cntlzd %0,%1" : "=r" (lz) : "r" (x));
-+ return 64 - lz;
++ return __ilog2(x);
+}
-+#else
- #include <asm-generic/bitops/fls64.h>
-+#endif /* __powerpc64__ */
- #include <asm-generic/bitops/hweight.h>
--
-#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
-unsigned long find_next_zero_bit(const unsigned long *addr,
- unsigned long size, unsigned long offset);
@@ -786657,10 +1050149,27 @@
- *
- * Returns the bit-number of the first set bit, not the number of the byte
- * containing a bit.
-- */
++/*
++ * 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.
+ */
-#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);
++#ifdef __powerpc64__
++static __inline__ int fls64(__u64 x)
++{
++ int lz;
++
++ asm ("cntlzd %0,%1" : "=r" (lz) : "r" (x));
++ return 64 - lz;
++}
++#else
++#include <asm-generic/bitops/fls64.h>
++#endif /* __powerpc64__ */
++
++#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/find.h>
/* Little-endian versions */
@@ -787328,6 +1050837,21 @@
+}
+
+#endif /* __ASM_FSL_LBC_H */
+diff --git a/include/asm-powerpc/futex.h b/include/asm-powerpc/futex.h
+index 3f3673f..6d406c5 100644
+--- a/include/asm-powerpc/futex.h
++++ b/include/asm-powerpc/futex.h
+@@ -4,9 +4,9 @@
+ #ifdef __KERNEL__
+
+ #include <linux/futex.h>
++#include <linux/uaccess.h>
+ #include <asm/errno.h>
+ #include <asm/synch.h>
+-#include <asm/uaccess.h>
+ #include <asm/asm-compat.h>
+
+ #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
diff --git a/include/asm-powerpc/gpio.h b/include/asm-powerpc/gpio.h
new file mode 100644
index 0000000..77ad3a8
@@ -787497,6 +1051021,91 @@
}
#define flush_cache_kmaps() flush_cache_all()
+diff --git a/include/asm-powerpc/hugetlb.h b/include/asm-powerpc/hugetlb.h
+new file mode 100644
+index 0000000..649c6c3
+--- /dev/null
++++ b/include/asm-powerpc/hugetlb.h
+@@ -0,0 +1,79 @@
++#ifndef _ASM_POWERPC_HUGETLB_H
++#define _ASM_POWERPC_HUGETLB_H
++
++#include <asm/page.h>
++
++
++int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
++ unsigned long len);
++
++void hugetlb_free_pgd_range(struct mmu_gather **tlb, unsigned long addr,
++ unsigned long end, unsigned long floor,
++ unsigned long ceiling);
++
++void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
++ pte_t *ptep, pte_t pte);
++
++pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
++ pte_t *ptep);
++
++/*
++ * If the arch doesn't supply something else, assume that hugepage
++ * size aligned regions are ok without further preparation.
++ */
++static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
++{
++ if (len & ~HPAGE_MASK)
++ return -EINVAL;
++ if (addr & ~HPAGE_MASK)
++ return -EINVAL;
++ return 0;
++}
++
++static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm)
++{
++}
++
++static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
++ unsigned long addr, pte_t *ptep)
++{
++}
++
++static inline int huge_pte_none(pte_t pte)
++{
++ return pte_none(pte);
++}
++
++static inline pte_t huge_pte_wrprotect(pte_t pte)
++{
++ return pte_wrprotect(pte);
++}
++
++static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
++ unsigned long addr, pte_t *ptep)
++{
++ ptep_set_wrprotect(mm, addr, ptep);
++}
++
++static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
++ unsigned long addr, pte_t *ptep,
++ pte_t pte, int dirty)
++{
++ return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
++}
++
++static inline pte_t huge_ptep_get(pte_t *ptep)
++{
++ return *ptep;
++}
++
++static inline int arch_prepare_hugepage(struct page *page)
++{
++ return 0;
++}
++
++static inline void arch_release_hugepage(struct page *page)
++{
++}
++
++#endif /* _ASM_POWERPC_HUGETLB_H */
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
@@ -787785,6 +1051394,19 @@
static inline void name at \
{ \
if (DEF_PCI_HOOK(ppc_pci_io.name) != NULL) \
+diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
+index b5c0312..5089deb 100644
+--- a/include/asm-powerpc/irq.h
++++ b/include/asm-powerpc/irq.h
+@@ -619,8 +619,6 @@ struct pt_regs;
+
+ #define __ARCH_HAS_DO_SOFTIRQ
+
+-extern void __do_softirq(void);
+-
+ #ifdef CONFIG_IRQSTACKS
+ /*
+ * Per-cpu stacks for handling hard and soft interrupts.
diff --git a/include/asm-powerpc/irqflags.h b/include/asm-powerpc/irqflags.h
index 7970cba..cc6fdba 100644
--- a/include/asm-powerpc/irqflags.h
@@ -787994,6 +1051616,424 @@
#endif /* CONFIG_CRASH_DUMP */
#ifndef __ASSEMBLY__
+diff --git a/include/asm-powerpc/kvm.h b/include/asm-powerpc/kvm.h
+index d1b530f..f993e41 100644
+--- a/include/asm-powerpc/kvm.h
++++ b/include/asm-powerpc/kvm.h
+@@ -1,6 +1,55 @@
++/*
++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * Copyright IBM Corp. 2007
++ *
++ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ */
++
+ #ifndef __LINUX_KVM_POWERPC_H
+ #define __LINUX_KVM_POWERPC_H
+
+-/* powerpc does not support KVM */
++#include <asm/types.h>
++
++struct kvm_regs {
++ __u64 pc;
++ __u64 cr;
++ __u64 ctr;
++ __u64 lr;
++ __u64 xer;
++ __u64 msr;
++ __u64 srr0;
++ __u64 srr1;
++ __u64 pid;
++
++ __u64 sprg0;
++ __u64 sprg1;
++ __u64 sprg2;
++ __u64 sprg3;
++ __u64 sprg4;
++ __u64 sprg5;
++ __u64 sprg6;
++ __u64 sprg7;
++
++ __u64 gpr[32];
++};
++
++struct kvm_sregs {
++};
++
++struct kvm_fpu {
++ __u64 fpr[32];
++};
+
+-#endif
++#endif /* __LINUX_KVM_POWERPC_H */
+diff --git a/include/asm-powerpc/kvm_asm.h b/include/asm-powerpc/kvm_asm.h
+new file mode 100644
+index 0000000..2197764
+--- /dev/null
++++ b/include/asm-powerpc/kvm_asm.h
+@@ -0,0 +1,55 @@
++/*
++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * Copyright IBM Corp. 2008
++ *
++ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ */
++
++#ifndef __POWERPC_KVM_ASM_H__
++#define __POWERPC_KVM_ASM_H__
++
++/* IVPR must be 64KiB-aligned. */
++#define VCPU_SIZE_ORDER 4
++#define VCPU_SIZE_LOG (VCPU_SIZE_ORDER + 12)
++#define VCPU_TLB_PGSZ PPC44x_TLB_64K
++#define VCPU_SIZE_BYTES (1<<VCPU_SIZE_LOG)
++
++#define BOOKE_INTERRUPT_CRITICAL 0
++#define BOOKE_INTERRUPT_MACHINE_CHECK 1
++#define BOOKE_INTERRUPT_DATA_STORAGE 2
++#define BOOKE_INTERRUPT_INST_STORAGE 3
++#define BOOKE_INTERRUPT_EXTERNAL 4
++#define BOOKE_INTERRUPT_ALIGNMENT 5
++#define BOOKE_INTERRUPT_PROGRAM 6
++#define BOOKE_INTERRUPT_FP_UNAVAIL 7
++#define BOOKE_INTERRUPT_SYSCALL 8
++#define BOOKE_INTERRUPT_AP_UNAVAIL 9
++#define BOOKE_INTERRUPT_DECREMENTER 10
++#define BOOKE_INTERRUPT_FIT 11
++#define BOOKE_INTERRUPT_WATCHDOG 12
++#define BOOKE_INTERRUPT_DTLB_MISS 13
++#define BOOKE_INTERRUPT_ITLB_MISS 14
++#define BOOKE_INTERRUPT_DEBUG 15
++#define BOOKE_MAX_INTERRUPT 15
++
++#define RESUME_FLAG_NV (1<<0) /* Reload guest nonvolatile state? */
++#define RESUME_FLAG_HOST (1<<1) /* Resume host? */
++
++#define RESUME_GUEST 0
++#define RESUME_GUEST_NV RESUME_FLAG_NV
++#define RESUME_HOST RESUME_FLAG_HOST
++#define RESUME_HOST_NV (RESUME_FLAG_HOST|RESUME_FLAG_NV)
++
++#endif /* __POWERPC_KVM_ASM_H__ */
+diff --git a/include/asm-powerpc/kvm_host.h b/include/asm-powerpc/kvm_host.h
+new file mode 100644
+index 0000000..04ffbb8
+--- /dev/null
++++ b/include/asm-powerpc/kvm_host.h
+@@ -0,0 +1,152 @@
++/*
++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * Copyright IBM Corp. 2007
++ *
++ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ */
++
++#ifndef __POWERPC_KVM_HOST_H__
++#define __POWERPC_KVM_HOST_H__
++
++#include <linux/mutex.h>
++#include <linux/timer.h>
++#include <linux/types.h>
++#include <linux/kvm_types.h>
++#include <asm/kvm_asm.h>
++
++#define KVM_MAX_VCPUS 1
++#define KVM_MEMORY_SLOTS 32
++/* memory slots that does not exposed to userspace */
++#define KVM_PRIVATE_MEM_SLOTS 4
++
++/* We don't currently support large pages. */
++#define KVM_PAGES_PER_HPAGE (1<<31)
++
++struct kvm;
++struct kvm_run;
++struct kvm_vcpu;
++
++struct kvm_vm_stat {
++ u32 remote_tlb_flush;
++};
++
++struct kvm_vcpu_stat {
++ u32 sum_exits;
++ u32 mmio_exits;
++ u32 dcr_exits;
++ u32 signal_exits;
++ u32 light_exits;
++ /* Account for special types of light exits: */
++ u32 itlb_real_miss_exits;
++ u32 itlb_virt_miss_exits;
++ u32 dtlb_real_miss_exits;
++ u32 dtlb_virt_miss_exits;
++ u32 syscall_exits;
++ u32 isi_exits;
++ u32 dsi_exits;
++ u32 emulated_inst_exits;
++ u32 dec_exits;
++ u32 ext_intr_exits;
++};
++
++struct tlbe {
++ u32 tid; /* Only the low 8 bits are used. */
++ u32 word0;
++ u32 word1;
++ u32 word2;
++};
++
++struct kvm_arch {
++};
++
++struct kvm_vcpu_arch {
++ /* Unmodified copy of the guest's TLB. */
++ struct tlbe guest_tlb[PPC44x_TLB_SIZE];
++ /* TLB that's actually used when the guest is running. */
++ struct tlbe shadow_tlb[PPC44x_TLB_SIZE];
++ /* Pages which are referenced in the shadow TLB. */
++ struct page *shadow_pages[PPC44x_TLB_SIZE];
++ /* Copy of the host's TLB. */
++ struct tlbe host_tlb[PPC44x_TLB_SIZE];
++
++ u32 host_stack;
++ u32 host_pid;
++
++ u64 fpr[32];
++ u32 gpr[32];
++
++ u32 pc;
++ u32 cr;
++ u32 ctr;
++ u32 lr;
++ u32 xer;
++
++ u32 msr;
++ u32 mmucr;
++ u32 sprg0;
++ u32 sprg1;
++ u32 sprg2;
++ u32 sprg3;
++ u32 sprg4;
++ u32 sprg5;
++ u32 sprg6;
++ u32 sprg7;
++ u32 srr0;
++ u32 srr1;
++ u32 csrr0;
++ u32 csrr1;
++ u32 dsrr0;
++ u32 dsrr1;
++ u32 dear;
++ u32 esr;
++ u32 dec;
++ u32 decar;
++ u32 tbl;
++ u32 tbu;
++ u32 tcr;
++ u32 tsr;
++ u32 ivor[16];
++ u32 ivpr;
++ u32 pir;
++ u32 pid;
++ u32 pvr;
++ u32 ccr0;
++ u32 ccr1;
++ u32 dbcr0;
++ u32 dbcr1;
++
++ u32 last_inst;
++ u32 fault_dear;
++ u32 fault_esr;
++ gpa_t paddr_accessed;
++
++ u8 io_gpr; /* GPR used as IO source/target */
++ u8 mmio_is_bigendian;
++ u8 dcr_needed;
++ u8 dcr_is_write;
++
++ u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */
++
++ struct timer_list dec_timer;
++ unsigned long pending_exceptions;
++};
++
++struct kvm_guest_debug {
++ int enabled;
++ unsigned long bp[4];
++ int singlestep;
++};
++
++#endif /* __POWERPC_KVM_HOST_H__ */
+diff --git a/include/asm-powerpc/kvm_para.h b/include/asm-powerpc/kvm_para.h
+new file mode 100644
+index 0000000..2d48f6a
+--- /dev/null
++++ b/include/asm-powerpc/kvm_para.h
+@@ -0,0 +1,37 @@
++/*
++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * Copyright IBM Corp. 2008
++ *
++ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ */
++
++#ifndef __POWERPC_KVM_PARA_H__
++#define __POWERPC_KVM_PARA_H__
++
++#ifdef __KERNEL__
++
++static inline int kvm_para_available(void)
++{
++ return 0;
++}
++
++static inline unsigned int kvm_arch_para_features(void)
++{
++ return 0;
++}
++
++#endif /* __KERNEL__ */
++
++#endif /* __POWERPC_KVM_PARA_H__ */
+diff --git a/include/asm-powerpc/kvm_ppc.h b/include/asm-powerpc/kvm_ppc.h
+new file mode 100644
+index 0000000..7ac8203
+--- /dev/null
++++ b/include/asm-powerpc/kvm_ppc.h
+@@ -0,0 +1,88 @@
++/*
++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * Copyright IBM Corp. 2008
++ *
++ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ */
++
++#ifndef __POWERPC_KVM_PPC_H__
++#define __POWERPC_KVM_PPC_H__
++
++/* This file exists just so we can dereference kvm_vcpu, avoiding nested header
++ * dependencies. */
++
++#include <linux/mutex.h>
++#include <linux/timer.h>
++#include <linux/types.h>
++#include <linux/kvm_types.h>
++#include <linux/kvm_host.h>
++
++struct kvm_tlb {
++ struct tlbe guest_tlb[PPC44x_TLB_SIZE];
++ struct tlbe shadow_tlb[PPC44x_TLB_SIZE];
++};
++
++enum emulation_result {
++ EMULATE_DONE, /* no further processing */
++ EMULATE_DO_MMIO, /* kvm_run filled with MMIO request */
++ EMULATE_DO_DCR, /* kvm_run filled with DCR request */
++ EMULATE_FAIL, /* can't emulate this instruction */
++};
++
++extern const unsigned char exception_priority[];
++extern const unsigned char priority_exception[];
++
++extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
++extern char kvmppc_handlers_start[];
++extern unsigned long kvmppc_handler_len;
++
++extern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu);
++extern int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
++ unsigned int rt, unsigned int bytes,
++ int is_bigendian);
++extern int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
++ u32 val, unsigned int bytes, int is_bigendian);
++
++extern int kvmppc_emulate_instruction(struct kvm_run *run,
++ struct kvm_vcpu *vcpu);
++
++extern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn,
++ u64 asid, u32 flags);
++extern void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, u64 eaddr, u64 asid);
++extern void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode);
++
++extern void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu);
++
++static inline void kvmppc_queue_exception(struct kvm_vcpu *vcpu, int exception)
++{
++ unsigned int priority = exception_priority[exception];
++ set_bit(priority, &vcpu->arch.pending_exceptions);
++}
++
++static inline void kvmppc_clear_exception(struct kvm_vcpu *vcpu, int exception)
++{
++ unsigned int priority = exception_priority[exception];
++ clear_bit(priority, &vcpu->arch.pending_exceptions);
++}
++
++static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
++{
++ if ((new_msr & MSR_PR) != (vcpu->arch.msr & MSR_PR))
++ kvmppc_mmu_priv_switch(vcpu, new_msr & MSR_PR);
++
++ vcpu->arch.msr = new_msr;
++}
++
++#endif /* __POWERPC_KVM_PPC_H__ */
diff --git a/include/asm-powerpc/lmb.h b/include/asm-powerpc/lmb.h
index 5d1dc48..6f5fdf0 100644
--- a/include/asm-powerpc/lmb.h
@@ -788158,18 +1052198,18 @@
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
+index 62772ae..a825524 100644
--- a/include/asm-powerpc/mmu-44x.h
+++ b/include/asm-powerpc/mmu-44x.h
-@@ -53,8 +53,6 @@
+@@ -53,7 +53,7 @@
#ifndef __ASSEMBLY__
-typedef unsigned long long phys_addr_t;
--
++extern unsigned int tlb_44x_hwater;
+
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
@@ -788363,6 +1052403,31 @@
#ifdef CONFIG_NOT_COHERENT_CACHE
#define ARCH_KMALLOC_MINALIGN L1_CACHE_BYTES
+diff --git a/include/asm-powerpc/page_64.h b/include/asm-powerpc/page_64.h
+index 67834ea..25af4fc 100644
+--- a/include/asm-powerpc/page_64.h
++++ b/include/asm-powerpc/page_64.h
+@@ -128,11 +128,6 @@ extern void slice_init_context(struct mm_struct *mm, unsigned int psize);
+ extern void slice_set_user_psize(struct mm_struct *mm, unsigned int psize);
+ #define slice_mm_new_context(mm) ((mm)->context.id == 0)
+
+-#define ARCH_HAS_HUGEPAGE_ONLY_RANGE
+-extern int is_hugepage_only_range(struct mm_struct *m,
+- unsigned long addr,
+- unsigned long len);
+-
+ #endif /* __ASSEMBLY__ */
+ #else
+ #define slice_init()
+@@ -146,8 +141,6 @@ do { \
+
+ #ifdef CONFIG_HUGETLB_PAGE
+
+-#define ARCH_HAS_HUGETLB_FREE_PGD_RANGE
+-#define ARCH_HAS_SETCLEAR_HUGE_PTE
+ #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+
+ #endif /* !CONFIG_HUGETLB_PAGE */
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
@@ -788508,7 +1052573,7 @@
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
+index 2c79f55..7c97b5a 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;
@@ -788531,7 +1052596,24 @@
/* 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,
+@@ -506,6 +504,7 @@ static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
+ 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_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
++static inline int pte_special(pte_t pte) { return 0; }
+
+ static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
+ static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; }
+@@ -523,6 +522,8 @@ static inline pte_t pte_mkdirty(pte_t pte) {
+ pte_val(pte) |= _PAGE_DIRTY; return pte; }
+ static inline pte_t pte_mkyoung(pte_t pte) {
+ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
++static inline pte_t pte_mkspecial(pte_t pte) {
++ return pte; }
+
+ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+ {
+@@ -692,7 +693,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) \
@@ -788540,6 +1052622,27 @@
#endif
/* to find an entry in a kernel page-table-directory */
+diff --git a/include/asm-powerpc/pgtable-ppc64.h b/include/asm-powerpc/pgtable-ppc64.h
+index dd4c26d..27f1869 100644
+--- a/include/asm-powerpc/pgtable-ppc64.h
++++ b/include/asm-powerpc/pgtable-ppc64.h
+@@ -239,6 +239,7 @@ static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW;}
+ 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_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE;}
++static inline int pte_special(pte_t pte) { return 0; }
+
+ static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
+ static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; }
+@@ -257,6 +258,8 @@ static inline pte_t pte_mkyoung(pte_t pte) {
+ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+ static inline pte_t pte_mkhuge(pte_t pte) {
+ return pte; }
++static inline pte_t pte_mkspecial(pte_t pte) {
++ return pte; }
+
+ /* Atomic PTE updates */
+ static inline unsigned long pte_update(struct mm_struct *mm,
diff --git a/include/asm-powerpc/phyp_dump.h b/include/asm-powerpc/phyp_dump.h
new file mode 100644
index 0000000..fa74c6c
@@ -788630,6 +1052733,42 @@
+extern void ppc4xx_reset_system(char *cmd);
+
+#endif /* __ASM_POWERPC_PPC4xx_H__ */
+diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
+index fd98ca9..cf83f2d 100644
+--- a/include/asm-powerpc/processor.h
++++ b/include/asm-powerpc/processor.h
+@@ -138,6 +138,8 @@ typedef struct {
+
+ struct thread_struct {
+ unsigned long ksp; /* Kernel stack pointer */
++ unsigned long ksp_limit; /* if ksp <= ksp_limit stack overflow */
++
+ #ifdef CONFIG_PPC64
+ unsigned long ksp_vsid;
+ #endif
+@@ -182,11 +184,14 @@ struct thread_struct {
+ #define ARCH_MIN_TASKALIGN 16
+
+ #define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)
++#define INIT_SP_LIMIT \
++ (_ALIGN_UP(sizeof(init_thread_info), 16) + (unsigned long) &init_stack)
+
+
+ #ifdef CONFIG_PPC32
+ #define INIT_THREAD { \
+ .ksp = INIT_SP, \
++ .ksp_limit = INIT_SP_LIMIT, \
+ .fs = KERNEL_DS, \
+ .pgdir = swapper_pg_dir, \
+ .fpexc_mode = MSR_FE0 | MSR_FE1, \
+@@ -194,6 +199,7 @@ struct thread_struct {
+ #else
+ #define INIT_THREAD { \
+ .ksp = INIT_SP, \
++ .ksp_limit = INIT_SP_LIMIT, \
+ .regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \
+ .fs = KERNEL_DS, \
+ .fpr = {0}, \
diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h
index 2b69367..9e8ed68 100644
--- a/include/asm-powerpc/ps3.h
@@ -788705,6 +1052844,30 @@
/* Structure that defines QE firmware binary files.
*
+diff --git a/include/asm-powerpc/rio.h b/include/asm-powerpc/rio.h
+new file mode 100644
+index 0000000..0018bf8
+--- /dev/null
++++ b/include/asm-powerpc/rio.h
+@@ -0,0 +1,18 @@
++/*
++ * RapidIO architecture support
++ *
++ * Copyright 2005 MontaVista Software, Inc.
++ * Matt Porter <mporter at kernel.crashing.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.
++ */
++
++#ifndef ASM_PPC_RIO_H
++#define ASM_PPC_RIO_H
++
++extern void platform_rio_init(void);
++
++#endif /* ASM_PPC_RIO_H */
diff --git a/include/asm-powerpc/rwsem.h b/include/asm-powerpc/rwsem.h
index cefc147..a6cc93b 100644
--- a/include/asm-powerpc/rwsem.h
@@ -788920,7 +1053083,7 @@
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
+index 29552ff..2b6559a 100644
--- a/include/asm-powerpc/system.h
+++ b/include/asm-powerpc/system.h
@@ -5,6 +5,7 @@
@@ -788931,6 +1053094,114 @@
#include <asm/hw_irq.h>
+@@ -203,7 +204,7 @@ extern int powersave_nap; /* set if nap mode can be used in idle loop */
+ * Changes the memory location '*ptr' to be val and returns
+ * the previous value stored there.
+ */
+-static __inline__ unsigned long
++static __always_inline unsigned long
+ __xchg_u32(volatile void *p, unsigned long val)
+ {
+ unsigned long prev;
+@@ -228,7 +229,7 @@ __xchg_u32(volatile void *p, unsigned long val)
+ * Changes the memory location '*ptr' to be val and returns
+ * the previous value stored there.
+ */
+-static __inline__ unsigned long
++static __always_inline unsigned long
+ __xchg_u32_local(volatile void *p, unsigned long val)
+ {
+ unsigned long prev;
+@@ -246,7 +247,7 @@ __xchg_u32_local(volatile void *p, unsigned long val)
+ }
+
+ #ifdef CONFIG_PPC64
+-static __inline__ unsigned long
++static __always_inline unsigned long
+ __xchg_u64(volatile void *p, unsigned long val)
+ {
+ unsigned long prev;
+@@ -265,7 +266,7 @@ __xchg_u64(volatile void *p, unsigned long val)
+ return prev;
+ }
+
+-static __inline__ unsigned long
++static __always_inline unsigned long
+ __xchg_u64_local(volatile void *p, unsigned long val)
+ {
+ unsigned long prev;
+@@ -289,7 +290,7 @@ __xchg_u64_local(volatile void *p, unsigned long val)
+ */
+ extern void __xchg_called_with_bad_pointer(void);
+
+-static __inline__ unsigned long
++static __always_inline unsigned long
+ __xchg(volatile void *ptr, unsigned long x, unsigned int size)
+ {
+ switch (size) {
+@@ -304,7 +305,7 @@ __xchg(volatile void *ptr, unsigned long x, unsigned int size)
+ return x;
+ }
+
+-static __inline__ unsigned long
++static __always_inline unsigned long
+ __xchg_local(volatile void *ptr, unsigned long x, unsigned int size)
+ {
+ switch (size) {
+@@ -337,7 +338,7 @@ __xchg_local(volatile void *ptr, unsigned long x, unsigned int size)
+ */
+ #define __HAVE_ARCH_CMPXCHG 1
+
+-static __inline__ unsigned long
++static __always_inline unsigned long
+ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
+ {
+ unsigned int prev;
+@@ -360,7 +361,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
+ return prev;
+ }
+
+-static __inline__ unsigned long
++static __always_inline unsigned long
+ __cmpxchg_u32_local(volatile unsigned int *p, unsigned long old,
+ unsigned long new)
+ {
+@@ -383,7 +384,7 @@ __cmpxchg_u32_local(volatile unsigned int *p, unsigned long old,
+ }
+
+ #ifdef CONFIG_PPC64
+-static __inline__ unsigned long
++static __always_inline unsigned long
+ __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
+ {
+ unsigned long prev;
+@@ -405,7 +406,7 @@ __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
+ return prev;
+ }
+
+-static __inline__ unsigned long
++static __always_inline unsigned long
+ __cmpxchg_u64_local(volatile unsigned long *p, unsigned long old,
+ unsigned long new)
+ {
+@@ -431,7 +432,7 @@ __cmpxchg_u64_local(volatile unsigned long *p, unsigned long old,
+ if something tries to do an invalid cmpxchg(). */
+ extern void __cmpxchg_called_with_bad_pointer(void);
+
+-static __inline__ unsigned long
++static __always_inline unsigned long
+ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
+ unsigned int size)
+ {
+@@ -447,7 +448,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
+ return old;
+ }
+
+-static __inline__ unsigned long
++static __always_inline unsigned long
+ __cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
+ unsigned int size)
+ {
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
@@ -788985,6 +1053256,30 @@
#ifdef __powerpc64__
typedef u64 dma_addr_t;
#else
+diff --git a/include/asm-powerpc/unaligned.h b/include/asm-powerpc/unaligned.h
+index 6c95dfa..5f1b1e3 100644
+--- a/include/asm-powerpc/unaligned.h
++++ b/include/asm-powerpc/unaligned.h
+@@ -5,15 +5,12 @@
+
+ /*
+ * The PowerPC can do unaligned accesses itself in big endian mode.
+- *
+- * The strange macros are there to make sure these can't
+- * be misused in a way that makes them not work on other
+- * architectures where unaligned accesses aren't as simple.
+ */
++#include <linux/unaligned/access_ok.h>
++#include <linux/unaligned/generic.h>
+
+-#define get_unaligned(ptr) (*(ptr))
+-
+-#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
++#define get_unaligned __get_unaligned_be
++#define put_unaligned __put_unaligned_be
+
+ #endif /* __KERNEL__ */
+ #endif /* _ASM_POWERPC_UNALIGNED_H */
diff --git a/include/asm-ppc/mmu.h b/include/asm-ppc/mmu.h
index d46b57b..d76ef09 100644
--- a/include/asm-ppc/mmu.h
@@ -789042,6 +1053337,93 @@
#ifdef CONFIG_PPC_OCP
+diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
+index 70435d3..55f9d38 100644
+--- a/include/asm-ppc/pgtable.h
++++ b/include/asm-ppc/pgtable.h
+@@ -483,6 +483,7 @@ static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
+ 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_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
++static inline int pte_special(pte_t pte) { return 0; }
+
+ static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
+ static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; }
+@@ -500,6 +501,8 @@ static inline pte_t pte_mkdirty(pte_t pte) {
+ pte_val(pte) |= _PAGE_DIRTY; return pte; }
+ static inline pte_t pte_mkyoung(pte_t pte) {
+ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
++static inline pte_t pte_mkspecial(pte_t pte) {
++ return pte; }
+
+ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+ {
+diff --git a/include/asm-ppc/rio.h b/include/asm-ppc/rio.h
+deleted file mode 100644
+index 0018bf8..0000000
+--- a/include/asm-ppc/rio.h
++++ /dev/null
+@@ -1,18 +0,0 @@
+-/*
+- * RapidIO architecture support
+- *
+- * Copyright 2005 MontaVista Software, Inc.
+- * Matt Porter <mporter at kernel.crashing.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.
+- */
+-
+-#ifndef ASM_PPC_RIO_H
+-#define ASM_PPC_RIO_H
+-
+-extern void platform_rio_init(void);
+-
+-#endif /* ASM_PPC_RIO_H */
+diff --git a/include/asm-s390/Kbuild b/include/asm-s390/Kbuild
+index e92b429..13c9805 100644
+--- a/include/asm-s390/Kbuild
++++ b/include/asm-s390/Kbuild
+@@ -7,6 +7,7 @@ header-y += tape390.h
+ header-y += ucontext.h
+ header-y += vtoc.h
+ header-y += zcrypt.h
++header-y += kvm.h
+
+ unifdef-y += cmb.h
+ unifdef-y += debug.h
+diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h
+index 965394e..b4eb24a 100644
+--- a/include/asm-s390/bitops.h
++++ b/include/asm-s390/bitops.h
+@@ -769,6 +769,7 @@ static inline int sched_find_first_bit(unsigned long *b)
+ }
+
+ #include <asm-generic/bitops/fls.h>
++#include <asm-generic/bitops/__fls.h>
+ #include <asm-generic/bitops/fls64.h>
+
+ #include <asm-generic/bitops/hweight.h>
+diff --git a/include/asm-s390/ccwgroup.h b/include/asm-s390/ccwgroup.h
+index 289053e..a27f689 100644
+--- a/include/asm-s390/ccwgroup.h
++++ b/include/asm-s390/ccwgroup.h
+@@ -57,10 +57,9 @@ struct ccwgroup_driver {
+
+ extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver);
+ extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver);
+-extern int ccwgroup_create (struct device *root,
+- unsigned int creator_id,
+- struct ccw_driver *gdrv,
+- int argc, char *argv[]);
++int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
++ struct ccw_driver *cdrv, int num_devices,
++ const char *buf);
+
+ extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev);
+ extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev);
diff --git a/include/asm-s390/cio.h b/include/asm-s390/cio.h
index 123b557..0818ecd 100644
--- a/include/asm-s390/cio.h
@@ -789131,8 +1053513,703 @@
+void clock_comparator_work(void);
#endif /* __ASM_HARDIRQ_H */
+diff --git a/include/asm-s390/hugetlb.h b/include/asm-s390/hugetlb.h
+new file mode 100644
+index 0000000..600a776
+--- /dev/null
++++ b/include/asm-s390/hugetlb.h
+@@ -0,0 +1,183 @@
++/*
++ * IBM System z Huge TLB Page Support for Kernel.
++ *
++ * Copyright IBM Corp. 2008
++ * Author(s): Gerald Schaefer <gerald.schaefer at de.ibm.com>
++ */
++
++#ifndef _ASM_S390_HUGETLB_H
++#define _ASM_S390_HUGETLB_H
++
++#include <asm/page.h>
++#include <asm/pgtable.h>
++
++
++#define is_hugepage_only_range(mm, addr, len) 0
++#define hugetlb_free_pgd_range free_pgd_range
++
++void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
++ pte_t *ptep, pte_t pte);
++
++/*
++ * If the arch doesn't supply something else, assume that hugepage
++ * size aligned regions are ok without further preparation.
++ */
++static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
++{
++ if (len & ~HPAGE_MASK)
++ return -EINVAL;
++ if (addr & ~HPAGE_MASK)
++ return -EINVAL;
++ return 0;
++}
++
++#define hugetlb_prefault_arch_hook(mm) do { } while (0)
++
++int arch_prepare_hugepage(struct page *page);
++void arch_release_hugepage(struct page *page);
++
++static inline pte_t pte_mkhuge(pte_t pte)
++{
++ /*
++ * PROT_NONE needs to be remapped from the pte type to the ste type.
++ * The HW invalid bit is also different for pte and ste. The pte
++ * invalid bit happens to be the same as the ste _SEGMENT_ENTRY_LARGE
++ * bit, so we don't have to clear it.
++ */
++ if (pte_val(pte) & _PAGE_INVALID) {
++ if (pte_val(pte) & _PAGE_SWT)
++ pte_val(pte) |= _HPAGE_TYPE_NONE;
++ pte_val(pte) |= _SEGMENT_ENTRY_INV;
++ }
++ /*
++ * Clear SW pte bits SWT and SWX, there are no SW bits in a segment
++ * table entry.
++ */
++ pte_val(pte) &= ~(_PAGE_SWT | _PAGE_SWX);
++ /*
++ * Also set the change-override bit because we don't need dirty bit
++ * tracking for hugetlbfs pages.
++ */
++ pte_val(pte) |= (_SEGMENT_ENTRY_LARGE | _SEGMENT_ENTRY_CO);
++ return pte;
++}
++
++static inline pte_t huge_pte_wrprotect(pte_t pte)
++{
++ pte_val(pte) |= _PAGE_RO;
++ return pte;
++}
++
++static inline int huge_pte_none(pte_t pte)
++{
++ return (pte_val(pte) & _SEGMENT_ENTRY_INV) &&
++ !(pte_val(pte) & _SEGMENT_ENTRY_RO);
++}
++
++static inline pte_t huge_ptep_get(pte_t *ptep)
++{
++ pte_t pte = *ptep;
++ unsigned long mask;
++
++ if (!MACHINE_HAS_HPAGE) {
++ ptep = (pte_t *) (pte_val(pte) & _SEGMENT_ENTRY_ORIGIN);
++ if (ptep) {
++ mask = pte_val(pte) &
++ (_SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO);
++ pte = pte_mkhuge(*ptep);
++ pte_val(pte) |= mask;
++ }
++ }
++ return pte;
++}
++
++static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
++ unsigned long addr, pte_t *ptep)
++{
++ pte_t pte = huge_ptep_get(ptep);
++
++ pmd_clear((pmd_t *) ptep);
++ return pte;
++}
++
++static inline void __pmd_csp(pmd_t *pmdp)
++{
++ register unsigned long reg2 asm("2") = pmd_val(*pmdp);
++ register unsigned long reg3 asm("3") = pmd_val(*pmdp) |
++ _SEGMENT_ENTRY_INV;
++ register unsigned long reg4 asm("4") = ((unsigned long) pmdp) + 5;
++
++ asm volatile(
++ " csp %1,%3"
++ : "=m" (*pmdp)
++ : "d" (reg2), "d" (reg3), "d" (reg4), "m" (*pmdp) : "cc");
++ pmd_val(*pmdp) = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY;
++}
++
++static inline void __pmd_idte(unsigned long address, pmd_t *pmdp)
++{
++ unsigned long sto = (unsigned long) pmdp -
++ pmd_index(address) * sizeof(pmd_t);
++
++ if (!(pmd_val(*pmdp) & _SEGMENT_ENTRY_INV)) {
++ asm volatile(
++ " .insn rrf,0xb98e0000,%2,%3,0,0"
++ : "=m" (*pmdp)
++ : "m" (*pmdp), "a" (sto),
++ "a" ((address & HPAGE_MASK))
++ );
++ }
++ pmd_val(*pmdp) = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY;
++}
++
++static inline void huge_ptep_invalidate(struct mm_struct *mm,
++ unsigned long address, pte_t *ptep)
++{
++ pmd_t *pmdp = (pmd_t *) ptep;
++
++ if (!MACHINE_HAS_IDTE) {
++ __pmd_csp(pmdp);
++ if (mm->context.noexec) {
++ pmdp = get_shadow_table(pmdp);
++ __pmd_csp(pmdp);
++ }
++ return;
++ }
++
++ __pmd_idte(address, pmdp);
++ if (mm->context.noexec) {
++ pmdp = get_shadow_table(pmdp);
++ __pmd_idte(address, pmdp);
++ }
++ return;
++}
++
++#define huge_ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \
++({ \
++ int __changed = !pte_same(huge_ptep_get(__ptep), __entry); \
++ if (__changed) { \
++ huge_ptep_invalidate((__vma)->vm_mm, __addr, __ptep); \
++ set_huge_pte_at((__vma)->vm_mm, __addr, __ptep, __entry); \
++ } \
++ __changed; \
++})
++
++#define huge_ptep_set_wrprotect(__mm, __addr, __ptep) \
++({ \
++ pte_t __pte = huge_ptep_get(__ptep); \
++ if (pte_write(__pte)) { \
++ if (atomic_read(&(__mm)->mm_users) > 1 || \
++ (__mm) != current->active_mm) \
++ huge_ptep_invalidate(__mm, __addr, __ptep); \
++ set_huge_pte_at(__mm, __addr, __ptep, \
++ huge_pte_wrprotect(__pte)); \
++ } \
++})
++
++static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
++ unsigned long address, pte_t *ptep)
++{
++ huge_ptep_invalidate(vma->vm_mm, address, ptep);
++}
++
++#endif /* _ASM_S390_HUGETLB_H */
+diff --git a/include/asm-s390/kvm.h b/include/asm-s390/kvm.h
+index 573f2a3..d74002f 100644
+--- a/include/asm-s390/kvm.h
++++ b/include/asm-s390/kvm.h
+@@ -1,6 +1,45 @@
+ #ifndef __LINUX_KVM_S390_H
+ #define __LINUX_KVM_S390_H
+
+-/* s390 does not support KVM */
++/*
++ * asm-s390/kvm.h - KVM s390 specific structures and definitions
++ *
++ * Copyright IBM Corp. 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): Carsten Otte <cotte at de.ibm.com>
++ * Christian Borntraeger <borntraeger at de.ibm.com>
++ */
++#include <asm/types.h>
++
++/* for KVM_GET_IRQCHIP and KVM_SET_IRQCHIP */
++struct kvm_pic_state {
++ /* no PIC for s390 */
++};
++
++struct kvm_ioapic_state {
++ /* no IOAPIC for s390 */
++};
++
++/* for KVM_GET_REGS and KVM_SET_REGS */
++struct kvm_regs {
++ /* general purpose regs for s390 */
++ __u64 gprs[16];
++};
++
++/* for KVM_GET_SREGS and KVM_SET_SREGS */
++struct kvm_sregs {
++ __u32 acrs[16];
++ __u64 crs[16];
++};
++
++/* for KVM_GET_FPU and KVM_SET_FPU */
++struct kvm_fpu {
++ __u32 fpc;
++ __u64 fprs[16];
++};
+
+ #endif
+diff --git a/include/asm-s390/kvm_host.h b/include/asm-s390/kvm_host.h
+new file mode 100644
+index 0000000..f8204a4
+--- /dev/null
++++ b/include/asm-s390/kvm_host.h
+@@ -0,0 +1,234 @@
++/*
++ * asm-s390/kvm_host.h - definition for kernel virtual machines on s390
++ *
++ * Copyright IBM Corp. 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): Carsten Otte <cotte at de.ibm.com>
++ */
++
++
++#ifndef ASM_KVM_HOST_H
++#define ASM_KVM_HOST_H
++#include <linux/kvm_host.h>
++#include <asm/debug.h>
++
++#define KVM_MAX_VCPUS 64
++#define KVM_MEMORY_SLOTS 32
++/* memory slots that does not exposed to userspace */
++#define KVM_PRIVATE_MEM_SLOTS 4
++
++struct kvm_guest_debug {
++};
++
++struct sca_entry {
++ atomic_t scn;
++ __u64 reserved;
++ __u64 sda;
++ __u64 reserved2[2];
++} __attribute__((packed));
++
++
++struct sca_block {
++ __u64 ipte_control;
++ __u64 reserved[5];
++ __u64 mcn;
++ __u64 reserved2;
++ struct sca_entry cpu[64];
++} __attribute__((packed));
++
++#define KVM_PAGES_PER_HPAGE 256
++
++#define CPUSTAT_HOST 0x80000000
++#define CPUSTAT_WAIT 0x10000000
++#define CPUSTAT_ECALL_PEND 0x08000000
++#define CPUSTAT_STOP_INT 0x04000000
++#define CPUSTAT_IO_INT 0x02000000
++#define CPUSTAT_EXT_INT 0x01000000
++#define CPUSTAT_RUNNING 0x00800000
++#define CPUSTAT_RETAINED 0x00400000
++#define CPUSTAT_TIMING_SUB 0x00020000
++#define CPUSTAT_SIE_SUB 0x00010000
++#define CPUSTAT_RRF 0x00008000
++#define CPUSTAT_SLSV 0x00004000
++#define CPUSTAT_SLSR 0x00002000
++#define CPUSTAT_ZARCH 0x00000800
++#define CPUSTAT_MCDS 0x00000100
++#define CPUSTAT_SM 0x00000080
++#define CPUSTAT_G 0x00000008
++#define CPUSTAT_J 0x00000002
++#define CPUSTAT_P 0x00000001
++
++struct sie_block {
++ atomic_t cpuflags; /* 0x0000 */
++ __u32 prefix; /* 0x0004 */
++ __u8 reserved8[32]; /* 0x0008 */
++ __u64 cputm; /* 0x0028 */
++ __u64 ckc; /* 0x0030 */
++ __u64 epoch; /* 0x0038 */
++ __u8 reserved40[4]; /* 0x0040 */
++#define LCTL_CR0 0x8000
++ __u16 lctl; /* 0x0044 */
++ __s16 icpua; /* 0x0046 */
++ __u32 ictl; /* 0x0048 */
++ __u32 eca; /* 0x004c */
++ __u8 icptcode; /* 0x0050 */
++ __u8 reserved51; /* 0x0051 */
++ __u16 ihcpu; /* 0x0052 */
++ __u8 reserved54[2]; /* 0x0054 */
++ __u16 ipa; /* 0x0056 */
++ __u32 ipb; /* 0x0058 */
++ __u32 scaoh; /* 0x005c */
++ __u8 reserved60; /* 0x0060 */
++ __u8 ecb; /* 0x0061 */
++ __u8 reserved62[2]; /* 0x0062 */
++ __u32 scaol; /* 0x0064 */
++ __u8 reserved68[4]; /* 0x0068 */
++ __u32 todpr; /* 0x006c */
++ __u8 reserved70[16]; /* 0x0070 */
++ __u64 gmsor; /* 0x0080 */
++ __u64 gmslm; /* 0x0088 */
++ psw_t gpsw; /* 0x0090 */
++ __u64 gg14; /* 0x00a0 */
++ __u64 gg15; /* 0x00a8 */
++ __u8 reservedb0[30]; /* 0x00b0 */
++ __u16 iprcc; /* 0x00ce */
++ __u8 reservedd0[48]; /* 0x00d0 */
++ __u64 gcr[16]; /* 0x0100 */
++ __u64 gbea; /* 0x0180 */
++ __u8 reserved188[120]; /* 0x0188 */
++} __attribute__((packed));
++
++struct kvm_vcpu_stat {
++ u32 exit_userspace;
++ u32 exit_external_request;
++ u32 exit_external_interrupt;
++ u32 exit_stop_request;
++ u32 exit_validity;
++ u32 exit_instruction;
++ u32 instruction_lctl;
++ u32 instruction_lctg;
++ u32 exit_program_interruption;
++ u32 exit_instr_and_program;
++ u32 deliver_emergency_signal;
++ u32 deliver_service_signal;
++ u32 deliver_virtio_interrupt;
++ u32 deliver_stop_signal;
++ u32 deliver_prefix_signal;
++ u32 deliver_restart_signal;
++ u32 deliver_program_int;
++ u32 exit_wait_state;
++ u32 instruction_stidp;
++ u32 instruction_spx;
++ u32 instruction_stpx;
++ u32 instruction_stap;
++ u32 instruction_storage_key;
++ u32 instruction_stsch;
++ u32 instruction_chsc;
++ u32 instruction_stsi;
++ u32 instruction_stfl;
++ u32 instruction_sigp_sense;
++ u32 instruction_sigp_emergency;
++ u32 instruction_sigp_stop;
++ u32 instruction_sigp_arch;
++ u32 instruction_sigp_prefix;
++ u32 instruction_sigp_restart;
++ u32 diagnose_44;
++};
++
++struct io_info {
++ __u16 subchannel_id; /* 0x0b8 */
++ __u16 subchannel_nr; /* 0x0ba */
++ __u32 io_int_parm; /* 0x0bc */
++ __u32 io_int_word; /* 0x0c0 */
++};
++
++struct ext_info {
++ __u32 ext_params;
++ __u64 ext_params2;
++};
++
++#define PGM_OPERATION 0x01
++#define PGM_PRIVILEGED_OPERATION 0x02
++#define PGM_EXECUTE 0x03
++#define PGM_PROTECTION 0x04
++#define PGM_ADDRESSING 0x05
++#define PGM_SPECIFICATION 0x06
++#define PGM_DATA 0x07
++
++struct pgm_info {
++ __u16 code;
++};
++
++struct prefix_info {
++ __u32 address;
++};
++
++struct interrupt_info {
++ struct list_head list;
++ u64 type;
++ union {
++ struct io_info io;
++ struct ext_info ext;
++ struct pgm_info pgm;
++ struct prefix_info prefix;
++ };
++};
++
++/* for local_interrupt.action_flags */
++#define ACTION_STORE_ON_STOP 1
++#define ACTION_STOP_ON_STOP 2
++
++struct local_interrupt {
++ spinlock_t lock;
++ struct list_head list;
++ atomic_t active;
++ struct float_interrupt *float_int;
++ int timer_due; /* event indicator for waitqueue below */
++ wait_queue_head_t wq;
++ atomic_t *cpuflags;
++ unsigned int action_bits;
++};
++
++struct float_interrupt {
++ spinlock_t lock;
++ struct list_head list;
++ atomic_t active;
++ int next_rr_cpu;
++ unsigned long idle_mask [(64 + sizeof(long) - 1) / sizeof(long)];
++ struct local_interrupt *local_int[64];
++};
++
++
++struct kvm_vcpu_arch {
++ struct sie_block *sie_block;
++ unsigned long guest_gprs[16];
++ s390_fp_regs host_fpregs;
++ unsigned int host_acrs[NUM_ACRS];
++ s390_fp_regs guest_fpregs;
++ unsigned int guest_acrs[NUM_ACRS];
++ struct local_interrupt local_int;
++ struct timer_list ckc_timer;
++ union {
++ cpuid_t cpu_id;
++ u64 stidp_data;
++ };
++};
++
++struct kvm_vm_stat {
++ u32 remote_tlb_flush;
++};
++
++struct kvm_arch{
++ unsigned long guest_origin;
++ unsigned long guest_memsize;
++ struct sca_block *sca;
++ debug_info_t *dbf;
++ struct float_interrupt float_int;
++};
++
++extern int sie64a(struct sie_block *, __u64 *);
++#endif
+diff --git a/include/asm-s390/kvm_para.h b/include/asm-s390/kvm_para.h
+new file mode 100644
+index 0000000..2c50379
+--- /dev/null
++++ b/include/asm-s390/kvm_para.h
+@@ -0,0 +1,150 @@
++/*
++ * asm-s390/kvm_para.h - definition for paravirtual devices on s390
++ *
++ * Copyright IBM Corp. 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): Christian Borntraeger <borntraeger at de.ibm.com>
++ */
++
++#ifndef __S390_KVM_PARA_H
++#define __S390_KVM_PARA_H
++
++/*
++ * Hypercalls for KVM on s390. The calling convention is similar to the
++ * s390 ABI, so we use R2-R6 for parameters 1-5. In addition we use R1
++ * as hypercall number and R7 as parameter 6. The return value is
++ * written to R2. We use the diagnose instruction as hypercall. To avoid
++ * conflicts with existing diagnoses for LPAR and z/VM, we do not use
++ * the instruction encoded number, but specify the number in R1 and
++ * use 0x500 as KVM hypercall
++ *
++ * Copyright IBM Corp. 2007,2008
++ * Author(s): Christian Borntraeger <borntraeger at de.ibm.com>
++ *
++ * This work is licensed under the terms of the GNU GPL, version 2.
++ */
++
++static inline long kvm_hypercall0(unsigned long nr)
++{
++ register unsigned long __nr asm("1") = nr;
++ register long __rc asm("2");
++
++ asm volatile ("diag 2,4,0x500\n"
++ : "=d" (__rc) : "d" (__nr): "memory", "cc");
++ return __rc;
++}
++
++static inline long kvm_hypercall1(unsigned long nr, unsigned long p1)
++{
++ register unsigned long __nr asm("1") = nr;
++ register unsigned long __p1 asm("2") = p1;
++ register long __rc asm("2");
++
++ asm volatile ("diag 2,4,0x500\n"
++ : "=d" (__rc) : "d" (__nr), "0" (__p1) : "memory", "cc");
++ return __rc;
++}
++
++static inline long kvm_hypercall2(unsigned long nr, unsigned long p1,
++ unsigned long p2)
++{
++ register unsigned long __nr asm("1") = nr;
++ register unsigned long __p1 asm("2") = p1;
++ register unsigned long __p2 asm("3") = p2;
++ register long __rc asm("2");
++
++ asm volatile ("diag 2,4,0x500\n"
++ : "=d" (__rc) : "d" (__nr), "0" (__p1), "d" (__p2)
++ : "memory", "cc");
++ return __rc;
++}
++
++static inline long kvm_hypercall3(unsigned long nr, unsigned long p1,
++ unsigned long p2, unsigned long p3)
++{
++ register unsigned long __nr asm("1") = nr;
++ register unsigned long __p1 asm("2") = p1;
++ register unsigned long __p2 asm("3") = p2;
++ register unsigned long __p3 asm("4") = p3;
++ register long __rc asm("2");
++
++ asm volatile ("diag 2,4,0x500\n"
++ : "=d" (__rc) : "d" (__nr), "0" (__p1), "d" (__p2),
++ "d" (__p3) : "memory", "cc");
++ return __rc;
++}
++
++
++static inline long kvm_hypercall4(unsigned long nr, unsigned long p1,
++ unsigned long p2, unsigned long p3,
++ unsigned long p4)
++{
++ register unsigned long __nr asm("1") = nr;
++ register unsigned long __p1 asm("2") = p1;
++ register unsigned long __p2 asm("3") = p2;
++ register unsigned long __p3 asm("4") = p3;
++ register unsigned long __p4 asm("5") = p4;
++ register long __rc asm("2");
++
++ asm volatile ("diag 2,4,0x500\n"
++ : "=d" (__rc) : "d" (__nr), "0" (__p1), "d" (__p2),
++ "d" (__p3), "d" (__p4) : "memory", "cc");
++ return __rc;
++}
++
++static inline long kvm_hypercall5(unsigned long nr, unsigned long p1,
++ unsigned long p2, unsigned long p3,
++ unsigned long p4, unsigned long p5)
++{
++ register unsigned long __nr asm("1") = nr;
++ register unsigned long __p1 asm("2") = p1;
++ register unsigned long __p2 asm("3") = p2;
++ register unsigned long __p3 asm("4") = p3;
++ register unsigned long __p4 asm("5") = p4;
++ register unsigned long __p5 asm("6") = p5;
++ register long __rc asm("2");
++
++ asm volatile ("diag 2,4,0x500\n"
++ : "=d" (__rc) : "d" (__nr), "0" (__p1), "d" (__p2),
++ "d" (__p3), "d" (__p4), "d" (__p5) : "memory", "cc");
++ return __rc;
++}
++
++static inline long kvm_hypercall6(unsigned long nr, unsigned long p1,
++ unsigned long p2, unsigned long p3,
++ unsigned long p4, unsigned long p5,
++ unsigned long p6)
++{
++ register unsigned long __nr asm("1") = nr;
++ register unsigned long __p1 asm("2") = p1;
++ register unsigned long __p2 asm("3") = p2;
++ register unsigned long __p3 asm("4") = p3;
++ register unsigned long __p4 asm("5") = p4;
++ register unsigned long __p5 asm("6") = p5;
++ register unsigned long __p6 asm("7") = p6;
++ register long __rc asm("2");
++
++ asm volatile ("diag 2,4,0x500\n"
++ : "=d" (__rc) : "d" (__nr), "0" (__p1), "d" (__p2),
++ "d" (__p3), "d" (__p4), "d" (__p5), "d" (__p6)
++ : "memory", "cc");
++ return __rc;
++}
++
++/* kvm on s390 is always paravirtualization enabled */
++static inline int kvm_para_available(void)
++{
++ return 1;
++}
++
++/* No feature bits are currently assigned for kvm on s390 */
++static inline unsigned int kvm_arch_para_features(void)
++{
++ return 0;
++}
++
++#endif /* __S390_KVM_PARA_H */
+diff --git a/include/asm-s390/kvm_virtio.h b/include/asm-s390/kvm_virtio.h
+new file mode 100644
+index 0000000..5c871a9
+--- /dev/null
++++ b/include/asm-s390/kvm_virtio.h
+@@ -0,0 +1,53 @@
++/*
++ * kvm_virtio.h - definition for virtio for kvm on s390
++ *
++ * Copyright IBM Corp. 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): Christian Borntraeger <borntraeger at de.ibm.com>
++ */
++
++#ifndef __KVM_S390_VIRTIO_H
++#define __KVM_S390_VIRTIO_H
++
++#include <linux/types.h>
++
++struct kvm_device_desc {
++ /* The device type: console, network, disk etc. Type 0 terminates. */
++ __u8 type;
++ /* The number of virtqueues (first in config array) */
++ __u8 num_vq;
++ /*
++ * The number of bytes of feature bits. Multiply by 2: one for host
++ * features and one for guest acknowledgements.
++ */
++ __u8 feature_len;
++ /* The number of bytes of the config array after virtqueues. */
++ __u8 config_len;
++ /* A status byte, written by the Guest. */
++ __u8 status;
++ __u8 config[0];
++};
++
++/*
++ * This is how we expect the device configuration field for a virtqueue
++ * to be laid out in config space.
++ */
++struct kvm_vqconfig {
++ /* The token returned with an interrupt. Set by the guest */
++ __u64 token;
++ /* The address of the virtio ring */
++ __u64 address;
++ /* The number of entries in the virtio_ring */
++ __u16 num;
++
++};
++
++#define KVM_S390_VIRTIO_NOTIFY 0
++#define KVM_S390_VIRTIO_RESET 1
++#define KVM_S390_VIRTIO_SET_STATUS 2
++
++#endif
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
-index 801a6fd..5de3efb 100644
+index 801a6fd..0bc51d5 100644
--- a/include/asm-s390/lowcore.h
+++ b/include/asm-s390/lowcore.h
@@ -56,6 +56,8 @@
@@ -789184,24 +1054261,421 @@
__u64 int_clock; /* 0xde8 */
__u8 pad12[0xe00-0xdf0]; /* 0xdf0 */
+@@ -380,27 +381,32 @@ struct _lowcore
+ /* whether the kernel died with panic() or not */
+ __u32 panic_magic; /* 0xe00 */
+
+- __u8 pad13[0x1200-0xe04]; /* 0xe04 */
++ __u8 pad13[0x11b8-0xe04]; /* 0xe04 */
++
++ /* 64 bit extparam used for pfault, diag 250 etc */
++ __u64 ext_params2; /* 0x11B8 */
++
++ __u8 pad14[0x1200-0x11C0]; /* 0x11C0 */
+
+ /* System info area */
+
+ __u64 floating_pt_save_area[16]; /* 0x1200 */
+ __u64 gpregs_save_area[16]; /* 0x1280 */
+ __u32 st_status_fixed_logout[4]; /* 0x1300 */
+- __u8 pad14[0x1318-0x1310]; /* 0x1310 */
++ __u8 pad15[0x1318-0x1310]; /* 0x1310 */
+ __u32 prefixreg_save_area; /* 0x1318 */
+ __u32 fpt_creg_save_area; /* 0x131c */
+- __u8 pad15[0x1324-0x1320]; /* 0x1320 */
++ __u8 pad16[0x1324-0x1320]; /* 0x1320 */
+ __u32 tod_progreg_save_area; /* 0x1324 */
+ __u32 cpu_timer_save_area[2]; /* 0x1328 */
+ __u32 clock_comp_save_area[2]; /* 0x1330 */
+- __u8 pad16[0x1340-0x1338]; /* 0x1338 */
++ __u8 pad17[0x1340-0x1338]; /* 0x1338 */
+ __u32 access_regs_save_area[16]; /* 0x1340 */
+ __u64 cregs_save_area[16]; /* 0x1380 */
+
+ /* align to the top of the prefix area */
+
+- __u8 pad17[0x2000-0x1400]; /* 0x1400 */
++ __u8 pad18[0x2000-0x1400]; /* 0x1400 */
+ #endif /* !__s390x__ */
+ } __attribute__((packed)); /* End structure*/
+
+diff --git a/include/asm-s390/mmu.h b/include/asm-s390/mmu.h
+index 1698e29..5dd5e7b 100644
+--- a/include/asm-s390/mmu.h
++++ b/include/asm-s390/mmu.h
+@@ -7,6 +7,7 @@ typedef struct {
+ unsigned long asce_bits;
+ unsigned long asce_limit;
+ int noexec;
++ int pgstes;
+ } mm_context_t;
+
+ #endif
+diff --git a/include/asm-s390/mmu_context.h b/include/asm-s390/mmu_context.h
+index b5a34c6..4c2fbf4 100644
+--- a/include/asm-s390/mmu_context.h
++++ b/include/asm-s390/mmu_context.h
+@@ -20,7 +20,13 @@ static inline int init_new_context(struct task_struct *tsk,
+ #ifdef CONFIG_64BIT
+ mm->context.asce_bits |= _ASCE_TYPE_REGION3;
+ #endif
+- mm->context.noexec = s390_noexec;
++ if (current->mm->context.pgstes) {
++ mm->context.noexec = 0;
++ mm->context.pgstes = 1;
++ } else {
++ mm->context.noexec = s390_noexec;
++ mm->context.pgstes = 0;
++ }
+ mm->context.asce_limit = STACK_TOP_MAX;
+ crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm));
+ return 0;
+diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
+index fe7f92b..f0f4579 100644
+--- a/include/asm-s390/page.h
++++ b/include/asm-s390/page.h
+@@ -19,17 +19,34 @@
+ #define PAGE_DEFAULT_ACC 0
+ #define PAGE_DEFAULT_KEY (PAGE_DEFAULT_ACC << 4)
+
++#define HPAGE_SHIFT 20
++#define HPAGE_SIZE (1UL << HPAGE_SHIFT)
++#define HPAGE_MASK (~(HPAGE_SIZE - 1))
++#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
++
++#define ARCH_HAS_SETCLEAR_HUGE_PTE
++#define ARCH_HAS_HUGE_PTE_TYPE
++#define ARCH_HAS_PREPARE_HUGEPAGE
++#define ARCH_HAS_HUGEPAGE_CLEAR_FLUSH
++
+ #include <asm/setup.h>
+ #ifndef __ASSEMBLY__
+
+ static inline void clear_page(void *page)
+ {
+- register unsigned long reg1 asm ("1") = 0;
+- register void *reg2 asm ("2") = page;
+- register unsigned long reg3 asm ("3") = 4096;
+- asm volatile(
+- " mvcl 2,0"
+- : "+d" (reg2), "+d" (reg3) : "d" (reg1) : "memory", "cc");
++ if (MACHINE_HAS_PFMF) {
++ asm volatile(
++ " .insn rre,0xb9af0000,%0,%1"
++ : : "d" (0x10000), "a" (page) : "memory", "cc");
++ } else {
++ register unsigned long reg1 asm ("1") = 0;
++ register void *reg2 asm ("2") = page;
++ register unsigned long reg3 asm ("3") = 4096;
++ asm volatile(
++ " mvcl 2,0"
++ : "+d" (reg2), "+d" (reg3) : "d" (reg1)
++ : "memory", "cc");
++ }
+ }
+
+ static inline void copy_page(void *to, void *from)
+@@ -108,26 +125,6 @@ page_get_storage_key(unsigned long addr)
+ return skey;
+ }
+
+-extern unsigned long max_pfn;
+-
+-static inline int pfn_valid(unsigned long pfn)
+-{
+- unsigned long dummy;
+- int ccode;
+-
+- if (pfn >= max_pfn)
+- return 0;
+-
+- asm volatile(
+- " lra %0,0(%2)\n"
+- " ipm %1\n"
+- " srl %1,28\n"
+- : "=d" (dummy), "=d" (ccode)
+- : "a" (pfn << PAGE_SHIFT)
+- : "cc");
+- return !ccode;
+-}
+-
+ #endif /* !__ASSEMBLY__ */
+
+ /* to align the pointer to the (next) page boundary */
+diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
+index 65154dc..c7f4f8e 100644
+--- a/include/asm-s390/pgtable.h
++++ b/include/asm-s390/pgtable.h
+@@ -30,6 +30,7 @@
+ */
+ #ifndef __ASSEMBLY__
+ #include <linux/mm_types.h>
++#include <asm/bitops.h>
+ #include <asm/bug.h>
+ #include <asm/processor.h>
+
+@@ -128,7 +129,7 @@ extern char empty_zero_page[PAGE_SIZE];
+ #define VMEM_MAX_PAGES ((VMEM_MAP_END - VMALLOC_END) / sizeof(struct page))
+ #define VMEM_MAX_PFN min(VMALLOC_START >> PAGE_SHIFT, VMEM_MAX_PAGES)
+ #define VMEM_MAX_PHYS ((VMEM_MAX_PFN << PAGE_SHIFT) & ~((16 << 20) - 1))
+-#define VMEM_MAP ((struct page *) VMALLOC_END)
++#define vmemmap ((struct page *) VMALLOC_END)
+
+ /*
+ * A 31 bit pagetable entry of S390 has following format:
+@@ -219,6 +220,8 @@ extern char empty_zero_page[PAGE_SIZE];
+ /* Software bits in the page table entry */
+ #define _PAGE_SWT 0x001 /* SW pte type bit t */
+ #define _PAGE_SWX 0x002 /* SW pte type bit x */
++#define _PAGE_SPECIAL 0x004 /* SW associated with special page */
++#define __HAVE_ARCH_PTE_SPECIAL
+
+ /* Six different types of pages. */
+ #define _PAGE_TYPE_EMPTY 0x400
+@@ -231,6 +234,15 @@ extern char empty_zero_page[PAGE_SIZE];
+ #define _PAGE_TYPE_EX_RW 0x002
+
+ /*
++ * Only four types for huge pages, using the invalid bit and protection bit
++ * of a segment table entry.
++ */
++#define _HPAGE_TYPE_EMPTY 0x020 /* _SEGMENT_ENTRY_INV */
++#define _HPAGE_TYPE_NONE 0x220
++#define _HPAGE_TYPE_RO 0x200 /* _SEGMENT_ENTRY_RO */
++#define _HPAGE_TYPE_RW 0x000
++
++/*
+ * PTE type bits are rather complicated. handle_pte_fault uses pte_present,
+ * pte_none and pte_file to find out the pte type WITHOUT holding the page
+ * table lock. ptep_clear_flush on the other hand uses ptep_clear_flush to
+@@ -258,6 +270,13 @@ extern char empty_zero_page[PAGE_SIZE];
+ * swap pte is 1011 and 0001, 0011, 0101, 0111 are invalid.
+ */
+
++/* Page status table bits for virtualization */
++#define RCP_PCL_BIT 55
++#define RCP_HR_BIT 54
++#define RCP_HC_BIT 53
++#define RCP_GR_BIT 50
++#define RCP_GC_BIT 49
++
+ #ifndef __s390x__
+
+ /* Bits in the segment table address-space-control-element */
+@@ -315,6 +334,9 @@ extern char empty_zero_page[PAGE_SIZE];
+ #define _SEGMENT_ENTRY (0)
+ #define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INV)
+
++#define _SEGMENT_ENTRY_LARGE 0x400 /* STE-format control, large page */
++#define _SEGMENT_ENTRY_CO 0x100 /* change-recording override */
++
+ #endif /* __s390x__ */
+
+ /*
+@@ -510,9 +532,56 @@ static inline int pte_file(pte_t pte)
+ return (pte_val(pte) & mask) == _PAGE_TYPE_FILE;
+ }
+
++static inline int pte_special(pte_t pte)
++{
++ return (pte_val(pte) & _PAGE_SPECIAL);
++}
++
+ #define __HAVE_ARCH_PTE_SAME
+ #define pte_same(a,b) (pte_val(a) == pte_val(b))
+
++static inline void rcp_lock(pte_t *ptep)
++{
++#ifdef CONFIG_PGSTE
++ unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
++ preempt_disable();
++ while (test_and_set_bit(RCP_PCL_BIT, pgste))
++ ;
++#endif
++}
++
++static inline void rcp_unlock(pte_t *ptep)
++{
++#ifdef CONFIG_PGSTE
++ unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
++ clear_bit(RCP_PCL_BIT, pgste);
++ preempt_enable();
++#endif
++}
++
++/* forward declaration for SetPageUptodate in page-flags.h*/
++static inline void page_clear_dirty(struct page *page);
++#include <linux/page-flags.h>
++
++static inline void ptep_rcp_copy(pte_t *ptep)
++{
++#ifdef CONFIG_PGSTE
++ struct page *page = virt_to_page(pte_val(*ptep));
++ unsigned int skey;
++ unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
++
++ skey = page_get_storage_key(page_to_phys(page));
++ if (skey & _PAGE_CHANGED)
++ set_bit_simple(RCP_GC_BIT, pgste);
++ if (skey & _PAGE_REFERENCED)
++ set_bit_simple(RCP_GR_BIT, pgste);
++ if (test_and_clear_bit_simple(RCP_HC_BIT, pgste))
++ SetPageDirty(page);
++ if (test_and_clear_bit_simple(RCP_HR_BIT, pgste))
++ SetPageReferenced(page);
++#endif
++}
++
+ /*
+ * query functions pte_write/pte_dirty/pte_young only work if
+ * pte_present() is true. Undefined behaviour if not..
+@@ -599,6 +668,8 @@ static inline void pmd_clear(pmd_t *pmd)
+
+ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+ {
++ if (mm->context.pgstes)
++ ptep_rcp_copy(ptep);
+ pte_val(*ptep) = _PAGE_TYPE_EMPTY;
+ if (mm->context.noexec)
+ pte_val(ptep[PTRS_PER_PTE]) = _PAGE_TYPE_EMPTY;
+@@ -663,10 +734,34 @@ static inline pte_t pte_mkyoung(pte_t pte)
+ return pte;
+ }
+
++static inline pte_t pte_mkspecial(pte_t pte)
++{
++ pte_val(pte) |= _PAGE_SPECIAL;
++ return pte;
++}
++
+ #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep)
+ {
++#ifdef CONFIG_PGSTE
++ unsigned long physpage;
++ int young;
++ unsigned long *pgste;
++
++ if (!vma->vm_mm->context.pgstes)
++ return 0;
++ physpage = pte_val(*ptep) & PAGE_MASK;
++ pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
++
++ young = ((page_get_storage_key(physpage) & _PAGE_REFERENCED) != 0);
++ rcp_lock(ptep);
++ if (young)
++ set_bit_simple(RCP_GR_BIT, pgste);
++ young |= test_and_clear_bit_simple(RCP_HR_BIT, pgste);
++ rcp_unlock(ptep);
++ return young;
++#endif
+ return 0;
+ }
+
+@@ -674,7 +769,13 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
+ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
+ unsigned long address, pte_t *ptep)
+ {
+- /* No need to flush TLB; bits are in storage key */
++ /* No need to flush TLB
++ * On s390 reference bits are in storage key and never in TLB
++ * With virtualization we handle the reference bit, without we
++ * we can simply return */
++#ifdef CONFIG_PGSTE
++ return ptep_test_and_clear_young(vma, address, ptep);
++#endif
+ return 0;
+ }
+
+@@ -693,15 +794,25 @@ static inline void __ptep_ipte(unsigned long address, pte_t *ptep)
+ : "=m" (*ptep) : "m" (*ptep),
+ "a" (pto), "a" (address));
+ }
+- pte_val(*ptep) = _PAGE_TYPE_EMPTY;
+ }
+
+ static inline void ptep_invalidate(struct mm_struct *mm,
+ unsigned long address, pte_t *ptep)
+ {
++ if (mm->context.pgstes) {
++ rcp_lock(ptep);
++ __ptep_ipte(address, ptep);
++ ptep_rcp_copy(ptep);
++ pte_val(*ptep) = _PAGE_TYPE_EMPTY;
++ rcp_unlock(ptep);
++ return;
++ }
+ __ptep_ipte(address, ptep);
+- if (mm->context.noexec)
++ pte_val(*ptep) = _PAGE_TYPE_EMPTY;
++ if (mm->context.noexec) {
+ __ptep_ipte(address, ptep + PTRS_PER_PTE);
++ pte_val(*(ptep + PTRS_PER_PTE)) = _PAGE_TYPE_EMPTY;
++ }
+ }
+
+ /*
+@@ -964,17 +1075,15 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
+
+ #define kern_addr_valid(addr) (1)
+
+-extern int add_shared_memory(unsigned long start, unsigned long size);
+-extern int remove_shared_memory(unsigned long start, unsigned long size);
++extern int vmem_add_mapping(unsigned long start, unsigned long size);
++extern int vmem_remove_mapping(unsigned long start, unsigned long size);
++extern int s390_enable_sie(void);
+
+ /*
+ * No page table caches to initialise
+ */
+ #define pgtable_cache_init() do { } while (0)
+
+-#define __HAVE_ARCH_MEMMAP_INIT
+-extern void memmap_init(unsigned long, int, unsigned long, unsigned long);
+-
+ #include <asm-generic/pgtable.h>
+
+ #endif /* _S390_PAGE_H */
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
-index 51d8891..8eaf343 100644
+index 51d8891..a00f79d 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);
+@@ -172,9 +172,7 @@ extern unsigned long thread_saved_pc(struct task_struct *t);
+ */
+ 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
+-extern void show_trace(struct task_struct *task, unsigned long *sp);
unsigned long get_wchan(struct task_struct *p);
#define task_pt_regs(tsk) ((struct pt_regs *) \
+diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
+index 61f6952..441d7c2 100644
+--- a/include/asm-s390/ptrace.h
++++ b/include/asm-s390/ptrace.h
+@@ -463,8 +463,6 @@ struct user_regs_struct
+ };
+
+ #ifdef __KERNEL__
+-#define __ARCH_SYS_PTRACE 1
+-
+ /*
+ * These are defined as per linux/ptrace.h, which see.
+ */
+diff --git a/include/asm-s390/qdio.h b/include/asm-s390/qdio.h
+index 4b8ff55..1124034 100644
+--- a/include/asm-s390/qdio.h
++++ b/include/asm-s390/qdio.h
+@@ -127,6 +127,7 @@ extern int do_QDIO(struct ccw_device*, unsigned int flags,
+ unsigned int qidx,unsigned int count,
+ struct qdio_buffer *buffers);
+
++extern int qdio_get_ssqd_pct(struct ccw_device*);
+ extern int qdio_synchronize(struct ccw_device*, unsigned int flags,
+ unsigned int queue_number);
+
diff --git a/include/asm-s390/semaphore.h b/include/asm-s390/semaphore.h
index 0e7001a..d9b2034 100644
--- a/include/asm-s390/semaphore.h
@@ -789315,11 +1054789,87 @@
-
-#endif
+#include <linux/semaphore.h>
+diff --git a/include/asm-s390/setup.h b/include/asm-s390/setup.h
+index a76a6b8..ba69674 100644
+--- a/include/asm-s390/setup.h
++++ b/include/asm-s390/setup.h
+@@ -59,22 +59,42 @@ extern unsigned int s390_noexec;
+ */
+ extern unsigned long machine_flags;
+
+-#define MACHINE_IS_VM (machine_flags & 1)
+-#define MACHINE_IS_P390 (machine_flags & 4)
+-#define MACHINE_HAS_MVPG (machine_flags & 16)
+-#define MACHINE_HAS_IDTE (machine_flags & 128)
+-#define MACHINE_HAS_DIAG9C (machine_flags & 256)
++#define MACHINE_FLAG_VM (1UL << 0)
++#define MACHINE_FLAG_IEEE (1UL << 1)
++#define MACHINE_FLAG_P390 (1UL << 2)
++#define MACHINE_FLAG_CSP (1UL << 3)
++#define MACHINE_FLAG_MVPG (1UL << 4)
++#define MACHINE_FLAG_DIAG44 (1UL << 5)
++#define MACHINE_FLAG_IDTE (1UL << 6)
++#define MACHINE_FLAG_DIAG9C (1UL << 7)
++#define MACHINE_FLAG_MVCOS (1UL << 8)
++#define MACHINE_FLAG_KVM (1UL << 9)
++#define MACHINE_FLAG_HPAGE (1UL << 10)
++#define MACHINE_FLAG_PFMF (1UL << 11)
++
++#define MACHINE_IS_VM (machine_flags & MACHINE_FLAG_VM)
++#define MACHINE_IS_KVM (machine_flags & MACHINE_FLAG_KVM)
++#define MACHINE_IS_P390 (machine_flags & MACHINE_FLAG_P390)
++#define MACHINE_HAS_DIAG9C (machine_flags & MACHINE_FLAG_DIAG9C)
+
+ #ifndef __s390x__
+-#define MACHINE_HAS_IEEE (machine_flags & 2)
+-#define MACHINE_HAS_CSP (machine_flags & 8)
++#define MACHINE_HAS_IEEE (machine_flags & MACHINE_FLAG_IEEE)
++#define MACHINE_HAS_CSP (machine_flags & MACHINE_FLAG_CSP)
++#define MACHINE_HAS_IDTE (0)
+ #define MACHINE_HAS_DIAG44 (1)
++#define MACHINE_HAS_MVPG (machine_flags & MACHINE_FLAG_MVPG)
+ #define MACHINE_HAS_MVCOS (0)
++#define MACHINE_HAS_HPAGE (0)
++#define MACHINE_HAS_PFMF (0)
+ #else /* __s390x__ */
+ #define MACHINE_HAS_IEEE (1)
+ #define MACHINE_HAS_CSP (1)
+-#define MACHINE_HAS_DIAG44 (machine_flags & 32)
+-#define MACHINE_HAS_MVCOS (machine_flags & 512)
++#define MACHINE_HAS_IDTE (machine_flags & MACHINE_FLAG_IDTE)
++#define MACHINE_HAS_DIAG44 (machine_flags & MACHINE_FLAG_DIAG44)
++#define MACHINE_HAS_MVPG (1)
++#define MACHINE_HAS_MVCOS (machine_flags & MACHINE_FLAG_MVCOS)
++#define MACHINE_HAS_HPAGE (machine_flags & MACHINE_FLAG_HPAGE)
++#define MACHINE_HAS_PFMF (machine_flags & MACHINE_FLAG_PFMF)
+ #endif /* __s390x__ */
+
+ #define MACHINE_HAS_SCLP (!MACHINE_IS_P390)
diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h
-index c7b7432..6f3821a 100644
+index c7b7432..ae89cf2 100644
--- a/include/asm-s390/smp.h
+++ b/include/asm-s390/smp.h
-@@ -90,6 +90,9 @@ extern void __cpu_die (unsigned int cpu);
+@@ -19,6 +19,7 @@
+ #include <asm/lowcore.h>
+ #include <asm/sigp.h>
+ #include <asm/ptrace.h>
++#include <asm/system.h>
+
+ /*
+ s390 specific smp.c headers
+@@ -53,10 +54,7 @@ extern void machine_power_off_smp(void);
+
+ static inline __u16 hard_smp_processor_id(void)
+ {
+- __u16 cpu_address;
+-
+- asm volatile("stap %0" : "=m" (cpu_address));
+- return cpu_address;
++ return stap();
+ }
+
+ /*
+@@ -90,6 +88,9 @@ extern void __cpu_die (unsigned int cpu);
extern void cpu_die (void) __attribute__ ((noreturn));
extern int __cpu_up (unsigned int cpu);
@@ -789329,12 +1054879,48 @@
extern int smp_call_function_mask(cpumask_t mask, void (*func)(void *),
void *info, int wait);
#endif
+@@ -105,5 +106,11 @@ static inline void smp_send_stop(void)
+ #define smp_cpu_not_running(cpu) 1
+ #endif
+
++#ifdef CONFIG_HOTPLUG_CPU
++extern int smp_rescan_cpus(void);
++#else
++static inline int smp_rescan_cpus(void) { return 0; }
++#endif
++
+ extern union save_area *zfcpdump_save_areas[NR_CPUS + 1];
+ #endif
+diff --git a/include/asm-s390/sparsemem.h b/include/asm-s390/sparsemem.h
+new file mode 100644
+index 0000000..06dfdab
+--- /dev/null
++++ b/include/asm-s390/sparsemem.h
+@@ -0,0 +1,18 @@
++#ifndef _ASM_S390_SPARSEMEM_H
++#define _ASM_S390_SPARSEMEM_H
++
++#define SECTION_SIZE_BITS 25
++
++#ifdef CONFIG_64BIT
++
++#define MAX_PHYSADDR_BITS 42
++#define MAX_PHYSMEM_BITS 42
++
++#else
++
++#define MAX_PHYSADDR_BITS 31
++#define MAX_PHYSMEM_BITS 31
++
++#endif /* CONFIG_64BIT */
++
++#endif /* _ASM_S390_SPARSEMEM_H */
diff --git a/include/asm-s390/sysinfo.h b/include/asm-s390/sysinfo.h
new file mode 100644
-index 0000000..abe10ae
+index 0000000..79d0134
--- /dev/null
+++ b/include/asm-s390/sysinfo.h
-@@ -0,0 +1,116 @@
+@@ -0,0 +1,121 @@
+/*
+ * definition for store system information stsi
+ *
@@ -789348,6 +1054934,9 @@
+ * Christian Borntraeger <borntraeger at de.ibm.com>
+ */
+
++#ifndef __ASM_S390_SYSINFO_H
++#define __ASM_S390_SYSINFO_H
++
+struct sysinfo_1_1_1 {
+ char reserved_0[32];
+ char manufacturer[16];
@@ -789451,11 +1055040,21 @@
+ : "cc", "memory");
+ return r0;
+}
++
++#endif /* __ASM_S390_SYSINFO_H */
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
-index 15aba30..92098df 100644
+index 15aba30..c819ae2 100644
--- a/include/asm-s390/system.h
+++ b/include/asm-s390/system.h
-@@ -406,6 +406,8 @@ __set_psw_mask(unsigned long mask)
+@@ -16,6 +16,7 @@
+ #include <asm/ptrace.h>
+ #include <asm/setup.h>
+ #include <asm/processor.h>
++#include <asm/lowcore.h>
+
+ #ifdef __KERNEL__
+
+@@ -406,6 +407,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)
@@ -789464,6 +1055063,50 @@
#ifdef CONFIG_SMP
extern void smp_ctl_set_bit(int cr, int bit);
+@@ -420,6 +423,23 @@ extern void smp_ctl_clear_bit(int cr, int bit);
+
+ #endif /* CONFIG_SMP */
+
++static inline unsigned int stfl(void)
++{
++ asm volatile(
++ " .insn s,0xb2b10000,0(0)\n" /* stfl */
++ "0:\n"
++ EX_TABLE(0b,0b));
++ return S390_lowcore.stfl_fac_list;
++}
++
++static inline unsigned short stap(void)
++{
++ unsigned short cpu_address;
++
++ asm volatile("stap %0" : "=m" (cpu_address));
++ return cpu_address;
++}
++
+ extern void (*_machine_restart)(char *command);
+ extern void (*_machine_halt)(void);
+ extern void (*_machine_power_off)(void);
+diff --git a/include/asm-s390/thread_info.h b/include/asm-s390/thread_info.h
+index 0a51891..99bbed9 100644
+--- a/include/asm-s390/thread_info.h
++++ b/include/asm-s390/thread_info.h
+@@ -89,7 +89,6 @@ static inline struct thread_info *current_thread_info(void)
+ * thread information flags bit numbers
+ */
+ #define TIF_SYSCALL_TRACE 0 /* syscall trace active */
+-#define TIF_RESTORE_SIGMASK 1 /* restore signal mask in do_signal() */
+ #define TIF_SIGPENDING 2 /* signal pending */
+ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+ #define TIF_RESTART_SVC 4 /* restart svc with new svc number */
+@@ -101,6 +100,7 @@ static inline struct thread_info *current_thread_info(void)
+ TIF_NEED_RESCHED */
+ #define TIF_31BIT 18 /* 32bit process */
+ #define TIF_MEMDIE 19
++#define TIF_RESTORE_SIGMASK 20 /* restore signal mask in do_signal() */
+
+ #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
+ #define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
diff --git a/include/asm-s390/timex.h b/include/asm-s390/timex.h
index 98229db..d744c3d 100644
--- a/include/asm-s390/timex.h
@@ -789500,10 +1055143,18 @@
#endif
diff --git a/include/asm-s390/tlbflush.h b/include/asm-s390/tlbflush.h
-index 35fb4f9..9e57a93 100644
+index 35fb4f9..d60394b 100644
--- a/include/asm-s390/tlbflush.h
+++ b/include/asm-s390/tlbflush.h
-@@ -13,12 +13,14 @@ static inline void __tlb_flush_local(void)
+@@ -2,6 +2,7 @@
+ #define _S390_TLBFLUSH_H
+
+ #include <linux/mm.h>
++#include <linux/sched.h>
+ #include <asm/processor.h>
+ #include <asm/pgalloc.h>
+
+@@ -13,12 +14,14 @@ static inline void __tlb_flush_local(void)
asm volatile("ptlb" : : : "memory");
}
@@ -789519,7 +1055170,7 @@
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)
+@@ -39,6 +42,25 @@ static inline void __tlb_flush_global(void)
: : "d" (reg2), "d" (reg3), "d" (reg4), "m" (dummy) : "cc" );
}
@@ -789545,7 +1055196,7 @@
/*
* Flush all tlb entries of a page table on all cpus.
*/
-@@ -51,8 +72,6 @@ static inline void __tlb_flush_idte(unsigned long asce)
+@@ -51,8 +73,6 @@ static inline void __tlb_flush_idte(unsigned long asce)
static inline void __tlb_flush_mm(struct mm_struct * mm)
{
@@ -789554,7 +1055205,7 @@
if (unlikely(cpus_empty(mm->cpu_vm_mask)))
return;
/*
-@@ -69,16 +88,7 @@ static inline void __tlb_flush_mm(struct mm_struct * mm)
+@@ -69,16 +89,7 @@ static inline void __tlb_flush_mm(struct mm_struct * mm)
mm->context.asce_bits);
return;
}
@@ -789573,10 +1055224,10 @@
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
+index 613aa64..d96c916 100644
--- a/include/asm-s390/topology.h
+++ b/include/asm-s390/topology.h
-@@ -1,6 +1,29 @@
+@@ -1,6 +1,33 @@
#ifndef _ASM_S390_TOPOLOGY_H
#define _ASM_S390_TOPOLOGY_H
@@ -789586,6 +1055237,10 @@
+
+cpumask_t cpu_coregroup_map(unsigned int cpu);
+
++extern cpumask_t cpu_core_map[NR_CPUS];
++
++#define topology_core_siblings(cpu) (cpu_core_map[cpu])
++
+int topology_set_cpu_management(int fc);
+void topology_schedule_update(void);
+
@@ -789606,6 +1055261,54 @@
#include <asm-generic/topology.h>
#endif /* _ASM_S390_TOPOLOGY_H */
+diff --git a/include/asm-s390/unaligned.h b/include/asm-s390/unaligned.h
+index 8ee86db..da9627a 100644
+--- a/include/asm-s390/unaligned.h
++++ b/include/asm-s390/unaligned.h
+@@ -1,24 +1,13 @@
+-/*
+- * include/asm-s390/unaligned.h
+- *
+- * S390 version
+- *
+- * Derived from "include/asm-i386/unaligned.h"
+- */
+-
+-#ifndef __S390_UNALIGNED_H
+-#define __S390_UNALIGNED_H
++#ifndef _ASM_S390_UNALIGNED_H
++#define _ASM_S390_UNALIGNED_H
+
+ /*
+ * The S390 can do unaligned accesses itself.
+- *
+- * The strange macros are there to make sure these can't
+- * be misused in a way that makes them not work on other
+- * architectures where unaligned accesses aren't as simple.
+ */
++#include <linux/unaligned/access_ok.h>
++#include <linux/unaligned/generic.h>
+
+-#define get_unaligned(ptr) (*(ptr))
+-
+-#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
++#define get_unaligned __get_unaligned_be
++#define put_unaligned __put_unaligned_be
+
+-#endif
++#endif /* _ASM_S390_UNALIGNED_H */
+diff --git a/include/asm-sh/bitops.h b/include/asm-sh/bitops.h
+index b6ba5a6..d7d382f 100644
+--- a/include/asm-sh/bitops.h
++++ b/include/asm-sh/bitops.h
+@@ -95,6 +95,7 @@ static inline unsigned long ffz(unsigned long word)
+ #include <asm-generic/bitops/ext2-atomic.h>
+ #include <asm-generic/bitops/minix.h>
+ #include <asm-generic/bitops/fls.h>
++#include <asm-generic/bitops/__fls.h>
+ #include <asm-generic/bitops/fls64.h>
+
+ #endif /* __KERNEL__ */
diff --git a/include/asm-sh/bugs.h b/include/asm-sh/bugs.h
index cfda7d5..121b2ec 100644
--- a/include/asm-sh/bugs.h
@@ -789658,6 +1055361,117 @@
#define RTC_BIT_INVERTED 0x40 /* bug on SH7750, SH7750S */
#define RTC_DEF_CAPABILITIES RTC_CAP_4_DIGIT_YEAR
+diff --git a/include/asm-sh/futex.h b/include/asm-sh/futex.h
+index 74ed368..68256ec 100644
+--- a/include/asm-sh/futex.h
++++ b/include/asm-sh/futex.h
+@@ -4,8 +4,8 @@
+ #ifdef __KERNEL__
+
+ #include <linux/futex.h>
++#include <linux/uaccess.h>
+ #include <asm/errno.h>
+-#include <asm/uaccess.h>
+
+ /* XXX: UP variants, fix for SH-4A and SMP.. */
+ #include <asm/futex-irq.h>
+diff --git a/include/asm-sh/hugetlb.h b/include/asm-sh/hugetlb.h
+new file mode 100644
+index 0000000..0240230
+--- /dev/null
++++ b/include/asm-sh/hugetlb.h
+@@ -0,0 +1,91 @@
++#ifndef _ASM_SH_HUGETLB_H
++#define _ASM_SH_HUGETLB_H
++
++#include <asm/page.h>
++
++
++static inline int is_hugepage_only_range(struct mm_struct *mm,
++ unsigned long addr,
++ unsigned long len) {
++ return 0;
++}
++
++/*
++ * If the arch doesn't supply something else, assume that hugepage
++ * size aligned regions are ok without further preparation.
++ */
++static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
++{
++ if (len & ~HPAGE_MASK)
++ return -EINVAL;
++ if (addr & ~HPAGE_MASK)
++ return -EINVAL;
++ return 0;
++}
++
++static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm) {
++}
++
++static inline void hugetlb_free_pgd_range(struct mmu_gather **tlb,
++ unsigned long addr, unsigned long end,
++ unsigned long floor,
++ unsigned long ceiling)
++{
++ free_pgd_range(tlb, addr, end, floor, ceiling);
++}
++
++static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
++ pte_t *ptep, pte_t pte)
++{
++ set_pte_at(mm, addr, ptep, pte);
++}
++
++static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
++ unsigned long addr, pte_t *ptep)
++{
++ return ptep_get_and_clear(mm, addr, ptep);
++}
++
++static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
++ unsigned long addr, pte_t *ptep)
++{
++}
++
++static inline int huge_pte_none(pte_t pte)
++{
++ return pte_none(pte);
++}
++
++static inline pte_t huge_pte_wrprotect(pte_t pte)
++{
++ return pte_wrprotect(pte);
++}
++
++static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
++ unsigned long addr, pte_t *ptep)
++{
++ ptep_set_wrprotect(mm, addr, ptep);
++}
++
++static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
++ unsigned long addr, pte_t *ptep,
++ pte_t pte, int dirty)
++{
++ return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
++}
++
++static inline pte_t huge_ptep_get(pte_t *ptep)
++{
++ return *ptep;
++}
++
++static inline int arch_prepare_hugepage(struct page *page)
++{
++ return 0;
++}
++
++static inline void arch_release_hugepage(struct page *page)
++{
++}
++
++#endif /* _ASM_SH_HUGETLB_H */
diff --git a/include/asm-sh/i2c-sh7760.h b/include/asm-sh/i2c-sh7760.h
new file mode 100644
index 0000000..2418211
@@ -789777,6 +1055591,55 @@
#define PCI_NO_CHECKS 0x400
#define PCI_ASSIGN_ROMS 0x1000
#define PCI_BIOS_IRQ_SCAN 0x2000
+diff --git a/include/asm-sh/pgtable_32.h b/include/asm-sh/pgtable_32.h
+index 3e3557c..cbc731d 100644
+--- a/include/asm-sh/pgtable_32.h
++++ b/include/asm-sh/pgtable_32.h
+@@ -326,6 +326,7 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
+ #define pte_dirty(pte) ((pte).pte_low & _PAGE_DIRTY)
+ #define pte_young(pte) ((pte).pte_low & _PAGE_ACCESSED)
+ #define pte_file(pte) ((pte).pte_low & _PAGE_FILE)
++#define pte_special(pte) (0)
+
+ #ifdef CONFIG_X2TLB
+ #define pte_write(pte) ((pte).pte_high & _PAGE_EXT_USER_WRITE)
+@@ -356,6 +357,8 @@ PTE_BIT_FUNC(low, mkdirty, |= _PAGE_DIRTY);
+ PTE_BIT_FUNC(low, mkold, &= ~_PAGE_ACCESSED);
+ PTE_BIT_FUNC(low, mkyoung, |= _PAGE_ACCESSED);
+
++static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
++
+ /*
+ * Macro and implementation to make a page protection as uncachable.
+ */
+diff --git a/include/asm-sh/pgtable_64.h b/include/asm-sh/pgtable_64.h
+index f9dd9d3..c78990c 100644
+--- a/include/asm-sh/pgtable_64.h
++++ b/include/asm-sh/pgtable_64.h
+@@ -254,10 +254,11 @@ extern void __handle_bad_pmd_kernel(pmd_t * pmd);
+ /*
+ * The following have defined behavior only work if pte_present() is true.
+ */
+-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_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
+-static inline int pte_write(pte_t pte){ return pte_val(pte) & _PAGE_WRITE; }
++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_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
++static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
++static inline int pte_special(pte_t pte){ return 0; }
+
+ static inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_WRITE)); return pte; }
+ static inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
+@@ -266,6 +267,7 @@ static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) |
+ static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
+ static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
+ static inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
++static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+
+
+ /*
diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h
index ec707b9..b7c7ce8 100644
--- a/include/asm-sh/processor.h
@@ -790216,6 +1056079,34 @@
}
#else /* CONFIG_MMU */
#define __addr_ok(addr) \
+diff --git a/include/asm-sh/unaligned.h b/include/asm-sh/unaligned.h
+index 5250e30..c1641a0 100644
+--- a/include/asm-sh/unaligned.h
++++ b/include/asm-sh/unaligned.h
+@@ -1,7 +1,19 @@
+-#ifndef __ASM_SH_UNALIGNED_H
+-#define __ASM_SH_UNALIGNED_H
++#ifndef _ASM_SH_UNALIGNED_H
++#define _ASM_SH_UNALIGNED_H
+
+ /* SH can't handle unaligned accesses. */
+-#include <asm-generic/unaligned.h>
++#ifdef __LITTLE_ENDIAN__
++# include <linux/unaligned/le_struct.h>
++# include <linux/unaligned/be_byteshift.h>
++# include <linux/unaligned/generic.h>
++# define get_unaligned __get_unaligned_le
++# define put_unaligned __put_unaligned_le
++#else
++# include <linux/unaligned/be_struct.h>
++# include <linux/unaligned/le_byteshift.h>
++# include <linux/unaligned/generic.h>
++# define get_unaligned __get_unaligned_be
++# define put_unaligned __put_unaligned_be
++#endif
+
+-#endif /* __ASM_SH_UNALIGNED_H */
++#endif /* _ASM_SH_UNALIGNED_H */
diff --git a/include/asm-sparc/Kbuild b/include/asm-sparc/Kbuild
index c6a55cf..6712237 100644
--- a/include/asm-sparc/Kbuild
@@ -790416,10 +1056307,10 @@
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
+index 1a03c28..e6532c3 100644
--- a/include/asm-sparc/head.h
+++ b/include/asm-sparc/head.h
-@@ -46,45 +46,12 @@
+@@ -46,44 +46,22 @@
b linux_sparc_syscall; \
rd %psr, %l0;
@@ -790461,10 +1056352,19 @@
- or %l7, %lo(sys_call_table), %l7; \
- b bsd_syscall; \
- rd %psr, %l0;
--
++#ifdef CONFIG_KGDB
++#define KGDB_TRAP(num) \
++ b kgdb_trap_low; \
++ rd %psr,%l0; \
++ nop; \
++ nop;
++#else
++#define KGDB_TRAP(num) \
++ BAD_TRAP(num)
++#endif
+
/* 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
@@ -790491,6 +1056391,135 @@
#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/kgdb.h b/include/asm-sparc/kgdb.h
+index d120adf..b6ef301 100644
+--- a/include/asm-sparc/kgdb.h
++++ b/include/asm-sparc/kgdb.h
+@@ -1,94 +1,38 @@
+-/* $Id: kgdb.h,v 1.8 1998/01/07 06:33:44 baccala Exp $
+- * kgdb.h: Defines and declarations for serial line source level
+- * remote debugging of the Linux kernel using gdb.
+- *
+- * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
+- */
+ #ifndef _SPARC_KGDB_H
+ #define _SPARC_KGDB_H
+
+-#ifndef __ASSEMBLY__
+-/* To init the kgdb engine. */
+-extern void set_debug_traps(void);
+-
+-/* To enter the debugger explicitly. */
+-extern void breakpoint(void);
+-
+-/* For convenience we define the format of a kgdb trap breakpoint
+- * frame here also.
+- */
+-struct kgdb_frame {
+- unsigned long globals[8];
+- unsigned long outs[8];
+- unsigned long locals[8];
+- unsigned long ins[8];
+- unsigned long fpregs[32];
+- unsigned long y;
+- unsigned long psr;
+- unsigned long wim;
+- unsigned long tbr;
+- unsigned long pc;
+- unsigned long npc;
+- unsigned long fpsr;
+- unsigned long cpsr;
++#ifdef CONFIG_SPARC32
++#define BUFMAX 2048
++#else
++#define BUFMAX 4096
++#endif
++
++enum regnames {
++ GDB_G0, GDB_G1, GDB_G2, GDB_G3, GDB_G4, GDB_G5, GDB_G6, GDB_G7,
++ GDB_O0, GDB_O1, GDB_O2, GDB_O3, GDB_O4, GDB_O5, GDB_SP, GDB_O7,
++ GDB_L0, GDB_L1, GDB_L2, GDB_L3, GDB_L4, GDB_L5, GDB_L6, GDB_L7,
++ GDB_I0, GDB_I1, GDB_I2, GDB_I3, GDB_I4, GDB_I5, GDB_FP, GDB_I7,
++ GDB_F0,
++ GDB_F31 = GDB_F0 + 31,
++#ifdef CONFIG_SPARC32
++ GDB_Y, GDB_PSR, GDB_WIM, GDB_TBR, GDB_PC, GDB_NPC,
++ GDB_FSR, GDB_CSR,
++#else
++ GDB_F32 = GDB_F0 + 32,
++ GDB_F62 = GDB_F32 + 15,
++ GDB_PC, GDB_NPC, GDB_STATE, GDB_FSR, GDB_FPRS, GDB_Y,
++#endif
+ };
+-#endif /* !(__ASSEMBLY__) */
+-
+-/* Macros for assembly usage of the kgdb breakpoint frame. */
+-#define KGDB_G0 0x000
+-#define KGDB_G1 0x004
+-#define KGDB_G2 0x008
+-#define KGDB_G4 0x010
+-#define KGDB_G6 0x018
+-#define KGDB_I0 0x020
+-#define KGDB_I2 0x028
+-#define KGDB_I4 0x030
+-#define KGDB_I6 0x038
+-#define KGDB_Y 0x100
+-#define KGDB_PSR 0x104
+-#define KGDB_WIM 0x108
+-#define KGDB_TBR 0x10c
+-#define KGDB_PC 0x110
+-#define KGDB_NPC 0x114
+-
+-#define SAVE_KGDB_GLOBALS(reg) \
+- std %g0, [%reg + STACKFRAME_SZ + KGDB_G0]; \
+- std %g2, [%reg + STACKFRAME_SZ + KGDB_G2]; \
+- std %g4, [%reg + STACKFRAME_SZ + KGDB_G4]; \
+- std %g6, [%reg + STACKFRAME_SZ + KGDB_G6];
+-
+-#define SAVE_KGDB_INS(reg) \
+- std %i0, [%reg + STACKFRAME_SZ + KGDB_I0]; \
+- std %i2, [%reg + STACKFRAME_SZ + KGDB_I2]; \
+- std %i4, [%reg + STACKFRAME_SZ + KGDB_I4]; \
+- std %i6, [%reg + STACKFRAME_SZ + KGDB_I6];
+-
+-#define SAVE_KGDB_SREGS(reg, reg_y, reg_psr, reg_wim, reg_tbr, reg_pc, reg_npc) \
+- st %reg_y, [%reg + STACKFRAME_SZ + KGDB_Y]; \
+- st %reg_psr, [%reg + STACKFRAME_SZ + KGDB_PSR]; \
+- st %reg_wim, [%reg + STACKFRAME_SZ + KGDB_WIM]; \
+- st %reg_tbr, [%reg + STACKFRAME_SZ + KGDB_TBR]; \
+- st %reg_pc, [%reg + STACKFRAME_SZ + KGDB_PC]; \
+- st %reg_npc, [%reg + STACKFRAME_SZ + KGDB_NPC];
+
+-#define LOAD_KGDB_GLOBALS(reg) \
+- ld [%reg + STACKFRAME_SZ + KGDB_G1], %g1; \
+- ldd [%reg + STACKFRAME_SZ + KGDB_G2], %g2; \
+- ldd [%reg + STACKFRAME_SZ + KGDB_G4], %g4; \
+- ldd [%reg + STACKFRAME_SZ + KGDB_G6], %g6;
++#ifdef CONFIG_SPARC32
++#define NUMREGBYTES ((GDB_CSR + 1) * 4)
++#else
++#define NUMREGBYTES ((GDB_Y + 1) * 8)
++#endif
+
+-#define LOAD_KGDB_INS(reg) \
+- ldd [%reg + STACKFRAME_SZ + KGDB_I0], %i0; \
+- ldd [%reg + STACKFRAME_SZ + KGDB_I2], %i2; \
+- ldd [%reg + STACKFRAME_SZ + KGDB_I4], %i4; \
+- ldd [%reg + STACKFRAME_SZ + KGDB_I6], %i6;
++extern void arch_kgdb_breakpoint(void);
+
+-#define LOAD_KGDB_SREGS(reg, reg_y, reg_psr, reg_wim, reg_tbr, reg_pc, reg_npc) \
+- ld [%reg + STACKFRAME_SZ + KGDB_Y], %reg_y; \
+- ld [%reg + STACKFRAME_SZ + KGDB_PSR], %reg_psr; \
+- ld [%reg + STACKFRAME_SZ + KGDB_WIM], %reg_wim; \
+- ld [%reg + STACKFRAME_SZ + KGDB_TBR], %reg_tbr; \
+- ld [%reg + STACKFRAME_SZ + KGDB_PC], %reg_pc; \
+- ld [%reg + STACKFRAME_SZ + KGDB_NPC], %reg_npc;
++#define BREAK_INSTR_SIZE 4
++#define CACHE_FLUSH_IS_SAFE 1
+
+-#endif /* !(_SPARC_KGDB_H) */
++#endif /* _SPARC_KGDB_H */
diff --git a/include/asm-sparc/mman.h b/include/asm-sparc/mman.h
index b7dc40b..e18be98 100644
--- a/include/asm-sparc/mman.h
@@ -790571,11 +1056600,43 @@
-#define _PCONF_MAXPCONF 9
-
-#endif /* !(_SPARC_PCONF_H) */
+diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h
+index 2cc235b..d84af6d 100644
+--- a/include/asm-sparc/pgtable.h
++++ b/include/asm-sparc/pgtable.h
+@@ -219,6 +219,11 @@ static inline int pte_file(pte_t pte)
+ return pte_val(pte) & BTFIXUP_HALF(pte_filei);
+ }
+
++static inline int pte_special(pte_t pte)
++{
++ return 0;
++}
++
+ /*
+ */
+ BTFIXUPDEF_HALF(pte_wrprotecti)
+@@ -251,6 +256,8 @@ BTFIXUPDEF_CALL_CONST(pte_t, pte_mkyoung, pte_t)
+ #define pte_mkdirty(pte) BTFIXUP_CALL(pte_mkdirty)(pte)
+ #define pte_mkyoung(pte) BTFIXUP_CALL(pte_mkyoung)(pte)
+
++#define pte_mkspecial(pte) (pte)
++
+ #define pfn_pte(pfn, prot) mk_pte(pfn_to_page(pfn), prot)
+
+ BTFIXUPDEF_CALL(unsigned long, pte_pfn, pte_t)
diff --git a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h
-index 40b1e41..e300697 100644
+index 40b1e41..8898efb 100644
--- a/include/asm-sparc/processor.h
+++ b/include/asm-sparc/processor.h
-@@ -13,8 +13,6 @@
+@@ -1,5 +1,4 @@
+-/* $Id: processor.h,v 1.83 2001/10/08 09:32:13 davem Exp $
+- * include/asm-sparc/processor.h
++/* include/asm-sparc/processor.h
+ *
+ * Copyright (C) 1994 David S. Miller (davem at caip.rutgers.edu)
+ */
+@@ -13,8 +12,6 @@
*/
#define current_text_addr() ({ void *pc; __asm__("sethi %%hi(1f), %0; or %0, %%lo(1f), %0;\n1:" : "=r" (pc)); pc; })
@@ -790584,14 +1056645,15 @@
#include <asm/psr.h>
#include <asm/ptrace.h>
#include <asm/head.h>
-@@ -67,7 +65,6 @@ struct thread_struct {
+@@ -67,8 +64,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;
+- int new_signal;
};
+ #define SPARC_FLAG_KTHREAD 0x1 /* task is a kernel thread */
diff --git a/include/asm-sparc/prom.h b/include/asm-sparc/prom.h
index df5dc44..fd55522 100644
--- a/include/asm-sparc/prom.h
@@ -790806,6 +1056868,24 @@
-
-#endif /* !(_SPARC_SEMAPHORE_H) */
+#include <linux/semaphore.h>
+diff --git a/include/asm-sparc/smp.h b/include/asm-sparc/smp.h
+index b3f4922..e6d5615 100644
+--- a/include/asm-sparc/smp.h
++++ b/include/asm-sparc/smp.h
+@@ -51,13 +51,11 @@ void smp_bogo(struct seq_file *);
+ void smp_info(struct seq_file *);
+
+ BTFIXUPDEF_CALL(void, smp_cross_call, smpfunc_t, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
+-BTFIXUPDEF_CALL(void, smp_message_pass, int, int, unsigned long, int)
+ BTFIXUPDEF_CALL(int, __hard_smp_processor_id, void)
+ BTFIXUPDEF_BLACKBOX(hard_smp_processor_id)
+ BTFIXUPDEF_BLACKBOX(load_current)
+
+ #define smp_cross_call(func,arg1,arg2,arg3,arg4,arg5) BTFIXUP_CALL(smp_cross_call)(func,arg1,arg2,arg3,arg4,arg5)
+-#define smp_message_pass(target,msg,data,wait) BTFIXUP_CALL(smp_message_pass)(target,msg,data,wait)
+
+ static inline void xc0(smpfunc_t func) { smp_cross_call(func, 0, 0, 0, 0, 0); }
+ static inline void xc1(smpfunc_t func, unsigned long arg1)
diff --git a/include/asm-sparc/socket.h b/include/asm-sparc/socket.h
index 2e2bd0b..a00e15d 100644
--- a/include/asm-sparc/socket.h
@@ -791083,6 +1057163,19 @@
-#define SVR4_SF_ALIGNED (((sizeof (svr4_signal_frame_t) + 7) & (~7)))
-
-#endif /* include control */
+diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h
+index 4e08210..b4b0244 100644
+--- a/include/asm-sparc/system.h
++++ b/include/asm-sparc/system.h
+@@ -94,6 +94,8 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
+ } while(0)
+ #endif
+
++extern void flushw_all(void);
++
+ /*
+ * Flush windows so that the VM switch which follows
+ * would not pull the stack from under us.
diff --git a/include/asm-sparc/termios.h b/include/asm-sparc/termios.h
index 4333232..733d405 100644
--- a/include/asm-sparc/termios.h
@@ -791099,6 +1057192,24 @@
struct winsize {
unsigned short ws_row;
unsigned short ws_col;
+diff --git a/include/asm-sparc/unaligned.h b/include/asm-sparc/unaligned.h
+index b6f8edd..11d2d5f 100644
+--- a/include/asm-sparc/unaligned.h
++++ b/include/asm-sparc/unaligned.h
+@@ -1,6 +1,10 @@
+-#ifndef _ASM_SPARC_UNALIGNED_H_
+-#define _ASM_SPARC_UNALIGNED_H_
++#ifndef _ASM_SPARC_UNALIGNED_H
++#define _ASM_SPARC_UNALIGNED_H
+
+-#include <asm-generic/unaligned.h>
++#include <linux/unaligned/be_struct.h>
++#include <linux/unaligned/le_byteshift.h>
++#include <linux/unaligned/generic.h>
++#define get_unaligned __get_unaligned_be
++#define put_unaligned __put_unaligned_be
+
+ #endif /* _ASM_SPARC_UNALIGNED_H */
diff --git a/include/asm-sparc/user.h b/include/asm-sparc/user.h
index b5f1abf..3400ea8 100644
--- a/include/asm-sparc/user.h
@@ -791221,6 +1057332,233 @@
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/a.out.h>
+diff --git a/include/asm-sparc64/bitops.h b/include/asm-sparc64/bitops.h
+index 982ce89..11f9d81 100644
+--- a/include/asm-sparc64/bitops.h
++++ b/include/asm-sparc64/bitops.h
+@@ -34,6 +34,7 @@ extern void change_bit(unsigned long nr, volatile unsigned long *addr);
+ #include <asm-generic/bitops/ffz.h>
+ #include <asm-generic/bitops/__ffs.h>
+ #include <asm-generic/bitops/fls.h>
++#include <asm-generic/bitops/__fls.h>
+ #include <asm-generic/bitops/fls64.h>
+
+ #ifdef __KERNEL__
+diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h
+index c47f58d..ca19f80 100644
+--- a/include/asm-sparc64/floppy.h
++++ b/include/asm-sparc64/floppy.h
+@@ -293,7 +293,6 @@ static int sun_fd_eject(int drive)
+
+ #ifdef CONFIG_PCI
+ #include <asm/ebus.h>
+-#include <asm/isa.h>
+ #include <asm/ns87303.h>
+
+ static struct ebus_dma_info sun_pci_fd_ebus_dma;
+@@ -558,82 +557,6 @@ static int __init ebus_fdthree_p(struct linux_ebus_device *edev)
+ }
+ #endif
+
+-#ifdef CONFIG_PCI
+-#undef ISA_FLOPPY_WORKS
+-
+-#ifdef ISA_FLOPPY_WORKS
+-static unsigned long __init isa_floppy_init(void)
+-{
+- struct sparc_isa_bridge *isa_br;
+- struct sparc_isa_device *isa_dev = NULL;
+-
+- for_each_isa(isa_br) {
+- for_each_isadev(isa_dev, isa_br) {
+- if (!strcmp(isa_dev->prom_node->name, "dma")) {
+- struct sparc_isa_device *child =
+- isa_dev->child;
+-
+- while (child) {
+- if (!strcmp(child->prom_node->name,
+- "floppy")) {
+- isa_dev = child;
+- goto isa_done;
+- }
+- child = child->next;
+- }
+- }
+- }
+- }
+-isa_done:
+- if (!isa_dev)
+- return 0;
+-
+- /* We could use DMA on devices behind the ISA bridge, but...
+- *
+- * There is a slight problem. Normally on x86 kit the x86 processor
+- * delays I/O port instructions when the ISA bus "dma in progress"
+- * signal is active. Well, sparc64 systems do not monitor this
+- * signal thus we would need to block all I/O port accesses in software
+- * when a dma transfer is active for some device.
+- */
+-
+- sun_fdc = (struct sun_flpy_controller *)isa_dev->resource.start;
+- FLOPPY_IRQ = isa_dev->irq;
+-
+- sun_fdops.fd_inb = sun_pci_fd_inb;
+- sun_fdops.fd_outb = sun_pci_fd_outb;
+-
+- can_use_virtual_dma = use_virtual_dma = 1;
+- sun_fdops.fd_enable_dma = sun_fd_enable_dma;
+- sun_fdops.fd_disable_dma = sun_fd_disable_dma;
+- sun_fdops.fd_set_dma_mode = sun_fd_set_dma_mode;
+- sun_fdops.fd_set_dma_addr = sun_fd_set_dma_addr;
+- sun_fdops.fd_set_dma_count = sun_fd_set_dma_count;
+- sun_fdops.get_dma_residue = sun_get_dma_residue;
+-
+- sun_fdops.fd_request_irq = sun_fd_request_irq;
+- sun_fdops.fd_free_irq = sun_fd_free_irq;
+-
+- /* Floppy eject is manual. Actually, could determine this
+- * via presence of 'manual' property in OBP node.
+- */
+- sun_fdops.fd_eject = sun_pci_fd_eject;
+-
+- fdc_status = (unsigned long) &sun_fdc->status_82077;
+-
+- allowed_drive_mask = 0;
+- sun_floppy_types[0] = 0;
+- sun_floppy_types[1] = 4;
+-
+- sun_pci_broken_drive = 1;
+- sun_fdops.fd_outb = sun_pci_fd_broken_outb;
+-
+- return sun_floppy_types[0];
+-}
+-#endif /* ISA_FLOPPY_WORKS */
+-
+-#endif
+-
+ static unsigned long __init sun_floppy_init(void)
+ {
+ char state[128];
+@@ -667,13 +590,8 @@ static unsigned long __init sun_floppy_init(void)
+ }
+ }
+ ebus_done:
+- if (!edev) {
+-#ifdef ISA_FLOPPY_WORKS
+- return isa_floppy_init();
+-#else
++ if (!edev)
+ return 0;
+-#endif
+- }
+
+ state_prop = of_get_property(edev->prom_node, "status", NULL);
+ if (state_prop && !strncmp(state_prop, "disabled", 8))
+diff --git a/include/asm-sparc64/futex.h b/include/asm-sparc64/futex.h
+index df1097d..d837893 100644
+--- a/include/asm-sparc64/futex.h
++++ b/include/asm-sparc64/futex.h
+@@ -2,9 +2,9 @@
+ #define _SPARC64_FUTEX_H
+
+ #include <linux/futex.h>
++#include <linux/uaccess.h>
+ #include <asm/errno.h>
+ #include <asm/system.h>
+-#include <asm/uaccess.h>
+
+ #define __futex_cas_op(insn, ret, oldval, uaddr, oparg) \
+ __asm__ __volatile__( \
+diff --git a/include/asm-sparc64/hugetlb.h b/include/asm-sparc64/hugetlb.h
+new file mode 100644
+index 0000000..412af58
+--- /dev/null
++++ b/include/asm-sparc64/hugetlb.h
+@@ -0,0 +1,84 @@
++#ifndef _ASM_SPARC64_HUGETLB_H
++#define _ASM_SPARC64_HUGETLB_H
++
++#include <asm/page.h>
++
++
++void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
++ pte_t *ptep, pte_t pte);
++
++pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
++ pte_t *ptep);
++
++void hugetlb_prefault_arch_hook(struct mm_struct *mm);
++
++static inline int is_hugepage_only_range(struct mm_struct *mm,
++ unsigned long addr,
++ unsigned long len) {
++ return 0;
++}
++
++/*
++ * If the arch doesn't supply something else, assume that hugepage
++ * size aligned regions are ok without further preparation.
++ */
++static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
++{
++ if (len & ~HPAGE_MASK)
++ return -EINVAL;
++ if (addr & ~HPAGE_MASK)
++ return -EINVAL;
++ return 0;
++}
++
++static inline void hugetlb_free_pgd_range(struct mmu_gather **tlb,
++ unsigned long addr, unsigned long end,
++ unsigned long floor,
++ unsigned long ceiling)
++{
++ free_pgd_range(tlb, addr, end, floor, ceiling);
++}
++
++static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
++ unsigned long addr, pte_t *ptep)
++{
++}
++
++static inline int huge_pte_none(pte_t pte)
++{
++ return pte_none(pte);
++}
++
++static inline pte_t huge_pte_wrprotect(pte_t pte)
++{
++ return pte_wrprotect(pte);
++}
++
++static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
++ unsigned long addr, pte_t *ptep)
++{
++ ptep_set_wrprotect(mm, addr, ptep);
++}
++
++static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
++ unsigned long addr, pte_t *ptep,
++ pte_t pte, int dirty)
++{
++ return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
++}
++
++static inline pte_t huge_ptep_get(pte_t *ptep)
++{
++ return *ptep;
++}
++
++static inline int arch_prepare_hugepage(struct page *page)
++{
++ return 0;
++}
++
++static inline void arch_release_hugepage(struct page *page)
++{
++}
++
++#endif /* _ASM_SPARC64_HUGETLB_H */
diff --git a/include/asm-sparc64/ide.h b/include/asm-sparc64/ide.h
index ac7eb21..c5fdabe 100644
--- a/include/asm-sparc64/ide.h
@@ -791260,6 +1057598,66 @@
+ int numa_node);
#endif /* !(_SPARC64_IOMMU_H) */
+diff --git a/include/asm-sparc64/isa.h b/include/asm-sparc64/isa.h
+deleted file mode 100644
+index ecd9290..0000000
+--- a/include/asm-sparc64/isa.h
++++ /dev/null
+@@ -1,47 +0,0 @@
+-/* $Id: isa.h,v 1.1 2001/05/11 04:31:55 davem Exp $
+- * isa.h: Sparc64 layer for PCI to ISA bridge devices.
+- *
+- * Copyright (C) 2001 David S. Miller (davem at redhat.com)
+- */
+-
+-#ifndef __SPARC64_ISA_H
+-#define __SPARC64_ISA_H
+-
+-#include <asm/oplib.h>
+-#include <asm/prom.h>
+-#include <asm/of_device.h>
+-
+-struct sparc_isa_bridge;
+-
+-struct sparc_isa_device {
+- struct of_device ofdev;
+- struct sparc_isa_device *next;
+- struct sparc_isa_device *child;
+- struct sparc_isa_bridge *bus;
+- struct device_node *prom_node;
+- struct resource resource;
+- unsigned int irq;
+-};
+-#define to_isa_device(d) container_of(d, struct sparc_isa_device, ofdev.dev)
+-
+-struct sparc_isa_bridge {
+- struct of_device ofdev;
+- struct sparc_isa_bridge *next;
+- struct sparc_isa_device *devices;
+- struct pci_dev *self;
+- int index;
+- struct device_node *prom_node;
+-};
+-#define to_isa_bridge(d) container_of(d, struct sparc_isa_bridge, ofdev.dev)
+-
+-extern struct sparc_isa_bridge *isa_chain;
+-
+-extern void isa_init(void);
+-
+-#define for_each_isa(bus) \
+- for((bus) = isa_chain; (bus); (bus) = (bus)->next)
+-
+-#define for_each_isadev(dev, bus) \
+- for((dev) = (bus)->devices; (dev); (dev) = (dev)->next)
+-
+-#endif /* !(__SPARC64_ISA_H) */
+diff --git a/include/asm-sparc64/kgdb.h b/include/asm-sparc64/kgdb.h
+new file mode 100644
+index 0000000..aa6532f
+--- /dev/null
++++ b/include/asm-sparc64/kgdb.h
+@@ -0,0 +1 @@
++#include <asm-sparc/kgdb.h>
diff --git a/include/asm-sparc64/lmb.h b/include/asm-sparc64/lmb.h
new file mode 100644
index 0000000..6a352cb
@@ -791360,6 +1057758,19 @@
-#define NODES_SHIFT 0
-
-#endif /* !(_SPARC64_NUMNODES_H) */
+diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h
+index e93a482..618117d 100644
+--- a/include/asm-sparc64/page.h
++++ b/include/asm-sparc64/page.h
+@@ -39,8 +39,6 @@
+ #define HPAGE_SIZE (_AC(1,UL) << HPAGE_SHIFT)
+ #define HPAGE_MASK (~(HPAGE_SIZE - 1UL))
+ #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+-#define ARCH_HAS_SETCLEAR_HUGE_PTE
+-#define ARCH_HAS_HUGETLB_PREFAULT_HOOK
+ #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+ #endif
+
diff --git a/include/asm-sparc64/pconf.h b/include/asm-sparc64/pconf.h
deleted file mode 100644
index aad106a..0000000
@@ -791391,20 +1057802,75 @@
-#define _PCONF_MAXPCONF 9
-
-#endif /* !(_SPARC64_PCONF_H) */
+diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
+index 549e452..0e200e7 100644
+--- a/include/asm-sparc64/pgtable.h
++++ b/include/asm-sparc64/pgtable.h
+@@ -506,6 +506,11 @@ static inline pte_t pte_mkyoung(pte_t pte)
+ return __pte(pte_val(pte) | mask);
+ }
+
++static inline pte_t pte_mkspecial(pte_t pte)
++{
++ return pte;
++}
++
+ static inline unsigned long pte_young(pte_t pte)
+ {
+ unsigned long mask;
+@@ -608,6 +613,11 @@ static inline unsigned long pte_present(pte_t pte)
+ return val;
+ }
+
++static inline int pte_special(pte_t pte)
++{
++ return 0;
++}
++
+ #define pmd_set(pmdp, ptep) \
+ (pmd_val(*(pmdp)) = (__pa((unsigned long) (ptep)) >> 11UL))
+ #define pud_set(pudp, pmdp) \
+diff --git a/include/asm-sparc64/pil.h b/include/asm-sparc64/pil.h
+index 7292774..2f5d126 100644
+--- a/include/asm-sparc64/pil.h
++++ b/include/asm-sparc64/pil.h
+@@ -19,11 +19,4 @@
+ #define PIL_SMP_CTX_NEW_VERSION 4
+ #define PIL_DEVICE_IRQ 5
+
+-#ifndef __ASSEMBLY__
+-#define PIL_RESERVED(PIL) ((PIL) == PIL_SMP_CALL_FUNC || \
+- (PIL) == PIL_SMP_RECEIVE_SIGNAL || \
+- (PIL) == PIL_SMP_CAPTURE || \
+- (PIL) == PIL_SMP_CTX_NEW_VERSION)
+-#endif
+-
+ #endif /* !(_SPARC64_PIL_H) */
diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h
-index 6da1978..b4b951d 100644
+index 6da1978..714b819 100644
--- a/include/asm-sparc64/ptrace.h
+++ b/include/asm-sparc64/ptrace.h
-@@ -8,6 +8,8 @@
+@@ -1,4 +1,3 @@
+-/* $Id: ptrace.h,v 1.14 2002/02/09 19:49:32 davem Exp $ */
+ #ifndef _SPARC64_PTRACE_H
+ #define _SPARC64_PTRACE_H
+
+@@ -8,17 +7,53 @@
* stack during a system call and basically all traps.
*/
++/* This magic value must have the low 9 bits clear,
++ * as that is where we encode the %tt value, see below.
++ */
+#define PT_REGS_MAGIC 0x57ac6c00
+
#ifndef __ASSEMBLY__
++#include <linux/types.h>
++
struct pt_regs {
-@@ -16,7 +18,19 @@ struct pt_regs {
+ unsigned long u_regs[16]; /* globals and ins */
+ unsigned long tstate;
unsigned long tpc;
unsigned long tnpc;
unsigned int y;
@@ -791424,8 +1057890,27 @@
+ unsigned int magic;
};
++static inline int pt_regs_trap_type(struct pt_regs *regs)
++{
++ return regs->magic & 0x1ff;
++}
++
++static inline int pt_regs_clear_trap_type(struct pt_regs *regs)
++{
++ return regs->magic &= ~0x1ff;
++}
++
++static inline bool pt_regs_is_syscall(struct pt_regs *regs)
++{
++ int tt = pt_regs_trap_type(regs);
++
++ return (tt == 0x110 || tt == 0x111 || tt == 0x16d);
++}
++
struct pt_regs32 {
-@@ -147,7 +161,7 @@ extern void __show_regs(struct pt_regs *);
+ unsigned int psr;
+ unsigned int pc;
+@@ -147,7 +182,7 @@ extern void __show_regs(struct pt_regs *);
#define PT_V9_TPC 0x88
#define PT_V9_TNPC 0x90
#define PT_V9_Y 0x98
@@ -791784,6 +1058269,26 @@
-#define SVR4_SF_ALIGNED (((sizeof (svr4_signal_frame_t) + 7) & (~7)))
-
-#endif /* include control */
+diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h
+index 53eae09..6897ac3 100644
+--- a/include/asm-sparc64/system.h
++++ b/include/asm-sparc64/system.h
+@@ -180,12 +180,13 @@ do { if (test_thread_flag(TIF_PERFCTR)) { \
+ "ldx [%%sp + 2047 + 0x70], %%i6\n\t" \
+ "ldx [%%sp + 2047 + 0x78], %%i7\n\t" \
+ "ldx [%%g6 + %9], %%g4\n\t" \
+- "brz,pt %%o7, 1f\n\t" \
++ "brz,pt %%o7, switch_to_pc\n\t" \
+ " mov %%g7, %0\n\t" \
+ "sethi %%hi(ret_from_syscall), %%g1\n\t" \
+ "jmpl %%g1 + %%lo(ret_from_syscall), %%g0\n\t" \
+ " nop\n\t" \
+- "1:\n\t" \
++ ".globl switch_to_pc\n\t" \
++ "switch_to_pc:\n\t" \
+ : "=&r" (last), "=r" (current), "=r" (current_thread_info_reg), \
+ "=r" (__local_per_cpu_offset) \
+ : "0" (task_thread_info(next)), \
diff --git a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h
index ef52721..cacbea1 100644
--- a/include/asm-sparc64/termios.h
@@ -791800,6 +1058305,34 @@
struct winsize {
unsigned short ws_row;
unsigned short ws_col;
+diff --git a/include/asm-sparc64/thread_info.h b/include/asm-sparc64/thread_info.h
+index 98252cd..71e42d1 100644
+--- a/include/asm-sparc64/thread_info.h
++++ b/include/asm-sparc64/thread_info.h
+@@ -1,5 +1,4 @@
+-/* $Id: thread_info.h,v 1.1 2002/02/10 00:00:58 davem Exp $
+- * thread_info.h: sparc64 low-level thread information
++/* thread_info.h: sparc64 low-level thread information
+ *
+ * Copyright (C) 2002 David S. Miller (davem at redhat.com)
+ */
+@@ -223,7 +222,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
+ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+ #define TIF_PERFCTR 4 /* performance counters active */
+ #define TIF_UNALIGNED 5 /* allowed to do unaligned accesses */
+-#define TIF_NEWSIGNALS 6 /* wants new-style signals */
++/* flag bit 6 is available */
+ #define TIF_32BIT 7 /* 32-bit binary */
+ /* flag bit 8 is available */
+ #define TIF_SECCOMP 9 /* secure computing */
+@@ -242,7 +241,6 @@ register struct thread_info *current_thread_info_reg asm("g6");
+ #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
+ #define _TIF_PERFCTR (1<<TIF_PERFCTR)
+ #define _TIF_UNALIGNED (1<<TIF_UNALIGNED)
+-#define _TIF_NEWSIGNALS (1<<TIF_NEWSIGNALS)
+ #define _TIF_32BIT (1<<TIF_32BIT)
+ #define _TIF_SECCOMP (1<<TIF_SECCOMP)
+ #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
diff --git a/include/asm-sparc64/topology.h b/include/asm-sparc64/topology.h
index c6b5570..001c040 100644
--- a/include/asm-sparc64/topology.h
@@ -791892,7 +1058425,7 @@
#endif /* _ASM_SPARC64_TOPOLOGY_H */
diff --git a/include/asm-sparc64/ttable.h b/include/asm-sparc64/ttable.h
-index bbb9c8f..d3cc4ef 100644
+index bbb9c8f..1b55538 100644
--- a/include/asm-sparc64/ttable.h
+++ b/include/asm-sparc64/ttable.h
@@ -28,7 +28,7 @@
@@ -791997,6 +1058530,37 @@
stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC];
#ifdef CONFIG_KPROBES
+@@ -193,6 +175,12 @@
+ #define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
+ #endif
+
++#ifdef CONFIG_KGDB
++#define KGDB_TRAP(lvl) TRAP_IRQ(kgdb_trap, lvl)
++#else
++#define KGDB_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
++#endif
++
+ #define SUN4V_ITSB_MISS \
+ ldxa [%g0] ASI_SCRATCHPAD, %g2; \
+ ldx [%g2 + HV_FAULT_I_ADDR_OFFSET], %g4; \
+diff --git a/include/asm-sparc64/unaligned.h b/include/asm-sparc64/unaligned.h
+index 1ed3ba5..edcebb0 100644
+--- a/include/asm-sparc64/unaligned.h
++++ b/include/asm-sparc64/unaligned.h
+@@ -1,6 +1,10 @@
+-#ifndef _ASM_SPARC64_UNALIGNED_H_
+-#define _ASM_SPARC64_UNALIGNED_H_
++#ifndef _ASM_SPARC64_UNALIGNED_H
++#define _ASM_SPARC64_UNALIGNED_H
+
+-#include <asm-generic/unaligned.h>
++#include <linux/unaligned/be_struct.h>
++#include <linux/unaligned/le_byteshift.h>
++#include <linux/unaligned/generic.h>
++#define get_unaligned __get_unaligned_be
++#define put_unaligned __put_unaligned_be
+
+ #endif /* _ASM_SPARC64_UNALIGNED_H */
diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
index 77559da..13be445 100644
--- a/include/asm-sparc64/unistd.h
@@ -792084,6 +1058648,34 @@
-
-#endif /* !(_SPARC64_USER_H) */
+#include <asm-sparc/user.h>
+diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
+index 4102b44..02db81b 100644
+--- a/include/asm-um/pgtable.h
++++ b/include/asm-um/pgtable.h
+@@ -173,6 +173,11 @@ static inline int pte_newprot(pte_t pte)
+ return(pte_present(pte) && (pte_get_bits(pte, _PAGE_NEWPROT)));
+ }
+
++static inline int pte_special(pte_t pte)
++{
++ return 0;
++}
++
+ /*
+ * =================================
+ * Flags setting section.
+@@ -241,6 +246,11 @@ static inline pte_t pte_mknewpage(pte_t pte)
+ return(pte);
+ }
+
++static inline pte_t pte_mkspecial(pte_t pte)
++{
++ return(pte);
++}
++
+ static inline void set_pte(pte_t *pteptr, pte_t pteval)
+ {
+ pte_copy(*pteptr, pteval);
diff --git a/include/asm-um/semaphore.h b/include/asm-um/semaphore.h
index ff13c34..d9b2034 100644
--- a/include/asm-um/semaphore.h
@@ -792096,6 +1058688,20 @@
-
-#endif
+#include <linux/semaphore.h>
+diff --git a/include/asm-um/unaligned.h b/include/asm-um/unaligned.h
+index 1d2497c..a471969 100644
+--- a/include/asm-um/unaligned.h
++++ b/include/asm-um/unaligned.h
+@@ -1,6 +1,6 @@
+-#ifndef __UM_UNALIGNED_H
+-#define __UM_UNALIGNED_H
++#ifndef _ASM_UM_UNALIGNED_H
++#define _ASM_UM_UNALIGNED_H
+
+ #include "asm/arch/unaligned.h"
+
+-#endif
++#endif /* _ASM_UM_UNALIGNED_H */
diff --git a/include/asm-v850/semaphore.h b/include/asm-v850/semaphore.h
index 10ed0cc..d9b2034 100644
--- a/include/asm-v850/semaphore.h
@@ -792186,6 +1058792,149 @@
-
-#endif /* __V850_SEMAPHORE_H__ */
+#include <linux/semaphore.h>
+diff --git a/include/asm-v850/unaligned.h b/include/asm-v850/unaligned.h
+index e30b186..53122b2 100644
+--- a/include/asm-v850/unaligned.h
++++ b/include/asm-v850/unaligned.h
+@@ -1,6 +1,4 @@
+ /*
+- * include/asm-v850/unaligned.h -- Unaligned memory access
+- *
+ * Copyright (C) 2001 NEC Corporation
+ * Copyright (C) 2001 Miles Bader <miles at gnu.org>
+ *
+@@ -8,123 +6,17 @@
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+- * This file is a copy of the arm version, include/asm-arm/unaligned.h
+- *
+ * Note that some v850 chips support unaligned access, but it seems too
+ * annoying to use.
+ */
++#ifndef _ASM_V850_UNALIGNED_H
++#define _ASM_V850_UNALIGNED_H
+
+-#ifndef __V850_UNALIGNED_H__
+-#define __V850_UNALIGNED_H__
+-
+-#include <asm/types.h>
+-
+-extern int __bug_unaligned_x(void *ptr);
+-
+-/*
+- * What is the most efficient way of loading/storing an unaligned value?
+- *
+- * That is the subject of this file. Efficiency here is defined as
+- * minimum code size with minimum register usage for the common cases.
+- * It is currently not believed that long longs are common, so we
+- * trade efficiency for the chars, shorts and longs against the long
+- * longs.
+- *
+- * Current stats with gcc 2.7.2.2 for these functions:
+- *
+- * ptrsize get: code regs put: code regs
+- * 1 1 1 1 2
+- * 2 3 2 3 2
+- * 4 7 3 7 3
+- * 8 20 6 16 6
+- *
+- * gcc 2.95.1 seems to code differently:
+- *
+- * ptrsize get: code regs put: code regs
+- * 1 1 1 1 2
+- * 2 3 2 3 2
+- * 4 7 4 7 4
+- * 8 19 8 15 6
+- *
+- * which may or may not be more efficient (depending upon whether
+- * you can afford the extra registers). Hopefully the gcc 2.95
+- * is inteligent enough to decide if it is better to use the
+- * extra register, but evidence so far seems to suggest otherwise.
+- *
+- * Unfortunately, gcc is not able to optimise the high word
+- * out of long long >> 32, or the low word from long long << 32
+- */
+-
+-#define __get_unaligned_2(__p) \
+- (__p[0] | __p[1] << 8)
+-
+-#define __get_unaligned_4(__p) \
+- (__p[0] | __p[1] << 8 | __p[2] << 16 | __p[3] << 24)
+-
+-#define get_unaligned(ptr) \
+- ({ \
+- __typeof__(*(ptr)) __v; \
+- __u8 *__p = (__u8 *)(ptr); \
+- switch (sizeof(*(ptr))) { \
+- case 1: __v = *(ptr); break; \
+- case 2: __v = __get_unaligned_2(__p); break; \
+- case 4: __v = __get_unaligned_4(__p); break; \
+- case 8: { \
+- unsigned int __v1, __v2; \
+- __v2 = __get_unaligned_4((__p+4)); \
+- __v1 = __get_unaligned_4(__p); \
+- __v = ((unsigned long long)__v2 << 32 | __v1); \
+- } \
+- break; \
+- default: __v = __bug_unaligned_x(__p); break; \
+- } \
+- __v; \
+- })
+-
+-
+-static inline void __put_unaligned_2(__u32 __v, register __u8 *__p)
+-{
+- *__p++ = __v;
+- *__p++ = __v >> 8;
+-}
+-
+-static inline void __put_unaligned_4(__u32 __v, register __u8 *__p)
+-{
+- __put_unaligned_2(__v >> 16, __p + 2);
+- __put_unaligned_2(__v, __p);
+-}
+-
+-static inline void __put_unaligned_8(const unsigned long long __v, register __u8 *__p)
+-{
+- /*
+- * tradeoff: 8 bytes of stack for all unaligned puts (2
+- * instructions), or an extra register in the long long
+- * case - go for the extra register.
+- */
+- __put_unaligned_4(__v >> 32, __p+4);
+- __put_unaligned_4(__v, __p);
+-}
+-
+-/*
+- * Try to store an unaligned value as efficiently as possible.
+- */
+-#define put_unaligned(val,ptr) \
+- ({ \
+- switch (sizeof(*(ptr))) { \
+- case 1: \
+- *(ptr) = (val); \
+- break; \
+- case 2: __put_unaligned_2((val),(__u8 *)(ptr)); \
+- break; \
+- case 4: __put_unaligned_4((val),(__u8 *)(ptr)); \
+- break; \
+- case 8: __put_unaligned_8((val),(__u8 *)(ptr)); \
+- break; \
+- default: __bug_unaligned_x(ptr); \
+- break; \
+- } \
+- (void) 0; \
+- })
++#include <linux/unaligned/be_byteshift.h>
++#include <linux/unaligned/le_byteshift.h>
++#include <linux/unaligned/generic.h>
+
++#define get_unaligned __get_unaligned_le
++#define put_unaligned __put_unaligned_le
+
+-#endif /* __V850_UNALIGNED_H__ */
++#endif /* _ASM_V850_UNALIGNED_H */
diff --git a/include/asm-x86/Kbuild b/include/asm-x86/Kbuild
index 3b8160a..1e35545 100644
--- a/include/asm-x86/Kbuild
@@ -793304,7 +1060053,7 @@
+
+#endif /* _MACH_BIOS_EBDA_H */
diff --git a/include/asm-x86/bitops.h b/include/asm-x86/bitops.h
-index 1a23ce1..1ae7b27 100644
+index 1a23ce1..b81a4d4 100644
--- a/include/asm-x86/bitops.h
+++ b/include/asm-x86/bitops.h
@@ -23,10 +23,13 @@
@@ -793333,7 +1060082,21 @@
}
/**
-@@ -79,9 +80,7 @@ static inline void __set_bit(int nr, volatile void *addr)
+@@ -61,12 +62,9 @@ static inline void set_bit(int nr, volatile void *addr)
+ */
+ static inline void __set_bit(int nr, volatile void *addr)
+ {
+- asm volatile("bts %1,%0"
+- : ADDR
+- : "Ir" (nr) : "memory");
++ asm volatile("bts %1,%0" : ADDR : "Ir" (nr) : "memory");
+ }
+
+-
+ /**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+@@ -79,9 +77,7 @@ static inline void __set_bit(int nr, volatile void *addr)
*/
static inline void clear_bit(int nr, volatile void *addr)
{
@@ -793344,7 +1060107,7 @@
}
/*
-@@ -100,7 +99,7 @@ static inline void clear_bit_unlock(unsigned nr, volatile void *addr)
+@@ -100,7 +96,7 @@ static inline void clear_bit_unlock(unsigned nr, volatile void *addr)
static inline void __clear_bit(int nr, volatile void *addr)
{
@@ -793353,7 +1060116,7 @@
}
/*
-@@ -135,7 +134,7 @@ static inline void __clear_bit_unlock(unsigned nr, volatile void *addr)
+@@ -135,7 +131,7 @@ static inline void __clear_bit_unlock(unsigned nr, volatile void *addr)
*/
static inline void __change_bit(int nr, volatile void *addr)
{
@@ -793362,7 +1060125,7 @@
}
/**
-@@ -149,8 +148,7 @@ static inline void __change_bit(int nr, volatile void *addr)
+@@ -149,8 +145,7 @@ static inline void __change_bit(int nr, volatile void *addr)
*/
static inline void change_bit(int nr, volatile void *addr)
{
@@ -793372,7 +1060135,7 @@
}
/**
-@@ -166,9 +164,7 @@ static inline int test_and_set_bit(int nr, volatile void *addr)
+@@ -166,9 +161,7 @@ static inline int test_and_set_bit(int nr, volatile void *addr)
int oldbit;
asm volatile(LOCK_PREFIX "bts %2,%1\n\t"
@@ -793383,7 +1060146,7 @@
return oldbit;
}
-@@ -198,10 +194,9 @@ static inline int __test_and_set_bit(int nr, volatile void *addr)
+@@ -198,10 +191,9 @@ static inline int __test_and_set_bit(int nr, volatile void *addr)
{
int oldbit;
@@ -793397,7 +1060160,7 @@
return oldbit;
}
-@@ -219,8 +214,7 @@ static inline int test_and_clear_bit(int nr, volatile void *addr)
+@@ -219,8 +211,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"
@@ -793407,7 +1060170,7 @@
return oldbit;
}
-@@ -238,10 +232,9 @@ static inline int __test_and_clear_bit(int nr, volatile void *addr)
+@@ -238,10 +229,9 @@ static inline int __test_and_clear_bit(int nr, volatile void *addr)
{
int oldbit;
@@ -793420,7 +1060183,7 @@
return oldbit;
}
-@@ -250,10 +243,9 @@ static inline int __test_and_change_bit(int nr, volatile void *addr)
+@@ -250,10 +240,9 @@ static inline int __test_and_change_bit(int nr, volatile void *addr)
{
int oldbit;
@@ -793433,7 +1060196,7 @@
return oldbit;
}
-@@ -272,8 +264,7 @@ static inline int test_and_change_bit(int nr, volatile void *addr)
+@@ -272,8 +261,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"
@@ -793443,7 +1060206,7 @@
return oldbit;
}
-@@ -288,10 +279,11 @@ static inline int variable_test_bit(int nr, volatile const void *addr)
+@@ -288,10 +276,11 @@ static inline int variable_test_bit(int nr, volatile const void *addr)
{
int oldbit;
@@ -793457,23 +1060220,188 @@
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)))
+@@ -305,17 +294,145 @@ static inline int variable_test_bit(int nr, volatile const void *addr)
+ static int test_bit(int nr, const volatile unsigned long *addr);
+ #endif
+
+-#define test_bit(nr,addr) \
+- (__builtin_constant_p(nr) ? \
+- constant_test_bit((nr),(addr)) : \
+- variable_test_bit((nr),(addr)))
++#define test_bit(nr, addr) \
++ (__builtin_constant_p((nr)) \
++ ? constant_test_bit((nr), (addr)) \
++ : variable_test_bit((nr), (addr)))
+
+-#undef ADDR
++/**
++ * __ffs - find first set bit in word
++ * @word: The word to search
++ *
++ * Undefined if no bit exists, so code should check against 0 first.
++ */
++static inline unsigned long __ffs(unsigned long word)
++{
++ asm("bsf %1,%0"
++ : "=r" (word)
++ : "rm" (word));
++ return word;
++}
++
++/**
++ * ffz - find first zero bit in word
++ * @word: The word to search
++ *
++ * Undefined if no zero exists, so code should check against ~0UL first.
++ */
++static inline unsigned long ffz(unsigned long word)
++{
++ asm("bsf %1,%0"
++ : "=r" (word)
++ : "r" (~word));
++ return word;
++}
+-#ifdef CONFIG_X86_32
+-# include "bitops_32.h"
++/*
++ * __fls: find last set bit in word
++ * @word: The word to search
++ *
++ * Undefined if no zero exists, so code should check against ~0UL first.
++ */
++static inline unsigned long __fls(unsigned long word)
++{
++ asm("bsr %1,%0"
++ : "=r" (word)
++ : "rm" (word));
++ return word;
++}
++
++#ifdef __KERNEL__
++/**
++ * ffs - find first set bit in word
++ * @x: the word to search
++ *
++ * This is defined the same way as the libc and compiler builtin ffs
++ * routines, therefore differs in spirit from the other bitops.
++ *
++ * ffs(value) returns 0 if value is 0 or the position of the first
++ * set bit if value is nonzero. The first (least significant) bit
++ * is at position 1.
++ */
++static inline int ffs(int x)
++{
++ int r;
++#ifdef CONFIG_X86_CMOV
++ asm("bsfl %1,%0\n\t"
++ "cmovzl %2,%0"
++ : "=r" (r) : "rm" (x), "r" (-1));
+ #else
+-# include "bitops_64.h"
++ asm("bsfl %1,%0\n\t"
++ "jnz 1f\n\t"
++ "movl $-1,%0\n"
++ "1:" : "=r" (r) : "rm" (x));
+ #endif
++ return r + 1;
++}
++
++/**
++ * fls - find last set bit in word
++ * @x: the word to search
++ *
++ * This is defined in a similar way as the libc and compiler builtin
++ * ffs, but returns the position of the most significant set bit.
++ *
++ * fls(value) returns 0 if value is 0 or the position of the last
++ * set bit if value is nonzero. The last (most significant) bit is
++ * at position 32.
++ */
++static inline int fls(int x)
++{
++ int r;
++#ifdef CONFIG_X86_CMOV
++ asm("bsrl %1,%0\n\t"
++ "cmovzl %2,%0"
++ : "=&r" (r) : "rm" (x), "rm" (-1));
++#else
++ asm("bsrl %1,%0\n\t"
++ "jnz 1f\n\t"
++ "movl $-1,%0\n"
++ "1:" : "=r" (r) : "rm" (x));
++#endif
++ return r + 1;
++}
++#endif /* __KERNEL__ */
++
+#undef BASE_ADDR
+#undef BIT_ADDR
- #undef ADDR
++#undef ADDR
++
++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);
++ i++;
++ }
++}
++
++#ifdef __KERNEL__
++
++#include <asm-generic/bitops/sched.h>
++
++#define ARCH_HAS_FAST_MULTIPLIER 1
++
++#include <asm-generic/bitops/hweight.h>
++
++#endif /* __KERNEL__ */
++
++#include <asm-generic/bitops/fls64.h>
++
++#ifdef __KERNEL__
++
++#include <asm-generic/bitops/ext2-non-atomic.h>
++
++#define ext2_set_bit_atomic(lock, nr, addr) \
++ test_and_set_bit((nr), (unsigned long *)(addr))
++#define ext2_clear_bit_atomic(lock, nr, addr) \
++ test_and_clear_bit((nr), (unsigned long *)(addr))
++
++#include <asm-generic/bitops/minix.h>
- #ifdef CONFIG_X86_32
++#endif /* __KERNEL__ */
+ #endif /* _ASM_X86_BITOPS_H */
diff --git a/include/asm-x86/bitops_32.h b/include/asm-x86/bitops_32.h
-index e4d75fc..2513a81 100644
+deleted file mode 100644
+index e4d75fc..0000000
--- 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;
++++ /dev/null
+@@ -1,164 +0,0 @@
+-#ifndef _I386_BITOPS_H
+-#define _I386_BITOPS_H
+-
+-/*
+- * Copyright 1992, Linus Torvalds.
+- */
+-
+-/**
+- * find_first_zero_bit - find the first zero 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 zero bit, not the number of the byte
+- * containing a bit.
+- */
+-static inline int find_first_zero_bit(const unsigned long *addr, unsigned size)
+-{
+- int d0, d1, d2;
+- int res;
+-
+- 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"
@@ -793488,120 +1060416,302 @@
- "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;
+- return res;
+-}
+-
+-/**
+- * find_next_zero_bit - find the first zero bit in a memory region
+- * @addr: The address to base the search on
+- * @offset: The bit number to start searching at
+- * @size: The maximum size to search
+- */
+-int find_next_zero_bit(const unsigned long *addr, int size, int offset);
+-
+-/**
+- * __ffs - find first bit in word.
+- * @word: The word to search
+- *
+- * Undefined if no bit exists, so code should check against 0 first.
+- */
+-static inline unsigned long __ffs(unsigned long word)
+-{
+- __asm__("bsfl %1,%0"
+- :"=r" (word)
+- :"rm" (word));
+- return word;
+-}
+-
+-/**
+- * 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.
+- */
+-static inline unsigned find_first_bit(const unsigned long *addr, unsigned size)
+-{
+- unsigned x = 0;
+-
+- while (x < size) {
+- unsigned long val = *addr++;
+- if (val)
+- return __ffs(val) + x;
- x += (sizeof(*addr)<<3);
-+ x += sizeof(*addr) << 3;
- }
- return x;
- }
-@@ -152,10 +154,10 @@ static inline int fls(int x)
-
- #include <asm-generic/bitops/ext2-non-atomic.h>
-
+- }
+- return x;
+-}
+-
+-/**
+- * find_next_bit - find the first set bit in a memory region
+- * @addr: The address to base the search on
+- * @offset: The bit number to start searching at
+- * @size: The maximum size to search
+- */
+-int find_next_bit(const unsigned long *addr, int size, int offset);
+-
+-/**
+- * ffz - find first zero in word.
+- * @word: The word to search
+- *
+- * Undefined if no zero exists, so code should check against ~0UL first.
+- */
+-static inline unsigned long ffz(unsigned long word)
+-{
+- __asm__("bsfl %1,%0"
+- :"=r" (word)
+- :"r" (~word));
+- return word;
+-}
+-
+-#ifdef __KERNEL__
+-
+-#include <asm-generic/bitops/sched.h>
+-
+-/**
+- * ffs - find first bit set
+- * @x: the word to search
+- *
+- * This is defined the same way as
+- * the libc and compiler builtin ffs routines, therefore
+- * differs in spirit from the above ffz() (man ffs).
+- */
+-static inline int ffs(int x)
+-{
+- int r;
+-
+- __asm__("bsfl %1,%0\n\t"
+- "jnz 1f\n\t"
+- "movl $-1,%0\n"
+- "1:" : "=r" (r) : "rm" (x));
+- return r+1;
+-}
+-
+-/**
+- * fls - find last bit set
+- * @x: the word to search
+- *
+- * This is defined the same way as ffs().
+- */
+-static inline int fls(int x)
+-{
+- int r;
+-
+- __asm__("bsrl %1,%0\n\t"
+- "jnz 1f\n\t"
+- "movl $-1,%0\n"
+- "1:" : "=r" (r) : "rm" (x));
+- return r+1;
+-}
+-
+-#include <asm-generic/bitops/hweight.h>
+-
+-#endif /* __KERNEL__ */
+-
+-#include <asm-generic/bitops/fls64.h>
+-
+-#ifdef __KERNEL__
+-
+-#include <asm-generic/bitops/ext2-non-atomic.h>
+-
-#define ext2_set_bit_atomic(lock, nr, addr) \
- test_and_set_bit((nr), (unsigned long *)addr)
-#define ext2_clear_bit_atomic(lock, nr, addr) \
- test_and_clear_bit((nr), (unsigned long *)addr)
-+#define ext2_set_bit_atomic(lock, nr, addr) \
-+ test_and_set_bit((nr), (unsigned long *)(addr))
-+#define ext2_clear_bit_atomic(lock, nr, addr) \
-+ test_and_clear_bit((nr), (unsigned long *)(addr))
-
- #include <asm-generic/bitops/minix.h>
-
+-
+-#include <asm-generic/bitops/minix.h>
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* _I386_BITOPS_H */
diff --git a/include/asm-x86/bitops_64.h b/include/asm-x86/bitops_64.h
-index aaf1519..365f820 100644
+deleted file mode 100644
+index aaf1519..0000000
--- 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;
- }
-
++++ /dev/null
+@@ -1,162 +0,0 @@
+-#ifndef _X86_64_BITOPS_H
+-#define _X86_64_BITOPS_H
+-
+-/*
+- * Copyright 1992, Linus Torvalds.
+- */
+-
+-extern long find_first_zero_bit(const unsigned long *addr, unsigned long size);
+-extern long find_next_zero_bit(const unsigned long *addr, long size, long offset);
+-extern long find_first_bit(const unsigned long *addr, unsigned long size);
+-extern long find_next_bit(const unsigned long *addr, long size, long offset);
+-
+-/* return index of first bet set in val or max when no bit is set */
+-static inline long __scanbit(unsigned long val, unsigned long max)
+-{
+- asm("bsfq %1,%0 ; cmovz %2,%0" : "=&r" (val) : "r" (val), "r" (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_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)))
-
+-#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) {
+- while (i < end) {
- __set_bit(i, bitmap);
-+ __set_bit(i, bitmap);
- i++;
- }
+- i++;
+- }
-}
-+}
-
- /**
- * ffz - find first zero in word.
-@@ -150,10 +150,10 @@ static inline int fls(int x)
-
- #include <asm-generic/bitops/ext2-non-atomic.h>
-
+-
+-/**
+- * ffz - find first zero in word.
+- * @word: The word to search
+- *
+- * Undefined if no zero exists, so code should check against ~0UL first.
+- */
+-static inline unsigned long ffz(unsigned long word)
+-{
+- __asm__("bsfq %1,%0"
+- :"=r" (word)
+- :"r" (~word));
+- return word;
+-}
+-
+-/**
+- * __ffs - find first bit in word.
+- * @word: The word to search
+- *
+- * Undefined if no bit exists, so code should check against 0 first.
+- */
+-static inline unsigned long __ffs(unsigned long word)
+-{
+- __asm__("bsfq %1,%0"
+- :"=r" (word)
+- :"rm" (word));
+- return word;
+-}
+-
+-/*
+- * __fls: find last bit set.
+- * @word: The word to search
+- *
+- * Undefined if no zero exists, so code should check against ~0UL first.
+- */
+-static inline unsigned long __fls(unsigned long word)
+-{
+- __asm__("bsrq %1,%0"
+- :"=r" (word)
+- :"rm" (word));
+- return word;
+-}
+-
+-#ifdef __KERNEL__
+-
+-#include <asm-generic/bitops/sched.h>
+-
+-/**
+- * ffs - find first bit set
+- * @x: the word to search
+- *
+- * This is defined the same way as
+- * the libc and compiler builtin ffs routines, therefore
+- * differs in spirit from the above ffz (man ffs).
+- */
+-static inline int ffs(int x)
+-{
+- int r;
+-
+- __asm__("bsfl %1,%0\n\t"
+- "cmovzl %2,%0"
+- : "=r" (r) : "rm" (x), "r" (-1));
+- return r+1;
+-}
+-
+-/**
+- * fls64 - find last bit set in 64 bit word
+- * @x: the word to search
+- *
+- * This is defined the same way as fls.
+- */
+-static inline int fls64(__u64 x)
+-{
+- if (x == 0)
+- return 0;
+- return __fls(x) + 1;
+-}
+-
+-/**
+- * fls - find last bit set
+- * @x: the word to search
+- *
+- * This is defined the same way as ffs.
+- */
+-static inline int fls(int x)
+-{
+- int r;
+-
+- __asm__("bsrl %1,%0\n\t"
+- "cmovzl %2,%0"
+- : "=&r" (r) : "rm" (x), "rm" (-1));
+- return r+1;
+-}
+-
+-#define ARCH_HAS_FAST_MULTIPLIER 1
+-
+-#include <asm-generic/bitops/hweight.h>
+-
+-#endif /* __KERNEL__ */
+-
+-#ifdef __KERNEL__
+-
+-#include <asm-generic/bitops/ext2-non-atomic.h>
+-
-#define ext2_set_bit_atomic(lock,nr,addr) \
- test_and_set_bit((nr),(unsigned long*)addr)
-#define ext2_clear_bit_atomic(lock,nr,addr) \
- test_and_clear_bit((nr),(unsigned long*)addr)
-+#define ext2_set_bit_atomic(lock, nr, addr) \
-+ test_and_set_bit((nr), (unsigned long *)(addr))
-+#define ext2_clear_bit_atomic(lock, nr, addr) \
-+ test_and_clear_bit((nr), (unsigned long *)(addr))
-
- #include <asm-generic/bitops/minix.h>
-
+-
+-#include <asm-generic/bitops/minix.h>
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* _X86_64_BITOPS_H */
diff --git a/include/asm-x86/boot.h b/include/asm-x86/boot.h
index ed8affb..2faed7e 100644
--- a/include/asm-x86/boot.h
@@ -793619,6 +1060729,38 @@
+#endif
+
#endif /* _ASM_BOOT_H */
+diff --git a/include/asm-x86/bootparam.h b/include/asm-x86/bootparam.h
+index 5115135..e865990 100644
+--- a/include/asm-x86/bootparam.h
++++ b/include/asm-x86/bootparam.h
+@@ -9,6 +9,17 @@
+ #include <asm/ist.h>
+ #include <video/edid.h>
+
++/* setup data types */
++#define SETUP_NONE 0
++
++/* extensible setup data list node */
++struct setup_data {
++ u64 next;
++ u32 type;
++ u32 len;
++ u8 data[0];
++};
++
+ struct setup_header {
+ __u8 setup_sects;
+ __u16 root_flags;
+@@ -46,6 +57,9 @@ struct setup_header {
+ __u32 cmdline_size;
+ __u32 hardware_subarch;
+ __u64 hardware_subarch_data;
++ __u32 payload_offset;
++ __u32 payload_length;
++ __u64 setup_data;
+ } __attribute__((packed));
+
+ struct sys_desc_table {
diff --git a/include/asm-x86/bug.h b/include/asm-x86/bug.h
index 8d477a2..b69aa64 100644
--- a/include/asm-x86/bug.h
@@ -796052,7 +1063194,7 @@
#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
+index 22ede73..71c4d68 100644
--- a/include/asm-x86/e820_64.h
+++ b/include/asm-x86/e820_64.h
@@ -14,20 +14,24 @@
@@ -796099,6 +1063241,16 @@
extern void finish_e820_parsing(void);
+@@ -44,7 +48,8 @@ extern struct e820map e820;
+ extern void update_e820(void);
+
+ extern void reserve_early(unsigned long start, unsigned long end, char *name);
+-extern void early_res_to_bootmem(void);
++extern void free_early(unsigned long start, unsigned long end);
++extern void early_res_to_bootmem(unsigned long start, unsigned long end);
+
+ #endif/*!__ASSEMBLY__*/
+
diff --git a/include/asm-x86/edac.h b/include/asm-x86/edac.h
index cf3200a..a8088f6 100644
--- a/include/asm-x86/edac.h
@@ -796705,11 +1063857,20 @@
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
+index c9952ea..e7a76b3 100644
--- a/include/asm-x86/futex.h
+++ b/include/asm-x86/futex.h
-@@ -12,35 +12,32 @@
- #include <asm/uaccess.h>
+@@ -4,43 +4,40 @@
+ #ifdef __KERNEL__
+
+ #include <linux/futex.h>
++#include <linux/uaccess.h>
+
+ #include <asm/asm.h>
+ #include <asm/errno.h>
+ #include <asm/processor.h>
+ #include <asm/system.h>
+-#include <asm/uaccess.h>
#define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \
- __asm__ __volatile( \
@@ -797018,10 +1064179,72 @@
#endif
diff --git a/include/asm-x86/geode.h b/include/asm-x86/geode.h
-index 9e72800..9870cc1 100644
+index 9e72800..7154dc4 100644
--- a/include/asm-x86/geode.h
+++ b/include/asm-x86/geode.h
-@@ -167,7 +167,7 @@ static inline int is_geode(void)
+@@ -30,7 +30,13 @@ extern int geode_get_dev_base(unsigned int dev);
+
+ /* MSRS */
+
+-#define GX_GLCP_SYS_RSTPLL 0x4C000014
++#define MSR_GLIU_P2D_RO0 0x10000029
++
++#define MSR_LX_GLD_MSR_CONFIG 0x48002001
++#define MSR_LX_MSR_PADSEL 0x48002011 /* NOT 0x48000011; the data
++ * sheet has the wrong value */
++#define MSR_GLCP_SYS_RSTPLL 0x4C000014
++#define MSR_GLCP_DOTPLL 0x4C000015
+
+ #define MSR_LBAR_SMB 0x5140000B
+ #define MSR_LBAR_GPIO 0x5140000C
+@@ -45,8 +51,14 @@ extern int geode_get_dev_base(unsigned int dev);
+ #define MSR_PIC_ZSEL_LOW 0x51400022
+ #define MSR_PIC_ZSEL_HIGH 0x51400023
+
+-#define MFGPT_IRQ_MSR 0x51400028
+-#define MFGPT_NR_MSR 0x51400029
++#define MSR_MFGPT_IRQ 0x51400028
++#define MSR_MFGPT_NR 0x51400029
++#define MSR_MFGPT_SETUP 0x5140002B
++
++#define MSR_LX_SPARE_MSR 0x80000011 /* DC-specific */
++
++#define MSR_GX_GLD_MSR_CONFIG 0xC0002001
++#define MSR_GX_MSR_PADSEL 0xC0002011
+
+ /* Resource Sizes */
+
+@@ -93,6 +105,15 @@ extern int geode_get_dev_base(unsigned int dev);
+ #define PM_AWKD 0x50
+ #define PM_SSC 0x54
+
++/* VSA2 magic values */
++
++#define VSA_VRC_INDEX 0xAC1C
++#define VSA_VRC_DATA 0xAC1E
++#define VSA_VR_UNLOCK 0xFC53 /* unlock virtual register */
++#define VSA_VR_SIGNATURE 0x0003
++#define VSA_VR_MEM_SIZE 0x0200
++#define VSA_SIG 0x4132 /* signature is ascii 'VSA2' */
++
+ /* GPIO */
+
+ #define GPIO_OUTPUT_VAL 0x00
+@@ -164,10 +185,21 @@ static inline int is_geode(void)
+ return (is_geode_gx() || is_geode_lx());
+ }
+
++/*
++ * The VSA has virtual registers that we can query for a signature.
++ */
++static inline int geode_has_vsa2(void)
++{
++ outw(VSA_VR_UNLOCK, VSA_VRC_INDEX);
++ outw(VSA_VR_SIGNATURE, VSA_VRC_INDEX);
++
++ return (inw(VSA_VRC_DATA) == VSA_SIG);
++}
++
/* MFGPTs */
#define MFGPT_MAX_TIMERS 8
@@ -797043,6 +1064266,103 @@
* 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/hugetlb.h b/include/asm-x86/hugetlb.h
+new file mode 100644
+index 0000000..14171a4
+--- /dev/null
++++ b/include/asm-x86/hugetlb.h
+@@ -0,0 +1,91 @@
++#ifndef _ASM_X86_HUGETLB_H
++#define _ASM_X86_HUGETLB_H
++
++#include <asm/page.h>
++
++
++static inline int is_hugepage_only_range(struct mm_struct *mm,
++ unsigned long addr,
++ unsigned long len) {
++ return 0;
++}
++
++/*
++ * If the arch doesn't supply something else, assume that hugepage
++ * size aligned regions are ok without further preparation.
++ */
++static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
++{
++ if (len & ~HPAGE_MASK)
++ return -EINVAL;
++ if (addr & ~HPAGE_MASK)
++ return -EINVAL;
++ return 0;
++}
++
++static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm) {
++}
++
++static inline void hugetlb_free_pgd_range(struct mmu_gather **tlb,
++ unsigned long addr, unsigned long end,
++ unsigned long floor,
++ unsigned long ceiling)
++{
++ free_pgd_range(tlb, addr, end, floor, ceiling);
++}
++
++static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
++ pte_t *ptep, pte_t pte)
++{
++ set_pte_at(mm, addr, ptep, pte);
++}
++
++static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
++ unsigned long addr, pte_t *ptep)
++{
++ return ptep_get_and_clear(mm, addr, ptep);
++}
++
++static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
++ unsigned long addr, pte_t *ptep)
++{
++}
++
++static inline int huge_pte_none(pte_t pte)
++{
++ return pte_none(pte);
++}
++
++static inline pte_t huge_pte_wrprotect(pte_t pte)
++{
++ return pte_wrprotect(pte);
++}
++
++static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
++ unsigned long addr, pte_t *ptep)
++{
++ ptep_set_wrprotect(mm, addr, ptep);
++}
++
++static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
++ unsigned long addr, pte_t *ptep,
++ pte_t pte, int dirty)
++{
++ return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
++}
++
++static inline pte_t huge_ptep_get(pte_t *ptep)
++{
++ return *ptep;
++}
++
++static inline int arch_prepare_hugepage(struct page *page)
++{
++ return 0;
++}
++
++static inline void arch_release_hugepage(struct page *page)
++{
++}
++
++#endif /* _ASM_X86_HUGETLB_H */
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
@@ -798419,12 +1065739,71 @@
#define flush_insn_slot(p) do { } while (0)
+diff --git a/include/asm-x86/kvm.h b/include/asm-x86/kvm.h
+index 7a71120..80eefef 100644
+--- a/include/asm-x86/kvm.h
++++ b/include/asm-x86/kvm.h
+@@ -188,4 +188,45 @@ struct kvm_cpuid2 {
+ struct kvm_cpuid_entry2 entries[0];
+ };
+
++/* for KVM_GET_PIT and KVM_SET_PIT */
++struct kvm_pit_channel_state {
++ __u32 count; /* can be 65536 */
++ __u16 latched_count;
++ __u8 count_latched;
++ __u8 status_latched;
++ __u8 status;
++ __u8 read_state;
++ __u8 write_state;
++ __u8 write_latch;
++ __u8 rw_mode;
++ __u8 mode;
++ __u8 bcd;
++ __u8 gate;
++ __s64 count_load_time;
++};
++
++struct kvm_pit_state {
++ struct kvm_pit_channel_state channels[3];
++};
++
++#define KVM_TRC_INJ_VIRQ (KVM_TRC_HANDLER + 0x02)
++#define KVM_TRC_REDELIVER_EVT (KVM_TRC_HANDLER + 0x03)
++#define KVM_TRC_PEND_INTR (KVM_TRC_HANDLER + 0x04)
++#define KVM_TRC_IO_READ (KVM_TRC_HANDLER + 0x05)
++#define KVM_TRC_IO_WRITE (KVM_TRC_HANDLER + 0x06)
++#define KVM_TRC_CR_READ (KVM_TRC_HANDLER + 0x07)
++#define KVM_TRC_CR_WRITE (KVM_TRC_HANDLER + 0x08)
++#define KVM_TRC_DR_READ (KVM_TRC_HANDLER + 0x09)
++#define KVM_TRC_DR_WRITE (KVM_TRC_HANDLER + 0x0A)
++#define KVM_TRC_MSR_READ (KVM_TRC_HANDLER + 0x0B)
++#define KVM_TRC_MSR_WRITE (KVM_TRC_HANDLER + 0x0C)
++#define KVM_TRC_CPUID (KVM_TRC_HANDLER + 0x0D)
++#define KVM_TRC_INTR (KVM_TRC_HANDLER + 0x0E)
++#define KVM_TRC_NMI (KVM_TRC_HANDLER + 0x0F)
++#define KVM_TRC_VMMCALL (KVM_TRC_HANDLER + 0x10)
++#define KVM_TRC_HLT (KVM_TRC_HANDLER + 0x11)
++#define KVM_TRC_CLTS (KVM_TRC_HANDLER + 0x12)
++#define KVM_TRC_LMSW (KVM_TRC_HANDLER + 0x13)
++#define KVM_TRC_APIC_ACCESS (KVM_TRC_HANDLER + 0x14)
++
+ #endif
diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h
-index 4702b04..68ee390 100644
+index 4702b04..9d963cd 100644
--- a/include/asm-x86/kvm_host.h
+++ b/include/asm-x86/kvm_host.h
-@@ -22,15 +22,16 @@
+@@ -20,17 +20,25 @@
+
+ #include <asm/desc.h>
++#define KVM_MAX_VCPUS 16
++#define KVM_MEMORY_SLOTS 32
++/* memory slots that does not exposed to userspace */
++#define KVM_PRIVATE_MEM_SLOTS 4
++
++#define KVM_PIO_PAGE_OFFSET 1
++
#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)
@@ -798444,7 +1065823,52 @@
(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 {
+@@ -38,6 +46,13 @@
+ #define INVALID_PAGE (~(hpa_t)0)
+ #define UNMAPPED_GVA (~(gpa_t)0)
+
++/* shadow tables are PAE even on non-PAE hosts */
++#define KVM_HPAGE_SHIFT 21
++#define KVM_HPAGE_SIZE (1UL << KVM_HPAGE_SHIFT)
++#define KVM_HPAGE_MASK (~(KVM_HPAGE_SIZE - 1))
++
++#define KVM_PAGES_PER_HPAGE (KVM_HPAGE_SIZE / PAGE_SIZE)
++
+ #define DE_VECTOR 0
+ #define UD_VECTOR 6
+ #define NM_VECTOR 7
+@@ -47,6 +62,7 @@
+ #define SS_VECTOR 12
+ #define GP_VECTOR 13
+ #define PF_VECTOR 14
++#define MC_VECTOR 18
+
+ #define SELECTOR_TI_MASK (1 << 2)
+ #define SELECTOR_RPL_MASK 0x03
+@@ -57,7 +73,8 @@
+
+ #define KVM_PERMILLE_MMU_PAGES 20
+ #define KVM_MIN_ALLOC_MMU_PAGES 64
+-#define KVM_NUM_MMU_PAGES 1024
++#define KVM_MMU_HASH_SHIFT 10
++#define KVM_NUM_MMU_PAGES (1 << KVM_MMU_HASH_SHIFT)
+ #define KVM_MIN_FREE_MMU_PAGES 5
+ #define KVM_REFILL_PAGES 25
+ #define KVM_MAX_CPUID_ENTRIES 40
+@@ -105,6 +122,12 @@ enum {
+
+ #define KVM_NR_MEM_OBJS 40
+
++struct kvm_guest_debug {
++ int enabled;
++ unsigned long bp[4];
++ int singlestep;
++};
++
+ /*
+ * We don't want allocation failures within the mmu code, so we preallocate
+ * enough memory for a single page fault in a cache.
+@@ -133,12 +156,13 @@ struct kvm_pte_chain {
union kvm_mmu_page_role {
unsigned word;
struct {
@@ -798460,18 +1065884,251 @@
+ unsigned pad_for_nice_hex_output:6;
+ unsigned metaphysical:1;
+ unsigned access:3;
++ unsigned invalid:1;
};
};
-@@ -606,6 +607,7 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code)
+@@ -203,11 +227,6 @@ struct kvm_vcpu_arch {
+ u64 shadow_efer;
+ u64 apic_base;
+ struct kvm_lapic *apic; /* kernel irqchip context */
+-#define VCPU_MP_STATE_RUNNABLE 0
+-#define VCPU_MP_STATE_UNINITIALIZED 1
+-#define VCPU_MP_STATE_INIT_RECEIVED 2
+-#define VCPU_MP_STATE_SIPI_RECEIVED 3
+-#define VCPU_MP_STATE_HALTED 4
+ int mp_state;
+ int sipi_vector;
+ u64 ia32_misc_enable_msr;
+@@ -225,8 +244,9 @@ struct kvm_vcpu_arch {
+ u64 *last_pte_updated;
+
+ struct {
+- gfn_t gfn; /* presumed gfn during guest pte update */
+- struct page *page; /* page corresponding to that gfn */
++ gfn_t gfn; /* presumed gfn during guest pte update */
++ pfn_t pfn; /* pfn corresponding to that gfn */
++ int largepage;
+ } update_pte;
+
+ struct i387_fxsave_struct host_fx_image;
+@@ -260,6 +280,11 @@ struct kvm_vcpu_arch {
+ /* emulate context */
+
+ struct x86_emulate_ctxt emulate_ctxt;
++
++ gpa_t time;
++ struct kvm_vcpu_time_info hv_clock;
++ unsigned int time_offset;
++ struct page *time_page;
+ };
+
+ struct kvm_mem_alias {
+@@ -282,10 +307,13 @@ struct kvm_arch{
+ struct list_head active_mmu_pages;
+ struct kvm_pic *vpic;
+ struct kvm_ioapic *vioapic;
++ struct kvm_pit *vpit;
+
+ int round_robin_prev_vcpu;
+ unsigned int tss_addr;
+ struct page *apic_access_page;
++
++ gpa_t wall_clock;
+ };
+
+ struct kvm_vm_stat {
+@@ -297,6 +325,7 @@ struct kvm_vm_stat {
+ u32 mmu_recycled;
+ u32 mmu_cache_miss;
+ u32 remote_tlb_flush;
++ u32 lpages;
+ };
+
+ struct kvm_vcpu_stat {
+@@ -319,6 +348,7 @@ struct kvm_vcpu_stat {
+ u32 fpu_reload;
+ u32 insn_emulation;
+ u32 insn_emulation_fail;
++ u32 hypercalls;
+ };
+
+ struct descriptor_table {
+@@ -354,6 +384,7 @@ struct kvm_x86_ops {
+ u64 (*get_segment_base)(struct kvm_vcpu *vcpu, int seg);
+ void (*get_segment)(struct kvm_vcpu *vcpu,
+ struct kvm_segment *var, int seg);
++ int (*get_cpl)(struct kvm_vcpu *vcpu);
+ void (*set_segment)(struct kvm_vcpu *vcpu,
+ struct kvm_segment *var, int seg);
+ void (*get_cs_db_l_bits)(struct kvm_vcpu *vcpu, int *db, int *l);
+@@ -409,6 +440,15 @@ void kvm_mmu_zap_all(struct kvm *kvm);
+ unsigned int kvm_mmu_calculate_mmu_pages(struct kvm *kvm);
+ void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int kvm_nr_mmu_pages);
+
++int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3);
++
++int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
++ const void *val, int bytes);
++int kvm_pv_mmu_op(struct kvm_vcpu *vcpu, unsigned long bytes,
++ gpa_t addr, unsigned long *ret);
++
++extern bool tdp_enabled;
++
+ enum emulation_result {
+ EMULATE_DONE, /* no further processing */
+ EMULATE_DO_MMIO, /* kvm_run filled with mmio request */
+@@ -428,6 +468,7 @@ void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw,
+ unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr);
+ void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long value,
+ unsigned long *rflags);
++void kvm_enable_efer_bits(u64);
+ int kvm_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *data);
+ int kvm_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data);
+
+@@ -447,12 +488,14 @@ int emulator_get_dr(struct x86_emulate_ctxt *ctxt, int dr,
+ int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr,
+ unsigned long value);
+
+-void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
+-void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr0);
+-void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr0);
+-void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr0);
+-unsigned long get_cr8(struct kvm_vcpu *vcpu);
+-void lmsw(struct kvm_vcpu *vcpu, unsigned long msw);
++int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason);
++
++void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
++void kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3);
++void kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
++void kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8);
++unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu);
++void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw);
+ void kvm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l);
+
+ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata);
+@@ -490,6 +533,8 @@ int kvm_fix_hypercall(struct kvm_vcpu *vcpu);
+
+ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, u32 error_code);
+
++void kvm_enable_tdp(void);
++
+ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3);
+ int complete_pio(struct kvm_vcpu *vcpu);
+
+@@ -599,6 +644,7 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code)
+ #define ASM_VMX_VMWRITE_RSP_RDX ".byte 0x0f, 0x79, 0xd4"
+ #define ASM_VMX_VMXOFF ".byte 0x0f, 0x01, 0xc4"
+ #define ASM_VMX_VMXON_RAX ".byte 0xf3, 0x0f, 0xc7, 0x30"
++#define ASM_VMX_INVVPID ".byte 0x66, 0x0f, 0x38, 0x81, 0x08"
+
+ #define MSR_IA32_TIME_STAMP_COUNTER 0x010
+
+@@ -606,6 +652,33 @@ 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)
++
++enum {
++ TASK_SWITCH_CALL = 0,
++ TASK_SWITCH_IRET = 1,
++ TASK_SWITCH_JMP = 2,
++ TASK_SWITCH_GATE = 3,
++};
++
++#define KVMTRACE_5D(evt, vcpu, d1, d2, d3, d4, d5, name) \
++ trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
++ vcpu, 5, d1, d2, d3, d4, d5)
++#define KVMTRACE_4D(evt, vcpu, d1, d2, d3, d4, name) \
++ trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
++ vcpu, 4, d1, d2, d3, d4, 0)
++#define KVMTRACE_3D(evt, vcpu, d1, d2, d3, name) \
++ trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
++ vcpu, 3, d1, d2, d3, 0, 0)
++#define KVMTRACE_2D(evt, vcpu, d1, d2, name) \
++ trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
++ vcpu, 2, d1, d2, 0, 0, 0)
++#define KVMTRACE_1D(evt, vcpu, d1, name) \
++ trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
++ vcpu, 1, d1, 0, 0, 0, 0)
++#define KVMTRACE_0D(evt, vcpu, name) \
++ trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
++ vcpu, 0, 0, 0, 0, 0, 0)
+
+ #endif
+diff --git a/include/asm-x86/kvm_para.h b/include/asm-x86/kvm_para.h
+index c6f3fd8..5098459 100644
+--- a/include/asm-x86/kvm_para.h
++++ b/include/asm-x86/kvm_para.h
+@@ -10,10 +10,65 @@
+ * paravirtualization, the appropriate feature bit should be checked.
+ */
+ #define KVM_CPUID_FEATURES 0x40000001
++#define KVM_FEATURE_CLOCKSOURCE 0
++#define KVM_FEATURE_NOP_IO_DELAY 1
++#define KVM_FEATURE_MMU_OP 2
++
++#define MSR_KVM_WALL_CLOCK 0x11
++#define MSR_KVM_SYSTEM_TIME 0x12
++
++#define KVM_MAX_MMU_OP_BATCH 32
++
++/* Operations for KVM_HC_MMU_OP */
++#define KVM_MMU_OP_WRITE_PTE 1
++#define KVM_MMU_OP_FLUSH_TLB 2
++#define KVM_MMU_OP_RELEASE_PT 3
++
++/* Payload for KVM_HC_MMU_OP */
++struct kvm_mmu_op_header {
++ __u32 op;
++ __u32 pad;
++};
++
++struct kvm_mmu_op_write_pte {
++ struct kvm_mmu_op_header header;
++ __u64 pte_phys;
++ __u64 pte_val;
++};
++
++struct kvm_mmu_op_flush_tlb {
++ struct kvm_mmu_op_header header;
++};
++
++struct kvm_mmu_op_release_pt {
++ struct kvm_mmu_op_header header;
++ __u64 pt_phys;
++};
- #endif
+ #ifdef __KERNEL__
+ #include <asm/processor.h>
+
++/* xen binary-compatible interface. See xen headers for details */
++struct kvm_vcpu_time_info {
++ uint32_t version;
++ uint32_t pad0;
++ uint64_t tsc_timestamp;
++ uint64_t system_time;
++ uint32_t tsc_to_system_mul;
++ int8_t tsc_shift;
++ int8_t pad[3];
++} __attribute__((__packed__)); /* 32 bytes */
++
++struct kvm_wall_clock {
++ uint32_t wc_version;
++ uint32_t wc_sec;
++ uint32_t wc_nsec;
++} __attribute__((__packed__));
++
++
++extern void kvmclock_init(void);
++
++
+ /* This instruction is vmcall. On non-VT architectures, it will generate a
+ * trap that we will then rewrite to the appropriate instruction.
+ */
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
@@ -798858,7 +1066515,7 @@
-
-#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
+index e3c2c10..21003b5 100644
--- a/include/asm-x86/mach-default/mach_apic.h
+++ b/include/asm-x86/mach-default/mach_apic.h
@@ -1,6 +1,8 @@
@@ -798964,21 +1066621,18 @@
{
return 0;
}
-@@ -78,8 +109,13 @@ static inline int cpu_to_logical_apicid(int cpu)
+@@ -78,8 +109,8 @@ 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))
+- if (mps_cpu < get_physical_broadcast())
+- return mps_cpu;
++ if (mps_cpu < NR_CPUS && 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)
+@@ -89,17 +120,6 @@ static inline physid_mask_t apicid_to_cpu_present(int phys_apicid)
return physid_mask_of_physid(phys_apicid);
}
@@ -798996,7 +1066650,7 @@
static inline void setup_portio_remap(void)
{
}
-@@ -109,23 +134,9 @@ static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
+@@ -109,23 +129,9 @@ static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
return physid_isset(boot_cpu_physical_apicid, phys_cpu_present_map);
}
@@ -801039,6 +1068693,144 @@
};
static inline unsigned long *get_zholes_size(int nid)
+diff --git a/include/asm-x86/olpc.h b/include/asm-x86/olpc.h
+new file mode 100644
+index 0000000..97d4713
+--- /dev/null
++++ b/include/asm-x86/olpc.h
+@@ -0,0 +1,132 @@
++/* OLPC machine specific definitions */
++
++#ifndef ASM_OLPC_H_
++#define ASM_OLPC_H_
++
++#include <asm/geode.h>
++
++struct olpc_platform_t {
++ int flags;
++ uint32_t boardrev;
++ int ecver;
++};
++
++#define OLPC_F_PRESENT 0x01
++#define OLPC_F_DCON 0x02
++#define OLPC_F_VSA 0x04
++
++#ifdef CONFIG_OLPC
++
++extern struct olpc_platform_t olpc_platform_info;
++
++/*
++ * OLPC board IDs contain the major build number within the mask 0x0ff0,
++ * and the minor build number withing 0x000f. Pre-builds have a minor
++ * number less than 8, and normal builds start at 8. For example, 0x0B10
++ * is a PreB1, and 0x0C18 is a C1.
++ */
++
++static inline uint32_t olpc_board(uint8_t id)
++{
++ return (id << 4) | 0x8;
++}
++
++static inline uint32_t olpc_board_pre(uint8_t id)
++{
++ return id << 4;
++}
++
++static inline int machine_is_olpc(void)
++{
++ return (olpc_platform_info.flags & OLPC_F_PRESENT) ? 1 : 0;
++}
++
++/*
++ * The DCON is OLPC's Display Controller. It has a number of unique
++ * features that we might want to take advantage of..
++ */
++static inline int olpc_has_dcon(void)
++{
++ return (olpc_platform_info.flags & OLPC_F_DCON) ? 1 : 0;
++}
++
++/*
++ * The VSA is software from AMD that typical Geode bioses will include.
++ * It is used to emulate the PCI bus, VGA, etc. OLPC's Open Firmware does
++ * not include the VSA; instead, PCI is emulated by the kernel.
++ *
++ * The VSA is described further in arch/x86/pci/olpc.c.
++ */
++static inline int olpc_has_vsa(void)
++{
++ return (olpc_platform_info.flags & OLPC_F_VSA) ? 1 : 0;
++}
++
++/*
++ * The "Mass Production" version of OLPC's XO is identified as being model
++ * C2. During the prototype phase, the following models (in chronological
++ * order) were created: A1, B1, B2, B3, B4, C1. The A1 through B2 models
++ * were based on Geode GX CPUs, and models after that were based upon
++ * Geode LX CPUs. There were also some hand-assembled models floating
++ * around, referred to as PreB1, PreB2, etc.
++ */
++static inline int olpc_board_at_least(uint32_t rev)
++{
++ return olpc_platform_info.boardrev >= rev;
++}
++
++#else
++
++static inline int machine_is_olpc(void)
++{
++ return 0;
++}
++
++static inline int olpc_has_dcon(void)
++{
++ return 0;
++}
++
++static inline int olpc_has_vsa(void)
++{
++ return 0;
++}
++
++#endif
++
++/* EC related functions */
++
++extern int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
++ unsigned char *outbuf, size_t outlen);
++
++extern int olpc_ec_mask_set(uint8_t bits);
++extern int olpc_ec_mask_unset(uint8_t bits);
++
++/* EC commands */
++
++#define EC_FIRMWARE_REV 0x08
++
++/* SCI source values */
++
++#define EC_SCI_SRC_EMPTY 0x00
++#define EC_SCI_SRC_GAME 0x01
++#define EC_SCI_SRC_BATTERY 0x02
++#define EC_SCI_SRC_BATSOC 0x04
++#define EC_SCI_SRC_BATERR 0x08
++#define EC_SCI_SRC_EBOOK 0x10
++#define EC_SCI_SRC_WLAN 0x20
++#define EC_SCI_SRC_ACPWR 0x40
++#define EC_SCI_SRC_ALL 0x7F
++
++/* GPIO assignments */
++
++#define OLPC_GPIO_MIC_AC geode_gpio(1)
++#define OLPC_GPIO_DCON_IRQ geode_gpio(7)
++#define OLPC_GPIO_THRM_ALRM geode_gpio(10)
++#define OLPC_GPIO_SMB_CLK geode_gpio(14)
++#define OLPC_GPIO_SMB_DATA geode_gpio(15)
++#define OLPC_GPIO_WORKAUX geode_gpio(24)
++#define OLPC_GPIO_LID geode_gpio(26)
++#define OLPC_GPIO_ECSCI geode_gpio(27)
++
++#endif
diff --git a/include/asm-x86/page.h b/include/asm-x86/page.h
index a05b289..b381f4a 100644
--- a/include/asm-x86/page.h
@@ -801406,10 +1069198,10 @@
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
+index c61190c..30bbde0 100644
--- a/include/asm-x86/pci.h
+++ b/include/asm-x86/pci.h
-@@ -8,14 +8,13 @@
+@@ -8,18 +8,19 @@
#include <asm/scatterlist.h>
#include <asm/io.h>
@@ -801425,7 +1069217,13 @@
#endif
};
-@@ -52,7 +51,7 @@ extern unsigned long pci_mem_start;
+ /* scan a bus after allocating a pci_sysdata for it */
++extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops,
++ int node);
+ extern struct pci_bus *pci_scan_bus_with_sysdata(int busno);
+
+ static inline int pci_domain_nr(struct pci_bus *bus)
+@@ -52,7 +53,7 @@ extern unsigned long pci_mem_start;
#define PCIBIOS_MIN_CARDBUS_IO 0x4000
void pcibios_config_init(void);
@@ -801434,7 +1069232,7 @@
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);
+@@ -62,7 +63,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,
@@ -802252,7 +1070050,7 @@
/* 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
+index 9cf472a..801b31f 100644
--- a/include/asm-x86/pgtable.h
+++ b/include/asm-x86/pgtable.h
@@ -1,16 +1,15 @@
@@ -802354,7 +1070152,7 @@
#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;
+@@ -144,30 +160,111 @@ extern struct list_head pgd_list;
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
@@ -802377,8 +1070175,19 @@
+static inline int pte_young(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_ACCESSED;
-+}
-+
+ }
+
+-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 int pte_write(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_RW;
@@ -802404,6 +1070213,11 @@
+ return !(pte_val(pte) & _PAGE_NX);
+}
+
++static inline int pte_special(pte_t pte)
++{
++ return 0;
++}
++
+static inline int pmd_large(pmd_t pte)
+{
+ return (pmd_val(pte) & (_PAGE_PSE | _PAGE_PRESENT)) ==
@@ -802423,19 +1070237,8 @@
+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);
@@ -802475,10 +1070278,15 @@
+{
+ return __pte(pte_val(pte) & ~(pteval_t)_PAGE_GLOBAL);
+}
++
++static inline pte_t pte_mkspecial(pte_t pte)
++{
++ return pte;
++}
extern pteval_t __supported_pte_mask;
-@@ -201,6 +288,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+@@ -201,6 +298,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
#define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask)
@@ -802494,7 +1070302,7 @@
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#else /* !CONFIG_PARAVIRT */
-@@ -242,6 +338,9 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+@@ -242,6 +348,9 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
# include "pgtable_64.h"
#endif
@@ -802504,7 +1070312,7 @@
#ifndef __ASSEMBLY__
enum {
-@@ -301,40 +400,21 @@ static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr,
+@@ -301,40 +410,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
@@ -802554,7 +1070362,7 @@
{
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,
+@@ -342,7 +432,9 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
}
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
@@ -802565,7 +1070373,7 @@
{
pte_t pte;
if (full) {
-@@ -358,12 +440,29 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
+@@ -358,12 +450,29 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
}
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
@@ -803251,20 +1071059,21 @@
}
i = __FDSET_LONGS;
diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h
-index 45a2f0a..117343b 100644
+index 45a2f0a..5591052 100644
--- a/include/asm-x86/processor.h
+++ b/include/asm-x86/processor.h
-@@ -3,8 +3,7 @@
+@@ -3,10 +3,6 @@
#include <asm/processor-flags.h>
-/* migration helpers, for KVM - will be removed in 2.6.25: */
-#include <asm/vm86.h>
-+/* migration helper, for KVM - will be removed in 2.6.25: */
- #define Xgt_desc_struct desc_ptr
-
+-#define Xgt_desc_struct desc_ptr
+-
/* Forward declaration, a strange C thing */
-@@ -24,6 +23,7 @@ struct mm_struct;
+ struct task_struct;
+ struct mm_struct;
+@@ -24,6 +20,7 @@ struct mm_struct;
#include <asm/msr.h>
#include <asm/desc_defs.h>
#include <asm/nops.h>
@@ -803272,7 +1071081,7 @@
#include <linux/personality.h>
#include <linux/cpumask.h>
#include <linux/cache.h>
-@@ -37,16 +37,18 @@ struct mm_struct;
+@@ -37,16 +34,18 @@ struct mm_struct;
static inline void *current_text_addr(void)
{
void *pc;
@@ -803296,7 +1071105,7 @@
#endif
/*
-@@ -56,69 +58,81 @@ static inline void *current_text_addr(void)
+@@ -56,69 +55,81 @@ static inline void *current_text_addr(void)
*/
struct cpuinfo_x86 {
@@ -803428,7 +1071237,7 @@
#ifdef CONFIG_SMP
DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
-@@ -129,7 +143,18 @@ DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
+@@ -129,7 +140,18 @@ DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
#define current_cpu_data boot_cpu_data
#endif
@@ -803448,7 +1071257,7 @@
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) {}
+@@ -146,15 +168,15 @@ static inline void detect_ht(struct cpuinfo_x86 *c) {}
#endif
static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
@@ -803471,7 +1071280,7 @@
}
static inline void load_cr3(pgd_t *pgdir)
-@@ -165,54 +190,67 @@ static inline void load_cr3(pgd_t *pgdir)
+@@ -165,54 +187,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 {
@@ -803577,7 +1071386,7 @@
/*
* The extra 1 is there because the CPU will access an
-@@ -220,135 +258,164 @@ struct tss_struct {
+@@ -220,135 +255,164 @@ struct tss_struct {
* bitmap. The extra byte must be all 1 bits, and must
* be within the limit.
*/
@@ -803820,7 +1071629,7 @@
/* 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 {
+@@ -358,21 +422,27 @@ struct thread_struct {
static inline unsigned long native_get_debugreg(int regno)
{
@@ -803855,7 +1071664,7 @@
default:
BUG();
}
-@@ -383,22 +456,22 @@ static inline void native_set_debugreg(int regno, unsigned long value)
+@@ -383,22 +453,22 @@ static inline void native_set_debugreg(int regno, unsigned long value)
{
switch (regno) {
case 0:
@@ -803884,7 +1071693,7 @@
break;
default:
BUG();
-@@ -412,23 +485,24 @@ static inline void native_set_iopl_mask(unsigned mask)
+@@ -412,23 +482,24 @@ static inline void native_set_iopl_mask(unsigned mask)
{
#ifdef CONFIG_X86_32
unsigned int reg;
@@ -803920,7 +1071729,7 @@
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)
+@@ -446,8 +517,8 @@ static inline void native_swapgs(void)
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#else
@@ -803931,7 +1071740,7 @@
/*
* 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,
+@@ -473,11 +544,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.
*/
@@ -803945,7 +1071754,7 @@
mmu_cr4_features |= mask;
cr4 = read_cr4();
cr4 |= mask;
-@@ -487,6 +562,7 @@ static inline void set_in_cr4(unsigned long mask)
+@@ -487,6 +559,7 @@ static inline void set_in_cr4(unsigned long mask)
static inline void clear_in_cr4(unsigned long mask)
{
unsigned cr4;
@@ -803953,7 +1071762,7 @@
mmu_cr4_features &= ~mask;
cr4 = read_cr4();
cr4 &= ~mask;
-@@ -494,42 +570,42 @@ static inline void clear_in_cr4(unsigned long mask)
+@@ -494,42 +567,42 @@ static inline void clear_in_cr4(unsigned long mask)
}
struct microcode_header {
@@ -804017,7 +1071826,7 @@
} mm_segment_t;
-@@ -541,7 +617,7 @@ extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+@@ -541,7 +614,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 *);
@@ -804026,7 +1071835,7 @@
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)
+@@ -578,118 +651,138 @@ static inline unsigned int cpuid_eax(unsigned int op)
unsigned int eax, ebx, ecx, edx;
cpuid(op, &eax, &ebx, &ecx, &edx);
@@ -804116,6 +1071925,7 @@
- asm volatile(
- "sti; .byte 0x0f,0x01,0xc9;"
- : :"a" (eax), "c" (ecx));
++ trace_hardirqs_on();
+ /* "mwait %eax, %ecx;" */
+ asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
+ :: "a" (eax), "c" (ecx));
@@ -804202,7 +1072012,7 @@
static inline void prefetch(const void *x)
{
alternative_input(BASE_PREFETCH,
-@@ -698,8 +793,11 @@ static inline void prefetch(const void *x)
+@@ -698,8 +791,11 @@ static inline void prefetch(const void *x)
"r" (x));
}
@@ -804216,7 +1072026,7 @@
static inline void prefetchw(const void *x)
{
alternative_input(BASE_PREFETCH,
-@@ -708,21 +806,25 @@ static inline void prefetchw(const void *x)
+@@ -708,21 +804,25 @@ static inline void prefetchw(const void *x)
"r" (x));
}
@@ -804253,7 +1072063,7 @@
}
/*
-@@ -731,28 +833,15 @@ static inline void prefetchw(const void *x)
+@@ -731,28 +831,15 @@ static inline void prefetchw(const void *x)
* permission bitmap. The extra byte must be all 1 bits, and must
* be within the limit.
*/
@@ -804290,7 +1072100,7 @@
extern unsigned long thread_saved_pc(struct task_struct *tsk);
-@@ -780,24 +869,24 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
+@@ -780,24 +867,24 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
__regs__ - 1; \
})
@@ -804323,7 +1072133,7 @@
#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);
+@@ -810,33 +897,32 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
.x86_tss.sp0 = (unsigned long)&init_stack + sizeof(init_stack) \
}
@@ -804374,7 +1072184,7 @@
#endif
diff --git a/include/asm-x86/proto.h b/include/asm-x86/proto.h
-index 68563c0..1e17bcc 100644
+index 68563c0..6c8b41b 100644
--- a/include/asm-x86/proto.h
+++ b/include/asm-x86/proto.h
@@ -7,8 +7,6 @@
@@ -804386,7 +1072196,15 @@
extern void system_call(void);
extern void syscall_init(void);
-@@ -26,7 +24,7 @@ extern int reboot_force;
+@@ -22,11 +20,15 @@ extern void syscall32_cpu_init(void);
+
+ extern void check_efer(void);
+
++#ifdef CONFIG_X86_BIOS_REBOOT
+ extern int reboot_force;
++#else
++static const int reboot_force = 0;
++#endif
long do_arch_prctl(struct task_struct *task, int code, unsigned long addr);
@@ -804489,7 +1072307,7 @@
#endif /* !__ASSEMBLY__ */
diff --git a/include/asm-x86/reboot.h b/include/asm-x86/reboot.h
-index e9e3ffc..6b5233b 100644
+index e9e3ffc..e63741f 100644
--- a/include/asm-x86/reboot.h
+++ b/include/asm-x86/reboot.h
@@ -3,8 +3,7 @@
@@ -804502,6 +1072320,14 @@
void (*restart)(char *cmd);
void (*halt)(void);
void (*power_off)(void);
+@@ -16,5 +15,7 @@ struct machine_ops
+ extern struct machine_ops machine_ops;
+
+ void machine_real_restart(unsigned char *code, int length);
++void native_machine_crash_shutdown(struct pt_regs *regs);
++void native_machine_shutdown(void);
+
+ #endif /* _ASM_REBOOT_H */
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
@@ -806800,7 +1074626,7 @@
+#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
+index 5bd5082..b633882 100644
--- a/include/asm-x86/thread_info_32.h
+++ b/include/asm-x86/thread_info_32.h
@@ -20,7 +20,8 @@
@@ -806869,7 +1074695,7 @@
movl $-THREAD_SIZE, reg; \
andl %esp, reg
-@@ -119,14 +117,16 @@ static inline struct thread_info *current_thread_info(void)
+@@ -119,19 +117,20 @@ static inline struct thread_info *current_thread_info(void)
/*
* thread information flags
@@ -806888,7 +1074714,12 @@
#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_SECCOMP 7 /* secure computing */
+-#define TIF_RESTORE_SIGMASK 8 /* restore signal mask in do_signal() */
+ #define TIF_HRTICK_RESCHED 9 /* reprogram hrtick timer */
+ #define TIF_MEMDIE 16
+ #define TIF_DEBUG 17 /* uses debug registers */
+@@ -143,36 +142,35 @@ 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 */
@@ -806918,7 +1074749,6 @@
+#define _TIF_SYSCALL_EMU (1 << TIF_SYSCALL_EMU)
+#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP (1 << TIF_SECCOMP)
-+#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
+#define _TIF_HRTICK_RESCHED (1 << TIF_HRTICK_RESCHED)
+#define _TIF_DEBUG (1 << TIF_DEBUG)
+#define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP)
@@ -806949,7 +1074779,7 @@
#define _TIF_WORK_CTXSW_PREV _TIF_WORK_CTXSW
#define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW | _TIF_DEBUG)
-@@ -184,8 +184,10 @@ static inline struct thread_info *current_thread_info(void)
+@@ -184,11 +182,24 @@ static inline struct thread_info *current_thread_info(void)
* ever touches our thread-synchronous status, so we don't
* have to worry about atomic accesses.
*/
@@ -806959,11 +1074789,25 @@
+ this quantum (SMP) */
+#define TS_POLLING 0x0002 /* True if in idle loop
+ and not sleeping */
++#define TS_RESTORE_SIGMASK 0x0004 /* restore signal mask in do_signal() */
#define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
++#ifndef __ASSEMBLY__
++#define HAVE_SET_RESTORE_SIGMASK 1
++static inline void set_restore_sigmask(void)
++{
++ struct thread_info *ti = current_thread_info();
++ ti->status |= TS_RESTORE_SIGMASK;
++ set_bit(TIF_SIGPENDING, &ti->flags);
++}
++#endif /* !__ASSEMBLY__ */
++
+ #endif /* __KERNEL__ */
+
+ #endif /* _ASM_THREAD_INFO_H */
diff --git a/include/asm-x86/thread_info_64.h b/include/asm-x86/thread_info_64.h
-index 6c9b214..ed664e8 100644
+index 6c9b214..cb69f70 100644
--- a/include/asm-x86/thread_info_64.h
+++ b/include/asm-x86/thread_info_64.h
@@ -29,9 +29,9 @@ struct thread_info {
@@ -807023,7 +1074867,11 @@
* - 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)
+@@ -110,11 +109,10 @@ static inline struct thread_info *stack_thread_info(void)
+ #define TIF_IRET 5 /* force IRET */
+ #define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */
+ #define TIF_SECCOMP 8 /* secure computing */
+-#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal */
#define TIF_MCE_NOTIFY 10 /* notify userspace of an MCE */
#define TIF_HRTICK_RESCHED 11 /* reprogram hrtick timer */
/* 16 free */
@@ -807032,7 +1074880,7 @@
#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)
+@@ -125,40 +123,42 @@ 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 */
@@ -807066,7 +1074914,6 @@
+#define _TIF_IRET (1 << TIF_IRET)
+#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP (1 << TIF_SECCOMP)
-+#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
+#define _TIF_MCE_NOTIFY (1 << TIF_MCE_NOTIFY)
+#define _TIF_HRTICK_RESCHED (1 << TIF_HRTICK_RESCHED)
+#define _TIF_IA32 (1 << TIF_IA32)
@@ -807102,7 +1074949,7 @@
#define _TIF_WORK_CTXSW_PREV _TIF_WORK_CTXSW
#define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW|_TIF_DEBUG)
-@@ -171,9 +173,11 @@ static inline struct thread_info *stack_thread_info(void)
+@@ -171,12 +171,25 @@ static inline struct thread_info *stack_thread_info(void)
* ever touches our thread-synchronous status, so we don't
* have to worry about atomic accesses.
*/
@@ -807113,9 +1074960,35 @@
-#define TS_POLLING 0x0004 /* true if in idle loop and not sleeping */
+#define TS_POLLING 0x0004 /* true if in idle loop
+ and not sleeping */
++#define TS_RESTORE_SIGMASK 0x0008 /* restore signal mask in do_signal() */
#define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
++#ifndef __ASSEMBLY__
++#define HAVE_SET_RESTORE_SIGMASK 1
++static inline void set_restore_sigmask(void)
++{
++ struct thread_info *ti = current_thread_info();
++ ti->status |= TS_RESTORE_SIGMASK;
++ set_bit(TIF_SIGPENDING, &ti->flags);
++}
++#endif /* !__ASSEMBLY__ */
++
+ #endif /* __KERNEL__ */
+
+ #endif /* _ASM_THREAD_INFO_H */
+diff --git a/include/asm-x86/time.h b/include/asm-x86/time.h
+index 68779b0..bce72d7 100644
+--- a/include/asm-x86/time.h
++++ b/include/asm-x86/time.h
+@@ -1,7 +1,6 @@
+ #ifndef _ASMX86_TIME_H
+ #define _ASMX86_TIME_H
+
+-extern void (*late_time_init)(void);
+ extern void hpet_time_init(void);
+
+ #include <asm/mc146818rtc.h>
diff --git a/include/asm-x86/tlbflush.h b/include/asm-x86/tlbflush.h
index 3998709..0c0674d 100644
--- a/include/asm-x86/tlbflush.h
@@ -807140,7 +1075013,7 @@
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
+index 8af05a9..4f35a0f 100644
--- a/include/asm-x86/topology.h
+++ b/include/asm-x86/topology.h
@@ -32,13 +32,18 @@
@@ -807253,6 +1075126,36 @@
extern cpumask_t cpu_coregroup_map(int cpu);
#ifdef ENABLE_TOPO_DEFINES
+@@ -180,9 +193,29 @@ extern cpumask_t cpu_coregroup_map(int cpu);
+ #define topology_thread_siblings(cpu) (per_cpu(cpu_sibling_map, cpu))
+ #endif
+
++static inline void arch_fix_phys_package_id(int num, u32 slot)
++{
++}
++
++struct pci_bus;
++void set_pci_bus_resources_arch_default(struct pci_bus *b);
++
+ #ifdef CONFIG_SMP
+ #define mc_capable() (boot_cpu_data.x86_max_cores > 1)
+ #define smt_capable() (smp_num_siblings > 1)
+ #endif
+
++#ifdef CONFIG_NUMA
++extern int get_mp_bus_to_node(int busnum);
++extern void set_mp_bus_to_node(int busnum, int node);
++#else
++static inline int get_mp_bus_to_node(int busnum)
++{
++ return 0;
++}
++static inline void set_mp_bus_to_node(int busnum, int node)
++{
++}
++#endif
++
+ #endif
diff --git a/include/asm-x86/trampoline.h b/include/asm-x86/trampoline.h
new file mode 100644
index 0000000..b156b08
@@ -807281,9 +1075184,18 @@
+
+#endif /* __TRAMPOLINE_HEADER */
diff --git a/include/asm-x86/tsc.h b/include/asm-x86/tsc.h
-index 7d3e27f..d2d8eb5 100644
+index 7d3e27f..548873a 100644
--- a/include/asm-x86/tsc.h
+++ b/include/asm-x86/tsc.h
+@@ -32,7 +32,7 @@ static inline cycles_t get_cycles(void)
+ return ret;
+ }
+
+-static inline cycles_t vget_cycles(void)
++static __always_inline cycles_t vget_cycles(void)
+ {
+ /*
+ * We only do VDSOs on TSC capable CPUs, so this shouldnt
@@ -42,7 +42,7 @@ static inline cycles_t vget_cycles(void)
if (!cpu_has_tsc)
return 0;
@@ -808306,15 +1076218,47 @@
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
+index 913598d..a7bd416 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.
+@@ -3,35 +3,12 @@
+
+ /*
+ * The x86 can do unaligned accesses itself.
+- *
+- * The strange macros are there to make sure these can't
+- * be misused in a way that makes them not work on other
+- * architectures where unaligned accesses aren't as simple.
*/
+
+-/**
+- * get_unaligned - get value from possibly mis-aligned location
+- * @ptr: pointer to value
+- *
+- * This macro should be used for accessing values larger in size than
+- * single bytes at locations that are expected to be improperly aligned,
+- * e.g. retrieving a u16 value from a location not u16-aligned.
+- *
+- * Note that unaligned accesses can be very expensive on some architectures.
+- */
+-#define get_unaligned(ptr) (*(ptr))
++#include <linux/unaligned/access_ok.h>
++#include <linux/unaligned/generic.h>
+
+-/**
+- * put_unaligned - put value to a possibly mis-aligned location
+- * @val: value to place
+- * @ptr: pointer to location
+- *
+- * This macro should be used for placing values larger in size than
+- * single bytes at locations that are expected to be improperly aligned,
+- * e.g. writing a u16 value to a location not u16-aligned.
+- *
+- * 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)))
++#define get_unaligned __get_unaligned_le
++#define put_unaligned __put_unaligned_le
#endif /* _ASM_X86_UNALIGNED_H */
diff --git a/include/asm-x86/unistd_32.h b/include/asm-x86/unistd_32.h
@@ -811008,6 +1078952,28 @@
/* 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/pgtable.h b/include/asm-xtensa/pgtable.h
+index c8b024a..8014d96 100644
+--- a/include/asm-xtensa/pgtable.h
++++ b/include/asm-xtensa/pgtable.h
+@@ -210,6 +210,8 @@ static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITABLE; }
+ 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_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
++static inline int pte_special(pte_t pte) { return 0; }
++
+ static inline pte_t pte_wrprotect(pte_t pte)
+ { pte_val(pte) &= ~(_PAGE_WRITABLE | _PAGE_HW_WRITE); return pte; }
+ static inline pte_t pte_mkclean(pte_t pte)
+@@ -222,6 +224,8 @@ static inline pte_t pte_mkyoung(pte_t pte)
+ { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+ static inline pte_t pte_mkwrite(pte_t pte)
+ { pte_val(pte) |= _PAGE_WRITABLE; return pte; }
++static inline pte_t pte_mkspecial(pte_t pte)
++ { return pte; }
+
+ /*
+ * Conversion functions: convert a page and protection to a page entry,
diff --git a/include/asm-xtensa/semaphore.h b/include/asm-xtensa/semaphore.h
index 3e04167..d9b2034 100644
--- a/include/asm-xtensa/semaphore.h
@@ -811113,6 +1079079,56 @@
-
-#endif /* _XTENSA_SEMAPHORE_H */
+#include <linux/semaphore.h>
+diff --git a/include/asm-xtensa/unaligned.h b/include/asm-xtensa/unaligned.h
+index 2822089..8f3424f 100644
+--- a/include/asm-xtensa/unaligned.h
++++ b/include/asm-xtensa/unaligned.h
+@@ -1,6 +1,4 @@
+ /*
+- * include/asm-xtensa/unaligned.h
+- *
+ * Xtensa doesn't handle unaligned accesses efficiently.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+@@ -9,20 +7,23 @@
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
++#ifndef _ASM_XTENSA_UNALIGNED_H
++#define _ASM_XTENSA_UNALIGNED_H
+
+-#ifndef _XTENSA_UNALIGNED_H
+-#define _XTENSA_UNALIGNED_H
+-
+-#include <linux/string.h>
+-
+-/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
+-
+-#define get_unaligned(ptr) \
+- ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
+-
+-#define put_unaligned(val, ptr) \
+- ({ __typeof__(*(ptr)) __tmp = (val); \
+- memmove((ptr), &__tmp, sizeof(*(ptr))); \
+- (void)0; })
++#ifdef __XTENSA_EL__
++# include <linux/unaligned/le_memmove.h>
++# include <linux/unaligned/be_byteshift.h>
++# include <linux/unaligned/generic.h>
++# define get_unaligned __get_unaligned_le
++# define put_unaligned __put_unaligned_le
++#elif defined(__XTENSA_EB__)
++# include <linux/unaligned/be_memmove.h>
++# include <linux/unaligned/le_byteshift.h>
++# include <linux/unaligned/generic.h>
++# define get_unaligned __get_unaligned_be
++# define put_unaligned __put_unaligned_be
++#else
++# error processor byte order undefined!
++#endif
+
+-#endif /* _XTENSA_UNALIGNED_H */
++#endif /* _ASM_XTENSA_UNALIGNED_H */
diff --git a/include/crypto/aes.h b/include/crypto/aes.h
index d480b76..40008d6 100644
--- a/include/crypto/aes.h
@@ -811151,10 +1079167,47 @@
-#endif /* _KEYS_USER_TYPE_H */
+#endif /* _KEYS_RXRPC_TYPE_H */
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
-index cedbbd8..bda6f04 100644
+index cedbbd8..78fade0 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
-@@ -100,7 +100,7 @@ header-y += ixjuser.h
+@@ -20,6 +20,7 @@ header-y += affs_hardblocks.h
+ header-y += aio_abi.h
+ header-y += arcfb.h
+ header-y += atmapi.h
++header-y += atmarp.h
+ header-y += atmbr2684.h
+ header-y += atmclip.h
+ header-y += atm_eni.h
+@@ -48,6 +49,7 @@ header-y += coff.h
+ header-y += comstats.h
+ header-y += const.h
+ header-y += cgroupstats.h
++header-y += cramfs_fs.h
+ header-y += cycx_cfm.h
+ header-y += dlmconstants.h
+ header-y += dlm_device.h
+@@ -70,10 +72,12 @@ header-y += firewire-constants.h
+ header-y += fuse.h
+ header-y += genetlink.h
+ header-y += gen_stats.h
++header-y += gfs2_ondisk.h
+ header-y += gigaset_dev.h
+ header-y += hysdn_if.h
+ header-y += i2o-dev.h
+ header-y += i8k.h
++header-y += if_addrlabel.h
+ header-y += if_arcnet.h
+ header-y += if_bonding.h
+ header-y += if_cablemodem.h
+@@ -91,6 +95,7 @@ header-y += if_tunnel.h
+ header-y += in6.h
+ header-y += in_route.h
+ header-y += ioctl.h
++header-y += ip6_tunnel.h
+ header-y += ipmi_msgdefs.h
+ header-y += ipsec.h
+ header-y += ipx.h
+@@ -100,7 +105,7 @@ header-y += ixjuser.h
header-y += jffs2.h
header-y += keyctl.h
header-y += limits.h
@@ -811163,7 +1079216,15 @@
header-y += magic.h
header-y += major.h
header-y += matroxfb.h
-@@ -150,6 +150,7 @@ header-y += tiocl.h
+@@ -117,7 +122,6 @@ header-y += nfs2.h
+ header-y += nfs4_mount.h
+ header-y += nfs_mount.h
+ header-y += nl80211.h
+-header-y += oom.h
+ header-y += param.h
+ header-y += pci_regs.h
+ header-y += pfkeyv2.h
+@@ -150,6 +154,7 @@ header-y += tiocl.h
header-y += tipc.h
header-y += tipc_config.h
header-y += toshiba.h
@@ -811171,7 +1079232,28 @@
header-y += ultrasound.h
header-y += un.h
header-y += utime.h
-@@ -209,8 +210,9 @@ unifdef-y += hayesesp.h
+@@ -165,7 +170,6 @@ unifdef-y += adfs_fs.h
+ unifdef-y += agpgart.h
+ unifdef-y += apm_bios.h
+ unifdef-y += atalk.h
+-unifdef-y += atmarp.h
+ unifdef-y += atmdev.h
+ unifdef-y += atm.h
+ unifdef-y += atm_tcp.h
+@@ -181,7 +185,6 @@ unifdef-y += cm4000_cs.h
+ unifdef-y += cn_proc.h
+ unifdef-y += coda.h
+ unifdef-y += connector.h
+-unifdef-y += cramfs_fs.h
+ unifdef-y += cuda.h
+ unifdef-y += cyclades.h
+ unifdef-y += dccp.h
+@@ -204,20 +207,19 @@ unifdef-y += futex.h
+ unifdef-y += fs.h
+ unifdef-y += gameport.h
+ unifdef-y += generic_serial.h
+-unifdef-y += gfs2_ondisk.h
+ unifdef-y += hayesesp.h
unifdef-y += hdlcdrv.h
unifdef-y += hdlc.h
unifdef-y += hdreg.h
@@ -811182,6 +1079264,13 @@
unifdef-y += hpet.h
unifdef-y += i2c.h
unifdef-y += i2c-dev.h
+ unifdef-y += icmp.h
+ unifdef-y += icmpv6.h
+ unifdef-y += if_addr.h
+-unifdef-y += if_addrlabel.h
+ unifdef-y += if_arp.h
+ unifdef-y += if_bridge.h
+ unifdef-y += if_ec.h
@@ -231,7 +233,6 @@ unifdef-y += if_pppol2tp.h
unifdef-y += if_pppox.h
unifdef-y += if_tr.h
@@ -811190,7 +1079279,15 @@
unifdef-y += igmp.h
unifdef-y += inet_diag.h
unifdef-y += in.h
-@@ -261,6 +262,7 @@ unifdef-y += mempolicy.h
+@@ -242,7 +243,6 @@ unifdef-y += ipc.h
+ unifdef-y += ipmi.h
+ unifdef-y += ipv6.h
+ unifdef-y += ipv6_route.h
+-unifdef-y += ip6_tunnel.h
+ unifdef-y += isdn.h
+ unifdef-y += isdnif.h
+ unifdef-y += isdn_divertif.h
+@@ -261,6 +261,7 @@ unifdef-y += mempolicy.h
unifdef-y += mii.h
unifdef-y += mman.h
unifdef-y += mroute.h
@@ -811198,7 +1079295,7 @@
unifdef-y += msdos_fs.h
unifdef-y += msg.h
unifdef-y += nbd.h
-@@ -289,6 +291,7 @@ unifdef-y += parport.h
+@@ -289,6 +290,7 @@ unifdef-y += parport.h
unifdef-y += patchkey.h
unifdef-y += pci.h
unifdef-y += personality.h
@@ -811206,7 +1079303,7 @@
unifdef-y += pktcdvd.h
unifdef-y += pmu.h
unifdef-y += poll.h
-@@ -333,7 +336,6 @@ unifdef-y += time.h
+@@ -333,7 +335,6 @@ unifdef-y += time.h
unifdef-y += timex.h
unifdef-y += tty.h
unifdef-y += types.h
@@ -811214,6 +1079311,29 @@
unifdef-y += udp.h
unifdef-y += uinput.h
unifdef-y += uio.h
+diff --git a/include/linux/acpi.h b/include/linux/acpi.h
+index 2c7e003..41f7ce7 100644
+--- a/include/linux/acpi.h
++++ b/include/linux/acpi.h
+@@ -79,6 +79,7 @@ typedef int (*acpi_table_handler) (struct acpi_table_header *table);
+ typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
+
+ char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
++int early_acpi_boot_init(void);
+ int acpi_boot_init (void);
+ int acpi_boot_table_init (void);
+ int acpi_numa_init (void);
+@@ -235,6 +236,10 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n,
+
+ #else /* CONFIG_ACPI */
+
++static inline int early_acpi_boot_init(void)
++{
++ return 0;
++}
+ static inline int acpi_boot_init(void)
+ {
+ return 0;
diff --git a/include/linux/aer.h b/include/linux/aer.h
index bcf236d..f251814 100644
--- a/include/linux/aer.h
@@ -811237,6 +1079357,57 @@
#endif
#endif //_AER_H_
+diff --git a/include/linux/agp_backend.h b/include/linux/agp_backend.h
+index 03e3454..661d90d 100644
+--- a/include/linux/agp_backend.h
++++ b/include/linux/agp_backend.h
+@@ -30,8 +30,6 @@
+ #ifndef _AGP_BACKEND_H
+ #define _AGP_BACKEND_H 1
+
+-#ifdef __KERNEL__
+-
+ #ifndef TRUE
+ #define TRUE 1
+ #endif
+@@ -111,5 +109,4 @@ extern struct agp_bridge_data *agp_backend_acquire(struct pci_dev *);
+ extern void agp_backend_release(struct agp_bridge_data *);
+ extern void agp_flush_chipset(struct agp_bridge_data *);
+
+-#endif /* __KERNEL__ */
+ #endif /* _AGP_BACKEND_H */
+diff --git a/include/linux/aio.h b/include/linux/aio.h
+index 0d0b7f6..b51ddd2 100644
+--- a/include/linux/aio.h
++++ b/include/linux/aio.h
+@@ -209,27 +209,8 @@ extern ssize_t wait_on_sync_kiocb(struct kiocb *iocb);
+ extern int aio_put_req(struct kiocb *iocb);
+ extern void kick_iocb(struct kiocb *iocb);
+ extern int aio_complete(struct kiocb *iocb, long res, long res2);
+-extern void __put_ioctx(struct kioctx *ctx);
+ struct mm_struct;
+ extern void exit_aio(struct mm_struct *mm);
+-extern struct kioctx *lookup_ioctx(unsigned long ctx_id);
+-extern int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
+- struct iocb *iocb);
+-
+-/* semi private, but used by the 32bit emulations: */
+-struct kioctx *lookup_ioctx(unsigned long ctx_id);
+-int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
+- struct iocb *iocb);
+-
+-#define get_ioctx(kioctx) do { \
+- BUG_ON(atomic_read(&(kioctx)->users) <= 0); \
+- atomic_inc(&(kioctx)->users); \
+-} while (0)
+-#define put_ioctx(kioctx) do { \
+- BUG_ON(atomic_read(&(kioctx)->users) <= 0); \
+- if (unlikely(atomic_dec_and_test(&(kioctx)->users))) \
+- __put_ioctx(kioctx); \
+-} while (0)
+
+ #define io_wait_to_kiocb(wait) container_of(wait, struct kiocb, ki_wait)
+
diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h
index fde6758..a191607 100644
--- a/include/linux/arcdevice.h
@@ -811608,10 +1079779,27 @@
#endif
diff --git a/include/linux/audit.h b/include/linux/audit.h
-index 2af9ec0..4ccb048 100644
+index 2af9ec0..63c3bb9 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
-@@ -353,6 +353,33 @@ struct netlink_skb_parms;
+@@ -146,7 +146,7 @@
+ /* Rule structure sizes -- if these change, different AUDIT_ADD and
+ * AUDIT_LIST commands must be implemented. */
+ #define AUDIT_MAX_FIELDS 64
+-#define AUDIT_MAX_KEY_LEN 32
++#define AUDIT_MAX_KEY_LEN 256
+ #define AUDIT_BITMASK_SIZE 64
+ #define AUDIT_WORD(nr) ((__u32)((nr)/32))
+ #define AUDIT_BIT(nr) (1 << ((nr) - AUDIT_WORD(nr)*32))
+@@ -209,6 +209,7 @@
+ #define AUDIT_WATCH 105
+ #define AUDIT_PERM 106
+ #define AUDIT_DIR 107
++#define AUDIT_FILETYPE 108
+
+ #define AUDIT_ARG0 200
+ #define AUDIT_ARG1 (AUDIT_ARG0+1)
+@@ -353,6 +354,33 @@ struct netlink_skb_parms;
struct linux_binprm;
struct mq_attr;
struct mqstat;
@@ -811645,7 +1079833,31 @@
#define AUDITSC_INVALID 0
#define AUDITSC_SUCCESS 1
-@@ -536,6 +563,8 @@ extern void audit_log_d_path(struct audit_buffer *ab,
+@@ -522,25 +550,32 @@ extern void audit_log_format(struct audit_buffer *ab,
+ const char *fmt, ...)
+ __attribute__((format(printf,2,3)));
+ extern void audit_log_end(struct audit_buffer *ab);
+-extern void audit_log_hex(struct audit_buffer *ab,
+- const unsigned char *buf,
+- size_t len);
+ extern int audit_string_contains_control(const char *string,
+ size_t len);
++extern void audit_log_n_hex(struct audit_buffer *ab,
++ const unsigned char *buf,
++ size_t len);
++extern void audit_log_n_string(struct audit_buffer *ab,
++ const char *buf,
++ size_t n);
++#define audit_log_string(a,b) audit_log_n_string(a, b, strlen(b));
++extern void audit_log_n_untrustedstring(struct audit_buffer *ab,
++ const char *string,
++ size_t n);
+ extern void audit_log_untrustedstring(struct audit_buffer *ab,
+ const char *string);
+-extern void audit_log_n_untrustedstring(struct audit_buffer *ab,
+- size_t n,
+- const char *string);
+ extern void audit_log_d_path(struct audit_buffer *ab,
const char *prefix,
struct path *path);
extern void audit_log_lost(const char *message);
@@ -811654,11 +1079866,225 @@
/* 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);
+ extern int audit_receive_filter(int type, int pid, int uid, int seq,
+- void *data, size_t datasz, uid_t loginuid, u32 sid);
++ void *data, size_t datasz, uid_t loginuid,
++ u32 sessionid, u32 sid);
+ extern int audit_enabled;
+ #else
+ #define audit_log(c,g,t,f,...) do { ; } while (0)
+@@ -548,9 +583,11 @@ extern int audit_enabled;
+ #define audit_log_vformat(b,f,a) do { ; } while (0)
+ #define audit_log_format(b,f,...) do { ; } while (0)
+ #define audit_log_end(b) do { ; } while (0)
+-#define audit_log_hex(a,b,l) do { ; } while (0)
+-#define audit_log_untrustedstring(a,s) do { ; } while (0)
++#define audit_log_n_hex(a,b,l) do { ; } while (0)
++#define audit_log_n_string(a,c,l) do { ; } while (0)
++#define audit_log_string(a,c) do { ; } while (0)
+ #define audit_log_n_untrustedstring(a,n,s) do { ; } while (0)
++#define audit_log_untrustedstring(a,s) do { ; } while (0)
+ #define audit_log_d_path(b, p, d) do { ; } while (0)
+ #define audit_enabled 0
+ #endif
+diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
+index 48a62ba..0a24d55 100644
+--- a/include/linux/backing-dev.h
++++ b/include/linux/backing-dev.h
+@@ -11,9 +11,13 @@
+ #include <linux/percpu_counter.h>
+ #include <linux/log2.h>
+ #include <linux/proportions.h>
++#include <linux/kernel.h>
++#include <linux/fs.h>
+ #include <asm/atomic.h>
+
+ struct page;
++struct device;
++struct dentry;
+
+ /*
+ * Bits in backing_dev_info.state
+@@ -48,11 +52,26 @@ struct backing_dev_info {
+
+ struct prop_local_percpu completions;
+ int dirty_exceeded;
++
++ unsigned int min_ratio;
++ unsigned int max_ratio, max_prop_frac;
++
++ struct device *dev;
++
++#ifdef CONFIG_DEBUG_FS
++ struct dentry *debug_dir;
++ struct dentry *debug_stats;
++#endif
+ };
+
+ int bdi_init(struct backing_dev_info *bdi);
+ void bdi_destroy(struct backing_dev_info *bdi);
+
++int bdi_register(struct backing_dev_info *bdi, struct device *parent,
++ const char *fmt, ...);
++int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
++void bdi_unregister(struct backing_dev_info *bdi);
++
+ static inline void __add_bdi_stat(struct backing_dev_info *bdi,
+ enum bdi_stat_item item, s64 amount)
+ {
+@@ -116,6 +135,8 @@ static inline s64 bdi_stat_sum(struct backing_dev_info *bdi,
+ return sum;
+ }
+
++extern void bdi_writeout_inc(struct backing_dev_info *bdi);
++
+ /*
+ * maximal error of a stat counter.
+ */
+@@ -128,24 +149,48 @@ static inline unsigned long bdi_stat_error(struct backing_dev_info *bdi)
+ #endif
+ }
+
++int bdi_set_min_ratio(struct backing_dev_info *bdi, unsigned int min_ratio);
++int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio);
++
+ /*
+ * Flags in backing_dev_info::capability
+- * - The first two flags control whether dirty pages will contribute to the
+- * VM's accounting and whether writepages() should be called for dirty pages
+- * (something that would not, for example, be appropriate for ramfs)
+- * - These flags let !MMU mmap() govern direct device mapping vs immediate
+- * copying more easily for MAP_PRIVATE, especially for ROM filesystems
++ *
++ * The first three flags control whether dirty pages will contribute to the
++ * VM's accounting and whether writepages() should be called for dirty pages
++ * (something that would not, for example, be appropriate for ramfs)
++ *
++ * WARNING: these flags are closely related and should not normally be
++ * used separately. The BDI_CAP_NO_ACCT_AND_WRITEBACK combines these
++ * three flags into a single convenience macro.
++ *
++ * BDI_CAP_NO_ACCT_DIRTY: Dirty pages shouldn't contribute to accounting
++ * BDI_CAP_NO_WRITEBACK: Don't write pages back
++ * BDI_CAP_NO_ACCT_WB: Don't automatically account writeback pages
++ *
++ * These flags let !MMU mmap() govern direct device mapping vs immediate
++ * copying more easily for MAP_PRIVATE, especially for ROM filesystems.
++ *
++ * BDI_CAP_MAP_COPY: Copy can be mapped (MAP_PRIVATE)
++ * BDI_CAP_MAP_DIRECT: Can be mapped directly (MAP_SHARED)
++ * BDI_CAP_READ_MAP: Can be mapped for reading
++ * BDI_CAP_WRITE_MAP: Can be mapped for writing
++ * BDI_CAP_EXEC_MAP: Can be mapped for execution
+ */
+-#define BDI_CAP_NO_ACCT_DIRTY 0x00000001 /* Dirty pages shouldn't contribute to accounting */
+-#define BDI_CAP_NO_WRITEBACK 0x00000002 /* Don't write pages back */
+-#define BDI_CAP_MAP_COPY 0x00000004 /* Copy can be mapped (MAP_PRIVATE) */
+-#define BDI_CAP_MAP_DIRECT 0x00000008 /* Can be mapped directly (MAP_SHARED) */
+-#define BDI_CAP_READ_MAP 0x00000010 /* Can be mapped for reading */
+-#define BDI_CAP_WRITE_MAP 0x00000020 /* Can be mapped for writing */
+-#define BDI_CAP_EXEC_MAP 0x00000040 /* Can be mapped for execution */
++#define BDI_CAP_NO_ACCT_DIRTY 0x00000001
++#define BDI_CAP_NO_WRITEBACK 0x00000002
++#define BDI_CAP_MAP_COPY 0x00000004
++#define BDI_CAP_MAP_DIRECT 0x00000008
++#define BDI_CAP_READ_MAP 0x00000010
++#define BDI_CAP_WRITE_MAP 0x00000020
++#define BDI_CAP_EXEC_MAP 0x00000040
++#define BDI_CAP_NO_ACCT_WB 0x00000080
++
+ #define BDI_CAP_VMFLAGS \
+ (BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP)
+
++#define BDI_CAP_NO_ACCT_AND_WRITEBACK \
++ (BDI_CAP_NO_WRITEBACK | BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_ACCT_WB)
++
+ #if defined(VM_MAYREAD) && \
+ (BDI_CAP_READ_MAP != VM_MAYREAD || \
+ BDI_CAP_WRITE_MAP != VM_MAYWRITE || \
+@@ -156,9 +201,7 @@ static inline unsigned long bdi_stat_error(struct backing_dev_info *bdi)
+ extern struct backing_dev_info default_backing_dev_info;
+ void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page);
+
+-int writeback_acquire(struct backing_dev_info *bdi);
+ int writeback_in_progress(struct backing_dev_info *bdi);
+-void writeback_release(struct backing_dev_info *bdi);
+
+ static inline int bdi_congested(struct backing_dev_info *bdi, int bdi_bits)
+ {
+@@ -187,17 +230,32 @@ void clear_bdi_congested(struct backing_dev_info *bdi, int rw);
+ void set_bdi_congested(struct backing_dev_info *bdi, int rw);
+ long congestion_wait(int rw, long timeout);
+
+-#define bdi_cap_writeback_dirty(bdi) \
+- (!((bdi)->capabilities & BDI_CAP_NO_WRITEBACK))
+
+-#define bdi_cap_account_dirty(bdi) \
+- (!((bdi)->capabilities & BDI_CAP_NO_ACCT_DIRTY))
++static inline bool bdi_cap_writeback_dirty(struct backing_dev_info *bdi)
++{
++ return !(bdi->capabilities & BDI_CAP_NO_WRITEBACK);
++}
++
++static inline bool bdi_cap_account_dirty(struct backing_dev_info *bdi)
++{
++ return !(bdi->capabilities & BDI_CAP_NO_ACCT_DIRTY);
++}
+
+-#define mapping_cap_writeback_dirty(mapping) \
+- bdi_cap_writeback_dirty((mapping)->backing_dev_info)
++static inline bool bdi_cap_account_writeback(struct backing_dev_info *bdi)
++{
++ /* Paranoia: BDI_CAP_NO_WRITEBACK implies BDI_CAP_NO_ACCT_WB */
++ return !(bdi->capabilities & (BDI_CAP_NO_ACCT_WB |
++ BDI_CAP_NO_WRITEBACK));
++}
+
+-#define mapping_cap_account_dirty(mapping) \
+- bdi_cap_account_dirty((mapping)->backing_dev_info)
++static inline bool mapping_cap_writeback_dirty(struct address_space *mapping)
++{
++ return bdi_cap_writeback_dirty(mapping->backing_dev_info);
++}
+
++static inline bool mapping_cap_account_dirty(struct address_space *mapping)
++{
++ return bdi_cap_account_dirty(mapping->backing_dev_info);
++}
+
+ #endif /* _LINUX_BACKING_DEV_H */
+diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
+index b7fc55e..b512e48 100644
+--- a/include/linux/binfmts.h
++++ b/include/linux/binfmts.h
+@@ -34,7 +34,8 @@ struct linux_binprm{
+ #endif
+ struct mm_struct *mm;
+ unsigned long p; /* current top of mem */
+- int sh_bang;
++ unsigned int sh_bang:1,
++ misc_bang:1;
+ struct file * file;
+ int e_uid, e_gid;
+ kernel_cap_t cap_inheritable, cap_permitted;
+@@ -48,7 +49,6 @@ struct linux_binprm{
+ unsigned interp_flags;
+ unsigned interp_data;
+ unsigned long loader, exec;
+- unsigned long argv_len;
+ };
+
+ #define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0
diff --git a/include/linux/bio.h b/include/linux/bio.h
-index 4c59bdc..d259690 100644
+index 4c59bdc..61c15ea 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,
+@@ -324,9 +324,13 @@ extern struct bio *bio_map_user_iov(struct request_queue *,
+ extern void bio_unmap_user(struct bio *);
+ extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int,
+ gfp_t);
++extern struct bio *bio_copy_kern(struct request_queue *, void *, unsigned int,
++ gfp_t, 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);
@@ -811668,10 +1080094,19 @@
void zero_fill_bio(struct bio *bio);
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
-index acad110..1dbe074 100644
+index acad110..43b406d 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);
+@@ -46,6 +46,8 @@
+ * bitmap_shift_left(dst, src, n, nbits) *dst = *src << n
+ * bitmap_remap(dst, src, old, new, nbits) *dst = map(old, new)(src)
+ * bitmap_bitremap(oldbit, old, new, nbits) newbit = map(old, new)(oldbit)
++ * bitmap_onto(dst, orig, relmap, nbits) *dst = orig relative to relmap
++ * bitmap_fold(dst, orig, sz, nbits) dst bits = orig bits mod sz
+ * bitmap_scnprintf(buf, len, src, nbits) Print bitmap src to buf
+ * bitmap_parse(buf, buflen, dst, nbits) Parse bitmap dst from kernel buf
+ * bitmap_parse_user(ubuf, ulen, dst, nbits) Parse bitmap dst from user buf
+@@ -108,6 +110,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);
@@ -811679,8 +1080114,87 @@
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,
+@@ -120,6 +123,10 @@ extern void bitmap_remap(unsigned long *dst, const unsigned long *src,
+ const unsigned long *old, const unsigned long *new, int bits);
+ extern int bitmap_bitremap(int oldbit,
+ const unsigned long *old, const unsigned long *new, int bits);
++extern void bitmap_onto(unsigned long *dst, const unsigned long *orig,
++ const unsigned long *relmap, int bits);
++extern void bitmap_fold(unsigned long *dst, const unsigned long *orig,
++ int sz, int bits);
+ extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order);
+ extern void bitmap_release_region(unsigned long *bitmap, int pos, int order);
+ extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order);
+diff --git a/include/linux/bitops.h b/include/linux/bitops.h
+index 40d5473..024f2b0 100644
+--- a/include/linux/bitops.h
++++ b/include/linux/bitops.h
+@@ -6,8 +6,8 @@
+ #define BIT(nr) (1UL << (nr))
+ #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
+ #define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
+-#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG)
+ #define BITS_PER_BYTE 8
++#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
+ #endif
+
+ /*
+@@ -112,4 +112,53 @@ static inline unsigned fls_long(unsigned long l)
+ return fls64(l);
+ }
+
++#ifdef __KERNEL__
++#ifdef CONFIG_GENERIC_FIND_FIRST_BIT
++
++/**
++ * 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.
++ */
++extern unsigned long find_first_bit(const unsigned long *addr,
++ unsigned long size);
++
++/**
++ * find_first_zero_bit - find the first cleared 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 cleared bit.
++ */
++extern unsigned long find_first_zero_bit(const unsigned long *addr,
++ unsigned long size);
++
++#endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
++
++#ifdef CONFIG_GENERIC_FIND_NEXT_BIT
++
++/**
++ * find_next_bit - find the next set bit in a memory region
++ * @addr: The address to base the search on
++ * @offset: The bitnumber to start searching at
++ * @size: The bitmap size in bits
++ */
++extern unsigned long find_next_bit(const unsigned long *addr,
++ unsigned long size, unsigned long offset);
++
++/**
++ * find_next_zero_bit - find the next cleared bit in a memory region
++ * @addr: The address to base the search on
++ * @offset: The bitnumber to start searching at
++ * @size: The bitmap size in bits
++ */
++
++extern unsigned long find_next_zero_bit(const unsigned long *addr,
++ unsigned long size,
++ unsigned long offset);
++
++#endif /* CONFIG_GENERIC_FIND_NEXT_BIT */
++#endif /* __KERNEL__ */
+ #endif
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
-index 6f79d40..c5065e3 100644
+index 6f79d40..d2a1b71 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -112,6 +112,7 @@ enum rq_flag_bits {
@@ -811699,7 +1080213,91 @@
#define BLK_MAX_CDB 16
-@@ -533,8 +535,13 @@ extern unsigned long blk_max_low_pfn, blk_max_pfn;
+@@ -213,8 +215,9 @@ struct request {
+ /*
+ * when request is used as a packet command carrier
+ */
+- unsigned int cmd_len;
+- unsigned char cmd[BLK_MAX_CDB];
++ unsigned short cmd_len;
++ unsigned char __cmd[BLK_MAX_CDB];
++ unsigned char *cmd;
+
+ unsigned int data_len;
+ unsigned int extra_len; /* length of alignment and padding */
+@@ -405,6 +408,41 @@ struct request_queue
+ #define QUEUE_FLAG_PLUGGED 7 /* queue is plugged */
+ #define QUEUE_FLAG_ELVSWITCH 8 /* don't use elevator, just do FIFO */
+ #define QUEUE_FLAG_BIDI 9 /* queue supports bidi requests */
++#define QUEUE_FLAG_NOMERGES 10 /* disable merge attempts */
++
++static inline int queue_is_locked(struct request_queue *q)
++{
++#ifdef CONFIG_SMP
++ spinlock_t *lock = q->queue_lock;
++ return lock && spin_is_locked(lock);
++#else
++ return 1;
++#endif
++}
++
++static inline void queue_flag_set_unlocked(unsigned int flag,
++ struct request_queue *q)
++{
++ __set_bit(flag, &q->queue_flags);
++}
++
++static inline void queue_flag_set(unsigned int flag, struct request_queue *q)
++{
++ WARN_ON_ONCE(!queue_is_locked(q));
++ __set_bit(flag, &q->queue_flags);
++}
++
++static inline void queue_flag_clear_unlocked(unsigned int flag,
++ struct request_queue *q)
++{
++ __clear_bit(flag, &q->queue_flags);
++}
++
++static inline void queue_flag_clear(unsigned int flag, struct request_queue *q)
++{
++ WARN_ON_ONCE(!queue_is_locked(q));
++ __clear_bit(flag, &q->queue_flags);
++}
+
+ enum {
+ /*
+@@ -449,6 +487,7 @@ enum {
+ #define blk_queue_plugged(q) test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags)
+ #define blk_queue_tagged(q) test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags)
+ #define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags)
++#define blk_queue_nomerges(q) test_bit(QUEUE_FLAG_NOMERGES, &(q)->queue_flags)
+ #define blk_queue_flushing(q) ((q)->ordseq)
+
+ #define blk_fs_request(rq) ((rq)->cmd_type == REQ_TYPE_FS)
+@@ -494,17 +533,17 @@ static inline int blk_queue_full(struct request_queue *q, int rw)
+ static inline void blk_set_queue_full(struct request_queue *q, int rw)
+ {
+ if (rw == READ)
+- set_bit(QUEUE_FLAG_READFULL, &q->queue_flags);
++ queue_flag_set(QUEUE_FLAG_READFULL, q);
+ else
+- set_bit(QUEUE_FLAG_WRITEFULL, &q->queue_flags);
++ queue_flag_set(QUEUE_FLAG_WRITEFULL, q);
+ }
+
+ static inline void blk_clear_queue_full(struct request_queue *q, int rw)
+ {
+ if (rw == READ)
+- clear_bit(QUEUE_FLAG_READFULL, &q->queue_flags);
++ queue_flag_clear(QUEUE_FLAG_READFULL, q);
+ else
+- clear_bit(QUEUE_FLAG_WRITEFULL, &q->queue_flags);
++ queue_flag_clear(QUEUE_FLAG_WRITEFULL, q);
+ }
+
+
+@@ -533,8 +572,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
*/
@@ -811714,19 +1080312,214 @@
#define BLK_BOUNCE_ISA (ISA_DMA_THRESHOLD)
/*
+@@ -576,6 +620,7 @@ extern int blk_register_queue(struct gendisk *disk);
+ extern void blk_unregister_queue(struct gendisk *disk);
+ extern void register_disk(struct gendisk *dev);
+ extern void generic_make_request(struct bio *bio);
++extern void blk_rq_init(struct request_queue *q, struct request *rq);
+ extern void blk_put_request(struct request *);
+ extern void __blk_put_request(struct request_queue *, struct request *);
+ extern void blk_end_sync_rq(struct request *rq, int error);
+@@ -619,6 +664,7 @@ extern void blk_start_queue(struct request_queue *q);
+ extern void blk_stop_queue(struct request_queue *q);
+ extern void blk_sync_queue(struct request_queue *q);
+ extern void __blk_stop_queue(struct request_queue *q);
++extern void __blk_run_queue(struct request_queue *);
+ extern void blk_run_queue(struct request_queue *);
+ extern void blk_start_queueing(struct request_queue *);
+ extern int blk_rq_map_user(struct request_queue *, struct request *, void __user *, unsigned long);
+diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
+index 4e4e340..6a5dbdc 100644
+--- a/include/linux/bootmem.h
++++ b/include/linux/bootmem.h
+@@ -101,6 +101,8 @@ extern void reserve_bootmem_node(pg_data_t *pgdat,
+ extern void free_bootmem_node(pg_data_t *pgdat,
+ unsigned long addr,
+ unsigned long size);
++extern void *alloc_bootmem_section(unsigned long size,
++ unsigned long section_nr);
+
+ #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
+ #define alloc_bootmem_node(pgdat, x) \
diff --git a/include/linux/bsg.h b/include/linux/bsg.h
-index 60e377b..e8406c5 100644
+index 60e377b..cf0303a 100644
--- a/include/linux/bsg.h
+++ b/include/linux/bsg.h
-@@ -55,7 +55,7 @@ struct sg_io_v4 {
+@@ -55,20 +55,26 @@ struct sg_io_v4 {
#if defined(CONFIG_BLK_DEV_BSG)
struct bsg_class_device {
- struct class_device *class_dev;
+- struct device *dev;
+ struct device *class_dev;
- struct device *dev;
++ struct device *parent;
int minor;
struct request_queue *queue;
++ struct kref ref;
++ void (*release)(struct device *);
+ };
+
+-extern int bsg_register_queue(struct request_queue *, struct device *, const char *);
++extern int bsg_register_queue(struct request_queue *q,
++ struct device *parent, const char *name,
++ void (*release)(struct device *));
+ extern void bsg_unregister_queue(struct request_queue *);
+ #else
+-static inline int bsg_register_queue(struct request_queue * rq, struct device *dev, const char *name)
++static inline int bsg_register_queue(struct request_queue *q,
++ struct device *parent, const char *name,
++ void (*release)(struct device *))
+ {
+ return 0;
+ }
+-static inline void bsg_unregister_queue(struct request_queue *rq)
++static inline void bsg_unregister_queue(struct request_queue *q)
+ {
+ }
+ #endif
+diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
+index 932eb02..82aa36c 100644
+--- a/include/linux/buffer_head.h
++++ b/include/linux/buffer_head.h
+@@ -225,7 +225,6 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct page *page,
+ get_block_t get_block);
+ void block_sync_page(struct page *);
+ sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *);
+-int generic_commit_write(struct file *, struct page *, unsigned, unsigned);
+ int block_truncate_page(struct address_space *, loff_t, get_block_t *);
+ int file_fsync(struct file *, struct dentry *, int);
+ int nobh_write_begin(struct file *, struct address_space *,
+diff --git a/include/linux/byteorder/Kbuild b/include/linux/byteorder/Kbuild
+index 79beddd..1133d5f 100644
+--- a/include/linux/byteorder/Kbuild
++++ b/include/linux/byteorder/Kbuild
+@@ -1,5 +1,3 @@
+-header-y += big_endian.h
+-header-y += little_endian.h
+-
+-unifdef-y += generic.h
++unifdef-y += big_endian.h
++unifdef-y += little_endian.h
+ unifdef-y += swab.h
+diff --git a/include/linux/byteorder/big_endian.h b/include/linux/byteorder/big_endian.h
+index bef8789..961ed4b 100644
+--- a/include/linux/byteorder/big_endian.h
++++ b/include/linux/byteorder/big_endian.h
+@@ -101,6 +101,8 @@ static inline __u16 __be16_to_cpup(const __be16 *p)
+ #define __cpu_to_be16s(x) do {} while (0)
+ #define __be16_to_cpus(x) do {} while (0)
+
++#ifdef __KERNEL__
+ #include <linux/byteorder/generic.h>
++#endif
+
+ #endif /* _LINUX_BYTEORDER_BIG_ENDIAN_H */
+diff --git a/include/linux/byteorder/generic.h b/include/linux/byteorder/generic.h
+index d377155..0846e6b 100644
+--- a/include/linux/byteorder/generic.h
++++ b/include/linux/byteorder/generic.h
+@@ -82,12 +82,6 @@
+ *
+ */
+
+-
+-#if defined(__KERNEL__)
+-/*
+- * inside the kernel, we can use nicknames;
+- * outside of it, we must avoid POSIX namespace pollution...
+- */
+ #define cpu_to_le64 __cpu_to_le64
+ #define le64_to_cpu __le64_to_cpu
+ #define cpu_to_le32 __cpu_to_le32
+@@ -176,6 +170,4 @@ static inline void be64_add_cpu(__be64 *var, u64 val)
+ *var = cpu_to_be64(be64_to_cpu(*var) + val);
+ }
+
+-#endif /* KERNEL */
+-
+ #endif /* _LINUX_BYTEORDER_GENERIC_H */
+diff --git a/include/linux/byteorder/little_endian.h b/include/linux/byteorder/little_endian.h
+index 86e62b7..05dc7c3 100644
+--- a/include/linux/byteorder/little_endian.h
++++ b/include/linux/byteorder/little_endian.h
+@@ -101,6 +101,8 @@ static inline __u16 __be16_to_cpup(const __be16 *p)
+ #define __cpu_to_be16s(x) __swab16s((x))
+ #define __be16_to_cpus(x) __swab16s((x))
+
++#ifdef __KERNEL__
+ #include <linux/byteorder/generic.h>
++#endif
+
+ #endif /* _LINUX_BYTEORDER_LITTLE_ENDIAN_H */
+diff --git a/include/linux/cache.h b/include/linux/cache.h
+index 4552504..97e2488 100644
+--- a/include/linux/cache.h
++++ b/include/linux/cache.h
+@@ -60,4 +60,8 @@
+ #endif
+ #endif
+
++#ifndef CONFIG_ARCH_HAS_CACHE_LINE_SIZE
++#define cache_line_size() L1_CACHE_BYTES
++#endif
++
+ #endif /* __LINUX_CACHE_H */
+diff --git a/include/linux/capability.h b/include/linux/capability.h
+index 7d50ff6..f4ea0dd 100644
+--- a/include/linux/capability.h
++++ b/include/linux/capability.h
+@@ -155,6 +155,7 @@ typedef struct kernel_cap_struct {
+ * Add any capability from current's capability bounding set
+ * to the current process' inheritable set
+ * Allow taking bits out of capability bounding set
++ * Allow modification of the securebits for a process
+ */
+
+ #define CAP_SETPCAP 8
+@@ -364,12 +365,12 @@ typedef struct kernel_cap_struct {
+ # error Fix up hand-coded capability macro initializers
+ #else /* HAND-CODED capability initializers */
+
+-# define CAP_EMPTY_SET {{ 0, 0 }}
+-# define CAP_FULL_SET {{ ~0, ~0 }}
+-# define CAP_INIT_EFF_SET {{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }}
+-# define CAP_FS_SET {{ CAP_FS_MASK_B0, CAP_FS_MASK_B1 } }
+-# define CAP_NFSD_SET {{ CAP_FS_MASK_B0|CAP_TO_MASK(CAP_SYS_RESOURCE), \
+- CAP_FS_MASK_B1 } }
++# define CAP_EMPTY_SET ((kernel_cap_t){{ 0, 0 }})
++# define CAP_FULL_SET ((kernel_cap_t){{ ~0, ~0 }})
++# define CAP_INIT_EFF_SET ((kernel_cap_t){{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }})
++# define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0, CAP_FS_MASK_B1 } })
++# define CAP_NFSD_SET ((kernel_cap_t){{ CAP_FS_MASK_B0|CAP_TO_MASK(CAP_SYS_RESOURCE), \
++ CAP_FS_MASK_B1 } })
+
+ #endif /* _LINUX_CAPABILITY_U32S != 2 */
+
+@@ -490,8 +491,6 @@ extern const kernel_cap_t __cap_init_eff_set;
+ int capable(int cap);
+ int __capable(struct task_struct *t, int cap);
+
+-extern long cap_prctl_drop(unsigned long cap);
+-
+ #endif /* __KERNEL__ */
+
+ #endif /* !_LINUX_CAPABILITY_H */
+diff --git a/include/linux/cdev.h b/include/linux/cdev.h
+index 1e29b13..fb45919 100644
+--- a/include/linux/cdev.h
++++ b/include/linux/cdev.h
+@@ -1,6 +1,5 @@
+ #ifndef _LINUX_CDEV_H
+ #define _LINUX_CDEV_H
+-#ifdef __KERNEL__
+
+ #include <linux/kobject.h>
+ #include <linux/kdev_t.h>
+@@ -34,4 +33,3 @@ void cd_forget(struct inode *);
+ extern struct backing_dev_info directly_mappable_cdev_bdi;
+
+ #endif
+-#endif
diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
index a5cd204..5db265e 100644
--- a/include/linux/cdrom.h
@@ -811757,6 +1080550,156 @@
typedef struct {
int data;
+diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
+index a6a6035..e155aa7 100644
+--- a/include/linux/cgroup.h
++++ b/include/linux/cgroup.h
+@@ -88,6 +88,17 @@ static inline void css_put(struct cgroup_subsys_state *css)
+ __css_put(css);
+ }
+
++/* bits in struct cgroup flags field */
++enum {
++ /* Control Group is dead */
++ CGRP_REMOVED,
++ /* Control Group has previously had a child cgroup or a task,
++ * but no longer (only if CGRP_NOTIFY_ON_RELEASE is set) */
++ CGRP_RELEASABLE,
++ /* Control Group requires release notifications to userspace */
++ CGRP_NOTIFY_ON_RELEASE,
++};
++
+ struct cgroup {
+ unsigned long flags; /* "unsigned long" so bitops work */
+
+@@ -139,10 +150,10 @@ struct css_set {
+ struct kref ref;
+
+ /*
+- * List running through all cgroup groups. Protected by
+- * css_set_lock
++ * List running through all cgroup groups in the same hash
++ * slot. Protected by css_set_lock
+ */
+- struct list_head list;
++ struct hlist_node hlist;
+
+ /*
+ * List running through all tasks using this cgroup
+@@ -163,7 +174,16 @@ struct css_set {
+ * during subsystem registration (at boot time).
+ */
+ struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
++};
++
++/*
++ * cgroup_map_cb is an abstract callback API for reporting map-valued
++ * control files
++ */
+
++struct cgroup_map_cb {
++ int (*fill)(struct cgroup_map_cb *cb, const char *key, u64 value);
++ void *state;
+ };
+
+ /* struct cftype:
+@@ -190,20 +210,51 @@ struct cftype {
+ struct file *file,
+ char __user *buf, size_t nbytes, loff_t *ppos);
+ /*
+- * read_uint() is a shortcut for the common case of returning a
++ * read_u64() is a shortcut for the common case of returning a
+ * single integer. Use it in place of read()
+ */
+- u64 (*read_uint) (struct cgroup *cgrp, struct cftype *cft);
++ u64 (*read_u64) (struct cgroup *cgrp, struct cftype *cft);
++ /*
++ * read_s64() is a signed version of read_u64()
++ */
++ s64 (*read_s64) (struct cgroup *cgrp, struct cftype *cft);
++ /*
++ * read_map() is used for defining a map of key/value
++ * pairs. It should call cb->fill(cb, key, value) for each
++ * entry. The key/value pairs (and their ordering) should not
++ * change between reboots.
++ */
++ int (*read_map) (struct cgroup *cont, struct cftype *cft,
++ struct cgroup_map_cb *cb);
++ /*
++ * read_seq_string() is used for outputting a simple sequence
++ * using seqfile.
++ */
++ int (*read_seq_string) (struct cgroup *cont, struct cftype *cft,
++ struct seq_file *m);
++
+ ssize_t (*write) (struct cgroup *cgrp, struct cftype *cft,
+ struct file *file,
+ const char __user *buf, size_t nbytes, loff_t *ppos);
+
+ /*
+- * write_uint() is a shortcut for the common case of accepting
++ * write_u64() is a shortcut for the common case of accepting
+ * a single integer (as parsed by simple_strtoull) from
+ * userspace. Use in place of write(); return 0 or error.
+ */
+- int (*write_uint) (struct cgroup *cgrp, struct cftype *cft, u64 val);
++ int (*write_u64) (struct cgroup *cgrp, struct cftype *cft, u64 val);
++ /*
++ * write_s64() is a signed version of write_u64()
++ */
++ int (*write_s64) (struct cgroup *cgrp, struct cftype *cft, s64 val);
++
++ /*
++ * trigger() callback can be used to get some kick from the
++ * userspace, when the actual string written is not important
++ * at all. The private field can be used to determine the
++ * kick type for multiplexing.
++ */
++ int (*trigger)(struct cgroup *cgrp, unsigned int event);
+
+ int (*release) (struct inode *inode, struct file *file);
+ };
+@@ -254,6 +305,12 @@ struct cgroup_subsys {
+ struct cgroup *cgrp);
+ void (*post_clone)(struct cgroup_subsys *ss, struct cgroup *cgrp);
+ void (*bind)(struct cgroup_subsys *ss, struct cgroup *root);
++ /*
++ * This routine is called with the task_lock of mm->owner held
++ */
++ void (*mm_owner_changed)(struct cgroup_subsys *ss,
++ struct cgroup *old,
++ struct cgroup *new);
+ int subsys_id;
+ int active;
+ int disabled;
+@@ -339,4 +396,13 @@ static inline int cgroupstats_build(struct cgroupstats *stats,
+
+ #endif /* !CONFIG_CGROUPS */
+
++#ifdef CONFIG_MM_OWNER
++extern void
++cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new);
++#else /* !CONFIG_MM_OWNER */
++static inline void
++cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new)
++{
++}
++#endif /* CONFIG_MM_OWNER */
+ #endif /* _LINUX_CGROUP_H */
+diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h
+index 1ddebfc..e287745 100644
+--- a/include/linux/cgroup_subsys.h
++++ b/include/linux/cgroup_subsys.h
+@@ -42,3 +42,9 @@ SUBSYS(mem_cgroup)
+ #endif
+
+ /* */
++
++#ifdef CONFIG_CGROUP_DEVICE
++SUBSYS(devices)
++#endif
++
++/* */
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 85778a4..3509447 100644
--- a/include/linux/clocksource.h
@@ -811769,11 +1080712,42 @@
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/coda_fs_i.h b/include/linux/coda_fs_i.h
+index 424fe9c..b3ef0c4 100644
+--- a/include/linux/coda_fs_i.h
++++ b/include/linux/coda_fs_i.h
+@@ -8,7 +8,6 @@
+ #ifndef _LINUX_CODA_FS_I
+ #define _LINUX_CODA_FS_I
+
+-#ifdef __KERNEL__
+ #include <linux/types.h>
+ #include <linux/list.h>
+ #include <linux/coda.h>
+@@ -52,4 +51,3 @@ struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb);
+ void coda_replace_fid(struct inode *, struct CodaFid *, struct CodaFid *);
+
+ #endif
+-#endif
+diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h
+index 1c47a34..31b7531 100644
+--- a/include/linux/coda_linux.h
++++ b/include/linux/coda_linux.h
+@@ -43,9 +43,6 @@ int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+ int coda_setattr(struct dentry *, struct iattr *);
+
+ /* this file: heloers */
+-static __inline__ struct CodaFid *coda_i2f(struct inode *);
+-static __inline__ char *coda_i2s(struct inode *);
+-static __inline__ void coda_flag_inode(struct inode *, int flag);
+ char *coda_f2s(struct CodaFid *f);
+ int coda_isroot(struct inode *i);
+ int coda_iscontrol(const char *name, size_t length);
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
-index fe23792..b2fd754 100644
+index fe23792..5c8351b 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
-@@ -28,9 +28,16 @@
+@@ -28,9 +28,17 @@
#define __must_be_array(a) \
BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&a[0])))
@@ -811781,10 +1080755,11 @@
-#define __inline__ __inline__ __attribute__((always_inline))
-#define __inline __inline __attribute__((always_inline))
+/*
-+ * Force always-inline if the user requests it so via the .config:
++ * Force always-inline if the user requests it so via the .config,
++ * or if gcc is too old:
+ */
+#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
-+ !defined(CONFIG_OPTIMIZE_INLINING) && (__GNUC__ >= 4)
++ !defined(CONFIG_OPTIMIZE_INLINING) || (__GNUC__ < 4)
+# define inline inline __attribute__((always_inline))
+# define __inline__ __inline__ __attribute__((always_inline))
+# define __inline __inline __attribute__((always_inline))
@@ -811793,8 +1080768,80 @@
#define __deprecated __attribute__((deprecated))
#define __packed __attribute__((packed))
#define __weak __attribute__((weak))
+diff --git a/include/linux/concap.h b/include/linux/concap.h
+index 2730465..977acb3 100644
+--- a/include/linux/concap.h
++++ b/include/linux/concap.h
+@@ -8,7 +8,7 @@
+
+ #ifndef _LINUX_CONCAP_H
+ #define _LINUX_CONCAP_H
+-#ifdef __KERNEL__
++
+ #include <linux/skbuff.h>
+ #include <linux/netdevice.h>
+
+@@ -110,4 +110,3 @@ extern int concap_nop(struct concap_proto *cprot);
+ */
+ extern int concap_drop_skb(struct concap_proto *cprot, struct sk_buff *skb);
+ #endif
+-#endif
+diff --git a/include/linux/configfs.h b/include/linux/configfs.h
+index 4b287ad..3ae65b1 100644
+--- a/include/linux/configfs.h
++++ b/include/linux/configfs.h
+@@ -35,8 +35,6 @@
+ #ifndef _CONFIGFS_H_
+ #define _CONFIGFS_H_
+
+-#ifdef __KERNEL__
+-
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+ #include <linux/list.h>
+@@ -194,6 +192,4 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys);
+ int configfs_depend_item(struct configfs_subsystem *subsys, struct config_item *target);
+ void configfs_undepend_item(struct configfs_subsystem *subsys, struct config_item *target);
+
+-#endif /* __KERNEL__ */
+-
+ #endif /* _CONFIGFS_H_ */
+diff --git a/include/linux/console.h b/include/linux/console.h
+index a5f88a6..a4f27fb 100644
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -91,6 +91,7 @@ void give_up_console(const struct consw *sw);
+ #define CON_ENABLED (4)
+ #define CON_BOOT (8)
+ #define CON_ANYTIME (16) /* Safe to call when cpu is offline */
++#define CON_BRL (32) /* Used for a braille device */
+
+ struct console {
+ char name[16];
+@@ -121,6 +122,9 @@ extern struct tty_driver *console_device(int *);
+ extern void console_stop(struct console *);
+ extern void console_start(struct console *);
+ extern int is_console_locked(void);
++extern int braille_register_console(struct console *, int index,
++ char *console_options, char *braille_options);
++extern int braille_unregister_console(struct console *);
+
+ extern int console_suspend_enabled;
+
+diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
+index d71f7c0..b03f80a 100644
+--- a/include/linux/console_struct.h
++++ b/include/linux/console_struct.h
+@@ -53,6 +53,7 @@ struct vc_data {
+ unsigned short vc_hi_font_mask; /* [#] Attribute set for upper 256 chars of font or 0 if not supported */
+ struct console_font vc_font; /* Current VC font set */
+ unsigned short vc_video_erase_char; /* Background erase character */
++ unsigned short vc_scrl_erase_char; /* Erase character for scroll */
+ /* VT terminal data */
+ unsigned int vc_state; /* Escape sequence parser state */
+ unsigned int vc_npar,vc_par[NPAR]; /* Parameters of current escape sequence */
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
-index 0be8d65..f212fa9 100644
+index 0be8d65..7464ba3 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -23,7 +23,6 @@
@@ -811805,11 +1080852,64 @@
#include <linux/mutex.h>
struct cpu {
+@@ -109,7 +108,7 @@ static inline void cpuhotplug_mutex_unlock(struct mutex *cpu_hp_mutex)
+ extern void get_online_cpus(void);
+ extern void put_online_cpus(void);
+ #define hotcpu_notifier(fn, pri) { \
+- static struct notifier_block fn##_nb = \
++ static struct notifier_block fn##_nb __cpuinitdata = \
+ { .notifier_call = fn, .priority = pri }; \
+ register_cpu_notifier(&fn##_nb); \
+ }
+diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
+index ddd8652..e7e91db 100644
+--- a/include/linux/cpufreq.h
++++ b/include/linux/cpufreq.h
+@@ -83,7 +83,8 @@ struct cpufreq_real_policy {
+ };
+
+ struct cpufreq_policy {
+- cpumask_t cpus; /* affected CPUs */
++ cpumask_t cpus; /* CPUs requiring sw coordination */
++ cpumask_t related_cpus; /* CPUs with any coordination */
+ unsigned int shared_type; /* ANY or ALL affected CPUs
+ should set cpufreq */
+ unsigned int cpu; /* cpu nr of registered CPU */
+@@ -307,6 +308,9 @@ extern struct cpufreq_governor cpufreq_gov_performance;
+ #endif
+ #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE
+ #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_performance)
++#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE)
++extern struct cpufreq_governor cpufreq_gov_powersave;
++#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_powersave)
+ #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE)
+ extern struct cpufreq_governor cpufreq_gov_userspace;
+ #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_userspace)
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
-index 7047f58..259c805 100644
+index 7047f58..9650806 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
-@@ -222,8 +222,13 @@ int __next_cpu(int n, const cpumask_t *srcp);
+@@ -14,6 +14,8 @@
+ * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c.
+ * For details of cpu_remap(), see bitmap_bitremap in lib/bitmap.c
+ * For details of cpus_remap(), see bitmap_remap in lib/bitmap.c.
++ * For details of cpus_onto(), see bitmap_onto in lib/bitmap.c.
++ * For details of cpus_fold(), see bitmap_fold in lib/bitmap.c.
+ *
+ * The available cpumask operations are:
+ *
+@@ -53,7 +55,9 @@
+ * int cpulist_scnprintf(buf, len, mask) Format cpumask as list for printing
+ * int cpulist_parse(buf, map) Parse ascii string as cpulist
+ * int cpu_remap(oldbit, old, new) newbit = map(old, new)(oldbit)
+- * int cpus_remap(dst, src, old, new) *dst = map(old, new)(src)
++ * void cpus_remap(dst, src, old, new) *dst = map(old, new)(src)
++ * void cpus_onto(dst, orig, relmap) *dst = orig relative to relmap
++ * void cpus_fold(dst, orig, sz) dst bits = orig bits mod sz
+ *
+ * for_each_cpu_mask(cpu, mask) for-loop cpu over mask
+ *
+@@ -222,8 +226,13 @@ int __next_cpu(int n, const cpumask_t *srcp);
#define next_cpu(n, src) ({ (void)(src); 1; })
#endif
@@ -811824,7 +1080924,7 @@
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);
+@@ -231,8 +240,9 @@ int __next_cpu(int n, const cpumask_t *srcp);
cpus_clear(m); \
cpu_set((cpu), m); \
} \
@@ -811836,7 +1080936,7 @@
#define CPU_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(NR_CPUS)
-@@ -243,6 +249,8 @@ int __next_cpu(int n, const cpumask_t *srcp);
+@@ -243,6 +253,8 @@ int __next_cpu(int n, const cpumask_t *srcp);
[BITS_TO_LONGS(NR_CPUS)-1] = CPU_MASK_LAST_WORD \
} }
@@ -811845,7 +1080945,7 @@
#else
#define CPU_MASK_ALL \
-@@ -251,6 +259,10 @@ int __next_cpu(int n, const cpumask_t *srcp);
+@@ -251,6 +263,10 @@ int __next_cpu(int n, const cpumask_t *srcp);
[BITS_TO_LONGS(NR_CPUS)-1] = CPU_MASK_LAST_WORD \
} }
@@ -811856,7 +1080956,7 @@
#endif
#define CPU_MASK_NONE \
-@@ -273,6 +285,13 @@ static inline int __cpumask_scnprintf(char *buf, int len,
+@@ -273,6 +289,13 @@ static inline int __cpumask_scnprintf(char *buf, int len,
return bitmap_scnprintf(buf, len, srcp->bits, nbits);
}
@@ -811870,11 +1080970,34 @@
#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,
+@@ -311,6 +334,22 @@ static inline void __cpus_remap(cpumask_t *dstp, const cpumask_t *srcp,
+ bitmap_remap(dstp->bits, srcp->bits, oldp->bits, newp->bits, nbits);
+ }
+
++#define cpus_onto(dst, orig, relmap) \
++ __cpus_onto(&(dst), &(orig), &(relmap), NR_CPUS)
++static inline void __cpus_onto(cpumask_t *dstp, const cpumask_t *origp,
++ const cpumask_t *relmapp, int nbits)
++{
++ bitmap_onto(dstp->bits, origp->bits, relmapp->bits, nbits);
++}
++
++#define cpus_fold(dst, orig, sz) \
++ __cpus_fold(&(dst), &(orig), sz, NR_CPUS)
++static inline void __cpus_fold(cpumask_t *dstp, const cpumask_t *origp,
++ int sz, int nbits)
++{
++ bitmap_fold(dstp->bits, origp->bits, sz, nbits);
++}
++
+ #if NR_CPUS > 1
+ #define for_each_cpu_mask(cpu, mask) \
+ for ((cpu) = first_cpu(mask); \
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
-index 0a26be3..726761e 100644
+index 0a26be3..0385783 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? */
+@@ -20,13 +20,13 @@ 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);
@@ -811885,6 +1081008,12 @@
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);
+ void cpuset_update_task_memory_state(void);
+-int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl);
++int cpuset_nodemask_valid_mems_allowed(nodemask_t *nodemask);
+
+ extern int __cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask);
+ extern int __cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask);
@@ -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) {}
@@ -811904,6 +1081033,32 @@
}
static inline nodemask_t cpuset_mems_allowed(struct task_struct *p)
+@@ -102,7 +103,7 @@ static inline nodemask_t cpuset_mems_allowed(struct task_struct *p)
+ static inline void cpuset_init_current_mems_allowed(void) {}
+ static inline void cpuset_update_task_memory_state(void) {}
+
+-static inline int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl)
++static inline int cpuset_nodemask_valid_mems_allowed(nodemask_t *nodemask)
+ {
+ return 1;
+ }
+diff --git a/include/linux/crc-ccitt.h b/include/linux/crc-ccitt.h
+index 9003761..f52696a 100644
+--- a/include/linux/crc-ccitt.h
++++ b/include/linux/crc-ccitt.h
+@@ -1,6 +1,5 @@
+ #ifndef _LINUX_CRC_CCITT_H
+ #define _LINUX_CRC_CCITT_H
+-#ifdef __KERNEL__
+
+ #include <linux/types.h>
+
+@@ -13,5 +12,4 @@ static inline u16 crc_ccitt_byte(u16 crc, const u8 c)
+ return (crc >> 8) ^ crc_ccitt_table[(crc ^ c) & 0xff];
+ }
+
+-#endif /* __KERNEL__ */
+ #endif /* _LINUX_CRC_CCITT_H */
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 5e02d1b..425824b 100644
--- a/include/linux/crypto.h
@@ -811924,10 +1081079,19 @@
/*
* Transforms: user-instantiated objects which encapsulate algorithms
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
-index 6bd6460..cfb1627 100644
+index 6bd6460..2a66394 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
-@@ -301,7 +301,9 @@ extern int d_validate(struct dentry *, struct dentry *);
+@@ -1,8 +1,6 @@
+ #ifndef __LINUX_DCACHE_H
+ #define __LINUX_DCACHE_H
+
+-#ifdef __KERNEL__
+-
+ #include <asm/atomic.h>
+ #include <linux/list.h>
+ #include <linux/spinlock.h>
+@@ -301,7 +299,9 @@ extern int d_validate(struct dentry *, struct dentry *);
*/
extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
@@ -811937,7 +1081101,7 @@
/* Allocation counts.. */
-@@ -359,7 +361,6 @@ static inline int d_mountpoint(struct dentry *dentry)
+@@ -359,11 +359,8 @@ static inline int d_mountpoint(struct dentry *dentry)
}
extern struct vfsmount *lookup_mnt(struct vfsmount *, struct dentry *);
@@ -811945,8 +1081109,108 @@
extern struct dentry *lookup_create(struct nameidata *nd, int is_dir);
extern int sysctl_vfs_cache_pressure;
+
+-#endif /* __KERNEL__ */
+-
+ #endif /* __LINUX_DCACHE_H */
+diff --git a/include/linux/debugobjects.h b/include/linux/debugobjects.h
+new file mode 100644
+index 0000000..8c243aa
+--- /dev/null
++++ b/include/linux/debugobjects.h
+@@ -0,0 +1,90 @@
++#ifndef _LINUX_DEBUGOBJECTS_H
++#define _LINUX_DEBUGOBJECTS_H
++
++#include <linux/list.h>
++#include <linux/spinlock.h>
++
++enum debug_obj_state {
++ ODEBUG_STATE_NONE,
++ ODEBUG_STATE_INIT,
++ ODEBUG_STATE_INACTIVE,
++ ODEBUG_STATE_ACTIVE,
++ ODEBUG_STATE_DESTROYED,
++ ODEBUG_STATE_NOTAVAILABLE,
++ ODEBUG_STATE_MAX,
++};
++
++struct debug_obj_descr;
++
++/**
++ * struct debug_obj - representaion of an tracked object
++ * @node: hlist node to link the object into the tracker list
++ * @state: tracked object state
++ * @object: pointer to the real object
++ * @descr: pointer to an object type specific debug description structure
++ */
++struct debug_obj {
++ struct hlist_node node;
++ enum debug_obj_state state;
++ void *object;
++ struct debug_obj_descr *descr;
++};
++
++/**
++ * struct debug_obj_descr - object type specific debug description structure
++ * @name: name of the object typee
++ * @fixup_init: fixup function, which is called when the init check
++ * fails
++ * @fixup_activate: fixup function, which is called when the activate check
++ * fails
++ * @fixup_destroy: fixup function, which is called when the destroy check
++ * fails
++ * @fixup_free: fixup function, which is called when the free check
++ * fails
++ */
++struct debug_obj_descr {
++ const char *name;
++
++ int (*fixup_init) (void *addr, enum debug_obj_state state);
++ int (*fixup_activate) (void *addr, enum debug_obj_state state);
++ int (*fixup_destroy) (void *addr, enum debug_obj_state state);
++ int (*fixup_free) (void *addr, enum debug_obj_state state);
++};
++
++#ifdef CONFIG_DEBUG_OBJECTS
++extern void debug_object_init (void *addr, struct debug_obj_descr *descr);
++extern void
++debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr);
++extern void debug_object_activate (void *addr, struct debug_obj_descr *descr);
++extern void debug_object_deactivate(void *addr, struct debug_obj_descr *descr);
++extern void debug_object_destroy (void *addr, struct debug_obj_descr *descr);
++extern void debug_object_free (void *addr, struct debug_obj_descr *descr);
++
++extern void debug_objects_early_init(void);
++extern void debug_objects_mem_init(void);
++#else
++static inline void
++debug_object_init (void *addr, struct debug_obj_descr *descr) { }
++static inline void
++debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr) { }
++static inline void
++debug_object_activate (void *addr, struct debug_obj_descr *descr) { }
++static inline void
++debug_object_deactivate(void *addr, struct debug_obj_descr *descr) { }
++static inline void
++debug_object_destroy (void *addr, struct debug_obj_descr *descr) { }
++static inline void
++debug_object_free (void *addr, struct debug_obj_descr *descr) { }
++
++static inline void debug_objects_early_init(void) { }
++static inline void debug_objects_mem_init(void) { }
++#endif
++
++#ifdef CONFIG_DEBUG_OBJECTS_FREE
++extern void debug_check_no_obj_freed(const void *address, unsigned long size);
++#else
++static inline void
++debug_check_no_obj_freed(const void *address, unsigned long size) { }
++#endif
++
++#endif
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
-index cb78457..ad3b787 100644
+index cb78457..0d8d419 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -1,6 +1,6 @@
@@ -811957,16 +1081221,16 @@
*
* This file is released under the LGPL.
*/
-@@ -10,6 +10,8 @@
-
- #ifdef __KERNEL__
+@@ -8,7 +8,7 @@
+ #ifndef _LINUX_DEVICE_MAPPER_H
+ #define _LINUX_DEVICE_MAPPER_H
+-#ifdef __KERNEL__
+#include <linux/bio.h>
-+
+
struct dm_target;
struct dm_table;
- struct dm_dev;
-@@ -250,11 +252,97 @@ void dm_table_event(struct dm_table *t);
+@@ -250,11 +250,96 @@ void dm_table_event(struct dm_table *t);
*/
int dm_swap_table(struct mapped_device *md, struct dm_table *t);
@@ -812027,9 +1081291,12 @@
+#define DM_ENDIO_INCOMPLETE 1
+#define DM_ENDIO_REQUEUE 2
+
-+/*
+ /*
+- * 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().
+ * Definitions of return values from target map function.
-+ */
+ */
+-int dm_create_error_table(struct dm_table **result, struct mapped_device *md);
+#define DM_MAPIO_SUBMITTED 0
+#define DM_MAPIO_REMAPPED 1
+#define DM_MAPIO_REQUEUE DM_ENDIO_REQUEUE
@@ -812047,12 +1081314,9 @@
+} \
+)
+
- /*
-- * 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)
@@ -812065,10 +1081329,10 @@
+ return (n << SECTOR_SHIFT);
+}
- #endif /* __KERNEL__ */
+-#endif /* __KERNEL__ */
#endif /* _LINUX_DEVICE_MAPPER_H */
diff --git a/include/linux/device.h b/include/linux/device.h
-index 2258d89..1a06026 100644
+index 2258d89..832fb0e 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -20,7 +20,7 @@
@@ -812080,7 +1081344,146 @@
#include <asm/atomic.h>
#include <asm/device.h>
-@@ -429,7 +429,6 @@ struct device {
+@@ -35,7 +35,6 @@ struct device;
+ struct device_driver;
+ struct driver_private;
+ struct class;
+-struct class_device;
+ struct bus_type;
+ struct bus_type_private;
+
+@@ -190,13 +189,10 @@ struct class {
+ struct kset class_dirs;
+ struct semaphore sem; /* locks children, devices, interfaces */
+ struct class_attribute *class_attrs;
+- struct class_device_attribute *class_dev_attrs;
+ struct device_attribute *dev_attrs;
+
+- int (*uevent)(struct class_device *dev, struct kobj_uevent_env *env);
+ int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
+
+- void (*release)(struct class_device *dev);
+ void (*class_release)(struct class *class);
+ void (*dev_release)(struct device *dev);
+
+@@ -210,9 +206,6 @@ extern int class_for_each_device(struct class *class, void *data,
+ int (*fn)(struct device *dev, void *data));
+ extern struct device *class_find_device(struct class *class, void *data,
+ int (*match)(struct device *, void *));
+-extern struct class_device *class_find_child(struct class *class, void *data,
+- int (*match)(struct class_device *, void *));
+-
+
+ struct class_attribute {
+ struct attribute attr;
+@@ -228,92 +221,10 @@ extern int __must_check class_create_file(struct class *class,
+ extern void class_remove_file(struct class *class,
+ const struct class_attribute *attr);
+
+-struct class_device_attribute {
+- struct attribute attr;
+- ssize_t (*show)(struct class_device *, char *buf);
+- ssize_t (*store)(struct class_device *, const char *buf, size_t count);
+-};
+-
+-#define CLASS_DEVICE_ATTR(_name, _mode, _show, _store) \
+-struct class_device_attribute class_device_attr_##_name = \
+- __ATTR(_name, _mode, _show, _store)
+-
+-extern int __must_check class_device_create_file(struct class_device *,
+- const struct class_device_attribute *);
+-
+-/**
+- * struct class_device - class devices
+- * @class: pointer to the parent class for this class device. This is required.
+- * @devt: for internal use by the driver core only.
+- * @node: for internal use by the driver core only.
+- * @kobj: for internal use by the driver core only.
+- * @groups: optional additional groups to be created
+- * @dev: if set, a symlink to the struct device is created in the sysfs
+- * directory for this struct class device.
+- * @class_data: pointer to whatever you want to store here for this struct
+- * class_device. Use class_get_devdata() and class_set_devdata() to get and
+- * set this pointer.
+- * @parent: pointer to a struct class_device that is the parent of this struct
+- * class_device. If NULL, this class_device will show up at the root of the
+- * struct class in sysfs (which is probably what you want to have happen.)
+- * @release: pointer to a release function for this struct class_device. If
+- * set, this will be called instead of the class specific release function.
+- * Only use this if you want to override the default release function, like
+- * when you are nesting class_device structures.
+- * @uevent: pointer to a uevent function for this struct class_device. If
+- * set, this will be called instead of the class specific uevent function.
+- * Only use this if you want to override the default uevent function, like
+- * when you are nesting class_device structures.
+- */
+-struct class_device {
+- struct list_head node;
+-
+- struct kobject kobj;
+- struct class *class;
+- dev_t devt;
+- struct device *dev;
+- void *class_data;
+- struct class_device *parent;
+- struct attribute_group **groups;
+-
+- void (*release)(struct class_device *dev);
+- int (*uevent)(struct class_device *dev, struct kobj_uevent_env *env);
+- char class_id[BUS_ID_SIZE];
+-};
+-
+-static inline void *class_get_devdata(struct class_device *dev)
+-{
+- return dev->class_data;
+-}
+-
+-static inline void class_set_devdata(struct class_device *dev, void *data)
+-{
+- dev->class_data = data;
+-}
+-
+-
+-extern int __must_check class_device_register(struct class_device *);
+-extern void class_device_unregister(struct class_device *);
+-extern void class_device_initialize(struct class_device *);
+-extern int __must_check class_device_add(struct class_device *);
+-extern void class_device_del(struct class_device *);
+-
+-extern struct class_device *class_device_get(struct class_device *);
+-extern void class_device_put(struct class_device *);
+-
+-extern void class_device_remove_file(struct class_device *,
+- const struct class_device_attribute *);
+-extern int __must_check class_device_create_bin_file(struct class_device *,
+- struct bin_attribute *);
+-extern void class_device_remove_bin_file(struct class_device *,
+- struct bin_attribute *);
+-
+ struct class_interface {
+ struct list_head node;
+ struct class *class;
+
+- int (*add) (struct class_device *, struct class_interface *);
+- void (*remove) (struct class_device *, struct class_interface *);
+ int (*add_dev) (struct device *, struct class_interface *);
+ void (*remove_dev) (struct device *, struct class_interface *);
+ };
+@@ -323,13 +234,6 @@ extern void class_interface_unregister(struct class_interface *);
+
+ extern struct class *class_create(struct module *owner, const char *name);
+ extern void class_destroy(struct class *cls);
+-extern struct class_device *class_device_create(struct class *cls,
+- struct class_device *parent,
+- dev_t devt,
+- struct device *device,
+- const char *fmt, ...)
+- __attribute__((format(printf, 5, 6)));
+-extern void class_device_destroy(struct class *cls, dev_t devt);
+
+ /*
+ * The type of device, "struct device" is embedded in. A class
+@@ -429,7 +333,6 @@ struct device {
struct kobject kobj;
char bus_id[BUS_ID_SIZE]; /* position on parent bus */
struct device_type *type;
@@ -812088,7 +1081491,15 @@
unsigned uevent_suppress:1;
struct semaphore sem; /* semaphore to synchronize calls to
-@@ -475,6 +474,9 @@ struct device {
+@@ -466,7 +369,6 @@ struct device {
+ spinlock_t devres_lock;
+ struct list_head devres_head;
+
+- /* class_device migration path */
+ struct list_head node;
+ struct class *class;
+ dev_t devt; /* dev_t, creates the sysfs "dev" */
+@@ -475,6 +377,9 @@ struct device {
void (*release)(struct device *dev);
};
@@ -812098,7 +1081509,7 @@
#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)
+@@ -506,7 +411,7 @@ static inline void dev_set_drvdata(struct device *dev, void *data)
static inline int device_is_registered(struct device *dev)
{
@@ -812107,7 +1081518,7 @@
}
void driver_init(void);
-@@ -543,20 +545,6 @@ extern struct device *device_create(struct class *cls, struct device *parent,
+@@ -543,20 +448,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);
@@ -812128,7 +1081539,7 @@
/*
* Platform "fixup" functions - allow the platform to have their say
-@@ -608,21 +596,16 @@ extern const char *dev_driver_string(struct device *dev);
+@@ -608,21 +499,16 @@ extern const char *dev_driver_string(struct device *dev);
#define dev_dbg(dev, format, arg...) \
dev_printk(KERN_DEBUG , dev , format , ## arg)
#else
@@ -812155,6 +1081566,46 @@
#endif
/* Create alias, so I can be autoloaded. */
+diff --git a/include/linux/device_cgroup.h b/include/linux/device_cgroup.h
+new file mode 100644
+index 0000000..0b0d9c3
+--- /dev/null
++++ b/include/linux/device_cgroup.h
+@@ -0,0 +1,12 @@
++#include <linux/module.h>
++#include <linux/fs.h>
++
++#ifdef CONFIG_CGROUP_DEVICE
++extern int devcgroup_inode_permission(struct inode *inode, int mask);
++extern int devcgroup_inode_mknod(int mode, dev_t dev);
++#else
++static inline int devcgroup_inode_permission(struct inode *inode, int mask)
++{ return 0; }
++static inline int devcgroup_inode_mknod(int mode, dev_t dev)
++{ return 0; }
++#endif
+diff --git a/include/linux/devpts_fs.h b/include/linux/devpts_fs.h
+index b672ddc..154769c 100644
+--- a/include/linux/devpts_fs.h
++++ b/include/linux/devpts_fs.h
+@@ -17,6 +17,8 @@
+
+ #ifdef CONFIG_UNIX98_PTYS
+
++int devpts_new_index(void);
++void devpts_kill_index(int idx);
+ int devpts_pty_new(struct tty_struct *tty); /* mknod in devpts */
+ struct tty_struct *devpts_get_tty(int number); /* get tty structure */
+ void devpts_pty_kill(int number); /* unlink */
+@@ -24,6 +26,8 @@ void devpts_pty_kill(int number); /* unlink */
+ #else
+
+ /* Dummy stubs in the no-pty case */
++static inline int devpts_new_index(void) { return -EINVAL; }
++static inline void devpts_kill_index(int idx) { }
+ static inline int devpts_pty_new(struct tty_struct *tty) { return -EINVAL; }
+ static inline struct tty_struct *devpts_get_tty(int number) { return NULL; }
+ static inline void devpts_pty_kill(int number) { }
diff --git a/include/linux/dlm.h b/include/linux/dlm.h
index c743fbc..203a025 100644
--- a/include/linux/dlm.h
@@ -812566,6 +1082017,112 @@
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_DM_KCOPYD_H */
+diff --git a/include/linux/dma-attrs.h b/include/linux/dma-attrs.h
+new file mode 100644
+index 0000000..1677e2b
+--- /dev/null
++++ b/include/linux/dma-attrs.h
+@@ -0,0 +1,74 @@
++#ifndef _DMA_ATTR_H
++#define _DMA_ATTR_H
++
++#include <linux/bitmap.h>
++#include <linux/bitops.h>
++#include <linux/bug.h>
++
++/**
++ * an enum dma_attr represents an attribute associated with a DMA
++ * mapping. The semantics of each attribute should be defined in
++ * Documentation/DMA-attributes.txt.
++ */
++enum dma_attr {
++ DMA_ATTR_WRITE_BARRIER,
++ DMA_ATTR_MAX,
++};
++
++#define __DMA_ATTRS_LONGS BITS_TO_LONGS(DMA_ATTR_MAX)
++
++/**
++ * struct dma_attrs - an opaque container for DMA attributes
++ * @flags - bitmask representing a collection of enum dma_attr
++ */
++struct dma_attrs {
++ unsigned long flags[__DMA_ATTRS_LONGS];
++};
++
++#define DEFINE_DMA_ATTRS(x) \
++ struct dma_attrs x = { \
++ .flags = { [0 ... __DMA_ATTRS_LONGS-1] = 0 }, \
++ }
++
++static inline void init_dma_attrs(struct dma_attrs *attrs)
++{
++ bitmap_zero(attrs->flags, __DMA_ATTRS_LONGS);
++}
++
++#ifdef CONFIG_HAVE_DMA_ATTRS
++/**
++ * dma_set_attr - set a specific attribute
++ * @attr: attribute to set
++ * @attrs: struct dma_attrs (may be NULL)
++ */
++static inline void dma_set_attr(enum dma_attr attr, struct dma_attrs *attrs)
++{
++ if (attrs == NULL)
++ return;
++ BUG_ON(attr >= DMA_ATTR_MAX);
++ __set_bit(attr, attrs->flags);
++}
++
++/**
++ * dma_get_attr - check for a specific attribute
++ * @attr: attribute to set
++ * @attrs: struct dma_attrs (may be NULL)
++ */
++static inline int dma_get_attr(enum dma_attr attr, struct dma_attrs *attrs)
++{
++ if (attrs == NULL)
++ return 0;
++ BUG_ON(attr >= DMA_ATTR_MAX);
++ return test_bit(attr, attrs->flags);
++}
++#else /* !CONFIG_HAVE_DMA_ATTRS */
++static inline void dma_set_attr(enum dma_attr attr, struct dma_attrs *attrs)
++{
++}
++
++static inline int dma_get_attr(enum dma_attr attr, struct dma_attrs *attrs)
++{
++ return 0;
++}
++#endif /* CONFIG_HAVE_DMA_ATTRS */
++#endif /* _DMA_ATTR_H */
+diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
+index 3320307..952e0f8 100644
+--- a/include/linux/dma-mapping.h
++++ b/include/linux/dma-mapping.h
+@@ -146,4 +146,21 @@ static inline void dmam_release_declared_memory(struct device *dev)
+ }
+ #endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
+
++#ifndef CONFIG_HAVE_DMA_ATTRS
++struct dma_attrs;
++
++#define dma_map_single_attrs(dev, cpu_addr, size, dir, attrs) \
++ dma_map_single(dev, cpu_addr, size, dir)
++
++#define dma_unmap_single_attrs(dev, dma_addr, size, dir, attrs) \
++ dma_unmap_single(dev, dma_addr, size, dir)
++
++#define dma_map_sg_attrs(dev, sgl, nents, dir, attrs) \
++ dma_map_sg(dev, sgl, nents, dir)
++
++#define dma_unmap_sg_attrs(dev, sgl, nents, dir, attrs) \
++ dma_unmap_sg(dev, sgl, nents, dir)
++
++#endif /* CONFIG_HAVE_DMA_ATTRS */
++
+ #endif
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 34d4406..d08a5c5 100644
--- a/include/linux/dmaengine.h
@@ -812672,6 +1082229,18 @@
*/
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/dmi.h b/include/linux/dmi.h
+index 325acdf..2a063b6 100644
+--- a/include/linux/dmi.h
++++ b/include/linux/dmi.h
+@@ -90,6 +90,7 @@ static inline int dmi_check_system(const struct dmi_system_id *list) { return 0;
+ static inline const char * dmi_get_system_info(int field) { return NULL; }
+ static inline const struct dmi_device * dmi_find_device(int type, const char *name,
+ const struct dmi_device *from) { return NULL; }
++static inline void dmi_scan_machine(void) { return; }
+ static inline int dmi_get_year(int year) { return 0; }
+ static inline int dmi_name_in_vendors(const char *s) { return 0; }
+ #define dmi_available 0
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index c6a2353..402fb7a 100644
--- a/include/linux/dvb/dmx.h
@@ -812688,6 +1082257,36 @@
} dmx_output_t;
+diff --git a/include/linux/edac.h b/include/linux/edac.h
+index eab451e..7cf92e8 100644
+--- a/include/linux/edac.h
++++ b/include/linux/edac.h
+@@ -3,7 +3,7 @@
+ *
+ * Author: Dave Jiang <djiang at mvista.com>
+ *
+- * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under
++ * 2006-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.
+@@ -26,4 +26,16 @@ extern atomic_t edac_handlers;
+ extern int edac_handler_set(void);
+ extern void edac_atomic_assert_error(void);
+
++static inline void opstate_init(void)
++{
++ switch (edac_op_state) {
++ case EDAC_OPSTATE_POLL:
++ case EDAC_OPSTATE_NMI:
++ break;
++ default:
++ edac_op_state = EDAC_OPSTATE_POLL;
++ }
++ return;
++}
++
+ #endif
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 14813b5..a5f359a 100644
--- a/include/linux/efi.h
@@ -812711,6 +1082310,19 @@
+}
+
#endif /* _LINUX_EFI_H */
+diff --git a/include/linux/elf.h b/include/linux/elf.h
+index bad1b16..ff9fbed 100644
+--- a/include/linux/elf.h
++++ b/include/linux/elf.h
+@@ -208,7 +208,7 @@ typedef struct elf32_hdr{
+ } Elf32_Ehdr;
+
+ typedef struct elf64_hdr {
+- unsigned char e_ident[16]; /* ELF "magic number" */
++ unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */
+ Elf64_Half e_type;
+ Elf64_Half e_machine;
+ Elf64_Word e_version;
diff --git a/include/linux/enclosure.h b/include/linux/enclosure.h
index a5978f1..4332442 100644
--- a/include/linux/enclosure.h
@@ -812750,6 +1082362,28 @@
{
return container_of(dev, struct enclosure_component, cdev);
}
+diff --git a/include/linux/eventfd.h b/include/linux/eventfd.h
+index b489fc6..a701399 100644
+--- a/include/linux/eventfd.h
++++ b/include/linux/eventfd.h
+@@ -8,9 +8,6 @@
+ #ifndef _LINUX_EVENTFD_H
+ #define _LINUX_EVENTFD_H
+
+-
+-#ifdef __KERNEL__
+-
+ #ifdef CONFIG_EVENTFD
+
+ struct file *eventfd_fget(int fd);
+@@ -24,7 +21,5 @@ static inline int eventfd_signal(struct file *file, int n)
+
+ #endif /* CONFIG_EVENTFD */
+
+-#endif /* __KERNEL__ */
+-
+ #endif /* _LINUX_EVENTFD_H */
+
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
index adcbb05..de8387b 100644
--- a/include/linux/exportfs.h
@@ -812763,6 +1082397,2090 @@
};
};
+diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h
+deleted file mode 100644
+index 2500325..0000000
+--- a/include/linux/ext4_fs.h
++++ /dev/null
+@@ -1,1207 +0,0 @@
+-/*
+- * linux/include/linux/ext4_fs.h
+- *
+- * Copyright (C) 1992, 1993, 1994, 1995
+- * Remy Card (card at masi.ibp.fr)
+- * Laboratoire MASI - Institut Blaise Pascal
+- * Universite Pierre et Marie Curie (Paris VI)
+- *
+- * from
+- *
+- * linux/include/linux/minix_fs.h
+- *
+- * Copyright (C) 1991, 1992 Linus Torvalds
+- */
+-
+-#ifndef _LINUX_EXT4_FS_H
+-#define _LINUX_EXT4_FS_H
+-
+-#include <linux/types.h>
+-#include <linux/blkdev.h>
+-#include <linux/magic.h>
+-
+-#include <linux/ext4_fs_i.h>
+-
+-/*
+- * The second extended filesystem constants/structures
+- */
+-
+-/*
+- * Define EXT4FS_DEBUG to produce debug messages
+- */
+-#undef EXT4FS_DEBUG
+-
+-/*
+- * Define EXT4_RESERVATION to reserve data blocks for expanding files
+- */
+-#define EXT4_DEFAULT_RESERVE_BLOCKS 8
+-/*max window size: 1024(direct blocks) + 3([t,d]indirect blocks) */
+-#define EXT4_MAX_RESERVE_BLOCKS 1027
+-#define EXT4_RESERVE_WINDOW_NOT_ALLOCATED 0
+-
+-/*
+- * Debug code
+- */
+-#ifdef EXT4FS_DEBUG
+-#define ext4_debug(f, a...) \
+- do { \
+- printk (KERN_DEBUG "EXT4-fs DEBUG (%s, %d): %s:", \
+- __FILE__, __LINE__, __FUNCTION__); \
+- printk (KERN_DEBUG f, ## a); \
+- } while (0)
+-#else
+-#define ext4_debug(f, a...) do {} while (0)
+-#endif
+-
+-#define EXT4_MULTIBLOCK_ALLOCATOR 1
+-
+-/* prefer goal again. length */
+-#define EXT4_MB_HINT_MERGE 1
+-/* blocks already reserved */
+-#define EXT4_MB_HINT_RESERVED 2
+-/* metadata is being allocated */
+-#define EXT4_MB_HINT_METADATA 4
+-/* first blocks in the file */
+-#define EXT4_MB_HINT_FIRST 8
+-/* search for the best chunk */
+-#define EXT4_MB_HINT_BEST 16
+-/* data is being allocated */
+-#define EXT4_MB_HINT_DATA 32
+-/* don't preallocate (for tails) */
+-#define EXT4_MB_HINT_NOPREALLOC 64
+-/* allocate for locality group */
+-#define EXT4_MB_HINT_GROUP_ALLOC 128
+-/* allocate goal blocks or none */
+-#define EXT4_MB_HINT_GOAL_ONLY 256
+-/* goal is meaningful */
+-#define EXT4_MB_HINT_TRY_GOAL 512
+-
+-struct ext4_allocation_request {
+- /* target inode for block we're allocating */
+- struct inode *inode;
+- /* logical block in target inode */
+- ext4_lblk_t logical;
+- /* phys. target (a hint) */
+- ext4_fsblk_t goal;
+- /* the closest logical allocated block to the left */
+- ext4_lblk_t lleft;
+- /* phys. block for ^^^ */
+- ext4_fsblk_t pleft;
+- /* the closest logical allocated block to the right */
+- ext4_lblk_t lright;
+- /* phys. block for ^^^ */
+- ext4_fsblk_t pright;
+- /* how many blocks we want to allocate */
+- unsigned long len;
+- /* flags. see above EXT4_MB_HINT_* */
+- unsigned long flags;
+-};
+-
+-/*
+- * Special inodes numbers
+- */
+-#define EXT4_BAD_INO 1 /* Bad blocks inode */
+-#define EXT4_ROOT_INO 2 /* Root inode */
+-#define EXT4_BOOT_LOADER_INO 5 /* Boot loader inode */
+-#define EXT4_UNDEL_DIR_INO 6 /* Undelete directory inode */
+-#define EXT4_RESIZE_INO 7 /* Reserved group descriptors inode */
+-#define EXT4_JOURNAL_INO 8 /* Journal inode */
+-
+-/* First non-reserved inode for old ext4 filesystems */
+-#define EXT4_GOOD_OLD_FIRST_INO 11
+-
+-/*
+- * Maximal count of links to a file
+- */
+-#define EXT4_LINK_MAX 65000
+-
+-/*
+- * Macro-instructions used to manage several block sizes
+- */
+-#define EXT4_MIN_BLOCK_SIZE 1024
+-#define EXT4_MAX_BLOCK_SIZE 65536
+-#define EXT4_MIN_BLOCK_LOG_SIZE 10
+-#ifdef __KERNEL__
+-# define EXT4_BLOCK_SIZE(s) ((s)->s_blocksize)
+-#else
+-# define EXT4_BLOCK_SIZE(s) (EXT4_MIN_BLOCK_SIZE << (s)->s_log_block_size)
+-#endif
+-#define EXT4_ADDR_PER_BLOCK(s) (EXT4_BLOCK_SIZE(s) / sizeof (__u32))
+-#ifdef __KERNEL__
+-# define EXT4_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
+-#else
+-# define EXT4_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
+-#endif
+-#ifdef __KERNEL__
+-#define EXT4_ADDR_PER_BLOCK_BITS(s) (EXT4_SB(s)->s_addr_per_block_bits)
+-#define EXT4_INODE_SIZE(s) (EXT4_SB(s)->s_inode_size)
+-#define EXT4_FIRST_INO(s) (EXT4_SB(s)->s_first_ino)
+-#else
+-#define EXT4_INODE_SIZE(s) (((s)->s_rev_level == EXT4_GOOD_OLD_REV) ? \
+- EXT4_GOOD_OLD_INODE_SIZE : \
+- (s)->s_inode_size)
+-#define EXT4_FIRST_INO(s) (((s)->s_rev_level == EXT4_GOOD_OLD_REV) ? \
+- EXT4_GOOD_OLD_FIRST_INO : \
+- (s)->s_first_ino)
+-#endif
+-#define EXT4_BLOCK_ALIGN(size, blkbits) ALIGN((size), (1 << (blkbits)))
+-
+-/*
+- * Structure of a blocks group descriptor
+- */
+-struct ext4_group_desc
+-{
+- __le32 bg_block_bitmap_lo; /* Blocks bitmap block */
+- __le32 bg_inode_bitmap_lo; /* Inodes bitmap block */
+- __le32 bg_inode_table_lo; /* Inodes table block */
+- __le16 bg_free_blocks_count; /* Free blocks count */
+- __le16 bg_free_inodes_count; /* Free inodes count */
+- __le16 bg_used_dirs_count; /* Directories count */
+- __le16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */
+- __u32 bg_reserved[2]; /* Likely block/inode bitmap checksum */
+- __le16 bg_itable_unused; /* Unused inodes count */
+- __le16 bg_checksum; /* crc16(sb_uuid+group+desc) */
+- __le32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */
+- __le32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */
+- __le32 bg_inode_table_hi; /* Inodes table block MSB */
+- __le16 bg_free_blocks_count_hi;/* Free blocks count MSB */
+- __le16 bg_free_inodes_count_hi;/* Free inodes count MSB */
+- __le16 bg_used_dirs_count_hi; /* Directories count MSB */
+- __le16 bg_itable_unused_hi; /* Unused inodes count MSB */
+- __u32 bg_reserved2[3];
+-};
+-
+-#define EXT4_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not in use */
+-#define EXT4_BG_BLOCK_UNINIT 0x0002 /* Block bitmap not in use */
+-#define EXT4_BG_INODE_ZEROED 0x0004 /* On-disk itable initialized to zero */
+-
+-#ifdef __KERNEL__
+-#include <linux/ext4_fs_i.h>
+-#include <linux/ext4_fs_sb.h>
+-#endif
+-/*
+- * Macro-instructions used to manage group descriptors
+- */
+-#define EXT4_MIN_DESC_SIZE 32
+-#define EXT4_MIN_DESC_SIZE_64BIT 64
+-#define EXT4_MAX_DESC_SIZE EXT4_MIN_BLOCK_SIZE
+-#define EXT4_DESC_SIZE(s) (EXT4_SB(s)->s_desc_size)
+-#ifdef __KERNEL__
+-# define EXT4_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_blocks_per_group)
+-# define EXT4_DESC_PER_BLOCK(s) (EXT4_SB(s)->s_desc_per_block)
+-# define EXT4_INODES_PER_GROUP(s) (EXT4_SB(s)->s_inodes_per_group)
+-# define EXT4_DESC_PER_BLOCK_BITS(s) (EXT4_SB(s)->s_desc_per_block_bits)
+-#else
+-# define EXT4_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group)
+-# define EXT4_DESC_PER_BLOCK(s) (EXT4_BLOCK_SIZE(s) / EXT4_DESC_SIZE(s))
+-# define EXT4_INODES_PER_GROUP(s) ((s)->s_inodes_per_group)
+-#endif
+-
+-/*
+- * Constants relative to the data blocks
+- */
+-#define EXT4_NDIR_BLOCKS 12
+-#define EXT4_IND_BLOCK EXT4_NDIR_BLOCKS
+-#define EXT4_DIND_BLOCK (EXT4_IND_BLOCK + 1)
+-#define EXT4_TIND_BLOCK (EXT4_DIND_BLOCK + 1)
+-#define EXT4_N_BLOCKS (EXT4_TIND_BLOCK + 1)
+-
+-/*
+- * Inode flags
+- */
+-#define EXT4_SECRM_FL 0x00000001 /* Secure deletion */
+-#define EXT4_UNRM_FL 0x00000002 /* Undelete */
+-#define EXT4_COMPR_FL 0x00000004 /* Compress file */
+-#define EXT4_SYNC_FL 0x00000008 /* Synchronous updates */
+-#define EXT4_IMMUTABLE_FL 0x00000010 /* Immutable file */
+-#define EXT4_APPEND_FL 0x00000020 /* writes to file may only append */
+-#define EXT4_NODUMP_FL 0x00000040 /* do not dump file */
+-#define EXT4_NOATIME_FL 0x00000080 /* do not update atime */
+-/* Reserved for compression usage... */
+-#define EXT4_DIRTY_FL 0x00000100
+-#define EXT4_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
+-#define EXT4_NOCOMPR_FL 0x00000400 /* Don't compress */
+-#define EXT4_ECOMPR_FL 0x00000800 /* Compression error */
+-/* End compression flags --- maybe not all used */
+-#define EXT4_INDEX_FL 0x00001000 /* hash-indexed directory */
+-#define EXT4_IMAGIC_FL 0x00002000 /* AFS directory */
+-#define EXT4_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
+-#define EXT4_NOTAIL_FL 0x00008000 /* file tail should not be merged */
+-#define EXT4_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */
+-#define EXT4_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
+-#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */
+-#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
+-#define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */
+-
+-#define EXT4_FL_USER_VISIBLE 0x000BDFFF /* User visible flags */
+-#define EXT4_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */
+-
+-/*
+- * Inode dynamic state flags
+- */
+-#define EXT4_STATE_JDATA 0x00000001 /* journaled data exists */
+-#define EXT4_STATE_NEW 0x00000002 /* inode is newly created */
+-#define EXT4_STATE_XATTR 0x00000004 /* has in-inode xattrs */
+-#define EXT4_STATE_NO_EXPAND 0x00000008 /* No space for expansion */
+-
+-/* Used to pass group descriptor data when online resize is done */
+-struct ext4_new_group_input {
+- __u32 group; /* Group number for this data */
+- __u64 block_bitmap; /* Absolute block number of block bitmap */
+- __u64 inode_bitmap; /* Absolute block number of inode bitmap */
+- __u64 inode_table; /* Absolute block number of inode table start */
+- __u32 blocks_count; /* Total number of blocks in this group */
+- __u16 reserved_blocks; /* Number of reserved blocks in this group */
+- __u16 unused;
+-};
+-
+-/* The struct ext4_new_group_input in kernel space, with free_blocks_count */
+-struct ext4_new_group_data {
+- __u32 group;
+- __u64 block_bitmap;
+- __u64 inode_bitmap;
+- __u64 inode_table;
+- __u32 blocks_count;
+- __u16 reserved_blocks;
+- __u16 unused;
+- __u32 free_blocks_count;
+-};
+-
+-/*
+- * Following is used by preallocation code to tell get_blocks() that we
+- * want uninitialzed extents.
+- */
+-#define EXT4_CREATE_UNINITIALIZED_EXT 2
+-
+-/*
+- * ioctl commands
+- */
+-#define EXT4_IOC_GETFLAGS FS_IOC_GETFLAGS
+-#define EXT4_IOC_SETFLAGS FS_IOC_SETFLAGS
+-#define EXT4_IOC_GETVERSION _IOR('f', 3, long)
+-#define EXT4_IOC_SETVERSION _IOW('f', 4, long)
+-#define EXT4_IOC_GROUP_EXTEND _IOW('f', 7, unsigned long)
+-#define EXT4_IOC_GROUP_ADD _IOW('f', 8,struct ext4_new_group_input)
+-#define EXT4_IOC_GETVERSION_OLD FS_IOC_GETVERSION
+-#define EXT4_IOC_SETVERSION_OLD FS_IOC_SETVERSION
+-#ifdef CONFIG_JBD2_DEBUG
+-#define EXT4_IOC_WAIT_FOR_READONLY _IOR('f', 99, long)
+-#endif
+-#define EXT4_IOC_GETRSVSZ _IOR('f', 5, long)
+-#define EXT4_IOC_SETRSVSZ _IOW('f', 6, long)
+-#define EXT4_IOC_MIGRATE _IO('f', 7)
+-
+-/*
+- * ioctl commands in 32 bit emulation
+- */
+-#define EXT4_IOC32_GETFLAGS FS_IOC32_GETFLAGS
+-#define EXT4_IOC32_SETFLAGS FS_IOC32_SETFLAGS
+-#define EXT4_IOC32_GETVERSION _IOR('f', 3, int)
+-#define EXT4_IOC32_SETVERSION _IOW('f', 4, int)
+-#define EXT4_IOC32_GETRSVSZ _IOR('f', 5, int)
+-#define EXT4_IOC32_SETRSVSZ _IOW('f', 6, int)
+-#define EXT4_IOC32_GROUP_EXTEND _IOW('f', 7, unsigned int)
+-#ifdef CONFIG_JBD2_DEBUG
+-#define EXT4_IOC32_WAIT_FOR_READONLY _IOR('f', 99, int)
+-#endif
+-#define EXT4_IOC32_GETVERSION_OLD FS_IOC32_GETVERSION
+-#define EXT4_IOC32_SETVERSION_OLD FS_IOC32_SETVERSION
+-
+-
+-/*
+- * Mount options
+- */
+-struct ext4_mount_options {
+- unsigned long s_mount_opt;
+- uid_t s_resuid;
+- gid_t s_resgid;
+- unsigned long s_commit_interval;
+-#ifdef CONFIG_QUOTA
+- int s_jquota_fmt;
+- char *s_qf_names[MAXQUOTAS];
+-#endif
+-};
+-
+-/*
+- * Structure of an inode on the disk
+- */
+-struct ext4_inode {
+- __le16 i_mode; /* File mode */
+- __le16 i_uid; /* Low 16 bits of Owner Uid */
+- __le32 i_size_lo; /* Size in bytes */
+- __le32 i_atime; /* Access time */
+- __le32 i_ctime; /* Inode Change time */
+- __le32 i_mtime; /* Modification time */
+- __le32 i_dtime; /* Deletion Time */
+- __le16 i_gid; /* Low 16 bits of Group Id */
+- __le16 i_links_count; /* Links count */
+- __le32 i_blocks_lo; /* Blocks count */
+- __le32 i_flags; /* File flags */
+- union {
+- struct {
+- __le32 l_i_version;
+- } linux1;
+- struct {
+- __u32 h_i_translator;
+- } hurd1;
+- struct {
+- __u32 m_i_reserved1;
+- } masix1;
+- } osd1; /* OS dependent 1 */
+- __le32 i_block[EXT4_N_BLOCKS];/* Pointers to blocks */
+- __le32 i_generation; /* File version (for NFS) */
+- __le32 i_file_acl_lo; /* File ACL */
+- __le32 i_size_high;
+- __le32 i_obso_faddr; /* Obsoleted fragment address */
+- union {
+- struct {
+- __le16 l_i_blocks_high; /* were l_i_reserved1 */
+- __le16 l_i_file_acl_high;
+- __le16 l_i_uid_high; /* these 2 fields */
+- __le16 l_i_gid_high; /* were reserved2[0] */
+- __u32 l_i_reserved2;
+- } linux2;
+- struct {
+- __le16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
+- __u16 h_i_mode_high;
+- __u16 h_i_uid_high;
+- __u16 h_i_gid_high;
+- __u32 h_i_author;
+- } hurd2;
+- struct {
+- __le16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
+- __le16 m_i_file_acl_high;
+- __u32 m_i_reserved2[2];
+- } masix2;
+- } osd2; /* OS dependent 2 */
+- __le16 i_extra_isize;
+- __le16 i_pad1;
+- __le32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */
+- __le32 i_mtime_extra; /* extra Modification time(nsec << 2 | epoch) */
+- __le32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */
+- __le32 i_crtime; /* File Creation time */
+- __le32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */
+- __le32 i_version_hi; /* high 32 bits for 64-bit version */
+-};
+-
+-
+-#define EXT4_EPOCH_BITS 2
+-#define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
+-#define EXT4_NSEC_MASK (~0UL << EXT4_EPOCH_BITS)
+-
+-/*
+- * Extended fields will fit into an inode if the filesystem was formatted
+- * with large inodes (-I 256 or larger) and there are not currently any EAs
+- * consuming all of the available space. For new inodes we always reserve
+- * enough space for the kernel's known extended fields, but for inodes
+- * created with an old kernel this might not have been the case. None of
+- * the extended inode fields is critical for correct filesystem operation.
+- * This macro checks if a certain field fits in the inode. Note that
+- * inode-size = GOOD_OLD_INODE_SIZE + i_extra_isize
+- */
+-#define EXT4_FITS_IN_INODE(ext4_inode, einode, field) \
+- ((offsetof(typeof(*ext4_inode), field) + \
+- sizeof((ext4_inode)->field)) \
+- <= (EXT4_GOOD_OLD_INODE_SIZE + \
+- (einode)->i_extra_isize)) \
+-
+-static inline __le32 ext4_encode_extra_time(struct timespec *time)
+-{
+- return cpu_to_le32((sizeof(time->tv_sec) > 4 ?
+- time->tv_sec >> 32 : 0) |
+- ((time->tv_nsec << 2) & EXT4_NSEC_MASK));
+-}
+-
+-static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
+-{
+- if (sizeof(time->tv_sec) > 4)
+- time->tv_sec |= (__u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK)
+- << 32;
+- time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> 2;
+-}
+-
+-#define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \
+-do { \
+- (raw_inode)->xtime = cpu_to_le32((inode)->xtime.tv_sec); \
+- if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) \
+- (raw_inode)->xtime ## _extra = \
+- ext4_encode_extra_time(&(inode)->xtime); \
+-} while (0)
+-
+-#define EXT4_EINODE_SET_XTIME(xtime, einode, raw_inode) \
+-do { \
+- if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \
+- (raw_inode)->xtime = cpu_to_le32((einode)->xtime.tv_sec); \
+- if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra)) \
+- (raw_inode)->xtime ## _extra = \
+- ext4_encode_extra_time(&(einode)->xtime); \
+-} while (0)
+-
+-#define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode) \
+-do { \
+- (inode)->xtime.tv_sec = (signed)le32_to_cpu((raw_inode)->xtime); \
+- if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) \
+- ext4_decode_extra_time(&(inode)->xtime, \
+- raw_inode->xtime ## _extra); \
+-} while (0)
+-
+-#define EXT4_EINODE_GET_XTIME(xtime, einode, raw_inode) \
+-do { \
+- if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \
+- (einode)->xtime.tv_sec = \
+- (signed)le32_to_cpu((raw_inode)->xtime); \
+- if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra)) \
+- ext4_decode_extra_time(&(einode)->xtime, \
+- raw_inode->xtime ## _extra); \
+-} while (0)
+-
+-#define i_disk_version osd1.linux1.l_i_version
+-
+-#if defined(__KERNEL__) || defined(__linux__)
+-#define i_reserved1 osd1.linux1.l_i_reserved1
+-#define i_file_acl_high osd2.linux2.l_i_file_acl_high
+-#define i_blocks_high osd2.linux2.l_i_blocks_high
+-#define i_uid_low i_uid
+-#define i_gid_low i_gid
+-#define i_uid_high osd2.linux2.l_i_uid_high
+-#define i_gid_high osd2.linux2.l_i_gid_high
+-#define i_reserved2 osd2.linux2.l_i_reserved2
+-
+-#elif defined(__GNU__)
+-
+-#define i_translator osd1.hurd1.h_i_translator
+-#define i_uid_high osd2.hurd2.h_i_uid_high
+-#define i_gid_high osd2.hurd2.h_i_gid_high
+-#define i_author osd2.hurd2.h_i_author
+-
+-#elif defined(__masix__)
+-
+-#define i_reserved1 osd1.masix1.m_i_reserved1
+-#define i_file_acl_high osd2.masix2.m_i_file_acl_high
+-#define i_reserved2 osd2.masix2.m_i_reserved2
+-
+-#endif /* defined(__KERNEL__) || defined(__linux__) */
+-
+-/*
+- * File system states
+- */
+-#define EXT4_VALID_FS 0x0001 /* Unmounted cleanly */
+-#define EXT4_ERROR_FS 0x0002 /* Errors detected */
+-#define EXT4_ORPHAN_FS 0x0004 /* Orphans being recovered */
+-
+-/*
+- * Misc. filesystem flags
+- */
+-#define EXT2_FLAGS_SIGNED_HASH 0x0001 /* Signed dirhash in use */
+-#define EXT2_FLAGS_UNSIGNED_HASH 0x0002 /* Unsigned dirhash in use */
+-#define EXT2_FLAGS_TEST_FILESYS 0x0004 /* to test development code */
+-
+-/*
+- * Mount flags
+- */
+-#define EXT4_MOUNT_CHECK 0x00001 /* Do mount-time checks */
+-#define EXT4_MOUNT_OLDALLOC 0x00002 /* Don't use the new Orlov allocator */
+-#define EXT4_MOUNT_GRPID 0x00004 /* Create files with directory's group */
+-#define EXT4_MOUNT_DEBUG 0x00008 /* Some debugging messages */
+-#define EXT4_MOUNT_ERRORS_CONT 0x00010 /* Continue on errors */
+-#define EXT4_MOUNT_ERRORS_RO 0x00020 /* Remount fs ro on errors */
+-#define EXT4_MOUNT_ERRORS_PANIC 0x00040 /* Panic on errors */
+-#define EXT4_MOUNT_MINIX_DF 0x00080 /* Mimics the Minix statfs */
+-#define EXT4_MOUNT_NOLOAD 0x00100 /* Don't use existing journal*/
+-#define EXT4_MOUNT_ABORT 0x00200 /* Fatal error detected */
+-#define EXT4_MOUNT_DATA_FLAGS 0x00C00 /* Mode for data writes: */
+-#define EXT4_MOUNT_JOURNAL_DATA 0x00400 /* Write data to journal */
+-#define EXT4_MOUNT_ORDERED_DATA 0x00800 /* Flush data before commit */
+-#define EXT4_MOUNT_WRITEBACK_DATA 0x00C00 /* No data ordering */
+-#define EXT4_MOUNT_UPDATE_JOURNAL 0x01000 /* Update the journal format */
+-#define EXT4_MOUNT_NO_UID32 0x02000 /* Disable 32-bit UIDs */
+-#define EXT4_MOUNT_XATTR_USER 0x04000 /* Extended user attributes */
+-#define EXT4_MOUNT_POSIX_ACL 0x08000 /* POSIX Access Control Lists */
+-#define EXT4_MOUNT_RESERVATION 0x10000 /* Preallocation */
+-#define EXT4_MOUNT_BARRIER 0x20000 /* Use block barriers */
+-#define EXT4_MOUNT_NOBH 0x40000 /* No bufferheads */
+-#define EXT4_MOUNT_QUOTA 0x80000 /* Some quota option set */
+-#define EXT4_MOUNT_USRQUOTA 0x100000 /* "old" user quota */
+-#define EXT4_MOUNT_GRPQUOTA 0x200000 /* "old" group quota */
+-#define EXT4_MOUNT_EXTENTS 0x400000 /* Extents support */
+-#define EXT4_MOUNT_JOURNAL_CHECKSUM 0x800000 /* Journal checksums */
+-#define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */
+-#define EXT4_MOUNT_I_VERSION 0x2000000 /* i_version support */
+-#define EXT4_MOUNT_MBALLOC 0x4000000 /* Buddy allocation support */
+-/* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */
+-#ifndef _LINUX_EXT2_FS_H
+-#define clear_opt(o, opt) o &= ~EXT4_MOUNT_##opt
+-#define set_opt(o, opt) o |= EXT4_MOUNT_##opt
+-#define test_opt(sb, opt) (EXT4_SB(sb)->s_mount_opt & \
+- EXT4_MOUNT_##opt)
+-#else
+-#define EXT2_MOUNT_NOLOAD EXT4_MOUNT_NOLOAD
+-#define EXT2_MOUNT_ABORT EXT4_MOUNT_ABORT
+-#define EXT2_MOUNT_DATA_FLAGS EXT4_MOUNT_DATA_FLAGS
+-#endif
+-
+-#define ext4_set_bit ext2_set_bit
+-#define ext4_set_bit_atomic ext2_set_bit_atomic
+-#define ext4_clear_bit ext2_clear_bit
+-#define ext4_clear_bit_atomic ext2_clear_bit_atomic
+-#define ext4_test_bit ext2_test_bit
+-#define ext4_find_first_zero_bit ext2_find_first_zero_bit
+-#define ext4_find_next_zero_bit ext2_find_next_zero_bit
+-#define ext4_find_next_bit ext2_find_next_bit
+-
+-/*
+- * Maximal mount counts between two filesystem checks
+- */
+-#define EXT4_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
+-#define EXT4_DFL_CHECKINTERVAL 0 /* Don't use interval check */
+-
+-/*
+- * Behaviour when detecting errors
+- */
+-#define EXT4_ERRORS_CONTINUE 1 /* Continue execution */
+-#define EXT4_ERRORS_RO 2 /* Remount fs read-only */
+-#define EXT4_ERRORS_PANIC 3 /* Panic */
+-#define EXT4_ERRORS_DEFAULT EXT4_ERRORS_CONTINUE
+-
+-/*
+- * Structure of the super block
+- */
+-struct ext4_super_block {
+-/*00*/ __le32 s_inodes_count; /* Inodes count */
+- __le32 s_blocks_count_lo; /* Blocks count */
+- __le32 s_r_blocks_count_lo; /* Reserved blocks count */
+- __le32 s_free_blocks_count_lo; /* Free blocks count */
+-/*10*/ __le32 s_free_inodes_count; /* Free inodes count */
+- __le32 s_first_data_block; /* First Data Block */
+- __le32 s_log_block_size; /* Block size */
+- __le32 s_obso_log_frag_size; /* Obsoleted fragment size */
+-/*20*/ __le32 s_blocks_per_group; /* # Blocks per group */
+- __le32 s_obso_frags_per_group; /* Obsoleted fragments per group */
+- __le32 s_inodes_per_group; /* # Inodes per group */
+- __le32 s_mtime; /* Mount time */
+-/*30*/ __le32 s_wtime; /* Write time */
+- __le16 s_mnt_count; /* Mount count */
+- __le16 s_max_mnt_count; /* Maximal mount count */
+- __le16 s_magic; /* Magic signature */
+- __le16 s_state; /* File system state */
+- __le16 s_errors; /* Behaviour when detecting errors */
+- __le16 s_minor_rev_level; /* minor revision level */
+-/*40*/ __le32 s_lastcheck; /* time of last check */
+- __le32 s_checkinterval; /* max. time between checks */
+- __le32 s_creator_os; /* OS */
+- __le32 s_rev_level; /* Revision level */
+-/*50*/ __le16 s_def_resuid; /* Default uid for reserved blocks */
+- __le16 s_def_resgid; /* Default gid for reserved blocks */
+- /*
+- * These fields are for EXT4_DYNAMIC_REV superblocks only.
+- *
+- * Note: the difference between the compatible feature set and
+- * the incompatible feature set is that if there is a bit set
+- * in the incompatible feature set that the kernel doesn't
+- * know about, it should refuse to mount the filesystem.
+- *
+- * e2fsck's requirements are more strict; if it doesn't know
+- * about a feature in either the compatible or incompatible
+- * feature set, it must abort and not try to meddle with
+- * things it doesn't understand...
+- */
+- __le32 s_first_ino; /* First non-reserved inode */
+- __le16 s_inode_size; /* size of inode structure */
+- __le16 s_block_group_nr; /* block group # of this superblock */
+- __le32 s_feature_compat; /* compatible feature set */
+-/*60*/ __le32 s_feature_incompat; /* incompatible feature set */
+- __le32 s_feature_ro_compat; /* readonly-compatible feature set */
+-/*68*/ __u8 s_uuid[16]; /* 128-bit uuid for volume */
+-/*78*/ char s_volume_name[16]; /* volume name */
+-/*88*/ char s_last_mounted[64]; /* directory where last mounted */
+-/*C8*/ __le32 s_algorithm_usage_bitmap; /* For compression */
+- /*
+- * Performance hints. Directory preallocation should only
+- * happen if the EXT4_FEATURE_COMPAT_DIR_PREALLOC flag is on.
+- */
+- __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
+- __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
+- __le16 s_reserved_gdt_blocks; /* Per group desc for online growth */
+- /*
+- * Journaling support valid if EXT4_FEATURE_COMPAT_HAS_JOURNAL set.
+- */
+-/*D0*/ __u8 s_journal_uuid[16]; /* uuid of journal superblock */
+-/*E0*/ __le32 s_journal_inum; /* inode number of journal file */
+- __le32 s_journal_dev; /* device number of journal file */
+- __le32 s_last_orphan; /* start of list of inodes to delete */
+- __le32 s_hash_seed[4]; /* HTREE hash seed */
+- __u8 s_def_hash_version; /* Default hash version to use */
+- __u8 s_reserved_char_pad;
+- __le16 s_desc_size; /* size of group descriptor */
+-/*100*/ __le32 s_default_mount_opts;
+- __le32 s_first_meta_bg; /* First metablock block group */
+- __le32 s_mkfs_time; /* When the filesystem was created */
+- __le32 s_jnl_blocks[17]; /* Backup of the journal inode */
+- /* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */
+-/*150*/ __le32 s_blocks_count_hi; /* Blocks count */
+- __le32 s_r_blocks_count_hi; /* Reserved blocks count */
+- __le32 s_free_blocks_count_hi; /* Free blocks count */
+- __le16 s_min_extra_isize; /* All inodes have at least # bytes */
+- __le16 s_want_extra_isize; /* New inodes should reserve # bytes */
+- __le32 s_flags; /* Miscellaneous flags */
+- __le16 s_raid_stride; /* RAID stride */
+- __le16 s_mmp_interval; /* # seconds to wait in MMP checking */
+- __le64 s_mmp_block; /* Block for multi-mount protection */
+- __le32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/
+- __u32 s_reserved[163]; /* Padding to the end of the block */
+-};
+-
+-#ifdef __KERNEL__
+-static inline struct ext4_sb_info * EXT4_SB(struct super_block *sb)
+-{
+- return sb->s_fs_info;
+-}
+-static inline struct ext4_inode_info *EXT4_I(struct inode *inode)
+-{
+- return container_of(inode, struct ext4_inode_info, vfs_inode);
+-}
+-
+-static inline struct timespec ext4_current_time(struct inode *inode)
+-{
+- return (inode->i_sb->s_time_gran < NSEC_PER_SEC) ?
+- current_fs_time(inode->i_sb) : CURRENT_TIME_SEC;
+-}
+-
+-
+-static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
+-{
+- return ino == EXT4_ROOT_INO ||
+- ino == EXT4_JOURNAL_INO ||
+- ino == EXT4_RESIZE_INO ||
+- (ino >= EXT4_FIRST_INO(sb) &&
+- ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
+-}
+-#else
+-/* Assume that user mode programs are passing in an ext4fs superblock, not
+- * a kernel struct super_block. This will allow us to call the feature-test
+- * macros from user land. */
+-#define EXT4_SB(sb) (sb)
+-#endif
+-
+-#define NEXT_ORPHAN(inode) EXT4_I(inode)->i_dtime
+-
+-/*
+- * Codes for operating systems
+- */
+-#define EXT4_OS_LINUX 0
+-#define EXT4_OS_HURD 1
+-#define EXT4_OS_MASIX 2
+-#define EXT4_OS_FREEBSD 3
+-#define EXT4_OS_LITES 4
+-
+-/*
+- * Revision levels
+- */
+-#define EXT4_GOOD_OLD_REV 0 /* The good old (original) format */
+-#define EXT4_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
+-
+-#define EXT4_CURRENT_REV EXT4_GOOD_OLD_REV
+-#define EXT4_MAX_SUPP_REV EXT4_DYNAMIC_REV
+-
+-#define EXT4_GOOD_OLD_INODE_SIZE 128
+-
+-/*
+- * Feature set definitions
+- */
+-
+-#define EXT4_HAS_COMPAT_FEATURE(sb,mask) \
+- ( EXT4_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask) )
+-#define EXT4_HAS_RO_COMPAT_FEATURE(sb,mask) \
+- ( EXT4_SB(sb)->s_es->s_feature_ro_compat & cpu_to_le32(mask) )
+-#define EXT4_HAS_INCOMPAT_FEATURE(sb,mask) \
+- ( EXT4_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask) )
+-#define EXT4_SET_COMPAT_FEATURE(sb,mask) \
+- EXT4_SB(sb)->s_es->s_feature_compat |= cpu_to_le32(mask)
+-#define EXT4_SET_RO_COMPAT_FEATURE(sb,mask) \
+- EXT4_SB(sb)->s_es->s_feature_ro_compat |= cpu_to_le32(mask)
+-#define EXT4_SET_INCOMPAT_FEATURE(sb,mask) \
+- EXT4_SB(sb)->s_es->s_feature_incompat |= cpu_to_le32(mask)
+-#define EXT4_CLEAR_COMPAT_FEATURE(sb,mask) \
+- EXT4_SB(sb)->s_es->s_feature_compat &= ~cpu_to_le32(mask)
+-#define EXT4_CLEAR_RO_COMPAT_FEATURE(sb,mask) \
+- EXT4_SB(sb)->s_es->s_feature_ro_compat &= ~cpu_to_le32(mask)
+-#define EXT4_CLEAR_INCOMPAT_FEATURE(sb,mask) \
+- EXT4_SB(sb)->s_es->s_feature_incompat &= ~cpu_to_le32(mask)
+-
+-#define EXT4_FEATURE_COMPAT_DIR_PREALLOC 0x0001
+-#define EXT4_FEATURE_COMPAT_IMAGIC_INODES 0x0002
+-#define EXT4_FEATURE_COMPAT_HAS_JOURNAL 0x0004
+-#define EXT4_FEATURE_COMPAT_EXT_ATTR 0x0008
+-#define EXT4_FEATURE_COMPAT_RESIZE_INODE 0x0010
+-#define EXT4_FEATURE_COMPAT_DIR_INDEX 0x0020
+-
+-#define EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
+-#define EXT4_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
+-#define EXT4_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
+-#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008
+-#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
+-#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020
+-#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
+-
+-#define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001
+-#define EXT4_FEATURE_INCOMPAT_FILETYPE 0x0002
+-#define EXT4_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
+-#define EXT4_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
+-#define EXT4_FEATURE_INCOMPAT_META_BG 0x0010
+-#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
+-#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
+-#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
+-#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
+-
+-#define EXT4_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
+-#define EXT4_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \
+- EXT4_FEATURE_INCOMPAT_RECOVER| \
+- EXT4_FEATURE_INCOMPAT_META_BG| \
+- EXT4_FEATURE_INCOMPAT_EXTENTS| \
+- EXT4_FEATURE_INCOMPAT_64BIT| \
+- EXT4_FEATURE_INCOMPAT_FLEX_BG)
+-#define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+- EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
+- EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \
+- EXT4_FEATURE_RO_COMPAT_DIR_NLINK | \
+- EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE | \
+- EXT4_FEATURE_RO_COMPAT_BTREE_DIR |\
+- EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
+-
+-/*
+- * Default values for user and/or group using reserved blocks
+- */
+-#define EXT4_DEF_RESUID 0
+-#define EXT4_DEF_RESGID 0
+-
+-/*
+- * Default mount options
+- */
+-#define EXT4_DEFM_DEBUG 0x0001
+-#define EXT4_DEFM_BSDGROUPS 0x0002
+-#define EXT4_DEFM_XATTR_USER 0x0004
+-#define EXT4_DEFM_ACL 0x0008
+-#define EXT4_DEFM_UID16 0x0010
+-#define EXT4_DEFM_JMODE 0x0060
+-#define EXT4_DEFM_JMODE_DATA 0x0020
+-#define EXT4_DEFM_JMODE_ORDERED 0x0040
+-#define EXT4_DEFM_JMODE_WBACK 0x0060
+-
+-/*
+- * Structure of a directory entry
+- */
+-#define EXT4_NAME_LEN 255
+-
+-struct ext4_dir_entry {
+- __le32 inode; /* Inode number */
+- __le16 rec_len; /* Directory entry length */
+- __le16 name_len; /* Name length */
+- char name[EXT4_NAME_LEN]; /* File name */
+-};
+-
+-/*
+- * The new version of the directory entry. Since EXT4 structures are
+- * stored in intel byte order, and the name_len field could never be
+- * bigger than 255 chars, it's safe to reclaim the extra byte for the
+- * file_type field.
+- */
+-struct ext4_dir_entry_2 {
+- __le32 inode; /* Inode number */
+- __le16 rec_len; /* Directory entry length */
+- __u8 name_len; /* Name length */
+- __u8 file_type;
+- char name[EXT4_NAME_LEN]; /* File name */
+-};
+-
+-/*
+- * Ext4 directory file types. Only the low 3 bits are used. The
+- * other bits are reserved for now.
+- */
+-#define EXT4_FT_UNKNOWN 0
+-#define EXT4_FT_REG_FILE 1
+-#define EXT4_FT_DIR 2
+-#define EXT4_FT_CHRDEV 3
+-#define EXT4_FT_BLKDEV 4
+-#define EXT4_FT_FIFO 5
+-#define EXT4_FT_SOCK 6
+-#define EXT4_FT_SYMLINK 7
+-
+-#define EXT4_FT_MAX 8
+-
+-/*
+- * EXT4_DIR_PAD defines the directory entries boundaries
+- *
+- * NOTE: It must be a multiple of 4
+- */
+-#define EXT4_DIR_PAD 4
+-#define EXT4_DIR_ROUND (EXT4_DIR_PAD - 1)
+-#define EXT4_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT4_DIR_ROUND) & \
+- ~EXT4_DIR_ROUND)
+-#define EXT4_MAX_REC_LEN ((1<<16)-1)
+-
+-static inline unsigned ext4_rec_len_from_disk(__le16 dlen)
+-{
+- unsigned len = le16_to_cpu(dlen);
+-
+- if (len == EXT4_MAX_REC_LEN)
+- return 1 << 16;
+- return len;
+-}
+-
+-static inline __le16 ext4_rec_len_to_disk(unsigned len)
+-{
+- if (len == (1 << 16))
+- return cpu_to_le16(EXT4_MAX_REC_LEN);
+- else if (len > (1 << 16))
+- BUG();
+- return cpu_to_le16(len);
+-}
+-
+-/*
+- * Hash Tree Directory indexing
+- * (c) Daniel Phillips, 2001
+- */
+-
+-#define is_dx(dir) (EXT4_HAS_COMPAT_FEATURE(dir->i_sb, \
+- EXT4_FEATURE_COMPAT_DIR_INDEX) && \
+- (EXT4_I(dir)->i_flags & EXT4_INDEX_FL))
+-#define EXT4_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT4_LINK_MAX)
+-#define EXT4_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1)
+-
+-/* Legal values for the dx_root hash_version field: */
+-
+-#define DX_HASH_LEGACY 0
+-#define DX_HASH_HALF_MD4 1
+-#define DX_HASH_TEA 2
+-
+-#ifdef __KERNEL__
+-
+-/* hash info structure used by the directory hash */
+-struct dx_hash_info
+-{
+- u32 hash;
+- u32 minor_hash;
+- int hash_version;
+- u32 *seed;
+-};
+-
+-#define EXT4_HTREE_EOF 0x7fffffff
+-
+-/*
+- * Control parameters used by ext4_htree_next_block
+- */
+-#define HASH_NB_ALWAYS 1
+-
+-
+-/*
+- * Describe an inode's exact location on disk and in memory
+- */
+-struct ext4_iloc
+-{
+- struct buffer_head *bh;
+- unsigned long offset;
+- ext4_group_t block_group;
+-};
+-
+-static inline struct ext4_inode *ext4_raw_inode(struct ext4_iloc *iloc)
+-{
+- return (struct ext4_inode *) (iloc->bh->b_data + iloc->offset);
+-}
+-
+-/*
+- * This structure is stuffed into the struct file's private_data field
+- * for directories. It is where we put information so that we can do
+- * readdir operations in hash tree order.
+- */
+-struct dir_private_info {
+- struct rb_root root;
+- struct rb_node *curr_node;
+- struct fname *extra_fname;
+- loff_t last_pos;
+- __u32 curr_hash;
+- __u32 curr_minor_hash;
+- __u32 next_hash;
+-};
+-
+-/* calculate the first block number of the group */
+-static inline ext4_fsblk_t
+-ext4_group_first_block_no(struct super_block *sb, ext4_group_t group_no)
+-{
+- return group_no * (ext4_fsblk_t)EXT4_BLOCKS_PER_GROUP(sb) +
+- le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
+-}
+-
+-/*
+- * Special error return code only used by dx_probe() and its callers.
+- */
+-#define ERR_BAD_DX_DIR -75000
+-
+-void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
+- unsigned long *blockgrpp, ext4_grpblk_t *offsetp);
+-
+-/*
+- * Function prototypes
+- */
+-
+-/*
+- * Ok, these declarations are also in <linux/kernel.h> but none of the
+- * ext4 source programs needs to include it so they are duplicated here.
+- */
+-# define NORET_TYPE /**/
+-# define ATTRIB_NORET __attribute__((noreturn))
+-# define NORET_AND noreturn,
+-
+-/* balloc.c */
+-extern unsigned int ext4_block_group(struct super_block *sb,
+- ext4_fsblk_t blocknr);
+-extern ext4_grpblk_t ext4_block_group_offset(struct super_block *sb,
+- ext4_fsblk_t blocknr);
+-extern int ext4_bg_has_super(struct super_block *sb, ext4_group_t group);
+-extern unsigned long ext4_bg_num_gdb(struct super_block *sb,
+- ext4_group_t group);
+-extern ext4_fsblk_t ext4_new_block (handle_t *handle, struct inode *inode,
+- ext4_fsblk_t goal, int *errp);
+-extern ext4_fsblk_t ext4_new_blocks (handle_t *handle, struct inode *inode,
+- ext4_fsblk_t goal, unsigned long *count, int *errp);
+-extern ext4_fsblk_t ext4_new_blocks_old(handle_t *handle, struct inode *inode,
+- ext4_fsblk_t goal, unsigned long *count, int *errp);
+-extern void ext4_free_blocks (handle_t *handle, struct inode *inode,
+- ext4_fsblk_t block, unsigned long count, int metadata);
+-extern void ext4_free_blocks_sb (handle_t *handle, struct super_block *sb,
+- ext4_fsblk_t block, unsigned long count,
+- unsigned long *pdquot_freed_blocks);
+-extern ext4_fsblk_t ext4_count_free_blocks (struct super_block *);
+-extern void ext4_check_blocks_bitmap (struct super_block *);
+-extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
+- ext4_group_t block_group,
+- struct buffer_head ** bh);
+-extern int ext4_should_retry_alloc(struct super_block *sb, int *retries);
+-extern void ext4_init_block_alloc_info(struct inode *);
+-extern void ext4_rsv_window_add(struct super_block *sb, struct ext4_reserve_window_node *rsv);
+-
+-/* dir.c */
+-extern int ext4_check_dir_entry(const char *, struct inode *,
+- struct ext4_dir_entry_2 *,
+- struct buffer_head *, unsigned long);
+-extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
+- __u32 minor_hash,
+- struct ext4_dir_entry_2 *dirent);
+-extern void ext4_htree_free_dir_info(struct dir_private_info *p);
+-
+-/* fsync.c */
+-extern int ext4_sync_file (struct file *, struct dentry *, int);
+-
+-/* hash.c */
+-extern int ext4fs_dirhash(const char *name, int len, struct
+- dx_hash_info *hinfo);
+-
+-/* ialloc.c */
+-extern struct inode * ext4_new_inode (handle_t *, struct inode *, int);
+-extern void ext4_free_inode (handle_t *, struct inode *);
+-extern struct inode * ext4_orphan_get (struct super_block *, unsigned long);
+-extern unsigned long ext4_count_free_inodes (struct super_block *);
+-extern unsigned long ext4_count_dirs (struct super_block *);
+-extern void ext4_check_inodes_bitmap (struct super_block *);
+-extern unsigned long ext4_count_free (struct buffer_head *, unsigned);
+-
+-/* mballoc.c */
+-extern long ext4_mb_stats;
+-extern long ext4_mb_max_to_scan;
+-extern int ext4_mb_init(struct super_block *, int);
+-extern int ext4_mb_release(struct super_block *);
+-extern ext4_fsblk_t ext4_mb_new_blocks(handle_t *,
+- struct ext4_allocation_request *, int *);
+-extern int ext4_mb_reserve_blocks(struct super_block *, int);
+-extern void ext4_mb_discard_inode_preallocations(struct inode *);
+-extern int __init init_ext4_mballoc(void);
+-extern void exit_ext4_mballoc(void);
+-extern void ext4_mb_free_blocks(handle_t *, struct inode *,
+- unsigned long, unsigned long, int, unsigned long *);
+-
+-
+-/* inode.c */
+-int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
+- struct buffer_head *bh, ext4_fsblk_t blocknr);
+-struct buffer_head *ext4_getblk(handle_t *, struct inode *,
+- ext4_lblk_t, int, int *);
+-struct buffer_head *ext4_bread(handle_t *, struct inode *,
+- ext4_lblk_t, int, int *);
+-int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
+- ext4_lblk_t iblock, unsigned long maxblocks,
+- struct buffer_head *bh_result,
+- int create, int extend_disksize);
+-
+-extern struct inode *ext4_iget(struct super_block *, unsigned long);
+-extern int ext4_write_inode (struct inode *, int);
+-extern int ext4_setattr (struct dentry *, struct iattr *);
+-extern void ext4_delete_inode (struct inode *);
+-extern int ext4_sync_inode (handle_t *, struct inode *);
+-extern void ext4_discard_reservation (struct inode *);
+-extern void ext4_dirty_inode(struct inode *);
+-extern int ext4_change_inode_journal_flag(struct inode *, int);
+-extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *);
+-extern void ext4_truncate (struct inode *);
+-extern void ext4_set_inode_flags(struct inode *);
+-extern void ext4_get_inode_flags(struct ext4_inode_info *);
+-extern void ext4_set_aops(struct inode *inode);
+-extern int ext4_writepage_trans_blocks(struct inode *);
+-extern int ext4_block_truncate_page(handle_t *handle, struct page *page,
+- struct address_space *mapping, loff_t from);
+-
+-/* ioctl.c */
+-extern int ext4_ioctl (struct inode *, struct file *, unsigned int,
+- unsigned long);
+-extern long ext4_compat_ioctl (struct file *, unsigned int, unsigned long);
+-
+-/* migrate.c */
+-extern int ext4_ext_migrate(struct inode *, struct file *, unsigned int,
+- unsigned long);
+-/* namei.c */
+-extern int ext4_orphan_add(handle_t *, struct inode *);
+-extern int ext4_orphan_del(handle_t *, struct inode *);
+-extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+- __u32 start_minor_hash, __u32 *next_hash);
+-
+-/* resize.c */
+-extern int ext4_group_add(struct super_block *sb,
+- struct ext4_new_group_data *input);
+-extern int ext4_group_extend(struct super_block *sb,
+- struct ext4_super_block *es,
+- ext4_fsblk_t n_blocks_count);
+-
+-/* super.c */
+-extern void ext4_error (struct super_block *, const char *, const char *, ...)
+- __attribute__ ((format (printf, 3, 4)));
+-extern void __ext4_std_error (struct super_block *, const char *, int);
+-extern void ext4_abort (struct super_block *, const char *, const char *, ...)
+- __attribute__ ((format (printf, 3, 4)));
+-extern void ext4_warning (struct super_block *, const char *, const char *, ...)
+- __attribute__ ((format (printf, 3, 4)));
+-extern void ext4_update_dynamic_rev (struct super_block *sb);
+-extern int ext4_update_compat_feature(handle_t *handle, struct super_block *sb,
+- __u32 compat);
+-extern int ext4_update_rocompat_feature(handle_t *handle,
+- struct super_block *sb, __u32 rocompat);
+-extern int ext4_update_incompat_feature(handle_t *handle,
+- struct super_block *sb, __u32 incompat);
+-extern ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
+- struct ext4_group_desc *bg);
+-extern ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
+- struct ext4_group_desc *bg);
+-extern ext4_fsblk_t ext4_inode_table(struct super_block *sb,
+- struct ext4_group_desc *bg);
+-extern void ext4_block_bitmap_set(struct super_block *sb,
+- struct ext4_group_desc *bg, ext4_fsblk_t blk);
+-extern void ext4_inode_bitmap_set(struct super_block *sb,
+- struct ext4_group_desc *bg, ext4_fsblk_t blk);
+-extern void ext4_inode_table_set(struct super_block *sb,
+- struct ext4_group_desc *bg, ext4_fsblk_t blk);
+-
+-static inline ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
+-{
+- return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) |
+- le32_to_cpu(es->s_blocks_count_lo);
+-}
+-
+-static inline ext4_fsblk_t ext4_r_blocks_count(struct ext4_super_block *es)
+-{
+- return ((ext4_fsblk_t)le32_to_cpu(es->s_r_blocks_count_hi) << 32) |
+- le32_to_cpu(es->s_r_blocks_count_lo);
+-}
+-
+-static inline ext4_fsblk_t ext4_free_blocks_count(struct ext4_super_block *es)
+-{
+- return ((ext4_fsblk_t)le32_to_cpu(es->s_free_blocks_count_hi) << 32) |
+- le32_to_cpu(es->s_free_blocks_count_lo);
+-}
+-
+-static inline void ext4_blocks_count_set(struct ext4_super_block *es,
+- ext4_fsblk_t blk)
+-{
+- es->s_blocks_count_lo = cpu_to_le32((u32)blk);
+- es->s_blocks_count_hi = cpu_to_le32(blk >> 32);
+-}
+-
+-static inline void ext4_free_blocks_count_set(struct ext4_super_block *es,
+- ext4_fsblk_t blk)
+-{
+- es->s_free_blocks_count_lo = cpu_to_le32((u32)blk);
+- es->s_free_blocks_count_hi = cpu_to_le32(blk >> 32);
+-}
+-
+-static inline void ext4_r_blocks_count_set(struct ext4_super_block *es,
+- ext4_fsblk_t blk)
+-{
+- es->s_r_blocks_count_lo = cpu_to_le32((u32)blk);
+- es->s_r_blocks_count_hi = cpu_to_le32(blk >> 32);
+-}
+-
+-static inline loff_t ext4_isize(struct ext4_inode *raw_inode)
+-{
+- return ((loff_t)le32_to_cpu(raw_inode->i_size_high) << 32) |
+- le32_to_cpu(raw_inode->i_size_lo);
+-}
+-
+-static inline void ext4_isize_set(struct ext4_inode *raw_inode, loff_t i_size)
+-{
+- raw_inode->i_size_lo = cpu_to_le32(i_size);
+- raw_inode->i_size_high = cpu_to_le32(i_size >> 32);
+-}
+-
+-static inline
+-struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
+- ext4_group_t group)
+-{
+- struct ext4_group_info ***grp_info;
+- long indexv, indexh;
+- grp_info = EXT4_SB(sb)->s_group_info;
+- indexv = group >> (EXT4_DESC_PER_BLOCK_BITS(sb));
+- indexh = group & ((EXT4_DESC_PER_BLOCK(sb)) - 1);
+- return grp_info[indexv][indexh];
+-}
+-
+-
+-#define ext4_std_error(sb, errno) \
+-do { \
+- if ((errno)) \
+- __ext4_std_error((sb), __FUNCTION__, (errno)); \
+-} while (0)
+-
+-/*
+- * Inodes and files operations
+- */
+-
+-/* dir.c */
+-extern const struct file_operations ext4_dir_operations;
+-
+-/* file.c */
+-extern const struct inode_operations ext4_file_inode_operations;
+-extern const struct file_operations ext4_file_operations;
+-
+-/* namei.c */
+-extern const struct inode_operations ext4_dir_inode_operations;
+-extern const struct inode_operations ext4_special_inode_operations;
+-
+-/* symlink.c */
+-extern const struct inode_operations ext4_symlink_inode_operations;
+-extern const struct inode_operations ext4_fast_symlink_inode_operations;
+-
+-/* extents.c */
+-extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
+-extern int ext4_ext_writepage_trans_blocks(struct inode *, int);
+-extern int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+- ext4_lblk_t iblock,
+- unsigned long max_blocks, struct buffer_head *bh_result,
+- int create, int extend_disksize);
+-extern void ext4_ext_truncate(struct inode *, struct page *);
+-extern void ext4_ext_init(struct super_block *);
+-extern void ext4_ext_release(struct super_block *);
+-extern long ext4_fallocate(struct inode *inode, int mode, loff_t offset,
+- loff_t len);
+-extern int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode,
+- sector_t block, unsigned long max_blocks,
+- struct buffer_head *bh, int create,
+- int extend_disksize);
+-#endif /* __KERNEL__ */
+-
+-#endif /* _LINUX_EXT4_FS_H */
+diff --git a/include/linux/ext4_fs_extents.h b/include/linux/ext4_fs_extents.h
+deleted file mode 100644
+index 1285c58..0000000
+--- a/include/linux/ext4_fs_extents.h
++++ /dev/null
+@@ -1,232 +0,0 @@
+-/*
+- * Copyright (c) 2003-2006, Cluster File Systems, Inc, info at clusterfs.com
+- * Written by Alex Tomas <alex at clusterfs.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public Licens
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
+- */
+-
+-#ifndef _LINUX_EXT4_EXTENTS
+-#define _LINUX_EXT4_EXTENTS
+-
+-#include <linux/ext4_fs.h>
+-
+-/*
+- * With AGGRESSIVE_TEST defined, the capacity of index/leaf blocks
+- * becomes very small, so index split, in-depth growing and
+- * other hard changes happen much more often.
+- * This is for debug purposes only.
+- */
+-#define AGGRESSIVE_TEST_
+-
+-/*
+- * With EXTENTS_STATS defined, the number of blocks and extents
+- * are collected in the truncate path. They'll be shown at
+- * umount time.
+- */
+-#define EXTENTS_STATS__
+-
+-/*
+- * If CHECK_BINSEARCH is defined, then the results of the binary search
+- * will also be checked by linear search.
+- */
+-#define CHECK_BINSEARCH__
+-
+-/*
+- * If EXT_DEBUG is defined you can use the 'extdebug' mount option
+- * to get lots of info about what's going on.
+- */
+-#define EXT_DEBUG__
+-#ifdef EXT_DEBUG
+-#define ext_debug(a...) printk(a)
+-#else
+-#define ext_debug(a...)
+-#endif
+-
+-/*
+- * If EXT_STATS is defined then stats numbers are collected.
+- * These number will be displayed at umount time.
+- */
+-#define EXT_STATS_
+-
+-
+-/*
+- * ext4_inode has i_block array (60 bytes total).
+- * The first 12 bytes store ext4_extent_header;
+- * the remainder stores an array of ext4_extent.
+- */
+-
+-/*
+- * This is the extent on-disk structure.
+- * It's used at the bottom of the tree.
+- */
+-struct ext4_extent {
+- __le32 ee_block; /* first logical block extent covers */
+- __le16 ee_len; /* number of blocks covered by extent */
+- __le16 ee_start_hi; /* high 16 bits of physical block */
+- __le32 ee_start_lo; /* low 32 bits of physical block */
+-};
+-
+-/*
+- * This is index on-disk structure.
+- * It's used at all the levels except the bottom.
+- */
+-struct ext4_extent_idx {
+- __le32 ei_block; /* index covers logical blocks from 'block' */
+- __le32 ei_leaf_lo; /* pointer to the physical block of the next *
+- * level. leaf or next index could be there */
+- __le16 ei_leaf_hi; /* high 16 bits of physical block */
+- __u16 ei_unused;
+-};
+-
+-/*
+- * Each block (leaves and indexes), even inode-stored has header.
+- */
+-struct ext4_extent_header {
+- __le16 eh_magic; /* probably will support different formats */
+- __le16 eh_entries; /* number of valid entries */
+- __le16 eh_max; /* capacity of store in entries */
+- __le16 eh_depth; /* has tree real underlying blocks? */
+- __le32 eh_generation; /* generation of the tree */
+-};
+-
+-#define EXT4_EXT_MAGIC cpu_to_le16(0xf30a)
+-
+-/*
+- * Array of ext4_ext_path contains path to some extent.
+- * Creation/lookup routines use it for traversal/splitting/etc.
+- * Truncate uses it to simulate recursive walking.
+- */
+-struct ext4_ext_path {
+- ext4_fsblk_t p_block;
+- __u16 p_depth;
+- struct ext4_extent *p_ext;
+- struct ext4_extent_idx *p_idx;
+- struct ext4_extent_header *p_hdr;
+- struct buffer_head *p_bh;
+-};
+-
+-/*
+- * structure for external API
+- */
+-
+-#define EXT4_EXT_CACHE_NO 0
+-#define EXT4_EXT_CACHE_GAP 1
+-#define EXT4_EXT_CACHE_EXTENT 2
+-
+-
+-#define EXT_MAX_BLOCK 0xffffffff
+-
+-/*
+- * EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an
+- * initialized extent. This is 2^15 and not (2^16 - 1), since we use the
+- * MSB of ee_len field in the extent datastructure to signify if this
+- * particular extent is an initialized extent or an uninitialized (i.e.
+- * preallocated).
+- * EXT_UNINIT_MAX_LEN is the maximum number of blocks we can have in an
+- * uninitialized extent.
+- * If ee_len is <= 0x8000, it is an initialized extent. Otherwise, it is an
+- * uninitialized one. In other words, if MSB of ee_len is set, it is an
+- * uninitialized extent with only one special scenario when ee_len = 0x8000.
+- * In this case we can not have an uninitialized extent of zero length and
+- * thus we make it as a special case of initialized extent with 0x8000 length.
+- * This way we get better extent-to-group alignment for initialized extents.
+- * Hence, the maximum number of blocks we can have in an *initialized*
+- * extent is 2^15 (32768) and in an *uninitialized* extent is 2^15-1 (32767).
+- */
+-#define EXT_INIT_MAX_LEN (1UL << 15)
+-#define EXT_UNINIT_MAX_LEN (EXT_INIT_MAX_LEN - 1)
+-
+-
+-#define EXT_FIRST_EXTENT(__hdr__) \
+- ((struct ext4_extent *) (((char *) (__hdr__)) + \
+- sizeof(struct ext4_extent_header)))
+-#define EXT_FIRST_INDEX(__hdr__) \
+- ((struct ext4_extent_idx *) (((char *) (__hdr__)) + \
+- sizeof(struct ext4_extent_header)))
+-#define EXT_HAS_FREE_INDEX(__path__) \
+- (le16_to_cpu((__path__)->p_hdr->eh_entries) \
+- < le16_to_cpu((__path__)->p_hdr->eh_max))
+-#define EXT_LAST_EXTENT(__hdr__) \
+- (EXT_FIRST_EXTENT((__hdr__)) + le16_to_cpu((__hdr__)->eh_entries) - 1)
+-#define EXT_LAST_INDEX(__hdr__) \
+- (EXT_FIRST_INDEX((__hdr__)) + le16_to_cpu((__hdr__)->eh_entries) - 1)
+-#define EXT_MAX_EXTENT(__hdr__) \
+- (EXT_FIRST_EXTENT((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)
+-#define EXT_MAX_INDEX(__hdr__) \
+- (EXT_FIRST_INDEX((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)
+-
+-static inline struct ext4_extent_header *ext_inode_hdr(struct inode *inode)
+-{
+- return (struct ext4_extent_header *) EXT4_I(inode)->i_data;
+-}
+-
+-static inline struct ext4_extent_header *ext_block_hdr(struct buffer_head *bh)
+-{
+- return (struct ext4_extent_header *) bh->b_data;
+-}
+-
+-static inline unsigned short ext_depth(struct inode *inode)
+-{
+- return le16_to_cpu(ext_inode_hdr(inode)->eh_depth);
+-}
+-
+-static inline void ext4_ext_tree_changed(struct inode *inode)
+-{
+- EXT4_I(inode)->i_ext_generation++;
+-}
+-
+-static inline void
+-ext4_ext_invalidate_cache(struct inode *inode)
+-{
+- EXT4_I(inode)->i_cached_extent.ec_type = EXT4_EXT_CACHE_NO;
+-}
+-
+-static inline void ext4_ext_mark_uninitialized(struct ext4_extent *ext)
+-{
+- /* We can not have an uninitialized extent of zero length! */
+- BUG_ON((le16_to_cpu(ext->ee_len) & ~EXT_INIT_MAX_LEN) == 0);
+- ext->ee_len |= cpu_to_le16(EXT_INIT_MAX_LEN);
+-}
+-
+-static inline int ext4_ext_is_uninitialized(struct ext4_extent *ext)
+-{
+- /* Extent with ee_len of 0x8000 is treated as an initialized extent */
+- return (le16_to_cpu(ext->ee_len) > EXT_INIT_MAX_LEN);
+-}
+-
+-static inline int ext4_ext_get_actual_len(struct ext4_extent *ext)
+-{
+- return (le16_to_cpu(ext->ee_len) <= EXT_INIT_MAX_LEN ?
+- le16_to_cpu(ext->ee_len) :
+- (le16_to_cpu(ext->ee_len) - EXT_INIT_MAX_LEN));
+-}
+-
+-extern ext4_fsblk_t idx_pblock(struct ext4_extent_idx *);
+-extern void ext4_ext_store_pblock(struct ext4_extent *, ext4_fsblk_t);
+-extern int ext4_extent_tree_init(handle_t *, struct inode *);
+-extern int ext4_ext_calc_credits_for_insert(struct inode *, struct ext4_ext_path *);
+-extern int ext4_ext_try_to_merge(struct inode *inode,
+- struct ext4_ext_path *path,
+- struct ext4_extent *);
+-extern unsigned int ext4_ext_check_overlap(struct inode *, struct ext4_extent *, struct ext4_ext_path *);
+-extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *);
+-extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
+- struct ext4_ext_path *);
+-extern int ext4_ext_search_left(struct inode *, struct ext4_ext_path *,
+- ext4_lblk_t *, ext4_fsblk_t *);
+-extern int ext4_ext_search_right(struct inode *, struct ext4_ext_path *,
+- ext4_lblk_t *, ext4_fsblk_t *);
+-extern void ext4_ext_drop_refs(struct ext4_ext_path *);
+-#endif /* _LINUX_EXT4_EXTENTS */
+-
+diff --git a/include/linux/ext4_fs_i.h b/include/linux/ext4_fs_i.h
+deleted file mode 100644
+index d5508d3..0000000
+--- a/include/linux/ext4_fs_i.h
++++ /dev/null
+@@ -1,167 +0,0 @@
+-/*
+- * linux/include/linux/ext4_fs_i.h
+- *
+- * Copyright (C) 1992, 1993, 1994, 1995
+- * Remy Card (card at masi.ibp.fr)
+- * Laboratoire MASI - Institut Blaise Pascal
+- * Universite Pierre et Marie Curie (Paris VI)
+- *
+- * from
+- *
+- * linux/include/linux/minix_fs_i.h
+- *
+- * Copyright (C) 1991, 1992 Linus Torvalds
+- */
+-
+-#ifndef _LINUX_EXT4_FS_I
+-#define _LINUX_EXT4_FS_I
+-
+-#include <linux/rwsem.h>
+-#include <linux/rbtree.h>
+-#include <linux/seqlock.h>
+-#include <linux/mutex.h>
+-
+-/* data type for block offset of block group */
+-typedef int ext4_grpblk_t;
+-
+-/* data type for filesystem-wide blocks number */
+-typedef unsigned long long ext4_fsblk_t;
+-
+-/* data type for file logical block number */
+-typedef __u32 ext4_lblk_t;
+-
+-/* data type for block group number */
+-typedef unsigned long ext4_group_t;
+-
+-struct ext4_reserve_window {
+- ext4_fsblk_t _rsv_start; /* First byte reserved */
+- ext4_fsblk_t _rsv_end; /* Last byte reserved or 0 */
+-};
+-
+-struct ext4_reserve_window_node {
+- struct rb_node rsv_node;
+- __u32 rsv_goal_size;
+- __u32 rsv_alloc_hit;
+- struct ext4_reserve_window rsv_window;
+-};
+-
+-struct ext4_block_alloc_info {
+- /* information about reservation window */
+- struct ext4_reserve_window_node rsv_window_node;
+- /*
+- * was i_next_alloc_block in ext4_inode_info
+- * is the logical (file-relative) number of the
+- * most-recently-allocated block in this file.
+- * We use this for detecting linearly ascending allocation requests.
+- */
+- ext4_lblk_t last_alloc_logical_block;
+- /*
+- * Was i_next_alloc_goal in ext4_inode_info
+- * is the *physical* companion to i_next_alloc_block.
+- * it the physical block number of the block which was most-recentl
+- * allocated to this file. This give us the goal (target) for the next
+- * allocation when we detect linearly ascending requests.
+- */
+- ext4_fsblk_t last_alloc_physical_block;
+-};
+-
+-#define rsv_start rsv_window._rsv_start
+-#define rsv_end rsv_window._rsv_end
+-
+-/*
+- * storage for cached extent
+- */
+-struct ext4_ext_cache {
+- ext4_fsblk_t ec_start;
+- ext4_lblk_t ec_block;
+- __u32 ec_len; /* must be 32bit to return holes */
+- __u32 ec_type;
+-};
+-
+-/*
+- * third extended file system inode data in memory
+- */
+-struct ext4_inode_info {
+- __le32 i_data[15]; /* unconverted */
+- __u32 i_flags;
+- ext4_fsblk_t i_file_acl;
+- __u32 i_dtime;
+-
+- /*
+- * i_block_group is the number of the block group which contains
+- * this file's inode. Constant across the lifetime of the inode,
+- * it is ued for making block allocation decisions - we try to
+- * place a file's data blocks near its inode block, and new inodes
+- * near to their parent directory's inode.
+- */
+- ext4_group_t i_block_group;
+- __u32 i_state; /* Dynamic state flags for ext4 */
+-
+- /* block reservation info */
+- struct ext4_block_alloc_info *i_block_alloc_info;
+-
+- ext4_lblk_t i_dir_start_lookup;
+-#ifdef CONFIG_EXT4DEV_FS_XATTR
+- /*
+- * Extended attributes can be read independently of the main file
+- * data. Taking i_mutex even when reading would cause contention
+- * between readers of EAs and writers of regular file data, so
+- * instead we synchronize on xattr_sem when reading or changing
+- * EAs.
+- */
+- struct rw_semaphore xattr_sem;
+-#endif
+-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
+- struct posix_acl *i_acl;
+- struct posix_acl *i_default_acl;
+-#endif
+-
+- struct list_head i_orphan; /* unlinked but open inodes */
+-
+- /*
+- * i_disksize keeps track of what the inode size is ON DISK, not
+- * in memory. During truncate, i_size is set to the new size by
+- * the VFS prior to calling ext4_truncate(), but the filesystem won't
+- * set i_disksize to 0 until the truncate is actually under way.
+- *
+- * The intent is that i_disksize always represents the blocks which
+- * are used by this file. This allows recovery to restart truncate
+- * on orphans if we crash during truncate. We actually write i_disksize
+- * into the on-disk inode when writing inodes out, instead of i_size.
+- *
+- * The only time when i_disksize and i_size may be different is when
+- * a truncate is in progress. The only things which change i_disksize
+- * are ext4_get_block (growth) and ext4_truncate (shrinkth).
+- */
+- loff_t i_disksize;
+-
+- /* on-disk additional length */
+- __u16 i_extra_isize;
+-
+- /*
+- * i_data_sem is for serialising ext4_truncate() against
+- * ext4_getblock(). In the 2.4 ext2 design, great chunks of inode's
+- * data tree are chopped off during truncate. We can't do that in
+- * ext4 because whenever we perform intermediate commits during
+- * truncate, the inode and all the metadata blocks *must* be in a
+- * consistent state which allows truncation of the orphans to restart
+- * during recovery. Hence we must fix the get_block-vs-truncate race
+- * by other means, so we have i_data_sem.
+- */
+- struct rw_semaphore i_data_sem;
+- struct inode vfs_inode;
+-
+- unsigned long i_ext_generation;
+- struct ext4_ext_cache i_cached_extent;
+- /*
+- * File creation time. Its function is same as that of
+- * struct timespec i_{a,c,m}time in the generic inode.
+- */
+- struct timespec i_crtime;
+-
+- /* mballoc */
+- struct list_head i_prealloc_list;
+- spinlock_t i_prealloc_lock;
+-};
+-
+-#endif /* _LINUX_EXT4_FS_I */
+diff --git a/include/linux/ext4_fs_sb.h b/include/linux/ext4_fs_sb.h
+deleted file mode 100644
+index abaae2c..0000000
+--- a/include/linux/ext4_fs_sb.h
++++ /dev/null
+@@ -1,148 +0,0 @@
+-/*
+- * linux/include/linux/ext4_fs_sb.h
+- *
+- * Copyright (C) 1992, 1993, 1994, 1995
+- * Remy Card (card at masi.ibp.fr)
+- * Laboratoire MASI - Institut Blaise Pascal
+- * Universite Pierre et Marie Curie (Paris VI)
+- *
+- * from
+- *
+- * linux/include/linux/minix_fs_sb.h
+- *
+- * Copyright (C) 1991, 1992 Linus Torvalds
+- */
+-
+-#ifndef _LINUX_EXT4_FS_SB
+-#define _LINUX_EXT4_FS_SB
+-
+-#ifdef __KERNEL__
+-#include <linux/timer.h>
+-#include <linux/wait.h>
+-#include <linux/blockgroup_lock.h>
+-#include <linux/percpu_counter.h>
+-#endif
+-#include <linux/rbtree.h>
+-
+-/*
+- * third extended-fs super-block data in memory
+- */
+-struct ext4_sb_info {
+- unsigned long s_desc_size; /* Size of a group descriptor in bytes */
+- unsigned long s_inodes_per_block;/* Number of inodes per block */
+- unsigned long s_blocks_per_group;/* Number of blocks in a group */
+- unsigned long s_inodes_per_group;/* Number of inodes in a group */
+- unsigned long s_itb_per_group; /* Number of inode table blocks per group */
+- unsigned long s_gdb_count; /* Number of group descriptor blocks */
+- unsigned long s_desc_per_block; /* Number of group descriptors per block */
+- ext4_group_t s_groups_count; /* Number of groups in the fs */
+- unsigned long s_overhead_last; /* Last calculated overhead */
+- unsigned long s_blocks_last; /* Last seen block count */
+- loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */
+- struct buffer_head * s_sbh; /* Buffer containing the super block */
+- struct ext4_super_block * s_es; /* Pointer to the super block in the buffer */
+- struct buffer_head ** s_group_desc;
+- unsigned long s_mount_opt;
+- ext4_fsblk_t s_sb_block;
+- uid_t s_resuid;
+- gid_t s_resgid;
+- unsigned short s_mount_state;
+- unsigned short s_pad;
+- int s_addr_per_block_bits;
+- int s_desc_per_block_bits;
+- int s_inode_size;
+- int s_first_ino;
+- spinlock_t s_next_gen_lock;
+- u32 s_next_generation;
+- u32 s_hash_seed[4];
+- int s_def_hash_version;
+- struct percpu_counter s_freeblocks_counter;
+- struct percpu_counter s_freeinodes_counter;
+- struct percpu_counter s_dirs_counter;
+- struct blockgroup_lock s_blockgroup_lock;
+-
+- /* root of the per fs reservation window tree */
+- spinlock_t s_rsv_window_lock;
+- struct rb_root s_rsv_window_root;
+- struct ext4_reserve_window_node s_rsv_window_head;
+-
+- /* Journaling */
+- struct inode * s_journal_inode;
+- struct journal_s * s_journal;
+- struct list_head s_orphan;
+- unsigned long s_commit_interval;
+- struct block_device *journal_bdev;
+-#ifdef CONFIG_JBD2_DEBUG
+- struct timer_list turn_ro_timer; /* For turning read-only (crash simulation) */
+- wait_queue_head_t ro_wait_queue; /* For people waiting for the fs to go read-only */
+-#endif
+-#ifdef CONFIG_QUOTA
+- char *s_qf_names[MAXQUOTAS]; /* Names of quota files with journalled quota */
+- int s_jquota_fmt; /* Format of quota to use */
+-#endif
+- unsigned int s_want_extra_isize; /* New inodes should reserve # bytes */
+-
+-#ifdef EXTENTS_STATS
+- /* ext4 extents stats */
+- unsigned long s_ext_min;
+- unsigned long s_ext_max;
+- unsigned long s_depth_max;
+- spinlock_t s_ext_stats_lock;
+- unsigned long s_ext_blocks;
+- unsigned long s_ext_extents;
+-#endif
+-
+- /* for buddy allocator */
+- struct ext4_group_info ***s_group_info;
+- struct inode *s_buddy_cache;
+- long s_blocks_reserved;
+- spinlock_t s_reserve_lock;
+- struct list_head s_active_transaction;
+- struct list_head s_closed_transaction;
+- struct list_head s_committed_transaction;
+- spinlock_t s_md_lock;
+- tid_t s_last_transaction;
+- unsigned short *s_mb_offsets, *s_mb_maxs;
+-
+- /* tunables */
+- unsigned long s_stripe;
+- unsigned long s_mb_stream_request;
+- unsigned long s_mb_max_to_scan;
+- unsigned long s_mb_min_to_scan;
+- unsigned long s_mb_stats;
+- unsigned long s_mb_order2_reqs;
+- unsigned long s_mb_group_prealloc;
+- /* where last allocation was done - for stream allocation */
+- unsigned long s_mb_last_group;
+- unsigned long s_mb_last_start;
+-
+- /* history to debug policy */
+- struct ext4_mb_history *s_mb_history;
+- int s_mb_history_cur;
+- int s_mb_history_max;
+- int s_mb_history_num;
+- struct proc_dir_entry *s_mb_proc;
+- spinlock_t s_mb_history_lock;
+- int s_mb_history_filter;
+-
+- /* stats for buddy allocator */
+- spinlock_t s_mb_pa_lock;
+- atomic_t s_bal_reqs; /* number of reqs with len > 1 */
+- atomic_t s_bal_success; /* we found long enough chunks */
+- atomic_t s_bal_allocated; /* in blocks */
+- atomic_t s_bal_ex_scanned; /* total extents scanned */
+- atomic_t s_bal_goals; /* goal hits */
+- atomic_t s_bal_breaks; /* too long searches */
+- atomic_t s_bal_2orders; /* 2^order hits */
+- spinlock_t s_bal_lock;
+- unsigned long s_mb_buddies_generated;
+- unsigned long long s_mb_generation_time;
+- atomic_t s_mb_lost_chunks;
+- atomic_t s_mb_preallocated;
+- atomic_t s_mb_discarded;
+-
+- /* locality groups */
+- struct ext4_locality_group *s_locality_groups;
+-};
+-
+-#endif /* _LINUX_EXT4_FS_SB */
+diff --git a/include/linux/ext4_jbd2.h b/include/linux/ext4_jbd2.h
+deleted file mode 100644
+index 38c71d3..0000000
+--- a/include/linux/ext4_jbd2.h
++++ /dev/null
+@@ -1,231 +0,0 @@
+-/*
+- * linux/include/linux/ext4_jbd2.h
+- *
+- * Written by Stephen C. Tweedie <sct at redhat.com>, 1999
+- *
+- * Copyright 1998--1999 Red Hat corp --- 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, or at your
+- * option, any later version, incorporated herein by reference.
+- *
+- * Ext4-specific journaling extensions.
+- */
+-
+-#ifndef _LINUX_EXT4_JBD2_H
+-#define _LINUX_EXT4_JBD2_H
+-
+-#include <linux/fs.h>
+-#include <linux/jbd2.h>
+-#include <linux/ext4_fs.h>
+-
+-#define EXT4_JOURNAL(inode) (EXT4_SB((inode)->i_sb)->s_journal)
+-
+-/* Define the number of blocks we need to account to a transaction to
+- * modify one block of data.
+- *
+- * We may have to touch one inode, one bitmap buffer, up to three
+- * indirection blocks, the group and superblock summaries, and the data
+- * block to complete the transaction.
+- *
+- * For extents-enabled fs we may have to allocate and modify up to
+- * 5 levels of tree + root which are stored in the inode. */
+-
+-#define EXT4_SINGLEDATA_TRANS_BLOCKS(sb) \
+- (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS) \
+- || test_opt(sb, EXTENTS) ? 27U : 8U)
+-
+-/* Extended attribute operations touch at most two data buffers,
+- * two bitmap buffers, and two group summaries, in addition to the inode
+- * and the superblock, which are already accounted for. */
+-
+-#define EXT4_XATTR_TRANS_BLOCKS 6U
+-
+-/* Define the minimum size for a transaction which modifies data. This
+- * needs to take into account the fact that we may end up modifying two
+- * quota files too (one for the group, one for the user quota). The
+- * superblock only gets updated once, of course, so don't bother
+- * counting that again for the quota updates. */
+-
+-#define EXT4_DATA_TRANS_BLOCKS(sb) (EXT4_SINGLEDATA_TRANS_BLOCKS(sb) + \
+- EXT4_XATTR_TRANS_BLOCKS - 2 + \
+- 2*EXT4_QUOTA_TRANS_BLOCKS(sb))
+-
+-/* Delete operations potentially hit one directory's namespace plus an
+- * entire inode, plus arbitrary amounts of bitmap/indirection data. Be
+- * generous. We can grow the delete transaction later if necessary. */
+-
+-#define EXT4_DELETE_TRANS_BLOCKS(sb) (2 * EXT4_DATA_TRANS_BLOCKS(sb) + 64)
+-
+-/* Define an arbitrary limit for the amount of data we will anticipate
+- * writing to any given transaction. For unbounded transactions such as
+- * write(2) and truncate(2) we can write more than this, but we always
+- * start off at the maximum transaction size and grow the transaction
+- * optimistically as we go. */
+-
+-#define EXT4_MAX_TRANS_DATA 64U
+-
+-/* We break up a large truncate or write transaction once the handle's
+- * buffer credits gets this low, we need either to extend the
+- * transaction or to start a new one. Reserve enough space here for
+- * inode, bitmap, superblock, group and indirection updates for at least
+- * one block, plus two quota updates. Quota allocations are not
+- * needed. */
+-
+-#define EXT4_RESERVE_TRANS_BLOCKS 12U
+-
+-#define EXT4_INDEX_EXTRA_TRANS_BLOCKS 8
+-
+-#ifdef CONFIG_QUOTA
+-/* Amount of blocks needed for quota update - we know that the structure was
+- * allocated so we need to update only inode+data */
+-#define EXT4_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 2 : 0)
+-/* Amount of blocks needed for quota insert/delete - we do some block writes
+- * but inode, sb and group updates are done only once */
+-#define EXT4_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\
+- (EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_INIT_REWRITE) : 0)
+-#define EXT4_QUOTA_DEL_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_DEL_ALLOC*\
+- (EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_DEL_REWRITE) : 0)
+-#else
+-#define EXT4_QUOTA_TRANS_BLOCKS(sb) 0
+-#define EXT4_QUOTA_INIT_BLOCKS(sb) 0
+-#define EXT4_QUOTA_DEL_BLOCKS(sb) 0
+-#endif
+-
+-int
+-ext4_mark_iloc_dirty(handle_t *handle,
+- struct inode *inode,
+- struct ext4_iloc *iloc);
+-
+-/*
+- * On success, We end up with an outstanding reference count against
+- * iloc->bh. This _must_ be cleaned up later.
+- */
+-
+-int ext4_reserve_inode_write(handle_t *handle, struct inode *inode,
+- struct ext4_iloc *iloc);
+-
+-int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode);
+-
+-/*
+- * Wrapper functions with which ext4 calls into JBD. The intent here is
+- * to allow these to be turned into appropriate stubs so ext4 can control
+- * ext2 filesystems, so ext2+ext4 systems only nee one fs. This work hasn't
+- * been done yet.
+- */
+-
+-static inline void ext4_journal_release_buffer(handle_t *handle,
+- struct buffer_head *bh)
+-{
+- jbd2_journal_release_buffer(handle, bh);
+-}
+-
+-void ext4_journal_abort_handle(const char *caller, const char *err_fn,
+- struct buffer_head *bh, handle_t *handle, int err);
+-
+-int __ext4_journal_get_undo_access(const char *where, handle_t *handle,
+- struct buffer_head *bh);
+-
+-int __ext4_journal_get_write_access(const char *where, handle_t *handle,
+- struct buffer_head *bh);
+-
+-int __ext4_journal_forget(const char *where, handle_t *handle,
+- struct buffer_head *bh);
+-
+-int __ext4_journal_revoke(const char *where, handle_t *handle,
+- ext4_fsblk_t blocknr, struct buffer_head *bh);
+-
+-int __ext4_journal_get_create_access(const char *where,
+- handle_t *handle, struct buffer_head *bh);
+-
+-int __ext4_journal_dirty_metadata(const char *where,
+- handle_t *handle, struct buffer_head *bh);
+-
+-#define ext4_journal_get_undo_access(handle, bh) \
+- __ext4_journal_get_undo_access(__FUNCTION__, (handle), (bh))
+-#define ext4_journal_get_write_access(handle, bh) \
+- __ext4_journal_get_write_access(__FUNCTION__, (handle), (bh))
+-#define ext4_journal_revoke(handle, blocknr, bh) \
+- __ext4_journal_revoke(__FUNCTION__, (handle), (blocknr), (bh))
+-#define ext4_journal_get_create_access(handle, bh) \
+- __ext4_journal_get_create_access(__FUNCTION__, (handle), (bh))
+-#define ext4_journal_dirty_metadata(handle, bh) \
+- __ext4_journal_dirty_metadata(__FUNCTION__, (handle), (bh))
+-#define ext4_journal_forget(handle, bh) \
+- __ext4_journal_forget(__FUNCTION__, (handle), (bh))
+-
+-int ext4_journal_dirty_data(handle_t *handle, struct buffer_head *bh);
+-
+-handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks);
+-int __ext4_journal_stop(const char *where, handle_t *handle);
+-
+-static inline handle_t *ext4_journal_start(struct inode *inode, int nblocks)
+-{
+- return ext4_journal_start_sb(inode->i_sb, nblocks);
+-}
+-
+-#define ext4_journal_stop(handle) \
+- __ext4_journal_stop(__FUNCTION__, (handle))
+-
+-static inline handle_t *ext4_journal_current_handle(void)
+-{
+- return journal_current_handle();
+-}
+-
+-static inline int ext4_journal_extend(handle_t *handle, int nblocks)
+-{
+- return jbd2_journal_extend(handle, nblocks);
+-}
+-
+-static inline int ext4_journal_restart(handle_t *handle, int nblocks)
+-{
+- return jbd2_journal_restart(handle, nblocks);
+-}
+-
+-static inline int ext4_journal_blocks_per_page(struct inode *inode)
+-{
+- return jbd2_journal_blocks_per_page(inode);
+-}
+-
+-static inline int ext4_journal_force_commit(journal_t *journal)
+-{
+- return jbd2_journal_force_commit(journal);
+-}
+-
+-/* super.c */
+-int ext4_force_commit(struct super_block *sb);
+-
+-static inline int ext4_should_journal_data(struct inode *inode)
+-{
+- if (!S_ISREG(inode->i_mode))
+- return 1;
+- if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
+- return 1;
+- if (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL)
+- return 1;
+- return 0;
+-}
+-
+-static inline int ext4_should_order_data(struct inode *inode)
+-{
+- if (!S_ISREG(inode->i_mode))
+- return 0;
+- if (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL)
+- return 0;
+- if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
+- return 1;
+- return 0;
+-}
+-
+-static inline int ext4_should_writeback_data(struct inode *inode)
+-{
+- if (!S_ISREG(inode->i_mode))
+- return 0;
+- if (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL)
+- return 0;
+- if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
+- return 1;
+- return 0;
+-}
+-
+-#endif /* _LINUX_EXT4_JBD2_H */
+diff --git a/include/linux/fb.h b/include/linux/fb.h
+index 58c57a3..72295b0 100644
+--- a/include/linux/fb.h
++++ b/include/linux/fb.h
+@@ -791,6 +791,17 @@ struct fb_tile_ops {
+ */
+ #define FBINFO_MISC_ALWAYS_SETPAR 0x40000
+
++/*
++ * Host and GPU endianness differ.
++ */
++#define FBINFO_FOREIGN_ENDIAN 0x100000
++/*
++ * Big endian math. This is the same flags as above, but with different
++ * meaning, it is set by the fb subsystem depending FOREIGN_ENDIAN flag
++ * and host endianness. Drivers should not use this flag.
++ */
++#define FBINFO_BE_MATH 0x100000
++
+ struct fb_info {
+ int node;
+ int flags;
+@@ -899,15 +910,11 @@ struct fb_info {
+
+ #endif
+
+-#if defined (__BIG_ENDIAN)
+-#define FB_LEFT_POS(bpp) (32 - bpp)
+-#define FB_SHIFT_HIGH(val, bits) ((val) >> (bits))
+-#define FB_SHIFT_LOW(val, bits) ((val) << (bits))
+-#else
+-#define FB_LEFT_POS(bpp) (0)
+-#define FB_SHIFT_HIGH(val, bits) ((val) << (bits))
+-#define FB_SHIFT_LOW(val, bits) ((val) >> (bits))
+-#endif
++#define FB_LEFT_POS(p, bpp) (fb_be_math(p) ? (32 - (bpp)) : 0)
++#define FB_SHIFT_HIGH(p, val, bits) (fb_be_math(p) ? (val) >> (bits) : \
++ (val) << (bits))
++#define FB_SHIFT_LOW(p, val, bits) (fb_be_math(p) ? (val) << (bits) : \
++ (val) >> (bits))
+
+ /*
+ * `Generic' versions of the frame buffer device operations
+@@ -970,6 +977,25 @@ extern void fb_deferred_io_cleanup(struct fb_info *info);
+ extern int fb_deferred_io_fsync(struct file *file, struct dentry *dentry,
+ int datasync);
+
++static inline bool fb_be_math(struct fb_info *info)
++{
++#ifdef CONFIG_FB_FOREIGN_ENDIAN
++#if defined(CONFIG_FB_BOTH_ENDIAN)
++ return info->flags & FBINFO_BE_MATH;
++#elif defined(CONFIG_FB_BIG_ENDIAN)
++ return true;
++#elif defined(CONFIG_FB_LITTLE_ENDIAN)
++ return false;
++#endif /* CONFIG_FB_BOTH_ENDIAN */
++#else
++#ifdef __BIG_ENDIAN
++ return true;
++#else
++ return false;
++#endif /* __BIG_ENDIAN */
++#endif /* CONFIG_FB_FOREIGN_ENDIAN */
++}
++
+ /* drivers/video/fbsysfs.c */
+ extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev);
+ extern void framebuffer_release(struct fb_info *info);
diff --git a/include/linux/file.h b/include/linux/file.h
index 7239baa..69baf5a 100644
--- a/include/linux/file.h
@@ -812846,7 +1084564,7 @@
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
+index b84b848..a1ba005 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -287,9 +287,9 @@ extern int dir_notify_enable;
@@ -812868,6 +1084586,17 @@
extern void __init files_init(unsigned long);
struct buffer_head;
+@@ -475,8 +474,8 @@ struct address_space_operations {
+ int (*releasepage) (struct page *, gfp_t);
+ ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
+ loff_t offset, unsigned long nr_segs);
+- struct page* (*get_xip_page)(struct address_space *, sector_t,
+- int);
++ int (*get_xip_mem)(struct address_space *, pgoff_t, int,
++ void **, unsigned long *);
+ /* migrate the contents of a page to the specified target */
+ int (*migratepage) (struct address_space *,
+ struct page *, struct page *);
@@ -776,6 +775,9 @@ static inline int ra_has_index(struct file_ra_state *ra, pgoff_t index)
index < ra->start + ra->size);
}
@@ -812946,7 +1084675,17 @@
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 {
+@@ -1129,7 +1178,8 @@ struct block_device_operations {
+ int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
+ long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
+ long (*compat_ioctl) (struct file *, unsigned, unsigned long);
+- int (*direct_access) (struct block_device *, sector_t, unsigned long *);
++ int (*direct_access) (struct block_device *, sector_t,
++ void **, unsigned long *);
+ int (*media_changed) (struct gendisk *);
+ int (*revalidate_disk) (struct gendisk *);
+ int (*getgeo)(struct block_device *, struct hd_geometry *);
+@@ -1260,7 +1310,7 @@ struct super_operations {
int (*statfs) (struct dentry *, struct kstatfs *);
int (*remount_fs) (struct super_block *, int *, char *);
void (*clear_inode) (struct inode *);
@@ -812955,6 +1084694,14 @@
int (*show_options)(struct seq_file *, struct vfsmount *);
int (*show_stats)(struct seq_file *, struct vfsmount *);
+@@ -1471,7 +1521,6 @@ extern int get_sb_pseudo(struct file_system_type *, char *,
+ const struct super_operations *ops, unsigned long,
+ struct vfsmount *mnt);
+ extern int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb);
+-int __put_super(struct super_block *sb);
+ int __put_super_and_need_restart(struct super_block *sb);
+ void unnamed_dev_init(void);
+
@@ -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 *);
@@ -812978,7 +1084725,15 @@
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)
+@@ -1919,7 +1964,6 @@ extern int vfs_stat_fd(int dfd, char __user *, struct kstat *);
+ extern int vfs_lstat_fd(int dfd, char __user *, struct kstat *);
+ extern int vfs_fstat(unsigned int, struct kstat *);
+
+-extern long vfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+ extern int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
+ unsigned long arg);
+
+@@ -1989,9 +2033,6 @@ static inline ino_t parent_ino(struct dentry *dentry)
return res;
}
@@ -812989,10 +1084744,18 @@
/*
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
-index 1831b19..2cad5c6 100644
+index 1831b19..c415a49 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
-@@ -50,7 +50,7 @@ struct gianfar_platform_data {
+@@ -14,7 +14,6 @@
+ * option) any later version.
+ */
+
+-#ifdef __KERNEL__
+ #ifndef _FSL_DEVICE_H_
+ #define _FSL_DEVICE_H_
+
+@@ -50,7 +49,7 @@ struct gianfar_platform_data {
u32 device_flags;
/* board specific information */
u32 board_flags;
@@ -813001,6 +1084764,151 @@
u32 phy_id;
u8 mac_addr[6];
phy_interface_t interface;
+@@ -127,4 +126,3 @@ struct mpc8xx_pcmcia_ops {
+ };
+
+ #endif /* _FSL_DEVICE_H_ */
+-#endif /* __KERNEL__ */
+diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
+index d4b7c4a..a895131 100644
+--- a/include/linux/fsnotify.h
++++ b/include/linux/fsnotify.h
+@@ -11,8 +11,6 @@
+ * (C) Copyright 2005 Robert Love
+ */
+
+-#ifdef __KERNEL__
+-
+ #include <linux/dnotify.h>
+ #include <linux/inotify.h>
+ #include <linux/audit.h>
+@@ -296,6 +294,4 @@ static inline void fsnotify_oldname_free(const char *old_name)
+
+ #endif /* ! CONFIG_INOTIFY */
+
+-#endif /* __KERNEL__ */
+-
+ #endif /* _LINUX_FS_NOTIFY_H */
+diff --git a/include/linux/generic_serial.h b/include/linux/generic_serial.h
+index 5412da2..1108336 100644
+--- a/include/linux/generic_serial.h
++++ b/include/linux/generic_serial.h
+@@ -78,7 +78,7 @@ struct gs_port {
+ #define GS_DEBUG_WRITE 0x00000040
+
+ #ifdef __KERNEL__
+-void gs_put_char(struct tty_struct *tty, unsigned char ch);
++int gs_put_char(struct tty_struct *tty, unsigned char ch);
+ int gs_write(struct tty_struct *tty,
+ const unsigned char *buf, int count);
+ int gs_write_room(struct tty_struct *tty);
+diff --git a/include/linux/gfp.h b/include/linux/gfp.h
+index 164be9d..b414be3 100644
+--- a/include/linux/gfp.h
++++ b/include/linux/gfp.h
+@@ -40,9 +40,9 @@ struct vm_area_struct;
+ #define __GFP_FS ((__force gfp_t)0x80u) /* Can call down to low-level FS? */
+ #define __GFP_COLD ((__force gfp_t)0x100u) /* Cache-cold page required */
+ #define __GFP_NOWARN ((__force gfp_t)0x200u) /* Suppress page allocation failure warning */
+-#define __GFP_REPEAT ((__force gfp_t)0x400u) /* Retry the allocation. Might fail */
+-#define __GFP_NOFAIL ((__force gfp_t)0x800u) /* Retry for ever. Cannot fail */
+-#define __GFP_NORETRY ((__force gfp_t)0x1000u)/* Do not retry. Might fail */
++#define __GFP_REPEAT ((__force gfp_t)0x400u) /* See above */
++#define __GFP_NOFAIL ((__force gfp_t)0x800u) /* See above */
++#define __GFP_NORETRY ((__force gfp_t)0x1000u)/* See above */
+ #define __GFP_COMP ((__force gfp_t)0x4000u)/* Add compound page metadata */
+ #define __GFP_ZERO ((__force gfp_t)0x8000u)/* Return zeroed page on success */
+ #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
+@@ -119,35 +119,22 @@ static inline int allocflags_to_migratetype(gfp_t gfp_flags)
+
+ static inline enum zone_type gfp_zone(gfp_t flags)
+ {
+- int base = 0;
+-
+-#ifdef CONFIG_NUMA
+- if (flags & __GFP_THISNODE)
+- base = MAX_NR_ZONES;
+-#endif
+-
+ #ifdef CONFIG_ZONE_DMA
+ if (flags & __GFP_DMA)
+- return base + ZONE_DMA;
++ return ZONE_DMA;
+ #endif
+ #ifdef CONFIG_ZONE_DMA32
+ if (flags & __GFP_DMA32)
+- return base + ZONE_DMA32;
++ return ZONE_DMA32;
+ #endif
+ if ((flags & (__GFP_HIGHMEM | __GFP_MOVABLE)) ==
+ (__GFP_HIGHMEM | __GFP_MOVABLE))
+- return base + ZONE_MOVABLE;
++ return ZONE_MOVABLE;
+ #ifdef CONFIG_HIGHMEM
+ if (flags & __GFP_HIGHMEM)
+- return base + ZONE_HIGHMEM;
++ return ZONE_HIGHMEM;
+ #endif
+- return base + ZONE_NORMAL;
+-}
+-
+-static inline gfp_t set_migrateflags(gfp_t gfp, gfp_t migrate_flags)
+-{
+- BUG_ON((gfp & GFP_MOVABLE_MASK) == GFP_MOVABLE_MASK);
+- return (gfp & ~(GFP_MOVABLE_MASK)) | migrate_flags;
++ return ZONE_NORMAL;
+ }
+
+ /*
+@@ -157,13 +144,27 @@ static inline gfp_t set_migrateflags(gfp_t gfp, gfp_t migrate_flags)
+ * virtual kernel addresses to the allocated page(s).
+ */
+
++static inline int gfp_zonelist(gfp_t flags)
++{
++ if (NUMA_BUILD && unlikely(flags & __GFP_THISNODE))
++ return 1;
++
++ return 0;
++}
++
+ /*
+ * We get the zone list from the current node and the gfp_mask.
+ * This zone list contains a maximum of MAXNODES*MAX_NR_ZONES zones.
++ * There are two zonelists per node, one for all zones with memory and
++ * one containing just zones from the node the zonelist belongs to.
+ *
+ * For the normal case of non-DISCONTIGMEM systems the NODE_DATA() gets
+ * optimized to &contig_page_data at compile-time.
+ */
++static inline struct zonelist *node_zonelist(int nid, gfp_t flags)
++{
++ return NODE_DATA(nid)->node_zonelists + gfp_zonelist(flags);
++}
+
+ #ifndef HAVE_ARCH_FREE_PAGE
+ static inline void arch_free_page(struct page *page, int order) { }
+@@ -174,6 +175,10 @@ static inline void arch_alloc_page(struct page *page, int order) { }
+
+ extern struct page *__alloc_pages(gfp_t, unsigned int, struct zonelist *);
+
++extern struct page *
++__alloc_pages_nodemask(gfp_t, unsigned int,
++ struct zonelist *, nodemask_t *nodemask);
++
+ static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask,
+ unsigned int order)
+ {
+@@ -184,8 +189,7 @@ static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask,
+ if (nid < 0)
+ nid = numa_node_id();
+
+- return __alloc_pages(gfp_mask, order,
+- NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_mask));
++ return __alloc_pages(gfp_mask, order, node_zonelist(nid, gfp_mask));
+ }
+
+ #ifdef CONFIG_NUMA
diff --git a/include/linux/hdreg.h b/include/linux/hdreg.h
index e38e759..c37e924 100644
--- a/include/linux/hdreg.h
@@ -813151,7 +1085059,7 @@
-
-#endif /* _LINUX_HDSMART_H */
diff --git a/include/linux/hid.h b/include/linux/hid.h
-index 74ff575..d951ec4 100644
+index 74ff575..4ce3b7a 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -284,6 +284,7 @@ struct hid_item {
@@ -813197,6 +1085105,22 @@
int open; /* is the device open by anyone? */
char name[128]; /* Device name */
char phys[64]; /* Device physical location */
+@@ -496,13 +498,13 @@ struct hid_parser {
+
+ struct hid_class_descriptor {
+ __u8 bDescriptorType;
+- __u16 wDescriptorLength;
++ __le16 wDescriptorLength;
+ } __attribute__ ((packed));
+
+ struct hid_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+- __u16 bcdHID;
++ __le16 bcdHID;
+ __u8 bCountryCode;
+ __u8 bNumDescriptors;
+
@@ -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);
@@ -813259,7 +1085183,7 @@
#include <linux/list.h>
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
-index 1ad56a7..56f3236 100644
+index 1ad56a7..31a4d65 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -173,7 +173,6 @@ struct hrtimer_clock_base {
@@ -813278,11 +1085202,105 @@
struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES];
struct list_head cb_pending;
#ifdef CONFIG_HIGH_RES_TIMERS
+@@ -268,6 +266,21 @@ extern ktime_t ktime_get_real(void);
+ extern void hrtimer_init(struct hrtimer *timer, clockid_t which_clock,
+ enum hrtimer_mode mode);
+
++#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
++extern void hrtimer_init_on_stack(struct hrtimer *timer, clockid_t which_clock,
++ enum hrtimer_mode mode);
++
++extern void destroy_hrtimer_on_stack(struct hrtimer *timer);
++#else
++static inline void hrtimer_init_on_stack(struct hrtimer *timer,
++ clockid_t which_clock,
++ enum hrtimer_mode mode)
++{
++ hrtimer_init(timer, which_clock, mode);
++}
++static inline void destroy_hrtimer_on_stack(struct hrtimer *timer) { }
++#endif
++
+ /* Basic timer operations: */
+ extern int hrtimer_start(struct hrtimer *timer, ktime_t tim,
+ const enum hrtimer_mode mode);
+diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
+index addca4c..a79e80b 100644
+--- a/include/linux/hugetlb.h
++++ b/include/linux/hugetlb.h
+@@ -8,6 +8,7 @@
+ #include <linux/mempolicy.h>
+ #include <linux/shm.h>
+ #include <asm/tlbflush.h>
++#include <asm/hugetlb.h>
+
+ struct ctl_table;
+
+@@ -51,51 +52,6 @@ int pmd_huge(pmd_t pmd);
+ void hugetlb_change_protection(struct vm_area_struct *vma,
+ unsigned long address, unsigned long end, pgprot_t newprot);
+
+-#ifndef ARCH_HAS_HUGEPAGE_ONLY_RANGE
+-#define is_hugepage_only_range(mm, addr, len) 0
+-#endif
+-
+-#ifndef ARCH_HAS_HUGETLB_FREE_PGD_RANGE
+-#define hugetlb_free_pgd_range free_pgd_range
+-#else
+-void hugetlb_free_pgd_range(struct mmu_gather **tlb, unsigned long addr,
+- unsigned long end, unsigned long floor,
+- unsigned long ceiling);
+-#endif
+-
+-#ifndef ARCH_HAS_PREPARE_HUGEPAGE_RANGE
+-/*
+- * If the arch doesn't supply something else, assume that hugepage
+- * size aligned regions are ok without further preparation.
+- */
+-static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
+-{
+- if (len & ~HPAGE_MASK)
+- return -EINVAL;
+- if (addr & ~HPAGE_MASK)
+- return -EINVAL;
+- return 0;
+-}
+-#else
+-int prepare_hugepage_range(unsigned long addr, unsigned long len);
+-#endif
+-
+-#ifndef ARCH_HAS_SETCLEAR_HUGE_PTE
+-#define set_huge_pte_at(mm, addr, ptep, pte) set_pte_at(mm, addr, ptep, pte)
+-#define huge_ptep_get_and_clear(mm, addr, ptep) ptep_get_and_clear(mm, addr, ptep)
+-#else
+-void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+- pte_t *ptep, pte_t pte);
+-pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+- pte_t *ptep);
+-#endif
+-
+-#ifndef ARCH_HAS_HUGETLB_PREFAULT_HOOK
+-#define hugetlb_prefault_arch_hook(mm) do { } while (0)
+-#else
+-void hugetlb_prefault_arch_hook(struct mm_struct *mm);
+-#endif
+-
+ #else /* !CONFIG_HUGETLB_PAGE */
+
+ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h
-index 4213182..85d1191 100644
+index 4213182..7244456 100644
--- a/include/linux/hw_random.h
+++ b/include/linux/hw_random.h
-@@ -44,15 +44,7 @@ struct hwrng {
+@@ -11,7 +11,6 @@
+
+ #ifndef LINUX_HWRANDOM_H_
+ #define LINUX_HWRANDOM_H_
+-#ifdef __KERNEL__
+
+ #include <linux/types.h>
+ #include <linux/list.h>
+@@ -44,15 +43,6 @@ struct hwrng {
/** Register a new Hardware Random Number Generator driver. */
extern int hwrng_register(struct hwrng *rng);
/** Unregister a Hardware Random Number Generator driver. */
@@ -813295,9 +1085313,10 @@
-{
- __hwrng_unregister(rng, true);
-}
+-
+-#endif /* __KERNEL__ */
+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
@@ -813351,10 +1085370,23 @@
#endif /* _LINUX_I2C_ALGO_PCA_H */
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
-index b979112..32eb8bb 100644
+index b979112..580acc9 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
-@@ -125,6 +125,7 @@
+@@ -79,12 +79,9 @@
+ #define I2C_DRIVERID_UPD64031A 79 /* upd64031a video processor */
+ #define I2C_DRIVERID_SAA717X 80 /* saa717x video encoder */
+ #define I2C_DRIVERID_DS1672 81 /* Dallas/Maxim DS1672 RTC */
+-#define I2C_DRIVERID_X1205 82 /* Xicor/Intersil X1205 RTC */
+-#define I2C_DRIVERID_PCF8563 83 /* Philips PCF8563 RTC */
+ #define I2C_DRIVERID_BT866 85 /* Conexant bt866 video encoder */
+ #define I2C_DRIVERID_KS0127 86 /* Samsung ks0127 video decoder */
+ #define I2C_DRIVERID_TLV320AIC23B 87 /* TI TLV320AIC23B audio codec */
+-#define I2C_DRIVERID_ISL1208 88 /* Intersil ISL1208 RTC */
+ #define I2C_DRIVERID_WM8731 89 /* Wolfson WM8731 audio codec */
+ #define I2C_DRIVERID_WM8750 90 /* Wolfson WM8750 audio codec */
+ #define I2C_DRIVERID_WM8753 91 /* Wolfson WM8753 audio codec */
+@@ -125,6 +122,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) */
@@ -813380,6 +1085412,56 @@
+};
+
+#endif /* I2C_PCA9564_PLATFORM_H */
+diff --git a/include/linux/i2c.h b/include/linux/i2c.h
+index 365e0df..cb63da5 100644
+--- a/include/linux/i2c.h
++++ b/include/linux/i2c.h
+@@ -126,7 +126,7 @@ struct i2c_driver {
+ * With the driver model, device enumeration is NEVER done by drivers;
+ * it's done by infrastructure. (NEW STYLE DRIVERS ONLY)
+ */
+- int (*probe)(struct i2c_client *);
++ int (*probe)(struct i2c_client *, const struct i2c_device_id *);
+ int (*remove)(struct i2c_client *);
+
+ /* driver model interfaces that don't relate to enumeration */
+@@ -140,11 +140,10 @@ struct i2c_driver {
+ int (*command)(struct i2c_client *client,unsigned int cmd, void *arg);
+
+ struct device_driver driver;
++ const struct i2c_device_id *id_table;
+ };
+ #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
+
+-#define I2C_NAME_SIZE 20
+-
+ /**
+ * struct i2c_client - represent an I2C slave device
+ * @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address;
+@@ -230,17 +229,17 @@ struct i2c_board_info {
+ };
+
+ /**
+- * I2C_BOARD_INFO - macro used to list an i2c device and its driver
+- * @driver: identifies the driver to use with the device
++ * I2C_BOARD_INFO - macro used to list an i2c device and its address
++ * @dev_type: identifies the device type
+ * @dev_addr: the device's address on the bus.
+ *
+ * This macro initializes essential fields of a struct i2c_board_info,
+ * declaring what has been provided on a particular board. Optional
+- * fields (such as the chip type, its associated irq, or device-specific
+- * platform_data) are provided using conventional syntax.
++ * fields (such as associated irq, or device-specific platform_data)
++ * are provided using conventional syntax.
+ */
+-#define I2C_BOARD_INFO(driver,dev_addr) \
+- .driver_name = (driver), .addr = (dev_addr)
++#define I2C_BOARD_INFO(dev_type,dev_addr) \
++ .type = (dev_type), .addr = (dev_addr)
+
+
+ /* Add-on boards should register/unregister their devices; e.g. a board
diff --git a/include/linux/i2c/tps65010.h b/include/linux/i2c/tps65010.h
index 7021635..918c535 100644
--- a/include/linux/i2c/tps65010.h
@@ -813421,10 +1085503,19 @@
#endif /* __LINUX_I2C_TPS65010_H */
diff --git a/include/linux/i2o.h b/include/linux/i2o.h
-index 7da5b98..e92170d 100644
+index 7da5b98..7d51cbc 100644
--- a/include/linux/i2o.h
+++ b/include/linux/i2o.h
-@@ -33,9 +33,9 @@
+@@ -18,8 +18,6 @@
+ #ifndef _I2O_H
+ #define _I2O_H
+
+-#ifdef __KERNEL__ /* This file to be included by kernel only */
+-
+ #include <linux/i2o-dev.h>
+
+ /* How many different OSM's are we allowing */
+@@ -33,9 +31,9 @@
#include <linux/mempool.h>
#include <linux/mutex.h>
#include <linux/scatterlist.h>
@@ -813435,6 +1085526,27 @@
/* message queue empty */
#define I2O_QUEUE_EMPTY 0xffffffff
+@@ -613,14 +611,9 @@ struct i2o_sys_tbl {
+ extern struct list_head i2o_controllers;
+
+ /* Message functions */
+-static inline struct i2o_message *i2o_msg_get(struct i2o_controller *);
+ extern struct i2o_message *i2o_msg_get_wait(struct i2o_controller *, int);
+-static inline void i2o_msg_post(struct i2o_controller *, struct i2o_message *);
+-static inline int i2o_msg_post_wait(struct i2o_controller *,
+- struct i2o_message *, unsigned long);
+ extern int i2o_msg_post_wait_mem(struct i2o_controller *, struct i2o_message *,
+ unsigned long, struct i2o_dma *);
+-static inline void i2o_flush_reply(struct i2o_controller *, u32);
+
+ /* IOP functions */
+ extern int i2o_status_get(struct i2o_controller *);
+@@ -1260,5 +1253,4 @@ extern void i2o_dump_message(struct i2o_message *);
+ extern void i2o_dump_hrt(struct i2o_controller *c);
+ extern void i2o_debug_state(struct i2o_controller *c);
+
+-#endif /* __KERNEL__ */
+ #endif /* _I2O_H */
diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h
index 7c5e981..0306744 100644
--- a/include/linux/icmpv6.h
@@ -813463,7 +1085575,7 @@
#endif
diff --git a/include/linux/ide.h b/include/linux/ide.h
-index bc26b2f..f20410d 100644
+index bc26b2f..b0135b0 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -23,7 +23,6 @@
@@ -813474,10 +1085586,37 @@
#include <asm/mutex.h>
#if defined(CONFIG_CRIS) || defined(CONFIG_FRV)
-@@ -82,24 +81,10 @@ typedef unsigned char byte; /* used everywhere */
+@@ -49,13 +48,6 @@ typedef unsigned char byte; /* used everywhere */
+ #define ERROR_RECAL 1 /* Recalibrate every 2nd retry */
+
+ /*
+- * Tune flags
+- */
+-#define IDE_TUNE_NOAUTO 2
+-#define IDE_TUNE_AUTO 1
+-#define IDE_TUNE_DEFAULT 0
+-
+-/*
+ * state flags
+ */
+
+@@ -69,37 +61,30 @@ typedef unsigned char byte; /* used everywhere */
+ */
+ #define IDE_NR_PORTS (10)
- #define IDE_FEATURE_OFFSET IDE_ERROR_OFFSET
- #define IDE_COMMAND_OFFSET IDE_STATUS_OFFSET
+-#define IDE_DATA_OFFSET (0)
+-#define IDE_ERROR_OFFSET (1)
+-#define IDE_NSECTOR_OFFSET (2)
+-#define IDE_SECTOR_OFFSET (3)
+-#define IDE_LCYL_OFFSET (4)
+-#define IDE_HCYL_OFFSET (5)
+-#define IDE_SELECT_OFFSET (6)
+-#define IDE_STATUS_OFFSET (7)
+-#define IDE_CONTROL_OFFSET (8)
+-#define IDE_IRQ_OFFSET (9)
+-
+-#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])
@@ -813496,10 +1085635,30 @@
-#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
++struct ide_io_ports {
++ unsigned long data_addr;
++
++ union {
++ unsigned long error_addr; /* read: error */
++ unsigned long feature_addr; /* write: feature */
++ };
++
++ unsigned long nsect_addr;
++ unsigned long lbal_addr;
++ unsigned long lbam_addr;
++ unsigned long lbah_addr;
++
++ unsigned long device_addr;
++
++ union {
++ unsigned long status_addr; /*  read: status  */
++ unsigned long command_addr; /* write: command */
++ };
++
++ unsigned long ctl_addr;
++
++ unsigned long irq_addr;
++};
#define OK_STAT(stat,good,bad) (((stat)&((good)|(bad)))==(good))
#define BAD_R_STAT (BUSY_STAT | ERR_STAT)
@@ -813512,7 +1085671,19 @@
};
typedef u8 hwif_chipset_t;
-@@ -185,15 +170,9 @@ typedef struct hw_regs_s {
+@@ -178,32 +163,30 @@ typedef u8 hwif_chipset_t;
+ * Structure to hold all information about the location of this port
+ */
+ typedef struct hw_regs_s {
+- unsigned long io_ports[IDE_NR_PORTS]; /* task file registers */
++ union {
++ struct ide_io_ports io_ports;
++ unsigned long io_ports_array[IDE_NR_PORTS];
++ };
++
+ int irq; /* our irq number */
+ ide_ack_intr_t *ack_intr; /* acknowledge interrupt */
+ hwif_chipset_t chipset;
struct device *dev;
} hw_regs_t;
@@ -813528,7 +1085699,20 @@
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,
+ {
+ unsigned int i;
+
+- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+- hw->io_ports[i] = io_addr++;
++ for (i = 0; i <= 7; i++)
++ hw->io_ports_array[i] = io_addr++;
+
+- hw->io_ports[IDE_CONTROL_OFFSET] = ctl_addr;
++ hw->io_ports.ctl_addr = ctl_addr;
+ }
+
+ #include <asm/ide.h>
+@@ -213,45 +196,6 @@ static inline void ide_std_init_ports(hw_regs_t *hw,
#define MAX_HWIFS CONFIG_IDE_MAX_HWIFS
#endif
@@ -813574,7 +1085758,15 @@
/* 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 {
+@@ -388,7 +332,6 @@ typedef struct ide_drive_s {
+ unsigned atapi_overlap : 1; /* ATAPI overlap (not supported) */
+ unsigned doorlocking : 1; /* for removable only: door lock/unlock works */
+ unsigned nodma : 1; /* disallow DMA */
+- unsigned autotune : 2; /* 0=default, 1=autotune, 2=noautotune */
+ unsigned remap_0_to_1 : 1; /* 0=noremap, 1=remap 0->1 (for EZDrive) */
+ unsigned blocked : 1; /* 1=powermanagment told us not to do anything, so sleep nicely */
+ unsigned vdma : 1; /* 1=doing PIO over DMA 0=doing normal DMA */
+@@ -406,7 +349,7 @@ typedef struct ide_drive_s {
u8 wcache; /* status of write cache */
u8 acoustic; /* acoustic management */
u8 media; /* disk, cdrom, tape, floppy, ... */
@@ -813583,23 +1085775,158 @@
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 *);
+@@ -447,6 +390,45 @@ typedef struct ide_drive_s {
+
+ struct ide_port_info;
+
++struct ide_port_ops {
++ /* host specific initialization of devices on a port */
++ void (*port_init_devs)(struct hwif_s *);
++ /* routine to program host for PIO mode */
++ void (*set_pio_mode)(ide_drive_t *, const u8);
++ /* routine to program host for DMA mode */
++ void (*set_dma_mode)(ide_drive_t *, const u8);
++ /* tweaks hardware to select drive */
++ void (*selectproc)(ide_drive_t *);
++ /* chipset polling based on hba specifics */
++ int (*reset_poll)(ide_drive_t *);
++ /* chipset specific changes to default for device-hba resets */
++ void (*pre_reset)(ide_drive_t *);
++ /* routine to reset controller after a disk reset */
++ void (*resetproc)(ide_drive_t *);
++ /* special host masking for drive selection */
++ void (*maskproc)(ide_drive_t *, int);
++ /* check host's drive quirk list */
++ void (*quirkproc)(ide_drive_t *);
++
++ u8 (*mdma_filter)(ide_drive_t *);
++ u8 (*udma_filter)(ide_drive_t *);
++
++ u8 (*cable_detect)(struct hwif_s *);
++};
++
++struct ide_dma_ops {
++ void (*dma_host_set)(struct ide_drive_s *, int);
++ int (*dma_setup)(struct ide_drive_s *);
++ void (*dma_exec_cmd)(struct ide_drive_s *, u8);
++ void (*dma_start)(struct ide_drive_s *);
++ int (*dma_end)(struct ide_drive_s *);
++ int (*dma_test_irq)(struct ide_drive_s *);
++ void (*dma_lost_irq)(struct ide_drive_s *);
++ void (*dma_timeout)(struct ide_drive_s *);
++};
++
++struct ide_task_s;
++
+ typedef struct hwif_s {
+ struct hwif_s *next; /* for linked-list in ide_hwgroup_t */
+ struct hwif_s *mate; /* other hwif from same PCI chip */
+@@ -455,8 +437,8 @@ typedef struct hwif_s {
+
+ char name[6]; /* name of interface, eg. "ide0" */
+
+- /* task file registers for pata and sata */
+- unsigned long io_ports[IDE_NR_PORTS];
++ struct ide_io_ports io_ports;
++
+ unsigned long sata_scr[SATA_NR_PORTS];
+
+ ide_drive_t drives[MAX_DRIVES]; /* drive info */
+@@ -480,67 +462,25 @@ typedef struct hwif_s {
+
+ struct device *dev;
+
+- const struct ide_port_info *cds; /* chipset device struct */
+-
+ ide_ack_intr_t *ack_intr;
+
+ void (*rw_disk)(ide_drive_t *, struct request *);
+
+-#if 0
+- ide_hwif_ops_t *hwifops;
+-#else
+- /* host specific initialization of devices on a port */
+- void (*port_init_devs)(struct hwif_s *);
+- /* routine to program host for PIO mode */
+- void (*set_pio_mode)(ide_drive_t *, const u8);
+- /* routine to program host for DMA mode */
+- void (*set_dma_mode)(ide_drive_t *, const u8);
+- /* tweaks hardware to select drive */
+- void (*selectproc)(ide_drive_t *);
+- /* chipset polling based on hba specifics */
+- int (*reset_poll)(ide_drive_t *);
+- /* chipset specific changes to default for device-hba resets */
+- void (*pre_reset)(ide_drive_t *);
+- /* routine to reset controller after a disk reset */
+- void (*resetproc)(ide_drive_t *);
+- /* special host masking for drive selection */
+- 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 {
+-#endif
+- u8 (*mdma_filter)(ide_drive_t *);
+- u8 (*udma_filter)(ide_drive_t *);
+-
+- u8 (*cable_detect)(struct hwif_s *);
++ const struct ide_port_ops *port_ops;
++ const struct ide_dma_ops *dma_ops;
+
+- void (*ata_input_data)(ide_drive_t *, void *, u32);
+- void (*ata_output_data)(ide_drive_t *, void *, u32);
++ void (*tf_load)(ide_drive_t *, struct ide_task_s *);
++ void (*tf_read)(ide_drive_t *, struct ide_task_s *);
+
+- void (*atapi_input_bytes)(ide_drive_t *, void *, u32);
+- void (*atapi_output_bytes)(ide_drive_t *, void *, u32);
++ void (*input_data)(ide_drive_t *, struct request *, void *, unsigned);
++ void (*output_data)(ide_drive_t *, struct request *, void *, unsigned);
+
+- void (*dma_host_set)(ide_drive_t *, int);
+- int (*dma_setup)(ide_drive_t *);
+- void (*dma_exec_cmd)(ide_drive_t *, u8);
+- void (*dma_start)(ide_drive_t *);
+- int (*ide_dma_end)(ide_drive_t *drive);
+- int (*ide_dma_test_irq)(ide_drive_t *drive);
+ void (*ide_dma_clear_irq)(ide_drive_t *drive);
+- void (*dma_lost_irq)(ide_drive_t *drive);
+- void (*dma_timeout)(ide_drive_t *drive);
+
+ void (*OUTB)(u8 addr, unsigned long port);
+ void (*OUTBSYNC)(ide_drive_t *drive, u8 addr, unsigned long port);
+- void (*OUTW)(u16 addr, unsigned long port);
+- void (*OUTSW)(unsigned long port, void *addr, u32 count);
+- void (*OUTSL)(unsigned long port, void *addr, u32 count);
+
+ u8 (*INB)(unsigned long port);
+- u16 (*INW)(unsigned long port);
+- void (*INSW)(unsigned long port, void *addr, u32 count);
+- void (*INSL)(unsigned long port, void *addr, u32 count);
+
+ /* dma physical region descriptor table (cpu view) */
+ unsigned int *dmatable_cpu;
+@@ -565,10 +505,7 @@ typedef struct hwif_s {
+
+ unsigned long dma_base; /* base addr for dma ports */
+ unsigned long dma_command; /* dma command register */
+- unsigned long dma_vendor1; /* dma vendor 1 register */
+ unsigned long dma_status; /* dma status register */
+- unsigned long dma_vendor3; /* dma vendor 3 register */
+- unsigned long dma_prdtable; /* actual prd table address */
+
+ unsigned long config_data; /* for use by chipset-specific code */
+ unsigned long select_data; /* for use by chipset-specific code */
+@@ -576,17 +513,15 @@ typedef struct hwif_s {
+ unsigned long extra_base; /* extra addr for dma ports */
+ unsigned extra_ports; /* number of extra dma ports */
- unsigned noprobe : 1; /* don't probe for this interface */
+- 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 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 */
@@ -813611,7 +1085938,16 @@
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);
+@@ -605,7 +540,7 @@ typedef ide_startstop_t (ide_handler_t)(ide_drive_t *);
+ typedef int (ide_expiry_t)(ide_drive_t *);
+
+ /* used by ide-cd, ide-floppy, etc. */
+-typedef void (xfer_func_t)(ide_drive_t *, void *, u32);
++typedef void (xfer_func_t)(ide_drive_t *, struct request *rq, void *, unsigned);
+
+ typedef struct hwgroup_s {
+ /* irq handler, if active */
+@@ -647,6 +582,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);
@@ -813680,7 +1086016,7 @@
#ifdef CONFIG_IDE_PROC_FS
/*
* configurable drive settings
-@@ -691,6 +691,7 @@ void proc_ide_create(void);
+@@ -691,6 +688,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 *);
@@ -813688,7 +1086024,18 @@
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) { ; }
+@@ -700,10 +698,6 @@ void ide_add_generic_settings(ide_drive_t *);
+ read_proc_t proc_ide_read_capacity;
+ read_proc_t proc_ide_read_geometry;
+
+-#ifdef CONFIG_BLK_DEV_IDEPCI
+-void ide_pci_create_host_proc(const char *, get_info_t *);
+-#endif
+-
+ /*
+ * Standard exit stuff:
+ */
+@@ -724,6 +718,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) { ; }
@@ -813696,10 +1086043,18 @@
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
+@@ -803,8 +798,21 @@ int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsig
+ #ifndef _IDE_C
+ extern ide_hwif_t ide_hwifs[]; /* master data repository */
+ #endif
++extern int ide_noacpi;
++extern int ide_acpigtf;
++extern int ide_acpionboot;
extern int noautodma;
++extern int ide_vlb_clk;
++extern int ide_pci_clk;
++
+ide_hwif_t *ide_find_port_slot(const struct ide_port_info *);
+
+static inline ide_hwif_t *ide_find_port(void)
@@ -813710,7 +1086065,28 @@
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 *);
+@@ -814,6 +822,10 @@ extern void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigne
+ void ide_execute_command(ide_drive_t *, u8, ide_handler_t *, unsigned int,
+ ide_expiry_t *);
+
++void ide_execute_pkt_cmd(ide_drive_t *);
++
++void ide_pad_transfer(ide_drive_t *, int, int);
++
+ ide_startstop_t __ide_error(ide_drive_t *, struct request *, u8, u8);
+
+ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat);
+@@ -950,8 +962,7 @@ typedef struct ide_task_s {
+ void *special; /* valid_t generally */
+ } ide_task_t;
+
+-void ide_tf_load(ide_drive_t *, ide_task_t *);
+-void ide_tf_read(ide_drive_t *, ide_task_t *);
++void ide_tf_dump(const char *, struct ide_taskfile *);
+
+ extern void SELECT_DRIVE(ide_drive_t *);
+ extern void SELECT_MASK(ide_drive_t *, int);
+@@ -990,7 +1001,6 @@ extern void do_ide_request(struct request_queue *);
void ide_init_disk(struct gendisk *, ide_drive_t *);
#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
@@ -813718,7 +1086094,26 @@
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 {
+@@ -1001,10 +1011,15 @@ void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, int, u8
+ void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *);
+
+ #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
+-void ide_hwif_setup_dma(ide_hwif_t *, const struct ide_port_info *);
++int ide_pci_set_master(struct pci_dev *, const char *);
++unsigned long ide_pci_dma_base(ide_hwif_t *, const struct ide_port_info *);
++int ide_hwif_setup_dma(ide_hwif_t *, const struct ide_port_info *);
+ #else
+-static inline void ide_hwif_setup_dma(ide_hwif_t *hwif,
+- const struct ide_port_info *d) { }
++static inline int ide_hwif_setup_dma(ide_hwif_t *hwif,
++ const struct ide_port_info *d)
++{
++ return -EINVAL;
++}
+ #endif
+
+ extern void default_hwif_iops(ide_hwif_t *);
+@@ -1024,8 +1039,8 @@ enum {
IDE_HFLAG_SINGLE = (1 << 1),
/* don't use legacy PIO blacklist */
IDE_HFLAG_PIO_NO_BLACKLIST = (1 << 2),
@@ -813729,7 +1086124,7 @@
/* 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 {
+@@ -1047,14 +1062,14 @@ enum {
IDE_HFLAG_VDMA = (1 << 11),
/* ATAPI DMA is unsupported */
IDE_HFLAG_NO_ATAPI_DMA = (1 << 12),
@@ -813740,16 +1086135,26 @@
/* 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 {
+ IDE_HFLAG_NO_AUTODMA = (1 << 15),
+- /* don't autotune PIO */
+- IDE_HFLAG_NO_AUTOTUNE = (1 << 16),
++ /* host uses MMIO */
++ IDE_HFLAG_MMIO = (1 << 16),
+ /* host is CS5510/CS5520 */
+ IDE_HFLAG_CS5520 = IDE_HFLAG_VDMA,
+ /* no LBA48 */
+@@ -1076,8 +1091,8 @@ 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),
++ /* serialize ports if DMA is possible (for sl82c105) */
++ IDE_HFLAG_SERIALIZE_DMA = (1 << 27),
/* force host out of "simplex" mode */
IDE_HFLAG_CLEAR_SIMPLEX = (1 << 28),
/* DSC overlap is unsupported */
-@@ -1089,9 +1095,9 @@ enum {
+@@ -1089,9 +1104,9 @@ enum {
};
#ifdef CONFIG_BLK_DEV_OFFBOARD
@@ -813761,25 +1086166,76 @@
#endif
struct ide_port_info {
-@@ -1195,7 +1201,7 @@ static inline void ide_acpi_set_state(ide_hwif_t *hwif, int on) {}
+@@ -1099,10 +1114,14 @@ struct ide_port_info {
+ unsigned int (*init_chipset)(struct pci_dev *, const char *);
+ void (*init_iops)(ide_hwif_t *);
+ void (*init_hwif)(ide_hwif_t *);
+- void (*init_dma)(ide_hwif_t *, unsigned long);
++ int (*init_dma)(ide_hwif_t *,
++ const struct ide_port_info *);
++
++ const struct ide_port_ops *port_ops;
++ const struct ide_dma_ops *dma_ops;
++
+ ide_pci_enablebit_t enablebits[2];
+ hwif_chipset_t chipset;
+- u8 extra;
+ u32 host_flags;
+ u8 pio_mask;
+ u8 swdma_mask;
+@@ -1149,13 +1168,16 @@ void ide_destroy_dmatable(ide_drive_t *);
+
+ #ifdef CONFIG_BLK_DEV_IDEDMA_SFF
+ extern int ide_build_dmatable(ide_drive_t *, struct request *);
+-extern int ide_release_dma(ide_hwif_t *);
+-extern void ide_setup_dma(ide_hwif_t *, unsigned long);
++int ide_allocate_dma_engine(ide_hwif_t *);
++void ide_release_dma_engine(ide_hwif_t *);
++void ide_setup_dma(ide_hwif_t *, unsigned long);
+
+ void ide_dma_host_set(ide_drive_t *, int);
+ extern int ide_dma_setup(ide_drive_t *);
++void ide_dma_exec_cmd(ide_drive_t *, u8);
+ extern void ide_dma_start(ide_drive_t *);
+ extern int __ide_dma_end(ide_drive_t *);
++int ide_dma_test_irq(ide_drive_t *);
+ extern void ide_dma_lost_irq(ide_drive_t *);
+ extern void ide_dma_timeout(ide_drive_t *);
+ #endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
+@@ -1173,7 +1195,7 @@ static inline void ide_check_dma_crc(ide_drive_t *drive) { ; }
+ #endif /* CONFIG_BLK_DEV_IDEDMA */
+
+ #ifndef CONFIG_BLK_DEV_IDEDMA_SFF
+-static inline void ide_release_dma(ide_hwif_t *drive) {;}
++static inline void ide_release_dma_engine(ide_hwif_t *hwif) { ; }
+ #endif
+
+ #ifdef CONFIG_BLK_DEV_IDEACPI
+@@ -1193,17 +1215,20 @@ static inline void ide_acpi_set_state(ide_hwif_t *hwif, int on) {}
+ #endif
+
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);
+-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_unregister(ide_hwif_t *);
void ide_register_region(struct gendisk *);
void ide_unregister_region(struct gendisk *);
-@@ -1204,6 +1210,8 @@ void ide_undecoded_slave(ide_drive_t *);
+ void ide_undecoded_slave(ide_drive_t *);
+
++void ide_port_apply_params(ide_hwif_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 *);
++int ide_legacy_device_add(const struct ide_port_info *, unsigned long);
+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;
+@@ -1279,6 +1304,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;
@@ -813787,45 +1086243,60 @@
/* 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)
+@@ -1307,28 +1333,29 @@ 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]);
++ hwif->OUTB(drive->ctl | (on ? 0 : 2), hwif->io_ports.ctl_addr);
}
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]);
+ {
+ ide_hwif_t *hwif = drive->hwif;
+
+- return hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
++ return hwif->INB(hwif->io_ports.status_addr);
}
-+/*
-+ * 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]);
-+}
-+
+ static inline u8 ide_read_altstatus(ide_drive_t *drive)
+ {
+ ide_hwif_t *hwif = drive->hwif;
+
+- return hwif->INB(hwif->io_ports[IDE_CONTROL_OFFSET]);
++ return hwif->INB(hwif->io_ports.ctl_addr);
+ }
+
+ static inline u8 ide_read_error(ide_drive_t *drive)
+ {
+ ide_hwif_t *hwif = drive->hwif;
+
+- return hwif->INB(hwif->io_ports[IDE_ERROR_OFFSET]);
++ return hwif->INB(hwif->io_ports.error_addr);
+ }
+-
#endif /* _IDE_H */
+diff --git a/include/linux/idr.h b/include/linux/idr.h
+index 0edda41..9a2d762 100644
+--- a/include/linux/idr.h
++++ b/include/linux/idr.h
+@@ -14,6 +14,7 @@
+
+ #include <linux/types.h>
+ #include <linux/bitops.h>
++#include <linux/init.h>
+
+ #if BITS_PER_LONG == 32
+ # define IDR_BITS 5
+@@ -115,4 +116,6 @@ void ida_remove(struct ida *ida, int id);
+ void ida_destroy(struct ida *ida);
+ void ida_init(struct ida *ida);
+
++void __init idr_init_cache(void);
++
+ #endif /* __IDR_H__ */
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index f577c8f..529f301 100644
--- a/include/linux/ieee80211.h
@@ -813916,6 +1086387,20 @@
#endif
#endif /* _LINUX_IF_ARP_H */
+diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
+index 0d9d7ea..5f200ba 100644
+--- a/include/linux/if_macvlan.h
++++ b/include/linux/if_macvlan.h
+@@ -1,9 +1,6 @@
+ #ifndef _LINUX_IF_MACVLAN_H
+ #define _LINUX_IF_MACVLAN_H
+
+-#ifdef __KERNEL__
+-
+ extern struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *);
+
+-#endif /* __KERNEL__ */
+ #endif /* _LINUX_IF_MACVLAN_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
@@ -814233,6 +1086718,22 @@
+ * (reserved) 209
+ */
#endif
+diff --git a/include/linux/inet.h b/include/linux/inet.h
+index 675a7db..1354080 100644
+--- a/include/linux/inet.h
++++ b/include/linux/inet.h
+@@ -42,11 +42,9 @@
+ #ifndef _LINUX_INET_H
+ #define _LINUX_INET_H
+
+-#ifdef __KERNEL__
+ #include <linux/types.h>
+
+ extern __be32 in_aton(const char *str);
+ extern int in4_pton(const char *src, int srclen, u8 *dst, int delim, const char **end);
+ extern int in6_pton(const char *src, int srclen, u8 *dst, int delim, const char **end);
+-#endif
+ #endif /* _LINUX_INET_H */
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index fc4e3db..7009b0c 100644
--- a/include/linux/inetdevice.h
@@ -814263,11 +1086764,32 @@
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.h b/include/linux/init.h
+index fb58c04..21d658c 100644
+--- a/include/linux/init.h
++++ b/include/linux/init.h
+@@ -147,6 +147,8 @@ extern unsigned int reset_devices;
+ void setup_arch(char **);
+ void prepare_namespace(void);
+
++extern void (*late_time_init)(void);
++
+ #endif
+
+ #ifndef MODULE
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
-index 1f74e1d..37a6f5b 100644
+index 1f74e1d..bf6b8a6 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
-@@ -151,6 +151,9 @@ extern struct group_info init_groups;
+@@ -9,6 +9,7 @@
+ #include <linux/ipc.h>
+ #include <linux/pid_namespace.h>
+ #include <linux/user_namespace.h>
++#include <linux/securebits.h>
+ #include <net/net_namespace.h>
+
+ #define INIT_FDTABLE \
+@@ -151,6 +152,9 @@ extern struct group_info init_groups;
.cpus_allowed = CPU_MASK_ALL, \
.mm = NULL, \
.active_mm = &init_mm, \
@@ -814277,6 +1086799,15 @@
.rt = { \
.run_list = LIST_HEAD_INIT(tsk.rt.run_list), \
.time_slice = HZ, \
+@@ -169,7 +173,7 @@ extern struct group_info init_groups;
+ .cap_inheritable = CAP_INIT_INH_SET, \
+ .cap_permitted = CAP_FULL_SET, \
+ .cap_bset = CAP_INIT_BSET, \
+- .keep_capabilities = 0, \
++ .securebits = SECUREBITS_DEFAULT, \
+ .user = INIT_USER, \
+ .comm = "swapper", \
+ .thread = INIT_THREAD, \
diff --git a/include/linux/input.h b/include/linux/input.h
index cae2c35..28a094f 100644
--- a/include/linux/input.h
@@ -814308,7 +1086839,7 @@
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
+index f8ab4ce..f1fc747 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -102,6 +102,25 @@ extern void disable_irq_nosync(unsigned int irq);
@@ -814337,6 +1086868,30 @@
#ifdef CONFIG_GENERIC_HARDIRQS
/*
* Special lockdep variants of irq disabling/enabling.
+@@ -270,6 +289,7 @@ struct softirq_action
+ };
+
+ asmlinkage void do_softirq(void);
++asmlinkage void __do_softirq(void);
+ extern void open_softirq(int nr, void (*action)(struct softirq_action*), void *data);
+ extern void softirq_init(void);
+ #define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
+diff --git a/include/linux/io.h b/include/linux/io.h
+index e3b2dda..3a03a36 100644
+--- a/include/linux/io.h
++++ b/include/linux/io.h
+@@ -58,9 +58,9 @@ static inline void devm_ioport_unmap(struct device *dev, void __iomem *addr)
+ }
+ #endif
+
+-void __iomem * devm_ioremap(struct device *dev, unsigned long offset,
++void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
+ unsigned long size);
+-void __iomem * devm_ioremap_nocache(struct device *dev, unsigned long offset,
++void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
+ unsigned long size);
+ void devm_iounmap(struct device *dev, void __iomem *addr);
+ int check_signature(const volatile void __iomem *io_addr,
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 605d237..d5d40a9 100644
--- a/include/linux/ioport.h
@@ -814360,6 +1086915,335 @@
/* Convenience shorthand with allocation */
#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name))
+diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
+index e4451d1..ea6c18a 100644
+--- a/include/linux/ipc_namespace.h
++++ b/include/linux/ipc_namespace.h
+@@ -4,6 +4,17 @@
+ #include <linux/err.h>
+ #include <linux/idr.h>
+ #include <linux/rwsem.h>
++#include <linux/notifier.h>
++
++/*
++ * ipc namespace events
++ */
++#define IPCNS_MEMCHANGED 0x00000001 /* Notify lowmem size changed */
++#define IPCNS_CREATED 0x00000002 /* Notify new ipc namespace created */
++#define IPCNS_REMOVED 0x00000003 /* Notify ipc namespace removed */
++
++#define IPCNS_CALLBACK_PRI 0
++
+
+ struct ipc_ids {
+ int in_use;
+@@ -30,15 +41,24 @@ struct ipc_namespace {
+ size_t shm_ctlall;
+ int shm_ctlmni;
+ int shm_tot;
++
++ struct notifier_block ipcns_nb;
+ };
+
+ extern struct ipc_namespace init_ipc_ns;
++extern atomic_t nr_ipc_ns;
+
+ #ifdef CONFIG_SYSVIPC
+ #define INIT_IPC_NS(ns) .ns = &init_ipc_ns,
+-#else
++
++extern int register_ipcns_notifier(struct ipc_namespace *);
++extern int cond_register_ipcns_notifier(struct ipc_namespace *);
++extern int unregister_ipcns_notifier(struct ipc_namespace *);
++extern int ipcns_notify(unsigned long);
++
++#else /* CONFIG_SYSVIPC */
+ #define INIT_IPC_NS(ns)
+-#endif
++#endif /* CONFIG_SYSVIPC */
+
+ #if defined(CONFIG_SYSVIPC) && defined(CONFIG_IPC_NS)
+ extern void free_ipc_ns(struct kref *kref);
+diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h
+index c5bd28b..7ebdb4f 100644
+--- a/include/linux/ipmi.h
++++ b/include/linux/ipmi.h
+@@ -64,7 +64,7 @@
+ * applications and another for userland applications. The
+ * capabilities are basically the same for both interface, although
+ * the interfaces are somewhat different. The stuff in the
+- * #ifdef KERNEL below is the in-kernel interface. The userland
++ * #ifdef __KERNEL__ below is the in-kernel interface. The userland
+ * interface is defined later in the file. */
+
+
+@@ -75,8 +75,7 @@
+ * work for sockets.
+ */
+ #define IPMI_MAX_ADDR_SIZE 32
+-struct ipmi_addr
+-{
++struct ipmi_addr {
+ /* Try to take these from the "Channel Medium Type" table
+ in section 6.5 of the IPMI 1.5 manual. */
+ int addr_type;
+@@ -90,8 +89,7 @@ struct ipmi_addr
+ * 0), or IPMC_BMC_CHANNEL if communicating directly with the BMC.
+ */
+ #define IPMI_SYSTEM_INTERFACE_ADDR_TYPE 0x0c
+-struct ipmi_system_interface_addr
+-{
++struct ipmi_system_interface_addr {
+ int addr_type;
+ short channel;
+ unsigned char lun;
+@@ -100,10 +98,9 @@ struct ipmi_system_interface_addr
+ /* An IPMB Address. */
+ #define IPMI_IPMB_ADDR_TYPE 0x01
+ /* Used for broadcast get device id as described in section 17.9 of the
+- IPMI 1.5 manual. */
++ IPMI 1.5 manual. */
+ #define IPMI_IPMB_BROADCAST_ADDR_TYPE 0x41
+-struct ipmi_ipmb_addr
+-{
++struct ipmi_ipmb_addr {
+ int addr_type;
+ short channel;
+ unsigned char slave_addr;
+@@ -128,8 +125,7 @@ struct ipmi_ipmb_addr
+ * message is a little weird, but this is required.
+ */
+ #define IPMI_LAN_ADDR_TYPE 0x04
+-struct ipmi_lan_addr
+-{
++struct ipmi_lan_addr {
+ int addr_type;
+ short channel;
+ unsigned char privilege;
+@@ -162,16 +158,14 @@ struct ipmi_lan_addr
+ * byte of data in the response (as the spec shows the messages laid
+ * out).
+ */
+-struct ipmi_msg
+-{
++struct ipmi_msg {
+ unsigned char netfn;
+ unsigned char cmd;
+ unsigned short data_len;
+ unsigned char __user *data;
+ };
+
+-struct kernel_ipmi_msg
+-{
++struct kernel_ipmi_msg {
+ unsigned char netfn;
+ unsigned char cmd;
+ unsigned short data_len;
+@@ -239,12 +233,11 @@ typedef struct ipmi_user *ipmi_user_t;
+ * used after the message is delivered, so the upper layer may use the
+ * link to build a linked list, if it likes.
+ */
+-struct ipmi_recv_msg
+-{
++struct ipmi_recv_msg {
+ struct list_head link;
+
+ /* The type of message as defined in the "Receive Types"
+- defines above. */
++ defines above. */
+ int recv_type;
+
+ ipmi_user_t user;
+@@ -271,9 +264,8 @@ struct ipmi_recv_msg
+ /* Allocate and free the receive message. */
+ void ipmi_free_recv_msg(struct ipmi_recv_msg *msg);
+
+-struct ipmi_user_hndl
+-{
+- /* Routine type to call when a message needs to be routed to
++struct ipmi_user_hndl {
++ /* Routine type to call when a message needs to be routed to
+ the upper layer. This will be called with some locks held,
+ the only IPMI routines that can be called are ipmi_request
+ and the alloc/free operations. The handler_data is the
+@@ -368,9 +360,8 @@ int ipmi_request_supply_msgs(ipmi_user_t user,
+ * Poll the IPMI interface for the user. This causes the IPMI code to
+ * do an immediate check for information from the driver and handle
+ * anything that is immediately pending. This will not block in any
+- * way. This is useful if you need to implement polling from the user
+- * for things like modifying the watchdog timeout when a panic occurs
+- * or disabling the watchdog timer on a reboot.
++ * way. This is useful if you need to spin waiting for something to
++ * happen in the IPMI driver.
+ */
+ void ipmi_poll_interface(ipmi_user_t user);
+
+@@ -422,12 +413,6 @@ int ipmi_get_maintenance_mode(ipmi_user_t user);
+ int ipmi_set_maintenance_mode(ipmi_user_t user, int mode);
+
+ /*
+- * Allow run-to-completion mode to be set for the interface of
+- * a specific user.
+- */
+-void ipmi_user_set_run_to_completion(ipmi_user_t user, int val);
+-
+-/*
+ * When the user is created, it will not receive IPMI events by
+ * default. The user must set this to TRUE to get incoming events.
+ * The first user that sets this to TRUE will receive all events that
+@@ -440,8 +425,7 @@ int ipmi_set_gets_events(ipmi_user_t user, int val);
+ * every existing interface when a new watcher is registered with
+ * ipmi_smi_watcher_register().
+ */
+-struct ipmi_smi_watcher
+-{
++struct ipmi_smi_watcher {
+ struct list_head link;
+
+ /* You must set the owner to the current module, if you are in
+@@ -512,8 +496,7 @@ int ipmi_validate_addr(struct ipmi_addr *addr, int len);
+
+
+ /* Messages sent to the interface are this format. */
+-struct ipmi_req
+-{
++struct ipmi_req {
+ unsigned char __user *addr; /* Address to send the message to. */
+ unsigned int addr_len;
+
+@@ -538,12 +521,11 @@ struct ipmi_req
+
+ /* Messages sent to the interface with timing parameters are this
+ format. */
+-struct ipmi_req_settime
+-{
++struct ipmi_req_settime {
+ struct ipmi_req req;
+
+ /* See ipmi_request_settime() above for details on these
+- values. */
++ values. */
+ int retries;
+ unsigned int retry_time_ms;
+ };
+@@ -560,8 +542,7 @@ struct ipmi_req_settime
+ struct ipmi_req_settime)
+
+ /* Messages received from the interface are this format. */
+-struct ipmi_recv
+-{
++struct ipmi_recv {
+ int recv_type; /* Is this a command, response or an
+ asyncronous event. */
+
+@@ -607,13 +588,12 @@ struct ipmi_recv
+ struct ipmi_recv)
+
+ /* Register to get commands from other entities on this interface. */
+-struct ipmi_cmdspec
+-{
++struct ipmi_cmdspec {
+ unsigned char netfn;
+ unsigned char cmd;
+ };
+
+-/*
++/*
+ * Register to receive a specific command. error values:
+ * - EFAULT - an address supplied was invalid.
+ * - EBUSY - The netfn/cmd supplied was already in use.
+@@ -636,8 +616,7 @@ struct ipmi_cmdspec
+ * else. The chans field is a bitmask, (1 << channel) for each channel.
+ * It may be IPMI_CHAN_ALL for all channels.
+ */
+-struct ipmi_cmdspec_chans
+-{
++struct ipmi_cmdspec_chans {
+ unsigned int netfn;
+ unsigned int cmd;
+ unsigned int chans;
+@@ -659,7 +638,7 @@ struct ipmi_cmdspec_chans
+ #define IPMICTL_UNREGISTER_FOR_CMD_CHANS _IOR(IPMI_IOC_MAGIC, 29, \
+ struct ipmi_cmdspec_chans)
+
+-/*
++/*
+ * Set whether this interface receives events. Note that the first
+ * user registered for events will get all pending events for the
+ * interface. error values:
+@@ -675,15 +654,18 @@ struct ipmi_cmdspec_chans
+ * things it takes to determine your address (if not the BMC) and set
+ * it for everyone else. You should probably leave the LUN alone.
+ */
+-struct ipmi_channel_lun_address_set
+-{
++struct ipmi_channel_lun_address_set {
+ unsigned short channel;
+ unsigned char value;
+ };
+-#define IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 24, struct ipmi_channel_lun_address_set)
+-#define IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 25, struct ipmi_channel_lun_address_set)
+-#define IPMICTL_SET_MY_CHANNEL_LUN_CMD _IOR(IPMI_IOC_MAGIC, 26, struct ipmi_channel_lun_address_set)
+-#define IPMICTL_GET_MY_CHANNEL_LUN_CMD _IOR(IPMI_IOC_MAGIC, 27, struct ipmi_channel_lun_address_set)
++#define IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD \
++ _IOR(IPMI_IOC_MAGIC, 24, struct ipmi_channel_lun_address_set)
++#define IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD \
++ _IOR(IPMI_IOC_MAGIC, 25, struct ipmi_channel_lun_address_set)
++#define IPMICTL_SET_MY_CHANNEL_LUN_CMD \
++ _IOR(IPMI_IOC_MAGIC, 26, struct ipmi_channel_lun_address_set)
++#define IPMICTL_GET_MY_CHANNEL_LUN_CMD \
++ _IOR(IPMI_IOC_MAGIC, 27, struct ipmi_channel_lun_address_set)
+ /* Legacy interfaces, these only set IPMB 0. */
+ #define IPMICTL_SET_MY_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 17, unsigned int)
+ #define IPMICTL_GET_MY_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 18, unsigned int)
+@@ -694,8 +676,7 @@ struct ipmi_channel_lun_address_set
+ * Get/set the default timing values for an interface. You shouldn't
+ * generally mess with these.
+ */
+-struct ipmi_timing_parms
+-{
++struct ipmi_timing_parms {
+ int retries;
+ unsigned int retry_time_ms;
+ };
+diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h
+index 6e8cec5..62b7366 100644
+--- a/include/linux/ipmi_smi.h
++++ b/include/linux/ipmi_smi.h
+@@ -60,8 +60,7 @@ typedef struct ipmi_smi *ipmi_smi_t;
+ * asynchronous data and messages and request them from the
+ * interface.
+ */
+-struct ipmi_smi_msg
+-{
++struct ipmi_smi_msg {
+ struct list_head link;
+
+ long msgid;
+@@ -74,12 +73,11 @@ struct ipmi_smi_msg
+ unsigned char rsp[IPMI_MAX_MSG_LENGTH];
+
+ /* Will be called when the system is done with the message
+- (presumably to free it). */
++ (presumably to free it). */
+ void (*done)(struct ipmi_smi_msg *msg);
+ };
+
+-struct ipmi_smi_handlers
+-{
++struct ipmi_smi_handlers {
+ struct module *owner;
+
+ /* The low-level interface cannot start sending messages to
+@@ -231,7 +229,7 @@ static inline void ipmi_free_smi_msg(struct ipmi_smi_msg *msg)
+ directory for this interface. Note that the entry will
+ automatically be dstroyed when the interface is destroyed. */
+ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
+- read_proc_t *read_proc, write_proc_t *write_proc,
++ read_proc_t *read_proc,
+ void *data, struct module *owner);
+
+ #endif /* __LINUX_IPMI_SMI_H */
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 134c8e5..10b666b 100644
--- a/include/linux/ipv6.h
@@ -814514,6 +1087398,27 @@
})
#define irqs_disabled_flags(flags) raw_irqs_disabled_flags(flags)
+diff --git a/include/linux/isapnp.h b/include/linux/isapnp.h
+index 1e8728a..cd5a269 100644
+--- a/include/linux/isapnp.h
++++ b/include/linux/isapnp.h
+@@ -26,16 +26,6 @@
+ #include <linux/pnp.h>
+
+ /*
+- * Configuration registers (TODO: change by specification)
+- */
+-
+-#define ISAPNP_CFG_ACTIVATE 0x30 /* byte */
+-#define ISAPNP_CFG_MEM 0x40 /* 4 * dword */
+-#define ISAPNP_CFG_PORT 0x60 /* 8 * word */
+-#define ISAPNP_CFG_IRQ 0x70 /* 2 * word */
+-#define ISAPNP_CFG_DMA 0x74 /* 2 * byte */
+-
+-/*
+ *
+ */
+
diff --git a/include/linux/iscsi_ibft.h b/include/linux/iscsi_ibft.h
new file mode 100644
index 0000000..6092487
@@ -814589,6 +1087494,29 @@
/* New ioctl-codes */
#define IIOCNETAIF _IO('I',1)
+diff --git a/include/linux/isicom.h b/include/linux/isicom.h
+index 8f4c717..bbd4219 100644
+--- a/include/linux/isicom.h
++++ b/include/linux/isicom.h
+@@ -1,11 +1,6 @@
+ #ifndef _LINUX_ISICOM_H
+ #define _LINUX_ISICOM_H
+
+-/*#define ISICOM_DEBUG*/
+-/*#define ISICOM_DEBUG_DTR_RTS*/
+-
+-#ifdef __KERNEL__
+-
+ #define YES 1
+ #define NO 0
+
+@@ -85,6 +80,4 @@
+
+ #define ISI_TXOK 0x0001
+
+-#endif /* __KERNEL__ */
+-
+ #endif /* ISICOM_H */
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index 423f582..07a9b52 100644
--- a/include/linux/jbd.h
@@ -814651,11 +1087579,58 @@
* Have the 32 bit jiffies value wrap 5 minutes after boot
* so jiffies wrap bugs show up earlier.
*/
+diff --git a/include/linux/kbuild.h b/include/linux/kbuild.h
+new file mode 100644
+index 0000000..22a7219
+--- /dev/null
++++ b/include/linux/kbuild.h
+@@ -0,0 +1,15 @@
++#ifndef __LINUX_KBUILD_H
++#define __LINUX_KBUILD_H
++
++#define DEFINE(sym, val) \
++ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
++
++#define BLANK() asm volatile("\n->" : : )
++
++#define OFFSET(sym, str, mem) \
++ DEFINE(sym, offsetof(struct str, mem))
++
++#define COMMENT(x) \
++ asm volatile("\n->#" x)
++
++#endif
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
-index 2df44e7..cd6d02c 100644
+index 2df44e7..4d46e29 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,
+@@ -20,6 +20,9 @@
+ extern const char linux_banner[];
+ extern const char linux_proc_banner[];
+
++#define USHORT_MAX ((u16)(~0U))
++#define SHORT_MAX ((s16)(USHORT_MAX>>1))
++#define SHORT_MIN (-SHORT_MAX - 1)
+ #define INT_MAX ((int)(~0U>>1))
+ #define INT_MIN (-INT_MAX - 1)
+ #define UINT_MAX (~0U)
+@@ -188,6 +191,7 @@ extern int log_buf_copy(char *dest, int idx, int len);
+ extern int printk_ratelimit_jiffies;
+ extern int printk_ratelimit_burst;
+ extern int printk_ratelimit(void);
++extern int __ratelimit(int ratelimit_jiffies, int ratelimit_burst);
+ extern int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst);
+ extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
+ unsigned int interval_msec);
+@@ -255,6 +259,7 @@ extern enum system_states {
+ #define TAINT_USER (1<<6)
+ #define TAINT_DIE (1<<7)
+ #define TAINT_OVERRIDDEN_ACPI_TABLE (1<<8)
++#define TAINT_WARN (1<<9)
+
+ extern void dump_stack(void) __cold;
+
+@@ -293,10 +298,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
@@ -814668,6 +1087643,114 @@
#endif
/*
+@@ -335,33 +338,90 @@ static inline int __attribute__ ((format (printf, 1, 2))) pr_debug(const char *
+ #endif /* __LITTLE_ENDIAN */
+
+ /*
+- * min()/max() macros that also do
++ * min()/max()/clamp() macros that also do
+ * strict type-checking.. See the
+ * "unnecessary" pointer comparison.
+ */
+-#define min(x,y) ({ \
+- typeof(x) _x = (x); \
+- typeof(y) _y = (y); \
+- (void) (&_x == &_y); \
+- _x < _y ? _x : _y; })
+-
+-#define max(x,y) ({ \
+- typeof(x) _x = (x); \
+- typeof(y) _y = (y); \
+- (void) (&_x == &_y); \
+- _x > _y ? _x : _y; })
++#define min(x, y) ({ \
++ typeof(x) _min1 = (x); \
++ typeof(y) _min2 = (y); \
++ (void) (&_min1 == &_min2); \
++ _min1 < _min2 ? _min1 : _min2; })
++
++#define max(x, y) ({ \
++ typeof(x) _max1 = (x); \
++ typeof(y) _max2 = (y); \
++ (void) (&_max1 == &_max2); \
++ _max1 > _max2 ? _max1 : _max2; })
++
++/**
++ * clamp - return a value clamped to a given range with strict typechecking
++ * @val: current value
++ * @min: minimum allowable value
++ * @max: maximum allowable value
++ *
++ * This macro does strict typechecking of min/max to make sure they are of the
++ * same type as val. See the unnecessary pointer comparisons.
++ */
++#define clamp(val, min, max) ({ \
++ typeof(val) __val = (val); \
++ typeof(min) __min = (min); \
++ typeof(max) __max = (max); \
++ (void) (&__val == &__min); \
++ (void) (&__val == &__max); \
++ __val = __val < __min ? __min: __val; \
++ __val > __max ? __max: __val; })
+
+ /*
+ * ..and if you can't take the strict
+ * types, you can specify one yourself.
+ *
+- * Or not use min/max at all, of course.
++ * Or not use min/max/clamp at all, of course.
+ */
+-#define min_t(type,x,y) \
+- ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+-#define max_t(type,x,y) \
+- ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
++#define min_t(type, x, y) ({ \
++ type __min1 = (x); \
++ type __min2 = (y); \
++ __min1 < __min2 ? __min1: __min2; })
++
++#define max_t(type, x, y) ({ \
++ type __max1 = (x); \
++ type __max2 = (y); \
++ __max1 > __max2 ? __max1: __max2; })
+
++/**
++ * clamp_t - return a value clamped to a given range using a given type
++ * @type: the type of variable to use
++ * @val: current value
++ * @min: minimum allowable value
++ * @max: maximum allowable value
++ *
++ * This macro does no typechecking and uses temporary variables of type
++ * 'type' to make all the comparisons.
++ */
++#define clamp_t(type, val, min, max) ({ \
++ type __val = (val); \
++ type __min = (min); \
++ type __max = (max); \
++ __val = __val < __min ? __min: __val; \
++ __val > __max ? __max: __val; })
++
++/**
++ * clamp_val - return a value clamped to a given range using val's type
++ * @val: current value
++ * @min: minimum allowable value
++ * @max: maximum allowable value
++ *
++ * This macro does no typechecking and uses temporary variables of whatever
++ * type the input argument 'val' is. This is useful when val is an unsigned
++ * type and min and max are literals that will otherwise be assigned a signed
++ * integer type.
++ */
++#define clamp_val(val, min, max) ({ \
++ typeof(val) __val = (val); \
++ typeof(val) __min = (min); \
++ typeof(val) __max = (max); \
++ __val = __val < __min ? __min: __val; \
++ __val > __max ? __max: __val; })
+
+ /**
+ * container_of - cast a member of a structure out to the containing structure
diff --git a/include/linux/kernelcapi.h b/include/linux/kernelcapi.h
index 8c4350a..a53e932 100644
--- a/include/linux/kernelcapi.h
@@ -814680,6 +1087763,100 @@
#define KCI_CONTRUP 0 /* arg: struct capi_profile */
#define KCI_CONTRDOWN 1 /* arg: NULL */
+diff --git a/include/linux/key.h b/include/linux/key.h
+index a70b8a8..c45c962 100644
+--- a/include/linux/key.h
++++ b/include/linux/key.h
+@@ -19,6 +19,7 @@
+ #include <linux/list.h>
+ #include <linux/rbtree.h>
+ #include <linux/rcupdate.h>
++#include <linux/sysctl.h>
+ #include <asm/atomic.h>
+
+ #ifdef __KERNEL__
+@@ -67,6 +68,8 @@ struct key;
+ #define KEY_OTH_SETATTR 0x00000020
+ #define KEY_OTH_ALL 0x0000003f
+
++#define KEY_PERM_UNDEF 0xffffffff
++
+ struct seq_file;
+ struct user_struct;
+ struct signal_struct;
+@@ -208,16 +211,19 @@ extern struct key *request_key(struct key_type *type,
+
+ extern struct key *request_key_with_auxdata(struct key_type *type,
+ const char *description,
+- const char *callout_info,
++ const void *callout_info,
++ size_t callout_len,
+ void *aux);
+
+ extern struct key *request_key_async(struct key_type *type,
+ const char *description,
+- const char *callout_info);
++ const void *callout_info,
++ size_t callout_len);
+
+ extern struct key *request_key_async_with_auxdata(struct key_type *type,
+ const char *description,
+- const char *callout_info,
++ const void *callout_info,
++ size_t callout_len,
+ void *aux);
+
+ extern int wait_for_key_construction(struct key *key, bool intr);
+@@ -229,6 +235,7 @@ extern key_ref_t key_create_or_update(key_ref_t keyring,
+ const char *description,
+ const void *payload,
+ size_t plen,
++ key_perm_t perm,
+ unsigned long flags);
+
+ extern int key_update(key_ref_t key,
+@@ -257,14 +264,18 @@ extern int keyring_add_key(struct key *keyring,
+
+ extern struct key *key_lookup(key_serial_t id);
+
+-#define key_serial(key) ((key) ? (key)->serial : 0)
++static inline key_serial_t key_serial(struct key *key)
++{
++ return key ? key->serial : 0;
++}
++
++#ifdef CONFIG_SYSCTL
++extern ctl_table key_sysctls[];
++#endif
+
+ /*
+ * the userspace interface
+ */
+-extern struct key root_user_keyring, root_session_keyring;
+-extern int alloc_uid_keyring(struct user_struct *user,
+- struct task_struct *ctx);
+ extern void switch_uid_keyring(struct user_struct *new_user);
+ extern int copy_keys(unsigned long clone_flags, struct task_struct *tsk);
+ extern int copy_thread_group_keys(struct task_struct *tsk);
+@@ -293,7 +304,6 @@ extern void key_init(void);
+ #define make_key_ref(k, p) ({ NULL; })
+ #define key_ref_to_ptr(k) ({ NULL; })
+ #define is_key_possessed(k) 0
+-#define alloc_uid_keyring(u,c) 0
+ #define switch_uid_keyring(u) do { } while(0)
+ #define __install_session_keyring(t, k) ({ NULL; })
+ #define copy_keys(f,t) 0
+@@ -306,10 +316,6 @@ extern void key_init(void);
+ #define key_fsgid_changed(t) do { } while(0)
+ #define key_init() do { } while(0)
+
+-/* Initial keyrings */
+-extern struct key root_user_keyring;
+-extern struct key root_session_keyring;
+-
+ #endif /* CONFIG_KEYS */
+ #endif /* __KERNEL__ */
+ #endif /* _LINUX_KEY_H */
diff --git a/include/linux/keyboard.h b/include/linux/keyboard.h
index 65c2d70..a3c984d 100644
--- a/include/linux/keyboard.h
@@ -814692,6 +1087869,38 @@
unsigned int value; /* keycode, unicode value or keysym */
};
+diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h
+index 3365945..656ee6b 100644
+--- a/include/linux/keyctl.h
++++ b/include/linux/keyctl.h
+@@ -49,5 +49,6 @@
+ #define KEYCTL_SET_REQKEY_KEYRING 14 /* set default request-key keyring */
+ #define KEYCTL_SET_TIMEOUT 15 /* set key timeout */
+ #define KEYCTL_ASSUME_AUTHORITY 16 /* assume request_key() authorisation */
++#define KEYCTL_GET_SECURITY 17 /* get key security label */
+
+ #endif /* _LINUX_KEYCTL_H */
+diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h
+index 404f446..29f62e1 100644
+--- a/include/linux/kfifo.h
++++ b/include/linux/kfifo.h
+@@ -21,8 +21,6 @@
+ #ifndef _LINUX_KFIFO_H
+ #define _LINUX_KFIFO_H
+
+-#ifdef __KERNEL__
+-
+ #include <linux/kernel.h>
+ #include <linux/spinlock.h>
+
+@@ -151,7 +149,4 @@ static inline unsigned int kfifo_len(struct kfifo *fifo)
+ return ret;
+ }
+
+-#else
+-#warning "don't include kernel headers in userspace"
+-#endif /* __KERNEL__ */
+ #endif
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h
new file mode 100644
index 0000000..9757b1a
@@ -814979,6 +1088188,215 @@
+extern atomic_t kgdb_active;
+
+#endif /* _KGDB_H_ */
+diff --git a/include/linux/klist.h b/include/linux/klist.h
+index 7407125..06c338e 100644
+--- a/include/linux/klist.h
++++ b/include/linux/klist.h
+@@ -25,37 +25,47 @@ struct klist {
+ void (*put)(struct klist_node *);
+ };
+
++#define KLIST_INIT(_name, _get, _put) \
++ { .k_lock = __SPIN_LOCK_UNLOCKED(_name.k_lock), \
++ .k_list = LIST_HEAD_INIT(_name.k_list), \
++ .get = _get, \
++ .put = _put, }
+
+-extern void klist_init(struct klist * k, void (*get)(struct klist_node *),
++#define DEFINE_KLIST(_name, _get, _put) \
++ struct klist _name = KLIST_INIT(_name, _get, _put)
++
++extern void klist_init(struct klist *k, void (*get)(struct klist_node *),
+ void (*put)(struct klist_node *));
+
+ struct klist_node {
+- struct klist * n_klist;
++ struct klist *n_klist;
+ struct list_head n_node;
+ struct kref n_ref;
+ struct completion n_removed;
+ };
+
+-extern void klist_add_tail(struct klist_node * n, struct klist * k);
+-extern void klist_add_head(struct klist_node * n, struct klist * k);
++extern void klist_add_tail(struct klist_node *n, struct klist *k);
++extern void klist_add_head(struct klist_node *n, struct klist *k);
++extern void klist_add_after(struct klist_node *n, struct klist_node *pos);
++extern void klist_add_before(struct klist_node *n, struct klist_node *pos);
+
+-extern void klist_del(struct klist_node * n);
+-extern void klist_remove(struct klist_node * n);
++extern void klist_del(struct klist_node *n);
++extern void klist_remove(struct klist_node *n);
+
+-extern int klist_node_attached(struct klist_node * n);
++extern int klist_node_attached(struct klist_node *n);
+
+
+ struct klist_iter {
+- struct klist * i_klist;
+- struct list_head * i_head;
+- struct klist_node * i_cur;
++ struct klist *i_klist;
++ struct list_head *i_head;
++ struct klist_node *i_cur;
+ };
+
+
+-extern void klist_iter_init(struct klist * k, struct klist_iter * i);
+-extern void klist_iter_init_node(struct klist * k, struct klist_iter * i,
+- struct klist_node * n);
+-extern void klist_iter_exit(struct klist_iter * i);
+-extern struct klist_node * klist_next(struct klist_iter * i);
++extern void klist_iter_init(struct klist *k, struct klist_iter *i);
++extern void klist_iter_init_node(struct klist *k, struct klist_iter *i,
++ struct klist_node *n);
++extern void klist_iter_exit(struct klist_iter *i);
++extern struct klist_node *klist_next(struct klist_iter *i);
+
+ #endif
+diff --git a/include/linux/kobj_map.h b/include/linux/kobj_map.h
+index bafe178..73717ed 100644
+--- a/include/linux/kobj_map.h
++++ b/include/linux/kobj_map.h
+@@ -1,5 +1,3 @@
+-#ifdef __KERNEL__
+-
+ #include <linux/mutex.h>
+
+ typedef struct kobject *kobj_probe_t(dev_t, int *, void *);
+@@ -10,5 +8,3 @@ int kobj_map(struct kobj_map *, dev_t, unsigned long, struct module *,
+ void kobj_unmap(struct kobj_map *, dev_t, unsigned long);
+ struct kobject *kobj_lookup(struct kobj_map *, dev_t, int *);
+ struct kobj_map *kobj_map_init(kobj_probe_t *, struct mutex *);
+-
+-#endif
+diff --git a/include/linux/kobject.h b/include/linux/kobject.h
+index caa3f41..39e709f 100644
+--- a/include/linux/kobject.h
++++ b/include/linux/kobject.h
+@@ -16,8 +16,6 @@
+ #ifndef _KOBJECT_H_
+ #define _KOBJECT_H_
+
+-#ifdef __KERNEL__
+-
+ #include <linux/types.h>
+ #include <linux/list.h>
+ #include <linux/sysfs.h>
+@@ -224,5 +222,4 @@ static inline int kobject_action_type(const char *buf, size_t count,
+ { return -EINVAL; }
+ #endif
+
+-#endif /* __KERNEL__ */
+ #endif /* _KOBJECT_H_ */
+diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
+index 0f28486..1036631 100644
+--- a/include/linux/kprobes.h
++++ b/include/linux/kprobes.h
+@@ -173,6 +173,13 @@ struct kretprobe_blackpoint {
+ const char *name;
+ void *addr;
+ };
++
++struct kprobe_blackpoint {
++ const char *name;
++ unsigned long start_addr;
++ unsigned long range;
++};
++
+ extern struct kretprobe_blackpoint kretprobe_blacklist[];
+
+ static inline void kretprobe_assert(struct kretprobe_instance *ri,
+@@ -227,15 +234,21 @@ static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void)
+
+ int register_kprobe(struct kprobe *p);
+ void unregister_kprobe(struct kprobe *p);
++int register_kprobes(struct kprobe **kps, int num);
++void unregister_kprobes(struct kprobe **kps, int num);
+ int setjmp_pre_handler(struct kprobe *, struct pt_regs *);
+ int longjmp_break_handler(struct kprobe *, struct pt_regs *);
+ int register_jprobe(struct jprobe *p);
+ void unregister_jprobe(struct jprobe *p);
++int register_jprobes(struct jprobe **jps, int num);
++void unregister_jprobes(struct jprobe **jps, int num);
+ void jprobe_return(void);
+ unsigned long arch_deref_entry_point(void *);
+
+ int register_kretprobe(struct kretprobe *rp);
+ void unregister_kretprobe(struct kretprobe *rp);
++int register_kretprobes(struct kretprobe **rps, int num);
++void unregister_kretprobes(struct kretprobe **rps, int num);
+
+ void kprobe_flush_task(struct task_struct *tk);
+ void recycle_rp_inst(struct kretprobe_instance *ri, struct hlist_head *head);
+@@ -254,16 +267,30 @@ static inline int register_kprobe(struct kprobe *p)
+ {
+ return -ENOSYS;
+ }
++static inline int register_kprobes(struct kprobe **kps, int num)
++{
++ return -ENOSYS;
++}
+ static inline void unregister_kprobe(struct kprobe *p)
+ {
+ }
++static inline void unregister_kprobes(struct kprobe **kps, int num)
++{
++}
+ static inline int register_jprobe(struct jprobe *p)
+ {
+ return -ENOSYS;
+ }
++static inline int register_jprobes(struct jprobe **jps, int num)
++{
++ return -ENOSYS;
++}
+ static inline void unregister_jprobe(struct jprobe *p)
+ {
+ }
++static inline void unregister_jprobes(struct jprobe **jps, int num)
++{
++}
+ static inline void jprobe_return(void)
+ {
+ }
+@@ -271,9 +298,16 @@ static inline int register_kretprobe(struct kretprobe *rp)
+ {
+ return -ENOSYS;
+ }
++static inline int register_kretprobes(struct kretprobe **rps, int num)
++{
++ return -ENOSYS;
++}
+ static inline void unregister_kretprobe(struct kretprobe *rp)
+ {
+ }
++static inline void unregister_kretprobes(struct kretprobe **rps, int num)
++{
++}
+ static inline void kprobe_flush_task(struct task_struct *tk)
+ {
+ }
+diff --git a/include/linux/kref.h b/include/linux/kref.h
+index 5d18563..0cef6ba 100644
+--- a/include/linux/kref.h
++++ b/include/linux/kref.h
+@@ -15,8 +15,6 @@
+ #ifndef _KREF_H_
+ #define _KREF_H_
+
+-#ifdef __KERNEL__
+-
+ #include <linux/types.h>
+ #include <asm/atomic.h>
+
+@@ -29,5 +27,4 @@ void kref_init(struct kref *kref);
+ void kref_get(struct kref *kref);
+ int kref_put(struct kref *kref, void (*release) (struct kref *kref));
+
+-#endif /* __KERNEL__ */
+ #endif /* _KREF_H_ */
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index 2cd7fa7..ce59832 100644
--- a/include/linux/ktime.h
@@ -814994,6 +1088412,414 @@
+}
+
#endif
+diff --git a/include/linux/kvm.h b/include/linux/kvm.h
+index c1ec04f..a281afe 100644
+--- a/include/linux/kvm.h
++++ b/include/linux/kvm.h
+@@ -8,11 +8,18 @@
+ */
+
+ #include <asm/types.h>
++#include <linux/compiler.h>
+ #include <linux/ioctl.h>
+ #include <asm/kvm.h>
+
+ #define KVM_API_VERSION 12
+
++/* for KVM_TRACE_ENABLE */
++struct kvm_user_trace_setup {
++ __u32 buf_size; /* sub_buffer size of each per-cpu */
++ __u32 buf_nr; /* the number of sub_buffers of each per-cpu */
++};
++
+ /* for KVM_CREATE_MEMORY_REGION */
+ struct kvm_memory_region {
+ __u32 slot;
+@@ -73,6 +80,9 @@ struct kvm_irqchip {
+ #define KVM_EXIT_INTR 10
+ #define KVM_EXIT_SET_TPR 11
+ #define KVM_EXIT_TPR_ACCESS 12
++#define KVM_EXIT_S390_SIEIC 13
++#define KVM_EXIT_S390_RESET 14
++#define KVM_EXIT_DCR 15
+
+ /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
+ struct kvm_run {
+@@ -137,6 +147,27 @@ struct kvm_run {
+ __u32 is_write;
+ __u32 pad;
+ } tpr_access;
++ /* KVM_EXIT_S390_SIEIC */
++ struct {
++ __u8 icptcode;
++ __u64 mask; /* psw upper half */
++ __u64 addr; /* psw lower half */
++ __u16 ipa;
++ __u32 ipb;
++ } s390_sieic;
++ /* KVM_EXIT_S390_RESET */
++#define KVM_S390_RESET_POR 1
++#define KVM_S390_RESET_CLEAR 2
++#define KVM_S390_RESET_SUBSYSTEM 4
++#define KVM_S390_RESET_CPU_INIT 8
++#define KVM_S390_RESET_IPL 16
++ __u64 s390_reset_flags;
++ /* KVM_EXIT_DCR */
++ struct {
++ __u32 dcrn;
++ __u32 data;
++ __u8 is_write;
++ } dcr;
+ /* Fix the size of the union. */
+ char padding[256];
+ };
+@@ -204,6 +235,74 @@ struct kvm_vapic_addr {
+ __u64 vapic_addr;
+ };
+
++/* for KVM_SET_MPSTATE */
++
++#define KVM_MP_STATE_RUNNABLE 0
++#define KVM_MP_STATE_UNINITIALIZED 1
++#define KVM_MP_STATE_INIT_RECEIVED 2
++#define KVM_MP_STATE_HALTED 3
++#define KVM_MP_STATE_SIPI_RECEIVED 4
++
++struct kvm_mp_state {
++ __u32 mp_state;
++};
++
++struct kvm_s390_psw {
++ __u64 mask;
++ __u64 addr;
++};
++
++/* valid values for type in kvm_s390_interrupt */
++#define KVM_S390_SIGP_STOP 0xfffe0000u
++#define KVM_S390_PROGRAM_INT 0xfffe0001u
++#define KVM_S390_SIGP_SET_PREFIX 0xfffe0002u
++#define KVM_S390_RESTART 0xfffe0003u
++#define KVM_S390_INT_VIRTIO 0xffff2603u
++#define KVM_S390_INT_SERVICE 0xffff2401u
++#define KVM_S390_INT_EMERGENCY 0xffff1201u
++
++struct kvm_s390_interrupt {
++ __u32 type;
++ __u32 parm;
++ __u64 parm64;
++};
++
++#define KVM_TRC_SHIFT 16
++/*
++ * kvm trace categories
++ */
++#define KVM_TRC_ENTRYEXIT (1 << KVM_TRC_SHIFT)
++#define KVM_TRC_HANDLER (1 << (KVM_TRC_SHIFT + 1)) /* only 12 bits */
++
++/*
++ * kvm trace action
++ */
++#define KVM_TRC_VMENTRY (KVM_TRC_ENTRYEXIT + 0x01)
++#define KVM_TRC_VMEXIT (KVM_TRC_ENTRYEXIT + 0x02)
++#define KVM_TRC_PAGE_FAULT (KVM_TRC_HANDLER + 0x01)
++
++#define KVM_TRC_HEAD_SIZE 12
++#define KVM_TRC_CYCLE_SIZE 8
++#define KVM_TRC_EXTRA_MAX 7
++
++/* This structure represents a single trace buffer record. */
++struct kvm_trace_rec {
++ __u32 event:28;
++ __u32 extra_u32:3;
++ __u32 cycle_in:1;
++ __u32 pid;
++ __u32 vcpu_id;
++ union {
++ struct {
++ __u32 cycle_lo, cycle_hi;
++ __u32 extra_u32[KVM_TRC_EXTRA_MAX];
++ } cycle;
++ struct {
++ __u32 extra_u32[KVM_TRC_EXTRA_MAX];
++ } nocycle;
++ } u;
++};
++
+ #define KVMIO 0xAE
+
+ /*
+@@ -212,6 +311,8 @@ struct kvm_vapic_addr {
+ #define KVM_GET_API_VERSION _IO(KVMIO, 0x00)
+ #define KVM_CREATE_VM _IO(KVMIO, 0x01) /* returns a VM fd */
+ #define KVM_GET_MSR_INDEX_LIST _IOWR(KVMIO, 0x02, struct kvm_msr_list)
++
++#define KVM_S390_ENABLE_SIE _IO(KVMIO, 0x06)
+ /*
+ * Check if a kvm extension is available. Argument is extension number,
+ * return is 1 (yes) or 0 (no, sorry).
+@@ -222,7 +323,12 @@ struct kvm_vapic_addr {
+ */
+ #define KVM_GET_VCPU_MMAP_SIZE _IO(KVMIO, 0x04) /* in bytes */
+ #define KVM_GET_SUPPORTED_CPUID _IOWR(KVMIO, 0x05, struct kvm_cpuid2)
+-
++/*
++ * ioctls for kvm trace
++ */
++#define KVM_TRACE_ENABLE _IOW(KVMIO, 0x06, struct kvm_user_trace_setup)
++#define KVM_TRACE_PAUSE _IO(KVMIO, 0x07)
++#define KVM_TRACE_DISABLE _IO(KVMIO, 0x08)
+ /*
+ * Extension capability list.
+ */
+@@ -233,6 +339,13 @@ struct kvm_vapic_addr {
+ #define KVM_CAP_SET_TSS_ADDR 4
+ #define KVM_CAP_VAPIC 6
+ #define KVM_CAP_EXT_CPUID 7
++#define KVM_CAP_CLOCKSOURCE 8
++#define KVM_CAP_NR_VCPUS 9 /* returns max vcpus per vm */
++#define KVM_CAP_NR_MEMSLOTS 10 /* returns max memory slots per vm */
++#define KVM_CAP_PIT 11
++#define KVM_CAP_NOP_IO_DELAY 12
++#define KVM_CAP_PV_MMU 13
++#define KVM_CAP_MP_STATE 14
+
+ /*
+ * ioctls for VM fds
+@@ -255,6 +368,9 @@ struct kvm_vapic_addr {
+ #define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level)
+ #define KVM_GET_IRQCHIP _IOWR(KVMIO, 0x62, struct kvm_irqchip)
+ #define KVM_SET_IRQCHIP _IOR(KVMIO, 0x63, struct kvm_irqchip)
++#define KVM_CREATE_PIT _IO(KVMIO, 0x64)
++#define KVM_GET_PIT _IOWR(KVMIO, 0x65, struct kvm_pit_state)
++#define KVM_SET_PIT _IOR(KVMIO, 0x66, struct kvm_pit_state)
+
+ /*
+ * ioctls for vcpu fds
+@@ -281,5 +397,17 @@ struct kvm_vapic_addr {
+ #define KVM_TPR_ACCESS_REPORTING _IOWR(KVMIO, 0x92, struct kvm_tpr_access_ctl)
+ /* Available with KVM_CAP_VAPIC */
+ #define KVM_SET_VAPIC_ADDR _IOW(KVMIO, 0x93, struct kvm_vapic_addr)
++/* valid for virtual machine (for floating interrupt)_and_ vcpu */
++#define KVM_S390_INTERRUPT _IOW(KVMIO, 0x94, struct kvm_s390_interrupt)
++/* store status for s390 */
++#define KVM_S390_STORE_STATUS_NOADDR (-1ul)
++#define KVM_S390_STORE_STATUS_PREFIXED (-2ul)
++#define KVM_S390_STORE_STATUS _IOW(KVMIO, 0x95, unsigned long)
++/* initial ipl psw for s390 */
++#define KVM_S390_SET_INITIAL_PSW _IOW(KVMIO, 0x96, struct kvm_s390_psw)
++/* initial reset for s390 */
++#define KVM_S390_INITIAL_RESET _IO(KVMIO, 0x97)
++#define KVM_GET_MP_STATE _IOR(KVMIO, 0x98, struct kvm_mp_state)
++#define KVM_SET_MP_STATE _IOW(KVMIO, 0x99, struct kvm_mp_state)
+
+ #endif
+diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
+index 928b0d5..3989789 100644
+--- a/include/linux/kvm_host.h
++++ b/include/linux/kvm_host.h
+@@ -15,6 +15,7 @@
+ #include <linux/sched.h>
+ #include <linux/mm.h>
+ #include <linux/preempt.h>
++#include <linux/marker.h>
+ #include <asm/signal.h>
+
+ #include <linux/kvm.h>
+@@ -24,29 +25,18 @@
+
+ #include <asm/kvm_host.h>
+
+-#define KVM_MAX_VCPUS 4
+-#define KVM_MEMORY_SLOTS 8
+-/* memory slots that does not exposed to userspace */
+-#define KVM_PRIVATE_MEM_SLOTS 4
+-
+-#define KVM_PIO_PAGE_OFFSET 1
+-
+ /*
+ * vcpu->requests bit members
+ */
+ #define KVM_REQ_TLB_FLUSH 0
+ #define KVM_REQ_MIGRATE_TIMER 1
+ #define KVM_REQ_REPORT_TPR_ACCESS 2
++#define KVM_REQ_MMU_RELOAD 3
++#define KVM_REQ_TRIPLE_FAULT 4
+
+ struct kvm_vcpu;
+ extern struct kmem_cache *kvm_vcpu_cache;
+
+-struct kvm_guest_debug {
+- int enabled;
+- unsigned long bp[4];
+- int singlestep;
+-};
+-
+ /*
+ * It would be nice to use something smarter than a linear search, TBD...
+ * Thankfully we dont expect many devices to register (famous last words :),
+@@ -67,7 +57,9 @@ void kvm_io_bus_register_dev(struct kvm_io_bus *bus,
+
+ struct kvm_vcpu {
+ struct kvm *kvm;
++#ifdef CONFIG_PREEMPT_NOTIFIERS
+ struct preempt_notifier preempt_notifier;
++#endif
+ int vcpu_id;
+ struct mutex mutex;
+ int cpu;
+@@ -100,6 +92,10 @@ struct kvm_memory_slot {
+ unsigned long flags;
+ unsigned long *rmap;
+ unsigned long *dirty_bitmap;
++ struct {
++ unsigned long rmap_pde;
++ int write_count;
++ } *lpage_info;
+ unsigned long userspace_addr;
+ int user_alloc;
+ };
+@@ -114,11 +110,11 @@ struct kvm {
+ KVM_PRIVATE_MEM_SLOTS];
+ struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
+ struct list_head vm_list;
+- struct file *filp;
+ struct kvm_io_bus mmio_bus;
+ struct kvm_io_bus pio_bus;
+ struct kvm_vm_stat stat;
+ struct kvm_arch arch;
++ atomic_t users_count;
+ };
+
+ /* The guest did something we don't support. */
+@@ -145,14 +141,19 @@ int kvm_init(void *opaque, unsigned int vcpu_size,
+ struct module *module);
+ void kvm_exit(void);
+
++void kvm_get_kvm(struct kvm *kvm);
++void kvm_put_kvm(struct kvm *kvm);
++
+ #define HPA_MSB ((sizeof(hpa_t) * 8) - 1)
+ #define HPA_ERR_MASK ((hpa_t)1 << HPA_MSB)
+ static inline int is_error_hpa(hpa_t hpa) { return hpa >> HPA_MSB; }
+ struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva);
+
+ extern struct page *bad_page;
++extern pfn_t bad_pfn;
+
+ int is_error_page(struct page *page);
++int is_error_pfn(pfn_t pfn);
+ int kvm_is_error_hva(unsigned long addr);
+ int kvm_set_memory_region(struct kvm *kvm,
+ struct kvm_userspace_memory_region *mem,
+@@ -166,8 +167,19 @@ int kvm_arch_set_memory_region(struct kvm *kvm,
+ int user_alloc);
+ gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn);
+ struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn);
++unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn);
+ void kvm_release_page_clean(struct page *page);
+ void kvm_release_page_dirty(struct page *page);
++void kvm_set_page_dirty(struct page *page);
++void kvm_set_page_accessed(struct page *page);
++
++pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn);
++void kvm_release_pfn_dirty(pfn_t);
++void kvm_release_pfn_clean(pfn_t pfn);
++void kvm_set_pfn_dirty(pfn_t pfn);
++void kvm_set_pfn_accessed(pfn_t pfn);
++void kvm_get_pfn(pfn_t pfn);
++
+ int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset,
+ int len);
+ int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data,
+@@ -188,6 +200,7 @@ void kvm_resched(struct kvm_vcpu *vcpu);
+ void kvm_load_guest_fpu(struct kvm_vcpu *vcpu);
+ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu);
+ void kvm_flush_remote_tlbs(struct kvm *kvm);
++void kvm_reload_remote_mmus(struct kvm *kvm);
+
+ long kvm_arch_dev_ioctl(struct file *filp,
+ unsigned int ioctl, unsigned long arg);
+@@ -223,6 +236,10 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
+ struct kvm_sregs *sregs);
+ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
+ struct kvm_sregs *sregs);
++int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
++ struct kvm_mp_state *mp_state);
++int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
++ struct kvm_mp_state *mp_state);
+ int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
+ struct kvm_debug_guest *dbg);
+ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run);
+@@ -255,6 +272,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm);
+
+ int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
+ int kvm_cpu_has_interrupt(struct kvm_vcpu *v);
++int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu);
+ void kvm_vcpu_kick(struct kvm_vcpu *vcpu);
+
+ static inline void kvm_guest_enter(void)
+@@ -296,5 +314,18 @@ struct kvm_stats_debugfs_item {
+ struct dentry *dentry;
+ };
+ extern struct kvm_stats_debugfs_item debugfs_entries[];
++extern struct dentry *kvm_debugfs_dir;
++
++#ifdef CONFIG_KVM_TRACE
++int kvm_trace_ioctl(unsigned int ioctl, unsigned long arg);
++void kvm_trace_cleanup(void);
++#else
++static inline
++int kvm_trace_ioctl(unsigned int ioctl, unsigned long arg)
++{
++ return -EINVAL;
++}
++#define kvm_trace_cleanup() ((void)0)
++#endif
+
+ #endif
+diff --git a/include/linux/kvm_para.h b/include/linux/kvm_para.h
+index 5497aac..3ddce03 100644
+--- a/include/linux/kvm_para.h
++++ b/include/linux/kvm_para.h
+@@ -11,8 +11,11 @@
+
+ /* Return values for hypercalls */
+ #define KVM_ENOSYS 1000
++#define KVM_EFAULT EFAULT
++#define KVM_E2BIG E2BIG
+
+-#define KVM_HC_VAPIC_POLL_IRQ 1
++#define KVM_HC_VAPIC_POLL_IRQ 1
++#define KVM_HC_MMU_OP 2
+
+ /*
+ * hypercalls use architecture specific
+@@ -20,6 +23,12 @@
+ #include <asm/kvm_para.h>
+
+ #ifdef __KERNEL__
++#ifdef CONFIG_KVM_GUEST
++void __init kvm_guest_init(void);
++#else
++#define kvm_guest_init() do { } while (0)
++#endif
++
+ static inline int kvm_para_has_feature(unsigned int feature)
+ {
+ if (kvm_arch_para_features() & (1UL << feature))
+diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
+index 1c4e46d..9b6f395 100644
+--- a/include/linux/kvm_types.h
++++ b/include/linux/kvm_types.h
+@@ -38,6 +38,8 @@ typedef unsigned long hva_t;
+ typedef u64 hpa_t;
+ typedef unsigned long hfn_t;
+
++typedef hfn_t pfn_t;
++
+ struct kvm_pio_request {
+ unsigned long count;
+ int cur_count;
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 0201f6f..519df72 100644
--- a/include/linux/leds.h
@@ -815038,7 +1088864,7 @@
diff --git a/include/linux/libata.h b/include/linux/libata.h
-index 37ee881..395a523 100644
+index 37ee881..d1dfe87 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -122,6 +122,8 @@ enum {
@@ -815174,6 +1089000,33 @@
unsigned long flags;
#ifdef CONFIG_ATA_ACPI
acpi_handle acpi_handle;
+@@ -513,11 +548,6 @@ struct ata_device {
+ u64 n_sectors; /* size of device, if ATA */
+ unsigned int class; /* ATA_DEV_xxx */
+
+- union {
+- u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
+- u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
+- };
+-
+ u8 pio_mode;
+ u8 dma_mode;
+ u8 xfer_mode;
+@@ -539,8 +569,13 @@ struct ata_device {
+ u16 sectors; /* Number of sectors per track */
+
+ /* error history */
+- struct ata_ering ering;
+ int spdn_cnt;
++ struct ata_ering ering;
++
++ union {
++ u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
++ u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
++ };
+ };
+
+ /* Offset into struct ata_device. Fields above it are maintained
@@ -605,7 +640,7 @@ struct ata_link {
struct ata_port {
@@ -815605,7 +1089458,7 @@
- unsigned long xfer_mask);
-#endif /* CONFIG_PCI */
-
--/*
+ /*
- * PMP
- */
-extern int sata_pmp_qc_defer_cmd_switch(struct ata_queued_cmd *qc);
@@ -815619,7 +1089472,7 @@
- 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
*/
@@ -816049,10 +1089902,47 @@
+
#endif /* __LINUX_LIBATA_H__ */
diff --git a/include/linux/list.h b/include/linux/list.h
-index 75ce2cb..dac16f9 100644
+index 75ce2cb..08cf4f6 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,
+@@ -1,8 +1,6 @@
+ #ifndef _LINUX_LIST_H
+ #define _LINUX_LIST_H
+
+-#ifdef __KERNEL__
+-
+ #include <linux/stddef.h>
+ #include <linux/poison.h>
+ #include <linux/prefetch.h>
+@@ -319,7 +317,16 @@ static inline int list_empty_careful(const struct list_head *head)
+ return (next == head) && (next == head->prev);
+ }
+
+-static inline void __list_splice(struct list_head *list,
++/**
++ * list_is_singular - tests whether a list has just one entry.
++ * @head: the list to test.
++ */
++static inline int list_is_singular(const struct list_head *head)
++{
++ return !list_empty(head) && (head->next == head->prev);
++}
++
++static inline void __list_splice(const struct list_head *list,
+ struct list_head *head)
+ {
+ struct list_head *first = list->next;
+@@ -338,7 +345,8 @@ static inline void __list_splice(struct list_head *list,
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+-static inline void list_splice(struct list_head *list, struct list_head *head)
++static inline void list_splice(const struct list_head *list,
++ struct list_head *head)
+ {
+ if (!list_empty(list))
+ __list_splice(list, head);
+@@ -631,31 +639,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) \
@@ -816090,7 +1089980,7 @@
/**
* 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,
+@@ -668,10 +659,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) \
@@ -816104,7 +1089994,7 @@
/**
-@@ -686,9 +668,9 @@ static inline void list_splice_init_rcu(struct list_head *list,
+@@ -686,9 +676,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) \
@@ -816117,7 +1090007,7 @@
/*
* Double linked lists with a single pointer list head.
-@@ -986,10 +968,10 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
+@@ -986,12 +976,9 @@ 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) \
@@ -816129,8 +1090019,10 @@
- pos = pos->next)
+ pos = rcu_dereference(pos->next))
- #else
- #warning "don't include kernel headers in userspace"
+-#else
+-#warning "don't include kernel headers in userspace"
+-#endif /* __KERNEL__ */
+ #endif
diff --git a/include/linux/lm_interface.h b/include/linux/lm_interface.h
index 1418fdc..f274997 100644
--- a/include/linux/lm_interface.h
@@ -816171,10 +1090063,10 @@
* lm_callback_t types
diff --git a/include/linux/lmb.h b/include/linux/lmb.h
new file mode 100644
-index 0000000..271153d
+index 0000000..c46c895
--- /dev/null
+++ b/include/linux/lmb.h
-@@ -0,0 +1,85 @@
+@@ -0,0 +1,87 @@
+#ifndef _LINUX_LMB_H
+#define _LINUX_LMB_H
+#ifdef __KERNEL__
@@ -816217,7 +1090109,8 @@
+
+extern void __init lmb_init(void);
+extern void __init lmb_analyze(void);
-+extern long __init lmb_add(u64 base, u64 size);
++extern long lmb_add(u64 base, u64 size);
++extern long lmb_remove(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 *));
@@ -816230,6 +1090123,7 @@
+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 int lmb_find(struct lmb_property *res);
+
+extern void lmb_dump_all(void);
+
@@ -816433,8 +1090327,62 @@
+
+
+#endif
+diff --git a/include/linux/mca-legacy.h b/include/linux/mca-legacy.h
+index f2bb770..7a3aea8 100644
+--- a/include/linux/mca-legacy.h
++++ b/include/linux/mca-legacy.h
+@@ -34,7 +34,6 @@
+ extern int mca_find_adapter(int id, int start);
+ extern int mca_find_unused_adapter(int id, int start);
+
+-extern int mca_is_adapter_used(int slot);
+ extern int mca_mark_as_used(int slot);
+ extern void mca_mark_as_unused(int slot);
+
+diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
+index 8b1c429..e660877 100644
+--- a/include/linux/memcontrol.h
++++ b/include/linux/memcontrol.h
+@@ -27,9 +27,6 @@ struct mm_struct;
+
+ #ifdef CONFIG_CGROUP_MEM_RES_CTLR
+
+-extern void mm_init_cgroup(struct mm_struct *mm, struct task_struct *p);
+-extern void mm_free_cgroup(struct mm_struct *mm);
+-
+ #define page_reset_bad_cgroup(page) ((page)->page_cgroup = 0)
+
+ extern struct page_cgroup *page_get_page_cgroup(struct page *page);
+@@ -48,8 +45,10 @@ extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
+ extern void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask);
+ int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem);
+
++extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p);
++
+ #define mm_match_cgroup(mm, cgroup) \
+- ((cgroup) == rcu_dereference((mm)->mem_cgroup))
++ ((cgroup) == mem_cgroup_from_task((mm)->owner))
+
+ extern int mem_cgroup_prepare_migration(struct page *page);
+ extern void mem_cgroup_end_migration(struct page *page);
+@@ -73,15 +72,6 @@ extern long mem_cgroup_calc_reclaim_inactive(struct mem_cgroup *mem,
+ struct zone *zone, int priority);
+
+ #else /* CONFIG_CGROUP_MEM_RES_CTLR */
+-static inline void mm_init_cgroup(struct mm_struct *mm,
+- struct task_struct *p)
+-{
+-}
+-
+-static inline void mm_free_cgroup(struct mm_struct *mm)
+-{
+-}
+-
+ static inline void page_reset_bad_cgroup(struct page *page)
+ {
+ }
diff --git a/include/linux/memory.h b/include/linux/memory.h
-index 33f0ff0..f80e0e3 100644
+index 33f0ff0..2f5f8a5 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -18,8 +18,7 @@
@@ -816456,6 +1090404,374 @@
int phys_device; /* to which fru does this belong? */
void *hw; /* optional pointer to fw/hw data */
int (*phys_callback)(struct memory_block *);
+@@ -54,6 +53,13 @@ struct memory_notify {
+ struct notifier_block;
+ struct mem_section;
+
++/*
++ * Priorities for the hotplug memory callback routines (stored in decreasing
++ * order in the callback chain)
++ */
++#define SLAB_CALLBACK_PRI 1
++#define IPC_CALLBACK_PRI 10
++
+ #ifndef CONFIG_MEMORY_HOTPLUG_SPARSE
+ static inline int memory_dev_init(void)
+ {
+diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
+index 8fee7a4..73e3586 100644
+--- a/include/linux/memory_hotplug.h
++++ b/include/linux/memory_hotplug.h
+@@ -8,8 +8,18 @@
+ struct page;
+ struct zone;
+ struct pglist_data;
++struct mem_section;
+
+ #ifdef CONFIG_MEMORY_HOTPLUG
++
++/*
++ * Magic number for free bootmem.
++ * The normal smallest mapcount is -1. Here is smaller value than it.
++ */
++#define SECTION_INFO 0xfffffffe
++#define MIX_INFO 0xfffffffd
++#define NODE_INFO 0xfffffffc
++
+ /*
+ * pgdat resizing functions
+ */
+@@ -64,9 +74,11 @@ extern int offline_pages(unsigned long, unsigned long, unsigned long);
+ /* reasonably generic interface to expand the physical pages in a zone */
+ extern int __add_pages(struct zone *zone, unsigned long start_pfn,
+ unsigned long nr_pages);
++extern int __remove_pages(struct zone *zone, unsigned long start_pfn,
++ unsigned long nr_pages);
+
+ /*
+- * Walk thorugh all memory which is registered as resource.
++ * Walk through all memory which is registered as resource.
+ * arg is (start_pfn, nr_pages, private_arg_pointer)
+ */
+ extern int walk_memory_resource(unsigned long start_pfn,
+@@ -142,6 +154,18 @@ static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
+ #endif /* CONFIG_NUMA */
+ #endif /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */
+
++#ifdef CONFIG_SPARSEMEM_VMEMMAP
++static inline void register_page_bootmem_info_node(struct pglist_data *pgdat)
++{
++}
++static inline void put_page_bootmem(struct page *page)
++{
++}
++#else
++extern void register_page_bootmem_info_node(struct pglist_data *pgdat);
++extern void put_page_bootmem(struct page *page);
++#endif
++
+ #else /* ! CONFIG_MEMORY_HOTPLUG */
+ /*
+ * Stub functions for when hotplug is off
+@@ -169,6 +193,10 @@ static inline int mhp_notimplemented(const char *func)
+ return -ENOSYS;
+ }
+
++static inline void register_page_bootmem_info_node(struct pglist_data *pgdat)
++{
++}
++
+ #endif /* ! CONFIG_MEMORY_HOTPLUG */
+
+ extern int add_memory(int nid, u64 start, u64 size);
+@@ -176,5 +204,8 @@ extern int arch_add_memory(int nid, u64 start, u64 size);
+ extern int remove_memory(u64 start, u64 size);
+ extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
+ int nr_pages);
++extern void sparse_remove_one_section(struct zone *zone, struct mem_section *ms);
++extern struct page *sparse_decode_mem_map(unsigned long coded_mem_map,
++ unsigned long pnum);
+
+ #endif /* __LINUX_MEMORY_HOTPLUG_H */
+diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
+index 59c4865..3a39570 100644
+--- a/include/linux/mempolicy.h
++++ b/include/linux/mempolicy.h
+@@ -8,15 +8,32 @@
+ * Copyright 2003,2004 Andi Kleen SuSE Labs
+ */
+
++/*
++ * Both the MPOL_* mempolicy mode and the MPOL_F_* optional mode flags are
++ * passed by the user to either set_mempolicy() or mbind() in an 'int' actual.
++ * The MPOL_MODE_FLAGS macro determines the legal set of optional mode flags.
++ */
++
+ /* Policies */
+-#define MPOL_DEFAULT 0
+-#define MPOL_PREFERRED 1
+-#define MPOL_BIND 2
+-#define MPOL_INTERLEAVE 3
++enum {
++ MPOL_DEFAULT,
++ MPOL_PREFERRED,
++ MPOL_BIND,
++ MPOL_INTERLEAVE,
++ MPOL_MAX, /* always last member of enum */
++};
+
+-#define MPOL_MAX MPOL_INTERLEAVE
++/* Flags for set_mempolicy */
++#define MPOL_F_STATIC_NODES (1 << 15)
++#define MPOL_F_RELATIVE_NODES (1 << 14)
+
+-/* Flags for get_mem_policy */
++/*
++ * MPOL_MODE_FLAGS is the union of all possible optional mode flags passed to
++ * either set_mempolicy() or mbind().
++ */
++#define MPOL_MODE_FLAGS (MPOL_F_STATIC_NODES | MPOL_F_RELATIVE_NODES)
++
++/* Flags for get_mempolicy */
+ #define MPOL_F_NODE (1<<0) /* return next IL mode instead of node mask */
+ #define MPOL_F_ADDR (1<<1) /* look up vma using address */
+ #define MPOL_F_MEMS_ALLOWED (1<<2) /* return allowed memories */
+@@ -27,6 +44,14 @@
+ #define MPOL_MF_MOVE_ALL (1<<2) /* Move every page to conform to mapping */
+ #define MPOL_MF_INTERNAL (1<<3) /* Internal flags start here */
+
++/*
++ * Internal flags that share the struct mempolicy flags word with
++ * "mode flags". These flags are allocated from bit 0 up, as they
++ * are never OR'ed into the mode in mempolicy API arguments.
++ */
++#define MPOL_F_SHARED (1 << 0) /* identify shared policies */
++#define MPOL_F_LOCAL (1 << 1) /* preferred local allocation */
++
+ #ifdef __KERNEL__
+
+ #include <linux/mmzone.h>
+@@ -35,7 +60,6 @@
+ #include <linux/spinlock.h>
+ #include <linux/nodemask.h>
+
+-struct vm_area_struct;
+ struct mm_struct;
+
+ #ifdef CONFIG_NUMA
+@@ -54,22 +78,27 @@ struct mm_struct;
+ * mmap_sem.
+ *
+ * Freeing policy:
+- * When policy is MPOL_BIND v.zonelist is kmalloc'ed and must be kfree'd.
+- * All other policies don't have any external state. mpol_free() handles this.
++ * Mempolicy objects are reference counted. A mempolicy will be freed when
++ * mpol_put() decrements the reference count to zero.
+ *
+- * Copying policy objects:
+- * For MPOL_BIND the zonelist must be always duplicated. mpol_clone() does this.
++ * Duplicating policy objects:
++ * mpol_dup() allocates a new mempolicy and copies the specified mempolicy
++ * to the new storage. The reference count of the new object is initialized
++ * to 1, representing the caller of mpol_dup().
+ */
+ struct mempolicy {
+ atomic_t refcnt;
+- short policy; /* See MPOL_* above */
++ unsigned short mode; /* See MPOL_* above */
++ unsigned short flags; /* See set_mempolicy() MPOL_F_* above */
+ union {
+- struct zonelist *zonelist; /* bind */
+ short preferred_node; /* preferred */
+- nodemask_t nodes; /* interleave */
++ nodemask_t nodes; /* interleave/bind */
+ /* undefined for default */
+ } v;
+- nodemask_t cpuset_mems_allowed; /* mempolicy relative to these nodes */
++ union {
++ nodemask_t cpuset_mems_allowed; /* relative to these nodes */
++ nodemask_t user_nodemask; /* nodemask passed by user */
++ } w;
+ };
+
+ /*
+@@ -77,18 +106,43 @@ struct mempolicy {
+ * The default fast path of a NULL MPOL_DEFAULT policy is always inlined.
+ */
+
+-extern void __mpol_free(struct mempolicy *pol);
+-static inline void mpol_free(struct mempolicy *pol)
++extern void __mpol_put(struct mempolicy *pol);
++static inline void mpol_put(struct mempolicy *pol)
+ {
+ if (pol)
+- __mpol_free(pol);
++ __mpol_put(pol);
+ }
+
+-extern struct mempolicy *__mpol_copy(struct mempolicy *pol);
+-static inline struct mempolicy *mpol_copy(struct mempolicy *pol)
++/*
++ * Does mempolicy pol need explicit unref after use?
++ * Currently only needed for shared policies.
++ */
++static inline int mpol_needs_cond_ref(struct mempolicy *pol)
++{
++ return (pol && (pol->flags & MPOL_F_SHARED));
++}
++
++static inline void mpol_cond_put(struct mempolicy *pol)
++{
++ if (mpol_needs_cond_ref(pol))
++ __mpol_put(pol);
++}
++
++extern struct mempolicy *__mpol_cond_copy(struct mempolicy *tompol,
++ struct mempolicy *frompol);
++static inline struct mempolicy *mpol_cond_copy(struct mempolicy *tompol,
++ struct mempolicy *frompol)
++{
++ if (!frompol)
++ return frompol;
++ return __mpol_cond_copy(tompol, frompol);
++}
++
++extern struct mempolicy *__mpol_dup(struct mempolicy *pol);
++static inline struct mempolicy *mpol_dup(struct mempolicy *pol)
+ {
+ if (pol)
+- pol = __mpol_copy(pol);
++ pol = __mpol_dup(pol);
+ return pol;
+ }
+
+@@ -108,11 +162,6 @@ static inline int mpol_equal(struct mempolicy *a, struct mempolicy *b)
+ return 1;
+ return __mpol_equal(a, b);
+ }
+-#define vma_mpol_equal(a,b) mpol_equal(vma_policy(a), vma_policy(b))
+-
+-/* Could later add inheritance of the process policy here. */
+-
+-#define mpol_set_vma_default(vma) ((vma)->vm_policy = NULL)
+
+ /*
+ * Tree of shared policies for a shared memory region.
+@@ -133,8 +182,7 @@ struct shared_policy {
+ spinlock_t lock;
+ };
+
+-void mpol_shared_policy_init(struct shared_policy *info, int policy,
+- nodemask_t *nodes);
++void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol);
+ int mpol_set_shared_policy(struct shared_policy *info,
+ struct vm_area_struct *vma,
+ struct mempolicy *new);
+@@ -149,9 +197,9 @@ extern void mpol_rebind_task(struct task_struct *tsk,
+ extern void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new);
+ extern void mpol_fix_fork_child_flag(struct task_struct *p);
+
+-extern struct mempolicy default_policy;
+ extern struct zonelist *huge_zonelist(struct vm_area_struct *vma,
+- unsigned long addr, gfp_t gfp_flags, struct mempolicy **mpol);
++ unsigned long addr, gfp_t gfp_flags,
++ struct mempolicy **mpol, nodemask_t **nodemask);
+ extern unsigned slab_node(struct mempolicy *policy);
+
+ extern enum zone_type policy_zone;
+@@ -165,6 +213,13 @@ static inline void check_highest_zone(enum zone_type k)
+ int do_migrate_pages(struct mm_struct *mm,
+ const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags);
+
++
++#ifdef CONFIG_TMPFS
++extern int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context);
++
++extern int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol,
++ int no_context);
++#endif
+ #else
+
+ struct mempolicy {};
+@@ -173,19 +228,26 @@ static inline int mpol_equal(struct mempolicy *a, struct mempolicy *b)
+ {
+ return 1;
+ }
+-#define vma_mpol_equal(a,b) 1
+
+-#define mpol_set_vma_default(vma) do {} while(0)
++static inline void mpol_put(struct mempolicy *p)
++{
++}
++
++static inline void mpol_cond_put(struct mempolicy *pol)
++{
++}
+
+-static inline void mpol_free(struct mempolicy *p)
++static inline struct mempolicy *mpol_cond_copy(struct mempolicy *to,
++ struct mempolicy *from)
+ {
++ return from;
+ }
+
+ static inline void mpol_get(struct mempolicy *pol)
+ {
+ }
+
+-static inline struct mempolicy *mpol_copy(struct mempolicy *old)
++static inline struct mempolicy *mpol_dup(struct mempolicy *old)
+ {
+ return NULL;
+ }
+@@ -199,8 +261,8 @@ static inline int mpol_set_shared_policy(struct shared_policy *info,
+ return -EINVAL;
+ }
+
+-static inline void mpol_shared_policy_init(struct shared_policy *info,
+- int policy, nodemask_t *nodes)
++static inline void mpol_shared_policy_init(struct shared_policy *sp,
++ struct mempolicy *mpol)
+ {
+ }
+
+@@ -239,9 +301,12 @@ static inline void mpol_fix_fork_child_flag(struct task_struct *p)
+ }
+
+ static inline struct zonelist *huge_zonelist(struct vm_area_struct *vma,
+- unsigned long addr, gfp_t gfp_flags, struct mempolicy **mpol)
++ unsigned long addr, gfp_t gfp_flags,
++ struct mempolicy **mpol, nodemask_t **nodemask)
+ {
+- return NODE_DATA(0)->node_zonelists + gfp_zone(gfp_flags);
++ *mpol = NULL;
++ *nodemask = NULL;
++ return node_zonelist(0, gfp_flags);
+ }
+
+ static inline int do_migrate_pages(struct mm_struct *mm,
+@@ -254,6 +319,21 @@ static inline int do_migrate_pages(struct mm_struct *mm,
+ static inline void check_highest_zone(int k)
+ {
+ }
++
++#ifdef CONFIG_TMPFS
++static inline int mpol_parse_str(char *str, struct mempolicy **mpol,
++ int no_context)
++{
++ return 1; /* error */
++}
++
++static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol,
++ int no_context)
++{
++ return 0;
++}
++#endif
++
+ #endif /* CONFIG_NUMA */
+ #endif /* __KERNEL__ */
+
diff --git a/include/linux/memstick.h b/include/linux/memstick.h
index 3e686ec..37a5cdb 100644
--- a/include/linux/memstick.h
@@ -816679,76 +1090995,553 @@
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);
++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..a744383 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 {
+@@ -207,6 +208,38 @@ struct mlx4_mtt {
+ int page_shift;
+ };
+
++enum {
++ MLX4_DB_PER_PAGE = PAGE_SIZE / 4
++};
++
++struct mlx4_db_pgdir {
++ struct list_head list;
++ DECLARE_BITMAP(order0, MLX4_DB_PER_PAGE);
++ DECLARE_BITMAP(order1, MLX4_DB_PER_PAGE / 2);
++ unsigned long *bits[2];
++ __be32 *db_page;
++ dma_addr_t db_dma;
++};
++
++struct mlx4_ib_user_db_page;
++
++struct mlx4_db {
++ __be32 *db;
++ union {
++ struct mlx4_db_pgdir *pgdir;
++ struct mlx4_ib_user_db_page *user_page;
++ } u;
++ dma_addr_t dma;
++ int index;
++ int order;
++};
++
++struct mlx4_hwq_resources {
++ struct mlx4_db db;
++ struct mlx4_mtt mtt;
++ struct mlx4_buf buf;
++};
++
+ struct mlx4_mr {
+ struct mlx4_mtt mtt;
+ u64 iova;
+@@ -340,8 +373,17 @@ int mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
+ int mlx4_buf_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
+ struct mlx4_buf *buf);
+
++int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, int order);
++void mlx4_db_free(struct mlx4_dev *dev, struct mlx4_db *db);
++
++int mlx4_alloc_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres,
++ int size, int max_direct);
++void mlx4_free_hwq_res(struct mlx4_dev *mdev, struct mlx4_hwq_resources *wqres,
++ int size);
++
+ 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);
++ struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq,
++ int collapsed);
+ void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq);
+
+ int mlx4_qp_alloc(struct mlx4_dev *dev, int sqpn, struct mlx4_qp *qp);
+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..7f128b2 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;
+@@ -289,6 +296,10 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
+ int mlx4_qp_query(struct mlx4_dev *dev, struct mlx4_qp *qp,
+ struct mlx4_qp_context *context);
+
++int mlx4_qp_to_ready(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
++ struct mlx4_qp_context *context,
++ struct mlx4_qp *qp, enum mlx4_qp_state *qp_state);
++
+ static inline struct mlx4_qp *__mlx4_qp_lookup(struct mlx4_dev *dev, u32 qpn)
+ {
+ return radix_tree_lookup(&dev->qp_table_tree, qpn & (dev->caps.num_qps - 1));
+diff --git a/include/linux/mm.h b/include/linux/mm.h
+index b695875..c31a9cd 100644
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -107,6 +107,7 @@ extern unsigned int kobjsize(const void *objp);
+ #define VM_ALWAYSDUMP 0x04000000 /* Always include in core dumps */
+
+ #define VM_CAN_NONLINEAR 0x08000000 /* Has ->fault & does nonlinear pages */
++#define VM_MIXEDMAP 0x10000000 /* Can contain "struct page" and pure PFN pages */
+
+ #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */
+ #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
+@@ -164,8 +165,6 @@ struct vm_operations_struct {
+ void (*open)(struct vm_area_struct * area);
+ void (*close)(struct vm_area_struct * area);
+ int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);
+- struct page *(*nopage)(struct vm_area_struct *area,
+- unsigned long address, int *type);
+ unsigned long (*nopfn)(struct vm_area_struct *area,
+ unsigned long address);
+
+@@ -173,7 +172,25 @@ struct vm_operations_struct {
+ * writable, if an error is returned it will cause a SIGBUS */
+ int (*page_mkwrite)(struct vm_area_struct *vma, struct page *page);
+ #ifdef CONFIG_NUMA
++ /*
++ * set_policy() op must add a reference to any non-NULL @new mempolicy
++ * to hold the policy upon return. Caller should pass NULL @new to
++ * remove a policy and fall back to surrounding context--i.e. do not
++ * install a MPOL_DEFAULT policy, nor the task or system default
++ * mempolicy.
++ */
+ int (*set_policy)(struct vm_area_struct *vma, struct mempolicy *new);
++
++ /*
++ * get_policy() op must add reference [mpol_get()] to any policy at
++ * (vma,addr) marked as MPOL_SHARED. The shared policy infrastructure
++ * in mm/mempolicy.c will do this automatically.
++ * get_policy() must NOT add a ref if the policy at (vma,addr) is not
++ * marked as MPOL_SHARED. vma policies are protected by the mmap_sem.
++ * If no [shared/vma] mempolicy exists at the addr, get_policy() op
++ * must return NULL--i.e., do not "fallback" to task or system default
++ * policy.
++ */
+ struct mempolicy *(*get_policy)(struct vm_area_struct *vma,
+ unsigned long addr);
+ int (*migrate)(struct vm_area_struct *vma, const nodemask_t *from,
+@@ -397,11 +414,11 @@ static inline void set_compound_order(struct page *page, unsigned long order)
+ * we have run out of space and have to fall back to an
+ * alternate (slower) way of determining the node.
+ *
+- * No sparsemem: | NODE | ZONE | ... | FLAGS |
+- * with space for node: | SECTION | NODE | ZONE | ... | FLAGS |
+- * no space for node: | SECTION | ZONE | ... | FLAGS |
++ * No sparsemem or sparsemem vmemmap: | NODE | ZONE | ... | FLAGS |
++ * classic sparse with space for node:| SECTION | NODE | ZONE | ... | FLAGS |
++ * classic sparse no space for node: | SECTION | ZONE | ... | FLAGS |
+ */
+-#ifdef CONFIG_SPARSEMEM
++#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
+ #define SECTIONS_WIDTH SECTIONS_SHIFT
+ #else
+ #define SECTIONS_WIDTH 0
+@@ -409,9 +426,12 @@ static inline void set_compound_order(struct page *page, unsigned long order)
+
+ #define ZONES_WIDTH ZONES_SHIFT
+
+-#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT <= FLAGS_RESERVED
++#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS
+ #define NODES_WIDTH NODES_SHIFT
+ #else
++#ifdef CONFIG_SPARSEMEM_VMEMMAP
++#error "Vmemmap: No space for nodes field in page flags"
++#endif
+ #define NODES_WIDTH 0
+ #endif
+
+@@ -454,8 +474,8 @@ static inline void set_compound_order(struct page *page, unsigned long order)
+
+ #define ZONEID_PGSHIFT (ZONEID_PGOFF * (ZONEID_SHIFT != 0))
+
+-#if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED
+-#error SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED
++#if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > BITS_PER_LONG - NR_PAGEFLAGS
++#error SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > BITS_PER_LONG - NR_PAGEFLAGS
+ #endif
+
+ #define ZONES_MASK ((1UL << ZONES_WIDTH) - 1)
+@@ -504,10 +524,12 @@ static inline struct zone *page_zone(struct page *page)
+ return &NODE_DATA(page_to_nid(page))->node_zones[page_zonenum(page)];
+ }
+
++#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
+ static inline unsigned long page_to_section(struct page *page)
+ {
+ return (page->flags >> SECTIONS_PGSHIFT) & SECTIONS_MASK;
+ }
++#endif
+
+ static inline void set_page_zone(struct page *page, enum zone_type zone)
+ {
+@@ -602,9 +624,12 @@ static inline struct address_space *page_mapping(struct page *page)
+ struct address_space *mapping = page->mapping;
+
+ VM_BUG_ON(PageSlab(page));
++#ifdef CONFIG_SWAP
+ if (unlikely(PageSwapCache(page)))
+ mapping = &swapper_space;
+- else if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON))
++ else
++#endif
++ if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON))
+ mapping = NULL;
+ return mapping;
+ }
+@@ -649,12 +674,6 @@ static inline int page_mapped(struct page *page)
+ }
+
+ /*
+- * Error return values for the *_nopage functions
+- */
+-#define NOPAGE_SIGBUS (NULL)
+-#define NOPAGE_OOM ((struct page *) (-1))
+-
+-/*
+ * Error return values for the *_nopfn functions
+ */
+ #define NOPFN_SIGBUS ((unsigned long) -1)
+@@ -720,7 +739,9 @@ struct zap_details {
+ unsigned long truncate_count; /* Compare vm_truncate_count */
+ };
+
+-struct page *vm_normal_page(struct vm_area_struct *, unsigned long, pte_t);
++struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
++ pte_t pte);
++
+ unsigned long zap_page_range(struct vm_area_struct *vma, unsigned long address,
+ unsigned long size, struct zap_details *);
+ unsigned long unmap_vmas(struct mmu_gather **tlb,
+@@ -1045,6 +1066,19 @@ extern void unlink_file_vma(struct vm_area_struct *);
+ extern struct vm_area_struct *copy_vma(struct vm_area_struct **,
+ unsigned long addr, unsigned long len, pgoff_t pgoff);
+ extern void exit_mmap(struct mm_struct *);
++
++#ifdef CONFIG_PROC_FS
++/* From fs/proc/base.c. callers must _not_ hold the mm's exe_file_lock */
++extern void added_exe_file_vma(struct mm_struct *mm);
++extern void removed_exe_file_vma(struct mm_struct *mm);
++#else
++static inline void added_exe_file_vma(struct mm_struct *mm)
++{}
++
++static inline void removed_exe_file_vma(struct mm_struct *mm)
++{}
++#endif /* CONFIG_PROC_FS */
++
+ extern int may_expand_vm(struct mm_struct *mm, unsigned long npages);
+ extern int install_special_mapping(struct mm_struct *mm,
+ unsigned long addr, unsigned long len,
+@@ -1149,6 +1183,8 @@ int remap_pfn_range(struct vm_area_struct *, unsigned long addr,
+ int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *);
+ int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
+ unsigned long pfn);
++int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr,
++ unsigned long pfn);
+
+ struct page *follow_page(struct vm_area_struct *, unsigned long address,
+ unsigned int foll_flags);
+@@ -1207,8 +1243,6 @@ int drop_caches_sysctl_handler(struct ctl_table *, int, struct file *,
+ void __user *, size_t *, loff_t *);
+ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
+ unsigned long lru_pages);
+-void drop_pagecache(void);
+-void drop_slab(void);
+
+ #ifndef CONFIG_MMU
+ #define randomize_va_space 0
+@@ -1229,6 +1263,7 @@ void vmemmap_verify(pte_t *, int, unsigned long, unsigned long);
+ int vmemmap_populate_basepages(struct page *start_page,
+ unsigned long pages, int node);
+ int vmemmap_populate(struct page *start_page, unsigned long pages, int node);
++void vmemmap_populate_print_last(void);
+
+ #endif /* __KERNEL__ */
+ #endif /* _LINUX_MM_H */
+diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
+index af190ce..eb7c16c 100644
+--- a/include/linux/mm_types.h
++++ b/include/linux/mm_types.h
+@@ -42,7 +42,10 @@ struct page {
+ * to show when page is mapped
+ * & limit reverse map searches.
+ */
+- unsigned int inuse; /* SLUB: Nr of objects */
++ struct { /* SLUB */
++ u16 inuse;
++ u16 objects;
++ };
+ };
+ union {
+ struct {
+@@ -172,6 +175,7 @@ struct mm_struct {
+ atomic_t mm_users; /* How many users with user space? */
+ atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */
+ int map_count; /* number of VMAs */
++ int core_waiters;
+ struct rw_semaphore mmap_sem;
+ spinlock_t page_table_lock; /* Protects page tables and some counters */
+
+@@ -216,14 +220,20 @@ struct mm_struct {
+ unsigned long flags; /* Must use atomic bitops to access the bits */
+
+ /* coredumping support */
+- int core_waiters;
+ struct completion *core_startup_done, core_done;
+
+ /* aio bits */
+- rwlock_t ioctx_list_lock;
++ rwlock_t ioctx_list_lock; /* aio lock */
+ struct kioctx *ioctx_list;
+-#ifdef CONFIG_CGROUP_MEM_RES_CTLR
+- struct mem_cgroup *mem_cgroup;
++#ifdef CONFIG_MM_OWNER
++ struct task_struct *owner; /* The thread group leader that */
++ /* owns the mm_struct. */
++#endif
++
++#ifdef CONFIG_PROC_FS
++ /* store ref to file /proc/<pid>/exe symlink points to */
++ struct file *exe_file;
++ unsigned long num_exe_file_vmas;
+ #endif
+ };
+
+diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
+index 8d8d197..c463cd8 100644
+--- a/include/linux/mmzone.h
++++ b/include/linux/mmzone.h
+@@ -1,8 +1,8 @@
+ #ifndef _LINUX_MMZONE_H
+ #define _LINUX_MMZONE_H
+
+-#ifdef __KERNEL__
+ #ifndef __ASSEMBLY__
++#ifndef __GENERATING_BOUNDS_H
+
+ #include <linux/spinlock.h>
+ #include <linux/list.h>
+@@ -15,6 +15,7 @@
+ #include <linux/seqlock.h>
+ #include <linux/nodemask.h>
+ #include <linux/pageblock-flags.h>
++#include <linux/bounds.h>
+ #include <asm/atomic.h>
+ #include <asm/page.h>
+
+@@ -95,6 +96,7 @@ enum zone_stat_item {
+ NR_UNSTABLE_NFS, /* NFS unstable pages */
+ NR_BOUNCE,
+ NR_VMSCAN_WRITE,
++ NR_WRITEBACK_TEMP, /* Writeback using temporary buffers */
+ #ifdef CONFIG_NUMA
+ NUMA_HIT, /* allocated in intended node */
+ NUMA_MISS, /* allocated in non intended node */
+@@ -129,6 +131,8 @@ struct per_cpu_pageset {
+ #define zone_pcp(__z, __cpu) (&(__z)->pageset[(__cpu)])
+ #endif
+
++#endif /* !__GENERATING_BOUNDS.H */
++
+ enum zone_type {
+ #ifdef CONFIG_ZONE_DMA
+ /*
+@@ -177,9 +181,11 @@ enum zone_type {
+ ZONE_HIGHMEM,
+ #endif
+ ZONE_MOVABLE,
+- MAX_NR_ZONES
++ __MAX_NR_ZONES
+ };
+
++#ifndef __GENERATING_BOUNDS_H
+
- #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;
- };
+ /*
+ * When a memory allocation must conform to specific limitations (such
+ * as being suitable for DMA) the caller will pass in hints to the
+@@ -188,28 +194,15 @@ enum zone_type {
+ * match the requested limits. See gfp_zone() in include/linux/gfp.h
+ */
- 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;
- };
+-/*
+- * Count the active zones. Note that the use of defined(X) outside
+- * #if and family is not necessarily defined so ensure we cannot use
+- * it later. Use __ZONE_COUNT to work out how many shift bits we need.
+- */
+-#define __ZONE_COUNT ( \
+- defined(CONFIG_ZONE_DMA) \
+- + defined(CONFIG_ZONE_DMA32) \
+- + 1 \
+- + defined(CONFIG_HIGHMEM) \
+- + 1 \
+-)
+-#if __ZONE_COUNT < 2
++#if MAX_NR_ZONES < 2
+ #define ZONES_SHIFT 0
+-#elif __ZONE_COUNT <= 2
++#elif MAX_NR_ZONES <= 2
+ #define ZONES_SHIFT 1
+-#elif __ZONE_COUNT <= 4
++#elif MAX_NR_ZONES <= 4
+ #define ZONES_SHIFT 2
+ #else
+ #error ZONES_SHIFT -- too many zones configured adjust calculation
+ #endif
+-#undef __ZONE_COUNT
-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)
+ struct zone {
+ /* Fields commonly accessed by the page allocator */
+@@ -393,10 +386,10 @@ static inline int zone_is_oom_locked(const struct zone *zone)
+ * The NUMA zonelists are doubled becausse we need zonelists that restrict the
+ * allocations to a single node for GFP_THISNODE.
+ *
+- * [0 .. MAX_NR_ZONES -1] : Zonelists with fallback
+- * [MAZ_NR_ZONES ... MAZ_ZONELISTS -1] : No fallback (GFP_THISNODE)
++ * [0] : Zonelist with fallback
++ * [1] : No fallback (GFP_THISNODE)
+ */
+-#define MAX_ZONELISTS (2 * MAX_NR_ZONES)
++#define MAX_ZONELISTS 2
- 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];
+ /*
+@@ -464,11 +457,20 @@ struct zonelist_cache {
+ unsigned long last_full_zap; /* when last zap'd (jiffies) */
};
+ #else
+-#define MAX_ZONELISTS MAX_NR_ZONES
++#define MAX_ZONELISTS 1
+ struct zonelist_cache;
+ #endif
-+struct mlx4_lso_seg {
-+ __be32 mss_hdr_size;
-+ __be32 header[0];
+ /*
++ * This struct contains information about a zone in a zonelist. It is stored
++ * here to avoid dereferences into large structures and lookups of tables
++ */
++struct zoneref {
++ struct zone *zone; /* Pointer to actual zone */
++ int zone_idx; /* zone_idx(zoneref->zone) */
+};
+
- 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[];
++/*
+ * One allocation request operates on a zonelist. A zonelist
+ * is a list of zones, the first one is the 'goal' of the
+ * allocation, the other zones are fallback zones, in decreasing
+@@ -476,34 +478,23 @@ struct zonelist_cache;
+ *
+ * If zlcache_ptr is not NULL, then it is just the address of zlcache,
+ * as explained above. If zlcache_ptr is NULL, there is no zlcache.
++ * *
++ * To speed the reading of the zonelist, the zonerefs contain the zone index
++ * of the entry being read. Helper functions to access information given
++ * a struct zoneref are
++ *
++ * zonelist_zone() - Return the struct zone * for an entry in _zonerefs
++ * zonelist_zone_idx() - Return the index of the zone for an entry
++ * zonelist_node_idx() - Return the index of the node for an entry
+ */
+-
+ struct zonelist {
+ struct zonelist_cache *zlcache_ptr; // NULL or &zlcache
+- struct zone *zones[MAX_ZONES_PER_ZONELIST + 1]; // NULL delimited
++ struct zoneref _zonerefs[MAX_ZONES_PER_ZONELIST + 1];
+ #ifdef CONFIG_NUMA
+ struct zonelist_cache zlcache; // optional ...
+ #endif
+ };
+
+-#ifdef CONFIG_NUMA
+-/*
+- * Only custom zonelists like MPOL_BIND need to be filtered as part of
+- * policies. As described in the comment for struct zonelist_cache, these
+- * zonelists will not have a zlcache so zlcache_ptr will not be set. Use
+- * that to determine if the zonelists needs to be filtered or not.
+- */
+-static inline int alloc_should_filter_zonelist(struct zonelist *zonelist)
+-{
+- return !zonelist->zlcache_ptr;
+-}
+-#else
+-static inline int alloc_should_filter_zonelist(struct zonelist *zonelist)
+-{
+- return 0;
+-}
+-#endif /* CONFIG_NUMA */
+-
+ #ifdef CONFIG_ARCH_POPULATES_NODE_MAP
+ struct node_active_region {
+ unsigned long start_pfn;
+@@ -637,9 +628,10 @@ static inline int is_normal_idx(enum zone_type idx)
+ static inline int is_highmem(struct zone *zone)
+ {
+ #ifdef CONFIG_HIGHMEM
+- int zone_idx = zone - zone->zone_pgdat->node_zones;
+- return zone_idx == ZONE_HIGHMEM ||
+- (zone_idx == ZONE_MOVABLE && zone_movable_is_highmem());
++ int zone_off = (char *)zone - (char *)zone->zone_pgdat->node_zones;
++ return zone_off == ZONE_HIGHMEM * sizeof(*zone) ||
++ (zone_off == ZONE_MOVABLE * sizeof(*zone) &&
++ zone_movable_is_highmem());
+ #else
+ return 0;
+ #endif
+@@ -699,7 +691,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
@@ -816756,6 +1091549,141 @@
#else /* CONFIG_NEED_MULTIPLE_NODES */
+@@ -731,32 +722,103 @@ extern struct zone *next_zone(struct zone *zone);
+ zone; \
+ zone = next_zone(zone))
+
+-#ifdef CONFIG_SPARSEMEM
+-#include <asm/sparsemem.h>
+-#endif
++static inline struct zone *zonelist_zone(struct zoneref *zoneref)
++{
++ return zoneref->zone;
++}
+
+-#if BITS_PER_LONG == 32
+-/*
+- * with 32 bit page->flags field, we reserve 9 bits for node/zone info.
+- * there are 4 zones (3 bits) and this leaves 9-3=6 bits for nodes.
++static inline int zonelist_zone_idx(struct zoneref *zoneref)
++{
++ return zoneref->zone_idx;
++}
++
++static inline int zonelist_node_idx(struct zoneref *zoneref)
++{
++#ifdef CONFIG_NUMA
++ /* zone_to_nid not available in this context */
++ return zoneref->zone->node;
++#else
++ return 0;
++#endif /* CONFIG_NUMA */
++}
++
++/**
++ * next_zones_zonelist - Returns the next zone at or below highest_zoneidx within the allowed nodemask using a cursor within a zonelist as a starting point
++ * @z - The cursor used as a starting point for the search
++ * @highest_zoneidx - The zone index of the highest zone to return
++ * @nodes - An optional nodemask to filter the zonelist with
++ * @zone - The first suitable zone found is returned via this parameter
++ *
++ * This function returns the next zone at or below a given zone index that is
++ * within the allowed nodemask using a cursor as the starting point for the
++ * search. The zoneref returned is a cursor that is used as the next starting
++ * point for future calls to next_zones_zonelist().
+ */
+-#define FLAGS_RESERVED 9
++struct zoneref *next_zones_zonelist(struct zoneref *z,
++ enum zone_type highest_zoneidx,
++ nodemask_t *nodes,
++ struct zone **zone);
+
+-#elif BITS_PER_LONG == 64
+-/*
+- * with 64 bit flags field, there's plenty of room.
++/**
++ * first_zones_zonelist - Returns the first zone at or below highest_zoneidx within the allowed nodemask in a zonelist
++ * @zonelist - The zonelist to search for a suitable zone
++ * @highest_zoneidx - The zone index of the highest zone to return
++ * @nodes - An optional nodemask to filter the zonelist with
++ * @zone - The first suitable zone found is returned via this parameter
++ *
++ * This function returns the first zone at or below a given zone index that is
++ * within the allowed nodemask. The zoneref returned is a cursor that can be
++ * used to iterate the zonelist with next_zones_zonelist. The cursor should
++ * not be used by the caller as it does not match the value of the zone
++ * returned.
+ */
+-#define FLAGS_RESERVED 32
++static inline struct zoneref *first_zones_zonelist(struct zonelist *zonelist,
++ enum zone_type highest_zoneidx,
++ nodemask_t *nodes,
++ struct zone **zone)
++{
++ return next_zones_zonelist(zonelist->_zonerefs, highest_zoneidx, nodes,
++ zone);
++}
+
+-#else
++/**
++ * for_each_zone_zonelist_nodemask - helper macro to iterate over valid zones in a zonelist at or below a given zone index and within a nodemask
++ * @zone - The current zone in the iterator
++ * @z - The current pointer within zonelist->zones being iterated
++ * @zlist - The zonelist being iterated
++ * @highidx - The zone index of the highest zone to return
++ * @nodemask - Nodemask allowed by the allocator
++ *
++ * This iterator iterates though all zones at or below a given zone index and
++ * within a given nodemask
++ */
++#define for_each_zone_zonelist_nodemask(zone, z, zlist, highidx, nodemask) \
++ for (z = first_zones_zonelist(zlist, highidx, nodemask, &zone); \
++ zone; \
++ z = next_zones_zonelist(z, highidx, nodemask, &zone)) \
+
+-#error BITS_PER_LONG not defined
++/**
++ * for_each_zone_zonelist - helper macro to iterate over valid zones in a zonelist at or below a given zone index
++ * @zone - The current zone in the iterator
++ * @z - The current pointer within zonelist->zones being iterated
++ * @zlist - The zonelist being iterated
++ * @highidx - The zone index of the highest zone to return
++ *
++ * This iterator iterates though all zones at or below a given zone index.
++ */
++#define for_each_zone_zonelist(zone, z, zlist, highidx) \
++ for_each_zone_zonelist_nodemask(zone, z, zlist, highidx, NULL)
+
++#ifdef CONFIG_SPARSEMEM
++#include <asm/sparsemem.h>
+ #endif
+
+ #if !defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID) && \
+ !defined(CONFIG_ARCH_POPULATES_NODE_MAP)
+-#define early_pfn_to_nid(nid) (0UL)
++static inline unsigned long early_pfn_to_nid(unsigned long pfn)
++{
++ return 0;
++}
+ #endif
+
+ #ifdef CONFIG_FLATMEM
+@@ -834,6 +896,7 @@ static inline struct mem_section *__nr_to_section(unsigned long nr)
+ return &mem_section[SECTION_NR_TO_ROOT(nr)][nr & SECTION_ROOT_MASK];
+ }
+ extern int __section_nr(struct mem_section* ms);
++extern unsigned long usemap_size(void);
+
+ /*
+ * We use the lower bits of the mem_map pointer to store
+@@ -939,6 +1002,6 @@ unsigned long __init node_memmap_size_bytes(int, unsigned long, unsigned long);
+ #define pfn_valid_within(pfn) (1)
+ #endif
+
++#endif /* !__GENERATING_BOUNDS.H */
+ #endif /* !__ASSEMBLY__ */
+-#endif /* __KERNEL__ */
+ #endif /* _LINUX_MMZONE_H */
diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
index 8eed44f..830bbcd 100644
--- a/include/linux/mnt_namespace.h
@@ -816792,11 +1091720,35 @@
+
#endif
#endif
+diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
+index 139d49d..d73ecea 100644
+--- a/include/linux/mod_devicetable.h
++++ b/include/linux/mod_devicetable.h
+@@ -368,4 +368,15 @@ struct virtio_device_id {
+ };
+ #define VIRTIO_DEV_ANY_ID 0xffffffff
+
++/* i2c */
++
++#define I2C_NAME_SIZE 20
++#define I2C_MODULE_PREFIX "i2c:"
++
++struct i2c_device_id {
++ char name[I2C_NAME_SIZE];
++ kernel_ulong_t driver_data; /* Data private to the driver */
++};
++
++
+ #endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/mount.h b/include/linux/mount.h
-index 5ee2df2..b4836d5 100644
+index 5ee2df2..4374d1a 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
-@@ -14,6 +14,7 @@
+@@ -10,10 +10,10 @@
+ */
+ #ifndef _LINUX_MOUNT_H
+ #define _LINUX_MOUNT_H
+-#ifdef __KERNEL__
#include <linux/types.h>
#include <linux/list.h>
@@ -816804,7 +1091756,7 @@
#include <linux/spinlock.h>
#include <asm/atomic.h>
-@@ -28,8 +29,10 @@ struct mnt_namespace;
+@@ -28,8 +28,10 @@ struct mnt_namespace;
#define MNT_NOATIME 0x08
#define MNT_NODIRATIME 0x10
#define MNT_RELATIME 0x20
@@ -816815,7 +1091767,7 @@
#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 {
+@@ -53,6 +55,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 */
@@ -816824,7 +1091776,7 @@
/*
* 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 {
+@@ -62,6 +66,11 @@ struct vfsmount {
int mnt_expiry_mark; /* true if marked for expiry */
int mnt_pinned;
int mnt_ghosts;
@@ -816836,7 +1091788,7 @@
};
static inline struct vfsmount *mntget(struct vfsmount *mnt)
-@@ -71,9 +81,12 @@ static inline struct vfsmount *mntget(struct vfsmount *mnt)
+@@ -71,9 +80,12 @@ static inline struct vfsmount *mntget(struct vfsmount *mnt)
return mnt;
}
@@ -816849,7 +1091801,7 @@
static inline void mntput(struct vfsmount *mnt)
{
-@@ -83,8 +96,6 @@ static inline void mntput(struct vfsmount *mnt)
+@@ -83,8 +95,6 @@ static inline void mntput(struct vfsmount *mnt)
}
}
@@ -816858,6 +1091810,12 @@
extern struct vfsmount *do_kern_mount(const char *fstype, int flags,
const char *name, void *data);
+@@ -103,5 +113,4 @@ extern void mark_mounts_for_expiry(struct list_head *mounts);
+ extern spinlock_t vfsmount_lock;
+ extern dev_t name_to_dev_t(char *name);
+
+-#endif
+ #endif /* _LINUX_MOUNT_H */
diff --git a/include/linux/mroute.h b/include/linux/mroute.h
index 35a8277..de4decf 100644
--- a/include/linux/mroute.h
@@ -817136,6 +1092094,93 @@
+};
+
+#endif
+diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
+index f950921..b03b274 100644
+--- a/include/linux/msdos_fs.h
++++ b/include/linux/msdos_fs.h
+@@ -58,7 +58,11 @@
+ #define MSDOS_DOTDOT ".. " /* "..", padded to MSDOS_NAME chars */
+
+ /* media of boot sector */
+-#define FAT_VALID_MEDIA(x) ((0xF8 <= (x) && (x) <= 0xFF) || (x) == 0xF0)
++static inline int fat_valid_media(u8 media)
++{
++ return 0xf8 <= media || media == 0xf0;
++}
++
+ #define FAT_FIRST_ENT(s, x) ((MSDOS_SB(s)->fat_bits == 32 ? 0x0FFFFF00 : \
+ MSDOS_SB(s)->fat_bits == 16 ? 0xFF00 : 0xF00) | (x))
+
+@@ -195,6 +199,7 @@ struct fat_mount_options {
+ char *iocharset; /* Charset used for filename input/display */
+ unsigned short shortname; /* flags for shortname display/create rule */
+ unsigned char name_check; /* r = relaxed, n = normal, s = strict */
++ unsigned short allow_utime;/* permission for setting the [am]time */
+ unsigned quiet:1, /* set = fake successful chmods and chowns */
+ showexec:1, /* set = only set x bit for com/exe/bat */
+ sys_immutable:1, /* set = system files are immutable */
+@@ -232,6 +237,7 @@ struct msdos_sb_info {
+ struct mutex fat_lock;
+ unsigned int prev_free; /* previously allocated cluster number */
+ unsigned int free_clusters; /* -1 if undefined */
++ unsigned int free_clus_valid; /* is free_clusters valid? */
+ struct fat_mount_options options;
+ struct nls_table *nls_disk; /* Codepage used on disk */
+ struct nls_table *nls_io; /* Charset used for input and display */
+@@ -401,7 +407,7 @@ extern int fat_generic_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+ extern const struct file_operations fat_file_operations;
+ extern const struct inode_operations fat_file_inode_operations;
+-extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
++extern int fat_setattr(struct dentry * dentry, struct iattr * attr);
+ extern void fat_truncate(struct inode *inode);
+ extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat);
+diff --git a/include/linux/msg.h b/include/linux/msg.h
+index 10a3d5a..6f3b8e7 100644
+--- a/include/linux/msg.h
++++ b/include/linux/msg.h
+@@ -49,16 +49,26 @@ struct msginfo {
+ unsigned short msgseg;
+ };
+
++/*
++ * Scaling factor to compute msgmni:
++ * the memory dedicated to msg queues (msgmni * msgmnb) should occupy
++ * at most 1/MSG_MEM_SCALE of the lowmem (see the formula in ipc/msg.c):
++ * up to 8MB : msgmni = 16 (MSGMNI)
++ * 4 GB : msgmni = 8K
++ * more than 16 GB : msgmni = 32K (IPCMNI)
++ */
++#define MSG_MEM_SCALE 32
++
+ #define MSGMNI 16 /* <= IPCMNI */ /* max # of msg queue identifiers */
+ #define MSGMAX 8192 /* <= INT_MAX */ /* max size of message (bytes) */
+ #define MSGMNB 16384 /* <= INT_MAX */ /* default max size of a message queue */
+
+ /* unused */
+-#define MSGPOOL (MSGMNI*MSGMNB/1024) /* size in kilobytes of message pool */
++#define MSGPOOL (MSGMNI * MSGMNB) /* size in bytes of message pool */
+ #define MSGTQL MSGMNB /* number of system message headers */
+ #define MSGMAP MSGMNB /* number of entries in message map */
+ #define MSGSSZ 16 /* message segment size */
+-#define __MSGSEG ((MSGPOOL*1024)/ MSGSSZ) /* max no. of segments */
++#define __MSGSEG (MSGPOOL / MSGSSZ) /* max no. of segments */
+ #define MSGSEG (__MSGSEG <= 0xffff ? __MSGSEG : 0xffff)
+
+ #ifdef __KERNEL__
+diff --git a/include/linux/msi.h b/include/linux/msi.h
+index 94bb46d..8f29392 100644
+--- a/include/linux/msi.h
++++ b/include/linux/msi.h
+@@ -22,6 +22,7 @@ struct msi_desc {
+ __u8 masked : 1;
+ __u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */
+ __u8 pos; /* Location of the msi capability */
++ __u32 maskbits_mask; /* mask bits mask */
+ __u16 entry_nr; /* specific enabled entry */
+ unsigned default_irq; /* default pre-assigned irq */
+ }msi_attrib;
diff --git a/include/linux/mtd/inftl.h b/include/linux/mtd/inftl.h
index 6977780..85fd041 100644
--- a/include/linux/mtd/inftl.h
@@ -817208,6 +1092253,81 @@
/* The mode parameters to be controlled. Parameter chosen with bits 20-28 */
#define MT_ST_CLEAR_DEFAULT 0xfffff
+diff --git a/include/linux/nbd.h b/include/linux/nbd.h
+index 9865720..155719d 100644
+--- a/include/linux/nbd.h
++++ b/include/linux/nbd.h
+@@ -56,9 +56,11 @@ struct nbd_device {
+ int magic;
+
+ spinlock_t queue_lock;
+- struct list_head queue_head;/* Requests are added here... */
++ struct list_head queue_head; /* Requests waiting result */
+ struct request *active_req;
+ wait_queue_head_t active_wq;
++ struct list_head waiting_queue; /* Requests to be sent */
++ wait_queue_head_t waiting_wq;
+
+ struct mutex tx_lock;
+ struct gendisk *disk;
+@@ -86,11 +88,7 @@ struct nbd_request {
+ char handle[8];
+ __be64 from;
+ __be32 len;
+-}
+-#ifdef __GNUC__
+- __attribute__ ((packed))
+-#endif
+-;
++} __attribute__ ((packed));
+
+ /*
+ * This is the reply packet that nbd-server sends back to the client after
+diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
+index 88766e4..9f2d763 100644
+--- a/include/linux/ncp_fs.h
++++ b/include/linux/ncp_fs.h
+@@ -204,6 +204,7 @@ void ncp_update_inode2(struct inode *, struct ncp_entry_info *);
+ /* linux/fs/ncpfs/dir.c */
+ extern const struct inode_operations ncp_dir_inode_operations;
+ extern const struct file_operations ncp_dir_operations;
++extern struct dentry_operations ncp_root_dentry_operations;
+ int ncp_conn_logged_in(struct super_block *);
+ int ncp_date_dos2unix(__le16 time, __le16 date);
+ void ncp_date_unix2dos(int unix_date, __le16 * time, __le16 * date);
+@@ -223,6 +224,12 @@ int ncp_disconnect(struct ncp_server *server);
+ void ncp_lock_server(struct ncp_server *server);
+ void ncp_unlock_server(struct ncp_server *server);
+
++/* linux/fs/ncpfs/symlink.c */
++#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
++extern const struct address_space_operations ncp_symlink_aops;
++int ncp_symlink(struct inode*, struct dentry*, const char*);
++#endif
++
+ /* linux/fs/ncpfs/file.c */
+ extern const struct inode_operations ncp_file_inode_operations;
+ extern const struct file_operations ncp_file_operations;
+diff --git a/include/linux/ncp_fs_i.h b/include/linux/ncp_fs_i.h
+index bdb4c8a..4b0bec4 100644
+--- a/include/linux/ncp_fs_i.h
++++ b/include/linux/ncp_fs_i.h
+@@ -8,8 +8,6 @@
+ #ifndef _LINUX_NCP_FS_I
+ #define _LINUX_NCP_FS_I
+
+-#ifdef __KERNEL__
+-
+ /*
+ * This is the ncpfs part of the inode structure. This must contain
+ * all the information we need to work with an inode after creation.
+@@ -28,6 +26,4 @@ struct ncp_inode_info {
+ struct inode vfs_inode;
+ };
+
+-#endif /* __KERNEL__ */
+-
+ #endif /* _LINUX_NCP_FS_I */
diff --git a/include/linux/net.h b/include/linux/net.h
index c414d90..71f7dd5 100644
--- a/include/linux/net.h
@@ -817917,6 +1093037,18 @@
NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
NF_IP_PRI_LAST = INT_MAX,
};
+diff --git a/include/linux/netlink.h b/include/linux/netlink.h
+index fb0713b..bec1062 100644
+--- a/include/linux/netlink.h
++++ b/include/linux/netlink.h
+@@ -166,6 +166,7 @@ struct netlink_skb_parms
+ __u32 dst_group;
+ kernel_cap_t eff_cap;
+ __u32 loginuid; /* Login (audit) uid */
++ __u32 sessionid; /* Session id (audit) */
+ __u32 sid; /* SELinux security id */
+ };
+
diff --git a/include/linux/nfs3.h b/include/linux/nfs3.h
index 7f11fa5..539f3b5 100644
--- a/include/linux/nfs3.h
@@ -818395,6 +1093527,76 @@
};
#endif /* __LINUX_NL80211_H */
+diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
+index 905e18f..848025c 100644
+--- a/include/linux/nodemask.h
++++ b/include/linux/nodemask.h
+@@ -14,6 +14,8 @@
+ * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c.
+ * For details of node_remap(), see bitmap_bitremap in lib/bitmap.c.
+ * For details of nodes_remap(), see bitmap_remap in lib/bitmap.c.
++ * For details of nodes_onto(), see bitmap_onto in lib/bitmap.c.
++ * For details of nodes_fold(), see bitmap_fold in lib/bitmap.c.
+ *
+ * The available nodemask operations are:
+ *
+@@ -55,7 +57,9 @@
+ * int nodelist_scnprintf(buf, len, mask) Format nodemask as list for printing
+ * int nodelist_parse(buf, map) Parse ascii string as nodelist
+ * int node_remap(oldbit, old, new) newbit = map(old, new)(oldbit)
+- * int nodes_remap(dst, src, old, new) *dst = map(old, new)(dst)
++ * void nodes_remap(dst, src, old, new) *dst = map(old, new)(src)
++ * void nodes_onto(dst, orig, relmap) *dst = orig relative to relmap
++ * void nodes_fold(dst, orig, sz) dst bits = orig bits mod sz
+ *
+ * for_each_node_mask(node, mask) for-loop node over mask
+ *
+@@ -326,6 +330,22 @@ static inline void __nodes_remap(nodemask_t *dstp, const nodemask_t *srcp,
+ bitmap_remap(dstp->bits, srcp->bits, oldp->bits, newp->bits, nbits);
+ }
+
++#define nodes_onto(dst, orig, relmap) \
++ __nodes_onto(&(dst), &(orig), &(relmap), MAX_NUMNODES)
++static inline void __nodes_onto(nodemask_t *dstp, const nodemask_t *origp,
++ const nodemask_t *relmapp, int nbits)
++{
++ bitmap_onto(dstp->bits, origp->bits, relmapp->bits, nbits);
++}
++
++#define nodes_fold(dst, orig, sz) \
++ __nodes_fold(&(dst), &(orig), sz, MAX_NUMNODES)
++static inline void __nodes_fold(nodemask_t *dstp, const nodemask_t *origp,
++ int sz, int nbits)
++{
++ bitmap_fold(dstp->bits, origp->bits, sz, nbits);
++}
++
+ #if MAX_NUMNODES > 1
+ #define for_each_node_mask(node, mask) \
+ for ((node) = first_node(mask); \
+diff --git a/include/linux/notifier.h b/include/linux/notifier.h
+index f4df400..0ff6224 100644
+--- a/include/linux/notifier.h
++++ b/include/linux/notifier.h
+@@ -121,6 +121,10 @@ extern int raw_notifier_chain_register(struct raw_notifier_head *nh,
+ extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
+ struct notifier_block *nb);
+
++extern int blocking_notifier_chain_cond_register(
++ struct blocking_notifier_head *nh,
++ struct notifier_block *nb);
++
+ extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
+ struct notifier_block *nb);
+ extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
+@@ -247,6 +251,7 @@ extern struct blocking_notifier_head reboot_notifier_list;
+ #define VT_DEALLOCATE 0x0002 /* Console will be deallocated */
+ #define VT_WRITE 0x0003 /* A char got output */
+ #define VT_UPDATE 0x0004 /* A bigger update occurred */
++#define VT_PREWRITE 0x0005 /* A char is about to be written to the console */
+
+ #endif /* __KERNEL__ */
+ #endif /* _LINUX_NOTIFIER_H */
diff --git a/include/linux/of.h b/include/linux/of.h
index 6981016..59a61bd 100644
--- a/include/linux/of.h
@@ -818407,6 +1093609,23 @@
extern const void *of_get_property(const struct device_node *node,
const char *name,
int *lenp);
+diff --git a/include/linux/of_device.h b/include/linux/of_device.h
+index 6dc1195..afe3382 100644
+--- a/include/linux/of_device.h
++++ b/include/linux/of_device.h
+@@ -1,6 +1,5 @@
+ #ifndef _LINUX_OF_DEVICE_H
+ #define _LINUX_OF_DEVICE_H
+-#ifdef __KERNEL__
+
+ #include <linux/device.h>
+ #include <linux/of.h>
+@@ -25,5 +24,4 @@ static inline void of_device_free(struct of_device *dev)
+ of_release_dev(&dev->dev);
+ }
+
+-#endif /* __KERNEL__ */
+ #endif /* _LINUX_OF_DEVICE_H */
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
new file mode 100644
index 0000000..2ee97e9
@@ -818512,6 +1093731,402 @@
+#endif /* CONFIG_OF_I2C */
+
+#endif /* __LINUX_OF_I2C_H */
+diff --git a/include/linux/oom.h b/include/linux/oom.h
+index 3852436..a7979ba 100644
+--- a/include/linux/oom.h
++++ b/include/linux/oom.h
+@@ -23,8 +23,8 @@ enum oom_constraint {
+ CONSTRAINT_MEMORY_POLICY,
+ };
+
+-extern int try_set_zone_oom(struct zonelist *zonelist);
+-extern void clear_zonelist_oom(struct zonelist *zonelist);
++extern int try_set_zone_oom(struct zonelist *zonelist, gfp_t gfp_flags);
++extern void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_flags);
+
+ extern void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order);
+ extern int register_oom_notifier(struct notifier_block *nb);
+diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
+index b5b30f1..590cff3 100644
+--- a/include/linux/page-flags.h
++++ b/include/linux/page-flags.h
+@@ -6,7 +6,10 @@
+ #define PAGE_FLAGS_H
+
+ #include <linux/types.h>
++#ifndef __GENERATING_BOUNDS_H
+ #include <linux/mm_types.h>
++#include <linux/bounds.h>
++#endif /* !__GENERATING_BOUNDS_H */
+
+ /*
+ * Various page->flags bits:
+@@ -59,77 +62,138 @@
+ * extends from the high bits downwards.
+ *
+ * | FIELD | ... | FLAGS |
+- * N-1 ^ 0
+- * (N-FLAGS_RESERVED)
++ * N-1 ^ 0
++ * (NR_PAGEFLAGS)
+ *
+- * The fields area is reserved for fields mapping zone, node and SPARSEMEM
+- * section. The boundry between these two areas is defined by
+- * FLAGS_RESERVED which defines the width of the fields section
+- * (see linux/mmzone.h). New flags must _not_ overlap with this area.
++ * The fields area is reserved for fields mapping zone, node (for NUMA) and
++ * SPARSEMEM section (for variants of SPARSEMEM that require section ids like
++ * SPARSEMEM_EXTREME with !SPARSEMEM_VMEMMAP).
+ */
+-#define PG_locked 0 /* Page is locked. Don't touch. */
+-#define PG_error 1
+-#define PG_referenced 2
+-#define PG_uptodate 3
++enum pageflags {
++ PG_locked, /* Page is locked. Don't touch. */
++ PG_error,
++ PG_referenced,
++ PG_uptodate,
++ PG_dirty,
++ PG_lru,
++ PG_active,
++ PG_slab,
++ PG_owner_priv_1, /* Owner use. If pagecache, fs may use*/
++ PG_arch_1,
++ PG_reserved,
++ PG_private, /* If pagecache, has fs-private data */
++ PG_writeback, /* Page is under writeback */
++#ifdef CONFIG_PAGEFLAGS_EXTENDED
++ PG_head, /* A head page */
++ PG_tail, /* A tail page */
++#else
++ PG_compound, /* A compound page */
++#endif
++ PG_swapcache, /* Swap page: swp_entry_t in private */
++ PG_mappedtodisk, /* Has blocks allocated on-disk */
++ PG_reclaim, /* To be reclaimed asap */
++ PG_buddy, /* Page is free, on buddy lists */
++#ifdef CONFIG_IA64_UNCACHED_ALLOCATOR
++ PG_uncached, /* Page has been mapped as uncached */
++#endif
++ __NR_PAGEFLAGS
++};
++
++#ifndef __GENERATING_BOUNDS_H
++
++/*
++ * Macros to create function definitions for page flags
++ */
++#define TESTPAGEFLAG(uname, lname) \
++static inline int Page##uname(struct page *page) \
++ { return test_bit(PG_##lname, &page->flags); }
+
+-#define PG_dirty 4
+-#define PG_lru 5
+-#define PG_active 6
+-#define PG_slab 7 /* slab debug (Suparna wants this) */
++#define SETPAGEFLAG(uname, lname) \
++static inline void SetPage##uname(struct page *page) \
++ { set_bit(PG_##lname, &page->flags); }
+
+-#define PG_owner_priv_1 8 /* Owner use. If pagecache, fs may use*/
+-#define PG_arch_1 9
+-#define PG_reserved 10
+-#define PG_private 11 /* If pagecache, has fs-private data */
++#define CLEARPAGEFLAG(uname, lname) \
++static inline void ClearPage##uname(struct page *page) \
++ { clear_bit(PG_##lname, &page->flags); }
+
+-#define PG_writeback 12 /* Page is under writeback */
+-#define PG_compound 14 /* Part of a compound page */
+-#define PG_swapcache 15 /* Swap page: swp_entry_t in private */
++#define __SETPAGEFLAG(uname, lname) \
++static inline void __SetPage##uname(struct page *page) \
++ { __set_bit(PG_##lname, &page->flags); }
+
+-#define PG_mappedtodisk 16 /* Has blocks allocated on-disk */
+-#define PG_reclaim 17 /* To be reclaimed asap */
+-#define PG_buddy 19 /* Page is free, on buddy lists */
++#define __CLEARPAGEFLAG(uname, lname) \
++static inline void __ClearPage##uname(struct page *page) \
++ { __clear_bit(PG_##lname, &page->flags); }
++
++#define TESTSETFLAG(uname, lname) \
++static inline int TestSetPage##uname(struct page *page) \
++ { return test_and_set_bit(PG_##lname, &page->flags); }
++
++#define TESTCLEARFLAG(uname, lname) \
++static inline int TestClearPage##uname(struct page *page) \
++ { return test_and_clear_bit(PG_##lname, &page->flags); }
+
+-/* PG_readahead is only used for file reads; PG_reclaim is only for writes */
+-#define PG_readahead PG_reclaim /* Reminder to do async read-ahead */
+
+-/* PG_owner_priv_1 users should have descriptive aliases */
+-#define PG_checked PG_owner_priv_1 /* Used by some filesystems */
+-#define PG_pinned PG_owner_priv_1 /* Xen pinned pagetable */
++#define PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \
++ SETPAGEFLAG(uname, lname) CLEARPAGEFLAG(uname, lname)
++
++#define __PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \
++ __SETPAGEFLAG(uname, lname) __CLEARPAGEFLAG(uname, lname)
++
++#define PAGEFLAG_FALSE(uname) \
++static inline int Page##uname(struct page *page) \
++ { return 0; }
++
++#define TESTSCFLAG(uname, lname) \
++ TESTSETFLAG(uname, lname) TESTCLEARFLAG(uname, lname)
++
++struct page; /* forward declaration */
++
++PAGEFLAG(Locked, locked) TESTSCFLAG(Locked, locked)
++PAGEFLAG(Error, error)
++PAGEFLAG(Referenced, referenced) TESTCLEARFLAG(Referenced, referenced)
++PAGEFLAG(Dirty, dirty) TESTSCFLAG(Dirty, dirty) __CLEARPAGEFLAG(Dirty, dirty)
++PAGEFLAG(LRU, lru) __CLEARPAGEFLAG(LRU, lru)
++PAGEFLAG(Active, active) __CLEARPAGEFLAG(Active, active)
++__PAGEFLAG(Slab, slab)
++PAGEFLAG(Checked, owner_priv_1) /* Used by some filesystems */
++PAGEFLAG(Pinned, owner_priv_1) TESTSCFLAG(Pinned, owner_priv_1) /* Xen */
++PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved)
++PAGEFLAG(Private, private) __CLEARPAGEFLAG(Private, private)
++ __SETPAGEFLAG(Private, private)
+
+-#if (BITS_PER_LONG > 32)
+ /*
+- * 64-bit-only flags build down from bit 31
+- *
+- * 32 bit -------------------------------| FIELDS | FLAGS |
+- * 64 bit | FIELDS | ?????? FLAGS |
+- * 63 32 0
++ * Only test-and-set exist for PG_writeback. The unconditional operators are
++ * risky: they bypass page accounting.
+ */
+-#define PG_uncached 31 /* Page has been mapped as uncached */
+-#endif
++TESTPAGEFLAG(Writeback, writeback) TESTSCFLAG(Writeback, writeback)
++__PAGEFLAG(Buddy, buddy)
++PAGEFLAG(MappedToDisk, mappedtodisk)
+
++/* PG_readahead is only used for file reads; PG_reclaim is only for writes */
++PAGEFLAG(Reclaim, reclaim) TESTCLEARFLAG(Reclaim, reclaim)
++PAGEFLAG(Readahead, reclaim) /* Reminder to do async read-ahead */
++
++#ifdef CONFIG_HIGHMEM
+ /*
+- * Manipulation of page state flags
++ * Must use a macro here due to header dependency issues. page_zone() is not
++ * available at this point.
+ */
+-#define PageLocked(page) \
+- test_bit(PG_locked, &(page)->flags)
+-#define SetPageLocked(page) \
+- set_bit(PG_locked, &(page)->flags)
+-#define TestSetPageLocked(page) \
+- test_and_set_bit(PG_locked, &(page)->flags)
+-#define ClearPageLocked(page) \
+- clear_bit(PG_locked, &(page)->flags)
+-#define TestClearPageLocked(page) \
+- test_and_clear_bit(PG_locked, &(page)->flags)
+-
+-#define PageError(page) test_bit(PG_error, &(page)->flags)
+-#define SetPageError(page) set_bit(PG_error, &(page)->flags)
+-#define ClearPageError(page) clear_bit(PG_error, &(page)->flags)
+-
+-#define PageReferenced(page) test_bit(PG_referenced, &(page)->flags)
+-#define SetPageReferenced(page) set_bit(PG_referenced, &(page)->flags)
+-#define ClearPageReferenced(page) clear_bit(PG_referenced, &(page)->flags)
+-#define TestClearPageReferenced(page) test_and_clear_bit(PG_referenced, &(page)->flags)
++#define PageHighMem(__p) is_highmem(page_zone(__p))
++#else
++PAGEFLAG_FALSE(HighMem)
++#endif
++
++#ifdef CONFIG_SWAP
++PAGEFLAG(SwapCache, swapcache)
++#else
++PAGEFLAG_FALSE(SwapCache)
++#endif
++
++#ifdef CONFIG_IA64_UNCACHED_ALLOCATOR
++PAGEFLAG(Uncached, uncached)
++#else
++PAGEFLAG_FALSE(Uncached)
++#endif
+
+ static inline int PageUptodate(struct page *page)
+ {
+@@ -177,97 +241,59 @@ static inline void SetPageUptodate(struct page *page)
+ #endif
+ }
+
+-#define ClearPageUptodate(page) clear_bit(PG_uptodate, &(page)->flags)
+-
+-#define PageDirty(page) test_bit(PG_dirty, &(page)->flags)
+-#define SetPageDirty(page) set_bit(PG_dirty, &(page)->flags)
+-#define TestSetPageDirty(page) test_and_set_bit(PG_dirty, &(page)->flags)
+-#define ClearPageDirty(page) clear_bit(PG_dirty, &(page)->flags)
+-#define __ClearPageDirty(page) __clear_bit(PG_dirty, &(page)->flags)
+-#define TestClearPageDirty(page) test_and_clear_bit(PG_dirty, &(page)->flags)
+-
+-#define PageLRU(page) test_bit(PG_lru, &(page)->flags)
+-#define SetPageLRU(page) set_bit(PG_lru, &(page)->flags)
+-#define ClearPageLRU(page) clear_bit(PG_lru, &(page)->flags)
+-#define __ClearPageLRU(page) __clear_bit(PG_lru, &(page)->flags)
+-
+-#define PageActive(page) test_bit(PG_active, &(page)->flags)
+-#define SetPageActive(page) set_bit(PG_active, &(page)->flags)
+-#define ClearPageActive(page) clear_bit(PG_active, &(page)->flags)
+-#define __ClearPageActive(page) __clear_bit(PG_active, &(page)->flags)
+-
+-#define PageSlab(page) test_bit(PG_slab, &(page)->flags)
+-#define __SetPageSlab(page) __set_bit(PG_slab, &(page)->flags)
+-#define __ClearPageSlab(page) __clear_bit(PG_slab, &(page)->flags)
+-
+-#ifdef CONFIG_HIGHMEM
+-#define PageHighMem(page) is_highmem(page_zone(page))
+-#else
+-#define PageHighMem(page) 0 /* needed to optimize away at compile time */
+-#endif
++CLEARPAGEFLAG(Uptodate, uptodate)
+
+-#define PageChecked(page) test_bit(PG_checked, &(page)->flags)
+-#define SetPageChecked(page) set_bit(PG_checked, &(page)->flags)
+-#define ClearPageChecked(page) clear_bit(PG_checked, &(page)->flags)
+-
+-#define PagePinned(page) test_bit(PG_pinned, &(page)->flags)
+-#define SetPagePinned(page) set_bit(PG_pinned, &(page)->flags)
+-#define ClearPagePinned(page) clear_bit(PG_pinned, &(page)->flags)
++extern void cancel_dirty_page(struct page *page, unsigned int account_size);
+
+-#define PageReserved(page) test_bit(PG_reserved, &(page)->flags)
+-#define SetPageReserved(page) set_bit(PG_reserved, &(page)->flags)
+-#define ClearPageReserved(page) clear_bit(PG_reserved, &(page)->flags)
+-#define __ClearPageReserved(page) __clear_bit(PG_reserved, &(page)->flags)
++int test_clear_page_writeback(struct page *page);
++int test_set_page_writeback(struct page *page);
+
+-#define SetPagePrivate(page) set_bit(PG_private, &(page)->flags)
+-#define ClearPagePrivate(page) clear_bit(PG_private, &(page)->flags)
+-#define PagePrivate(page) test_bit(PG_private, &(page)->flags)
+-#define __SetPagePrivate(page) __set_bit(PG_private, &(page)->flags)
+-#define __ClearPagePrivate(page) __clear_bit(PG_private, &(page)->flags)
++static inline void set_page_writeback(struct page *page)
++{
++ test_set_page_writeback(page);
++}
+
++#ifdef CONFIG_PAGEFLAGS_EXTENDED
+ /*
+- * Only test-and-set exist for PG_writeback. The unconditional operators are
+- * risky: they bypass page accounting.
++ * System with lots of page flags available. This allows separate
++ * flags for PageHead() and PageTail() checks of compound pages so that bit
++ * tests can be used in performance sensitive paths. PageCompound is
++ * generally not used in hot code paths.
+ */
+-#define PageWriteback(page) test_bit(PG_writeback, &(page)->flags)
+-#define TestSetPageWriteback(page) test_and_set_bit(PG_writeback, \
+- &(page)->flags)
+-#define TestClearPageWriteback(page) test_and_clear_bit(PG_writeback, \
+- &(page)->flags)
++__PAGEFLAG(Head, head)
++__PAGEFLAG(Tail, tail)
+
+-#define PageBuddy(page) test_bit(PG_buddy, &(page)->flags)
+-#define __SetPageBuddy(page) __set_bit(PG_buddy, &(page)->flags)
+-#define __ClearPageBuddy(page) __clear_bit(PG_buddy, &(page)->flags)
+-
+-#define PageMappedToDisk(page) test_bit(PG_mappedtodisk, &(page)->flags)
+-#define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags)
+-#define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags)
+-
+-#define PageReadahead(page) test_bit(PG_readahead, &(page)->flags)
+-#define SetPageReadahead(page) set_bit(PG_readahead, &(page)->flags)
+-#define ClearPageReadahead(page) clear_bit(PG_readahead, &(page)->flags)
+-
+-#define PageReclaim(page) test_bit(PG_reclaim, &(page)->flags)
+-#define SetPageReclaim(page) set_bit(PG_reclaim, &(page)->flags)
+-#define ClearPageReclaim(page) clear_bit(PG_reclaim, &(page)->flags)
+-#define TestClearPageReclaim(page) test_and_clear_bit(PG_reclaim, &(page)->flags)
++static inline int PageCompound(struct page *page)
++{
++ return page->flags & ((1L << PG_head) | (1L << PG_tail));
+
+-#define PageCompound(page) test_bit(PG_compound, &(page)->flags)
+-#define __SetPageCompound(page) __set_bit(PG_compound, &(page)->flags)
+-#define __ClearPageCompound(page) __clear_bit(PG_compound, &(page)->flags)
++}
++#else
++/*
++ * Reduce page flag use as much as possible by overlapping
++ * compound page flags with the flags used for page cache pages. Possible
++ * because PageCompound is always set for compound pages and not for
++ * pages on the LRU and/or pagecache.
++ */
++TESTPAGEFLAG(Compound, compound)
++__PAGEFLAG(Head, compound)
+
+ /*
+ * PG_reclaim is used in combination with PG_compound to mark the
+- * head and tail of a compound page
++ * head and tail of a compound page. This saves one page flag
++ * but makes it impossible to use compound pages for the page cache.
++ * The PG_reclaim bit would have to be used for reclaim or readahead
++ * if compound pages enter the page cache.
+ *
+ * PG_compound & PG_reclaim => Tail page
+ * PG_compound & ~PG_reclaim => Head page
+ */
+-
+ #define PG_head_tail_mask ((1L << PG_compound) | (1L << PG_reclaim))
+
+-#define PageTail(page) (((page)->flags & PG_head_tail_mask) \
+- == PG_head_tail_mask)
++static inline int PageTail(struct page *page)
++{
++ return ((page->flags & PG_head_tail_mask) == PG_head_tail_mask);
++}
+
+ static inline void __SetPageTail(struct page *page)
+ {
+@@ -279,33 +305,6 @@ static inline void __ClearPageTail(struct page *page)
+ page->flags &= ~PG_head_tail_mask;
+ }
+
+-#define PageHead(page) (((page)->flags & PG_head_tail_mask) \
+- == (1L << PG_compound))
+-#define __SetPageHead(page) __SetPageCompound(page)
+-#define __ClearPageHead(page) __ClearPageCompound(page)
+-
+-#ifdef CONFIG_SWAP
+-#define PageSwapCache(page) test_bit(PG_swapcache, &(page)->flags)
+-#define SetPageSwapCache(page) set_bit(PG_swapcache, &(page)->flags)
+-#define ClearPageSwapCache(page) clear_bit(PG_swapcache, &(page)->flags)
+-#else
+-#define PageSwapCache(page) 0
+-#endif
+-
+-#define PageUncached(page) test_bit(PG_uncached, &(page)->flags)
+-#define SetPageUncached(page) set_bit(PG_uncached, &(page)->flags)
+-#define ClearPageUncached(page) clear_bit(PG_uncached, &(page)->flags)
+-
+-struct page; /* forward declaration */
+-
+-extern void cancel_dirty_page(struct page *page, unsigned int account_size);
+-
+-int test_clear_page_writeback(struct page *page);
+-int test_set_page_writeback(struct page *page);
+-
+-static inline void set_page_writeback(struct page *page)
+-{
+- test_set_page_writeback(page);
+-}
+-
++#endif /* !PAGEFLAGS_EXTENDED */
++#endif /* !__GENERATING_BOUNDS_H */
+ #endif /* PAGE_FLAGS_H */
diff --git a/include/linux/parport.h b/include/linux/parport.h
index d1ad546..dcb9e01 100644
--- a/include/linux/parport.h
@@ -818590,23 +1094205,16 @@
+#endif
+#endif /* LINUX_ASPM_H */
diff --git a/include/linux/pci.h b/include/linux/pci.h
-index ea760e5..2924913 100644
+index ea760e5..96acd0d 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
-@@ -20,6 +20,8 @@
- /* Include the pci register defines */
- #include <linux/pci_regs.h>
-
-+struct pci_vpd;
-+
- /*
- * The PCI interface treats multi-function devices as independent
- * devices. The slot/function address of each device is encoded
-@@ -128,11 +130,11 @@ struct pci_cap_saved_state {
+@@ -128,11 +128,13 @@ struct pci_cap_saved_state {
u32 data[0];
};
+struct pcie_link_state;
++struct pci_vpd;
++
/*
* The pci_dev structure is used to describe PCI devices.
*/
@@ -818647,6 +1094255,15 @@
#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)
+@@ -247,7 +254,7 @@ static inline void pci_add_saved_cap(struct pci_dev *pci_dev,
+ #define PCI_NUM_RESOURCES 11
+
+ #ifndef PCI_BUS_NUM_RESOURCES
+-#define PCI_BUS_NUM_RESOURCES 8
++#define PCI_BUS_NUM_RESOURCES 16
+ #endif
+
+ #define PCI_REGION_FLAG_MASK 0x0fU /* These bits of resource flags tell us the PCI region flags */
@@ -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. */
@@ -818690,7 +1094307,45 @@
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,
+@@ -664,6 +666,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
+
+ void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
+ void *userdata);
++int pci_cfg_space_size_ext(struct pci_dev *dev, unsigned check_exp_pcix);
+ int pci_cfg_space_size(struct pci_dev *dev);
+ unsigned char pci_bus_max_busnr(struct pci_bus *bus);
+
+@@ -699,6 +702,8 @@ static inline int pci_enable_msi(struct pci_dev *dev)
+ return -1;
+ }
+
++static inline void pci_msi_shutdown(struct pci_dev *dev)
++{ }
+ static inline void pci_disable_msi(struct pci_dev *dev)
+ { }
+
+@@ -708,6 +713,8 @@ static inline int pci_enable_msix(struct pci_dev *dev,
+ return -1;
+ }
+
++static inline void pci_msix_shutdown(struct pci_dev *dev)
++{ }
+ static inline void pci_disable_msix(struct pci_dev *dev)
+ { }
+
+@@ -718,9 +725,11 @@ static inline void pci_restore_msi_state(struct pci_dev *dev)
+ { }
+ #else
+ extern int pci_enable_msi(struct pci_dev *dev);
++extern void pci_msi_shutdown(struct pci_dev *dev);
+ extern void pci_disable_msi(struct pci_dev *dev);
+ extern int pci_enable_msix(struct pci_dev *dev,
+ struct msix_entry *entries, int nvec);
++extern void pci_msix_shutdown(struct pci_dev *dev);
+ extern void pci_disable_msix(struct pci_dev *dev);
+ extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
+ extern void pci_restore_msi_state(struct pci_dev *dev);
+@@ -793,18 +802,11 @@ static inline struct pci_dev *pci_get_device(unsigned int vendor,
return NULL;
}
@@ -818710,7 +1094365,7 @@
{
return NULL;
}
-@@ -817,7 +812,6 @@ static inline struct pci_dev *pci_get_class(unsigned int class,
+@@ -817,7 +819,6 @@ static inline struct pci_dev *pci_get_class(unsigned int class,
#define pci_dev_present(ids) (0)
#define no_pci_devices() (1)
@@ -818718,6 +1094373,33 @@
#define pci_dev_put(dev) do { } while (0)
static inline void pci_set_master(struct pci_dev *dev)
+@@ -1059,5 +1060,13 @@ extern unsigned long pci_cardbus_mem_size;
+
+ extern int pcibios_add_platform_entries(struct pci_dev *dev);
+
++#ifdef CONFIG_PCI_MMCONFIG
++extern void __init pci_mmcfg_early_init(void);
++extern void __init pci_mmcfg_late_init(void);
++#else
++static inline void pci_mmcfg_early_init(void) { }
++static inline void pci_mmcfg_late_init(void) { }
++#endif
++
+ #endif /* __KERNEL__ */
+ #endif /* LINUX_PCI_H */
+diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
+index 70eb3c8..e5a53da 100644
+--- a/include/linux/pci_ids.h
++++ b/include/linux/pci_ids.h
+@@ -2413,6 +2413,8 @@
+ #define PCI_DEVICE_ID_INTEL_82443GX_0 0x71a0
+ #define PCI_DEVICE_ID_INTEL_82443GX_2 0x71a2
+ #define PCI_DEVICE_ID_INTEL_82372FB_1 0x7601
++#define PCI_DEVICE_ID_INTEL_SCH_LPC 0x8119
++#define PCI_DEVICE_ID_INTEL_SCH_IDE 0x811a
+ #define PCI_DEVICE_ID_INTEL_82454GX 0x84c4
+ #define PCI_DEVICE_ID_INTEL_82450GX 0x84c5
+ #define PCI_DEVICE_ID_INTEL_82451NX 0x84ca
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
index c1914a8..c0c1223 100644
--- a/include/linux/pci_regs.h
@@ -818820,6 +1094502,59 @@
-#endif /* CONFIG_SMP */
-
-#endif /* __LINUX_PCOUNTER_H */
+diff --git a/include/linux/percpu.h b/include/linux/percpu.h
+index 1ac9697..d746a2a 100644
+--- a/include/linux/percpu.h
++++ b/include/linux/percpu.h
+@@ -4,7 +4,6 @@
+ #include <linux/preempt.h>
+ #include <linux/slab.h> /* For kmalloc() */
+ #include <linux/smp.h>
+-#include <linux/string.h> /* For memset() */
+ #include <linux/cpumask.h>
+
+ #include <asm/percpu.h>
+diff --git a/include/linux/personality.h b/include/linux/personality.h
+index 012cd55..a84e9ff 100644
+--- a/include/linux/personality.h
++++ b/include/linux/personality.h
+@@ -105,10 +105,6 @@ struct exec_domain {
+ */
+ #define personality(pers) (pers & PER_MASK)
+
+-/*
+- * Personality of the currently running process.
+- */
+-#define get_personality (current->personality)
+
+ /*
+ * Change personality of the currently running process.
+diff --git a/include/linux/phantom.h b/include/linux/phantom.h
+index 96f4048..02268c5 100644
+--- a/include/linux/phantom.h
++++ b/include/linux/phantom.h
+@@ -27,14 +27,17 @@ struct phm_regs {
+
+ #define PH_IOC_MAGIC 'p'
+ #define PHN_GET_REG _IOWR(PH_IOC_MAGIC, 0, struct phm_reg *)
+-#define PHN_SET_REG _IOW (PH_IOC_MAGIC, 1, struct phm_reg *)
++#define PHN_SET_REG _IOW(PH_IOC_MAGIC, 1, struct phm_reg *)
+ #define PHN_GET_REGS _IOWR(PH_IOC_MAGIC, 2, struct phm_regs *)
+-#define PHN_SET_REGS _IOW (PH_IOC_MAGIC, 3, struct phm_regs *)
++#define PHN_SET_REGS _IOW(PH_IOC_MAGIC, 3, struct phm_regs *)
+ /* this ioctl tells the driver, that the caller is not OpenHaptics and might
+ * use improved registers update (no more phantom switchoffs when using
+ * libphantom) */
+-#define PHN_NOT_OH _IO (PH_IOC_MAGIC, 4)
+-#define PH_IOC_MAXNR 4
++#define PHN_NOT_OH _IO(PH_IOC_MAGIC, 4)
++#define PHN_GETREG _IOWR(PH_IOC_MAGIC, 5, struct phm_reg)
++#define PHN_SETREG _IOW(PH_IOC_MAGIC, 6, struct phm_reg)
++#define PHN_GETREGS _IOWR(PH_IOC_MAGIC, 7, struct phm_regs)
++#define PHN_SETREGS _IOW(PH_IOC_MAGIC, 8, struct phm_regs)
+
+ #define PHN_CONTROL 0x6 /* control byte in iaddr space */
+ #define PHN_CTL_AMP 0x1 /* switch after torques change */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 5e43ae7..02df20f 100644
--- a/include/linux/phy.h
@@ -818995,6 +1094730,46 @@
+
extern struct bus_type mdio_bus_type;
#endif /* __PHY_H */
+diff --git a/include/linux/pid.h b/include/linux/pid.h
+index c798081..c21c7e8 100644
+--- a/include/linux/pid.h
++++ b/include/linux/pid.h
+@@ -60,7 +60,7 @@ struct pid
+ /* lists of tasks that use this pid */
+ struct hlist_head tasks[PIDTYPE_MAX];
+ struct rcu_head rcu;
+- int level;
++ unsigned int level;
+ struct upid numbers[1];
+ };
+
+@@ -89,9 +89,11 @@ extern struct pid *get_task_pid(struct task_struct *task, enum pid_type type);
+ * attach_pid() and detach_pid() must be called with the tasklist_lock
+ * write-held.
+ */
+-extern int attach_pid(struct task_struct *task, enum pid_type type,
+- struct pid *pid);
++extern void attach_pid(struct task_struct *task, enum pid_type type,
++ struct pid *pid);
+ extern void detach_pid(struct task_struct *task, enum pid_type);
++extern void change_pid(struct task_struct *task, enum pid_type,
++ struct pid *pid);
+ extern void transfer_pid(struct task_struct *old, struct task_struct *new,
+ enum pid_type);
+
+diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
+index fcd61fa..caff528 100644
+--- a/include/linux/pid_namespace.h
++++ b/include/linux/pid_namespace.h
+@@ -20,7 +20,7 @@ struct pid_namespace {
+ int last_pid;
+ struct task_struct *child_reaper;
+ struct kmem_cache *pid_cachep;
+- int level;
++ unsigned int level;
+ struct pid_namespace *parent;
+ #ifdef CONFIG_PROC_FS
+ struct vfsmount *proc_mnt;
diff --git a/include/linux/pim.h b/include/linux/pim.h
new file mode 100644
index 0000000..236ffd3
@@ -819047,10 +1094822,19 @@
+#endif
+#endif
diff --git a/include/linux/pm.h b/include/linux/pm.h
-index 015b735..1de72cb 100644
+index 015b735..39a7ee8 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
-@@ -183,8 +183,9 @@ typedef struct pm_message {
+@@ -21,8 +21,6 @@
+ #ifndef _LINUX_PM_H
+ #define _LINUX_PM_H
+
+-#ifdef __KERNEL__
+-
+ #include <linux/list.h>
+ #include <asm/atomic.h>
+ #include <asm/errno.h>
+@@ -183,8 +181,9 @@ typedef struct pm_message {
struct dev_pm_info {
pm_message_t power_state;
unsigned can_wakeup:1;
@@ -819061,7 +1094845,7 @@
struct list_head entry;
#endif
};
-@@ -197,11 +198,6 @@ extern void device_resume(void);
+@@ -197,11 +196,6 @@ extern void device_resume(void);
extern int device_suspend(pm_message_t state);
extern int device_prepare_suspend(pm_message_t state);
@@ -819073,7 +1094857,7 @@
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);
+@@ -209,20 +203,6 @@ extern void __suspend_report_result(const char *function, void *fn, int ret);
__suspend_report_result(__FUNCTION__, fn, ret); \
} while (0)
@@ -819094,7 +1094878,7 @@
#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)
+@@ -230,29 +210,10 @@ static inline int device_suspend(pm_message_t state)
return 0;
}
@@ -819125,6 +1094909,13 @@
/*
* Global Power Management flags
* Used to keep APM and ACPI from both being active
+@@ -262,6 +223,4 @@ extern unsigned int pm_flags;
+ #define PM_APM 1
+ #define PM_ACPI 2
+
+-#endif /* __KERNEL__ */
+-
+ #endif /* _LINUX_PM_H */
diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h
new file mode 100644
index 0000000..f0d0b2c
@@ -819221,11 +1095012,522 @@
+#endif /* !CONFIG_PM */
+
+#endif /* _LINUX_PM_WAKEUP_H */
+diff --git a/include/linux/pnp.h b/include/linux/pnp.h
+index b2f05c2..63b128d 100644
+--- a/include/linux/pnp.h
++++ b/include/linux/pnp.h
+@@ -6,66 +6,127 @@
+ #ifndef _LINUX_PNP_H
+ #define _LINUX_PNP_H
+
+-#ifdef __KERNEL__
+-
+ #include <linux/device.h>
+ #include <linux/list.h>
+ #include <linux/errno.h>
+ #include <linux/mod_devicetable.h>
+
+-#define PNP_MAX_PORT 40
+-#define PNP_MAX_MEM 24
+-#define PNP_MAX_IRQ 2
+-#define PNP_MAX_DMA 2
+ #define PNP_NAME_LEN 50
+
+ struct pnp_protocol;
+ struct pnp_dev;
++struct pnp_resource_table;
+
+ /*
+ * Resource Management
+ */
++struct resource *pnp_get_resource(struct pnp_dev *, unsigned int, unsigned int);
++
++static inline int pnp_resource_valid(struct resource *res)
++{
++ if (res && !(res->flags & IORESOURCE_UNSET))
++ return 1;
++ return 0;
++}
++
++static inline resource_size_t pnp_resource_len(struct resource *res)
++{
++ if (res->start == 0 && res->end == 0)
++ return 0;
++ return res->end - res->start + 1;
++}
++
++
++static inline resource_size_t pnp_port_start(struct pnp_dev *dev,
++ unsigned int bar)
++{
++ return pnp_get_resource(dev, IORESOURCE_IO, bar)->start;
++}
++
++static inline resource_size_t pnp_port_end(struct pnp_dev *dev,
++ unsigned int bar)
++{
++ return pnp_get_resource(dev, IORESOURCE_IO, bar)->end;
++}
++
++static inline unsigned long pnp_port_flags(struct pnp_dev *dev,
++ unsigned int bar)
++{
++ return pnp_get_resource(dev, IORESOURCE_IO, bar)->flags;
++}
++
++static inline int pnp_port_valid(struct pnp_dev *dev, unsigned int bar)
++{
++ return pnp_resource_valid(pnp_get_resource(dev, IORESOURCE_IO, bar));
++}
++
++static inline resource_size_t pnp_port_len(struct pnp_dev *dev,
++ unsigned int bar)
++{
++ return pnp_resource_len(pnp_get_resource(dev, IORESOURCE_IO, bar));
++}
++
++
++static inline resource_size_t pnp_mem_start(struct pnp_dev *dev,
++ unsigned int bar)
++{
++ return pnp_get_resource(dev, IORESOURCE_MEM, bar)->start;
++}
++
++static inline resource_size_t pnp_mem_end(struct pnp_dev *dev,
++ unsigned int bar)
++{
++ return pnp_get_resource(dev, IORESOURCE_MEM, bar)->end;
++}
++
++static inline unsigned long pnp_mem_flags(struct pnp_dev *dev, unsigned int bar)
++{
++ return pnp_get_resource(dev, IORESOURCE_MEM, bar)->flags;
++}
++
++static inline int pnp_mem_valid(struct pnp_dev *dev, unsigned int bar)
++{
++ return pnp_resource_valid(pnp_get_resource(dev, IORESOURCE_MEM, bar));
++}
++
++static inline resource_size_t pnp_mem_len(struct pnp_dev *dev,
++ unsigned int bar)
++{
++ return pnp_resource_len(pnp_get_resource(dev, IORESOURCE_MEM, bar));
++}
++
++
++static inline resource_size_t pnp_irq(struct pnp_dev *dev, unsigned int bar)
++{
++ return pnp_get_resource(dev, IORESOURCE_IRQ, bar)->start;
++}
++
++static inline unsigned long pnp_irq_flags(struct pnp_dev *dev, unsigned int bar)
++{
++ return pnp_get_resource(dev, IORESOURCE_IRQ, bar)->flags;
++}
++
++static inline int pnp_irq_valid(struct pnp_dev *dev, unsigned int bar)
++{
++ return pnp_resource_valid(pnp_get_resource(dev, IORESOURCE_IRQ, bar));
++}
++
++
++static inline resource_size_t pnp_dma(struct pnp_dev *dev, unsigned int bar)
++{
++ return pnp_get_resource(dev, IORESOURCE_DMA, bar)->start;
++}
++
++static inline unsigned long pnp_dma_flags(struct pnp_dev *dev, unsigned int bar)
++{
++ return pnp_get_resource(dev, IORESOURCE_DMA, bar)->flags;
++}
++
++static inline int pnp_dma_valid(struct pnp_dev *dev, unsigned int bar)
++{
++ return pnp_resource_valid(pnp_get_resource(dev, IORESOURCE_DMA, bar));
++}
+
+-/* Use these instead of directly reading pnp_dev to get resource information */
+-#define pnp_port_start(dev,bar) ((dev)->res.port_resource[(bar)].start)
+-#define pnp_port_end(dev,bar) ((dev)->res.port_resource[(bar)].end)
+-#define pnp_port_flags(dev,bar) ((dev)->res.port_resource[(bar)].flags)
+-#define pnp_port_valid(dev,bar) \
+- ((pnp_port_flags((dev),(bar)) & (IORESOURCE_IO | IORESOURCE_UNSET)) \
+- == IORESOURCE_IO)
+-#define pnp_port_len(dev,bar) \
+- ((pnp_port_start((dev),(bar)) == 0 && \
+- pnp_port_end((dev),(bar)) == \
+- pnp_port_start((dev),(bar))) ? 0 : \
+- \
+- (pnp_port_end((dev),(bar)) - \
+- pnp_port_start((dev),(bar)) + 1))
+-
+-#define pnp_mem_start(dev,bar) ((dev)->res.mem_resource[(bar)].start)
+-#define pnp_mem_end(dev,bar) ((dev)->res.mem_resource[(bar)].end)
+-#define pnp_mem_flags(dev,bar) ((dev)->res.mem_resource[(bar)].flags)
+-#define pnp_mem_valid(dev,bar) \
+- ((pnp_mem_flags((dev),(bar)) & (IORESOURCE_MEM | IORESOURCE_UNSET)) \
+- == IORESOURCE_MEM)
+-#define pnp_mem_len(dev,bar) \
+- ((pnp_mem_start((dev),(bar)) == 0 && \
+- pnp_mem_end((dev),(bar)) == \
+- pnp_mem_start((dev),(bar))) ? 0 : \
+- \
+- (pnp_mem_end((dev),(bar)) - \
+- pnp_mem_start((dev),(bar)) + 1))
+-
+-#define pnp_irq(dev,bar) ((dev)->res.irq_resource[(bar)].start)
+-#define pnp_irq_flags(dev,bar) ((dev)->res.irq_resource[(bar)].flags)
+-#define pnp_irq_valid(dev,bar) \
+- ((pnp_irq_flags((dev),(bar)) & (IORESOURCE_IRQ | IORESOURCE_UNSET)) \
+- == IORESOURCE_IRQ)
+-
+-#define pnp_dma(dev,bar) ((dev)->res.dma_resource[(bar)].start)
+-#define pnp_dma_flags(dev,bar) ((dev)->res.dma_resource[(bar)].flags)
+-#define pnp_dma_valid(dev,bar) \
+- ((pnp_dma_flags((dev),(bar)) & (IORESOURCE_DMA | IORESOURCE_UNSET)) \
+- == IORESOURCE_DMA)
+
+ #define PNP_PORT_FLAG_16BITADDR (1<<0)
+ #define PNP_PORT_FLAG_FIXED (1<<1)
+@@ -118,13 +179,6 @@ struct pnp_option {
+ struct pnp_option *next; /* used to chain dependent resources */
+ };
+
+-struct pnp_resource_table {
+- struct resource port_resource[PNP_MAX_PORT];
+- struct resource mem_resource[PNP_MAX_MEM];
+- struct resource dma_resource[PNP_MAX_DMA];
+- struct resource irq_resource[PNP_MAX_IRQ];
+-};
+-
+ /*
+ * Device Management
+ */
+@@ -194,10 +248,9 @@ struct pnp_dev {
+ int capabilities;
+ struct pnp_option *independent;
+ struct pnp_option *dependent;
+- struct pnp_resource_table res;
++ struct pnp_resource_table *res;
+
+ char name[PNP_NAME_LEN]; /* contains a human-readable name */
+- unsigned short regs; /* ISAPnP: supported registers */
+ int flags; /* used by protocols */
+ struct proc_dir_entry *procent; /* device entry in /proc/bus/isapnp */
+ void *data;
+@@ -328,8 +381,8 @@ struct pnp_protocol {
+ char *name;
+
+ /* resource control functions */
+- int (*get) (struct pnp_dev *dev, struct pnp_resource_table *res);
+- int (*set) (struct pnp_dev *dev, struct pnp_resource_table *res);
++ int (*get) (struct pnp_dev *dev);
++ int (*set) (struct pnp_dev *dev);
+ int (*disable) (struct pnp_dev *dev);
+
+ /* protocol specific suspend/resume */
+@@ -358,20 +411,12 @@ extern struct bus_type pnp_bus_type;
+ #if defined(CONFIG_PNP)
+
+ /* device management */
+-int pnp_register_protocol(struct pnp_protocol *protocol);
+-void pnp_unregister_protocol(struct pnp_protocol *protocol);
+-int pnp_add_device(struct pnp_dev *dev);
+ int pnp_device_attach(struct pnp_dev *pnp_dev);
+ void pnp_device_detach(struct pnp_dev *pnp_dev);
+ extern struct list_head pnp_global;
+ extern int pnp_platform_devices;
+
+ /* multidevice card support */
+-int pnp_add_card(struct pnp_card *card);
+-void pnp_remove_card(struct pnp_card *card);
+-int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev);
+-void pnp_remove_card_device(struct pnp_dev *dev);
+-int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card);
+ struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink,
+ const char *id, struct pnp_dev *from);
+ void pnp_release_card_device(struct pnp_dev *dev);
+@@ -380,77 +425,42 @@ void pnp_unregister_card_driver(struct pnp_card_driver *drv);
+ extern struct list_head pnp_cards;
+
+ /* resource management */
+-struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev);
+-struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
+- int priority);
+-int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data);
+-int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data);
+-int pnp_register_port_resource(struct pnp_option *option,
+- struct pnp_port *data);
+-int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data);
+-void pnp_init_resource_table(struct pnp_resource_table *table);
+-int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res,
+- int mode);
+ int pnp_auto_config_dev(struct pnp_dev *dev);
+-int pnp_validate_config(struct pnp_dev *dev);
+ int pnp_start_dev(struct pnp_dev *dev);
+ int pnp_stop_dev(struct pnp_dev *dev);
+ int pnp_activate_dev(struct pnp_dev *dev);
+ int pnp_disable_dev(struct pnp_dev *dev);
+-void pnp_resource_change(struct resource *resource, resource_size_t start,
+- resource_size_t size);
+
+ /* protocol helpers */
+ int pnp_is_active(struct pnp_dev *dev);
+ int compare_pnp_id(struct pnp_id *pos, const char *id);
+-int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev);
+ int pnp_register_driver(struct pnp_driver *drv);
+ void pnp_unregister_driver(struct pnp_driver *drv);
+
+ #else
+
+ /* device management */
+-static inline int pnp_register_protocol(struct pnp_protocol *protocol) { return -ENODEV; }
+-static inline void pnp_unregister_protocol(struct pnp_protocol *protocol) { }
+-static inline int pnp_init_device(struct pnp_dev *dev) { return -ENODEV; }
+-static inline int pnp_add_device(struct pnp_dev *dev) { return -ENODEV; }
+ static inline int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; }
+ static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { }
+
+ #define pnp_platform_devices 0
+
+ /* multidevice card support */
+-static inline int pnp_add_card(struct pnp_card *card) { return -ENODEV; }
+-static inline void pnp_remove_card(struct pnp_card *card) { }
+-static inline int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev) { return -ENODEV; }
+-static inline void pnp_remove_card_device(struct pnp_dev *dev) { }
+-static inline int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card) { return -ENODEV; }
+ static inline struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink, const char *id, struct pnp_dev *from) { return NULL; }
+ static inline void pnp_release_card_device(struct pnp_dev *dev) { }
+ static inline int pnp_register_card_driver(struct pnp_card_driver *drv) { return -ENODEV; }
+ static inline void pnp_unregister_card_driver(struct pnp_card_driver *drv) { }
+
+ /* resource management */
+-static inline struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev) { return NULL; }
+-static inline struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev, int priority) { return NULL; }
+-static inline int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data) { return -ENODEV; }
+-static inline int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data) { return -ENODEV; }
+-static inline int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data) { return -ENODEV; }
+-static inline int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data) { return -ENODEV; }
+-static inline void pnp_init_resource_table(struct pnp_resource_table *table) { }
+-static inline int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode) { return -ENODEV; }
+ static inline int pnp_auto_config_dev(struct pnp_dev *dev) { return -ENODEV; }
+-static inline int pnp_validate_config(struct pnp_dev *dev) { return -ENODEV; }
+ static inline int pnp_start_dev(struct pnp_dev *dev) { return -ENODEV; }
+ static inline int pnp_stop_dev(struct pnp_dev *dev) { return -ENODEV; }
+ static inline int pnp_activate_dev(struct pnp_dev *dev) { return -ENODEV; }
+ static inline int pnp_disable_dev(struct pnp_dev *dev) { return -ENODEV; }
+-static inline void pnp_resource_change(struct resource *resource, resource_size_t start, resource_size_t size) { }
+
+ /* protocol helpers */
+ static inline int pnp_is_active(struct pnp_dev *dev) { return 0; }
+ static inline int compare_pnp_id(struct pnp_id *pos, const char *id) { return -ENODEV; }
+-static inline int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) { return -ENODEV; }
+ static inline int pnp_register_driver(struct pnp_driver *drv) { return -ENODEV; }
+ static inline void pnp_unregister_driver(struct pnp_driver *drv) { }
+
+@@ -466,6 +476,4 @@ static inline void pnp_unregister_driver(struct pnp_driver *drv) { }
+ #define pnp_dbg(format, arg...) do {} while (0)
+ #endif
+
+-#endif /* __KERNEL__ */
+-
+ #endif /* _LINUX_PNP_H */
+diff --git a/include/linux/pnpbios.h b/include/linux/pnpbios.h
+deleted file mode 100644
+index 329192a..0000000
+--- a/include/linux/pnpbios.h
++++ /dev/null
+@@ -1,151 +0,0 @@
+-/*
+- * Include file for the interface to a PnP BIOS
+- *
+- * Original BIOS code (C) 1998 Christian Schmidt (chr.schmidt at tu-bs.de)
+- * PnP handler parts (c) 1998 Tom Lees <tom at lpsg.demon.co.uk>
+- * Minor reorganizations by David Hinds <dahinds at users.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, or (at your option) any
+- * later version.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * General Public License for more details.
+- *
+- * You 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_PNPBIOS_H
+-#define _LINUX_PNPBIOS_H
+-
+-#ifdef __KERNEL__
+-
+-#include <linux/types.h>
+-#include <linux/pnp.h>
+-
+-/*
+- * Return codes
+- */
+-#define PNP_SUCCESS 0x00
+-#define PNP_NOT_SET_STATICALLY 0x7f
+-#define PNP_UNKNOWN_FUNCTION 0x81
+-#define PNP_FUNCTION_NOT_SUPPORTED 0x82
+-#define PNP_INVALID_HANDLE 0x83
+-#define PNP_BAD_PARAMETER 0x84
+-#define PNP_SET_FAILED 0x85
+-#define PNP_EVENTS_NOT_PENDING 0x86
+-#define PNP_SYSTEM_NOT_DOCKED 0x87
+-#define PNP_NO_ISA_PNP_CARDS 0x88
+-#define PNP_UNABLE_TO_DETERMINE_DOCK_CAPABILITIES 0x89
+-#define PNP_CONFIG_CHANGE_FAILED_NO_BATTERY 0x8a
+-#define PNP_CONFIG_CHANGE_FAILED_RESOURCE_CONFLICT 0x8b
+-#define PNP_BUFFER_TOO_SMALL 0x8c
+-#define PNP_USE_ESCD_SUPPORT 0x8d
+-#define PNP_MESSAGE_NOT_SUPPORTED 0x8e
+-#define PNP_HARDWARE_ERROR 0x8f
+-
+-#define ESCD_SUCCESS 0x00
+-#define ESCD_IO_ERROR_READING 0x55
+-#define ESCD_INVALID 0x56
+-#define ESCD_BUFFER_TOO_SMALL 0x59
+-#define ESCD_NVRAM_TOO_SMALL 0x5a
+-#define ESCD_FUNCTION_NOT_SUPPORTED 0x81
+-
+-/*
+- * Events that can be received by "get event"
+- */
+-#define PNPEV_ABOUT_TO_CHANGE_CONFIG 0x0001
+-#define PNPEV_DOCK_CHANGED 0x0002
+-#define PNPEV_SYSTEM_DEVICE_CHANGED 0x0003
+-#define PNPEV_CONFIG_CHANGED_FAILED 0x0004
+-#define PNPEV_UNKNOWN_SYSTEM_EVENT 0xffff
+-/* 0x8000 through 0xfffe are OEM defined */
+-
+-/*
+- * Messages that should be sent through "send message"
+- */
+-#define PNPMSG_OK 0x00
+-#define PNPMSG_ABORT 0x01
+-#define PNPMSG_UNDOCK_DEFAULT_ACTION 0x40
+-#define PNPMSG_POWER_OFF 0x41
+-#define PNPMSG_PNP_OS_ACTIVE 0x42
+-#define PNPMSG_PNP_OS_INACTIVE 0x43
+-
+-/*
+- * Plug and Play BIOS flags
+- */
+-#define PNPBIOS_NO_DISABLE 0x0001
+-#define PNPBIOS_NO_CONFIG 0x0002
+-#define PNPBIOS_OUTPUT 0x0004
+-#define PNPBIOS_INPUT 0x0008
+-#define PNPBIOS_BOOTABLE 0x0010
+-#define PNPBIOS_DOCK 0x0020
+-#define PNPBIOS_REMOVABLE 0x0040
+-#define pnpbios_is_static(x) (((x)->flags & 0x0100) == 0x0000)
+-#define pnpbios_is_dynamic(x) ((x)->flags & 0x0080)
+-
+-/*
+- * Function Parameters
+- */
+-#define PNPMODE_STATIC 1
+-#define PNPMODE_DYNAMIC 0
+-
+-/* 0x8000 through 0xffff are OEM defined */
+-
+-#pragma pack(1)
+-struct pnp_dev_node_info {
+- __u16 no_nodes;
+- __u16 max_node_size;
+-};
+-struct pnp_docking_station_info {
+- __u32 location_id;
+- __u32 serial;
+- __u16 capabilities;
+-};
+-struct pnp_isa_config_struc {
+- __u8 revision;
+- __u8 no_csns;
+- __u16 isa_rd_data_port;
+- __u16 reserved;
+-};
+-struct escd_info_struc {
+- __u16 min_escd_write_size;
+- __u16 escd_size;
+- __u32 nv_storage_base;
+-};
+-struct pnp_bios_node {
+- __u16 size;
+- __u8 handle;
+- __u32 eisa_id;
+- __u8 type_code[3];
+- __u16 flags;
+- __u8 data[0];
+-};
+-#pragma pack()
+-
+-#ifdef CONFIG_PNPBIOS
+-
+-/* non-exported */
+-extern struct pnp_dev_node_info node_info;
+-
+-extern int pnp_bios_dev_node_info(struct pnp_dev_node_info *data);
+-extern int pnp_bios_get_dev_node(u8 *nodenum, char config,
+- struct pnp_bios_node *data);
+-extern int pnp_bios_set_dev_node(u8 nodenum, char config,
+- struct pnp_bios_node *data);
+-extern int pnp_bios_get_stat_res(char *info);
+-extern int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data);
+-extern int pnp_bios_escd_info(struct escd_info_struc *data);
+-extern int pnp_bios_read_escd(char *data, u32 nvram_base);
+-extern int pnp_bios_dock_station_info(struct pnp_docking_station_info *data);
+-
+-#endif /* CONFIG_PNPBIOS */
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* _LINUX_PNPBIOS_H */
+diff --git a/include/linux/poison.h b/include/linux/poison.h
+index a9c31be..9f31683 100644
+--- a/include/linux/poison.h
++++ b/include/linux/poison.h
+@@ -10,6 +10,13 @@
+ #define LIST_POISON1 ((void *) 0x00100100)
+ #define LIST_POISON2 ((void *) 0x00200200)
+
++/********** include/linux/timer.h **********/
++/*
++ * Magic number "tsta" to indicate a static timer initializer
++ * for the object debugging code.
++ */
++#define TIMER_ENTRY_STATIC ((void *) 0x74737461)
++
+ /********** mm/slab.c **********/
+ /*
+ * Magic nums for obj red zoning.
diff --git a/include/linux/prctl.h b/include/linux/prctl.h
-index 3800639..5c80b19 100644
+index 3800639..5ad7919 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
-@@ -67,4 +67,10 @@
+@@ -16,7 +16,8 @@
+ # define PR_UNALIGN_NOPRINT 1 /* silently fix up unaligned user accesses */
+ # define PR_UNALIGN_SIGBUS 2 /* generate SIGBUS on unaligned user access */
+
+-/* Get/set whether or not to drop capabilities on setuid() away from uid 0 */
++/* Get/set whether or not to drop capabilities on setuid() away from
++ * uid 0 (as per security/commoncap.c) */
+ #define PR_GET_KEEPCAPS 7
+ #define PR_SET_KEEPCAPS 8
+
+@@ -63,8 +64,18 @@
+ #define PR_GET_SECCOMP 21
+ #define PR_SET_SECCOMP 22
+
+-/* Get/set the capability bounding set */
++/* Get/set the capability bounding set (as per security/commoncap.c) */
#define PR_CAPBSET_READ 23
#define PR_CAPBSET_DROP 24
@@ -819235,9 +1095537,227 @@
+# 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 */
+
++/* Get/set securebits (as per security/commoncap.c) */
++#define PR_GET_SECUREBITS 27
++#define PR_SET_SECUREBITS 28
++
#endif /* _LINUX_PRCTL_H */
+diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
+index 9b6c935..9883bc9 100644
+--- a/include/linux/proc_fs.h
++++ b/include/linux/proc_fs.h
+@@ -9,7 +9,6 @@
+
+ struct net;
+ struct completion;
+-
+ /*
+ * The proc filesystem constants/structures
+ */
+@@ -41,7 +40,7 @@ enum {
+ * /proc file has a parent, but "subdir" is NULL for all
+ * non-directory entries).
+ *
+- * "get_info" is called at "read", while "owner" is used to protect module
++ * "owner" is used to protect module
+ * from unloading while proc_dir_entry is in use
+ */
+
+@@ -49,7 +48,6 @@ typedef int (read_proc_t)(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+ typedef int (write_proc_t)(struct file *file, const char __user *buffer,
+ unsigned long count, void *data);
+-typedef int (get_info_t)(char *, char **, off_t, int);
+
+ struct proc_dir_entry {
+ unsigned int low_ino;
+@@ -70,7 +68,6 @@ struct proc_dir_entry {
+ * somewhere.
+ */
+ const struct file_operations *proc_fops;
+- get_info_t *get_info;
+ struct module *owner;
+ struct proc_dir_entry *next, *parent, *subdir;
+ void *data;
+@@ -97,10 +94,6 @@ struct vmcore {
+
+ #ifdef CONFIG_PROC_FS
+
+-extern struct proc_dir_entry proc_root;
+-extern struct proc_dir_entry *proc_root_fs;
+-extern struct proc_dir_entry *proc_bus;
+-extern struct proc_dir_entry *proc_root_driver;
+ extern struct proc_dir_entry *proc_root_kcore;
+
+ extern spinlock_t proc_subdir_lock;
+@@ -123,9 +116,10 @@ void de_put(struct proc_dir_entry *de);
+
+ extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
+ struct proc_dir_entry *parent);
+-struct proc_dir_entry *proc_create(const char *name, mode_t mode,
++struct proc_dir_entry *proc_create_data(const char *name, mode_t mode,
+ struct proc_dir_entry *parent,
+- const struct file_operations *proc_fops);
++ const struct file_operations *proc_fops,
++ void *data);
+ extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
+
+ extern struct vfsmount *proc_mnt;
+@@ -180,6 +174,12 @@ extern struct proc_dir_entry *proc_mkdir(const char *,struct proc_dir_entry *);
+ extern struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode,
+ struct proc_dir_entry *parent);
+
++static inline struct proc_dir_entry *proc_create(const char *name, mode_t mode,
++ struct proc_dir_entry *parent, const struct file_operations *proc_fops)
++{
++ return proc_create_data(name, mode, parent, proc_fops, NULL);
++}
++
+ static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
+ mode_t mode, struct proc_dir_entry *base,
+ read_proc_t *read_proc, void * data)
+@@ -192,24 +192,19 @@ static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
+ return res;
+ }
+
+-static inline struct proc_dir_entry *create_proc_info_entry(const char *name,
+- mode_t mode, struct proc_dir_entry *base, get_info_t *get_info)
+-{
+- struct proc_dir_entry *res=create_proc_entry(name,mode,base);
+- if (res) res->get_info=get_info;
+- return res;
+-}
+-
+ extern struct proc_dir_entry *proc_net_fops_create(struct net *net,
+ const char *name, mode_t mode, const struct file_operations *fops);
+ extern void proc_net_remove(struct net *net, const char *name);
+ extern struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name,
+ struct proc_dir_entry *parent);
+
+-#else
++/* While the {get|set|dup}_mm_exe_file functions are for mm_structs, they are
++ * only needed to implement /proc/<pid>|self/exe so we define them here. */
++extern void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file);
++extern struct file *get_mm_exe_file(struct mm_struct *mm);
++extern void dup_mm_exe_file(struct mm_struct *oldmm, struct mm_struct *newmm);
+
+-#define proc_root_driver NULL
+-#define proc_bus NULL
++#else
+
+ #define proc_net_fops_create(net, name, mode, fops) ({ (void)(mode), NULL; })
+ static inline void proc_net_remove(struct net *net, const char *name) {}
+@@ -226,6 +221,12 @@ static inline struct proc_dir_entry *proc_create(const char *name,
+ {
+ return NULL;
+ }
++static inline struct proc_dir_entry *proc_create_data(const char *name,
++ mode_t mode, struct proc_dir_entry *parent,
++ const struct file_operations *proc_fops, void *data)
++{
++ return NULL;
++}
+ #define remove_proc_entry(name, parent) do {} while (0)
+
+ static inline struct proc_dir_entry *proc_symlink(const char *name,
+@@ -236,16 +237,11 @@ static inline struct proc_dir_entry *proc_mkdir(const char *name,
+ static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
+ mode_t mode, struct proc_dir_entry *base,
+ read_proc_t *read_proc, void * data) { return NULL; }
+-static inline struct proc_dir_entry *create_proc_info_entry(const char *name,
+- mode_t mode, struct proc_dir_entry *base, get_info_t *get_info)
+- { return NULL; }
+
+ struct tty_driver;
+ static inline void proc_tty_register_driver(struct tty_driver *driver) {};
+ static inline void proc_tty_unregister_driver(struct tty_driver *driver) {};
+
+-extern struct proc_dir_entry proc_root;
+-
+ static inline int pid_ns_prepare_proc(struct pid_namespace *ns)
+ {
+ return 0;
+@@ -255,6 +251,19 @@ static inline void pid_ns_release_proc(struct pid_namespace *ns)
+ {
+ }
+
++static inline void set_mm_exe_file(struct mm_struct *mm,
++ struct file *new_exe_file)
++{}
++
++static inline struct file *get_mm_exe_file(struct mm_struct *mm)
++{
++ return NULL;
++}
++
++static inline void dup_mm_exe_file(struct mm_struct *oldmm,
++ struct mm_struct *newmm)
++{}
++
+ #endif /* CONFIG_PROC_FS */
+
+ #if !defined(CONFIG_PROC_KCORE)
+diff --git a/include/linux/profile.h b/include/linux/profile.h
+index ff576d1..05c1cc7 100644
+--- a/include/linux/profile.h
++++ b/include/linux/profile.h
+@@ -1,8 +1,6 @@
+ #ifndef _LINUX_PROFILE_H
+ #define _LINUX_PROFILE_H
+
+-#ifdef __KERNEL__
+-
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/cpumask.h>
+@@ -118,6 +116,4 @@ static inline void unregister_timer_hook(int (*hook)(struct pt_regs *))
+
+ #endif /* CONFIG_PROFILING */
+
+-#endif /* __KERNEL__ */
+-
+ #endif /* _LINUX_PROFILE_H */
+diff --git a/include/linux/proportions.h b/include/linux/proportions.h
+index 2c3b3ca..5afc1b2 100644
+--- a/include/linux/proportions.h
++++ b/include/linux/proportions.h
+@@ -78,6 +78,19 @@ void prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl)
+ }
+
+ /*
++ * Limit the time part in order to ensure there are some bits left for the
++ * cycle counter and fraction multiply.
++ */
++#define PROP_MAX_SHIFT (3*BITS_PER_LONG/4)
++
++#define PROP_FRAC_SHIFT (BITS_PER_LONG - PROP_MAX_SHIFT - 1)
++#define PROP_FRAC_BASE (1UL << PROP_FRAC_SHIFT)
++
++void __prop_inc_percpu_max(struct prop_descriptor *pd,
++ struct prop_local_percpu *pl, long frac);
++
++
++/*
+ * ----- SINGLE ------
+ */
+
+diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
+index ebe0c17..f98501b 100644
+--- a/include/linux/ptrace.h
++++ b/include/linux/ptrace.h
+@@ -98,6 +98,10 @@ extern void ptrace_untrace(struct task_struct *child);
+ extern int ptrace_may_attach(struct task_struct *task);
+ extern int __ptrace_may_attach(struct task_struct *task);
+
++static inline int ptrace_reparented(struct task_struct *child)
++{
++ return child->real_parent != child->parent;
++}
+ static inline void ptrace_link(struct task_struct *child,
+ struct task_struct *new_parent)
+ {
diff --git a/include/linux/quota.h b/include/linux/quota.h
-index 6e0393a..eb560d0 100644
+index 6e0393a..52e49dc 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -160,14 +160,18 @@ enum {
@@ -819261,8 +1095781,314 @@
extern spinlock_t dq_data_lock;
/* Maximal numbers of writes for quota operation (insert/delete/update)
+@@ -198,10 +202,14 @@ struct quota_format_type;
+
+ struct mem_dqinfo {
+ struct quota_format_type *dqi_format;
++ int dqi_fmt_id; /* Id of the dqi_format - used when turning
++ * quotas on after remount RW */
+ struct list_head dqi_dirty_list; /* List of dirty dquots */
+ unsigned long dqi_flags;
+ unsigned int dqi_bgrace;
+ unsigned int dqi_igrace;
++ qsize_t dqi_maxblimit;
++ qsize_t dqi_maxilimit;
+ union {
+ struct v1_mem_dqinfo v1_i;
+ struct v2_mem_dqinfo v2_i;
+@@ -292,8 +300,8 @@ struct dquot_operations {
+
+ /* Operations handling requests from userspace */
+ struct quotactl_ops {
+- int (*quota_on)(struct super_block *, int, int, char *);
+- int (*quota_off)(struct super_block *, int);
++ int (*quota_on)(struct super_block *, int, int, char *, int);
++ int (*quota_off)(struct super_block *, int, int);
+ int (*quota_sync)(struct super_block *, int);
+ int (*get_info)(struct super_block *, int, struct if_dqinfo *);
+ int (*set_info)(struct super_block *, int, struct if_dqinfo *);
+@@ -314,6 +322,10 @@ struct quota_format_type {
+
+ #define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */
+ #define DQUOT_GRP_ENABLED 0x02 /* Group diskquotas enabled */
++#define DQUOT_USR_SUSPENDED 0x04 /* User diskquotas are off, but
++ * we have necessary info in
++ * memory to turn them on */
++#define DQUOT_GRP_SUSPENDED 0x08 /* The same for group quotas */
+
+ struct quota_info {
+ unsigned int flags; /* Flags for diskquotas on this device */
+@@ -325,17 +337,16 @@ struct quota_info {
+ struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */
+ };
+
+-/* Inline would be better but we need to dereference super_block which is not defined yet */
+-int mark_dquot_dirty(struct dquot *dquot);
+-
+-#define dquot_dirty(dquot) test_bit(DQ_MOD_B, &(dquot)->dq_flags)
+-
+ #define sb_has_quota_enabled(sb, type) ((type)==USRQUOTA ? \
+ (sb_dqopt(sb)->flags & DQUOT_USR_ENABLED) : (sb_dqopt(sb)->flags & DQUOT_GRP_ENABLED))
+
+ #define sb_any_quota_enabled(sb) (sb_has_quota_enabled(sb, USRQUOTA) | \
+ sb_has_quota_enabled(sb, GRPQUOTA))
+
++#define sb_has_quota_suspended(sb, type) \
++ ((type) == USRQUOTA ? (sb_dqopt(sb)->flags & DQUOT_USR_SUSPENDED) : \
++ (sb_dqopt(sb)->flags & DQUOT_GRP_SUSPENDED))
++
+ int register_quota_format(struct quota_format_type *fmt);
+ void unregister_quota_format(struct quota_format_type *fmt);
+
+diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
+index 5110201..f867020 100644
+--- a/include/linux/quotaops.h
++++ b/include/linux/quotaops.h
+@@ -37,11 +37,11 @@ extern int dquot_release(struct dquot *dquot);
+ extern int dquot_commit_info(struct super_block *sb, int type);
+ extern int dquot_mark_dquot_dirty(struct dquot *dquot);
+
+-extern int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path);
++extern int vfs_quota_on(struct super_block *sb, int type, int format_id,
++ char *path, int remount);
+ extern int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
+ int format_id, int type);
+-extern int vfs_quota_off(struct super_block *sb, int type);
+-#define vfs_quota_off_mount(sb, type) vfs_quota_off(sb, type)
++extern int vfs_quota_off(struct super_block *sb, int type, int remount);
+ extern int vfs_quota_sync(struct super_block *sb, int type);
+ extern int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
+ extern int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
+@@ -59,7 +59,7 @@ extern struct quotactl_ops vfs_quotactl_ops;
+
+ /* It is better to call this function outside of any transaction as it might
+ * need a lot of space in journal for dquot structure allocation. */
+-static __inline__ void DQUOT_INIT(struct inode *inode)
++static inline void DQUOT_INIT(struct inode *inode)
+ {
+ BUG_ON(!inode->i_sb);
+ if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode))
+@@ -67,7 +67,7 @@ static __inline__ void DQUOT_INIT(struct inode *inode)
+ }
+
+ /* The same as with DQUOT_INIT */
+-static __inline__ void DQUOT_DROP(struct inode *inode)
++static inline void DQUOT_DROP(struct inode *inode)
+ {
+ /* Here we can get arbitrary inode from clear_inode() so we have
+ * to be careful. OTOH we don't need locking as quota operations
+@@ -90,7 +90,7 @@ static __inline__ void DQUOT_DROP(struct inode *inode)
+
+ /* The following allocation/freeing/transfer functions *must* be called inside
+ * a transaction (deadlocks possible otherwise) */
+-static __inline__ int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
++static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+ {
+ if (sb_any_quota_enabled(inode->i_sb)) {
+ /* Used space is updated in alloc_space() */
+@@ -102,7 +102,7 @@ static __inline__ int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t
+ return 0;
+ }
+
+-static __inline__ int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr)
++static inline int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr)
+ {
+ int ret;
+ if (!(ret = DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr)))
+@@ -110,7 +110,7 @@ static __inline__ int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr)
+ return ret;
+ }
+
+-static __inline__ int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
++static inline int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+ {
+ if (sb_any_quota_enabled(inode->i_sb)) {
+ /* Used space is updated in alloc_space() */
+@@ -122,7 +122,7 @@ static __inline__ int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+ return 0;
+ }
+
+-static __inline__ int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr)
++static inline int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr)
+ {
+ int ret;
+ if (!(ret = DQUOT_ALLOC_SPACE_NODIRTY(inode, nr)))
+@@ -130,7 +130,7 @@ static __inline__ int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr)
+ return ret;
+ }
+
+-static __inline__ int DQUOT_ALLOC_INODE(struct inode *inode)
++static inline int DQUOT_ALLOC_INODE(struct inode *inode)
+ {
+ if (sb_any_quota_enabled(inode->i_sb)) {
+ DQUOT_INIT(inode);
+@@ -140,7 +140,7 @@ static __inline__ int DQUOT_ALLOC_INODE(struct inode *inode)
+ return 0;
+ }
+
+-static __inline__ void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
++static inline void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+ {
+ if (sb_any_quota_enabled(inode->i_sb))
+ inode->i_sb->dq_op->free_space(inode, nr);
+@@ -148,19 +148,19 @@ static __inline__ void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+ inode_sub_bytes(inode, nr);
+ }
+
+-static __inline__ void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
++static inline void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
+ {
+ DQUOT_FREE_SPACE_NODIRTY(inode, nr);
+ mark_inode_dirty(inode);
+ }
+
+-static __inline__ void DQUOT_FREE_INODE(struct inode *inode)
++static inline void DQUOT_FREE_INODE(struct inode *inode)
+ {
+ if (sb_any_quota_enabled(inode->i_sb))
+ inode->i_sb->dq_op->free_inode(inode, 1);
+ }
+
+-static __inline__ int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr)
++static inline int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr)
+ {
+ if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode)) {
+ DQUOT_INIT(inode);
+@@ -171,14 +171,32 @@ static __inline__ int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr)
+ }
+
+ /* The following two functions cannot be called inside a transaction */
+-#define DQUOT_SYNC(sb) sync_dquots(sb, -1)
++static inline void DQUOT_SYNC(struct super_block *sb)
++{
++ sync_dquots(sb, -1);
++}
+
+-static __inline__ int DQUOT_OFF(struct super_block *sb)
++static inline int DQUOT_OFF(struct super_block *sb, int remount)
+ {
+ int ret = -ENOSYS;
+
+- if (sb_any_quota_enabled(sb) && sb->s_qcop && sb->s_qcop->quota_off)
+- ret = sb->s_qcop->quota_off(sb, -1);
++ if (sb->s_qcop && sb->s_qcop->quota_off)
++ ret = sb->s_qcop->quota_off(sb, -1, remount);
++ return ret;
++}
++
++static inline int DQUOT_ON_REMOUNT(struct super_block *sb)
++{
++ int cnt;
++ int ret = 0, err;
++
++ if (!sb->s_qcop || !sb->s_qcop->quota_on)
++ return -ENOSYS;
++ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
++ err = sb->s_qcop->quota_on(sb, cnt, 0, NULL, 1);
++ if (err < 0 && !ret)
++ ret = err;
++ }
+ return ret;
+ }
+
+@@ -189,13 +207,43 @@ static __inline__ int DQUOT_OFF(struct super_block *sb)
+ */
+ #define sb_dquot_ops (NULL)
+ #define sb_quotactl_ops (NULL)
+-#define DQUOT_INIT(inode) do { } while(0)
+-#define DQUOT_DROP(inode) do { } while(0)
+-#define DQUOT_ALLOC_INODE(inode) (0)
+-#define DQUOT_FREE_INODE(inode) do { } while(0)
+-#define DQUOT_SYNC(sb) do { } while(0)
+-#define DQUOT_OFF(sb) do { } while(0)
+-#define DQUOT_TRANSFER(inode, iattr) (0)
++
++static inline void DQUOT_INIT(struct inode *inode)
++{
++}
++
++static inline void DQUOT_DROP(struct inode *inode)
++{
++}
++
++static inline int DQUOT_ALLOC_INODE(struct inode *inode)
++{
++ return 0;
++}
++
++static inline void DQUOT_FREE_INODE(struct inode *inode)
++{
++}
++
++static inline void DQUOT_SYNC(struct super_block *sb)
++{
++}
++
++static inline int DQUOT_OFF(struct super_block *sb, int remount)
++{
++ return 0;
++}
++
++static inline int DQUOT_ON_REMOUNT(struct super_block *sb)
++{
++ return 0;
++}
++
++static inline int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr)
++{
++ return 0;
++}
++
+ static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+ {
+ inode_add_bytes(inode, nr);
+@@ -235,11 +283,38 @@ static inline void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
+
+ #endif /* CONFIG_QUOTA */
+
+-#define DQUOT_PREALLOC_BLOCK_NODIRTY(inode, nr) DQUOT_PREALLOC_SPACE_NODIRTY(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits)
+-#define DQUOT_PREALLOC_BLOCK(inode, nr) DQUOT_PREALLOC_SPACE(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits)
+-#define DQUOT_ALLOC_BLOCK_NODIRTY(inode, nr) DQUOT_ALLOC_SPACE_NODIRTY(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits)
+-#define DQUOT_ALLOC_BLOCK(inode, nr) DQUOT_ALLOC_SPACE(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits)
+-#define DQUOT_FREE_BLOCK_NODIRTY(inode, nr) DQUOT_FREE_SPACE_NODIRTY(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits)
+-#define DQUOT_FREE_BLOCK(inode, nr) DQUOT_FREE_SPACE(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits)
++static inline int DQUOT_PREALLOC_BLOCK_NODIRTY(struct inode *inode, qsize_t nr)
++{
++ return DQUOT_PREALLOC_SPACE_NODIRTY(inode,
++ nr << inode->i_sb->s_blocksize_bits);
++}
++
++static inline int DQUOT_PREALLOC_BLOCK(struct inode *inode, qsize_t nr)
++{
++ return DQUOT_PREALLOC_SPACE(inode,
++ nr << inode->i_sb->s_blocksize_bits);
++}
++
++static inline int DQUOT_ALLOC_BLOCK_NODIRTY(struct inode *inode, qsize_t nr)
++{
++ return DQUOT_ALLOC_SPACE_NODIRTY(inode,
++ nr << inode->i_sb->s_blocksize_bits);
++}
++
++static inline int DQUOT_ALLOC_BLOCK(struct inode *inode, qsize_t nr)
++{
++ return DQUOT_ALLOC_SPACE(inode,
++ nr << inode->i_sb->s_blocksize_bits);
++}
++
++static inline void DQUOT_FREE_BLOCK_NODIRTY(struct inode *inode, qsize_t nr)
++{
++ DQUOT_FREE_SPACE_NODIRTY(inode, nr << inode->i_sb->s_blocksize_bits);
++}
++
++static inline void DQUOT_FREE_BLOCK(struct inode *inode, qsize_t nr)
++{
++ DQUOT_FREE_SPACE(inode, nr << inode->i_sb->s_blocksize_bits);
++}
+
+ #endif /* _LINUX_QUOTAOPS_ */
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
-index fbaeda7..8ab630b 100644
+index fbaeda7..81a1a02 100644
--- a/include/linux/raid/md.h
+++ b/include/linux/raid/md.h
@@ -19,7 +19,6 @@
@@ -819273,6 +1096099,60 @@
#include <linux/major.h>
#include <linux/ioctl.h>
#include <linux/types.h>
+@@ -95,6 +94,7 @@ extern int sync_page_io(struct block_device *bdev, sector_t sector, int size,
+ extern void md_do_sync(mddev_t *mddev);
+ extern void md_new_event(mddev_t *mddev);
+ extern void md_allow_write(mddev_t *mddev);
++extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
+
+ #endif /* CONFIG_MD */
+ #endif
+diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
+index 7bb6d1a..812ffa5 100644
+--- a/include/linux/raid/md_k.h
++++ b/include/linux/raid/md_k.h
+@@ -84,6 +84,10 @@ struct mdk_rdev_s
+ #define AllReserved 6 /* If whole device is reserved for
+ * one array */
+ #define AutoDetected 7 /* added by auto-detect */
++#define Blocked 8 /* An error occured on an externally
++ * managed array, don't allow writes
++ * until it is cleared */
++ wait_queue_head_t blocked_wait;
+
+ int desc_nr; /* descriptor index in the superblock */
+ int raid_disk; /* role of device in array */
+diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h
+index 93678f5..f0827d3 100644
+--- a/include/linux/raid/raid5.h
++++ b/include/linux/raid/raid5.h
+@@ -252,6 +252,8 @@ struct r6_state {
+ #define STRIPE_EXPANDING 9
+ #define STRIPE_EXPAND_SOURCE 10
+ #define STRIPE_EXPAND_READY 11
++#define STRIPE_IO_STARTED 12 /* do not count towards 'bypass_count' */
++#define STRIPE_FULL_WRITE 13 /* all blocks are set to be overwritten */
+ /*
+ * Operations flags (in issue order)
+ */
+@@ -316,12 +318,17 @@ struct raid5_private_data {
+ int previous_raid_disks;
+
+ struct list_head handle_list; /* stripes needing handling */
++ struct list_head hold_list; /* preread ready stripes */
+ struct list_head delayed_list; /* stripes that have plugged requests */
+ struct list_head bitmap_list; /* stripes delaying awaiting bitmap update */
+ struct bio *retry_read_aligned; /* currently retrying aligned bios */
+ struct bio *retry_read_aligned_list; /* aligned bios retry list */
+ atomic_t preread_active_stripes; /* stripes with scheduled io */
+ atomic_t active_aligned_reads;
++ atomic_t pending_full_writes; /* full write backlog */
++ int bypass_count; /* bypassed prereads */
++ int bypass_threshold; /* preread nice */
++ struct list_head *last_hold; /* detect hold_list promotions */
+
+ atomic_t reshape_stripes; /* stripes with pending writes for reshape */
+ /* unfortunately we need two cache names as we temporarily have
diff --git a/include/linux/raid_class.h b/include/linux/raid_class.h
index d22ad39..6b537f1 100644
--- a/include/linux/raid_class.h
@@ -819304,6 +1096184,317 @@
return rd->attr; \
}
+diff --git a/include/linux/rcuclassic.h b/include/linux/rcuclassic.h
+index b3dccd6..b3aa05b 100644
+--- a/include/linux/rcuclassic.h
++++ b/include/linux/rcuclassic.h
+@@ -33,8 +33,6 @@
+ #ifndef __LINUX_RCUCLASSIC_H
+ #define __LINUX_RCUCLASSIC_H
+
+-#ifdef __KERNEL__
+-
+ #include <linux/cache.h>
+ #include <linux/spinlock.h>
+ #include <linux/threads.h>
+@@ -163,5 +161,4 @@ extern long rcu_batches_completed_bh(void);
+ #define rcu_enter_nohz() do { } while (0)
+ #define rcu_exit_nohz() do { } while (0)
+
+-#endif /* __KERNEL__ */
+ #endif /* __LINUX_RCUCLASSIC_H */
+diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
+index 37a642c..8082d65 100644
+--- a/include/linux/rcupdate.h
++++ b/include/linux/rcupdate.h
+@@ -33,8 +33,6 @@
+ #ifndef __LINUX_RCUPDATE_H
+ #define __LINUX_RCUPDATE_H
+
+-#ifdef __KERNEL__
+-
+ #include <linux/cache.h>
+ #include <linux/spinlock.h>
+ #include <linux/threads.h>
+@@ -245,5 +243,4 @@ extern long rcu_batches_completed_bh(void);
+ extern void rcu_init(void);
+ extern int rcu_needs_cpu(int cpu);
+
+-#endif /* __KERNEL__ */
+ #endif /* __LINUX_RCUPDATE_H */
+diff --git a/include/linux/rcupreempt.h b/include/linux/rcupreempt.h
+index d038aa6..8a05c7e 100644
+--- a/include/linux/rcupreempt.h
++++ b/include/linux/rcupreempt.h
+@@ -33,8 +33,6 @@
+ #ifndef __LINUX_RCUPREEMPT_H
+ #define __LINUX_RCUPREEMPT_H
+
+-#ifdef __KERNEL__
+-
+ #include <linux/cache.h>
+ #include <linux/spinlock.h>
+ #include <linux/threads.h>
+@@ -104,5 +102,4 @@ static inline void rcu_exit_nohz(void)
+ #define rcu_exit_nohz() do { } while (0)
+ #endif /* CONFIG_NO_HZ */
+
+-#endif /* __KERNEL__ */
+ #endif /* __LINUX_RCUPREEMPT_H */
+diff --git a/include/linux/rcupreempt_trace.h b/include/linux/rcupreempt_trace.h
+index 21cd6b2..b99ae07 100644
+--- a/include/linux/rcupreempt_trace.h
++++ b/include/linux/rcupreempt_trace.h
+@@ -32,7 +32,6 @@
+ #ifndef __LINUX_RCUPREEMPT_TRACE_H
+ #define __LINUX_RCUPREEMPT_TRACE_H
+
+-#ifdef __KERNEL__
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+
+@@ -95,5 +94,4 @@ extern void rcupreempt_trace_done_remove(struct rcupreempt_trace *trace);
+ extern void rcupreempt_trace_invoke(struct rcupreempt_trace *trace);
+ extern void rcupreempt_trace_next_add(struct rcupreempt_trace *trace);
+
+-#endif /* __KERNEL__ */
+ #endif /* __LINUX_RCUPREEMPT_TRACE_H */
+diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
+index 8e7eff2..4aacaee 100644
+--- a/include/linux/reiserfs_fs.h
++++ b/include/linux/reiserfs_fs.h
+@@ -2176,6 +2176,7 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+ long reiserfs_compat_ioctl(struct file *filp,
+ unsigned int cmd, unsigned long arg);
++int reiserfs_unpack(struct inode *inode, struct file *filp);
+
+ /* ioctl's command */
+ #define REISERFS_IOC_UNPACK _IOW(0xCD,1,long)
+diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
+index db5ef9b..336ee43 100644
+--- a/include/linux/reiserfs_fs_sb.h
++++ b/include/linux/reiserfs_fs_sb.h
+@@ -177,7 +177,6 @@ struct reiserfs_journal {
+ struct reiserfs_journal_cnode *j_last; /* newest journal block */
+ struct reiserfs_journal_cnode *j_first; /* oldest journal block. start here for traverse */
+
+- struct file *j_dev_file;
+ struct block_device *j_dev_bd;
+ int j_1st_reserved_block; /* first block on s_dev of reserved area journal */
+
+diff --git a/include/linux/res_counter.h b/include/linux/res_counter.h
+index 61363ce..6d9e1fc 100644
+--- a/include/linux/res_counter.h
++++ b/include/linux/res_counter.h
+@@ -9,6 +9,8 @@
+ *
+ * Author: Pavel Emelianov <xemul at openvz.org>
+ *
++ * See Documentation/controllers/resource_counter.txt for more
++ * info about what this counter is.
+ */
+
+ #include <linux/cgroup.h>
+@@ -25,6 +27,10 @@ struct res_counter {
+ */
+ unsigned long long usage;
+ /*
++ * the maximal value of the usage from the counter creation
++ */
++ unsigned long long max_usage;
++ /*
+ * the limit that usage cannot exceed
+ */
+ unsigned long long limit;
+@@ -39,8 +45,9 @@ struct res_counter {
+ spinlock_t lock;
+ };
+
+-/*
++/**
+ * Helpers to interact with userspace
++ * res_counter_read_u64() - returns the value of the specified member.
+ * res_counter_read/_write - put/get the specified fields from the
+ * res_counter struct to/from the user
+ *
+@@ -51,6 +58,8 @@ struct res_counter {
+ * @pos: and the offset.
+ */
+
++u64 res_counter_read_u64(struct res_counter *counter, int member);
++
+ ssize_t res_counter_read(struct res_counter *counter, int member,
+ const char __user *buf, size_t nbytes, loff_t *pos,
+ int (*read_strategy)(unsigned long long val, char *s));
+@@ -64,6 +73,7 @@ ssize_t res_counter_write(struct res_counter *counter, int member,
+
+ enum {
+ RES_USAGE,
++ RES_MAX_USAGE,
+ RES_LIMIT,
+ RES_FAILCNT,
+ };
+@@ -124,4 +134,21 @@ static inline bool res_counter_check_under_limit(struct res_counter *cnt)
+ return ret;
+ }
+
++static inline void res_counter_reset_max(struct res_counter *cnt)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&cnt->lock, flags);
++ cnt->max_usage = cnt->usage;
++ spin_unlock_irqrestore(&cnt->lock, flags);
++}
++
++static inline void res_counter_reset_failcnt(struct res_counter *cnt)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&cnt->lock, flags);
++ cnt->failcnt = 0;
++ spin_unlock_irqrestore(&cnt->lock, flags);
++}
+ #endif
+diff --git a/include/linux/resource.h b/include/linux/resource.h
+index ae13db7..aaa423a 100644
+--- a/include/linux/resource.h
++++ b/include/linux/resource.h
+@@ -19,6 +19,7 @@ struct task_struct;
+ #define RUSAGE_SELF 0
+ #define RUSAGE_CHILDREN (-1)
+ #define RUSAGE_BOTH (-2) /* sys_wait4() uses this */
++#define RUSAGE_THREAD 1 /* only the calling thread */
+
+ struct rusage {
+ struct timeval ru_utime; /* user time used */
+diff --git a/include/linux/rio.h b/include/linux/rio.h
+index 68e3f68..c1c99c9 100644
+--- a/include/linux/rio.h
++++ b/include/linux/rio.h
+@@ -14,8 +14,6 @@
+ #ifndef LINUX_RIO_H
+ #define LINUX_RIO_H
+
+-#ifdef __KERNEL__
+-
+ #include <linux/types.h>
+ #include <linux/ioport.h>
+ #include <linux/list.h>
+@@ -23,7 +21,6 @@
+ #include <linux/device.h>
+ #include <linux/rio_regs.h>
+
+-#define RIO_ANY_DESTID 0xff
+ #define RIO_NO_HOPCOUNT -1
+ #define RIO_INVALID_DESTID 0xffff
+
+@@ -39,11 +36,8 @@
+ entry is invalid (no route
+ exists for the device ID) */
+
+-#ifdef CONFIG_RAPIDIO_8_BIT_TRANSPORT
+-#define RIO_MAX_ROUTE_ENTRIES (1 << 8)
+-#else
+-#define RIO_MAX_ROUTE_ENTRIES (1 << 16)
+-#endif
++#define RIO_MAX_ROUTE_ENTRIES(size) (size ? (1 << 16) : (1 << 8))
++#define RIO_ANY_DESTID(size) (size ? 0xffff : 0xff)
+
+ #define RIO_MAX_MBOX 4
+ #define RIO_MAX_MSG_SIZE 0x1000
+@@ -149,6 +143,11 @@ struct rio_dbell {
+ void *dev_id;
+ };
+
++enum rio_phy_type {
++ RIO_PHY_PARALLEL,
++ RIO_PHY_SERIAL,
++};
++
+ /**
+ * struct rio_mport - RIO master port info
+ * @dbells: List of doorbell events
+@@ -163,6 +162,7 @@ struct rio_dbell {
+ * @id: Port ID, unique among all ports
+ * @index: Port index, unique among all port interfaces of the same type
+ * @name: Port name string
++ * @priv: Master port private data
+ */
+ struct rio_mport {
+ struct list_head dbells; /* list of doorbell events */
+@@ -177,7 +177,13 @@ struct rio_mport {
+ unsigned char id; /* port ID, unique among all ports */
+ unsigned char index; /* port index, unique among all port
+ interfaces of the same type */
++ unsigned int sys_size; /* RapidIO common transport system size.
++ * 0 - Small size. 256 devices.
++ * 1 - Large size, 65536 devices.
++ */
++ enum rio_phy_type phy_type; /* RapidIO phy type */
+ unsigned char name[40];
++ void *priv; /* Master port private data */
+ };
+
+ /**
+@@ -211,7 +217,7 @@ struct rio_switch {
+ u16 switchid;
+ u16 hopcount;
+ u16 destid;
+- u8 route_table[RIO_MAX_ROUTE_ENTRIES];
++ u8 *route_table;
+ int (*add_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
+ u16 table, u16 route_destid, u8 route_port);
+ int (*get_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
+@@ -229,13 +235,15 @@ struct rio_switch {
+ * @dsend: Callback to send a doorbell message.
+ */
+ struct rio_ops {
+- int (*lcread) (int index, u32 offset, int len, u32 * data);
+- int (*lcwrite) (int index, u32 offset, int len, u32 data);
+- int (*cread) (int index, u16 destid, u8 hopcount, u32 offset, int len,
+- u32 * data);
+- int (*cwrite) (int index, u16 destid, u8 hopcount, u32 offset, int len,
+- u32 data);
+- int (*dsend) (int index, u16 destid, u16 data);
++ int (*lcread) (struct rio_mport *mport, int index, u32 offset, int len,
++ u32 *data);
++ int (*lcwrite) (struct rio_mport *mport, int index, u32 offset, int len,
++ u32 data);
++ int (*cread) (struct rio_mport *mport, int index, u16 destid,
++ u8 hopcount, u32 offset, int len, u32 *data);
++ int (*cwrite) (struct rio_mport *mport, int index, u16 destid,
++ u8 hopcount, u32 offset, int len, u32 data);
++ int (*dsend) (struct rio_mport *mport, int index, u16 destid, u16 data);
+ };
+
+ #define RIO_RESOURCE_MEM 0x00000100
+@@ -321,5 +329,4 @@ extern void rio_close_inb_mbox(struct rio_mport *, int);
+ extern int rio_open_outb_mbox(struct rio_mport *, void *, int, int);
+ extern void rio_close_outb_mbox(struct rio_mport *, int);
+
+-#endif /* __KERNEL__ */
+ #endif /* LINUX_RIO_H */
+diff --git a/include/linux/rio_drv.h b/include/linux/rio_drv.h
+index 7adb2a1..90987b7 100644
+--- a/include/linux/rio_drv.h
++++ b/include/linux/rio_drv.h
+@@ -13,8 +13,6 @@
+ #ifndef LINUX_RIO_DRV_H
+ #define LINUX_RIO_DRV_H
+
+-#ifdef __KERNEL__
+-
+ #include <linux/types.h>
+ #include <linux/ioport.h>
+ #include <linux/list.h>
+@@ -465,5 +463,4 @@ extern struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from);
+ extern struct rio_dev *rio_get_asm(u16 vid, u16 did, u16 asm_vid, u16 asm_did,
+ struct rio_dev *from);
+
+-#endif /* __KERNEL__ */
+ #endif /* LINUX_RIO_DRV_H */
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index b9e1740..44c81c7 100644
--- a/include/linux/rtnetlink.h
@@ -819324,6 +1096515,25 @@
printk(KERN_ERR "RTNL: assertion failed at %s (%d)\n", \
__FILE__, __LINE__); \
dump_stack(); \
+diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h
+index 7b524b4..efd348f 100644
+--- a/include/linux/rwsem.h
++++ b/include/linux/rwsem.h
+@@ -9,8 +9,6 @@
+
+ #include <linux/linkage.h>
+
+-#ifdef __KERNEL__
+-
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <asm/system.h>
+@@ -90,5 +88,4 @@ extern void up_read_non_owner(struct rw_semaphore *sem);
+ # define up_read_non_owner(sem) up_read(sem)
+ #endif
+
+-#endif /* __KERNEL__ */
+ #endif /* _LINUX_RWSEM_H */
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index a3d567a..71fc813 100644
--- a/include/linux/scatterlist.h
@@ -819341,7 +1096551,7 @@
* 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
+index 6a1e7af..03c2380 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -61,7 +61,6 @@ struct sched_param {
@@ -819352,7 +1096562,30 @@
#include <asm/page.h>
#include <asm/ptrace.h>
#include <asm/cputime.h>
-@@ -704,6 +703,7 @@ enum cpu_idle_type {
+@@ -69,7 +68,6 @@ struct sched_param {
+ #include <linux/smp.h>
+ #include <linux/sem.h>
+ #include <linux/signal.h>
+-#include <linux/securebits.h>
+ #include <linux/fs_struct.h>
+ #include <linux/compiler.h>
+ #include <linux/completion.h>
+@@ -556,6 +554,14 @@ struct signal_struct {
+ #define SIGNAL_STOP_DEQUEUED 0x00000002 /* stop signal dequeued */
+ #define SIGNAL_STOP_CONTINUED 0x00000004 /* SIGCONT since WCONTINUED reap */
+ #define SIGNAL_GROUP_EXIT 0x00000008 /* group exit in progress */
++/*
++ * Pending notifications to parent.
++ */
++#define SIGNAL_CLD_STOPPED 0x00000010
++#define SIGNAL_CLD_CONTINUED 0x00000020
++#define SIGNAL_CLD_MASK (SIGNAL_CLD_STOPPED|SIGNAL_CLD_CONTINUED)
++
++#define SIGNAL_UNKILLABLE 0x00000040 /* for init: ignore fatal signals */
+
+ /* If true, all threads except ->group_exit_task have pending SIGKILL */
+ static inline int signal_group_exit(const struct signal_struct *sig)
+@@ -704,6 +710,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 */
@@ -819360,7 +1096593,7 @@
#define BALANCE_FOR_MC_POWER \
(sched_smt_power_savings ? SD_POWERSAVINGS_BALANCE : 0)
-@@ -733,12 +733,31 @@ struct sched_group {
+@@ -733,12 +740,31 @@ struct sched_group {
u32 reciprocal_cpu_power;
};
@@ -819392,7 +1096625,7 @@
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 {
+@@ -750,6 +776,7 @@ struct sched_domain {
unsigned int wake_idx;
unsigned int forkexec_idx;
int flags; /* See SD_* */
@@ -819400,7 +1096633,7 @@
/* Runtime fields. */
unsigned long last_balance; /* init to jiffies. units in jiffies */
-@@ -789,7 +809,8 @@ struct sched_domain {
+@@ -789,7 +816,8 @@ struct sched_domain {
#endif
};
@@ -819410,7 +1096643,7 @@
extern int arch_reinit_sched_domains(void);
#endif /* CONFIG_SMP */
-@@ -889,7 +910,8 @@ struct sched_class {
+@@ -889,7 +917,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);
@@ -819420,7 +1096653,7 @@
void (*join_domain)(struct rq *rq);
void (*leave_domain)(struct rq *rq);
-@@ -923,6 +945,7 @@ struct load_weight {
+@@ -923,6 +952,7 @@ struct load_weight {
struct sched_entity {
struct load_weight load; /* for load-balancing */
struct rb_node run_node;
@@ -819428,7 +1096661,7 @@
unsigned int on_rq;
u64 exec_start;
-@@ -982,6 +1005,7 @@ struct sched_rt_entity {
+@@ -982,6 +1012,7 @@ struct sched_rt_entity {
unsigned long timeout;
int nr_cpus_allowed;
@@ -819436,7 +1096669,25 @@
#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)
+@@ -1109,7 +1140,7 @@ struct task_struct {
+ gid_t gid,egid,sgid,fsgid;
+ struct group_info *group_info;
+ kernel_cap_t cap_effective, cap_inheritable, cap_permitted, cap_bset;
+- unsigned keep_capabilities:1;
++ unsigned securebits;
+ struct user_struct *user;
+ #ifdef CONFIG_KEYS
+ struct key *request_key_auth; /* assumed request_key authority */
+@@ -1144,7 +1175,7 @@ struct task_struct {
+ struct sighand_struct *sighand;
+
+ sigset_t blocked, real_blocked;
+- sigset_t saved_sigmask; /* To be restored with TIF_RESTORE_SIGMASK */
++ sigset_t saved_sigmask; /* restored if set_restore_sigmask() was used */
+ struct sigpending pending;
+
+ unsigned long sas_ss_sp;
+@@ -1502,15 +1533,21 @@ static inline void put_task_struct(struct task_struct *t)
#define used_math() tsk_used_math(current)
#ifdef CONFIG_SMP
@@ -819461,7 +1096712,7 @@
extern unsigned long long sched_clock(void);
-@@ -1551,7 +1581,6 @@ static inline void wake_up_idle_cpu(int cpu) { }
+@@ -1551,7 +1588,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;
@@ -819469,7 +1096720,7 @@
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,
+@@ -1564,6 +1600,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;
@@ -819480,7 +1096731,38 @@
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)
+@@ -1637,7 +1677,10 @@ extern struct pid_namespace init_pid_ns;
+ extern struct task_struct *find_task_by_pid_type_ns(int type, int pid,
+ struct pid_namespace *ns);
+
+-extern struct task_struct *find_task_by_pid(pid_t nr);
++static inline struct task_struct *__deprecated find_task_by_pid(pid_t nr)
++{
++ return find_task_by_pid_type_ns(PIDTYPE_PID, nr, &init_pid_ns);
++}
+ extern struct task_struct *find_task_by_vpid(pid_t nr);
+ extern struct task_struct *find_task_by_pid_ns(pid_t nr,
+ struct pid_namespace *ns);
+@@ -1713,8 +1756,7 @@ extern void zap_other_threads(struct task_struct *p);
+ extern int kill_proc(pid_t, int, int);
+ extern struct sigqueue *sigqueue_alloc(void);
+ extern void sigqueue_free(struct sigqueue *);
+-extern int send_sigqueue(int, struct sigqueue *, struct task_struct *);
+-extern int send_group_sigqueue(int, struct sigqueue *, struct task_struct *);
++extern int send_sigqueue(struct sigqueue *, struct task_struct *, int group);
+ extern int do_sigaction(int, struct k_sigaction *, struct k_sigaction *);
+ extern int do_sigaltstack(const stack_t __user *, stack_t __user *, unsigned long);
+
+@@ -1765,6 +1807,8 @@ extern void mmput(struct mm_struct *);
+ extern struct mm_struct *get_task_mm(struct task_struct *task);
+ /* Remove the current tasks stale references to the old mm_struct */
+ extern void mm_release(struct task_struct *, struct mm_struct *);
++/* Allocate a new mm structure and copy contents from tsk->mm */
++extern struct mm_struct *dup_mm(struct task_struct *tsk);
+
+ extern int copy_thread(int, unsigned long, unsigned long, unsigned long, struct task_struct *, struct pt_regs *);
+ extern void flush_thread(void);
+@@ -1893,6 +1937,8 @@ static inline unsigned long *end_of_stack(struct task_struct *p)
#endif
@@ -819489,7 +1096771,7 @@
/* 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)
+@@ -2031,7 +2077,7 @@ static inline void arch_pick_mmap_layout(struct mm_struct *mm)
}
#endif
@@ -819498,7 +1096780,7 @@
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);
+@@ -2041,8 +2087,11 @@ extern void normalize_rt_tasks(void);
#ifdef CONFIG_GROUP_SCHED
extern struct task_group init_task_group;
@@ -819511,7 +1096793,7 @@
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);
+@@ -2053,6 +2102,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);
@@ -819521,23 +1096803,147 @@
#endif
#endif
+@@ -2106,6 +2158,19 @@ static inline void migration_init(void)
+ #define TASK_SIZE_OF(tsk) TASK_SIZE
+ #endif
+
++#ifdef CONFIG_MM_OWNER
++extern void mm_update_next_owner(struct mm_struct *mm);
++extern void mm_init_owner(struct mm_struct *mm, struct task_struct *p);
++#else
++static inline void mm_update_next_owner(struct mm_struct *mm)
++{
++}
++
++static inline void mm_init_owner(struct mm_struct *mm, struct task_struct *p)
++{
++}
++#endif /* CONFIG_MM_OWNER */
++
+ #endif /* __KERNEL__ */
+
+ #endif
+diff --git a/include/linux/securebits.h b/include/linux/securebits.h
+index 5b06178..c1f19db 100644
+--- a/include/linux/securebits.h
++++ b/include/linux/securebits.h
+@@ -3,28 +3,39 @@
+
+ #define SECUREBITS_DEFAULT 0x00000000
+
+-extern unsigned securebits;
+-
+ /* When set UID 0 has no special privileges. When unset, we support
+ inheritance of root-permissions and suid-root executable under
+ compatibility mode. We raise the effective and inheritable bitmasks
+ *of the executable file* if the effective uid of the new process is
+ 0. If the real uid is 0, we raise the inheritable bitmask of the
+ executable file. */
+-#define SECURE_NOROOT 0
++#define SECURE_NOROOT 0
++#define SECURE_NOROOT_LOCKED 1 /* make bit-0 immutable */
+
+ /* When set, setuid to/from uid 0 does not trigger capability-"fixes"
+ to be compatible with old programs relying on set*uid to loose
+ privileges. When unset, setuid doesn't change privileges. */
+-#define SECURE_NO_SETUID_FIXUP 2
++#define SECURE_NO_SETUID_FIXUP 2
++#define SECURE_NO_SETUID_FIXUP_LOCKED 3 /* make bit-2 immutable */
++
++/* When set, a process can retain its capabilities even after
++ transitioning to a non-root user (the set-uid fixup suppressed by
++ bit 2). Bit-4 is cleared when a process calls exec(); setting both
++ bit 4 and 5 will create a barrier through exec that no exec()'d
++ child can use this feature again. */
++#define SECURE_KEEP_CAPS 4
++#define SECURE_KEEP_CAPS_LOCKED 5 /* make bit-4 immutable */
+
+ /* Each securesetting is implemented using two bits. One bit specify
+ whether the setting is on or off. The other bit specify whether the
+ setting is fixed or not. A setting which is fixed cannot be changed
+ from user-level. */
++#define issecure_mask(X) (1 << (X))
++#define issecure(X) (issecure_mask(X) & current->securebits)
+
+-#define issecure(X) ( (1 << (X+1)) & SECUREBITS_DEFAULT ? \
+- (1 << (X)) & SECUREBITS_DEFAULT : \
+- (1 << (X)) & securebits )
++#define SECURE_ALL_BITS (issecure_mask(SECURE_NOROOT) | \
++ issecure_mask(SECURE_NO_SETUID_FIXUP) | \
++ issecure_mask(SECURE_KEEP_CAPS))
++#define SECURE_ALL_LOCKS (SECURE_ALL_BITS << 1)
+
+ #endif /* !_LINUX_SECUREBITS_H */
diff --git a/include/linux/security.h b/include/linux/security.h
-index c673dfd..53a3453 100644
+index c673dfd..50737c7 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
-@@ -36,7 +36,11 @@
-
- extern unsigned securebits;
+@@ -34,33 +34,38 @@
+ #include <linux/xfrm.h>
+ #include <net/flow.h>
+-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)
+ * as the default capabilities functions
+ */
+-extern int cap_capable (struct task_struct *tsk, int cap);
+-extern int cap_settime (struct timespec *ts, struct timezone *tz);
+-extern int cap_ptrace (struct task_struct *parent, struct task_struct *child);
+-extern int cap_capget (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
+-extern int cap_capset_check (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
+-extern void cap_capset_set (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
+-extern int cap_bprm_set_security (struct linux_binprm *bprm);
+-extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
++extern int cap_capable(struct task_struct *tsk, int cap);
++extern int cap_settime(struct timespec *ts, struct timezone *tz);
++extern int cap_ptrace(struct task_struct *parent, struct task_struct *child);
++extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
++extern int cap_capset_check(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
++extern void cap_capset_set(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
++extern int cap_bprm_set_security(struct linux_binprm *bprm);
++extern void cap_bprm_apply_creds(struct linux_binprm *bprm, int unsafe);
+ extern int cap_bprm_secureexec(struct linux_binprm *bprm);
+-extern int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags);
+-extern int cap_inode_removexattr(struct dentry *dentry, char *name);
++extern int cap_inode_setxattr(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags);
++extern int cap_inode_removexattr(struct dentry *dentry, const char *name);
+ extern int cap_inode_need_killpriv(struct dentry *dentry);
+ extern int cap_inode_killpriv(struct dentry *dentry);
+-extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
+-extern void cap_task_reparent_to_init (struct task_struct *p);
+-extern int cap_task_setscheduler (struct task_struct *p, int policy, struct sched_param *lp);
+-extern int cap_task_setioprio (struct task_struct *p, int ioprio);
+-extern int cap_task_setnice (struct task_struct *p, int nice);
+-extern int cap_syslog (int type);
++extern int cap_task_post_setuid(uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
++extern void cap_task_reparent_to_init(struct task_struct *p);
++extern int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
++ unsigned long arg4, unsigned long arg5, long *rc_p);
++extern int cap_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp);
++extern int cap_task_setioprio(struct task_struct *p, int ioprio);
++extern int cap_task_setnice(struct task_struct *p, int nice);
++extern int cap_syslog(int type);
+ extern int cap_vm_enough_memory(struct mm_struct *mm, long pages);
+
+ struct msghdr;
+@@ -124,7 +129,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ {
+ int i;
+ if (opts->mnt_opts)
+- for(i = 0; i < opts->num_mnt_opts; i++)
++ for (i = 0; i < opts->num_mnt_opts; i++)
+ kfree(opts->mnt_opts[i]);
+ kfree(opts->mnt_opts);
+ opts->mnt_opts = NULL;
+@@ -136,6 +141,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
/**
* struct security_operations - main security structure
*
@@ -819550,7 +1096956,51 @@
* 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)
+@@ -180,21 +191,21 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * @bprm contains the linux_binprm structure.
+ * Return 0 if the hook is successful and permission is granted.
+ * @bprm_check_security:
+- * This hook mediates the point when a search for a binary handler will
+- * begin. It allows a check the @bprm->security value which is set in
+- * the preceding set_security call. The primary difference from
+- * set_security is that the argv list and envp list are reliably
+- * available in @bprm. This hook may be called multiple times
+- * during a single execve; and in each pass set_security is called
+- * first.
+- * @bprm contains the linux_binprm structure.
++ * This hook mediates the point when a search for a binary handler will
++ * begin. It allows a check the @bprm->security value which is set in
++ * the preceding set_security call. The primary difference from
++ * set_security is that the argv list and envp list are reliably
++ * available in @bprm. This hook may be called multiple times
++ * during a single execve; and in each pass set_security is called
++ * first.
++ * @bprm contains the linux_binprm structure.
+ * Return 0 if the hook is successful and permission is granted.
+ * @bprm_secureexec:
+- * Return a boolean value (0 or 1) indicating whether a "secure exec"
+- * is required. The flag is passed in the auxiliary table
+- * on the initial stack to the ELF interpreter to indicate whether libc
+- * should enable secure mode.
+- * @bprm contains the linux_binprm structure.
++ * Return a boolean value (0 or 1) indicating whether a "secure exec"
++ * is required. The flag is passed in the auxiliary table
++ * on the initial stack to the ELF interpreter to indicate whether libc
++ * should enable secure mode.
++ * @bprm contains the linux_binprm structure.
+ *
+ * Security hooks for filesystem operations.
+ *
+@@ -211,7 +222,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * Check permission before obtaining filesystem statistics for the @mnt
+ * mountpoint.
+ * @dentry is a handle on the superblock for the filesystem.
+- * Return 0 if permission is granted.
++ * Return 0 if permission is granted.
+ * @sb_mount:
+ * Check permission before an object specified by @dev_name is mounted on
+ * the mount point named by @nd. For an ordinary mount, @dev_name
+@@ -220,7 +231,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.
@@ -819559,7 +1097009,7 @@
* @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)
+@@ -239,7 +250,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.
@@ -819568,7 +1097018,7 @@
* 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)
+@@ -268,16 +279,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.
@@ -819579,18 +1097029,105 @@
- * @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).
++ * @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.
++ * @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)
+@@ -306,9 +317,9 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * @inode_free_security:
+ * @inode contains the inode structure.
+ * Deallocate the inode security structure and set @inode->i_security to
+- * NULL.
++ * NULL.
+ * @inode_init_security:
+- * Obtain the security attribute name suffix and value to set on a newly
++ * Obtain the security attribute name suffix and value to set on a newly
+ * created inode and set up the incore security field for the new inode.
+ * This hook is called by the fs code as part of the inode creation
+ * transaction and provides for atomic labeling of the inode, unlike
+@@ -339,7 +350,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * @new_dentry contains the dentry structure for the new link.
+ * Return 0 if permission is granted.
+ * @inode_unlink:
+- * Check the permission to remove a hard link to a file.
++ * Check the permission to remove a hard link to a file.
+ * @dir contains the inode structure of parent directory of the file.
+ * @dentry contains the dentry structure for file to be unlinked.
+ * Return 0 if permission is granted.
+@@ -351,7 +362,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * Return 0 if permission is granted.
+ * @inode_mkdir:
+ * Check permissions to create a new directory in the existing directory
+- * associated with inode strcture @dir.
++ * associated with inode strcture @dir.
+ * @dir containst the inode structure of parent of the directory to be created.
+ * @dentry contains the dentry structure of new directory.
+ * @mode contains the mode of new directory.
+@@ -396,7 +407,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * called when the actual read/write operations are performed.
+ * @inode contains the inode structure to check.
+ * @mask contains the permission mask.
+- * @nd contains the nameidata (may be NULL).
++ * @nd contains the nameidata (may be NULL).
+ * Return 0 if permission is granted.
+ * @inode_setattr:
+ * Check permission before setting file attributes. Note that the kernel
+@@ -418,24 +429,24 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * can use this hook to release any persistent label associated with the
+ * inode.
+ * @inode_setxattr:
+- * Check permission before setting the extended attributes
+- * @value identified by @name for @dentry.
+- * Return 0 if permission is granted.
++ * Check permission before setting the extended attributes
++ * @value identified by @name for @dentry.
++ * Return 0 if permission is granted.
+ * @inode_post_setxattr:
+- * Update inode security field after successful setxattr operation.
+- * @value identified by @name for @dentry.
++ * Update inode security field after successful setxattr operation.
++ * @value identified by @name for @dentry.
+ * @inode_getxattr:
+- * Check permission before obtaining the extended attributes
+- * identified by @name for @dentry.
+- * Return 0 if permission is granted.
++ * Check permission before obtaining the extended attributes
++ * identified by @name for @dentry.
++ * Return 0 if permission is granted.
+ * @inode_listxattr:
+- * Check permission before obtaining the list of extended attribute
+- * names for @dentry.
+- * Return 0 if permission is granted.
++ * Check permission before obtaining the list of extended attribute
++ * names for @dentry.
++ * Return 0 if permission is granted.
+ * @inode_removexattr:
+- * Check permission before removing the extended attribute
+- * identified by @name for @dentry.
+- * Return 0 if permission is granted.
++ * Check permission before removing the extended attribute
++ * identified by @name for @dentry.
++ * Return 0 if permission is granted.
+ * @inode_getsecurity:
+ * Retrieve a copy of the extended attribute representation of the
+ * security label associated with @name for @inode via @buffer. Note that
+@@ -447,7 +458,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * Set the security label associated with @name for @inode from the
+ * extended attribute value @value. @size indicates the size of the
+ * @value in bytes. @flags may be XATTR_CREATE, XATTR_REPLACE, or 0.
+- * Note that @name is the remainder of the attribute name after the
++ * Note that @name is the remainder of the attribute name after the
+ * security. prefix has been removed.
+ * Return 0 on success.
+ * @inode_listsecurity:
+@@ -468,6 +479,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.
@@ -819602,7 +1097139,16 @@
*
* Security hooks for file operations
*
-@@ -636,6 +651,8 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+@@ -549,7 +565,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * struct file, so the file structure (and associated security information)
+ * can always be obtained:
+ * container_of(fown, struct file, f_owner)
+- * @tsk contains the structure of task receiving signal.
++ * @tsk contains the structure of task receiving signal.
+ * @fown contains the file owner information.
+ * @sig is the signal that will be sent. When 0, kernel sends SIGIO.
+ * Return 0 if permission is granted.
+@@ -636,6 +652,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.
@@ -819611,7 +1097157,113 @@
* @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)
+@@ -703,14 +721,16 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * @arg3 contains a argument.
+ * @arg4 contains a argument.
+ * @arg5 contains a argument.
+- * Return 0 if permission is granted.
++ * @rc_p contains a pointer to communicate back the forced return code
++ * Return 0 if permission is granted, and non-zero if the security module
++ * has taken responsibility (setting *rc_p) for the prctl call.
+ * @task_reparent_to_init:
+- * Set the security attributes in @p->security for a kernel thread that
+- * is being reparented to the init task.
++ * Set the security attributes in @p->security for a kernel thread that
++ * is being reparented to the init task.
+ * @p contains the task_struct for the kernel thread.
+ * @task_to_inode:
+- * Set the security attributes for an inode based on an associated task's
+- * security attributes, e.g. for /proc/pid inodes.
++ * Set the security attributes for an inode based on an associated task's
++ * security attributes, e.g. for /proc/pid inodes.
+ * @p contains the task_struct for the task.
+ * @inode contains the inode structure for the inode.
+ *
+@@ -720,7 +740,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * Save security information for a netlink message so that permission
+ * checking can be performed when the message is processed. The security
+ * information can be saved using the eff_cap field of the
+- * netlink_skb_parms structure. Also may be used to provide fine
++ * netlink_skb_parms structure. Also may be used to provide fine
+ * grained control over message transmission.
+ * @sk associated sock of task sending the message.,
+ * @skb contains the sk_buff structure for the netlink message.
+@@ -788,14 +808,14 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * @sock contains the socket structure.
+ * @address contains the address to bind to.
+ * @addrlen contains the length of address.
+- * Return 0 if permission is granted.
++ * Return 0 if permission is granted.
+ * @socket_connect:
+ * Check permission before socket protocol layer connect operation
+ * attempts to connect socket @sock to a remote address, @address.
+ * @sock contains the socket structure.
+ * @address contains the address of remote endpoint.
+ * @addrlen contains the length of address.
+- * Return 0 if permission is granted.
++ * Return 0 if permission is granted.
+ * @socket_listen:
+ * Check permission before socket protocol layer listen operation.
+ * @sock contains the socket structure.
+@@ -825,7 +845,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * @msg contains the message structure.
+ * @size contains the size of message structure.
+ * @flags contains the operational flags.
+- * Return 0 if permission is granted.
++ * Return 0 if permission is granted.
+ * @socket_getsockname:
+ * Check permission before the local address (name) of the socket object
+ * @sock is retrieved.
+@@ -849,7 +869,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * @sock contains the socket structure.
+ * @level contains the protocol level to set options for.
+ * @optname contains the name of the option to set.
+- * Return 0 if permission is granted.
++ * Return 0 if permission is granted.
+ * @socket_shutdown:
+ * Checks permission before all or part of a connection on the socket
+ * @sock is shut down.
+@@ -876,19 +896,19 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * Return 0 if all is well, otherwise, typical getsockopt return
+ * values.
+ * @socket_getpeersec_dgram:
+- * This hook allows the security module to provide peer socket security
+- * state for udp sockets on a per-packet basis to userspace via
+- * getsockopt SO_GETPEERSEC. The application must first have indicated
+- * the IP_PASSSEC option via getsockopt. It can then retrieve the
+- * security state returned by this hook for a packet via the SCM_SECURITY
+- * ancillary message type.
+- * @skb is the skbuff for the packet being queried
+- * @secdata is a pointer to a buffer in which to copy the security data
+- * @seclen is the maximum length for @secdata
+- * Return 0 on success, error on failure.
++ * This hook allows the security module to provide peer socket security
++ * state for udp sockets on a per-packet basis to userspace via
++ * getsockopt SO_GETPEERSEC. The application must first have indicated
++ * the IP_PASSSEC option via getsockopt. It can then retrieve the
++ * security state returned by this hook for a packet via the SCM_SECURITY
++ * ancillary message type.
++ * @skb is the skbuff for the packet being queried
++ * @secdata is a pointer to a buffer in which to copy the security data
++ * @seclen is the maximum length for @secdata
++ * Return 0 on success, error on failure.
+ * @sk_alloc_security:
+- * Allocate and attach a security structure to the sk->sk_security field,
+- * which is used to copy security attributes between local stream sockets.
++ * Allocate and attach a security structure to the sk->sk_security field,
++ * which is used to copy security attributes between local stream sockets.
+ * @sk_free_security:
+ * Deallocate security structure.
+ * @sk_clone_security:
+@@ -903,31 +923,31 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * @inet_csk_clone:
+ * Sets the new child socket's sid to the openreq sid.
+ * @inet_conn_established:
+- * Sets the connection's peersid to the secmark on skb.
++ * Sets the connection's peersid to the secmark on skb.
+ * @req_classify_flow:
+ * Sets the flow's sid to the openreq sid.
+ *
* Security hooks for XFRM operations.
*
* @xfrm_policy_alloc_security:
@@ -819644,7 +1097296,7 @@
* 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)
+@@ -947,7 +967,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:
@@ -819653,7 +1097305,35 @@
* 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)
+@@ -982,13 +1002,24 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * No return value.
+ * @key_permission:
+ * See whether a specific operational right is granted to a process on a
+- * key.
++ * key.
+ * @key_ref refers to the key (key pointer + possession attribute bit).
+ * @context points to the process to provide the context against which to
+- * evaluate the security data on the key.
++ * evaluate the security data on the key.
+ * @perm describes the combination of permissions required of this key.
+ * Return 1 if permission granted, 0 if permission denied and -ve it the
+- * normal permissions model should be effected.
++ * normal permissions model should be effected.
++ * @key_getsecurity:
++ * Get a textual representation of the security context attached to a key
++ * for the purposes of honouring KEYCTL_GETSECURITY. This function
++ * allocates the storage for the NUL-terminated string and the caller
++ * should free it.
++ * @key points to the key to be queried.
++ * @_buffer points to a pointer that should be set to point to the
++ * resulting string (if no label or an error occurs).
++ * Return the length of the string (including terminating NUL) or -ve if
++ * an error.
++ * May also return 0 (and a NULL buffer pointer) if there is no label.
+ *
+ * Security hooks affecting all System V IPC operations.
+ *
+@@ -997,6 +1028,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.
@@ -819665,7 +1097345,85 @@
*
* 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)
+@@ -1034,7 +1070,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * The @msq may be NULL, e.g. for IPC_INFO or MSG_INFO.
+ * @msq contains the message queue to act upon. May be NULL.
+ * @cmd contains the operation to be performed.
+- * Return 0 if permission is granted.
++ * Return 0 if permission is granted.
+ * @msg_queue_msgsnd:
+ * Check permission before a message, @msg, is enqueued on the message
+ * queue, @msq.
+@@ -1044,8 +1080,8 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * Return 0 if permission is granted.
+ * @msg_queue_msgrcv:
+ * Check permission before a message, @msg, is removed from the message
+- * queue, @msq. The @target task structure contains a pointer to the
+- * process that will be receiving the message (not equal to the current
++ * queue, @msq. The @target task structure contains a pointer to the
++ * process that will be receiving the message (not equal to the current
+ * process when inline receives are being performed).
+ * @msq contains the message queue to retrieve message from.
+ * @msg contains the message destination.
+@@ -1110,15 +1146,15 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * Return 0 if permission is granted.
+ * @sem_semctl:
+ * Check permission when a semaphore operation specified by @cmd is to be
+- * performed on the semaphore @sma. The @sma may be NULL, e.g. for
++ * performed on the semaphore @sma. The @sma may be NULL, e.g. for
+ * IPC_INFO or SEM_INFO.
+ * @sma contains the semaphore structure. May be NULL.
+ * @cmd contains the operation to be performed.
+ * Return 0 if permission is granted.
+ * @sem_semop
+ * Check permissions before performing operations on members of the
+- * semaphore set @sma. If the @alter flag is nonzero, the semaphore set
+- * may be modified.
++ * semaphore set @sma. If the @alter flag is nonzero, the semaphore set
++ * may be modified.
+ * @sma contains the semaphore structure.
+ * @sops contains the operations to perform.
+ * @nsops contains the number of operations to perform.
+@@ -1189,7 +1225,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * @syslog:
+ * Check permission before accessing the kernel message ring or changing
+ * logging to the console.
+- * See the syslog(2) manual page for an explanation of the @type values.
++ * See the syslog(2) manual page for an explanation of the @type values.
+ * @type contains the type of action.
+ * Return 0 if permission is granted.
+ * @settime:
+@@ -1201,79 +1237,112 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * @vm_enough_memory:
+ * Check permissions for allocating a new virtual mapping.
+ * @mm contains the mm struct it is being added to.
+- * @pages contains the number of pages.
++ * @pages contains the number of pages.
+ * Return 0 if permission is granted.
+ *
+ * @register_security:
+- * allow module stacking.
+- * @name contains the name of the security module being stacked.
+- * @ops contains a pointer to the struct security_operations of the module to stack.
+- *
++ * allow module stacking.
++ * @name contains the name of the security module being stacked.
++ * @ops contains a pointer to the struct security_operations of the module to stack.
++ *
+ * @secid_to_secctx:
+ * Convert secid to security context.
+ * @secid contains the security ID.
+ * @secdata contains the pointer that stores the converted security context.
+ * @secctx_to_secid:
+- * Convert security context to secid.
+- * @secid contains the pointer to the generated security ID.
+- * @secdata contains the security context.
++ * Convert security context to secid.
++ * @secid contains the pointer to the generated security ID.
++ * @secdata contains the security context.
+ *
+ * @release_secctx:
+ * Release the security context.
* @secdata contains the security context.
* @seclen contains the length of the security context.
*
@@ -819703,31 +1097461,91 @@
* This is the main security structure.
*/
struct security_operations {
+- int (*ptrace) (struct task_struct * parent, struct task_struct * child);
+- int (*capget) (struct task_struct * target,
+- kernel_cap_t * effective,
+- kernel_cap_t * inheritable, kernel_cap_t * permitted);
+- int (*capset_check) (struct task_struct * target,
+- kernel_cap_t * effective,
+- kernel_cap_t * inheritable,
+- kernel_cap_t * permitted);
+- void (*capset_set) (struct task_struct * target,
+- kernel_cap_t * effective,
+- kernel_cap_t * inheritable,
+- kernel_cap_t * permitted);
+- int (*capable) (struct task_struct * tsk, int cap);
+- int (*acct) (struct file * file);
+- int (*sysctl) (struct ctl_table * table, int op);
+- int (*quotactl) (int cmds, int type, int id, struct super_block * sb);
+- int (*quota_on) (struct dentry * dentry);
+ 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 (*ptrace) (struct task_struct *parent, struct task_struct *child);
++ int (*capget) (struct task_struct *target,
++ kernel_cap_t *effective,
++ kernel_cap_t *inheritable, kernel_cap_t *permitted);
++ int (*capset_check) (struct task_struct *target,
++ kernel_cap_t *effective,
++ kernel_cap_t *inheritable,
++ kernel_cap_t *permitted);
++ void (*capset_set) (struct task_struct *target,
++ kernel_cap_t *effective,
++ kernel_cap_t *inheritable,
++ kernel_cap_t *permitted);
++ int (*capable) (struct task_struct *tsk, int cap);
++ int (*acct) (struct file *file);
++ int (*sysctl) (struct ctl_table *table, int op);
++ int (*quotactl) (int cmds, int type, int id, struct super_block *sb);
++ int (*quota_on) (struct dentry *dentry);
+ int (*syslog) (int type);
+ int (*settime) (struct timespec *ts, struct timezone *tz);
+ int (*vm_enough_memory) (struct mm_struct *mm, long pages);
+
+- int (*bprm_alloc_security) (struct linux_binprm * bprm);
+- void (*bprm_free_security) (struct linux_binprm * bprm);
+- void (*bprm_apply_creds) (struct linux_binprm * bprm, int unsafe);
+- void (*bprm_post_apply_creds) (struct linux_binprm * bprm);
+- int (*bprm_set_security) (struct linux_binprm * bprm);
+- int (*bprm_check_security) (struct linux_binprm * bprm);
+- int (*bprm_secureexec) (struct linux_binprm * bprm);
+-
+- int (*sb_alloc_security) (struct super_block * sb);
+- void (*sb_free_security) (struct super_block * sb);
+- int (*sb_copy_data)(char *orig, char *copy);
++ int (*bprm_alloc_security) (struct linux_binprm *bprm);
++ void (*bprm_free_security) (struct linux_binprm *bprm);
++ void (*bprm_apply_creds) (struct linux_binprm *bprm, int unsafe);
++ void (*bprm_post_apply_creds) (struct linux_binprm *bprm);
++ int (*bprm_set_security) (struct linux_binprm *bprm);
++ int (*bprm_check_security) (struct linux_binprm *bprm);
++ int (*bprm_secureexec) (struct linux_binprm *bprm);
++
++ int (*sb_alloc_security) (struct super_block *sb);
++ void (*sb_free_security) (struct super_block *sb);
++ 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,
+- 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,
++ 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,
+- 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);
++ void (*sb_post_addmount) (struct vfsmount *mnt,
+ struct path *mountpoint);
+ int (*sb_pivotroot) (struct path *old_path,
+ struct path *new_path);
@@ -819736,23 +1097554,293 @@
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);
+@@ -1282,231 +1351,241 @@ struct security_operations {
+ struct super_block *newsb);
+ int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts);
+
+- int (*inode_alloc_security) (struct inode *inode);
++ int (*inode_alloc_security) (struct inode *inode);
+ void (*inode_free_security) (struct inode *inode);
+ int (*inode_init_security) (struct inode *inode, struct inode *dir,
+ char **name, void **value, size_t *len);
+ int (*inode_create) (struct inode *dir,
+- struct dentry *dentry, int mode);
++ struct dentry *dentry, int mode);
+ int (*inode_link) (struct dentry *old_dentry,
+- struct inode *dir, struct dentry *new_dentry);
++ struct inode *dir, struct dentry *new_dentry);
+ int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
+ int (*inode_symlink) (struct inode *dir,
+- struct dentry *dentry, const char *old_name);
++ struct dentry *dentry, const char *old_name);
+ int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, int mode);
+ int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
+ int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
+- int mode, dev_t dev);
++ int mode, dev_t dev);
+ int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
+- struct inode *new_dir, struct dentry *new_dentry);
++ struct inode *new_dir, struct dentry *new_dentry);
+ int (*inode_readlink) (struct dentry *dentry);
+ int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
+ int (*inode_permission) (struct inode *inode, int mask, struct nameidata *nd);
+ int (*inode_setattr) (struct dentry *dentry, struct iattr *attr);
+ int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
+- void (*inode_delete) (struct inode *inode);
+- int (*inode_setxattr) (struct dentry *dentry, char *name, void *value,
+- size_t size, int flags);
+- void (*inode_post_setxattr) (struct dentry *dentry, char *name, void *value,
+- size_t size, int flags);
+- int (*inode_getxattr) (struct dentry *dentry, char *name);
++ void (*inode_delete) (struct inode *inode);
++ int (*inode_setxattr) (struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags);
++ void (*inode_post_setxattr) (struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags);
++ int (*inode_getxattr) (struct dentry *dentry, const char *name);
+ int (*inode_listxattr) (struct dentry *dentry);
+- int (*inode_removexattr) (struct dentry *dentry, char *name);
++ int (*inode_removexattr) (struct dentry *dentry, const char *name);
+ int (*inode_need_killpriv) (struct dentry *dentry);
+ int (*inode_killpriv) (struct dentry *dentry);
+- 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);
+-
+- int (*file_permission) (struct file * file, int mask);
+- int (*file_alloc_security) (struct file * file);
+- void (*file_free_security) (struct file * file);
+- int (*file_ioctl) (struct file * file, unsigned int cmd,
++ 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);
++ void (*file_free_security) (struct file *file);
++ int (*file_ioctl) (struct file *file, unsigned int cmd,
+ unsigned long arg);
+- int (*file_mmap) (struct file * file,
++ int (*file_mmap) (struct file *file,
+ unsigned long reqprot, unsigned long prot,
+ unsigned long flags, unsigned long addr,
+ unsigned long addr_only);
+- int (*file_mprotect) (struct vm_area_struct * vma,
++ int (*file_mprotect) (struct vm_area_struct *vma,
+ unsigned long reqprot,
+ unsigned long prot);
+- int (*file_lock) (struct file * file, unsigned int cmd);
+- int (*file_fcntl) (struct file * file, unsigned int cmd,
++ int (*file_lock) (struct file *file, unsigned int cmd);
++ int (*file_fcntl) (struct file *file, unsigned int cmd,
+ unsigned long arg);
+- int (*file_set_fowner) (struct file * file);
+- int (*file_send_sigiotask) (struct task_struct * tsk,
+- struct fown_struct * fown, int sig);
+- int (*file_receive) (struct file * file);
+- int (*dentry_open) (struct file *file);
++ int (*file_set_fowner) (struct file *file);
++ int (*file_send_sigiotask) (struct task_struct *tsk,
++ struct fown_struct *fown, int sig);
++ int (*file_receive) (struct file *file);
++ int (*dentry_open) (struct file *file);
+
+ int (*task_create) (unsigned long clone_flags);
+- int (*task_alloc_security) (struct task_struct * p);
+- void (*task_free_security) (struct task_struct * p);
++ int (*task_alloc_security) (struct task_struct *p);
++ void (*task_free_security) (struct task_struct *p);
+ int (*task_setuid) (uid_t id0, uid_t id1, uid_t id2, int flags);
+ int (*task_post_setuid) (uid_t old_ruid /* or fsuid */ ,
+ uid_t old_euid, uid_t old_suid, int flags);
+ int (*task_setgid) (gid_t id0, gid_t id1, gid_t id2, int flags);
+- int (*task_setpgid) (struct task_struct * p, pid_t pgid);
+- int (*task_getpgid) (struct task_struct * p);
+- int (*task_getsid) (struct task_struct * p);
+- void (*task_getsecid) (struct task_struct * p, u32 * secid);
++ int (*task_setpgid) (struct task_struct *p, pid_t pgid);
++ int (*task_getpgid) (struct task_struct *p);
++ int (*task_getsid) (struct task_struct *p);
++ void (*task_getsecid) (struct task_struct *p, u32 *secid);
+ int (*task_setgroups) (struct group_info *group_info);
+- int (*task_setnice) (struct task_struct * p, int nice);
+- int (*task_setioprio) (struct task_struct * p, int ioprio);
+- int (*task_getioprio) (struct task_struct * p);
+- int (*task_setrlimit) (unsigned int resource, struct rlimit * new_rlim);
+- int (*task_setscheduler) (struct task_struct * p, int policy,
+- struct sched_param * lp);
+- int (*task_getscheduler) (struct task_struct * p);
+- int (*task_movememory) (struct task_struct * p);
+- int (*task_kill) (struct task_struct * p,
+- struct siginfo * info, int sig, u32 secid);
+- int (*task_wait) (struct task_struct * p);
++ int (*task_setnice) (struct task_struct *p, int nice);
++ int (*task_setioprio) (struct task_struct *p, int ioprio);
++ int (*task_getioprio) (struct task_struct *p);
++ int (*task_setrlimit) (unsigned int resource, struct rlimit *new_rlim);
++ int (*task_setscheduler) (struct task_struct *p, int policy,
++ struct sched_param *lp);
++ int (*task_getscheduler) (struct task_struct *p);
++ int (*task_movememory) (struct task_struct *p);
++ int (*task_kill) (struct task_struct *p,
++ struct siginfo *info, int sig, u32 secid);
++ int (*task_wait) (struct task_struct *p);
+ int (*task_prctl) (int option, unsigned long arg2,
+ unsigned long arg3, unsigned long arg4,
+- unsigned long arg5);
+- void (*task_reparent_to_init) (struct task_struct * p);
+- void (*task_to_inode)(struct task_struct *p, struct inode *inode);
+-
+- int (*ipc_permission) (struct kern_ipc_perm * ipcp, short flag);
+-
+- int (*msg_msg_alloc_security) (struct msg_msg * msg);
+- void (*msg_msg_free_security) (struct msg_msg * msg);
+-
+- int (*msg_queue_alloc_security) (struct msg_queue * msq);
+- void (*msg_queue_free_security) (struct msg_queue * msq);
+- int (*msg_queue_associate) (struct msg_queue * msq, int msqflg);
+- int (*msg_queue_msgctl) (struct msg_queue * msq, int cmd);
+- int (*msg_queue_msgsnd) (struct msg_queue * msq,
+- struct msg_msg * msg, int msqflg);
+- int (*msg_queue_msgrcv) (struct msg_queue * msq,
+- struct msg_msg * msg,
+- struct task_struct * target,
++ unsigned long arg5, long *rc_p);
++ void (*task_reparent_to_init) (struct task_struct *p);
++ 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 {
++
++ int (*msg_msg_alloc_security) (struct msg_msg *msg);
++ void (*msg_msg_free_security) (struct msg_msg *msg);
++
++ int (*msg_queue_alloc_security) (struct msg_queue *msq);
++ void (*msg_queue_free_security) (struct msg_queue *msq);
++ int (*msg_queue_associate) (struct msg_queue *msq, int msqflg);
++ int (*msg_queue_msgctl) (struct msg_queue *msq, int cmd);
++ int (*msg_queue_msgsnd) (struct msg_queue *msq,
++ struct msg_msg *msg, int msqflg);
++ int (*msg_queue_msgrcv) (struct msg_queue *msq,
++ struct msg_msg *msg,
++ struct task_struct *target,
+ long type, int mode);
+
+- int (*shm_alloc_security) (struct shmid_kernel * shp);
+- void (*shm_free_security) (struct shmid_kernel * shp);
+- int (*shm_associate) (struct shmid_kernel * shp, int shmflg);
+- int (*shm_shmctl) (struct shmid_kernel * shp, int cmd);
+- int (*shm_shmat) (struct shmid_kernel * shp,
++ int (*shm_alloc_security) (struct shmid_kernel *shp);
++ void (*shm_free_security) (struct shmid_kernel *shp);
++ int (*shm_associate) (struct shmid_kernel *shp, int shmflg);
++ int (*shm_shmctl) (struct shmid_kernel *shp, int cmd);
++ int (*shm_shmat) (struct shmid_kernel *shp,
+ char __user *shmaddr, int shmflg);
+
+- int (*sem_alloc_security) (struct sem_array * sma);
+- void (*sem_free_security) (struct sem_array * sma);
+- int (*sem_associate) (struct sem_array * sma, int semflg);
+- int (*sem_semctl) (struct sem_array * sma, int cmd);
+- int (*sem_semop) (struct sem_array * sma,
+- struct sembuf * sops, unsigned nsops, int alter);
++ int (*sem_alloc_security) (struct sem_array *sma);
++ void (*sem_free_security) (struct sem_array *sma);
++ int (*sem_associate) (struct sem_array *sma, int semflg);
++ int (*sem_semctl) (struct sem_array *sma, int cmd);
++ int (*sem_semop) (struct sem_array *sma,
++ struct sembuf *sops, unsigned nsops, int alter);
+
+- int (*netlink_send) (struct sock * sk, struct sk_buff * skb);
+- int (*netlink_recv) (struct sk_buff * skb, int cap);
++ int (*netlink_send) (struct sock *sk, struct sk_buff *skb);
++ int (*netlink_recv) (struct sk_buff *skb, int cap);
+
+ /* allow module stacking */
+ int (*register_security) (const char *name,
+- struct security_operations *ops);
++ struct security_operations *ops);
+
+ void (*d_instantiate) (struct dentry *dentry, struct inode *inode);
+
+- int (*getprocattr)(struct task_struct *p, char *name, char **value);
+- int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size);
+- int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen);
+- int (*secctx_to_secid)(char *secdata, u32 seclen, u32 *secid);
+- void (*release_secctx)(char *secdata, u32 seclen);
++ int (*getprocattr) (struct task_struct *p, char *name, char **value);
++ int (*setprocattr) (struct task_struct *p, char *name, void *value, size_t size);
++ int (*secid_to_secctx) (u32 secid, char **secdata, u32 *seclen);
++ int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid);
++ void (*release_secctx) (char *secdata, u32 seclen);
+
+ #ifdef CONFIG_SECURITY_NETWORK
+- int (*unix_stream_connect) (struct socket * sock,
+- struct socket * other, struct sock * newsk);
+- int (*unix_may_send) (struct socket * sock, struct socket * other);
++ int (*unix_stream_connect) (struct socket *sock,
++ struct socket *other, struct sock *newsk);
++ int (*unix_may_send) (struct socket *sock, struct socket *other);
+
+ int (*socket_create) (int family, int type, int protocol, int kern);
+- int (*socket_post_create) (struct socket * sock, int family,
++ int (*socket_post_create) (struct socket *sock, int family,
+ int type, int protocol, int kern);
+- int (*socket_bind) (struct socket * sock,
+- struct sockaddr * address, int addrlen);
+- int (*socket_connect) (struct socket * sock,
+- struct sockaddr * address, int addrlen);
+- int (*socket_listen) (struct socket * sock, int backlog);
+- int (*socket_accept) (struct socket * sock, struct socket * newsock);
+- void (*socket_post_accept) (struct socket * sock,
+- struct socket * newsock);
+- int (*socket_sendmsg) (struct socket * sock,
+- struct msghdr * msg, int size);
+- int (*socket_recvmsg) (struct socket * sock,
+- struct msghdr * msg, int size, int flags);
+- int (*socket_getsockname) (struct socket * sock);
+- int (*socket_getpeername) (struct socket * sock);
+- int (*socket_getsockopt) (struct socket * sock, int level, int optname);
+- int (*socket_setsockopt) (struct socket * sock, int level, int optname);
+- int (*socket_shutdown) (struct socket * sock, int how);
+- int (*socket_sock_rcv_skb) (struct sock * sk, struct sk_buff * skb);
++ int (*socket_bind) (struct socket *sock,
++ struct sockaddr *address, int addrlen);
++ int (*socket_connect) (struct socket *sock,
++ struct sockaddr *address, int addrlen);
++ int (*socket_listen) (struct socket *sock, int backlog);
++ int (*socket_accept) (struct socket *sock, struct socket *newsock);
++ void (*socket_post_accept) (struct socket *sock,
++ struct socket *newsock);
++ int (*socket_sendmsg) (struct socket *sock,
++ struct msghdr *msg, int size);
++ int (*socket_recvmsg) (struct socket *sock,
++ struct msghdr *msg, int size, int flags);
++ int (*socket_getsockname) (struct socket *sock);
++ int (*socket_getpeername) (struct socket *sock);
++ int (*socket_getsockopt) (struct socket *sock, int level, int optname);
++ int (*socket_setsockopt) (struct socket *sock, int level, int optname);
++ int (*socket_shutdown) (struct socket *sock, int how);
++ int (*socket_sock_rcv_skb) (struct sock *sk, struct sk_buff *skb);
+ int (*socket_getpeersec_stream) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len);
+ int (*socket_getpeersec_dgram) (struct socket *sock, struct sk_buff *skb, u32 *secid);
+ int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority);
+ void (*sk_free_security) (struct sock *sk);
+ void (*sk_clone_security) (const struct sock *sk, struct sock *newsk);
+ void (*sk_getsecid) (struct sock *sk, u32 *secid);
+- void (*sock_graft)(struct sock* sk, struct socket *parent);
+- int (*inet_conn_request)(struct sock *sk, struct sk_buff *skb,
+- struct request_sock *req);
+- void (*inet_csk_clone)(struct sock *newsk, const struct request_sock *req);
+- void (*inet_conn_established)(struct sock *sk, struct sk_buff *skb);
+- void (*req_classify_flow)(const struct request_sock *req, struct flowi *fl);
++ void (*sock_graft) (struct sock *sk, struct socket *parent);
++ int (*inet_conn_request) (struct sock *sk, struct sk_buff *skb,
++ struct request_sock *req);
++ void (*inet_csk_clone) (struct sock *newsk, const struct request_sock *req);
++ void (*inet_conn_established) (struct sock *sk, struct sk_buff *skb);
++ void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -819771,37 +1097859,89 @@
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 {
+- 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);
++ 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);
+ #endif /* CONFIG_SECURITY_NETWORK_XFRM */
+ /* key management security hooks */
+ #ifdef CONFIG_KEYS
+- int (*key_alloc)(struct key *key, struct task_struct *tsk, unsigned long flags);
+- void (*key_free)(struct key *key);
+- int (*key_permission)(key_ref_t key_ref,
+- struct task_struct *context,
+- key_perm_t perm);
+-
++ int (*key_alloc) (struct key *key, struct task_struct *tsk, unsigned long flags);
++ void (*key_free) (struct key *key);
++ int (*key_permission) (key_ref_t key_ref,
++ struct task_struct *context,
++ key_perm_t perm);
++ int (*key_getsecurity)(struct key *key, char **_buffer);
#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);
++ 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_init (void);
+-extern int register_security (struct security_operations *ops);
+-extern int mod_reg_security (const char *name, struct security_operations *ops);
++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 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);
+ struct dentry *parent, void *data,
+ const struct file_operations *fops);
+ extern struct dentry *securityfs_create_dir(const char *name, struct dentry *parent);
+ extern void securityfs_remove(struct dentry *dentry);
+
+-
+ /* Security operations */
+ int security_ptrace(struct task_struct *parent, struct task_struct *child);
+ int security_capget(struct task_struct *target,
+- kernel_cap_t *effective,
+- kernel_cap_t *inheritable,
+- kernel_cap_t *permitted);
++ kernel_cap_t *effective,
++ kernel_cap_t *inheritable,
++ kernel_cap_t *permitted);
+ int security_capset_check(struct task_struct *target,
+- kernel_cap_t *effective,
+- kernel_cap_t *inheritable,
+- kernel_cap_t *permitted);
+-void security_capset_set(struct task_struct *target,
+ kernel_cap_t *effective,
+ kernel_cap_t *inheritable,
+ kernel_cap_t *permitted);
++void security_capset_set(struct task_struct *target,
++ kernel_cap_t *effective,
++ kernel_cap_t *inheritable,
++ kernel_cap_t *permitted);
+ int security_capable(struct task_struct *tsk, int cap);
+ int security_acct(struct file *file);
+ int security_sysctl(struct ctl_table *table, int op);
+@@ -1528,16 +1607,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);
+- char *type, unsigned long flags, void *data);
-int security_sb_check_sb(struct vfsmount *mnt, 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 path *path);
int security_sb_umount(struct vfsmount *mnt, int flags);
void security_sb_umount_close(struct vfsmount *mnt);
@@ -819816,7 +1097956,39 @@
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);
+@@ -1554,30 +1633,31 @@ int security_inode_link(struct dentry *old_dentry, struct inode *dir,
+ struct dentry *new_dentry);
+ int security_inode_unlink(struct inode *dir, struct dentry *dentry);
+ int security_inode_symlink(struct inode *dir, struct dentry *dentry,
+- const char *old_name);
++ const char *old_name);
+ int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode);
+ int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
+ int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
+ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
+- struct inode *new_dir, struct dentry *new_dentry);
++ struct inode *new_dir, struct dentry *new_dentry);
+ int security_inode_readlink(struct dentry *dentry);
+ int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
+ int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd);
+ int security_inode_setattr(struct dentry *dentry, struct iattr *attr);
+ int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
+ void security_inode_delete(struct inode *inode);
+-int security_inode_setxattr(struct dentry *dentry, char *name,
+- void *value, size_t size, int flags);
+-void security_inode_post_setxattr(struct dentry *dentry, char *name,
+- void *value, size_t size, int flags);
+-int security_inode_getxattr(struct dentry *dentry, char *name);
++int security_inode_setxattr(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags);
++void security_inode_post_setxattr(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags);
++int security_inode_getxattr(struct dentry *dentry, const char *name);
+ int security_inode_listxattr(struct dentry *dentry);
+-int security_inode_removexattr(struct dentry *dentry, char *name);
++int security_inode_removexattr(struct dentry *dentry, const char *name);
+ int security_inode_need_killpriv(struct dentry *dentry);
+ 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);
@@ -819824,7 +1097996,36 @@
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,
+@@ -1586,12 +1666,12 @@ int security_file_mmap(struct file *file, unsigned long reqprot,
+ unsigned long prot, unsigned long flags,
+ unsigned long addr, unsigned long addr_only);
+ int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
+- unsigned long prot);
++ unsigned long prot);
+ int security_file_lock(struct file *file, unsigned int cmd);
+ int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg);
+ int security_file_set_fowner(struct file *file);
+ int security_file_send_sigiotask(struct task_struct *tsk,
+- struct fown_struct *fown, int sig);
++ struct fown_struct *fown, int sig);
+ int security_file_receive(struct file *file);
+ int security_dentry_open(struct file *file);
+ int security_task_create(unsigned long clone_flags);
+@@ -1599,7 +1679,7 @@ int security_task_alloc(struct task_struct *p);
+ void security_task_free(struct task_struct *p);
+ int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags);
+ int security_task_post_setuid(uid_t old_ruid, uid_t old_euid,
+- uid_t old_suid, int flags);
++ uid_t old_suid, int flags);
+ int security_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags);
+ int security_task_setpgid(struct task_struct *p, pid_t pgid);
+ int security_task_getpgid(struct task_struct *p);
+@@ -1618,10 +1698,11 @@ int security_task_kill(struct task_struct *p, struct siginfo *info,
+ int sig, u32 secid);
+ int security_task_wait(struct task_struct *p);
+ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
+- unsigned long arg4, unsigned long arg5);
++ unsigned long arg4, unsigned long arg5, long *rc_p);
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);
@@ -819832,83 +1098033,957 @@
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)
+@@ -1629,9 +1710,9 @@ void security_msg_queue_free(struct msg_queue *msq);
+ int security_msg_queue_associate(struct msg_queue *msq, int msqflg);
+ int security_msg_queue_msgctl(struct msg_queue *msq, int cmd);
+ int security_msg_queue_msgsnd(struct msg_queue *msq,
+- struct msg_msg *msg, int msqflg);
++ struct msg_msg *msg, int msqflg);
+ int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
+- struct task_struct *target, long type, int mode);
++ struct task_struct *target, long type, int mode);
+ int security_shm_alloc(struct shmid_kernel *shp);
+ void security_shm_free(struct shmid_kernel *shp);
+ int security_shm_associate(struct shmid_kernel *shp, int shmflg);
+@@ -1643,13 +1724,13 @@ int security_sem_associate(struct sem_array *sma, int semflg);
+ int security_sem_semctl(struct sem_array *sma, int cmd);
+ int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
+ unsigned nsops, int alter);
+-void security_d_instantiate (struct dentry *dentry, struct inode *inode);
++void security_d_instantiate(struct dentry *dentry, struct inode *inode);
+ int security_getprocattr(struct task_struct *p, char *name, char **value);
+ int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size);
+ int security_netlink_send(struct sock *sk, struct sk_buff *skb);
+ int security_netlink_recv(struct sk_buff *skb, int cap);
+ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
+-int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid);
++int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
+ void security_release_secctx(char *secdata, u32 seclen);
+
+ #else /* CONFIG_SECURITY */
+@@ -1674,33 +1755,33 @@ static inline int security_init(void)
+ return 0;
+ }
+
+-static inline int security_ptrace (struct task_struct *parent, struct task_struct * child)
++static inline int security_ptrace(struct task_struct *parent, struct task_struct *child)
+ {
+- return cap_ptrace (parent, child);
++ return cap_ptrace(parent, child);
+ }
+
+-static inline int security_capget (struct task_struct *target,
++static inline int security_capget(struct task_struct *target,
+ kernel_cap_t *effective,
+ kernel_cap_t *inheritable,
+ kernel_cap_t *permitted)
+ {
+- return cap_capget (target, effective, inheritable, permitted);
++ return cap_capget(target, effective, inheritable, permitted);
+ }
+
+-static inline int security_capset_check (struct task_struct *target,
++static inline int security_capset_check(struct task_struct *target,
+ kernel_cap_t *effective,
+ kernel_cap_t *inheritable,
+ kernel_cap_t *permitted)
+ {
+- return cap_capset_check (target, effective, inheritable, permitted);
++ return cap_capset_check(target, effective, inheritable, permitted);
+ }
+
+-static inline void security_capset_set (struct task_struct *target,
++static inline void security_capset_set(struct task_struct *target,
+ kernel_cap_t *effective,
+ kernel_cap_t *inheritable,
+ kernel_cap_t *permitted)
+ {
+- cap_capset_set (target, effective, inheritable, permitted);
++ cap_capset_set(target, effective, inheritable, permitted);
+ }
+
+ static inline int security_capable(struct task_struct *tsk, int cap)
+@@ -1708,7 +1789,7 @@ static inline int security_capable(struct task_struct *tsk, int cap)
+ return cap_capable(tsk, cap);
+ }
+
+-static inline int security_acct (struct file *file)
++static inline int security_acct(struct file *file)
+ {
+ return 0;
+ }
+@@ -1718,13 +1799,13 @@ static inline int security_sysctl(struct ctl_table *table, int op)
+ return 0;
+ }
+
+-static inline int security_quotactl (int cmds, int type, int id,
+- struct super_block * sb)
++static inline int security_quotactl(int cmds, int type, int id,
++ struct super_block *sb)
+ {
+ return 0;
+ }
+
+-static inline int security_quota_on (struct dentry * dentry)
++static inline int security_quota_on(struct dentry *dentry)
+ {
+ return 0;
+ }
+@@ -1749,102 +1830,102 @@ static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
+ return cap_vm_enough_memory(mm, pages);
+ }
+
+-static inline int security_bprm_alloc (struct linux_binprm *bprm)
++static inline int security_bprm_alloc(struct linux_binprm *bprm)
+ {
+ return 0;
+ }
+
+-static inline void security_bprm_free (struct linux_binprm *bprm)
++static inline void security_bprm_free(struct linux_binprm *bprm)
+ { }
+
+-static inline void security_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
+-{
+- cap_bprm_apply_creds (bprm, unsafe);
++static inline void security_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
++{
++ cap_bprm_apply_creds(bprm, unsafe);
+ }
+
+-static inline void security_bprm_post_apply_creds (struct linux_binprm *bprm)
++static inline void security_bprm_post_apply_creds(struct linux_binprm *bprm)
+ {
+ return;
+ }
+
+-static inline int security_bprm_set (struct linux_binprm *bprm)
++static inline int security_bprm_set(struct linux_binprm *bprm)
+ {
+- return cap_bprm_set_security (bprm);
++ return cap_bprm_set_security(bprm);
+ }
+
+-static inline int security_bprm_check (struct linux_binprm *bprm)
++static inline int security_bprm_check(struct linux_binprm *bprm)
+ {
+ return 0;
+ }
+
+-static inline int security_bprm_secureexec (struct linux_binprm *bprm)
++static inline int security_bprm_secureexec(struct linux_binprm *bprm)
+ {
+ return cap_bprm_secureexec(bprm);
+ }
+
+-static inline int security_sb_alloc (struct super_block *sb)
++static inline int security_sb_alloc(struct super_block *sb)
+ {
+ return 0;
+ }
+
+-static inline void security_sb_free (struct super_block *sb)
++static inline void security_sb_free(struct super_block *sb)
+ { }
+
+-static inline int security_sb_copy_data (char *orig, char *copy)
++static inline int security_sb_copy_data(char *orig, char *copy)
+ {
+ return 0;
+ }
+
+-static inline int security_sb_kern_mount (struct super_block *sb, void *data)
++static inline int security_sb_kern_mount(struct super_block *sb, void *data)
+ {
+ return 0;
+ }
+
+-static inline int security_sb_statfs (struct dentry *dentry)
++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,
++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,
+ return 0;
}
- static inline int security_sb_check_sb (struct vfsmount *mnt,
+-static inline int security_sb_check_sb (struct vfsmount *mnt,
- struct nameidata *nd)
-+ struct path *path)
++static inline int security_sb_check_sb(struct vfsmount *mnt,
++ struct path *path)
+ {
+ return 0;
+ }
+
+-static inline int security_sb_umount (struct vfsmount *mnt, int flags)
++static inline int security_sb_umount(struct vfsmount *mnt, int flags)
{
return 0;
}
-@@ -1834,17 +1901,17 @@ static inline void security_sb_post_remount (struct vfsmount *mnt,
+
+-static inline void security_sb_umount_close (struct vfsmount *mnt)
++static inline void security_sb_umount_close(struct vfsmount *mnt)
{ }
- static inline void security_sb_post_addmount (struct vfsmount *mnt,
+-static inline void security_sb_umount_busy (struct vfsmount *mnt)
++static inline void security_sb_umount_busy(struct vfsmount *mnt)
+ { }
+
+-static inline void security_sb_post_remount (struct vfsmount *mnt,
++static inline void security_sb_post_remount(struct vfsmount *mnt,
+ unsigned long flags, void *data)
+ { }
+
+-static inline void security_sb_post_addmount (struct vfsmount *mnt,
- struct nameidata *mountpoint_nd)
-+ struct path *mountpoint)
++static inline void security_sb_post_addmount(struct vfsmount *mnt,
++ 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)
++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 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,
+@@ -1868,15 +1949,15 @@ static inline int security_sb_parse_opts_str(char *options, struct security_mnt_
+ return 0;
+ }
+
+-static inline int security_inode_alloc (struct inode *inode)
++static inline int security_inode_alloc(struct inode *inode)
+ {
+ return 0;
+ }
+
+-static inline void security_inode_free (struct inode *inode)
++static inline void security_inode_free(struct inode *inode)
+ { }
+
+-static inline int security_inode_init_security (struct inode *inode,
++static inline int security_inode_init_security(struct inode *inode,
+ struct inode *dir,
+ char **name,
+ void **value,
+@@ -1884,55 +1965,55 @@ static inline int security_inode_init_security (struct inode *inode,
+ {
+ return -EOPNOTSUPP;
+ }
+-
+-static inline int security_inode_create (struct inode *dir,
++
++static inline int security_inode_create(struct inode *dir,
+ struct dentry *dentry,
+ int mode)
+ {
+ return 0;
+ }
+
+-static inline int security_inode_link (struct dentry *old_dentry,
++static inline int security_inode_link(struct dentry *old_dentry,
+ struct inode *dir,
+ struct dentry *new_dentry)
+ {
+ return 0;
+ }
+
+-static inline int security_inode_unlink (struct inode *dir,
++static inline int security_inode_unlink(struct inode *dir,
+ struct dentry *dentry)
+ {
+ return 0;
+ }
+
+-static inline int security_inode_symlink (struct inode *dir,
++static inline int security_inode_symlink(struct inode *dir,
+ struct dentry *dentry,
+ const char *old_name)
+ {
+ return 0;
+ }
+
+-static inline int security_inode_mkdir (struct inode *dir,
++static inline int security_inode_mkdir(struct inode *dir,
+ struct dentry *dentry,
+ int mode)
+ {
+ return 0;
+ }
+
+-static inline int security_inode_rmdir (struct inode *dir,
++static inline int security_inode_rmdir(struct inode *dir,
+ struct dentry *dentry)
+ {
+ return 0;
+ }
+
+-static inline int security_inode_mknod (struct inode *dir,
++static inline int security_inode_mknod(struct inode *dir,
+ struct dentry *dentry,
+ int mode, dev_t dev)
+ {
+ return 0;
+ }
+
+-static inline int security_inode_rename (struct inode *old_dir,
++static inline int security_inode_rename(struct inode *old_dir,
+ struct dentry *old_dentry,
+ struct inode *new_dir,
+ struct dentry *new_dentry)
+@@ -1940,59 +2021,61 @@ static inline int security_inode_rename (struct inode *old_dir,
+ return 0;
+ }
+
+-static inline int security_inode_readlink (struct dentry *dentry)
++static inline int security_inode_readlink(struct dentry *dentry)
+ {
+ return 0;
+ }
+
+-static inline int security_inode_follow_link (struct dentry *dentry,
++static inline int security_inode_follow_link(struct dentry *dentry,
+ struct nameidata *nd)
+ {
+ return 0;
+ }
+
+-static inline int security_inode_permission (struct inode *inode, int mask,
++static inline int security_inode_permission(struct inode *inode, int mask,
+ struct nameidata *nd)
+ {
+ return 0;
+ }
+
+-static inline int security_inode_setattr (struct dentry *dentry,
++static inline int security_inode_setattr(struct dentry *dentry,
+ struct iattr *attr)
+ {
+ return 0;
+ }
+
+-static inline int security_inode_getattr (struct vfsmount *mnt,
++static inline int security_inode_getattr(struct vfsmount *mnt,
+ struct dentry *dentry)
+ {
+ return 0;
+ }
+
+-static inline void security_inode_delete (struct inode *inode)
++static inline void security_inode_delete(struct inode *inode)
+ { }
+
+-static inline int security_inode_setxattr (struct dentry *dentry, char *name,
+- void *value, size_t size, int flags)
++static inline int security_inode_setxattr(struct dentry *dentry,
++ const char *name, const void *value, size_t size, int flags)
+ {
+ return cap_inode_setxattr(dentry, name, value, size, flags);
+ }
+
+-static inline void security_inode_post_setxattr (struct dentry *dentry, char *name,
+- void *value, size_t size, int flags)
++static inline void security_inode_post_setxattr(struct dentry *dentry,
++ const char *name, const void *value, size_t size, int flags)
+ { }
+
+-static inline int security_inode_getxattr (struct dentry *dentry, char *name)
++static inline int security_inode_getxattr(struct dentry *dentry,
++ const char *name)
+ {
+ return 0;
+ }
+
+-static inline int security_inode_listxattr (struct dentry *dentry)
++static inline int security_inode_listxattr(struct dentry *dentry)
+ {
+ return 0;
+ }
+
+-static inline int security_inode_removexattr (struct dentry *dentry, char *name)
++static inline int security_inode_removexattr(struct dentry *dentry,
++ const char *name)
+ {
+ return cap_inode_removexattr(dentry, name);
+ }
+@@ -2022,292 +2105,304 @@ static inline int security_inode_listsecurity(struct inode *inode, char *buffer,
return 0;
}
+-static inline int security_file_permission (struct file *file, int mask)
+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)
++static inline int security_file_permission(struct file *file, int mask)
+ {
+ return 0;
+ }
+
+-static inline int security_file_alloc (struct file *file)
++static inline int security_file_alloc(struct file *file)
+ {
+ return 0;
+ }
+
+-static inline void security_file_free (struct file *file)
++static inline void security_file_free(struct file *file)
+ { }
+
+-static inline int security_file_ioctl (struct file *file, unsigned int cmd,
+- unsigned long arg)
++static inline int security_file_ioctl(struct file *file, unsigned int cmd,
++ unsigned long arg)
+ {
+ return 0;
+ }
+
+-static inline int security_file_mmap (struct file *file, unsigned long reqprot,
+- unsigned long prot,
+- unsigned long flags,
+- unsigned long addr,
+- unsigned long addr_only)
++static inline int security_file_mmap(struct file *file, unsigned long reqprot,
++ unsigned long prot,
++ unsigned long flags,
++ unsigned long addr,
++ unsigned long addr_only)
+ {
+ return 0;
+ }
+
+-static inline int security_file_mprotect (struct vm_area_struct *vma,
+- unsigned long reqprot,
+- unsigned long prot)
++static inline int security_file_mprotect(struct vm_area_struct *vma,
++ unsigned long reqprot,
++ unsigned long prot)
+ {
+ return 0;
+ }
+
+-static inline int security_file_lock (struct file *file, unsigned int cmd)
++static inline int security_file_lock(struct file *file, unsigned int cmd)
+ {
+ return 0;
+ }
+
+-static inline int security_file_fcntl (struct file *file, unsigned int cmd,
+- unsigned long arg)
++static inline int security_file_fcntl(struct file *file, unsigned int cmd,
++ unsigned long arg)
+ {
+ return 0;
+ }
+
+-static inline int security_file_set_fowner (struct file *file)
++static inline int security_file_set_fowner(struct file *file)
+ {
+ return 0;
+ }
+
+-static inline int security_file_send_sigiotask (struct task_struct *tsk,
+- struct fown_struct *fown,
+- int sig)
++static inline int security_file_send_sigiotask(struct task_struct *tsk,
++ struct fown_struct *fown,
++ int sig)
+ {
+ return 0;
+ }
+
+-static inline int security_file_receive (struct file *file)
++static inline int security_file_receive(struct file *file)
+ {
+ return 0;
+ }
+
+-static inline int security_dentry_open (struct file *file)
++static inline int security_dentry_open(struct file *file)
+ {
+ return 0;
+ }
+
+-static inline int security_task_create (unsigned long clone_flags)
++static inline int security_task_create(unsigned long clone_flags)
+ {
+ return 0;
+ }
+
+-static inline int security_task_alloc (struct task_struct *p)
++static inline int security_task_alloc(struct task_struct *p)
+ {
+ return 0;
+ }
+
+-static inline void security_task_free (struct task_struct *p)
++static inline void security_task_free(struct task_struct *p)
+ { }
+
+-static inline int security_task_setuid (uid_t id0, uid_t id1, uid_t id2,
+- int flags)
++static inline int security_task_setuid(uid_t id0, uid_t id1, uid_t id2,
++ int flags)
+ {
+ return 0;
+ }
+
+-static inline int security_task_post_setuid (uid_t old_ruid, uid_t old_euid,
+- uid_t old_suid, int flags)
++static inline int security_task_post_setuid(uid_t old_ruid, uid_t old_euid,
++ uid_t old_suid, int flags)
+ {
+- return cap_task_post_setuid (old_ruid, old_euid, old_suid, flags);
++ return cap_task_post_setuid(old_ruid, old_euid, old_suid, flags);
+ }
+
+-static inline int security_task_setgid (gid_t id0, gid_t id1, gid_t id2,
+- int flags)
++static inline int security_task_setgid(gid_t id0, gid_t id1, gid_t id2,
++ int flags)
+ {
+ return 0;
+ }
+
+-static inline int security_task_setpgid (struct task_struct *p, pid_t pgid)
++static inline int security_task_setpgid(struct task_struct *p, pid_t pgid)
+ {
+ return 0;
+ }
+
+-static inline int security_task_getpgid (struct task_struct *p)
++static inline int security_task_getpgid(struct task_struct *p)
+ {
+ return 0;
+ }
+
+-static inline int security_task_getsid (struct task_struct *p)
++static inline int security_task_getsid(struct task_struct *p)
{
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)
+-static inline void security_task_getsecid (struct task_struct *p, u32 *secid)
-{ }
++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)
+-static inline int security_task_setgroups (struct group_info *group_info)
++static inline int security_task_setgroups(struct group_info *group_info)
+ {
+ return 0;
+ }
+
+-static inline int security_task_setnice (struct task_struct *p, int nice)
++static inline int security_task_setnice(struct task_struct *p, int nice)
+ {
+ return cap_task_setnice(p, nice);
+ }
+
+-static inline int security_task_setioprio (struct task_struct *p, int ioprio)
++static inline int security_task_setioprio(struct task_struct *p, int ioprio)
+ {
+ return cap_task_setioprio(p, ioprio);
+ }
+
+-static inline int security_task_getioprio (struct task_struct *p)
++static inline int security_task_getioprio(struct task_struct *p)
+ {
+ return 0;
+ }
+
+-static inline int security_task_setrlimit (unsigned int resource,
+- struct rlimit *new_rlim)
++static inline int security_task_setrlimit(unsigned int resource,
++ struct rlimit *new_rlim)
+ {
+ return 0;
+ }
+
+-static inline int security_task_setscheduler (struct task_struct *p,
+- int policy,
+- struct sched_param *lp)
++static inline int security_task_setscheduler(struct task_struct *p,
++ int policy,
++ struct sched_param *lp)
+ {
+ return cap_task_setscheduler(p, policy, lp);
+ }
+
+-static inline int security_task_getscheduler (struct task_struct *p)
++static inline int security_task_getscheduler(struct task_struct *p)
+ {
+ return 0;
+ }
+
+-static inline int security_task_movememory (struct task_struct *p)
++static inline int security_task_movememory(struct task_struct *p)
+ {
+ return 0;
+ }
+
+-static inline int security_task_kill (struct task_struct *p,
+- struct siginfo *info, int sig,
+- u32 secid)
++static inline int security_task_kill(struct task_struct *p,
++ struct siginfo *info, int sig,
++ u32 secid)
+ {
+ return 0;
+ }
+
+-static inline int security_task_wait (struct task_struct *p)
++static inline int security_task_wait(struct task_struct *p)
{
-@@ -2216,6 +2290,11 @@ static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
return 0;
}
+-static inline int security_task_prctl (int option, unsigned long arg2,
+- unsigned long arg3,
+- unsigned long arg4,
+- unsigned long arg5)
++static inline int security_task_prctl(int option, unsigned long arg2,
++ unsigned long arg3,
++ unsigned long arg4,
++ unsigned long arg5, long *rc_p)
+ {
+- return 0;
++ return cap_task_prctl(option, arg2, arg3, arg3, arg5, rc_p);
+ }
+
+-static inline void security_task_reparent_to_init (struct task_struct *p)
++static inline void security_task_reparent_to_init(struct task_struct *p)
+ {
+- cap_task_reparent_to_init (p);
++ cap_task_reparent_to_init(p);
+ }
+
+ static inline void security_task_to_inode(struct task_struct *p, struct inode *inode)
+ { }
+
+-static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
+- short flag)
++static inline int security_ipc_permission(struct kern_ipc_perm *ipcp,
++ short flag)
+ {
+ return 0;
+ }
+
+-static inline int security_msg_msg_alloc (struct msg_msg * msg)
+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)
++static inline int security_msg_msg_alloc(struct msg_msg *msg)
+ {
+ return 0;
+ }
+
+-static inline void security_msg_msg_free (struct msg_msg * msg)
++static inline void security_msg_msg_free(struct msg_msg *msg)
+ { }
+
+-static inline int security_msg_queue_alloc (struct msg_queue *msq)
++static inline int security_msg_queue_alloc(struct msg_queue *msq)
+ {
+ return 0;
+ }
+
+-static inline void security_msg_queue_free (struct msg_queue *msq)
++static inline void security_msg_queue_free(struct msg_queue *msq)
+ { }
+
+-static inline int security_msg_queue_associate (struct msg_queue * msq,
+- int msqflg)
++static inline int security_msg_queue_associate(struct msg_queue *msq,
++ int msqflg)
+ {
+ return 0;
+ }
+
+-static inline int security_msg_queue_msgctl (struct msg_queue * msq, int cmd)
++static inline int security_msg_queue_msgctl(struct msg_queue *msq, int cmd)
+ {
+ return 0;
+ }
+
+-static inline int security_msg_queue_msgsnd (struct msg_queue * msq,
+- struct msg_msg * msg, int msqflg)
++static inline int security_msg_queue_msgsnd(struct msg_queue *msq,
++ struct msg_msg *msg, int msqflg)
+ {
+ return 0;
+ }
+
+-static inline int security_msg_queue_msgrcv (struct msg_queue * msq,
+- struct msg_msg * msg,
+- struct task_struct * target,
+- long type, int mode)
++static inline int security_msg_queue_msgrcv(struct msg_queue *msq,
++ struct msg_msg *msg,
++ struct task_struct *target,
++ long type, int mode)
+ {
+ return 0;
+ }
+
+-static inline int security_shm_alloc (struct shmid_kernel *shp)
++static inline int security_shm_alloc(struct shmid_kernel *shp)
+ {
+ return 0;
+ }
+
+-static inline void security_shm_free (struct shmid_kernel *shp)
++static inline void security_shm_free(struct shmid_kernel *shp)
+ { }
+
+-static inline int security_shm_associate (struct shmid_kernel * shp,
+- int shmflg)
++static inline int security_shm_associate(struct shmid_kernel *shp,
++ int shmflg)
+ {
+ return 0;
+ }
+
+-static inline int security_shm_shmctl (struct shmid_kernel * shp, int cmd)
++static inline int security_shm_shmctl(struct shmid_kernel *shp, int cmd)
+ {
+ return 0;
+ }
+
+-static inline int security_shm_shmat (struct shmid_kernel * shp,
+- char __user *shmaddr, int shmflg)
++static inline int security_shm_shmat(struct shmid_kernel *shp,
++ char __user *shmaddr, int shmflg)
+ {
+ return 0;
+ }
+
+-static inline int security_sem_alloc (struct sem_array *sma)
++static inline int security_sem_alloc(struct sem_array *sma)
+ {
+ return 0;
+ }
+
+-static inline void security_sem_free (struct sem_array *sma)
++static inline void security_sem_free(struct sem_array *sma)
+ { }
+
+-static inline int security_sem_associate (struct sem_array * sma, int semflg)
++static inline int security_sem_associate(struct sem_array *sma, int semflg)
+ {
+ return 0;
+ }
+
+-static inline int security_sem_semctl (struct sem_array * sma, int cmd)
++static inline int security_sem_semctl(struct sem_array *sma, int cmd)
+ {
+ return 0;
+ }
+
+-static inline int security_sem_semop (struct sem_array * sma,
+- struct sembuf * sops, unsigned nsops,
+- int alter)
++static inline int security_sem_semop(struct sem_array *sma,
++ struct sembuf *sops, unsigned nsops,
++ int alter)
+ {
+ return 0;
+ }
+
+-static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
++static inline void security_d_instantiate(struct dentry *dentry, struct inode *inode)
+ { }
+
+ static inline int security_getprocattr(struct task_struct *p, char *name, char **value)
+@@ -2320,14 +2415,14 @@ static inline int security_setprocattr(struct task_struct *p, char *name, void *
+ return -EINVAL;
+ }
+
+-static inline int security_netlink_send (struct sock *sk, struct sk_buff *skb)
++static inline int security_netlink_send(struct sock *sk, struct sk_buff *skb)
+ {
+- return cap_netlink_send (sk, skb);
++ return cap_netlink_send(sk, skb);
+ }
+
+-static inline int security_netlink_recv (struct sk_buff *skb, int cap)
++static inline int security_netlink_recv(struct sk_buff *skb, int cap)
+ {
+- return cap_netlink_recv (skb, cap);
++ return cap_netlink_recv(skb, cap);
+ }
+
+ static inline struct dentry *securityfs_create_dir(const char *name,
+@@ -2354,7 +2449,7 @@ static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *secle
+ return -EOPNOTSUPP;
+ }
+
+-static inline int security_secctx_to_secid(char *secdata,
++static inline int security_secctx_to_secid(const char *secdata,
+ u32 seclen,
+ u32 *secid)
+ {
+@@ -2405,26 +2500,26 @@ void security_inet_conn_established(struct sock *sk,
+ struct sk_buff *skb);
+
+ #else /* CONFIG_SECURITY_NETWORK */
+-static inline int security_unix_stream_connect(struct socket * sock,
+- struct socket * other,
+- struct sock * newsk)
++static inline int security_unix_stream_connect(struct socket *sock,
++ struct socket *other,
++ struct sock *newsk)
+ {
+ return 0;
+ }
+
+-static inline int security_unix_may_send(struct socket * sock,
+- struct socket * other)
++static inline int security_unix_may_send(struct socket *sock,
++ struct socket *other)
{
return 0;
-@@ -2562,16 +2641,16 @@ static inline void security_inet_conn_established(struct sock *sk,
+ }
+
+-static inline int security_socket_create (int family, int type,
+- int protocol, int kern)
++static inline int security_socket_create(int family, int type,
++ int protocol, int kern)
+ {
+ return 0;
+ }
+
+-static inline int security_socket_post_create(struct socket * sock,
++static inline int security_socket_post_create(struct socket *sock,
+ int family,
+ int type,
+ int protocol, int kern)
+@@ -2432,77 +2527,77 @@ static inline int security_socket_post_create(struct socket * sock,
+ return 0;
+ }
+
+-static inline int security_socket_bind(struct socket * sock,
+- struct sockaddr * address,
++static inline int security_socket_bind(struct socket *sock,
++ struct sockaddr *address,
+ int addrlen)
+ {
+ return 0;
+ }
+
+-static inline int security_socket_connect(struct socket * sock,
+- struct sockaddr * address,
++static inline int security_socket_connect(struct socket *sock,
++ struct sockaddr *address,
+ int addrlen)
+ {
+ return 0;
+ }
+
+-static inline int security_socket_listen(struct socket * sock, int backlog)
++static inline int security_socket_listen(struct socket *sock, int backlog)
+ {
+ return 0;
+ }
+
+-static inline int security_socket_accept(struct socket * sock,
+- struct socket * newsock)
++static inline int security_socket_accept(struct socket *sock,
++ struct socket *newsock)
+ {
+ return 0;
+ }
+
+-static inline void security_socket_post_accept(struct socket * sock,
+- struct socket * newsock)
++static inline void security_socket_post_accept(struct socket *sock,
++ struct socket *newsock)
+ {
+ }
+
+-static inline int security_socket_sendmsg(struct socket * sock,
+- struct msghdr * msg, int size)
++static inline int security_socket_sendmsg(struct socket *sock,
++ struct msghdr *msg, int size)
+ {
+ return 0;
+ }
+
+-static inline int security_socket_recvmsg(struct socket * sock,
+- struct msghdr * msg, int size,
++static inline int security_socket_recvmsg(struct socket *sock,
++ struct msghdr *msg, int size,
+ int flags)
+ {
+ return 0;
+ }
+
+-static inline int security_socket_getsockname(struct socket * sock)
++static inline int security_socket_getsockname(struct socket *sock)
+ {
+ return 0;
+ }
+
+-static inline int security_socket_getpeername(struct socket * sock)
++static inline int security_socket_getpeername(struct socket *sock)
+ {
+ return 0;
+ }
+
+-static inline int security_socket_getsockopt(struct socket * sock,
++static inline int security_socket_getsockopt(struct socket *sock,
+ int level, int optname)
+ {
+ return 0;
+ }
+
+-static inline int security_socket_setsockopt(struct socket * sock,
++static inline int security_socket_setsockopt(struct socket *sock,
+ int level, int optname)
+ {
+ return 0;
+ }
+
+-static inline int security_socket_shutdown(struct socket * sock, int how)
++static inline int security_socket_shutdown(struct socket *sock, int how)
+ {
+ return 0;
+ }
+-static inline int security_sock_rcv_skb (struct sock * sk,
+- struct sk_buff * skb)
++static inline int security_sock_rcv_skb(struct sock *sk,
++ struct sk_buff *skb)
+ {
+ return 0;
+ }
+@@ -2539,7 +2634,7 @@ static inline void security_req_classify_flow(const struct request_sock *req, st
+ {
+ }
+
+-static inline void security_sock_graft(struct sock* sk, struct socket *parent)
++static inline void security_sock_graft(struct sock *sk, struct socket *parent)
+ {
+ }
+
+@@ -2562,16 +2657,16 @@ static inline void security_inet_conn_established(struct sock *sk,
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -819930,7 +1099005,7 @@
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);
+@@ -2579,21 +2674,21 @@ void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl);
#else /* CONFIG_SECURITY_NETWORK_XFRM */
@@ -819956,7 +1099031,7 @@
{
return 0;
}
-@@ -2619,7 +2698,7 @@ static inline int security_xfrm_state_delete(struct xfrm_state *x)
+@@ -2619,7 +2714,7 @@ static inline int security_xfrm_state_delete(struct xfrm_state *x)
return 0;
}
@@ -819965,7 +1099040,24 @@
{
return 0;
}
-@@ -2672,5 +2751,38 @@ static inline int security_key_permission(key_ref_t key_ref,
+@@ -2648,6 +2743,7 @@ int security_key_alloc(struct key *key, struct task_struct *tsk, unsigned long f
+ void security_key_free(struct key *key);
+ int security_key_permission(key_ref_t key_ref,
+ struct task_struct *context, key_perm_t perm);
++int security_key_getsecurity(struct key *key, char **_buffer);
+
+ #else
+
+@@ -2669,8 +2765,47 @@ static inline int security_key_permission(key_ref_t key_ref,
+ return 0;
+ }
+
++static inline int security_key_getsecurity(struct key *key, char **_buffer)
++{
++ *_buffer = NULL;
++ return 0;
++}
++
#endif
#endif /* CONFIG_KEYS */
@@ -820219,10 +1099311,17 @@
+
+#endif /* __LINUX_SEMAPHORE_H */
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
-index 67c2563..5b5369c 100644
+index 67c2563..a66304a 100644
--- a/include/linux/seq_file.h
+++ b/include/linux/seq_file.h
-@@ -10,6 +10,7 @@ struct seq_operations;
+@@ -1,6 +1,5 @@
+ #ifndef _LINUX_SEQ_FILE_H
+ #define _LINUX_SEQ_FILE_H
+-#ifdef __KERNEL__
+
+ #include <linux/types.h>
+ #include <linux/string.h>
+@@ -10,6 +9,7 @@ struct seq_operations;
struct file;
struct path;
struct inode;
@@ -820230,7 +1099329,7 @@
struct seq_file {
char *buf;
-@@ -30,6 +31,8 @@ struct seq_operations {
+@@ -30,6 +30,8 @@ struct seq_operations {
int (*show) (struct seq_file *m, void *v);
};
@@ -820239,7 +1099338,7 @@
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 *, ...)
+@@ -42,6 +44,9 @@ int seq_printf(struct seq_file *, const char *, ...)
__attribute__ ((format (printf,2,3)));
int seq_path(struct seq_file *, struct path *, char *);
@@ -820249,7 +1099348,7 @@
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,
+@@ -62,18 +67,4 @@ 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);
@@ -820266,7 +1099365,7 @@
- return ((struct seq_net_private *)seq->private)->net;
-}
-
- #endif
+-#endif
#endif
diff --git a/include/linux/seq_file_net.h b/include/linux/seq_file_net.h
new file mode 100644
@@ -820379,11 +1099478,41 @@
}
+diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
+index 00b65c0..3d37c94 100644
+--- a/include/linux/serial_8250.h
++++ b/include/linux/serial_8250.h
+@@ -46,6 +46,7 @@ enum {
+ PLAT8250_DEV_HUB6,
+ PLAT8250_DEV_MCA,
+ PLAT8250_DEV_AU1X00,
++ PLAT8250_DEV_SM501,
+ };
+
+ /*
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
-index 289942f..7cb094a 100644
+index 289942f..d32123a 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
-@@ -213,6 +213,10 @@ struct uart_ops {
+@@ -149,13 +149,15 @@
+ /* Freescale ColdFire */
+ #define PORT_MCF 78
+
+-#define PORT_SC26XX 79
+-
++/* Blackfin SPORT */
++#define PORT_BFIN_SPORT 79
+
+ /* MN10300 on-chip UART numbers */
+ #define PORT_MN10300 80
+ #define PORT_MN10300_CTS 81
+
++#define PORT_SC26XX 82
++
+ #ifdef __KERNEL__
+
+ #include <linux/compiler.h>
+@@ -213,6 +215,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);
@@ -820405,6 +1099534,33 @@
+#define SERIO_ZHENHUA 0x36
#endif
+diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
+index 8d5fb36..f2d12d5 100644
+--- a/include/linux/shmem_fs.h
++++ b/include/linux/shmem_fs.h
+@@ -34,8 +34,7 @@ struct shmem_sb_info {
+ uid_t uid; /* Mount uid for root directory */
+ gid_t gid; /* Mount gid for root directory */
+ mode_t mode; /* Mount mode for root directory */
+- int policy; /* Default NUMA memory alloc policy */
+- nodemask_t policy_nodes; /* nodemask for preferred and bind */
++ struct mempolicy *mpol; /* default memory policy for mappings */
+ };
+
+ static inline struct shmem_inode_info *SHMEM_I(struct inode *inode)
+diff --git a/include/linux/signal.h b/include/linux/signal.h
+index 42d2e0a..84f997f 100644
+--- a/include/linux/signal.h
++++ b/include/linux/signal.h
+@@ -362,8 +362,6 @@ int unhandled_signal(struct task_struct *tsk, int sig);
+ #define sig_kernel_stop(sig) \
+ (((sig) < SIGRTMIN) && siginmask(sig, SIG_KERNEL_STOP_MASK))
+
+-#define sig_needs_tasklist(sig) ((sig) == SIGCONT)
+-
+ #define sig_user_defined(t, signr) \
+ (((t)->sighand->action[(signr)-1].sa.sa_handler != SIG_DFL) && \
+ ((t)->sighand->action[(signr)-1].sa.sa_handler != SIG_IGN))
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index bbd8d00..299ec4b 100644
--- a/include/linux/skbuff.h
@@ -820712,11 +1099868,52 @@
extern struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
unsigned int length, gfp_t gfp_mask);
+diff --git a/include/linux/slab.h b/include/linux/slab.h
+index f62caaa..805ed4b 100644
+--- a/include/linux/slab.h
++++ b/include/linux/slab.h
+@@ -9,8 +9,6 @@
+ #ifndef _LINUX_SLAB_H
+ #define _LINUX_SLAB_H
+
+-#ifdef __KERNEL__
+-
+ #include <linux/gfp.h>
+ #include <linux/types.h>
+
+@@ -29,6 +27,13 @@
+ #define SLAB_MEM_SPREAD 0x00100000UL /* Spread some memory over cpuset */
+ #define SLAB_TRACE 0x00200000UL /* Trace allocations and frees */
+
++/* Flag to prevent checks on free */
++#ifdef CONFIG_DEBUG_OBJECTS
++# define SLAB_DEBUG_OBJECTS 0x00400000UL
++#else
++# define SLAB_DEBUG_OBJECTS 0x00000000UL
++#endif
++
+ /* The following flags affect the page allocator grouping pages by mobility */
+ #define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* Objects are reclaimable */
+ #define SLAB_TEMPORARY SLAB_RECLAIM_ACCOUNT /* Objects are short-lived */
+@@ -276,5 +281,4 @@ extern const struct seq_operations slabinfo_op;
+ ssize_t slabinfo_write(struct file *, const char __user *, size_t, loff_t *);
+ #endif
+
+-#endif /* __KERNEL__ */
+ #endif /* _LINUX_SLAB_H */
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
-index b00c1c7..79d59c9 100644
+index b00c1c7..71e43a1 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
-@@ -45,9 +45,9 @@ struct kmem_cache_cpu {
+@@ -29,6 +29,7 @@ enum stat_item {
+ DEACTIVATE_TO_HEAD, /* Cpu slab was moved to the head of partials */
+ DEACTIVATE_TO_TAIL, /* Cpu slab was moved to the tail of partials */
+ DEACTIVATE_REMOTE_FREES,/* Slab contained remotely freed objects */
++ ORDER_FALLBACK, /* Number of times fallback was necessary */
+ NR_SLUB_STAT_ITEMS };
+
+ struct kmem_cache_cpu {
+@@ -45,14 +46,24 @@ struct kmem_cache_cpu {
struct kmem_cache_node {
spinlock_t list_lock; /* Protect partial list and nr_partial */
unsigned long nr_partial;
@@ -820724,9 +1099921,92 @@
struct list_head partial;
#ifdef CONFIG_SLUB_DEBUG
+ atomic_long_t nr_slabs;
++ atomic_long_t total_objects;
struct list_head full;
#endif
};
+
+ /*
++ * Word size structure that can be atomically updated or read and that
++ * contains both the order and the number of objects that a slab of the
++ * given order would contain.
++ */
++struct kmem_cache_order_objects {
++ unsigned long x;
++};
++
++/*
+ * Slab cache management.
+ */
+ struct kmem_cache {
+@@ -61,7 +72,7 @@ struct kmem_cache {
+ int size; /* The size of an object including meta data */
+ int objsize; /* The size of an object without meta data */
+ int offset; /* Free pointer offset. */
+- int order; /* Current preferred allocation order */
++ struct kmem_cache_order_objects oo;
+
+ /*
+ * Avoid an extra cache line for UP, SMP and for the node local to
+@@ -70,7 +81,8 @@ struct kmem_cache {
+ struct kmem_cache_node local_node;
+
+ /* Allocation and freeing of slabs */
+- int objects; /* Number of objects in slab */
++ struct kmem_cache_order_objects max;
++ struct kmem_cache_order_objects min;
+ gfp_t allocflags; /* gfp flags to use on each alloc */
+ int refcount; /* Refcount for slab cache destroy */
+ void (*ctor)(struct kmem_cache *, void *);
+diff --git a/include/linux/smb.h b/include/linux/smb.h
+index f098dff..caa43b2 100644
+--- a/include/linux/smb.h
++++ b/include/linux/smb.h
+@@ -11,6 +11,7 @@
+
+ #include <linux/types.h>
+ #include <linux/magic.h>
++#include <linux/time.h>
+
+ enum smb_protocol {
+ SMB_PROTOCOL_NONE,
+diff --git a/include/linux/smb_fs_i.h b/include/linux/smb_fs_i.h
+index 8516954..8ccf4ec 100644
+--- a/include/linux/smb_fs_i.h
++++ b/include/linux/smb_fs_i.h
+@@ -9,7 +9,6 @@
+ #ifndef _LINUX_SMB_FS_I
+ #define _LINUX_SMB_FS_I
+
+-#ifdef __KERNEL__
+ #include <linux/types.h>
+ #include <linux/fs.h>
+
+@@ -36,4 +35,3 @@ struct smb_inode_info {
+ };
+
+ #endif
+-#endif
+diff --git a/include/linux/smb_fs_sb.h b/include/linux/smb_fs_sb.h
+index 3aa97aa..8a060a7 100644
+--- a/include/linux/smb_fs_sb.h
++++ b/include/linux/smb_fs_sb.h
+@@ -9,8 +9,6 @@
+ #ifndef _SMB_FS_SB
+ #define _SMB_FS_SB
+
+-#ifdef __KERNEL__
+-
+ #include <linux/types.h>
+ #include <linux/smb.h>
+
+@@ -96,6 +94,4 @@ smb_unlock_server(struct smb_sb_info *server)
+ up(&(server->sem));
+ }
+
+-#endif /* __KERNEL__ */
+-
+ #endif
diff --git a/include/linux/smc91x.h b/include/linux/smc91x.h
new file mode 100644
index 0000000..8e0556b
@@ -821535,8 +1100815,90 @@
/*
* Reserved bit positions in xprt->state
+diff --git a/include/linux/suspend.h b/include/linux/suspend.h
+index 1d7d4c5..a697742 100644
+--- a/include/linux/suspend.h
++++ b/include/linux/suspend.h
+@@ -12,11 +12,22 @@
+ #include <asm/errno.h>
+
+ #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE)
++extern void pm_set_vt_switch(int);
+ extern int pm_prepare_console(void);
+ extern void pm_restore_console(void);
+ #else
+-static inline int pm_prepare_console(void) { return 0; }
+-static inline void pm_restore_console(void) {}
++static inline void pm_set_vt_switch(int do_switch)
++{
++}
++
++static inline int pm_prepare_console(void)
++{
++ return 0;
++}
++
++static inline void pm_restore_console(void)
++{
++}
+ #endif
+
+ typedef int __bitwise suspend_state_t;
+diff --git a/include/linux/svga.h b/include/linux/svga.h
+index 13ad0b8..c59a51a 100644
+--- a/include/linux/svga.h
++++ b/include/linux/svga.h
+@@ -1,8 +1,6 @@
+ #ifndef _LINUX_SVGA_H
+ #define _LINUX_SVGA_H
+
+-#ifdef __KERNEL__
+-
+ #include <linux/pci.h>
+ #include <video/vga.h>
+
+@@ -122,6 +120,5 @@ void svga_set_timings(const struct svga_timing_regs *tm, struct fb_var_screeninf
+
+ int svga_match_format(const struct svga_fb_format *frm, struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix);
+
+-#endif /* __KERNEL__ */
+ #endif /* _LINUX_SVGA_H */
+
+diff --git a/include/linux/swap.h b/include/linux/swap.h
+index 878459a..0b33776 100644
+--- a/include/linux/swap.h
++++ b/include/linux/swap.h
+@@ -177,11 +177,11 @@ extern void activate_page(struct page *);
+ extern void mark_page_accessed(struct page *);
+ extern void lru_add_drain(void);
+ extern int lru_add_drain_all(void);
+-extern int rotate_reclaimable_page(struct page *page);
++extern void rotate_reclaimable_page(struct page *page);
+ extern void swap_setup(void);
+
+ /* linux/mm/vmscan.c */
+-extern unsigned long try_to_free_pages(struct zone **zones, int order,
++extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
+ gfp_t gfp_mask);
+ extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem,
+ gfp_t gfp_mask);
+diff --git a/include/linux/synclink.h b/include/linux/synclink.h
+index 5562fbf..45f6bc8 100644
+--- a/include/linux/synclink.h
++++ b/include/linux/synclink.h
+@@ -13,10 +13,6 @@
+ #define _SYNCLINK_H_
+ #define SYNCLINK_H_VERSION 3.6
+
+-#define BOOLEAN int
+-#define TRUE 1
+-#define FALSE 0
+-
+ #define BIT0 0x0001
+ #define BIT1 0x0002
+ #define BIT2 0x0004
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
-index 4c2577b..8df6d13 100644
+index 4c2577b..0522f36 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -60,7 +60,6 @@ struct getcpu_cache;
@@ -821547,6 +1100909,99 @@
#include <asm/siginfo.h>
#include <asm/signal.h>
#include <linux/quota.h>
+@@ -241,26 +240,28 @@ asmlinkage long sys_truncate64(const char __user *path, loff_t length);
+ asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length);
+ #endif
+
+-asmlinkage long sys_setxattr(char __user *path, char __user *name,
+- void __user *value, size_t size, int flags);
+-asmlinkage long sys_lsetxattr(char __user *path, char __user *name,
+- void __user *value, size_t size, int flags);
+-asmlinkage long sys_fsetxattr(int fd, char __user *name, void __user *value,
+- size_t size, int flags);
+-asmlinkage ssize_t sys_getxattr(char __user *path, char __user *name,
++asmlinkage long sys_setxattr(const char __user *path, const char __user *name,
++ const void __user *value, size_t size, int flags);
++asmlinkage long sys_lsetxattr(const char __user *path, const char __user *name,
++ const void __user *value, size_t size, int flags);
++asmlinkage long sys_fsetxattr(int fd, const char __user *name,
++ const void __user *value, size_t size, int flags);
++asmlinkage ssize_t sys_getxattr(const char __user *path, const char __user *name,
+ void __user *value, size_t size);
+-asmlinkage ssize_t sys_lgetxattr(char __user *path, char __user *name,
++asmlinkage ssize_t sys_lgetxattr(const char __user *path, const char __user *name,
+ void __user *value, size_t size);
+-asmlinkage ssize_t sys_fgetxattr(int fd, char __user *name,
++asmlinkage ssize_t sys_fgetxattr(int fd, const char __user *name,
+ void __user *value, size_t size);
+-asmlinkage ssize_t sys_listxattr(char __user *path, char __user *list,
++asmlinkage ssize_t sys_listxattr(const char __user *path, char __user *list,
+ size_t size);
+-asmlinkage ssize_t sys_llistxattr(char __user *path, char __user *list,
++asmlinkage ssize_t sys_llistxattr(const char __user *path, char __user *list,
+ size_t size);
+ asmlinkage ssize_t sys_flistxattr(int fd, char __user *list, size_t size);
+-asmlinkage long sys_removexattr(char __user *path, char __user *name);
+-asmlinkage long sys_lremovexattr(char __user *path, char __user *name);
+-asmlinkage long sys_fremovexattr(int fd, char __user *name);
++asmlinkage long sys_removexattr(const char __user *path,
++ const char __user *name);
++asmlinkage long sys_lremovexattr(const char __user *path,
++ const char __user *name);
++asmlinkage long sys_fremovexattr(int fd, const char __user *name);
+
+ asmlinkage unsigned long sys_brk(unsigned long brk);
+ asmlinkage long sys_mprotect(unsigned long start, size_t len,
+diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
+index 571f01d..24141b4 100644
+--- a/include/linux/sysctl.h
++++ b/include/linux/sysctl.h
+@@ -945,11 +945,14 @@ enum
+ /* For the /proc/sys support */
+ struct ctl_table;
+ struct nsproxy;
++struct ctl_table_root;
++
+ extern struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev);
+ extern struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces,
+ struct ctl_table_header *prev);
+ extern void sysctl_head_finish(struct ctl_table_header *prev);
+-extern int sysctl_perm(struct ctl_table *table, int op);
++extern int sysctl_perm(struct ctl_table_root *root,
++ struct ctl_table *table, int op);
+
+ typedef struct ctl_table ctl_table;
+
+@@ -981,11 +984,6 @@ extern int do_sysctl (int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen);
+
+-extern int do_sysctl_strategy (struct ctl_table *table,
+- int __user *name, int nlen,
+- void __user *oldval, size_t __user *oldlenp,
+- void __user *newval, size_t newlen);
+-
+ extern ctl_handler sysctl_data;
+ extern ctl_handler sysctl_string;
+ extern ctl_handler sysctl_intvec;
+@@ -1054,6 +1052,8 @@ struct ctl_table_root {
+ struct list_head header_list;
+ struct list_head *(*lookup)(struct ctl_table_root *root,
+ struct nsproxy *namespaces);
++ int (*permissions)(struct ctl_table_root *root,
++ struct nsproxy *namespaces, struct ctl_table *table);
+ };
+
+ /* struct ctl_table_header is used to maintain dynamic lists of
+@@ -1085,8 +1085,6 @@ struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path,
+ void unregister_sysctl_table(struct ctl_table_header * table);
+ int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table);
+
+-#else /* __KERNEL__ */
+-
+ #endif /* __KERNEL__ */
+
+ #endif /* _LINUX_SYSCTL_H */
diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h
index f752e73..f2767bc 100644
--- a/include/linux/sysdev.h
@@ -821592,10 +1101047,28 @@
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
+index 8027104..7858eac 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
-@@ -131,7 +131,6 @@ static inline int sysfs_create_dir(struct kobject *kobj)
+@@ -32,7 +32,7 @@ struct attribute {
+
+ struct attribute_group {
+ const char *name;
+- int (*is_visible)(struct kobject *,
++ mode_t (*is_visible)(struct kobject *,
+ struct attribute *, int);
+ struct attribute **attrs;
+ };
+@@ -105,6 +105,8 @@ void sysfs_remove_link(struct kobject *kobj, const char *name);
+
+ int __must_check sysfs_create_group(struct kobject *kobj,
+ const struct attribute_group *grp);
++int sysfs_update_group(struct kobject *kobj,
++ const struct attribute_group *grp);
+ void sysfs_remove_group(struct kobject *kobj,
+ const struct attribute_group *grp);
+ int sysfs_add_file_to_group(struct kobject *kobj,
+@@ -131,7 +133,6 @@ static inline int sysfs_create_dir(struct kobject *kobj)
static inline void sysfs_remove_dir(struct kobject *kobj)
{
@@ -821603,7 +1101076,7 @@
}
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,
+@@ -160,7 +161,6 @@ static inline int sysfs_chmod_file(struct kobject *kobj,
static inline void sysfs_remove_file(struct kobject *kobj,
const struct attribute *attr)
{
@@ -821611,7 +1101084,7 @@
}
static inline int sysfs_create_bin_file(struct kobject *kobj,
-@@ -169,10 +167,9 @@ static inline int sysfs_create_bin_file(struct kobject *kobj,
+@@ -169,10 +169,9 @@ static inline int sysfs_create_bin_file(struct kobject *kobj,
return 0;
}
@@ -821624,7 +1101097,7 @@
}
static inline int sysfs_create_link(struct kobject *kobj,
-@@ -183,7 +180,6 @@ static inline int sysfs_create_link(struct kobject *kobj,
+@@ -183,7 +182,6 @@ static inline int sysfs_create_link(struct kobject *kobj,
static inline void sysfs_remove_link(struct kobject *kobj, const char *name)
{
@@ -821632,7 +1101105,16 @@
}
static inline int sysfs_create_group(struct kobject *kobj,
-@@ -195,7 +191,6 @@ static inline int sysfs_create_group(struct kobject *kobj,
+@@ -192,10 +190,15 @@ static inline int sysfs_create_group(struct kobject *kobj,
+ return 0;
+ }
+
++static inline int sysfs_update_group(struct kobject *kobj,
++ const struct attribute_group *grp)
++{
++ return 0;
++}
++
static inline void sysfs_remove_group(struct kobject *kobj,
const struct attribute_group *grp)
{
@@ -821640,6 +1101122,23 @@
}
static inline int sysfs_add_file_to_group(struct kobject *kobj,
+diff --git a/include/linux/sysv_fs.h b/include/linux/sysv_fs.h
+index e024863..9641130 100644
+--- a/include/linux/sysv_fs.h
++++ b/include/linux/sysv_fs.h
+@@ -1,11 +1,7 @@
+ #ifndef _LINUX_SYSV_FS_H
+ #define _LINUX_SYSV_FS_H
+
+-#if defined(__GNUC__)
+-# define __packed2__ __attribute__((packed, aligned(2)))
+-#else
+->> I want to scream! <<
+-#endif
++#define __packed2__ __attribute__((packed, aligned(2)))
+
+
+ #ifndef __KERNEL__
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 08027f1..d96d9b1 100644
--- a/include/linux/tcp.h
@@ -821665,8 +1101164,103 @@
unsigned long last_synq_overflow;
u32 tso_deferred;
+diff --git a/include/linux/textsearch.h b/include/linux/textsearch.h
+index 004808a..6f371f2 100644
+--- a/include/linux/textsearch.h
++++ b/include/linux/textsearch.h
+@@ -1,8 +1,6 @@
+ #ifndef __LINUX_TEXTSEARCH_H
+ #define __LINUX_TEXTSEARCH_H
+
+-#ifdef __KERNEL__
+-
+ #include <linux/types.h>
+ #include <linux/list.h>
+ #include <linux/kernel.h>
+@@ -177,6 +175,4 @@ static inline void *ts_config_priv(struct ts_config *conf)
+ return ((u8 *) conf + TS_PRIV_ALIGN(sizeof(struct ts_config)));
+ }
+
+-#endif /* __KERNEL__ */
+-
+ #endif
+diff --git a/include/linux/thermal.h b/include/linux/thermal.h
+index 90c1c19..06d3e6e 100644
+--- a/include/linux/thermal.h
++++ b/include/linux/thermal.h
+@@ -41,6 +41,7 @@ struct thermal_zone_device_ops {
+ int (*set_mode) (struct thermal_zone_device *, const char *);
+ int (*get_trip_type) (struct thermal_zone_device *, int, char *);
+ int (*get_trip_temp) (struct thermal_zone_device *, int, char *);
++ int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
+ };
+
+ struct thermal_cooling_device_ops {
+@@ -65,6 +66,23 @@ struct thermal_cooling_device {
+ ((long)t-2732+5)/10 : ((long)t-2732-5)/10)
+ #define CELSIUS_TO_KELVIN(t) ((t)*10+2732)
+
++#if defined(CONFIG_HWMON) || \
++ (defined(CONFIG_HWMON_MODULE) && defined(CONFIG_THERMAL_MODULE))
++/* thermal zone devices with the same type share one hwmon device */
++struct thermal_hwmon_device {
++ char type[THERMAL_NAME_LENGTH];
++ struct device *device;
++ int count;
++ struct list_head tz_list;
++ struct list_head node;
++};
++
++struct thermal_hwmon_attr {
++ struct device_attribute attr;
++ char name[16];
++};
++#endif
++
+ struct thermal_zone_device {
+ int id;
+ char type[THERMAL_NAME_LENGTH];
+@@ -76,6 +94,13 @@ struct thermal_zone_device {
+ struct idr idr;
+ struct mutex lock; /* protect cooling devices list */
+ struct list_head node;
++#if defined(CONFIG_HWMON) || \
++ (defined(CONFIG_HWMON_MODULE) && defined(CONFIG_THERMAL_MODULE))
++ struct list_head hwmon_node;
++ struct thermal_hwmon_device *hwmon;
++ struct thermal_hwmon_attr temp_input; /* hwmon sys attr */
++ struct thermal_hwmon_attr temp_crit; /* hwmon sys attr */
++#endif
+ };
+
+ struct thermal_zone_device *thermal_zone_device_register(char *, int, void *,
+@@ -88,24 +113,10 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
+ struct thermal_cooling_device *);
+ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int,
+ struct thermal_cooling_device *);
+-
+-#ifdef CONFIG_THERMAL
+ struct thermal_cooling_device *thermal_cooling_device_register(char *, void *,
+ struct
+ thermal_cooling_device_ops
+ *);
+ void thermal_cooling_device_unregister(struct thermal_cooling_device *);
+-#else
+-static inline struct thermal_cooling_device
+-*thermal_cooling_device_register(char *c, void *v,
+- struct thermal_cooling_device_ops *t)
+-{
+- return NULL;
+-}
+-static inline
+- void thermal_cooling_device_unregister(struct thermal_cooling_device *t)
+-{
+-};
+-#endif
+
+ #endif /* __THERMAL_H__ */
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
-index 421323e..accd7ba 100644
+index 421323e..38a5647 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -9,6 +9,9 @@
@@ -821695,6 +1101289,99 @@
};
};
+@@ -80,6 +92,31 @@ static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
+ #define set_need_resched() set_thread_flag(TIF_NEED_RESCHED)
+ #define clear_need_resched() clear_thread_flag(TIF_NEED_RESCHED)
+
+-#endif
++#if defined TIF_RESTORE_SIGMASK && !defined HAVE_SET_RESTORE_SIGMASK
++/*
++ * An arch can define its own version of set_restore_sigmask() to get the
++ * job done however works, with or without TIF_RESTORE_SIGMASK.
++ */
++#define HAVE_SET_RESTORE_SIGMASK 1
++
++/**
++ * set_restore_sigmask() - make sure saved_sigmask processing gets done
++ *
++ * This sets TIF_RESTORE_SIGMASK and ensures that the arch signal code
++ * will run before returning to user mode, to process the flag. For
++ * all callers, TIF_SIGPENDING is already set or it's no harm to set
++ * it. TIF_RESTORE_SIGMASK need not be in the set of bits that the
++ * arch code will notice on return to user mode, in case those bits
++ * are scarce. We set TIF_SIGPENDING here to ensure that the arch
++ * signal code always gets run when TIF_RESTORE_SIGMASK is set.
++ */
++static inline void set_restore_sigmask(void)
++{
++ set_thread_flag(TIF_RESTORE_SIGMASK);
++ set_thread_flag(TIF_SIGPENDING);
++}
++#endif /* TIF_RESTORE_SIGMASK && !HAVE_SET_RESTORE_SIGMASK */
++
++#endif /* __KERNEL__ */
+
+ #endif /* _LINUX_THREAD_INFO_H */
+diff --git a/include/linux/timer.h b/include/linux/timer.h
+index 979fefd..d4ba792 100644
+--- a/include/linux/timer.h
++++ b/include/linux/timer.h
+@@ -4,6 +4,7 @@
+ #include <linux/list.h>
+ #include <linux/ktime.h>
+ #include <linux/stddef.h>
++#include <linux/debugobjects.h>
+
+ struct tvec_base;
+
+@@ -25,6 +26,7 @@ struct timer_list {
+ extern struct tvec_base boot_tvec_bases;
+
+ #define TIMER_INITIALIZER(_function, _expires, _data) { \
++ .entry = { .prev = TIMER_ENTRY_STATIC }, \
+ .function = (_function), \
+ .expires = (_expires), \
+ .data = (_data), \
+@@ -38,6 +40,17 @@ extern struct tvec_base boot_tvec_bases;
+ void init_timer(struct timer_list *timer);
+ void init_timer_deferrable(struct timer_list *timer);
+
++#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
++extern void init_timer_on_stack(struct timer_list *timer);
++extern void destroy_timer_on_stack(struct timer_list *timer);
++#else
++static inline void destroy_timer_on_stack(struct timer_list *timer) { }
++static inline void init_timer_on_stack(struct timer_list *timer)
++{
++ init_timer(timer);
++}
++#endif
++
+ static inline void setup_timer(struct timer_list * timer,
+ void (*function)(unsigned long),
+ unsigned long data)
+@@ -47,6 +60,15 @@ static inline void setup_timer(struct timer_list * timer,
+ init_timer(timer);
+ }
+
++static inline void setup_timer_on_stack(struct timer_list *timer,
++ void (*function)(unsigned long),
++ unsigned long data)
++{
++ timer->function = function;
++ timer->data = data;
++ init_timer_on_stack(timer);
++}
++
+ /**
+ * timer_pending - is a timer pending?
+ * @timer: the timer in question
+@@ -164,5 +186,4 @@ unsigned long __round_jiffies_relative(unsigned long j, int cpu);
+ unsigned long round_jiffies(unsigned long j);
+ unsigned long round_jiffies_relative(unsigned long j);
+
+-
+ #endif
diff --git a/include/linux/topology.h b/include/linux/topology.h
index bd14f8b..4bb7074 100644
--- a/include/linux/topology.h
@@ -821863,11 +1101550,277 @@
}
int transport_class_register(struct transport_class *);
+diff --git a/include/linux/tty.h b/include/linux/tty.h
+index dd8e08f..7f7121f 100644
+--- a/include/linux/tty.h
++++ b/include/linux/tty.h
+@@ -177,27 +177,33 @@ struct signal_struct;
+ * size each time the window is created or resized anyway.
+ * - TYT, 9/14/92
+ */
++
++struct tty_operations;
++
+ struct tty_struct {
+ int magic;
+ struct tty_driver *driver;
++ const struct tty_operations *ops;
+ int index;
+ struct tty_ldisc ldisc;
+ struct mutex termios_mutex;
++ spinlock_t ctrl_lock;
++ /* Termios values are protected by the termios mutex */
+ struct ktermios *termios, *termios_locked;
+ char name[64];
+- struct pid *pgrp;
++ struct pid *pgrp; /* Protected by ctrl lock */
+ struct pid *session;
+ unsigned long flags;
+ int count;
+- struct winsize winsize;
++ struct winsize winsize; /* termios mutex */
+ unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1;
+ unsigned char low_latency:1, warned:1;
+- unsigned char ctrl_status;
++ unsigned char ctrl_status; /* ctrl_lock */
+ unsigned int receive_room; /* Bytes free for queue */
+
+ struct tty_struct *link;
+ struct fasync_struct *fasync;
+- struct tty_bufhead buf;
++ struct tty_bufhead buf; /* Locked internally */
+ int alt_speed; /* For magic substitution of 38400 bps */
+ wait_queue_head_t write_wait;
+ wait_queue_head_t read_wait;
+@@ -211,6 +217,7 @@ struct tty_struct {
+ /*
+ * The following is data for the N_TTY line discipline. For
+ * historical reasons, this is included in the tty structure.
++ * Mostly locked by the BKL.
+ */
+ unsigned int column;
+ unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
+@@ -292,15 +299,21 @@ extern void tty_unregister_device(struct tty_driver *driver, unsigned index);
+ extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
+ int buflen);
+ extern void tty_write_message(struct tty_struct *tty, char *msg);
++extern int tty_put_char(struct tty_struct *tty, unsigned char c);
++extern int tty_chars_in_buffer(struct tty_struct *tty);
++extern int tty_write_room(struct tty_struct *tty);
++extern void tty_driver_flush_buffer(struct tty_struct *tty);
++extern void tty_throttle(struct tty_struct *tty);
++extern void tty_unthrottle(struct tty_struct *tty);
+
+ extern int is_current_pgrp_orphaned(void);
++extern struct pid *tty_get_pgrp(struct tty_struct *tty);
+ extern int is_ignored(int sig);
+ extern int tty_signal(int sig, struct tty_struct *tty);
+ extern void tty_hangup(struct tty_struct * tty);
+ extern void tty_vhangup(struct tty_struct * tty);
+ extern void tty_unhangup(struct file *filp);
+ extern int tty_hung_up_p(struct file * filp);
+-extern int is_tty(struct file *filp);
+ extern void do_SAK(struct tty_struct *tty);
+ extern void __do_SAK(struct tty_struct *tty);
+ extern void disassociate_ctty(int priv);
+@@ -324,8 +337,7 @@ extern void tty_ldisc_put(int);
+ extern void tty_wakeup(struct tty_struct *tty);
+ extern void tty_ldisc_flush(struct tty_struct *tty);
+
+-extern int tty_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+- unsigned long arg);
++extern long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+ extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg);
+ extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
+@@ -351,8 +363,7 @@ extern void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
+ extern void tty_audit_exit(void);
+ extern void tty_audit_fork(struct signal_struct *sig);
+ extern void tty_audit_push(struct tty_struct *tty);
+-extern void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid);
+-extern void tty_audit_opening(void);
++extern void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid);
+ #else
+ static inline void tty_audit_add_data(struct tty_struct *tty,
+ unsigned char *data, size_t size)
+@@ -367,10 +378,7 @@ static inline void tty_audit_fork(struct signal_struct *sig)
+ static inline void tty_audit_push(struct tty_struct *tty)
+ {
+ }
+-static inline void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
+-{
+-}
+-static inline void tty_audit_opening(void)
++static inline void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid)
+ {
+ }
+ #endif
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
-index 85c95cd..21f69ac 100644
+index 85c95cd..59f1c0b 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
-@@ -125,6 +125,7 @@
+@@ -12,11 +12,15 @@
+ * This routine is called when a particular tty device is opened.
+ * This routine is mandatory; if this routine is not filled in,
+ * the attempted open will fail with ENODEV.
++ *
++ * Required method.
+ *
+ * void (*close)(struct tty_struct * tty, struct file * filp);
+ *
+ * This routine is called when a particular tty device is closed.
+ *
++ * Required method.
++ *
+ * int (*write)(struct tty_struct * tty,
+ * const unsigned char *buf, int count);
+ *
+@@ -26,7 +30,9 @@
+ * number of characters actually accepted for writing. This
+ * routine is mandatory.
+ *
+- * void (*put_char)(struct tty_struct *tty, unsigned char ch);
++ * Optional: Required for writable devices.
++ *
++ * int (*put_char)(struct tty_struct *tty, unsigned char ch);
+ *
+ * This routine is called by the kernel to write a single
+ * character to the tty device. If the kernel uses this routine,
+@@ -34,10 +40,18 @@
+ * done stuffing characters into the driver. If there is no room
+ * in the queue, the character is ignored.
+ *
++ * Optional: Kernel will use the write method if not provided.
++ *
++ * Note: Do not call this function directly, call tty_put_char
++ *
+ * void (*flush_chars)(struct tty_struct *tty);
+ *
+ * This routine is called by the kernel after it has written a
+ * series of characters to the tty device using put_char().
++ *
++ * Optional:
++ *
++ * Note: Do not call this function directly, call tty_driver_flush_chars
+ *
+ * int (*write_room)(struct tty_struct *tty);
+ *
+@@ -45,6 +59,10 @@
+ * will accept for queuing to be written. This number is subject
+ * to change as output buffers get emptied, or if the output flow
+ * control is acted.
++ *
++ * Required if write method is provided else not needed.
++ *
++ * Note: Do not call this function directly, call tty_write_room
+ *
+ * int (*ioctl)(struct tty_struct *tty, struct file * file,
+ * unsigned int cmd, unsigned long arg);
+@@ -53,28 +71,37 @@
+ * device-specific ioctl's. If the ioctl number passed in cmd
+ * is not recognized by the driver, it should return ENOIOCTLCMD.
+ *
++ * Optional
++ *
+ * long (*compat_ioctl)(struct tty_struct *tty, struct file * file,
+ * unsigned int cmd, unsigned long arg);
+ *
+ * implement ioctl processing for 32 bit process on 64 bit system
++ *
++ * Optional
+ *
+ * void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
+ *
+ * This routine allows the tty driver to be notified when
+- * device's termios settings have changed. Note that a
+- * well-designed tty driver should be prepared to accept the case
+- * where old == NULL, and try to do something rational.
++ * device's termios settings have changed.
++ *
++ * Optional: Called under the termios lock
++ *
+ *
+ * void (*set_ldisc)(struct tty_struct *tty);
+ *
+ * This routine allows the tty driver to be notified when the
+ * device's termios settings have changed.
++ *
++ * Optional: Called under BKL (currently)
+ *
+ * void (*throttle)(struct tty_struct * tty);
+ *
+ * This routine notifies the tty driver that input buffers for
+ * the line discipline are close to full, and it should somehow
+ * signal that no more characters should be sent to the tty.
++ *
++ * Optional: Always invoke via tty_throttle();
+ *
+ * void (*unthrottle)(struct tty_struct * tty);
+ *
+@@ -82,21 +109,33 @@
+ * that characters can now be sent to the tty without fear of
+ * overrunning the input buffers of the line disciplines.
+ *
++ * Optional: Always invoke via tty_unthrottle();
++ *
+ * void (*stop)(struct tty_struct *tty);
+ *
+ * This routine notifies the tty driver that it should stop
+ * outputting characters to the tty device.
++ *
++ * Optional:
++ *
++ * Note: Call stop_tty not this method.
+ *
+ * void (*start)(struct tty_struct *tty);
+ *
+ * This routine notifies the tty driver that it resume sending
+ * characters to the tty device.
++ *
++ * Optional:
++ *
++ * Note: Call start_tty not this method.
+ *
+ * void (*hangup)(struct tty_struct *tty);
+ *
+ * This routine notifies the tty driver that it should hangup the
+ * tty device.
+ *
++ * Required:
++ *
+ * void (*break_ctl)(struct tty_stuct *tty, int state);
+ *
+ * This optional routine requests the tty driver to turn on or
+@@ -106,18 +145,26 @@
+ *
+ * If this routine is implemented, the high-level tty driver will
+ * handle the following ioctls: TCSBRK, TCSBRKP, TIOCSBRK,
+- * TIOCCBRK. Otherwise, these ioctls will be passed down to the
+- * driver to handle.
++ * TIOCCBRK.
++ *
++ * Optional: Required for TCSBRK/BRKP/etc handling.
+ *
+ * void (*wait_until_sent)(struct tty_struct *tty, int timeout);
+ *
+ * This routine waits until the device has written out all of the
+ * characters in its transmitter FIFO.
+ *
++ * Optional: If not provided the device is assumed to have no FIFO
++ *
++ * Note: Usually correct to call tty_wait_until_sent
++ *
+ * void (*send_xchar)(struct tty_struct *tty, char ch);
+ *
+ * This routine is used to send a high-priority XON/XOFF
+ * character to the device.
++ *
++ * Optional: If not provided then the write method is called under
++ * the atomic write lock to keep it serialized with the ldisc.
+ */
+
+ #include <linux/fs.h>
+@@ -125,13 +172,14 @@
#include <linux/cdev.h>
struct tty_struct;
@@ -821875,7 +1101828,20 @@
struct tty_operations {
int (*open)(struct tty_struct * tty, struct file * filp);
-@@ -157,6 +158,11 @@ struct tty_operations {
+ void (*close)(struct tty_struct * tty, struct file * filp);
+ int (*write)(struct tty_struct * tty,
+ const unsigned char *buf, int count);
+- void (*put_char)(struct tty_struct *tty, unsigned char ch);
++ int (*put_char)(struct tty_struct *tty, unsigned char ch);
+ void (*flush_chars)(struct tty_struct *tty);
+ int (*write_room)(struct tty_struct *tty);
+ int (*chars_in_buffer)(struct tty_struct *tty);
+@@ -152,11 +200,14 @@ struct tty_operations {
+ void (*send_xchar)(struct tty_struct *tty, char ch);
+ int (*read_proc)(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+- int (*write_proc)(struct file *file, const char __user *buffer,
+- unsigned long count, void *data);
int (*tiocmget)(struct tty_struct *tty, struct file *file);
int (*tiocmset)(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
@@ -821887,19 +1101853,55 @@
};
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
+@@ -184,43 +235,13 @@ struct tty_driver {
+ struct tty_struct **ttys;
+ struct ktermios **termios;
+ struct ktermios **termios_locked;
+- void *driver_state; /* only used for the PTY driver */
+-
++ void *driver_state;
++
+ /*
+- * Interface routines from the upper tty layer to the tty
+- * driver. Will be replaced with struct tty_operations.
++ * Driver methods
+ */
+- int (*open)(struct tty_struct * tty, struct file * filp);
+- void (*close)(struct tty_struct * tty, struct file * filp);
+- int (*write)(struct tty_struct * tty,
+- const unsigned char *buf, int count);
+- void (*put_char)(struct tty_struct *tty, unsigned char ch);
+- void (*flush_chars)(struct tty_struct *tty);
+- int (*write_room)(struct tty_struct *tty);
+- int (*chars_in_buffer)(struct tty_struct *tty);
+- int (*ioctl)(struct tty_struct *tty, struct file * file,
+- unsigned int cmd, unsigned long arg);
+- long (*compat_ioctl)(struct tty_struct *tty, struct file * file,
+- unsigned int cmd, unsigned long arg);
+- void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
+- void (*throttle)(struct tty_struct * tty);
+- void (*unthrottle)(struct tty_struct * tty);
+- void (*stop)(struct tty_struct *tty);
+- void (*start)(struct tty_struct *tty);
+- void (*hangup)(struct tty_struct *tty);
+- void (*break_ctl)(struct tty_struct *tty, int state);
+- void (*flush_buffer)(struct tty_struct *tty);
+- void (*set_ldisc)(struct tty_struct *tty);
+- void (*wait_until_sent)(struct tty_struct *tty, int timeout);
+- void (*send_xchar)(struct tty_struct *tty, char ch);
+- int (*read_proc)(char *page, char **start, off_t off,
+- int count, int *eof, void *data);
+- int (*write_proc)(struct file *file, const char __user *buffer,
+- unsigned long count, void *data);
+- int (*tiocmget)(struct tty_struct *tty, struct file *file);
+- int (*tiocmset)(struct tty_struct *tty, struct file *file,
+- unsigned int set, unsigned int clear);
++ const struct tty_operations *ops;
struct list_head tty_drivers;
};
-@@ -230,6 +241,7 @@ struct tty_driver *alloc_tty_driver(int lines);
+
+@@ -230,6 +251,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);
@@ -821926,289 +1101928,859 @@
+ */
+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);
++/*
++ * probe_kernel_write(): safely attempt to write to a location
++ * @dst: address to write to
++ * @src: pointer to the data that shall be written
++ * @size: size of the data chunk
++ *
++ * Safely write to address @dst from the buffer at @src. If a kernel fault
++ * happens, handle that and return -EFAULT.
++ */
++extern long probe_kernel_write(void *dst, void *src, size_t size);
++
+ #endif /* __LINUX_UACCESS_H__ */
+diff --git a/include/linux/udf_fs.h b/include/linux/udf_fs.h
+deleted file mode 100644
+index aa88654..0000000
+--- a/include/linux/udf_fs.h
++++ /dev/null
+@@ -1,51 +0,0 @@
+-/*
+- * udf_fs.h
+- *
+- * PURPOSE
+- * Included by fs/filesystems.c
+- *
+- * DESCRIPTION
+- * OSTA-UDF(tm) = Optical Storage Technology Association
+- * Universal Disk Format.
+- *
+- * This code is based on version 2.50 of the UDF specification,
+- * and revision 3 of the ECMA 167 standard [equivalent to ISO 13346].
+- * http://www.osta.org/ * http://www.ecma.ch/
+- * http://www.iso.org/
+- *
+- * COPYRIGHT
+- * This file is distributed under the terms of the GNU General Public
+- * License (GPL). Copies of the GPL can be obtained from:
+- * ftp://prep.ai.mit.edu/pub/gnu/GPL
+- * Each contributing author retains all rights to their own work.
+- *
+- * (C) 1999-2004 Ben Fennema
+- * (C) 1999-2000 Stelias Computing Inc
+- *
+- * HISTORY
+- *
+- */
+-
+-#ifndef _UDF_FS_H
+-#define _UDF_FS_H 1
+-
+-#define UDF_PREALLOCATE
+-#define UDF_DEFAULT_PREALLOC_BLOCKS 8
+-
+-#undef UDFFS_DEBUG
+-
+-#ifdef UDFFS_DEBUG
+-#define udf_debug(f, a...) \
+- do { \
+- printk (KERN_DEBUG "UDF-fs DEBUG %s:%d:%s: ", \
+- __FILE__, __LINE__, __FUNCTION__); \
+- printk (f, ##a); \
+- } while (0)
+-#else
+-#define udf_debug(f, a...) /**/
+-#endif
+-
+-#define udf_info(f, a...) \
+- printk (KERN_INFO "UDF-fs INFO " f, ##a);
+-
+-#endif /* _UDF_FS_H */
+diff --git a/include/linux/udf_fs_i.h b/include/linux/udf_fs_i.h
+index ffaf056..3536965 100644
+--- a/include/linux/udf_fs_i.h
++++ b/include/linux/udf_fs_i.h
+@@ -9,41 +9,10 @@
+ * ftp://prep.ai.mit.edu/pub/gnu/GPL
+ * Each contributing author retains all rights to their own work.
+ */
+-
+ #ifndef _UDF_FS_I_H
+ #define _UDF_FS_I_H 1
+
+-#ifdef __KERNEL__
+-
+-struct udf_inode_info
+-{
+- struct timespec i_crtime;
+- /* Physical address of inode */
+- kernel_lb_addr i_location;
+- __u64 i_unique;
+- __u32 i_lenEAttr;
+- __u32 i_lenAlloc;
+- __u64 i_lenExtents;
+- __u32 i_next_alloc_block;
+- __u32 i_next_alloc_goal;
+- unsigned i_alloc_type : 3;
+- unsigned i_efe : 1;
+- unsigned i_use : 1;
+- unsigned i_strat4096 : 1;
+- unsigned reserved : 26;
+- union
+- {
+- short_ad *i_sad;
+- long_ad *i_lad;
+- __u8 *i_data;
+- } i_ext;
+- struct inode vfs_inode;
+-};
+-
+-#endif
+-
+ /* exported IOCTLs, we have 'l', 0x40-0x7f */
+-
+ #define UDF_GETEASIZE _IOR('l', 0x40, int)
+ #define UDF_GETEABLOCK _IOR('l', 0x41, void *)
+ #define UDF_GETVOLIDENT _IOR('l', 0x42, void *)
+diff --git a/include/linux/udf_fs_sb.h b/include/linux/udf_fs_sb.h
+deleted file mode 100644
+index 9bc4735..0000000
+--- a/include/linux/udf_fs_sb.h
++++ /dev/null
+@@ -1,117 +0,0 @@
+-/*
+- * udf_fs_sb.h
+- *
+- * This include file is for the Linux kernel/module.
+- *
+- * COPYRIGHT
+- * This file is distributed under the terms of the GNU General Public
+- * License (GPL). Copies of the GPL can be obtained from:
+- * ftp://prep.ai.mit.edu/pub/gnu/GPL
+- * Each contributing author retains all rights to their own work.
+- */
+-
+-#ifndef _UDF_FS_SB_H
+-#define _UDF_FS_SB_H 1
+-
+-#include <linux/mutex.h>
+-
+-#pragma pack(1)
+-
+-#define UDF_MAX_BLOCK_LOADED 8
+-
+-#define UDF_TYPE1_MAP15 0x1511U
+-#define UDF_VIRTUAL_MAP15 0x1512U
+-#define UDF_VIRTUAL_MAP20 0x2012U
+-#define UDF_SPARABLE_MAP15 0x1522U
+-
+-struct udf_sparing_data
+-{
+- __u16 s_packet_len;
+- struct buffer_head *s_spar_map[4];
+-};
+-
+-struct udf_virtual_data
+-{
+- __u32 s_num_entries;
+- __u16 s_start_offset;
+-};
+-
+-struct udf_bitmap
+-{
+- __u32 s_extLength;
+- __u32 s_extPosition;
+- __u16 s_nr_groups;
+- struct buffer_head **s_block_bitmap;
+-};
+-
+-struct udf_part_map
+-{
+- union
+- {
+- struct udf_bitmap *s_bitmap;
+- struct inode *s_table;
+- } s_uspace;
+- union
+- {
+- struct udf_bitmap *s_bitmap;
+- struct inode *s_table;
+- } s_fspace;
+- __u32 s_partition_root;
+- __u32 s_partition_len;
+- __u16 s_partition_type;
+- __u16 s_partition_num;
+- union
+- {
+- struct udf_sparing_data s_sparing;
+- struct udf_virtual_data s_virtual;
+- } s_type_specific;
+- __u32 (*s_partition_func)(struct super_block *, __u32, __u16, __u32);
+- __u16 s_volumeseqnum;
+- __u16 s_partition_flags;
+-};
+-
+-#pragma pack()
+-
+-struct udf_sb_info
+-{
+- struct udf_part_map *s_partmaps;
+- __u8 s_volume_ident[32];
+-
+- /* Overall info */
+- __u16 s_partitions;
+- __u16 s_partition;
+-
+- /* Sector headers */
+- __s32 s_session;
+- __u32 s_anchor[4];
+- __u32 s_last_block;
+-
+- struct buffer_head *s_lvid_bh;
+-
+- /* Default permissions */
+- mode_t s_umask;
+- gid_t s_gid;
+- uid_t s_uid;
+-
+- /* Root Info */
+- struct timespec s_record_time;
+-
+- /* Fileset Info */
+- __u16 s_serial_number;
+-
+- /* highest UDF revision we have recorded to this media */
+- __u16 s_udfrev;
+-
+- /* Miscellaneous flags */
+- __u32 s_flags;
+-
+- /* Encoding info */
+- struct nls_table *s_nls_map;
+-
+- /* VAT inode */
+- struct inode *s_vat_inode;
+-
+- struct mutex s_alloc_mutex;
+-};
+-
+-#endif /* _UDF_FS_SB_H */
+diff --git a/include/linux/udp.h b/include/linux/udp.h
+index 8ec703f..581ca2c 100644
+--- a/include/linux/udp.h
++++ b/include/linux/udp.h
+@@ -26,15 +26,6 @@ struct udphdr {
+ __sum16 check;
+ };
+
+-#ifdef __KERNEL__
+-#include <linux/skbuff.h>
+-
+-static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
+-{
+- return (struct udphdr *)skb_transport_header(skb);
+-}
+-#endif
+-
+ /* UDP socket options */
+ #define UDP_CORK 1 /* Never send partially complete segments */
+ #define UDP_ENCAP 100 /* Set the socket to accept encapsulated packets */
+@@ -45,9 +36,14 @@ static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
+ #define UDP_ENCAP_L2TPINUDP 3 /* rfc2661 */
+
+ #ifdef __KERNEL__
+-#include <linux/types.h>
+-
+ #include <net/inet_sock.h>
++#include <linux/skbuff.h>
++
++static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
++{
++ return (struct udphdr *)skb_transport_header(skb);
++}
++
+ #define UDP_HTABLE_SIZE 128
+
+ struct udp_sock {
+@@ -82,6 +78,7 @@ static inline struct udp_sock *udp_sk(const struct sock *sk)
+ {
+ return (struct udp_sock *)sk;
+ }
++
+ #define IS_UDPLITE(__sk) (udp_sk(__sk)->pcflag)
+
+ #endif
+diff --git a/include/linux/unaligned/access_ok.h b/include/linux/unaligned/access_ok.h
+new file mode 100644
+index 0000000..99c1b4d
+--- /dev/null
++++ b/include/linux/unaligned/access_ok.h
+@@ -0,0 +1,67 @@
++#ifndef _LINUX_UNALIGNED_ACCESS_OK_H
++#define _LINUX_UNALIGNED_ACCESS_OK_H
++
++#include <linux/kernel.h>
++#include <asm/byteorder.h>
++
++static inline u16 get_unaligned_le16(const void *p)
++{
++ return le16_to_cpup((__le16 *)p);
++}
++
++static inline u32 get_unaligned_le32(const void *p)
++{
++ return le32_to_cpup((__le32 *)p);
++}
++
++static inline u64 get_unaligned_le64(const void *p)
++{
++ return le64_to_cpup((__le64 *)p);
++}
++
++static inline u16 get_unaligned_be16(const void *p)
++{
++ return be16_to_cpup((__be16 *)p);
++}
++
++static inline u32 get_unaligned_be32(const void *p)
++{
++ return be32_to_cpup((__be32 *)p);
++}
++
++static inline u64 get_unaligned_be64(const void *p)
++{
++ return be64_to_cpup((__be64 *)p);
++}
++
++static inline void put_unaligned_le16(u16 val, void *p)
++{
++ *((__le16 *)p) = cpu_to_le16(val);
++}
++
++static inline void put_unaligned_le32(u32 val, void *p)
++{
++ *((__le32 *)p) = cpu_to_le32(val);
++}
++
++static inline void put_unaligned_le64(u64 val, void *p)
++{
++ *((__le64 *)p) = cpu_to_le64(val);
++}
++
++static inline void put_unaligned_be16(u16 val, void *p)
++{
++ *((__be16 *)p) = cpu_to_be16(val);
++}
++
++static inline void put_unaligned_be32(u32 val, void *p)
++{
++ *((__be32 *)p) = cpu_to_be32(val);
++}
++
++static inline void put_unaligned_be64(u64 val, void *p)
++{
++ *((__be64 *)p) = cpu_to_be64(val);
++}
++
++#endif /* _LINUX_UNALIGNED_ACCESS_OK_H */
+diff --git a/include/linux/unaligned/be_byteshift.h b/include/linux/unaligned/be_byteshift.h
+new file mode 100644
+index 0000000..46dd12c
+--- /dev/null
++++ b/include/linux/unaligned/be_byteshift.h
+@@ -0,0 +1,70 @@
++#ifndef _LINUX_UNALIGNED_BE_BYTESHIFT_H
++#define _LINUX_UNALIGNED_BE_BYTESHIFT_H
++
++#include <linux/kernel.h>
++
++static inline u16 __get_unaligned_be16(const u8 *p)
++{
++ return p[0] << 8 | p[1];
++}
++
++static inline u32 __get_unaligned_be32(const u8 *p)
++{
++ return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
++}
++
++static inline u64 __get_unaligned_be64(const u8 *p)
++{
++ return (u64)__get_unaligned_be32(p) << 32 |
++ __get_unaligned_be32(p + 4);
++}
++
++static inline void __put_unaligned_be16(u16 val, u8 *p)
++{
++ *p++ = val >> 8;
++ *p++ = val;
++}
++
++static inline void __put_unaligned_be32(u32 val, u8 *p)
++{
++ __put_unaligned_be16(val >> 16, p);
++ __put_unaligned_be16(val, p + 2);
++}
++
++static inline void __put_unaligned_be64(u64 val, u8 *p)
++{
++ __put_unaligned_be32(val >> 32, p);
++ __put_unaligned_be32(val, p + 4);
++}
++
++static inline u16 get_unaligned_be16(const void *p)
++{
++ return __get_unaligned_be16((const u8 *)p);
++}
++
++static inline u32 get_unaligned_be32(const void *p)
++{
++ return __get_unaligned_be32((const u8 *)p);
++}
++
++static inline u64 get_unaligned_be64(const void *p)
++{
++ return __get_unaligned_be64((const u8 *)p);
++}
++
++static inline void put_unaligned_be16(u16 val, void *p)
++{
++ __put_unaligned_be16(val, p);
++}
++
++static inline void put_unaligned_be32(u32 val, void *p)
++{
++ __put_unaligned_be32(val, p);
++}
++
++static inline void put_unaligned_be64(u64 val, void *p)
++{
++ __put_unaligned_be64(val, p);
++}
++
++#endif /* _LINUX_UNALIGNED_BE_BYTESHIFT_H */
+diff --git a/include/linux/unaligned/be_memmove.h b/include/linux/unaligned/be_memmove.h
+new file mode 100644
+index 0000000..c2a76c5
+--- /dev/null
++++ b/include/linux/unaligned/be_memmove.h
+@@ -0,0 +1,36 @@
++#ifndef _LINUX_UNALIGNED_BE_MEMMOVE_H
++#define _LINUX_UNALIGNED_BE_MEMMOVE_H
++
++#include <linux/unaligned/memmove.h>
++
++static inline u16 get_unaligned_be16(const void *p)
++{
++ return __get_unaligned_memmove16((const u8 *)p);
++}
++
++static inline u32 get_unaligned_be32(const void *p)
++{
++ return __get_unaligned_memmove32((const u8 *)p);
++}
++
++static inline u64 get_unaligned_be64(const void *p)
++{
++ return __get_unaligned_memmove64((const u8 *)p);
++}
++
++static inline void put_unaligned_be16(u16 val, void *p)
++{
++ __put_unaligned_memmove16(val, p);
++}
++
++static inline void put_unaligned_be32(u32 val, void *p)
++{
++ __put_unaligned_memmove32(val, p);
++}
++
++static inline void put_unaligned_be64(u64 val, void *p)
++{
++ __put_unaligned_memmove64(val, p);
++}
++
++#endif /* _LINUX_UNALIGNED_LE_MEMMOVE_H */
+diff --git a/include/linux/unaligned/be_struct.h b/include/linux/unaligned/be_struct.h
+new file mode 100644
+index 0000000..1324158
+--- /dev/null
++++ b/include/linux/unaligned/be_struct.h
+@@ -0,0 +1,36 @@
++#ifndef _LINUX_UNALIGNED_BE_STRUCT_H
++#define _LINUX_UNALIGNED_BE_STRUCT_H
++
++#include <linux/unaligned/packed_struct.h>
++
++static inline u16 get_unaligned_be16(const void *p)
++{
++ return __get_unaligned_cpu16((const u8 *)p);
++}
++
++static inline u32 get_unaligned_be32(const void *p)
++{
++ return __get_unaligned_cpu32((const u8 *)p);
++}
++
++static inline u64 get_unaligned_be64(const void *p)
++{
++ return __get_unaligned_cpu64((const u8 *)p);
++}
++
++static inline void put_unaligned_be16(u16 val, void *p)
++{
++ __put_unaligned_cpu16(val, p);
++}
++
++static inline void put_unaligned_be32(u32 val, void *p)
++{
++ __put_unaligned_cpu32(val, p);
++}
++
++static inline void put_unaligned_be64(u64 val, void *p)
++{
++ __put_unaligned_cpu64(val, p);
++}
++
++#endif /* _LINUX_UNALIGNED_BE_STRUCT_H */
+diff --git a/include/linux/unaligned/generic.h b/include/linux/unaligned/generic.h
+new file mode 100644
+index 0000000..02d97ff
+--- /dev/null
++++ b/include/linux/unaligned/generic.h
+@@ -0,0 +1,68 @@
++#ifndef _LINUX_UNALIGNED_GENERIC_H
++#define _LINUX_UNALIGNED_GENERIC_H
++
++/*
++ * Cause a link-time error if we try an unaligned access other than
++ * 1,2,4 or 8 bytes long
++ */
++extern void __bad_unaligned_access_size(void);
++
++#define __get_unaligned_le(ptr) ((__force typeof(*(ptr)))({ \
++ __builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr), \
++ __builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_le16((ptr)), \
++ __builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_le32((ptr)), \
++ __builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_le64((ptr)), \
++ __bad_unaligned_access_size())))); \
++ }))
++
++#define __get_unaligned_be(ptr) ((__force typeof(*(ptr)))({ \
++ __builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr), \
++ __builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_be16((ptr)), \
++ __builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_be32((ptr)), \
++ __builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_be64((ptr)), \
++ __bad_unaligned_access_size())))); \
++ }))
++
++#define __put_unaligned_le(val, ptr) ({ \
++ void *__gu_p = (ptr); \
++ switch (sizeof(*(ptr))) { \
++ case 1: \
++ *(u8 *)__gu_p = (__force u8)(val); \
++ break; \
++ case 2: \
++ put_unaligned_le16((__force u16)(val), __gu_p); \
++ break; \
++ case 4: \
++ put_unaligned_le32((__force u32)(val), __gu_p); \
++ break; \
++ case 8: \
++ put_unaligned_le64((__force u64)(val), __gu_p); \
++ break; \
++ default: \
++ __bad_unaligned_access_size(); \
++ break; \
++ } \
++ (void)0; })
++
++#define __put_unaligned_be(val, ptr) ({ \
++ void *__gu_p = (ptr); \
++ switch (sizeof(*(ptr))) { \
++ case 1: \
++ *(u8 *)__gu_p = (__force u8)(val); \
++ break; \
++ case 2: \
++ put_unaligned_be16((__force u16)(val), __gu_p); \
++ break; \
++ case 4: \
++ put_unaligned_be32((__force u32)(val), __gu_p); \
++ break; \
++ case 8: \
++ put_unaligned_be64((__force u64)(val), __gu_p); \
++ break; \
++ default: \
++ __bad_unaligned_access_size(); \
++ break; \
++ } \
++ (void)0; })
++
++#endif /* _LINUX_UNALIGNED_GENERIC_H */
+diff --git a/include/linux/unaligned/le_byteshift.h b/include/linux/unaligned/le_byteshift.h
+new file mode 100644
+index 0000000..59777e9
+--- /dev/null
++++ b/include/linux/unaligned/le_byteshift.h
+@@ -0,0 +1,70 @@
++#ifndef _LINUX_UNALIGNED_LE_BYTESHIFT_H
++#define _LINUX_UNALIGNED_LE_BYTESHIFT_H
++
++#include <linux/kernel.h>
++
++static inline u16 __get_unaligned_le16(const u8 *p)
++{
++ return p[0] | p[1] << 8;
++}
++
++static inline u32 __get_unaligned_le32(const u8 *p)
++{
++ return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
++}
++
++static inline u64 __get_unaligned_le64(const u8 *p)
++{
++ return (u64)__get_unaligned_le32(p + 4) << 32 |
++ __get_unaligned_le32(p);
++}
++
++static inline void __put_unaligned_le16(u16 val, u8 *p)
++{
++ *p++ = val;
++ *p++ = val >> 8;
++}
++
++static inline void __put_unaligned_le32(u32 val, u8 *p)
++{
++ __put_unaligned_le16(val >> 16, p + 2);
++ __put_unaligned_le16(val, p);
++}
++
++static inline void __put_unaligned_le64(u64 val, u8 *p)
++{
++ __put_unaligned_le32(val >> 32, p + 4);
++ __put_unaligned_le32(val, p);
++}
++
++static inline u16 get_unaligned_le16(const void *p)
++{
++ return __get_unaligned_le16((const u8 *)p);
++}
++
++static inline u32 get_unaligned_le32(const void *p)
++{
++ return __get_unaligned_le32((const u8 *)p);
++}
++
++static inline u64 get_unaligned_le64(const void *p)
++{
++ return __get_unaligned_le64((const u8 *)p);
++}
++
++static inline void put_unaligned_le16(u16 val, void *p)
++{
++ __put_unaligned_le16(val, p);
++}
++
++static inline void put_unaligned_le32(u32 val, void *p)
++{
++ __put_unaligned_le32(val, p);
++}
++
++static inline void put_unaligned_le64(u64 val, void *p)
++{
++ __put_unaligned_le64(val, p);
++}
++
++#endif /* _LINUX_UNALIGNED_LE_BYTESHIFT_H */
+diff --git a/include/linux/unaligned/le_memmove.h b/include/linux/unaligned/le_memmove.h
+new file mode 100644
+index 0000000..269849b
+--- /dev/null
++++ b/include/linux/unaligned/le_memmove.h
+@@ -0,0 +1,36 @@
++#ifndef _LINUX_UNALIGNED_LE_MEMMOVE_H
++#define _LINUX_UNALIGNED_LE_MEMMOVE_H
++
++#include <linux/unaligned/memmove.h>
++
++static inline u16 get_unaligned_le16(const void *p)
++{
++ return __get_unaligned_memmove16((const u8 *)p);
++}
++
++static inline u32 get_unaligned_le32(const void *p)
++{
++ return __get_unaligned_memmove32((const u8 *)p);
++}
++
++static inline u64 get_unaligned_le64(const void *p)
++{
++ return __get_unaligned_memmove64((const u8 *)p);
++}
++
++static inline void put_unaligned_le16(u16 val, void *p)
++{
++ __put_unaligned_memmove16(val, p);
++}
++
++static inline void put_unaligned_le32(u32 val, void *p)
++{
++ __put_unaligned_memmove32(val, p);
++}
++
++static inline void put_unaligned_le64(u64 val, void *p)
++{
++ __put_unaligned_memmove64(val, p);
++}
++
++#endif /* _LINUX_UNALIGNED_LE_MEMMOVE_H */
+diff --git a/include/linux/unaligned/le_struct.h b/include/linux/unaligned/le_struct.h
+new file mode 100644
+index 0000000..088c457
+--- /dev/null
++++ b/include/linux/unaligned/le_struct.h
+@@ -0,0 +1,36 @@
++#ifndef _LINUX_UNALIGNED_LE_STRUCT_H
++#define _LINUX_UNALIGNED_LE_STRUCT_H
++
++#include <linux/unaligned/packed_struct.h>
++
++static inline u16 get_unaligned_le16(const void *p)
++{
++ return __get_unaligned_cpu16((const u8 *)p);
++}
++
++static inline u32 get_unaligned_le32(const void *p)
++{
++ return __get_unaligned_cpu32((const u8 *)p);
++}
++
++static inline u64 get_unaligned_le64(const void *p)
++{
++ return __get_unaligned_cpu64((const u8 *)p);
++}
++
++static inline void put_unaligned_le16(u16 val, void *p)
++{
++ __put_unaligned_cpu16(val, p);
++}
++
++static inline void put_unaligned_le32(u32 val, void *p)
++{
++ __put_unaligned_cpu32(val, p);
++}
++
++static inline void put_unaligned_le64(u64 val, void *p)
++{
++ __put_unaligned_cpu64(val, p);
++}
++
++#endif /* _LINUX_UNALIGNED_LE_STRUCT_H */
+diff --git a/include/linux/unaligned/memmove.h b/include/linux/unaligned/memmove.h
+new file mode 100644
+index 0000000..eeb5a77
+--- /dev/null
++++ b/include/linux/unaligned/memmove.h
+@@ -0,0 +1,45 @@
++#ifndef _LINUX_UNALIGNED_MEMMOVE_H
++#define _LINUX_UNALIGNED_MEMMOVE_H
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++
++/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
++
++static inline u16 __get_unaligned_memmove16(const void *p)
++{
++ u16 tmp;
++ memmove(&tmp, p, 2);
++ return tmp;
++}
++
++static inline u32 __get_unaligned_memmove32(const void *p)
++{
++ u32 tmp;
++ memmove(&tmp, p, 4);
++ return tmp;
++}
++
++static inline u64 __get_unaligned_memmove64(const void *p)
++{
++ u64 tmp;
++ memmove(&tmp, p, 8);
++ return tmp;
++}
++
++static inline void __put_unaligned_memmove16(u16 val, void *p)
++{
++ memmove(p, &val, 2);
++}
++
++static inline void __put_unaligned_memmove32(u32 val, void *p)
++{
++ memmove(p, &val, 4);
++}
++
++static inline void __put_unaligned_memmove64(u64 val, void *p)
++{
++ memmove(p, &val, 8);
++}
++
++#endif /* _LINUX_UNALIGNED_MEMMOVE_H */
+diff --git a/include/linux/unaligned/packed_struct.h b/include/linux/unaligned/packed_struct.h
+new file mode 100644
+index 0000000..2498bb9
+--- /dev/null
++++ b/include/linux/unaligned/packed_struct.h
+@@ -0,0 +1,46 @@
++#ifndef _LINUX_UNALIGNED_PACKED_STRUCT_H
++#define _LINUX_UNALIGNED_PACKED_STRUCT_H
++
++#include <linux/kernel.h>
+
- #endif /* __LINUX_UACCESS_H__ */
-diff --git a/include/linux/udf_fs.h b/include/linux/udf_fs.h
-deleted file mode 100644
-index aa88654..0000000
---- a/include/linux/udf_fs.h
-+++ /dev/null
-@@ -1,51 +0,0 @@
--/*
-- * udf_fs.h
-- *
-- * PURPOSE
-- * Included by fs/filesystems.c
-- *
-- * DESCRIPTION
-- * OSTA-UDF(tm) = Optical Storage Technology Association
-- * Universal Disk Format.
-- *
-- * This code is based on version 2.50 of the UDF specification,
-- * and revision 3 of the ECMA 167 standard [equivalent to ISO 13346].
-- * http://www.osta.org/ * http://www.ecma.ch/
-- * http://www.iso.org/
-- *
-- * COPYRIGHT
-- * This file is distributed under the terms of the GNU General Public
-- * License (GPL). Copies of the GPL can be obtained from:
-- * ftp://prep.ai.mit.edu/pub/gnu/GPL
-- * Each contributing author retains all rights to their own work.
-- *
-- * (C) 1999-2004 Ben Fennema
-- * (C) 1999-2000 Stelias Computing Inc
-- *
-- * HISTORY
-- *
-- */
--
--#ifndef _UDF_FS_H
--#define _UDF_FS_H 1
--
--#define UDF_PREALLOCATE
--#define UDF_DEFAULT_PREALLOC_BLOCKS 8
--
--#undef UDFFS_DEBUG
--
--#ifdef UDFFS_DEBUG
--#define udf_debug(f, a...) \
-- do { \
-- printk (KERN_DEBUG "UDF-fs DEBUG %s:%d:%s: ", \
-- __FILE__, __LINE__, __FUNCTION__); \
-- printk (f, ##a); \
-- } while (0)
--#else
--#define udf_debug(f, a...) /**/
--#endif
--
--#define udf_info(f, a...) \
-- printk (KERN_INFO "UDF-fs INFO " f, ##a);
--
--#endif /* _UDF_FS_H */
-diff --git a/include/linux/udf_fs_i.h b/include/linux/udf_fs_i.h
-index ffaf056..3536965 100644
---- a/include/linux/udf_fs_i.h
-+++ b/include/linux/udf_fs_i.h
-@@ -9,41 +9,10 @@
- * ftp://prep.ai.mit.edu/pub/gnu/GPL
- * Each contributing author retains all rights to their own work.
- */
--
- #ifndef _UDF_FS_I_H
- #define _UDF_FS_I_H 1
-
--#ifdef __KERNEL__
--
--struct udf_inode_info
--{
-- struct timespec i_crtime;
-- /* Physical address of inode */
-- kernel_lb_addr i_location;
-- __u64 i_unique;
-- __u32 i_lenEAttr;
-- __u32 i_lenAlloc;
-- __u64 i_lenExtents;
-- __u32 i_next_alloc_block;
-- __u32 i_next_alloc_goal;
-- unsigned i_alloc_type : 3;
-- unsigned i_efe : 1;
-- unsigned i_use : 1;
-- unsigned i_strat4096 : 1;
-- unsigned reserved : 26;
-- union
-- {
-- short_ad *i_sad;
-- long_ad *i_lad;
-- __u8 *i_data;
-- } i_ext;
-- struct inode vfs_inode;
--};
--
--#endif
--
- /* exported IOCTLs, we have 'l', 0x40-0x7f */
--
- #define UDF_GETEASIZE _IOR('l', 0x40, int)
- #define UDF_GETEABLOCK _IOR('l', 0x41, void *)
- #define UDF_GETVOLIDENT _IOR('l', 0x42, void *)
-diff --git a/include/linux/udf_fs_sb.h b/include/linux/udf_fs_sb.h
-deleted file mode 100644
-index 9bc4735..0000000
---- a/include/linux/udf_fs_sb.h
-+++ /dev/null
-@@ -1,117 +0,0 @@
--/*
-- * udf_fs_sb.h
-- *
-- * This include file is for the Linux kernel/module.
-- *
-- * COPYRIGHT
-- * This file is distributed under the terms of the GNU General Public
-- * License (GPL). Copies of the GPL can be obtained from:
-- * ftp://prep.ai.mit.edu/pub/gnu/GPL
-- * Each contributing author retains all rights to their own work.
-- */
--
--#ifndef _UDF_FS_SB_H
--#define _UDF_FS_SB_H 1
--
--#include <linux/mutex.h>
--
--#pragma pack(1)
--
--#define UDF_MAX_BLOCK_LOADED 8
--
--#define UDF_TYPE1_MAP15 0x1511U
--#define UDF_VIRTUAL_MAP15 0x1512U
--#define UDF_VIRTUAL_MAP20 0x2012U
--#define UDF_SPARABLE_MAP15 0x1522U
--
--struct udf_sparing_data
--{
-- __u16 s_packet_len;
-- struct buffer_head *s_spar_map[4];
--};
--
--struct udf_virtual_data
--{
-- __u32 s_num_entries;
-- __u16 s_start_offset;
--};
--
--struct udf_bitmap
--{
-- __u32 s_extLength;
-- __u32 s_extPosition;
-- __u16 s_nr_groups;
-- struct buffer_head **s_block_bitmap;
--};
--
--struct udf_part_map
--{
-- union
-- {
-- struct udf_bitmap *s_bitmap;
-- struct inode *s_table;
-- } s_uspace;
-- union
-- {
-- struct udf_bitmap *s_bitmap;
-- struct inode *s_table;
-- } s_fspace;
-- __u32 s_partition_root;
-- __u32 s_partition_len;
-- __u16 s_partition_type;
-- __u16 s_partition_num;
-- union
-- {
-- struct udf_sparing_data s_sparing;
-- struct udf_virtual_data s_virtual;
-- } s_type_specific;
-- __u32 (*s_partition_func)(struct super_block *, __u32, __u16, __u32);
-- __u16 s_volumeseqnum;
-- __u16 s_partition_flags;
--};
--
--#pragma pack()
--
--struct udf_sb_info
--{
-- struct udf_part_map *s_partmaps;
-- __u8 s_volume_ident[32];
--
-- /* Overall info */
-- __u16 s_partitions;
-- __u16 s_partition;
--
-- /* Sector headers */
-- __s32 s_session;
-- __u32 s_anchor[4];
-- __u32 s_last_block;
--
-- struct buffer_head *s_lvid_bh;
--
-- /* Default permissions */
-- mode_t s_umask;
-- gid_t s_gid;
-- uid_t s_uid;
--
-- /* Root Info */
-- struct timespec s_record_time;
--
-- /* Fileset Info */
-- __u16 s_serial_number;
--
-- /* highest UDF revision we have recorded to this media */
-- __u16 s_udfrev;
--
-- /* Miscellaneous flags */
-- __u32 s_flags;
--
-- /* Encoding info */
-- struct nls_table *s_nls_map;
--
-- /* VAT inode */
-- struct inode *s_vat_inode;
--
-- struct mutex s_alloc_mutex;
--};
--
--#endif /* _UDF_FS_SB_H */
-diff --git a/include/linux/udp.h b/include/linux/udp.h
-index 8ec703f..581ca2c 100644
---- a/include/linux/udp.h
-+++ b/include/linux/udp.h
-@@ -26,15 +26,6 @@ struct udphdr {
- __sum16 check;
- };
-
--#ifdef __KERNEL__
--#include <linux/skbuff.h>
--
--static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
--{
-- return (struct udphdr *)skb_transport_header(skb);
--}
--#endif
--
- /* UDP socket options */
- #define UDP_CORK 1 /* Never send partially complete segments */
- #define UDP_ENCAP 100 /* Set the socket to accept encapsulated packets */
-@@ -45,9 +36,14 @@ static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
- #define UDP_ENCAP_L2TPINUDP 3 /* rfc2661 */
-
- #ifdef __KERNEL__
--#include <linux/types.h>
--
- #include <net/inet_sock.h>
-+#include <linux/skbuff.h>
++struct __una_u16 { u16 x __attribute__((packed)); };
++struct __una_u32 { u32 x __attribute__((packed)); };
++struct __una_u64 { u64 x __attribute__((packed)); };
+
-+static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
++static inline u16 __get_unaligned_cpu16(const void *p)
+{
-+ return (struct udphdr *)skb_transport_header(skb);
++ const struct __una_u16 *ptr = (const struct __una_u16 *)p;
++ return ptr->x;
+}
+
- #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;
- }
++static inline u32 __get_unaligned_cpu32(const void *p)
++{
++ const struct __una_u32 *ptr = (const struct __una_u32 *)p;
++ return ptr->x;
++}
+
- #define IS_UDPLITE(__sk) (udp_sk(__sk)->pcflag)
-
- #endif
++static inline u64 __get_unaligned_cpu64(const void *p)
++{
++ const struct __una_u64 *ptr = (const struct __una_u64 *)p;
++ return ptr->x;
++}
++
++static inline void __put_unaligned_cpu16(u16 val, void *p)
++{
++ struct __una_u16 *ptr = (struct __una_u16 *)p;
++ ptr->x = val;
++}
++
++static inline void __put_unaligned_cpu32(u32 val, void *p)
++{
++ struct __una_u32 *ptr = (struct __una_u32 *)p;
++ ptr->x = val;
++}
++
++static inline void __put_unaligned_cpu64(u64 val, void *p)
++{
++ struct __una_u64 *ptr = (struct __una_u64 *)p;
++ ptr->x = val;
++}
++
++#endif /* _LINUX_UNALIGNED_PACKED_STRUCT_H */
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 583e048..c08689e 100644
--- a/include/linux/usb.h
@@ -823066,6 +1103638,65 @@
/*
* T U N I N G
*/
+diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
+index ce8e7da..364789a 100644
+--- a/include/linux/vmalloc.h
++++ b/include/linux/vmalloc.h
+@@ -31,6 +31,7 @@ struct vm_struct {
+ struct page **pages;
+ unsigned int nr_pages;
+ unsigned long phys_addr;
++ void *caller;
+ };
+
+ /*
+@@ -66,6 +67,8 @@ static inline size_t get_vm_area_size(const struct vm_struct *area)
+ }
+
+ extern struct vm_struct *get_vm_area(unsigned long size, unsigned long flags);
++extern struct vm_struct *get_vm_area_caller(unsigned long size,
++ unsigned long flags, void *caller);
+ extern struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
+ unsigned long start, unsigned long end);
+ extern struct vm_struct *get_vm_area_node(unsigned long size,
+@@ -87,4 +90,6 @@ extern void free_vm_area(struct vm_struct *area);
+ extern rwlock_t vmlist_lock;
+ extern struct vm_struct *vmlist;
+
++extern const struct seq_operations vmalloc_op;
++
+ #endif /* _LINUX_VMALLOC_H */
+diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
+index 9f1b4b4..e83b693 100644
+--- a/include/linux/vmstat.h
++++ b/include/linux/vmstat.h
+@@ -25,6 +25,7 @@
+ #define HIGHMEM_ZONE(xx)
+ #endif
+
++
+ #define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL HIGHMEM_ZONE(xx) , xx##_MOVABLE
+
+ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
+@@ -37,6 +38,9 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
+ FOR_ALL_ZONES(PGSCAN_DIRECT),
+ PGINODESTEAL, SLABS_SCANNED, KSWAPD_STEAL, KSWAPD_INODESTEAL,
+ PAGEOUTRUN, ALLOCSTALL, PGROTATED,
++#ifdef CONFIG_HUGETLB_PAGE
++ HTLB_BUDDY_PGALLOC, HTLB_BUDDY_PGALLOC_FAIL,
++#endif
+ NR_VM_EVENT_ITEMS
+ };
+
+@@ -174,7 +178,7 @@ static inline unsigned long node_page_state(int node,
+ zone_page_state(&zones[ZONE_MOVABLE], item);
+ }
+
+-extern void zone_statistics(struct zonelist *, struct zone *);
++extern void zone_statistics(struct zone *, struct zone *);
+
+ #else
+
diff --git a/include/linux/wireless.h b/include/linux/wireless.h
index 3160dfe..2864b16 100644
--- a/include/linux/wireless.h
@@ -823398,6 +1104029,38 @@
+void wm97xx_unregister_mach_ops(struct wm97xx *);
+
+#endif
+diff --git a/include/linux/writeback.h b/include/linux/writeback.h
+index b7b3362..f462439 100644
+--- a/include/linux/writeback.h
++++ b/include/linux/writeback.h
+@@ -114,6 +114,9 @@ struct file;
+ int dirty_writeback_centisecs_handler(struct ctl_table *, int, struct file *,
+ void __user *, size_t *, loff_t *);
+
++void get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty,
++ struct backing_dev_info *bdi);
++
+ void page_writeback_init(void);
+ void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
+ unsigned long nr_pages_dirtied);
+diff --git a/include/linux/xattr.h b/include/linux/xattr.h
+index df6b95d..d131e35 100644
+--- a/include/linux/xattr.h
++++ b/include/linux/xattr.h
+@@ -47,10 +47,10 @@ struct xattr_handler {
+ };
+
+ ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
+-ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
++ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
+ ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
+-int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
+-int vfs_removexattr(struct dentry *, char *);
++int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int);
++int vfs_removexattr(struct dentry *, const char *);
+
+ ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
+ ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index e31b8c8..2ca6bae 100644
--- a/include/linux/xfrm.h
@@ -823691,10 +1104354,18 @@
#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
+index 032bb75..2a52774 100644
--- a/include/media/v4l2-chip-ident.h
+++ b/include/media/v4l2-chip-ident.h
-@@ -153,6 +153,12 @@ enum {
+@@ -64,6 +64,7 @@ enum {
+ /* Conexant MPEG encoder/decoders: reserved range 410-420 */
+ V4L2_IDENT_CX23415 = 415,
+ V4L2_IDENT_CX23416 = 416,
++ V4L2_IDENT_CX23418 = 418,
+
+ /* module vp27smpx: just ident 2700 */
+ V4L2_IDENT_VP27SMPX = 2700,
+@@ -153,6 +154,12 @@ enum {
V4L2_IDENT_MSP4428G = 44287,
V4L2_IDENT_MSP4448G = 44487,
V4L2_IDENT_MSP4458G = 44587,
@@ -823707,6 +1104378,23 @@
};
#endif
+diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
+index 316a584..020d057 100644
+--- a/include/media/v4l2-common.h
++++ b/include/media/v4l2-common.h
+@@ -107,9 +107,11 @@ int v4l2_chip_match_host(u32 id_type, u32 chip_id);
+ struct i2c_driver;
+ struct i2c_adapter;
+ struct i2c_client;
++struct i2c_device_id;
+
+ int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver,
+- const char *name, int (*probe)(struct i2c_client *));
++ const char *name,
++ int (*probe)(struct i2c_client *, const struct i2c_device_id *));
+
+ /* ------------------------------------------------------------------------- */
+
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index f211445..a807d2f 100644
--- a/include/media/v4l2-dev.h
@@ -823722,6 +1104410,32 @@
#ifdef OBSOLETE_OWNER /* to be removed soon */
/* obsolete -- fops->owner is used instead */
+diff --git a/include/media/v4l2-i2c-drv-legacy.h b/include/media/v4l2-i2c-drv-legacy.h
+index e764557..347b6f8 100644
+--- a/include/media/v4l2-i2c-drv-legacy.h
++++ b/include/media/v4l2-i2c-drv-legacy.h
+@@ -25,7 +25,7 @@ struct v4l2_i2c_driver_data {
+ const char * const name;
+ int driverid;
+ int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
+- int (*probe)(struct i2c_client *client);
++ int (*probe)(struct i2c_client *client, const struct i2c_device_id *id);
+ int (*remove)(struct i2c_client *client);
+ int (*suspend)(struct i2c_client *client, pm_message_t state);
+ int (*resume)(struct i2c_client *client);
+diff --git a/include/media/v4l2-i2c-drv.h b/include/media/v4l2-i2c-drv.h
+index 9e4bab2..7b6f06b 100644
+--- a/include/media/v4l2-i2c-drv.h
++++ b/include/media/v4l2-i2c-drv.h
+@@ -30,7 +30,7 @@ struct v4l2_i2c_driver_data {
+ const char * const name;
+ int driverid;
+ int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
+- int (*probe)(struct i2c_client *client);
++ int (*probe)(struct i2c_client *client, const struct i2c_device_id *id);
+ int (*remove)(struct i2c_client *client);
+ int (*suspend)(struct i2c_client *client, pm_message_t state);
+ int (*resume)(struct i2c_client *client);
diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h
index 9903394..5b39a22 100644
--- a/include/media/videobuf-core.h
@@ -824682,6 +1105396,21 @@
};
#endif /* __NET_CFG80211_H */
+diff --git a/include/net/compat.h b/include/net/compat.h
+index 406db24..164cb68 100644
+--- a/include/net/compat.h
++++ b/include/net/compat.h
+@@ -40,4 +40,10 @@ extern int put_cmsg_compat(struct msghdr*, int, int, int, void *);
+
+ extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *, unsigned char *, int);
+
++extern int compat_mc_setsockopt(struct sock *, int, int, char __user *, int,
++ int (*)(struct sock *, int, int, char __user *, int));
++extern int compat_mc_getsockopt(struct sock *, int, int, char __user *,
++ int __user *, int (*)(struct sock *, int, int, char __user *,
++ int __user *));
++
+ #endif /* NET_COMPAT_H */
diff --git a/include/net/dst.h b/include/net/dst.h
index ae13370..002500e 100644
--- a/include/net/dst.h
@@ -825596,6 +1106325,20 @@
extern void rt6_mtu_change(struct net_device *dev, unsigned mtu);
extern rwlock_t rt6_lock;
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index 56f3c94..9a51eba 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -405,7 +405,8 @@ struct sk_buff;
+ struct ip_vs_protocol {
+ struct ip_vs_protocol *next;
+ char *name;
+- __u16 protocol;
++ u16 protocol;
++ u16 num_states;
+ int dont_defrag;
+ atomic_t appcnt; /* counter of proto app incs */
+ int *timeout_table; /* protocol timeout table */
diff --git a/include/net/ipip.h b/include/net/ipip.h
index 549e132..633ed4d 100644
--- a/include/net/ipip.h
@@ -827339,7 +1108082,7 @@
/* 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
+index e69ab2e..a6874ba 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
@@ -827362,8 +1108105,20 @@
} sctp;
struct {
__be16 key;
-@@ -113,11 +119,37 @@ struct nf_conntrack_tuple_mask
+@@ -101,23 +107,39 @@ struct nf_conntrack_tuple_mask
+ } src;
+ };
+-/* This is optimized opposed to a memset of the whole structure. Everything we
+- * really care about is the source/destination unions */
+-#define NF_CT_TUPLE_U_BLANK(tuple) \
+- do { \
+- (tuple)->src.u.all = 0; \
+- (tuple)->dst.u.all = 0; \
+- memset(&(tuple)->src.u3, 0, sizeof((tuple)->src.u3)); \
+- memset(&(tuple)->dst.u3, 0, sizeof((tuple)->dst.u3)); \
+- } while (0)
+-
#ifdef __KERNEL__
-#define NF_CT_DUMP_TUPLE(tp) \
@@ -827405,7 +1108160,7 @@
/* 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
+@@ -132,70 +154,64 @@ struct nf_conntrack_tuple_hash
#endif /* __KERNEL__ */
@@ -827604,10 +1108359,18 @@
-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
+index 0ca67d7..e4d2d6b 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
-@@ -162,7 +162,7 @@ struct netlbl_lsm_secattr_catmap {
+@@ -103,6 +103,7 @@ struct cipso_v4_doi;
+ struct netlbl_audit {
+ u32 secid;
+ uid_t loginuid;
++ u32 sessionid;
+ };
+
+ /*
+@@ -162,7 +163,7 @@ struct netlbl_lsm_secattr_catmap {
/**
* struct netlbl_lsm_secattr - NetLabel LSM security attributes
@@ -827616,7 +1108379,7 @@
* @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 {
+@@ -180,17 +181,22 @@ struct netlbl_lsm_secattr_catmap {
* NetLabel itself when returning security attributes to the LSM.
*
*/
@@ -827641,7 +1108404,7 @@
u32 type;
char *domain;
struct netlbl_lsm_cache *cache;
-@@ -303,7 +308,8 @@ static inline void netlbl_secattr_init(struct netlbl_lsm_secattr *secattr)
+@@ -303,7 +309,8 @@ static inline void netlbl_secattr_init(struct netlbl_lsm_secattr *secattr)
*/
static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr)
{
@@ -827884,7 +1108647,7 @@
};
diff --git a/include/net/route.h b/include/net/route.h
-index eadad59..c633880 100644
+index eadad59..fc836ff 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -34,7 +34,6 @@
@@ -827895,6 +1108658,15 @@
#ifndef __KERNEL__
#warning This file is not supposed to be used outside of kernel.
+@@ -117,7 +116,7 @@ extern int __ip_route_output_key(struct net *, struct rtable **, const struct f
+ extern int ip_route_output_key(struct net *, struct rtable **, struct flowi *flp);
+ extern int ip_route_output_flow(struct net *, struct rtable **rp, struct flowi *flp, struct sock *sk, int flags);
+ extern int ip_route_input(struct sk_buff*, __be32 dst, __be32 src, u8 tos, struct net_device *devin);
+-extern unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph, unsigned short new_mtu);
++extern unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph, unsigned short new_mtu, struct net_device *dev);
+ extern void ip_rt_send_redirect(struct sk_buff *skb);
+
+ extern unsigned inet_addr_type(struct net *net, __be32 addr);
@@ -161,7 +160,7 @@ static inline int ip_route_connect(struct rtable **rp, __be32 dst,
.dport = dport } } };
@@ -828658,7 +1109430,7 @@
+}
#endif /* __NET_WIRELESS_H */
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
-index 0d255ae..baa9f37 100644
+index 0d255ae..d1350bc 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -121,6 +121,7 @@ extern struct mutex xfrm_cfg_mutex;
@@ -828687,7 +1109459,67 @@
struct hlist_node bydst;
struct hlist_node byidx;
-@@ -1071,6 +1076,23 @@ xfrm_address_t *xfrm_flowi_saddr(struct flowi *fl, unsigned short family)
+@@ -592,8 +597,9 @@ struct xfrm_spi_skb_cb {
+ /* Audit Information */
+ struct xfrm_audit
+ {
+- u32 loginuid;
+ u32 secid;
++ uid_t loginuid;
++ u32 sessionid;
+ };
+
+ #ifdef CONFIG_AUDITSYSCALL
+@@ -611,13 +617,13 @@ static inline struct audit_buffer *xfrm_audit_start(const char *op)
+ return audit_buf;
+ }
+
+-static inline void xfrm_audit_helper_usrinfo(u32 auid, u32 secid,
++static inline void xfrm_audit_helper_usrinfo(uid_t auid, u32 ses, u32 secid,
+ struct audit_buffer *audit_buf)
+ {
+ char *secctx;
+ u32 secctx_len;
+
+- audit_log_format(audit_buf, " auid=%u", auid);
++ audit_log_format(audit_buf, " auid=%u ses=%u", auid, ses);
+ if (secid != 0 &&
+ security_secid_to_secctx(secid, &secctx, &secctx_len) == 0) {
+ audit_log_format(audit_buf, " subj=%s", secctx);
+@@ -627,13 +633,13 @@ static inline void xfrm_audit_helper_usrinfo(u32 auid, u32 secid,
+ }
+
+ extern void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
+- u32 auid, u32 secid);
++ u32 auid, u32 ses, u32 secid);
+ extern void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
+- u32 auid, u32 secid);
++ u32 auid, u32 ses, u32 secid);
+ extern void xfrm_audit_state_add(struct xfrm_state *x, int result,
+- u32 auid, u32 secid);
++ u32 auid, u32 ses, u32 secid);
+ extern void xfrm_audit_state_delete(struct xfrm_state *x, int result,
+- u32 auid, u32 secid);
++ u32 auid, u32 ses, u32 secid);
+ extern void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
+ struct sk_buff *skb);
+ extern void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family);
+@@ -642,10 +648,10 @@ extern void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
+ extern void xfrm_audit_state_icvfail(struct xfrm_state *x,
+ struct sk_buff *skb, u8 proto);
+ #else
+-#define xfrm_audit_policy_add(x, r, a, s) do { ; } while (0)
+-#define xfrm_audit_policy_delete(x, r, a, s) do { ; } while (0)
+-#define xfrm_audit_state_add(x, r, a, s) do { ; } while (0)
+-#define xfrm_audit_state_delete(x, r, a, s) do { ; } while (0)
++#define xfrm_audit_policy_add(x, r, a, se, s) do { ; } while (0)
++#define xfrm_audit_policy_delete(x, r, a, se, s) do { ; } while (0)
++#define xfrm_audit_state_add(x, r, a, se, s) do { ; } while (0)
++#define xfrm_audit_state_delete(x, r, a, se, s) do { ; } while (0)
+ #define xfrm_audit_state_replay_overflow(x, s) do { ; } while (0)
+ #define xfrm_audit_state_notfound_simple(s, f) do { ; } while (0)
+ #define xfrm_audit_state_notfound(s, f, sp, sq) do { ; } while (0)
+@@ -1071,6 +1077,23 @@ xfrm_address_t *xfrm_flowi_saddr(struct flowi *fl, unsigned short family)
return NULL;
}
@@ -828711,7 +1109543,7 @@
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 {
+@@ -1188,6 +1211,18 @@ struct xfrm6_tunnel {
int priority;
};
@@ -828730,7 +1109562,7 @@
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)
+@@ -1212,7 +1247,23 @@ static inline void xfrm6_fini(void)
extern int xfrm_proc_init(void);
#endif
@@ -828755,7 +1109587,7 @@
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)
+@@ -1335,7 +1386,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);
@@ -828782,6 +1109614,28 @@
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_umem.h b/include/rdma/ib_umem.h
+index 2229842..9ee0d2e 100644
+--- a/include/rdma/ib_umem.h
++++ b/include/rdma/ib_umem.h
+@@ -62,7 +62,7 @@ struct ib_umem_chunk {
+ #ifdef CONFIG_INFINIBAND_USER_MEM
+
+ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
+- size_t size, int access);
++ size_t size, int access, int dmasync);
+ void ib_umem_release(struct ib_umem *umem);
+ int ib_umem_page_count(struct ib_umem *umem);
+
+@@ -72,7 +72,7 @@ int ib_umem_page_count(struct ib_umem *umem);
+
+ static inline struct ib_umem *ib_umem_get(struct ib_ucontext *context,
+ unsigned long addr, size_t size,
+- int access) {
++ int access, int dmasync) {
+ return ERR_PTR(-EINVAL);
+ }
+ static inline void ib_umem_release(struct ib_umem *umem) { }
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
@@ -828799,7 +1109653,7 @@
struct {
__u64 remote_addr;
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
-index 701e7b4..2dcbecc 100644
+index 701e7b4..911a661 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -94,7 +94,7 @@ enum ib_device_cap_flags {
@@ -828923,6 +1109777,53 @@
* ib_destroy_cq - Destroys the specified CQ.
* @cq: The CQ to destroy.
*/
+@@ -1515,6 +1542,24 @@ static inline void ib_dma_unmap_single(struct ib_device *dev,
+ dma_unmap_single(dev->dma_device, addr, size, direction);
+ }
+
++static inline u64 ib_dma_map_single_attrs(struct ib_device *dev,
++ void *cpu_addr, size_t size,
++ enum dma_data_direction direction,
++ struct dma_attrs *attrs)
++{
++ return dma_map_single_attrs(dev->dma_device, cpu_addr, size,
++ direction, attrs);
++}
++
++static inline void ib_dma_unmap_single_attrs(struct ib_device *dev,
++ u64 addr, size_t size,
++ enum dma_data_direction direction,
++ struct dma_attrs *attrs)
++{
++ return dma_unmap_single_attrs(dev->dma_device, addr, size,
++ direction, attrs);
++}
++
+ /**
+ * ib_dma_map_page - Map a physical page to DMA address
+ * @dev: The device for which the dma_addr is to be created
+@@ -1584,6 +1629,21 @@ static inline void ib_dma_unmap_sg(struct ib_device *dev,
+ dma_unmap_sg(dev->dma_device, sg, nents, direction);
+ }
+
++static inline int ib_dma_map_sg_attrs(struct ib_device *dev,
++ struct scatterlist *sg, int nents,
++ enum dma_data_direction direction,
++ struct dma_attrs *attrs)
++{
++ return dma_map_sg_attrs(dev->dma_device, sg, nents, direction, attrs);
++}
++
++static inline void ib_dma_unmap_sg_attrs(struct ib_device *dev,
++ struct scatterlist *sg, int nents,
++ enum dma_data_direction direction,
++ struct dma_attrs *attrs)
++{
++ dma_unmap_sg_attrs(dev->dma_device, sg, nents, direction, attrs);
++}
+ /**
+ * ib_sg_dma_address - Return the DMA address from a scatter/gather entry
+ * @dev: The device for which the DMA addresses were created
diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
index 5ffec8a..e0593bf 100644
--- a/include/scsi/iscsi_proto.h
@@ -828954,6 +1109855,18 @@
};
/* SCSI Response Header */
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 7b90b63..cd3ca63 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -225,6 +225,7 @@ struct iscsi_conn {
+
+ /* custom statistics */
+ uint32_t eh_abort_cnt;
++ uint32_t fmr_unalign_cnt;
+ };
+
+ struct iscsi_pool {
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 39e1cac..e78d3b6 100644
--- a/include/scsi/libsas.h
@@ -829026,7 +1109939,7 @@
+
#endif /* _SCSI_SCSI_CMND_H */
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
-index ab7acbe..b8b19e2 100644
+index ab7acbe..f6a9fe0 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -156,8 +156,8 @@ struct scsi_device {
@@ -829052,7 +1109965,17 @@
#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)
+@@ -181,7 +181,8 @@ struct scsi_device {
+ sdev_printk(prefix, (scmd)->device, fmt, ##a)
+
+ enum scsi_target_state {
+- STARGET_RUNNING = 1,
++ STARGET_CREATED = 1,
++ STARGET_RUNNING,
+ STARGET_DEL,
+ };
+
+@@ -220,7 +221,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) \
@@ -829356,10 +1110279,18 @@
*/
#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
+index d45218b..1f1d53f 100644
--- a/include/sound/mpu401.h
+++ b/include/sound/mpu401.h
-@@ -103,6 +103,21 @@ struct snd_mpu401 {
+@@ -50,6 +50,7 @@
+ #define MPU401_INFO_INTEGRATED (1 << 2) /* integrated h/w port */
+ #define MPU401_INFO_MMIO (1 << 3) /* MMIO access */
+ #define MPU401_INFO_TX_IRQ (1 << 4) /* independent TX irq */
++#define MPU401_INFO_NO_ACK (1 << 6) /* No ACK cmd needed */
+
+ #define MPU401_MODE_BIT_INPUT 0
+ #define MPU401_MODE_BIT_OUTPUT 1
+@@ -103,6 +104,21 @@ struct snd_mpu401 {
#define MPU401D(mpu) (mpu)->port
/*
@@ -829391,6 +1110322,162 @@
-#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/video/atmel_lcdc.h b/include/video/atmel_lcdc.h
+index 336c20d..ed64862 100644
+--- a/include/video/atmel_lcdc.h
++++ b/include/video/atmel_lcdc.h
+@@ -22,6 +22,15 @@
+ #ifndef __ATMEL_LCDC_H__
+ #define __ATMEL_LCDC_H__
+
++
++/* Way LCD wires are connected to the chip:
++ * Some Atmel chips use BGR color mode (instead of standard RGB)
++ * A swapped wiring onboard can bring to RGB mode.
++ */
++#define ATMEL_LCDC_WIRING_BGR 0
++#define ATMEL_LCDC_WIRING_RGB 1
++
++
+ /* LCD Controller info data structure, stored in device platform_data */
+ struct atmel_lcdfb_info {
+ spinlock_t lock;
+@@ -39,8 +48,10 @@ struct atmel_lcdfb_info {
+ u8 bl_power;
+ #endif
+ bool lcdcon_is_backlight;
++ u8 saved_lcdcon;
+
+ u8 default_bpp;
++ u8 lcd_wiring_mode;
+ unsigned int default_lcdcon2;
+ unsigned int default_dmacon;
+ void (*atmel_lcdfb_power_control)(int on);
+diff --git a/include/video/hecubafb.h b/include/video/hecubafb.h
+new file mode 100644
+index 0000000..7b99523
+--- /dev/null
++++ b/include/video/hecubafb.h
+@@ -0,0 +1,51 @@
++/*
++ * hecubafb.h - definitions for the hecuba framebuffer driver
++ *
++ * Copyright (C) 2008 by Jaya Kumar
++ *
++ * 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 _LINUX_HECUBAFB_H_
++#define _LINUX_HECUBAFB_H_
++
++/* Apollo controller specific defines */
++#define APOLLO_START_NEW_IMG 0xA0
++#define APOLLO_STOP_IMG_DATA 0xA1
++#define APOLLO_DISPLAY_IMG 0xA2
++#define APOLLO_ERASE_DISPLAY 0xA3
++#define APOLLO_INIT_DISPLAY 0xA4
++
++/* Hecuba interface specific defines */
++#define HCB_WUP_BIT 0x01
++#define HCB_DS_BIT 0x02
++#define HCB_RW_BIT 0x04
++#define HCB_CD_BIT 0x08
++#define HCB_ACK_BIT 0x80
++
++/* struct used by hecuba. board specific stuff comes from *board */
++struct hecubafb_par {
++ struct fb_info *info;
++ struct hecuba_board *board;
++ void (*send_command)(struct hecubafb_par *, unsigned char);
++ void (*send_data)(struct hecubafb_par *, unsigned char);
++};
++
++/* board specific routines
++board drivers can implement wait_for_ack with interrupts if desired. if
++wait_for_ack is called with clear=0, then go to sleep and return when ack
++goes hi or if wait_for_ack with clear=1, then return when ack goes lo */
++struct hecuba_board {
++ struct module *owner;
++ void (*remove)(struct hecubafb_par *);
++ void (*set_ctl)(struct hecubafb_par *, unsigned char, unsigned char);
++ void (*set_data)(struct hecubafb_par *, unsigned char);
++ void (*wait_for_ack)(struct hecubafb_par *, int);
++ int (*init)(struct hecubafb_par *);
++};
++
++
++#endif
+diff --git a/include/video/metronomefb.h b/include/video/metronomefb.h
+new file mode 100644
+index 0000000..dab04b4
+--- /dev/null
++++ b/include/video/metronomefb.h
+@@ -0,0 +1,62 @@
++/*
++ * metronomefb.h - definitions for the metronome framebuffer driver
++ *
++ * Copyright (C) 2008 by Jaya Kumar
++ *
++ * 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 _LINUX_METRONOMEFB_H_
++#define _LINUX_METRONOMEFB_H_
++
++/* address and control descriptors used by metronome controller */
++struct metromem_desc {
++ u32 mFDADR0;
++ u32 mFSADR0;
++ u32 mFIDR0;
++ u32 mLDCMD0;
++};
++
++/* command structure used by metronome controller */
++struct metromem_cmd {
++ u16 opcode;
++ u16 args[((64-2)/2)];
++ u16 csum;
++};
++
++/* struct used by metronome. board specific stuff comes from *board */
++struct metronomefb_par {
++ unsigned char *metromem;
++ struct metromem_desc *metromem_desc;
++ struct metromem_cmd *metromem_cmd;
++ unsigned char *metromem_wfm;
++ unsigned char *metromem_img;
++ u16 *metromem_img_csum;
++ u16 *csum_table;
++ int metromemsize;
++ dma_addr_t metromem_dma;
++ dma_addr_t metromem_desc_dma;
++ struct fb_info *info;
++ struct metronome_board *board;
++ wait_queue_head_t waitq;
++ u8 frame_count;
++};
++
++/* board specific routines */
++struct metronome_board {
++ struct module *owner;
++ void (*free_irq)(struct fb_info *);
++ void (*init_gpio_regs)(struct metronomefb_par *);
++ void (*init_lcdc_regs)(struct metronomefb_par *);
++ void (*post_dma_setup)(struct metronomefb_par *);
++ void (*set_rst)(struct metronomefb_par *, int);
++ void (*set_stdby)(struct metronomefb_par *, int);
++ int (*met_wait_event)(struct metronomefb_par *);
++ int (*met_wait_event_intr)(struct metronomefb_par *);
++ int (*setup_irq)(struct fb_info *);
++};
++
++#endif
diff --git a/include/xen/balloon.h b/include/xen/balloon.h
new file mode 100644
index 0000000..fe43b0f
@@ -830450,10 +1111537,56 @@
+
+#endif /* _LINUX_XENCOMM_H_ */
diff --git a/init/Kconfig b/init/Kconfig
-index a97924b..ba3a389 100644
+index a97924b..3e7b257 100644
--- a/init/Kconfig
+++ b/init/Kconfig
-@@ -328,6 +328,13 @@ config RT_GROUP_SCHED
+@@ -259,17 +259,14 @@ config IKCONFIG_PROC
+ config LOG_BUF_SHIFT
+ int "Kernel log buffer size (16 => 64KB, 17 => 128KB)"
+ range 12 21
+- default 17 if S390 || LOCKDEP
+- default 16 if X86_NUMAQ || IA64
+- default 15 if SMP
+- default 14
++ default 17
+ help
+ Select kernel log buffer size as a power of 2.
+- Defaults and Examples:
+- 17 => 128 KB for S/390
+- 16 => 64 KB for x86 NUMAQ or IA-64
+- 15 => 32 KB for SMP
+- 14 => 16 KB for uniprocessor
++ Examples:
++ 17 => 128 KB
++ 16 => 64 KB
++ 15 => 32 KB
++ 14 => 16 KB
+ 13 => 8 KB
+ 12 => 4 KB
+
+@@ -284,6 +281,7 @@ config CGROUPS
+ config CGROUP_DEBUG
+ bool "Example debug cgroup subsystem"
+ depends on CGROUPS
++ default n
+ help
+ This option enables a simple cgroup subsystem that
+ exports useful debugging information about the cgroups
+@@ -300,6 +298,13 @@ config CGROUP_NS
+ for instance virtual servers and checkpoint/restart
+ jobs.
+
++config CGROUP_DEVICE
++ bool "Device controller for cgroups"
++ depends on CGROUPS && EXPERIMENTAL
++ help
++ Provides a cgroup implementing whitelists for devices which
++ a process in the cgroup can mknod or open.
++
+ config CPUSETS
+ bool "Cpuset support"
+ depends on SMP && CGROUPS
+@@ -328,6 +333,13 @@ config RT_GROUP_SCHED
depends on EXPERIMENTAL
depends on GROUP_SCHED
default n
@@ -830467,7 +1111600,76 @@
choice
depends on GROUP_SCHED
-@@ -763,7 +770,7 @@ endmenu # General setup
+@@ -366,9 +378,13 @@ config RESOURCE_COUNTERS
+ infrastructure that works with cgroups
+ depends on CGROUPS
+
++config MM_OWNER
++ bool
++
+ config CGROUP_MEM_RES_CTLR
+ bool "Memory Resource Controller for Control Groups"
+ depends on CGROUPS && RESOURCE_COUNTERS
++ select MM_OWNER
+ help
+ Provides a memory resource controller that manages both page cache and
+ RSS memory.
+@@ -381,6 +397,9 @@ config CGROUP_MEM_RES_CTLR
+ Only enable when you're ok with these trade offs and really
+ sure you need the memory resource controller.
+
++ This config option also selects MM_OWNER config option, which
++ could in turn add some fork/exit overhead.
++
+ config SYSFS_DEPRECATED
+ bool
+
+@@ -489,16 +508,12 @@ source "usr/Kconfig"
+ endif
+
+ config CC_OPTIMIZE_FOR_SIZE
+- bool "Optimize for size (Look out for broken compilers!)"
++ bool "Optimize for size"
+ default y
+- depends on ARM || H8300 || SUPERH || EXPERIMENTAL
+ help
+ Enabling this option will pass "-Os" instead of "-O2" to gcc
+ resulting in a smaller kernel.
+
+- WARNING: some versions of gcc may generate incorrect code with this
+- option. If problems are observed, a gcc upgrade may be needed.
+-
+ If unsure, say N.
+
+ config SYSCTL
+@@ -514,7 +529,7 @@ menuconfig EMBEDDED
+
+ config UID16
+ bool "Enable 16-bit UID system calls" if EMBEDDED
+- depends on ARM || BLACKFIN || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && SPARC32_COMPAT) || UML || (X86_64 && IA32_EMULATION)
++ depends on ARM || BLACKFIN || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && COMPAT) || UML || (X86_64 && IA32_EMULATION)
+ default y
+ help
+ This enables the legacy 16-bit UID syscall wrappers.
+@@ -535,6 +550,17 @@ config SYSCTL_SYSCALL
+
+ If unsure say Y here.
+
++config SYSCTL_SYSCALL_CHECK
++ bool "Sysctl checks" if EMBEDDED
++ depends on SYSCTL_SYSCALL
++ default y
++ ---help---
++ sys_sysctl uses binary paths that have been found challenging
++ to properly maintain and use. This enables checks that help
++ you to keep things correct.
++
++ If unsure say Y here.
++
+ config KALLSYMS
+ bool "Load all symbols for debugging/ksymoops" if EMBEDDED
+ default y
+@@ -763,7 +789,7 @@ endmenu # General setup
config SLABINFO
bool
depends on PROC_FS
@@ -830476,11 +1111678,104 @@
default y
config RT_MUTEXES
+diff --git a/init/do_mounts_md.c b/init/do_mounts_md.c
+index 753dc54..7473b0c 100644
+--- a/init/do_mounts_md.c
++++ b/init/do_mounts_md.c
+@@ -133,7 +133,7 @@ static void __init md_setup_drive(void)
+ else
+ dev = MKDEV(MD_MAJOR, minor);
+ create_dev(name, dev);
+- for (i = 0; i < MD_SB_DISKS && devname != 0; i++) {
++ for (i = 0; i < MD_SB_DISKS && devname != NULL; i++) {
+ char *p;
+ char comp_name[64];
+ u32 rdev;
+diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c
+index 3ac5904..46dfd64 100644
+--- a/init/do_mounts_rd.c
++++ b/init/do_mounts_rd.c
+@@ -212,7 +212,7 @@ int __init rd_load_image(char *from)
+ }
+
+ buf = kmalloc(BLOCK_SIZE, GFP_KERNEL);
+- if (buf == 0) {
++ if (!buf) {
+ printk(KERN_ERR "RAMDISK: could not allocate buffer\n");
+ goto done;
+ }
+diff --git a/init/initramfs.c b/init/initramfs.c
+index d53fee8..8eeeccb 100644
+--- a/init/initramfs.c
++++ b/init/initramfs.c
+@@ -57,7 +57,7 @@ static char __init *find_link(int major, int minor, int ino,
+ continue;
+ return (*p)->name;
+ }
+- q = (struct hash *)malloc(sizeof(struct hash));
++ q = kmalloc(sizeof(struct hash), GFP_KERNEL);
+ if (!q)
+ panic("can't allocate link hash entry");
+ q->major = major;
+@@ -77,7 +77,7 @@ static void __init free_hash(void)
+ while (*p) {
+ q = *p;
+ *p = q->next;
+- free(q);
++ kfree(q);
+ }
+ }
+ }
+@@ -445,10 +445,10 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
+ {
+ int written;
+ dry_run = check_only;
+- header_buf = malloc(110);
+- symlink_buf = malloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1);
+- name_buf = malloc(N_ALIGN(PATH_MAX));
+- window = malloc(WSIZE);
++ header_buf = kmalloc(110, GFP_KERNEL);
++ symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL);
++ name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL);
++ window = kmalloc(WSIZE, GFP_KERNEL);
+ if (!window || !header_buf || !symlink_buf || !name_buf)
+ panic("can't allocate buffers");
+ state = Start;
+@@ -484,10 +484,10 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
+ buf += inptr;
+ len -= inptr;
+ }
+- free(window);
+- free(name_buf);
+- free(symlink_buf);
+- free(header_buf);
++ kfree(window);
++ kfree(name_buf);
++ kfree(symlink_buf);
++ kfree(header_buf);
+ return message;
+ }
+
diff --git a/init/main.c b/init/main.c
-index 99ce949..1687b01 100644
+index 99ce949..a87d4ca 100644
--- a/init/main.c
+++ b/init/main.c
-@@ -359,10 +359,31 @@ static void __init smp_init(void)
+@@ -52,12 +52,14 @@
+ #include <linux/unwind.h>
+ #include <linux/buffer_head.h>
+ #include <linux/debug_locks.h>
++#include <linux/debugobjects.h>
+ #include <linux/lockdep.h>
+ #include <linux/pid_namespace.h>
+ #include <linux/device.h>
+ #include <linux/kthread.h>
+ #include <linux/sched.h>
+ #include <linux/signal.h>
++#include <linux/idr.h>
+
+ #include <asm/io.h>
+ #include <asm/bugs.h>
+@@ -359,10 +361,31 @@ static void __init smp_init(void)
#endif
static inline void setup_per_cpu_areas(void) { }
@@ -830512,7 +1111807,16 @@
#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)
+@@ -437,7 +460,7 @@ static void noinline __init_refok rest_init(void)
+ kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
+ numa_default_policy();
+ pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
+- kthreadd_task = find_task_by_pid(pid);
++ kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
+ unlock_kernel();
+
+ /*
+@@ -500,7 +523,11 @@ static void __init boot_cpu_init(void)
cpu_set(cpu, cpu_possible_map);
}
@@ -830525,7 +1111829,19 @@
{
}
-@@ -537,6 +562,7 @@ asmlinkage void __init start_kernel(void)
+@@ -517,6 +544,7 @@ asmlinkage void __init start_kernel(void)
+ */
+ unwind_init();
+ lockdep_init();
++ debug_objects_early_init();
+ cgroup_init_early();
+
+ local_irq_disable();
+@@ -534,9 +562,11 @@ asmlinkage void __init start_kernel(void)
+ printk(KERN_NOTICE);
+ printk(linux_banner);
+ setup_arch(&command_line);
++ mm_init_owner(&init_mm, &init_task);
setup_command_line(command_line);
unwind_setup();
setup_per_cpu_areas();
@@ -830533,7 +1111849,16 @@
smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
/*
-@@ -623,6 +649,7 @@ asmlinkage void __init start_kernel(void)
+@@ -610,6 +640,8 @@ asmlinkage void __init start_kernel(void)
+ enable_debug_pagealloc();
+ cpu_hotplug_init();
+ kmem_cache_init();
++ debug_objects_mem_init();
++ idr_init_cache();
+ setup_per_cpu_pageset();
+ numa_policy_init();
+ if (late_time_init)
+@@ -623,6 +655,7 @@ asmlinkage void __init start_kernel(void)
if (efi_enabled)
efi_enter_virtual_mode();
#endif
@@ -830541,6 +1111866,59 @@
fork_init(num_physpages);
proc_caches_init();
buffer_init();
+@@ -673,10 +706,8 @@ static void __init do_initcalls(void)
+ int result;
+
+ if (initcall_debug) {
+- printk("Calling initcall 0x%p", *call);
+- print_fn_descriptor_symbol(": %s()",
++ print_fn_descriptor_symbol("calling %s()\n",
+ (unsigned long) *call);
+- printk("\n");
+ t0 = ktime_get();
+ }
+
+@@ -686,15 +717,10 @@ static void __init do_initcalls(void)
+ t1 = ktime_get();
+ delta = ktime_sub(t1, t0);
+
+- printk("initcall 0x%p", *call);
+- print_fn_descriptor_symbol(": %s()",
++ print_fn_descriptor_symbol("initcall %s()",
+ (unsigned long) *call);
+- printk(" returned %d.\n", result);
+-
+- printk("initcall 0x%p ran for %Ld msecs: ",
+- *call, (unsigned long long)delta.tv64 >> 20);
+- print_fn_descriptor_symbol("%s()\n",
+- (unsigned long) *call);
++ printk(" returned %d after %Ld msecs\n", result,
++ (unsigned long long) delta.tv64 >> 20);
+ }
+
+ if (result && result != -ENODEV && initcall_debug) {
+@@ -710,10 +736,9 @@ static void __init do_initcalls(void)
+ local_irq_enable();
+ }
+ if (msg) {
+- printk(KERN_WARNING "initcall at 0x%p", *call);
+- print_fn_descriptor_symbol(": %s()",
++ print_fn_descriptor_symbol(KERN_WARNING "initcall %s()",
+ (unsigned long) *call);
+- printk(": returned with %s\n", msg);
++ printk(" returned with %s\n", msg);
+ }
+ }
+
+@@ -780,6 +805,8 @@ static int noinline init_post(void)
+ (void) sys_dup(0);
+ (void) sys_dup(0);
+
++ current->signal->flags |= SIGNAL_UNKILLABLE;
++
+ if (ramdisk_execute_command) {
+ run_init_process(ramdisk_execute_command);
+ printk(KERN_WARNING "Failed to execute %s\n",
@@ -811,7 +838,7 @@ static int __init kernel_init(void * unused)
/*
* init can run on any cpu.
@@ -830550,6 +1111928,223 @@
/*
* Tell the world that we're going to be the grim
* reaper of innocent orphaned children.
+diff --git a/ipc/Makefile b/ipc/Makefile
+index 5fc5e33..65c3843 100644
+--- a/ipc/Makefile
++++ b/ipc/Makefile
+@@ -3,7 +3,7 @@
+ #
+
+ obj-$(CONFIG_SYSVIPC_COMPAT) += compat.o
+-obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o
++obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o ipcns_notifier.o
+ obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o
+ obj_mq-$(CONFIG_COMPAT) += compat_mq.o
+ obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y)
+diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
+index 7f4235b..d349746 100644
+--- a/ipc/ipc_sysctl.c
++++ b/ipc/ipc_sysctl.c
+@@ -15,6 +15,8 @@
+ #include <linux/sysctl.h>
+ #include <linux/uaccess.h>
+ #include <linux/ipc_namespace.h>
++#include <linux/msg.h>
++#include "util.h"
+
+ static void *get_ipc(ctl_table *table)
+ {
+@@ -24,6 +26,27 @@ static void *get_ipc(ctl_table *table)
+ return which;
+ }
+
++/*
++ * Routine that is called when a tunable has successfully been changed by
++ * hand and it has a callback routine registered on the ipc namespace notifier
++ * chain: we don't want such tunables to be recomputed anymore upon memory
++ * add/remove or ipc namespace creation/removal.
++ * They can come back to a recomputable state by being set to a <0 value.
++ */
++static void tunable_set_callback(int val)
++{
++ if (val >= 0)
++ unregister_ipcns_notifier(current->nsproxy->ipc_ns);
++ else {
++ /*
++ * Re-enable automatic recomputing only if not already
++ * enabled.
++ */
++ recompute_msgmni(current->nsproxy->ipc_ns);
++ cond_register_ipcns_notifier(current->nsproxy->ipc_ns);
++ }
++}
++
+ #ifdef CONFIG_PROC_FS
+ static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+@@ -35,6 +58,24 @@ static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
+ return proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos);
+ }
+
++static int proc_ipc_callback_dointvec(ctl_table *table, int write,
++ struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos)
++{
++ struct ctl_table ipc_table;
++ size_t lenp_bef = *lenp;
++ int rc;
++
++ memcpy(&ipc_table, table, sizeof(ipc_table));
++ ipc_table.data = get_ipc(table);
++
++ rc = proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos);
++
++ if (write && !rc && lenp_bef == *lenp)
++ tunable_set_callback(*((int *)(ipc_table.data)));
++
++ return rc;
++}
++
+ static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
+ struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos)
+ {
+@@ -49,6 +90,7 @@ static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
+ #else
+ #define proc_ipc_doulongvec_minmax NULL
+ #define proc_ipc_dointvec NULL
++#define proc_ipc_callback_dointvec NULL
+ #endif
+
+ #ifdef CONFIG_SYSCTL_SYSCALL
+@@ -90,8 +132,30 @@ static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
+ }
+ return 1;
+ }
++
++static int sysctl_ipc_registered_data(ctl_table *table, int __user *name,
++ int nlen, void __user *oldval, size_t __user *oldlenp,
++ void __user *newval, size_t newlen)
++{
++ int rc;
++
++ rc = sysctl_ipc_data(table, name, nlen, oldval, oldlenp, newval,
++ newlen);
++
++ if (newval && newlen && rc > 0) {
++ /*
++ * Tunable has successfully been changed from userland
++ */
++ int *data = get_ipc(table);
++
++ tunable_set_callback(*data);
++ }
++
++ return rc;
++}
+ #else
+ #define sysctl_ipc_data NULL
++#define sysctl_ipc_registered_data NULL
+ #endif
+
+ static struct ctl_table ipc_kern_table[] = {
+@@ -137,8 +201,8 @@ static struct ctl_table ipc_kern_table[] = {
+ .data = &init_ipc_ns.msg_ctlmni,
+ .maxlen = sizeof (init_ipc_ns.msg_ctlmni),
+ .mode = 0644,
+- .proc_handler = proc_ipc_dointvec,
+- .strategy = sysctl_ipc_data,
++ .proc_handler = proc_ipc_callback_dointvec,
++ .strategy = sysctl_ipc_registered_data,
+ },
+ {
+ .ctl_name = KERN_MSGMNB,
+diff --git a/ipc/ipcns_notifier.c b/ipc/ipcns_notifier.c
+new file mode 100644
+index 0000000..70ff091
+--- /dev/null
++++ b/ipc/ipcns_notifier.c
+@@ -0,0 +1,82 @@
++/*
++ * linux/ipc/ipcns_notifier.c
++ * Copyright (C) 2007 BULL SA. Nadia Derbey
++ *
++ * Notification mechanism for ipc namespaces:
++ * The callback routine registered in the memory chain invokes the ipcns
++ * notifier chain with the IPCNS_MEMCHANGED event.
++ * Each callback routine registered in the ipcns namespace recomputes msgmni
++ * for the owning namespace.
++ */
++
++#include <linux/msg.h>
++#include <linux/rcupdate.h>
++#include <linux/notifier.h>
++#include <linux/nsproxy.h>
++#include <linux/ipc_namespace.h>
++
++#include "util.h"
++
++
++
++static BLOCKING_NOTIFIER_HEAD(ipcns_chain);
++
++
++static int ipcns_callback(struct notifier_block *self,
++ unsigned long action, void *arg)
++{
++ struct ipc_namespace *ns;
++
++ switch (action) {
++ case IPCNS_MEMCHANGED: /* amount of lowmem has changed */
++ case IPCNS_CREATED:
++ case IPCNS_REMOVED:
++ /*
++ * It's time to recompute msgmni
++ */
++ ns = container_of(self, struct ipc_namespace, ipcns_nb);
++ /*
++ * No need to get a reference on the ns: the 1st job of
++ * free_ipc_ns() is to unregister the callback routine.
++ * blocking_notifier_chain_unregister takes the wr lock to do
++ * it.
++ * When this callback routine is called the rd lock is held by
++ * blocking_notifier_call_chain.
++ * So the ipc ns cannot be freed while we are here.
++ */
++ recompute_msgmni(ns);
++ break;
++ default:
++ break;
++ }
++
++ return NOTIFY_OK;
++}
++
++int register_ipcns_notifier(struct ipc_namespace *ns)
++{
++ memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb));
++ ns->ipcns_nb.notifier_call = ipcns_callback;
++ ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI;
++ return blocking_notifier_chain_register(&ipcns_chain, &ns->ipcns_nb);
++}
++
++int cond_register_ipcns_notifier(struct ipc_namespace *ns)
++{
++ memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb));
++ ns->ipcns_nb.notifier_call = ipcns_callback;
++ ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI;
++ return blocking_notifier_chain_cond_register(&ipcns_chain,
++ &ns->ipcns_nb);
++}
++
++int unregister_ipcns_notifier(struct ipc_namespace *ns)
++{
++ return blocking_notifier_chain_unregister(&ipcns_chain,
++ &ns->ipcns_nb);
++}
++
++int ipcns_notify(unsigned long val)
++{
++ return blocking_notifier_call_chain(&ipcns_chain, val, NULL);
++}
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 60f7a27..94fd3b0 100644
--- a/ipc/mqueue.c
@@ -830604,11 +1112199,1213 @@
out_err:
dput(dentry);
+diff --git a/ipc/msg.c b/ipc/msg.c
+index 46585a0..32494e8 100644
+--- a/ipc/msg.c
++++ b/ipc/msg.c
+@@ -27,6 +27,7 @@
+ #include <linux/msg.h>
+ #include <linux/spinlock.h>
+ #include <linux/init.h>
++#include <linux/mm.h>
+ #include <linux/proc_fs.h>
+ #include <linux/list.h>
+ #include <linux/security.h>
+@@ -70,7 +71,6 @@ struct msg_sender {
+ #define msg_ids(ns) ((ns)->ids[IPC_MSG_IDS])
+
+ #define msg_unlock(msq) ipc_unlock(&(msq)->q_perm)
+-#define msg_buildid(id, seq) ipc_buildid(id, seq)
+
+ static void freeque(struct ipc_namespace *, struct kern_ipc_perm *);
+ static int newque(struct ipc_namespace *, struct ipc_params *);
+@@ -78,11 +78,49 @@ static int newque(struct ipc_namespace *, struct ipc_params *);
+ static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
+ #endif
+
++/*
++ * Scale msgmni with the available lowmem size: the memory dedicated to msg
++ * queues should occupy at most 1/MSG_MEM_SCALE of lowmem.
++ * Also take into account the number of nsproxies created so far.
++ * This should be done staying within the (MSGMNI , IPCMNI/nr_ipc_ns) range.
++ */
++void recompute_msgmni(struct ipc_namespace *ns)
++{
++ struct sysinfo i;
++ unsigned long allowed;
++ int nb_ns;
++
++ si_meminfo(&i);
++ allowed = (((i.totalram - i.totalhigh) / MSG_MEM_SCALE) * i.mem_unit)
++ / MSGMNB;
++ nb_ns = atomic_read(&nr_ipc_ns);
++ allowed /= nb_ns;
++
++ if (allowed < MSGMNI) {
++ ns->msg_ctlmni = MSGMNI;
++ goto out_callback;
++ }
++
++ if (allowed > IPCMNI / nb_ns) {
++ ns->msg_ctlmni = IPCMNI / nb_ns;
++ goto out_callback;
++ }
++
++ ns->msg_ctlmni = allowed;
++
++out_callback:
++
++ printk(KERN_INFO "msgmni has been set to %d for ipc namespace %p\n",
++ ns->msg_ctlmni, ns);
++}
++
+ void msg_init_ns(struct ipc_namespace *ns)
+ {
+ ns->msg_ctlmax = MSGMAX;
+ ns->msg_ctlmnb = MSGMNB;
+- ns->msg_ctlmni = MSGMNI;
++
++ recompute_msgmni(ns);
++
+ atomic_set(&ns->msg_bytes, 0);
+ atomic_set(&ns->msg_hdrs, 0);
+ ipc_init_ids(&ns->ids[IPC_MSG_IDS]);
+@@ -104,21 +142,6 @@ void __init msg_init(void)
+ }
+
+ /*
+- * This routine is called in the paths where the rw_mutex is held to protect
+- * access to the idr tree.
+- */
+-static inline struct msg_queue *msg_lock_check_down(struct ipc_namespace *ns,
+- int id)
+-{
+- struct kern_ipc_perm *ipcp = ipc_lock_check_down(&msg_ids(ns), id);
+-
+- if (IS_ERR(ipcp))
+- return (struct msg_queue *)ipcp;
+-
+- return container_of(ipcp, struct msg_queue, q_perm);
+-}
+-
+-/*
+ * msg_lock_(check_) routines are called in the paths where the rw_mutex
+ * is not held.
+ */
+@@ -186,7 +209,6 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
+ return id;
+ }
+
+- msq->q_perm.id = msg_buildid(id, msq->q_perm.seq);
+ msq->q_stime = msq->q_rtime = 0;
+ msq->q_ctime = get_seconds();
+ msq->q_cbytes = msq->q_qnum = 0;
+@@ -324,19 +346,19 @@ copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version)
+ out.msg_rtime = in->msg_rtime;
+ out.msg_ctime = in->msg_ctime;
+
+- if (in->msg_cbytes > USHRT_MAX)
+- out.msg_cbytes = USHRT_MAX;
++ if (in->msg_cbytes > USHORT_MAX)
++ out.msg_cbytes = USHORT_MAX;
+ else
+ out.msg_cbytes = in->msg_cbytes;
+ out.msg_lcbytes = in->msg_cbytes;
+
+- if (in->msg_qnum > USHRT_MAX)
+- out.msg_qnum = USHRT_MAX;
++ if (in->msg_qnum > USHORT_MAX)
++ out.msg_qnum = USHORT_MAX;
+ else
+ out.msg_qnum = in->msg_qnum;
+
+- if (in->msg_qbytes > USHRT_MAX)
+- out.msg_qbytes = USHRT_MAX;
++ if (in->msg_qbytes > USHORT_MAX)
++ out.msg_qbytes = USHORT_MAX;
+ else
+ out.msg_qbytes = in->msg_qbytes;
+ out.msg_lqbytes = in->msg_qbytes;
+@@ -351,31 +373,14 @@ copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version)
+ }
+ }
+
+-struct msq_setbuf {
+- unsigned long qbytes;
+- uid_t uid;
+- gid_t gid;
+- mode_t mode;
+-};
+-
+ static inline unsigned long
+-copy_msqid_from_user(struct msq_setbuf *out, void __user *buf, int version)
++copy_msqid_from_user(struct msqid64_ds *out, void __user *buf, int version)
+ {
+ switch(version) {
+ case IPC_64:
+- {
+- struct msqid64_ds tbuf;
+-
+- if (copy_from_user(&tbuf, buf, sizeof(tbuf)))
++ if (copy_from_user(out, buf, sizeof(*out)))
+ return -EFAULT;
+-
+- out->qbytes = tbuf.msg_qbytes;
+- out->uid = tbuf.msg_perm.uid;
+- out->gid = tbuf.msg_perm.gid;
+- out->mode = tbuf.msg_perm.mode;
+-
+ return 0;
+- }
+ case IPC_OLD:
+ {
+ struct msqid_ds tbuf_old;
+@@ -383,14 +388,14 @@ copy_msqid_from_user(struct msq_setbuf *out, void __user *buf, int version)
+ if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
+ return -EFAULT;
+
+- out->uid = tbuf_old.msg_perm.uid;
+- out->gid = tbuf_old.msg_perm.gid;
+- out->mode = tbuf_old.msg_perm.mode;
++ out->msg_perm.uid = tbuf_old.msg_perm.uid;
++ out->msg_perm.gid = tbuf_old.msg_perm.gid;
++ out->msg_perm.mode = tbuf_old.msg_perm.mode;
+
+ if (tbuf_old.msg_qbytes == 0)
+- out->qbytes = tbuf_old.msg_lqbytes;
++ out->msg_qbytes = tbuf_old.msg_lqbytes;
+ else
+- out->qbytes = tbuf_old.msg_qbytes;
++ out->msg_qbytes = tbuf_old.msg_qbytes;
+
+ return 0;
+ }
+@@ -399,10 +404,71 @@ copy_msqid_from_user(struct msq_setbuf *out, void __user *buf, int version)
+ }
+ }
+
+-asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
++/*
++ * This function handles some msgctl commands which require the rw_mutex
++ * to be held in write mode.
++ * NOTE: no locks must be held, the rw_mutex is taken inside this function.
++ */
++static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
++ struct msqid_ds __user *buf, int version)
+ {
+ struct kern_ipc_perm *ipcp;
+- struct msq_setbuf uninitialized_var(setbuf);
++ struct msqid64_ds msqid64;
++ struct msg_queue *msq;
++ int err;
++
++ if (cmd == IPC_SET) {
++ if (copy_msqid_from_user(&msqid64, buf, version))
++ return -EFAULT;
++ }
++
++ ipcp = ipcctl_pre_down(&msg_ids(ns), msqid, cmd,
++ &msqid64.msg_perm, msqid64.msg_qbytes);
++ if (IS_ERR(ipcp))
++ return PTR_ERR(ipcp);
++
++ msq = container_of(ipcp, struct msg_queue, q_perm);
++
++ err = security_msg_queue_msgctl(msq, cmd);
++ if (err)
++ goto out_unlock;
++
++ switch (cmd) {
++ case IPC_RMID:
++ freeque(ns, ipcp);
++ goto out_up;
++ case IPC_SET:
++ if (msqid64.msg_qbytes > ns->msg_ctlmnb &&
++ !capable(CAP_SYS_RESOURCE)) {
++ err = -EPERM;
++ goto out_unlock;
++ }
++
++ msq->q_qbytes = msqid64.msg_qbytes;
++
++ ipc_update_perm(&msqid64.msg_perm, ipcp);
++ msq->q_ctime = get_seconds();
++ /* sleeping receivers might be excluded by
++ * stricter permissions.
++ */
++ expunge_all(msq, -EAGAIN);
++ /* sleeping senders might be able to send
++ * due to a larger queue size.
++ */
++ ss_wakeup(&msq->q_senders, 0);
++ break;
++ default:
++ err = -EINVAL;
++ }
++out_unlock:
++ msg_unlock(msq);
++out_up:
++ up_write(&msg_ids(ns).rw_mutex);
++ return err;
++}
++
++asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
++{
+ struct msg_queue *msq;
+ int err, version;
+ struct ipc_namespace *ns;
+@@ -498,82 +564,13 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
+ return success_return;
+ }
+ case IPC_SET:
+- if (!buf)
+- return -EFAULT;
+- if (copy_msqid_from_user(&setbuf, buf, version))
+- return -EFAULT;
+- break;
+ case IPC_RMID:
+- break;
++ err = msgctl_down(ns, msqid, cmd, buf, version);
++ return err;
+ default:
+ return -EINVAL;
+ }
+
+- down_write(&msg_ids(ns).rw_mutex);
+- msq = msg_lock_check_down(ns, msqid);
+- if (IS_ERR(msq)) {
+- err = PTR_ERR(msq);
+- goto out_up;
+- }
+-
+- ipcp = &msq->q_perm;
+-
+- err = audit_ipc_obj(ipcp);
+- if (err)
+- goto out_unlock_up;
+- if (cmd == IPC_SET) {
+- err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid,
+- setbuf.mode);
+- if (err)
+- goto out_unlock_up;
+- }
+-
+- err = -EPERM;
+- if (current->euid != ipcp->cuid &&
+- current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
+- /* We _could_ check for CAP_CHOWN above, but we don't */
+- goto out_unlock_up;
+-
+- err = security_msg_queue_msgctl(msq, cmd);
+- if (err)
+- goto out_unlock_up;
+-
+- switch (cmd) {
+- case IPC_SET:
+- {
+- err = -EPERM;
+- if (setbuf.qbytes > ns->msg_ctlmnb && !capable(CAP_SYS_RESOURCE))
+- goto out_unlock_up;
+-
+- msq->q_qbytes = setbuf.qbytes;
+-
+- ipcp->uid = setbuf.uid;
+- ipcp->gid = setbuf.gid;
+- ipcp->mode = (ipcp->mode & ~S_IRWXUGO) |
+- (S_IRWXUGO & setbuf.mode);
+- msq->q_ctime = get_seconds();
+- /* sleeping receivers might be excluded by
+- * stricter permissions.
+- */
+- expunge_all(msq, -EAGAIN);
+- /* sleeping senders might be able to send
+- * due to a larger queue size.
+- */
+- ss_wakeup(&msq->q_senders, 0);
+- msg_unlock(msq);
+- break;
+- }
+- case IPC_RMID:
+- freeque(ns, &msq->q_perm);
+- break;
+- }
+- err = 0;
+-out_up:
+- up_write(&msg_ids(ns).rw_mutex);
+- return err;
+-out_unlock_up:
+- msg_unlock(msq);
+- goto out_up;
+ out_unlock:
+ msg_unlock(msq);
+ return err;
+diff --git a/ipc/namespace.c b/ipc/namespace.c
+index 1b96765..9171d94 100644
+--- a/ipc/namespace.c
++++ b/ipc/namespace.c
+@@ -20,10 +20,20 @@ static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns)
+ if (ns == NULL)
+ return ERR_PTR(-ENOMEM);
+
++ atomic_inc(&nr_ipc_ns);
++
+ sem_init_ns(ns);
+ msg_init_ns(ns);
+ shm_init_ns(ns);
+
++ /*
++ * msgmni has already been computed for the new ipc ns.
++ * Thus, do the ipcns creation notification before registering that
++ * new ipcns in the chain.
++ */
++ ipcns_notify(IPCNS_CREATED);
++ register_ipcns_notifier(ns);
++
+ kref_init(&ns->kref);
+ return ns;
+ }
+@@ -79,8 +89,24 @@ void free_ipc_ns(struct kref *kref)
+ struct ipc_namespace *ns;
+
+ ns = container_of(kref, struct ipc_namespace, kref);
++ /*
++ * Unregistering the hotplug notifier at the beginning guarantees
++ * that the ipc namespace won't be freed while we are inside the
++ * callback routine. Since the blocking_notifier_chain_XXX routines
++ * hold a rw lock on the notifier list, unregister_ipcns_notifier()
++ * won't take the rw lock before blocking_notifier_call_chain() has
++ * released the rd lock.
++ */
++ unregister_ipcns_notifier(ns);
+ sem_exit_ns(ns);
+ msg_exit_ns(ns);
+ shm_exit_ns(ns);
+ kfree(ns);
++ atomic_dec(&nr_ipc_ns);
++
++ /*
++ * Do the ipcns removal notification after decrementing nr_ipc_ns in
++ * order to have a correct value when recomputing msgmni.
++ */
++ ipcns_notify(IPCNS_REMOVED);
+ }
+diff --git a/ipc/sem.c b/ipc/sem.c
+index 0b45a4d..e9418df 100644
+--- a/ipc/sem.c
++++ b/ipc/sem.c
+@@ -91,7 +91,6 @@
+
+ #define sem_unlock(sma) ipc_unlock(&(sma)->sem_perm)
+ #define sem_checkid(sma, semid) ipc_checkid(&sma->sem_perm, semid)
+-#define sem_buildid(id, seq) ipc_buildid(id, seq)
+
+ static int newary(struct ipc_namespace *, struct ipc_params *);
+ static void freeary(struct ipc_namespace *, struct kern_ipc_perm *);
+@@ -142,21 +141,6 @@ void __init sem_init (void)
+ }
+
+ /*
+- * This routine is called in the paths where the rw_mutex is held to protect
+- * access to the idr tree.
+- */
+-static inline struct sem_array *sem_lock_check_down(struct ipc_namespace *ns,
+- int id)
+-{
+- struct kern_ipc_perm *ipcp = ipc_lock_check_down(&sem_ids(ns), id);
+-
+- if (IS_ERR(ipcp))
+- return (struct sem_array *)ipcp;
+-
+- return container_of(ipcp, struct sem_array, sem_perm);
+-}
+-
+-/*
+ * sem_lock_(check_) routines are called in the paths where the rw_mutex
+ * is not held.
+ */
+@@ -181,6 +165,25 @@ static inline struct sem_array *sem_lock_check(struct ipc_namespace *ns,
+ return container_of(ipcp, struct sem_array, sem_perm);
+ }
+
++static inline void sem_lock_and_putref(struct sem_array *sma)
++{
++ ipc_lock_by_ptr(&sma->sem_perm);
++ ipc_rcu_putref(sma);
++}
++
++static inline void sem_getref_and_unlock(struct sem_array *sma)
++{
++ ipc_rcu_getref(sma);
++ ipc_unlock(&(sma)->sem_perm);
++}
++
++static inline void sem_putref(struct sem_array *sma)
++{
++ ipc_lock_by_ptr(&sma->sem_perm);
++ ipc_rcu_putref(sma);
++ ipc_unlock(&(sma)->sem_perm);
++}
++
+ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
+ {
+ ipc_rmid(&sem_ids(ns), &s->sem_perm);
+@@ -268,7 +271,6 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
+ }
+ ns->used_sems += nsems;
+
+- sma->sem_perm.id = sem_buildid(id, sma->sem_perm.seq);
+ sma->sem_base = (struct sem *) &sma[1];
+ /* sma->sem_pending = NULL; */
+ sma->sem_pending_last = &sma->sem_pending;
+@@ -700,19 +702,15 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
+ int i;
+
+ if(nsems > SEMMSL_FAST) {
+- ipc_rcu_getref(sma);
+- sem_unlock(sma);
++ sem_getref_and_unlock(sma);
+
+ sem_io = ipc_alloc(sizeof(ushort)*nsems);
+ if(sem_io == NULL) {
+- ipc_lock_by_ptr(&sma->sem_perm);
+- ipc_rcu_putref(sma);
+- sem_unlock(sma);
++ sem_putref(sma);
+ return -ENOMEM;
+ }
+
+- ipc_lock_by_ptr(&sma->sem_perm);
+- ipc_rcu_putref(sma);
++ sem_lock_and_putref(sma);
+ if (sma->sem_perm.deleted) {
+ sem_unlock(sma);
+ err = -EIDRM;
+@@ -733,38 +731,30 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
+ int i;
+ struct sem_undo *un;
+
+- ipc_rcu_getref(sma);
+- sem_unlock(sma);
++ sem_getref_and_unlock(sma);
+
+ if(nsems > SEMMSL_FAST) {
+ sem_io = ipc_alloc(sizeof(ushort)*nsems);
+ if(sem_io == NULL) {
+- ipc_lock_by_ptr(&sma->sem_perm);
+- ipc_rcu_putref(sma);
+- sem_unlock(sma);
++ sem_putref(sma);
+ return -ENOMEM;
+ }
+ }
+
+ if (copy_from_user (sem_io, arg.array, nsems*sizeof(ushort))) {
+- ipc_lock_by_ptr(&sma->sem_perm);
+- ipc_rcu_putref(sma);
+- sem_unlock(sma);
++ sem_putref(sma);
+ err = -EFAULT;
+ goto out_free;
+ }
+
+ for (i = 0; i < nsems; i++) {
+ if (sem_io[i] > SEMVMX) {
+- ipc_lock_by_ptr(&sma->sem_perm);
+- ipc_rcu_putref(sma);
+- sem_unlock(sma);
++ sem_putref(sma);
+ err = -ERANGE;
+ goto out_free;
+ }
+ }
+- ipc_lock_by_ptr(&sma->sem_perm);
+- ipc_rcu_putref(sma);
++ sem_lock_and_putref(sma);
+ if (sma->sem_perm.deleted) {
+ sem_unlock(sma);
+ err = -EIDRM;
+@@ -830,28 +820,14 @@ out_free:
+ return err;
+ }
+
+-struct sem_setbuf {
+- uid_t uid;
+- gid_t gid;
+- mode_t mode;
+-};
+-
+-static inline unsigned long copy_semid_from_user(struct sem_setbuf *out, void __user *buf, int version)
++static inline unsigned long
++copy_semid_from_user(struct semid64_ds *out, void __user *buf, int version)
+ {
+ switch(version) {
+ case IPC_64:
+- {
+- struct semid64_ds tbuf;
+-
+- if(copy_from_user(&tbuf, buf, sizeof(tbuf)))
++ if (copy_from_user(out, buf, sizeof(*out)))
+ return -EFAULT;
+-
+- out->uid = tbuf.sem_perm.uid;
+- out->gid = tbuf.sem_perm.gid;
+- out->mode = tbuf.sem_perm.mode;
+-
+ return 0;
+- }
+ case IPC_OLD:
+ {
+ struct semid_ds tbuf_old;
+@@ -859,9 +835,9 @@ static inline unsigned long copy_semid_from_user(struct sem_setbuf *out, void __
+ if(copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
+ return -EFAULT;
+
+- out->uid = tbuf_old.sem_perm.uid;
+- out->gid = tbuf_old.sem_perm.gid;
+- out->mode = tbuf_old.sem_perm.mode;
++ out->sem_perm.uid = tbuf_old.sem_perm.uid;
++ out->sem_perm.gid = tbuf_old.sem_perm.gid;
++ out->sem_perm.mode = tbuf_old.sem_perm.mode;
+
+ return 0;
+ }
+@@ -870,38 +846,29 @@ static inline unsigned long copy_semid_from_user(struct sem_setbuf *out, void __
+ }
+ }
+
+-static int semctl_down(struct ipc_namespace *ns, int semid, int semnum,
+- int cmd, int version, union semun arg)
++/*
++ * This function handles some semctl commands which require the rw_mutex
++ * to be held in write mode.
++ * NOTE: no locks must be held, the rw_mutex is taken inside this function.
++ */
++static int semctl_down(struct ipc_namespace *ns, int semid,
++ int cmd, int version, union semun arg)
+ {
+ struct sem_array *sma;
+ int err;
+- struct sem_setbuf uninitialized_var(setbuf);
++ struct semid64_ds semid64;
+ struct kern_ipc_perm *ipcp;
+
+ if(cmd == IPC_SET) {
+- if(copy_semid_from_user (&setbuf, arg.buf, version))
++ if (copy_semid_from_user(&semid64, arg.buf, version))
+ return -EFAULT;
+ }
+- sma = sem_lock_check_down(ns, semid);
+- if (IS_ERR(sma))
+- return PTR_ERR(sma);
+
+- ipcp = &sma->sem_perm;
+-
+- err = audit_ipc_obj(ipcp);
+- if (err)
+- goto out_unlock;
++ ipcp = ipcctl_pre_down(&sem_ids(ns), semid, cmd, &semid64.sem_perm, 0);
++ if (IS_ERR(ipcp))
++ return PTR_ERR(ipcp);
+
+- if (cmd == IPC_SET) {
+- err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode);
+- if (err)
+- goto out_unlock;
+- }
+- if (current->euid != ipcp->cuid &&
+- current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
+- err=-EPERM;
+- goto out_unlock;
+- }
++ sma = container_of(ipcp, struct sem_array, sem_perm);
+
+ err = security_sem_semctl(sma, cmd);
+ if (err)
+@@ -910,26 +877,19 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum,
+ switch(cmd){
+ case IPC_RMID:
+ freeary(ns, ipcp);
+- err = 0;
+- break;
++ goto out_up;
+ case IPC_SET:
+- ipcp->uid = setbuf.uid;
+- ipcp->gid = setbuf.gid;
+- ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
+- | (setbuf.mode & S_IRWXUGO);
++ ipc_update_perm(&semid64.sem_perm, ipcp);
+ sma->sem_ctime = get_seconds();
+- sem_unlock(sma);
+- err = 0;
+ break;
+ default:
+- sem_unlock(sma);
+ err = -EINVAL;
+- break;
+ }
+- return err;
+
+ out_unlock:
+ sem_unlock(sma);
++out_up:
++ up_write(&sem_ids(ns).rw_mutex);
+ return err;
+ }
+
+@@ -963,9 +923,7 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
+ return err;
+ case IPC_RMID:
+ case IPC_SET:
+- down_write(&sem_ids(ns).rw_mutex);
+- err = semctl_down(ns,semid,semnum,cmd,version,arg);
+- up_write(&sem_ids(ns).rw_mutex);
++ err = semctl_down(ns, semid, cmd, version, arg);
+ return err;
+ default:
+ return -EINVAL;
+@@ -1044,14 +1002,11 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
+ return ERR_PTR(PTR_ERR(sma));
+
+ nsems = sma->sem_nsems;
+- ipc_rcu_getref(sma);
+- sem_unlock(sma);
++ sem_getref_and_unlock(sma);
+
+ new = kzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL);
+ if (!new) {
+- ipc_lock_by_ptr(&sma->sem_perm);
+- ipc_rcu_putref(sma);
+- sem_unlock(sma);
++ sem_putref(sma);
+ return ERR_PTR(-ENOMEM);
+ }
+ new->semadj = (short *) &new[1];
+@@ -1062,13 +1017,10 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
+ if (un) {
+ spin_unlock(&ulp->lock);
+ kfree(new);
+- ipc_lock_by_ptr(&sma->sem_perm);
+- ipc_rcu_putref(sma);
+- sem_unlock(sma);
++ sem_putref(sma);
+ goto out;
+ }
+- ipc_lock_by_ptr(&sma->sem_perm);
+- ipc_rcu_putref(sma);
++ sem_lock_and_putref(sma);
+ if (sma->sem_perm.deleted) {
+ sem_unlock(sma);
+ spin_unlock(&ulp->lock);
+@@ -1298,6 +1250,7 @@ void exit_sem(struct task_struct *tsk)
+ undo_list = tsk->sysvsem.undo_list;
+ if (!undo_list)
+ return;
++ tsk->sysvsem.undo_list = NULL;
+
+ if (!atomic_dec_and_test(&undo_list->refcnt))
+ return;
+diff --git a/ipc/shm.c b/ipc/shm.c
+index cc63fae..554429a 100644
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -60,7 +60,6 @@ static struct vm_operations_struct shm_vm_ops;
+
+ #define shm_unlock(shp) \
+ ipc_unlock(&(shp)->shm_perm)
+-#define shm_buildid(id, seq) ipc_buildid(id, seq)
+
+ static int newseg(struct ipc_namespace *, struct ipc_params *);
+ static void shm_open(struct vm_area_struct *vma);
+@@ -127,18 +126,6 @@ static inline struct shmid_kernel *shm_lock_down(struct ipc_namespace *ns,
+ return container_of(ipcp, struct shmid_kernel, shm_perm);
+ }
+
+-static inline struct shmid_kernel *shm_lock_check_down(
+- struct ipc_namespace *ns,
+- int id)
+-{
+- struct kern_ipc_perm *ipcp = ipc_lock_check_down(&shm_ids(ns), id);
+-
+- if (IS_ERR(ipcp))
+- return (struct shmid_kernel *)ipcp;
+-
+- return container_of(ipcp, struct shmid_kernel, shm_perm);
+-}
+-
+ /*
+ * shm_lock_(check_) routines are called in the paths where the rw_mutex
+ * is not held.
+@@ -169,12 +156,6 @@ static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s)
+ ipc_rmid(&shm_ids(ns), &s->shm_perm);
+ }
+
+-static inline int shm_addid(struct ipc_namespace *ns, struct shmid_kernel *shp)
+-{
+- return ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
+-}
+-
+-
+
+ /* This is called by fork, once for every shm attach. */
+ static void shm_open(struct vm_area_struct *vma)
+@@ -271,11 +252,9 @@ static struct mempolicy *shm_get_policy(struct vm_area_struct *vma,
+
+ if (sfd->vm_ops->get_policy)
+ pol = sfd->vm_ops->get_policy(vma, addr);
+- else if (vma->vm_policy) {
++ else if (vma->vm_policy)
+ pol = vma->vm_policy;
+- mpol_get(pol); /* get_vma_policy() expects this */
+- } else
+- pol = current->mempolicy;
++
+ return pol;
+ }
+ #endif
+@@ -418,7 +397,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
+ if (IS_ERR(file))
+ goto no_file;
+
+- id = shm_addid(ns, shp);
++ id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
+ if (id < 0) {
+ error = id;
+ goto no_id;
+@@ -430,7 +409,6 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
+ shp->shm_ctim = get_seconds();
+ shp->shm_segsz = size;
+ shp->shm_nattch = 0;
+- shp->shm_perm.id = shm_buildid(id, shp->shm_perm.seq);
+ shp->shm_file = file;
+ /*
+ * shmid gets reported as "inode#" in /proc/pid/maps.
+@@ -521,28 +499,14 @@ static inline unsigned long copy_shmid_to_user(void __user *buf, struct shmid64_
+ }
+ }
+
+-struct shm_setbuf {
+- uid_t uid;
+- gid_t gid;
+- mode_t mode;
+-};
+-
+-static inline unsigned long copy_shmid_from_user(struct shm_setbuf *out, void __user *buf, int version)
++static inline unsigned long
++copy_shmid_from_user(struct shmid64_ds *out, void __user *buf, int version)
+ {
+ switch(version) {
+ case IPC_64:
+- {
+- struct shmid64_ds tbuf;
+-
+- if (copy_from_user(&tbuf, buf, sizeof(tbuf)))
++ if (copy_from_user(out, buf, sizeof(*out)))
+ return -EFAULT;
+-
+- out->uid = tbuf.shm_perm.uid;
+- out->gid = tbuf.shm_perm.gid;
+- out->mode = tbuf.shm_perm.mode;
+-
+ return 0;
+- }
+ case IPC_OLD:
+ {
+ struct shmid_ds tbuf_old;
+@@ -550,9 +514,9 @@ static inline unsigned long copy_shmid_from_user(struct shm_setbuf *out, void __
+ if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
+ return -EFAULT;
+
+- out->uid = tbuf_old.shm_perm.uid;
+- out->gid = tbuf_old.shm_perm.gid;
+- out->mode = tbuf_old.shm_perm.mode;
++ out->shm_perm.uid = tbuf_old.shm_perm.uid;
++ out->shm_perm.gid = tbuf_old.shm_perm.gid;
++ out->shm_perm.mode = tbuf_old.shm_perm.mode;
+
+ return 0;
+ }
+@@ -626,9 +590,53 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
+ }
+ }
+
+-asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
++/*
++ * This function handles some shmctl commands which require the rw_mutex
++ * to be held in write mode.
++ * NOTE: no locks must be held, the rw_mutex is taken inside this function.
++ */
++static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
++ struct shmid_ds __user *buf, int version)
++{
++ struct kern_ipc_perm *ipcp;
++ struct shmid64_ds shmid64;
++ struct shmid_kernel *shp;
++ int err;
++
++ if (cmd == IPC_SET) {
++ if (copy_shmid_from_user(&shmid64, buf, version))
++ return -EFAULT;
++ }
++
++ ipcp = ipcctl_pre_down(&shm_ids(ns), shmid, cmd, &shmid64.shm_perm, 0);
++ if (IS_ERR(ipcp))
++ return PTR_ERR(ipcp);
++
++ shp = container_of(ipcp, struct shmid_kernel, shm_perm);
++
++ err = security_shm_shmctl(shp, cmd);
++ if (err)
++ goto out_unlock;
++ switch (cmd) {
++ case IPC_RMID:
++ do_shm_rmid(ns, ipcp);
++ goto out_up;
++ case IPC_SET:
++ ipc_update_perm(&shmid64.shm_perm, ipcp);
++ shp->shm_ctim = get_seconds();
++ break;
++ default:
++ err = -EINVAL;
++ }
++out_unlock:
++ shm_unlock(shp);
++out_up:
++ up_write(&shm_ids(ns).rw_mutex);
++ return err;
++}
++
++asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
+ {
+- struct shm_setbuf setbuf;
+ struct shmid_kernel *shp;
+ int err, version;
+ struct ipc_namespace *ns;
+@@ -785,97 +793,13 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
+ goto out;
+ }
+ case IPC_RMID:
+- {
+- /*
+- * We cannot simply remove the file. The SVID states
+- * that the block remains until the last person
+- * detaches from it, then is deleted. A shmat() on
+- * an RMID segment is legal in older Linux and if
+- * we change it apps break...
+- *
+- * Instead we set a destroyed flag, and then blow
+- * the name away when the usage hits zero.
+- */
+- down_write(&shm_ids(ns).rw_mutex);
+- shp = shm_lock_check_down(ns, shmid);
+- if (IS_ERR(shp)) {
+- err = PTR_ERR(shp);
+- goto out_up;
+- }
+-
+- err = audit_ipc_obj(&(shp->shm_perm));
+- if (err)
+- goto out_unlock_up;
+-
+- if (current->euid != shp->shm_perm.uid &&
+- current->euid != shp->shm_perm.cuid &&
+- !capable(CAP_SYS_ADMIN)) {
+- err=-EPERM;
+- goto out_unlock_up;
+- }
+-
+- err = security_shm_shmctl(shp, cmd);
+- if (err)
+- goto out_unlock_up;
+-
+- do_shm_rmid(ns, &shp->shm_perm);
+- up_write(&shm_ids(ns).rw_mutex);
+- goto out;
+- }
+-
+ case IPC_SET:
+- {
+- if (!buf) {
+- err = -EFAULT;
+- goto out;
+- }
+-
+- if (copy_shmid_from_user (&setbuf, buf, version)) {
+- err = -EFAULT;
+- goto out;
+- }
+- down_write(&shm_ids(ns).rw_mutex);
+- shp = shm_lock_check_down(ns, shmid);
+- if (IS_ERR(shp)) {
+- err = PTR_ERR(shp);
+- goto out_up;
+- }
+- err = audit_ipc_obj(&(shp->shm_perm));
+- if (err)
+- goto out_unlock_up;
+- err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode);
+- if (err)
+- goto out_unlock_up;
+- err=-EPERM;
+- if (current->euid != shp->shm_perm.uid &&
+- current->euid != shp->shm_perm.cuid &&
+- !capable(CAP_SYS_ADMIN)) {
+- goto out_unlock_up;
+- }
+-
+- err = security_shm_shmctl(shp, cmd);
+- if (err)
+- goto out_unlock_up;
+-
+- shp->shm_perm.uid = setbuf.uid;
+- shp->shm_perm.gid = setbuf.gid;
+- shp->shm_perm.mode = (shp->shm_perm.mode & ~S_IRWXUGO)
+- | (setbuf.mode & S_IRWXUGO);
+- shp->shm_ctim = get_seconds();
+- break;
+- }
+-
++ err = shmctl_down(ns, shmid, cmd, buf, version);
++ return err;
+ default:
+- err = -EINVAL;
+- goto out;
++ return -EINVAL;
+ }
+
+- err = 0;
+-out_unlock_up:
+- shm_unlock(shp);
+-out_up:
+- up_write(&shm_ids(ns).rw_mutex);
+- goto out;
+ out_unlock:
+ shm_unlock(shp);
+ out:
+diff --git a/ipc/util.c b/ipc/util.c
+index fd1b50d..3339177 100644
+--- a/ipc/util.c
++++ b/ipc/util.c
+@@ -33,6 +33,7 @@
+ #include <linux/audit.h>
+ #include <linux/nsproxy.h>
+ #include <linux/rwsem.h>
++#include <linux/memory.h>
+ #include <linux/ipc_namespace.h>
+
+ #include <asm/unistd.h>
+@@ -52,11 +53,57 @@ struct ipc_namespace init_ipc_ns = {
+ },
+ };
+
++atomic_t nr_ipc_ns = ATOMIC_INIT(1);
++
++
++#ifdef CONFIG_MEMORY_HOTPLUG
++
++static void ipc_memory_notifier(struct work_struct *work)
++{
++ ipcns_notify(IPCNS_MEMCHANGED);
++}
++
++static DECLARE_WORK(ipc_memory_wq, ipc_memory_notifier);
++
++
++static int ipc_memory_callback(struct notifier_block *self,
++ unsigned long action, void *arg)
++{
++ switch (action) {
++ case MEM_ONLINE: /* memory successfully brought online */
++ case MEM_OFFLINE: /* or offline: it's time to recompute msgmni */
++ /*
++ * This is done by invoking the ipcns notifier chain with the
++ * IPC_MEMCHANGED event.
++ * In order not to keep the lock on the hotplug memory chain
++ * for too long, queue a work item that will, when waken up,
++ * activate the ipcns notification chain.
++ * No need to keep several ipc work items on the queue.
++ */
++ if (!work_pending(&ipc_memory_wq))
++ schedule_work(&ipc_memory_wq);
++ break;
++ case MEM_GOING_ONLINE:
++ case MEM_GOING_OFFLINE:
++ case MEM_CANCEL_ONLINE:
++ case MEM_CANCEL_OFFLINE:
++ default:
++ break;
++ }
++
++ return NOTIFY_OK;
++}
++
++#endif /* CONFIG_MEMORY_HOTPLUG */
++
+ /**
+ * ipc_init - initialise IPC subsystem
+ *
+ * The various system5 IPC resources (semaphores, messages and shared
+ * memory) are initialised
++ * A callback routine is registered into the memory hotplug notifier
++ * chain: since msgmni scales to lowmem this callback routine will be
++ * called upon successful memory add / remove to recompute msmgni.
+ */
+
+ static int __init ipc_init(void)
+@@ -64,6 +111,8 @@ static int __init ipc_init(void)
+ sem_init();
+ msg_init();
+ shm_init();
++ hotplug_memory_notifier(ipc_memory_callback, IPC_CALLBACK_PRI);
++ register_ipcns_notifier(&init_ipc_ns);
+ return 0;
+ }
+ __initcall(ipc_init);
+@@ -84,8 +133,8 @@ void ipc_init_ids(struct ipc_ids *ids)
+ ids->seq = 0;
+ {
+ int seq_limit = INT_MAX/SEQ_MULTIPLIER;
+- if(seq_limit > USHRT_MAX)
+- ids->seq_max = USHRT_MAX;
++ if (seq_limit > USHORT_MAX)
++ ids->seq_max = USHORT_MAX;
+ else
+ ids->seq_max = seq_limit;
+ }
+@@ -116,13 +165,12 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
+ iface->ids = ids;
+ iface->show = show;
+
+- pde = create_proc_entry(path,
+- S_IRUGO, /* world readable */
+- NULL /* parent dir */);
+- if (pde) {
+- pde->data = iface;
+- pde->proc_fops = &sysvipc_proc_fops;
+- } else {
++ pde = proc_create_data(path,
++ S_IRUGO, /* world readable */
++ NULL, /* parent dir */
++ &sysvipc_proc_fops,
++ iface);
++ if (!pde) {
+ kfree(iface);
+ }
+ }
+@@ -231,6 +279,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
+ if(ids->seq > ids->seq_max)
+ ids->seq = 0;
+
++ new->id = ipc_buildid(id, new->seq);
+ spin_lock_init(&new->lock);
+ new->deleted = 0;
+ rcu_read_lock();
+@@ -761,6 +810,70 @@ int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
+ return ipcget_public(ns, ids, ops, params);
+ }
+
++/**
++ * ipc_update_perm - update the permissions of an IPC.
++ * @in: the permission given as input.
++ * @out: the permission of the ipc to set.
++ */
++void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
++{
++ out->uid = in->uid;
++ out->gid = in->gid;
++ out->mode = (out->mode & ~S_IRWXUGO)
++ | (in->mode & S_IRWXUGO);
++}
++
++/**
++ * ipcctl_pre_down - retrieve an ipc and check permissions for some IPC_XXX cmd
++ * @ids: the table of ids where to look for the ipc
++ * @id: the id of the ipc to retrieve
++ * @cmd: the cmd to check
++ * @perm: the permission to set
++ * @extra_perm: one extra permission parameter used by msq
++ *
++ * This function does some common audit and permissions check for some IPC_XXX
++ * cmd and is called from semctl_down, shmctl_down and msgctl_down.
++ * It must be called without any lock held and
++ * - retrieves the ipc with the given id in the given table.
++ * - performs some audit and permission check, depending on the given cmd
++ * - returns the ipc with both ipc and rw_mutex locks held in case of success
++ * or an err-code without any lock held otherwise.
++ */
++struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd,
++ struct ipc64_perm *perm, int extra_perm)
++{
++ struct kern_ipc_perm *ipcp;
++ int err;
++
++ down_write(&ids->rw_mutex);
++ ipcp = ipc_lock_check_down(ids, id);
++ if (IS_ERR(ipcp)) {
++ err = PTR_ERR(ipcp);
++ goto out_up;
++ }
++
++ err = audit_ipc_obj(ipcp);
++ if (err)
++ goto out_unlock;
++
++ if (cmd == IPC_SET) {
++ err = audit_ipc_set_perm(extra_perm, perm->uid,
++ perm->gid, perm->mode);
++ if (err)
++ goto out_unlock;
++ }
++ if (current->euid == ipcp->cuid ||
++ current->euid == ipcp->uid || capable(CAP_SYS_ADMIN))
++ return ipcp;
++
++ err = -EPERM;
++out_unlock:
++ ipc_unlock(ipcp);
++out_up:
++ up_write(&ids->rw_mutex);
++ return ERR_PTR(err);
++}
++
+ #ifdef __ARCH_WANT_IPC_PARSE_VERSION
+
+
+diff --git a/ipc/util.h b/ipc/util.h
+index f37d160..cdb966a 100644
+--- a/ipc/util.h
++++ b/ipc/util.h
+@@ -12,7 +12,6 @@
+
+ #include <linux/err.h>
+
+-#define USHRT_MAX 0xffff
+ #define SEQ_MULTIPLIER (IPCMNI)
+
+ void sem_init (void);
+@@ -112,6 +111,9 @@ struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int);
+
+ void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
+ void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out);
++void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out);
++struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd,
++ struct ipc64_perm *perm, int extra_perm);
+
+ #if defined(__ia64__) || defined(__x86_64__) || defined(__hppa__) || defined(__XTENSA__)
+ /* On IA-64, we always use the "64-bit version" of the IPC structures. */
+@@ -124,6 +126,8 @@ extern void free_msg(struct msg_msg *msg);
+ extern struct msg_msg *load_msg(const void __user *src, int len);
+ extern int store_msg(void __user *dest, struct msg_msg *msg, int len);
+
++extern void recompute_msgmni(struct ipc_namespace *);
++
+ static inline int ipc_buildid(int id, int seq)
+ {
+ return SEQ_MULTIPLIER * seq + id;
diff --git a/kernel/Makefile b/kernel/Makefile
-index 6c584c5..6c5f081 100644
+index 6c584c5..188c432 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 \
+@@ -8,10 +8,10 @@ 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 \
@@ -830616,7 +1113413,11 @@
+ hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
notifier.o ksysfs.o pm_qos_params.o
- obj-$(CONFIG_SYSCTL) += sysctl_check.o
+-obj-$(CONFIG_SYSCTL) += sysctl_check.o
++obj-$(CONFIG_SYSCTL_SYSCALL_CHECK) += sysctl_check.o
+ obj-$(CONFIG_STACKTRACE) += stacktrace.o
+ obj-y += time/
+ obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o
@@ -53,6 +53,7 @@ obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
obj-$(CONFIG_AUDIT_TREE) += audit_tree.o
@@ -830626,7 +1113427,7 @@
obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
obj-$(CONFIG_SECCOMP) += seccomp.o
diff --git a/kernel/audit.c b/kernel/audit.c
-index b782b04..a7b1608 100644
+index b782b04..b7d3709 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -21,7 +21,7 @@
@@ -830646,7 +1113447,44 @@
#include <linux/inotify.h>
#include <linux/freezer.h>
#include <linux/tty.h>
-@@ -265,13 +264,13 @@ static int audit_log_config_change(char *function_name, int new, int old,
+@@ -127,6 +126,8 @@ static int audit_freelist_count;
+ static LIST_HEAD(audit_freelist);
+
+ static struct sk_buff_head audit_skb_queue;
++/* queue of skbs to send to auditd when/if it comes back */
++static struct sk_buff_head audit_skb_hold_queue;
+ static struct task_struct *kauditd_task;
+ static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
+ static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait);
+@@ -155,6 +156,11 @@ struct audit_buffer {
+ gfp_t gfp_mask;
+ };
+
++struct audit_reply {
++ int pid;
++ struct sk_buff *skb;
++};
++
+ static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
+ {
+ if (ab) {
+@@ -253,25 +259,26 @@ void audit_log_lost(const char *message)
+ }
+
+ static int audit_log_config_change(char *function_name, int new, int old,
+- uid_t loginuid, u32 sid, int allow_changes)
++ uid_t loginuid, u32 sessionid, u32 sid,
++ int allow_changes)
+ {
+ struct audit_buffer *ab;
+ int rc = 0;
+
+ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+- audit_log_format(ab, "%s=%d old=%d by auid=%u", function_name, new,
+- old, loginuid);
++ audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new,
++ old, loginuid, sessionid);
+ if (sid) {
char *ctx = NULL;
u32 len;
@@ -830662,9 +1113500,265 @@
}
}
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);
+@@ -280,7 +287,8 @@ static int audit_log_config_change(char *function_name, int new, int old,
+ }
+
+ static int audit_do_config_change(char *function_name, int *to_change,
+- int new, uid_t loginuid, u32 sid)
++ int new, uid_t loginuid, u32 sessionid,
++ u32 sid)
+ {
+ int allow_changes, rc = 0, old = *to_change;
+
+@@ -291,8 +299,8 @@ static int audit_do_config_change(char *function_name, int *to_change,
+ allow_changes = 1;
+
+ if (audit_enabled != AUDIT_OFF) {
+- rc = audit_log_config_change(function_name, new, old,
+- loginuid, sid, allow_changes);
++ rc = audit_log_config_change(function_name, new, old, loginuid,
++ sessionid, sid, allow_changes);
+ if (rc)
+ allow_changes = 0;
+ }
+@@ -306,26 +314,28 @@ static int audit_do_config_change(char *function_name, int *to_change,
+ return rc;
+ }
+
+-static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
++static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sessionid,
++ u32 sid)
+ {
+ return audit_do_config_change("audit_rate_limit", &audit_rate_limit,
+- limit, loginuid, sid);
++ limit, loginuid, sessionid, sid);
+ }
+
+-static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
++static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sessionid,
++ u32 sid)
+ {
+ return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit,
+- limit, loginuid, sid);
++ limit, loginuid, sessionid, sid);
+ }
+
+-static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
++static int audit_set_enabled(int state, uid_t loginuid, u32 sessionid, u32 sid)
+ {
+ int rc;
+ if (state < AUDIT_OFF || state > AUDIT_LOCKED)
+ return -EINVAL;
+
+ rc = audit_do_config_change("audit_enabled", &audit_enabled, state,
+- loginuid, sid);
++ loginuid, sessionid, sid);
+
+ if (!rc)
+ audit_ever_enabled |= !!state;
+@@ -333,7 +343,7 @@ static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
+ return rc;
+ }
+
+-static int audit_set_failure(int state, uid_t loginuid, u32 sid)
++static int audit_set_failure(int state, uid_t loginuid, u32 sessionid, u32 sid)
+ {
+ if (state != AUDIT_FAIL_SILENT
+ && state != AUDIT_FAIL_PRINTK
+@@ -341,7 +351,43 @@ static int audit_set_failure(int state, uid_t loginuid, u32 sid)
+ return -EINVAL;
+
+ return audit_do_config_change("audit_failure", &audit_failure, state,
+- loginuid, sid);
++ loginuid, sessionid, sid);
++}
++
++/*
++ * Queue skbs to be sent to auditd when/if it comes back. These skbs should
++ * already have been sent via prink/syslog and so if these messages are dropped
++ * it is not a huge concern since we already passed the audit_log_lost()
++ * notification and stuff. This is just nice to get audit messages during
++ * boot before auditd is running or messages generated while auditd is stopped.
++ * This only holds messages is audit_default is set, aka booting with audit=1
++ * or building your kernel that way.
++ */
++static void audit_hold_skb(struct sk_buff *skb)
++{
++ if (audit_default &&
++ skb_queue_len(&audit_skb_hold_queue) < audit_backlog_limit)
++ skb_queue_tail(&audit_skb_hold_queue, skb);
++ else
++ kfree_skb(skb);
++}
++
++static void kauditd_send_skb(struct sk_buff *skb)
++{
++ int err;
++ /* take a reference in case we can't send it and we want to hold it */
++ skb_get(skb);
++ err = netlink_unicast(audit_sock, skb, audit_nlk_pid, 0);
++ if (err < 0) {
++ BUG_ON(err != -ECONNREFUSED); /* Shoudn't happen */
++ printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid);
++ audit_log_lost("auditd dissapeared\n");
++ audit_pid = 0;
++ /* we might get lucky and get this in the next auditd */
++ audit_hold_skb(skb);
++ } else
++ /* drop the extra reference if sent ok */
++ kfree_skb(skb);
+ }
+
+ static int kauditd_thread(void *dummy)
+@@ -350,24 +396,41 @@ static int kauditd_thread(void *dummy)
+
+ set_freezable();
+ while (!kthread_should_stop()) {
++ /*
++ * if auditd just started drain the queue of messages already
++ * sent to syslog/printk. remember loss here is ok. we already
++ * called audit_log_lost() if it didn't go out normally. so the
++ * race between the skb_dequeue and the next check for audit_pid
++ * doesn't matter.
++ *
++ * if you ever find kauditd to be too slow we can get a perf win
++ * by doing our own locking and keeping better track if there
++ * are messages in this queue. I don't see the need now, but
++ * in 5 years when I want to play with this again I'll see this
++ * note and still have no friggin idea what i'm thinking today.
++ */
++ if (audit_default && audit_pid) {
++ skb = skb_dequeue(&audit_skb_hold_queue);
++ if (unlikely(skb)) {
++ while (skb && audit_pid) {
++ kauditd_send_skb(skb);
++ skb = skb_dequeue(&audit_skb_hold_queue);
++ }
++ }
++ }
++
+ skb = skb_dequeue(&audit_skb_queue);
+ wake_up(&audit_backlog_wait);
+ if (skb) {
+- if (audit_pid) {
+- int err = netlink_unicast(audit_sock, skb, audit_nlk_pid, 0);
+- if (err < 0) {
+- BUG_ON(err != -ECONNREFUSED); /* Shoudn't happen */
+- printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid);
+- audit_log_lost("auditd dissapeared\n");
+- audit_pid = 0;
+- }
+- } else {
++ if (audit_pid)
++ kauditd_send_skb(skb);
++ else {
+ if (printk_ratelimit())
+- printk(KERN_NOTICE "%s\n", skb->data +
+- NLMSG_SPACE(0));
++ printk(KERN_NOTICE "%s\n", skb->data + NLMSG_SPACE(0));
+ else
+ audit_log_lost("printk limit exceeded\n");
+- kfree_skb(skb);
++
++ audit_hold_skb(skb);
+ }
+ } else {
+ DECLARE_WAITQUEUE(wait, current);
+@@ -386,13 +449,13 @@ static int kauditd_thread(void *dummy)
+ return 0;
+ }
+
+-static int audit_prepare_user_tty(pid_t pid, uid_t loginuid)
++static int audit_prepare_user_tty(pid_t pid, uid_t loginuid, u32 sessionid)
+ {
+ struct task_struct *tsk;
+ int err;
+
+ read_lock(&tasklist_lock);
+- tsk = find_task_by_pid(pid);
++ tsk = find_task_by_vpid(pid);
+ err = -ESRCH;
+ if (!tsk)
+ goto out;
+@@ -405,7 +468,7 @@ static int audit_prepare_user_tty(pid_t pid, uid_t loginuid)
+ if (err)
+ goto out;
+
+- tty_audit_push_task(tsk, loginuid);
++ tty_audit_push_task(tsk, loginuid, sessionid);
+ out:
+ read_unlock(&tasklist_lock);
+ return err;
+@@ -470,6 +533,19 @@ nlmsg_failure: /* Used by NLMSG_PUT */
+ return NULL;
+ }
+
++static int audit_send_reply_thread(void *arg)
++{
++ struct audit_reply *reply = (struct audit_reply *)arg;
++
++ mutex_lock(&audit_cmd_mutex);
++ mutex_unlock(&audit_cmd_mutex);
++
++ /* Ignore failure. It'll only happen if the sender goes away,
++ because our timeout is set to infinite. */
++ netlink_unicast(audit_sock, reply->skb, reply->pid, 0);
++ kfree(reply);
++ return 0;
++}
+ /**
+ * audit_send_reply - send an audit reply message via netlink
+ * @pid: process id to send reply to
+@@ -486,14 +562,26 @@ nlmsg_failure: /* Used by NLMSG_PUT */
+ void audit_send_reply(int pid, int seq, int type, int done, int multi,
+ void *payload, int size)
+ {
+- struct sk_buff *skb;
++ struct sk_buff *skb;
++ struct task_struct *tsk;
++ struct audit_reply *reply = kmalloc(sizeof(struct audit_reply),
++ GFP_KERNEL);
++
++ if (!reply)
++ return;
++
+ skb = audit_make_reply(pid, seq, type, done, multi, payload, size);
+ if (!skb)
+ return;
+- /* Ignore failure. It'll only happen if the sender goes away,
+- because our timeout is set to infinite. */
+- netlink_unicast(audit_sock, skb, pid, 0);
+- return;
++
++ reply->pid = pid;
++ reply->skb = skb;
++
++ tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply");
++ if (IS_ERR(tsk)) {
++ kfree(reply);
++ kfree_skb(skb);
++ }
+ }
+
+ /*
+@@ -535,7 +623,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
+ }
+
+ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
+- u32 pid, u32 uid, uid_t auid, u32 sid)
++ u32 pid, u32 uid, uid_t auid, u32 ses,
++ u32 sid)
+ {
+ int rc = 0;
+ char *ctx = NULL;
+@@ -547,15 +636,16 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
+ }
+
+ *ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
+- audit_log_format(*ab, "user pid=%d uid=%u auid=%u",
+- pid, uid, auid);
++ audit_log_format(*ab, "user pid=%d uid=%u auid=%u ses=%u",
++ pid, uid, auid, ses);
if (sid) {
- rc = selinux_sid_to_string(sid, &ctx, &len);
+ rc = security_secid_to_secctx(sid, &ctx, &len);
@@ -830679,7 +1113773,164 @@
}
return rc;
-@@ -758,18 +758,18 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+@@ -570,6 +660,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ struct audit_buffer *ab;
+ u16 msg_type = nlh->nlmsg_type;
+ uid_t loginuid; /* loginuid of sender */
++ u32 sessionid;
+ struct audit_sig_info *sig_data;
+ char *ctx = NULL;
+ u32 len;
+@@ -591,6 +682,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ pid = NETLINK_CREDS(skb)->pid;
+ uid = NETLINK_CREDS(skb)->uid;
+ loginuid = NETLINK_CB(skb).loginuid;
++ sessionid = NETLINK_CB(skb).sessionid;
+ sid = NETLINK_CB(skb).sid;
+ seq = nlh->nlmsg_seq;
+ data = NLMSG_DATA(nlh);
+@@ -613,12 +705,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ status_get = (struct audit_status *)data;
+ if (status_get->mask & AUDIT_STATUS_ENABLED) {
+ err = audit_set_enabled(status_get->enabled,
+- loginuid, sid);
++ loginuid, sessionid, sid);
+ if (err < 0) return err;
+ }
+ if (status_get->mask & AUDIT_STATUS_FAILURE) {
+ err = audit_set_failure(status_get->failure,
+- loginuid, sid);
++ loginuid, sessionid, sid);
+ if (err < 0) return err;
+ }
+ if (status_get->mask & AUDIT_STATUS_PID) {
+@@ -627,17 +719,17 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ if (audit_enabled != AUDIT_OFF)
+ audit_log_config_change("audit_pid", new_pid,
+ audit_pid, loginuid,
+- sid, 1);
++ sessionid, sid, 1);
+
+ audit_pid = new_pid;
+ audit_nlk_pid = NETLINK_CB(skb).pid;
+ }
+ if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
+ err = audit_set_rate_limit(status_get->rate_limit,
+- loginuid, sid);
++ loginuid, sessionid, sid);
+ if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
+ err = audit_set_backlog_limit(status_get->backlog_limit,
+- loginuid, sid);
++ loginuid, sessionid, sid);
+ break;
+ case AUDIT_USER:
+ case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:
+@@ -649,12 +741,13 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ if (err == 1) {
+ err = 0;
+ if (msg_type == AUDIT_USER_TTY) {
+- err = audit_prepare_user_tty(pid, loginuid);
++ err = audit_prepare_user_tty(pid, loginuid,
++ sessionid);
+ if (err)
+ break;
+ }
+ audit_log_common_recv_msg(&ab, msg_type, pid, uid,
+- loginuid, sid);
++ loginuid, sessionid, sid);
+
+ if (msg_type != AUDIT_USER_TTY)
+ audit_log_format(ab, " msg='%.1024s'",
+@@ -664,8 +757,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+
+ audit_log_format(ab, " msg=");
+ size = nlmsg_len(nlh);
+- audit_log_n_untrustedstring(ab, size,
+- data);
++ audit_log_n_untrustedstring(ab, data, size);
+ }
+ audit_set_pid(ab, pid);
+ audit_log_end(ab);
+@@ -677,7 +769,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ return -EINVAL;
+ if (audit_enabled == AUDIT_LOCKED) {
+ audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,
+- uid, loginuid, sid);
++ uid, loginuid, sessionid, sid);
+
+ audit_log_format(ab, " audit_enabled=%d res=0",
+ audit_enabled);
+@@ -688,7 +780,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ case AUDIT_LIST:
+ err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
+ uid, seq, data, nlmsg_len(nlh),
+- loginuid, sid);
++ loginuid, sessionid, sid);
+ break;
+ case AUDIT_ADD_RULE:
+ case AUDIT_DEL_RULE:
+@@ -696,7 +788,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ return -EINVAL;
+ if (audit_enabled == AUDIT_LOCKED) {
+ audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,
+- uid, loginuid, sid);
++ uid, loginuid, sessionid, sid);
+
+ audit_log_format(ab, " audit_enabled=%d res=0",
+ audit_enabled);
+@@ -707,13 +799,13 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ case AUDIT_LIST_RULES:
+ err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
+ uid, seq, data, nlmsg_len(nlh),
+- loginuid, sid);
++ loginuid, sessionid, sid);
+ break;
+ case AUDIT_TRIM:
+ audit_trim_trees();
+
+ audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,
+- uid, loginuid, sid);
++ uid, loginuid, sessionid, sid);
+
+ audit_log_format(ab, " op=trim res=1");
+ audit_log_end(ab);
+@@ -721,21 +813,21 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ case AUDIT_MAKE_EQUIV: {
+ void *bufp = data;
+ u32 sizes[2];
+- size_t len = nlmsg_len(nlh);
++ size_t msglen = nlmsg_len(nlh);
+ char *old, *new;
+
+ err = -EINVAL;
+- if (len < 2 * sizeof(u32))
++ if (msglen < 2 * sizeof(u32))
+ break;
+ memcpy(sizes, bufp, 2 * sizeof(u32));
+ bufp += 2 * sizeof(u32);
+- len -= 2 * sizeof(u32);
+- old = audit_unpack_string(&bufp, &len, sizes[0]);
++ msglen -= 2 * sizeof(u32);
++ old = audit_unpack_string(&bufp, &msglen, sizes[0]);
+ if (IS_ERR(old)) {
+ err = PTR_ERR(old);
+ break;
+ }
+- new = audit_unpack_string(&bufp, &len, sizes[1]);
++ new = audit_unpack_string(&bufp, &msglen, sizes[1]);
+ if (IS_ERR(new)) {
+ err = PTR_ERR(new);
+ kfree(old);
+@@ -745,7 +837,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ err = audit_tag_tree(old, new);
+
+ audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,
+- uid, loginuid, sid);
++ uid, loginuid, sessionid, sid);
+
+ audit_log_format(ab, " op=make_equiv old=");
+ audit_log_untrustedstring(ab, old);
+@@ -758,18 +850,18 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
break;
}
case AUDIT_SIGNAL_INFO:
@@ -830701,7 +1113952,30 @@
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)
+@@ -779,7 +871,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ struct task_struct *tsk;
+
+ read_lock(&tasklist_lock);
+- tsk = find_task_by_pid(pid);
++ tsk = find_task_by_vpid(pid);
+ if (!tsk)
+ err = -ESRCH;
+ else {
+@@ -802,7 +894,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ if (s->enabled != 0 && s->enabled != 1)
+ return -EINVAL;
+ read_lock(&tasklist_lock);
+- tsk = find_task_by_pid(pid);
++ tsk = find_task_by_vpid(pid);
+ if (!tsk)
+ err = -ESRCH;
+ else {
+@@ -877,14 +969,11 @@ static int __init audit_init(void)
+ audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
+
+ skb_queue_head_init(&audit_skb_queue);
++ skb_queue_head_init(&audit_skb_hold_queue);
+ audit_initialized = 1;
audit_enabled = audit_default;
audit_ever_enabled |= !!audit_default;
@@ -830712,11 +1113986,91 @@
audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
#ifdef CONFIG_AUDITSYSCALL
+@@ -1203,7 +1292,7 @@ void audit_log_format(struct audit_buffer *ab, const char *fmt, ...)
+ * This function will take the passed buf and convert it into a string of
+ * ascii hex digits. The new string is placed onto the skb.
+ */
+-void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf,
++void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf,
+ size_t len)
+ {
+ int i, avail, new_len;
+@@ -1239,8 +1328,8 @@ void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf,
+ * Format a string of no more than slen characters into the audit buffer,
+ * enclosed in quote marks.
+ */
+-static void audit_log_n_string(struct audit_buffer *ab, size_t slen,
+- const char *string)
++void audit_log_n_string(struct audit_buffer *ab, const char *string,
++ size_t slen)
+ {
+ int avail, new_len;
+ unsigned char *ptr;
+@@ -1296,13 +1385,13 @@ int audit_string_contains_control(const char *string, size_t len)
+ * The caller specifies the number of characters in the string to log, which may
+ * or may not be the entire string.
+ */
+-void audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len,
+- const char *string)
++void audit_log_n_untrustedstring(struct audit_buffer *ab, const char *string,
++ size_t len)
+ {
+ if (audit_string_contains_control(string, len))
+- audit_log_hex(ab, string, len);
++ audit_log_n_hex(ab, string, len);
+ else
+- audit_log_n_string(ab, len, string);
++ audit_log_n_string(ab, string, len);
+ }
+
+ /**
+@@ -1315,7 +1404,7 @@ void audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len,
+ */
+ void audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
+ {
+- audit_log_n_untrustedstring(ab, strlen(string), string);
++ audit_log_n_untrustedstring(ab, string, strlen(string));
+ }
+
+ /* This is a helper-function to print the escaped d_path */
+@@ -1359,19 +1448,23 @@ void audit_log_end(struct audit_buffer *ab)
+ audit_log_lost("rate limit exceeded");
+ } else {
+ struct nlmsghdr *nlh = nlmsg_hdr(ab->skb);
++ nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0);
++
+ if (audit_pid) {
+- nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0);
+ skb_queue_tail(&audit_skb_queue, ab->skb);
+- ab->skb = NULL;
+ wake_up_interruptible(&kauditd_wait);
+- } else if (nlh->nlmsg_type != AUDIT_EOE) {
+- if (printk_ratelimit()) {
+- printk(KERN_NOTICE "type=%d %s\n",
+- nlh->nlmsg_type,
+- ab->skb->data + NLMSG_SPACE(0));
+- } else
+- audit_log_lost("printk limit exceeded\n");
++ } else {
++ if (nlh->nlmsg_type != AUDIT_EOE) {
++ if (printk_ratelimit()) {
++ printk(KERN_NOTICE "type=%d %s\n",
++ nlh->nlmsg_type,
++ ab->skb->data + NLMSG_SPACE(0));
++ } else
++ audit_log_lost("printk limit exceeded\n");
++ }
++ audit_hold_skb(ab->skb);
+ }
++ ab->skb = NULL;
+ }
+ audit_buffer_free(ab);
+ }
diff --git a/kernel/audit.h b/kernel/audit.h
-index 2554bd5..3cfc54e 100644
+index 2554bd5..9d67174 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
-@@ -65,34 +65,9 @@ struct audit_watch {
+@@ -65,40 +65,20 @@ struct audit_watch {
struct list_head rules; /* associated rules */
};
@@ -830751,8 +1114105,48 @@
struct audit_entry {
struct list_head list;
struct rcu_head rcu;
+ struct audit_krule rule;
+ };
+
++#ifdef CONFIG_AUDIT
++extern int audit_enabled;
++extern int audit_ever_enabled;
++#endif
++
+ extern int audit_pid;
+
+ #define AUDIT_INODE_BUCKETS 32
+@@ -129,6 +109,9 @@ struct audit_netlink_list {
+ int audit_send_list(void *);
+
+ struct inotify_watch;
++/* Inotify handle */
++extern struct inotify_handle *audit_ih;
++
+ extern void audit_free_parent(struct inotify_watch *);
+ extern void audit_handle_ievent(struct inotify_watch *, u32, u32, u32,
+ const char *, struct inode *);
+@@ -136,6 +119,7 @@ extern int selinux_audit_rule_update(void);
+
+ extern struct mutex audit_filter_mutex;
+ extern void audit_free_rule_rcu(struct rcu_head *);
++extern struct list_head audit_filter_list[];
+
+ #ifdef CONFIG_AUDIT_TREE
+ extern struct audit_chunk *audit_tree_lookup(const struct inode *);
+@@ -162,6 +146,10 @@ extern void audit_put_tree(struct audit_tree *);
+
+ extern char *audit_unpack_string(void **, size_t *, size_t);
+
++extern pid_t audit_sig_pid;
++extern uid_t audit_sig_uid;
++extern u32 audit_sig_sid;
++
+ #ifdef CONFIG_AUDITSYSCALL
+ extern int __audit_signal_info(int sig, struct task_struct *t);
+ static inline int audit_signal_info(int sig, struct task_struct *t)
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
-index 2f2914b..28fef6b 100644
+index 2f2914b..0e0bd27 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -28,7 +28,7 @@
@@ -830773,7 +1114167,22 @@
* 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)
+@@ -89,14 +89,9 @@ struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
+
+ DEFINE_MUTEX(audit_filter_mutex);
+
+-/* Inotify handle */
+-extern struct inotify_handle *audit_ih;
+-
+ /* Inotify events we care about. */
+ #define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF
+
+-extern int audit_enabled;
+-
+ void audit_free_parent(struct inotify_watch *i_watch)
+ {
+ struct audit_parent *parent;
+@@ -139,8 +134,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];
@@ -830784,7 +1114193,58 @@
}
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,
+@@ -272,7 +267,7 @@ static int audit_to_watch(struct audit_krule *krule, char *path, int len,
+ return -EINVAL;
+
+ watch = audit_init_watch(path);
+- if (unlikely(IS_ERR(watch)))
++ if (IS_ERR(watch))
+ return PTR_ERR(watch);
+
+ audit_get_watch(watch);
+@@ -422,7 +417,7 @@ exit_err:
+ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
+ {
+ struct audit_entry *entry;
+- struct audit_field *f;
++ struct audit_field *ino_f;
+ int err = 0;
+ int i;
+
+@@ -483,6 +478,10 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
+ if (f->val & ~15)
+ goto exit_free;
+ break;
++ case AUDIT_FILETYPE:
++ if ((f->val & ~S_IFMT) > S_IFMT)
++ goto exit_free;
++ break;
+ case AUDIT_INODE:
+ err = audit_to_inode(&entry->rule, f);
+ if (err)
+@@ -504,9 +503,9 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
+ }
+ }
+
+- f = entry->rule.inode_f;
+- if (f) {
+- switch(f->op) {
++ ino_f = entry->rule.inode_f;
++ if (ino_f) {
++ switch(ino_f->op) {
+ case AUDIT_NOT_EQUAL:
+ entry->rule.inode_f = NULL;
+ case AUDIT_EQUAL:
+@@ -531,7 +530,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
+ {
+ int err = 0;
+ struct audit_entry *entry;
+- struct audit_field *f;
++ struct audit_field *ino_f;
+ void *bufp;
+ size_t remain = datasz - sizeof(struct audit_rule_data);
+ int i;
+@@ -554,8 +553,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];
@@ -830795,7 +1114255,7 @@
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,
+@@ -597,12 +596,12 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
goto exit_free;
entry->rule.buflen += f->val;
@@ -830811,7 +1114271,7 @@
"\'%s\' is invalid\n", str);
err = 0;
}
-@@ -610,7 +610,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
+@@ -610,7 +609,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
kfree(str);
goto exit_free;
} else
@@ -830820,7 +1114280,29 @@
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)
+@@ -654,14 +653,18 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
+ if (f->val & ~15)
+ goto exit_free;
+ break;
++ case AUDIT_FILETYPE:
++ if ((f->val & ~S_IFMT) > S_IFMT)
++ goto exit_free;
++ break;
+ default:
+ goto exit_free;
+ }
+ }
+
+- f = entry->rule.inode_f;
+- if (f) {
+- switch(f->op) {
++ ino_f = entry->rule.inode_f;
++ if (ino_f) {
++ switch(ino_f->op) {
+ case AUDIT_NOT_EQUAL:
+ entry->rule.inode_f = NULL;
+ case AUDIT_EQUAL:
+@@ -754,7 +757,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] =
@@ -830829,7 +1114311,7 @@
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)
+@@ -806,7 +809,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:
@@ -830838,7 +1114320,16 @@
return 1;
break;
case AUDIT_WATCH:
-@@ -862,28 +862,28 @@ out:
+@@ -848,7 +851,7 @@ static struct audit_watch *audit_dupe_watch(struct audit_watch *old)
+ return ERR_PTR(-ENOMEM);
+
+ new = audit_init_watch(path);
+- if (unlikely(IS_ERR(new))) {
++ if (IS_ERR(new)) {
+ kfree(path);
+ goto out;
+ }
+@@ -862,28 +865,28 @@ out:
return new;
}
@@ -830879,7 +1114370,7 @@
ret = 0;
}
-@@ -891,7 +891,7 @@ static inline int audit_dupe_selinux_field(struct audit_field *df,
+@@ -891,7 +894,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
@@ -830888,7 +1114379,7 @@
* 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,
+@@ -930,7 +933,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);
@@ -830897,7 +1114388,7 @@
* 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,
+@@ -944,7 +947,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:
@@ -830906,7 +1114397,42 @@
&old->fields[i]);
break;
case AUDIT_FILTERKEY:
-@@ -1515,11 +1515,12 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
+@@ -989,7 +992,7 @@ static void audit_update_watch(struct audit_parent *parent,
+ audit_set_auditable(current->audit_context);
+
+ nwatch = audit_dupe_watch(owatch);
+- if (unlikely(IS_ERR(nwatch))) {
++ if (IS_ERR(nwatch)) {
+ mutex_unlock(&audit_filter_mutex);
+ audit_panic("error updating watch, skipping");
+ return;
+@@ -1004,7 +1007,7 @@ static void audit_update_watch(struct audit_parent *parent,
+ list_del_rcu(&oentry->list);
+
+ nentry = audit_dupe_rule(&oentry->rule, nwatch);
+- if (unlikely(IS_ERR(nentry)))
++ if (IS_ERR(nentry))
+ audit_panic("error updating watch, removing");
+ else {
+ int h = audit_hash_ino((u32)ino);
+@@ -1500,8 +1503,9 @@ static void audit_list_rules(int pid, int seq, struct sk_buff_head *q)
+ }
+
+ /* Log rule additions and removals */
+-static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
+- struct audit_krule *rule, int res)
++static void audit_log_rule_change(uid_t loginuid, u32 sessionid, u32 sid,
++ char *action, struct audit_krule *rule,
++ int res)
+ {
+ struct audit_buffer *ab;
+
+@@ -1511,15 +1515,16 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
+ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+ if (!ab)
+ return;
+- audit_log_format(ab, "auid=%u", loginuid);
++ audit_log_format(ab, "auid=%u ses=%u", loginuid, sessionid);
if (sid) {
char *ctx = NULL;
u32 len;
@@ -830922,7 +1114448,37 @@
}
audit_log_format(ab, " op=%s rule key=", action);
if (rule->filterkey)
-@@ -1761,38 +1762,12 @@ unlock_and_return:
+@@ -1542,7 +1547,7 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
+ * @sid: SE Linux Security ID of sender
+ */
+ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
+- size_t datasz, uid_t loginuid, u32 sid)
++ size_t datasz, uid_t loginuid, u32 sessionid, u32 sid)
+ {
+ struct task_struct *tsk;
+ struct audit_netlink_list *dest;
+@@ -1589,7 +1594,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
+
+ err = audit_add_rule(entry,
+ &audit_filter_list[entry->rule.listnr]);
+- audit_log_rule_change(loginuid, sid, "add", &entry->rule, !err);
++ audit_log_rule_change(loginuid, sessionid, sid, "add",
++ &entry->rule, !err);
+
+ if (err)
+ audit_free_rule(entry);
+@@ -1605,8 +1611,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
+
+ err = audit_del_rule(entry,
+ &audit_filter_list[entry->rule.listnr]);
+- audit_log_rule_change(loginuid, sid, "remove", &entry->rule,
+- !err);
++ audit_log_rule_change(loginuid, sessionid, sid, "remove",
++ &entry->rule, !err);
+
+ audit_free_rule(entry);
+ break;
+@@ -1761,38 +1767,12 @@ unlock_and_return:
return result;
}
@@ -830965,7 +1114521,7 @@
{
struct audit_entry *entry, *n, *nentry;
struct audit_watch *watch;
-@@ -1804,7 +1779,7 @@ int selinux_audit_rule_update(void)
+@@ -1804,18 +1784,18 @@ 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) {
@@ -830974,7 +1114530,11 @@
continue;
watch = entry->rule.watch;
-@@ -1815,7 +1790,7 @@ int selinux_audit_rule_update(void)
+ tree = entry->rule.tree;
+ nentry = audit_dupe_rule(&entry->rule, watch);
+- if (unlikely(IS_ERR(nentry))) {
++ if (IS_ERR(nentry)) {
+ /* save the first error encountered for the
* return value */
if (!err)
err = PTR_ERR(nentry);
@@ -830984,7 +1114544,7 @@
list_del(&entry->rule.rlist);
list_del_rcu(&entry->list);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
-index 782262e..56e56ed 100644
+index 782262e..c10e7aa 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -61,7 +61,6 @@
@@ -830995,7 +1114555,37 @@
#include <linux/binfmts.h>
#include <linux/highmem.h>
#include <linux/syscalls.h>
-@@ -528,14 +527,14 @@ static int audit_filter_rules(struct task_struct *tsk,
+@@ -69,9 +68,6 @@
+
+ #include "audit.h"
+
+-extern struct list_head audit_filter_list[];
+-extern int audit_ever_enabled;
+-
+ /* AUDIT_NAMES is the number of slots we reserve in the audit_context
+ * for saving names from getname(). */
+ #define AUDIT_NAMES 20
+@@ -284,6 +280,19 @@ static int audit_match_perm(struct audit_context *ctx, int mask)
+ }
+ }
+
++static int audit_match_filetype(struct audit_context *ctx, int which)
++{
++ unsigned index = which & ~S_IFMT;
++ mode_t mode = which & S_IFMT;
++ if (index >= ctx->name_count)
++ return 0;
++ if (ctx->names[index].ino == -1)
++ return 0;
++ if ((ctx->names[index].mode ^ mode) & S_IFMT)
++ return 0;
++ return 1;
++}
++
+ /*
+ * We keep a linked list of fixed-sized (31 pointer) arrays of audit_chunk *;
+ * ->first_trees points to its beginning, ->trees - to the current end of data.
+@@ -528,14 +537,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 */
@@ -831014,7 +1114604,7 @@
ctx);
}
break;
-@@ -546,18 +545,18 @@ static int audit_filter_rules(struct task_struct *tsk,
+@@ -546,18 +555,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 */
@@ -831038,7 +1114628,7 @@
++result;
break;
}
-@@ -570,7 +569,7 @@ static int audit_filter_rules(struct task_struct *tsk,
+@@ -570,7 +579,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;
@@ -831047,7 +1114637,17 @@
++result;
break;
}
-@@ -885,11 +884,11 @@ void audit_log_task_context(struct audit_buffer *ab)
+@@ -593,6 +602,9 @@ static int audit_filter_rules(struct task_struct *tsk,
+ case AUDIT_PERM:
+ result = audit_match_perm(ctx, f->val);
+ break;
++ case AUDIT_FILETYPE:
++ result = audit_match_filetype(ctx, f->val);
++ break;
+ }
+
+ if (!result)
+@@ -885,11 +897,11 @@ void audit_log_task_context(struct audit_buffer *ab)
int error;
u32 sid;
@@ -831061,7 +1114661,7 @@
if (error) {
if (error != -EINVAL)
goto error_path;
-@@ -897,7 +896,7 @@ void audit_log_task_context(struct audit_buffer *ab)
+@@ -897,7 +909,7 @@ void audit_log_task_context(struct audit_buffer *ab)
}
audit_log_format(ab, " subj=%s", ctx);
@@ -831070,7 +1114670,7 @@
return;
error_path:
-@@ -941,7 +940,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
+@@ -941,7 +953,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
u32 sid, char *comm)
{
struct audit_buffer *ab;
@@ -831079,7 +1114679,7 @@
u32 len;
int rc = 0;
-@@ -951,15 +950,16 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
+@@ -951,15 +963,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);
@@ -831100,7 +1114700,16 @@
return rc;
}
-@@ -1271,14 +1271,15 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
+@@ -1095,7 +1108,7 @@ static int audit_log_single_execve_arg(struct audit_context *context,
+ audit_log_format(*ab, "[%d]", i);
+ audit_log_format(*ab, "=");
+ if (has_cntl)
+- audit_log_hex(*ab, buf, to_send);
++ audit_log_n_hex(*ab, buf, to_send);
+ else
+ audit_log_format(*ab, "\"%s\"", buf);
+ audit_log_format(*ab, "\n");
+@@ -1271,14 +1284,15 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
if (axi->osid != 0) {
char *ctx = NULL;
u32 len;
@@ -831119,7 +1114728,43 @@
}
break; }
-@@ -1392,13 +1393,14 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
+@@ -1295,7 +1309,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
+ break; }
+
+ case AUDIT_SOCKETCALL: {
+- int i;
+ struct audit_aux_data_socketcall *axs = (void *)aux;
+ audit_log_format(ab, "nargs=%d", axs->nargs);
+ for (i=0; i<axs->nargs; i++)
+@@ -1306,7 +1319,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
+ struct audit_aux_data_sockaddr *axs = (void *)aux;
+
+ audit_log_format(ab, "saddr=");
+- audit_log_hex(ab, axs->a, axs->len);
++ audit_log_n_hex(ab, axs->a, axs->len);
+ break; }
+
+ case AUDIT_FD_PAIR: {
+@@ -1320,7 +1333,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
+
+ for (aux = context->aux_pids; aux; aux = aux->next) {
+ struct audit_aux_data_pids *axs = (void *)aux;
+- int i;
+
+ for (i = 0; i < axs->pid_count; i++)
+ if (audit_log_pid_context(context, axs->target_pid[i],
+@@ -1370,8 +1382,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
+ default:
+ /* log the name's directory component */
+ audit_log_format(ab, " name=");
+- audit_log_n_untrustedstring(ab, n->name_len,
+- n->name);
++ audit_log_n_untrustedstring(ab, n->name,
++ n->name_len);
+ }
+ } else
+ audit_log_format(ab, " name=(null)");
+@@ -1392,13 +1404,14 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
if (n->osid != 0) {
char *ctx = NULL;
u32 len;
@@ -831137,7 +1114782,41 @@
}
audit_log_end(ab);
-@@ -1775,7 +1777,7 @@ static void audit_copy_inode(struct audit_names *name, const struct inode *inode
+@@ -1594,7 +1607,7 @@ static inline void handle_one(const struct inode *inode)
+ if (likely(put_tree_ref(context, chunk)))
+ return;
+ if (unlikely(!grow_tree_refs(context))) {
+- printk(KERN_WARNING "out of memory, audit has lost a tree reference");
++ printk(KERN_WARNING "out of memory, audit has lost a tree reference\n");
+ audit_set_auditable(context);
+ audit_put_chunk(chunk);
+ unroll_tree_refs(context, p, count);
+@@ -1654,7 +1667,7 @@ retry:
+ }
+ /* too bad */
+ printk(KERN_WARNING
+- "out of memory, audit has lost a tree reference");
++ "out of memory, audit has lost a tree reference\n");
+ unroll_tree_refs(context, p, count);
+ audit_set_auditable(context);
+ return;
+@@ -1750,13 +1763,13 @@ static int audit_inc_name_count(struct audit_context *context,
+ if (context->name_count >= AUDIT_NAMES) {
+ if (inode)
+ printk(KERN_DEBUG "name_count maxed, losing inode data: "
+- "dev=%02x:%02x, inode=%lu",
++ "dev=%02x:%02x, inode=%lu\n",
+ MAJOR(inode->i_sb->s_dev),
+ MINOR(inode->i_sb->s_dev),
+ inode->i_ino);
+
+ else
+- printk(KERN_DEBUG "name_count maxed, losing inode data");
++ printk(KERN_DEBUG "name_count maxed, losing inode data\n");
+ return 1;
+ }
+ context->name_count++;
+@@ -1775,7 +1788,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;
@@ -831146,7 +1114825,7 @@
}
/**
-@@ -2190,8 +2192,7 @@ int __audit_ipc_obj(struct kern_ipc_perm *ipcp)
+@@ -2190,8 +2203,7 @@ int __audit_ipc_obj(struct kern_ipc_perm *ipcp)
ax->uid = ipcp->uid;
ax->gid = ipcp->gid;
ax->mode = ipcp->mode;
@@ -831156,7 +1114835,7 @@
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)
+@@ -2343,7 +2355,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);
@@ -831165,7 +1114844,17 @@
memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
}
-@@ -2371,7 +2372,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
+@@ -2360,9 +2372,6 @@ int __audit_signal_info(int sig, struct task_struct *t)
+ struct audit_aux_data_pids *axp;
+ struct task_struct *tsk = current;
+ struct audit_context *ctx = tsk->audit_context;
+- extern pid_t audit_sig_pid;
+- extern uid_t audit_sig_uid;
+- extern u32 audit_sig_sid;
+
+ if (audit_pid && t->tgid == audit_pid) {
+ if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) {
+@@ -2371,7 +2380,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
audit_sig_uid = tsk->loginuid;
else
audit_sig_uid = tsk->uid;
@@ -831174,7 +1114863,7 @@
}
if (!audit_signals || audit_dummy_context())
return 0;
-@@ -2384,7 +2385,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
+@@ -2384,7 +2393,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);
@@ -831183,7 +1114872,7 @@
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)
+@@ -2405,7 +2414,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);
@@ -831192,7 +1114881,7 @@
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)
+@@ -2435,16 +2444,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);
@@ -831214,11 +1114903,429 @@
}
audit_log_format(ab, " pid=%d comm=", current->pid);
audit_log_untrustedstring(ab, current->comm);
+diff --git a/kernel/bounds.c b/kernel/bounds.c
+new file mode 100644
+index 0000000..3c53013
+--- /dev/null
++++ b/kernel/bounds.c
+@@ -0,0 +1,19 @@
++/*
++ * Generate definitions needed by the preprocessor.
++ * This code generates raw asm output which is post-processed
++ * to extract and format the required data.
++ */
++
++#define __GENERATING_BOUNDS_H
++/* Include headers that define the enum constants of interest */
++#include <linux/page-flags.h>
++#include <linux/mmzone.h>
++#include <linux/kbuild.h>
++
++void foo(void)
++{
++ /* The enum constants to put into include/linux/bounds.h */
++ DEFINE(NR_PAGEFLAGS, __NR_PAGEFLAGS);
++ DEFINE(MAX_NR_ZONES, __MAX_NR_ZONES);
++ /* End of constants */
++}
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
-index 2727f92..6d8de05 100644
+index 2727f92..fbc6fc8 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
-@@ -1722,7 +1722,12 @@ void cgroup_enable_task_cg_lists(void)
+@@ -44,6 +44,7 @@
+ #include <linux/kmod.h>
+ #include <linux/delayacct.h>
+ #include <linux/cgroupstats.h>
++#include <linux/hash.h>
+
+ #include <asm/atomic.h>
+
+@@ -118,17 +119,7 @@ static int root_count;
+ * be called.
+ */
+ static int need_forkexit_callback;
+-
+-/* bits in struct cgroup flags field */
+-enum {
+- /* Control Group is dead */
+- CGRP_REMOVED,
+- /* Control Group has previously had a child cgroup or a task,
+- * but no longer (only if CGRP_NOTIFY_ON_RELEASE is set) */
+- CGRP_RELEASABLE,
+- /* Control Group requires release notifications to userspace */
+- CGRP_NOTIFY_ON_RELEASE,
+-};
++static int need_mm_owner_callback __read_mostly;
+
+ /* convenient tests for these bits */
+ inline int cgroup_is_removed(const struct cgroup *cgrp)
+@@ -204,6 +195,27 @@ static struct cg_cgroup_link init_css_set_link;
+ static DEFINE_RWLOCK(css_set_lock);
+ static int css_set_count;
+
++/* hash table for cgroup groups. This improves the performance to
++ * find an existing css_set */
++#define CSS_SET_HASH_BITS 7
++#define CSS_SET_TABLE_SIZE (1 << CSS_SET_HASH_BITS)
++static struct hlist_head css_set_table[CSS_SET_TABLE_SIZE];
++
++static struct hlist_head *css_set_hash(struct cgroup_subsys_state *css[])
++{
++ int i;
++ int index;
++ unsigned long tmp = 0UL;
++
++ for (i = 0; i < CGROUP_SUBSYS_COUNT; i++)
++ tmp += (unsigned long)css[i];
++ tmp = (tmp >> 16) ^ tmp;
++
++ index = hash_long(tmp, CSS_SET_HASH_BITS);
++
++ return &css_set_table[index];
++}
++
+ /* We don't maintain the lists running through each css_set to its
+ * task until after the first call to cgroup_iter_start(). This
+ * reduces the fork()/exit() overhead for people who have cgroups
+@@ -230,7 +242,7 @@ static int use_task_css_set_links;
+ static void unlink_css_set(struct css_set *cg)
+ {
+ write_lock(&css_set_lock);
+- list_del(&cg->list);
++ hlist_del(&cg->hlist);
+ css_set_count--;
+ while (!list_empty(&cg->cg_links)) {
+ struct cg_cgroup_link *link;
+@@ -295,9 +307,7 @@ static inline void put_css_set_taskexit(struct css_set *cg)
+ /*
+ * find_existing_css_set() is a helper for
+ * find_css_set(), and checks to see whether an existing
+- * css_set is suitable. This currently walks a linked-list for
+- * simplicity; a later patch will use a hash table for better
+- * performance
++ * css_set is suitable.
+ *
+ * oldcg: the cgroup group that we're using before the cgroup
+ * transition
+@@ -314,7 +324,9 @@ static struct css_set *find_existing_css_set(
+ {
+ int i;
+ struct cgroupfs_root *root = cgrp->root;
+- struct list_head *l = &init_css_set.list;
++ struct hlist_head *hhead;
++ struct hlist_node *node;
++ struct css_set *cg;
+
+ /* Built the set of subsystem state objects that we want to
+ * see in the new css_set */
+@@ -331,18 +343,13 @@ static struct css_set *find_existing_css_set(
+ }
+ }
+
+- /* Look through existing cgroup groups to find one to reuse */
+- do {
+- struct css_set *cg =
+- list_entry(l, struct css_set, list);
+-
++ hhead = css_set_hash(template);
++ hlist_for_each_entry(cg, node, hhead, hlist) {
+ if (!memcmp(template, cg->subsys, sizeof(cg->subsys))) {
+ /* All subsystems matched */
+ return cg;
+ }
+- /* Try the next cgroup group */
+- l = l->next;
+- } while (l != &init_css_set.list);
++ }
+
+ /* No existing cgroup group matched */
+ return NULL;
+@@ -404,6 +411,8 @@ static struct css_set *find_css_set(
+ struct list_head tmp_cg_links;
+ struct cg_cgroup_link *link;
+
++ struct hlist_head *hhead;
++
+ /* First see if we already have a cgroup group that matches
+ * the desired set */
+ write_lock(&css_set_lock);
+@@ -428,6 +437,7 @@ static struct css_set *find_css_set(
+ kref_init(&res->ref);
+ INIT_LIST_HEAD(&res->cg_links);
+ INIT_LIST_HEAD(&res->tasks);
++ INIT_HLIST_NODE(&res->hlist);
+
+ /* Copy the set of subsystem state objects generated in
+ * find_existing_css_set() */
+@@ -467,9 +477,12 @@ static struct css_set *find_css_set(
+
+ BUG_ON(!list_empty(&tmp_cg_links));
+
+- /* Link this cgroup group into the list */
+- list_add(&res->list, &init_css_set.list);
+ css_set_count++;
++
++ /* Add this cgroup group to the hash table */
++ hhead = css_set_hash(res->subsys);
++ hlist_add_head(&res->hlist, hhead);
++
+ write_unlock(&css_set_lock);
+
+ return res;
+@@ -562,7 +575,7 @@ static struct inode_operations cgroup_dir_inode_operations;
+ static struct file_operations proc_cgroupstats_operations;
+
+ static struct backing_dev_info cgroup_backing_dev_info = {
+- .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
++ .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK,
+ };
+
+ static struct inode *cgroup_new_inode(mode_t mode, struct super_block *sb)
+@@ -948,7 +961,7 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
+ int ret = 0;
+ struct super_block *sb;
+ struct cgroupfs_root *root;
+- struct list_head tmp_cg_links, *l;
++ struct list_head tmp_cg_links;
+ INIT_LIST_HEAD(&tmp_cg_links);
+
+ /* First find the desired set of subsystems */
+@@ -990,6 +1003,7 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
+ /* New superblock */
+ struct cgroup *cgrp = &root->top_cgroup;
+ struct inode *inode;
++ int i;
+
+ BUG_ON(sb->s_root != NULL);
+
+@@ -1034,22 +1048,25 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
+ /* Link the top cgroup in this hierarchy into all
+ * the css_set objects */
+ write_lock(&css_set_lock);
+- l = &init_css_set.list;
+- do {
++ for (i = 0; i < CSS_SET_TABLE_SIZE; i++) {
++ struct hlist_head *hhead = &css_set_table[i];
++ struct hlist_node *node;
+ struct css_set *cg;
+- struct cg_cgroup_link *link;
+- cg = list_entry(l, struct css_set, list);
+- BUG_ON(list_empty(&tmp_cg_links));
+- link = list_entry(tmp_cg_links.next,
+- struct cg_cgroup_link,
+- cgrp_link_list);
+- list_del(&link->cgrp_link_list);
+- link->cg = cg;
+- list_add(&link->cgrp_link_list,
+- &root->top_cgroup.css_sets);
+- list_add(&link->cg_link_list, &cg->cg_links);
+- l = l->next;
+- } while (l != &init_css_set.list);
++
++ hlist_for_each_entry(cg, node, hhead, hlist) {
++ struct cg_cgroup_link *link;
++
++ BUG_ON(list_empty(&tmp_cg_links));
++ link = list_entry(tmp_cg_links.next,
++ struct cg_cgroup_link,
++ cgrp_link_list);
++ list_del(&link->cgrp_link_list);
++ link->cg = cg;
++ list_add(&link->cgrp_link_list,
++ &root->top_cgroup.css_sets);
++ list_add(&link->cg_link_list, &cg->cg_links);
++ }
++ }
+ write_unlock(&css_set_lock);
+
+ free_cg_links(&tmp_cg_links);
+@@ -1307,18 +1324,16 @@ enum cgroup_filetype {
+ FILE_DIR,
+ FILE_TASKLIST,
+ FILE_NOTIFY_ON_RELEASE,
+- FILE_RELEASABLE,
+ FILE_RELEASE_AGENT,
+ };
+
+-static ssize_t cgroup_write_uint(struct cgroup *cgrp, struct cftype *cft,
+- struct file *file,
+- const char __user *userbuf,
+- size_t nbytes, loff_t *unused_ppos)
++static ssize_t cgroup_write_X64(struct cgroup *cgrp, struct cftype *cft,
++ struct file *file,
++ const char __user *userbuf,
++ size_t nbytes, loff_t *unused_ppos)
+ {
+ char buffer[64];
+ int retval = 0;
+- u64 val;
+ char *end;
+
+ if (!nbytes)
+@@ -1329,16 +1344,18 @@ static ssize_t cgroup_write_uint(struct cgroup *cgrp, struct cftype *cft,
+ return -EFAULT;
+
+ buffer[nbytes] = 0; /* nul-terminate */
+-
+- /* strip newline if necessary */
+- if (nbytes && (buffer[nbytes-1] == '\n'))
+- buffer[nbytes-1] = 0;
+- val = simple_strtoull(buffer, &end, 0);
+- if (*end)
+- return -EINVAL;
+-
+- /* Pass to subsystem */
+- retval = cft->write_uint(cgrp, cft, val);
++ strstrip(buffer);
++ if (cft->write_u64) {
++ u64 val = simple_strtoull(buffer, &end, 0);
++ if (*end)
++ return -EINVAL;
++ retval = cft->write_u64(cgrp, cft, val);
++ } else {
++ s64 val = simple_strtoll(buffer, &end, 0);
++ if (*end)
++ return -EINVAL;
++ retval = cft->write_s64(cgrp, cft, val);
++ }
+ if (!retval)
+ retval = nbytes;
+ return retval;
+@@ -1419,23 +1436,39 @@ static ssize_t cgroup_file_write(struct file *file, const char __user *buf,
+ return -ENODEV;
+ if (cft->write)
+ return cft->write(cgrp, cft, file, buf, nbytes, ppos);
+- if (cft->write_uint)
+- return cgroup_write_uint(cgrp, cft, file, buf, nbytes, ppos);
++ if (cft->write_u64 || cft->write_s64)
++ return cgroup_write_X64(cgrp, cft, file, buf, nbytes, ppos);
++ if (cft->trigger) {
++ int ret = cft->trigger(cgrp, (unsigned int)cft->private);
++ return ret ? ret : nbytes;
++ }
+ return -EINVAL;
+ }
+
+-static ssize_t cgroup_read_uint(struct cgroup *cgrp, struct cftype *cft,
+- struct file *file,
+- char __user *buf, size_t nbytes,
+- loff_t *ppos)
++static ssize_t cgroup_read_u64(struct cgroup *cgrp, struct cftype *cft,
++ struct file *file,
++ char __user *buf, size_t nbytes,
++ loff_t *ppos)
+ {
+ char tmp[64];
+- u64 val = cft->read_uint(cgrp, cft);
++ u64 val = cft->read_u64(cgrp, cft);
+ int len = sprintf(tmp, "%llu\n", (unsigned long long) val);
+
+ return simple_read_from_buffer(buf, nbytes, ppos, tmp, len);
+ }
+
++static ssize_t cgroup_read_s64(struct cgroup *cgrp, struct cftype *cft,
++ struct file *file,
++ char __user *buf, size_t nbytes,
++ loff_t *ppos)
++{
++ char tmp[64];
++ s64 val = cft->read_s64(cgrp, cft);
++ int len = sprintf(tmp, "%lld\n", (long long) val);
++
++ return simple_read_from_buffer(buf, nbytes, ppos, tmp, len);
++}
++
+ static ssize_t cgroup_common_file_read(struct cgroup *cgrp,
+ struct cftype *cft,
+ struct file *file,
+@@ -1490,11 +1523,56 @@ static ssize_t cgroup_file_read(struct file *file, char __user *buf,
+
+ if (cft->read)
+ return cft->read(cgrp, cft, file, buf, nbytes, ppos);
+- if (cft->read_uint)
+- return cgroup_read_uint(cgrp, cft, file, buf, nbytes, ppos);
++ if (cft->read_u64)
++ return cgroup_read_u64(cgrp, cft, file, buf, nbytes, ppos);
++ if (cft->read_s64)
++ return cgroup_read_s64(cgrp, cft, file, buf, nbytes, ppos);
+ return -EINVAL;
+ }
+
++/*
++ * seqfile ops/methods for returning structured data. Currently just
++ * supports string->u64 maps, but can be extended in future.
++ */
++
++struct cgroup_seqfile_state {
++ struct cftype *cft;
++ struct cgroup *cgroup;
++};
++
++static int cgroup_map_add(struct cgroup_map_cb *cb, const char *key, u64 value)
++{
++ struct seq_file *sf = cb->state;
++ return seq_printf(sf, "%s %llu\n", key, (unsigned long long)value);
++}
++
++static int cgroup_seqfile_show(struct seq_file *m, void *arg)
++{
++ struct cgroup_seqfile_state *state = m->private;
++ struct cftype *cft = state->cft;
++ if (cft->read_map) {
++ struct cgroup_map_cb cb = {
++ .fill = cgroup_map_add,
++ .state = m,
++ };
++ return cft->read_map(state->cgroup, cft, &cb);
++ }
++ return cft->read_seq_string(state->cgroup, cft, m);
++}
++
++int cgroup_seqfile_release(struct inode *inode, struct file *file)
++{
++ struct seq_file *seq = file->private_data;
++ kfree(seq->private);
++ return single_release(inode, file);
++}
++
++static struct file_operations cgroup_seqfile_operations = {
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = cgroup_seqfile_release,
++};
++
+ static int cgroup_file_open(struct inode *inode, struct file *file)
+ {
+ int err;
+@@ -1507,7 +1585,18 @@ static int cgroup_file_open(struct inode *inode, struct file *file)
+ cft = __d_cft(file->f_dentry);
+ if (!cft)
+ return -ENODEV;
+- if (cft->open)
++ if (cft->read_map || cft->read_seq_string) {
++ struct cgroup_seqfile_state *state =
++ kzalloc(sizeof(*state), GFP_USER);
++ if (!state)
++ return -ENOMEM;
++ state->cft = cft;
++ state->cgroup = __d_cgrp(file->f_dentry->d_parent);
++ file->f_op = &cgroup_seqfile_operations;
++ err = single_open(file, cgroup_seqfile_show, state);
++ if (err < 0)
++ kfree(state);
++ } else if (cft->open)
+ err = cft->open(inode, file);
+ else
+ err = 0;
+@@ -1715,14 +1804,19 @@ static void cgroup_advance_iter(struct cgroup *cgrp,
+ * The tasklist_lock is not held here, as do_each_thread() and
+ * while_each_thread() are protected by RCU.
+ */
+-void cgroup_enable_task_cg_lists(void)
++static void cgroup_enable_task_cg_lists(void)
+ {
+ struct task_struct *p, *g;
+ write_lock(&css_set_lock);
use_task_css_set_links = 1;
do_each_thread(g, p) {
task_lock(p);
@@ -831232,8 +1115339,250 @@
list_add(&p->cg_list, &p->cgroups->tasks);
task_unlock(p);
} while_each_thread(g, p);
+@@ -1908,14 +2002,14 @@ int cgroup_scan_tasks(struct cgroup_scanner *scan)
+
+ if (heap->size) {
+ for (i = 0; i < heap->size; i++) {
+- struct task_struct *p = heap->ptrs[i];
++ struct task_struct *q = heap->ptrs[i];
+ if (i == 0) {
+- latest_time = p->start_time;
+- latest_task = p;
++ latest_time = q->start_time;
++ latest_task = q;
+ }
+ /* Process the task per the caller's callback */
+- scan->process_task(p, scan);
+- put_task_struct(p);
++ scan->process_task(q, scan);
++ put_task_struct(q);
+ }
+ /*
+ * If we had to process any tasks at all, scan again
+@@ -2133,11 +2227,6 @@ static u64 cgroup_read_notify_on_release(struct cgroup *cgrp,
+ return notify_on_release(cgrp);
+ }
+
+-static u64 cgroup_read_releasable(struct cgroup *cgrp, struct cftype *cft)
+-{
+- return test_bit(CGRP_RELEASABLE, &cgrp->flags);
+-}
+-
+ /*
+ * for the common functions, 'private' gives the type of file
+ */
+@@ -2153,16 +2242,10 @@ static struct cftype files[] = {
+
+ {
+ .name = "notify_on_release",
+- .read_uint = cgroup_read_notify_on_release,
++ .read_u64 = cgroup_read_notify_on_release,
+ .write = cgroup_common_file_write,
+ .private = FILE_NOTIFY_ON_RELEASE,
+ },
+-
+- {
+- .name = "releasable",
+- .read_uint = cgroup_read_releasable,
+- .private = FILE_RELEASABLE,
+- }
+ };
+
+ static struct cftype cft_release_agent = {
+@@ -2396,10 +2479,9 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry)
+ return 0;
+ }
+
+-static void cgroup_init_subsys(struct cgroup_subsys *ss)
++static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
+ {
+ struct cgroup_subsys_state *css;
+- struct list_head *l;
+
+ printk(KERN_INFO "Initializing cgroup subsys %s\n", ss->name);
+
+@@ -2410,34 +2492,19 @@ static void cgroup_init_subsys(struct cgroup_subsys *ss)
+ BUG_ON(IS_ERR(css));
+ init_cgroup_css(css, ss, dummytop);
+
+- /* Update all cgroup groups to contain a subsys
++ /* Update the init_css_set to contain a subsys
+ * pointer to this state - since the subsystem is
+- * newly registered, all tasks and hence all cgroup
+- * groups are in the subsystem's top cgroup. */
+- write_lock(&css_set_lock);
+- l = &init_css_set.list;
+- do {
+- struct css_set *cg =
+- list_entry(l, struct css_set, list);
+- cg->subsys[ss->subsys_id] = dummytop->subsys[ss->subsys_id];
+- l = l->next;
+- } while (l != &init_css_set.list);
+- write_unlock(&css_set_lock);
+-
+- /* If this subsystem requested that it be notified with fork
+- * events, we should send it one now for every process in the
+- * system */
+- if (ss->fork) {
+- struct task_struct *g, *p;
+-
+- read_lock(&tasklist_lock);
+- do_each_thread(g, p) {
+- ss->fork(ss, p);
+- } while_each_thread(g, p);
+- read_unlock(&tasklist_lock);
+- }
++ * newly registered, all tasks and hence the
++ * init_css_set is in the subsystem's top cgroup. */
++ init_css_set.subsys[ss->subsys_id] = dummytop->subsys[ss->subsys_id];
+
+ need_forkexit_callback |= ss->fork || ss->exit;
++ need_mm_owner_callback |= !!ss->mm_owner_changed;
++
++ /* At system boot, before all subsystems have been
++ * registered, no tasks have been forked, so we don't
++ * need to invoke fork callbacks here. */
++ BUG_ON(!list_empty(&init_task.tasks));
+
+ ss->active = 1;
+ }
+@@ -2453,9 +2520,9 @@ int __init cgroup_init_early(void)
+ int i;
+ kref_init(&init_css_set.ref);
+ kref_get(&init_css_set.ref);
+- INIT_LIST_HEAD(&init_css_set.list);
+ INIT_LIST_HEAD(&init_css_set.cg_links);
+ INIT_LIST_HEAD(&init_css_set.tasks);
++ INIT_HLIST_NODE(&init_css_set.hlist);
+ css_set_count = 1;
+ init_cgroup_root(&rootnode);
+ list_add(&rootnode.root_list, &roots);
+@@ -2468,6 +2535,9 @@ int __init cgroup_init_early(void)
+ list_add(&init_css_set_link.cg_link_list,
+ &init_css_set.cg_links);
+
++ for (i = 0; i < CSS_SET_TABLE_SIZE; i++)
++ INIT_HLIST_HEAD(&css_set_table[i]);
++
+ for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ struct cgroup_subsys *ss = subsys[i];
+
+@@ -2497,7 +2567,7 @@ int __init cgroup_init(void)
+ {
+ int err;
+ int i;
+- struct proc_dir_entry *entry;
++ struct hlist_head *hhead;
+
+ err = bdi_init(&cgroup_backing_dev_info);
+ if (err)
+@@ -2509,13 +2579,15 @@ int __init cgroup_init(void)
+ cgroup_init_subsys(ss);
+ }
+
++ /* Add init_css_set to the hash table */
++ hhead = css_set_hash(init_css_set.subsys);
++ hlist_add_head(&init_css_set.hlist, hhead);
++
+ err = register_filesystem(&cgroup_fs_type);
+ if (err < 0)
+ goto out;
+
+- entry = create_proc_entry("cgroups", 0, NULL);
+- if (entry)
+- entry->proc_fops = &proc_cgroupstats_operations;
++ proc_create("cgroups", 0, NULL, &proc_cgroupstats_operations);
+
+ out:
+ if (err)
+@@ -2678,6 +2750,34 @@ void cgroup_fork_callbacks(struct task_struct *child)
+ }
+ }
+
++#ifdef CONFIG_MM_OWNER
++/**
++ * cgroup_mm_owner_callbacks - run callbacks when the mm->owner changes
++ * @p: the new owner
++ *
++ * Called on every change to mm->owner. mm_init_owner() does not
++ * invoke this routine, since it assigns the mm->owner the first time
++ * and does not change it.
++ */
++void cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new)
++{
++ struct cgroup *oldcgrp, *newcgrp;
++
++ if (need_mm_owner_callback) {
++ int i;
++ for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
++ struct cgroup_subsys *ss = subsys[i];
++ oldcgrp = task_cgroup(old, ss->subsys_id);
++ newcgrp = task_cgroup(new, ss->subsys_id);
++ if (oldcgrp == newcgrp)
++ continue;
++ if (ss->mm_owner_changed)
++ ss->mm_owner_changed(ss, oldcgrp, newcgrp);
++ }
++ }
++}
++#endif /* CONFIG_MM_OWNER */
++
+ /**
+ * cgroup_post_fork - called on a new task after adding it to the task list
+ * @child: the task in question
+diff --git a/kernel/cgroup_debug.c b/kernel/cgroup_debug.c
+index 37301e8..c3dc3ab 100644
+--- a/kernel/cgroup_debug.c
++++ b/kernel/cgroup_debug.c
+@@ -1,5 +1,5 @@
+ /*
+- * kernel/ccontainer_debug.c - Example cgroup subsystem that
++ * kernel/cgroup_debug.c - Example cgroup subsystem that
+ * exposes debug info
+ *
+ * Copyright (C) Google Inc, 2007
+@@ -62,25 +62,35 @@ static u64 current_css_set_refcount_read(struct cgroup *cont,
+ return count;
+ }
+
++static u64 releasable_read(struct cgroup *cgrp, struct cftype *cft)
++{
++ return test_bit(CGRP_RELEASABLE, &cgrp->flags);
++}
++
+ static struct cftype files[] = {
+ {
+ .name = "cgroup_refcount",
+- .read_uint = cgroup_refcount_read,
++ .read_u64 = cgroup_refcount_read,
+ },
+ {
+ .name = "taskcount",
+- .read_uint = taskcount_read,
++ .read_u64 = taskcount_read,
+ },
+
+ {
+ .name = "current_css_set",
+- .read_uint = current_css_set_read,
++ .read_u64 = current_css_set_read,
+ },
+
+ {
+ .name = "current_css_set_refcount",
+- .read_uint = current_css_set_refcount_read,
++ .read_u64 = current_css_set_refcount_read,
+ },
++
++ {
++ .name = "releasable",
++ .read_u64 = releasable_read,
++ }
+ };
+
+ static int debug_populate(struct cgroup_subsys *ss, struct cgroup *cont)
diff --git a/kernel/compat.c b/kernel/compat.c
-index 5f0e201..e1ef048 100644
+index 5f0e201..4a856a3 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -47,15 +47,14 @@ static long compat_nanosleep_restart(struct restart_block *restart)
@@ -831302,11 +1115651,166 @@
}
return err;
}
+@@ -899,7 +898,7 @@ asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat
+
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+- set_thread_flag(TIF_RESTORE_SIGMASK);
++ set_restore_sigmask();
+ return -ERESTARTNOHAND;
+ }
+ #endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */
+@@ -1081,4 +1080,3 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info)
+
+ return 0;
+ }
+-
+diff --git a/kernel/configs.c b/kernel/configs.c
+index e84d3f9..4c34521 100644
+--- a/kernel/configs.c
++++ b/kernel/configs.c
+@@ -79,12 +79,11 @@ static int __init ikconfig_init(void)
+ struct proc_dir_entry *entry;
+
+ /* create the current config file */
+- entry = create_proc_entry("config.gz", S_IFREG | S_IRUGO,
+- &proc_root);
++ entry = proc_create("config.gz", S_IFREG | S_IRUGO, NULL,
++ &ikconfig_file_ops);
+ if (!entry)
+ return -ENOMEM;
+
+- entry->proc_fops = &ikconfig_file_ops;
+ entry->size = kernel_config_data_size;
+
+ return 0;
+@@ -95,7 +94,7 @@ static int __init ikconfig_init(void)
+
+ static void __exit ikconfig_cleanup(void)
+ {
+- remove_proc_entry("config.gz", &proc_root);
++ remove_proc_entry("config.gz", NULL);
+ }
+
+ module_init(ikconfig_init);
diff --git a/kernel/cpu.c b/kernel/cpu.c
-index 2eff3f6..2011ad8 100644
+index 2eff3f6..c77bc3a 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
-@@ -232,9 +232,9 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
+@@ -33,17 +33,13 @@ static struct {
+ * an ongoing cpu hotplug operation.
+ */
+ int refcount;
+- wait_queue_head_t writer_queue;
+ } cpu_hotplug;
+
+-#define writer_exists() (cpu_hotplug.active_writer != NULL)
+-
+ void __init cpu_hotplug_init(void)
+ {
+ cpu_hotplug.active_writer = NULL;
+ mutex_init(&cpu_hotplug.lock);
+ cpu_hotplug.refcount = 0;
+- init_waitqueue_head(&cpu_hotplug.writer_queue);
+ }
+
+ #ifdef CONFIG_HOTPLUG_CPU
+@@ -65,11 +61,8 @@ void put_online_cpus(void)
+ if (cpu_hotplug.active_writer == current)
+ return;
+ mutex_lock(&cpu_hotplug.lock);
+- cpu_hotplug.refcount--;
+-
+- if (unlikely(writer_exists()) && !cpu_hotplug.refcount)
+- wake_up(&cpu_hotplug.writer_queue);
+-
++ if (!--cpu_hotplug.refcount && unlikely(cpu_hotplug.active_writer))
++ wake_up_process(cpu_hotplug.active_writer);
+ mutex_unlock(&cpu_hotplug.lock);
+
+ }
+@@ -98,8 +91,8 @@ void cpu_maps_update_done(void)
+ * Note that during a cpu-hotplug operation, the new readers, if any,
+ * will be blocked by the cpu_hotplug.lock
+ *
+- * Since cpu_maps_update_begin is always called after invoking
+- * cpu_maps_update_begin, we can be sure that only one writer is active.
++ * Since cpu_hotplug_begin() is always called after invoking
++ * cpu_maps_update_begin(), we can be sure that only one writer is active.
+ *
+ * Note that theoretically, there is a possibility of a livelock:
+ * - Refcount goes to zero, last reader wakes up the sleeping
+@@ -115,19 +108,16 @@ void cpu_maps_update_done(void)
+ */
+ static void cpu_hotplug_begin(void)
+ {
+- DECLARE_WAITQUEUE(wait, current);
+-
+- mutex_lock(&cpu_hotplug.lock);
+-
+ cpu_hotplug.active_writer = current;
+- add_wait_queue_exclusive(&cpu_hotplug.writer_queue, &wait);
+- while (cpu_hotplug.refcount) {
+- set_current_state(TASK_UNINTERRUPTIBLE);
++
++ for (;;) {
++ mutex_lock(&cpu_hotplug.lock);
++ if (likely(!cpu_hotplug.refcount))
++ break;
++ __set_current_state(TASK_UNINTERRUPTIBLE);
+ mutex_unlock(&cpu_hotplug.lock);
+ schedule();
+- mutex_lock(&cpu_hotplug.lock);
+ }
+- remove_wait_queue_locked(&cpu_hotplug.writer_queue, &wait);
+ }
+
+ static void cpu_hotplug_done(void)
+@@ -136,7 +126,7 @@ static void cpu_hotplug_done(void)
+ mutex_unlock(&cpu_hotplug.lock);
+ }
+ /* Need to know about CPUs going up/down? */
+-int __cpuinit register_cpu_notifier(struct notifier_block *nb)
++int __ref register_cpu_notifier(struct notifier_block *nb)
+ {
+ int ret;
+ cpu_maps_update_begin();
+@@ -149,7 +139,7 @@ int __cpuinit register_cpu_notifier(struct notifier_block *nb)
+
+ EXPORT_SYMBOL(register_cpu_notifier);
+
+-void unregister_cpu_notifier(struct notifier_block *nb)
++void __ref unregister_cpu_notifier(struct notifier_block *nb)
+ {
+ cpu_maps_update_begin();
+ raw_notifier_chain_unregister(&cpu_chain, nb);
+@@ -180,7 +170,7 @@ struct take_cpu_down_param {
+ };
+
+ /* Take this CPU down. */
+-static int take_cpu_down(void *_param)
++static int __ref take_cpu_down(void *_param)
+ {
+ struct take_cpu_down_param *param = _param;
+ int err;
+@@ -199,7 +189,7 @@ static int take_cpu_down(void *_param)
+ }
+
+ /* Requires cpu_add_remove_lock to be held */
+-static int _cpu_down(unsigned int cpu, int tasks_frozen)
++static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
+ {
+ int err, nr_calls = 0;
+ struct task_struct *p;
+@@ -225,16 +215,16 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
+ __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod,
+ hcpu, nr_calls, NULL);
+ printk("%s: attempt to take down CPU %u failed\n",
+- __FUNCTION__, cpu);
++ __func__, cpu);
+ err = -EINVAL;
+ goto out_release;
+ }
/* Ensure that we are not runnable on dying cpu */
old_allowed = current->cpus_allowed;
@@ -831318,7 +1115822,7 @@
p = __stop_machine_run(take_cpu_down, &tcd_param, cpu);
-@@ -268,7 +268,7 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
+@@ -268,13 +258,13 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
out_thread:
err = kthread_stop(p);
out_allowed:
@@ -831327,8 +1115831,24 @@
out_release:
cpu_hotplug_done();
return err;
+ }
+
+-int cpu_down(unsigned int cpu)
++int __ref cpu_down(unsigned int cpu)
+ {
+ int err = 0;
+
+@@ -305,7 +295,7 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen)
+ if (ret == NOTIFY_BAD) {
+ nr_calls--;
+ printk("%s: attempt to bring up CPU %u failed\n",
+- __FUNCTION__, cpu);
++ __func__, cpu);
+ ret = -EINVAL;
+ goto out_notify;
+ }
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
-index a1b61f4..8b35fbd 100644
+index a1b61f4..8da627d 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -98,6 +98,9 @@ struct cpuset {
@@ -831341,7 +1115861,27 @@
/* 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)
+@@ -124,6 +127,7 @@ struct cpuset_hotplug_scanner {
+ typedef enum {
+ CS_CPU_EXCLUSIVE,
+ CS_MEM_EXCLUSIVE,
++ CS_MEM_HARDWALL,
+ CS_MEMORY_MIGRATE,
+ CS_SCHED_LOAD_BALANCE,
+ CS_SPREAD_PAGE,
+@@ -141,6 +145,11 @@ static inline int is_mem_exclusive(const struct cpuset *cs)
+ return test_bit(CS_MEM_EXCLUSIVE, &cs->flags);
+ }
+
++static inline int is_mem_hardwall(const struct cpuset *cs)
++{
++ return test_bit(CS_MEM_HARDWALL, &cs->flags);
++}
++
+ static inline int is_sched_load_balance(const struct cpuset *cs)
+ {
+ return test_bit(CS_SCHED_LOAD_BALANCE, &cs->flags);
+@@ -478,6 +487,16 @@ static int cpusets_overlap(struct cpuset *a, struct cpuset *b)
return cpus_intersects(a->cpus_allowed, b->cpus_allowed);
}
@@ -831358,7 +1115898,7 @@
/*
* rebuild_sched_domains()
*
-@@ -553,12 +566,14 @@ static void rebuild_sched_domains(void)
+@@ -553,12 +572,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 */
@@ -831373,7 +1115913,7 @@
/* 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)
+@@ -566,6 +587,11 @@ static void rebuild_sched_domains(void)
doms = kmalloc(sizeof(cpumask_t), GFP_KERNEL);
if (!doms)
goto rebuild;
@@ -831385,7 +1115925,7 @@
*doms = top_cpuset.cpus_allowed;
goto rebuild;
}
-@@ -622,6 +642,7 @@ restart:
+@@ -622,6 +648,7 @@ restart:
doms = kmalloc(ndoms * sizeof(cpumask_t), GFP_KERNEL);
if (!doms)
goto rebuild;
@@ -831393,7 +1115933,7 @@
for (nslot = 0, i = 0; i < csn; i++) {
struct cpuset *a = csa[i];
-@@ -644,12 +665,15 @@ restart:
+@@ -644,12 +671,15 @@ restart:
}
cpus_clear(*dp);
@@ -831409,7 +1115949,7 @@
}
}
nslot++;
-@@ -660,7 +684,7 @@ restart:
+@@ -660,7 +690,7 @@ restart:
rebuild:
/* Have scheduler rebuild sched domains */
get_online_cpus();
@@ -831418,7 +1115958,7 @@
put_online_cpus();
done:
-@@ -668,6 +692,7 @@ done:
+@@ -668,6 +698,7 @@ done:
kfifo_free(q);
kfree(csa);
/* Don't kfree(doms) -- partition_sched_domains() does that. */
@@ -831426,21 +1115966,62 @@
}
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)
+@@ -710,7 +741,8 @@ static inline int started_after(void *p1, void *p2)
+ * Return nonzero if this tasks's cpus_allowed mask should be changed (in other
+ * words, if its mask is not equal to its cpuset's mask).
+ */
+-int cpuset_test_cpumask(struct task_struct *tsk, struct cgroup_scanner *scan)
++static int cpuset_test_cpumask(struct task_struct *tsk,
++ struct cgroup_scanner *scan)
+ {
+ return !cpus_equal(tsk->cpus_allowed,
+ (cgroup_cs(scan->cg))->cpus_allowed);
+@@ -727,9 +759,10 @@ int cpuset_test_cpumask(struct task_struct *tsk, struct cgroup_scanner *scan)
+ * We don't need to re-check for the cgroup/cpuset membership, since we're
+ * holding cgroup_lock() at this point.
+ */
+-void cpuset_change_cpumask(struct task_struct *tsk, struct cgroup_scanner *scan)
++static 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;
+@@ -916,7 +949,7 @@ static int update_nodemask(struct cpuset *cs, char *buf)
+ cs->mems_generation = cpuset_mems_generation++;
+ mutex_unlock(&callback_mutex);
+
+- cpuset_being_rebound = cs; /* causes mpol_copy() rebind */
++ cpuset_being_rebound = cs; /* causes mpol_dup() rebind */
+
+ fudge = 10; /* spare mmarray[] slots */
+ fudge += cpus_weight(cs->cpus_allowed); /* imagine one fork-bomb/cpu */
+@@ -967,7 +1000,7 @@ static int update_nodemask(struct cpuset *cs, char *buf)
+ * rebind the vma mempolicies of each mm in mmarray[] to their
+ * new cpuset, and release that mm. The mpol_rebind_mm()
+ * call takes mmap_sem, which we couldn't take while holding
+- * tasklist_lock. Forks can happen again now - the mpol_copy()
++ * tasklist_lock. Forks can happen again now - the mpol_dup()
+ * cpuset_being_rebound check will catch such forks, and rebind
+ * their vma mempolicies too. Because we still hold the global
+ * cgroup_mutex, we know that no other rebind effort will
+@@ -998,40 +1031,37 @@ int current_cpuset_is_being_rebound(void)
+ return task_cs(current) == cpuset_being_rebound;
}
+-/*
+- * Call with cgroup_mutex held.
+- */
+-
+-static int update_memory_pressure_enabled(struct cpuset *cs, char *buf)
+static int update_relax_domain_level(struct cpuset *cs, char *buf)
-+{
+ {
+- if (simple_strtoul(buf, NULL, 10) != 0)
+- cpuset_memory_pressure_enabled = 1;
+- else
+- cpuset_memory_pressure_enabled = 0;
+ int val = simple_strtol(buf, NULL, 10);
+
+ if (val < 0)
@@ -831451,13 +1116032,39 @@
+ rebuild_sched_domains();
+ }
+
-+ return 0;
-+}
-+
+ 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,
+- * bit: the bit to update (CS_CPU_EXCLUSIVE, CS_MEM_EXCLUSIVE,
+- * CS_SCHED_LOAD_BALANCE,
+- * CS_NOTIFY_ON_RELEASE, CS_MEMORY_MIGRATE,
+- * CS_SPREAD_PAGE, CS_SPREAD_SLAB)
+- * cs: the cpuset to update
+- * buf: the buffer where we read the 0 or 1
++ * bit: the bit to update (see cpuset_flagbits_t)
++ * cs: the cpuset to update
++ * turning_on: whether the flag is being set or cleared
+ *
+ * Call with cgroup_mutex held.
+ */
+
+-static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf)
++static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
++ int turning_on)
+ {
+- int turning_on;
+ struct cpuset trialcs;
+ int err;
+ int cpus_nonempty, balance_flag_changed;
+
+- turning_on = (simple_strtoul(buf, NULL, 10) != 0);
+-
+ trialcs = *cs;
+ if (turning_on)
+ set_bit(bit, &trialcs.flags);
+@@ -1178,7 +1208,7 @@ static void cpuset_attach(struct cgroup_subsys *ss,
mutex_lock(&callback_mutex);
guarantee_online_cpus(cs, &cpus);
@@ -831466,59 +1116073,368 @@
mutex_unlock(&callback_mutex);
from = oldcs->mems_allowed;
-@@ -1202,6 +1242,7 @@ typedef enum {
+@@ -1201,7 +1231,9 @@ typedef enum {
+ FILE_MEMLIST,
FILE_CPU_EXCLUSIVE,
FILE_MEM_EXCLUSIVE,
++ FILE_MEM_HARDWALL,
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);
+@@ -1224,7 +1256,8 @@ static ssize_t cpuset_common_file_write(struct cgroup *cont,
+ return -E2BIG;
+
+ /* +1 for nul-terminator */
+- if ((buffer = kmalloc(nbytes + 1, GFP_KERNEL)) == 0)
++ buffer = kmalloc(nbytes + 1, GFP_KERNEL);
++ if (!buffer)
+ return -ENOMEM;
+
+ if (copy_from_user(buffer, userbuf, nbytes)) {
+@@ -1247,43 +1280,71 @@ static ssize_t cpuset_common_file_write(struct cgroup *cont,
+ case FILE_MEMLIST:
+ retval = update_nodemask(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);
++ default:
++ retval = -EINVAL;
++ goto out2;
++ }
++
++ if (retval == 0)
++ retval = nbytes;
++out2:
++ cgroup_unlock();
++out1:
++ kfree(buffer);
++ return retval;
++}
++
++static int cpuset_write_u64(struct cgroup *cgrp, struct cftype *cft, u64 val)
++{
++ int retval = 0;
++ struct cpuset *cs = cgroup_cs(cgrp);
++ cpuset_filetype_t type = cft->private;
++
++ cgroup_lock();
++
++ if (cgroup_is_removed(cgrp)) {
++ cgroup_unlock();
++ return -ENODEV;
++ }
++
++ switch (type) {
+ case FILE_CPU_EXCLUSIVE:
+- retval = update_flag(CS_CPU_EXCLUSIVE, cs, buffer);
++ retval = update_flag(CS_CPU_EXCLUSIVE, cs, val);
+ break;
+ case FILE_MEM_EXCLUSIVE:
+- retval = update_flag(CS_MEM_EXCLUSIVE, cs, buffer);
++ retval = update_flag(CS_MEM_EXCLUSIVE, cs, val);
++ break;
++ case FILE_MEM_HARDWALL:
++ retval = update_flag(CS_MEM_HARDWALL, cs, val);
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';
+- retval = update_flag(CS_SCHED_LOAD_BALANCE, cs, buffer);
++ retval = update_flag(CS_SCHED_LOAD_BALANCE, cs, val);
+ break;
+ case FILE_MEMORY_MIGRATE:
+- retval = update_flag(CS_MEMORY_MIGRATE, cs, buffer);
++ retval = update_flag(CS_MEMORY_MIGRATE, cs, val);
+ break;
+ case FILE_MEMORY_PRESSURE_ENABLED:
+- retval = update_memory_pressure_enabled(cs, buffer);
++ cpuset_memory_pressure_enabled = !!val;
+ break;
+ case FILE_MEMORY_PRESSURE:
+ retval = -EACCES;
+ break;
+ case FILE_SPREAD_PAGE:
+- retval = update_flag(CS_SPREAD_PAGE, cs, buffer);
++ retval = update_flag(CS_SPREAD_PAGE, cs, val);
+ cs->mems_generation = cpuset_mems_generation++;
+ break;
+ case FILE_SPREAD_SLAB:
+- retval = update_flag(CS_SPREAD_SLAB, cs, buffer);
++ retval = update_flag(CS_SPREAD_SLAB, cs, val);
+ cs->mems_generation = cpuset_mems_generation++;
break;
+ default:
+ retval = -EINVAL;
+- goto out2;
++ break;
+ }
+-
+- if (retval == 0)
+- retval = nbytes;
+-out2:
+ cgroup_unlock();
+-out1:
+- kfree(buffer);
+ return retval;
+ }
+
+@@ -1345,29 +1406,8 @@ static ssize_t cpuset_common_file_read(struct cgroup *cont,
+ case FILE_MEMLIST:
+ s += cpuset_sprintf_memlist(s, cs);
+ break;
+- case FILE_CPU_EXCLUSIVE:
+- *s++ = is_cpu_exclusive(cs) ? '1' : '0';
+- break;
+- case FILE_MEM_EXCLUSIVE:
+- *s++ = is_mem_exclusive(cs) ? '1' : '0';
+- break;
+- case FILE_SCHED_LOAD_BALANCE:
+- *s++ = is_sched_load_balance(cs) ? '1' : '0';
+- break;
+- case FILE_MEMORY_MIGRATE:
+- *s++ = is_memory_migrate(cs) ? '1' : '0';
+- break;
+- case FILE_MEMORY_PRESSURE_ENABLED:
+- *s++ = cpuset_memory_pressure_enabled ? '1' : '0';
+- break;
+- case FILE_MEMORY_PRESSURE:
+- s += sprintf(s, "%d", fmeter_getrate(&cs->fmeter));
+- break;
+- case FILE_SPREAD_PAGE:
+- *s++ = is_spread_page(cs) ? '1' : '0';
+- break;
+- case FILE_SPREAD_SLAB:
+- *s++ = is_spread_slab(cs) ? '1' : '0';
+ 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,
- };
+ default:
+ retval = -EINVAL;
+@@ -1381,111 +1421,137 @@ out:
+ return retval;
+ }
-+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 u64 cpuset_read_u64(struct cgroup *cont, struct cftype *cft)
++{
++ struct cpuset *cs = cgroup_cs(cont);
++ cpuset_filetype_t type = cft->private;
++ switch (type) {
++ case FILE_CPU_EXCLUSIVE:
++ return is_cpu_exclusive(cs);
++ case FILE_MEM_EXCLUSIVE:
++ return is_mem_exclusive(cs);
++ case FILE_MEM_HARDWALL:
++ return is_mem_hardwall(cs);
++ case FILE_SCHED_LOAD_BALANCE:
++ return is_sched_load_balance(cs);
++ case FILE_MEMORY_MIGRATE:
++ return is_memory_migrate(cs);
++ case FILE_MEMORY_PRESSURE_ENABLED:
++ return cpuset_memory_pressure_enabled;
++ case FILE_MEMORY_PRESSURE:
++ return fmeter_getrate(&cs->fmeter);
++ case FILE_SPREAD_PAGE:
++ return is_spread_page(cs);
++ case FILE_SPREAD_SLAB:
++ return is_spread_slab(cs);
++ default:
++ BUG();
++ }
++}
+
+
+ /*
+ * for the common functions, 'private' gives the type of file
+ */
+
+-static struct cftype cft_cpus = {
+- .name = "cpus",
+- .read = cpuset_common_file_read,
+- .write = cpuset_common_file_write,
+- .private = FILE_CPULIST,
+-};
+-
+-static struct cftype cft_mems = {
+- .name = "mems",
+- .read = cpuset_common_file_read,
+- .write = cpuset_common_file_write,
+- .private = FILE_MEMLIST,
+-};
+-
+-static struct cftype cft_cpu_exclusive = {
+- .name = "cpu_exclusive",
+- .read = cpuset_common_file_read,
+- .write = cpuset_common_file_write,
+- .private = FILE_CPU_EXCLUSIVE,
+-};
+-
+-static struct cftype cft_mem_exclusive = {
+- .name = "mem_exclusive",
+- .read = cpuset_common_file_read,
+- .write = cpuset_common_file_write,
+- .private = FILE_MEM_EXCLUSIVE,
+-};
+-
+-static struct cftype cft_sched_load_balance = {
+- .name = "sched_load_balance",
+- .read = cpuset_common_file_read,
+- .write = cpuset_common_file_write,
+- .private = FILE_SCHED_LOAD_BALANCE,
+-};
+-
+-static struct cftype cft_memory_migrate = {
+- .name = "memory_migrate",
+- .read = cpuset_common_file_read,
+- .write = cpuset_common_file_write,
+- .private = FILE_MEMORY_MIGRATE,
++static struct cftype files[] = {
++ {
++ .name = "cpus",
++ .read = cpuset_common_file_read,
++ .write = cpuset_common_file_write,
++ .private = FILE_CPULIST,
++ },
+
- 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)
++ {
++ .name = "mems",
++ .read = cpuset_common_file_read,
++ .write = cpuset_common_file_write,
++ .private = FILE_MEMLIST,
++ },
++
++ {
++ .name = "cpu_exclusive",
++ .read_u64 = cpuset_read_u64,
++ .write_u64 = cpuset_write_u64,
++ .private = FILE_CPU_EXCLUSIVE,
++ },
++
++ {
++ .name = "mem_exclusive",
++ .read_u64 = cpuset_read_u64,
++ .write_u64 = cpuset_write_u64,
++ .private = FILE_MEM_EXCLUSIVE,
++ },
++
++ {
++ .name = "mem_hardwall",
++ .read_u64 = cpuset_read_u64,
++ .write_u64 = cpuset_write_u64,
++ .private = FILE_MEM_HARDWALL,
++ },
++
++ {
++ .name = "sched_load_balance",
++ .read_u64 = cpuset_read_u64,
++ .write_u64 = cpuset_write_u64,
++ .private = FILE_SCHED_LOAD_BALANCE,
++ },
++
++ {
++ .name = "sched_relax_domain_level",
++ .read_u64 = cpuset_read_u64,
++ .write_u64 = cpuset_write_u64,
++ .private = FILE_SCHED_RELAX_DOMAIN_LEVEL,
++ },
++
++ {
++ .name = "memory_migrate",
++ .read_u64 = cpuset_read_u64,
++ .write_u64 = cpuset_write_u64,
++ .private = FILE_MEMORY_MIGRATE,
++ },
++
++ {
++ .name = "memory_pressure",
++ .read_u64 = cpuset_read_u64,
++ .write_u64 = cpuset_write_u64,
++ .private = FILE_MEMORY_PRESSURE,
++ },
++
++ {
++ .name = "memory_spread_page",
++ .read_u64 = cpuset_read_u64,
++ .write_u64 = cpuset_write_u64,
++ .private = FILE_SPREAD_PAGE,
++ },
++
++ {
++ .name = "memory_spread_slab",
++ .read_u64 = cpuset_read_u64,
++ .write_u64 = cpuset_write_u64,
++ .private = FILE_SPREAD_SLAB,
++ },
+ };
+
+ static struct cftype cft_memory_pressure_enabled = {
+ .name = "memory_pressure_enabled",
+- .read = cpuset_common_file_read,
+- .write = cpuset_common_file_write,
++ .read_u64 = cpuset_read_u64,
++ .write_u64 = cpuset_write_u64,
+ .private = FILE_MEMORY_PRESSURE_ENABLED,
+ };
+
+-static struct cftype cft_memory_pressure = {
+- .name = "memory_pressure",
+- .read = cpuset_common_file_read,
+- .write = cpuset_common_file_write,
+- .private = FILE_MEMORY_PRESSURE,
+-};
+-
+-static struct cftype cft_spread_page = {
+- .name = "memory_spread_page",
+- .read = cpuset_common_file_read,
+- .write = cpuset_common_file_write,
+- .private = FILE_SPREAD_PAGE,
+-};
+-
+-static struct cftype cft_spread_slab = {
+- .name = "memory_spread_slab",
+- .read = cpuset_common_file_read,
+- .write = cpuset_common_file_write,
+- .private = FILE_SPREAD_SLAB,
+-};
+-
+ static int cpuset_populate(struct cgroup_subsys *ss, struct cgroup *cont)
+ {
+ int err;
+
+- if ((err = cgroup_add_file(cont, ss, &cft_cpus)) < 0)
+- return err;
+- if ((err = cgroup_add_file(cont, ss, &cft_mems)) < 0)
+- return err;
+- if ((err = cgroup_add_file(cont, ss, &cft_cpu_exclusive)) < 0)
+- return err;
+- if ((err = cgroup_add_file(cont, ss, &cft_mem_exclusive)) < 0)
+- return err;
+- if ((err = cgroup_add_file(cont, ss, &cft_memory_migrate)) < 0)
+- return err;
+- if ((err = cgroup_add_file(cont, ss, &cft_sched_load_balance)) < 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)
+- return err;
+- if ((err = cgroup_add_file(cont, ss, &cft_spread_slab)) < 0)
++ err = cgroup_add_files(cont, ss, files, ARRAY_SIZE(files));
++ if (err)
return err;
- if ((err = cgroup_add_file(cont, ss, &cft_spread_page)) < 0)
-@@ -1555,10 +1612,11 @@ static struct cgroup_subsys_state *cpuset_create(
+ /* memory_pressure_enabled is in root cpuset only */
+- if (err == 0 && !cont->parent)
++ if (!cont->parent)
+ err = cgroup_add_file(cont, ss,
+- &cft_memory_pressure_enabled);
+- return 0;
++ &cft_memory_pressure_enabled);
++ return err;
+ }
+
+ /*
+@@ -1555,10 +1621,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);
@@ -831532,7 +1116448,16 @@
cs->parent = parent;
number_of_cpusets++;
-@@ -1625,12 +1683,13 @@ int __init cpuset_init(void)
+@@ -1584,7 +1651,7 @@ static void cpuset_destroy(struct cgroup_subsys *ss, struct cgroup *cont)
+ cpuset_update_task_memory_state();
+
+ if (is_sched_load_balance(cs))
+- update_flag(CS_SCHED_LOAD_BALANCE, cs, "0");
++ update_flag(CS_SCHED_LOAD_BALANCE, cs, 0);
+
+ number_of_cpusets--;
+ kfree(cs);
+@@ -1625,12 +1692,13 @@ int __init cpuset_init(void)
{
int err = 0;
@@ -831548,7 +1116473,17 @@
err = register_filesystem(&cpuset_fs_type);
if (err < 0)
-@@ -1844,6 +1903,7 @@ void __init cpuset_init_smp(void)
+@@ -1648,7 +1716,8 @@ int __init cpuset_init(void)
+ * Called by cgroup_scan_tasks() for each task in a cgroup.
+ * Return nonzero to stop the walk through the tasks.
+ */
+-void cpuset_do_move_task(struct task_struct *tsk, struct cgroup_scanner *scan)
++static void cpuset_do_move_task(struct task_struct *tsk,
++ struct cgroup_scanner *scan)
+ {
+ struct cpuset_hotplug_scanner *chsp;
+
+@@ -1844,6 +1913,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.
@@ -831556,7 +1116491,7 @@
*
* 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)
+@@ -1851,35 +1921,27 @@ void __init cpuset_init_smp(void)
* tasks cpuset.
**/
@@ -831597,7 +1116532,88 @@
}
/**
-@@ -2261,8 +2313,16 @@ void cpuset_task_status_allowed(struct seq_file *m, struct task_struct *task)
+@@ -1906,33 +1968,25 @@ nodemask_t cpuset_mems_allowed(struct task_struct *tsk)
+ }
+
+ /**
+- * cpuset_zonelist_valid_mems_allowed - check zonelist vs. curremt mems_allowed
+- * @zl: the zonelist to be checked
++ * cpuset_nodemask_valid_mems_allowed - check nodemask vs. curremt mems_allowed
++ * @nodemask: the nodemask to be checked
+ *
+- * Are any of the nodes on zonelist zl allowed in current->mems_allowed?
++ * Are any of the nodes in the nodemask allowed in current->mems_allowed?
+ */
+-int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl)
++int cpuset_nodemask_valid_mems_allowed(nodemask_t *nodemask)
+ {
+- int i;
+-
+- for (i = 0; zl->zones[i]; i++) {
+- int nid = zone_to_nid(zl->zones[i]);
+-
+- if (node_isset(nid, current->mems_allowed))
+- return 1;
+- }
+- return 0;
++ return nodes_intersects(*nodemask, current->mems_allowed);
+ }
+
+ /*
+- * nearest_exclusive_ancestor() - Returns the nearest mem_exclusive
+- * ancestor to the specified cpuset. Call holding callback_mutex.
+- * If no ancestor is mem_exclusive (an unusual configuration), then
+- * returns the root cpuset.
++ * nearest_hardwall_ancestor() - Returns the nearest mem_exclusive or
++ * mem_hardwall ancestor to the specified cpuset. Call holding
++ * callback_mutex. If no ancestor is mem_exclusive or mem_hardwall
++ * (an unusual configuration), then returns the root cpuset.
+ */
+-static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs)
++static const struct cpuset *nearest_hardwall_ancestor(const struct cpuset *cs)
+ {
+- while (!is_mem_exclusive(cs) && cs->parent)
++ while (!(is_mem_exclusive(cs) || is_mem_hardwall(cs)) && cs->parent)
+ cs = cs->parent;
+ return cs;
+ }
+@@ -1946,7 +2000,7 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs)
+ * __GFP_THISNODE is set, yes, we can always allocate. If zone
+ * z's node is in our tasks mems_allowed, yes. If it's not a
+ * __GFP_HARDWALL request and this zone's nodes is in the nearest
+- * mem_exclusive cpuset ancestor to this tasks cpuset, yes.
++ * hardwalled cpuset ancestor to this tasks cpuset, yes.
+ * If the task has been OOM killed and has access to memory reserves
+ * as specified by the TIF_MEMDIE flag, yes.
+ * Otherwise, no.
+@@ -1969,7 +2023,7 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs)
+ * and do not allow allocations outside the current tasks cpuset
+ * unless the task has been OOM killed as is marked TIF_MEMDIE.
+ * GFP_KERNEL allocations are not so marked, so can escape to the
+- * nearest enclosing mem_exclusive ancestor cpuset.
++ * nearest enclosing hardwalled ancestor cpuset.
+ *
+ * Scanning up parent cpusets requires callback_mutex. The
+ * __alloc_pages() routine only calls here with __GFP_HARDWALL bit
+@@ -1992,7 +2046,7 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs)
+ * in_interrupt - any node ok (current task context irrelevant)
+ * GFP_ATOMIC - any node ok
+ * TIF_MEMDIE - any node ok
+- * GFP_KERNEL - any node in enclosing mem_exclusive cpuset ok
++ * GFP_KERNEL - any node in enclosing hardwalled cpuset ok
+ * GFP_USER - only nodes in current tasks mems allowed ok.
+ *
+ * Rule:
+@@ -2029,7 +2083,7 @@ int __cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask)
+ mutex_lock(&callback_mutex);
+
+ task_lock(current);
+- cs = nearest_exclusive_ancestor(task_cs(current));
++ cs = nearest_hardwall_ancestor(task_cs(current));
+ task_unlock(current);
+
+ allowed = node_isset(node, cs->mems_allowed);
+@@ -2261,8 +2315,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");
@@ -831614,11 +1116630,75 @@
+ task->mems_allowed);
+ seq_printf(m, "\n");
}
+diff --git a/kernel/dma.c b/kernel/dma.c
+index 6a82bb7..d2c60a8 100644
+--- a/kernel/dma.c
++++ b/kernel/dma.c
+@@ -149,12 +149,7 @@ static const struct file_operations proc_dma_operations = {
+
+ static int __init proc_dma_init(void)
+ {
+- struct proc_dir_entry *e;
+-
+- e = create_proc_entry("dma", 0, NULL);
+- if (e)
+- e->proc_fops = &proc_dma_operations;
+-
++ proc_create("dma", 0, NULL, &proc_dma_operations);
+ return 0;
+ }
+
diff --git a/kernel/exit.c b/kernel/exit.c
-index 073005b..97f609f 100644
+index 073005b..d3ad546 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
-@@ -507,10 +507,9 @@ void put_files_struct(struct files_struct *files)
+@@ -52,6 +52,11 @@
+
+ static void exit_mm(struct task_struct * tsk);
+
++static inline int task_detached(struct task_struct *p)
++{
++ return p->exit_signal == -1;
++}
++
+ static void __unhash_process(struct task_struct *p)
+ {
+ nr_threads--;
+@@ -160,7 +165,7 @@ repeat:
+ zap_leader = 0;
+ leader = p->group_leader;
+ if (leader != p && thread_group_empty(leader) && leader->exit_state == EXIT_ZOMBIE) {
+- BUG_ON(leader->exit_signal == -1);
++ BUG_ON(task_detached(leader));
+ do_notify_parent(leader, leader->exit_signal);
+ /*
+ * If we were the last child thread and the leader has
+@@ -170,7 +175,7 @@ repeat:
+ * do_notify_parent() will have marked it self-reaping in
+ * that case.
+ */
+- zap_leader = (leader->exit_signal == -1);
++ zap_leader = task_detached(leader);
+ }
+
+ write_unlock_irq(&tasklist_lock);
+@@ -329,13 +334,11 @@ void __set_special_pids(struct pid *pid)
+ pid_t nr = pid_nr(pid);
+
+ if (task_session(curr) != pid) {
+- detach_pid(curr, PIDTYPE_SID);
+- attach_pid(curr, PIDTYPE_SID, pid);
++ change_pid(curr, PIDTYPE_SID, pid);
+ set_task_session(curr, nr);
+ }
+ if (task_pgrp(curr) != pid) {
+- detach_pid(curr, PIDTYPE_PGID);
+- attach_pid(curr, PIDTYPE_PGID, pid);
++ change_pid(curr, PIDTYPE_PGID, pid);
+ set_task_pgrp(curr, nr);
+ }
+ }
+@@ -507,10 +510,9 @@ void put_files_struct(struct files_struct *files)
}
}
@@ -831631,7 +1116711,7 @@
struct files_struct *old;
old = tsk->files;
-@@ -519,9 +518,8 @@ void reset_files_struct(struct task_struct *tsk, struct files_struct *files)
+@@ -519,9 +521,8 @@ void reset_files_struct(struct task_struct *tsk, struct files_struct *files)
task_unlock(tsk);
put_files_struct(old);
}
@@ -831642,7 +1116722,7 @@
{
struct files_struct * files = tsk->files;
-@@ -533,12 +531,7 @@ static void __exit_files(struct task_struct *tsk)
+@@ -533,12 +534,7 @@ static void __exit_files(struct task_struct *tsk)
}
}
@@ -831656,7 +1116736,7 @@
{
/* 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)
+@@ -550,12 +546,7 @@ static void __put_fs_struct(struct fs_struct *fs)
}
}
@@ -831670,7 +1116750,7 @@
{
struct fs_struct * fs = tsk->fs;
-@@ -563,15 +551,10 @@ static void __exit_fs(struct task_struct *tsk)
+@@ -563,16 +554,93 @@ static void __exit_fs(struct task_struct *tsk)
task_lock(tsk);
tsk->fs = NULL;
task_unlock(tsk);
@@ -831680,14 +1116760,197 @@
}
-void exit_fs(struct task_struct *tsk)
--{
++EXPORT_SYMBOL_GPL(exit_fs);
++
++#ifdef CONFIG_MM_OWNER
++/*
++ * Task p is exiting and it owned mm, lets find a new owner for it
++ */
++static inline int
++mm_need_new_owner(struct mm_struct *mm, struct task_struct *p)
+ {
- __exit_fs(tsk);
--}
--
- EXPORT_SYMBOL_GPL(exit_fs);
++ /*
++ * If there are other users of the mm and the owner (us) is exiting
++ * we need to find a new owner to take on the responsibility.
++ */
++ if (!mm)
++ return 0;
++ if (atomic_read(&mm->mm_users) <= 1)
++ return 0;
++ if (mm->owner != p)
++ return 0;
++ return 1;
+ }
+
+-EXPORT_SYMBOL_GPL(exit_fs);
++void mm_update_next_owner(struct mm_struct *mm)
++{
++ struct task_struct *c, *g, *p = current;
++
++retry:
++ if (!mm_need_new_owner(mm, p))
++ return;
++
++ read_lock(&tasklist_lock);
++ /*
++ * Search in the children
++ */
++ list_for_each_entry(c, &p->children, sibling) {
++ if (c->mm == mm)
++ goto assign_new_owner;
++ }
++
++ /*
++ * Search in the siblings
++ */
++ list_for_each_entry(c, &p->parent->children, sibling) {
++ if (c->mm == mm)
++ goto assign_new_owner;
++ }
++
++ /*
++ * Search through everything else. We should not get
++ * here often
++ */
++ do_each_thread(g, c) {
++ if (c->mm == mm)
++ goto assign_new_owner;
++ } while_each_thread(g, c);
++
++ read_unlock(&tasklist_lock);
++ return;
++
++assign_new_owner:
++ BUG_ON(c == p);
++ get_task_struct(c);
++ /*
++ * The task_lock protects c->mm from changing.
++ * We always want mm->owner->mm == mm
++ */
++ task_lock(c);
++ /*
++ * Delay read_unlock() till we have the task_lock()
++ * to ensure that c does not slip away underneath us
++ */
++ read_unlock(&tasklist_lock);
++ if (c->mm != mm) {
++ task_unlock(c);
++ put_task_struct(c);
++ goto retry;
++ }
++ cgroup_mm_owner_callbacks(mm->owner, c);
++ mm->owner = c;
++ task_unlock(c);
++ put_task_struct(c);
++}
++#endif /* CONFIG_MM_OWNER */
/*
-@@ -967,8 +950,8 @@ NORET_TYPE void do_exit(long code)
+ * Turn us into a lazy TLB process if we
+@@ -613,6 +681,7 @@ static void exit_mm(struct task_struct * tsk)
+ /* We don't want this task to be frozen prematurely */
+ clear_freeze_flag(tsk);
+ task_unlock(tsk);
++ mm_update_next_owner(mm);
+ mmput(mm);
+ }
+
+@@ -627,7 +696,7 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
+ if (unlikely(traced)) {
+ /* Preserve ptrace links if someone else is tracing this child. */
+ list_del_init(&p->ptrace_list);
+- if (p->parent != p->real_parent)
++ if (ptrace_reparented(p))
+ list_add(&p->ptrace_list, &p->real_parent->ptrace_children);
+ } else {
+ /* If this child is being traced, then we're the one tracing it
+@@ -651,18 +720,18 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
+ /* If this is a threaded reparent there is no need to
+ * notify anyone anything has happened.
+ */
+- if (p->real_parent->group_leader == father->group_leader)
++ if (same_thread_group(p->real_parent, father))
+ return;
+
+ /* We don't want people slaying init. */
+- if (p->exit_signal != -1)
++ if (!task_detached(p))
+ p->exit_signal = SIGCHLD;
+
+ /* If we'd notified the old parent about this child's death,
+ * also notify the new parent.
+ */
+ if (!traced && p->exit_state == EXIT_ZOMBIE &&
+- p->exit_signal != -1 && thread_group_empty(p))
++ !task_detached(p) && thread_group_empty(p))
+ do_notify_parent(p, p->exit_signal);
+
+ kill_orphaned_pgrp(p, father);
+@@ -715,18 +784,18 @@ static void forget_original_parent(struct task_struct *father)
+ } else {
+ /* reparent ptraced task to its real parent */
+ __ptrace_unlink (p);
+- if (p->exit_state == EXIT_ZOMBIE && p->exit_signal != -1 &&
++ if (p->exit_state == EXIT_ZOMBIE && !task_detached(p) &&
+ thread_group_empty(p))
+ do_notify_parent(p, p->exit_signal);
+ }
+
+ /*
+- * if the ptraced child is a zombie with exit_signal == -1
+- * we must collect it before we exit, or it will remain
+- * zombie forever since we prevented it from self-reap itself
+- * while it was being traced by us, to be able to see it in wait4.
++ * if the ptraced child is a detached zombie we must collect
++ * it before we exit, or it will remain zombie forever since
++ * we prevented it from self-reap itself while it was being
++ * traced by us, to be able to see it in wait4.
+ */
+- if (unlikely(ptrace && p->exit_state == EXIT_ZOMBIE && p->exit_signal == -1))
++ if (unlikely(ptrace && p->exit_state == EXIT_ZOMBIE && task_detached(p)))
+ list_add(&p->ptrace_list, &ptrace_dead);
+ }
+
+@@ -783,29 +852,30 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
+ * we have changed execution domain as these two values started
+ * the same after a fork.
+ */
+- if (tsk->exit_signal != SIGCHLD && tsk->exit_signal != -1 &&
++ if (tsk->exit_signal != SIGCHLD && !task_detached(tsk) &&
+ (tsk->parent_exec_id != tsk->real_parent->self_exec_id ||
+- tsk->self_exec_id != tsk->parent_exec_id)
+- && !capable(CAP_KILL))
++ tsk->self_exec_id != tsk->parent_exec_id) &&
++ !capable(CAP_KILL))
+ tsk->exit_signal = SIGCHLD;
+
+-
+ /* If something other than our normal parent is ptracing us, then
+ * send it a SIGCHLD instead of honoring exit_signal. exit_signal
+ * only has special meaning to our real parent.
+ */
+- if (tsk->exit_signal != -1 && thread_group_empty(tsk)) {
+- int signal = tsk->parent == tsk->real_parent ? tsk->exit_signal : SIGCHLD;
++ if (!task_detached(tsk) && thread_group_empty(tsk)) {
++ int signal = ptrace_reparented(tsk) ?
++ SIGCHLD : tsk->exit_signal;
+ do_notify_parent(tsk, signal);
+ } else if (tsk->ptrace) {
+ do_notify_parent(tsk, SIGCHLD);
+ }
+
+ state = EXIT_ZOMBIE;
+- if (tsk->exit_signal == -1 && likely(!tsk->ptrace))
++ if (task_detached(tsk) && likely(!tsk->ptrace))
+ state = EXIT_DEAD;
+ tsk->exit_state = state;
+
++ /* mt-exec, de_thread() is waiting for us */
+ if (thread_group_leader(tsk) &&
+ tsk->signal->notify_count < 0 &&
+ tsk->signal->group_exit_task)
+@@ -967,8 +1037,8 @@ NORET_TYPE void do_exit(long code)
if (group_dead)
acct_process();
exit_sem(tsk);
@@ -831698,8 +1116961,65 @@
check_stack_usage();
exit_thread();
cgroup_exit(tsk, 1);
+@@ -984,7 +1054,7 @@ NORET_TYPE void do_exit(long code)
+ proc_exit_connector(tsk);
+ exit_notify(tsk, group_dead);
+ #ifdef CONFIG_NUMA
+- mpol_free(tsk->mempolicy);
++ mpol_put(tsk->mempolicy);
+ tsk->mempolicy = NULL;
+ #endif
+ #ifdef CONFIG_FUTEX
+@@ -1049,12 +1119,13 @@ asmlinkage long sys_exit(int error_code)
+ NORET_TYPE void
+ do_group_exit(int exit_code)
+ {
++ struct signal_struct *sig = current->signal;
++
+ BUG_ON(exit_code & 0x80); /* core dumps don't get here */
+
+- if (current->signal->flags & SIGNAL_GROUP_EXIT)
+- exit_code = current->signal->group_exit_code;
++ if (signal_group_exit(sig))
++ exit_code = sig->group_exit_code;
+ else if (!thread_group_empty(current)) {
+- struct signal_struct *const sig = current->signal;
+ struct sighand_struct *const sighand = current->sighand;
+ spin_lock_irq(&sighand->siglock);
+ if (signal_group_exit(sig))
+@@ -1106,7 +1177,7 @@ static int eligible_child(enum pid_type type, struct pid *pid, int options,
+ * Do not consider detached threads that are
+ * not ptraced:
+ */
+- if (p->exit_signal == -1 && !p->ptrace)
++ if (task_detached(p) && !p->ptrace)
+ return 0;
+
+ /* Wait for all children (clone and not) if __WALL is set;
+@@ -1196,8 +1267,7 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
+ return 0;
+ }
+
+- /* traced means p->ptrace, but not vice versa */
+- traced = (p->real_parent != p->parent);
++ traced = ptrace_reparented(p);
+
+ if (likely(!traced)) {
+ struct signal_struct *psig;
+@@ -1298,9 +1368,9 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
+ * If it's still not detached after that, don't release
+ * it now.
+ */
+- if (p->exit_signal != -1) {
++ if (!task_detached(p)) {
+ do_notify_parent(p, p->exit_signal);
+- if (p->exit_signal != -1) {
++ if (!task_detached(p)) {
+ p->exit_state = EXIT_ZOMBIE;
+ p = NULL;
+ }
diff --git a/kernel/fork.c b/kernel/fork.c
-index 9c042f9..cb46bef 100644
+index 9c042f9..2bb675a 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -132,6 +132,14 @@ void __put_task_struct(struct task_struct *tsk)
@@ -831775,7 +1117095,65 @@
}
#ifdef CONFIG_MMU
-@@ -782,12 +805,6 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
+@@ -256,7 +279,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
+ if (!tmp)
+ goto fail_nomem;
+ *tmp = *mpnt;
+- pol = mpol_copy(vma_policy(mpnt));
++ pol = mpol_dup(vma_policy(mpnt));
+ retval = PTR_ERR(pol);
+ if (IS_ERR(pol))
+ goto fail_nomem_policy;
+@@ -358,14 +381,13 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
+ mm->ioctx_list = NULL;
+ mm->free_area_cache = TASK_UNMAPPED_BASE;
+ mm->cached_hole_size = ~0UL;
+- mm_init_cgroup(mm, p);
++ mm_init_owner(mm, p);
+
+ if (likely(!mm_alloc_pgd(mm))) {
+ mm->def_flags = 0;
+ return mm;
+ }
+
+- mm_free_cgroup(mm);
+ free_mm(mm);
+ return NULL;
+ }
+@@ -409,13 +431,13 @@ void mmput(struct mm_struct *mm)
+ if (atomic_dec_and_test(&mm->mm_users)) {
+ exit_aio(mm);
+ exit_mmap(mm);
++ set_mm_exe_file(mm, NULL);
+ if (!list_empty(&mm->mmlist)) {
+ spin_lock(&mmlist_lock);
+ list_del(&mm->mmlist);
+ spin_unlock(&mmlist_lock);
+ }
+ put_swap_token(mm);
+- mm_free_cgroup(mm);
+ mmdrop(mm);
+ }
+ }
+@@ -498,7 +520,7 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm)
+ * Allocate a new mm structure and copy contents from the
+ * mm structure of the passed in task structure.
+ */
+-static struct mm_struct *dup_mm(struct task_struct *tsk)
++struct mm_struct *dup_mm(struct task_struct *tsk)
+ {
+ struct mm_struct *mm, *oldmm = current->mm;
+ int err;
+@@ -522,6 +544,8 @@ static struct mm_struct *dup_mm(struct task_struct *tsk)
+ if (init_new_context(tsk, mm))
+ goto fail_nocontext;
+
++ dup_mm_exe_file(oldmm, mm);
++
+ err = dup_mmap(mm, oldmm);
+ if (err)
+ goto free_pt;
+@@ -782,12 +806,6 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
goto out;
}
@@ -831788,7 +1117166,7 @@
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)
+@@ -823,34 +841,6 @@ static int copy_io(unsigned long clone_flags, struct task_struct *tsk)
return 0;
}
@@ -831823,7 +1117201,121 @@
static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
{
struct sighand_struct *sig;
-@@ -1788,3 +1777,27 @@ bad_unshare_cleanup_thread:
+@@ -902,7 +892,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
+ sig->group_exit_code = 0;
+ sig->group_exit_task = NULL;
+ sig->group_stop_count = 0;
+- sig->curr_target = NULL;
++ sig->curr_target = tsk;
+ init_sigpending(&sig->shared_pending);
+ INIT_LIST_HEAD(&sig->posix_timers);
+
+@@ -993,6 +983,13 @@ static void rt_mutex_init_task(struct task_struct *p)
+ #endif
+ }
+
++#ifdef CONFIG_MM_OWNER
++void mm_init_owner(struct mm_struct *mm, struct task_struct *p)
++{
++ mm->owner = p;
++}
++#endif /* CONFIG_MM_OWNER */
++
+ /*
+ * This creates a new process as a copy of the old one,
+ * but does not actually start it yet.
+@@ -1127,7 +1124,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+ p->audit_context = NULL;
+ cgroup_fork(p);
+ #ifdef CONFIG_NUMA
+- p->mempolicy = mpol_copy(p->mempolicy);
++ p->mempolicy = mpol_dup(p->mempolicy);
+ if (IS_ERR(p->mempolicy)) {
+ retval = PTR_ERR(p->mempolicy);
+ p->mempolicy = NULL;
+@@ -1385,7 +1382,7 @@ bad_fork_cleanup_security:
+ security_task_free(p);
+ bad_fork_cleanup_policy:
+ #ifdef CONFIG_NUMA
+- mpol_free(p->mempolicy);
++ mpol_put(p->mempolicy);
+ bad_fork_cleanup_cgroup:
+ #endif
+ cgroup_exit(p, cgroup_callbacks_done);
+@@ -1675,18 +1672,6 @@ static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp
+ }
+
+ /*
+- * Unsharing of semundo for tasks created with CLONE_SYSVSEM is not
+- * supported yet
+- */
+-static int unshare_semundo(unsigned long unshare_flags, struct sem_undo_list **new_ulistp)
+-{
+- if (unshare_flags & CLONE_SYSVSEM)
+- return -EINVAL;
+-
+- return 0;
+-}
+-
+-/*
+ * unshare allows a process to 'unshare' part of the process
+ * context which was originally shared using clone. copy_*
+ * functions used by do_fork() cannot be used here directly
+@@ -1701,8 +1686,8 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
+ struct sighand_struct *new_sigh = NULL;
+ struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL;
+ struct files_struct *fd, *new_fd = NULL;
+- struct sem_undo_list *new_ulist = NULL;
+ struct nsproxy *new_nsproxy = NULL;
++ int do_sysvsem = 0;
+
+ check_unshare_flags(&unshare_flags);
+
+@@ -1714,6 +1699,13 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
+ CLONE_NEWNET))
+ goto bad_unshare_out;
+
++ /*
++ * CLONE_NEWIPC must also detach from the undolist: after switching
++ * to a new ipc namespace, the semaphore arrays from the old
++ * namespace are unreachable.
++ */
++ if (unshare_flags & (CLONE_NEWIPC|CLONE_SYSVSEM))
++ do_sysvsem = 1;
+ if ((err = unshare_thread(unshare_flags)))
+ goto bad_unshare_out;
+ if ((err = unshare_fs(unshare_flags, &new_fs)))
+@@ -1724,13 +1716,17 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
+ goto bad_unshare_cleanup_sigh;
+ if ((err = unshare_fd(unshare_flags, &new_fd)))
+ goto bad_unshare_cleanup_vm;
+- if ((err = unshare_semundo(unshare_flags, &new_ulist)))
+- goto bad_unshare_cleanup_fd;
+ if ((err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy,
+ new_fs)))
+- goto bad_unshare_cleanup_semundo;
++ goto bad_unshare_cleanup_fd;
+
+- if (new_fs || new_mm || new_fd || new_ulist || new_nsproxy) {
++ if (new_fs || new_mm || new_fd || do_sysvsem || new_nsproxy) {
++ if (do_sysvsem) {
++ /*
++ * CLONE_SYSVSEM is equivalent to sys_exit().
++ */
++ exit_sem(current);
++ }
+
+ if (new_nsproxy) {
+ switch_task_namespaces(current, new_nsproxy);
+@@ -1766,7 +1762,6 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
+ if (new_nsproxy)
+ put_nsproxy(new_nsproxy);
+
+-bad_unshare_cleanup_semundo:
+ bad_unshare_cleanup_fd:
+ if (new_fd)
+ put_files_struct(new_fd);
+@@ -1788,3 +1783,27 @@ bad_unshare_cleanup_thread:
bad_unshare_out:
return err;
}
@@ -831851,11 +1117343,373 @@
+ task_unlock(task);
+ return 0;
+}
+diff --git a/kernel/futex.c b/kernel/futex.c
+index e43945e..98092c9 100644
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -1266,11 +1266,13 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
+ if (!abs_time)
+ schedule();
+ else {
+- hrtimer_init(&t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
++ hrtimer_init_on_stack(&t.timer, CLOCK_MONOTONIC,
++ HRTIMER_MODE_ABS);
+ hrtimer_init_sleeper(&t, current);
+ t.timer.expires = *abs_time;
+
+- hrtimer_start(&t.timer, t.timer.expires, HRTIMER_MODE_ABS);
++ hrtimer_start(&t.timer, t.timer.expires,
++ HRTIMER_MODE_ABS);
+ if (!hrtimer_active(&t.timer))
+ t.task = NULL;
+
+@@ -1286,6 +1288,8 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
+
+ /* Flag if a timeout occured */
+ rem = (t.task == NULL);
++
++ destroy_hrtimer_on_stack(&t.timer);
+ }
+ }
+ __set_current_state(TASK_RUNNING);
+@@ -1367,7 +1371,8 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
+
+ if (time) {
+ to = &timeout;
+- hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
++ hrtimer_init_on_stack(&to->timer, CLOCK_REALTIME,
++ HRTIMER_MODE_ABS);
+ hrtimer_init_sleeper(to, current);
+ to->timer.expires = *time;
+ }
+@@ -1581,6 +1586,8 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
+ unqueue_me_pi(&q);
+ futex_unlock_mm(fshared);
+
++ if (to)
++ destroy_hrtimer_on_stack(&to->timer);
+ return ret != -EINTR ? ret : -ERESTARTNOINTR;
+
+ out_unlock_release_sem:
+@@ -1588,6 +1595,8 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
+
+ out_release_sem:
+ futex_unlock_mm(fshared);
++ if (to)
++ destroy_hrtimer_on_stack(&to->timer);
+ return ret;
+
+ uaddr_faulted:
+@@ -1615,6 +1624,8 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
+ if (!ret && (uval != -EFAULT))
+ goto retry;
+
++ if (to)
++ destroy_hrtimer_on_stack(&to->timer);
+ return ret;
+ }
+
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
-index 98bee01..f78777a 100644
+index 98bee01..9af1d6a 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
-@@ -1238,51 +1238,50 @@ void hrtimer_run_pending(void)
+@@ -43,6 +43,7 @@
+ #include <linux/tick.h>
+ #include <linux/seq_file.h>
+ #include <linux/err.h>
++#include <linux/debugobjects.h>
+
+ #include <asm/uaccess.h>
+
+@@ -342,6 +343,115 @@ ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs)
+ return res;
+ }
+
++#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
++
++static struct debug_obj_descr hrtimer_debug_descr;
++
++/*
++ * fixup_init is called when:
++ * - an active object is initialized
++ */
++static int hrtimer_fixup_init(void *addr, enum debug_obj_state state)
++{
++ struct hrtimer *timer = addr;
++
++ switch (state) {
++ case ODEBUG_STATE_ACTIVE:
++ hrtimer_cancel(timer);
++ debug_object_init(timer, &hrtimer_debug_descr);
++ return 1;
++ default:
++ return 0;
++ }
++}
++
++/*
++ * fixup_activate is called when:
++ * - an active object is activated
++ * - an unknown object is activated (might be a statically initialized object)
++ */
++static int hrtimer_fixup_activate(void *addr, enum debug_obj_state state)
++{
++ switch (state) {
++
++ case ODEBUG_STATE_NOTAVAILABLE:
++ WARN_ON_ONCE(1);
++ return 0;
++
++ case ODEBUG_STATE_ACTIVE:
++ WARN_ON(1);
++
++ default:
++ return 0;
++ }
++}
++
++/*
++ * fixup_free is called when:
++ * - an active object is freed
++ */
++static int hrtimer_fixup_free(void *addr, enum debug_obj_state state)
++{
++ struct hrtimer *timer = addr;
++
++ switch (state) {
++ case ODEBUG_STATE_ACTIVE:
++ hrtimer_cancel(timer);
++ debug_object_free(timer, &hrtimer_debug_descr);
++ return 1;
++ default:
++ return 0;
++ }
++}
++
++static struct debug_obj_descr hrtimer_debug_descr = {
++ .name = "hrtimer",
++ .fixup_init = hrtimer_fixup_init,
++ .fixup_activate = hrtimer_fixup_activate,
++ .fixup_free = hrtimer_fixup_free,
++};
++
++static inline void debug_hrtimer_init(struct hrtimer *timer)
++{
++ debug_object_init(timer, &hrtimer_debug_descr);
++}
++
++static inline void debug_hrtimer_activate(struct hrtimer *timer)
++{
++ debug_object_activate(timer, &hrtimer_debug_descr);
++}
++
++static inline void debug_hrtimer_deactivate(struct hrtimer *timer)
++{
++ debug_object_deactivate(timer, &hrtimer_debug_descr);
++}
++
++static inline void debug_hrtimer_free(struct hrtimer *timer)
++{
++ debug_object_free(timer, &hrtimer_debug_descr);
++}
++
++static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
++ enum hrtimer_mode mode);
++
++void hrtimer_init_on_stack(struct hrtimer *timer, clockid_t clock_id,
++ enum hrtimer_mode mode)
++{
++ debug_object_init_on_stack(timer, &hrtimer_debug_descr);
++ __hrtimer_init(timer, clock_id, mode);
++}
++
++void destroy_hrtimer_on_stack(struct hrtimer *timer)
++{
++ debug_object_free(timer, &hrtimer_debug_descr);
++}
++
++#else
++static inline void debug_hrtimer_init(struct hrtimer *timer) { }
++static inline void debug_hrtimer_activate(struct hrtimer *timer) { }
++static inline void debug_hrtimer_deactivate(struct hrtimer *timer) { }
++#endif
++
+ /*
+ * Check, whether the timer is on the callback pending list
+ */
+@@ -567,6 +677,7 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
+ /* Timer is expired, act upon the callback mode */
+ switch(timer->cb_mode) {
+ case HRTIMER_CB_IRQSAFE_NO_RESTART:
++ debug_hrtimer_deactivate(timer);
+ /*
+ * We can call the callback from here. No restart
+ * happens, so no danger of recursion
+@@ -581,6 +692,7 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
+ * the tick timer in the softirq ! The calling site
+ * takes care of this.
+ */
++ debug_hrtimer_deactivate(timer);
+ return 1;
+ case HRTIMER_CB_IRQSAFE:
+ case HRTIMER_CB_SOFTIRQ:
+@@ -590,7 +702,6 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
+ list_add_tail(&timer->cb_entry,
+ &base->cpu_base->cb_pending);
+ timer->state = HRTIMER_STATE_PENDING;
+- raise_softirq(HRTIMER_SOFTIRQ);
+ return 1;
+ default:
+ BUG();
+@@ -633,6 +744,11 @@ static int hrtimer_switch_to_hres(void)
+ return 1;
+ }
+
++static inline void hrtimer_raise_softirq(void)
++{
++ raise_softirq(HRTIMER_SOFTIRQ);
++}
++
+ #else
+
+ static inline int hrtimer_hres_active(void) { return 0; }
+@@ -651,6 +767,7 @@ static inline int hrtimer_reprogram(struct hrtimer *timer,
+ {
+ return 0;
+ }
++static inline void hrtimer_raise_softirq(void) { }
+
+ #endif /* CONFIG_HIGH_RES_TIMERS */
+
+@@ -730,6 +847,8 @@ static void enqueue_hrtimer(struct hrtimer *timer,
+ struct hrtimer *entry;
+ int leftmost = 1;
+
++ debug_hrtimer_activate(timer);
++
+ /*
+ * Find the right place in the rbtree:
+ */
+@@ -826,6 +945,7 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base)
+ * reprogramming happens in the interrupt handler. This is a
+ * rare case and less expensive than a smp call.
+ */
++ debug_hrtimer_deactivate(timer);
+ timer_stats_hrtimer_clear_start_info(timer);
+ reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases);
+ __remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE,
+@@ -850,7 +970,7 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
+ {
+ struct hrtimer_clock_base *base, *new_base;
+ unsigned long flags;
+- int ret;
++ int ret, raise;
+
+ base = lock_hrtimer_base(timer, &flags);
+
+@@ -873,6 +993,7 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
+ tim = ktime_add_safe(tim, base->resolution);
+ #endif
+ }
++
+ timer->expires = tim;
+
+ timer_stats_hrtimer_set_start_info(timer);
+@@ -884,8 +1005,18 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
+ enqueue_hrtimer(timer, new_base,
+ new_base->cpu_base == &__get_cpu_var(hrtimer_bases));
+
++ /*
++ * The timer may be expired and moved to the cb_pending
++ * list. We can not raise the softirq with base lock held due
++ * to a possible deadlock with runqueue lock.
++ */
++ raise = timer->state == HRTIMER_STATE_PENDING;
++
+ unlock_hrtimer_base(timer, &flags);
+
++ if (raise)
++ hrtimer_raise_softirq();
++
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(hrtimer_start);
+@@ -996,14 +1127,8 @@ ktime_t hrtimer_get_next_event(void)
+ }
+ #endif
+
+-/**
+- * hrtimer_init - initialize a timer to the given clock
+- * @timer: the timer to be initialized
+- * @clock_id: the clock to be used
+- * @mode: timer mode abs/rel
+- */
+-void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
+- enum hrtimer_mode mode)
++static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
++ enum hrtimer_mode mode)
+ {
+ struct hrtimer_cpu_base *cpu_base;
+
+@@ -1024,6 +1149,19 @@ void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
+ memset(timer->start_comm, 0, TASK_COMM_LEN);
+ #endif
+ }
++
++/**
++ * hrtimer_init - initialize a timer to the given clock
++ * @timer: the timer to be initialized
++ * @clock_id: the clock to be used
++ * @mode: timer mode abs/rel
++ */
++void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
++ enum hrtimer_mode mode)
++{
++ debug_hrtimer_init(timer);
++ __hrtimer_init(timer, clock_id, mode);
++}
+ EXPORT_SYMBOL_GPL(hrtimer_init);
+
+ /**
+@@ -1057,6 +1195,7 @@ static void run_hrtimer_pending(struct hrtimer_cpu_base *cpu_base)
+ timer = list_entry(cpu_base->cb_pending.next,
+ struct hrtimer, cb_entry);
+
++ debug_hrtimer_deactivate(timer);
+ timer_stats_account_hrtimer(timer);
+
+ fn = timer->function;
+@@ -1080,8 +1219,19 @@ static void run_hrtimer_pending(struct hrtimer_cpu_base *cpu_base)
+ * If the timer was rearmed on another CPU, reprogram
+ * the event device.
+ */
+- if (timer->base->first == &timer->node)
+- hrtimer_reprogram(timer, timer->base);
++ struct hrtimer_clock_base *base = timer->base;
++
++ if (base->first == &timer->node &&
++ hrtimer_reprogram(timer, base)) {
++ /*
++ * Timer is expired. Thus move it from tree to
++ * pending list again.
++ */
++ __remove_hrtimer(timer, base,
++ HRTIMER_STATE_PENDING, 0);
++ list_add_tail(&timer->cb_entry,
++ &base->cpu_base->cb_pending);
++ }
+ }
+ }
+ spin_unlock_irq(&cpu_base->lock);
+@@ -1094,6 +1244,7 @@ static void __run_hrtimer(struct hrtimer *timer)
+ enum hrtimer_restart (*fn)(struct hrtimer *);
+ int restart;
+
++ debug_hrtimer_deactivate(timer);
+ __remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0);
+ timer_stats_account_hrtimer(timer);
+
+@@ -1238,51 +1389,50 @@ void hrtimer_run_pending(void)
/*
* Called from hardirq context every jiffy
*/
@@ -831877,16 +1117731,16 @@
- 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;
--
++ for (index = 0; index < HRTIMER_MAX_CLOCK_BASES; index++) {
++ base = &cpu_base->clock_base[index];
+
- if (timer->cb_mode == HRTIMER_CB_SOFTIRQ) {
- __remove_hrtimer(timer, base, HRTIMER_STATE_PENDING, 0);
- list_add_tail(&timer->cb_entry,
@@ -831937,25 +1117791,70 @@
+ }
}
- /*
-@@ -1354,13 +1353,13 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
+ /*
+@@ -1353,22 +1503,27 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
+ {
+ struct hrtimer_sleeper t;
+ struct timespec __user *rmtp;
++ int ret = 0;
+
+- hrtimer_init(&t.timer, restart->arg0, HRTIMER_MODE_ABS);
+- t.timer.expires.tv64 = ((u64)restart->arg3 << 32) | (u64) restart->arg2;
++ hrtimer_init_on_stack(&t.timer, restart->nanosleep.index,
++ HRTIMER_MODE_ABS);
++ t.timer.expires.tv64 = restart->nanosleep.expires;
+
+ if (do_nanosleep(&t, HRTIMER_MODE_ABS))
+- return 0;
++ goto out;
+
+- rmtp = (struct timespec __user *)restart->arg1;
++ rmtp = restart->nanosleep.rmtp;
+ if (rmtp) {
+- int ret = update_rmtp(&t.timer, rmtp);
++ ret = update_rmtp(&t.timer, rmtp);
+ if (ret <= 0)
+- return ret;
++ goto out;
+ }
+
+ /* The other values in restart are already filled in */
+- return -ERESTART_RESTARTBLOCK;
++ ret = -ERESTART_RESTARTBLOCK;
++out:
++ destroy_hrtimer_on_stack(&t.timer);
++ return ret;
+ }
+
+ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
+@@ -1376,30 +1531,35 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
+ {
+ struct restart_block *restart;
struct hrtimer_sleeper t;
- struct timespec __user *rmtp;
++ int ret = 0;
-- 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;
+- hrtimer_init(&t.timer, clockid, mode);
++ hrtimer_init_on_stack(&t.timer, clockid, mode);
+ t.timer.expires = timespec_to_ktime(*rqtp);
+ if (do_nanosleep(&t, mode))
+- return 0;
++ goto out;
- if (do_nanosleep(&t, HRTIMER_MODE_ABS))
- return 0;
+ /* Absolute timers do not update the rmtp value and restart: */
+- if (mode == HRTIMER_MODE_ABS)
+- return -ERESTARTNOHAND;
++ if (mode == HRTIMER_MODE_ABS) {
++ ret = -ERESTARTNOHAND;
++ goto out;
++ }
-- rmtp = (struct timespec __user *)restart->arg1;
-+ rmtp = restart->nanosleep.rmtp;
if (rmtp) {
- int ret = update_rmtp(&t.timer, rmtp);
+- int ret = update_rmtp(&t.timer, rmtp);
++ ret = update_rmtp(&t.timer, rmtp);
if (ret <= 0)
-@@ -1394,10 +1393,9 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
+- return ret;
++ goto out;
+ }
restart = ¤t_thread_info()->restart_block;
restart->fn = hrtimer_nanosleep_restart;
@@ -831967,9 +1117866,15 @@
+ restart->nanosleep.rmtp = rmtp;
+ restart->nanosleep.expires = t.timer.expires.tv64;
- return -ERESTART_RESTARTBLOCK;
+- return -ERESTART_RESTARTBLOCK;
++ ret = -ERESTART_RESTARTBLOCK;
++out:
++ destroy_hrtimer_on_stack(&t.timer);
++ return ret;
}
-@@ -1425,7 +1423,6 @@ static void __cpuinit init_hrtimers_cpu(int cpu)
+
+ asmlinkage long
+@@ -1425,7 +1585,6 @@ static void __cpuinit init_hrtimers_cpu(int cpu)
int i;
spin_lock_init(&cpu_base->lock);
@@ -831977,7 +1117882,15 @@
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)
+@@ -1445,6 +1604,7 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
+ while ((node = rb_first(&old_base->active))) {
+ timer = rb_entry(node, struct hrtimer, node);
+ BUG_ON(hrtimer_callback_running(timer));
++ debug_hrtimer_deactivate(timer);
+ __remove_hrtimer(timer, old_base, HRTIMER_STATE_INACTIVE, 0);
+ timer->base = new_base;
+ /*
+@@ -1466,16 +1626,16 @@ static void migrate_hrtimers(int cpu)
tick_cancel_sched_timer(cpu);
local_irq_disable();
@@ -832011,8 +1117924,49 @@
#endif
spin_unlock_irqrestore(&desc->lock, flags);
}
+diff --git a/kernel/irq/devres.c b/kernel/irq/devres.c
+index 6d9204f..38a25b8 100644
+--- a/kernel/irq/devres.c
++++ b/kernel/irq/devres.c
+@@ -1,6 +1,7 @@
+ #include <linux/module.h>
+ #include <linux/interrupt.h>
+ #include <linux/device.h>
++#include <linux/gfp.h>
+
+ /*
+ * Device resource management aware IRQ request/free implementation.
+diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
+index 438a014..46e4ad1 100644
+--- a/kernel/irq/manage.c
++++ b/kernel/irq/manage.c
+@@ -11,6 +11,7 @@
+ #include <linux/module.h>
+ #include <linux/random.h>
+ #include <linux/interrupt.h>
++#include <linux/slab.h>
+
+ #include "internals.h"
+
+diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
+index f091d13..6fc0040 100644
+--- a/kernel/kallsyms.c
++++ b/kernel/kallsyms.c
+@@ -472,11 +472,7 @@ static const struct file_operations kallsyms_operations = {
+
+ static int __init kallsyms_init(void)
+ {
+- struct proc_dir_entry *entry;
+-
+- entry = create_proc_entry("kallsyms", 0444, NULL);
+- if (entry)
+- entry->proc_fops = &kallsyms_operations;
++ proc_create("kallsyms", 0444, NULL, &kallsyms_operations);
+ return 0;
+ }
+ __initcall(kallsyms_init);
diff --git a/kernel/kexec.c b/kernel/kexec.c
-index 06a0e27..6782dce 100644
+index 06a0e27..cb85c79 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -29,7 +29,6 @@
@@ -832023,6 +1117977,16 @@
#include <asm/sections.h>
/* Per cpu memory for storing cpu states in case of system crash. */
+@@ -1406,6 +1405,9 @@ static int __init crash_save_vmcoreinfo_init(void)
+ VMCOREINFO_LENGTH(zone.free_area, MAX_ORDER);
+ VMCOREINFO_LENGTH(free_area.free_list, MIGRATE_TYPES);
+ VMCOREINFO_NUMBER(NR_FREE_PAGES);
++ VMCOREINFO_NUMBER(PG_lru);
++ VMCOREINFO_NUMBER(PG_private);
++ VMCOREINFO_NUMBER(PG_swapcache);
+
+ arch_crash_save_vmcoreinfo();
+
diff --git a/kernel/kgdb.c b/kernel/kgdb.c
new file mode 100644
index 0000000..1bd0ec1
@@ -833742,8 +1119706,507 @@
/*
* Our parent is keventd, which runs with elevated scheduling priority.
+diff --git a/kernel/kprobes.c b/kernel/kprobes.c
+index fcfb580..1e0250c 100644
+--- a/kernel/kprobes.c
++++ b/kernel/kprobes.c
+@@ -72,6 +72,18 @@ DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */
+ DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */
+ static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
+
++/*
++ * Normally, functions that we'd want to prohibit kprobes in, are marked
++ * __kprobes. But, there are cases where such functions already belong to
++ * a different section (__sched for preempt_schedule)
++ *
++ * For such cases, we now have a blacklist
++ */
++struct kprobe_blackpoint kprobe_blacklist[] = {
++ {"preempt_schedule",},
++ {NULL} /* Terminator */
++};
++
+ #ifdef __ARCH_WANT_KPROBES_INSN_SLOT
+ /*
+ * kprobe->ainsn.insn points to the copy of the instruction to be
+@@ -417,6 +429,21 @@ static inline void free_rp_inst(struct kretprobe *rp)
+ }
+ }
+
++static void __kprobes cleanup_rp_inst(struct kretprobe *rp)
++{
++ unsigned long flags;
++ struct kretprobe_instance *ri;
++ struct hlist_node *pos, *next;
++ /* No race here */
++ spin_lock_irqsave(&kretprobe_lock, flags);
++ hlist_for_each_entry_safe(ri, pos, next, &rp->used_instances, uflist) {
++ ri->rp = NULL;
++ hlist_del(&ri->uflist);
++ }
++ spin_unlock_irqrestore(&kretprobe_lock, flags);
++ free_rp_inst(rp);
++}
++
+ /*
+ * Keep all fields in the kprobe consistent
+ */
+@@ -492,9 +519,22 @@ static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
+
+ static int __kprobes in_kprobes_functions(unsigned long addr)
+ {
++ struct kprobe_blackpoint *kb;
++
+ if (addr >= (unsigned long)__kprobes_text_start &&
+ addr < (unsigned long)__kprobes_text_end)
+ return -EINVAL;
++ /*
++ * If there exists a kprobe_blacklist, verify and
++ * fail any probe registration in the prohibited area
++ */
++ for (kb = kprobe_blacklist; kb->name != NULL; kb++) {
++ if (kb->start_addr) {
++ if (addr >= kb->start_addr &&
++ addr < (kb->start_addr + kb->range))
++ return -EINVAL;
++ }
++ }
+ return 0;
+ }
+
+@@ -555,6 +595,7 @@ static int __kprobes __register_kprobe(struct kprobe *p,
+ }
+
+ p->nmissed = 0;
++ INIT_LIST_HEAD(&p->list);
+ mutex_lock(&kprobe_mutex);
+ old_p = get_kprobe(p->addr);
+ if (old_p) {
+@@ -581,35 +622,28 @@ out:
+ return ret;
+ }
+
+-int __kprobes register_kprobe(struct kprobe *p)
+-{
+- return __register_kprobe(p, (unsigned long)__builtin_return_address(0));
+-}
+-
+-void __kprobes unregister_kprobe(struct kprobe *p)
++/*
++ * Unregister a kprobe without a scheduler synchronization.
++ */
++static int __kprobes __unregister_kprobe_top(struct kprobe *p)
+ {
+- struct module *mod;
+ struct kprobe *old_p, *list_p;
+- int cleanup_p;
+
+- mutex_lock(&kprobe_mutex);
+ old_p = get_kprobe(p->addr);
+- if (unlikely(!old_p)) {
+- mutex_unlock(&kprobe_mutex);
+- return;
+- }
++ if (unlikely(!old_p))
++ return -EINVAL;
++
+ if (p != old_p) {
+ list_for_each_entry_rcu(list_p, &old_p->list, list)
+ if (list_p == p)
+ /* kprobe p is a valid probe */
+ goto valid_p;
+- mutex_unlock(&kprobe_mutex);
+- return;
++ return -EINVAL;
+ }
+ valid_p:
+ if (old_p == p ||
+ (old_p->pre_handler == aggr_pre_handler &&
+- p->list.next == &old_p->list && p->list.prev == &old_p->list)) {
++ list_is_singular(&old_p->list))) {
+ /*
+ * Only probe on the hash list. Disarm only if kprobes are
+ * enabled - otherwise, the breakpoint would already have
+@@ -618,43 +652,97 @@ valid_p:
+ if (kprobe_enabled)
+ arch_disarm_kprobe(p);
+ hlist_del_rcu(&old_p->hlist);
+- cleanup_p = 1;
+ } else {
++ if (p->break_handler)
++ old_p->break_handler = NULL;
++ if (p->post_handler) {
++ list_for_each_entry_rcu(list_p, &old_p->list, list) {
++ if ((list_p != p) && (list_p->post_handler))
++ goto noclean;
++ }
++ old_p->post_handler = NULL;
++ }
++noclean:
+ list_del_rcu(&p->list);
+- cleanup_p = 0;
+ }
++ return 0;
++}
+
+- mutex_unlock(&kprobe_mutex);
++static void __kprobes __unregister_kprobe_bottom(struct kprobe *p)
++{
++ struct module *mod;
++ struct kprobe *old_p;
+
+- synchronize_sched();
+ if (p->mod_refcounted) {
+ mod = module_text_address((unsigned long)p->addr);
+ if (mod)
+ module_put(mod);
+ }
+
+- if (cleanup_p) {
+- if (p != old_p) {
+- list_del_rcu(&p->list);
++ if (list_empty(&p->list) || list_is_singular(&p->list)) {
++ if (!list_empty(&p->list)) {
++ /* "p" is the last child of an aggr_kprobe */
++ old_p = list_entry(p->list.next, struct kprobe, list);
++ list_del(&p->list);
+ kfree(old_p);
+ }
+ arch_remove_kprobe(p);
+- } else {
+- mutex_lock(&kprobe_mutex);
+- if (p->break_handler)
+- old_p->break_handler = NULL;
+- if (p->post_handler){
+- list_for_each_entry_rcu(list_p, &old_p->list, list){
+- if (list_p->post_handler){
+- cleanup_p = 2;
+- break;
+- }
+- }
+- if (cleanup_p == 0)
+- old_p->post_handler = NULL;
++ }
++}
++
++static int __register_kprobes(struct kprobe **kps, int num,
++ unsigned long called_from)
++{
++ int i, ret = 0;
++
++ if (num <= 0)
++ return -EINVAL;
++ for (i = 0; i < num; i++) {
++ ret = __register_kprobe(kps[i], called_from);
++ if (ret < 0 && i > 0) {
++ unregister_kprobes(kps, i);
++ break;
+ }
+- mutex_unlock(&kprobe_mutex);
+ }
++ return ret;
++}
++
++/*
++ * Registration and unregistration functions for kprobe.
++ */
++int __kprobes register_kprobe(struct kprobe *p)
++{
++ return __register_kprobes(&p, 1,
++ (unsigned long)__builtin_return_address(0));
++}
++
++void __kprobes unregister_kprobe(struct kprobe *p)
++{
++ unregister_kprobes(&p, 1);
++}
++
++int __kprobes register_kprobes(struct kprobe **kps, int num)
++{
++ return __register_kprobes(kps, num,
++ (unsigned long)__builtin_return_address(0));
++}
++
++void __kprobes unregister_kprobes(struct kprobe **kps, int num)
++{
++ int i;
++
++ if (num <= 0)
++ return;
++ mutex_lock(&kprobe_mutex);
++ for (i = 0; i < num; i++)
++ if (__unregister_kprobe_top(kps[i]) < 0)
++ kps[i]->addr = NULL;
++ mutex_unlock(&kprobe_mutex);
++
++ synchronize_sched();
++ for (i = 0; i < num; i++)
++ if (kps[i]->addr)
++ __unregister_kprobe_bottom(kps[i]);
+ }
+
+ static struct notifier_block kprobe_exceptions_nb = {
+@@ -667,24 +755,69 @@ unsigned long __weak arch_deref_entry_point(void *entry)
+ return (unsigned long)entry;
+ }
+
+-int __kprobes register_jprobe(struct jprobe *jp)
++static int __register_jprobes(struct jprobe **jps, int num,
++ unsigned long called_from)
+ {
+- unsigned long addr = arch_deref_entry_point(jp->entry);
++ struct jprobe *jp;
++ int ret = 0, i;
+
+- if (!kernel_text_address(addr))
++ if (num <= 0)
+ return -EINVAL;
++ for (i = 0; i < num; i++) {
++ unsigned long addr;
++ jp = jps[i];
++ addr = arch_deref_entry_point(jp->entry);
++
++ if (!kernel_text_address(addr))
++ ret = -EINVAL;
++ else {
++ /* Todo: Verify probepoint is a function entry point */
++ jp->kp.pre_handler = setjmp_pre_handler;
++ jp->kp.break_handler = longjmp_break_handler;
++ ret = __register_kprobe(&jp->kp, called_from);
++ }
++ if (ret < 0 && i > 0) {
++ unregister_jprobes(jps, i);
++ break;
++ }
++ }
++ return ret;
++}
+
+- /* Todo: Verify probepoint is a function entry point */
+- jp->kp.pre_handler = setjmp_pre_handler;
+- jp->kp.break_handler = longjmp_break_handler;
+-
+- return __register_kprobe(&jp->kp,
++int __kprobes register_jprobe(struct jprobe *jp)
++{
++ return __register_jprobes(&jp, 1,
+ (unsigned long)__builtin_return_address(0));
+ }
+
+ void __kprobes unregister_jprobe(struct jprobe *jp)
+ {
+- unregister_kprobe(&jp->kp);
++ unregister_jprobes(&jp, 1);
++}
++
++int __kprobes register_jprobes(struct jprobe **jps, int num)
++{
++ return __register_jprobes(jps, num,
++ (unsigned long)__builtin_return_address(0));
++}
++
++void __kprobes unregister_jprobes(struct jprobe **jps, int num)
++{
++ int i;
++
++ if (num <= 0)
++ return;
++ mutex_lock(&kprobe_mutex);
++ for (i = 0; i < num; i++)
++ if (__unregister_kprobe_top(&jps[i]->kp) < 0)
++ jps[i]->kp.addr = NULL;
++ mutex_unlock(&kprobe_mutex);
++
++ synchronize_sched();
++ for (i = 0; i < num; i++) {
++ if (jps[i]->kp.addr)
++ __unregister_kprobe_bottom(&jps[i]->kp);
++ }
+ }
+
+ #ifdef CONFIG_KRETPROBES
+@@ -725,7 +858,8 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p,
+ return 0;
+ }
+
+-int __kprobes register_kretprobe(struct kretprobe *rp)
++static int __kprobes __register_kretprobe(struct kretprobe *rp,
++ unsigned long called_from)
+ {
+ int ret = 0;
+ struct kretprobe_instance *inst;
+@@ -771,46 +905,101 @@ int __kprobes register_kretprobe(struct kretprobe *rp)
+
+ rp->nmissed = 0;
+ /* Establish function entry probe point */
+- if ((ret = __register_kprobe(&rp->kp,
+- (unsigned long)__builtin_return_address(0))) != 0)
++ ret = __register_kprobe(&rp->kp, called_from);
++ if (ret != 0)
+ free_rp_inst(rp);
+ return ret;
+ }
+
++static int __register_kretprobes(struct kretprobe **rps, int num,
++ unsigned long called_from)
++{
++ int ret = 0, i;
++
++ if (num <= 0)
++ return -EINVAL;
++ for (i = 0; i < num; i++) {
++ ret = __register_kretprobe(rps[i], called_from);
++ if (ret < 0 && i > 0) {
++ unregister_kretprobes(rps, i);
++ break;
++ }
++ }
++ return ret;
++}
++
++int __kprobes register_kretprobe(struct kretprobe *rp)
++{
++ return __register_kretprobes(&rp, 1,
++ (unsigned long)__builtin_return_address(0));
++}
++
++void __kprobes unregister_kretprobe(struct kretprobe *rp)
++{
++ unregister_kretprobes(&rp, 1);
++}
++
++int __kprobes register_kretprobes(struct kretprobe **rps, int num)
++{
++ return __register_kretprobes(rps, num,
++ (unsigned long)__builtin_return_address(0));
++}
++
++void __kprobes unregister_kretprobes(struct kretprobe **rps, int num)
++{
++ int i;
++
++ if (num <= 0)
++ return;
++ mutex_lock(&kprobe_mutex);
++ for (i = 0; i < num; i++)
++ if (__unregister_kprobe_top(&rps[i]->kp) < 0)
++ rps[i]->kp.addr = NULL;
++ mutex_unlock(&kprobe_mutex);
++
++ synchronize_sched();
++ for (i = 0; i < num; i++) {
++ if (rps[i]->kp.addr) {
++ __unregister_kprobe_bottom(&rps[i]->kp);
++ cleanup_rp_inst(rps[i]);
++ }
++ }
++}
++
+ #else /* CONFIG_KRETPROBES */
+ int __kprobes register_kretprobe(struct kretprobe *rp)
+ {
+ return -ENOSYS;
+ }
+
+-static int __kprobes pre_handler_kretprobe(struct kprobe *p,
+- struct pt_regs *regs)
++int __kprobes register_kretprobes(struct kretprobe **rps, int num)
+ {
+- return 0;
++ return -ENOSYS;
+ }
+-#endif /* CONFIG_KRETPROBES */
+-
+ void __kprobes unregister_kretprobe(struct kretprobe *rp)
+ {
+- unsigned long flags;
+- struct kretprobe_instance *ri;
+- struct hlist_node *pos, *next;
++}
+
+- unregister_kprobe(&rp->kp);
++void __kprobes unregister_kretprobes(struct kretprobe **rps, int num)
++{
++}
+
+- /* No race here */
+- spin_lock_irqsave(&kretprobe_lock, flags);
+- hlist_for_each_entry_safe(ri, pos, next, &rp->used_instances, uflist) {
+- ri->rp = NULL;
+- hlist_del(&ri->uflist);
+- }
+- spin_unlock_irqrestore(&kretprobe_lock, flags);
+- free_rp_inst(rp);
++static int __kprobes pre_handler_kretprobe(struct kprobe *p,
++ struct pt_regs *regs)
++{
++ return 0;
+ }
+
++#endif /* CONFIG_KRETPROBES */
++
+ static int __init init_kprobes(void)
+ {
+ int i, err = 0;
++ unsigned long offset = 0, size = 0;
++ char *modname, namebuf[128];
++ const char *symbol_name;
++ void *addr;
++ struct kprobe_blackpoint *kb;
+
+ /* FIXME allocate the probe table, currently defined statically */
+ /* initialize all list heads */
+@@ -819,6 +1008,28 @@ static int __init init_kprobes(void)
+ INIT_HLIST_HEAD(&kretprobe_inst_table[i]);
+ }
+
++ /*
++ * Lookup and populate the kprobe_blacklist.
++ *
++ * Unlike the kretprobe blacklist, we'll need to determine
++ * the range of addresses that belong to the said functions,
++ * since a kprobe need not necessarily be at the beginning
++ * of a function.
++ */
++ for (kb = kprobe_blacklist; kb->name != NULL; kb++) {
++ kprobe_lookup_name(kb->name, addr);
++ if (!addr)
++ continue;
++
++ kb->start_addr = (unsigned long)addr;
++ symbol_name = kallsyms_lookup(kb->start_addr,
++ &size, &offset, &modname, namebuf);
++ if (!symbol_name)
++ kb->range = 0;
++ else
++ kb->range = size;
++ }
++
+ if (kretprobe_blacklist_size) {
+ /* lookup the function address from its name */
+ for (i = 0; kretprobe_blacklist[i].name != NULL; i++) {
+@@ -1066,8 +1277,12 @@ module_init(init_kprobes);
+
+ EXPORT_SYMBOL_GPL(register_kprobe);
+ EXPORT_SYMBOL_GPL(unregister_kprobe);
++EXPORT_SYMBOL_GPL(register_kprobes);
++EXPORT_SYMBOL_GPL(unregister_kprobes);
+ EXPORT_SYMBOL_GPL(register_jprobe);
+ EXPORT_SYMBOL_GPL(unregister_jprobe);
++EXPORT_SYMBOL_GPL(register_jprobes);
++EXPORT_SYMBOL_GPL(unregister_jprobes);
+ #ifdef CONFIG_KPROBES
+ EXPORT_SYMBOL_GPL(jprobe_return);
+ #endif
+@@ -1075,4 +1290,6 @@ EXPORT_SYMBOL_GPL(jprobe_return);
+ #ifdef CONFIG_KPROBES
+ EXPORT_SYMBOL_GPL(register_kretprobe);
+ EXPORT_SYMBOL_GPL(unregister_kretprobe);
++EXPORT_SYMBOL_GPL(register_kretprobes);
++EXPORT_SYMBOL_GPL(unregister_kretprobes);
+ #endif
diff --git a/kernel/kthread.c b/kernel/kthread.c
-index 0ac8878..92cf693 100644
+index 0ac8878..bd1b9ea 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -13,7 +13,6 @@
@@ -833754,6 +1120217,26 @@
#define KTHREAD_NICE_LEVEL (-5)
+@@ -99,7 +98,7 @@ static void create_kthread(struct kthread_create_info *create)
+ struct sched_param param = { .sched_priority = 0 };
+ wait_for_completion(&create->started);
+ read_lock(&tasklist_lock);
+- create->result = find_task_by_pid(pid);
++ create->result = find_task_by_pid_ns(pid, &init_pid_ns);
+ read_unlock(&tasklist_lock);
+ /*
+ * root may have changed our (kthreadd's) priority or CPU mask.
+@@ -145,9 +144,9 @@ struct task_struct *kthread_create(int (*threadfn)(void *data),
+
+ spin_lock(&kthread_create_lock);
+ list_add_tail(&create.list, &kthread_create_list);
+- wake_up_process(kthreadd_task);
+ spin_unlock(&kthread_create_lock);
+
++ wake_up_process(kthreadd_task);
+ wait_for_completion(&create.done);
+
+ if (!IS_ERR(create.result)) {
@@ -180,6 +179,7 @@ void kthread_bind(struct task_struct *k, unsigned int cpu)
wait_task_inactive(k);
set_task_cpu(k, cpu);
@@ -833763,7 +1120246,7 @@
EXPORT_SYMBOL(kthread_bind);
diff --git a/kernel/latencytop.c b/kernel/latencytop.c
-index b4e3c85..7c74dab 100644
+index b4e3c85..5e7b45c 100644
--- a/kernel/latencytop.c
+++ b/kernel/latencytop.c
@@ -64,8 +64,8 @@ account_global_scheduler_latency(struct task_struct *tsk, struct latency_record
@@ -833820,6 +1120303,70 @@
break;
}
if (same) {
+@@ -226,14 +233,7 @@ static struct file_operations lstats_fops = {
+
+ static int __init init_lstats_procfs(void)
+ {
+- struct proc_dir_entry *pe;
+-
+- pe = create_proc_entry("latency_stats", 0644, NULL);
+- if (!pe)
+- return -ENOMEM;
+-
+- pe->proc_fops = &lstats_fops;
+-
++ proc_create("latency_stats", 0644, NULL, &lstats_fops);
+ return 0;
+ }
+ __initcall(init_lstats_procfs);
+diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c
+index 8a135bd..dc5d296 100644
+--- a/kernel/lockdep_proc.c
++++ b/kernel/lockdep_proc.c
+@@ -660,20 +660,12 @@ static const struct file_operations proc_lock_stat_operations = {
+
+ static int __init lockdep_proc_init(void)
+ {
+- struct proc_dir_entry *entry;
+-
+- entry = create_proc_entry("lockdep", S_IRUSR, NULL);
+- if (entry)
+- entry->proc_fops = &proc_lockdep_operations;
+-
+- entry = create_proc_entry("lockdep_stats", S_IRUSR, NULL);
+- if (entry)
+- entry->proc_fops = &proc_lockdep_stats_operations;
++ proc_create("lockdep", S_IRUSR, NULL, &proc_lockdep_operations);
++ proc_create("lockdep_stats", S_IRUSR, NULL,
++ &proc_lockdep_stats_operations);
+
+ #ifdef CONFIG_LOCK_STAT
+- entry = create_proc_entry("lock_stat", S_IRUSR, NULL);
+- if (entry)
+- entry->proc_fops = &proc_lock_stat_operations;
++ proc_create("lock_stat", S_IRUSR, NULL, &proc_lock_stat_operations);
+ #endif
+
+ return 0;
+diff --git a/kernel/marker.c b/kernel/marker.c
+index 005b959..b5a9fe1 100644
+--- a/kernel/marker.c
++++ b/kernel/marker.c
+@@ -23,12 +23,13 @@
+ #include <linux/rcupdate.h>
+ #include <linux/marker.h>
+ #include <linux/err.h>
++#include <linux/slab.h>
+
+ extern struct marker __start___markers[];
+ extern struct marker __stop___markers[];
+
+ /* Set to 1 to enable marker debug output */
+-const int marker_debug;
++static const int marker_debug;
+
+ /*
+ * markers_mutex nests inside module_mutex. Markers mutex protects the builtin
diff --git a/kernel/module.c b/kernel/module.c
index 5d437bf..8d6cccc 100644
--- a/kernel/module.c
@@ -833841,6 +1120388,270 @@
mutex_unlock(&module_mutex);
for (;;) {
DEBUGP("Looking at refcount...\n");
+diff --git a/kernel/notifier.c b/kernel/notifier.c
+index 643360d..823be11 100644
+--- a/kernel/notifier.c
++++ b/kernel/notifier.c
+@@ -31,6 +31,21 @@ static int notifier_chain_register(struct notifier_block **nl,
+ return 0;
+ }
+
++static int notifier_chain_cond_register(struct notifier_block **nl,
++ struct notifier_block *n)
++{
++ while ((*nl) != NULL) {
++ if ((*nl) == n)
++ return 0;
++ if (n->priority > (*nl)->priority)
++ break;
++ nl = &((*nl)->next);
++ }
++ n->next = *nl;
++ rcu_assign_pointer(*nl, n);
++ return 0;
++}
++
+ static int notifier_chain_unregister(struct notifier_block **nl,
+ struct notifier_block *n)
+ {
+@@ -205,6 +220,29 @@ int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
+ EXPORT_SYMBOL_GPL(blocking_notifier_chain_register);
+
+ /**
++ * blocking_notifier_chain_cond_register - Cond add notifier to a blocking notifier chain
++ * @nh: Pointer to head of the blocking notifier chain
++ * @n: New entry in notifier chain
++ *
++ * Adds a notifier to a blocking notifier chain, only if not already
++ * present in the chain.
++ * Must be called in process context.
++ *
++ * Currently always returns zero.
++ */
++int blocking_notifier_chain_cond_register(struct blocking_notifier_head *nh,
++ struct notifier_block *n)
++{
++ int ret;
++
++ down_write(&nh->rwsem);
++ ret = notifier_chain_cond_register(&nh->head, n);
++ up_write(&nh->rwsem);
++ return ret;
++}
++EXPORT_SYMBOL_GPL(blocking_notifier_chain_cond_register);
++
++/**
+ * blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain
+ * @nh: Pointer to head of the blocking notifier chain
+ * @n: Entry to remove from notifier chain
+diff --git a/kernel/ns_cgroup.c b/kernel/ns_cgroup.c
+index aead4d6..48d7ed6 100644
+--- a/kernel/ns_cgroup.c
++++ b/kernel/ns_cgroup.c
+@@ -7,6 +7,8 @@
+ #include <linux/module.h>
+ #include <linux/cgroup.h>
+ #include <linux/fs.h>
++#include <linux/slab.h>
++#include <linux/nsproxy.h>
+
+ struct ns_cgroup {
+ struct cgroup_subsys_state css;
+diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
+index f5d332c..adc7851 100644
+--- a/kernel/nsproxy.c
++++ b/kernel/nsproxy.c
+@@ -139,6 +139,18 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
+ goto out;
+ }
+
++ /*
++ * CLONE_NEWIPC must detach from the undolist: after switching
++ * to a new ipc namespace, the semaphore arrays from the old
++ * namespace are unreachable. In clone parlance, CLONE_SYSVSEM
++ * means share undolist with parent, so we must forbid using
++ * it along with CLONE_NEWIPC.
++ */
++ if ((flags & CLONE_NEWIPC) && (flags & CLONE_SYSVSEM)) {
++ err = -EINVAL;
++ goto out;
++ }
++
+ new_ns = create_new_namespaces(flags, tsk, tsk->fs);
+ if (IS_ERR(new_ns)) {
+ err = PTR_ERR(new_ns);
+diff --git a/kernel/panic.c b/kernel/panic.c
+index 24af9f8..425567f 100644
+--- a/kernel/panic.c
++++ b/kernel/panic.c
+@@ -153,6 +153,8 @@ EXPORT_SYMBOL(panic);
+ * 'M' - System experienced a machine check exception.
+ * 'B' - System has hit bad_page.
+ * 'U' - Userspace-defined naughtiness.
++ * 'A' - ACPI table overridden.
++ * 'W' - Taint on warning.
+ *
+ * The string is overwritten by the next call to print_taint().
+ */
+@@ -161,7 +163,7 @@ const char *print_tainted(void)
+ {
+ static char buf[20];
+ if (tainted) {
+- snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c%c%c",
++ snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c%c%c%c",
+ tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G',
+ tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
+ tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
+@@ -170,7 +172,8 @@ const char *print_tainted(void)
+ tainted & TAINT_BAD_PAGE ? 'B' : ' ',
+ tainted & TAINT_USER ? 'U' : ' ',
+ tainted & TAINT_DIE ? 'D' : ' ',
+- tainted & TAINT_OVERRIDDEN_ACPI_TABLE ? 'A' : ' ');
++ tainted & TAINT_OVERRIDDEN_ACPI_TABLE ? 'A' : ' ',
++ tainted & TAINT_WARN ? 'W' : ' ');
+ }
+ else
+ snprintf(buf, sizeof(buf), "Not tainted");
+@@ -312,6 +315,7 @@ void warn_on_slowpath(const char *file, int line)
+ print_modules();
+ dump_stack();
+ print_oops_end_marker();
++ add_taint(TAINT_WARN);
+ }
+ EXPORT_SYMBOL(warn_on_slowpath);
+ #endif
+diff --git a/kernel/pid.c b/kernel/pid.c
+index 4776915..20d59fa 100644
+--- a/kernel/pid.c
++++ b/kernel/pid.c
+@@ -111,10 +111,11 @@ EXPORT_SYMBOL(is_container_init);
+
+ static __cacheline_aligned_in_smp DEFINE_SPINLOCK(pidmap_lock);
+
+-static void free_pidmap(struct pid_namespace *pid_ns, int pid)
++static void free_pidmap(struct upid *upid)
+ {
+- struct pidmap *map = pid_ns->pidmap + pid / BITS_PER_PAGE;
+- int offset = pid & BITS_PER_PAGE_MASK;
++ int nr = upid->nr;
++ struct pidmap *map = upid->ns->pidmap + nr / BITS_PER_PAGE;
++ int offset = nr & BITS_PER_PAGE_MASK;
+
+ clear_bit(offset, map->page);
+ atomic_inc(&map->nr_free);
+@@ -232,7 +233,7 @@ void free_pid(struct pid *pid)
+ spin_unlock_irqrestore(&pidmap_lock, flags);
+
+ for (i = 0; i <= pid->level; i++)
+- free_pidmap(pid->numbers[i].ns, pid->numbers[i].nr);
++ free_pidmap(pid->numbers + i);
+
+ call_rcu(&pid->rcu, delayed_put_pid);
+ }
+@@ -278,8 +279,8 @@ out:
+ return pid;
+
+ out_free:
+- for (i++; i <= ns->level; i++)
+- free_pidmap(pid->numbers[i].ns, pid->numbers[i].nr);
++ while (++i <= ns->level)
++ free_pidmap(pid->numbers + i);
+
+ kmem_cache_free(ns->pid_cachep, pid);
+ pid = NULL;
+@@ -316,7 +317,7 @@ EXPORT_SYMBOL_GPL(find_pid);
+ /*
+ * attach_pid() must be called with the tasklist_lock write-held.
+ */
+-int attach_pid(struct task_struct *task, enum pid_type type,
++void attach_pid(struct task_struct *task, enum pid_type type,
+ struct pid *pid)
+ {
+ struct pid_link *link;
+@@ -324,11 +325,10 @@ int attach_pid(struct task_struct *task, enum pid_type type,
+ link = &task->pids[type];
+ link->pid = pid;
+ hlist_add_head_rcu(&link->node, &pid->tasks[type]);
+-
+- return 0;
+ }
+
+-void detach_pid(struct task_struct *task, enum pid_type type)
++static void __change_pid(struct task_struct *task, enum pid_type type,
++ struct pid *new)
+ {
+ struct pid_link *link;
+ struct pid *pid;
+@@ -338,7 +338,7 @@ void detach_pid(struct task_struct *task, enum pid_type type)
+ pid = link->pid;
+
+ hlist_del_rcu(&link->node);
+- link->pid = NULL;
++ link->pid = new;
+
+ for (tmp = PIDTYPE_MAX; --tmp >= 0; )
+ if (!hlist_empty(&pid->tasks[tmp]))
+@@ -347,13 +347,24 @@ void detach_pid(struct task_struct *task, enum pid_type type)
+ free_pid(pid);
+ }
+
++void detach_pid(struct task_struct *task, enum pid_type type)
++{
++ __change_pid(task, type, NULL);
++}
++
++void change_pid(struct task_struct *task, enum pid_type type,
++ struct pid *pid)
++{
++ __change_pid(task, type, pid);
++ attach_pid(task, type, pid);
++}
++
+ /* transfer_pid is an optimization of attach_pid(new), detach_pid(old) */
+ void transfer_pid(struct task_struct *old, struct task_struct *new,
+ enum pid_type type)
+ {
+ new->pids[type].pid = old->pids[type].pid;
+ hlist_replace_rcu(&old->pids[type].node, &new->pids[type].node);
+- old->pids[type].pid = NULL;
+ }
+
+ struct task_struct *pid_task(struct pid *pid, enum pid_type type)
+@@ -380,12 +391,6 @@ struct task_struct *find_task_by_pid_type_ns(int type, int nr,
+
+ EXPORT_SYMBOL(find_task_by_pid_type_ns);
+
+-struct task_struct *find_task_by_pid(pid_t nr)
+-{
+- return find_task_by_pid_type_ns(PIDTYPE_PID, nr, &init_pid_ns);
+-}
+-EXPORT_SYMBOL(find_task_by_pid);
+-
+ struct task_struct *find_task_by_vpid(pid_t vnr)
+ {
+ return find_task_by_pid_type_ns(PIDTYPE_PID, vnr,
+diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
+index 6d792b6..98702b4 100644
+--- a/kernel/pid_namespace.c
++++ b/kernel/pid_namespace.c
+@@ -66,7 +66,7 @@ err_alloc:
+ return NULL;
+ }
+
+-static struct pid_namespace *create_pid_namespace(int level)
++static struct pid_namespace *create_pid_namespace(unsigned int level)
+ {
+ struct pid_namespace *ns;
+ int i;
+@@ -92,7 +92,7 @@ static struct pid_namespace *create_pid_namespace(int level)
+ atomic_set(&ns->pidmap[0].nr_free, BITS_PER_PAGE - 1);
+
+ for (i = 1; i < PIDMAP_ENTRIES; i++) {
+- ns->pidmap[i].page = 0;
++ ns->pidmap[i].page = NULL;
+ atomic_set(&ns->pidmap[i].nr_free, BITS_PER_PAGE);
+ }
+
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 2eae91f..ae5c6c1 100644
--- a/kernel/posix-cpu-timers.c
@@ -833907,7 +1120718,7 @@
/*
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
-index a9b0420..8476956 100644
+index a9b0420..dbd8398 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -37,7 +37,6 @@
@@ -833918,8 +1120729,527 @@
#include <linux/list.h>
#include <linux/init.h>
#include <linux/compiler.h>
+@@ -311,8 +310,7 @@ int posix_timer_event(struct k_itimer *timr,int si_private)
+
+ if (timr->it_sigev_notify & SIGEV_THREAD_ID) {
+ struct task_struct *leader;
+- int ret = send_sigqueue(timr->it_sigev_signo, timr->sigq,
+- timr->it_process);
++ int ret = send_sigqueue(timr->sigq, timr->it_process, 0);
+
+ if (likely(ret >= 0))
+ return ret;
+@@ -323,8 +321,7 @@ int posix_timer_event(struct k_itimer *timr,int si_private)
+ timr->it_process = leader;
+ }
+
+- return send_group_sigqueue(timr->it_sigev_signo, timr->sigq,
+- timr->it_process);
++ return send_sigqueue(timr->sigq, timr->it_process, 1);
+ }
+ EXPORT_SYMBOL_GPL(posix_timer_event);
+
+diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
+index 6233f3b..b45da40 100644
+--- a/kernel/power/Kconfig
++++ b/kernel/power/Kconfig
+@@ -19,16 +19,6 @@ config PM
+ will issue the hlt instruction if nothing is to be done, thereby
+ sending the processor to sleep and saving power.
+
+-config PM_LEGACY
+- bool "Legacy Power Management API (DEPRECATED)"
+- depends on PM
+- default n
+- ---help---
+- Support for pm_register() and friends. This old API is obsoleted
+- by the driver model.
+-
+- If unsure, say N.
+-
+ config PM_DEBUG
+ bool "Power Management Debug Support"
+ depends on PM
+diff --git a/kernel/power/Makefile b/kernel/power/Makefile
+index f7dfff2..597823b 100644
+--- a/kernel/power/Makefile
++++ b/kernel/power/Makefile
+@@ -4,7 +4,6 @@ EXTRA_CFLAGS += -DDEBUG
+ endif
+
+ obj-y := main.o
+-obj-$(CONFIG_PM_LEGACY) += pm.o
+ obj-$(CONFIG_PM_SLEEP) += process.o console.o
+ obj-$(CONFIG_HIBERNATION) += swsusp.o disk.o snapshot.o swap.o user.o
+
+diff --git a/kernel/power/console.c b/kernel/power/console.c
+index 89bcf49..b8628be 100644
+--- a/kernel/power/console.c
++++ b/kernel/power/console.c
+@@ -7,17 +7,39 @@
+ #include <linux/vt_kern.h>
+ #include <linux/kbd_kern.h>
+ #include <linux/console.h>
++#include <linux/module.h>
+ #include "power.h"
+
+ #if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE)
+ #define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1)
+
+ static int orig_fgconsole, orig_kmsg;
++static int disable_vt_switch;
++
++/*
++ * Normally during a suspend, we allocate a new console and switch to it.
++ * When we resume, we switch back to the original console. This switch
++ * can be slow, so on systems where the framebuffer can handle restoration
++ * of video registers anyways, there's little point in doing the console
++ * switch. This function allows you to disable it by passing it '0'.
++ */
++void pm_set_vt_switch(int do_switch)
++{
++ acquire_console_sem();
++ disable_vt_switch = !do_switch;
++ release_console_sem();
++}
++EXPORT_SYMBOL(pm_set_vt_switch);
+
+ int pm_prepare_console(void)
+ {
+ acquire_console_sem();
+
++ if (disable_vt_switch) {
++ release_console_sem();
++ return 0;
++ }
++
+ orig_fgconsole = fg_console;
+
+ if (vc_allocate(SUSPEND_CONSOLE)) {
+@@ -50,9 +72,12 @@ int pm_prepare_console(void)
+ void pm_restore_console(void)
+ {
+ acquire_console_sem();
++ if (disable_vt_switch) {
++ release_console_sem();
++ return;
++ }
+ set_console(orig_fgconsole);
+ release_console_sem();
+ kmsg_redirect = orig_kmsg;
+- return;
+ }
+ #endif
+diff --git a/kernel/power/pm.c b/kernel/power/pm.c
+deleted file mode 100644
+index 60c73fa..0000000
+--- a/kernel/power/pm.c
++++ /dev/null
+@@ -1,205 +0,0 @@
+-/*
+- * pm.c - Power management interface
+- *
+- * Copyright (C) 2000 Andrew Henroid
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/spinlock.h>
+-#include <linux/mm.h>
+-#include <linux/slab.h>
+-#include <linux/pm.h>
+-#include <linux/pm_legacy.h>
+-#include <linux/interrupt.h>
+-#include <linux/mutex.h>
+-
+-/*
+- * Locking notes:
+- * pm_devs_lock can be a semaphore providing pm ops are not called
+- * from an interrupt handler (already a bad idea so no change here). Each
+- * change must be protected so that an unlink of an entry doesn't clash
+- * with a pm send - which is permitted to sleep in the current architecture
+- *
+- * Module unloads clashing with pm events now work out safely, the module
+- * unload path will block until the event has been sent. It may well block
+- * until a resume but that will be fine.
+- */
+-
+-static DEFINE_MUTEX(pm_devs_lock);
+-static LIST_HEAD(pm_devs);
+-
+-/**
+- * pm_register - register a device with power management
+- * @type: device type
+- * @id: device ID
+- * @callback: callback function
+- *
+- * Add a device to the list of devices that wish to be notified about
+- * power management events. A &pm_dev structure is returned on success,
+- * on failure the return is %NULL.
+- *
+- * The callback function will be called in process context and
+- * it may sleep.
+- */
+-
+-struct pm_dev *pm_register(pm_dev_t type,
+- unsigned long id,
+- pm_callback callback)
+-{
+- struct pm_dev *dev = kzalloc(sizeof(struct pm_dev), GFP_KERNEL);
+- if (dev) {
+- dev->type = type;
+- dev->id = id;
+- dev->callback = callback;
+-
+- mutex_lock(&pm_devs_lock);
+- list_add(&dev->entry, &pm_devs);
+- mutex_unlock(&pm_devs_lock);
+- }
+- return dev;
+-}
+-
+-/**
+- * pm_send - send request to a single device
+- * @dev: device to send to
+- * @rqst: power management request
+- * @data: data for the callback
+- *
+- * Issue a power management request to a given device. The
+- * %PM_SUSPEND and %PM_RESUME events are handled specially. The
+- * data field must hold the intended next state. No call is made
+- * if the state matches.
+- *
+- * BUGS: what stops two power management requests occurring in parallel
+- * and conflicting.
+- *
+- * WARNING: Calling pm_send directly is not generally recommended, in
+- * particular there is no locking against the pm_dev going away. The
+- * caller must maintain all needed locking or have 'inside knowledge'
+- * on the safety. Also remember that this function is not locked against
+- * pm_unregister. This means that you must handle SMP races on callback
+- * execution and unload yourself.
+- */
+-
+-static int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data)
+-{
+- int status = 0;
+- unsigned long prev_state, next_state;
+-
+- if (in_interrupt())
+- BUG();
+-
+- switch (rqst) {
+- case PM_SUSPEND:
+- case PM_RESUME:
+- prev_state = dev->state;
+- next_state = (unsigned long) data;
+- if (prev_state != next_state) {
+- if (dev->callback)
+- status = (*dev->callback)(dev, rqst, data);
+- if (!status) {
+- dev->state = next_state;
+- dev->prev_state = prev_state;
+- }
+- }
+- else {
+- dev->prev_state = prev_state;
+- }
+- break;
+- default:
+- if (dev->callback)
+- status = (*dev->callback)(dev, rqst, data);
+- break;
+- }
+- return status;
+-}
+-
+-/*
+- * Undo incomplete request
+- */
+-static void pm_undo_all(struct pm_dev *last)
+-{
+- struct list_head *entry = last->entry.prev;
+- while (entry != &pm_devs) {
+- struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
+- if (dev->state != dev->prev_state) {
+- /* previous state was zero (running) resume or
+- * previous state was non-zero (suspended) suspend
+- */
+- pm_request_t undo = (dev->prev_state
+- ? PM_SUSPEND:PM_RESUME);
+- pm_send(dev, undo, (void*) dev->prev_state);
+- }
+- entry = entry->prev;
+- }
+-}
+-
+-/**
+- * pm_send_all - send request to all managed devices
+- * @rqst: power management request
+- * @data: data for the callback
+- *
+- * Issue a power management request to a all devices. The
+- * %PM_SUSPEND events are handled specially. Any device is
+- * permitted to fail a suspend by returning a non zero (error)
+- * value from its callback function. If any device vetoes a
+- * suspend request then all other devices that have suspended
+- * during the processing of this request are restored to their
+- * previous state.
+- *
+- * WARNING: This function takes the pm_devs_lock. The lock is not dropped until
+- * the callbacks have completed. This prevents races against pm locking
+- * functions, races against module unload pm_unregister code. It does
+- * mean however that you must not issue pm_ functions within the callback
+- * or you will deadlock and users will hate you.
+- *
+- * Zero is returned on success. If a suspend fails then the status
+- * from the device that vetoes the suspend is returned.
+- *
+- * BUGS: what stops two power management requests occurring in parallel
+- * and conflicting.
+- */
+-
+-int pm_send_all(pm_request_t rqst, void *data)
+-{
+- struct list_head *entry;
+-
+- mutex_lock(&pm_devs_lock);
+- entry = pm_devs.next;
+- while (entry != &pm_devs) {
+- struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
+- if (dev->callback) {
+- int status = pm_send(dev, rqst, data);
+- if (status) {
+- /* return devices to previous state on
+- * failed suspend request
+- */
+- if (rqst == PM_SUSPEND)
+- pm_undo_all(dev);
+- mutex_unlock(&pm_devs_lock);
+- return status;
+- }
+- }
+- entry = entry->next;
+- }
+- mutex_unlock(&pm_devs_lock);
+- return 0;
+-}
+-
+-EXPORT_SYMBOL(pm_register);
+-EXPORT_SYMBOL(pm_send_all);
+-
+diff --git a/kernel/printk.c b/kernel/printk.c
+index bdd4ea8..8fb01c3 100644
+--- a/kernel/printk.c
++++ b/kernel/printk.c
+@@ -111,6 +111,9 @@ struct console_cmdline
+ char name[8]; /* Name of the driver */
+ int index; /* Minor dev. to use */
+ char *options; /* Options for the driver */
++#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
++ char *brl_options; /* Options for braille driver */
++#endif
+ };
+
+ #define MAX_CMDLINECONSOLES 8
+@@ -808,15 +811,60 @@ static void call_console_drivers(unsigned start, unsigned end)
+
+ #endif
+
++static int __add_preferred_console(char *name, int idx, char *options,
++ char *brl_options)
++{
++ struct console_cmdline *c;
++ int i;
++
++ /*
++ * See if this tty is not yet registered, and
++ * if we have a slot free.
++ */
++ for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
++ if (strcmp(console_cmdline[i].name, name) == 0 &&
++ console_cmdline[i].index == idx) {
++ if (!brl_options)
++ selected_console = i;
++ return 0;
++ }
++ if (i == MAX_CMDLINECONSOLES)
++ return -E2BIG;
++ if (!brl_options)
++ selected_console = i;
++ c = &console_cmdline[i];
++ strlcpy(c->name, name, sizeof(c->name));
++ c->options = options;
++#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
++ c->brl_options = brl_options;
++#endif
++ c->index = idx;
++ return 0;
++}
+ /*
+ * Set up a list of consoles. Called from init/main.c
+ */
+ static int __init console_setup(char *str)
+ {
+ char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for index */
+- char *s, *options;
++ char *s, *options, *brl_options = NULL;
+ int idx;
+
++#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
++ if (!memcmp(str, "brl,", 4)) {
++ brl_options = "";
++ str += 4;
++ } else if (!memcmp(str, "brl=", 4)) {
++ brl_options = str + 4;
++ str = strchr(brl_options, ',');
++ if (!str) {
++ printk(KERN_ERR "need port name after brl=\n");
++ return 1;
++ }
++ *(str++) = 0;
++ }
++#endif
++
+ /*
+ * Decode str into name, index, options.
+ */
+@@ -841,7 +889,7 @@ static int __init console_setup(char *str)
+ idx = simple_strtoul(s, NULL, 10);
+ *s = 0;
+
+- add_preferred_console(buf, idx, options);
++ __add_preferred_console(buf, idx, options, brl_options);
+ return 1;
+ }
+ __setup("console=", console_setup);
+@@ -861,28 +909,7 @@ __setup("console=", console_setup);
+ */
+ int add_preferred_console(char *name, int idx, char *options)
+ {
+- struct console_cmdline *c;
+- int i;
+-
+- /*
+- * See if this tty is not yet registered, and
+- * if we have a slot free.
+- */
+- for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
+- if (strcmp(console_cmdline[i].name, name) == 0 &&
+- console_cmdline[i].index == idx) {
+- selected_console = i;
+- return 0;
+- }
+- if (i == MAX_CMDLINECONSOLES)
+- return -E2BIG;
+- selected_console = i;
+- c = &console_cmdline[i];
+- memcpy(c->name, name, sizeof(c->name));
+- c->name[sizeof(c->name) - 1] = 0;
+- c->options = options;
+- c->index = idx;
+- return 0;
++ return __add_preferred_console(name, idx, options, NULL);
+ }
+
+ int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options)
+@@ -894,7 +921,7 @@ int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, cha
+ if (strcmp(console_cmdline[i].name, name) == 0 &&
+ console_cmdline[i].index == idx) {
+ c = &console_cmdline[i];
+- memcpy(c->name, name_new, sizeof(c->name));
++ strlcpy(c->name, name_new, sizeof(c->name));
+ c->name[sizeof(c->name) - 1] = 0;
+ c->options = options;
+ c->index = idx_new;
+@@ -1163,6 +1190,16 @@ void register_console(struct console *console)
+ continue;
+ if (console->index < 0)
+ console->index = console_cmdline[i].index;
++#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
++ if (console_cmdline[i].brl_options) {
++ console->flags |= CON_BRL;
++ braille_register_console(console,
++ console_cmdline[i].index,
++ console_cmdline[i].options,
++ console_cmdline[i].brl_options);
++ return;
++ }
++#endif
+ if (console->setup &&
+ console->setup(console, console_cmdline[i].options) != 0)
+ break;
+@@ -1221,6 +1258,11 @@ int unregister_console(struct console *console)
+ struct console *a, *b;
+ int res = 1;
+
++#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
++ if (console->flags & CON_BRL)
++ return braille_unregister_console(console);
++#endif
++
+ acquire_console_sem();
+ if (console_drivers == console) {
+ console_drivers=console->next;
+@@ -1272,8 +1314,8 @@ late_initcall(disable_boot_consoles);
+ */
+ void tty_write_message(struct tty_struct *tty, char *msg)
+ {
+- if (tty && tty->driver->write)
+- tty->driver->write(tty, msg, strlen(msg));
++ if (tty && tty->ops->write)
++ tty->ops->write(tty, msg, strlen(msg));
+ return;
+ }
+
+@@ -1287,31 +1329,7 @@ void tty_write_message(struct tty_struct *tty, char *msg)
+ */
+ int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst)
+ {
+- static DEFINE_SPINLOCK(ratelimit_lock);
+- static unsigned toks = 10 * 5 * HZ;
+- static unsigned long last_msg;
+- static int missed;
+- unsigned long flags;
+- unsigned long now = jiffies;
+-
+- spin_lock_irqsave(&ratelimit_lock, flags);
+- toks += now - last_msg;
+- last_msg = now;
+- if (toks > (ratelimit_burst * ratelimit_jiffies))
+- toks = ratelimit_burst * ratelimit_jiffies;
+- if (toks >= ratelimit_jiffies) {
+- int lost = missed;
+-
+- missed = 0;
+- toks -= ratelimit_jiffies;
+- spin_unlock_irqrestore(&ratelimit_lock, flags);
+- if (lost)
+- printk(KERN_WARNING "printk: %d messages suppressed.\n", lost);
+- return 1;
+- }
+- missed++;
+- spin_unlock_irqrestore(&ratelimit_lock, flags);
+- return 0;
++ return __ratelimit(ratelimit_jiffies, ratelimit_burst);
+ }
+ EXPORT_SYMBOL(__printk_ratelimit);
+
diff --git a/kernel/profile.c b/kernel/profile.c
-index 3b7a1b0..606d738 100644
+index 3b7a1b0..ae7ead8 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -23,7 +23,6 @@
@@ -833930,11 +1121260,52 @@
#include <asm/irq_regs.h>
#include <asm/ptrace.h>
+@@ -588,10 +587,10 @@ static int __init create_proc_profile(void)
+ return 0;
+ if (create_hash_tables())
+ return -1;
+- entry = create_proc_entry("profile", S_IWUSR | S_IRUGO, NULL);
++ entry = proc_create("profile", S_IWUSR | S_IRUGO,
++ NULL, &proc_profile_operations);
+ if (!entry)
+ return 0;
+- entry->proc_fops = &proc_profile_operations;
+ entry->size = (1+prof_len) * sizeof(atomic_t);
+ hotcpu_notifier(profile_cpu_callback, 0);
+ return 0;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
-index fdb34e8..67e392e 100644
+index fdb34e8..dcc199c 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
-@@ -323,9 +323,8 @@ static int ptrace_setoptions(struct task_struct *child, long data)
+@@ -73,7 +73,7 @@ void __ptrace_unlink(struct task_struct *child)
+ BUG_ON(!child->ptrace);
+
+ child->ptrace = 0;
+- if (!list_empty(&child->ptrace_list)) {
++ if (ptrace_reparented(child)) {
+ list_del_init(&child->ptrace_list);
+ remove_parent(child);
+ child->parent = child->real_parent;
+@@ -168,8 +168,6 @@ int ptrace_attach(struct task_struct *task)
+ audit_ptrace(task);
+
+ retval = -EPERM;
+- if (task->pid <= 1)
+- goto out;
+ if (same_thread_group(task, current))
+ goto out;
+
+@@ -208,8 +206,7 @@ repeat:
+
+ __ptrace_link(task, current);
+
+- force_sig_specific(SIGSTOP, task);
+-
++ send_sig_info(SIGSTOP, SEND_SIG_FORCED, task);
+ bad:
+ write_unlock_irqrestore(&tasklist_lock, flags);
+ task_unlock(task);
+@@ -323,9 +320,8 @@ static int ptrace_setoptions(struct task_struct *child, long data)
return (data & ~PTRACE_O_MASK) ? -EINVAL : 0;
}
@@ -833945,7 +1121316,7 @@
int error = -ESRCH;
read_lock(&tasklist_lock);
-@@ -333,31 +332,25 @@ static int ptrace_getsiginfo(struct task_struct *child, siginfo_t __user * data)
+@@ -333,31 +329,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)) {
@@ -833980,7 +1121351,7 @@
error = 0;
}
spin_unlock_irq(&child->sighand->siglock);
-@@ -424,6 +417,7 @@ int ptrace_request(struct task_struct *child, long request,
+@@ -424,6 +414,7 @@ int ptrace_request(struct task_struct *child, long request,
long addr, long data)
{
int ret = -EIO;
@@ -833988,7 +1121359,7 @@
switch (request) {
case PTRACE_PEEKTEXT:
-@@ -442,12 +436,22 @@ int ptrace_request(struct task_struct *child, long request,
+@@ -442,12 +433,22 @@ int ptrace_request(struct task_struct *child, long request,
case PTRACE_GETEVENTMSG:
ret = put_user(child->ptrace_message, (unsigned long __user *) data);
break;
@@ -834013,7 +1121384,29 @@
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,
+@@ -518,12 +519,6 @@ struct task_struct *ptrace_get_task_struct(pid_t pid)
+ {
+ struct task_struct *child;
+
+- /*
+- * Tracing init is not allowed.
+- */
+- if (pid == 1)
+- return ERR_PTR(-EPERM);
+-
+ read_lock(&tasklist_lock);
+ child = find_task_by_vpid(pid);
+ if (child)
+@@ -608,7 +603,7 @@ int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data)
+ return (copied == sizeof(data)) ? 0 : -EIO;
+ }
+
+-#ifdef CONFIG_COMPAT
++#if defined CONFIG_COMPAT && defined __ARCH_WANT_COMPAT_SYS_PTRACE
+ #include <linux/compat.h>
+
+ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
+@@ -616,6 +611,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;
@@ -834021,7 +1121414,7 @@
int ret;
switch (request) {
-@@ -638,6 +643,23 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
+@@ -638,6 +634,23 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
ret = put_user((compat_ulong_t) child->ptrace_message, datap);
break;
@@ -834045,6 +1121438,22 @@
default:
ret = ptrace_request(child, request, addr, data);
}
+@@ -645,7 +658,6 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
+ return ret;
+ }
+
+-#ifdef __ARCH_WANT_COMPAT_SYS_PTRACE
+ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
+ compat_long_t addr, compat_long_t data)
+ {
+@@ -688,6 +700,4 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
+ unlock_kernel();
+ return ret;
+ }
+-#endif /* __ARCH_WANT_COMPAT_SYS_PTRACE */
+-
+-#endif /* CONFIG_COMPAT */
++#endif /* CONFIG_COMPAT && __ARCH_WANT_COMPAT_SYS_PTRACE */
diff --git a/kernel/rcupreempt.c b/kernel/rcupreempt.c
index e951701..e1cdf19 100644
--- a/kernel/rcupreempt.c
@@ -834063,10 +1121472,18 @@
EXPORT_SYMBOL_GPL(__synchronize_sched);
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
-index fd59982..47894f9 100644
+index fd59982..33acc42 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 */
+@@ -45,6 +45,7 @@
+ #include <linux/byteorder/swabb.h>
+ #include <linux/stat.h>
+ #include <linux/srcu.h>
++#include <linux/slab.h>
+
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Paul E. McKenney <paulmck at us.ibm.com> and "
+@@ -723,9 +724,10 @@ static int rcu_idle_cpu; /* Force all torture tasks off this CPU */
*/
static void rcu_torture_shuffle_tasks(void)
{
@@ -834078,7 +1121495,7 @@
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)
+@@ -737,25 +739,27 @@ static void rcu_torture_shuffle_tasks(void)
if (rcu_idle_cpu != -1)
cpu_clear(rcu_idle_cpu, tmp_mask);
@@ -834111,11 +1121528,146 @@
if (rcu_idle_cpu == -1)
rcu_idle_cpu = num_online_cpus() - 1;
+diff --git a/kernel/relay.c b/kernel/relay.c
+index d6204a4..7de644c 100644
+--- a/kernel/relay.c
++++ b/kernel/relay.c
+@@ -65,6 +65,35 @@ static struct vm_operations_struct relay_file_mmap_ops = {
+ .close = relay_file_mmap_close,
+ };
+
++/*
++ * allocate an array of pointers of struct page
++ */
++static struct page **relay_alloc_page_array(unsigned int n_pages)
++{
++ struct page **array;
++ size_t pa_size = n_pages * sizeof(struct page *);
++
++ if (pa_size > PAGE_SIZE) {
++ array = vmalloc(pa_size);
++ if (array)
++ memset(array, 0, pa_size);
++ } else {
++ array = kzalloc(pa_size, GFP_KERNEL);
++ }
++ return array;
++}
++
++/*
++ * free an array of pointers of struct page
++ */
++static void relay_free_page_array(struct page **array)
++{
++ if (is_vmalloc_addr(array))
++ vfree(array);
++ else
++ kfree(array);
++}
++
+ /**
+ * relay_mmap_buf: - mmap channel buffer to process address space
+ * @buf: relay channel buffer
+@@ -109,7 +138,7 @@ static void *relay_alloc_buf(struct rchan_buf *buf, size_t *size)
+ *size = PAGE_ALIGN(*size);
+ n_pages = *size >> PAGE_SHIFT;
+
+- buf->page_array = kcalloc(n_pages, sizeof(struct page *), GFP_KERNEL);
++ buf->page_array = relay_alloc_page_array(n_pages);
+ if (!buf->page_array)
+ return NULL;
+
+@@ -130,7 +159,7 @@ static void *relay_alloc_buf(struct rchan_buf *buf, size_t *size)
+ depopulate:
+ for (j = 0; j < i; j++)
+ __free_page(buf->page_array[j]);
+- kfree(buf->page_array);
++ relay_free_page_array(buf->page_array);
+ return NULL;
+ }
+
+@@ -189,7 +218,7 @@ static void relay_destroy_buf(struct rchan_buf *buf)
+ vunmap(buf->start);
+ for (i = 0; i < buf->page_count; i++)
+ __free_page(buf->page_array[i]);
+- kfree(buf->page_array);
++ relay_free_page_array(buf->page_array);
+ }
+ chan->buf[buf->cpu] = NULL;
+ kfree(buf->padding);
+@@ -1162,7 +1191,7 @@ static ssize_t relay_file_splice_read(struct file *in,
+ ret = 0;
+ spliced = 0;
+
+- while (len) {
++ while (len && !spliced) {
+ ret = subbuf_splice_actor(in, ppos, pipe, len, flags, &nonpad_ret);
+ if (ret < 0)
+ break;
+diff --git a/kernel/res_counter.c b/kernel/res_counter.c
+index efbfc0f..d3c61b4 100644
+--- a/kernel/res_counter.c
++++ b/kernel/res_counter.c
+@@ -10,6 +10,7 @@
+ #include <linux/types.h>
+ #include <linux/parser.h>
+ #include <linux/fs.h>
++#include <linux/slab.h>
+ #include <linux/res_counter.h>
+ #include <linux/uaccess.h>
+
+@@ -27,6 +28,8 @@ int res_counter_charge_locked(struct res_counter *counter, unsigned long val)
+ }
+
+ counter->usage += val;
++ if (counter->usage > counter->max_usage)
++ counter->max_usage = counter->usage;
+ return 0;
+ }
+
+@@ -65,6 +68,8 @@ res_counter_member(struct res_counter *counter, int member)
+ switch (member) {
+ case RES_USAGE:
+ return &counter->usage;
++ case RES_MAX_USAGE:
++ return &counter->max_usage;
+ case RES_LIMIT:
+ return &counter->limit;
+ case RES_FAILCNT:
+@@ -92,6 +97,11 @@ ssize_t res_counter_read(struct res_counter *counter, int member,
+ pos, buf, s - buf);
+ }
+
++u64 res_counter_read_u64(struct res_counter *counter, int member)
++{
++ return *res_counter_member(counter, member);
++}
++
+ ssize_t res_counter_write(struct res_counter *counter, int member,
+ const char __user *userbuf, size_t nbytes, loff_t *pos,
+ int (*write_strategy)(char *st_buf, unsigned long long *val))
diff --git a/kernel/resource.c b/kernel/resource.c
-index 82aea81..cee12cc 100644
+index 82aea81..74af2d7 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
+@@ -131,14 +131,8 @@ static const struct file_operations proc_iomem_operations = {
+
+ static int __init ioresources_init(void)
+ {
+- struct proc_dir_entry *entry;
+-
+- entry = create_proc_entry("ioports", 0, NULL);
+- if (entry)
+- entry->proc_fops = &proc_ioports_operations;
+- entry = create_proc_entry("iomem", 0, NULL);
+- if (entry)
+- entry->proc_fops = &proc_iomem_operations;
++ proc_create("ioports", 0, NULL, &proc_ioports_operations);
++ proc_create("iomem", 0, NULL, &proc_iomem_operations);
+ return 0;
+ }
+ __initcall(ioresources_init);
+@@ -486,6 +480,24 @@ int adjust_resource(struct resource *res, resource_size_t start, resource_size_t
EXPORT_SYMBOL(adjust_resource);
@@ -834141,7 +1121693,7 @@
* This is compatibility stuff for IO resources.
*
diff --git a/kernel/sched.c b/kernel/sched.c
-index 8dcdec6..740fb40 100644
+index 8dcdec6..e2f7f5a 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -66,6 +66,10 @@
@@ -834526,10 +1122078,10 @@
+#include "sched_features.h"
+ NULL
+};
-+
-+#undef SCHED_FEAT
-#define sched_feat(x) (sysctl_sched_features & SCHED_FEAT_##x)
++#undef SCHED_FEAT
++
+int sched_feat_open(struct inode *inode, struct file *filp)
+{
+ filp->private_data = inode->i_private;
@@ -836009,9 +1123561,9 @@
+#ifdef CONFIG_NUMA
+ kfree(sched_group_nodes);
+#endif
-+ return -ENOMEM;
-+ }
-+
+ return -ENOMEM;
+ }
+
+#if SCHED_CPUMASK_ALLOC
+ /* get space for all scratch cpumask variables */
+ allmasks = kmalloc(sizeof(*allmasks), GFP_KERNEL);
@@ -836021,8 +1123573,8 @@
+#ifdef CONFIG_NUMA
+ kfree(sched_group_nodes);
+#endif
- return -ENOMEM;
- }
++ return -ENOMEM;
++ }
+#endif
+ tmpmask = (cpumask_t *)allmasks;
+
@@ -836030,7 +1123582,7 @@
+#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.
*/
@@ -837209,46 +1124761,112 @@
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)
+@@ -7920,13 +9057,13 @@ cpu_cgroup_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
+ }
+
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+-static int cpu_shares_write_uint(struct cgroup *cgrp, struct cftype *cftype,
++static int cpu_shares_write_u64(struct cgroup *cgrp, struct cftype *cftype,
+ u64 shareval)
+ {
+ return sched_group_set_shares(cgroup_tg(cgrp), shareval);
+ }
+
+-static u64 cpu_shares_read_uint(struct cgroup *cgrp, struct cftype *cft)
++static u64 cpu_shares_read_u64(struct cgroup *cgrp, struct cftype *cft)
+ {
+ struct task_group *tg = cgroup_tg(cgrp);
+
+@@ -7935,49 +9072,26 @@ 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,
+- struct file *file,
+- const char __user *userbuf,
+- size_t nbytes, loff_t *unused_ppos)
+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,
++ s64 val)
+ {
+- char buffer[64];
+- int retval = 0;
+- s64 val;
+- char *end;
+-
+- if (!nbytes)
+- return -EINVAL;
+- if (nbytes >= sizeof(buffer))
+- return -E2BIG;
+- if (copy_from_user(buffer, userbuf, nbytes))
+- return -EFAULT;
+-
+- buffer[nbytes] = 0; /* nul-terminate */
+-
+- /* strip newline if necessary */
+- if (nbytes && (buffer[nbytes-1] == '\n'))
+- buffer[nbytes-1] = 0;
+- val = simple_strtoll(buffer, &end, 0);
+- if (*end)
+- return -EINVAL;
++ return sched_group_set_rt_runtime(cgroup_tg(cgrp), val);
++}
- return simple_read_from_buffer(buf, nbytes, ppos, tmp, len);
+- /* Pass to subsystem */
+- retval = sched_group_set_rt_runtime(cgroup_tg(cgrp), val);
+- if (!retval)
+- retval = nbytes;
+- return retval;
++static s64 cpu_rt_runtime_read(struct cgroup *cgrp, struct cftype *cft)
++{
++ return sched_group_rt_runtime(cgroup_tg(cgrp));
}
-+
+
+-static ssize_t cpu_rt_runtime_read(struct cgroup *cgrp, struct cftype *cft,
+- struct file *file,
+- char __user *buf, size_t nbytes,
+- loff_t *ppos)
+static int cpu_rt_period_write_uint(struct cgroup *cgrp, struct cftype *cftype,
+ u64 rt_period_us)
-+{
+ {
+- char tmp[64];
+- long val = sched_group_rt_runtime(cgroup_tg(cgrp));
+- int len = sprintf(tmp, "%ld\n", val);
+ return sched_group_set_rt_period(cgroup_tg(cgrp), rt_period_us);
+}
-+
+
+- return simple_read_from_buffer(buf, nbytes, ppos, tmp, len);
+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,
+@@ -7985,15 +9099,20 @@ static struct cftype cpu_files[] = {
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ {
+ .name = "shares",
+- .read_uint = cpu_shares_read_uint,
+- .write_uint = cpu_shares_write_uint,
++ .read_u64 = cpu_shares_read_u64,
++ .write_u64 = cpu_shares_write_u64,
},
+ #endif
+ #ifdef CONFIG_RT_GROUP_SCHED
+ {
+ .name = "rt_runtime_us",
+- .read = cpu_rt_runtime_read,
+- .write = cpu_rt_runtime_write,
++ .read_s64 = cpu_rt_runtime_read,
++ .write_s64 = cpu_rt_runtime_write,
++ },
+ {
+ .name = "rt_period_us",
-+ .read_uint = cpu_rt_period_read_uint,
-+ .write_uint = cpu_rt_period_write_uint,
-+ },
++ .read_u64 = cpu_rt_period_read_uint,
++ .write_u64 = cpu_rt_period_write_uint,
+ },
#endif
};
-
-@@ -8035,9 +9188,9 @@ struct cpuacct {
+@@ -8035,9 +9154,9 @@ struct cpuacct {
struct cgroup_subsys cpuacct_subsys;
/* return cpu accounting group corresponding to this container */
@@ -837260,7 +1124878,7 @@
struct cpuacct, css);
}
-@@ -8050,7 +9203,7 @@ static inline struct cpuacct *task_ca(struct task_struct *tsk)
+@@ -8050,7 +9169,7 @@ static inline struct cpuacct *task_ca(struct task_struct *tsk)
/* create a new cpu accounting group */
static struct cgroup_subsys_state *cpuacct_create(
@@ -837269,7 +1124887,7 @@
{
struct cpuacct *ca = kzalloc(sizeof(*ca), GFP_KERNEL);
-@@ -8068,18 +9221,18 @@ static struct cgroup_subsys_state *cpuacct_create(
+@@ -8068,18 +9187,18 @@ static struct cgroup_subsys_state *cpuacct_create(
/* destroy an existing cpu accounting group */
static void
@@ -837292,7 +1124910,7 @@
u64 totalcpuusage = 0;
int i;
-@@ -8098,16 +9251,40 @@ static u64 cpuusage_read(struct cgroup *cont, struct cftype *cft)
+@@ -8098,16 +9217,40 @@ static u64 cpuusage_read(struct cgroup *cont, struct cftype *cft)
return totalcpuusage;
}
@@ -837322,8 +1124940,9 @@
static struct cftype files[] = {
{
.name = "usage",
- .read_uint = cpuusage_read,
-+ .write_uint = cpuusage_write,
+- .read_uint = cpuusage_read,
++ .read_u64 = cpuusage_read,
++ .write_u64 = cpuusage_write,
},
};
@@ -837336,7 +1124955,7 @@
/*
diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c
-index ef358ba..f3f4af4 100644
+index ef358ba..8a9498e 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)
@@ -837409,6 +1125028,20 @@
PN(sysctl_sched_child_runs_first);
P(sysctl_sched_features);
#undef PN
+@@ -249,12 +277,9 @@ static int __init init_sched_debug_procfs(void)
+ {
+ struct proc_dir_entry *pe;
+
+- pe = create_proc_entry("sched_debug", 0644, NULL);
++ pe = proc_create("sched_debug", 0644, NULL, &sched_debug_fops);
+ if (!pe)
+ return -ENOMEM;
+-
+- pe->proc_fops = &sched_debug_fops;
+-
+ return 0;
+ }
+
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index 0080968..89fa32b 100644
--- a/kernel/sched_fair.c
@@ -838850,10 +1126483,44 @@
+ wake_up_process(waiter->task);
+}
diff --git a/kernel/signal.c b/kernel/signal.c
-index 6af1210..64ad0ed 100644
+index 6af1210..72bb4f5 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
-@@ -220,7 +220,7 @@ void flush_signals(struct task_struct *t)
+@@ -39,11 +39,19 @@
+
+ static struct kmem_cache *sigqueue_cachep;
+
++static int __sig_ignored(struct task_struct *t, int sig)
++{
++ void __user *handler;
++
++ /* Is it explicitly or implicitly ignored? */
++
++ handler = t->sighand->action[sig - 1].sa.sa_handler;
++ return handler == SIG_IGN ||
++ (handler == SIG_DFL && sig_kernel_ignore(sig));
++}
+
+ static int sig_ignored(struct task_struct *t, int sig)
+ {
+- void __user * handler;
+-
+ /*
+ * Tracers always want to know about signals..
+ */
+@@ -58,10 +66,7 @@ static int sig_ignored(struct task_struct *t, int sig)
+ if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig))
+ return 0;
+
+- /* Is it explicitly or implicitly ignored? */
+- handler = t->sighand->action[sig-1].sa.sa_handler;
+- return handler == SIG_IGN ||
+- (handler == SIG_DFL && sig_kernel_ignore(sig));
++ return __sig_ignored(t, sig);
+ }
+
+ /*
+@@ -220,7 +225,7 @@ void flush_signals(struct task_struct *t)
unsigned long flags;
spin_lock_irqsave(&t->sighand->siglock, flags);
@@ -838862,16 +1126529,789 @@
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)
+@@ -372,7 +377,7 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
+ */
+ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
+ {
+- int signr = 0;
++ int signr;
+
+ /* We only dequeue private signals from ourselves, we don't let
+ * signalfd steal them
+@@ -405,8 +410,12 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
+ }
+ }
+ }
++
+ recalc_sigpending();
+- if (signr && unlikely(sig_kernel_stop(signr))) {
++ if (!signr)
++ return 0;
++
++ if (unlikely(sig_kernel_stop(signr))) {
+ /*
+ * Set a marker that we have dequeued a stop signal. Our
+ * caller might release the siglock and then the pending
+@@ -422,9 +431,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
+ if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT))
+ tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
}
- if (signr &&
- ((info->si_code & __SI_MASK) == __SI_TIMER) &&
+- if (signr &&
+- ((info->si_code & __SI_MASK) == __SI_TIMER) &&
- info->si_sys_private){
-+ info->si_sys_private) {
++ if ((info->si_code & __SI_MASK) == __SI_TIMER && 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)
+@@ -526,21 +533,34 @@ static int rm_from_queue(unsigned long mask, struct sigpending *s)
+ static int check_kill_permission(int sig, struct siginfo *info,
+ struct task_struct *t)
+ {
+- int error = -EINVAL;
++ struct pid *sid;
++ int error;
++
+ if (!valid_signal(sig))
+- return error;
++ return -EINVAL;
+
+- if (info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) {
+- error = audit_signal_info(sig, t); /* Let audit system see the signal */
+- if (error)
+- return error;
+- error = -EPERM;
+- if (((sig != SIGCONT) ||
+- (task_session_nr(current) != task_session_nr(t)))
+- && (current->euid ^ t->suid) && (current->euid ^ t->uid)
+- && (current->uid ^ t->suid) && (current->uid ^ t->uid)
+- && !capable(CAP_KILL))
++ if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
++ return 0;
++
++ error = audit_signal_info(sig, t); /* Let audit system see the signal */
++ if (error)
+ return error;
++
++ if ((current->euid ^ t->suid) && (current->euid ^ t->uid) &&
++ (current->uid ^ t->suid) && (current->uid ^ t->uid) &&
++ !capable(CAP_KILL)) {
++ switch (sig) {
++ case SIGCONT:
++ sid = task_session(t);
++ /*
++ * We don't return the error if sid == NULL. The
++ * task was unhashed, the caller must notice this.
++ */
++ if (!sid || sid == task_session(current))
++ break;
++ default:
++ return -EPERM;
++ }
+ }
+
+ return security_task_kill(t, info, sig, 0);
+@@ -550,62 +570,44 @@ static int check_kill_permission(int sig, struct siginfo *info,
+ static void do_notify_parent_cldstop(struct task_struct *tsk, int why);
+
+ /*
+- * Handle magic process-wide effects of stop/continue signals.
+- * Unlike the signal actions, these happen immediately at signal-generation
++ * Handle magic process-wide effects of stop/continue signals. Unlike
++ * the signal actions, these happen immediately at signal-generation
+ * time regardless of blocking, ignoring, or handling. This does the
+ * actual continuing for SIGCONT, but not the actual stopping for stop
+- * signals. The process stop is done as a signal action for SIG_DFL.
++ * signals. The process stop is done as a signal action for SIG_DFL.
++ *
++ * Returns true if the signal should be actually delivered, otherwise
++ * it should be dropped.
+ */
+-static void handle_stop_signal(int sig, struct task_struct *p)
++static int prepare_signal(int sig, struct task_struct *p)
+ {
++ struct signal_struct *signal = p->signal;
+ struct task_struct *t;
+
+- if (p->signal->flags & SIGNAL_GROUP_EXIT)
++ if (unlikely(signal->flags & SIGNAL_GROUP_EXIT)) {
+ /*
+- * The process is in the middle of dying already.
++ * The process is in the middle of dying, nothing to do.
+ */
+- return;
+-
+- if (sig_kernel_stop(sig)) {
++ } else if (sig_kernel_stop(sig)) {
+ /*
+ * This is a stop signal. Remove SIGCONT from all queues.
+ */
+- rm_from_queue(sigmask(SIGCONT), &p->signal->shared_pending);
++ rm_from_queue(sigmask(SIGCONT), &signal->shared_pending);
+ t = p;
+ do {
+ rm_from_queue(sigmask(SIGCONT), &t->pending);
+- t = next_thread(t);
+- } while (t != p);
++ } while_each_thread(p, t);
+ } else if (sig == SIGCONT) {
++ unsigned int why;
+ /*
+ * Remove all stop signals from all queues,
+ * and wake all threads.
+ */
+- if (unlikely(p->signal->group_stop_count > 0)) {
+- /*
+- * There was a group stop in progress. We'll
+- * pretend it finished before we got here. We are
+- * obliged to report it to the parent: if the
+- * SIGSTOP happened "after" this SIGCONT, then it
+- * would have cleared this pending SIGCONT. If it
+- * happened "before" this SIGCONT, then the parent
+- * got the SIGCHLD about the stop finishing before
+- * the continue happened. We do the notification
+- * now, and it's as if the stop had finished and
+- * the SIGCHLD was pending on entry to this kill.
+- */
+- p->signal->group_stop_count = 0;
+- p->signal->flags = SIGNAL_STOP_CONTINUED;
+- spin_unlock(&p->sighand->siglock);
+- do_notify_parent_cldstop(p, CLD_STOPPED);
+- spin_lock(&p->sighand->siglock);
+- }
+- rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending);
++ rm_from_queue(SIG_KERNEL_STOP_MASK, &signal->shared_pending);
+ t = p;
+ do {
+ unsigned int state;
+ rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending);
+-
+ /*
+ * If there is a handler for SIGCONT, we must make
+ * sure that no thread returns to user mode before
+@@ -615,7 +617,7 @@ static void handle_stop_signal(int sig, struct task_struct *p)
+ * running the handler. With the TIF_SIGPENDING
+ * flag set, the thread will pause and acquire the
+ * siglock that we hold now and until we've queued
+- * the pending signal.
++ * the pending signal.
+ *
+ * Wake up the stopped thread _after_ setting
+ * TIF_SIGPENDING
+@@ -626,49 +628,163 @@ static void handle_stop_signal(int sig, struct task_struct *p)
+ state |= TASK_INTERRUPTIBLE;
+ }
+ wake_up_state(t, state);
++ } while_each_thread(p, t);
+
+- t = next_thread(t);
+- } while (t != p);
++ /*
++ * Notify the parent with CLD_CONTINUED if we were stopped.
++ *
++ * If we were in the middle of a group stop, we pretend it
++ * was already finished, and then continued. Since SIGCHLD
++ * doesn't queue we report only CLD_STOPPED, as if the next
++ * CLD_CONTINUED was dropped.
++ */
++ why = 0;
++ if (signal->flags & SIGNAL_STOP_STOPPED)
++ why |= SIGNAL_CLD_CONTINUED;
++ else if (signal->group_stop_count)
++ why |= SIGNAL_CLD_STOPPED;
+
+- if (p->signal->flags & SIGNAL_STOP_STOPPED) {
++ if (why) {
+ /*
+- * We were in fact stopped, and are now continued.
+- * Notify the parent with CLD_CONTINUED.
++ * The first thread which returns from finish_stop()
++ * will take ->siglock, notice SIGNAL_CLD_MASK, and
++ * notify its parent. See get_signal_to_deliver().
+ */
+- p->signal->flags = SIGNAL_STOP_CONTINUED;
+- p->signal->group_exit_code = 0;
+- spin_unlock(&p->sighand->siglock);
+- do_notify_parent_cldstop(p, CLD_CONTINUED);
+- spin_lock(&p->sighand->siglock);
++ signal->flags = why | SIGNAL_STOP_CONTINUED;
++ signal->group_stop_count = 0;
++ signal->group_exit_code = 0;
+ } else {
+ /*
+ * We are not stopped, but there could be a stop
+ * signal in the middle of being processed after
+ * being removed from the queue. Clear that too.
+ */
+- p->signal->flags = 0;
++ signal->flags &= ~SIGNAL_STOP_DEQUEUED;
++ }
++ }
++
++ return !sig_ignored(p, sig);
++}
++
++/*
++ * Test if P wants to take SIG. After we've checked all threads with this,
++ * it's equivalent to finding no threads not blocking SIG. Any threads not
++ * blocking SIG were ruled out because they are not running and already
++ * have pending signals. Such threads will dequeue from the shared queue
++ * as soon as they're available, so putting the signal on the shared queue
++ * will be equivalent to sending it to one such thread.
++ */
++static inline int wants_signal(int sig, struct task_struct *p)
++{
++ if (sigismember(&p->blocked, sig))
++ return 0;
++ if (p->flags & PF_EXITING)
++ return 0;
++ if (sig == SIGKILL)
++ return 1;
++ if (task_is_stopped_or_traced(p))
++ return 0;
++ return task_curr(p) || !signal_pending(p);
++}
++
++static void complete_signal(int sig, struct task_struct *p, int group)
++{
++ struct signal_struct *signal = p->signal;
++ struct task_struct *t;
++
++ /*
++ * Now find a thread we can wake up to take the signal off the queue.
++ *
++ * If the main thread wants the signal, it gets first crack.
++ * Probably the least surprising to the average bear.
++ */
++ if (wants_signal(sig, p))
++ t = p;
++ else if (!group || thread_group_empty(p))
++ /*
++ * There is just one thread and it does not need to be woken.
++ * It will dequeue unblocked signals before it runs again.
++ */
++ return;
++ else {
++ /*
++ * Otherwise try to find a suitable thread.
++ */
++ t = signal->curr_target;
++ while (!wants_signal(sig, t)) {
++ t = next_thread(t);
++ if (t == signal->curr_target)
++ /*
++ * No thread needs to be woken.
++ * Any eligible threads will see
++ * the signal in the queue soon.
++ */
++ return;
+ }
+- } else if (sig == SIGKILL) {
++ signal->curr_target = t;
++ }
++
++ /*
++ * Found a killable thread. If the signal will be fatal,
++ * then start taking the whole group down immediately.
++ */
++ if (sig_fatal(p, sig) &&
++ !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) &&
++ !sigismember(&t->real_blocked, sig) &&
++ (sig == SIGKILL || !(t->ptrace & PT_PTRACED))) {
+ /*
+- * Make sure that any pending stop signal already dequeued
+- * is undone by the wakeup for SIGKILL.
++ * This signal will be fatal to the whole group.
+ */
+- p->signal->flags = 0;
++ if (!sig_kernel_coredump(sig)) {
++ /*
++ * Start a group exit and wake everybody up.
++ * This way we don't have other threads
++ * running and doing things after a slower
++ * thread has the fatal signal pending.
++ */
++ signal->flags = SIGNAL_GROUP_EXIT;
++ signal->group_exit_code = sig;
++ signal->group_stop_count = 0;
++ t = p;
++ do {
++ sigaddset(&t->pending.signal, SIGKILL);
++ signal_wake_up(t, 1);
++ } while_each_thread(p, t);
++ return;
++ }
+ }
++
++ /*
++ * The signal is already in the shared-pending queue.
++ * Tell the chosen thread to wake up and dequeue it.
++ */
++ signal_wake_up(t, sig == SIGKILL);
++ return;
++}
++
++static inline int legacy_queue(struct sigpending *signals, int sig)
++{
++ return (sig < SIGRTMIN) && sigismember(&signals->signal, sig);
+ }
+
+ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
+- struct sigpending *signals)
++ int group)
+ {
+- struct sigqueue * q = NULL;
+- int ret = 0;
++ struct sigpending *pending;
++ struct sigqueue *q;
++
++ assert_spin_locked(&t->sighand->siglock);
++ if (!prepare_signal(sig, t))
++ return 0;
+
++ pending = group ? &t->signal->shared_pending : &t->pending;
+ /*
+- * Deliver the signal to listening signalfds. This must be called
+- * with the sighand lock held.
++ * Short-circuit ignored signals and support queuing
++ * exactly one non-rt signal, so that we can get more
++ * detailed information about the cause of the signal.
+ */
+- signalfd_notify(t, sig);
+-
++ if (legacy_queue(pending, sig))
++ return 0;
+ /*
+ * fast-pathed signals for kernel-internal things like SIGSTOP
+ * or SIGKILL.
+@@ -688,7 +804,7 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
+ (is_si_special(info) ||
+ info->si_code >= 0)));
+ if (q) {
+- list_add_tail(&q->list, &signals->list);
++ list_add_tail(&q->list, &pending->list);
+ switch ((unsigned long) info) {
+ case (unsigned long) SEND_SIG_NOINFO:
+ q->info.si_signo = sig;
+@@ -718,13 +834,12 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
+ }
+
+ out_set:
+- sigaddset(&signals->signal, sig);
+- return ret;
++ signalfd_notify(t, sig);
++ sigaddset(&pending->signal, sig);
++ complete_signal(sig, t, group);
++ return 0;
+ }
+
+-#define LEGACY_QUEUE(sigptr, sig) \
+- (((sig) < SIGRTMIN) && sigismember(&(sigptr)->signal, (sig)))
+-
+ int print_fatal_signals;
+
+ static void print_fatal_signal(struct pt_regs *regs, int signr)
+@@ -757,29 +872,16 @@ static int __init setup_print_fatal_signals(char *str)
+
+ __setup("print-fatal-signals=", setup_print_fatal_signals);
+
++int
++__group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
++{
++ return send_signal(sig, info, p, 1);
++}
++
+ static int
+ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
+ {
+- int ret = 0;
+-
+- BUG_ON(!irqs_disabled());
+- assert_spin_locked(&t->sighand->siglock);
+-
+- /* Short-circuit ignored signals. */
+- if (sig_ignored(t, sig))
+- goto out;
+-
+- /* Support queueing exactly one non-rt signal, so that we
+- can get more detailed information about the cause of
+- the signal. */
+- if (LEGACY_QUEUE(&t->pending, sig))
+- goto out;
+-
+- ret = send_signal(sig, info, t, &t->pending);
+- if (!ret && !sigismember(&t->blocked, sig))
+- signal_wake_up(t, sig == SIGKILL);
+-out:
+- return ret;
++ return send_signal(sig, info, t, 0);
+ }
+
+ /*
+@@ -790,7 +892,8 @@ out:
+ * since we do not want to have a signal handler that was blocked
+ * be invoked when user space had explicitly blocked it.
+ *
+- * We don't want to have recursive SIGSEGV's etc, for example.
++ * We don't want to have recursive SIGSEGV's etc, for example,
++ * that is why we also clear SIGNAL_UNKILLABLE.
+ */
+ int
+ force_sig_info(int sig, struct siginfo *info, struct task_struct *t)
+@@ -810,6 +913,8 @@ force_sig_info(int sig, struct siginfo *info, struct task_struct *t)
+ recalc_sigpending_and_wake(t);
+ }
+ }
++ if (action->sa.sa_handler == SIG_DFL)
++ t->signal->flags &= ~SIGNAL_UNKILLABLE;
+ ret = specific_send_sig_info(sig, info, t);
+ spin_unlock_irqrestore(&t->sighand->siglock, flags);
+
+@@ -823,134 +928,6 @@ force_sig_specific(int sig, struct task_struct *t)
+ }
+
+ /*
+- * Test if P wants to take SIG. After we've checked all threads with this,
+- * it's equivalent to finding no threads not blocking SIG. Any threads not
+- * blocking SIG were ruled out because they are not running and already
+- * have pending signals. Such threads will dequeue from the shared queue
+- * as soon as they're available, so putting the signal on the shared queue
+- * will be equivalent to sending it to one such thread.
+- */
+-static inline int wants_signal(int sig, struct task_struct *p)
+-{
+- if (sigismember(&p->blocked, sig))
+- return 0;
+- if (p->flags & PF_EXITING)
+- return 0;
+- if (sig == SIGKILL)
+- return 1;
+- if (task_is_stopped_or_traced(p))
+- return 0;
+- return task_curr(p) || !signal_pending(p);
+-}
+-
+-static void
+-__group_complete_signal(int sig, struct task_struct *p)
+-{
+- struct task_struct *t;
+-
+- /*
+- * Now find a thread we can wake up to take the signal off the queue.
+- *
+- * If the main thread wants the signal, it gets first crack.
+- * Probably the least surprising to the average bear.
+- */
+- if (wants_signal(sig, p))
+- t = p;
+- else if (thread_group_empty(p))
+- /*
+- * There is just one thread and it does not need to be woken.
+- * It will dequeue unblocked signals before it runs again.
+- */
+- return;
+- else {
+- /*
+- * Otherwise try to find a suitable thread.
+- */
+- t = p->signal->curr_target;
+- if (t == NULL)
+- /* restart balancing at this thread */
+- t = p->signal->curr_target = p;
+-
+- while (!wants_signal(sig, t)) {
+- t = next_thread(t);
+- if (t == p->signal->curr_target)
+- /*
+- * No thread needs to be woken.
+- * Any eligible threads will see
+- * the signal in the queue soon.
+- */
+- return;
+- }
+- p->signal->curr_target = t;
+- }
+-
+- /*
+- * Found a killable thread. If the signal will be fatal,
+- * then start taking the whole group down immediately.
+- */
+- if (sig_fatal(p, sig) && !(p->signal->flags & SIGNAL_GROUP_EXIT) &&
+- !sigismember(&t->real_blocked, sig) &&
+- (sig == SIGKILL || !(t->ptrace & PT_PTRACED))) {
+- /*
+- * This signal will be fatal to the whole group.
+- */
+- if (!sig_kernel_coredump(sig)) {
+- /*
+- * Start a group exit and wake everybody up.
+- * This way we don't have other threads
+- * running and doing things after a slower
+- * thread has the fatal signal pending.
+- */
+- p->signal->flags = SIGNAL_GROUP_EXIT;
+- p->signal->group_exit_code = sig;
+- p->signal->group_stop_count = 0;
+- t = p;
+- do {
+- sigaddset(&t->pending.signal, SIGKILL);
+- signal_wake_up(t, 1);
+- } while_each_thread(p, t);
+- return;
+- }
+- }
+-
+- /*
+- * The signal is already in the shared-pending queue.
+- * Tell the chosen thread to wake up and dequeue it.
+- */
+- signal_wake_up(t, sig == SIGKILL);
+- return;
+-}
+-
+-int
+-__group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
+-{
+- int ret = 0;
+-
+- assert_spin_locked(&p->sighand->siglock);
+- handle_stop_signal(sig, p);
+-
+- /* Short-circuit ignored signals. */
+- if (sig_ignored(p, sig))
+- return ret;
+-
+- if (LEGACY_QUEUE(&p->signal->shared_pending, sig))
+- /* This is a non-RT signal and we already have one queued. */
+- return ret;
+-
+- /*
+- * Put this signal on the shared-pending queue, or fail with EAGAIN.
+- * We always use the shared queue for process-wide signals,
+- * to avoid several races.
+- */
+- ret = send_signal(sig, info, p, &p->signal->shared_pending);
+- if (unlikely(ret))
+- return ret;
+-
+- __group_complete_signal(sig, p);
+- return 0;
+-}
+-
+-/*
+ * Nuke all other threads in the group.
+ */
+ void zap_other_threads(struct task_struct *p)
+@@ -978,13 +955,11 @@ int __fatal_signal_pending(struct task_struct *tsk)
+ }
+ EXPORT_SYMBOL(__fatal_signal_pending);
+
+-/*
+- * Must be called under rcu_read_lock() or with tasklist_lock read-held.
+- */
+ struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long *flags)
+ {
+ struct sighand_struct *sighand;
+
++ rcu_read_lock();
+ for (;;) {
+ sighand = rcu_dereference(tsk->sighand);
+ if (unlikely(sighand == NULL))
+@@ -995,6 +970,7 @@ struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long
+ break;
+ spin_unlock_irqrestore(&sighand->siglock, *flags);
+ }
++ rcu_read_unlock();
+
+ return sighand;
+ }
+@@ -1043,9 +1019,6 @@ int kill_pid_info(int sig, struct siginfo *info, struct pid *pid)
+ struct task_struct *p;
+
+ rcu_read_lock();
+- if (unlikely(sig_needs_tasklist(sig)))
+- read_lock(&tasklist_lock);
+-
+ retry:
+ p = pid_task(pid, PIDTYPE_PID);
+ if (p) {
+@@ -1059,10 +1032,8 @@ retry:
+ */
+ goto retry;
+ }
+-
+- if (unlikely(sig_needs_tasklist(sig)))
+- read_unlock(&tasklist_lock);
+ rcu_read_unlock();
++
+ return error;
+ }
+
+@@ -1159,8 +1130,7 @@ static int kill_something_info(int sig, struct siginfo *info, int pid)
+ */
+
+ /*
+- * These two are the most common entry points. They send a signal
+- * just to the specific thread.
++ * The caller must ensure the task can't exit.
+ */
+ int
+ send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
+@@ -1175,17 +1145,9 @@ send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
+ if (!valid_signal(sig))
+ return -EINVAL;
+
+- /*
+- * We need the tasklist lock even for the specific
+- * thread case (when we don't need to follow the group
+- * lists) in order to avoid races with "p->sighand"
+- * going away or changing from under us.
+- */
+- read_lock(&tasklist_lock);
+ spin_lock_irqsave(&p->sighand->siglock, flags);
+ ret = specific_send_sig_info(sig, info, p);
+ spin_unlock_irqrestore(&p->sighand->siglock, flags);
+- read_unlock(&tasklist_lock);
+ return ret;
+ }
+
+@@ -1291,28 +1253,24 @@ void sigqueue_free(struct sigqueue *q)
+ __sigqueue_free(q);
+ }
+
+-int send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
++int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group)
+ {
++ int sig = q->info.si_signo;
++ struct sigpending *pending;
+ unsigned long flags;
+- int ret = 0;
++ int ret;
+
+ BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
+
+- /*
+- * The rcu based delayed sighand destroy makes it possible to
+- * run this without tasklist lock held. The task struct itself
+- * cannot go away as create_timer did get_task_struct().
+- *
+- * We return -1, when the task is marked exiting, so
+- * posix_timer_event can redirect it to the group leader
+- */
+- rcu_read_lock();
++ ret = -1;
++ if (!likely(lock_task_sighand(t, &flags)))
++ goto ret;
+
+- if (!likely(lock_task_sighand(p, &flags))) {
+- ret = -1;
+- goto out_err;
+- }
++ ret = 1; /* the signal is ignored */
++ if (!prepare_signal(sig, t))
++ goto out;
+
++ ret = 0;
+ if (unlikely(!list_empty(&q->list))) {
+ /*
+ * If an SI_TIMER entry is already queue just increment
+@@ -1322,77 +1280,15 @@ int send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
+ q->info.si_overrun++;
+ goto out;
+ }
+- /* Short-circuit ignored signals. */
+- if (sig_ignored(p, sig)) {
+- ret = 1;
+- goto out;
+- }
+- /*
+- * Deliver the signal to listening signalfds. This must be called
+- * with the sighand lock held.
+- */
+- signalfd_notify(p, sig);
+-
+- list_add_tail(&q->list, &p->pending.list);
+- sigaddset(&p->pending.signal, sig);
+- if (!sigismember(&p->blocked, sig))
+- signal_wake_up(p, sig == SIGKILL);
+-
+-out:
+- unlock_task_sighand(p, &flags);
+-out_err:
+- rcu_read_unlock();
+-
+- return ret;
+-}
+-
+-int
+-send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
+-{
+- unsigned long flags;
+- int ret = 0;
+-
+- BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
+-
+- read_lock(&tasklist_lock);
+- /* Since it_lock is held, p->sighand cannot be NULL. */
+- spin_lock_irqsave(&p->sighand->siglock, flags);
+- handle_stop_signal(sig, p);
+-
+- /* Short-circuit ignored signals. */
+- if (sig_ignored(p, sig)) {
+- ret = 1;
+- goto out;
+- }
+-
+- if (unlikely(!list_empty(&q->list))) {
+- /*
+- * If an SI_TIMER entry is already queue just increment
+- * the overrun count. Other uses should not try to
+- * send the signal multiple times.
+- */
+- BUG_ON(q->info.si_code != SI_TIMER);
+- q->info.si_overrun++;
+- goto out;
+- }
+- /*
+- * Deliver the signal to listening signalfds. This must be called
+- * with the sighand lock held.
+- */
+- signalfd_notify(p, sig);
+
+- /*
+- * Put this signal on the shared-pending queue.
+- * We always use the shared queue for process-wide signals,
+- * to avoid several races.
+- */
+- list_add_tail(&q->list, &p->signal->shared_pending.list);
+- sigaddset(&p->signal->shared_pending.signal, sig);
+-
+- __group_complete_signal(sig, p);
++ signalfd_notify(t, sig);
++ pending = group ? &t->signal->shared_pending : &t->pending;
++ list_add_tail(&q->list, &pending->list);
++ sigaddset(&pending->signal, sig);
++ complete_signal(sig, t, group);
+ out:
+- spin_unlock_irqrestore(&p->sighand->siglock, flags);
+- read_unlock(&tasklist_lock);
++ unlock_task_sighand(t, &flags);
++ret:
+ return ret;
+ }
+
+@@ -1723,8 +1619,9 @@ static int do_signal_stop(int signr)
+ } else {
+ struct task_struct *t;
+
+- if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) ||
+- unlikely(sig->group_exit_task))
++ if (unlikely((sig->flags & (SIGNAL_STOP_DEQUEUED | SIGNAL_UNKILLABLE))
++ != SIGNAL_STOP_DEQUEUED) ||
++ unlikely(signal_group_exit(sig)))
+ return 0;
+ /*
+ * There is no group stop already in progress.
+@@ -1757,11 +1654,51 @@ static int do_signal_stop(int signr)
return 1;
}
@@ -838917,7 +1127357,48 @@
int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
struct pt_regs *regs, void *cookie)
{
-@@ -1785,36 +1824,10 @@ relock:
+- sigset_t *mask = ¤t->blocked;
+- int signr = 0;
++ struct sighand_struct *sighand = current->sighand;
++ struct signal_struct *signal = current->signal;
++ int signr;
+
+ relock:
+ /*
+@@ -1772,52 +1709,42 @@ relock:
+ */
+ try_to_freeze();
+
+- spin_lock_irq(¤t->sighand->siglock);
++ spin_lock_irq(&sighand->siglock);
++ /*
++ * Every stopped thread goes here after wakeup. Check to see if
++ * we should notify the parent, prepare_signal(SIGCONT) encodes
++ * the CLD_ si_code into SIGNAL_CLD_MASK bits.
++ */
++ if (unlikely(signal->flags & SIGNAL_CLD_MASK)) {
++ int why = (signal->flags & SIGNAL_STOP_CONTINUED)
++ ? CLD_CONTINUED : CLD_STOPPED;
++ signal->flags &= ~SIGNAL_CLD_MASK;
++ spin_unlock_irq(&sighand->siglock);
++
++ read_lock(&tasklist_lock);
++ do_notify_parent_cldstop(current->group_leader, why);
++ read_unlock(&tasklist_lock);
++ goto relock;
++ }
++
+ for (;;) {
+ struct k_sigaction *ka;
+
+- if (unlikely(current->signal->group_stop_count > 0) &&
++ if (unlikely(signal->group_stop_count > 0) &&
+ do_signal_stop(0))
+ goto relock;
+
+- signr = dequeue_signal(current, mask, info);
+-
++ signr = dequeue_signal(current, ¤t->blocked, info);
if (!signr)
break; /* will return 0 */
@@ -838956,7 +1127437,142 @@
- }
}
- ka = ¤t->sighand->action[signr-1];
+- ka = ¤t->sighand->action[signr-1];
++ ka = &sighand->action[signr-1];
+ if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */
+ continue;
+ if (ka->sa.sa_handler != SIG_DFL) {
+@@ -1839,7 +1766,8 @@ relock:
+ /*
+ * Global init gets no signals it doesn't want.
+ */
+- if (is_global_init(current))
++ if (unlikely(signal->flags & SIGNAL_UNKILLABLE) &&
++ !signal_group_exit(signal))
+ continue;
+
+ if (sig_kernel_stop(signr)) {
+@@ -1854,14 +1782,14 @@ relock:
+ * We need to check for that and bail out if necessary.
+ */
+ if (signr != SIGSTOP) {
+- spin_unlock_irq(¤t->sighand->siglock);
++ spin_unlock_irq(&sighand->siglock);
+
+ /* signals can be posted during this window */
+
+ if (is_current_pgrp_orphaned())
+ goto relock;
+
+- spin_lock_irq(¤t->sighand->siglock);
++ spin_lock_irq(&sighand->siglock);
+ }
+
+ if (likely(do_signal_stop(signr))) {
+@@ -1876,15 +1804,16 @@ relock:
+ continue;
+ }
+
+- spin_unlock_irq(¤t->sighand->siglock);
++ spin_unlock_irq(&sighand->siglock);
+
+ /*
+ * Anything else is fatal, maybe with a core dump.
+ */
+ current->flags |= PF_SIGNALED;
+- if ((signr != SIGKILL) && print_fatal_signals)
+- print_fatal_signal(regs, signr);
++
+ if (sig_kernel_coredump(signr)) {
++ if (print_fatal_signals)
++ print_fatal_signal(regs, signr);
+ /*
+ * If it was able to dump core, this kills all
+ * other threads in the group and synchronizes with
+@@ -1902,7 +1831,7 @@ relock:
+ do_group_exit(signr);
+ /* NOTREACHED */
+ }
+- spin_unlock_irq(¤t->sighand->siglock);
++ spin_unlock_irq(&sighand->siglock);
+ return signr;
+ }
+
+@@ -2246,6 +2175,7 @@ static int do_tkill(int tgid, int pid, int sig)
+ int error;
+ struct siginfo info;
+ struct task_struct *p;
++ unsigned long flags;
+
+ error = -ESRCH;
+ info.si_signo = sig;
+@@ -2254,22 +2184,24 @@ static int do_tkill(int tgid, int pid, int sig)
+ info.si_pid = task_tgid_vnr(current);
+ info.si_uid = current->uid;
+
+- read_lock(&tasklist_lock);
++ rcu_read_lock();
+ p = find_task_by_vpid(pid);
+ if (p && (tgid <= 0 || task_tgid_vnr(p) == tgid)) {
+ error = check_kill_permission(sig, &info, p);
+ /*
+ * The null signal is a permissions and process existence
+ * probe. No signal is actually delivered.
++ *
++ * If lock_task_sighand() fails we pretend the task dies
++ * after receiving the signal. The window is tiny, and the
++ * signal is private anyway.
+ */
+- if (!error && sig && p->sighand) {
+- spin_lock_irq(&p->sighand->siglock);
+- handle_stop_signal(sig, p);
++ if (!error && sig && lock_task_sighand(p, &flags)) {
+ error = specific_send_sig_info(sig, &info, p);
+- spin_unlock_irq(&p->sighand->siglock);
++ unlock_task_sighand(p, &flags);
+ }
+ }
+- read_unlock(&tasklist_lock);
++ rcu_read_unlock();
+
+ return error;
+ }
+@@ -2326,13 +2258,14 @@ sys_rt_sigqueueinfo(int pid, int sig, siginfo_t __user *uinfo)
+
+ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
+ {
++ struct task_struct *t = current;
+ struct k_sigaction *k;
+ sigset_t mask;
+
+ if (!valid_signal(sig) || sig < 1 || (act && sig_kernel_only(sig)))
+ return -EINVAL;
+
+- k = ¤t->sighand->action[sig-1];
++ k = &t->sighand->action[sig-1];
+
+ spin_lock_irq(¤t->sighand->siglock);
+ if (oact)
+@@ -2353,9 +2286,7 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
+ * (for example, SIGCHLD), shall cause the pending signal to
+ * be discarded, whether or not it is blocked"
+ */
+- if (act->sa.sa_handler == SIG_IGN ||
+- (act->sa.sa_handler == SIG_DFL && sig_kernel_ignore(sig))) {
+- struct task_struct *t = current;
++ if (__sig_ignored(t, sig)) {
+ sigemptyset(&mask);
+ sigaddset(&mask, sig);
+ rm_from_queue_full(&mask, &t->signal->shared_pending);
+@@ -2610,7 +2541,7 @@ asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
+
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+- set_thread_flag(TIF_RESTORE_SIGMASK);
++ set_restore_sigmask();
+ return -ERESTARTNOHAND;
+ }
+ #endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 31e9f2a..3c44956 100644
--- a/kernel/softirq.c
@@ -839134,7 +1127750,7 @@
void *data;
struct completion done;
diff --git a/kernel/sys.c b/kernel/sys.c
-index a626116..6a0cc71 100644
+index a626116..895d2d4 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -67,6 +67,12 @@
@@ -839150,10 +1127766,235 @@
/*
* 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;
+@@ -972,8 +978,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
+ goto out;
+
+ if (task_pgrp(p) != pgrp) {
+- detach_pid(p, PIDTYPE_PGID);
+- attach_pid(p, PIDTYPE_PGID, pgrp);
++ change_pid(p, PIDTYPE_PGID, pgrp);
+ set_task_pgrp(p, pid_nr(pgrp));
+ }
+
+@@ -986,54 +991,67 @@ out:
+
+ asmlinkage long sys_getpgid(pid_t pid)
+ {
++ struct task_struct *p;
++ struct pid *grp;
++ int retval;
++
++ rcu_read_lock();
+ if (!pid)
+- return task_pgrp_vnr(current);
++ grp = task_pgrp(current);
+ else {
+- int retval;
+- struct task_struct *p;
+-
+- read_lock(&tasklist_lock);
+- p = find_task_by_vpid(pid);
+ retval = -ESRCH;
+- if (p) {
+- retval = security_task_getpgid(p);
+- if (!retval)
+- retval = task_pgrp_vnr(p);
+- }
+- read_unlock(&tasklist_lock);
+- return retval;
++ p = find_task_by_vpid(pid);
++ if (!p)
++ goto out;
++ grp = task_pgrp(p);
++ if (!grp)
++ goto out;
++
++ retval = security_task_getpgid(p);
++ if (retval)
++ goto out;
+ }
++ retval = pid_vnr(grp);
++out:
++ rcu_read_unlock();
++ return retval;
+ }
+
+ #ifdef __ARCH_WANT_SYS_GETPGRP
+
+ asmlinkage long sys_getpgrp(void)
+ {
+- /* SMP - assuming writes are word atomic this is fine */
+- return task_pgrp_vnr(current);
++ return sys_getpgid(0);
+ }
+
#endif
+
+ asmlinkage long sys_getsid(pid_t pid)
+ {
++ struct task_struct *p;
++ struct pid *sid;
++ int retval;
++
++ rcu_read_lock();
+ if (!pid)
+- return task_session_vnr(current);
++ sid = task_session(current);
+ else {
+- int retval;
+- struct task_struct *p;
+-
+- rcu_read_lock();
+- p = find_task_by_vpid(pid);
+ retval = -ESRCH;
+- if (p) {
+- retval = security_task_getsid(p);
+- if (!retval)
+- retval = task_session_vnr(p);
+- }
+- rcu_read_unlock();
+- return retval;
++ p = find_task_by_vpid(pid);
++ if (!p)
++ goto out;
++ sid = task_session(p);
++ if (!sid)
++ goto out;
++
++ retval = security_task_getsid(p);
++ if (retval)
++ goto out;
+ }
++ retval = pid_vnr(sid);
++out:
++ rcu_read_unlock();
++ return retval;
+ }
+
+ asmlinkage long sys_setsid(void)
+@@ -1539,6 +1557,19 @@ out:
+ *
+ */
+
++static void accumulate_thread_rusage(struct task_struct *t, struct rusage *r,
++ cputime_t *utimep, cputime_t *stimep)
++{
++ *utimep = cputime_add(*utimep, t->utime);
++ *stimep = cputime_add(*stimep, t->stime);
++ r->ru_nvcsw += t->nvcsw;
++ r->ru_nivcsw += t->nivcsw;
++ r->ru_minflt += t->min_flt;
++ r->ru_majflt += t->maj_flt;
++ r->ru_inblock += task_io_get_inblock(t);
++ r->ru_oublock += task_io_get_oublock(t);
++}
++
+ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
+ {
+ struct task_struct *t;
+@@ -1548,12 +1579,14 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
+ memset((char *) r, 0, sizeof *r);
+ utime = stime = cputime_zero;
+
+- rcu_read_lock();
+- if (!lock_task_sighand(p, &flags)) {
+- rcu_read_unlock();
+- return;
++ if (who == RUSAGE_THREAD) {
++ accumulate_thread_rusage(p, r, &utime, &stime);
++ goto out;
+ }
+
++ if (!lock_task_sighand(p, &flags))
++ return;
++
+ switch (who) {
+ case RUSAGE_BOTH:
+ case RUSAGE_CHILDREN:
+@@ -1580,14 +1613,7 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
+ r->ru_oublock += p->signal->oublock;
+ t = p;
+ do {
+- utime = cputime_add(utime, t->utime);
+- stime = cputime_add(stime, t->stime);
+- r->ru_nvcsw += t->nvcsw;
+- r->ru_nivcsw += t->nivcsw;
+- r->ru_minflt += t->min_flt;
+- r->ru_majflt += t->maj_flt;
+- r->ru_inblock += task_io_get_inblock(t);
+- r->ru_oublock += task_io_get_oublock(t);
++ accumulate_thread_rusage(t, r, &utime, &stime);
+ t = next_thread(t);
+ } while (t != p);
+ break;
+@@ -1595,10 +1621,9 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
+ default:
+ BUG();
+ }
+-
+ unlock_task_sighand(p, &flags);
+- rcu_read_unlock();
+
++out:
+ cputime_to_timeval(utime, &r->ru_utime);
+ cputime_to_timeval(stime, &r->ru_stime);
+ }
+@@ -1612,7 +1637,8 @@ int getrusage(struct task_struct *p, int who, struct rusage __user *ru)
+
+ asmlinkage long sys_getrusage(int who, struct rusage __user *ru)
+ {
+- if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
++ if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN &&
++ who != RUSAGE_THREAD)
+ return -EINVAL;
+ return getrusage(current, who, ru);
+ }
+@@ -1626,10 +1652,9 @@ asmlinkage long sys_umask(int mask)
+ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
+ unsigned long arg4, unsigned long arg5)
+ {
+- long error;
++ long uninitialized_var(error);
+
+- error = security_task_prctl(option, arg2, arg3, arg4, arg5);
+- if (error)
++ if (security_task_prctl(option, arg2, arg3, arg4, arg5, &error))
+ return error;
+
+ switch (option) {
+@@ -1682,17 +1707,6 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
+ error = -EINVAL;
+ break;
+
+- case PR_GET_KEEPCAPS:
+- if (current->keep_capabilities)
+- error = 1;
+- break;
+- case PR_SET_KEEPCAPS:
+- if (arg2 != 0 && arg2 != 1) {
+- error = -EINVAL;
+- break;
+- }
+- current->keep_capabilities = arg2;
+- break;
+ case PR_SET_NAME: {
+ struct task_struct *me = current;
+ unsigned char ncomm[sizeof(me->comm)];
+@@ -1726,18 +1740,12 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
+ case PR_SET_SECCOMP:
+ error = prctl_set_seccomp(arg2);
+ break;
+-
+- case PR_CAPBSET_READ:
+- if (!cap_valid(arg2))
+- return -EINVAL;
+- return !!cap_raised(current->cap_bset, arg2);
+- case PR_CAPBSET_DROP:
+-#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
+- return cap_prctl_drop(arg2);
+-#else
+- return -EINVAL;
+-#endif
-
+ case PR_GET_TSC:
+ error = GET_TSC_CTL(arg2);
@@ -839165,10 +1128006,31 @@
error = -EINVAL;
break;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index b2a2d68..fd33648 100644
+index b2a2d68..d7ffdc5 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
-@@ -270,17 +270,6 @@ static struct ctl_table kern_table[] = {
+@@ -38,6 +38,7 @@
+ #include <linux/writeback.h>
+ #include <linux/hugetlb.h>
+ #include <linux/initrd.h>
++#include <linux/key.h>
+ #include <linux/times.h>
+ #include <linux/limits.h>
+ #include <linux/dcache.h>
+@@ -144,12 +145,6 @@ extern int no_unaligned_warning;
+ extern int max_lock_depth;
+ #endif
+
+-#ifdef CONFIG_SYSCTL_SYSCALL
+-static int parse_table(int __user *, int, void __user *, size_t __user *,
+- void __user *, size_t, struct ctl_table *);
+-#endif
+-
+-
+ #ifdef CONFIG_PROC_SYSCTL
+ static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos);
+@@ -270,17 +265,6 @@ static struct ctl_table kern_table[] = {
},
{
.ctl_name = CTL_UNNUMBERED,
@@ -839186,7 +1128048,7 @@
.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[] = {
+@@ -318,7 +302,7 @@ static struct ctl_table kern_table[] = {
.data = &sysctl_sched_rt_period,
.maxlen = sizeof(unsigned int),
.mode = 0644,
@@ -839195,7 +1128057,7 @@
},
{
.ctl_name = CTL_UNNUMBERED,
-@@ -326,7 +315,7 @@ static struct ctl_table kern_table[] = {
+@@ -326,7 +310,7 @@ static struct ctl_table kern_table[] = {
.data = &sysctl_sched_rt_runtime,
.maxlen = sizeof(int),
.mode = 0644,
@@ -839204,11 +1128066,274 @@
},
{
.ctl_name = CTL_UNNUMBERED,
+@@ -820,6 +804,14 @@ static struct ctl_table kern_table[] = {
+ .proc_handler = &proc_dostring,
+ .strategy = &sysctl_string,
+ },
++#ifdef CONFIG_KEYS
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "keys",
++ .mode = 0555,
++ .child = key_sysctls,
++ },
++#endif
+ /*
+ * NOTE: do not add new entries to this table unless you have read
+ * Documentation/sysctl/ctl_unnumbered.txt
+@@ -1441,6 +1433,76 @@ void register_sysctl_root(struct ctl_table_root *root)
+ }
+
+ #ifdef CONFIG_SYSCTL_SYSCALL
++/* Perform the actual read/write of a sysctl table entry. */
++static int do_sysctl_strategy(struct ctl_table_root *root,
++ struct ctl_table *table,
++ int __user *name, int nlen,
++ void __user *oldval, size_t __user *oldlenp,
++ void __user *newval, size_t newlen)
++{
++ int op = 0, rc;
++
++ if (oldval)
++ op |= 004;
++ if (newval)
++ op |= 002;
++ if (sysctl_perm(root, table, op))
++ return -EPERM;
++
++ if (table->strategy) {
++ rc = table->strategy(table, name, nlen, oldval, oldlenp,
++ newval, newlen);
++ if (rc < 0)
++ return rc;
++ if (rc > 0)
++ return 0;
++ }
++
++ /* If there is no strategy routine, or if the strategy returns
++ * zero, proceed with automatic r/w */
++ if (table->data && table->maxlen) {
++ rc = sysctl_data(table, name, nlen, oldval, oldlenp,
++ newval, newlen);
++ if (rc < 0)
++ return rc;
++ }
++ return 0;
++}
++
++static int parse_table(int __user *name, int nlen,
++ void __user *oldval, size_t __user *oldlenp,
++ void __user *newval, size_t newlen,
++ struct ctl_table_root *root,
++ struct ctl_table *table)
++{
++ int n;
++repeat:
++ if (!nlen)
++ return -ENOTDIR;
++ if (get_user(n, name))
++ return -EFAULT;
++ for ( ; table->ctl_name || table->procname; table++) {
++ if (!table->ctl_name)
++ continue;
++ if (n == table->ctl_name) {
++ int error;
++ if (table->child) {
++ if (sysctl_perm(root, table, 001))
++ return -EPERM;
++ name++;
++ nlen--;
++ table = table->child;
++ goto repeat;
++ }
++ error = do_sysctl_strategy(root, table, name, nlen,
++ oldval, oldlenp,
++ newval, newlen);
++ return error;
++ }
++ }
++ return -ENOTDIR;
++}
++
+ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen)
+ {
+@@ -1458,7 +1520,8 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol
+ for (head = sysctl_head_next(NULL); head;
+ head = sysctl_head_next(head)) {
+ error = parse_table(name, nlen, oldval, oldlenp,
+- newval, newlen, head->ctl_table);
++ newval, newlen,
++ head->root, head->ctl_table);
+ if (error != -ENOTDIR) {
+ sysctl_head_finish(head);
+ break;
+@@ -1504,84 +1567,22 @@ static int test_perm(int mode, int op)
+ return -EACCES;
+ }
+
+-int sysctl_perm(struct ctl_table *table, int op)
++int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
+ {
+ int error;
++ int mode;
++
+ error = security_sysctl(table, op);
+ if (error)
+ return error;
+- return test_perm(table->mode, op);
+-}
+
+-#ifdef CONFIG_SYSCTL_SYSCALL
+-static int parse_table(int __user *name, int nlen,
+- void __user *oldval, size_t __user *oldlenp,
+- void __user *newval, size_t newlen,
+- struct ctl_table *table)
+-{
+- int n;
+-repeat:
+- if (!nlen)
+- return -ENOTDIR;
+- if (get_user(n, name))
+- return -EFAULT;
+- for ( ; table->ctl_name || table->procname; table++) {
+- if (!table->ctl_name)
+- continue;
+- if (n == table->ctl_name) {
+- int error;
+- if (table->child) {
+- if (sysctl_perm(table, 001))
+- return -EPERM;
+- name++;
+- nlen--;
+- table = table->child;
+- goto repeat;
+- }
+- error = do_sysctl_strategy(table, name, nlen,
+- oldval, oldlenp,
+- newval, newlen);
+- return error;
+- }
+- }
+- return -ENOTDIR;
+-}
+-
+-/* Perform the actual read/write of a sysctl table entry. */
+-int do_sysctl_strategy (struct ctl_table *table,
+- int __user *name, int nlen,
+- void __user *oldval, size_t __user *oldlenp,
+- void __user *newval, size_t newlen)
+-{
+- int op = 0, rc;
++ if (root->permissions)
++ mode = root->permissions(root, current->nsproxy, table);
++ else
++ mode = table->mode;
+
+- if (oldval)
+- op |= 004;
+- if (newval)
+- op |= 002;
+- if (sysctl_perm(table, op))
+- return -EPERM;
+-
+- if (table->strategy) {
+- rc = table->strategy(table, name, nlen, oldval, oldlenp,
+- newval, newlen);
+- if (rc < 0)
+- return rc;
+- if (rc > 0)
+- return 0;
+- }
+-
+- /* If there is no strategy routine, or if the strategy returns
+- * zero, proceed with automatic r/w */
+- if (table->data && table->maxlen) {
+- rc = sysctl_data(table, name, nlen, oldval, oldlenp,
+- newval, newlen);
+- if (rc < 0)
+- return rc;
+- }
+- return 0;
++ return test_perm(mode, op);
+ }
+-#endif /* CONFIG_SYSCTL_SYSCALL */
+
+ static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table)
+ {
+@@ -1594,9 +1595,13 @@ static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table)
+
+ static __init int sysctl_init(void)
+ {
+- int err;
+ sysctl_set_parent(NULL, root_table);
+- err = sysctl_check_table(current->nsproxy, root_table);
++#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
++ {
++ int err;
++ err = sysctl_check_table(current->nsproxy, root_table);
++ }
++#endif
+ return 0;
+ }
+
+@@ -1723,10 +1728,12 @@ struct ctl_table_header *__register_sysctl_paths(
+ header->unregistering = NULL;
+ header->root = root;
+ sysctl_set_parent(NULL, header->ctl_table);
++#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
+ if (sysctl_check_table(namespaces, header->ctl_table)) {
+ kfree(header);
+ return NULL;
+ }
++#endif
+ spin_lock(&sysctl_lock);
+ header_list = lookup_header_list(root, namespaces);
+ list_add_tail(&header->ctl_entry, header_list);
+diff --git a/kernel/taskstats.c b/kernel/taskstats.c
+index 07e86a8..4a23517 100644
+--- a/kernel/taskstats.c
++++ b/kernel/taskstats.c
+@@ -183,7 +183,7 @@ static int fill_pid(pid_t pid, struct task_struct *tsk,
+
+ if (!tsk) {
+ rcu_read_lock();
+- tsk = find_task_by_pid(pid);
++ tsk = find_task_by_vpid(pid);
+ if (tsk)
+ get_task_struct(tsk);
+ rcu_read_unlock();
+@@ -230,7 +230,7 @@ static int fill_tgid(pid_t tgid, struct task_struct *first,
+ */
+ rcu_read_lock();
+ if (!first)
+- first = find_task_by_pid(tgid);
++ first = find_task_by_vpid(tgid);
+
+ if (!first || !lock_task_sighand(first, &flags))
+ goto out;
+@@ -547,7 +547,7 @@ void taskstats_exit(struct task_struct *tsk, int group_dead)
+ if (!stats)
+ goto err;
+
+- rc = fill_pid(tsk->pid, tsk, stats);
++ rc = fill_pid(-1, tsk, stats);
+ if (rc < 0)
+ goto err;
+
diff --git a/kernel/time.c b/kernel/time.c
-index a5ec013..35d373a 100644
+index a5ec013..8672904 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)
+@@ -35,6 +35,7 @@
+ #include <linux/syscalls.h>
+ #include <linux/security.h>
+ #include <linux/fs.h>
++#include <linux/slab.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/unistd.h>
+@@ -379,6 +380,7 @@ void set_normalized_timespec(struct timespec *ts, time_t sec, long nsec)
ts->tv_sec = sec;
ts->tv_nsec = nsec;
}
@@ -839413,11 +1128538,247 @@
clock->cycle_last = clocksource_read(clock);
clock->error = 0;
timekeeping_suspended = 0;
+diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
+index 67fe8fc..a40e20f 100644
+--- a/kernel/time/timer_list.c
++++ b/kernel/time/timer_list.c
+@@ -278,12 +278,9 @@ static int __init init_timer_list_procfs(void)
+ {
+ struct proc_dir_entry *pe;
+
+- pe = create_proc_entry("timer_list", 0644, NULL);
++ pe = proc_create("timer_list", 0644, NULL, &timer_list_fops);
+ if (!pe)
+ return -ENOMEM;
+-
+- pe->proc_fops = &timer_list_fops;
+-
+ return 0;
+ }
+ __initcall(init_timer_list_procfs);
+diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c
+index 417da8c..c994530 100644
+--- a/kernel/time/timer_stats.c
++++ b/kernel/time/timer_stats.c
+@@ -415,12 +415,9 @@ static int __init init_tstats_procfs(void)
+ {
+ struct proc_dir_entry *pe;
+
+- pe = create_proc_entry("timer_stats", 0644, NULL);
++ pe = proc_create("timer_stats", 0644, NULL, &tstats_fops);
+ if (!pe)
+ return -ENOMEM;
+-
+- pe->proc_fops = &tstats_fops;
+-
+ return 0;
+ }
+ __initcall(init_tstats_procfs);
diff --git a/kernel/timer.c b/kernel/timer.c
-index b024106..f3d35d4 100644
+index b024106..ceacc66 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
-@@ -1228,13 +1228,6 @@ asmlinkage long sys_sysinfo(struct sysinfo __user *info)
+@@ -320,14 +320,130 @@ static void timer_stats_account_timer(struct timer_list *timer)
+ static void timer_stats_account_timer(struct timer_list *timer) {}
+ #endif
+
+-/**
+- * init_timer - initialize a timer.
+- * @timer: the timer to be initialized
+- *
+- * init_timer() must be done to a timer prior calling *any* of the
+- * other timer functions.
++#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
++
++static struct debug_obj_descr timer_debug_descr;
++
++/*
++ * fixup_init is called when:
++ * - an active object is initialized
+ */
+-void init_timer(struct timer_list *timer)
++static int timer_fixup_init(void *addr, enum debug_obj_state state)
++{
++ struct timer_list *timer = addr;
++
++ switch (state) {
++ case ODEBUG_STATE_ACTIVE:
++ del_timer_sync(timer);
++ debug_object_init(timer, &timer_debug_descr);
++ return 1;
++ default:
++ return 0;
++ }
++}
++
++/*
++ * fixup_activate is called when:
++ * - an active object is activated
++ * - an unknown object is activated (might be a statically initialized object)
++ */
++static int timer_fixup_activate(void *addr, enum debug_obj_state state)
++{
++ struct timer_list *timer = addr;
++
++ switch (state) {
++
++ case ODEBUG_STATE_NOTAVAILABLE:
++ /*
++ * This is not really a fixup. The timer was
++ * statically initialized. We just make sure that it
++ * is tracked in the object tracker.
++ */
++ if (timer->entry.next == NULL &&
++ timer->entry.prev == TIMER_ENTRY_STATIC) {
++ debug_object_init(timer, &timer_debug_descr);
++ debug_object_activate(timer, &timer_debug_descr);
++ return 0;
++ } else {
++ WARN_ON_ONCE(1);
++ }
++ return 0;
++
++ case ODEBUG_STATE_ACTIVE:
++ WARN_ON(1);
++
++ default:
++ return 0;
++ }
++}
++
++/*
++ * fixup_free is called when:
++ * - an active object is freed
++ */
++static int timer_fixup_free(void *addr, enum debug_obj_state state)
++{
++ struct timer_list *timer = addr;
++
++ switch (state) {
++ case ODEBUG_STATE_ACTIVE:
++ del_timer_sync(timer);
++ debug_object_free(timer, &timer_debug_descr);
++ return 1;
++ default:
++ return 0;
++ }
++}
++
++static struct debug_obj_descr timer_debug_descr = {
++ .name = "timer_list",
++ .fixup_init = timer_fixup_init,
++ .fixup_activate = timer_fixup_activate,
++ .fixup_free = timer_fixup_free,
++};
++
++static inline void debug_timer_init(struct timer_list *timer)
++{
++ debug_object_init(timer, &timer_debug_descr);
++}
++
++static inline void debug_timer_activate(struct timer_list *timer)
++{
++ debug_object_activate(timer, &timer_debug_descr);
++}
++
++static inline void debug_timer_deactivate(struct timer_list *timer)
++{
++ debug_object_deactivate(timer, &timer_debug_descr);
++}
++
++static inline void debug_timer_free(struct timer_list *timer)
++{
++ debug_object_free(timer, &timer_debug_descr);
++}
++
++static void __init_timer(struct timer_list *timer);
++
++void init_timer_on_stack(struct timer_list *timer)
++{
++ debug_object_init_on_stack(timer, &timer_debug_descr);
++ __init_timer(timer);
++}
++EXPORT_SYMBOL_GPL(init_timer_on_stack);
++
++void destroy_timer_on_stack(struct timer_list *timer)
++{
++ debug_object_free(timer, &timer_debug_descr);
++}
++EXPORT_SYMBOL_GPL(destroy_timer_on_stack);
++
++#else
++static inline void debug_timer_init(struct timer_list *timer) { }
++static inline void debug_timer_activate(struct timer_list *timer) { }
++static inline void debug_timer_deactivate(struct timer_list *timer) { }
++#endif
++
++static void __init_timer(struct timer_list *timer)
+ {
+ timer->entry.next = NULL;
+ timer->base = __raw_get_cpu_var(tvec_bases);
+@@ -337,6 +453,19 @@ void init_timer(struct timer_list *timer)
+ memset(timer->start_comm, 0, TASK_COMM_LEN);
+ #endif
+ }
++
++/**
++ * init_timer - initialize a timer.
++ * @timer: the timer to be initialized
++ *
++ * init_timer() must be done to a timer prior calling *any* of the
++ * other timer functions.
++ */
++void init_timer(struct timer_list *timer)
++{
++ debug_timer_init(timer);
++ __init_timer(timer);
++}
+ EXPORT_SYMBOL(init_timer);
+
+ void init_timer_deferrable(struct timer_list *timer)
+@@ -351,6 +480,8 @@ static inline void detach_timer(struct timer_list *timer,
+ {
+ struct list_head *entry = &timer->entry;
+
++ debug_timer_deactivate(timer);
++
+ __list_del(entry->prev, entry->next);
+ if (clear_pending)
+ entry->next = NULL;
+@@ -405,6 +536,8 @@ int __mod_timer(struct timer_list *timer, unsigned long expires)
+ ret = 1;
+ }
+
++ debug_timer_activate(timer);
++
+ new_base = __get_cpu_var(tvec_bases);
+
+ if (base != new_base) {
+@@ -450,6 +583,7 @@ void add_timer_on(struct timer_list *timer, int cpu)
+ BUG_ON(timer_pending(timer) || !timer->function);
+ spin_lock_irqsave(&base->lock, flags);
+ timer_set_base(timer, base);
++ debug_timer_activate(timer);
+ internal_add_timer(base, timer);
+ /*
+ * Check whether the other CPU is idle and needs to be
+@@ -1086,11 +1220,14 @@ signed long __sched schedule_timeout(signed long timeout)
+
+ expire = timeout + jiffies;
+
+- setup_timer(&timer, process_timeout, (unsigned long)current);
++ setup_timer_on_stack(&timer, process_timeout, (unsigned long)current);
+ __mod_timer(&timer, expire);
+ schedule();
+ del_singleshot_timer_sync(&timer);
+
++ /* Remove the timer from the object tracker */
++ destroy_timer_on_stack(&timer);
++
+ timeout = expire - jiffies;
+
+ out:
+@@ -1228,13 +1365,6 @@ asmlinkage long sys_sysinfo(struct sysinfo __user *info)
return 0;
}
@@ -839431,7 +1128792,7 @@
static int __cpuinit init_timers_cpu(int cpu)
{
int j;
-@@ -1277,7 +1270,6 @@ static int __cpuinit init_timers_cpu(int cpu)
+@@ -1277,7 +1407,6 @@ static int __cpuinit init_timers_cpu(int cpu)
}
spin_lock_init(&base->lock);
@@ -839439,7 +1128800,7 @@
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)
+@@ -1316,8 +1445,8 @@ static void __cpuinit migrate_timers(int cpu)
new_base = get_cpu_var(tvec_bases);
local_irq_disable();
@@ -839450,7 +1128811,7 @@
BUG_ON(old_base->running_timer);
-@@ -1330,8 +1322,8 @@ static void __cpuinit migrate_timers(int cpu)
+@@ -1330,8 +1459,8 @@ static void __cpuinit migrate_timers(int cpu)
migrate_timer_list(new_base, old_base->tv5.vec + i);
}
@@ -839462,10 +1128823,21 @@
put_cpu_var(tvec_bases);
}
diff --git a/kernel/user.c b/kernel/user.c
-index 7132022..debce60 100644
+index 7132022..865ecf5 100644
--- a/kernel/user.c
+++ b/kernel/user.c
-@@ -101,7 +101,7 @@ static int sched_create_user(struct user_struct *up)
+@@ -53,10 +53,6 @@ struct user_struct root_user = {
+ .files = ATOMIC_INIT(0),
+ .sigpending = ATOMIC_INIT(0),
+ .locked_shm = 0,
+-#ifdef CONFIG_KEYS
+- .uid_keyring = &root_user_keyring,
+- .session_keyring = &root_session_keyring,
+-#endif
+ #ifdef CONFIG_USER_SCHED
+ .tg = &init_task_group,
+ #endif
+@@ -101,7 +97,7 @@ static int sched_create_user(struct user_struct *up)
{
int rc = 0;
@@ -839474,7 +1128846,7 @@
if (IS_ERR(up->tg))
rc = -ENOMEM;
-@@ -193,6 +193,33 @@ static ssize_t cpu_rt_runtime_store(struct kobject *kobj,
+@@ -193,6 +189,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);
@@ -839508,7 +1128880,7 @@
#endif
/* default attributes per uid directory */
-@@ -202,6 +229,7 @@ static struct attribute *uids_attributes[] = {
+@@ -202,6 +225,7 @@ static struct attribute *uids_attributes[] = {
#endif
#ifdef CONFIG_RT_GROUP_SCHED
&cpu_rt_runtime_attr.attr,
@@ -839516,10 +1128888,101 @@
#endif
NULL
};
+@@ -360,7 +384,7 @@ void free_uid(struct user_struct *up)
+ local_irq_restore(flags);
+ }
+
+-struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)
++struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid)
+ {
+ struct hlist_head *hashent = uidhashentry(ns, uid);
+ struct user_struct *up, *new;
+@@ -375,29 +399,15 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)
+ spin_unlock_irq(&uidhash_lock);
+
+ if (!up) {
+- new = kmem_cache_alloc(uid_cachep, GFP_KERNEL);
++ new = kmem_cache_zalloc(uid_cachep, GFP_KERNEL);
+ if (!new)
+ goto out_unlock;
+
+ new->uid = uid;
+ atomic_set(&new->__count, 1);
+- atomic_set(&new->processes, 0);
+- atomic_set(&new->files, 0);
+- atomic_set(&new->sigpending, 0);
+-#ifdef CONFIG_INOTIFY_USER
+- atomic_set(&new->inotify_watches, 0);
+- atomic_set(&new->inotify_devs, 0);
+-#endif
+-#ifdef CONFIG_POSIX_MQUEUE
+- new->mq_bytes = 0;
+-#endif
+- new->locked_shm = 0;
+-
+- if (alloc_uid_keyring(new, current) < 0)
+- goto out_free_user;
+
+ if (sched_create_user(new) < 0)
+- goto out_put_keys;
++ goto out_free_user;
+
+ if (uids_user_create(new))
+ goto out_destoy_sched;
+@@ -431,9 +441,6 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)
+
+ out_destoy_sched:
+ sched_destroy_user(new);
+-out_put_keys:
+- key_put(new->uid_keyring);
+- key_put(new->session_keyring);
+ out_free_user:
+ kmem_cache_free(uid_cachep, new);
+ out_unlock:
+diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
+index 4c90062..a9ab059 100644
+--- a/kernel/user_namespace.c
++++ b/kernel/user_namespace.c
+@@ -8,6 +8,7 @@
+ #include <linux/module.h>
+ #include <linux/version.h>
+ #include <linux/nsproxy.h>
++#include <linux/slab.h>
+ #include <linux/user_namespace.h>
+
+ /*
+@@ -73,3 +74,4 @@ void free_user_ns(struct kref *kref)
+ release_uids(ns);
+ kfree(ns);
+ }
++EXPORT_SYMBOL(free_user_ns);
+diff --git a/kernel/utsname.c b/kernel/utsname.c
+index 816d7b2..64d398f 100644
+--- a/kernel/utsname.c
++++ b/kernel/utsname.c
+@@ -14,6 +14,7 @@
+ #include <linux/utsname.h>
+ #include <linux/version.h>
+ #include <linux/err.h>
++#include <linux/slab.h>
+
+ /*
+ * Clone a new ns copying an original utsname, setting refcount to 1
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
-index ff06611..00ff4d0 100644
+index ff06611..721093a 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
+@@ -158,8 +158,8 @@ static void __queue_work(struct cpu_workqueue_struct *cwq,
+ *
+ * Returns 0 if @work was already on a queue, non-zero otherwise.
+ *
+- * We queue the work to the CPU it was submitted, but there is no
+- * guarantee that it will be processed by that CPU.
++ * We queue the work to the CPU on which it was submitted, but if the CPU dies
++ * it can be processed by another CPU.
+ */
+ int queue_work(struct workqueue_struct *wq, struct work_struct *work)
+ {
@@ -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;
@@ -839528,6 +1128991,15 @@
if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) {
BUG_ON(timer_pending(timer));
BUG_ON(!list_empty(&work->entry));
+@@ -246,7 +247,7 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq)
+ if (cwq->run_depth > 3) {
+ /* morton gets to eat his hat */
+ printk("%s: recursion depth exceeded: %d\n",
+- __FUNCTION__, cwq->run_depth);
++ __func__, cwq->run_depth);
+ dump_stack();
+ }
+ while (!list_empty(&cwq->worklist)) {
@@ -580,6 +581,7 @@ EXPORT_SYMBOL(schedule_delayed_work);
int schedule_delayed_work_on(int cpu,
struct delayed_work *dwork, unsigned long delay)
@@ -839536,11 +1129008,83 @@
return queue_delayed_work_on(cpu, keventd_wq, dwork, delay);
}
EXPORT_SYMBOL(schedule_delayed_work_on);
+@@ -770,7 +772,7 @@ struct workqueue_struct *__create_workqueue_key(const char *name,
+ }
+ EXPORT_SYMBOL_GPL(__create_workqueue_key);
+
+-static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
++static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq)
+ {
+ /*
+ * Our caller is either destroy_workqueue() or CPU_DEAD,
+@@ -806,19 +808,16 @@ static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
+ void destroy_workqueue(struct workqueue_struct *wq)
+ {
+ const cpumask_t *cpu_map = wq_cpu_map(wq);
+- struct cpu_workqueue_struct *cwq;
+ int cpu;
+
+ get_online_cpus();
+ spin_lock(&workqueue_lock);
+ list_del(&wq->list);
+ spin_unlock(&workqueue_lock);
+- put_online_cpus();
+
+- for_each_cpu_mask(cpu, *cpu_map) {
+- cwq = per_cpu_ptr(wq->cpu_wq, cpu);
+- cleanup_workqueue_thread(cwq, cpu);
+- }
++ for_each_cpu_mask(cpu, *cpu_map)
++ cleanup_workqueue_thread(per_cpu_ptr(wq->cpu_wq, cpu));
++ put_online_cpus();
+
+ free_percpu(wq->cpu_wq);
+ kfree(wq);
+@@ -836,7 +835,6 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
+ action &= ~CPU_TASKS_FROZEN;
+
+ switch (action) {
+-
+ case CPU_UP_PREPARE:
+ cpu_set(cpu, cpu_populated_map);
+ }
+@@ -859,11 +857,17 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
+ case CPU_UP_CANCELED:
+ start_workqueue_thread(cwq, -1);
+ case CPU_DEAD:
+- cleanup_workqueue_thread(cwq, cpu);
++ cleanup_workqueue_thread(cwq);
+ break;
+ }
+ }
+
++ switch (action) {
++ case CPU_UP_CANCELED:
++ case CPU_DEAD:
++ cpu_clear(cpu, cpu_populated_map);
++ }
++
+ return NOTIFY_OK;
+ }
+
diff --git a/lib/Kconfig b/lib/Kconfig
-index ba3d104..2d53dc0 100644
+index ba3d104..8cc8e87 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
-@@ -141,4 +141,7 @@ config HAS_DMA
+@@ -7,6 +7,12 @@ menu "Library routines"
+ config BITREVERSE
+ tristate
+
++config GENERIC_FIND_FIRST_BIT
++ def_bool n
++
++config GENERIC_FIND_NEXT_BIT
++ def_bool n
++
+ config CRC_CCITT
+ tristate "CRC-CCITT functions"
+ help
+@@ -141,4 +147,7 @@ config HAS_DMA
config CHECK_SIGNATURE
bool
@@ -839549,7 +1129093,7 @@
+
endmenu
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
-index 0796c1a..754cc00 100644
+index 0796c1a..d2099f4 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -25,6 +25,17 @@ config ENABLE_MUST_CHECK
@@ -839567,199 +1129111,1497 @@
+ 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.
+ config MAGIC_SYSRQ
+ bool "Magic SysRq key"
+ depends on !UML
+@@ -183,6 +194,37 @@ config TIMER_STATS
+ (it defaults to deactivated on bootup and will only be activated
+ if some application like powertop activates it explicitly).
+
++config DEBUG_OBJECTS
++ bool "Debug object operations"
++ depends on DEBUG_KERNEL
++ help
++ If you say Y here, additional code will be inserted into the
++ kernel to track the life time of various objects and validate
++ the operations on those objects.
++
++config DEBUG_OBJECTS_SELFTEST
++ bool "Debug objects selftest"
++ depends on DEBUG_OBJECTS
++ help
++ This enables the selftest of the object debug code.
++
++config DEBUG_OBJECTS_FREE
++ bool "Debug objects in freed memory"
++ depends on DEBUG_OBJECTS
++ help
++ This enables checks whether a k/v free operation frees an area
++ which contains an object which has not been deactivated
++ properly. This can make kmalloc/kfree-intensive workloads
++ much slower.
++
++config DEBUG_OBJECTS_TIMERS
++ bool "Debug timer objects"
++ depends on DEBUG_OBJECTS
++ help
++ If you say Y here, additional code will be inserted into the
++ timer routines to track the life time of timer objects and
++ validate the timer operations.
++
+ config DEBUG_SLAB
+ bool "Debug slab memory allocations"
+ depends on DEBUG_KERNEL && SLAB
+@@ -211,7 +253,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 +307,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 +469,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 +635,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 +663,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..74b0cfb 100644
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -6,7 +6,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
+ rbtree.o radix-tree.o dump_stack.o \
+ idr.o int_sqrt.o extable.o prio_tree.o \
+ sha1.o irq_regs.o reciprocal_div.o argv_split.o \
+- proportions.o prio_heap.o
++ proportions.o prio_heap.o ratelimit.o
+
+ lib-$(CONFIG_MMU) += ioremap.o
+ lib-$(CONFIG_SMP) += cpumask.o
+@@ -29,13 +29,14 @@ 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_FIRST_BIT) += find_next_bit.o
+ lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
+ obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
+ obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
+ obj-$(CONFIG_PLIST) += plist.o
+ obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
+ obj-$(CONFIG_DEBUG_LIST) += list_debug.o
++obj-$(CONFIG_DEBUG_OBJECTS) += debugobjects.o
+
+ ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
+ lib-y += dec_and_lock.o
+@@ -61,7 +62,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 +70,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..c4cb48f 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
+@@ -698,6 +714,164 @@ int bitmap_bitremap(int oldbit, const unsigned long *old,
+ }
+ EXPORT_SYMBOL(bitmap_bitremap);
+
++/**
++ * bitmap_onto - translate one bitmap relative to another
++ * @dst: resulting translated bitmap
++ * @orig: original untranslated bitmap
++ * @relmap: bitmap relative to which translated
++ * @bits: number of bits in each of these bitmaps
++ *
++ * Set the n-th bit of @dst iff there exists some m such that the
++ * n-th bit of @relmap is set, the m-th bit of @orig is set, and
++ * the n-th bit of @relmap is also the m-th _set_ bit of @relmap.
++ * (If you understood the previous sentence the first time your
++ * read it, you're overqualified for your current job.)
++ *
++ * In other words, @orig is mapped onto (surjectively) @dst,
++ * using the the map { <n, m> | the n-th bit of @relmap is the
++ * m-th set bit of @relmap }.
++ *
++ * Any set bits in @orig above bit number W, where W is the
++ * weight of (number of set bits in) @relmap are mapped nowhere.
++ * In particular, if for all bits m set in @orig, m >= W, then
++ * @dst will end up empty. In situations where the possibility
++ * of such an empty result is not desired, one way to avoid it is
++ * to use the bitmap_fold() operator, below, to first fold the
++ * @orig bitmap over itself so that all its set bits x are in the
++ * range 0 <= x < W. The bitmap_fold() operator does this by
++ * setting the bit (m % W) in @dst, for each bit (m) set in @orig.
++ *
++ * Example [1] for bitmap_onto():
++ * Let's say @relmap has bits 30-39 set, and @orig has bits
++ * 1, 3, 5, 7, 9 and 11 set. Then on return from this routine,
++ * @dst will have bits 31, 33, 35, 37 and 39 set.
++ *
++ * When bit 0 is set in @orig, it means turn on the bit in
++ * @dst corresponding to whatever is the first bit (if any)
++ * that is turned on in @relmap. Since bit 0 was off in the
++ * above example, we leave off that bit (bit 30) in @dst.
++ *
++ * When bit 1 is set in @orig (as in the above example), it
++ * means turn on the bit in @dst corresponding to whatever
++ * is the second bit that is turned on in @relmap. The second
++ * bit in @relmap that was turned on in the above example was
++ * bit 31, so we turned on bit 31 in @dst.
++ *
++ * Similarly, we turned on bits 33, 35, 37 and 39 in @dst,
++ * because they were the 4th, 6th, 8th and 10th set bits
++ * set in @relmap, and the 4th, 6th, 8th and 10th bits of
++ * @orig (i.e. bits 3, 5, 7 and 9) were also set.
++ *
++ * When bit 11 is set in @orig, it means turn on the bit in
++ * @dst corresponding to whatever is the twelth bit that is
++ * turned on in @relmap. In the above example, there were
++ * only ten bits turned on in @relmap (30..39), so that bit
++ * 11 was set in @orig had no affect on @dst.
++ *
++ * Example [2] for bitmap_fold() + bitmap_onto():
++ * Let's say @relmap has these ten bits set:
++ * 40 41 42 43 45 48 53 61 74 95
++ * (for the curious, that's 40 plus the first ten terms of the
++ * Fibonacci sequence.)
++ *
++ * Further lets say we use the following code, invoking
++ * bitmap_fold() then bitmap_onto, as suggested above to
++ * avoid the possitility of an empty @dst result:
++ *
++ * unsigned long *tmp; // a temporary bitmap's bits
++ *
++ * bitmap_fold(tmp, orig, bitmap_weight(relmap, bits), bits);
++ * bitmap_onto(dst, tmp, relmap, bits);
++ *
++ * Then this table shows what various values of @dst would be, for
++ * various @orig's. I list the zero-based positions of each set bit.
++ * The tmp column shows the intermediate result, as computed by
++ * using bitmap_fold() to fold the @orig bitmap modulo ten
++ * (the weight of @relmap).
++ *
++ * @orig tmp @dst
++ * 0 0 40
++ * 1 1 41
++ * 9 9 95
++ * 10 0 40 (*)
++ * 1 3 5 7 1 3 5 7 41 43 48 61
++ * 0 1 2 3 4 0 1 2 3 4 40 41 42 43 45
++ * 0 9 18 27 0 9 8 7 40 61 74 95
++ * 0 10 20 30 0 40
++ * 0 11 22 33 0 1 2 3 40 41 42 43
++ * 0 12 24 36 0 2 4 6 40 42 45 53
++ * 78 102 211 1 2 8 41 42 74 (*)
++ *
++ * (*) For these marked lines, if we hadn't first done bitmap_fold()
++ * into tmp, then the @dst result would have been empty.
++ *
++ * If either of @orig or @relmap is empty (no set bits), then @dst
++ * will be returned empty.
++ *
++ * If (as explained above) the only set bits in @orig are in positions
++ * m where m >= W, (where W is the weight of @relmap) then @dst will
++ * once again be returned empty.
++ *
++ * All bits in @dst not set by the above rule are cleared.
++ */
++void bitmap_onto(unsigned long *dst, const unsigned long *orig,
++ const unsigned long *relmap, int bits)
++{
++ int n, m; /* same meaning as in above comment */
++
++ if (dst == orig) /* following doesn't handle inplace mappings */
++ return;
++ bitmap_zero(dst, bits);
++
++ /*
++ * The following code is a more efficient, but less
++ * obvious, equivalent to the loop:
++ * for (m = 0; m < bitmap_weight(relmap, bits); m++) {
++ * n = bitmap_ord_to_pos(orig, m, bits);
++ * if (test_bit(m, orig))
++ * set_bit(n, dst);
++ * }
++ */
++
++ m = 0;
++ for (n = find_first_bit(relmap, bits);
++ n < bits;
++ n = find_next_bit(relmap, bits, n + 1)) {
++ /* m == bitmap_pos_to_ord(relmap, n, bits) */
++ if (test_bit(m, orig))
++ set_bit(n, dst);
++ m++;
++ }
++}
++EXPORT_SYMBOL(bitmap_onto);
++
++/**
++ * bitmap_fold - fold larger bitmap into smaller, modulo specified size
++ * @dst: resulting smaller bitmap
++ * @orig: original larger bitmap
++ * @sz: specified size
++ * @bits: number of bits in each of these bitmaps
++ *
++ * For each bit oldbit in @orig, set bit oldbit mod @sz in @dst.
++ * Clear all other bits in @dst. See further the comment and
++ * Example [2] for bitmap_onto() for why and how to use this.
++ */
++void bitmap_fold(unsigned long *dst, const unsigned long *orig,
++ int sz, int bits)
++{
++ int oldbit;
++
++ if (dst == orig) /* following doesn't handle inplace mappings */
++ return;
++ bitmap_zero(dst, bits);
++
++ for (oldbit = find_first_bit(orig, bits);
++ oldbit < bits;
++ oldbit = find_next_bit(orig, bits, oldbit + 1))
++ set_bit(oldbit % sz, dst);
++}
++EXPORT_SYMBOL(bitmap_fold);
++
+ /*
+ * Common code for bitmap_*_region() routines.
+ * bitmap: array of unsigned longs corresponding to the bitmap
+diff --git a/lib/debugobjects.c b/lib/debugobjects.c
+new file mode 100644
+index 0000000..a76a5e1
+--- /dev/null
++++ b/lib/debugobjects.c
+@@ -0,0 +1,890 @@
++/*
++ * Generic infrastructure for lifetime debugging of objects.
++ *
++ * Started by Thomas Gleixner
++ *
++ * Copyright (C) 2008, Thomas Gleixner <tglx at linutronix.de>
++ *
++ * For licencing details see kernel-base/COPYING
++ */
++#include <linux/debugobjects.h>
++#include <linux/interrupt.h>
++#include <linux/seq_file.h>
++#include <linux/debugfs.h>
++#include <linux/hash.h>
++
++#define ODEBUG_HASH_BITS 14
++#define ODEBUG_HASH_SIZE (1 << ODEBUG_HASH_BITS)
++
++#define ODEBUG_POOL_SIZE 512
++#define ODEBUG_POOL_MIN_LEVEL 256
++
++#define ODEBUG_CHUNK_SHIFT PAGE_SHIFT
++#define ODEBUG_CHUNK_SIZE (1 << ODEBUG_CHUNK_SHIFT)
++#define ODEBUG_CHUNK_MASK (~(ODEBUG_CHUNK_SIZE - 1))
++
++struct debug_bucket {
++ struct hlist_head list;
++ spinlock_t lock;
++};
++
++static struct debug_bucket obj_hash[ODEBUG_HASH_SIZE];
++
++static struct debug_obj obj_static_pool[ODEBUG_POOL_SIZE];
++
++static DEFINE_SPINLOCK(pool_lock);
++
++static HLIST_HEAD(obj_pool);
++
++static int obj_pool_min_free = ODEBUG_POOL_SIZE;
++static int obj_pool_free = ODEBUG_POOL_SIZE;
++static int obj_pool_used;
++static int obj_pool_max_used;
++static struct kmem_cache *obj_cache;
++
++static int debug_objects_maxchain __read_mostly;
++static int debug_objects_fixups __read_mostly;
++static int debug_objects_warnings __read_mostly;
++static int debug_objects_enabled __read_mostly;
++static struct debug_obj_descr *descr_test __read_mostly;
++
++static int __init enable_object_debug(char *str)
++{
++ debug_objects_enabled = 1;
++ return 0;
++}
++early_param("debug_objects", enable_object_debug);
++
++static const char *obj_states[ODEBUG_STATE_MAX] = {
++ [ODEBUG_STATE_NONE] = "none",
++ [ODEBUG_STATE_INIT] = "initialized",
++ [ODEBUG_STATE_INACTIVE] = "inactive",
++ [ODEBUG_STATE_ACTIVE] = "active",
++ [ODEBUG_STATE_DESTROYED] = "destroyed",
++ [ODEBUG_STATE_NOTAVAILABLE] = "not available",
++};
++
++static int fill_pool(void)
++{
++ gfp_t gfp = GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN;
++ struct debug_obj *new;
++
++ if (likely(obj_pool_free >= ODEBUG_POOL_MIN_LEVEL))
++ return obj_pool_free;
++
++ if (unlikely(!obj_cache))
++ return obj_pool_free;
++
++ while (obj_pool_free < ODEBUG_POOL_MIN_LEVEL) {
++
++ new = kmem_cache_zalloc(obj_cache, gfp);
++ if (!new)
++ return obj_pool_free;
++
++ spin_lock(&pool_lock);
++ hlist_add_head(&new->node, &obj_pool);
++ obj_pool_free++;
++ spin_unlock(&pool_lock);
++ }
++ return obj_pool_free;
++}
++
++/*
++ * Lookup an object in the hash bucket.
++ */
++static struct debug_obj *lookup_object(void *addr, struct debug_bucket *b)
++{
++ struct hlist_node *node;
++ struct debug_obj *obj;
++ int cnt = 0;
++
++ hlist_for_each_entry(obj, node, &b->list, node) {
++ cnt++;
++ if (obj->object == addr)
++ return obj;
++ }
++ if (cnt > debug_objects_maxchain)
++ debug_objects_maxchain = cnt;
++
++ return NULL;
++}
++
++/*
++ * Allocate a new object. If the pool is empty and no refill possible,
++ * switch off the debugger.
++ */
++static struct debug_obj *
++alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr)
++{
++ struct debug_obj *obj = NULL;
++ int retry = 0;
++
++repeat:
++ spin_lock(&pool_lock);
++ if (obj_pool.first) {
++ obj = hlist_entry(obj_pool.first, typeof(*obj), node);
++
++ obj->object = addr;
++ obj->descr = descr;
++ obj->state = ODEBUG_STATE_NONE;
++ hlist_del(&obj->node);
++
++ hlist_add_head(&obj->node, &b->list);
++
++ obj_pool_used++;
++ if (obj_pool_used > obj_pool_max_used)
++ obj_pool_max_used = obj_pool_used;
++
++ obj_pool_free--;
++ if (obj_pool_free < obj_pool_min_free)
++ obj_pool_min_free = obj_pool_free;
++ }
++ spin_unlock(&pool_lock);
++
++ if (fill_pool() && !obj && !retry++)
++ goto repeat;
++
++ return obj;
++}
++
++/*
++ * Put the object back into the pool or give it back to kmem_cache:
++ */
++static void free_object(struct debug_obj *obj)
++{
++ unsigned long idx = (unsigned long)(obj - obj_static_pool);
++
++ if (obj_pool_free < ODEBUG_POOL_SIZE || idx < ODEBUG_POOL_SIZE) {
++ spin_lock(&pool_lock);
++ hlist_add_head(&obj->node, &obj_pool);
++ obj_pool_free++;
++ obj_pool_used--;
++ spin_unlock(&pool_lock);
++ } else {
++ spin_lock(&pool_lock);
++ obj_pool_used--;
++ spin_unlock(&pool_lock);
++ kmem_cache_free(obj_cache, obj);
++ }
++}
++
++/*
++ * We run out of memory. That means we probably have tons of objects
++ * allocated.
++ */
++static void debug_objects_oom(void)
++{
++ struct debug_bucket *db = obj_hash;
++ struct hlist_node *node, *tmp;
++ struct debug_obj *obj;
++ unsigned long flags;
++ int i;
++
++ printk(KERN_WARNING "ODEBUG: Out of memory. ODEBUG disabled\n");
++
++ for (i = 0; i < ODEBUG_HASH_SIZE; i++, db++) {
++ spin_lock_irqsave(&db->lock, flags);
++ hlist_for_each_entry_safe(obj, node, tmp, &db->list, node) {
++ hlist_del(&obj->node);
++ free_object(obj);
++ }
++ spin_unlock_irqrestore(&db->lock, flags);
++ }
++}
++
++/*
++ * We use the pfn of the address for the hash. That way we can check
++ * for freed objects simply by checking the affected bucket.
++ */
++static struct debug_bucket *get_bucket(unsigned long addr)
++{
++ unsigned long hash;
++
++ hash = hash_long((addr >> ODEBUG_CHUNK_SHIFT), ODEBUG_HASH_BITS);
++ return &obj_hash[hash];
++}
++
++static void debug_print_object(struct debug_obj *obj, char *msg)
++{
++ static int limit;
++
++ if (limit < 5 && obj->descr != descr_test) {
++ limit++;
++ printk(KERN_ERR "ODEBUG: %s %s object type: %s\n", msg,
++ obj_states[obj->state], obj->descr->name);
++ WARN_ON(1);
++ }
++ debug_objects_warnings++;
++}
++
++/*
++ * Try to repair the damage, so we have a better chance to get useful
++ * debug output.
++ */
++static void
++debug_object_fixup(int (*fixup)(void *addr, enum debug_obj_state state),
++ void * addr, enum debug_obj_state state)
++{
++ if (fixup)
++ debug_objects_fixups += fixup(addr, state);
++}
++
++static void debug_object_is_on_stack(void *addr, int onstack)
++{
++ void *stack = current->stack;
++ int is_on_stack;
++ static int limit;
++
++ if (limit > 4)
++ return;
++
++ is_on_stack = (addr >= stack && addr < (stack + THREAD_SIZE));
++
++ if (is_on_stack == onstack)
++ return;
++
++ limit++;
++ if (is_on_stack)
++ printk(KERN_WARNING
++ "ODEBUG: object is on stack, but not annotated\n");
++ else
++ printk(KERN_WARNING
++ "ODEBUG: object is not on stack, but annotated\n");
++ WARN_ON(1);
++}
++
++static void
++__debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack)
++{
++ enum debug_obj_state state;
++ struct debug_bucket *db;
++ struct debug_obj *obj;
++ unsigned long flags;
++
++ db = get_bucket((unsigned long) addr);
++
++ spin_lock_irqsave(&db->lock, flags);
++
++ obj = lookup_object(addr, db);
++ if (!obj) {
++ obj = alloc_object(addr, db, descr);
++ if (!obj) {
++ debug_objects_enabled = 0;
++ spin_unlock_irqrestore(&db->lock, flags);
++ debug_objects_oom();
++ return;
++ }
++ debug_object_is_on_stack(addr, onstack);
++ }
++
++ switch (obj->state) {
++ case ODEBUG_STATE_NONE:
++ case ODEBUG_STATE_INIT:
++ case ODEBUG_STATE_INACTIVE:
++ obj->state = ODEBUG_STATE_INIT;
++ break;
++
++ case ODEBUG_STATE_ACTIVE:
++ debug_print_object(obj, "init");
++ state = obj->state;
++ spin_unlock_irqrestore(&db->lock, flags);
++ debug_object_fixup(descr->fixup_init, addr, state);
++ return;
++
++ case ODEBUG_STATE_DESTROYED:
++ debug_print_object(obj, "init");
++ break;
++ default:
++ break;
++ }
++
++ spin_unlock_irqrestore(&db->lock, flags);
++}
++
++/**
++ * debug_object_init - debug checks when an object is initialized
++ * @addr: address of the object
++ * @descr: pointer to an object specific debug description structure
++ */
++void debug_object_init(void *addr, struct debug_obj_descr *descr)
++{
++ if (!debug_objects_enabled)
++ return;
++
++ __debug_object_init(addr, descr, 0);
++}
++
++/**
++ * debug_object_init_on_stack - debug checks when an object on stack is
++ * initialized
++ * @addr: address of the object
++ * @descr: pointer to an object specific debug description structure
++ */
++void debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr)
++{
++ if (!debug_objects_enabled)
++ return;
++
++ __debug_object_init(addr, descr, 1);
++}
++
++/**
++ * debug_object_activate - debug checks when an object is activated
++ * @addr: address of the object
++ * @descr: pointer to an object specific debug description structure
++ */
++void debug_object_activate(void *addr, struct debug_obj_descr *descr)
++{
++ enum debug_obj_state state;
++ struct debug_bucket *db;
++ struct debug_obj *obj;
++ unsigned long flags;
++
++ if (!debug_objects_enabled)
++ return;
++
++ db = get_bucket((unsigned long) addr);
++
++ spin_lock_irqsave(&db->lock, flags);
++
++ obj = lookup_object(addr, db);
++ if (obj) {
++ switch (obj->state) {
++ case ODEBUG_STATE_INIT:
++ case ODEBUG_STATE_INACTIVE:
++ obj->state = ODEBUG_STATE_ACTIVE;
++ break;
++
++ case ODEBUG_STATE_ACTIVE:
++ debug_print_object(obj, "activate");
++ state = obj->state;
++ spin_unlock_irqrestore(&db->lock, flags);
++ debug_object_fixup(descr->fixup_activate, addr, state);
++ return;
++
++ case ODEBUG_STATE_DESTROYED:
++ debug_print_object(obj, "activate");
++ break;
++ default:
++ break;
++ }
++ spin_unlock_irqrestore(&db->lock, flags);
++ return;
++ }
++
++ spin_unlock_irqrestore(&db->lock, flags);
++ /*
++ * This happens when a static object is activated. We
++ * let the type specific code decide whether this is
++ * true or not.
++ */
++ debug_object_fixup(descr->fixup_activate, addr,
++ ODEBUG_STATE_NOTAVAILABLE);
++}
++
++/**
++ * debug_object_deactivate - debug checks when an object is deactivated
++ * @addr: address of the object
++ * @descr: pointer to an object specific debug description structure
++ */
++void debug_object_deactivate(void *addr, struct debug_obj_descr *descr)
++{
++ struct debug_bucket *db;
++ struct debug_obj *obj;
++ unsigned long flags;
++
++ if (!debug_objects_enabled)
++ return;
++
++ db = get_bucket((unsigned long) addr);
++
++ spin_lock_irqsave(&db->lock, flags);
++
++ obj = lookup_object(addr, db);
++ if (obj) {
++ switch (obj->state) {
++ case ODEBUG_STATE_INIT:
++ case ODEBUG_STATE_INACTIVE:
++ case ODEBUG_STATE_ACTIVE:
++ obj->state = ODEBUG_STATE_INACTIVE;
++ break;
++
++ case ODEBUG_STATE_DESTROYED:
++ debug_print_object(obj, "deactivate");
++ break;
++ default:
++ break;
++ }
++ } else {
++ struct debug_obj o = { .object = addr,
++ .state = ODEBUG_STATE_NOTAVAILABLE,
++ .descr = descr };
++
++ debug_print_object(&o, "deactivate");
++ }
++
++ spin_unlock_irqrestore(&db->lock, flags);
++}
++
++/**
++ * debug_object_destroy - debug checks when an object is destroyed
++ * @addr: address of the object
++ * @descr: pointer to an object specific debug description structure
++ */
++void debug_object_destroy(void *addr, struct debug_obj_descr *descr)
++{
++ enum debug_obj_state state;
++ struct debug_bucket *db;
++ struct debug_obj *obj;
++ unsigned long flags;
++
++ if (!debug_objects_enabled)
++ return;
++
++ db = get_bucket((unsigned long) addr);
++
++ spin_lock_irqsave(&db->lock, flags);
++
++ obj = lookup_object(addr, db);
++ if (!obj)
++ goto out_unlock;
++
++ switch (obj->state) {
++ case ODEBUG_STATE_NONE:
++ case ODEBUG_STATE_INIT:
++ case ODEBUG_STATE_INACTIVE:
++ obj->state = ODEBUG_STATE_DESTROYED;
++ break;
++ case ODEBUG_STATE_ACTIVE:
++ debug_print_object(obj, "destroy");
++ state = obj->state;
++ spin_unlock_irqrestore(&db->lock, flags);
++ debug_object_fixup(descr->fixup_destroy, addr, state);
++ return;
++
++ case ODEBUG_STATE_DESTROYED:
++ debug_print_object(obj, "destroy");
++ break;
++ default:
++ break;
++ }
++out_unlock:
++ spin_unlock_irqrestore(&db->lock, flags);
++}
++
++/**
++ * debug_object_free - debug checks when an object is freed
++ * @addr: address of the object
++ * @descr: pointer to an object specific debug description structure
++ */
++void debug_object_free(void *addr, struct debug_obj_descr *descr)
++{
++ enum debug_obj_state state;
++ struct debug_bucket *db;
++ struct debug_obj *obj;
++ unsigned long flags;
++
++ if (!debug_objects_enabled)
++ return;
++
++ db = get_bucket((unsigned long) addr);
++
++ spin_lock_irqsave(&db->lock, flags);
++
++ obj = lookup_object(addr, db);
++ if (!obj)
++ goto out_unlock;
++
++ switch (obj->state) {
++ case ODEBUG_STATE_ACTIVE:
++ debug_print_object(obj, "free");
++ state = obj->state;
++ spin_unlock_irqrestore(&db->lock, flags);
++ debug_object_fixup(descr->fixup_free, addr, state);
++ return;
++ default:
++ hlist_del(&obj->node);
++ free_object(obj);
++ break;
++ }
++out_unlock:
++ spin_unlock_irqrestore(&db->lock, flags);
++}
++
++#ifdef CONFIG_DEBUG_OBJECTS_FREE
++static void __debug_check_no_obj_freed(const void *address, unsigned long size)
++{
++ unsigned long flags, oaddr, saddr, eaddr, paddr, chunks;
++ struct hlist_node *node, *tmp;
++ struct debug_obj_descr *descr;
++ enum debug_obj_state state;
++ struct debug_bucket *db;
++ struct debug_obj *obj;
++ int cnt;
++
++ saddr = (unsigned long) address;
++ eaddr = saddr + size;
++ paddr = saddr & ODEBUG_CHUNK_MASK;
++ chunks = ((eaddr - paddr) + (ODEBUG_CHUNK_SIZE - 1));
++ chunks >>= ODEBUG_CHUNK_SHIFT;
++
++ for (;chunks > 0; chunks--, paddr += ODEBUG_CHUNK_SIZE) {
++ db = get_bucket(paddr);
++
++repeat:
++ cnt = 0;
++ spin_lock_irqsave(&db->lock, flags);
++ hlist_for_each_entry_safe(obj, node, tmp, &db->list, node) {
++ cnt++;
++ oaddr = (unsigned long) obj->object;
++ if (oaddr < saddr || oaddr >= eaddr)
++ continue;
++
++ switch (obj->state) {
++ case ODEBUG_STATE_ACTIVE:
++ debug_print_object(obj, "free");
++ descr = obj->descr;
++ state = obj->state;
++ spin_unlock_irqrestore(&db->lock, flags);
++ debug_object_fixup(descr->fixup_free,
++ (void *) oaddr, state);
++ goto repeat;
++ default:
++ hlist_del(&obj->node);
++ free_object(obj);
++ break;
++ }
++ }
++ spin_unlock_irqrestore(&db->lock, flags);
++ if (cnt > debug_objects_maxchain)
++ debug_objects_maxchain = cnt;
++ }
++}
++
++void debug_check_no_obj_freed(const void *address, unsigned long size)
++{
++ if (debug_objects_enabled)
++ __debug_check_no_obj_freed(address, size);
++}
++#endif
++
++#ifdef CONFIG_DEBUG_FS
++
++static int debug_stats_show(struct seq_file *m, void *v)
++{
++ seq_printf(m, "max_chain :%d\n", debug_objects_maxchain);
++ seq_printf(m, "warnings :%d\n", debug_objects_warnings);
++ seq_printf(m, "fixups :%d\n", debug_objects_fixups);
++ seq_printf(m, "pool_free :%d\n", obj_pool_free);
++ seq_printf(m, "pool_min_free :%d\n", obj_pool_min_free);
++ seq_printf(m, "pool_used :%d\n", obj_pool_used);
++ seq_printf(m, "pool_max_used :%d\n", obj_pool_max_used);
++ return 0;
++}
++
++static int debug_stats_open(struct inode *inode, struct file *filp)
++{
++ return single_open(filp, debug_stats_show, NULL);
++}
++
++static const struct file_operations debug_stats_fops = {
++ .open = debug_stats_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int __init debug_objects_init_debugfs(void)
++{
++ struct dentry *dbgdir, *dbgstats;
++
++ if (!debug_objects_enabled)
++ return 0;
++
++ dbgdir = debugfs_create_dir("debug_objects", NULL);
++ if (!dbgdir)
++ return -ENOMEM;
++
++ dbgstats = debugfs_create_file("stats", 0444, dbgdir, NULL,
++ &debug_stats_fops);
++ if (!dbgstats)
++ goto err;
++
++ return 0;
++
++err:
++ debugfs_remove(dbgdir);
++
++ return -ENOMEM;
++}
++__initcall(debug_objects_init_debugfs);
++
++#else
++static inline void debug_objects_init_debugfs(void) { }
++#endif
++
++#ifdef CONFIG_DEBUG_OBJECTS_SELFTEST
++
++/* Random data structure for the self test */
++struct self_test {
++ unsigned long dummy1[6];
++ int static_init;
++ unsigned long dummy2[3];
++};
++
++static __initdata struct debug_obj_descr descr_type_test;
++
++/*
++ * fixup_init is called when:
++ * - an active object is initialized
++ */
++static int __init fixup_init(void *addr, enum debug_obj_state state)
++{
++ struct self_test *obj = addr;
++
++ switch (state) {
++ case ODEBUG_STATE_ACTIVE:
++ debug_object_deactivate(obj, &descr_type_test);
++ debug_object_init(obj, &descr_type_test);
++ return 1;
++ default:
++ return 0;
++ }
++}
++
++/*
++ * fixup_activate is called when:
++ * - an active object is activated
++ * - an unknown object is activated (might be a statically initialized object)
++ */
++static int __init fixup_activate(void *addr, enum debug_obj_state state)
++{
++ struct self_test *obj = addr;
++
++ switch (state) {
++ case ODEBUG_STATE_NOTAVAILABLE:
++ if (obj->static_init == 1) {
++ debug_object_init(obj, &descr_type_test);
++ debug_object_activate(obj, &descr_type_test);
++ /*
++ * Real code should return 0 here ! This is
++ * not a fixup of some bad behaviour. We
++ * merily call the debug_init function to keep
++ * track of the object.
++ */
++ return 1;
++ } else {
++ /* Real code needs to emit a warning here */
++ }
++ return 0;
++
++ case ODEBUG_STATE_ACTIVE:
++ debug_object_deactivate(obj, &descr_type_test);
++ debug_object_activate(obj, &descr_type_test);
++ return 1;
++
++ default:
++ return 0;
++ }
++}
++
++/*
++ * fixup_destroy is called when:
++ * - an active object is destroyed
++ */
++static int __init fixup_destroy(void *addr, enum debug_obj_state state)
++{
++ struct self_test *obj = addr;
++
++ switch (state) {
++ case ODEBUG_STATE_ACTIVE:
++ debug_object_deactivate(obj, &descr_type_test);
++ debug_object_destroy(obj, &descr_type_test);
++ return 1;
++ default:
++ return 0;
++ }
++}
++
++/*
++ * fixup_free is called when:
++ * - an active object is freed
++ */
++static int __init fixup_free(void *addr, enum debug_obj_state state)
++{
++ struct self_test *obj = addr;
++
++ switch (state) {
++ case ODEBUG_STATE_ACTIVE:
++ debug_object_deactivate(obj, &descr_type_test);
++ debug_object_free(obj, &descr_type_test);
++ return 1;
++ default:
++ return 0;
++ }
++}
++
++static int
++check_results(void *addr, enum debug_obj_state state, int fixups, int warnings)
++{
++ struct debug_bucket *db;
++ struct debug_obj *obj;
++ unsigned long flags;
++ int res = -EINVAL;
++
++ db = get_bucket((unsigned long) addr);
++
++ spin_lock_irqsave(&db->lock, flags);
++
++ obj = lookup_object(addr, db);
++ if (!obj && state != ODEBUG_STATE_NONE) {
++ printk(KERN_ERR "ODEBUG: selftest object not found\n");
++ WARN_ON(1);
++ goto out;
++ }
++ if (obj && obj->state != state) {
++ printk(KERN_ERR "ODEBUG: selftest wrong state: %d != %d\n",
++ obj->state, state);
++ WARN_ON(1);
++ goto out;
++ }
++ if (fixups != debug_objects_fixups) {
++ printk(KERN_ERR "ODEBUG: selftest fixups failed %d != %d\n",
++ fixups, debug_objects_fixups);
++ WARN_ON(1);
++ goto out;
++ }
++ if (warnings != debug_objects_warnings) {
++ printk(KERN_ERR "ODEBUG: selftest warnings failed %d != %d\n",
++ warnings, debug_objects_warnings);
++ WARN_ON(1);
++ goto out;
++ }
++ res = 0;
++out:
++ spin_unlock_irqrestore(&db->lock, flags);
++ if (res)
++ debug_objects_enabled = 0;
++ return res;
++}
++
++static __initdata struct debug_obj_descr descr_type_test = {
++ .name = "selftest",
++ .fixup_init = fixup_init,
++ .fixup_activate = fixup_activate,
++ .fixup_destroy = fixup_destroy,
++ .fixup_free = fixup_free,
++};
+
-+ If unsure, say N.
++static __initdata struct self_test obj = { .static_init = 0 };
+
- 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.
++static void __init debug_objects_selftest(void)
++{
++ int fixups, oldfixups, warnings, oldwarnings;
++ unsigned long flags;
+
-+ If unsure, say N.
++ local_irq_save(flags);
+
- source "samples/Kconfig"
++ fixups = oldfixups = debug_objects_fixups;
++ warnings = oldwarnings = debug_objects_warnings;
++ descr_test = &descr_type_test;
+
-+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 @@
++ debug_object_init(&obj, &descr_type_test);
++ if (check_results(&obj, ODEBUG_STATE_INIT, fixups, warnings))
++ goto out;
++ debug_object_activate(&obj, &descr_type_test);
++ if (check_results(&obj, ODEBUG_STATE_ACTIVE, fixups, warnings))
++ goto out;
++ debug_object_activate(&obj, &descr_type_test);
++ if (check_results(&obj, ODEBUG_STATE_ACTIVE, ++fixups, ++warnings))
++ goto out;
++ debug_object_deactivate(&obj, &descr_type_test);
++ if (check_results(&obj, ODEBUG_STATE_INACTIVE, fixups, warnings))
++ goto out;
++ debug_object_destroy(&obj, &descr_type_test);
++ if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, warnings))
++ goto out;
++ debug_object_init(&obj, &descr_type_test);
++ if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings))
++ goto out;
++ debug_object_activate(&obj, &descr_type_test);
++ if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings))
++ goto out;
++ debug_object_deactivate(&obj, &descr_type_test);
++ if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings))
++ goto out;
++ debug_object_free(&obj, &descr_type_test);
++ if (check_results(&obj, ODEBUG_STATE_NONE, fixups, warnings))
++ goto out;
+
-+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.
++ obj.static_init = 1;
++ debug_object_activate(&obj, &descr_type_test);
++ if (check_results(&obj, ODEBUG_STATE_ACTIVE, ++fixups, warnings))
++ goto out;
++ debug_object_init(&obj, &descr_type_test);
++ if (check_results(&obj, ODEBUG_STATE_INIT, ++fixups, ++warnings))
++ goto out;
++ debug_object_free(&obj, &descr_type_test);
++ if (check_results(&obj, ODEBUG_STATE_NONE, fixups, warnings))
++ goto out;
+
-+config HAVE_ARCH_KGDB_SHADOW_INFO
-+ bool
++#ifdef CONFIG_DEBUG_OBJECTS_FREE
++ debug_object_init(&obj, &descr_type_test);
++ if (check_results(&obj, ODEBUG_STATE_INIT, fixups, warnings))
++ goto out;
++ debug_object_activate(&obj, &descr_type_test);
++ if (check_results(&obj, ODEBUG_STATE_ACTIVE, fixups, warnings))
++ goto out;
++ __debug_check_no_obj_freed(&obj, sizeof(obj));
++ if (check_results(&obj, ODEBUG_STATE_NONE, ++fixups, ++warnings))
++ goto out;
++#endif
++ printk(KERN_INFO "ODEBUG: selftest passed\n");
+
-+config HAVE_ARCH_KGDB
-+ bool
++out:
++ debug_objects_fixups = oldfixups;
++ debug_objects_warnings = oldwarnings;
++ descr_test = NULL;
+
-+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.
++ local_irq_restore(flags);
++}
++#else
++static inline void debug_objects_selftest(void) { }
++#endif
+
-+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"
++/*
++ * Called during early boot to initialize the hash buckets and link
++ * the static object pool objects into the poll list. After this call
++ * the object tracker is fully operational.
++ */
++void __init debug_objects_early_init(void)
++{
++ int i;
+
-+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
++ for (i = 0; i < ODEBUG_HASH_SIZE; i++)
++ spin_lock_init(&obj_hash[i].lock);
+
-+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
++ for (i = 0; i < ODEBUG_POOL_SIZE; i++)
++ hlist_add_head(&obj_static_pool[i].node, &obj_pool);
++}
++
++/*
++ * Called after the kmem_caches are functional to setup a dedicated
++ * cache pool, which has the SLAB_DEBUG_OBJECTS flag set. This flag
++ * prevents that the debug code is called on kmem_cache_free() for the
++ * debug tracker objects to avoid recursive calls.
++ */
++void __init debug_objects_mem_init(void)
++{
++ if (!debug_objects_enabled)
++ return;
++
++ obj_cache = kmem_cache_create("debug_objects_cache",
++ sizeof (struct debug_obj), 0,
++ SLAB_DEBUG_OBJECTS, NULL);
++
++ if (!obj_cache)
++ debug_objects_enabled = 0;
++ else
++ debug_objects_selftest();
++}
+diff --git a/lib/devres.c b/lib/devres.c
+index edc27a5..26c87c4 100644
+--- a/lib/devres.c
++++ b/lib/devres.c
+@@ -20,7 +20,7 @@ static int devm_ioremap_match(struct device *dev, void *res, void *match_data)
+ *
+ * Managed ioremap(). Map is automatically unmapped on driver detach.
+ */
+-void __iomem *devm_ioremap(struct device *dev, unsigned long offset,
++void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
+ unsigned long size)
+ {
+ void __iomem **ptr, *addr;
+@@ -49,7 +49,7 @@ EXPORT_SYMBOL(devm_ioremap);
+ * Managed ioremap_nocache(). Map is automatically unmapped on driver
+ * detach.
+ */
+-void __iomem *devm_ioremap_nocache(struct device *dev, unsigned long offset,
++void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
+ unsigned long size)
+ {
+ void __iomem **ptr, *addr;
+diff --git a/lib/find_next_bit.c b/lib/find_next_bit.c
+index 78ccd73..24c59de 100644
+--- a/lib/find_next_bit.c
++++ b/lib/find_next_bit.c
+@@ -16,14 +16,12 @@
- obj-$(CONFIG_SWIOTLB) += swiotlb.o
-@@ -70,6 +68,8 @@ obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o
+ #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
- lib-$(CONFIG_GENERIC_BUG) += bug.o
+-/**
+- * find_next_bit - find the next set bit in a memory region
+- * @addr: The address to base the search on
+- * @offset: The bitnumber to start searching at
+- * @size: The maximum size to search
++#ifdef CONFIG_GENERIC_FIND_NEXT_BIT
++/*
++ * Find the next set bit in a memory region.
+ */
+ unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
+- unsigned long offset)
++ unsigned long offset)
+ {
+ const unsigned long *p = addr + BITOP_WORD(offset);
+ unsigned long result = offset & ~(BITS_PER_LONG-1);
+@@ -60,7 +58,6 @@ found_first:
+ found_middle:
+ return result + __ffs(tmp);
+ }
+-
+ EXPORT_SYMBOL(find_next_bit);
-+obj-$(CONFIG_HAVE_LMB) += lmb.o
+ /*
+@@ -68,7 +65,7 @@ EXPORT_SYMBOL(find_next_bit);
+ * Linus' asm-alpha/bitops.h.
+ */
+ unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
+- unsigned long offset)
++ unsigned long offset)
+ {
+ const unsigned long *p = addr + BITOP_WORD(offset);
+ unsigned long result = offset & ~(BITS_PER_LONG-1);
+@@ -105,8 +102,62 @@ found_first:
+ found_middle:
+ return result + ffz(tmp);
+ }
+-
+ EXPORT_SYMBOL(find_next_zero_bit);
++#endif /* CONFIG_GENERIC_FIND_NEXT_BIT */
+
- 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
++#ifdef CONFIG_GENERIC_FIND_FIRST_BIT
++/*
++ * Find the first set bit in a memory region.
+ */
-+int bitmap_scnprintf_len(unsigned int len)
++unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
+{
-+ /* 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);
++ const unsigned long *p = addr;
++ unsigned long result = 0;
++ unsigned long tmp;
+
-+ return buflen;
++ while (size & ~(BITS_PER_LONG-1)) {
++ if ((tmp = *(p++)))
++ goto found;
++ result += BITS_PER_LONG;
++ size -= BITS_PER_LONG;
++ }
++ if (!size)
++ return result;
++
++ tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
++ if (tmp == 0UL) /* Are any bits set? */
++ return result + size; /* Nope. */
++found:
++ return result + __ffs(tmp);
+}
-+EXPORT_SYMBOL(bitmap_scnprintf_len);
++EXPORT_SYMBOL(find_first_bit);
+
-+/**
- * __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
++/*
++ * Find the first cleared bit in a memory region.
++ */
++unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
++{
++ const unsigned long *p = addr;
++ unsigned long result = 0;
++ unsigned long tmp;
++
++ while (size & ~(BITS_PER_LONG-1)) {
++ if (~(tmp = *(p++)))
++ goto found;
++ result += BITS_PER_LONG;
++ size -= BITS_PER_LONG;
++ }
++ if (!size)
++ return result;
++
++ tmp = (*p) | (~0UL << size);
++ if (tmp == ~0UL) /* Are any bits zero? */
++ return result + size; /* Nope. */
++found:
++ return result + ffz(tmp);
++}
++EXPORT_SYMBOL(find_first_zero_bit);
++#endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
+
+ #ifdef __BIG_ENDIAN
+
+diff --git a/lib/idr.c b/lib/idr.c
+index afbb0b1..8368c81 100644
+--- a/lib/idr.c
++++ b/lib/idr.c
+@@ -585,12 +585,11 @@ static void idr_cache_ctor(struct kmem_cache *idr_layer_cache, void *idr_layer)
+ memset(idr_layer, 0, sizeof(struct idr_layer));
+ }
+
+-static int init_id_cache(void)
++void __init idr_init_cache(void)
+ {
+- if (!idr_layer_cache)
+- idr_layer_cache = kmem_cache_create("idr_layer_cache",
+- sizeof(struct idr_layer), 0, 0, idr_cache_ctor);
+- return 0;
++ idr_layer_cache = kmem_cache_create("idr_layer_cache",
++ sizeof(struct idr_layer), 0, SLAB_PANIC,
++ idr_cache_ctor);
+ }
+
+ /**
+@@ -602,7 +601,6 @@ static int init_id_cache(void)
+ */
+ void idr_init(struct idr *idp)
+ {
+- init_id_cache();
+ memset(idp, 0, sizeof(struct idr));
+ spin_lock_init(&idp->lock);
+ }
+diff --git a/lib/inflate.c b/lib/inflate.c
+index 845f91d..9762294 100644
+--- a/lib/inflate.c
++++ b/lib/inflate.c
+@@ -811,6 +811,9 @@ DEBG("<dyn");
+ ll = malloc(sizeof(*ll) * (286+30)); /* literal/length and distance code lengths */
+ #endif
+
++ if (ll == NULL)
++ return 1;
++
+ /* make local bit buffer */
+ b = bb;
+ k = bk;
+diff --git a/lib/iomap.c b/lib/iomap.c
+index dd6ca48..37a3ea4 100644
+--- a/lib/iomap.c
++++ b/lib/iomap.c
+@@ -257,7 +257,7 @@ EXPORT_SYMBOL(ioport_unmap);
+ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+ {
+ resource_size_t start = pci_resource_start(dev, bar);
+- unsigned long len = pci_resource_len(dev, bar);
++ resource_size_t len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (!len || !start)
diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c
index 812dbf0..cd3e825 100644
--- a/lib/kernel_lock.c
@@ -839772,8 +1130614,399 @@
/*
* The 'big kernel semaphore'
+diff --git a/lib/klist.c b/lib/klist.c
+index 120bd17..cca37f9 100644
+--- a/lib/klist.c
++++ b/lib/klist.c
+@@ -1,38 +1,37 @@
+ /*
+- * klist.c - Routines for manipulating klists.
++ * klist.c - Routines for manipulating klists.
+ *
++ * Copyright (C) 2005 Patrick Mochel
+ *
+- * This klist interface provides a couple of structures that wrap around
+- * struct list_head to provide explicit list "head" (struct klist) and
+- * list "node" (struct klist_node) objects. For struct klist, a spinlock
+- * is included that protects access to the actual list itself. struct
+- * klist_node provides a pointer to the klist that owns it and a kref
+- * reference count that indicates the number of current users of that node
+- * in the list.
++ * This file is released under the GPL v2.
+ *
+- * The entire point is to provide an interface for iterating over a list
+- * that is safe and allows for modification of the list during the
+- * iteration (e.g. insertion and removal), including modification of the
+- * current node on the list.
++ * This klist interface provides a couple of structures that wrap around
++ * struct list_head to provide explicit list "head" (struct klist) and list
++ * "node" (struct klist_node) objects. For struct klist, a spinlock is
++ * included that protects access to the actual list itself. struct
++ * klist_node provides a pointer to the klist that owns it and a kref
++ * reference count that indicates the number of current users of that node
++ * in the list.
+ *
+- * It works using a 3rd object type - struct klist_iter - that is declared
+- * and initialized before an iteration. klist_next() is used to acquire the
+- * next element in the list. It returns NULL if there are no more items.
+- * Internally, that routine takes the klist's lock, decrements the reference
+- * count of the previous klist_node and increments the count of the next
+- * klist_node. It then drops the lock and returns.
++ * The entire point is to provide an interface for iterating over a list
++ * that is safe and allows for modification of the list during the
++ * iteration (e.g. insertion and removal), including modification of the
++ * current node on the list.
+ *
+- * There are primitives for adding and removing nodes to/from a klist.
+- * When deleting, klist_del() will simply decrement the reference count.
+- * Only when the count goes to 0 is the node removed from the list.
+- * klist_remove() will try to delete the node from the list and block
+- * until it is actually removed. This is useful for objects (like devices)
+- * that have been removed from the system and must be freed (but must wait
+- * until all accessors have finished).
++ * It works using a 3rd object type - struct klist_iter - that is declared
++ * and initialized before an iteration. klist_next() is used to acquire the
++ * next element in the list. It returns NULL if there are no more items.
++ * Internally, that routine takes the klist's lock, decrements the
++ * reference count of the previous klist_node and increments the count of
++ * the next klist_node. It then drops the lock and returns.
+ *
+- * Copyright (C) 2005 Patrick Mochel
+- *
+- * This file is released under the GPL v2.
++ * There are primitives for adding and removing nodes to/from a klist.
++ * When deleting, klist_del() will simply decrement the reference count.
++ * Only when the count goes to 0 is the node removed from the list.
++ * klist_remove() will try to delete the node from the list and block until
++ * it is actually removed. This is useful for objects (like devices) that
++ * have been removed from the system and must be freed (but must wait until
++ * all accessors have finished).
+ */
+
+ #include <linux/klist.h>
+@@ -40,10 +39,10 @@
+
+
+ /**
+- * klist_init - Initialize a klist structure.
+- * @k: The klist we're initializing.
+- * @get: The get function for the embedding object (NULL if none)
+- * @put: The put function for the embedding object (NULL if none)
++ * klist_init - Initialize a klist structure.
++ * @k: The klist we're initializing.
++ * @get: The get function for the embedding object (NULL if none)
++ * @put: The put function for the embedding object (NULL if none)
+ *
+ * Initialises the klist structure. If the klist_node structures are
+ * going to be embedded in refcounted objects (necessary for safe
+@@ -51,8 +50,7 @@
+ * functions that take and release references on the embedding
+ * objects.
+ */
+-
+-void klist_init(struct klist * k, void (*get)(struct klist_node *),
++void klist_init(struct klist *k, void (*get)(struct klist_node *),
+ void (*put)(struct klist_node *))
+ {
+ INIT_LIST_HEAD(&k->k_list);
+@@ -60,26 +58,23 @@ void klist_init(struct klist * k, void (*get)(struct klist_node *),
+ k->get = get;
+ k->put = put;
+ }
+-
+ EXPORT_SYMBOL_GPL(klist_init);
+
+-
+-static void add_head(struct klist * k, struct klist_node * n)
++static void add_head(struct klist *k, struct klist_node *n)
+ {
+ spin_lock(&k->k_lock);
+ list_add(&n->n_node, &k->k_list);
+ spin_unlock(&k->k_lock);
+ }
+
+-static void add_tail(struct klist * k, struct klist_node * n)
++static void add_tail(struct klist *k, struct klist_node *n)
+ {
+ spin_lock(&k->k_lock);
+ list_add_tail(&n->n_node, &k->k_list);
+ spin_unlock(&k->k_lock);
+ }
+
+-
+-static void klist_node_init(struct klist * k, struct klist_node * n)
++static void klist_node_init(struct klist *k, struct klist_node *n)
+ {
+ INIT_LIST_HEAD(&n->n_node);
+ init_completion(&n->n_removed);
+@@ -89,60 +84,83 @@ static void klist_node_init(struct klist * k, struct klist_node * n)
+ k->get(n);
+ }
+
+-
+ /**
+- * klist_add_head - Initialize a klist_node and add it to front.
+- * @n: node we're adding.
+- * @k: klist it's going on.
++ * klist_add_head - Initialize a klist_node and add it to front.
++ * @n: node we're adding.
++ * @k: klist it's going on.
+ */
+-
+-void klist_add_head(struct klist_node * n, struct klist * k)
++void klist_add_head(struct klist_node *n, struct klist *k)
+ {
+ klist_node_init(k, n);
+ add_head(k, n);
+ }
+-
+ EXPORT_SYMBOL_GPL(klist_add_head);
+
+-
+ /**
+- * klist_add_tail - Initialize a klist_node and add it to back.
+- * @n: node we're adding.
+- * @k: klist it's going on.
++ * klist_add_tail - Initialize a klist_node and add it to back.
++ * @n: node we're adding.
++ * @k: klist it's going on.
+ */
+-
+-void klist_add_tail(struct klist_node * n, struct klist * k)
++void klist_add_tail(struct klist_node *n, struct klist *k)
+ {
+ klist_node_init(k, n);
+ add_tail(k, n);
+ }
+-
+ EXPORT_SYMBOL_GPL(klist_add_tail);
+
++/**
++ * klist_add_after - Init a klist_node and add it after an existing node
++ * @n: node we're adding.
++ * @pos: node to put @n after
++ */
++void klist_add_after(struct klist_node *n, struct klist_node *pos)
++{
++ struct klist *k = pos->n_klist;
++
++ klist_node_init(k, n);
++ spin_lock(&k->k_lock);
++ list_add(&n->n_node, &pos->n_node);
++ spin_unlock(&k->k_lock);
++}
++EXPORT_SYMBOL_GPL(klist_add_after);
++
++/**
++ * klist_add_before - Init a klist_node and add it before an existing node
++ * @n: node we're adding.
++ * @pos: node to put @n after
++ */
++void klist_add_before(struct klist_node *n, struct klist_node *pos)
++{
++ struct klist *k = pos->n_klist;
++
++ klist_node_init(k, n);
++ spin_lock(&k->k_lock);
++ list_add_tail(&n->n_node, &pos->n_node);
++ spin_unlock(&k->k_lock);
++}
++EXPORT_SYMBOL_GPL(klist_add_before);
+
+-static void klist_release(struct kref * kref)
++static void klist_release(struct kref *kref)
+ {
+- struct klist_node * n = container_of(kref, struct klist_node, n_ref);
++ struct klist_node *n = container_of(kref, struct klist_node, n_ref);
+
+ list_del(&n->n_node);
+ complete(&n->n_removed);
+ n->n_klist = NULL;
+ }
+
+-static int klist_dec_and_del(struct klist_node * n)
++static int klist_dec_and_del(struct klist_node *n)
+ {
+ return kref_put(&n->n_ref, klist_release);
+ }
+
+-
+ /**
+- * klist_del - Decrement the reference count of node and try to remove.
+- * @n: node we're deleting.
++ * klist_del - Decrement the reference count of node and try to remove.
++ * @n: node we're deleting.
+ */
+-
+-void klist_del(struct klist_node * n)
++void klist_del(struct klist_node *n)
+ {
+- struct klist * k = n->n_klist;
++ struct klist *k = n->n_klist;
+ void (*put)(struct klist_node *) = k->put;
+
+ spin_lock(&k->k_lock);
+@@ -152,48 +170,40 @@ void klist_del(struct klist_node * n)
+ if (put)
+ put(n);
+ }
+-
+ EXPORT_SYMBOL_GPL(klist_del);
+
+-
+ /**
+- * klist_remove - Decrement the refcount of node and wait for it to go away.
+- * @n: node we're removing.
++ * klist_remove - Decrement the refcount of node and wait for it to go away.
++ * @n: node we're removing.
+ */
+-
+-void klist_remove(struct klist_node * n)
++void klist_remove(struct klist_node *n)
+ {
+ klist_del(n);
+ wait_for_completion(&n->n_removed);
+ }
+-
+ EXPORT_SYMBOL_GPL(klist_remove);
+
+-
+ /**
+- * klist_node_attached - Say whether a node is bound to a list or not.
+- * @n: Node that we're testing.
++ * klist_node_attached - Say whether a node is bound to a list or not.
++ * @n: Node that we're testing.
+ */
+-
+-int klist_node_attached(struct klist_node * n)
++int klist_node_attached(struct klist_node *n)
+ {
+ return (n->n_klist != NULL);
+ }
+-
+ EXPORT_SYMBOL_GPL(klist_node_attached);
+
+-
+ /**
+- * klist_iter_init_node - Initialize a klist_iter structure.
+- * @k: klist we're iterating.
+- * @i: klist_iter we're filling.
+- * @n: node to start with.
++ * klist_iter_init_node - Initialize a klist_iter structure.
++ * @k: klist we're iterating.
++ * @i: klist_iter we're filling.
++ * @n: node to start with.
+ *
+- * Similar to klist_iter_init(), but starts the action off with @n,
+- * instead of with the list head.
++ * Similar to klist_iter_init(), but starts the action off with @n,
++ * instead of with the list head.
+ */
+-
+-void klist_iter_init_node(struct klist * k, struct klist_iter * i, struct klist_node * n)
++void klist_iter_init_node(struct klist *k, struct klist_iter *i,
++ struct klist_node *n)
+ {
+ i->i_klist = k;
+ i->i_head = &k->k_list;
+@@ -201,66 +211,56 @@ void klist_iter_init_node(struct klist * k, struct klist_iter * i, struct klist_
+ if (n)
+ kref_get(&n->n_ref);
+ }
+-
+ EXPORT_SYMBOL_GPL(klist_iter_init_node);
+
+-
+ /**
+- * klist_iter_init - Iniitalize a klist_iter structure.
+- * @k: klist we're iterating.
+- * @i: klist_iter structure we're filling.
++ * klist_iter_init - Iniitalize a klist_iter structure.
++ * @k: klist we're iterating.
++ * @i: klist_iter structure we're filling.
+ *
+- * Similar to klist_iter_init_node(), but start with the list head.
++ * Similar to klist_iter_init_node(), but start with the list head.
+ */
+-
+-void klist_iter_init(struct klist * k, struct klist_iter * i)
++void klist_iter_init(struct klist *k, struct klist_iter *i)
+ {
+ klist_iter_init_node(k, i, NULL);
+ }
+-
+ EXPORT_SYMBOL_GPL(klist_iter_init);
+
+-
+ /**
+- * klist_iter_exit - Finish a list iteration.
+- * @i: Iterator structure.
++ * klist_iter_exit - Finish a list iteration.
++ * @i: Iterator structure.
+ *
+- * Must be called when done iterating over list, as it decrements the
+- * refcount of the current node. Necessary in case iteration exited before
+- * the end of the list was reached, and always good form.
++ * Must be called when done iterating over list, as it decrements the
++ * refcount of the current node. Necessary in case iteration exited before
++ * the end of the list was reached, and always good form.
+ */
+-
+-void klist_iter_exit(struct klist_iter * i)
++void klist_iter_exit(struct klist_iter *i)
+ {
+ if (i->i_cur) {
+ klist_del(i->i_cur);
+ i->i_cur = NULL;
+ }
+ }
+-
+ EXPORT_SYMBOL_GPL(klist_iter_exit);
+
+-
+-static struct klist_node * to_klist_node(struct list_head * n)
++static struct klist_node *to_klist_node(struct list_head *n)
+ {
+ return container_of(n, struct klist_node, n_node);
+ }
+
+-
+ /**
+- * klist_next - Ante up next node in list.
+- * @i: Iterator structure.
++ * klist_next - Ante up next node in list.
++ * @i: Iterator structure.
+ *
+- * First grab list lock. Decrement the reference count of the previous
+- * node, if there was one. Grab the next node, increment its reference
+- * count, drop the lock, and return that next node.
++ * First grab list lock. Decrement the reference count of the previous
++ * node, if there was one. Grab the next node, increment its reference
++ * count, drop the lock, and return that next node.
+ */
+-
+-struct klist_node * klist_next(struct klist_iter * i)
++struct klist_node *klist_next(struct klist_iter *i)
+ {
+- struct list_head * next;
+- struct klist_node * lnode = i->i_cur;
+- struct klist_node * knode = NULL;
++ struct list_head *next;
++ struct klist_node *lnode = i->i_cur;
++ struct klist_node *knode = NULL;
+ void (*put)(struct klist_node *) = i->i_klist->put;
+
+ spin_lock(&i->i_klist->k_lock);
+@@ -281,7 +281,4 @@ struct klist_node * klist_next(struct klist_iter * i)
+ put(lnode);
+ return knode;
+ }
+-
+ EXPORT_SYMBOL_GPL(klist_next);
+-
+-
diff --git a/lib/kobject.c b/lib/kobject.c
-index 0d03252..2c64903 100644
+index 0d03252..718e510 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -58,11 +58,6 @@ static int create_dir(struct kobject *kobj)
@@ -839788,7 +1131021,103 @@
static int get_kobj_path_length(struct kobject *kobj)
{
int length = 1;
-@@ -592,8 +587,15 @@ static void kobject_release(struct kref *kref)
+@@ -95,7 +90,7 @@ static void fill_kobj_path(struct kobject *kobj, char *path, int length)
+ }
+
+ pr_debug("kobject: '%s' (%p): %s: path = '%s'\n", kobject_name(kobj),
+- kobj, __FUNCTION__, path);
++ kobj, __func__, path);
+ }
+
+ /**
+@@ -186,7 +181,7 @@ static int kobject_add_internal(struct kobject *kobj)
+ }
+
+ pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'\n",
+- kobject_name(kobj), kobj, __FUNCTION__,
++ kobject_name(kobj), kobj, __func__,
+ parent ? kobject_name(parent) : "<NULL>",
+ kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>");
+
+@@ -201,10 +196,10 @@ static int kobject_add_internal(struct kobject *kobj)
+ printk(KERN_ERR "%s failed for %s with "
+ "-EEXIST, don't try to register things with "
+ "the same name in the same directory.\n",
+- __FUNCTION__, kobject_name(kobj));
++ __func__, kobject_name(kobj));
+ else
+ printk(KERN_ERR "%s failed for %s (%d)\n",
+- __FUNCTION__, kobject_name(kobj), error);
++ __func__, kobject_name(kobj), error);
+ dump_stack();
+ } else
+ kobj->state_in_sysfs = 1;
+@@ -221,21 +216,12 @@ static int kobject_add_internal(struct kobject *kobj)
+ static int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
+ va_list vargs)
+ {
+- va_list aq;
+- char *name;
+-
+- va_copy(aq, vargs);
+- name = kvasprintf(GFP_KERNEL, fmt, vargs);
+- va_end(aq);
+-
+- if (!name)
+- return -ENOMEM;
+-
+ /* Free the old name, if necessary. */
+ kfree(kobj->name);
+
+- /* Now, set the new name */
+- kobj->name = name;
++ kobj->name = kvasprintf(GFP_KERNEL, fmt, vargs);
++ if (!kobj->name)
++ return -ENOMEM;
+
+ return 0;
+ }
+@@ -251,12 +237,12 @@ static int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
+ */
+ int kobject_set_name(struct kobject *kobj, const char *fmt, ...)
+ {
+- va_list args;
++ va_list vargs;
+ int retval;
+
+- va_start(args, fmt);
+- retval = kobject_set_name_vargs(kobj, fmt, args);
+- va_end(args);
++ va_start(vargs, fmt);
++ retval = kobject_set_name_vargs(kobj, fmt, vargs);
++ va_end(vargs);
+
+ return retval;
+ }
+@@ -306,12 +292,9 @@ EXPORT_SYMBOL(kobject_init);
+ static int kobject_add_varg(struct kobject *kobj, struct kobject *parent,
+ const char *fmt, va_list vargs)
+ {
+- va_list aq;
+ int retval;
+
+- va_copy(aq, vargs);
+- retval = kobject_set_name_vargs(kobj, fmt, aq);
+- va_end(aq);
++ retval = kobject_set_name_vargs(kobj, fmt, vargs);
+ if (retval) {
+ printk(KERN_ERR "kobject: can not set name properly!\n");
+ return retval;
+@@ -545,7 +528,7 @@ static void kobject_cleanup(struct kobject *kobj)
+ const char *name = kobj->name;
+
+ pr_debug("kobject: '%s' (%p): %s\n",
+- kobject_name(kobj), kobj, __FUNCTION__);
++ kobject_name(kobj), kobj, __func__);
+
+ if (t && !t->release)
+ pr_debug("kobject: '%s' (%p): does not have a release() "
+@@ -592,13 +575,20 @@ static void kobject_release(struct kref *kref)
*/
void kobject_put(struct kobject *kobj)
{
@@ -839805,7 +1131134,22 @@
}
static void dynamic_kobj_release(struct kobject *kobj)
-@@ -745,12 +747,11 @@ void kset_unregister(struct kset *k)
+ {
+- pr_debug("kobject: (%p): %s\n", kobj, __FUNCTION__);
++ pr_debug("kobject: (%p): %s\n", kobj, __func__);
+ kfree(kobj);
+ }
+
+@@ -655,7 +645,7 @@ struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
+ retval = kobject_add(kobj, parent, "%s", name);
+ if (retval) {
+ printk(KERN_WARNING "%s: kobject_add error: %d\n",
+- __FUNCTION__, retval);
++ __func__, retval);
+ kobject_put(kobj);
+ kobj = NULL;
+ }
+@@ -745,12 +735,11 @@ void kset_unregister(struct kset *k)
*/
struct kobject *kset_find_obj(struct kset *kset, const char *name)
{
@@ -839820,8 +1131164,17 @@
if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
ret = kobject_get(k);
break;
+@@ -764,7 +753,7 @@ static void kset_release(struct kobject *kobj)
+ {
+ struct kset *kset = container_of(kobj, struct kset, kobj);
+ pr_debug("kobject: '%s' (%p): %s\n",
+- kobject_name(kobj), kobj, __FUNCTION__);
++ kobject_name(kobj), kobj, __func__);
+ kfree(kset);
+ }
+
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
-index 5b6d7f6..9fb6b86 100644
+index 5b6d7f6..2fa545a 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -15,11 +15,13 @@
@@ -839840,12 +1131193,57 @@
#include <net/sock.h>
+@@ -99,7 +101,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
+ int retval = 0;
+
+ pr_debug("kobject: '%s' (%p): %s\n",
+- kobject_name(kobj), kobj, __FUNCTION__);
++ kobject_name(kobj), kobj, __func__);
+
+ /* search the kset we belong to */
+ top_kobj = kobj;
+@@ -109,7 +111,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
+ if (!top_kobj->kset) {
+ pr_debug("kobject: '%s' (%p): %s: attempted to send uevent "
+ "without kset!\n", kobject_name(kobj), kobj,
+- __FUNCTION__);
++ __func__);
+ return -EINVAL;
+ }
+
+@@ -121,7 +123,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
+ if (!uevent_ops->filter(kset, kobj)) {
+ pr_debug("kobject: '%s' (%p): %s: filter function "
+ "caused the event to drop!\n",
+- kobject_name(kobj), kobj, __FUNCTION__);
++ kobject_name(kobj), kobj, __func__);
+ return 0;
+ }
+
+@@ -133,7 +135,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
+ if (!subsystem) {
+ pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the "
+ "event to drop!\n", kobject_name(kobj), kobj,
+- __FUNCTION__);
++ __func__);
+ return 0;
+ }
+
+@@ -175,7 +177,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
+ if (retval) {
+ pr_debug("kobject: '%s' (%p): %s: uevent() returned "
+ "%d\n", kobject_name(kobj), kobj,
+- __FUNCTION__, retval);
++ __func__, retval);
+ goto exit;
+ }
+ }
diff --git a/lib/lmb.c b/lib/lmb.c
new file mode 100644
-index 0000000..207147a
+index 0000000..83287d3
--- /dev/null
+++ b/lib/lmb.c
-@@ -0,0 +1,428 @@
+@@ -0,0 +1,509 @@
+/*
+ * Procedures for maintaining information about logical memory blocks.
+ *
@@ -839894,14 +1131292,13 @@
+#endif /* DEBUG */
+}
+
-+static unsigned long __init lmb_addrs_overlap(u64 base1, u64 size1,
-+ u64 base2, u64 size2)
++static unsigned long 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)
++static long lmb_addrs_adjacent(u64 base1, u64 size1, u64 base2, u64 size2)
+{
+ if (base2 == base1 + size1)
+ return 1;
@@ -839911,7 +1131308,7 @@
+ return 0;
+}
+
-+static long __init lmb_regions_adjacent(struct lmb_region *rgn,
++static long lmb_regions_adjacent(struct lmb_region *rgn,
+ unsigned long r1, unsigned long r2)
+{
+ u64 base1 = rgn->region[r1].base;
@@ -839922,7 +1131319,7 @@
+ return lmb_addrs_adjacent(base1, size1, base2, size2);
+}
+
-+static void __init lmb_remove_region(struct lmb_region *rgn, unsigned long r)
++static void lmb_remove_region(struct lmb_region *rgn, unsigned long r)
+{
+ unsigned long i;
+
@@ -839934,7 +1131331,7 @@
+}
+
+/* Assumption: base addr of region 1 < base addr of region 2 */
-+static void __init lmb_coalesce_regions(struct lmb_region *rgn,
++static void lmb_coalesce_regions(struct lmb_region *rgn,
+ unsigned long r1, unsigned long r2)
+{
+ rgn->region[r1].size += rgn->region[r2].size;
@@ -839966,7 +1131363,7 @@
+ lmb.memory.size += lmb.memory.region[i].size;
+}
+
-+static long __init lmb_add_region(struct lmb_region *rgn, u64 base, u64 size)
++static long lmb_add_region(struct lmb_region *rgn, u64 base, u64 size)
+{
+ unsigned long coalesced = 0;
+ long adjacent, i;
@@ -840030,7 +1131427,7 @@
+ return 0;
+}
+
-+long __init lmb_add(u64 base, u64 size)
++long lmb_add(u64 base, u64 size)
+{
+ struct lmb_region *_rgn = &lmb.memory;
+
@@ -840042,6 +1131439,55 @@
+
+}
+
++long lmb_remove(u64 base, u64 size)
++{
++ struct lmb_region *rgn = &(lmb.memory);
++ u64 rgnbegin, rgnend;
++ u64 end = base + size;
++ int i;
++
++ rgnbegin = rgnend = 0; /* supress gcc warnings */
++
++ /* Find the region where (base, size) belongs to */
++ for (i=0; i < rgn->cnt; i++) {
++ rgnbegin = rgn->region[i].base;
++ rgnend = rgnbegin + rgn->region[i].size;
++
++ if ((rgnbegin <= base) && (end <= rgnend))
++ break;
++ }
++
++ /* Didn't find the region */
++ if (i == rgn->cnt)
++ return -1;
++
++ /* Check to see if we are removing entire region */
++ if ((rgnbegin == base) && (rgnend == end)) {
++ lmb_remove_region(rgn, i);
++ return 0;
++ }
++
++ /* Check to see if region is matching at the front */
++ if (rgnbegin == base) {
++ rgn->region[i].base = end;
++ rgn->region[i].size -= size;
++ return 0;
++ }
++
++ /* Check to see if the region is matching at the end */
++ if (rgnend == end) {
++ rgn->region[i].size -= size;
++ return 0;
++ }
++
++ /*
++ * We need to split the entry - adjust the current one to the
++ * beginging of the hole and add the region after hole.
++ */
++ rgn->region[i].size = base - rgn->region[i].base;
++ return lmb_add_region(rgn, end, rgnend - end);
++}
++
+long __init lmb_reserve(u64 base, u64 size)
+{
+ struct lmb_region *_rgn = &lmb.reserved;
@@ -840274,6 +1131720,39 @@
+ }
+ return 0;
+}
++
++/*
++ * Given a <base, len>, find which memory regions belong to this range.
++ * Adjust the request and return a contiguous chunk.
++ */
++int lmb_find(struct lmb_property *res)
++{
++ int i;
++ u64 rstart, rend;
++
++ rstart = res->base;
++ rend = rstart + res->size - 1;
++
++ for (i = 0; i < lmb.memory.cnt; i++) {
++ u64 start = lmb.memory.region[i].base;
++ u64 end = start + lmb.memory.region[i].size - 1;
++
++ if (start > rend)
++ return -1;
++
++ if ((end >= rstart) && (start < rend)) {
++ /* adjust the request */
++ if (rstart < start)
++ rstart = start;
++ if (rend > end)
++ rend = end;
++ res->base = rstart;
++ res->size = rend - rstart + 1;
++ return 0;
++ }
++ }
++ return -1;
++}
diff --git a/lib/pcounter.c b/lib/pcounter.c
deleted file mode 100644
index 9b56807..0000000
@@ -840338,6 +1131817,165 @@
-}
-EXPORT_SYMBOL_GPL(pcounter_free);
-
+diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c
+index 393a0e9..1191744 100644
+--- a/lib/percpu_counter.c
++++ b/lib/percpu_counter.c
+@@ -102,6 +102,7 @@ void percpu_counter_destroy(struct percpu_counter *fbc)
+ return;
+
+ free_percpu(fbc->counters);
++ fbc->counters = NULL;
+ #ifdef CONFIG_HOTPLUG_CPU
+ mutex_lock(&percpu_counters_lock);
+ list_del(&fbc->list);
+diff --git a/lib/proportions.c b/lib/proportions.c
+index 9508d9a..4f387a6 100644
+--- a/lib/proportions.c
++++ b/lib/proportions.c
+@@ -73,12 +73,6 @@
+ #include <linux/proportions.h>
+ #include <linux/rcupdate.h>
+
+-/*
+- * Limit the time part in order to ensure there are some bits left for the
+- * cycle counter.
+- */
+-#define PROP_MAX_SHIFT (3*BITS_PER_LONG/4)
+-
+ int prop_descriptor_init(struct prop_descriptor *pd, int shift)
+ {
+ int err;
+@@ -268,6 +262,38 @@ void __prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl)
+ }
+
+ /*
++ * identical to __prop_inc_percpu, except that it limits this pl's fraction to
++ * @frac/PROP_FRAC_BASE by ignoring events when this limit has been exceeded.
++ */
++void __prop_inc_percpu_max(struct prop_descriptor *pd,
++ struct prop_local_percpu *pl, long frac)
++{
++ struct prop_global *pg = prop_get_global(pd);
++
++ prop_norm_percpu(pg, pl);
++
++ if (unlikely(frac != PROP_FRAC_BASE)) {
++ unsigned long period_2 = 1UL << (pg->shift - 1);
++ unsigned long counter_mask = period_2 - 1;
++ unsigned long global_count;
++ long numerator, denominator;
++
++ numerator = percpu_counter_read_positive(&pl->events);
++ global_count = percpu_counter_read(&pg->events);
++ denominator = period_2 + (global_count & counter_mask);
++
++ if (numerator > ((denominator * frac) >> PROP_FRAC_SHIFT))
++ goto out_put;
++ }
++
++ percpu_counter_add(&pl->events, 1);
++ percpu_counter_add(&pg->events, 1);
++
++out_put:
++ prop_put_global(pd, pg);
++}
++
++/*
+ * Obtain a fraction of this proportion
+ *
+ * p_{j} = x_{j} / (period/2 + t % period/2)
+diff --git a/lib/radix-tree.c b/lib/radix-tree.c
+index 65f0e75..bd52171 100644
+--- a/lib/radix-tree.c
++++ b/lib/radix-tree.c
+@@ -114,8 +114,7 @@ radix_tree_node_alloc(struct radix_tree_root *root)
+ }
+ }
+ if (ret == NULL)
+- ret = kmem_cache_alloc(radix_tree_node_cachep,
+- set_migrateflags(gfp_mask, __GFP_RECLAIMABLE));
++ ret = kmem_cache_alloc(radix_tree_node_cachep, gfp_mask);
+
+ BUG_ON(radix_tree_is_indirect_ptr(ret));
+ return ret;
+@@ -150,8 +149,7 @@ int radix_tree_preload(gfp_t gfp_mask)
+ rtp = &__get_cpu_var(radix_tree_preloads);
+ while (rtp->nr < ARRAY_SIZE(rtp->nodes)) {
+ preempt_enable();
+- node = kmem_cache_alloc(radix_tree_node_cachep,
+- set_migrateflags(gfp_mask, __GFP_RECLAIMABLE));
++ node = kmem_cache_alloc(radix_tree_node_cachep, gfp_mask);
+ if (node == NULL)
+ goto out;
+ preempt_disable();
+@@ -1098,7 +1096,8 @@ void __init radix_tree_init(void)
+ {
+ radix_tree_node_cachep = kmem_cache_create("radix_tree_node",
+ sizeof(struct radix_tree_node), 0,
+- SLAB_PANIC, radix_tree_node_ctor);
++ SLAB_PANIC | SLAB_RECLAIM_ACCOUNT,
++ radix_tree_node_ctor);
+ radix_tree_init_maxindex();
+ hotcpu_notifier(radix_tree_callback, 0);
+ }
+diff --git a/lib/ratelimit.c b/lib/ratelimit.c
+new file mode 100644
+index 0000000..485e304
+--- /dev/null
++++ b/lib/ratelimit.c
+@@ -0,0 +1,51 @@
++/*
++ * ratelimit.c - Do something with rate limit.
++ *
++ * Isolated from kernel/printk.c by Dave Young <hidave.darkstar at gmail.com>
++ *
++ * This file is released under the GPLv2.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/jiffies.h>
++#include <linux/module.h>
++
++/*
++ * __ratelimit - rate limiting
++ * @ratelimit_jiffies: minimum time in jiffies between two callbacks
++ * @ratelimit_burst: number of callbacks we do before ratelimiting
++ *
++ * This enforces a rate limit: not more than @ratelimit_burst callbacks
++ * in every ratelimit_jiffies
++ */
++int __ratelimit(int ratelimit_jiffies, int ratelimit_burst)
++{
++ static DEFINE_SPINLOCK(ratelimit_lock);
++ static unsigned toks = 10 * 5 * HZ;
++ static unsigned long last_msg;
++ static int missed;
++ unsigned long flags;
++ unsigned long now = jiffies;
++
++ spin_lock_irqsave(&ratelimit_lock, flags);
++ toks += now - last_msg;
++ last_msg = now;
++ if (toks > (ratelimit_burst * ratelimit_jiffies))
++ toks = ratelimit_burst * ratelimit_jiffies;
++ if (toks >= ratelimit_jiffies) {
++ int lost = missed;
++
++ missed = 0;
++ toks -= ratelimit_jiffies;
++ spin_unlock_irqrestore(&ratelimit_lock, flags);
++ if (lost)
++ printk(KERN_WARNING "%s: %d messages suppressed\n",
++ __func__, lost);
++ return 1;
++ }
++ missed++;
++ spin_unlock_irqrestore(&ratelimit_lock, flags);
++ return 0;
++}
++EXPORT_SYMBOL(__ratelimit);
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
@@ -840594,169 +1132232,5210 @@
- 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;
+- /*
+- * 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/lib/swiotlb.c b/lib/swiotlb.c
+index 0259228..d568894 100644
+--- a/lib/swiotlb.c
++++ b/lib/swiotlb.c
+@@ -31,6 +31,7 @@
+
+ #include <linux/init.h>
+ #include <linux/bootmem.h>
++#include <linux/iommu-helper.h>
+
+ #define OFFSET(val,align) ((unsigned long) \
+ ( (val) & ( (align) - 1)))
+@@ -282,15 +283,6 @@ address_needs_mapping(struct device *hwdev, dma_addr_t addr)
+ return (addr & ~mask) != 0;
+ }
+
+-static inline unsigned int is_span_boundary(unsigned int index,
+- unsigned int nslots,
+- unsigned long offset_slots,
+- unsigned long max_slots)
+-{
+- unsigned long offset = (offset_slots + index) & (max_slots - 1);
+- return offset + nslots > max_slots;
+-}
+-
+ /*
+ * Allocates bounce buffer and returns its kernel virtual address.
+ */
+@@ -331,56 +323,53 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir)
+ * request and allocate a buffer from that IO TLB pool.
+ */
+ spin_lock_irqsave(&io_tlb_lock, flags);
+- {
+- index = ALIGN(io_tlb_index, stride);
+- if (index >= io_tlb_nslabs)
+- index = 0;
+- wrap = index;
+-
+- do {
+- while (is_span_boundary(index, nslots, offset_slots,
+- max_slots)) {
+- index += stride;
+- if (index >= io_tlb_nslabs)
+- index = 0;
+- if (index == wrap)
+- goto not_found;
+- }
+-
+- /*
+- * If we find a slot that indicates we have 'nslots'
+- * number of contiguous buffers, we allocate the
+- * buffers from that slot and mark the entries as '0'
+- * indicating unavailable.
+- */
+- if (io_tlb_list[index] >= nslots) {
+- int count = 0;
+-
+- for (i = index; i < (int) (index + nslots); i++)
+- io_tlb_list[i] = 0;
+- for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE -1) && io_tlb_list[i]; i--)
+- io_tlb_list[i] = ++count;
+- dma_addr = io_tlb_start + (index << IO_TLB_SHIFT);
+-
+- /*
+- * Update the indices to avoid searching in
+- * the next round.
+- */
+- io_tlb_index = ((index + nslots) < io_tlb_nslabs
+- ? (index + nslots) : 0);
+-
+- goto found;
+- }
++ index = ALIGN(io_tlb_index, stride);
++ if (index >= io_tlb_nslabs)
++ index = 0;
++ wrap = index;
++
++ do {
++ while (iommu_is_span_boundary(index, nslots, offset_slots,
++ max_slots)) {
+ index += stride;
+ if (index >= io_tlb_nslabs)
+ index = 0;
+- } while (index != wrap);
++ if (index == wrap)
++ goto not_found;
++ }
+
+- not_found:
+- spin_unlock_irqrestore(&io_tlb_lock, flags);
+- return NULL;
+- }
+- found:
++ /*
++ * If we find a slot that indicates we have 'nslots' number of
++ * contiguous buffers, we allocate the buffers from that slot
++ * and mark the entries as '0' indicating unavailable.
++ */
++ if (io_tlb_list[index] >= nslots) {
++ int count = 0;
++
++ for (i = index; i < (int) (index + nslots); i++)
++ io_tlb_list[i] = 0;
++ for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE - 1) && io_tlb_list[i]; i--)
++ io_tlb_list[i] = ++count;
++ dma_addr = io_tlb_start + (index << IO_TLB_SHIFT);
++
++ /*
++ * Update the indices to avoid searching in the next
++ * round.
++ */
++ io_tlb_index = ((index + nslots) < io_tlb_nslabs
++ ? (index + nslots) : 0);
++
++ goto found;
++ }
++ index += stride;
++ if (index >= io_tlb_nslabs)
++ index = 0;
++ } while (index != wrap);
++
++not_found:
++ spin_unlock_irqrestore(&io_tlb_lock, flags);
++ return NULL;
++found:
+ spin_unlock_irqrestore(&io_tlb_lock, flags);
+
+ /*
+@@ -566,7 +555,8 @@ swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
+ * either swiotlb_unmap_single or swiotlb_dma_sync_single is performed.
+ */
+ dma_addr_t
+-swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
++swiotlb_map_single_attrs(struct device *hwdev, void *ptr, size_t size,
++ int dir, struct dma_attrs *attrs)
+ {
+ dma_addr_t dev_addr = virt_to_bus(ptr);
+ void *map;
+@@ -599,6 +589,13 @@ swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
+
+ return dev_addr;
+ }
++EXPORT_SYMBOL(swiotlb_map_single_attrs);
++
++dma_addr_t
++swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
++{
++ return swiotlb_map_single_attrs(hwdev, ptr, size, dir, NULL);
++}
+
+ /*
+ * Unmap a single streaming mode DMA translation. The dma_addr and size must
+@@ -609,8 +606,8 @@ swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
+ * whatever the device wrote there.
+ */
+ void
+-swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, size_t size,
+- int dir)
++swiotlb_unmap_single_attrs(struct device *hwdev, dma_addr_t dev_addr,
++ size_t size, int dir, struct dma_attrs *attrs)
+ {
+ char *dma_addr = bus_to_virt(dev_addr);
+
+@@ -620,7 +617,14 @@ swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, size_t size,
+ else if (dir == DMA_FROM_DEVICE)
+ dma_mark_clean(dma_addr, size);
+ }
++EXPORT_SYMBOL(swiotlb_unmap_single_attrs);
+
++void
++swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, size_t size,
++ int dir)
++{
++ return swiotlb_unmap_single_attrs(hwdev, dev_addr, size, dir, NULL);
++}
+ /*
+ * Make physical memory consistent for a single streaming mode DMA translation
+ * after a transfer.
+@@ -691,6 +695,8 @@ swiotlb_sync_single_range_for_device(struct device *hwdev, dma_addr_t dev_addr,
+ SYNC_FOR_DEVICE);
+ }
+
++void swiotlb_unmap_sg_attrs(struct device *, struct scatterlist *, int, int,
++ struct dma_attrs *);
+ /*
+ * Map a set of buffers described by scatterlist in streaming mode for DMA.
+ * This is the scatter-gather version of the above swiotlb_map_single
+@@ -708,8 +714,8 @@ swiotlb_sync_single_range_for_device(struct device *hwdev, dma_addr_t dev_addr,
+ * same here.
+ */
+ int
+-swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
+- int dir)
++swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
++ int dir, struct dma_attrs *attrs)
+ {
+ struct scatterlist *sg;
+ void *addr;
+@@ -727,7 +733,8 @@ swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
+ /* Don't panic here, we expect map_sg users
+ to do proper error handling. */
+ swiotlb_full(hwdev, sg->length, dir, 0);
+- swiotlb_unmap_sg(hwdev, sgl, i, dir);
++ swiotlb_unmap_sg_attrs(hwdev, sgl, i, dir,
++ attrs);
+ sgl[0].dma_length = 0;
+ return 0;
+ }
+@@ -738,14 +745,22 @@ swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
+ }
+ return nelems;
+ }
++EXPORT_SYMBOL(swiotlb_map_sg_attrs);
++
++int
++swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
++ int dir)
++{
++ return swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, NULL);
++}
+
+ /*
+ * Unmap a set of streaming mode DMA translations. Again, cpu read rules
+ * concerning calls here are the same as for swiotlb_unmap_single() above.
+ */
+ void
+-swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
+- int dir)
++swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
++ int nelems, int dir, struct dma_attrs *attrs)
+ {
+ struct scatterlist *sg;
+ int i;
+@@ -760,6 +775,14 @@ swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
+ dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
+ }
+ }
++EXPORT_SYMBOL(swiotlb_unmap_sg_attrs);
++
++void
++swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
++ int dir)
++{
++ return swiotlb_unmap_sg_attrs(hwdev, sgl, nelems, dir, NULL);
++}
+
+ /*
+ * Make physical memory consistent for a set of streaming mode DMA translations
+diff --git a/mm/Kconfig b/mm/Kconfig
+index 0016ebd..3aa819d 100644
+--- a/mm/Kconfig
++++ b/mm/Kconfig
+@@ -143,6 +143,18 @@ config MEMORY_HOTREMOVE
+ depends on MEMORY_HOTPLUG && ARCH_ENABLE_MEMORY_HOTREMOVE
+ depends on MIGRATION
+
++#
++# If we have space for more page flags then we can enable additional
++# optimizations and functionality.
++#
++# Regular Sparsemem takes page flag bits for the sectionid if it does not
++# use a virtual memmap. Disable extended page flags for 32 bit platforms
++# that require the use of a sectionid in the page flags.
++#
++config PAGEFLAGS_EXTENDED
++ def_bool y
++ depends on 64BIT || SPARSEMEM_VMEMMAP || !NUMA || !SPARSEMEM
++
+ # Heavily threaded applications may benefit from splitting the mm-wide
+ # page_table_lock, so that faults on different parts of the user address
+ # space can be handled with less contention: split it at this NR_CPUS.
+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/backing-dev.c b/mm/backing-dev.c
+index e8644b1..7c4f9e0 100644
+--- a/mm/backing-dev.c
++++ b/mm/backing-dev.c
+@@ -4,12 +4,229 @@
+ #include <linux/fs.h>
+ #include <linux/sched.h>
+ #include <linux/module.h>
++#include <linux/writeback.h>
++#include <linux/device.h>
++
++
++static struct class *bdi_class;
++
++#ifdef CONFIG_DEBUG_FS
++#include <linux/debugfs.h>
++#include <linux/seq_file.h>
++
++static struct dentry *bdi_debug_root;
++
++static void bdi_debug_init(void)
++{
++ bdi_debug_root = debugfs_create_dir("bdi", NULL);
++}
++
++static int bdi_debug_stats_show(struct seq_file *m, void *v)
++{
++ struct backing_dev_info *bdi = m->private;
++ long background_thresh;
++ long dirty_thresh;
++ long bdi_thresh;
++
++ get_dirty_limits(&background_thresh, &dirty_thresh, &bdi_thresh, bdi);
++
++#define K(x) ((x) << (PAGE_SHIFT - 10))
++ seq_printf(m,
++ "BdiWriteback: %8lu kB\n"
++ "BdiReclaimable: %8lu kB\n"
++ "BdiDirtyThresh: %8lu kB\n"
++ "DirtyThresh: %8lu kB\n"
++ "BackgroundThresh: %8lu kB\n",
++ (unsigned long) K(bdi_stat(bdi, BDI_WRITEBACK)),
++ (unsigned long) K(bdi_stat(bdi, BDI_RECLAIMABLE)),
++ K(bdi_thresh),
++ K(dirty_thresh),
++ K(background_thresh));
++#undef K
++
++ return 0;
++}
++
++static int bdi_debug_stats_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, bdi_debug_stats_show, inode->i_private);
++}
++
++static const struct file_operations bdi_debug_stats_fops = {
++ .open = bdi_debug_stats_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static void bdi_debug_register(struct backing_dev_info *bdi, const char *name)
++{
++ bdi->debug_dir = debugfs_create_dir(name, bdi_debug_root);
++ bdi->debug_stats = debugfs_create_file("stats", 0444, bdi->debug_dir,
++ bdi, &bdi_debug_stats_fops);
++}
++
++static void bdi_debug_unregister(struct backing_dev_info *bdi)
++{
++ debugfs_remove(bdi->debug_stats);
++ debugfs_remove(bdi->debug_dir);
++}
++#else
++static inline void bdi_debug_init(void)
++{
++}
++static inline void bdi_debug_register(struct backing_dev_info *bdi,
++ const char *name)
++{
++}
++static inline void bdi_debug_unregister(struct backing_dev_info *bdi)
++{
++}
++#endif
++
++static ssize_t read_ahead_kb_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct backing_dev_info *bdi = dev_get_drvdata(dev);
++ char *end;
++ unsigned long read_ahead_kb;
++ ssize_t ret = -EINVAL;
++
++ read_ahead_kb = simple_strtoul(buf, &end, 10);
++ if (*buf && (end[0] == '\0' || (end[0] == '\n' && end[1] == '\0'))) {
++ bdi->ra_pages = read_ahead_kb >> (PAGE_SHIFT - 10);
++ ret = count;
++ }
++ return ret;
++}
++
++#define K(pages) ((pages) << (PAGE_SHIFT - 10))
++
++#define BDI_SHOW(name, expr) \
++static ssize_t name##_show(struct device *dev, \
++ struct device_attribute *attr, char *page) \
++{ \
++ struct backing_dev_info *bdi = dev_get_drvdata(dev); \
++ \
++ return snprintf(page, PAGE_SIZE-1, "%lld\n", (long long)expr); \
++}
++
++BDI_SHOW(read_ahead_kb, K(bdi->ra_pages))
++
++static ssize_t min_ratio_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct backing_dev_info *bdi = dev_get_drvdata(dev);
++ char *end;
++ unsigned int ratio;
++ ssize_t ret = -EINVAL;
++
++ ratio = simple_strtoul(buf, &end, 10);
++ if (*buf && (end[0] == '\0' || (end[0] == '\n' && end[1] == '\0'))) {
++ ret = bdi_set_min_ratio(bdi, ratio);
++ if (!ret)
++ ret = count;
++ }
++ return ret;
++}
++BDI_SHOW(min_ratio, bdi->min_ratio)
++
++static ssize_t max_ratio_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct backing_dev_info *bdi = dev_get_drvdata(dev);
++ char *end;
++ unsigned int ratio;
++ ssize_t ret = -EINVAL;
++
++ ratio = simple_strtoul(buf, &end, 10);
++ if (*buf && (end[0] == '\0' || (end[0] == '\n' && end[1] == '\0'))) {
++ ret = bdi_set_max_ratio(bdi, ratio);
++ if (!ret)
++ ret = count;
++ }
++ return ret;
++}
++BDI_SHOW(max_ratio, bdi->max_ratio)
++
++#define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store)
++
++static struct device_attribute bdi_dev_attrs[] = {
++ __ATTR_RW(read_ahead_kb),
++ __ATTR_RW(min_ratio),
++ __ATTR_RW(max_ratio),
++ __ATTR_NULL,
++};
++
++static __init int bdi_class_init(void)
++{
++ bdi_class = class_create(THIS_MODULE, "bdi");
++ bdi_class->dev_attrs = bdi_dev_attrs;
++ bdi_debug_init();
++ return 0;
++}
++
++postcore_initcall(bdi_class_init);
++
++int bdi_register(struct backing_dev_info *bdi, struct device *parent,
++ const char *fmt, ...)
++{
++ char *name;
++ va_list args;
++ int ret = 0;
++ struct device *dev;
++
++ va_start(args, fmt);
++ name = kvasprintf(GFP_KERNEL, fmt, args);
++ va_end(args);
++
++ if (!name)
++ return -ENOMEM;
++
++ dev = device_create(bdi_class, parent, MKDEV(0, 0), name);
++ if (IS_ERR(dev)) {
++ ret = PTR_ERR(dev);
++ goto exit;
++ }
++
++ bdi->dev = dev;
++ dev_set_drvdata(bdi->dev, bdi);
++ bdi_debug_register(bdi, name);
++
++exit:
++ kfree(name);
++ return ret;
++}
++EXPORT_SYMBOL(bdi_register);
++
++int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev)
++{
++ return bdi_register(bdi, NULL, "%u:%u", MAJOR(dev), MINOR(dev));
++}
++EXPORT_SYMBOL(bdi_register_dev);
++
++void bdi_unregister(struct backing_dev_info *bdi)
++{
++ if (bdi->dev) {
++ bdi_debug_unregister(bdi);
++ device_unregister(bdi->dev);
++ bdi->dev = NULL;
++ }
++}
++EXPORT_SYMBOL(bdi_unregister);
+
+ int bdi_init(struct backing_dev_info *bdi)
+ {
+ int i;
+ int err;
+
++ bdi->dev = NULL;
++
++ bdi->min_ratio = 0;
++ bdi->max_ratio = 100;
++ bdi->max_prop_frac = PROP_FRAC_BASE;
++
+ for (i = 0; i < NR_BDI_STAT_ITEMS; i++) {
+ err = percpu_counter_init_irq(&bdi->bdi_stat[i], 0);
+ if (err)
+@@ -33,6 +250,8 @@ void bdi_destroy(struct backing_dev_info *bdi)
+ {
+ int i;
+
++ bdi_unregister(bdi);
++
+ for (i = 0; i < NR_BDI_STAT_ITEMS; i++)
+ percpu_counter_destroy(&bdi->bdi_stat[i]);
+
+diff --git a/mm/bootmem.c b/mm/bootmem.c
+index 2ccea70..e8fb927 100644
+--- a/mm/bootmem.c
++++ b/mm/bootmem.c
+@@ -111,44 +111,74 @@ static unsigned long __init init_bootmem_core(pg_data_t *pgdat,
+ * might be used for boot-time allocations - or it might get added
+ * to the free page pool later on.
+ */
+-static int __init reserve_bootmem_core(bootmem_data_t *bdata,
++static int __init can_reserve_bootmem_core(bootmem_data_t *bdata,
+ unsigned long addr, unsigned long size, int flags)
+ {
+ unsigned long sidx, eidx;
+ unsigned long i;
+- int ret;
++
++ BUG_ON(!size);
++
++ /* out of range, don't hold other */
++ if (addr + size < bdata->node_boot_start ||
++ PFN_DOWN(addr) > bdata->node_low_pfn)
++ return 0;
+
+ /*
+- * round up, partially reserved pages are considered
+- * fully reserved.
++ * Round up to index to the range.
+ */
++ if (addr > bdata->node_boot_start)
++ sidx= PFN_DOWN(addr - bdata->node_boot_start);
++ else
++ sidx = 0;
++
++ eidx = PFN_UP(addr + size - bdata->node_boot_start);
++ if (eidx > bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start))
++ eidx = bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start);
++
++ for (i = sidx; i < eidx; i++) {
++ if (test_bit(i, bdata->node_bootmem_map)) {
++ if (flags & BOOTMEM_EXCLUSIVE)
++ return -EBUSY;
++ }
++ }
++
++ return 0;
++
++}
++
++static void __init reserve_bootmem_core(bootmem_data_t *bdata,
++ unsigned long addr, unsigned long size, int flags)
++{
++ unsigned long sidx, eidx;
++ unsigned long i;
++
+ BUG_ON(!size);
+- BUG_ON(PFN_DOWN(addr) >= bdata->node_low_pfn);
+- BUG_ON(PFN_UP(addr + size) > bdata->node_low_pfn);
+- BUG_ON(addr < bdata->node_boot_start);
+
+- sidx = PFN_DOWN(addr - bdata->node_boot_start);
++ /* out of range */
++ if (addr + size < bdata->node_boot_start ||
++ PFN_DOWN(addr) > bdata->node_low_pfn)
++ return;
++
++ /*
++ * Round up to index to the range.
++ */
++ if (addr > bdata->node_boot_start)
++ sidx= PFN_DOWN(addr - bdata->node_boot_start);
++ else
++ sidx = 0;
++
+ eidx = PFN_UP(addr + size - bdata->node_boot_start);
++ if (eidx > bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start))
++ eidx = bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start);
+
+- for (i = sidx; i < eidx; i++)
++ for (i = sidx; i < eidx; i++) {
+ if (test_and_set_bit(i, bdata->node_bootmem_map)) {
+ #ifdef CONFIG_DEBUG_BOOTMEM
+ printk("hm, page %08lx reserved twice.\n", i*PAGE_SIZE);
+ #endif
+- if (flags & BOOTMEM_EXCLUSIVE) {
+- ret = -EBUSY;
+- goto err;
+- }
+ }
+-
+- return 0;
+-
+-err:
+- /* unreserve memory we accidentally reserved */
+- for (i--; i >= sidx; i--)
+- clear_bit(i, bdata->node_bootmem_map);
+-
+- return ret;
++ }
+ }
+
+ static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr,
+@@ -206,9 +236,11 @@ void * __init
+ __alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
+ unsigned long align, unsigned long goal, unsigned long limit)
+ {
+- unsigned long offset, remaining_size, areasize, preferred;
++ unsigned long areasize, preferred;
+ unsigned long i, start = 0, incr, eidx, end_pfn;
+ void *ret;
++ unsigned long node_boot_start;
++ void *node_bootmem_map;
+
+ if (!size) {
+ printk("__alloc_bootmem_core(): zero-sized request\n");
+@@ -216,70 +248,83 @@ __alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
+ }
+ BUG_ON(align & (align-1));
+
+- if (limit && bdata->node_boot_start >= limit)
+- return NULL;
+-
+ /* on nodes without memory - bootmem_map is NULL */
+ if (!bdata->node_bootmem_map)
+ return NULL;
+
++ /* bdata->node_boot_start is supposed to be (12+6)bits alignment on x86_64 ? */
++ node_boot_start = bdata->node_boot_start;
++ node_bootmem_map = bdata->node_bootmem_map;
++ if (align) {
++ node_boot_start = ALIGN(bdata->node_boot_start, align);
++ if (node_boot_start > bdata->node_boot_start)
++ node_bootmem_map = (unsigned long *)bdata->node_bootmem_map +
++ PFN_DOWN(node_boot_start - bdata->node_boot_start)/BITS_PER_LONG;
++ }
++
++ if (limit && node_boot_start >= limit)
++ return NULL;
++
+ end_pfn = bdata->node_low_pfn;
+ limit = PFN_DOWN(limit);
+ if (limit && end_pfn > limit)
+ end_pfn = limit;
+
+- eidx = end_pfn - PFN_DOWN(bdata->node_boot_start);
+- offset = 0;
+- if (align && (bdata->node_boot_start & (align - 1UL)) != 0)
+- offset = align - (bdata->node_boot_start & (align - 1UL));
+- offset = PFN_DOWN(offset);
++ eidx = end_pfn - PFN_DOWN(node_boot_start);
+
+ /*
+ * We try to allocate bootmem pages above 'goal'
+ * first, then we try to allocate lower pages.
+ */
+- if (goal && goal >= bdata->node_boot_start && PFN_DOWN(goal) < end_pfn) {
+- preferred = goal - bdata->node_boot_start;
++ preferred = 0;
++ if (goal && PFN_DOWN(goal) < end_pfn) {
++ if (goal > node_boot_start)
++ preferred = goal - node_boot_start;
+
+- if (bdata->last_success >= preferred)
++ if (bdata->last_success > node_boot_start &&
++ bdata->last_success - node_boot_start >= preferred)
+ if (!limit || (limit && limit > bdata->last_success))
+- preferred = bdata->last_success;
+- } else
+- preferred = 0;
++ preferred = bdata->last_success - node_boot_start;
++ }
+
+- preferred = PFN_DOWN(ALIGN(preferred, align)) + offset;
++ preferred = PFN_DOWN(ALIGN(preferred, align));
+ areasize = (size + PAGE_SIZE-1) / PAGE_SIZE;
+ incr = align >> PAGE_SHIFT ? : 1;
+
+ restart_scan:
+- for (i = preferred; i < eidx; i += incr) {
++ for (i = preferred; i < eidx;) {
+ unsigned long j;
+- i = find_next_zero_bit(bdata->node_bootmem_map, eidx, i);
++
++ i = find_next_zero_bit(node_bootmem_map, eidx, i);
+ i = ALIGN(i, incr);
+ if (i >= eidx)
+ break;
+- if (test_bit(i, bdata->node_bootmem_map))
++ if (test_bit(i, node_bootmem_map)) {
++ i += incr;
+ continue;
++ }
+ for (j = i + 1; j < i + areasize; ++j) {
+ if (j >= eidx)
+ goto fail_block;
+- if (test_bit(j, bdata->node_bootmem_map))
++ if (test_bit(j, node_bootmem_map))
+ goto fail_block;
+ }
+ start = i;
+ goto found;
+ fail_block:
+ i = ALIGN(j, incr);
++ if (i == j)
++ i += incr;
+ }
+
+- if (preferred > offset) {
+- preferred = offset;
++ if (preferred > 0) {
++ preferred = 0;
+ goto restart_scan;
+ }
+ return NULL;
+
+ found:
+- bdata->last_success = PFN_PHYS(start);
++ bdata->last_success = PFN_PHYS(start) + node_boot_start;
+ BUG_ON(start >= eidx);
+
+ /*
+@@ -289,6 +334,7 @@ found:
+ */
+ if (align < PAGE_SIZE &&
+ bdata->last_offset && bdata->last_pos+1 == start) {
++ unsigned long offset, remaining_size;
+ offset = ALIGN(bdata->last_offset, align);
+ BUG_ON(offset > PAGE_SIZE);
+ remaining_size = PAGE_SIZE - offset;
+@@ -297,14 +343,12 @@ found:
+ /* last_pos unchanged */
+ bdata->last_offset = offset + size;
+ ret = phys_to_virt(bdata->last_pos * PAGE_SIZE +
+- offset +
+- bdata->node_boot_start);
++ offset + node_boot_start);
+ } else {
+ remaining_size = size - remaining_size;
+ areasize = (remaining_size + PAGE_SIZE-1) / PAGE_SIZE;
+ ret = phys_to_virt(bdata->last_pos * PAGE_SIZE +
+- offset +
+- bdata->node_boot_start);
++ offset + node_boot_start);
+ bdata->last_pos = start + areasize - 1;
+ bdata->last_offset = remaining_size;
+ }
+@@ -312,14 +356,14 @@ found:
+ } else {
+ bdata->last_pos = start + areasize - 1;
+ bdata->last_offset = size & ~PAGE_MASK;
+- ret = phys_to_virt(start * PAGE_SIZE + bdata->node_boot_start);
++ ret = phys_to_virt(start * PAGE_SIZE + node_boot_start);
+ }
+
+ /*
+ * Reserve the area now:
+ */
+ for (i = start; i < start + areasize; i++)
+- if (unlikely(test_and_set_bit(i, bdata->node_bootmem_map)))
++ if (unlikely(test_and_set_bit(i, node_bootmem_map)))
+ BUG();
+ memset(ret, 0, size);
+ return ret;
+@@ -401,6 +445,11 @@ unsigned long __init init_bootmem_node(pg_data_t *pgdat, unsigned long freepfn,
+ void __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
+ unsigned long size, int flags)
+ {
++ int ret;
++
++ ret = can_reserve_bootmem_core(pgdat->bdata, physaddr, size, flags);
++ if (ret < 0)
++ return;
+ reserve_bootmem_core(pgdat->bdata, physaddr, size, flags);
+ }
+
+@@ -412,6 +461,7 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
+
+ unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
+ {
++ register_page_bootmem_info_node(pgdat);
+ return free_all_bootmem_core(pgdat);
+ }
+
+@@ -426,7 +476,18 @@ unsigned long __init init_bootmem(unsigned long start, unsigned long pages)
+ int __init reserve_bootmem(unsigned long addr, unsigned long size,
+ int flags)
+ {
+- return reserve_bootmem_core(NODE_DATA(0)->bdata, addr, size, flags);
++ bootmem_data_t *bdata;
++ int ret;
++
++ list_for_each_entry(bdata, &bdata_list, list) {
++ ret = can_reserve_bootmem_core(bdata, addr, size, flags);
++ if (ret < 0)
++ return ret;
++ }
++ list_for_each_entry(bdata, &bdata_list, list)
++ reserve_bootmem_core(bdata, addr, size, flags);
++
++ return 0;
+ }
+ #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
+
+@@ -484,6 +545,37 @@ void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
+ return __alloc_bootmem(size, align, goal);
+ }
+
++#ifdef CONFIG_SPARSEMEM
++void * __init alloc_bootmem_section(unsigned long size,
++ unsigned long section_nr)
++{
++ void *ptr;
++ unsigned long limit, goal, start_nr, end_nr, pfn;
++ struct pglist_data *pgdat;
++
++ pfn = section_nr_to_pfn(section_nr);
++ goal = PFN_PHYS(pfn);
++ limit = PFN_PHYS(section_nr_to_pfn(section_nr + 1)) - 1;
++ pgdat = NODE_DATA(early_pfn_to_nid(pfn));
++ ptr = __alloc_bootmem_core(pgdat->bdata, size, SMP_CACHE_BYTES, goal,
++ limit);
++
++ if (!ptr)
++ return NULL;
++
++ start_nr = pfn_to_section_nr(PFN_DOWN(__pa(ptr)));
++ end_nr = pfn_to_section_nr(PFN_DOWN(__pa(ptr) + size));
++ if (start_nr != section_nr || end_nr != section_nr) {
++ printk(KERN_WARNING "alloc_bootmem failed on section %ld.\n",
++ section_nr);
++ free_bootmem_core(pgdat->bdata, __pa(ptr), size);
++ ptr = NULL;
++ }
++
++ return ptr;
++}
++#endif
++
+ #ifndef ARCH_LOW_ADDRESS_LIMIT
+ #define ARCH_LOW_ADDRESS_LIMIT 0xffffffffUL
+ #endif
+diff --git a/mm/dmapool.c b/mm/dmapool.c
+index 34aaac4..b1f0885 100644
+--- a/mm/dmapool.c
++++ b/mm/dmapool.c
+@@ -37,6 +37,10 @@
+ #include <linux/types.h>
+ #include <linux/wait.h>
+
++#if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB_DEBUG_ON)
++#define DMAPOOL_DEBUG 1
++#endif
++
+ struct dma_pool { /* the pool */
+ struct list_head page_list;
+ spinlock_t lock;
+@@ -216,7 +220,7 @@ static struct dma_page *pool_alloc_page(struct dma_pool *pool, gfp_t mem_flags)
+ page->vaddr = dma_alloc_coherent(pool->dev, pool->allocation,
+ &page->dma, mem_flags);
+ if (page->vaddr) {
+-#ifdef CONFIG_DEBUG_SLAB
++#ifdef DMAPOOL_DEBUG
+ memset(page->vaddr, POOL_POISON_FREED, pool->allocation);
+ #endif
+ pool_initialise_page(pool, page);
+@@ -239,7 +243,7 @@ static void pool_free_page(struct dma_pool *pool, struct dma_page *page)
+ {
+ dma_addr_t dma = page->dma;
+
+-#ifdef CONFIG_DEBUG_SLAB
++#ifdef DMAPOOL_DEBUG
+ memset(page->vaddr, POOL_POISON_FREED, pool->allocation);
+ #endif
+ dma_free_coherent(pool->dev, pool->allocation, page->vaddr, dma);
+@@ -336,7 +340,7 @@ void *dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags,
+ page->offset = *(int *)(page->vaddr + offset);
+ retval = offset + page->vaddr;
+ *handle = offset + page->dma;
+-#ifdef CONFIG_DEBUG_SLAB
++#ifdef DMAPOOL_DEBUG
+ memset(retval, POOL_POISON_ALLOCATED, pool->size);
+ #endif
+ done:
+@@ -391,7 +395,7 @@ void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t dma)
+ }
+
+ offset = vaddr - page->vaddr;
+-#ifdef CONFIG_DEBUG_SLAB
++#ifdef DMAPOOL_DEBUG
+ if ((dma - page->dma) != offset) {
+ if (pool->dev)
+ dev_err(pool->dev,
+diff --git a/mm/fadvise.c b/mm/fadvise.c
+index 3c0f1e9..343cfdf 100644
+--- a/mm/fadvise.c
++++ b/mm/fadvise.c
+@@ -49,7 +49,7 @@ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
+ goto out;
+ }
+
+- if (mapping->a_ops->get_xip_page) {
++ if (mapping->a_ops->get_xip_mem) {
+ switch (advice) {
+ case POSIX_FADV_NORMAL:
+ case POSIX_FADV_RANDOM:
+diff --git a/mm/filemap.c b/mm/filemap.c
+index 07e9d92..239d361 100644
+--- a/mm/filemap.c
++++ b/mm/filemap.c
+@@ -576,10 +576,12 @@ EXPORT_SYMBOL(unlock_page);
+ */
+ void end_page_writeback(struct page *page)
+ {
+- if (!TestClearPageReclaim(page) || rotate_reclaimable_page(page)) {
+- if (!test_clear_page_writeback(page))
+- BUG();
+- }
++ if (TestClearPageReclaim(page))
++ rotate_reclaimable_page(page);
++
++ if (!test_clear_page_writeback(page))
++ BUG();
++
+ smp_mb__after_clear_bit();
+ wake_up_page(page, PG_writeback);
+ }
+diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
+index 5e598c4..3e744ab 100644
+--- a/mm/filemap_xip.c
++++ b/mm/filemap_xip.c
+@@ -15,6 +15,7 @@
+ #include <linux/rmap.h>
+ #include <linux/sched.h>
+ #include <asm/tlbflush.h>
++#include <asm/io.h>
+
+ /*
+ * We do use our own empty page to avoid interference with other users
+@@ -42,37 +43,41 @@ static struct page *xip_sparse_page(void)
+
+ /*
+ * This is a file read routine for execute in place files, and uses
+- * the mapping->a_ops->get_xip_page() function for the actual low-level
++ * the mapping->a_ops->get_xip_mem() function for the actual low-level
+ * stuff.
+ *
+ * Note the struct file* is not used at all. It may be NULL.
+ */
+-static void
++static ssize_t
+ do_xip_mapping_read(struct address_space *mapping,
+ struct file_ra_state *_ra,
+ struct file *filp,
+- loff_t *ppos,
+- read_descriptor_t *desc,
+- read_actor_t actor)
++ char __user *buf,
++ size_t len,
++ loff_t *ppos)
+ {
+ struct inode *inode = mapping->host;
+ pgoff_t index, end_index;
+ unsigned long offset;
+- loff_t isize;
++ loff_t isize, pos;
++ size_t copied = 0, error = 0;
+
+- BUG_ON(!mapping->a_ops->get_xip_page);
++ BUG_ON(!mapping->a_ops->get_xip_mem);
+
+- index = *ppos >> PAGE_CACHE_SHIFT;
+- offset = *ppos & ~PAGE_CACHE_MASK;
++ pos = *ppos;
++ index = pos >> PAGE_CACHE_SHIFT;
++ offset = pos & ~PAGE_CACHE_MASK;
+
+ isize = i_size_read(inode);
+ if (!isize)
+ goto out;
+
+ end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+- for (;;) {
+- struct page *page;
+- unsigned long nr, ret;
++ do {
++ unsigned long nr, left;
++ void *xip_mem;
++ unsigned long xip_pfn;
++ int zero = 0;
+
+ /* nr is the maximum number of bytes to copy from this page */
+ nr = PAGE_CACHE_SIZE;
+@@ -85,19 +90,17 @@ do_xip_mapping_read(struct address_space *mapping,
+ }
+ }
+ nr = nr - offset;
++ if (nr > len)
++ nr = len;
+
+- page = mapping->a_ops->get_xip_page(mapping,
+- index*(PAGE_SIZE/512), 0);
+- if (!page)
+- goto no_xip_page;
+- if (unlikely(IS_ERR(page))) {
+- if (PTR_ERR(page) == -ENODATA) {
++ error = mapping->a_ops->get_xip_mem(mapping, index, 0,
++ &xip_mem, &xip_pfn);
++ if (unlikely(error)) {
++ if (error == -ENODATA) {
+ /* sparse */
+- page = ZERO_PAGE(0);
+- } else {
+- desc->error = PTR_ERR(page);
++ zero = 1;
++ } else
+ goto out;
+- }
+ }
+
+ /* If users can be writing to this page using arbitrary
+@@ -105,10 +108,10 @@ do_xip_mapping_read(struct address_space *mapping,
+ * before reading the page on the kernel side.
+ */
+ if (mapping_writably_mapped(mapping))
+- flush_dcache_page(page);
++ /* address based flush */ ;
+
+ /*
+- * Ok, we have the page, so now we can copy it to user space...
++ * Ok, we have the mem, so now we can copy it to user space...
+ *
+ * The actor routine returns how many bytes were actually used..
+ * NOTE! This may not be the same as how much of a user buffer
+@@ -116,47 +119,38 @@ do_xip_mapping_read(struct address_space *mapping,
+ * "pos" here (the actor routine has to update the user buffer
+ * pointers and the remaining count).
+ */
+- ret = actor(desc, page, offset, nr);
+- offset += ret;
+- index += offset >> PAGE_CACHE_SHIFT;
+- offset &= ~PAGE_CACHE_MASK;
++ if (!zero)
++ left = __copy_to_user(buf+copied, xip_mem+offset, nr);
++ else
++ left = __clear_user(buf + copied, nr);
+
+- if (ret == nr && desc->count)
+- continue;
+- goto out;
++ if (left) {
++ error = -EFAULT;
++ goto out;
++ }
+
+-no_xip_page:
+- /* Did not get the page. Report it */
+- desc->error = -EIO;
+- goto out;
+- }
++ copied += (nr - left);
++ offset += (nr - left);
++ index += offset >> PAGE_CACHE_SHIFT;
++ offset &= ~PAGE_CACHE_MASK;
++ } while (copied < len);
+
+ out:
+- *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
++ *ppos = pos + copied;
+ if (filp)
+ file_accessed(filp);
++
++ return (copied ? copied : error);
+ }
+
+ ssize_t
+ xip_file_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
+ {
+- read_descriptor_t desc;
+-
+ if (!access_ok(VERIFY_WRITE, buf, len))
+ return -EFAULT;
+
+- desc.written = 0;
+- desc.arg.buf = buf;
+- desc.count = len;
+- desc.error = 0;
+-
+- do_xip_mapping_read(filp->f_mapping, &filp->f_ra, filp,
+- ppos, &desc, file_read_actor);
+-
+- if (desc.written)
+- return desc.written;
+- else
+- return desc.error;
++ return do_xip_mapping_read(filp->f_mapping, &filp->f_ra, filp,
++ buf, len, ppos);
+ }
+ EXPORT_SYMBOL_GPL(xip_file_read);
+
+@@ -211,13 +205,16 @@ __xip_unmap (struct address_space * mapping,
+ *
+ * This function is derived from filemap_fault, but used for execute in place
+ */
+-static int xip_file_fault(struct vm_area_struct *area, struct vm_fault *vmf)
++static int xip_file_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ {
+- struct file *file = area->vm_file;
++ struct file *file = vma->vm_file;
+ struct address_space *mapping = file->f_mapping;
+ struct inode *inode = mapping->host;
+- struct page *page;
+ pgoff_t size;
++ void *xip_mem;
++ unsigned long xip_pfn;
++ struct page *page;
++ int error;
+
+ /* XXX: are VM_FAULT_ codes OK? */
+
+@@ -225,35 +222,44 @@ static int xip_file_fault(struct vm_area_struct *area, struct vm_fault *vmf)
+ if (vmf->pgoff >= size)
+ return VM_FAULT_SIGBUS;
+
+- page = mapping->a_ops->get_xip_page(mapping,
+- vmf->pgoff*(PAGE_SIZE/512), 0);
+- if (!IS_ERR(page))
+- goto out;
+- if (PTR_ERR(page) != -ENODATA)
++ error = mapping->a_ops->get_xip_mem(mapping, vmf->pgoff, 0,
++ &xip_mem, &xip_pfn);
++ if (likely(!error))
++ goto found;
++ if (error != -ENODATA)
+ return VM_FAULT_OOM;
+
+ /* sparse block */
+- if ((area->vm_flags & (VM_WRITE | VM_MAYWRITE)) &&
+- (area->vm_flags & (VM_SHARED| VM_MAYSHARE)) &&
++ if ((vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) &&
++ (vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) &&
+ (!(mapping->host->i_sb->s_flags & MS_RDONLY))) {
++ int err;
++
+ /* maybe shared writable, allocate new block */
+- page = mapping->a_ops->get_xip_page(mapping,
+- vmf->pgoff*(PAGE_SIZE/512), 1);
+- if (IS_ERR(page))
++ error = mapping->a_ops->get_xip_mem(mapping, vmf->pgoff, 1,
++ &xip_mem, &xip_pfn);
++ if (error)
+ return VM_FAULT_SIGBUS;
+- /* unmap page at pgoff from all other vmas */
++ /* unmap sparse mappings at pgoff from all other vmas */
+ __xip_unmap(mapping, vmf->pgoff);
++
++found:
++ err = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address,
++ xip_pfn);
++ if (err == -ENOMEM)
++ return VM_FAULT_OOM;
++ BUG_ON(err);
++ return VM_FAULT_NOPAGE;
+ } else {
+ /* not shared and writable, use xip_sparse_page() */
+ page = xip_sparse_page();
+ if (!page)
+ return VM_FAULT_OOM;
+- }
+
+-out:
+- page_cache_get(page);
+- vmf->page = page;
+- return 0;
++ page_cache_get(page);
++ vmf->page = page;
++ return 0;
++ }
+ }
+
+ static struct vm_operations_struct xip_file_vm_ops = {
+@@ -262,11 +268,11 @@ static struct vm_operations_struct xip_file_vm_ops = {
+
+ int xip_file_mmap(struct file * file, struct vm_area_struct * vma)
+ {
+- BUG_ON(!file->f_mapping->a_ops->get_xip_page);
++ BUG_ON(!file->f_mapping->a_ops->get_xip_mem);
+
+ file_accessed(file);
+ vma->vm_ops = &xip_file_vm_ops;
+- vma->vm_flags |= VM_CAN_NONLINEAR;
++ vma->vm_flags |= VM_CAN_NONLINEAR | VM_MIXEDMAP;
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(xip_file_mmap);
+@@ -279,17 +285,17 @@ __xip_file_write(struct file *filp, const char __user *buf,
+ const struct address_space_operations *a_ops = mapping->a_ops;
+ struct inode *inode = mapping->host;
+ long status = 0;
+- struct page *page;
+ size_t bytes;
+ ssize_t written = 0;
+
+- BUG_ON(!mapping->a_ops->get_xip_page);
++ BUG_ON(!mapping->a_ops->get_xip_mem);
+
+ do {
+ unsigned long index;
+ unsigned long offset;
+ size_t copied;
+- char *kaddr;
++ void *xip_mem;
++ unsigned long xip_pfn;
+
+ offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
+ index = pos >> PAGE_CACHE_SHIFT;
+@@ -297,28 +303,22 @@ __xip_file_write(struct file *filp, const char __user *buf,
+ if (bytes > count)
+ bytes = count;
+
+- page = a_ops->get_xip_page(mapping,
+- index*(PAGE_SIZE/512), 0);
+- if (IS_ERR(page) && (PTR_ERR(page) == -ENODATA)) {
++ status = a_ops->get_xip_mem(mapping, index, 0,
++ &xip_mem, &xip_pfn);
++ if (status == -ENODATA) {
+ /* we allocate a new page unmap it */
+- page = a_ops->get_xip_page(mapping,
+- index*(PAGE_SIZE/512), 1);
+- if (!IS_ERR(page))
++ status = a_ops->get_xip_mem(mapping, index, 1,
++ &xip_mem, &xip_pfn);
++ if (!status)
+ /* unmap page at pgoff from all other vmas */
+ __xip_unmap(mapping, index);
+ }
+
+- if (IS_ERR(page)) {
+- status = PTR_ERR(page);
++ if (status)
+ break;
+- }
+
+- fault_in_pages_readable(buf, bytes);
+- kaddr = kmap_atomic(page, KM_USER0);
+ copied = bytes -
+- __copy_from_user_inatomic_nocache(kaddr + offset, buf, bytes);
+- kunmap_atomic(kaddr, KM_USER0);
+- flush_dcache_page(page);
++ __copy_from_user_nocache(xip_mem + offset, buf, bytes);
+
+ if (likely(copied > 0)) {
+ status = copied;
+@@ -398,7 +398,7 @@ EXPORT_SYMBOL_GPL(xip_file_write);
+
+ /*
+ * truncate a page used for execute in place
+- * functionality is analog to block_truncate_page but does use get_xip_page
++ * functionality is analog to block_truncate_page but does use get_xip_mem
+ * to get the page instead of page cache
+ */
+ int
+@@ -408,9 +408,11 @@ xip_truncate_page(struct address_space *mapping, loff_t from)
+ unsigned offset = from & (PAGE_CACHE_SIZE-1);
+ unsigned blocksize;
+ unsigned length;
+- struct page *page;
++ void *xip_mem;
++ unsigned long xip_pfn;
++ int err;
+
+- BUG_ON(!mapping->a_ops->get_xip_page);
++ BUG_ON(!mapping->a_ops->get_xip_mem);
+
+ blocksize = 1 << mapping->host->i_blkbits;
+ length = offset & (blocksize - 1);
+@@ -421,18 +423,16 @@ xip_truncate_page(struct address_space *mapping, loff_t from)
+
+ length = blocksize - length;
+
+- page = mapping->a_ops->get_xip_page(mapping,
+- index*(PAGE_SIZE/512), 0);
+- if (!page)
+- return -ENOMEM;
+- if (unlikely(IS_ERR(page))) {
+- if (PTR_ERR(page) == -ENODATA)
++ err = mapping->a_ops->get_xip_mem(mapping, index, 0,
++ &xip_mem, &xip_pfn);
++ if (unlikely(err)) {
++ if (err == -ENODATA)
+ /* Hole? No need to truncate */
+ return 0;
+ else
+- return PTR_ERR(page);
++ return err;
+ }
+- zero_user(page, offset, length);
++ memset(xip_mem + offset, 0, length);
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(xip_truncate_page);
+diff --git a/mm/hugetlb.c b/mm/hugetlb.c
+index 51c9e2c..bbf953e 100644
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -95,13 +95,16 @@ static struct page *dequeue_huge_page_vma(struct vm_area_struct *vma,
+ int nid;
+ struct page *page = NULL;
+ struct mempolicy *mpol;
++ nodemask_t *nodemask;
+ struct zonelist *zonelist = huge_zonelist(vma, address,
+- htlb_alloc_mask, &mpol);
+- struct zone **z;
+-
+- for (z = zonelist->zones; *z; z++) {
+- nid = zone_to_nid(*z);
+- if (cpuset_zone_allowed_softwall(*z, htlb_alloc_mask) &&
++ htlb_alloc_mask, &mpol, &nodemask);
++ struct zone *zone;
++ struct zoneref *z;
++
++ for_each_zone_zonelist_nodemask(zone, z, zonelist,
++ MAX_NR_ZONES - 1, nodemask) {
++ nid = zone_to_nid(zone);
++ if (cpuset_zone_allowed_softwall(zone, htlb_alloc_mask) &&
+ !list_empty(&hugepage_freelists[nid])) {
+ page = list_entry(hugepage_freelists[nid].next,
+ struct page, lru);
+@@ -113,7 +116,7 @@ static struct page *dequeue_huge_page_vma(struct vm_area_struct *vma,
+ break;
+ }
+ }
+- mpol_free(mpol); /* unref if mpol !NULL */
++ mpol_cond_put(mpol);
+ return page;
+ }
+
+@@ -129,6 +132,7 @@ static void update_and_free_page(struct page *page)
+ }
+ set_compound_page_dtor(page, NULL);
+ set_page_refcounted(page);
++ arch_release_hugepage(page);
+ __free_pages(page, HUGETLB_PAGE_ORDER);
+ }
+
+@@ -195,9 +199,14 @@ static struct page *alloc_fresh_huge_page_node(int nid)
+ struct page *page;
+
+ page = alloc_pages_node(nid,
+- htlb_alloc_mask|__GFP_COMP|__GFP_THISNODE|__GFP_NOWARN,
++ htlb_alloc_mask|__GFP_COMP|__GFP_THISNODE|
++ __GFP_REPEAT|__GFP_NOWARN,
+ HUGETLB_PAGE_ORDER);
+ if (page) {
++ if (arch_prepare_hugepage(page)) {
++ __free_pages(page, HUGETLB_PAGE_ORDER);
++ return NULL;
++ }
+ set_compound_page_dtor(page, free_huge_page);
+ spin_lock(&hugetlb_lock);
+ nr_huge_pages++;
+@@ -239,6 +248,11 @@ static int alloc_fresh_huge_page(void)
+ hugetlb_next_nid = next_nid;
+ } while (!page && hugetlb_next_nid != start_nid);
+
++ if (ret)
++ count_vm_event(HTLB_BUDDY_PGALLOC);
++ else
++ count_vm_event(HTLB_BUDDY_PGALLOC_FAIL);
++
+ return ret;
+ }
+
+@@ -281,7 +295,8 @@ static struct page *alloc_buddy_huge_page(struct vm_area_struct *vma,
+ }
+ spin_unlock(&hugetlb_lock);
+
+- page = alloc_pages(htlb_alloc_mask|__GFP_COMP|__GFP_NOWARN,
++ page = alloc_pages(htlb_alloc_mask|__GFP_COMP|
++ __GFP_REPEAT|__GFP_NOWARN,
+ HUGETLB_PAGE_ORDER);
+
+ spin_lock(&hugetlb_lock);
+@@ -299,9 +314,11 @@ static struct page *alloc_buddy_huge_page(struct vm_area_struct *vma,
+ */
+ nr_huge_pages_node[nid]++;
+ surplus_huge_pages_node[nid]++;
++ __count_vm_event(HTLB_BUDDY_PGALLOC);
+ } else {
+ nr_huge_pages--;
+ surplus_huge_pages--;
++ __count_vm_event(HTLB_BUDDY_PGALLOC_FAIL);
+ }
+ spin_unlock(&hugetlb_lock);
+
+@@ -369,11 +386,19 @@ retry:
+ resv_huge_pages += delta;
+ ret = 0;
+ free:
++ /* Free the needed pages to the hugetlb pool */
+ list_for_each_entry_safe(page, tmp, &surplus_list, lru) {
++ if ((--needed) < 0)
++ break;
+ list_del(&page->lru);
+- if ((--needed) >= 0)
+- enqueue_huge_page(page);
+- else {
++ enqueue_huge_page(page);
++ }
++
++ /* Free unnecessary surplus pages to the buddy allocator */
++ if (!list_empty(&surplus_list)) {
++ spin_unlock(&hugetlb_lock);
++ list_for_each_entry_safe(page, tmp, &surplus_list, lru) {
++ list_del(&page->lru);
+ /*
+ * The page has a reference count of zero already, so
+ * call free_huge_page directly instead of using
+@@ -381,10 +406,9 @@ free:
+ * unlocked which is safe because free_huge_page takes
+ * hugetlb_lock before deciding how to free the page.
+ */
+- spin_unlock(&hugetlb_lock);
+ free_huge_page(page);
+- spin_lock(&hugetlb_lock);
+ }
++ spin_lock(&hugetlb_lock);
+ }
+
+ return ret;
+@@ -718,7 +742,7 @@ static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page,
+ entry =
+ pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
+ } else {
+- entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
++ entry = huge_pte_wrprotect(mk_pte(page, vma->vm_page_prot));
+ }
+ entry = pte_mkyoung(entry);
+ entry = pte_mkhuge(entry);
+@@ -731,8 +755,8 @@ static void set_huge_ptep_writable(struct vm_area_struct *vma,
+ {
+ pte_t entry;
+
+- entry = pte_mkwrite(pte_mkdirty(*ptep));
+- if (ptep_set_access_flags(vma, address, ptep, entry, 1)) {
++ entry = pte_mkwrite(pte_mkdirty(huge_ptep_get(ptep)));
++ if (huge_ptep_set_access_flags(vma, address, ptep, entry, 1)) {
+ update_mmu_cache(vma, address, entry);
+ }
+ }
+@@ -762,10 +786,10 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
+
+ spin_lock(&dst->page_table_lock);
+ spin_lock(&src->page_table_lock);
+- if (!pte_none(*src_pte)) {
++ if (!huge_pte_none(huge_ptep_get(src_pte))) {
+ if (cow)
+- ptep_set_wrprotect(src, addr, src_pte);
+- entry = *src_pte;
++ huge_ptep_set_wrprotect(src, addr, src_pte);
++ entry = huge_ptep_get(src_pte);
+ ptepage = pte_page(entry);
+ get_page(ptepage);
+ set_huge_pte_at(dst, addr, dst_pte, entry);
+@@ -809,7 +833,7 @@ void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
+ continue;
+
+ pte = huge_ptep_get_and_clear(mm, address, ptep);
+- if (pte_none(pte))
++ if (huge_pte_none(pte))
+ continue;
+
+ page = pte_page(pte);
+@@ -873,8 +897,9 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
+ spin_lock(&mm->page_table_lock);
+
+ ptep = huge_pte_offset(mm, address & HPAGE_MASK);
+- if (likely(pte_same(*ptep, pte))) {
++ if (likely(pte_same(huge_ptep_get(ptep), pte))) {
+ /* Break COW */
++ huge_ptep_clear_flush(vma, address, ptep);
+ set_huge_pte_at(mm, address, ptep,
+ make_huge_pte(vma, new_page, 1));
+ /* Make the old page be freed below */
+@@ -942,7 +967,7 @@ retry:
+ goto backout;
+
+ ret = 0;
+- if (!pte_none(*ptep))
++ if (!huge_pte_none(huge_ptep_get(ptep)))
+ goto backout;
+
+ new_pte = make_huge_pte(vma, page, ((vma->vm_flags & VM_WRITE)
+@@ -984,8 +1009,8 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
+ * the same page in the page cache.
+ */
+ mutex_lock(&hugetlb_instantiation_mutex);
+- entry = *ptep;
+- if (pte_none(entry)) {
++ entry = huge_ptep_get(ptep);
++ if (huge_pte_none(entry)) {
+ ret = hugetlb_no_page(mm, vma, address, ptep, write_access);
+ mutex_unlock(&hugetlb_instantiation_mutex);
+ return ret;
+@@ -995,7 +1020,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
+
+ spin_lock(&mm->page_table_lock);
+ /* Check for a racing update before calling hugetlb_cow */
+- if (likely(pte_same(entry, *ptep)))
++ if (likely(pte_same(entry, huge_ptep_get(ptep))))
+ if (write_access && !pte_write(entry))
+ ret = hugetlb_cow(mm, vma, address, ptep, entry);
+ spin_unlock(&mm->page_table_lock);
+@@ -1025,7 +1050,8 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
+ */
+ pte = huge_pte_offset(mm, vaddr & HPAGE_MASK);
+
+- if (!pte || pte_none(*pte) || (write && !pte_write(*pte))) {
++ if (!pte || huge_pte_none(huge_ptep_get(pte)) ||
++ (write && !pte_write(huge_ptep_get(pte)))) {
+ int ret;
+
+ spin_unlock(&mm->page_table_lock);
+@@ -1041,7 +1067,7 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
+ }
+
+ pfn_offset = (vaddr & ~HPAGE_MASK) >> PAGE_SHIFT;
+- page = pte_page(*pte);
++ page = pte_page(huge_ptep_get(pte));
+ same_page:
+ if (pages) {
+ get_page(page);
+@@ -1090,7 +1116,7 @@ void hugetlb_change_protection(struct vm_area_struct *vma,
+ continue;
+ if (huge_pmd_unshare(mm, &address, ptep))
+ continue;
+- if (!pte_none(*ptep)) {
++ if (!huge_pte_none(huge_ptep_get(ptep))) {
+ pte = huge_ptep_get_and_clear(mm, address, ptep);
+ pte = pte_mkhuge(pte_modify(pte, newprot));
+ set_huge_pte_at(mm, address, ptep, pte);
+diff --git a/mm/internal.h b/mm/internal.h
+index 7897273..0034e94 100644
+--- a/mm/internal.h
++++ b/mm/internal.h
+@@ -34,8 +34,7 @@ static inline void __put_page(struct page *page)
+ atomic_dec(&page->_count);
+ }
+
+-extern void __init __free_pages_bootmem(struct page *page,
+- unsigned int order);
++extern void __free_pages_bootmem(struct page *page, unsigned int order);
+
+ /*
+ * function for dealing with page's order in buddy system.
+diff --git a/mm/maccess.c b/mm/maccess.c
+new file mode 100644
+index 0000000..ac40796
+--- /dev/null
++++ b/mm/maccess.c
+@@ -0,0 +1,55 @@
++/*
++ * Access kernel memory without faulting.
++ */
++#include <linux/uaccess.h>
++#include <linux/module.h>
++#include <linux/mm.h>
++
++/**
++ * probe_kernel_read(): safely attempt to read from a location
++ * @dst: pointer to the buffer that shall take the data
++ * @src: address to read from
++ * @size: size of the data chunk
++ *
++ * Safely read from address @src to the buffer at @dst. If a kernel fault
++ * happens, handle that and return -EFAULT.
++ */
++long probe_kernel_read(void *dst, void *src, size_t size)
++{
++ long ret;
++ mm_segment_t old_fs = get_fs();
++
++ set_fs(KERNEL_DS);
++ pagefault_disable();
++ ret = __copy_from_user_inatomic(dst,
++ (__force const void __user *)src, size);
++ pagefault_enable();
++ set_fs(old_fs);
++
++ return ret ? -EFAULT : 0;
++}
++EXPORT_SYMBOL_GPL(probe_kernel_read);
++
++/**
++ * probe_kernel_write(): safely attempt to write to a location
++ * @dst: address to write to
++ * @src: pointer to the data that shall be written
++ * @size: size of the data chunk
++ *
++ * Safely write to address @dst from the buffer at @src. If a kernel fault
++ * happens, handle that and return -EFAULT.
++ */
++long probe_kernel_write(void *dst, void *src, size_t size)
++{
++ long ret;
++ mm_segment_t old_fs = get_fs();
++
++ set_fs(KERNEL_DS);
++ pagefault_disable();
++ ret = __copy_to_user_inatomic((__force void __user *)dst, src, size);
++ pagefault_enable();
++ set_fs(old_fs);
++
++ return ret ? -EFAULT : 0;
++}
++EXPORT_SYMBOL_GPL(probe_kernel_write);
+diff --git a/mm/madvise.c b/mm/madvise.c
+index 93ee375..23a0ec3 100644
+--- a/mm/madvise.c
++++ b/mm/madvise.c
+@@ -112,7 +112,7 @@ static long madvise_willneed(struct vm_area_struct * vma,
+ if (!file)
+ return -EBADF;
+
+- if (file->f_mapping->a_ops->get_xip_page) {
++ if (file->f_mapping->a_ops->get_xip_mem) {
+ /* no bad return value, but ignore advice */
+ return 0;
+ }
+diff --git a/mm/memcontrol.c b/mm/memcontrol.c
+index 2e0bfc9..33add96 100644
+--- a/mm/memcontrol.c
++++ b/mm/memcontrol.c
+@@ -26,15 +26,18 @@
+ #include <linux/backing-dev.h>
+ #include <linux/bit_spinlock.h>
+ #include <linux/rcupdate.h>
++#include <linux/slab.h>
+ #include <linux/swap.h>
+ #include <linux/spinlock.h>
+ #include <linux/fs.h>
+ #include <linux/seq_file.h>
++#include <linux/vmalloc.h>
+
+ #include <asm/uaccess.h>
+
+ struct cgroup_subsys mem_cgroup_subsys;
+ static const int MEM_CGROUP_RECLAIM_RETRIES = 5;
++static struct kmem_cache *page_cgroup_cache;
+
+ /*
+ * Statistics for memory cgroup.
+@@ -236,26 +239,12 @@ static struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont)
+ css);
+ }
+
+-static struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p)
++struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p)
+ {
+ return container_of(task_subsys_state(p, mem_cgroup_subsys_id),
+ struct mem_cgroup, css);
+ }
+
+-void mm_init_cgroup(struct mm_struct *mm, struct task_struct *p)
+-{
+- struct mem_cgroup *mem;
+-
+- mem = mem_cgroup_from_task(p);
+- css_get(&mem->css);
+- mm->mem_cgroup = mem;
+-}
+-
+-void mm_free_cgroup(struct mm_struct *mm)
+-{
+- css_put(&mm->mem_cgroup->css);
+-}
+-
+ static inline int page_cgroup_locked(struct page *page)
+ {
+ return bit_spin_is_locked(PAGE_CGROUP_LOCK_BIT, &page->page_cgroup);
+@@ -287,10 +276,10 @@ static void unlock_page_cgroup(struct page *page)
+ bit_spin_unlock(PAGE_CGROUP_LOCK_BIT, &page->page_cgroup);
+ }
+
+-static void __mem_cgroup_remove_list(struct page_cgroup *pc)
++static void __mem_cgroup_remove_list(struct mem_cgroup_per_zone *mz,
++ struct page_cgroup *pc)
+ {
+ int from = pc->flags & PAGE_CGROUP_FLAG_ACTIVE;
+- struct mem_cgroup_per_zone *mz = page_cgroup_zoneinfo(pc);
+
+ if (from)
+ MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_ACTIVE) -= 1;
+@@ -301,10 +290,10 @@ static void __mem_cgroup_remove_list(struct page_cgroup *pc)
+ list_del_init(&pc->lru);
+ }
+
+-static void __mem_cgroup_add_list(struct page_cgroup *pc)
++static void __mem_cgroup_add_list(struct mem_cgroup_per_zone *mz,
++ struct page_cgroup *pc)
+ {
+ int to = pc->flags & PAGE_CGROUP_FLAG_ACTIVE;
+- struct mem_cgroup_per_zone *mz = page_cgroup_zoneinfo(pc);
+
+ if (!to) {
+ MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_INACTIVE) += 1;
+@@ -476,6 +465,7 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
+ int zid = zone_idx(z);
+ struct mem_cgroup_per_zone *mz;
+
++ BUG_ON(!mem_cont);
+ mz = mem_cgroup_zoneinfo(mem_cont, nid, zid);
+ if (active)
+ src = &mz->active_list;
+@@ -560,7 +550,7 @@ retry:
+ }
+ unlock_page_cgroup(page);
+
+- pc = kzalloc(sizeof(struct page_cgroup), gfp_mask);
++ pc = kmem_cache_zalloc(page_cgroup_cache, gfp_mask);
+ if (pc == NULL)
+ goto err;
+
+@@ -574,7 +564,7 @@ retry:
+ mm = &init_mm;
+
+ rcu_read_lock();
+- mem = rcu_dereference(mm->mem_cgroup);
++ mem = mem_cgroup_from_task(rcu_dereference(mm->owner));
+ /*
+ * For every charge from the cgroup, increment reference count
+ */
+@@ -602,7 +592,6 @@ retry:
+ mem_cgroup_out_of_memory(mem, gfp_mask);
+ goto out;
+ }
+- congestion_wait(WRITE, HZ/10);
+ }
+
+ pc->ref_cnt = 1;
+@@ -610,7 +599,7 @@ retry:
+ pc->page = page;
+ pc->flags = PAGE_CGROUP_FLAG_ACTIVE;
+ if (ctype == MEM_CGROUP_CHARGE_TYPE_CACHE)
+- pc->flags |= PAGE_CGROUP_FLAG_CACHE;
++ pc->flags = PAGE_CGROUP_FLAG_CACHE;
+
+ lock_page_cgroup(page);
+ if (page_get_page_cgroup(page)) {
+@@ -622,14 +611,14 @@ retry:
+ */
+ res_counter_uncharge(&mem->res, PAGE_SIZE);
+ css_put(&mem->css);
+- kfree(pc);
++ kmem_cache_free(page_cgroup_cache, pc);
+ goto retry;
+ }
+ page_assign_page_cgroup(page, pc);
+
+ mz = page_cgroup_zoneinfo(pc);
+ spin_lock_irqsave(&mz->lru_lock, flags);
+- __mem_cgroup_add_list(pc);
++ __mem_cgroup_add_list(mz, pc);
+ spin_unlock_irqrestore(&mz->lru_lock, flags);
+
+ unlock_page_cgroup(page);
+@@ -637,7 +626,7 @@ done:
+ return 0;
+ out:
+ css_put(&mem->css);
+- kfree(pc);
++ kmem_cache_free(page_cgroup_cache, pc);
+ err:
+ return -ENOMEM;
+ }
+@@ -685,7 +674,7 @@ void mem_cgroup_uncharge_page(struct page *page)
+ if (--(pc->ref_cnt) == 0) {
+ mz = page_cgroup_zoneinfo(pc);
+ spin_lock_irqsave(&mz->lru_lock, flags);
+- __mem_cgroup_remove_list(pc);
++ __mem_cgroup_remove_list(mz, pc);
+ spin_unlock_irqrestore(&mz->lru_lock, flags);
+
+ page_assign_page_cgroup(page, NULL);
+@@ -695,7 +684,7 @@ void mem_cgroup_uncharge_page(struct page *page)
+ res_counter_uncharge(&mem->res, PAGE_SIZE);
+ css_put(&mem->css);
+
+- kfree(pc);
++ kmem_cache_free(page_cgroup_cache, pc);
+ return;
+ }
+
+@@ -747,7 +736,7 @@ void mem_cgroup_page_migration(struct page *page, struct page *newpage)
+
+ mz = page_cgroup_zoneinfo(pc);
+ spin_lock_irqsave(&mz->lru_lock, flags);
+- __mem_cgroup_remove_list(pc);
++ __mem_cgroup_remove_list(mz, pc);
+ spin_unlock_irqrestore(&mz->lru_lock, flags);
+
+ page_assign_page_cgroup(page, NULL);
+@@ -759,7 +748,7 @@ void mem_cgroup_page_migration(struct page *page, struct page *newpage)
+
+ mz = page_cgroup_zoneinfo(pc);
+ spin_lock_irqsave(&mz->lru_lock, flags);
+- __mem_cgroup_add_list(pc);
++ __mem_cgroup_add_list(mz, pc);
+ spin_unlock_irqrestore(&mz->lru_lock, flags);
+
+ unlock_page_cgroup(newpage);
+@@ -853,13 +842,10 @@ static int mem_cgroup_write_strategy(char *buf, unsigned long long *tmp)
+ return 0;
+ }
+
+-static ssize_t mem_cgroup_read(struct cgroup *cont,
+- struct cftype *cft, struct file *file,
+- char __user *userbuf, size_t nbytes, loff_t *ppos)
++static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft)
+ {
+- return res_counter_read(&mem_cgroup_from_cont(cont)->res,
+- cft->private, userbuf, nbytes, ppos,
+- NULL);
++ return res_counter_read_u64(&mem_cgroup_from_cont(cont)->res,
++ cft->private);
+ }
+
+ static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
+@@ -871,27 +857,25 @@ static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
+ mem_cgroup_write_strategy);
+ }
+
+-static ssize_t mem_force_empty_write(struct cgroup *cont,
+- struct cftype *cft, struct file *file,
+- const char __user *userbuf,
+- size_t nbytes, loff_t *ppos)
++static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)
+ {
+- struct mem_cgroup *mem = mem_cgroup_from_cont(cont);
+- int ret = mem_cgroup_force_empty(mem);
+- if (!ret)
+- ret = nbytes;
+- return ret;
++ struct mem_cgroup *mem;
++
++ mem = mem_cgroup_from_cont(cont);
++ switch (event) {
++ case RES_MAX_USAGE:
++ res_counter_reset_max(&mem->res);
++ break;
++ case RES_FAILCNT:
++ res_counter_reset_failcnt(&mem->res);
++ break;
++ }
++ return 0;
+ }
+
+-/*
+- * Note: This should be removed if cgroup supports write-only file.
+- */
+-static ssize_t mem_force_empty_read(struct cgroup *cont,
+- struct cftype *cft,
+- struct file *file, char __user *userbuf,
+- size_t nbytes, loff_t *ppos)
++static int mem_force_empty_write(struct cgroup *cont, unsigned int event)
+ {
+- return -EINVAL;
++ return mem_cgroup_force_empty(mem_cgroup_from_cont(cont));
+ }
+
+ static const struct mem_cgroup_stat_desc {
+@@ -902,9 +886,9 @@ static const struct mem_cgroup_stat_desc {
+ [MEM_CGROUP_STAT_RSS] = { "rss", PAGE_SIZE, },
+ };
+
+-static int mem_control_stat_show(struct seq_file *m, void *arg)
++static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft,
++ struct cgroup_map_cb *cb)
+ {
+- struct cgroup *cont = m->private;
+ struct mem_cgroup *mem_cont = mem_cgroup_from_cont(cont);
+ struct mem_cgroup_stat *stat = &mem_cont->stat;
+ int i;
+@@ -914,8 +898,7 @@ static int mem_control_stat_show(struct seq_file *m, void *arg)
+
+ val = mem_cgroup_read_stat(stat, i);
+ val *= mem_cgroup_stat_desc[i].unit;
+- seq_printf(m, "%s %lld\n", mem_cgroup_stat_desc[i].msg,
+- (long long)val);
++ cb->fill(cb, mem_cgroup_stat_desc[i].msg, val);
+ }
+ /* showing # of active pages */
+ {
+@@ -925,52 +908,43 @@ static int mem_control_stat_show(struct seq_file *m, void *arg)
+ MEM_CGROUP_ZSTAT_INACTIVE);
+ active = mem_cgroup_get_all_zonestat(mem_cont,
+ MEM_CGROUP_ZSTAT_ACTIVE);
+- seq_printf(m, "active %ld\n", (active) * PAGE_SIZE);
+- seq_printf(m, "inactive %ld\n", (inactive) * PAGE_SIZE);
++ cb->fill(cb, "active", (active) * PAGE_SIZE);
++ cb->fill(cb, "inactive", (inactive) * PAGE_SIZE);
+ }
+ return 0;
+ }
+
+-static const struct file_operations mem_control_stat_file_operations = {
+- .read = seq_read,
+- .llseek = seq_lseek,
+- .release = single_release,
+-};
+-
+-static int mem_control_stat_open(struct inode *unused, struct file *file)
+-{
+- /* XXX __d_cont */
+- struct cgroup *cont = file->f_dentry->d_parent->d_fsdata;
+-
+- file->f_op = &mem_control_stat_file_operations;
+- return single_open(file, mem_control_stat_show, cont);
+-}
+-
+ static struct cftype mem_cgroup_files[] = {
+ {
+ .name = "usage_in_bytes",
+ .private = RES_USAGE,
+- .read = mem_cgroup_read,
++ .read_u64 = mem_cgroup_read,
++ },
++ {
++ .name = "max_usage_in_bytes",
++ .private = RES_MAX_USAGE,
++ .trigger = mem_cgroup_reset,
++ .read_u64 = mem_cgroup_read,
+ },
+ {
+ .name = "limit_in_bytes",
+ .private = RES_LIMIT,
+ .write = mem_cgroup_write,
+- .read = mem_cgroup_read,
++ .read_u64 = mem_cgroup_read,
+ },
+ {
+ .name = "failcnt",
+ .private = RES_FAILCNT,
+- .read = mem_cgroup_read,
++ .trigger = mem_cgroup_reset,
++ .read_u64 = mem_cgroup_read,
+ },
+ {
+ .name = "force_empty",
+- .write = mem_force_empty_write,
+- .read = mem_force_empty_read,
++ .trigger = mem_force_empty_write,
+ },
+ {
+ .name = "stat",
+- .open = mem_control_stat_open,
++ .read_map = mem_control_stat_show,
+ },
+ };
+
+@@ -1010,6 +984,29 @@ static void free_mem_cgroup_per_zone_info(struct mem_cgroup *mem, int node)
+ kfree(mem->info.nodeinfo[node]);
+ }
+
++static struct mem_cgroup *mem_cgroup_alloc(void)
++{
++ struct mem_cgroup *mem;
++
++ if (sizeof(*mem) < PAGE_SIZE)
++ mem = kmalloc(sizeof(*mem), GFP_KERNEL);
++ else
++ mem = vmalloc(sizeof(*mem));
++
++ if (mem)
++ memset(mem, 0, sizeof(*mem));
++ return mem;
++}
++
++static void mem_cgroup_free(struct mem_cgroup *mem)
++{
++ if (sizeof(*mem) < PAGE_SIZE)
++ kfree(mem);
++ else
++ vfree(mem);
++}
++
++
+ static struct cgroup_subsys_state *
+ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
+ {
+@@ -1018,17 +1015,15 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
+
+ if (unlikely((cont->parent) == NULL)) {
+ mem = &init_mem_cgroup;
+- init_mm.mem_cgroup = mem;
+- } else
+- mem = kzalloc(sizeof(struct mem_cgroup), GFP_KERNEL);
+-
+- if (mem == NULL)
+- return ERR_PTR(-ENOMEM);
++ page_cgroup_cache = KMEM_CACHE(page_cgroup, SLAB_PANIC);
++ } else {
++ mem = mem_cgroup_alloc();
++ if (!mem)
++ return ERR_PTR(-ENOMEM);
++ }
+
+ res_counter_init(&mem->res);
+
+- memset(&mem->info, 0, sizeof(mem->info));
+-
+ for_each_node_state(node, N_POSSIBLE)
+ if (alloc_mem_cgroup_per_zone_info(mem, node))
+ goto free_out;
+@@ -1038,7 +1033,7 @@ free_out:
+ for_each_node_state(node, N_POSSIBLE)
+ free_mem_cgroup_per_zone_info(mem, node);
+ if (cont->parent != NULL)
+- kfree(mem);
++ mem_cgroup_free(mem);
+ return ERR_PTR(-ENOMEM);
+ }
+
+@@ -1058,7 +1053,7 @@ static void mem_cgroup_destroy(struct cgroup_subsys *ss,
+ for_each_node_state(node, N_POSSIBLE)
+ free_mem_cgroup_per_zone_info(mem, node);
+
+- kfree(mem_cgroup_from_cont(cont));
++ mem_cgroup_free(mem_cgroup_from_cont(cont));
+ }
+
+ static int mem_cgroup_populate(struct cgroup_subsys *ss,
+@@ -1098,10 +1093,6 @@ static void mem_cgroup_move_task(struct cgroup_subsys *ss,
+ if (!thread_group_leader(p))
+ goto out;
+
+- css_get(&mem->css);
+- rcu_assign_pointer(mm->mem_cgroup, mem);
+- css_put(&old_mem->css);
+-
+ out:
+ mmput(mm);
+ }
+diff --git a/mm/memory.c b/mm/memory.c
+index 0d14d1e..bbab1e3 100644
+--- a/mm/memory.c
++++ b/mm/memory.c
+@@ -371,57 +371,93 @@ static inline int is_cow_mapping(unsigned int flags)
+ }
+
+ /*
+- * This function gets the "struct page" associated with a pte.
++ * vm_normal_page -- This function gets the "struct page" associated with a pte.
+ *
+- * NOTE! Some mappings do not have "struct pages". A raw PFN mapping
+- * will have each page table entry just pointing to a raw page frame
+- * number, and as far as the VM layer is concerned, those do not have
+- * pages associated with them - even if the PFN might point to memory
+- * that otherwise is perfectly fine and has a "struct page".
++ * "Special" mappings do not wish to be associated with a "struct page" (either
++ * it doesn't exist, or it exists but they don't want to touch it). In this
++ * case, NULL is returned here. "Normal" mappings do have a struct page.
+ *
+- * The way we recognize those mappings is through the rules set up
+- * by "remap_pfn_range()": the vma will have the VM_PFNMAP bit set,
+- * and the vm_pgoff will point to the first PFN mapped: thus every
+- * page that is a raw mapping will always honor the rule
++ * There are 2 broad cases. Firstly, an architecture may define a pte_special()
++ * pte bit, in which case this function is trivial. Secondly, an architecture
++ * may not have a spare pte bit, which requires a more complicated scheme,
++ * described below.
++ *
++ * A raw VM_PFNMAP mapping (ie. one that is not COWed) is always considered a
++ * special mapping (even if there are underlying and valid "struct pages").
++ * COWed pages of a VM_PFNMAP are always normal.
++ *
++ * The way we recognize COWed pages within VM_PFNMAP mappings is through the
++ * rules set up by "remap_pfn_range()": the vma will have the VM_PFNMAP bit
++ * set, and the vm_pgoff will point to the first PFN mapped: thus every special
++ * mapping will always honor the rule
+ *
+ * pfn_of_page == vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT)
+ *
+- * and if that isn't true, the page has been COW'ed (in which case it
+- * _does_ have a "struct page" associated with it even if it is in a
+- * VM_PFNMAP range).
++ * And for normal mappings this is false.
++ *
++ * This restricts such mappings to be a linear translation from virtual address
++ * to pfn. To get around this restriction, we allow arbitrary mappings so long
++ * as the vma is not a COW mapping; in that case, we know that all ptes are
++ * special (because none can have been COWed).
++ *
++ *
++ * In order to support COW of arbitrary special mappings, we have VM_MIXEDMAP.
++ *
++ * VM_MIXEDMAP mappings can likewise contain memory with or without "struct
++ * page" backing, however the difference is that _all_ pages with a struct
++ * page (that is, those where pfn_valid is true) are refcounted and considered
++ * normal pages by the VM. The disadvantage is that pages are refcounted
++ * (which can be slower and simply not an option for some PFNMAP users). The
++ * advantage is that we don't have to follow the strict linearity rule of
++ * PFNMAP mappings in order to support COWable mappings.
++ *
+ */
+-struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
++#ifdef __HAVE_ARCH_PTE_SPECIAL
++# define HAVE_PTE_SPECIAL 1
++#else
++# define HAVE_PTE_SPECIAL 0
++#endif
++struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
++ pte_t pte)
+ {
+- unsigned long pfn = pte_pfn(pte);
++ unsigned long pfn;
+
+- if (unlikely(vma->vm_flags & VM_PFNMAP)) {
+- unsigned long off = (addr - vma->vm_start) >> PAGE_SHIFT;
+- if (pfn == vma->vm_pgoff + off)
+- return NULL;
+- if (!is_cow_mapping(vma->vm_flags))
+- return NULL;
++ if (HAVE_PTE_SPECIAL) {
++ if (likely(!pte_special(pte))) {
++ VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
++ return pte_page(pte);
++ }
++ VM_BUG_ON(!(vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP)));
++ return NULL;
+ }
+
+-#ifdef CONFIG_DEBUG_VM
+- /*
+- * Add some anal sanity checks for now. Eventually,
+- * we should just do "return pfn_to_page(pfn)", but
+- * in the meantime we check that we get a valid pfn,
+- * and that the resulting page looks ok.
+- */
+- if (unlikely(!pfn_valid(pfn))) {
+- print_bad_pte(vma, pte, addr);
+- return NULL;
++ /* !HAVE_PTE_SPECIAL case follows: */
++
++ pfn = pte_pfn(pte);
++
++ if (unlikely(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP))) {
++ if (vma->vm_flags & VM_MIXEDMAP) {
++ if (!pfn_valid(pfn))
++ return NULL;
++ goto out;
++ } else {
++ unsigned long off;
++ off = (addr - vma->vm_start) >> PAGE_SHIFT;
++ if (pfn == vma->vm_pgoff + off)
++ return NULL;
++ if (!is_cow_mapping(vma->vm_flags))
++ return NULL;
++ }
+ }
+-#endif
++
++ VM_BUG_ON(!pfn_valid(pfn));
+
+ /*
+- * NOTE! We still have PageReserved() pages in the page
+- * tables.
++ * NOTE! We still have PageReserved() pages in the page tables.
+ *
+- * The PAGE_ZERO() pages and various VDSO mappings can
+- * cause them to exist.
++ * eg. VDSO mappings can cause them to exist.
+ */
++out:
+ return pfn_to_page(pfn);
+ }
+
+@@ -1057,8 +1093,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
+ if (pages)
+ foll_flags |= FOLL_GET;
+ if (!write && !(vma->vm_flags & VM_LOCKED) &&
+- (!vma->vm_ops || (!vma->vm_ops->nopage &&
+- !vma->vm_ops->fault)))
++ (!vma->vm_ops || !vma->vm_ops->fault))
+ foll_flags |= FOLL_ANON;
+
+ do {
+@@ -1141,8 +1176,10 @@ pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr,
+ * old drivers should use this, and they needed to mark their
+ * pages reserved for the old functions anyway.
+ */
+-static int insert_page(struct mm_struct *mm, unsigned long addr, struct page *page, pgprot_t prot)
++static int insert_page(struct vm_area_struct *vma, unsigned long addr,
++ struct page *page, pgprot_t prot)
+ {
++ struct mm_struct *mm = vma->vm_mm;
+ int retval;
+ pte_t *pte;
+ spinlock_t *ptl;
+@@ -1202,40 +1239,26 @@ out:
+ *
+ * The page does not need to be reserved.
+ */
+-int vm_insert_page(struct vm_area_struct *vma, unsigned long addr, struct page *page)
++int vm_insert_page(struct vm_area_struct *vma, unsigned long addr,
++ struct page *page)
+ {
+ if (addr < vma->vm_start || addr >= vma->vm_end)
+ return -EFAULT;
+ if (!page_count(page))
+ return -EINVAL;
+ vma->vm_flags |= VM_INSERTPAGE;
+- return insert_page(vma->vm_mm, addr, page, vma->vm_page_prot);
++ return insert_page(vma, addr, page, vma->vm_page_prot);
+ }
+ EXPORT_SYMBOL(vm_insert_page);
+
+-/**
+- * vm_insert_pfn - insert single pfn into user vma
+- * @vma: user vma to map to
+- * @addr: target user address of this page
+- * @pfn: source kernel pfn
+- *
+- * Similar to vm_inert_page, this allows drivers to insert individual pages
+- * they've allocated into a user vma. Same comments apply.
+- *
+- * This function should only be called from a vm_ops->fault handler, and
+- * in that case the handler should return NULL.
+- */
+-int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
+- unsigned long pfn)
++static int insert_pfn(struct vm_area_struct *vma, unsigned long addr,
++ unsigned long pfn, pgprot_t prot)
+ {
+ struct mm_struct *mm = vma->vm_mm;
+ int retval;
+ pte_t *pte, entry;
+ spinlock_t *ptl;
+
+- BUG_ON(!(vma->vm_flags & VM_PFNMAP));
+- BUG_ON(is_cow_mapping(vma->vm_flags));
+-
+ retval = -ENOMEM;
+ pte = get_locked_pte(mm, addr, &ptl);
+ if (!pte)
+@@ -1245,19 +1268,74 @@ int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
+ goto out_unlock;
+
+ /* Ok, finally just insert the thing.. */
+- entry = pfn_pte(pfn, vma->vm_page_prot);
++ entry = pte_mkspecial(pfn_pte(pfn, prot));
+ set_pte_at(mm, addr, pte, entry);
+- update_mmu_cache(vma, addr, entry);
++ update_mmu_cache(vma, addr, entry); /* XXX: why not for insert_page? */
+
+ retval = 0;
+ out_unlock:
+ pte_unmap_unlock(pte, ptl);
+-
+ out:
+ return retval;
+ }
++
++/**
++ * vm_insert_pfn - insert single pfn into user vma
++ * @vma: user vma to map to
++ * @addr: target user address of this page
++ * @pfn: source kernel pfn
++ *
++ * Similar to vm_inert_page, this allows drivers to insert individual pages
++ * they've allocated into a user vma. Same comments apply.
++ *
++ * This function should only be called from a vm_ops->fault handler, and
++ * in that case the handler should return NULL.
++ */
++int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
++ unsigned long pfn)
++{
++ /*
++ * Technically, architectures with pte_special can avoid all these
++ * restrictions (same for remap_pfn_range). However we would like
++ * consistency in testing and feature parity among all, so we should
++ * try to keep these invariants in place for everybody.
++ */
++ BUG_ON(!(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)));
++ BUG_ON((vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)) ==
++ (VM_PFNMAP|VM_MIXEDMAP));
++ BUG_ON((vma->vm_flags & VM_PFNMAP) && is_cow_mapping(vma->vm_flags));
++ BUG_ON((vma->vm_flags & VM_MIXEDMAP) && pfn_valid(pfn));
++
++ if (addr < vma->vm_start || addr >= vma->vm_end)
++ return -EFAULT;
++ return insert_pfn(vma, addr, pfn, vma->vm_page_prot);
++}
+ EXPORT_SYMBOL(vm_insert_pfn);
+
++int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr,
++ unsigned long pfn)
++{
++ BUG_ON(!(vma->vm_flags & VM_MIXEDMAP));
++
++ if (addr < vma->vm_start || addr >= vma->vm_end)
++ return -EFAULT;
++
++ /*
++ * If we don't have pte special, then we have to use the pfn_valid()
++ * based VM_MIXEDMAP scheme (see vm_normal_page), and thus we *must*
++ * refcount the page if pfn_valid is true (hence insert_page rather
++ * than insert_pfn).
++ */
++ if (!HAVE_PTE_SPECIAL && pfn_valid(pfn)) {
++ struct page *page;
++
++ page = pfn_to_page(pfn);
++ return insert_page(vma, addr, page, vma->vm_page_prot);
++ }
++ return insert_pfn(vma, addr, pfn, vma->vm_page_prot);
++}
++EXPORT_SYMBOL(vm_insert_mixed);
++
+ /*
+ * maps a range of physical memory into the requested pages. the old
+ * mappings are removed. any references to nonexistent pages results
+@@ -1276,7 +1354,7 @@ static int remap_pte_range(struct mm_struct *mm, pmd_t *pmd,
+ arch_enter_lazy_mmu_mode();
+ do {
+ BUG_ON(!pte_none(*pte));
+- set_pte_at(mm, addr, pte, pfn_pte(pfn, prot));
++ set_pte_at(mm, addr, pte, pte_mkspecial(pfn_pte(pfn, prot)));
+ pfn++;
+ } while (pte++, addr += PAGE_SIZE, addr != end);
+ arch_leave_lazy_mmu_mode();
+@@ -2199,20 +2277,9 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
+
+ BUG_ON(vma->vm_flags & VM_PFNMAP);
+
+- if (likely(vma->vm_ops->fault)) {
+- ret = vma->vm_ops->fault(vma, &vmf);
+- if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE)))
+- return ret;
+- } else {
+- /* Legacy ->nopage path */
+- ret = 0;
+- vmf.page = vma->vm_ops->nopage(vma, address & PAGE_MASK, &ret);
+- /* no page was available -- either SIGBUS or OOM */
+- if (unlikely(vmf.page == NOPAGE_SIGBUS))
+- return VM_FAULT_SIGBUS;
+- else if (unlikely(vmf.page == NOPAGE_OOM))
+- return VM_FAULT_OOM;
+- }
++ ret = vma->vm_ops->fault(vma, &vmf);
++ if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE)))
++ return ret;
+
+ /*
+ * For consistency in subsequent calls, make the faulted page always
+@@ -2377,10 +2444,13 @@ static noinline int do_no_pfn(struct mm_struct *mm, struct vm_area_struct *vma,
+ unsigned long pfn;
+
+ pte_unmap(page_table);
+- BUG_ON(!(vma->vm_flags & VM_PFNMAP));
+- BUG_ON(is_cow_mapping(vma->vm_flags));
++ BUG_ON(!(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)));
++ BUG_ON((vma->vm_flags & VM_PFNMAP) && is_cow_mapping(vma->vm_flags));
+
+ pfn = vma->vm_ops->nopfn(vma, address & PAGE_MASK);
++
++ BUG_ON((vma->vm_flags & VM_MIXEDMAP) && pfn_valid(pfn));
++
+ if (unlikely(pfn == NOPFN_OOM))
+ return VM_FAULT_OOM;
+ else if (unlikely(pfn == NOPFN_SIGBUS))
+@@ -2458,7 +2528,7 @@ static inline int handle_pte_fault(struct mm_struct *mm,
+ if (!pte_present(entry)) {
+ if (pte_none(entry)) {
+ if (vma->vm_ops) {
+- if (vma->vm_ops->fault || vma->vm_ops->nopage)
++ if (likely(vma->vm_ops->fault))
+ return do_linear_fault(mm, vma, address,
+ pte, pmd, write_access, entry);
+ if (unlikely(vma->vm_ops->nopfn))
+diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
+index 7469c50..b17dca7 100644
+--- a/mm/memory_hotplug.c
++++ b/mm/memory_hotplug.c
+@@ -29,6 +29,8 @@
+
+ #include <asm/tlbflush.h>
+
++#include "internal.h"
++
+ /* add this memory to iomem resource */
+ static struct resource *register_memory_resource(u64 start, u64 size)
+ {
+@@ -58,8 +60,105 @@ static void release_memory_resource(struct resource *res)
+ return;
+ }
+
+-
+ #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
++#ifndef CONFIG_SPARSEMEM_VMEMMAP
++static void get_page_bootmem(unsigned long info, struct page *page, int magic)
++{
++ atomic_set(&page->_mapcount, magic);
++ SetPagePrivate(page);
++ set_page_private(page, info);
++ atomic_inc(&page->_count);
++}
++
++void put_page_bootmem(struct page *page)
++{
++ int magic;
++
++ magic = atomic_read(&page->_mapcount);
++ BUG_ON(magic >= -1);
++
++ if (atomic_dec_return(&page->_count) == 1) {
++ ClearPagePrivate(page);
++ set_page_private(page, 0);
++ reset_page_mapcount(page);
++ __free_pages_bootmem(page, 0);
++ }
++
++}
++
++void register_page_bootmem_info_section(unsigned long start_pfn)
++{
++ unsigned long *usemap, mapsize, section_nr, i;
++ struct mem_section *ms;
++ struct page *page, *memmap;
++
++ if (!pfn_valid(start_pfn))
++ return;
++
++ section_nr = pfn_to_section_nr(start_pfn);
++ ms = __nr_to_section(section_nr);
++
++ /* Get section's memmap address */
++ memmap = sparse_decode_mem_map(ms->section_mem_map, section_nr);
++
++ /*
++ * Get page for the memmap's phys address
++ * XXX: need more consideration for sparse_vmemmap...
++ */
++ page = virt_to_page(memmap);
++ mapsize = sizeof(struct page) * PAGES_PER_SECTION;
++ mapsize = PAGE_ALIGN(mapsize) >> PAGE_SHIFT;
++
++ /* remember memmap's page */
++ for (i = 0; i < mapsize; i++, page++)
++ get_page_bootmem(section_nr, page, SECTION_INFO);
++
++ usemap = __nr_to_section(section_nr)->pageblock_flags;
++ page = virt_to_page(usemap);
++
++ mapsize = PAGE_ALIGN(usemap_size()) >> PAGE_SHIFT;
++
++ for (i = 0; i < mapsize; i++, page++)
++ get_page_bootmem(section_nr, page, MIX_INFO);
++
++}
++
++void register_page_bootmem_info_node(struct pglist_data *pgdat)
++{
++ unsigned long i, pfn, end_pfn, nr_pages;
++ int node = pgdat->node_id;
++ struct page *page;
++ struct zone *zone;
++
++ nr_pages = PAGE_ALIGN(sizeof(struct pglist_data)) >> PAGE_SHIFT;
++ page = virt_to_page(pgdat);
++
++ for (i = 0; i < nr_pages; i++, page++)
++ get_page_bootmem(node, page, NODE_INFO);
++
++ zone = &pgdat->node_zones[0];
++ for (; zone < pgdat->node_zones + MAX_NR_ZONES - 1; zone++) {
++ if (zone->wait_table) {
++ nr_pages = zone->wait_table_hash_nr_entries
++ * sizeof(wait_queue_head_t);
++ nr_pages = PAGE_ALIGN(nr_pages) >> PAGE_SHIFT;
++ page = virt_to_page(zone->wait_table);
++
++ for (i = 0; i < nr_pages; i++, page++)
++ get_page_bootmem(node, page, NODE_INFO);
++ }
++ }
++
++ pfn = pgdat->node_start_pfn;
++ end_pfn = pfn + pgdat->node_spanned_pages;
++
++ /* register_section info */
++ for (; pfn < end_pfn; pfn += PAGES_PER_SECTION)
++ register_page_bootmem_info_section(pfn);
++
++}
++#endif /* !CONFIG_SPARSEMEM_VMEMMAP */
++
+ static int __add_zone(struct zone *zone, unsigned long phys_start_pfn)
+ {
+ struct pglist_data *pgdat = zone->zone_pgdat;
+@@ -101,6 +200,36 @@ static int __add_section(struct zone *zone, unsigned long phys_start_pfn)
+ return register_new_memory(__pfn_to_section(phys_start_pfn));
+ }
+
++#ifdef CONFIG_SPARSEMEM_VMEMMAP
++static int __remove_section(struct zone *zone, struct mem_section *ms)
++{
++ /*
++ * XXX: Freeing memmap with vmemmap is not implement yet.
++ * This should be removed later.
++ */
++ return -EBUSY;
++}
++#else
++static int __remove_section(struct zone *zone, struct mem_section *ms)
++{
++ unsigned long flags;
++ struct pglist_data *pgdat = zone->zone_pgdat;
++ int ret = -EINVAL;
++
++ if (!valid_section(ms))
++ return ret;
++
++ ret = unregister_memory_section(ms);
++ if (ret)
++ return ret;
++
++ pgdat_resize_lock(pgdat, &flags);
++ sparse_remove_one_section(zone, ms);
++ pgdat_resize_unlock(pgdat, &flags);
++ return 0;
++}
++#endif
++
+ /*
+ * Reasonably generic function for adding memory. It is
+ * expected that archs that support memory hotplug will
+@@ -134,6 +263,42 @@ int __add_pages(struct zone *zone, unsigned long phys_start_pfn,
+ }
+ EXPORT_SYMBOL_GPL(__add_pages);
+
++/**
++ * __remove_pages() - remove sections of pages from a zone
++ * @zone: zone from which pages need to be removed
++ * @phys_start_pfn: starting pageframe (must be aligned to start of a section)
++ * @nr_pages: number of pages to remove (must be multiple of section size)
++ *
++ * Generic helper function to remove section mappings and sysfs entries
++ * for the section of the memory we are removing. Caller needs to make
++ * sure that pages are marked reserved and zones are adjust properly by
++ * calling offline_pages().
++ */
++int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
++ unsigned long nr_pages)
++{
++ unsigned long i, ret = 0;
++ int sections_to_remove;
++
++ /*
++ * We can only remove entire sections
++ */
++ BUG_ON(phys_start_pfn & ~PAGE_SECTION_MASK);
++ BUG_ON(nr_pages % PAGES_PER_SECTION);
++
++ release_mem_region(phys_start_pfn << PAGE_SHIFT, nr_pages * PAGE_SIZE);
++
++ sections_to_remove = nr_pages / PAGES_PER_SECTION;
++ for (i = 0; i < sections_to_remove; i++) {
++ unsigned long pfn = phys_start_pfn + i*PAGES_PER_SECTION;
++ ret = __remove_section(zone, __pfn_to_section(pfn));
++ if (ret)
++ break;
++ }
++ return ret;
++}
++EXPORT_SYMBOL_GPL(__remove_pages);
++
+ static void grow_zone_span(struct zone *zone,
+ unsigned long start_pfn, unsigned long end_pfn)
+ {
+@@ -164,6 +329,25 @@ static void grow_pgdat_span(struct pglist_data *pgdat,
+ pgdat->node_start_pfn;
+ }
+
++void online_page(struct page *page)
++{
++ totalram_pages++;
++ num_physpages++;
++
++#ifdef CONFIG_HIGHMEM
++ if (PageHighMem(page))
++ totalhigh_pages++;
++#endif
++
++#ifdef CONFIG_FLATMEM
++ max_mapnr = max(page_to_pfn(page), max_mapnr);
++#endif
++
++ ClearPageReserved(page);
++ init_page_count(page);
++ __free_page(page);
++}
++
+ static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages,
+ void *arg)
+ {
+@@ -208,7 +392,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/mempolicy.c b/mm/mempolicy.c
+index 3c36011..a37a503 100644
+--- a/mm/mempolicy.c
++++ b/mm/mempolicy.c
+@@ -63,7 +63,6 @@
+ grows down?
+ make bind policy root only? It can trigger oom much faster and the
+ kernel is not always grateful with that.
+- could replace all the switch()es with a mempolicy_ops structure.
+ */
+
+ #include <linux/mempolicy.h>
+@@ -89,6 +88,7 @@
+ #include <linux/rmap.h>
+ #include <linux/security.h>
+ #include <linux/syscalls.h>
++#include <linux/ctype.h>
+
+ #include <asm/tlbflush.h>
+ #include <asm/uaccess.h>
+@@ -105,142 +105,264 @@ static struct kmem_cache *sn_cache;
+ policied. */
+ enum zone_type policy_zone = 0;
+
++/*
++ * run-time system-wide default policy => local allocation
++ */
+ struct mempolicy default_policy = {
+ .refcnt = ATOMIC_INIT(1), /* never free it */
+- .policy = MPOL_DEFAULT,
++ .mode = MPOL_PREFERRED,
++ .flags = MPOL_F_LOCAL,
+ };
+
+-static void mpol_rebind_policy(struct mempolicy *pol,
+- const nodemask_t *newmask);
++static const struct mempolicy_operations {
++ int (*create)(struct mempolicy *pol, const nodemask_t *nodes);
++ void (*rebind)(struct mempolicy *pol, const nodemask_t *nodes);
++} mpol_ops[MPOL_MAX];
+
+-/* Do sanity checking on a policy */
+-static int mpol_check_policy(int mode, nodemask_t *nodes)
++/* Check that the nodemask contains at least one populated zone */
++static int is_valid_nodemask(const nodemask_t *nodemask)
+ {
+- int was_empty, is_empty;
++ int nd, k;
+
+- if (!nodes)
+- return 0;
++ /* Check that there is something useful in this mask */
++ k = policy_zone;
+
+- /*
+- * "Contextualize" the in-coming nodemast for cpusets:
+- * Remember whether in-coming nodemask was empty, If not,
+- * restrict the nodes to the allowed nodes in the cpuset.
+- * This is guaranteed to be a subset of nodes with memory.
+- */
+- cpuset_update_task_memory_state();
+- is_empty = was_empty = nodes_empty(*nodes);
+- if (!was_empty) {
+- nodes_and(*nodes, *nodes, cpuset_current_mems_allowed);
+- is_empty = nodes_empty(*nodes); /* after "contextualization" */
+- }
++ for_each_node_mask(nd, *nodemask) {
++ struct zone *z;
+
+- switch (mode) {
+- case MPOL_DEFAULT:
+- /*
+- * require caller to specify an empty nodemask
+- * before "contextualization"
+- */
+- if (!was_empty)
+- return -EINVAL;
+- break;
+- case MPOL_BIND:
+- case MPOL_INTERLEAVE:
+- /*
+- * require at least 1 valid node after "contextualization"
+- */
+- if (is_empty)
+- return -EINVAL;
+- break;
+- case MPOL_PREFERRED:
+- /*
+- * Did caller specify invalid nodes?
+- * Don't silently accept this as "local allocation".
+- */
+- if (!was_empty && is_empty)
+- return -EINVAL;
+- break;
++ for (k = 0; k <= policy_zone; k++) {
++ z = &NODE_DATA(nd)->node_zones[k];
++ if (z->present_pages > 0)
++ return 1;
++ }
+ }
++
+ return 0;
+ }
+
+-/* Generate a custom zonelist for the BIND policy. */
+-static struct zonelist *bind_zonelist(nodemask_t *nodes)
++static inline int mpol_store_user_nodemask(const struct mempolicy *pol)
+ {
+- struct zonelist *zl;
+- int num, max, nd;
+- enum zone_type k;
++ return pol->flags & (MPOL_F_STATIC_NODES | MPOL_F_RELATIVE_NODES);
++}
+
+- max = 1 + MAX_NR_ZONES * nodes_weight(*nodes);
+- max++; /* space for zlcache_ptr (see mmzone.h) */
+- zl = kmalloc(sizeof(struct zone *) * max, GFP_KERNEL);
+- if (!zl)
+- return ERR_PTR(-ENOMEM);
+- zl->zlcache_ptr = NULL;
+- num = 0;
+- /* First put in the highest zones from all nodes, then all the next
+- lower zones etc. Avoid empty zones because the memory allocator
+- doesn't like them. If you implement node hot removal you
+- have to fix that. */
+- k = MAX_NR_ZONES - 1;
+- while (1) {
+- for_each_node_mask(nd, *nodes) {
+- struct zone *z = &NODE_DATA(nd)->node_zones[k];
+- if (z->present_pages > 0)
+- zl->zones[num++] = z;
+- }
+- if (k == 0)
+- break;
+- k--;
+- }
+- if (num == 0) {
+- kfree(zl);
+- return ERR_PTR(-EINVAL);
+- }
+- zl->zones[num] = NULL;
+- return zl;
++static void mpol_relative_nodemask(nodemask_t *ret, const nodemask_t *orig,
++ const nodemask_t *rel)
++{
++ nodemask_t tmp;
++ nodes_fold(tmp, *orig, nodes_weight(*rel));
++ nodes_onto(*ret, tmp, *rel);
++}
++
++static int mpol_new_interleave(struct mempolicy *pol, const nodemask_t *nodes)
++{
++ if (nodes_empty(*nodes))
++ return -EINVAL;
++ pol->v.nodes = *nodes;
++ return 0;
++}
++
++static int mpol_new_preferred(struct mempolicy *pol, const nodemask_t *nodes)
++{
++ if (!nodes)
++ pol->flags |= MPOL_F_LOCAL; /* local allocation */
++ else if (nodes_empty(*nodes))
++ return -EINVAL; /* no allowed nodes */
++ else
++ pol->v.preferred_node = first_node(*nodes);
++ return 0;
++}
++
++static int mpol_new_bind(struct mempolicy *pol, const nodemask_t *nodes)
++{
++ if (!is_valid_nodemask(nodes))
++ return -EINVAL;
++ pol->v.nodes = *nodes;
++ return 0;
+ }
+
+ /* Create a new policy */
+-static struct mempolicy *mpol_new(int mode, nodemask_t *nodes)
++static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags,
++ nodemask_t *nodes)
+ {
+ struct mempolicy *policy;
++ nodemask_t cpuset_context_nmask;
++ int ret;
+
+- pr_debug("setting mode %d nodes[0] %lx\n",
+- mode, nodes ? nodes_addr(*nodes)[0] : -1);
++ pr_debug("setting mode %d flags %d nodes[0] %lx\n",
++ mode, flags, nodes ? nodes_addr(*nodes)[0] : -1);
+
+- if (mode == MPOL_DEFAULT)
+- return NULL;
++ if (mode == MPOL_DEFAULT) {
++ if (nodes && !nodes_empty(*nodes))
++ return ERR_PTR(-EINVAL);
++ return NULL; /* simply delete any existing policy */
++ }
++ VM_BUG_ON(!nodes);
++
++ /*
++ * MPOL_PREFERRED cannot be used with MPOL_F_STATIC_NODES or
++ * MPOL_F_RELATIVE_NODES if the nodemask is empty (local allocation).
++ * All other modes require a valid pointer to a non-empty nodemask.
++ */
++ if (mode == MPOL_PREFERRED) {
++ if (nodes_empty(*nodes)) {
++ if (((flags & MPOL_F_STATIC_NODES) ||
++ (flags & MPOL_F_RELATIVE_NODES)))
++ return ERR_PTR(-EINVAL);
++ nodes = NULL; /* flag local alloc */
++ }
++ } else if (nodes_empty(*nodes))
++ return ERR_PTR(-EINVAL);
+ policy = kmem_cache_alloc(policy_cache, GFP_KERNEL);
+ if (!policy)
+ return ERR_PTR(-ENOMEM);
+ atomic_set(&policy->refcnt, 1);
+- switch (mode) {
+- case MPOL_INTERLEAVE:
+- policy->v.nodes = *nodes;
+- if (nodes_weight(policy->v.nodes) == 0) {
+- kmem_cache_free(policy_cache, policy);
+- return ERR_PTR(-EINVAL);
+- }
+- break;
+- case MPOL_PREFERRED:
+- policy->v.preferred_node = first_node(*nodes);
+- if (policy->v.preferred_node >= MAX_NUMNODES)
+- policy->v.preferred_node = -1;
+- break;
+- case MPOL_BIND:
+- policy->v.zonelist = bind_zonelist(nodes);
+- if (IS_ERR(policy->v.zonelist)) {
+- void *error_code = policy->v.zonelist;
+- kmem_cache_free(policy_cache, policy);
+- return error_code;
+- }
+- break;
++ policy->mode = mode;
++ policy->flags = flags;
++
++ if (nodes) {
++ /*
++ * cpuset related setup doesn't apply to local allocation
++ */
++ cpuset_update_task_memory_state();
++ if (flags & MPOL_F_RELATIVE_NODES)
++ mpol_relative_nodemask(&cpuset_context_nmask, nodes,
++ &cpuset_current_mems_allowed);
++ else
++ nodes_and(cpuset_context_nmask, *nodes,
++ cpuset_current_mems_allowed);
++ if (mpol_store_user_nodemask(policy))
++ policy->w.user_nodemask = *nodes;
++ else
++ policy->w.cpuset_mems_allowed =
++ cpuset_mems_allowed(current);
++ }
++
++ ret = mpol_ops[mode].create(policy,
++ nodes ? &cpuset_context_nmask : NULL);
++ if (ret < 0) {
++ kmem_cache_free(policy_cache, policy);
++ return ERR_PTR(ret);
+ }
+- policy->policy = mode;
+- policy->cpuset_mems_allowed = cpuset_mems_allowed(current);
+ return policy;
+ }
+
++/* Slow path of a mpol destructor. */
++void __mpol_put(struct mempolicy *p)
++{
++ if (!atomic_dec_and_test(&p->refcnt))
++ return;
++ kmem_cache_free(policy_cache, p);
++}
++
++static void mpol_rebind_default(struct mempolicy *pol, const nodemask_t *nodes)
++{
++}
++
++static void mpol_rebind_nodemask(struct mempolicy *pol,
++ const nodemask_t *nodes)
++{
++ nodemask_t tmp;
++
++ if (pol->flags & MPOL_F_STATIC_NODES)
++ nodes_and(tmp, pol->w.user_nodemask, *nodes);
++ else if (pol->flags & MPOL_F_RELATIVE_NODES)
++ mpol_relative_nodemask(&tmp, &pol->w.user_nodemask, nodes);
++ else {
++ nodes_remap(tmp, pol->v.nodes, pol->w.cpuset_mems_allowed,
++ *nodes);
++ pol->w.cpuset_mems_allowed = *nodes;
++ }
++
++ pol->v.nodes = tmp;
++ if (!node_isset(current->il_next, tmp)) {
++ current->il_next = next_node(current->il_next, tmp);
++ if (current->il_next >= MAX_NUMNODES)
++ current->il_next = first_node(tmp);
++ if (current->il_next >= MAX_NUMNODES)
++ current->il_next = numa_node_id();
++ }
++}
++
++static void mpol_rebind_preferred(struct mempolicy *pol,
++ const nodemask_t *nodes)
++{
++ nodemask_t tmp;
++
++ if (pol->flags & MPOL_F_STATIC_NODES) {
++ int node = first_node(pol->w.user_nodemask);
++
++ if (node_isset(node, *nodes)) {
++ pol->v.preferred_node = node;
++ pol->flags &= ~MPOL_F_LOCAL;
++ } else
++ pol->flags |= MPOL_F_LOCAL;
++ } else if (pol->flags & MPOL_F_RELATIVE_NODES) {
++ mpol_relative_nodemask(&tmp, &pol->w.user_nodemask, nodes);
++ pol->v.preferred_node = first_node(tmp);
++ } else if (!(pol->flags & MPOL_F_LOCAL)) {
++ pol->v.preferred_node = node_remap(pol->v.preferred_node,
++ pol->w.cpuset_mems_allowed,
++ *nodes);
++ pol->w.cpuset_mems_allowed = *nodes;
++ }
++}
++
++/* Migrate a policy to a different set of nodes */
++static void mpol_rebind_policy(struct mempolicy *pol,
++ const nodemask_t *newmask)
++{
++ if (!pol)
++ return;
++ if (!mpol_store_user_nodemask(pol) &&
++ nodes_equal(pol->w.cpuset_mems_allowed, *newmask))
++ return;
++ mpol_ops[pol->mode].rebind(pol, newmask);
++}
++
++/*
++ * Wrapper for mpol_rebind_policy() that just requires task
++ * pointer, and updates task mempolicy.
++ */
++
++void mpol_rebind_task(struct task_struct *tsk, const nodemask_t *new)
++{
++ mpol_rebind_policy(tsk->mempolicy, new);
++}
++
++/*
++ * Rebind each vma in mm to new nodemask.
++ *
++ * Call holding a reference to mm. Takes mm->mmap_sem during call.
++ */
++
++void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new)
++{
++ struct vm_area_struct *vma;
++
++ down_write(&mm->mmap_sem);
++ for (vma = mm->mmap; vma; vma = vma->vm_next)
++ mpol_rebind_policy(vma->vm_policy, new);
++ up_write(&mm->mmap_sem);
++}
++
++static const struct mempolicy_operations mpol_ops[MPOL_MAX] = {
++ [MPOL_DEFAULT] = {
++ .rebind = mpol_rebind_default,
++ },
++ [MPOL_INTERLEAVE] = {
++ .create = mpol_new_interleave,
++ .rebind = mpol_rebind_nodemask,
++ },
++ [MPOL_PREFERRED] = {
++ .create = mpol_new_preferred,
++ .rebind = mpol_rebind_preferred,
++ },
++ [MPOL_BIND] = {
++ .create = mpol_new_bind,
++ .rebind = mpol_rebind_nodemask,
++ },
++};
++
+ static void gather_stats(struct page *, void *, int pte_dirty);
+ static void migrate_page_add(struct page *page, struct list_head *pagelist,
+ unsigned long flags);
+@@ -421,7 +543,7 @@ static int policy_vma(struct vm_area_struct *vma, struct mempolicy *new)
+ if (!err) {
+ mpol_get(new);
+ vma->vm_policy = new;
+- mpol_free(old);
++ mpol_put(old);
+ }
+ return err;
+ }
+@@ -479,46 +601,55 @@ static void mpol_set_task_struct_flag(void)
+ }
+
+ /* Set the process memory policy */
+-static long do_set_mempolicy(int mode, nodemask_t *nodes)
++static long do_set_mempolicy(unsigned short mode, unsigned short flags,
++ nodemask_t *nodes)
+ {
+ struct mempolicy *new;
++ struct mm_struct *mm = current->mm;
+
+- if (mpol_check_policy(mode, nodes))
+- return -EINVAL;
+- new = mpol_new(mode, nodes);
++ new = mpol_new(mode, flags, nodes);
+ if (IS_ERR(new))
+ return PTR_ERR(new);
+- mpol_free(current->mempolicy);
++
++ /*
++ * prevent changing our mempolicy while show_numa_maps()
++ * is using it.
++ * Note: do_set_mempolicy() can be called at init time
++ * with no 'mm'.
++ */
++ if (mm)
++ down_write(&mm->mmap_sem);
++ mpol_put(current->mempolicy);
+ current->mempolicy = new;
+ mpol_set_task_struct_flag();
+- if (new && new->policy == MPOL_INTERLEAVE)
++ if (new && new->mode == MPOL_INTERLEAVE &&
++ nodes_weight(new->v.nodes))
+ current->il_next = first_node(new->v.nodes);
++ if (mm)
++ up_write(&mm->mmap_sem);
++
+ return 0;
+ }
+
+-/* Fill a zone bitmap for a policy */
+-static void get_zonemask(struct mempolicy *p, nodemask_t *nodes)
++/*
++ * Return nodemask for policy for get_mempolicy() query
++ */
++static void get_policy_nodemask(struct mempolicy *p, nodemask_t *nodes)
+ {
+- int i;
+-
+ nodes_clear(*nodes);
+- switch (p->policy) {
++ if (p == &default_policy)
++ return;
++
++ switch (p->mode) {
+ case MPOL_BIND:
+- for (i = 0; p->v.zonelist->zones[i]; i++)
+- node_set(zone_to_nid(p->v.zonelist->zones[i]),
+- *nodes);
+- break;
+- case MPOL_DEFAULT:
+- break;
++ /* Fall through */
+ case MPOL_INTERLEAVE:
+ *nodes = p->v.nodes;
+ break;
+ case MPOL_PREFERRED:
+- /* or use current node instead of memory_map? */
+- if (p->v.preferred_node < 0)
+- *nodes = node_states[N_HIGH_MEMORY];
+- else
++ if (!(p->flags & MPOL_F_LOCAL))
+ node_set(p->v.preferred_node, *nodes);
++ /* else return empty node mask for local allocation */
+ break;
+ default:
+ BUG();
+@@ -561,6 +692,11 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
+ }
+
+ if (flags & MPOL_F_ADDR) {
++ /*
++ * Do NOT fall back to task policy if the
++ * vma/shared policy at addr is NULL. We
++ * want to return MPOL_DEFAULT in this case.
++ */
+ down_read(&mm->mmap_sem);
+ vma = find_vma_intersection(mm, addr, addr+1);
+ if (!vma) {
+@@ -575,7 +711,7 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
+ return -EINVAL;
+
+ if (!pol)
+- pol = &default_policy;
++ pol = &default_policy; /* indicates default behavior */
+
+ if (flags & MPOL_F_NODE) {
+ if (flags & MPOL_F_ADDR) {
+@@ -584,14 +720,17 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
+ goto out;
+ *policy = err;
+ } else if (pol == current->mempolicy &&
+- pol->policy == MPOL_INTERLEAVE) {
++ pol->mode == MPOL_INTERLEAVE) {
+ *policy = current->il_next;
+ } else {
+ err = -EINVAL;
+ goto out;
+ }
+- } else
+- *policy = pol->policy;
++ } else {
++ *policy = pol == &default_policy ? MPOL_DEFAULT :
++ pol->mode;
++ *policy |= pol->flags;
++ }
+
+ if (vma) {
+ up_read(¤t->mm->mmap_sem);
+@@ -600,9 +739,10 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
+
+ err = 0;
+ if (nmask)
+- get_zonemask(pol, nmask);
++ get_policy_nodemask(pol, nmask);
+
+ out:
++ mpol_cond_put(pol);
+ if (vma)
+ up_read(¤t->mm->mmap_sem);
+ return err;
+@@ -664,7 +804,7 @@ int do_migrate_pages(struct mm_struct *mm,
+ int err = 0;
+ nodemask_t tmp;
+
+- down_read(&mm->mmap_sem);
++ down_read(&mm->mmap_sem);
+
+ err = migrate_vmas(mm, from_nodes, to_nodes, flags);
+ if (err)
+@@ -781,8 +921,8 @@ static struct page *new_vma_page(struct page *page, unsigned long private, int *
+ #endif
+
+ static long do_mbind(unsigned long start, unsigned long len,
+- unsigned long mode, nodemask_t *nmask,
+- unsigned long flags)
++ unsigned short mode, unsigned short mode_flags,
++ nodemask_t *nmask, unsigned long flags)
+ {
+ struct vm_area_struct *vma;
+ struct mm_struct *mm = current->mm;
+@@ -791,9 +931,8 @@ static long do_mbind(unsigned long start, unsigned long len,
+ int err;
+ LIST_HEAD(pagelist);
+
+- if ((flags & ~(unsigned long)(MPOL_MF_STRICT |
+- MPOL_MF_MOVE | MPOL_MF_MOVE_ALL))
+- || mode > MPOL_MAX)
++ if (flags & ~(unsigned long)(MPOL_MF_STRICT |
++ MPOL_MF_MOVE | MPOL_MF_MOVE_ALL))
+ return -EINVAL;
+ if ((flags & MPOL_MF_MOVE_ALL) && !capable(CAP_SYS_NICE))
+ return -EPERM;
+@@ -812,10 +951,7 @@ static long do_mbind(unsigned long start, unsigned long len,
+ if (end == start)
+ return 0;
+
+- if (mpol_check_policy(mode, nmask))
+- return -EINVAL;
+-
+- new = mpol_new(mode, nmask);
++ new = mpol_new(mode, mode_flags, nmask);
+ if (IS_ERR(new))
+ return PTR_ERR(new);
+
+@@ -826,8 +962,9 @@ static long do_mbind(unsigned long start, unsigned long len,
+ if (!new)
+ flags |= MPOL_MF_DISCONTIG_OK;
+
+- pr_debug("mbind %lx-%lx mode:%ld nodes:%lx\n",start,start+len,
+- mode, nmask ? nodes_addr(*nmask)[0] : -1);
++ pr_debug("mbind %lx-%lx mode:%d flags:%d nodes:%lx\n",
++ start, start + len, mode, mode_flags,
++ nmask ? nodes_addr(*nmask)[0] : -1);
+
+ down_write(&mm->mmap_sem);
+ vma = check_range(mm, start, end, nmask,
+@@ -848,7 +985,7 @@ static long do_mbind(unsigned long start, unsigned long len,
+ }
+
+ up_write(&mm->mmap_sem);
+- mpol_free(new);
++ mpol_put(new);
+ return err;
+ }
+
+@@ -926,11 +1063,19 @@ asmlinkage long sys_mbind(unsigned long start, unsigned long len,
+ {
+ nodemask_t nodes;
+ int err;
++ unsigned short mode_flags;
+
++ mode_flags = mode & MPOL_MODE_FLAGS;
++ mode &= ~MPOL_MODE_FLAGS;
++ if (mode >= MPOL_MAX)
++ return -EINVAL;
++ if ((mode_flags & MPOL_F_STATIC_NODES) &&
++ (mode_flags & MPOL_F_RELATIVE_NODES))
++ return -EINVAL;
+ err = get_nodes(&nodes, nmask, maxnode);
+ if (err)
+ return err;
+- return do_mbind(start, len, mode, &nodes, flags);
++ return do_mbind(start, len, mode, mode_flags, &nodes, flags);
+ }
+
+ /* Set the process memory policy */
+@@ -939,13 +1084,18 @@ asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask,
+ {
+ int err;
+ nodemask_t nodes;
++ unsigned short flags;
+
+- if (mode < 0 || mode > MPOL_MAX)
++ flags = mode & MPOL_MODE_FLAGS;
++ mode &= ~MPOL_MODE_FLAGS;
++ if ((unsigned int)mode >= MPOL_MAX)
++ return -EINVAL;
++ if ((flags & MPOL_F_STATIC_NODES) && (flags & MPOL_F_RELATIVE_NODES))
+ return -EINVAL;
+ err = get_nodes(&nodes, nmask, maxnode);
+ if (err)
+ return err;
+- return do_set_mempolicy(mode, &nodes);
++ return do_set_mempolicy(mode, flags, &nodes);
+ }
+
+ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,
+@@ -1131,59 +1281,75 @@ asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len,
+ *
+ * Returns effective policy for a VMA at specified address.
+ * Falls back to @task or system default policy, as necessary.
+- * Returned policy has extra reference count if shared, vma,
+- * or some other task's policy [show_numa_maps() can pass
+- * @task != current]. It is the caller's responsibility to
+- * free the reference in these cases.
++ * Current or other task's task mempolicy and non-shared vma policies
++ * are protected by the task's mmap_sem, which must be held for read by
++ * the caller.
++ * Shared policies [those marked as MPOL_F_SHARED] require an extra reference
++ * count--added by the get_policy() vm_op, as appropriate--to protect against
++ * freeing by another task. It is the caller's responsibility to free the
++ * extra reference for shared policies.
+ */
+-static struct mempolicy * get_vma_policy(struct task_struct *task,
++static struct mempolicy *get_vma_policy(struct task_struct *task,
+ struct vm_area_struct *vma, unsigned long addr)
+ {
+ struct mempolicy *pol = task->mempolicy;
+- int shared_pol = 0;
+
+ if (vma) {
+ if (vma->vm_ops && vma->vm_ops->get_policy) {
+- pol = vma->vm_ops->get_policy(vma, addr);
+- shared_pol = 1; /* if pol non-NULL, add ref below */
+- } else if (vma->vm_policy &&
+- vma->vm_policy->policy != MPOL_DEFAULT)
++ struct mempolicy *vpol = vma->vm_ops->get_policy(vma,
++ addr);
++ if (vpol)
++ pol = vpol;
++ } else if (vma->vm_policy)
+ pol = vma->vm_policy;
+ }
+ if (!pol)
+ pol = &default_policy;
+- else if (!shared_pol && pol != current->mempolicy)
+- mpol_get(pol); /* vma or other task's policy */
+ return pol;
+ }
+
+-/* Return a zonelist representing a mempolicy */
+-static struct zonelist *zonelist_policy(gfp_t gfp, struct mempolicy *policy)
++/*
++ * Return a nodemask representing a mempolicy for filtering nodes for
++ * page allocation
++ */
++static nodemask_t *policy_nodemask(gfp_t gfp, struct mempolicy *policy)
+ {
+- int nd;
++ /* Lower zones don't get a nodemask applied for MPOL_BIND */
++ if (unlikely(policy->mode == MPOL_BIND) &&
++ gfp_zone(gfp) >= policy_zone &&
++ cpuset_nodemask_valid_mems_allowed(&policy->v.nodes))
++ return &policy->v.nodes;
+
+- switch (policy->policy) {
++ return NULL;
++}
++
++/* Return a zonelist indicated by gfp for node representing a mempolicy */
++static struct zonelist *policy_zonelist(gfp_t gfp, struct mempolicy *policy)
++{
++ int nd = numa_node_id();
++
++ switch (policy->mode) {
+ case MPOL_PREFERRED:
+- nd = policy->v.preferred_node;
+- if (nd < 0)
+- nd = numa_node_id();
++ if (!(policy->flags & MPOL_F_LOCAL))
++ nd = policy->v.preferred_node;
+ break;
+ case MPOL_BIND:
+- /* Lower zones don't get a policy applied */
+- /* Careful: current->mems_allowed might have moved */
+- if (gfp_zone(gfp) >= policy_zone)
+- if (cpuset_zonelist_valid_mems_allowed(policy->v.zonelist))
+- return policy->v.zonelist;
+- /*FALL THROUGH*/
++ /*
++ * Normally, MPOL_BIND allocations are node-local within the
++ * allowed nodemask. However, if __GFP_THISNODE is set and the
++ * current node is part of the mask, we use the zonelist for
++ * the first node in the mask instead.
++ */
++ if (unlikely(gfp & __GFP_THISNODE) &&
++ unlikely(!node_isset(nd, policy->v.nodes)))
++ nd = first_node(policy->v.nodes);
++ break;
+ case MPOL_INTERLEAVE: /* should not happen */
+- case MPOL_DEFAULT:
+- nd = numa_node_id();
+ break;
+ default:
+- nd = 0;
+ BUG();
+ }
+- return NODE_DATA(nd)->node_zonelists + gfp_zone(gfp);
++ return node_zonelist(nd, gfp);
+ }
+
+ /* Do dynamic interleaving for a process */
+@@ -1196,36 +1362,51 @@ static unsigned interleave_nodes(struct mempolicy *policy)
+ next = next_node(nid, policy->v.nodes);
+ if (next >= MAX_NUMNODES)
+ next = first_node(policy->v.nodes);
+- me->il_next = next;
++ if (next < MAX_NUMNODES)
++ me->il_next = next;
+ return nid;
+ }
+
+ /*
+ * Depending on the memory policy provide a node from which to allocate the
+ * next slab entry.
++ * @policy must be protected by freeing by the caller. If @policy is
++ * the current task's mempolicy, this protection is implicit, as only the
++ * task can change it's policy. The system default policy requires no
++ * such protection.
+ */
+ unsigned slab_node(struct mempolicy *policy)
+ {
+- int pol = policy ? policy->policy : MPOL_DEFAULT;
++ if (!policy || policy->flags & MPOL_F_LOCAL)
++ return numa_node_id();
++
++ switch (policy->mode) {
++ case MPOL_PREFERRED:
++ /*
++ * handled MPOL_F_LOCAL above
++ */
++ return policy->v.preferred_node;
+
+- switch (pol) {
+ case MPOL_INTERLEAVE:
+ return interleave_nodes(policy);
+
+- case MPOL_BIND:
++ case MPOL_BIND: {
+ /*
+ * Follow bind policy behavior and start allocation at the
+ * first node.
+ */
+- return zone_to_nid(policy->v.zonelist->zones[0]);
+-
+- case MPOL_PREFERRED:
+- if (policy->v.preferred_node >= 0)
+- return policy->v.preferred_node;
+- /* Fall through */
++ struct zonelist *zonelist;
++ struct zone *zone;
++ enum zone_type highest_zoneidx = gfp_zone(GFP_KERNEL);
++ zonelist = &NODE_DATA(numa_node_id())->node_zonelists[0];
++ (void)first_zones_zonelist(zonelist, highest_zoneidx,
++ &policy->v.nodes,
++ &zone);
++ return zone->node;
++ }
+
+ default:
+- return numa_node_id();
++ BUG();
+ }
+ }
+
+@@ -1234,10 +1415,13 @@ static unsigned offset_il_node(struct mempolicy *pol,
+ struct vm_area_struct *vma, unsigned long off)
+ {
+ unsigned nnodes = nodes_weight(pol->v.nodes);
+- unsigned target = (unsigned)off % nnodes;
++ unsigned target;
+ int c;
+ int nid = -1;
+
++ if (!nnodes)
++ return numa_node_id();
++ target = (unsigned int)off % nnodes;
+ c = 0;
+ do {
+ nid = next_node(nid, pol->v.nodes);
+@@ -1274,40 +1458,30 @@ static inline unsigned interleave_nid(struct mempolicy *pol,
+ * @vma = virtual memory area whose policy is sought
+ * @addr = address in @vma for shared policy lookup and interleave policy
+ * @gfp_flags = for requested zone
+- * @mpol = pointer to mempolicy pointer for reference counted 'BIND policy
++ * @mpol = pointer to mempolicy pointer for reference counted mempolicy
++ * @nodemask = pointer to nodemask pointer for MPOL_BIND nodemask
+ *
+- * Returns a zonelist suitable for a huge page allocation.
+- * If the effective policy is 'BIND, returns pointer to policy's zonelist.
+- * If it is also a policy for which get_vma_policy() returns an extra
+- * reference, we must hold that reference until after allocation.
+- * In that case, return policy via @mpol so hugetlb allocation can drop
+- * the reference. For non-'BIND referenced policies, we can/do drop the
+- * reference here, so the caller doesn't need to know about the special case
+- * for default and current task policy.
++ * Returns a zonelist suitable for a huge page allocation and a pointer
++ * to the struct mempolicy for conditional unref after allocation.
++ * If the effective policy is 'BIND, returns a pointer to the mempolicy's
++ * @nodemask for filtering the zonelist.
+ */
+ struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr,
+- gfp_t gfp_flags, struct mempolicy **mpol)
++ gfp_t gfp_flags, struct mempolicy **mpol,
++ nodemask_t **nodemask)
+ {
+- struct mempolicy *pol = get_vma_policy(current, vma, addr);
+ struct zonelist *zl;
+
+- *mpol = NULL; /* probably no unref needed */
+- if (pol->policy == MPOL_INTERLEAVE) {
+- unsigned nid;
+-
+- nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT);
+- if (unlikely(pol != &default_policy &&
+- pol != current->mempolicy))
+- __mpol_free(pol); /* finished with pol */
+- return NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_flags);
+- }
++ *mpol = get_vma_policy(current, vma, addr);
++ *nodemask = NULL; /* assume !MPOL_BIND */
+
+- zl = zonelist_policy(GFP_HIGHUSER, pol);
+- if (unlikely(pol != &default_policy && pol != current->mempolicy)) {
+- if (pol->policy != MPOL_BIND)
+- __mpol_free(pol); /* finished with pol */
+- else
+- *mpol = pol; /* unref needed after allocation */
++ if (unlikely((*mpol)->mode == MPOL_INTERLEAVE)) {
++ zl = node_zonelist(interleave_nid(*mpol, vma, addr,
++ HPAGE_SHIFT), gfp_flags);
++ } else {
++ zl = policy_zonelist(gfp_flags, *mpol);
++ if ((*mpol)->mode == MPOL_BIND)
++ *nodemask = &(*mpol)->v.nodes;
+ }
+ return zl;
+ }
+@@ -1321,9 +1495,9 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order,
+ struct zonelist *zl;
+ struct page *page;
+
+- zl = NODE_DATA(nid)->node_zonelists + gfp_zone(gfp);
++ zl = node_zonelist(nid, gfp);
+ page = __alloc_pages(gfp, order, zl);
+- if (page && page_zone(page) == zl->zones[0])
++ if (page && page_zone(page) == zonelist_zone(&zl->_zonerefs[0]))
+ inc_zone_page_state(page, NUMA_INTERLEAVE_HIT);
+ return page;
+ }
+@@ -1358,28 +1532,27 @@ alloc_page_vma(gfp_t gfp, struct vm_area_struct *vma, unsigned long addr)
+
+ cpuset_update_task_memory_state();
+
+- if (unlikely(pol->policy == MPOL_INTERLEAVE)) {
++ if (unlikely(pol->mode == MPOL_INTERLEAVE)) {
+ unsigned nid;
+
+ nid = interleave_nid(pol, vma, addr, PAGE_SHIFT);
+- if (unlikely(pol != &default_policy &&
+- pol != current->mempolicy))
+- __mpol_free(pol); /* finished with pol */
++ mpol_cond_put(pol);
+ return alloc_page_interleave(gfp, 0, nid);
+ }
+- zl = zonelist_policy(gfp, pol);
+- if (pol != &default_policy && pol != current->mempolicy) {
++ zl = policy_zonelist(gfp, pol);
++ if (unlikely(mpol_needs_cond_ref(pol))) {
+ /*
+- * slow path: ref counted policy -- shared or vma
++ * slow path: ref counted shared policy
+ */
+- struct page *page = __alloc_pages(gfp, 0, zl);
+- __mpol_free(pol);
++ struct page *page = __alloc_pages_nodemask(gfp, 0,
++ zl, policy_nodemask(gfp, pol));
++ __mpol_put(pol);
+ return page;
+ }
+ /*
+ * fast path: default or task policy
+ */
+- return __alloc_pages(gfp, 0, zl);
++ return __alloc_pages_nodemask(gfp, 0, zl, policy_nodemask(gfp, pol));
+ }
+
+ /**
+@@ -1409,22 +1582,28 @@ struct page *alloc_pages_current(gfp_t gfp, unsigned order)
+ cpuset_update_task_memory_state();
+ if (!pol || in_interrupt() || (gfp & __GFP_THISNODE))
+ pol = &default_policy;
+- if (pol->policy == MPOL_INTERLEAVE)
++
++ /*
++ * No reference counting needed for current->mempolicy
++ * nor system default_policy
++ */
++ if (pol->mode == MPOL_INTERLEAVE)
+ return alloc_page_interleave(gfp, order, interleave_nodes(pol));
+- return __alloc_pages(gfp, order, zonelist_policy(gfp, pol));
++ return __alloc_pages_nodemask(gfp, order,
++ policy_zonelist(gfp, pol), policy_nodemask(gfp, pol));
+ }
+ EXPORT_SYMBOL(alloc_pages_current);
+
+ /*
+- * If mpol_copy() sees current->cpuset == cpuset_being_rebound, then it
++ * If mpol_dup() sees current->cpuset == cpuset_being_rebound, then it
+ * rebinds the mempolicy its copying by calling mpol_rebind_policy()
+ * with the mems_allowed returned by cpuset_mems_allowed(). This
+ * keeps mempolicies cpuset relative after its cpuset moves. See
+ * further kernel/cpuset.c update_nodemask().
+ */
+
+-/* Slow path of a mempolicy copy */
+-struct mempolicy *__mpol_copy(struct mempolicy *old)
++/* Slow path of a mempolicy duplicate */
++struct mempolicy *__mpol_dup(struct mempolicy *old)
+ {
+ struct mempolicy *new = kmem_cache_alloc(policy_cache, GFP_KERNEL);
+
+@@ -1436,55 +1615,64 @@ struct mempolicy *__mpol_copy(struct mempolicy *old)
+ }
+ *new = *old;
+ atomic_set(&new->refcnt, 1);
+- if (new->policy == MPOL_BIND) {
+- int sz = ksize(old->v.zonelist);
+- new->v.zonelist = kmemdup(old->v.zonelist, sz, GFP_KERNEL);
+- if (!new->v.zonelist) {
+- kmem_cache_free(policy_cache, new);
+- return ERR_PTR(-ENOMEM);
+- }
+- }
+ return new;
+ }
+
++/*
++ * If *frompol needs [has] an extra ref, copy *frompol to *tompol ,
++ * eliminate the * MPOL_F_* flags that require conditional ref and
++ * [NOTE!!!] drop the extra ref. Not safe to reference *frompol directly
++ * after return. Use the returned value.
++ *
++ * Allows use of a mempolicy for, e.g., multiple allocations with a single
++ * policy lookup, even if the policy needs/has extra ref on lookup.
++ * shmem_readahead needs this.
++ */
++struct mempolicy *__mpol_cond_copy(struct mempolicy *tompol,
++ struct mempolicy *frompol)
++{
++ if (!mpol_needs_cond_ref(frompol))
++ return frompol;
++
++ *tompol = *frompol;
++ tompol->flags &= ~MPOL_F_SHARED; /* copy doesn't need unref */
++ __mpol_put(frompol);
++ return tompol;
++}
++
++static int mpol_match_intent(const struct mempolicy *a,
++ const struct mempolicy *b)
++{
++ if (a->flags != b->flags)
++ return 0;
++ if (!mpol_store_user_nodemask(a))
++ return 1;
++ return nodes_equal(a->w.user_nodemask, b->w.user_nodemask);
++}
++
+ /* Slow path of a mempolicy comparison */
+ int __mpol_equal(struct mempolicy *a, struct mempolicy *b)
+ {
+ if (!a || !b)
+ return 0;
+- if (a->policy != b->policy)
++ if (a->mode != b->mode)
+ return 0;
+- switch (a->policy) {
+- case MPOL_DEFAULT:
+- return 1;
++ if (a->mode != MPOL_DEFAULT && !mpol_match_intent(a, b))
++ return 0;
++ switch (a->mode) {
++ case MPOL_BIND:
++ /* Fall through */
+ case MPOL_INTERLEAVE:
+ return nodes_equal(a->v.nodes, b->v.nodes);
+ case MPOL_PREFERRED:
+- return a->v.preferred_node == b->v.preferred_node;
+- case MPOL_BIND: {
+- int i;
+- for (i = 0; a->v.zonelist->zones[i]; i++)
+- if (a->v.zonelist->zones[i] != b->v.zonelist->zones[i])
+- return 0;
+- return b->v.zonelist->zones[i] == NULL;
+- }
++ return a->v.preferred_node == b->v.preferred_node &&
++ a->flags == b->flags;
+ default:
+ BUG();
+ return 0;
+ }
+ }
+
+-/* Slow path of a mpol destructor. */
+-void __mpol_free(struct mempolicy *p)
+-{
+- if (!atomic_dec_and_test(&p->refcnt))
+- return;
+- if (p->policy == MPOL_BIND)
+- kfree(p->v.zonelist);
+- p->policy = MPOL_DEFAULT;
+- kmem_cache_free(policy_cache, p);
+-}
+-
+ /*
+ * Shared memory backing store policy support.
+ *
+@@ -1547,7 +1735,7 @@ static void sp_insert(struct shared_policy *sp, struct sp_node *new)
+ rb_link_node(&new->nd, parent, p);
+ rb_insert_color(&new->nd, &sp->root);
+ pr_debug("inserting %lx-%lx: %d\n", new->start, new->end,
+- new->policy ? new->policy->policy : 0);
++ new->policy ? new->policy->mode : 0);
+ }
+
+ /* Find shared policy intersecting idx */
+@@ -1573,7 +1761,7 @@ static void sp_delete(struct shared_policy *sp, struct sp_node *n)
+ {
+ pr_debug("deleting %lx-l%lx\n", n->start, n->end);
+ rb_erase(&n->nd, &sp->root);
+- mpol_free(n->policy);
++ mpol_put(n->policy);
+ kmem_cache_free(sn_cache, n);
+ }
+
+@@ -1587,6 +1775,7 @@ static struct sp_node *sp_alloc(unsigned long start, unsigned long end,
+ n->start = start;
+ n->end = end;
+ mpol_get(pol);
++ pol->flags |= MPOL_F_SHARED; /* for unref */
+ n->policy = pol;
+ return n;
+ }
+@@ -1633,33 +1822,41 @@ restart:
+ sp_insert(sp, new);
+ spin_unlock(&sp->lock);
+ if (new2) {
+- mpol_free(new2->policy);
++ mpol_put(new2->policy);
+ kmem_cache_free(sn_cache, new2);
+ }
+ return 0;
+ }
+
+-void mpol_shared_policy_init(struct shared_policy *info, int policy,
+- nodemask_t *policy_nodes)
+-{
+- info->root = RB_ROOT;
+- spin_lock_init(&info->lock);
+-
+- if (policy != MPOL_DEFAULT) {
+- struct mempolicy *newpol;
+-
+- /* Falls back to MPOL_DEFAULT on any error */
+- newpol = mpol_new(policy, policy_nodes);
+- if (!IS_ERR(newpol)) {
+- /* Create pseudo-vma that contains just the policy */
+- struct vm_area_struct pvma;
+-
+- memset(&pvma, 0, sizeof(struct vm_area_struct));
+- /* Policy covers entire file */
+- pvma.vm_end = TASK_SIZE;
+- mpol_set_shared_policy(info, &pvma, newpol);
+- mpol_free(newpol);
+- }
++/**
++ * mpol_shared_policy_init - initialize shared policy for inode
++ * @sp: pointer to inode shared policy
++ * @mpol: struct mempolicy to install
++ *
++ * Install non-NULL @mpol in inode's shared policy rb-tree.
++ * On entry, the current task has a reference on a non-NULL @mpol.
++ * This must be released on exit.
++ */
++void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol)
++{
++ sp->root = RB_ROOT; /* empty tree == default mempolicy */
++ spin_lock_init(&sp->lock);
++
++ if (mpol) {
++ struct vm_area_struct pvma;
++ struct mempolicy *new;
++
++ /* contextualize the tmpfs mount point mempolicy */
++ new = mpol_new(mpol->mode, mpol->flags, &mpol->w.user_nodemask);
++ mpol_put(mpol); /* drop our ref on sb mpol */
++ if (IS_ERR(new))
++ return; /* no valid nodemask intersection */
++
++ /* Create pseudo-vma that contains just the policy */
++ memset(&pvma, 0, sizeof(struct vm_area_struct));
++ pvma.vm_end = TASK_SIZE; /* policy covers entire file */
++ mpol_set_shared_policy(sp, &pvma, new); /* adds ref */
++ mpol_put(new); /* drop initial ref */
+ }
+ }
+
+@@ -1670,9 +1867,10 @@ int mpol_set_shared_policy(struct shared_policy *info,
+ struct sp_node *new = NULL;
+ unsigned long sz = vma_pages(vma);
+
+- pr_debug("set_shared_policy %lx sz %lu %d %lx\n",
++ pr_debug("set_shared_policy %lx sz %lu %d %d %lx\n",
+ vma->vm_pgoff,
+- sz, npol? npol->policy : -1,
++ sz, npol ? npol->mode : -1,
++ npol ? npol->flags : -1,
+ npol ? nodes_addr(npol->v.nodes)[0] : -1);
+
+ if (npol) {
+@@ -1700,7 +1898,7 @@ void mpol_free_shared_policy(struct shared_policy *p)
+ n = rb_entry(next, struct sp_node, nd);
+ next = rb_next(&n->nd);
+ rb_erase(&n->nd, &p->root);
+- mpol_free(n->policy);
++ mpol_put(n->policy);
+ kmem_cache_free(sn_cache, n);
+ }
+ spin_unlock(&p->lock);
+@@ -1745,120 +1943,177 @@ void __init numa_policy_init(void)
+ if (unlikely(nodes_empty(interleave_nodes)))
+ node_set(prefer, interleave_nodes);
+
+- if (do_set_mempolicy(MPOL_INTERLEAVE, &interleave_nodes))
++ if (do_set_mempolicy(MPOL_INTERLEAVE, 0, &interleave_nodes))
+ printk("numa_policy_init: interleaving failed\n");
+ }
+
+ /* Reset policy of current process to default */
+ void numa_default_policy(void)
+ {
+- do_set_mempolicy(MPOL_DEFAULT, NULL);
++ do_set_mempolicy(MPOL_DEFAULT, 0, NULL);
+ }
+
+-/* Migrate a policy to a different set of nodes */
+-static void mpol_rebind_policy(struct mempolicy *pol,
+- const nodemask_t *newmask)
+-{
+- nodemask_t *mpolmask;
+- nodemask_t tmp;
++/*
++ * Parse and format mempolicy from/to strings
++ */
+
+- if (!pol)
+- return;
+- mpolmask = &pol->cpuset_mems_allowed;
+- if (nodes_equal(*mpolmask, *newmask))
+- return;
++/*
++ * "local" is pseudo-policy: MPOL_PREFERRED with MPOL_F_LOCAL flag
++ * Used only for mpol_parse_str() and mpol_to_str()
++ */
++#define MPOL_LOCAL (MPOL_INTERLEAVE + 1)
++static const char * const policy_types[] =
++ { "default", "prefer", "bind", "interleave", "local" };
+
+- switch (pol->policy) {
+- case MPOL_DEFAULT:
+- break;
+- case MPOL_INTERLEAVE:
+- nodes_remap(tmp, pol->v.nodes, *mpolmask, *newmask);
+- pol->v.nodes = tmp;
+- *mpolmask = *newmask;
+- current->il_next = node_remap(current->il_next,
+- *mpolmask, *newmask);
+- break;
+- case MPOL_PREFERRED:
+- pol->v.preferred_node = node_remap(pol->v.preferred_node,
+- *mpolmask, *newmask);
+- *mpolmask = *newmask;
+- break;
+- case MPOL_BIND: {
+- nodemask_t nodes;
+- struct zone **z;
+- struct zonelist *zonelist;
+
++#ifdef CONFIG_TMPFS
++/**
++ * mpol_parse_str - parse string to mempolicy
++ * @str: string containing mempolicy to parse
++ * @mpol: pointer to struct mempolicy pointer, returned on success.
++ * @no_context: flag whether to "contextualize" the mempolicy
++ *
++ * Format of input:
++ * <mode>[=<flags>][:<nodelist>]
++ *
++ * if @no_context is true, save the input nodemask in w.user_nodemask in
++ * the returned mempolicy. This will be used to "clone" the mempolicy in
++ * a specific context [cpuset] at a later time. Used to parse tmpfs mpol
++ * mount option. Note that if 'static' or 'relative' mode flags were
++ * specified, the input nodemask will already have been saved. Saving
++ * it again is redundant, but safe.
++ *
++ * On success, returns 0, else 1
++ */
++int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)
++{
++ struct mempolicy *new = NULL;
++ unsigned short uninitialized_var(mode);
++ unsigned short uninitialized_var(mode_flags);
++ nodemask_t nodes;
++ char *nodelist = strchr(str, ':');
++ char *flags = strchr(str, '=');
++ int i;
++ int err = 1;
++
++ if (nodelist) {
++ /* NUL-terminate mode or flags string */
++ *nodelist++ = '\0';
++ if (nodelist_parse(nodelist, nodes))
++ goto out;
++ if (!nodes_subset(nodes, node_states[N_HIGH_MEMORY]))
++ goto out;
++ } else
+ nodes_clear(nodes);
+- for (z = pol->v.zonelist->zones; *z; z++)
+- node_set(zone_to_nid(*z), nodes);
+- nodes_remap(tmp, nodes, *mpolmask, *newmask);
+- nodes = tmp;
+
+- zonelist = bind_zonelist(&nodes);
++ if (flags)
++ *flags++ = '\0'; /* terminate mode string */
+
+- /* If no mem, then zonelist is NULL and we keep old zonelist.
+- * If that old zonelist has no remaining mems_allowed nodes,
+- * then zonelist_policy() will "FALL THROUGH" to MPOL_DEFAULT.
+- */
++ for (i = 0; i <= MPOL_LOCAL; i++) {
++ if (!strcmp(str, policy_types[i])) {
++ mode = i;
++ break;
++ }
++ }
++ if (i > MPOL_LOCAL)
++ goto out;
+
+- if (!IS_ERR(zonelist)) {
+- /* Good - got mem - substitute new zonelist */
+- kfree(pol->v.zonelist);
+- pol->v.zonelist = zonelist;
++ switch (mode) {
++ case MPOL_PREFERRED:
++ /*
++ * Insist on a nodelist of one node only
++ */
++ if (nodelist) {
++ char *rest = nodelist;
++ while (isdigit(*rest))
++ rest++;
++ if (!*rest)
++ err = 0;
+ }
+- *mpolmask = *newmask;
+ break;
+- }
+- default:
+- BUG();
++ case MPOL_INTERLEAVE:
++ /*
++ * Default to online nodes with memory if no nodelist
++ */
++ if (!nodelist)
++ nodes = node_states[N_HIGH_MEMORY];
++ err = 0;
++ break;
++ case MPOL_LOCAL:
++ /*
++ * Don't allow a nodelist; mpol_new() checks flags
++ */
++ if (nodelist)
++ goto out;
++ mode = MPOL_PREFERRED;
+ break;
+- }
+-}
+-
+-/*
+- * Wrapper for mpol_rebind_policy() that just requires task
+- * pointer, and updates task mempolicy.
+- */
+
+-void mpol_rebind_task(struct task_struct *tsk, const nodemask_t *new)
+-{
+- mpol_rebind_policy(tsk->mempolicy, new);
+-}
++ /*
++ * case MPOL_BIND: mpol_new() enforces non-empty nodemask.
++ * case MPOL_DEFAULT: mpol_new() enforces empty nodemask, ignores flags.
++ */
++ }
+
+-/*
+- * Rebind each vma in mm to new nodemask.
+- *
+- * Call holding a reference to mm. Takes mm->mmap_sem during call.
+- */
++ mode_flags = 0;
++ if (flags) {
++ /*
++ * Currently, we only support two mutually exclusive
++ * mode flags.
++ */
++ if (!strcmp(flags, "static"))
++ mode_flags |= MPOL_F_STATIC_NODES;
++ else if (!strcmp(flags, "relative"))
++ mode_flags |= MPOL_F_RELATIVE_NODES;
++ else
++ err = 1;
++ }
+
+-void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new)
+-{
+- struct vm_area_struct *vma;
++ new = mpol_new(mode, mode_flags, &nodes);
++ if (IS_ERR(new))
++ err = 1;
++ else if (no_context)
++ new->w.user_nodemask = nodes; /* save for contextualization */
+
+- down_write(&mm->mmap_sem);
+- for (vma = mm->mmap; vma; vma = vma->vm_next)
+- mpol_rebind_policy(vma->vm_policy, new);
+- up_write(&mm->mmap_sem);
++out:
++ /* Restore string for error message */
++ if (nodelist)
++ *--nodelist = ':';
++ if (flags)
++ *--flags = '=';
++ if (!err)
++ *mpol = new;
++ return err;
+ }
++#endif /* CONFIG_TMPFS */
+
+-/*
+- * Display pages allocated per node and memory policy via /proc.
+- */
+-
+-static const char * const policy_types[] =
+- { "default", "prefer", "bind", "interleave" };
+-
+-/*
++/**
++ * mpol_to_str - format a mempolicy structure for printing
++ * @buffer: to contain formatted mempolicy string
++ * @maxlen: length of @buffer
++ * @pol: pointer to mempolicy to be formatted
++ * @no_context: "context free" mempolicy - use nodemask in w.user_nodemask
++ *
+ * Convert a mempolicy into a string.
+ * Returns the number of characters in buffer (if positive)
+ * or an error (negative)
+ */
+-static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
++int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context)
+ {
+ char *p = buffer;
+ int l;
+ nodemask_t nodes;
+- int mode = pol ? pol->policy : MPOL_DEFAULT;
++ unsigned short mode;
++ unsigned short flags = pol ? pol->flags : 0;
++
++ /*
++ * Sanity check: room for longest mode, flag and some nodes
++ */
++ VM_BUG_ON(maxlen < strlen("interleave") + strlen("relative") + 16);
++
++ if (!pol || pol == &default_policy)
++ mode = MPOL_DEFAULT;
++ else
++ mode = pol->mode;
+
+ switch (mode) {
+ case MPOL_DEFAULT:
+@@ -1867,33 +2122,50 @@ static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
+
+ case MPOL_PREFERRED:
+ nodes_clear(nodes);
+- node_set(pol->v.preferred_node, nodes);
++ if (flags & MPOL_F_LOCAL)
++ mode = MPOL_LOCAL; /* pseudo-policy */
++ else
++ node_set(pol->v.preferred_node, nodes);
+ break;
+
+ case MPOL_BIND:
+- get_zonemask(pol, &nodes);
+- break;
+-
++ /* Fall through */
+ case MPOL_INTERLEAVE:
+- nodes = pol->v.nodes;
++ if (no_context)
++ nodes = pol->w.user_nodemask;
++ else
++ nodes = pol->v.nodes;
+ break;
+
+ default:
+ BUG();
+- return -EFAULT;
+ }
+
+ l = strlen(policy_types[mode]);
+- if (buffer + maxlen < p + l + 1)
+- return -ENOSPC;
++ if (buffer + maxlen < p + l + 1)
++ return -ENOSPC;
+
+ strcpy(p, policy_types[mode]);
+ p += l;
+
+- if (!nodes_empty(nodes)) {
++ if (flags & MPOL_MODE_FLAGS) {
+ if (buffer + maxlen < p + 2)
+ return -ENOSPC;
+ *p++ = '=';
++
++ /*
++ * Currently, the only defined flags are mutually exclusive
++ */
++ if (flags & MPOL_F_STATIC_NODES)
++ p += snprintf(p, buffer + maxlen - p, "static");
++ else if (flags & MPOL_F_RELATIVE_NODES)
++ p += snprintf(p, buffer + maxlen - p, "relative");
++ }
++
++ if (!nodes_empty(nodes)) {
++ if (buffer + maxlen < p + 2)
++ return -ENOSPC;
++ *p++ = ':';
+ p += nodelist_scnprintf(p, buffer + maxlen - p, nodes);
+ }
+ return p - buffer;
+@@ -1971,6 +2243,9 @@ static inline void check_huge_range(struct vm_area_struct *vma,
+ }
+ #endif
+
++/*
++ * Display pages allocated per node and memory policy via /proc.
++ */
+ int show_numa_map(struct seq_file *m, void *v)
+ {
+ struct proc_maps_private *priv = m->private;
+@@ -1990,12 +2265,8 @@ int show_numa_map(struct seq_file *m, void *v)
+ return 0;
+
+ pol = get_vma_policy(priv->task, vma, vma->vm_start);
+- mpol_to_str(buffer, sizeof(buffer), pol);
+- /*
+- * unref shared or other task's mempolicy
+- */
+- if (pol != &default_policy && pol != current->mempolicy)
+- __mpol_free(pol);
++ mpol_to_str(buffer, sizeof(buffer), pol, 0);
++ mpol_cond_put(pol);
+
+ seq_printf(m, "%08lx %s", vma->vm_start, buffer);
+
+diff --git a/mm/migrate.c b/mm/migrate.c
+index 4e0eccc..449d77d 100644
+--- a/mm/migrate.c
++++ b/mm/migrate.c
+@@ -383,7 +383,14 @@ static void migrate_page_copy(struct page *newpage, struct page *page)
+
+ if (PageDirty(page)) {
+ clear_page_dirty_for_io(page);
+- set_page_dirty(newpage);
++ /*
++ * Want to mark the page and the radix tree as dirty, and
++ * redo the accounting that clear_page_dirty_for_io undid,
++ * but we can't use set_page_dirty because that function
++ * is actually a signal that all of the page has become dirty.
++ * Wheras only part of our page may be dirty.
++ */
++ __set_page_dirty_nobuffers(newpage);
+ }
+
+ #ifdef CONFIG_SWAP
+diff --git a/mm/mincore.c b/mm/mincore.c
+index 5efe0de..5178800 100644
+--- a/mm/mincore.c
++++ b/mm/mincore.c
+@@ -33,7 +33,7 @@ static unsigned char mincore_page(struct address_space *mapping, pgoff_t pgoff)
+ * When tmpfs swaps out a page from a file, any process mapping that
+ * file will not get a swp_entry_t in its pte, but rather it is like
+ * any other file mapping (ie. marked !present and faulted in with
+- * tmpfs's .nopage). So swapped out tmpfs mappings are tested here.
++ * tmpfs's .fault). So swapped out tmpfs mappings are tested here.
+ *
+ * However when tmpfs moves the page from pagecache and into swapcache,
+ * it is still in core, but the find_get_page below won't find it.
+diff --git a/mm/mmap.c b/mm/mmap.c
+index a32d28c..fac6633 100644
+--- a/mm/mmap.c
++++ b/mm/mmap.c
+@@ -230,9 +230,12 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma)
+ might_sleep();
+ if (vma->vm_ops && vma->vm_ops->close)
+ vma->vm_ops->close(vma);
+- if (vma->vm_file)
++ if (vma->vm_file) {
+ fput(vma->vm_file);
+- mpol_free(vma_policy(vma));
++ if (vma->vm_flags & VM_EXECUTABLE)
++ removed_exe_file_vma(vma->vm_mm);
++ }
++ mpol_put(vma_policy(vma));
+ kmem_cache_free(vm_area_cachep, vma);
+ return next;
+ }
+@@ -623,10 +626,13 @@ again: remove_next = 1 + (end > next->vm_end);
+ spin_unlock(&mapping->i_mmap_lock);
+
+ if (remove_next) {
+- if (file)
++ if (file) {
+ fput(file);
++ if (next->vm_flags & VM_EXECUTABLE)
++ removed_exe_file_vma(mm);
++ }
+ mm->map_count--;
+- mpol_free(vma_policy(next));
++ mpol_put(vma_policy(next));
+ kmem_cache_free(vm_area_cachep, next);
+ /*
+ * In mprotect's case 6 (see comments on vma_merge),
+@@ -1068,7 +1074,6 @@ int vma_wants_writenotify(struct vm_area_struct *vma)
+ mapping_cap_account_dirty(vma->vm_file->f_mapping);
+ }
+
+-
+ unsigned long mmap_region(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long flags,
+ unsigned int vm_flags, unsigned long pgoff,
+@@ -1155,6 +1160,8 @@ munmap_back:
+ error = file->f_op->mmap(file, vma);
+ if (error)
+ goto unmap_and_free_vma;
++ if (vm_flags & VM_EXECUTABLE)
++ added_exe_file_vma(mm);
+ } else if (vm_flags & VM_SHARED) {
+ error = shmem_zero_setup(vma);
+ if (error)
+@@ -1181,22 +1188,22 @@ munmap_back:
+ if (vma_wants_writenotify(vma))
+ vma->vm_page_prot = vm_get_page_prot(vm_flags & ~VM_SHARED);
+
+- if (!file || !vma_merge(mm, prev, addr, vma->vm_end,
++ if (file && vma_merge(mm, prev, addr, vma->vm_end,
+ vma->vm_flags, NULL, file, pgoff, vma_policy(vma))) {
+- file = vma->vm_file;
+- vma_link(mm, vma, prev, rb_link, rb_parent);
+- if (correct_wcount)
+- atomic_inc(&inode->i_writecount);
+- } else {
+- if (file) {
+- if (correct_wcount)
+- atomic_inc(&inode->i_writecount);
+- fput(file);
- }
-- 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;
+- mpol_free(vma_policy(vma));
++ mpol_put(vma_policy(vma));
+ kmem_cache_free(vm_area_cachep, vma);
++ fput(file);
++ if (vm_flags & VM_EXECUTABLE)
++ removed_exe_file_vma(mm);
++ } else {
++ vma_link(mm, vma, prev, rb_link, rb_parent);
++ file = vma->vm_file;
+ }
+-out:
++
++ /* Once vma denies write, undo our temporary denial count */
++ if (correct_wcount)
++ atomic_inc(&inode->i_writecount);
++out:
+ mm->total_vm += len >> PAGE_SHIFT;
+ vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
+ if (vm_flags & VM_LOCKED) {
+@@ -1813,15 +1820,18 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
+ new->vm_pgoff += ((addr - vma->vm_start) >> PAGE_SHIFT);
+ }
+
+- pol = mpol_copy(vma_policy(vma));
++ pol = mpol_dup(vma_policy(vma));
+ if (IS_ERR(pol)) {
+ kmem_cache_free(vm_area_cachep, new);
+ return PTR_ERR(pol);
+ }
+ vma_set_policy(new, pol);
+
+- if (new->vm_file)
++ if (new->vm_file) {
+ get_file(new->vm_file);
++ if (vma->vm_flags & VM_EXECUTABLE)
++ added_exe_file_vma(mm);
++ }
+
+ if (new->vm_ops && new->vm_ops->open)
+ new->vm_ops->open(new);
+@@ -2129,7 +2139,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
+ new_vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
+ if (new_vma) {
+ *new_vma = *vma;
+- pol = mpol_copy(vma_policy(vma));
++ pol = mpol_dup(vma_policy(vma));
+ if (IS_ERR(pol)) {
+ kmem_cache_free(vm_area_cachep, new_vma);
+ return NULL;
+@@ -2138,8 +2148,11 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
+ new_vma->vm_start = addr;
+ new_vma->vm_end = addr + len;
+ new_vma->vm_pgoff = pgoff;
+- if (new_vma->vm_file)
++ if (new_vma->vm_file) {
+ get_file(new_vma->vm_file);
++ if (vma->vm_flags & VM_EXECUTABLE)
++ added_exe_file_vma(mm);
++ }
+ if (new_vma->vm_ops && new_vma->vm_ops->open)
+ new_vma->vm_ops->open(new_vma);
+ vma_link(mm, new_vma, prev, rb_link, rb_parent);
+diff --git a/mm/mmzone.c b/mm/mmzone.c
+index eb58386..486ed59 100644
+--- a/mm/mmzone.c
++++ b/mm/mmzone.c
+@@ -42,3 +42,33 @@ struct zone *next_zone(struct zone *zone)
+ return zone;
+ }
+
++static inline int zref_in_nodemask(struct zoneref *zref, nodemask_t *nodes)
++{
++#ifdef CONFIG_NUMA
++ return node_isset(zonelist_node_idx(zref), *nodes);
++#else
++ return 1;
++#endif /* CONFIG_NUMA */
++}
++
++/* Returns the next zone at or below highest_zoneidx in a zonelist */
++struct zoneref *next_zones_zonelist(struct zoneref *z,
++ enum zone_type highest_zoneidx,
++ nodemask_t *nodes,
++ struct zone **zone)
++{
++ /*
++ * Find the next suitable zone to use for the allocation.
++ * Only filter based on nodemask if it's set
++ */
++ if (likely(nodes == NULL))
++ while (zonelist_zone_idx(z) > highest_zoneidx)
++ z++;
++ else
++ while (zonelist_zone_idx(z) > highest_zoneidx ||
++ (z->zone && !zref_in_nodemask(z, nodes)))
++ z++;
++
++ *zone = zonelist_zone(z++);
++ return z;
++}
+diff --git a/mm/nommu.c b/mm/nommu.c
+index 5d8ae08..ef8c62c 100644
+--- a/mm/nommu.c
++++ b/mm/nommu.c
+@@ -105,7 +105,11 @@ unsigned int kobjsize(const void *objp)
+ {
+ struct page *page;
+
+- if (!objp || !((page = virt_to_page(objp))))
++ /*
++ * If the object we have should not have ksize performed on it,
++ * return size of 0
++ */
++ if (!objp || (unsigned long)objp >= memory_end || !((page = virt_to_page(objp))))
+ return 0;
+
+ if (PageSlab(page))
+@@ -962,8 +966,13 @@ unsigned long do_mmap_pgoff(struct file *file,
+
+ INIT_LIST_HEAD(&vma->anon_vma_node);
+ atomic_set(&vma->vm_usage, 1);
+- if (file)
++ if (file) {
+ get_file(file);
++ if (vm_flags & VM_EXECUTABLE) {
++ added_exe_file_vma(current->mm);
++ vma->vm_mm = current->mm;
++ }
++ }
+ vma->vm_file = file;
+ vma->vm_flags = vm_flags;
+ vma->vm_start = addr;
+@@ -1018,8 +1027,11 @@ unsigned long do_mmap_pgoff(struct file *file,
+ up_write(&nommu_vma_sem);
+ kfree(vml);
+ if (vma) {
+- if (vma->vm_file)
++ if (vma->vm_file) {
+ fput(vma->vm_file);
++ if (vma->vm_flags & VM_EXECUTABLE)
++ removed_exe_file_vma(vma->vm_mm);
++ }
+ kfree(vma);
+ }
+ return ret;
+@@ -1049,7 +1061,7 @@ EXPORT_SYMBOL(do_mmap_pgoff);
+ /*
+ * handle mapping disposal for uClinux
+ */
+-static void put_vma(struct vm_area_struct *vma)
++static void put_vma(struct mm_struct *mm, struct vm_area_struct *vma)
+ {
+ if (vma) {
+ down_write(&nommu_vma_sem);
+@@ -1071,8 +1083,11 @@ static void put_vma(struct vm_area_struct *vma)
+ realalloc -= kobjsize(vma);
+ askedalloc -= sizeof(*vma);
+
+- if (vma->vm_file)
++ if (vma->vm_file) {
+ fput(vma->vm_file);
++ if (vma->vm_flags & VM_EXECUTABLE)
++ removed_exe_file_vma(mm);
++ }
+ kfree(vma);
+ }
+
+@@ -1109,7 +1124,7 @@ int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
+ found:
+ vml = *parent;
+
+- put_vma(vml->vma);
++ put_vma(mm, vml->vma);
+
+ *parent = vml->next;
+ realalloc -= kobjsize(vml);
+@@ -1154,7 +1169,7 @@ void exit_mmap(struct mm_struct * mm)
+
+ while ((tmp = mm->context.vmlist)) {
+ mm->context.vmlist = tmp->next;
+- put_vma(tmp->vma);
++ put_vma(mm, tmp->vma);
+
+ realalloc -= kobjsize(tmp);
+ askedalloc -= sizeof(*tmp);
+diff --git a/mm/oom_kill.c b/mm/oom_kill.c
+index beb592f..8a5467e 100644
+--- a/mm/oom_kill.c
++++ b/mm/oom_kill.c
+@@ -53,8 +53,7 @@ static DEFINE_SPINLOCK(zone_scan_mutex);
+ * of least surprise ... (be careful when you change it)
+ */
+
+-unsigned long badness(struct task_struct *p, unsigned long uptime,
+- struct mem_cgroup *mem)
++unsigned long badness(struct task_struct *p, unsigned long uptime)
+ {
+ unsigned long points, cpu_time, run_time, s;
+ struct mm_struct *mm;
+@@ -175,12 +174,14 @@ static inline enum oom_constraint constrained_alloc(struct zonelist *zonelist,
+ gfp_t gfp_mask)
+ {
+ #ifdef CONFIG_NUMA
+- struct zone **z;
++ struct zone *zone;
++ struct zoneref *z;
++ enum zone_type high_zoneidx = gfp_zone(gfp_mask);
+ nodemask_t nodes = node_states[N_HIGH_MEMORY];
+
+- for (z = zonelist->zones; *z; z++)
+- if (cpuset_zone_allowed_softwall(*z, gfp_mask))
+- node_clear(zone_to_nid(*z), nodes);
++ for_each_zone_zonelist(zone, z, zonelist, high_zoneidx)
++ if (cpuset_zone_allowed_softwall(zone, gfp_mask))
++ node_clear(zone_to_nid(zone), nodes);
+ else
+ return CONSTRAINT_CPUSET;
+
+@@ -254,7 +255,7 @@ static struct task_struct *select_bad_process(unsigned long *ppoints,
+ if (p->oomkilladj == OOM_DISABLE)
+ continue;
+
+- points = badness(p, uptime.tv_sec, mem);
++ points = badness(p, uptime.tv_sec);
+ if (points > *ppoints || !chosen) {
+ chosen = p;
+ *ppoints = points;
+@@ -460,29 +461,29 @@ EXPORT_SYMBOL_GPL(unregister_oom_notifier);
+ * if a parallel OOM killing is already taking place that includes a zone in
+ * the zonelist. Otherwise, locks all zones in the zonelist and returns 1.
+ */
+-int try_set_zone_oom(struct zonelist *zonelist)
++int try_set_zone_oom(struct zonelist *zonelist, gfp_t gfp_mask)
+ {
+- struct zone **z;
++ struct zoneref *z;
++ struct zone *zone;
+ int ret = 1;
+
+- z = zonelist->zones;
-
+ spin_lock(&zone_scan_mutex);
+- do {
+- if (zone_is_oom_locked(*z)) {
++ for_each_zone_zonelist(zone, z, zonelist, gfp_zone(gfp_mask)) {
++ if (zone_is_oom_locked(zone)) {
+ ret = 0;
+ goto out;
+ }
+- } while (*(++z) != NULL);
++ }
++
++ for_each_zone_zonelist(zone, z, zonelist, gfp_zone(gfp_mask)) {
++ /*
++ * Lock each zone in the zonelist under zone_scan_mutex so a
++ * parallel invocation of try_set_zone_oom() doesn't succeed
++ * when it shouldn't.
++ */
++ zone_set_flag(zone, ZONE_OOM_LOCKED);
++ }
+
- /*
-- * Add "everybody else" and us into it. They aren't
-- * playing, because we own the spinlock in the
-- * wait_queue_head.
+- * Lock each zone in the zonelist under zone_scan_mutex so a parallel
+- * invocation of try_set_zone_oom() doesn't succeed when it shouldn't.
- */
-- if (!atomic_add_negative(sleepers, &sem->count)) {
-- wake_up_locked(&sem->wait);
-- }
+- z = zonelist->zones;
+- do {
+- zone_set_flag(*z, ZONE_OOM_LOCKED);
+- } while (*(++z) != NULL);
+ out:
+ spin_unlock(&zone_scan_mutex);
+ return ret;
+@@ -493,16 +494,15 @@ out:
+ * allocation attempts with zonelists containing them may now recall the OOM
+ * killer, if necessary.
+ */
+-void clear_zonelist_oom(struct zonelist *zonelist)
++void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_mask)
+ {
+- struct zone **z;
-
-- 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
+- z = zonelist->zones;
++ struct zoneref *z;
++ struct zone *zone;
- 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)
+ spin_lock(&zone_scan_mutex);
+- do {
+- zone_clear_flag(*z, ZONE_OOM_LOCKED);
+- } while (*(++z) != NULL);
++ for_each_zone_zonelist(zone, z, zonelist, gfp_zone(gfp_mask)) {
++ zone_clear_flag(zone, ZONE_OOM_LOCKED);
++ }
+ spin_unlock(&zone_scan_mutex);
+ }
+
+diff --git a/mm/page-writeback.c b/mm/page-writeback.c
+index 5e00f17..789b6ad 100644
+--- a/mm/page-writeback.c
++++ b/mm/page-writeback.c
+@@ -164,9 +164,20 @@ int dirty_ratio_handler(struct ctl_table *table, int write,
+ */
+ static inline void __bdi_writeout_inc(struct backing_dev_info *bdi)
{
-- cpumask_t populated = CPU_MASK_NONE;
-+ cpumask_t populated;
- int cpu;
+- __prop_inc_percpu(&vm_completions, &bdi->completions);
++ __prop_inc_percpu_max(&vm_completions, &bdi->completions,
++ bdi->max_prop_frac);
+ }
-+ cpus_clear(populated);
- for_each_cpu_mask(cpu, *mask)
- if (unlikely(!percpu_populate(__pdata, size, gfp, cpu))) {
- __percpu_depopulate_mask(__pdata, &populated);
-diff --git a/mm/maccess.c b/mm/maccess.c
-new file mode 100644
-index 0000000..ac40796
---- /dev/null
-+++ b/mm/maccess.c
-@@ -0,0 +1,55 @@
-+/*
-+ * Access kernel memory without faulting.
-+ */
-+#include <linux/uaccess.h>
-+#include <linux/module.h>
-+#include <linux/mm.h>
++void bdi_writeout_inc(struct backing_dev_info *bdi)
++{
++ unsigned long flags;
+
-+/**
-+ * 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
++ local_irq_save(flags);
++ __bdi_writeout_inc(bdi);
++ local_irq_restore(flags);
++}
++EXPORT_SYMBOL_GPL(bdi_writeout_inc);
++
+ static inline void task_dirty_inc(struct task_struct *tsk)
+ {
+ prop_inc_single(&vm_dirties, &tsk->dirties);
+@@ -200,7 +211,8 @@ clip_bdi_dirty_limit(struct backing_dev_info *bdi, long dirty, long *pbdi_dirty)
+ avail_dirty = dirty -
+ (global_page_state(NR_FILE_DIRTY) +
+ global_page_state(NR_WRITEBACK) +
+- global_page_state(NR_UNSTABLE_NFS));
++ global_page_state(NR_UNSTABLE_NFS) +
++ global_page_state(NR_WRITEBACK_TEMP));
+
+ if (avail_dirty < 0)
+ avail_dirty = 0;
+@@ -243,6 +255,55 @@ static void task_dirty_limit(struct task_struct *tsk, long *pdirty)
+ }
+
+ /*
+ *
-+ * 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)
++static DEFINE_SPINLOCK(bdi_lock);
++static unsigned int bdi_min_ratio;
++
++int bdi_set_min_ratio(struct backing_dev_info *bdi, unsigned int min_ratio)
+{
-+ long ret;
-+ mm_segment_t old_fs = get_fs();
++ int ret = 0;
++ unsigned long flags;
+
-+ set_fs(KERNEL_DS);
-+ pagefault_disable();
-+ ret = __copy_from_user_inatomic(dst,
-+ (__force const void __user *)src, size);
-+ pagefault_enable();
-+ set_fs(old_fs);
++ spin_lock_irqsave(&bdi_lock, flags);
++ if (min_ratio > bdi->max_ratio) {
++ ret = -EINVAL;
++ } else {
++ min_ratio -= bdi->min_ratio;
++ if (bdi_min_ratio + min_ratio < 100) {
++ bdi_min_ratio += min_ratio;
++ bdi->min_ratio += min_ratio;
++ } else {
++ ret = -EINVAL;
++ }
++ }
++ spin_unlock_irqrestore(&bdi_lock, flags);
+
-+ return ret ? -EFAULT : 0;
++ return ret;
+}
-+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)
++int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned max_ratio)
+{
-+ long ret;
-+ mm_segment_t old_fs = get_fs();
++ unsigned long flags;
++ int ret = 0;
+
-+ set_fs(KERNEL_DS);
-+ pagefault_disable();
-+ ret = __copy_to_user_inatomic((__force void __user *)dst, src, size);
-+ pagefault_enable();
-+ set_fs(old_fs);
++ if (max_ratio > 100)
++ return -EINVAL;
+
-+ return ret ? -EFAULT : 0;
++ spin_lock_irqsave(&bdi_lock, flags);
++ if (bdi->min_ratio > max_ratio) {
++ ret = -EINVAL;
++ } else {
++ bdi->max_ratio = max_ratio;
++ bdi->max_prop_frac = (PROP_FRAC_BASE * max_ratio) / 100;
++ }
++ spin_unlock_irqrestore(&bdi_lock, flags);
++
++ return ret;
+}
-+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);
++EXPORT_SYMBOL(bdi_set_max_ratio);
++
++/*
+ * Work out the current dirty-memory clamping and background writeout
+ * thresholds.
+ *
+@@ -300,7 +361,7 @@ static unsigned long determine_dirtyable_memory(void)
+ return x + 1; /* Ensure that we never return 0 */
+ }
+
+-static void
++void
+ get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty,
+ struct backing_dev_info *bdi)
+ {
+@@ -330,7 +391,7 @@ get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty,
+ *pdirty = dirty;
+
+ if (bdi) {
+- u64 bdi_dirty = dirty;
++ u64 bdi_dirty;
+ long numerator, denominator;
+
+ /*
+@@ -338,8 +399,12 @@ get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty,
+ */
+ bdi_writeout_fraction(bdi, &numerator, &denominator);
+
++ bdi_dirty = (dirty * (100 - bdi_min_ratio)) / 100;
+ bdi_dirty *= numerator;
+ do_div(bdi_dirty, denominator);
++ bdi_dirty += (dirty * bdi->min_ratio) / 100;
++ if (bdi_dirty > (dirty * bdi->max_ratio) / 100)
++ bdi_dirty = dirty * bdi->max_ratio / 100;
+
+ *pbdi_dirty = bdi_dirty;
+ clip_bdi_dirty_limit(bdi, dirty, pbdi_dirty);
+@@ -1192,7 +1257,7 @@ int test_clear_page_writeback(struct page *page)
+ radix_tree_tag_clear(&mapping->page_tree,
+ page_index(page),
+ PAGECACHE_TAG_WRITEBACK);
+- if (bdi_cap_writeback_dirty(bdi)) {
++ if (bdi_cap_account_writeback(bdi)) {
+ __dec_bdi_stat(bdi, BDI_WRITEBACK);
+ __bdi_writeout_inc(bdi);
+ }
+@@ -1221,7 +1286,7 @@ int test_set_page_writeback(struct page *page)
+ radix_tree_tag_set(&mapping->page_tree,
+ page_index(page),
+ PAGECACHE_TAG_WRITEBACK);
+- if (bdi_cap_writeback_dirty(bdi))
++ if (bdi_cap_account_writeback(bdi))
+ __inc_bdi_stat(bdi, BDI_WRITEBACK);
+ }
+ if (!PageDirty(page))
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
-index 402a504..32e796a 100644
+index 402a504..bdd5c43 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)
+@@ -45,6 +45,7 @@
+ #include <linux/fault-inject.h>
+ #include <linux/page-isolation.h>
+ #include <linux/memcontrol.h>
++#include <linux/debugobjects.h>
+
+ #include <asm/tlbflush.h>
+ #include <asm/div64.h>
+@@ -532,8 +533,11 @@ static void __free_pages_ok(struct page *page, unsigned int order)
+ if (reserved)
+ return;
+
+- if (!PageHighMem(page))
++ if (!PageHighMem(page)) {
+ debug_check_no_locks_freed(page_address(page),PAGE_SIZE<<order);
++ debug_check_no_obj_freed(page_address(page),
++ PAGE_SIZE << order);
++ }
+ arch_free_page(page, order);
+ kernel_map_pages(page, 1 << order, 0);
+
+@@ -546,7 +550,7 @@ static void __free_pages_ok(struct page *page, unsigned int order)
+ /*
+ * permit the bootmem allocator to evade page validation on high-order frees
+ */
+-void __init __free_pages_bootmem(struct page *page, unsigned int order)
++void __free_pages_bootmem(struct page *page, unsigned int order)
+ {
+ if (order == 0) {
+ __ClearPageReserved(page);
+@@ -632,7 +636,7 @@ static int prep_new_page(struct page *page, int order, gfp_t gfp_flags)
+ if (PageReserved(page))
+ return 1;
+
+- page->flags &= ~(1 << PG_uptodate | 1 << PG_error | 1 << PG_readahead |
++ page->flags &= ~(1 << PG_uptodate | 1 << PG_error | 1 << PG_reclaim |
+ 1 << PG_referenced | 1 << PG_arch_1 |
+ 1 << PG_owner_priv_1 | 1 << PG_mappedtodisk);
+ set_page_private(page, 0);
+@@ -995,8 +999,10 @@ static void free_hot_cold_page(struct page *page, int cold)
+ if (free_pages_check(page))
+ return;
+
+- if (!PageHighMem(page))
++ if (!PageHighMem(page)) {
+ debug_check_no_locks_freed(page_address(page), PAGE_SIZE);
++ debug_check_no_obj_freed(page_address(page), PAGE_SIZE);
++ }
+ arch_free_page(page, 0);
+ kernel_map_pages(page, 1, 0);
+
+@@ -1050,7 +1056,7 @@ void split_page(struct page *page, unsigned int order)
+ * we cheat by calling it from here, in the order > 0 path. Saves a branch
+ * or two.
+ */
+-static struct page *buffered_rmqueue(struct zonelist *zonelist,
++static struct page *buffered_rmqueue(struct zone *preferred_zone,
+ struct zone *zone, int order, gfp_t gfp_flags)
+ {
+ unsigned long flags;
+@@ -1102,7 +1108,7 @@ again:
+ }
+
+ __count_zone_vm_events(PGALLOC, zone, 1 << order);
+- zone_statistics(zonelist, zone);
++ zone_statistics(preferred_zone, zone);
+ local_irq_restore(flags);
+ put_cpu();
+
+@@ -1284,7 +1290,7 @@ static nodemask_t *zlc_setup(struct zonelist *zonelist, int alloc_flags)
+ if (!zlc)
+ return NULL;
+
+- if (time_after(jiffies, zlc->last_full_zap + HZ)) {
++ if (time_after(jiffies, zlc->last_full_zap + HZ)) {
+ bitmap_zero(zlc->fullzones, MAX_ZONES_PER_ZONELIST);
+ zlc->last_full_zap = jiffies;
+ }
+@@ -1317,7 +1323,7 @@ static nodemask_t *zlc_setup(struct zonelist *zonelist, int alloc_flags)
+ * We are low on memory in the second scan, and should leave no stone
+ * unturned looking for a free page.
+ */
+-static int zlc_zone_worth_trying(struct zonelist *zonelist, struct zone **z,
++static int zlc_zone_worth_trying(struct zonelist *zonelist, struct zoneref *z,
+ nodemask_t *allowednodes)
+ {
+ struct zonelist_cache *zlc; /* cached zonelist speedup info */
+@@ -1328,7 +1334,7 @@ static int zlc_zone_worth_trying(struct zonelist *zonelist, struct zone **z,
+ if (!zlc)
+ return 1;
+
+- i = z - zonelist->zones;
++ i = z - zonelist->_zonerefs;
+ n = zlc->z_to_n[i];
+
+ /* This zone is worth trying if it is allowed but not full */
+@@ -1340,7 +1346,7 @@ static int zlc_zone_worth_trying(struct zonelist *zonelist, struct zone **z,
+ * zlc->fullzones, so that subsequent attempts to allocate a page
+ * from that zone don't waste time re-examining it.
+ */
+-static void zlc_mark_zone_full(struct zonelist *zonelist, struct zone **z)
++static void zlc_mark_zone_full(struct zonelist *zonelist, struct zoneref *z)
+ {
+ struct zonelist_cache *zlc; /* cached zonelist speedup info */
+ int i; /* index of *z in zonelist zones */
+@@ -1349,7 +1355,7 @@ static void zlc_mark_zone_full(struct zonelist *zonelist, struct zone **z)
+ if (!zlc)
+ return;
+
+- i = z - zonelist->zones;
++ i = z - zonelist->_zonerefs;
+
+ set_bit(i, zlc->fullzones);
+ }
+@@ -1361,13 +1367,13 @@ static nodemask_t *zlc_setup(struct zonelist *zonelist, int alloc_flags)
+ return NULL;
+ }
+
+-static int zlc_zone_worth_trying(struct zonelist *zonelist, struct zone **z,
++static int zlc_zone_worth_trying(struct zonelist *zonelist, struct zoneref *z,
+ nodemask_t *allowednodes)
+ {
+ return 1;
+ }
+
+-static void zlc_mark_zone_full(struct zonelist *zonelist, struct zone **z)
++static void zlc_mark_zone_full(struct zonelist *zonelist, struct zoneref *z)
+ {
+ }
+ #endif /* CONFIG_NUMA */
+@@ -1377,42 +1383,31 @@ static void zlc_mark_zone_full(struct zonelist *zonelist, struct zone **z)
+ * a page.
+ */
+ static struct page *
+-get_page_from_freelist(gfp_t gfp_mask, unsigned int order,
+- struct zonelist *zonelist, int alloc_flags)
++get_page_from_freelist(gfp_t gfp_mask, nodemask_t *nodemask, unsigned int order,
++ struct zonelist *zonelist, int high_zoneidx, int alloc_flags)
+ {
+- struct zone **z;
++ struct zoneref *z;
+ struct page *page = NULL;
+- int classzone_idx = zone_idx(zonelist->zones[0]);
+- struct zone *zone;
++ int classzone_idx;
++ struct zone *zone, *preferred_zone;
+ nodemask_t *allowednodes = NULL;/* zonelist_cache approximation */
+ int zlc_active = 0; /* set if using zonelist_cache */
+ int did_zlc_setup = 0; /* just call zlc_setup() one time */
+- enum zone_type highest_zoneidx = -1; /* Gets set for policy zonelists */
++
++ (void)first_zones_zonelist(zonelist, high_zoneidx, nodemask,
++ &preferred_zone);
++ classzone_idx = zone_idx(preferred_zone);
+
+ zonelist_scan:
+ /*
+ * Scan zonelist, looking for a zone with enough free.
+ * See also cpuset_zone_allowed() comment in kernel/cpuset.c.
+ */
+- z = zonelist->zones;
+-
+- do {
+- /*
+- * In NUMA, this could be a policy zonelist which contains
+- * zones that may not be allowed by the current gfp_mask.
+- * Check the zone is allowed by the current flags
+- */
+- if (unlikely(alloc_should_filter_zonelist(zonelist))) {
+- if (highest_zoneidx == -1)
+- highest_zoneidx = gfp_zone(gfp_mask);
+- if (zone_idx(*z) > highest_zoneidx)
+- continue;
+- }
+-
++ for_each_zone_zonelist_nodemask(zone, z, zonelist,
++ high_zoneidx, nodemask) {
+ if (NUMA_BUILD && zlc_active &&
+ !zlc_zone_worth_trying(zonelist, z, allowednodes))
+ continue;
+- zone = *z;
+ if ((alloc_flags & ALLOC_CPUSET) &&
+ !cpuset_zone_allowed_softwall(zone, gfp_mask))
+ goto try_next_zone;
+@@ -1433,7 +1428,7 @@ zonelist_scan:
+ }
+ }
+
+- page = buffered_rmqueue(zonelist, zone, order, gfp_mask);
++ page = buffered_rmqueue(preferred_zone, zone, order, gfp_mask);
+ if (page)
+ break;
+ this_zone_full:
+@@ -1446,7 +1441,7 @@ try_next_zone:
+ zlc_active = 1;
+ did_zlc_setup = 1;
+ }
+- } while (*(++z) != NULL);
++ }
+
+ if (unlikely(NUMA_BUILD && page == NULL && zlc_active)) {
+ /* Disable zlc cache for second zonelist scan */
+@@ -1459,18 +1454,21 @@ try_next_zone:
+ /*
+ * This is the 'heart' of the zoned buddy allocator.
+ */
+-struct page *
+-__alloc_pages(gfp_t gfp_mask, unsigned int order,
+- struct zonelist *zonelist)
++static struct page *
++__alloc_pages_internal(gfp_t gfp_mask, unsigned int order,
++ struct zonelist *zonelist, nodemask_t *nodemask)
+ {
+ const gfp_t wait = gfp_mask & __GFP_WAIT;
+- struct zone **z;
++ enum zone_type high_zoneidx = gfp_zone(gfp_mask);
++ struct zoneref *z;
++ struct zone *zone;
+ struct page *page;
+ struct reclaim_state reclaim_state;
+ struct task_struct *p = current;
+ int do_retry;
+ int alloc_flags;
+- int did_some_progress;
++ unsigned long did_some_progress;
++ unsigned long pages_reclaimed = 0;
+
+ might_sleep_if(wait);
+
+@@ -1478,9 +1476,9 @@ __alloc_pages(gfp_t gfp_mask, unsigned int order,
+ return NULL;
+
+ restart:
+- z = zonelist->zones; /* the list of zones suitable for gfp_mask */
++ z = zonelist->_zonerefs; /* the list of zones suitable for gfp_mask */
+
+- if (unlikely(*z == NULL)) {
++ if (unlikely(!z->zone)) {
+ /*
+ * Happens if we have an empty zonelist as a result of
+ * GFP_THISNODE being used on a memoryless node
+@@ -1488,8 +1486,8 @@ restart:
+ return NULL;
+ }
+
+- page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, order,
+- zonelist, ALLOC_WMARK_LOW|ALLOC_CPUSET);
++ page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, order,
++ zonelist, high_zoneidx, ALLOC_WMARK_LOW|ALLOC_CPUSET);
+ if (page)
+ goto got_pg;
+
+@@ -1504,8 +1502,8 @@ restart:
+ if (NUMA_BUILD && (gfp_mask & GFP_THISNODE) == GFP_THISNODE)
+ goto nopage;
+
+- for (z = zonelist->zones; *z; z++)
+- wakeup_kswapd(*z, order);
++ for_each_zone_zonelist(zone, z, zonelist, high_zoneidx)
++ wakeup_kswapd(zone, order);
+
+ /*
+ * OK, we're below the kswapd watermark and have kicked background
+@@ -1533,7 +1531,8 @@ restart:
+ * Ignore cpuset if GFP_ATOMIC (!wait) rather than fail alloc.
+ * See also cpuset_zone_allowed() comment in kernel/cpuset.c.
+ */
+- page = get_page_from_freelist(gfp_mask, order, zonelist, alloc_flags);
++ page = get_page_from_freelist(gfp_mask, nodemask, order, zonelist,
++ high_zoneidx, alloc_flags);
+ if (page)
+ goto got_pg;
+
+@@ -1545,8 +1544,8 @@ rebalance:
+ if (!(gfp_mask & __GFP_NOMEMALLOC)) {
+ nofail_alloc:
+ /* go through the zonelist yet again, ignoring mins */
+- page = get_page_from_freelist(gfp_mask, order,
+- zonelist, ALLOC_NO_WATERMARKS);
++ page = get_page_from_freelist(gfp_mask, nodemask, order,
++ zonelist, high_zoneidx, ALLOC_NO_WATERMARKS);
+ if (page)
+ goto got_pg;
+ if (gfp_mask & __GFP_NOFAIL) {
+@@ -1569,7 +1568,7 @@ nofail_alloc:
+ reclaim_state.reclaimed_slab = 0;
+ p->reclaim_state = &reclaim_state;
+
+- did_some_progress = try_to_free_pages(zonelist->zones, order, gfp_mask);
++ did_some_progress = try_to_free_pages(zonelist, order, gfp_mask);
+
+ p->reclaim_state = NULL;
+ p->flags &= ~PF_MEMALLOC;
+@@ -1580,12 +1579,12 @@ nofail_alloc:
+ drain_all_pages();
+
+ if (likely(did_some_progress)) {
+- page = get_page_from_freelist(gfp_mask, order,
+- zonelist, alloc_flags);
++ page = get_page_from_freelist(gfp_mask, nodemask, order,
++ zonelist, high_zoneidx, alloc_flags);
+ if (page)
+ goto got_pg;
+ } else if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) {
+- if (!try_set_zone_oom(zonelist)) {
++ if (!try_set_zone_oom(zonelist, gfp_mask)) {
+ schedule_timeout_uninterruptible(1);
+ goto restart;
+ }
+@@ -1596,21 +1595,22 @@ nofail_alloc:
+ * a parallel oom killing, we must fail if we're still
+ * under heavy pressure.
+ */
+- page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, order,
+- zonelist, ALLOC_WMARK_HIGH|ALLOC_CPUSET);
++ page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask,
++ order, zonelist, high_zoneidx,
++ ALLOC_WMARK_HIGH|ALLOC_CPUSET);
+ if (page) {
+- clear_zonelist_oom(zonelist);
++ clear_zonelist_oom(zonelist, gfp_mask);
+ goto got_pg;
+ }
+
+ /* The OOM killer will not help higher order allocs so fail */
+ if (order > PAGE_ALLOC_COSTLY_ORDER) {
+- clear_zonelist_oom(zonelist);
++ clear_zonelist_oom(zonelist, gfp_mask);
+ goto nopage;
+ }
+
+ out_of_memory(zonelist, gfp_mask, order);
+- clear_zonelist_oom(zonelist);
++ clear_zonelist_oom(zonelist, gfp_mask);
+ goto restart;
+ }
+
+@@ -1618,14 +1618,26 @@ nofail_alloc:
+ * Don't let big-order allocations loop unless the caller explicitly
+ * requests that. Wait for some write requests to complete then retry.
+ *
+- * In this implementation, __GFP_REPEAT means __GFP_NOFAIL for order
+- * <= 3, but that may not be true in other implementations.
++ * In this implementation, order <= PAGE_ALLOC_COSTLY_ORDER
++ * means __GFP_NOFAIL, but that may not be true in other
++ * implementations.
++ *
++ * For order > PAGE_ALLOC_COSTLY_ORDER, if __GFP_REPEAT is
++ * specified, then we retry until we no longer reclaim any pages
++ * (above), or we've reclaimed an order of pages at least as
++ * large as the allocation's order. In both cases, if the
++ * allocation still fails, we stop retrying.
+ */
++ pages_reclaimed += did_some_progress;
+ do_retry = 0;
+ if (!(gfp_mask & __GFP_NORETRY)) {
+- if ((order <= PAGE_ALLOC_COSTLY_ORDER) ||
+- (gfp_mask & __GFP_REPEAT))
++ if (order <= PAGE_ALLOC_COSTLY_ORDER) {
+ do_retry = 1;
++ } else {
++ if (gfp_mask & __GFP_REPEAT &&
++ pages_reclaimed < (1 << order))
++ do_retry = 1;
++ }
+ if (gfp_mask & __GFP_NOFAIL)
+ do_retry = 1;
+ }
+@@ -1646,6 +1658,20 @@ got_pg:
+ return page;
+ }
+
++struct page *
++__alloc_pages(gfp_t gfp_mask, unsigned int order,
++ struct zonelist *zonelist)
++{
++ return __alloc_pages_internal(gfp_mask, order, zonelist, NULL);
++}
++
++struct page *
++__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
++ struct zonelist *zonelist, nodemask_t *nodemask)
++{
++ return __alloc_pages_internal(gfp_mask, order, zonelist, nodemask);
++}
++
+ EXPORT_SYMBOL(__alloc_pages);
+
+ /*
+@@ -1712,15 +1738,15 @@ EXPORT_SYMBOL(free_pages);
+
+ static unsigned int nr_free_zone_pages(int offset)
+ {
++ struct zoneref *z;
++ struct zone *zone;
++
+ /* Just pick one node, since fallback list is circular */
+- pg_data_t *pgdat = NODE_DATA(numa_node_id());
+ unsigned int sum = 0;
+
+- struct zonelist *zonelist = pgdat->node_zonelists + offset;
+- struct zone **zonep = zonelist->zones;
+- struct zone *zone;
++ struct zonelist *zonelist = node_zonelist(numa_node_id(), GFP_KERNEL);
+
+- for (zone = *zonep++; zone; zone = *zonep++) {
++ for_each_zone_zonelist(zone, z, zonelist, offset) {
+ unsigned long size = zone->present_pages;
+ unsigned long high = zone->pages_high;
+ if (size > high)
+@@ -1889,6 +1915,12 @@ void show_free_areas(void)
+ show_swap_cache_info();
+ }
+
++static void zoneref_set_zone(struct zone *zone, struct zoneref *zoneref)
++{
++ zoneref->zone = zone;
++ zoneref->zone_idx = zone_idx(zone);
++}
++
+ /*
+ * Builds allocation fallback zone lists.
+ *
+@@ -1906,7 +1938,8 @@ static int build_zonelists_node(pg_data_t *pgdat, struct zonelist *zonelist,
+ zone_type--;
+ zone = pgdat->node_zones + zone_type;
+ if (populated_zone(zone)) {
+- zonelist->zones[nr_zones++] = zone;
++ zoneref_set_zone(zone,
++ &zonelist->_zonerefs[nr_zones++]);
+ check_highest_zone(zone_type);
+ }
+
+@@ -2029,6 +2062,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;
@@ -840764,7 +1137443,7 @@
/* 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)
+@@ -2037,7 +2071,6 @@ static int find_next_best_node(int node, nodemask_t *used_node_mask)
}
for_each_node_state(n, N_HIGH_MEMORY) {
@@ -840772,7 +1137451,7 @@
/* 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)
+@@ -2050,8 +2083,8 @@ static int find_next_best_node(int node, nodemask_t *used_node_mask)
val += (n < node);
/* Give preference to headless and unused nodes */
@@ -840783,6 +1137462,280 @@
val += PENALTY_FOR_NODE_WITH_CPUS;
/* Slight preference for less loaded node */
+@@ -2078,17 +2111,16 @@ static int find_next_best_node(int node, nodemask_t *used_node_mask)
+ */
+ static void build_zonelists_in_node_order(pg_data_t *pgdat, int node)
+ {
+- enum zone_type i;
+ int j;
+ struct zonelist *zonelist;
+
+- for (i = 0; i < MAX_NR_ZONES; i++) {
+- zonelist = pgdat->node_zonelists + i;
+- for (j = 0; zonelist->zones[j] != NULL; j++)
+- ;
+- j = build_zonelists_node(NODE_DATA(node), zonelist, j, i);
+- zonelist->zones[j] = NULL;
+- }
++ zonelist = &pgdat->node_zonelists[0];
++ for (j = 0; zonelist->_zonerefs[j].zone != NULL; j++)
++ ;
++ j = build_zonelists_node(NODE_DATA(node), zonelist, j,
++ MAX_NR_ZONES - 1);
++ zonelist->_zonerefs[j].zone = NULL;
++ zonelist->_zonerefs[j].zone_idx = 0;
+ }
+
+ /*
+@@ -2096,15 +2128,13 @@ static void build_zonelists_in_node_order(pg_data_t *pgdat, int node)
+ */
+ static void build_thisnode_zonelists(pg_data_t *pgdat)
+ {
+- enum zone_type i;
+ int j;
+ struct zonelist *zonelist;
+
+- for (i = 0; i < MAX_NR_ZONES; i++) {
+- zonelist = pgdat->node_zonelists + MAX_NR_ZONES + i;
+- j = build_zonelists_node(pgdat, zonelist, 0, i);
+- zonelist->zones[j] = NULL;
+- }
++ zonelist = &pgdat->node_zonelists[1];
++ j = build_zonelists_node(pgdat, zonelist, 0, MAX_NR_ZONES - 1);
++ zonelist->_zonerefs[j].zone = NULL;
++ zonelist->_zonerefs[j].zone_idx = 0;
+ }
+
+ /*
+@@ -2117,27 +2147,26 @@ static int node_order[MAX_NUMNODES];
+
+ static void build_zonelists_in_zone_order(pg_data_t *pgdat, int nr_nodes)
+ {
+- enum zone_type i;
+ int pos, j, node;
+ int zone_type; /* needs to be signed */
+ struct zone *z;
+ struct zonelist *zonelist;
+
+- for (i = 0; i < MAX_NR_ZONES; i++) {
+- zonelist = pgdat->node_zonelists + i;
+- pos = 0;
+- for (zone_type = i; zone_type >= 0; zone_type--) {
+- for (j = 0; j < nr_nodes; j++) {
+- node = node_order[j];
+- z = &NODE_DATA(node)->node_zones[zone_type];
+- if (populated_zone(z)) {
+- zonelist->zones[pos++] = z;
+- check_highest_zone(zone_type);
+- }
++ zonelist = &pgdat->node_zonelists[0];
++ pos = 0;
++ for (zone_type = MAX_NR_ZONES - 1; zone_type >= 0; zone_type--) {
++ for (j = 0; j < nr_nodes; j++) {
++ node = node_order[j];
++ z = &NODE_DATA(node)->node_zones[zone_type];
++ if (populated_zone(z)) {
++ zoneref_set_zone(z,
++ &zonelist->_zonerefs[pos++]);
++ check_highest_zone(zone_type);
+ }
+ }
+- zonelist->zones[pos] = NULL;
+ }
++ zonelist->_zonerefs[pos].zone = NULL;
++ zonelist->_zonerefs[pos].zone_idx = 0;
+ }
+
+ static int default_zonelist_order(void)
+@@ -2214,7 +2243,8 @@ static void build_zonelists(pg_data_t *pgdat)
+ /* initialize zonelists */
+ for (i = 0; i < MAX_ZONELISTS; i++) {
+ zonelist = pgdat->node_zonelists + i;
+- zonelist->zones[0] = NULL;
++ zonelist->_zonerefs[0].zone = NULL;
++ zonelist->_zonerefs[0].zone_idx = 0;
+ }
+
+ /* NUMA-aware ordering of nodes */
+@@ -2264,19 +2294,15 @@ static void build_zonelists(pg_data_t *pgdat)
+ /* Construct the zonelist performance cache - see further mmzone.h */
+ static void build_zonelist_cache(pg_data_t *pgdat)
+ {
+- int i;
+-
+- for (i = 0; i < MAX_NR_ZONES; i++) {
+- struct zonelist *zonelist;
+- struct zonelist_cache *zlc;
+- struct zone **z;
++ struct zonelist *zonelist;
++ struct zonelist_cache *zlc;
++ struct zoneref *z;
+
+- zonelist = pgdat->node_zonelists + i;
+- zonelist->zlcache_ptr = zlc = &zonelist->zlcache;
+- bitmap_zero(zlc->fullzones, MAX_ZONES_PER_ZONELIST);
+- for (z = zonelist->zones; *z; z++)
+- zlc->z_to_n[z - zonelist->zones] = zone_to_nid(*z);
+- }
++ zonelist = &pgdat->node_zonelists[0];
++ zonelist->zlcache_ptr = zlc = &zonelist->zlcache;
++ bitmap_zero(zlc->fullzones, MAX_ZONES_PER_ZONELIST);
++ for (z = zonelist->_zonerefs; z->zone; z++)
++ zlc->z_to_n[z - zonelist->_zonerefs] = zonelist_node_idx(z);
+ }
+
+
+@@ -2290,45 +2316,44 @@ static void set_zonelist_order(void)
+ static void build_zonelists(pg_data_t *pgdat)
+ {
+ int node, local_node;
+- enum zone_type i,j;
++ enum zone_type j;
++ struct zonelist *zonelist;
+
+ local_node = pgdat->node_id;
+- for (i = 0; i < MAX_NR_ZONES; i++) {
+- struct zonelist *zonelist;
+-
+- zonelist = pgdat->node_zonelists + i;
+
+- j = build_zonelists_node(pgdat, zonelist, 0, i);
+- /*
+- * Now we build the zonelist so that it contains the zones
+- * of all the other nodes.
+- * We don't want to pressure a particular node, so when
+- * building the zones for node N, we make sure that the
+- * zones coming right after the local ones are those from
+- * node N+1 (modulo N)
+- */
+- for (node = local_node + 1; node < MAX_NUMNODES; node++) {
+- if (!node_online(node))
+- continue;
+- j = build_zonelists_node(NODE_DATA(node), zonelist, j, i);
+- }
+- for (node = 0; node < local_node; node++) {
+- if (!node_online(node))
+- continue;
+- j = build_zonelists_node(NODE_DATA(node), zonelist, j, i);
+- }
++ zonelist = &pgdat->node_zonelists[0];
++ j = build_zonelists_node(pgdat, zonelist, 0, MAX_NR_ZONES - 1);
+
+- zonelist->zones[j] = NULL;
++ /*
++ * Now we build the zonelist so that it contains the zones
++ * of all the other nodes.
++ * We don't want to pressure a particular node, so when
++ * building the zones for node N, we make sure that the
++ * zones coming right after the local ones are those from
++ * node N+1 (modulo N)
++ */
++ for (node = local_node + 1; node < MAX_NUMNODES; node++) {
++ if (!node_online(node))
++ continue;
++ j = build_zonelists_node(NODE_DATA(node), zonelist, j,
++ MAX_NR_ZONES - 1);
+ }
++ for (node = 0; node < local_node; node++) {
++ if (!node_online(node))
++ continue;
++ j = build_zonelists_node(NODE_DATA(node), zonelist, j,
++ MAX_NR_ZONES - 1);
++ }
++
++ zonelist->_zonerefs[j].zone = NULL;
++ zonelist->_zonerefs[j].zone_idx = 0;
+ }
+
+ /* non-NUMA variant of zonelist performance cache - just NULL zlcache_ptr */
+ static void build_zonelist_cache(pg_data_t *pgdat)
+ {
+- int i;
+-
+- for (i = 0; i < MAX_NR_ZONES; i++)
+- pgdat->node_zonelists[i].zlcache_ptr = NULL;
++ pgdat->node_zonelists[0].zlcache_ptr = NULL;
++ pgdat->node_zonelists[1].zlcache_ptr = NULL;
+ }
+
+ #endif /* CONFIG_NUMA */
+@@ -2518,7 +2543,9 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
+ struct page *page;
+ unsigned long end_pfn = start_pfn + size;
+ unsigned long pfn;
++ struct zone *z;
+
++ z = &NODE_DATA(nid)->node_zones[zone];
+ for (pfn = start_pfn; pfn < end_pfn; pfn++) {
+ /*
+ * There can be holes in boot-time mem_map[]s
+@@ -2536,7 +2563,6 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
+ init_page_count(page);
+ reset_page_mapcount(page);
+ SetPageReserved(page);
+-
+ /*
+ * Mark the block movable so that blocks are reserved for
+ * movable at startup. This will force kernel allocations
+@@ -2545,8 +2571,15 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
+ * kernel allocations are made. Later some blocks near
+ * the start are marked MIGRATE_RESERVE by
+ * setup_zone_migrate_reserve()
++ *
++ * bitmap is created for zone's valid pfn range. but memmap
++ * can be created for invalid pages (for alignment)
++ * check here not to call set_pageblock_migratetype() against
++ * pfn out of zone.
+ */
+- if ((pfn & (pageblock_nr_pages-1)))
++ if ((z->zone_start_pfn <= pfn)
++ && (pfn < z->zone_start_pfn + z->spanned_pages)
++ && !(pfn & (pageblock_nr_pages - 1)))
+ set_pageblock_migratetype(page, MIGRATE_MOVABLE);
+
+ INIT_LIST_HEAD(&page->lru);
+@@ -4339,9 +4372,7 @@ void *__init alloc_large_system_hash(const char *tablename,
+ else if (hashdist)
+ table = __vmalloc(size, GFP_ATOMIC, PAGE_KERNEL);
+ else {
+- unsigned long order;
+- for (order = 0; ((1UL << order) << PAGE_SHIFT) < size; order++)
+- ;
++ unsigned long order = get_order(size);
+ table = (void*) __get_free_pages(GFP_ATOMIC, order);
+ /*
+ * If bucketsize is not a power-of-two, we may free
+@@ -4460,6 +4491,8 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags,
+ pfn = page_to_pfn(page);
+ bitmap = get_pageblock_bitmap(zone, pfn);
+ bitidx = pfn_to_bitidx(zone, pfn);
++ VM_BUG_ON(pfn < zone->zone_start_pfn);
++ VM_BUG_ON(pfn >= zone->zone_start_pfn + zone->spanned_pages);
+
+ for (; start_bitidx <= end_bitidx; start_bitidx++, value <<= 1)
+ if (flags & value)
+diff --git a/mm/pagewalk.c b/mm/pagewalk.c
+index 1cf1417..0afd238 100644
+--- a/mm/pagewalk.c
++++ b/mm/pagewalk.c
+@@ -9,11 +9,15 @@ static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
+ int err = 0;
+
+ pte = pte_offset_map(pmd, addr);
+- do {
++ for (;;) {
+ err = walk->pte_entry(pte, addr, addr + PAGE_SIZE, private);
+ if (err)
+ break;
+- } while (pte++, addr += PAGE_SIZE, addr != end);
++ addr += PAGE_SIZE;
++ if (addr == end)
++ break;
++ pte++;
++ }
+
+ pte_unmap(pte);
+ return err;
diff --git a/mm/pdflush.c b/mm/pdflush.c
index 8f6ee07..1c96cfc 100644
--- a/mm/pdflush.c
@@ -840809,11 +1137762,357 @@
return __pdflush(&my_work);
}
+diff --git a/mm/readahead.c b/mm/readahead.c
+index 8762e89..d8723a5 100644
+--- a/mm/readahead.c
++++ b/mm/readahead.c
+@@ -235,7 +235,13 @@ unsigned long max_sane_readahead(unsigned long nr)
+
+ static int __init readahead_init(void)
+ {
+- return bdi_init(&default_backing_dev_info);
++ int err;
++
++ err = bdi_init(&default_backing_dev_info);
++ if (!err)
++ bdi_register(&default_backing_dev_info, NULL, "default");
++
++ return err;
+ }
+ subsys_initcall(readahead_init);
+
+diff --git a/mm/rmap.c b/mm/rmap.c
+index 997f069..bf0a5b7 100644
+--- a/mm/rmap.c
++++ b/mm/rmap.c
+@@ -413,9 +413,6 @@ int page_referenced(struct page *page, int is_locked,
+ {
+ int referenced = 0;
+
+- if (page_test_and_clear_young(page))
+- referenced++;
+-
+ if (TestClearPageReferenced(page))
+ referenced++;
+
+@@ -433,6 +430,10 @@ int page_referenced(struct page *page, int is_locked,
+ unlock_page(page);
+ }
+ }
++
++ if (page_test_and_clear_young(page))
++ referenced++;
++
+ return referenced;
+ }
+
+@@ -661,7 +662,6 @@ void page_remove_rmap(struct page *page, struct vm_area_struct *vma)
+ printk (KERN_EMERG " page->mapping = %p\n", page->mapping);
+ print_symbol (KERN_EMERG " vma->vm_ops = %s\n", (unsigned long)vma->vm_ops);
+ if (vma->vm_ops) {
+- print_symbol (KERN_EMERG " vma->vm_ops->nopage = %s\n", (unsigned long)vma->vm_ops->nopage);
+ print_symbol (KERN_EMERG " vma->vm_ops->fault = %s\n", (unsigned long)vma->vm_ops->fault);
+ }
+ if (vma->vm_file && vma->vm_file->f_op)
+diff --git a/mm/shmem.c b/mm/shmem.c
+index f514dd3..e2a6ae1 100644
+--- a/mm/shmem.c
++++ b/mm/shmem.c
+@@ -201,7 +201,7 @@ static struct vm_operations_struct shmem_vm_ops;
+
+ static struct backing_dev_info shmem_backing_dev_info __read_mostly = {
+ .ra_pages = 0, /* No readahead */
+- .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
++ .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK,
+ .unplug_io_fn = default_unplug_io_fn,
+ };
+
+@@ -1079,104 +1079,47 @@ redirty:
+
+ #ifdef CONFIG_NUMA
+ #ifdef CONFIG_TMPFS
+-static int shmem_parse_mpol(char *value, int *policy, nodemask_t *policy_nodes)
++static void shmem_show_mpol(struct seq_file *seq, struct mempolicy *mpol)
+ {
+- char *nodelist = strchr(value, ':');
+- int err = 1;
++ char buffer[64];
+
+- if (nodelist) {
+- /* NUL-terminate policy string */
+- *nodelist++ = '\0';
+- if (nodelist_parse(nodelist, *policy_nodes))
+- goto out;
+- if (!nodes_subset(*policy_nodes, node_states[N_HIGH_MEMORY]))
+- goto out;
+- }
+- if (!strcmp(value, "default")) {
+- *policy = MPOL_DEFAULT;
+- /* Don't allow a nodelist */
+- if (!nodelist)
+- err = 0;
+- } else if (!strcmp(value, "prefer")) {
+- *policy = MPOL_PREFERRED;
+- /* Insist on a nodelist of one node only */
+- if (nodelist) {
+- char *rest = nodelist;
+- while (isdigit(*rest))
+- rest++;
+- if (!*rest)
+- err = 0;
+- }
+- } else if (!strcmp(value, "bind")) {
+- *policy = MPOL_BIND;
+- /* Insist on a nodelist */
+- if (nodelist)
+- err = 0;
+- } else if (!strcmp(value, "interleave")) {
+- *policy = MPOL_INTERLEAVE;
+- /*
+- * Default to online nodes with memory if no nodelist
+- */
+- if (!nodelist)
+- *policy_nodes = node_states[N_HIGH_MEMORY];
+- err = 0;
+- }
+-out:
+- /* Restore string for error message */
+- if (nodelist)
+- *--nodelist = ':';
+- return err;
+-}
+-
+-static void shmem_show_mpol(struct seq_file *seq, int policy,
+- const nodemask_t policy_nodes)
+-{
+- char *policy_string;
++ if (!mpol || mpol->mode == MPOL_DEFAULT)
++ return; /* show nothing */
+
+- switch (policy) {
+- case MPOL_PREFERRED:
+- policy_string = "prefer";
+- break;
+- case MPOL_BIND:
+- policy_string = "bind";
+- break;
+- case MPOL_INTERLEAVE:
+- policy_string = "interleave";
+- break;
+- default:
+- /* MPOL_DEFAULT */
+- return;
+- }
++ mpol_to_str(buffer, sizeof(buffer), mpol, 1);
+
+- seq_printf(seq, ",mpol=%s", policy_string);
+-
+- if (policy != MPOL_INTERLEAVE ||
+- !nodes_equal(policy_nodes, node_states[N_HIGH_MEMORY])) {
+- char buffer[64];
+- int len;
++ seq_printf(seq, ",mpol=%s", buffer);
++}
+
+- len = nodelist_scnprintf(buffer, sizeof(buffer), policy_nodes);
+- if (len < sizeof(buffer))
+- seq_printf(seq, ":%s", buffer);
+- else
+- seq_printf(seq, ":?");
++static struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo)
++{
++ struct mempolicy *mpol = NULL;
++ if (sbinfo->mpol) {
++ spin_lock(&sbinfo->stat_lock); /* prevent replace/use races */
++ mpol = sbinfo->mpol;
++ mpol_get(mpol);
++ spin_unlock(&sbinfo->stat_lock);
+ }
++ return mpol;
+ }
+ #endif /* CONFIG_TMPFS */
+
+ static struct page *shmem_swapin(swp_entry_t entry, gfp_t gfp,
+ struct shmem_inode_info *info, unsigned long idx)
+ {
++ struct mempolicy mpol, *spol;
+ struct vm_area_struct pvma;
+ struct page *page;
+
++ spol = mpol_cond_copy(&mpol,
++ mpol_shared_policy_lookup(&info->policy, idx));
++
+ /* Create a pseudo vma that just contains the policy */
+ pvma.vm_start = 0;
+ pvma.vm_pgoff = idx;
+ pvma.vm_ops = NULL;
+- pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, idx);
++ pvma.vm_policy = spol;
+ page = swapin_readahead(entry, gfp, &pvma, 0);
+- mpol_free(pvma.vm_policy);
+ return page;
+ }
+
+@@ -1184,27 +1127,21 @@ static struct page *shmem_alloc_page(gfp_t gfp,
+ struct shmem_inode_info *info, unsigned long idx)
+ {
+ struct vm_area_struct pvma;
+- struct page *page;
+
+ /* Create a pseudo vma that just contains the policy */
+ pvma.vm_start = 0;
+ pvma.vm_pgoff = idx;
+ pvma.vm_ops = NULL;
+ pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, idx);
+- page = alloc_page_vma(gfp, &pvma, 0);
+- mpol_free(pvma.vm_policy);
+- return page;
++
++ /*
++ * alloc_page_vma() will drop the shared policy reference
++ */
++ return alloc_page_vma(gfp, &pvma, 0);
+ }
+ #else /* !CONFIG_NUMA */
+ #ifdef CONFIG_TMPFS
+-static inline int shmem_parse_mpol(char *value, int *policy,
+- nodemask_t *policy_nodes)
+-{
+- return 1;
+-}
+-
+-static inline void shmem_show_mpol(struct seq_file *seq, int policy,
+- const nodemask_t policy_nodes)
++static inline void shmem_show_mpol(struct seq_file *seq, struct mempolicy *p)
+ {
+ }
+ #endif /* CONFIG_TMPFS */
+@@ -1222,6 +1159,13 @@ static inline struct page *shmem_alloc_page(gfp_t gfp,
+ }
+ #endif /* CONFIG_NUMA */
+
++#if !defined(CONFIG_NUMA) || !defined(CONFIG_TMPFS)
++static inline struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo)
++{
++ return NULL;
++}
++#endif
++
+ /*
+ * shmem_getpage - either get the page from swap or allocate a new one
+ *
+@@ -1576,8 +1520,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
+ case S_IFREG:
+ inode->i_op = &shmem_inode_operations;
+ inode->i_fop = &shmem_file_operations;
+- mpol_shared_policy_init(&info->policy, sbinfo->policy,
+- &sbinfo->policy_nodes);
++ mpol_shared_policy_init(&info->policy,
++ shmem_get_sbmpol(sbinfo));
+ break;
+ case S_IFDIR:
+ inc_nlink(inode);
+@@ -1591,8 +1535,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
+ * Must not load anything in the rbtree,
+ * mpol_free_shared_policy will not be called.
+ */
+- mpol_shared_policy_init(&info->policy, MPOL_DEFAULT,
+- NULL);
++ mpol_shared_policy_init(&info->policy, NULL);
+ break;
+ }
+ } else
+@@ -2207,8 +2150,7 @@ static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo,
+ if (*rest)
+ goto bad_val;
+ } else if (!strcmp(this_char,"mpol")) {
+- if (shmem_parse_mpol(value, &sbinfo->policy,
+- &sbinfo->policy_nodes))
++ if (mpol_parse_str(value, &sbinfo->mpol, 1))
+ goto bad_val;
+ } else {
+ printk(KERN_ERR "tmpfs: Bad mount option %s\n",
+@@ -2259,8 +2201,9 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
+ sbinfo->free_blocks = config.max_blocks - blocks;
+ sbinfo->max_inodes = config.max_inodes;
+ sbinfo->free_inodes = config.max_inodes - inodes;
+- sbinfo->policy = config.policy;
+- sbinfo->policy_nodes = config.policy_nodes;
++
++ mpol_put(sbinfo->mpol);
++ sbinfo->mpol = config.mpol; /* transfers initial ref */
+ out:
+ spin_unlock(&sbinfo->stat_lock);
+ return error;
+@@ -2281,7 +2224,7 @@ static int shmem_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ seq_printf(seq, ",uid=%u", sbinfo->uid);
+ if (sbinfo->gid != 0)
+ seq_printf(seq, ",gid=%u", sbinfo->gid);
+- shmem_show_mpol(seq, sbinfo->policy, sbinfo->policy_nodes);
++ shmem_show_mpol(seq, sbinfo->mpol);
+ return 0;
+ }
+ #endif /* CONFIG_TMPFS */
+@@ -2311,8 +2254,7 @@ static int shmem_fill_super(struct super_block *sb,
+ sbinfo->mode = S_IRWXUGO | S_ISVTX;
+ sbinfo->uid = current->fsuid;
+ sbinfo->gid = current->fsgid;
+- sbinfo->policy = MPOL_DEFAULT;
+- sbinfo->policy_nodes = node_states[N_HIGH_MEMORY];
++ sbinfo->mpol = NULL;
+ sb->s_fs_info = sbinfo;
+
+ #ifdef CONFIG_TMPFS
diff --git a/mm/slab.c b/mm/slab.c
-index 04b308c..03927cb 100644
+index 04b308c..06236e4 100644
--- a/mm/slab.c
+++ b/mm/slab.c
-@@ -1160,14 +1160,13 @@ static void __cpuinit cpuup_canceled(long cpu)
+@@ -110,6 +110,7 @@
+ #include <linux/fault-inject.h>
+ #include <linux/rtmutex.h>
+ #include <linux/reciprocal_div.h>
++#include <linux/debugobjects.h>
+
+ #include <asm/cacheflush.h>
+ #include <asm/tlbflush.h>
+@@ -139,10 +140,6 @@
+ #define BYTES_PER_WORD sizeof(void *)
+ #define REDZONE_ALIGN max(BYTES_PER_WORD, __alignof__(unsigned long long))
+
+-#ifndef cache_line_size
+-#define cache_line_size() L1_CACHE_BYTES
+-#endif
+-
+ #ifndef ARCH_KMALLOC_MINALIGN
+ /*
+ * Enforce a minimum alignment for the kmalloc caches.
+@@ -178,12 +175,14 @@
+ SLAB_CACHE_DMA | \
+ SLAB_STORE_USER | \
+ SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \
+- SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD)
++ SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \
++ SLAB_DEBUG_OBJECTS)
+ #else
+ # define CREATE_MASK (SLAB_HWCACHE_ALIGN | \
+ SLAB_CACHE_DMA | \
+ SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \
+- SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD)
++ SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \
++ SLAB_DEBUG_OBJECTS)
+ #endif
+
+ /*
+@@ -862,7 +861,7 @@ static void cache_estimate(unsigned long gfporder, size_t buffer_size,
+ *left_over = slab_size - nr_objs*buffer_size - mgmt_size;
+ }
+
+-#define slab_error(cachep, msg) __slab_error(__FUNCTION__, cachep, msg)
++#define slab_error(cachep, msg) __slab_error(__func__, cachep, msg)
+
+ static void __slab_error(const char *function, struct kmem_cache *cachep,
+ char *msg)
+@@ -1160,14 +1159,13 @@ static void __cpuinit cpuup_canceled(long cpu)
struct kmem_cache *cachep;
struct kmem_list3 *l3 = NULL;
int node = cpu_to_node(cpu);
@@ -840829,7 +1138128,7 @@
/* 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)
+@@ -1183,7 +1181,7 @@ static void __cpuinit cpuup_canceled(long cpu)
if (nc)
free_block(cachep, nc->entry, nc->avail, node);
@@ -840838,11 +1138137,191 @@
spin_unlock_irq(&l3->list_lock);
goto free_array_cache;
}
+@@ -2158,7 +2156,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
+ */
+ if (!name || in_interrupt() || (size < BYTES_PER_WORD) ||
+ size > KMALLOC_MAX_SIZE) {
+- printk(KERN_ERR "%s: Early error in slab %s\n", __FUNCTION__,
++ printk(KERN_ERR "%s: Early error in slab %s\n", __func__,
+ name);
+ BUG();
+ }
+@@ -3243,15 +3241,16 @@ static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
+ {
+ struct zonelist *zonelist;
+ gfp_t local_flags;
+- struct zone **z;
++ struct zoneref *z;
++ struct zone *zone;
++ enum zone_type high_zoneidx = gfp_zone(flags);
+ void *obj = NULL;
+ int nid;
+
+ if (flags & __GFP_THISNODE)
+ return NULL;
+
+- zonelist = &NODE_DATA(slab_node(current->mempolicy))
+- ->node_zonelists[gfp_zone(flags)];
++ zonelist = node_zonelist(slab_node(current->mempolicy), flags);
+ local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK);
+
+ retry:
+@@ -3259,10 +3258,10 @@ retry:
+ * Look through allowed nodes for objects available
+ * from existing per node queues.
+ */
+- for (z = zonelist->zones; *z && !obj; z++) {
+- nid = zone_to_nid(*z);
++ for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) {
++ nid = zone_to_nid(zone);
+
+- if (cpuset_zone_allowed_hardwall(*z, flags) &&
++ if (cpuset_zone_allowed_hardwall(zone, flags) &&
+ cache->nodelists[nid] &&
+ cache->nodelists[nid]->free_objects)
+ obj = ____cache_alloc_node(cache,
+@@ -3764,6 +3763,8 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp)
+
+ local_irq_save(flags);
+ debug_check_no_locks_freed(objp, obj_size(cachep));
++ if (!(cachep->flags & SLAB_DEBUG_OBJECTS))
++ debug_check_no_obj_freed(objp, obj_size(cachep));
+ __cache_free(cachep, objp);
+ local_irq_restore(flags);
+ }
+@@ -3789,6 +3790,7 @@ void kfree(const void *objp)
+ kfree_debugcheck(objp);
+ c = virt_to_cache(objp);
+ debug_check_no_locks_freed(objp, obj_size(c));
++ debug_check_no_obj_freed(objp, obj_size(c));
+ __cache_free(c, (void *)objp);
+ local_irq_restore(flags);
+ }
+diff --git a/mm/slob.c b/mm/slob.c
+index e2c3c0e..6038cba 100644
+--- a/mm/slob.c
++++ b/mm/slob.c
+@@ -533,7 +533,8 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
+ {
+ struct kmem_cache *c;
+
+- c = slob_alloc(sizeof(struct kmem_cache), flags, 0, -1);
++ c = slob_alloc(sizeof(struct kmem_cache),
++ flags, ARCH_KMALLOC_MINALIGN, -1);
+
+ if (c) {
+ c->name = name;
diff --git a/mm/slub.c b/mm/slub.c
-index acc975f..39592b5 100644
+index acc975f..70db289 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)
+@@ -19,6 +19,7 @@
+ #include <linux/cpuset.h>
+ #include <linux/mempolicy.h>
+ #include <linux/ctype.h>
++#include <linux/debugobjects.h>
+ #include <linux/kallsyms.h>
+ #include <linux/memory.h>
+
+@@ -149,25 +150,6 @@ static inline void ClearSlabDebug(struct page *page)
+ /* Enable to test recovery from slab corruption on boot */
+ #undef SLUB_RESILIENCY_TEST
+
+-#if PAGE_SHIFT <= 12
+-
+-/*
+- * Small page size. Make sure that we do not fragment memory
+- */
+-#define DEFAULT_MAX_ORDER 1
+-#define DEFAULT_MIN_OBJECTS 4
+-
+-#else
+-
+-/*
+- * Large page machines are customarily able to handle larger
+- * page orders.
+- */
+-#define DEFAULT_MAX_ORDER 2
+-#define DEFAULT_MIN_OBJECTS 8
+-
+-#endif
+-
+ /*
+ * Mininum number of partial slabs. These will be left on the partial
+ * lists even if they are empty. kmem_cache_shrink may reclaim them.
+@@ -204,13 +186,6 @@ static inline void ClearSlabDebug(struct page *page)
+ /* Internal SLUB flags */
+ #define __OBJECT_POISON 0x80000000 /* Poison object */
+ #define __SYSFS_ADD_DEFERRED 0x40000000 /* Not yet visible via sysfs */
+-#define __KMALLOC_CACHE 0x20000000 /* objects freed using kfree */
+-#define __PAGE_ALLOC_FALLBACK 0x10000000 /* Allow fallback to page alloc */
+-
+-/* Not all arches define cache_line_size */
+-#ifndef cache_line_size
+-#define cache_line_size() L1_CACHE_BYTES
+-#endif
+
+ static int kmem_size = sizeof(struct kmem_cache);
+
+@@ -301,7 +276,7 @@ static inline int check_valid_pointer(struct kmem_cache *s,
+ return 1;
+
+ base = page_address(page);
+- if (object < base || object >= base + s->objects * s->size ||
++ if (object < base || object >= base + page->objects * s->size ||
+ (object - base) % s->size) {
+ return 0;
+ }
+@@ -327,8 +302,8 @@ static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)
+ }
+
+ /* Loop over all objects in a slab */
+-#define for_each_object(__p, __s, __addr) \
+- for (__p = (__addr); __p < (__addr) + (__s)->objects * (__s)->size;\
++#define for_each_object(__p, __s, __addr, __objects) \
++ for (__p = (__addr); __p < (__addr) + (__objects) * (__s)->size;\
+ __p += (__s)->size)
+
+ /* Scan freelist */
+@@ -341,6 +316,26 @@ static inline int slab_index(void *p, struct kmem_cache *s, void *addr)
+ return (p - addr) / s->size;
+ }
+
++static inline struct kmem_cache_order_objects oo_make(int order,
++ unsigned long size)
++{
++ struct kmem_cache_order_objects x = {
++ (order << 16) + (PAGE_SIZE << order) / size
++ };
++
++ return x;
++}
++
++static inline int oo_order(struct kmem_cache_order_objects x)
++{
++ return x.x >> 16;
++}
++
++static inline int oo_objects(struct kmem_cache_order_objects x)
++{
++ return x.x & ((1 << 16) - 1);
++}
++
+ #ifdef CONFIG_SLUB_DEBUG
+ /*
+ * Debug settings:
+@@ -451,8 +446,8 @@ static void print_tracking(struct kmem_cache *s, void *object)
+
+ static void print_page_info(struct page *page)
+ {
+- printk(KERN_ERR "INFO: Slab 0x%p used=%u fp=0x%p flags=0x%04lx\n",
+- page, page->inuse, page->freelist, page->flags);
++ printk(KERN_ERR "INFO: Slab 0x%p objects=%u used=%u fp=0x%p flags=0x%04lx\n",
++ page, page->objects, page->inuse, page->freelist, page->flags);
+
+ }
+
+@@ -521,7 +516,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)
{
@@ -840851,7 +1138330,7 @@
print_trailer(s, page, object);
}
-@@ -533,7 +533,7 @@ static void slab_err(struct kmem_cache *s, struct page *page, char *fmt, ...)
+@@ -533,7 +528,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);
@@ -840860,7 +1138339,112 @@
print_page_info(page);
dump_stack();
}
-@@ -837,6 +837,35 @@ static void remove_full(struct kmem_cache *s, struct page *page)
+@@ -652,6 +647,7 @@ static int check_pad_bytes(struct kmem_cache *s, struct page *page, u8 *p)
+ p + off, POISON_INUSE, s->size - off);
+ }
+
++/* Check the pad bytes at the end of a slab page */
+ static int slab_pad_check(struct kmem_cache *s, struct page *page)
+ {
+ u8 *start;
+@@ -664,20 +660,20 @@ static int slab_pad_check(struct kmem_cache *s, struct page *page)
+ return 1;
+
+ start = page_address(page);
+- end = start + (PAGE_SIZE << s->order);
+- length = s->objects * s->size;
+- remainder = end - (start + length);
++ length = (PAGE_SIZE << compound_order(page));
++ end = start + length;
++ remainder = length % s->size;
+ if (!remainder)
+ return 1;
+
+- fault = check_bytes(start + length, POISON_INUSE, remainder);
++ fault = check_bytes(end - remainder, POISON_INUSE, remainder);
+ if (!fault)
+ return 1;
+ while (end > fault && end[-1] == POISON_INUSE)
+ end--;
+
+ slab_err(s, page, "Padding overwritten. 0x%p-0x%p", fault, end - 1);
+- print_section("Padding", start, length);
++ print_section("Padding", end - remainder, remainder);
+
+ restore_bytes(s, "slab padding", POISON_INUSE, start, end);
+ return 0;
+@@ -739,15 +735,24 @@ static int check_object(struct kmem_cache *s, struct page *page,
+
+ static int check_slab(struct kmem_cache *s, struct page *page)
+ {
++ int maxobj;
++
+ VM_BUG_ON(!irqs_disabled());
+
+ if (!PageSlab(page)) {
+ slab_err(s, page, "Not a valid slab page");
+ return 0;
+ }
+- if (page->inuse > s->objects) {
++
++ maxobj = (PAGE_SIZE << compound_order(page)) / s->size;
++ if (page->objects > maxobj) {
++ slab_err(s, page, "objects %u > max %u",
++ s->name, page->objects, maxobj);
++ return 0;
++ }
++ if (page->inuse > page->objects) {
+ slab_err(s, page, "inuse %u > max %u",
+- s->name, page->inuse, s->objects);
++ s->name, page->inuse, page->objects);
+ return 0;
+ }
+ /* Slab_pad_check fixes things up after itself */
+@@ -764,8 +769,9 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search)
+ int nr = 0;
+ void *fp = page->freelist;
+ void *object = NULL;
++ unsigned long max_objects;
+
+- while (fp && nr <= s->objects) {
++ while (fp && nr <= page->objects) {
+ if (fp == search)
+ return 1;
+ if (!check_valid_pointer(s, page, fp)) {
+@@ -777,7 +783,7 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search)
+ } else {
+ slab_err(s, page, "Freepointer corrupt");
+ page->freelist = NULL;
+- page->inuse = s->objects;
++ page->inuse = page->objects;
+ slab_fix(s, "Freelist cleared");
+ return 0;
+ }
+@@ -788,10 +794,20 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search)
+ nr++;
+ }
+
+- if (page->inuse != s->objects - nr) {
++ max_objects = (PAGE_SIZE << compound_order(page)) / s->size;
++ if (max_objects > 65535)
++ max_objects = 65535;
++
++ if (page->objects != max_objects) {
++ slab_err(s, page, "Wrong number of objects. Found %d but "
++ "should be %d", page->objects, max_objects);
++ page->objects = max_objects;
++ slab_fix(s, "Number of objects adjusted.");
++ }
++ if (page->inuse != page->objects - nr) {
+ slab_err(s, page, "Wrong object count. Counter is %d but "
+- "counted were %d", page->inuse, s->objects - nr);
+- page->inuse = s->objects - nr;
++ "counted were %d", page->inuse, page->objects - nr);
++ page->inuse = page->objects - nr;
+ slab_fix(s, "Object count adjusted.");
+ }
+ return search == NULL;
+@@ -837,6 +853,38 @@ static void remove_full(struct kmem_cache *s, struct page *page)
spin_unlock(&n->list_lock);
}
@@ -840872,7 +1138456,7 @@
+ return atomic_long_read(&n->nr_slabs);
+}
+
-+static inline void inc_slabs_node(struct kmem_cache *s, int node)
++static inline void inc_slabs_node(struct kmem_cache *s, int node, int objects)
+{
+ struct kmem_cache_node *n = get_node(s, node);
+
@@ -840882,33 +1138466,98 @@
+ * dilemma by deferring the increment of the count during
+ * bootstrap (see early_kmem_cache_node_alloc).
+ */
-+ if (!NUMA_BUILD || n)
++ if (!NUMA_BUILD || n) {
+ atomic_long_inc(&n->nr_slabs);
++ atomic_long_add(objects, &n->total_objects);
++ }
+}
-+static inline void dec_slabs_node(struct kmem_cache *s, int node)
++static inline void dec_slabs_node(struct kmem_cache *s, int node, int objects)
+{
+ struct kmem_cache_node *n = get_node(s, node);
+
+ atomic_long_dec(&n->nr_slabs);
++ atomic_long_sub(objects, &n->total_objects);
+}
+
+/* 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,
+@@ -881,7 +929,7 @@ bad:
+ * as used avoids touching the remaining objects.
+ */
+ slab_fix(s, "Marking all objects used");
+- page->inuse = s->objects;
++ page->inuse = page->objects;
+ page->freelist = NULL;
+ }
+ return 0;
+@@ -1028,29 +1076,55 @@ 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) {}
++static inline void inc_slabs_node(struct kmem_cache *s, int node,
++ int objects) {}
++static inline void dec_slabs_node(struct kmem_cache *s, int node,
++ int objects) {}
#endif
++
/*
* Slab allocation and freeing
-@@ -1066,7 +1100,6 @@ static void setup_object(struct kmem_cache *s, struct page *page,
+ */
++static inline struct page *alloc_slab_page(gfp_t flags, int node,
++ struct kmem_cache_order_objects oo)
++{
++ int order = oo_order(oo);
++
++ if (node == -1)
++ return alloc_pages(flags, order);
++ else
++ return alloc_pages_node(node, flags, order);
++}
++
+ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
+ {
+ struct page *page;
+- int pages = 1 << s->order;
++ struct kmem_cache_order_objects oo = s->oo;
+
+ flags |= s->allocflags;
+
+- if (node == -1)
+- page = alloc_pages(flags, s->order);
+- else
+- page = alloc_pages_node(node, flags, s->order);
+-
+- if (!page)
+- return NULL;
++ page = alloc_slab_page(flags | __GFP_NOWARN | __GFP_NORETRY, node,
++ oo);
++ if (unlikely(!page)) {
++ oo = s->min;
++ /*
++ * Allocation may have failed due to fragmentation.
++ * Try a lower order alloc if possible
++ */
++ page = alloc_slab_page(flags, node, oo);
++ if (!page)
++ return NULL;
+
++ stat(get_cpu_slab(s, raw_smp_processor_id()), ORDER_FALLBACK);
++ }
++ page->objects = oo_objects(oo);
+ mod_zone_page_state(page_zone(page),
+ (s->flags & SLAB_RECLAIM_ACCOUNT) ?
+ NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,
+- pages);
++ 1 << oo_order(oo));
+
+ return page;
+ }
+@@ -1066,7 +1140,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;
@@ -840916,27 +1138565,60 @@
void *start;
void *last;
void *p;
-@@ -1078,9 +1111,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
+@@ -1078,9 +1151,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));
++ inc_slabs_node(s, page_to_nid(page), page->objects);
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)
+@@ -1090,10 +1161,10 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
+ start = page_address(page);
+
+ if (unlikely(s->flags & SLAB_POISON))
+- memset(start, POISON_INUSE, PAGE_SIZE << s->order);
++ memset(start, POISON_INUSE, PAGE_SIZE << compound_order(page));
+
+ last = start;
+- for_each_object(p, s, start) {
++ for_each_object(p, s, start, page->objects) {
+ setup_object(s, page, last);
+ set_freepointer(s, last, p);
+ last = p;
+@@ -1109,13 +1180,15 @@ out:
+
+ static void __free_slab(struct kmem_cache *s, struct page *page)
+ {
+- int pages = 1 << s->order;
++ int order = compound_order(page);
++ int pages = 1 << order;
+
+ if (unlikely(SlabDebug(page))) {
+ void *p;
+
+ slab_pad_check(s, page);
+- for_each_object(p, s, page_address(page))
++ for_each_object(p, s, page_address(page),
++ page->objects)
+ check_object(s, page, p, 0);
+ ClearSlabDebug(page);
+ }
+@@ -1125,7 +1198,9 @@ static void __free_slab(struct kmem_cache *s, struct page *page)
NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,
-pages);
+- __free_pages(page, s->order);
+ __ClearPageSlab(page);
+ reset_page_mapcount(page);
- __free_pages(page, s->order);
++ __free_pages(page, order);
}
-@@ -1151,11 +1184,7 @@ static void free_slab(struct kmem_cache *s, struct page *page)
+ static void rcu_free_slab(struct rcu_head *h)
+@@ -1151,11 +1226,7 @@ static void free_slab(struct kmem_cache *s, struct page *page)
static void discard_slab(struct kmem_cache *s, struct page *page)
{
@@ -840945,11 +1138627,129 @@
- atomic_long_dec(&n->nr_slabs);
- reset_page_mapcount(page);
- __ClearPageSlab(page);
-+ dec_slabs_node(s, page_to_nid(page));
++ dec_slabs_node(s, page_to_nid(page), page->objects);
free_slab(s, page);
}
-@@ -1886,15 +1915,18 @@ static void init_kmem_cache_cpu(struct kmem_cache *s,
+@@ -1255,7 +1326,9 @@ static struct page *get_any_partial(struct kmem_cache *s, gfp_t flags)
+ {
+ #ifdef CONFIG_NUMA
+ struct zonelist *zonelist;
+- struct zone **z;
++ struct zoneref *z;
++ struct zone *zone;
++ enum zone_type high_zoneidx = gfp_zone(flags);
+ struct page *page;
+
+ /*
+@@ -1280,14 +1353,13 @@ static struct page *get_any_partial(struct kmem_cache *s, gfp_t flags)
+ get_cycles() % 1024 > s->remote_node_defrag_ratio)
+ return NULL;
+
+- zonelist = &NODE_DATA(
+- slab_node(current->mempolicy))->node_zonelists[gfp_zone(flags)];
+- for (z = zonelist->zones; *z; z++) {
++ zonelist = node_zonelist(slab_node(current->mempolicy), flags);
++ for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) {
+ struct kmem_cache_node *n;
+
+- n = get_node(s, zone_to_nid(*z));
++ n = get_node(s, zone_to_nid(zone));
+
+- if (n && cpuset_zone_allowed_hardwall(*z, flags) &&
++ if (n && cpuset_zone_allowed_hardwall(zone, flags) &&
+ n->nr_partial > MIN_PARTIAL) {
+ page = get_partial_node(n);
+ if (page)
+@@ -1490,7 +1562,7 @@ load_freelist:
+ goto debug;
+
+ c->freelist = object[c->offset];
+- c->page->inuse = s->objects;
++ c->page->inuse = c->page->objects;
+ c->page->freelist = NULL;
+ c->node = page_to_nid(c->page);
+ unlock_out:
+@@ -1527,27 +1599,6 @@ new_slab:
+ c->page = new;
+ goto load_freelist;
+ }
+-
+- /*
+- * No memory available.
+- *
+- * If the slab uses higher order allocs but the object is
+- * smaller than a page size then we can fallback in emergencies
+- * to the page allocator via kmalloc_large. The page allocator may
+- * have failed to obtain a higher order page and we can try to
+- * allocate a single page if the object fits into a single page.
+- * That is only possible if certain conditions are met that are being
+- * checked when a slab is created.
+- */
+- if (!(gfpflags & __GFP_NORETRY) &&
+- (s->flags & __PAGE_ALLOC_FALLBACK)) {
+- if (gfpflags & __GFP_WAIT)
+- local_irq_enable();
+- object = kmalloc_large(s->objsize, gfpflags);
+- if (gfpflags & __GFP_WAIT)
+- local_irq_disable();
+- return object;
+- }
+ return NULL;
+ debug:
+ if (!alloc_debug_processing(s, c->page, object, addr))
+@@ -1697,6 +1748,8 @@ static __always_inline void slab_free(struct kmem_cache *s,
+ local_irq_save(flags);
+ c = get_cpu_slab(s, smp_processor_id());
+ debug_check_no_locks_freed(object, c->objsize);
++ if (!(s->flags & SLAB_DEBUG_OBJECTS))
++ debug_check_no_obj_freed(object, s->objsize);
+ if (likely(page == c->page && c->node >= 0)) {
+ object[c->offset] = c->freelist;
+ c->freelist = object;
+@@ -1748,8 +1801,8 @@ static struct page *get_object_page(const void *x)
+ * take the list_lock.
+ */
+ static int slub_min_order;
+-static int slub_max_order = DEFAULT_MAX_ORDER;
+-static int slub_min_objects = DEFAULT_MIN_OBJECTS;
++static int slub_max_order = PAGE_ALLOC_COSTLY_ORDER;
++static int slub_min_objects;
+
+ /*
+ * Merge control. If this is set then no merging of slab caches will occur.
+@@ -1764,7 +1817,7 @@ static int slub_nomerge;
+ * system components. Generally order 0 allocations should be preferred since
+ * order 0 does not cause fragmentation in the page allocator. Larger objects
+ * be problematic to put into order 0 slabs because there may be too much
+- * unused space left. We go to a higher order if more than 1/8th of the slab
++ * unused space left. We go to a higher order if more than 1/16th of the slab
+ * would be wasted.
+ *
+ * In order to reach satisfactory performance we must ensure that a minimum
+@@ -1789,6 +1842,9 @@ static inline int slab_order(int size, int min_objects,
+ int rem;
+ int min_order = slub_min_order;
+
++ if ((PAGE_SIZE << min_order) / size > 65535)
++ return get_order(size * 65535) - 1;
++
+ for (order = max(min_order,
+ fls(min_objects * size - 1) - PAGE_SHIFT);
+ order <= max_order; order++) {
+@@ -1823,8 +1879,10 @@ static inline int calculate_order(int size)
+ * we reduce the minimum objects required in a slab.
+ */
+ min_objects = slub_min_objects;
++ if (!min_objects)
++ min_objects = 4 * (fls(nr_cpu_ids) + 1);
+ while (min_objects > 1) {
+- fraction = 8;
++ fraction = 16;
+ while (fraction >= 4) {
+ order = slab_order(size, min_objects,
+ slub_max_order, fraction);
+@@ -1886,15 +1944,18 @@ static void init_kmem_cache_cpu(struct kmem_cache *s,
c->node = 0;
c->offset = s->offset / sizeof(void *);
c->objsize = s->objsize;
@@ -840969,25 +1138769,183 @@
INIT_LIST_HEAD(&n->full);
#endif
}
-@@ -2063,7 +2095,7 @@ static struct kmem_cache_node *early_kmem_cache_node_alloc(gfp_t gfpflags,
+@@ -2063,7 +2124,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);
++ inc_slabs_node(kmalloc_caches, node, page->objects);
/*
* lockdep requires consistent irq usage for each lock
-@@ -2376,7 +2408,7 @@ static inline int kmem_cache_close(struct kmem_cache *s)
+@@ -2139,11 +2200,12 @@ static int init_kmem_cache_nodes(struct kmem_cache *s, gfp_t gfpflags)
+ * calculate_sizes() determines the order and the distribution of data within
+ * a slab object.
+ */
+-static int calculate_sizes(struct kmem_cache *s)
++static int calculate_sizes(struct kmem_cache *s, int forced_order)
+ {
+ unsigned long flags = s->flags;
+ unsigned long size = s->objsize;
+ unsigned long align = s->align;
++ int order;
+
+ /*
+ * Round up object size to the next word boundary. We can only
+@@ -2227,26 +2289,16 @@ static int calculate_sizes(struct kmem_cache *s)
+ */
+ size = ALIGN(size, align);
+ s->size = size;
++ if (forced_order >= 0)
++ order = forced_order;
++ else
++ order = calculate_order(size);
+
+- if ((flags & __KMALLOC_CACHE) &&
+- PAGE_SIZE / size < slub_min_objects) {
+- /*
+- * Kmalloc cache that would not have enough objects in
+- * an order 0 page. Kmalloc slabs can fallback to
+- * page allocator order 0 allocs so take a reasonably large
+- * order that will allows us a good number of objects.
+- */
+- s->order = max(slub_max_order, PAGE_ALLOC_COSTLY_ORDER);
+- s->flags |= __PAGE_ALLOC_FALLBACK;
+- s->allocflags |= __GFP_NOWARN;
+- } else
+- s->order = calculate_order(size);
+-
+- if (s->order < 0)
++ if (order < 0)
+ return 0;
+
+ s->allocflags = 0;
+- if (s->order)
++ if (order)
+ s->allocflags |= __GFP_COMP;
+
+ if (s->flags & SLAB_CACHE_DMA)
+@@ -2258,9 +2310,12 @@ static int calculate_sizes(struct kmem_cache *s)
+ /*
+ * Determine the number of objects per slab
+ */
+- s->objects = (PAGE_SIZE << s->order) / size;
++ s->oo = oo_make(order, size);
++ s->min = oo_make(get_order(size), size);
++ if (oo_objects(s->oo) > oo_objects(s->max))
++ s->max = s->oo;
+
+- return !!s->objects;
++ return !!oo_objects(s->oo);
+
+ }
+
+@@ -2276,7 +2331,7 @@ static int kmem_cache_open(struct kmem_cache *s, gfp_t gfpflags,
+ s->align = align;
+ s->flags = kmem_cache_flags(size, flags, name, ctor);
+
+- if (!calculate_sizes(s))
++ if (!calculate_sizes(s, -1))
+ goto error;
+
+ s->refcount = 1;
+@@ -2293,7 +2348,7 @@ error:
+ if (flags & SLAB_PANIC)
+ panic("Cannot create slab %s size=%lu realsize=%u "
+ "order=%u offset=%u flags=%lx\n",
+- s->name, (unsigned long)size, s->size, s->order,
++ s->name, (unsigned long)size, s->size, oo_order(s->oo),
+ s->offset, flags);
+ return 0;
+ }
+@@ -2339,26 +2394,52 @@ const char *kmem_cache_name(struct kmem_cache *s)
+ }
+ EXPORT_SYMBOL(kmem_cache_name);
+
++static void list_slab_objects(struct kmem_cache *s, struct page *page,
++ const char *text)
++{
++#ifdef CONFIG_SLUB_DEBUG
++ void *addr = page_address(page);
++ void *p;
++ DECLARE_BITMAP(map, page->objects);
++
++ bitmap_zero(map, page->objects);
++ slab_err(s, page, "%s", text);
++ slab_lock(page);
++ for_each_free_object(p, s, page->freelist)
++ set_bit(slab_index(p, s, addr), map);
++
++ for_each_object(p, s, addr, page->objects) {
++
++ if (!test_bit(slab_index(p, s, addr), map)) {
++ printk(KERN_ERR "INFO: Object 0x%p @offset=%tu\n",
++ p, p - addr);
++ print_tracking(s, p);
++ }
++ }
++ slab_unlock(page);
++#endif
++}
++
+ /*
+- * Attempt to free all slabs on a node. Return the number of slabs we
+- * were unable to free.
++ * Attempt to free all partial slabs on a node.
+ */
+-static int free_list(struct kmem_cache *s, struct kmem_cache_node *n,
+- struct list_head *list)
++static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
+ {
+- int slabs_inuse = 0;
+ unsigned long flags;
+ struct page *page, *h;
+
+ spin_lock_irqsave(&n->list_lock, flags);
+- list_for_each_entry_safe(page, h, list, lru)
++ list_for_each_entry_safe(page, h, &n->partial, lru) {
+ if (!page->inuse) {
+ list_del(&page->lru);
+ discard_slab(s, page);
+- } else
+- slabs_inuse++;
++ n->nr_partial--;
++ } else {
++ list_slab_objects(s, page,
++ "Objects remaining on kmem_cache_close()");
++ }
++ }
+ spin_unlock_irqrestore(&n->list_lock, flags);
+- return slabs_inuse;
+ }
+
+ /*
+@@ -2375,8 +2456,8 @@ static inline int kmem_cache_close(struct kmem_cache *s)
+ for_each_node_state(node, N_NORMAL_MEMORY) {
struct kmem_cache_node *n = get_node(s, node);
- n->nr_partial -= free_list(s, n, &n->partial);
+- n->nr_partial -= free_list(s, n, &n->partial);
- if (atomic_long_read(&n->nr_slabs))
-+ if (slabs_node(s, node))
++ free_partial(s, n);
++ if (n->nr_partial || slabs_node(s, node))
return 1;
}
free_kmem_cache_nodes(s);
-@@ -2409,10 +2441,6 @@ EXPORT_SYMBOL(kmem_cache_destroy);
+@@ -2394,8 +2475,11 @@ void kmem_cache_destroy(struct kmem_cache *s)
+ if (!s->refcount) {
+ list_del(&s->list);
+ up_write(&slub_lock);
+- if (kmem_cache_close(s))
+- WARN_ON(1);
++ if (kmem_cache_close(s)) {
++ printk(KERN_ERR "SLUB %s: %s called for cache that "
++ "still has objects.\n", s->name, __func__);
++ dump_stack();
++ }
+ sysfs_slab_remove(s);
+ } else
+ up_write(&slub_lock);
+@@ -2409,10 +2493,6 @@ EXPORT_SYMBOL(kmem_cache_destroy);
struct kmem_cache kmalloc_caches[PAGE_SHIFT + 1] __cacheline_aligned;
EXPORT_SYMBOL(kmalloc_caches);
@@ -840998,7 +1138956,16 @@
static int __init setup_slub_min_order(char *str)
{
get_option(&str, &slub_min_order);
-@@ -2472,6 +2500,7 @@ panic:
+@@ -2458,7 +2538,7 @@ static struct kmem_cache *create_kmalloc_cache(struct kmem_cache *s,
+
+ down_write(&slub_lock);
+ if (!kmem_cache_open(s, gfp_flags, name, size, ARCH_KMALLOC_MINALIGN,
+- flags | __KMALLOC_CACHE, NULL))
++ flags, NULL))
+ goto panic;
+
+ list_add(&s->list, &slab_caches);
+@@ -2472,6 +2552,7 @@ panic:
}
#ifdef CONFIG_ZONE_DMA
@@ -841006,7 +1138973,7 @@
static void sysfs_add_func(struct work_struct *w)
{
-@@ -2688,21 +2717,6 @@ void kfree(const void *x)
+@@ -2688,21 +2769,6 @@ void kfree(const void *x)
}
EXPORT_SYMBOL(kfree);
@@ -841028,7 +1138995,36 @@
/*
* 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)
+@@ -2720,8 +2786,9 @@ int kmem_cache_shrink(struct kmem_cache *s)
+ struct kmem_cache_node *n;
+ struct page *page;
+ struct page *t;
++ int objects = oo_objects(s->max);
+ struct list_head *slabs_by_inuse =
+- kmalloc(sizeof(struct list_head) * s->objects, GFP_KERNEL);
++ kmalloc(sizeof(struct list_head) * objects, GFP_KERNEL);
+ unsigned long flags;
+
+ if (!slabs_by_inuse)
+@@ -2734,7 +2801,7 @@ int kmem_cache_shrink(struct kmem_cache *s)
+ if (!n->nr_partial)
+ continue;
+
+- for (i = 0; i < s->objects; i++)
++ for (i = 0; i < objects; i++)
+ INIT_LIST_HEAD(slabs_by_inuse + i);
+
+ spin_lock_irqsave(&n->list_lock, flags);
+@@ -2766,7 +2833,7 @@ int kmem_cache_shrink(struct kmem_cache *s)
+ * Rebuild the partial list with the slabs filled up most
+ * first and the least used slabs at the end.
+ */
+- for (i = s->objects - 1; i >= 0; i--)
++ for (i = objects - 1; i >= 0; i--)
+ list_splice(slabs_by_inuse + i, n->partial.prev);
+
+ spin_unlock_irqrestore(&n->list_lock, flags);
+@@ -2816,7 +2883,7 @@ static void slab_mem_offline_callback(void *arg)
* and offline_pages() function shoudn't call this
* callback. So, we must fail.
*/
@@ -841037,12 +1139033,32 @@
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,
+@@ -2914,7 +2981,7 @@ void __init kmem_cache_init(void)
+ kmalloc_caches[0].refcount = -1;
+ caches++;
+
+- hotplug_memory_notifier(slab_memory_callback, 1);
++ hotplug_memory_notifier(slab_memory_callback, SLAB_CALLBACK_PRI);
+ #endif
+
+ /* Able to allocate the per node structures */
+@@ -2987,9 +3054,6 @@ static int slab_unmergeable(struct kmem_cache *s)
+ if (slub_nomerge || (s->flags & SLUB_NEVER_MERGE))
+ return 1;
+
+- if ((s->flags & __PAGE_ALLOC_FALLBACK))
+- return 1;
+-
+ if (s->ctor)
+ return 1;
+
+@@ -3181,6 +3245,37 @@ 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)
++static unsigned long count_partial(struct kmem_cache_node *n,
++ int (*get_count)(struct page *))
+{
+ unsigned long flags;
+ unsigned long x = 0;
@@ -841050,16 +1139066,311 @@
+
+ spin_lock_irqsave(&n->list_lock, flags);
+ list_for_each_entry(page, &n->partial, lru)
-+ x += page->inuse;
++ x += get_count(page);
+ spin_unlock_irqrestore(&n->list_lock, flags);
+ return x;
+}
++
++static int count_inuse(struct page *page)
++{
++ return page->inuse;
++}
++
++static int count_total(struct page *page)
++{
++ return page->objects;
++}
++
++static int count_free(struct page *page)
++{
++ return page->objects - page->inuse;
++}
+#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)
+@@ -3193,7 +3288,7 @@ static int validate_slab(struct kmem_cache *s, struct page *page,
+ return 0;
+
+ /* Now we know that a valid freelist exists */
+- bitmap_zero(map, s->objects);
++ bitmap_zero(map, page->objects);
+
+ for_each_free_object(p, s, page->freelist) {
+ set_bit(slab_index(p, s, addr), map);
+@@ -3201,7 +3296,7 @@ static int validate_slab(struct kmem_cache *s, struct page *page,
+ return 0;
+ }
+
+- for_each_object(p, s, addr)
++ for_each_object(p, s, addr, page->objects)
+ if (!test_bit(slab_index(p, s, addr), map))
+ if (!check_object(s, page, p, 1))
+ return 0;
+@@ -3267,7 +3362,7 @@ static long validate_slab_cache(struct kmem_cache *s)
+ {
+ int node;
+ unsigned long count = 0;
+- unsigned long *map = kmalloc(BITS_TO_LONGS(s->objects) *
++ unsigned long *map = kmalloc(BITS_TO_LONGS(oo_objects(s->max)) *
+ sizeof(unsigned long), GFP_KERNEL);
+
+ if (!map)
+@@ -3470,14 +3565,14 @@ static void process_slab(struct loc_track *t, struct kmem_cache *s,
+ struct page *page, enum track_item alloc)
+ {
+ void *addr = page_address(page);
+- DECLARE_BITMAP(map, s->objects);
++ DECLARE_BITMAP(map, page->objects);
+ void *p;
+
+- bitmap_zero(map, s->objects);
++ bitmap_zero(map, page->objects);
+ for_each_free_object(p, s, page->freelist)
+ set_bit(slab_index(p, s, addr), map);
+
+- for_each_object(p, s, addr)
++ for_each_object(p, s, addr, page->objects)
+ if (!test_bit(slab_index(p, s, addr), map))
+ add_location(t, s, get_track(s, p, alloc));
+ }
+@@ -3567,22 +3662,23 @@ static int list_locations(struct kmem_cache *s, char *buf,
+ }
+
+ enum slab_stat_type {
+- SL_FULL,
+- SL_PARTIAL,
+- SL_CPU,
+- SL_OBJECTS
++ SL_ALL, /* All slabs */
++ SL_PARTIAL, /* Only partially allocated slabs */
++ SL_CPU, /* Only slabs used for cpu caches */
++ SL_OBJECTS, /* Determine allocated objects not slabs */
++ SL_TOTAL /* Determine object capacity not slabs */
+ };
+
+-#define SO_FULL (1 << SL_FULL)
++#define SO_ALL (1 << SL_ALL)
+ #define SO_PARTIAL (1 << SL_PARTIAL)
+ #define SO_CPU (1 << SL_CPU)
+ #define SO_OBJECTS (1 << SL_OBJECTS)
++#define SO_TOTAL (1 << SL_TOTAL)
+
+ static ssize_t show_slab_objects(struct kmem_cache *s,
+ char *buf, unsigned long flags)
+ {
+ unsigned long total = 0;
+- int cpu;
+ int node;
+ int x;
+ unsigned long *nodes;
+@@ -3593,56 +3689,60 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
+ return -ENOMEM;
+ per_cpu = nodes + nr_node_ids;
+
+- for_each_possible_cpu(cpu) {
+- struct page *page;
+- struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
++ if (flags & SO_CPU) {
++ int cpu;
+
+- if (!c)
+- continue;
++ for_each_possible_cpu(cpu) {
++ struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
+
+- page = c->page;
+- node = c->node;
+- if (node < 0)
+- continue;
+- if (page) {
+- if (flags & SO_CPU) {
+- if (flags & SO_OBJECTS)
+- x = page->inuse;
++ if (!c || c->node < 0)
++ continue;
++
++ if (c->page) {
++ if (flags & SO_TOTAL)
++ x = c->page->objects;
++ else if (flags & SO_OBJECTS)
++ x = c->page->inuse;
+ else
+ x = 1;
++
+ total += x;
+- nodes[node] += x;
++ nodes[c->node] += x;
+ }
+- per_cpu[node]++;
++ per_cpu[c->node]++;
+ }
+ }
+
+- for_each_node_state(node, N_NORMAL_MEMORY) {
+- struct kmem_cache_node *n = get_node(s, node);
++ if (flags & SO_ALL) {
++ for_each_node_state(node, N_NORMAL_MEMORY) {
++ struct kmem_cache_node *n = get_node(s, node);
++
++ if (flags & SO_TOTAL)
++ x = atomic_long_read(&n->total_objects);
++ else if (flags & SO_OBJECTS)
++ x = atomic_long_read(&n->total_objects) -
++ count_partial(n, count_free);
+
+- if (flags & SO_PARTIAL) {
+- if (flags & SO_OBJECTS)
+- x = count_partial(n);
+ else
+- x = n->nr_partial;
++ x = atomic_long_read(&n->nr_slabs);
+ total += x;
+ nodes[node] += x;
+ }
+
+- if (flags & SO_FULL) {
+- int full_slabs = atomic_long_read(&n->nr_slabs)
+- - per_cpu[node]
+- - n->nr_partial;
++ } else if (flags & SO_PARTIAL) {
++ for_each_node_state(node, N_NORMAL_MEMORY) {
++ struct kmem_cache_node *n = get_node(s, node);
+
+- if (flags & SO_OBJECTS)
+- x = full_slabs * s->objects;
++ if (flags & SO_TOTAL)
++ x = count_partial(n, count_total);
++ else if (flags & SO_OBJECTS)
++ x = count_partial(n, count_inuse);
+ else
+- x = full_slabs;
++ x = n->nr_partial;
+ total += x;
+ nodes[node] += x;
+ }
+ }
+-
+ x = sprintf(buf, "%lu", total);
+ #ifdef CONFIG_NUMA
+ for_each_node_state(node, N_NORMAL_MEMORY)
+@@ -3657,14 +3757,6 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
+ static int any_slab_objects(struct kmem_cache *s)
+ {
+ int node;
+- int cpu;
+-
+- for_each_possible_cpu(cpu) {
+- struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
+-
+- if (c && c->page)
+- return 1;
+- }
+
+ for_each_online_node(node) {
+ struct kmem_cache_node *n = get_node(s, node);
+@@ -3672,7 +3764,7 @@ static int any_slab_objects(struct kmem_cache *s)
+ if (!n)
+ continue;
+
+- if (n->nr_partial || atomic_long_read(&n->nr_slabs))
++ if (atomic_read(&n->total_objects))
+ return 1;
+ }
+ return 0;
+@@ -3714,15 +3806,27 @@ SLAB_ATTR_RO(object_size);
+
+ static ssize_t objs_per_slab_show(struct kmem_cache *s, char *buf)
+ {
+- return sprintf(buf, "%d\n", s->objects);
++ return sprintf(buf, "%d\n", oo_objects(s->oo));
+ }
+ SLAB_ATTR_RO(objs_per_slab);
+
++static ssize_t order_store(struct kmem_cache *s,
++ const char *buf, size_t length)
++{
++ int order = simple_strtoul(buf, NULL, 10);
++
++ if (order > slub_max_order || order < slub_min_order)
++ return -EINVAL;
++
++ calculate_sizes(s, order);
++ return length;
++}
++
+ static ssize_t order_show(struct kmem_cache *s, char *buf)
+ {
+- return sprintf(buf, "%d\n", s->order);
++ return sprintf(buf, "%d\n", oo_order(s->oo));
+ }
+-SLAB_ATTR_RO(order);
++SLAB_ATTR(order);
+
+ static ssize_t ctor_show(struct kmem_cache *s, char *buf)
+ {
+@@ -3743,7 +3847,7 @@ SLAB_ATTR_RO(aliases);
+
+ static ssize_t slabs_show(struct kmem_cache *s, char *buf)
+ {
+- return show_slab_objects(s, buf, SO_FULL|SO_PARTIAL|SO_CPU);
++ return show_slab_objects(s, buf, SO_ALL);
+ }
+ SLAB_ATTR_RO(slabs);
+
+@@ -3761,10 +3865,22 @@ SLAB_ATTR_RO(cpu_slabs);
+
+ static ssize_t objects_show(struct kmem_cache *s, char *buf)
+ {
+- return show_slab_objects(s, buf, SO_FULL|SO_PARTIAL|SO_CPU|SO_OBJECTS);
++ return show_slab_objects(s, buf, SO_ALL|SO_OBJECTS);
+ }
+ SLAB_ATTR_RO(objects);
+
++static ssize_t objects_partial_show(struct kmem_cache *s, char *buf)
++{
++ return show_slab_objects(s, buf, SO_PARTIAL|SO_OBJECTS);
++}
++SLAB_ATTR_RO(objects_partial);
++
++static ssize_t total_objects_show(struct kmem_cache *s, char *buf)
++{
++ return show_slab_objects(s, buf, SO_ALL|SO_TOTAL);
++}
++SLAB_ATTR_RO(total_objects);
++
+ static ssize_t sanity_checks_show(struct kmem_cache *s, char *buf)
+ {
+ return sprintf(buf, "%d\n", !!(s->flags & SLAB_DEBUG_FREE));
+@@ -3844,7 +3960,7 @@ static ssize_t red_zone_store(struct kmem_cache *s,
+ s->flags &= ~SLAB_RED_ZONE;
+ if (buf[0] == '1')
+ s->flags |= SLAB_RED_ZONE;
+- calculate_sizes(s);
++ calculate_sizes(s, -1);
+ return length;
+ }
+ SLAB_ATTR(red_zone);
+@@ -3863,7 +3979,7 @@ static ssize_t poison_store(struct kmem_cache *s,
+ s->flags &= ~SLAB_POISON;
+ if (buf[0] == '1')
+ s->flags |= SLAB_POISON;
+- calculate_sizes(s);
++ calculate_sizes(s, -1);
+ return length;
+ }
+ SLAB_ATTR(poison);
+@@ -3882,7 +3998,7 @@ static ssize_t store_user_store(struct kmem_cache *s,
+ s->flags &= ~SLAB_STORE_USER;
+ if (buf[0] == '1')
+ s->flags |= SLAB_STORE_USER;
+- calculate_sizes(s);
++ calculate_sizes(s, -1);
+ return length;
+ }
+ SLAB_ATTR(store_user);
+@@ -3979,10 +4095,12 @@ static int show_stat(struct kmem_cache *s, char *buf, enum stat_item si)
len = sprintf(buf, "%lu", sum);
@@ -841073,11 +1139384,873 @@
kfree(data);
return len + sprintf(buf + len, "\n");
}
+@@ -4011,7 +4129,7 @@ STAT_ATTR(DEACTIVATE_EMPTY, deactivate_empty);
+ STAT_ATTR(DEACTIVATE_TO_HEAD, deactivate_to_head);
+ STAT_ATTR(DEACTIVATE_TO_TAIL, deactivate_to_tail);
+ STAT_ATTR(DEACTIVATE_REMOTE_FREES, deactivate_remote_frees);
+-
++STAT_ATTR(ORDER_FALLBACK, order_fallback);
+ #endif
+
+ static struct attribute *slab_attrs[] = {
+@@ -4020,6 +4138,8 @@ static struct attribute *slab_attrs[] = {
+ &objs_per_slab_attr.attr,
+ &order_attr.attr,
+ &objects_attr.attr,
++ &objects_partial_attr.attr,
++ &total_objects_attr.attr,
+ &slabs_attr.attr,
+ &partial_attr.attr,
+ &cpu_slabs_attr.attr,
+@@ -4062,6 +4182,7 @@ static struct attribute *slab_attrs[] = {
+ &deactivate_to_head_attr.attr,
+ &deactivate_to_tail_attr.attr,
+ &deactivate_remote_frees_attr.attr,
++ &order_fallback_attr.attr,
+ #endif
+ NULL
+ };
+@@ -4348,7 +4469,8 @@ static int s_show(struct seq_file *m, void *p)
+ unsigned long nr_partials = 0;
+ unsigned long nr_slabs = 0;
+ unsigned long nr_inuse = 0;
+- unsigned long nr_objs;
++ unsigned long nr_objs = 0;
++ unsigned long nr_free = 0;
+ struct kmem_cache *s;
+ int node;
+
+@@ -4362,14 +4484,15 @@ static int s_show(struct seq_file *m, void *p)
+
+ nr_partials += n->nr_partial;
+ nr_slabs += atomic_long_read(&n->nr_slabs);
+- nr_inuse += count_partial(n);
++ nr_objs += atomic_long_read(&n->total_objects);
++ nr_free += count_partial(n, count_free);
+ }
+
+- nr_objs = nr_slabs * s->objects;
+- nr_inuse += (nr_slabs - nr_partials) * s->objects;
++ nr_inuse = nr_objs - nr_free;
+
+ seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", s->name, nr_inuse,
+- nr_objs, s->size, s->objects, (1 << s->order));
++ nr_objs, s->size, oo_objects(s->oo),
++ (1 << oo_order(s->oo)));
+ seq_printf(m, " : tunables %4u %4u %4u", 0, 0, 0);
+ seq_printf(m, " : slabdata %6lu %6lu %6lu", nr_slabs, nr_slabs,
+ 0UL);
+diff --git a/mm/sparse.c b/mm/sparse.c
+index 98d6b39..36511c7 100644
+--- a/mm/sparse.c
++++ b/mm/sparse.c
+@@ -8,6 +8,7 @@
+ #include <linux/module.h>
+ #include <linux/spinlock.h>
+ #include <linux/vmalloc.h>
++#include "internal.h"
+ #include <asm/dma.h>
+ #include <asm/pgalloc.h>
+ #include <asm/pgtable.h>
+@@ -208,12 +209,12 @@ static unsigned long sparse_encode_mem_map(struct page *mem_map, unsigned long p
+ }
+
+ /*
+- * We need this if we ever free the mem_maps. While not implemented yet,
+- * this function is included for parity with its sibling.
++ * Decode mem_map from the coded memmap
+ */
+-static __attribute((unused))
+ struct page *sparse_decode_mem_map(unsigned long coded_mem_map, unsigned long pnum)
+ {
++ /* mask off the extra low bits of information */
++ coded_mem_map &= SECTION_MAP_MASK;
+ return ((struct page *)coded_mem_map) + section_nr_to_pfn(pnum);
+ }
+
+@@ -232,7 +233,7 @@ static int __meminit sparse_init_one_section(struct mem_section *ms,
+ return 1;
+ }
+
+-static unsigned long usemap_size(void)
++unsigned long usemap_size(void)
+ {
+ unsigned long size_bytes;
+ size_bytes = roundup(SECTION_BLOCKFLAGS_BITS, 8) / 8;
+@@ -260,7 +261,7 @@ static unsigned long *__init sparse_early_usemap_alloc(unsigned long pnum)
+ /* Stupid: suppress gcc warning for SPARSEMEM && !NUMA */
+ nid = 0;
+
+- printk(KERN_WARNING "%s: allocation failed\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: allocation failed\n", __func__);
+ return NULL;
+ }
+
+@@ -273,8 +274,8 @@ struct page __init *sparse_mem_map_populate(unsigned long pnum, int nid)
+ if (map)
+ return map;
+
+- map = alloc_bootmem_node(NODE_DATA(nid),
+- sizeof(struct page) * PAGES_PER_SECTION);
++ map = alloc_bootmem_pages_node(NODE_DATA(nid),
++ PAGE_ALIGN(sizeof(struct page) * PAGES_PER_SECTION));
+ return map;
+ }
+ #endif /* !CONFIG_SPARSEMEM_VMEMMAP */
+@@ -290,11 +291,14 @@ struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
+ return map;
+
+ printk(KERN_ERR "%s: sparsemem memory map backing failed "
+- "some memory will not be available.\n", __FUNCTION__);
++ "some memory will not be available.\n", __func__);
+ ms->section_mem_map = 0;
+ return NULL;
+ }
+
++void __attribute__((weak)) __meminit vmemmap_populate_print_last(void)
++{
++}
+ /*
+ * Allocate the accumulated non-linear sections, allocate a mem_map
+ * for each and record the physical to section mapping.
+@@ -304,22 +308,50 @@ void __init sparse_init(void)
+ unsigned long pnum;
+ struct page *map;
+ unsigned long *usemap;
++ unsigned long **usemap_map;
++ int size;
++
++ /*
++ * map is using big page (aka 2M in x86 64 bit)
++ * usemap is less one page (aka 24 bytes)
++ * so alloc 2M (with 2M align) and 24 bytes in turn will
++ * make next 2M slip to one more 2M later.
++ * then in big system, the memory will have a lot of holes...
++ * here try to allocate 2M pages continously.
++ *
++ * powerpc need to call sparse_init_one_section right after each
++ * sparse_early_mem_map_alloc, so allocate usemap_map at first.
++ */
++ size = sizeof(unsigned long *) * NR_MEM_SECTIONS;
++ usemap_map = alloc_bootmem(size);
++ if (!usemap_map)
++ panic("can not allocate usemap_map\n");
+
+ for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
+ if (!present_section_nr(pnum))
+ continue;
++ usemap_map[pnum] = sparse_early_usemap_alloc(pnum);
++ }
+
+- map = sparse_early_mem_map_alloc(pnum);
+- if (!map)
++ for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
++ if (!present_section_nr(pnum))
+ continue;
+
+- usemap = sparse_early_usemap_alloc(pnum);
++ usemap = usemap_map[pnum];
+ if (!usemap)
+ continue;
+
++ map = sparse_early_mem_map_alloc(pnum);
++ if (!map)
++ continue;
++
+ sparse_init_one_section(__nr_to_section(pnum), pnum, map,
+ usemap);
+ }
++
++ vmemmap_populate_print_last();
++
++ free_bootmem(__pa(usemap_map), size);
+ }
+
+ #ifdef CONFIG_MEMORY_HOTPLUG
+@@ -334,6 +366,9 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
+ {
+ return; /* XXX: Not implemented yet */
+ }
++static void free_map_bootmem(struct page *page, unsigned long nr_pages)
++{
++}
+ #else
+ static struct page *__kmalloc_section_memmap(unsigned long nr_pages)
+ {
+@@ -371,8 +406,69 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
+ free_pages((unsigned long)memmap,
+ get_order(sizeof(struct page) * nr_pages));
+ }
++
++static void free_map_bootmem(struct page *page, unsigned long nr_pages)
++{
++ unsigned long maps_section_nr, removing_section_nr, i;
++ int magic;
++
++ for (i = 0; i < nr_pages; i++, page++) {
++ magic = atomic_read(&page->_mapcount);
++
++ BUG_ON(magic == NODE_INFO);
++
++ maps_section_nr = pfn_to_section_nr(page_to_pfn(page));
++ removing_section_nr = page->private;
++
++ /*
++ * When this function is called, the removing section is
++ * logical offlined state. This means all pages are isolated
++ * from page allocator. If removing section's memmap is placed
++ * on the same section, it must not be freed.
++ * If it is freed, page allocator may allocate it which will
++ * be removed physically soon.
++ */
++ if (maps_section_nr != removing_section_nr)
++ put_page_bootmem(page);
++ }
++}
+ #endif /* CONFIG_SPARSEMEM_VMEMMAP */
+
++static void free_section_usemap(struct page *memmap, unsigned long *usemap)
++{
++ struct page *usemap_page;
++ unsigned long nr_pages;
++
++ if (!usemap)
++ return;
++
++ usemap_page = virt_to_page(usemap);
++ /*
++ * Check to see if allocation came from hot-plug-add
++ */
++ if (PageSlab(usemap_page)) {
++ kfree(usemap);
++ if (memmap)
++ __kfree_section_memmap(memmap, PAGES_PER_SECTION);
++ return;
++ }
++
++ /*
++ * The usemap came from bootmem. This is packed with other usemaps
++ * on the section which has pgdat at boot time. Just keep it as is now.
++ */
++
++ if (memmap) {
++ struct page *memmap_page;
++ memmap_page = virt_to_page(memmap);
++
++ nr_pages = PAGE_ALIGN(PAGES_PER_SECTION * sizeof(struct page))
++ >> PAGE_SHIFT;
++
++ free_map_bootmem(memmap_page, nr_pages);
++ }
++}
++
+ /*
+ * returns the number of sections whose mem_maps were properly
+ * set. If this is <=0, then that means that the passed-in
+@@ -425,4 +521,20 @@ out:
+ }
+ return ret;
+ }
++
++void sparse_remove_one_section(struct zone *zone, struct mem_section *ms)
++{
++ struct page *memmap = NULL;
++ unsigned long *usemap = NULL;
++
++ if (ms->section_mem_map) {
++ usemap = ms->pageblock_flags;
++ memmap = sparse_decode_mem_map(ms->section_mem_map,
++ __section_nr(ms));
++ ms->section_mem_map = 0;
++ ms->pageblock_flags = NULL;
++ }
++
++ free_section_usemap(memmap, usemap);
++}
+ #endif
+diff --git a/mm/swap.c b/mm/swap.c
+index aa1139c..91e1944 100644
+--- a/mm/swap.c
++++ b/mm/swap.c
+@@ -132,34 +132,21 @@ static void pagevec_move_tail(struct pagevec *pvec)
+ * Writeback is about to end against a page which has been marked for immediate
+ * reclaim. If it still appears to be reclaimable, move it to the tail of the
+ * inactive list.
+- *
+- * Returns zero if it cleared PG_writeback.
+ */
+-int rotate_reclaimable_page(struct page *page)
++void rotate_reclaimable_page(struct page *page)
+ {
+- struct pagevec *pvec;
+- unsigned long flags;
+-
+- if (PageLocked(page))
+- return 1;
+- if (PageDirty(page))
+- return 1;
+- if (PageActive(page))
+- return 1;
+- if (!PageLRU(page))
+- return 1;
+-
+- page_cache_get(page);
+- local_irq_save(flags);
+- pvec = &__get_cpu_var(lru_rotate_pvecs);
+- if (!pagevec_add(pvec, page))
+- pagevec_move_tail(pvec);
+- local_irq_restore(flags);
+-
+- if (!test_clear_page_writeback(page))
+- BUG();
++ if (!PageLocked(page) && !PageDirty(page) && !PageActive(page) &&
++ PageLRU(page)) {
++ struct pagevec *pvec;
++ unsigned long flags;
+
+- return 0;
++ page_cache_get(page);
++ local_irq_save(flags);
++ pvec = &__get_cpu_var(lru_rotate_pvecs);
++ if (!pagevec_add(pvec, page))
++ pagevec_move_tail(pvec);
++ local_irq_restore(flags);
++ }
+ }
+
+ /*
+diff --git a/mm/swap_state.c b/mm/swap_state.c
+index 50757ee..d8aadaf 100644
+--- a/mm/swap_state.c
++++ b/mm/swap_state.c
+@@ -33,7 +33,7 @@ static const struct address_space_operations swap_aops = {
+ };
+
+ static struct backing_dev_info swap_backing_dev_info = {
+- .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
++ .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK,
+ .unplug_io_fn = swap_unplug_io_fn,
+ };
+
+diff --git a/mm/swapfile.c b/mm/swapfile.c
+index 2da149c..bd1bb59 100644
+--- a/mm/swapfile.c
++++ b/mm/swapfile.c
+@@ -1426,11 +1426,7 @@ static const struct file_operations proc_swaps_operations = {
+
+ static int __init procswaps_init(void)
+ {
+- struct proc_dir_entry *entry;
+-
+- entry = create_proc_entry("swaps", 0, NULL);
+- if (entry)
+- entry->proc_fops = &proc_swaps_operations;
++ proc_create("swaps", 0, NULL, &proc_swaps_operations);
+ return 0;
+ }
+ __initcall(procswaps_init);
+@@ -1582,6 +1578,14 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
+ error = -EINVAL;
+ goto bad_swap;
+ case 2:
++ /* swap partition endianess hack... */
++ if (swab32(swap_header->info.version) == 1) {
++ swab32s(&swap_header->info.version);
++ swab32s(&swap_header->info.last_page);
++ swab32s(&swap_header->info.nr_badpages);
++ for (i = 0; i < swap_header->info.nr_badpages; i++)
++ swab32s(&swap_header->info.badpages[i]);
++ }
+ /* Check the swap header's sub-version and the size of
+ the swap file and bad block lists */
+ if (swap_header->info.version != 1) {
+diff --git a/mm/truncate.c b/mm/truncate.c
+index 7d20ce4..b8961cb 100644
+--- a/mm/truncate.c
++++ b/mm/truncate.c
+@@ -391,6 +391,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
+ pgoff_t next;
+ int i;
+ int ret = 0;
++ int ret2 = 0;
+ int did_range_unmap = 0;
+ int wrapped = 0;
+
+@@ -438,9 +439,13 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
+ }
+ }
+ BUG_ON(page_mapped(page));
+- ret = do_launder_page(mapping, page);
+- if (ret == 0 && !invalidate_complete_page2(mapping, page))
+- ret = -EIO;
++ ret2 = do_launder_page(mapping, page);
++ if (ret2 == 0) {
++ if (!invalidate_complete_page2(mapping, page))
++ ret2 = -EIO;
++ }
++ if (ret2 < 0)
++ ret = ret2;
+ unlock_page(page);
+ }
+ pagevec_release(&pvec);
+diff --git a/mm/vmalloc.c b/mm/vmalloc.c
+index ecf91f8..2a39cf1 100644
+--- a/mm/vmalloc.c
++++ b/mm/vmalloc.c
+@@ -14,8 +14,10 @@
+ #include <linux/slab.h>
+ #include <linux/spinlock.h>
+ #include <linux/interrupt.h>
+-
++#include <linux/seq_file.h>
++#include <linux/debugobjects.h>
+ #include <linux/vmalloc.h>
++#include <linux/kallsyms.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/tlbflush.h>
+@@ -25,7 +27,7 @@ DEFINE_RWLOCK(vmlist_lock);
+ struct vm_struct *vmlist;
+
+ static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
+- int node);
++ int node, void *caller);
+
+ static void vunmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end)
+ {
+@@ -204,9 +206,9 @@ unsigned long vmalloc_to_pfn(const void *vmalloc_addr)
+ }
+ EXPORT_SYMBOL(vmalloc_to_pfn);
+
+-static struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long flags,
+- unsigned long start, unsigned long end,
+- int node, gfp_t gfp_mask)
++static struct vm_struct *
++__get_vm_area_node(unsigned long size, unsigned long flags, unsigned long start,
++ unsigned long end, int node, gfp_t gfp_mask, void *caller)
+ {
+ struct vm_struct **p, *tmp, *area;
+ unsigned long align = 1;
+@@ -269,6 +271,7 @@ found:
+ area->pages = NULL;
+ area->nr_pages = 0;
+ area->phys_addr = 0;
++ area->caller = caller;
+ write_unlock(&vmlist_lock);
+
+ return area;
+@@ -284,7 +287,8 @@ out:
+ struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
+ unsigned long start, unsigned long end)
+ {
+- return __get_vm_area_node(size, flags, start, end, -1, GFP_KERNEL);
++ return __get_vm_area_node(size, flags, start, end, -1, GFP_KERNEL,
++ __builtin_return_address(0));
+ }
+ EXPORT_SYMBOL_GPL(__get_vm_area);
+
+@@ -299,14 +303,22 @@ EXPORT_SYMBOL_GPL(__get_vm_area);
+ */
+ struct vm_struct *get_vm_area(unsigned long size, unsigned long flags)
+ {
+- return __get_vm_area(size, flags, VMALLOC_START, VMALLOC_END);
++ return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END,
++ -1, GFP_KERNEL, __builtin_return_address(0));
++}
++
++struct vm_struct *get_vm_area_caller(unsigned long size, unsigned long flags,
++ void *caller)
++{
++ return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END,
++ -1, GFP_KERNEL, caller);
+ }
+
+ struct vm_struct *get_vm_area_node(unsigned long size, unsigned long flags,
+ int node, gfp_t gfp_mask)
+ {
+ return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END, node,
+- gfp_mask);
++ gfp_mask, __builtin_return_address(0));
+ }
+
+ /* Caller must hold vmlist_lock */
+@@ -383,6 +395,7 @@ static void __vunmap(const void *addr, int deallocate_pages)
+ }
+
+ debug_check_no_locks_freed(addr, area->size);
++ debug_check_no_obj_freed(addr, area->size);
+
+ if (deallocate_pages) {
+ int i;
+@@ -455,9 +468,11 @@ void *vmap(struct page **pages, unsigned int count,
+ if (count > num_physpages)
+ return NULL;
+
+- area = get_vm_area((count << PAGE_SHIFT), flags);
++ area = get_vm_area_caller((count << PAGE_SHIFT), flags,
++ __builtin_return_address(0));
+ if (!area)
+ return NULL;
++
+ if (map_vm_area(area, prot, &pages)) {
+ vunmap(area->addr);
+ return NULL;
+@@ -468,7 +483,7 @@ void *vmap(struct page **pages, unsigned int count,
+ EXPORT_SYMBOL(vmap);
+
+ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
+- pgprot_t prot, int node)
++ pgprot_t prot, int node, void *caller)
+ {
+ struct page **pages;
+ unsigned int nr_pages, array_size, i;
+@@ -480,7 +495,7 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
+ /* Please note that the recursion is strictly bounded. */
+ if (array_size > PAGE_SIZE) {
+ pages = __vmalloc_node(array_size, gfp_mask | __GFP_ZERO,
+- PAGE_KERNEL, node);
++ PAGE_KERNEL, node, caller);
+ area->flags |= VM_VPAGES;
+ } else {
+ pages = kmalloc_node(array_size,
+@@ -488,6 +503,7 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
+ node);
+ }
+ area->pages = pages;
++ area->caller = caller;
+ if (!area->pages) {
+ remove_vm_area(area->addr);
+ kfree(area);
+@@ -521,7 +537,8 @@ fail:
+
+ void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot)
+ {
+- return __vmalloc_area_node(area, gfp_mask, prot, -1);
++ return __vmalloc_area_node(area, gfp_mask, prot, -1,
++ __builtin_return_address(0));
+ }
+
+ /**
+@@ -536,7 +553,7 @@ void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot)
+ * kernel virtual space, using a pagetable protection of @prot.
+ */
+ static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
+- int node)
++ int node, void *caller)
+ {
+ struct vm_struct *area;
+
+@@ -544,16 +561,19 @@ static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
+ if (!size || (size >> PAGE_SHIFT) > num_physpages)
+ return NULL;
+
+- area = get_vm_area_node(size, VM_ALLOC, node, gfp_mask);
++ area = __get_vm_area_node(size, VM_ALLOC, VMALLOC_START, VMALLOC_END,
++ node, gfp_mask, caller);
++
+ if (!area)
+ return NULL;
+
+- return __vmalloc_area_node(area, gfp_mask, prot, node);
++ return __vmalloc_area_node(area, gfp_mask, prot, node, caller);
+ }
+
+ void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
+ {
+- return __vmalloc_node(size, gfp_mask, prot, -1);
++ return __vmalloc_node(size, gfp_mask, prot, -1,
++ __builtin_return_address(0));
+ }
+ EXPORT_SYMBOL(__vmalloc);
+
+@@ -568,7 +588,8 @@ EXPORT_SYMBOL(__vmalloc);
+ */
+ void *vmalloc(unsigned long size)
+ {
+- return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
++ return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL,
++ -1, __builtin_return_address(0));
+ }
+ EXPORT_SYMBOL(vmalloc);
+
+@@ -608,7 +629,8 @@ EXPORT_SYMBOL(vmalloc_user);
+ */
+ void *vmalloc_node(unsigned long size, int node)
+ {
+- return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, node);
++ return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL,
++ node, __builtin_return_address(0));
+ }
+ EXPORT_SYMBOL(vmalloc_node);
+
+@@ -843,7 +865,8 @@ struct vm_struct *alloc_vm_area(size_t size)
+ {
+ struct vm_struct *area;
+
+- area = get_vm_area(size, VM_IOREMAP);
++ area = get_vm_area_caller(size, VM_IOREMAP,
++ __builtin_return_address(0));
+ if (area == NULL)
+ return NULL;
+
+@@ -873,3 +896,85 @@ void free_vm_area(struct vm_struct *area)
+ kfree(area);
+ }
+ EXPORT_SYMBOL_GPL(free_vm_area);
++
++
++#ifdef CONFIG_PROC_FS
++static void *s_start(struct seq_file *m, loff_t *pos)
++{
++ loff_t n = *pos;
++ struct vm_struct *v;
++
++ read_lock(&vmlist_lock);
++ v = vmlist;
++ while (n > 0 && v) {
++ n--;
++ v = v->next;
++ }
++ if (!n)
++ return v;
++
++ return NULL;
++
++}
++
++static void *s_next(struct seq_file *m, void *p, loff_t *pos)
++{
++ struct vm_struct *v = p;
++
++ ++*pos;
++ return v->next;
++}
++
++static void s_stop(struct seq_file *m, void *p)
++{
++ read_unlock(&vmlist_lock);
++}
++
++static int s_show(struct seq_file *m, void *p)
++{
++ struct vm_struct *v = p;
++
++ seq_printf(m, "0x%p-0x%p %7ld",
++ v->addr, v->addr + v->size, v->size);
++
++ if (v->caller) {
++ char buff[2 * KSYM_NAME_LEN];
++
++ seq_putc(m, ' ');
++ sprint_symbol(buff, (unsigned long)v->caller);
++ seq_puts(m, buff);
++ }
++
++ if (v->nr_pages)
++ seq_printf(m, " pages=%d", v->nr_pages);
++
++ if (v->phys_addr)
++ seq_printf(m, " phys=%lx", v->phys_addr);
++
++ if (v->flags & VM_IOREMAP)
++ seq_printf(m, " ioremap");
++
++ if (v->flags & VM_ALLOC)
++ seq_printf(m, " vmalloc");
++
++ if (v->flags & VM_MAP)
++ seq_printf(m, " vmap");
++
++ if (v->flags & VM_USERMAP)
++ seq_printf(m, " user");
++
++ if (v->flags & VM_VPAGES)
++ seq_printf(m, " vpages");
++
++ seq_putc(m, '\n');
++ return 0;
++}
++
++const struct seq_operations vmalloc_op = {
++ .start = s_start,
++ .next = s_next,
++ .stop = s_stop,
++ .show = s_show,
++};
++#endif
++
diff --git a/mm/vmscan.c b/mm/vmscan.c
-index 4046434..f80a5b7 100644
+index 4046434..9a29901 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
-@@ -1647,11 +1647,10 @@ static int kswapd(void *p)
+@@ -191,7 +191,7 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
+ shrinker->nr += delta;
+ if (shrinker->nr < 0) {
+ printk(KERN_ERR "%s: nr=%ld\n",
+- __FUNCTION__, shrinker->nr);
++ __func__, shrinker->nr);
+ shrinker->nr = max_pass;
+ }
+
+@@ -339,7 +339,7 @@ static pageout_t pageout(struct page *page, struct address_space *mapping,
+ if (PagePrivate(page)) {
+ if (try_to_free_buffers(page)) {
+ ClearPageDirty(page);
+- printk("%s: orphaned page\n", __FUNCTION__);
++ printk("%s: orphaned page\n", __func__);
+ return PAGE_CLEAN;
+ }
+ }
+@@ -1246,17 +1246,16 @@ static unsigned long shrink_zone(int priority, struct zone *zone,
+ * If a zone is deemed to be full of pinned pages then just give it a light
+ * scan then give up on it.
+ */
+-static unsigned long shrink_zones(int priority, struct zone **zones,
++static unsigned long shrink_zones(int priority, struct zonelist *zonelist,
+ struct scan_control *sc)
+ {
++ enum zone_type high_zoneidx = gfp_zone(sc->gfp_mask);
+ unsigned long nr_reclaimed = 0;
+- int i;
+-
++ struct zoneref *z;
++ struct zone *zone;
+
+ sc->all_unreclaimable = 1;
+- for (i = 0; zones[i] != NULL; i++) {
+- struct zone *zone = zones[i];
+-
++ for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) {
+ if (!populated_zone(zone))
+ continue;
+ /*
+@@ -1300,9 +1299,12 @@ static unsigned long shrink_zones(int priority, struct zone **zones,
+ * hope that some of these pages can be written. But if the allocating task
+ * holds filesystem locks which prevent writeout this might not work, and the
+ * allocation attempt will fail.
++ *
++ * returns: 0, if no pages reclaimed
++ * else, the number of pages reclaimed
+ */
+-static unsigned long do_try_to_free_pages(struct zone **zones, gfp_t gfp_mask,
+- struct scan_control *sc)
++static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
++ struct scan_control *sc)
+ {
+ int priority;
+ int ret = 0;
+@@ -1310,7 +1312,9 @@ static unsigned long do_try_to_free_pages(struct zone **zones, gfp_t gfp_mask,
+ unsigned long nr_reclaimed = 0;
+ struct reclaim_state *reclaim_state = current->reclaim_state;
+ unsigned long lru_pages = 0;
+- int i;
++ struct zoneref *z;
++ struct zone *zone;
++ enum zone_type high_zoneidx = gfp_zone(sc->gfp_mask);
+
+ if (scan_global_lru(sc))
+ count_vm_event(ALLOCSTALL);
+@@ -1318,8 +1322,7 @@ static unsigned long do_try_to_free_pages(struct zone **zones, gfp_t gfp_mask,
+ * mem_cgroup will not do shrink_slab.
+ */
+ if (scan_global_lru(sc)) {
+- for (i = 0; zones[i] != NULL; i++) {
+- struct zone *zone = zones[i];
++ for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) {
+
+ if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
+ continue;
+@@ -1333,13 +1336,13 @@ static unsigned long do_try_to_free_pages(struct zone **zones, gfp_t gfp_mask,
+ sc->nr_scanned = 0;
+ if (!priority)
+ disable_swap_token();
+- nr_reclaimed += shrink_zones(priority, zones, sc);
++ nr_reclaimed += shrink_zones(priority, zonelist, sc);
+ /*
+ * Don't shrink slabs when reclaiming memory from
+ * over limit cgroups
+ */
+ if (scan_global_lru(sc)) {
+- shrink_slab(sc->nr_scanned, gfp_mask, lru_pages);
++ shrink_slab(sc->nr_scanned, sc->gfp_mask, lru_pages);
+ if (reclaim_state) {
+ nr_reclaimed += reclaim_state->reclaimed_slab;
+ reclaim_state->reclaimed_slab = 0;
+@@ -1347,7 +1350,7 @@ static unsigned long do_try_to_free_pages(struct zone **zones, gfp_t gfp_mask,
+ }
+ total_scanned += sc->nr_scanned;
+ if (nr_reclaimed >= sc->swap_cluster_max) {
+- ret = 1;
++ ret = nr_reclaimed;
+ goto out;
+ }
+
+@@ -1370,7 +1373,7 @@ static unsigned long do_try_to_free_pages(struct zone **zones, gfp_t gfp_mask,
+ }
+ /* top priority shrink_caches still had more to do? don't OOM, then */
+ if (!sc->all_unreclaimable && scan_global_lru(sc))
+- ret = 1;
++ ret = nr_reclaimed;
+ out:
+ /*
+ * Now that we've scanned all the zones at this priority level, note
+@@ -1383,8 +1386,7 @@ out:
+ priority = 0;
+
+ if (scan_global_lru(sc)) {
+- for (i = 0; zones[i] != NULL; i++) {
+- struct zone *zone = zones[i];
++ for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) {
+
+ if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
+ continue;
+@@ -1397,7 +1399,8 @@ out:
+ return ret;
+ }
+
+-unsigned long try_to_free_pages(struct zone **zones, int order, gfp_t gfp_mask)
++unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
++ gfp_t gfp_mask)
+ {
+ struct scan_control sc = {
+ .gfp_mask = gfp_mask,
+@@ -1410,7 +1413,7 @@ unsigned long try_to_free_pages(struct zone **zones, int order, gfp_t gfp_mask)
+ .isolate_pages = isolate_pages_global,
+ };
+
+- return do_try_to_free_pages(zones, gfp_mask, &sc);
++ return do_try_to_free_pages(zonelist, &sc);
+ }
+
+ #ifdef CONFIG_CGROUP_MEM_RES_CTLR
+@@ -1419,7 +1422,6 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,
+ gfp_t gfp_mask)
+ {
+ struct scan_control sc = {
+- .gfp_mask = gfp_mask,
+ .may_writepage = !laptop_mode,
+ .may_swap = 1,
+ .swap_cluster_max = SWAP_CLUSTER_MAX,
+@@ -1428,13 +1430,12 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,
+ .mem_cgroup = mem_cont,
+ .isolate_pages = mem_cgroup_isolate_pages,
+ };
+- struct zone **zones;
+- int target_zone = gfp_zone(GFP_HIGHUSER_MOVABLE);
++ struct zonelist *zonelist;
+
+- zones = NODE_DATA(numa_node_id())->node_zonelists[target_zone].zones;
+- if (do_try_to_free_pages(zones, sc.gfp_mask, &sc))
+- return 1;
+- return 0;
++ sc.gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) |
++ (GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK);
++ zonelist = NODE_DATA(numa_node_id())->node_zonelists;
++ return do_try_to_free_pages(zonelist, &sc);
+ }
+ #endif
+
+@@ -1647,11 +1648,10 @@ static int kswapd(void *p)
struct reclaim_state reclaim_state = {
.reclaimed_slab = 0,
};
@@ -841092,7 +1140265,7 @@
current->reclaim_state = &reclaim_state;
/*
-@@ -1880,17 +1879,16 @@ out:
+@@ -1880,17 +1880,16 @@ out:
static int __devinit cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
@@ -841115,6 +1140288,65 @@
}
}
return NOTIFY_OK;
+diff --git a/mm/vmstat.c b/mm/vmstat.c
+index 7c7286e..1a32130 100644
+--- a/mm/vmstat.c
++++ b/mm/vmstat.c
+@@ -322,6 +322,7 @@ void refresh_cpu_vm_stats(int cpu)
+ p->expire = 3;
+ #endif
+ }
++ cond_resched();
+ #ifdef CONFIG_NUMA
+ /*
+ * Deal with draining the remote pageset of this
+@@ -364,13 +365,13 @@ void refresh_cpu_vm_stats(int cpu)
+ *
+ * Must be called with interrupts disabled.
+ */
+-void zone_statistics(struct zonelist *zonelist, struct zone *z)
++void zone_statistics(struct zone *preferred_zone, struct zone *z)
+ {
+- if (z->zone_pgdat == zonelist->zones[0]->zone_pgdat) {
++ if (z->zone_pgdat == preferred_zone->zone_pgdat) {
+ __inc_zone_state(z, NUMA_HIT);
+ } else {
+ __inc_zone_state(z, NUMA_MISS);
+- __inc_zone_state(zonelist->zones[0], NUMA_FOREIGN);
++ __inc_zone_state(preferred_zone, NUMA_FOREIGN);
+ }
+ if (z->node == numa_node_id())
+ __inc_zone_state(z, NUMA_LOCAL);
+@@ -547,6 +548,10 @@ static int pagetypeinfo_show(struct seq_file *m, void *arg)
+ {
+ pg_data_t *pgdat = (pg_data_t *)arg;
+
++ /* check memoryless node */
++ if (!node_state(pgdat->node_id, N_HIGH_MEMORY))
++ return 0;
++
+ seq_printf(m, "Page block order: %d\n", pageblock_order);
+ seq_printf(m, "Pages per block: %lu\n", pageblock_nr_pages);
+ seq_putc(m, '\n');
+@@ -607,6 +612,7 @@ static const char * const vmstat_text[] = {
+ "nr_unstable",
+ "nr_bounce",
+ "nr_vmscan_write",
++ "nr_writeback_temp",
+
+ #ifdef CONFIG_NUMA
+ "numa_hit",
+@@ -645,6 +651,10 @@ static const char * const vmstat_text[] = {
+ "allocstall",
+
+ "pgrotated",
++#ifdef CONFIG_HUGETLB_PAGE
++ "htlb_buddy_alloc_success",
++ "htlb_buddy_alloc_fail",
++#endif
+ #endif
+ };
+
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index b33410a..2a739ad 100644
--- a/net/8021q/vlan.c
@@ -842215,6 +1141447,44 @@
if (!sk) {
bh_unlock_sock(parent);
goto done;
+diff --git a/net/bridge/br.c b/net/bridge/br.c
+index a901828..8f3c58e 100644
+--- a/net/bridge/br.c
++++ b/net/bridge/br.c
+@@ -76,7 +76,6 @@ static void __exit br_deinit(void)
+ rcu_assign_pointer(br_stp_sap->rcv_func, NULL);
+
+ br_netlink_fini();
+- br_netfilter_fini();
+ unregister_netdevice_notifier(&br_device_notifier);
+ brioctl_set(NULL);
+
+@@ -84,6 +83,7 @@ static void __exit br_deinit(void)
+
+ synchronize_net();
+
++ br_netfilter_fini();
+ llc_sap_put(br_stp_sap);
+ br_fdb_get_hook = NULL;
+ br_fdb_put_hook = NULL;
+diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
+index 298e0f4..77a981a 100644
+--- a/net/bridge/br_if.c
++++ b/net/bridge/br_if.c
+@@ -411,9 +411,12 @@ err2:
+ br_fdb_delete_by_port(br, p, 1);
+ err1:
+ kobject_del(&p->kobj);
+- return err;
++ goto put_back;
+ err0:
+ kobject_put(&p->kobj);
++
++put_back:
++ dev_put(dev);
+ return err;
+ }
+
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index af7e8be..bb90cd7 100644
--- a/net/bridge/br_netfilter.c
@@ -842998,7 +1142268,7 @@
if (dev->type != ARPHRD_CAN)
diff --git a/net/can/raw.c b/net/can/raw.c
-index 94cd7f2..201cbfc 100644
+index 94cd7f2..69877b8 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -210,7 +210,7 @@ static int raw_notifier(struct notifier_block *nb,
@@ -843010,7 +1142280,59 @@
return NOTIFY_DONE;
if (dev->type != ARPHRD_CAN)
-@@ -573,7 +573,8 @@ static int raw_getsockopt(struct socket *sock, int level, int optname,
+@@ -435,15 +435,13 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
+ if (!filter)
+ return -ENOMEM;
+
+- err = copy_from_user(filter, optval, optlen);
+- if (err) {
++ if (copy_from_user(filter, optval, optlen)) {
+ kfree(filter);
+- return err;
++ return -EFAULT;
+ }
+ } else if (count == 1) {
+- err = copy_from_user(&sfilter, optval, optlen);
+- if (err)
+- return err;
++ if (copy_from_user(&sfilter, optval, optlen))
++ return -EFAULT;
+ }
+
+ lock_sock(sk);
+@@ -493,9 +491,8 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
+ if (optlen != sizeof(err_mask))
+ return -EINVAL;
+
+- err = copy_from_user(&err_mask, optval, optlen);
+- if (err)
+- return err;
++ if (copy_from_user(&err_mask, optval, optlen))
++ return -EFAULT;
+
+ err_mask &= CAN_ERR_MASK;
+
+@@ -531,7 +528,8 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
+ if (optlen != sizeof(ro->loopback))
+ return -EINVAL;
+
+- err = copy_from_user(&ro->loopback, optval, optlen);
++ if (copy_from_user(&ro->loopback, optval, optlen))
++ return -EFAULT;
+
+ break;
+
+@@ -539,7 +537,8 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
+ if (optlen != sizeof(ro->recv_own_msgs))
+ return -EINVAL;
+
+- err = copy_from_user(&ro->recv_own_msgs, optval, optlen);
++ if (copy_from_user(&ro->recv_own_msgs, optval, optlen))
++ return -EFAULT;
+
+ break;
+
+@@ -573,7 +572,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;
@@ -843020,8 +1142342,225 @@
} else
len = 0;
release_sock(sk);
+diff --git a/net/compat.c b/net/compat.c
+index 80013fb..c823f6f 100644
+--- a/net/compat.c
++++ b/net/compat.c
+@@ -24,6 +24,8 @@
+
+ #include <net/scm.h>
+ #include <net/sock.h>
++#include <net/ip.h>
++#include <net/ipv6.h>
+ #include <asm/uaccess.h>
+ #include <net/compat.h>
+
+@@ -521,6 +523,203 @@ asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
+ }
+ return err;
+ }
++
++struct compat_group_req {
++ __u32 gr_interface;
++ struct __kernel_sockaddr_storage gr_group
++ __attribute__ ((aligned(4)));
++} __attribute__ ((packed));
++
++struct compat_group_source_req {
++ __u32 gsr_interface;
++ struct __kernel_sockaddr_storage gsr_group
++ __attribute__ ((aligned(4)));
++ struct __kernel_sockaddr_storage gsr_source
++ __attribute__ ((aligned(4)));
++} __attribute__ ((packed));
++
++struct compat_group_filter {
++ __u32 gf_interface;
++ struct __kernel_sockaddr_storage gf_group
++ __attribute__ ((aligned(4)));
++ __u32 gf_fmode;
++ __u32 gf_numsrc;
++ struct __kernel_sockaddr_storage gf_slist[1]
++ __attribute__ ((aligned(4)));
++} __attribute__ ((packed));
++
++#define __COMPAT_GF0_SIZE (sizeof(struct compat_group_filter) - \
++ sizeof(struct __kernel_sockaddr_storage))
++
++
++int compat_mc_setsockopt(struct sock *sock, int level, int optname,
++ char __user *optval, int optlen,
++ int (*setsockopt)(struct sock *,int,int,char __user *,int))
++{
++ char __user *koptval = optval;
++ int koptlen = optlen;
++
++ switch (optname) {
++ case MCAST_JOIN_GROUP:
++ case MCAST_LEAVE_GROUP:
++ {
++ struct compat_group_req __user *gr32 = (void *)optval;
++ struct group_req __user *kgr =
++ compat_alloc_user_space(sizeof(struct group_req));
++ u32 interface;
++
++ if (!access_ok(VERIFY_READ, gr32, sizeof(*gr32)) ||
++ !access_ok(VERIFY_WRITE, kgr, sizeof(struct group_req)) ||
++ __get_user(interface, &gr32->gr_interface) ||
++ __put_user(interface, &kgr->gr_interface) ||
++ copy_in_user(&kgr->gr_group, &gr32->gr_group,
++ sizeof(kgr->gr_group)))
++ return -EFAULT;
++ koptval = (char __user *)kgr;
++ koptlen = sizeof(struct group_req);
++ break;
++ }
++ case MCAST_JOIN_SOURCE_GROUP:
++ case MCAST_LEAVE_SOURCE_GROUP:
++ case MCAST_BLOCK_SOURCE:
++ case MCAST_UNBLOCK_SOURCE:
++ {
++ struct compat_group_source_req __user *gsr32 = (void *)optval;
++ struct group_source_req __user *kgsr = compat_alloc_user_space(
++ sizeof(struct group_source_req));
++ u32 interface;
++
++ if (!access_ok(VERIFY_READ, gsr32, sizeof(*gsr32)) ||
++ !access_ok(VERIFY_WRITE, kgsr,
++ sizeof(struct group_source_req)) ||
++ __get_user(interface, &gsr32->gsr_interface) ||
++ __put_user(interface, &kgsr->gsr_interface) ||
++ copy_in_user(&kgsr->gsr_group, &gsr32->gsr_group,
++ sizeof(kgsr->gsr_group)) ||
++ copy_in_user(&kgsr->gsr_source, &gsr32->gsr_source,
++ sizeof(kgsr->gsr_source)))
++ return -EFAULT;
++ koptval = (char __user *)kgsr;
++ koptlen = sizeof(struct group_source_req);
++ break;
++ }
++ case MCAST_MSFILTER:
++ {
++ struct compat_group_filter __user *gf32 = (void *)optval;
++ struct group_filter __user *kgf;
++ u32 interface, fmode, numsrc;
++
++ if (!access_ok(VERIFY_READ, gf32, __COMPAT_GF0_SIZE) ||
++ __get_user(interface, &gf32->gf_interface) ||
++ __get_user(fmode, &gf32->gf_fmode) ||
++ __get_user(numsrc, &gf32->gf_numsrc))
++ return -EFAULT;
++ koptlen = optlen + sizeof(struct group_filter) -
++ sizeof(struct compat_group_filter);
++ if (koptlen < GROUP_FILTER_SIZE(numsrc))
++ return -EINVAL;
++ kgf = compat_alloc_user_space(koptlen);
++ if (!access_ok(VERIFY_WRITE, kgf, koptlen) ||
++ __put_user(interface, &kgf->gf_interface) ||
++ __put_user(fmode, &kgf->gf_fmode) ||
++ __put_user(numsrc, &kgf->gf_numsrc) ||
++ copy_in_user(&kgf->gf_group, &gf32->gf_group,
++ sizeof(kgf->gf_group)) ||
++ (numsrc && copy_in_user(kgf->gf_slist, gf32->gf_slist,
++ numsrc * sizeof(kgf->gf_slist[0]))))
++ return -EFAULT;
++ koptval = (char __user *)kgf;
++ break;
++ }
++
++ default:
++ break;
++ }
++ return setsockopt(sock, level, optname, koptval, koptlen);
++}
++
++EXPORT_SYMBOL(compat_mc_setsockopt);
++
++int compat_mc_getsockopt(struct sock *sock, int level, int optname,
++ char __user *optval, int __user *optlen,
++ int (*getsockopt)(struct sock *,int,int,char __user *,int __user *))
++{
++ struct compat_group_filter __user *gf32 = (void *)optval;
++ struct group_filter __user *kgf;
++ int __user *koptlen;
++ u32 interface, fmode, numsrc;
++ int klen, ulen, err;
++
++ if (optname != MCAST_MSFILTER)
++ return getsockopt(sock, level, optname, optval, optlen);
++
++ koptlen = compat_alloc_user_space(sizeof(*koptlen));
++ if (!access_ok(VERIFY_READ, optlen, sizeof(*optlen)) ||
++ __get_user(ulen, optlen))
++ return -EFAULT;
++
++ /* adjust len for pad */
++ klen = ulen + sizeof(*kgf) - sizeof(*gf32);
++
++ if (klen < GROUP_FILTER_SIZE(0))
++ return -EINVAL;
++
++ if (!access_ok(VERIFY_WRITE, koptlen, sizeof(*koptlen)) ||
++ __put_user(klen, koptlen))
++ return -EFAULT;
++
++ /* have to allow space for previous compat_alloc_user_space, too */
++ kgf = compat_alloc_user_space(klen+sizeof(*optlen));
++
++ if (!access_ok(VERIFY_READ, gf32, __COMPAT_GF0_SIZE) ||
++ __get_user(interface, &gf32->gf_interface) ||
++ __get_user(fmode, &gf32->gf_fmode) ||
++ __get_user(numsrc, &gf32->gf_numsrc) ||
++ __put_user(interface, &kgf->gf_interface) ||
++ __put_user(fmode, &kgf->gf_fmode) ||
++ __put_user(numsrc, &kgf->gf_numsrc) ||
++ copy_in_user(&kgf->gf_group,&gf32->gf_group,sizeof(kgf->gf_group)))
++ return -EFAULT;
++
++ err = getsockopt(sock, level, optname, (char __user *)kgf, koptlen);
++ if (err)
++ return err;
++
++ if (!access_ok(VERIFY_READ, koptlen, sizeof(*koptlen)) ||
++ __get_user(klen, koptlen))
++ return -EFAULT;
++
++ ulen = klen - (sizeof(*kgf)-sizeof(*gf32));
++
++ if (!access_ok(VERIFY_WRITE, optlen, sizeof(*optlen)) ||
++ __put_user(ulen, optlen))
++ return -EFAULT;
++
++ if (!access_ok(VERIFY_READ, kgf, klen) ||
++ !access_ok(VERIFY_WRITE, gf32, ulen) ||
++ __get_user(interface, &kgf->gf_interface) ||
++ __get_user(fmode, &kgf->gf_fmode) ||
++ __get_user(numsrc, &kgf->gf_numsrc) ||
++ __put_user(interface, &gf32->gf_interface) ||
++ __put_user(fmode, &gf32->gf_fmode) ||
++ __put_user(numsrc, &gf32->gf_numsrc))
++ return -EFAULT;
++ if (numsrc) {
++ int copylen;
++
++ klen -= GROUP_FILTER_SIZE(0);
++ copylen = numsrc * sizeof(gf32->gf_slist[0]);
++ if (copylen > klen)
++ copylen = klen;
++ if (copy_in_user(gf32->gf_slist, kgf->gf_slist, copylen))
++ return -EFAULT;
++ }
++ return err;
++}
++
++EXPORT_SYMBOL(compat_mc_getsockopt);
++
++
+ /* Argument list sizes for compat_sys_socketcall */
+ #define AL(x) ((x) * sizeof(u32))
+ static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
diff --git a/net/core/dev.c b/net/core/dev.c
-index 460e7f9..e1df1ab 100644
+index 460e7f9..ed49da5 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)
@@ -843056,6 +1142595,15 @@
if (dev->flags & IFF_UP)
return -EBUSY;
+@@ -1524,7 +1524,7 @@ static int dev_gso_segment(struct sk_buff *skb)
+ if (!segs)
+ return 0;
+
+- if (unlikely(IS_ERR(segs)))
++ if (IS_ERR(segs))
+ return PTR_ERR(segs);
+
+ skb->next = segs;
@@ -2615,7 +2615,7 @@ static int ptype_seq_show(struct seq_file *seq, void *v)
if (v == SEQ_START_TOKEN)
@@ -848959,7 +1148507,7 @@
-}
-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
+index 0d10950..24eca23 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -243,6 +243,23 @@ void build_ehash_secret(void)
@@ -849068,6 +1148616,15 @@
}
if (!err)
sk_setup_caps(sk, &rt->u.dst);
+@@ -1215,7 +1234,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
+ segs = ops->gso_segment(skb, features);
+ rcu_read_unlock();
+
+- if (!segs || unlikely(IS_ERR(segs)))
++ if (!segs || IS_ERR(segs))
+ goto out;
+
+ skb = segs;
@@ -1231,6 +1250,29 @@ out:
return segs;
}
@@ -850157,7 +1149714,7 @@
}
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
-index 40508ba..c67d00e 100644
+index 40508ba..8739735 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -93,6 +93,7 @@
@@ -850412,7 +1149969,7 @@
/*
* Incomplete header ?
-@@ -698,7 +685,7 @@ static void icmp_unreach(struct sk_buff *skb)
+@@ -698,19 +685,20 @@ static void icmp_unreach(struct sk_buff *skb)
break;
case ICMP_FRAG_NEEDED:
if (ipv4_config.no_pmtu_disc) {
@@ -850421,7 +1149978,13 @@
"fragmentation needed "
"and DF set.\n",
NIPQUAD(iph->daddr));
-@@ -710,7 +697,7 @@ static void icmp_unreach(struct sk_buff *skb)
+ } else {
+ info = ip_rt_frag_needed(net, iph,
+- ntohs(icmph->un.frag.mtu));
++ ntohs(icmph->un.frag.mtu),
++ skb->dev);
+ if (!info)
+ goto out;
}
break;
case ICMP_SR_FAILED:
@@ -850430,7 +1149993,7 @@
"Route Failed.\n",
NIPQUAD(iph->daddr));
break;
-@@ -740,12 +727,12 @@ static void icmp_unreach(struct sk_buff *skb)
+@@ -740,12 +728,12 @@ static void icmp_unreach(struct sk_buff *skb)
* get the other vendor to fix their kit.
*/
@@ -850446,7 +1150009,7 @@
NIPQUAD(ip_hdr(skb)->saddr),
icmph->type, icmph->code,
NIPQUAD(iph->daddr),
-@@ -835,7 +822,10 @@ out_err:
+@@ -835,7 +823,10 @@ out_err:
static void icmp_echo(struct sk_buff *skb)
{
@@ -850458,7 +1150021,7 @@
struct icmp_bxm icmp_param;
icmp_param.data.icmph = *icmp_hdr(skb);
-@@ -857,7 +847,7 @@ static void icmp_echo(struct sk_buff *skb)
+@@ -857,7 +848,7 @@ static void icmp_echo(struct sk_buff *skb)
*/
static void icmp_timestamp(struct sk_buff *skb)
{
@@ -850467,7 +1150030,7 @@
struct icmp_bxm icmp_param;
/*
* Too short.
-@@ -868,9 +858,9 @@ static void icmp_timestamp(struct sk_buff *skb)
+@@ -868,9 +859,9 @@ static void icmp_timestamp(struct sk_buff *skb)
/*
* Fill in the current time as ms since midnight UT:
*/
@@ -850480,7 +1150043,7 @@
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)
+@@ -938,7 +929,7 @@ static void icmp_address(struct sk_buff *skb)
static void icmp_address_reply(struct sk_buff *skb)
{
@@ -850489,7 +1150052,7 @@
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)
+@@ -963,8 +954,8 @@ static void icmp_address_reply(struct sk_buff *skb)
break;
}
if (!ifa && net_ratelimit()) {
@@ -850500,7 +1150063,7 @@
NIPQUAD(*mp), dev->name, NIPQUAD(rt->rt_src));
}
}
-@@ -983,7 +973,7 @@ static void icmp_discard(struct sk_buff *skb)
+@@ -983,7 +974,7 @@ static void icmp_discard(struct sk_buff *skb)
int icmp_rcv(struct sk_buff *skb)
{
struct icmphdr *icmph;
@@ -850509,7 +1150072,7 @@
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
int nh;
-@@ -1038,6 +1028,9 @@ int icmp_rcv(struct sk_buff *skb)
+@@ -1038,6 +1029,9 @@ int icmp_rcv(struct sk_buff *skb)
*/
if (rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {
@@ -850519,7 +1150082,7 @@
/*
* 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)
+@@ -1046,7 +1040,7 @@ int icmp_rcv(struct sk_buff *skb)
*/
if ((icmph->type == ICMP_ECHO ||
icmph->type == ICMP_TIMESTAMP) &&
@@ -850528,7 +1150091,7 @@
goto error;
}
if (icmph->type != ICMP_ECHO &&
-@@ -1141,38 +1134,84 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {
+@@ -1141,38 +1135,84 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {
},
};
@@ -852046,7 +1151609,7 @@
}
ip_rt_put(rt);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
-index 341779e..0834926 100644
+index 341779e..e527628 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,
@@ -852094,7 +1151657,35 @@
int err = 0;
dev = rt->u.dst.dev;
-@@ -825,7 +825,7 @@ int ip_append_data(struct sock *sk,
+@@ -753,23 +753,15 @@ static inline int ip_ufo_append_data(struct sock *sk,
+ skb->ip_summed = CHECKSUM_PARTIAL;
+ skb->csum = 0;
+ sk->sk_sndmsg_off = 0;
+- }
+
+- err = skb_append_datato_frags(sk,skb, getfrag, from,
+- (length - transhdrlen));
+- if (!err) {
+- /* specify the length of each IP datagram fragment*/
++ /* specify the length of each IP datagram fragment */
+ skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
+ skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+ __skb_queue_tail(&sk->sk_write_queue, skb);
+-
+- return 0;
+ }
+- /* There is not enough support do UFO ,
+- * so follow normal path
+- */
+- kfree_skb(skb);
+- return err;
++
++ return skb_append_datato_frags(sk, skb, getfrag, from,
++ (length - transhdrlen));
+ }
+
+ /*
+@@ -825,7 +817,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);
@@ -852103,7 +1151694,7 @@
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,
+@@ -834,7 +826,7 @@ int ip_append_data(struct sock *sk,
transhdrlen += exthdrlen;
}
} else {
@@ -852112,7 +1151703,20 @@
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,
+@@ -863,9 +855,9 @@ int ip_append_data(struct sock *sk,
+ csummode = CHECKSUM_PARTIAL;
+
+ inet->cork.length += length;
+- if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) &&
+- (rt->u.dst.dev->features & NETIF_F_UFO)) {
+-
++ if (((length> mtu) || !skb_queue_empty(&sk->sk_write_queue)) &&
++ (sk->sk_protocol == IPPROTO_UDP) &&
++ (rt->u.dst.dev->features & NETIF_F_UFO)) {
+ err = ip_ufo_append_data(sk, getfrag, from, length, hh_len,
+ fragheaderlen, transhdrlen, mtu,
+ flags);
+@@ -1083,7 +1075,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page,
if (skb_queue_empty(&sk->sk_write_queue))
return -EINVAL;
@@ -852121,7 +1151725,7 @@
if (inet->cork.flags & IPCORK_OPT)
opt = inet->cork.opt;
-@@ -1208,10 +1208,8 @@ static void ip_cork_release(struct inet_sock *inet)
+@@ -1208,10 +1200,8 @@ static void ip_cork_release(struct inet_sock *inet)
inet->cork.flags &= ~IPCORK_OPT;
kfree(inet->cork.opt);
inet->cork.opt = NULL;
@@ -852134,7 +1151738,7 @@
}
/*
-@@ -1224,7 +1222,7 @@ int ip_push_pending_frames(struct sock *sk)
+@@ -1224,7 +1214,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;
@@ -852143,7 +1151747,7 @@
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
+@@ -1357,7 +1347,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
} replyopts;
struct ipcm_cookie ipc;
__be32 daddr;
@@ -852152,7 +1151756,7 @@
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
+@@ -1384,7 +1374,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);
@@ -852162,10 +1151766,18 @@
}
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
-index c2921d0..d8adfd4 100644
+index c2921d0..e0514e8 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
-@@ -57,7 +57,7 @@
+@@ -36,6 +36,7 @@
+ #include <linux/mroute.h>
+ #include <net/route.h>
+ #include <net/xfrm.h>
++#include <net/compat.h>
+ #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ #include <net/transp_v6.h>
+ #endif
+@@ -57,7 +58,7 @@
static void ip_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb)
{
struct in_pktinfo info;
@@ -852174,7 +1151786,7 @@
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)
+@@ -163,7 +164,7 @@ void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
ip_cmsg_recv_security(msg, skb);
}
@@ -852183,7 +1151795,7 @@
{
int err;
struct cmsghdr *cmsg;
-@@ -176,7 +176,7 @@ int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc)
+@@ -176,7 +177,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));
@@ -852192,7 +1151804,7 @@
if (err)
return err;
break;
-@@ -449,7 +449,8 @@ static int do_ip_setsockopt(struct sock *sk, int level,
+@@ -449,7 +450,8 @@ static int do_ip_setsockopt(struct sock *sk, int level,
struct ip_options * opt = NULL;
if (optlen > 40 || optlen < 0)
goto e_inval;
@@ -852202,7 +1151814,7 @@
if (err)
break;
if (inet->is_icsk) {
-@@ -589,13 +590,13 @@ static int do_ip_setsockopt(struct sock *sk, int level,
+@@ -589,13 +591,13 @@ static int do_ip_setsockopt(struct sock *sk, int level,
err = 0;
break;
}
@@ -852218,6 +1151830,33 @@
err = -EADDRNOTAVAIL;
+@@ -922,6 +924,10 @@ int compat_ip_setsockopt(struct sock *sk, int level, int optname,
+ if (level != SOL_IP)
+ return -ENOPROTOOPT;
+
++ if (optname >= MCAST_JOIN_GROUP && optname <= MCAST_MSFILTER)
++ return compat_mc_setsockopt(sk, level, optname, optval, optlen,
++ ip_setsockopt);
++
+ err = do_ip_setsockopt(sk, level, optname, optval, optlen);
+ #ifdef CONFIG_NETFILTER
+ /* we need to exclude all possible ENOPROTOOPTs except default case */
+@@ -1180,7 +1186,14 @@ int ip_getsockopt(struct sock *sk, int level,
+ int compat_ip_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
+ {
+- int err = do_ip_getsockopt(sk, level, optname, optval, optlen);
++ int err;
++
++ if (optname == MCAST_MSFILTER)
++ return compat_mc_getsockopt(sk, level, optname, optval, optlen,
++ ip_getsockopt);
++
++ err = do_ip_getsockopt(sk, level, optname, optval, optlen);
++
+ #ifdef CONFIG_NETFILTER
+ /* we need to exclude all possible ENOPROTOOPTs except default case */
+ if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS &&
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 58b60b2..a75807b 100644
--- a/net/ipv4/ipcomp.c
@@ -852240,7 +1151879,7 @@
xfrm_state_put(x);
}
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
-index 4824fe8..0f42d1c 100644
+index 4824fe8..89dee43 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)
@@ -852275,6 +1151914,21 @@
}
return 0;
+@@ -412,12 +412,12 @@ static struct packet_type rarp_packet_type __initdata = {
+ .func = ic_rarp_recv,
+ };
+
+-static inline void ic_rarp_init(void)
++static inline void __init ic_rarp_init(void)
+ {
+ dev_add_pack(&rarp_packet_type);
+ }
+
+-static inline void ic_rarp_cleanup(void)
++static inline void __init ic_rarp_cleanup(void)
+ {
+ dev_remove_pack(&rarp_packet_type);
+ }
@@ -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;
@@ -852296,6 +1151950,24 @@
goto drop;
/* OK, it is all there and looks valid, process... */
+@@ -685,7 +682,7 @@ static void __init ic_bootp_init_ext(u8 *e)
+ /*
+ * Initialize the DHCP/BOOTP mechanism.
+ */
+-static inline void ic_bootp_init(void)
++static inline void __init ic_bootp_init(void)
+ {
+ int i;
+
+@@ -699,7 +696,7 @@ static inline void ic_bootp_init(void)
+ /*
+ * DHCP/BOOTP cleanup.
+ */
+-static inline void ic_bootp_cleanup(void)
++static inline void __init ic_bootp_cleanup(void)
+ {
+ dev_remove_pack(&bootp_packet_type);
+ }
@@ -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;
@@ -852902,8 +1152574,45 @@
read_lock(&mrt_lock);
cache = ipmr_cache_find(rt->rt_src, rt->rt_dst);
+diff --git a/net/ipv4/ipvs/ip_vs_proto.c b/net/ipv4/ipvs/ip_vs_proto.c
+index dde28a2..4b1c16c 100644
+--- a/net/ipv4/ipvs/ip_vs_proto.c
++++ b/net/ipv4/ipvs/ip_vs_proto.c
+@@ -148,7 +148,7 @@ const char * ip_vs_state_name(__u16 proto, int state)
+ struct ip_vs_protocol *pp = ip_vs_proto_get(proto);
+
+ if (pp == NULL || pp->state_name == NULL)
+- return "ERR!";
++ return (IPPROTO_IP == proto) ? "NONE" : "ERR!";
+ return pp->state_name(state);
+ }
+
+diff --git a/net/ipv4/ipvs/ip_vs_proto_ah.c b/net/ipv4/ipvs/ip_vs_proto_ah.c
+index a842676..4bf835e 100644
+--- a/net/ipv4/ipvs/ip_vs_proto_ah.c
++++ b/net/ipv4/ipvs/ip_vs_proto_ah.c
+@@ -160,6 +160,7 @@ static void ah_exit(struct ip_vs_protocol *pp)
+ struct ip_vs_protocol ip_vs_protocol_ah = {
+ .name = "AH",
+ .protocol = IPPROTO_AH,
++ .num_states = 1,
+ .dont_defrag = 1,
+ .init = ah_init,
+ .exit = ah_exit,
+diff --git a/net/ipv4/ipvs/ip_vs_proto_esp.c b/net/ipv4/ipvs/ip_vs_proto_esp.c
+index aef0d3e..db6a6b7 100644
+--- a/net/ipv4/ipvs/ip_vs_proto_esp.c
++++ b/net/ipv4/ipvs/ip_vs_proto_esp.c
+@@ -159,6 +159,7 @@ static void esp_exit(struct ip_vs_protocol *pp)
+ struct ip_vs_protocol ip_vs_protocol_esp = {
+ .name = "ESP",
+ .protocol = IPPROTO_ESP,
++ .num_states = 1,
+ .dont_defrag = 1,
+ .init = esp_init,
+ .exit = esp_exit,
diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c
-index 12dc0d6..620e40f 100644
+index 12dc0d6..b83dc14 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)
@@ -852915,8 +1152624,16 @@
NIPQUAD(cp->caddr), ntohs(cp->cport),
NIPQUAD(cp->vaddr), ntohs(cp->vport),
inc->name, ntohs(inc->port));
+@@ -594,6 +594,7 @@ static void ip_vs_tcp_exit(struct ip_vs_protocol *pp)
+ struct ip_vs_protocol ip_vs_protocol_tcp = {
+ .name = "TCP",
+ .protocol = IPPROTO_TCP,
++ .num_states = IP_VS_TCP_S_LAST,
+ .dont_defrag = 0,
+ .appcnt = ATOMIC_INIT(0),
+ .init = ip_vs_tcp_init,
diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c
-index 1fa7b33..1caa290 100644
+index 1fa7b33..75771cb 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)
@@ -852928,11 +1152645,139 @@
NIPQUAD(cp->caddr), ntohs(cp->cport),
NIPQUAD(cp->vaddr), ntohs(cp->vport),
inc->name, ntohs(inc->port));
+@@ -409,6 +409,7 @@ static void udp_exit(struct ip_vs_protocol *pp)
+ struct ip_vs_protocol ip_vs_protocol_udp = {
+ .name = "UDP",
+ .protocol = IPPROTO_UDP,
++ .num_states = IP_VS_UDP_S_LAST,
+ .dont_defrag = 0,
+ .init = udp_init,
+ .exit = udp_exit,
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
-index 948378d..69c5666 100644
+index 948378d..eff54ef 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)
+@@ -288,11 +288,16 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
+ char *p;
+ int i;
+
++ if (buflen < sizeof(struct ip_vs_sync_mesg)) {
++ IP_VS_ERR_RL("sync message header too short\n");
++ return;
++ }
++
+ /* Convert size back to host byte order */
+ m->size = ntohs(m->size);
+
+ if (buflen != m->size) {
+- IP_VS_ERR("bogus message\n");
++ IP_VS_ERR_RL("bogus sync message size\n");
+ return;
+ }
+
+@@ -307,9 +312,48 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
+ for (i=0; i<m->nr_conns; i++) {
+ unsigned flags, state;
+
+- s = (struct ip_vs_sync_conn *)p;
++ if (p + SIMPLE_CONN_SIZE > buffer+buflen) {
++ IP_VS_ERR_RL("bogus conn in sync message\n");
++ return;
++ }
++ s = (struct ip_vs_sync_conn *) p;
+ flags = ntohs(s->flags) | IP_VS_CONN_F_SYNC;
++ flags &= ~IP_VS_CONN_F_HASHED;
++ if (flags & IP_VS_CONN_F_SEQ_MASK) {
++ opt = (struct ip_vs_sync_conn_options *)&s[1];
++ p += FULL_CONN_SIZE;
++ if (p > buffer+buflen) {
++ IP_VS_ERR_RL("bogus conn options in sync message\n");
++ return;
++ }
++ } else {
++ opt = NULL;
++ p += SIMPLE_CONN_SIZE;
++ }
++
+ state = ntohs(s->state);
++ if (!(flags & IP_VS_CONN_F_TEMPLATE)) {
++ pp = ip_vs_proto_get(s->protocol);
++ if (!pp) {
++ IP_VS_ERR_RL("Unsupported protocol %u in sync msg\n",
++ s->protocol);
++ continue;
++ }
++ if (state >= pp->num_states) {
++ IP_VS_DBG(2, "Invalid %s state %u in sync msg\n",
++ pp->name, state);
++ continue;
++ }
++ } else {
++ /* protocol in templates is not used for state/timeout */
++ pp = NULL;
++ if (state > 0) {
++ IP_VS_DBG(2, "Invalid template state %u in sync msg\n",
++ state);
++ state = 0;
++ }
++ }
++
+ if (!(flags & IP_VS_CONN_F_TEMPLATE))
+ cp = ip_vs_conn_in_get(s->protocol,
+ s->caddr, s->cport,
+@@ -345,14 +389,9 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
+ IP_VS_ERR("ip_vs_conn_new failed\n");
+ return;
+ }
+- cp->state = state;
+ } else if (!cp->dest) {
+ dest = ip_vs_try_bind_dest(cp);
+- if (!dest) {
+- /* it is an unbound entry created by
+- * synchronization */
+- cp->flags = flags | IP_VS_CONN_F_HASHED;
+- } else
++ if (dest)
+ atomic_dec(&dest->refcnt);
+ } else if ((cp->dest) && (cp->protocol == IPPROTO_TCP) &&
+ (cp->state != state)) {
+@@ -371,23 +410,22 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
+ }
+ }
+
+- if (flags & IP_VS_CONN_F_SEQ_MASK) {
+- opt = (struct ip_vs_sync_conn_options *)&s[1];
++ if (opt)
+ memcpy(&cp->in_seq, opt, sizeof(*opt));
+- p += FULL_CONN_SIZE;
+- } else
+- p += SIMPLE_CONN_SIZE;
+-
+ atomic_set(&cp->in_pkts, sysctl_ip_vs_sync_threshold[0]);
+ cp->state = state;
+- pp = ip_vs_proto_get(s->protocol);
+- cp->timeout = pp->timeout_table[cp->state];
++ cp->old_state = cp->state;
++ /*
++ * We can not recover the right timeout for templates
++ * in all cases, we can not find the right fwmark
++ * virtual service. If needed, we can do it for
++ * non-fwmark persistent services.
++ */
++ if (!(flags & IP_VS_CONN_F_TEMPLATE) && pp->timeout_table)
++ cp->timeout = pp->timeout_table[state];
++ else
++ cp->timeout = (3*60*HZ);
+ ip_vs_conn_put(cp);
+-
+- if (p > buffer+buflen) {
+- IP_VS_ERR("bogus message\n");
+- return;
+- }
+ }
+ }
+
+@@ -916,7 +954,7 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
if (!tinfo)
return -ENOMEM;
@@ -852941,7 +1152786,7 @@
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)
+@@ -956,7 +994,7 @@ int stop_sync_thread(int state)
(state == IP_VS_STATE_BACKUP && !sync_backup_pid))
return -ESRCH;
@@ -853465,10 +1153310,22 @@
};
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
-index 4dc1628..719be29 100644
+index 4dc1628..26a37ce 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,
+@@ -296,9 +296,8 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct nf_queue_entry *e)
+ if (v->data_len > 0xFFFF)
+ return -EINVAL;
+ if (diff > skb_tailroom(e->skb)) {
+- nskb = skb_copy_expand(e->skb, 0,
+- diff - skb_tailroom(e->skb),
+- GFP_ATOMIC);
++ nskb = skb_copy_expand(e->skb, skb_headroom(e->skb),
++ diff, GFP_ATOMIC);
+ if (!nskb) {
+ printk(KERN_WARNING "ip_queue: error "
+ "in mangle, dropping packet\n");
+@@ -481,7 +480,7 @@ ipq_rcv_dev_event(struct notifier_block *this,
{
struct net_device *dev = ptr;
@@ -854076,7 +1153933,7 @@
/* '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
+index a65b845..5a955c4 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -23,30 +23,36 @@
@@ -854201,6 +1154058,15 @@
.hook = ipv4_confirm,
.owner = THIS_MODULE,
.pf = PF_INET,
+@@ -305,7 +303,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
+ const struct nf_conntrack_tuple_hash *h;
+ struct nf_conntrack_tuple tuple;
+
+- NF_CT_TUPLE_U_BLANK(&tuple);
++ memset(&tuple, 0, sizeof(tuple));
+ tuple.src.u3.ip = inet->rcv_saddr;
+ tuple.src.u.tcp.port = inet->sport;
+ tuple.dst.u3.ip = inet->daddr;
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
@@ -856679,7 +1156545,7 @@
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
+index 7b5e8e1..5e3685c 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -118,21 +118,19 @@
@@ -857074,16 +1156940,73 @@
{
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)) &&
+@@ -1399,11 +1430,13 @@ static __inline__ unsigned short guess_mtu(unsigned short old_mtu)
+ }
+
+ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
+- unsigned short new_mtu)
++ unsigned short new_mtu,
++ struct net_device *dev)
+ {
+- int i;
++ int i, k;
+ unsigned short old_mtu = ntohs(iph->tot_len);
+ struct rtable *rth;
++ int ikeys[2] = { dev->ifindex, 0 };
+ __be32 skeys[2] = { iph->saddr, 0, };
+ __be32 daddr = iph->daddr;
+ unsigned short est_mtu = 0;
+@@ -1411,22 +1444,26 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
+ if (ipv4_config.no_pmtu_disc)
+ return 0;
+
+- for (i = 0; i < 2; i++) {
+- unsigned hash = rt_hash(daddr, skeys[i], 0);
++ for (k = 0; k < 2; k++) {
++ for (i = 0; i < 2; i++) {
++ unsigned hash = rt_hash(daddr, skeys[i], ikeys[k]);
+
+- 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 == skeys[i] &&
+- rth->rt_dst == daddr &&
+- 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)) {
+- rth->rt_genid == atomic_read(&rt_genid)) {
++ rcu_read_lock();
++ for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
++ rth = rcu_dereference(rth->u.dst.rt_next)) {
unsigned short mtu = new_mtu;
-@@ -1499,9 +1530,9 @@ static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
++ if (rth->fl.fl4_dst != daddr ||
++ rth->fl.fl4_src != skeys[i] ||
++ rth->rt_dst != daddr ||
++ rth->rt_src != iph->saddr ||
++ rth->fl.oif != ikeys[k] ||
++ rth->fl.iif != 0 ||
++ dst_metric_locked(&rth->u.dst, RTAX_MTU) ||
++ !net_eq(dev_net(rth->u.dst.dev), net) ||
++ rth->rt_genid != atomic_read(&rt_genid))
++ continue;
++
+ if (new_mtu < 68 || new_mtu >= old_mtu) {
+
+ /* BSD 4.2 compatibility hack :-( */
+@@ -1452,8 +1489,8 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
+ est_mtu = mtu;
+ }
+ }
++ rcu_read_unlock();
+ }
+- rcu_read_unlock();
+ }
+ return est_mtu ? : new_mtu;
+ }
+@@ -1499,9 +1536,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;
@@ -857095,7 +1157018,7 @@
if (loopback_idev) {
rt->idev = loopback_idev;
in_dev_put(idev);
-@@ -1515,14 +1546,14 @@ static void ipv4_link_failure(struct sk_buff *skb)
+@@ -1515,14 +1552,14 @@ static void ipv4_link_failure(struct sk_buff *skb)
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
@@ -857112,7 +1157035,7 @@
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)
+@@ -1545,7 +1582,7 @@ void ip_rt_get_source(u8 *addr, struct rtable *rt)
if (rt->fl.iif == 0)
src = rt->rt_src;
@@ -857121,7 +1157044,7 @@
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,
+@@ -1675,7 +1712,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);
@@ -857130,7 +1157053,7 @@
e_nobufs:
in_dev_put(in_dev);
-@@ -1700,8 +1731,8 @@ static void ip_handle_martian_source(struct net_device *dev,
+@@ -1700,8 +1737,8 @@ static void ip_handle_martian_source(struct net_device *dev,
* RFC1812 recommendation, if source is martian,
* the only hint is MAC header.
*/
@@ -857141,7 +1157064,7 @@
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,
+@@ -1718,11 +1755,11 @@ static void ip_handle_martian_source(struct net_device *dev,
#endif
}
@@ -857158,7 +1157081,7 @@
{
struct rtable *rth;
-@@ -1814,11 +1845,11 @@ static inline int __mkroute_input(struct sk_buff *skb,
+@@ -1814,11 +1851,11 @@ static inline int __mkroute_input(struct sk_buff *skb,
return err;
}
@@ -857175,7 +1157098,7 @@
{
struct rtable* rth = NULL;
int err;
-@@ -1836,7 +1867,7 @@ static inline int ip_mkroute_input(struct sk_buff *skb,
+@@ -1836,7 +1873,7 @@ static inline int ip_mkroute_input(struct sk_buff *skb,
/* put it into the cache */
hash = rt_hash(daddr, saddr, fl->iif);
@@ -857184,7 +1157107,7 @@
}
/*
-@@ -1869,7 +1900,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+@@ -1869,7 +1906,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;
@@ -857193,7 +1157116,7 @@
/* IP on this device is disabled. */
-@@ -1992,7 +2023,7 @@ local_input:
+@@ -1992,7 +2029,7 @@ local_input:
}
rth->rt_type = res.type;
hash = rt_hash(daddr, saddr, fl.iif);
@@ -857202,7 +1157125,7 @@
goto done;
no_route:
-@@ -2010,8 +2041,8 @@ martian_destination:
+@@ -2010,8 +2047,8 @@ martian_destination:
RT_CACHE_STAT_INC(in_martian_dst);
#ifdef CONFIG_IP_ROUTE_VERBOSE
if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
@@ -857213,7 +1157136,7 @@
NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
#endif
-@@ -2040,25 +2071,25 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+@@ -2040,25 +2077,25 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
int iif = dev->ifindex;
struct net *net;
@@ -857247,7 +1157170,7 @@
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,
+@@ -2100,12 +2137,12 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
return ip_route_input_slow(skb, daddr, saddr, tos, dev);
}
@@ -857266,7 +1157189,7 @@
{
struct rtable *rth;
struct in_device *in_dev;
-@@ -2220,12 +2251,12 @@ static inline int __mkroute_output(struct rtable **result,
+@@ -2220,12 +2257,12 @@ static inline int __mkroute_output(struct rtable **result,
return err;
}
@@ -857285,7 +1157208,7 @@
{
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,
+@@ -2455,7 +2492,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)) &&
@@ -857294,7 +1157217,7 @@
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 = {
+@@ -2487,7 +2524,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
};
@@ -857303,7 +1157226,7 @@
{
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,
+@@ -2547,7 +2584,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)
@@ -857312,7 +1157235,7 @@
return err;
}
-@@ -2565,7 +2596,7 @@ int ip_route_output_key(struct net *net, struct rtable **rp, struct flowi *flp)
+@@ -2565,7 +2602,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)
{
@@ -857321,7 +1157244,7 @@
struct rtmsg *r;
struct nlmsghdr *nlh;
long expires;
-@@ -2658,7 +2689,7 @@ nla_put_failure:
+@@ -2658,7 +2695,7 @@ nla_put_failure:
static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
{
@@ -857330,7 +1157253,7 @@
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
+@@ -2668,9 +2705,6 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
int err;
struct sk_buff *skb;
@@ -857340,7 +1157263,7 @@
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
+@@ -2700,7 +2734,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
if (iif) {
struct net_device *dev;
@@ -857349,7 +1157272,7 @@
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
+@@ -2712,7 +2746,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();
@@ -857358,7 +1157281,7 @@
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
+@@ -2726,22 +2760,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,
};
@@ -857385,7 +1157308,7 @@
errout:
return err;
-@@ -2755,6 +2783,9 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb)
+@@ -2755,6 +2789,9 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb)
struct rtable *rt;
int h, s_h;
int idx, s_idx;
@@ -857395,7 +1157318,7 @@
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)
+@@ -2764,7 +2801,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++) {
@@ -857404,7 +1157327,7 @@
continue;
if (rt->rt_genid != atomic_read(&rt_genid))
continue;
-@@ -3028,7 +3059,9 @@ int __init ip_rt_init(void)
+@@ -3028,7 +3065,9 @@ int __init ip_rt_init(void)
devinet_init();
ip_fib_init();
@@ -857415,7 +1157338,7 @@
/* All the timers, started at system startup tend
to synchronize. Perturb it a bit.
-@@ -3040,7 +3073,7 @@ int __init ip_rt_init(void)
+@@ -3040,7 +3079,7 @@ int __init ip_rt_init(void)
ip_rt_secret_interval;
add_timer(&rt_secret_timer);
@@ -857855,6 +1157778,30 @@
break;
case TCP_WINDOW_CLAMP:
val = tp->window_clamp;
+diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
+index 3a6be23..6a25082 100644
+--- a/net/ipv4/tcp_cong.c
++++ b/net/ipv4/tcp_cong.c
+@@ -285,14 +285,12 @@ int tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight)
+ if (in_flight >= tp->snd_cwnd)
+ return 1;
+
+- if (!sk_can_gso(sk))
+- return 0;
+-
+ left = tp->snd_cwnd - in_flight;
+- if (sysctl_tcp_tso_win_divisor)
+- return left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd;
+- else
+- return left <= tcp_max_burst(tp);
++ if (sk_can_gso(sk) &&
++ left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd &&
++ left * tp->mss_cache < sk->sk_gso_max_size)
++ return 1;
++ return left <= tcp_max_burst(tp);
+ }
+ EXPORT_SYMBOL_GPL(tcp_is_cwnd_limited);
+
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
index 3aa0b23..eb5b985 100644
--- a/net/ipv4/tcp_cubic.c
@@ -857940,7 +1157887,7 @@
-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
+index bbb7d88..0298f80 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)
@@ -858052,17 +1157999,16 @@
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:
+@@ -4868,6 +4924,8 @@ step5:
tcp_data_snd_check(sk);
tcp_ack_snd_check(sk);
+
-+ if (tcp_defer_accept_check(sk))
-+ return -1;
++ tcp_defer_accept_check(sk);
return 0;
csum_error:
-@@ -5387,6 +5446,7 @@ discard:
+@@ -5387,6 +5445,7 @@ discard:
EXPORT_SYMBOL(sysctl_tcp_ecn);
EXPORT_SYMBOL(sysctl_tcp_reordering);
@@ -858828,6 +1158774,67 @@
if (!sock_flag(sk, SOCK_KEEPOPEN) || sk->sk_state == TCP_CLOSE)
goto out;
+diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c
+index be24d6e..0e1a8c9 100644
+--- a/net/ipv4/tcp_vegas.c
++++ b/net/ipv4/tcp_vegas.c
+@@ -229,7 +229,8 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
+ */
+ tcp_reno_cong_avoid(sk, ack, in_flight);
+ } else {
+- u32 rtt, target_cwnd, diff;
++ u32 rtt, diff;
++ u64 target_cwnd;
+
+ /* We have enough RTT samples, so, using the Vegas
+ * algorithm, we determine if we should increase or
+@@ -252,8 +253,9 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
+ * We keep it as a fixed point number with
+ * V_PARAM_SHIFT bits to the right of the binary point.
+ */
+- target_cwnd = ((old_wnd * vegas->baseRTT)
+- << V_PARAM_SHIFT) / rtt;
++ target_cwnd = ((u64)old_wnd * vegas->baseRTT);
++ target_cwnd <<= V_PARAM_SHIFT;
++ do_div(target_cwnd, rtt);
+
+ /* Calculate the difference between the window we had,
+ * and the window we would like to have. This quantity
+@@ -279,7 +281,7 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
+ * utilization.
+ */
+ tp->snd_cwnd = min(tp->snd_cwnd,
+- (target_cwnd >>
++ ((u32)target_cwnd >>
+ V_PARAM_SHIFT)+1);
+
+ } else if (tp->snd_cwnd <= tp->snd_ssthresh) {
+diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c
+index d16689e..2bf618a 100644
+--- a/net/ipv4/tcp_veno.c
++++ b/net/ipv4/tcp_veno.c
+@@ -133,7 +133,8 @@ static void tcp_veno_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
+ */
+ tcp_reno_cong_avoid(sk, ack, in_flight);
+ } else {
+- u32 rtt, target_cwnd;
++ u64 target_cwnd;
++ u32 rtt;
+
+ /* We have enough rtt samples, so, using the Veno
+ * algorithm, we determine the state of the network.
+@@ -141,8 +142,9 @@ static void tcp_veno_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
+
+ rtt = veno->minrtt;
+
+- target_cwnd = ((tp->snd_cwnd * veno->basertt)
+- << V_PARAM_SHIFT) / rtt;
++ target_cwnd = (tp->snd_cwnd * veno->basertt);
++ target_cwnd <<= V_PARAM_SHIFT;
++ do_div(target_cwnd, rtt);
+
+ veno->diff = (tp->snd_cwnd << V_PARAM_SHIFT) - target_cwnd;
+
diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c
index 978b3fd..d3b709a 100644
--- a/net/ipv4/tunnel4.c
@@ -859376,7 +1159383,7 @@
do {
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
-index 47263e4..b2c9bec 100644
+index 47263e4..42814a2 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -3,7 +3,7 @@
@@ -859474,7 +1159481,7 @@
default IPV6
select XFRM
---help---
-@@ -159,29 +153,31 @@ config INET6_XFRM_MODE_BEET
+@@ -159,15 +153,15 @@ config INET6_XFRM_MODE_BEET
config INET6_XFRM_MODE_ROUTEOPTIMIZATION
tristate "IPv6: MIPv6 route optimization mode (EXPERIMENTAL)"
@@ -859492,11 +1159499,7 @@
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.
+@@ -178,10 +172,12 @@ config IPV6_SIT
Saying M here will produce a module called sit.ko. If unsure, say Y.
@@ -864001,7 +1164004,7 @@
module_init(ip6_tunnel_init);
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
new file mode 100644
-index 0000000..c8c6e33
+index 0000000..2de3c46
--- /dev/null
+++ b/net/ipv6/ip6mr.c
@@ -0,0 +1,1643 @@
@@ -864365,7 +1164368,7 @@
+ 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))))
++ csum_fold(skb_checksum(skb, 0, skb->len, 0))))
+ goto drop;
+
+ /* check if the inner packet is destined to mcast group */
@@ -865661,7 +1165664,7 @@
#include <linux/err.h>
#include <linux/pfkeyv2.h>
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
-index bf2a686..06de9d0 100644
+index bf2a686..56d55fe 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -16,7 +16,6 @@
@@ -865680,7 +1165683,13 @@
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/init.h>
-@@ -57,118 +57,6 @@
+@@ -52,123 +52,12 @@
+ #include <net/udp.h>
+ #include <net/udplite.h>
+ #include <net/xfrm.h>
++#include <net/compat.h>
+
+ #include <asm/uaccess.h>
DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics) __read_mostly;
@@ -865799,7 +1165808,7 @@
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 *))
+@@ -215,25 +104,59 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *))
return 0;
}
@@ -865861,7 +1165870,7 @@
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,
+@@ -266,10 +189,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);
@@ -865874,7 +1165883,7 @@
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,
+@@ -282,8 +204,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();
@@ -865885,7 +1165894,7 @@
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,
+@@ -309,63 +231,86 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
goto e_inval;
case IPV6_V6ONLY:
@@ -865973,7 +1165982,7 @@
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,
+@@ -373,11 +318,15 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
break;
case IPV6_RECVTCLASS:
@@ -865989,7 +1165998,7 @@
np->rxopt.bits.rxflow = valbool;
retv = 0;
break;
-@@ -396,9 +344,9 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
+@@ -396,9 +345,9 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW))
break;
@@ -866002,7 +1166011,7 @@
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,
+@@ -426,25 +375,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
}
retv = 0;
@@ -866029,7 +1166038,7 @@
sticky_done:
if (opt)
sock_kfree_s(sk, opt, opt->tot_len);
-@@ -490,32 +420,15 @@ sticky_done:
+@@ -490,32 +421,15 @@ sticky_done:
goto done;
update:
retv = 0;
@@ -866065,7 +1166074,7 @@
if (val > 255 || val < -1)
goto e_inval;
np->hop_limit = val;
-@@ -525,6 +438,8 @@ done:
+@@ -525,6 +439,8 @@ done:
case IPV6_MULTICAST_HOPS:
if (sk->sk_type == SOCK_STREAM)
goto e_inval;
@@ -866074,7 +1166083,7 @@
if (val > 255 || val < -1)
goto e_inval;
np->mcast_hops = val;
-@@ -532,6 +447,8 @@ done:
+@@ -532,6 +448,8 @@ done:
break;
case IPV6_MULTICAST_LOOP:
@@ -866083,7 +1166092,7 @@
np->mc_loop = valbool;
retv = 0;
break;
-@@ -539,12 +456,14 @@ done:
+@@ -539,12 +457,14 @@ done:
case IPV6_MULTICAST_IF:
if (sk->sk_type == SOCK_STREAM)
goto e_inval;
@@ -866099,7 +1166108,7 @@
retv = -ENODEV;
break;
}
-@@ -557,6 +476,9 @@ done:
+@@ -557,6 +477,9 @@ done:
{
struct ipv6_mreq mreq;
@@ -866109,7 +1166118,7 @@
retv = -EPROTO;
if (inet_sk(sk)->is_icsk)
break;
-@@ -576,7 +498,7 @@ done:
+@@ -576,7 +499,7 @@ done:
{
struct ipv6_mreq mreq;
@@ -866118,7 +1166127,7 @@
goto e_inval;
retv = -EFAULT;
-@@ -595,6 +517,9 @@ done:
+@@ -595,6 +518,9 @@ done:
struct group_req greq;
struct sockaddr_in6 *psin6;
@@ -866128,7 +1166137,7 @@
retv = -EFAULT;
if (copy_from_user(&greq, optval, sizeof(struct group_req)))
break;
-@@ -619,7 +544,7 @@ done:
+@@ -619,7 +545,7 @@ done:
struct group_source_req greqs;
int omode, add;
@@ -866137,7 +1166146,7 @@
goto e_inval;
if (copy_from_user(&greqs, optval, sizeof(greqs))) {
retv = -EFAULT;
-@@ -693,27 +618,37 @@ done:
+@@ -693,27 +619,37 @@ done:
break;
}
case IPV6_ROUTER_ALERT:
@@ -866175,7 +1166184,7 @@
np->sndflow = valbool;
retv = 0;
break;
-@@ -728,7 +663,70 @@ done:
+@@ -728,7 +664,70 @@ done:
retv = xfrm_user_policy(sk, optname, optval, optlen);
break;
@@ -866246,7 +1166255,18 @@
release_sock(sk);
return retv;
-@@ -839,6 +837,9 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
+@@ -781,6 +780,10 @@ int compat_ipv6_setsockopt(struct sock *sk, int level, int optname,
+ if (level != SOL_IPV6)
+ return -ENOPROTOOPT;
+
++ if (optname >= MCAST_JOIN_GROUP && optname <= MCAST_MSFILTER)
++ return compat_mc_setsockopt(sk, level, optname, optval, optlen,
++ ipv6_setsockopt);
++
+ err = do_ipv6_setsockopt(sk, level, optname, optval, optlen);
+ #ifdef CONFIG_NETFILTER
+ /* we need to exclude all possible ENOPROTOOPTs except default case */
+@@ -839,6 +842,9 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
int len;
int val;
@@ -866256,7 +1166276,7 @@
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,
+@@ -1015,9 +1021,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
dst = sk_dst_get(sk);
if (dst) {
if (val < 0)
@@ -866267,7 +1166287,7 @@
dst_release(dst);
}
if (val < 0)
-@@ -1045,6 +1044,24 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
+@@ -1045,6 +1049,24 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
val = np->sndflow;
break;
@@ -866292,7 +1166312,18 @@
default:
return -ENOPROTOOPT;
}
-@@ -1128,13 +1145,3 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
+@@ -1105,6 +1127,10 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
+ if (level != SOL_IPV6)
+ return -ENOPROTOOPT;
+
++ if (optname == MCAST_MSFILTER)
++ return compat_mc_getsockopt(sk, level, optname, optval, optlen,
++ ipv6_getsockopt);
++
+ err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
+ #ifdef CONFIG_NETFILTER
+ /* we need to exclude all possible ENOPROTOOPTs except default case */
+@@ -1128,13 +1154,3 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
EXPORT_SYMBOL(compat_ipv6_getsockopt);
#endif
@@ -867671,10 +1167702,22 @@
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
+index 8d366f7..2eff3ae 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,
+@@ -298,9 +298,8 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct nf_queue_entry *e)
+ if (v->data_len > 0xFFFF)
+ return -EINVAL;
+ if (diff > skb_tailroom(e->skb)) {
+- nskb = skb_copy_expand(e->skb, 0,
+- diff - skb_tailroom(e->skb),
+- GFP_ATOMIC);
++ nskb = skb_copy_expand(e->skb, skb_headroom(e->skb),
++ diff, GFP_ATOMIC);
+ if (!nskb) {
+ printk(KERN_WARNING "ip6_queue: OOM "
+ "in mangle, dropping packet\n");
+@@ -484,7 +483,7 @@ ipq_rcv_dev_event(struct notifier_block *this,
{
struct net_device *dev = ptr;
@@ -873715,7 +1173758,7 @@
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
+index be627e1..76c3057 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)
@@ -873909,7 +1173952,20 @@
return;
}
-@@ -608,7 +608,7 @@ static void ircomm_tty_do_softint(struct work_struct *work)
+@@ -555,10 +555,8 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
+
+ ircomm_tty_shutdown(self);
+
+- if (tty->driver->flush_buffer)
+- tty->driver->flush_buffer(tty);
+- if (tty->ldisc.flush_buffer)
+- tty->ldisc.flush_buffer(tty);
++ tty_driver_flush_buffer(tty);
++ tty_ldisc_flush(tty);
+
+ tty->closing = 0;
+ self->tty = NULL;
+@@ -608,7 +606,7 @@ static void ircomm_tty_do_softint(struct work_struct *work)
unsigned long flags;
struct sk_buff *skb, *ctrl_skb;
@@ -873918,7 +1173974,7 @@
if (!self || self->magic != IRCOMM_TTY_MAGIC)
return;
-@@ -678,7 +678,7 @@ static int ircomm_tty_write(struct tty_struct *tty,
+@@ -678,7 +676,7 @@ static int ircomm_tty_write(struct tty_struct *tty,
int len = 0;
int size;
@@ -873927,7 +1173983,7 @@
tty->hw_stopped);
IRDA_ASSERT(self != NULL, return -1;);
-@@ -701,7 +701,7 @@ static int ircomm_tty_write(struct tty_struct *tty,
+@@ -701,7 +699,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) {
@@ -873936,7 +1173992,7 @@
#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)
+@@ -830,7 +828,7 @@ static int ircomm_tty_write_room(struct tty_struct *tty)
ret = self->max_data_size;
spin_unlock_irqrestore(&self->spinlock, flags);
}
@@ -873945,7 +1174001,7 @@
return ret;
}
-@@ -847,7 +847,7 @@ static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
+@@ -847,7 +845,7 @@ static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
unsigned long orig_jiffies, poll_time;
unsigned long flags;
@@ -873954,7 +1174010,7 @@
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)
+@@ -882,7 +880,7 @@ static void ircomm_tty_throttle(struct tty_struct *tty)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
@@ -873963,7 +1174019,7 @@
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)
+@@ -913,7 +911,7 @@ static void ircomm_tty_unthrottle(struct tty_struct *tty)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
@@ -873972,7 +1174028,7 @@
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)
+@@ -928,7 +926,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);
@@ -873981,7 +1174037,7 @@
}
ircomm_flow_request(self->ircomm, FLOW_START);
}
-@@ -965,7 +965,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)
+@@ -965,7 +963,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
@@ -873990,7 +1174046,7 @@
if (!test_and_clear_bit(ASYNC_B_INITIALIZED, &self->flags))
return;
-@@ -1008,7 +1008,7 @@ static void ircomm_tty_hangup(struct tty_struct *tty)
+@@ -1008,7 +1006,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;
@@ -873999,7 +1174055,7 @@
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)
+@@ -1037,7 +1035,7 @@ static void ircomm_tty_hangup(struct tty_struct *tty)
*/
static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch)
{
@@ -874008,7 +1174064,7 @@
}
/*
-@@ -1081,7 +1081,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
+@@ -1081,7 +1079,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
struct tty_struct *tty;
int status;
@@ -874017,7 +1174073,7 @@
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)
+@@ -1095,14 +1093,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,
@@ -874034,7 +1174090,7 @@
if (tty)
tty_hangup(tty);
-@@ -1114,7 +1114,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
+@@ -1114,7 +1112,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
if (tty->hw_stopped) {
if (status & IRCOMM_CTS) {
IRDA_DEBUG(2,
@@ -874043,7 +1174099,7 @@
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)
+@@ -1126,7 +1124,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
} else {
if (!(status & IRCOMM_CTS)) {
IRDA_DEBUG(2,
@@ -874052,7 +1174108,7 @@
tty->hw_stopped = 1;
}
}
-@@ -1144,14 +1144,14 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
+@@ -1144,14 +1142,14 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
@@ -874069,7 +1174125,7 @@
return 0;
}
-@@ -1162,7 +1162,7 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
+@@ -1162,7 +1160,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)) {
@@ -874078,7 +1174134,7 @@
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,
+@@ -1194,7 +1192,7 @@ static int ircomm_tty_control_indication(void *instance, void *sap,
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
int clen;
@@ -874087,7 +1174143,7 @@
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,
+@@ -1230,7 +1228,7 @@ static void ircomm_tty_flow_indication(void *instance, void *sap,
switch (cmd) {
case FLOW_START:
@@ -874096,7 +1174152,7 @@
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,
+@@ -1238,7 +1236,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:
@@ -878664,6 +1178720,157 @@
/* Exit a function with debug */
#define DRETURN(ret, dbg, args...) \
+diff --git a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c
+index a4f1439..75497e5 100644
+--- a/net/irda/irnet/irnet_irda.c
++++ b/net/irda/irnet/irnet_irda.c
+@@ -9,6 +9,7 @@
+ */
+
+ #include "irnet_irda.h" /* Private header */
++#include <linux/seq_file.h>
+
+ /*
+ * PPP disconnect work: we need to make sure we're in
+@@ -1717,34 +1718,23 @@ irnet_expiry_indication(discinfo_t * expiry,
+ */
+
+ #ifdef CONFIG_PROC_FS
+-/*------------------------------------------------------------------*/
+-/*
+- * Function irnet_proc_read (buf, start, offset, len, unused)
+- *
+- * Give some info to the /proc file system
+- */
+ static int
+-irnet_proc_read(char * buf,
+- char ** start,
+- off_t offset,
+- int len)
++irnet_proc_show(struct seq_file *m, void *v)
+ {
+ irnet_socket * self;
+ char * state;
+ int i = 0;
+
+- len = 0;
+-
+ /* Get the IrNET server information... */
+- len += sprintf(buf+len, "IrNET server - ");
+- len += sprintf(buf+len, "IrDA state: %s, ",
++ seq_printf(m, "IrNET server - ");
++ seq_printf(m, "IrDA state: %s, ",
+ (irnet_server.running ? "running" : "dead"));
+- len += sprintf(buf+len, "stsap_sel: %02x, ", irnet_server.s.stsap_sel);
+- len += sprintf(buf+len, "dtsap_sel: %02x\n", irnet_server.s.dtsap_sel);
++ seq_printf(m, "stsap_sel: %02x, ", irnet_server.s.stsap_sel);
++ seq_printf(m, "dtsap_sel: %02x\n", irnet_server.s.dtsap_sel);
+
+ /* Do we need to continue ? */
+ if(!irnet_server.running)
+- return len;
++ return 0;
+
+ /* Protect access to the instance list */
+ spin_lock_bh(&irnet_server.spinlock);
+@@ -1754,23 +1744,23 @@ irnet_proc_read(char * buf,
+ while(self != NULL)
+ {
+ /* Start printing info about the socket. */
+- len += sprintf(buf+len, "\nIrNET socket %d - ", i++);
++ seq_printf(m, "\nIrNET socket %d - ", i++);
+
+ /* First, get the requested configuration */
+- len += sprintf(buf+len, "Requested IrDA name: \"%s\", ", self->rname);
+- len += sprintf(buf+len, "daddr: %08x, ", self->rdaddr);
+- len += sprintf(buf+len, "saddr: %08x\n", self->rsaddr);
++ seq_printf(m, "Requested IrDA name: \"%s\", ", self->rname);
++ seq_printf(m, "daddr: %08x, ", self->rdaddr);
++ seq_printf(m, "saddr: %08x\n", self->rsaddr);
+
+ /* Second, get all the PPP info */
+- len += sprintf(buf+len, " PPP state: %s",
++ seq_printf(m, " PPP state: %s",
+ (self->ppp_open ? "registered" : "unregistered"));
+ if(self->ppp_open)
+ {
+- len += sprintf(buf+len, ", unit: ppp%d",
++ seq_printf(m, ", unit: ppp%d",
+ ppp_unit_number(&self->chan));
+- len += sprintf(buf+len, ", channel: %d",
++ seq_printf(m, ", channel: %d",
+ ppp_channel_index(&self->chan));
+- len += sprintf(buf+len, ", mru: %d",
++ seq_printf(m, ", mru: %d",
+ self->mru);
+ /* Maybe add self->flags ? Later... */
+ }
+@@ -1789,10 +1779,10 @@ irnet_proc_read(char * buf,
+ state = "weird";
+ else
+ state = "idle";
+- len += sprintf(buf+len, "\n IrDA state: %s, ", state);
+- len += sprintf(buf+len, "daddr: %08x, ", self->daddr);
+- len += sprintf(buf+len, "stsap_sel: %02x, ", self->stsap_sel);
+- len += sprintf(buf+len, "dtsap_sel: %02x\n", self->dtsap_sel);
++ seq_printf(m, "\n IrDA state: %s, ", state);
++ seq_printf(m, "daddr: %08x, ", self->daddr);
++ seq_printf(m, "stsap_sel: %02x, ", self->stsap_sel);
++ seq_printf(m, "dtsap_sel: %02x\n", self->dtsap_sel);
+
+ /* Next socket, please... */
+ self = (irnet_socket *) hashbin_get_next(irnet_server.list);
+@@ -1801,8 +1791,21 @@ irnet_proc_read(char * buf,
+ /* Spin lock end */
+ spin_unlock_bh(&irnet_server.spinlock);
+
+- return len;
++ return 0;
+ }
++
++static int irnet_proc_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, irnet_proc_show, NULL);
++}
++
++static const struct file_operations irnet_proc_fops = {
++ .owner = THIS_MODULE,
++ .open = irnet_proc_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
+ #endif /* PROC_FS */
+
+
+@@ -1841,7 +1844,7 @@ irda_irnet_init(void)
+
+ #ifdef CONFIG_PROC_FS
+ /* Add a /proc file for irnet infos */
+- create_proc_info_entry("irnet", 0, proc_irda, irnet_proc_read);
++ proc_create("irnet", 0, proc_irda, &irnet_proc_fops);
+ #endif /* CONFIG_PROC_FS */
+
+ /* Setup the IrNET server */
+diff --git a/net/irda/irnet/irnet_irda.h b/net/irda/irnet/irnet_irda.h
+index 0ba92d0..3e40895 100644
+--- a/net/irda/irnet/irnet_irda.h
++++ b/net/irda/irnet/irnet_irda.h
+@@ -159,14 +159,6 @@ static void
+ DISCOVERY_MODE,
+ void *);
+ #endif
+-/* -------------------------- PROC ENTRY -------------------------- */
+-#ifdef CONFIG_PROC_FS
+-static int
+- irnet_proc_read(char *,
+- char **,
+- off_t,
+- int);
+-#endif /* CONFIG_PROC_FS */
+
+ /**************************** VARIABLES ****************************/
+
diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c
index cd9ff17..9e1fb82 100644
--- a/net/irda/irnetlink.c
@@ -879613,7 +1179820,7 @@
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
+index e9ef9af..9e7236f 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -48,6 +48,17 @@ struct pfkey_sock {
@@ -879662,7 +1179869,35 @@
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
+@@ -1466,7 +1498,8 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
+ err = xfrm_state_update(x);
+
+ xfrm_audit_state_add(x, err ? 0 : 1,
+- audit_get_loginuid(current), 0);
++ audit_get_loginuid(current),
++ audit_get_sessionid(current), 0);
+
+ if (err < 0) {
+ x->km.state = XFRM_STATE_DEAD;
+@@ -1520,7 +1553,8 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
+ km_state_notify(x, &c);
+ out:
+ xfrm_audit_state_delete(x, err ? 0 : 1,
+- audit_get_loginuid(current), 0);
++ audit_get_loginuid(current),
++ audit_get_sessionid(current), 0);
+ xfrm_state_put(x);
+
+ return err;
+@@ -1696,6 +1730,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
+ return -EINVAL;
+
+ audit_info.loginuid = audit_get_loginuid(current);
++ audit_info.sessionid = audit_get_sessionid(current);
+ audit_info.secid = 0;
+ err = xfrm_state_flush(proto, &audit_info);
+ if (err)
+@@ -1709,45 +1744,60 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
return 0;
}
@@ -879736,7 +1179971,7 @@
}
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)
+@@ -1780,7 +1830,9 @@ static int check_reqid(struct xfrm_policy *xp, int dir, int count, void *ptr)
static u32 gen_reqid(void)
{
@@ -879746,7 +1179981,7 @@
static u32 reqid = IPSEC_MANUAL_REQID_MAX;
start = reqid;
-@@ -1788,8 +1837,10 @@ static u32 gen_reqid(void)
+@@ -1788,8 +1840,10 @@ static u32 gen_reqid(void)
++reqid;
if (reqid == 0)
reqid = IPSEC_MANUAL_REQID_MAX+1;
@@ -879759,7 +1179994,7 @@
return reqid;
} while (reqid != start);
return 0;
-@@ -1856,7 +1907,7 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
+@@ -1856,7 +1910,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 */
@@ -879768,7 +1180003,7 @@
xp->xfrm_nr++;
return 0;
}
-@@ -2241,7 +2292,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
+@@ -2241,7 +2295,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
goto out;
}
@@ -879777,7 +1180012,17 @@
kfree(uctx);
if (err)
-@@ -2301,10 +2352,11 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
+@@ -2273,7 +2327,8 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
+ hdr->sadb_msg_type != SADB_X_SPDUPDATE);
+
+ xfrm_audit_policy_add(xp, err ? 0 : 1,
+- audit_get_loginuid(current), 0);
++ audit_get_loginuid(current),
++ audit_get_sessionid(current), 0);
+
+ if (err)
+ goto out;
+@@ -2301,10 +2356,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;
@@ -879790,7 +1180035,7 @@
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
+@@ -2334,30 +2390,28 @@ 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];
@@ -879821,7 +1180066,24 @@
if (xp == NULL)
return -ENOENT;
-@@ -2638,11 +2687,14 @@ out:
+ xfrm_audit_policy_delete(xp, err ? 0 : 1,
+- audit_get_loginuid(current), 0);
++ audit_get_loginuid(current),
++ audit_get_sessionid(current), 0);
+
+ if (err)
+ goto out;
+@@ -2618,7 +2672,8 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
+
+ if (delete) {
+ xfrm_audit_policy_delete(xp, err ? 0 : 1,
+- audit_get_loginuid(current), 0);
++ audit_get_loginuid(current),
++ audit_get_sessionid(current), 0);
+
+ if (err)
+ goto out;
+@@ -2638,11 +2693,14 @@ out:
static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
{
@@ -879837,7 +1180099,7 @@
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)
+@@ -2652,21 +2710,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;
@@ -879883,7 +1180145,15 @@
}
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,
+@@ -2696,6 +2773,7 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg
+ int err;
+
+ audit_info.loginuid = audit_get_loginuid(current);
++ audit_info.sessionid = audit_get_sessionid(current);
+ audit_info.secid = 0;
+ err = xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info);
+ if (err)
+@@ -3225,7 +3303,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);
@@ -879892,7 +1180162,7 @@
kfree(uctx);
if (*dir)
-@@ -3671,6 +3742,7 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
+@@ -3671,6 +3749,7 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
int flags)
{
struct sock *sk = sock->sk;
@@ -879900,7 +1180170,7 @@
struct sk_buff *skb;
int copied, err;
-@@ -3698,6 +3770,10 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
+@@ -3698,6 +3777,10 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
err = (flags & MSG_TRUNC) ? skb->len : copied;
@@ -880186,7 +1180456,7 @@
goto drop;
}
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
-index 45c7c0c..520a518 100644
+index 45c7c0c..a24b459 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -32,15 +32,6 @@ config MAC80211_RC_DEFAULT_PID
@@ -880213,7 +1180483,7 @@
default ""
config MAC80211_RC_PID
-@@ -70,16 +60,16 @@ config MAC80211_RC_PID
+@@ -70,20 +60,22 @@ config MAC80211_RC_PID
Say Y or M unless you're sure you want to use a
different rate control algorithm.
@@ -880238,7 +1180508,14 @@
config MAC80211_LEDS
bool "Enable LED triggers"
-@@ -166,3 +156,10 @@ config MAC80211_VERBOSE_PS_DEBUG
+- depends on MAC80211 && LEDS_TRIGGERS
++ depends on MAC80211
++ select NEW_LEDS
++ select LEDS_TRIGGERS
+ ---help---
+ This option enables a few LED triggers for different
+ packet receive/transmit events.
+@@ -166,3 +158,10 @@ config MAC80211_VERBOSE_PS_DEBUG
---help---
Say Y here to print out verbose powersave
mode debug messages.
@@ -893652,10 +1193929,10 @@
+}
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
new file mode 100644
-index 0000000..742003d
+index 0000000..9ee3aff
--- /dev/null
+++ b/net/mac80211/mesh.h
-@@ -0,0 +1,290 @@
+@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2008 open80211s Ltd.
+ * Authors: Luis Carlos Cobo <luisca at cozybit.com>
@@ -893671,6 +1193948,7 @@
+
+#include <linux/types.h>
+#include <linux/jhash.h>
++#include <asm/unaligned.h>
+#include "ieee80211_i.h"
+
+
@@ -893948,10 +1194226,10 @@
+#endif /* IEEE80211S_H */
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
new file mode 100644
-index 0000000..02de8f1
+index 0000000..3df8092
--- /dev/null
+++ b/net/mac80211/mesh_hwmp.c
-@@ -0,0 +1,855 @@
+@@ -0,0 +1,854 @@
+/*
+ * Copyright (c) 2008 open80211s Ltd.
+ * Author: Luis Carlos Cobo <luisca at cozybit.com>
@@ -893961,7 +1194239,6 @@
+ * published by the Free Software Foundation.
+ */
+
-+#include <asm/unaligned.h>
+#include "mesh.h"
+
+#define TEST_FRAME_LEN 8192
@@ -908676,7 +1208953,7 @@
};
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
-index b77eb56..4eac65c 100644
+index b77eb56..c4b1799 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)
@@ -908688,7 +1208965,12 @@
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,
+@@ -104,11 +104,11 @@ nf_ct_get_tuple(const struct sk_buff *skb,
+ const struct nf_conntrack_l3proto *l3proto,
+ const struct nf_conntrack_l4proto *l4proto)
+ {
+- NF_CT_TUPLE_U_BLANK(tuple);
++ memset(tuple, 0, sizeof(*tuple));
tuple->src.l3num = l3num;
if (l3proto->pkt_to_tuple(skb, nhoff, tuple) == 0)
@@ -908719,7 +1209001,7 @@
}
l4proto = __nf_ct_l4proto_find(l3num, protonum);
-@@ -147,7 +145,7 @@ int nf_ct_get_tuplepr(const struct sk_buff *skb,
+@@ -147,17 +145,17 @@ int nf_ct_get_tuplepr(const struct sk_buff *skb,
}
EXPORT_SYMBOL_GPL(nf_ct_get_tuplepr);
@@ -908728,7 +1209010,10 @@
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,
+ const struct nf_conntrack_l4proto *l4proto)
+ {
+- NF_CT_TUPLE_U_BLANK(inverse);
++ memset(inverse, 0, sizeof(*inverse));
inverse->src.l3num = orig->src.l3num;
if (l3proto->invert_tuple(inverse, orig) == 0)
@@ -913019,6 +1213304,19 @@
tftp[i][j].me = THIS_MODULE;
tftp[i][j].help = tftp_help;
+diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
+index bbd2689..582ec3e 100644
+--- a/net/netfilter/nf_queue.c
++++ b/net/netfilter/nf_queue.c
+@@ -214,7 +214,7 @@ int nf_queue(struct sk_buff *skb,
+
+ segs = skb_gso_segment(skb, 0);
+ kfree_skb(skb);
+- if (unlikely(IS_ERR(segs)))
++ if (IS_ERR(segs))
+ return 1;
+
+ do {
diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c
index 3dd4b3c..69d699f 100644
--- a/net/netfilter/nf_sockopt.c
@@ -913033,10 +1213331,22 @@
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
+index 10522c0..3447025 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,
+@@ -454,9 +454,8 @@ nfqnl_mangle(void *data, int data_len, struct nf_queue_entry *e)
+ if (data_len > 0xFFFF)
+ return -EINVAL;
+ if (diff > skb_tailroom(e->skb)) {
+- nskb = skb_copy_expand(e->skb, 0,
+- diff - skb_tailroom(e->skb),
+- GFP_ATOMIC);
++ nskb = skb_copy_expand(e->skb, skb_headroom(e->skb),
++ diff, GFP_ATOMIC);
+ if (!nskb) {
+ printk(KERN_WARNING "nf_queue: OOM "
+ "in mangle, dropping packet\n");
+@@ -557,7 +556,7 @@ nfqnl_rcv_dev_event(struct notifier_block *this,
{
struct net_device *dev = ptr;
@@ -913046,7 +1213356,7 @@
/* 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
+index a679208..11b22ab 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -58,7 +58,7 @@ static struct xt_af *xt;
@@ -913148,6 +1213458,15 @@
int af = priv->af;
return seq_list_next(v, &net->xt.tables[af], pos);
+@@ -787,7 +787,7 @@ static const struct file_operations xt_table_ops = {
+ .open = xt_table_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = seq_release,
++ .release = seq_release_net,
+ };
+
+ static void *xt_match_seq_start(struct seq_file *seq, loff_t *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
@@ -913174,6 +1213493,19 @@
struct xt_rateest *est;
struct {
struct nlattr opt;
+diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c
+index 3b2aa56..9685b6f 100644
+--- a/net/netfilter/xt_TCPOPTSTRIP.c
++++ b/net/netfilter/xt_TCPOPTSTRIP.c
+@@ -90,7 +90,7 @@ tcpoptstrip_tg6(struct sk_buff *skb, const struct net_device *in,
+ const struct xt_target *target, const void *targinfo)
+ {
+ struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+- unsigned int tcphoff;
++ int tcphoff;
+ u_int8_t nexthdr;
+
+ nexthdr = ipv6h->nexthdr;
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index 3b01119..2e89a00 100644
--- a/net/netfilter/xt_connlimit.c
@@ -913410,7 +1213742,7 @@
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
+index 4478f2f..0099da5 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,
@@ -913433,8 +1213765,43 @@
ret_val = nla_put_string(cb_arg->skb,
NLBL_UNLABEL_A_IFACE, dev->name);
dev_put(dev);
+@@ -1776,6 +1780,7 @@ int __init netlbl_unlabel_defconf(void)
+ * messages so don't worry to much about these values. */
+ security_task_getsecid(current, &audit_info.secid);
+ audit_info.loginuid = 0;
++ audit_info.sessionid = 0;
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (entry == NULL)
+diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
+index b17d420..68706b4 100644
+--- a/net/netlabel/netlabel_user.c
++++ b/net/netlabel/netlabel_user.c
+@@ -107,7 +107,9 @@ struct audit_buffer *netlbl_audit_start_common(int type,
+ if (audit_buf == NULL)
+ return NULL;
+
+- audit_log_format(audit_buf, "netlabel: auid=%u", audit_info->loginuid);
++ audit_log_format(audit_buf, "netlabel: auid=%u ses=%u",
++ audit_info->loginuid,
++ audit_info->sessionid);
+
+ if (audit_info->secid != 0 &&
+ security_secid_to_secctx(audit_info->secid,
+diff --git a/net/netlabel/netlabel_user.h b/net/netlabel/netlabel_user.h
+index 6d7f4ab..6caef8b 100644
+--- a/net/netlabel/netlabel_user.h
++++ b/net/netlabel/netlabel_user.h
+@@ -51,6 +51,7 @@ static inline void netlbl_netlink_auditinfo(struct sk_buff *skb,
+ {
+ audit_info->secid = NETLINK_CB(skb).sid;
+ audit_info->loginuid = NETLINK_CB(skb).loginuid;
++ audit_info->sessionid = NETLINK_CB(skb).sessionid;
+ }
+
+ /* NetLabel NETLINK I/O functions */
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
-index 1ab0da2..46f3e44 100644
+index 1ab0da2..9b97f80 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -54,7 +54,6 @@
@@ -913559,16 +1213926,17 @@
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,
+@@ -1239,7 +1248,8 @@ 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));
++ NETLINK_CB(skb).sessionid = audit_get_sessionid(current);
+ 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)
+@@ -1344,22 +1354,6 @@ static void netlink_data_ready(struct sock *sk, int len)
* queueing.
*/
@@ -913591,7 +1213959,7 @@
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,
+@@ -1388,8 +1382,7 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups,
goto out_sock_release_nosk;
sk = sock->sk;
@@ -913601,7 +1213969,7 @@
if (groups < 32)
groups = 32;
-@@ -1424,7 +1416,7 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups,
+@@ -1424,7 +1417,7 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups,
out_sock_release:
kfree(listeners);
@@ -913610,7 +1213978,7 @@
return NULL;
out_sock_release_nosk:
-@@ -1437,10 +1429,7 @@ EXPORT_SYMBOL(netlink_kernel_create);
+@@ -1437,10 +1430,7 @@ EXPORT_SYMBOL(netlink_kernel_create);
void
netlink_kernel_release(struct sock *sk)
{
@@ -913622,7 +1213990,7 @@
}
EXPORT_SYMBOL(netlink_kernel_release);
-@@ -1553,8 +1542,13 @@ static int netlink_dump(struct sock *sk)
+@@ -1553,8 +1543,13 @@ static int netlink_dump(struct sock *sk)
if (len > 0) {
mutex_unlock(nlk->cb_mutex);
@@ -913638,7 +1214006,7 @@
return 0;
}
-@@ -1564,8 +1558,12 @@ static int netlink_dump(struct sock *sk)
+@@ -1564,8 +1559,12 @@ static int netlink_dump(struct sock *sk)
memcpy(nlmsg_data(nlh), &len, sizeof(len));
@@ -913653,7 +1214021,7 @@
if (cb->done)
cb->done(cb);
-@@ -1602,7 +1600,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
+@@ -1602,7 +1601,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
atomic_inc(&skb->users);
cb->skb = skb;
@@ -913662,7 +1214030,7 @@
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)
+@@ -1644,7 +1643,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
if (!skb) {
struct sock *sk;
@@ -913671,7 +1214039,7 @@
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)
+@@ -1759,7 +1758,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]) {
@@ -913680,7 +1214048,7 @@
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)
+@@ -1795,7 +1794,7 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
s = v;
do {
s = sk_next(s);
@@ -913689,7 +1214057,7 @@
if (s)
return s;
-@@ -1807,7 +1805,7 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+@@ -1807,7 +1806,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]);
@@ -914114,6 +1214482,20 @@
int t;
int s_t;
struct net_device *dev;
+diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
+index a20e2ef..f0463d7 100644
+--- a/net/sched/sch_sfq.c
++++ b/net/sched/sch_sfq.c
+@@ -521,7 +521,8 @@ static void sfq_destroy(struct Qdisc *sch)
+ struct sfq_sched_data *q = qdisc_priv(sch);
+
+ tcf_destroy_chain(q->filter_list);
+- del_timer(&q->perturb_timer);
++ q->perturb_period = 0;
++ del_timer_sync(&q->perturb_timer);
+ }
+
+ static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb)
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index d29f792..b4cd2b7 100644
--- a/net/sctp/associola.c
@@ -918141,7 +1218523,7 @@
/*
* 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
+index d5553b8..e1770f7 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -188,9 +188,9 @@ out_sleep:
@@ -918168,9 +1218550,12 @@
return 0;
}
EXPORT_SYMBOL_GPL(xprt_reserve_xprt_cong);
-@@ -447,13 +447,13 @@ EXPORT_SYMBOL_GPL(xprt_wake_pending_tasks);
+@@ -445,15 +445,15 @@ EXPORT_SYMBOL_GPL(xprt_wake_pending_tasks);
+ /**
+ * xprt_wait_for_buffer_space - wait for transport output buffer to clear
* @task: task to be put to sleep
- *
+- *
++ * @action: function pointer to be executed after wait
*/
-void xprt_wait_for_buffer_space(struct rpc_task *task)
+void xprt_wait_for_buffer_space(struct rpc_task *task, rpc_action action)
@@ -918879,7 +1219264,7 @@
break; /* No error */
switch (msg_errcode(msg)) {
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
-index e9ef6df..6ad070d 100644
+index e9ef6df..ad487e8 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -40,18 +40,16 @@
@@ -918908,20 +1219293,17 @@
/*
-@@ -72,8 +70,10 @@ static inline void msg_set_bits(struct tipc_msg *m, u32 w,
+@@ -72,7 +70,8 @@ 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;
++ mask = mask << pos;
++ m->hdr[w] &= ~htonl(mask);
+ m->hdr[w] |= htonl(val);
}
- /*
-@@ -87,7 +87,7 @@ static inline u32 msg_version(struct tipc_msg *m)
+@@ -87,7 +86,7 @@ static inline u32 msg_version(struct tipc_msg *m)
static inline void msg_set_version(struct tipc_msg *m)
{
@@ -918930,7 +1219312,7 @@
}
static inline u32 msg_user(struct tipc_msg *m)
-@@ -97,7 +97,7 @@ static inline u32 msg_user(struct tipc_msg *m)
+@@ -97,7 +96,7 @@ static inline u32 msg_user(struct tipc_msg *m)
static inline u32 msg_isdata(struct tipc_msg *m)
{
@@ -918939,7 +1219321,7 @@
}
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)
+@@ -190,18 +189,6 @@ static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n)
msg_set_bits(m, 1, 19, 0x3, n);
}
@@ -918958,7 +1219340,7 @@
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)
+@@ -330,17 +317,6 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m)
return (struct tipc_msg *)msg_data(m);
}
@@ -918976,7 +1219358,7 @@
/*
TIPC internal message header format, version 2
-@@ -388,7 +365,6 @@ static inline void msg_expand(struct tipc_msg *m, u32 destnode)
+@@ -388,7 +364,6 @@ static inline void msg_expand(struct tipc_msg *m, u32 destnode)
#define NAME_DISTRIBUTOR 11
#define MSG_FRAGMENTER 12
#define LINK_CONFIG 13
@@ -922659,8 +1223041,35 @@
goto drop;
nskb = skb_copy(skb, GFP_ATOMIC);
+diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
+index 8aa6440..ac765dd 100644
+--- a/net/xfrm/xfrm_algo.c
++++ b/net/xfrm/xfrm_algo.c
+@@ -129,8 +129,7 @@ static struct xfrm_algo_desc aead_list[] = {
+
+ static struct xfrm_algo_desc aalg_list[] = {
+ {
+- .name = "hmac(digest_null)",
+- .compat = "digest_null",
++ .name = "digest_null",
+
+ .uinfo = {
+ .auth = {
+diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
+index 2519129..09cd9c0 100644
+--- a/net/xfrm/xfrm_output.c
++++ b/net/xfrm/xfrm_output.c
+@@ -150,7 +150,7 @@ static int xfrm_output_gso(struct sk_buff *skb)
+
+ segs = skb_gso_segment(skb, 0);
+ kfree_skb(skb);
+- if (unlikely(IS_ERR(segs)))
++ if (IS_ERR(segs))
+ return PTR_ERR(segs);
+
+ do {
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
-index 9fc4c31..e0c0390 100644
+index 9fc4c31..cae9fd8 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -46,6 +46,7 @@ EXPORT_SYMBOL(xfrm_cfg_mutex);
@@ -922781,7 +1223190,7 @@
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)
+@@ -722,10 +758,11 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
&xfrm_policy_inexact[dir], bydst) {
if (pol->type != type)
continue;
@@ -922790,7 +1223199,11 @@
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)
++ audit_info->sessionid,
+ audit_info->secid);
+ return err;
+ }
+@@ -736,10 +773,12 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
bydst) {
if (pol->type != type)
continue;
@@ -922800,7 +1223213,27 @@
if (err) {
xfrm_audit_policy_delete(pol, 0,
audit_info->loginuid,
-@@ -822,57 +859,60 @@ out:
++ audit_info->sessionid,
+ audit_info->secid);
+ return err;
+ }
+@@ -782,6 +821,7 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
+ write_unlock_bh(&xfrm_policy_lock);
+
+ xfrm_audit_policy_delete(pol, 1, audit_info->loginuid,
++ audit_info->sessionid,
+ audit_info->secid);
+
+ xfrm_policy_kill(pol);
+@@ -804,6 +844,7 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
+
+ xfrm_audit_policy_delete(pol, 1,
+ audit_info->loginuid,
++ audit_info->sessionid,
+ audit_info->secid);
+ xfrm_policy_kill(pol);
+ killed++;
+@@ -822,57 +863,60 @@ out:
}
EXPORT_SYMBOL(xfrm_policy_flush);
@@ -922894,7 +1223327,7 @@
return error;
}
EXPORT_SYMBOL(xfrm_policy_walk);
-@@ -894,7 +934,8 @@ static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl,
+@@ -894,7 +938,8 @@ static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl,
match = xfrm_selector_match(sel, fl, family);
if (match)
@@ -922904,7 +1223337,7 @@
return ret;
}
-@@ -1011,8 +1052,9 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc
+@@ -1011,8 +1056,9 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc
int err = 0;
if (match) {
@@ -922916,7 +1223349,7 @@
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)
+@@ -1101,7 +1147,8 @@ static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir)
if (newp) {
newp->selector = old->selector;
@@ -922926,7 +1223359,7 @@
kfree(newp);
return NULL; /* ENOMEM */
}
-@@ -1344,6 +1387,9 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
+@@ -1344,6 +1391,9 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
int trailer_len = 0;
int tos;
int family = policy->selector.family;
@@ -922936,7 +1223369,7 @@
tos = xfrm_get_tos(fl, family);
err = tos;
-@@ -1374,7 +1420,8 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
+@@ -1374,7 +1424,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;
@@ -922946,7 +1223379,7 @@
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,
+@@ -1772,7 +1823,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 &&
@@ -922955,7 +1223388,7 @@
!(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)
+@@ -2038,7 +2089,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) {
@@ -922964,7 +1223397,7 @@
dev_hold(dst->dev);
dev_put(dev);
}
-@@ -2309,7 +2356,7 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void
+@@ -2309,7 +2360,7 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void
{
struct net_device *dev = ptr;
@@ -922973,7 +1223406,7 @@
return NOTIFY_DONE;
switch (event) {
-@@ -2365,6 +2412,9 @@ static void __init xfrm_policy_init(void)
+@@ -2365,6 +2416,9 @@ static void __init xfrm_policy_init(void)
panic("XFRM: failed to allocate bydst hash\n");
}
@@ -922983,8 +1223416,42 @@
INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task);
register_netdevice_notifier(&xfrm_dev_notifier);
}
+@@ -2422,14 +2476,14 @@ static void xfrm_audit_common_policyinfo(struct xfrm_policy *xp,
+ }
+
+ void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
+- u32 auid, u32 secid)
++ uid_t auid, u32 sessionid, u32 secid)
+ {
+ struct audit_buffer *audit_buf;
+
+ audit_buf = xfrm_audit_start("SPD-add");
+ if (audit_buf == NULL)
+ return;
+- xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
++ xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
+ audit_log_format(audit_buf, " res=%u", result);
+ xfrm_audit_common_policyinfo(xp, audit_buf);
+ audit_log_end(audit_buf);
+@@ -2437,14 +2491,14 @@ void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
+ EXPORT_SYMBOL_GPL(xfrm_audit_policy_add);
+
+ void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
+- u32 auid, u32 secid)
++ uid_t auid, u32 sessionid, u32 secid)
+ {
+ struct audit_buffer *audit_buf;
+
+ audit_buf = xfrm_audit_start("SPD-delete");
+ if (audit_buf == NULL)
+ return;
+- xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
++ xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
+ audit_log_format(audit_buf, " res=%u", result);
+ xfrm_audit_common_policyinfo(xp, audit_buf);
+ audit_log_end(audit_buf);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
-index 58f1f93..5dcc10b 100644
+index 58f1f93..72fddaf 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -50,6 +50,7 @@ static DEFINE_SPINLOCK(xfrm_state_lock);
@@ -922995,7 +1223462,17 @@
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)
+@@ -495,7 +496,8 @@ expired:
+ km_state_expired(x, 1, 0);
+
+ xfrm_audit_state_delete(x, err ? 0 : 1,
+- audit_get_loginuid(current), 0);
++ audit_get_loginuid(current),
++ audit_get_sessionid(current), 0);
+
+ out:
+ spin_unlock(&x->lock);
+@@ -512,6 +514,7 @@ struct xfrm_state *xfrm_state_alloc(void)
if (x) {
atomic_set(&x->refcnt, 1);
atomic_set(&x->tunnel_users, 0);
@@ -923003,7 +1223480,7 @@
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)
+@@ -537,6 +540,10 @@ void __xfrm_state_destroy(struct xfrm_state *x)
{
BUG_TRAP(x->km.state == XFRM_STATE_DEAD);
@@ -923014,7 +1223491,23 @@
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)
+@@ -597,6 +604,7 @@ xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
+ (err = security_xfrm_state_delete(x)) != 0) {
+ xfrm_audit_state_delete(x, 0,
+ audit_info->loginuid,
++ audit_info->sessionid,
+ audit_info->secid);
+ return err;
+ }
+@@ -635,6 +643,7 @@ restart:
+ err = xfrm_state_delete(x);
+ xfrm_audit_state_delete(x, err ? 0 : 1,
+ audit_info->loginuid,
++ audit_info->sessionid,
+ audit_info->secid);
+ xfrm_state_put(x);
+
+@@ -913,6 +922,8 @@ static void __xfrm_state_insert(struct xfrm_state *x)
x->genid = ++xfrm_state_genid;
@@ -923023,7 +1223516,7 @@
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:
+@@ -1522,36 +1533,47 @@ unlock:
}
EXPORT_SYMBOL(xfrm_alloc_spi);
@@ -923088,11 +1223581,94 @@
return err;
}
EXPORT_SYMBOL(xfrm_state_walk);
+@@ -2093,7 +2115,7 @@ static void xfrm_audit_helper_pktinfo(struct sk_buff *skb, u16 family,
+ iph6 = ipv6_hdr(skb);
+ audit_log_format(audit_buf,
+ " src=" NIP6_FMT " dst=" NIP6_FMT
+- " flowlbl=0x%x%x%x",
++ " flowlbl=0x%x%02x%02x",
+ NIP6(iph6->saddr),
+ NIP6(iph6->daddr),
+ iph6->flow_lbl[0] & 0x0f,
+@@ -2104,14 +2126,14 @@ static void xfrm_audit_helper_pktinfo(struct sk_buff *skb, u16 family,
+ }
+
+ void xfrm_audit_state_add(struct xfrm_state *x, int result,
+- u32 auid, u32 secid)
++ uid_t auid, u32 sessionid, u32 secid)
+ {
+ struct audit_buffer *audit_buf;
+
+ audit_buf = xfrm_audit_start("SAD-add");
+ if (audit_buf == NULL)
+ return;
+- xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
++ xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
+ xfrm_audit_helper_sainfo(x, audit_buf);
+ audit_log_format(audit_buf, " res=%u", result);
+ audit_log_end(audit_buf);
+@@ -2119,14 +2141,14 @@ void xfrm_audit_state_add(struct xfrm_state *x, int result,
+ EXPORT_SYMBOL_GPL(xfrm_audit_state_add);
+
+ void xfrm_audit_state_delete(struct xfrm_state *x, int result,
+- u32 auid, u32 secid)
++ uid_t auid, u32 sessionid, u32 secid)
+ {
+ struct audit_buffer *audit_buf;
+
+ audit_buf = xfrm_audit_start("SAD-delete");
+ if (audit_buf == NULL)
+ return;
+- xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
++ xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
+ xfrm_audit_helper_sainfo(x, audit_buf);
+ audit_log_format(audit_buf, " res=%u", result);
+ audit_log_end(audit_buf);
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
-index 019d21d..22a30ae 100644
+index 019d21d..a1b0fbe 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
-@@ -529,8 +529,6 @@ struct xfrm_dump_info {
+@@ -407,6 +407,9 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct xfrm_state *x;
+ int err;
+ struct km_event c;
++ uid_t loginuid = NETLINK_CB(skb).loginuid;
++ u32 sessionid = NETLINK_CB(skb).sessionid;
++ u32 sid = NETLINK_CB(skb).sid;
+
+ err = verify_newsa_info(p, attrs);
+ if (err)
+@@ -422,8 +425,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
+ else
+ err = xfrm_state_update(x);
+
+- xfrm_audit_state_add(x, err ? 0 : 1, NETLINK_CB(skb).loginuid,
+- NETLINK_CB(skb).sid);
++ xfrm_audit_state_add(x, err ? 0 : 1, loginuid, sessionid, sid);
+
+ if (err < 0) {
+ x->km.state = XFRM_STATE_DEAD;
+@@ -478,6 +480,9 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
+ int err = -ESRCH;
+ struct km_event c;
+ struct xfrm_usersa_id *p = nlmsg_data(nlh);
++ uid_t loginuid = NETLINK_CB(skb).loginuid;
++ u32 sessionid = NETLINK_CB(skb).sessionid;
++ u32 sid = NETLINK_CB(skb).sid;
+
+ x = xfrm_user_state_lookup(p, attrs, &err);
+ if (x == NULL)
+@@ -502,8 +507,7 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
+ km_state_notify(x, &c);
+
+ out:
+- xfrm_audit_state_delete(x, err ? 0 : 1, NETLINK_CB(skb).loginuid,
+- NETLINK_CB(skb).sid);
++ xfrm_audit_state_delete(x, err ? 0 : 1, loginuid, sessionid, sid);
+ xfrm_state_put(x);
+ return err;
+ }
+@@ -529,8 +533,6 @@ struct xfrm_dump_info {
struct sk_buff *out_skb;
u32 nlmsg_seq;
u16 nlmsg_flags;
@@ -923101,7 +1223677,7 @@
};
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)
+@@ -597,9 +599,6 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
struct nlmsghdr *nlh;
int err;
@@ -923111,7 +1223687,7 @@
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)
+@@ -612,8 +611,6 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
goto nla_put_failure;
nlmsg_end(skb, nlh);
@@ -923120,7 +1223696,7 @@
return 0;
nla_put_failure:
-@@ -621,18 +614,32 @@ nla_put_failure:
+@@ -621,18 +618,32 @@ nla_put_failure:
return err;
}
@@ -923157,7 +1223733,7 @@
return skb->len;
}
-@@ -651,7 +658,6 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
+@@ -651,7 +662,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;
@@ -923165,7 +1223741,7 @@
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
+@@ -953,7 +963,7 @@ static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs
return 0;
uctx = nla_data(rt);
@@ -923174,7 +1223750,7 @@
}
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,
+@@ -975,6 +985,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;
@@ -923183,8 +1223759,23 @@
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);
+@@ -1115,6 +1127,9 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct km_event c;
+ int err;
+ int excl;
++ uid_t loginuid = NETLINK_CB(skb).loginuid;
++ u32 sessionid = NETLINK_CB(skb).sessionid;
++ u32 sid = NETLINK_CB(skb).sid;
+
+ err = verify_newpolicy_info(p);
+ if (err)
+@@ -1133,11 +1148,10 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
+ * a type XFRM_MSG_UPDPOLICY - JHS */
+ excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
+ err = xfrm_policy_insert(p->dir, xp, excl);
+- xfrm_audit_policy_add(xp, err ? 0 : 1, NETLINK_CB(skb).loginuid,
+- NETLINK_CB(skb).sid);
++ xfrm_audit_policy_add(xp, err ? 0 : 1, loginuid, sessionid, sid);
if (err) {
- security_xfrm_policy_free(xp);
@@ -923192,7 +1223783,7 @@
kfree(xp);
return err;
}
-@@ -1229,9 +1237,6 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
+@@ -1229,9 +1243,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;
@@ -923202,7 +1223793,7 @@
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
+@@ -1247,8 +1258,6 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
goto nlmsg_failure;
nlmsg_end(skb, nlh);
@@ -923211,7 +1223802,7 @@
return 0;
nlmsg_failure:
-@@ -1256,21 +1259,33 @@ nlmsg_failure:
+@@ -1256,21 +1265,33 @@ nlmsg_failure:
return -EMSGSIZE;
}
@@ -923252,7 +1223843,7 @@
return skb->len;
}
-@@ -1290,7 +1305,6 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
+@@ -1290,7 +1311,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;
@@ -923260,7 +1223851,7 @@
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,
+@@ -1325,22 +1345,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];
@@ -923289,7 +1223880,39 @@
}
if (xp == NULL)
return -ENOENT;
-@@ -1560,26 +1575,26 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
+@@ -1356,9 +1377,12 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
+ NETLINK_CB(skb).pid);
+ }
+ } else {
+- xfrm_audit_policy_delete(xp, err ? 0 : 1,
+- NETLINK_CB(skb).loginuid,
+- NETLINK_CB(skb).sid);
++ uid_t loginuid = NETLINK_CB(skb).loginuid;
++ u32 sessionid = NETLINK_CB(skb).sessionid;
++ u32 sid = NETLINK_CB(skb).sid;
++
++ xfrm_audit_policy_delete(xp, err ? 0 : 1, loginuid, sessionid,
++ sid);
+
+ if (err != 0)
+ goto out;
+@@ -1384,6 +1408,7 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
+ int err;
+
+ audit_info.loginuid = NETLINK_CB(skb).loginuid;
++ audit_info.sessionid = NETLINK_CB(skb).sessionid;
+ audit_info.secid = NETLINK_CB(skb).sid;
+ err = xfrm_state_flush(p->proto, &audit_info);
+ if (err)
+@@ -1531,6 +1556,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
+ return err;
+
+ audit_info.loginuid = NETLINK_CB(skb).loginuid;
++ audit_info.sessionid = NETLINK_CB(skb).sessionid;
+ audit_info.secid = NETLINK_CB(skb).sid;
+ err = xfrm_policy_flush(type, &audit_info);
+ if (err)
+@@ -1560,26 +1586,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];
@@ -923323,7 +1223946,35 @@
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] = {
+@@ -1589,9 +1615,11 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
+ read_unlock(&xp->lock);
+ err = 0;
+ if (up->hard) {
++ uid_t loginuid = NETLINK_CB(skb).loginuid;
++ uid_t sessionid = NETLINK_CB(skb).sessionid;
++ u32 sid = NETLINK_CB(skb).sid;
+ xfrm_policy_delete(xp, p->dir);
+- xfrm_audit_policy_delete(xp, 1, NETLINK_CB(skb).loginuid,
+- NETLINK_CB(skb).sid);
++ xfrm_audit_policy_delete(xp, 1, loginuid, sessionid, sid);
+
+ } else {
+ // reset the timers here?
+@@ -1625,9 +1653,11 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
+ km_state_expired(x, ue->hard, current->pid);
+
+ if (ue->hard) {
++ uid_t loginuid = NETLINK_CB(skb).loginuid;
++ uid_t sessionid = NETLINK_CB(skb).sessionid;
++ u32 sid = NETLINK_CB(skb).sid;
+ __xfrm_state_delete(x);
+- xfrm_audit_state_delete(x, 1, NETLINK_CB(skb).loginuid,
+- NETLINK_CB(skb).sid);
++ xfrm_audit_state_delete(x, 1, loginuid, sessionid, sid);
+ }
+ err = 0;
+ out:
+@@ -1888,15 +1918,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 *);
@@ -923344,7 +1223995,7 @@
[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)
+@@ -1935,7 +1968,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (link->dump == NULL)
return -EINVAL;
@@ -923690,6 +1224341,47 @@
+
+module_init(firmware_sample_init);
+module_exit(firmware_sample_exit);
+diff --git a/samples/markers/marker-example.c b/samples/markers/marker-example.c
+index 05e438f..e90dc5d 100644
+--- a/samples/markers/marker-example.c
++++ b/samples/markers/marker-example.c
+@@ -33,10 +33,8 @@ static struct file_operations mark_ops = {
+ static int example_init(void)
+ {
+ printk(KERN_ALERT "example init\n");
+- pentry_example = create_proc_entry("marker-example", 0444, NULL);
+- if (pentry_example)
+- pentry_example->proc_fops = &mark_ops;
+- else
++ pentry_example = proc_create("marker-example", 0444, NULL, &mark_ops);
++ if (!pentry_example)
+ return -EPERM;
+ return 0;
+ }
+diff --git a/scripts/Lindent b/scripts/Lindent
+index 9468ec7..9c4b3e2 100755
+--- a/scripts/Lindent
++++ b/scripts/Lindent
+@@ -1,2 +1,18 @@
+ #!/bin/sh
+-indent -npro -kr -i8 -ts8 -sob -l80 -ss -ncs -cp1 "$@"
++PARAM="-npro -kr -i8 -ts8 -sob -l80 -ss -ncs -cp1"
++RES=`indent --version`
++V1=`echo $RES | cut -d' ' -f3 | cut -d'.' -f1`
++V2=`echo $RES | cut -d' ' -f3 | cut -d'.' -f2`
++V3=`echo $RES | cut -d' ' -f3 | cut -d'.' -f3`
++if [ $V1 -gt 2 ]; then
++ PARAM="$PARAM -il0"
++elif [ $V1 -eq 2 ]; then
++ if [ $V2 -gt 2 ]; then
++ PARAM="$PARAM -il0";
++ elif [ $V2 -eq 2 ]; then
++ if [ $V3 -ge 10 ]; then
++ PARAM="$PARAM -il0"
++ fi
++ fi
++fi
++indent $PARAM "$@"
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 67fb453..277cfe0 100644
--- a/scripts/Makefile.build
@@ -923771,7 +1224463,7 @@
# 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
+index 2d20640..a098a04 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -42,6 +42,13 @@ _modpost: __modpost
@@ -923792,15 +1224484,267 @@
$(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_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
+index 58a9494..b6bbbcd 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
-@@ -1889,6 +1889,13 @@ sub process {
+@@ -9,7 +9,7 @@ use strict;
+ my $P = $0;
+ $P =~ s at .*/@@g;
+
+-my $V = '0.16';
++my $V = '0.18';
+
+ use Getopt::Long qw(:config no_auto_abbrev);
+
+@@ -131,6 +131,17 @@ our $NonptrType;
+ our $Type;
+ our $Declare;
+
++our $UTF8 = qr {
++ [\x09\x0A\x0D\x20-\x7E] # ASCII
++ | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
++ | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
++ | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
++ | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
++ | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
++ | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
++ | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
++}x;
++
+ our @typeList = (
+ qr{void},
+ qr{char},
+@@ -692,7 +703,7 @@ sub annotate_values {
+ while (length($cur)) {
+ @av_paren_type = ('E') if ($#av_paren_type < 0);
+ print " <" . join('', @av_paren_type) .
+- "> <$type> " if ($dbg_values > 1);
++ "> <$type> <$av_pending>" if ($dbg_values > 1);
+ if ($cur =~ /^(\s+)/o) {
+ print "WS($1)\n" if ($dbg_values > 1);
+ if ($1 =~ /\n/ && $av_preprocessor) {
+@@ -705,9 +716,18 @@ sub annotate_values {
+ $type = 'T';
+
+ } elsif ($cur =~ /^(#\s*define\s*$Ident)(\(?)/o) {
+- print "DEFINE($1)\n" if ($dbg_values > 1);
++ print "DEFINE($1,$2)\n" if ($dbg_values > 1);
+ $av_preprocessor = 1;
+- $av_pending = 'N';
++ push(@av_paren_type, $type);
++ if ($2 ne '') {
++ $av_pending = 'N';
++ }
++ $type = 'E';
++
++ } elsif ($cur =~ /^(#\s*undef\s*$Ident)/o) {
++ print "UNDEF($1)\n" if ($dbg_values > 1);
++ $av_preprocessor = 1;
++ push(@av_paren_type, $type);
+
+ } elsif ($cur =~ /^(#\s*(?:ifdef|ifndef|if))/o) {
+ print "PRE_START($1)\n" if ($dbg_values > 1);
+@@ -715,7 +735,7 @@ sub annotate_values {
+
+ push(@av_paren_type, $type);
+ push(@av_paren_type, $type);
+- $type = 'N';
++ $type = 'E';
+
+ } elsif ($cur =~ /^(#\s*(?:else|elif))/o) {
+ print "PRE_RESTART($1)\n" if ($dbg_values > 1);
+@@ -723,7 +743,7 @@ sub annotate_values {
+
+ push(@av_paren_type, $av_paren_type[$#av_paren_type]);
+
+- $type = 'N';
++ $type = 'E';
+
+ } elsif ($cur =~ /^(#\s*(?:endif))/o) {
+ print "PRE_END($1)\n" if ($dbg_values > 1);
+@@ -734,11 +754,16 @@ sub annotate_values {
+ # one does, and continue as if the #endif was not here.
+ pop(@av_paren_type);
+ push(@av_paren_type, $type);
+- $type = 'N';
++ $type = 'E';
+
+ } elsif ($cur =~ /^(\\\n)/o) {
+ print "PRECONT($1)\n" if ($dbg_values > 1);
+
++ } elsif ($cur =~ /^(__attribute__)\s*\(?/o) {
++ print "ATTR($1)\n" if ($dbg_values > 1);
++ $av_pending = $type;
++ $type = 'N';
++
+ } elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
+ print "SIZEOF($1)\n" if ($dbg_values > 1);
+ if (defined $2) {
+@@ -930,7 +955,7 @@ sub process {
+ # edge is a close comment then we must be in a comment
+ # at context start.
+ my $edge;
+- for (my $ln = $linenr; $ln < ($linenr + $realcnt); $ln++) {
++ for (my $ln = $linenr + 1; $ln < ($linenr + $realcnt); $ln++) {
+ next if ($line =~ /^-/);
+ ($edge) = ($rawlines[$ln - 1] =~ m@(/\*|\*/)@);
+ last if (defined $edge);
+@@ -951,9 +976,9 @@ sub process {
+ ##print "COMMENT:$in_comment edge<$edge> $rawline\n";
+ sanitise_line_reset($in_comment);
+
+- } elsif ($realcnt) {
++ } elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) {
+ # Standardise the strings and chars within the input to
+- # simplify matching.
++ # simplify matching -- only bother with positive lines.
+ $line = sanitise_line($rawline);
+ }
+ push(@lines, $line);
+@@ -1066,17 +1091,14 @@ sub process {
+
+ # UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
+ if (($realfile =~ /^$/ || $line =~ /^\+/) &&
+- !($rawline =~ m/^(
+- [\x09\x0A\x0D\x20-\x7E] # ASCII
+- | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
+- | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
+- | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
+- | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
+- | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
+- | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
+- | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
+- )*$/x )) {
+- ERROR("Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $herecurr);
++ $rawline !~ m/^$UTF8*$/) {
++ my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/);
++
++ my $blank = copy_spacing($rawline);
++ my $ptr = substr($blank, 0, length($utf8_prefix)) . "^";
++ my $hereptr = "$hereline$ptr\n";
++
++ ERROR("Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr);
+ }
+
+ #ignore lines being removed
+@@ -1112,7 +1134,7 @@ sub process {
+ if ($rawline =~ /^\+\s* \t\s*\S/ ||
+ $rawline =~ /^\+\s* \s*/) {
+ my $herevet = "$here\n" . cat_vet($rawline) . "\n";
+- ERROR("use tabs not spaces\n" . $herevet);
++ ERROR("code indent should use tabs where possible\n" . $herevet);
+ }
+
+ # check for RCS/CVS revision markers
+@@ -1121,35 +1143,40 @@ sub process {
+ }
+
+ # Check for potential 'bare' types
+- if ($realcnt) {
+- my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
+- $s =~ s/\n./ /g;
+- $s =~ s/{.*$//;
++ my ($stat, $cond);
++ if ($realcnt && $line =~ /.\s*\S/) {
++ ($stat, $cond) = ctx_statement_block($linenr,
++ $realcnt, 0);
++ $stat =~ s/\n./\n /g;
++ $cond =~ s/\n./\n /g;
++
++ my $s = $stat;
++ $s =~ s/{.*$//s;
+
+ # Ignore goto labels.
+- if ($s =~ /$Ident:\*$/) {
++ if ($s =~ /$Ident:\*$/s) {
+
+ # Ignore functions being called
+- } elsif ($s =~ /^.\s*$Ident\s*\(/) {
++ } elsif ($s =~ /^.\s*$Ident\s*\(/s) {
+
+ # definitions in global scope can only start with types
+- } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b/) {
++ } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b/s) {
+ possible($1, $s);
+
+ # declarations always start with types
+- } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:const\s+)?($Ident)\b(:?\s+$Sparse)?\s*\**\s*$Ident\s*(?:;|=|,)/) {
++ } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:const\s+)?($Ident)\b(:?\s+$Sparse)?\s*\**\s*$Ident\s*(?:;|=|,)/s) {
+ possible($1, $s);
+ }
+
+ # any (foo ... *) is a pointer cast, and foo is a type
+- while ($s =~ /\(($Ident)(?:\s+$Sparse)*\s*\*+\s*\)/g) {
++ while ($s =~ /\(($Ident)(?:\s+$Sparse)*\s*\*+\s*\)/sg) {
+ possible($1, $s);
+ }
+
+ # Check for any sort of function declaration.
+ # int foo(something bar, other baz);
+ # void (*store_gdt)(x86_descr_ptr *);
+- if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/) {
++ if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) {
+ my ($name_len) = length($1);
+
+ my $ctx = $s;
+@@ -1282,18 +1309,19 @@ sub process {
+ ($prevline !~ /^ }/) &&
+ ($prevline !~ /^.DECLARE_$Ident\(\Q$name\E\)/) &&
+ ($prevline !~ /^.LIST_HEAD\(\Q$name\E\)/) &&
++ ($prevline !~ /^.$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(/) &&
+ ($prevline !~ /\b\Q$name\E(?:\s+$Attribute)?\s*(?:;|=|\[)/)) {
+ WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
+ }
+ }
+
+ # check for external initialisers.
+- if ($line =~ /^.$Type\s*$Ident\s*=\s*(0|NULL);/) {
++ if ($line =~ /^.$Type\s*$Ident\s*=\s*(0|NULL|false)\s*;/) {
+ ERROR("do not initialise externals to 0 or NULL\n" .
+ $herecurr);
+ }
+ # check for static initialisers.
+- if ($line =~ /\s*static\s.*=\s*(0|NULL);/) {
++ if ($line =~ /\s*static\s.*=\s*(0|NULL|false)\s*;/) {
+ ERROR("do not initialise statics to 0 or NULL\n" .
+ $herecurr);
+ }
+@@ -1512,7 +1540,10 @@ sub process {
+ if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
+ ERROR("space required before that '$op' $at\n" . $hereptr);
+ }
+- if ($ctx =~ /.xW/) {
++ if ($op eq '*' && $cc =~/\s*const\b/) {
++ # A unary '*' may be const
++
++ } elsif ($ctx =~ /.xW/) {
+ ERROR("space prohibited after that '$op' $at\n" . $hereptr);
+ }
+
+@@ -1617,7 +1648,7 @@ sub process {
+
+ # Check for illegal assignment in if conditional.
+ if ($line =~ /\bif\s*\(/) {
+- my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
++ my ($s, $c) = ($stat, $cond);
+
+ if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/) {
+ ERROR("do not use assignment in if condition\n" . $herecurr);
+@@ -1695,7 +1726,7 @@ sub process {
+ #warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
+ if ($tree && $rawline =~ m{^.\#\s*include\s*\<asm\/(.*)\.h\>}) {
+ my $checkfile = "$root/include/linux/$1.h";
+- if (-f $checkfile && $1 ne 'irq.h') {
++ if (-f $checkfile && $1 ne 'irq') {
+ WARN("Use #include <linux/$1.h> instead of <asm/$1.h>\n" .
+ $herecurr);
+ }
+@@ -1889,6 +1920,13 @@ sub process {
WARN("kfree(NULL) is safe this check is probabally not required\n" . $hereprev);
}
}
@@ -923814,6 +1224758,115 @@
# warn about #ifdefs in C files
# if ($line =~ /^.#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
+@@ -1903,7 +1941,8 @@ sub process {
+ }
+
+ # check for spinlock_t definitions without a comment.
+- if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/) {
++ if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ ||
++ $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) {
+ my $which = $1;
+ if (!ctx_has_comment($first_line, $linenr)) {
+ CHK("$1 definition without comment\n" . $herecurr);
+@@ -1933,7 +1972,26 @@ sub process {
+ }
+
+ # check for new externs in .c files.
+- if ($line =~ /^.\s*extern\s/ && ($realfile =~ /\.c$/)) {
++ if ($realfile =~ /\.c$/ && defined $stat &&
++ $stat =~ /^.\s*(?:extern\s+)?$Type\s+$Ident(\s*)\(/s)
++ {
++ my $paren_space = $1;
++
++ my $s = $stat;
++ if (defined $cond) {
++ substr($s, 0, length($cond), '');
++ }
++ if ($s =~ /^\s*;/) {
++ WARN("externs should be avoided in .c files\n" . $herecurr);
++ }
++
++ if ($paren_space =~ /\n/) {
++ WARN("arguments for function declarations should follow identifier\n" . $herecurr);
++ }
++
++ } elsif ($realfile =~ /\.c$/ && defined $stat &&
++ $stat =~ /^.\s*extern\s+/)
++ {
+ WARN("externs should be avoided in .c files\n" . $herecurr);
+ }
+
+@@ -1957,11 +2015,11 @@ sub process {
+ }
+
+ # check for semaphores used as mutexes
+- if ($line =~ /\b(DECLARE_MUTEX|init_MUTEX)\s*\(/) {
++ if ($line =~ /^.\s*(DECLARE_MUTEX|init_MUTEX)\s*\(/) {
+ WARN("mutexes are preferred for single holder semaphores\n" . $herecurr);
+ }
+ # check for semaphores used as mutexes
+- if ($line =~ /\binit_MUTEX_LOCKED\s*\(/) {
++ if ($line =~ /^.\s*init_MUTEX_LOCKED\s*\(/) {
+ WARN("consider using a completion\n" . $herecurr);
+ }
+ # recommend strict_strto* over simple_strto*
+@@ -1972,11 +2030,24 @@ sub process {
+ # use of NR_CPUS is usually wrong
+ # ignore definitions of NR_CPUS and usage to define arrays as likely right
+ if ($line =~ /\bNR_CPUS\b/ &&
+- $line !~ /^.#\s*define\s+NR_CPUS\s+/ &&
+- $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/)
++ $line !~ /^.#\s*if\b.*\bNR_CPUS\b/ &&
++ $line !~ /^.#\s*define\b.*\bNR_CPUS\b/ &&
++ $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ &&
++ $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ &&
++ $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/)
+ {
+ WARN("usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr);
+ }
++
++# check for %L{u,d,i} in strings
++ my $string;
++ while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) {
++ $string = substr($rawline, $-[1], $+[1] - $-[1]);
++ if ($string =~ /(?<!%)%L[udi]/) {
++ WARN("\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $herecurr);
++ last;
++ }
++ }
+ }
+
+ # If we have no input at all, then there is nothing to report on
+diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
+index 684fb9c..5f3415f 100644
+--- a/scripts/gen_initramfs_list.sh
++++ b/scripts/gen_initramfs_list.sh
+@@ -135,7 +135,7 @@ parse() {
+ str="${ftype} ${name} ${str} ${dev} ${maj} ${min}"
+ ;;
+ "slink")
+- local target=`field 11 $(LC_ALL=C ls -l "${location}")`
++ local target=`readlink "${location}"`
+ str="${ftype} ${name} ${target} ${str}"
+ ;;
+ *)
+diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
+index c912137..5d20a2e 100644
+--- a/scripts/kallsyms.c
++++ b/scripts/kallsyms.c
+@@ -7,12 +7,6 @@
+ *
+ * Usage: nm -n vmlinux | scripts/kallsyms [--all-symbols] > symbols.S
+ *
+- * ChangeLog:
+- *
+- * (25/Aug/2004) Paulo Marques <pmarques at grupopie.com>
+- * Changed the compression method from stem compression to "table lookup"
+- * compression
+- *
+ * Table compression uses all the unused char codes on the symbols and
+ * maps these to the most used substrings (tokens). For instance, it might
+ * map char code 0xF7 to represent "write_" and then in every symbol where
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 32e8c5a..fa1a7d5 100644
--- a/scripts/kconfig/Makefile
@@ -923831,8 +1224884,962 @@
>> $(obj)/config.pot; \
done )
$(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \
+diff --git a/scripts/kconfig/lex.zconf.c_shipped b/scripts/kconfig/lex.zconf.c_shipped
+index bed0f4e..6a61cee 100644
+--- a/scripts/kconfig/lex.zconf.c_shipped
++++ b/scripts/kconfig/lex.zconf.c_shipped
+@@ -5,25 +5,6 @@
+
+ /* A lexical scanner generated by flex */
+
+-#define yy_create_buffer zconf_create_buffer
+-#define yy_delete_buffer zconf_delete_buffer
+-#define yy_flex_debug zconf_flex_debug
+-#define yy_init_buffer zconf_init_buffer
+-#define yy_flush_buffer zconf_flush_buffer
+-#define yy_load_buffer_state zconf_load_buffer_state
+-#define yy_switch_to_buffer zconf_switch_to_buffer
+-#define yyin zconfin
+-#define yyleng zconfleng
+-#define yylex zconflex
+-#define yylineno zconflineno
+-#define yyout zconfout
+-#define yyrestart zconfrestart
+-#define yytext zconftext
+-#define yywrap zconfwrap
+-#define yyalloc zconfalloc
+-#define yyrealloc zconfrealloc
+-#define yyfree zconffree
+-
+ #define FLEX_SCANNER
+ #define YY_FLEX_MAJOR_VERSION 2
+ #define YY_FLEX_MINOR_VERSION 5
+@@ -354,7 +335,7 @@ void zconffree (void * );
+
+ /* Begin user sect3 */
+
+-#define zconfwrap(n) 1
++#define zconfwrap() 1
+ #define YY_SKIP_YYWRAP
+
+ typedef unsigned char YY_CHAR;
+@@ -1535,7 +1516,7 @@ static int yy_get_next_buffer (void)
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+- (yy_n_chars), num_to_read );
++ (yy_n_chars), (size_t) num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+@@ -2007,7 +1988,7 @@ YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size )
+
+ /** Setup the input buffer state to scan a string. The next call to zconflex() will
+ * scan from a @e copy of @a str.
+- * @param str a NUL-terminated string to scan
++ * @param yystr a NUL-terminated string to scan
+ *
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
+index 4d09f6d..8e69461 100644
+--- a/scripts/kconfig/lkc_proto.h
++++ b/scripts/kconfig/lkc_proto.h
+@@ -21,7 +21,7 @@ P(menu_get_help,const char *,(struct menu *menu));
+ /* symbol.c */
+ P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
+
+-P(sym_lookup,struct symbol *,(const char *name, int isconst));
++P(sym_lookup,struct symbol *,(const char *name, int flags));
+ P(sym_find,struct symbol *,(const char *name));
+ P(sym_re_search,struct symbol **,(const char *pattern));
+ P(sym_type_name,const char *,(enum symbol_type type));
+diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c
+index 4946bd0..616c601 100644
+--- a/scripts/kconfig/lxdialog/inputbox.c
++++ b/scripts/kconfig/lxdialog/inputbox.c
+@@ -89,7 +89,7 @@ do_resize:
+ box_y = y + 2;
+ box_x = (width - box_width) / 2;
+ draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2,
+- dlg.border.atr, dlg.dialog.atr);
++ dlg.dialog.atr, dlg.border.atr);
+
+ print_buttons(dialog, height, width, 0);
+
+diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
+index 606ceb9..07ff8d1 100644
+--- a/scripts/kconfig/menu.c
++++ b/scripts/kconfig/menu.c
+@@ -235,18 +235,22 @@ void menu_finalize(struct menu *parent)
+ sym = parent->sym;
+ if (parent->list) {
+ if (sym && sym_is_choice(sym)) {
+- /* find the first choice value and find out choice type */
+- for (menu = parent->list; menu; menu = menu->next) {
+- if (menu->sym) {
+- current_entry = parent;
+- if (sym->type == S_UNKNOWN)
++ if (sym->type == S_UNKNOWN) {
++ /* find the first choice value to find out choice type */
++ current_entry = parent;
++ for (menu = parent->list; menu; menu = menu->next) {
++ if (menu->sym && menu->sym->type != S_UNKNOWN) {
+ menu_set_type(menu->sym->type);
+- current_entry = menu;
+- if (menu->sym->type == S_UNKNOWN)
+- menu_set_type(sym->type);
+- break;
++ break;
++ }
+ }
+ }
++ /* set the type of the remaining choice values */
++ for (menu = parent->list; menu; menu = menu->next) {
++ current_entry = menu;
++ if (menu->sym && menu->sym->type == S_UNKNOWN)
++ menu_set_type(sym->type);
++ }
+ parentdep = expr_alloc_symbol(sym);
+ } else if (parent->prompt)
+ parentdep = parent->prompt->visible.expr;
+@@ -313,50 +317,36 @@ void menu_finalize(struct menu *parent)
+ }
+ }
+ for (menu = parent->list; menu; menu = menu->next) {
+- if (sym && sym_is_choice(sym) && menu->sym) {
++ if (sym && sym_is_choice(sym) &&
++ menu->sym && !sym_is_choice_value(menu->sym)) {
++ current_entry = menu;
+ menu->sym->flags |= SYMBOL_CHOICEVAL;
+ if (!menu->prompt)
+ menu_warn(menu, "choice value must have a prompt");
+ for (prop = menu->sym->prop; prop; prop = prop->next) {
+- if (prop->type == P_PROMPT && prop->menu != menu) {
+- prop_warn(prop, "choice values "
+- "currently only support a "
+- "single prompt");
+- }
+ if (prop->type == P_DEFAULT)
+ prop_warn(prop, "defaults for choice "
+- "values not supported");
++ "values not supported");
++ if (prop->menu == menu)
++ continue;
++ if (prop->type == P_PROMPT &&
++ prop->menu->parent->sym != sym)
++ prop_warn(prop, "choice value used outside its choice group");
+ }
+- current_entry = menu;
+- if (menu->sym->type == S_UNKNOWN)
+- menu_set_type(sym->type);
+ /* Non-tristate choice values of tristate choices must
+ * depend on the choice being set to Y. The choice
+ * values' dependencies were propagated to their
+ * properties above, so the change here must be re-
+- * propagated. */
++ * propagated.
++ */
+ if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) {
+ basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes);
+- basedep = expr_alloc_and(basedep, menu->dep);
+- basedep = expr_eliminate_dups(basedep);
+- menu->dep = basedep;
++ menu->dep = expr_alloc_and(basedep, menu->dep);
+ for (prop = menu->sym->prop; prop; prop = prop->next) {
+ if (prop->menu != menu)
+ continue;
+- dep = expr_alloc_and(expr_copy(basedep),
+- prop->visible.expr);
+- dep = expr_eliminate_dups(dep);
+- dep = expr_trans_bool(dep);
+- prop->visible.expr = dep;
+- if (prop->type == P_SELECT) {
+- struct symbol *es = prop_get_symbol(prop);
+- dep2 = expr_alloc_symbol(menu->sym);
+- dep = expr_alloc_and(dep2,
+- expr_copy(dep));
+- dep = expr_alloc_or(es->rev_dep.expr, dep);
+- dep = expr_eliminate_dups(dep);
+- es->rev_dep.expr = dep;
+- }
++ prop->visible.expr = expr_alloc_and(expr_copy(basedep),
++ prop->visible.expr);
+ }
+ }
+ menu_add_symbol(P_CHOICE, sym, NULL);
+diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
+index 4a03191..18f3e5c 100644
+--- a/scripts/kconfig/symbol.c
++++ b/scripts/kconfig/symbol.c
+@@ -40,7 +40,7 @@ void sym_add_default(struct symbol *sym, const char *def)
+ {
+ struct property *prop = prop_alloc(P_DEFAULT, sym);
+
+- prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
++ prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));
+ }
+
+ void sym_init(void)
+@@ -350,9 +350,6 @@ void sym_calc_value(struct symbol *sym)
+ ;
+ }
+
+- if (sym->flags & SYMBOL_AUTO)
+- sym->flags &= ~SYMBOL_WRITE;
+-
+ sym->curr = newval;
+ if (sym_is_choice(sym) && newval.tri == yes)
+ sym->curr.val = sym_calc_choice(sym);
+@@ -377,6 +374,9 @@ void sym_calc_value(struct symbol *sym)
+ sym_set_changed(choice_sym);
+ }
+ }
++
++ if (sym->flags & SYMBOL_AUTO)
++ sym->flags &= ~SYMBOL_WRITE;
+ }
+
+ void sym_clear_all_valid(void)
+@@ -651,7 +651,7 @@ bool sym_is_changable(struct symbol *sym)
+ return sym->visible > sym->rev_dep.tri;
+ }
+
+-struct symbol *sym_lookup(const char *name, int isconst)
++struct symbol *sym_lookup(const char *name, int flags)
+ {
+ struct symbol *symbol;
+ const char *ptr;
+@@ -671,11 +671,10 @@ struct symbol *sym_lookup(const char *name, int isconst)
+ hash &= 0xff;
+
+ for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
+- if (!strcmp(symbol->name, name)) {
+- if ((isconst && symbol->flags & SYMBOL_CONST) ||
+- (!isconst && !(symbol->flags & SYMBOL_CONST)))
+- return symbol;
+- }
++ if (!strcmp(symbol->name, name) &&
++ (flags ? symbol->flags & flags
++ : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
++ return symbol;
+ }
+ new_name = strdup(name);
+ } else {
+@@ -687,8 +686,7 @@ struct symbol *sym_lookup(const char *name, int isconst)
+ memset(symbol, 0, sizeof(*symbol));
+ symbol->name = new_name;
+ symbol->type = S_UNKNOWN;
+- if (isconst)
+- symbol->flags |= SYMBOL_CONST;
++ symbol->flags |= flags;
+
+ symbol->next = symbol_hash[hash];
+ symbol_hash[hash] = symbol;
+@@ -762,8 +760,6 @@ struct symbol **sym_re_search(const char *pattern)
+ }
+
+
+-struct symbol *sym_check_deps(struct symbol *sym);
+-
+ static struct symbol *sym_check_expr_deps(struct expr *e)
+ {
+ struct symbol *sym;
+@@ -795,40 +791,100 @@ static struct symbol *sym_check_expr_deps(struct expr *e)
+ }
+
+ /* return NULL when dependencies are OK */
+-struct symbol *sym_check_deps(struct symbol *sym)
++static struct symbol *sym_check_sym_deps(struct symbol *sym)
+ {
+ struct symbol *sym2;
+ struct property *prop;
+
+- if (sym->flags & SYMBOL_CHECK) {
+- fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
+- sym->prop->file->name, sym->prop->lineno, sym->name);
+- return sym;
+- }
+- if (sym->flags & SYMBOL_CHECKED)
+- return NULL;
+-
+- sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
+ sym2 = sym_check_expr_deps(sym->rev_dep.expr);
+ if (sym2)
+- goto out;
++ return sym2;
+
+ for (prop = sym->prop; prop; prop = prop->next) {
+ if (prop->type == P_CHOICE || prop->type == P_SELECT)
+ continue;
+ sym2 = sym_check_expr_deps(prop->visible.expr);
+ if (sym2)
+- goto out;
++ break;
+ if (prop->type != P_DEFAULT || sym_is_choice(sym))
+ continue;
+ sym2 = sym_check_expr_deps(prop->expr);
+ if (sym2)
+- goto out;
++ break;
+ }
+-out:
++
++ return sym2;
++}
++
++static struct symbol *sym_check_choice_deps(struct symbol *choice)
++{
++ struct symbol *sym, *sym2;
++ struct property *prop;
++ struct expr *e;
++
++ prop = sym_get_choice_prop(choice);
++ expr_list_for_each_sym(prop->expr, e, sym)
++ sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
++
++ choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
++ sym2 = sym_check_sym_deps(choice);
++ choice->flags &= ~SYMBOL_CHECK;
+ if (sym2)
+- fprintf(stderr, " -> %s%s", sym->name, sym2 == sym? "\n": "");
+- sym->flags &= ~SYMBOL_CHECK;
++ goto out;
++
++ expr_list_for_each_sym(prop->expr, e, sym) {
++ sym2 = sym_check_sym_deps(sym);
++ if (sym2) {
++ fprintf(stderr, " -> %s", sym->name);
++ break;
++ }
++ }
++out:
++ expr_list_for_each_sym(prop->expr, e, sym)
++ sym->flags &= ~SYMBOL_CHECK;
++
++ if (sym2 && sym_is_choice_value(sym2) &&
++ prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
++ sym2 = choice;
++
++ return sym2;
++}
++
++struct symbol *sym_check_deps(struct symbol *sym)
++{
++ struct symbol *sym2;
++ struct property *prop;
++
++ if (sym->flags & SYMBOL_CHECK) {
++ fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
++ sym->prop->file->name, sym->prop->lineno,
++ sym->name ? sym->name : "<choice>");
++ return sym;
++ }
++ if (sym->flags & SYMBOL_CHECKED)
++ return NULL;
++
++ if (sym_is_choice_value(sym)) {
++ /* for choice groups start the check with main choice symbol */
++ prop = sym_get_choice_prop(sym);
++ sym2 = sym_check_deps(prop_get_symbol(prop));
++ } else if (sym_is_choice(sym)) {
++ sym2 = sym_check_choice_deps(sym);
++ } else {
++ sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
++ sym2 = sym_check_sym_deps(sym);
++ sym->flags &= ~SYMBOL_CHECK;
++ }
++
++ if (sym2) {
++ fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>");
++ if (sym2 == sym) {
++ fprintf(stderr, "\n");
++ zconfnerrs++;
++ sym2 = NULL;
++ }
++ }
++
+ return sym2;
+ }
+
+@@ -904,7 +960,7 @@ void prop_add_env(const char *env)
+ }
+
+ prop = prop_alloc(P_ENV, sym);
+- prop->expr = expr_alloc_symbol(sym_lookup(env, 1));
++ prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
+
+ sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
+ sym_env_list->right.sym = sym;
+diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
+index d22d924..95df833 100644
+--- a/scripts/kconfig/zconf.tab.c_shipped
++++ b/scripts/kconfig/zconf.tab.c_shipped
+@@ -446,16 +446,16 @@ union yyalloc
+ /* YYFINAL -- State number of the termination state. */
+ #define YYFINAL 3
+ /* YYLAST -- Last index in YYTABLE. */
+-#define YYLAST 258
++#define YYLAST 259
+
+ /* YYNTOKENS -- Number of terminals. */
+ #define YYNTOKENS 35
+ /* YYNNTS -- Number of nonterminals. */
+-#define YYNNTS 45
++#define YYNNTS 46
+ /* YYNRULES -- Number of rules. */
+-#define YYNRULES 108
++#define YYNRULES 110
+ /* YYNRULES -- Number of states. */
+-#define YYNSTATES 178
++#define YYNSTATES 180
+
+ /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+ #define YYUNDEFTOK 2
+@@ -507,13 +507,14 @@ static const yytype_uint16 yyprhs[] =
+ 28, 33, 37, 39, 41, 43, 45, 47, 49, 51,
+ 53, 55, 57, 59, 61, 63, 67, 70, 74, 77,
+ 81, 84, 85, 88, 91, 94, 97, 100, 103, 107,
+- 112, 117, 122, 128, 132, 133, 137, 138, 141, 144,
+- 147, 149, 153, 154, 157, 160, 163, 166, 169, 174,
+- 178, 181, 186, 187, 190, 194, 196, 200, 201, 204,
+- 207, 210, 214, 217, 219, 223, 224, 227, 230, 233,
+- 237, 241, 244, 247, 250, 251, 254, 257, 260, 265,
+- 266, 269, 271, 273, 276, 279, 282, 284, 287, 288,
+- 291, 293, 297, 301, 305, 308, 312, 316, 318
++ 112, 117, 122, 128, 132, 133, 137, 138, 141, 145,
++ 148, 150, 154, 155, 158, 161, 164, 167, 170, 175,
++ 179, 182, 187, 188, 191, 195, 197, 201, 202, 205,
++ 208, 211, 215, 218, 220, 224, 225, 228, 231, 234,
++ 238, 242, 245, 248, 251, 252, 255, 258, 261, 266,
++ 267, 270, 272, 274, 277, 280, 283, 285, 288, 289,
++ 292, 294, 298, 302, 306, 309, 313, 317, 319, 321,
++ 322
+ };
+
+ /* YYRHS -- A `-1'-separated list of the rules' RHS. */
+@@ -533,24 +534,25 @@ static const yytype_int8 yyrhs[] =
+ 30, -1, 20, 78, 77, 30, -1, 21, 25, 77,
+ 30, -1, 22, 79, 79, 77, 30, -1, 23, 48,
+ 30, -1, -1, 48, 25, 49, -1, -1, 33, 74,
+- -1, 7, 30, -1, 50, 54, -1, 75, -1, 51,
+- 56, 52, -1, -1, 54, 55, -1, 54, 72, -1,
+- 54, 70, -1, 54, 30, -1, 54, 40, -1, 18,
+- 74, 77, 30, -1, 19, 73, 30, -1, 17, 30,
+- -1, 20, 25, 77, 30, -1, -1, 56, 39, -1,
+- 14, 78, 76, -1, 75, -1, 57, 60, 58, -1,
+- -1, 60, 39, -1, 60, 64, -1, 60, 53, -1,
+- 4, 74, 30, -1, 61, 71, -1, 75, -1, 62,
+- 65, 63, -1, -1, 65, 39, -1, 65, 64, -1,
+- 65, 53, -1, 6, 74, 30, -1, 9, 74, 30,
+- -1, 67, 71, -1, 12, 30, -1, 69, 13, -1,
+- -1, 71, 72, -1, 71, 30, -1, 71, 40, -1,
+- 16, 24, 78, 30, -1, -1, 74, 77, -1, 25,
+- -1, 26, -1, 5, 30, -1, 8, 30, -1, 15,
+- 30, -1, 30, -1, 76, 30, -1, -1, 14, 78,
+- -1, 79, -1, 79, 33, 79, -1, 79, 27, 79,
+- -1, 29, 78, 28, -1, 34, 78, -1, 78, 31,
+- 78, -1, 78, 32, 78, -1, 25, -1, 26, -1
++ -1, 7, 80, 30, -1, 50, 54, -1, 75, -1,
++ 51, 56, 52, -1, -1, 54, 55, -1, 54, 72,
++ -1, 54, 70, -1, 54, 30, -1, 54, 40, -1,
++ 18, 74, 77, 30, -1, 19, 73, 30, -1, 17,
++ 30, -1, 20, 25, 77, 30, -1, -1, 56, 39,
++ -1, 14, 78, 76, -1, 75, -1, 57, 60, 58,
++ -1, -1, 60, 39, -1, 60, 64, -1, 60, 53,
++ -1, 4, 74, 30, -1, 61, 71, -1, 75, -1,
++ 62, 65, 63, -1, -1, 65, 39, -1, 65, 64,
++ -1, 65, 53, -1, 6, 74, 30, -1, 9, 74,
++ 30, -1, 67, 71, -1, 12, 30, -1, 69, 13,
++ -1, -1, 71, 72, -1, 71, 30, -1, 71, 40,
++ -1, 16, 24, 78, 30, -1, -1, 74, 77, -1,
++ 25, -1, 26, -1, 5, 30, -1, 8, 30, -1,
++ 15, 30, -1, 30, -1, 76, 30, -1, -1, 14,
++ 78, -1, 79, -1, 79, 33, 79, -1, 79, 27,
++ 79, -1, 29, 78, 28, -1, 34, 78, -1, 78,
++ 31, 78, -1, 78, 32, 78, -1, 25, -1, 26,
++ -1, -1, 25, -1
+ };
+
+ /* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+@@ -566,7 +568,8 @@ static const yytype_uint16 yyrline[] =
+ 339, 344, 351, 356, 364, 367, 369, 370, 371, 374,
+ 382, 389, 396, 402, 409, 411, 412, 413, 416, 424,
+ 426, 431, 432, 435, 436, 437, 441, 442, 445, 446,
+- 449, 450, 451, 452, 453, 454, 455, 458, 459
++ 449, 450, 451, 452, 453, 454, 455, 458, 459, 462,
++ 463
+ };
+ #endif
+
+@@ -590,7 +593,8 @@ static const char *const yytname[] =
+ "if_entry", "if_end", "if_stmt", "if_block", "menu", "menu_entry",
+ "menu_end", "menu_stmt", "menu_block", "source_stmt", "comment",
+ "comment_stmt", "help_start", "help", "depends_list", "depends",
+- "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol", 0
++ "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol",
++ "word_opt", 0
+ };
+ #endif
+
+@@ -619,7 +623,8 @@ static const yytype_uint8 yyr1[] =
+ 60, 61, 62, 63, 64, 65, 65, 65, 65, 66,
+ 67, 68, 69, 70, 71, 71, 71, 71, 72, 73,
+ 73, 74, 74, 75, 75, 75, 76, 76, 77, 77,
+- 78, 78, 78, 78, 78, 78, 78, 79, 79
++ 78, 78, 78, 78, 78, 78, 78, 79, 79, 80,
++ 80
+ };
+
+ /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+@@ -629,13 +634,14 @@ static const yytype_uint8 yyr2[] =
+ 4, 3, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 3, 2, 3, 2, 3,
+ 2, 0, 2, 2, 2, 2, 2, 2, 3, 4,
+- 4, 4, 5, 3, 0, 3, 0, 2, 2, 2,
++ 4, 4, 5, 3, 0, 3, 0, 2, 3, 2,
+ 1, 3, 0, 2, 2, 2, 2, 2, 4, 3,
+ 2, 4, 0, 2, 3, 1, 3, 0, 2, 2,
+ 2, 3, 2, 1, 3, 0, 2, 2, 2, 3,
+ 3, 2, 2, 2, 0, 2, 2, 2, 4, 0,
+ 2, 1, 1, 2, 2, 2, 1, 2, 0, 2,
+- 1, 3, 3, 3, 2, 3, 3, 1, 1
++ 1, 3, 3, 3, 2, 3, 3, 1, 1, 0,
++ 1
+ };
+
+ /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+@@ -643,69 +649,69 @@ static const yytype_uint8 yyr2[] =
+ means the default is an error. */
+ static const yytype_uint8 yydefact[] =
+ {
+- 3, 0, 0, 1, 0, 0, 0, 0, 0, 0,
++ 3, 0, 0, 1, 0, 0, 0, 0, 0, 109,
+ 0, 0, 0, 0, 0, 0, 12, 16, 13, 14,
+ 18, 15, 17, 0, 19, 0, 4, 31, 22, 31,
+ 23, 52, 62, 5, 67, 20, 84, 75, 6, 24,
+ 84, 21, 8, 11, 91, 92, 0, 0, 93, 0,
+- 48, 94, 0, 0, 0, 107, 108, 0, 0, 0,
+- 100, 95, 0, 0, 0, 0, 0, 0, 0, 0,
+- 0, 0, 96, 7, 71, 79, 80, 27, 29, 0,
+- 104, 0, 0, 64, 0, 0, 9, 10, 0, 0,
+- 0, 0, 89, 0, 0, 0, 44, 0, 37, 36,
+- 32, 33, 0, 35, 34, 0, 0, 89, 0, 56,
+- 57, 53, 55, 54, 63, 51, 50, 68, 70, 66,
+- 69, 65, 86, 87, 85, 76, 78, 74, 77, 73,
+- 97, 103, 105, 106, 102, 101, 26, 82, 0, 98,
+- 0, 98, 98, 98, 0, 0, 0, 83, 60, 98,
+- 0, 98, 0, 0, 0, 38, 90, 0, 0, 98,
+- 46, 43, 25, 0, 59, 0, 88, 99, 39, 40,
+- 41, 0, 0, 45, 58, 61, 42, 47
++ 110, 0, 94, 0, 0, 0, 107, 108, 0, 0,
++ 0, 100, 95, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 96, 7, 71, 79, 48, 80, 27,
++ 29, 0, 104, 0, 0, 64, 0, 0, 9, 10,
++ 0, 0, 0, 0, 89, 0, 0, 0, 44, 0,
++ 37, 36, 32, 33, 0, 35, 34, 0, 0, 89,
++ 0, 56, 57, 53, 55, 54, 63, 51, 50, 68,
++ 70, 66, 69, 65, 86, 87, 85, 76, 78, 74,
++ 77, 73, 97, 103, 105, 106, 102, 101, 26, 82,
++ 0, 98, 0, 98, 98, 98, 0, 0, 0, 83,
++ 60, 98, 0, 98, 0, 0, 0, 38, 90, 0,
++ 0, 98, 46, 43, 25, 0, 59, 0, 88, 99,
++ 39, 40, 41, 0, 0, 45, 58, 61, 42, 47
+ };
+
+ /* YYDEFGOTO[NTERM-NUM]. */
+ static const yytype_int16 yydefgoto[] =
+ {
+- -1, 1, 2, 25, 26, 99, 27, 28, 29, 30,
+- 64, 100, 101, 145, 173, 31, 32, 115, 33, 66,
+- 111, 67, 34, 119, 35, 68, 36, 37, 127, 38,
+- 70, 39, 40, 41, 102, 103, 69, 104, 140, 141,
+- 42, 73, 154, 59, 60
++ -1, 1, 2, 25, 26, 101, 27, 28, 29, 30,
++ 65, 102, 103, 147, 175, 31, 32, 117, 33, 67,
++ 113, 68, 34, 121, 35, 69, 36, 37, 129, 38,
++ 71, 39, 40, 41, 104, 105, 70, 106, 142, 143,
++ 42, 74, 156, 60, 61, 51
+ };
+
+ /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+-#define YYPACT_NINF -78
++#define YYPACT_NINF -80
+ static const yytype_int16 yypact[] =
+ {
+- -78, 33, 130, -78, -28, 73, 73, 7, 73, 36,
+- 41, 73, 26, 52, -4, 58, -78, -78, -78, -78,
+- -78, -78, -78, 90, -78, 94, -78, -78, -78, -78,
+- -78, -78, -78, -78, -78, -78, -78, -78, -78, -78,
+- -78, -78, -78, -78, -78, -78, 74, 85, -78, 96,
+- -78, -78, 131, 134, 147, -78, -78, -4, -4, 193,
+- -10, -78, 162, 164, 38, 102, 64, 148, 5, 192,
+- 5, 165, -78, 174, -78, -78, -78, -78, -78, 65,
+- -78, -4, -4, 174, 103, 103, -78, -78, 175, 185,
+- 197, 73, 73, -4, 194, 103, -78, 231, -78, -78,
+- -78, -78, 220, -78, -78, 204, 73, 73, 210, -78,
+- -78, -78, -78, -78, -78, -78, -78, -78, -78, -78,
+- -78, -78, -78, -78, -78, -78, -78, -78, -78, -78,
+- -78, -78, 205, -78, -78, -78, -78, -78, -4, 222,
+- 208, 222, 195, 222, 103, 2, 209, -78, -78, 222,
+- 211, 222, 199, -4, 212, -78, -78, 213, 214, 222,
+- 207, -78, -78, 215, -78, 216, -78, 111, -78, -78,
+- -78, 217, 73, -78, -78, -78, -78, -78
++ -80, 2, 132, -80, -13, -1, -1, -2, -1, 9,
++ 33, -1, 27, 40, -3, 38, -80, -80, -80, -80,
++ -80, -80, -80, 71, -80, 77, -80, -80, -80, -80,
++ -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
++ -80, -80, -80, -80, -80, -80, 57, 61, -80, 63,
++ -80, 76, -80, 87, 101, 133, -80, -80, -3, -3,
++ 195, -6, -80, 136, 149, 39, 104, 65, 150, 5,
++ 194, 5, 167, -80, 176, -80, -80, -80, -80, -80,
++ -80, 68, -80, -3, -3, 176, 72, 72, -80, -80,
++ 177, 187, 78, -1, -1, -3, 196, 72, -80, 222,
++ -80, -80, -80, -80, 221, -80, -80, 205, -1, -1,
++ 211, -80, -80, -80, -80, -80, -80, -80, -80, -80,
++ -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
++ -80, -80, -80, -80, 206, -80, -80, -80, -80, -80,
++ -3, 223, 209, 223, 197, 223, 72, 7, 210, -80,
++ -80, 223, 212, 223, 201, -3, 213, -80, -80, 214,
++ 215, 223, 208, -80, -80, 216, -80, 217, -80, 113,
++ -80, -80, -80, 218, -1, -80, -80, -80, -80, -80
+ };
+
+ /* YYPGOTO[NTERM-NUM]. */
+ static const yytype_int16 yypgoto[] =
+ {
+- -78, -78, -78, -78, 121, -35, -78, -78, -78, -78,
+- 219, -78, -78, -78, -78, -78, -78, -78, -44, -78,
+- -78, -78, -78, -78, -78, -78, -78, -78, -78, -6,
+- -78, -78, -78, -78, -78, 183, 218, 21, 143, -5,
+- 146, 196, 69, -53, -77
++ -80, -80, -80, -80, 122, -34, -80, -80, -80, -80,
++ 220, -80, -80, -80, -80, -80, -80, -80, 59, -80,
++ -80, -80, -80, -80, -80, -80, -80, -80, -80, 125,
++ -80, -80, -80, -80, -80, 183, 219, 22, 142, -5,
++ 147, 192, 69, -54, -79, -80
+ };
+
+ /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+@@ -715,62 +721,62 @@ static const yytype_int16 yypgoto[] =
+ #define YYTABLE_NINF -82
+ static const yytype_int16 yytable[] =
+ {
+- 46, 47, 43, 49, 79, 80, 52, 134, 135, 6,
+- 7, 8, 9, 10, 11, 12, 13, 84, 144, 14,
+- 15, 55, 56, 85, 118, 57, 126, 160, 132, 133,
+- 58, 110, 161, 3, 123, 24, 123, 48, -28, 88,
+- 142, -28, -28, -28, -28, -28, -28, -28, -28, -28,
+- 89, 53, -28, -28, 90, -28, 91, 92, 93, 94,
+- 95, 96, 120, 97, 128, 88, 50, 159, 98, -49,
+- -49, 51, -49, -49, -49, -49, 89, 54, -49, -49,
+- 90, 105, 106, 107, 108, 152, 139, 113, 61, 97,
+- 124, 62, 124, 131, 109, 63, 81, 82, 44, 45,
+- 167, 149, -30, 88, 72, -30, -30, -30, -30, -30,
+- -30, -30, -30, -30, 89, 74, -30, -30, 90, -30,
+- 91, 92, 93, 94, 95, 96, 75, 97, 55, 56,
+- -2, 4, 98, 5, 6, 7, 8, 9, 10, 11,
+- 12, 13, 81, 82, 14, 15, 16, 17, 18, 19,
+- 20, 21, 22, 7, 8, 23, 10, 11, 12, 13,
+- 24, 76, 14, 15, 77, -81, 88, 177, -81, -81,
+- -81, -81, -81, -81, -81, -81, -81, 78, 24, -81,
+- -81, 90, -81, -81, -81, -81, -81, -81, 114, 117,
+- 97, 125, 86, 88, 87, 122, -72, -72, -72, -72,
+- -72, -72, -72, -72, 130, 136, -72, -72, 90, 153,
+- 156, 157, 158, 116, 121, 137, 129, 97, 163, 143,
+- 165, 138, 122, 72, 81, 82, 81, 82, 171, 166,
+- 81, 82, 146, 147, 148, 151, 153, 82, 155, 162,
+- 172, 164, 168, 169, 170, 174, 175, 176, 65, 112,
+- 150, 0, 0, 0, 0, 83, 0, 0, 71
++ 46, 47, 3, 49, 81, 82, 53, 136, 137, 6,
++ 7, 8, 9, 10, 11, 12, 13, 43, 146, 14,
++ 15, 86, 56, 57, 44, 45, 58, 87, 48, 134,
++ 135, 59, 162, 112, 50, 24, 125, 163, 125, -28,
++ 90, 144, -28, -28, -28, -28, -28, -28, -28, -28,
++ -28, 91, 54, -28, -28, 92, -28, 93, 94, 95,
++ 96, 97, 98, 52, 99, 55, 90, 161, 62, 100,
++ -49, -49, 63, -49, -49, -49, -49, 91, 64, -49,
++ -49, 92, 107, 108, 109, 110, 154, 73, 141, 115,
++ 99, 75, 126, 76, 126, 111, 133, 56, 57, 83,
++ 84, 169, 140, 151, -30, 90, 77, -30, -30, -30,
++ -30, -30, -30, -30, -30, -30, 91, 78, -30, -30,
++ 92, -30, 93, 94, 95, 96, 97, 98, 120, 99,
++ 128, 79, -2, 4, 100, 5, 6, 7, 8, 9,
++ 10, 11, 12, 13, 83, 84, 14, 15, 16, 17,
++ 18, 19, 20, 21, 22, 7, 8, 23, 10, 11,
++ 12, 13, 24, 80, 14, 15, 88, -81, 90, 179,
++ -81, -81, -81, -81, -81, -81, -81, -81, -81, 89,
++ 24, -81, -81, 92, -81, -81, -81, -81, -81, -81,
++ 116, 119, 99, 127, 122, 90, 130, 124, -72, -72,
++ -72, -72, -72, -72, -72, -72, 132, 138, -72, -72,
++ 92, 155, 158, 159, 160, 118, 123, 139, 131, 99,
++ 165, 145, 167, 148, 124, 73, 83, 84, 83, 84,
++ 173, 168, 83, 84, 149, 150, 153, 155, 84, 157,
++ 164, 174, 166, 170, 171, 172, 176, 177, 178, 66,
++ 114, 152, 85, 0, 0, 0, 0, 0, 0, 72
+ };
+
+ static const yytype_int16 yycheck[] =
+ {
+- 5, 6, 30, 8, 57, 58, 11, 84, 85, 4,
+- 5, 6, 7, 8, 9, 10, 11, 27, 95, 14,
+- 15, 25, 26, 33, 68, 29, 70, 25, 81, 82,
+- 34, 66, 30, 0, 69, 30, 71, 30, 0, 1,
+- 93, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+- 12, 25, 14, 15, 16, 17, 18, 19, 20, 21,
+- 22, 23, 68, 25, 70, 1, 30, 144, 30, 5,
+- 6, 30, 8, 9, 10, 11, 12, 25, 14, 15,
+- 16, 17, 18, 19, 20, 138, 91, 66, 30, 25,
+- 69, 1, 71, 28, 30, 1, 31, 32, 25, 26,
+- 153, 106, 0, 1, 30, 3, 4, 5, 6, 7,
+- 8, 9, 10, 11, 12, 30, 14, 15, 16, 17,
+- 18, 19, 20, 21, 22, 23, 30, 25, 25, 26,
+- 0, 1, 30, 3, 4, 5, 6, 7, 8, 9,
+- 10, 11, 31, 32, 14, 15, 16, 17, 18, 19,
+- 20, 21, 22, 5, 6, 25, 8, 9, 10, 11,
+- 30, 30, 14, 15, 30, 0, 1, 172, 3, 4,
+- 5, 6, 7, 8, 9, 10, 11, 30, 30, 14,
+- 15, 16, 17, 18, 19, 20, 21, 22, 67, 68,
+- 25, 70, 30, 1, 30, 30, 4, 5, 6, 7,
+- 8, 9, 10, 11, 30, 30, 14, 15, 16, 14,
+- 141, 142, 143, 67, 68, 30, 70, 25, 149, 25,
+- 151, 24, 30, 30, 31, 32, 31, 32, 159, 30,
+- 31, 32, 1, 13, 30, 25, 14, 32, 30, 30,
+- 33, 30, 30, 30, 30, 30, 30, 30, 29, 66,
+- 107, -1, -1, -1, -1, 59, -1, -1, 40
++ 5, 6, 0, 8, 58, 59, 11, 86, 87, 4,
++ 5, 6, 7, 8, 9, 10, 11, 30, 97, 14,
++ 15, 27, 25, 26, 25, 26, 29, 33, 30, 83,
++ 84, 34, 25, 67, 25, 30, 70, 30, 72, 0,
++ 1, 95, 3, 4, 5, 6, 7, 8, 9, 10,
++ 11, 12, 25, 14, 15, 16, 17, 18, 19, 20,
++ 21, 22, 23, 30, 25, 25, 1, 146, 30, 30,
++ 5, 6, 1, 8, 9, 10, 11, 12, 1, 14,
++ 15, 16, 17, 18, 19, 20, 140, 30, 93, 67,
++ 25, 30, 70, 30, 72, 30, 28, 25, 26, 31,
++ 32, 155, 24, 108, 0, 1, 30, 3, 4, 5,
++ 6, 7, 8, 9, 10, 11, 12, 30, 14, 15,
++ 16, 17, 18, 19, 20, 21, 22, 23, 69, 25,
++ 71, 30, 0, 1, 30, 3, 4, 5, 6, 7,
++ 8, 9, 10, 11, 31, 32, 14, 15, 16, 17,
++ 18, 19, 20, 21, 22, 5, 6, 25, 8, 9,
++ 10, 11, 30, 30, 14, 15, 30, 0, 1, 174,
++ 3, 4, 5, 6, 7, 8, 9, 10, 11, 30,
++ 30, 14, 15, 16, 17, 18, 19, 20, 21, 22,
++ 68, 69, 25, 71, 69, 1, 71, 30, 4, 5,
++ 6, 7, 8, 9, 10, 11, 30, 30, 14, 15,
++ 16, 14, 143, 144, 145, 68, 69, 30, 71, 25,
++ 151, 25, 153, 1, 30, 30, 31, 32, 31, 32,
++ 161, 30, 31, 32, 13, 30, 25, 14, 32, 30,
++ 30, 33, 30, 30, 30, 30, 30, 30, 30, 29,
++ 67, 109, 60, -1, -1, -1, -1, -1, -1, 40
+ };
+
+ /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+@@ -782,19 +788,19 @@ static const yytype_uint8 yystos[] =
+ 20, 21, 22, 25, 30, 38, 39, 41, 42, 43,
+ 44, 50, 51, 53, 57, 59, 61, 62, 64, 66,
+ 67, 68, 75, 30, 25, 26, 74, 74, 30, 74,
+- 30, 30, 74, 25, 25, 25, 26, 29, 34, 78,
+- 79, 30, 1, 1, 45, 45, 54, 56, 60, 71,
+- 65, 71, 30, 76, 30, 30, 30, 30, 30, 78,
+- 78, 31, 32, 76, 27, 33, 30, 30, 1, 12,
+- 16, 18, 19, 20, 21, 22, 23, 25, 30, 40,
+- 46, 47, 69, 70, 72, 17, 18, 19, 20, 30,
+- 40, 55, 70, 72, 39, 52, 75, 39, 53, 58,
+- 64, 75, 30, 40, 72, 39, 53, 63, 64, 75,
+- 30, 28, 78, 78, 79, 79, 30, 30, 24, 74,
+- 73, 74, 78, 25, 79, 48, 1, 13, 30, 74,
+- 73, 25, 78, 14, 77, 30, 77, 77, 77, 79,
+- 25, 30, 30, 77, 30, 77, 30, 78, 30, 30,
+- 30, 77, 33, 49, 30, 30, 30, 74
++ 25, 80, 30, 74, 25, 25, 25, 26, 29, 34,
++ 78, 79, 30, 1, 1, 45, 45, 54, 56, 60,
++ 71, 65, 71, 30, 76, 30, 30, 30, 30, 30,
++ 30, 78, 78, 31, 32, 76, 27, 33, 30, 30,
++ 1, 12, 16, 18, 19, 20, 21, 22, 23, 25,
++ 30, 40, 46, 47, 69, 70, 72, 17, 18, 19,
++ 20, 30, 40, 55, 70, 72, 39, 52, 75, 39,
++ 53, 58, 64, 75, 30, 40, 72, 39, 53, 63,
++ 64, 75, 30, 28, 78, 78, 79, 79, 30, 30,
++ 24, 74, 73, 74, 78, 25, 79, 48, 1, 13,
++ 30, 74, 73, 25, 78, 14, 77, 30, 77, 77,
++ 77, 79, 25, 30, 30, 77, 30, 77, 30, 78,
++ 30, 30, 30, 77, 33, 49, 30, 30, 30, 74
+ };
+
+ #define yyerrok (yyerrstatus = 0)
+@@ -1781,8 +1787,8 @@ yyreduce:
+ case 48:
+
+ {
+- struct symbol *sym = sym_lookup(NULL, 0);
+- sym->flags |= SYMBOL_CHOICE;
++ struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE);
++ sym->flags |= SYMBOL_AUTO;
+ menu_add_entry(sym);
+ menu_add_expr(P_CHOICE, NULL, NULL);
+ printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
+@@ -2014,7 +2020,12 @@ yyreduce:
+
+ case 108:
+
+- { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 1); free((yyvsp[(1) - (1)].string)); ;}
++ { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;}
++ break;
++
++ case 109:
++
++ { (yyval.string) = NULL; ;}
+ break;
+
+
+diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
+index d9b96ba..9710b82 100644
+--- a/scripts/kconfig/zconf.y
++++ b/scripts/kconfig/zconf.y
+@@ -91,7 +91,7 @@ static struct menu *current_menu, *current_entry;
+ %type <id> end
+ %type <id> option_name
+ %type <menu> if_entry menu_entry choice_entry
+-%type <string> symbol_option_arg
++%type <string> symbol_option_arg word_opt
+
+ %destructor {
+ fprintf(stderr, "%s:%d: missing end statement for this entry\n",
+@@ -239,10 +239,10 @@ symbol_option_arg:
+
+ /* choice entry */
+
+-choice: T_CHOICE T_EOL
++choice: T_CHOICE word_opt T_EOL
+ {
+- struct symbol *sym = sym_lookup(NULL, 0);
+- sym->flags |= SYMBOL_CHOICE;
++ struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);
++ sym->flags |= SYMBOL_AUTO;
+ menu_add_entry(sym);
+ menu_add_expr(P_CHOICE, NULL, NULL);
+ printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
+@@ -456,9 +456,12 @@ expr: symbol { $$ = expr_alloc_symbol($1); }
+ ;
+
+ symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
+- | T_WORD_QUOTE { $$ = sym_lookup($1, 1); free($1); }
++ | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
+ ;
+
++word_opt: /* empty */ { $$ = NULL; }
++ | T_WORD
++
+ %%
+
+ void conf_parse(const char *name)
+diff --git a/scripts/kernel-doc b/scripts/kernel-doc
+index 263d04a..83cee18 100755
+--- a/scripts/kernel-doc
++++ b/scripts/kernel-doc
+@@ -5,7 +5,7 @@ use strict;
+ ## Copyright (c) 1998 Michael Zucchi, All Rights Reserved ##
+ ## Copyright (C) 2000, 1 Tim Waugh <twaugh at redhat.com> ##
+ ## Copyright (C) 2001 Simon Huggins ##
+-## Copyright (C) 2005-2007 Randy Dunlap ##
++## Copyright (C) 2005-2008 Randy Dunlap ##
+ ## ##
+ ## #define enhancements by Armin Kuster <akuster at mvista.com> ##
+ ## Copyright (c) 2000 MontaVista Software, Inc. ##
+@@ -366,6 +366,7 @@ foreach my $pattern (keys %highlights) {
+ # dumps section contents to arrays/hashes intended for that purpose.
+ #
+ sub dump_section {
++ my $file = shift;
+ my $name = shift;
+ my $contents = join "\n", @_;
+
+@@ -379,6 +380,10 @@ sub dump_section {
+ $parameterdescs{$name} = $contents;
+ } else {
+ # print STDERR "other section '$name' = '$contents'\n";
++ if (defined($sections{$name}) && ($sections{$name} ne "")) {
++ print STDERR "Error(${file}:$.): duplicate section name '$name'\n";
++ ++$errors;
++ }
+ $sections{$name} = $contents;
+ push @sectionlist, $name;
+ }
+@@ -388,6 +393,7 @@ sub dump_section {
+ # dump DOC: section after checking that it should go out
+ #
+ sub dump_doc_section {
++ my $file = shift;
+ my $name = shift;
+ my $contents = join "\n", @_;
+
+@@ -399,7 +405,7 @@ sub dump_doc_section {
+ ( $function_only == 1 && defined($function_table{$name})) ||
+ ( $function_only == 2 && !defined($function_table{$name})))
+ {
+- dump_section $name, $contents;
++ dump_section($file, $name, $contents);
+ output_blockhead({'sectionlist' => \@sectionlist,
+ 'sections' => \%sections,
+ 'module' => $modulename,
+@@ -1923,7 +1929,7 @@ sub process_file($) {
+ print STDERR "Warning(${file}:$.): contents before sections\n";
+ ++$warnings;
+ }
+- dump_section($section, xml_escape($contents));
++ dump_section($file, $section, xml_escape($contents));
+ $section = $section_default;
+ }
+
+@@ -1940,10 +1946,15 @@ sub process_file($) {
+ } elsif (/$doc_end/) {
+
+ if ($contents ne "") {
+- dump_section($section, xml_escape($contents));
++ dump_section($file, $section, xml_escape($contents));
+ $section = $section_default;
+ $contents = "";
+ }
++ # look for doc_com + <text> + doc_end:
++ if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') {
++ print STDERR "Warning(${file}:$.): suspicious ending line: $_";
++ ++$warnings;
++ }
+
+ $prototype = "";
+ $state = 3;
+@@ -1954,7 +1965,7 @@ sub process_file($) {
+ # @parameter line to signify start of description
+ if ($1 eq "" &&
+ ($section =~ m/^@/ || $section eq $section_context)) {
+- dump_section($section, xml_escape($contents));
++ dump_section($file, $section, xml_escape($contents));
+ $section = $section_default;
+ $contents = "";
+ } else {
+@@ -1974,7 +1985,7 @@ sub process_file($) {
+ } elsif ($state == 4) {
+ # Documentation block
+ if (/$doc_block/) {
+- dump_doc_section($section, xml_escape($contents));
++ dump_doc_section($file, $section, xml_escape($contents));
+ $contents = "";
+ $function = "";
+ %constants = ();
+@@ -1992,7 +2003,7 @@ sub process_file($) {
+ }
+ elsif (/$doc_end/)
+ {
+- dump_doc_section($section, xml_escape($contents));
++ dump_doc_section($file, $section, xml_escape($contents));
+ $contents = "";
+ $function = "";
+ %constants = ();
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
-index 348d868..769b69d 100644
+index 348d868..e04c421 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -328,19 +328,52 @@ static int do_pnp_entry(const char *filename,
@@ -923898,7 +1225905,23 @@
}
/* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */
-@@ -634,9 +667,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
+@@ -543,6 +576,15 @@ static int do_virtio_entry(const char *filename, struct virtio_device_id *id,
+ return 1;
+ }
+
++/* Looks like: i2c:S */
++static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
++ char *alias)
++{
++ sprintf(alias, I2C_MODULE_PREFIX "%s", id->name);
++
++ return 1;
++}
++
+ /* Ignore any prefix, eg. v850 prepends _ */
+ static inline int sym_is(const char *symbol, const char *name)
+ {
+@@ -634,9 +676,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"))
@@ -923909,18 +1225932,29 @@
else if (sym_is(symname, "__mod_pcmcia_device_table"))
do_table(symval, sym->st_size,
sizeof(struct pcmcia_device_id), "pcmcia",
+@@ -673,6 +713,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
+ do_table(symval, sym->st_size,
+ sizeof(struct virtio_device_id), "virtio",
+ do_virtio_entry, mod);
++ else if (sym_is(symname, "__mod_i2c_device_table"))
++ do_table(symval, sym->st_size,
++ sizeof(struct i2c_device_id), "i2c",
++ do_i2c_entry, mod);
+ free(zeros);
+ }
+
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
-index 110cf24..f8b42ab 100644
+index 110cf24..757294b 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);
++ if (info.modinfo && !license && !is_vmlinux(modname))
++ warn("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;
@@ -923997,11 +1226031,46 @@
This value can be changed after boot using the
/proc/sys/vm/mmap_min_addr tunable.
+diff --git a/security/Makefile b/security/Makefile
+index 9e8b025..7ef1107 100644
+--- a/security/Makefile
++++ b/security/Makefile
+@@ -18,3 +18,4 @@ obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
+ obj-$(CONFIG_SECURITY_SMACK) += commoncap.o smack/built-in.o
+ obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
+ obj-$(CONFIG_SECURITY_ROOTPLUG) += commoncap.o root_plug.o
++obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
+diff --git a/security/capability.c b/security/capability.c
+index 2c6e06d..38ac54e 100644
+--- a/security/capability.c
++++ b/security/capability.c
+@@ -44,6 +44,7 @@ static struct security_operations capability_ops = {
+ .task_setioprio = cap_task_setioprio,
+ .task_setnice = cap_task_setnice,
+ .task_post_setuid = cap_task_post_setuid,
++ .task_prctl = cap_task_prctl,
+ .task_reparent_to_init = cap_task_reparent_to_init,
+
+ .syslog = cap_syslog,
diff --git a/security/commoncap.c b/security/commoncap.c
-index 06d5c94..8529057 100644
+index 06d5c94..5edabc7 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
-@@ -267,7 +267,7 @@ static int get_file_caps(struct linux_binprm *bprm)
+@@ -24,11 +24,8 @@
+ #include <linux/hugetlb.h>
+ #include <linux/mount.h>
+ #include <linux/sched.h>
+-
+-/* Global security state */
+-
+-unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
+-EXPORT_SYMBOL(securebits);
++#include <linux/prctl.h>
++#include <linux/securebits.h>
+
+ int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
+ {
+@@ -267,7 +264,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",
@@ -924010,7 +1226079,7 @@
out:
dput(dentry);
-@@ -302,7 +302,7 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
+@@ -302,7 +299,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",
@@ -924019,8 +1226088,745 @@
/* To support inheritance of root-permissions and suid-root
* executables under compatibility mode, we raise all three
+@@ -368,7 +365,7 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
+
+ /* AUD: Audit candidate if current->cap_effective is set */
+
+- current->keep_capabilities = 0;
++ current->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
+ }
+
+ int cap_bprm_secureexec (struct linux_binprm *bprm)
+@@ -386,8 +383,8 @@ int cap_bprm_secureexec (struct linux_binprm *bprm)
+ current->egid != current->gid);
+ }
+
+-int cap_inode_setxattr(struct dentry *dentry, char *name, void *value,
+- size_t size, int flags)
++int cap_inode_setxattr(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags)
+ {
+ if (!strcmp(name, XATTR_NAME_CAPS)) {
+ if (!capable(CAP_SETFCAP))
+@@ -400,7 +397,7 @@ int cap_inode_setxattr(struct dentry *dentry, char *name, void *value,
+ return 0;
+ }
+
+-int cap_inode_removexattr(struct dentry *dentry, char *name)
++int cap_inode_removexattr(struct dentry *dentry, const char *name)
+ {
+ if (!strcmp(name, XATTR_NAME_CAPS)) {
+ if (!capable(CAP_SETFCAP))
+@@ -448,7 +445,7 @@ static inline void cap_emulate_setxuid (int old_ruid, int old_euid,
+ {
+ if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) &&
+ (current->uid != 0 && current->euid != 0 && current->suid != 0) &&
+- !current->keep_capabilities) {
++ !issecure(SECURE_KEEP_CAPS)) {
+ cap_clear (current->cap_permitted);
+ cap_clear (current->cap_effective);
+ }
+@@ -547,7 +544,7 @@ int cap_task_setnice (struct task_struct *p, int nice)
+ * this task could get inconsistent info. There can be no
+ * racing writer bc a task can only change its own caps.
+ */
+-long cap_prctl_drop(unsigned long cap)
++static long cap_prctl_drop(unsigned long cap)
+ {
+ if (!capable(CAP_SETPCAP))
+ return -EPERM;
+@@ -556,6 +553,7 @@ long cap_prctl_drop(unsigned long cap)
+ cap_lower(current->cap_bset, cap);
+ return 0;
+ }
++
+ #else
+ int cap_task_setscheduler (struct task_struct *p, int policy,
+ struct sched_param *lp)
+@@ -572,12 +570,99 @@ int cap_task_setnice (struct task_struct *p, int nice)
+ }
+ #endif
+
++int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
++ unsigned long arg4, unsigned long arg5, long *rc_p)
++{
++ long error = 0;
++
++ switch (option) {
++ case PR_CAPBSET_READ:
++ if (!cap_valid(arg2))
++ error = -EINVAL;
++ else
++ error = !!cap_raised(current->cap_bset, arg2);
++ break;
++#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
++ case PR_CAPBSET_DROP:
++ error = cap_prctl_drop(arg2);
++ break;
++
++ /*
++ * The next four prctl's remain to assist with transitioning a
++ * system from legacy UID=0 based privilege (when filesystem
++ * capabilities are not in use) to a system using filesystem
++ * capabilities only - as the POSIX.1e draft intended.
++ *
++ * Note:
++ *
++ * PR_SET_SECUREBITS =
++ * issecure_mask(SECURE_KEEP_CAPS_LOCKED)
++ * | issecure_mask(SECURE_NOROOT)
++ * | issecure_mask(SECURE_NOROOT_LOCKED)
++ * | issecure_mask(SECURE_NO_SETUID_FIXUP)
++ * | issecure_mask(SECURE_NO_SETUID_FIXUP_LOCKED)
++ *
++ * will ensure that the current process and all of its
++ * children will be locked into a pure
++ * capability-based-privilege environment.
++ */
++ case PR_SET_SECUREBITS:
++ if ((((current->securebits & SECURE_ALL_LOCKS) >> 1)
++ & (current->securebits ^ arg2)) /*[1]*/
++ || ((current->securebits & SECURE_ALL_LOCKS
++ & ~arg2)) /*[2]*/
++ || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/
++ || (cap_capable(current, CAP_SETPCAP) != 0)) { /*[4]*/
++ /*
++ * [1] no changing of bits that are locked
++ * [2] no unlocking of locks
++ * [3] no setting of unsupported bits
++ * [4] doing anything requires privilege (go read about
++ * the "sendmail capabilities bug")
++ */
++ error = -EPERM; /* cannot change a locked bit */
++ } else {
++ current->securebits = arg2;
++ }
++ break;
++ case PR_GET_SECUREBITS:
++ error = current->securebits;
++ break;
++
++#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
++
++ case PR_GET_KEEPCAPS:
++ if (issecure(SECURE_KEEP_CAPS))
++ error = 1;
++ break;
++ case PR_SET_KEEPCAPS:
++ if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */
++ error = -EINVAL;
++ else if (issecure(SECURE_KEEP_CAPS_LOCKED))
++ error = -EPERM;
++ else if (arg2)
++ current->securebits |= issecure_mask(SECURE_KEEP_CAPS);
++ else
++ current->securebits &=
++ ~issecure_mask(SECURE_KEEP_CAPS);
++ break;
++
++ default:
++ /* No functionality available - continue with default */
++ return 0;
++ }
++
++ /* Functionality provided */
++ *rc_p = error;
++ return 1;
++}
++
+ void cap_task_reparent_to_init (struct task_struct *p)
+ {
+ cap_set_init_eff(p->cap_effective);
+ cap_clear(p->cap_inheritable);
+ cap_set_full(p->cap_permitted);
+- p->keep_capabilities = 0;
++ p->securebits = SECUREBITS_DEFAULT;
+ return;
+ }
+
+diff --git a/security/device_cgroup.c b/security/device_cgroup.c
+new file mode 100644
+index 0000000..4ea5836
+--- /dev/null
++++ b/security/device_cgroup.c
+@@ -0,0 +1,575 @@
++/*
++ * dev_cgroup.c - device cgroup subsystem
++ *
++ * Copyright 2007 IBM Corp
++ */
++
++#include <linux/device_cgroup.h>
++#include <linux/cgroup.h>
++#include <linux/ctype.h>
++#include <linux/list.h>
++#include <linux/uaccess.h>
++#include <linux/seq_file.h>
++
++#define ACC_MKNOD 1
++#define ACC_READ 2
++#define ACC_WRITE 4
++#define ACC_MASK (ACC_MKNOD | ACC_READ | ACC_WRITE)
++
++#define DEV_BLOCK 1
++#define DEV_CHAR 2
++#define DEV_ALL 4 /* this represents all devices */
++
++/*
++ * whitelist locking rules:
++ * cgroup_lock() cannot be taken under dev_cgroup->lock.
++ * dev_cgroup->lock can be taken with or without cgroup_lock().
++ *
++ * modifications always require cgroup_lock
++ * modifications to a list which is visible require the
++ * dev_cgroup->lock *and* cgroup_lock()
++ * walking the list requires dev_cgroup->lock or cgroup_lock().
++ *
++ * reasoning: dev_whitelist_copy() needs to kmalloc, so needs
++ * a mutex, which the cgroup_lock() is. Since modifying
++ * a visible list requires both locks, either lock can be
++ * taken for walking the list.
++ */
++
++struct dev_whitelist_item {
++ u32 major, minor;
++ short type;
++ short access;
++ struct list_head list;
++};
++
++struct dev_cgroup {
++ struct cgroup_subsys_state css;
++ struct list_head whitelist;
++ spinlock_t lock;
++};
++
++static inline struct dev_cgroup *cgroup_to_devcgroup(struct cgroup *cgroup)
++{
++ return container_of(cgroup_subsys_state(cgroup, devices_subsys_id),
++ struct dev_cgroup, css);
++}
++
++struct cgroup_subsys devices_subsys;
++
++static int devcgroup_can_attach(struct cgroup_subsys *ss,
++ struct cgroup *new_cgroup, struct task_struct *task)
++{
++ if (current != task && !capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ return 0;
++}
++
++/*
++ * called under cgroup_lock()
++ */
++static int dev_whitelist_copy(struct list_head *dest, struct list_head *orig)
++{
++ struct dev_whitelist_item *wh, *tmp, *new;
++
++ list_for_each_entry(wh, orig, list) {
++ new = kmalloc(sizeof(*wh), GFP_KERNEL);
++ if (!new)
++ goto free_and_exit;
++ new->major = wh->major;
++ new->minor = wh->minor;
++ new->type = wh->type;
++ new->access = wh->access;
++ list_add_tail(&new->list, dest);
++ }
++
++ return 0;
++
++free_and_exit:
++ list_for_each_entry_safe(wh, tmp, dest, list) {
++ list_del(&wh->list);
++ kfree(wh);
++ }
++ return -ENOMEM;
++}
++
++/* Stupid prototype - don't bother combining existing entries */
++/*
++ * called under cgroup_lock()
++ * since the list is visible to other tasks, we need the spinlock also
++ */
++static int dev_whitelist_add(struct dev_cgroup *dev_cgroup,
++ struct dev_whitelist_item *wh)
++{
++ struct dev_whitelist_item *whcopy;
++
++ whcopy = kmalloc(sizeof(*whcopy), GFP_KERNEL);
++ if (!whcopy)
++ return -ENOMEM;
++
++ memcpy(whcopy, wh, sizeof(*whcopy));
++ spin_lock(&dev_cgroup->lock);
++ list_add_tail(&whcopy->list, &dev_cgroup->whitelist);
++ spin_unlock(&dev_cgroup->lock);
++ return 0;
++}
++
++/*
++ * called under cgroup_lock()
++ * since the list is visible to other tasks, we need the spinlock also
++ */
++static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup,
++ struct dev_whitelist_item *wh)
++{
++ struct dev_whitelist_item *walk, *tmp;
++
++ spin_lock(&dev_cgroup->lock);
++ list_for_each_entry_safe(walk, tmp, &dev_cgroup->whitelist, list) {
++ if (walk->type == DEV_ALL)
++ goto remove;
++ if (walk->type != wh->type)
++ continue;
++ if (walk->major != ~0 && walk->major != wh->major)
++ continue;
++ if (walk->minor != ~0 && walk->minor != wh->minor)
++ continue;
++
++remove:
++ walk->access &= ~wh->access;
++ if (!walk->access) {
++ list_del(&walk->list);
++ kfree(walk);
++ }
++ }
++ spin_unlock(&dev_cgroup->lock);
++}
++
++/*
++ * called from kernel/cgroup.c with cgroup_lock() held.
++ */
++static struct cgroup_subsys_state *devcgroup_create(struct cgroup_subsys *ss,
++ struct cgroup *cgroup)
++{
++ struct dev_cgroup *dev_cgroup, *parent_dev_cgroup;
++ struct cgroup *parent_cgroup;
++ int ret;
++
++ dev_cgroup = kzalloc(sizeof(*dev_cgroup), GFP_KERNEL);
++ if (!dev_cgroup)
++ return ERR_PTR(-ENOMEM);
++ INIT_LIST_HEAD(&dev_cgroup->whitelist);
++ parent_cgroup = cgroup->parent;
++
++ if (parent_cgroup == NULL) {
++ struct dev_whitelist_item *wh;
++ wh = kmalloc(sizeof(*wh), GFP_KERNEL);
++ if (!wh) {
++ kfree(dev_cgroup);
++ return ERR_PTR(-ENOMEM);
++ }
++ wh->minor = wh->major = ~0;
++ wh->type = DEV_ALL;
++ wh->access = ACC_MKNOD | ACC_READ | ACC_WRITE;
++ list_add(&wh->list, &dev_cgroup->whitelist);
++ } else {
++ parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup);
++ ret = dev_whitelist_copy(&dev_cgroup->whitelist,
++ &parent_dev_cgroup->whitelist);
++ if (ret) {
++ kfree(dev_cgroup);
++ return ERR_PTR(ret);
++ }
++ }
++
++ spin_lock_init(&dev_cgroup->lock);
++ return &dev_cgroup->css;
++}
++
++static void devcgroup_destroy(struct cgroup_subsys *ss,
++ struct cgroup *cgroup)
++{
++ struct dev_cgroup *dev_cgroup;
++ struct dev_whitelist_item *wh, *tmp;
++
++ dev_cgroup = cgroup_to_devcgroup(cgroup);
++ list_for_each_entry_safe(wh, tmp, &dev_cgroup->whitelist, list) {
++ list_del(&wh->list);
++ kfree(wh);
++ }
++ kfree(dev_cgroup);
++}
++
++#define DEVCG_ALLOW 1
++#define DEVCG_DENY 2
++#define DEVCG_LIST 3
++
++#define MAJMINLEN 10
++#define ACCLEN 4
++
++static void set_access(char *acc, short access)
++{
++ int idx = 0;
++ memset(acc, 0, ACCLEN);
++ if (access & ACC_READ)
++ acc[idx++] = 'r';
++ if (access & ACC_WRITE)
++ acc[idx++] = 'w';
++ if (access & ACC_MKNOD)
++ acc[idx++] = 'm';
++}
++
++static char type_to_char(short type)
++{
++ if (type == DEV_ALL)
++ return 'a';
++ if (type == DEV_CHAR)
++ return 'c';
++ if (type == DEV_BLOCK)
++ return 'b';
++ return 'X';
++}
++
++static void set_majmin(char *str, unsigned m)
++{
++ memset(str, 0, MAJMINLEN);
++ if (m == ~0)
++ sprintf(str, "*");
++ else
++ snprintf(str, MAJMINLEN, "%d", m);
++}
++
++static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
++ struct seq_file *m)
++{
++ struct dev_cgroup *devcgroup = cgroup_to_devcgroup(cgroup);
++ struct dev_whitelist_item *wh;
++ char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN];
++
++ spin_lock(&devcgroup->lock);
++ list_for_each_entry(wh, &devcgroup->whitelist, list) {
++ set_access(acc, wh->access);
++ set_majmin(maj, wh->major);
++ set_majmin(min, wh->minor);
++ seq_printf(m, "%c %s:%s %s\n", type_to_char(wh->type),
++ maj, min, acc);
++ }
++ spin_unlock(&devcgroup->lock);
++
++ return 0;
++}
++
++/*
++ * may_access_whitelist:
++ * does the access granted to dev_cgroup c contain the access
++ * requested in whitelist item refwh.
++ * return 1 if yes, 0 if no.
++ * call with c->lock held
++ */
++static int may_access_whitelist(struct dev_cgroup *c,
++ struct dev_whitelist_item *refwh)
++{
++ struct dev_whitelist_item *whitem;
++
++ list_for_each_entry(whitem, &c->whitelist, list) {
++ if (whitem->type & DEV_ALL)
++ return 1;
++ if ((refwh->type & DEV_BLOCK) && !(whitem->type & DEV_BLOCK))
++ continue;
++ if ((refwh->type & DEV_CHAR) && !(whitem->type & DEV_CHAR))
++ continue;
++ if (whitem->major != ~0 && whitem->major != refwh->major)
++ continue;
++ if (whitem->minor != ~0 && whitem->minor != refwh->minor)
++ continue;
++ if (refwh->access & (~(whitem->access | ACC_MASK)))
++ continue;
++ return 1;
++ }
++ return 0;
++}
++
++/*
++ * parent_has_perm:
++ * when adding a new allow rule to a device whitelist, the rule
++ * must be allowed in the parent device
++ */
++static int parent_has_perm(struct cgroup *childcg,
++ struct dev_whitelist_item *wh)
++{
++ struct cgroup *pcg = childcg->parent;
++ struct dev_cgroup *parent;
++ int ret;
++
++ if (!pcg)
++ return 1;
++ parent = cgroup_to_devcgroup(pcg);
++ spin_lock(&parent->lock);
++ ret = may_access_whitelist(parent, wh);
++ spin_unlock(&parent->lock);
++ return ret;
++}
++
++/*
++ * Modify the whitelist using allow/deny rules.
++ * CAP_SYS_ADMIN is needed for this. It's at least separate from CAP_MKNOD
++ * so we can give a container CAP_MKNOD to let it create devices but not
++ * modify the whitelist.
++ * It seems likely we'll want to add a CAP_CONTAINER capability to allow
++ * us to also grant CAP_SYS_ADMIN to containers without giving away the
++ * device whitelist controls, but for now we'll stick with CAP_SYS_ADMIN
++ *
++ * Taking rules away is always allowed (given CAP_SYS_ADMIN). Granting
++ * new access is only allowed if you're in the top-level cgroup, or your
++ * parent cgroup has the access you're asking for.
++ */
++static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
++ struct file *file, const char __user *userbuf,
++ size_t nbytes, loff_t *ppos)
++{
++ struct cgroup *cur_cgroup;
++ struct dev_cgroup *devcgroup, *cur_devcgroup;
++ int filetype = cft->private;
++ char *buffer, *b;
++ int retval = 0, count;
++ struct dev_whitelist_item wh;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ devcgroup = cgroup_to_devcgroup(cgroup);
++ cur_cgroup = task_cgroup(current, devices_subsys.subsys_id);
++ cur_devcgroup = cgroup_to_devcgroup(cur_cgroup);
++
++ buffer = kmalloc(nbytes+1, GFP_KERNEL);
++ if (!buffer)
++ return -ENOMEM;
++
++ if (copy_from_user(buffer, userbuf, nbytes)) {
++ retval = -EFAULT;
++ goto out1;
++ }
++ buffer[nbytes] = 0; /* nul-terminate */
++
++ cgroup_lock();
++ if (cgroup_is_removed(cgroup)) {
++ retval = -ENODEV;
++ goto out2;
++ }
++
++ memset(&wh, 0, sizeof(wh));
++ b = buffer;
++
++ switch (*b) {
++ case 'a':
++ wh.type = DEV_ALL;
++ wh.access = ACC_MASK;
++ goto handle;
++ case 'b':
++ wh.type = DEV_BLOCK;
++ break;
++ case 'c':
++ wh.type = DEV_CHAR;
++ break;
++ default:
++ retval = -EINVAL;
++ goto out2;
++ }
++ b++;
++ if (!isspace(*b)) {
++ retval = -EINVAL;
++ goto out2;
++ }
++ b++;
++ if (*b == '*') {
++ wh.major = ~0;
++ b++;
++ } else if (isdigit(*b)) {
++ wh.major = 0;
++ while (isdigit(*b)) {
++ wh.major = wh.major*10+(*b-'0');
++ b++;
++ }
++ } else {
++ retval = -EINVAL;
++ goto out2;
++ }
++ if (*b != ':') {
++ retval = -EINVAL;
++ goto out2;
++ }
++ b++;
++
++ /* read minor */
++ if (*b == '*') {
++ wh.minor = ~0;
++ b++;
++ } else if (isdigit(*b)) {
++ wh.minor = 0;
++ while (isdigit(*b)) {
++ wh.minor = wh.minor*10+(*b-'0');
++ b++;
++ }
++ } else {
++ retval = -EINVAL;
++ goto out2;
++ }
++ if (!isspace(*b)) {
++ retval = -EINVAL;
++ goto out2;
++ }
++ for (b++, count = 0; count < 3; count++, b++) {
++ switch (*b) {
++ case 'r':
++ wh.access |= ACC_READ;
++ break;
++ case 'w':
++ wh.access |= ACC_WRITE;
++ break;
++ case 'm':
++ wh.access |= ACC_MKNOD;
++ break;
++ case '\n':
++ case '\0':
++ count = 3;
++ break;
++ default:
++ retval = -EINVAL;
++ goto out2;
++ }
++ }
++
++handle:
++ retval = 0;
++ switch (filetype) {
++ case DEVCG_ALLOW:
++ if (!parent_has_perm(cgroup, &wh))
++ retval = -EPERM;
++ else
++ retval = dev_whitelist_add(devcgroup, &wh);
++ break;
++ case DEVCG_DENY:
++ dev_whitelist_rm(devcgroup, &wh);
++ break;
++ default:
++ retval = -EINVAL;
++ goto out2;
++ }
++
++ if (retval == 0)
++ retval = nbytes;
++
++out2:
++ cgroup_unlock();
++out1:
++ kfree(buffer);
++ return retval;
++}
++
++static struct cftype dev_cgroup_files[] = {
++ {
++ .name = "allow",
++ .write = devcgroup_access_write,
++ .private = DEVCG_ALLOW,
++ },
++ {
++ .name = "deny",
++ .write = devcgroup_access_write,
++ .private = DEVCG_DENY,
++ },
++ {
++ .name = "list",
++ .read_seq_string = devcgroup_seq_read,
++ .private = DEVCG_LIST,
++ },
++};
++
++static int devcgroup_populate(struct cgroup_subsys *ss,
++ struct cgroup *cgroup)
++{
++ return cgroup_add_files(cgroup, ss, dev_cgroup_files,
++ ARRAY_SIZE(dev_cgroup_files));
++}
++
++struct cgroup_subsys devices_subsys = {
++ .name = "devices",
++ .can_attach = devcgroup_can_attach,
++ .create = devcgroup_create,
++ .destroy = devcgroup_destroy,
++ .populate = devcgroup_populate,
++ .subsys_id = devices_subsys_id,
++};
++
++int devcgroup_inode_permission(struct inode *inode, int mask)
++{
++ struct cgroup *cgroup;
++ struct dev_cgroup *dev_cgroup;
++ struct dev_whitelist_item *wh;
++
++ dev_t device = inode->i_rdev;
++ if (!device)
++ return 0;
++ if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode))
++ return 0;
++ cgroup = task_cgroup(current, devices_subsys.subsys_id);
++ dev_cgroup = cgroup_to_devcgroup(cgroup);
++ if (!dev_cgroup)
++ return 0;
++
++ spin_lock(&dev_cgroup->lock);
++ list_for_each_entry(wh, &dev_cgroup->whitelist, list) {
++ if (wh->type & DEV_ALL)
++ goto acc_check;
++ if ((wh->type & DEV_BLOCK) && !S_ISBLK(inode->i_mode))
++ continue;
++ if ((wh->type & DEV_CHAR) && !S_ISCHR(inode->i_mode))
++ continue;
++ if (wh->major != ~0 && wh->major != imajor(inode))
++ continue;
++ if (wh->minor != ~0 && wh->minor != iminor(inode))
++ continue;
++acc_check:
++ if ((mask & MAY_WRITE) && !(wh->access & ACC_WRITE))
++ continue;
++ if ((mask & MAY_READ) && !(wh->access & ACC_READ))
++ continue;
++ spin_unlock(&dev_cgroup->lock);
++ return 0;
++ }
++ spin_unlock(&dev_cgroup->lock);
++
++ return -EPERM;
++}
++
++int devcgroup_inode_mknod(int mode, dev_t dev)
++{
++ struct cgroup *cgroup;
++ struct dev_cgroup *dev_cgroup;
++ struct dev_whitelist_item *wh;
++
++ cgroup = task_cgroup(current, devices_subsys.subsys_id);
++ dev_cgroup = cgroup_to_devcgroup(cgroup);
++ if (!dev_cgroup)
++ return 0;
++
++ spin_lock(&dev_cgroup->lock);
++ list_for_each_entry(wh, &dev_cgroup->whitelist, list) {
++ if (wh->type & DEV_ALL)
++ goto acc_check;
++ if ((wh->type & DEV_BLOCK) && !S_ISBLK(mode))
++ continue;
++ if ((wh->type & DEV_CHAR) && !S_ISCHR(mode))
++ continue;
++ if (wh->major != ~0 && wh->major != MAJOR(dev))
++ continue;
++ if (wh->minor != ~0 && wh->minor != MINOR(dev))
++ continue;
++acc_check:
++ if (!(wh->access & ACC_MKNOD))
++ continue;
++ spin_unlock(&dev_cgroup->lock);
++ return 0;
++ }
++ spin_unlock(&dev_cgroup->lock);
++ return -EPERM;
++}
diff --git a/security/dummy.c b/security/dummy.c
-index 78d8f92..b0232bb 100644
+index 78d8f92..f50c6c3 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -196,13 +196,13 @@ static int dummy_sb_statfs (struct dentry *dentry)
@@ -924060,7 +1226866,44 @@
{
return;
}
-@@ -424,6 +424,11 @@ static int dummy_inode_listsecurity(struct inode *inode, char *buffer, size_t bu
+@@ -365,8 +365,8 @@ static void dummy_inode_delete (struct inode *ino)
+ return;
+ }
+
+-static int dummy_inode_setxattr (struct dentry *dentry, char *name, void *value,
+- size_t size, int flags)
++static int dummy_inode_setxattr (struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags)
+ {
+ if (!strncmp(name, XATTR_SECURITY_PREFIX,
+ sizeof(XATTR_SECURITY_PREFIX) - 1) &&
+@@ -375,12 +375,13 @@ static int dummy_inode_setxattr (struct dentry *dentry, char *name, void *value,
+ return 0;
+ }
+
+-static void dummy_inode_post_setxattr (struct dentry *dentry, char *name, void *value,
+- size_t size, int flags)
++static void dummy_inode_post_setxattr (struct dentry *dentry, const char *name,
++ const void *value, size_t size,
++ int flags)
+ {
+ }
+
+-static int dummy_inode_getxattr (struct dentry *dentry, char *name)
++static int dummy_inode_getxattr (struct dentry *dentry, const char *name)
+ {
+ return 0;
+ }
+@@ -390,7 +391,7 @@ static int dummy_inode_listxattr (struct dentry *dentry)
+ return 0;
+ }
+
+-static int dummy_inode_removexattr (struct dentry *dentry, char *name)
++static int dummy_inode_removexattr (struct dentry *dentry, const char *name)
+ {
+ if (!strncmp(name, XATTR_SECURITY_PREFIX,
+ sizeof(XATTR_SECURITY_PREFIX) - 1) &&
+@@ -424,6 +425,11 @@ static int dummy_inode_listsecurity(struct inode *inode, char *buffer, size_t bu
return 0;
}
@@ -924072,7 +1226915,7 @@
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)
+@@ -542,7 +548,9 @@ static int dummy_task_getsid (struct task_struct *p)
}
static void dummy_task_getsecid (struct task_struct *p, u32 *secid)
@@ -924083,7 +1226926,16 @@
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)
+@@ -597,7 +605,7 @@ static int dummy_task_kill (struct task_struct *p, struct siginfo *info,
+ }
+
+ static int dummy_task_prctl (int option, unsigned long arg2, unsigned long arg3,
+- unsigned long arg4, unsigned long arg5)
++ unsigned long arg4, unsigned long arg5, long *rc_p)
+ {
+ return 0;
+ }
+@@ -616,6 +624,11 @@ static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
return 0;
}
@@ -924095,7 +1226947,7 @@
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,
+@@ -876,22 +889,23 @@ static inline void dummy_req_classify_flow(const struct request_sock *req,
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -924124,7 +1226976,7 @@
{
return 0;
}
-@@ -911,7 +924,8 @@ static int dummy_xfrm_state_delete_security(struct xfrm_state *x)
+@@ -911,7 +925,8 @@ static int dummy_xfrm_state_delete_security(struct xfrm_state *x)
return 0;
}
@@ -924134,8 +1226986,26 @@
{
return 0;
}
-@@ -981,7 +995,33 @@ static inline int dummy_key_permission(key_ref_t key_ref,
+@@ -953,7 +968,7 @@ static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+ return -EOPNOTSUPP;
+ }
+
+-static int dummy_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
++static int dummy_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
+ {
+ return -EOPNOTSUPP;
+ }
+@@ -979,9 +994,42 @@ static inline int dummy_key_permission(key_ref_t key_ref,
+ {
+ return 0;
}
++
++static int dummy_key_getsecurity(struct key *key, char **_buffer)
++{
++ *_buffer = NULL;
++ return 0;
++}
++
#endif /* CONFIG_KEYS */
-struct security_operations dummy_security_ops;
@@ -924169,7 +1227039,7 @@
#define set_to_dummy_if_null(ops, function) \
do { \
-@@ -1058,6 +1098,7 @@ void security_fixup_ops (struct security_operations *ops)
+@@ -1058,6 +1106,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);
@@ -924177,7 +1227047,7 @@
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)
+@@ -1094,6 +1143,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);
@@ -924185,9 +1227055,11 @@
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)
+@@ -1167,7 +1217,13 @@ void security_fixup_ops (struct security_operations *ops)
+ set_to_dummy_if_null(ops, key_alloc);
set_to_dummy_if_null(ops, key_free);
set_to_dummy_if_null(ops, key_permission);
++ set_to_dummy_if_null(ops, key_getsecurity);
#endif /* CONFIG_KEYS */
-
+#ifdef CONFIG_AUDIT
@@ -924198,8 +1227070,31 @@
+#endif
}
+diff --git a/security/keys/Makefile b/security/keys/Makefile
+index 5145adf..747a464 100644
+--- a/security/keys/Makefile
++++ b/security/keys/Makefile
+@@ -14,3 +14,4 @@ obj-y := \
+
+ obj-$(CONFIG_KEYS_COMPAT) += compat.o
+ obj-$(CONFIG_PROC_FS) += proc.o
++obj-$(CONFIG_SYSCTL) += sysctl.o
+diff --git a/security/keys/compat.c b/security/keys/compat.c
+index e10ec99..c766c68 100644
+--- a/security/keys/compat.c
++++ b/security/keys/compat.c
+@@ -79,6 +79,9 @@ asmlinkage long compat_sys_keyctl(u32 option,
+ case KEYCTL_ASSUME_AUTHORITY:
+ return keyctl_assume_authority(arg2);
+
++ case KEYCTL_GET_SECURITY:
++ return keyctl_get_security(arg2, compat_ptr(arg3), arg4);
++
+ default:
+ return -EOPNOTSUPP;
+ }
diff --git a/security/keys/internal.h b/security/keys/internal.h
-index d36d693..7d894ef 100644
+index d36d693..8c05587 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -22,16 +22,16 @@ void no_printk(const char *fmt, ...)
@@ -924223,8 +1227118,1142 @@
#define kdebug(FMT, ...) \
no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__)
#endif
+@@ -57,10 +57,6 @@ struct key_user {
+ int qnbytes; /* number of bytes allocated to this user */
+ };
+
+-#define KEYQUOTA_MAX_KEYS 100
+-#define KEYQUOTA_MAX_BYTES 10000
+-#define KEYQUOTA_LINK_BYTES 4 /* a link in a keyring is worth 4 bytes */
+-
+ extern struct rb_root key_user_tree;
+ extern spinlock_t key_user_lock;
+ extern struct key_user root_key_user;
+@@ -68,6 +64,16 @@ extern struct key_user root_key_user;
+ extern struct key_user *key_user_lookup(uid_t uid);
+ extern void key_user_put(struct key_user *user);
+
++/*
++ * key quota limits
++ * - root has its own separate limits to everyone else
++ */
++extern unsigned key_quota_root_maxkeys;
++extern unsigned key_quota_root_maxbytes;
++extern unsigned key_quota_maxkeys;
++extern unsigned key_quota_maxbytes;
++
++#define KEYQUOTA_LINK_BYTES 4 /* a link in a keyring is worth 4 bytes */
+
+
+ extern struct rb_root key_serial_tree;
+@@ -77,8 +83,6 @@ extern struct mutex key_construction_mutex;
+ extern wait_queue_head_t request_key_conswq;
+
+
+-extern void keyring_publish_name(struct key *keyring);
+-
+ extern int __key_link(struct key *keyring, struct key *key);
+
+ extern key_ref_t __keyring_search_one(key_ref_t keyring_ref,
+@@ -102,14 +106,15 @@ extern key_ref_t search_process_keyrings(struct key_type *type,
+ key_match_func_t match,
+ struct task_struct *tsk);
+
+-extern struct key *find_keyring_by_name(const char *name, key_serial_t bound);
++extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check);
+
+ extern int install_thread_keyring(struct task_struct *tsk);
+ extern int install_process_keyring(struct task_struct *tsk);
+
+ extern struct key *request_key_and_link(struct key_type *type,
+ const char *description,
+- const char *callout_info,
++ const void *callout_info,
++ size_t callout_len,
+ void *aux,
+ struct key *dest_keyring,
+ unsigned long flags);
+@@ -120,13 +125,15 @@ extern struct key *request_key_and_link(struct key_type *type,
+ struct request_key_auth {
+ struct key *target_key;
+ struct task_struct *context;
+- char *callout_info;
++ void *callout_info;
++ size_t callout_len;
+ pid_t pid;
+ };
+
+ extern struct key_type key_type_request_key_auth;
+ extern struct key *request_key_auth_new(struct key *target,
+- const char *callout_info);
++ const void *callout_info,
++ size_t callout_len);
+
+ extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
+
+@@ -152,7 +159,8 @@ extern long keyctl_negate_key(key_serial_t, unsigned, key_serial_t);
+ extern long keyctl_set_reqkey_keyring(int);
+ extern long keyctl_set_timeout(key_serial_t, unsigned);
+ extern long keyctl_assume_authority(key_serial_t);
+-
++extern long keyctl_get_security(key_serial_t keyid, char __user *buffer,
++ size_t buflen);
+
+ /*
+ * debugging key validation
+diff --git a/security/keys/key.c b/security/keys/key.c
+index 654d23b..14948cf 100644
+--- a/security/keys/key.c
++++ b/security/keys/key.c
+@@ -1,6 +1,6 @@
+ /* Basic authentication token and access key management
+ *
+- * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells at redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+@@ -27,6 +27,11 @@ DEFINE_SPINLOCK(key_serial_lock);
+ struct rb_root key_user_tree; /* tree of quota records indexed by UID */
+ DEFINE_SPINLOCK(key_user_lock);
+
++unsigned int key_quota_root_maxkeys = 200; /* root's key count quota */
++unsigned int key_quota_root_maxbytes = 20000; /* root's key space quota */
++unsigned int key_quota_maxkeys = 200; /* general key count quota */
++unsigned int key_quota_maxbytes = 20000; /* general key space quota */
++
+ static LIST_HEAD(key_types_list);
+ static DECLARE_RWSEM(key_types_sem);
+
+@@ -139,36 +144,6 @@ void key_user_put(struct key_user *user)
+
+ /*****************************************************************************/
+ /*
+- * insert a key with a fixed serial number
+- */
+-static void __init __key_insert_serial(struct key *key)
+-{
+- struct rb_node *parent, **p;
+- struct key *xkey;
+-
+- parent = NULL;
+- p = &key_serial_tree.rb_node;
+-
+- while (*p) {
+- parent = *p;
+- xkey = rb_entry(parent, struct key, serial_node);
+-
+- if (key->serial < xkey->serial)
+- p = &(*p)->rb_left;
+- else if (key->serial > xkey->serial)
+- p = &(*p)->rb_right;
+- else
+- BUG();
+- }
+-
+- /* we've found a suitable hole - arrange for this key to occupy it */
+- rb_link_node(&key->serial_node, parent, p);
+- rb_insert_color(&key->serial_node, &key_serial_tree);
+-
+-} /* end __key_insert_serial() */
+-
+-/*****************************************************************************/
+-/*
+ * assign a key the next unique serial number
+ * - these are assigned randomly to avoid security issues through covert
+ * channel problems
+@@ -266,11 +241,16 @@ struct key *key_alloc(struct key_type *type, const char *desc,
+ /* check that the user's quota permits allocation of another key and
+ * its description */
+ if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) {
++ unsigned maxkeys = (uid == 0) ?
++ key_quota_root_maxkeys : key_quota_maxkeys;
++ unsigned maxbytes = (uid == 0) ?
++ key_quota_root_maxbytes : key_quota_maxbytes;
++
+ spin_lock(&user->lock);
+ if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) {
+- if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
+- user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES
+- )
++ if (user->qnkeys + 1 >= maxkeys ||
++ user->qnbytes + quotalen >= maxbytes ||
++ user->qnbytes + quotalen < user->qnbytes)
+ goto no_quota;
+ }
+
+@@ -375,11 +355,14 @@ int key_payload_reserve(struct key *key, size_t datalen)
+
+ /* contemplate the quota adjustment */
+ if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
++ unsigned maxbytes = (key->user->uid == 0) ?
++ key_quota_root_maxbytes : key_quota_maxbytes;
++
+ spin_lock(&key->user->lock);
+
+ if (delta > 0 &&
+- key->user->qnbytes + delta > KEYQUOTA_MAX_BYTES
+- ) {
++ (key->user->qnbytes + delta >= maxbytes ||
++ key->user->qnbytes + delta < key->user->qnbytes)) {
+ ret = -EDQUOT;
+ }
+ else {
+@@ -757,11 +740,11 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
+ const char *description,
+ const void *payload,
+ size_t plen,
++ key_perm_t perm,
+ unsigned long flags)
+ {
+ struct key_type *ktype;
+ struct key *keyring, *key = NULL;
+- key_perm_t perm;
+ key_ref_t key_ref;
+ int ret;
+
+@@ -806,15 +789,17 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
+ goto found_matching_key;
+ }
+
+- /* decide on the permissions we want */
+- perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
+- perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR;
++ /* if the client doesn't provide, decide on the permissions we want */
++ if (perm == KEY_PERM_UNDEF) {
++ perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
++ perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR;
+
+- if (ktype->read)
+- perm |= KEY_POS_READ | KEY_USR_READ;
++ if (ktype->read)
++ perm |= KEY_POS_READ | KEY_USR_READ;
+
+- if (ktype == &key_type_keyring || ktype->update)
+- perm |= KEY_USR_WRITE;
++ if (ktype == &key_type_keyring || ktype->update)
++ perm |= KEY_USR_WRITE;
++ }
+
+ /* allocate a new key */
+ key = key_alloc(ktype, description, current->fsuid, current->fsgid,
+@@ -1018,17 +1003,4 @@ void __init key_init(void)
+ rb_insert_color(&root_key_user.node,
+ &key_user_tree);
+
+- /* record root's user standard keyrings */
+- key_check(&root_user_keyring);
+- key_check(&root_session_keyring);
+-
+- __key_insert_serial(&root_user_keyring);
+- __key_insert_serial(&root_session_keyring);
+-
+- keyring_publish_name(&root_user_keyring);
+- keyring_publish_name(&root_session_keyring);
+-
+- /* link the two root keyrings together */
+- key_link(&root_session_keyring, &root_user_keyring);
+-
+ } /* end key_init() */
+diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
+index d9ca15c..acc9c89 100644
+--- a/security/keys/keyctl.c
++++ b/security/keys/keyctl.c
+@@ -19,6 +19,8 @@
+ #include <linux/capability.h>
+ #include <linux/string.h>
+ #include <linux/err.h>
++#include <linux/vmalloc.h>
++#include <linux/security.h>
+ #include <asm/uaccess.h>
+ #include "internal.h"
+
+@@ -62,9 +64,10 @@ asmlinkage long sys_add_key(const char __user *_type,
+ char type[32], *description;
+ void *payload;
+ long ret;
++ bool vm;
+
+ ret = -EINVAL;
+- if (plen > 32767)
++ if (plen > 1024 * 1024 - 1)
+ goto error;
+
+ /* draw all the data into kernel space */
+@@ -81,11 +84,18 @@ asmlinkage long sys_add_key(const char __user *_type,
+ /* pull the payload in if one was supplied */
+ payload = NULL;
+
++ vm = false;
+ if (_payload) {
+ ret = -ENOMEM;
+ payload = kmalloc(plen, GFP_KERNEL);
+- if (!payload)
+- goto error2;
++ if (!payload) {
++ if (plen <= PAGE_SIZE)
++ goto error2;
++ vm = true;
++ payload = vmalloc(plen);
++ if (!payload)
++ goto error2;
++ }
+
+ ret = -EFAULT;
+ if (copy_from_user(payload, _payload, plen) != 0)
+@@ -102,7 +112,8 @@ asmlinkage long sys_add_key(const char __user *_type,
+ /* create or update the requested key and add it to the target
+ * keyring */
+ key_ref = key_create_or_update(keyring_ref, type, description,
+- payload, plen, KEY_ALLOC_IN_QUOTA);
++ payload, plen, KEY_PERM_UNDEF,
++ KEY_ALLOC_IN_QUOTA);
+ if (!IS_ERR(key_ref)) {
+ ret = key_ref_to_ptr(key_ref)->serial;
+ key_ref_put(key_ref);
+@@ -113,7 +124,10 @@ asmlinkage long sys_add_key(const char __user *_type,
+
+ key_ref_put(keyring_ref);
+ error3:
+- kfree(payload);
++ if (!vm)
++ kfree(payload);
++ else
++ vfree(payload);
+ error2:
+ kfree(description);
+ error:
+@@ -140,6 +154,7 @@ asmlinkage long sys_request_key(const char __user *_type,
+ struct key_type *ktype;
+ struct key *key;
+ key_ref_t dest_ref;
++ size_t callout_len;
+ char type[32], *description, *callout_info;
+ long ret;
+
+@@ -157,12 +172,14 @@ asmlinkage long sys_request_key(const char __user *_type,
+
+ /* pull the callout info into kernel space */
+ callout_info = NULL;
++ callout_len = 0;
+ if (_callout_info) {
+ callout_info = strndup_user(_callout_info, PAGE_SIZE);
+ if (IS_ERR(callout_info)) {
+ ret = PTR_ERR(callout_info);
+ goto error2;
+ }
++ callout_len = strlen(callout_info);
+ }
+
+ /* get the destination keyring if specified */
+@@ -183,8 +200,8 @@ asmlinkage long sys_request_key(const char __user *_type,
+ }
+
+ /* do the search */
+- key = request_key_and_link(ktype, description, callout_info, NULL,
+- key_ref_to_ptr(dest_ref),
++ key = request_key_and_link(ktype, description, callout_info,
++ callout_len, NULL, key_ref_to_ptr(dest_ref),
+ KEY_ALLOC_IN_QUOTA);
+ if (IS_ERR(key)) {
+ ret = PTR_ERR(key);
+@@ -714,10 +731,16 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
+
+ /* transfer the quota burden to the new user */
+ if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
++ unsigned maxkeys = (uid == 0) ?
++ key_quota_root_maxkeys : key_quota_maxkeys;
++ unsigned maxbytes = (uid == 0) ?
++ key_quota_root_maxbytes : key_quota_maxbytes;
++
+ spin_lock(&newowner->lock);
+- if (newowner->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
+- newowner->qnbytes + key->quotalen >=
+- KEYQUOTA_MAX_BYTES)
++ if (newowner->qnkeys + 1 >= maxkeys ||
++ newowner->qnbytes + key->quotalen >= maxbytes ||
++ newowner->qnbytes + key->quotalen <
++ newowner->qnbytes)
+ goto quota_overrun;
+
+ newowner->qnkeys++;
+@@ -821,9 +844,10 @@ long keyctl_instantiate_key(key_serial_t id,
+ key_ref_t keyring_ref;
+ void *payload;
+ long ret;
++ bool vm = false;
+
+ ret = -EINVAL;
+- if (plen > 32767)
++ if (plen > 1024 * 1024 - 1)
+ goto error;
+
+ /* the appropriate instantiation authorisation key must have been
+@@ -843,8 +867,14 @@ long keyctl_instantiate_key(key_serial_t id,
+ if (_payload) {
+ ret = -ENOMEM;
+ payload = kmalloc(plen, GFP_KERNEL);
+- if (!payload)
+- goto error;
++ if (!payload) {
++ if (plen <= PAGE_SIZE)
++ goto error;
++ vm = true;
++ payload = vmalloc(plen);
++ if (!payload)
++ goto error;
++ }
+
+ ret = -EFAULT;
+ if (copy_from_user(payload, _payload, plen) != 0)
+@@ -877,7 +907,10 @@ long keyctl_instantiate_key(key_serial_t id,
+ }
+
+ error2:
+- kfree(payload);
++ if (!vm)
++ kfree(payload);
++ else
++ vfree(payload);
+ error:
+ return ret;
+
+@@ -1055,6 +1088,66 @@ error:
+
+ } /* end keyctl_assume_authority() */
+
++/*
++ * get the security label of a key
++ * - the key must grant us view permission
++ * - if there's a buffer, we place up to buflen bytes of data into it
++ * - unless there's an error, we return the amount of information available,
++ * irrespective of how much we may have copied (including the terminal NUL)
++ * - implements keyctl(KEYCTL_GET_SECURITY)
++ */
++long keyctl_get_security(key_serial_t keyid,
++ char __user *buffer,
++ size_t buflen)
++{
++ struct key *key, *instkey;
++ key_ref_t key_ref;
++ char *context;
++ long ret;
++
++ key_ref = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW);
++ if (IS_ERR(key_ref)) {
++ if (PTR_ERR(key_ref) != -EACCES)
++ return PTR_ERR(key_ref);
++
++ /* viewing a key under construction is also permitted if we
++ * have the authorisation token handy */
++ instkey = key_get_instantiation_authkey(keyid);
++ if (IS_ERR(instkey))
++ return PTR_ERR(key_ref);
++ key_put(instkey);
++
++ key_ref = lookup_user_key(NULL, keyid, 0, 1, 0);
++ if (IS_ERR(key_ref))
++ return PTR_ERR(key_ref);
++ }
++
++ key = key_ref_to_ptr(key_ref);
++ ret = security_key_getsecurity(key, &context);
++ if (ret == 0) {
++ /* if no information was returned, give userspace an empty
++ * string */
++ ret = 1;
++ if (buffer && buflen > 0 &&
++ copy_to_user(buffer, "", 1) != 0)
++ ret = -EFAULT;
++ } else if (ret > 0) {
++ /* return as much data as there's room for */
++ if (buffer && buflen > 0) {
++ if (buflen > ret)
++ buflen = ret;
++
++ if (copy_to_user(buffer, context, buflen) != 0)
++ ret = -EFAULT;
++ }
++
++ kfree(context);
++ }
++
++ key_ref_put(key_ref);
++ return ret;
++}
++
+ /*****************************************************************************/
+ /*
+ * the key control system call
+@@ -1135,6 +1228,11 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
+ case KEYCTL_ASSUME_AUTHORITY:
+ return keyctl_assume_authority((key_serial_t) arg2);
+
++ case KEYCTL_GET_SECURITY:
++ return keyctl_get_security((key_serial_t) arg2,
++ (char *) arg3,
++ (size_t) arg4);
++
+ default:
+ return -EOPNOTSUPP;
+ }
+diff --git a/security/keys/keyring.c b/security/keys/keyring.c
+index 88292e3..a9ab8af 100644
+--- a/security/keys/keyring.c
++++ b/security/keys/keyring.c
+@@ -1,6 +1,6 @@
+-/* keyring.c: keyring handling
++/* Keyring handling
+ *
+- * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
++ * Copyright (C) 2004-2005, 2008 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells at redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+@@ -79,7 +79,7 @@ static DECLARE_RWSEM(keyring_serialise_link_sem);
+ * publish the name of a keyring so that it can be found by name (if it has
+ * one)
+ */
+-void keyring_publish_name(struct key *keyring)
++static void keyring_publish_name(struct key *keyring)
+ {
+ int bucket;
+
+@@ -292,7 +292,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
+
+ struct keyring_list *keylist;
+ struct timespec now;
+- unsigned long possessed;
++ unsigned long possessed, kflags;
+ struct key *keyring, *key;
+ key_ref_t key_ref;
+ long err;
+@@ -319,6 +319,32 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
+ err = -EAGAIN;
+ sp = 0;
+
++ /* firstly we should check to see if this top-level keyring is what we
++ * are looking for */
++ key_ref = ERR_PTR(-EAGAIN);
++ kflags = keyring->flags;
++ if (keyring->type == type && match(keyring, description)) {
++ key = keyring;
++
++ /* check it isn't negative and hasn't expired or been
++ * revoked */
++ if (kflags & (1 << KEY_FLAG_REVOKED))
++ goto error_2;
++ if (key->expiry && now.tv_sec >= key->expiry)
++ goto error_2;
++ key_ref = ERR_PTR(-ENOKEY);
++ if (kflags & (1 << KEY_FLAG_NEGATIVE))
++ goto error_2;
++ goto found;
++ }
++
++ /* otherwise, the top keyring must not be revoked, expired, or
++ * negatively instantiated if we are to search it */
++ key_ref = ERR_PTR(-EAGAIN);
++ if (kflags & ((1 << KEY_FLAG_REVOKED) | (1 << KEY_FLAG_NEGATIVE)) ||
++ (keyring->expiry && now.tv_sec >= keyring->expiry))
++ goto error_2;
++
+ /* start processing a new keyring */
+ descend:
+ if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
+@@ -331,13 +357,14 @@ descend:
+ /* iterate through the keys in this keyring first */
+ for (kix = 0; kix < keylist->nkeys; kix++) {
+ key = keylist->keys[kix];
++ kflags = key->flags;
+
+ /* ignore keys not of this type */
+ if (key->type != type)
+ continue;
+
+ /* skip revoked keys and expired keys */
+- if (test_bit(KEY_FLAG_REVOKED, &key->flags))
++ if (kflags & (1 << KEY_FLAG_REVOKED))
+ continue;
+
+ if (key->expiry && now.tv_sec >= key->expiry)
+@@ -352,8 +379,8 @@ descend:
+ context, KEY_SEARCH) < 0)
+ continue;
+
+- /* we set a different error code if we find a negative key */
+- if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
++ /* we set a different error code if we pass a negative key */
++ if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
+ err = -ENOKEY;
+ continue;
+ }
+@@ -489,10 +516,9 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
+ /*
+ * find a keyring with the specified name
+ * - all named keyrings are searched
+- * - only find keyrings with search permission for the process
+- * - only find keyrings with a serial number greater than the one specified
++ * - normally only finds keyrings with search permission for the current process
+ */
+-struct key *find_keyring_by_name(const char *name, key_serial_t bound)
++struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
+ {
+ struct key *keyring;
+ int bucket;
+@@ -518,15 +544,11 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound)
+ if (strcmp(keyring->description, name) != 0)
+ continue;
+
+- if (key_permission(make_key_ref(keyring, 0),
++ if (!skip_perm_check &&
++ key_permission(make_key_ref(keyring, 0),
+ KEY_SEARCH) < 0)
+ continue;
+
+- /* found a potential candidate, but we still need to
+- * check the serial number */
+- if (keyring->serial <= bound)
+- continue;
+-
+ /* we've got a match */
+ atomic_inc(&keyring->usage);
+ read_unlock(&keyring_name_lock);
+diff --git a/security/keys/proc.c b/security/keys/proc.c
+index 6941260..f619170 100644
+--- a/security/keys/proc.c
++++ b/security/keys/proc.c
+@@ -70,19 +70,15 @@ static int __init key_proc_init(void)
+ struct proc_dir_entry *p;
+
+ #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS
+- p = create_proc_entry("keys", 0, NULL);
++ p = proc_create("keys", 0, NULL, &proc_keys_fops);
+ if (!p)
+ panic("Cannot create /proc/keys\n");
+-
+- p->proc_fops = &proc_keys_fops;
+ #endif
+
+- p = create_proc_entry("key-users", 0, NULL);
++ p = proc_create("key-users", 0, NULL, &proc_key_users_fops);
+ if (!p)
+ panic("Cannot create /proc/key-users\n");
+
+- p->proc_fops = &proc_key_users_fops;
+-
+ return 0;
+
+ } /* end key_proc_init() */
+@@ -246,6 +242,10 @@ static int proc_key_users_show(struct seq_file *m, void *v)
+ {
+ struct rb_node *_p = v;
+ struct key_user *user = rb_entry(_p, struct key_user, node);
++ unsigned maxkeys = (user->uid == 0) ?
++ key_quota_root_maxkeys : key_quota_maxkeys;
++ unsigned maxbytes = (user->uid == 0) ?
++ key_quota_root_maxbytes : key_quota_maxbytes;
+
+ seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n",
+ user->uid,
+@@ -253,10 +253,9 @@ static int proc_key_users_show(struct seq_file *m, void *v)
+ atomic_read(&user->nkeys),
+ atomic_read(&user->nikeys),
+ user->qnkeys,
+- KEYQUOTA_MAX_KEYS,
++ maxkeys,
+ user->qnbytes,
+- KEYQUOTA_MAX_BYTES
+- );
++ maxbytes);
+
+ return 0;
+
+diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
+index c886a2b..5be6d01 100644
+--- a/security/keys/process_keys.c
++++ b/security/keys/process_keys.c
+@@ -1,6 +1,6 @@
+-/* process_keys.c: management of a process's keyrings
++/* Management of a process's keyrings
+ *
+- * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
++ * Copyright (C) 2004-2005, 2008 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells at redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+@@ -23,6 +23,9 @@
+ /* session keyring create vs join semaphore */
+ static DEFINE_MUTEX(key_session_mutex);
+
++/* user keyring creation semaphore */
++static DEFINE_MUTEX(key_user_keyring_mutex);
++
+ /* the root user's tracking struct */
+ struct key_user root_key_user = {
+ .usage = ATOMIC_INIT(3),
+@@ -33,78 +36,84 @@ struct key_user root_key_user = {
+ .uid = 0,
+ };
+
+-/* the root user's UID keyring */
+-struct key root_user_keyring = {
+- .usage = ATOMIC_INIT(1),
+- .serial = 2,
+- .type = &key_type_keyring,
+- .user = &root_key_user,
+- .sem = __RWSEM_INITIALIZER(root_user_keyring.sem),
+- .perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
+- .flags = 1 << KEY_FLAG_INSTANTIATED,
+- .description = "_uid.0",
+-#ifdef KEY_DEBUGGING
+- .magic = KEY_DEBUG_MAGIC,
+-#endif
+-};
+-
+-/* the root user's default session keyring */
+-struct key root_session_keyring = {
+- .usage = ATOMIC_INIT(1),
+- .serial = 1,
+- .type = &key_type_keyring,
+- .user = &root_key_user,
+- .sem = __RWSEM_INITIALIZER(root_session_keyring.sem),
+- .perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
+- .flags = 1 << KEY_FLAG_INSTANTIATED,
+- .description = "_uid_ses.0",
+-#ifdef KEY_DEBUGGING
+- .magic = KEY_DEBUG_MAGIC,
+-#endif
+-};
+-
+ /*****************************************************************************/
+ /*
+- * allocate the keyrings to be associated with a UID
++ * install user and user session keyrings for a particular UID
+ */
+-int alloc_uid_keyring(struct user_struct *user,
+- struct task_struct *ctx)
++static int install_user_keyrings(struct task_struct *tsk)
+ {
++ struct user_struct *user = tsk->user;
+ struct key *uid_keyring, *session_keyring;
+ char buf[20];
+ int ret;
+
+- /* concoct a default session keyring */
+- sprintf(buf, "_uid_ses.%u", user->uid);
++ kenter("%p{%u}", user, user->uid);
+
+- session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx,
+- KEY_ALLOC_IN_QUOTA, NULL);
+- if (IS_ERR(session_keyring)) {
+- ret = PTR_ERR(session_keyring);
+- goto error;
++ if (user->uid_keyring) {
++ kleave(" = 0 [exist]");
++ return 0;
+ }
+
+- /* and a UID specific keyring, pointed to by the default session
+- * keyring */
+- sprintf(buf, "_uid.%u", user->uid);
++ mutex_lock(&key_user_keyring_mutex);
++ ret = 0;
+
+- uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx,
+- KEY_ALLOC_IN_QUOTA, session_keyring);
+- if (IS_ERR(uid_keyring)) {
+- key_put(session_keyring);
+- ret = PTR_ERR(uid_keyring);
+- goto error;
++ if (!user->uid_keyring) {
++ /* get the UID-specific keyring
++ * - there may be one in existence already as it may have been
++ * pinned by a session, but the user_struct pointing to it
++ * may have been destroyed by setuid */
++ sprintf(buf, "_uid.%u", user->uid);
++
++ uid_keyring = find_keyring_by_name(buf, true);
++ if (IS_ERR(uid_keyring)) {
++ uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1,
++ tsk, KEY_ALLOC_IN_QUOTA,
++ NULL);
++ if (IS_ERR(uid_keyring)) {
++ ret = PTR_ERR(uid_keyring);
++ goto error;
++ }
++ }
++
++ /* get a default session keyring (which might also exist
++ * already) */
++ sprintf(buf, "_uid_ses.%u", user->uid);
++
++ session_keyring = find_keyring_by_name(buf, true);
++ if (IS_ERR(session_keyring)) {
++ session_keyring =
++ keyring_alloc(buf, user->uid, (gid_t) -1,
++ tsk, KEY_ALLOC_IN_QUOTA, NULL);
++ if (IS_ERR(session_keyring)) {
++ ret = PTR_ERR(session_keyring);
++ goto error_release;
++ }
++
++ /* we install a link from the user session keyring to
++ * the user keyring */
++ ret = key_link(session_keyring, uid_keyring);
++ if (ret < 0)
++ goto error_release_both;
++ }
++
++ /* install the keyrings */
++ user->uid_keyring = uid_keyring;
++ user->session_keyring = session_keyring;
+ }
+
+- /* install the keyrings */
+- user->uid_keyring = uid_keyring;
+- user->session_keyring = session_keyring;
+- ret = 0;
++ mutex_unlock(&key_user_keyring_mutex);
++ kleave(" = 0");
++ return 0;
+
++error_release_both:
++ key_put(session_keyring);
++error_release:
++ key_put(uid_keyring);
+ error:
++ mutex_unlock(&key_user_keyring_mutex);
++ kleave(" = %d", ret);
+ return ret;
+-
+-} /* end alloc_uid_keyring() */
++}
+
+ /*****************************************************************************/
+ /*
+@@ -481,7 +490,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
+ }
+ }
+ /* or search the user-session keyring */
+- else {
++ else if (context->user->session_keyring) {
+ key_ref = keyring_search_aux(
+ make_key_ref(context->user->session_keyring, 1),
+ context, type, description, match);
+@@ -614,6 +623,9 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
+ if (!context->signal->session_keyring) {
+ /* always install a session keyring upon access if one
+ * doesn't exist yet */
++ ret = install_user_keyrings(context);
++ if (ret < 0)
++ goto error;
+ ret = install_session_keyring(
+ context, context->user->session_keyring);
+ if (ret < 0)
+@@ -628,12 +640,24 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
+ break;
+
+ case KEY_SPEC_USER_KEYRING:
++ if (!context->user->uid_keyring) {
++ ret = install_user_keyrings(context);
++ if (ret < 0)
++ goto error;
++ }
++
+ key = context->user->uid_keyring;
+ atomic_inc(&key->usage);
+ key_ref = make_key_ref(key, 1);
+ break;
+
+ case KEY_SPEC_USER_SESSION_KEYRING:
++ if (!context->user->session_keyring) {
++ ret = install_user_keyrings(context);
++ if (ret < 0)
++ goto error;
++ }
++
+ key = context->user->session_keyring;
+ atomic_inc(&key->usage);
+ key_ref = make_key_ref(key, 1);
+@@ -744,7 +768,7 @@ long join_session_keyring(const char *name)
+ mutex_lock(&key_session_mutex);
+
+ /* look for an existing keyring of this name */
+- keyring = find_keyring_by_name(name, 0);
++ keyring = find_keyring_by_name(name, false);
+ if (PTR_ERR(keyring) == -ENOKEY) {
+ /* not found - try and create a new one */
+ keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk,
+diff --git a/security/keys/request_key.c b/security/keys/request_key.c
+index 5ecc505..ba32ca6 100644
+--- a/security/keys/request_key.c
++++ b/security/keys/request_key.c
+@@ -16,6 +16,7 @@
+ #include <linux/kmod.h>
+ #include <linux/err.h>
+ #include <linux/keyctl.h>
++#include <linux/slab.h>
+ #include "internal.h"
+
+ /*
+@@ -161,21 +162,22 @@ error_alloc:
+ * call out to userspace for key construction
+ * - we ignore program failure and go on key status instead
+ */
+-static int construct_key(struct key *key, const char *callout_info, void *aux)
++static int construct_key(struct key *key, const void *callout_info,
++ size_t callout_len, void *aux)
+ {
+ struct key_construction *cons;
+ request_key_actor_t actor;
+ struct key *authkey;
+ int ret;
+
+- kenter("%d,%s,%p", key->serial, callout_info, aux);
++ kenter("%d,%p,%zu,%p", key->serial, callout_info, callout_len, aux);
+
+ cons = kmalloc(sizeof(*cons), GFP_KERNEL);
+ if (!cons)
+ return -ENOMEM;
+
+ /* allocate an authorisation key */
+- authkey = request_key_auth_new(key, callout_info);
++ authkey = request_key_auth_new(key, callout_info, callout_len);
+ if (IS_ERR(authkey)) {
+ kfree(cons);
+ ret = PTR_ERR(authkey);
+@@ -331,6 +333,7 @@ alloc_failed:
+ static struct key *construct_key_and_link(struct key_type *type,
+ const char *description,
+ const char *callout_info,
++ size_t callout_len,
+ void *aux,
+ struct key *dest_keyring,
+ unsigned long flags)
+@@ -348,7 +351,7 @@ static struct key *construct_key_and_link(struct key_type *type,
+ key_user_put(user);
+
+ if (ret == 0) {
+- ret = construct_key(key, callout_info, aux);
++ ret = construct_key(key, callout_info, callout_len, aux);
+ if (ret < 0)
+ goto construction_failed;
+ }
+@@ -370,7 +373,8 @@ construction_failed:
+ */
+ struct key *request_key_and_link(struct key_type *type,
+ const char *description,
+- const char *callout_info,
++ const void *callout_info,
++ size_t callout_len,
+ void *aux,
+ struct key *dest_keyring,
+ unsigned long flags)
+@@ -378,8 +382,8 @@ struct key *request_key_and_link(struct key_type *type,
+ struct key *key;
+ key_ref_t key_ref;
+
+- kenter("%s,%s,%s,%p,%p,%lx",
+- type->name, description, callout_info, aux,
++ kenter("%s,%s,%p,%zu,%p,%p,%lx",
++ type->name, description, callout_info, callout_len, aux,
+ dest_keyring, flags);
+
+ /* search all the process keyrings for a key */
+@@ -398,7 +402,8 @@ struct key *request_key_and_link(struct key_type *type,
+ goto error;
+
+ key = construct_key_and_link(type, description, callout_info,
+- aux, dest_keyring, flags);
++ callout_len, aux, dest_keyring,
++ flags);
+ }
+
+ error:
+@@ -434,10 +439,13 @@ struct key *request_key(struct key_type *type,
+ const char *callout_info)
+ {
+ struct key *key;
++ size_t callout_len = 0;
+ int ret;
+
+- key = request_key_and_link(type, description, callout_info, NULL,
+- NULL, KEY_ALLOC_IN_QUOTA);
++ if (callout_info)
++ callout_len = strlen(callout_info);
++ key = request_key_and_link(type, description, callout_info, callout_len,
++ NULL, NULL, KEY_ALLOC_IN_QUOTA);
+ if (!IS_ERR(key)) {
+ ret = wait_for_key_construction(key, false);
+ if (ret < 0) {
+@@ -458,14 +466,15 @@ EXPORT_SYMBOL(request_key);
+ */
+ struct key *request_key_with_auxdata(struct key_type *type,
+ const char *description,
+- const char *callout_info,
++ const void *callout_info,
++ size_t callout_len,
+ void *aux)
+ {
+ struct key *key;
+ int ret;
+
+- key = request_key_and_link(type, description, callout_info, aux,
+- NULL, KEY_ALLOC_IN_QUOTA);
++ key = request_key_and_link(type, description, callout_info, callout_len,
++ aux, NULL, KEY_ALLOC_IN_QUOTA);
+ if (!IS_ERR(key)) {
+ ret = wait_for_key_construction(key, false);
+ if (ret < 0) {
+@@ -485,10 +494,12 @@ EXPORT_SYMBOL(request_key_with_auxdata);
+ */
+ struct key *request_key_async(struct key_type *type,
+ const char *description,
+- const char *callout_info)
++ const void *callout_info,
++ size_t callout_len)
+ {
+- return request_key_and_link(type, description, callout_info, NULL,
+- NULL, KEY_ALLOC_IN_QUOTA);
++ return request_key_and_link(type, description, callout_info,
++ callout_len, NULL, NULL,
++ KEY_ALLOC_IN_QUOTA);
+ }
+ EXPORT_SYMBOL(request_key_async);
+
+@@ -500,10 +511,11 @@ EXPORT_SYMBOL(request_key_async);
+ */
+ struct key *request_key_async_with_auxdata(struct key_type *type,
+ const char *description,
+- const char *callout_info,
++ const void *callout_info,
++ size_t callout_len,
+ void *aux)
+ {
+- return request_key_and_link(type, description, callout_info, aux,
+- NULL, KEY_ALLOC_IN_QUOTA);
++ return request_key_and_link(type, description, callout_info,
++ callout_len, aux, NULL, KEY_ALLOC_IN_QUOTA);
+ }
+ EXPORT_SYMBOL(request_key_async_with_auxdata);
+diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
+index e42b525..bd237b0 100644
+--- a/security/keys/request_key_auth.c
++++ b/security/keys/request_key_auth.c
+@@ -15,6 +15,7 @@
+ #include <linux/sched.h>
+ #include <linux/err.h>
+ #include <linux/seq_file.h>
++#include <linux/slab.h>
+ #include <asm/uaccess.h>
+ #include "internal.h"
+
+@@ -61,7 +62,7 @@ static void request_key_auth_describe(const struct key *key,
+
+ seq_puts(m, "key:");
+ seq_puts(m, key->description);
+- seq_printf(m, " pid:%d ci:%zu", rka->pid, strlen(rka->callout_info));
++ seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len);
+
+ } /* end request_key_auth_describe() */
+
+@@ -77,7 +78,7 @@ static long request_key_auth_read(const struct key *key,
+ size_t datalen;
+ long ret;
+
+- datalen = strlen(rka->callout_info);
++ datalen = rka->callout_len;
+ ret = datalen;
+
+ /* we can return the data as is */
+@@ -137,7 +138,8 @@ static void request_key_auth_destroy(struct key *key)
+ * create an authorisation token for /sbin/request-key or whoever to gain
+ * access to the caller's security data
+ */
+-struct key *request_key_auth_new(struct key *target, const char *callout_info)
++struct key *request_key_auth_new(struct key *target, const void *callout_info,
++ size_t callout_len)
+ {
+ struct request_key_auth *rka, *irka;
+ struct key *authkey = NULL;
+@@ -152,7 +154,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
+ kleave(" = -ENOMEM");
+ return ERR_PTR(-ENOMEM);
+ }
+- rka->callout_info = kmalloc(strlen(callout_info) + 1, GFP_KERNEL);
++ rka->callout_info = kmalloc(callout_len, GFP_KERNEL);
+ if (!rka->callout_info) {
+ kleave(" = -ENOMEM");
+ kfree(rka);
+@@ -186,7 +188,8 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
+ }
+
+ rka->target_key = key_get(target);
+- strcpy(rka->callout_info, callout_info);
++ memcpy(rka->callout_info, callout_info, callout_len);
++ rka->callout_len = callout_len;
+
+ /* allocate the auth key */
+ sprintf(desc, "%x", target->serial);
+diff --git a/security/keys/sysctl.c b/security/keys/sysctl.c
+new file mode 100644
+index 0000000..b611d49
+--- /dev/null
++++ b/security/keys/sysctl.c
+@@ -0,0 +1,50 @@
++/* Key management controls
++ *
++ * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
++ * Written by David Howells (dhowells at redhat.com)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public Licence
++ * as published by the Free Software Foundation; either version
++ * 2 of the Licence, or (at your option) any later version.
++ */
++
++#include <linux/key.h>
++#include <linux/sysctl.h>
++#include "internal.h"
++
++ctl_table key_sysctls[] = {
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "maxkeys",
++ .data = &key_quota_maxkeys,
++ .maxlen = sizeof(unsigned),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec,
++ },
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "maxbytes",
++ .data = &key_quota_maxbytes,
++ .maxlen = sizeof(unsigned),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec,
++ },
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "root_maxkeys",
++ .data = &key_quota_root_maxkeys,
++ .maxlen = sizeof(unsigned),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec,
++ },
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "root_maxbytes",
++ .data = &key_quota_root_maxbytes,
++ .maxlen = sizeof(unsigned),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec,
++ },
++ { .ctl_name = 0 }
++};
diff --git a/security/root_plug.c b/security/root_plug.c
-index 870f130..6112d14 100644
+index 870f130..a41cf42 100644
--- a/security/root_plug.c
+++ b/security/root_plug.c
@@ -49,7 +49,7 @@ module_param(debug, bool, 0600);
@@ -924236,8 +1228265,16 @@
## arg); \
} while (0)
+@@ -86,6 +86,7 @@ static struct security_operations rootplug_security_ops = {
+
+ .task_post_setuid = cap_task_post_setuid,
+ .task_reparent_to_init = cap_task_reparent_to_init,
++ .task_prctl = cap_task_prctl,
+
+ .bprm_check_security = rootplug_bprm_check_security,
+ };
diff --git a/security/security.c b/security/security.c
-index b1387a6..8a285c7 100644
+index b1387a6..59838a9 100644
--- a/security/security.c
+++ b/security/security.c
@@ -17,6 +17,8 @@
@@ -924378,6 +1228415,44 @@
}
int security_sb_get_mnt_opts(const struct super_block *sb,
+@@ -455,23 +491,23 @@ void security_inode_delete(struct inode *inode)
+ security_ops->inode_delete(inode);
+ }
+
+-int security_inode_setxattr(struct dentry *dentry, char *name,
+- void *value, size_t size, int flags)
++int security_inode_setxattr(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags)
+ {
+ if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ return 0;
+ return security_ops->inode_setxattr(dentry, name, value, size, flags);
+ }
+
+-void security_inode_post_setxattr(struct dentry *dentry, char *name,
+- void *value, size_t size, int flags)
++void security_inode_post_setxattr(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags)
+ {
+ if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ return;
+ security_ops->inode_post_setxattr(dentry, name, value, size, flags);
+ }
+
+-int security_inode_getxattr(struct dentry *dentry, char *name)
++int security_inode_getxattr(struct dentry *dentry, const char *name)
+ {
+ if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ return 0;
+@@ -485,7 +521,7 @@ int security_inode_listxattr(struct dentry *dentry)
+ return security_ops->inode_listxattr(dentry);
+ }
+
+-int security_inode_removexattr(struct dentry *dentry, char *name)
++int security_inode_removexattr(struct dentry *dentry, const char *name)
+ {
+ if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ return 0;
@@ -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);
}
@@ -924390,6 +1228465,18 @@
int security_file_permission(struct file *file, int mask)
{
return security_ops->file_permission(file, mask);
+@@ -692,9 +733,9 @@ int security_task_wait(struct task_struct *p)
+ }
+
+ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
+- unsigned long arg4, unsigned long arg5)
++ unsigned long arg4, unsigned long arg5, long *rc_p)
+ {
+- return security_ops->task_prctl(option, arg2, arg3, arg4, arg5);
++ return security_ops->task_prctl(option, arg2, arg3, arg4, arg5, rc_p);
+ }
+
+ void security_task_reparent_to_init(struct task_struct *p)
@@ -712,6 +753,11 @@ int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
return security_ops->ipc_permission(ipcp, flag);
}
@@ -924402,6 +1228489,15 @@
int security_msg_msg_alloc(struct msg_msg *msg)
{
return security_ops->msg_msg_alloc_security(msg);
+@@ -840,7 +886,7 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+ }
+ EXPORT_SYMBOL(security_secid_to_secctx);
+
+-int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
++int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
+ {
+ return security_ops->secctx_to_secid(secdata, seclen, secid);
+ }
@@ -1014,26 +1060,27 @@ void security_inet_conn_established(struct sock *sk,
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -924450,9 +1228546,15 @@
}
int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
-@@ -1110,3 +1157,28 @@ int security_key_permission(key_ref_t key_ref,
+@@ -1109,4 +1156,34 @@ int security_key_permission(key_ref_t key_ref,
+ return security_ops->key_permission(key_ref, context, perm);
}
++int security_key_getsecurity(struct key *key, char **_buffer)
++{
++ return security_ops->key_getsecurity(key, _buffer);
++}
++
#endif /* CONFIG_KEYS */
+
+#ifdef CONFIG_AUDIT
@@ -924505,7 +1228607,7 @@
selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
-index 187964e..95a8ef4 100644
+index 187964e..114b4b4 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -2,16 +2,16 @@
@@ -924651,7 +1228753,12 @@
audit_log_format(ab, " for ");
if (a && a->tsk)
tsk = a->tsk;
-@@ -647,7 +650,7 @@ void avc_audit(u32 ssid, u32 tsid,
+@@ -643,11 +646,11 @@ void avc_audit(u32 ssid, u32 tsid,
+ if (*p)
+ audit_log_untrustedstring(ab, p);
+ else
+- audit_log_hex(ab, p, len);
++ audit_log_n_hex(ab, p, len);
break;
}
}
@@ -924817,7 +1228924,7 @@
{
if (selinux_enabled)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
-index d39b59c..308e2cf 100644
+index d39b59c..1b50a6e 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4,22 +4,22 @@
@@ -925548,7 +1229655,26 @@
}
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
+@@ -2562,7 +2619,7 @@ static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+ return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
+ }
+
+-static int selinux_inode_setotherxattr(struct dentry *dentry, char *name)
++static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
+ {
+ if (!strncmp(name, XATTR_SECURITY_PREFIX,
+ sizeof XATTR_SECURITY_PREFIX - 1)) {
+@@ -2581,7 +2638,8 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, char *name)
+ return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
+ }
+
+-static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
++static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags)
+ {
+ struct task_security_struct *tsec = current->security;
+ struct inode *inode = dentry->d_inode;
+@@ -2601,7 +2659,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
if (!is_owner_or_cap(inode))
return -EPERM;
@@ -925557,7 +1229683,7 @@
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
+@@ -2619,7 +2677,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
return rc;
rc = security_validate_transition(isec->sid, newsid, tsec->sid,
@@ -925566,16 +1229692,19 @@
if (rc)
return rc;
-@@ -2631,7 +2688,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
+@@ -2630,8 +2688,9 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
+ &ad);
}
- static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
+-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)
++static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
++ const 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,
+@@ -2646,7 +2705,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 "
@@ -925584,12 +1229713,12 @@
return;
}
-@@ -2654,17 +2711,17 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
+@@ -2654,17 +2713,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)
++static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
{
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
}
@@ -925601,11 +1229730,11 @@
}
-static int selinux_inode_removexattr (struct dentry *dentry, char *name)
-+static int selinux_inode_removexattr(struct dentry *dentry, char *name)
++static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
{
if (strcmp(name, XATTR_NAME_SELINUX))
return selinux_inode_setotherxattr(dentry, name);
-@@ -2705,7 +2762,7 @@ out_nofree:
+@@ -2705,7 +2764,7 @@ out_nofree:
}
static int selinux_inode_setsecurity(struct inode *inode, const char *name,
@@ -925614,7 +1229743,7 @@
{
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,
+@@ -2717,7 +2776,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
if (!value || !size)
return -EACCES;
@@ -925623,7 +1229752,7 @@
if (rc)
return rc;
-@@ -2743,6 +2800,12 @@ static int selinux_inode_killpriv(struct dentry *dentry)
+@@ -2743,6 +2802,12 @@ static int selinux_inode_killpriv(struct dentry *dentry)
return secondary_ops->inode_killpriv(dentry);
}
@@ -925636,7 +1229765,7 @@
/* 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,
+@@ -2802,42 +2867,41 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
int error = 0;
switch (cmd) {
@@ -925710,7 +1229839,7 @@
}
return error;
}
-@@ -2878,7 +2940,7 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot,
+@@ -2878,7 +2942,7 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot,
unsigned long addr, unsigned long addr_only)
{
int rc = 0;
@@ -925719,7 +1229848,7 @@
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,
+@@ -2947,39 +3011,39 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
int err = 0;
switch (cmd) {
@@ -925787,7 +1229916,7 @@
}
return err;
-@@ -3000,13 +3062,13 @@ static int selinux_file_set_fowner(struct file *file)
+@@ -3000,13 +3064,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)
{
@@ -925803,7 +1229932,7 @@
tsec = tsk->security;
fsec = file->f_security;
-@@ -3087,11 +3149,6 @@ static int selinux_task_alloc_security(struct task_struct *tsk)
+@@ -3087,11 +3151,6 @@ static int selinux_task_alloc_security(struct task_struct *tsk)
tsec2->keycreate_sid = tsec1->keycreate_sid;
tsec2->sockcreate_sid = tsec1->sockcreate_sid;
@@ -925815,7 +1229944,7 @@
return 0;
}
-@@ -3113,7 +3170,7 @@ static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
+@@ -3113,7 +3172,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)
{
@@ -925824,7 +1229953,7 @@
}
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)
+@@ -3139,7 +3198,8 @@ static int selinux_task_getsid(struct task_struct *p)
static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
{
@@ -925834,7 +1229963,7 @@
}
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)
+@@ -3156,7 +3216,7 @@ static int selinux_task_setnice(struct task_struct *p, int nice)
if (rc)
return rc;
@@ -925843,6 +1229972,32 @@
}
static int selinux_task_setioprio(struct task_struct *p, int ioprio)
+@@ -3226,9 +3286,6 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
+ if (rc)
+ return rc;
+
+- if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
+- return 0;
+-
+ if (!sig)
+ perm = PROCESS__SIGNULL; /* null signal; existence test */
+ else
+@@ -3245,12 +3302,13 @@ static int selinux_task_prctl(int option,
+ unsigned long arg2,
+ unsigned long arg3,
+ unsigned long arg4,
+- unsigned long arg5)
++ unsigned long arg5,
++ long *rc_p)
+ {
+ /* The current prctl operations do not appear to require
+ any SELinux controls since they merely observe or modify
+ the state of the current process. */
+- return 0;
++ return secondary_ops->task_prctl(option, arg2, arg3, arg4, arg5, rc_p);
+ }
+
+ static int selinux_task_wait(struct task_struct *p)
@@ -3260,7 +3318,7 @@ static int selinux_task_wait(struct task_struct *p)
static void selinux_task_reparent_to_init(struct task_struct *p)
@@ -926344,6 +1230499,15 @@
return -EINVAL;
return size;
+@@ -5172,7 +5235,7 @@ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+ return security_sid_to_context(secid, secdata, seclen);
+ }
+
+-static int selinux_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
++static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
+ {
+ return security_context_to_sid(secdata, seclen, secid);
+ }
@@ -5194,7 +5257,6 @@ static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
if (!ksec)
return -ENOMEM;
@@ -926352,7 +1230516,24 @@
if (tsec->keycreate_sid)
ksec->sid = tsec->keycreate_sid;
else
-@@ -5238,6 +5300,8 @@ static int selinux_key_permission(key_ref_t key_ref,
+@@ -5235,9 +5297,25 @@ static int selinux_key_permission(key_ref_t key_ref,
+ SECCLASS_KEY, perm, NULL);
+ }
+
++static int selinux_key_getsecurity(struct key *key, char **_buffer)
++{
++ struct key_security_struct *ksec = key->security;
++ char *context = NULL;
++ unsigned len;
++ int rc;
++
++ rc = security_sid_to_context(ksec->sid, &context, &len);
++ if (!rc)
++ rc = len;
++ *_buffer = context;
++ return rc;
++}
++
#endif
static struct security_operations selinux_ops = {
@@ -926361,7 +1230542,7 @@
.ptrace = selinux_ptrace,
.capget = selinux_capget,
.capset_check = selinux_capset_check,
-@@ -5250,7 +5314,7 @@ static struct security_operations selinux_ops = {
+@@ -5250,7 +5328,7 @@ static struct security_operations selinux_ops = {
.vm_enough_memory = selinux_vm_enough_memory,
.netlink_send = selinux_netlink_send,
@@ -926370,7 +1230551,7 @@
.bprm_alloc_security = selinux_bprm_alloc_security,
.bprm_free_security = selinux_bprm_free_security,
-@@ -5263,13 +5327,13 @@ static struct security_operations selinux_ops = {
+@@ -5263,13 +5341,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,
@@ -926386,7 +1230567,7 @@
.sb_parse_opts_str = selinux_parse_opts_str,
-@@ -5294,11 +5358,12 @@ static struct security_operations selinux_ops = {
+@@ -5294,11 +5372,12 @@ static struct security_operations selinux_ops = {
.inode_getxattr = selinux_inode_getxattr,
.inode_listxattr = selinux_inode_listxattr,
.inode_removexattr = selinux_inode_removexattr,
@@ -926402,7 +1230583,7 @@
.file_permission = selinux_file_permission,
.file_alloc_security = selinux_file_alloc_security,
-@@ -5312,7 +5377,7 @@ static struct security_operations selinux_ops = {
+@@ -5312,7 +5391,7 @@ static struct security_operations selinux_ops = {
.file_send_sigiotask = selinux_file_send_sigiotask,
.file_receive = selinux_file_receive,
@@ -926411,7 +1230592,7 @@
.task_create = selinux_task_create,
.task_alloc_security = selinux_task_alloc_security,
-@@ -5322,7 +5387,7 @@ static struct security_operations selinux_ops = {
+@@ -5322,7 +5401,7 @@ static struct security_operations selinux_ops = {
.task_setgid = selinux_task_setgid,
.task_setpgid = selinux_task_setpgid,
.task_getpgid = selinux_task_getpgid,
@@ -926420,7 +1230601,7 @@
.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 = {
+@@ -5336,9 +5415,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,
@@ -926432,7 +1230613,7 @@
.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 = {
+@@ -5356,24 +5436,24 @@ static struct security_operations selinux_ops = {
.shm_shmctl = selinux_shm_shmctl,
.shm_shmat = selinux_shm_shmat,
@@ -926463,7 +1230644,7 @@
.unix_may_send = selinux_socket_unix_may_send,
.socket_create = selinux_socket_create,
-@@ -5395,7 +5461,7 @@ static struct security_operations selinux_ops = {
+@@ -5395,7 +5475,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,
@@ -926472,7 +1230653,7 @@
.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 = {
+@@ -5410,15 +5490,23 @@ 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,
@@ -926489,6 +1230670,7 @@
+ .key_alloc = selinux_key_alloc,
+ .key_free = selinux_key_free,
+ .key_permission = selinux_key_permission,
++ .key_getsecurity = selinux_key_getsecurity,
+#endif
+
+#ifdef CONFIG_AUDIT
@@ -926499,7 +1230681,7 @@
#endif
};
-@@ -5426,6 +5499,11 @@ static __init int selinux_init(void)
+@@ -5426,6 +5514,11 @@ static __init int selinux_init(void)
{
struct task_security_struct *tsec;
@@ -926511,7 +1230693,7 @@
if (!selinux_enabled) {
printk(KERN_INFO "SELinux: Disabled at boot.\n");
return 0;
-@@ -5446,15 +5524,14 @@ static __init int selinux_init(void)
+@@ -5446,23 +5539,14 @@ static __init int selinux_init(void)
original_ops = secondary_ops = security_ops;
if (!secondary_ops)
@@ -926528,10 +1230710,18 @@
+ else
printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
- }
+-
+-#ifdef CONFIG_KEYS
+- /* Add security information to initial keyrings */
+- selinux_key_alloc(&root_user_keyring, current,
+- KEY_ALLOC_NOT_IN_QUOTA);
+- selinux_key_alloc(&root_session_keyring, current,
+- KEY_ALLOC_NOT_IN_QUOTA);
+-#endif
- #ifdef CONFIG_KEYS
- /* Add security information to initial keyrings */
-@@ -5479,8 +5556,8 @@ next_sb:
+ return 0;
+ }
+@@ -5479,8 +5563,8 @@ next_sb:
if (!list_empty(&superblock_security_head)) {
struct superblock_security_struct *sbsec =
list_entry(superblock_security_head.next,
@@ -926542,7 +1230732,7 @@
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)
+@@ -5599,10 +5683,11 @@ static void selinux_nf_ip_exit(void)
#endif /* CONFIG_NETFILTER */
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
@@ -926555,7 +1230745,7 @@
if (ss_initialized) {
/* Not permitted after initial policy load. */
-@@ -5631,5 +5709,3 @@ int selinux_disable(void)
+@@ -5631,5 +5716,3 @@ int selinux_disable(void)
return 0;
}
#endif
@@ -926698,8 +1230888,38 @@
#define FD__USE 0x00000001UL
#define SOCKET__IOCTL 0x00000001UL
#define SOCKET__READ 0x00000002UL
+diff --git a/security/selinux/include/avc_ss.h b/security/selinux/include/avc_ss.h
+index ff869e8..c0d314d 100644
+--- a/security/selinux/include/avc_ss.h
++++ b/security/selinux/include/avc_ss.h
+@@ -10,22 +10,19 @@
+
+ int avc_ss_reset(u32 seqno);
+
+-struct av_perm_to_string
+-{
++struct av_perm_to_string {
+ u16 tclass;
+ u32 value;
+ const char *name;
+ };
+
+-struct av_inherit
+-{
++struct av_inherit {
+ u16 tclass;
+ const char **common_pts;
+ u32 common_base;
+ };
+
+-struct selinux_class_perm
+-{
++struct selinux_class_perm {
+ const struct av_perm_to_string *av_perm_to_string;
+ u32 av_pts_len;
+ const char **class_to_string;
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
-index 00a2809..9a9e7cd 100644
+index 00a2809..487a7d8 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -41,10 +41,6 @@ void selinux_netlbl_cache_invalidate(void);
@@ -926713,7 +1230933,13 @@
int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
u16 family,
-@@ -73,18 +69,6 @@ static inline void selinux_netlbl_sk_security_reset(
+@@ -68,23 +64,11 @@ static inline void selinux_netlbl_cache_invalidate(void)
+ }
+
+ static inline void selinux_netlbl_sk_security_reset(
+- struct sk_security_struct *ssec,
++ struct sk_security_struct *ssec,
+ int family)
{
return;
}
@@ -926770,51 +1230996,120 @@
+
+#endif
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
-index c6c2bb4..300b61b 100644
+index c6c2bb4..032c235 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
-@@ -28,14 +28,12 @@
+@@ -4,16 +4,16 @@
+ * This file contains the SELinux security data structures for kernel objects.
+ *
+ * Author(s): Stephen Smalley, <sds at epoch.ncsc.mil>
+- * Chris Vance, <cvance at nai.com>
+- * Wayne Salamon, <wsalamon at nai.com>
+- * James Morris <jmorris at redhat.com>
++ * Chris Vance, <cvance at nai.com>
++ * Wayne Salamon, <wsalamon at nai.com>
++ * James Morris <jmorris at redhat.com>
+ *
+ * Copyright (C) 2001,2002 Networks Associates Technology, Inc.
+ * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris at redhat.com>
+ *
+ * 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.
+ */
+ #ifndef _SELINUX_OBJSEC_H_
+ #define _SELINUX_OBJSEC_H_
+@@ -28,64 +28,58 @@
#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 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 */
++ 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 */
};
struct inode_security_struct {
-@@ -50,7 +48,6 @@ struct inode_security_struct {
+- struct inode *inode; /* back pointer to inode object */
+- struct list_head list; /* list of inode_security_struct */
+- u32 task_sid; /* SID of creating task */
+- u32 sid; /* SID of this object */
+- u16 sclass; /* security class of this object */
+- unsigned char initialized; /* initialization flag */
++ struct inode *inode; /* back pointer to inode object */
++ struct list_head list; /* list of inode_security_struct */
++ u32 task_sid; /* SID of creating task */
++ u32 sid; /* SID of this object */
++ u16 sclass; /* security class of this object */
++ unsigned char initialized; /* initialization flag */
+ struct mutex lock;
+- unsigned char inherit; /* inherit SID from parent entry */
++ unsigned char inherit; /* inherit SID from parent entry */
};
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 {
+- 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 */
+- u32 pseqno; /* Policy seqno at the time of file open */
++ 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 */
++ u32 pseqno; /* Policy seqno at the time of file open */
+ };
+
+ struct superblock_security_struct {
+- struct super_block *sb; /* back pointer to sb object */
+- struct list_head list; /* list of superblock_security_struct */
++ struct super_block *sb; /* back pointer to sb object */
++ struct list_head list; /* list of superblock_security_struct */
+ u32 sid; /* SID of file system superblock */
+ u32 def_sid; /* default SID for labeling */
+ u32 mntpoint_sid; /* SECURITY_FS_USE_MNTPOINT context for files */
+- unsigned int behavior; /* labeling behavior */
+- unsigned char initialized; /* initialization flag */
++ unsigned int behavior; /* labeling behavior */
++ unsigned char initialized; /* initialization flag */
+ unsigned char flags; /* which mount options were specified */
+- unsigned char proc; /* proc fs */
++ unsigned char proc; /* proc fs */
+ struct mutex lock;
+ struct list_head isec_head;
+ spinlock_t isec_lock;
};
struct msg_security_struct {
- struct msg_msg *msg; /* back pointer */
- u32 sid; /* SID of message */
+- u32 sid; /* SID of message */
++ 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 */
+- u32 sid; /* SID of IPC resource */
++ 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 */
+- u32 sid; /* SID for transformed process */
++ u32 sid; /* SID for transformed process */
unsigned char set;
+ /*
@@ -109,8 +103,13 @@ struct netnode_security_struct {
u16 family; /* address family */
};
@@ -926830,7 +1231125,7 @@
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 {
+@@ -120,13 +119,11 @@ struct sk_security_struct {
NLBL_REQUIRE,
NLBL_LABELED,
} nlbl_state;
@@ -926840,11 +1231135,13 @@
struct key_security_struct {
- struct key *obj; /* back pointer */
- u32 sid; /* SID of key */
+- u32 sid; /* SID of key */
++ u32 sid; /* SID of key */
};
+ extern unsigned int selinux_checkreqprot;
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
-index 44e12ec..1904c46 100644
+index 44e12ec..ad30ac4 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -26,13 +26,14 @@
@@ -926875,7 +1231172,7 @@
struct netlbl_lsm_secattr;
extern int selinux_enabled;
-@@ -48,11 +54,13 @@ extern int selinux_mls_enabled;
+@@ -48,13 +54,15 @@ extern int selinux_mls_enabled;
/* Policy capabilities */
enum {
POLICYDB_CAPABILITY_NETPEER,
@@ -926887,7 +1231184,10 @@
extern int selinux_policycap_netpeer;
+extern int selinux_policycap_openperm;
- int security_load_policy(void * data, size_t len);
+-int security_load_policy(void * data, size_t len);
++int security_load_policy(void *data, size_t len);
+
+ int security_policycap_supported(unsigned int req_cap);
@@ -67,6 +75,8 @@ struct av_decision {
u32 seqno;
@@ -926898,7 +1231198,18 @@
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,
+@@ -83,17 +93,16 @@ int security_change_sid(u32 ssid, u32 tsid,
+ int security_sid_to_context(u32 sid, char **scontext,
+ u32 *scontext_len);
+
+-int security_context_to_sid(char *scontext, u32 scontext_len,
++int security_context_to_sid(const char *scontext, u32 scontext_len,
+ u32 *out_sid);
+
+-int security_context_to_sid_default(char *scontext, u32 scontext_len,
++int security_context_to_sid_default(const char *scontext, u32 scontext_len,
+ u32 *out_sid, u32 def_sid, gfp_t gfp_flags);
+
int security_get_user_sids(u32 callsid, char *username,
u32 **sids, u32 *nel);
@@ -926908,6 +1231219,15 @@
int security_netif_sid(char *name, u32 *if_sid);
+@@ -101,7 +110,7 @@ int security_node_sid(u16 domain, void *addr, u32 addrlen,
+ u32 *out_sid);
+
+ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
+- u16 tclass);
++ u16 tclass);
+
+ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_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
@@ -927287,11 +1231607,225 @@
}
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
-index f3c526f..2edc4c5 100644
+index f3c526f..b6ccd09 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]);
+@@ -40,11 +40,17 @@
+ #include <net/ipv6.h>
+ #include <asm/bug.h>
+
++#include "netnode.h"
+ #include "objsec.h"
+
+ #define SEL_NETNODE_HASH_SIZE 256
+ #define SEL_NETNODE_HASH_BKT_LIMIT 16
+
++struct sel_netnode_bkt {
++ unsigned int size;
++ struct list_head list;
++};
++
+ struct sel_netnode {
+ struct netnode_security_struct nsec;
+
+@@ -60,7 +66,7 @@ struct sel_netnode {
+
+ static LIST_HEAD(sel_netnode_list);
+ static DEFINE_SPINLOCK(sel_netnode_lock);
+-static struct list_head sel_netnode_hash[SEL_NETNODE_HASH_SIZE];
++static struct sel_netnode_bkt sel_netnode_hash[SEL_NETNODE_HASH_SIZE];
+
+ /**
+ * sel_netnode_free - Frees a node entry
+@@ -87,7 +93,7 @@ static void sel_netnode_free(struct rcu_head *p)
+ * the bucket number for the given IP address.
+ *
+ */
+-static u32 sel_netnode_hashfn_ipv4(__be32 addr)
++static unsigned int sel_netnode_hashfn_ipv4(__be32 addr)
+ {
+ /* at some point we should determine if the mismatch in byte order
+ * affects the hash function dramatically */
+@@ -103,7 +109,7 @@ static u32 sel_netnode_hashfn_ipv4(__be32 addr)
+ * the bucket number for the given IP address.
+ *
+ */
+-static u32 sel_netnode_hashfn_ipv6(const struct in6_addr *addr)
++static unsigned int sel_netnode_hashfn_ipv6(const struct in6_addr *addr)
+ {
+ /* just hash the least significant 32 bits to keep things fast (they
+ * are the most likely to be different anyway), we can revisit this
+@@ -123,7 +129,7 @@ static u32 sel_netnode_hashfn_ipv6(const struct in6_addr *addr)
+ */
+ static struct sel_netnode *sel_netnode_find(const void *addr, u16 family)
+ {
+- u32 idx;
++ unsigned int idx;
+ struct sel_netnode *node;
+
+ switch (family) {
+@@ -137,7 +143,7 @@ static struct sel_netnode *sel_netnode_find(const void *addr, u16 family)
+ BUG();
+ }
+
+- list_for_each_entry_rcu(node, &sel_netnode_hash[idx], list)
++ list_for_each_entry_rcu(node, &sel_netnode_hash[idx].list, list)
+ if (node->nsec.family == family)
+ switch (family) {
+ case PF_INET:
+@@ -159,15 +165,12 @@ static struct sel_netnode *sel_netnode_find(const void *addr, u16 family)
+ * @node: the new node record
+ *
+ * Description:
+- * Add a new node record to the network address hash table. Returns zero on
+- * success, negative values on failure.
++ * Add a new node record to the network address hash table.
+ *
+ */
+-static int sel_netnode_insert(struct sel_netnode *node)
++static void sel_netnode_insert(struct sel_netnode *node)
+ {
+- u32 idx;
+- u32 count = 0;
+- struct sel_netnode *iter;
++ unsigned int idx;
+
+ switch (node->nsec.family) {
+ case PF_INET:
+@@ -179,32 +182,21 @@ static int sel_netnode_insert(struct sel_netnode *node)
+ default:
+ BUG();
+ }
+- list_add_rcu(&node->list, &sel_netnode_hash[idx]);
++
++ INIT_RCU_HEAD(&node->rcu);
+
+ /* 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 */
+- list_for_each_entry(iter, &sel_netnode_hash[idx], list)
+- if (++count > SEL_NETNODE_HASH_BKT_LIMIT) {
+- list_del_rcu(&iter->list);
+- call_rcu(&iter->rcu, sel_netnode_free);
+- break;
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * sel_netnode_destroy - Remove a node record from the table
+- * @node: the existing node record
+- *
+- * Description:
+- * Remove an existing node record from the network address table.
+- *
+- */
+-static void sel_netnode_destroy(struct sel_netnode *node)
+-{
+- list_del_rcu(&node->list);
+- call_rcu(&node->rcu, sel_netnode_free);
++ list_add_rcu(&node->list, &sel_netnode_hash[idx].list);
++ if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) {
++ struct sel_netnode *tail;
++ tail = list_entry(
++ rcu_dereference(sel_netnode_hash[idx].list.prev),
++ struct sel_netnode, list);
++ list_del_rcu(&tail->list);
++ call_rcu(&tail->rcu, sel_netnode_free);
++ } else
++ sel_netnode_hash[idx].size++;
+ }
+
+ /**
+@@ -222,7 +214,7 @@ static void sel_netnode_destroy(struct sel_netnode *node)
+ */
+ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
+ {
+- int ret;
++ int ret = -ENOMEM;
+ struct sel_netnode *node;
+ struct sel_netnode *new = NULL;
+
+@@ -230,25 +222,21 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
+ node = sel_netnode_find(addr, family);
+ if (node != NULL) {
+ *sid = node->nsec.sid;
+- ret = 0;
+- goto out;
++ spin_unlock_bh(&sel_netnode_lock);
++ return 0;
+ }
+ new = kzalloc(sizeof(*new), GFP_ATOMIC);
+- if (new == NULL) {
+- ret = -ENOMEM;
++ if (new == NULL)
+ goto out;
+- }
+ switch (family) {
+ case PF_INET:
+ ret = security_node_sid(PF_INET,
+- addr, sizeof(struct in_addr),
+- &new->nsec.sid);
++ addr, sizeof(struct in_addr), sid);
+ new->nsec.addr.ipv4 = *(__be32 *)addr;
+ break;
+ case PF_INET6:
+ ret = security_node_sid(PF_INET6,
+- addr, sizeof(struct in6_addr),
+- &new->nsec.sid);
++ addr, sizeof(struct in6_addr), sid);
+ ipv6_addr_copy(&new->nsec.addr.ipv6, addr);
+ break;
+ default:
+@@ -256,11 +244,10 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
+ }
+ if (ret != 0)
+ goto out;
++
+ new->nsec.family = family;
+- ret = sel_netnode_insert(new);
+- if (ret != 0)
+- goto out;
+- *sid = new->nsec.sid;
++ new->nsec.sid = *sid;
++ sel_netnode_insert(new);
+
+ out:
+ spin_unlock_bh(&sel_netnode_lock);
+@@ -312,13 +299,18 @@ int sel_netnode_sid(void *addr, u16 family, u32 *sid)
+ */
+ static void sel_netnode_flush(void)
+ {
+- u32 idx;
+- struct sel_netnode *node;
++ unsigned int idx;
++ struct sel_netnode *node, *node_tmp;
+
+ spin_lock_bh(&sel_netnode_lock);
+- for (idx = 0; idx < SEL_NETNODE_HASH_SIZE; idx++)
+- list_for_each_entry(node, &sel_netnode_hash[idx], list)
+- sel_netnode_destroy(node);
++ for (idx = 0; idx < SEL_NETNODE_HASH_SIZE; idx++) {
++ list_for_each_entry_safe(node, node_tmp,
++ &sel_netnode_hash[idx].list, list) {
++ list_del_rcu(&node->list);
++ call_rcu(&node->rcu, sel_netnode_free);
++ }
++ sel_netnode_hash[idx].size = 0;
++ }
+ spin_unlock_bh(&sel_netnode_lock);
+ }
+
+@@ -340,11 +332,13 @@ static __init int sel_netnode_init(void)
+ if (!selinux_enabled)
+ return 0;
+
+- for (iter = 0; iter < SEL_NETNODE_HASH_SIZE; iter++)
+- INIT_LIST_HEAD(&sel_netnode_hash[iter]);
++ for (iter = 0; iter < SEL_NETNODE_HASH_SIZE; iter++) {
++ INIT_LIST_HEAD(&sel_netnode_hash[iter].list);
++ sel_netnode_hash[iter].size = 0;
++ }
ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET,
- SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
@@ -927301,10 +1231835,10 @@
diff --git a/security/selinux/netport.c b/security/selinux/netport.c
new file mode 100644
-index 0000000..68ede3c
+index 0000000..90b4cff
--- /dev/null
+++ b/security/selinux/netport.c
-@@ -0,0 +1,286 @@
+@@ -0,0 +1,282 @@
+/*
+ * Network port table
+ *
@@ -927421,8 +1231955,7 @@
+
+ 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)
++ if (port->psec.port == pnum && port->psec.protocol == protocol)
+ return port;
+
+ return NULL;
@@ -927433,11 +1231966,10 @@
+ * @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.
++ * Add a new port record to the network address hash table.
+ *
+ */
-+static int sel_netport_insert(struct sel_netport *port)
++static void sel_netport_insert(struct sel_netport *port)
+{
+ unsigned int idx;
+
@@ -927447,13 +1231979,13 @@
+ 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);
++ tail = list_entry(
++ rcu_dereference(sel_netport_hash[idx].list.prev),
++ struct sel_netport, list);
++ list_del_rcu(&tail->list);
+ call_rcu(&tail->rcu, sel_netport_free);
+ } else
+ sel_netport_hash[idx].size++;
-+
-+ return 0;
+}
+
+/**
@@ -927470,7 +1232002,7 @@
+ */
+static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid)
+{
-+ int ret;
++ int ret = -ENOMEM;
+ struct sel_netport *port;
+ struct sel_netport *new = NULL;
+
@@ -927478,23 +1232010,20 @@
+ port = sel_netport_find(protocol, pnum);
+ if (port != NULL) {
+ *sid = port->psec.sid;
-+ ret = 0;
-+ goto out;
++ spin_unlock_bh(&sel_netport_lock);
++ return 0;
+ }
+ new = kzalloc(sizeof(*new), GFP_ATOMIC);
-+ if (new == NULL) {
-+ ret = -ENOMEM;
++ if (new == NULL)
+ goto out;
-+ }
-+ ret = security_port_sid(protocol, pnum, &new->psec.sid);
++ ret = security_port_sid(protocol, pnum, 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;
++ new->psec.sid = *sid;
++ sel_netport_insert(new);
+
+out:
+ spin_unlock_bh(&sel_netport_lock);
@@ -927546,11 +1232075,12 @@
+static void sel_netport_flush(void)
+{
+ unsigned int idx;
-+ struct sel_netport *port;
++ struct sel_netport *port, *port_tmp;
+
+ 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_for_each_entry_safe(port, port_tmp,
++ &sel_netport_hash[idx].list, list) {
+ list_del_rcu(&port->list);
+ call_rcu(&port->rcu, sel_netport_free);
+ }
@@ -928559,6 +1233089,40 @@
avd->auditallow |= node->datum.data;
}
return;
+diff --git a/security/selinux/ss/conditional.h b/security/selinux/ss/conditional.h
+index f3a1fc6..65b9f83 100644
+--- a/security/selinux/ss/conditional.h
++++ b/security/selinux/ss/conditional.h
+@@ -59,10 +59,10 @@ struct cond_node {
+ struct cond_node *next;
+ };
+
+-int cond_policydb_init(struct policydb* p);
+-void cond_policydb_destroy(struct policydb* p);
++int cond_policydb_init(struct policydb *p);
++void cond_policydb_destroy(struct policydb *p);
+
+-int cond_init_bool_indexes(struct policydb* p);
++int cond_init_bool_indexes(struct policydb *p);
+ int cond_destroy_bool(void *key, void *datum, void *p);
+
+ int cond_index_bool(void *key, void *datum, void *datap);
+diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h
+index 2eee0da..b9a6f7f 100644
+--- a/security/selinux/ss/context.h
++++ b/security/selinux/ss/context.h
+@@ -84,9 +84,9 @@ static inline int mls_context_cmp(struct context *c1, struct context *c2)
+ return 1;
+
+ return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
+- ebitmap_cmp(&c1->range.level[0].cat,&c2->range.level[0].cat) &&
++ ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) &&
+ (c1->range.level[1].sens == c2->range.level[1].sens) &&
+- ebitmap_cmp(&c1->range.level[1].cat,&c2->range.level[1].cat));
++ ebitmap_cmp(&c1->range.level[1].cat, &c2->range.level[1].cat));
+ }
+
+ static inline void mls_context_destroy(struct context *c)
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index 920b5e3..ddc2754 100644
--- a/security/selinux/ss/ebitmap.c
@@ -928644,6 +1233208,30 @@
{
struct hashtab *p;
u32 i;
+diff --git a/security/selinux/ss/hashtab.h b/security/selinux/ss/hashtab.h
+index 7e2ff3e..953872c 100644
+--- a/security/selinux/ss/hashtab.h
++++ b/security/selinux/ss/hashtab.h
+@@ -40,8 +40,8 @@ struct hashtab_info {
+ * the new hash table otherwise.
+ */
+ 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);
+
+ /*
+ * Inserts the specified (key, datum) pair into the specified hash table.
+@@ -49,7 +49,7 @@ struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *
+ * Returns -ENOMEM on memory allocation error,
+ * -EEXIST if there is already an entry with the same key,
+ * -EINVAL for general errors or
+- * 0 otherwise.
++ 0 otherwise.
+ */
+ int hashtab_insert(struct hashtab *h, void *k, void *d);
+
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index feaf0a5..8b1706b 100644
--- a/security/selinux/ss/mls.c
@@ -928751,6 +1233339,59 @@
}
}
/* Fallthrough */
+diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
+index ab53663..0fdf625 100644
+--- a/security/selinux/ss/mls.h
++++ b/security/selinux/ss/mls.h
+@@ -13,7 +13,7 @@
+ /*
+ * Updated: Hewlett-Packard <paul.moore at hp.com>
+ *
+- * Added support to import/export the MLS label from NetLabel
++ * Added support to import/export the MLS label from NetLabel
+ *
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ */
+@@ -31,7 +31,7 @@ int mls_range_isvalid(struct policydb *p, struct mls_range *r);
+ int mls_level_isvalid(struct policydb *p, struct mls_level *l);
+
+ int mls_context_to_sid(char oldc,
+- char **scontext,
++ char **scontext,
+ struct context *context,
+ struct sidtab *s,
+ u32 def_sid);
+@@ -49,7 +49,7 @@ int mls_compute_sid(struct context *scontext,
+ struct context *newcontext);
+
+ int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
+- struct context *usercon);
++ struct context *usercon);
+
+ #ifdef CONFIG_NETLABEL
+ void mls_export_netlbl_lvl(struct context *context,
+diff --git a/security/selinux/ss/mls_types.h b/security/selinux/ss/mls_types.h
+index 0c692d5..b6e943a 100644
+--- a/security/selinux/ss/mls_types.h
++++ b/security/selinux/ss/mls_types.h
+@@ -31,7 +31,7 @@ static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2)
+ return 1;
+
+ return ((l1->sens == l2->sens) &&
+- ebitmap_cmp(&l1->cat, &l2->cat));
++ ebitmap_cmp(&l1->cat, &l2->cat));
+ }
+
+ static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2)
+@@ -40,7 +40,7 @@ static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2)
+ return 1;
+
+ return ((l1->sens >= l2->sens) &&
+- ebitmap_contains(&l1->cat, &l2->cat));
++ ebitmap_contains(&l1->cat, &l2->cat));
+ }
+
+ #define mls_level_incomp(l1, l2) \
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index bd7d6a0..84f8cc7 100644
--- a/security/selinux/ss/policydb.c
@@ -929447,9 +1234088,46 @@
if (!rc)
rc = -EINVAL;
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
-index c4ce996..ba593a3 100644
+index c4ce996..4253370 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
+@@ -12,12 +12,12 @@
+ *
+ * Updated: Frank Mayer <mayerf at tresys.com> and Karl MacMillan <kmacmillan at tresys.com>
+ *
+- * Added conditional policy language extensions
++ * Added conditional policy language extensions
+ *
+ * Copyright (C) 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.
+ */
+
+@@ -221,7 +221,7 @@ struct policydb {
+ /* type enforcement conditional access vectors and transitions */
+ struct avtab te_cond_avtab;
+ /* linked list indexing te_cond_avtab by conditional */
+- struct cond_node* cond_list;
++ struct cond_node *cond_list;
+
+ /* role allows */
+ struct role_allow *role_allow;
+@@ -230,10 +230,10 @@ struct policydb {
+ TCP or UDP port numbers, network interfaces and nodes */
+ struct ocontext *ocontexts[OCON_NUM];
+
+- /* security contexts for files in filesystems that cannot support
++ /* security contexts for files in filesystems that cannot support
+ a persistent label mapping or use another
+ fixed labeling behavior. */
+- struct genfs *genfs;
++ struct genfs *genfs;
+
+ /* range transitions */
+ struct range_trans *range_tr;
@@ -243,6 +243,8 @@ struct policydb {
struct ebitmap policycaps;
@@ -929460,7 +1234138,7 @@
unsigned int reject_unknown : 1;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
-index 3f2bad2..2daaddb 100644
+index 3f2bad2..dcc2e1c 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2,7 +2,7 @@
@@ -929745,6 +1234423,35 @@
rc = -EINVAL;
goto out_unlock;
}
+@@ -680,7 +708,7 @@ out:
+
+ }
+
+-static int security_context_to_sid_core(char *scontext, u32 scontext_len,
++static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
+ u32 *sid, u32 def_sid, gfp_t gfp_flags)
+ {
+ char *scontext2;
+@@ -807,7 +835,7 @@ out:
+ * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
+ * memory is available, or 0 on success.
+ */
+-int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
++int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid)
+ {
+ return security_context_to_sid_core(scontext, scontext_len,
+ sid, SECSID_NULL, GFP_KERNEL);
+@@ -830,8 +858,8 @@ int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
+ * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
+ * memory is available, or 0 on success.
+ */
+-int security_context_to_sid_default(char *scontext, u32 scontext_len, u32 *sid,
+- u32 def_sid, gfp_t gfp_flags)
++int security_context_to_sid_default(const char *scontext, u32 scontext_len,
++ u32 *sid, u32 def_sid, gfp_t gfp_flags)
+ {
+ return security_context_to_sid_core(scontext, scontext_len,
+ sid, def_sid, gfp_flags);
@@ -898,15 +926,15 @@ static int security_compute_sid(u32 ssid,
scontext = sidtab_search(&sidtab, ssid);
@@ -930431,10 +1235138,18 @@
/*
* Stricly for CIPSO level manipulation.
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
-index 732ba27..4215971 100644
+index 732ba27..b5c8f92 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)
+@@ -26,6 +26,7 @@
+ #include <linux/pipe_fs_i.h>
+ #include <net/netlabel.h>
+ #include <net/cipso_ipv4.h>
++#include <linux/audit.h>
+
+ #include "smack.h"
+
+@@ -315,10 +316,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.
*/
@@ -930447,7 +1235162,91 @@
return smk_curacc(sbp->smk_floor, MAY_WRITE);
}
-@@ -1275,7 +1275,7 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
+@@ -574,8 +575,8 @@ static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+ *
+ * Returns 0 if access is permitted, an error code otherwise
+ */
+-static int smack_inode_setxattr(struct dentry *dentry, char *name,
+- void *value, size_t size, int flags)
++static int smack_inode_setxattr(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags)
+ {
+ int rc = 0;
+
+@@ -604,8 +605,8 @@ static int smack_inode_setxattr(struct dentry *dentry, char *name,
+ * Set the pointer in the inode blob to the entry found
+ * in the master label list.
+ */
+-static void smack_inode_post_setxattr(struct dentry *dentry, char *name,
+- void *value, size_t size, int flags)
++static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags)
+ {
+ struct inode_smack *isp;
+ char *nsp;
+@@ -641,7 +642,7 @@ static void smack_inode_post_setxattr(struct dentry *dentry, char *name,
+ *
+ * Returns 0 if access is permitted, an error code otherwise
+ */
+-static int smack_inode_getxattr(struct dentry *dentry, char *name)
++static int smack_inode_getxattr(struct dentry *dentry, const char *name)
+ {
+ return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ);
+ }
+@@ -655,7 +656,7 @@ static int smack_inode_getxattr(struct dentry *dentry, char *name)
+ *
+ * Returns 0 if access is permitted, an error code otherwise
+ */
+-static int smack_inode_removexattr(struct dentry *dentry, char *name)
++static int smack_inode_removexattr(struct dentry *dentry, const char *name)
+ {
+ int rc = 0;
+
+@@ -752,6 +753,18 @@ static int smack_inode_listsecurity(struct inode *inode, char *buffer,
+ return -EINVAL;
+ }
+
++/**
++ * smack_inode_getsecid - Extract inode's security id
++ * @inode: inode to extract the info from
++ * @secid: where result will be saved
++ */
++static void smack_inode_getsecid(const struct inode *inode, u32 *secid)
++{
++ struct inode_smack *isp = inode->i_security;
++
++ *secid = smack_to_secid(isp->smk_inode);
++}
++
+ /*
+ * File Hooks
+ */
+@@ -1118,15 +1131,6 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info,
+ int sig, u32 secid)
+ {
+ /*
+- * Special cases where signals really ought to go through
+- * in spite of policy. Stephen Smalley suggests it may
+- * make sense to change the caller so that it doesn't
+- * bother with the LSM hook in these cases.
+- */
+- if (info != SEND_SIG_NOINFO &&
+- (is_si_special(info) || SI_FROMKERNEL(info)))
+- return 0;
+- /*
+ * Sending a signal requires that the sender
+ * can write the receiver.
+ */
+@@ -1242,7 +1246,7 @@ static void smack_set_catset(char *catset, struct netlbl_lsm_secattr *sap)
+ int rc;
+ int byte;
+
+- if (catset == 0)
++ if (!catset)
+ return;
+
+ sap->flags |= NETLBL_SECATTR_MLS_CAT;
+@@ -1275,7 +1279,7 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
switch (smack_net_nltype) {
case NETLBL_NLTYPE_CIPSOV4:
@@ -930456,7 +1235255,160 @@
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)
+@@ -1805,6 +1809,18 @@ static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag)
+ return smk_curacc(isp, may);
+ }
+
++/**
++ * smack_ipc_getsecid - Extract smack security id
++ * @ipcp: the object permissions
++ * @secid: where result will be saved
++ */
++static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid)
++{
++ char *smack = ipp->security;
++
++ *secid = smack_to_secid(smack);
++}
++
+ /* module stacking operations */
+
+ /**
+@@ -2382,6 +2398,124 @@ static int smack_key_permission(key_ref_t key_ref,
+ #endif /* CONFIG_KEYS */
+
+ /*
++ * Smack Audit hooks
++ *
++ * Audit requires a unique representation of each Smack specific
++ * rule. This unique representation is used to distinguish the
++ * object to be audited from remaining kernel objects and also
++ * works as a glue between the audit hooks.
++ *
++ * Since repository entries are added but never deleted, we'll use
++ * the smack_known label address related to the given audit rule as
++ * the needed unique representation. This also better fits the smack
++ * model where nearly everything is a label.
++ */
++#ifdef CONFIG_AUDIT
++
++/**
++ * smack_audit_rule_init - Initialize a smack audit rule
++ * @field: audit rule fields given from user-space (audit.h)
++ * @op: required testing operator (=, !=, >, <, ...)
++ * @rulestr: smack label to be audited
++ * @vrule: pointer to save our own audit rule representation
++ *
++ * Prepare to audit cases where (@field @op @rulestr) is true.
++ * The label to be audited is created if necessay.
++ */
++static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
++{
++ char **rule = (char **)vrule;
++ *rule = NULL;
++
++ if (field != AUDIT_SUBJ_USER && field != AUDIT_OBJ_USER)
++ return -EINVAL;
++
++ if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL)
++ return -EINVAL;
++
++ *rule = smk_import(rulestr, 0);
++
++ return 0;
++}
++
++/**
++ * smack_audit_rule_known - Distinguish Smack audit rules
++ * @krule: rule of interest, in Audit kernel representation format
++ *
++ * This is used to filter Smack rules from remaining Audit ones.
++ * If it's proved that this rule belongs to us, the
++ * audit_rule_match hook will be called to do the final judgement.
++ */
++static int smack_audit_rule_known(struct audit_krule *krule)
++{
++ struct audit_field *f;
++ int i;
++
++ for (i = 0; i < krule->field_count; i++) {
++ f = &krule->fields[i];
++
++ if (f->type == AUDIT_SUBJ_USER || f->type == AUDIT_OBJ_USER)
++ return 1;
++ }
++
++ return 0;
++}
++
++/**
++ * smack_audit_rule_match - Audit given object ?
++ * @secid: security id for identifying the object to test
++ * @field: audit rule flags given from user-space
++ * @op: required testing operator
++ * @vrule: smack internal rule presentation
++ * @actx: audit context associated with the check
++ *
++ * The core Audit hook. It's used to take the decision of
++ * whether to audit or not to audit a given object.
++ */
++static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule,
++ struct audit_context *actx)
++{
++ char *smack;
++ char *rule = vrule;
++
++ if (!rule) {
++ audit_log(actx, GFP_KERNEL, AUDIT_SELINUX_ERR,
++ "Smack: missing rule\n");
++ return -ENOENT;
++ }
++
++ if (field != AUDIT_SUBJ_USER && field != AUDIT_OBJ_USER)
++ return 0;
++
++ smack = smack_from_secid(secid);
++
++ /*
++ * No need to do string comparisons. If a match occurs,
++ * both pointers will point to the same smack_known
++ * label.
++ */
++ if (op == AUDIT_EQUAL)
++ return (rule == smack);
++ if (op == AUDIT_NOT_EQUAL)
++ return (rule != smack);
++
++ return 0;
++}
++
++/**
++ * smack_audit_rule_free - free smack rule representation
++ * @vrule: rule to be freed.
++ *
++ * No memory was allocated.
++ */
++static void smack_audit_rule_free(void *vrule)
++{
++ /* No-op */
++}
++
++#endif /* CONFIG_AUDIT */
++
++/*
+ * smack_secid_to_secctx - return the smack label for a secid
+ * @secid: incoming integer
+ * @secdata: destination
+@@ -2406,7 +2540,7 @@ static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+ *
+ * Exists for audit and networking code.
+ */
+-static int smack_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
++static int smack_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
+ {
+ *secid = smack_to_secid(secdata);
+ return 0;
+@@ -2424,7 +2558,9 @@ static void smack_release_secctx(char *secdata, u32 seclen)
{
}
@@ -930467,7 +1235419,49 @@
.ptrace = smack_ptrace,
.capget = cap_capget,
.capset_check = cap_capset_check,
-@@ -2557,6 +2559,9 @@ static struct security_operations smack_ops = {
+@@ -2465,6 +2601,7 @@ static struct security_operations smack_ops = {
+ .inode_getsecurity = smack_inode_getsecurity,
+ .inode_setsecurity = smack_inode_setsecurity,
+ .inode_listsecurity = smack_inode_listsecurity,
++ .inode_getsecid = smack_inode_getsecid,
+
+ .file_permission = smack_file_permission,
+ .file_alloc_security = smack_file_alloc_security,
+@@ -2493,8 +2630,10 @@ static struct security_operations smack_ops = {
+ .task_wait = smack_task_wait,
+ .task_reparent_to_init = cap_task_reparent_to_init,
+ .task_to_inode = smack_task_to_inode,
++ .task_prctl = cap_task_prctl,
+
+ .ipc_permission = smack_ipc_permission,
++ .ipc_getsecid = smack_ipc_getsecid,
+
+ .msg_msg_alloc_security = smack_msg_msg_alloc_security,
+ .msg_msg_free_security = smack_msg_msg_free_security,
+@@ -2539,12 +2678,22 @@ static struct security_operations smack_ops = {
+ .sk_free_security = smack_sk_free_security,
+ .sock_graft = smack_sock_graft,
+ .inet_conn_request = smack_inet_conn_request,
++
+ /* key management security hooks */
+ #ifdef CONFIG_KEYS
+ .key_alloc = smack_key_alloc,
+ .key_free = smack_key_free,
+ .key_permission = smack_key_permission,
+ #endif /* CONFIG_KEYS */
++
++ /* Audit hooks */
++#ifdef CONFIG_AUDIT
++ .audit_rule_init = smack_audit_rule_init,
++ .audit_rule_known = smack_audit_rule_known,
++ .audit_rule_match = smack_audit_rule_match,
++ .audit_rule_free = smack_audit_rule_free,
++#endif /* CONFIG_AUDIT */
++
+ .secid_to_secctx = smack_secid_to_secctx,
+ .secctx_to_secid = smack_secctx_to_secid,
+ .release_secctx = smack_release_secctx,
+@@ -2557,6 +2706,9 @@ static struct security_operations smack_ops = {
*/
static __init int smack_init(void)
{
@@ -930478,10 +1235472,41 @@
/*
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
-index cfae8af..6ba2837 100644
+index cfae8af..271a835 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
-@@ -965,12 +965,21 @@ static struct vfsmount *smackfs_mount;
+@@ -317,13 +317,14 @@ static const struct file_operations smk_load_ops = {
+ /**
+ * smk_cipso_doi - initialize the CIPSO domain
+ */
+-void smk_cipso_doi(void)
++static void smk_cipso_doi(void)
+ {
+ int rc;
+ struct cipso_v4_doi *doip;
+ struct netlbl_audit audit_info;
+
+ audit_info.loginuid = audit_get_loginuid(current);
++ audit_info.sessionid = audit_get_sessionid(current);
+ audit_info.secid = smack_to_secid(current->security);
+
+ rc = netlbl_cfg_map_del(NULL, &audit_info);
+@@ -350,12 +351,13 @@ void smk_cipso_doi(void)
+ /**
+ * smk_unlbl_ambient - initialize the unlabeled domain
+ */
+-void smk_unlbl_ambient(char *oldambient)
++static void smk_unlbl_ambient(char *oldambient)
+ {
+ int rc;
+ struct netlbl_audit audit_info;
+
+ audit_info.loginuid = audit_get_loginuid(current);
++ audit_info.sessionid = audit_get_sessionid(current);
+ audit_info.secid = smack_to_secid(current->security);
+
+ if (oldambient != NULL) {
+@@ -965,12 +967,21 @@ static struct vfsmount *smackfs_mount;
*
* register the smackfs
*
@@ -930737,6 +1235762,28 @@
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/info.c b/sound/core/info.c
+index 9977ec2..cb5ead3 100644
+--- a/sound/core/info.c
++++ b/sound/core/info.c
+@@ -544,7 +544,7 @@ int __init snd_info_init(void)
+ {
+ struct proc_dir_entry *p;
+
+- p = snd_create_proc_entry("asound", S_IFDIR | S_IRUGO | S_IXUGO, &proc_root);
++ p = snd_create_proc_entry("asound", S_IFDIR | S_IRUGO | S_IXUGO, NULL);
+ if (p == NULL)
+ return -ENOMEM;
+ snd_proc_root = p;
+@@ -594,7 +594,7 @@ int __exit snd_info_done(void)
+ #ifdef CONFIG_SND_OSSEMUL
+ snd_info_free_entry(snd_oss_root);
+ #endif
+- snd_remove_proc_entry(&proc_root, snd_proc_root);
++ snd_remove_proc_entry(NULL, snd_proc_root);
+ }
+ return 0;
+ }
diff --git a/sound/core/init.c b/sound/core/init.c
index e3338d6..ac05734 100644
--- a/sound/core/init.c
@@ -930828,6 +1235875,22 @@
if (ret)
return ret;
+diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
+index 920e578..23b7bc0 100644
+--- a/sound/core/memalloc.c
++++ b/sound/core/memalloc.c
+@@ -629,9 +629,8 @@ static const struct file_operations snd_mem_proc_fops = {
+ static int __init snd_mem_init(void)
+ {
+ #ifdef CONFIG_PROC_FS
+- snd_mem_proc = create_proc_entry(SND_MEM_PROC_FILE, 0644, NULL);
+- if (snd_mem_proc)
+- snd_mem_proc->proc_fops = &snd_mem_proc_fops;
++ snd_mem_proc = proc_create(SND_MEM_PROC_FILE, 0644, NULL,
++ &snd_mem_proc_fops);
+ #endif
+ return 0;
+ }
diff --git a/sound/core/misc.c b/sound/core/misc.c
index 102d1c3..38524f6 100644
--- a/sound/core/misc.c
@@ -931261,10 +1236324,10 @@
+
+EXPORT_SYMBOL(snd_ctl_make_virtual_master);
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
-index 75d4fe0..fe85af1 100644
+index 75d4fe0..a78a8d0 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
-@@ -4,6 +4,24 @@ menu "Generic devices"
+@@ -4,6 +4,26 @@ menu "Generic devices"
depends on SND!=n
@@ -931272,6 +1236335,8 @@
+ tristate "Internal PC speaker support"
+ depends on X86_PC && HIGH_RES_TIMERS
+ depends on INPUT
++ depends on SND
++ select SND_PCM
+ 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
@@ -931405,7 +1236470,7 @@
};
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
-index 5993864..18cca24 100644
+index 5993864..2af0999 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);
@@ -931425,6 +1236490,15 @@
/* Build in lowlevel io */
static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data,
+@@ -245,7 +243,7 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
+ #endif
+ }
+ mpu->write(mpu, cmd, MPU401C(mpu));
+- if (ack) {
++ if (ack && !(mpu->info_flags & MPU401_INFO_NO_ACK)) {
+ ok = 0;
+ timeout = 10000;
+ while (!ok && timeout-- > 0) {
@@ -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)
{
@@ -937668,7 +1242742,7 @@
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
+index 33282f9..d9783a4 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -30,6 +30,7 @@
@@ -937679,7 +1242753,15 @@
#define ALC880_FRONT_EVENT 0x01
#define ALC880_DCVOL_EVENT 0x02
-@@ -97,16 +98,19 @@ enum {
+@@ -59,6 +60,7 @@ enum {
+ ALC880_TCL_S700,
+ ALC880_LG,
+ ALC880_LG_LW,
++ ALC880_MEDION_RIM,
+ #ifdef CONFIG_SND_DEBUG
+ ALC880_TEST,
+ #endif
+@@ -97,16 +99,19 @@ enum {
ALC262_SONY_ASSAMD,
ALC262_BENQ_T31,
ALC262_ULTRA,
@@ -937699,7 +1242781,7 @@
#ifdef CONFIG_SND_DEBUG
ALC268_TEST,
#endif
-@@ -195,10 +199,11 @@ enum {
+@@ -195,10 +200,11 @@ enum {
ALC883_LENOVO_NB0763,
ALC888_LENOVO_MS7195_DIG,
ALC883_HAIER_W66,
@@ -937712,7 +1242794,7 @@
ALC883_AUTO,
ALC883_MODEL_LAST,
};
-@@ -237,6 +242,7 @@ struct alc_spec {
+@@ -237,6 +243,7 @@ struct alc_spec {
/* capture */
unsigned int num_adc_nids;
hda_nid_t *adc_nids;
@@ -937720,7 +1242802,7 @@
hda_nid_t dig_in_nid; /* digital-in NID; optional */
/* capture source */
-@@ -270,7 +276,6 @@ struct alc_spec {
+@@ -270,7 +277,6 @@ struct alc_spec {
/* for virtual master */
hda_nid_t vmaster_nid;
@@ -937728,7 +1242810,7 @@
#ifdef CONFIG_SND_HDA_POWER_SAVE
struct hda_loopback_check loopback;
#endif
-@@ -290,6 +295,7 @@ struct alc_config_preset {
+@@ -290,6 +296,7 @@ struct alc_config_preset {
hda_nid_t hp_nid; /* optional */
unsigned int num_adc_nids;
hda_nid_t *adc_nids;
@@ -937736,7 +1242818,7 @@
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,
+@@ -336,9 +343,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;
@@ -937749,7 +1242831,7 @@
}
-@@ -707,6 +714,7 @@ static void setup_preset(struct alc_spec *spec,
+@@ -707,6 +715,7 @@ static void setup_preset(struct alc_spec *spec,
spec->num_adc_nids = preset->num_adc_nids;
spec->adc_nids = preset->adc_nids;
@@ -937757,7 +1242839,7 @@
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[] = {
+@@ -741,7 +750,6 @@ static struct hda_verb alc_gpio3_init_verbs[] = {
static void alc_sku_automute(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
@@ -937765,7 +1242847,7 @@
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)
+@@ -751,16 +759,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;
@@ -937784,7 +1242866,7 @@
}
/* unsolicited event for HP jack sensing */
-@@ -1319,11 +1318,19 @@ static struct snd_kcontrol_new alc880_f1734_mixer[] = {
+@@ -1319,11 +1319,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),
@@ -937806,7 +1242888,7 @@
/*
* ALC880 ASUS model
-@@ -1516,6 +1523,11 @@ static int alc_build_controls(struct hda_codec *codec)
+@@ -1516,6 +1524,11 @@ static int alc_build_controls(struct hda_codec *codec)
spec->multiout.dig_out_nid);
if (err < 0)
return err;
@@ -937818,7 +1242900,7 @@
}
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)
+@@ -1525,10 +1538,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")) {
@@ -937832,7 +1242914,7 @@
if (err < 0)
return err;
}
-@@ -1882,7 +1895,7 @@ static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec)
+@@ -1882,7 +1896,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;
@@ -937841,7 +1242923,7 @@
}
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,
+@@ -1915,6 +1929,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[] = {
@@ -937849,7 +1242931,7 @@
{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[] = {
+@@ -1927,7 +1942,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},
@@ -937858,7 +1242940,7 @@
{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[] = {
+@@ -1935,6 +1950,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},
@@ -937868,7 +1242950,83 @@
{ }
};
-@@ -2318,7 +2335,8 @@ static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
+@@ -2258,6 +2276,75 @@ static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res)
+ alc880_lg_lw_automute(codec);
+ }
+
++static struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
++ 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, 0x0, HDA_INPUT),
++ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
++ HDA_CODEC_MUTE("Internal Playback Switch", 0x0b, 0x1, HDA_INPUT),
++ { } /* end */
++};
++
++static struct hda_input_mux alc880_medion_rim_capture_source = {
++ .num_items = 2,
++ .items = {
++ { "Mic", 0x0 },
++ { "Internal Mic", 0x1 },
++ },
++};
++
++static struct hda_verb alc880_medion_rim_init_verbs[] = {
++ {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
++
++ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++
++ /* Mic1 (rear panel) pin widget for input and vref at 80% */
++ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
++ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++ /* Mic2 (as headphone out) for HP output */
++ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++ /* Internal Speaker */
++ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
++ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++
++ {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
++ {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
++
++ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
++ { }
++};
++
++/* toggle speaker-output according to the hp-jack state */
++static void alc880_medion_rim_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, 0x1b, HDA_OUTPUT, 0,
++ HDA_AMP_MUTE, bits);
++ if (present)
++ snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
++ else
++ snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 2);
++}
++
++static void alc880_medion_rim_unsol_event(struct hda_codec *codec,
++ unsigned int res)
++{
++ /* Looks like the unsol event is incompatible with the standard
++ * definition. 4bit tag is placed at 28 bit!
++ */
++ if ((res >> 28) == ALC880_HP_EVENT)
++ alc880_medion_rim_automute(codec);
++}
++
+ #ifdef CONFIG_SND_HDA_POWER_SAVE
+ static struct hda_amp_list alc880_loopbacks[] = {
+ { 0x0b, HDA_INPUT, 0 },
+@@ -2318,7 +2405,8 @@ static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
struct snd_pcm_substream *substream)
{
struct alc_spec *spec = codec->spec;
@@ -937878,7 +1243036,7 @@
}
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,
+@@ -2392,8 +2480,8 @@ static int alc880_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
{
struct alc_spec *spec = codec->spec;
@@ -937889,7 +1243047,7 @@
return 0;
}
-@@ -2498,6 +2516,7 @@ static int alc_build_pcms(struct hda_codec *codec)
+@@ -2498,6 +2586,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;
@@ -937897,7 +1243055,7 @@
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)
+@@ -2560,6 +2649,7 @@ static void alc_free(struct hda_codec *codec)
kfree(spec->kctl_alloc);
}
kfree(spec);
@@ -937905,7 +1243063,23 @@
}
/*
-@@ -3057,7 +3077,9 @@ static struct alc_config_preset alc880_presets[] = {
+@@ -2862,6 +2952,7 @@ static const char *alc880_models[ALC880_MODEL_LAST] = {
+ [ALC880_F1734] = "F1734",
+ [ALC880_LG] = "lg",
+ [ALC880_LG_LW] = "lg-lw",
++ [ALC880_MEDION_RIM] = "medion",
+ #ifdef CONFIG_SND_DEBUG
+ [ALC880_TEST] = "test",
+ #endif
+@@ -2913,6 +3004,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = {
+ SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
+ SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
+ SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
++ SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_MEDION_RIM),
+ SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
+ SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
+ SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
+@@ -3057,7 +3149,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,
@@ -937916,7 +1243090,28 @@
},
[ALC880_ASUS] = {
.mixers = { alc880_asus_mixer },
-@@ -3467,15 +3489,21 @@ static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,
+@@ -3205,6 +3299,20 @@ static struct alc_config_preset alc880_presets[] = {
+ .unsol_event = alc880_lg_lw_unsol_event,
+ .init_hook = alc880_lg_lw_automute,
+ },
++ [ALC880_MEDION_RIM] = {
++ .mixers = { alc880_medion_rim_mixer },
++ .init_verbs = { alc880_volume_init_verbs,
++ alc880_medion_rim_init_verbs,
++ alc_gpio2_init_verbs },
++ .num_dacs = ARRAY_SIZE(alc880_dac_nids),
++ .dac_nids = alc880_dac_nids,
++ .dig_out_nid = ALC880_DIGOUT_NID,
++ .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
++ .channel_mode = alc880_2_jack_modes,
++ .input_mux = &alc880_medion_rim_capture_source,
++ .unsol_event = alc880_medion_rim_unsol_event,
++ .init_hook = alc880_medion_rim_automute,
++ },
+ #ifdef CONFIG_SND_DEBUG
+ [ALC880_TEST] = {
+ .mixers = { alc880_test_mixer },
+@@ -3467,15 +3575,21 @@ static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,
return 0;
}
@@ -937942,7 +1243137,7 @@
/* 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)
+@@ -3597,9 +3711,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)
{
@@ -937955,7 +1243150,7 @@
}
/*
-@@ -4795,11 +4826,7 @@ static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
+@@ -4795,11 +4912,7 @@ static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
hda_nid_t nid, int pin_type,
int sel_idx)
{
@@ -937968,7 +1243163,7 @@
/* 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)
+@@ -4929,7 +5042,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 */
@@ -937977,7 +1243172,7 @@
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)
+@@ -4946,8 +5059,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)
{
@@ -937989,7 +1243184,7 @@
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
-@@ -5204,6 +5234,9 @@ static hda_nid_t alc882_dac_nids[4] = {
+@@ -5204,6 +5320,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
@@ -937999,7 +1243194,7 @@
/* 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,
+@@ -5226,15 +5345,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);
@@ -938017,7 +1243212,7 @@
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[] = {
+@@ -6111,6 +6226,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,
@@ -938025,7 +1243220,7 @@
.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[] = {
+@@ -6127,6 +6243,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,
@@ -938033,7 +1243228,7 @@
.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,
+@@ -6182,15 +6299,11 @@ static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
struct alc_spec *spec = codec->spec;
int idx;
@@ -938050,7 +1243245,7 @@
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)
+@@ -6219,6 +6332,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);
@@ -938060,7 +1243255,7 @@
}
#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)
+@@ -6231,16 +6347,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];
@@ -938091,7 +1243286,7 @@
}
}
-@@ -6294,11 +6329,16 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
+@@ -6294,11 +6415,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)
{
@@ -938108,7 +1243303,7 @@
static int patch_alc882(struct hda_codec *codec)
{
struct alc_spec *spec;
-@@ -6328,6 +6368,11 @@ static int patch_alc882(struct hda_codec *codec)
+@@ -6328,6 +6454,11 @@ static int patch_alc882(struct hda_codec *codec)
board_config = ALC885_MBP3;
break;
default:
@@ -938120,7 +1243315,7 @@
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)
+@@ -6372,12 +6503,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);
@@ -938135,7 +1243330,7 @@
spec->mixers[spec->num_mixers] = alc882_capture_mixer;
spec->num_mixers++;
}
-@@ -6412,7 +6459,7 @@ static int patch_alc882(struct hda_codec *codec)
+@@ -6412,7 +6545,7 @@ static int patch_alc882(struct hda_codec *codec)
static hda_nid_t alc883_dac_nids[4] = {
/* front, rear, clfe, rear_surr */
@@ -938144,7 +1243339,7 @@
};
static hda_nid_t alc883_adc_nids[2] = {
-@@ -6420,6 +6467,8 @@ static hda_nid_t alc883_adc_nids[2] = {
+@@ -6420,6 +6553,8 @@ static hda_nid_t alc883_adc_nids[2] = {
0x08, 0x09,
};
@@ -938153,7 +1243348,7 @@
/* 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 = {
+@@ -6451,35 +6586,18 @@ static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
},
};
@@ -938199,7 +1243394,7 @@
/*
* 2ch mode
-@@ -6638,6 +6670,60 @@ static struct snd_kcontrol_new alc883_mitac_mixer[] = {
+@@ -6638,6 +6756,60 @@ static struct snd_kcontrol_new alc883_mitac_mixer[] = {
{ } /* end */
};
@@ -938260,7 +1243455,7 @@
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[] = {
+@@ -6787,6 +6959,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),
@@ -938270,7 +1243465,7 @@
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[] = {
+@@ -6878,124 +7053,6 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {
{ } /* end */
};
@@ -938395,7 +1243590,7 @@
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[] = {
+@@ -7171,6 +7228,35 @@ static struct hda_verb alc883_mitac_verbs[] = {
{ } /* end */
};
@@ -938431,7 +1243626,7 @@
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[] = {
+@@ -7227,26 +7313,14 @@ static struct hda_verb alc883_haier_w66_verbs[] = {
{ } /* end */
};
@@ -938460,7 +1243655,7 @@
{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)
+@@ -7354,6 +7428,68 @@ static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
alc883_tagra_automute(codec);
}
@@ -938529,7 +1243724,7 @@
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] = {
+@@ -7587,10 +7723,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",
@@ -938542,7 +1243737,7 @@
[ALC883_AUTO] = "auto",
};
-@@ -7604,7 +7655,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
+@@ -7604,7 +7741,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),
@@ -938551,7 +1243746,7 @@
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[] = {
+@@ -7614,7 +7751,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),
@@ -938561,7 +1243756,7 @@
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[] = {
+@@ -7627,13 +7766,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),
@@ -938579,7 +1243774,7 @@
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[] = {
+@@ -7652,8 +7795,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,
@@ -938588,7 +1243783,7 @@
.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[] = {
+@@ -7665,8 +7806,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,
@@ -938597,7 +1243792,7 @@
.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[] = {
+@@ -7678,8 +7817,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,
@@ -938606,7 +1243801,7 @@
.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[] = {
+@@ -7691,8 +7828,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,
@@ -938615,7 +1243810,7 @@
.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[] = {
+@@ -7704,8 +7839,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,
@@ -938624,7 +1243819,7 @@
.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[] = {
+@@ -7719,8 +7852,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,
@@ -938633,7 +1243828,7 @@
.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[] = {
+@@ -7737,8 +7868,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,
@@ -938642,7 +1243837,7 @@
.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[] = {
+@@ -7749,8 +7878,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,
@@ -938651,7 +1243846,7 @@
.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[] = {
+@@ -7764,8 +7891,6 @@ static struct alc_config_preset alc883_presets[] = {
alc883_medion_eapd_verbs },
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
@@ -938660,7 +1243855,7 @@
.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[] = {
+@@ -7776,8 +7901,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,
@@ -938669,7 +1243864,7 @@
.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[] = {
+@@ -7789,19 +7912,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,
@@ -938701,7 +1243896,7 @@
.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[] = {
+@@ -7813,8 +7944,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,
@@ -938710,7 +1243905,7 @@
.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[] = {
+@@ -7828,8 +7957,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,
@@ -938719,7 +1243914,7 @@
.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[] = {
+@@ -7843,47 +7970,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,
@@ -938769,7 +1243964,7 @@
.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[] = {
+@@ -7896,14 +8004,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,
@@ -938797,7 +1243992,7 @@
};
-@@ -7918,15 +7951,11 @@ static void alc883_auto_set_output_and_unmute(struct hda_codec *codec,
+@@ -7918,15 +8037,11 @@ static void alc883_auto_set_output_and_unmute(struct hda_codec *codec,
struct alc_spec *spec = codec->spec;
int idx;
@@ -938814,7 +1244009,7 @@
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)
+@@ -7955,6 +8070,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);
@@ -938824,7 +1244019,7 @@
}
#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)
+@@ -8006,9 +8124,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)
{
@@ -938837,7 +1244032,7 @@
}
static int patch_alc883(struct hda_codec *codec)
-@@ -8057,10 +8092,9 @@ static int patch_alc883(struct hda_codec *codec)
+@@ -8057,10 +8178,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;
@@ -938851,7 +1244046,7 @@
spec->vmaster_nid = 0x0c;
-@@ -8085,6 +8119,8 @@ static int patch_alc883(struct hda_codec *codec)
+@@ -8085,6 +8205,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
@@ -938860,7 +1244055,7 @@
#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,
+@@ -8585,7 +8707,8 @@ static void alc262_hippo1_unsol_event(struct hda_codec *codec,
/*
* fujitsu model
@@ -938870,7 +1244065,7 @@
*/
#define ALC_HP_EVENT 0x37
-@@ -8593,6 +8630,14 @@ static void alc262_hippo1_unsol_event(struct hda_codec *codec,
+@@ -8593,6 +8716,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},
@@ -938885,7 +1244080,7 @@
{}
};
-@@ -8633,12 +8678,16 @@ static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
+@@ -8633,12 +8764,16 @@ static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
unsigned int mute;
if (force || !spec->sense_updated) {
@@ -938906,7 +1244101,7 @@
spec->sense_updated = 1;
}
if (spec->jack_present) {
-@@ -8672,6 +8721,46 @@ static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
+@@ -8672,6 +8807,46 @@ static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
},
};
@@ -938953,7 +1244148,7 @@
/* 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,
+@@ -8680,12 +8855,13 @@ static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
long *valp = ucontrol->value.integer.value;
int change;
@@ -938973,7 +1244168,7 @@
if (change)
alc262_fujitsu_automute(codec, 0);
return change;
-@@ -8703,6 +8793,46 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
+@@ -8703,6 +8879,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),
@@ -939020,7 +1244215,7 @@
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[] = {
+@@ -8730,59 +8946,72 @@ static struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
/* Samsung Q1 Ultra Vista model setup */
static struct snd_kcontrol_new alc262_ultra_mixer[] = {
@@ -939128,7 +1244323,7 @@
}
/* unsolicited event for HP jack sensing */
-@@ -8794,6 +8937,45 @@ static void alc262_ultra_unsol_event(struct hda_codec *codec,
+@@ -8794,6 +9023,45 @@ static void alc262_ultra_unsol_event(struct hda_codec *codec,
alc262_ultra_automute(codec);
}
@@ -939174,7 +1244369,7 @@
/* 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)
+@@ -9185,9 +9453,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)
{
@@ -939187,7 +1244382,7 @@
}
/*
-@@ -9206,6 +9391,7 @@ static const char *alc262_models[ALC262_MODEL_LAST] = {
+@@ -9206,6 +9477,7 @@ static const char *alc262_models[ALC262_MODEL_LAST] = {
[ALC262_BENQ_T31] = "benq-t31",
[ALC262_SONY_ASSAMD] = "sony-assamd",
[ALC262_ULTRA] = "ultra",
@@ -939195,7 +1244390,7 @@
[ALC262_AUTO] = "auto",
};
-@@ -9241,6 +9427,8 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
+@@ -9241,6 +9513,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),
@@ -939204,7 +1244399,7 @@
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[] = {
+@@ -9390,18 +9664,32 @@ static struct alc_config_preset alc262_presets[] = {
.init_hook = alc262_hippo_automute,
},
[ALC262_ULTRA] = {
@@ -939241,7 +1244436,7 @@
};
static int patch_alc262(struct hda_codec *codec)
-@@ -9472,12 +9674,14 @@ static int patch_alc262(struct hda_codec *codec)
+@@ -9472,12 +9760,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);
@@ -939256,7 +1244451,7 @@
spec->mixers[spec->num_mixers] = alc262_capture_mixer;
spec->num_mixers++;
}
-@@ -9517,6 +9721,8 @@ static hda_nid_t alc268_adc_nids_alt[1] = {
+@@ -9517,6 +9807,8 @@ static hda_nid_t alc268_adc_nids_alt[1] = {
0x08
};
@@ -939265,7 +1244460,7 @@
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[] = {
+@@ -9529,6 +9821,22 @@ static struct snd_kcontrol_new alc268_base_mixer[] = {
{ }
};
@@ -939288,7 +1244483,7 @@
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[] = {
+@@ -9613,8 +9921,12 @@ static struct snd_kcontrol_new alc268_acer_mixer[] = {
};
static struct hda_verb alc268_acer_verbs[] = {
@@ -939301,7 +1244496,7 @@
{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,
+@@ -9685,6 +9997,64 @@ static void alc268_dell_unsol_event(struct hda_codec *codec,
#define alc268_dell_init_hook alc268_dell_automute
@@ -939366,7 +1244561,7 @@
/*
* generic initialization of ADC, input mixers and output mixers
*/
-@@ -9725,7 +10009,11 @@ static struct hda_verb alc268_base_init_verbs[] = {
+@@ -9725,7 +10095,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},
@@ -939379,7 +1244574,7 @@
/* Unmute Selector 23h,24h and set the default input to mic-in */
-@@ -9764,29 +10052,17 @@ static struct hda_verb alc268_volume_init_verbs[] = {
+@@ -9764,29 +10138,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},
@@ -939414,7 +1244609,7 @@
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 = {
+@@ -9836,13 +10198,17 @@ static struct hda_input_mux alc268_capture_source = {
},
};
@@ -939437,7 +1244632,7 @@
/* 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,
+@@ -9981,6 +10347,10 @@ static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec,
case 0x1c:
idx1 = 3; /* CD */
break;
@@ -939448,7 +1244643,7 @@
default:
continue;
}
-@@ -10073,6 +10357,9 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
+@@ -10073,6 +10443,9 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
if (spec->kctl_alloc)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
@@ -939458,7 +1244653,7 @@
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)
+@@ -10091,20 +10464,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)
{
@@ -939484,7 +1244679,7 @@
#ifdef CONFIG_SND_DEBUG
[ALC268_TEST] = "test",
#endif
-@@ -10112,6 +10404,7 @@ static const char *alc268_models[ALC268_MODEL_LAST] = {
+@@ -10112,6 +10490,7 @@ static const char *alc268_models[ALC268_MODEL_LAST] = {
};
static struct snd_pci_quirk alc268_cfg_tbl[] = {
@@ -939492,7 +1244687,7 @@
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[] = {
+@@ -10122,17 +10501,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),
@@ -939530,7 +1244725,7 @@
.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[] = {
+@@ -10140,13 +10538,15 @@ static struct alc_config_preset alc268_presets[] = {
.input_mux = &alc268_capture_source,
},
[ALC268_TOSHIBA] = {
@@ -939547,7 +1244742,7 @@
.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[] = {
+@@ -10155,22 +10555,24 @@ static struct alc_config_preset alc268_presets[] = {
.init_hook = alc268_toshiba_automute,
},
[ALC268_ACER] = {
@@ -939575,7 +1244770,7 @@
.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[] = {
+@@ -10182,6 +10584,24 @@ static struct alc_config_preset alc268_presets[] = {
.init_hook = alc268_dell_init_hook,
.input_mux = &alc268_capture_source,
},
@@ -939600,7 +1244795,7 @@
#ifdef CONFIG_SND_DEBUG
[ALC268_TEST] = {
.mixers = { alc268_test_mixer, alc268_capture_mixer },
-@@ -10191,6 +10525,7 @@ static struct alc_config_preset alc268_presets[] = {
+@@ -10191,6 +10611,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,
@@ -939608,7 +1244803,7 @@
.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)
+@@ -10247,13 +10668,22 @@ static int patch_alc268(struct hda_codec *codec)
spec->stream_name_digital = "ALC268 Digital";
spec->stream_digital_playback = &alc268_pcm_digital_playback;
@@ -939632,7 +1244827,7 @@
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)
+@@ -10266,6 +10696,12 @@ static int patch_alc268(struct hda_codec *codec)
alc268_capture_mixer;
spec->num_mixers++;
}
@@ -939645,7 +1244840,7 @@
}
spec->vmaster_nid = 0x02;
-@@ -10539,9 +10889,12 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
+@@ -10539,9 +10975,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)
{
@@ -939658,7 +1244853,7 @@
}
/*
-@@ -11463,13 +11816,7 @@ static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
+@@ -11463,13 +11902,7 @@ static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
hda_nid_t nid,
int pin_type, int dac_idx)
{
@@ -939673,7 +1244868,7 @@
}
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)
+@@ -11496,6 +11929,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]);
@@ -939683,7 +1244878,7 @@
}
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)
+@@ -11568,9 +12004,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)
{
@@ -939696,7 +1244891,7 @@
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
-@@ -11822,6 +12175,8 @@ static hda_nid_t alc861vd_adc_nids[1] = {
+@@ -11822,6 +12261,8 @@ static hda_nid_t alc861vd_adc_nids[1] = {
0x09,
};
@@ -939705,7 +1244900,7 @@
/* 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 = {
+@@ -11835,11 +12276,10 @@ static struct hda_input_mux alc861vd_capture_source = {
};
static struct hda_input_mux alc861vd_dallas_capture_source = {
@@ -939720,7 +1244915,7 @@
},
};
-@@ -11853,33 +12207,8 @@ static struct hda_input_mux alc861vd_hp_capture_source = {
+@@ -11853,33 +12293,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
@@ -939756,7 +1244951,7 @@
/*
* 2ch mode
-@@ -12034,20 +12363,22 @@ static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
+@@ -12034,20 +12449,22 @@ static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
{ } /* end */
};
@@ -939789,7 +1244984,7 @@
{ } /* end */
};
-@@ -12348,6 +12679,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
+@@ -12348,6 +12765,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),
@@ -939797,7 +1244992,7 @@
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[] = {
+@@ -12362,8 +12780,6 @@ static struct alc_config_preset alc861vd_presets[] = {
alc861vd_3stack_init_verbs },
.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
.dac_nids = alc660vd_dac_nids,
@@ -939806,7 +1245001,7 @@
.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[] = {
+@@ -12375,8 +12791,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,
@@ -939815,7 +1245010,7 @@
.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[] = {
+@@ -12421,8 +12835,6 @@ static struct alc_config_preset alc861vd_presets[] = {
alc861vd_lenovo_unsol_verbs },
.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
.dac_nids = alc660vd_dac_nids,
@@ -939824,7 +1245019,7 @@
.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[] = {
+@@ -12434,8 +12846,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,
@@ -939833,7 +1245028,7 @@
.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[] = {
+@@ -12447,9 +12857,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,
@@ -939843,7 +1245038,7 @@
.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[] = {
+@@ -12464,11 +12872,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)
{
@@ -939856,7 +1245051,7 @@
}
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)
+@@ -12495,6 +12899,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);
@@ -939866,7 +1245061,7 @@
}
#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)
+@@ -12698,9 +13105,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)
{
@@ -939879,7 +1245074,7 @@
}
static int patch_alc861vd(struct hda_codec *codec)
-@@ -12751,6 +13075,7 @@ static int patch_alc861vd(struct hda_codec *codec)
+@@ -12751,6 +13161,7 @@ static int patch_alc861vd(struct hda_codec *codec)
spec->adc_nids = alc861vd_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
@@ -939887,7 +1245082,7 @@
spec->mixers[spec->num_mixers] = alc861vd_capture_mixer;
spec->num_mixers++;
-@@ -12792,9 +13117,11 @@ static hda_nid_t alc662_adc_nids[1] = {
+@@ -12792,9 +13203,11 @@ static hda_nid_t alc662_adc_nids[1] = {
/* ADC1-2 */
0x09,
};
@@ -939900,7 +1245095,7 @@
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 = {
+@@ -12823,33 +13236,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
@@ -939935,7 +1245130,7 @@
/*
* 2ch mode
*/
-@@ -12918,13 +13220,13 @@ static struct hda_channel_mode alc662_5stack_modes[2] = {
+@@ -12918,13 +13306,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),
@@ -939953,7 +1245148,7 @@
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[] = {
+@@ -12941,7 +13329,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),
@@ -939962,7 +1245157,7 @@
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[] = {
+@@ -12958,13 +13346,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),
@@ -939980,7 +1245175,7 @@
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] = {
+@@ -13313,6 +13701,7 @@ static const char *alc662_models[ALC662_MODEL_LAST] = {
};
static struct snd_pci_quirk alc662_cfg_tbl[] = {
@@ -939988,7 +1245183,7 @@
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[] = {
+@@ -13326,8 +13715,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,
@@ -939997,7 +1245192,7 @@
.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[] = {
+@@ -13340,8 +13727,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,
@@ -940006,7 +1245201,7 @@
.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[] = {
+@@ -13354,8 +13739,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,
@@ -940015,7 +1245210,7 @@
.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[] = {
+@@ -13368,8 +13751,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,
@@ -940024,7 +1245219,7 @@
.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[] = {
+@@ -13380,8 +13761,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,
@@ -940033,7 +1245228,7 @@
.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[] = {
+@@ -13394,8 +13773,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,
@@ -940042,7 +1245237,7 @@
.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[] = {
+@@ -13409,8 +13786,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,
@@ -940051,7 +1245246,7 @@
.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,
+@@ -13556,11 +13931,7 @@ static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
hda_nid_t nid, int pin_type,
int dac_idx)
{
@@ -940064,7 +1245259,7 @@
/* 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)
+@@ -13595,6 +13966,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);
@@ -940074,7 +1245269,7 @@
}
#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)
+@@ -13672,9 +14046,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)
{
@@ -940087,7 +1245282,7 @@
}
static int patch_alc662(struct hda_codec *codec)
-@@ -13722,10 +14013,9 @@ static int patch_alc662(struct hda_codec *codec)
+@@ -13722,10 +14099,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;
@@ -940101,7 +1245296,7 @@
spec->vmaster_nid = 0x02;
-@@ -13761,6 +14051,8 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
+@@ -13761,6 +14137,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 },
@@ -941818,7 +1247013,7 @@
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
+index f533850..6735090 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -106,15 +106,19 @@ static unsigned int PRO_RATE_DEFAULT = 44100;
@@ -941908,7 +1247103,10 @@
- */
- if ((status & VT1724_IRQ_MPU_RX)||(status & VT1724_IRQ_MPU_TX)) {
+ if (status & VT1724_IRQ_MPU_TX) {
-+ if (ice->rmidi[0])
+ 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_tx(irq,
+ ice->rmidi[0]->private_data);
+ else /* disable TX to be sure */
@@ -941921,19 +1247119,16 @@
+ * 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);
++ if (ice->rmidi[0])
+ 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) {
@@ -941950,14 +1247145,14 @@
+};
+
+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) {
@@ -942451,7 +1247646,7 @@
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,
+@@ -2377,14 +2425,28 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
if (! c->no_mpu401) {
if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) {
@@ -942460,6 +1247655,7 @@
ICEREG1724(ice, MPU_CTRL),
- MPU401_INFO_INTEGRATED,
+ (MPU401_INFO_INTEGRATED |
++ MPU401_INFO_NO_ACK |
+ MPU401_INFO_TX_IRQ),
ice->irq, 0,
&ice->rmidi[0])) < 0) {
@@ -942473,12 +1247669,10 @@
+ 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
}
}
@@ -947371,20 +1252565,34 @@
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_NONINTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
+diff --git a/sound/sh/aica.c b/sound/sh/aica.c
+index d49417b..9ca1133 100644
+--- a/sound/sh/aica.c
++++ b/sound/sh/aica.c
+@@ -663,7 +663,7 @@ static int __init aica_init(void)
+ return err;
+ pd = platform_device_register_simple(SND_AICA_DRIVER, -1,
+ aica_memory_space, 2);
+- if (unlikely(IS_ERR(pd))) {
++ if (IS_ERR(pd)) {
+ platform_driver_unregister(&snd_aica_driver);
+ return PTR_ERR(pd);
+ }
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
-index 2765852..a3b51df 100644
+index 2765852..18f28ac 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
-@@ -29,6 +29,7 @@ source "sound/soc/pxa/Kconfig"
+@@ -29,6 +29,8 @@ 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"
++source "sound/soc/omap/Kconfig"
# Supported codecs
source "sound/soc/codecs/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
-index 4869c9a..e489dbd 100644
+index 4869c9a..782db21 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,4 +1,4 @@
@@ -947392,7 +1252600,7 @@
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/
++obj-$(CONFIG_SND_SOC) += codecs/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/ omap/
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
@@ -947823,9 +1253031,18 @@
MODULE_DESCRIPTION("ASoC WM8750 driver");
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
-index ddd9c71..76a5c7b 100644
+index ddd9c71..fb41826 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
+@@ -150,7 +150,7 @@ static int wm8753_write(struct snd_soc_codec *codec, unsigned int reg,
+ data[0] = (reg << 1) | ((value >> 8) & 0x0001);
+ data[1] = value & 0x00ff;
+
+- wm8753_write_reg_cache (codec, reg, value);
++ wm8753_write_reg_cache(codec, reg, value);
+ if (codec->hw_write(codec->control_data, data, 2) == 2)
+ return 0;
+ else
@@ -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",
@@ -947842,6 +1253059,15 @@
};
+@@ -247,7 +249,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
+
+- if (((mode &0xc) >> 2) == ucontrol->value.integer.value[0])
++ if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0])
+ return 0;
+
+ mode &= 0xfff3;
@@ -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),
@@ -947859,12 +1253085,223 @@
};
/* add non dapm controls */
+@@ -339,7 +342,8 @@ static int wm8753_add_controls(struct snd_soc_codec *codec)
+
+ for (i = 0; i < ARRAY_SIZE(wm8753_snd_controls); i++) {
+ err = snd_ctl_add(codec->card,
+- snd_soc_cnew(&wm8753_snd_controls[i],codec, NULL));
++ snd_soc_cnew(&wm8753_snd_controls[i],
++ codec, NULL));
+ if (err < 0)
+ return err;
+ }
+@@ -719,7 +723,7 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
+
+ if ((Ndiv < 6) || (Ndiv > 12))
+ printk(KERN_WARNING
+- "WM8753 N value outwith recommended range! N = %d\n",Ndiv);
++ "wm8753: unsupported N = %d\n", Ndiv);
+
+ pll_div->n = Ndiv;
+ Nmod = target % source;
+@@ -1297,8 +1301,9 @@ static int wm8753_dapm_event(struct snd_soc_codec *codec, int event)
+ }
+
+ #define WM8753_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 WM8753_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE)
+@@ -1504,9 +1509,9 @@ static int wm8753_suspend(struct platform_device *pdev, pm_message_t state)
+ struct snd_soc_codec *codec = socdev->codec;
+
+ /* we only need to suspend if we are a valid card */
+- if(!codec->card)
++ if (!codec->card)
+ return 0;
+-
++
+ wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
+ return 0;
+ }
+@@ -1520,7 +1525,7 @@ static int wm8753_resume(struct platform_device *pdev)
+ u16 *cache = codec->reg_cache;
+
+ /* we only need to resume if we are a valid card */
+- if(!codec->card)
++ if (!codec->card)
+ return 0;
+
+ /* Sync reg_cache with the hardware */
+@@ -1610,9 +1615,10 @@ static int wm8753_init(struct snd_soc_device *socdev)
+ wm8753_add_widgets(codec);
+ ret = snd_soc_register_card(socdev);
+ if (ret < 0) {
+- printk(KERN_ERR "wm8753: failed to register card\n");
++ printk(KERN_ERR "wm8753: failed to register card\n");
+ goto card_err;
+- }
++ }
++
+ return ret;
+
+ card_err:
+@@ -1627,7 +1633,7 @@ pcm_err:
+ around */
+ static struct snd_soc_device *wm8753_socdev;
+
+-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+ /*
+ * WM8753 2 wire address is determined by GPIO5
+@@ -1658,7 +1664,7 @@ static int wm8753_codec_probe(struct i2c_adapter *adap, int addr, int kind)
+ client_template.addr = addr;
+
+ i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
+- if (i2c == NULL){
++ if (!i2c) {
+ kfree(codec);
+ return -ENOMEM;
+ }
+@@ -1746,7 +1752,7 @@ static int wm8753_probe(struct platform_device *pdev)
+ wm8753_socdev = socdev;
+ INIT_DELAYED_WORK(&codec->delayed_work, wm8753_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;
+@@ -1790,7 +1796,7 @@ static int wm8753_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(&wm8753_i2c_driver);
+ #endif
+ kfree(codec->private_data);
+@@ -1805,7 +1811,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8753 = {
+ .suspend = wm8753_suspend,
+ .resume = wm8753_resume,
+ };
+-
+ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
+
+ MODULE_DESCRIPTION("ASoC WM8753 driver");
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
-index 524f745..d2d79e1 100644
+index 524f745..76c1e2d 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)
+@@ -37,23 +37,23 @@ static int ac97_write(struct snd_soc_codec *codec,
+ * WM9712 register cache
+ */
+ static const u16 wm9712_reg[] = {
+- 0x6174, 0x8000, 0x8000, 0x8000, // 6
+- 0x0f0f, 0xaaa0, 0xc008, 0x6808, // e
+- 0xe808, 0xaaa0, 0xad00, 0x8000, // 16
+- 0xe808, 0x3000, 0x8000, 0x0000, // 1e
+- 0x0000, 0x0000, 0x0000, 0x000f, // 26
+- 0x0405, 0x0410, 0xbb80, 0xbb80, // 2e
+- 0x0000, 0xbb80, 0x0000, 0x0000, // 36
+- 0x0000, 0x2000, 0x0000, 0x0000, // 3e
+- 0x0000, 0x0000, 0x0000, 0x0000, // 46
+- 0x0000, 0x0000, 0xf83e, 0xffff, // 4e
+- 0x0000, 0x0000, 0x0000, 0xf83e, // 56
+- 0x0008, 0x0000, 0x0000, 0x0000, // 5e
+- 0xb032, 0x3e00, 0x0000, 0x0000, // 66
+- 0x0000, 0x0000, 0x0000, 0x0000, // 6e
+- 0x0000, 0x0000, 0x0000, 0x0006, // 76
+- 0x0001, 0x0000, 0x574d, 0x4c12, // 7e
+- 0x0000, 0x0000 // virtual hp mixers
++ 0x6174, 0x8000, 0x8000, 0x8000, /* 6 */
++ 0x0f0f, 0xaaa0, 0xc008, 0x6808, /* e */
++ 0xe808, 0xaaa0, 0xad00, 0x8000, /* 16 */
++ 0xe808, 0x3000, 0x8000, 0x0000, /* 1e */
++ 0x0000, 0x0000, 0x0000, 0x000f, /* 26 */
++ 0x0405, 0x0410, 0xbb80, 0xbb80, /* 2e */
++ 0x0000, 0xbb80, 0x0000, 0x0000, /* 36 */
++ 0x0000, 0x2000, 0x0000, 0x0000, /* 3e */
++ 0x0000, 0x0000, 0x0000, 0x0000, /* 46 */
++ 0x0000, 0x0000, 0xf83e, 0xffff, /* 4e */
++ 0x0000, 0x0000, 0x0000, 0xf83e, /* 56 */
++ 0x0008, 0x0000, 0x0000, 0x0000, /* 5e */
++ 0xb032, 0x3e00, 0x0000, 0x0000, /* 66 */
++ 0x0000, 0x0000, 0x0000, 0x0000, /* 6e */
++ 0x0000, 0x0000, 0x0000, 0x0006, /* 76 */
++ 0x0001, 0x0000, 0x574d, 0x4c12, /* 7e */
++ 0x0000, 0x0000 /* virtual hp mixers */
+ };
+
+ /* virtual HP mixers regs */
+@@ -94,7 +94,7 @@ static const struct snd_kcontrol_new wm9712_snd_ac97_controls[] = {
+ SOC_DOUBLE("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1),
+ SOC_SINGLE("Speaker Playback Switch", AC97_MASTER, 15, 1, 1),
+ SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1),
+-SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE,15, 1, 1),
++SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 1, 1),
+ SOC_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1),
+
+ SOC_SINGLE("Speaker Playback ZC Switch", AC97_MASTER, 7, 1, 0),
+@@ -165,7 +165,8 @@ static int wm9712_add_controls(struct snd_soc_codec *codec)
+
+ for (i = 0; i < ARRAY_SIZE(wm9712_snd_ac97_controls); i++) {
+ err = snd_ctl_add(codec->card,
+- snd_soc_cnew(&wm9712_snd_ac97_controls[i],codec, NULL));
++ snd_soc_cnew(&wm9712_snd_ac97_controls[i],
++ codec, NULL));
+ if (err < 0)
+ return err;
+ }
+@@ -363,7 +364,6 @@ static const char *audio_map[][3] = {
+ {"Left HP Mixer", "PCM Playback Switch", "Left DAC"},
+ {"Left HP Mixer", "Mic Sidetone Switch", "Mic PGA"},
+ {"Left HP Mixer", NULL, "ALC Sidetone Mux"},
+- //{"Right HP Mixer", NULL, "HP Mixer"},
+
+ /* Right HP mixer */
+ {"Right HP Mixer", "PCBeep Bypass Switch", "PCBEEP"},
+@@ -454,15 +454,13 @@ static int wm9712_add_widgets(struct snd_soc_codec *codec)
+ {
+ int i;
+
+- for(i = 0; i < ARRAY_SIZE(wm9712_dapm_widgets); i++) {
++ for (i = 0; i < ARRAY_SIZE(wm9712_dapm_widgets); i++)
+ snd_soc_dapm_new_control(codec, &wm9712_dapm_widgets[i]);
+- }
+
+- /* set up audio path audio_mapnects */
+- for(i = 0; audio_map[i][0] != NULL; i++) {
++ /* set up audio path connects */
++ 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]);
+- }
++ audio_map[i][1], audio_map[i][2]);
+
+ snd_soc_dapm_new_widgets(codec);
+ return 0;
+@@ -540,7 +538,8 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream)
+ }
+
+ #define WM9712_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 wm9712_dai[] = {
+ {
+@@ -577,26 +576,16 @@ EXPORT_SYMBOL_GPL(wm9712_dai);
+ static int wm9712_dapm_event(struct snd_soc_codec *codec, int event)
+ {
+- u16 reg;
+-
switch (event) {
case SNDRV_CTL_POWER_D0: /* full On */
- /* liam - maybe enable thermal shutdown */
@@ -947886,6 +1253323,35 @@
ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
ac97_write(codec, AC97_POWERDOWN, 0xffff);
break;
+@@ -641,7 +630,7 @@ static int wm9712_soc_resume(struct platform_device *pdev)
+ u16 *cache = codec->reg_cache;
+
+ ret = wm9712_reset(codec, 1);
+- if (ret < 0){
++ if (ret < 0) {
+ printk(KERN_ERR "could not reset AC97 codec\n");
+ return ret;
+ }
+@@ -650,9 +639,9 @@ static int wm9712_soc_resume(struct platform_device *pdev)
+
+ if (ret == 0) {
+ /* Sync reg_cache with the hardware after cold reset */
+- for (i = 2; i < ARRAY_SIZE(wm9712_reg) << 1; i+=2) {
++ for (i = 2; i < ARRAY_SIZE(wm9712_reg) << 1; i += 2) {
+ if (i == AC97_INT_PAGING || i == AC97_POWERDOWN ||
+- (i > 0x58 && i != 0x5c))
++ (i > 0x58 && i != 0x5c))
+ continue;
+ soc_ac97_ops.write(codec->ac97, i, cache[i>>1]);
+ }
+@@ -765,7 +754,6 @@ struct snd_soc_codec_device soc_codec_dev_wm9712 = {
+ .suspend = wm9712_soc_suspend,
+ .resume = wm9712_soc_resume,
+ };
+-
+ EXPORT_SYMBOL_GPL(soc_codec_dev_wm9712);
+
+ MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver");
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
new file mode 100644
index 0000000..1f24116
@@ -950397,6 +1255863,1269 @@
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
+diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
+new file mode 100644
+index 0000000..0230d83
+--- /dev/null
++++ b/sound/soc/omap/Kconfig
+@@ -0,0 +1,19 @@
++menu "SoC Audio for the Texas Instruments OMAP"
++
++config SND_OMAP_SOC
++ tristate "SoC Audio for the Texas Instruments OMAP chips"
++ depends on ARCH_OMAP && SND_SOC
++
++config SND_OMAP_SOC_MCBSP
++ tristate
++ select OMAP_MCBSP
++
++config SND_OMAP_SOC_N810
++ tristate "SoC Audio support for Nokia N810"
++ depends on SND_OMAP_SOC && MACH_NOKIA_N810
++ select SND_OMAP_SOC_MCBSP
++ select SND_SOC_TLV320AIC3X
++ help
++ Say Y if you want to add support for SoC audio on Nokia N810.
++
++endmenu
+diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
+new file mode 100644
+index 0000000..d8d8d58
+--- /dev/null
++++ b/sound/soc/omap/Makefile
+@@ -0,0 +1,11 @@
++# OMAP Platform Support
++snd-soc-omap-objs := omap-pcm.o
++snd-soc-omap-mcbsp-objs := omap-mcbsp.o
++
++obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o
++obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
++
++# OMAP Machine Support
++snd-soc-n810-objs := n810.o
++
++obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
+diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
+new file mode 100644
+index 0000000..83b1eb4
+--- /dev/null
++++ b/sound/soc/omap/n810.c
+@@ -0,0 +1,336 @@
++/*
++ * n810.c -- SoC audio for Nokia N810
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ *
++ * Contact: Jarkko Nikula <jarkko.nikula at nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ *
++ */
++
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++
++#include <asm/mach-types.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/gpio.h>
++#include <asm/arch/mcbsp.h>
++
++#include "omap-mcbsp.h"
++#include "omap-pcm.h"
++#include "../codecs/tlv320aic3x.h"
++
++#define RX44_HEADSET_AMP_GPIO 10
++#define RX44_SPEAKER_AMP_GPIO 101
++
++static struct clk *sys_clkout2;
++static struct clk *sys_clkout2_src;
++static struct clk *func96m_clk;
++
++static int n810_spk_func;
++static int n810_jack_func;
++
++static void n810_ext_control(struct snd_soc_codec *codec)
++{
++ snd_soc_dapm_set_endpoint(codec, "Ext Spk", n810_spk_func);
++ snd_soc_dapm_set_endpoint(codec, "Headphone Jack", n810_jack_func);
++
++ snd_soc_dapm_sync_endpoints(codec);
++}
++
++static int n810_startup(struct snd_pcm_substream *substream)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_codec *codec = rtd->socdev->codec;
++
++ n810_ext_control(codec);
++ return clk_enable(sys_clkout2);
++}
++
++static void n810_shutdown(struct snd_pcm_substream *substream)
++{
++ clk_disable(sys_clkout2);
++}
++
++static int n810_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 err;
++
++ /* Set codec DAI configuration */
++ err = codec_dai->dai_ops.set_fmt(codec_dai,
++ SND_SOC_DAIFMT_I2S |
++ SND_SOC_DAIFMT_NB_NF |
++ SND_SOC_DAIFMT_CBM_CFM);
++ if (err < 0)
++ return err;
++
++ /* Set cpu DAI configuration */
++ err = cpu_dai->dai_ops.set_fmt(cpu_dai,
++ SND_SOC_DAIFMT_I2S |
++ SND_SOC_DAIFMT_NB_NF |
++ SND_SOC_DAIFMT_CBM_CFM);
++ if (err < 0)
++ return err;
++
++ /* Set the codec system clock for DAC and ADC */
++ err = codec_dai->dai_ops.set_sysclk(codec_dai, 0, 12000000,
++ SND_SOC_CLOCK_IN);
++
++ return err;
++}
++
++static struct snd_soc_ops n810_ops = {
++ .startup = n810_startup,
++ .hw_params = n810_hw_params,
++ .shutdown = n810_shutdown,
++};
++
++static int n810_get_spk(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ ucontrol->value.integer.value[0] = n810_spk_func;
++
++ return 0;
++}
++
++static int n810_set_spk(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++
++ if (n810_spk_func == ucontrol->value.integer.value[0])
++ return 0;
++
++ n810_spk_func = ucontrol->value.integer.value[0];
++ n810_ext_control(codec);
++
++ return 1;
++}
++
++static int n810_get_jack(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ ucontrol->value.integer.value[0] = n810_jack_func;
++
++ return 0;
++}
++
++static int n810_set_jack(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++
++ if (n810_jack_func == ucontrol->value.integer.value[0])
++ return 0;
++
++ n810_jack_func = ucontrol->value.integer.value[0];
++ n810_ext_control(codec);
++
++ return 1;
++}
++
++static int n810_spk_event(struct snd_soc_dapm_widget *w,
++ struct snd_kcontrol *k, int event)
++{
++ if (SND_SOC_DAPM_EVENT_ON(event))
++ omap_set_gpio_dataout(RX44_SPEAKER_AMP_GPIO, 1);
++ else
++ omap_set_gpio_dataout(RX44_SPEAKER_AMP_GPIO, 0);
++
++ return 0;
++}
++
++static int n810_jack_event(struct snd_soc_dapm_widget *w,
++ struct snd_kcontrol *k, int event)
++{
++ if (SND_SOC_DAPM_EVENT_ON(event))
++ omap_set_gpio_dataout(RX44_HEADSET_AMP_GPIO, 1);
++ else
++ omap_set_gpio_dataout(RX44_HEADSET_AMP_GPIO, 0);
++
++ return 0;
++}
++
++static const struct snd_soc_dapm_widget aic33_dapm_widgets[] = {
++ SND_SOC_DAPM_SPK("Ext Spk", n810_spk_event),
++ SND_SOC_DAPM_HP("Headphone Jack", n810_jack_event),
++};
++
++static const char *audio_map[][3] = {
++ {"Headphone Jack", NULL, "HPLOUT"},
++ {"Headphone Jack", NULL, "HPROUT"},
++
++ {"Ext Spk", NULL, "LLOUT"},
++ {"Ext Spk", NULL, "RLOUT"},
++};
++
++static const char *spk_function[] = {"Off", "On"};
++static const char *jack_function[] = {"Off", "Headphone"};
++static const struct soc_enum n810_enum[] = {
++ SOC_ENUM_SINGLE_EXT(2, spk_function),
++ SOC_ENUM_SINGLE_EXT(3, jack_function),
++};
++
++static const struct snd_kcontrol_new aic33_n810_controls[] = {
++ SOC_ENUM_EXT("Speaker Function", n810_enum[0],
++ n810_get_spk, n810_set_spk),
++ SOC_ENUM_EXT("Jack Function", n810_enum[1],
++ n810_get_jack, n810_set_jack),
++};
++
++static int n810_aic33_init(struct snd_soc_codec *codec)
++{
++ int i, err;
++
++ /* 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);
++
++ /* Add N810 specific controls */
++ for (i = 0; i < ARRAY_SIZE(aic33_n810_controls); i++) {
++ err = snd_ctl_add(codec->card,
++ snd_soc_cnew(&aic33_n810_controls[i], codec, NULL));
++ if (err < 0)
++ return err;
++ }
++
++ /* Add N810 specific widgets */
++ for (i = 0; i < ARRAY_SIZE(aic33_dapm_widgets); i++)
++ snd_soc_dapm_new_control(codec, &aic33_dapm_widgets[i]);
++
++ /* Set up N810 specific audio path audio_map */
++ for (i = 0; i < ARRAY_SIZE(audio_map); 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;
++}
++
++/* Digital audio interface glue - connects codec <--> CPU */
++static struct snd_soc_dai_link n810_dai = {
++ .name = "TLV320AIC33",
++ .stream_name = "AIC33",
++ .cpu_dai = &omap_mcbsp_dai[0],
++ .codec_dai = &aic3x_dai,
++ .init = n810_aic33_init,
++ .ops = &n810_ops,
++};
++
++/* Audio machine driver */
++static struct snd_soc_machine snd_soc_machine_n810 = {
++ .name = "N810",
++ .dai_link = &n810_dai,
++ .num_links = 1,
++};
++
++/* Audio private data */
++static struct aic3x_setup_data n810_aic33_setup = {
++ .i2c_address = 0x18,
++};
++
++/* Audio subsystem */
++static struct snd_soc_device n810_snd_devdata = {
++ .machine = &snd_soc_machine_n810,
++ .platform = &omap_soc_platform,
++ .codec_dev = &soc_codec_dev_aic3x,
++ .codec_data = &n810_aic33_setup,
++};
++
++static struct platform_device *n810_snd_device;
++
++static int __init n810_soc_init(void)
++{
++ int err;
++ struct device *dev;
++
++ if (!machine_is_nokia_n810())
++ return -ENODEV;
++
++ n810_snd_device = platform_device_alloc("soc-audio", -1);
++ if (!n810_snd_device)
++ return -ENOMEM;
++
++ platform_set_drvdata(n810_snd_device, &n810_snd_devdata);
++ n810_snd_devdata.dev = &n810_snd_device->dev;
++ *(unsigned int *)n810_dai.cpu_dai->private_data = 1; /* McBSP2 */
++ err = platform_device_add(n810_snd_device);
++ if (err)
++ goto err1;
++
++ dev = &n810_snd_device->dev;
++
++ sys_clkout2_src = clk_get(dev, "sys_clkout2_src");
++ if (IS_ERR(sys_clkout2_src)) {
++ dev_err(dev, "Could not get sys_clkout2_src clock\n");
++ return -ENODEV;
++ }
++ sys_clkout2 = clk_get(dev, "sys_clkout2");
++ if (IS_ERR(sys_clkout2)) {
++ dev_err(dev, "Could not get sys_clkout2\n");
++ goto err1;
++ }
++ /*
++ * Configure 12 MHz output on SYS_CLKOUT2. Therefore we must use
++ * 96 MHz as its parent in order to get 12 MHz
++ */
++ func96m_clk = clk_get(dev, "func_96m_ck");
++ if (IS_ERR(func96m_clk)) {
++ dev_err(dev, "Could not get func 96M clock\n");
++ goto err2;
++ }
++ clk_set_parent(sys_clkout2_src, func96m_clk);
++ clk_set_rate(sys_clkout2, 12000000);
++
++ if (omap_request_gpio(RX44_HEADSET_AMP_GPIO) < 0)
++ BUG();
++ if (omap_request_gpio(RX44_SPEAKER_AMP_GPIO) < 0)
++ BUG();
++ omap_set_gpio_direction(RX44_HEADSET_AMP_GPIO, 0);
++ omap_set_gpio_direction(RX44_SPEAKER_AMP_GPIO, 0);
++
++ return 0;
++err2:
++ clk_put(sys_clkout2);
++ platform_device_del(n810_snd_device);
++err1:
++ platform_device_put(n810_snd_device);
++
++ return err;
++
++}
++
++static void __exit n810_soc_exit(void)
++{
++ platform_device_unregister(n810_snd_device);
++}
++
++module_init(n810_soc_init);
++module_exit(n810_soc_exit);
++
++MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula at nokia.com>");
++MODULE_DESCRIPTION("ALSA SoC Nokia N810");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
+new file mode 100644
+index 0000000..40d87e6
+--- /dev/null
++++ b/sound/soc/omap/omap-mcbsp.c
+@@ -0,0 +1,414 @@
++/*
++ * omap-mcbsp.c -- OMAP ALSA SoC DAI driver using McBSP port
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ *
++ * Contact: Jarkko Nikula <jarkko.nikula at nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ *
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/initval.h>
++#include <sound/soc.h>
++
++#include <asm/arch/control.h>
++#include <asm/arch/dma.h>
++#include <asm/arch/mcbsp.h>
++#include "omap-mcbsp.h"
++#include "omap-pcm.h"
++
++#define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_44100 | \
++ SNDRV_PCM_RATE_48000 | \
++ SNDRV_PCM_RATE_KNOT)
++
++struct omap_mcbsp_data {
++ unsigned int bus_id;
++ struct omap_mcbsp_reg_cfg regs;
++ /*
++ * Flags indicating is the bus already activated and configured by
++ * another substream
++ */
++ int active;
++ int configured;
++};
++
++#define to_mcbsp(priv) container_of((priv), struct omap_mcbsp_data, bus_id)
++
++static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
++
++/*
++ * Stream DMA parameters. DMA request line and port address are set runtime
++ * since they are different between OMAP1 and later OMAPs
++ */
++static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2] = {
++{
++ { .name = "I2S PCM Stereo out", },
++ { .name = "I2S PCM Stereo in", },
++},
++};
++
++#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
++static const int omap1_dma_reqs[][2] = {
++ { OMAP_DMA_MCBSP1_TX, OMAP_DMA_MCBSP1_RX },
++ { OMAP_DMA_MCBSP2_TX, OMAP_DMA_MCBSP2_RX },
++ { OMAP_DMA_MCBSP3_TX, OMAP_DMA_MCBSP3_RX },
++};
++static const unsigned long omap1_mcbsp_port[][2] = {
++ { OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
++ OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
++ { OMAP1510_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1,
++ OMAP1510_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
++ { OMAP1510_MCBSP3_BASE + OMAP_MCBSP_REG_DXR1,
++ OMAP1510_MCBSP3_BASE + OMAP_MCBSP_REG_DRR1 },
++};
++#else
++static const int omap1_dma_reqs[][2] = {};
++static const unsigned long omap1_mcbsp_port[][2] = {};
++#endif
++#if defined(CONFIG_ARCH_OMAP2420)
++static const int omap2420_dma_reqs[][2] = {
++ { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX },
++ { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX },
++};
++static const unsigned long omap2420_mcbsp_port[][2] = {
++ { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
++ OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
++ { OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1,
++ OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
++};
++#else
++static const int omap2420_dma_reqs[][2] = {};
++static const unsigned long omap2420_mcbsp_port[][2] = {};
++#endif
++
++static int omap_mcbsp_dai_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 omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
++ int err = 0;
++
++ if (!cpu_dai->active)
++ err = omap_mcbsp_request(mcbsp_data->bus_id);
++
++ return err;
++}
++
++static void omap_mcbsp_dai_shutdown(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 omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
++
++ if (!cpu_dai->active) {
++ omap_mcbsp_free(mcbsp_data->bus_id);
++ mcbsp_data->configured = 0;
++ }
++}
++
++static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
++ struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
++ int err = 0;
++
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++ case SNDRV_PCM_TRIGGER_RESUME:
++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++ if (!mcbsp_data->active++)
++ omap_mcbsp_start(mcbsp_data->bus_id);
++ break;
++
++ case SNDRV_PCM_TRIGGER_STOP:
++ case SNDRV_PCM_TRIGGER_SUSPEND:
++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++ if (!--mcbsp_data->active)
++ omap_mcbsp_stop(mcbsp_data->bus_id);
++ break;
++ default:
++ err = -EINVAL;
++ }
++
++ return err;
++}
++
++static int omap_mcbsp_dai_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_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
++ struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
++ struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
++ int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
++ unsigned long port;
++
++ if (cpu_class_is_omap1()) {
++ dma = omap1_dma_reqs[bus_id][substream->stream];
++ port = omap1_mcbsp_port[bus_id][substream->stream];
++ } else if (cpu_is_omap2420()) {
++ dma = omap2420_dma_reqs[bus_id][substream->stream];
++ port = omap2420_mcbsp_port[bus_id][substream->stream];
++ } else {
++ /*
++ * TODO: Add support for 2430 and 3430
++ */
++ return -ENODEV;
++ }
++ omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
++ omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
++ cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];
++
++ if (mcbsp_data->configured) {
++ /* McBSP already configured by another stream */
++ return 0;
++ }
++
++ switch (params_channels(params)) {
++ case 2:
++ /* Set 1 word per (McBPSP) frame and use dual-phase frames */
++ regs->rcr2 |= RFRLEN2(1 - 1) | RPHASE;
++ regs->rcr1 |= RFRLEN1(1 - 1);
++ regs->xcr2 |= XFRLEN2(1 - 1) | XPHASE;
++ regs->xcr1 |= XFRLEN1(1 - 1);
++ break;
++ default:
++ /* Unsupported number of channels */
++ return -EINVAL;
++ }
++
++ switch (params_format(params)) {
++ case SNDRV_PCM_FORMAT_S16_LE:
++ /* Set word lengths */
++ regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_16);
++ regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_16);
++ regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16);
++ regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_16);
++ /* Set FS period and length in terms of bit clock periods */
++ regs->srgr2 |= FPER(16 * 2 - 1);
++ regs->srgr1 |= FWID(16 - 1);
++ break;
++ default:
++ /* Unsupported PCM format */
++ return -EINVAL;
++ }
++
++ omap_mcbsp_config(bus_id, &mcbsp_data->regs);
++ mcbsp_data->configured = 1;
++
++ return 0;
++}
++
++/*
++ * This must be called before _set_clkdiv and _set_sysclk since McBSP register
++ * cache is initialized here
++ */
++static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
++ unsigned int fmt)
++{
++ struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
++ struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
++
++ if (mcbsp_data->configured)
++ return 0;
++
++ memset(regs, 0, sizeof(*regs));
++ /* Generic McBSP register settings */
++ regs->spcr2 |= XINTM(3) | FREE;
++ regs->spcr1 |= RINTM(3);
++ regs->rcr2 |= RFIG;
++ regs->xcr2 |= XFIG;
++
++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++ case SND_SOC_DAIFMT_I2S:
++ /* 1-bit data delay */
++ regs->rcr2 |= RDATDLY(1);
++ regs->xcr2 |= XDATDLY(1);
++ break;
++ default:
++ /* Unsupported data format */
++ return -EINVAL;
++ }
++
++ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
++ case SND_SOC_DAIFMT_CBS_CFS:
++ /* McBSP master. Set FS and bit clocks as outputs */
++ regs->pcr0 |= FSXM | FSRM |
++ CLKXM | CLKRM;
++ /* Sample rate generator drives the FS */
++ regs->srgr2 |= FSGM;
++ break;
++ case SND_SOC_DAIFMT_CBM_CFM:
++ /* McBSP slave */
++ break;
++ default:
++ /* Unsupported master/slave configuration */
++ return -EINVAL;
++ }
++
++ /* Set bit clock (CLKX/CLKR) and FS polarities */
++ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
++ case SND_SOC_DAIFMT_NB_NF:
++ /*
++ * Normal BCLK + FS.
++ * FS active low. TX data driven on falling edge of bit clock
++ * and RX data sampled on rising edge of bit clock.
++ */
++ regs->pcr0 |= FSXP | FSRP |
++ CLKXP | CLKRP;
++ break;
++ case SND_SOC_DAIFMT_NB_IF:
++ regs->pcr0 |= CLKXP | CLKRP;
++ break;
++ case SND_SOC_DAIFMT_IB_NF:
++ regs->pcr0 |= FSXP | FSRP;
++ break;
++ case SND_SOC_DAIFMT_IB_IF:
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
++ int div_id, int div)
++{
++ struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
++ struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
++
++ if (div_id != OMAP_MCBSP_CLKGDV)
++ return -ENODEV;
++
++ regs->srgr1 |= CLKGDV(div - 1);
++
++ return 0;
++}
++
++static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
++ int clk_id)
++{
++ int sel_bit;
++ u16 reg;
++
++ if (cpu_class_is_omap1()) {
++ /* OMAP1's can use only external source clock */
++ if (unlikely(clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK))
++ return -EINVAL;
++ else
++ return 0;
++ }
++
++ switch (mcbsp_data->bus_id) {
++ case 0:
++ reg = OMAP2_CONTROL_DEVCONF0;
++ sel_bit = 2;
++ break;
++ case 1:
++ reg = OMAP2_CONTROL_DEVCONF0;
++ sel_bit = 6;
++ break;
++ /* TODO: Support for ports 3 - 5 in OMAP2430 and OMAP34xx */
++ default:
++ return -EINVAL;
++ }
++
++ if (cpu_class_is_omap2()) {
++ if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK) {
++ omap_ctrl_writel(omap_ctrl_readl(reg) &
++ ~(1 << sel_bit), reg);
++ } else {
++ omap_ctrl_writel(omap_ctrl_readl(reg) |
++ (1 << sel_bit), reg);
++ }
++ }
++
++ return 0;
++}
++
++static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
++ int clk_id, unsigned int freq,
++ int dir)
++{
++ struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
++ struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
++ int err = 0;
++
++ switch (clk_id) {
++ case OMAP_MCBSP_SYSCLK_CLK:
++ regs->srgr2 |= CLKSM;
++ break;
++ case OMAP_MCBSP_SYSCLK_CLKS_FCLK:
++ case OMAP_MCBSP_SYSCLK_CLKS_EXT:
++ err = omap_mcbsp_dai_set_clks_src(mcbsp_data, clk_id);
++ break;
++
++ case OMAP_MCBSP_SYSCLK_CLKX_EXT:
++ regs->srgr2 |= CLKSM;
++ case OMAP_MCBSP_SYSCLK_CLKR_EXT:
++ regs->pcr0 |= SCLKME;
++ break;
++ default:
++ err = -ENODEV;
++ }
++
++ return err;
++}
++
++struct snd_soc_cpu_dai omap_mcbsp_dai[NUM_LINKS] = {
++{
++ .name = "omap-mcbsp-dai",
++ .id = 0,
++ .type = SND_SOC_DAI_I2S,
++ .playback = {
++ .channels_min = 2,
++ .channels_max = 2,
++ .rates = OMAP_MCBSP_RATES,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE,
++ },
++ .capture = {
++ .channels_min = 2,
++ .channels_max = 2,
++ .rates = OMAP_MCBSP_RATES,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE,
++ },
++ .ops = {
++ .startup = omap_mcbsp_dai_startup,
++ .shutdown = omap_mcbsp_dai_shutdown,
++ .trigger = omap_mcbsp_dai_trigger,
++ .hw_params = omap_mcbsp_dai_hw_params,
++ },
++ .dai_ops = {
++ .set_fmt = omap_mcbsp_dai_set_dai_fmt,
++ .set_clkdiv = omap_mcbsp_dai_set_clkdiv,
++ .set_sysclk = omap_mcbsp_dai_set_dai_sysclk,
++ },
++ .private_data = &mcbsp_data[0].bus_id,
++},
++};
++EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
++
++MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula at nokia.com>");
++MODULE_DESCRIPTION("OMAP I2S SoC Interface");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h
+new file mode 100644
+index 0000000..9965fd4
+--- /dev/null
++++ b/sound/soc/omap/omap-mcbsp.h
+@@ -0,0 +1,49 @@
++/*
++ * omap-mcbsp.h
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ *
++ * Contact: Jarkko Nikula <jarkko.nikula at nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ *
++ */
++
++#ifndef __OMAP_I2S_H__
++#define __OMAP_I2S_H__
++
++/* Source clocks for McBSP sample rate generator */
++enum omap_mcbsp_clksrg_clk {
++ OMAP_MCBSP_SYSCLK_CLKS_FCLK, /* Internal FCLK */
++ OMAP_MCBSP_SYSCLK_CLKS_EXT, /* External CLKS pin */
++ OMAP_MCBSP_SYSCLK_CLK, /* Internal ICLK */
++ OMAP_MCBSP_SYSCLK_CLKX_EXT, /* External CLKX pin */
++ OMAP_MCBSP_SYSCLK_CLKR_EXT, /* External CLKR pin */
++};
++
++/* McBSP dividers */
++enum omap_mcbsp_div {
++ OMAP_MCBSP_CLKGDV, /* Sample rate generator divider */
++};
++
++/*
++ * REVISIT: Preparation for the ASoC v2. Let the number of available links to
++ * be same than number of McBSP ports found in OMAP(s) we are compiling for.
++ */
++#define NUM_LINKS 1
++
++extern struct snd_soc_cpu_dai omap_mcbsp_dai[NUM_LINKS];
++
++#endif
+diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
+new file mode 100644
+index 0000000..6237020
+--- /dev/null
++++ b/sound/soc/omap/omap-pcm.c
+@@ -0,0 +1,357 @@
++/*
++ * omap-pcm.c -- ALSA PCM interface for the OMAP SoC
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ *
++ * Contact: Jarkko Nikula <jarkko.nikula at nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ *
++ */
++
++#include <linux/dma-mapping.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++
++#include <asm/arch/dma.h>
++#include "omap-pcm.h"
++
++static const struct snd_pcm_hardware omap_pcm_hardware = {
++ .info = SNDRV_PCM_INFO_MMAP |
++ SNDRV_PCM_INFO_MMAP_VALID |
++ SNDRV_PCM_INFO_INTERLEAVED |
++ SNDRV_PCM_INFO_PAUSE |
++ SNDRV_PCM_INFO_RESUME,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE,
++ .period_bytes_min = 32,
++ .period_bytes_max = 64 * 1024,
++ .periods_min = 2,
++ .periods_max = 255,
++ .buffer_bytes_max = 128 * 1024,
++};
++
++struct omap_runtime_data {
++ spinlock_t lock;
++ struct omap_pcm_dma_data *dma_data;
++ int dma_ch;
++ int period_index;
++};
++
++static void omap_pcm_dma_irq(int ch, u16 stat, void *data)
++{
++ struct snd_pcm_substream *substream = data;
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ struct omap_runtime_data *prtd = runtime->private_data;
++ unsigned long flags;
++
++ if (cpu_is_omap1510()) {
++ /*
++ * OMAP1510 doesn't support DMA chaining so have to restart
++ * the transfer after all periods are transferred
++ */
++ spin_lock_irqsave(&prtd->lock, flags);
++ if (prtd->period_index >= 0) {
++ if (++prtd->period_index == runtime->periods) {
++ prtd->period_index = 0;
++ omap_start_dma(prtd->dma_ch);
++ }
++ }
++ spin_unlock_irqrestore(&prtd->lock, flags);
++ }
++
++ snd_pcm_period_elapsed(substream);
++}
++
++/* this may get called several times by oss emulation */
++static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct omap_runtime_data *prtd = runtime->private_data;
++ struct omap_pcm_dma_data *dma_data = rtd->dai->cpu_dai->dma_data;
++ int err = 0;
++
++ if (!dma_data)
++ return -ENODEV;
++
++ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
++ runtime->dma_bytes = params_buffer_bytes(params);
++
++ if (prtd->dma_data)
++ return 0;
++ prtd->dma_data = dma_data;
++ err = omap_request_dma(dma_data->dma_req, dma_data->name,
++ omap_pcm_dma_irq, substream, &prtd->dma_ch);
++ if (!cpu_is_omap1510()) {
++ /*
++ * Link channel with itself so DMA doesn't need any
++ * reprogramming while looping the buffer
++ */
++ omap_dma_link_lch(prtd->dma_ch, prtd->dma_ch);
++ }
++
++ return err;
++}
++
++static int omap_pcm_hw_free(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ struct omap_runtime_data *prtd = runtime->private_data;
++
++ if (prtd->dma_data == NULL)
++ return 0;
++
++ if (!cpu_is_omap1510())
++ omap_dma_unlink_lch(prtd->dma_ch, prtd->dma_ch);
++ omap_free_dma(prtd->dma_ch);
++ prtd->dma_data = NULL;
++
++ snd_pcm_set_runtime_buffer(substream, NULL);
++
++ return 0;
++}
++
++static int omap_pcm_prepare(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ struct omap_runtime_data *prtd = runtime->private_data;
++ struct omap_pcm_dma_data *dma_data = prtd->dma_data;
++ struct omap_dma_channel_params dma_params;
++
++ memset(&dma_params, 0, sizeof(dma_params));
++ /*
++ * Note: Regardless of interface data formats supported by OMAP McBSP
++ * or EAC blocks, internal representation is always fixed 16-bit/sample
++ */
++ dma_params.data_type = OMAP_DMA_DATA_TYPE_S16;
++ dma_params.trigger = dma_data->dma_req;
++ dma_params.sync_mode = OMAP_DMA_SYNC_ELEMENT;
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++ dma_params.src_amode = OMAP_DMA_AMODE_POST_INC;
++ dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT;
++ dma_params.src_or_dst_synch = OMAP_DMA_DST_SYNC;
++ dma_params.src_start = runtime->dma_addr;
++ dma_params.dst_start = dma_data->port_addr;
++ } else {
++ dma_params.src_amode = OMAP_DMA_AMODE_CONSTANT;
++ dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC;
++ dma_params.src_or_dst_synch = OMAP_DMA_SRC_SYNC;
++ dma_params.src_start = dma_data->port_addr;
++ dma_params.dst_start = runtime->dma_addr;
++ }
++ /*
++ * Set DMA transfer frame size equal to ALSA period size and frame
++ * count as no. of ALSA periods. Then with DMA frame interrupt enabled,
++ * we can transfer the whole ALSA buffer with single DMA transfer but
++ * still can get an interrupt at each period bounary
++ */
++ dma_params.elem_count = snd_pcm_lib_period_bytes(substream) / 2;
++ dma_params.frame_count = runtime->periods;
++ omap_set_dma_params(prtd->dma_ch, &dma_params);
++
++ omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);
++
++ return 0;
++}
++
++static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ struct omap_runtime_data *prtd = runtime->private_data;
++ int ret = 0;
++
++ spin_lock_irq(&prtd->lock);
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++ case SNDRV_PCM_TRIGGER_RESUME:
++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++ prtd->period_index = 0;
++ omap_start_dma(prtd->dma_ch);
++ break;
++
++ case SNDRV_PCM_TRIGGER_STOP:
++ case SNDRV_PCM_TRIGGER_SUSPEND:
++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++ prtd->period_index = -1;
++ omap_stop_dma(prtd->dma_ch);
++ break;
++ default:
++ ret = -EINVAL;
++ }
++ spin_unlock_irq(&prtd->lock);
++
++ return ret;
++}
++
++static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ struct omap_runtime_data *prtd = runtime->private_data;
++ dma_addr_t ptr;
++ snd_pcm_uframes_t offset;
++
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ ptr = omap_get_dma_src_pos(prtd->dma_ch);
++ else
++ ptr = omap_get_dma_dst_pos(prtd->dma_ch);
++
++ offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
++ if (offset >= runtime->buffer_size)
++ offset = 0;
++
++ return offset;
++}
++
++static int omap_pcm_open(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ struct omap_runtime_data *prtd;
++ int ret;
++
++ snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware);
++
++ /* Ensure that buffer size is a multiple of period size */
++ ret = snd_pcm_hw_constraint_integer(runtime,
++ SNDRV_PCM_HW_PARAM_PERIODS);
++ if (ret < 0)
++ goto out;
++
++ prtd = kzalloc(sizeof(prtd), GFP_KERNEL);
++ if (prtd == NULL) {
++ ret = -ENOMEM;
++ goto out;
++ }
++ spin_lock_init(&prtd->lock);
++ runtime->private_data = prtd;
++
++out:
++ return ret;
++}
++
++static int omap_pcm_close(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++
++ kfree(runtime->private_data);
++ return 0;
++}
++
++static int omap_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 omap_pcm_ops = {
++ .open = omap_pcm_open,
++ .close = omap_pcm_close,
++ .ioctl = snd_pcm_lib_ioctl,
++ .hw_params = omap_pcm_hw_params,
++ .hw_free = omap_pcm_hw_free,
++ .prepare = omap_pcm_prepare,
++ .trigger = omap_pcm_trigger,
++ .pointer = omap_pcm_pointer,
++ .mmap = omap_pcm_mmap,
++};
++
++static u64 omap_pcm_dmamask = DMA_BIT_MASK(32);
++
++static int omap_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 = omap_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);
++ if (!buf->area)
++ return -ENOMEM;
++
++ buf->bytes = size;
++ return 0;
++}
++
++static void omap_pcm_free_dma_buffers(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;
++ }
++}
++
++int omap_pcm_new(struct snd_card *card, struct snd_soc_codec_dai *dai,
++ struct snd_pcm *pcm)
++{
++ int ret = 0;
++
++ if (!card->dev->dma_mask)
++ card->dev->dma_mask = &omap_pcm_dmamask;
++ if (!card->dev->coherent_dma_mask)
++ card->dev->coherent_dma_mask = DMA_32BIT_MASK;
++
++ if (dai->playback.channels_min) {
++ ret = omap_pcm_preallocate_dma_buffer(pcm,
++ SNDRV_PCM_STREAM_PLAYBACK);
++ if (ret)
++ goto out;
++ }
++
++ if (dai->capture.channels_min) {
++ ret = omap_pcm_preallocate_dma_buffer(pcm,
++ SNDRV_PCM_STREAM_CAPTURE);
++ if (ret)
++ goto out;
++ }
++
++out:
++ return ret;
++}
++
++struct snd_soc_platform omap_soc_platform = {
++ .name = "omap-pcm-audio",
++ .pcm_ops = &omap_pcm_ops,
++ .pcm_new = omap_pcm_new,
++ .pcm_free = omap_pcm_free_dma_buffers,
++};
++EXPORT_SYMBOL_GPL(omap_soc_platform);
++
++MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula at nokia.com>");
++MODULE_DESCRIPTION("OMAP PCM DMA module");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h
+new file mode 100644
+index 0000000..e4369bd
+--- /dev/null
++++ b/sound/soc/omap/omap-pcm.h
+@@ -0,0 +1,35 @@
++/*
++ * omap-pcm.h
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ *
++ * Contact: Jarkko Nikula <jarkko.nikula at nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ *
++ */
++
++#ifndef __OMAP_PCM_H__
++#define __OMAP_PCM_H__
++
++struct omap_pcm_dma_data {
++ char *name; /* stream identifier */
++ int dma_req; /* DMA request line */
++ unsigned long port_addr; /* transmit/receive register */
++};
++
++extern struct snd_soc_platform omap_soc_platform;
++
++#endif
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 1a70a6a..7f32a11 100644
--- a/sound/soc/pxa/corgi.c
@@ -950749,11 +1257478,171 @@
snd_soc_dapm_sync_endpoints(codec);
return 0;
+diff --git a/sound/soc/s3c24xx/ln2440sbc_alc650.c b/sound/soc/s3c24xx/ln2440sbc_alc650.c
+index 9ed8f2e..4eab2c1 100644
+--- a/sound/soc/s3c24xx/ln2440sbc_alc650.c
++++ b/sound/soc/s3c24xx/ln2440sbc_alc650.c
+@@ -1,10 +1,10 @@
+ /*
+ * SoC audio for ln2440sbc
+- *
++ *
+ * Copyright 2007 KonekTel, a.s.
+ * Author: Ivan Kuten
+ * ivan.kuten at promwad.com
+- *
++ *
+ * Heavily based on smdk2443_wm9710.c
+ * Copyright 2007 Wolfson Microelectronics PLC.
+ * Author: Graeme Gregory
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
-index 6ee115c..962cc20 100644
+index 6ee115c..0e9d1c5 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)
+@@ -33,7 +33,7 @@
+ #include <asm/arch/regs-gpio.h>
+ #include <asm/hardware.h>
+ #include <asm/arch/audio.h>
+-#include <asm/io.h>
++#include <linux/io.h>
+ #include <asm/arch/spi-gpio.h>
+
+ #include <asm/plat-s3c24xx/regs-iis.h>
+@@ -122,7 +122,7 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
+
+ /* set MCLK division for sample rate */
+ ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
+- S3C2410_IISMOD_32FS );
++ S3C2410_IISMOD_32FS);
+ if (ret < 0)
+ return ret;
+
+@@ -133,7 +133,7 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
+
+ /* set prescaler division for sample rate */
+ ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
+- S3C24XX_PRESCALE(4,4));
++ S3C24XX_PRESCALE(4, 4));
+ if (ret < 0)
+ return ret;
+
+@@ -222,7 +222,7 @@ static struct snd_soc_ops neo1973_voice_ops = {
+ .hw_free = neo1973_voice_hw_free,
+ };
+
+-static int neo1973_scenario = 0;
++static int neo1973_scenario;
+
+ static int neo1973_get_scenario(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+@@ -233,7 +233,7 @@ static int neo1973_get_scenario(struct snd_kcontrol *kcontrol,
+
+ static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario)
+ {
+- switch(neo1973_scenario) {
++ switch (neo1973_scenario) {
+ case NEO_AUDIO_OFF:
+ snd_soc_dapm_set_endpoint(codec, "Audio Out", 0);
+ snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
+@@ -334,7 +334,7 @@ static void lm4857_write_regs(void)
+ static int lm4857_get_reg(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+- int reg=kcontrol->private_value & 0xFF;
++ int reg = kcontrol->private_value & 0xFF;
+ int shift = (kcontrol->private_value >> 8) & 0x0F;
+ int mask = (kcontrol->private_value >> 16) & 0xFF;
+
+@@ -349,11 +349,11 @@ static int lm4857_set_reg(struct snd_kcontrol *kcontrol,
+ int shift = (kcontrol->private_value >> 8) & 0x0F;
+ int mask = (kcontrol->private_value >> 16) & 0xFF;
+
+- if (((lm4857_regs[reg] >> shift ) & mask) ==
++ if (((lm4857_regs[reg] >> shift) & mask) ==
+ ucontrol->value.integer.value[0])
+ return 0;
+
+- lm4857_regs[reg] &= ~ (mask << shift);
++ lm4857_regs[reg] &= ~(mask << shift);
+ lm4857_regs[reg] |= ucontrol->value.integer.value[0] << shift;
+ lm4857_write_regs();
+ return 1;
+@@ -398,7 +398,7 @@ static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
+
+
+ /* example machine audio_mapnections */
+-static const char* audio_map[][3] = {
++static const char *audio_map[][3] = {
+
+ /* Connections to the lm4857 amp */
+ {"Audio Out", NULL, "LOUT1"},
+@@ -450,7 +450,7 @@ static const char *neo_scenarios[] = {
+ };
+
+ static const struct soc_enum neo_scenario_enum[] = {
+- SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(neo_scenarios),neo_scenarios),
++ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(neo_scenarios), neo_scenarios),
+ };
+
+ static const struct snd_kcontrol_new wm8753_neo1973_controls[] = {
+@@ -521,8 +521,8 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec)
+ /*
+ * BT Codec DAI
+ */
+-static struct snd_soc_cpu_dai bt_dai =
+-{ .name = "Bluetooth",
++static struct snd_soc_cpu_dai bt_dai = {
++ .name = "Bluetooth",
+ .id = 0,
+ .type = SND_SOC_DAI_PCM,
+ .playback = {
+@@ -616,6 +616,35 @@ static int lm4857_i2c_attach(struct i2c_adapter *adap)
+ return i2c_probe(adap, &addr_data, lm4857_amp_probe);
+ }
+
++static u8 lm4857_state;
++
++static int lm4857_suspend(struct i2c_client *dev, pm_message_t state)
++{
++ dev_dbg(&dev->dev, "lm4857_suspend\n");
++ lm4857_state = lm4857_regs[LM4857_CTRL] & 0xf;
++ if (lm4857_state) {
++ lm4857_regs[LM4857_CTRL] &= 0xf0;
++ lm4857_write_regs();
++ }
++ return 0;
++}
++
++static int lm4857_resume(struct i2c_client *dev)
++{
++ if (lm4857_state) {
++ lm4857_regs[LM4857_CTRL] |= (lm4857_state & 0x0f);
++ lm4857_write_regs();
++ }
++ return 0;
++}
++
++static void lm4857_shutdown(struct i2c_client *dev)
++{
++ dev_dbg(&dev->dev, "lm4857_shutdown\n");
++ lm4857_regs[LM4857_CTRL] &= 0xf0;
++ lm4857_write_regs();
++}
++
+ /* corgi i2c codec control layer */
+ static struct i2c_driver lm4857_i2c_driver = {
+ .driver = {
+@@ -623,6 +652,9 @@ static struct i2c_driver lm4857_i2c_driver = {
+ .owner = THIS_MODULE,
+ },
+ .id = I2C_DRIVERID_LM4857,
++ .suspend = lm4857_suspend,
++ .resume = lm4857_resume,
++ .shutdown = lm4857_shutdown,
+ .attach_adapter = lm4857_i2c_attach,
+ .detach_client = lm4857_i2c_detach,
+ .command = NULL,
+@@ -659,6 +691,7 @@ static int __init neo1973_init(void)
static void __exit neo1973_exit(void)
{
@@ -950761,6 +1257650,69 @@
platform_device_unregister(neo1973_snd_device);
}
+@@ -666,6 +699,6 @@ module_init(neo1973_init);
+ module_exit(neo1973_exit);
+
+ /* Module information */
+-MODULE_AUTHOR("Graeme Gregory, graeme.gregory at wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_AUTHOR("Graeme Gregory, graeme at openmoko.org, www.openmoko.org");
+ MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973");
+ MODULE_LICENSE("GPL");
+diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c
+index 1c1ddbf..e81d9a6 100644
+--- a/sound/soc/s3c24xx/s3c2443-ac97.c
++++ b/sound/soc/s3c24xx/s3c2443-ac97.c
+@@ -19,6 +19,7 @@
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/interrupt.h>
++#include <linux/io.h>
+ #include <linux/wait.h>
+ #include <linux/delay.h>
+ #include <linux/clk.h>
+@@ -30,7 +31,6 @@
+ #include <sound/soc.h>
+
+ #include <asm/hardware.h>
+-#include <asm/io.h>
+ #include <asm/plat-s3c/regs-ac97.h>
+ #include <asm/arch/regs-gpio.h>
+ #include <asm/arch/regs-clock.h>
+@@ -47,7 +47,7 @@ struct s3c24xx_ac97_info {
+ };
+ static struct s3c24xx_ac97_info s3c24xx_ac97;
+
+-DECLARE_COMPLETION(ac97_completion);
++static DECLARE_COMPLETION(ac97_completion);
+ static u32 codec_ready;
+ static DECLARE_MUTEX(ac97_mutex);
+
+@@ -290,7 +290,7 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd)
+ u32 ac_glbctrl;
+
+ ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
+- switch(cmd) {
++ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+@@ -333,7 +333,7 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
+ u32 ac_glbctrl;
+
+ ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
+- switch(cmd) {
++ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+@@ -391,7 +391,6 @@ struct snd_soc_cpu_dai s3c2443_ac97_dai[] = {
+ .trigger = s3c2443_ac97_mic_trigger,},
+ },
+ };
+-
+ EXPORT_SYMBOL_GPL(s3c2443_ac97_dai);
+ EXPORT_SYMBOL_GPL(soc_ac97_ops);
+
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
@@ -950928,9 +1257880,25 @@
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
+index 29a6c82..6c70a81 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
+@@ -20,6 +20,7 @@
+
+ #include <linux/module.h>
+ #include <linux/init.h>
++#include <linux/io.h>
+ #include <linux/platform_device.h>
+ #include <linux/slab.h>
+ #include <linux/dma-mapping.h>
+@@ -30,7 +31,6 @@
+ #include <sound/soc.h>
+
+ #include <asm/dma.h>
+-#include <asm/io.h>
+ #include <asm/hardware.h>
+ #include <asm/arch/dma.h>
+ #include <asm/arch/audio.h>
@@ -39,7 +39,7 @@
#define S3C24XX_PCM_DEBUG 0
@@ -950940,7 +1257908,7 @@
#else
#define DBG(x...)
#endif
-@@ -88,7 +88,7 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream)
+@@ -88,20 +88,20 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream)
dma_addr_t pos = prtd->dma_pos;
int ret;
@@ -950949,7 +1257917,10 @@
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)
+
+- DBG("dma_loaded: %d\n",prtd->dma_loaded);
++ DBG("dma_loaded: %d\n", prtd->dma_loaded);
+
if ((pos + len) > prtd->dma_end) {
len = prtd->dma_end - pos;
DBG(KERN_DEBUG "%s: corrected dma len %ld\n",
@@ -950957,8 +1257928,12 @@
+ __func__, len);
}
- ret = s3c2410_dma_enqueue(prtd->params->channel,
-@@ -123,7 +123,7 @@ static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel,
+- ret = s3c2410_dma_enqueue(prtd->params->channel,
++ ret = s3c2410_dma_enqueue(prtd->params->channel,
+ substream, pos, len);
+
+ if (ret == 0) {
+@@ -123,13 +123,13 @@ static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel,
struct snd_pcm_substream *substream = dev_id;
struct s3c24xx_runtime_data *prtd;
@@ -950967,9 +1257942,19 @@
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,
+
+ prtd = substream->runtime->private_data;
+-
++
+ if (substream)
+ snd_pcm_period_elapsed(substream);
+
+@@ -150,9 +150,9 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct s3c24xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data;
unsigned long totbytes = params_buffer_bytes(params);
- int ret=0;
+- int ret=0;
++ int ret = 0;
- DBG("Entered %s\n", __FUNCTION__);
+ DBG("Entered %s\n", __func__);
@@ -950985,7 +1257970,7 @@
/* 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)
+@@ -218,12 +218,12 @@ static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream)
struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
int ret = 0;
@@ -950994,6 +1257979,12 @@
/* return if this is a bufferless transfer e.g.
* codec <--> BT codec or GSM modem -- lg FIXME */
+ if (!prtd->params)
+- return 0;
++ return 0;
+
+ /* channel needs configuring for mem=>device, increment memory addr,
+ * sync to pclk, half-word transfers to the IIS-FIFO. */
@@ -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;
@@ -951003,7 +1257994,17 @@
spin_lock(&prtd->lock);
-@@ -301,7 +301,7 @@ static snd_pcm_uframes_t
+@@ -293,15 +293,15 @@ static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+ return ret;
+ }
+
+-static snd_pcm_uframes_t
+- s3c24xx_pcm_pointer(struct snd_pcm_substream *substream)
++static snd_pcm_uframes_t
++s3c24xx_pcm_pointer(struct snd_pcm_substream *substream)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct s3c24xx_runtime_data *prtd = runtime->private_data;
unsigned long res;
dma_addr_t src, dst;
@@ -951012,6 +1258013,15 @@
spin_lock(&prtd->lock);
s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
+@@ -313,7 +313,7 @@ static snd_pcm_uframes_t
+
+ spin_unlock(&prtd->lock);
+
+- DBG("Pointer %x %x\n",src,dst);
++ DBG("Pointer %x %x\n", src, dst);
+
+ /* we seem to be getting the odd error from the pcm library due
+ * to out-of-bounds pointers. this is maybe due to the dma engine
@@ -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;
@@ -951021,16 +1258031,25 @@
snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware);
-@@ -353,7 +353,7 @@ static int s3c24xx_pcm_close(struct snd_pcm_substream *substream)
+@@ -353,13 +353,13 @@ 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,
+- if (prtd)
+- kfree(prtd);
+- else
++ if (!prtd)
+ DBG("s3c24xx_pcm_close called with prtd == NULL\n");
+
++ kfree(prtd);
++
+ return 0;
+ }
+
+@@ -368,12 +368,12 @@ static int s3c24xx_pcm_mmap(struct snd_pcm_substream *substream,
{
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -951038,7 +1258057,15 @@
+ DBG("Entered %s\n", __func__);
return dma_mmap_writecombine(substream->pcm->card->dev, vma,
- runtime->dma_area,
+- runtime->dma_area,
+- runtime->dma_addr,
+- runtime->dma_bytes);
++ runtime->dma_area,
++ runtime->dma_addr,
++ runtime->dma_bytes);
+ }
+
+ static struct snd_pcm_ops s3c24xx_pcm_ops = {
@@ -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;
@@ -951057,7 +1258084,13 @@
for (stream = 0; stream < 2; stream++) {
substream = pcm->streams[stream].substream;
-@@ -437,7 +437,7 @@ static int s3c24xx_pcm_new(struct snd_card *card,
+@@ -432,12 +432,12 @@ static void s3c24xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
+
+ static u64 s3c24xx_pcm_dmamask = DMA_32BIT_MASK;
+
+-static int s3c24xx_pcm_new(struct snd_card *card,
++static int s3c24xx_pcm_new(struct snd_card *card,
+ struct snd_soc_codec_dai *dai, struct snd_pcm *pcm)
{
int ret = 0;
@@ -951066,6 +1258099,14 @@
if (!card->dev->dma_mask)
card->dev->dma_mask = &s3c24xx_pcm_dmamask;
+@@ -467,7 +467,6 @@ struct snd_soc_platform s3c24xx_soc_platform = {
+ .pcm_new = s3c24xx_pcm_new,
+ .pcm_free = s3c24xx_pcm_free_dma_buffers,
+ };
+-
+ EXPORT_SYMBOL_GPL(s3c24xx_soc_platform);
+
+ MODULE_AUTHOR("Ben Dooks, <ben at simtec.co.uk>");
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index f03220d..4c1e013 100644
--- a/sound/soc/sh/Kconfig
@@ -952009,3 +1259050,760 @@
/* Emagic devices */
{
USB_DEVICE(0x086a, 0x0001),
+diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
+index b2e1289..c82cf15 100644
+--- a/virt/kvm/kvm_main.c
++++ b/virt/kvm/kvm_main.c
+@@ -40,6 +40,7 @@
+ #include <linux/kvm_para.h>
+ #include <linux/pagemap.h>
+ #include <linux/mman.h>
++#include <linux/swap.h>
+
+ #include <asm/processor.h>
+ #include <asm/io.h>
+@@ -59,7 +60,7 @@ EXPORT_SYMBOL_GPL(kvm_vcpu_cache);
+
+ static __read_mostly struct preempt_ops kvm_preempt_ops;
+
+-static struct dentry *debugfs_dir;
++struct dentry *kvm_debugfs_dir;
+
+ static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
+ unsigned long arg);
+@@ -119,6 +120,29 @@ void kvm_flush_remote_tlbs(struct kvm *kvm)
+ smp_call_function_mask(cpus, ack_flush, NULL, 1);
+ }
+
++void kvm_reload_remote_mmus(struct kvm *kvm)
++{
++ int i, cpu;
++ cpumask_t cpus;
++ struct kvm_vcpu *vcpu;
++
++ cpus_clear(cpus);
++ for (i = 0; i < KVM_MAX_VCPUS; ++i) {
++ vcpu = kvm->vcpus[i];
++ if (!vcpu)
++ continue;
++ if (test_and_set_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
++ continue;
++ cpu = vcpu->cpu;
++ if (cpu != -1 && cpu != raw_smp_processor_id())
++ cpu_set(cpu, cpus);
++ }
++ if (cpus_empty(cpus))
++ return;
++ smp_call_function_mask(cpus, ack_flush, NULL, 1);
++}
++
++
+ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
+ {
+ struct page *page;
+@@ -170,6 +194,7 @@ static struct kvm *kvm_create_vm(void)
+ mutex_init(&kvm->lock);
+ kvm_io_bus_init(&kvm->mmio_bus);
+ init_rwsem(&kvm->slots_lock);
++ atomic_set(&kvm->users_count, 1);
+ spin_lock(&kvm_lock);
+ list_add(&kvm->vm_list, &vm_list);
+ spin_unlock(&kvm_lock);
+@@ -189,9 +214,13 @@ static void kvm_free_physmem_slot(struct kvm_memory_slot *free,
+ if (!dont || free->dirty_bitmap != dont->dirty_bitmap)
+ vfree(free->dirty_bitmap);
+
++ if (!dont || free->lpage_info != dont->lpage_info)
++ vfree(free->lpage_info);
++
+ free->npages = 0;
+ free->dirty_bitmap = NULL;
+ free->rmap = NULL;
++ free->lpage_info = NULL;
+ }
+
+ void kvm_free_physmem(struct kvm *kvm)
+@@ -215,11 +244,25 @@ static void kvm_destroy_vm(struct kvm *kvm)
+ mmdrop(mm);
+ }
+
++void kvm_get_kvm(struct kvm *kvm)
++{
++ atomic_inc(&kvm->users_count);
++}
++EXPORT_SYMBOL_GPL(kvm_get_kvm);
++
++void kvm_put_kvm(struct kvm *kvm)
++{
++ if (atomic_dec_and_test(&kvm->users_count))
++ kvm_destroy_vm(kvm);
++}
++EXPORT_SYMBOL_GPL(kvm_put_kvm);
++
++
+ static int kvm_vm_release(struct inode *inode, struct file *filp)
+ {
+ struct kvm *kvm = filp->private_data;
+
+- kvm_destroy_vm(kvm);
++ kvm_put_kvm(kvm);
+ return 0;
+ }
+
+@@ -301,6 +344,25 @@ int __kvm_set_memory_region(struct kvm *kvm,
+ new.user_alloc = user_alloc;
+ new.userspace_addr = mem->userspace_addr;
+ }
++ if (npages && !new.lpage_info) {
++ int largepages = npages / KVM_PAGES_PER_HPAGE;
++ if (npages % KVM_PAGES_PER_HPAGE)
++ largepages++;
++ if (base_gfn % KVM_PAGES_PER_HPAGE)
++ largepages++;
++
++ new.lpage_info = vmalloc(largepages * sizeof(*new.lpage_info));
++
++ if (!new.lpage_info)
++ goto out_free;
++
++ memset(new.lpage_info, 0, largepages * sizeof(*new.lpage_info));
++
++ if (base_gfn % KVM_PAGES_PER_HPAGE)
++ new.lpage_info[0].write_count = 1;
++ if ((base_gfn+npages) % KVM_PAGES_PER_HPAGE)
++ new.lpage_info[largepages-1].write_count = 1;
++ }
+
+ /* Allocate page dirty bitmap if needed */
+ if ((new.flags & KVM_MEM_LOG_DIRTY_PAGES) && !new.dirty_bitmap) {
+@@ -397,6 +459,12 @@ int is_error_page(struct page *page)
+ }
+ EXPORT_SYMBOL_GPL(is_error_page);
+
++int is_error_pfn(pfn_t pfn)
++{
++ return pfn == bad_pfn;
++}
++EXPORT_SYMBOL_GPL(is_error_pfn);
++
+ static inline unsigned long bad_hva(void)
+ {
+ return PAGE_OFFSET;
+@@ -444,7 +512,7 @@ int kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn)
+ }
+ EXPORT_SYMBOL_GPL(kvm_is_visible_gfn);
+
+-static unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn)
++unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn)
+ {
+ struct kvm_memory_slot *slot;
+
+@@ -458,7 +526,7 @@ static unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn)
+ /*
+ * Requires current->mm->mmap_sem to be held
+ */
+-struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
++pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn)
+ {
+ struct page *page[1];
+ unsigned long addr;
+@@ -469,7 +537,7 @@ struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
+ addr = gfn_to_hva(kvm, gfn);
+ if (kvm_is_error_hva(addr)) {
+ get_page(bad_page);
+- return bad_page;
++ return page_to_pfn(bad_page);
+ }
+
+ npages = get_user_pages(current, current->mm, addr, 1, 1, 1, page,
+@@ -477,27 +545,71 @@ struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
+
+ if (npages != 1) {
+ get_page(bad_page);
+- return bad_page;
++ return page_to_pfn(bad_page);
+ }
+
+- return page[0];
++ return page_to_pfn(page[0]);
++}
++
++EXPORT_SYMBOL_GPL(gfn_to_pfn);
++
++struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
++{
++ return pfn_to_page(gfn_to_pfn(kvm, gfn));
+ }
+
+ EXPORT_SYMBOL_GPL(gfn_to_page);
+
+ void kvm_release_page_clean(struct page *page)
+ {
+- put_page(page);
++ kvm_release_pfn_clean(page_to_pfn(page));
+ }
+ EXPORT_SYMBOL_GPL(kvm_release_page_clean);
+
++void kvm_release_pfn_clean(pfn_t pfn)
++{
++ put_page(pfn_to_page(pfn));
++}
++EXPORT_SYMBOL_GPL(kvm_release_pfn_clean);
++
+ void kvm_release_page_dirty(struct page *page)
+ {
++ kvm_release_pfn_dirty(page_to_pfn(page));
++}
++EXPORT_SYMBOL_GPL(kvm_release_page_dirty);
++
++void kvm_release_pfn_dirty(pfn_t pfn)
++{
++ kvm_set_pfn_dirty(pfn);
++ kvm_release_pfn_clean(pfn);
++}
++EXPORT_SYMBOL_GPL(kvm_release_pfn_dirty);
++
++void kvm_set_page_dirty(struct page *page)
++{
++ kvm_set_pfn_dirty(page_to_pfn(page));
++}
++EXPORT_SYMBOL_GPL(kvm_set_page_dirty);
++
++void kvm_set_pfn_dirty(pfn_t pfn)
++{
++ struct page *page = pfn_to_page(pfn);
+ if (!PageReserved(page))
+ SetPageDirty(page);
+- put_page(page);
+ }
+-EXPORT_SYMBOL_GPL(kvm_release_page_dirty);
++EXPORT_SYMBOL_GPL(kvm_set_pfn_dirty);
++
++void kvm_set_pfn_accessed(pfn_t pfn)
++{
++ mark_page_accessed(pfn_to_page(pfn));
++}
++EXPORT_SYMBOL_GPL(kvm_set_pfn_accessed);
++
++void kvm_get_pfn(pfn_t pfn)
++{
++ get_page(pfn_to_page(pfn));
++}
++EXPORT_SYMBOL_GPL(kvm_get_pfn);
+
+ static int next_segment(unsigned long len, int offset)
+ {
+@@ -554,7 +666,9 @@ int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data,
+ addr = gfn_to_hva(kvm, gfn);
+ if (kvm_is_error_hva(addr))
+ return -EFAULT;
++ pagefault_disable();
+ r = __copy_from_user_inatomic(data, (void __user *)addr + offset, len);
++ pagefault_enable();
+ if (r)
+ return -EFAULT;
+ return 0;
+@@ -651,6 +765,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
+ * We will block until either an interrupt or a signal wakes us up
+ */
+ while (!kvm_cpu_has_interrupt(vcpu)
++ && !kvm_cpu_has_pending_timer(vcpu)
+ && !signal_pending(current)
+ && !kvm_arch_vcpu_runnable(vcpu)) {
+ set_current_state(TASK_INTERRUPTIBLE);
+@@ -678,8 +793,10 @@ static int kvm_vcpu_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+
+ if (vmf->pgoff == 0)
+ page = virt_to_page(vcpu->run);
++#ifdef CONFIG_X86
+ else if (vmf->pgoff == KVM_PIO_PAGE_OFFSET)
+ page = virt_to_page(vcpu->arch.pio_data);
++#endif
+ else
+ return VM_FAULT_SIGBUS;
+ get_page(page);
+@@ -701,11 +818,11 @@ static int kvm_vcpu_release(struct inode *inode, struct file *filp)
+ {
+ struct kvm_vcpu *vcpu = filp->private_data;
+
+- fput(vcpu->kvm->filp);
++ kvm_put_kvm(vcpu->kvm);
+ return 0;
+ }
+
+-static struct file_operations kvm_vcpu_fops = {
++static const struct file_operations kvm_vcpu_fops = {
+ .release = kvm_vcpu_release,
+ .unlocked_ioctl = kvm_vcpu_ioctl,
+ .compat_ioctl = kvm_vcpu_ioctl,
+@@ -723,9 +840,10 @@ static int create_vcpu_fd(struct kvm_vcpu *vcpu)
+
+ r = anon_inode_getfd(&fd, &inode, &file,
+ "kvm-vcpu", &kvm_vcpu_fops, vcpu);
+- if (r)
++ if (r) {
++ kvm_put_kvm(vcpu->kvm);
+ return r;
+- atomic_inc(&vcpu->kvm->filp->f_count);
++ }
+ return fd;
+ }
+
+@@ -760,6 +878,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n)
+ mutex_unlock(&kvm->lock);
+
+ /* Now it's all set up, let userspace reach it */
++ kvm_get_kvm(kvm);
+ r = create_vcpu_fd(vcpu);
+ if (r < 0)
+ goto unlink;
+@@ -802,28 +921,39 @@ static long kvm_vcpu_ioctl(struct file *filp,
+ r = kvm_arch_vcpu_ioctl_run(vcpu, vcpu->run);
+ break;
+ case KVM_GET_REGS: {
+- struct kvm_regs kvm_regs;
++ struct kvm_regs *kvm_regs;
+
+- memset(&kvm_regs, 0, sizeof kvm_regs);
+- r = kvm_arch_vcpu_ioctl_get_regs(vcpu, &kvm_regs);
+- if (r)
++ r = -ENOMEM;
++ kvm_regs = kzalloc(sizeof(struct kvm_regs), GFP_KERNEL);
++ if (!kvm_regs)
+ goto out;
++ r = kvm_arch_vcpu_ioctl_get_regs(vcpu, kvm_regs);
++ if (r)
++ goto out_free1;
+ r = -EFAULT;
+- if (copy_to_user(argp, &kvm_regs, sizeof kvm_regs))
+- goto out;
++ if (copy_to_user(argp, kvm_regs, sizeof(struct kvm_regs)))
++ goto out_free1;
+ r = 0;
++out_free1:
++ kfree(kvm_regs);
+ break;
+ }
+ case KVM_SET_REGS: {
+- struct kvm_regs kvm_regs;
++ struct kvm_regs *kvm_regs;
+
+- r = -EFAULT;
+- if (copy_from_user(&kvm_regs, argp, sizeof kvm_regs))
++ r = -ENOMEM;
++ kvm_regs = kzalloc(sizeof(struct kvm_regs), GFP_KERNEL);
++ if (!kvm_regs)
+ goto out;
+- r = kvm_arch_vcpu_ioctl_set_regs(vcpu, &kvm_regs);
++ r = -EFAULT;
++ if (copy_from_user(kvm_regs, argp, sizeof(struct kvm_regs)))
++ goto out_free2;
++ r = kvm_arch_vcpu_ioctl_set_regs(vcpu, kvm_regs);
+ if (r)
+- goto out;
++ goto out_free2;
+ r = 0;
++out_free2:
++ kfree(kvm_regs);
+ break;
+ }
+ case KVM_GET_SREGS: {
+@@ -851,6 +981,30 @@ static long kvm_vcpu_ioctl(struct file *filp,
+ r = 0;
+ break;
+ }
++ case KVM_GET_MP_STATE: {
++ struct kvm_mp_state mp_state;
++
++ r = kvm_arch_vcpu_ioctl_get_mpstate(vcpu, &mp_state);
++ if (r)
++ goto out;
++ r = -EFAULT;
++ if (copy_to_user(argp, &mp_state, sizeof mp_state))
++ goto out;
++ r = 0;
++ break;
++ }
++ case KVM_SET_MP_STATE: {
++ struct kvm_mp_state mp_state;
++
++ r = -EFAULT;
++ if (copy_from_user(&mp_state, argp, sizeof mp_state))
++ goto out;
++ r = kvm_arch_vcpu_ioctl_set_mpstate(vcpu, &mp_state);
++ if (r)
++ goto out;
++ r = 0;
++ break;
++ }
+ case KVM_TRANSLATE: {
+ struct kvm_translation tr;
+
+@@ -1005,7 +1159,7 @@ static int kvm_vm_mmap(struct file *file, struct vm_area_struct *vma)
+ return 0;
+ }
+
+-static struct file_operations kvm_vm_fops = {
++static const struct file_operations kvm_vm_fops = {
+ .release = kvm_vm_release,
+ .unlocked_ioctl = kvm_vm_ioctl,
+ .compat_ioctl = kvm_vm_ioctl,
+@@ -1024,12 +1178,10 @@ static int kvm_dev_ioctl_create_vm(void)
+ return PTR_ERR(kvm);
+ r = anon_inode_getfd(&fd, &inode, &file, "kvm-vm", &kvm_vm_fops, kvm);
+ if (r) {
+- kvm_destroy_vm(kvm);
++ kvm_put_kvm(kvm);
+ return r;
+ }
+
+- kvm->filp = file;
+-
+ return fd;
+ }
+
+@@ -1059,7 +1211,15 @@ static long kvm_dev_ioctl(struct file *filp,
+ r = -EINVAL;
+ if (arg)
+ goto out;
+- r = 2 * PAGE_SIZE;
++ r = PAGE_SIZE; /* struct kvm_run */
++#ifdef CONFIG_X86
++ r += PAGE_SIZE; /* pio data page */
++#endif
++ break;
++ case KVM_TRACE_ENABLE:
++ case KVM_TRACE_PAUSE:
++ case KVM_TRACE_DISABLE:
++ r = kvm_trace_ioctl(ioctl, arg);
+ break;
+ default:
+ return kvm_arch_dev_ioctl(filp, ioctl, arg);
+@@ -1232,9 +1392,9 @@ static void kvm_init_debug(void)
+ {
+ struct kvm_stats_debugfs_item *p;
+
+- debugfs_dir = debugfs_create_dir("kvm", NULL);
++ kvm_debugfs_dir = debugfs_create_dir("kvm", NULL);
+ for (p = debugfs_entries; p->name; ++p)
+- p->dentry = debugfs_create_file(p->name, 0444, debugfs_dir,
++ p->dentry = debugfs_create_file(p->name, 0444, kvm_debugfs_dir,
+ (void *)(long)p->offset,
+ stat_fops[p->kind]);
+ }
+@@ -1245,7 +1405,7 @@ static void kvm_exit_debug(void)
+
+ for (p = debugfs_entries; p->name; ++p)
+ debugfs_remove(p->dentry);
+- debugfs_remove(debugfs_dir);
++ debugfs_remove(kvm_debugfs_dir);
+ }
+
+ static int kvm_suspend(struct sys_device *dev, pm_message_t state)
+@@ -1272,6 +1432,7 @@ static struct sys_device kvm_sysdev = {
+ };
+
+ struct page *bad_page;
++pfn_t bad_pfn;
+
+ static inline
+ struct kvm_vcpu *preempt_notifier_to_vcpu(struct preempt_notifier *pn)
+@@ -1313,6 +1474,8 @@ int kvm_init(void *opaque, unsigned int vcpu_size,
+ goto out;
+ }
+
++ bad_pfn = page_to_pfn(bad_page);
++
+ r = kvm_arch_hardware_setup();
+ if (r < 0)
+ goto out_free_0;
+@@ -1386,6 +1549,7 @@ EXPORT_SYMBOL_GPL(kvm_init);
+
+ void kvm_exit(void)
+ {
++ kvm_trace_cleanup();
+ misc_deregister(&kvm_dev);
+ kmem_cache_destroy(kvm_vcpu_cache);
+ sysdev_unregister(&kvm_sysdev);
+diff --git a/virt/kvm/kvm_trace.c b/virt/kvm/kvm_trace.c
+new file mode 100644
+index 0000000..0e49547
+--- /dev/null
++++ b/virt/kvm/kvm_trace.c
+@@ -0,0 +1,276 @@
++/*
++ * kvm trace
++ *
++ * It is designed to allow debugging traces of kvm to be generated
++ * on UP / SMP machines. Each trace entry can be timestamped so that
++ * it's possible to reconstruct a chronological record of trace events.
++ * The implementation refers to blktrace kernel support.
++ *
++ * Copyright (c) 2008 Intel Corporation
++ * Copyright (C) 2006 Jens Axboe <axboe at kernel.dk>
++ *
++ * Authors: Feng(Eric) Liu, eric.e.liu at intel.com
++ *
++ * Date: Feb 2008
++ */
++
++#include <linux/module.h>
++#include <linux/relay.h>
++#include <linux/debugfs.h>
++
++#include <linux/kvm_host.h>
++
++#define KVM_TRACE_STATE_RUNNING (1 << 0)
++#define KVM_TRACE_STATE_PAUSE (1 << 1)
++#define KVM_TRACE_STATE_CLEARUP (1 << 2)
++
++struct kvm_trace {
++ int trace_state;
++ struct rchan *rchan;
++ struct dentry *lost_file;
++ atomic_t lost_records;
++};
++static struct kvm_trace *kvm_trace;
++
++struct kvm_trace_probe {
++ const char *name;
++ const char *format;
++ u32 cycle_in;
++ marker_probe_func *probe_func;
++};
++
++static inline int calc_rec_size(int cycle, int extra)
++{
++ int rec_size = KVM_TRC_HEAD_SIZE;
++
++ rec_size += extra;
++ return cycle ? rec_size += KVM_TRC_CYCLE_SIZE : rec_size;
++}
++
++static void kvm_add_trace(void *probe_private, void *call_data,
++ const char *format, va_list *args)
++{
++ struct kvm_trace_probe *p = probe_private;
++ struct kvm_trace *kt = kvm_trace;
++ struct kvm_trace_rec rec;
++ struct kvm_vcpu *vcpu;
++ int i, extra, size;
++
++ if (unlikely(kt->trace_state != KVM_TRACE_STATE_RUNNING))
++ return;
++
++ rec.event = va_arg(*args, u32);
++ vcpu = va_arg(*args, struct kvm_vcpu *);
++ rec.pid = current->tgid;
++ rec.vcpu_id = vcpu->vcpu_id;
++
++ extra = va_arg(*args, u32);
++ WARN_ON(!(extra <= KVM_TRC_EXTRA_MAX));
++ extra = min_t(u32, extra, KVM_TRC_EXTRA_MAX);
++ rec.extra_u32 = extra;
++
++ rec.cycle_in = p->cycle_in;
++
++ if (rec.cycle_in) {
++ u64 cycle = 0;
++
++ cycle = get_cycles();
++ rec.u.cycle.cycle_lo = (u32)cycle;
++ rec.u.cycle.cycle_hi = (u32)(cycle >> 32);
++
++ for (i = 0; i < rec.extra_u32; i++)
++ rec.u.cycle.extra_u32[i] = va_arg(*args, u32);
++ } else {
++ for (i = 0; i < rec.extra_u32; i++)
++ rec.u.nocycle.extra_u32[i] = va_arg(*args, u32);
++ }
++
++ size = calc_rec_size(rec.cycle_in, rec.extra_u32 * sizeof(u32));
++ relay_write(kt->rchan, &rec, size);
++}
++
++static struct kvm_trace_probe kvm_trace_probes[] = {
++ { "kvm_trace_entryexit", "%u %p %u %u %u %u %u %u", 1, kvm_add_trace },
++ { "kvm_trace_handler", "%u %p %u %u %u %u %u %u", 0, kvm_add_trace },
++};
++
++static int lost_records_get(void *data, u64 *val)
++{
++ struct kvm_trace *kt = data;
++
++ *val = atomic_read(&kt->lost_records);
++ return 0;
++}
++
++DEFINE_SIMPLE_ATTRIBUTE(kvm_trace_lost_ops, lost_records_get, NULL, "%llu\n");
++
++/*
++ * The relay channel is used in "no-overwrite" mode, it keeps trace of how
++ * many times we encountered a full subbuffer, to tell user space app the
++ * lost records there were.
++ */
++static int kvm_subbuf_start_callback(struct rchan_buf *buf, void *subbuf,
++ void *prev_subbuf, size_t prev_padding)
++{
++ struct kvm_trace *kt;
++
++ if (!relay_buf_full(buf))
++ return 1;
++
++ kt = buf->chan->private_data;
++ atomic_inc(&kt->lost_records);
++
++ return 0;
++}
++
++static struct dentry *kvm_create_buf_file_callack(const char *filename,
++ struct dentry *parent,
++ int mode,
++ struct rchan_buf *buf,
++ int *is_global)
++{
++ return debugfs_create_file(filename, mode, parent, buf,
++ &relay_file_operations);
++}
++
++static int kvm_remove_buf_file_callback(struct dentry *dentry)
++{
++ debugfs_remove(dentry);
++ return 0;
++}
++
++static struct rchan_callbacks kvm_relay_callbacks = {
++ .subbuf_start = kvm_subbuf_start_callback,
++ .create_buf_file = kvm_create_buf_file_callack,
++ .remove_buf_file = kvm_remove_buf_file_callback,
++};
++
++static int do_kvm_trace_enable(struct kvm_user_trace_setup *kuts)
++{
++ struct kvm_trace *kt;
++ int i, r = -ENOMEM;
++
++ if (!kuts->buf_size || !kuts->buf_nr)
++ return -EINVAL;
++
++ kt = kzalloc(sizeof(*kt), GFP_KERNEL);
++ if (!kt)
++ goto err;
++
++ r = -EIO;
++ atomic_set(&kt->lost_records, 0);
++ kt->lost_file = debugfs_create_file("lost_records", 0444, kvm_debugfs_dir,
++ kt, &kvm_trace_lost_ops);
++ if (!kt->lost_file)
++ goto err;
++
++ kt->rchan = relay_open("trace", kvm_debugfs_dir, kuts->buf_size,
++ kuts->buf_nr, &kvm_relay_callbacks, kt);
++ if (!kt->rchan)
++ goto err;
++
++ kvm_trace = kt;
++
++ for (i = 0; i < ARRAY_SIZE(kvm_trace_probes); i++) {
++ struct kvm_trace_probe *p = &kvm_trace_probes[i];
++
++ r = marker_probe_register(p->name, p->format, p->probe_func, p);
++ if (r)
++ printk(KERN_INFO "Unable to register probe %s\n",
++ p->name);
++ }
++
++ kvm_trace->trace_state = KVM_TRACE_STATE_RUNNING;
++
++ return 0;
++err:
++ if (kt) {
++ if (kt->lost_file)
++ debugfs_remove(kt->lost_file);
++ if (kt->rchan)
++ relay_close(kt->rchan);
++ kfree(kt);
++ }
++ return r;
++}
++
++static int kvm_trace_enable(char __user *arg)
++{
++ struct kvm_user_trace_setup kuts;
++ int ret;
++
++ ret = copy_from_user(&kuts, arg, sizeof(kuts));
++ if (ret)
++ return -EFAULT;
++
++ ret = do_kvm_trace_enable(&kuts);
++ if (ret)
++ return ret;
++
++ return 0;
++}
++
++static int kvm_trace_pause(void)
++{
++ struct kvm_trace *kt = kvm_trace;
++ int r = -EINVAL;
++
++ if (kt == NULL)
++ return r;
++
++ if (kt->trace_state == KVM_TRACE_STATE_RUNNING) {
++ kt->trace_state = KVM_TRACE_STATE_PAUSE;
++ relay_flush(kt->rchan);
++ r = 0;
++ }
++
++ return r;
++}
++
++void kvm_trace_cleanup(void)
++{
++ struct kvm_trace *kt = kvm_trace;
++ int i;
++
++ if (kt == NULL)
++ return;
++
++ if (kt->trace_state == KVM_TRACE_STATE_RUNNING ||
++ kt->trace_state == KVM_TRACE_STATE_PAUSE) {
++
++ kt->trace_state = KVM_TRACE_STATE_CLEARUP;
++
++ for (i = 0; i < ARRAY_SIZE(kvm_trace_probes); i++) {
++ struct kvm_trace_probe *p = &kvm_trace_probes[i];
++ marker_probe_unregister(p->name, p->probe_func, p);
++ }
++
++ relay_close(kt->rchan);
++ debugfs_remove(kt->lost_file);
++ kfree(kt);
++ }
++}
++
++int kvm_trace_ioctl(unsigned int ioctl, unsigned long arg)
++{
++ void __user *argp = (void __user *)arg;
++ long r = -EINVAL;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ switch (ioctl) {
++ case KVM_TRACE_ENABLE:
++ r = kvm_trace_enable(argp);
++ break;
++ case KVM_TRACE_PAUSE:
++ r = kvm_trace_pause();
++ break;
++ case KVM_TRACE_DISABLE:
++ r = 0;
++ kvm_trace_cleanup();
++ break;
++ }
++
++ return r;
++}
Modified: dists/trunk/linux-2.6/debian/patches/series/1~experimental.1
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/1~experimental.1 (original)
+++ dists/trunk/linux-2.6/debian/patches/series/1~experimental.1 Thu May 1 08:26:37 2008
@@ -11,18 +11,14 @@
+ debian/dfsg/drivers-net-bnx2-request_firmware-1.patch
+ features/all/export-gfs2-locking-symbols.patch
+ features/all/export-unionfs-symbols.patch
-+ features/all/export-input-braille.patch
#+ bugfix/powerpc/mv643xx-hotplug-support.patch
+ bugfix/powerpc/oldworld-boot-fix.patch
+ bugfix/powerpc/prep-utah-ide-interrupt.patch
+ bugfix/powerpc/serial.patch
-+ bugfix/arm/orion-enawrallo.patch
-+ features/arm/ixp4xx-net-drivers.patch
##+ features/arm/linkstation.patch
##+ features/arm/orion-mv88f5281-d0.patch
##+ features/arm/ts409.patch
-+ features/all/rtc-pcf8563-new-style-conversion.patch
##+ features/arm/mv2120.patch
+ bugfix/sparc/drivers_net-broken.patch
+ bugfix/ia64/hardcode-arch-script-output.patch
@@ -35,10 +31,8 @@
+ bugfix/arm/disable-scsi_acard.patch
##+ bugfix/arm/disable-ath5k.patch
+ bugfix/arm/disable-r6040.patch
-+ features/all/at76.patch
+# FIXME: trivial MAINTAINERS reject
+#+ features/all/at76.patch
+ bugfix/fix-hifn_795X-divdi3.patch
##+ features/all/mtd-nor-add-support-for-the-st-m29w400db-flash-chip.patch
-+ bugfix/all/rtc-x1205-new-style-conversion.patch
-+ bugfix/all/rtc-x1205-new-style-conversion-checkpatch-fixes.patch
+ bugfix/all/mtd-prevent-physmap-from-causing-request_module-runaway-loop-modprobe-net-pf-1.patch
-+ bugfix/arm/fix-ixp4xx_qmgr-used_sram_bitmap-corruption.patch
Modified: dists/trunk/linux-2.6/debian/patches/series/1~experimental.1-extra
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/1~experimental.1-extra (original)
+++ dists/trunk/linux-2.6/debian/patches/series/1~experimental.1-extra Thu May 1 08:26:37 2008
@@ -8,7 +8,7 @@
+ bugfix/m68k/2.6.24/633-atari_scc.diff arch=m68k
#+ bugfix/m68k/2.6.24/130-adbraw.diff arch=m68k
#+ bugfix/m68k/2.6.24/133-arch.diff arch=m68k
-+ bugfix/m68k/2.6.24/134-atari-fat.diff arch=m68k
+#+ bugfix/m68k/2.6.24/134-atari-fat.diff arch=m68k
+ bugfix/m68k/2.6.24/141-ide.diff arch=m68k
+ bugfix/m68k/2.6.24/143-ioext.diff arch=m68k
+ bugfix/m68k/2.6.24/149-mc68681.diff arch=m68k
@@ -21,7 +21,7 @@
#+ bugfix/m68k/2.6.24/atari-ethernat.diff arch=m68k
+ bugfix/m68k/2.6.24/falconide_intr_lock-ratelimit.diff arch=m68k
-+ bugfix/m68k/2.6.24/zorro-module-device-table.diff arch=m68k
+#+ bugfix/m68k/2.6.24/zorro-module-device-table.diff arch=m68k
+ bugfix/m68k/2.6.24/m68k-q40ints.c-needs-asm-floppy.h.diff arch=m68k
+ bugfix/m68k/2.6.24/blinux-list-is-subscribers-only.diff arch=m68k
+ bugfix/m68k/2.6.24/b43-depends-on-HAS_DMA.diff arch=m68k
More information about the Kernel-svn-changes
mailing list